diff --git a/MANIFEST.in b/MANIFEST.in index 6b2eeb618..6a67273e0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,7 +3,7 @@ include dash_core_components/dash_core_components.dev.js include dash_core_components/metadata.json include dash_core_components/rc-slider@6.1.2.css include dash_core_components/react-select@1.0.0-rc.3.min.css -include dash_core_components/plotly-1.42.2.min.js +include dash_core_components/plotly-18863-45646037.js include dash_core_components/react-virtualized-select@3.1.0.css include dash_core_components/react-virtualized@9.9.0.css include dash_core_components/react-dates@12.3.0.css diff --git a/dash_core_components/__init__.py b/dash_core_components/__init__.py index 848115c9e..736d0690a 100644 --- a/dash_core_components/__init__.py +++ b/dash_core_components/__init__.py @@ -5,8 +5,9 @@ import os as _os import sys as _sys import dash as _dash - from .version import __version__ +NPM_VERSION = '0.39.0-rc4' + # Module imports trigger a dash.development import, need to check this first if not hasattr(_dash, 'development'): @@ -35,8 +36,8 @@ _js_dist = [ { - 'external_url': 'https://cdn.plot.ly/plotly-1.42.2.min.js', - 'relative_package_path': 'plotly-1.42.2.min.js', + 'external_url': 'https://18863-45646037-gh.circle-artifacts.com/0/plotly.min.js', + 'relative_package_path': 'plotly-18863-45646037.js', 'namespace': 'dash_core_components' }, { @@ -45,7 +46,7 @@ 'external_url': ( 'https://unpkg.com/dash-core-components@{}' '/dash_core_components/dash_core_components.min.js' - ).format(__version__), + ).format(NPM_VERSION), 'namespace': 'dash_core_components' } ] diff --git a/dash_core_components/dash_core_components.dev.js b/dash_core_components/dash_core_components.dev.js index 710c83ffd..1ab977514 100644 --- a/dash_core_components/dash_core_components.dev.js +++ b/dash_core_components/dash_core_components.dev.js @@ -12463,7 +12463,7 @@ eval("/*! http://mths.be/repeat v0.2.0 by @mathias */\nif (!String.prototype.rep /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n\nvar stylesInDom = {};\n\nvar\tmemoize = function (fn) {\n\tvar memo;\n\n\treturn function () {\n\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\treturn memo;\n\t};\n};\n\nvar isOldIE = memoize(function () {\n\t// Test for IE <= 9 as proposed by Browserhacks\n\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n\t// Tests for existence of standard globals is to allow style-loader\n\t// to operate correctly into non-standard environments\n\t// @see https://github.com/webpack-contrib/style-loader/issues/177\n\treturn window && document && document.all && !window.atob;\n});\n\nvar getTarget = function (target) {\n return document.querySelector(target);\n};\n\nvar getElement = (function (fn) {\n\tvar memo = {};\n\n\treturn function(target) {\n // If passing function in options, then use it for resolve \"head\" element.\n // Useful for Shadow Root style i.e\n // {\n // insertInto: function () { return document.querySelector(\"#foo\").shadowRoot }\n // }\n if (typeof target === 'function') {\n return target();\n }\n if (typeof memo[target] === \"undefined\") {\n\t\t\tvar styleTarget = getTarget.call(this, target);\n\t\t\t// Special case to return head of iframe instead of iframe itself\n\t\t\tif (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n\t\t\t\ttry {\n\t\t\t\t\t// This will throw an exception if access to iframe is blocked\n\t\t\t\t\t// due to cross-origin restrictions\n\t\t\t\t\tstyleTarget = styleTarget.contentDocument.head;\n\t\t\t\t} catch(e) {\n\t\t\t\t\tstyleTarget = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmemo[target] = styleTarget;\n\t\t}\n\t\treturn memo[target]\n\t};\n})();\n\nvar singleton = null;\nvar\tsingletonCounter = 0;\nvar\tstylesInsertedAtTop = [];\n\nvar\tfixUrls = __webpack_require__(/*! ./urls */ \"./node_modules/style-loader/lib/urls.js\");\n\nmodule.exports = function(list, options) {\n\tif (typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif (typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\n\toptions.attrs = typeof options.attrs === \"object\" ? options.attrs : {};\n\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of plotly-logomark' + } +}; + +},{}],3:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/transforms/aggregate'); + +},{"../src/transforms/aggregate":1155}],4:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/bar'); + +},{"../src/traces/bar":843}],5:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/barpolar'); + +},{"../src/traces/barpolar":855}],6:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/box'); + +},{"../src/traces/box":865}],7:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/components/calendars'); + +},{"../src/components/calendars":568}],8:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/candlestick'); + +},{"../src/traces/candlestick":874}],9:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/carpet'); + +},{"../src/traces/carpet":893}],10:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/choropleth'); + +},{"../src/traces/choropleth":907}],11:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/cone'); + +},{"../src/traces/cone":915}],12:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/contour'); + +},{"../src/traces/contour":930}],13:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/contourcarpet'); + +},{"../src/traces/contourcarpet":941}],14:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/core'); + +},{"../src/core":675}],15:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/transforms/filter'); + +},{"../src/transforms/filter":1156}],16:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/transforms/groupby'); + +},{"../src/transforms/groupby":1157}],17:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/heatmap'); + +},{"../src/traces/heatmap":953}],18:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/heatmapgl'); + +},{"../src/traces/heatmapgl":963}],19:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/histogram'); + +},{"../src/traces/histogram":974}],20:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/histogram2d'); + +},{"../src/traces/histogram2d":981}],21:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/histogram2dcontour'); + +},{"../src/traces/histogram2dcontour":985}],22:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Plotly = _dereq_('./core'); + +// traces +Plotly.register([ + _dereq_('./bar'), + _dereq_('./box'), + _dereq_('./heatmap'), + _dereq_('./histogram'), + _dereq_('./histogram2d'), + _dereq_('./histogram2dcontour'), + _dereq_('./pie'), + _dereq_('./contour'), + _dereq_('./scatterternary'), + _dereq_('./violin'), + + _dereq_('./scatter3d'), + _dereq_('./surface'), + _dereq_('./mesh3d'), + _dereq_('./cone'), + _dereq_('./streamtube'), + + _dereq_('./scattergeo'), + _dereq_('./choropleth'), + + _dereq_('./scattergl'), + _dereq_('./splom'), + + _dereq_('./pointcloud'), + _dereq_('./heatmapgl'), + _dereq_('./parcoords'), + _dereq_('./parcats'), + _dereq_('./scattermapbox'), + + _dereq_('./sankey'), + + _dereq_('./table'), + + _dereq_('./carpet'), + _dereq_('./scattercarpet'), + _dereq_('./contourcarpet'), + + _dereq_('./ohlc'), + _dereq_('./candlestick'), + + _dereq_('./scatterpolar'), + _dereq_('./scatterpolargl'), + _dereq_('./barpolar') +]); + +// transforms +// +// Please note that all *transform* methods are executed before +// all *calcTransform* methods - which could possibly lead to +// unexpected results when applying multiple transforms of different types +// to a given trace. +// +// For more info, see: +// https://github.com/plotly/plotly.js/pull/978#pullrequestreview-2403353 +// +Plotly.register([ + _dereq_('./aggregate'), + _dereq_('./filter'), + _dereq_('./groupby'), + _dereq_('./sort') +]); + +// components +Plotly.register([ + _dereq_('./calendars') +]); + +module.exports = Plotly; + +},{"./aggregate":3,"./bar":4,"./barpolar":5,"./box":6,"./calendars":7,"./candlestick":8,"./carpet":9,"./choropleth":10,"./cone":11,"./contour":12,"./contourcarpet":13,"./core":14,"./filter":15,"./groupby":16,"./heatmap":17,"./heatmapgl":18,"./histogram":19,"./histogram2d":20,"./histogram2dcontour":21,"./mesh3d":23,"./ohlc":24,"./parcats":25,"./parcoords":26,"./pie":27,"./pointcloud":28,"./sankey":29,"./scatter3d":30,"./scattercarpet":31,"./scattergeo":32,"./scattergl":33,"./scattermapbox":34,"./scatterpolar":35,"./scatterpolargl":36,"./scatterternary":37,"./sort":38,"./splom":39,"./streamtube":40,"./surface":41,"./table":42,"./violin":43}],23:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/mesh3d'); + +},{"../src/traces/mesh3d":990}],24:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/ohlc'); + +},{"../src/traces/ohlc":995}],25:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/parcats'); + +},{"../src/traces/parcats":1004}],26:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/parcoords'); + +},{"../src/traces/parcoords":1013}],27:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/pie'); + +},{"../src/traces/pie":1024}],28:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/pointcloud'); + +},{"../src/traces/pointcloud":1033}],29:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/sankey'); + +},{"../src/traces/sankey":1039}],30:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scatter3d'); + +},{"../src/traces/scatter3d":1075}],31:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scattercarpet'); + +},{"../src/traces/scattercarpet":1081}],32:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scattergeo'); + +},{"../src/traces/scattergeo":1088}],33:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scattergl'); + +},{"../src/traces/scattergl":1096}],34:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scattermapbox'); + +},{"../src/traces/scattermapbox":1102}],35:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scatterpolar'); + +},{"../src/traces/scatterpolar":1109}],36:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scatterpolargl'); + +},{"../src/traces/scatterpolargl":1113}],37:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/scatterternary'); + +},{"../src/traces/scatterternary":1119}],38:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/transforms/sort'); + +},{"../src/transforms/sort":1159}],39:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/splom'); + +},{"../src/traces/splom":1124}],40:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/streamtube'); + +},{"../src/traces/streamtube":1129}],41:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/surface'); + +},{"../src/traces/surface":1134}],42:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/table'); + +},{"../src/traces/table":1142}],43:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = _dereq_('../src/traces/violin'); + +},{"../src/traces/violin":1150}],44:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createCamera + +var now = _dereq_('right-now') +var createView = _dereq_('3d-view') +var mouseChange = _dereq_('mouse-change') +var mouseWheel = _dereq_('mouse-wheel') +var mouseOffset = _dereq_('mouse-event-offset') +var hasPassive = _dereq_('has-passive-events') + +function createCamera(element, options) { + element = element || document.body + options = options || {} + + var limits = [ 0.01, Infinity ] + if('distanceLimits' in options) { + limits[0] = options.distanceLimits[0] + limits[1] = options.distanceLimits[1] + } + if('zoomMin' in options) { + limits[0] = options.zoomMin + } + if('zoomMax' in options) { + limits[1] = options.zoomMax + } + + var view = createView({ + center: options.center || [0,0,0], + up: options.up || [0,1,0], + eye: options.eye || [0,0,10], + mode: options.mode || 'orbit', + distanceLimits: limits + }) + + var pmatrix = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + var distance = 0.0 + var width = element.clientWidth + var height = element.clientHeight + + var camera = { + view: view, + element: element, + delay: options.delay || 16, + rotateSpeed: options.rotateSpeed || 1, + zoomSpeed: options.zoomSpeed || 1, + translateSpeed: options.translateSpeed || 1, + flipX: !!options.flipX, + flipY: !!options.flipY, + modes: view.modes, + tick: function() { + var t = now() + var delay = this.delay + view.idle(t-delay) + view.flush(t-(100+delay*2)) + var ctime = t - 2 * delay + view.recalcMatrix(ctime) + var allEqual = true + var matrix = view.computedMatrix + for(var i=0; i<16; ++i) { + allEqual = allEqual && (pmatrix[i] === matrix[i]) + pmatrix[i] = matrix[i] + } + var sizeChanged = + element.clientWidth === width && + element.clientHeight === height + width = element.clientWidth + height = element.clientHeight + if(allEqual) { + return !sizeChanged + } + distance = Math.exp(view.computedRadius[0]) + return true + }, + lookAt: function(center, eye, up) { + view.lookAt(view.lastT(), center, eye, up) + }, + rotate: function(pitch, yaw, roll) { + view.rotate(view.lastT(), pitch, yaw, roll) + }, + pan: function(dx, dy, dz) { + view.pan(view.lastT(), dx, dy, dz) + }, + translate: function(dx, dy, dz) { + view.translate(view.lastT(), dx, dy, dz) + } + } + + Object.defineProperties(camera, { + matrix: { + get: function() { + return view.computedMatrix + }, + set: function(mat) { + view.setMatrix(view.lastT(), mat) + return view.computedMatrix + }, + enumerable: true + }, + mode: { + get: function() { + return view.getMode() + }, + set: function(mode) { + view.setMode(mode) + return view.getMode() + }, + enumerable: true + }, + center: { + get: function() { + return view.computedCenter + }, + set: function(ncenter) { + view.lookAt(view.lastT(), ncenter) + return view.computedCenter + }, + enumerable: true + }, + eye: { + get: function() { + return view.computedEye + }, + set: function(neye) { + view.lookAt(view.lastT(), null, neye) + return view.computedEye + }, + enumerable: true + }, + up: { + get: function() { + return view.computedUp + }, + set: function(nup) { + view.lookAt(view.lastT(), null, null, nup) + return view.computedUp + }, + enumerable: true + }, + distance: { + get: function() { + return distance + }, + set: function(d) { + view.setDistance(view.lastT(), d) + return d + }, + enumerable: true + }, + distanceLimits: { + get: function() { + return view.getDistanceLimits(limits) + }, + set: function(v) { + view.setDistanceLimits(v) + return v + }, + enumerable: true + } + }) + + element.addEventListener('contextmenu', function(ev) { + ev.preventDefault() + return false + }) + + var lastX = 0, lastY = 0, lastMods = {shift: false, control: false, alt: false, meta: false} + mouseChange(element, handleInteraction) + + //enable simple touch interactions + element.addEventListener('touchstart', function (ev) { + var xy = mouseOffset(ev.changedTouches[0], element) + handleInteraction(0, xy[0], xy[1], lastMods) + handleInteraction(1, xy[0], xy[1], lastMods) + + ev.preventDefault() + }, hasPassive ? {passive: false} : false) + + element.addEventListener('touchmove', function (ev) { + var xy = mouseOffset(ev.changedTouches[0], element) + handleInteraction(1, xy[0], xy[1], lastMods) + + ev.preventDefault() + }, hasPassive ? {passive: false} : false) + + element.addEventListener('touchend', function (ev) { + var xy = mouseOffset(ev.changedTouches[0], element) + handleInteraction(0, lastX, lastY, lastMods) + + ev.preventDefault() + }, hasPassive ? {passive: false} : false) + + function handleInteraction (buttons, x, y, mods) { + var scale = 1.0 / element.clientHeight + var dx = scale * (x - lastX) + var dy = scale * (y - lastY) + + var flipX = camera.flipX ? 1 : -1 + var flipY = camera.flipY ? 1 : -1 + + var drot = Math.PI * camera.rotateSpeed + + var t = now() + + if(buttons & 1) { + if(mods.shift) { + view.rotate(t, 0, 0, -dx * drot) + } else { + view.rotate(t, flipX * drot * dx, -flipY * drot * dy, 0) + } + } else if(buttons & 2) { + view.pan(t, -camera.translateSpeed * dx * distance, camera.translateSpeed * dy * distance, 0) + } else if(buttons & 4) { + var kzoom = camera.zoomSpeed * dy / window.innerHeight * (t - view.lastT()) * 50.0 + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) + } + + lastX = x + lastY = y + lastMods = mods + } + + mouseWheel(element, function(dx, dy, dz) { + var flipX = camera.flipX ? 1 : -1 + var flipY = camera.flipY ? 1 : -1 + var t = now() + if(Math.abs(dx) > Math.abs(dy)) { + view.rotate(t, 0, 0, -dx * flipX * Math.PI * camera.rotateSpeed / window.innerWidth) + } else { + var kzoom = camera.zoomSpeed * flipY * dy / window.innerHeight * (t - view.lastT()) / 100.0 + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) + } + }, true) + + return camera +} + +},{"3d-view":45,"has-passive-events":394,"mouse-change":418,"mouse-event-offset":419,"mouse-wheel":421,"right-now":480}],45:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createViewController + +var createTurntable = _dereq_('turntable-camera-controller') +var createOrbit = _dereq_('orbit-camera-controller') +var createMatrix = _dereq_('matrix-camera-controller') + +function ViewController(controllers, mode) { + this._controllerNames = Object.keys(controllers) + this._controllerList = this._controllerNames.map(function(n) { + return controllers[n] + }) + this._mode = mode + this._active = controllers[mode] + if(!this._active) { + this._mode = 'turntable' + this._active = controllers.turntable + } + this.modes = this._controllerNames + this.computedMatrix = this._active.computedMatrix + this.computedEye = this._active.computedEye + this.computedUp = this._active.computedUp + this.computedCenter = this._active.computedCenter + this.computedRadius = this._active.computedRadius +} + +var proto = ViewController.prototype + +var COMMON_METHODS = [ + ['flush', 1], + ['idle', 1], + ['lookAt', 4], + ['rotate', 4], + ['pan', 4], + ['translate', 4], + ['setMatrix', 2], + ['setDistanceLimits', 2], + ['setDistance', 2] +] + +COMMON_METHODS.forEach(function(method) { + var name = method[0] + var argNames = [] + for(var i=0; i 0; --iterations) { + relaxRightToLeft(alpha *= .99); + resolveCollisions(); + relaxLeftToRight(alpha); + resolveCollisions(); + } + + function initializeNodeDepth() { + var L = d3Array.max(nodesByBreadth, function(nodes) { + return nodes.length; + }); + var maxNodePadding = maxPaddedSpace * size[1] / (L - 1); + if(nodePadding > maxNodePadding) nodePadding = maxNodePadding; + var ky = d3Array.min(nodesByBreadth, function(nodes) { + return (size[1] - (nodes.length - 1) * nodePadding) / d3Array.sum(nodes, value); + }); + + nodesByBreadth.forEach(function(nodes) { + nodes.forEach(function(node, i) { + node.y = i; + node.dy = node.value * ky; + }); + }); + + links.forEach(function(link) { + link.dy = link.value * ky; + }); + } + + function relaxLeftToRight(alpha) { + nodesByBreadth.forEach(function(nodes) { + nodes.forEach(function(node) { + if (node.targetLinks.length) { + var y = d3Array.sum(node.targetLinks, weightedSource) / d3Array.sum(node.targetLinks, value); + node.y += (y - center(node)) * alpha; + } + }); + }); + + function weightedSource(link) { + return center(link.source) * link.value; + } + } + + function relaxRightToLeft(alpha) { + nodesByBreadth.slice().reverse().forEach(function(nodes) { + nodes.forEach(function(node) { + if (node.sourceLinks.length) { + var y = d3Array.sum(node.sourceLinks, weightedTarget) / d3Array.sum(node.sourceLinks, value); + node.y += (y - center(node)) * alpha; + } + }); + }); + + function weightedTarget(link) { + return center(link.target) * link.value; + } + } + + function resolveCollisions() { + nodesByBreadth.forEach(function(nodes) { + var node, + dy, + y0 = 0, + n = nodes.length, + i; + + // Push any overlapping nodes down. + nodes.sort(ascendingDepth); + for (i = 0; i < n; ++i) { + node = nodes[i]; + dy = y0 - node.y; + if (dy > 0) node.y += dy; + y0 = node.y + node.dy + nodePadding; + } + + // If the bottommost node goes outside the bounds, push it back up. + dy = y0 - nodePadding - size[1]; + if (dy > 0) { + y0 = node.y -= dy; + + // Push any overlapping nodes back up. + for (i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.y + node.dy + nodePadding - y0; + if (dy > 0) node.y -= dy; + y0 = node.y; + } + } + }); + } + + function ascendingDepth(a, b) { + return a.y - b.y; + } + } + + function computeLinkDepths() { + nodes.forEach(function(node) { + node.sourceLinks.sort(ascendingTargetDepth); + node.targetLinks.sort(ascendingSourceDepth); + }); + nodes.forEach(function(node) { + var sy = 0, ty = 0; + node.sourceLinks.forEach(function(link) { + link.sy = sy; + sy += link.dy; + }); + node.targetLinks.forEach(function(link) { + link.ty = ty; + ty += link.dy; + }); + }); + + function ascendingSourceDepth(a, b) { + return (a.source.y - b.source.y) || (a.originalIndex - b.originalIndex); + } + + function ascendingTargetDepth(a, b) { + return (a.target.y - b.target.y) || (a.originalIndex - b.originalIndex); + } + } + + function center(node) { + return node.y + node.dy / 2; + } + + function value(link) { + return link.value; + } + + return sankey; +}; + +exports.sankey = sankey; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-array":140,"d3-collection":141,"d3-interpolate":145}],47:[function(_dereq_,module,exports){ +'use strict' + +var weakMap = typeof WeakMap === 'undefined' ? _dereq_('weak-map') : WeakMap +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') + +var TriangleCache = new weakMap() + +function createABigTriangle(gl) { + + var triangleVAO = TriangleCache.get(gl) + var handle = triangleVAO && (triangleVAO._triangleBuffer.handle || triangleVAO._triangleBuffer.buffer) + if(!handle || !gl.isBuffer(handle)) { + var buf = createBuffer(gl, new Float32Array([-1, -1, -1, 4, 4, -1])) + triangleVAO = createVAO(gl, [ + { buffer: buf, + type: gl.FLOAT, + size: 2 + } + ]) + triangleVAO._triangleBuffer = buf + TriangleCache.set(gl, triangleVAO) + } + triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, 3) + triangleVAO.unbind() +} + +module.exports = createABigTriangle + +},{"gl-buffer":230,"gl-vao":310,"weak-map":529}],48:[function(_dereq_,module,exports){ + +module.exports = absolutize + +/** + * redefine `path` with absolute coordinates + * + * @param {Array} path + * @return {Array} + */ + +function absolutize(path){ + var startX = 0 + var startY = 0 + var x = 0 + var y = 0 + + return path.map(function(seg){ + seg = seg.slice() + var type = seg[0] + var command = type.toUpperCase() + + // is relative + if (type != command) { + seg[0] = command + switch (type) { + case 'a': + seg[6] += x + seg[7] += y + break + case 'v': + seg[1] += y + break + case 'h': + seg[1] += x + break + default: + for (var i = 1; i < seg.length;) { + seg[i++] += x + seg[i++] += y + } + } + } + + // update cursor state + switch (command) { + case 'Z': + x = startX + y = startY + break + case 'H': + x = seg[1] + break + case 'V': + y = seg[1] + break + case 'M': + x = startX = seg[1] + y = startY = seg[2] + break + default: + x = seg[seg.length - 2] + y = seg[seg.length - 1] + } + + return seg + }) +} + +},{}],49:[function(_dereq_,module,exports){ +var padLeft = _dereq_('pad-left') + +module.exports = addLineNumbers +function addLineNumbers (string, start, delim) { + start = typeof start === 'number' ? start : 1 + delim = delim || ': ' + + var lines = string.split(/\r?\n/) + var totalDigits = String(lines.length + start - 1).length + return lines.map(function (line, i) { + var c = i + start + var digits = String(c).length + var prefix = padLeft(c, totalDigits - digits) + return prefix + delim + line + }).join('\n') +} + +},{"pad-left":440}],50:[function(_dereq_,module,exports){ +'use strict' + +module.exports = affineHull + +var orient = _dereq_('robust-orientation') + +function linearlyIndependent(points, d) { + var nhull = new Array(d+1) + for(var i=0; i max) max = arr[i]; + if (arr[i] < min) min = arr[i]; + } + + bounds[offset] = min + bounds[dim + offset] = max + } + + return bounds; +} + +},{}],54:[function(_dereq_,module,exports){ +'use strict' + +var getBounds = _dereq_('array-bounds') + +module.exports = normalize; + +function normalize (arr, dim, bounds) { + if (!arr || arr.length == null) throw Error('Argument should be an array') + + if (dim == null) dim = 1 + if (bounds == null) bounds = getBounds(arr, dim) + + for (var offset = 0; offset < dim; offset++) { + var max = bounds[dim + offset], min = bounds[offset], i = offset, l = arr.length; + + if (max === Infinity && min === -Infinity) { + for (i = offset; i < l; i+=dim) { + arr[i] = arr[i] === max ? 1 : arr[i] === min ? 0 : .5 + } + } + else if (max === Infinity) { + for (i = offset; i < l; i+=dim) { + arr[i] = arr[i] === max ? 1 : 0 + } + } + else if (min === -Infinity) { + for (i = offset; i < l; i+=dim) { + arr[i] = arr[i] === min ? 0 : 1 + } + } + else { + var range = max - min + for (i = offset; i < l; i+=dim) { + arr[i] = range === 0 ? .5 : (arr[i] - min) / range + } + } + } + + return arr; +} + +},{"array-bounds":53}],55:[function(_dereq_,module,exports){ + +module.exports = function newArray(start, end) { + var n0 = typeof start === 'number', + n1 = typeof end === 'number' + + if (n0 && !n1) { + end = start + start = 0 + } else if (!n0 && !n1) { + start = 0 + end = 0 + } + + start = start|0 + end = end|0 + var len = end-start + if (len<0) + throw new Error('array length must be positive') + + var a = new Array(len) + for (var i=0, c=start; i + * @license MIT + */ +function compare(a, b) { + if (a === b) { + return 0; + } + + var x = a.length; + var y = b.length; + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break; + } + } + + if (x < y) { + return -1; + } + if (y < x) { + return 1; + } + return 0; +} +function isBuffer(b) { + if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { + return global.Buffer.isBuffer(b); + } + return !!(b != null && b._isBuffer); +} + +// based on node assert, original notice: + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +var util = _dereq_('util/'); +var hasOwn = Object.prototype.hasOwnProperty; +var pSlice = Array.prototype.slice; +var functionsHaveNames = (function () { + return function foo() {}.name === 'foo'; +}()); +function pToString (obj) { + return Object.prototype.toString.call(obj); +} +function isView(arrbuf) { + if (isBuffer(arrbuf)) { + return false; + } + if (typeof global.ArrayBuffer !== 'function') { + return false; + } + if (typeof ArrayBuffer.isView === 'function') { + return ArrayBuffer.isView(arrbuf); + } + if (!arrbuf) { + return false; + } + if (arrbuf instanceof DataView) { + return true; + } + if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { + return true; + } + return false; +} +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +var regex = /\s*function\s+([^\(\s]*)\s*/; +// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js +function getName(func) { + if (!util.isFunction(func)) { + return; + } + if (functionsHaveNames) { + return func.name; + } + var str = func.toString(); + var match = str.match(regex); + return match && match[1]; +} +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = getName(stackStartFunction); + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function truncate(s, n) { + if (typeof s === 'string') { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} +function inspect(something) { + if (functionsHaveNames || !util.isFunction(something)) { + return util.inspect(something); + } + var rawname = getName(something); + var name = rawname ? ': ' + rawname : ''; + return '[Function' + name + ']'; +} +function getMessage(self) { + return truncate(inspect(self.actual), 128) + ' ' + + self.operator + ' ' + + truncate(inspect(self.expected), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); + } +}; + +function _deepEqual(actual, expected, strict, memos) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if (isBuffer(actual) && isBuffer(expected)) { + return compare(actual, expected) === 0; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if ((actual === null || typeof actual !== 'object') && + (expected === null || typeof expected !== 'object')) { + return strict ? actual === expected : actual == expected; + + // If both values are instances of typed arrays, wrap their underlying + // ArrayBuffers in a Buffer each to increase performance + // This optimization requires the arrays to have the same type as checked by + // Object.prototype.toString (aka pToString). Never perform binary + // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their + // bit patterns are not identical. + } else if (isView(actual) && isView(expected) && + pToString(actual) === pToString(expected) && + !(actual instanceof Float32Array || + actual instanceof Float64Array)) { + return compare(new Uint8Array(actual.buffer), + new Uint8Array(expected.buffer)) === 0; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else if (isBuffer(actual) !== isBuffer(expected)) { + return false; + } else { + memos = memos || {actual: [], expected: []}; + + var actualIndex = memos.actual.indexOf(actual); + if (actualIndex !== -1) { + if (actualIndex === memos.expected.indexOf(expected)) { + return true; + } + } + + memos.actual.push(actual); + memos.expected.push(expected); + + return objEquiv(actual, expected, strict, memos); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b, strict, actualVisitedObjects) { + if (a === null || a === undefined || b === null || b === undefined) + return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) + return a === b; + if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) + return false; + var aIsArgs = isArguments(a); + var bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b, strict); + } + var ka = objectKeys(a); + var kb = objectKeys(b); + var key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length !== kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] !== kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +assert.notDeepStrictEqual = notDeepStrictEqual; +function notDeepStrictEqual(actual, expected, message) { + if (_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); + } +} + + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } + + try { + if (actual instanceof expected) { + return true; + } + } catch (e) { + // Ignore. The instanceof check doesn't work for arrow functions. + } + + if (Error.isPrototypeOf(expected)) { + return false; + } + + return expected.call({}, actual) === true; +} + +function _tryBlock(block) { + var error; + try { + block(); + } catch (e) { + error = e; + } + return error; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof block !== 'function') { + throw new TypeError('"block" argument must be a function'); + } + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + actual = _tryBlock(block); + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + var userProvidedMessage = typeof message === 'string'; + var isUnwantedException = !shouldThrow && util.isError(actual); + var isUnexpectedException = !shouldThrow && actual && !expected; + + if ((isUnwantedException && + userProvidedMessage && + expectedException(actual, expected)) || + isUnexpectedException) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws(true, block, error, message); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws(false, block, error, message); +}; + +assert.ifError = function(err) { if (err) throw err; }; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"util/":59}],57:[function(_dereq_,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],58:[function(_dereq_,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],59:[function(_dereq_,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = _dereq_('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = _dereq_('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./support/isBuffer":58,"_process":465,"inherits":57}],60:[function(_dereq_,module,exports){ +module.exports = function _atob(str) { + return atob(str) +} + +},{}],61:[function(_dereq_,module,exports){ +'use strict' + +module.exports = barycentric + +var solve = _dereq_('robust-linear-solve') + +function reduce(x) { + var r = 0 + for(var i=0; i 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],63:[function(_dereq_,module,exports){ +'use strict' + +var rationalize = _dereq_('./lib/rationalize') + +module.exports = add + +function add(a, b) { + return rationalize( + a[0].mul(b[1]).add(b[0].mul(a[1])), + a[1].mul(b[1])) +} + +},{"./lib/rationalize":73}],64:[function(_dereq_,module,exports){ +'use strict' + +module.exports = cmp + +function cmp(a, b) { + return a[0].mul(b[1]).cmp(b[0].mul(a[1])) +} + +},{}],65:[function(_dereq_,module,exports){ +'use strict' + +var rationalize = _dereq_('./lib/rationalize') + +module.exports = div + +function div(a, b) { + return rationalize(a[0].mul(b[1]), a[1].mul(b[0])) +} + +},{"./lib/rationalize":73}],66:[function(_dereq_,module,exports){ +'use strict' + +var isRat = _dereq_('./is-rat') +var isBN = _dereq_('./lib/is-bn') +var num2bn = _dereq_('./lib/num-to-bn') +var str2bn = _dereq_('./lib/str-to-bn') +var rationalize = _dereq_('./lib/rationalize') +var div = _dereq_('./div') + +module.exports = makeRational + +function makeRational(numer, denom) { + if(isRat(numer)) { + if(denom) { + return div(numer, makeRational(denom)) + } + return [numer[0].clone(), numer[1].clone()] + } + var shift = 0 + var a, b + if(isBN(numer)) { + a = numer.clone() + } else if(typeof numer === 'string') { + a = str2bn(numer) + } else if(numer === 0) { + return [num2bn(0), num2bn(1)] + } else if(numer === Math.floor(numer)) { + a = num2bn(numer) + } else { + while(numer !== Math.floor(numer)) { + numer = numer * Math.pow(2, 256) + shift -= 256 + } + a = num2bn(numer) + } + if(isRat(denom)) { + a.mul(denom[1]) + b = denom[0].clone() + } else if(isBN(denom)) { + b = denom.clone() + } else if(typeof denom === 'string') { + b = str2bn(denom) + } else if(!denom) { + b = num2bn(1) + } else if(denom === Math.floor(denom)) { + b = num2bn(denom) + } else { + while(denom !== Math.floor(denom)) { + denom = denom * Math.pow(2, 256) + shift += 256 + } + b = num2bn(denom) + } + if(shift > 0) { + a = a.ushln(shift) + } else if(shift < 0) { + b = b.ushln(-shift) + } + return rationalize(a, b) +} + +},{"./div":65,"./is-rat":67,"./lib/is-bn":71,"./lib/num-to-bn":72,"./lib/rationalize":73,"./lib/str-to-bn":74}],67:[function(_dereq_,module,exports){ +'use strict' + +var isBN = _dereq_('./lib/is-bn') + +module.exports = isRat + +function isRat(x) { + return Array.isArray(x) && x.length === 2 && isBN(x[0]) && isBN(x[1]) +} + +},{"./lib/is-bn":71}],68:[function(_dereq_,module,exports){ +'use strict' + +var BN = _dereq_('bn.js') + +module.exports = sign + +function sign (x) { + return x.cmp(new BN(0)) +} + +},{"bn.js":82}],69:[function(_dereq_,module,exports){ +'use strict' + +var sign = _dereq_('./bn-sign') + +module.exports = bn2num + +//TODO: Make this better +function bn2num(b) { + var l = b.length + var words = b.words + var out = 0 + if (l === 1) { + out = words[0] + } else if (l === 2) { + out = words[0] + (words[1] * 0x4000000) + } else { + for (var i = 0; i < l; i++) { + var w = words[i] + out += w * Math.pow(0x4000000, i) + } + } + return sign(b) * out +} + +},{"./bn-sign":68}],70:[function(_dereq_,module,exports){ +'use strict' + +var db = _dereq_('double-bits') +var ctz = _dereq_('bit-twiddle').countTrailingZeros + +module.exports = ctzNumber + +//Counts the number of trailing zeros +function ctzNumber(x) { + var l = ctz(db.lo(x)) + if(l < 32) { + return l + } + var h = ctz(db.hi(x)) + if(h > 20) { + return 52 + } + return h + 32 +} + +},{"bit-twiddle":80,"double-bits":152}],71:[function(_dereq_,module,exports){ +'use strict' + +var BN = _dereq_('bn.js') + +module.exports = isBN + +//Test if x is a bignumber +//FIXME: obviously this is the wrong way to do it +function isBN(x) { + return x && typeof x === 'object' && Boolean(x.words) +} + +},{"bn.js":82}],72:[function(_dereq_,module,exports){ +'use strict' + +var BN = _dereq_('bn.js') +var db = _dereq_('double-bits') + +module.exports = num2bn + +function num2bn(x) { + var e = db.exponent(x) + if(e < 52) { + return new BN(x) + } else { + return (new BN(x * Math.pow(2, 52-e))).ushln(e-52) + } +} + +},{"bn.js":82,"double-bits":152}],73:[function(_dereq_,module,exports){ +'use strict' + +var num2bn = _dereq_('./num-to-bn') +var sign = _dereq_('./bn-sign') + +module.exports = rationalize + +function rationalize(numer, denom) { + var snumer = sign(numer) + var sdenom = sign(denom) + if(snumer === 0) { + return [num2bn(0), num2bn(1)] + } + if(sdenom === 0) { + return [num2bn(0), num2bn(0)] + } + if(sdenom < 0) { + numer = numer.neg() + denom = denom.neg() + } + var d = numer.gcd(denom) + if(d.cmpn(1)) { + return [ numer.div(d), denom.div(d) ] + } + return [ numer, denom ] +} + +},{"./bn-sign":68,"./num-to-bn":72}],74:[function(_dereq_,module,exports){ +'use strict' + +var BN = _dereq_('bn.js') + +module.exports = str2BN + +function str2BN(x) { + return new BN(x) +} + +},{"bn.js":82}],75:[function(_dereq_,module,exports){ +'use strict' + +var rationalize = _dereq_('./lib/rationalize') + +module.exports = mul + +function mul(a, b) { + return rationalize(a[0].mul(b[0]), a[1].mul(b[1])) +} + +},{"./lib/rationalize":73}],76:[function(_dereq_,module,exports){ +'use strict' + +var bnsign = _dereq_('./lib/bn-sign') + +module.exports = sign + +function sign(x) { + return bnsign(x[0]) * bnsign(x[1]) +} + +},{"./lib/bn-sign":68}],77:[function(_dereq_,module,exports){ +'use strict' + +var rationalize = _dereq_('./lib/rationalize') + +module.exports = sub + +function sub(a, b) { + return rationalize(a[0].mul(b[1]).sub(a[1].mul(b[0])), a[1].mul(b[1])) +} + +},{"./lib/rationalize":73}],78:[function(_dereq_,module,exports){ +'use strict' + +var bn2num = _dereq_('./lib/bn-to-num') +var ctz = _dereq_('./lib/ctz') + +module.exports = roundRat + +// Round a rational to the closest float +function roundRat (f) { + var a = f[0] + var b = f[1] + if (a.cmpn(0) === 0) { + return 0 + } + var h = a.abs().divmod(b.abs()) + var iv = h.div + var x = bn2num(iv) + var ir = h.mod + var sgn = (a.negative !== b.negative) ? -1 : 1 + if (ir.cmpn(0) === 0) { + return sgn * x + } + if (x) { + var s = ctz(x) + 4 + var y = bn2num(ir.ushln(s).divRound(b)) + return sgn * (x + y * Math.pow(2, -s)) + } else { + var ybits = b.bitLength() - ir.bitLength() + 53 + var y = bn2num(ir.ushln(ybits).divRound(b)) + if (ybits < 1023) { + return sgn * y * Math.pow(2, -ybits) + } + y *= Math.pow(2, -1023) + return sgn * y * Math.pow(2, 1023 - ybits) + } +} + +},{"./lib/bn-to-num":69,"./lib/ctz":70}],79:[function(_dereq_,module,exports){ +"use strict" + +function compileSearch(funcName, predicate, reversed, extraArgs, useNdarray, earlyOut) { + var code = [ + "function ", funcName, "(a,l,h,", extraArgs.join(","), "){", +earlyOut ? "" : "var i=", (reversed ? "l-1" : "h+1"), +";while(l<=h){\ +var m=(l+h)>>>1,x=a", useNdarray ? ".get(m)" : "[m]"] + if(earlyOut) { + if(predicate.indexOf("c") < 0) { + code.push(";if(x===y){return m}else if(x<=y){") + } else { + code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") + } + } else { + code.push(";if(", predicate, "){i=m;") + } + if(reversed) { + code.push("l=m+1}else{h=m-1}") + } else { + code.push("h=m-1}else{l=m+1}") + } + code.push("}") + if(earlyOut) { + code.push("return -1};") + } else { + code.push("return i};") + } + return code.join("") +} + +function compileBoundsSearch(predicate, reversed, suffix, earlyOut) { + var result = new Function([ + compileSearch("A", "x" + predicate + "y", reversed, ["y"], false, earlyOut), + compileSearch("B", "x" + predicate + "y", reversed, ["y"], true, earlyOut), + compileSearch("P", "c(x,y)" + predicate + "0", reversed, ["y", "c"], false, earlyOut), + compileSearch("Q", "c(x,y)" + predicate + "0", reversed, ["y", "c"], true, earlyOut), +"function dispatchBsearch", suffix, "(a,y,c,l,h){\ +if(a.shape){\ +if(typeof(c)==='function'){\ +return Q(a,(l===undefined)?0:l|0,(h===undefined)?a.shape[0]-1:h|0,y,c)\ +}else{\ +return B(a,(c===undefined)?0:c|0,(l===undefined)?a.shape[0]-1:l|0,y)\ +}}else{\ +if(typeof(c)==='function'){\ +return P(a,(l===undefined)?0:l|0,(h===undefined)?a.length-1:h|0,y,c)\ +}else{\ +return A(a,(c===undefined)?0:c|0,(l===undefined)?a.length-1:l|0,y)\ +}}}\ +return dispatchBsearch", suffix].join("")) + return result() +} + +module.exports = { + ge: compileBoundsSearch(">=", false, "GE"), + gt: compileBoundsSearch(">", false, "GT"), + lt: compileBoundsSearch("<", true, "LT"), + le: compileBoundsSearch("<=", true, "LE"), + eq: compileBoundsSearch("-", true, "EQ", true) +} + +},{}],80:[function(_dereq_,module,exports){ +/** + * Bit twiddling hacks for JavaScript. + * + * Author: Mikola Lysenko + * + * Ported from Stanford bit twiddling hack library: + * http://graphics.stanford.edu/~seander/bithacks.html + */ + +"use strict"; "use restrict"; + +//Number of bits in an integer +var INT_BITS = 32; + +//Constants +exports.INT_BITS = INT_BITS; +exports.INT_MAX = 0x7fffffff; +exports.INT_MIN = -1<<(INT_BITS-1); + +//Returns -1, 0, +1 depending on sign of x +exports.sign = function(v) { + return (v > 0) - (v < 0); +} + +//Computes absolute value of integer +exports.abs = function(v) { + var mask = v >> (INT_BITS-1); + return (v ^ mask) - mask; +} + +//Computes minimum of integers x and y +exports.min = function(x, y) { + return y ^ ((x ^ y) & -(x < y)); +} + +//Computes maximum of integers x and y +exports.max = function(x, y) { + return x ^ ((x ^ y) & -(x < y)); +} + +//Checks if a number is a power of two +exports.isPow2 = function(v) { + return !(v & (v-1)) && (!!v); +} + +//Computes log base 2 of v +exports.log2 = function(v) { + var r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} + +//Computes log base 10 of v +exports.log10 = function(v) { + return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : + (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : + (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; +} + +//Counts number of bits +exports.popCount = function(v) { + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} + +//Counts number of trailing zeros +function countTrailingZeros(v) { + var c = 32; + v &= -v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +} +exports.countTrailingZeros = countTrailingZeros; + +//Rounds to next power of 2 +exports.nextPow2 = function(v) { + v += v === 0; + --v; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v + 1; +} + +//Rounds down to previous power of 2 +exports.prevPow2 = function(v) { + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v - (v>>>1); +} + +//Computes parity of word +exports.parity = function(v) { + v ^= v >>> 16; + v ^= v >>> 8; + v ^= v >>> 4; + v &= 0xf; + return (0x6996 >>> v) & 1; +} + +var REVERSE_TABLE = new Array(256); + +(function(tab) { + for(var i=0; i<256; ++i) { + var v = i, r = i, s = 7; + for (v >>>= 1; v; v >>>= 1) { + r <<= 1; + r |= v & 1; + --s; + } + tab[i] = (r << s) & 0xff; + } +})(REVERSE_TABLE); + +//Reverse bits in a 32 bit word +exports.reverse = function(v) { + return (REVERSE_TABLE[ v & 0xff] << 24) | + (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | + (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | + REVERSE_TABLE[(v >>> 24) & 0xff]; +} + +//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes +exports.interleave2 = function(x, y) { + x &= 0xFFFF; + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y &= 0xFFFF; + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +//Extracts the nth interleaved component +exports.deinterleave2 = function(v, n) { + v = (v >>> n) & 0x55555555; + v = (v | (v >>> 1)) & 0x33333333; + v = (v | (v >>> 2)) & 0x0F0F0F0F; + v = (v | (v >>> 4)) & 0x00FF00FF; + v = (v | (v >>> 16)) & 0x000FFFF; + return (v << 16) >> 16; +} + + +//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes +exports.interleave3 = function(x, y, z) { + x &= 0x3FF; + x = (x | (x<<16)) & 4278190335; + x = (x | (x<<8)) & 251719695; + x = (x | (x<<4)) & 3272356035; + x = (x | (x<<2)) & 1227133513; + + y &= 0x3FF; + y = (y | (y<<16)) & 4278190335; + y = (y | (y<<8)) & 251719695; + y = (y | (y<<4)) & 3272356035; + y = (y | (y<<2)) & 1227133513; + x |= (y << 1); + + z &= 0x3FF; + z = (z | (z<<16)) & 4278190335; + z = (z | (z<<8)) & 251719695; + z = (z | (z<<4)) & 3272356035; + z = (z | (z<<2)) & 1227133513; + + return x | (z << 2); +} + +//Extracts nth interleaved component of a 3-tuple +exports.deinterleave3 = function(v, n) { + v = (v >>> n) & 1227133513; + v = (v | (v>>>2)) & 3272356035; + v = (v | (v>>>4)) & 251719695; + v = (v | (v>>>8)) & 4278190335; + v = (v | (v>>>16)) & 0x3FF; + return (v<<22)>>22; +} + +//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) +exports.nextCombination = function(v) { + var t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); +} + + +},{}],81:[function(_dereq_,module,exports){ +'use strict' + +var clamp = _dereq_('clamp') + +module.exports = calcSDF + +var INF = 1e20; + +function calcSDF(src, options) { + if (!options) options = {} + + var cutoff = options.cutoff == null ? 0.25 : options.cutoff + var radius = options.radius == null ? 8 : options.radius + var channel = options.channel || 0 + var w, h, size, data, intData, stride, ctx, canvas, imgData, i, l + + // handle image container + if (ArrayBuffer.isView(src) || Array.isArray(src)) { + if (!options.width || !options.height) throw Error('For raw data width and height should be provided by options') + w = options.width, h = options.height + data = src + + if (!options.stride) stride = Math.floor(src.length / w / h) + else stride = options.stride + } + else { + if (window.HTMLCanvasElement && src instanceof window.HTMLCanvasElement) { + canvas = src + ctx = canvas.getContext('2d') + w = canvas.width, h = canvas.height + imgData = ctx.getImageData(0, 0, w, h) + data = imgData.data + stride = 4 + } + else if (window.CanvasRenderingContext2D && src instanceof window.CanvasRenderingContext2D) { + canvas = src.canvas + ctx = src + w = canvas.width, h = canvas.height + imgData = ctx.getImageData(0, 0, w, h) + data = imgData.data + stride = 4 + } + else if (window.ImageData && src instanceof window.ImageData) { + imgData = src + w = src.width, h = src.height + data = imgData.data + stride = 4 + } + } + + size = Math.max(w, h) + + //convert int data to floats + if ((window.Uint8ClampedArray && data instanceof window.Uint8ClampedArray) || (window.Uint8Array && data instanceof window.Uint8Array)) { + intData = data + data = Array(w*h) + + for (i = 0, l = intData.length; i < l; i++) { + data[i] = intData[i*stride + channel] / 255 + } + } + else { + if (stride !== 1) throw Error('Raw data can have only 1 value per pixel') + } + + // temporary arrays for the distance transform + var gridOuter = Array(w * h) + var gridInner = Array(w * h) + var f = Array(size) + var d = Array(size) + var z = Array(size + 1) + var v = Array(size) + + for (i = 0, l = w * h; i < l; i++) { + var a = data[i] + gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2) + gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2) + } + + edt(gridOuter, w, h, f, d, v, z) + edt(gridInner, w, h, f, d, v, z) + + var dist = window.Float32Array ? new Float32Array(w * h) : new Array(w * h) + + for (i = 0, l = w*h; i < l; i++) { + dist[i] = clamp(1 - ( (gridOuter[i] - gridInner[i]) / radius + cutoff), 0, 1) + } + + return dist +} + +// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/dt/ +function edt(data, width, height, f, d, v, z) { + for (var x = 0; x < width; x++) { + for (var y = 0; y < height; y++) { + f[y] = data[y * width + x] + } + edt1d(f, d, v, z, height) + for (y = 0; y < height; y++) { + data[y * width + x] = d[y] + } + } + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + f[x] = data[y * width + x] + } + edt1d(f, d, v, z, width) + for (x = 0; x < width; x++) { + data[y * width + x] = Math.sqrt(d[x]) + } + } +} + +// 1D squared distance transform +function edt1d(f, d, v, z, n) { + v[0] = 0; + z[0] = -INF + z[1] = +INF + + for (var q = 1, k = 0; q < n; q++) { + var s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) + while (s <= z[k]) { + k-- + s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) + } + k++ + v[k] = q + z[k] = s + z[k + 1] = +INF + } + + for (q = 0, k = 0; q < n; q++) { + while (z[k + 1] < q) k++ + d[q] = (q - v[k]) * (q - v[k]) + f[v[k]] + } +} + +},{"clamp":103}],82:[function(_dereq_,module,exports){ +(function (module, exports) { + 'use strict'; + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = _dereq_('buffer').Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); + +},{"buffer":91}],83:[function(_dereq_,module,exports){ +'use strict' + +module.exports = boundary + +function boundary (cells) { + var i, j, k + var n = cells.length + var sz = 0 + for (i = 0; i < n; ++i) { + sz += cells[i].length + } + var result = new Array(sz) + var ptr = 0 + for (i = 0; i < n; ++i) { + var c = cells[i] + var d = c.length + for (j = 0; j < d; ++j) { + var b = result[ptr++] = new Array(d - 1) + var p = 0 + for (k = 0; k < d; ++k) { + if (k === j) { + continue + } + b[p++] = c[k] + } + if (j & 1) { + var tmp = b[1] + b[1] = b[0] + b[0] = tmp + } + } + } + return result +} + +},{}],84:[function(_dereq_,module,exports){ +'use strict' + +module.exports = boxIntersectWrapper + +var pool = _dereq_('typedarray-pool') +var sweep = _dereq_('./lib/sweep') +var boxIntersectIter = _dereq_('./lib/intersect') + +function boxEmpty(d, box) { + for(var j=0; j>>1 + if(d <= 0) { + return + } + + var retval + + //Convert red boxes + var redList = pool.mallocDouble(2*d*n) + var redIds = pool.mallocInt32(n) + n = convertBoxes(red, d, redList, redIds) + + if(n > 0) { + if(d === 1 && full) { + //Special case: 1d complete + sweep.init(n) + retval = sweep.sweepComplete( + d, visit, + 0, n, redList, redIds, + 0, n, redList, redIds) + } else { + + //Convert blue boxes + var blueList = pool.mallocDouble(2*d*m) + var blueIds = pool.mallocInt32(m) + m = convertBoxes(blue, d, blueList, blueIds) + + if(m > 0) { + sweep.init(n+m) + + if(d === 1) { + //Special case: 1d bipartite + retval = sweep.sweepBipartite( + d, visit, + 0, n, redList, redIds, + 0, m, blueList, blueIds) + } else { + //General case: d>1 + retval = boxIntersectIter( + d, visit, full, + n, redList, redIds, + m, blueList, blueIds) + } + + pool.free(blueList) + pool.free(blueIds) + } + } + + pool.free(redList) + pool.free(redIds) + } + + return retval +} + + +var RESULT + +function appendItem(i,j) { + RESULT.push([i,j]) +} + +function intersectFullArray(x) { + RESULT = [] + boxIntersect(x, x, appendItem, true) + return RESULT +} + +function intersectBipartiteArray(x, y) { + RESULT = [] + boxIntersect(x, y, appendItem, false) + return RESULT +} + +//User-friendly wrapper, handle full input and no-visitor cases +function boxIntersectWrapper(arg0, arg1, arg2) { + var result + switch(arguments.length) { + case 1: + return intersectFullArray(arg0) + case 2: + if(typeof arg1 === 'function') { + return boxIntersect(arg0, arg0, arg1, true) + } else { + return intersectBipartiteArray(arg0, arg1) + } + case 3: + return boxIntersect(arg0, arg1, arg2, false) + default: + throw new Error('box-intersect: Invalid arguments') + } +} +},{"./lib/intersect":86,"./lib/sweep":90,"typedarray-pool":522}],85:[function(_dereq_,module,exports){ +'use strict' + +var DIMENSION = 'd' +var AXIS = 'ax' +var VISIT = 'vv' +var FLIP = 'fp' + +var ELEM_SIZE = 'es' + +var RED_START = 'rs' +var RED_END = 're' +var RED_BOXES = 'rb' +var RED_INDEX = 'ri' +var RED_PTR = 'rp' + +var BLUE_START = 'bs' +var BLUE_END = 'be' +var BLUE_BOXES = 'bb' +var BLUE_INDEX = 'bi' +var BLUE_PTR = 'bp' + +var RETVAL = 'rv' + +var INNER_LABEL = 'Q' + +var ARGS = [ + DIMENSION, + AXIS, + VISIT, + RED_START, + RED_END, + RED_BOXES, + RED_INDEX, + BLUE_START, + BLUE_END, + BLUE_BOXES, + BLUE_INDEX +] + +function generateBruteForce(redMajor, flip, full) { + var funcName = 'bruteForce' + + (redMajor ? 'Red' : 'Blue') + + (flip ? 'Flip' : '') + + (full ? 'Full' : '') + + var code = ['function ', funcName, '(', ARGS.join(), '){', + 'var ', ELEM_SIZE, '=2*', DIMENSION, ';'] + + var redLoop = + 'for(var i=' + RED_START + ',' + RED_PTR + '=' + ELEM_SIZE + '*' + RED_START + ';' + + 'i<' + RED_END +';' + + '++i,' + RED_PTR + '+=' + ELEM_SIZE + '){' + + 'var x0=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '],' + + 'x1=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '+' + DIMENSION + '],' + + 'xi=' + RED_INDEX + '[i];' + + var blueLoop = + 'for(var j=' + BLUE_START + ',' + BLUE_PTR + '=' + ELEM_SIZE + '*' + BLUE_START + ';' + + 'j<' + BLUE_END + ';' + + '++j,' + BLUE_PTR + '+=' + ELEM_SIZE + '){' + + 'var y0=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '],' + + (full ? 'y1=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '+' + DIMENSION + '],' : '') + + 'yi=' + BLUE_INDEX + '[j];' + + if(redMajor) { + code.push(redLoop, INNER_LABEL, ':', blueLoop) + } else { + code.push(blueLoop, INNER_LABEL, ':', redLoop) + } + + if(full) { + code.push('if(y1' + + BLUE_END + '-' + BLUE_START + '){') + + if(full) { + invoke(true, false) + code.push('}else{') + invoke(false, false) + } else { + code.push('if(' + FLIP + '){') + invoke(true, true) + code.push('}else{') + invoke(true, false) + code.push('}}else{if(' + FLIP + '){') + invoke(false, true) + code.push('}else{') + invoke(false, false) + code.push('}') + } + code.push('}}return ' + funcName) + + var codeStr = prefix.join('') + code.join('') + var proc = new Function(codeStr) + return proc() +} + + +exports.partial = bruteForcePlanner(false) +exports.full = bruteForcePlanner(true) +},{}],86:[function(_dereq_,module,exports){ +'use strict' + +module.exports = boxIntersectIter + +var pool = _dereq_('typedarray-pool') +var bits = _dereq_('bit-twiddle') +var bruteForce = _dereq_('./brute') +var bruteForcePartial = bruteForce.partial +var bruteForceFull = bruteForce.full +var sweep = _dereq_('./sweep') +var findMedian = _dereq_('./median') +var genPartition = _dereq_('./partition') + +//Twiddle parameters +var BRUTE_FORCE_CUTOFF = 128 //Cut off for brute force search +var SCAN_CUTOFF = (1<<22) //Cut off for two way scan +var SCAN_COMPLETE_CUTOFF = (1<<22) + +//Partition functions +var partitionInteriorContainsInterval = genPartition( + '!(lo>=p0)&&!(p1>=hi)', + ['p0', 'p1']) + +var partitionStartEqual = genPartition( + 'lo===p0', + ['p0']) + +var partitionStartLessThan = genPartition( + 'lo 0) { + top -= 1 + + var iptr = top * IFRAME_SIZE + var axis = BOX_ISTACK[iptr] + var redStart = BOX_ISTACK[iptr+1] + var redEnd = BOX_ISTACK[iptr+2] + var blueStart = BOX_ISTACK[iptr+3] + var blueEnd = BOX_ISTACK[iptr+4] + var state = BOX_ISTACK[iptr+5] + + var dptr = top * DFRAME_SIZE + var lo = BOX_DSTACK[dptr] + var hi = BOX_DSTACK[dptr+1] + + //Unpack state info + var flip = (state & 1) + var full = !!(state & 16) + + //Unpack indices + var red = xBoxes + var redIndex = xIndex + var blue = yBoxes + var blueIndex = yIndex + if(flip) { + red = yBoxes + redIndex = yIndex + blue = xBoxes + blueIndex = xIndex + } + + if(state & 2) { + redEnd = partitionStartLessThan( + d, axis, + redStart, redEnd, red, redIndex, + hi) + if(redStart >= redEnd) { + continue + } + } + if(state & 4) { + redStart = partitionEndLessThanEqual( + d, axis, + redStart, redEnd, red, redIndex, + lo) + if(redStart >= redEnd) { + continue + } + } + + var redCount = redEnd - redStart + var blueCount = blueEnd - blueStart + + if(full) { + if(d * redCount * (redCount + blueCount) < SCAN_COMPLETE_CUTOFF) { + retval = sweep.scanComplete( + d, axis, visit, + redStart, redEnd, red, redIndex, + blueStart, blueEnd, blue, blueIndex) + if(retval !== void 0) { + return retval + } + continue + } + } else { + if(d * Math.min(redCount, blueCount) < BRUTE_FORCE_CUTOFF) { + //If input small, then use brute force + retval = bruteForcePartial( + d, axis, visit, flip, + redStart, redEnd, red, redIndex, + blueStart, blueEnd, blue, blueIndex) + if(retval !== void 0) { + return retval + } + continue + } else if(d * redCount * blueCount < SCAN_CUTOFF) { + //If input medium sized, then use sweep and prune + retval = sweep.scanBipartite( + d, axis, visit, flip, + redStart, redEnd, red, redIndex, + blueStart, blueEnd, blue, blueIndex) + if(retval !== void 0) { + return retval + } + continue + } + } + + //First, find all red intervals whose interior contains (lo,hi) + var red0 = partitionInteriorContainsInterval( + d, axis, + redStart, redEnd, red, redIndex, + lo, hi) + + //Lower dimensional case + if(redStart < red0) { + + if(d * (red0 - redStart) < BRUTE_FORCE_CUTOFF) { + //Special case for small inputs: use brute force + retval = bruteForceFull( + d, axis+1, visit, + redStart, red0, red, redIndex, + blueStart, blueEnd, blue, blueIndex) + if(retval !== void 0) { + return retval + } + } else if(axis === d-2) { + if(flip) { + retval = sweep.sweepBipartite( + d, visit, + blueStart, blueEnd, blue, blueIndex, + redStart, red0, red, redIndex) + } else { + retval = sweep.sweepBipartite( + d, visit, + redStart, red0, red, redIndex, + blueStart, blueEnd, blue, blueIndex) + } + if(retval !== void 0) { + return retval + } + } else { + iterPush(top++, + axis+1, + redStart, red0, + blueStart, blueEnd, + flip, + -Infinity, Infinity) + iterPush(top++, + axis+1, + blueStart, blueEnd, + redStart, red0, + flip^1, + -Infinity, Infinity) + } + } + + //Divide and conquer phase + if(red0 < redEnd) { + + //Cut blue into 3 parts: + // + // Points < mid point + // Points = mid point + // Points > mid point + // + var blue0 = findMedian( + d, axis, + blueStart, blueEnd, blue, blueIndex) + var mid = blue[elemSize * blue0 + axis] + var blue1 = partitionStartEqual( + d, axis, + blue0, blueEnd, blue, blueIndex, + mid) + + //Right case + if(blue1 < blueEnd) { + iterPush(top++, + axis, + red0, redEnd, + blue1, blueEnd, + (flip|4) + (full ? 16 : 0), + mid, hi) + } + + //Left case + if(blueStart < blue0) { + iterPush(top++, + axis, + red0, redEnd, + blueStart, blue0, + (flip|2) + (full ? 16 : 0), + lo, mid) + } + + //Center case (the hard part) + if(blue0 + 1 === blue1) { + //Optimization: Range with exactly 1 point, use a brute force scan + if(full) { + retval = onePointFull( + d, axis, visit, + red0, redEnd, red, redIndex, + blue0, blue, blueIndex[blue0]) + } else { + retval = onePointPartial( + d, axis, visit, flip, + red0, redEnd, red, redIndex, + blue0, blue, blueIndex[blue0]) + } + if(retval !== void 0) { + return retval + } + } else if(blue0 < blue1) { + var red1 + if(full) { + //If full intersection, need to handle special case + red1 = partitionContainsPoint( + d, axis, + red0, redEnd, red, redIndex, + mid) + if(red0 < red1) { + var redX = partitionStartEqual( + d, axis, + red0, red1, red, redIndex, + mid) + if(axis === d-2) { + //Degenerate sweep intersection: + // [red0, redX] with [blue0, blue1] + if(red0 < redX) { + retval = sweep.sweepComplete( + d, visit, + red0, redX, red, redIndex, + blue0, blue1, blue, blueIndex) + if(retval !== void 0) { + return retval + } + } + + //Normal sweep intersection: + // [redX, red1] with [blue0, blue1] + if(redX < red1) { + retval = sweep.sweepBipartite( + d, visit, + redX, red1, red, redIndex, + blue0, blue1, blue, blueIndex) + if(retval !== void 0) { + return retval + } + } + } else { + if(red0 < redX) { + iterPush(top++, + axis+1, + red0, redX, + blue0, blue1, + 16, + -Infinity, Infinity) + } + if(redX < red1) { + iterPush(top++, + axis+1, + redX, red1, + blue0, blue1, + 0, + -Infinity, Infinity) + iterPush(top++, + axis+1, + blue0, blue1, + redX, red1, + 1, + -Infinity, Infinity) + } + } + } + } else { + if(flip) { + red1 = partitionContainsPointProper( + d, axis, + red0, redEnd, red, redIndex, + mid) + } else { + red1 = partitionContainsPoint( + d, axis, + red0, redEnd, red, redIndex, + mid) + } + if(red0 < red1) { + if(axis === d-2) { + if(flip) { + retval = sweep.sweepBipartite( + d, visit, + blue0, blue1, blue, blueIndex, + red0, red1, red, redIndex) + } else { + retval = sweep.sweepBipartite( + d, visit, + red0, red1, red, redIndex, + blue0, blue1, blue, blueIndex) + } + } else { + iterPush(top++, + axis+1, + red0, red1, + blue0, blue1, + flip, + -Infinity, Infinity) + iterPush(top++, + axis+1, + blue0, blue1, + red0, red1, + flip^1, + -Infinity, Infinity) + } + } + } + } + } + } +} +},{"./brute":85,"./median":87,"./partition":88,"./sweep":90,"bit-twiddle":80,"typedarray-pool":522}],87:[function(_dereq_,module,exports){ +'use strict' + +module.exports = findMedian + +var genPartition = _dereq_('./partition') + +var partitionStartLessThan = genPartition('lostart && boxes[ptr+axis] > x; + --j, ptr-=elemSize) { + //Swap + var aPtr = ptr + var bPtr = ptr+elemSize + for(var k=0; k>> 1) + var elemSize = 2*d + var pivot = mid + var value = boxes[elemSize*mid+axis] + + while(lo < hi) { + if(hi - lo < PARTITION_THRESHOLD) { + insertionSort(d, axis, lo, hi, boxes, ids) + value = boxes[elemSize*mid+axis] + break + } + + //Select pivot using median-of-3 + var count = hi - lo + var pivot0 = (Math.random()*count+lo)|0 + var value0 = boxes[elemSize*pivot0 + axis] + var pivot1 = (Math.random()*count+lo)|0 + var value1 = boxes[elemSize*pivot1 + axis] + var pivot2 = (Math.random()*count+lo)|0 + var value2 = boxes[elemSize*pivot2 + axis] + if(value0 <= value1) { + if(value2 >= value1) { + pivot = pivot1 + value = value1 + } else if(value0 >= value2) { + pivot = pivot0 + value = value0 + } else { + pivot = pivot2 + value = value2 + } + } else { + if(value1 >= value2) { + pivot = pivot1 + value = value1 + } else if(value2 >= value0) { + pivot = pivot0 + value = value0 + } else { + pivot = pivot2 + value = value2 + } + } + + //Swap pivot to end of array + var aPtr = elemSize * (hi-1) + var bPtr = elemSize * pivot + for(var i=0; i= 0) { + reads.push('lo=e[k+n]') + } + if(predicate.indexOf('hi') >= 0) { + reads.push('hi=e[k+o]') + } + fargs.push( + code.replace('_', reads.join()) + .replace('$', predicate)) + return Function.apply(void 0, fargs) +} +},{}],89:[function(_dereq_,module,exports){ +'use strict'; + +//This code is extracted from ndarray-sort +//It is inlined here as a temporary workaround + +module.exports = wrapper; + +var INSERT_SORT_CUTOFF = 32 + +function wrapper(data, n0) { + if (n0 <= 4*INSERT_SORT_CUTOFF) { + insertionSort(0, n0 - 1, data); + } else { + quickSort(0, n0 - 1, data); + } +} + +function insertionSort(left, right, data) { + var ptr = 2*(left+1) + for(var i=left+1; i<=right; ++i) { + var a = data[ptr++] + var b = data[ptr++] + var j = i + var jptr = ptr-2 + while(j-- > left) { + var x = data[jptr-2] + var y = data[jptr-1] + if(x < a) { + break + } else if(x === a && y < b) { + break + } + data[jptr] = x + data[jptr+1] = y + jptr -= 2 + } + data[jptr] = a + data[jptr+1] = b + } +} + +function swap(i, j, data) { + i *= 2 + j *= 2 + var x = data[i] + var y = data[i+1] + data[i] = data[j] + data[i+1] = data[j+1] + data[j] = x + data[j+1] = y +} + +function move(i, j, data) { + i *= 2 + j *= 2 + data[i] = data[j] + data[i+1] = data[j+1] +} + +function rotate(i, j, k, data) { + i *= 2 + j *= 2 + k *= 2 + var x = data[i] + var y = data[i+1] + data[i] = data[j] + data[i+1] = data[j+1] + data[j] = data[k] + data[j+1] = data[k+1] + data[k] = x + data[k+1] = y +} + +function shufflePivot(i, j, px, py, data) { + i *= 2 + j *= 2 + data[i] = data[j] + data[j] = px + data[i+1] = data[j+1] + data[j+1] = py +} + +function compare(i, j, data) { + i *= 2 + j *= 2 + var x = data[i], + y = data[j] + if(x < y) { + return false + } else if(x === y) { + return data[i+1] > data[j+1] + } + return true +} + +function comparePivot(i, y, b, data) { + i *= 2 + var x = data[i] + if(x < y) { + return true + } else if(x === y) { + return data[i+1] < b + } + return false +} + +function quickSort(left, right, data) { + var sixth = (right - left + 1) / 6 | 0, + index1 = left + sixth, + index5 = right - sixth, + index3 = left + right >> 1, + index2 = index3 - sixth, + index4 = index3 + sixth, + el1 = index1, + el2 = index2, + el3 = index3, + el4 = index4, + el5 = index5, + less = left + 1, + great = right - 1, + tmp = 0 + if(compare(el1, el2, data)) { + tmp = el1 + el1 = el2 + el2 = tmp + } + if(compare(el4, el5, data)) { + tmp = el4 + el4 = el5 + el5 = tmp + } + if(compare(el1, el3, data)) { + tmp = el1 + el1 = el3 + el3 = tmp + } + if(compare(el2, el3, data)) { + tmp = el2 + el2 = el3 + el3 = tmp + } + if(compare(el1, el4, data)) { + tmp = el1 + el1 = el4 + el4 = tmp + } + if(compare(el3, el4, data)) { + tmp = el3 + el3 = el4 + el4 = tmp + } + if(compare(el2, el5, data)) { + tmp = el2 + el2 = el5 + el5 = tmp + } + if(compare(el2, el3, data)) { + tmp = el2 + el2 = el3 + el3 = tmp + } + if(compare(el4, el5, data)) { + tmp = el4 + el4 = el5 + el5 = tmp + } + + var pivot1X = data[2*el2] + var pivot1Y = data[2*el2+1] + var pivot2X = data[2*el4] + var pivot2Y = data[2*el4+1] + + var ptr0 = 2 * el1; + var ptr2 = 2 * el3; + var ptr4 = 2 * el5; + var ptr5 = 2 * index1; + var ptr6 = 2 * index3; + var ptr7 = 2 * index5; + for (var i1 = 0; i1 < 2; ++i1) { + var x = data[ptr0+i1]; + var y = data[ptr2+i1]; + var z = data[ptr4+i1]; + data[ptr5+i1] = x; + data[ptr6+i1] = y; + data[ptr7+i1] = z; + } + + move(index2, left, data) + move(index4, right, data) + for (var k = less; k <= great; ++k) { + if (comparePivot(k, pivot1X, pivot1Y, data)) { + if (k !== less) { + swap(k, less, data) + } + ++less; + } else { + if (!comparePivot(k, pivot2X, pivot2Y, data)) { + while (true) { + if (!comparePivot(great, pivot2X, pivot2Y, data)) { + if (--great < k) { + break; + } + continue; + } else { + if (comparePivot(great, pivot1X, pivot1Y, data)) { + rotate(k, less, great, data) + ++less; + --great; + } else { + swap(k, great, data) + --great; + } + break; + } + } + } + } + } + shufflePivot(left, less-1, pivot1X, pivot1Y, data) + shufflePivot(right, great+1, pivot2X, pivot2Y, data) + if (less - 2 - left <= INSERT_SORT_CUTOFF) { + insertionSort(left, less - 2, data); + } else { + quickSort(left, less - 2, data); + } + if (right - (great + 2) <= INSERT_SORT_CUTOFF) { + insertionSort(great + 2, right, data); + } else { + quickSort(great + 2, right, data); + } + if (great - less <= INSERT_SORT_CUTOFF) { + insertionSort(less, great, data); + } else { + quickSort(less, great, data); + } +} +},{}],90:[function(_dereq_,module,exports){ +'use strict' + +module.exports = { + init: sqInit, + sweepBipartite: sweepBipartite, + sweepComplete: sweepComplete, + scanBipartite: scanBipartite, + scanComplete: scanComplete +} + +var pool = _dereq_('typedarray-pool') +var bits = _dereq_('bit-twiddle') +var isort = _dereq_('./sort') + +//Flag for blue +var BLUE_FLAG = (1<<28) + +//1D sweep event queue stuff (use pool to save space) +var INIT_CAPACITY = 1024 +var RED_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) +var RED_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) +var BLUE_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) +var BLUE_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) +var COMMON_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) +var COMMON_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) +var SWEEP_EVENTS = pool.mallocDouble(INIT_CAPACITY * 8) + +//Reserves memory for the 1D sweep data structures +function sqInit(count) { + var rcount = bits.nextPow2(count) + if(RED_SWEEP_QUEUE.length < rcount) { + pool.free(RED_SWEEP_QUEUE) + RED_SWEEP_QUEUE = pool.mallocInt32(rcount) + } + if(RED_SWEEP_INDEX.length < rcount) { + pool.free(RED_SWEEP_INDEX) + RED_SWEEP_INDEX = pool.mallocInt32(rcount) + } + if(BLUE_SWEEP_QUEUE.length < rcount) { + pool.free(BLUE_SWEEP_QUEUE) + BLUE_SWEEP_QUEUE = pool.mallocInt32(rcount) + } + if(BLUE_SWEEP_INDEX.length < rcount) { + pool.free(BLUE_SWEEP_INDEX) + BLUE_SWEEP_INDEX = pool.mallocInt32(rcount) + } + if(COMMON_SWEEP_QUEUE.length < rcount) { + pool.free(COMMON_SWEEP_QUEUE) + COMMON_SWEEP_QUEUE = pool.mallocInt32(rcount) + } + if(COMMON_SWEEP_INDEX.length < rcount) { + pool.free(COMMON_SWEEP_INDEX) + COMMON_SWEEP_INDEX = pool.mallocInt32(rcount) + } + var eventLength = 8 * rcount + if(SWEEP_EVENTS.length < eventLength) { + pool.free(SWEEP_EVENTS) + SWEEP_EVENTS = pool.mallocDouble(eventLength) + } +} + +//Remove an item from the active queue in O(1) +function sqPop(queue, index, count, item) { + var idx = index[item] + var top = queue[count-1] + queue[idx] = top + index[top] = idx +} + +//Insert an item into the active queue in O(1) +function sqPush(queue, index, count, item) { + queue[count] = item + index[item] = count +} + +//Recursion base case: use 1D sweep algorithm +function sweepBipartite( + d, visit, + redStart, redEnd, red, redIndex, + blueStart, blueEnd, blue, blueIndex) { + + //store events as pairs [coordinate, idx] + // + // red create: -(idx+1) + // red destroy: idx + // blue create: -(idx+BLUE_FLAG) + // blue destroy: idx+BLUE_FLAG + // + var ptr = 0 + var elemSize = 2*d + var istart = d-1 + var iend = elemSize-1 + + for(var i=redStart; iright + var n = ptr >>> 1 + isort(SWEEP_EVENTS, n) + + var redActive = 0 + var blueActive = 0 + for(var i=0; i= BLUE_FLAG) { + //blue destroy event + e = (e-BLUE_FLAG)|0 + sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, e) + } else if(e >= 0) { + //red destroy event + sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e) + } else if(e <= -BLUE_FLAG) { + //blue create event + e = (-e-BLUE_FLAG)|0 + for(var j=0; jright + var n = ptr >>> 1 + isort(SWEEP_EVENTS, n) + + var redActive = 0 + var blueActive = 0 + var commonActive = 0 + for(var i=0; i>1) === (SWEEP_EVENTS[2*i+3]>>1)) { + color = 2 + i += 1 + } + + if(e < 0) { + //Create event + var id = -(e>>1) - 1 + + //Intersect with common + for(var j=0; j>1) - 1 + if(color === 0) { + //Red + sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, id) + } else if(color === 1) { + //Blue + sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, id) + } else if(color === 2) { + //Both + sqPop(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive--, id) + } + } + } +} + +//Sweep and prune/scanline algorithm: +// Scan along axis, detect intersections +// Brute force all boxes along axis +function scanBipartite( + d, axis, visit, flip, + redStart, redEnd, red, redIndex, + blueStart, blueEnd, blue, blueIndex) { + + var ptr = 0 + var elemSize = 2*d + var istart = axis + var iend = axis+d + + var redShift = 1 + var blueShift = 1 + if(flip) { + blueShift = BLUE_FLAG + } else { + redShift = BLUE_FLAG + } + + for(var i=redStart; iright + var n = ptr >>> 1 + isort(SWEEP_EVENTS, n) + + var redActive = 0 + for(var i=0; i= BLUE_FLAG) { + isRed = !flip + idx -= BLUE_FLAG + } else { + isRed = !!flip + idx -= 1 + } + if(isRed) { + sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, idx) + } else { + var blueId = blueIndex[idx] + var bluePtr = elemSize * idx + + var b0 = blue[bluePtr+axis+1] + var b1 = blue[bluePtr+axis+1+d] + +red_loop: + for(var j=0; jright + var n = ptr >>> 1 + isort(SWEEP_EVENTS, n) + + var redActive = 0 + for(var i=0; i= BLUE_FLAG) { + RED_SWEEP_QUEUE[redActive++] = idx - BLUE_FLAG + } else { + idx -= 1 + var blueId = blueIndex[idx] + var bluePtr = elemSize * idx + + var b0 = blue[bluePtr+axis+1] + var b1 = blue[bluePtr+axis+1+d] + +red_loop: + for(var j=0; j=0; --j) { + if(RED_SWEEP_QUEUE[j] === idx) { + for(var k=j+1; k 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],93:[function(_dereq_,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = _dereq_('base64-js') +var ieee754 = _dereq_('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } + + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +},{"base64-js":62,"ieee754":395}],94:[function(_dereq_,module,exports){ +'use strict' + +var monotoneTriangulate = _dereq_('./lib/monotone') +var makeIndex = _dereq_('./lib/triangulation') +var delaunayFlip = _dereq_('./lib/delaunay') +var filterTriangulation = _dereq_('./lib/filter') + +module.exports = cdt2d + +function canonicalizeEdge(e) { + return [Math.min(e[0], e[1]), Math.max(e[0], e[1])] +} + +function compareEdge(a, b) { + return a[0]-b[0] || a[1]-b[1] +} + +function canonicalizeEdges(edges) { + return edges.map(canonicalizeEdge).sort(compareEdge) +} + +function getDefault(options, property, dflt) { + if(property in options) { + return options[property] + } + return dflt +} + +function cdt2d(points, edges, options) { + + if(!Array.isArray(edges)) { + options = edges || {} + edges = [] + } else { + options = options || {} + edges = edges || [] + } + + //Parse out options + var delaunay = !!getDefault(options, 'delaunay', true) + var interior = !!getDefault(options, 'interior', true) + var exterior = !!getDefault(options, 'exterior', true) + var infinity = !!getDefault(options, 'infinity', false) + + //Handle trivial case + if((!interior && !exterior) || points.length === 0) { + return [] + } + + //Construct initial triangulation + var cells = monotoneTriangulate(points, edges) + + //If delaunay refinement needed, then improve quality by edge flipping + if(delaunay || interior !== exterior || infinity) { + + //Index all of the cells to support fast neighborhood queries + var triangulation = makeIndex(points.length, canonicalizeEdges(edges)) + for(var i=0; i 0) { + var b = stack.pop() + var a = stack.pop() + + //Find opposite pairs + var x = -1, y = -1 + var star = stars[a] + for(var i=1; i= 0) { + continue + } + + //Flip the edge + triangulation.flip(a, b) + + //Test flipping neighboring edges + testFlip(points, triangulation, stack, x, a, y) + testFlip(points, triangulation, stack, a, y, x) + testFlip(points, triangulation, stack, y, b, x) + testFlip(points, triangulation, stack, b, x, y) + } +} + +},{"binary-search-bounds":99,"robust-in-sphere":484}],96:[function(_dereq_,module,exports){ +'use strict' + +var bsearch = _dereq_('binary-search-bounds') + +module.exports = classifyFaces + +function FaceIndex(cells, neighbor, constraint, flags, active, next, boundary) { + this.cells = cells + this.neighbor = neighbor + this.flags = flags + this.constraint = constraint + this.active = active + this.next = next + this.boundary = boundary +} + +var proto = FaceIndex.prototype + +function compareCell(a, b) { + return a[0] - b[0] || + a[1] - b[1] || + a[2] - b[2] +} + +proto.locate = (function() { + var key = [0,0,0] + return function(a, b, c) { + var x = a, y = b, z = c + if(b < c) { + if(b < a) { + x = b + y = c + z = a + } + } else if(c < a) { + x = c + y = a + z = b + } + if(x < 0) { + return -1 + } + key[0] = x + key[1] = y + key[2] = z + return bsearch.eq(this.cells, key, compareCell) + } +})() + +function indexCells(triangulation, infinity) { + //First get cells and canonicalize + var cells = triangulation.cells() + var nc = cells.length + for(var i=0; i 0 || next.length > 0) { + while(active.length > 0) { + var t = active.pop() + if(flags[t] === -side) { + continue + } + flags[t] = side + var c = cells[t] + for(var j=0; j<3; ++j) { + var f = neighbor[3*t+j] + if(f >= 0 && flags[f] === 0) { + if(constraint[3*t+j]) { + next.push(f) + } else { + active.push(f) + flags[f] = side + } + } + } + } + + //Swap arrays and loop + var tmp = next + next = active + active = tmp + next.length = 0 + side = -side + } + + var result = filterCells(cells, flags, target) + if(infinity) { + return result.concat(index.boundary) + } + return result +} + +},{"binary-search-bounds":99}],97:[function(_dereq_,module,exports){ +'use strict' + +var bsearch = _dereq_('binary-search-bounds') +var orient = _dereq_('robust-orientation')[3] + +var EVENT_POINT = 0 +var EVENT_END = 1 +var EVENT_START = 2 + +module.exports = monotoneTriangulate + +//A partial convex hull fragment, made of two unimonotone polygons +function PartialHull(a, b, idx, lowerIds, upperIds) { + this.a = a + this.b = b + this.idx = idx + this.lowerIds = lowerIds + this.upperIds = upperIds +} + +//An event in the sweep line procedure +function Event(a, b, type, idx) { + this.a = a + this.b = b + this.type = type + this.idx = idx +} + +//This is used to compare events for the sweep line procedure +// Points are: +// 1. sorted lexicographically +// 2. sorted by type (point < end < start) +// 3. segments sorted by winding order +// 4. sorted by index +function compareEvent(a, b) { + var d = + (a.a[0] - b.a[0]) || + (a.a[1] - b.a[1]) || + (a.type - b.type) + if(d) { return d } + if(a.type !== EVENT_POINT) { + d = orient(a.a, a.b, b.b) + if(d) { return d } + } + return a.idx - b.idx +} + +function testPoint(hull, p) { + return orient(hull.a, hull.b, p) +} + +function addPoint(cells, hulls, points, p, idx) { + var lo = bsearch.lt(hulls, p, testPoint) + var hi = bsearch.gt(hulls, p, testPoint) + for(var i=lo; i 1 && orient( + points[lowerIds[m-2]], + points[lowerIds[m-1]], + p) > 0) { + cells.push( + [lowerIds[m-1], + lowerIds[m-2], + idx]) + m -= 1 + } + lowerIds.length = m + lowerIds.push(idx) + + //Insert p into upper hull + var upperIds = hull.upperIds + var m = upperIds.length + while(m > 1 && orient( + points[upperIds[m-2]], + points[upperIds[m-1]], + p) < 0) { + cells.push( + [upperIds[m-2], + upperIds[m-1], + idx]) + m -= 1 + } + upperIds.length = m + upperIds.push(idx) + } +} + +function findSplit(hull, edge) { + var d + if(hull.a[0] < edge.a[0]) { + d = orient(hull.a, hull.b, edge.a) + } else { + d = orient(edge.b, edge.a, hull.a) + } + if(d) { return d } + if(edge.b[0] < hull.b[0]) { + d = orient(hull.a, hull.b, edge.b) + } else { + d = orient(edge.b, edge.a, hull.b) + } + return d || hull.idx - edge.idx +} + +function splitHulls(hulls, points, event) { + var splitIdx = bsearch.le(hulls, event, findSplit) + var hull = hulls[splitIdx] + var upperIds = hull.upperIds + var x = upperIds[upperIds.length-1] + hull.upperIds = [x] + hulls.splice(splitIdx+1, 0, + new PartialHull(event.a, event.b, event.idx, [x], upperIds)) +} + + +function mergeHulls(hulls, points, event) { + //Swap pointers for merge search + var tmp = event.a + event.a = event.b + event.b = tmp + var mergeIdx = bsearch.eq(hulls, event, findSplit) + var upper = hulls[mergeIdx] + var lower = hulls[mergeIdx-1] + lower.upperIds = upper.upperIds + hulls.splice(mergeIdx, 1) +} + + +function monotoneTriangulate(points, edges) { + + var numPoints = points.length + var numEdges = edges.length + + var events = [] + + //Create point events + for(var i=0; i b[0]) { + events.push( + new Event(b, a, EVENT_START, i), + new Event(a, b, EVENT_END, i)) + } + } + + //Sort events + events.sort(compareEvent) + + //Initialize hull + var minX = events[0].a[0] - (1 + Math.abs(events[0].a[0])) * Math.pow(2, -52) + var hull = [ new PartialHull([minX, 1], [minX, 0], -1, [], [], [], []) ] + + //Process events in order + var cells = [] + for(var i=0, numEvents=events.length; i= 0 + } +})() + +proto.removeTriangle = function(i, j, k) { + var stars = this.stars + removePair(stars[i], j, k) + removePair(stars[j], k, i) + removePair(stars[k], i, j) +} + +proto.addTriangle = function(i, j, k) { + var stars = this.stars + stars[i].push(j, k) + stars[j].push(k, i) + stars[k].push(i, j) +} + +proto.opposite = function(j, i) { + var list = this.stars[i] + for(var k=1, n=list.length; k>>1,x=a[m]"] + if(earlyOut) { + if(predicate.indexOf("c") < 0) { + code.push(";if(x===y){return m}else if(x<=y){") + } else { + code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") + } + } else { + code.push(";if(", predicate, "){i=m;") + } + if(reversed) { + code.push("l=m+1}else{h=m-1}") + } else { + code.push("h=m-1}else{l=m+1}") + } + code.push("}") + if(earlyOut) { + code.push("return -1};") + } else { + code.push("return i};") + } + return code.join("") +} + +function compileBoundsSearch(predicate, reversed, suffix, earlyOut) { + var result = new Function([ + compileSearch("A", "x" + predicate + "y", reversed, ["y"], earlyOut), + compileSearch("P", "c(x,y)" + predicate + "0", reversed, ["y", "c"], earlyOut), +"function dispatchBsearch", suffix, "(a,y,c,l,h){\ +if(typeof(c)==='function'){\ +return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)\ +}else{\ +return A(a,(c===void 0)?0:c|0,(l===void 0)?a.length-1:l|0,y)\ +}}\ +return dispatchBsearch", suffix].join("")) + return result() +} + +module.exports = { + ge: compileBoundsSearch(">=", false, "GE"), + gt: compileBoundsSearch(">", false, "GT"), + lt: compileBoundsSearch("<", true, "LT"), + le: compileBoundsSearch("<=", true, "LE"), + eq: compileBoundsSearch("-", true, "EQ", true) +} + +},{}],100:[function(_dereq_,module,exports){ +'use strict' + +module.exports = orientation + +function orientation(s) { + var p = 1 + for(var i=1; i max ? max : value) + : (value < max ? max : value > min ? min : value) +} + +},{}],104:[function(_dereq_,module,exports){ +'use strict' + +module.exports = cleanPSLG + +var UnionFind = _dereq_('union-find') +var boxIntersect = _dereq_('box-intersect') +var segseg = _dereq_('robust-segment-intersect') +var rat = _dereq_('big-rat') +var ratCmp = _dereq_('big-rat/cmp') +var ratToFloat = _dereq_('big-rat/to-float') +var ratVec = _dereq_('rat-vec') +var nextafter = _dereq_('nextafter') + +var solveIntersection = _dereq_('./lib/rat-seg-intersect') + +// Bounds on a rational number when rounded to a float +function boundRat (r) { + var f = ratToFloat(r) + return [ + nextafter(f, -Infinity), + nextafter(f, Infinity) + ] +} + +// Convert a list of edges in a pslg to bounding boxes +function boundEdges (points, edges) { + var bounds = new Array(edges.length) + for (var i = 0; i < edges.length; ++i) { + var e = edges[i] + var a = points[e[0]] + var b = points[e[1]] + bounds[i] = [ + nextafter(Math.min(a[0], b[0]), -Infinity), + nextafter(Math.min(a[1], b[1]), -Infinity), + nextafter(Math.max(a[0], b[0]), Infinity), + nextafter(Math.max(a[1], b[1]), Infinity) + ] + } + return bounds +} + +// Convert a list of points into bounding boxes by duplicating coords +function boundPoints (points) { + var bounds = new Array(points.length) + for (var i = 0; i < points.length; ++i) { + var p = points[i] + bounds[i] = [ + nextafter(p[0], -Infinity), + nextafter(p[1], -Infinity), + nextafter(p[0], Infinity), + nextafter(p[1], Infinity) + ] + } + return bounds +} + +// Find all pairs of crossing edges in a pslg (given edge bounds) +function getCrossings (points, edges, edgeBounds) { + var result = [] + boxIntersect(edgeBounds, function (i, j) { + var e = edges[i] + var f = edges[j] + if (e[0] === f[0] || e[0] === f[1] || + e[1] === f[0] || e[1] === f[1]) { + return + } + var a = points[e[0]] + var b = points[e[1]] + var c = points[f[0]] + var d = points[f[1]] + if (segseg(a, b, c, d)) { + result.push([i, j]) + } + }) + return result +} + +// Find all pairs of crossing vertices in a pslg (given edge/vert bounds) +function getTJunctions (points, edges, edgeBounds, vertBounds) { + var result = [] + boxIntersect(edgeBounds, vertBounds, function (i, v) { + var e = edges[i] + if (e[0] === v || e[1] === v) { + return + } + var p = points[v] + var a = points[e[0]] + var b = points[e[1]] + if (segseg(a, b, p, p)) { + result.push([i, v]) + } + }) + return result +} + +// Cut edges along crossings/tjunctions +function cutEdges (floatPoints, edges, crossings, junctions, useColor) { + var i, e + + // Convert crossings into tjunctions by constructing rational points + var ratPoints = floatPoints.map(function(p) { + return [ + rat(p[0]), + rat(p[1]) + ] + }) + for (i = 0; i < crossings.length; ++i) { + var crossing = crossings[i] + e = crossing[0] + var f = crossing[1] + var ee = edges[e] + var ef = edges[f] + var x = solveIntersection( + ratVec(floatPoints[ee[0]]), + ratVec(floatPoints[ee[1]]), + ratVec(floatPoints[ef[0]]), + ratVec(floatPoints[ef[1]])) + if (!x) { + // Segments are parallel, should already be handled by t-junctions + continue + } + var idx = floatPoints.length + floatPoints.push([ratToFloat(x[0]), ratToFloat(x[1])]) + ratPoints.push(x) + junctions.push([e, idx], [f, idx]) + } + + // Sort tjunctions + junctions.sort(function (a, b) { + if (a[0] !== b[0]) { + return a[0] - b[0] + } + var u = ratPoints[a[1]] + var v = ratPoints[b[1]] + return ratCmp(u[0], v[0]) || ratCmp(u[1], v[1]) + }) + + // Split edges along junctions + for (i = junctions.length - 1; i >= 0; --i) { + var junction = junctions[i] + e = junction[0] + + var edge = edges[e] + var s = edge[0] + var t = edge[1] + + // Check if edge is not lexicographically sorted + var a = floatPoints[s] + var b = floatPoints[t] + if (((a[0] - b[0]) || (a[1] - b[1])) < 0) { + var tmp = s + s = t + t = tmp + } + + // Split leading edge + edge[0] = s + var last = edge[1] = junction[1] + + // If we are grouping edges by color, remember to track data + var color + if (useColor) { + color = edge[2] + } + + // Split other edges + while (i > 0 && junctions[i - 1][0] === e) { + var junction = junctions[--i] + var next = junction[1] + if (useColor) { + edges.push([last, next, color]) + } else { + edges.push([last, next]) + } + last = next + } + + // Add final edge + if (useColor) { + edges.push([last, t, color]) + } else { + edges.push([last, t]) + } + } + + // Return constructed rational points + return ratPoints +} + +// Merge overlapping points +function dedupPoints (floatPoints, ratPoints, floatBounds) { + var numPoints = ratPoints.length + var uf = new UnionFind(numPoints) + + // Compute rational bounds + var bounds = [] + for (var i = 0; i < ratPoints.length; ++i) { + var p = ratPoints[i] + var xb = boundRat(p[0]) + var yb = boundRat(p[1]) + bounds.push([ + nextafter(xb[0], -Infinity), + nextafter(yb[0], -Infinity), + nextafter(xb[1], Infinity), + nextafter(yb[1], Infinity) + ]) + } + + // Link all points with over lapping boxes + boxIntersect(bounds, function (i, j) { + uf.link(i, j) + }) + + // Do 1 pass over points to combine points in label sets + var noDupes = true + var labels = new Array(numPoints) + for (var i = 0; i < numPoints; ++i) { + var j = uf.find(i) + if (j !== i) { + // Clear no-dupes flag, zero out label + noDupes = false + // Make each point the top-left point from its cell + floatPoints[j] = [ + Math.min(floatPoints[i][0], floatPoints[j][0]), + Math.min(floatPoints[i][1], floatPoints[j][1]) + ] + } + } + + // If no duplicates, return null to signal termination + if (noDupes) { + return null + } + + var ptr = 0 + for (var i = 0; i < numPoints; ++i) { + var j = uf.find(i) + if (j === i) { + labels[i] = ptr + floatPoints[ptr++] = floatPoints[i] + } else { + labels[i] = -1 + } + } + + floatPoints.length = ptr + + // Do a second pass to fix up missing labels + for (var i = 0; i < numPoints; ++i) { + if (labels[i] < 0) { + labels[i] = labels[uf.find(i)] + } + } + + // Return resulting union-find data structure + return labels +} + +function compareLex2 (a, b) { return (a[0] - b[0]) || (a[1] - b[1]) } +function compareLex3 (a, b) { + var d = (a[0] - b[0]) || (a[1] - b[1]) + if (d) { + return d + } + if (a[2] < b[2]) { + return -1 + } else if (a[2] > b[2]) { + return 1 + } + return 0 +} + +// Remove duplicate edge labels +function dedupEdges (edges, labels, useColor) { + if (edges.length === 0) { + return + } + if (labels) { + for (var i = 0; i < edges.length; ++i) { + var e = edges[i] + var a = labels[e[0]] + var b = labels[e[1]] + e[0] = Math.min(a, b) + e[1] = Math.max(a, b) + } + } else { + for (var i = 0; i < edges.length; ++i) { + var e = edges[i] + var a = e[0] + var b = e[1] + e[0] = Math.min(a, b) + e[1] = Math.max(a, b) + } + } + if (useColor) { + edges.sort(compareLex3) + } else { + edges.sort(compareLex2) + } + var ptr = 1 + for (var i = 1; i < edges.length; ++i) { + var prev = edges[i - 1] + var next = edges[i] + if (next[0] === prev[0] && next[1] === prev[1] && + (!useColor || next[2] === prev[2])) { + continue + } + edges[ptr++] = next + } + edges.length = ptr +} + +function preRound (points, edges, useColor) { + var labels = dedupPoints(points, [], boundPoints(points)) + dedupEdges(edges, labels, useColor) + return !!labels +} + +// Repeat until convergence +function snapRound (points, edges, useColor) { + // 1. find edge crossings + var edgeBounds = boundEdges(points, edges) + var crossings = getCrossings(points, edges, edgeBounds) + + // 2. find t-junctions + var vertBounds = boundPoints(points) + var tjunctions = getTJunctions(points, edges, edgeBounds, vertBounds) + + // 3. cut edges, construct rational points + var ratPoints = cutEdges(points, edges, crossings, tjunctions, useColor) + + // 4. dedupe verts + var labels = dedupPoints(points, ratPoints, vertBounds) + + // 5. dedupe edges + dedupEdges(edges, labels, useColor) + + // 6. check termination + if (!labels) { + return (crossings.length > 0 || tjunctions.length > 0) + } + + // More iterations necessary + return true +} + +// Main loop, runs PSLG clean up until completion +function cleanPSLG (points, edges, colors) { + // If using colors, augment edges with color data + var prevEdges + if (colors) { + prevEdges = edges + var augEdges = new Array(edges.length) + for (var i = 0; i < edges.length; ++i) { + var e = edges[i] + augEdges[i] = [e[0], e[1], colors[i]] + } + edges = augEdges + } + + // First round: remove duplicate edges and points + var modified = preRound(points, edges, !!colors) + + // Run snap rounding until convergence + while (snapRound(points, edges, !!colors)) { + modified = true + } + + // Strip color tags + if (!!colors && modified) { + prevEdges.length = 0 + colors.length = 0 + for (var i = 0; i < edges.length; ++i) { + var e = edges[i] + prevEdges.push([e[0], e[1]]) + colors.push(e[2]) + } + } + + return modified +} + +},{"./lib/rat-seg-intersect":105,"big-rat":66,"big-rat/cmp":64,"big-rat/to-float":78,"box-intersect":84,"nextafter":434,"rat-vec":469,"robust-segment-intersect":489,"union-find":523}],105:[function(_dereq_,module,exports){ +'use strict' + +module.exports = solveIntersection + +var ratMul = _dereq_('big-rat/mul') +var ratDiv = _dereq_('big-rat/div') +var ratSub = _dereq_('big-rat/sub') +var ratSign = _dereq_('big-rat/sign') +var rvSub = _dereq_('rat-vec/sub') +var rvAdd = _dereq_('rat-vec/add') +var rvMuls = _dereq_('rat-vec/muls') + +function ratPerp (a, b) { + return ratSub(ratMul(a[0], b[1]), ratMul(a[1], b[0])) +} + +// Solve for intersection +// x = a + t (b-a) +// (x - c) ^ (d-c) = 0 +// (t * (b-a) + (a-c) ) ^ (d-c) = 0 +// t * (b-a)^(d-c) = (d-c)^(a-c) +// t = (d-c)^(a-c) / (b-a)^(d-c) + +function solveIntersection (a, b, c, d) { + var ba = rvSub(b, a) + var dc = rvSub(d, c) + + var baXdc = ratPerp(ba, dc) + + if (ratSign(baXdc) === 0) { + return null + } + + var ac = rvSub(a, c) + var dcXac = ratPerp(dc, ac) + + var t = ratDiv(dcXac, baXdc) + var s = rvMuls(ba, t) + var r = rvAdd(a, s) + + return r +} + +},{"big-rat/div":65,"big-rat/mul":75,"big-rat/sign":76,"big-rat/sub":77,"rat-vec/add":468,"rat-vec/muls":470,"rat-vec/sub":471}],106:[function(_dereq_,module,exports){ +/** @module color-id */ + +'use strict' + +var clamp = _dereq_('clamp') + +module.exports = toNumber +module.exports.to = toNumber +module.exports.from = fromNumber + +function toNumber (rgba, normalized) { + if(normalized == null) normalized = true + + var r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3] + + if (a == null) a = normalized ? 1 : 255 + + if (normalized) { + r *= 255 + g *= 255 + b *= 255 + a *= 255 + } + + r = clamp(r, 0, 255) & 0xFF + g = clamp(g, 0, 255) & 0xFF + b = clamp(b, 0, 255) & 0xFF + a = clamp(a, 0, 255) & 0xFF + + //hi-order shift converts to -1, so we can't use <<24 + var n = (r * 0x01000000) + (g << 16) + (b << 8) + (a) + + return n +} + +function fromNumber (n, normalized) { + n = +n + + var r = n >>> 24 + var g = (n & 0x00ff0000) >>> 16 + var b = (n & 0x0000ff00) >>> 8 + var a = n & 0x000000ff + + if (normalized === false) return [r, g, b, a] + + return [r/255, g/255, b/255, a/255] +} + +},{"clamp":103}],107:[function(_dereq_,module,exports){ +'use strict' + +module.exports = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + +},{}],108:[function(_dereq_,module,exports){ +/** @module color-normalize */ + +'use strict' + +var rgba = _dereq_('color-rgba') +var clamp = _dereq_('clamp') +var dtype = _dereq_('dtype') + +module.exports = function normalize (color, type) { + if (type === 'float' || !type) type = 'array' + if (type === 'uint') type = 'uint8' + if (type === 'uint_clamped') type = 'uint8_clamped' + var Ctor = dtype(type) + var output = new Ctor(4) + + var normalize = type !== 'uint8' && type !== 'uint8_clamped' + + // attempt to parse non-array arguments + if (!color.length || typeof color === 'string') { + color = rgba(color) + color[0] /= 255 + color[1] /= 255 + color[2] /= 255 + } + + // 0, 1 are possible contradictory values for Arrays: + // [1,1,1] input gives [1,1,1] output instead of [1/255,1/255,1/255], which may be collision if input is meant to be uint. + // converting [1,1,1] to [1/255,1/255,1/255] in case of float input gives larger mistake since [1,1,1] float is frequent edge value, whereas [0,1,1], [1,1,1] etc. uint inputs are relatively rare + if (isInt(color)) { + output[0] = color[0] + output[1] = color[1] + output[2] = color[2] + output[3] = color[3] != null ? color[3] : 255 + + if (normalize) { + output[0] /= 255 + output[1] /= 255 + output[2] /= 255 + output[3] /= 255 + } + + return output + } + + if (!normalize) { + output[0] = clamp(Math.floor(color[0] * 255), 0, 255) + output[1] = clamp(Math.floor(color[1] * 255), 0, 255) + output[2] = clamp(Math.floor(color[2] * 255), 0, 255) + output[3] = color[3] == null ? 255 : clamp(Math.floor(color[3] * 255), 0, 255) + } else { + output[0] = color[0] + output[1] = color[1] + output[2] = color[2] + output[3] = color[3] != null ? color[3] : 1 + } + + return output +} + +function isInt(color) { + if (color instanceof Uint8Array || color instanceof Uint8ClampedArray) return true + + if (Array.isArray(color) && + (color[0] > 1 || color[0] === 0) && + (color[1] > 1 || color[1] === 0) && + (color[2] > 1 || color[2] === 0) && + (!color[3] || color[3] > 1) + ) return true + + return false +} + +},{"clamp":103,"color-rgba":110,"dtype":154}],109:[function(_dereq_,module,exports){ +(function (global){ +/** + * @module color-parse + */ + +'use strict' + +var names = _dereq_('color-name') +var isObject = _dereq_('is-plain-obj') +var defined = _dereq_('defined') + +module.exports = parse + +/** + * Base hues + * http://dev.w3.org/csswg/css-color/#typedef-named-hue + */ +//FIXME: use external hue detector +var baseHues = { + red: 0, + orange: 60, + yellow: 120, + green: 180, + blue: 240, + purple: 300 +} + +/** + * Parse color from the string passed + * + * @return {Object} A space indicator `space`, an array `values` and `alpha` + */ +function parse (cstr) { + var m, parts = [], alpha = 1, space + + if (typeof cstr === 'string') { + //keyword + if (names[cstr]) { + parts = names[cstr].slice() + space = 'rgb' + } + + //reserved words + else if (cstr === 'transparent') { + alpha = 0 + space = 'rgb' + parts = [0,0,0] + } + + //hex + else if (/^#[A-Fa-f0-9]+$/.test(cstr)) { + var base = cstr.slice(1) + var size = base.length + var isShort = size <= 4 + alpha = 1 + + if (isShort) { + parts = [ + parseInt(base[0] + base[0], 16), + parseInt(base[1] + base[1], 16), + parseInt(base[2] + base[2], 16) + ] + if (size === 4) { + alpha = parseInt(base[3] + base[3], 16) / 255 + } + } + else { + parts = [ + parseInt(base[0] + base[1], 16), + parseInt(base[2] + base[3], 16), + parseInt(base[4] + base[5], 16) + ] + if (size === 8) { + alpha = parseInt(base[6] + base[7], 16) / 255 + } + } + + if (!parts[0]) parts[0] = 0 + if (!parts[1]) parts[1] = 0 + if (!parts[2]) parts[2] = 0 + + space = 'rgb' + } + + //color space + else if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\s*\(([^\)]*)\)/.exec(cstr)) { + var name = m[1] + var base = name.replace(/a$/, '') + space = base + var size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3 + parts = m[2].trim() + .split(/\s*,\s*/) + .map(function (x, i) { + // + if (/%$/.test(x)) { + //alpha + if (i === size) return parseFloat(x) / 100 + //rgb + if (base === 'rgb') return parseFloat(x) * 255 / 100 + return parseFloat(x) + } + //hue + else if (base[i] === 'h') { + // + if (/deg$/.test(x)) { + return parseFloat(x) + } + // + else if (baseHues[x] !== undefined) { + return baseHues[x] + } + } + return parseFloat(x) + }) + + if (name === base) parts.push(1) + alpha = parts[size] === undefined ? 1 : parts[size] + parts = parts.slice(0, size) + } + + //named channels case + else if (cstr.length > 10 && /[0-9](?:\s|\/)/.test(cstr)) { + parts = cstr.match(/([0-9]+)/g).map(function (value) { + return parseFloat(value) + }) + + space = cstr.match(/([a-z])/ig).join('').toLowerCase() + } + } + + //numeric case + else if (!isNaN(cstr)) { + space = 'rgb' + parts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff] + } + + //object case - detects css cases of rgb and hsl + else if (isObject(cstr)) { + var r = defined(cstr.r, cstr.red, cstr.R, null) + + if (r !== null) { + space = 'rgb' + parts = [ + r, + defined(cstr.g, cstr.green, cstr.G), + defined(cstr.b, cstr.blue, cstr.B) + ] + } + else { + space = 'hsl' + parts = [ + defined(cstr.h, cstr.hue, cstr.H), + defined(cstr.s, cstr.saturation, cstr.S), + defined(cstr.l, cstr.lightness, cstr.L, cstr.b, cstr.brightness) + ] + } + + alpha = defined(cstr.a, cstr.alpha, cstr.opacity, 1) + + if (cstr.opacity != null) alpha /= 100 + } + + //array + else if (Array.isArray(cstr) || global.ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(cstr)) { + parts = [cstr[0], cstr[1], cstr[2]] + space = 'rgb' + alpha = cstr.length === 4 ? cstr[3] : 1 + } + + return { + space: space, + values: parts, + alpha: alpha + } +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"color-name":107,"defined":149,"is-plain-obj":405}],110:[function(_dereq_,module,exports){ +/** @module color-rgba */ + +'use strict' + +var parse = _dereq_('color-parse') +var hsl = _dereq_('color-space/hsl') +var clamp = _dereq_('clamp') + +module.exports = function rgba (color) { + var values, i, l + + //attempt to parse non-array arguments + var parsed = parse(color) + + if (!parsed.space) return [] + + values = Array(3) + values[0] = clamp(parsed.values[0], 0, 255) + values[1] = clamp(parsed.values[1], 0, 255) + values[2] = clamp(parsed.values[2], 0, 255) + + if (parsed.space[0] === 'h') { + values = hsl.rgb(values) + } + + values.push(clamp(parsed.alpha, 0, 1)) + + return values +} + +},{"clamp":103,"color-parse":109,"color-space/hsl":111}],111:[function(_dereq_,module,exports){ +/** + * @module color-space/hsl + */ +'use strict' + +var rgb = _dereq_('./rgb'); + +module.exports = { + name: 'hsl', + min: [0,0,0], + max: [360,100,100], + channel: ['hue', 'saturation', 'lightness'], + alias: ['HSL'], + + rgb: function(hsl) { + var h = hsl[0] / 360, + s = hsl[1] / 100, + l = hsl[2] / 100, + t1, t2, t3, rgb, val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } + else { + t2 = l + s - l * s; + } + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * - (i - 1); + if (t3 < 0) { + t3++; + } + else if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } + else if (2 * t3 < 1) { + val = t2; + } + else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } + else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; + } +}; + + +//extend rgb +rgb.hsl = function(rgb) { + var r = rgb[0]/255, + g = rgb[1]/255, + b = rgb[2]/255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h, s, l; + + if (max === min) { + h = 0; + } + else if (r === max) { + h = (g - b) / delta; + } + else if (g === max) { + h = 2 + (b - r) / delta; + } + else if (b === max) { + h = 4 + (r - g)/ delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + l = (min + max) / 2; + + if (max === min) { + s = 0; + } + else if (l <= 0.5) { + s = delta / (max + min); + } + else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +},{"./rgb":112}],112:[function(_dereq_,module,exports){ +/** + * RGB space. + * + * @module color-space/rgb + */ +'use strict' + +module.exports = { + name: 'rgb', + min: [0,0,0], + max: [255,255,255], + channel: ['red', 'green', 'blue'], + alias: ['RGB'] +}; + +},{}],113:[function(_dereq_,module,exports){ +module.exports={ + "jet":[{"index":0,"rgb":[0,0,131]},{"index":0.125,"rgb":[0,60,170]},{"index":0.375,"rgb":[5,255,255]},{"index":0.625,"rgb":[255,255,0]},{"index":0.875,"rgb":[250,0,0]},{"index":1,"rgb":[128,0,0]}], + + "hsv":[{"index":0,"rgb":[255,0,0]},{"index":0.169,"rgb":[253,255,2]},{"index":0.173,"rgb":[247,255,2]},{"index":0.337,"rgb":[0,252,4]},{"index":0.341,"rgb":[0,252,10]},{"index":0.506,"rgb":[1,249,255]},{"index":0.671,"rgb":[2,0,253]},{"index":0.675,"rgb":[8,0,253]},{"index":0.839,"rgb":[255,0,251]},{"index":0.843,"rgb":[255,0,245]},{"index":1,"rgb":[255,0,6]}], + + "hot":[{"index":0,"rgb":[0,0,0]},{"index":0.3,"rgb":[230,0,0]},{"index":0.6,"rgb":[255,210,0]},{"index":1,"rgb":[255,255,255]}], + + "cool":[{"index":0,"rgb":[0,255,255]},{"index":1,"rgb":[255,0,255]}], + + "spring":[{"index":0,"rgb":[255,0,255]},{"index":1,"rgb":[255,255,0]}], + + "summer":[{"index":0,"rgb":[0,128,102]},{"index":1,"rgb":[255,255,102]}], + + "autumn":[{"index":0,"rgb":[255,0,0]},{"index":1,"rgb":[255,255,0]}], + + "winter":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[0,255,128]}], + + "bone":[{"index":0,"rgb":[0,0,0]},{"index":0.376,"rgb":[84,84,116]},{"index":0.753,"rgb":[169,200,200]},{"index":1,"rgb":[255,255,255]}], + + "copper":[{"index":0,"rgb":[0,0,0]},{"index":0.804,"rgb":[255,160,102]},{"index":1,"rgb":[255,199,127]}], + + "greys":[{"index":0,"rgb":[0,0,0]},{"index":1,"rgb":[255,255,255]}], + + "yignbu":[{"index":0,"rgb":[8,29,88]},{"index":0.125,"rgb":[37,52,148]},{"index":0.25,"rgb":[34,94,168]},{"index":0.375,"rgb":[29,145,192]},{"index":0.5,"rgb":[65,182,196]},{"index":0.625,"rgb":[127,205,187]},{"index":0.75,"rgb":[199,233,180]},{"index":0.875,"rgb":[237,248,217]},{"index":1,"rgb":[255,255,217]}], + + "greens":[{"index":0,"rgb":[0,68,27]},{"index":0.125,"rgb":[0,109,44]},{"index":0.25,"rgb":[35,139,69]},{"index":0.375,"rgb":[65,171,93]},{"index":0.5,"rgb":[116,196,118]},{"index":0.625,"rgb":[161,217,155]},{"index":0.75,"rgb":[199,233,192]},{"index":0.875,"rgb":[229,245,224]},{"index":1,"rgb":[247,252,245]}], + + "yiorrd":[{"index":0,"rgb":[128,0,38]},{"index":0.125,"rgb":[189,0,38]},{"index":0.25,"rgb":[227,26,28]},{"index":0.375,"rgb":[252,78,42]},{"index":0.5,"rgb":[253,141,60]},{"index":0.625,"rgb":[254,178,76]},{"index":0.75,"rgb":[254,217,118]},{"index":0.875,"rgb":[255,237,160]},{"index":1,"rgb":[255,255,204]}], + + "bluered":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[255,0,0]}], + + "rdbu":[{"index":0,"rgb":[5,10,172]},{"index":0.35,"rgb":[106,137,247]},{"index":0.5,"rgb":[190,190,190]},{"index":0.6,"rgb":[220,170,132]},{"index":0.7,"rgb":[230,145,90]},{"index":1,"rgb":[178,10,28]}], + + "picnic":[{"index":0,"rgb":[0,0,255]},{"index":0.1,"rgb":[51,153,255]},{"index":0.2,"rgb":[102,204,255]},{"index":0.3,"rgb":[153,204,255]},{"index":0.4,"rgb":[204,204,255]},{"index":0.5,"rgb":[255,255,255]},{"index":0.6,"rgb":[255,204,255]},{"index":0.7,"rgb":[255,153,255]},{"index":0.8,"rgb":[255,102,204]},{"index":0.9,"rgb":[255,102,102]},{"index":1,"rgb":[255,0,0]}], + + "rainbow":[{"index":0,"rgb":[150,0,90]},{"index":0.125,"rgb":[0,0,200]},{"index":0.25,"rgb":[0,25,255]},{"index":0.375,"rgb":[0,152,255]},{"index":0.5,"rgb":[44,255,150]},{"index":0.625,"rgb":[151,255,0]},{"index":0.75,"rgb":[255,234,0]},{"index":0.875,"rgb":[255,111,0]},{"index":1,"rgb":[255,0,0]}], + + "portland":[{"index":0,"rgb":[12,51,131]},{"index":0.25,"rgb":[10,136,186]},{"index":0.5,"rgb":[242,211,56]},{"index":0.75,"rgb":[242,143,56]},{"index":1,"rgb":[217,30,30]}], + + "blackbody":[{"index":0,"rgb":[0,0,0]},{"index":0.2,"rgb":[230,0,0]},{"index":0.4,"rgb":[230,210,0]},{"index":0.7,"rgb":[255,255,255]},{"index":1,"rgb":[160,200,255]}], + + "earth":[{"index":0,"rgb":[0,0,130]},{"index":0.1,"rgb":[0,180,180]},{"index":0.2,"rgb":[40,210,40]},{"index":0.4,"rgb":[230,230,50]},{"index":0.6,"rgb":[120,70,20]},{"index":1,"rgb":[255,255,255]}], + + "electric":[{"index":0,"rgb":[0,0,0]},{"index":0.15,"rgb":[30,0,100]},{"index":0.4,"rgb":[120,0,100]},{"index":0.6,"rgb":[160,90,0]},{"index":0.8,"rgb":[230,200,0]},{"index":1,"rgb":[255,250,220]}], + + "alpha": [{"index":0, "rgb": [255,255,255,0]},{"index":1, "rgb": [255,255,255,1]}], + + "viridis": [{"index":0,"rgb":[68,1,84]},{"index":0.13,"rgb":[71,44,122]},{"index":0.25,"rgb":[59,81,139]},{"index":0.38,"rgb":[44,113,142]},{"index":0.5,"rgb":[33,144,141]},{"index":0.63,"rgb":[39,173,129]},{"index":0.75,"rgb":[92,200,99]},{"index":0.88,"rgb":[170,220,50]},{"index":1,"rgb":[253,231,37]}], + + "inferno": [{"index":0,"rgb":[0,0,4]},{"index":0.13,"rgb":[31,12,72]},{"index":0.25,"rgb":[85,15,109]},{"index":0.38,"rgb":[136,34,106]},{"index":0.5,"rgb":[186,54,85]},{"index":0.63,"rgb":[227,89,51]},{"index":0.75,"rgb":[249,140,10]},{"index":0.88,"rgb":[249,201,50]},{"index":1,"rgb":[252,255,164]}], + + "magma": [{"index":0,"rgb":[0,0,4]},{"index":0.13,"rgb":[28,16,68]},{"index":0.25,"rgb":[79,18,123]},{"index":0.38,"rgb":[129,37,129]},{"index":0.5,"rgb":[181,54,122]},{"index":0.63,"rgb":[229,80,100]},{"index":0.75,"rgb":[251,135,97]},{"index":0.88,"rgb":[254,194,135]},{"index":1,"rgb":[252,253,191]}], + + "plasma": [{"index":0,"rgb":[13,8,135]},{"index":0.13,"rgb":[75,3,161]},{"index":0.25,"rgb":[125,3,168]},{"index":0.38,"rgb":[168,34,150]},{"index":0.5,"rgb":[203,70,121]},{"index":0.63,"rgb":[229,107,93]},{"index":0.75,"rgb":[248,148,65]},{"index":0.88,"rgb":[253,195,40]},{"index":1,"rgb":[240,249,33]}], + + "warm": [{"index":0,"rgb":[125,0,179]},{"index":0.13,"rgb":[172,0,187]},{"index":0.25,"rgb":[219,0,170]},{"index":0.38,"rgb":[255,0,130]},{"index":0.5,"rgb":[255,63,74]},{"index":0.63,"rgb":[255,123,0]},{"index":0.75,"rgb":[234,176,0]},{"index":0.88,"rgb":[190,228,0]},{"index":1,"rgb":[147,255,0]}], + + "cool": [{"index":0,"rgb":[125,0,179]},{"index":0.13,"rgb":[116,0,218]},{"index":0.25,"rgb":[98,74,237]},{"index":0.38,"rgb":[68,146,231]},{"index":0.5,"rgb":[0,204,197]},{"index":0.63,"rgb":[0,247,146]},{"index":0.75,"rgb":[0,255,88]},{"index":0.88,"rgb":[40,255,8]},{"index":1,"rgb":[147,255,0]}], + + "rainbow-soft": [{"index":0,"rgb":[125,0,179]},{"index":0.1,"rgb":[199,0,180]},{"index":0.2,"rgb":[255,0,121]},{"index":0.3,"rgb":[255,108,0]},{"index":0.4,"rgb":[222,194,0]},{"index":0.5,"rgb":[150,255,0]},{"index":0.6,"rgb":[0,255,55]},{"index":0.7,"rgb":[0,246,150]},{"index":0.8,"rgb":[50,167,222]},{"index":0.9,"rgb":[103,51,235]},{"index":1,"rgb":[124,0,186]}], + + "bathymetry": [{"index":0,"rgb":[40,26,44]},{"index":0.13,"rgb":[59,49,90]},{"index":0.25,"rgb":[64,76,139]},{"index":0.38,"rgb":[63,110,151]},{"index":0.5,"rgb":[72,142,158]},{"index":0.63,"rgb":[85,174,163]},{"index":0.75,"rgb":[120,206,163]},{"index":0.88,"rgb":[187,230,172]},{"index":1,"rgb":[253,254,204]}], + + "cdom": [{"index":0,"rgb":[47,15,62]},{"index":0.13,"rgb":[87,23,86]},{"index":0.25,"rgb":[130,28,99]},{"index":0.38,"rgb":[171,41,96]},{"index":0.5,"rgb":[206,67,86]},{"index":0.63,"rgb":[230,106,84]},{"index":0.75,"rgb":[242,149,103]},{"index":0.88,"rgb":[249,193,135]},{"index":1,"rgb":[254,237,176]}], + + "chlorophyll": [{"index":0,"rgb":[18,36,20]},{"index":0.13,"rgb":[25,63,41]},{"index":0.25,"rgb":[24,91,59]},{"index":0.38,"rgb":[13,119,72]},{"index":0.5,"rgb":[18,148,80]},{"index":0.63,"rgb":[80,173,89]},{"index":0.75,"rgb":[132,196,122]},{"index":0.88,"rgb":[175,221,162]},{"index":1,"rgb":[215,249,208]}], + + "density": [{"index":0,"rgb":[54,14,36]},{"index":0.13,"rgb":[89,23,80]},{"index":0.25,"rgb":[110,45,132]},{"index":0.38,"rgb":[120,77,178]},{"index":0.5,"rgb":[120,113,213]},{"index":0.63,"rgb":[115,151,228]},{"index":0.75,"rgb":[134,185,227]},{"index":0.88,"rgb":[177,214,227]},{"index":1,"rgb":[230,241,241]}], + + "freesurface-blue": [{"index":0,"rgb":[30,4,110]},{"index":0.13,"rgb":[47,14,176]},{"index":0.25,"rgb":[41,45,236]},{"index":0.38,"rgb":[25,99,212]},{"index":0.5,"rgb":[68,131,200]},{"index":0.63,"rgb":[114,156,197]},{"index":0.75,"rgb":[157,181,203]},{"index":0.88,"rgb":[200,208,216]},{"index":1,"rgb":[241,237,236]}], + + "freesurface-red": [{"index":0,"rgb":[60,9,18]},{"index":0.13,"rgb":[100,17,27]},{"index":0.25,"rgb":[142,20,29]},{"index":0.38,"rgb":[177,43,27]},{"index":0.5,"rgb":[192,87,63]},{"index":0.63,"rgb":[205,125,105]},{"index":0.75,"rgb":[216,162,148]},{"index":0.88,"rgb":[227,199,193]},{"index":1,"rgb":[241,237,236]}], + + "oxygen": [{"index":0,"rgb":[64,5,5]},{"index":0.13,"rgb":[106,6,15]},{"index":0.25,"rgb":[144,26,7]},{"index":0.38,"rgb":[168,64,3]},{"index":0.5,"rgb":[188,100,4]},{"index":0.63,"rgb":[206,136,11]},{"index":0.75,"rgb":[220,174,25]},{"index":0.88,"rgb":[231,215,44]},{"index":1,"rgb":[248,254,105]}], + + "par": [{"index":0,"rgb":[51,20,24]},{"index":0.13,"rgb":[90,32,35]},{"index":0.25,"rgb":[129,44,34]},{"index":0.38,"rgb":[159,68,25]},{"index":0.5,"rgb":[182,99,19]},{"index":0.63,"rgb":[199,134,22]},{"index":0.75,"rgb":[212,171,35]},{"index":0.88,"rgb":[221,210,54]},{"index":1,"rgb":[225,253,75]}], + + "phase": [{"index":0,"rgb":[145,105,18]},{"index":0.13,"rgb":[184,71,38]},{"index":0.25,"rgb":[186,58,115]},{"index":0.38,"rgb":[160,71,185]},{"index":0.5,"rgb":[110,97,218]},{"index":0.63,"rgb":[50,123,164]},{"index":0.75,"rgb":[31,131,110]},{"index":0.88,"rgb":[77,129,34]},{"index":1,"rgb":[145,105,18]}], + + "salinity": [{"index":0,"rgb":[42,24,108]},{"index":0.13,"rgb":[33,50,162]},{"index":0.25,"rgb":[15,90,145]},{"index":0.38,"rgb":[40,118,137]},{"index":0.5,"rgb":[59,146,135]},{"index":0.63,"rgb":[79,175,126]},{"index":0.75,"rgb":[120,203,104]},{"index":0.88,"rgb":[193,221,100]},{"index":1,"rgb":[253,239,154]}], + + "temperature": [{"index":0,"rgb":[4,35,51]},{"index":0.13,"rgb":[23,51,122]},{"index":0.25,"rgb":[85,59,157]},{"index":0.38,"rgb":[129,79,143]},{"index":0.5,"rgb":[175,95,130]},{"index":0.63,"rgb":[222,112,101]},{"index":0.75,"rgb":[249,146,66]},{"index":0.88,"rgb":[249,196,65]},{"index":1,"rgb":[232,250,91]}], + + "turbidity": [{"index":0,"rgb":[34,31,27]},{"index":0.13,"rgb":[65,50,41]},{"index":0.25,"rgb":[98,69,52]},{"index":0.38,"rgb":[131,89,57]},{"index":0.5,"rgb":[161,112,59]},{"index":0.63,"rgb":[185,140,66]},{"index":0.75,"rgb":[202,174,88]},{"index":0.88,"rgb":[216,209,126]},{"index":1,"rgb":[233,246,171]}], + + "velocity-blue": [{"index":0,"rgb":[17,32,64]},{"index":0.13,"rgb":[35,52,116]},{"index":0.25,"rgb":[29,81,156]},{"index":0.38,"rgb":[31,113,162]},{"index":0.5,"rgb":[50,144,169]},{"index":0.63,"rgb":[87,173,176]},{"index":0.75,"rgb":[149,196,189]},{"index":0.88,"rgb":[203,221,211]},{"index":1,"rgb":[254,251,230]}], + + "velocity-green": [{"index":0,"rgb":[23,35,19]},{"index":0.13,"rgb":[24,64,38]},{"index":0.25,"rgb":[11,95,45]},{"index":0.38,"rgb":[39,123,35]},{"index":0.5,"rgb":[95,146,12]},{"index":0.63,"rgb":[152,165,18]},{"index":0.75,"rgb":[201,186,69]},{"index":0.88,"rgb":[233,216,137]},{"index":1,"rgb":[255,253,205]}], + + "cubehelix": [{"index":0,"rgb":[0,0,0]},{"index":0.07,"rgb":[22,5,59]},{"index":0.13,"rgb":[60,4,105]},{"index":0.2,"rgb":[109,1,135]},{"index":0.27,"rgb":[161,0,147]},{"index":0.33,"rgb":[210,2,142]},{"index":0.4,"rgb":[251,11,123]},{"index":0.47,"rgb":[255,29,97]},{"index":0.53,"rgb":[255,54,69]},{"index":0.6,"rgb":[255,85,46]},{"index":0.67,"rgb":[255,120,34]},{"index":0.73,"rgb":[255,157,37]},{"index":0.8,"rgb":[241,191,57]},{"index":0.87,"rgb":[224,220,93]},{"index":0.93,"rgb":[218,241,142]},{"index":1,"rgb":[227,253,198]}] +}; + +},{}],114:[function(_dereq_,module,exports){ +/* + * Ben Postlethwaite + * January 2013 + * License MIT + */ +'use strict'; + +var colorScale = _dereq_('./colorScale'); +var lerp = _dereq_('lerp') + +module.exports = createColormap; + +function createColormap (spec) { + /* + * Default Options + */ + var indicies, rgba, fromrgba, torgba, + nsteps, cmap, colormap, format, + nshades, colors, alpha, index, i, + r = [], + g = [], + b = [], + a = []; + + if ( !spec ) spec = {}; + + nshades = (spec.nshades || 72) - 1; + format = spec.format || 'hex'; + + colormap = spec.colormap; + if (!colormap) colormap = 'jet'; + + if (typeof colormap === 'string') { + colormap = colormap.toLowerCase(); + + if (!colorScale[colormap]) { + throw Error(colormap + ' not a supported colorscale'); + } + + cmap = colorScale[colormap]; + + } else if (Array.isArray(colormap)) { + cmap = colormap.slice(); + + } else { + throw Error('unsupported colormap option', colormap); + } + + if (cmap.length > nshades) { + throw new Error( + colormap+' map requires nshades to be at least size '+cmap.length + ); + } + + if (!Array.isArray(spec.alpha)) { + + if (typeof spec.alpha === 'number') { + alpha = [spec.alpha, spec.alpha]; + + } else { + alpha = [1, 1]; + } + + } else if (spec.alpha.length !== 2) { + alpha = [1, 1]; + + } else { + alpha = spec.alpha.slice(); + } + + // map index points from 0..1 to 0..n-1 + indicies = cmap.map(function(c) { + return Math.round(c.index * nshades); + }); + + // Add alpha channel to the map + alpha[0] = Math.min(Math.max(alpha[0], 0), 1); + alpha[1] = Math.min(Math.max(alpha[1], 0), 1); + + var steps = cmap.map(function(c, i) { + var index = cmap[i].index + + var rgba = cmap[i].rgb.slice(); + + // if user supplies their own map use it + if (rgba.length === 4 && rgba[3] >= 0 && rgba[3] <= 1) { + return rgba + } + rgba[3] = alpha[0] + (alpha[1] - alpha[0])*index; + + return rgba + }) + + + /* + * map increasing linear values between indicies to + * linear steps in colorvalues + */ + var colors = [] + for (i = 0; i < indicies.length-1; ++i) { + nsteps = indicies[i+1] - indicies[i]; + fromrgba = steps[i]; + torgba = steps[i+1]; + + for (var j = 0; j < nsteps; j++) { + var amt = j / nsteps + colors.push([ + Math.round(lerp(fromrgba[0], torgba[0], amt)), + Math.round(lerp(fromrgba[1], torgba[1], amt)), + Math.round(lerp(fromrgba[2], torgba[2], amt)), + lerp(fromrgba[3], torgba[3], amt) + ]) + } + } + + //add 1 step as last value + colors.push(cmap[cmap.length - 1].rgb.concat(alpha[1])) + + if (format === 'hex') colors = colors.map( rgb2hex ); + else if (format === 'rgbaString') colors = colors.map( rgbaStr ); + else if (format === 'float') colors = colors.map( rgb2float ); + + return colors; +}; + +function rgb2float (rgba) { + return [ + rgba[0] / 255, + rgba[1] / 255, + rgba[2] / 255, + rgba[3] + ] +} + +function rgb2hex (rgba) { + var dig, hex = '#'; + for (var i = 0; i < 3; ++i) { + dig = rgba[i]; + dig = dig.toString(16); + hex += ('00' + dig).substr( dig.length ); + } + return hex; +} + +function rgbaStr (rgba) { + return 'rgba(' + rgba.join(',') + ')'; +} + +},{"./colorScale":113,"lerp":408}],115:[function(_dereq_,module,exports){ +"use strict" + +module.exports = compareAngle + +var orient = _dereq_("robust-orientation") +var sgn = _dereq_("signum") +var twoSum = _dereq_("two-sum") +var robustProduct = _dereq_("robust-product") +var robustSum = _dereq_("robust-sum") + +function testInterior(a, b, c) { + var x0 = twoSum(a[0], -b[0]) + var y0 = twoSum(a[1], -b[1]) + var x1 = twoSum(c[0], -b[0]) + var y1 = twoSum(c[1], -b[1]) + + var d = robustSum( + robustProduct(x0, x1), + robustProduct(y0, y1)) + + return d[d.length-1] >= 0 +} + +function compareAngle(a, b, c, d) { + var bcd = orient(b, c, d) + if(bcd === 0) { + //Handle degenerate cases + var sabc = sgn(orient(a, b, c)) + var sabd = sgn(orient(a, b, d)) + if(sabc === sabd) { + if(sabc === 0) { + var ic = testInterior(a, b, c) + var id = testInterior(a, b, d) + if(ic === id) { + return 0 + } else if(ic) { + return 1 + } else { + return -1 + } + } + return 0 + } else if(sabd === 0) { + if(sabc > 0) { + return -1 + } else if(testInterior(a, b, d)) { + return -1 + } else { + return 1 + } + } else if(sabc === 0) { + if(sabd > 0) { + return 1 + } else if(testInterior(a, b, c)) { + return 1 + } else { + return -1 + } + } + return sgn(sabd - sabc) + } + var abc = orient(a, b, c) + if(abc > 0) { + if(bcd > 0 && orient(a, b, d) > 0) { + return 1 + } + return -1 + } else if(abc < 0) { + if(bcd > 0 || orient(a, b, d) > 0) { + return 1 + } + return -1 + } else { + var abd = orient(a, b, d) + if(abd > 0) { + return 1 + } else { + if(testInterior(a, b, c)) { + return 1 + } else { + return -1 + } + } + } +} +},{"robust-orientation":486,"robust-product":487,"robust-sum":491,"signum":492,"two-sum":521}],116:[function(_dereq_,module,exports){ +module.exports = compareCells + +var min = Math.min + +function compareInt(a, b) { + return a - b +} + +function compareCells(a, b) { + var n = a.length + , t = a.length - b.length + if(t) { + return t + } + switch(n) { + case 0: + return 0 + case 1: + return a[0] - b[0] + case 2: + return (a[0]+a[1]-b[0]-b[1]) || + min(a[0],a[1]) - min(b[0],b[1]) + case 3: + var l1 = a[0]+a[1] + , m1 = b[0]+b[1] + t = l1+a[2] - (m1+b[2]) + if(t) { + return t + } + var l0 = min(a[0], a[1]) + , m0 = min(b[0], b[1]) + return min(l0, a[2]) - min(m0, b[2]) || + min(l0+a[2], l1) - min(m0+b[2], m1) + case 4: + var aw=a[0], ax=a[1], ay=a[2], az=a[3] + , bw=b[0], bx=b[1], by=b[2], bz=b[3] + return (aw+ax+ay+az)-(bw+bx+by+bz) || + min(aw,ax,ay,az)-min(bw,bx,by,bz,bw) || + min(aw+ax,aw+ay,aw+az,ax+ay,ax+az,ay+az) - + min(bw+bx,bw+by,bw+bz,bx+by,bx+bz,by+bz) || + min(aw+ax+ay,aw+ax+az,aw+ay+az,ax+ay+az) - + min(bw+bx+by,bw+bx+bz,bw+by+bz,bx+by+bz) + default: + var as = a.slice().sort(compareInt) + var bs = b.slice().sort(compareInt) + for(var i=0; i points[hi][0]) { + hi = i + } + } + if(lo < hi) { + return [[lo], [hi]] + } else if(lo > hi) { + return [[hi], [lo]] + } else { + return [[lo]] + } +} +},{}],120:[function(_dereq_,module,exports){ +'use strict' + +module.exports = convexHull2D + +var monotoneHull = _dereq_('monotone-convex-hull-2d') + +function convexHull2D(points) { + var hull = monotoneHull(points) + var h = hull.length + if(h <= 2) { + return [] + } + var edges = new Array(h) + var a = hull[h-1] + for(var i=0; i= front[k]) { + x += 1 + } + } + c[j] = x + } + } + } + return cells +} + +function convexHullnD(points, d) { + try { + return ich(points, true) + } catch(e) { + //If point set is degenerate, try to find a basis and rerun it + var ah = aff(points) + if(ah.length <= d) { + //No basis, no try + return [] + } + var npoints = permute(points, ah) + var nhull = ich(npoints, true) + return invPermute(nhull, ah) + } +} +},{"affine-hull":50,"incremental-convex-hull":396}],122:[function(_dereq_,module,exports){ +module.exports = { + AFG: 'afghan', + ALA: '\\b\\wland', + ALB: 'albania', + DZA: 'algeria', + ASM: '^(?=.*americ).*samoa', + AND: 'andorra', + AGO: 'angola', + AIA: 'anguill?a', + ATA: 'antarctica', + ATG: 'antigua', + ARG: 'argentin', + ARM: 'armenia', + ABW: '^(?!.*bonaire).*\\baruba', + AUS: 'australia', + AUT: '^(?!.*hungary).*austria|\\baustri.*\\bemp', + AZE: 'azerbaijan', + BHS: 'bahamas', + BHR: 'bahrain', + BGD: 'bangladesh|^(?=.*east).*paki?stan', + BRB: 'barbados', + BLR: 'belarus|byelo', + BEL: '^(?!.*luxem).*belgium', + BLZ: 'belize|^(?=.*british).*honduras', + BEN: 'benin|dahome', + BMU: 'bermuda', + BTN: 'bhutan', + BOL: 'bolivia', + BES: '^(?=.*bonaire).*eustatius|^(?=.*carib).*netherlands|\\bbes.?islands', + BIH: 'herzegovina|bosnia', + BWA: 'botswana|bechuana', + BVT: 'bouvet', + BRA: 'brazil', + IOT: 'british.?indian.?ocean', + BRN: 'brunei', + BGR: 'bulgaria', + BFA: 'burkina|\\bfaso|upper.?volta', + BDI: 'burundi', + CPV: 'verde', + KHM: 'cambodia|kampuchea|khmer', + CMR: 'cameroon', + CAN: 'canada', + CYM: 'cayman', + CAF: '\\bcentral.african.republic', + TCD: '\\bchad', + CHL: '\\bchile', + CHN: '^(?!.*\\bmac)(?!.*\\bhong)(?!.*\\btai)(?!.*\\brep).*china|^(?=.*peo)(?=.*rep).*china', + CXR: 'christmas', + CCK: '\\bcocos|keeling', + COL: 'colombia', + COM: 'comoro', + COG: '^(?!.*\\bdem)(?!.*\\bd[\\.]?r)(?!.*kinshasa)(?!.*zaire)(?!.*belg)(?!.*l.opoldville)(?!.*free).*\\bcongo', + COK: '\\bcook', + CRI: 'costa.?rica', + CIV: 'ivoire|ivory', + HRV: 'croatia', + CUB: '\\bcuba', + CUW: '^(?!.*bonaire).*\\bcura(c|ç)ao', + CYP: 'cyprus', + CSK: 'czechoslovakia', + CZE: '^(?=.*rep).*czech|czechia|bohemia', + COD: '\\bdem.*congo|congo.*\\bdem|congo.*\\bd[\\.]?r|\\bd[\\.]?r.*congo|belgian.?congo|congo.?free.?state|kinshasa|zaire|l.opoldville|drc|droc|rdc', + DNK: 'denmark', + DJI: 'djibouti', + DMA: 'dominica(?!n)', + DOM: 'dominican.rep', + ECU: 'ecuador', + EGY: 'egypt', + SLV: 'el.?salvador', + GNQ: 'guine.*eq|eq.*guine|^(?=.*span).*guinea', + ERI: 'eritrea', + EST: 'estonia', + ETH: 'ethiopia|abyssinia', + FLK: 'falkland|malvinas', + FRO: 'faroe|faeroe', + FJI: 'fiji', + FIN: 'finland', + FRA: '^(?!.*\\bdep)(?!.*martinique).*france|french.?republic|\\bgaul', + GUF: '^(?=.*french).*guiana', + PYF: 'french.?polynesia|tahiti', + ATF: 'french.?southern', + GAB: 'gabon', + GMB: 'gambia', + GEO: '^(?!.*south).*georgia', + DDR: 'german.?democratic.?republic|democratic.?republic.*germany|east.germany', + DEU: '^(?!.*east).*germany|^(?=.*\\bfed.*\\brep).*german', + GHA: 'ghana|gold.?coast', + GIB: 'gibraltar', + GRC: 'greece|hellenic|hellas', + GRL: 'greenland', + GRD: 'grenada', + GLP: 'guadeloupe', + GUM: '\\bguam', + GTM: 'guatemala', + GGY: 'guernsey', + GIN: '^(?!.*eq)(?!.*span)(?!.*bissau)(?!.*portu)(?!.*new).*guinea', + GNB: 'bissau|^(?=.*portu).*guinea', + GUY: 'guyana|british.?guiana', + HTI: 'haiti', + HMD: 'heard.*mcdonald', + VAT: 'holy.?see|vatican|papal.?st', + HND: '^(?!.*brit).*honduras', + HKG: 'hong.?kong', + HUN: '^(?!.*austr).*hungary', + ISL: 'iceland', + IND: 'india(?!.*ocea)', + IDN: 'indonesia', + IRN: '\\biran|persia', + IRQ: '\\biraq|mesopotamia', + IRL: '(^ireland)|(^republic.*ireland)', + IMN: '^(?=.*isle).*\\bman', + ISR: 'israel', + ITA: 'italy', + JAM: 'jamaica', + JPN: 'japan', + JEY: 'jersey', + JOR: 'jordan', + KAZ: 'kazak', + KEN: 'kenya|british.?east.?africa|east.?africa.?prot', + KIR: 'kiribati', + PRK: '^(?=.*democrat|people|north|d.*p.*.r).*\\bkorea|dprk|korea.*(d.*p.*r)', + KWT: 'kuwait', + KGZ: 'kyrgyz|kirghiz', + LAO: '\\blaos?\\b', + LVA: 'latvia', + LBN: 'lebanon', + LSO: 'lesotho|basuto', + LBR: 'liberia', + LBY: 'libya', + LIE: 'liechtenstein', + LTU: 'lithuania', + LUX: '^(?!.*belg).*luxem', + MAC: 'maca(o|u)', + MDG: 'madagascar|malagasy', + MWI: 'malawi|nyasa', + MYS: 'malaysia', + MDV: 'maldive', + MLI: '\\bmali\\b', + MLT: '\\bmalta', + MHL: 'marshall', + MTQ: 'martinique', + MRT: 'mauritania', + MUS: 'mauritius', + MYT: '\\bmayotte', + MEX: '\\bmexic', + FSM: 'fed.*micronesia|micronesia.*fed', + MCO: 'monaco', + MNG: 'mongolia', + MNE: '^(?!.*serbia).*montenegro', + MSR: 'montserrat', + MAR: 'morocco|\\bmaroc', + MOZ: 'mozambique', + MMR: 'myanmar|burma', + NAM: 'namibia', + NRU: 'nauru', + NPL: 'nepal', + NLD: '^(?!.*\\bant)(?!.*\\bcarib).*netherlands', + ANT: '^(?=.*\\bant).*(nether|dutch)', + NCL: 'new.?caledonia', + NZL: 'new.?zealand', + NIC: 'nicaragua', + NER: '\\bniger(?!ia)', + NGA: 'nigeria', + NIU: 'niue', + NFK: 'norfolk', + MNP: 'mariana', + NOR: 'norway', + OMN: '\\boman|trucial', + PAK: '^(?!.*east).*paki?stan', + PLW: 'palau', + PSE: 'palestin|\\bgaza|west.?bank', + PAN: 'panama', + PNG: 'papua|new.?guinea', + PRY: 'paraguay', + PER: 'peru', + PHL: 'philippines', + PCN: 'pitcairn', + POL: 'poland', + PRT: 'portugal', + PRI: 'puerto.?rico', + QAT: 'qatar', + KOR: '^(?!.*d.*p.*r)(?!.*democrat)(?!.*people)(?!.*north).*\\bkorea(?!.*d.*p.*r)', + MDA: 'moldov|b(a|e)ssarabia', + REU: 'r(e|é)union', + ROU: 'r(o|u|ou)mania', + RUS: '\\brussia|soviet.?union|u\\.?s\\.?s\\.?r|socialist.?republics', + RWA: 'rwanda', + BLM: 'barth(e|é)lemy', + SHN: 'helena', + KNA: 'kitts|\\bnevis', + LCA: '\\blucia', + MAF: '^(?=.*collectivity).*martin|^(?=.*france).*martin(?!ique)|^(?=.*french).*martin(?!ique)', + SPM: 'miquelon', + VCT: 'vincent', + WSM: '^(?!.*amer).*samoa', + SMR: 'san.?marino', + STP: '\\bs(a|ã)o.?tom(e|é)', + SAU: '\\bsa\\w*.?arabia', + SEN: 'senegal', + SRB: '^(?!.*monte).*serbia', + SYC: 'seychell', + SLE: 'sierra', + SGP: 'singapore', + SXM: '^(?!.*martin)(?!.*saba).*maarten', + SVK: '^(?!.*cze).*slovak', + SVN: 'slovenia', + SLB: 'solomon', + SOM: 'somali', + ZAF: 'south.africa|s\\\\..?africa', + SGS: 'south.?georgia|sandwich', + SSD: '\\bs\\w*.?sudan', + ESP: 'spain', + LKA: 'sri.?lanka|ceylon', + SDN: '^(?!.*\\bs(?!u)).*sudan', + SUR: 'surinam|dutch.?guiana', + SJM: 'svalbard', + SWZ: 'swaziland', + SWE: 'sweden', + CHE: 'switz|swiss', + SYR: 'syria', + TWN: 'taiwan|taipei|formosa|^(?!.*peo)(?=.*rep).*china', + TJK: 'tajik', + THA: 'thailand|\\bsiam', + MKD: 'macedonia|fyrom', + TLS: '^(?=.*leste).*timor|^(?=.*east).*timor', + TGO: 'togo', + TKL: 'tokelau', + TON: 'tonga', + TTO: 'trinidad|tobago', + TUN: 'tunisia', + TUR: 'turkey', + TKM: 'turkmen', + TCA: 'turks', + TUV: 'tuvalu', + UGA: 'uganda', + UKR: 'ukrain', + ARE: 'emirates|^u\\.?a\\.?e\\.?$|united.?arab.?em', + GBR: 'united.?kingdom|britain|^u\\.?k\\.?$', + TZA: 'tanzania', + USA: 'united.?states\\b(?!.*islands)|\\bu\\.?s\\.?a\\.?\\b|^\\s*u\\.?s\\.?\\b(?!.*islands)', + UMI: 'minor.?outlying.?is', + URY: 'uruguay', + UZB: 'uzbek', + VUT: 'vanuatu|new.?hebrides', + VEN: 'venezuela', + VNM: '^(?!.*republic).*viet.?nam|^(?=.*socialist).*viet.?nam', + VGB: '^(?=.*\\bu\\.?\\s?k).*virgin|^(?=.*brit).*virgin|^(?=.*kingdom).*virgin', + VIR: '^(?=.*\\bu\\.?\\s?s).*virgin|^(?=.*states).*virgin', + WLF: 'futuna|wallis', + ESH: 'western.sahara', + YEM: '^(?!.*arab)(?!.*north)(?!.*sana)(?!.*peo)(?!.*dem)(?!.*south)(?!.*aden)(?!.*\\bp\\.?d\\.?r).*yemen', + YMD: '^(?=.*peo).*yemen|^(?!.*rep)(?=.*dem).*yemen|^(?=.*south).*yemen|^(?=.*aden).*yemen|^(?=.*\\bp\\.?d\\.?r).*yemen', + YUG: 'yugoslavia', + ZMB: 'zambia|northern.?rhodesia', + EAZ: 'zanzibar', + ZWE: 'zimbabwe|^(?!.*northern).*rhodesia' +} + +},{}],123:[function(_dereq_,module,exports){ +module.exports=[ + "xx-small", + "x-small", + "small", + "medium", + "large", + "x-large", + "xx-large", + "larger", + "smaller" +] + +},{}],124:[function(_dereq_,module,exports){ +module.exports=[ + "normal", + "condensed", + "semi-condensed", + "extra-condensed", + "ultra-condensed", + "expanded", + "semi-expanded", + "extra-expanded", + "ultra-expanded" +] + +},{}],125:[function(_dereq_,module,exports){ +module.exports=[ + "normal", + "italic", + "oblique" +] + +},{}],126:[function(_dereq_,module,exports){ +module.exports=[ + "normal", + "bold", + "bolder", + "lighter", + "100", + "200", + "300", + "400", + "500", + "600", + "700", + "800", + "900" +] + +},{}],127:[function(_dereq_,module,exports){ +'use strict' + +module.exports = { + parse: _dereq_('./parse'), + stringify: _dereq_('./stringify') +} + +},{"./parse":129,"./stringify":130}],128:[function(_dereq_,module,exports){ +'use strict' + +var sizes = _dereq_('css-font-size-keywords') + +module.exports = { + isSize: function isSize(value) { + return /^[\d\.]/.test(value) + || value.indexOf('/') !== -1 + || sizes.indexOf(value) !== -1 + } +} + +},{"css-font-size-keywords":123}],129:[function(_dereq_,module,exports){ +'use strict' + +var unquote = _dereq_('unquote') +var globalKeywords = _dereq_('css-global-keywords') +var systemFontKeywords = _dereq_('css-system-font-keywords') +var fontWeightKeywords = _dereq_('css-font-weight-keywords') +var fontStyleKeywords = _dereq_('css-font-style-keywords') +var fontStretchKeywords = _dereq_('css-font-stretch-keywords') +var splitBy = _dereq_('string-split-by') +var isSize = _dereq_('./lib/util').isSize + + +module.exports = parseFont + + +var cache = parseFont.cache = {} + + +function parseFont (value) { + if (typeof value !== 'string') throw new Error('Font argument must be a string.') + + if (cache[value]) return cache[value] + + if (value === '') { + throw new Error('Cannot parse an empty string.') + } + + if (systemFontKeywords.indexOf(value) !== -1) { + return cache[value] = {system: value} + } + + var font = { + style: 'normal', + variant: 'normal', + weight: 'normal', + stretch: 'normal', + lineHeight: 'normal', + size: '1rem', + family: ['serif'] + } + + var tokens = splitBy(value, /\s+/) + var token + + while (token = tokens.shift()) { + if (globalKeywords.indexOf(token) !== -1) { + ['style', 'variant', 'weight', 'stretch'].forEach(function(prop) { + font[prop] = token + }) + + return cache[value] = font + } + + if (fontStyleKeywords.indexOf(token) !== -1) { + font.style = token + continue + } + + if (token === 'normal' || token === 'small-caps') { + font.variant = token + continue + } + + if (fontStretchKeywords.indexOf(token) !== -1) { + font.stretch = token + continue + } + + if (fontWeightKeywords.indexOf(token) !== -1) { + font.weight = token + continue + } + + + if (isSize(token)) { + var parts = splitBy(token, '/') + font.size = parts[0] + if (parts[1] != null) { + font.lineHeight = parseLineHeight(parts[1]) + } + else if (tokens[0] === '/') { + tokens.shift() + font.lineHeight = parseLineHeight(tokens.shift()) + } + + if (!tokens.length) { + throw new Error('Missing required font-family.') + } + font.family = splitBy(tokens.join(' '), /\s*,\s*/).map(unquote) + + return cache[value] = font + } + + throw new Error('Unknown or unsupported font token: ' + token) + } + + throw new Error('Missing required font-size.') +} + + +function parseLineHeight(value) { + var parsed = parseFloat(value) + if (parsed.toString() === value) { + return parsed + } + return value +} + +},{"./lib/util":128,"css-font-stretch-keywords":124,"css-font-style-keywords":125,"css-font-weight-keywords":126,"css-global-keywords":131,"css-system-font-keywords":132,"string-split-by":505,"unquote":525}],130:[function(_dereq_,module,exports){ +'use strict' + +var pick = _dereq_('pick-by-alias') +var isSize = _dereq_('./lib/util').isSize + +var globals = a2o(_dereq_('css-global-keywords')) +var systems = a2o(_dereq_('css-system-font-keywords')) +var weights = a2o(_dereq_('css-font-weight-keywords')) +var styles = a2o(_dereq_('css-font-style-keywords')) +var stretches = a2o(_dereq_('css-font-stretch-keywords')) + +var variants = {'normal': 1, 'small-caps': 1} +var fams = { + 'serif': 1, + 'sans-serif': 1, + 'monospace': 1, + 'cursive': 1, + 'fantasy': 1, + 'system-ui': 1 +} + +var defaults = { + style: 'normal', + variant: 'normal', + weight: 'normal', + stretch: 'normal', + size: '1rem', + lineHeight: 'normal', + family: 'serif' +} + +module.exports = function stringifyFont (o) { + o = pick(o, { + style: 'style fontstyle fontStyle font-style slope distinction', + variant: 'variant font-variant fontVariant fontvariant var capitalization', + weight: 'weight w font-weight fontWeight fontweight', + stretch: 'stretch font-stretch fontStretch fontstretch width', + size: 'size s font-size fontSize fontsize height em emSize', + lineHeight: 'lh line-height lineHeight lineheight leading', + family: 'font family fontFamily font-family fontfamily type typeface face', + system: 'system reserved default global', + }) + + if (o.system) { + if (o.system) verify(o.system, systems) + return o.system + } + + verify(o.style, styles) + verify(o.variant, variants) + verify(o.weight, weights) + verify(o.stretch, stretches) + + // default root value is medium, but by default it's inherited + if (o.size == null) o.size = defaults.size + if (typeof o.size === 'number') o.size += 'px' + + if (!isSize) throw Error('Bad size value `' + o.size + '`') + + // many user-agents use serif, we don't detect that for consistency + if (!o.family) o.family = defaults.family + if (Array.isArray(o.family)) { + if (!o.family.length) o.family = [defaults.family] + o.family = o.family.map(function (f) { + return fams[f] ? f : '"' + f + '"' + }).join(', ') + } + + // [ [ <'font-style'> || || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] + var result = [] + + result.push(o.style) + if (o.variant !== o.style) result.push(o.variant) + + if (o.weight !== o.variant && + o.weight !== o.style) result.push(o.weight) + + if (o.stretch !== o.weight && + o.stretch !== o.variant && + o.stretch !== o.style) result.push(o.stretch) + + result.push(o.size + (o.lineHeight == null || o.lineHeight === 'normal' || (o.lineHeight + '' === '1') ? '' : ('/' + o.lineHeight))) + result.push(o.family) + + return result.filter(Boolean).join(' ') +} + +function verify (value, values) { + if (value && !values[value] && !globals[value]) throw Error('Unknown keyword `' + value +'`') + + return value +} + + +// ['a', 'b'] -> {a: true, b: true} +function a2o (a) { + var o = {} + for (var i = 0; i < a.length; i++) { + o[a[i]] = 1 + } + return o +} + +},{"./lib/util":128,"css-font-stretch-keywords":124,"css-font-style-keywords":125,"css-font-weight-keywords":126,"css-global-keywords":131,"css-system-font-keywords":132,"pick-by-alias":448}],131:[function(_dereq_,module,exports){ +module.exports=[ + "inherit", + "initial", + "unset" +] + +},{}],132:[function(_dereq_,module,exports){ +module.exports=[ + "caption", + "icon", + "menu", + "message-box", + "small-caption", + "status-bar" +] + +},{}],133:[function(_dereq_,module,exports){ +"use strict" + +function dcubicHermite(p0, v0, p1, v1, t, f) { + var dh00 = 6*t*t-6*t, + dh10 = 3*t*t-4*t + 1, + dh01 = -6*t*t+6*t, + dh11 = 3*t*t-2*t + if(p0.length) { + if(!f) { + f = new Array(p0.length) + } + for(var i=p0.length-1; i>=0; --i) { + f[i] = dh00*p0[i] + dh10*v0[i] + dh01*p1[i] + dh11*v1[i] + } + return f + } + return dh00*p0 + dh10*v0 + dh01*p1[i] + dh11*v1 +} + +function cubicHermite(p0, v0, p1, v1, t, f) { + var ti = (t-1), t2 = t*t, ti2 = ti*ti, + h00 = (1+2*t)*ti2, + h10 = t*ti2, + h01 = t2*(3-2*t), + h11 = t2*ti + if(p0.length) { + if(!f) { + f = new Array(p0.length) + } + for(var i=p0.length-1; i>=0; --i) { + f[i] = h00*p0[i] + h10*v0[i] + h01*p1[i] + h11*v1[i] + } + return f + } + return h00*p0 + h10*v0 + h01*p1 + h11*v1 +} + +module.exports = cubicHermite +module.exports.derivative = dcubicHermite +},{}],134:[function(_dereq_,module,exports){ +"use strict" + +var createThunk = _dereq_("./lib/thunk.js") + +function Procedure() { + this.argTypes = [] + this.shimArgs = [] + this.arrayArgs = [] + this.arrayBlockIndices = [] + this.scalarArgs = [] + this.offsetArgs = [] + this.offsetArgIndex = [] + this.indexArgs = [] + this.shapeArgs = [] + this.funcName = "" + this.pre = null + this.body = null + this.post = null + this.debug = false +} + +function compileCwise(user_args) { + //Create procedure + var proc = new Procedure() + + //Parse blocks + proc.pre = user_args.pre + proc.body = user_args.body + proc.post = user_args.post + + //Parse arguments + var proc_args = user_args.args.slice(0) + proc.argTypes = proc_args + for(var i=0; i0) { + throw new Error("cwise: pre() block may not reference array args") + } + if(i < proc.post.args.length && proc.post.args[i].count>0) { + throw new Error("cwise: post() block may not reference array args") + } + } else if(arg_type === "scalar") { + proc.scalarArgs.push(i) + proc.shimArgs.push("scalar" + i) + } else if(arg_type === "index") { + proc.indexArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { + throw new Error("cwise: pre() block may not reference array index") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array index") + } + if(i < proc.post.args.length && proc.post.args[i].count > 0) { + throw new Error("cwise: post() block may not reference array index") + } + } else if(arg_type === "shape") { + proc.shapeArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { + throw new Error("cwise: pre() block may not write to array shape") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array shape") + } + if(i < proc.post.args.length && proc.post.args[i].lvalue) { + throw new Error("cwise: post() block may not write to array shape") + } + } else if(typeof arg_type === "object" && arg_type.offset) { + proc.argTypes[i] = "offset" + proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) + proc.offsetArgIndex.push(i) + } else { + throw new Error("cwise: Unknown argument type " + proc_args[i]) + } + } + + //Make sure at least one array argument was specified + if(proc.arrayArgs.length <= 0) { + throw new Error("cwise: No array arguments specified") + } + + //Make sure arguments are correct + if(proc.pre.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in pre() block") + } + if(proc.body.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in body() block") + } + if(proc.post.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in post() block") + } + + //Check debug flag + proc.debug = !!user_args.printCode || !!user_args.debug + + //Retrieve name + proc.funcName = user_args.funcName || "cwise" + + //Read in block size + proc.blockSize = user_args.blockSize || 64 + + return createThunk(proc) +} + +module.exports = compileCwise + +},{"./lib/thunk.js":136}],135:[function(_dereq_,module,exports){ +"use strict" + +var uniq = _dereq_("uniq") + +// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index) +// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments. +function innerFill(order, proc, body) { + var dimension = order.length + , nargs = proc.arrayArgs.length + , has_index = proc.indexArgs.length>0 + , code = [] + , vars = [] + , idx=0, pidx=0, i, j + for(i=0; i 0) { + code.push("var " + vars.join(",")) + } + //Scan loop + for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards + idx = order[i] + code.push(["for(i",i,"=0;i",i," 0) { + code.push(["index[",pidx,"]-=s",pidx].join("")) + } + code.push(["++index[",idx,"]"].join("")) + } + code.push("}") + } + return code.join("\n") +} + +// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block. +// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. +// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used. +function outerFill(matched, order, proc, body) { + var dimension = order.length + , nargs = proc.arrayArgs.length + , blockSize = proc.blockSize + , has_index = proc.indexArgs.length > 0 + , code = [] + for(var i=0; i0;){"].join("")) // Iterate back to front + code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). + code.push(["s",order[i],"=j",i].join("")) + code.push(["j",i,"=0"].join("")) + code.push(["}else{s",order[i],"=",blockSize].join("")) + code.push(["j",i,"-=",blockSize,"}"].join("")) + if(has_index) { + code.push(["index[",order[i],"]=j",i].join("")) + } + } + for(var i=0; i 0) { + allEqual = allEqual && summary[i] === summary[i-1] + } + } + if(allEqual) { + return summary[0] + } + return summary.join("") +} + +//Generates a cwise operator +function generateCWiseOp(proc, typesig) { + + //Compute dimension + // Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg. + var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 + var orders = new Array(proc.arrayArgs.length) + var dtypes = new Array(proc.arrayArgs.length) + for(var i=0; i 0) { + vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example) + } + if(proc.indexArgs.length > 0) { + // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. + var zeros = new Array(dimension) + for(var i=0; i 0) { + code.push("var " + vars.join(",")) + } + for(var i=0; i 3) { + code.push(processBlock(proc.pre, proc, dtypes)) + } + + //Process body + var body = processBlock(proc.body, proc, dtypes) + var matched = countMatches(loopOrders) + if(matched < dimension) { + code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example. + } else { + code.push(innerFill(loopOrders[0], proc, body)) + } + + //Inline epilog + if(proc.post.body.length > 3) { + code.push(processBlock(proc.post, proc, dtypes)) + } + + if(proc.debug) { + console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") + } + + var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") + var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) + return f() +} +module.exports = generateCWiseOp + +},{"uniq":524}],136:[function(_dereq_,module,exports){ +"use strict" + +// The function below is called when constructing a cwise function object, and does the following: +// A function object is constructed which accepts as argument a compilation function and returns another function. +// It is this other function that is eventually returned by createThunk, and this function is the one that actually +// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. +// The compilation passed to the first function object is used for compiling new functions. +// Once this function object is created, it is called with compile as argument, where the first argument of compile +// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). +// So createThunk roughly works like this: +// function createThunk(proc) { +// var thunk = function(compileBound) { +// var CACHED = {} +// return function(arrays and scalars) { +// if (dtype and order of arrays in CACHED) { +// var func = CACHED[dtype and order of arrays] +// } else { +// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) +// } +// return func(arrays and scalars) +// } +// } +// return thunk(compile.bind1(proc)) +// } + +var compile = _dereq_("./compile.js") + +function createThunk(proc) { + var code = ["'use strict'", "var CACHED={}"] + var vars = [] + var thunkName = proc.funcName + "_cwise_thunk" + + //Build thunk + code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) + var typesig = [] + var string_typesig = [] + var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS). + Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")] + var shapeLengthConditions = [], shapeConditions = [] + // Process array arguments + for(var i=0; i0) { // Gather conditions to check for shape equality (ignoring block indices) + shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i]))) + shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]") + } + } + // Check for shape equality + if (proc.arrayArgs.length > 1) { + code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')") + code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {") + code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") + code.push("}") + } + // Process scalar arguments + for(var i=0; i b ? 1 : a >= b ? 0 : NaN; +} + +function bisector(compare) { + if (compare.length === 1) compare = ascendingComparator(compare); + return { + left: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; + else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; + else lo = mid + 1; + } + return lo; + } + }; +} + +function ascendingComparator(f) { + return function(d, x) { + return ascending(f(d), x); + }; +} + +var ascendingBisect = bisector(ascending); +var bisectRight = ascendingBisect.right; +var bisectLeft = ascendingBisect.left; + +function pairs(array, f) { + if (f == null) f = pair; + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = f(p, p = array[++i]); + return pairs; +} + +function pair(a, b) { + return [a, b]; +} + +function cross(values0, values1, reduce) { + var n0 = values0.length, + n1 = values1.length, + values = new Array(n0 * n1), + i0, + i1, + i, + value0; + + if (reduce == null) reduce = pair; + + for (i0 = i = 0; i0 < n0; ++i0) { + for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { + values[i] = reduce(value0, values1[i1]); + } + } + + return values; +} + +function descending(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +} + +function number(x) { + return x === null ? NaN : +x; +} + +function variance(values, valueof) { + var n = values.length, + m = 0, + i = -1, + mean = 0, + value, + delta, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + if (m > 1) return sum / (m - 1); +} + +function deviation(array, f) { + var v = variance(array, f); + return v ? Math.sqrt(v) : v; +} + +function extent(values, valueof) { + var n = values.length, + i = -1, + value, + min, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + return [min, max]; +} + +var array = Array.prototype; + +var slice = array.slice; +var map = array.map; + +function constant(x) { + return function() { + return x; + }; +} + +function identity(x) { + return x; +} + +function range(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; +} + +var e10 = Math.sqrt(50), + e5 = Math.sqrt(10), + e2 = Math.sqrt(2); + +function ticks(start, stop, count) { + var reverse, + i = -1, + n, + ticks, + step; + + stop = +stop, start = +start, count = +count; + if (start === stop && count > 0) return [start]; + if (reverse = stop < start) n = start, start = stop, stop = n; + if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; + + if (step > 0) { + start = Math.ceil(start / step); + stop = Math.floor(stop / step); + ticks = new Array(n = Math.ceil(stop - start + 1)); + while (++i < n) ticks[i] = (start + i) * step; + } else { + start = Math.floor(start * step); + stop = Math.ceil(stop * step); + ticks = new Array(n = Math.ceil(start - stop + 1)); + while (++i < n) ticks[i] = (start - i) / step; + } + + if (reverse) ticks.reverse(); + + return ticks; +} + +function tickIncrement(start, stop, count) { + var step = (stop - start) / Math.max(0, count), + power = Math.floor(Math.log(step) / Math.LN10), + error = step / Math.pow(10, power); + return power >= 0 + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) + : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); +} + +function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) step1 *= 10; + else if (error >= e5) step1 *= 5; + else if (error >= e2) step1 *= 2; + return stop < start ? -step1 : step1; +} + +function sturges(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; +} + +function histogram() { + var value = identity, + domain = extent, + threshold = sturges; + + function histogram(data) { + var i, + n = data.length, + x, + values = new Array(n); + + for (i = 0; i < n; ++i) { + values[i] = value(data[i], i, data); + } + + var xz = domain(values), + x0 = xz[0], + x1 = xz[1], + tz = threshold(values, x0, x1); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + tz = tickStep(x0, x1, tz); + tz = range(Math.ceil(x0 / tz) * tz, x1, tz); // exclusive + } + + // Remove any thresholds outside the domain. + var m = tz.length; + while (tz[0] <= x0) tz.shift(), --m; + while (tz[m - 1] > x1) tz.pop(), --m; + + var bins = new Array(m + 1), + bin; + + // Initialize bins. + for (i = 0; i <= m; ++i) { + bin = bins[i] = []; + bin.x0 = i > 0 ? tz[i - 1] : x0; + bin.x1 = i < m ? tz[i] : x1; + } + + // Assign data to bins by value, ignoring any outside the domain. + for (i = 0; i < n; ++i) { + x = values[i]; + if (x0 <= x && x <= x1) { + bins[bisectRight(tz, x, 0, m)].push(data[i]); + } + } + + return bins; + } + + histogram.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; + }; + + histogram.domain = function(_) { + return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; + }; + + histogram.thresholds = function(_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; + }; + + return histogram; +} + +function quantile(values, p, valueof) { + if (valueof == null) valueof = number; + if (!(n = values.length)) return; + if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); + if (p >= 1) return +valueof(values[n - 1], n - 1, values); + var n, + i = (n - 1) * p, + i0 = Math.floor(i), + value0 = +valueof(values[i0], i0, values), + value1 = +valueof(values[i0 + 1], i0 + 1, values); + return value0 + (value1 - value0) * (i - i0); +} + +function freedmanDiaconis(values, min, max) { + values = map.call(values, number).sort(ascending); + return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); +} + +function scott(values, min, max) { + return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); +} + +function max(values, valueof) { + var n = values.length, + i = -1, + value, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && value > max) { + max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && value > max) { + max = value; + } + } + } + } + } + + return max; +} + +function mean(values, valueof) { + var n = values.length, + m = n, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) sum += value; + else --m; + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; + else --m; + } + } + + if (m) return sum / m; +} + +function median(values, valueof) { + var n = values.length, + i = -1, + value, + numbers = []; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + numbers.push(value); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + numbers.push(value); + } + } + } + + return quantile(numbers.sort(ascending), 0.5); +} + +function merge(arrays) { + var n = arrays.length, + m, + i = -1, + j = 0, + merged, + array; + + while (++i < n) j += arrays[i].length; + merged = new Array(j); + + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + + return merged; +} + +function min(values, valueof) { + var n = values.length, + i = -1, + value, + min; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && min > value) { + min = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && min > value) { + min = value; + } + } + } + } + } + + return min; +} + +function permute(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; +} + +function scan(values, compare) { + if (!(n = values.length)) return; + var n, + i = 0, + j = 0, + xi, + xj = values[j]; + + if (compare == null) compare = ascending; + + while (++i < n) { + if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { + xj = xi, j = i; + } + } + + if (compare(xj, xj) === 0) return j; +} + +function shuffle(array, i0, i1) { + var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0]; + array[m + i0] = array[i + i0]; + array[i + i0] = t; + } + + return array; +} + +function sum(values, valueof) { + var n = values.length, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (value = +values[i]) sum += value; // Note: zero and null are equivalent. + } + } + + else { + while (++i < n) { + if (value = +valueof(values[i], i, values)) sum += value; + } + } + + return sum; +} + +function transpose(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { + row[j] = matrix[j][i]; + } + } + return transpose; +} + +function length(d) { + return d.length; +} + +function zip() { + return transpose(arguments); +} + +exports.bisect = bisectRight; +exports.bisectRight = bisectRight; +exports.bisectLeft = bisectLeft; +exports.ascending = ascending; +exports.bisector = bisector; +exports.cross = cross; +exports.descending = descending; +exports.deviation = deviation; +exports.extent = extent; +exports.histogram = histogram; +exports.thresholdFreedmanDiaconis = freedmanDiaconis; +exports.thresholdScott = scott; +exports.thresholdSturges = sturges; +exports.max = max; +exports.mean = mean; +exports.median = median; +exports.merge = merge; +exports.min = min; +exports.pairs = pairs; +exports.permute = permute; +exports.quantile = quantile; +exports.range = range; +exports.scan = scan; +exports.shuffle = shuffle; +exports.sum = sum; +exports.ticks = ticks; +exports.tickIncrement = tickIncrement; +exports.tickStep = tickStep; +exports.transpose = transpose; +exports.variance = variance; +exports.zip = zip; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],141:[function(_dereq_,module,exports){ +// https://d3js.org/d3-collection/ Version 1.0.4. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var prefix = "$"; + +function Map() {} + +Map.prototype = map.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); + } +}; + +function map(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +var nest = function() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; + + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) { + if (sortValues != null) array.sort(sortValues); + return rollup != null ? rollup(array) : array; + } + + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map(), + values, + result = createResult(); + + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } + + valuesByKey.each(function(values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); + + return result; + } + + function entries(map$$1, depth) { + if (++depth > keys.length) return map$$1; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) array = map$$1.entries(); + else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); + return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; + } + + return nest = { + object: function(array) { return apply(array, 0, createObject, setObject); }, + map: function(array) { return apply(array, 0, createMap, setMap); }, + entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, + key: function(d) { keys.push(d); return nest; }, + sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, + sortValues: function(order) { sortValues = order; return nest; }, + rollup: function(f) { rollup = f; return nest; } + }; +}; + +function createObject() { + return {}; +} + +function setObject(object, key, value) { + object[key] = value; +} + +function createMap() { + return map(); +} + +function setMap(map$$1, key, value) { + map$$1.set(key, value); +} + +function Set() {} + +var proto = map.prototype; + +Set.prototype = set.prototype = { + constructor: Set, + has: proto.has, + add: function(value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each +}; + +function set(object, f) { + var set = new Set; + + // Copy constructor. + if (object instanceof Set) object.each(function(value) { set.add(value); }); + + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) while (++i < n) set.add(object[i]); + else while (++i < n) set.add(f(object[i], i, object)); + } + + return set; +} + +var keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; +}; + +var values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; +}; + +var entries = function(map) { + var entries = []; + for (var key in map) entries.push({key: key, value: map[key]}); + return entries; +}; + +exports.nest = nest; +exports.set = set; +exports.map = map; +exports.keys = keys; +exports.values = values; +exports.entries = entries; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],142:[function(_dereq_,module,exports){ +// https://d3js.org/d3-color/ v1.2.3 Copyright 2018 Mike Bostock +(function (global, factory) { +typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : +typeof define === 'function' && define.amd ? define(['exports'], factory) : +(factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +function define(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; +} + +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; +} + +function Color() {} + +var darker = 0.7; +var brighter = 1 / darker; + +var reI = "\\s*([+-]?\\d+)\\s*", + reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", + reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", + reHex3 = /^#([0-9a-f]{3})$/, + reHex6 = /^#([0-9a-f]{6})$/, + reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"), + reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"), + reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"), + reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"), + reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"), + reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); + +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 +}; + +define(Color, color, { + displayable: function() { + return this.rgb().displayable(); + }, + hex: function() { + return this.rgb().hex(); + }, + toString: function() { + return this.rgb() + ""; + } +}); + +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} + +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} + +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} + +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} + +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +} + +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; +} + +define(Rgb, rgb, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function() { + return this; + }, + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); + }, + hex: function() { + return "#" + hex(this.r) + hex(this.g) + hex(this.b); + }, + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } +})); + +function hex(value) { + value = Math.max(0, Math.min(255, Math.round(value) || 0)); + return (value < 16 ? "0" : "") + value.toString(16); +} + +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} + +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); +} + +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} + +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Hsl, hsl, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); + +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} + +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; + +// https://beta.observablehq.com/@mbostock/lab-and-rgb +var K = 18, + Xn = 0.96422, + Yn = 1, + Zn = 0.82521, + t0 = 4 / 29, + t1 = 6 / 29, + t2 = 3 * t1 * t1, + t3 = t1 * t1 * t1; + +function labConvert(o) { + if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) { + if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity); + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); + } + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = rgb2lrgb(o.r), + g = rgb2lrgb(o.g), + b = rgb2lrgb(o.b), + y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z; + if (r === g && g === b) x = z = y; else { + x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn); + z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn); + } + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +} + +function gray(l, opacity) { + return new Lab(l, 0, 0, opacity == null ? 1 : opacity); +} + +function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +} + +function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; +} + +define(Lab, lab, extend(Color, { + brighter: function(k) { + return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + darker: function(k) { + return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + rgb: function() { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + x = Xn * lab2xyz(x); + y = Yn * lab2xyz(y); + z = Zn * lab2xyz(z); + return new Rgb( + lrgb2rgb( 3.1338561 * x - 1.6168667 * y - 0.4906146 * z), + lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z), + lrgb2rgb( 0.0719453 * x - 0.2289914 * y + 1.4052427 * z), + this.opacity + ); + } +})); + +function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; +} + +function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); +} + +function lrgb2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); +} + +function rgb2lrgb(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); +} + +function hclConvert(o) { + if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) o = labConvert(o); + if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0, o.l, o.opacity); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); +} + +function lch(l, c, h, opacity) { + return arguments.length === 1 ? hclConvert(l) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; +} + +define(Hcl, hcl, extend(Color, { + brighter: function(k) { + return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity); + }, + darker: function(k) { + return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity); + }, + rgb: function() { + return labConvert(this).rgb(); + } +})); + +var A = -0.14861, + B = +1.78277, + C = -0.29227, + D = -0.90649, + E = +1.97294, + ED = E * D, + EB = E * B, + BC_DA = B * C - D * A; + +function cubehelixConvert(o) { + if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); +} + +function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); +} + +function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Cubehelix, cubehelix, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); + } +})); + +exports.color = color; +exports.rgb = rgb; +exports.hsl = hsl; +exports.lab = lab; +exports.hcl = hcl; +exports.lch = lch; +exports.gray = gray; +exports.cubehelix = cubehelix; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],143:[function(_dereq_,module,exports){ +// https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var noop = {value: function() {}}; + +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); +} + +function Dispatch(_) { + this._ = _; +} + +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} + +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } +}; + +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } +} + +function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} + +exports.dispatch = dispatch; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],144:[function(_dereq_,module,exports){ +// https://d3js.org/d3-force/ Version 1.1.0. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-quadtree'), _dereq_('d3-collection'), _dereq_('d3-dispatch'), _dereq_('d3-timer')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-quadtree', 'd3-collection', 'd3-dispatch', 'd3-timer'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Quadtree,d3Collection,d3Dispatch,d3Timer) { 'use strict'; + +var center = function(x, y) { + var nodes; + + if (x == null) x = 0; + if (y == null) y = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + + force.initialize = function(_) { + nodes = _; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var jiggle = function() { + return (Math.random() - 0.5) * 1e-6; +}; + +function x(d) { + return d.x + d.vx; +} + +function y(d) { + return d.y + d.vy; +} + +var collide = function(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; + + if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius); + + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; + + for (var k = 0; k < iterations; ++k) { + tree = d3Quadtree.quadtree(nodes, x, y).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + + function prepare(quad) { + if (quad.data) return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; + }; + + return force; +}; + +function index(d) { + return d.index; +} + +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; +} + +var link = function(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = d3Collection.map(nodes, id), + link; + + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; + }; + + return force; +}; + +function x$1(d) { + return d.x; +} + +function y$1(d) { + return d.y; +} + +var initialRadius = 10; +var initialAngle = Math.PI * (3 - Math.sqrt(5)); + +var simulation = function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = d3Collection.map(), + stepper = d3Timer.timer(step), + event = d3Dispatch.dispatch("tick", "end"); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick() { + var i, n = nodes.length, node; + + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function(force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) radius = Infinity; + else radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; +}; + +var manyBody = function() { + var nodes, + node, + alpha, + strength = constant(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, n = nodes.length, tree = d3Quadtree.quadtree(nodes, x$1, y$1).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } + + function accumulate(quad) { + var strength = 0, q, c, weight = 0, x, y, i; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x = y = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = Math.abs(q.value))) { + strength += q.value, weight += c, x += c * q.x, y += c * q.y; + } + } + quad.x = x / weight; + quad.y = y / weight; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do strength += strengths[q.data.index]; + while (q = q.next); + } + + quad.value = strength; + } + + function apply(quad, x1, _, x2) { + if (!quad.value) return true; + + var x = quad.x - node.x, + y = quad.y - node.y, + w = x2 - x1, + l = x * x + y * y; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x * quad.value * alpha / l; + node.vy += y * quad.value * alpha / l; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + } + + do if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x * w; + node.vy += y * w; + } while (quad = quad.next); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; +}; + +var radial = function(radius, x, y) { + var nodes, + strength = constant(0.1), + strengths, + radiuses; + + if (typeof radius !== "function") radius = constant(+radius); + if (x == null) x = 0; + if (y == null) y = 0; + + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], + dx = node.x - x || 1e-6, + dy = node.y - y || 1e-6, + r = Math.sqrt(dx * dx + dy * dy), + k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + node.vy += dy * k; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _, initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var x$2 = function(x) { + var strength = constant(0.1), + nodes, + strengths, + xz; + + if (typeof x !== "function") x = constant(x == null ? 0 : +x); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x; + }; + + return force; +}; + +var y$2 = function(y) { + var strength = constant(0.1), + nodes, + strengths, + yz; + + if (typeof y !== "function") y = constant(y == null ? 0 : +y); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y; + }; + + return force; +}; + +exports.forceCenter = center; +exports.forceCollide = collide; +exports.forceLink = link; +exports.forceManyBody = manyBody; +exports.forceRadial = radial; +exports.forceSimulation = simulation; +exports.forceX = x$2; +exports.forceY = y$2; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-collection":141,"d3-dispatch":143,"d3-quadtree":146,"d3-timer":147}],145:[function(_dereq_,module,exports){ +// https://d3js.org/d3-interpolate/ v1.3.2 Copyright 2018 Mike Bostock +(function (global, factory) { +typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-color')) : +typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : +(factory((global.d3 = global.d3 || {}),global.d3)); +}(this, (function (exports,d3Color) { 'use strict'; + +function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; +} + +function basis$1(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +} + +function basisClosed(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +} + +function constant(x) { + return function() { + return x; + }; +} + +function linear(a, d) { + return function(t) { + return a + t * d; + }; +} + +function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; +} + +function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); +} + +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); + }; +} + +function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant(isNaN(a) ? b : a); +} + +var rgb = (function rgbGamma(y) { + var color = gamma(y); + + function rgb(start, end) { + var r = color((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), + g = color(start.g, end.g), + b = color(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb.gamma = rgbGamma; + + return rgb; +})(1); + +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color; + for (i = 0; i < n; ++i) { + color = d3Color.rgb(colors[i]); + r[i] = color.r || 0; + g[i] = color.g || 0; + b[i] = color.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color.opacity = 1; + return function(t) { + color.r = r(t); + color.g = g(t); + color.b = b(t); + return color + ""; + }; + }; +} + +var rgbBasis = rgbSpline(basis$1); +var rgbBasisClosed = rgbSpline(basisClosed); + +function array(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(na), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; +} + +function date(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; +} + +function number(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +} + +function object(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; + + for (k in b) { + if (k in a) { + i[k] = value(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; +} + +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, + reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; +} + +function one(b) { + return function(t) { + return b(t) + ""; + }; +} + +function string(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: number(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); +} + +function value(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant(b) + : (t === "number" ? number + : t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb) : string) + : b instanceof d3Color.color ? rgb + : b instanceof Date ? date + : Array.isArray(b) ? array + : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object + : number)(a, b); +} + +function discrete(range) { + var n = range.length; + return function(t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; +} + +function hue$1(a, b) { + var i = hue(+a, +b); + return function(t) { + var x = i(t); + return x - 360 * Math.floor(x / 360); + }; +} + +function round(a, b) { + return a = +a, b -= a, function(t) { + return Math.round(a + b * t); + }; +} + +var degrees = 180 / Math.PI; + +var identity = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 +}; + +function decompose(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; +} + +var cssNode, + cssRoot, + cssView, + svgNode; + +function parseCss(value) { + if (value === "none") return identity; + if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +} + +function parseSvg(value) { + if (value == null) return identity; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); +} + +function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; +} + +var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); +var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + +var rho = Math.SQRT2, + rho2 = 2, + rho4 = 4, + epsilon2 = 1e-12; + +function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; +} + +function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; +} + +function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); +} + +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] +function zoom(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], + ux1 = p1[0], uy1 = p1[1], w1 = p1[2], + dx = ux1 - ux0, + dy = uy1 - uy0, + d2 = dx * dx + dy * dy, + i, + S; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; +} + +function hsl(hue$$1) { + return function(start, end) { + var h = hue$$1((start = d3Color.hsl(start)).h, (end = d3Color.hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hsl$1 = hsl(hue); +var hslLong = hsl(nogamma); + +function lab(start, end) { + var l = nogamma((start = d3Color.lab(start)).l, (end = d3Color.lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; +} + +function hcl(hue$$1) { + return function(start, end) { + var h = hue$$1((start = d3Color.hcl(start)).h, (end = d3Color.hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hcl$1 = hcl(hue); +var hclLong = hcl(nogamma); + +function cubehelix(hue$$1) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix(start, end) { + var h = hue$$1((start = d3Color.cubehelix(start)).h, (end = d3Color.cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix.gamma = cubehelixGamma; + + return cubehelix; + })(1); +} + +var cubehelix$1 = cubehelix(hue); +var cubehelixLong = cubehelix(nogamma); + +function piecewise(interpolate, values) { + var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n); + while (i < n) I[i] = interpolate(v, v = values[++i]); + return function(t) { + var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n))); + return I[i](t - i); + }; +} + +function quantize(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); + return samples; +} + +exports.interpolate = value; +exports.interpolateArray = array; +exports.interpolateBasis = basis$1; +exports.interpolateBasisClosed = basisClosed; +exports.interpolateDate = date; +exports.interpolateDiscrete = discrete; +exports.interpolateHue = hue$1; +exports.interpolateNumber = number; +exports.interpolateObject = object; +exports.interpolateRound = round; +exports.interpolateString = string; +exports.interpolateTransformCss = interpolateTransformCss; +exports.interpolateTransformSvg = interpolateTransformSvg; +exports.interpolateZoom = zoom; +exports.interpolateRgb = rgb; +exports.interpolateRgbBasis = rgbBasis; +exports.interpolateRgbBasisClosed = rgbBasisClosed; +exports.interpolateHsl = hsl$1; +exports.interpolateHslLong = hslLong; +exports.interpolateLab = lab; +exports.interpolateHcl = hcl$1; +exports.interpolateHclLong = hclLong; +exports.interpolateCubehelix = cubehelix$1; +exports.interpolateCubehelixLong = cubehelixLong; +exports.piecewise = piecewise; +exports.quantize = quantize; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-color":142}],146:[function(_dereq_,module,exports){ +// https://d3js.org/d3-quadtree/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var tree_add = function(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); +}; + +function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; +} + +function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } + + // If there were no (valid) points, inherit the existing extent. + if (x1 < x0) x0 = this._x0, x1 = this._x1; + if (y1 < y0) y0 = this._y0, y1 = this._y1; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + + return this; +} + +var tree_cover = function(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else if (x0 > x || x > x1 || y0 > y || y > y1) { + var z = x1 - x0, + node = this._root, + parent, + i; + + switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { + case 0: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); + break; + } + case 1: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); + break; + } + case 2: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); + break; + } + case 3: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); + break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + // If the quadtree covers the point already, just return. + else return this; + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; +}; + +var tree_data = function() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; +}; + +var tree_extent = function(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; +}; + +var Quad = function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}; + +var tree_find = function(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; +}; + +var tree_remove = function(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; +}; + +function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; +} + +var tree_root = function() { + return this._root; +}; + +var tree_size = function() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; +}; + +var tree_visit = function(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; +}; + +var tree_visitAfter = function(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; +}; + +function defaultX(d) { + return d[0]; +} + +var tree_x = function(_) { + return arguments.length ? (this._x = _, this) : this._x; +}; + +function defaultY(d) { + return d[1]; +} + +var tree_y = function(_) { + return arguments.length ? (this._y = _, this) : this._y; +}; + +function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); +} + +function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; +} + +function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; +} + +var treeProto = quadtree.prototype = Quadtree.prototype; + +treeProto.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy(child); + } + } + } + + return copy; +}; + +treeProto.add = tree_add; +treeProto.addAll = addAll; +treeProto.cover = tree_cover; +treeProto.data = tree_data; +treeProto.extent = tree_extent; +treeProto.find = tree_find; +treeProto.remove = tree_remove; +treeProto.removeAll = removeAll; +treeProto.root = tree_root; +treeProto.size = tree_size; +treeProto.visit = tree_visit; +treeProto.visitAfter = tree_visitAfter; +treeProto.x = tree_x; +treeProto.y = tree_y; + +exports.quadtree = quadtree; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],147:[function(_dereq_,module,exports){ +// https://d3js.org/d3-timer/ Version 1.0.7. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var frame = 0; +var timeout = 0; +var interval = 0; +var pokeDelay = 1000; +var taskHead; +var taskTail; +var clockLast = 0; +var clockNow = 0; +var clockSkew = 0; +var clock = typeof performance === "object" && performance.now ? performance : Date; +var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); +} + +function clearNow() { + clockNow = 0; +} + +function Timer() { + this._call = + this._time = + this._next = null; +} + +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } +}; + +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; +} + +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } +} + +function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; +} + +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); +} + +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; // Strictly less than if we recomputed clockNow. + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } +} + +var timeout$1 = function(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function(elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; +}; + +var interval$1 = function(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; +}; + +exports.now = now; +exports.timer = timer; +exports.timerFlush = timerFlush; +exports.timeout = timeout$1; +exports.interval = interval$1; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],148:[function(_dereq_,module,exports){ +!function() { + var d3 = { + version: "3.5.17" + }; + var d3_arraySlice = [].slice, d3_array = function(list) { + return d3_arraySlice.call(list); + }; + var d3_document = this.document; + function d3_documentElement(node) { + return node && (node.ownerDocument || node.document || node).documentElement; + } + function d3_window(node) { + return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); + } + if (d3_document) { + try { + d3_array(d3_document.documentElement.childNodes)[0].nodeType; + } catch (e) { + d3_array = function(list) { + var i = list.length, array = new Array(i); + while (i--) array[i] = list[i]; + return array; + }; + } + } + if (!Date.now) Date.now = function() { + return +new Date(); + }; + if (d3_document) { + try { + d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); + } catch (error) { + var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; + d3_element_prototype.setAttribute = function(name, value) { + d3_element_setAttribute.call(this, name, value + ""); + }; + d3_element_prototype.setAttributeNS = function(space, local, value) { + d3_element_setAttributeNS.call(this, space, local, value + ""); + }; + d3_style_prototype.setProperty = function(name, value, priority) { + d3_style_setProperty.call(this, name, value + "", priority); + }; + } + } + d3.ascending = d3_ascending; + function d3_ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + }; + d3.min = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && a > b) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; + } + return a; + }; + d3.max = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && b > a) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; + } + return a; + }; + d3.extent = function(array, f) { + var i = -1, n = array.length, a, b, c; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = array[i]) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } + return [ a, c ]; + }; + function d3_number(x) { + return x === null ? NaN : +x; + } + function d3_numeric(x) { + return !isNaN(x); + } + d3.sum = function(array, f) { + var s = 0, n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = +array[i])) s += a; + } else { + while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; + } + return s; + }; + d3.mean = function(array, f) { + var s = 0, n = array.length, a, i = -1, j = n; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; + } + if (j) return s / j; + }; + d3.quantile = function(values, p) { + var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; + return e ? v + e * (values[h] - v) : v; + }; + d3.median = function(array, f) { + var numbers = [], n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); + } + if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); + }; + d3.variance = function(array, f) { + var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; + if (arguments.length === 1) { + while (++i < n) { + if (d3_numeric(a = d3_number(array[i]))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } else { + while (++i < n) { + if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + if (j > 1) return s / (j - 1); + }; + d3.deviation = function() { + var v = d3.variance.apply(this, arguments); + return v ? Math.sqrt(v) : v; + }; + function d3_bisector(compare) { + return { + left: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; + } + return lo; + } + }; + } + var d3_bisect = d3_bisector(d3_ascending); + d3.bisectLeft = d3_bisect.left; + d3.bisect = d3.bisectRight = d3_bisect.right; + d3.bisector = function(f) { + return d3_bisector(f.length === 1 ? function(d, x) { + return d3_ascending(f(d), x); + } : f); + }; + d3.shuffle = function(array, i0, i1) { + if ((m = arguments.length) < 3) { + i1 = array.length; + if (m < 2) i0 = 0; + } + var m = i1 - i0, t, i; + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; + } + return array; + }; + d3.permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; + }; + d3.pairs = function(array) { + var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; + return pairs; + }; + d3.transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { + row[j] = matrix[j][i]; + } + } + return transpose; + }; + function d3_transposeLength(d) { + return d.length; + } + d3.zip = function() { + return d3.transpose(arguments); + }; + d3.keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; + }; + d3.values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; + }; + d3.entries = function(map) { + var entries = []; + for (var key in map) entries.push({ + key: key, + value: map[key] + }); + return entries; + }; + d3.merge = function(arrays) { + var n = arrays.length, m, i = -1, j = 0, merged, array; + while (++i < n) j += arrays[i].length; + merged = new Array(j); + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + return merged; + }; + var abs = Math.abs; + d3.range = function(start, stop, step) { + if (arguments.length < 3) { + step = 1; + if (arguments.length < 2) { + stop = start; + start = 0; + } + } + if ((stop - start) / step === Infinity) throw new Error("infinite range"); + var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; + start *= k, stop *= k, step *= k; + if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); + return range; + }; + function d3_range_integerScale(x) { + var k = 1; + while (x * k % 1) k *= 10; + return k; + } + function d3_class(ctor, properties) { + for (var key in properties) { + Object.defineProperty(ctor.prototype, key, { + value: properties[key], + enumerable: false + }); + } + } + d3.map = function(object, f) { + var map = new d3_Map(); + if (object instanceof d3_Map) { + object.forEach(function(key, value) { + map.set(key, value); + }); + } else if (Array.isArray(object)) { + var i = -1, n = object.length, o; + if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); + } else { + for (var key in object) map.set(key, object[key]); + } + return map; + }; + function d3_Map() { + this._ = Object.create(null); + } + var d3_map_proto = "__proto__", d3_map_zero = "\x00"; + d3_class(d3_Map, { + has: d3_map_has, + get: function(key) { + return this._[d3_map_escape(key)]; + }, + set: function(key, value) { + return this._[d3_map_escape(key)] = value; + }, + remove: d3_map_remove, + keys: d3_map_keys, + values: function() { + var values = []; + for (var key in this._) values.push(this._[key]); + return values; + }, + entries: function() { + var entries = []; + for (var key in this._) entries.push({ + key: d3_map_unescape(key), + value: this._[key] + }); + return entries; + }, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); + } + }); + function d3_map_escape(key) { + return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; + } + function d3_map_unescape(key) { + return (key += "")[0] === d3_map_zero ? key.slice(1) : key; + } + function d3_map_has(key) { + return d3_map_escape(key) in this._; + } + function d3_map_remove(key) { + return (key = d3_map_escape(key)) in this._ && delete this._[key]; + } + function d3_map_keys() { + var keys = []; + for (var key in this._) keys.push(d3_map_unescape(key)); + return keys; + } + function d3_map_size() { + var size = 0; + for (var key in this._) ++size; + return size; + } + function d3_map_empty() { + for (var key in this._) return false; + return true; + } + d3.nest = function() { + var nest = {}, keys = [], sortKeys = [], sortValues, rollup; + function map(mapType, array, depth) { + if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; + var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(object = array[i]))) { + values.push(object); + } else { + valuesByKey.set(keyValue, [ object ]); + } + } + if (mapType) { + object = mapType(); + setter = function(keyValue, values) { + object.set(keyValue, map(mapType, values, depth)); + }; + } else { + object = {}; + setter = function(keyValue, values) { + object[keyValue] = map(mapType, values, depth); + }; + } + valuesByKey.forEach(setter); + return object; + } + function entries(map, depth) { + if (depth >= keys.length) return map; + var array = [], sortKey = sortKeys[depth++]; + map.forEach(function(key, keyMap) { + array.push({ + key: key, + values: entries(keyMap, depth) + }); + }); + return sortKey ? array.sort(function(a, b) { + return sortKey(a.key, b.key); + }) : array; + } + nest.map = function(array, mapType) { + return map(mapType, array, 0); + }; + nest.entries = function(array) { + return entries(map(d3.map, array, 0), 0); + }; + nest.key = function(d) { + keys.push(d); + return nest; + }; + nest.sortKeys = function(order) { + sortKeys[keys.length - 1] = order; + return nest; + }; + nest.sortValues = function(order) { + sortValues = order; + return nest; + }; + nest.rollup = function(f) { + rollup = f; + return nest; + }; + return nest; + }; + d3.set = function(array) { + var set = new d3_Set(); + if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); + return set; + }; + function d3_Set() { + this._ = Object.create(null); + } + d3_class(d3_Set, { + has: d3_map_has, + add: function(key) { + this._[d3_map_escape(key += "")] = true; + return key; + }, + remove: d3_map_remove, + values: d3_map_keys, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key)); + } + }); + d3.behavior = {}; + function d3_identity(d) { + return d; + } + d3.rebind = function(target, source) { + var i = 1, n = arguments.length, method; + while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); + return target; + }; + function d3_rebind(target, source, method) { + return function() { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; + } + function d3_vendorSymbol(object, name) { + if (name in object) return name; + name = name.charAt(0).toUpperCase() + name.slice(1); + for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { + var prefixName = d3_vendorPrefixes[i] + name; + if (prefixName in object) return prefixName; + } + } + var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; + function d3_noop() {} + d3.dispatch = function() { + var dispatch = new d3_dispatch(), i = -1, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + return dispatch; + }; + function d3_dispatch() {} + d3_dispatch.prototype.on = function(type, listener) { + var i = type.indexOf("."), name = ""; + if (i >= 0) { + name = type.slice(i + 1); + type = type.slice(0, i); + } + if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); + if (arguments.length === 2) { + if (listener == null) for (type in this) { + if (this.hasOwnProperty(type)) this[type].on(name, null); + } + return this; + } + }; + function d3_dispatch_event(dispatch) { + var listeners = [], listenerByName = new d3_Map(); + function event() { + var z = listeners, i = -1, n = z.length, l; + while (++i < n) if (l = z[i].on) l.apply(this, arguments); + return dispatch; + } + event.on = function(name, listener) { + var l = listenerByName.get(name), i; + if (arguments.length < 2) return l && l.on; + if (l) { + l.on = null; + listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); + listenerByName.remove(name); + } + if (listener) listeners.push(listenerByName.set(name, { + on: listener + })); + return dispatch; + }; + return event; + } + d3.event = null; + function d3_eventPreventDefault() { + d3.event.preventDefault(); + } + function d3_eventSource() { + var e = d3.event, s; + while (s = e.sourceEvent) e = s; + return e; + } + function d3_eventDispatch(target) { + var dispatch = new d3_dispatch(), i = 0, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + dispatch.of = function(thiz, argumentz) { + return function(e1) { + try { + var e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + return dispatch; + } + d3.requote = function(s) { + return s.replace(d3_requote_re, "\\$&"); + }; + var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + var d3_subclass = {}.__proto__ ? function(object, prototype) { + object.__proto__ = prototype; + } : function(object, prototype) { + for (var property in prototype) object[property] = prototype[property]; + }; + function d3_selection(groups) { + d3_subclass(groups, d3_selectionPrototype); + return groups; + } + var d3_select = function(s, n) { + return n.querySelector(s); + }, d3_selectAll = function(s, n) { + return n.querySelectorAll(s); + }, d3_selectMatches = function(n, s) { + var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; + d3_selectMatches = function(n, s) { + return d3_selectMatcher.call(n, s); + }; + return d3_selectMatches(n, s); + }; + if (typeof Sizzle === "function") { + d3_select = function(s, n) { + return Sizzle(s, n)[0] || null; + }; + d3_selectAll = Sizzle; + d3_selectMatches = Sizzle.matchesSelector; + } + d3.selection = function() { + return d3.select(d3_document.documentElement); + }; + var d3_selectionPrototype = d3.selection.prototype = []; + d3_selectionPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, group, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(subnode = selector.call(node, node.__data__, i, j)); + if (subnode && "__data__" in node) subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selector(selector) { + return typeof selector === "function" ? selector : function() { + return d3_select(selector, this); + }; + } + d3_selectionPrototype.selectAll = function(selector) { + var subgroups = [], subgroup, node; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); + subgroup.parentNode = node; + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selectorAll(selector) { + return typeof selector === "function" ? selector : function() { + return d3_selectAll(selector, this); + }; + } + var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; + var d3_nsPrefix = { + svg: "http://www.w3.org/2000/svg", + xhtml: d3_nsXhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: d3_nsPrefix, + qualify: function(name) { + var i = name.indexOf(":"), prefix = name; + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return d3_nsPrefix.hasOwnProperty(prefix) ? { + space: d3_nsPrefix[prefix], + local: name + } : name; + } + }; + d3_selectionPrototype.attr = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(); + name = d3.ns.qualify(name); + return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); + } + for (value in name) this.each(d3_selection_attr(value, name[value])); + return this; + } + return this.each(d3_selection_attr(name, value)); + }; + function d3_selection_attr(name, value) { + name = d3.ns.qualify(name); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrConstant() { + this.setAttribute(name, value); + } + function attrConstantNS() { + this.setAttributeNS(name.space, name.local, value); + } + function attrFunction() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); + } + function attrFunctionNS() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); + } + return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; + } + function d3_collapse(s) { + return s.trim().replace(/\s+/g, " "); + } + d3_selectionPrototype.classed = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; + if (value = node.classList) { + while (++i < n) if (!value.contains(name[i])) return false; + } else { + value = node.getAttribute("class"); + while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; + } + return true; + } + for (value in name) this.each(d3_selection_classed(value, name[value])); + return this; + } + return this.each(d3_selection_classed(name, value)); + }; + function d3_selection_classedRe(name) { + return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); + } + function d3_selection_classes(name) { + return (name + "").trim().split(/^|\s+/); + } + function d3_selection_classed(name, value) { + name = d3_selection_classes(name).map(d3_selection_classedName); + var n = name.length; + function classedConstant() { + var i = -1; + while (++i < n) name[i](this, value); + } + function classedFunction() { + var i = -1, x = value.apply(this, arguments); + while (++i < n) name[i](this, x); + } + return typeof value === "function" ? classedFunction : classedConstant; + } + function d3_selection_classedName(name) { + var re = d3_selection_classedRe(name); + return function(node, value) { + if (c = node.classList) return value ? c.add(name) : c.remove(name); + var c = node.getAttribute("class") || ""; + if (value) { + re.lastIndex = 0; + if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); + } else { + node.setAttribute("class", d3_collapse(c.replace(re, " "))); + } + }; + } + d3_selectionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); + return this; + } + if (n < 2) { + var node = this.node(); + return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); + } + priority = ""; + } + return this.each(d3_selection_style(name, value, priority)); + }; + function d3_selection_style(name, value, priority) { + function styleNull() { + this.style.removeProperty(name); + } + function styleConstant() { + this.style.setProperty(name, value, priority); + } + function styleFunction() { + var x = value.apply(this, arguments); + if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); + } + return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; + } + d3_selectionPrototype.property = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") return this.node()[name]; + for (value in name) this.each(d3_selection_property(value, name[value])); + return this; + } + return this.each(d3_selection_property(name, value)); + }; + function d3_selection_property(name, value) { + function propertyNull() { + delete this[name]; + } + function propertyConstant() { + this[name] = value; + } + function propertyFunction() { + var x = value.apply(this, arguments); + if (x == null) delete this[name]; else this[name] = x; + } + return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; + } + d3_selectionPrototype.text = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + } : value == null ? function() { + this.textContent = ""; + } : function() { + this.textContent = value; + }) : this.node().textContent; + }; + d3_selectionPrototype.html = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + } : value == null ? function() { + this.innerHTML = ""; + } : function() { + this.innerHTML = value; + }) : this.node().innerHTML; + }; + d3_selectionPrototype.append = function(name) { + name = d3_selection_creator(name); + return this.select(function() { + return this.appendChild(name.apply(this, arguments)); + }); + }; + function d3_selection_creator(name) { + function create() { + var document = this.ownerDocument, namespace = this.namespaceURI; + return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); + } + function createNS() { + return this.ownerDocument.createElementNS(name.space, name.local); + } + return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; + } + d3_selectionPrototype.insert = function(name, before) { + name = d3_selection_creator(name); + before = d3_selection_selector(before); + return this.select(function() { + return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); + }); + }; + d3_selectionPrototype.remove = function() { + return this.each(d3_selectionRemove); + }; + function d3_selectionRemove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + } + d3_selectionPrototype.data = function(value, key) { + var i = -1, n = this.length, group, node; + if (!arguments.length) { + value = new Array(n = (group = this[0]).length); + while (++i < n) { + if (node = group[i]) { + value[i] = node.__data__; + } + } + return value; + } + function bind(group, groupData) { + var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; + if (key) { + var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; + for (i = -1; ++i < n; ) { + if (node = group[i]) { + if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { + exitNodes[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + keyValues[i] = keyValue; + } + } + for (i = -1; ++i < m; ) { + if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { + enterNodes[i] = d3_selection_dataNode(nodeData); + } else if (node !== true) { + updateNodes[i] = node; + node.__data__ = nodeData; + } + nodeByKeyValue.set(keyValue, true); + } + for (i = -1; ++i < n; ) { + if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { + exitNodes[i] = group[i]; + } + } + } else { + for (i = -1; ++i < n0; ) { + node = group[i]; + nodeData = groupData[i]; + if (node) { + node.__data__ = nodeData; + updateNodes[i] = node; + } else { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + } + for (;i < m; ++i) { + enterNodes[i] = d3_selection_dataNode(groupData[i]); + } + for (;i < n; ++i) { + exitNodes[i] = group[i]; + } + } + enterNodes.update = updateNodes; + enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; + enter.push(enterNodes); + update.push(updateNodes); + exit.push(exitNodes); + } + var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); + if (typeof value === "function") { + while (++i < n) { + bind(group = this[i], value.call(group, group.parentNode.__data__, i)); + } + } else { + while (++i < n) { + bind(group = this[i], value); + } + } + update.enter = function() { + return enter; + }; + update.exit = function() { + return exit; + }; + return update; + }; + function d3_selection_dataNode(data) { + return { + __data__: data + }; + } + d3_selectionPrototype.datum = function(value) { + return arguments.length ? this.property("__data__", value) : this.property("__data__"); + }; + d3_selectionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_filter(selector) { + return function() { + return d3_selectMatches(this, selector); + }; + } + d3_selectionPrototype.order = function() { + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + }; + d3_selectionPrototype.sort = function(comparator) { + comparator = d3_selection_sortComparator.apply(this, arguments); + for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); + return this.order(); + }; + function d3_selection_sortComparator(comparator) { + if (!arguments.length) comparator = d3_ascending; + return function(a, b) { + return a && b ? comparator(a.__data__, b.__data__) : !a - !b; + }; + } + d3_selectionPrototype.each = function(callback) { + return d3_selection_each(this, function(node, i, j) { + callback.call(node, node.__data__, i, j); + }); + }; + function d3_selection_each(groups, callback) { + for (var j = 0, m = groups.length; j < m; j++) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { + if (node = group[i]) callback(node, i, j); + } + } + return groups; + } + d3_selectionPrototype.call = function(callback) { + var args = d3_array(arguments); + callback.apply(args[0] = this, args); + return this; + }; + d3_selectionPrototype.empty = function() { + return !this.node(); + }; + d3_selectionPrototype.node = function() { + for (var j = 0, m = this.length; j < m; j++) { + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + var node = group[i]; + if (node) return node; + } + } + return null; + }; + d3_selectionPrototype.size = function() { + var n = 0; + d3_selection_each(this, function() { + ++n; + }); + return n; + }; + function d3_selection_enter(selection) { + d3_subclass(selection, d3_selection_enterPrototype); + return selection; + } + var d3_selection_enterPrototype = []; + d3.selection.enter = d3_selection_enter; + d3.selection.enter.prototype = d3_selection_enterPrototype; + d3_selection_enterPrototype.append = d3_selectionPrototype.append; + d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; + d3_selection_enterPrototype.node = d3_selectionPrototype.node; + d3_selection_enterPrototype.call = d3_selectionPrototype.call; + d3_selection_enterPrototype.size = d3_selectionPrototype.size; + d3_selection_enterPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, upgroup, group, node; + for (var j = -1, m = this.length; ++j < m; ) { + upgroup = (group = this[j]).update; + subgroups.push(subgroup = []); + subgroup.parentNode = group.parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); + subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + d3_selection_enterPrototype.insert = function(name, before) { + if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); + return d3_selectionPrototype.insert.call(this, name, before); + }; + function d3_selection_enterInsertBefore(enter) { + var i0, j0; + return function(d, i, j) { + var group = enter[j].update, n = group.length, node; + if (j != j0) j0 = j, i0 = 0; + if (i >= i0) i0 = i + 1; + while (!(node = group[i0]) && ++i0 < n) ; + return node; + }; + } + d3.select = function(node) { + var group; + if (typeof node === "string") { + group = [ d3_select(node, d3_document) ]; + group.parentNode = d3_document.documentElement; + } else { + group = [ node ]; + group.parentNode = d3_documentElement(node); + } + return d3_selection([ group ]); + }; + d3.selectAll = function(nodes) { + var group; + if (typeof nodes === "string") { + group = d3_array(d3_selectAll(nodes, d3_document)); + group.parentNode = d3_document.documentElement; + } else { + group = d3_array(nodes); + group.parentNode = null; + } + return d3_selection([ group ]); + }; + d3_selectionPrototype.on = function(type, listener, capture) { + var n = arguments.length; + if (n < 3) { + if (typeof type !== "string") { + if (n < 2) listener = false; + for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); + return this; + } + if (n < 2) return (n = this.node()["__on" + type]) && n._; + capture = false; + } + return this.each(d3_selection_on(type, listener, capture)); + }; + function d3_selection_on(type, listener, capture) { + var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; + if (i > 0) type = type.slice(0, i); + var filter = d3_selection_onFilters.get(type); + if (filter) type = filter, wrap = d3_selection_onFilter; + function onRemove() { + var l = this[name]; + if (l) { + this.removeEventListener(type, l, l.$); + delete this[name]; + } + } + function onAdd() { + var l = wrap(listener, d3_array(arguments)); + onRemove.call(this); + this.addEventListener(type, this[name] = l, l.$ = capture); + l._ = listener; + } + function removeAll() { + var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; + for (var name in this) { + if (match = name.match(re)) { + var l = this[name]; + this.removeEventListener(match[1], l, l.$); + delete this[name]; + } + } + } + return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; + } + var d3_selection_onFilters = d3.map({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }); + if (d3_document) { + d3_selection_onFilters.forEach(function(k) { + if ("on" + k in d3_document) d3_selection_onFilters.remove(k); + }); + } + function d3_selection_onListener(listener, argumentz) { + return function(e) { + var o = d3.event; + d3.event = e; + argumentz[0] = this.__data__; + try { + listener.apply(this, argumentz); + } finally { + d3.event = o; + } + }; + } + function d3_selection_onFilter(listener, argumentz) { + var l = d3_selection_onListener(listener, argumentz); + return function(e) { + var target = this, related = e.relatedTarget; + if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { + l.call(target, e); + } + }; + } + var d3_event_dragSelect, d3_event_dragId = 0; + function d3_event_dragSuppress(node) { + var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); + if (d3_event_dragSelect == null) { + d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); + } + if (d3_event_dragSelect) { + var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; + style[d3_event_dragSelect] = "none"; + } + return function(suppressClick) { + w.on(name, null); + if (d3_event_dragSelect) style[d3_event_dragSelect] = select; + if (suppressClick) { + var off = function() { + w.on(click, null); + }; + w.on(click, function() { + d3_eventPreventDefault(); + off(); + }, true); + setTimeout(off, 0); + } + }; + } + d3.mouse = function(container) { + return d3_mousePoint(container, d3_eventSource()); + }; + var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; + function d3_mousePoint(container, e) { + if (e.changedTouches) e = e.changedTouches[0]; + var svg = container.ownerSVGElement || container; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + if (d3_mouse_bug44083 < 0) { + var window = d3_window(container); + if (window.scrollX || window.scrollY) { + svg = d3.select("body").append("svg").style({ + position: "absolute", + top: 0, + left: 0, + margin: 0, + padding: 0, + border: "none" + }, "important"); + var ctm = svg[0][0].getScreenCTM(); + d3_mouse_bug44083 = !(ctm.f || ctm.e); + svg.remove(); + } + } + if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, + point.y = e.clientY; + point = point.matrixTransform(container.getScreenCTM().inverse()); + return [ point.x, point.y ]; + } + var rect = container.getBoundingClientRect(); + return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; + } + d3.touch = function(container, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; + if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return d3_mousePoint(container, touch); + } + } + }; + d3.behavior.drag = function() { + var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); + function drag() { + this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); + } + function dragstart(id, position, subject, move, end) { + return function() { + var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); + if (origin) { + dragOffset = origin.apply(that, arguments); + dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; + } else { + dragOffset = [ 0, 0 ]; + } + dispatch({ + type: "dragstart" + }); + function moved() { + var position1 = position(parent, dragId), dx, dy; + if (!position1) return; + dx = position1[0] - position0[0]; + dy = position1[1] - position0[1]; + dragged |= dx | dy; + position0 = position1; + dispatch({ + type: "drag", + x: position1[0] + dragOffset[0], + y: position1[1] + dragOffset[1], + dx: dx, + dy: dy + }); + } + function ended() { + if (!position(parent, dragId)) return; + dragSubject.on(move + dragName, null).on(end + dragName, null); + dragRestore(dragged); + dispatch({ + type: "dragend" + }); + } + }; + } + drag.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return drag; + }; + return d3.rebind(drag, event, "on"); + }; + function d3_behavior_dragTouchId() { + return d3.event.changedTouches[0].identifier; + } + d3.touches = function(container, touches) { + if (arguments.length < 2) touches = d3_eventSource().touches; + return touches ? d3_array(touches).map(function(touch) { + var point = d3_mousePoint(container, touch); + point.identifier = touch.identifier; + return point; + }) : []; + }; + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; + function d3_sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function d3_cross2d(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + function d3_acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); + } + function d3_asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); + } + function d3_sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + function d3_cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + function d3_tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + function d3_haversin(x) { + return (x = Math.sin(x / 2)) * x; + } + var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; + d3.interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; + if (d2 < ε2) { + S = Math.log(w1 / w0) / ρ; + i = function(t) { + return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; + }; + } else { + var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / ρ; + i = function(t) { + var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); + return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; + }; + } + i.duration = S * 1e3; + return i; + }; + d3.behavior.zoom = function() { + var view = { + x: 0, + y: 0, + k: 1 + }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; + if (!d3_behavior_zoomWheel) { + d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); + }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return d3.event.wheelDelta; + }, "mousewheel") : (d3_behavior_zoomDelta = function() { + return -d3.event.detail; + }, "MozMousePixelScroll"); + } + function zoom(g) { + g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); + } + zoom.event = function(g) { + g.each(function() { + var dispatch = event.of(this, arguments), view1 = view; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.zoom", function() { + view = this.__chart__ || { + x: 0, + y: 0, + k: 1 + }; + zoomstarted(dispatch); + }).tween("zoom:zoom", function() { + var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); + return function(t) { + var l = i(t), k = dx / l[2]; + this.__chart__ = view = { + x: cx - l[0] * k, + y: cy - l[1] * k, + k: k + }; + zoomed(dispatch); + }; + }).each("interrupt.zoom", function() { + zoomended(dispatch); + }).each("end.zoom", function() { + zoomended(dispatch); + }); + } else { + this.__chart__ = view; + zoomstarted(dispatch); + zoomed(dispatch); + zoomended(dispatch); + } + }); + }; + zoom.translate = function(_) { + if (!arguments.length) return [ view.x, view.y ]; + view = { + x: +_[0], + y: +_[1], + k: view.k + }; + rescale(); + return zoom; + }; + zoom.scale = function(_) { + if (!arguments.length) return view.k; + view = { + x: view.x, + y: view.y, + k: null + }; + scaleTo(+_); + rescale(); + return zoom; + }; + zoom.scaleExtent = function(_) { + if (!arguments.length) return scaleExtent; + scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; + return zoom; + }; + zoom.center = function(_) { + if (!arguments.length) return center; + center = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.size = function(_) { + if (!arguments.length) return size; + size = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.duration = function(_) { + if (!arguments.length) return duration; + duration = +_; + return zoom; + }; + zoom.x = function(z) { + if (!arguments.length) return x1; + x1 = z; + x0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + zoom.y = function(z) { + if (!arguments.length) return y1; + y1 = z; + y0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + function location(p) { + return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; + } + function point(l) { + return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; + } + function scaleTo(s) { + view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); + } + function translateTo(p, l) { + l = point(l); + view.x += p[0] - l[0]; + view.y += p[1] - l[1]; + } + function zoomTo(that, p, l, k) { + that.__chart__ = { + x: view.x, + y: view.y, + k: view.k + }; + scaleTo(Math.pow(2, k)); + translateTo(center0 = p, l); + that = d3.select(that); + if (duration > 0) that = that.transition().duration(duration); + that.call(zoom.event); + } + function rescale() { + if (x1) x1.domain(x0.range().map(function(x) { + return (x - view.x) / view.k; + }).map(x0.invert)); + if (y1) y1.domain(y0.range().map(function(y) { + return (y - view.y) / view.k; + }).map(y0.invert)); + } + function zoomstarted(dispatch) { + if (!zooming++) dispatch({ + type: "zoomstart" + }); + } + function zoomed(dispatch) { + rescale(); + dispatch({ + type: "zoom", + scale: view.k, + translate: [ view.x, view.y ] + }); + } + function zoomended(dispatch) { + if (!--zooming) dispatch({ + type: "zoomend" + }), center0 = null; + } + function mousedowned() { + var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); + d3_selection_interrupt.call(that); + zoomstarted(dispatch); + function moved() { + dragged = 1; + translateTo(d3.mouse(that), location0); + zoomed(dispatch); + } + function ended() { + subject.on(mousemove, null).on(mouseup, null); + dragRestore(dragged); + zoomended(dispatch); + } + } + function touchstarted() { + var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); + started(); + zoomstarted(dispatch); + subject.on(mousedown, null).on(touchstart, started); + function relocate() { + var touches = d3.touches(that); + scale0 = view.k; + touches.forEach(function(t) { + if (t.identifier in locations0) locations0[t.identifier] = location(t); + }); + return touches; + } + function started() { + var target = d3.event.target; + d3.select(target).on(touchmove, moved).on(touchend, ended); + targets.push(target); + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + locations0[changed[i].identifier] = null; + } + var touches = relocate(), now = Date.now(); + if (touches.length === 1) { + if (now - touchtime < 500) { + var p = touches[0]; + zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); + d3_eventPreventDefault(); + } + touchtime = now; + } else if (touches.length > 1) { + var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; + distance0 = dx * dx + dy * dy; + } + } + function moved() { + var touches = d3.touches(that), p0, l0, p1, l1; + d3_selection_interrupt.call(that); + for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { + p1 = touches[i]; + if (l1 = locations0[p1.identifier]) { + if (l0) break; + p0 = p1, l0 = l1; + } + } + if (l1) { + var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); + p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; + l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; + scaleTo(scale1 * scale0); + } + touchtime = null; + translateTo(p0, l0); + zoomed(dispatch); + } + function ended() { + if (d3.event.touches.length) { + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + delete locations0[changed[i].identifier]; + } + for (var identifier in locations0) { + return void relocate(); + } + } + d3.selectAll(targets).on(zoomName, null); + subject.on(mousedown, mousedowned).on(touchstart, touchstarted); + dragRestore(); + zoomended(dispatch); + } + } + function mousewheeled() { + var dispatch = event.of(this, arguments); + if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), + translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); + mousewheelTimer = setTimeout(function() { + mousewheelTimer = null; + zoomended(dispatch); + }, 50); + d3_eventPreventDefault(); + scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); + translateTo(center0, translate0); + zoomed(dispatch); + } + function dblclicked() { + var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; + zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); + } + return d3.rebind(zoom, event, "on"); + }; + var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; + d3.color = d3_color; + function d3_color() {} + d3_color.prototype.toString = function() { + return this.rgb() + ""; + }; + d3.hsl = d3_hsl; + function d3_hsl(h, s, l) { + return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); + } + var d3_hslPrototype = d3_hsl.prototype = new d3_color(); + d3_hslPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, this.l / k); + }; + d3_hslPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, k * this.l); + }; + d3_hslPrototype.rgb = function() { + return d3_hsl_rgb(this.h, this.s, this.l); + }; + function d3_hsl_rgb(h, s, l) { + var m1, m2; + h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; + s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; + l = l < 0 ? 0 : l > 1 ? 1 : l; + m2 = l <= .5 ? l * (1 + s) : l + s - l * s; + m1 = 2 * l - m2; + function v(h) { + if (h > 360) h -= 360; else if (h < 0) h += 360; + if (h < 60) return m1 + (m2 - m1) * h / 60; + if (h < 180) return m2; + if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; + return m1; + } + function vv(h) { + return Math.round(v(h) * 255); + } + return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); + } + d3.hcl = d3_hcl; + function d3_hcl(h, c, l) { + return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); + } + var d3_hclPrototype = d3_hcl.prototype = new d3_color(); + d3_hclPrototype.brighter = function(k) { + return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.darker = function(k) { + return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.rgb = function() { + return d3_hcl_lab(this.h, this.c, this.l).rgb(); + }; + function d3_hcl_lab(h, c, l) { + if (isNaN(h)) h = 0; + if (isNaN(c)) c = 0; + return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); + } + d3.lab = d3_lab; + function d3_lab(l, a, b) { + return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); + } + var d3_lab_K = 18; + var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; + var d3_labPrototype = d3_lab.prototype = new d3_color(); + d3_labPrototype.brighter = function(k) { + return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.darker = function(k) { + return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.rgb = function() { + return d3_lab_rgb(this.l, this.a, this.b); + }; + function d3_lab_rgb(l, a, b) { + var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; + x = d3_lab_xyz(x) * d3_lab_X; + y = d3_lab_xyz(y) * d3_lab_Y; + z = d3_lab_xyz(z) * d3_lab_Z; + return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); + } + function d3_lab_hcl(l, a, b) { + return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); + } + function d3_lab_xyz(x) { + return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; + } + function d3_xyz_lab(x) { + return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; + } + function d3_xyz_rgb(r) { + return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); + } + d3.rgb = d3_rgb; + function d3_rgb(r, g, b) { + return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); + } + function d3_rgbNumber(value) { + return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); + } + function d3_rgbString(value) { + return d3_rgbNumber(value) + ""; + } + var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); + d3_rgbPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + var r = this.r, g = this.g, b = this.b, i = 30; + if (!r && !g && !b) return new d3_rgb(i, i, i); + if (r && r < i) r = i; + if (g && g < i) g = i; + if (b && b < i) b = i; + return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + }; + d3_rgbPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_rgb(k * this.r, k * this.g, k * this.b); + }; + d3_rgbPrototype.hsl = function() { + return d3_rgb_hsl(this.r, this.g, this.b); + }; + d3_rgbPrototype.toString = function() { + return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + }; + function d3_rgb_hex(v) { + return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); + } + function d3_rgb_parse(format, rgb, hsl) { + var r = 0, g = 0, b = 0, m1, m2, color; + m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); + if (m1) { + m2 = m1[2].split(","); + switch (m1[1]) { + case "hsl": + { + return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); + } + + case "rgb": + { + return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); + } + } + } + if (color = d3_rgb_names.get(format)) { + return rgb(color.r, color.g, color.b); + } + if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { + if (format.length === 4) { + r = (color & 3840) >> 4; + r = r >> 4 | r; + g = color & 240; + g = g >> 4 | g; + b = color & 15; + b = b << 4 | b; + } else if (format.length === 7) { + r = (color & 16711680) >> 16; + g = (color & 65280) >> 8; + b = color & 255; + } + } + return rgb(r, g, b); + } + function d3_rgb_hsl(r, g, b) { + var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; + if (d) { + s = l < .5 ? d / (max + min) : d / (2 - max - min); + if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; + h *= 60; + } else { + h = NaN; + s = l > 0 && l < 1 ? 0 : h; + } + return new d3_hsl(h, s, l); + } + function d3_rgb_lab(r, g, b) { + r = d3_rgb_xyz(r); + g = d3_rgb_xyz(g); + b = d3_rgb_xyz(b); + var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); + return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); + } + function d3_rgb_xyz(r) { + return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); + } + function d3_rgb_parseNumber(c) { + var f = parseFloat(c); + return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; + } + var d3_rgb_names = d3.map({ + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }); + d3_rgb_names.forEach(function(key, value) { + d3_rgb_names.set(key, d3_rgbNumber(value)); + }); + function d3_functor(v) { + return typeof v === "function" ? v : function() { + return v; + }; + } + d3.functor = d3_functor; + d3.xhr = d3_xhrType(d3_identity); + function d3_xhrType(response) { + return function(url, mimeType, callback) { + if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, + mimeType = null; + return d3_xhr(url, mimeType, response, callback); + }; + } + function d3_xhr(url, mimeType, response, callback) { + var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; + if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); + "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { + request.readyState > 3 && respond(); + }; + function respond() { + var status = request.status, result; + if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { + try { + result = response.call(xhr, request); + } catch (e) { + dispatch.error.call(xhr, e); + return; + } + dispatch.load.call(xhr, result); + } else { + dispatch.error.call(xhr, request); + } + } + request.onprogress = function(event) { + var o = d3.event; + d3.event = event; + try { + dispatch.progress.call(xhr, request); + } finally { + d3.event = o; + } + }; + xhr.header = function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers[name]; + if (value == null) delete headers[name]; else headers[name] = value + ""; + return xhr; + }; + xhr.mimeType = function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return xhr; + }; + xhr.responseType = function(value) { + if (!arguments.length) return responseType; + responseType = value; + return xhr; + }; + xhr.response = function(value) { + response = value; + return xhr; + }; + [ "get", "post" ].forEach(function(method) { + xhr[method] = function() { + return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); + }; + }); + xhr.send = function(method, data, callback) { + if (arguments.length === 2 && typeof data === "function") callback = data, data = null; + request.open(method, url, true); + if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; + if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); + if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); + if (responseType != null) request.responseType = responseType; + if (callback != null) xhr.on("error", callback).on("load", function(request) { + callback(null, request); + }); + dispatch.beforesend.call(xhr, request); + request.send(data == null ? null : data); + return xhr; + }; + xhr.abort = function() { + request.abort(); + return xhr; + }; + d3.rebind(xhr, dispatch, "on"); + return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); + } + function d3_xhr_fixCallback(callback) { + return callback.length === 1 ? function(error, request) { + callback(error == null ? request : null); + } : callback; + } + function d3_xhrHasResponse(request) { + var type = request.responseType; + return type && type !== "text" ? request.response : request.responseText; + } + d3.dsv = function(delimiter, mimeType) { + var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); + function dsv(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); + xhr.row = function(_) { + return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; + }; + return xhr; + } + function response(request) { + return dsv.parse(request.responseText); + } + function typedResponse(f) { + return function(request) { + return dsv.parse(request.responseText, f); + }; + } + dsv.parse = function(text, f) { + var o; + return dsv.parseRows(text, function(row, i) { + if (o) return o(row, i - 1); + var a = new Function("d", "return {" + row.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); + o = f ? function(row, i) { + return f(a(row), i); + } : a; + }); + }; + dsv.parseRows = function(text, f) { + var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; + function token() { + if (I >= N) return EOF; + if (eol) return eol = false, EOL; + var j = I; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; + } + } + I = i + 2; + var c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; + } + return text.slice(j + 1, i).replace(/""/g, '"'); + } + while (I < N) { + var c = text.charCodeAt(I++), k = 1; + if (c === 10) eol = true; else if (c === 13) { + eol = true; + if (text.charCodeAt(I) === 10) ++I, ++k; + } else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } + return text.slice(j); + } + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); + } + if (f && (a = f(a, n++)) == null) continue; + rows.push(a); + } + return rows; + }; + dsv.format = function(rows) { + if (Array.isArray(rows[0])) return dsv.formatRows(rows); + var fieldSet = new d3_Set(), fields = []; + rows.forEach(function(row) { + for (var field in row) { + if (!fieldSet.has(field)) { + fields.push(fieldSet.add(field)); + } + } + }); + return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { + return fields.map(function(field) { + return formatValue(row[field]); + }).join(delimiter); + })).join("\n"); + }; + dsv.formatRows = function(rows) { + return rows.map(formatRow).join("\n"); + }; + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + function formatValue(text) { + return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; + } + return dsv; + }; + d3.csv = d3.dsv(",", "text/csv"); + d3.tsv = d3.dsv(" ", "text/tab-separated-values"); + var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { + setTimeout(callback, 17); + }; + d3.timer = function() { + d3_timer.apply(this, arguments); + }; + function d3_timer(callback, delay, then) { + var n = arguments.length; + if (n < 2) delay = 0; + if (n < 3) then = Date.now(); + var time = then + delay, timer = { + c: callback, + t: time, + n: null + }; + if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; + d3_timer_queueTail = timer; + if (!d3_timer_interval) { + d3_timer_timeout = clearTimeout(d3_timer_timeout); + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + return timer; + } + function d3_timer_step() { + var now = d3_timer_mark(), delay = d3_timer_sweep() - now; + if (delay > 24) { + if (isFinite(delay)) { + clearTimeout(d3_timer_timeout); + d3_timer_timeout = setTimeout(d3_timer_step, delay); + } + d3_timer_interval = 0; + } else { + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + } + d3.timer.flush = function() { + d3_timer_mark(); + d3_timer_sweep(); + }; + function d3_timer_mark() { + var now = Date.now(), timer = d3_timer_queueHead; + while (timer) { + if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; + timer = timer.n; + } + return now; + } + function d3_timer_sweep() { + var t0, t1 = d3_timer_queueHead, time = Infinity; + while (t1) { + if (t1.c) { + if (t1.t < time) time = t1.t; + t1 = (t0 = t1).n; + } else { + t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; + } + } + d3_timer_queueTail = t0; + return time; + } + function d3_format_precision(x, p) { + return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); + } + d3.round = function(x, n) { + return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); + }; + var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); + d3.formatPrefix = function(value, precision) { + var i = 0; + if (value = +value) { + if (value < 0) value *= -1; + if (precision) value = d3.round(value, d3_format_precision(value, precision)); + i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); + i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); + } + return d3_formatPrefixes[8 + i / 3]; + }; + function d3_formatPrefix(d, i) { + var k = Math.pow(10, abs(8 - i) * 3); + return { + scale: i > 8 ? function(d) { + return d / k; + } : function(d) { + return d * k; + }, + symbol: d + }; + } + function d3_locale_numberFormat(locale) { + var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { + var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = locale_grouping[j = (j + 1) % locale_grouping.length]; + } + return t.reverse().join(locale_thousands); + } : d3_identity; + return function(specifier) { + var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; + if (precision) precision = +precision.substring(1); + if (zfill || fill === "0" && align === "=") { + zfill = fill = "0"; + align = "="; + } + switch (type) { + case "n": + comma = true; + type = "g"; + break; + + case "%": + scale = 100; + suffix = "%"; + type = "f"; + break; + + case "p": + scale = 100; + suffix = "%"; + type = "r"; + break; + + case "b": + case "o": + case "x": + case "X": + if (symbol === "#") prefix = "0" + type.toLowerCase(); + + case "c": + exponent = false; + + case "d": + integer = true; + precision = 0; + break; + + case "s": + scale = -1; + type = "r"; + break; + } + if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; + if (type == "r" && !precision) type = "g"; + if (precision != null) { + if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); + } + type = d3_format_types.get(type) || d3_format_typeDefault; + var zcomma = zfill && comma; + return function(value) { + var fullSuffix = suffix; + if (integer && value % 1) return ""; + var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; + if (scale < 0) { + var unit = d3.formatPrefix(value, precision); + value = unit.scale(value); + fullSuffix = unit.symbol + suffix; + } else { + value *= scale; + } + value = type(value, precision); + var i = value.lastIndexOf("."), before, after; + if (i < 0) { + var j = exponent ? value.lastIndexOf("e") : -1; + if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); + } else { + before = value.substring(0, i); + after = locale_decimal + value.substring(i + 1); + } + if (!zfill && comma) before = formatGroup(before, Infinity); + var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; + if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); + negative += prefix; + value = before + after; + return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; + }; + }; + } + var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; + var d3_format_types = d3.map({ + b: function(x) { + return x.toString(2); + }, + c: function(x) { + return String.fromCharCode(x); + }, + o: function(x) { + return x.toString(8); + }, + x: function(x) { + return x.toString(16); + }, + X: function(x) { + return x.toString(16).toUpperCase(); + }, + g: function(x, p) { + return x.toPrecision(p); + }, + e: function(x, p) { + return x.toExponential(p); + }, + f: function(x, p) { + return x.toFixed(p); + }, + r: function(x, p) { + return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); + } + }); + function d3_format_typeDefault(x) { + return x + ""; + } + var d3_time = d3.time = {}, d3_date = Date; + function d3_date_utc() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); + } + d3_date_utc.prototype = { + getDate: function() { + return this._.getUTCDate(); + }, + getDay: function() { + return this._.getUTCDay(); + }, + getFullYear: function() { + return this._.getUTCFullYear(); + }, + getHours: function() { + return this._.getUTCHours(); + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds(); + }, + getMinutes: function() { + return this._.getUTCMinutes(); + }, + getMonth: function() { + return this._.getUTCMonth(); + }, + getSeconds: function() { + return this._.getUTCSeconds(); + }, + getTime: function() { + return this._.getTime(); + }, + getTimezoneOffset: function() { + return 0; + }, + valueOf: function() { + return this._.valueOf(); + }, + setDate: function() { + d3_time_prototype.setUTCDate.apply(this._, arguments); + }, + setDay: function() { + d3_time_prototype.setUTCDay.apply(this._, arguments); + }, + setFullYear: function() { + d3_time_prototype.setUTCFullYear.apply(this._, arguments); + }, + setHours: function() { + d3_time_prototype.setUTCHours.apply(this._, arguments); + }, + setMilliseconds: function() { + d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); + }, + setMinutes: function() { + d3_time_prototype.setUTCMinutes.apply(this._, arguments); + }, + setMonth: function() { + d3_time_prototype.setUTCMonth.apply(this._, arguments); + }, + setSeconds: function() { + d3_time_prototype.setUTCSeconds.apply(this._, arguments); + }, + setTime: function() { + d3_time_prototype.setTime.apply(this._, arguments); + } + }; + var d3_time_prototype = Date.prototype; + function d3_time_interval(local, step, number) { + function round(date) { + var d0 = local(date), d1 = offset(d0, 1); + return date - d0 < d1 - date ? d0 : d1; + } + function ceil(date) { + step(date = local(new d3_date(date - 1)), 1); + return date; + } + function offset(date, k) { + step(date = new d3_date(+date), k); + return date; + } + function range(t0, t1, dt) { + var time = ceil(t0), times = []; + if (dt > 1) { + while (time < t1) { + if (!(number(time) % dt)) times.push(new Date(+time)); + step(time, 1); + } + } else { + while (time < t1) times.push(new Date(+time)), step(time, 1); + } + return times; + } + function range_utc(t0, t1, dt) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = t0; + return range(utc, t1, dt); + } finally { + d3_date = Date; + } + } + local.floor = local; + local.round = round; + local.ceil = ceil; + local.offset = offset; + local.range = range; + var utc = local.utc = d3_time_interval_utc(local); + utc.floor = utc; + utc.round = d3_time_interval_utc(round); + utc.ceil = d3_time_interval_utc(ceil); + utc.offset = d3_time_interval_utc(offset); + utc.range = range_utc; + return local; + } + function d3_time_interval_utc(method) { + return function(date, k) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = date; + return method(utc, k)._; + } finally { + d3_date = Date; + } + }; + } + d3_time.year = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setMonth(0, 1); + return date; + }, function(date, offset) { + date.setFullYear(date.getFullYear() + offset); + }, function(date) { + return date.getFullYear(); + }); + d3_time.years = d3_time.year.range; + d3_time.years.utc = d3_time.year.utc.range; + d3_time.day = d3_time_interval(function(date) { + var day = new d3_date(2e3, 0); + day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + return day; + }, function(date, offset) { + date.setDate(date.getDate() + offset); + }, function(date) { + return date.getDate() - 1; + }); + d3_time.days = d3_time.day.range; + d3_time.days.utc = d3_time.day.utc.range; + d3_time.dayOfYear = function(date) { + var year = d3_time.year(date); + return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); + }; + [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { + i = 7 - i; + var interval = d3_time[day] = d3_time_interval(function(date) { + (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); + return date; + }, function(date, offset) { + date.setDate(date.getDate() + Math.floor(offset) * 7); + }, function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); + }); + d3_time[day + "s"] = interval.range; + d3_time[day + "s"].utc = interval.utc.range; + d3_time[day + "OfYear"] = function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); + }; + }); + d3_time.week = d3_time.sunday; + d3_time.weeks = d3_time.sunday.range; + d3_time.weeks.utc = d3_time.sunday.utc.range; + d3_time.weekOfYear = d3_time.sundayOfYear; + function d3_locale_timeFormat(locale) { + var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; + function d3_time_format(template) { + var n = template.length; + function format(date) { + var string = [], i = -1, j = 0, c, p, f; + while (++i < n) { + if (template.charCodeAt(i) === 37) { + string.push(template.slice(j, i)); + if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); + if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); + string.push(c); + j = i + 1; + } + } + string.push(template.slice(j, i)); + return string.join(""); + } + format.parse = function(string) { + var d = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0, + Z: null + }, i = d3_time_parse(d, template, string, 0); + if (i != string.length) return null; + if ("p" in d) d.H = d.H % 12 + d.p * 12; + var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); + if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + date.setFullYear(d.y, 0, 1); + date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); + } else date.setFullYear(d.y, d.m, d.d); + date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); + return localZ ? date._ : date; + }; + format.toString = function() { + return template; + }; + return format; + } + function d3_time_parse(date, template, string, j) { + var c, p, t, i = 0, n = template.length, m = string.length; + while (i < n) { + if (j >= m) return -1; + c = template.charCodeAt(i++); + if (c === 37) { + t = template.charAt(i++); + p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; + if (!p || (j = p(date, string, j)) < 0) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + return j; + } + d3_time_format.utc = function(template) { + var local = d3_time_format(template); + function format(date) { + try { + d3_date = d3_date_utc; + var utc = new d3_date(); + utc._ = date; + return local(utc); + } finally { + d3_date = Date; + } + } + format.parse = function(string) { + try { + d3_date = d3_date_utc; + var date = local.parse(string); + return date && date._; + } finally { + d3_date = Date; + } + }; + format.toString = local.toString; + return format; + }; + d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; + var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); + locale_periods.forEach(function(p, i) { + d3_time_periodLookup.set(p.toLowerCase(), i); + }); + var d3_time_formats = { + a: function(d) { + return locale_shortDays[d.getDay()]; + }, + A: function(d) { + return locale_days[d.getDay()]; + }, + b: function(d) { + return locale_shortMonths[d.getMonth()]; + }, + B: function(d) { + return locale_months[d.getMonth()]; + }, + c: d3_time_format(locale_dateTime), + d: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + e: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + H: function(d, p) { + return d3_time_formatPad(d.getHours(), p, 2); + }, + I: function(d, p) { + return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); + }, + j: function(d, p) { + return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); + }, + L: function(d, p) { + return d3_time_formatPad(d.getMilliseconds(), p, 3); + }, + m: function(d, p) { + return d3_time_formatPad(d.getMonth() + 1, p, 2); + }, + M: function(d, p) { + return d3_time_formatPad(d.getMinutes(), p, 2); + }, + p: function(d) { + return locale_periods[+(d.getHours() >= 12)]; + }, + S: function(d, p) { + return d3_time_formatPad(d.getSeconds(), p, 2); + }, + U: function(d, p) { + return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); + }, + w: function(d) { + return d.getDay(); + }, + W: function(d, p) { + return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); + }, + x: d3_time_format(locale_date), + X: d3_time_format(locale_time), + y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 100, p, 2); + }, + Y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); + }, + Z: d3_time_zone, + "%": function() { + return "%"; + } + }; + var d3_time_parsers = { + a: d3_time_parseWeekdayAbbrev, + A: d3_time_parseWeekday, + b: d3_time_parseMonthAbbrev, + B: d3_time_parseMonth, + c: d3_time_parseLocaleFull, + d: d3_time_parseDay, + e: d3_time_parseDay, + H: d3_time_parseHour24, + I: d3_time_parseHour24, + j: d3_time_parseDayOfYear, + L: d3_time_parseMilliseconds, + m: d3_time_parseMonthNumber, + M: d3_time_parseMinutes, + p: d3_time_parseAmPm, + S: d3_time_parseSeconds, + U: d3_time_parseWeekNumberSunday, + w: d3_time_parseWeekdayNumber, + W: d3_time_parseWeekNumberMonday, + x: d3_time_parseLocaleDate, + X: d3_time_parseLocaleTime, + y: d3_time_parseYear, + Y: d3_time_parseFullYear, + Z: d3_time_parseZone, + "%": d3_time_parseLiteralPercent + }; + function d3_time_parseWeekdayAbbrev(date, string, i) { + d3_time_dayAbbrevRe.lastIndex = 0; + var n = d3_time_dayAbbrevRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseWeekday(date, string, i) { + d3_time_dayRe.lastIndex = 0; + var n = d3_time_dayRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonthAbbrev(date, string, i) { + d3_time_monthAbbrevRe.lastIndex = 0; + var n = d3_time_monthAbbrevRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonth(date, string, i) { + d3_time_monthRe.lastIndex = 0; + var n = d3_time_monthRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseLocaleFull(date, string, i) { + return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + } + function d3_time_parseLocaleDate(date, string, i) { + return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + } + function d3_time_parseLocaleTime(date, string, i) { + return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + } + function d3_time_parseAmPm(date, string, i) { + var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); + return n == null ? -1 : (date.p = n, i); + } + return d3_time_format; + } + var d3_time_formatPads = { + "-": "", + _: " ", + "0": "0" + }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; + function d3_time_formatPad(value, fill, width) { + var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); + } + function d3_time_formatRe(names) { + return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); + } + function d3_time_formatLookup(names) { + var map = new d3_Map(), i = -1, n = names.length; + while (++i < n) map.set(names[i].toLowerCase(), i); + return map; + } + function d3_time_parseWeekdayNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 1)); + return n ? (date.w = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberSunday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.U = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberMonday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.W = +n[0], i + n[0].length) : -1; + } + function d3_time_parseFullYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 4)); + return n ? (date.y = +n[0], i + n[0].length) : -1; + } + function d3_time_parseYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; + } + function d3_time_parseZone(date, string, i) { + return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, + i + 5) : -1; + } + function d3_time_expandYear(d) { + return d + (d > 68 ? 1900 : 2e3); + } + function d3_time_parseMonthNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.m = n[0] - 1, i + n[0].length) : -1; + } + function d3_time_parseDay(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.d = +n[0], i + n[0].length) : -1; + } + function d3_time_parseDayOfYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.j = +n[0], i + n[0].length) : -1; + } + function d3_time_parseHour24(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.H = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMinutes(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.M = +n[0], i + n[0].length) : -1; + } + function d3_time_parseSeconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.S = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMilliseconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.L = +n[0], i + n[0].length) : -1; + } + function d3_time_zone(d) { + var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; + return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + } + function d3_time_parseLiteralPercent(date, string, i) { + d3_time_percentRe.lastIndex = 0; + var n = d3_time_percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; + } + function d3_time_formatMulti(formats) { + var n = formats.length, i = -1; + while (++i < n) formats[i][0] = this(formats[i][0]); + return function(date) { + var i = 0, f = formats[i]; + while (!f[1](date)) f = formats[++i]; + return f[0](date); + }; + } + d3.locale = function(locale) { + return { + numberFormat: d3_locale_numberFormat(locale), + timeFormat: d3_locale_timeFormat(locale) + }; + }; + var d3_locale_enUS = d3.locale({ + decimal: ".", + thousands: ",", + grouping: [ 3 ], + currency: [ "$", "" ], + dateTime: "%a %b %e %X %Y", + date: "%m/%d/%Y", + time: "%H:%M:%S", + periods: [ "AM", "PM" ], + days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], + shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] + }); + d3.format = d3_locale_enUS.numberFormat; + d3.geo = {}; + function d3_adder() {} + d3_adder.prototype = { + s: 0, + t: 0, + add: function(y) { + d3_adderSum(y, this.t, d3_adderTemp); + d3_adderSum(d3_adderTemp.s, this.s, this); + if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; + }, + reset: function() { + this.s = this.t = 0; + }, + valueOf: function() { + return this.s; + } + }; + var d3_adderTemp = new d3_adder(); + function d3_adderSum(a, b, o) { + var x = o.s = a + b, bv = x - a, av = x - bv; + o.t = a - av + (b - bv); + } + d3.geo.stream = function(object, listener) { + if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { + d3_geo_streamObjectType[object.type](object, listener); + } else { + d3_geo_streamGeometry(object, listener); + } + }; + function d3_geo_streamGeometry(geometry, listener) { + if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { + d3_geo_streamGeometryType[geometry.type](geometry, listener); + } + } + var d3_geo_streamObjectType = { + Feature: function(feature, listener) { + d3_geo_streamGeometry(feature.geometry, listener); + }, + FeatureCollection: function(object, listener) { + var features = object.features, i = -1, n = features.length; + while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); + } + }; + var d3_geo_streamGeometryType = { + Sphere: function(object, listener) { + listener.sphere(); + }, + Point: function(object, listener) { + object = object.coordinates; + listener.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); + }, + LineString: function(object, listener) { + d3_geo_streamLine(object.coordinates, listener, 0); + }, + MultiLineString: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); + }, + Polygon: function(object, listener) { + d3_geo_streamPolygon(object.coordinates, listener); + }, + MultiPolygon: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); + }, + GeometryCollection: function(object, listener) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + } + }; + function d3_geo_streamLine(coordinates, listener, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + listener.lineStart(); + while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); + listener.lineEnd(); + } + function d3_geo_streamPolygon(coordinates, listener) { + var i = -1, n = coordinates.length; + listener.polygonStart(); + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); + listener.polygonEnd(); + } + d3.geo.area = function(object) { + d3_geo_areaSum = 0; + d3.geo.stream(object, d3_geo_area); + return d3_geo_areaSum; + }; + var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); + var d3_geo_area = { + sphere: function() { + d3_geo_areaSum += 4 * π; + }, + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_areaRingSum.reset(); + d3_geo_area.lineStart = d3_geo_areaRingStart; + }, + polygonEnd: function() { + var area = 2 * d3_geo_areaRingSum; + d3_geo_areaSum += area < 0 ? 4 * π + area : area; + d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; + } + }; + function d3_geo_areaRingStart() { + var λ00, φ00, λ0, cosφ0, sinφ0; + d3_geo_area.point = function(λ, φ) { + d3_geo_area.point = nextPoint; + λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), + sinφ0 = Math.sin(φ); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + φ = φ * d3_radians / 2 + π / 4; + var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); + d3_geo_areaRingSum.add(Math.atan2(v, u)); + λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; + } + d3_geo_area.lineEnd = function() { + nextPoint(λ00, φ00); + }; + } + function d3_geo_cartesian(spherical) { + var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); + return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; + } + function d3_geo_cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + function d3_geo_cartesianCross(a, b) { + return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; + } + function d3_geo_cartesianAdd(a, b) { + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; + } + function d3_geo_cartesianScale(vector, k) { + return [ vector[0] * k, vector[1] * k, vector[2] * k ]; + } + function d3_geo_cartesianNormalize(d) { + var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l; + d[1] /= l; + d[2] /= l; + } + function d3_geo_spherical(cartesian) { + return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; + } + function d3_geo_sphericalEqual(a, b) { + return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + } + d3.geo.bounds = function() { + var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; + var bound = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + bound.point = ringPoint; + bound.lineStart = ringStart; + bound.lineEnd = ringEnd; + dλSum = 0; + d3_geo_area.polygonStart(); + }, + polygonEnd: function() { + d3_geo_area.polygonEnd(); + bound.point = point; + bound.lineStart = lineStart; + bound.lineEnd = lineEnd; + if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; + range[0] = λ0, range[1] = λ1; + } + }; + function point(λ, φ) { + ranges.push(range = [ λ0 = λ, λ1 = λ ]); + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + function linePoint(λ, φ) { + var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); + if (p0) { + var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); + d3_geo_cartesianNormalize(inflection); + inflection = d3_geo_spherical(inflection); + var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; + if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = inflection[1] * d3_degrees; + if (φi > φ1) φ1 = φi; + } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = -inflection[1] * d3_degrees; + if (φi < φ0) φ0 = φi; + } else { + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + if (antimeridian) { + if (λ < λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } else { + if (λ1 >= λ0) { + if (λ < λ0) λ0 = λ; + if (λ > λ1) λ1 = λ; + } else { + if (λ > λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } + } + } else { + point(λ, φ); + } + p0 = p, λ_ = λ; + } + function lineStart() { + bound.point = linePoint; + } + function lineEnd() { + range[0] = λ0, range[1] = λ1; + bound.point = point; + p0 = null; + } + function ringPoint(λ, φ) { + if (p0) { + var dλ = λ - λ_; + dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; + } else λ__ = λ, φ__ = φ; + d3_geo_area.point(λ, φ); + linePoint(λ, φ); + } + function ringStart() { + d3_geo_area.lineStart(); + } + function ringEnd() { + ringPoint(λ__, φ__); + d3_geo_area.lineEnd(); + if (abs(dλSum) > ε) λ0 = -(λ1 = 180); + range[0] = λ0, range[1] = λ1; + p0 = null; + } + function angle(λ0, λ1) { + return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + } + function compareRanges(a, b) { + return a[0] - b[0]; + } + function withinRange(x, range) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + return function(feature) { + φ1 = λ1 = -(λ0 = φ0 = Infinity); + ranges = []; + d3.geo.stream(feature, bound); + var n = ranges.length; + if (n) { + ranges.sort(compareRanges); + for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { + b = ranges[i]; + if (withinRange(b[0], a) || withinRange(b[1], a)) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + var best = -Infinity, dλ; + for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { + b = merged[i]; + if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + } + } + ranges = range = null; + return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }; + }(); + d3.geo.centroid = function(object) { + d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, d3_geo_centroid); + var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; + if (m < ε2) { + x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; + if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; + m = x * x + y * y + z * z; + if (m < ε2) return [ NaN, NaN ]; + } + return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; + }; + var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; + var d3_geo_centroid = { + sphere: d3_noop, + point: d3_geo_centroidPoint, + lineStart: d3_geo_centroidLineStart, + lineEnd: d3_geo_centroidLineEnd, + polygonStart: function() { + d3_geo_centroid.lineStart = d3_geo_centroidRingStart; + }, + polygonEnd: function() { + d3_geo_centroid.lineStart = d3_geo_centroidLineStart; + } + }; + function d3_geo_centroidPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); + } + function d3_geo_centroidPointXYZ(x, y, z) { + ++d3_geo_centroidW0; + d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; + d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; + d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; + } + function d3_geo_centroidLineStart() { + var x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroid.point = nextPoint; + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_centroidLineEnd() { + d3_geo_centroid.point = d3_geo_centroidPoint; + } + function d3_geo_centroidRingStart() { + var λ00, φ00, x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ00 = λ, φ00 = φ; + d3_geo_centroid.point = nextPoint; + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + d3_geo_centroid.lineEnd = function() { + nextPoint(λ00, φ00); + d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; + d3_geo_centroid.point = d3_geo_centroidPoint; + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); + d3_geo_centroidX2 += v * cx; + d3_geo_centroidY2 += v * cy; + d3_geo_centroidZ2 += v * cz; + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_compose(a, b) { + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + return compose; + } + function d3_true() { + return true; + } + function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { + var subject = [], clip = []; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n]; + if (d3_geo_sphericalEqual(p0, p1)) { + listener.lineStart(); + for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); + listener.lineEnd(); + return; + } + var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); + a.o = b; + subject.push(a); + clip.push(b); + a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); + b = new d3_geo_clipPolygonIntersection(p1, null, a, true); + a.o = b; + subject.push(a); + clip.push(b); + }); + clip.sort(compare); + d3_geo_clipPolygonLinkCircular(subject); + d3_geo_clipPolygonLinkCircular(clip); + if (!subject.length) return; + for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { + clip[i].e = entry = !entry; + } + var start = subject[0], points, point; + while (1) { + var current = start, isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + listener.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, listener); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, listener); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + listener.lineEnd(); + } + } + function d3_geo_clipPolygonLinkCircular(array) { + if (!(n = array.length)) return; + var n, i = 0, a = array[0], b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; + } + function d3_geo_clipPolygonIntersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; + this.e = entry; + this.v = false; + this.n = this.p = null; + } + function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { + return function(rotate, listener) { + var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3.merge(segments); + var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); + if (segments.length) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); + } else if (clipStartInside) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (polygonStarted) listener.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + listener.polygonStart(); + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + listener.polygonEnd(); + } + }; + function point(λ, φ) { + var point = rotate(λ, φ); + if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); + } + function pointLine(λ, φ) { + var point = rotate(λ, φ); + line.point(point[0], point[1]); + } + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + var segments; + var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; + function pointRing(λ, φ) { + ring.push([ λ, φ ]); + var point = rotate(λ, φ); + ringListener.point(point[0], point[1]); + } + function ringStart() { + ringListener.lineStart(); + ring = []; + } + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringListener.lineEnd(); + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; + ring.pop(); + polygon.push(ring); + ring = null; + if (!n) return; + if (clean & 1) { + segment = ringSegments[0]; + var n = segment.length - 1, i = -1, point; + if (n > 0) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + while (++i < n) listener.point((point = segment[i])[0], point[1]); + listener.lineEnd(); + } + return; + } + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + } + return clip; + }; + } + function d3_geo_clipSegmentLength1(segment) { + return segment.length > 1; + } + function d3_geo_clipBufferListener() { + var lines = [], line; + return { + lineStart: function() { + lines.push(line = []); + }, + point: function(λ, φ) { + line.push([ λ, φ ]); + }, + lineEnd: d3_noop, + buffer: function() { + var buffer = lines; + lines = []; + line = null; + return buffer; + }, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + } + }; + } + function d3_geo_clipSort(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); + } + var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); + function d3_geo_clipAntimeridianLine(listener) { + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; + return { + lineStart: function() { + listener.lineStart(); + clean = 1; + }, + point: function(λ1, φ1) { + var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); + if (abs(dλ - π) < ε) { + listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + listener.point(λ1, φ0); + clean = 0; + } else if (sλ0 !== sλ1 && dλ >= π) { + if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; + if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; + φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + clean = 0; + } + listener.point(λ0 = λ1, φ0 = φ1); + sλ0 = sλ1; + }, + lineEnd: function() { + listener.lineEnd(); + λ0 = φ0 = NaN; + }, + clean: function() { + return 2 - clean; + } + }; + } + function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { + var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); + return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; + } + function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { + var φ; + if (from == null) { + φ = direction * halfπ; + listener.point(-π, φ); + listener.point(0, φ); + listener.point(π, φ); + listener.point(π, 0); + listener.point(π, -φ); + listener.point(0, -φ); + listener.point(-π, -φ); + listener.point(-π, 0); + listener.point(-π, φ); + } else if (abs(from[0] - to[0]) > ε) { + var s = from[0] < to[0] ? π : -π; + φ = direction * s / 2; + listener.point(-s, φ); + listener.point(0, φ); + listener.point(s, φ); + } else { + listener.point(to[0], to[1]); + } + } + function d3_geo_pointInPolygon(point, polygon) { + var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; + d3_geo_areaRingSum.reset(); + for (var i = 0, n = polygon.length; i < n; ++i) { + var ring = polygon[i], m = ring.length; + if (!m) continue; + var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; + while (true) { + if (j === m) j = 0; + point = ring[j]; + var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; + d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); + polarAngle += antimeridian ? dλ + sdλ * τ : dλ; + if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { + var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); + d3_geo_cartesianNormalize(arc); + var intersection = d3_geo_cartesianCross(meridianNormal, arc); + d3_geo_cartesianNormalize(intersection); + var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); + if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { + winding += antimeridian ^ dλ >= 0 ? 1 : -1; + } + } + if (!j++) break; + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; + } + } + return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1; + } + function d3_geo_clipCircle(radius) { + var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); + return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); + function visible(λ, φ) { + return Math.cos(λ) * Math.cos(φ) > cr; + } + function clipLine(listener) { + var point0, c0, v0, v00, clean; + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(λ, φ) { + var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; + if (!point0 && (v00 = v0 = v)) listener.lineStart(); + if (v !== v0) { + point2 = intersect(point0, point1); + if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { + point1[0] += ε; + point1[1] += ε; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + listener.lineStart(); + point2 = intersect(point1, point0); + listener.point(point2[0], point2[1]); + } else { + point2 = intersect(point0, point1); + listener.point(point2[0], point2[1]); + listener.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + } else { + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { + listener.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) listener.lineEnd(); + point0 = null; + }, + clean: function() { + return clean | (v00 && v0) << 1; + } + }; + } + function intersect(a, b, two) { + var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); + var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; + if (!determinant) return !two && a; + var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); + d3_geo_cartesianAdd(A, B); + var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); + if (t2 < 0) return; + var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); + d3_geo_cartesianAdd(q, A); + q = d3_geo_spherical(q); + if (!two) return q; + var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; + if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; + var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; + if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; + if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { + var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); + d3_geo_cartesianAdd(q1, A); + return [ q, d3_geo_spherical(q1) ]; + } + } + function code(λ, φ) { + var r = smallRadius ? radius : π - radius, code = 0; + if (λ < -r) code |= 1; else if (λ > r) code |= 2; + if (φ < -r) code |= 4; else if (φ > r) code |= 8; + return code; + } + } + function d3_geom_clipLine(x0, y0, x1, y1) { + return function(line) { + var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + if (t0 > 0) line.a = { + x: ax + t0 * dx, + y: ay + t0 * dy + }; + if (t1 < 1) line.b = { + x: ax + t1 * dx, + y: ay + t1 * dy + }; + return line; + }; + } + var d3_geo_clipExtentMAX = 1e9; + d3.geo.clipExtent = function() { + var x0, y0, x1, y1, stream, clip, clipExtent = { + stream: function(output) { + if (stream) stream.valid = false; + stream = clip(output); + stream.valid = true; + return stream; + }, + extent: function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); + if (stream) stream.valid = false, stream = null; + return clipExtent; + } + }; + return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); + }; + function d3_geo_clipExtent(x0, y0, x1, y1) { + return function(listener) { + var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + listener = bufferListener; + segments = []; + polygon = []; + clean = true; + }, + polygonEnd: function() { + listener = listener_; + segments = d3.merge(segments); + var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; + if (inside || visible) { + listener.polygonStart(); + if (inside) { + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (visible) { + d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + } + listener.polygonEnd(); + } + segments = polygon = ring = null; + } + }; + function insidePolygon(p) { + var wn = 0, n = polygon.length, y = p[1]; + for (var i = 0; i < n; ++i) { + for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { + b = v[j]; + if (a[1] <= y) { + if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; + } else { + if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; + } + a = b; + } + } + return wn !== 0; + } + function interpolate(from, to, direction, listener) { + var a = 0, a1 = 0; + if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { + do { + listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + } while ((a = (a + direction + 4) % 4) !== a1); + } else { + listener.point(to[0], to[1]); + } + } + function pointVisible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + function point(x, y) { + if (pointVisible(x, y)) listener.point(x, y); + } + var x__, y__, v__, x_, y_, v_, first, clean; + function lineStart() { + clip.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferListener.rejoin(); + segments.push(bufferListener.buffer()); + } + clip.point = point; + if (v_) listener.lineEnd(); + } + function linePoint(x, y) { + x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); + y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); + var v = pointVisible(x, y); + if (polygon) ring.push([ x, y ]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + listener.lineStart(); + listener.point(x, y); + } + } else { + if (v && v_) listener.point(x, y); else { + var l = { + a: { + x: x_, + y: y_ + }, + b: { + x: x, + y: y + } + }; + if (clipLine(l)) { + if (!v_) { + listener.lineStart(); + listener.point(l.a.x, l.a.y); + } + listener.point(l.b.x, l.b.y); + if (!v) listener.lineEnd(); + clean = false; + } else if (v) { + listener.lineStart(); + listener.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + return clip; + }; + function corner(p, direction) { + return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; + } + function compare(a, b) { + return comparePoints(a.x, b.x); + } + function comparePoints(a, b) { + var ca = corner(a, 1), cb = corner(b, 1); + return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; + } + } + function d3_geo_conic(projectAt) { + var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); + p.parallels = function(_) { + if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; + return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); + }; + return p; + } + function d3_geo_conicEqualArea(φ0, φ1) { + var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; + function forward(λ, φ) { + var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; + return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = ρ0 - y; + return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; + }; + return forward; + } + (d3.geo.conicEqualArea = function() { + return d3_geo_conic(d3_geo_conicEqualArea); + }).raw = d3_geo_conicEqualArea; + d3.geo.albers = function() { + return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); + }; + d3.geo.albersUsa = function() { + var lower48 = d3.geo.albers(); + var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); + var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); + var point, pointStream = { + point: function(x, y) { + point = [ x, y ]; + } + }, lower48Point, alaskaPoint, hawaiiPoint; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + point = null; + (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); + return point; + } + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; + return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); + }; + albersUsa.stream = function(stream) { + var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); + return { + point: function(x, y) { + lower48Stream.point(x, y); + alaskaStream.point(x, y); + hawaiiStream.point(x, y); + }, + sphere: function() { + lower48Stream.sphere(); + alaskaStream.sphere(); + hawaiiStream.sphere(); + }, + lineStart: function() { + lower48Stream.lineStart(); + alaskaStream.lineStart(); + hawaiiStream.lineStart(); + }, + lineEnd: function() { + lower48Stream.lineEnd(); + alaskaStream.lineEnd(); + hawaiiStream.lineEnd(); + }, + polygonStart: function() { + lower48Stream.polygonStart(); + alaskaStream.polygonStart(); + hawaiiStream.polygonStart(); + }, + polygonEnd: function() { + lower48Stream.polygonEnd(); + alaskaStream.polygonEnd(); + hawaiiStream.polygonEnd(); + } + }; + }; + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + return albersUsa; + }; + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * .35); + hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; + alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + return albersUsa; + }; + return albersUsa.scale(1070); + }; + var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_pathAreaPolygon = 0; + d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; + }, + polygonEnd: function() { + d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; + d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); + } + }; + function d3_geo_pathAreaRingStart() { + var x00, y00, x0, y0; + d3_geo_pathArea.point = function(x, y) { + d3_geo_pathArea.point = nextPoint; + x00 = x0 = x, y00 = y0 = y; + }; + function nextPoint(x, y) { + d3_geo_pathAreaPolygon += y0 * x - x0 * y; + x0 = x, y0 = y; + } + d3_geo_pathArea.lineEnd = function() { + nextPoint(x00, y00); + }; + } + var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; + var d3_geo_pathBounds = { + point: d3_geo_pathBoundsPoint, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_pathBoundsPoint(x, y) { + if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; + if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; + if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; + if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; + } + function d3_geo_pathBuffer() { + var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointCircle = d3_geo_pathBufferCircle(_); + return stream; + }, + result: function() { + if (buffer.length) { + var result = buffer.join(""); + buffer = []; + return result; + } + } + }; + function point(x, y) { + buffer.push("M", x, ",", y, pointCircle); + } + function pointLineStart(x, y) { + buffer.push("M", x, ",", y); + stream.point = pointLine; + } + function pointLine(x, y) { + buffer.push("L", x, ",", y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + buffer.push("Z"); + } + return stream; + } + function d3_geo_pathBufferCircle(radius) { + return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; + } + var d3_geo_pathCentroid = { + point: d3_geo_pathCentroidPoint, + lineStart: d3_geo_pathCentroidLineStart, + lineEnd: d3_geo_pathCentroidLineEnd, + polygonStart: function() { + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; + }, + polygonEnd: function() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; + d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; + } + }; + function d3_geo_pathCentroidPoint(x, y) { + d3_geo_centroidX0 += x; + d3_geo_centroidY0 += y; + ++d3_geo_centroidZ0; + } + function d3_geo_pathCentroidLineStart() { + var x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + } + function d3_geo_pathCentroidLineEnd() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + } + function d3_geo_pathCentroidRingStart() { + var x00, y00, x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + z = y0 * x - x0 * y; + d3_geo_centroidX2 += z * (x0 + x); + d3_geo_centroidY2 += z * (y0 + y); + d3_geo_centroidZ2 += z * 3; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + d3_geo_pathCentroid.lineEnd = function() { + nextPoint(x00, y00); + }; + } + function d3_geo_pathContext(context) { + var pointRadius = 4.5; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointRadius = _; + return stream; + }, + result: d3_noop + }; + function point(x, y) { + context.moveTo(x + pointRadius, y); + context.arc(x, y, pointRadius, 0, τ); + } + function pointLineStart(x, y) { + context.moveTo(x, y); + stream.point = pointLine; + } + function pointLine(x, y) { + context.lineTo(x, y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + context.closePath(); + } + return stream; + } + function d3_geo_resample(project) { + var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; + function resample(stream) { + return (maxDepth ? resampleRecursive : resampleNone)(stream); + } + function resampleNone(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + }); + } + function resampleRecursive(stream) { + var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; + var resample = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + stream.polygonStart(); + resample.lineStart = ringStart; + }, + polygonEnd: function() { + stream.polygonEnd(); + resample.lineStart = lineStart; + } + }; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + function lineStart() { + x0 = NaN; + resample.point = linePoint; + stream.lineStart(); + } + function linePoint(λ, φ) { + var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); + resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + function lineEnd() { + resample.point = point; + stream.lineEnd(); + } + function ringStart() { + lineStart(); + resample.point = ringPoint; + resample.lineEnd = ringEnd; + } + function ringPoint(λ, φ) { + linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resample.point = linePoint; + } + function ringEnd() { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); + resample.lineEnd = lineEnd; + lineEnd(); + } + return resample; + } + function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; + if (d2 > 4 * δ2 && depth--) { + var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); + } + } + } + resample.precision = function(_) { + if (!arguments.length) return Math.sqrt(δ2); + maxDepth = (δ2 = _ * _) > 0 && 16; + return resample; + }; + return resample; + } + d3.geo.path = function() { + var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); + d3.geo.stream(object, cacheStream); + } + return contextStream.result(); + } + path.area = function(object) { + d3_geo_pathAreaSum = 0; + d3.geo.stream(object, projectStream(d3_geo_pathArea)); + return d3_geo_pathAreaSum; + }; + path.centroid = function(object) { + d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); + return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; + }; + path.bounds = function(object) { + d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); + d3.geo.stream(object, projectStream(d3_geo_pathBounds)); + return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; + }; + path.projection = function(_) { + if (!arguments.length) return projection; + projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; + return reset(); + }; + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return reset(); + }; + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + function reset() { + cacheStream = null; + return path; + } + return path.projection(d3.geo.albersUsa()).context(null); + }; + function d3_geo_pathProjectStream(project) { + var resample = d3_geo_resample(function(x, y) { + return project([ x * d3_degrees, y * d3_degrees ]); + }); + return function(stream) { + return d3_geo_projectionRadians(resample(stream)); + }; + } + d3.geo.transform = function(methods) { + return { + stream: function(stream) { + var transform = new d3_geo_transform(stream); + for (var k in methods) transform[k] = methods[k]; + return transform; + } + }; + }; + function d3_geo_transform(stream) { + this.stream = stream; + } + d3_geo_transform.prototype = { + point: function(x, y) { + this.stream.point(x, y); + }, + sphere: function() { + this.stream.sphere(); + }, + lineStart: function() { + this.stream.lineStart(); + }, + lineEnd: function() { + this.stream.lineEnd(); + }, + polygonStart: function() { + this.stream.polygonStart(); + }, + polygonEnd: function() { + this.stream.polygonEnd(); + } + }; + function d3_geo_transformPoint(stream, point) { + return { + point: point, + sphere: function() { + stream.sphere(); + }, + lineStart: function() { + stream.lineStart(); + }, + lineEnd: function() { + stream.lineEnd(); + }, + polygonStart: function() { + stream.polygonStart(); + }, + polygonEnd: function() { + stream.polygonEnd(); + } + }; + } + d3.geo.projection = d3_geo_projection; + d3.geo.projectionMutator = d3_geo_projectionMutator; + function d3_geo_projection(project) { + return d3_geo_projectionMutator(function() { + return project; + })(); + } + function d3_geo_projectionMutator(projectAt) { + var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { + x = project(x, y); + return [ x[0] * k + δx, δy - x[1] * k ]; + }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; + function projection(point) { + point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); + return [ point[0] * k + δx, δy - point[1] * k ]; + } + function invert(point) { + point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); + return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; + } + projection.stream = function(output) { + if (stream) stream.valid = false; + stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); + stream.valid = true; + return stream; + }; + projection.clipAngle = function(_) { + if (!arguments.length) return clipAngle; + preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); + return invalidate(); + }; + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; + return invalidate(); + }; + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return reset(); + }; + projection.translate = function(_) { + if (!arguments.length) return [ x, y ]; + x = +_[0]; + y = +_[1]; + return reset(); + }; + projection.center = function(_) { + if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; + λ = _[0] % 360 * d3_radians; + φ = _[1] % 360 * d3_radians; + return reset(); + }; + projection.rotate = function(_) { + if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; + δλ = _[0] % 360 * d3_radians; + δφ = _[1] % 360 * d3_radians; + δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; + return reset(); + }; + d3.rebind(projection, projectResample, "precision"); + function reset() { + projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); + var center = project(λ, φ); + δx = x - center[0] * k; + δy = y + center[1] * k; + return invalidate(); + } + function invalidate() { + if (stream) stream.valid = false, stream = null; + return projection; + } + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return reset(); + }; + } + function d3_geo_projectionRadians(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + stream.point(x * d3_radians, y * d3_radians); + }); + } + function d3_geo_equirectangular(λ, φ) { + return [ λ, φ ]; + } + (d3.geo.equirectangular = function() { + return d3_geo_projection(d3_geo_equirectangular); + }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; + d3.geo.rotation = function(rotate) { + rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); + function forward(coordinates) { + coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + } + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + }; + return forward; + }; + function d3_geo_identityRotation(λ, φ) { + return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + } + d3_geo_identityRotation.invert = d3_geo_equirectangular; + function d3_geo_rotation(δλ, δφ, δγ) { + return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; + } + function d3_geo_forwardRotationλ(δλ) { + return function(λ, φ) { + return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + }; + } + function d3_geo_rotationλ(δλ) { + var rotation = d3_geo_forwardRotationλ(δλ); + rotation.invert = d3_geo_forwardRotationλ(-δλ); + return rotation; + } + function d3_geo_rotationφγ(δφ, δγ) { + var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); + function rotation(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; + return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; + } + rotation.invert = function(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; + return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; + }; + return rotation; + } + d3.geo.circle = function() { + var origin = [ 0, 0 ], angle, precision = 6, interpolate; + function circle() { + var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; + interpolate(null, null, 1, { + point: function(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= d3_degrees, x[1] *= d3_degrees; + } + }); + return { + type: "Polygon", + coordinates: [ ring ] + }; + } + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; + }; + circle.angle = function(x) { + if (!arguments.length) return angle; + interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); + return circle; + }; + circle.precision = function(_) { + if (!arguments.length) return precision; + interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); + return circle; + }; + return circle.angle(90); + }; + function d3_geo_circleInterpolate(radius, precision) { + var cr = Math.cos(radius), sr = Math.sin(radius); + return function(from, to, direction, listener) { + var step = direction * precision; + if (from != null) { + from = d3_geo_circleAngle(cr, from); + to = d3_geo_circleAngle(cr, to); + if (direction > 0 ? from < to : from > to) from += direction * τ; + } else { + from = radius + direction * τ; + to = radius - .5 * step; + } + for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { + listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); + } + }; + } + function d3_geo_circleAngle(cr, point) { + var a = d3_geo_cartesian(point); + a[0] -= cr; + d3_geo_cartesianNormalize(a); + var angle = d3_acos(-a[1]); + return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + } + d3.geo.distance = function(a, b) { + var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; + return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); + }; + d3.geo.graticule = function() { + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; + function graticule() { + return { + type: "MultiLineString", + coordinates: lines() + }; + } + function lines() { + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { + return abs(x % DX) > ε; + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { + return abs(y % DY) > ε; + }).map(y)); + } + graticule.lines = function() { + return lines().map(function(coordinates) { + return { + type: "LineString", + coordinates: coordinates + }; + }); + }; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] + }; + }; + graticule.extent = function(_) { + if (!arguments.length) return graticule.minorExtent(); + return graticule.majorExtent(_).minorExtent(_); + }; + graticule.majorExtent = function(_) { + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + graticule.minorExtent = function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + graticule.step = function(_) { + if (!arguments.length) return graticule.minorStep(); + return graticule.majorStep(_).minorStep(_); + }; + graticule.majorStep = function(_) { + if (!arguments.length) return [ DX, DY ]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + graticule.minorStep = function(_) { + if (!arguments.length) return [ dx, dy ]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = d3_geo_graticuleX(y0, y1, 90); + y = d3_geo_graticuleY(x0, x1, precision); + X = d3_geo_graticuleX(Y0, Y1, 90); + Y = d3_geo_graticuleY(X0, X1, precision); + return graticule; + }; + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); + }; + function d3_geo_graticuleX(y0, y1, dy) { + var y = d3.range(y0, y1 - ε, dy).concat(y1); + return function(x) { + return y.map(function(y) { + return [ x, y ]; + }); + }; + } + function d3_geo_graticuleY(x0, x1, dx) { + var x = d3.range(x0, x1 - ε, dx).concat(x1); + return function(y) { + return x.map(function(x) { + return [ x, y ]; + }); + }; + } + function d3_source(d) { + return d.source; + } + function d3_target(d) { + return d.target; + } + d3.geo.greatArc = function() { + var source = d3_source, source_, target = d3_target, target_; + function greatArc() { + return { + type: "LineString", + coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] + }; + } + greatArc.distance = function() { + return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); + }; + greatArc.source = function(_) { + if (!arguments.length) return source; + source = _, source_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.target = function(_) { + if (!arguments.length) return target; + target = _, target_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.precision = function() { + return arguments.length ? greatArc : 0; + }; + return greatArc; + }; + d3.geo.interpolate = function(source, target) { + return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + }; + function d3_geo_interpolate(x0, y0, x1, y1) { + var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); + var interpolate = d ? function(t) { + var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; + return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; + } : function() { + return [ x0 * d3_degrees, y0 * d3_degrees ]; + }; + interpolate.distance = d; + return interpolate; + } + d3.geo.length = function(object) { + d3_geo_lengthSum = 0; + d3.geo.stream(object, d3_geo_length); + return d3_geo_lengthSum; + }; + var d3_geo_lengthSum; + var d3_geo_length = { + sphere: d3_noop, + point: d3_noop, + lineStart: d3_geo_lengthLineStart, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_lengthLineStart() { + var λ0, sinφ0, cosφ0; + d3_geo_length.point = function(λ, φ) { + λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); + d3_geo_length.point = nextPoint; + }; + d3_geo_length.lineEnd = function() { + d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + }; + function nextPoint(λ, φ) { + var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); + d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; + } + } + function d3_geo_azimuthal(scale, angle) { + function azimuthal(λ, φ) { + var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); + return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + } + azimuthal.invert = function(x, y) { + var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); + return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; + }; + return azimuthal; + } + var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { + return Math.sqrt(2 / (1 + cosλcosφ)); + }, function(ρ) { + return 2 * Math.asin(ρ / 2); + }); + (d3.geo.azimuthalEqualArea = function() { + return d3_geo_projection(d3_geo_azimuthalEqualArea); + }).raw = d3_geo_azimuthalEqualArea; + var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { + var c = Math.acos(cosλcosφ); + return c && c / Math.sin(c); + }, d3_identity); + (d3.geo.azimuthalEquidistant = function() { + return d3_geo_projection(d3_geo_azimuthalEquidistant); + }).raw = d3_geo_azimuthalEquidistant; + function d3_geo_conicConformal(φ0, φ1) { + var cosφ0 = Math.cos(φ0), t = function(φ) { + return Math.tan(π / 4 + φ / 2); + }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; + if (!n) return d3_geo_mercator; + function forward(λ, φ) { + if (F > 0) { + if (φ < -halfπ + ε) φ = -halfπ + ε; + } else { + if (φ > halfπ - ε) φ = halfπ - ε; + } + var ρ = F / Math.pow(t(φ), n); + return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); + return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; + }; + return forward; + } + (d3.geo.conicConformal = function() { + return d3_geo_conic(d3_geo_conicConformal); + }).raw = d3_geo_conicConformal; + function d3_geo_conicEquidistant(φ0, φ1) { + var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; + if (abs(n) < ε) return d3_geo_equirectangular; + function forward(λ, φ) { + var ρ = G - φ; + return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = G - y; + return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; + }; + return forward; + } + (d3.geo.conicEquidistant = function() { + return d3_geo_conic(d3_geo_conicEquidistant); + }).raw = d3_geo_conicEquidistant; + var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / cosλcosφ; + }, Math.atan); + (d3.geo.gnomonic = function() { + return d3_geo_projection(d3_geo_gnomonic); + }).raw = d3_geo_gnomonic; + function d3_geo_mercator(λ, φ) { + return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; + } + d3_geo_mercator.invert = function(x, y) { + return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; + }; + function d3_geo_mercatorProjection(project) { + var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; + m.scale = function() { + var v = scale.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.translate = function() { + var v = translate.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.clipExtent = function(_) { + var v = clipExtent.apply(m, arguments); + if (v === m) { + if (clipAuto = _ == null) { + var k = π * scale(), t = translate(); + clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); + } + } else if (clipAuto) { + v = null; + } + return v; + }; + return m.clipExtent(null); + } + (d3.geo.mercator = function() { + return d3_geo_mercatorProjection(d3_geo_mercator); + }).raw = d3_geo_mercator; + var d3_geo_orthographic = d3_geo_azimuthal(function() { + return 1; + }, Math.asin); + (d3.geo.orthographic = function() { + return d3_geo_projection(d3_geo_orthographic); + }).raw = d3_geo_orthographic; + var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / (1 + cosλcosφ); + }, function(ρ) { + return 2 * Math.atan(ρ); + }); + (d3.geo.stereographic = function() { + return d3_geo_projection(d3_geo_stereographic); + }).raw = d3_geo_stereographic; + function d3_geo_transverseMercator(λ, φ) { + return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; + } + d3_geo_transverseMercator.invert = function(x, y) { + return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; + }; + (d3.geo.transverseMercator = function() { + var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; + projection.center = function(_) { + return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); + }; + projection.rotate = function(_) { + return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), + [ _[0], _[1], _[2] - 90 ]); + }; + return rotate([ 0, 0, 90 ]); + }).raw = d3_geo_transverseMercator; + d3.geom = {}; + function d3_geom_pointX(d) { + return d[0]; + } + function d3_geom_pointY(d) { + return d[1]; + } + d3.geom.hull = function(vertices) { + var x = d3_geom_pointX, y = d3_geom_pointY; + if (arguments.length) return hull(vertices); + function hull(data) { + if (data.length < 3) return []; + var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; + for (i = 0; i < n; i++) { + points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + } + points.sort(d3_geom_hullOrder); + for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); + var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); + var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; + for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); + for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); + return polygon; + } + hull.x = function(_) { + return arguments.length ? (x = _, hull) : x; + }; + hull.y = function(_) { + return arguments.length ? (y = _, hull) : y; + }; + return hull; + }; + function d3_geom_hullUpper(points) { + var n = points.length, hull = [ 0, 1 ], hs = 2; + for (var i = 2; i < n; i++) { + while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; + hull[hs++] = i; + } + return hull.slice(0, hs); + } + function d3_geom_hullOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + d3.geom.polygon = function(coordinates) { + d3_subclass(coordinates, d3_geom_polygonPrototype); + return coordinates; + }; + var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; + d3_geom_polygonPrototype.area = function() { + var i = -1, n = this.length, a, b = this[n - 1], area = 0; + while (++i < n) { + a = b; + b = this[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + return area * .5; + }; + d3_geom_polygonPrototype.centroid = function(k) { + var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; + if (!arguments.length) k = -1 / (6 * this.area()); + while (++i < n) { + a = b; + b = this[i]; + c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + return [ x * k, y * k ]; + }; + d3_geom_polygonPrototype.clip = function(subject) { + var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; + while (++i < n) { + input = subject.slice(); + subject.length = 0; + b = this[i]; + c = input[(m = input.length - closed) - 1]; + j = -1; + while (++j < m) { + d = input[j]; + if (d3_geom_polygonInside(d, a, b)) { + if (!d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + subject.push(d); + } else if (d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + c = d; + } + if (closed) subject.push(subject[0]); + a = b; + } + return subject; + }; + function d3_geom_polygonInside(p, a, b) { + return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); + } + function d3_geom_polygonIntersect(c, d, a, b) { + var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); + return [ x1 + ua * x21, y1 + ua * y21 ]; + } + function d3_geom_polygonClosed(coordinates) { + var a = coordinates[0], b = coordinates[coordinates.length - 1]; + return !(a[0] - b[0] || a[1] - b[1]); + } + var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; + function d3_geom_voronoiBeach() { + d3_geom_voronoiRedBlackNode(this); + this.edge = this.site = this.circle = null; + } + function d3_geom_voronoiCreateBeach(site) { + var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); + beach.site = site; + return beach; + } + function d3_geom_voronoiDetachBeach(beach) { + d3_geom_voronoiDetachCircle(beach); + d3_geom_voronoiBeaches.remove(beach); + d3_geom_voronoiBeachPool.push(beach); + d3_geom_voronoiRedBlackNode(beach); + } + function d3_geom_voronoiRemoveBeach(beach) { + var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { + x: x, + y: y + }, previous = beach.P, next = beach.N, disappearing = [ beach ]; + d3_geom_voronoiDetachBeach(beach); + var lArc = previous; + while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { + previous = lArc.P; + disappearing.unshift(lArc); + d3_geom_voronoiDetachBeach(lArc); + lArc = previous; + } + disappearing.unshift(lArc); + d3_geom_voronoiDetachCircle(lArc); + var rArc = next; + while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { + next = rArc.N; + disappearing.push(rArc); + d3_geom_voronoiDetachBeach(rArc); + rArc = next; + } + disappearing.push(rArc); + d3_geom_voronoiDetachCircle(rArc); + var nArcs = disappearing.length, iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiAddBeach(site) { + var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; + while (node) { + dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; + if (dxl > ε) node = node.L; else { + dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); + if (dxr > ε) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -ε) { + lArc = node.P; + rArc = node; + } else if (dxr > -ε) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + var newArc = d3_geom_voronoiCreateBeach(site); + d3_geom_voronoiBeaches.insert(lArc, newArc); + if (!lArc && !rArc) return; + if (lArc === rArc) { + d3_geom_voronoiDetachCircle(lArc); + rArc = d3_geom_voronoiCreateBeach(lArc.site); + d3_geom_voronoiBeaches.insert(newArc, rArc); + newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + return; + } + if (!rArc) { + newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + return; + } + d3_geom_voronoiDetachCircle(lArc); + d3_geom_voronoiDetachCircle(rArc); + var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { + x: (cy * hb - by * hc) / d + ax, + y: (bx * hc - cx * hb) / d + ay + }; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); + rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiLeftBreakPoint(arc, directrix) { + var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; + if (!pby2) return rfocx; + var lArc = arc.P; + if (!lArc) return -Infinity; + site = lArc.site; + var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; + if (!plby2) return lfocx; + var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + return (rfocx + lfocx) / 2; + } + function d3_geom_voronoiRightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); + var site = arc.site; + return site.y === directrix ? site.x : Infinity; + } + function d3_geom_voronoiCell(site) { + this.site = site; + this.edges = []; + } + d3_geom_voronoiCell.prototype.prepare = function() { + var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; + while (iHalfEdge--) { + edge = halfEdges[iHalfEdge].edge; + if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); + } + halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); + return halfEdges.length; + }; + function d3_geom_voronoiCloseCells(extent) { + var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; + while (iCell--) { + cell = cells[iCell]; + if (!cell || !cell.prepare()) continue; + halfEdges = cell.edges; + nHalfEdges = halfEdges.length; + iHalfEdge = 0; + while (iHalfEdge < nHalfEdges) { + end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; + start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; + if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { + halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { + x: x0, + y: abs(x2 - x0) < ε ? y2 : y1 + } : abs(y3 - y1) < ε && x1 - x3 > ε ? { + x: abs(y2 - y1) < ε ? x2 : x1, + y: y1 + } : abs(x3 - x1) < ε && y3 - y0 > ε ? { + x: x1, + y: abs(x2 - x1) < ε ? y2 : y0 + } : abs(y3 - y0) < ε && x3 - x0 > ε ? { + x: abs(y2 - y0) < ε ? x2 : x0, + y: y0 + } : null), cell.site, null)); + ++nHalfEdges; + } + } + } + } + function d3_geom_voronoiHalfEdgeOrder(a, b) { + return b.angle - a.angle; + } + function d3_geom_voronoiCircle() { + d3_geom_voronoiRedBlackNode(this); + this.x = this.y = this.arc = this.site = this.cy = null; + } + function d3_geom_voronoiAttachCircle(arc) { + var lArc = arc.P, rArc = arc.N; + if (!lArc || !rArc) return; + var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; + if (lSite === rSite) return; + var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; + var d = 2 * (ax * cy - ay * cx); + if (d >= -ε2) return; + var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; + var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = cy + Math.sqrt(x * x + y * y); + circle.cy = cy; + arc.circle = circle; + var before = null, node = d3_geom_voronoiCircles._; + while (node) { + if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { + if (node.L) node = node.L; else { + before = node.P; + break; + } + } else { + if (node.R) node = node.R; else { + before = node; + break; + } + } + } + d3_geom_voronoiCircles.insert(before, circle); + if (!before) d3_geom_voronoiFirstCircle = circle; + } + function d3_geom_voronoiDetachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; + d3_geom_voronoiCircles.remove(circle); + d3_geom_voronoiCirclePool.push(circle); + d3_geom_voronoiRedBlackNode(circle); + arc.circle = null; + } + } + function d3_geom_voronoiClipEdges(extent) { + var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; + while (i--) { + e = edges[i]; + if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { + e.a = e.b = null; + edges.splice(i, 1); + } + } + } + function d3_geom_voronoiConnectEdge(edge, extent) { + var vb = edge.b; + if (vb) return true; + var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!va) va = { + x: fx, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: fx, + y: y1 + }; + } else { + if (!va) va = { + x: fx, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: fx, + y: y0 + }; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!va) va = { + x: (y0 - fb) / fm, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: (y1 - fb) / fm, + y: y1 + }; + } else { + if (!va) va = { + x: (y1 - fb) / fm, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: (y0 - fb) / fm, + y: y0 + }; + } + } else { + if (ly < ry) { + if (!va) va = { + x: x0, + y: fm * x0 + fb + }; else if (va.x >= x1) return; + vb = { + x: x1, + y: fm * x1 + fb + }; + } else { + if (!va) va = { + x: x1, + y: fm * x1 + fb + }; else if (va.x < x0) return; + vb = { + x: x0, + y: fm * x0 + fb + }; + } + } + } + edge.a = va; + edge.b = vb; + return true; + } + function d3_geom_voronoiEdge(lSite, rSite) { + this.l = lSite; + this.r = rSite; + this.a = this.b = null; + } + function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, rSite); + d3_geom_voronoiEdges.push(edge); + if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); + if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); + d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); + d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); + return edge; + } + function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, null); + edge.a = va; + edge.b = vb; + d3_geom_voronoiEdges.push(edge); + return edge; + } + function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { + if (!edge.a && !edge.b) { + edge.a = vertex; + edge.l = lSite; + edge.r = rSite; + } else if (edge.l === rSite) { + edge.b = vertex; + } else { + edge.a = vertex; + } + } + function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { + var va = edge.a, vb = edge.b; + this.edge = edge; + this.site = lSite; + this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); + } + d3_geom_voronoiHalfEdge.prototype = { + start: function() { + return this.edge.l === this.site ? this.edge.a : this.edge.b; + }, + end: function() { + return this.edge.l === this.site ? this.edge.b : this.edge.a; + } + }; + function d3_geom_voronoiRedBlackTree() { + this._ = null; + } + function d3_geom_voronoiRedBlackNode(node) { + node.U = node.C = node.L = node.R = node.P = node.N = null; + } + d3_geom_voronoiRedBlackTree.prototype = { + insert: function(after, node) { + var parent, grandpa, uncle; + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = d3_geom_voronoiRedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + d3_geom_voronoiRedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + d3_geom_voronoiRedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + var parent = node.U, sibling, left = node.L, right = node.R, next, red; + if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); + if (parent) { + if (parent.L === node) parent.L = next; else parent.R = next; + } else { + this._ = next; + } + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + if (node) node.U = parent; + if (red) return; + if (node && node.C) { + node.C = false; + return; + } + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateRight(this, parent); + sibling = parent.L; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + d3_geom_voronoiRedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + if (node) node.C = false; + } + }; + function d3_geom_voronoiRedBlackRotateLeft(tree, node) { + var p = node, q = node.R, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; + } + function d3_geom_voronoiRedBlackRotateRight(tree, node) { + var p = node, q = node.L, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; + } + function d3_geom_voronoiRedBlackFirst(node) { + while (node.L) node = node.L; + return node; + } + function d3_geom_voronoi(sites, bbox) { + var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; + d3_geom_voronoiEdges = []; + d3_geom_voronoiCells = new Array(sites.length); + d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); + d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); + while (true) { + circle = d3_geom_voronoiFirstCircle; + if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { + if (site.x !== x0 || site.y !== y0) { + d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); + d3_geom_voronoiAddBeach(site); + x0 = site.x, y0 = site.y; + } + site = sites.pop(); + } else if (circle) { + d3_geom_voronoiRemoveBeach(circle.arc); + } else { + break; + } + } + if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); + var diagram = { + cells: d3_geom_voronoiCells, + edges: d3_geom_voronoiEdges + }; + d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; + return diagram; + } + function d3_geom_voronoiVertexOrder(a, b) { + return b.y - a.y || b.x - a.x; + } + d3.geom.voronoi = function(points) { + var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; + if (points) return voronoi(points); + function voronoi(data) { + var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; + d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { + var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { + var s = e.start(); + return [ s.x, s.y ]; + }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; + polygon.point = data[i]; + }); + return polygons; + } + function sites(data) { + return data.map(function(d, i) { + return { + x: Math.round(fx(d, i) / ε) * ε, + y: Math.round(fy(d, i) / ε) * ε, + i: i + }; + }); + } + voronoi.links = function(data) { + return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { + return edge.l && edge.r; + }).map(function(edge) { + return { + source: data[edge.l.i], + target: data[edge.r.i] + }; + }); + }; + voronoi.triangles = function(data) { + var triangles = []; + d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { + var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; + while (++j < m) { + e0 = e1; + s0 = s1; + e1 = edges[j].edge; + s1 = e1.l === site ? e1.r : e1.l; + if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { + triangles.push([ data[i], data[s0.i], data[s1.i] ]); + } + } + }); + return triangles; + }; + voronoi.x = function(_) { + return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; + }; + voronoi.y = function(_) { + return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; + }; + voronoi.clipExtent = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; + clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; + return voronoi; + }; + voronoi.size = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; + return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + }; + return voronoi; + }; + var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; + function d3_geom_voronoiTriangleArea(a, b, c) { + return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); + } + d3.geom.delaunay = function(vertices) { + return d3.geom.voronoi().triangles(vertices); + }; + d3.geom.quadtree = function(points, x1, y1, x2, y2) { + var x = d3_geom_pointX, y = d3_geom_pointY, compat; + if (compat = arguments.length) { + x = d3_geom_quadtreeCompatX; + y = d3_geom_quadtreeCompatY; + if (compat === 3) { + y2 = y1; + x2 = x1; + y1 = x1 = 0; + } + return quadtree(points); + } + function quadtree(data) { + var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; + if (x1 != null) { + x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; + } else { + x2_ = y2_ = -(x1_ = y1_ = Infinity); + xs = [], ys = []; + n = data.length; + if (compat) for (i = 0; i < n; ++i) { + d = data[i]; + if (d.x < x1_) x1_ = d.x; + if (d.y < y1_) y1_ = d.y; + if (d.x > x2_) x2_ = d.x; + if (d.y > y2_) y2_ = d.y; + xs.push(d.x); + ys.push(d.y); + } else for (i = 0; i < n; ++i) { + var x_ = +fx(d = data[i], i), y_ = +fy(d, i); + if (x_ < x1_) x1_ = x_; + if (y_ < y1_) y1_ = y_; + if (x_ > x2_) x2_ = x_; + if (y_ > y2_) y2_ = y_; + xs.push(x_); + ys.push(y_); + } + } + var dx = x2_ - x1_, dy = y2_ - y1_; + if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; + function insert(n, d, x, y, x1, y1, x2, y2) { + if (isNaN(x) || isNaN(y)) return; + if (n.leaf) { + var nx = n.x, ny = n.y; + if (nx != null) { + if (abs(nx - x) + abs(ny - y) < .01) { + insertChild(n, d, x, y, x1, y1, x2, y2); + } else { + var nPoint = n.point; + n.x = n.y = n.point = null; + insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } else { + n.x = x, n.y = y, n.point = d; + } + } else { + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } + function insertChild(n, d, x, y, x1, y1, x2, y2) { + var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; + n.leaf = false; + n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); + if (right) x1 = xm; else x2 = xm; + if (below) y1 = ym; else y2 = ym; + insert(n, d, x, y, x1, y1, x2, y2); + } + var root = d3_geom_quadtreeNode(); + root.add = function(d) { + insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); + }; + root.visit = function(f) { + d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); + }; + root.find = function(point) { + return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); + }; + i = -1; + if (x1 == null) { + while (++i < n) { + insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); + } + --i; + } else data.forEach(root.add); + xs = ys = data = d = null; + return root; + } + quadtree.x = function(_) { + return arguments.length ? (x = _, quadtree) : x; + }; + quadtree.y = function(_) { + return arguments.length ? (y = _, quadtree) : y; + }; + quadtree.extent = function(_) { + if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], + y2 = +_[1][1]; + return quadtree; + }; + quadtree.size = function(_) { + if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; + return quadtree; + }; + return quadtree; + }; + function d3_geom_quadtreeCompatX(d) { + return d.x; + } + function d3_geom_quadtreeCompatY(d) { + return d.y; + } + function d3_geom_quadtreeNode() { + return { + leaf: true, + nodes: [], + point: null, + x: null, + y: null + }; + } + function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { + if (!f(node, x1, y1, x2, y2)) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; + if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); + if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); + if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); + if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); + } + } + function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { + var minDistance2 = Infinity, closestPoint; + (function find(node, x1, y1, x2, y2) { + if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; + if (point = node.point) { + var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; + if (distance2 < minDistance2) { + var distance = Math.sqrt(minDistance2 = distance2); + x0 = x - distance, y0 = y - distance; + x3 = x + distance, y3 = y + distance; + closestPoint = point; + } + } + var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; + for (var i = below << 1 | right, j = i + 4; i < j; ++i) { + if (node = children[i & 3]) switch (i & 3) { + case 0: + find(node, x1, y1, xm, ym); + break; + + case 1: + find(node, xm, y1, x2, ym); + break; + + case 2: + find(node, x1, ym, xm, y2); + break; + + case 3: + find(node, xm, ym, x2, y2); + break; + } + } + })(root, x0, y0, x3, y3); + return closestPoint; + } + d3.interpolateRgb = d3_interpolateRgb; + function d3_interpolateRgb(a, b) { + a = d3.rgb(a); + b = d3.rgb(b); + var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; + return function(t) { + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + }; + } + d3.interpolateObject = d3_interpolateObject; + function d3_interpolateObject(a, b) { + var i = {}, c = {}, k; + for (k in a) { + if (k in b) { + i[k] = d3_interpolate(a[k], b[k]); + } else { + c[k] = a[k]; + } + } + for (k in b) { + if (!(k in a)) { + c[k] = b[k]; + } + } + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; + } + d3.interpolateNumber = d3_interpolateNumber; + function d3_interpolateNumber(a, b) { + a = +a, b = +b; + return function(t) { + return a * (1 - t) + b * t; + }; + } + d3.interpolateString = d3_interpolateString; + function d3_interpolateString(a, b) { + var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a = a + "", b = b + ""; + while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) s[i] += bm; else s[++i] = bm; + } else { + s[++i] = null; + q.push({ + i: i, + x: d3_interpolateNumber(am, bm) + }); + } + bi = d3_interpolate_numberB.lastIndex; + } + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { + return b(t) + ""; + }) : function() { + return b; + } : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); + d3.interpolate = d3_interpolate; + function d3_interpolate(a, b) { + var i = d3.interpolators.length, f; + while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; + return f; + } + d3.interpolators = [ function(a, b) { + var t = typeof b; + return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); + } ]; + d3.interpolateArray = d3_interpolateArray; + function d3_interpolateArray(a, b) { + var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; + for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); + for (;i < na; ++i) c[i] = a[i]; + for (;i < nb; ++i) c[i] = b[i]; + return function(t) { + for (i = 0; i < n0; ++i) c[i] = x[i](t); + return c; + }; + } + var d3_ease_default = function() { + return d3_identity; + }; + var d3_ease = d3.map({ + linear: d3_ease_default, + poly: d3_ease_poly, + quad: function() { + return d3_ease_quad; + }, + cubic: function() { + return d3_ease_cubic; + }, + sin: function() { + return d3_ease_sin; + }, + exp: function() { + return d3_ease_exp; + }, + circle: function() { + return d3_ease_circle; + }, + elastic: d3_ease_elastic, + back: d3_ease_back, + bounce: function() { + return d3_ease_bounce; + } + }); + var d3_ease_mode = d3.map({ + "in": d3_identity, + out: d3_ease_reverse, + "in-out": d3_ease_reflect, + "out-in": function(f) { + return d3_ease_reflect(d3_ease_reverse(f)); + } + }); + d3.ease = function(name) { + var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; + t = d3_ease.get(t) || d3_ease_default; + m = d3_ease_mode.get(m) || d3_identity; + return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); + }; + function d3_ease_clamp(f) { + return function(t) { + return t <= 0 ? 0 : t >= 1 ? 1 : f(t); + }; + } + function d3_ease_reverse(f) { + return function(t) { + return 1 - f(1 - t); + }; + } + function d3_ease_reflect(f) { + return function(t) { + return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); + }; + } + function d3_ease_quad(t) { + return t * t; + } + function d3_ease_cubic(t) { + return t * t * t; + } + function d3_ease_cubicInOut(t) { + if (t <= 0) return 0; + if (t >= 1) return 1; + var t2 = t * t, t3 = t2 * t; + return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + } + function d3_ease_poly(e) { + return function(t) { + return Math.pow(t, e); + }; + } + function d3_ease_sin(t) { + return 1 - Math.cos(t * halfπ); + } + function d3_ease_exp(t) { + return Math.pow(2, 10 * (t - 1)); + } + function d3_ease_circle(t) { + return 1 - Math.sqrt(1 - t * t); + } + function d3_ease_elastic(a, p) { + var s; + if (arguments.length < 2) p = .45; + if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; + return function(t) { + return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); + }; + } + function d3_ease_back(s) { + if (!s) s = 1.70158; + return function(t) { + return t * t * ((s + 1) * t - s); + }; + } + function d3_ease_bounce(t) { + return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; + } + d3.interpolateHcl = d3_interpolateHcl; + function d3_interpolateHcl(a, b) { + a = d3.hcl(a); + b = d3.hcl(b); + var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; + if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + }; + } + d3.interpolateHsl = d3_interpolateHsl; + function d3_interpolateHsl(a, b) { + a = d3.hsl(a); + b = d3.hsl(b); + var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; + if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + }; + } + d3.interpolateLab = d3_interpolateLab; + function d3_interpolateLab(a, b) { + a = d3.lab(a); + b = d3.lab(b); + var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; + return function(t) { + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + }; + } + d3.interpolateRound = d3_interpolateRound; + function d3_interpolateRound(a, b) { + b -= a; + return function(t) { + return Math.round(a + b * t); + }; + } + d3.transform = function(string) { + var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); + return (d3.transform = function(string) { + if (string != null) { + g.setAttribute("transform", string); + var t = g.transform.baseVal.consolidate(); + } + return new d3_transform(t ? t.matrix : d3_transformIdentity); + })(string); + }; + function d3_transform(m) { + var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; + if (r0[0] * r1[1] < r1[0] * r0[1]) { + r0[0] *= -1; + r0[1] *= -1; + kx *= -1; + kz *= -1; + } + this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; + this.translate = [ m.e, m.f ]; + this.scale = [ kx, ky ]; + this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + } + d3_transform.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + }; + function d3_transformDot(a, b) { + return a[0] * b[0] + a[1] * b[1]; + } + function d3_transformNormalize(a) { + var k = Math.sqrt(d3_transformDot(a, a)); + if (k) { + a[0] /= k; + a[1] /= k; + } + return k; + } + function d3_transformCombine(a, b, k) { + a[0] += k * b[0]; + a[1] += k * b[1]; + return a; + } + var d3_transformIdentity = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + d3.interpolateTransform = d3_interpolateTransform; + function d3_interpolateTransformPop(s) { + return s.length ? s.pop() + "," : ""; + } + function d3_interpolateTranslate(ta, tb, s, q) { + if (ta[0] !== tb[0] || ta[1] !== tb[1]) { + var i = s.push("translate(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ta[0], tb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ta[1], tb[1]) + }); + } else if (tb[0] || tb[1]) { + s.push("translate(" + tb + ")"); + } + } + function d3_interpolateRotate(ra, rb, s, q) { + if (ra !== rb) { + if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, + x: d3_interpolateNumber(ra, rb) + }); + } else if (rb) { + s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); + } + } + function d3_interpolateSkew(wa, wb, s, q) { + if (wa !== wb) { + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, + x: d3_interpolateNumber(wa, wb) + }); + } else if (wb) { + s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); + } + } + function d3_interpolateScale(ka, kb, s, q) { + if (ka[0] !== kb[0] || ka[1] !== kb[1]) { + var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ka[0], kb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ka[1], kb[1]) + }); + } else if (kb[0] !== 1 || kb[1] !== 1) { + s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); + } + } + function d3_interpolateTransform(a, b) { + var s = [], q = []; + a = d3.transform(a), b = d3.transform(b); + d3_interpolateTranslate(a.translate, b.translate, s, q); + d3_interpolateRotate(a.rotate, b.rotate, s, q); + d3_interpolateSkew(a.skew, b.skew, s, q); + d3_interpolateScale(a.scale, b.scale, s, q); + a = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + } + function d3_uninterpolateNumber(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return (x - a) / b; + }; + } + function d3_uninterpolateClamp(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return Math.max(0, Math.min(1, (x - a) / b)); + }; + } + d3.layout = {}; + d3.layout.bundle = function() { + return function(links) { + var paths = [], i = -1, n = links.length; + while (++i < n) paths.push(d3_layout_bundlePath(links[i])); + return paths; + }; + }; + function d3_layout_bundlePath(link) { + var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; + while (start !== lca) { + start = start.parent; + points.push(start); + } + var k = points.length; + while (end !== lca) { + points.splice(k, 0, end); + end = end.parent; + } + return points; + } + function d3_layout_bundleAncestors(node) { + var ancestors = [], parent = node.parent; + while (parent != null) { + ancestors.push(node); + node = parent; + parent = parent.parent; + } + ancestors.push(node); + return ancestors; + } + function d3_layout_bundleLeastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; + while (aNode === bNode) { + sharedNode = aNode; + aNode = aNodes.pop(); + bNode = bNodes.pop(); + } + return sharedNode; + } + d3.layout.chord = function() { + var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; + function relayout() { + var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; + chords = []; + groups = []; + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3.range(n)); + k += x; + } + if (sortGroups) { + groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + } + if (sortSubgroups) { + subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + } + k = (τ - padding * n) / k; + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; + subgroups[di + "-" + dj] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += padding; + } + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; + if (source.value || target.value) { + chords.push(source.value < target.value ? { + source: target, + target: source + } : { + source: source, + target: target + }); + } + } + } + if (sortChords) resort(); + } + function resort() { + chords.sort(function(a, b) { + return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); + }); + } + chord.matrix = function(x) { + if (!arguments.length) return matrix; + n = (matrix = x) && matrix.length; + chords = groups = null; + return chord; + }; + chord.padding = function(x) { + if (!arguments.length) return padding; + padding = x; + chords = groups = null; + return chord; + }; + chord.sortGroups = function(x) { + if (!arguments.length) return sortGroups; + sortGroups = x; + chords = groups = null; + return chord; + }; + chord.sortSubgroups = function(x) { + if (!arguments.length) return sortSubgroups; + sortSubgroups = x; + chords = null; + return chord; + }; + chord.sortChords = function(x) { + if (!arguments.length) return sortChords; + sortChords = x; + if (chords) resort(); + return chord; + }; + chord.chords = function() { + if (!chords) relayout(); + return chords; + }; + chord.groups = function() { + if (!groups) relayout(); + return groups; + }; + return chord; + }; + d3.layout.force = function() { + var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; + function repulse(node) { + return function(quad, x1, _, x2) { + if (quad.point !== node) { + var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; + if (dw * dw / theta2 < dn) { + if (dn < chargeDistance2) { + var k = quad.charge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + return true; + } + if (quad.point && dn && dn < chargeDistance2) { + var k = quad.pointCharge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + } + return !quad.charge; + }; + } + force.tick = function() { + if ((alpha *= .99) < .005) { + timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + return true; + } + var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; + for (i = 0; i < m; ++i) { + o = links[i]; + s = o.source; + t = o.target; + x = t.x - s.x; + y = t.y - s.y; + if (l = x * x + y * y) { + l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; + x *= l; + y *= l; + t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; + } + } + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; + if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } + } + if (charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); + i = -1; + while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o)); + } + } + } + i = -1; + while (++i < n) { + o = nodes[i]; + if (o.fixed) { + o.x = o.px; + o.y = o.py; + } else { + o.x -= (o.px - (o.px = o.x)) * friction; + o.y -= (o.py - (o.py = o.y)) * friction; + } + } + event.tick({ + type: "tick", + alpha: alpha + }); + }; + force.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return force; + }; + force.links = function(x) { + if (!arguments.length) return links; + links = x; + return force; + }; + force.size = function(x) { + if (!arguments.length) return size; + size = x; + return force; + }; + force.linkDistance = function(x) { + if (!arguments.length) return linkDistance; + linkDistance = typeof x === "function" ? x : +x; + return force; + }; + force.distance = force.linkDistance; + force.linkStrength = function(x) { + if (!arguments.length) return linkStrength; + linkStrength = typeof x === "function" ? x : +x; + return force; + }; + force.friction = function(x) { + if (!arguments.length) return friction; + friction = +x; + return force; + }; + force.charge = function(x) { + if (!arguments.length) return charge; + charge = typeof x === "function" ? x : +x; + return force; + }; + force.chargeDistance = function(x) { + if (!arguments.length) return Math.sqrt(chargeDistance2); + chargeDistance2 = x * x; + return force; + }; + force.gravity = function(x) { + if (!arguments.length) return gravity; + gravity = +x; + return force; + }; + force.theta = function(x) { + if (!arguments.length) return Math.sqrt(theta2); + theta2 = x * x; + return force; + }; + force.alpha = function(x) { + if (!arguments.length) return alpha; + x = +x; + if (alpha) { + if (x > 0) { + alpha = x; + } else { + timer.c = null, timer.t = NaN, timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + } + } else if (x > 0) { + event.start({ + type: "start", + alpha: alpha = x + }); + timer = d3_timer(force.tick); + } + return force; + }; + force.start = function() { + var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; + for (i = 0; i < n; ++i) { + (o = nodes[i]).index = i; + o.weight = 0; + } + for (i = 0; i < m; ++i) { + o = links[i]; + if (typeof o.source == "number") o.source = nodes[o.source]; + if (typeof o.target == "number") o.target = nodes[o.target]; + ++o.source.weight; + ++o.target.weight; + } + for (i = 0; i < n; ++i) { + o = nodes[i]; + if (isNaN(o.x)) o.x = position("x", w); + if (isNaN(o.y)) o.y = position("y", h); + if (isNaN(o.px)) o.px = o.x; + if (isNaN(o.py)) o.py = o.y; + } + distances = []; + if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; + strengths = []; + if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; + charges = []; + if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; + function position(dimension, size) { + if (!neighbors) { + neighbors = new Array(n); + for (j = 0; j < n; ++j) { + neighbors[j] = []; + } + for (j = 0; j < m; ++j) { + var o = links[j]; + neighbors[o.source.index].push(o.target); + neighbors[o.target.index].push(o.source); + } + } + var candidates = neighbors[i], j = -1, l = candidates.length, x; + while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; + return Math.random() * size; + } + return force.resume(); + }; + force.resume = function() { + return force.alpha(.1); + }; + force.stop = function() { + return force.alpha(0); + }; + force.drag = function() { + if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); + if (!arguments.length) return drag; + this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); + }; + function dragmove(d) { + d.px = d3.event.x, d.py = d3.event.y; + force.resume(); + } + return d3.rebind(force, event, "on"); + }; + function d3_layout_forceDragstart(d) { + d.fixed |= 2; + } + function d3_layout_forceDragend(d) { + d.fixed &= ~6; + } + function d3_layout_forceMouseover(d) { + d.fixed |= 4; + d.px = d.x, d.py = d.y; + } + function d3_layout_forceMouseout(d) { + d.fixed &= ~4; + } + function d3_layout_forceAccumulate(quad, alpha, charges) { + var cx = 0, cy = 0; + quad.charge = 0; + if (!quad.leaf) { + var nodes = quad.nodes, n = nodes.length, i = -1, c; + while (++i < n) { + c = nodes[i]; + if (c == null) continue; + d3_layout_forceAccumulate(c, alpha, charges); + quad.charge += c.charge; + cx += c.charge * c.cx; + cy += c.charge * c.cy; + } + } + if (quad.point) { + if (!quad.leaf) { + quad.point.x += Math.random() - .5; + quad.point.y += Math.random() - .5; + } + var k = alpha * charges[quad.point.index]; + quad.charge += quad.pointCharge = k; + cx += k * quad.point.x; + cy += k * quad.point.y; + } + quad.cx = cx / quad.charge; + quad.cy = cy / quad.charge; + } + var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; + d3.layout.hierarchy = function() { + var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; + function hierarchy(root) { + var stack = [ root ], nodes = [], node; + root.depth = 0; + while ((node = stack.pop()) != null) { + nodes.push(node); + if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { + var n, childs, child; + while (--n >= 0) { + stack.push(child = childs[n]); + child.parent = node; + child.depth = node.depth + 1; + } + if (value) node.value = 0; + node.children = childs; + } else { + if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; + delete node.children; + } + } + d3_layout_hierarchyVisitAfter(root, function(node) { + var childs, parent; + if (sort && (childs = node.children)) childs.sort(sort); + if (value && (parent = node.parent)) parent.value += node.value; + }); + return nodes; + } + hierarchy.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return hierarchy; + }; + hierarchy.children = function(x) { + if (!arguments.length) return children; + children = x; + return hierarchy; + }; + hierarchy.value = function(x) { + if (!arguments.length) return value; + value = x; + return hierarchy; + }; + hierarchy.revalue = function(root) { + if (value) { + d3_layout_hierarchyVisitBefore(root, function(node) { + if (node.children) node.value = 0; + }); + d3_layout_hierarchyVisitAfter(root, function(node) { + var parent; + if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; + if (parent = node.parent) parent.value += node.value; + }); + } + return root; + }; + return hierarchy; + }; + function d3_layout_hierarchyRebind(object, hierarchy) { + d3.rebind(object, hierarchy, "sort", "children", "value"); + object.nodes = object; + object.links = d3_layout_hierarchyLinks; + return object; + } + function d3_layout_hierarchyVisitBefore(node, callback) { + var nodes = [ node ]; + while ((node = nodes.pop()) != null) { + callback(node); + if ((children = node.children) && (n = children.length)) { + var n, children; + while (--n >= 0) nodes.push(children[n]); + } + } + } + function d3_layout_hierarchyVisitAfter(node, callback) { + var nodes = [ node ], nodes2 = []; + while ((node = nodes.pop()) != null) { + nodes2.push(node); + if ((children = node.children) && (n = children.length)) { + var i = -1, n, children; + while (++i < n) nodes.push(children[i]); + } + } + while ((node = nodes2.pop()) != null) { + callback(node); + } + } + function d3_layout_hierarchyChildren(d) { + return d.children; + } + function d3_layout_hierarchyValue(d) { + return d.value; + } + function d3_layout_hierarchySort(a, b) { + return b.value - a.value; + } + function d3_layout_hierarchyLinks(nodes) { + return d3.merge(nodes.map(function(parent) { + return (parent.children || []).map(function(child) { + return { + source: parent, + target: child + }; + }); + })); + } + d3.layout.partition = function() { + var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; + function position(node, x, dx, dy) { + var children = node.children; + node.x = x; + node.y = node.depth * dy; + node.dx = dx; + node.dy = dy; + if (children && (n = children.length)) { + var i = -1, n, c, d; + dx = node.value ? dx / node.value : 0; + while (++i < n) { + position(c = children[i], x, d = c.value * dx, dy); + x += d; + } + } + } + function depth(node) { + var children = node.children, d = 0; + if (children && (n = children.length)) { + var i = -1, n; + while (++i < n) d = Math.max(d, depth(children[i])); + } + return 1 + d; + } + function partition(d, i) { + var nodes = hierarchy.call(this, d, i); + position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); + return nodes; + } + partition.size = function(x) { + if (!arguments.length) return size; + size = x; + return partition; + }; + return d3_layout_hierarchyRebind(partition, hierarchy); + }; + d3.layout.pie = function() { + var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; + function pie(data) { + var n = data.length, values = data.map(function(d, i) { + return +value.call(pie, d, i); + }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; + if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { + return values[j] - values[i]; + } : function(i, j) { + return sort(data[i], data[j]); + }); + index.forEach(function(i) { + arcs[i] = { + data: data[i], + value: v = values[i], + startAngle: a, + endAngle: a += v * k + pa, + padAngle: p + }; + }); + return arcs; + } + pie.value = function(_) { + if (!arguments.length) return value; + value = _; + return pie; + }; + pie.sort = function(_) { + if (!arguments.length) return sort; + sort = _; + return pie; + }; + pie.startAngle = function(_) { + if (!arguments.length) return startAngle; + startAngle = _; + return pie; + }; + pie.endAngle = function(_) { + if (!arguments.length) return endAngle; + endAngle = _; + return pie; + }; + pie.padAngle = function(_) { + if (!arguments.length) return padAngle; + padAngle = _; + return pie; + }; + return pie; + }; + var d3_layout_pieSortByValue = {}; + d3.layout.stack = function() { + var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; + function stack(data, index) { + if (!(n = data.length)) return data; + var series = data.map(function(d, i) { + return values.call(stack, d, i); + }); + var points = series.map(function(d) { + return d.map(function(v, i) { + return [ x.call(stack, v, i), y.call(stack, v, i) ]; + }); + }); + var orders = order.call(stack, points, index); + series = d3.permute(series, orders); + points = d3.permute(points, orders); + var offsets = offset.call(stack, points, index); + var m = series[0].length, n, i, j, o; + for (j = 0; j < m; ++j) { + out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); + for (i = 1; i < n; ++i) { + out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + } + } + return data; + } + stack.values = function(x) { + if (!arguments.length) return values; + values = x; + return stack; + }; + stack.order = function(x) { + if (!arguments.length) return order; + order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; + return stack; + }; + stack.offset = function(x) { + if (!arguments.length) return offset; + offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; + return stack; + }; + stack.x = function(z) { + if (!arguments.length) return x; + x = z; + return stack; + }; + stack.y = function(z) { + if (!arguments.length) return y; + y = z; + return stack; + }; + stack.out = function(z) { + if (!arguments.length) return out; + out = z; + return stack; + }; + return stack; + }; + function d3_layout_stackX(d) { + return d.x; + } + function d3_layout_stackY(d) { + return d.y; + } + function d3_layout_stackOut(d, y0, y) { + d.y0 = y0; + d.y = y; + } + var d3_layout_stackOrders = d3.map({ + "inside-out": function(data) { + var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { + return max[a] - max[b]; + }), top = 0, bottom = 0, tops = [], bottoms = []; + for (i = 0; i < n; ++i) { + j = index[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + return bottoms.reverse().concat(tops); + }, + reverse: function(data) { + return d3.range(data.length).reverse(); + }, + "default": d3_layout_stackOrderDefault + }); + var d3_layout_stackOffsets = d3.map({ + silhouette: function(data) { + var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o > max) max = o; + sums.push(o); + } + for (j = 0; j < m; ++j) { + y0[j] = (max - sums[j]) / 2; + } + return y0; + }, + wiggle: function(data) { + var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; + y0[0] = o = o0 = 0; + for (j = 1; j < m; ++j) { + for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; + for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { + for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { + s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; + } + s2 += s3 * data[i][j][1]; + } + y0[j] = o -= s1 ? s2 / s1 * dx : 0; + if (o < o0) o0 = o; + } + for (j = 0; j < m; ++j) y0[j] -= o0; + return y0; + }, + expand: function(data) { + var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }, + zero: d3_layout_stackOffsetZero + }); + function d3_layout_stackOrderDefault(data) { + return d3.range(data.length); + } + function d3_layout_stackOffsetZero(data) { + var j = -1, m = data[0].length, y0 = []; + while (++j < m) y0[j] = 0; + return y0; + } + function d3_layout_stackMaxIndex(array) { + var i = 1, j = 0, v = array[0][1], k, n = array.length; + for (;i < n; ++i) { + if ((k = array[i][1]) > v) { + j = i; + v = k; + } + } + return j; + } + function d3_layout_stackReduceSum(d) { + return d.reduce(d3_layout_stackSum, 0); + } + function d3_layout_stackSum(p, d) { + return p + d[1]; + } + d3.layout.histogram = function() { + var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; + function histogram(data, i) { + var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; + while (++i < m) { + bin = bins[i] = []; + bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); + bin.y = 0; + } + if (m > 0) { + i = -1; + while (++i < n) { + x = values[i]; + if (x >= range[0] && x <= range[1]) { + bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; + bin.y += k; + bin.push(data[i]); + } + } + } + return bins; + } + histogram.value = function(x) { + if (!arguments.length) return valuer; + valuer = x; + return histogram; + }; + histogram.range = function(x) { + if (!arguments.length) return ranger; + ranger = d3_functor(x); + return histogram; + }; + histogram.bins = function(x) { + if (!arguments.length) return binner; + binner = typeof x === "number" ? function(range) { + return d3_layout_histogramBinFixed(range, x); + } : d3_functor(x); + return histogram; + }; + histogram.frequency = function(x) { + if (!arguments.length) return frequency; + frequency = !!x; + return histogram; + }; + return histogram; + }; + function d3_layout_histogramBinSturges(range, values) { + return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); + } + function d3_layout_histogramBinFixed(range, n) { + var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; + while (++x <= n) f[x] = m * x + b; + return f; + } + function d3_layout_histogramRange(values) { + return [ d3.min(values), d3.max(values) ]; + } + d3.layout.pack = function() { + var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; + function pack(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { + return radius; + }; + root.x = root.y = 0; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r = +r(d.value); + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + if (padding) { + var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r += dr; + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r -= dr; + }); + } + d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); + return nodes; + } + pack.size = function(_) { + if (!arguments.length) return size; + size = _; + return pack; + }; + pack.radius = function(_) { + if (!arguments.length) return radius; + radius = _ == null || typeof _ === "function" ? _ : +_; + return pack; + }; + pack.padding = function(_) { + if (!arguments.length) return padding; + padding = +_; + return pack; + }; + return d3_layout_hierarchyRebind(pack, hierarchy); + }; + function d3_layout_packSort(a, b) { + return a.value - b.value; + } + function d3_layout_packInsert(a, b) { + var c = a._pack_next; + a._pack_next = b; + b._pack_prev = a; + b._pack_next = c; + c._pack_prev = b; + } + function d3_layout_packSplice(a, b) { + a._pack_next = b; + b._pack_prev = a; + } + function d3_layout_packIntersects(a, b) { + var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; + return .999 * dr * dr > dx * dx + dy * dy; + } + function d3_layout_packSiblings(node) { + if (!(nodes = node.children) || !(n = nodes.length)) return; + var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; + function bound(node) { + xMin = Math.min(node.x - node.r, xMin); + xMax = Math.max(node.x + node.r, xMax); + yMin = Math.min(node.y - node.r, yMin); + yMax = Math.max(node.y + node.r, yMax); + } + nodes.forEach(d3_layout_packLink); + a = nodes[0]; + a.x = -a.r; + a.y = 0; + bound(a); + if (n > 1) { + b = nodes[1]; + b.x = b.r; + b.y = 0; + bound(b); + if (n > 2) { + c = nodes[2]; + d3_layout_packPlace(a, b, c); + bound(c); + d3_layout_packInsert(a, c); + a._pack_prev = c; + d3_layout_packInsert(c, b); + b = a._pack_next; + for (i = 3; i < n; i++) { + d3_layout_packPlace(a, b, c = nodes[i]); + var isect = 0, s1 = 1, s2 = 1; + for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { + if (d3_layout_packIntersects(j, c)) { + isect = 1; + break; + } + } + if (isect == 1) { + for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { + if (d3_layout_packIntersects(k, c)) { + break; + } + } + } + if (isect) { + if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); + i--; + } else { + d3_layout_packInsert(a, c); + b = c; + bound(c); + } + } + } + } + var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; + for (i = 0; i < n; i++) { + c = nodes[i]; + c.x -= cx; + c.y -= cy; + cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); + } + node.r = cr; + nodes.forEach(d3_layout_packUnlink); + } + function d3_layout_packLink(node) { + node._pack_next = node._pack_prev = node; + } + function d3_layout_packUnlink(node) { + delete node._pack_next; + delete node._pack_prev; + } + function d3_layout_packTransform(node, x, y, k) { + var children = node.children; + node.x = x += k * node.x; + node.y = y += k * node.y; + node.r *= k; + if (children) { + var i = -1, n = children.length; + while (++i < n) d3_layout_packTransform(children[i], x, y, k); + } + } + function d3_layout_packPlace(a, b, c) { + var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; + if (db && (dx || dy)) { + var da = b.r + c.r, dc = dx * dx + dy * dy; + da *= da; + db *= db; + var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = a.x + x * dx + y * dy; + c.y = a.y + x * dy - y * dx; + } else { + c.x = a.x + db; + c.y = a.y; + } + } + d3.layout.tree = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; + function tree(d, i) { + var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); + d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; + d3_layout_hierarchyVisitBefore(root1, secondWalk); + if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { + var left = root0, right = root0, bottom = root0; + d3_layout_hierarchyVisitBefore(root0, function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); + d3_layout_hierarchyVisitBefore(root0, function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + return nodes; + } + function wrapTree(root0) { + var root1 = { + A: null, + children: [ root0 ] + }, queue = [ root1 ], node1; + while ((node1 = queue.pop()) != null) { + for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { + queue.push((children[i] = child = { + _: children[i], + parent: node1, + children: (child = children[i].children) && child.slice() || [], + A: null, + a: null, + z: 0, + m: 0, + c: 0, + s: 0, + t: null, + i: i + }).a = child); + } + } + return root1.children[0]; + } + function firstWalk(v) { + var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; + if (children.length) { + d3_layout_treeShift(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + function apportion(v, w, ancestor) { + if (w) { + var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; + while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { + vom = d3_layout_treeLeft(vom); + vop = d3_layout_treeRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !d3_layout_treeRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !d3_layout_treeLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + function sizeNode(node) { + node.x *= size[0]; + node.y = node.depth * size[1]; + } + tree.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return tree; + }; + tree.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null ? sizeNode : null; + return tree; + }; + tree.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) == null ? null : sizeNode; + return tree; + }; + return d3_layout_hierarchyRebind(tree, hierarchy); + }; + function d3_layout_treeSeparation(a, b) { + return a.parent == b.parent ? 1 : 2; + } + function d3_layout_treeLeft(v) { + var children = v.children; + return children.length ? children[0] : v.t; + } + function d3_layout_treeRight(v) { + var children = v.children, n; + return (n = children.length) ? children[n - 1] : v.t; + } + function d3_layout_treeMove(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; + } + function d3_layout_treeShift(v) { + var shift = 0, change = 0, children = v.children, i = children.length, w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } + } + function d3_layout_treeAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + d3.layout.cluster = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; + function cluster(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; + d3_layout_hierarchyVisitAfter(root, function(node) { + var children = node.children; + if (children && children.length) { + node.x = d3_layout_clusterX(children); + node.y = d3_layout_clusterY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; + d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { + node.x = (node.x - root.x) * size[0]; + node.y = (root.y - node.y) * size[1]; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * size[0]; + node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + }); + return nodes; + } + cluster.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return cluster; + }; + cluster.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null; + return cluster; + }; + cluster.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) != null; + return cluster; + }; + return d3_layout_hierarchyRebind(cluster, hierarchy); + }; + function d3_layout_clusterY(children) { + return 1 + d3.max(children, function(child) { + return child.y; + }); + } + function d3_layout_clusterX(children) { + return children.reduce(function(x, child) { + return x + child.x; + }, 0) / children.length; + } + function d3_layout_clusterLeft(node) { + var children = node.children; + return children && children.length ? d3_layout_clusterLeft(children[0]) : node; + } + function d3_layout_clusterRight(node) { + var children = node.children, n; + return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + } + d3.layout.treemap = function() { + var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); + function scale(children, k) { + var i = -1, n = children.length, child, area; + while (++i < n) { + area = (child = children[i]).value * (k < 0 ? 0 : k); + child.area = isNaN(area) || area <= 0 ? 0 : area; + } + } + function squarify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while ((n = remaining.length) > 0) { + row.push(child = remaining[n - 1]); + row.area += child.area; + if (mode !== "squarify" || (score = worst(row, u)) <= best) { + remaining.pop(); + best = score; + } else { + row.area -= row.pop().area; + position(row, u, rect, false); + u = Math.min(rect.dx, rect.dy); + row.length = row.area = 0; + best = Infinity; + } + } + if (row.length) { + position(row, u, rect, true); + row.length = row.area = 0; + } + children.forEach(squarify); + } + } + function stickify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), remaining = children.slice(), child, row = []; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while (child = remaining.pop()) { + row.push(child); + row.area += child.area; + if (child.z != null) { + position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); + row.length = row.area = 0; + } + } + children.forEach(stickify); + } + } + function worst(row, u) { + var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; + while (++i < n) { + if (!(r = row[i].area)) continue; + if (r < rmin) rmin = r; + if (r > rmax) rmax = r; + } + s *= s; + u *= u; + return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; + } + function position(row, u, rect, flush) { + var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; + if (u == rect.dx) { + if (flush || v > rect.dy) v = rect.dy; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dy = v; + x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); + } + o.z = true; + o.dx += rect.x + rect.dx - x; + rect.y += v; + rect.dy -= v; + } else { + if (flush || v > rect.dx) v = rect.dx; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dx = v; + y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); + } + o.z = false; + o.dy += rect.y + rect.dy - y; + rect.x += v; + rect.dx -= v; + } + } + function treemap(d) { + var nodes = stickies || hierarchy(d), root = nodes[0]; + root.x = root.y = 0; + if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; + if (stickies) hierarchy.revalue(root); + scale([ root ], root.dx * root.dy / root.value); + (stickies ? stickify : squarify)(root); + if (sticky) stickies = nodes; + return nodes; + } + treemap.size = function(x) { + if (!arguments.length) return size; + size = x; + return treemap; + }; + treemap.padding = function(x) { + if (!arguments.length) return padding; + function padFunction(node) { + var p = x.call(treemap, node, node.depth); + return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); + } + function padConstant(node) { + return d3_layout_treemapPad(node, x); + } + var type; + pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], + padConstant) : padConstant; + return treemap; + }; + treemap.round = function(x) { + if (!arguments.length) return round != Number; + round = x ? Math.round : Number; + return treemap; + }; + treemap.sticky = function(x) { + if (!arguments.length) return sticky; + sticky = x; + stickies = null; + return treemap; + }; + treemap.ratio = function(x) { + if (!arguments.length) return ratio; + ratio = x; + return treemap; + }; + treemap.mode = function(x) { + if (!arguments.length) return mode; + mode = x + ""; + return treemap; + }; + return d3_layout_hierarchyRebind(treemap, hierarchy); + }; + function d3_layout_treemapPadNull(node) { + return { + x: node.x, + y: node.y, + dx: node.dx, + dy: node.dy + }; + } + function d3_layout_treemapPad(node, padding) { + var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; + if (dx < 0) { + x += dx / 2; + dx = 0; + } + if (dy < 0) { + y += dy / 2; + dy = 0; + } + return { + x: x, + y: y, + dx: dx, + dy: dy + }; + } + d3.random = { + normal: function(µ, σ) { + var n = arguments.length; + if (n < 2) σ = 1; + if (n < 1) µ = 0; + return function() { + var x, y, r; + do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); + }; + }, + logNormal: function() { + var random = d3.random.normal.apply(d3, arguments); + return function() { + return Math.exp(random()); + }; + }, + bates: function(m) { + var random = d3.random.irwinHall(m); + return function() { + return random() / m; + }; + }, + irwinHall: function(m) { + return function() { + for (var s = 0, j = 0; j < m; j++) s += Math.random(); + return s; + }; + } + }; + d3.scale = {}; + function d3_scaleExtent(domain) { + var start = domain[0], stop = domain[domain.length - 1]; + return start < stop ? [ start, stop ] : [ stop, start ]; + } + function d3_scaleRange(scale) { + return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + } + function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { + var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); + return function(x) { + return i(u(x)); + }; + } + function d3_scale_nice(domain, nice) { + var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; + if (x1 < x0) { + dx = i0, i0 = i1, i1 = dx; + dx = x0, x0 = x1, x1 = dx; + } + domain[i0] = nice.floor(x0); + domain[i1] = nice.ceil(x1); + return domain; + } + function d3_scale_niceStep(step) { + return step ? { + floor: function(x) { + return Math.floor(x / step) * step; + }, + ceil: function(x) { + return Math.ceil(x / step) * step; + } + } : d3_scale_niceIdentity; + } + var d3_scale_niceIdentity = { + floor: d3_identity, + ceil: d3_identity + }; + function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { + var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; + if (domain[k] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + while (++j <= k) { + u.push(uninterpolate(domain[j - 1], domain[j])); + i.push(interpolate(range[j - 1], range[j])); + } + return function(x) { + var j = d3.bisect(domain, x, 1, k) - 1; + return i[j](u[j](x)); + }; + } + d3.scale.linear = function() { + return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + }; + function d3_scale_linear(domain, range, interpolate, clamp) { + var output, input; + function rescale() { + var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; + output = linear(domain, range, uninterpolate, interpolate); + input = linear(range, domain, uninterpolate, d3_interpolate); + return scale; + } + function scale(x) { + return output(x); + } + scale.invert = function(y) { + return input(y); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(Number); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.rangeRound = function(x) { + return scale.range(x).interpolate(d3_interpolateRound); + }; + scale.clamp = function(x) { + if (!arguments.length) return clamp; + clamp = x; + return rescale(); + }; + scale.interpolate = function(x) { + if (!arguments.length) return interpolate; + interpolate = x; + return rescale(); + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + d3_scale_linearNice(domain, m); + return rescale(); + }; + scale.copy = function() { + return d3_scale_linear(domain, range, interpolate, clamp); + }; + return rescale(); + } + function d3_scale_linearRebind(scale, linear) { + return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); + } + function d3_scale_linearNice(domain, m) { + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + return domain; + } + function d3_scale_linearTickRange(domain, m) { + if (m == null) m = 10; + var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; + if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; + extent[0] = Math.ceil(extent[0] / step) * step; + extent[1] = Math.floor(extent[1] / step) * step + step * .5; + extent[2] = step; + return extent; + } + function d3_scale_linearTicks(domain, m) { + return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); + } + function d3_scale_linearTickFormat(domain, m, format) { + var range = d3_scale_linearTickRange(domain, m); + if (format) { + var match = d3_format_re.exec(format); + match.shift(); + if (match[8] === "s") { + var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); + if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); + match[8] = "f"; + format = d3.format(match.join("")); + return function(d) { + return format(prefix.scale(d)) + prefix.symbol; + }; + } + if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); + format = match.join(""); + } else { + format = ",." + d3_scale_linearPrecision(range[2]) + "f"; + } + return d3.format(format); + } + var d3_scale_linearFormatSignificant = { + s: 1, + g: 1, + p: 1, + r: 1, + e: 1 + }; + function d3_scale_linearPrecision(value) { + return -Math.floor(Math.log(value) / Math.LN10 + .01); + } + function d3_scale_linearFormatPrecision(type, range) { + var p = d3_scale_linearPrecision(range[2]); + return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; + } + d3.scale.log = function() { + return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); + }; + function d3_scale_log(linear, base, positive, domain) { + function log(x) { + return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); + } + function pow(x) { + return positive ? Math.pow(base, x) : -Math.pow(base, -x); + } + function scale(x) { + return linear(log(x)); + } + scale.invert = function(x) { + return pow(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + positive = x[0] >= 0; + linear.domain((domain = x.map(Number)).map(log)); + return scale; + }; + scale.base = function(_) { + if (!arguments.length) return base; + base = +_; + linear.domain(domain.map(log)); + return scale; + }; + scale.nice = function() { + var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); + linear.domain(niced); + domain = niced.map(pow); + return scale; + }; + scale.ticks = function() { + var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; + if (isFinite(j - i)) { + if (positive) { + for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); + ticks.push(pow(i)); + } else { + ticks.push(pow(i)); + for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); + } + for (i = 0; ticks[i] < u; i++) {} + for (j = ticks.length; ticks[j - 1] > v; j--) {} + ticks = ticks.slice(i, j); + } + return ticks; + }; + scale.tickFormat = function(n, format) { + if (!arguments.length) return d3_scale_logFormat; + if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); + var k = Math.max(1, base * n / scale.ticks().length); + return function(d) { + var i = d / pow(Math.round(log(d))); + if (i * base < base - .5) i *= base; + return i <= k ? format(d) : ""; + }; + }; + scale.copy = function() { + return d3_scale_log(linear.copy(), base, positive, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { + floor: function(x) { + return -Math.ceil(-x); + }, + ceil: function(x) { + return -Math.floor(-x); + } + }; + d3.scale.pow = function() { + return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); + }; + function d3_scale_pow(linear, exponent, domain) { + var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); + function scale(x) { + return linear(powp(x)); + } + scale.invert = function(x) { + return powb(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + linear.domain((domain = x.map(Number)).map(powp)); + return scale; + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + return scale.domain(d3_scale_linearNice(domain, m)); + }; + scale.exponent = function(x) { + if (!arguments.length) return exponent; + powp = d3_scale_powPow(exponent = x); + powb = d3_scale_powPow(1 / exponent); + linear.domain(domain.map(powp)); + return scale; + }; + scale.copy = function() { + return d3_scale_pow(linear.copy(), exponent, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_scale_powPow(e) { + return function(x) { + return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + }; + } + d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5); + }; + d3.scale.ordinal = function() { + return d3_scale_ordinal([], { + t: "range", + a: [ [] ] + }); + }; + function d3_scale_ordinal(domain, ranger) { + var index, range, rangeBand; + function scale(x) { + return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; + } + function steps(start, step) { + return d3.range(domain.length).map(function(i) { + return start + step * i; + }); + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = []; + index = new d3_Map(); + var i = -1, n = x.length, xi; + while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); + return scale[ranger.t].apply(scale, ranger.a); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + rangeBand = 0; + ranger = { + t: "range", + a: arguments + }; + return scale; + }; + scale.rangePoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, + 0) : (stop - start) / (domain.length - 1 + padding); + range = steps(start + step * padding / 2, step); + rangeBand = 0; + ranger = { + t: "rangePoints", + a: arguments + }; + return scale; + }; + scale.rangeRoundPoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), + 0) : (stop - start) / (domain.length - 1 + padding) | 0; + range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); + rangeBand = 0; + ranger = { + t: "rangeRoundPoints", + a: arguments + }; + return scale; + }; + scale.rangeBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); + range = steps(start + step * outerPadding, step); + if (reverse) range.reverse(); + rangeBand = step * (1 - padding); + ranger = { + t: "rangeBands", + a: arguments + }; + return scale; + }; + scale.rangeRoundBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); + range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); + if (reverse) range.reverse(); + rangeBand = Math.round(step * (1 - padding)); + ranger = { + t: "rangeRoundBands", + a: arguments + }; + return scale; + }; + scale.rangeBand = function() { + return rangeBand; + }; + scale.rangeExtent = function() { + return d3_scaleExtent(ranger.a[0]); + }; + scale.copy = function() { + return d3_scale_ordinal(domain, ranger); + }; + return scale.domain(domain); + } + d3.scale.category10 = function() { + return d3.scale.ordinal().range(d3_category10); + }; + d3.scale.category20 = function() { + return d3.scale.ordinal().range(d3_category20); + }; + d3.scale.category20b = function() { + return d3.scale.ordinal().range(d3_category20b); + }; + d3.scale.category20c = function() { + return d3.scale.ordinal().range(d3_category20c); + }; + var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); + var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); + var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); + var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); + d3.scale.quantile = function() { + return d3_scale_quantile([], []); + }; + function d3_scale_quantile(domain, range) { + var thresholds; + function rescale() { + var k = 0, q = range.length; + thresholds = []; + while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); + return scale; + } + function scale(x) { + if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.quantiles = function() { + return thresholds; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; + }; + scale.copy = function() { + return d3_scale_quantile(domain, range); + }; + return rescale(); + } + d3.scale.quantize = function() { + return d3_scale_quantize(0, 1, [ 0, 1 ]); + }; + function d3_scale_quantize(x0, x1, range) { + var kx, i; + function scale(x) { + return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; + } + function rescale() { + kx = range.length / (x1 - x0); + i = range.length - 1; + return scale; + } + scale.domain = function(x) { + if (!arguments.length) return [ x0, x1 ]; + x0 = +x[0]; + x1 = +x[x.length - 1]; + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + y = y < 0 ? NaN : y / kx + x0; + return [ y, y + 1 / kx ]; + }; + scale.copy = function() { + return d3_scale_quantize(x0, x1, range); + }; + return rescale(); + } + d3.scale.threshold = function() { + return d3_scale_threshold([ .5 ], [ 0, 1 ]); + }; + function d3_scale_threshold(domain, range) { + function scale(x) { + if (x <= x) return range[d3.bisect(domain, x)]; + } + scale.domain = function(_) { + if (!arguments.length) return domain; + domain = _; + return scale; + }; + scale.range = function(_) { + if (!arguments.length) return range; + range = _; + return scale; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return [ domain[y - 1], domain[y] ]; + }; + scale.copy = function() { + return d3_scale_threshold(domain, range); + }; + return scale; + } + d3.scale.identity = function() { + return d3_scale_identity([ 0, 1 ]); + }; + function d3_scale_identity(domain) { + function identity(x) { + return +x; + } + identity.invert = identity; + identity.domain = identity.range = function(x) { + if (!arguments.length) return domain; + domain = x.map(identity); + return identity; + }; + identity.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + identity.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + identity.copy = function() { + return d3_scale_identity(domain); + }; + return identity; + } + d3.svg = {}; + function d3_zero() { + return 0; + } + d3.svg.arc = function() { + var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; + function arc() { + var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; + if (r1 < r0) rc = r1, r1 = r0, r0 = rc; + if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; + var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; + if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { + rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); + if (!cw) p1 *= -1; + if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); + if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); + } + if (r1) { + x0 = r1 * Math.cos(a0 + p1); + y0 = r1 * Math.sin(a0 + p1); + x1 = r1 * Math.cos(a1 - p1); + y1 = r1 * Math.sin(a1 - p1); + var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; + if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { + var h1 = (a0 + a1) / 2; + x0 = r1 * Math.cos(h1); + y0 = r1 * Math.sin(h1); + x1 = y1 = null; + } + } else { + x0 = y0 = 0; + } + if (r0) { + x2 = r0 * Math.cos(a1 - p0); + y2 = r0 * Math.sin(a1 - p0); + x3 = r0 * Math.cos(a0 + p0); + y3 = r0 * Math.sin(a0 + p0); + var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; + if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { + var h0 = (a0 + a1) / 2; + x2 = r0 * Math.cos(h0); + y2 = r0 * Math.sin(h0); + x3 = y3 = null; + } + } else { + x2 = y2 = 0; + } + if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { + cr = r0 < r1 ^ cw ? 0 : 1; + var rc1 = rc, rc0 = rc; + if (da < π) { + var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); + rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); + } + if (x1 != null) { + var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); + if (rc === rc1) { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); + } else { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); + } + } else { + path.push("M", x0, ",", y0); + } + if (x3 != null) { + var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); + if (rc === rc0) { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } else { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } + } else { + path.push("L", x2, ",", y2); + } + } else { + path.push("M", x0, ",", y0); + if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); + path.push("L", x2, ",", y2); + if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); + } + path.push("Z"); + return path.join(""); + } + function circleSegment(r1, cw) { + return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; + } + arc.innerRadius = function(v) { + if (!arguments.length) return innerRadius; + innerRadius = d3_functor(v); + return arc; + }; + arc.outerRadius = function(v) { + if (!arguments.length) return outerRadius; + outerRadius = d3_functor(v); + return arc; + }; + arc.cornerRadius = function(v) { + if (!arguments.length) return cornerRadius; + cornerRadius = d3_functor(v); + return arc; + }; + arc.padRadius = function(v) { + if (!arguments.length) return padRadius; + padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); + return arc; + }; + arc.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return arc; + }; + arc.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return arc; + }; + arc.padAngle = function(v) { + if (!arguments.length) return padAngle; + padAngle = d3_functor(v); + return arc; + }; + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; + return [ Math.cos(a) * r, Math.sin(a) * r ]; + }; + return arc; + }; + var d3_svg_arcAuto = "auto"; + function d3_svg_arcInnerRadius(d) { + return d.innerRadius; + } + function d3_svg_arcOuterRadius(d) { + return d.outerRadius; + } + function d3_svg_arcStartAngle(d) { + return d.startAngle; + } + function d3_svg_arcEndAngle(d) { + return d.endAngle; + } + function d3_svg_arcPadAngle(d) { + return d && d.padAngle; + } + function d3_svg_arcSweep(x0, y0, x1, y1) { + return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; + } + function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { + var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; + } + function d3_svg_line(projection) { + var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; + function line(data) { + var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); + function segment() { + segments.push("M", interpolate(projection(points), tension)); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); + } else if (points.length) { + segment(); + points = []; + } + } + if (points.length) segment(); + return segments.length ? segments.join("") : null; + } + line.x = function(_) { + if (!arguments.length) return x; + x = _; + return line; + }; + line.y = function(_) { + if (!arguments.length) return y; + y = _; + return line; + }; + line.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return line; + }; + line.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + return line; + }; + line.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return line; + }; + return line; + } + d3.svg.line = function() { + return d3_svg_line(d3_identity); + }; + var d3_svg_lineInterpolators = d3.map({ + linear: d3_svg_lineLinear, + "linear-closed": d3_svg_lineLinearClosed, + step: d3_svg_lineStep, + "step-before": d3_svg_lineStepBefore, + "step-after": d3_svg_lineStepAfter, + basis: d3_svg_lineBasis, + "basis-open": d3_svg_lineBasisOpen, + "basis-closed": d3_svg_lineBasisClosed, + bundle: d3_svg_lineBundle, + cardinal: d3_svg_lineCardinal, + "cardinal-open": d3_svg_lineCardinalOpen, + "cardinal-closed": d3_svg_lineCardinalClosed, + monotone: d3_svg_lineMonotone + }); + d3_svg_lineInterpolators.forEach(function(key, value) { + value.key = key; + value.closed = /-closed$/.test(key); + }); + function d3_svg_lineLinear(points) { + return points.length > 1 ? points.join("L") : points + "Z"; + } + function d3_svg_lineLinearClosed(points) { + return points.join("L") + "Z"; + } + function d3_svg_lineStep(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); + if (n > 1) path.push("H", p[0]); + return path.join(""); + } + function d3_svg_lineStepBefore(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); + return path.join(""); + } + function d3_svg_lineStepAfter(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); + return path.join(""); + } + function d3_svg_lineCardinalOpen(points, tension) { + return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineCardinalClosed(points, tension) { + return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), + points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + } + function d3_svg_lineCardinal(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineHermite(points, tangents) { + if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { + return d3_svg_lineLinear(points); + } + var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; + if (quad) { + path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; + p0 = points[1]; + pi = 2; + } + if (tangents.length > 1) { + t = tangents[1]; + p = points[pi]; + pi++; + path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + for (var i = 2; i < tangents.length; i++, pi++) { + p = points[pi]; + t = tangents[i]; + path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + } + } + if (quad) { + var lp = points[pi]; + path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + } + return path; + } + function d3_svg_lineCardinalTangents(points, tension) { + var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; + while (++i < n) { + p0 = p1; + p1 = p2; + p2 = points[i]; + tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + } + return tangents; + } + function d3_svg_lineBasis(points) { + if (points.length < 3) return d3_svg_lineLinear(points); + var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + points.push(points[n - 1]); + while (++i <= n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + points.pop(); + path.push("L", pi); + return path.join(""); + } + function d3_svg_lineBasisOpen(points) { + if (points.length < 4) return d3_svg_lineLinear(points); + var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; + while (++i < 3) { + pi = points[i]; + px.push(pi[0]); + py.push(pi[1]); + } + path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); + --i; + while (++i < n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBasisClosed(points) { + var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; + while (++i < 4) { + pi = points[i % n]; + px.push(pi[0]); + py.push(pi[1]); + } + path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + --i; + while (++i < m) { + pi = points[i % n]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBundle(points, tension) { + var n = points.length - 1; + if (n) { + var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; + while (++i <= n) { + p = points[i]; + t = i / n; + p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); + p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); + } + } + return d3_svg_lineBasis(points); + } + function d3_svg_lineDot4(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + } + var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; + function d3_svg_lineBasisBezier(path, x, y) { + path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); + } + function d3_svg_lineSlope(p0, p1) { + return (p1[1] - p0[1]) / (p1[0] - p0[0]); + } + function d3_svg_lineFiniteDifferences(points) { + var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); + while (++i < j) { + m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + } + m[i] = d; + return m; + } + function d3_svg_lineMonotoneTangents(points) { + var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; + while (++i < j) { + d = d3_svg_lineSlope(points[i], points[i + 1]); + if (abs(d) < ε) { + m[i] = m[i + 1] = 0; + } else { + a = m[i] / d; + b = m[i + 1] / d; + s = a * a + b * b; + if (s > 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } + } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); + tangents.push([ s || 0, m[i] * s || 0 ]); + } + return tangents; + } + function d3_svg_lineMonotone(points) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); + } + d3.svg.line.radial = function() { + var line = d3_svg_line(d3_svg_lineRadial); + line.radius = line.x, delete line.x; + line.angle = line.y, delete line.y; + return line; + }; + function d3_svg_lineRadial(points) { + var point, i = -1, n = points.length, r, a; + while (++i < n) { + point = points[i]; + r = point[0]; + a = point[1] - halfπ; + point[0] = r * Math.cos(a); + point[1] = r * Math.sin(a); + } + return points; + } + function d3_svg_area(projection) { + var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; + function area(data) { + var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { + return x; + } : d3_functor(x1), fy1 = y0 === y1 ? function() { + return y; + } : d3_functor(y1), x, y; + function segment() { + segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); + points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); + } else if (points0.length) { + segment(); + points0 = []; + points1 = []; + } + } + if (points0.length) segment(); + return segments.length ? segments.join("") : null; + } + area.x = function(_) { + if (!arguments.length) return x1; + x0 = x1 = _; + return area; + }; + area.x0 = function(_) { + if (!arguments.length) return x0; + x0 = _; + return area; + }; + area.x1 = function(_) { + if (!arguments.length) return x1; + x1 = _; + return area; + }; + area.y = function(_) { + if (!arguments.length) return y1; + y0 = y1 = _; + return area; + }; + area.y0 = function(_) { + if (!arguments.length) return y0; + y0 = _; + return area; + }; + area.y1 = function(_) { + if (!arguments.length) return y1; + y1 = _; + return area; + }; + area.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return area; + }; + area.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + interpolateReverse = interpolate.reverse || interpolate; + L = interpolate.closed ? "M" : "L"; + return area; + }; + area.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return area; + }; + return area; + } + d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; + d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; + d3.svg.area = function() { + return d3_svg_area(d3_identity); + }; + d3.svg.area.radial = function() { + var area = d3_svg_area(d3_svg_lineRadial); + area.radius = area.x, delete area.x; + area.innerRadius = area.x0, delete area.x0; + area.outerRadius = area.x1, delete area.x1; + area.angle = area.y, delete area.y; + area.startAngle = area.y0, delete area.y0; + area.endAngle = area.y1, delete area.y1; + return area; + }; + d3.svg.chord = function() { + var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; + function chord(d, i) { + var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); + return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; + } + function subgroup(self, f, d, i) { + var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; + return { + r: r, + a0: a0, + a1: a1, + p0: [ r * Math.cos(a0), r * Math.sin(a0) ], + p1: [ r * Math.cos(a1), r * Math.sin(a1) ] + }; + } + function equals(a, b) { + return a.a0 == b.a0 && a.a1 == b.a1; + } + function arc(r, p, a) { + return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; + } + function curve(r0, p0, r1, p1) { + return "Q 0,0 " + p1; + } + chord.radius = function(v) { + if (!arguments.length) return radius; + radius = d3_functor(v); + return chord; + }; + chord.source = function(v) { + if (!arguments.length) return source; + source = d3_functor(v); + return chord; + }; + chord.target = function(v) { + if (!arguments.length) return target; + target = d3_functor(v); + return chord; + }; + chord.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return chord; + }; + chord.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return chord; + }; + return chord; + }; + function d3_svg_chordRadius(d) { + return d.radius; + } + d3.svg.diagonal = function() { + var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; + function diagonal(d, i) { + var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { + x: p0.x, + y: m + }, { + x: p3.x, + y: m + }, p3 ]; + p = p.map(projection); + return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; + } + diagonal.source = function(x) { + if (!arguments.length) return source; + source = d3_functor(x); + return diagonal; + }; + diagonal.target = function(x) { + if (!arguments.length) return target; + target = d3_functor(x); + return diagonal; + }; + diagonal.projection = function(x) { + if (!arguments.length) return projection; + projection = x; + return diagonal; + }; + return diagonal; + }; + function d3_svg_diagonalProjection(d) { + return [ d.x, d.y ]; + } + d3.svg.diagonal.radial = function() { + var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; + diagonal.projection = function(x) { + return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; + }; + return diagonal; + }; + function d3_svg_diagonalRadialProjection(projection) { + return function() { + var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; + return [ r * Math.cos(a), r * Math.sin(a) ]; + }; + } + d3.svg.symbol = function() { + var type = d3_svg_symbolType, size = d3_svg_symbolSize; + function symbol(d, i) { + return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); + } + symbol.type = function(x) { + if (!arguments.length) return type; + type = d3_functor(x); + return symbol; + }; + symbol.size = function(x) { + if (!arguments.length) return size; + size = d3_functor(x); + return symbol; + }; + return symbol; + }; + function d3_svg_symbolSize() { + return 64; + } + function d3_svg_symbolType() { + return "circle"; + } + function d3_svg_symbolCircle(size) { + var r = Math.sqrt(size / π); + return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + } + var d3_svg_symbols = d3.map({ + circle: d3_svg_symbolCircle, + cross: function(size) { + var r = Math.sqrt(size / 5) / 2; + return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; + }, + diamond: function(size) { + var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; + return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; + }, + square: function(size) { + var r = Math.sqrt(size) / 2; + return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; + }, + "triangle-down": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; + }, + "triangle-up": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; + } + }); + d3.svg.symbolTypes = d3_svg_symbols.keys(); + var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); + d3_selectionPrototype.transition = function(name) { + var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { + time: Date.now(), + ease: d3_ease_cubicInOut, + delay: 0, + duration: 250 + }; + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id); + }; + d3_selectionPrototype.interrupt = function(name) { + return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); + }; + var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); + function d3_selection_interruptNS(ns) { + return function() { + var lock, activeId, active; + if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { + active.timer.c = null; + active.timer.t = NaN; + if (--lock.count) delete lock[activeId]; else delete this[ns]; + lock.active += .5; + active.event && active.event.interrupt.call(this, this.__data__, active.index); + } + }; + } + function d3_transition(groups, ns, id) { + d3_subclass(groups, d3_transitionPrototype); + groups.namespace = ns; + groups.id = id; + return groups; + } + var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; + d3_transitionPrototype.call = d3_selectionPrototype.call; + d3_transitionPrototype.empty = d3_selectionPrototype.empty; + d3_transitionPrototype.node = d3_selectionPrototype.node; + d3_transitionPrototype.size = d3_selectionPrototype.size; + d3.transition = function(selection, name) { + return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); + }; + d3.transition.prototype = d3_transitionPrototype; + d3_transitionPrototype.select = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + d3_transitionNode(subnode, i, ns, id, node[ns][id]); + subgroup.push(subnode); + } else { + subgroup.push(null); + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.selectAll = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + transition = node[ns][id]; + subnodes = selector.call(node, node.__data__, i, j); + subgroups.push(subgroup = []); + for (var k = -1, o = subnodes.length; ++k < o; ) { + if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); + subgroup.push(subnode); + } + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_transition(subgroups, this.namespace, this.id); + }; + d3_transitionPrototype.tween = function(name, tween) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) return this.node()[ns][id].tween.get(name); + return d3_selection_each(this, tween == null ? function(node) { + node[ns][id].tween.remove(name); + } : function(node) { + node[ns][id].tween.set(name, tween); + }); + }; + function d3_transition_tween(groups, name, value, tween) { + var id = groups.id, ns = groups.namespace; + return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { + node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); + } : (value = tween(value), function(node) { + node[ns][id].tween.set(name, value); + })); + } + d3_transitionPrototype.attr = function(nameNS, value) { + if (arguments.length < 2) { + for (value in nameNS) this.attr(value, nameNS[value]); + return this; + } + var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrTween(b) { + return b == null ? attrNull : (b += "", function() { + var a = this.getAttribute(name), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttribute(name, i(t)); + }); + }); + } + function attrTweenNS(b) { + return b == null ? attrNullNS : (b += "", function() { + var a = this.getAttributeNS(name.space, name.local), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttributeNS(name.space, name.local, i(t)); + }); + }); + } + return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.attrTween = function(nameNS, tween) { + var name = d3.ns.qualify(nameNS); + function attrTween(d, i) { + var f = tween.call(this, d, i, this.getAttribute(name)); + return f && function(t) { + this.setAttribute(name, f(t)); + }; + } + function attrTweenNS(d, i) { + var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); + return f && function(t) { + this.setAttributeNS(name.space, name.local, f(t)); + }; + } + return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.style(priority, name[priority], value); + return this; + } + priority = ""; + } + function styleNull() { + this.style.removeProperty(name); + } + function styleString(b) { + return b == null ? styleNull : (b += "", function() { + var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; + return a !== b && (i = d3_interpolate(a, b), function(t) { + this.style.setProperty(name, i(t), priority); + }); + }); + } + return d3_transition_tween(this, "style." + name, value, styleString); + }; + d3_transitionPrototype.styleTween = function(name, tween, priority) { + if (arguments.length < 3) priority = ""; + function styleTween(d, i) { + var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); + return f && function(t) { + this.style.setProperty(name, f(t), priority); + }; + } + return this.tween("style." + name, styleTween); + }; + d3_transitionPrototype.text = function(value) { + return d3_transition_tween(this, "text", value, d3_transition_text); + }; + function d3_transition_text(b) { + if (b == null) b = ""; + return function() { + this.textContent = b; + }; + } + d3_transitionPrototype.remove = function() { + var ns = this.namespace; + return this.each("end.transition", function() { + var p; + if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); + }); + }; + d3_transitionPrototype.ease = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].ease; + if (typeof value !== "function") value = d3.ease.apply(d3, arguments); + return d3_selection_each(this, function(node) { + node[ns][id].ease = value; + }); + }; + d3_transitionPrototype.delay = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].delay; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].delay = +value.call(node, node.__data__, i, j); + } : (value = +value, function(node) { + node[ns][id].delay = value; + })); + }; + d3_transitionPrototype.duration = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].duration; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); + } : (value = Math.max(1, value), function(node) { + node[ns][id].duration = value; + })); + }; + d3_transitionPrototype.each = function(type, listener) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) { + var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; + try { + d3_transitionInheritId = id; + d3_selection_each(this, function(node, i, j) { + d3_transitionInherit = node[ns][id]; + type.call(node, node.__data__, i, j); + }); + } finally { + d3_transitionInherit = inherit; + d3_transitionInheritId = inheritId; + } + } else { + d3_selection_each(this, function(node) { + var transition = node[ns][id]; + (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); + }); + } + return this; + }; + d3_transitionPrototype.transition = function() { + var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if (node = group[i]) { + transition = node[ns][id0]; + d3_transitionNode(node, i, ns, id1, { + time: transition.time, + ease: transition.ease, + delay: transition.delay + transition.duration, + duration: transition.duration + }); + } + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id1); + }; + function d3_transitionNamespace(name) { + return name == null ? "__transition__" : "__transition_" + name + "__"; + } + function d3_transitionNode(node, i, ns, id, inherit) { + var lock = node[ns] || (node[ns] = { + active: 0, + count: 0 + }), transition = lock[id], time, timer, duration, ease, tweens; + function schedule(elapsed) { + var delay = transition.delay; + timer.t = delay + time; + if (delay <= elapsed) return start(elapsed - delay); + timer.c = start; + } + function start(elapsed) { + var activeId = lock.active, active = lock[activeId]; + if (active) { + active.timer.c = null; + active.timer.t = NaN; + --lock.count; + delete lock[activeId]; + active.event && active.event.interrupt.call(node, node.__data__, active.index); + } + for (var cancelId in lock) { + if (+cancelId < id) { + var cancel = lock[cancelId]; + cancel.timer.c = null; + cancel.timer.t = NaN; + --lock.count; + delete lock[cancelId]; + } + } + timer.c = tick; + d3_timer(function() { + if (timer.c && tick(elapsed || 1)) { + timer.c = null; + timer.t = NaN; + } + return 1; + }, 0, time); + lock.active = id; + transition.event && transition.event.start.call(node, node.__data__, i); + tweens = []; + transition.tween.forEach(function(key, value) { + if (value = value.call(node, node.__data__, i)) { + tweens.push(value); + } + }); + ease = transition.ease; + duration = transition.duration; + } + function tick(elapsed) { + var t = elapsed / duration, e = ease(t), n = tweens.length; + while (n > 0) { + tweens[--n].call(node, e); + } + if (t >= 1) { + transition.event && transition.event.end.call(node, node.__data__, i); + if (--lock.count) delete lock[id]; else delete node[ns]; + return 1; + } + } + if (!transition) { + time = inherit.time; + timer = d3_timer(schedule, 0, time); + transition = lock[id] = { + tween: new d3_Map(), + time: time, + timer: timer, + delay: inherit.delay, + duration: inherit.duration, + ease: inherit.ease, + index: i + }; + inherit = null; + ++lock.count; + } + } + d3.svg.axis = function() { + var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; + function axis(g) { + g.each(function() { + var g = d3.select(this); + var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); + var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; + var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), + d3.transition(path)); + tickEnter.append("line"); + tickEnter.append("text"); + var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; + if (orient === "bottom" || orient === "top") { + tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; + text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); + } else { + tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; + text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); + pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); + } + lineEnter.attr(y2, sign * innerTickSize); + textEnter.attr(y1, sign * tickSpacing); + lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); + textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); + if (scale1.rangeBand) { + var x = scale1, dx = x.rangeBand() / 2; + scale0 = scale1 = function(d) { + return x(d) + dx; + }; + } else if (scale0.rangeBand) { + scale0 = scale1; + } else { + tickExit.call(tickTransform, scale1, scale0); + } + tickEnter.call(tickTransform, scale0, scale1); + tickUpdate.call(tickTransform, scale1, scale1); + }); + } + axis.scale = function(x) { + if (!arguments.length) return scale; + scale = x; + return axis; + }; + axis.orient = function(x) { + if (!arguments.length) return orient; + orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; + return axis; + }; + axis.ticks = function() { + if (!arguments.length) return tickArguments_; + tickArguments_ = d3_array(arguments); + return axis; + }; + axis.tickValues = function(x) { + if (!arguments.length) return tickValues; + tickValues = x; + return axis; + }; + axis.tickFormat = function(x) { + if (!arguments.length) return tickFormat_; + tickFormat_ = x; + return axis; + }; + axis.tickSize = function(x) { + var n = arguments.length; + if (!n) return innerTickSize; + innerTickSize = +x; + outerTickSize = +arguments[n - 1]; + return axis; + }; + axis.innerTickSize = function(x) { + if (!arguments.length) return innerTickSize; + innerTickSize = +x; + return axis; + }; + axis.outerTickSize = function(x) { + if (!arguments.length) return outerTickSize; + outerTickSize = +x; + return axis; + }; + axis.tickPadding = function(x) { + if (!arguments.length) return tickPadding; + tickPadding = +x; + return axis; + }; + axis.tickSubdivide = function() { + return arguments.length && axis; + }; + return axis; + }; + var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { + top: 1, + right: 1, + bottom: 1, + left: 1 + }; + function d3_svg_axisX(selection, x0, x1) { + selection.attr("transform", function(d) { + var v0 = x0(d); + return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; + }); + } + function d3_svg_axisY(selection, y0, y1) { + selection.attr("transform", function(d) { + var v0 = y0(d); + return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; + }); + } + d3.svg.brush = function() { + var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; + function brush(g) { + g.each(function() { + var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); + var background = g.selectAll(".background").data([ 0 ]); + background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); + g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); + var resize = g.selectAll(".resize").data(resizes, d3_identity); + resize.exit().remove(); + resize.enter().append("g").attr("class", function(d) { + return "resize " + d; + }).style("cursor", function(d) { + return d3_svg_brushCursor[d]; + }).append("rect").attr("x", function(d) { + return /[ew]$/.test(d) ? -3 : null; + }).attr("y", function(d) { + return /^[ns]/.test(d) ? -3 : null; + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); + resize.style("display", brush.empty() ? "none" : null); + var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; + if (x) { + range = d3_scaleRange(x); + backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); + redrawX(gUpdate); + } + if (y) { + range = d3_scaleRange(y); + backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); + redrawY(gUpdate); + } + redraw(gUpdate); + }); + } + brush.event = function(g) { + g.each(function() { + var event_ = event.of(this, arguments), extent1 = { + x: xExtent, + y: yExtent, + i: xExtentDomain, + j: yExtentDomain + }, extent0 = this.__chart__ || extent1; + this.__chart__ = extent1; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.brush", function() { + xExtentDomain = extent0.i; + yExtentDomain = extent0.j; + xExtent = extent0.x; + yExtent = extent0.y; + event_({ + type: "brushstart" + }); + }).tween("brush:brush", function() { + var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); + xExtentDomain = yExtentDomain = null; + return function(t) { + xExtent = extent1.x = xi(t); + yExtent = extent1.y = yi(t); + event_({ + type: "brush", + mode: "resize" + }); + }; + }).each("end.brush", function() { + xExtentDomain = extent1.i; + yExtentDomain = extent1.j; + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + }); + } else { + event_({ + type: "brushstart" + }); + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + } + }); + }; + function redraw(g) { + g.selectAll(".resize").attr("transform", function(d) { + return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; + }); + } + function redrawX(g) { + g.select(".extent").attr("x", xExtent[0]); + g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); + } + function redrawY(g) { + g.select(".extent").attr("y", yExtent[0]); + g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); + } + function brushstart() { + var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; + var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); + if (d3.event.changedTouches) { + w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); + } else { + w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); + } + g.interrupt().selectAll("*").interrupt(); + if (dragging) { + origin[0] = xExtent[0] - origin[0]; + origin[1] = yExtent[0] - origin[1]; + } else if (resizing) { + var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); + offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; + origin[0] = xExtent[ex]; + origin[1] = yExtent[ey]; + } else if (d3.event.altKey) center = origin.slice(); + g.style("pointer-events", "none").selectAll(".resize").style("display", null); + d3.select("body").style("cursor", eventTarget.style("cursor")); + event_({ + type: "brushstart" + }); + brushmove(); + function keydown() { + if (d3.event.keyCode == 32) { + if (!dragging) { + center = null; + origin[0] -= xExtent[1]; + origin[1] -= yExtent[1]; + dragging = 2; + } + d3_eventPreventDefault(); + } + } + function keyup() { + if (d3.event.keyCode == 32 && dragging == 2) { + origin[0] += xExtent[1]; + origin[1] += yExtent[1]; + dragging = 0; + d3_eventPreventDefault(); + } + } + function brushmove() { + var point = d3.mouse(target), moved = false; + if (offset) { + point[0] += offset[0]; + point[1] += offset[1]; + } + if (!dragging) { + if (d3.event.altKey) { + if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; + origin[0] = xExtent[+(point[0] < center[0])]; + origin[1] = yExtent[+(point[1] < center[1])]; + } else center = null; + } + if (resizingX && move1(point, x, 0)) { + redrawX(g); + moved = true; + } + if (resizingY && move1(point, y, 1)) { + redrawY(g); + moved = true; + } + if (moved) { + redraw(g); + event_({ + type: "brush", + mode: dragging ? "move" : "resize" + }); + } + } + function move1(point, scale, i) { + var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; + if (dragging) { + r0 -= position; + r1 -= size + position; + } + min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; + if (dragging) { + max = (min += position) + size; + } else { + if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); + if (position < min) { + max = min; + min = position; + } else { + max = position; + } + } + if (extent[0] != min || extent[1] != max) { + if (i) yExtentDomain = null; else xExtentDomain = null; + extent[0] = min; + extent[1] = max; + return true; + } + } + function brushend() { + brushmove(); + g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); + d3.select("body").style("cursor", null); + w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); + dragRestore(); + event_({ + type: "brushend" + }); + } + } + brush.x = function(z) { + if (!arguments.length) return x; + x = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.y = function(z) { + if (!arguments.length) return y; + y = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.clamp = function(z) { + if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; + if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; + return brush; + }; + brush.extent = function(z) { + var x0, x1, y0, y1, t; + if (!arguments.length) { + if (x) { + if (xExtentDomain) { + x0 = xExtentDomain[0], x1 = xExtentDomain[1]; + } else { + x0 = xExtent[0], x1 = xExtent[1]; + if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + } + } + if (y) { + if (yExtentDomain) { + y0 = yExtentDomain[0], y1 = yExtentDomain[1]; + } else { + y0 = yExtent[0], y1 = yExtent[1]; + if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + } + } + return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; + } + if (x) { + x0 = z[0], x1 = z[1]; + if (y) x0 = x0[0], x1 = x1[0]; + xExtentDomain = [ x0, x1 ]; + if (x.invert) x0 = x(x0), x1 = x(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; + } + if (y) { + y0 = z[0], y1 = z[1]; + if (x) y0 = y0[1], y1 = y1[1]; + yExtentDomain = [ y0, y1 ]; + if (y.invert) y0 = y(y0), y1 = y(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; + } + return brush; + }; + brush.clear = function() { + if (!brush.empty()) { + xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; + xExtentDomain = yExtentDomain = null; + } + return brush; + }; + brush.empty = function() { + return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + }; + return d3.rebind(brush, event, "on"); + }; + var d3_svg_brushCursor = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; + var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; + var d3_time_formatUtc = d3_time_format.utc; + var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; + function d3_time_formatIsoNative(date) { + return date.toISOString(); + } + d3_time_formatIsoNative.parse = function(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + }; + d3_time_formatIsoNative.toString = d3_time_formatIso.toString; + d3_time.second = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 1e3) * 1e3); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 1e3); + }, function(date) { + return date.getSeconds(); + }); + d3_time.seconds = d3_time.second.range; + d3_time.seconds.utc = d3_time.second.utc.range; + d3_time.minute = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 6e4) * 6e4); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 6e4); + }, function(date) { + return date.getMinutes(); + }); + d3_time.minutes = d3_time.minute.range; + d3_time.minutes.utc = d3_time.minute.utc.range; + d3_time.hour = d3_time_interval(function(date) { + var timezone = date.getTimezoneOffset() / 60; + return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 36e5); + }, function(date) { + return date.getHours(); + }); + d3_time.hours = d3_time.hour.range; + d3_time.hours.utc = d3_time.hour.utc.range; + d3_time.month = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setDate(1); + return date; + }, function(date, offset) { + date.setMonth(date.getMonth() + offset); + }, function(date) { + return date.getMonth(); + }); + d3_time.months = d3_time.month.range; + d3_time.months.utc = d3_time.month.utc.range; + function d3_time_scale(linear, methods, format) { + function scale(x) { + return linear(x); + } + scale.invert = function(x) { + return d3_time_scaleDate(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return linear.domain().map(d3_time_scaleDate); + linear.domain(x); + return scale; + }; + function tickMethod(extent, count) { + var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); + return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { + return d / 31536e6; + }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; + } + scale.nice = function(interval, skip) { + var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); + if (method) interval = method[0], skip = method[1]; + function skipped(date) { + return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; + } + return scale.domain(d3_scale_nice(domain, skip > 1 ? { + floor: function(date) { + while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); + return date; + }, + ceil: function(date) { + while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); + return date; + } + } : interval)); + }; + scale.ticks = function(interval, skip) { + var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { + range: interval + }, skip ]; + if (method) interval = method[0], skip = method[1]; + return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + }; + scale.tickFormat = function() { + return format; + }; + scale.copy = function() { + return d3_time_scale(linear.copy(), methods, format); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_time_scaleDate(t) { + return new Date(t); + } + var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; + var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; + var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { + return d.getMilliseconds(); + } ], [ ":%S", function(d) { + return d.getSeconds(); + } ], [ "%I:%M", function(d) { + return d.getMinutes(); + } ], [ "%I %p", function(d) { + return d.getHours(); + } ], [ "%a %d", function(d) { + return d.getDay() && d.getDate() != 1; + } ], [ "%b %d", function(d) { + return d.getDate() != 1; + } ], [ "%B", function(d) { + return d.getMonth(); + } ], [ "%Y", d3_true ] ]); + var d3_time_scaleMilliseconds = { + range: function(start, stop, step) { + return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); + }, + floor: d3_identity, + ceil: d3_identity + }; + d3_time_scaleLocalMethods.year = d3_time.year; + d3_time.scale = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + }; + var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { + return [ m[0].utc, m[1] ]; + }); + var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { + return d.getUTCMilliseconds(); + } ], [ ":%S", function(d) { + return d.getUTCSeconds(); + } ], [ "%I:%M", function(d) { + return d.getUTCMinutes(); + } ], [ "%I %p", function(d) { + return d.getUTCHours(); + } ], [ "%a %d", function(d) { + return d.getUTCDay() && d.getUTCDate() != 1; + } ], [ "%b %d", function(d) { + return d.getUTCDate() != 1; + } ], [ "%B", function(d) { + return d.getUTCMonth(); + } ], [ "%Y", d3_true ] ]); + d3_time_scaleUtcMethods.year = d3_time.year.utc; + d3_time.scale.utc = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); + }; + d3.text = d3_xhrType(function(request) { + return request.responseText; + }); + d3.json = function(url, callback) { + return d3_xhr(url, "application/json", d3_json, callback); + }; + function d3_json(request) { + return JSON.parse(request.responseText); + } + d3.html = function(url, callback) { + return d3_xhr(url, "text/html", d3_html, callback); + }; + function d3_html(request) { + var range = d3_document.createRange(); + range.selectNode(d3_document.body); + return range.createContextualFragment(request.responseText); + } + d3.xml = d3_xhrType(function(request) { + return request.responseXML; + }); + if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; +}(); +},{}],149:[function(_dereq_,module,exports){ +module.exports = function () { + for (var i = 0; i < arguments.length; i++) { + if (arguments[i] !== undefined) return arguments[i]; + } +}; + +},{}],150:[function(_dereq_,module,exports){ +"use strict" + +var ch = _dereq_("incremental-convex-hull") +var uniq = _dereq_("uniq") + +module.exports = triangulate + +function LiftedPoint(p, i) { + this.point = p + this.index = i +} + +function compareLifted(a, b) { + var ap = a.point + var bp = b.point + var d = ap.length + for(var i=0; i= 2) { + return false + } + } + cell[j] = v + } + return true + }) + } else { + hull = hull.filter(function(cell) { + for(var i=0; i<=d; ++i) { + var v = dindex[cell[i]] + if(v < 0) { + return false + } + cell[i] = v + } + return true + }) + } + + if(d & 1) { + for(var i=0; i fs * threshold) { + var emWidth = (kerningWidth - width) / fs + table[pair] = emWidth * 1000 + } + } + + return table +} + + +function createPairs (range) { + var pairs = [] + + for (var i = range[0]; i <= range[1]; i++) { + var leftChar = String.fromCharCode(i) + for (var j = range[0]; j < range[1]; j++) { + var rightChar = String.fromCharCode(j) + var pair = leftChar + rightChar + + pairs.push(pair) + } + } + + return pairs +} + +},{}],152:[function(_dereq_,module,exports){ +(function (Buffer){ +var hasTypedArrays = false +if(typeof Float64Array !== "undefined") { + var DOUBLE_VIEW = new Float64Array(1) + , UINT_VIEW = new Uint32Array(DOUBLE_VIEW.buffer) + DOUBLE_VIEW[0] = 1.0 + hasTypedArrays = true + if(UINT_VIEW[1] === 0x3ff00000) { + //Use little endian + module.exports = function doubleBitsLE(n) { + DOUBLE_VIEW[0] = n + return [ UINT_VIEW[0], UINT_VIEW[1] ] + } + function toDoubleLE(lo, hi) { + UINT_VIEW[0] = lo + UINT_VIEW[1] = hi + return DOUBLE_VIEW[0] + } + module.exports.pack = toDoubleLE + function lowUintLE(n) { + DOUBLE_VIEW[0] = n + return UINT_VIEW[0] + } + module.exports.lo = lowUintLE + function highUintLE(n) { + DOUBLE_VIEW[0] = n + return UINT_VIEW[1] + } + module.exports.hi = highUintLE + } else if(UINT_VIEW[0] === 0x3ff00000) { + //Use big endian + module.exports = function doubleBitsBE(n) { + DOUBLE_VIEW[0] = n + return [ UINT_VIEW[1], UINT_VIEW[0] ] + } + function toDoubleBE(lo, hi) { + UINT_VIEW[1] = lo + UINT_VIEW[0] = hi + return DOUBLE_VIEW[0] + } + module.exports.pack = toDoubleBE + function lowUintBE(n) { + DOUBLE_VIEW[0] = n + return UINT_VIEW[1] + } + module.exports.lo = lowUintBE + function highUintBE(n) { + DOUBLE_VIEW[0] = n + return UINT_VIEW[0] + } + module.exports.hi = highUintBE + } else { + hasTypedArrays = false + } +} +if(!hasTypedArrays) { + var buffer = new Buffer(8) + module.exports = function doubleBits(n) { + buffer.writeDoubleLE(n, 0, true) + return [ buffer.readUInt32LE(0, true), buffer.readUInt32LE(4, true) ] + } + function toDouble(lo, hi) { + buffer.writeUInt32LE(lo, 0, true) + buffer.writeUInt32LE(hi, 4, true) + return buffer.readDoubleLE(0, true) + } + module.exports.pack = toDouble + function lowUint(n) { + buffer.writeDoubleLE(n, 0, true) + return buffer.readUInt32LE(0, true) + } + module.exports.lo = lowUint + function highUint(n) { + buffer.writeDoubleLE(n, 0, true) + return buffer.readUInt32LE(4, true) + } + module.exports.hi = highUint +} + +module.exports.sign = function(n) { + return module.exports.hi(n) >>> 31 +} + +module.exports.exponent = function(n) { + var b = module.exports.hi(n) + return ((b<<1) >>> 21) - 1023 +} + +module.exports.fraction = function(n) { + var lo = module.exports.lo(n) + var hi = module.exports.hi(n) + var b = hi & ((1<<20) - 1) + if(hi & 0x7ff00000) { + b += (1<<20) + } + return [lo, b] +} + +module.exports.denormalized = function(n) { + var hi = module.exports.hi(n) + return !(hi & 0x7ff00000) +} +}).call(this,_dereq_("buffer").Buffer) + +},{"buffer":93}],153:[function(_dereq_,module,exports){ +var abs = _dereq_('abs-svg-path') +var normalize = _dereq_('normalize-svg-path') + +var methods = { + 'M': 'moveTo', + 'C': 'bezierCurveTo' +} + +module.exports = function(context, segments) { + context.beginPath() + + // Make path easy to reproduce. + normalize(abs(segments)).forEach( + function(segment) { + var command = segment[0] + var args = segment.slice(1) + + // Convert the path command to a context method. + context[methods[command]].apply(context, args) + } + ) + + context.closePath() +} + +},{"abs-svg-path":48,"normalize-svg-path":435}],154:[function(_dereq_,module,exports){ +module.exports = function(dtype) { + switch (dtype) { + case 'int8': + return Int8Array + case 'int16': + return Int16Array + case 'int32': + return Int32Array + case 'uint8': + return Uint8Array + case 'uint16': + return Uint16Array + case 'uint32': + return Uint32Array + case 'float32': + return Float32Array + case 'float64': + return Float64Array + case 'array': + return Array + case 'uint8_clamped': + return Uint8ClampedArray + } +} + +},{}],155:[function(_dereq_,module,exports){ +"use strict" + +function dupe_array(count, value, i) { + var c = count[i]|0 + if(c <= 0) { + return [] + } + var result = new Array(c), j + if(i === count.length-1) { + for(j=0; j 0) { + return dupe_number(count|0, value) + } + break + case "object": + if(typeof (count.length) === "number") { + return dupe_array(count, value, 0) + } + break + } + return [] +} + +module.exports = dupe +},{}],156:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = earcut; +module.exports.default = earcut; + +function earcut(data, holeIndices, dim) { + + dim = dim || 2; + + var hasHoles = holeIndices && holeIndices.length, + outerLen = hasHoles ? holeIndices[0] * dim : data.length, + outerNode = linkedList(data, 0, outerLen, dim, true), + triangles = []; + + if (!outerNode) return triangles; + + var minX, minY, maxX, maxY, x, y, invSize; + + if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + + for (var i = dim; i < outerLen; i += dim) { + x = data[i]; + y = data[i + 1]; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + + // minX, minY and invSize are later used to transform coords into integers for z-order calculation + invSize = Math.max(maxX - minX, maxY - minY); + invSize = invSize !== 0 ? 1 / invSize : 0; + } + + earcutLinked(outerNode, triangles, dim, minX, minY, invSize); + + return triangles; +} + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList(data, start, end, dim, clockwise) { + var i, last; + + if (clockwise === (signedArea(data, start, end, dim) > 0)) { + for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + } + + if (last && equals(last, last.next)) { + removeNode(last); + last = last.next; + } + + return last; +} + +// eliminate colinear or duplicate points +function filterPoints(start, end) { + if (!start) return start; + if (!end) end = start; + + var p = start, + again; + do { + again = false; + + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) break; + again = true; + + } else { + p = p.next; + } + } while (again || p !== end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && invSize) indexCurve(ear, minX, minY, invSize); + + var stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + + if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { + // cut off the triangle + triangles.push(prev.i / dim); + triangles.push(ear.i / dim); + triangles.push(next.i / dim); + + removeNode(ear); + + // skipping the next vertice leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear === stop) { + // try filtering points and slicing again + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); + + // if this didn't work, try curing all small self-intersections locally + } else if (pass === 1) { + ear = cureLocalIntersections(ear, triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, invSize); + } + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar(ear) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + var p = ear.next.next; + + while (p !== ear.prev) { + if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.next; + } + + return true; +} + +function isEarHashed(ear, minX, minY, invSize) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // triangle bbox; min & max are calculated like this for speed + var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), + minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), + maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), + maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); + + // z-order range for the current triangle bbox; + var minZ = zOrder(minTX, minTY, minX, minY, invSize), + maxZ = zOrder(maxTX, maxTY, minX, minY, invSize); + + var p = ear.prevZ, + n = ear.nextZ; + + // look for points inside the triangle in both directions + while (p && p.z >= minZ && n && n.z <= maxZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + + if (n !== ear.prev && n !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && + area(n.prev, n, n.next) >= 0) return false; + n = n.nextZ; + } + + // look for remaining points in decreasing z-order + while (p && p.z >= minZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + } + + // look for remaining points in increasing z-order + while (n && n.z <= maxZ) { + if (n !== ear.prev && n !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && + area(n.prev, n, n.next) >= 0) return false; + n = n.nextZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections(start, triangles, dim) { + var p = start; + do { + var a = p.prev, + b = p.next.next; + + if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { + + triangles.push(a.i / dim); + triangles.push(p.i / dim); + triangles.push(b.i / dim); + + // remove two nodes involved + removeNode(p); + removeNode(p.next); + + p = start = b; + } + p = p.next; + } while (p !== start); + + return p; +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut(start, triangles, dim, minX, minY, invSize) { + // look for a valid diagonal that divides the polygon into two + var a = start; + do { + var b = a.next.next; + while (b !== a.prev) { + if (a.i !== b.i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + var c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a.next); + c = filterPoints(c, c.next); + + // run earcut on each half + earcutLinked(a, triangles, dim, minX, minY, invSize); + earcutLinked(c, triangles, dim, minX, minY, invSize); + return; + } + b = b.next; + } + a = a.next; + } while (a !== start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles(data, holeIndices, outerNode, dim) { + var queue = [], + i, len, start, end, list; + + for (i = 0, len = holeIndices.length; i < len; i++) { + start = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start, end, dim, false); + if (list === list.next) list.steiner = true; + queue.push(getLeftmost(list)); + } + + queue.sort(compareX); + + // process holes from left to right + for (i = 0; i < queue.length; i++) { + eliminateHole(queue[i], outerNode); + outerNode = filterPoints(outerNode, outerNode.next); + } + + return outerNode; +} + +function compareX(a, b) { + return a.x - b.x; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +function eliminateHole(hole, outerNode) { + outerNode = findHoleBridge(hole, outerNode); + if (outerNode) { + var b = splitPolygon(outerNode, hole); + filterPoints(b, b.next); + } +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge(hole, outerNode) { + var p = outerNode, + hx = hole.x, + hy = hole.y, + qx = -Infinity, + m; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { + var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x <= hx && x > qx) { + qx = x; + if (x === hx) { + if (hy === p.y) return p; + if (hy === p.next.y) return p.next; + } + m = p.x < p.next.x ? p : p.next; + } + } + p = p.next; + } while (p !== outerNode); + + if (!m) return null; + + if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + var stop = m, + mx = m.x, + my = m.y, + tanMin = Infinity, + tan; + + p = m.next; + + while (p !== stop) { + if (hx >= p.x && p.x >= mx && hx !== p.x && + pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { + + tan = Math.abs(hy - p.y) / (hx - p.x); // tangential + + if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { + m = p; + tanMin = tan; + } + } + + p = p.next; + } + + return m; +} + +// interlink polygon nodes in z-order +function indexCurve(start, minX, minY, invSize) { + var p = start; + do { + if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked(list) { + var i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + p = list; + list = null; + tail = null; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) break; + } + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + + if (tail) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + } + + p = q; + } + + tail.nextZ = null; + inSize *= 2; + + } while (numMerges > 1); + + return list; +} + +// z-order of a point given coords and inverse of the longer side of data bbox +function zOrder(x, y, minX, minY, invSize) { + // coords are transformed into non-negative 15-bit integer range + x = 32767 * (x - minX) * invSize; + y = 32767 * (y - minY) * invSize; + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +function getLeftmost(start) { + var p = start, + leftmost = start; + do { + if (p.x < leftmost.x) leftmost = p; + p = p.next; + } while (p !== start); + + return leftmost; +} + +// check if a point lies within a convex triangle +function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { + return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && + (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && + (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal(a, b) { + return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && + locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); +} + +// signed area of a triangle +function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); +} + +// check if two points are equal +function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +} + +// check if two segments intersect +function intersects(p1, q1, p2, q2) { + if ((equals(p1, q1) && equals(p2, q2)) || + (equals(p1, q2) && equals(p2, q1))) return true; + return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && + area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon(a, b) { + var p = a; + do { + if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects(p, p.next, a, b)) return true; + p = p.next; + } while (p !== a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside(a, b) { + return area(a.prev, a, a.next) < 0 ? + area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : + area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside(a, b) { + var p = a, + inside = false, + px = (a.x + b.x) / 2, + py = (a.y + b.y) / 2; + do { + if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && + (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) + inside = !inside; + p = p.next; + } while (p !== a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon(a, b) { + var a2 = new Node(a.i, a.x, a.y), + b2 = new Node(b.i, b.x, b.y), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode(i, x, y, last) { + var p = new Node(i, x, y); + + if (!last) { + p.prev = p; + p.next = p; + + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; +} + +function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + + if (p.prevZ) p.prevZ.nextZ = p.nextZ; + if (p.nextZ) p.nextZ.prevZ = p.prevZ; +} + +function Node(i, x, y) { + // vertice index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertice nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = null; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; +} + +// return a percentage difference between the polygon area and its triangulation area; +// used to verify correctness of triangulation +earcut.deviation = function (data, holeIndices, dim, triangles) { + var hasHoles = holeIndices && holeIndices.length; + var outerLen = hasHoles ? holeIndices[0] * dim : data.length; + + var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); + if (hasHoles) { + for (var i = 0, len = holeIndices.length; i < len; i++) { + var start = holeIndices[i] * dim; + var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + polygonArea -= Math.abs(signedArea(data, start, end, dim)); + } + } + + var trianglesArea = 0; + for (i = 0; i < triangles.length; i += 3) { + var a = triangles[i] * dim; + var b = triangles[i + 1] * dim; + var c = triangles[i + 2] * dim; + trianglesArea += Math.abs( + (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - + (data[a] - data[b]) * (data[c + 1] - data[a + 1])); + } + + return polygonArea === 0 && trianglesArea === 0 ? 0 : + Math.abs((trianglesArea - polygonArea) / polygonArea); +}; + +function signedArea(data, start, end, dim) { + var sum = 0; + for (var i = start, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + return sum; +} + +// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts +earcut.flatten = function (data) { + var dim = data[0][0].length, + result = {vertices: [], holes: [], dimensions: dim}, + holeIndex = 0; + + for (var i = 0; i < data.length; i++) { + for (var j = 0; j < data[i].length; j++) { + for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]); + } + if (i > 0) { + holeIndex += data[i - 1].length; + result.holes.push(holeIndex); + } + } + return result; +}; + +},{}],157:[function(_dereq_,module,exports){ +"use strict" + +module.exports = edgeToAdjacency + +var uniq = _dereq_("uniq") + +function edgeToAdjacency(edges, numVertices) { + var numEdges = edges.length + if(typeof numVertices !== "number") { + numVertices = 0 + for(var i=0; i= 0xd800 && code <= 0xdbff) value += arrayLike[++i]; + } + value = mapFn ? call.call(mapFn, thisArg, value, j) : value; + if (Context) { + desc.value = value; + defineProperty(arr, j, desc); + } else { + arr[j] = value; + } + ++j; + } + length = j; + } + } + if (length === undefined) { + // Source: array or array-like + length = toPosInt(arrayLike.length); + if (Context) arr = new Context(length); + for (i = 0; i < length; ++i) { + value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i]; + if (Context) { + desc.value = value; + defineProperty(arr, i, desc); + } else { + arr[i] = value; + } + } + } + if (Context) { + desc.value = null; + arr.length = length; + } + return arr; +}; + +},{"../../function/is-arguments":162,"../../function/is-function":163,"../../number/to-pos-integer":169,"../../object/is-value":179,"../../object/valid-callable":188,"../../object/valid-value":190,"../../string/is-string":194,"es6-symbol":204}],162:[function(_dereq_,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString + , id = objToString.call( + (function () { + return arguments; + })() +); + +module.exports = function (value) { + return objToString.call(value) === id; +}; + +},{}],163:[function(_dereq_,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString, id = objToString.call(_dereq_("./noop")); + +module.exports = function (value) { + return typeof value === "function" && objToString.call(value) === id; +}; + +},{"./noop":164}],164:[function(_dereq_,module,exports){ +"use strict"; + +// eslint-disable-next-line no-empty-function +module.exports = function () {}; + +},{}],165:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./is-implemented")() + ? Math.sign + : _dereq_("./shim"); + +},{"./is-implemented":166,"./shim":167}],166:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = function () { + var sign = Math.sign; + if (typeof sign !== "function") return false; + return (sign(10) === 1) && (sign(-20) === -1); +}; + +},{}],167:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = function (value) { + value = Number(value); + if (isNaN(value) || (value === 0)) return value; + return value > 0 ? 1 : -1; +}; + +},{}],168:[function(_dereq_,module,exports){ +"use strict"; + +var sign = _dereq_("../math/sign") + + , abs = Math.abs, floor = Math.floor; + +module.exports = function (value) { + if (isNaN(value)) return 0; + value = Number(value); + if ((value === 0) || !isFinite(value)) return value; + return sign(value) * floor(abs(value)); +}; + +},{"../math/sign":165}],169:[function(_dereq_,module,exports){ +"use strict"; + +var toInteger = _dereq_("./to-integer") + + , max = Math.max; + +module.exports = function (value) { + return max(0, toInteger(value)); +}; + +},{"./to-integer":168}],170:[function(_dereq_,module,exports){ +// Internal method, used by iteration functions. +// Calls a function for each key-value pair found in object +// Optionally takes compareFn to iterate object in specific order + +"use strict"; + +var callable = _dereq_("./valid-callable") + , value = _dereq_("./valid-value") + , bind = Function.prototype.bind + , call = Function.prototype.call + , keys = Object.keys + , objPropertyIsEnumerable = Object.prototype.propertyIsEnumerable; + +module.exports = function (method, defVal) { + return function (obj, cb /*, thisArg, compareFn*/) { + var list, thisArg = arguments[2], compareFn = arguments[3]; + obj = Object(value(obj)); + callable(cb); + + list = keys(obj); + if (compareFn) { + list.sort(typeof compareFn === "function" ? bind.call(compareFn, obj) : undefined); + } + if (typeof method !== "function") method = list[method]; + return call.call(method, list, function (key, index) { + if (!objPropertyIsEnumerable.call(obj, key)) return defVal; + return call.call(cb, thisArg, obj[key], key, obj, index); + }); + }; +}; + +},{"./valid-callable":188,"./valid-value":190}],171:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./is-implemented")() + ? Object.assign + : _dereq_("./shim"); + +},{"./is-implemented":172,"./shim":173}],172:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = function () { + var assign = Object.assign, obj; + if (typeof assign !== "function") return false; + obj = { foo: "raz" }; + assign(obj, { bar: "dwa" }, { trzy: "trzy" }); + return (obj.foo + obj.bar + obj.trzy) === "razdwatrzy"; +}; + +},{}],173:[function(_dereq_,module,exports){ +"use strict"; + +var keys = _dereq_("../keys") + , value = _dereq_("../valid-value") + , max = Math.max; + +module.exports = function (dest, src /*, …srcn*/) { + var error, i, length = max(arguments.length, 2), assign; + dest = Object(value(dest)); + assign = function (key) { + try { + dest[key] = src[key]; + } catch (e) { + if (!error) error = e; + } + }; + for (i = 1; i < length; ++i) { + src = arguments[i]; + keys(src).forEach(assign); + } + if (error !== undefined) throw error; + return dest; +}; + +},{"../keys":180,"../valid-value":190}],174:[function(_dereq_,module,exports){ +"use strict"; + +var aFrom = _dereq_("../array/from") + , assign = _dereq_("./assign") + , value = _dereq_("./valid-value"); + +module.exports = function (obj/*, propertyNames, options*/) { + var copy = Object(value(obj)), propertyNames = arguments[1], options = Object(arguments[2]); + if (copy !== obj && !propertyNames) return copy; + var result = {}; + if (propertyNames) { + aFrom(propertyNames, function (propertyName) { + if (options.ensure || propertyName in obj) result[propertyName] = obj[propertyName]; + }); + } else { + assign(result, obj); + } + return result; +}; + +},{"../array/from":159,"./assign":171,"./valid-value":190}],175:[function(_dereq_,module,exports){ +// Workaround for http://code.google.com/p/v8/issues/detail?id=2804 + +"use strict"; + +var create = Object.create, shim; + +if (!_dereq_("./set-prototype-of/is-implemented")()) { + shim = _dereq_("./set-prototype-of/shim"); +} + +module.exports = (function () { + var nullObject, polyProps, desc; + if (!shim) return create; + if (shim.level !== 1) return create; + + nullObject = {}; + polyProps = {}; + desc = { + configurable: false, + enumerable: false, + writable: true, + value: undefined + }; + Object.getOwnPropertyNames(Object.prototype).forEach(function (name) { + if (name === "__proto__") { + polyProps[name] = { + configurable: true, + enumerable: false, + writable: true, + value: undefined + }; + return; + } + polyProps[name] = desc; + }); + Object.defineProperties(nullObject, polyProps); + + Object.defineProperty(shim, "nullPolyfill", { + configurable: false, + enumerable: false, + writable: false, + value: nullObject + }); + + return function (prototype, props) { + return create(prototype === null ? nullObject : prototype, props); + }; +}()); + +},{"./set-prototype-of/is-implemented":186,"./set-prototype-of/shim":187}],176:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./_iterate")("forEach"); + +},{"./_iterate":170}],177:[function(_dereq_,module,exports){ +// Deprecated + +"use strict"; + +module.exports = function (obj) { + return typeof obj === "function"; +}; + +},{}],178:[function(_dereq_,module,exports){ +"use strict"; + +var isValue = _dereq_("./is-value"); + +var map = { function: true, object: true }; + +module.exports = function (value) { + return (isValue(value) && map[typeof value]) || false; +}; + +},{"./is-value":179}],179:[function(_dereq_,module,exports){ +"use strict"; + +var _undefined = _dereq_("../function/noop")(); // Support ES3 engines + +module.exports = function (val) { + return (val !== _undefined) && (val !== null); +}; + +},{"../function/noop":164}],180:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./is-implemented")() ? Object.keys : _dereq_("./shim"); + +},{"./is-implemented":181,"./shim":182}],181:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = function () { + try { + Object.keys("primitive"); + return true; + } catch (e) { + return false; + } +}; + +},{}],182:[function(_dereq_,module,exports){ +"use strict"; + +var isValue = _dereq_("../is-value"); + +var keys = Object.keys; + +module.exports = function (object) { return keys(isValue(object) ? Object(object) : object); }; + +},{"../is-value":179}],183:[function(_dereq_,module,exports){ +"use strict"; + +var callable = _dereq_("./valid-callable") + , forEach = _dereq_("./for-each") + , call = Function.prototype.call; + +module.exports = function (obj, cb /*, thisArg*/) { + var result = {}, thisArg = arguments[2]; + callable(cb); + forEach(obj, function (value, key, targetObj, index) { + result[key] = call.call(cb, thisArg, value, key, targetObj, index); + }); + return result; +}; + +},{"./for-each":176,"./valid-callable":188}],184:[function(_dereq_,module,exports){ +"use strict"; + +var isValue = _dereq_("./is-value"); + +var forEach = Array.prototype.forEach, create = Object.create; + +var process = function (src, obj) { + var key; + for (key in src) obj[key] = src[key]; +}; + +// eslint-disable-next-line no-unused-vars +module.exports = function (opts1 /*, …options*/) { + var result = create(null); + forEach.call(arguments, function (options) { + if (!isValue(options)) return; + process(Object(options), result); + }); + return result; +}; + +},{"./is-value":179}],185:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./is-implemented")() + ? Object.setPrototypeOf + : _dereq_("./shim"); + +},{"./is-implemented":186,"./shim":187}],186:[function(_dereq_,module,exports){ +"use strict"; + +var create = Object.create, getPrototypeOf = Object.getPrototypeOf, plainObject = {}; + +module.exports = function (/* CustomCreate*/) { + var setPrototypeOf = Object.setPrototypeOf, customCreate = arguments[0] || create; + if (typeof setPrototypeOf !== "function") return false; + return getPrototypeOf(setPrototypeOf(customCreate(null), plainObject)) === plainObject; +}; + +},{}],187:[function(_dereq_,module,exports){ +/* eslint no-proto: "off" */ + +// Big thanks to @WebReflection for sorting this out +// https://gist.github.com/WebReflection/5593554 + +"use strict"; + +var isObject = _dereq_("../is-object") + , value = _dereq_("../valid-value") + , objIsPrototypeOf = Object.prototype.isPrototypeOf + , defineProperty = Object.defineProperty + , nullDesc = { + configurable: true, + enumerable: false, + writable: true, + value: undefined +} + , validate; + +validate = function (obj, prototype) { + value(obj); + if (prototype === null || isObject(prototype)) return obj; + throw new TypeError("Prototype must be null or an object"); +}; + +module.exports = (function (status) { + var fn, set; + if (!status) return null; + if (status.level === 2) { + if (status.set) { + set = status.set; + fn = function (obj, prototype) { + set.call(validate(obj, prototype), prototype); + return obj; + }; + } else { + fn = function (obj, prototype) { + validate(obj, prototype).__proto__ = prototype; + return obj; + }; + } + } else { + fn = function self(obj, prototype) { + var isNullBase; + validate(obj, prototype); + isNullBase = objIsPrototypeOf.call(self.nullPolyfill, obj); + if (isNullBase) delete self.nullPolyfill.__proto__; + if (prototype === null) prototype = self.nullPolyfill; + obj.__proto__ = prototype; + if (isNullBase) defineProperty(self.nullPolyfill, "__proto__", nullDesc); + return obj; + }; + } + return Object.defineProperty(fn, "level", { + configurable: false, + enumerable: false, + writable: false, + value: status.level + }); +}( + (function () { + var tmpObj1 = Object.create(null) + , tmpObj2 = {} + , set + , desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); + + if (desc) { + try { + set = desc.set; // Opera crashes at this point + set.call(tmpObj1, tmpObj2); + } catch (ignore) {} + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { set: set, level: 2 }; + } + + tmpObj1.__proto__ = tmpObj2; + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 2 }; + + tmpObj1 = {}; + tmpObj1.__proto__ = tmpObj2; + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 1 }; + + return false; + })() +)); + +_dereq_("../create"); + +},{"../create":175,"../is-object":178,"../valid-value":190}],188:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = function (fn) { + if (typeof fn !== "function") throw new TypeError(fn + " is not a function"); + return fn; +}; + +},{}],189:[function(_dereq_,module,exports){ +"use strict"; + +var isObject = _dereq_("./is-object"); + +module.exports = function (value) { + if (!isObject(value)) throw new TypeError(value + " is not an Object"); + return value; +}; + +},{"./is-object":178}],190:[function(_dereq_,module,exports){ +"use strict"; + +var isValue = _dereq_("./is-value"); + +module.exports = function (value) { + if (!isValue(value)) throw new TypeError("Cannot use null or undefined"); + return value; +}; + +},{"./is-value":179}],191:[function(_dereq_,module,exports){ +"use strict"; + +module.exports = _dereq_("./is-implemented")() + ? String.prototype.contains + : _dereq_("./shim"); + +},{"./is-implemented":192,"./shim":193}],192:[function(_dereq_,module,exports){ +"use strict"; + +var str = "razdwatrzy"; + +module.exports = function () { + if (typeof str.contains !== "function") return false; + return (str.contains("dwa") === true) && (str.contains("foo") === false); +}; + +},{}],193:[function(_dereq_,module,exports){ +"use strict"; + +var indexOf = String.prototype.indexOf; + +module.exports = function (searchString/*, position*/) { + return indexOf.call(this, searchString, arguments[1]) > -1; +}; + +},{}],194:[function(_dereq_,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString, id = objToString.call(""); + +module.exports = function (value) { + return ( + typeof value === "string" || + (value && + typeof value === "object" && + (value instanceof String || objToString.call(value) === id)) || + false + ); +}; + +},{}],195:[function(_dereq_,module,exports){ +"use strict"; + +var generated = Object.create(null), random = Math.random; + +module.exports = function () { + var str; + do { + str = random() + .toString(36) + .slice(2); + } while (generated[str]); + return str; +}; + +},{}],196:[function(_dereq_,module,exports){ +"use strict"; + +var setPrototypeOf = _dereq_("es5-ext/object/set-prototype-of") + , contains = _dereq_("es5-ext/string/#/contains") + , d = _dereq_("d") + , Symbol = _dereq_("es6-symbol") + , Iterator = _dereq_("./"); + +var defineProperty = Object.defineProperty, ArrayIterator; + +ArrayIterator = module.exports = function (arr, kind) { + if (!(this instanceof ArrayIterator)) throw new TypeError("Constructor requires 'new'"); + Iterator.call(this, arr); + if (!kind) kind = "value"; + else if (contains.call(kind, "key+value")) kind = "key+value"; + else if (contains.call(kind, "key")) kind = "key"; + else kind = "value"; + defineProperty(this, "__kind__", d("", kind)); +}; +if (setPrototypeOf) setPrototypeOf(ArrayIterator, Iterator); + +// Internal %ArrayIteratorPrototype% doesn't expose its constructor +delete ArrayIterator.prototype.constructor; + +ArrayIterator.prototype = Object.create(Iterator.prototype, { + _resolve: d(function (i) { + if (this.__kind__ === "value") return this.__list__[i]; + if (this.__kind__ === "key+value") return [i, this.__list__[i]]; + return i; + }) +}); +defineProperty(ArrayIterator.prototype, Symbol.toStringTag, d("c", "Array Iterator")); + +},{"./":199,"d":139,"es5-ext/object/set-prototype-of":185,"es5-ext/string/#/contains":191,"es6-symbol":204}],197:[function(_dereq_,module,exports){ +"use strict"; + +var isArguments = _dereq_("es5-ext/function/is-arguments") + , callable = _dereq_("es5-ext/object/valid-callable") + , isString = _dereq_("es5-ext/string/is-string") + , get = _dereq_("./get"); + +var isArray = Array.isArray, call = Function.prototype.call, some = Array.prototype.some; + +module.exports = function (iterable, cb /*, thisArg*/) { + var mode, thisArg = arguments[2], result, doBreak, broken, i, length, char, code; + if (isArray(iterable) || isArguments(iterable)) mode = "array"; + else if (isString(iterable)) mode = "string"; + else iterable = get(iterable); + + callable(cb); + doBreak = function () { + broken = true; + }; + if (mode === "array") { + some.call(iterable, function (value) { + call.call(cb, thisArg, value, doBreak); + return broken; + }); + return; + } + if (mode === "string") { + length = iterable.length; + for (i = 0; i < length; ++i) { + char = iterable[i]; + if (i + 1 < length) { + code = char.charCodeAt(0); + if (code >= 0xd800 && code <= 0xdbff) char += iterable[++i]; + } + call.call(cb, thisArg, char, doBreak); + if (broken) break; + } + return; + } + result = iterable.next(); + + while (!result.done) { + call.call(cb, thisArg, result.value, doBreak); + if (broken) return; + result = iterable.next(); + } +}; + +},{"./get":198,"es5-ext/function/is-arguments":162,"es5-ext/object/valid-callable":188,"es5-ext/string/is-string":194}],198:[function(_dereq_,module,exports){ +"use strict"; + +var isArguments = _dereq_("es5-ext/function/is-arguments") + , isString = _dereq_("es5-ext/string/is-string") + , ArrayIterator = _dereq_("./array") + , StringIterator = _dereq_("./string") + , iterable = _dereq_("./valid-iterable") + , iteratorSymbol = _dereq_("es6-symbol").iterator; + +module.exports = function (obj) { + if (typeof iterable(obj)[iteratorSymbol] === "function") return obj[iteratorSymbol](); + if (isArguments(obj)) return new ArrayIterator(obj); + if (isString(obj)) return new StringIterator(obj); + return new ArrayIterator(obj); +}; + +},{"./array":196,"./string":201,"./valid-iterable":202,"es5-ext/function/is-arguments":162,"es5-ext/string/is-string":194,"es6-symbol":204}],199:[function(_dereq_,module,exports){ +"use strict"; + +var clear = _dereq_("es5-ext/array/#/clear") + , assign = _dereq_("es5-ext/object/assign") + , callable = _dereq_("es5-ext/object/valid-callable") + , value = _dereq_("es5-ext/object/valid-value") + , d = _dereq_("d") + , autoBind = _dereq_("d/auto-bind") + , Symbol = _dereq_("es6-symbol"); + +var defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, Iterator; + +module.exports = Iterator = function (list, context) { + if (!(this instanceof Iterator)) throw new TypeError("Constructor requires 'new'"); + defineProperties(this, { + __list__: d("w", value(list)), + __context__: d("w", context), + __nextIndex__: d("w", 0) + }); + if (!context) return; + callable(context.on); + context.on("_add", this._onAdd); + context.on("_delete", this._onDelete); + context.on("_clear", this._onClear); +}; + +// Internal %IteratorPrototype% doesn't expose its constructor +delete Iterator.prototype.constructor; + +defineProperties( + Iterator.prototype, + assign( + { + _next: d(function () { + var i; + if (!this.__list__) return undefined; + if (this.__redo__) { + i = this.__redo__.shift(); + if (i !== undefined) return i; + } + if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++; + this._unBind(); + return undefined; + }), + next: d(function () { + return this._createResult(this._next()); + }), + _createResult: d(function (i) { + if (i === undefined) return { done: true, value: undefined }; + return { done: false, value: this._resolve(i) }; + }), + _resolve: d(function (i) { + return this.__list__[i]; + }), + _unBind: d(function () { + this.__list__ = null; + delete this.__redo__; + if (!this.__context__) return; + this.__context__.off("_add", this._onAdd); + this.__context__.off("_delete", this._onDelete); + this.__context__.off("_clear", this._onClear); + this.__context__ = null; + }), + toString: d(function () { + return "[object " + (this[Symbol.toStringTag] || "Object") + "]"; + }) + }, + autoBind({ + _onAdd: d(function (index) { + if (index >= this.__nextIndex__) return; + ++this.__nextIndex__; + if (!this.__redo__) { + defineProperty(this, "__redo__", d("c", [index])); + return; + } + this.__redo__.forEach(function (redo, i) { + if (redo >= index) this.__redo__[i] = ++redo; + }, this); + this.__redo__.push(index); + }), + _onDelete: d(function (index) { + var i; + if (index >= this.__nextIndex__) return; + --this.__nextIndex__; + if (!this.__redo__) return; + i = this.__redo__.indexOf(index); + if (i !== -1) this.__redo__.splice(i, 1); + this.__redo__.forEach(function (redo, j) { + if (redo > index) this.__redo__[j] = --redo; + }, this); + }), + _onClear: d(function () { + if (this.__redo__) clear.call(this.__redo__); + this.__nextIndex__ = 0; + }) + }) + ) +); + +defineProperty( + Iterator.prototype, + Symbol.iterator, + d(function () { + return this; + }) +); + +},{"d":139,"d/auto-bind":138,"es5-ext/array/#/clear":158,"es5-ext/object/assign":171,"es5-ext/object/valid-callable":188,"es5-ext/object/valid-value":190,"es6-symbol":204}],200:[function(_dereq_,module,exports){ +"use strict"; + +var isArguments = _dereq_("es5-ext/function/is-arguments") + , isValue = _dereq_("es5-ext/object/is-value") + , isString = _dereq_("es5-ext/string/is-string"); + +var iteratorSymbol = _dereq_("es6-symbol").iterator + , isArray = Array.isArray; + +module.exports = function (value) { + if (!isValue(value)) return false; + if (isArray(value)) return true; + if (isString(value)) return true; + if (isArguments(value)) return true; + return typeof value[iteratorSymbol] === "function"; +}; + +},{"es5-ext/function/is-arguments":162,"es5-ext/object/is-value":179,"es5-ext/string/is-string":194,"es6-symbol":204}],201:[function(_dereq_,module,exports){ +// Thanks @mathiasbynens +// http://mathiasbynens.be/notes/javascript-unicode#iterating-over-symbols + +"use strict"; + +var setPrototypeOf = _dereq_("es5-ext/object/set-prototype-of") + , d = _dereq_("d") + , Symbol = _dereq_("es6-symbol") + , Iterator = _dereq_("./"); + +var defineProperty = Object.defineProperty, StringIterator; + +StringIterator = module.exports = function (str) { + if (!(this instanceof StringIterator)) throw new TypeError("Constructor requires 'new'"); + str = String(str); + Iterator.call(this, str); + defineProperty(this, "__length__", d("", str.length)); +}; +if (setPrototypeOf) setPrototypeOf(StringIterator, Iterator); + +// Internal %ArrayIteratorPrototype% doesn't expose its constructor +delete StringIterator.prototype.constructor; + +StringIterator.prototype = Object.create(Iterator.prototype, { + _next: d(function () { + if (!this.__list__) return undefined; + if (this.__nextIndex__ < this.__length__) return this.__nextIndex__++; + this._unBind(); + return undefined; + }), + _resolve: d(function (i) { + var char = this.__list__[i], code; + if (this.__nextIndex__ === this.__length__) return char; + code = char.charCodeAt(0); + if (code >= 0xd800 && code <= 0xdbff) return char + this.__list__[this.__nextIndex__++]; + return char; + }) +}); +defineProperty(StringIterator.prototype, Symbol.toStringTag, d("c", "String Iterator")); + +},{"./":199,"d":139,"es5-ext/object/set-prototype-of":185,"es6-symbol":204}],202:[function(_dereq_,module,exports){ +"use strict"; + +var isIterable = _dereq_("./is-iterable"); + +module.exports = function (value) { + if (!isIterable(value)) throw new TypeError(value + " is not iterable"); + return value; +}; + +},{"./is-iterable":200}],203:[function(_dereq_,module,exports){ +(function (process,global){ +/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version 3.3.1 + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.ES6Promise = factory()); +}(this, (function () { 'use strict'; + +function objectOrFunction(x) { + return typeof x === 'function' || typeof x === 'object' && x !== null; +} + +function isFunction(x) { + return typeof x === 'function'; +} + +var _isArray = undefined; +if (!Array.isArray) { + _isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; +} else { + _isArray = Array.isArray; +} + +var isArray = _isArray; + +var len = 0; +var vertxNext = undefined; +var customSchedulerFn = undefined; + +var asap = function asap(callback, arg) { + queue[len] = callback; + queue[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (customSchedulerFn) { + customSchedulerFn(flush); + } else { + scheduleFlush(); + } + } +}; + +function setScheduler(scheduleFn) { + customSchedulerFn = scheduleFn; +} + +function setAsap(asapFn) { + asap = asapFn; +} + +var browserWindow = typeof window !== 'undefined' ? window : undefined; +var browserGlobal = browserWindow || {}; +var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; +var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; + +// test for web worker but not in IE10 +var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; + +// node +function useNextTick() { + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // see https://github.com/cujojs/when/issues/410 for details + return function () { + return process.nextTick(flush); + }; +} + +// vertx +function useVertxTimer() { + return function () { + vertxNext(flush); + }; +} + +function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return function () { + node.data = iterations = ++iterations % 2; + }; +} + +// web worker +function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; +} + +function useSetTimeout() { + // Store setTimeout reference so es6-promise will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var globalSetTimeout = setTimeout; + return function () { + return globalSetTimeout(flush, 1); + }; +} + +var queue = new Array(1000); +function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue[i]; + var arg = queue[i + 1]; + + callback(arg); + + queue[i] = undefined; + queue[i + 1] = undefined; + } + + len = 0; +} + +function attemptVertx() { + try { + var r = _dereq_; + var vertx = r('vertx'); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); + } +} + +var scheduleFlush = undefined; +// Decide what async method to use to triggering processing of queued callbacks: +if (isNode) { + scheduleFlush = useNextTick(); +} else if (BrowserMutationObserver) { + scheduleFlush = useMutationObserver(); +} else if (isWorker) { + scheduleFlush = useMessageChannel(); +} else if (browserWindow === undefined && typeof _dereq_ === 'function') { + scheduleFlush = attemptVertx(); +} else { + scheduleFlush = useSetTimeout(); +} + +function then(onFulfillment, onRejection) { + var _arguments = arguments; + + var parent = this; + + var child = new this.constructor(noop); + + if (child[PROMISE_ID] === undefined) { + makePromise(child); + } + + var _state = parent._state; + + if (_state) { + (function () { + var callback = _arguments[_state - 1]; + asap(function () { + return invokeCallback(_state, child, callback, parent._result); + }); + })(); + } else { + subscribe(parent, child, onFulfillment, onRejection); + } + + return child; +} + +/** + `Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {Any} value value that the returned promise will be resolved with + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` +*/ +function resolve(object) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(noop); + _resolve(promise, object); + return promise; +} + +var PROMISE_ID = Math.random().toString(36).substring(16); + +function noop() {} + +var PENDING = void 0; +var FULFILLED = 1; +var REJECTED = 2; + +var GET_THEN_ERROR = new ErrorObject(); + +function selfFulfillment() { + return new TypeError("You cannot resolve a promise with itself"); +} + +function cannotReturnOwn() { + return new TypeError('A promises callback cannot return that same promise.'); +} + +function getThen(promise) { + try { + return promise.then; + } catch (error) { + GET_THEN_ERROR.error = error; + return GET_THEN_ERROR; + } +} + +function tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; + } +} + +function handleForeignThenable(promise, thenable, then) { + asap(function (promise) { + var sealed = false; + var error = tryThen(then, thenable, function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + _resolve(promise, value); + } else { + fulfill(promise, value); + } + }, function (reason) { + if (sealed) { + return; + } + sealed = true; + + _reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); + + if (!sealed && error) { + sealed = true; + _reject(promise, error); + } + }, promise); +} + +function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + _reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, function (value) { + return _resolve(promise, value); + }, function (reason) { + return _reject(promise, reason); + }); + } +} + +function handleMaybeThenable(promise, maybeThenable, then$$) { + if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$ === GET_THEN_ERROR) { + _reject(promise, GET_THEN_ERROR.error); + } else if (then$$ === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$)) { + handleForeignThenable(promise, maybeThenable, then$$); + } else { + fulfill(promise, maybeThenable); + } + } +} + +function _resolve(promise, value) { + if (promise === value) { + _reject(promise, selfFulfillment()); + } else if (objectOrFunction(value)) { + handleMaybeThenable(promise, value, getThen(value)); + } else { + fulfill(promise, value); + } +} + +function publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); + } + + publish(promise); +} + +function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } + + promise._result = value; + promise._state = FULFILLED; + + if (promise._subscribers.length !== 0) { + asap(publish, promise); + } +} + +function _reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + + asap(publishRejection, promise); +} + +function subscribe(parent, child, onFulfillment, onRejection) { + var _subscribers = parent._subscribers; + var length = _subscribers.length; + + parent._onerror = null; + + _subscribers[length] = child; + _subscribers[length + FULFILLED] = onFulfillment; + _subscribers[length + REJECTED] = onRejection; + + if (length === 0 && parent._state) { + asap(publish, parent); + } +} + +function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + + if (subscribers.length === 0) { + return; + } + + var child = undefined, + callback = undefined, + detail = promise._result; + + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + + promise._subscribers.length = 0; +} + +function ErrorObject() { + this.error = null; +} + +var TRY_CATCH_ERROR = new ErrorObject(); + +function tryCatch(callback, detail) { + try { + return callback(detail); + } catch (e) { + TRY_CATCH_ERROR.error = e; + return TRY_CATCH_ERROR; + } +} + +function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = undefined, + error = undefined, + succeeded = undefined, + failed = undefined; + + if (hasCallback) { + value = tryCatch(callback, detail); + + if (value === TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } + + if (promise === value) { + _reject(promise, cannotReturnOwn()); + return; + } + } else { + value = detail; + succeeded = true; + } + + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + _resolve(promise, value); + } else if (failed) { + _reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + _reject(promise, value); + } +} + +function initializePromise(promise, resolver) { + try { + resolver(function resolvePromise(value) { + _resolve(promise, value); + }, function rejectPromise(reason) { + _reject(promise, reason); + }); + } catch (e) { + _reject(promise, e); + } +} + +var id = 0; +function nextId() { + return id++; +} + +function makePromise(promise) { + promise[PROMISE_ID] = id++; + promise._state = undefined; + promise._result = undefined; + promise._subscribers = []; +} + +function Enumerator(Constructor, input) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop); + + if (!this.promise[PROMISE_ID]) { + makePromise(this.promise); + } + + if (isArray(input)) { + this._input = input; + this.length = input.length; + this._remaining = input.length; + + this._result = new Array(this.length); + + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + _reject(this.promise, validationError()); + } +} + +function validationError() { + return new Error('Array Methods must be provided an Array'); +}; + +Enumerator.prototype._enumerate = function () { + var length = this.length; + var _input = this._input; + + for (var i = 0; this._state === PENDING && i < length; i++) { + this._eachEntry(_input[i], i); + } +}; + +Enumerator.prototype._eachEntry = function (entry, i) { + var c = this._instanceConstructor; + var resolve$$ = c.resolve; + + if (resolve$$ === resolve) { + var _then = getThen(entry); + + if (_then === then && entry._state !== PENDING) { + this._settledAt(entry._state, i, entry._result); + } else if (typeof _then !== 'function') { + this._remaining--; + this._result[i] = entry; + } else if (c === Promise) { + var promise = new c(noop); + handleMaybeThenable(promise, entry, _then); + this._willSettleAt(promise, i); + } else { + this._willSettleAt(new c(function (resolve$$) { + return resolve$$(entry); + }), i); + } + } else { + this._willSettleAt(resolve$$(entry), i); + } +}; + +Enumerator.prototype._settledAt = function (state, i, value) { + var promise = this.promise; + + if (promise._state === PENDING) { + this._remaining--; + + if (state === REJECTED) { + _reject(promise, value); + } else { + this._result[i] = value; + } + } + + if (this._remaining === 0) { + fulfill(promise, this._result); + } +}; + +Enumerator.prototype._willSettleAt = function (promise, i) { + var enumerator = this; + + subscribe(promise, undefined, function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + }); +}; + +/** + `Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = reject(new Error("2")); + let promise3 = reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static +*/ +function all(entries) { + return new Enumerator(this, entries).promise; +} + +/** + `Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} promises array of promises to observe + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. +*/ +function race(entries) { + /*jshint validthis:true */ + var Constructor = this; + + if (!isArray(entries)) { + return new Constructor(function (_, reject) { + return reject(new TypeError('You must pass an array to race.')); + }); + } else { + return new Constructor(function (resolve, reject) { + var length = entries.length; + for (var i = 0; i < length; i++) { + Constructor.resolve(entries[i]).then(resolve, reject); + } + }); + } +} + +/** + `Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {Any} reason value that the returned promise will be rejected with. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. +*/ +function reject(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop); + _reject(promise, reason); + return promise; +} + +function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); +} + +function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); +} + +/** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise's eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {function} resolver + Useful for tooling. + @constructor +*/ +function Promise(resolver) { + this[PROMISE_ID] = nextId(); + this._result = this._state = undefined; + this._subscribers = []; + + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } +} + +Promise.all = all; +Promise.race = race; +Promise.resolve = resolve; +Promise.reject = reject; +Promise._setScheduler = setScheduler; +Promise._setAsap = setAsap; +Promise._asap = asap; + +Promise.prototype = { + constructor: Promise, + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + + Chaining + -------- + + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + + Assimilation + ------------ + + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + + If the assimliated promise rejects, then the downstream promise will also reject. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + + Simple Example + -------------- + + Synchronous Example + + ```javascript + let result; + + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + + Promise Example; + + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + + Advanced Example + -------------- + + Synchronous Example + + ```javascript + let author, books; + + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + + function foundBooks(books) { + + } + + function failure(reason) { + + } + + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + then: then, + + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + + ```js + function findAuthor(){ + throw new Error('couldn't find that author'); + } + + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + + @method catch + @param {Function} onRejection + Useful for tooling. + @return {Promise} + */ + 'catch': function _catch(onRejection) { + return this.then(null, onRejection); + } +}; + +function polyfill() { + var local = undefined; + + if (typeof global !== 'undefined') { + local = global; + } else if (typeof self !== 'undefined') { + local = self; + } else { + try { + local = Function('return this')(); + } catch (e) { + throw new Error('polyfill failed because global object is unavailable in this environment'); + } + } + + var P = local.Promise; + + if (P) { + var promiseToString = null; + try { + promiseToString = Object.prototype.toString.call(P.resolve()); + } catch (e) { + // silently ignored + } + + if (promiseToString === '[object Promise]' && !P.cast) { + return; + } + } + + local.Promise = Promise; +} + +polyfill(); +// Strange compat.. +Promise.polyfill = polyfill; +Promise.Promise = Promise; + +return Promise; + +}))); + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"_process":465}],204:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = _dereq_('./is-implemented')() ? Symbol : _dereq_('./polyfill'); + +},{"./is-implemented":205,"./polyfill":207}],205:[function(_dereq_,module,exports){ +'use strict'; + +var validTypes = { object: true, symbol: true }; + +module.exports = function () { + var symbol; + if (typeof Symbol !== 'function') return false; + symbol = Symbol('test symbol'); + try { String(symbol); } catch (e) { return false; } + + // Return 'true' also for polyfills + if (!validTypes[typeof Symbol.iterator]) return false; + if (!validTypes[typeof Symbol.toPrimitive]) return false; + if (!validTypes[typeof Symbol.toStringTag]) return false; + + return true; +}; + +},{}],206:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = function (x) { + if (!x) return false; + if (typeof x === 'symbol') return true; + if (!x.constructor) return false; + if (x.constructor.name !== 'Symbol') return false; + return (x[x.constructor.toStringTag] === 'Symbol'); +}; + +},{}],207:[function(_dereq_,module,exports){ +// ES2015 Symbol polyfill for environments that do not (or partially) support it + +'use strict'; + +var d = _dereq_('d') + , validateSymbol = _dereq_('./validate-symbol') + + , create = Object.create, defineProperties = Object.defineProperties + , defineProperty = Object.defineProperty, objPrototype = Object.prototype + , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null) + , isNativeSafe; + +if (typeof Symbol === 'function') { + NativeSymbol = Symbol; + try { + String(NativeSymbol()); + isNativeSafe = true; + } catch (ignore) {} +} + +var generateName = (function () { + var created = create(null); + return function (desc) { + var postfix = 0, name, ie11BugWorkaround; + while (created[desc + (postfix || '')]) ++postfix; + desc += (postfix || ''); + created[desc] = true; + name = '@@' + desc; + defineProperty(objPrototype, name, d.gs(null, function (value) { + // For IE11 issue see: + // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/ + // ie11-broken-getters-on-dom-objects + // https://github.com/medikoo/es6-symbol/issues/12 + if (ie11BugWorkaround) return; + ie11BugWorkaround = true; + defineProperty(this, name, d(value)); + ie11BugWorkaround = false; + })); + return name; + }; +}()); + +// Internal constructor (not one exposed) for creating Symbol instances. +// This one is used to ensure that `someSymbol instanceof Symbol` always return false +HiddenSymbol = function Symbol(description) { + if (this instanceof HiddenSymbol) throw new TypeError('Symbol is not a constructor'); + return SymbolPolyfill(description); +}; + +// Exposed `Symbol` constructor +// (returns instances of HiddenSymbol) +module.exports = SymbolPolyfill = function Symbol(description) { + var symbol; + if (this instanceof Symbol) throw new TypeError('Symbol is not a constructor'); + if (isNativeSafe) return NativeSymbol(description); + symbol = create(HiddenSymbol.prototype); + description = (description === undefined ? '' : String(description)); + return defineProperties(symbol, { + __description__: d('', description), + __name__: d('', generateName(description)) + }); +}; +defineProperties(SymbolPolyfill, { + for: d(function (key) { + if (globalSymbols[key]) return globalSymbols[key]; + return (globalSymbols[key] = SymbolPolyfill(String(key))); + }), + keyFor: d(function (s) { + var key; + validateSymbol(s); + for (key in globalSymbols) if (globalSymbols[key] === s) return key; + }), + + // To ensure proper interoperability with other native functions (e.g. Array.from) + // fallback to eventual native implementation of given symbol + hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')), + isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) || + SymbolPolyfill('isConcatSpreadable')), + iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')), + match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')), + replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')), + search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')), + species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')), + split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')), + toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')), + toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')), + unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables')) +}); + +// Internal tweaks for real symbol producer +defineProperties(HiddenSymbol.prototype, { + constructor: d(SymbolPolyfill), + toString: d('', function () { return this.__name__; }) +}); + +// Proper implementation of methods exposed on Symbol.prototype +// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype +defineProperties(SymbolPolyfill.prototype, { + toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }), + valueOf: d(function () { return validateSymbol(this); }) +}); +defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, d('', function () { + var symbol = validateSymbol(this); + if (typeof symbol === 'symbol') return symbol; + return symbol.toString(); +})); +defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d('c', 'Symbol')); + +// Proper implementaton of toPrimitive and toStringTag for returned symbol instances +defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag, + d('c', SymbolPolyfill.prototype[SymbolPolyfill.toStringTag])); + +// Note: It's important to define `toPrimitive` as last one, as some implementations +// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) +// And that may invoke error in definition flow: +// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 +defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, + d('c', SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive])); + +},{"./validate-symbol":208,"d":139}],208:[function(_dereq_,module,exports){ +'use strict'; + +var isSymbol = _dereq_('./is-symbol'); + +module.exports = function (value) { + if (!isSymbol(value)) throw new TypeError(value + " is not a symbol"); + return value; +}; + +},{"./is-symbol":206}],209:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = _dereq_('./is-implemented')() ? WeakMap : _dereq_('./polyfill'); + +},{"./is-implemented":210,"./polyfill":212}],210:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = function () { + var weakMap, x; + if (typeof WeakMap !== 'function') return false; + try { + // WebKit doesn't support arguments and crashes + weakMap = new WeakMap([[x = {}, 'one'], [{}, 'two'], [{}, 'three']]); + } catch (e) { + return false; + } + if (String(weakMap) !== '[object WeakMap]') return false; + if (typeof weakMap.set !== 'function') return false; + if (weakMap.set({}, 1) !== weakMap) return false; + if (typeof weakMap.delete !== 'function') return false; + if (typeof weakMap.has !== 'function') return false; + if (weakMap.get(x) !== 'one') return false; + + return true; +}; + +},{}],211:[function(_dereq_,module,exports){ +// Exports true if environment provides native `WeakMap` implementation, whatever that is. + +'use strict'; + +module.exports = (function () { + if (typeof WeakMap !== 'function') return false; + return (Object.prototype.toString.call(new WeakMap()) === '[object WeakMap]'); +}()); + +},{}],212:[function(_dereq_,module,exports){ +'use strict'; + +var setPrototypeOf = _dereq_('es5-ext/object/set-prototype-of') + , object = _dereq_('es5-ext/object/valid-object') + , value = _dereq_('es5-ext/object/valid-value') + , randomUniq = _dereq_('es5-ext/string/random-uniq') + , d = _dereq_('d') + , getIterator = _dereq_('es6-iterator/get') + , forOf = _dereq_('es6-iterator/for-of') + , toStringTagSymbol = _dereq_('es6-symbol').toStringTag + , isNative = _dereq_('./is-native-implemented') + + , isArray = Array.isArray, defineProperty = Object.defineProperty + , hasOwnProperty = Object.prototype.hasOwnProperty, getPrototypeOf = Object.getPrototypeOf + , WeakMapPoly; + +module.exports = WeakMapPoly = function (/*iterable*/) { + var iterable = arguments[0], self; + if (!(this instanceof WeakMapPoly)) throw new TypeError('Constructor requires \'new\''); + if (isNative && setPrototypeOf && (WeakMap !== WeakMapPoly)) { + self = setPrototypeOf(new WeakMap(), getPrototypeOf(this)); + } else { + self = this; + } + if (iterable != null) { + if (!isArray(iterable)) iterable = getIterator(iterable); + } + defineProperty(self, '__weakMapData__', d('c', '$weakMap$' + randomUniq())); + if (!iterable) return self; + forOf(iterable, function (val) { + value(val); + self.set(val[0], val[1]); + }); + return self; +}; + +if (isNative) { + if (setPrototypeOf) setPrototypeOf(WeakMapPoly, WeakMap); + WeakMapPoly.prototype = Object.create(WeakMap.prototype, { + constructor: d(WeakMapPoly) + }); +} + +Object.defineProperties(WeakMapPoly.prototype, { + delete: d(function (key) { + if (hasOwnProperty.call(object(key), this.__weakMapData__)) { + delete key[this.__weakMapData__]; + return true; + } + return false; + }), + get: d(function (key) { + if (hasOwnProperty.call(object(key), this.__weakMapData__)) { + return key[this.__weakMapData__]; + } + }), + has: d(function (key) { + return hasOwnProperty.call(object(key), this.__weakMapData__); + }), + set: d(function (key, value) { + defineProperty(object(key), this.__weakMapData__, d('c', value)); + return this; + }), + toString: d(function () { return '[object WeakMap]'; }) +}); +defineProperty(WeakMapPoly.prototype, toStringTagSymbol, d('c', 'WeakMap')); + +},{"./is-native-implemented":211,"d":139,"es5-ext/object/set-prototype-of":185,"es5-ext/object/valid-object":189,"es5-ext/object/valid-value":190,"es5-ext/string/random-uniq":195,"es6-iterator/for-of":197,"es6-iterator/get":198,"es6-symbol":204}],213:[function(_dereq_,module,exports){ +"use strict" + +module.exports = extractPlanes + +function extractPlanes(M, zNear, zFar) { + var z = zNear || 0.0 + var zf = zFar || 1.0 + return [ + [ M[12] + M[0], M[13] + M[1], M[14] + M[2], M[15] + M[3] ], + [ M[12] - M[0], M[13] - M[1], M[14] - M[2], M[15] - M[3] ], + [ M[12] + M[4], M[13] + M[5], M[14] + M[6], M[15] + M[7] ], + [ M[12] - M[4], M[13] - M[5], M[14] - M[6], M[15] - M[7] ], + [ z*M[12] + M[8], z*M[13] + M[9], z*M[14] + M[10], z*M[15] + M[11] ], + [ zf*M[12] - M[8], zf*M[13] - M[9], zf*M[14] - M[10], zf*M[15] - M[11] ] + ] +} +},{}],214:[function(_dereq_,module,exports){ +/** + * inspired by is-number + * but significantly simplified and sped up by ignoring number and string constructors + * ie these return false: + * new Number(1) + * new String('1') + */ + +'use strict'; + +var allBlankCharCodes = _dereq_('is-string-blank'); + +module.exports = function(n) { + var type = typeof n; + if(type === 'string') { + var original = n; + n = +n; + // whitespace strings cast to zero - filter them out + if(n===0 && allBlankCharCodes(original)) return false; + } + else if(type !== 'number') return false; + + return n - n < 1; +}; + +},{"is-string-blank":406}],215:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createFilteredVector + +var cubicHermite = _dereq_('cubic-hermite') +var bsearch = _dereq_('binary-search-bounds') + +function clamp(lo, hi, x) { + return Math.min(hi, Math.max(lo, x)) +} + +function FilteredVector(state0, velocity0, t0) { + this.dimension = state0.length + this.bounds = [ new Array(this.dimension), new Array(this.dimension) ] + for(var i=0; i= n-1) { + var ptr = state.length-1 + var tf = t - time[n-1] + for(var i=0; i= n-1) { + var ptr = state.length-1 + var tf = t - time[n-1] + for(var i=0; i=0; --i) { + if(velocity[--ptr]) { + return false + } + } + return true +} + +proto.jump = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t < t0 || arguments.length !== d+1) { + return + } + var state = this._state + var velocity = this._velocity + var ptr = state.length-this.dimension + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + this._time.push(t0, t) + for(var j=0; j<2; ++j) { + for(var i=0; i0; --i) { + state.push(clamp(lo[i-1], hi[i-1], arguments[i])) + velocity.push(0) + } +} + +proto.push = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t < t0 || arguments.length !== d+1) { + return + } + var state = this._state + var velocity = this._velocity + var ptr = state.length-this.dimension + var dt = t - t0 + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var sf = (dt > 1e-6) ? 1/dt : 0 + this._time.push(t) + for(var i=d; i>0; --i) { + var xc = clamp(lo[i-1], hi[i-1], arguments[i]) + state.push(xc) + velocity.push((xc - state[ptr++]) * sf) + } +} + +proto.set = function(t) { + var d = this.dimension + if(t < this.lastT() || arguments.length !== d+1) { + return + } + var state = this._state + var velocity = this._velocity + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + this._time.push(t) + for(var i=d; i>0; --i) { + state.push(clamp(lo[i-1], hi[i-1], arguments[i])) + velocity.push(0) + } +} + +proto.move = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t <= t0 || arguments.length !== d+1) { + return + } + var state = this._state + var velocity = this._velocity + var statePtr = state.length - this.dimension + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var dt = t - t0 + var sf = (dt > 1e-6) ? 1/dt : 0.0 + this._time.push(t) + for(var i=d; i>0; --i) { + var dx = arguments[i] + state.push(clamp(lo[i-1], hi[i-1], state[statePtr++] + dx)) + velocity.push(dx * sf) + } +} + +proto.idle = function(t) { + var t0 = this.lastT() + if(t < t0) { + return + } + var d = this.dimension + var state = this._state + var velocity = this._velocity + var statePtr = state.length-d + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var dt = t - t0 + this._time.push(t) + for(var i=d-1; i>=0; --i) { + state.push(clamp(lo[i], hi[i], state[statePtr] + dt * velocity[statePtr])) + velocity.push(0) + statePtr += 1 + } +} + +function getZero(d) { + var result = new Array(d) + for(var i=0; i shape[0] - step[0]/2) (x = step[0]/2), (y += step[1]) + } + + return canvas +} + +},{"css-font/stringify":130}],218:[function(_dereq_,module,exports){ +'use strict' + +module.exports = measure + +measure.canvas = document.createElement('canvas') +measure.cache = {} + +function measure (font, o) { + if (!o) o = {} + + if (typeof font === 'string' || Array.isArray(font)) { + o.family = font + } + + var family = Array.isArray(o.family) ? o.family.join(', ') : o.family + if (!family) throw Error('`family` must be defined') + + var fs = o.size || o.fontSize || o.em || 48 + var weight = o.weight || o.fontWeight || '' + var style = o.style || o.fontStyle || '' + var font = [style, weight, fs].join(' ') + 'px ' + family + var origin = o.origin || 'top' + + if (measure.cache[family]) { + // return more precise values if cache has them + if (fs <= measure.cache[family].em) { + return applyOrigin(measure.cache[family], origin) + } + } + + var canvas = o.canvas || measure.canvas + var ctx = canvas.getContext('2d') + var chars = { + upper: o.upper !== undefined ? o.upper : 'H', + lower: o.lower !== undefined ? o.lower : 'x', + descent: o.descent !== undefined ? o.descent : 'p', + ascent: o.ascent !== undefined ? o.ascent : 'h', + tittle: o.tittle !== undefined ? o.tittle : 'i', + overshoot: o.overshoot !== undefined ? o.overshoot : 'O' + } + var l = Math.ceil(fs * 1.5) + canvas.height = l + canvas.width = l * .5 + ctx.font = font + + var char = 'H' + var result = { + top: 0 + } + + // measure line-height + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillStyle = 'black' + ctx.fillText(char, 0, 0) + var topPx = firstTop(ctx.getImageData(0, 0, l, l)) + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'bottom' + ctx.fillText(char, 0, l) + var bottomPx = firstTop(ctx.getImageData(0, 0, l, l)) + result.lineHeight = + result.bottom = l - bottomPx + topPx + + // measure baseline + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'alphabetic' + ctx.fillText(char, 0, l) + var baselinePx = firstTop(ctx.getImageData(0, 0, l, l)) + var baseline = l - baselinePx - 1 + topPx + result.baseline = + result.alphabetic = baseline + + // measure median + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'middle' + ctx.fillText(char, 0, l * .5) + var medianPx = firstTop(ctx.getImageData(0, 0, l, l)) + result.median = + result.middle = l - medianPx - 1 + topPx - l * .5 + + // measure hanging + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'hanging' + ctx.fillText(char, 0, l * .5) + var hangingPx = firstTop(ctx.getImageData(0, 0, l, l)) + result.hanging = l - hangingPx - 1 + topPx - l * .5 + + // measure ideographic + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'ideographic' + ctx.fillText(char, 0, l) + var ideographicPx = firstTop(ctx.getImageData(0, 0, l, l)) + result.ideographic = l - ideographicPx - 1 + topPx + + // measure cap + if (chars.upper) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.upper, 0, 0) + result.upper = firstTop(ctx.getImageData(0, 0, l, l)) + result.capHeight = (result.baseline - result.upper) + } + + // measure x + if (chars.lower) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.lower, 0, 0) + result.lower = firstTop(ctx.getImageData(0, 0, l, l)) + result.xHeight = (result.baseline - result.lower) + } + + // measure tittle + if (chars.tittle) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.tittle, 0, 0) + result.tittle = firstTop(ctx.getImageData(0, 0, l, l)) + } + + // measure ascent + if (chars.ascent) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.ascent, 0, 0) + result.ascent = firstTop(ctx.getImageData(0, 0, l, l)) + } + + // measure descent + if (chars.descent) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.descent, 0, 0) + result.descent = firstBottom(ctx.getImageData(0, 0, l, l)) + } + + // measure overshoot + if (chars.overshoot) { + ctx.clearRect(0, 0, l, l) + ctx.textBaseline = 'top' + ctx.fillText(chars.overshoot, 0, 0) + var overshootPx = firstBottom(ctx.getImageData(0, 0, l, l)) + result.overshoot = overshootPx - baseline + } + + // normalize result + for (var name in result) { + result[name] /= fs + } + + result.em = fs + measure.cache[family] = result + + return applyOrigin(result, origin) +} + +function applyOrigin(obj, origin) { + var res = {} + if (typeof origin === 'string') origin = obj[origin] + for (var name in obj) { + if (name === 'em') continue + res[name] = obj[name] - origin + } + return res +} + +function firstTop(iData) { + var l = iData.height + var data = iData.data + for (var i = 3; i < data.length; i+=4) { + if (data[i] !== 0) { + return Math.floor((i - 3) *.25 / l) + } + } +} + +function firstBottom(iData) { + var l = iData.height + var data = iData.data + for (var i = data.length - 1; i > 0; i -= 4) { + if (data[i] !== 0) { + return Math.floor((i - 3) *.25 / l) + } + } +} + +},{}],219:[function(_dereq_,module,exports){ +"use strict" + +module.exports = createRBTree + +var RED = 0 +var BLACK = 1 + +function RBNode(color, key, value, left, right, count) { + this._color = color + this.key = key + this.value = value + this.left = left + this.right = right + this._count = count +} + +function cloneNode(node) { + return new RBNode(node._color, node.key, node.value, node.left, node.right, node._count) +} + +function repaint(color, node) { + return new RBNode(color, node.key, node.value, node.left, node.right, node._count) +} + +function recount(node) { + node._count = 1 + (node.left ? node.left._count : 0) + (node.right ? node.right._count : 0) +} + +function RedBlackTree(compare, root) { + this._compare = compare + this.root = root +} + +var proto = RedBlackTree.prototype + +Object.defineProperty(proto, "keys", { + get: function() { + var result = [] + this.forEach(function(k,v) { + result.push(k) + }) + return result + } +}) + +Object.defineProperty(proto, "values", { + get: function() { + var result = [] + this.forEach(function(k,v) { + result.push(v) + }) + return result + } +}) + +//Returns the number of nodes in the tree +Object.defineProperty(proto, "length", { + get: function() { + if(this.root) { + return this.root._count + } + return 0 + } +}) + +//Insert a new item into the tree +proto.insert = function(key, value) { + var cmp = this._compare + //Find point to insert new node at + var n = this.root + var n_stack = [] + var d_stack = [] + while(n) { + var d = cmp(key, n.key) + n_stack.push(n) + d_stack.push(d) + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + //Rebuild path to leaf node + n_stack.push(new RBNode(RED, key, value, null, null, 1)) + for(var s=n_stack.length-2; s>=0; --s) { + var n = n_stack[s] + if(d_stack[s] <= 0) { + n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s+1], n.right, n._count+1) + } else { + n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s+1], n._count+1) + } + } + //Rebalance tree using rotations + //console.log("start insert", key, d_stack) + for(var s=n_stack.length-1; s>1; --s) { + var p = n_stack[s-1] + var n = n_stack[s] + if(p._color === BLACK || n._color === BLACK) { + break + } + var pp = n_stack[s-2] + if(pp.left === p) { + if(p.left === n) { + var y = pp.right + if(y && y._color === RED) { + //console.log("LLr") + p._color = BLACK + pp.right = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("LLb") + pp._color = RED + pp.left = p.right + p._color = BLACK + p.right = pp + n_stack[s-2] = p + n_stack[s-1] = n + recount(pp) + recount(p) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.left === pp) { + ppp.left = p + } else { + ppp.right = p + } + } + break + } + } else { + var y = pp.right + if(y && y._color === RED) { + //console.log("LRr") + p._color = BLACK + pp.right = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("LRb") + p.right = n.left + pp._color = RED + pp.left = n.right + n._color = BLACK + n.left = p + n.right = pp + n_stack[s-2] = n + n_stack[s-1] = p + recount(pp) + recount(p) + recount(n) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.left === pp) { + ppp.left = n + } else { + ppp.right = n + } + } + break + } + } + } else { + if(p.right === n) { + var y = pp.left + if(y && y._color === RED) { + //console.log("RRr", y.key) + p._color = BLACK + pp.left = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("RRb") + pp._color = RED + pp.right = p.left + p._color = BLACK + p.left = pp + n_stack[s-2] = p + n_stack[s-1] = n + recount(pp) + recount(p) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.right === pp) { + ppp.right = p + } else { + ppp.left = p + } + } + break + } + } else { + var y = pp.left + if(y && y._color === RED) { + //console.log("RLr") + p._color = BLACK + pp.left = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("RLb") + p.left = n.right + pp._color = RED + pp.right = n.left + n._color = BLACK + n.right = p + n.left = pp + n_stack[s-2] = n + n_stack[s-1] = p + recount(pp) + recount(p) + recount(n) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.right === pp) { + ppp.right = n + } else { + ppp.left = n + } + } + break + } + } + } + } + //Return new tree + n_stack[0]._color = BLACK + return new RedBlackTree(cmp, n_stack[0]) +} + + +//Visit all nodes inorder +function doVisitFull(visit, node) { + if(node.left) { + var v = doVisitFull(visit, node.left) + if(v) { return v } + } + var v = visit(node.key, node.value) + if(v) { return v } + if(node.right) { + return doVisitFull(visit, node.right) + } +} + +//Visit half nodes in order +function doVisitHalf(lo, compare, visit, node) { + var l = compare(lo, node.key) + if(l <= 0) { + if(node.left) { + var v = doVisitHalf(lo, compare, visit, node.left) + if(v) { return v } + } + var v = visit(node.key, node.value) + if(v) { return v } + } + if(node.right) { + return doVisitHalf(lo, compare, visit, node.right) + } +} + +//Visit all nodes within a range +function doVisit(lo, hi, compare, visit, node) { + var l = compare(lo, node.key) + var h = compare(hi, node.key) + var v + if(l <= 0) { + if(node.left) { + v = doVisit(lo, hi, compare, visit, node.left) + if(v) { return v } + } + if(h > 0) { + v = visit(node.key, node.value) + if(v) { return v } + } + } + if(h > 0 && node.right) { + return doVisit(lo, hi, compare, visit, node.right) + } +} + + +proto.forEach = function rbTreeForEach(visit, lo, hi) { + if(!this.root) { + return + } + switch(arguments.length) { + case 1: + return doVisitFull(visit, this.root) + break + + case 2: + return doVisitHalf(lo, this._compare, visit, this.root) + break + + case 3: + if(this._compare(lo, hi) >= 0) { + return + } + return doVisit(lo, hi, this._compare, visit, this.root) + break + } +} + +//First item in list +Object.defineProperty(proto, "begin", { + get: function() { + var stack = [] + var n = this.root + while(n) { + stack.push(n) + n = n.left + } + return new RedBlackTreeIterator(this, stack) + } +}) + +//Last item in list +Object.defineProperty(proto, "end", { + get: function() { + var stack = [] + var n = this.root + while(n) { + stack.push(n) + n = n.right + } + return new RedBlackTreeIterator(this, stack) + } +}) + +//Find the ith item in the tree +proto.at = function(idx) { + if(idx < 0) { + return new RedBlackTreeIterator(this, []) + } + var n = this.root + var stack = [] + while(true) { + stack.push(n) + if(n.left) { + if(idx < n.left._count) { + n = n.left + continue + } + idx -= n.left._count + } + if(!idx) { + return new RedBlackTreeIterator(this, stack) + } + idx -= 1 + if(n.right) { + if(idx >= n.right._count) { + break + } + n = n.right + } else { + break + } + } + return new RedBlackTreeIterator(this, []) +} + +proto.ge = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d <= 0) { + last_ptr = stack.length + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.gt = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d < 0) { + last_ptr = stack.length + } + if(d < 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.lt = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d > 0) { + last_ptr = stack.length + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.le = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d >= 0) { + last_ptr = stack.length + } + if(d < 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +//Finds the item with key if it exists +proto.find = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d === 0) { + return new RedBlackTreeIterator(this, stack) + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + return new RedBlackTreeIterator(this, []) +} + +//Removes item with key from tree +proto.remove = function(key) { + var iter = this.find(key) + if(iter) { + return iter.remove() + } + return this +} + +//Returns the item at `key` +proto.get = function(key) { + var cmp = this._compare + var n = this.root + while(n) { + var d = cmp(key, n.key) + if(d === 0) { + return n.value + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + return +} + +//Iterator for red black tree +function RedBlackTreeIterator(tree, stack) { + this.tree = tree + this._stack = stack +} + +var iproto = RedBlackTreeIterator.prototype + +//Test if iterator is valid +Object.defineProperty(iproto, "valid", { + get: function() { + return this._stack.length > 0 + } +}) + +//Node of the iterator +Object.defineProperty(iproto, "node", { + get: function() { + if(this._stack.length > 0) { + return this._stack[this._stack.length-1] + } + return null + }, + enumerable: true +}) + +//Makes a copy of an iterator +iproto.clone = function() { + return new RedBlackTreeIterator(this.tree, this._stack.slice()) +} + +//Swaps two nodes +function swapNode(n, v) { + n.key = v.key + n.value = v.value + n.left = v.left + n.right = v.right + n._color = v._color + n._count = v._count +} + +//Fix up a double black node in a tree +function fixDoubleBlack(stack) { + var n, p, s, z + for(var i=stack.length-1; i>=0; --i) { + n = stack[i] + if(i === 0) { + n._color = BLACK + return + } + //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key) + p = stack[i-1] + if(p.left === n) { + //console.log("left child") + s = p.right + if(s.right && s.right._color === RED) { + //console.log("case 1: right sibling child red") + s = p.right = cloneNode(s) + z = s.right = cloneNode(s.right) + p.right = s.left + s.left = p + s.right = z + s._color = p._color + n._color = BLACK + p._color = BLACK + z._color = BLACK + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = s + } else { + pp.right = s + } + } + stack[i-1] = s + return + } else if(s.left && s.left._color === RED) { + //console.log("case 1: left sibling child red") + s = p.right = cloneNode(s) + z = s.left = cloneNode(s.left) + p.right = z.left + s.left = z.right + z.left = p + z.right = s + z._color = p._color + p._color = BLACK + s._color = BLACK + n._color = BLACK + recount(p) + recount(s) + recount(z) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = z + } else { + pp.right = z + } + } + stack[i-1] = z + return + } + if(s._color === BLACK) { + if(p._color === RED) { + //console.log("case 2: black sibling, red parent", p.right.value) + p._color = BLACK + p.right = repaint(RED, s) + return + } else { + //console.log("case 2: black sibling, black parent", p.right.value) + p.right = repaint(RED, s) + continue + } + } else { + //console.log("case 3: red sibling") + s = cloneNode(s) + p.right = s.left + s.left = p + s._color = p._color + p._color = RED + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = s + } else { + pp.right = s + } + } + stack[i-1] = s + stack[i] = p + if(i+1 < stack.length) { + stack[i+1] = n + } else { + stack.push(n) + } + i = i+2 + } + } else { + //console.log("right child") + s = p.left + if(s.left && s.left._color === RED) { + //console.log("case 1: left sibling child red", p.value, p._color) + s = p.left = cloneNode(s) + z = s.left = cloneNode(s.left) + p.left = s.right + s.right = p + s.left = z + s._color = p._color + n._color = BLACK + p._color = BLACK + z._color = BLACK + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = s + } else { + pp.left = s + } + } + stack[i-1] = s + return + } else if(s.right && s.right._color === RED) { + //console.log("case 1: right sibling child red") + s = p.left = cloneNode(s) + z = s.right = cloneNode(s.right) + p.left = z.right + s.right = z.left + z.right = p + z.left = s + z._color = p._color + p._color = BLACK + s._color = BLACK + n._color = BLACK + recount(p) + recount(s) + recount(z) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = z + } else { + pp.left = z + } + } + stack[i-1] = z + return + } + if(s._color === BLACK) { + if(p._color === RED) { + //console.log("case 2: black sibling, red parent") + p._color = BLACK + p.left = repaint(RED, s) + return + } else { + //console.log("case 2: black sibling, black parent") + p.left = repaint(RED, s) + continue + } + } else { + //console.log("case 3: red sibling") + s = cloneNode(s) + p.left = s.right + s.right = p + s._color = p._color + p._color = RED + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = s + } else { + pp.left = s + } + } + stack[i-1] = s + stack[i] = p + if(i+1 < stack.length) { + stack[i+1] = n + } else { + stack.push(n) + } + i = i+2 + } + } + } +} + +//Removes item at iterator from tree +iproto.remove = function() { + var stack = this._stack + if(stack.length === 0) { + return this.tree + } + //First copy path to node + var cstack = new Array(stack.length) + var n = stack[stack.length-1] + cstack[cstack.length-1] = new RBNode(n._color, n.key, n.value, n.left, n.right, n._count) + for(var i=stack.length-2; i>=0; --i) { + var n = stack[i] + if(n.left === stack[i+1]) { + cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) + } else { + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + } + + //Get node + n = cstack[cstack.length-1] + //console.log("start remove: ", n.value) + + //If not leaf, then swap with previous node + if(n.left && n.right) { + //console.log("moving to leaf") + + //First walk to previous leaf + var split = cstack.length + n = n.left + while(n.right) { + cstack.push(n) + n = n.right + } + //Copy path to leaf + var v = cstack[split-1] + cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right, n._count)) + cstack[split-1].key = n.key + cstack[split-1].value = n.value + + //Fix up stack + for(var i=cstack.length-2; i>=split; --i) { + n = cstack[i] + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + cstack[split-1].left = cstack[split] + } + //console.log("stack=", cstack.map(function(v) { return v.value })) + + //Remove leaf node + n = cstack[cstack.length-1] + if(n._color === RED) { + //Easy case: removing red leaf + //console.log("RED leaf") + var p = cstack[cstack.length-2] + if(p.left === n) { + p.left = null + } else if(p.right === n) { + p.right = null + } + cstack.pop() + for(var i=0; i 0) { + return this._stack[this._stack.length-1].key + } + return + }, + enumerable: true +}) + +//Returns value +Object.defineProperty(iproto, "value", { + get: function() { + if(this._stack.length > 0) { + return this._stack[this._stack.length-1].value + } + return + }, + enumerable: true +}) + + +//Returns the position of this iterator in the sorted list +Object.defineProperty(iproto, "index", { + get: function() { + var idx = 0 + var stack = this._stack + if(stack.length === 0) { + var r = this.tree.root + if(r) { + return r._count + } + return 0 + } else if(stack[stack.length-1].left) { + idx = stack[stack.length-1].left._count + } + for(var s=stack.length-2; s>=0; --s) { + if(stack[s+1] === stack[s].right) { + ++idx + if(stack[s].left) { + idx += stack[s].left._count + } + } + } + return idx + }, + enumerable: true +}) + +//Advances iterator to next element in list +iproto.next = function() { + var stack = this._stack + if(stack.length === 0) { + return + } + var n = stack[stack.length-1] + if(n.right) { + n = n.right + while(n) { + stack.push(n) + n = n.left + } + } else { + stack.pop() + while(stack.length > 0 && stack[stack.length-1].right === n) { + n = stack[stack.length-1] + stack.pop() + } + } +} + +//Checks if iterator is at end of tree +Object.defineProperty(iproto, "hasNext", { + get: function() { + var stack = this._stack + if(stack.length === 0) { + return false + } + if(stack[stack.length-1].right) { + return true + } + for(var s=stack.length-1; s>0; --s) { + if(stack[s-1].left === stack[s]) { + return true + } + } + return false + } +}) + +//Update value +iproto.update = function(value) { + var stack = this._stack + if(stack.length === 0) { + throw new Error("Can't update empty node!") + } + var cstack = new Array(stack.length) + var n = stack[stack.length-1] + cstack[cstack.length-1] = new RBNode(n._color, n.key, value, n.left, n.right, n._count) + for(var i=stack.length-2; i>=0; --i) { + n = stack[i] + if(n.left === stack[i+1]) { + cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) + } else { + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + } + return new RedBlackTree(this.tree._compare, cstack[0]) +} + +//Moves iterator backward one element +iproto.prev = function() { + var stack = this._stack + if(stack.length === 0) { + return + } + var n = stack[stack.length-1] + if(n.left) { + n = n.left + while(n) { + stack.push(n) + n = n.right + } + } else { + stack.pop() + while(stack.length > 0 && stack[stack.length-1].left === n) { + n = stack[stack.length-1] + stack.pop() + } + } +} + +//Checks if iterator is at start of tree +Object.defineProperty(iproto, "hasPrev", { + get: function() { + var stack = this._stack + if(stack.length === 0) { + return false + } + if(stack[stack.length-1].left) { + return true + } + for(var s=stack.length-1; s>0; --s) { + if(stack[s-1].right === stack[s]) { + return true + } + } + return false + } +}) + +//Default comparison function +function defaultCompare(a, b) { + if(a < b) { + return -1 + } + if(a > b) { + return 1 + } + return 0 +} + +//Build a tree +function createRBTree(compare) { + return new RedBlackTree(compare || defaultCompare, null) +} +},{}],220:[function(_dereq_,module,exports){ +// transliterated from the python snippet here: +// http://en.wikipedia.org/wiki/Lanczos_approximation + +var g = 7; +var p = [ + 0.99999999999980993, + 676.5203681218851, + -1259.1392167224028, + 771.32342877765313, + -176.61502916214059, + 12.507343278686905, + -0.13857109526572012, + 9.9843695780195716e-6, + 1.5056327351493116e-7 +]; + +var g_ln = 607/128; +var p_ln = [ + 0.99999999999999709182, + 57.156235665862923517, + -59.597960355475491248, + 14.136097974741747174, + -0.49191381609762019978, + 0.33994649984811888699e-4, + 0.46523628927048575665e-4, + -0.98374475304879564677e-4, + 0.15808870322491248884e-3, + -0.21026444172410488319e-3, + 0.21743961811521264320e-3, + -0.16431810653676389022e-3, + 0.84418223983852743293e-4, + -0.26190838401581408670e-4, + 0.36899182659531622704e-5 +]; + +// Spouge approximation (suitable for large arguments) +function lngamma(z) { + + if(z < 0) return Number('0/0'); + var x = p_ln[0]; + for(var i = p_ln.length - 1; i > 0; --i) x += p_ln[i] / (z + i); + var t = z + g_ln + 0.5; + return .5*Math.log(2*Math.PI)+(z+.5)*Math.log(t)-t+Math.log(x)-Math.log(z); +} + +module.exports = function gamma (z) { + if (z < 0.5) { + return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z)); + } + else if(z > 100) return Math.exp(lngamma(z)); + else { + z -= 1; + var x = p[0]; + for (var i = 1; i < g + 2; i++) { + x += p[i] / (z + i); + } + var t = z + g + 0.5; + + return Math.sqrt(2 * Math.PI) + * Math.pow(t, z + 0.5) + * Math.exp(-t) + * x + ; + } +}; + +module.exports.log = lngamma; + +},{}],221:[function(_dereq_,module,exports){ +module.exports = getCanvasContext +function getCanvasContext (type, opts) { + if (typeof type !== 'string') { + throw new TypeError('must specify type string') + } + + opts = opts || {} + + if (typeof document === 'undefined' && !opts.canvas) { + return null // check for Node + } + + var canvas = opts.canvas || document.createElement('canvas') + if (typeof opts.width === 'number') { + canvas.width = opts.width + } + if (typeof opts.height === 'number') { + canvas.height = opts.height + } + + var attribs = opts + var gl + try { + var names = [ type ] + // prefix GL contexts + if (type.indexOf('webgl') === 0) { + names.push('experimental-' + type) + } + + for (var i = 0; i < names.length; i++) { + gl = canvas.getContext(names[i], attribs) + if (gl) return gl + } + } catch (e) { + gl = null + } + return (gl || null) // ensure null on fail +} + +},{}],222:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createAxes + +var createText = _dereq_('./lib/text.js') +var createLines = _dereq_('./lib/lines.js') +var createBackground = _dereq_('./lib/background.js') +var getCubeProperties = _dereq_('./lib/cube.js') +var Ticks = _dereq_('./lib/ticks.js') + +var identity = new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]) + +function copyVec3(a, b) { + a[0] = b[0] + a[1] = b[1] + a[2] = b[2] + return a +} + +function Axes(gl) { + this.gl = gl + + this.pixelRatio = 1 + + this.bounds = [ [-10, -10, -10], + [ 10, 10, 10] ] + this.ticks = [ [], [], [] ] + this.autoTicks = true + this.tickSpacing = [ 1, 1, 1 ] + + this.tickEnable = [ true, true, true ] + this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ] + this.tickSize = [ 12, 12, 12 ] + this.tickAngle = [ 0, 0, 0 ] + this._tickAlign = [ 'auto', 'auto', 'auto' ] + this.tickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.tickPad = [ 10, 10, 10 ] + + this.lastCubeProps = { + cubeEdges: [0,0,0], + axis: [0,0,0] + } + + this.labels = [ 'x', 'y', 'z' ] + this.labelEnable = [ true, true, true ] + this.labelFont = 'sans-serif' + this.labelSize = [ 20, 20, 20 ] + this._labelAngle = [ 0, 0, 0 ] + this._labelAlign = [ 'auto', 'auto', 'auto' ] + this.labelColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.labelPad = [ 10, 10, 10 ] + + this.lineEnable = [ true, true, true ] + this.lineMirror = [ false, false, false ] + this.lineWidth = [ 1, 1, 1 ] + this.lineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + + this.lineTickEnable = [ true, true, true ] + this.lineTickMirror = [ false, false, false ] + this.lineTickLength = [ 0, 0, 0 ] + this.lineTickWidth = [ 1, 1, 1 ] + this.lineTickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + + this.gridEnable = [ true, true, true ] + this.gridWidth = [ 1, 1, 1 ] + this.gridColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + + this.zeroEnable = [ true, true, true ] + this.zeroLineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.zeroLineWidth = [ 2, 2, 2 ] + + this.backgroundEnable = [ false, false, false ] + this.backgroundColor = [ [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5] ] + + this._firstInit = true + this._text = null + this._lines = null + this._background = createBackground(gl) +} + +var proto = Axes.prototype + +proto.update = function(options) { + options = options || {} + + //Option parsing helper functions + function parseOption(nest, cons, name) { + if(name in options) { + var opt = options[name] + var prev = this[name] + var next + if(nest ? (Array.isArray(opt) && Array.isArray(opt[0])) : + Array.isArray(opt) ) { + this[name] = next = [ cons(opt[0]), cons(opt[1]), cons(opt[2]) ] + } else { + this[name] = next = [ cons(opt), cons(opt), cons(opt) ] + } + for(var i=0; i<3; ++i) { + if(next[i] !== prev[i]) { + return true + } + } + } + return false + } + + var NUMBER = parseOption.bind(this, false, Number) + var BOOLEAN = parseOption.bind(this, false, Boolean) + var STRING = parseOption.bind(this, false, String) + var COLOR = parseOption.bind(this, true, function(v) { + if(Array.isArray(v)) { + if(v.length === 3) { + return [ +v[0], +v[1], +v[2], 1.0 ] + } else if(v.length === 4) { + return [ +v[0], +v[1], +v[2], +v[3] ] + } + } + return [ 0, 0, 0, 1 ] + }) + + //Tick marks and bounds + var nextTicks + var ticksUpdate = false + var boundsChanged = false + if('bounds' in options) { + var bounds = options.bounds +i_loop: + for(var i=0; i<2; ++i) { + for(var j=0; j<3; ++j) { + if(bounds[i][j] !== this.bounds[i][j]) { + boundsChanged = true + } + this.bounds[i][j] = bounds[i][j] + } + } + } + if('ticks' in options) { + nextTicks = options.ticks + ticksUpdate = true + this.autoTicks = false + for(var i=0; i<3; ++i) { + this.tickSpacing[i] = 0.0 + } + } else if(NUMBER('tickSpacing')) { + this.autoTicks = true + boundsChanged = true + } + + if(this._firstInit) { + if(!('ticks' in options || 'tickSpacing' in options)) { + this.autoTicks = true + } + + //Force tick recomputation on first update + boundsChanged = true + ticksUpdate = true + this._firstInit = false + } + + if(boundsChanged && this.autoTicks) { + nextTicks = Ticks.create(this.bounds, this.tickSpacing) + ticksUpdate = true + } + + //Compare next ticks to previous ticks, only update if needed + if(ticksUpdate) { + for(var i=0; i<3; ++i) { + nextTicks[i].sort(function(a,b) { + return a.x-b.x + }) + } + if(Ticks.equal(nextTicks, this.ticks)) { + ticksUpdate = false + } else { + this.ticks = nextTicks + } + } + + //Parse tick properties + BOOLEAN('tickEnable') + if(STRING('tickFont')) { + ticksUpdate = true //If font changes, must rebuild vbo + } + NUMBER('tickSize') + NUMBER('tickAngle') + NUMBER('tickPad') + COLOR('tickColor') + + //Axis labels + var labelUpdate = STRING('labels') + if(STRING('labelFont')) { + labelUpdate = true + } + BOOLEAN('labelEnable') + NUMBER('labelSize') + NUMBER('labelPad') + COLOR('labelColor') + + //Axis lines + BOOLEAN('lineEnable') + BOOLEAN('lineMirror') + NUMBER('lineWidth') + COLOR('lineColor') + + //Axis line ticks + BOOLEAN('lineTickEnable') + BOOLEAN('lineTickMirror') + NUMBER('lineTickLength') + NUMBER('lineTickWidth') + COLOR('lineTickColor') + + //Grid lines + BOOLEAN('gridEnable') + NUMBER('gridWidth') + COLOR('gridColor') + + //Zero line + BOOLEAN('zeroEnable') + COLOR('zeroLineColor') + NUMBER('zeroLineWidth') + + //Background + BOOLEAN('backgroundEnable') + COLOR('backgroundColor') + + //Update text if necessary + if(!this._text) { + this._text = createText( + this.gl, + this.bounds, + this.labels, + this.labelFont, + this.ticks, + this.tickFont) + } else if(this._text && (labelUpdate || ticksUpdate)) { + this._text.update( + this.bounds, + this.labels, + this.labelFont, + this.ticks, + this.tickFont) + } + + //Update lines if necessary + if(this._lines && ticksUpdate) { + this._lines.dispose() + this._lines = null + } + if(!this._lines) { + this._lines = createLines(this.gl, this.bounds, this.ticks) + } +} + +function OffsetInfo() { + this.primalOffset = [0,0,0] + this.primalMinor = [0,0,0] + this.mirrorOffset = [0,0,0] + this.mirrorMinor = [0,0,0] +} + +var LINE_OFFSET = [ new OffsetInfo(), new OffsetInfo(), new OffsetInfo() ] + +function computeLineOffset(result, i, bounds, cubeEdges, cubeAxis) { + var primalOffset = result.primalOffset + var primalMinor = result.primalMinor + var dualOffset = result.mirrorOffset + var dualMinor = result.mirrorMinor + var e = cubeEdges[i] + + //Calculate offsets + for(var j=0; j<3; ++j) { + if(i === j) { + continue + } + var a = primalOffset, + b = dualOffset, + c = primalMinor, + d = dualMinor + if(e & (1< 0) { + c[j] = -1 + d[j] = 0 + } else { + c[j] = 0 + d[j] = +1 + } + } +} + +var CUBE_ENABLE = [0,0,0] +var DEFAULT_PARAMS = { + model: identity, + view: identity, + projection: identity +} + +proto.isOpaque = function() { + return true +} + +proto.isTransparent = function() { + return false +} + +proto.drawTransparent = function(params) {} + +var ALIGN_OPTION_AUTO = 0 // i.e. as defined in the shader the text would rotate to stay upwards range: [-90,90] + +var PRIMAL_MINOR = [0,0,0] +var MIRROR_MINOR = [0,0,0] +var PRIMAL_OFFSET = [0,0,0] + +proto.draw = function(params) { + params = params || DEFAULT_PARAMS + + var gl = this.gl + + //Geometry for camera and axes + var model = params.model || identity + var view = params.view || identity + var projection = params.projection || identity + var bounds = this.bounds + + //Unpack axis info + var cubeParams = getCubeProperties(model, view, projection, bounds) + var cubeEdges = cubeParams.cubeEdges + var cubeAxis = cubeParams.axis + + var cx = view[12] + var cy = view[13] + var cz = view[14] + var cw = view[15] + + var pixelScaleF = this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight + + for(var i=0; i<3; ++i) { + this.lastCubeProps.cubeEdges[i] = cubeEdges[i] + this.lastCubeProps.axis[i] = cubeAxis[i] + } + + //Compute axis info + var lineOffset = LINE_OFFSET + for(var i=0; i<3; ++i) { + computeLineOffset( + LINE_OFFSET[i], + i, + this.bounds, + cubeEdges, + cubeAxis) + } + + //Set up state parameters + var gl = this.gl + + //Draw background first + var cubeEnable = CUBE_ENABLE + for(var i=0; i<3; ++i) { + if(this.backgroundEnable[i]) { + cubeEnable[i] = cubeAxis[i] + } else { + cubeEnable[i] = 0 + } + } + + this._background.draw( + model, + view, + projection, + bounds, + cubeEnable, + this.backgroundColor) + + //Draw lines + this._lines.bind( + model, + view, + projection, + this) + + //First draw grid lines and zero lines + for(var i=0; i<3; ++i) { + var x = [0,0,0] + if(cubeAxis[i] > 0) { + x[i] = bounds[1][i] + } else { + x[i] = bounds[0][i] + } + + //Draw grid lines + for(var j=0; j<2; ++j) { + var u = (i + 1 + j) % 3 + var v = (i + 1 + (j^1)) % 3 + if(this.gridEnable[u]) { + this._lines.drawGrid(u, v, this.bounds, x, this.gridColor[u], this.gridWidth[u]*this.pixelRatio) + } + } + + //Draw zero lines (need to do this AFTER all grid lines are drawn) + for(var j=0; j<2; ++j) { + var u = (i + 1 + j) % 3 + var v = (i + 1 + (j^1)) % 3 + if(this.zeroEnable[v]) { + //Check if zero line in bounds + if(Math.min(bounds[0][v], bounds[1][v]) <= 0 && Math.max(bounds[0][v], bounds[1][v]) >= 0) { + this._lines.drawZero(u, v, this.bounds, x, this.zeroLineColor[v], this.zeroLineWidth[v]*this.pixelRatio) + } + } + } + } + + //Then draw axis lines and tick marks + for(var i=0; i<3; ++i) { + + //Draw axis lines + if(this.lineEnable[i]) { + this._lines.drawAxisLine(i, this.bounds, lineOffset[i].primalOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) + } + if(this.lineMirror[i]) { + this._lines.drawAxisLine(i, this.bounds, lineOffset[i].mirrorOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) + } + + //Compute minor axes + var primalMinor = copyVec3(PRIMAL_MINOR, lineOffset[i].primalMinor) + var mirrorMinor = copyVec3(MIRROR_MINOR, lineOffset[i].mirrorMinor) + var tickLength = this.lineTickLength + var op = 0 + for(var j=0; j<3; ++j) { + var scaleFactor = pixelScaleF / model[5*j] + primalMinor[j] *= tickLength[j] * scaleFactor + mirrorMinor[j] *= tickLength[j] * scaleFactor + } + + //Draw axis line ticks + if(this.lineTickEnable[i]) { + this._lines.drawAxisTicks(i, lineOffset[i].primalOffset, primalMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) + } + if(this.lineTickMirror[i]) { + this._lines.drawAxisTicks(i, lineOffset[i].mirrorOffset, mirrorMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) + } + } + this._lines.unbind() + + //Draw text sprites + this._text.bind( + model, + view, + projection, + this.pixelRatio) + + var alignOpt // options in shader are from this list {-1, 0, 1, 2, 3, ..., n} + // -1: backward compatible + // 0: raw data + // 1: auto align, free angles + // 2: auto align, horizontal or vertical + //3-n: auto align, round to n directions e.g. 12 -> round to angles with 30-degree steps + + var hv_ratio = 0.5 // can have an effect on the ratio between horizontals and verticals when using option 2 + + var enableAlign + var alignDir + + function alignTo(i) { + alignDir = [0,0,0] + alignDir[i] = 1 + } + + function solveTickAlignments(i, minor, major) { + + var i1 = (i + 1) % 3 + var i2 = (i + 2) % 3 + + var A = minor[i1] + var B = minor[i2] + var C = major[i1] + var D = major[i2] + + if ((A > 0) && (D > 0)) { alignTo(i1); return; } + else if ((A > 0) && (D < 0)) { alignTo(i1); return; } + else if ((A < 0) && (D > 0)) { alignTo(i1); return; } + else if ((A < 0) && (D < 0)) { alignTo(i1); return; } + else if ((B > 0) && (C > 0)) { alignTo(i2); return; } + else if ((B > 0) && (C < 0)) { alignTo(i2); return; } + else if ((B < 0) && (C > 0)) { alignTo(i2); return; } + else if ((B < 0) && (C < 0)) { alignTo(i2); return; } + } + + for(var i=0; i<3; ++i) { + + var minor = lineOffset[i].primalMinor + var major = lineOffset[i].mirrorMinor + + var offset = copyVec3(PRIMAL_OFFSET, lineOffset[i].primalOffset) + + for(var j=0; j<3; ++j) { + if(this.lineTickEnable[i]) { + offset[j] += pixelScaleF * minor[j] * Math.max(this.lineTickLength[j], 0) / model[5*j] + } + } + + var axis = [0,0,0] + axis[i] = 1 + + //Draw tick text + if(this.tickEnable[i]) { + + if(this.tickAngle[i] === -3600) { + this.tickAngle[i] = 0 + this._tickAlign[i] = 'auto' + } else { + this._tickAlign[i] = -1 + } + + enableAlign = 1; + + alignOpt = [this._tickAlign[i], hv_ratio, enableAlign] + if(alignOpt[0] === 'auto') alignOpt[0] = ALIGN_OPTION_AUTO + else alignOpt[0] = parseInt('' + alignOpt[0]) + + alignDir = [0,0,0] + solveTickAlignments(i, minor, major) + + //Add tick padding + for(var j=0; j<3; ++j) { + offset[j] += pixelScaleF * minor[j] * this.tickPad[j] / model[5*j] + } + + //Draw axis + this._text.drawTicks( + i, + this.tickSize[i], + this.tickAngle[i], + offset, + this.tickColor[i], + axis, + alignDir, + alignOpt) + } + + //Draw labels + if(this.labelEnable[i]) { + + enableAlign = 0 + alignDir = [0,0,0] + if(this.labels[i].length > 4) { // for large label axis enable alignDir to axis + alignTo(i) + enableAlign = 1 + } + + alignOpt = [this._labelAlign[i], hv_ratio, enableAlign] + if(alignOpt[0] === 'auto') alignOpt[0] = ALIGN_OPTION_AUTO + else alignOpt[0] = parseInt('' + alignOpt[0]) + + //Add label padding + for(var j=0; j<3; ++j) { + offset[j] += pixelScaleF * minor[j] * this.labelPad[j] / model[5*j] + } + offset[i] += 0.5 * (bounds[0][i] + bounds[1][i]) + + //Draw axis + this._text.drawLabel( + i, + this.labelSize[i], + this._labelAngle[i], + offset, + this.labelColor[i], + [0,0,0], + alignDir, + alignOpt) + } + } + + this._text.unbind() +} + +proto.dispose = function() { + this._text.dispose() + this._lines.dispose() + this._background.dispose() + this._lines = null + this._text = null + this._background = null + this.gl = null +} + +function createAxes(gl, options) { + var axes = new Axes(gl) + axes.update(options) + return axes +} + +},{"./lib/background.js":223,"./lib/cube.js":224,"./lib/lines.js":225,"./lib/text.js":227,"./lib/ticks.js":228}],223:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createBackgroundCube + +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createShader = _dereq_('./shaders').bg + +function BackgroundCube(gl, buffer, vao, shader) { + this.gl = gl + this.buffer = buffer + this.vao = vao + this.shader = shader +} + +var proto = BackgroundCube.prototype + +proto.draw = function(model, view, projection, bounds, enable, colors) { + var needsBG = false + for(var i=0; i<3; ++i) { + needsBG = needsBG || enable[i] + } + if(!needsBG) { + return + } + + var gl = this.gl + + gl.enable(gl.POLYGON_OFFSET_FILL) + gl.polygonOffset(1, 2) + + this.shader.bind() + this.shader.uniforms = { + model: model, + view: view, + projection: projection, + bounds: bounds, + enable: enable, + colors: colors + } + this.vao.bind() + this.vao.draw(this.gl.TRIANGLES, 36) + this.vao.unbind() + + gl.disable(gl.POLYGON_OFFSET_FILL) +} + +proto.dispose = function() { + this.vao.dispose() + this.buffer.dispose() + this.shader.dispose() +} + +function createBackgroundCube(gl) { + //Create cube vertices + var vertices = [] + var indices = [] + var ptr = 0 + for(var d=0; d<3; ++d) { + var u = (d+1) % 3 + var v = (d+2) % 3 + var x = [0,0,0] + var c = [0,0,0] + for(var s=-1; s<=1; s+=2) { + indices.push(ptr, ptr+2, ptr+1, + ptr+1, ptr+2, ptr+3) + x[d] = s + c[d] = s + for(var i=-1; i<=1; i+=2) { + x[u] = i + for(var j=-1; j<=1; j+=2) { + x[v] = j + vertices.push(x[0], x[1], x[2], + c[0], c[1], c[2]) + ptr += 1 + } + } + //Swap u and v + var tt = u + u = v + v = tt + } + } + + //Allocate buffer and vertex array + var buffer = createBuffer(gl, new Float32Array(vertices)) + var elements = createBuffer(gl, new Uint16Array(indices), gl.ELEMENT_ARRAY_BUFFER) + var vao = createVAO(gl, [ + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 0, + stride: 24 + }, + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 12, + stride: 24 + } + ], elements) + + //Create shader object + var shader = createShader(gl) + shader.attributes.position.location = 0 + shader.attributes.normal.location = 1 + + return new BackgroundCube(gl, buffer, vao, shader) +} + +},{"./shaders":226,"gl-buffer":230,"gl-vao":310}],224:[function(_dereq_,module,exports){ +"use strict" + +module.exports = getCubeEdges + +var bits = _dereq_('bit-twiddle') +var multiply = _dereq_('gl-mat4/multiply') +var invert = _dereq_('gl-mat4/invert') +var splitPoly = _dereq_('split-polygon') +var orient = _dereq_('robust-orientation') + +var mvp = new Array(16) +var imvp = new Array(16) +var pCubeVerts = new Array(8) +var cubeVerts = new Array(8) +var x = new Array(3) +var zero3 = [0,0,0] + +;(function() { + for(var i=0; i<8; ++i) { + pCubeVerts[i] =[1,1,1,1] + cubeVerts[i] = [1,1,1] + } +})() + + +function transformHg(result, x, mat) { + for(var i=0; i<4; ++i) { + result[i] = mat[12+i] + for(var j=0; j<3; ++j) { + result[i] += x[j]*mat[4*j+i] + } + } +} + +var FRUSTUM_PLANES = [ + [ 0, 0, 1, 0, 0], + [ 0, 0,-1, 1, 0], + [ 0,-1, 0, 1, 0], + [ 0, 1, 0, 1, 0], + [-1, 0, 0, 1, 0], + [ 1, 0, 0, 1, 0] +] + +function polygonArea(p) { + for(var i=0; i o0) { + closest |= 1< o0) { + closest |= 1< cubeVerts[i][1]) { + bottom = i + } + } + + //Find left/right neighbors of bottom vertex + var left = -1 + for(var i=0; i<3; ++i) { + var idx = bottom ^ (1< cubeVerts[right][0]) { + right = idx + } + } + + //Determine edge axis coordinates + var cubeEdges = CUBE_EDGES + cubeEdges[0] = cubeEdges[1] = cubeEdges[2] = 0 + cubeEdges[bits.log2(left^bottom)] = bottom&left + cubeEdges[bits.log2(bottom^right)] = bottom&right + var top = right ^ 7 + if(top === closest || top === farthest) { + top = left ^ 7 + cubeEdges[bits.log2(right^top)] = top&right + } else { + cubeEdges[bits.log2(left^top)] = top&left + } + + //Determine visible faces + var axis = CUBE_AXIS + var cutCorner = closest + for(var d=0; d<3; ++d) { + if(cutCorner & (1< HALF_PI) && (b <= ONE_AND_HALF_PI)) ?\n b - PI :\n b;\n}\n\nfloat look_horizontal_or_vertical(float a, float ratio) {\n // ratio controls the ratio between being horizontal to (vertical + horizontal)\n // if ratio is set to 0.5 then it is 50%, 50%.\n // when using a higher ratio e.g. 0.75 the result would\n // likely be more horizontal than vertical.\n\n float b = positive_angle(a);\n\n return\n (b < ( ratio) * HALF_PI) ? 0.0 :\n (b < (2.0 - ratio) * HALF_PI) ? -HALF_PI :\n (b < (2.0 + ratio) * HALF_PI) ? 0.0 :\n (b < (4.0 - ratio) * HALF_PI) ? HALF_PI :\n 0.0;\n}\n\nfloat roundTo(float a, float b) {\n return float(b * floor((a + 0.5 * b) / b));\n}\n\nfloat look_round_n_directions(float a, int n) {\n float b = positive_angle(a);\n float div = TWO_PI / float(n);\n float c = roundTo(b, div);\n return look_upwards(c);\n}\n\nfloat applyAlignOption(float rawAngle, float delta) {\n return\n (option > 2) ? look_round_n_directions(rawAngle + delta, option) : // option 3-n: round to n directions\n (option == 2) ? look_horizontal_or_vertical(rawAngle + delta, hv_ratio) : // horizontal or vertical\n (option == 1) ? rawAngle + delta : // use free angle, and flip to align with one direction of the axis\n (option == 0) ? look_upwards(rawAngle) : // use free angle, and stay upwards\n (option ==-1) ? 0.0 : // useful for backward compatibility, all texts remains horizontal\n rawAngle; // otherwise return back raw input angle\n}\n\nbool isAxisTitle = (axis.x == 0.0) &&\n (axis.y == 0.0) &&\n (axis.z == 0.0);\n\nvoid main() {\n //Compute world offset\n float axisDistance = position.z;\n vec3 dataPosition = axisDistance * axis + offset;\n\n float beta = angle; // i.e. user defined attributes for each tick\n\n float axisAngle;\n float clipAngle;\n float flip;\n\n if (enableAlign) {\n axisAngle = (isAxisTitle) ? HALF_PI :\n computeViewAngle(dataPosition, dataPosition + axis);\n clipAngle = computeViewAngle(dataPosition, dataPosition + alignDir);\n\n axisAngle += (sin(axisAngle) < 0.0) ? PI : 0.0;\n clipAngle += (sin(clipAngle) < 0.0) ? PI : 0.0;\n\n flip = (dot(vec2(cos(axisAngle), sin(axisAngle)),\n vec2(sin(clipAngle),-cos(clipAngle))) > 0.0) ? 1.0 : 0.0;\n\n beta += applyAlignOption(clipAngle, flip * PI);\n }\n\n //Compute plane offset\n vec2 planeCoord = position.xy * pixelScale;\n\n mat2 planeXform = scale * mat2(\n cos(beta), sin(beta),\n -sin(beta), cos(beta)\n );\n\n vec2 viewOffset = 2.0 * planeXform * planeCoord / resolution;\n\n //Compute clip position\n vec3 clipPosition = project(dataPosition);\n\n //Apply text offset in clip coordinates\n clipPosition += vec3(viewOffset, 0.0);\n\n //Done\n gl_Position = vec4(clipPosition, 1.0);\n}"]) +var textFrag = glslify(["precision mediump float;\n#define GLSLIFY 1\nuniform vec4 color;\nvoid main() {\n gl_FragColor = color;\n}"]) +exports.text = function(gl) { + return createShader(gl, textVert, textFrag, null, [ + {name: 'position', type: 'vec3'} + ]) +} + +var bgVert = glslify(["#define GLSLIFY 1\nattribute vec3 position;\nattribute vec3 normal;\n\nuniform mat4 model, view, projection;\nuniform vec3 enable;\nuniform vec3 bounds[2];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n\n vec3 signAxis = sign(bounds[1] - bounds[0]);\n\n vec3 realNormal = signAxis * normal;\n\n if(dot(realNormal, enable) > 0.0) {\n vec3 minRange = min(bounds[0], bounds[1]);\n vec3 maxRange = max(bounds[0], bounds[1]);\n vec3 nPosition = mix(minRange, maxRange, 0.5 * (position + 1.0));\n gl_Position = projection * view * model * vec4(nPosition, 1.0);\n } else {\n gl_Position = vec4(0,0,0,0);\n }\n\n colorChannel = abs(realNormal);\n}"]) +var bgFrag = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nuniform vec4 colors[3];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n gl_FragColor = colorChannel.x * colors[0] +\n colorChannel.y * colors[1] +\n colorChannel.z * colors[2];\n}"]) +exports.bg = function(gl) { + return createShader(gl, bgVert, bgFrag, null, [ + {name: 'position', type: 'vec3'}, + {name: 'normal', type: 'vec3'} + ]) +} + +},{"gl-shader":288,"glslify":392}],227:[function(_dereq_,module,exports){ +(function (process){ +"use strict" + +module.exports = createTextSprites + +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var vectorizeText = _dereq_('vectorize-text') +var createShader = _dereq_('./shaders').text + +var globals = window || process.global || {} +var __TEXT_CACHE = globals.__TEXT_CACHE || {} +globals.__TEXT_CACHE = {} + +//Vertex buffer format for text is: +// +/// [x,y,z] = Spatial coordinate +// + +var VERTEX_SIZE = 3 +var VERTEX_STRIDE = VERTEX_SIZE * 4 + +function TextSprites( + gl, + shader, + buffer, + vao) { + this.gl = gl + this.shader = shader + this.buffer = buffer + this.vao = vao + this.tickOffset = + this.tickCount = + this.labelOffset = + this.labelCount = null +} + +var proto = TextSprites.prototype + +//Bind textures for rendering +var SHAPE = [0,0] +proto.bind = function(model, view, projection, pixelScale) { + this.vao.bind() + this.shader.bind() + var uniforms = this.shader.uniforms + uniforms.model = model + uniforms.view = view + uniforms.projection = projection + uniforms.pixelScale = pixelScale + SHAPE[0] = this.gl.drawingBufferWidth + SHAPE[1] = this.gl.drawingBufferHeight + this.shader.uniforms.resolution = SHAPE +} + +proto.unbind = function() { + this.vao.unbind() +} + +proto.update = function(bounds, labels, labelFont, ticks, tickFont) { + var gl = this.gl + var data = [] + + function addItem(t, text, font, size) { + var fontcache = __TEXT_CACHE[font] + if(!fontcache) { + fontcache = __TEXT_CACHE[font] = {} + } + var mesh = fontcache[text] + if(!mesh) { + mesh = fontcache[text] = tryVectorizeText(text, { + triangles: true, + font: font, + textAlign: 'center', + textBaseline: 'middle' + }) + } + var scale = (size || 12) / 12 + var positions = mesh.positions + var cells = mesh.cells + var lo = [ Infinity, Infinity] + var hi = [-Infinity,-Infinity] + for(var i=0, nc=cells.length; i=0; --j) { + var p = positions[c[j]] + data.push(scale*p[0], -scale*p[1], t) + } + } + } + + //Generate sprites for all 3 axes, store data in texture atlases + var tickOffset = [0,0,0] + var tickCount = [0,0,0] + var labelOffset = [0,0,0] + var labelCount = [0,0,0] + for(var d=0; d<3; ++d) { + + //Generate label + labelOffset[d] = (data.length/VERTEX_SIZE)|0 + addItem(0.5*(bounds[0][d]+bounds[1][d]), labels[d], labelFont) + labelCount[d] = ((data.length/VERTEX_SIZE)|0) - labelOffset[d] + + //Generate sprites for tick marks + tickOffset[d] = (data.length/VERTEX_SIZE)|0 + for(var i=0; i= 0) { + sigFigs = stepStr.length - u - 1 + } + var shift = Math.pow(10, sigFigs) + var x = Math.round(spacing * i * shift) + var xstr = x + "" + if(xstr.indexOf("e") >= 0) { + return xstr + } + var xi = x / shift, xf = x % shift + if(x < 0) { + xi = -Math.ceil(xi)|0 + xf = (-xf)|0 + } else { + xi = Math.floor(xi)|0 + xf = xf|0 + } + var xis = "" + xi + if(x < 0) { + xis = "-" + xis + } + if(sigFigs) { + var xs = "" + xf + while(xs.length < sigFigs) { + xs = "0" + xs + } + return xis + "." + xs + } else { + return xis + } +} + +function defaultTicks(bounds, tickSpacing) { + var array = [] + for(var d=0; d<3; ++d) { + var ticks = [] + var m = 0.5*(bounds[0][d]+bounds[1][d]) + for(var t=0; t*tickSpacing[d]<=bounds[1][d]; ++t) { + ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) + } + for(var t=-1; t*tickSpacing[d]>=bounds[0][d]; --t) { + ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) + } + array.push(ticks) + } + return array +} + +function ticksEqual(ticksA, ticksB) { + for(var i=0; i<3; ++i) { + if(ticksA[i].length !== ticksB[i].length) { + return false + } + for(var j=0; j len) { + throw new Error("gl-buffer: If resizing buffer, must not specify offset") + } + gl.bufferSubData(type, offset, data) + return len +} + +function makeScratchTypeArray(array, dtype) { + var res = pool.malloc(array.length, dtype) + var n = array.length + for(var i=0; i=0; --i) { + if(stride[i] !== n) { + return false + } + n *= shape[i] + } + return true +} + +proto.update = function(array, offset) { + if(typeof offset !== "number") { + offset = -1 + } + this.bind() + if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray + var dtype = array.dtype + if(SUPPORTED_TYPES.indexOf(dtype) < 0) { + dtype = "float32" + } + if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { + var ext = gl.getExtension('OES_element_index_uint') + if(ext && dtype !== "uint16") { + dtype = "uint32" + } else { + dtype = "uint16" + } + } + if(dtype === array.dtype && isPacked(array.shape, array.stride)) { + if(array.offset === 0 && array.data.length === array.shape[0]) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset) + } + } else { + var tmp = pool.malloc(array.size, dtype) + var ndt = ndarray(tmp, array.shape) + ops.assign(ndt, array) + if(offset < 0) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset) + } + pool.free(tmp) + } + } else if(Array.isArray(array)) { //Vanilla array + var t + if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { + t = makeScratchTypeArray(array, "uint16") + } else { + t = makeScratchTypeArray(array, "float32") + } + if(offset < 0) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset) + } + pool.free(t) + } else if(typeof array === "object" && typeof array.length === "number") { //Typed array + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset) + } else if(typeof array === "number" || array === undefined) { //Number/default + if(offset >= 0) { + throw new Error("gl-buffer: Cannot specify offset when resizing buffer") + } + array = array | 0 + if(array <= 0) { + array = 1 + } + this.gl.bufferData(this.type, array|0, this.usage) + this.length = array + } else { //Error, case should not happen + throw new Error("gl-buffer: Invalid data type") + } +} + +function createBuffer(gl, data, type, usage) { + type = type || gl.ARRAY_BUFFER + usage = usage || gl.DYNAMIC_DRAW + if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) { + throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER") + } + if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) { + throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW") + } + var handle = gl.createBuffer() + var result = new GLBuffer(gl, type, handle, 0, usage) + result.update(data) + return result +} + +module.exports = createBuffer + +},{"ndarray":433,"ndarray-ops":427,"typedarray-pool":522}],231:[function(_dereq_,module,exports){ +"use strict"; + +var V = _dereq_('gl-vec3'); +var V4 = _dereq_('gl-vec4'); + +var vec3 = function(x, y, z) { + var v = V.create(); + if (x !== undefined) { + V.set(v, x, y, z); + } + return v; +} + +var createPositionsForMeshgrid = function(meshgrid) { + var xs = meshgrid[0], ys = meshgrid[1], zs = meshgrid[2]; + var positions = []; + for (var z=0; z= v) { + return i-1; + } + } + return i; +}; + +var tmp = V.create(); +var tmp2 = V.create(); + +var clamp = function(v, min, max) { + return v < min ? min : (v > max ? max : v); +}; + +var sampleMeshgrid = function(point, array, meshgrid, clampOverflow) { + var x = point[0]; + var y = point[1]; + var z = point[2]; + + var w = meshgrid[0].length; + var h = meshgrid[1].length; + var d = meshgrid[2].length; + + // Find the index of the nearest smaller value in the meshgrid for each coordinate of (x,y,z). + // The nearest smaller value index for x is the index x0 such that + // meshgrid[0][x0] < x and for all x1 > x0, meshgrid[0][x1] >= x. + var x0 = findLastSmallerIndex(meshgrid[0], x); + var y0 = findLastSmallerIndex(meshgrid[1], y); + var z0 = findLastSmallerIndex(meshgrid[2], z); + + // Get the nearest larger meshgrid value indices. + // From the above "nearest smaller value", we know that + // meshgrid[0][x0] < x + // meshgrid[0][x0+1] >= x + var x1 = x0 + 1; + var y1 = y0 + 1; + var z1 = z0 + 1; + + if (clampOverflow) { + x0 = clamp(x0, 0, w-1); + x1 = clamp(x1, 0, w-1); + y0 = clamp(y0, 0, h-1); + y1 = clamp(y1, 0, h-1); + z0 = clamp(z0, 0, d-1); + z1 = clamp(z1, 0, d-1); + } + + // Reject points outside the meshgrid, return a zero vector. + if (x0 < 0 || y0 < 0 || z0 < 0 || x1 >= w || y1 >= h || z1 >= d) { + return V.create(); + } + + // Normalize point coordinates to 0..1 scaling factor between x0 and x1. + var xf = (x - meshgrid[0][x0]) / (meshgrid[0][x1] - meshgrid[0][x0]); + var yf = (y - meshgrid[1][y0]) / (meshgrid[1][y1] - meshgrid[1][y0]); + var zf = (z - meshgrid[2][z0]) / (meshgrid[2][z1] - meshgrid[2][z0]); + + if (xf < 0 || xf > 1 || isNaN(xf)) xf = 0; + if (yf < 0 || yf > 1 || isNaN(yf)) yf = 0; + if (zf < 0 || zf > 1 || isNaN(zf)) zf = 0; + + var z0off = z0*w*h; + var z1off = z1*w*h; + + var y0off = y0*w; + var y1off = y1*w; + + var x0off = x0; + var x1off = x1; + + // Sample data array around the (x,y,z) point. + // vZYX = array[zZoff + yYoff + xXoff] + var v000 = array[y0off + z0off + x0off]; + var v001 = array[y0off + z0off + x1off]; + var v010 = array[y1off + z0off + x0off]; + var v011 = array[y1off + z0off + x1off]; + var v100 = array[y0off + z1off + x0off]; + var v101 = array[y0off + z1off + x1off]; + var v110 = array[y1off + z1off + x0off]; + var v111 = array[y1off + z1off + x1off]; + + var result = V.create(); + + // Average samples according to distance to point. + V.lerp(result, v000, v001, xf); + V.lerp(tmp, v010, v011, xf); + V.lerp(result, result, tmp, yf); + V.lerp(tmp, v100, v101, xf); + V.lerp(tmp2, v110, v111, xf); + V.lerp(tmp, tmp, tmp2, yf); + V.lerp(result, result, tmp, zf); + + return result; +}; + +var getOrthogonalVector = function(dst, v) { + // Return up-vector for only-z vector. + if (v[0] === 0 && v[1] === 0) { + V.set(dst, 0, 1, 0); + } else { + // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0). + // From the above if-statement we have ||a|| > 0 U ||b|| > 0. + // Assign z = 0, x = -b, y = a: + // a*-b + b*a + c*0 = -ba + ba + 0 = 0 + V.set(dst, -v[1], v[0], 0); + } + return dst; +}; + +module.exports = function(vectorfield, bounds) { + var positions; + if (vectorfield.positions) { + positions = vectorfield.positions; + } else { + positions = createPositionsForMeshgrid(vectorfield.meshgrid); + } + var meshgrid = vectorfield.meshgrid; + var vectors = vectorfield.vectors; + var geo = { + positions: [], + vertexIntensity: [], + vertexIntensityBounds: vectorfield.vertexIntensityBounds, + vertexNormals: [], + vectors: [], + cells: [], + coneOffset: vectorfield.coneOffset, + colormap: vectorfield.colormap + }; + + if (vectorfield.positions.length === 0) { + if (bounds) { + bounds[0] = [0,0,0]; + bounds[1] = [0,0,0]; + } + return geo; + } + + // Compute bounding box for the dataset. + // Compute maximum velocity for the dataset to use for scaling the cones. + var maxNorm = 0; + var minX = 1/0, maxX = -1/0; + var minY = 1/0, maxY = -1/0; + var minZ = 1/0, maxZ = -1/0; + var p2 = null; + var u2 = null; + var positionVectors = []; + var vectorScale = 1/0; + for (var i = 0; i < positions.length; i++) { + var p = positions[i]; + minX = Math.min(p[0], minX); + maxX = Math.max(p[0], maxX); + minY = Math.min(p[1], minY); + maxY = Math.max(p[1], maxY); + minZ = Math.min(p[2], minZ); + maxZ = Math.max(p[2], maxZ); + var u; + if (meshgrid) { + u = sampleMeshgrid(p, vectors, meshgrid, true); + } else { + u = vectors[i]; + } + if (V.length(u) > maxNorm) { + maxNorm = V.length(u); + } + if (i) { + // Find vector scale [w/ units of time] using "successive" positions + // (not "adjacent" with would be O(n^2)), + // + // The vector scale corresponds to the minimum "time" to travel across two + // two adjacent positions at the average velocity of those two adjacent positions + vectorScale = Math.min(vectorScale, + 2 * V.distance(p2, p) / (V.length(u2) + V.length(u)) + ); + } + p2 = p; + u2 = u; + positionVectors.push(u); + } + var minV = [minX, minY, minZ]; + var maxV = [maxX, maxY, maxZ]; + if (bounds) { + bounds[0] = minV; + bounds[1] = maxV; + } + if (maxNorm === 0) { + maxNorm = 1; + } + + // Inverted max norm would map vector with norm maxNorm to 1 coord space units in length + var invertedMaxNorm = 1 / maxNorm; + + if (!isFinite(vectorScale) || isNaN(vectorScale)) { + vectorScale = 1.0; + } + geo.vectorScale = vectorScale; + + var nml = vec3(0,1,0); + + var coneScale = vectorfield.coneSize || 0.5; + + if (vectorfield.absoluteConeSize) { + coneScale = vectorfield.absoluteConeSize * invertedMaxNorm; + } + + geo.coneScale = coneScale; + + // Build the cone model. + for (var i = 0, j = 0; i < positions.length; i++) { + var p = positions[i]; + var x = p[0], y = p[1], z = p[2]; + var d = positionVectors[i]; + var intensity = V.length(d) * invertedMaxNorm; + for (var k = 0, l = 8; k < l; k++) { + geo.positions.push([x, y, z, j++]); + geo.positions.push([x, y, z, j++]); + geo.positions.push([x, y, z, j++]); + geo.positions.push([x, y, z, j++]); + geo.positions.push([x, y, z, j++]); + geo.positions.push([x, y, z, j++]); + + geo.vectors.push(d); + geo.vectors.push(d); + geo.vectors.push(d); + geo.vectors.push(d); + geo.vectors.push(d); + geo.vectors.push(d); + + geo.vertexIntensity.push(intensity, intensity, intensity); + geo.vertexIntensity.push(intensity, intensity, intensity); + + geo.vertexNormals.push(nml, nml, nml); + geo.vertexNormals.push(nml, nml, nml); + + var m = geo.positions.length; + geo.cells.push([m-6, m-5, m-4], [m-3, m-2, m-1]); + } + } + + return geo; +}; + +module.exports.createConeMesh = _dereq_('./lib/conemesh'); + +},{"./lib/conemesh":233,"gl-vec3":329,"gl-vec4":365}],232:[function(_dereq_,module,exports){ +'use strict' + +var barycentric = _dereq_('barycentric') +var closestPointToTriangle = _dereq_('polytope-closest-point/lib/closest_point_2d.js') + +module.exports = closestPointToPickLocation + +function xformMatrix(m, v) { + var out = [0,0,0,0] + for(var i=0; i<4; ++i) { + for(var j=0; j<4; ++j) { + out[j] += m[4*i + j] * v[i] + } + } + return out +} + +function projectVertex(v, model, view, projection, resolution) { + var p = xformMatrix(projection, + xformMatrix(view, + xformMatrix(model, [v[0], v[1], v[2], 1]))) + for(var i=0; i<3; ++i) { + p[i] /= p[3] + } + return [ 0.5 * resolution[0] * (1.0+p[0]), 0.5 * resolution[1] * (1.0-p[1]) ] +} + +function barycentricCoord(simplex, point) { + if(simplex.length === 2) { + var d0 = 0.0 + var d1 = 0.0 + for(var i=0; i<2; ++i) { + d0 += Math.pow(point[i] - simplex[0][i], 2) + d1 += Math.pow(point[i] - simplex[1][i], 2) + } + d0 = Math.sqrt(d0) + d1 = Math.sqrt(d1) + if(d0+d1 < 1e-6) { + return [1,0] + } + return [d1/(d0+d1),d0/(d1+d0)] + } else if(simplex.length === 3) { + var closestPoint = [0,0] + closestPointToTriangle(simplex[0], simplex[1], simplex[2], point, closestPoint) + return barycentric(simplex, closestPoint) + } + return [] +} + +function interpolate(simplex, weights) { + var result = [0,0,0] + for(var i=0; i 1.0001) { + return null + } + s += weights[i] + } + if(Math.abs(s - 1.0) > 0.001) { + return null + } + return [closestIndex, interpolate(simplex, weights), weights] +} +},{"barycentric":61,"polytope-closest-point/lib/closest_point_2d.js":464}],233:[function(_dereq_,module,exports){ +'use strict' + +var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small +var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; + +var createShader = _dereq_('gl-shader') +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createTexture = _dereq_('gl-texture2d') +var normals = _dereq_('normals') +var multiply = _dereq_('gl-mat4/multiply') +var invert = _dereq_('gl-mat4/invert') +var ndarray = _dereq_('ndarray') +var colormap = _dereq_('colormap') +var getContour = _dereq_('simplicial-complex-contour') +var pool = _dereq_('typedarray-pool') +var shaders = _dereq_('./shaders') +var closestPoint = _dereq_('./closest-point') + +var meshShader = shaders.meshShader +var pickShader = shaders.pickShader + +var identityMatrix = [ + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +function SimplicialMesh(gl + , texture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleVectors + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) { + + this.gl = gl + this.cells = [] + this.positions = [] + this.intensity = [] + this.texture = texture + this.dirty = true + + this.triShader = triShader + this.lineShader = lineShader + this.pointShader = pointShader + this.pickShader = pickShader + this.pointPickShader = pointPickShader + this.contourShader = contourShader + + this.trianglePositions = trianglePositions + this.triangleVectors = triangleVectors + this.triangleColors = triangleColors + this.triangleNormals = triangleNormals + this.triangleUVs = triangleUVs + this.triangleIds = triangleIds + this.triangleVAO = triangleVAO + this.triangleCount = 0 + + this.lineWidth = 1 + this.edgePositions = edgePositions + this.edgeColors = edgeColors + this.edgeUVs = edgeUVs + this.edgeIds = edgeIds + this.edgeVAO = edgeVAO + this.edgeCount = 0 + + this.pointPositions = pointPositions + this.pointColors = pointColors + this.pointUVs = pointUVs + this.pointSizes = pointSizes + this.pointIds = pointIds + this.pointVAO = pointVAO + this.pointCount = 0 + + this.contourLineWidth = 1 + this.contourPositions = contourPositions + this.contourVAO = contourVAO + this.contourCount = 0 + this.contourColor = [0,0,0] + this.contourEnable = true + + this.pickId = 1 + this.bounds = [ + [ Infinity, Infinity, Infinity], + [-Infinity,-Infinity,-Infinity] ] + this.clipBounds = [ + [-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity] ] + + this.lightPosition = [1e5, 1e5, 0] + this.ambientLight = 0.8 + this.diffuseLight = 0.8 + this.specularLight = 2.0 + this.roughness = 0.5 + this.fresnel = 1.5 + + this.opacity = 1.0 + + this.coneScale = 2.0 + this.vectorScale = 1.0 + this.coneOffset = 1.0 / 4.0; + + this._model = identityMatrix + this._view = identityMatrix + this._projection = identityMatrix + this._resolution = [1,1] +} + +var proto = SimplicialMesh.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 +} + +proto.isTransparent = function() { + return this.opacity < 1 +} + +proto.pickSlots = 1 + +proto.setPickBase = function(id) { + this.pickId = id +} + +function genColormap(param) { + var colors = colormap({ + colormap: param + , nshades: 256 + , format: 'rgba' + }) + + var result = new Uint8Array(256*4) + for(var i=0; i<256; ++i) { + var c = colors[i] + for(var j=0; j<3; ++j) { + result[4*i+j] = c[j] + } + result[4*i+3] = c[3]*255 + } + + return ndarray(result, [256,256,4], [4,0,1]) +} + +function unpackIntensity(cells, numVerts, cellIntensity) { + var result = new Array(numVerts) + for(var i=0; i 0) { + var shader = this.triShader + shader.bind() + shader.uniforms = uniforms + + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0 && this.lineWidth > 0) { + var shader = this.lineShader + shader.bind() + shader.uniforms = uniforms + + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } + + if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { + var shader = this.contourShader + shader.bind() + shader.uniforms = uniforms + + this.contourVAO.bind() + gl.drawArrays(gl.LINES, 0, this.contourCount) + this.contourVAO.unbind() + } +} + +proto.drawPick = function(params) { + params = params || {} + + var gl = this.gl + + var model = params.model || identityMatrix + var view = params.view || identityMatrix + var projection = params.projection || identityMatrix + + var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] + for(var i=0; i<3; ++i) { + clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) + clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) + } + + //Save camera parameters + this._model = [].slice.call(model) + this._view = [].slice.call(view) + this._projection = [].slice.call(projection) + this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] + + var uniforms = { + model: model, + view: view, + projection: projection, + clipBounds: clipBounds, + + vectorScale: this.vectorScale, + coneScale: this.coneScale, + coneOffset: this.coneOffset, + + pickId: this.pickId / 255.0, + } + + var shader = this.pickShader + shader.bind() + shader.uniforms = uniforms + + if(this.triangleCount > 0) { + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0) { + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointPickShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } +} + + +proto.pick = function(pickData) { + if(!pickData) { + return null + } + if(pickData.id !== this.pickId) { + return null + } + + var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] + var cell = this.cells[cellId] + var pos = this.positions[cell[1]].slice(0, 3) + + return { + // corresponding to input indices + index: Math.floor(cell[1] / 48), + position: pos, + dataCoordinate: pos + } +} + + +proto.dispose = function() { + this.texture.dispose() + + this.triShader.dispose() + // this.lineShader.dispose() + // this.pointShader.dispose() + this.pickShader.dispose() + // this.pointPickShader.dispose() + + this.triangleVAO.dispose() + this.trianglePositions.dispose() + this.triangleVectors.dispose() + this.triangleColors.dispose() + this.triangleUVs.dispose() + this.triangleNormals.dispose() + this.triangleIds.dispose() + + this.edgeVAO.dispose() + this.edgePositions.dispose() + this.edgeColors.dispose() + this.edgeUVs.dispose() + this.edgeIds.dispose() + + this.pointVAO.dispose() + this.pointPositions.dispose() + this.pointColors.dispose() + this.pointUVs.dispose() + this.pointSizes.dispose() + this.pointIds.dispose() + + this.contourVAO.dispose() + this.contourPositions.dispose() + // this.contourShader.dispose() +} + +function createMeshShader(gl) { + // need to pass meshShader attributes manually, + // to make this work on etpinard's Ubuntu Thinkpad + var shader = createShader(gl, meshShader.vertex, meshShader.fragment, null, meshShader.attributes) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + shader.attributes.vector.location = 5 + return shader +} + +function createWireShader(gl) { + var shader = createShader(gl, wireShader.vertex, wireShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + return shader +} + +function createPointShader(gl) { + var shader = createShader(gl, pointShader.vertex, pointShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + shader.attributes.pointSize.location = 4 + return shader +} + +function createPickShader(gl) { + var shader = createShader(gl, pickShader.vertex, pickShader.fragment, null, pickShader.attributes) + shader.attributes.position.location = 0 + shader.attributes.id.location = 1 + shader.attributes.vector.location = 5 + return shader +} + +function createPointPickShader(gl) { + var shader = createShader(gl, pointPickShader.vertex, pointPickShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.id.location = 1 + shader.attributes.pointSize.location = 4 + return shader +} + +function createContourShader(gl) { + var shader = createShader(gl, contourShader.vertex, contourShader.fragment) + shader.attributes.position.location = 0 + return shader +} + +function createSimplicialMesh(gl, params) { + if (arguments.length === 1) { + params = gl; + gl = params.gl; + } + + var triShader = params.triShader || createMeshShader(gl) + var lineShader = null; //createWireShader(gl) + var pointShader = null; //createPointShader(gl) + var pickShader = createPickShader(gl) + var pointPickShader = null; //createPointPickShader(gl) + var contourShader = null; //createContourShader(gl) + + var meshTexture = createTexture(gl, + ndarray(new Uint8Array([255,255,255,255]), [1,1,4])) + meshTexture.generateMipmap() + meshTexture.minFilter = gl.LINEAR_MIPMAP_LINEAR + meshTexture.magFilter = gl.LINEAR + + var trianglePositions = createBuffer(gl) + var triangleVectors = createBuffer(gl) + var triangleColors = createBuffer(gl) + var triangleUVs = createBuffer(gl) + var triangleNormals = createBuffer(gl) + var triangleIds = createBuffer(gl) + var triangleVAO = createVAO(gl, [ + { buffer: trianglePositions, + type: gl.FLOAT, + size: 4 + }, + { buffer: triangleIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: triangleColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: triangleUVs, + type: gl.FLOAT, + size: 2 + }, + { buffer: triangleNormals, + type: gl.FLOAT, + size: 3 + }, + { buffer: triangleVectors, + type: gl.FLOAT, + size: 3 + } + ]) + + var edgePositions = createBuffer(gl) + var edgeColors = createBuffer(gl) + var edgeUVs = createBuffer(gl) + var edgeIds = createBuffer(gl) + var edgeVAO = createVAO(gl, [ + { buffer: edgePositions, + type: gl.FLOAT, + size: 3 + }, + { buffer: edgeIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: edgeColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: edgeUVs, + type: gl.FLOAT, + size: 2 + } + ]) + + var pointPositions = createBuffer(gl) + var pointColors = createBuffer(gl) + var pointUVs = createBuffer(gl) + var pointSizes = createBuffer(gl) + var pointIds = createBuffer(gl) + var pointVAO = createVAO(gl, [ + { buffer: pointPositions, + type: gl.FLOAT, + size: 3 + }, + { buffer: pointIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: pointColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: pointUVs, + type: gl.FLOAT, + size: 2 + }, + { buffer: pointSizes, + type: gl.FLOAT, + size: 1 + } + ]) + + var contourPositions = createBuffer(gl) + var contourVAO = createVAO(gl, [ + { buffer: contourPositions, + type: gl.FLOAT, + size: 3 + }]) + + var mesh = new SimplicialMesh(gl + , meshTexture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleVectors + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) + + mesh.update(params) + + return mesh +} + +module.exports = createSimplicialMesh + +},{"./closest-point":232,"./shaders":234,"colormap":114,"gl-buffer":230,"gl-mat4/invert":254,"gl-mat4/multiply":256,"gl-shader":288,"gl-texture2d":305,"gl-vao":310,"ndarray":433,"normals":436,"simplicial-complex-contour":494,"typedarray-pool":522}],234:[function(_dereq_,module,exports){ +var glslify = _dereq_('glslify') + +var triVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nfloat inverse(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float index, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n index = mod(index, segmentCount * 6.0);\n\n float segment = floor(index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex == 3.0) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n // angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)\n float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex <= 2.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float vectorScale;\nuniform float coneScale;\n\nuniform float coneOffset;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n normal = normalize(normal * inverse(mat3(model)));\n\n // vec4 m_position = model * vec4(conePosition, 1.0);\n vec4 t_position = view * conePosition;\n gl_Position = projection * t_position;\n f_color = color; //vec4(position.w, color.r, 0, 0);\n f_normal = normal;\n f_data = conePosition.xyz;\n f_position = position.xyz;\n f_eyeDirection = eyePosition - conePosition.xyz;\n f_lightDirection = lightPosition - conePosition.xyz;\n f_uv = uv;\n}\n"]) +var triFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}"]) +var pickVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float index, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n index = mod(index, segmentCount * 6.0);\n\n float segment = floor(index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex == 3.0) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n // angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)\n float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex <= 2.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nuniform float vectorScale;\nuniform float coneScale;\nuniform float coneOffset;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n gl_Position = projection * view * conePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]) +var pickFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) + +exports.meshShader = { + vertex: triVertSrc, + fragment: triFragSrc, + attributes: [ + {name: 'position', type: 'vec4'}, + {name: 'normal', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'}, + {name: 'vector', type: 'vec3'} + ] +} +exports.pickShader = { + vertex: pickVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec4'}, + {name: 'id', type: 'vec4'}, + {name: 'vector', type: 'vec3'} + ] +} + +},{"glslify":392}],235:[function(_dereq_,module,exports){ +module.exports = { + 0: 'NONE', + 1: 'ONE', + 2: 'LINE_LOOP', + 3: 'LINE_STRIP', + 4: 'TRIANGLES', + 5: 'TRIANGLE_STRIP', + 6: 'TRIANGLE_FAN', + 256: 'DEPTH_BUFFER_BIT', + 512: 'NEVER', + 513: 'LESS', + 514: 'EQUAL', + 515: 'LEQUAL', + 516: 'GREATER', + 517: 'NOTEQUAL', + 518: 'GEQUAL', + 519: 'ALWAYS', + 768: 'SRC_COLOR', + 769: 'ONE_MINUS_SRC_COLOR', + 770: 'SRC_ALPHA', + 771: 'ONE_MINUS_SRC_ALPHA', + 772: 'DST_ALPHA', + 773: 'ONE_MINUS_DST_ALPHA', + 774: 'DST_COLOR', + 775: 'ONE_MINUS_DST_COLOR', + 776: 'SRC_ALPHA_SATURATE', + 1024: 'STENCIL_BUFFER_BIT', + 1028: 'FRONT', + 1029: 'BACK', + 1032: 'FRONT_AND_BACK', + 1280: 'INVALID_ENUM', + 1281: 'INVALID_VALUE', + 1282: 'INVALID_OPERATION', + 1285: 'OUT_OF_MEMORY', + 1286: 'INVALID_FRAMEBUFFER_OPERATION', + 2304: 'CW', + 2305: 'CCW', + 2849: 'LINE_WIDTH', + 2884: 'CULL_FACE', + 2885: 'CULL_FACE_MODE', + 2886: 'FRONT_FACE', + 2928: 'DEPTH_RANGE', + 2929: 'DEPTH_TEST', + 2930: 'DEPTH_WRITEMASK', + 2931: 'DEPTH_CLEAR_VALUE', + 2932: 'DEPTH_FUNC', + 2960: 'STENCIL_TEST', + 2961: 'STENCIL_CLEAR_VALUE', + 2962: 'STENCIL_FUNC', + 2963: 'STENCIL_VALUE_MASK', + 2964: 'STENCIL_FAIL', + 2965: 'STENCIL_PASS_DEPTH_FAIL', + 2966: 'STENCIL_PASS_DEPTH_PASS', + 2967: 'STENCIL_REF', + 2968: 'STENCIL_WRITEMASK', + 2978: 'VIEWPORT', + 3024: 'DITHER', + 3042: 'BLEND', + 3088: 'SCISSOR_BOX', + 3089: 'SCISSOR_TEST', + 3106: 'COLOR_CLEAR_VALUE', + 3107: 'COLOR_WRITEMASK', + 3317: 'UNPACK_ALIGNMENT', + 3333: 'PACK_ALIGNMENT', + 3379: 'MAX_TEXTURE_SIZE', + 3386: 'MAX_VIEWPORT_DIMS', + 3408: 'SUBPIXEL_BITS', + 3410: 'RED_BITS', + 3411: 'GREEN_BITS', + 3412: 'BLUE_BITS', + 3413: 'ALPHA_BITS', + 3414: 'DEPTH_BITS', + 3415: 'STENCIL_BITS', + 3553: 'TEXTURE_2D', + 4352: 'DONT_CARE', + 4353: 'FASTEST', + 4354: 'NICEST', + 5120: 'BYTE', + 5121: 'UNSIGNED_BYTE', + 5122: 'SHORT', + 5123: 'UNSIGNED_SHORT', + 5124: 'INT', + 5125: 'UNSIGNED_INT', + 5126: 'FLOAT', + 5386: 'INVERT', + 5890: 'TEXTURE', + 6401: 'STENCIL_INDEX', + 6402: 'DEPTH_COMPONENT', + 6406: 'ALPHA', + 6407: 'RGB', + 6408: 'RGBA', + 6409: 'LUMINANCE', + 6410: 'LUMINANCE_ALPHA', + 7680: 'KEEP', + 7681: 'REPLACE', + 7682: 'INCR', + 7683: 'DECR', + 7936: 'VENDOR', + 7937: 'RENDERER', + 7938: 'VERSION', + 9728: 'NEAREST', + 9729: 'LINEAR', + 9984: 'NEAREST_MIPMAP_NEAREST', + 9985: 'LINEAR_MIPMAP_NEAREST', + 9986: 'NEAREST_MIPMAP_LINEAR', + 9987: 'LINEAR_MIPMAP_LINEAR', + 10240: 'TEXTURE_MAG_FILTER', + 10241: 'TEXTURE_MIN_FILTER', + 10242: 'TEXTURE_WRAP_S', + 10243: 'TEXTURE_WRAP_T', + 10497: 'REPEAT', + 10752: 'POLYGON_OFFSET_UNITS', + 16384: 'COLOR_BUFFER_BIT', + 32769: 'CONSTANT_COLOR', + 32770: 'ONE_MINUS_CONSTANT_COLOR', + 32771: 'CONSTANT_ALPHA', + 32772: 'ONE_MINUS_CONSTANT_ALPHA', + 32773: 'BLEND_COLOR', + 32774: 'FUNC_ADD', + 32777: 'BLEND_EQUATION_RGB', + 32778: 'FUNC_SUBTRACT', + 32779: 'FUNC_REVERSE_SUBTRACT', + 32819: 'UNSIGNED_SHORT_4_4_4_4', + 32820: 'UNSIGNED_SHORT_5_5_5_1', + 32823: 'POLYGON_OFFSET_FILL', + 32824: 'POLYGON_OFFSET_FACTOR', + 32854: 'RGBA4', + 32855: 'RGB5_A1', + 32873: 'TEXTURE_BINDING_2D', + 32926: 'SAMPLE_ALPHA_TO_COVERAGE', + 32928: 'SAMPLE_COVERAGE', + 32936: 'SAMPLE_BUFFERS', + 32937: 'SAMPLES', + 32938: 'SAMPLE_COVERAGE_VALUE', + 32939: 'SAMPLE_COVERAGE_INVERT', + 32968: 'BLEND_DST_RGB', + 32969: 'BLEND_SRC_RGB', + 32970: 'BLEND_DST_ALPHA', + 32971: 'BLEND_SRC_ALPHA', + 33071: 'CLAMP_TO_EDGE', + 33170: 'GENERATE_MIPMAP_HINT', + 33189: 'DEPTH_COMPONENT16', + 33306: 'DEPTH_STENCIL_ATTACHMENT', + 33635: 'UNSIGNED_SHORT_5_6_5', + 33648: 'MIRRORED_REPEAT', + 33901: 'ALIASED_POINT_SIZE_RANGE', + 33902: 'ALIASED_LINE_WIDTH_RANGE', + 33984: 'TEXTURE0', + 33985: 'TEXTURE1', + 33986: 'TEXTURE2', + 33987: 'TEXTURE3', + 33988: 'TEXTURE4', + 33989: 'TEXTURE5', + 33990: 'TEXTURE6', + 33991: 'TEXTURE7', + 33992: 'TEXTURE8', + 33993: 'TEXTURE9', + 33994: 'TEXTURE10', + 33995: 'TEXTURE11', + 33996: 'TEXTURE12', + 33997: 'TEXTURE13', + 33998: 'TEXTURE14', + 33999: 'TEXTURE15', + 34000: 'TEXTURE16', + 34001: 'TEXTURE17', + 34002: 'TEXTURE18', + 34003: 'TEXTURE19', + 34004: 'TEXTURE20', + 34005: 'TEXTURE21', + 34006: 'TEXTURE22', + 34007: 'TEXTURE23', + 34008: 'TEXTURE24', + 34009: 'TEXTURE25', + 34010: 'TEXTURE26', + 34011: 'TEXTURE27', + 34012: 'TEXTURE28', + 34013: 'TEXTURE29', + 34014: 'TEXTURE30', + 34015: 'TEXTURE31', + 34016: 'ACTIVE_TEXTURE', + 34024: 'MAX_RENDERBUFFER_SIZE', + 34041: 'DEPTH_STENCIL', + 34055: 'INCR_WRAP', + 34056: 'DECR_WRAP', + 34067: 'TEXTURE_CUBE_MAP', + 34068: 'TEXTURE_BINDING_CUBE_MAP', + 34069: 'TEXTURE_CUBE_MAP_POSITIVE_X', + 34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X', + 34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y', + 34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y', + 34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z', + 34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z', + 34076: 'MAX_CUBE_MAP_TEXTURE_SIZE', + 34338: 'VERTEX_ATTRIB_ARRAY_ENABLED', + 34339: 'VERTEX_ATTRIB_ARRAY_SIZE', + 34340: 'VERTEX_ATTRIB_ARRAY_STRIDE', + 34341: 'VERTEX_ATTRIB_ARRAY_TYPE', + 34342: 'CURRENT_VERTEX_ATTRIB', + 34373: 'VERTEX_ATTRIB_ARRAY_POINTER', + 34466: 'NUM_COMPRESSED_TEXTURE_FORMATS', + 34467: 'COMPRESSED_TEXTURE_FORMATS', + 34660: 'BUFFER_SIZE', + 34661: 'BUFFER_USAGE', + 34816: 'STENCIL_BACK_FUNC', + 34817: 'STENCIL_BACK_FAIL', + 34818: 'STENCIL_BACK_PASS_DEPTH_FAIL', + 34819: 'STENCIL_BACK_PASS_DEPTH_PASS', + 34877: 'BLEND_EQUATION_ALPHA', + 34921: 'MAX_VERTEX_ATTRIBS', + 34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED', + 34930: 'MAX_TEXTURE_IMAGE_UNITS', + 34962: 'ARRAY_BUFFER', + 34963: 'ELEMENT_ARRAY_BUFFER', + 34964: 'ARRAY_BUFFER_BINDING', + 34965: 'ELEMENT_ARRAY_BUFFER_BINDING', + 34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING', + 35040: 'STREAM_DRAW', + 35044: 'STATIC_DRAW', + 35048: 'DYNAMIC_DRAW', + 35632: 'FRAGMENT_SHADER', + 35633: 'VERTEX_SHADER', + 35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS', + 35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', + 35663: 'SHADER_TYPE', + 35664: 'FLOAT_VEC2', + 35665: 'FLOAT_VEC3', + 35666: 'FLOAT_VEC4', + 35667: 'INT_VEC2', + 35668: 'INT_VEC3', + 35669: 'INT_VEC4', + 35670: 'BOOL', + 35671: 'BOOL_VEC2', + 35672: 'BOOL_VEC3', + 35673: 'BOOL_VEC4', + 35674: 'FLOAT_MAT2', + 35675: 'FLOAT_MAT3', + 35676: 'FLOAT_MAT4', + 35678: 'SAMPLER_2D', + 35680: 'SAMPLER_CUBE', + 35712: 'DELETE_STATUS', + 35713: 'COMPILE_STATUS', + 35714: 'LINK_STATUS', + 35715: 'VALIDATE_STATUS', + 35716: 'INFO_LOG_LENGTH', + 35717: 'ATTACHED_SHADERS', + 35718: 'ACTIVE_UNIFORMS', + 35719: 'ACTIVE_UNIFORM_MAX_LENGTH', + 35720: 'SHADER_SOURCE_LENGTH', + 35721: 'ACTIVE_ATTRIBUTES', + 35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH', + 35724: 'SHADING_LANGUAGE_VERSION', + 35725: 'CURRENT_PROGRAM', + 36003: 'STENCIL_BACK_REF', + 36004: 'STENCIL_BACK_VALUE_MASK', + 36005: 'STENCIL_BACK_WRITEMASK', + 36006: 'FRAMEBUFFER_BINDING', + 36007: 'RENDERBUFFER_BINDING', + 36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', + 36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', + 36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', + 36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE', + 36053: 'FRAMEBUFFER_COMPLETE', + 36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT', + 36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT', + 36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS', + 36061: 'FRAMEBUFFER_UNSUPPORTED', + 36064: 'COLOR_ATTACHMENT0', + 36096: 'DEPTH_ATTACHMENT', + 36128: 'STENCIL_ATTACHMENT', + 36160: 'FRAMEBUFFER', + 36161: 'RENDERBUFFER', + 36162: 'RENDERBUFFER_WIDTH', + 36163: 'RENDERBUFFER_HEIGHT', + 36164: 'RENDERBUFFER_INTERNAL_FORMAT', + 36168: 'STENCIL_INDEX8', + 36176: 'RENDERBUFFER_RED_SIZE', + 36177: 'RENDERBUFFER_GREEN_SIZE', + 36178: 'RENDERBUFFER_BLUE_SIZE', + 36179: 'RENDERBUFFER_ALPHA_SIZE', + 36180: 'RENDERBUFFER_DEPTH_SIZE', + 36181: 'RENDERBUFFER_STENCIL_SIZE', + 36194: 'RGB565', + 36336: 'LOW_FLOAT', + 36337: 'MEDIUM_FLOAT', + 36338: 'HIGH_FLOAT', + 36339: 'LOW_INT', + 36340: 'MEDIUM_INT', + 36341: 'HIGH_INT', + 36346: 'SHADER_COMPILER', + 36347: 'MAX_VERTEX_UNIFORM_VECTORS', + 36348: 'MAX_VARYING_VECTORS', + 36349: 'MAX_FRAGMENT_UNIFORM_VECTORS', + 37440: 'UNPACK_FLIP_Y_WEBGL', + 37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL', + 37442: 'CONTEXT_LOST_WEBGL', + 37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL', + 37444: 'BROWSER_DEFAULT_WEBGL' +} + +},{}],236:[function(_dereq_,module,exports){ +var gl10 = _dereq_('./1.0/numbers') + +module.exports = function lookupConstant (number) { + return gl10[number] +} + +},{"./1.0/numbers":235}],237:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createErrorBars + +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createShader = _dereq_('./shaders/index') + +var IDENTITY = [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +function ErrorBars(gl, buffer, vao, shader) { + this.gl = gl + this.shader = shader + this.buffer = buffer + this.vao = vao + this.pixelRatio = 1 + this.bounds = [[ Infinity, Infinity, Infinity], [-Infinity,-Infinity,-Infinity]] + this.clipBounds = [[-Infinity,-Infinity,-Infinity], [ Infinity, Infinity, Infinity]] + this.lineWidth = [1,1,1] + this.capSize = [10,10,10] + this.lineCount = [0,0,0] + this.lineOffset = [0,0,0] + this.opacity = 1 +} + +var proto = ErrorBars.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 +} + +proto.isTransparent = function() { + return this.opacity < 1 +} + +proto.drawTransparent = proto.draw = function(cameraParams) { + var gl = this.gl + var uniforms = this.shader.uniforms + + this.shader.bind() + var view = uniforms.view = cameraParams.view || IDENTITY + var projection = uniforms.projection = cameraParams.projection || IDENTITY + uniforms.model = cameraParams.model || IDENTITY + uniforms.clipBounds = this.clipBounds + uniforms.opacity = this.opacity + + + var cx = view[12] + var cy = view[13] + var cz = view[14] + var cw = view[15] + var pixelScaleF = this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight + + this.vao.bind() + for(var i=0; i<3; ++i) { + gl.lineWidth(this.lineWidth[i]) + uniforms.capSize = this.capSize[i] * pixelScaleF + if (this.lineCount[i]) { + gl.drawArrays(gl.LINES, this.lineOffset[i], this.lineCount[i]) + } + } + this.vao.unbind() +} + +function updateBounds(bounds, point) { + for(var i=0; i<3; ++i) { + bounds[0][i] = Math.min(bounds[0][i], point[i]) + bounds[1][i] = Math.max(bounds[1][i], point[i]) + } +} + +var FACE_TABLE = (function(){ + var table = new Array(3) + for(var d=0; d<3; ++d) { + var row = [] + for(var j=1; j<=2; ++j) { + for(var s=-1; s<=1; s+=2) { + var u = (j+d) % 3 + var y = [0,0,0] + y[u] = s + row.push(y) + } + } + table[d] = row + } + return table +})() + + +function emitFace(verts, x, c, d) { + var offsets = FACE_TABLE[d] + for(var i=0; i 0) { + var x = p.slice() + x[j] += e[1][j] + verts.push(p[0], p[1], p[2], + c[0], c[1], c[2], c[3], + 0, 0, 0, + x[0], x[1], x[2], + c[0], c[1], c[2], c[3], + 0, 0, 0) + updateBounds(this.bounds, x) + vertexCount += 2 + emitFace(verts, x, c, j) + } + } + this.lineCount[j] = vertexCount - this.lineOffset[j] + } + this.buffer.update(verts) + } +} + +proto.dispose = function() { + this.shader.dispose() + this.buffer.dispose() + this.vao.dispose() +} + +function createErrorBars(options) { + var gl = options.gl + var buffer = createBuffer(gl) + var vao = createVAO(gl, [ + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 0, + stride: 40 + }, + { + buffer: buffer, + type: gl.FLOAT, + size: 4, + offset: 12, + stride: 40 + }, + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 28, + stride: 40 + } + ]) + + var shader = createShader(gl) + shader.attributes.position.location = 0 + shader.attributes.color.location = 1 + shader.attributes.offset.location = 2 + + var result = new ErrorBars(gl, buffer, vao, shader) + result.update(options) + return result +} + +},{"./shaders/index":238,"gl-buffer":230,"gl-vao":310}],238:[function(_dereq_,module,exports){ +'use strict' + +var glslify = _dereq_('glslify') +var createShader = _dereq_('gl-shader') + +var vertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}"]) +var fragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], fragPosition)) discard;\n\n gl_FragColor = opacity * fragColor;\n}"]) + +module.exports = function(gl) { + return createShader(gl, vertSrc, fragSrc, null, [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'offset', type: 'vec3'} + ]) +} + +},{"gl-shader":288,"glslify":392}],239:[function(_dereq_,module,exports){ +'use strict' + +var createTexture = _dereq_('gl-texture2d') + +module.exports = createFBO + +var colorAttachmentArrays = null +var FRAMEBUFFER_UNSUPPORTED +var FRAMEBUFFER_INCOMPLETE_ATTACHMENT +var FRAMEBUFFER_INCOMPLETE_DIMENSIONS +var FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT + +function saveFBOState(gl) { + var fbo = gl.getParameter(gl.FRAMEBUFFER_BINDING) + var rbo = gl.getParameter(gl.RENDERBUFFER_BINDING) + var tex = gl.getParameter(gl.TEXTURE_BINDING_2D) + return [fbo, rbo, tex] +} + +function restoreFBOState(gl, data) { + gl.bindFramebuffer(gl.FRAMEBUFFER, data[0]) + gl.bindRenderbuffer(gl.RENDERBUFFER, data[1]) + gl.bindTexture(gl.TEXTURE_2D, data[2]) +} + +function lazyInitColorAttachments(gl, ext) { + var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL) + colorAttachmentArrays = new Array(maxColorAttachments + 1) + for(var i=0; i<=maxColorAttachments; ++i) { + var x = new Array(maxColorAttachments) + for(var j=0; j 1) { + ext.drawBuffersWEBGL(colorAttachmentArrays[numColors]) + } + + //Allocate depth/stencil buffers + var WEBGL_depth_texture = gl.getExtension('WEBGL_depth_texture') + if(WEBGL_depth_texture) { + if(useStencil) { + fbo.depth = initTexture(gl, width, height, + WEBGL_depth_texture.UNSIGNED_INT_24_8_WEBGL, + gl.DEPTH_STENCIL, + gl.DEPTH_STENCIL_ATTACHMENT) + } else if(useDepth) { + fbo.depth = initTexture(gl, width, height, + gl.UNSIGNED_SHORT, + gl.DEPTH_COMPONENT, + gl.DEPTH_ATTACHMENT) + } + } else { + if(useDepth && useStencil) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT) + } else if(useDepth) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) + } else if(useStencil) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.STENCIL_INDEX, gl.STENCIL_ATTACHMENT) + } + } + + //Check frame buffer state + var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER) + if(status !== gl.FRAMEBUFFER_COMPLETE) { + + //Release all partially allocated resources + fbo._destroyed = true + + //Release all resources + gl.bindFramebuffer(gl.FRAMEBUFFER, null) + gl.deleteFramebuffer(fbo.handle) + fbo.handle = null + if(fbo.depth) { + fbo.depth.dispose() + fbo.depth = null + } + if(fbo._depth_rb) { + gl.deleteRenderbuffer(fbo._depth_rb) + fbo._depth_rb = null + } + for(var i=0; i maxFBOSize || + h < 0 || h > maxFBOSize) { + throw new Error('gl-fbo: Can\'t resize FBO, invalid dimensions') + } + + //Update shape + fbo._shape[0] = w + fbo._shape[1] = h + + //Save framebuffer state + var state = saveFBOState(gl) + + //Resize framebuffer attachments + for(var i=0; i maxFBOSize || height < 0 || height > maxFBOSize) { + throw new Error('gl-fbo: Parameters are too large for FBO') + } + + //Handle each option type + options = options || {} + + //Figure out number of color buffers to use + var numColors = 1 + if('color' in options) { + numColors = Math.max(options.color|0, 0) + if(numColors < 0) { + throw new Error('gl-fbo: Must specify a nonnegative number of colors') + } + if(numColors > 1) { + //Check if multiple render targets supported + if(!WEBGL_draw_buffers) { + throw new Error('gl-fbo: Multiple draw buffer extension not supported') + } else if(numColors > gl.getParameter(WEBGL_draw_buffers.MAX_COLOR_ATTACHMENTS_WEBGL)) { + throw new Error('gl-fbo: Context does not support ' + numColors + ' draw buffers') + } + } + } + + //Determine whether to use floating point textures + var colorType = gl.UNSIGNED_BYTE + var OES_texture_float = gl.getExtension('OES_texture_float') + if(options.float && numColors > 0) { + if(!OES_texture_float) { + throw new Error('gl-fbo: Context does not support floating point textures') + } + colorType = gl.FLOAT + } else if(options.preferFloat && numColors > 0) { + if(OES_texture_float) { + colorType = gl.FLOAT + } + } + + //Check if we should use depth buffer + var useDepth = true + if('depth' in options) { + useDepth = !!options.depth + } + + //Check if we should use a stencil buffer + var useStencil = false + if('stencil' in options) { + useStencil = !!options.stencil + } + + return new Framebuffer( + gl, + width, + height, + colorType, + numColors, + useDepth, + useStencil, + WEBGL_draw_buffers) +} + +},{"gl-texture2d":305}],240:[function(_dereq_,module,exports){ + +var sprintf = _dereq_('sprintf-js').sprintf; +var glConstants = _dereq_('gl-constants/lookup'); +var shaderName = _dereq_('glsl-shader-name'); +var addLineNumbers = _dereq_('add-line-numbers'); + +module.exports = formatCompilerError; + +function formatCompilerError(errLog, src, type) { + "use strict"; + + var name = shaderName(src) || 'of unknown name (see npm glsl-shader-name)'; + + var typeName = 'unknown type'; + if (type !== undefined) { + typeName = type === glConstants.FRAGMENT_SHADER ? 'fragment' : 'vertex' + } + + var longForm = sprintf('Error compiling %s shader %s:\n', typeName, name); + var shortForm = sprintf("%s%s", longForm, errLog); + + var errorStrings = errLog.split('\n'); + var errors = {}; + + for (var i = 0; i < errorStrings.length; i++) { + var errorString = errorStrings[i]; + if (errorString === '' || errorString === "\0") continue; + var lineNo = parseInt(errorString.split(':')[2]); + if (isNaN(lineNo)) { + throw new Error(sprintf('Could not parse error: %s', errorString)); + } + errors[lineNo] = errorString; + } + + var lines = addLineNumbers(src).split('\n'); + + for (var i = 0; i < lines.length; i++) { + if (!errors[i+3] && !errors[i+2] && !errors[i+1]) continue; + var line = lines[i]; + longForm += line + '\n'; + if (errors[i+1]) { + var e = errors[i+1]; + e = e.substr(e.split(':', 3).join(':').length + 1).trim(); + longForm += sprintf('^^^ %s\n\n', e); + } + } + + return { + long: longForm.trim(), + short: shortForm.trim() + }; +} + + +},{"add-line-numbers":49,"gl-constants/lookup":236,"glsl-shader-name":384,"sprintf-js":504}],241:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createHeatmap2D + +var bsearch = _dereq_('binary-search-bounds') +var iota = _dereq_('iota-array') +var pool = _dereq_('typedarray-pool') +var createShader = _dereq_('gl-shader') +var createBuffer = _dereq_('gl-buffer') + +var shaders = _dereq_('./lib/shaders') + +function GLHeatmap2D ( + plot, + shader, + pickShader, + positionBuffer, + weightBuffer, + colorBuffer, + idBuffer) { + this.plot = plot + this.shader = shader + this.pickShader = pickShader + this.positionBuffer = positionBuffer + this.weightBuffer = weightBuffer + this.colorBuffer = colorBuffer + this.idBuffer = idBuffer + this.xData = [] + this.yData = [] + this.shape = [0, 0] + this.bounds = [Infinity, Infinity, -Infinity, -Infinity] + this.pickOffset = 0 +} + +var proto = GLHeatmap2D.prototype + +var WEIGHTS = [ + 0, 0, + 1, 0, + 0, 1, + 1, 0, + 1, 1, + 0, 1 +] + +proto.draw = (function () { + var MATRIX = [ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ] + + return function () { + var plot = this.plot + var shader = this.shader + var bounds = this.bounds + var numVertices = this.numVertices + + if (numVertices <= 0) { + return + } + + var gl = plot.gl + var dataBox = plot.dataBox + + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 + + shader.bind() + + var uniforms = shader.uniforms + uniforms.viewTransform = MATRIX + + uniforms.shape = this.shape + + var attributes = shader.attributes + this.positionBuffer.bind() + attributes.position.pointer() + + this.weightBuffer.bind() + attributes.weight.pointer(gl.UNSIGNED_BYTE, false) + + this.colorBuffer.bind() + attributes.color.pointer(gl.UNSIGNED_BYTE, true) + + gl.drawArrays(gl.TRIANGLES, 0, numVertices) + } +})() + +proto.drawPick = (function () { + var MATRIX = [ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ] + + var PICK_VECTOR = [0, 0, 0, 0] + + return function (pickOffset) { + var plot = this.plot + var shader = this.pickShader + var bounds = this.bounds + var numVertices = this.numVertices + + if (numVertices <= 0) { + return + } + + var gl = plot.gl + var dataBox = plot.dataBox + + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 + + for (var i = 0; i < 4; ++i) { + PICK_VECTOR[i] = (pickOffset >> (i * 8)) & 0xff + } + + this.pickOffset = pickOffset + + shader.bind() + + var uniforms = shader.uniforms + uniforms.viewTransform = MATRIX + uniforms.pickOffset = PICK_VECTOR + uniforms.shape = this.shape + + var attributes = shader.attributes + this.positionBuffer.bind() + attributes.position.pointer() + + this.weightBuffer.bind() + attributes.weight.pointer(gl.UNSIGNED_BYTE, false) + + this.idBuffer.bind() + attributes.pickId.pointer(gl.UNSIGNED_BYTE, false) + + gl.drawArrays(gl.TRIANGLES, 0, numVertices) + + return pickOffset + this.shape[0] * this.shape[1] + } +})() + +proto.pick = function (x, y, value) { + var pickOffset = this.pickOffset + var pointCount = this.shape[0] * this.shape[1] + if (value < pickOffset || value >= pickOffset + pointCount) { + return null + } + var pointId = value - pickOffset + var xData = this.xData + var yData = this.yData + return { + object: this, + pointId: pointId, + dataCoord: [ + xData[pointId % this.shape[0]], + yData[(pointId / this.shape[0]) | 0]] + } +} + +proto.update = function (options) { + options = options || {} + + var shape = options.shape || [0, 0] + + var x = options.x || iota(shape[0]) + var y = options.y || iota(shape[1]) + var z = options.z || new Float32Array(shape[0] * shape[1]) + + this.xData = x + this.yData = y + + var colorLevels = options.colorLevels || [0] + var colorValues = options.colorValues || [0, 0, 0, 1] + var colorCount = colorLevels.length + + var bounds = this.bounds + var lox = bounds[0] = x[0] + var loy = bounds[1] = y[0] + var hix = bounds[2] = x[x.length - 1] + var hiy = bounds[3] = y[y.length - 1] + + var xs = 1.0 / (hix - lox) + var ys = 1.0 / (hiy - loy) + + var numX = shape[0] + var numY = shape[1] + + this.shape = [numX, numY] + + var numVerts = (numX - 1) * (numY - 1) * (WEIGHTS.length >>> 1) + + this.numVertices = numVerts + + var colors = pool.mallocUint8(numVerts * 4) + var positions = pool.mallocFloat32(numVerts * 2) + var weights = pool.mallocUint8 (numVerts * 2) + var ids = pool.mallocUint32(numVerts) + + var ptr = 0 + + for (var j = 0; j < numY - 1; ++j) { + var yc0 = ys * (y[j] - loy) + var yc1 = ys * (y[j + 1] - loy) + for (var i = 0; i < numX - 1; ++i) { + var xc0 = xs * (x[i] - lox) + var xc1 = xs * (x[i + 1] - lox) + + for (var dd = 0; dd < WEIGHTS.length; dd += 2) { + var dx = WEIGHTS[dd] + var dy = WEIGHTS[dd + 1] + var offset = (j + dy) * numX + (i + dx) + var zc = z[offset] + var colorIdx = bsearch.le(colorLevels, zc) + var r, g, b, a + if (colorIdx < 0) { + r = colorValues[0] + g = colorValues[1] + b = colorValues[2] + a = colorValues[3] + } else if (colorIdx === colorCount - 1) { + r = colorValues[4 * colorCount - 4] + g = colorValues[4 * colorCount - 3] + b = colorValues[4 * colorCount - 2] + a = colorValues[4 * colorCount - 1] + } else { + var t = (zc - colorLevels[colorIdx]) / + (colorLevels[colorIdx + 1] - colorLevels[colorIdx]) + var ti = 1.0 - t + var i0 = 4 * colorIdx + var i1 = 4 * (colorIdx + 1) + r = ti * colorValues[i0] + t * colorValues[i1] + g = ti * colorValues[i0 + 1] + t * colorValues[i1 + 1] + b = ti * colorValues[i0 + 2] + t * colorValues[i1 + 2] + a = ti * colorValues[i0 + 3] + t * colorValues[i1 + 3] + } + + colors[4 * ptr] = 255 * r + colors[4 * ptr + 1] = 255 * g + colors[4 * ptr + 2] = 255 * b + colors[4 * ptr + 3] = 255 * a + + positions[2*ptr] = xc0*.5 + xc1*.5; + positions[2*ptr+1] = yc0*.5 + yc1*.5; + + weights[2*ptr] = dx; + weights[2*ptr+1] = dy; + + ids[ptr] = j * numX + i + + ptr += 1 + } + } + } + + this.positionBuffer.update(positions) + this.weightBuffer.update(weights) + this.colorBuffer.update(colors) + this.idBuffer.update(ids) + + pool.free(positions) + pool.free(colors) + pool.free(weights) + pool.free(ids) +} + +proto.dispose = function () { + this.shader.dispose() + this.pickShader.dispose() + this.positionBuffer.dispose() + this.weightBuffer.dispose() + this.colorBuffer.dispose() + this.idBuffer.dispose() + this.plot.removeObject(this) +} + +function createHeatmap2D (plot, options) { + var gl = plot.gl + + var shader = createShader(gl, shaders.vertex, shaders.fragment) + var pickShader = createShader(gl, shaders.pickVertex, shaders.pickFragment) + + var positionBuffer = createBuffer(gl) + var weightBuffer = createBuffer(gl) + var colorBuffer = createBuffer(gl) + var idBuffer = createBuffer(gl) + + var heatmap = new GLHeatmap2D( + plot, + shader, + pickShader, + positionBuffer, + weightBuffer, + colorBuffer, + idBuffer) + + heatmap.update(options) + plot.addObject(heatmap) + + return heatmap +} + +},{"./lib/shaders":242,"binary-search-bounds":243,"gl-buffer":230,"gl-shader":288,"iota-array":399,"typedarray-pool":522}],242:[function(_dereq_,module,exports){ +'use strict' + +var glslify = _dereq_('glslify') + +module.exports = { + fragment: glslify(["precision lowp float;\n#define GLSLIFY 1\nvarying vec4 fragColor;\nvoid main() {\n gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);\n}\n"]), + vertex: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 color;\nattribute vec2 weight;\n\nuniform vec2 shape;\nuniform mat3 viewTransform;\n\nvarying vec4 fragColor;\n\nvoid main() {\n vec3 vPosition = viewTransform * vec3( position + (weight-.5)/(shape-1.) , 1.0);\n fragColor = color;\n gl_Position = vec4(vPosition.xy, 0, vPosition.z);\n}\n"]), + pickFragment: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\nvarying vec2 vWeight;\n\nuniform vec2 shape;\nuniform vec4 pickOffset;\n\nvoid main() {\n vec2 d = step(.5, vWeight);\n vec4 id = fragId + pickOffset;\n id.x += d.x + d.y*shape.x;\n\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n gl_FragColor = id/255.;\n}\n"]), + pickVertex: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\nattribute vec2 weight;\n\nuniform vec2 shape;\nuniform mat3 viewTransform;\n\nvarying vec4 fragId;\nvarying vec2 vWeight;\n\nvoid main() {\n vWeight = weight;\n\n fragId = pickId;\n\n vec3 vPosition = viewTransform * vec3( position + (weight-.5)/(shape-1.) , 1.0);\n gl_Position = vec4(vPosition.xy, 0, vPosition.z);\n}\n"]) +} + +},{"glslify":392}],243:[function(_dereq_,module,exports){ +arguments[4][99][0].apply(exports,arguments) +},{"dup":99}],244:[function(_dereq_,module,exports){ +var glslify = _dereq_('glslify') +var createShader = _dereq_('gl-shader') + +var vertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position, nextPosition;\nattribute float arcLength, lineWidth;\nattribute vec4 color;\n\nuniform vec2 screenShape;\nuniform float pixelRatio;\nuniform mat4 model, view, projection;\n\nvarying vec4 fragColor;\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\n\nvec4 project(vec3 p) {\n return projection * view * model * vec4(p, 1.0);\n}\n\nvoid main() {\n vec4 startPoint = project(position);\n vec4 endPoint = project(nextPosition);\n\n vec2 A = startPoint.xy / startPoint.w;\n vec2 B = endPoint.xy / endPoint.w;\n\n float clipAngle = atan(\n (B.y - A.y) * screenShape.y,\n (B.x - A.x) * screenShape.x\n );\n\n vec2 offset = 0.5 * pixelRatio * lineWidth * vec2(\n sin(clipAngle),\n -cos(clipAngle)\n ) / screenShape;\n\n gl_Position = vec4(startPoint.xy + startPoint.w * offset, startPoint.zw);\n\n worldPosition = position;\n pixelArcLength = arcLength;\n fragColor = color;\n}\n"]) +var forwardFrag = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D dashTexture;\nuniform float dashScale;\nuniform float opacity;\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n float dashWeight = texture2D(dashTexture, vec2(dashScale * pixelArcLength, 0)).r;\n if(dashWeight < 0.5) {\n discard;\n }\n gl_FragColor = fragColor * opacity;\n}\n"]) +var pickFrag = glslify(["precision mediump float;\n#define GLSLIFY 1\n\n#define FLOAT_MAX 1.70141184e38\n#define FLOAT_MIN 1.17549435e-38\n\nlowp vec4 encode_float_1540259130(highp float v) {\n highp float av = abs(v);\n\n //Handle special cases\n if(av < FLOAT_MIN) {\n return vec4(0.0, 0.0, 0.0, 0.0);\n } else if(v > FLOAT_MAX) {\n return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;\n } else if(v < -FLOAT_MAX) {\n return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;\n }\n\n highp vec4 c = vec4(0,0,0,0);\n\n //Compute exponent and mantissa\n highp float e = floor(log2(av));\n highp float m = av * pow(2.0, -e) - 1.0;\n \n //Unpack mantissa\n c[1] = floor(128.0 * m);\n m -= c[1] / 128.0;\n c[2] = floor(32768.0 * m);\n m -= c[2] / 32768.0;\n c[3] = floor(8388608.0 * m);\n \n //Unpack exponent\n highp float ebias = e + 127.0;\n c[0] = floor(ebias / 2.0);\n ebias -= c[0] * 2.0;\n c[1] += floor(ebias) * 128.0; \n\n //Unpack sign bit\n c[0] += 128.0 * step(0.0, -v);\n\n //Scale back to range\n return c / 255.0;\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform float pickId;\nuniform vec3 clipBounds[2];\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n gl_FragColor = vec4(pickId/255.0, encode_float_1540259130(pixelArcLength).xyz);\n}"]) + +var ATTRIBUTES = [ + {name: 'position', type: 'vec3'}, + {name: 'nextPosition', type: 'vec3'}, + {name: 'arcLength', type: 'float'}, + {name: 'lineWidth', type: 'float'}, + {name: 'color', type: 'vec4'} +] + +exports.createShader = function(gl) { + return createShader(gl, vertSrc, forwardFrag, null, ATTRIBUTES) +} + +exports.createPickShader = function(gl) { + return createShader(gl, vertSrc, pickFrag, null, ATTRIBUTES) +} + +},{"gl-shader":288,"glslify":392}],245:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createLinePlot + +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createTexture = _dereq_('gl-texture2d') +var unpackFloat = _dereq_('glsl-read-float') +var bsearch = _dereq_('binary-search-bounds') +var ndarray = _dereq_('ndarray') +var shaders = _dereq_('./lib/shaders') + +var createShader = shaders.createShader +var createPickShader = shaders.createPickShader + +var identity = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1] + +function distance (a, b) { + var s = 0.0 + for (var i = 0; i < 3; ++i) { + var d = a[i] - b[i] + s += d * d + } + return Math.sqrt(s) +} + +function filterClipBounds (bounds) { + var result = [[-1e6, -1e6, -1e6], [1e6, 1e6, 1e6]] + for (var i = 0; i < 3; ++i) { + result[0][i] = Math.max(bounds[0][i], result[0][i]) + result[1][i] = Math.min(bounds[1][i], result[1][i]) + } + return result +} + +function PickResult (tau, position, index, dataCoordinate) { + this.arcLength = tau + this.position = position + this.index = index + this.dataCoordinate = dataCoordinate +} + +function LinePlot (gl, shader, pickShader, buffer, vao, texture) { + this.gl = gl + this.shader = shader + this.pickShader = pickShader + this.buffer = buffer + this.vao = vao + this.clipBounds = [ + [ -Infinity, -Infinity, -Infinity ], + [ Infinity, Infinity, Infinity ]] + this.points = [] + this.arcLength = [] + this.vertexCount = 0 + this.bounds = [[0, 0, 0], [0, 0, 0]] + this.pickId = 0 + this.lineWidth = 1 + this.texture = texture + this.dashScale = 1 + this.opacity = 1 + this.dirty = true + this.pixelRatio = 1 +} + +var proto = LinePlot.prototype + +proto.isTransparent = function () { + return this.opacity < 1 +} + +proto.isOpaque = function () { + return this.opacity >= 1 +} + +proto.pickSlots = 1 + +proto.setPickBase = function (id) { + this.pickId = id +} + +proto.drawTransparent = proto.draw = function (camera) { + if (!this.vertexCount) return + var gl = this.gl + var shader = this.shader + var vao = this.vao + shader.bind() + shader.uniforms = { + model: camera.model || identity, + view: camera.view || identity, + projection: camera.projection || identity, + clipBounds: filterClipBounds(this.clipBounds), + dashTexture: this.texture.bind(), + dashScale: this.dashScale / this.arcLength[this.arcLength.length - 1], + opacity: this.opacity, + screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], + pixelRatio: this.pixelRatio + } + vao.bind() + vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) + vao.unbind() +} + +proto.drawPick = function (camera) { + if (!this.vertexCount) return + var gl = this.gl + var shader = this.pickShader + var vao = this.vao + shader.bind() + shader.uniforms = { + model: camera.model || identity, + view: camera.view || identity, + projection: camera.projection || identity, + pickId: this.pickId, + clipBounds: filterClipBounds(this.clipBounds), + screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], + pixelRatio: this.pixelRatio + } + vao.bind() + vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) + vao.unbind() +} + +proto.update = function (options) { + var i, j + + this.dirty = true + + var connectGaps = !!options.connectGaps + + if ('dashScale' in options) { + this.dashScale = options.dashScale + } + if ('opacity' in options) { + this.opacity = +options.opacity + } + + // Recalculate buffer data + var buffer = [] + var arcLengthArray = [] + var pointArray = [] + var arcLength = 0.0 + var vertexCount = 0 + var bounds = [ + [ Infinity, Infinity, Infinity ], + [ -Infinity, -Infinity, -Infinity ]] + + var positions = options.position || options.positions + if (positions) { + + // Default color + var colors = options.color || options.colors || [0, 0, 0, 1] + + var lineWidth = options.lineWidth || 1 + + var hadGap = false + + fill_loop: + for (i = 1; i < positions.length; ++i) { + var a = positions[i - 1] + var b = positions[i] + + arcLengthArray.push(arcLength) + pointArray.push(a.slice()) + + for (j = 0; j < 3; ++j) { + if (isNaN(a[j]) || isNaN(b[j]) || + !isFinite(a[j]) || !isFinite(b[j])) { + + if (!connectGaps && buffer.length > 0) { + for (var k = 0; k < 24; ++k) { + buffer.push(buffer[buffer.length - 12]) + } + vertexCount += 2 + hadGap = true + } + + continue fill_loop + } + bounds[0][j] = Math.min(bounds[0][j], a[j], b[j]) + bounds[1][j] = Math.max(bounds[1][j], a[j], b[j]) + } + + var acolor, bcolor + if (Array.isArray(colors[0])) { + acolor = (colors.length > i - 1) ? colors[i - 1] : // using index value + (colors.length > 0) ? colors[colors.length - 1] : // using last item + [0, 0, 0, 1]; // using black + + bcolor = (colors.length > i) ? colors[i] : // using index value + (colors.length > 0) ? colors[colors.length - 1] : // using last item + [0, 0, 0, 1]; // using black + } else { + acolor = bcolor = colors + } + + if (acolor.length === 3) { + acolor = [acolor[0], acolor[1], acolor[2], 1] + } + if (bcolor.length === 3) { + bcolor = [bcolor[0], bcolor[1], bcolor[2], 1] + } + + var w0 + if (Array.isArray(lineWidth)) { + w0 = (lineWidth.length > i - 1) ? lineWidth[i - 1] : // using index value + (lineWidth.length > 0) ? lineWidth[lineWidth.length - 1] : // using last item + [0, 0, 0, 1]; // using black + } else { + w0 = lineWidth + } + + var t0 = arcLength + arcLength += distance(a, b) + + if (hadGap) { + for (j = 0; j < 2; ++j) { + buffer.push( + a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3]) + } + vertexCount += 2 + hadGap = false + } + + buffer.push( + a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3], + a[0], a[1], a[2], b[0], b[1], b[2], t0, -w0, acolor[0], acolor[1], acolor[2], acolor[3], + b[0], b[1], b[2], a[0], a[1], a[2], arcLength, -w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3], + b[0], b[1], b[2], a[0], a[1], a[2], arcLength, w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3]) + + vertexCount += 4 + } + } + this.buffer.update(buffer) + + arcLengthArray.push(arcLength) + pointArray.push(positions[positions.length - 1].slice()) + + this.bounds = bounds + + this.vertexCount = vertexCount + + this.points = pointArray + this.arcLength = arcLengthArray + + if ('dashes' in options) { + var dashArray = options.dashes + + // Calculate prefix sum + var prefixSum = dashArray.slice() + prefixSum.unshift(0) + for (i = 1; i < prefixSum.length; ++i) { + prefixSum[i] = prefixSum[i - 1] + prefixSum[i] + } + + var dashTexture = ndarray(new Array(256 * 4), [256, 1, 4]) + for (i = 0; i < 256; ++i) { + for (j = 0; j < 4; ++j) { + dashTexture.set(i, 0, j, 0) + } + if (bsearch.le(prefixSum, prefixSum[prefixSum.length - 1] * i / 255.0) & 1) { + dashTexture.set(i, 0, 0, 0) + } else { + dashTexture.set(i, 0, 0, 255) + } + } + + this.texture.setPixels(dashTexture) + } +} + +proto.dispose = function () { + this.shader.dispose() + this.vao.dispose() + this.buffer.dispose() +} + +proto.pick = function (selection) { + if (!selection) { + return null + } + if (selection.id !== this.pickId) { + return null + } + var tau = unpackFloat( + selection.value[0], + selection.value[1], + selection.value[2], + 0) + var index = bsearch.le(this.arcLength, tau) + if (index < 0) { + return null + } + if (index === this.arcLength.length - 1) { + return new PickResult( + this.arcLength[this.arcLength.length - 1], + this.points[this.points.length - 1].slice(), + index) + } + var a = this.points[index] + var b = this.points[Math.min(index + 1, this.points.length - 1)] + var t = (tau - this.arcLength[index]) / (this.arcLength[index + 1] - this.arcLength[index]) + var ti = 1.0 - t + var x = [0, 0, 0] + for (var i = 0; i < 3; ++i) { + x[i] = ti * a[i] + t * b[i] + } + var dataIndex = Math.min((t < 0.5) ? index : (index + 1), this.points.length - 1) + return new PickResult( + tau, + x, + dataIndex, + this.points[dataIndex]) +} + +function createLinePlot (options) { + var gl = options.gl || (options.scene && options.scene.gl) + + var shader = createShader(gl) + shader.attributes.position.location = 0 + shader.attributes.nextPosition.location = 1 + shader.attributes.arcLength.location = 2 + shader.attributes.lineWidth.location = 3 + shader.attributes.color.location = 4 + + var pickShader = createPickShader(gl) + pickShader.attributes.position.location = 0 + pickShader.attributes.nextPosition.location = 1 + pickShader.attributes.arcLength.location = 2 + pickShader.attributes.lineWidth.location = 3 + pickShader.attributes.color.location = 4 + + var buffer = createBuffer(gl) + var vao = createVAO(gl, [ + { + 'buffer': buffer, + 'size': 3, + 'offset': 0, + 'stride': 48 + }, + { + 'buffer': buffer, + 'size': 3, + 'offset': 12, + 'stride': 48 + }, + { + 'buffer': buffer, + 'size': 1, + 'offset': 24, + 'stride': 48 + }, + { + 'buffer': buffer, + 'size': 1, + 'offset': 28, + 'stride': 48 + }, + { + 'buffer': buffer, + 'size': 4, + 'offset': 32, + 'stride': 48 + } + ]) + + // Create texture for dash pattern + var defaultTexture = ndarray(new Array(256 * 4), [256, 1, 4]) + for (var i = 0; i < 256 * 4; ++i) { + defaultTexture.data[i] = 255 + } + var texture = createTexture(gl, defaultTexture) + texture.wrap = gl.REPEAT + + var linePlot = new LinePlot(gl, shader, pickShader, buffer, vao, texture) + linePlot.update(options) + return linePlot +} + +},{"./lib/shaders":244,"binary-search-bounds":79,"gl-buffer":230,"gl-texture2d":305,"gl-vao":310,"glsl-read-float":383,"ndarray":433}],246:[function(_dereq_,module,exports){ +module.exports = invert + +/** + * Inverts a mat2 + * + * @alias mat2.invert + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +function invert(out, a) { + var a0 = a[0] + var a1 = a[1] + var a2 = a[2] + var a3 = a[3] + var det = a0 * a3 - a2 * a1 + + if (!det) return null + det = 1.0 / det + + out[0] = a3 * det + out[1] = -a1 * det + out[2] = -a2 * det + out[3] = a0 * det + + return out +} + +},{}],247:[function(_dereq_,module,exports){ +module.exports = invert + +/** + * Inverts a mat3 + * + * @alias mat3.invert + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ +function invert(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + var b01 = a22 * a11 - a12 * a21 + var b11 = -a22 * a10 + a12 * a20 + var b21 = a21 * a10 - a11 * a20 + + // Calculate the determinant + var det = a00 * b01 + a01 * b11 + a02 * b21 + + if (!det) return null + det = 1.0 / det + + out[0] = b01 * det + out[1] = (-a22 * a01 + a02 * a21) * det + out[2] = (a12 * a01 - a02 * a11) * det + out[3] = b11 * det + out[4] = (a22 * a00 - a02 * a20) * det + out[5] = (-a12 * a00 + a02 * a10) * det + out[6] = b21 * det + out[7] = (-a21 * a00 + a01 * a20) * det + out[8] = (a11 * a00 - a01 * a10) * det + + return out +} + +},{}],248:[function(_dereq_,module,exports){ +module.exports = clone; + +/** + * Creates a new mat4 initialized with values from an existing matrix + * + * @param {mat4} a matrix to clone + * @returns {mat4} a new 4x4 matrix + */ +function clone(a) { + var out = new Float32Array(16); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; +},{}],249:[function(_dereq_,module,exports){ +module.exports = create; + +/** + * Creates a new identity mat4 + * + * @returns {mat4} a new 4x4 matrix + */ +function create() { + var out = new Float32Array(16); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; +},{}],250:[function(_dereq_,module,exports){ +module.exports = determinant; + +/** + * Calculates the determinant of a mat4 + * + * @param {mat4} a the source matrix + * @returns {Number} determinant of a + */ +function determinant(a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; +}; +},{}],251:[function(_dereq_,module,exports){ +module.exports = fromQuat; + +/** + * Creates a matrix from a quaternion rotation. + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @returns {mat4} out + */ +function fromQuat(out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + yx = y * x2, + yy = y * y2, + zx = z * x2, + zy = z * y2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - yy - zz; + out[1] = yx + wz; + out[2] = zx - wy; + out[3] = 0; + + out[4] = yx - wz; + out[5] = 1 - xx - zz; + out[6] = zy + wx; + out[7] = 0; + + out[8] = zx + wy; + out[9] = zy - wx; + out[10] = 1 - xx - yy; + out[11] = 0; + + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + + return out; +}; +},{}],252:[function(_dereq_,module,exports){ +module.exports = fromRotationTranslation; + +/** + * Creates a matrix from a quaternion rotation and vector translation + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * var quatMat = mat4.create(); + * quat4.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @param {vec3} v Translation vector + * @returns {mat4} out + */ +function fromRotationTranslation(out, q, v) { + // Quaternion math + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + out[12] = v[0]; + out[13] = v[1]; + out[14] = v[2]; + out[15] = 1; + + return out; +}; +},{}],253:[function(_dereq_,module,exports){ +module.exports = identity; + +/** + * Set a mat4 to the identity matrix + * + * @param {mat4} out the receiving matrix + * @returns {mat4} out + */ +function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; +},{}],254:[function(_dereq_,module,exports){ +module.exports = invert; + +/** + * Inverts a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +function invert(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; + + return out; +}; +},{}],255:[function(_dereq_,module,exports){ +var identity = _dereq_('./identity'); + +module.exports = lookAt; + +/** + * Generates a look-at matrix with the given eye position, focal point, and up axis + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {vec3} eye Position of the viewer + * @param {vec3} center Point the viewer is looking at + * @param {vec3} up vec3 pointing up + * @returns {mat4} out + */ +function lookAt(out, eye, center, up) { + var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, + eyex = eye[0], + eyey = eye[1], + eyez = eye[2], + upx = up[0], + upy = up[1], + upz = up[2], + centerx = center[0], + centery = center[1], + centerz = center[2]; + + if (Math.abs(eyex - centerx) < 0.000001 && + Math.abs(eyey - centery) < 0.000001 && + Math.abs(eyez - centerz) < 0.000001) { + return identity(out); + } + + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; + + len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + z0 *= len; + z1 *= len; + z2 *= len; + + x0 = upy * z2 - upz * z1; + x1 = upz * z0 - upx * z2; + x2 = upx * z1 - upy * z0; + len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + if (!len) { + x0 = 0; + x1 = 0; + x2 = 0; + } else { + len = 1 / len; + x0 *= len; + x1 *= len; + x2 *= len; + } + + y0 = z1 * x2 - z2 * x1; + y1 = z2 * x0 - z0 * x2; + y2 = z0 * x1 - z1 * x0; + + len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); + if (!len) { + y0 = 0; + y1 = 0; + y2 = 0; + } else { + len = 1 / len; + y0 *= len; + y1 *= len; + y2 *= len; + } + + out[0] = x0; + out[1] = y0; + out[2] = z0; + out[3] = 0; + out[4] = x1; + out[5] = y1; + out[6] = z1; + out[7] = 0; + out[8] = x2; + out[9] = y2; + out[10] = z2; + out[11] = 0; + out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); + out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); + out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); + out[15] = 1; + + return out; +}; +},{"./identity":253}],256:[function(_dereq_,module,exports){ +module.exports = multiply; + +/** + * Multiplies two mat4's + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the first operand + * @param {mat4} b the second operand + * @returns {mat4} out + */ +function multiply(out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + // Cache only the current line of the second matrix + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; + out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; + out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; + out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + return out; +}; +},{}],257:[function(_dereq_,module,exports){ +module.exports = perspective; + +/** + * Generates a perspective projection matrix with the given bounds + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} fovy Vertical field of view in radians + * @param {number} aspect Aspect ratio. typically viewport width/height + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out + */ +function perspective(out, fovy, aspect, near, far) { + var f = 1.0 / Math.tan(fovy / 2), + nf = 1 / (near - far); + out[0] = f / aspect; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = f; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (2 * far * near) * nf; + out[15] = 0; + return out; +}; +},{}],258:[function(_dereq_,module,exports){ +module.exports = rotate; + +/** + * Rotates a mat4 by the given angle + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @param {vec3} axis the axis to rotate around + * @returns {mat4} out + */ +function rotate(out, a, rad, axis) { + var x = axis[0], y = axis[1], z = axis[2], + len = Math.sqrt(x * x + y * y + z * z), + s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; + + if (Math.abs(len) < 0.000001) { return null; } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; + + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; + + // Perform rotation-specific matrix multiplication + out[0] = a00 * b00 + a10 * b01 + a20 * b02; + out[1] = a01 * b00 + a11 * b01 + a21 * b02; + out[2] = a02 * b00 + a12 * b01 + a22 * b02; + out[3] = a03 * b00 + a13 * b01 + a23 * b02; + out[4] = a00 * b10 + a10 * b11 + a20 * b12; + out[5] = a01 * b10 + a11 * b11 + a21 * b12; + out[6] = a02 * b10 + a12 * b11 + a22 * b12; + out[7] = a03 * b10 + a13 * b11 + a23 * b12; + out[8] = a00 * b20 + a10 * b21 + a20 * b22; + out[9] = a01 * b20 + a11 * b21 + a21 * b22; + out[10] = a02 * b20 + a12 * b21 + a22 * b22; + out[11] = a03 * b20 + a13 * b21 + a23 * b22; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + return out; +}; +},{}],259:[function(_dereq_,module,exports){ +module.exports = rotateX; + +/** + * Rotates a matrix by the given angle around the X axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateX(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[4] = a10 * c + a20 * s; + out[5] = a11 * c + a21 * s; + out[6] = a12 * c + a22 * s; + out[7] = a13 * c + a23 * s; + out[8] = a20 * c - a10 * s; + out[9] = a21 * c - a11 * s; + out[10] = a22 * c - a12 * s; + out[11] = a23 * c - a13 * s; + return out; +}; +},{}],260:[function(_dereq_,module,exports){ +module.exports = rotateY; + +/** + * Rotates a matrix by the given angle around the Y axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateY(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c - a20 * s; + out[1] = a01 * c - a21 * s; + out[2] = a02 * c - a22 * s; + out[3] = a03 * c - a23 * s; + out[8] = a00 * s + a20 * c; + out[9] = a01 * s + a21 * c; + out[10] = a02 * s + a22 * c; + out[11] = a03 * s + a23 * c; + return out; +}; +},{}],261:[function(_dereq_,module,exports){ +module.exports = rotateZ; + +/** + * Rotates a matrix by the given angle around the Z axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateZ(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7]; + + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + + // Perform axis-specific matrix multiplication + out[0] = a00 * c + a10 * s; + out[1] = a01 * c + a11 * s; + out[2] = a02 * c + a12 * s; + out[3] = a03 * c + a13 * s; + out[4] = a10 * c - a00 * s; + out[5] = a11 * c - a01 * s; + out[6] = a12 * c - a02 * s; + out[7] = a13 * c - a03 * s; + return out; +}; +},{}],262:[function(_dereq_,module,exports){ +module.exports = scale; + +/** + * Scales the mat4 by the dimensions in the given vec3 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to scale + * @param {vec3} v the vec3 to scale the matrix by + * @returns {mat4} out + **/ +function scale(out, a, v) { + var x = v[0], y = v[1], z = v[2]; + + out[0] = a[0] * x; + out[1] = a[1] * x; + out[2] = a[2] * x; + out[3] = a[3] * x; + out[4] = a[4] * y; + out[5] = a[5] * y; + out[6] = a[6] * y; + out[7] = a[7] * y; + out[8] = a[8] * z; + out[9] = a[9] * z; + out[10] = a[10] * z; + out[11] = a[11] * z; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; +},{}],263:[function(_dereq_,module,exports){ +module.exports = translate; + +/** + * Translate a mat4 by the given vector + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to translate + * @param {vec3} v vector to translate by + * @returns {mat4} out + */ +function translate(out, a, v) { + var x = v[0], y = v[1], z = v[2], + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; + + if (a === out) { + out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + } else { + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; + + out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; + out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; + out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; + + out[12] = a00 * x + a10 * y + a20 * z + a[12]; + out[13] = a01 * x + a11 * y + a21 * z + a[13]; + out[14] = a02 * x + a12 * y + a22 * z + a[14]; + out[15] = a03 * x + a13 * y + a23 * z + a[15]; + } + + return out; +}; +},{}],264:[function(_dereq_,module,exports){ +module.exports = transpose; + +/** + * Transpose the values of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +function transpose(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a03 = a[3], + a12 = a[6], a13 = a[7], + a23 = a[11]; + + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a01; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a02; + out[9] = a12; + out[11] = a[14]; + out[12] = a03; + out[13] = a13; + out[14] = a23; + } else { + out[0] = a[0]; + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a[1]; + out[5] = a[5]; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a[2]; + out[9] = a[6]; + out[10] = a[10]; + out[11] = a[14]; + out[12] = a[3]; + out[13] = a[7]; + out[14] = a[11]; + out[15] = a[15]; + } + + return out; +}; +},{}],265:[function(_dereq_,module,exports){ +'use strict' + +module.exports = invert + +var invert2 = _dereq_('gl-mat2/invert') +var invert3 = _dereq_('gl-mat3/invert') +var invert4 = _dereq_('gl-mat4/invert') + +function invert(out, M) { + switch(M.length) { + case 0: + break + case 1: + out[0] = 1.0 / M[0] + break + case 4: + invert2(out, M) + break + case 9: + invert3(out, M) + break + case 16: + invert4(out, M) + break + default: + throw new Error('currently supports matrices up to 4x4') + break + } + return out +} +},{"gl-mat2/invert":246,"gl-mat3/invert":247,"gl-mat4/invert":254}],266:[function(_dereq_,module,exports){ +arguments[4][232][0].apply(exports,arguments) +},{"barycentric":61,"dup":232,"polytope-closest-point/lib/closest_point_2d.js":464}],267:[function(_dereq_,module,exports){ +var glslify = _dereq_('glslify') + +var triVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, normal;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec4 m_position = model * vec4(position, 1.0);\n vec4 t_position = view * m_position;\n gl_Position = projection * t_position;\n f_color = color;\n f_normal = normal;\n f_data = position;\n f_eyeDirection = eyePosition - position;\n f_lightDirection = lightPosition - position;\n f_uv = uv;\n}\n"]) +var triFragSrc = glslify(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nvec3 normals(vec3 pos) {\n vec3 fdx = dFdx(pos);\n vec3 fdy = dFdy(pos);\n return normalize(cross(fdx, fdy));\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n vec3 normal = normals(f_data);\n\n if (dot(N, normal) < 0.0) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]) +var edgeVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}"]) +var edgeFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]) +var pointVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}"]) +var pointFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5,0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]) +var pickVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}"]) +var pickFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) +var pickPointVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}"]) +var contourVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}"]) +var contourFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor,1);\n}\n"]) + +exports.meshShader = { + vertex: triVertSrc, + fragment: triFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'normal', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'} + ] +} +exports.wireShader = { + vertex: edgeVertSrc, + fragment: edgeFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'} + ] +} +exports.pointShader = { + vertex: pointVertSrc, + fragment: pointFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'}, + {name: 'pointSize', type: 'float'} + ] +} +exports.pickShader = { + vertex: pickVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'id', type: 'vec4'} + ] +} +exports.pointPickShader = { + vertex: pickPointVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'pointSize', type: 'float'}, + {name: 'id', type: 'vec4'} + ] +} +exports.contourShader = { + vertex: contourVertSrc, + fragment: contourFragSrc, + attributes: [ + {name: 'position', type: 'vec3'} + ] +} + +},{"glslify":392}],268:[function(_dereq_,module,exports){ +'use strict' + +var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small +var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; + +var createShader = _dereq_('gl-shader') +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createTexture = _dereq_('gl-texture2d') +var normals = _dereq_('normals') +var multiply = _dereq_('gl-mat4/multiply') +var invert = _dereq_('gl-mat4/invert') +var ndarray = _dereq_('ndarray') +var colormap = _dereq_('colormap') +var getContour = _dereq_('simplicial-complex-contour') +var pool = _dereq_('typedarray-pool') +var shaders = _dereq_('./lib/shaders') +var closestPoint = _dereq_('./lib/closest-point') + +var meshShader = shaders.meshShader +var wireShader = shaders.wireShader +var pointShader = shaders.pointShader +var pickShader = shaders.pickShader +var pointPickShader = shaders.pointPickShader +var contourShader = shaders.contourShader + +var identityMatrix = [ + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + + +function SimplicialMesh(gl + , texture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) { + + this.gl = gl + this.cells = [] + this.positions = [] + this.intensity = [] + this.texture = texture + this.dirty = true + + this.triShader = triShader + this.lineShader = lineShader + this.pointShader = pointShader + this.pickShader = pickShader + this.pointPickShader = pointPickShader + this.contourShader = contourShader + + this.trianglePositions = trianglePositions + this.triangleColors = triangleColors + this.triangleNormals = triangleNormals + this.triangleUVs = triangleUVs + this.triangleIds = triangleIds + this.triangleVAO = triangleVAO + this.triangleCount = 0 + + this.lineWidth = 1 + this.edgePositions = edgePositions + this.edgeColors = edgeColors + this.edgeUVs = edgeUVs + this.edgeIds = edgeIds + this.edgeVAO = edgeVAO + this.edgeCount = 0 + + this.pointPositions = pointPositions + this.pointColors = pointColors + this.pointUVs = pointUVs + this.pointSizes = pointSizes + this.pointIds = pointIds + this.pointVAO = pointVAO + this.pointCount = 0 + + this.contourLineWidth = 1 + this.contourPositions = contourPositions + this.contourVAO = contourVAO + this.contourCount = 0 + this.contourColor = [0,0,0] + this.contourEnable = true + + this.pickId = 1 + this.bounds = [ + [ Infinity, Infinity, Infinity], + [-Infinity,-Infinity,-Infinity] ] + this.clipBounds = [ + [-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity] ] + + this.lightPosition = [1e5, 1e5, 0] + this.ambientLight = 0.8 + this.diffuseLight = 0.8 + this.specularLight = 2.0 + this.roughness = 0.5 + this.fresnel = 1.5 + + this.opacity = 1.0 + + this._model = identityMatrix + this._view = identityMatrix + this._projection = identityMatrix + this._resolution = [1,1] +} + +var proto = SimplicialMesh.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 +} + +proto.isTransparent = function() { + return this.opacity < 1 +} + +proto.pickSlots = 1 + +proto.setPickBase = function(id) { + this.pickId = id +} + +function genColormap(param) { + var colors = colormap({ + colormap: param + , nshades: 256 + , format: 'rgba' + }) + + var result = new Uint8Array(256*4) + for(var i=0; i<256; ++i) { + var c = colors[i] + for(var j=0; j<3; ++j) { + result[4*i+j] = c[j] + } + result[4*i+3] = c[3]*255 + } + + return ndarray(result, [256,256,4], [4,0,1]) +} + +function unpackIntensity(cells, numVerts, cellIntensity) { + var result = new Array(numVerts) + for(var i=0; i 0) { + var shader = this.triShader + shader.bind() + shader.uniforms = uniforms + + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0 && this.lineWidth > 0) { + var shader = this.lineShader + shader.bind() + shader.uniforms = uniforms + + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } + + if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { + var shader = this.contourShader + shader.bind() + shader.uniforms = uniforms + + this.contourVAO.bind() + gl.drawArrays(gl.LINES, 0, this.contourCount) + this.contourVAO.unbind() + } +} + +proto.drawPick = function(params) { + params = params || {} + + var gl = this.gl + + var model = params.model || identityMatrix + var view = params.view || identityMatrix + var projection = params.projection || identityMatrix + + var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] + for(var i=0; i<3; ++i) { + clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) + clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) + } + + //Save camera parameters + this._model = [].slice.call(model) + this._view = [].slice.call(view) + this._projection = [].slice.call(projection) + this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] + + var uniforms = { + model: model, + view: view, + projection: projection, + clipBounds: clipBounds, + pickId: this.pickId / 255.0, + } + + var shader = this.pickShader + shader.bind() + shader.uniforms = uniforms + + if(this.triangleCount > 0) { + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0) { + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointPickShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } +} + + +proto.pick = function(pickData) { + if(!pickData) { + return null + } + if(pickData.id !== this.pickId) { + return null + } + + var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] + var cell = this.cells[cellId] + var positions = this.positions + + var simplex = new Array(cell.length) + for(var i=0; i tickOffset[start]) { + shader.uniforms.dataAxis = DATA_AXIS + shader.uniforms.screenOffset = SCREEN_OFFSET + shader.uniforms.color = textColor[axis] + shader.uniforms.angle = textAngle[axis] + gl.drawArrays( + gl.TRIANGLES, + tickOffset[start], + tickOffset[end] - tickOffset[start]) + } + } + if(labelEnable[axis] && labelCount) { + SCREEN_OFFSET[axis^1] -= screenScale * pixelRatio * labelPad[axis] + shader.uniforms.dataAxis = ZERO_2 + shader.uniforms.screenOffset = SCREEN_OFFSET + shader.uniforms.color = labelColor[axis] + shader.uniforms.angle = labelAngle[axis] + gl.drawArrays( + gl.TRIANGLES, + labelOffset, + labelCount) + } + + SCREEN_OFFSET[axis^1] = screenScale * viewBox[2+(axis^1)] - 1.0 + if(tickEnable[axis+2]) { + SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * tickPad[axis+2] + if(start < end && tickOffset[end] > tickOffset[start]) { + shader.uniforms.dataAxis = DATA_AXIS + shader.uniforms.screenOffset = SCREEN_OFFSET + shader.uniforms.color = textColor[axis+2] + shader.uniforms.angle = textAngle[axis+2] + gl.drawArrays( + gl.TRIANGLES, + tickOffset[start], + tickOffset[end] - tickOffset[start]) + } + } + if(labelEnable[axis+2] && labelCount) { + SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * labelPad[axis+2] + shader.uniforms.dataAxis = ZERO_2 + shader.uniforms.screenOffset = SCREEN_OFFSET + shader.uniforms.color = labelColor[axis+2] + shader.uniforms.angle = labelAngle[axis+2] + gl.drawArrays( + gl.TRIANGLES, + labelOffset, + labelCount) + } + + } +})() + +proto.drawTitle = (function() { + var DATA_AXIS = [0,0] + var SCREEN_OFFSET = [0,0] + + return function() { + var plot = this.plot + var shader = this.shader + var gl = plot.gl + var screenBox = plot.screenBox + var titleCenter = plot.titleCenter + var titleAngle = plot.titleAngle + var titleColor = plot.titleColor + var pixelRatio = plot.pixelRatio + + if(!this.titleCount) { + return + } + + for(var i=0; i<2; ++i) { + SCREEN_OFFSET[i] = 2.0 * (titleCenter[i]*pixelRatio - screenBox[i]) / + (screenBox[2+i] - screenBox[i]) - 1 + } + + shader.bind() + shader.uniforms.dataAxis = DATA_AXIS + shader.uniforms.screenOffset = SCREEN_OFFSET + shader.uniforms.angle = titleAngle + shader.uniforms.color = titleColor + + gl.drawArrays(gl.TRIANGLES, this.titleOffset, this.titleCount) + } +})() + +proto.bind = (function() { + var DATA_SHIFT = [0,0] + var DATA_SCALE = [0,0] + var TEXT_SCALE = [0,0] + + return function() { + var plot = this.plot + var shader = this.shader + var bounds = plot._tickBounds + var dataBox = plot.dataBox + var screenBox = plot.screenBox + var viewBox = plot.viewBox + + shader.bind() + + //Set up coordinate scaling uniforms + for(var i=0; i<2; ++i) { + + var lo = bounds[i] + var hi = bounds[i+2] + var boundScale = hi - lo + var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) + var dataWidth = (dataBox[i+2] - dataBox[i]) + + var viewLo = viewBox[i] + var viewHi = viewBox[i+2] + var viewScale = viewHi - viewLo + var screenLo = screenBox[i] + var screenHi = screenBox[i+2] + var screenScale = screenHi - screenLo + + DATA_SCALE[i] = 2.0 * boundScale / dataWidth * viewScale / screenScale + DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth * viewScale / screenScale + } + + TEXT_SCALE[1] = 2.0 * plot.pixelRatio / (screenBox[3] - screenBox[1]) + TEXT_SCALE[0] = TEXT_SCALE[1] * (screenBox[3] - screenBox[1]) / (screenBox[2] - screenBox[0]) + + shader.uniforms.dataScale = DATA_SCALE + shader.uniforms.dataShift = DATA_SHIFT + shader.uniforms.textScale = TEXT_SCALE + + //Set attributes + this.vbo.bind() + shader.attributes.textCoordinate.pointer() + } +})() + +proto.update = function(options) { + var vertices = [] + var axesTicks = options.ticks + var bounds = options.bounds + var i, j, k, data, scale, dimension + + for(dimension=0; dimension<2; ++dimension) { + var offsets = [Math.floor(vertices.length/3)], tickX = [-Infinity] + + //Copy vertices over to buffer + var ticks = axesTicks[dimension] + for(i=0; i= 0)) { + continue + } + + var zeroIntercept = screenBox[i] - + dataBox[i] * (screenBox[i+2] - screenBox[i]) / (dataBox[i+2] - dataBox[i]) + + if(i === 0) { + line.drawLine( + zeroIntercept, screenBox[1], zeroIntercept, screenBox[3], + zeroLineWidth[i], + zeroLineColor[i]) + } else { + line.drawLine( + screenBox[0], zeroIntercept, screenBox[2], zeroIntercept, + zeroLineWidth[i], + zeroLineColor[i]) + } + } + } + + //Draw traces + for(var i=0; i=0; --i) { + this.objects[i].dispose() + } + this.objects.length = 0 + for(var i=this.overlays.length-1; i>=0; --i) { + this.overlays[i].dispose() + } + this.overlays.length = 0 + + this.gl = null +} + +proto.addObject = function(object) { + if(this.objects.indexOf(object) < 0) { + this.objects.push(object) + this.setDirty() + } +} + +proto.removeObject = function(object) { + var objects = this.objects + for(var i=0; i 0) { + var base = Math.round(Math.pow(10, y)) + return Math.ceil(x/base) * base + } + return Math.ceil(x) +} + +function defaultBool(x) { + if(typeof x === 'boolean') { + return x + } + return true +} + +function createScene(options) { + options = options || {} + + var stopped = false + + var pixelRatio = options.pixelRatio || parseFloat(window.devicePixelRatio) + + var canvas = options.canvas + if(!canvas) { + canvas = document.createElement('canvas') + if(options.container) { + var container = options.container + container.appendChild(canvas) + } else { + document.body.appendChild(canvas) + } + } + + var gl = options.gl + if(!gl) { + gl = getContext(canvas, + options.glOptions || { + premultipliedAlpha: true, + antialias: true, + preserveDrawingBuffer: isMobile + }) + } + if(!gl) { + throw new Error('webgl not supported') + } + + //Initial bounds + var bounds = options.bounds || [[-10,-10,-10], [10,10,10]] + + //Create selection + var selection = new MouseSelect() + + //Accumulation buffer + var accumBuffer = createFBO(gl, + [gl.drawingBufferWidth, gl.drawingBufferHeight], { + preferFloat: !isMobile + }) + + var accumShader = createShader(gl) + + //Create a camera + var cameraOptions = options.camera || { + eye: [2,0,0], + center: [0,0,0], + up: [0,1,0], + zoomMin: 0.1, + zoomMax: 100, + mode: 'turntable' + } + + //Create axes + var axesOptions = options.axes || {} + var axes = createAxes(gl, axesOptions) + axes.enable = !axesOptions.disable + + //Create spikes + var spikeOptions = options.spikes || {} + var spikes = createSpikes(gl, spikeOptions) + + //Object list is empty initially + var objects = [] + var pickBufferIds = [] + var pickBufferCount = [] + var pickBuffers = [] + + //Dirty flag, skip redraw if scene static + var dirty = true + var pickDirty = true + + var projection = new Array(16) + var model = new Array(16) + + var cameraParams = { + view: null, + projection: projection, + model: model + } + + var pickDirty = true + + var viewShape = [ gl.drawingBufferWidth, gl.drawingBufferHeight ] + + //Create scene object + var scene = { + gl: gl, + contextLost: false, + pixelRatio: options.pixelRatio || parseFloat(window.devicePixelRatio), + canvas: canvas, + selection: selection, + camera: createCamera(canvas, cameraOptions), + axes: axes, + axesPixels: null, + spikes: spikes, + bounds: bounds, + objects: objects, + shape: viewShape, + aspect: options.aspectRatio || [1,1,1], + pickRadius: options.pickRadius || 10, + zNear: options.zNear || 0.01, + zFar: options.zFar || 1000, + fovy: options.fovy || Math.PI/4, + clearColor: options.clearColor || [0,0,0,0], + autoResize: defaultBool(options.autoResize), + autoBounds: defaultBool(options.autoBounds), + autoScale: !!options.autoScale, + autoCenter: defaultBool(options.autoCenter), + clipToBounds: defaultBool(options.clipToBounds), + snapToData: !!options.snapToData, + onselect: options.onselect || null, + onrender: options.onrender || null, + onclick: options.onclick || null, + cameraParams: cameraParams, + oncontextloss: null, + mouseListener: null + } + + var pickShape = [ (gl.drawingBufferWidth/scene.pixelRatio)|0, (gl.drawingBufferHeight/scene.pixelRatio)|0 ] + + function resizeListener() { + if(stopped) { + return + } + if(!scene.autoResize) { + return + } + var parent = canvas.parentNode + var width = 1 + var height = 1 + if(parent && parent !== document.body) { + width = parent.clientWidth + height = parent.clientHeight + } else { + width = window.innerWidth + height = window.innerHeight + } + var nextWidth = Math.ceil(width * scene.pixelRatio)|0 + var nextHeight = Math.ceil(height * scene.pixelRatio)|0 + if(nextWidth !== canvas.width || nextHeight !== canvas.height) { + canvas.width = nextWidth + canvas.height = nextHeight + var style = canvas.style + style.position = style.position || 'absolute' + style.left = '0px' + style.top = '0px' + style.width = width + 'px' + style.height = height + 'px' + dirty = true + } + } + if(scene.autoResize) { + resizeListener() + } + window.addEventListener('resize', resizeListener) + + function reallocPickIds() { + var numObjs = objects.length + var numPick = pickBuffers.length + for(var i=0; i 0 && pickBufferCount[numPick-1] === 0) { + pickBufferCount.pop() + pickBuffers.pop().dispose() + } + } + + scene.update = function(options) { + if(stopped) { + return + } + options = options || {} + dirty = true + pickDirty = true + } + + scene.add = function(obj) { + if(stopped) { + return + } + obj.axes = axes + objects.push(obj) + pickBufferIds.push(-1) + dirty = true + pickDirty = true + reallocPickIds() + } + + scene.remove = function(obj) { + if(stopped) { + return + } + var idx = objects.indexOf(obj) + if(idx < 0) { + return + } + objects.splice(idx, 1) + pickBufferIds.pop() + dirty = true + pickDirty = true + reallocPickIds() + } + + scene.dispose = function() { + if(stopped) { + return + } + + stopped = true + + window.removeEventListener('resize', resizeListener) + canvas.removeEventListener('webglcontextlost', checkContextLoss) + scene.mouseListener.enabled = false + + if(scene.contextLost) { + return + } + + //Destroy objects + axes.dispose() + spikes.dispose() + for(var i=0; i selection.distance) { + continue + } + for(var j=0; j 1.0) {\n discard;\n }\n baseColor = mix(borderColor, color, step(radius, centerFraction));\n gl_FragColor = vec4(baseColor.rgb * baseColor.a, baseColor.a);\n }\n}\n"]) +exports.pickVertex = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\n\nuniform mat3 matrix;\nuniform float pointSize;\nuniform vec4 pickOffset;\n\nvarying vec4 fragId;\n\nvoid main() {\n vec3 hgPosition = matrix * vec3(position, 1);\n gl_Position = vec4(hgPosition.xy, 0, hgPosition.z);\n gl_PointSize = pointSize;\n\n vec4 id = pickId + pickOffset;\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n fragId = id;\n}\n"]) +exports.pickFragment = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\n\nvoid main() {\n float radius = length(2.0 * gl_PointCoord.xy - 1.0);\n if(radius > 1.0) {\n discard;\n }\n gl_FragColor = fragId / 255.0;\n}\n"]) + +},{"glslify":392}],279:[function(_dereq_,module,exports){ +'use strict' + +var createShader = _dereq_('gl-shader') +var createBuffer = _dereq_('gl-buffer') + +var pool = _dereq_('typedarray-pool') + +var SHADERS = _dereq_('./lib/shader') + +module.exports = createPointcloud2D + +function Pointcloud2D(plot, offsetBuffer, pickBuffer, shader, pickShader) { + this.plot = plot + this.offsetBuffer = offsetBuffer + this.pickBuffer = pickBuffer + this.shader = shader + this.pickShader = pickShader + this.sizeMin = 0.5 + this.sizeMinCap = 2 + this.sizeMax = 20 + this.areaRatio = 1.0 + this.pointCount = 0 + this.color = [1, 0, 0, 1] + this.borderColor = [0, 0, 0, 1] + this.blend = false + this.pickOffset = 0 + this.points = null +} + +var proto = Pointcloud2D.prototype + +proto.dispose = function() { + this.shader.dispose() + this.pickShader.dispose() + this.offsetBuffer.dispose() + this.pickBuffer.dispose() + this.plot.removeObject(this) +} + +proto.update = function(options) { + + var i + + options = options || {} + + function dflt(opt, value) { + if(opt in options) { + return options[opt] + } + return value + } + + this.sizeMin = dflt('sizeMin', 0.5) + // this.sizeMinCap = dflt('sizeMinCap', 2) + this.sizeMax = dflt('sizeMax', 20) + this.color = dflt('color', [1, 0, 0, 1]).slice() + this.areaRatio = dflt('areaRatio', 1) + this.borderColor = dflt('borderColor', [0, 0, 0, 1]).slice() + this.blend = dflt('blend', false) + + //Update point data + + // Attempt straight-through processing (STP) to avoid allocation and copy + // TODO eventually abstract out STP logic, maybe into `pool` or a layer above + var pointCount = options.positions.length >>> 1 + var dataStraightThrough = options.positions instanceof Float32Array + var idStraightThrough = options.idToIndex instanceof Int32Array && options.idToIndex.length >= pointCount // permit larger to help reuse + + var data = options.positions + var packed = dataStraightThrough ? data : pool.mallocFloat32(data.length) + var packedId = idStraightThrough ? options.idToIndex : pool.mallocInt32(pointCount) + + if(!dataStraightThrough) { + packed.set(data) + } + + if(!idStraightThrough) { + packed.set(data) + for(i = 0; i < pointCount; i++) { + packedId[i] = i + } + } + + this.points = data + + this.offsetBuffer.update(packed) + this.pickBuffer.update(packedId) + + if(!dataStraightThrough) { + pool.free(packed) + } + + if(!idStraightThrough) { + pool.free(packedId) + } + + this.pointCount = pointCount + this.pickOffset = 0 +} + +function count(points, dataBox) { + var visiblePointCountEstimate = 0 + var length = points.length >>> 1 + var i + for(i = 0; i < length; i++) { + var x = points[i * 2] + var y = points[i * 2 + 1] + if(x >= dataBox[0] && x <= dataBox[2] && y >= dataBox[1] && y <= dataBox[3]) + visiblePointCountEstimate++ + } + return visiblePointCountEstimate +} + +proto.unifiedDraw = (function() { + var MATRIX = [1, 0, 0, + 0, 1, 0, + 0, 0, 1] + var PICK_VEC4 = [0, 0, 0, 0] +return function(pickOffset) { + var pick = pickOffset !== void(0) + + var shader = pick ? this.pickShader : this.shader + var gl = this.plot.gl + var dataBox = this.plot.dataBox + + if(this.pointCount === 0) { + return pickOffset + } + + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + + var visiblePointCountEstimate = count(this.points, dataBox) + var basicPointSize = this.plot.pickPixelRatio * Math.max(Math.min(this.sizeMinCap, this.sizeMin), Math.min(this.sizeMax, this.sizeMax / Math.pow(visiblePointCountEstimate, 0.33333))) + + MATRIX[0] = 2.0 / dataX + MATRIX[4] = 2.0 / dataY + MATRIX[6] = -2.0 * dataBox[0] / dataX - 1.0 + MATRIX[7] = -2.0 * dataBox[1] / dataY - 1.0 + + this.offsetBuffer.bind() + + shader.bind() + shader.attributes.position.pointer() + shader.uniforms.matrix = MATRIX + shader.uniforms.color = this.color + shader.uniforms.borderColor = this.borderColor + shader.uniforms.pointCloud = basicPointSize < 5 + shader.uniforms.pointSize = basicPointSize + shader.uniforms.centerFraction = Math.min(1, Math.max(0, Math.sqrt(1 - this.areaRatio))) + + if(pick) { + + PICK_VEC4[0] = ( pickOffset & 0xff) + PICK_VEC4[1] = ((pickOffset >> 8) & 0xff) + PICK_VEC4[2] = ((pickOffset >> 16) & 0xff) + PICK_VEC4[3] = ((pickOffset >> 24) & 0xff) + + this.pickBuffer.bind() + shader.attributes.pickId.pointer(gl.UNSIGNED_BYTE) + shader.uniforms.pickOffset = PICK_VEC4 + this.pickOffset = pickOffset + } + + // Worth switching these off, but we can't make assumptions about other + // renderers, so let's restore it after each draw + var blend = gl.getParameter(gl.BLEND) + var dither = gl.getParameter(gl.DITHER) + + if(blend && !this.blend) + gl.disable(gl.BLEND) + if(dither) + gl.disable(gl.DITHER) + + gl.drawArrays(gl.POINTS, 0, this.pointCount) + + if(blend && !this.blend) + gl.enable(gl.BLEND) + if(dither) + gl.enable(gl.DITHER) + + return pickOffset + this.pointCount +} +})() + +proto.draw = proto.unifiedDraw +proto.drawPick = proto.unifiedDraw + +proto.pick = function(x, y, value) { + var pickOffset = this.pickOffset + var pointCount = this.pointCount + if(value < pickOffset || value >= pickOffset + pointCount) { + return null + } + var pointId = value - pickOffset + var points = this.points + return { + object: this, + pointId: pointId, + dataCoord: [points[2 * pointId], points[2 * pointId + 1] ] + } +} + +function createPointcloud2D(plot, options) { + var gl = plot.gl + var buffer = createBuffer(gl) + var pickBuffer = createBuffer(gl) + var shader = createShader(gl, SHADERS.pointVertex, SHADERS.pointFragment) + var pickShader = createShader(gl, SHADERS.pickVertex, SHADERS.pickFragment) + + var result = new Pointcloud2D(plot, buffer, pickBuffer, shader, pickShader) + result.update(options) + + //Register with plot + plot.addObject(result) + + return result +} + +},{"./lib/shader":278,"gl-buffer":230,"gl-shader":288,"typedarray-pool":522}],280:[function(_dereq_,module,exports){ +module.exports = slerp + +/** + * Performs a spherical linear interpolation between two quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + */ +function slerp (out, a, b, t) { + // benchmarks: + // http://jsperf.com/quaternion-slerp-implementations + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3] + + var omega, cosom, sinom, scale0, scale1 + + // calc cosine + cosom = ax * bx + ay * by + az * bz + aw * bw + // adjust signs (if necessary) + if (cosom < 0.0) { + cosom = -cosom + bx = -bx + by = -by + bz = -bz + bw = -bw + } + // calculate coefficients + if ((1.0 - cosom) > 0.000001) { + // standard case (slerp) + omega = Math.acos(cosom) + sinom = Math.sin(omega) + scale0 = Math.sin((1.0 - t) * omega) / sinom + scale1 = Math.sin(t * omega) / sinom + } else { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = 1.0 - t + scale1 = t + } + // calculate final values + out[0] = scale0 * ax + scale1 * bx + out[1] = scale0 * ay + scale1 * by + out[2] = scale0 * az + scale1 * bz + out[3] = scale0 * aw + scale1 * bw + + return out +} + +},{}],281:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = function(a){ + return (!a && a !== 0) ? '' : a.toString(); +} + +},{}],282:[function(_dereq_,module,exports){ +"use strict" + +var vectorizeText = _dereq_("vectorize-text") + +module.exports = getGlyph + +var GLYPH_CACHE = {} + +function getGlyph(symbol, font) { + var fontCache = GLYPH_CACHE[font] + if(!fontCache) { + fontCache = GLYPH_CACHE[font] = {} + } + if(symbol in fontCache) { + return fontCache[symbol] + } + + //Get line and triangle meshes for glyph + var lineSymbol = vectorizeText(symbol, { + textAlign: "center", + textBaseline: "middle", + lineHeight: 1.0, + font: font + }) + var triSymbol = vectorizeText(symbol, { + triangles: true, + textAlign: "center", + textBaseline: "middle", + lineHeight: 1.0, + font: font + }) + + //Calculate bounding box + var bounds = [[Infinity,Infinity], [-Infinity,-Infinity]] + for(var i=0; i max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform vec4 highlightId;\nuniform float highlightScale;\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = 1.0;\n if(distance(highlightId, id) < 0.0001) {\n scale = highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1);\n vec4 viewPosition = view * worldPosition;\n viewPosition = viewPosition / viewPosition.w;\n vec4 clipPosition = projection * (viewPosition + scale * vec4(glyph.x, -glyph.y, 0, 0));\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]) +var orthographicVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float highlightScale, pixelRatio;\nuniform vec4 highlightId;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = pixelRatio;\n if(distance(highlightId.bgr, id.bgr) < 0.001) {\n scale *= highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1.0);\n vec4 viewPosition = view * worldPosition;\n vec4 clipPosition = projection * viewPosition;\n clipPosition /= clipPosition.w;\n\n gl_Position = clipPosition + vec4(screenSize * scale * vec2(glyph.x, -glyph.y), 0.0, 0.0);\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]) +var projectionVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform float highlightScale;\nuniform vec4 highlightId;\nuniform vec3 axes[2];\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float scale, pixelRatio;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float lscale = pixelRatio * scale;\n if(distance(highlightId, id) < 0.0001) {\n lscale *= highlightScale;\n }\n\n vec4 clipCenter = projection * view * model * vec4(position, 1);\n vec3 dataPosition = position + 0.5*lscale*(axes[0] * glyph.x + axes[1] * glyph.y) * clipCenter.w * screenSize.y;\n vec4 clipPosition = projection * view * model * vec4(dataPosition, 1);\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = dataPosition;\n }\n}\n"]) +var drawFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float opacity;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = interpColor * opacity;\n}\n"]) +var pickFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float pickGroup;\n\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = vec4(pickGroup, pickId.bgr);\n}"]) + +var ATTRIBUTES = [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'glyph', type: 'vec2'}, + {name: 'id', type: 'vec4'} +] + +var perspective = { + vertex: perspectiveVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + ortho = { + vertex: orthographicVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + project = { + vertex: projectionVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + pickPerspective = { + vertex: perspectiveVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + }, + pickOrtho = { + vertex: orthographicVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + }, + pickProject = { + vertex: projectionVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + } + +function createShader(gl, src) { + var shader = createShaderWrapper(gl, src) + var attr = shader.attributes + attr.position.location = 0 + attr.color.location = 1 + attr.glyph.location = 2 + attr.id.location = 3 + return shader +} + +exports.createPerspective = function(gl) { + return createShader(gl, perspective) +} +exports.createOrtho = function(gl) { + return createShader(gl, ortho) +} +exports.createProject = function(gl) { + return createShader(gl, project) +} +exports.createPickPerspective = function(gl) { + return createShader(gl, pickPerspective) +} +exports.createPickOrtho = function(gl) { + return createShader(gl, pickOrtho) +} +exports.createPickProject = function(gl) { + return createShader(gl, pickProject) +} + +},{"gl-shader":288,"glslify":392}],284:[function(_dereq_,module,exports){ +'use strict' + +var isAllBlank = _dereq_('is-string-blank') +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var pool = _dereq_('typedarray-pool') +var mat4mult = _dereq_('gl-mat4/multiply') +var shaders = _dereq_('./lib/shaders') +var getGlyph = _dereq_('./lib/glyphs') +var getSimpleString = _dereq_('./lib/get-simple-string') + +var IDENTITY = [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +module.exports = createPointCloud + +function transformMat4(x, m) { + var x0 = x[0] + var x1 = x[1] + var x2 = x[2] + var x3 = x[3] + x[0] = m[0] * x0 + m[4] * x1 + m[8] * x2 + m[12] * x3 + x[1] = m[1] * x0 + m[5] * x1 + m[9] * x2 + m[13] * x3 + x[2] = m[2] * x0 + m[6] * x1 + m[10] * x2 + m[14] * x3 + x[3] = m[3] * x0 + m[7] * x1 + m[11] * x2 + m[15] * x3 + return x +} + +function project(p, v, m, x) { + transformMat4(x, x, m) + transformMat4(x, x, v) + return transformMat4(x, x, p) +} + +function clampVec(v) { + var result = new Array(3) + for(var i=0; i<3; ++i) { + result[i] = Math.min(Math.max(v[i], -1e8), 1e8) + } + return result +} + +function ScatterPlotPickResult(index, position) { + this.index = index + this.dataCoordinate = this.position = position +} + +function PointCloud( + gl, + shader, + orthoShader, + projectShader, + pointBuffer, + colorBuffer, + glyphBuffer, + idBuffer, + vao, + pickPerspectiveShader, + pickOrthoShader, + pickProjectShader) { + + this.gl = gl + + this.pixelRatio = 1 + + this.shader = shader + this.orthoShader = orthoShader + this.projectShader = projectShader + + this.pointBuffer = pointBuffer + this.colorBuffer = colorBuffer + this.glyphBuffer = glyphBuffer + this.idBuffer = idBuffer + this.vao = vao + this.vertexCount = 0 + this.lineVertexCount = 0 + + this.opacity = 1.0 + + this.lineWidth = 0 + this.projectScale = [2.0/3.0, 2.0/3.0, 2.0/3.0] + this.projectOpacity = [1,1,1] + + this.pickId = 0 + this.pickPerspectiveShader = pickPerspectiveShader + this.pickOrthoShader = pickOrthoShader + this.pickProjectShader = pickProjectShader + this.points = [] + + this._selectResult = new ScatterPlotPickResult(0, [0,0,0]) + + this.useOrtho = true + this.bounds = [[ Infinity,Infinity,Infinity], + [-Infinity,-Infinity,-Infinity]] + + //Axes projections + this.axesProject = [ true, true, true ] + this.axesBounds = [[-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity]] + + this.highlightId = [1,1,1,1] + this.highlightScale = 2 + + this.clipBounds = [[-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity]] + + this.dirty = true +} + +var proto = PointCloud.prototype + +proto.pickSlots = 1 + +proto.setPickBase = function(pickBase) { + this.pickId = pickBase +} + +proto.isTransparent = function() { + if(this.opacity < 1) { + return true + } + for(var i=0; i<3; ++i) { + if(this.axesProject[i] && this.projectOpacity[i] < 1) { + return true + } + } + return false +} + +proto.isOpaque = function() { + if(this.opacity >= 1) { + return true + } + for(var i=0; i<3; ++i) { + if(this.axesProject[i] && this.projectOpacity[i] >= 1) { + return true + } + } + return false +} + +var VIEW_SHAPE = [0,0] +var U_VEC = [0,0,0] +var V_VEC = [0,0,0] +var MU_VEC = [0,0,0,1] +var MV_VEC = [0,0,0,1] +var SCRATCH_MATRIX = IDENTITY.slice() +var SCRATCH_VEC = [0,0,0] +var CLIP_BOUNDS = [[0,0,0], [0,0,0]] + +function zeroVec(a) { + a[0] = a[1] = a[2] = 0 + return a +} + +function augment(hg, af) { + hg[0] = af[0] + hg[1] = af[1] + hg[2] = af[2] + hg[3] = 1 + return hg +} + +function setComponent(out, v, i, x) { + out[0] = v[0] + out[1] = v[1] + out[2] = v[2] + out[i] = x + return out +} + +function getClipBounds(bounds) { + var result = CLIP_BOUNDS + for(var i=0; i<2; ++i) { + for(var j=0; j<3; ++j) { + result[i][j] = Math.max(Math.min(bounds[i][j], 1e8), -1e8) + } + } + return result +} + +function drawProject(shader, points, camera, transparent, forceDraw) { + var axesProject = points.axesProject + + var gl = points.gl + var uniforms = shader.uniforms + var model = camera.model || IDENTITY + var view = camera.view || IDENTITY + var projection = camera.projection || IDENTITY + var bounds = points.axesBounds + var clipBounds = getClipBounds(points.clipBounds) + + var cubeAxis + if(points.axes && points.axes.lastCubeProps) { + cubeAxis = points.axes.lastCubeProps.axis + } else { + cubeAxis = [1,1,1] + } + + VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth + VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight + + shader.bind() + uniforms.view = view + uniforms.projection = projection + uniforms.screenSize = VIEW_SHAPE + uniforms.highlightId = points.highlightId + uniforms.highlightScale = points.highlightScale + uniforms.clipBounds = clipBounds + uniforms.pickGroup = points.pickId / 255.0 + uniforms.pixelRatio = points.pixelRatio + + for(var i=0; i<3; ++i) { + if(!axesProject[i]) { + continue + } + if((points.projectOpacity[i] < 1) !== transparent) { + continue + } + + uniforms.scale = points.projectScale[i] + uniforms.opacity = points.projectOpacity[i] + + //Project model matrix + var pmodel = SCRATCH_MATRIX + for(var j=0; j<16; ++j) { + pmodel[j] = 0 + } + for(var j=0; j<4; ++j) { + pmodel[5*j] = 1 + } + pmodel[5*i] = 0 + if(cubeAxis[i] < 0) { + pmodel[12+i] = bounds[0][i] + } else { + pmodel[12+i] = bounds[1][i] + } + mat4mult(pmodel, model, pmodel) + uniforms.model = pmodel + + //Compute initial axes + var u = (i+1)%3 + var v = (i+2)%3 + var du = zeroVec(U_VEC) + var dv = zeroVec(V_VEC) + du[u] = 1 + dv[v] = 1 + + //Align orientation relative to viewer + var mdu = project(projection, view, model, augment(MU_VEC, du)) + var mdv = project(projection, view, model, augment(MV_VEC, dv)) + if(Math.abs(mdu[1]) > Math.abs(mdv[1])) { + var tmp = mdu + mdu = mdv + mdv = tmp + tmp = du + du = dv + dv = tmp + var t = u + u = v + v = t + } + if(mdu[0] < 0) { + du[u] = -1 + } + if(mdv[1] > 0) { + dv[v] = -1 + } + var su = 0.0 + var sv = 0.0 + for(var j=0; j<4; ++j) { + su += Math.pow(model[4*u+j], 2) + sv += Math.pow(model[4*v+j], 2) + } + du[u] /= Math.sqrt(su) + dv[v] /= Math.sqrt(sv) + uniforms.axes[0] = du + uniforms.axes[1] = dv + + //Update fragment clip bounds + uniforms.fragClipBounds[0] = setComponent(SCRATCH_VEC, clipBounds[0], i, -1e8) + uniforms.fragClipBounds[1] = setComponent(SCRATCH_VEC, clipBounds[1], i, 1e8) + + //Draw interior + points.vao.draw(gl.TRIANGLES, points.vertexCount) + + //Draw edges + if(points.lineWidth > 0) { + gl.lineWidth(points.lineWidth) + points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) + } + } +} + + +var NEG_INFINITY3 = [-1e8, -1e8, -1e8] +var POS_INFINITY3 = [1e8, 1e8, 1e8] +var CLIP_GROUP = [NEG_INFINITY3, POS_INFINITY3] + +function drawFull(shader, pshader, points, camera, transparent, forceDraw) { + var gl = points.gl + + points.vao.bind() + + if(transparent === (points.opacity < 1) || forceDraw) { + shader.bind() + var uniforms = shader.uniforms + + uniforms.model = camera.model || IDENTITY + uniforms.view = camera.view || IDENTITY + uniforms.projection = camera.projection || IDENTITY + + VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth + VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight + uniforms.screenSize = VIEW_SHAPE + + uniforms.highlightId = points.highlightId + uniforms.highlightScale = points.highlightScale + + uniforms.fragClipBounds = CLIP_GROUP + uniforms.clipBounds = points.axes.bounds + + uniforms.opacity = points.opacity + uniforms.pickGroup = points.pickId / 255.0 + + uniforms.pixelRatio = points.pixelRatio + + //Draw interior + points.vao.draw(gl.TRIANGLES, points.vertexCount) + + //Draw edges + if(points.lineWidth > 0) { + gl.lineWidth(points.lineWidth) + points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) + } + } + + drawProject(pshader, points, camera, transparent, forceDraw) + + points.vao.unbind() +} + +proto.draw = function(camera) { + var shader = this.useOrtho ? this.orthoShader : this.shader + drawFull(shader, this.projectShader, this, camera, false, false) +} + +proto.drawTransparent = function(camera) { + var shader = this.useOrtho ? this.orthoShader : this.shader + drawFull(shader, this.projectShader, this, camera, true, false) +} + +proto.drawPick = function(camera) { + var shader = this.useOrtho ? this.pickOrthoShader : this.pickPerspectiveShader + drawFull(shader, this.pickProjectShader, this, camera, false, true) +} + +proto.pick = function(selected) { + if(!selected) { + return null + } + if(selected.id !== this.pickId) { + return null + } + var x = selected.value[2] + (selected.value[1]<<8) + (selected.value[0]<<16) + if(x >= this.pointCount || x < 0) { + return null + } + + //Unpack result + var coord = this.points[x] + var result = this._selectResult + result.index = x + for(var i=0; i<3; ++i) { + result.position[i] = result.dataCoordinate[i] = coord[i] + } + return result +} + +proto.highlight = function(selection) { + if(!selection) { + this.highlightId = [1,1,1,1] + } else { + var pointId = selection.index + var a0 = pointId &0xff + var a1 = (pointId>>8) &0xff + var a2 = (pointId>>16)&0xff + this.highlightId = [a0/255.0, a1/255.0, a2/255.0, 0] + } +} + +function get_glyphData(glyphs, index, font) { + var str + + // use the data if presented in an array + if(Array.isArray(glyphs)) { + if(index < glyphs.length) { + str = glyphs[index] + } else { + str = undefined + } + } else { + str = glyphs + } + + str = getSimpleString(str) // this would handle undefined cases + + var visible = true + if(isAllBlank(str)) { + str = '▼' // Note: this special character may have minimum number of surfaces + visible = false + } + + var glyph = getGlyph(str, font) + + return { mesh:glyph[0], + lines:glyph[1], + bounds:glyph[2], + visible:visible }; +} + + + +proto.update = function(options) { + + options = options || {} + + if('perspective' in options) { + this.useOrtho = !options.perspective + } + if('orthographic' in options) { + this.useOrtho = !!options.orthographic + } + if('lineWidth' in options) { + this.lineWidth = options.lineWidth + } + if('project' in options) { + if(Array.isArray(options.project)) { + this.axesProject = options.project + } else { + var v = !!options.project + this.axesProject = [v,v,v] + } + } + if('projectScale' in options) { + if(Array.isArray(options.projectScale)) { + this.projectScale = options.projectScale.slice() + } else { + var s = +options.projectScale + this.projectScale = [s,s,s] + } + } + if('projectOpacity' in options) { + if(Array.isArray(options.projectOpacity)) { + this.projectOpacity = options.projectOpacity.slice() + } else { + var s = +options.projectOpacity + this.projectOpacity = [s,s,s] + } + } + if('opacity' in options) { + this.opacity = options.opacity + } + + //Set dirty flag + this.dirty = true + + //Create new buffers + var points = options.position + + //Text font + var font = options.font || 'normal' + var alignment = options.alignment || [0,0] + + //Bounds + var lowerBound = [ Infinity, Infinity, Infinity] + var upperBound = [-Infinity,-Infinity,-Infinity] + + //Unpack options + var glyphs = options.glyph + var colors = options.color + var sizes = options.size + var angles = options.angle + var lineColors = options.lineColor + + //Picking geometry + var pickCounter = -1 + + //First do pass to compute buffer sizes + var triVertexCount = 0 + var lineVertexCount = 0 + + var numPoints = 0; + + if(points.length) { + + //Count number of points and buffer size + numPoints = points.length + + count_loop: + for(var i=0; i 0) { + var triOffset = 0 + var lineOffset = triVertexCount + var color = [0,0,0,1] + var lineColor = [0,0,0,1] + + var isColorArray = Array.isArray(colors) && Array.isArray(colors[0]) + var isLineColorArray = Array.isArray(lineColors) && Array.isArray(lineColors[0]) + + fill_loop: + for(var i=0; i 0) { + textOffset[j] *= (1-glyphBounds[0][j]) + } else if(alignment[j] < 0) { + textOffset[j] *= (1+glyphBounds[1][j]) + } + } + + //Write out inner marker + var cells = glyphMesh.cells || [] + var verts = glyphMesh.positions || [] + + for(var j=0; j 0) { + + //Draw border + var w = lineWidth * pixelRatio + boxes.drawBox(loX-w, loY-w, hiX+w, loY+w, borderColor) + boxes.drawBox(loX-w, hiY-w, hiX+w, hiY+w, borderColor) + boxes.drawBox(loX-w, loY-w, loX+w, hiY+w, borderColor) + boxes.drawBox(hiX-w, loY-w, hiX+w, hiY+w, borderColor) + } +} + +proto.update = function(options) { + options = options || {} + + this.innerFill = !!options.innerFill + this.outerFill = !!options.outerFill + this.innerColor = (options.innerColor || [0,0,0,0.5]).slice() + this.outerColor = (options.outerColor || [0,0,0,0.5]).slice() + this.borderColor = (options.borderColor || [0,0,0,1]).slice() + this.borderWidth = options.borderWidth || 0 + this.selectBox = (options.selectBox || this.selectBox).slice() +} + +proto.dispose = function() { + this.boxBuffer.dispose() + this.boxShader.dispose() + this.plot.removeOverlay(this) +} + +function createSelectBox(plot, options) { + var gl = plot.gl + var buffer = createBuffer(gl, [ + 0, 0, + 0, 1, + 1, 0, + 1, 1 ]) + var shader = createShader(gl, SHADERS.boxVertex, SHADERS.boxFragment) + var selectBox = new SelectBox(plot, buffer, shader) + selectBox.update(options) + plot.addOverlay(selectBox) + return selectBox +} + +},{"./lib/shaders":285,"gl-buffer":230,"gl-shader":288}],287:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createSelectBuffer + +var createFBO = _dereq_('gl-fbo') +var pool = _dereq_('typedarray-pool') +var ndarray = _dereq_('ndarray') + +var nextPow2 = _dereq_('bit-twiddle').nextPow2 + +var selectRange = _dereq_('cwise/lib/wrapper')({"args":["array",{"offset":[0,0,1],"array":0},{"offset":[0,0,2],"array":0},{"offset":[0,0,3],"array":0},"scalar","scalar","index"],"pre":{"body":"{this_closestD2=1e8,this_closestX=-1,this_closestY=-1}","args":[],"thisVars":["this_closestD2","this_closestX","this_closestY"],"localVars":[]},"body":{"body":"{if(_inline_16_arg0_<255||_inline_16_arg1_<255||_inline_16_arg2_<255||_inline_16_arg3_<255){var _inline_16_l=_inline_16_arg4_-_inline_16_arg6_[0],_inline_16_a=_inline_16_arg5_-_inline_16_arg6_[1],_inline_16_f=_inline_16_l*_inline_16_l+_inline_16_a*_inline_16_a;_inline_16_f this.buffer.length) { + pool.free(this.buffer) + var buffer = this.buffer = pool.mallocUint8(nextPow2(r*c*4)) + for(var i=0; i oldAttribCount) { + for(i = oldAttribCount; i < newAttribCount; i++) { + this.gl.enableVertexAttribArray(i) + } + } else if(oldAttribCount > newAttribCount) { + for(i = newAttribCount; i < oldAttribCount; i++) { + this.gl.disableVertexAttribArray(i) + } + } + + this.gl.lastAttribCount = newAttribCount + + this.gl.useProgram(this.program) +} + +proto.dispose = function() { + + // disabling vertex attributes so new shader starts with zero + // and it's also useful if all shaders are disposed but the + // gl context is reused for subsequent replotting + var oldAttribCount = this.gl.lastAttribCount + for (var i = 0; i < oldAttribCount; i++) { + this.gl.disableVertexAttribArray(i) + } + this.gl.lastAttribCount = 0 + + if(this._fref) { + this._fref.dispose() + } + if(this._vref) { + this._vref.dispose() + } + this.attributes = + this.types = + this.vertShader = + this.fragShader = + this.program = + this._relink = + this._fref = + this._vref = null +} + +function compareAttributes(a, b) { + if(a.name < b.name) { + return -1 + } + return 1 +} + +//Update export hook for glslify-live +proto.update = function( + vertSource + , fragSource + , uniforms + , attributes) { + + //If only one object passed, assume glslify style output + if(!fragSource || arguments.length === 1) { + var obj = vertSource + vertSource = obj.vertex + fragSource = obj.fragment + uniforms = obj.uniforms + attributes = obj.attributes + } + + var wrapper = this + var gl = wrapper.gl + + //Compile vertex and fragment shaders + var pvref = wrapper._vref + wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource) + if(pvref) { + pvref.dispose() + } + wrapper.vertShader = wrapper._vref.shader + var pfref = this._fref + wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource) + if(pfref) { + pfref.dispose() + } + wrapper.fragShader = wrapper._fref.shader + + //If uniforms/attributes is not specified, use RT reflection + if(!uniforms || !attributes) { + + //Create initial test program + var testProgram = gl.createProgram() + gl.attachShader(testProgram, wrapper.fragShader) + gl.attachShader(testProgram, wrapper.vertShader) + gl.linkProgram(testProgram) + if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) { + var errLog = gl.getProgramInfoLog(testProgram) + throw new GLError(errLog, 'Error linking program:' + errLog) + } + + //Load data from runtime + uniforms = uniforms || runtime.uniforms(gl, testProgram) + attributes = attributes || runtime.attributes(gl, testProgram) + + //Release test program + gl.deleteProgram(testProgram) + } + + //Sort attributes lexicographically + // overrides undefined WebGL behavior for attribute locations + attributes = attributes.slice() + attributes.sort(compareAttributes) + + //Convert attribute types, read out locations + var attributeUnpacked = [] + var attributeNames = [] + var attributeLocations = [] + var i + for(i=0; i= 0) { + var size = attr.type.charAt(attr.type.length-1)|0 + var locVector = new Array(size) + for(var j=0; j= 0) { + curLocation += 1 + } + attributeLocations[i] = curLocation + } + } + + //Rebuild program and recompute all uniform locations + var uniformLocations = new Array(uniforms.length) + function relink() { + wrapper.program = shaderCache.program( + gl + , wrapper._vref + , wrapper._fref + , attributeNames + , attributeLocations) + + for(var i=0; i= 0) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) + } + addVectorAttribute( + gl + , wrapper + , locs[0] + , locations + , d + , obj + , name) + } else if(type.indexOf('mat') >= 0) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) + } + addMatrixAttribute( + gl + , wrapper + , locs + , locations + , d + , obj + , name) + } else { + throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type) + } + break + } + } + return obj +} + +},{"./GLError":289}],291:[function(_dereq_,module,exports){ +'use strict' + +var coallesceUniforms = _dereq_('./reflect') +var GLError = _dereq_("./GLError") + +module.exports = createUniformWrapper + +//Binds a function and returns a value +function identity(x) { + var c = new Function('y', 'return function(){return y}') + return c(x) +} + +function makeVector(length, fill) { + var result = new Array(length) + for(var i=0; i 4) { + throw new GLError('', 'Invalid data type') + } + switch(type.charAt(0)) { + case 'b': + case 'i': + return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')' + case 'v': + return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')' + default: + throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + type) + } + } else if(type.indexOf('mat') === 0 && type.length === 4) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) + } + return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')' + } else { + throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + } + break + } + } + + function enumerateIndices(prefix, type) { + if(typeof type !== 'object') { + return [ [prefix, type] ] + } + var indices = [] + for(var id in type) { + var prop = type[id] + var tprefix = prefix + if(parseInt(id) + '' === id) { + tprefix += '[' + id + ']' + } else { + tprefix += '.' + id + } + if(typeof prop === 'object') { + indices.push.apply(indices, enumerateIndices(tprefix, prop)) + } else { + indices.push([tprefix, prop]) + } + } + return indices + } + + function makeSetter(type) { + var code = [ 'return function updateProperty(obj){' ] + var indices = enumerateIndices('', type) + for(var i=0; i 4) { + throw new GLError('', 'Invalid data type') + } + if(type.charAt(0) === 'b') { + return makeVector(d, false) + } + return makeVector(d, 0) + } else if(type.indexOf('mat') === 0 && type.length === 4) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) + } + return makeVector(d*d, 0) + } else { + throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + } + break + } + } + + function storeProperty(obj, prop, type) { + if(typeof type === 'object') { + var child = processObject(type) + Object.defineProperty(obj, prop, { + get: identity(child), + set: makeSetter(type), + enumerable: true, + configurable: false + }) + } else { + if(locations[type]) { + Object.defineProperty(obj, prop, { + get: makeGetter(type), + set: makeSetter(type), + enumerable: true, + configurable: false + }) + } else { + obj[prop] = defaultValue(uniforms[type].type) + } + } + } + + function processObject(obj) { + var result + if(Array.isArray(obj)) { + result = new Array(obj.length) + for(var i=0; i 1) { + if(!(x[0] in o)) { + o[x[0]] = [] + } + o = o[x[0]] + for(var k=1; k 1) { + for(var j=0; j 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float tubeScale;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n normal = normalize(normal * inverse(mat3(model)));\n\n gl_Position = projection * view * tubePosition;\n f_color = color;\n f_normal = normal;\n f_data = tubePosition.xyz;\n f_position = position.xyz;\n f_eyeDirection = eyePosition - tubePosition.xyz;\n f_lightDirection = lightPosition - tubePosition.xyz;\n f_uv = uv;\n}\n"]) +var triFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}"]) +var pickVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform float tubeScale;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n gl_Position = projection * view * tubePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]) +var pickFragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) + +exports.meshShader = { + vertex: triVertSrc, + fragment: triFragSrc, + attributes: [ + {name: 'position', type: 'vec4'}, + {name: 'normal', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'}, + {name: 'vector', type: 'vec4'} + ] +} +exports.pickShader = { + vertex: pickVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec4'}, + {name: 'id', type: 'vec4'}, + {name: 'vector', type: 'vec4'} + ] +} + +},{"glslify":392}],300:[function(_dereq_,module,exports){ +'use strict' + +var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small +var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; + +var createShader = _dereq_('gl-shader') +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createTexture = _dereq_('gl-texture2d') +var normals = _dereq_('normals') +var multiply = _dereq_('gl-mat4/multiply') +var invert = _dereq_('gl-mat4/invert') +var ndarray = _dereq_('ndarray') +var colormap = _dereq_('colormap') +var getContour = _dereq_('simplicial-complex-contour') +var pool = _dereq_('typedarray-pool') +var shaders = _dereq_('./shaders') +var closestPoint = _dereq_('./closest-point') + +var meshShader = shaders.meshShader +var pickShader = shaders.pickShader + +var identityMatrix = [ + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +function SimplicialMesh(gl + , texture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleVectors + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) { + + this.gl = gl + this.cells = [] + this.positions = [] + this.intensity = [] + this.texture = texture + this.dirty = true + + this.triShader = triShader + this.lineShader = lineShader + this.pointShader = pointShader + this.pickShader = pickShader + this.pointPickShader = pointPickShader + this.contourShader = contourShader + + this.trianglePositions = trianglePositions + this.triangleVectors = triangleVectors + this.triangleColors = triangleColors + this.triangleNormals = triangleNormals + this.triangleUVs = triangleUVs + this.triangleIds = triangleIds + this.triangleVAO = triangleVAO + this.triangleCount = 0 + + this.lineWidth = 1 + this.edgePositions = edgePositions + this.edgeColors = edgeColors + this.edgeUVs = edgeUVs + this.edgeIds = edgeIds + this.edgeVAO = edgeVAO + this.edgeCount = 0 + + this.pointPositions = pointPositions + this.pointColors = pointColors + this.pointUVs = pointUVs + this.pointSizes = pointSizes + this.pointIds = pointIds + this.pointVAO = pointVAO + this.pointCount = 0 + + this.contourLineWidth = 1 + this.contourPositions = contourPositions + this.contourVAO = contourVAO + this.contourCount = 0 + this.contourColor = [0,0,0] + this.contourEnable = false + + this.pickId = 1 + this.bounds = [ + [ Infinity, Infinity, Infinity], + [-Infinity,-Infinity,-Infinity] ] + this.clipBounds = [ + [-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity] ] + + this.lightPosition = [1e5, 1e5, 0] + this.ambientLight = 0.8 + this.diffuseLight = 0.8 + this.specularLight = 2.0 + this.roughness = 0.5 + this.fresnel = 1.5 + + this.opacity = 1.0 + + this.tubeScale = 1.0 + + this._model = identityMatrix + this._view = identityMatrix + this._projection = identityMatrix + this._resolution = [1,1] +} + +var proto = SimplicialMesh.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 +} + +proto.isTransparent = function() { + return this.opacity < 1 +} + +proto.pickSlots = 1 + +proto.setPickBase = function(id) { + this.pickId = id +} + +function genColormap(param) { + var colors = colormap({ + colormap: param + , nshades: 256 + , format: 'rgba' + }) + + var result = new Uint8Array(256*4) + for(var i=0; i<256; ++i) { + var c = colors[i] + for(var j=0; j<3; ++j) { + result[4*i+j] = c[j] + } + result[4*i+3] = c[3]*255 + } + + return ndarray(result, [256,256,4], [4,0,1]) +} + +function unpackIntensity(cells, numVerts, cellIntensity) { + var result = new Array(numVerts) + for(var i=0; i 0) { + var shader = this.triShader + shader.bind() + shader.uniforms = uniforms + + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0 && this.lineWidth > 0) { + var shader = this.lineShader + shader.bind() + shader.uniforms = uniforms + + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } + + if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { + var shader = this.contourShader + shader.bind() + shader.uniforms = uniforms + + this.contourVAO.bind() + gl.drawArrays(gl.LINES, 0, this.contourCount) + this.contourVAO.unbind() + } +} + +proto.drawPick = function(params) { + params = params || {} + + var gl = this.gl + + var model = params.model || identityMatrix + var view = params.view || identityMatrix + var projection = params.projection || identityMatrix + + var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] + for(var i=0; i<3; ++i) { + clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) + clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) + } + + //Save camera parameters + this._model = [].slice.call(model) + this._view = [].slice.call(view) + this._projection = [].slice.call(projection) + this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] + + var uniforms = { + model: model, + view: view, + projection: projection, + clipBounds: clipBounds, + + tubeScale: this.tubeScale, + + pickId: this.pickId / 255.0, + } + + var shader = this.pickShader + shader.bind() + shader.uniforms = uniforms + + if(this.triangleCount > 0) { + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0) { + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } + + if(this.pointCount > 0) { + var shader = this.pointPickShader + shader.bind() + shader.uniforms = uniforms + + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } +} + + +proto.pick = function(pickData) { + if(!pickData) { + return null + } + if(pickData.id !== this.pickId) { + return null + } + + var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] + var cell = this.cells[cellId] + + var pos = this.positions[cell[1]].slice(0, 3) + var intensity = this.intensity[cell[1]] + var velocity = this.vectors[cell[1]].slice(0, 3) + var divergence = this.vectors[cell[1]][3] + + return { + index: cellId, + position: pos, + intensity: intensity, + velocity: velocity, + divergence: divergence, + dataCoordinate: pos + } +} + + +proto.dispose = function() { + this.texture.dispose() + + this.triShader.dispose() + // this.lineShader.dispose() + // this.pointShader.dispose() + this.pickShader.dispose() + // this.pointPickShader.dispose() + + this.triangleVAO.dispose() + this.trianglePositions.dispose() + this.triangleVectors.dispose() + this.triangleColors.dispose() + this.triangleUVs.dispose() + this.triangleNormals.dispose() + this.triangleIds.dispose() + + this.edgeVAO.dispose() + this.edgePositions.dispose() + this.edgeColors.dispose() + this.edgeUVs.dispose() + this.edgeIds.dispose() + + this.pointVAO.dispose() + this.pointPositions.dispose() + this.pointColors.dispose() + this.pointUVs.dispose() + this.pointSizes.dispose() + this.pointIds.dispose() + + this.contourVAO.dispose() + this.contourPositions.dispose() + // this.contourShader.dispose() +} + +function createMeshShader(gl) { + var shader = createShader(gl, meshShader.vertex, meshShader.fragment, null, meshShader.attributes) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + shader.attributes.vector.location = 5 + return shader +} + +function createWireShader(gl) { + var shader = createShader(gl, wireShader.vertex, wireShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + return shader +} + +function createPointShader(gl) { + var shader = createShader(gl, pointShader.vertex, pointShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.color.location = 2 + shader.attributes.uv.location = 3 + shader.attributes.pointSize.location = 4 + return shader +} + +function createPickShader(gl) { + var shader = createShader(gl, pickShader.vertex, pickShader.fragment, null, pickShader.attributes) + shader.attributes.position.location = 0 + shader.attributes.id.location = 1 + shader.attributes.vector.location = 5 + return shader +} + +function createPointPickShader(gl) { + var shader = createShader(gl, pointPickShader.vertex, pointPickShader.fragment) + shader.attributes.position.location = 0 + shader.attributes.id.location = 1 + shader.attributes.pointSize.location = 4 + return shader +} + +function createContourShader(gl) { + var shader = createShader(gl, contourShader.vertex, contourShader.fragment) + shader.attributes.position.location = 0 + return shader +} + +function createSimplicialMesh(gl, params) { + if (arguments.length === 1) { + params = gl; + gl = params.gl; + } + + var triShader = params.triShader || createMeshShader(gl) + var lineShader = null; //createWireShader(gl) + var pointShader = null; //createPointShader(gl) + var pickShader = createPickShader(gl) + var pointPickShader = null; //createPointPickShader(gl) + var contourShader = null; //createContourShader(gl) + + var meshTexture = createTexture(gl, + ndarray(new Uint8Array([255,255,255,255]), [1,1,4])) + meshTexture.generateMipmap() + meshTexture.minFilter = gl.LINEAR_MIPMAP_LINEAR + meshTexture.magFilter = gl.LINEAR + + var trianglePositions = createBuffer(gl) + var triangleVectors = createBuffer(gl) + var triangleColors = createBuffer(gl) + var triangleUVs = createBuffer(gl) + var triangleNormals = createBuffer(gl) + var triangleIds = createBuffer(gl) + var triangleVAO = createVAO(gl, [ + { buffer: trianglePositions, + type: gl.FLOAT, + size: 4 + }, + { buffer: triangleIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: triangleColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: triangleUVs, + type: gl.FLOAT, + size: 2 + }, + { buffer: triangleNormals, + type: gl.FLOAT, + size: 3 + }, + { buffer: triangleVectors, + type: gl.FLOAT, + size: 4 + } + ]) + + var edgePositions = createBuffer(gl) + var edgeColors = createBuffer(gl) + var edgeUVs = createBuffer(gl) + var edgeIds = createBuffer(gl) + var edgeVAO = createVAO(gl, [ + { buffer: edgePositions, + type: gl.FLOAT, + size: 3 + }, + { buffer: edgeIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: edgeColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: edgeUVs, + type: gl.FLOAT, + size: 2 + } + ]) + + var pointPositions = createBuffer(gl) + var pointColors = createBuffer(gl) + var pointUVs = createBuffer(gl) + var pointSizes = createBuffer(gl) + var pointIds = createBuffer(gl) + var pointVAO = createVAO(gl, [ + { buffer: pointPositions, + type: gl.FLOAT, + size: 3 + }, + { buffer: pointIds, + type: gl.UNSIGNED_BYTE, + size: 4, + normalized: true + }, + { buffer: pointColors, + type: gl.FLOAT, + size: 4 + }, + { buffer: pointUVs, + type: gl.FLOAT, + size: 2 + }, + { buffer: pointSizes, + type: gl.FLOAT, + size: 1 + } + ]) + + var contourPositions = createBuffer(gl) + var contourVAO = createVAO(gl, [ + { buffer: contourPositions, + type: gl.FLOAT, + size: 3 + }]) + + var mesh = new SimplicialMesh(gl + , meshTexture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleVectors + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) + + mesh.update(params) + + return mesh +} + +module.exports = createSimplicialMesh + +},{"./closest-point":298,"./shaders":299,"colormap":114,"gl-buffer":230,"gl-mat4/invert":254,"gl-mat4/multiply":256,"gl-shader":288,"gl-texture2d":305,"gl-vao":310,"ndarray":433,"normals":436,"simplicial-complex-contour":494,"typedarray-pool":522}],301:[function(_dereq_,module,exports){ +"use strict"; + +var vec3 = _dereq_('gl-vec3'); +var vec4 = _dereq_('gl-vec4'); + +var streamToTube = function(stream, maxDivergence, minDistance, maxNorm) { + var points = stream.points; + var velocities = stream.velocities; + var divergences = stream.divergences; + + var p, fwd, r, u, v, up; + up = vec3.set(vec3.create(), 0, 1, 0); + u = vec3.create(); + v = vec3.create(); + var p2 = vec3.create(); + + var verts = []; + var faces = []; + var vectors = []; + var previousVerts = []; + var currentVerts = []; + var intensities = []; + var previousIntensity = 0; + var currentIntensity = 0; + var currentVector = vec4.create(); + var previousVector = vec4.create(); + + var facets = 8; + + for (var i = 0; i < points.length; i++) { + p = points[i]; + fwd = velocities[i]; + r = divergences[i]; + if (maxDivergence === 0) { + r = minDistance * 0.05; + } + currentIntensity = vec3.length(fwd) / maxNorm; + currentVector = vec4.create(); + vec3.copy(currentVector, fwd); + currentVector[3] = r; + + for (var a = 0; a < facets; a++) { + currentVerts[a] = [p[0], p[1], p[2], a]; + } + if (previousVerts.length > 0) { + for (var a = 0; a < facets; a++) { + var a1 = (a+1) % facets; + verts.push( + previousVerts[a], + currentVerts[a], + currentVerts[a1], + + currentVerts[a1], + previousVerts[a1], + previousVerts[a] + ); + vectors.push( + previousVector, + currentVector, + currentVector, + + currentVector, + previousVector, + previousVector + ); + intensities.push( + previousIntensity, + currentIntensity, + currentIntensity, + + currentIntensity, + previousIntensity, + previousIntensity + ); + faces.push( + [verts.length-6, verts.length-5, verts.length-4], + [verts.length-3, verts.length-2, verts.length-1] + ); + } + } + var tmp = previousVerts; + previousVerts = currentVerts; + currentVerts = tmp; + tmp = previousVector; + previousVector = currentVector; + currentVector = tmp; + tmp = previousIntensity; + previousIntensity = currentIntensity; + currentIntensity = tmp; + } + return { + positions: verts, + cells: faces, + vectors: vectors, + vertexIntensity: intensities + }; + +}; + +var createTubes = function(streams, colormap, maxDivergence, minDistance) { + + var maxNorm = 0; + for (var i=0; i maxNorm) { + maxNorm = norm; + } + } + } + + var tubes = streams.map(function(s) { + return streamToTube(s, maxDivergence, minDistance, maxNorm); + }); + + var positions = []; + var cells = []; + var vectors = []; + var vertexIntensity = []; + for (var i=0; i < tubes.length; i++) { + var tube = tubes[i]; + var offset = positions.length; + positions = positions.concat(tube.positions); + vectors = vectors.concat(tube.vectors); + vertexIntensity = vertexIntensity.concat(tube.vertexIntensity); + for (var j=0; j v) return i-1; + } + return i; +}; + +var tmp = vec3.create(); +var tmp2 = vec3.create(); + +var clamp = function(v, min, max) { + return v < min ? min : (v > max ? max : v); +}; + +var sampleMeshgrid = function(point, array, meshgrid, clampOverflow) { + var x = point[0]; + var y = point[1]; + var z = point[2]; + + var w = meshgrid[0].length; + var h = meshgrid[1].length; + var d = meshgrid[2].length; + + // Find the index of the nearest smaller value in the meshgrid for each coordinate of (x,y,z). + // The nearest smaller value index for x is the index x0 such that + // meshgrid[0][x0] < x and for all x1 > x0, meshgrid[0][x1] >= x. + var x0 = findLastSmallerIndex(meshgrid[0], x); + var y0 = findLastSmallerIndex(meshgrid[1], y); + var z0 = findLastSmallerIndex(meshgrid[2], z); + + // Get the nearest larger meshgrid value indices. + // From the above "nearest smaller value", we know that + // meshgrid[0][x0] < x + // meshgrid[0][x0+1] >= x + var x1 = x0 + 1; + var y1 = y0 + 1; + var z1 = z0 + 1; + + if (meshgrid[0][x0] === x) x1 = x0; + if (meshgrid[1][y0] === y) y1 = y0; + if (meshgrid[2][z0] === z) z1 = z0; + + if (clampOverflow) { + x0 = clamp(x0, 0, w-1); + x1 = clamp(x1, 0, w-1); + y0 = clamp(y0, 0, h-1); + y1 = clamp(y1, 0, h-1); + z0 = clamp(z0, 0, d-1); + z1 = clamp(z1, 0, d-1); + } + + // Reject points outside the meshgrid, return a zero vector. + if (x0 < 0 || y0 < 0 || z0 < 0 || x1 >= w || y1 >= h || z1 >= d) { + return vec3.create(); + } + + // Normalize point coordinates to 0..1 scaling factor between x0 and x1. + var xf = (x - meshgrid[0][x0]) / (meshgrid[0][x1] - meshgrid[0][x0]); + var yf = (y - meshgrid[1][y0]) / (meshgrid[1][y1] - meshgrid[1][y0]); + var zf = (z - meshgrid[2][z0]) / (meshgrid[2][z1] - meshgrid[2][z0]); + + if (xf < 0 || xf > 1 || isNaN(xf)) xf = 0; + if (yf < 0 || yf > 1 || isNaN(yf)) yf = 0; + if (zf < 0 || zf > 1 || isNaN(zf)) zf = 0; + + var z0off = z0*w*h; + var z1off = z1*w*h; + + var y0off = y0*w; + var y1off = y1*w; + + var x0off = x0; + var x1off = x1; + + // Sample data array around the (x,y,z) point. + // vZYX = array[zZoff + yYoff + xXoff] + var v000 = array[y0off + z0off + x0off]; + var v001 = array[y0off + z0off + x1off]; + var v010 = array[y1off + z0off + x0off]; + var v011 = array[y1off + z0off + x1off]; + var v100 = array[y0off + z1off + x0off]; + var v101 = array[y0off + z1off + x1off]; + var v110 = array[y1off + z1off + x0off]; + var v111 = array[y1off + z1off + x1off]; + + var result = vec3.create(); + + // Average samples according to distance to point. + vec3.lerp(result, v000, v001, xf); + vec3.lerp(tmp, v010, v011, xf); + vec3.lerp(result, result, tmp, yf); + vec3.lerp(tmp, v100, v101, xf); + vec3.lerp(tmp2, v110, v111, xf); + vec3.lerp(tmp, tmp, tmp2, yf); + vec3.lerp(result, result, tmp, zf); + + return result; +}; + + +var vabs = function(dst, v) { + var x = v[0]; + var y = v[1]; + var z = v[2]; + dst[0] = x >= 0 ? x : -x; + dst[1] = y >= 0 ? y : -y; + dst[2] = z >= 0 ? z : -z; + return dst; +}; + +var findMinSeparation = function(xs) { + var minSeparation = 1/0; + xs.sort(function(a, b) { return a - b; }); + for (var i=1; i= minX && x <= maxX && + y >= minY && y <= maxY && + z >= minZ && z <= maxZ + ); + }; + + var boundsSize = vec3.distance(bounds[0], bounds[1]); + var maxStepSize = 10 * boundsSize / maxLength; + var maxStepSizeSq = maxStepSize * maxStepSize; + + var minDistance = 1; + var maxDivergence = 0; // For component-wise divergence vec3.create(); + var tmp = vec3.create(); + + if (positions.length >= 2) { + minDistance = calculateMinPositionDistance(positions); + } + + for (var i = 0; i < positions.length; i++) { + var p = vec3.create(); + vec3.copy(p, positions[i]); + + var stream = [p]; + var velocities = []; + var v = vectorField.getVelocity(p); + var op = p; + velocities.push(v); + + var divergences = []; + + var dv = vectorField.getDivergence(p, v); + var dvLength = vec3.length(dv); + if (dvLength > maxDivergence && !isNaN(dvLength) && isFinite(dvLength)) { + maxDivergence = dvLength; + } + // In case we need to do component-wise divergence visualization + // vec3.max(maxDivergence, maxDivergence, vabs(tmp, dv)); + divergences.push(dvLength); + + streams.push({points: stream, velocities: velocities, divergences: divergences}); + + var j = 0; + + while (j < maxLength * 100 && stream.length < maxLength && inBounds(bounds, p)) { + j++; + var np = vec3.clone(v); + var sqLen = vec3.squaredLength(np); + if (sqLen === 0) { + break; + } else if (sqLen > maxStepSizeSq) { + vec3.scale(np, np, maxStepSize / Math.sqrt(sqLen)); + } + vec3.add(np, np, p); + + v = vectorField.getVelocity(np); + + if (vec3.squaredDistance(op, np) - maxStepSizeSq > -0.0001 * maxStepSizeSq) { + stream.push(np); + op = np; + velocities.push(v); + var dv = vectorField.getDivergence(np, v); + var dvLength = vec3.length(dv); + if (dvLength > maxDivergence && !isNaN(dvLength) && isFinite(dvLength)) { + maxDivergence = dvLength; + } + // In case we need to do component-wise divergence visualization + //vec3.max(maxDivergence, maxDivergence, vabs(tmp, dv)); + divergences.push(dvLength); + } + + p = np; + } + } + + // Replace NaNs and Infinities with non-NaN, finite maxDivergence + for (var i=0; i max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 lowerBound, upperBound;\nuniform float contourTint;\nuniform vec4 contourColor;\nuniform sampler2D colormap;\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform float vertexColor;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec3 N = normalize(surfaceNormal);\n vec3 V = normalize(eyeDirection);\n vec3 L = normalize(lightDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = max(beckmannSpecular(L, V, N, roughness), 0.);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n //decide how to interpolate color — in vertex or in fragment\n vec4 surfaceColor = step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) + step(.5, vertexColor) * vColor;\n\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = mix(litColor, contourColor, contourTint) * opacity;\n}\n"]) +var contourVertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec4 uv;\nattribute float f;\n\nuniform mat3 permutation;\nuniform mat4 model, view, projection;\nuniform float height, zOffset;\nuniform sampler2D colormap;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n vec3 dataCoordinate = permutation * vec3(uv.xy, height);\n vec4 worldPosition = model * vec4(dataCoordinate, 1.0);\n\n vec4 clipPosition = projection * view * worldPosition;\n clipPosition.z = clipPosition.z + zOffset;\n\n gl_Position = clipPosition;\n value = f;\n kill = -1.0;\n worldCoordinate = dataCoordinate;\n planeCoordinate = uv.zw;\n\n vColor = texture2D(colormap, vec2(value, value));\n\n //Don't do lighting for contours\n surfaceNormal = vec3(1,0,0);\n eyeDirection = vec3(0,1,0);\n lightDirection = vec3(0,0,1);\n}\n"]) +var pickSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec2 shape;\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 surfaceNormal;\n\nvec2 splitFloat(float v) {\n float vh = 255.0 * v;\n float upper = floor(vh);\n float lower = fract(vh);\n return vec2(upper / 255.0, floor(lower * 16.0) / 16.0);\n}\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec2 ux = splitFloat(planeCoordinate.x / shape.x);\n vec2 uy = splitFloat(planeCoordinate.y / shape.y);\n gl_FragColor = vec4(pickId, ux.x, uy.x, ux.y + (uy.y/16.0));\n}\n"]) + +exports.createShader = function (gl) { + var shader = createShader(gl, vertSrc, fragSrc, null, [ + {name: 'uv', type: 'vec4'}, + {name: 'f', type: 'vec3'}, + {name: 'normal', type: 'vec3'} + ]) + shader.attributes.uv.location = 0 + shader.attributes.f.location = 1 + shader.attributes.normal.location = 2 + return shader +} +exports.createPickShader = function (gl) { + var shader = createShader(gl, vertSrc, pickSrc, null, [ + {name: 'uv', type: 'vec4'}, + {name: 'f', type: 'vec3'}, + {name: 'normal', type: 'vec3'} + ]) + shader.attributes.uv.location = 0 + shader.attributes.f.location = 1 + shader.attributes.normal.location = 2 + return shader +} +exports.createContourShader = function (gl) { + var shader = createShader(gl, contourVertSrc, fragSrc, null, [ + {name: 'uv', type: 'vec4'}, + {name: 'f', type: 'float'} + ]) + shader.attributes.uv.location = 0 + shader.attributes.f.location = 1 + return shader +} +exports.createPickContourShader = function (gl) { + var shader = createShader(gl, contourVertSrc, pickSrc, null, [ + {name: 'uv', type: 'vec4'}, + {name: 'f', type: 'float'} + ]) + shader.attributes.uv.location = 0 + shader.attributes.f.location = 1 + return shader +} + +},{"gl-shader":288,"glslify":392}],303:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createSurfacePlot + +var bits = _dereq_('bit-twiddle') +var createBuffer = _dereq_('gl-buffer') +var createVAO = _dereq_('gl-vao') +var createTexture = _dereq_('gl-texture2d') +var pool = _dereq_('typedarray-pool') +var colormap = _dereq_('colormap') +var ops = _dereq_('ndarray-ops') +var pack = _dereq_('ndarray-pack') +var ndarray = _dereq_('ndarray') +var surfaceNets = _dereq_('surface-nets') +var multiply = _dereq_('gl-mat4/multiply') +var invert = _dereq_('gl-mat4/invert') +var bsearch = _dereq_('binary-search-bounds') +var gradient = _dereq_('ndarray-gradient') +var shaders = _dereq_('./lib/shaders') + +var createShader = shaders.createShader +var createContourShader = shaders.createContourShader +var createPickShader = shaders.createPickShader +var createPickContourShader = shaders.createPickContourShader + +var SURFACE_VERTEX_SIZE = 4 * (4 + 3 + 3) + +var IDENTITY = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ] + +var QUAD = [ + [0, 0], + [0, 1], + [1, 0], + [1, 1], + [1, 0], + [0, 1] +] + +var PERMUTATIONS = [ + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0] +] + +;(function () { + for (var i = 0; i < 3; ++i) { + var p = PERMUTATIONS[i] + var u = (i + 1) % 3 + var v = (i + 2) % 3 + p[u + 0] = 1 + p[v + 3] = 1 + p[i + 6] = 1 + } +})() + +function SurfacePickResult (position, index, uv, level, dataCoordinate) { + this.position = position + this.index = index + this.uv = uv + this.level = level + this.dataCoordinate = dataCoordinate +} + +var N_COLORS = 256 + +function genColormap (name) { + var x = pack([colormap({ + colormap: name, + nshades: N_COLORS, + format: 'rgba' + }).map(function (c) { + return [c[0], c[1], c[2], 255 * c[3]] + })]) + ops.divseq(x, 255.0) + return x +} + +function SurfacePlot ( + gl, + shape, + bounds, + shader, + pickShader, + coordinates, + vao, + colorMap, + contourShader, + contourPickShader, + contourBuffer, + contourVAO, + dynamicBuffer, + dynamicVAO) { + this.gl = gl + this.shape = shape + this.bounds = bounds + this.intensityBounds = []; + + this._shader = shader + this._pickShader = pickShader + this._coordinateBuffer = coordinates + this._vao = vao + this._colorMap = colorMap + + this._contourShader = contourShader + this._contourPickShader = contourPickShader + this._contourBuffer = contourBuffer + this._contourVAO = contourVAO + this._contourOffsets = [[], [], []] + this._contourCounts = [[], [], []] + this._vertexCount = 0 + + this._pickResult = new SurfacePickResult([0, 0, 0], [0, 0], [0, 0], [0, 0, 0], [0, 0, 0]) + + this._dynamicBuffer = dynamicBuffer + this._dynamicVAO = dynamicVAO + this._dynamicOffsets = [0, 0, 0] + this._dynamicCounts = [0, 0, 0] + + this.contourWidth = [ 1, 1, 1 ] + this.contourLevels = [[1], [1], [1]] + this.contourTint = [0, 0, 0] + this.contourColor = [[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1]] + + this.showContour = true + this.showSurface = true + + this.enableHighlight = [true, true, true] + this.highlightColor = [[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]] + this.highlightTint = [ 1, 1, 1 ] + this.highlightLevel = [-1, -1, -1] + + // Dynamic contour options + this.enableDynamic = [ true, true, true ] + this.dynamicLevel = [ NaN, NaN, NaN ] + this.dynamicColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ] + this.dynamicTint = [ 1, 1, 1 ] + this.dynamicWidth = [ 1, 1, 1 ] + + this.axesBounds = [[Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity]] + this.surfaceProject = [ false, false, false ] + this.contourProject = [[ false, false, false ], + [ false, false, false ], + [ false, false, false ]] + + this.colorBounds = [ false, false ] + + // Store xyz fields, need this for picking + this._field = [ + ndarray(pool.mallocFloat(1024), [0, 0]), + ndarray(pool.mallocFloat(1024), [0, 0]), + ndarray(pool.mallocFloat(1024), [0, 0]) ] + + this.pickId = 1 + this.clipBounds = [[-Infinity, -Infinity, -Infinity], [Infinity, Infinity, Infinity]] + + this.snapToData = false + + this.opacity = 1.0 + + this.lightPosition = [10, 10000, 0] + this.ambientLight = 0.8 + this.diffuseLight = 0.8 + this.specularLight = 2.0 + this.roughness = 0.5 + this.fresnel = 1.5 + this.vertexColor = 0; + + this.dirty = true +} + +var proto = SurfacePlot.prototype + +proto.isTransparent = function () { + return this.opacity < 1 +} + +proto.isOpaque = function () { + if (this.opacity >= 1) { + return true + } + for (var i = 0; i < 3; ++i) { + if (this._contourCounts[i].length > 0 || this._dynamicCounts[i] > 0) { + return true + } + } + return false +} + +proto.pickSlots = 1 + +proto.setPickBase = function (id) { + this.pickId = id +} + +var ZERO_VEC = [0, 0, 0] + +var PROJECT_DATA = { + showSurface: false, + showContour: false, + projections: [IDENTITY.slice(), IDENTITY.slice(), IDENTITY.slice()], + clipBounds: [ + [[0, 0, 0], [0, 0, 0]], + [[0, 0, 0], [0, 0, 0]], + [[0, 0, 0], [0, 0, 0]]] +} + +function computeProjectionData (camera, obj) { + var i, j, k + + // Compute cube properties + var cubeAxis = (obj.axes && obj.axes.lastCubeProps.axis) || ZERO_VEC + + var showSurface = obj.showSurface + var showContour = obj.showContour + + for (i = 0; i < 3; ++i) { + showSurface = showSurface || obj.surfaceProject[i] + for (j = 0; j < 3; ++j) { + showContour = showContour || obj.contourProject[i][j] + } + } + + for (i = 0; i < 3; ++i) { + // Construct projection onto axis + var axisSquish = PROJECT_DATA.projections[i] + for (j = 0; j < 16; ++j) { + axisSquish[j] = 0 + } + for (j = 0; j < 4; ++j) { + axisSquish[5 * j] = 1 + } + axisSquish[5 * i] = 0 + axisSquish[12 + i] = obj.axesBounds[+(cubeAxis[i] > 0)][i] + multiply(axisSquish, camera.model, axisSquish) + + var nclipBounds = PROJECT_DATA.clipBounds[i] + for (k = 0; k < 2; ++k) { + for (j = 0; j < 3; ++j) { + nclipBounds[k][j] = camera.clipBounds[k][j] + } + } + nclipBounds[0][i] = -1e8 + nclipBounds[1][i] = 1e8 + } + + PROJECT_DATA.showSurface = showSurface + PROJECT_DATA.showContour = showContour + + return PROJECT_DATA +} + +var UNIFORMS = { + model: IDENTITY, + view: IDENTITY, + projection: IDENTITY, + inverseModel: IDENTITY.slice(), + lowerBound: [0, 0, 0], + upperBound: [0, 0, 0], + colorMap: 0, + clipBounds: [[0, 0, 0], [0, 0, 0]], + height: 0.0, + contourTint: 0, + contourColor: [0, 0, 0, 1], + permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1], + zOffset: -1e-4, + kambient: 1, + kdiffuse: 1, + kspecular: 1, + lightPosition: [1000, 1000, 1000], + eyePosition: [0, 0, 0], + roughness: 1, + fresnel: 1, + opacity: 1, + vertexColor: 0 +} + +var MATRIX_INVERSE = IDENTITY.slice() +var DEFAULT_PERM = [1, 0, 0, 0, 1, 0, 0, 0, 1] + +function drawCore (params, transparent) { + params = params || {} + var gl = this.gl + + gl.disable(gl.CULL_FACE) + + this._colorMap.bind(0) + + var uniforms = UNIFORMS + uniforms.model = params.model || IDENTITY + uniforms.view = params.view || IDENTITY + uniforms.projection = params.projection || IDENTITY + uniforms.lowerBound = [this.bounds[0][0], this.bounds[0][1], this.colorBounds[0] || this.bounds[0][2]] + uniforms.upperBound = [this.bounds[1][0], this.bounds[1][1], this.colorBounds[1] || this.bounds[1][2]] + uniforms.contourColor = this.contourColor[0] + + uniforms.inverseModel = invert(uniforms.inverseModel, uniforms.model) + + for (var i = 0; i < 2; ++i) { + var clipClamped = uniforms.clipBounds[i] + for (var j = 0; j < 3; ++j) { + clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8) + } + } + + uniforms.kambient = this.ambientLight + uniforms.kdiffuse = this.diffuseLight + uniforms.kspecular = this.specularLight + + uniforms.roughness = this.roughness + uniforms.fresnel = this.fresnel + uniforms.opacity = this.opacity + + uniforms.height = 0.0 + uniforms.permutation = DEFAULT_PERM + + uniforms.vertexColor = this.vertexColor + + // Compute camera matrix inverse + var invCameraMatrix = MATRIX_INVERSE + multiply(invCameraMatrix, uniforms.view, uniforms.model) + multiply(invCameraMatrix, uniforms.projection, invCameraMatrix) + invert(invCameraMatrix, invCameraMatrix) + + for (i = 0; i < 3; ++i) { + uniforms.eyePosition[i] = invCameraMatrix[12 + i] / invCameraMatrix[15] + } + + var w = invCameraMatrix[15] + for (i = 0; i < 3; ++i) { + w += this.lightPosition[i] * invCameraMatrix[4 * i + 3] + } + for (i = 0; i < 3; ++i) { + var s = invCameraMatrix[12 + i] + for (j = 0; j < 3; ++j) { + s += invCameraMatrix[4 * j + i] * this.lightPosition[j] + } + uniforms.lightPosition[i] = s / w + } + + var projectData = computeProjectionData(uniforms, this) + + if (projectData.showSurface && (transparent === (this.opacity < 1))) { + // Set up uniforms + this._shader.bind() + this._shader.uniforms = uniforms + + // Draw it + this._vao.bind() + + if (this.showSurface && this._vertexCount) { + this._vao.draw(gl.TRIANGLES, this._vertexCount) + } + + // Draw projections of surface + for (i = 0; i < 3; ++i) { + if (!this.surfaceProject[i] || !this.vertexCount) { + continue + } + this._shader.uniforms.model = projectData.projections[i] + this._shader.uniforms.clipBounds = projectData.clipBounds[i] + this._vao.draw(gl.TRIANGLES, this._vertexCount) + } + + this._vao.unbind() + } + + if (projectData.showContour && !transparent) { + var shader = this._contourShader + + // Don't apply lighting to contours + uniforms.kambient = 1.0 + uniforms.kdiffuse = 0.0 + uniforms.kspecular = 0.0 + uniforms.opacity = 1.0 + + shader.bind() + shader.uniforms = uniforms + + // Draw contour lines + var vao = this._contourVAO + vao.bind() + + // Draw contour levels + for (i = 0; i < 3; ++i) { + shader.uniforms.permutation = PERMUTATIONS[i] + gl.lineWidth(this.contourWidth[i]) + + for (j = 0; j < this.contourLevels[i].length; ++j) { + if (j === this.highlightLevel[i]) { + shader.uniforms.contourColor = this.highlightColor[i] + shader.uniforms.contourTint = this.highlightTint[i] + } else if (j === 0 || (j - 1) === this.highlightLevel[i]) { + shader.uniforms.contourColor = this.contourColor[i] + shader.uniforms.contourTint = this.contourTint[i] + } + if (!this._contourCounts[i][j]) { + continue + } + shader.uniforms.height = this.contourLevels[i][j] + vao.draw(gl.LINES, this._contourCounts[i][j], this._contourOffsets[i][j]) + } + } + + // Draw projections of surface + for (i = 0; i < 3; ++i) { + shader.uniforms.model = projectData.projections[i] + shader.uniforms.clipBounds = projectData.clipBounds[i] + for (j = 0; j < 3; ++j) { + if (!this.contourProject[i][j]) { + continue + } + shader.uniforms.permutation = PERMUTATIONS[j] + gl.lineWidth(this.contourWidth[j]) + for (var k = 0; k < this.contourLevels[j].length; ++k) { + if (k === this.highlightLevel[j]) { + shader.uniforms.contourColor = this.highlightColor[j] + shader.uniforms.contourTint = this.highlightTint[j] + } else if (k === 0 || (k - 1) === this.highlightLevel[j]) { + shader.uniforms.contourColor = this.contourColor[j] + shader.uniforms.contourTint = this.contourTint[j] + } + shader.uniforms.height = this.contourLevels[j][k] + vao.draw(gl.LINES, this._contourCounts[j][k], this._contourOffsets[j][k]) + } + } + } + vao.unbind() + + // Draw dynamic contours + vao = this._dynamicVAO + vao.bind() + + // Draw contour levels + for (i = 0; i < 3; ++i) { + if (this._dynamicCounts[i] === 0) { + continue + } + + shader.uniforms.model = uniforms.model + shader.uniforms.clipBounds = uniforms.clipBounds + shader.uniforms.permutation = PERMUTATIONS[i] + gl.lineWidth(this.dynamicWidth[i]) + + shader.uniforms.contourColor = this.dynamicColor[i] + shader.uniforms.contourTint = this.dynamicTint[i] + shader.uniforms.height = this.dynamicLevel[i] + vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) + + for (j = 0; j < 3; ++j) { + if (!this.contourProject[j][i]) { + continue + } + + shader.uniforms.model = projectData.projections[j] + shader.uniforms.clipBounds = projectData.clipBounds[j] + vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) + } + } + + vao.unbind() + } +} + +proto.draw = function (params) { + return drawCore.call(this, params, false) +} + +proto.drawTransparent = function (params) { + return drawCore.call(this, params, true) +} + +var PICK_UNIFORMS = { + model: IDENTITY, + view: IDENTITY, + projection: IDENTITY, + inverseModel: IDENTITY, + clipBounds: [[0, 0, 0], [0, 0, 0]], + height: 0.0, + shape: [0, 0], + pickId: 0, + lowerBound: [0, 0, 0], + upperBound: [0, 0, 0], + zOffset: 0.0, + permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1], + lightPosition: [0, 0, 0], + eyePosition: [0, 0, 0] +} + +proto.drawPick = function (params) { + params = params || {} + var gl = this.gl + gl.disable(gl.CULL_FACE) + + var uniforms = PICK_UNIFORMS + uniforms.model = params.model || IDENTITY + uniforms.view = params.view || IDENTITY + uniforms.projection = params.projection || IDENTITY + uniforms.shape = this._field[2].shape + uniforms.pickId = this.pickId / 255.0 + uniforms.lowerBound = this.bounds[0] + uniforms.upperBound = this.bounds[1] + uniforms.permutation = DEFAULT_PERM + + for (var i = 0; i < 2; ++i) { + var clipClamped = uniforms.clipBounds[i] + for (var j = 0; j < 3; ++j) { + clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8) + } + } + + var projectData = computeProjectionData(uniforms, this) + + if (projectData.showSurface) { + // Set up uniforms + this._pickShader.bind() + this._pickShader.uniforms = uniforms + + // Draw it + this._vao.bind() + this._vao.draw(gl.TRIANGLES, this._vertexCount) + + // Draw projections of surface + for (i = 0; i < 3; ++i) { + if (!this.surfaceProject[i]) { + continue + } + this._pickShader.uniforms.model = projectData.projections[i] + this._pickShader.uniforms.clipBounds = projectData.clipBounds[i] + this._vao.draw(gl.TRIANGLES, this._vertexCount) + } + + this._vao.unbind() + } + + if (projectData.showContour) { + var shader = this._contourPickShader + + shader.bind() + shader.uniforms = uniforms + + var vao = this._contourVAO + vao.bind() + + for (j = 0; j < 3; ++j) { + gl.lineWidth(this.contourWidth[j]) + shader.uniforms.permutation = PERMUTATIONS[j] + for (i = 0; i < this.contourLevels[j].length; ++i) { + if (this._contourCounts[j][i]) { + shader.uniforms.height = this.contourLevels[j][i] + vao.draw(gl.LINES, this._contourCounts[j][i], this._contourOffsets[j][i]) + } + } + } + + // Draw projections of surface + for (i = 0; i < 3; ++i) { + shader.uniforms.model = projectData.projections[i] + shader.uniforms.clipBounds = projectData.clipBounds[i] + + for (j = 0; j < 3; ++j) { + if (!this.contourProject[i][j]) { + continue + } + + shader.uniforms.permutation = PERMUTATIONS[j] + gl.lineWidth(this.contourWidth[j]) + for (var k = 0; k < this.contourLevels[j].length; ++k) { + if (this._contourCounts[j][k]) { + shader.uniforms.height = this.contourLevels[j][k] + vao.draw(gl.LINES, this._contourCounts[j][k], this._contourOffsets[j][k]) + } + } + } + } + + vao.unbind() + } +} + +proto.pick = function (selection) { + if (!selection) { + return null + } + + if (selection.id !== this.pickId) { + return null + } + + var shape = this._field[2].shape + + var result = this._pickResult + + // Compute uv coordinate + var x = shape[0] * (selection.value[0] + (selection.value[2] >> 4) / 16.0) / 255.0 + var ix = Math.floor(x) + var fx = x - ix + + var y = shape[1] * (selection.value[1] + (selection.value[2] & 15) / 16.0) / 255.0 + var iy = Math.floor(y) + var fy = y - iy + + ix += 1 + iy += 1 + + // Compute xyz coordinate + var pos = result.position + pos[0] = pos[1] = pos[2] = 0 + for (var dx = 0; dx < 2; ++dx) { + var s = dx ? fx : 1.0 - fx + for (var dy = 0; dy < 2; ++dy) { + var t = dy ? fy : 1.0 - fy + + var r = ix + dx + var c = iy + dy + var w = s * t + + for (var i = 0; i < 3; ++i) { + pos[i] += this._field[i].get(r, c) * w + } + } + } + + // Find closest level + var levelIndex = this._pickResult.level + for (var j = 0; j < 3; ++j) { + levelIndex[j] = bsearch.le(this.contourLevels[j], pos[j]) + if (levelIndex[j] < 0) { + if (this.contourLevels[j].length > 0) { + levelIndex[j] = 0 + } + } else if (levelIndex[j] < this.contourLevels[j].length - 1) { + var a = this.contourLevels[j][levelIndex[j]] + var b = this.contourLevels[j][levelIndex[j] + 1] + if (Math.abs(a - pos[j]) > Math.abs(b - pos[j])) { + levelIndex[j] += 1 + } + } + } + + result.index[0] = fx < 0.5 ? ix : (ix + 1) + result.index[1] = fy < 0.5 ? iy : (iy + 1) + + result.uv[0] = x / shape[0] + result.uv[1] = y / shape[1] + + for (i = 0; i < 3; ++i) { + result.dataCoordinate[i] = this._field[i].get(result.index[0], result.index[1]) + } + + return result +} + +function padField (nfield, field) { + var shape = field.shape.slice() + var nshape = nfield.shape.slice() + + // Center + ops.assign(nfield.lo(1, 1).hi(shape[0], shape[1]), field) + + // Edges + ops.assign(nfield.lo(1).hi(shape[0], 1), + field.hi(shape[0], 1)) + ops.assign(nfield.lo(1, nshape[1] - 1).hi(shape[0], 1), + field.lo(0, shape[1] - 1).hi(shape[0], 1)) + ops.assign(nfield.lo(0, 1).hi(1, shape[1]), + field.hi(1)) + ops.assign(nfield.lo(nshape[0] - 1, 1).hi(1, shape[1]), + field.lo(shape[0] - 1)) + // Corners + nfield.set(0, 0, field.get(0, 0)) + nfield.set(0, nshape[1] - 1, field.get(0, shape[1] - 1)) + nfield.set(nshape[0] - 1, 0, field.get(shape[0] - 1, 0)) + nfield.set(nshape[0] - 1, nshape[1] - 1, field.get(shape[0] - 1, shape[1] - 1)) +} + +function handleArray (param, ctor) { + if (Array.isArray(param)) { + return [ ctor(param[0]), ctor(param[1]), ctor(param[2]) ] + } + return [ ctor(param), ctor(param), ctor(param) ] +} + +function toColor (x) { + if (Array.isArray(x)) { + if (x.length === 3) { + return [x[0], x[1], x[2], 1] + } + return [x[0], x[1], x[2], x[3]] + } + return [0, 0, 0, 1] +} + +function handleColor (param) { + if (Array.isArray(param)) { + if (Array.isArray(param)) { + return [ + toColor(param[0]), + toColor(param[1]), + toColor(param[2]) ] + } else { + var c = toColor(param) + return [ + c.slice(), + c.slice(), + c.slice() ] + } + } +} + +proto.update = function (params) { + params = params || {} + + this.dirty = true + + if ('contourWidth' in params) { + this.contourWidth = handleArray(params.contourWidth, Number) + } + if ('showContour' in params) { + this.showContour = handleArray(params.showContour, Boolean) + } + if ('showSurface' in params) { + this.showSurface = !!params.showSurface + } + if ('contourTint' in params) { + this.contourTint = handleArray(params.contourTint, Boolean) + } + if ('contourColor' in params) { + this.contourColor = handleColor(params.contourColor) + } + if ('contourProject' in params) { + this.contourProject = handleArray(params.contourProject, function (x) { + return handleArray(x, Boolean) + }) + } + if ('surfaceProject' in params) { + this.surfaceProject = params.surfaceProject + } + if ('dynamicColor' in params) { + this.dynamicColor = handleColor(params.dynamicColor) + } + if ('dynamicTint' in params) { + this.dynamicTint = handleArray(params.dynamicTint, Number) + } + if ('dynamicWidth' in params) { + this.dynamicWidth = handleArray(params.dynamicWidth, Number) + } + if ('opacity' in params) { + this.opacity = params.opacity + } + if ('colorBounds' in params) { + this.colorBounds = params.colorBounds + } + if ('vertexColor' in params) { + this.vertexColor = params.vertexColor ? 1 : 0; + } + + var field = params.field || (params.coords && params.coords[2]) || null + var levelsChanged = false + + if (!field) { + if (this._field[2].shape[0] || this._field[2].shape[2]) { + field = this._field[2].lo(1, 1).hi(this._field[2].shape[0] - 2, this._field[2].shape[1] - 2) + } else { + field = this._field[2].hi(0, 0) + } + } + + // Update field + if ('field' in params || 'coords' in params) { + var fsize = (field.shape[0] + 2) * (field.shape[1] + 2) + + // Resize if necessary + if (fsize > this._field[2].data.length) { + pool.freeFloat(this._field[2].data) + this._field[2].data = pool.mallocFloat(bits.nextPow2(fsize)) + } + + // Pad field + this._field[2] = ndarray(this._field[2].data, [field.shape[0] + 2, field.shape[1] + 2]) + padField(this._field[2], field) + + // Save shape of field + this.shape = field.shape.slice() + var shape = this.shape + + // Resize coordinate fields if necessary + for (var i = 0; i < 2; ++i) { + if (this._field[2].size > this._field[i].data.length) { + pool.freeFloat(this._field[i].data) + this._field[i].data = pool.mallocFloat(this._field[2].size) + } + this._field[i] = ndarray(this._field[i].data, [shape[0] + 2, shape[1] + 2]) + } + + // Generate x/y coordinates + if (params.coords) { + var coords = params.coords + if (!Array.isArray(coords) || coords.length !== 3) { + throw new Error('gl-surface: invalid coordinates for x/y') + } + for (i = 0; i < 2; ++i) { + var coord = coords[i] + for (j = 0; j < 2; ++j) { + if (coord.shape[j] !== shape[j]) { + throw new Error('gl-surface: coords have incorrect shape') + } + } + padField(this._field[i], coord) + } + } else if (params.ticks) { + var ticks = params.ticks + if (!Array.isArray(ticks) || ticks.length !== 2) { + throw new Error('gl-surface: invalid ticks') + } + for (i = 0; i < 2; ++i) { + var tick = ticks[i] + if (Array.isArray(tick) || tick.length) { + tick = ndarray(tick) + } + if (tick.shape[0] !== shape[i]) { + throw new Error('gl-surface: invalid tick length') + } + // Make a copy view of the tick array + var tick2 = ndarray(tick.data, shape) + tick2.stride[i] = tick.stride[0] + tick2.stride[i ^ 1] = 0 + + // Fill in field array + padField(this._field[i], tick2) + } + } else { + for (i = 0; i < 2; ++i) { + var offset = [0, 0] + offset[i] = 1 + this._field[i] = ndarray(this._field[i].data, [shape[0] + 2, shape[1] + 2], offset, 0) + } + this._field[0].set(0, 0, 0) + for (var j = 0; j < shape[0]; ++j) { + this._field[0].set(j + 1, 0, j) + } + this._field[0].set(shape[0] + 1, 0, shape[0] - 1) + this._field[1].set(0, 0, 0) + for (j = 0; j < shape[1]; ++j) { + this._field[1].set(0, j + 1, j) + } + this._field[1].set(0, shape[1] + 1, shape[1] - 1) + } + + // Save shape + var fields = this._field + + // Compute surface normals + var dfields = ndarray(pool.mallocFloat(fields[2].size * 3 * 2), [3, shape[0] + 2, shape[1] + 2, 2]) + for (i = 0; i < 3; ++i) { + gradient(dfields.pick(i), fields[i], 'mirror') + } + var normals = ndarray(pool.mallocFloat(fields[2].size * 3), [shape[0] + 2, shape[1] + 2, 3]) + for (i = 0; i < shape[0] + 2; ++i) { + for (j = 0; j < shape[1] + 2; ++j) { + var dxdu = dfields.get(0, i, j, 0) + var dxdv = dfields.get(0, i, j, 1) + var dydu = dfields.get(1, i, j, 0) + var dydv = dfields.get(1, i, j, 1) + var dzdu = dfields.get(2, i, j, 0) + var dzdv = dfields.get(2, i, j, 1) + + var nx = dydu * dzdv - dydv * dzdu + var ny = dzdu * dxdv - dzdv * dxdu + var nz = dxdu * dydv - dxdv * dydu + + var nl = Math.sqrt(nx * nx + ny * ny + nz * nz) + if (nl < 1e-8) { + nl = Math.max(Math.abs(nx), Math.abs(ny), Math.abs(nz)) + if (nl < 1e-8) { + nz = 1.0 + ny = nx = 0.0 + nl = 1.0 + } else { + nl = 1.0 / nl + } + } else { + nl = 1.0 / Math.sqrt(nl) + } + + normals.set(i, j, 0, nx * nl) + normals.set(i, j, 1, ny * nl) + normals.set(i, j, 2, nz * nl) + } + } + pool.free(dfields.data) + + // Initialize surface + var lo = [ Infinity, Infinity, Infinity ] + var hi = [ -Infinity, -Infinity, -Infinity ] + var lo_intensity = Infinity + var hi_intensity = -Infinity + var count = (shape[0] - 1) * (shape[1] - 1) * 6 + var tverts = pool.mallocFloat(bits.nextPow2(10 * count)) + var tptr = 0 + var vertexCount = 0 + for (i = 0; i < shape[0] - 1; ++i) { + j_loop: + for (j = 0; j < shape[1] - 1; ++j) { + // Test for NaNs + for (var dx = 0; dx < 2; ++dx) { + for (var dy = 0; dy < 2; ++dy) { + for (var k = 0; k < 3; ++k) { + var f = this._field[k].get(1 + i + dx, 1 + j + dy) + if (isNaN(f) || !isFinite(f)) { + continue j_loop + } + } + } + } + for (k = 0; k < 6; ++k) { + var r = i + QUAD[k][0] + var c = j + QUAD[k][1] + + var tx = this._field[0].get(r + 1, c + 1) + var ty = this._field[1].get(r + 1, c + 1) + f = this._field[2].get(r + 1, c + 1) + var vf = f + nx = normals.get(r + 1, c + 1, 0) + ny = normals.get(r + 1, c + 1, 1) + nz = normals.get(r + 1, c + 1, 2) + + if (params.intensity) { + vf = params.intensity.get(r, c) + } + + tverts[tptr++] = r + tverts[tptr++] = c + tverts[tptr++] = tx + tverts[tptr++] = ty + tverts[tptr++] = f + tverts[tptr++] = 0 + tverts[tptr++] = vf + tverts[tptr++] = nx + tverts[tptr++] = ny + tverts[tptr++] = nz + + lo[0] = Math.min(lo[0], tx) + lo[1] = Math.min(lo[1], ty) + lo[2] = Math.min(lo[2], f) + lo_intensity = Math.min(lo_intensity, vf) + + hi[0] = Math.max(hi[0], tx) + hi[1] = Math.max(hi[1], ty) + hi[2] = Math.max(hi[2], f) + hi_intensity = Math.max(hi_intensity, vf) + + vertexCount += 1 + } + } + } + + if (params.intensityBounds) { + lo_intensity = +params.intensityBounds[0] + hi_intensity = +params.intensityBounds[1] + } + + // Scale all vertex intensities + for (i = 6; i < tptr; i += 10) { + tverts[i] = (tverts[i] - lo_intensity) / (hi_intensity - lo_intensity) + } + + this._vertexCount = vertexCount + this._coordinateBuffer.update(tverts.subarray(0, tptr)) + pool.freeFloat(tverts) + pool.free(normals.data) + + // Update bounds + this.bounds = [lo, hi] + + // Save intensity + this.intensity = params.intensity || this._field[2] + + if(this.intensityBounds[0] !== lo_intensity || this.intensityBounds[1] !== hi_intensity) { + levelsChanged = true + } + + // Save intensity bound + this.intensityBounds = [lo_intensity, hi_intensity] + } + + // Update level crossings + if ('levels' in params) { + var levels = params.levels + if (!Array.isArray(levels[0])) { + levels = [ [], [], levels ] + } else { + levels = levels.slice() + } + for (i = 0; i < 3; ++i) { + levels[i] = levels[i].slice() + levels.sort(function (a, b) { + return a - b + }) + } + change_test: + for (i = 0; i < 3; ++i) { + if (levels[i].length !== this.contourLevels[i].length) { + levelsChanged = true + break + } + for (j = 0; j < levels[i].length; ++j) { + if (levels[i][j] !== this.contourLevels[i][j]) { + levelsChanged = true + break change_test + } + } + } + this.contourLevels = levels + } + + if (levelsChanged) { + fields = this._field + shape = this.shape + + // Update contour lines + var contourVerts = [] + + for (var dim = 0; dim < 3; ++dim) { + levels = this.contourLevels[dim] + var levelOffsets = [] + var levelCounts = [] + + var parts = [0, 0, 0] + + for (i = 0; i < levels.length; ++i) { + var graph = surfaceNets(this._field[dim], levels[i]) + levelOffsets.push((contourVerts.length / 5) | 0) + vertexCount = 0 + + edge_loop: + for (j = 0; j < graph.cells.length; ++j) { + var e = graph.cells[j] + for (k = 0; k < 2; ++k) { + var p = graph.positions[e[k]] + + var x = p[0] + var ix = Math.floor(x) | 0 + var fx = x - ix + + var y = p[1] + var iy = Math.floor(y) | 0 + var fy = y - iy + + var hole = false + dd_loop: + for (var dd = 0; dd < 3; ++dd) { + parts[dd] = 0.0 + var iu = (dim + dd + 1) % 3 + for (dx = 0; dx < 2; ++dx) { + var s = dx ? fx : 1.0 - fx + r = Math.min(Math.max(ix + dx, 0), shape[0]) | 0 + for (dy = 0; dy < 2; ++dy) { + var t = dy ? fy : 1.0 - fy + c = Math.min(Math.max(iy + dy, 0), shape[1]) | 0 + + if (dd < 2) { + f = this._field[iu].get(r, c) + } else { + f = (this.intensity.get(r, c) - this.intensityBounds[0]) / (this.intensityBounds[1] - this.intensityBounds[0]) + } + if (!isFinite(f) || isNaN(f)) { + hole = true + break dd_loop + } + + var w = s * t + parts[dd] += w * f + } + } + } + + if (!hole) { + contourVerts.push(parts[0], parts[1], p[0], p[1], parts[2]) + vertexCount += 1 + } else { + if (k > 0) { + // If we already added first edge, pop off verts + for (var l = 0; l < 5; ++l) { + contourVerts.pop() + } + vertexCount -= 1 + } + continue edge_loop + } + } + } + levelCounts.push(vertexCount) + } + + // Store results + this._contourOffsets[dim] = levelOffsets + this._contourCounts[dim] = levelCounts + } + + var floatBuffer = pool.mallocFloat(contourVerts.length) + for (i = 0; i < contourVerts.length; ++i) { + floatBuffer[i] = contourVerts[i] + } + this._contourBuffer.update(floatBuffer) + pool.freeFloat(floatBuffer) + } + + if (params.colormap) { + this._colorMap.setPixels(genColormap(params.colormap)) + } +} + +proto.dispose = function () { + this._shader.dispose() + this._vao.dispose() + this._coordinateBuffer.dispose() + this._colorMap.dispose() + this._contourBuffer.dispose() + this._contourVAO.dispose() + this._contourShader.dispose() + this._contourPickShader.dispose() + this._dynamicBuffer.dispose() + this._dynamicVAO.dispose() + for (var i = 0; i < 3; ++i) { + pool.freeFloat(this._field[i].data) + } +} + +proto.highlight = function (selection) { + if (!selection) { + this._dynamicCounts = [0, 0, 0] + this.dyanamicLevel = [NaN, NaN, NaN] + this.highlightLevel = [-1, -1, -1] + return + } + + for (var i = 0; i < 3; ++i) { + if (this.enableHighlight[i]) { + this.highlightLevel[i] = selection.level[i] + } else { + this.highlightLevel[i] = -1 + } + } + + var levels + if (this.snapToData) { + levels = selection.dataCoordinate + } else { + levels = selection.position + } + if ((!this.enableDynamic[0] || levels[0] === this.dynamicLevel[0]) && + (!this.enableDynamic[1] || levels[1] === this.dynamicLevel[1]) && + (!this.enableDynamic[2] || levels[2] === this.dynamicLevel[2])) { + return + } + + var vertexCount = 0 + var shape = this.shape + var scratchBuffer = pool.mallocFloat(12 * shape[0] * shape[1]) + + for (var d = 0; d < 3; ++d) { + if (!this.enableDynamic[d]) { + this.dynamicLevel[d] = NaN + this._dynamicCounts[d] = 0 + continue + } + + this.dynamicLevel[d] = levels[d] + + var u = (d + 1) % 3 + var v = (d + 2) % 3 + + var f = this._field[d] + var g = this._field[u] + var h = this._field[v] + var intensity = this.intensity + + var graph = surfaceNets(f, levels[d]) + var edges = graph.cells + var positions = graph.positions + + this._dynamicOffsets[d] = vertexCount + + for (i = 0; i < edges.length; ++i) { + var e = edges[i] + for (var j = 0; j < 2; ++j) { + var p = positions[e[j]] + + var x = +p[0] + var ix = x | 0 + var jx = Math.min(ix + 1, shape[0]) | 0 + var fx = x - ix + var hx = 1.0 - fx + + var y = +p[1] + var iy = y | 0 + var jy = Math.min(iy + 1, shape[1]) | 0 + var fy = y - iy + var hy = 1.0 - fy + + var w00 = hx * hy + var w01 = hx * fy + var w10 = fx * hy + var w11 = fx * fy + + var cu = w00 * g.get(ix, iy) + + w01 * g.get(ix, jy) + + w10 * g.get(jx, iy) + + w11 * g.get(jx, jy) + + var cv = w00 * h.get(ix, iy) + + w01 * h.get(ix, jy) + + w10 * h.get(jx, iy) + + w11 * h.get(jx, jy) + + if (isNaN(cu) || isNaN(cv)) { + if (j) { + vertexCount -= 1 + } + break + } + + scratchBuffer[2 * vertexCount + 0] = cu + scratchBuffer[2 * vertexCount + 1] = cv + + vertexCount += 1 + } + } + + this._dynamicCounts[d] = vertexCount - this._dynamicOffsets[d] + } + + this._dynamicBuffer.update(scratchBuffer.subarray(0, 2 * vertexCount)) + pool.freeFloat(scratchBuffer) +} + +function createSurfacePlot (params) { + var gl = params.gl + var shader = createShader(gl) + var pickShader = createPickShader(gl) + var contourShader = createContourShader(gl) + var contourPickShader = createPickContourShader(gl) + + var coordinateBuffer = createBuffer(gl) + var vao = createVAO(gl, [ + { buffer: coordinateBuffer, + size: 4, + stride: SURFACE_VERTEX_SIZE, + offset: 0 + }, + { buffer: coordinateBuffer, + size: 3, + stride: SURFACE_VERTEX_SIZE, + offset: 16 + }, + { + buffer: coordinateBuffer, + size: 3, + stride: SURFACE_VERTEX_SIZE, + offset: 28 + } + ]) + + var contourBuffer = createBuffer(gl) + var contourVAO = createVAO(gl, [ + { + buffer: contourBuffer, + size: 4, + stride: 20, + offset: 0 + }, + { + buffer: contourBuffer, + size: 1, + stride: 20, + offset: 16 + } + ]) + + var dynamicBuffer = createBuffer(gl) + var dynamicVAO = createVAO(gl, [ + { + buffer: dynamicBuffer, + size: 2, + type: gl.FLOAT + }]) + + var cmap = createTexture(gl, 1, N_COLORS, gl.RGBA, gl.UNSIGNED_BYTE) + cmap.minFilter = gl.LINEAR + cmap.magFilter = gl.LINEAR + + var surface = new SurfacePlot( + gl, + [0, 0], + [[0, 0, 0], [0, 0, 0]], + shader, + pickShader, + coordinateBuffer, + vao, + cmap, + contourShader, + contourPickShader, + contourBuffer, + contourVAO, + dynamicBuffer, + dynamicVAO + ) + + var nparams = { + levels: [[], [], []] + } + for (var id in params) { + nparams[id] = params[id] + } + nparams.colormap = nparams.colormap || 'jet' + + surface.update(nparams) + + return surface +} + +},{"./lib/shaders":302,"binary-search-bounds":79,"bit-twiddle":80,"colormap":114,"gl-buffer":230,"gl-mat4/invert":254,"gl-mat4/multiply":256,"gl-texture2d":305,"gl-vao":310,"ndarray":433,"ndarray-gradient":424,"ndarray-ops":427,"ndarray-pack":428,"surface-nets":508,"typedarray-pool":522}],304:[function(_dereq_,module,exports){ +'use strict' + +var Font = _dereq_('css-font') +var pick = _dereq_('pick-by-alias') +var createRegl = _dereq_('regl') +var createGl = _dereq_('gl-util/context') +var WeakMap = _dereq_('es6-weak-map') +var rgba = _dereq_('color-normalize') +var fontAtlas = _dereq_('font-atlas') +var pool = _dereq_('typedarray-pool') +var parseRect = _dereq_('parse-rect') +var isObj = _dereq_('is-plain-obj') +var parseUnit = _dereq_('parse-unit') +var px = _dereq_('to-px') +var kerning = _dereq_('detect-kerning') +var extend = _dereq_('object-assign') +var metrics = _dereq_('font-measure') +var flatten = _dereq_('flatten-vertex-data') +var ref = _dereq_('bit-twiddle'); +var nextPow2 = ref.nextPow2; + +var shaderCache = new WeakMap + + +// Safari does not support font-stretch +var isStretchSupported = false +if (document.body) { + var el = document.body.appendChild(document.createElement('div')) + el.style.font = 'italic small-caps bold condensed 16px/2 cursive' + if (getComputedStyle(el).fontStretch) { + isStretchSupported = true + } + document.body.removeChild(el) +} + +var GlText = function GlText (o) { + if (isRegl(o)) { + o = {regl: o} + this.gl = o.regl._gl + } + else { + this.gl = createGl(o) + } + + this.shader = shaderCache.get(this.gl) + + if (!this.shader) { + this.regl = o.regl || createRegl({ gl: this.gl }) + } + else { + this.regl = this.shader.regl + } + + this.charBuffer = this.regl.buffer({ type: 'uint8', usage: 'stream' }) + this.sizeBuffer = this.regl.buffer({ type: 'float', usage: 'stream' }) + + if (!this.shader) { + this.shader = this.createShader() + shaderCache.set(this.gl, this.shader) + } + + this.batch = [] + + // multiple options initial state + this.fontSize = [] + this.font = [] + this.fontAtlas = [] + + this.draw = this.shader.draw.bind(this) + this.render = function () { + // FIXME: add Safari regl report here: + // charBuffer and width just do not trigger + this.regl._refresh() + this.draw(this.batch) + } + this.canvas = this.gl.canvas + + this.update(isObj(o) ? o : {}) +}; + +GlText.prototype.createShader = function createShader () { + var regl = this.regl + + // FIXME: store 2 shader versions: with normal viewport and without + // draw texture method + var draw = regl({ + blend: { + enable: true, + color: [0,0,0,1], + + func: { + srcRGB: 'src alpha', + dstRGB: 'one minus src alpha', + srcAlpha: 'one minus dst alpha', + dstAlpha: 'one' + } + }, + stencil: {enable: false}, + depth: {enable: false}, + + count: regl.prop('count'), + offset: regl.prop('offset'), + attributes: { + charOffset: { + offset: 4, + stride: 8, + buffer: regl.this('sizeBuffer') + }, + width: { + offset: 0, + stride: 8, + buffer: regl.this('sizeBuffer') + }, + char: regl.this('charBuffer'), + position: regl.this('position') + }, + uniforms: { + atlasSize: function (c, p) { return [p.atlas.width, p.atlas.height]; }, + atlasDim: function (c, p) { return [p.atlas.cols, p.atlas.rows]; }, + atlas: function (c, p) { return p.atlas.texture; }, + charStep: function (c, p) { return p.atlas.step; }, + em: function (c, p) { return p.atlas.em; }, + color: regl.prop('color'), + opacity: regl.prop('opacity'), + viewport: regl.this('viewportArray'), + scale: regl.this('scale'), + align: regl.prop('align'), + baseline: regl.prop('baseline'), + translate: regl.this('translate'), + positionOffset: regl.prop('positionOffset') + }, + primitive: 'points', + viewport: regl.this('viewport'), + + vert: ("\n\t\t\tprecision highp float;\n\t\t\tattribute float width, charOffset, char;\n\t\t\tattribute vec2 position;\n\t\t\tuniform float fontSize, charStep, em, align, baseline;\n\t\t\tuniform vec4 viewport;\n\t\t\tuniform vec4 color;\n\t\t\tuniform vec2 atlasSize, atlasDim, scale, translate, positionOffset;\n\t\t\tvarying vec2 charCoord, charId;\n\t\t\tvarying float charWidth;\n\t\t\tvarying vec4 fontColor;\n\t\t\tvoid main () {\n\t\t\t\t" + (!GlText.normalViewport ? 'vec2 positionOffset = vec2(positionOffset.x,- positionOffset.y);' : '') + "\n\n\t\t\t\tvec2 offset = floor(em * (vec2(align + charOffset, baseline)\n\t\t\t\t\t+ positionOffset))\n\t\t\t\t\t/ (viewport.zw * scale.xy);\n\n\t\t\t\tvec2 position = (position + translate) * scale;\n\t\t\t\tposition += offset * scale;\n\n\t\t\t\t" + (GlText.normalViewport ? 'position.y = 1. - position.y;' : '') + "\n\n\t\t\t\tcharCoord = position * viewport.zw + viewport.xy;\n\n\t\t\t\tgl_Position = vec4(position * 2. - 1., 0, 1);\n\n\t\t\t\tgl_PointSize = charStep;\n\n\t\t\t\tcharId.x = mod(char, atlasDim.x);\n\t\t\t\tcharId.y = floor(char / atlasDim.x);\n\n\t\t\t\tcharWidth = width * em;\n\n\t\t\t\tfontColor = color / 255.;\n\t\t\t}"), + + frag: "\n\t\t\tprecision highp float;\n\t\t\tuniform sampler2D atlas;\n\t\t\tuniform float fontSize, charStep, opacity;\n\t\t\tuniform vec2 atlasSize;\n\t\t\tuniform vec4 viewport;\n\t\t\tvarying vec4 fontColor;\n\t\t\tvarying vec2 charCoord, charId;\n\t\t\tvarying float charWidth;\n\n\t\t\tfloat lightness(vec4 color) {\n\t\t\t\treturn color.r * 0.299 + color.g * 0.587 + color.b * 0.114;\n\t\t\t}\n\n\t\t\tvoid main () {\n\t\t\t\tvec2 uv = gl_FragCoord.xy - charCoord + charStep * .5;\n\t\t\t\tfloat halfCharStep = floor(charStep * .5 + .5);\n\n\t\t\t\t// invert y and shift by 1px (FF expecially needs that)\n\t\t\t\tuv.y = charStep - uv.y;\n\n\t\t\t\t// ignore points outside of character bounding box\n\t\t\t\tfloat halfCharWidth = ceil(charWidth * .5);\n\t\t\t\tif (floor(uv.x) > halfCharStep + halfCharWidth ||\n\t\t\t\t\tfloor(uv.x) < halfCharStep - halfCharWidth) return;\n\n\t\t\t\tuv += charId * charStep;\n\t\t\t\tuv = uv / atlasSize;\n\n\t\t\t\tvec4 color = fontColor;\n\t\t\t\tvec4 mask = texture2D(atlas, uv);\n\n\t\t\t\tfloat maskY = lightness(mask);\n\t\t\t\t// float colorY = lightness(color);\n\t\t\t\tcolor.a *= maskY;\n\t\t\t\tcolor.a *= opacity;\n\n\t\t\t\t// color.a += .1;\n\n\t\t\t\t// antialiasing, see yiq color space y-channel formula\n\t\t\t\t// color.rgb += (1. - color.rgb) * (1. - mask.rgb);\n\n\t\t\t\tgl_FragColor = color;\n\t\t\t}" + }) + + // per font-size atlas + var atlas = {} + + return { regl: regl, draw: draw, atlas: atlas } +}; + +GlText.prototype.update = function update (o) { + var this$1 = this; + + if (typeof o === 'string') { o = { text: o } } + else if (!o) { return } + + // FIXME: make this a static transform or more general approact + o = pick(o, { + position: 'position positions coord coords coordinates', + font: 'font fontFace fontface typeface cssFont css-font family fontFamily', + fontSize: 'fontSize fontsize size font-size', + text: 'text texts chars characters value values symbols', + align: 'align alignment textAlign textbaseline', + baseline: 'baseline textBaseline textbaseline', + direction: 'dir direction textDirection', + color: 'color colour fill fill-color fillColor textColor textcolor', + kerning: 'kerning kern', + range: 'range dataBox', + viewport: 'vp viewport viewBox viewbox viewPort', + opacity: 'opacity alpha transparency visible visibility opaque', + offset: 'offset positionOffset padding shift indent indentation' + }, true) + + + if (o.opacity != null) { + if (Array.isArray(o.opacity)) { + this.opacity = o.opacity.map(function (o) { return parseFloat(o); }) + } + else { + this.opacity = parseFloat(o.opacity) + } + } + + if (o.viewport != null) { + this.viewport = parseRect(o.viewport) + + if (GlText.normalViewport) { + this.viewport.y = this.canvas.height - this.viewport.y - this.viewport.height + } + + this.viewportArray = [this.viewport.x, this.viewport.y, this.viewport.width, this.viewport.height] + + } + if (this.viewport == null) { + this.viewport = { + x: 0, y: 0, + width: this.gl.drawingBufferWidth, + height: this.gl.drawingBufferHeight + } + this.viewportArray = [this.viewport.x, this.viewport.y, this.viewport.width, this.viewport.height] + } + + if (o.kerning != null) { this.kerning = o.kerning } + + if (o.offset != null) { + if (typeof o.offset === 'number') { o.offset = [o.offset, 0] } + + this.positionOffset = flatten(o.offset) + } + + if (o.direction) { this.direction = o.direction } + + if (o.range) { + this.range = o.range + this.scale = [1 / (o.range[2] - o.range[0]), 1 / (o.range[3] - o.range[1])] + this.translate = [-o.range[0], -o.range[1]] + } + if (o.scale) { this.scale = o.scale } + if (o.translate) { this.translate = o.translate } + + // default scale corresponds to viewport + if (!this.scale) { this.scale = [1 / this.viewport.width, 1 / this.viewport.height] } + + if (!this.translate) { this.translate = [0, 0] } + + if (!this.font.length && !o.font) { o.font = GlText.baseFontSize + 'px sans-serif' } + + // normalize font caching string + var newFont = false, newFontSize = false + + // obtain new font data + if (o.font) { + (Array.isArray(o.font) ? o.font : [o.font]).forEach(function (font, i) { + // normalize font + if (typeof font === 'string') { + try { + font = Font.parse(font) + } catch (e) { + font = Font.parse(GlText.baseFontSize + 'px ' + font) + } + } + else { font = Font.parse(Font.stringify(font)) } + + var baseString = Font.stringify({ + size: GlText.baseFontSize, + family: font.family, + stretch: isStretchSupported ? font.stretch : undefined, + variant: font.variant, + weight: font.weight, + style: font.style + }) + + var unit = parseUnit(font.size) + var fs = Math.round(unit[0] * px(unit[1])) + if (fs !== this$1.fontSize[i]) { + newFontSize = true + this$1.fontSize[i] = fs + } + + // calc new font metrics/atlas + if (!this$1.font[i] || baseString != this$1.font[i].baseString) { + newFont = true + + // obtain font cache or create one + this$1.font[i] = GlText.fonts[baseString] + if (!this$1.font[i]) { + var family = font.family.join(', ') + var style = [font.style] + if (font.style != font.variant) { style.push(font.variant) } + if (font.variant != font.weight) { style.push(font.weight) } + if (isStretchSupported && font.weight != font.stretch) { style.push(font.stretch) } + + this$1.font[i] = { + baseString: baseString, + + // typeface + family: family, + weight: font.weight, + stretch: font.stretch, + style: font.style, + variant: font.variant, + + // widths of characters + width: {}, + + // kernin pairs offsets + kerning: {}, + + metrics: metrics(family, { + origin: 'top', + fontSize: GlText.baseFontSize, + fontStyle: style.join(' ') + }) + } + + GlText.fonts[baseString] = this$1.font[i] + } + } + }) + } + + // FIXME: make independend font-size + // if (o.fontSize) { + // let unit = parseUnit(o.fontSize) + // let fs = Math.round(unit[0] * px(unit[1])) + + // if (fs != this.fontSize) { + // newFontSize = true + // this.fontSize = fs + // } + // } + + if (newFont || newFontSize) { + this.font.forEach(function (font, i) { + var fontString = Font.stringify({ + size: this$1.fontSize[i], + family: font.family, + stretch: isStretchSupported ? font.stretch : undefined, + variant: font.variant, + weight: font.weight, + style: font.style + }) + + // calc new font size atlas + this$1.fontAtlas[i] = this$1.shader.atlas[fontString] + + if (!this$1.fontAtlas[i]) { + var metrics = font.metrics + + this$1.shader.atlas[fontString] = + this$1.fontAtlas[i] = { + fontString: fontString, + // even step is better for rendered characters + step: Math.ceil(this$1.fontSize[i] * metrics.bottom * .5) * 2, + em: this$1.fontSize[i], + cols: 0, + rows: 0, + height: 0, + width: 0, + chars: [], + ids: {}, + texture: this$1.regl.texture() + } + } + + // bump atlas characters + if (o.text == null) { o.text = this$1.text } + }) + } + + // if multiple positions - duplicate text arguments + // FIXME: this possibly can be done better to avoid array spawn + if (typeof o.text === 'string' && o.position && o.position.length > 2) { + var textArray = Array(o.position.length * .5) + for (var i = 0; i < textArray.length; i++) { + textArray[i] = o.text + } + o.text = textArray + } + + // calculate offsets for the new font/text + var newAtlasChars + if (o.text != null || newFont) { + // FIXME: ignore spaces + // text offsets within the text buffer + this.textOffsets = [0] + + if (Array.isArray(o.text)) { + this.count = o.text[0].length + this.counts = [this.count] + for (var i$1 = 1; i$1 < o.text.length; i$1++) { + this$1.textOffsets[i$1] = this$1.textOffsets[i$1 - 1] + o.text[i$1 - 1].length + this$1.count += o.text[i$1].length + this$1.counts.push(o.text[i$1].length) + } + this.text = o.text.join('') + } + else { + this.text = o.text + this.count = this.text.length + this.counts = [this.count] + } + + newAtlasChars = [] + + // detect & measure new characters + this.font.forEach(function (font, idx) { + GlText.atlasContext.font = font.baseString + + var atlas = this$1.fontAtlas[idx] + + for (var i = 0; i < this$1.text.length; i++) { + var char = this$1.text.charAt(i) + + if (atlas.ids[char] == null) { + atlas.ids[char] = atlas.chars.length + atlas.chars.push(char) + newAtlasChars.push(char) + } + + if (font.width[char] == null) { + font.width[char] = GlText.atlasContext.measureText(char).width / GlText.baseFontSize + + // measure kerning pairs for the new character + if (this$1.kerning) { + var pairs = [] + for (var baseChar in font.width) { + pairs.push(baseChar + char, char + baseChar) + } + extend(font.kerning, kerning(font.family, { + pairs: pairs + })) + } + } + } + }) + } + + // create single position buffer (faster than batch or multiple separate instances) + if (o.position) { + if (o.position.length > 2) { + var flat = !o.position[0].length + var positionData = pool.mallocFloat(this.count * 2) + for (var i$2 = 0, ptr = 0; i$2 < this.counts.length; i$2++) { + var count = this$1.counts[i$2] + if (flat) { + for (var j = 0; j < count; j++) { + positionData[ptr++] = o.position[i$2 * 2] + positionData[ptr++] = o.position[i$2 * 2 + 1] + } + } + else { + for (var j$1 = 0; j$1 < count; j$1++) { + positionData[ptr++] = o.position[i$2][0] + positionData[ptr++] = o.position[i$2][1] + } + } + } + if (this.position.call) { + this.position({ + type: 'float', + data: positionData + }) + } else { + this.position = this.regl.buffer({ + type: 'float', + data: positionData + }) + } + pool.freeFloat(positionData) + } + else { + if (this.position.destroy) { this.position.destroy() } + this.position = { + constant: o.position + } + } + } + + // populate text/offset buffers if font/text has changed + // as [charWidth, offset, charWidth, offset...] + // that is in em units since font-size can change often + if (o.text || newFont) { + var charIds = pool.mallocUint8(this.count) + var sizeData = pool.mallocFloat(this.count * 2) + this.textWidth = [] + + for (var i$3 = 0, ptr$1 = 0; i$3 < this.counts.length; i$3++) { + var count$1 = this$1.counts[i$3] + var font = this$1.font[i$3] || this$1.font[0] + var atlas = this$1.fontAtlas[i$3] || this$1.fontAtlas[0] + + for (var j$2 = 0; j$2 < count$1; j$2++) { + var char = this$1.text.charAt(ptr$1) + var prevChar = this$1.text.charAt(ptr$1 - 1) + + charIds[ptr$1] = atlas.ids[char] + sizeData[ptr$1 * 2] = font.width[char] + + if (j$2) { + var prevWidth = sizeData[ptr$1 * 2 - 2] + var currWidth = sizeData[ptr$1 * 2] + var prevOffset = sizeData[ptr$1 * 2 - 1] + var offset = prevOffset + prevWidth * .5 + currWidth * .5; + + if (this$1.kerning) { + var kerning$1 = font.kerning[prevChar + char] + if (kerning$1) { + offset += kerning$1 * 1e-3 + } + } + + sizeData[ptr$1 * 2 + 1] = offset + } + else { + sizeData[ptr$1 * 2 + 1] = sizeData[ptr$1 * 2] * .5 + } + + ptr$1++ + } + this$1.textWidth.push( + !sizeData.length ? 0 : + // last offset + half last width + sizeData[ptr$1 * 2 - 2] * .5 + sizeData[ptr$1 * 2 - 1] + ) + } + + + // bump recalc align offset + if (!o.align) { o.align = this.align } + this.charBuffer({data: charIds, type: 'uint8', usage: 'stream'}) + this.sizeBuffer({data: sizeData, type: 'float', usage: 'stream'}) + pool.freeUint8(charIds) + pool.freeFloat(sizeData) + + // udpate font atlas and texture + if (newAtlasChars.length) { + this.font.forEach(function (font, i) { + var atlas = this$1.fontAtlas[i] + + // FIXME: insert metrics-based ratio here + var step = atlas.step + + var maxCols = Math.floor(GlText.maxAtlasSize / step) + var cols = Math.min(maxCols, atlas.chars.length) + var rows = Math.ceil(atlas.chars.length / cols) + + var atlasWidth = nextPow2( cols * step ) + // let atlasHeight = Math.min(rows * step + step * .5, GlText.maxAtlasSize); + var atlasHeight = nextPow2( rows * step ); + + atlas.width = atlasWidth + atlas.height = atlasHeight; + atlas.rows = rows + atlas.cols = cols + + if (!atlas.em) { return } + + atlas.texture({ + data: fontAtlas({ + canvas: GlText.atlasCanvas, + font: atlas.fontString, + chars: atlas.chars, + shape: [atlasWidth, atlasHeight], + step: [step, step] + }) + }) + + }) + } + } + + if (o.align) { + this.align = o.align + this.alignOffset = this.textWidth.map(function (textWidth, i) { + var align = !Array.isArray(this$1.align) ? this$1.align : this$1.align.length > 1 ? this$1.align[i] : this$1.align[0] + + if (typeof align === 'number') { return align } + switch (align) { + case 'right': + case 'end': + return -textWidth + case 'center': + case 'centre': + case 'middle': + return -textWidth * .5 + } + + return 0 + }) + } + + if (this.baseline == null && o.baseline == null) { + o.baseline = 0 + } + if (o.baseline != null) { + this.baseline = o.baseline + if (!Array.isArray(this.baseline)) { this.baseline = [this.baseline] } + this.baselineOffset = this.baseline.map(function (baseline, i) { + var m = (this$1.font[i] || this$1.font[0]).metrics + var base = 0 + + base += m.bottom * .5 + + if (typeof baseline === 'number') { + base += (baseline - m.baseline) + } + else { + base += -m[baseline] + } + + if (!GlText.normalViewport) { base *= -1 } + return base + }) + } + + // flatten colors to a single uint8 array + if (o.color != null) { + if (!o.color) { o.color = 'transparent' } + + // single color + if (typeof o.color === 'string' || !isNaN(o.color)) { + this.color = rgba(o.color, 'uint8') + } + // array + else { + var colorData + + // flat array + if (typeof o.color[0] === 'number' && o.color.length > this.counts.length) { + var l = o.color.length + colorData = pool.mallocUint8(l) + var sub = (o.color.subarray || o.color.slice).bind(o.color) + for (var i$4 = 0; i$4 < l; i$4 += 4) { + colorData.set(rgba(sub(i$4, i$4 + 4), 'uint8'), i$4) + } + } + // nested array + else { + var l$1 = o.color.length + colorData = pool.mallocUint8(l$1 * 4) + for (var i$5 = 0; i$5 < l$1; i$5++) { + colorData.set(rgba(o.color[i$5] || 0, 'uint8'), i$5 * 4) + } + } + + this.color = colorData + } + } + + // update render batch + if (o.position || o.text || o.color || o.baseline || o.align || o.font || o.offset || o.opacity) { + var isBatch = (this.color.length > 4) + || (this.baselineOffset.length > 1) + || (this.align && this.align.length > 1) + || (this.fontAtlas.length > 1) + || (this.positionOffset.length > 2) + if (isBatch) { + var length = Math.max( + this.position.length * .5 || 0, + this.color.length * .25 || 0, + this.baselineOffset.length || 0, + this.alignOffset.length || 0, + this.font.length || 0, + this.opacity.length || 0, + this.positionOffset.length * .5 || 0 + ) + this.batch = Array(length) + for (var i$6 = 0; i$6 < this.batch.length; i$6++) { + this$1.batch[i$6] = { + count: this$1.counts.length > 1 ? this$1.counts[i$6] : this$1.counts[0], + offset: this$1.textOffsets.length > 1 ? this$1.textOffsets[i$6] : this$1.textOffsets[0], + color: !this$1.color ? [0,0,0,255] : this$1.color.length <= 4 ? this$1.color : this$1.color.subarray(i$6 * 4, i$6 * 4 + 4), + opacity: Array.isArray(this$1.opacity) ? this$1.opacity[i$6] : this$1.opacity, + baseline: this$1.baselineOffset[i$6] != null ? this$1.baselineOffset[i$6] : this$1.baselineOffset[0], + align: !this$1.align ? 0 : this$1.alignOffset[i$6] != null ? this$1.alignOffset[i$6] : this$1.alignOffset[0], + atlas: this$1.fontAtlas[i$6] || this$1.fontAtlas[0], + positionOffset: this$1.positionOffset.length > 2 ? this$1.positionOffset.subarray(i$6 * 2, i$6 * 2 + 2) : this$1.positionOffset + } + } + } + // single-color, single-baseline, single-align batch is faster to render + else { + if (this.count) { + this.batch = [{ + count: this.count, + offset: 0, + color: this.color || [0,0,0,255], + opacity: Array.isArray(this.opacity) ? this.opacity[0] : this.opacity, + baseline: this.baselineOffset[0], + align: this.alignOffset ? this.alignOffset[0] : 0, + atlas: this.fontAtlas[0], + positionOffset: this.positionOffset + }] + } + else { + this.batch = [] + } + } + } +}; + +GlText.prototype.destroy = function destroy () { + // TODO: count instances of atlases and destroy all on null +}; + + +// defaults +GlText.prototype.kerning = true +GlText.prototype.position = { constant: new Float32Array(2) } +GlText.prototype.translate = null +GlText.prototype.scale = null +GlText.prototype.font = null +GlText.prototype.text = '' +GlText.prototype.positionOffset = [0, 0] +GlText.prototype.opacity = 1 +GlText.prototype.color = new Uint8Array([0, 0, 0, 255]) +GlText.prototype.alignOffset = [0, 0] + + +// whether viewport should be top↓bottom 2d one (true) or webgl one (false) +GlText.normalViewport = false + +// size of an atlas +GlText.maxAtlasSize = 1024 + +// font atlas canvas is singleton +GlText.atlasCanvas = document.createElement('canvas') +GlText.atlasContext = GlText.atlasCanvas.getContext('2d', {alpha: false}) + +// font-size used for metrics, atlas step calculation +GlText.baseFontSize = 64 + +// fonts storage +GlText.fonts = {} + +// max number of different font atlases/textures cached +// FIXME: enable atlas size limitation via LRU +// GlText.atlasCacheSize = 64 + +function isRegl (o) { + return typeof o === 'function' && + o._gl && + o.prop && + o.texture && + o.buffer +} + + +module.exports = GlText + + +},{"bit-twiddle":80,"color-normalize":108,"css-font":127,"detect-kerning":151,"es6-weak-map":209,"flatten-vertex-data":216,"font-atlas":217,"font-measure":218,"gl-util/context":306,"is-plain-obj":405,"object-assign":437,"parse-rect":442,"parse-unit":444,"pick-by-alias":448,"regl":478,"to-px":516,"typedarray-pool":522}],305:[function(_dereq_,module,exports){ +'use strict' + +var ndarray = _dereq_('ndarray') +var ops = _dereq_('ndarray-ops') +var pool = _dereq_('typedarray-pool') + +module.exports = createTexture2D + +var linearTypes = null +var filterTypes = null +var wrapTypes = null + +function lazyInitLinearTypes(gl) { + linearTypes = [ + gl.LINEAR, + gl.NEAREST_MIPMAP_LINEAR, + gl.LINEAR_MIPMAP_NEAREST, + gl.LINEAR_MIPMAP_NEAREST + ] + filterTypes = [ + gl.NEAREST, + gl.LINEAR, + gl.NEAREST_MIPMAP_NEAREST, + gl.NEAREST_MIPMAP_LINEAR, + gl.LINEAR_MIPMAP_NEAREST, + gl.LINEAR_MIPMAP_LINEAR + ] + wrapTypes = [ + gl.REPEAT, + gl.CLAMP_TO_EDGE, + gl.MIRRORED_REPEAT + ] +} + +function acceptTextureDOM (obj) { + return ( + ('undefined' != typeof HTMLCanvasElement && obj instanceof HTMLCanvasElement) || + ('undefined' != typeof HTMLImageElement && obj instanceof HTMLImageElement) || + ('undefined' != typeof HTMLVideoElement && obj instanceof HTMLVideoElement) || + ('undefined' != typeof ImageData && obj instanceof ImageData)) +} + +var convertFloatToUint8 = function(out, inp) { + ops.muls(out, inp, 255.0) +} + +function reshapeTexture(tex, w, h) { + var gl = tex.gl + var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(w < 0 || w > maxSize || h < 0 || h > maxSize) { + throw new Error('gl-texture2d: Invalid texture size') + } + tex._shape = [w, h] + tex.bind() + gl.texImage2D(gl.TEXTURE_2D, 0, tex.format, w, h, 0, tex.format, tex.type, null) + tex._mipLevels = [0] + return tex +} + +function Texture2D(gl, handle, width, height, format, type) { + this.gl = gl + this.handle = handle + this.format = format + this.type = type + this._shape = [width, height] + this._mipLevels = [0] + this._magFilter = gl.NEAREST + this._minFilter = gl.NEAREST + this._wrapS = gl.CLAMP_TO_EDGE + this._wrapT = gl.CLAMP_TO_EDGE + this._anisoSamples = 1 + + var parent = this + var wrapVector = [this._wrapS, this._wrapT] + Object.defineProperties(wrapVector, [ + { + get: function() { + return parent._wrapS + }, + set: function(v) { + return parent.wrapS = v + } + }, + { + get: function() { + return parent._wrapT + }, + set: function(v) { + return parent.wrapT = v + } + } + ]) + this._wrapVector = wrapVector + + var shapeVector = [this._shape[0], this._shape[1]] + Object.defineProperties(shapeVector, [ + { + get: function() { + return parent._shape[0] + }, + set: function(v) { + return parent.width = v + } + }, + { + get: function() { + return parent._shape[1] + }, + set: function(v) { + return parent.height = v + } + } + ]) + this._shapeVector = shapeVector +} + +var proto = Texture2D.prototype + +Object.defineProperties(proto, { + minFilter: { + get: function() { + return this._minFilter + }, + set: function(v) { + this.bind() + var gl = this.gl + if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { + if(!gl.getExtension('OES_texture_float_linear')) { + v = gl.NEAREST + } + } + if(filterTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown filter mode ' + v) + } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, v) + return this._minFilter = v + } + }, + magFilter: { + get: function() { + return this._magFilter + }, + set: function(v) { + this.bind() + var gl = this.gl + if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { + if(!gl.getExtension('OES_texture_float_linear')) { + v = gl.NEAREST + } + } + if(filterTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown filter mode ' + v) + } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, v) + return this._magFilter = v + } + }, + mipSamples: { + get: function() { + return this._anisoSamples + }, + set: function(i) { + var psamples = this._anisoSamples + this._anisoSamples = Math.max(i, 1)|0 + if(psamples !== this._anisoSamples) { + var ext = this.gl.getExtension('EXT_texture_filter_anisotropic') + if(ext) { + this.gl.texParameterf(this.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisoSamples) + } + } + return this._anisoSamples + } + }, + wrapS: { + get: function() { + return this._wrapS + }, + set: function(v) { + this.bind() + if(wrapTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) + } + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, v) + return this._wrapS = v + } + }, + wrapT: { + get: function() { + return this._wrapT + }, + set: function(v) { + this.bind() + if(wrapTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) + } + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, v) + return this._wrapT = v + } + }, + wrap: { + get: function() { + return this._wrapVector + }, + set: function(v) { + if(!Array.isArray(v)) { + v = [v,v] + } + if(v.length !== 2) { + throw new Error('gl-texture2d: Must specify wrap mode for rows and columns') + } + for(var i=0; i<2; ++i) { + if(wrapTypes.indexOf(v[i]) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) + } + } + this._wrapS = v[0] + this._wrapT = v[1] + + var gl = this.gl + this.bind() + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT) + + return v + } + }, + shape: { + get: function() { + return this._shapeVector + }, + set: function(x) { + if(!Array.isArray(x)) { + x = [x|0,x|0] + } else { + if(x.length !== 2) { + throw new Error('gl-texture2d: Invalid texture shape') + } + } + reshapeTexture(this, x[0]|0, x[1]|0) + return [x[0]|0, x[1]|0] + } + }, + width: { + get: function() { + return this._shape[0] + }, + set: function(w) { + w = w|0 + reshapeTexture(this, w, this._shape[1]) + return w + } + }, + height: { + get: function() { + return this._shape[1] + }, + set: function(h) { + h = h|0 + reshapeTexture(this, this._shape[0], h) + return h + } + } +}) + +proto.bind = function(unit) { + var gl = this.gl + if(unit !== undefined) { + gl.activeTexture(gl.TEXTURE0 + (unit|0)) + } + gl.bindTexture(gl.TEXTURE_2D, this.handle) + if(unit !== undefined) { + return (unit|0) + } + return gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0 +} + +proto.dispose = function() { + this.gl.deleteTexture(this.handle) +} + +proto.generateMipmap = function() { + this.bind() + this.gl.generateMipmap(this.gl.TEXTURE_2D) + + //Update mip levels + var l = Math.min(this._shape[0], this._shape[1]) + for(var i=0; l>0; ++i, l>>>=1) { + if(this._mipLevels.indexOf(i) < 0) { + this._mipLevels.push(i) + } + } +} + +proto.setPixels = function(data, x_off, y_off, mip_level) { + var gl = this.gl + this.bind() + if(Array.isArray(x_off)) { + mip_level = y_off + y_off = x_off[1]|0 + x_off = x_off[0]|0 + } else { + x_off = x_off || 0 + y_off = y_off || 0 + } + mip_level = mip_level || 0 + var directData = acceptTextureDOM(data) ? data : data.raw + if(directData) { + var needsMip = this._mipLevels.indexOf(mip_level) < 0 + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, directData) + this._mipLevels.push(mip_level) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, this.format, this.type, directData) + } + } else if(data.shape && data.stride && data.data) { + if(data.shape.length < 2 || + x_off + data.shape[1] > this._shape[1]>>>mip_level || + y_off + data.shape[0] > this._shape[0]>>>mip_level || + x_off < 0 || + y_off < 0) { + throw new Error('gl-texture2d: Texture dimensions are out of bounds') + } + texSubImageArray(gl, x_off, y_off, mip_level, this.format, this.type, this._mipLevels, data) + } else { + throw new Error('gl-texture2d: Unsupported data type') + } +} + + +function isPacked(shape, stride) { + if(shape.length === 3) { + return (stride[2] === 1) && + (stride[1] === shape[0]*shape[2]) && + (stride[0] === shape[2]) + } + return (stride[0] === 1) && + (stride[1] === shape[0]) +} + +function texSubImageArray(gl, x_off, y_off, mip_level, cformat, ctype, mipLevels, array) { + var dtype = array.dtype + var shape = array.shape.slice() + if(shape.length < 2 || shape.length > 3) { + throw new Error('gl-texture2d: Invalid ndarray, must be 2d or 3d') + } + var type = 0, format = 0 + var packed = isPacked(shape, array.stride.slice()) + if(dtype === 'float32') { + type = gl.FLOAT + } else if(dtype === 'float64') { + type = gl.FLOAT + packed = false + dtype = 'float32' + } else if(dtype === 'uint8') { + type = gl.UNSIGNED_BYTE + } else { + type = gl.UNSIGNED_BYTE + packed = false + dtype = 'uint8' + } + var channels = 1 + if(shape.length === 2) { + format = gl.LUMINANCE + shape = [shape[0], shape[1], 1] + array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) + } else if(shape.length === 3) { + if(shape[2] === 1) { + format = gl.ALPHA + } else if(shape[2] === 2) { + format = gl.LUMINANCE_ALPHA + } else if(shape[2] === 3) { + format = gl.RGB + } else if(shape[2] === 4) { + format = gl.RGBA + } else { + throw new Error('gl-texture2d: Invalid shape for pixel coords') + } + channels = shape[2] + } else { + throw new Error('gl-texture2d: Invalid shape for texture') + } + //For 1-channel textures allow conversion between formats + if((format === gl.LUMINANCE || format === gl.ALPHA) && + (cformat === gl.LUMINANCE || cformat === gl.ALPHA)) { + format = cformat + } + if(format !== cformat) { + throw new Error('gl-texture2d: Incompatible texture format for setPixels') + } + var size = array.size + var needsMip = mipLevels.indexOf(mip_level) < 0 + if(needsMip) { + mipLevels.push(mip_level) + } + if(type === ctype && packed) { + //Array data types are compatible, can directly copy into texture + if(array.offset === 0 && array.data.length === size) { + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data) + } + } else { + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data.subarray(array.offset, array.offset+size)) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data.subarray(array.offset, array.offset+size)) + } + } + } else { + //Need to do type conversion to pack data into buffer + var pack_buffer + if(ctype === gl.FLOAT) { + pack_buffer = pool.mallocFloat32(size) + } else { + pack_buffer = pool.mallocUint8(size) + } + var pack_view = ndarray(pack_buffer, shape, [shape[2], shape[2]*shape[0], 1]) + if(type === gl.FLOAT && ctype === gl.UNSIGNED_BYTE) { + convertFloatToUint8(pack_view, array) + } else { + ops.assign(pack_view, array) + } + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, pack_buffer.subarray(0, size)) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, pack_buffer.subarray(0, size)) + } + if(ctype === gl.FLOAT) { + pool.freeFloat32(pack_buffer) + } else { + pool.freeUint8(pack_buffer) + } + } +} + +function initTexture(gl) { + var tex = gl.createTexture() + gl.bindTexture(gl.TEXTURE_2D, tex) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + return tex +} + +function createTextureShape(gl, width, height, format, type) { + var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(width < 0 || width > maxTextureSize || height < 0 || height > maxTextureSize) { + throw new Error('gl-texture2d: Invalid texture shape') + } + if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { + throw new Error('gl-texture2d: Floating point textures not supported on this platform') + } + var tex = initTexture(gl) + gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null) + return new Texture2D(gl, tex, width, height, format, type) +} + +function createTextureDOM(gl, directData, width, height, format, type) { + var tex = initTexture(gl) + gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, directData) + return new Texture2D(gl, tex, width, height, format, type) +} + +//Creates a texture from an ndarray +function createTextureArray(gl, array) { + var dtype = array.dtype + var shape = array.shape.slice() + var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(shape[0] < 0 || shape[0] > maxSize || shape[1] < 0 || shape[1] > maxSize) { + throw new Error('gl-texture2d: Invalid texture size') + } + var packed = isPacked(shape, array.stride.slice()) + var type = 0 + if(dtype === 'float32') { + type = gl.FLOAT + } else if(dtype === 'float64') { + type = gl.FLOAT + packed = false + dtype = 'float32' + } else if(dtype === 'uint8') { + type = gl.UNSIGNED_BYTE + } else { + type = gl.UNSIGNED_BYTE + packed = false + dtype = 'uint8' + } + var format = 0 + if(shape.length === 2) { + format = gl.LUMINANCE + shape = [shape[0], shape[1], 1] + array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) + } else if(shape.length === 3) { + if(shape[2] === 1) { + format = gl.ALPHA + } else if(shape[2] === 2) { + format = gl.LUMINANCE_ALPHA + } else if(shape[2] === 3) { + format = gl.RGB + } else if(shape[2] === 4) { + format = gl.RGBA + } else { + throw new Error('gl-texture2d: Invalid shape for pixel coords') + } + } else { + throw new Error('gl-texture2d: Invalid shape for texture') + } + if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { + type = gl.UNSIGNED_BYTE + packed = false + } + var buffer, buf_store + var size = array.size + if(!packed) { + var stride = [shape[2], shape[2]*shape[0], 1] + buf_store = pool.malloc(size, dtype) + var buf_array = ndarray(buf_store, shape, stride, 0) + if((dtype === 'float32' || dtype === 'float64') && type === gl.UNSIGNED_BYTE) { + convertFloatToUint8(buf_array, array) + } else { + ops.assign(buf_array, array) + } + buffer = buf_store.subarray(0, size) + } else if (array.offset === 0 && array.data.length === size) { + buffer = array.data + } else { + buffer = array.data.subarray(array.offset, array.offset + size) + } + var tex = initTexture(gl) + gl.texImage2D(gl.TEXTURE_2D, 0, format, shape[0], shape[1], 0, format, type, buffer) + if(!packed) { + pool.free(buf_store) + } + return new Texture2D(gl, tex, shape[0], shape[1], format, type) +} + +function createTexture2D(gl) { + if(arguments.length <= 1) { + throw new Error('gl-texture2d: Missing arguments for texture2d constructor') + } + if(!linearTypes) { + lazyInitLinearTypes(gl) + } + if(typeof arguments[1] === 'number') { + return createTextureShape(gl, arguments[1], arguments[2], arguments[3]||gl.RGBA, arguments[4]||gl.UNSIGNED_BYTE) + } + if(Array.isArray(arguments[1])) { + return createTextureShape(gl, arguments[1][0]|0, arguments[1][1]|0, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) + } + if(typeof arguments[1] === 'object') { + var obj = arguments[1] + var directData = acceptTextureDOM(obj) ? obj : obj.raw + if (directData) { + return createTextureDOM(gl, directData, obj.width|0, obj.height|0, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) + } else if(obj.shape && obj.data && obj.stride) { + return createTextureArray(gl, obj) + } + } + throw new Error('gl-texture2d: Invalid arguments for texture2d constructor') +} + +},{"ndarray":433,"ndarray-ops":427,"typedarray-pool":522}],306:[function(_dereq_,module,exports){ +/** @module gl-util/context */ +'use strict' + +var pick = _dereq_('pick-by-alias') + +module.exports = function setContext (o) { + if (!o) o = {} + else if (typeof o === 'string') o = {container: o} + + // HTMLCanvasElement + if (isCanvas(o)) { + o = {container: o} + } + // HTMLElement + else if (isElement(o)) { + o = {container: o} + } + // WebGLContext + else if (isContext(o)) { + o = {gl: o} + } + // options object + else { + o = pick(o, { + container: 'container target element el canvas holder parent parentNode wrapper use ref root node', + gl: 'gl context webgl glContext', + attrs: 'attributes attrs contextAttributes', + pixelRatio: 'pixelRatio pxRatio px ratio pxratio pixelratio' + }, true) + } + + if (!o.pixelRatio) o.pixelRatio = window.pixelRatio || 1 + + // make sure there is container and canvas + if (o.gl) { + return o.gl + } + if (o.canvas) { + o.container = o.canvas.parentNode + } + if (o.container) { + if (typeof o.container === 'string') { + var c = document.querySelector(o.container) + if (!c) throw Error('Element ' + o.container + ' is not found') + o.container = c + } + if (isCanvas(o.container)) { + o.canvas = o.container + o.container = o.canvas.parentNode + } + else if (!o.canvas) { + o.canvas = document.createElement('canvas') + o.container.appendChild(o.canvas) + resize(o) + } + } + // blank new canvas + else if (!o.canvas) { + o.container = document.body || document.documentElement + o.canvas = document.createElement('canvas') + o.canvas.style.position = 'absolute' + o.canvas.style.top = 0 + o.canvas.style.left = 0 + o.container.appendChild(o.canvas) + resize(o) + } + + // make sure there is context + if (!o.gl) { + try { + o.gl = o.canvas.getContext('webgl', o.attrs) + } catch (e) { + try { + o.gl = o.canvas.getContext('experimental-webgl', o.attrs) + } + catch (e) { + o.gl = o.canvas.getContext('webgl-experimental', o.attrs) + } + } + } + + return o.gl +} + + +function resize (o) { + if (o.container) { + if (o.container == document.body) { + if (!document.body.style.width) o.canvas.width = o.width || (o.pixelRatio * window.innerWidth) + if (!document.body.style.height) o.canvas.height = o.height || (o.pixelRatio * window.innerHeight) + } + else { + var bounds = o.container.getBoundingClientRect() + o.canvas.width = o.width || (bounds.right - bounds.left) + o.canvas.height = o.height || (bounds.bottom - bounds.top) + } + } +} + +function isCanvas (e) { + return typeof e.getContext === 'function' + && 'width' in e + && 'height' in e +} + +function isElement (e) { + return typeof e.nodeName === 'string' && + typeof e.appendChild === 'function' && + typeof e.getBoundingClientRect === 'function' +} + +function isContext (e) { + return typeof e.drawArrays === 'function' || + typeof e.drawElements === 'function' +} + +},{"pick-by-alias":448}],307:[function(_dereq_,module,exports){ +"use strict" + +function doBind(gl, elements, attributes) { + if(elements) { + elements.bind() + } else { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) + } + var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0 + if(attributes) { + if(attributes.length > nattribs) { + throw new Error("gl-vao: Too many vertex attributes") + } + for(var i=0; i 1.0){ + return 0 + } else { + return Math.acos(cosine) + } +} + +},{"./dot":322,"./fromValues":328,"./normalize":339}],313:[function(_dereq_,module,exports){ +module.exports = ceil + +/** + * Math.ceil the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to ceil + * @returns {vec3} out + */ +function ceil(out, a) { + out[0] = Math.ceil(a[0]) + out[1] = Math.ceil(a[1]) + out[2] = Math.ceil(a[2]) + return out +} + +},{}],314:[function(_dereq_,module,exports){ +module.exports = clone; + +/** + * Creates a new vec3 initialized with values from an existing vector + * + * @param {vec3} a vector to clone + * @returns {vec3} a new 3D vector + */ +function clone(a) { + var out = new Float32Array(3) + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + return out +} +},{}],315:[function(_dereq_,module,exports){ +module.exports = copy; + +/** + * Copy the values from one vec3 to another + * + * @param {vec3} out the receiving vector + * @param {vec3} a the source vector + * @returns {vec3} out + */ +function copy(out, a) { + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + return out +} +},{}],316:[function(_dereq_,module,exports){ +module.exports = create; + +/** + * Creates a new, empty vec3 + * + * @returns {vec3} a new 3D vector + */ +function create() { + var out = new Float32Array(3) + out[0] = 0 + out[1] = 0 + out[2] = 0 + return out +} +},{}],317:[function(_dereq_,module,exports){ +module.exports = cross; + +/** + * Computes the cross product of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function cross(out, a, b) { + var ax = a[0], ay = a[1], az = a[2], + bx = b[0], by = b[1], bz = b[2] + + out[0] = ay * bz - az * by + out[1] = az * bx - ax * bz + out[2] = ax * by - ay * bx + return out +} +},{}],318:[function(_dereq_,module,exports){ +module.exports = _dereq_('./distance') + +},{"./distance":319}],319:[function(_dereq_,module,exports){ +module.exports = distance; + +/** + * Calculates the euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} distance between a and b + */ +function distance(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2] + return Math.sqrt(x*x + y*y + z*z) +} +},{}],320:[function(_dereq_,module,exports){ +module.exports = _dereq_('./divide') + +},{"./divide":321}],321:[function(_dereq_,module,exports){ +module.exports = divide; + +/** + * Divides two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function divide(out, a, b) { + out[0] = a[0] / b[0] + out[1] = a[1] / b[1] + out[2] = a[2] / b[2] + return out +} +},{}],322:[function(_dereq_,module,exports){ +module.exports = dot; + +/** + * Calculates the dot product of two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} dot product of a and b + */ +function dot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] +} +},{}],323:[function(_dereq_,module,exports){ +module.exports = 0.000001 + +},{}],324:[function(_dereq_,module,exports){ +module.exports = equals + +var EPSILON = _dereq_('./epsilon') + +/** + * Returns whether or not the vectors have approximately the same elements in the same position. + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0] + var a1 = a[1] + var a2 = a[2] + var b0 = b[0] + var b1 = b[1] + var b2 = b[2] + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))) +} + +},{"./epsilon":323}],325:[function(_dereq_,module,exports){ +module.exports = exactEquals + +/** + * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] +} + +},{}],326:[function(_dereq_,module,exports){ +module.exports = floor + +/** + * Math.floor the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to floor + * @returns {vec3} out + */ +function floor(out, a) { + out[0] = Math.floor(a[0]) + out[1] = Math.floor(a[1]) + out[2] = Math.floor(a[2]) + return out +} + +},{}],327:[function(_dereq_,module,exports){ +module.exports = forEach; + +var vec = _dereq_('./create')() + +/** + * Perform some operation over an array of vec3s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +function forEach(a, stride, offset, count, fn, arg) { + var i, l + if(!stride) { + stride = 3 + } + + if(!offset) { + offset = 0 + } + + if(count) { + l = Math.min((count * stride) + offset, a.length) + } else { + l = a.length + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i] + vec[1] = a[i+1] + vec[2] = a[i+2] + fn(vec, vec, arg) + a[i] = vec[0] + a[i+1] = vec[1] + a[i+2] = vec[2] + } + + return a +} +},{"./create":316}],328:[function(_dereq_,module,exports){ +module.exports = fromValues; + +/** + * Creates a new vec3 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} a new 3D vector + */ +function fromValues(x, y, z) { + var out = new Float32Array(3) + out[0] = x + out[1] = y + out[2] = z + return out +} +},{}],329:[function(_dereq_,module,exports){ +module.exports = { + EPSILON: _dereq_('./epsilon') + , create: _dereq_('./create') + , clone: _dereq_('./clone') + , angle: _dereq_('./angle') + , fromValues: _dereq_('./fromValues') + , copy: _dereq_('./copy') + , set: _dereq_('./set') + , equals: _dereq_('./equals') + , exactEquals: _dereq_('./exactEquals') + , add: _dereq_('./add') + , subtract: _dereq_('./subtract') + , sub: _dereq_('./sub') + , multiply: _dereq_('./multiply') + , mul: _dereq_('./mul') + , divide: _dereq_('./divide') + , div: _dereq_('./div') + , min: _dereq_('./min') + , max: _dereq_('./max') + , floor: _dereq_('./floor') + , ceil: _dereq_('./ceil') + , round: _dereq_('./round') + , scale: _dereq_('./scale') + , scaleAndAdd: _dereq_('./scaleAndAdd') + , distance: _dereq_('./distance') + , dist: _dereq_('./dist') + , squaredDistance: _dereq_('./squaredDistance') + , sqrDist: _dereq_('./sqrDist') + , length: _dereq_('./length') + , len: _dereq_('./len') + , squaredLength: _dereq_('./squaredLength') + , sqrLen: _dereq_('./sqrLen') + , negate: _dereq_('./negate') + , inverse: _dereq_('./inverse') + , normalize: _dereq_('./normalize') + , dot: _dereq_('./dot') + , cross: _dereq_('./cross') + , lerp: _dereq_('./lerp') + , random: _dereq_('./random') + , transformMat4: _dereq_('./transformMat4') + , transformMat3: _dereq_('./transformMat3') + , transformQuat: _dereq_('./transformQuat') + , rotateX: _dereq_('./rotateX') + , rotateY: _dereq_('./rotateY') + , rotateZ: _dereq_('./rotateZ') + , forEach: _dereq_('./forEach') +} + +},{"./add":311,"./angle":312,"./ceil":313,"./clone":314,"./copy":315,"./create":316,"./cross":317,"./dist":318,"./distance":319,"./div":320,"./divide":321,"./dot":322,"./epsilon":323,"./equals":324,"./exactEquals":325,"./floor":326,"./forEach":327,"./fromValues":328,"./inverse":330,"./len":331,"./length":332,"./lerp":333,"./max":334,"./min":335,"./mul":336,"./multiply":337,"./negate":338,"./normalize":339,"./random":340,"./rotateX":341,"./rotateY":342,"./rotateZ":343,"./round":344,"./scale":345,"./scaleAndAdd":346,"./set":347,"./sqrDist":348,"./sqrLen":349,"./squaredDistance":350,"./squaredLength":351,"./sub":352,"./subtract":353,"./transformMat3":354,"./transformMat4":355,"./transformQuat":356}],330:[function(_dereq_,module,exports){ +module.exports = inverse; + +/** + * Returns the inverse of the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to invert + * @returns {vec3} out + */ +function inverse(out, a) { + out[0] = 1.0 / a[0] + out[1] = 1.0 / a[1] + out[2] = 1.0 / a[2] + return out +} +},{}],331:[function(_dereq_,module,exports){ +module.exports = _dereq_('./length') + +},{"./length":332}],332:[function(_dereq_,module,exports){ +module.exports = length; + +/** + * Calculates the length of a vec3 + * + * @param {vec3} a vector to calculate length of + * @returns {Number} length of a + */ +function length(a) { + var x = a[0], + y = a[1], + z = a[2] + return Math.sqrt(x*x + y*y + z*z) +} +},{}],333:[function(_dereq_,module,exports){ +module.exports = lerp; + +/** + * Performs a linear interpolation between two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ +function lerp(out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2] + out[0] = ax + t * (b[0] - ax) + out[1] = ay + t * (b[1] - ay) + out[2] = az + t * (b[2] - az) + return out +} +},{}],334:[function(_dereq_,module,exports){ +module.exports = max; + +/** + * Returns the maximum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function max(out, a, b) { + out[0] = Math.max(a[0], b[0]) + out[1] = Math.max(a[1], b[1]) + out[2] = Math.max(a[2], b[2]) + return out +} +},{}],335:[function(_dereq_,module,exports){ +module.exports = min; + +/** + * Returns the minimum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function min(out, a, b) { + out[0] = Math.min(a[0], b[0]) + out[1] = Math.min(a[1], b[1]) + out[2] = Math.min(a[2], b[2]) + return out +} +},{}],336:[function(_dereq_,module,exports){ +module.exports = _dereq_('./multiply') + +},{"./multiply":337}],337:[function(_dereq_,module,exports){ +module.exports = multiply; + +/** + * Multiplies two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function multiply(out, a, b) { + out[0] = a[0] * b[0] + out[1] = a[1] * b[1] + out[2] = a[2] * b[2] + return out +} +},{}],338:[function(_dereq_,module,exports){ +module.exports = negate; + +/** + * Negates the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to negate + * @returns {vec3} out + */ +function negate(out, a) { + out[0] = -a[0] + out[1] = -a[1] + out[2] = -a[2] + return out +} +},{}],339:[function(_dereq_,module,exports){ +module.exports = normalize; + +/** + * Normalize a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to normalize + * @returns {vec3} out + */ +function normalize(out, a) { + var x = a[0], + y = a[1], + z = a[2] + var len = x*x + y*y + z*z + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len) + out[0] = a[0] * len + out[1] = a[1] * len + out[2] = a[2] * len + } + return out +} +},{}],340:[function(_dereq_,module,exports){ +module.exports = random; + +/** + * Generates a random vector with the given scale + * + * @param {vec3} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec3} out + */ +function random(out, scale) { + scale = scale || 1.0 + + var r = Math.random() * 2.0 * Math.PI + var z = (Math.random() * 2.0) - 1.0 + var zScale = Math.sqrt(1.0-z*z) * scale + + out[0] = Math.cos(r) * zScale + out[1] = Math.sin(r) * zScale + out[2] = z * scale + return out +} +},{}],341:[function(_dereq_,module,exports){ +module.exports = rotateX; + +/** + * Rotate a 3D vector around the x-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +function rotateX(out, a, b, c){ + var by = b[1] + var bz = b[2] + + // Translate point to the origin + var py = a[1] - by + var pz = a[2] - bz + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = a[0] + out[1] = by + py * cc - pz * sc + out[2] = bz + py * sc + pz * cc + + return out +} + +},{}],342:[function(_dereq_,module,exports){ +module.exports = rotateY; + +/** + * Rotate a 3D vector around the y-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +function rotateY(out, a, b, c){ + var bx = b[0] + var bz = b[2] + + // translate point to the origin + var px = a[0] - bx + var pz = a[2] - bz + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = bx + pz * sc + px * cc + out[1] = a[1] + out[2] = bz + pz * cc - px * sc + + return out +} + +},{}],343:[function(_dereq_,module,exports){ +module.exports = rotateZ; + +/** + * Rotate a 3D vector around the z-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ +function rotateZ(out, a, b, c){ + var bx = b[0] + var by = b[1] + + //Translate point to the origin + var px = a[0] - bx + var py = a[1] - by + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = bx + px * cc - py * sc + out[1] = by + px * sc + py * cc + out[2] = a[2] + + return out +} + +},{}],344:[function(_dereq_,module,exports){ +module.exports = round + +/** + * Math.round the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to round + * @returns {vec3} out + */ +function round(out, a) { + out[0] = Math.round(a[0]) + out[1] = Math.round(a[1]) + out[2] = Math.round(a[2]) + return out +} + +},{}],345:[function(_dereq_,module,exports){ +module.exports = scale; + +/** + * Scales a vec3 by a scalar number + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec3} out + */ +function scale(out, a, b) { + out[0] = a[0] * b + out[1] = a[1] * b + out[2] = a[2] * b + return out +} +},{}],346:[function(_dereq_,module,exports){ +module.exports = scaleAndAdd; + +/** + * Adds two vec3's after scaling the second operand by a scalar value + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec3} out + */ +function scaleAndAdd(out, a, b, scale) { + out[0] = a[0] + (b[0] * scale) + out[1] = a[1] + (b[1] * scale) + out[2] = a[2] + (b[2] * scale) + return out +} +},{}],347:[function(_dereq_,module,exports){ +module.exports = set; + +/** + * Set the components of a vec3 to the given values + * + * @param {vec3} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} out + */ +function set(out, x, y, z) { + out[0] = x + out[1] = y + out[2] = z + return out +} +},{}],348:[function(_dereq_,module,exports){ +module.exports = _dereq_('./squaredDistance') + +},{"./squaredDistance":350}],349:[function(_dereq_,module,exports){ +module.exports = _dereq_('./squaredLength') + +},{"./squaredLength":351}],350:[function(_dereq_,module,exports){ +module.exports = squaredDistance; + +/** + * Calculates the squared euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} squared distance between a and b + */ +function squaredDistance(a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2] + return x*x + y*y + z*z +} +},{}],351:[function(_dereq_,module,exports){ +module.exports = squaredLength; + +/** + * Calculates the squared length of a vec3 + * + * @param {vec3} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +function squaredLength(a) { + var x = a[0], + y = a[1], + z = a[2] + return x*x + y*y + z*z +} +},{}],352:[function(_dereq_,module,exports){ +module.exports = _dereq_('./subtract') + +},{"./subtract":353}],353:[function(_dereq_,module,exports){ +module.exports = subtract; + +/** + * Subtracts vector b from vector a + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ +function subtract(out, a, b) { + out[0] = a[0] - b[0] + out[1] = a[1] - b[1] + out[2] = a[2] - b[2] + return out +} +},{}],354:[function(_dereq_,module,exports){ +module.exports = transformMat3; + +/** + * Transforms the vec3 with a mat3. + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m the 3x3 matrix to transform with + * @returns {vec3} out + */ +function transformMat3(out, a, m) { + var x = a[0], y = a[1], z = a[2] + out[0] = x * m[0] + y * m[3] + z * m[6] + out[1] = x * m[1] + y * m[4] + z * m[7] + out[2] = x * m[2] + y * m[5] + z * m[8] + return out +} +},{}],355:[function(_dereq_,module,exports){ +module.exports = transformMat4; + +/** + * Transforms the vec3 with a mat4. + * 4th vector component is implicitly '1' + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec3} out + */ +function transformMat4(out, a, m) { + var x = a[0], y = a[1], z = a[2], + w = m[3] * x + m[7] * y + m[11] * z + m[15] + w = w || 1.0 + out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w + out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w + out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w + return out +} +},{}],356:[function(_dereq_,module,exports){ +module.exports = transformQuat; + +/** + * Transforms the vec3 with a quat + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec3} out + */ +function transformQuat(out, a, q) { + // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations + + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx + return out +} +},{}],357:[function(_dereq_,module,exports){ +module.exports = add + +/** + * Adds two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function add (out, a, b) { + out[0] = a[0] + b[0] + out[1] = a[1] + b[1] + out[2] = a[2] + b[2] + out[3] = a[3] + b[3] + return out +} + +},{}],358:[function(_dereq_,module,exports){ +module.exports = clone + +/** + * Creates a new vec4 initialized with values from an existing vector + * + * @param {vec4} a vector to clone + * @returns {vec4} a new 4D vector + */ +function clone (a) { + var out = new Float32Array(4) + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + return out +} + +},{}],359:[function(_dereq_,module,exports){ +module.exports = copy + +/** + * Copy the values from one vec4 to another + * + * @param {vec4} out the receiving vector + * @param {vec4} a the source vector + * @returns {vec4} out + */ +function copy (out, a) { + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + return out +} + +},{}],360:[function(_dereq_,module,exports){ +module.exports = create + +/** + * Creates a new, empty vec4 + * + * @returns {vec4} a new 4D vector + */ +function create () { + var out = new Float32Array(4) + out[0] = 0 + out[1] = 0 + out[2] = 0 + out[3] = 0 + return out +} + +},{}],361:[function(_dereq_,module,exports){ +module.exports = distance + +/** + * Calculates the euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} distance between a and b + */ +function distance (a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3] + return Math.sqrt(x * x + y * y + z * z + w * w) +} + +},{}],362:[function(_dereq_,module,exports){ +module.exports = divide + +/** + * Divides two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function divide (out, a, b) { + out[0] = a[0] / b[0] + out[1] = a[1] / b[1] + out[2] = a[2] / b[2] + out[3] = a[3] / b[3] + return out +} + +},{}],363:[function(_dereq_,module,exports){ +module.exports = dot + +/** + * Calculates the dot product of two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} dot product of a and b + */ +function dot (a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] +} + +},{}],364:[function(_dereq_,module,exports){ +module.exports = fromValues + +/** + * Creates a new vec4 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} a new 4D vector + */ +function fromValues (x, y, z, w) { + var out = new Float32Array(4) + out[0] = x + out[1] = y + out[2] = z + out[3] = w + return out +} + +},{}],365:[function(_dereq_,module,exports){ +module.exports = { + create: _dereq_('./create'), + clone: _dereq_('./clone'), + fromValues: _dereq_('./fromValues'), + copy: _dereq_('./copy'), + set: _dereq_('./set'), + add: _dereq_('./add'), + subtract: _dereq_('./subtract'), + multiply: _dereq_('./multiply'), + divide: _dereq_('./divide'), + min: _dereq_('./min'), + max: _dereq_('./max'), + scale: _dereq_('./scale'), + scaleAndAdd: _dereq_('./scaleAndAdd'), + distance: _dereq_('./distance'), + squaredDistance: _dereq_('./squaredDistance'), + length: _dereq_('./length'), + squaredLength: _dereq_('./squaredLength'), + negate: _dereq_('./negate'), + inverse: _dereq_('./inverse'), + normalize: _dereq_('./normalize'), + dot: _dereq_('./dot'), + lerp: _dereq_('./lerp'), + random: _dereq_('./random'), + transformMat4: _dereq_('./transformMat4'), + transformQuat: _dereq_('./transformQuat') +} + +},{"./add":357,"./clone":358,"./copy":359,"./create":360,"./distance":361,"./divide":362,"./dot":363,"./fromValues":364,"./inverse":366,"./length":367,"./lerp":368,"./max":369,"./min":370,"./multiply":371,"./negate":372,"./normalize":373,"./random":374,"./scale":375,"./scaleAndAdd":376,"./set":377,"./squaredDistance":378,"./squaredLength":379,"./subtract":380,"./transformMat4":381,"./transformQuat":382}],366:[function(_dereq_,module,exports){ +module.exports = inverse + +/** + * Returns the inverse of the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to invert + * @returns {vec4} out + */ +function inverse (out, a) { + out[0] = 1.0 / a[0] + out[1] = 1.0 / a[1] + out[2] = 1.0 / a[2] + out[3] = 1.0 / a[3] + return out +} + +},{}],367:[function(_dereq_,module,exports){ +module.exports = length + +/** + * Calculates the length of a vec4 + * + * @param {vec4} a vector to calculate length of + * @returns {Number} length of a + */ +function length (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + return Math.sqrt(x * x + y * y + z * z + w * w) +} + +},{}],368:[function(_dereq_,module,exports){ +module.exports = lerp + +/** + * Performs a linear interpolation between two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec4} out + */ +function lerp (out, a, b, t) { + var ax = a[0], + ay = a[1], + az = a[2], + aw = a[3] + out[0] = ax + t * (b[0] - ax) + out[1] = ay + t * (b[1] - ay) + out[2] = az + t * (b[2] - az) + out[3] = aw + t * (b[3] - aw) + return out +} + +},{}],369:[function(_dereq_,module,exports){ +module.exports = max + +/** + * Returns the maximum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function max (out, a, b) { + out[0] = Math.max(a[0], b[0]) + out[1] = Math.max(a[1], b[1]) + out[2] = Math.max(a[2], b[2]) + out[3] = Math.max(a[3], b[3]) + return out +} + +},{}],370:[function(_dereq_,module,exports){ +module.exports = min + +/** + * Returns the minimum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function min (out, a, b) { + out[0] = Math.min(a[0], b[0]) + out[1] = Math.min(a[1], b[1]) + out[2] = Math.min(a[2], b[2]) + out[3] = Math.min(a[3], b[3]) + return out +} + +},{}],371:[function(_dereq_,module,exports){ +module.exports = multiply + +/** + * Multiplies two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function multiply (out, a, b) { + out[0] = a[0] * b[0] + out[1] = a[1] * b[1] + out[2] = a[2] * b[2] + out[3] = a[3] * b[3] + return out +} + +},{}],372:[function(_dereq_,module,exports){ +module.exports = negate + +/** + * Negates the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to negate + * @returns {vec4} out + */ +function negate (out, a) { + out[0] = -a[0] + out[1] = -a[1] + out[2] = -a[2] + out[3] = -a[3] + return out +} + +},{}],373:[function(_dereq_,module,exports){ +module.exports = normalize + +/** + * Normalize a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to normalize + * @returns {vec4} out + */ +function normalize (out, a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + var len = x * x + y * y + z * z + w * w + if (len > 0) { + len = 1 / Math.sqrt(len) + out[0] = x * len + out[1] = y * len + out[2] = z * len + out[3] = w * len + } + return out +} + +},{}],374:[function(_dereq_,module,exports){ +var vecNormalize = _dereq_('./normalize') +var vecScale = _dereq_('./scale') + +module.exports = random + +/** + * Generates a random vector with the given scale + * + * @param {vec4} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec4} out + */ +function random (out, scale) { + scale = scale || 1.0 + + // TODO: This is a pretty awful way of doing this. Find something better. + out[0] = Math.random() + out[1] = Math.random() + out[2] = Math.random() + out[3] = Math.random() + vecNormalize(out, out) + vecScale(out, out, scale) + return out +} + +},{"./normalize":373,"./scale":375}],375:[function(_dereq_,module,exports){ +module.exports = scale + +/** + * Scales a vec4 by a scalar number + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec4} out + */ +function scale (out, a, b) { + out[0] = a[0] * b + out[1] = a[1] * b + out[2] = a[2] * b + out[3] = a[3] * b + return out +} + +},{}],376:[function(_dereq_,module,exports){ +module.exports = scaleAndAdd + +/** + * Adds two vec4's after scaling the second operand by a scalar value + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec4} out + */ +function scaleAndAdd (out, a, b, scale) { + out[0] = a[0] + (b[0] * scale) + out[1] = a[1] + (b[1] * scale) + out[2] = a[2] + (b[2] * scale) + out[3] = a[3] + (b[3] * scale) + return out +} + +},{}],377:[function(_dereq_,module,exports){ +module.exports = set + +/** + * Set the components of a vec4 to the given values + * + * @param {vec4} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} out + */ +function set (out, x, y, z, w) { + out[0] = x + out[1] = y + out[2] = z + out[3] = w + return out +} + +},{}],378:[function(_dereq_,module,exports){ +module.exports = squaredDistance + +/** + * Calculates the squared euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} squared distance between a and b + */ +function squaredDistance (a, b) { + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3] + return x * x + y * y + z * z + w * w +} + +},{}],379:[function(_dereq_,module,exports){ +module.exports = squaredLength + +/** + * Calculates the squared length of a vec4 + * + * @param {vec4} a vector to calculate squared length of + * @returns {Number} squared length of a + */ +function squaredLength (a) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + return x * x + y * y + z * z + w * w +} + +},{}],380:[function(_dereq_,module,exports){ +module.exports = subtract + +/** + * Subtracts vector b from vector a + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ +function subtract (out, a, b) { + out[0] = a[0] - b[0] + out[1] = a[1] - b[1] + out[2] = a[2] - b[2] + out[3] = a[3] - b[3] + return out +} + +},{}],381:[function(_dereq_,module,exports){ +module.exports = transformMat4 + +/** + * Transforms the vec4 with a mat4. + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec4} out + */ +function transformMat4 (out, a, m) { + var x = a[0], y = a[1], z = a[2], w = a[3] + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w + return out +} + +},{}],382:[function(_dereq_,module,exports){ +module.exports = transformQuat + +/** + * Transforms the vec4 with a quat + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec4} out + */ +function transformQuat (out, a, q) { + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx + out[3] = a[3] + return out +} + +},{}],383:[function(_dereq_,module,exports){ +module.exports = decodeFloat + +var UINT8_VIEW = new Uint8Array(4) +var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer) + +function decodeFloat(x, y, z, w) { + UINT8_VIEW[0] = w + UINT8_VIEW[1] = z + UINT8_VIEW[2] = y + UINT8_VIEW[3] = x + return FLOAT_VIEW[0] +} + +},{}],384:[function(_dereq_,module,exports){ +var tokenize = _dereq_('glsl-tokenizer') +var atob = _dereq_('atob-lite') + +module.exports = getName + +function getName(src) { + var tokens = Array.isArray(src) + ? src + : tokenize(src) + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i] + if (token.type !== 'preprocessor') continue + var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/) + if (!match) continue + if (!match[2]) continue + + var b64 = match[1] + var name = match[2] + + return (b64 ? atob(name) : name).trim() + } +} + +},{"atob-lite":60,"glsl-tokenizer":391}],385:[function(_dereq_,module,exports){ +module.exports = tokenize + +var literals100 = _dereq_('./lib/literals') + , operators = _dereq_('./lib/operators') + , builtins100 = _dereq_('./lib/builtins') + , literals300es = _dereq_('./lib/literals-300es') + , builtins300es = _dereq_('./lib/builtins-300es') + +var NORMAL = 999 // <-- never emitted + , TOKEN = 9999 // <-- never emitted + , BLOCK_COMMENT = 0 + , LINE_COMMENT = 1 + , PREPROCESSOR = 2 + , OPERATOR = 3 + , INTEGER = 4 + , FLOAT = 5 + , IDENT = 6 + , BUILTIN = 7 + , KEYWORD = 8 + , WHITESPACE = 9 + , EOF = 10 + , HEX = 11 + +var map = [ + 'block-comment' + , 'line-comment' + , 'preprocessor' + , 'operator' + , 'integer' + , 'float' + , 'ident' + , 'builtin' + , 'keyword' + , 'whitespace' + , 'eof' + , 'integer' +] + +function tokenize(opt) { + var i = 0 + , total = 0 + , mode = NORMAL + , c + , last + , content = [] + , tokens = [] + , token_idx = 0 + , token_offs = 0 + , line = 1 + , col = 0 + , start = 0 + , isnum = false + , isoperator = false + , input = '' + , len + + opt = opt || {} + var allBuiltins = builtins100 + var allLiterals = literals100 + if (opt.version === '300 es') { + allBuiltins = builtins300es + allLiterals = literals300es + } + + return function(data) { + tokens = [] + if (data !== null) return write(data.replace ? data.replace(/\r\n/g, '\n') : data) + return end() + } + + function token(data) { + if (data.length) { + tokens.push({ + type: map[mode] + , data: data + , position: start + , line: line + , column: col + }) + } + } + + function write(chunk) { + i = 0 + input += chunk + len = input.length + + var last + + while(c = input[i], i < len) { + last = i + + switch(mode) { + case BLOCK_COMMENT: i = block_comment(); break + case LINE_COMMENT: i = line_comment(); break + case PREPROCESSOR: i = preprocessor(); break + case OPERATOR: i = operator(); break + case INTEGER: i = integer(); break + case HEX: i = hex(); break + case FLOAT: i = decimal(); break + case TOKEN: i = readtoken(); break + case WHITESPACE: i = whitespace(); break + case NORMAL: i = normal(); break + } + + if(last !== i) { + switch(input[last]) { + case '\n': col = 0; ++line; break + default: ++col; break + } + } + } + + total += i + input = input.slice(i) + return tokens + } + + function end(chunk) { + if(content.length) { + token(content.join('')) + } + + mode = EOF + token('(eof)') + return tokens + } + + function normal() { + content = content.length ? [] : content + + if(last === '/' && c === '*') { + start = total + i - 1 + mode = BLOCK_COMMENT + last = c + return i + 1 + } + + if(last === '/' && c === '/') { + start = total + i - 1 + mode = LINE_COMMENT + last = c + return i + 1 + } + + if(c === '#') { + mode = PREPROCESSOR + start = total + i + return i + } + + if(/\s/.test(c)) { + mode = WHITESPACE + start = total + i + return i + } + + isnum = /\d/.test(c) + isoperator = /[^\w_]/.test(c) + + start = total + i + mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN + return i + } + + function whitespace() { + if(/[^\s]/g.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } + + function preprocessor() { + if((c === '\r' || c === '\n') && last !== '\\') { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } + + function line_comment() { + return preprocessor() + } + + function block_comment() { + if(c === '/' && last === '*') { + content.push(c) + token(content.join('')) + mode = NORMAL + return i + 1 + } + + content.push(c) + last = c + return i + 1 + } + + function operator() { + if(last === '.' && /\d/.test(c)) { + mode = FLOAT + return i + } + + if(last === '/' && c === '*') { + mode = BLOCK_COMMENT + return i + } + + if(last === '/' && c === '/') { + mode = LINE_COMMENT + return i + } + + if(c === '.' && content.length) { + while(determine_operator(content)); + + mode = FLOAT + return i + } + + if(c === ';' || c === ')' || c === '(') { + if(content.length) while(determine_operator(content)); + token(c) + mode = NORMAL + return i + 1 + } + + var is_composite_operator = content.length === 2 && c !== '=' + if(/[\w_\d\s]/.test(c) || is_composite_operator) { + while(determine_operator(content)); + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function determine_operator(buf) { + var j = 0 + , idx + , res + + do { + idx = operators.indexOf(buf.slice(0, buf.length + j).join('')) + res = operators[idx] + + if(idx === -1) { + if(j-- + buf.length > 0) continue + res = buf.slice(0, 1).join('') + } + + token(res) + + start += res.length + content = content.slice(res.length) + return content.length + } while(1) + } + + function hex() { + if(/[^a-fA-F0-9]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function integer() { + if(c === '.') { + content.push(c) + mode = FLOAT + last = c + return i + 1 + } + + if(/[eE]/.test(c)) { + content.push(c) + mode = FLOAT + last = c + return i + 1 + } + + if(c === 'x' && content.length === 1 && content[0] === '0') { + mode = HEX + content.push(c) + last = c + return i + 1 + } + + if(/[^\d]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function decimal() { + if(c === 'f') { + content.push(c) + last = c + i += 1 + } + + if(/[eE]/.test(c)) { + content.push(c) + last = c + return i + 1 + } + + if (c === '-' && /[eE]/.test(last)) { + content.push(c) + last = c + return i + 1 + } + + if(/[^\d]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function readtoken() { + if(/[^\d\w_]/.test(c)) { + var contentstr = content.join('') + if(allLiterals.indexOf(contentstr) > -1) { + mode = KEYWORD + } else if(allBuiltins.indexOf(contentstr) > -1) { + mode = BUILTIN + } else { + mode = IDENT + } + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } +} + +},{"./lib/builtins":387,"./lib/builtins-300es":386,"./lib/literals":389,"./lib/literals-300es":388,"./lib/operators":390}],386:[function(_dereq_,module,exports){ +// 300es builtins/reserved words that were previously valid in v100 +var v100 = _dereq_('./builtins') + +// The texture2D|Cube functions have been removed +// And the gl_ features are updated +v100 = v100.slice().filter(function (b) { + return !/^(gl\_|texture)/.test(b) +}) + +module.exports = v100.concat([ + // the updated gl_ constants + 'gl_VertexID' + , 'gl_InstanceID' + , 'gl_Position' + , 'gl_PointSize' + , 'gl_FragCoord' + , 'gl_FrontFacing' + , 'gl_FragDepth' + , 'gl_PointCoord' + , 'gl_MaxVertexAttribs' + , 'gl_MaxVertexUniformVectors' + , 'gl_MaxVertexOutputVectors' + , 'gl_MaxFragmentInputVectors' + , 'gl_MaxVertexTextureImageUnits' + , 'gl_MaxCombinedTextureImageUnits' + , 'gl_MaxTextureImageUnits' + , 'gl_MaxFragmentUniformVectors' + , 'gl_MaxDrawBuffers' + , 'gl_MinProgramTexelOffset' + , 'gl_MaxProgramTexelOffset' + , 'gl_DepthRangeParameters' + , 'gl_DepthRange' + + // other builtins + , 'trunc' + , 'round' + , 'roundEven' + , 'isnan' + , 'isinf' + , 'floatBitsToInt' + , 'floatBitsToUint' + , 'intBitsToFloat' + , 'uintBitsToFloat' + , 'packSnorm2x16' + , 'unpackSnorm2x16' + , 'packUnorm2x16' + , 'unpackUnorm2x16' + , 'packHalf2x16' + , 'unpackHalf2x16' + , 'outerProduct' + , 'transpose' + , 'determinant' + , 'inverse' + , 'texture' + , 'textureSize' + , 'textureProj' + , 'textureLod' + , 'textureOffset' + , 'texelFetch' + , 'texelFetchOffset' + , 'textureProjOffset' + , 'textureLodOffset' + , 'textureProjLod' + , 'textureProjLodOffset' + , 'textureGrad' + , 'textureGradOffset' + , 'textureProjGrad' + , 'textureProjGradOffset' +]) + +},{"./builtins":387}],387:[function(_dereq_,module,exports){ +module.exports = [ + // Keep this list sorted + 'abs' + , 'acos' + , 'all' + , 'any' + , 'asin' + , 'atan' + , 'ceil' + , 'clamp' + , 'cos' + , 'cross' + , 'dFdx' + , 'dFdy' + , 'degrees' + , 'distance' + , 'dot' + , 'equal' + , 'exp' + , 'exp2' + , 'faceforward' + , 'floor' + , 'fract' + , 'gl_BackColor' + , 'gl_BackLightModelProduct' + , 'gl_BackLightProduct' + , 'gl_BackMaterial' + , 'gl_BackSecondaryColor' + , 'gl_ClipPlane' + , 'gl_ClipVertex' + , 'gl_Color' + , 'gl_DepthRange' + , 'gl_DepthRangeParameters' + , 'gl_EyePlaneQ' + , 'gl_EyePlaneR' + , 'gl_EyePlaneS' + , 'gl_EyePlaneT' + , 'gl_Fog' + , 'gl_FogCoord' + , 'gl_FogFragCoord' + , 'gl_FogParameters' + , 'gl_FragColor' + , 'gl_FragCoord' + , 'gl_FragData' + , 'gl_FragDepth' + , 'gl_FragDepthEXT' + , 'gl_FrontColor' + , 'gl_FrontFacing' + , 'gl_FrontLightModelProduct' + , 'gl_FrontLightProduct' + , 'gl_FrontMaterial' + , 'gl_FrontSecondaryColor' + , 'gl_LightModel' + , 'gl_LightModelParameters' + , 'gl_LightModelProducts' + , 'gl_LightProducts' + , 'gl_LightSource' + , 'gl_LightSourceParameters' + , 'gl_MaterialParameters' + , 'gl_MaxClipPlanes' + , 'gl_MaxCombinedTextureImageUnits' + , 'gl_MaxDrawBuffers' + , 'gl_MaxFragmentUniformComponents' + , 'gl_MaxLights' + , 'gl_MaxTextureCoords' + , 'gl_MaxTextureImageUnits' + , 'gl_MaxTextureUnits' + , 'gl_MaxVaryingFloats' + , 'gl_MaxVertexAttribs' + , 'gl_MaxVertexTextureImageUnits' + , 'gl_MaxVertexUniformComponents' + , 'gl_ModelViewMatrix' + , 'gl_ModelViewMatrixInverse' + , 'gl_ModelViewMatrixInverseTranspose' + , 'gl_ModelViewMatrixTranspose' + , 'gl_ModelViewProjectionMatrix' + , 'gl_ModelViewProjectionMatrixInverse' + , 'gl_ModelViewProjectionMatrixInverseTranspose' + , 'gl_ModelViewProjectionMatrixTranspose' + , 'gl_MultiTexCoord0' + , 'gl_MultiTexCoord1' + , 'gl_MultiTexCoord2' + , 'gl_MultiTexCoord3' + , 'gl_MultiTexCoord4' + , 'gl_MultiTexCoord5' + , 'gl_MultiTexCoord6' + , 'gl_MultiTexCoord7' + , 'gl_Normal' + , 'gl_NormalMatrix' + , 'gl_NormalScale' + , 'gl_ObjectPlaneQ' + , 'gl_ObjectPlaneR' + , 'gl_ObjectPlaneS' + , 'gl_ObjectPlaneT' + , 'gl_Point' + , 'gl_PointCoord' + , 'gl_PointParameters' + , 'gl_PointSize' + , 'gl_Position' + , 'gl_ProjectionMatrix' + , 'gl_ProjectionMatrixInverse' + , 'gl_ProjectionMatrixInverseTranspose' + , 'gl_ProjectionMatrixTranspose' + , 'gl_SecondaryColor' + , 'gl_TexCoord' + , 'gl_TextureEnvColor' + , 'gl_TextureMatrix' + , 'gl_TextureMatrixInverse' + , 'gl_TextureMatrixInverseTranspose' + , 'gl_TextureMatrixTranspose' + , 'gl_Vertex' + , 'greaterThan' + , 'greaterThanEqual' + , 'inversesqrt' + , 'length' + , 'lessThan' + , 'lessThanEqual' + , 'log' + , 'log2' + , 'matrixCompMult' + , 'max' + , 'min' + , 'mix' + , 'mod' + , 'normalize' + , 'not' + , 'notEqual' + , 'pow' + , 'radians' + , 'reflect' + , 'refract' + , 'sign' + , 'sin' + , 'smoothstep' + , 'sqrt' + , 'step' + , 'tan' + , 'texture2D' + , 'texture2DLod' + , 'texture2DProj' + , 'texture2DProjLod' + , 'textureCube' + , 'textureCubeLod' + , 'texture2DLodEXT' + , 'texture2DProjLodEXT' + , 'textureCubeLodEXT' + , 'texture2DGradEXT' + , 'texture2DProjGradEXT' + , 'textureCubeGradEXT' +] + +},{}],388:[function(_dereq_,module,exports){ +var v100 = _dereq_('./literals') + +module.exports = v100.slice().concat([ + 'layout' + , 'centroid' + , 'smooth' + , 'case' + , 'mat2x2' + , 'mat2x3' + , 'mat2x4' + , 'mat3x2' + , 'mat3x3' + , 'mat3x4' + , 'mat4x2' + , 'mat4x3' + , 'mat4x4' + , 'uint' + , 'uvec2' + , 'uvec3' + , 'uvec4' + , 'samplerCubeShadow' + , 'sampler2DArray' + , 'sampler2DArrayShadow' + , 'isampler2D' + , 'isampler3D' + , 'isamplerCube' + , 'isampler2DArray' + , 'usampler2D' + , 'usampler3D' + , 'usamplerCube' + , 'usampler2DArray' + , 'coherent' + , 'restrict' + , 'readonly' + , 'writeonly' + , 'resource' + , 'atomic_uint' + , 'noperspective' + , 'patch' + , 'sample' + , 'subroutine' + , 'common' + , 'partition' + , 'active' + , 'filter' + , 'image1D' + , 'image2D' + , 'image3D' + , 'imageCube' + , 'iimage1D' + , 'iimage2D' + , 'iimage3D' + , 'iimageCube' + , 'uimage1D' + , 'uimage2D' + , 'uimage3D' + , 'uimageCube' + , 'image1DArray' + , 'image2DArray' + , 'iimage1DArray' + , 'iimage2DArray' + , 'uimage1DArray' + , 'uimage2DArray' + , 'image1DShadow' + , 'image2DShadow' + , 'image1DArrayShadow' + , 'image2DArrayShadow' + , 'imageBuffer' + , 'iimageBuffer' + , 'uimageBuffer' + , 'sampler1DArray' + , 'sampler1DArrayShadow' + , 'isampler1D' + , 'isampler1DArray' + , 'usampler1D' + , 'usampler1DArray' + , 'isampler2DRect' + , 'usampler2DRect' + , 'samplerBuffer' + , 'isamplerBuffer' + , 'usamplerBuffer' + , 'sampler2DMS' + , 'isampler2DMS' + , 'usampler2DMS' + , 'sampler2DMSArray' + , 'isampler2DMSArray' + , 'usampler2DMSArray' +]) + +},{"./literals":389}],389:[function(_dereq_,module,exports){ +module.exports = [ + // current + 'precision' + , 'highp' + , 'mediump' + , 'lowp' + , 'attribute' + , 'const' + , 'uniform' + , 'varying' + , 'break' + , 'continue' + , 'do' + , 'for' + , 'while' + , 'if' + , 'else' + , 'in' + , 'out' + , 'inout' + , 'float' + , 'int' + , 'void' + , 'bool' + , 'true' + , 'false' + , 'discard' + , 'return' + , 'mat2' + , 'mat3' + , 'mat4' + , 'vec2' + , 'vec3' + , 'vec4' + , 'ivec2' + , 'ivec3' + , 'ivec4' + , 'bvec2' + , 'bvec3' + , 'bvec4' + , 'sampler1D' + , 'sampler2D' + , 'sampler3D' + , 'samplerCube' + , 'sampler1DShadow' + , 'sampler2DShadow' + , 'struct' + + // future + , 'asm' + , 'class' + , 'union' + , 'enum' + , 'typedef' + , 'template' + , 'this' + , 'packed' + , 'goto' + , 'switch' + , 'default' + , 'inline' + , 'noinline' + , 'volatile' + , 'public' + , 'static' + , 'extern' + , 'external' + , 'interface' + , 'long' + , 'short' + , 'double' + , 'half' + , 'fixed' + , 'unsigned' + , 'input' + , 'output' + , 'hvec2' + , 'hvec3' + , 'hvec4' + , 'dvec2' + , 'dvec3' + , 'dvec4' + , 'fvec2' + , 'fvec3' + , 'fvec4' + , 'sampler2DRect' + , 'sampler3DRect' + , 'sampler2DRectShadow' + , 'sizeof' + , 'cast' + , 'namespace' + , 'using' +] + +},{}],390:[function(_dereq_,module,exports){ +module.exports = [ + '<<=' + , '>>=' + , '++' + , '--' + , '<<' + , '>>' + , '<=' + , '>=' + , '==' + , '!=' + , '&&' + , '||' + , '+=' + , '-=' + , '*=' + , '/=' + , '%=' + , '&=' + , '^^' + , '^=' + , '|=' + , '(' + , ')' + , '[' + , ']' + , '.' + , '!' + , '~' + , '*' + , '/' + , '%' + , '+' + , '-' + , '<' + , '>' + , '&' + , '^' + , '|' + , '?' + , ':' + , '=' + , ',' + , ';' + , '{' + , '}' +] + +},{}],391:[function(_dereq_,module,exports){ +var tokenize = _dereq_('./index') + +module.exports = tokenizeString + +function tokenizeString(str, opt) { + var generator = tokenize(opt) + var tokens = [] + + tokens = tokens.concat(generator(str)) + tokens = tokens.concat(generator(null)) + + return tokens +} + +},{"./index":385}],392:[function(_dereq_,module,exports){ +module.exports = function(strings) { + if (typeof strings === 'string') strings = [strings] + var exprs = [].slice.call(arguments,1) + var parts = [] + for (var i = 0; i < strings.length-1; i++) { + parts.push(strings[i], exprs[i] || '') + } + parts.push(strings[i]) + return parts.join('') +} + +},{}],393:[function(_dereq_,module,exports){ +(function (global){ +'use strict' + +var isBrowser = _dereq_('is-browser') +var hasHover + +if (typeof global.matchMedia === 'function') { + hasHover = !global.matchMedia('(hover: none)').matches +} +else { + hasHover = isBrowser +} + +module.exports = hasHover + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"is-browser":400}],394:[function(_dereq_,module,exports){ +'use strict' + +var isBrowser = _dereq_('is-browser') + +function detect() { + var supported = false + + try { + var opts = Object.defineProperty({}, 'passive', { + get: function() { + supported = true + } + }) + + window.addEventListener('test', null, opts) + window.removeEventListener('test', null, opts) + } catch(e) { + supported = false + } + + return supported +} + +module.exports = isBrowser && detect() + +},{"is-browser":400}],395:[function(_dereq_,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],396:[function(_dereq_,module,exports){ +"use strict" + +//High level idea: +// 1. Use Clarkson's incremental construction to find convex hull +// 2. Point location in triangulation by jump and walk + +module.exports = incrementalConvexHull + +var orient = _dereq_("robust-orientation") +var compareCell = _dereq_("simplicial-complex").compareCells + +function compareInt(a, b) { + return a - b +} + +function Simplex(vertices, adjacent, boundary) { + this.vertices = vertices + this.adjacent = adjacent + this.boundary = boundary + this.lastVisited = -1 +} + +Simplex.prototype.flip = function() { + var t = this.vertices[0] + this.vertices[0] = this.vertices[1] + this.vertices[1] = t + var u = this.adjacent[0] + this.adjacent[0] = this.adjacent[1] + this.adjacent[1] = u +} + +function GlueFacet(vertices, cell, index) { + this.vertices = vertices + this.cell = cell + this.index = index +} + +function compareGlue(a, b) { + return compareCell(a.vertices, b.vertices) +} + +function bakeOrient(d) { + var code = ["function orient(){var tuple=this.tuple;return test("] + for(var i=0; i<=d; ++i) { + if(i > 0) { + code.push(",") + } + code.push("tuple[", i, "]") + } + code.push(")}return orient") + var proc = new Function("test", code.join("")) + var test = orient[d+1] + if(!test) { + test = orient + } + return proc(test) +} + +var BAKED = [] + +function Triangulation(dimension, vertices, simplices) { + this.dimension = dimension + this.vertices = vertices + this.simplices = simplices + this.interior = simplices.filter(function(c) { + return !c.boundary + }) + + this.tuple = new Array(dimension+1) + for(var i=0; i<=dimension; ++i) { + this.tuple[i] = this.vertices[i] + } + + var o = BAKED[dimension] + if(!o) { + o = BAKED[dimension] = bakeOrient(dimension) + } + this.orient = o +} + +var proto = Triangulation.prototype + +//Degenerate situation where we are on boundary, but coplanar to face +proto.handleBoundaryDegeneracy = function(cell, point) { + var d = this.dimension + var n = this.vertices.length - 1 + var tuple = this.tuple + var verts = this.vertices + + //Dumb solution: Just do dfs from boundary cell until we find any peak, or terminate + var toVisit = [ cell ] + cell.lastVisited = -n + while(toVisit.length > 0) { + cell = toVisit.pop() + var cellVerts = cell.vertices + var cellAdj = cell.adjacent + for(var i=0; i<=d; ++i) { + var neighbor = cellAdj[i] + if(!neighbor.boundary || neighbor.lastVisited <= -n) { + continue + } + var nv = neighbor.vertices + for(var j=0; j<=d; ++j) { + var vv = nv[j] + if(vv < 0) { + tuple[j] = point + } else { + tuple[j] = verts[vv] + } + } + var o = this.orient() + if(o > 0) { + return neighbor + } + neighbor.lastVisited = -n + if(o === 0) { + toVisit.push(neighbor) + } + } + } + return null +} + +proto.walk = function(point, random) { + //Alias local properties + var n = this.vertices.length - 1 + var d = this.dimension + var verts = this.vertices + var tuple = this.tuple + + //Compute initial jump cell + var initIndex = random ? (this.interior.length * Math.random())|0 : (this.interior.length-1) + var cell = this.interior[ initIndex ] + + //Start walking +outerLoop: + while(!cell.boundary) { + var cellVerts = cell.vertices + var cellAdj = cell.adjacent + + for(var i=0; i<=d; ++i) { + tuple[i] = verts[cellVerts[i]] + } + cell.lastVisited = n + + //Find farthest adjacent cell + for(var i=0; i<=d; ++i) { + var neighbor = cellAdj[i] + if(neighbor.lastVisited >= n) { + continue + } + var prev = tuple[i] + tuple[i] = point + var o = this.orient() + tuple[i] = prev + if(o < 0) { + cell = neighbor + continue outerLoop + } else { + if(!neighbor.boundary) { + neighbor.lastVisited = n + } else { + neighbor.lastVisited = -n + } + } + } + return + } + + return cell +} + +proto.addPeaks = function(point, cell) { + var n = this.vertices.length - 1 + var d = this.dimension + var verts = this.vertices + var tuple = this.tuple + var interior = this.interior + var simplices = this.simplices + + //Walking finished at boundary, time to add peaks + var tovisit = [ cell ] + + //Stretch initial boundary cell into a peak + cell.lastVisited = n + cell.vertices[cell.vertices.indexOf(-1)] = n + cell.boundary = false + interior.push(cell) + + //Record a list of all new boundaries created by added peaks so we can glue them together when we are all done + var glueFacets = [] + + //Do a traversal of the boundary walking outward from starting peak + while(tovisit.length > 0) { + //Pop off peak and walk over adjacent cells + var cell = tovisit.pop() + var cellVerts = cell.vertices + var cellAdj = cell.adjacent + var indexOfN = cellVerts.indexOf(n) + if(indexOfN < 0) { + continue + } + + for(var i=0; i<=d; ++i) { + if(i === indexOfN) { + continue + } + + //For each boundary neighbor of the cell + var neighbor = cellAdj[i] + if(!neighbor.boundary || neighbor.lastVisited >= n) { + continue + } + + var nv = neighbor.vertices + + //Test if neighbor is a peak + if(neighbor.lastVisited !== -n) { + //Compute orientation of p relative to each boundary peak + var indexOfNeg1 = 0 + for(var j=0; j<=d; ++j) { + if(nv[j] < 0) { + indexOfNeg1 = j + tuple[j] = point + } else { + tuple[j] = verts[nv[j]] + } + } + var o = this.orient() + + //Test if neighbor cell is also a peak + if(o > 0) { + nv[indexOfNeg1] = n + neighbor.boundary = false + interior.push(neighbor) + tovisit.push(neighbor) + neighbor.lastVisited = n + continue + } else { + neighbor.lastVisited = -n + } + } + + var na = neighbor.adjacent + + //Otherwise, replace neighbor with new face + var vverts = cellVerts.slice() + var vadj = cellAdj.slice() + var ncell = new Simplex(vverts, vadj, true) + simplices.push(ncell) + + //Connect to neighbor + var opposite = na.indexOf(cell) + if(opposite < 0) { + continue + } + na[opposite] = ncell + vadj[indexOfN] = neighbor + + //Connect to cell + vverts[i] = -1 + vadj[i] = cell + cellAdj[i] = ncell + + //Flip facet + ncell.flip() + + //Add to glue list + for(var j=0; j<=d; ++j) { + var uu = vverts[j] + if(uu < 0 || uu === n) { + continue + } + var nface = new Array(d-1) + var nptr = 0 + for(var k=0; k<=d; ++k) { + var vv = vverts[k] + if(vv < 0 || k === j) { + continue + } + nface[nptr++] = vv + } + glueFacets.push(new GlueFacet(nface, ncell, j)) + } + } + } + + //Glue boundary facets together + glueFacets.sort(compareGlue) + + for(var i=0; i+1= 0) { + bcell[ptr++] = cv[j] + } else { + parity = j&1 + } + } + if(parity === (d&1)) { + var t = bcell[0] + bcell[0] = bcell[1] + bcell[1] = t + } + boundary.push(bcell) + } + } + return boundary +} + +function incrementalConvexHull(points, randomSearch) { + var n = points.length + if(n === 0) { + throw new Error("Must have at least d+1 points") + } + var d = points[0].length + if(n <= d) { + throw new Error("Must input at least d+1 points") + } + + //FIXME: This could be degenerate, but need to select d+1 non-coplanar points to bootstrap process + var initialSimplex = points.slice(0, d+1) + + //Make sure initial simplex is positively oriented + var o = orient.apply(void 0, initialSimplex) + if(o === 0) { + throw new Error("Input not in general position") + } + var initialCoords = new Array(d+1) + for(var i=0; i<=d; ++i) { + initialCoords[i] = i + } + if(o < 0) { + initialCoords[0] = 1 + initialCoords[1] = 0 + } + + //Create initial topological index, glue pointers together (kind of messy) + var initialCell = new Simplex(initialCoords, new Array(d+1), false) + var boundary = initialCell.adjacent + var list = new Array(d+2) + for(var i=0; i<=d; ++i) { + var verts = initialCoords.slice() + for(var j=0; j<=d; ++j) { + if(j === i) { + verts[j] = -1 + } + } + var t = verts[0] + verts[0] = verts[1] + verts[1] = t + var cell = new Simplex(verts, new Array(d+1), true) + boundary[i] = cell + list[i] = cell + } + list[d+1] = initialCell + for(var i=0; i<=d; ++i) { + var verts = boundary[i].vertices + var adj = boundary[i].adjacent + for(var j=0; j<=d; ++j) { + var v = verts[j] + if(v < 0) { + adj[j] = initialCell + continue + } + for(var k=0; k<=d; ++k) { + if(boundary[k].vertices.indexOf(v) < 0) { + adj[j] = boundary[k] + } + } + } + } + + //Initialize triangles + var triangles = new Triangulation(d, initialSimplex, list) + + //Insert remaining points + var useRandom = !!randomSearch + for(var i=d+1; i 3*(weight+1)) { + rebuildWithInterval(this, interval) + } else { + this.left.insert(interval) + } + } else { + this.left = createIntervalTree([interval]) + } + } else if(interval[0] > this.mid) { + if(this.right) { + if(4*(this.right.count+1) > 3*(weight+1)) { + rebuildWithInterval(this, interval) + } else { + this.right.insert(interval) + } + } else { + this.right = createIntervalTree([interval]) + } + } else { + var l = bounds.ge(this.leftPoints, interval, compareBegin) + var r = bounds.ge(this.rightPoints, interval, compareEnd) + this.leftPoints.splice(l, 0, interval) + this.rightPoints.splice(r, 0, interval) + } +} + +proto.remove = function(interval) { + var weight = this.count - this.leftPoints + if(interval[1] < this.mid) { + if(!this.left) { + return NOT_FOUND + } + var rw = this.right ? this.right.count : 0 + if(4 * rw > 3 * (weight-1)) { + return rebuildWithoutInterval(this, interval) + } + var r = this.left.remove(interval) + if(r === EMPTY) { + this.left = null + this.count -= 1 + return SUCCESS + } else if(r === SUCCESS) { + this.count -= 1 + } + return r + } else if(interval[0] > this.mid) { + if(!this.right) { + return NOT_FOUND + } + var lw = this.left ? this.left.count : 0 + if(4 * lw > 3 * (weight-1)) { + return rebuildWithoutInterval(this, interval) + } + var r = this.right.remove(interval) + if(r === EMPTY) { + this.right = null + this.count -= 1 + return SUCCESS + } else if(r === SUCCESS) { + this.count -= 1 + } + return r + } else { + if(this.count === 1) { + if(this.leftPoints[0] === interval) { + return EMPTY + } else { + return NOT_FOUND + } + } + if(this.leftPoints.length === 1 && this.leftPoints[0] === interval) { + if(this.left && this.right) { + var p = this + var n = this.left + while(n.right) { + p = n + n = n.right + } + if(p === this) { + n.right = this.right + } else { + var l = this.left + var r = this.right + p.count -= n.count + p.right = n.left + n.left = l + n.right = r + } + copy(this, n) + this.count = (this.left?this.left.count:0) + (this.right?this.right.count:0) + this.leftPoints.length + } else if(this.left) { + copy(this, this.left) + } else { + copy(this, this.right) + } + return SUCCESS + } + for(var l = bounds.ge(this.leftPoints, interval, compareBegin); l=0 && arr[i][1] >= lo; --i) { + var r = cb(arr[i]) + if(r) { return r } + } +} + +function reportRange(arr, cb) { + for(var i=0; i this.mid) { + if(this.right) { + var r = this.right.queryPoint(x, cb) + if(r) { return r } + } + return reportRightRange(this.rightPoints, x, cb) + } else { + return reportRange(this.leftPoints, cb) + } +} + +proto.queryInterval = function(lo, hi, cb) { + if(lo < this.mid && this.left) { + var r = this.left.queryInterval(lo, hi, cb) + if(r) { return r } + } + if(hi > this.mid && this.right) { + var r = this.right.queryInterval(lo, hi, cb) + if(r) { return r } + } + if(hi < this.mid) { + return reportLeftRange(this.leftPoints, hi, cb) + } else if(lo > this.mid) { + return reportRightRange(this.rightPoints, lo, cb) + } else { + return reportRange(this.leftPoints, cb) + } +} + +function compareNumbers(a, b) { + return a - b +} + +function compareBegin(a, b) { + var d = a[0] - b[0] + if(d) { return d } + return a[1] - b[1] +} + +function compareEnd(a, b) { + var d = a[1] - b[1] + if(d) { return d } + return a[0] - b[0] +} + +function createIntervalTree(intervals) { + if(intervals.length === 0) { + return null + } + var pts = [] + for(var i=0; i>1] + + var leftIntervals = [] + var rightIntervals = [] + var centerIntervals = [] + for(var i=0; i + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],402:[function(_dereq_,module,exports){ +'use strict'; +module.exports = typeof navigator !== 'undefined' && + (/MSIE/.test(navigator.userAgent) || /Trident\//.test(navigator.appVersion)); + +},{}],403:[function(_dereq_,module,exports){ +'use strict' + +module.exports = isMobile; +module.exports.isMobile = isMobile; + +var mobileRE = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i; + +var tabletRE = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|android|ipad|playbook|silk/i; + +function isMobile (opts) { + if (!opts) opts = {} + var ua = opts.ua + if (!ua && typeof navigator !== 'undefined') ua = navigator.userAgent; + if (ua && ua.headers && typeof ua.headers['user-agent'] === 'string') { + ua = ua.headers['user-agent']; + } + if (typeof ua !== 'string') return false; + + return opts.tablet + ? tabletRE.test(ua) + : mobileRE.test(ua); +} + +},{}],404:[function(_dereq_,module,exports){ +'use strict'; +module.exports = function (x) { + var type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +}; + +},{}],405:[function(_dereq_,module,exports){ +'use strict'; +var toString = Object.prototype.toString; + +module.exports = function (x) { + var prototype; + return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({})); +}; + +},{}],406:[function(_dereq_,module,exports){ +'use strict'; + +/** + * Is this string all whitespace? + * This solution kind of makes my brain hurt, but it's significantly faster + * than !str.trim() or any other solution I could find. + * + * whitespace codes from: http://en.wikipedia.org/wiki/Whitespace_character + * and verified with: + * + * for(var i = 0; i < 65536; i++) { + * var s = String.fromCharCode(i); + * if(+s===0 && !s.trim()) console.log(i, s); + * } + * + * which counts a couple of these as *not* whitespace, but finds nothing else + * that *is* whitespace. Note that charCodeAt stops at 16 bits, but it appears + * that there are no whitespace characters above this, and code points above + * this do not map onto white space characters. + */ + +module.exports = function(str){ + var l = str.length, + a; + for(var i = 0; i < l; i++) { + a = str.charCodeAt(i); + if((a < 9 || a > 13) && (a !== 32) && (a !== 133) && (a !== 160) && + (a !== 5760) && (a !== 6158) && (a < 8192 || a > 8205) && + (a !== 8232) && (a !== 8233) && (a !== 8239) && (a !== 8287) && + (a !== 8288) && (a !== 12288) && (a !== 65279)) { + return false; + } + } + return true; +} + +},{}],407:[function(_dereq_,module,exports){ +'use strict' + +module.exports = function isPath(str) { + if (typeof str !== 'string') return false + + str = str.trim() + + // https://www.w3.org/TR/SVG/paths.html#PathDataBNF + if (/^[mzlhvcsqta]\s*[-+.0-9][^mlhvzcsqta]+/i.test(str) && /[\dz]$/i.test(str) && str.length > 4) return true + + return false +} + +},{}],408:[function(_dereq_,module,exports){ +function lerp(v0, v1, t) { + return v0*(1-t)+v1*t +} +module.exports = lerp +},{}],409:[function(_dereq_,module,exports){ +(function (global){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.mapboxgl = factory()); +}(this, (function () { 'use strict'; + +/* eslint-disable */ + +var shared, worker, mapboxgl; +// define gets called three times: one for each chunk. we rely on the order +// they're imported to know which is which +function define(_, chunk) { +if (!shared) { + shared = chunk; +} else if (!worker) { + worker = chunk; +} else { + var workerBundleString = 'var sharedChunk = {}; (' + shared + ')(sharedChunk); (' + worker + ')(sharedChunk);' + + var sharedChunk = {}; + shared(sharedChunk); + mapboxgl = chunk(sharedChunk); + mapboxgl.workerUrl = window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' })); +} +} + + +define(["exports"],function(t){"use strict";var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function n(t,e){return t(e={exports:{}},e.exports),e.exports}var i=o;function o(t,e,r,n){this.cx=3*t,this.bx=3*(r-t)-this.cx,this.ax=1-this.cx-this.bx,this.cy=3*e,this.by=3*(n-e)-this.cy,this.ay=1-this.cy-this.by,this.p1x=t,this.p1y=n,this.p2x=r,this.p2y=n;}o.prototype.sampleCurveX=function(t){return((this.ax*t+this.bx)*t+this.cx)*t},o.prototype.sampleCurveY=function(t){return((this.ay*t+this.by)*t+this.cy)*t},o.prototype.sampleCurveDerivativeX=function(t){return(3*this.ax*t+2*this.bx)*t+this.cx},o.prototype.solveCurveX=function(t,e){var r,n,i,o,a;for(void 0===e&&(e=1e-6),i=t,a=0;a<8;a++){if(o=this.sampleCurveX(i)-t,Math.abs(o)(n=1))return n;for(;ro?r=i:n=i,i=.5*(n-r)+r;}return i},o.prototype.solve=function(t,e){return this.sampleCurveY(this.solveCurveX(t,e))};var a=function(t,e,r){this.column=t,this.row=e,this.zoom=r;};a.prototype.clone=function(){return new a(this.column,this.row,this.zoom)},a.prototype.zoomTo=function(t){return this.clone()._zoomTo(t)},a.prototype.sub=function(t){return this.clone()._sub(t)},a.prototype._zoomTo=function(t){var e=Math.pow(2,t-this.zoom);return this.column*=e,this.row*=e,this.zoom=t,this},a.prototype._sub=function(t){return t=t.zoomTo(this.zoom),this.column-=t.column,this.row-=t.row,this};var s=u;function u(t,e){this.x=t,this.y=e;}function l(t,e,r,n){var o=new i(t,e,r,n);return function(t){return o.solve(t)}}u.prototype={clone:function(){return new u(this.x,this.y)},add:function(t){return this.clone()._add(t)},sub:function(t){return this.clone()._sub(t)},multByPoint:function(t){return this.clone()._multByPoint(t)},divByPoint:function(t){return this.clone()._divByPoint(t)},mult:function(t){return this.clone()._mult(t)},div:function(t){return this.clone()._div(t)},rotate:function(t){return this.clone()._rotate(t)},rotateAround:function(t,e){return this.clone()._rotateAround(t,e)},matMult:function(t){return this.clone()._matMult(t)},unit:function(){return this.clone()._unit()},perp:function(){return this.clone()._perp()},round:function(){return this.clone()._round()},mag:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},equals:function(t){return this.x===t.x&&this.y===t.y},dist:function(t){return Math.sqrt(this.distSqr(t))},distSqr:function(t){var e=t.x-this.x,r=t.y-this.y;return e*e+r*r},angle:function(){return Math.atan2(this.y,this.x)},angleTo:function(t){return Math.atan2(this.y-t.y,this.x-t.x)},angleWith:function(t){return this.angleWithSep(t.x,t.y)},angleWithSep:function(t,e){return Math.atan2(this.x*e-this.y*t,this.x*t+this.y*e)},_matMult:function(t){var e=t[0]*this.x+t[1]*this.y,r=t[2]*this.x+t[3]*this.y;return this.x=e,this.y=r,this},_add:function(t){return this.x+=t.x,this.y+=t.y,this},_sub:function(t){return this.x-=t.x,this.y-=t.y,this},_mult:function(t){return this.x*=t,this.y*=t,this},_div:function(t){return this.x/=t,this.y/=t,this},_multByPoint:function(t){return this.x*=t.x,this.y*=t.y,this},_divByPoint:function(t){return this.x/=t.x,this.y/=t.y,this},_unit:function(){return this._div(this.mag()),this},_perp:function(){var t=this.y;return this.y=this.x,this.x=-t,this},_rotate:function(t){var e=Math.cos(t),r=Math.sin(t),n=e*this.x-r*this.y,i=r*this.x+e*this.y;return this.x=n,this.y=i,this},_rotateAround:function(t,e){var r=Math.cos(t),n=Math.sin(t),i=e.x+r*(this.x-e.x)-n*(this.y-e.y),o=e.y+n*(this.x-e.x)+r*(this.y-e.y);return this.x=i,this.y=o,this},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}},u.convert=function(t){return t instanceof u?t:Array.isArray(t)?new u(t[0],t[1]):t};var p=l(.25,.1,.25,1);function c(t,e,r){return Math.min(r,Math.max(e,t))}function h(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];for(var n=0,i=e;n(e.y-t.y)*(r.x-t.x)}function _(t){for(var e=0,r=0,n=t.length,i=n-1,o=void 0,a=void 0;r=200&&r.status<300&&r.response?e(null,{data:n,cacheControl:r.getResponseHeader("Cache-Control"),expires:r.getResponseHeader("Expires")}):e(new k(r.statusText,r.status,t.url));},r.send(),r};function M(t,e,r){r[t]=r[t]||[],r[t].push(e);}function V(t,e,r){if(r&&r[t]){var n=r[t].indexOf(e);-1!==n&&r[t].splice(n,1);}}var B=function(t,e){void 0===e&&(e={}),h(this,e),this.type=t;},C=function(t){function e(e,r){void 0===r&&(r={}),t.call(this,"error",h({error:e},r));}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(B),I=function(){};I.prototype.on=function(t,e){return this._listeners=this._listeners||{},M(t,e,this._listeners),this},I.prototype.off=function(t,e){return V(t,e,this._listeners),V(t,e,this._oneTimeListeners),this},I.prototype.once=function(t,e){return this._oneTimeListeners=this._oneTimeListeners||{},M(t,e,this._oneTimeListeners),this},I.prototype.fire=function(t){"string"==typeof t&&(t=new B(t,arguments[1]||{}));var e=t.type;if(this.listens(e)){t.target=this;for(var r=0,n=this._listeners&&this._listeners[e]?this._listeners[e].slice():[];r0||this._oneTimeListeners&&this._oneTimeListeners[t]&&this._oneTimeListeners[t].length>0||this._eventedParent&&this._eventedParent.listens(t)},I.prototype.setEventedParent=function(t,e){return this._eventedParent=t,this._eventedParentData=e,this};var E={$version:8,$root:{version:{required:!0,type:"enum",values:[8]},name:{type:"string"},metadata:{type:"*"},center:{type:"array",value:"number"},zoom:{type:"number"},bearing:{type:"number",default:0,period:360,units:"degrees"},pitch:{type:"number",default:0,units:"degrees"},light:{type:"light"},sources:{required:!0,type:"sources"},sprite:{type:"string"},glyphs:{type:"string"},transition:{type:"transition"},layers:{required:!0,type:"array",value:"layer"}},sources:{"*":{type:"source"}},source:["source_vector","source_raster","source_raster_dem","source_geojson","source_video","source_image"],source_vector:{type:{required:!0,type:"enum",values:{vector:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},attribution:{type:"string"},"*":{type:"*"}},source_raster:{type:{required:!0,type:"enum",values:{raster:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},scheme:{type:"enum",values:{xyz:{},tms:{}},default:"xyz"},attribution:{type:"string"},"*":{type:"*"}},source_raster_dem:{type:{required:!0,type:"enum",values:{"raster-dem":{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},attribution:{type:"string"},encoding:{type:"enum",values:{terrarium:{},mapbox:{}},default:"mapbox"},"*":{type:"*"}},source_geojson:{type:{required:!0,type:"enum",values:{geojson:{}}},data:{type:"*"},maxzoom:{type:"number",default:18},buffer:{type:"number",default:128,maximum:512,minimum:0},tolerance:{type:"number",default:.375},cluster:{type:"boolean",default:!1},clusterRadius:{type:"number",default:50,minimum:0},clusterMaxZoom:{type:"number"},lineMetrics:{type:"boolean",default:!1}},source_video:{type:{required:!0,type:"enum",values:{video:{}}},urls:{required:!0,type:"array",value:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},source_image:{type:{required:!0,type:"enum",values:{image:{}}},url:{required:!0,type:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},layer:{id:{type:"string",required:!0},type:{type:"enum",values:{fill:{},line:{},symbol:{},circle:{},heatmap:{},"fill-extrusion":{},raster:{},hillshade:{},background:{}},required:!0},metadata:{type:"*"},source:{type:"string"},"source-layer":{type:"string"},minzoom:{type:"number",minimum:0,maximum:24},maxzoom:{type:"number",minimum:0,maximum:24},filter:{type:"filter"},layout:{type:"layout"},paint:{type:"paint"}},layout:["layout_fill","layout_line","layout_circle","layout_heatmap","layout_fill-extrusion","layout_symbol","layout_raster","layout_hillshade","layout_background"],layout_background:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_fill:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_circle:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_heatmap:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_line:{"line-cap":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{butt:{},round:{},square:{}},default:"butt"},"line-join":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{bevel:{},round:{},miter:{}},default:"miter"},"line-miter-limit":{type:"number",default:2,function:"interpolated","zoom-function":!0,requires:[{"line-join":"miter"}]},"line-round-limit":{type:"number",default:1.05,function:"interpolated","zoom-function":!0,requires:[{"line-join":"round"}]},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_symbol:{"symbol-placement":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{point:{},line:{}},default:"point"},"symbol-spacing":{type:"number",default:250,minimum:1,function:"interpolated","zoom-function":!0,units:"pixels",requires:[{"symbol-placement":"line"}]},"symbol-avoid-edges":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1},"icon-allow-overlap":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image"]},"icon-ignore-placement":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image"]},"icon-optional":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image","text-field"]},"icon-rotation-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"]},"icon-size":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,units:"factor of the original icon size",requires:["icon-image"]},"icon-text-fit":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{none:{},width:{},height:{},both:{}},default:"none",requires:["icon-image","text-field"]},"icon-text-fit-padding":{type:"array",value:"number",length:4,default:[0,0,0,0],units:"pixels",function:"interpolated","zoom-function":!0,requires:["icon-image","text-field",{"icon-text-fit":["both","width","height"]}]},"icon-image":{type:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,tokens:!0},"icon-rotate":{type:"number",default:0,period:360,function:"interpolated","zoom-function":!0,"property-function":!0,units:"degrees",requires:["icon-image"]},"icon-padding":{type:"number",default:2,minimum:0,function:"interpolated","zoom-function":!0,units:"pixels",requires:["icon-image"]},"icon-keep-upright":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image",{"icon-rotation-alignment":"map"},{"symbol-placement":"line"}]},"icon-offset":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,"property-function":!0,requires:["icon-image"]},"icon-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",requires:["icon-image"]},"icon-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"]},"text-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"]},"text-rotation-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"]},"text-field":{type:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,default:"",tokens:!0},"text-font":{type:"array",value:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,default:["Open Sans Regular","Arial Unicode MS Regular"],requires:["text-field"]},"text-size":{type:"number",default:16,minimum:0,units:"pixels",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-max-width":{type:"number",default:10,minimum:0,units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-line-height":{type:"number",default:1.2,units:"ems",function:"interpolated","zoom-function":!0,requires:["text-field"]},"text-letter-spacing":{type:"number",default:0,units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-justify":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{left:{},center:{},right:{}},default:"center",requires:["text-field"]},"text-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",requires:["text-field"]},"text-max-angle":{type:"number",default:45,units:"degrees",function:"interpolated","zoom-function":!0,requires:["text-field",{"symbol-placement":"line"}]},"text-rotate":{type:"number",default:0,period:360,units:"degrees",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-padding":{type:"number",default:2,minimum:0,units:"pixels",function:"interpolated","zoom-function":!0,requires:["text-field"]},"text-keep-upright":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!0,requires:["text-field",{"text-rotation-alignment":"map"},{"symbol-placement":"line"}]},"text-transform":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{none:{},uppercase:{},lowercase:{}},default:"none",requires:["text-field"]},"text-offset":{type:"array",value:"number",units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,length:2,default:[0,0],requires:["text-field"]},"text-allow-overlap":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field"]},"text-ignore-placement":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field"]},"text-optional":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field","icon-image"]},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_raster:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_hillshade:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},filter:{type:"array",value:"*"},filter_operator:{type:"enum",values:{"==":{},"!=":{},">":{},">=":{},"<":{},"<=":{},in:{},"!in":{},all:{},any:{},none:{},has:{},"!has":{}}},geometry_type:{type:"enum",values:{Point:{},LineString:{},Polygon:{}}},function_stop:{type:"array",minimum:0,maximum:22,value:["number","color"],length:2},expression:{type:"array",value:"*",minimum:1},expression_name:{type:"enum",values:{let:{group:"Variable binding"},var:{group:"Variable binding"},literal:{group:"Types"},array:{group:"Types"},at:{group:"Lookup"},case:{group:"Decision"},match:{group:"Decision"},coalesce:{group:"Decision"},step:{group:"Ramps, scales, curves"},interpolate:{group:"Ramps, scales, curves"},ln2:{group:"Math"},pi:{group:"Math"},e:{group:"Math"},typeof:{group:"Types"},string:{group:"Types"},number:{group:"Types"},boolean:{group:"Types"},object:{group:"Types"},collator:{group:"Types"},"to-string":{group:"Types"},"to-number":{group:"Types"},"to-boolean":{group:"Types"},"to-rgba":{group:"Color"},"to-color":{group:"Types"},rgb:{group:"Color"},rgba:{group:"Color"},get:{group:"Lookup"},has:{group:"Lookup"},length:{group:"Lookup"},properties:{group:"Feature data"},"geometry-type":{group:"Feature data"},id:{group:"Feature data"},zoom:{group:"Zoom"},"heatmap-density":{group:"Heatmap"},"line-progress":{group:"Heatmap"},"+":{group:"Math"},"*":{group:"Math"},"-":{group:"Math"},"/":{group:"Math"},"%":{group:"Math"},"^":{group:"Math"},sqrt:{group:"Math"},log10:{group:"Math"},ln:{group:"Math"},log2:{group:"Math"},sin:{group:"Math"},cos:{group:"Math"},tan:{group:"Math"},asin:{group:"Math"},acos:{group:"Math"},atan:{group:"Math"},min:{group:"Math"},max:{group:"Math"},round:{group:"Math"},abs:{group:"Math"},ceil:{group:"Math"},floor:{group:"Math"},"==":{group:"Decision"},"!=":{group:"Decision"},">":{group:"Decision"},"<":{group:"Decision"},">=":{group:"Decision"},"<=":{group:"Decision"},all:{group:"Decision"},any:{group:"Decision"},"!":{group:"Decision"},"is-supported-script":{group:"String"},upcase:{group:"String"},downcase:{group:"String"},concat:{group:"String"},"resolved-locale":{group:"String"}}},light:{anchor:{type:"enum",default:"viewport",values:{map:{},viewport:{}},transition:!1,"zoom-function":!0,"property-function":!1,function:"piecewise-constant"},position:{type:"array",default:[1.15,210,30],length:3,value:"number",transition:!0,function:"interpolated","zoom-function":!0,"property-function":!1},color:{type:"color",default:"#ffffff",function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0},intensity:{type:"number",default:.5,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0}},paint:["paint_fill","paint_line","paint_circle","paint_heatmap","paint_fill-extrusion","paint_symbol","paint_raster","paint_hillshade","paint_background"],paint_fill:{"fill-antialias":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!0},"fill-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:1,minimum:0,maximum:1,transition:!0},"fill-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-pattern"}]},"fill-outline-color":{type:"color",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-pattern"},{"fill-antialias":!0}]},"fill-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"fill-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["fill-translate"]},"fill-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0}},paint_line:{"line-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:1,minimum:0,maximum:1,transition:!0},"line-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"line-pattern"}]},"line-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"line-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["line-translate"]},"line-width":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-gap-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-offset":{type:"number",default:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-dasharray":{type:"array",value:"number",function:"piecewise-constant","zoom-function":!0,minimum:0,transition:!0,units:"line widths",requires:[{"!":"line-pattern"}]},"line-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"line-gradient":{type:"color",function:"interpolated","zoom-function":!1,"property-function":!1,transition:!1,requires:[{"!":"line-dasharray"},{"!":"line-pattern"},{source:"geojson",has:{lineMetrics:!0}}]}},paint_circle:{"circle-radius":{type:"number",default:5,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"circle-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-blur":{type:"number",default:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"circle-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["circle-translate"]},"circle-pitch-scale":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map"},"circle-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"viewport"},"circle-stroke-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"circle-stroke-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-stroke-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0}},paint_heatmap:{"heatmap-radius":{type:"number",default:30,minimum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"heatmap-weight":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!1},"heatmap-intensity":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0},"heatmap-color":{type:"color",default:["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",.1,"royalblue",.3,"cyan",.5,"lime",.7,"yellow",1,"red"],function:"interpolated","zoom-function":!1,"property-function":!1,transition:!1},"heatmap-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0}},paint_symbol:{"icon-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-halo-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-halo-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["icon-image","icon-translate"]},"text-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-halo-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-halo-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["text-field","text-translate"]}},paint_raster:{"raster-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-hue-rotate":{type:"number",default:0,period:360,function:"interpolated","zoom-function":!0,transition:!0,units:"degrees"},"raster-brightness-min":{type:"number",function:"interpolated","zoom-function":!0,default:0,minimum:0,maximum:1,transition:!0},"raster-brightness-max":{type:"number",function:"interpolated","zoom-function":!0,default:1,minimum:0,maximum:1,transition:!0},"raster-saturation":{type:"number",default:0,minimum:-1,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-contrast":{type:"number",default:0,minimum:-1,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-fade-duration":{type:"number",default:300,minimum:0,function:"interpolated","zoom-function":!0,transition:!1,units:"milliseconds"}},paint_hillshade:{"hillshade-illumination-direction":{type:"number",default:335,minimum:0,maximum:359,function:"interpolated","zoom-function":!0,transition:!1},"hillshade-illumination-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"viewport"},"hillshade-exaggeration":{type:"number",default:.5,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"hillshade-shadow-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0},"hillshade-highlight-color":{type:"color",default:"#FFFFFF",function:"interpolated","zoom-function":!0,transition:!0},"hillshade-accent-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0}},paint_background:{"background-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0,requires:[{"!":"background-pattern"}]},"background-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"background-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0}},transition:{duration:{type:"number",default:300,minimum:0,units:"milliseconds"},delay:{type:"number",default:0,minimum:0,units:"milliseconds"}},"layout_fill-extrusion":{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},function:{expression:{type:"expression"},stops:{type:"array",value:"function_stop"},base:{type:"number",default:1,minimum:0},property:{type:"string",default:"$zoom"},type:{type:"enum",values:{identity:{},exponential:{},interval:{},categorical:{}},default:"exponential"},colorSpace:{type:"enum",values:{rgb:{},lab:{},hcl:{}},default:"rgb"},default:{type:"*",required:!1}},"paint_fill-extrusion":{"fill-extrusion-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!1,default:1,minimum:0,maximum:1,transition:!0},"fill-extrusion-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-extrusion-pattern"}]},"fill-extrusion-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"fill-extrusion-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["fill-extrusion-translate"]},"fill-extrusion-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"fill-extrusion-height":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:0,minimum:0,units:"meters",transition:!0},"fill-extrusion-base":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:0,minimum:0,units:"meters",transition:!0,requires:["fill-extrusion-height"]}}},F=function(t,e,r,n){this.message=(t?t+": ":"")+r,n&&(this.identifier=n),null!=e&&e.__line__&&(this.line=e.__line__);};function P(t){var e=t.key,r=t.value;return r?[new F(e,r,"constants have been deprecated as of v8")]:[]}function T(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];for(var n=0,i=e;n":"value"===t.itemType.kind?"array":"array<"+e+">"}return t.kind}var G=[R,U,D,N,Z,K,H(J)];function Y(t,e){if("error"===e.kind)return null;if("array"===t.kind){if("array"===e.kind&&!Y(t.itemType,e.itemType)&&("number"!=typeof t.N||t.N===e.N))return null}else{if(t.kind===e.kind)return null;if("value"===t.kind)for(var r=0,n=G;r255?255:t}function i(t){return t<0?0:t>1?1:t}function o(t){return"%"===t[t.length-1]?n(parseFloat(t)/100*255):n(parseInt(t))}function a(t){return"%"===t[t.length-1]?i(parseFloat(t)/100):i(parseFloat(t))}function s(t,e,r){return r<0?r+=1:r>1&&(r-=1),6*r<1?t+(e-t)*r*6:2*r<1?e:3*r<2?t+(e-t)*(2/3-r)*6:t}try{e.parseCSSColor=function(t){var e,i=t.replace(/ /g,"").toLowerCase();if(i in r)return r[i].slice();if("#"===i[0])return 4===i.length?(e=parseInt(i.substr(1),16))>=0&&e<=4095?[(3840&e)>>4|(3840&e)>>8,240&e|(240&e)>>4,15&e|(15&e)<<4,1]:null:7===i.length&&(e=parseInt(i.substr(1),16))>=0&&e<=16777215?[(16711680&e)>>16,(65280&e)>>8,255&e,1]:null;var u=i.indexOf("("),l=i.indexOf(")");if(-1!==u&&l+1===i.length){var p=i.substr(0,u),c=i.substr(u+1,l-(u+1)).split(","),h=1;switch(p){case"rgba":if(4!==c.length)return null;h=a(c.pop());case"rgb":return 3!==c.length?null:[o(c[0]),o(c[1]),o(c[2]),h];case"hsla":if(4!==c.length)return null;h=a(c.pop());case"hsl":if(3!==c.length)return null;var f=(parseFloat(c[0])%360+360)%360/360,y=a(c[1]),d=a(c[2]),v=d<=.5?d*(y+1):d+y-d*y,m=2*d-v;return[n(255*s(m,v,f+1/3)),n(255*s(m,v,f)),n(255*s(m,v,f-1/3)),h];default:return null}}return null};}catch(t){}}).parseCSSColor,Q=function(t,e,r,n){void 0===n&&(n=1),this.r=t,this.g=e,this.b=r,this.a=n;};Q.parse=function(t){if(t){if(t instanceof Q)return t;if("string"==typeof t){var e=W(t);if(e)return new Q(e[0]/255*e[3],e[1]/255*e[3],e[2]/255*e[3],e[3])}}},Q.prototype.toString=function(){var t=this.toArray(),e=t[0],r=t[1],n=t[2],i=t[3];return"rgba("+Math.round(e)+","+Math.round(r)+","+Math.round(n)+","+i+")"},Q.prototype.toArray=function(){var t=this.r,e=this.g,r=this.b,n=this.a;return 0===n?[0,0,0,0]:[255*t/n,255*e/n,255*r/n,n]},Q.black=new Q(0,0,0,1),Q.white=new Q(1,1,1,1),Q.transparent=new Q(0,0,0,0);var tt=function(t,e,r){this.sensitivity=t?e?"variant":"case":e?"accent":"base",this.locale=r,this.collator=new Intl.Collator(this.locale?this.locale:[],{sensitivity:this.sensitivity,usage:"search"});};tt.prototype.compare=function(t,e){return this.collator.compare(t,e)},tt.prototype.resolvedLocale=function(){return new Intl.Collator(this.locale?this.locale:[]).resolvedOptions().locale};var et=function(t,e,r){this.type=$,this.locale=r,this.caseSensitive=t,this.diacriticSensitive=e;};function rt(t,e,r,n){return"number"==typeof t&&t>=0&&t<=255&&"number"==typeof e&&e>=0&&e<=255&&"number"==typeof r&&r>=0&&r<=255?void 0===n||"number"==typeof n&&n>=0&&n<=1?null:"Invalid rgba value ["+[t,e,r,n].join(", ")+"]: 'a' must be between 0 and 1.":"Invalid rgba value ["+("number"==typeof n?[t,e,r,n]:[t,e,r]).join(", ")+"]: 'r', 'g', and 'b' must be between 0 and 255."}function nt(t){if(null===t)return R;if("string"==typeof t)return D;if("boolean"==typeof t)return N;if("number"==typeof t)return U;if(t instanceof Q)return Z;if(t instanceof tt)return $;if(Array.isArray(t)){for(var e,r=t.length,n=0,i=t;n4)return e.error("Expected 1, 2, or 3 arguments, but found "+(t.length-1)+" instead.");var r,n;if(t.length>2){var i=t[1];if("string"!=typeof i||!(i in ut))return e.error('The item type argument of "array" must be one of string, number, boolean',1);r=ut[i];}else r=J;if(t.length>3){if("number"!=typeof t[2]||t[2]<0||t[2]!==Math.floor(t[2]))return e.error('The length argument to "array" must be a positive integer literal',2);n=t[2];}var o=H(r,n),a=e.parse(t[t.length-1],t.length-1,J);return a?new lt(o,a):null},lt.prototype.evaluate=function(t){var e=this.input.evaluate(t);if(Y(this.type,nt(e)))throw new ot("Expected value to be of type "+X(this.type)+", but found "+X(nt(e))+" instead.");return e},lt.prototype.eachChild=function(t){t(this.input);},lt.prototype.possibleOutputs=function(){return this.input.possibleOutputs()},lt.prototype.serialize=function(){var t=["array"],e=this.type.itemType;if("string"===e.kind||"number"===e.kind||"boolean"===e.kind){t.push(e.kind);var r=this.type.N;"number"==typeof r&&t.push(r);}return t.push(this.input.serialize()),t};var pt={"to-number":U,"to-color":Z},ct=function(t,e){this.type=t,this.args=e;};ct.parse=function(t,e){if(t.length<2)return e.error("Expected at least one argument.");for(var r=t[0],n=pt[r],i=[],o=1;o4?"Invalid rbga value "+JSON.stringify(e)+": expected an array containing either three or four numeric values.":rt(e[0],e[1],e[2],e[3])))return new Q(e[0]/255,e[1]/255,e[2]/255,e[3])}throw new ot(r||"Could not parse color from value '"+("string"==typeof e?e:JSON.stringify(e))+"'")}for(var a=null,s=0,u=this.args;s=0)return!1;var r=!0;return t.eachChild(function(t){r&&!vt(t,e)&&(r=!1);}),r}yt.prototype.evaluate=function(t){return this._evaluate(t,this.args)},yt.prototype.eachChild=function(t){this.args.forEach(t);},yt.prototype.possibleOutputs=function(){return[void 0]},yt.prototype.serialize=function(){return[this.name].concat(this.args.map(function(t){return t.serialize()}))},yt.parse=function(t,e){var r=t[0],n=yt.definitions[r];if(!n)return e.error('Unknown expression "'+r+'". If you wanted a literal array, use ["literal", [...]].',0);for(var i=Array.isArray(n)?n[0]:n.type,o=Array.isArray(n)?[[n[1],n[2]]]:n.overloads,a=o.filter(function(e){var r=e[0];return!Array.isArray(r)||r.length===t.length-1}),s=[],u=1;ur&&ee))throw new ot("Input is not a number.");o=a-1;}}return Math.max(a-1,0)}gt.prototype.parse=function(t,e,r,n,i){return void 0===i&&(i={}),e?this.concat(e,r,n)._parse(t,i):this._parse(t,i)},gt.prototype._parse=function(t,e){if(null!==t&&"string"!=typeof t&&"boolean"!=typeof t&&"number"!=typeof t||(t=["literal",t]),Array.isArray(t)){if(0===t.length)return this.error('Expected an array with at least one element. If you wanted a literal array, use ["literal", []].');var r=t[0];if("string"!=typeof r)return this.error("Expression name must be a string, but found "+typeof r+' instead. If you wanted a literal array, use ["literal", [...]].',0),null;var n=this.registry[r];if(n){var i=n.parse(t,this);if(!i)return null;if(this.expectedType){var o=this.expectedType,a=i.type;if("string"!==o.kind&&"number"!==o.kind&&"boolean"!==o.kind&&"object"!==o.kind||"value"!==a.kind)if("array"===o.kind&&"value"===a.kind)e.omitTypeAnnotations||(i=new lt(o,i));else if("color"!==o.kind||"value"!==a.kind&&"string"!==a.kind){if(this.checkSubtype(this.expectedType,i.type))return null}else e.omitTypeAnnotations||(i=new ct(o,[i]));else e.omitTypeAnnotations||(i=new st(o,[i]));}if(!(i instanceof it)&&function t(e){if(e instanceof mt)return t(e.boundExpression);if(e instanceof yt&&"error"===e.name)return!1;if(e instanceof et)return!1;var r=e instanceof ct||e instanceof st||e instanceof lt;var n=!0;e.eachChild(function(e){n=r?n&&t(e):n&&e instanceof it;});if(!n)return!1;return dt(e)&&vt(e,["zoom","heatmap-density","line-progress","is-supported-script"])}(i)){var s=new ft;try{i=new it(i.type,i.evaluate(s));}catch(t){return this.error(t.message),null}}return i}return this.error('Unknown expression "'+r+'". If you wanted a literal array, use ["literal", [...]].',0)}return void 0===t?this.error("'undefined' value invalid. Use null instead."):"object"==typeof t?this.error('Bare objects invalid. Use ["literal", {...}] instead.'):this.error("Expected an array, but found "+typeof t+" instead.")},gt.prototype.concat=function(t,e,r){var n="number"==typeof t?this.path.concat(t):this.path,i=r?this.scope.concat(r):this.scope;return new gt(this.registry,n,e||null,i,this.errors)},gt.prototype.error=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];var n=""+this.key+e.map(function(t){return"["+t+"]"}).join("");this.errors.push(new j(n,t));},gt.prototype.checkSubtype=function(t,e){var r=Y(t,e);return r&&this.error(r),r};var bt=function(t,e,r){this.type=t,this.input=e,this.labels=[],this.outputs=[];for(var n=0,i=r;n=s)return e.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.',l);var c=e.parse(u,p,o);if(!c)return null;o=o||c.type,i.push([s,c]);}return new bt(o,r,i)},bt.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;return n>=e[i-1]?r[i-1].evaluate(t):r[xt(e,n)].evaluate(t)},bt.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e0&&t.push(this.labels[e]),t.push(this.outputs[e].serialize());return t};var _t=Object.freeze({number:wt,color:function(t,e,r){return new Q(wt(t.r,e.r,r),wt(t.g,e.g,r),wt(t.b,e.b,r),wt(t.a,e.a,r))},array:function(t,e,r){return t.map(function(t,n){return wt(t,e[n],r)})}}),At=function(t,e,r,n){this.type=t,this.interpolation=e,this.input=r,this.labels=[],this.outputs=[];for(var i=0,o=n;i1}))return e.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.",1);r={name:"cubic-bezier",controlPoints:a};}if(t.length-1<4)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if((t.length-1)%2!=0)return e.error("Expected an even number of arguments.");if(!(n=e.parse(n,2,U)))return null;var s=[],u=null;e.expectedType&&"value"!==e.expectedType.kind&&(u=e.expectedType);for(var l=0;l=p)return e.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.',h);var y=e.parse(c,f,u);if(!y)return null;u=u||y.type,s.push([p,y]);}return"number"===u.kind||"color"===u.kind||"array"===u.kind&&"number"===u.itemType.kind&&"number"==typeof u.N?new At(u,r,n,s):e.error("Type "+X(u)+" is not interpolatable.")},At.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;if(n>=e[i-1])return r[i-1].evaluate(t);var o=xt(e,n),a=e[o],s=e[o+1],u=At.interpolationFactor(this.interpolation,n,a,s),l=r[o].evaluate(t),p=r[o+1].evaluate(t);return _t[this.type.kind.toLowerCase()](l,p,u)},At.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e=r.length)throw new ot("Array index out of bounds: "+e+" > "+(r.length-1)+".");if(e!==Math.floor(e))throw new ot("Array index must be an integer, but found "+e+" instead.");return r[e]},Mt.prototype.eachChild=function(t){t(this.index),t(this.input);},Mt.prototype.possibleOutputs=function(){return[void 0]},Mt.prototype.serialize=function(){return["at",this.index.serialize(),this.input.serialize()]};var Vt=function(t,e,r,n,i,o){this.inputType=t,this.type=e,this.input=r,this.cases=n,this.outputs=i,this.otherwise=o;};Vt.parse=function(t,e){if(t.length<5)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if(t.length%2!=1)return e.error("Expected an even number of arguments.");var r,n;e.expectedType&&"value"!==e.expectedType.kind&&(n=e.expectedType);for(var i={},o=[],a=2;aNumber.MAX_SAFE_INTEGER)return l.error("Branch labels must be integers no larger than "+Number.MAX_SAFE_INTEGER+".");if("number"==typeof h&&Math.floor(h)!==h)return l.error("Numeric branch labels must be integer values.");if(r){if(l.checkSubtype(r,nt(h)))return null}else r=nt(h);if(void 0!==i[String(h)])return l.error("Branch labels must be unique.");i[String(h)]=o.length;}var f=e.parse(u,a,n);if(!f)return null;n=n||f.type,o.push(f);}var y=e.parse(t[1],1,r);if(!y)return null;var d=e.parse(t[t.length-1],t.length-1,n);return d?new Vt(r,n,y,i,o,d):null},Vt.prototype.evaluate=function(t){var e=this.input.evaluate(t);return(this.outputs[this.cases[e]]||this.otherwise).evaluate(t)},Vt.prototype.eachChild=function(t){t(this.input),this.outputs.forEach(t),t(this.otherwise);},Vt.prototype.possibleOutputs=function(){return(t=[]).concat.apply(t,this.outputs.map(function(t){return t.possibleOutputs()})).concat(this.otherwise.possibleOutputs());var t;},Vt.prototype.serialize=function(){for(var t=this,e=["match",this.input.serialize()],r=[],n={},i=0,o=Object.keys(this.cases).sort();in.evaluate(t)}function Ut(t,e){var r=e[0],n=e[1];return r.evaluate(t)<=n.evaluate(t)}function Dt(t,e){var r=e[0],n=e[1];return r.evaluate(t)>=n.evaluate(t)}function Nt(t){return{type:t}}function Zt(t){return{result:"success",value:t}}function Kt(t){return{result:"error",value:t}}yt.register(Tt,{error:[{kind:"error"},[D],function(t,e){var r=e[0];throw new ot(r.evaluate(t))}],typeof:[D,[J],function(t,e){return X(nt(e[0].evaluate(t)))}],"to-string":[D,[J],function(t,e){var r=e[0],n=typeof(r=r.evaluate(t));return null===r?"":"string"===n||"number"===n||"boolean"===n?String(r):r instanceof Q?r.toString():JSON.stringify(r)}],"to-boolean":[N,[J],function(t,e){var r=e[0];return Boolean(r.evaluate(t))}],"to-rgba":[H(U,4),[Z],function(t,e){return e[0].evaluate(t).toArray()}],rgb:[Z,[U,U,U],Ot],rgba:[Z,[U,U,U,U],Ot],has:{type:N,overloads:[[[D],function(t,e){return Lt(e[0].evaluate(t),t.properties())}],[[D,K],function(t,e){var r=e[0],n=e[1];return Lt(r.evaluate(t),n.evaluate(t))}]]},get:{type:J,overloads:[[[D],function(t,e){return jt(e[0].evaluate(t),t.properties())}],[[D,K],function(t,e){var r=e[0],n=e[1];return jt(r.evaluate(t),n.evaluate(t))}]]},properties:[K,[],function(t){return t.properties()}],"geometry-type":[D,[],function(t){return t.geometryType()}],id:[J,[],function(t){return t.id()}],zoom:[U,[],function(t){return t.globals.zoom}],"heatmap-density":[U,[],function(t){return t.globals.heatmapDensity||0}],"line-progress":[U,[],function(t){return t.globals.lineProgress||0}],"+":[U,Nt(U),function(t,e){for(var r=0,n=0,i=e;n":[N,[D,J],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],o=n.value;return typeof i==typeof o&&i>o}],"filter-id->":[N,[J],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>i}],"filter-<=":[N,[D,J],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],o=n.value;return typeof i==typeof o&&i<=o}],"filter-id-<=":[N,[J],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n<=i}],"filter->=":[N,[D,J],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],o=n.value;return typeof i==typeof o&&i>=o}],"filter-id->=":[N,[J],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>=i}],"filter-has":[N,[J],function(t,e){return e[0].value in t.properties()}],"filter-has-id":[N,[],function(t){return null!==t.id()}],"filter-type-in":[N,[H(D)],function(t,e){return e[0].value.indexOf(t.geometryType())>=0}],"filter-id-in":[N,[H(J)],function(t,e){return e[0].value.indexOf(t.id())>=0}],"filter-in-small":[N,[D,H(J)],function(t,e){var r=e[0];return e[1].value.indexOf(t.properties()[r.value])>=0}],"filter-in-large":[N,[D,H(J)],function(t,e){var r=e[0],n=e[1];return function(t,e,r,n){for(;r<=n;){var i=r+n>>1;if(e[i]===t)return!0;e[i]>t?n=i-1:r=i+1;}return!1}(t.properties()[r.value],n.value,0,n.value.length-1)}],">":{type:N,overloads:[[[U,U],Rt],[[D,D],Rt],[[D,D,$],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))>0}]]},"<":{type:N,overloads:[[[U,U],qt],[[D,D],qt],[[D,D,$],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))<0}]]},">=":{type:N,overloads:[[[U,U],Dt],[[D,D],Dt],[[D,D,$],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))>=0}]]},"<=":{type:N,overloads:[[[U,U],Ut],[[D,D],Ut],[[D,D,$],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))<=0}]]},all:{type:N,overloads:[[[N,N],function(t,e){var r=e[0],n=e[1];return r.evaluate(t)&&n.evaluate(t)}],[Nt(N),function(t,e){for(var r=0,n=e;rWt?Math.pow(t,1/3):t/Yt+Xt}function re(t){return t>Gt?t*t*t:Yt*(t-Xt)}function ne(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function ie(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function oe(t){var e=ie(t.r),r=ie(t.g),n=ie(t.b),i=ee((.4124564*e+.3575761*r+.1804375*n)/Jt),o=ee((.2126729*e+.7151522*r+.072175*n)/$t);return{l:116*o-16,a:500*(i-o),b:200*(o-ee((.0193339*e+.119192*r+.9503041*n)/Ht)),alpha:t.a}}function ae(t){var e=(t.l+16)/116,r=isNaN(t.a)?e:e+t.a/500,n=isNaN(t.b)?e:e-t.b/200;return e=$t*re(e),r=Jt*re(r),n=Ht*re(n),new Q(ne(3.2404542*r-1.5371385*e-.4985314*n),ne(-.969266*r+1.8760108*e+.041556*n),ne(.0556434*r-.2040259*e+1.0572252*n),t.alpha)}var se={forward:oe,reverse:ae,interpolate:function(t,e,r){return{l:wt(t.l,e.l,r),a:wt(t.a,e.a,r),b:wt(t.b,e.b,r),alpha:wt(t.alpha,e.alpha,r)}}},ue={forward:function(t){var e=oe(t),r=e.l,n=e.a,i=e.b,o=Math.atan2(i,n)*te;return{h:o<0?o+360:o,c:Math.sqrt(n*n+i*i),l:r,alpha:t.a}},reverse:function(t){var e=t.h*Qt,r=t.c;return ae({l:t.l,a:Math.cos(e)*r,b:Math.sin(e)*r,alpha:t.alpha})},interpolate:function(t,e,r){return{h:function(t,e,r){var n=e-t;return t+r*(n>180||n<-180?n-360*Math.round(n/360):n)}(t.h,e.h,r),c:wt(t.c,e.c,r),l:wt(t.l,e.l,r),alpha:wt(t.alpha,e.alpha,r)}}},le=Object.freeze({lab:se,hcl:ue});function pe(t){return t instanceof Number?"number":t instanceof String?"string":t instanceof Boolean?"boolean":Array.isArray(t)?"array":null===t?"null":typeof t}function ce(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function he(t){return t}function fe(t,e,r){return void 0!==t?t:void 0!==e?e:void 0!==r?r:void 0}function ye(t,e,r,n,i){return fe(typeof r===i?n[r]:void 0,t.default,e.default)}function de(t,e,r){if("number"!==pe(r))return fe(t.default,e.default);var n=t.stops.length;if(1===n)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[n-1][0])return t.stops[n-1][1];var i=ge(t.stops,r);return t.stops[i][1]}function ve(t,e,r){var n=void 0!==t.base?t.base:1;if("number"!==pe(r))return fe(t.default,e.default);var i=t.stops.length;if(1===i)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[i-1][0])return t.stops[i-1][1];var o=ge(t.stops,r),a=function(t,e,r,n){var i=n-r,o=t-r;return 0===i?0:1===e?o/i:(Math.pow(e,o)-1)/(Math.pow(e,i)-1)}(r,n,t.stops[o][0],t.stops[o+1][0]),s=t.stops[o][1],u=t.stops[o+1][1],l=_t[e.type]||he;if(t.colorSpace&&"rgb"!==t.colorSpace){var p=le[t.colorSpace];l=function(t,e){return p.reverse(p.interpolate(p.forward(t),p.forward(e),a))};}return"function"==typeof s.evaluate?{evaluate:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var r=s.evaluate.apply(void 0,t),n=u.evaluate.apply(void 0,t);if(void 0!==r&&void 0!==n)return l(r,n,a)}}:l(s,u,a)}function me(t,e,r){return"color"===e.type?r=Q.parse(r):pe(r)===e.type||"enum"===e.type&&e.values[r]||(r=void 0),fe(r,t.default,e.default)}function ge(t,e){for(var r,n,i=0,o=t.length-1,a=0;i<=o;){if(r=t[a=Math.floor((i+o)/2)][0],n=t[a+1][0],e===r||e>r&&ee&&(o=a-1);}return Math.max(a-1,0)}var xe=function(t,e){var r;this.expression=t,this._warningHistory={},this._defaultValue="color"===(r=e).type&&ce(r.default)?new Q(0,0,0,0):"color"===r.type?Q.parse(r.default)||null:void 0===r.default?null:r.default,"enum"===e.type&&(this._enumValues=e.values);};function be(t){return Array.isArray(t)&&t.length>0&&"string"==typeof t[0]&&t[0]in Tt}function we(t,e){var r=new gt(Tt,[],function(t){var e={color:Z,string:D,number:U,enum:D,boolean:N};if("array"===t.type)return H(e[t.value]||J,t.length);return e[t.type]||null}(e)),n=r.parse(t);return n?Zt(new xe(n,e)):Kt(r.errors)}xe.prototype.evaluateWithoutErrorHandling=function(t,e){return this._evaluator||(this._evaluator=new ft),this._evaluator.globals=t,this._evaluator.feature=e,this.expression.evaluate(this._evaluator)},xe.prototype.evaluate=function(t,e){this._evaluator||(this._evaluator=new ft),this._evaluator.globals=t,this._evaluator.feature=e;try{var r=this.expression.evaluate(this._evaluator);if(null==r)return this._defaultValue;if(this._enumValues&&!(r in this._enumValues))throw new ot("Expected value to be one of "+Object.keys(this._enumValues).map(function(t){return JSON.stringify(t)}).join(", ")+", but found "+JSON.stringify(r)+" instead.");return r}catch(t){return this._warningHistory[t.message]||(this._warningHistory[t.message]=!0,"undefined"!=typeof console&&console.warn(t.message)),this._defaultValue}};var _e=function(t,e){this.kind=t,this._styleExpression=e;};_e.prototype.evaluateWithoutErrorHandling=function(t,e){return this._styleExpression.evaluateWithoutErrorHandling(t,e)},_e.prototype.evaluate=function(t,e){return this._styleExpression.evaluate(t,e)};var Ae=function(t,e,r){this.kind=t,this.zoomStops=r.labels,this._styleExpression=e,r instanceof At&&(this._interpolationType=r.interpolation);};function ke(t,e){if("error"===(t=we(t,e)).result)return t;var r=t.value.expression,n=dt(r);if(!n&&!e["property-function"])return Kt([new j("","property expressions not supported")]);var i=vt(r,["zoom"]);if(!i&&!1===e["zoom-function"])return Kt([new j("","zoom expressions not supported")]);var o=function t(e){var r=null;if(e instanceof St)r=t(e.result);else if(e instanceof zt)for(var n=0,i=e.args;nn.maximum?[new F(e,r,r+" is greater than the maximum value "+n.maximum)]:[]}function Ce(t){var e,r,n,i=t.valueSpec,o=O(t.value.type),a={},s="categorical"!==o&&void 0===t.value.property,u=!s,l="array"===pe(t.value.stops)&&"array"===pe(t.value.stops[0])&&"object"===pe(t.value.stops[0][0]),p=Me({key:t.key,value:t.value,valueSpec:t.styleSpec.function,style:t.style,styleSpec:t.styleSpec,objectElementValidators:{stops:function(t){if("identity"===o)return[new F(t.key,t.value,'identity function may not have a "stops" property')];var e=[],r=t.value;e=e.concat(Ve({key:t.key,value:r,valueSpec:t.valueSpec,style:t.style,styleSpec:t.styleSpec,arrayElementValidator:c})),"array"===pe(r)&&0===r.length&&e.push(new F(t.key,r,"array must have at least one stop"));return e},default:function(t){return Ye({key:t.key,value:t.value,valueSpec:i,style:t.style,styleSpec:t.styleSpec})}}});return"identity"===o&&s&&p.push(new F(t.key,t.value,'missing required property "property"')),"identity"===o||t.value.stops||p.push(new F(t.key,t.value,'missing required property "stops"')),"exponential"===o&&"piecewise-constant"===t.valueSpec.function&&p.push(new F(t.key,t.value,"exponential functions not supported")),t.styleSpec.$version>=8&&(u&&!t.valueSpec["property-function"]?p.push(new F(t.key,t.value,"property functions not supported")):s&&!t.valueSpec["zoom-function"]&&"heatmap-color"!==t.objectKey&&"line-gradient"!==t.objectKey&&p.push(new F(t.key,t.value,"zoom functions not supported"))),"categorical"!==o&&!l||void 0!==t.value.property||p.push(new F(t.key,t.value,'"property" property is required')),p;function c(t){var e=[],o=t.value,s=t.key;if("array"!==pe(o))return[new F(s,o,"array expected, "+pe(o)+" found")];if(2!==o.length)return[new F(s,o,"array length 2 expected, length "+o.length+" found")];if(l){if("object"!==pe(o[0]))return[new F(s,o,"object expected, "+pe(o[0])+" found")];if(void 0===o[0].zoom)return[new F(s,o,"object stop key must have zoom")];if(void 0===o[0].value)return[new F(s,o,"object stop key must have value")];if(n&&n>O(o[0].zoom))return[new F(s,o[0].zoom,"stop zoom values must appear in ascending order")];O(o[0].zoom)!==n&&(n=O(o[0].zoom),r=void 0,a={}),e=e.concat(Me({key:s+"[0]",value:o[0],valueSpec:{zoom:{}},style:t.style,styleSpec:t.styleSpec,objectElementValidators:{zoom:Be,value:h}}));}else e=e.concat(h({key:s+"[0]",value:o[0],valueSpec:{},style:t.style,styleSpec:t.styleSpec},o));return e.concat(Ye({key:s+"[1]",value:o[1],valueSpec:i,style:t.style,styleSpec:t.styleSpec}))}function h(t,n){var s=pe(t.value),u=O(t.value),l=null!==t.value?t.value:n;if(e){if(s!==e)return[new F(t.key,l,s+" stop domain type must match previous stop domain type "+e)]}else e=s;if("number"!==s&&"string"!==s&&"boolean"!==s)return[new F(t.key,l,"stop domain value must be a number, string, or boolean")];if("number"!==s&&"categorical"!==o){var p="number expected, "+s+" found";return i["property-function"]&&void 0===o&&(p+='\nIf you intended to use a categorical function, specify `"type": "categorical"`.'),[new F(t.key,l,p)]}return"categorical"!==o||"number"!==s||isFinite(u)&&Math.floor(u)===u?"categorical"!==o&&"number"===s&&void 0!==r&&u=2&&"$id"!==t[1]&&"$type"!==t[1];case"in":case"!in":case"!has":case"none":return!1;case"==":case"!=":case">":case">=":case"<":case"<=":return 3===t.length&&(Array.isArray(t[1])||Array.isArray(t[2]));case"any":case"all":for(var e=0,r=t.slice(1);ee?1:0}function Le(t){if(!t)return!0;var e,r=t[0];return t.length<=1?"any"!==r:"=="===r?je(t[1],t[2],"=="):"!="===r?Ue(je(t[1],t[2],"==")):"<"===r||">"===r||"<="===r||">="===r?je(t[1],t[2],r):"any"===r?(e=t.slice(1),["any"].concat(e.map(Le))):"all"===r?["all"].concat(t.slice(1).map(Le)):"none"===r?["all"].concat(t.slice(1).map(Le).map(Ue)):"in"===r?qe(t[1],t.slice(2)):"!in"===r?Ue(qe(t[1],t.slice(2))):"has"===r?Re(t[1]):"!has"!==r||Ue(Re(t[1]))}function je(t,e,r){switch(t){case"$type":return["filter-type-"+r,e];case"$id":return["filter-id-"+r,e];default:return["filter-"+r,t,e]}}function qe(t,e){if(0===e.length)return!1;switch(t){case"$type":return["filter-type-in",["literal",e]];case"$id":return["filter-id-in",["literal",e]];default:return e.length>200&&!e.some(function(t){return typeof t!=typeof e[0]})?["filter-in-large",t,["literal",e.sort(Oe)]]:["filter-in-small",t,["literal",e]]}}function Re(t){switch(t){case"$type":return!0;case"$id":return["filter-has-id"];default:return["filter-has",t]}}function Ue(t){return["!",t]}function De(t){return Fe(L(t.value))?Ie(T({},t,{expressionContext:"filter",valueSpec:{value:"boolean"}})):function t(e){var r=e.value;var n=e.key;if("array"!==pe(r))return[new F(n,r,"array expected, "+pe(r)+" found")];var i=e.styleSpec;var o;var a=[];if(r.length<1)return[new F(n,r,"filter array must have at least 1 element")];a=a.concat(Ee({key:n+"[0]",value:r[0],valueSpec:i.filter_operator,style:e.style,styleSpec:e.styleSpec}));switch(O(r[0])){case"<":case"<=":case">":case">=":r.length>=2&&"$type"===O(r[1])&&a.push(new F(n,r,'"$type" cannot be use with operator "'+r[0]+'"'));case"==":case"!=":3!==r.length&&a.push(new F(n,r,'filter array for operator "'+r[0]+'" must have 3 elements'));case"in":case"!in":r.length>=2&&"string"!==(o=pe(r[1]))&&a.push(new F(n+"[1]",r[1],"string expected, "+o+" found"));for(var s=2;s=l[h+0]&&n>=l[h+1]?(a[c]=!0,o.push(u[c])):a[c]=!1;}}},lr.prototype._forEachCell=function(t,e,r,n,i,o,a){for(var s=this._convertToCellCoord(t),u=this._convertToCellCoord(e),l=this._convertToCellCoord(r),p=this._convertToCellCoord(n),c=s;c<=l;c++)for(var h=u;h<=p;h++){var f=this.d*h+c;if(i.call(this,t,e,r,n,f,o,a))return}},lr.prototype._convertToCellCoord=function(t){return Math.max(0,Math.min(this.d-1,Math.floor(t*this.scale)+this.padding))},lr.prototype.toArrayBuffer=function(){if(this.arrayBuffer)return this.arrayBuffer;for(var t=this.cells,e=ur+this.cells.length+1+1,r=0,n=0;n=0)){var c=t[p];l[p]=cr[u].shallow.indexOf(p)>=0?c:yr(c,e);}t instanceof Error&&(l.message=t.message);}return{name:u,properties:l}}throw new Error("can't serialize object of type "+typeof t)}function dr(t){if(null==t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||t instanceof Boolean||t instanceof Number||t instanceof String||t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||ArrayBuffer.isView(t)||t instanceof pr)return t;if(Array.isArray(t))return t.map(function(t){return dr(t)});if("object"==typeof t){var e=t,r=e.name,n=e.properties;if(!r)throw new Error("can't deserialize object of anonymous class");var i=cr[r].klass;if(!i)throw new Error("can't deserialize unregistered class "+r);if(i.deserialize)return i.deserialize(n._serialized);for(var o=Object.create(i.prototype),a=0,s=Object.keys(n);a=0?n[u]:dr(n[u]);}return o}throw new Error("can't deserialize object of type "+typeof t)}var vr=function(){this.first=!0;};vr.prototype.update=function(t,e){var r=Math.floor(t);return this.first?(this.first=!1,this.lastIntegerZoom=r,this.lastIntegerZoomTime=0,this.lastZoom=t,this.lastFloorZoom=r,!0):(this.lastFloorZoom>r?(this.lastIntegerZoom=r+1,this.lastIntegerZoomTime=e):this.lastFloorZoom=128&&t<=255},Arabic:function(t){return t>=1536&&t<=1791},"Arabic Supplement":function(t){return t>=1872&&t<=1919},"Arabic Extended-A":function(t){return t>=2208&&t<=2303},"Hangul Jamo":function(t){return t>=4352&&t<=4607},"Unified Canadian Aboriginal Syllabics":function(t){return t>=5120&&t<=5759},Khmer:function(t){return t>=6016&&t<=6143},"Unified Canadian Aboriginal Syllabics Extended":function(t){return t>=6320&&t<=6399},"General Punctuation":function(t){return t>=8192&&t<=8303},"Letterlike Symbols":function(t){return t>=8448&&t<=8527},"Number Forms":function(t){return t>=8528&&t<=8591},"Miscellaneous Technical":function(t){return t>=8960&&t<=9215},"Control Pictures":function(t){return t>=9216&&t<=9279},"Optical Character Recognition":function(t){return t>=9280&&t<=9311},"Enclosed Alphanumerics":function(t){return t>=9312&&t<=9471},"Geometric Shapes":function(t){return t>=9632&&t<=9727},"Miscellaneous Symbols":function(t){return t>=9728&&t<=9983},"Miscellaneous Symbols and Arrows":function(t){return t>=11008&&t<=11263},"CJK Radicals Supplement":function(t){return t>=11904&&t<=12031},"Kangxi Radicals":function(t){return t>=12032&&t<=12255},"Ideographic Description Characters":function(t){return t>=12272&&t<=12287},"CJK Symbols and Punctuation":function(t){return t>=12288&&t<=12351},Hiragana:function(t){return t>=12352&&t<=12447},Katakana:function(t){return t>=12448&&t<=12543},Bopomofo:function(t){return t>=12544&&t<=12591},"Hangul Compatibility Jamo":function(t){return t>=12592&&t<=12687},Kanbun:function(t){return t>=12688&&t<=12703},"Bopomofo Extended":function(t){return t>=12704&&t<=12735},"CJK Strokes":function(t){return t>=12736&&t<=12783},"Katakana Phonetic Extensions":function(t){return t>=12784&&t<=12799},"Enclosed CJK Letters and Months":function(t){return t>=12800&&t<=13055},"CJK Compatibility":function(t){return t>=13056&&t<=13311},"CJK Unified Ideographs Extension A":function(t){return t>=13312&&t<=19903},"Yijing Hexagram Symbols":function(t){return t>=19904&&t<=19967},"CJK Unified Ideographs":function(t){return t>=19968&&t<=40959},"Yi Syllables":function(t){return t>=40960&&t<=42127},"Yi Radicals":function(t){return t>=42128&&t<=42191},"Hangul Jamo Extended-A":function(t){return t>=43360&&t<=43391},"Hangul Syllables":function(t){return t>=44032&&t<=55215},"Hangul Jamo Extended-B":function(t){return t>=55216&&t<=55295},"Private Use Area":function(t){return t>=57344&&t<=63743},"CJK Compatibility Ideographs":function(t){return t>=63744&&t<=64255},"Arabic Presentation Forms-A":function(t){return t>=64336&&t<=65023},"Vertical Forms":function(t){return t>=65040&&t<=65055},"CJK Compatibility Forms":function(t){return t>=65072&&t<=65103},"Small Form Variants":function(t){return t>=65104&&t<=65135},"Arabic Presentation Forms-B":function(t){return t>=65136&&t<=65279},"Halfwidth and Fullwidth Forms":function(t){return t>=65280&&t<=65519}};function gr(t){for(var e=0,r=t;e=65097&&t<=65103)||(!!mr["CJK Compatibility Ideographs"](t)||(!!mr["CJK Compatibility"](t)||(!!mr["CJK Radicals Supplement"](t)||(!!mr["CJK Strokes"](t)||(!(!mr["CJK Symbols and Punctuation"](t)||t>=12296&&t<=12305||t>=12308&&t<=12319||12336===t)||(!!mr["CJK Unified Ideographs Extension A"](t)||(!!mr["CJK Unified Ideographs"](t)||(!!mr["Enclosed CJK Letters and Months"](t)||(!!mr["Hangul Compatibility Jamo"](t)||(!!mr["Hangul Jamo Extended-A"](t)||(!!mr["Hangul Jamo Extended-B"](t)||(!!mr["Hangul Jamo"](t)||(!!mr["Hangul Syllables"](t)||(!!mr.Hiragana(t)||(!!mr["Ideographic Description Characters"](t)||(!!mr.Kanbun(t)||(!!mr["Kangxi Radicals"](t)||(!!mr["Katakana Phonetic Extensions"](t)||(!(!mr.Katakana(t)||12540===t)||(!(!mr["Halfwidth and Fullwidth Forms"](t)||65288===t||65289===t||65293===t||t>=65306&&t<=65310||65339===t||65341===t||65343===t||t>=65371&&t<=65503||65507===t||t>=65512&&t<=65519)||(!(!mr["Small Form Variants"](t)||t>=65112&&t<=65118||t>=65123&&t<=65126)||(!!mr["Unified Canadian Aboriginal Syllabics"](t)||(!!mr["Unified Canadian Aboriginal Syllabics Extended"](t)||(!!mr["Vertical Forms"](t)||(!!mr["Yijing Hexagram Symbols"](t)||(!!mr["Yi Syllables"](t)||!!mr["Yi Radicals"](t))))))))))))))))))))))))))))))}function wr(t){return!(br(t)||function(t){return!!(mr["Latin-1 Supplement"](t)&&(167===t||169===t||174===t||177===t||188===t||189===t||190===t||215===t||247===t)||mr["General Punctuation"](t)&&(8214===t||8224===t||8225===t||8240===t||8241===t||8251===t||8252===t||8258===t||8263===t||8264===t||8265===t||8273===t)||mr["Letterlike Symbols"](t)||mr["Number Forms"](t)||mr["Miscellaneous Technical"](t)&&(t>=8960&&t<=8967||t>=8972&&t<=8991||t>=8996&&t<=9e3||9003===t||t>=9085&&t<=9114||t>=9150&&t<=9165||9167===t||t>=9169&&t<=9179||t>=9186&&t<=9215)||mr["Control Pictures"](t)&&9251!==t||mr["Optical Character Recognition"](t)||mr["Enclosed Alphanumerics"](t)||mr["Geometric Shapes"](t)||mr["Miscellaneous Symbols"](t)&&!(t>=9754&&t<=9759)||mr["Miscellaneous Symbols and Arrows"](t)&&(t>=11026&&t<=11055||t>=11088&&t<=11097||t>=11192&&t<=11243)||mr["CJK Symbols and Punctuation"](t)||mr.Katakana(t)||mr["Private Use Area"](t)||mr["CJK Compatibility Forms"](t)||mr["Small Form Variants"](t)||mr["Halfwidth and Fullwidth Forms"](t)||8734===t||8756===t||8757===t||t>=9984&&t<=10087||t>=10102&&t<=10131||65532===t||65533===t)}(t))}function _r(t,e){return!(!e&&(t>=1424&&t<=2303||mr["Arabic Presentation Forms-A"](t)||mr["Arabic Presentation Forms-B"](t)))&&!(t>=2304&&t<=3583||t>=3840&&t<=4255||mr.Khmer(t))}var Ar,kr=!1,zr=null,Sr=!1,Mr=new I,Vr={applyArabicShaping:null,processBidirectionalText:null,isLoaded:function(){return Sr||null!=Vr.applyArabicShaping}},Br=function(t,e){this.zoom=t,e?(this.now=e.now,this.fadeDuration=e.fadeDuration,this.zoomHistory=e.zoomHistory,this.transition=e.transition):(this.now=0,this.fadeDuration=0,this.zoomHistory=new vr,this.transition={});};Br.prototype.isSupportedScript=function(t){return function(t,e){for(var r=0,n=t;rthis.end)return this.prior=null,r;if(this.value.isDataDriven())return this.prior=null,r;if(e=1)return 1;var e=t*t,r=e*t;return 4*(t<.5?r:3*(t-e)+r-.75)}(i))}return r};var Pr=function(t){this._properties=t,this._values=Object.create(t.defaultTransitioningPropertyValues);};Pr.prototype.possiblyEvaluate=function(t){for(var e=new Lr(this._properties),r=0,n=Object.keys(this._values);rn.zoomHistory.lastIntegerZoom?{from:t,to:e,fromScale:2,toScale:1,t:o+(1-o)*a}:{from:r,to:e,fromScale:.5,toScale:1,t:1-(1-a)*o}},Rr.prototype.interpolate=function(t){return t};var Ur=function(t){this.specification=t;};Ur.prototype.possiblyEvaluate=function(t,e){return!!t.expression.evaluate(e)},Ur.prototype.interpolate=function(){return!1};var Dr=function(t){for(var e in this.properties=t,this.defaultPropertyValues={},this.defaultTransitionablePropertyValues={},this.defaultTransitioningPropertyValues={},this.defaultPossiblyEvaluatedValues={},t){var r=t[e],n=this.defaultPropertyValues[e]=new Cr(r,void 0),i=this.defaultTransitionablePropertyValues[e]=new Ir(r);this.defaultTransitioningPropertyValues[e]=i.untransitioned(),this.defaultPossiblyEvaluatedValues[e]=n.possiblyEvaluate({});}};hr("DataDrivenProperty",qr),hr("DataConstantProperty",jr),hr("CrossFadedProperty",Rr),hr("ColorRampProperty",Ur);var Nr=function(t){function e(e,r){for(var n in t.call(this),this.id=e.id,this.metadata=e.metadata,this.type=e.type,this.minzoom=e.minzoom,this.maxzoom=e.maxzoom,this.visibility="visible","background"!==e.type&&(this.source=e.source,this.sourceLayer=e["source-layer"],this.filter=e.filter),this._featureFilter=function(){return!0},r.layout&&(this._unevaluatedLayout=new Tr(r.layout)),this._transitionablePaint=new Er(r.paint),e.paint)this.setPaintProperty(n,e.paint[n],{validate:!1});for(var i in e.layout)this.setLayoutProperty(i,e.layout[i],{validate:!1});this._transitioningPaint=this._transitionablePaint.untransitioned();}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getLayoutProperty=function(t){return"visibility"===t?this.visibility:this._unevaluatedLayout.getValue(t)},e.prototype.setLayoutProperty=function(t,e,r){if(null!=e){var n="layers."+this.id+".layout."+t;if(this._validate(or,n,t,e,r))return}"visibility"!==t?this._unevaluatedLayout.setValue(t,e):this.visibility="none"===e?e:"visible";},e.prototype.getPaintProperty=function(t){return d(t,"-transition")?this._transitionablePaint.getTransition(t.slice(0,-"-transition".length)):this._transitionablePaint.getValue(t)},e.prototype.setPaintProperty=function(t,e,r){if(null!=e){var n="layers."+this.id+".paint."+t;if(this._validate(ir,n,t,e,r))return}d(t,"-transition")?this._transitionablePaint.setTransition(t.slice(0,-"-transition".length),e||void 0):this._transitionablePaint.setValue(t,e);},e.prototype.isHidden=function(t){return!!(this.minzoom&&t=this.maxzoom)||"none"===this.visibility)},e.prototype.updateTransitions=function(t){this._transitioningPaint=this._transitionablePaint.transitioned(t,this._transitioningPaint);},e.prototype.hasTransition=function(){return this._transitioningPaint.hasTransition()},e.prototype.recalculate=function(t){this._unevaluatedLayout&&(this.layout=this._unevaluatedLayout.possiblyEvaluate(t)),this.paint=this._transitioningPaint.possiblyEvaluate(t);},e.prototype.serialize=function(){var t={id:this.id,type:this.type,source:this.source,"source-layer":this.sourceLayer,metadata:this.metadata,minzoom:this.minzoom,maxzoom:this.maxzoom,filter:this.filter,layout:this._unevaluatedLayout&&this._unevaluatedLayout.serialize(),paint:this._transitionablePaint&&this._transitionablePaint.serialize()};return"none"===this.visibility&&(t.layout=t.layout||{},t.layout.visibility="none"),m(t,function(t,e){return!(void 0===t||"layout"===e&&!Object.keys(t).length||"paint"===e&&!Object.keys(t).length)})},e.prototype._validate=function(t,e,r,n,i){return(!i||!1!==i.validate)&&ar(this,t.call(rr,{key:e,layerType:this.type,objectKey:r,value:n,styleSpec:E,style:{glyphs:!0,sprite:!0}}))},e.prototype.hasOffscreenPass=function(){return!1},e.prototype.resize=function(){},e}(I),Zr={Int8:Int8Array,Uint8:Uint8Array,Int16:Int16Array,Uint16:Uint16Array,Int32:Int32Array,Uint32:Uint32Array,Float32:Float32Array},Kr=function(t,e){this._structArray=t,this._pos1=e*this.size,this._pos2=this._pos1/2,this._pos4=this._pos1/4,this._pos8=this._pos1/8;},Jr=function(){this.isTransferred=!1,this.capacity=-1,this.resize(0);};function $r(t,e){void 0===e&&(e=1);var r=0,n=0;return{members:t.map(function(t){var i,o=(i=t.type,Zr[i].BYTES_PER_ELEMENT),a=r=Hr(r,Math.max(e,o)),s=t.components||1;return n=Math.max(n,o),r+=o*s,{name:t.name,type:t.type,components:s,offset:a}}),size:Hr(r,Math.max(n,e)),alignment:e}}function Hr(t,e){return Math.ceil(t/e)*e}Jr.serialize=function(t,e){return t._trim(),e&&(t.isTransferred=!0,e.push(t.arrayBuffer)),{length:t.length,arrayBuffer:t.arrayBuffer}},Jr.deserialize=function(t){var e=Object.create(this.prototype);return e.arrayBuffer=t.arrayBuffer,e.length=t.length,e.capacity=t.arrayBuffer.byteLength/e.bytesPerElement,e._refreshViews(),e},Jr.prototype._trim=function(){this.length!==this.capacity&&(this.capacity=this.length,this.arrayBuffer=this.arrayBuffer.slice(0,this.length*this.bytesPerElement),this._refreshViews());},Jr.prototype.clear=function(){this.length=0;},Jr.prototype.resize=function(t){this.reserve(t),this.length=t;},Jr.prototype.reserve=function(t){if(t>this.capacity){this.capacity=Math.max(t,Math.floor(5*this.capacity),128),this.arrayBuffer=new ArrayBuffer(this.capacity*this.bytesPerElement);var e=this.uint8;this._refreshViews(),e&&this.uint8.set(e);}},Jr.prototype._refreshViews=function(){throw new Error("_refreshViews() must be implemented by each concrete StructArray layout")};var Xr=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.int16[n+0]=t,this.int16[n+1]=e,r},e}(Jr);Xr.prototype.bytesPerElement=4,hr("StructArrayLayout2i4",Xr);var Gr=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;this.resize(i+1);var o=4*i;return this.int16[o+0]=t,this.int16[o+1]=e,this.int16[o+2]=r,this.int16[o+3]=n,i},e}(Jr);Gr.prototype.bytesPerElement=8,hr("StructArrayLayout4i8",Gr);var Yr=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o){var a=this.length;this.resize(a+1);var s=6*a;return this.int16[s+0]=t,this.int16[s+1]=e,this.int16[s+2]=r,this.int16[s+3]=n,this.int16[s+4]=i,this.int16[s+5]=o,a},e}(Jr);Yr.prototype.bytesPerElement=12,hr("StructArrayLayout2i4i12",Yr);var Wr=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o,a,s){var u=this.length;this.resize(u+1);var l=6*u,p=12*u;return this.int16[l+0]=t,this.int16[l+1]=e,this.int16[l+2]=r,this.int16[l+3]=n,this.uint8[p+8]=i,this.uint8[p+9]=o,this.uint8[p+10]=a,this.uint8[p+11]=s,u},e}(Jr);Wr.prototype.bytesPerElement=12,hr("StructArrayLayout4i4ub12",Wr);var Qr=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o,a,s){var u=this.length;this.resize(u+1);var l=8*u;return this.int16[l+0]=t,this.int16[l+1]=e,this.int16[l+2]=r,this.int16[l+3]=n,this.uint16[l+4]=i,this.uint16[l+5]=o,this.uint16[l+6]=a,this.uint16[l+7]=s,u},e}(Jr);Qr.prototype.bytesPerElement=16,hr("StructArrayLayout4i4ui16",Qr);var tn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.float32[i+0]=t,this.float32[i+1]=e,this.float32[i+2]=r,n},e}(Jr);tn.prototype.bytesPerElement=12,hr("StructArrayLayout3f12",tn);var en=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t){var e=this.length;this.resize(e+1);var r=1*e;return this.uint32[r+0]=t,e},e}(Jr);en.prototype.bytesPerElement=4,hr("StructArrayLayout1ul4",en);var rn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o,a,s,u,l,p){var c=this.length;this.resize(c+1);var h=12*c,f=6*c;return this.int16[h+0]=t,this.int16[h+1]=e,this.int16[h+2]=r,this.int16[h+3]=n,this.int16[h+4]=i,this.int16[h+5]=o,this.uint32[f+3]=a,this.uint16[h+8]=s,this.uint16[h+9]=u,this.int16[h+10]=l,this.int16[h+11]=p,c},e}(Jr);rn.prototype.bytesPerElement=24,hr("StructArrayLayout6i1ul2ui2i24",rn);var nn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o){var a=this.length;this.resize(a+1);var s=6*a;return this.int16[s+0]=t,this.int16[s+1]=e,this.int16[s+2]=r,this.int16[s+3]=n,this.int16[s+4]=i,this.int16[s+5]=o,a},e}(Jr);nn.prototype.bytesPerElement=12,hr("StructArrayLayout2i2i2i12",nn);var on=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=4*r;return this.uint8[n+0]=t,this.uint8[n+1]=e,r},e}(Jr);on.prototype.bytesPerElement=4,hr("StructArrayLayout2ub4",on);var an=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,o,a,s,u,l,p,c,h,f){var y=this.length;this.resize(y+1);var d=20*y,v=10*y,m=40*y;return this.int16[d+0]=t,this.int16[d+1]=e,this.uint16[d+2]=r,this.uint16[d+3]=n,this.uint32[v+2]=i,this.uint32[v+3]=o,this.uint32[v+4]=a,this.uint16[d+10]=s,this.uint16[d+11]=u,this.uint16[d+12]=l,this.float32[v+7]=p,this.float32[v+8]=c,this.uint8[m+36]=h,this.uint8[m+37]=f,y},e}(Jr);an.prototype.bytesPerElement=40,hr("StructArrayLayout2i2ui3ul3ui2f2ub40",an);var sn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t){var e=this.length;this.resize(e+1);var r=1*e;return this.float32[r+0]=t,e},e}(Jr);sn.prototype.bytesPerElement=4,hr("StructArrayLayout1f4",sn);var un=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.int16[i+0]=t,this.int16[i+1]=e,this.int16[i+2]=r,n},e}(Jr);un.prototype.bytesPerElement=6,hr("StructArrayLayout3i6",un);var ln=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=2*n,o=4*n;return this.uint32[i+0]=t,this.uint16[o+2]=e,this.uint16[o+3]=r,n},e}(Jr);ln.prototype.bytesPerElement=8,hr("StructArrayLayout1ul2ui8",ln);var pn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.uint16[i+0]=t,this.uint16[i+1]=e,this.uint16[i+2]=r,n},e}(Jr);pn.prototype.bytesPerElement=6,hr("StructArrayLayout3ui6",pn);var cn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.uint16[n+0]=t,this.uint16[n+1]=e,r},e}(Jr);cn.prototype.bytesPerElement=4,hr("StructArrayLayout2ui4",cn);var hn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.float32[n+0]=t,this.float32[n+1]=e,r},e}(Jr);hn.prototype.bytesPerElement=8,hr("StructArrayLayout2f8",hn);var fn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;this.resize(i+1);var o=4*i;return this.float32[o+0]=t,this.float32[o+1]=e,this.float32[o+2]=r,this.float32[o+3]=n,i},e}(Jr);fn.prototype.bytesPerElement=16,hr("StructArrayLayout4f16",fn);var yn=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorPointX:{configurable:!0},anchorPointY:{configurable:!0},x1:{configurable:!0},y1:{configurable:!0},x2:{configurable:!0},y2:{configurable:!0},featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0},radius:{configurable:!0},signedDistanceFromAnchor:{configurable:!0},anchorPoint:{configurable:!0}};return r.anchorPointX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorPointX.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.anchorPointY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorPointY.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.x1.get=function(){return this._structArray.int16[this._pos2+2]},r.x1.set=function(t){this._structArray.int16[this._pos2+2]=t;},r.y1.get=function(){return this._structArray.int16[this._pos2+3]},r.y1.set=function(t){this._structArray.int16[this._pos2+3]=t;},r.x2.get=function(){return this._structArray.int16[this._pos2+4]},r.x2.set=function(t){this._structArray.int16[this._pos2+4]=t;},r.y2.get=function(){return this._structArray.int16[this._pos2+5]},r.y2.set=function(t){this._structArray.int16[this._pos2+5]=t;},r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t;},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+8]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+8]=t;},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+9]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+9]=t;},r.radius.get=function(){return this._structArray.int16[this._pos2+10]},r.radius.set=function(t){this._structArray.int16[this._pos2+10]=t;},r.signedDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+11]},r.signedDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+11]=t;},r.anchorPoint.get=function(){return new s(this.anchorPointX,this.anchorPointY)},Object.defineProperties(e.prototype,r),e}(Kr);yn.prototype.size=24;var dn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new yn(this,t)},e}(rn);hr("CollisionBoxArray",dn);var vn=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorX:{configurable:!0},anchorY:{configurable:!0},glyphStartIndex:{configurable:!0},numGlyphs:{configurable:!0},vertexStartIndex:{configurable:!0},lineStartIndex:{configurable:!0},lineLength:{configurable:!0},segment:{configurable:!0},lowerSize:{configurable:!0},upperSize:{configurable:!0},lineOffsetX:{configurable:!0},lineOffsetY:{configurable:!0},writingMode:{configurable:!0},hidden:{configurable:!0}};return r.anchorX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorX.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.anchorY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorY.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.glyphStartIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.glyphStartIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t;},r.numGlyphs.get=function(){return this._structArray.uint16[this._pos2+3]},r.numGlyphs.set=function(t){this._structArray.uint16[this._pos2+3]=t;},r.vertexStartIndex.get=function(){return this._structArray.uint32[this._pos4+2]},r.vertexStartIndex.set=function(t){this._structArray.uint32[this._pos4+2]=t;},r.lineStartIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.lineStartIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t;},r.lineLength.get=function(){return this._structArray.uint32[this._pos4+4]},r.lineLength.set=function(t){this._structArray.uint32[this._pos4+4]=t;},r.segment.get=function(){return this._structArray.uint16[this._pos2+10]},r.segment.set=function(t){this._structArray.uint16[this._pos2+10]=t;},r.lowerSize.get=function(){return this._structArray.uint16[this._pos2+11]},r.lowerSize.set=function(t){this._structArray.uint16[this._pos2+11]=t;},r.upperSize.get=function(){return this._structArray.uint16[this._pos2+12]},r.upperSize.set=function(t){this._structArray.uint16[this._pos2+12]=t;},r.lineOffsetX.get=function(){return this._structArray.float32[this._pos4+7]},r.lineOffsetX.set=function(t){this._structArray.float32[this._pos4+7]=t;},r.lineOffsetY.get=function(){return this._structArray.float32[this._pos4+8]},r.lineOffsetY.set=function(t){this._structArray.float32[this._pos4+8]=t;},r.writingMode.get=function(){return this._structArray.uint8[this._pos1+36]},r.writingMode.set=function(t){this._structArray.uint8[this._pos1+36]=t;},r.hidden.get=function(){return this._structArray.uint8[this._pos1+37]},r.hidden.set=function(t){this._structArray.uint8[this._pos1+37]=t;},Object.defineProperties(e.prototype,r),e}(Kr);vn.prototype.size=40;var mn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new vn(this,t)},e}(an);hr("PlacedSymbolArray",mn);var gn=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={offsetX:{configurable:!0}};return r.offsetX.get=function(){return this._structArray.float32[this._pos4+0]},r.offsetX.set=function(t){this._structArray.float32[this._pos4+0]=t;},Object.defineProperties(e.prototype,r),e}(Kr);gn.prototype.size=4;var xn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getoffsetX=function(t){return this.float32[1*t+0]},e.prototype.get=function(t){return new gn(this,t)},e}(sn);hr("GlyphOffsetArray",xn);var bn=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={x:{configurable:!0},y:{configurable:!0},tileUnitDistanceFromAnchor:{configurable:!0}};return r.x.get=function(){return this._structArray.int16[this._pos2+0]},r.x.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.y.get=function(){return this._structArray.int16[this._pos2+1]},r.y.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.tileUnitDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+2]},r.tileUnitDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+2]=t;},Object.defineProperties(e.prototype,r),e}(Kr);bn.prototype.size=6;var wn=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getx=function(t){return this.int16[3*t+0]},e.prototype.gety=function(t){return this.int16[3*t+1]},e.prototype.gettileUnitDistanceFromAnchor=function(t){return this.int16[3*t+2]},e.prototype.get=function(t){return new bn(this,t)},e}(un);hr("SymbolLineVertexArray",wn);var _n=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0}};return r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+0]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+0]=t;},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t;},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+3]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+3]=t;},Object.defineProperties(e.prototype,r),e}(Kr);_n.prototype.size=8;var An=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new _n(this,t)},e}(ln);hr("FeatureIndexArray",An);var kn=$r([{name:"a_pos",components:2,type:"Int16"}],4).members,zn=function(t){void 0===t&&(t=[]),this.segments=t;};zn.prototype.prepareSegment=function(t,e,r){var n=this.segments[this.segments.length-1];return t>zn.MAX_VERTEX_ARRAY_LENGTH&&b("Max vertices per segment is "+zn.MAX_VERTEX_ARRAY_LENGTH+": bucket requested "+t),(!n||n.vertexLength+t>zn.MAX_VERTEX_ARRAY_LENGTH)&&(n={vertexOffset:e.length,primitiveOffset:r.length,vertexLength:0,primitiveLength:0},this.segments.push(n)),n},zn.prototype.get=function(){return this.segments},zn.prototype.destroy=function(){for(var t=0,e=this.segments;tOn.max||a.yOn.max)&&b("Geometry exceeds allowed extent, reduce your vector tile buffer size");}return r}function jn(t,e,r,n,i){t.emplaceBack(2*e+(n+1)/2,2*r+(i+1)/2);}var qn=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.layoutVertexArray=new Xr,this.indexArray=new pn,this.segments=new zn,this.programConfigurations=new En(kn,t.layers,t.zoom);};function Rn(t,e,r){for(var n=0;n=3)for(var s=0;s1){if(Zn(t,e))return!0;for(var n=0;n1?t.distSqr(r):t.distSqr(r.sub(e)._mult(i)._add(e))}function Hn(t,e){for(var r,n,i,o=!1,a=0;ae.y!=i.y>e.y&&e.x<(i.x-n.x)*(e.y-n.y)/(i.y-n.y)+n.x&&(o=!o);return o}function Xn(t,e){for(var r=!1,n=0,i=t.length-1;ne.y!=a.y>e.y&&e.x<(a.x-o.x)*(e.y-o.y)/(a.y-o.y)+o.x&&(r=!r);}return r}function Gn(t,e,r){var n=e.paint.get(t).value;return"constant"===n.kind?n.value:r.programConfigurations.get(e.id).binders[t].statistics.max}function Yn(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])}function Wn(t,e,r,n,i){if(!e[0]&&!e[1])return t;var o=s.convert(e);"viewport"===r&&o._rotate(-n);for(var a=[],u=0;u=Pn||u<0||u>=Pn)){var l=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray),p=l.vertexLength;jn(this.layoutVertexArray,s,u,-1,-1),jn(this.layoutVertexArray,s,u,1,-1),jn(this.layoutVertexArray,s,u,1,1),jn(this.layoutVertexArray,s,u,-1,1),this.indexArray.emplaceBack(p,p+1,p+2),this.indexArray.emplaceBack(p,p+3,p+2),l.vertexLength+=4,l.primitiveLength+=2;}}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,t);},hr("CircleBucket",qn,{omit:["layers"]});var Qn={paint:new Dr({"circle-radius":new qr(E.paint_circle["circle-radius"]),"circle-color":new qr(E.paint_circle["circle-color"]),"circle-blur":new qr(E.paint_circle["circle-blur"]),"circle-opacity":new qr(E.paint_circle["circle-opacity"]),"circle-translate":new jr(E.paint_circle["circle-translate"]),"circle-translate-anchor":new jr(E.paint_circle["circle-translate-anchor"]),"circle-pitch-scale":new jr(E.paint_circle["circle-pitch-scale"]),"circle-pitch-alignment":new jr(E.paint_circle["circle-pitch-alignment"]),"circle-stroke-width":new qr(E.paint_circle["circle-stroke-width"]),"circle-stroke-color":new qr(E.paint_circle["circle-stroke-color"]),"circle-stroke-opacity":new qr(E.paint_circle["circle-stroke-opacity"])})},ti=n(function(t,e){var r;t.exports=((r=new Float32Array(3))[0]=0,r[1]=0,r[2]=0,function(){var t=new Float32Array(4);t[0]=0,t[1]=0,t[2]=0,t[3]=0;}(),{vec3:{transformMat3:function(t,e,r){var n=e[0],i=e[1],o=e[2];return t[0]=n*r[0]+i*r[3]+o*r[6],t[1]=n*r[1]+i*r[4]+o*r[7],t[2]=n*r[2]+i*r[5]+o*r[8],t}},vec4:{transformMat4:function(t,e,r){var n=e[0],i=e[1],o=e[2],a=e[3];return t[0]=r[0]*n+r[4]*i+r[8]*o+r[12]*a,t[1]=r[1]*n+r[5]*i+r[9]*o+r[13]*a,t[2]=r[2]*n+r[6]*i+r[10]*o+r[14]*a,t[3]=r[3]*n+r[7]*i+r[11]*o+r[15]*a,t}},mat2:{create:function(){var t=new Float32Array(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},rotate:function(t,e,r){var n=e[0],i=e[1],o=e[2],a=e[3],s=Math.sin(r),u=Math.cos(r);return t[0]=n*u+o*s,t[1]=i*u+a*s,t[2]=n*-s+o*u,t[3]=i*-s+a*u,t},scale:function(t,e,r){var n=e[0],i=e[1],o=e[2],a=e[3],s=r[0],u=r[1];return t[0]=n*s,t[1]=i*s,t[2]=o*u,t[3]=a*u,t}},mat3:{create:function(){var t=new Float32Array(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromRotation:function(t,e){var r=Math.sin(e),n=Math.cos(e);return t[0]=n,t[1]=r,t[2]=0,t[3]=-r,t[4]=n,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}},mat4:{create:function(){var t=new Float32Array(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},translate:function(t,e,r){var n,i,o,a,s,u,l,p,c,h,f,y,d=r[0],v=r[1],m=r[2];return e===t?(t[12]=e[0]*d+e[4]*v+e[8]*m+e[12],t[13]=e[1]*d+e[5]*v+e[9]*m+e[13],t[14]=e[2]*d+e[6]*v+e[10]*m+e[14],t[15]=e[3]*d+e[7]*v+e[11]*m+e[15]):(n=e[0],i=e[1],o=e[2],a=e[3],s=e[4],u=e[5],l=e[6],p=e[7],c=e[8],h=e[9],f=e[10],y=e[11],t[0]=n,t[1]=i,t[2]=o,t[3]=a,t[4]=s,t[5]=u,t[6]=l,t[7]=p,t[8]=c,t[9]=h,t[10]=f,t[11]=y,t[12]=n*d+s*v+c*m+e[12],t[13]=i*d+u*v+h*m+e[13],t[14]=o*d+l*v+f*m+e[14],t[15]=a*d+p*v+y*m+e[15]),t},scale:function(t,e,r){var n=r[0],i=r[1],o=r[2];return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t[3]=e[3]*n,t[4]=e[4]*i,t[5]=e[5]*i,t[6]=e[6]*i,t[7]=e[7]*i,t[8]=e[8]*o,t[9]=e[9]*o,t[10]=e[10]*o,t[11]=e[11]*o,t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t},multiply:function(t,e,r){var n=e[0],i=e[1],o=e[2],a=e[3],s=e[4],u=e[5],l=e[6],p=e[7],c=e[8],h=e[9],f=e[10],y=e[11],d=e[12],v=e[13],m=e[14],g=e[15],x=r[0],b=r[1],w=r[2],_=r[3];return t[0]=x*n+b*s+w*c+_*d,t[1]=x*i+b*u+w*h+_*v,t[2]=x*o+b*l+w*f+_*m,t[3]=x*a+b*p+w*y+_*g,x=r[4],b=r[5],w=r[6],_=r[7],t[4]=x*n+b*s+w*c+_*d,t[5]=x*i+b*u+w*h+_*v,t[6]=x*o+b*l+w*f+_*m,t[7]=x*a+b*p+w*y+_*g,x=r[8],b=r[9],w=r[10],_=r[11],t[8]=x*n+b*s+w*c+_*d,t[9]=x*i+b*u+w*h+_*v,t[10]=x*o+b*l+w*f+_*m,t[11]=x*a+b*p+w*y+_*g,x=r[12],b=r[13],w=r[14],_=r[15],t[12]=x*n+b*s+w*c+_*d,t[13]=x*i+b*u+w*h+_*v,t[14]=x*o+b*l+w*f+_*m,t[15]=x*a+b*p+w*y+_*g,t},perspective:function(t,e,r,n,i){var o=1/Math.tan(e/2),a=1/(n-i);return t[0]=o/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(i+n)*a,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*i*n*a,t[15]=0,t},rotateX:function(t,e,r){var n=Math.sin(r),i=Math.cos(r),o=e[4],a=e[5],s=e[6],u=e[7],l=e[8],p=e[9],c=e[10],h=e[11];return e!==t&&(t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[4]=o*i+l*n,t[5]=a*i+p*n,t[6]=s*i+c*n,t[7]=u*i+h*n,t[8]=l*i-o*n,t[9]=p*i-a*n,t[10]=c*i-s*n,t[11]=h*i-u*n,t},rotateZ:function(t,e,r){var n=Math.sin(r),i=Math.cos(r),o=e[0],a=e[1],s=e[2],u=e[3],l=e[4],p=e[5],c=e[6],h=e[7];return e!==t&&(t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[0]=o*i+l*n,t[1]=a*i+p*n,t[2]=s*i+c*n,t[3]=u*i+h*n,t[4]=l*i-o*n,t[5]=p*i-a*n,t[6]=c*i-s*n,t[7]=h*i-u*n,t},invert:function(t,e){var r=e[0],n=e[1],i=e[2],o=e[3],a=e[4],s=e[5],u=e[6],l=e[7],p=e[8],c=e[9],h=e[10],f=e[11],y=e[12],d=e[13],v=e[14],m=e[15],g=r*s-n*a,x=r*u-i*a,b=r*l-o*a,w=n*u-i*s,_=n*l-o*s,A=i*l-o*u,k=p*d-c*y,z=p*v-h*y,S=p*m-f*y,M=c*v-h*d,V=c*m-f*d,B=h*m-f*v,C=g*B-x*V+b*M+w*S-_*z+A*k;return C?(C=1/C,t[0]=(s*B-u*V+l*M)*C,t[1]=(i*V-n*B-o*M)*C,t[2]=(d*A-v*_+m*w)*C,t[3]=(h*_-c*A-f*w)*C,t[4]=(u*S-a*B-l*z)*C,t[5]=(r*B-i*S+o*z)*C,t[6]=(v*b-y*A-m*x)*C,t[7]=(p*A-h*b+f*x)*C,t[8]=(a*V-s*S+l*k)*C,t[9]=(n*S-r*V-o*k)*C,t[10]=(y*_-d*b+m*g)*C,t[11]=(c*b-p*_-f*g)*C,t[12]=(s*z-a*M-u*k)*C,t[13]=(r*M-n*z+i*k)*C,t[14]=(d*x-y*w-v*g)*C,t[15]=(p*w-c*x+h*g)*C,t):null},ortho:function(t,e,r,n,i,o,a){var s=1/(e-r),u=1/(n-i),l=1/(o-a);return t[0]=-2*s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*l,t[11]=0,t[12]=(e+r)*s,t[13]=(i+n)*u,t[14]=(a+o)*l,t[15]=1,t}}});}),ei=(ti.vec3,ti.vec4),ri=(ti.mat2,ti.mat3,ti.mat4),ni=function(t){function e(e){t.call(this,e,Qn);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.createBucket=function(t){return new qn(t)},e.prototype.queryRadius=function(t){var e=t;return Gn("circle-radius",this,e)+Gn("circle-stroke-width",this,e)+Yn(this.paint.get("circle-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,i,o,a){for(var s=Wn(t,this.paint.get("circle-translate"),this.paint.get("circle-translate-anchor"),i.angle,o),u=this.paint.get("circle-radius").evaluate(e)+this.paint.get("circle-stroke-width").evaluate(e),l="map"===this.paint.get("circle-pitch-alignment"),p=l?s:function(t,e,r){return t.map(function(t){return t.map(function(t){return ii(t,e,r)})})}(s,a,i),c=l?u*o:u,h=0,f=r;ht.width||i.height>t.height||r.x>t.width-i.width||r.y>t.height-i.height)throw new RangeError("out of range source coordinates for image copy");if(i.width>e.width||i.height>e.height||n.x>e.width-i.width||n.y>e.height-i.height)throw new RangeError("out of range destination coordinates for image copy");for(var a=t.data,s=e.data,u=0;u80*r){n=o=t[0],i=a=t[1];for(var y=r;yo&&(o=s),u>a&&(a=u);l=0!==(l=Math.max(o-n,a-i))?1/l:0;}return _i(h,f,r,n,i,l),f}function bi(t,e,r,n,i){var o,a;if(i===Ui(t,e,r,n)>0)for(o=e;o=e;o-=n)a=ji(o,t[o],t[o+1],a);return a&&Pi(a,a.next)&&(qi(a),a=a.next),a}function wi(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!Pi(n,n.next)&&0!==Fi(n.prev,n,n.next))n=n.next;else{if(qi(n),(n=e=n.prev)===n.next)break;r=!0;}}while(r||n!==e);return e}function _i(t,e,r,n,i,o,a){if(t){!a&&o&&function(t,e,r,n){var i=t;do{null===i.z&&(i.z=Bi(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,function(t){var e,r,n,i,o,a,s,u,l=1;do{for(r=t,t=null,o=null,a=0;r;){for(a++,n=r,s=0,e=0;e0||u>0&&n;)0!==s&&(0===u||!n||r.z<=n.z)?(i=r,r=r.nextZ,s--):(i=n,n=n.nextZ,u--),o?o.nextZ=i:t=i,i.prevZ=o,o=i;r=n;}o.nextZ=null,l*=2;}while(a>1)}(i);}(t,n,i,o);for(var s,u,l=t;t.prev!==t.next;)if(s=t.prev,u=t.next,o?ki(t,n,i,o):Ai(t))e.push(s.i/r),e.push(t.i/r),e.push(u.i/r),qi(t),t=u.next,l=u.next;else if((t=u)===l){a?1===a?_i(t=zi(t,e,r),e,r,n,i,o,2):2===a&&Si(t,e,r,n,i,o):_i(wi(t),e,r,n,i,o,1);break}}}function Ai(t){var e=t.prev,r=t,n=t.next;if(Fi(e,r,n)>=0)return!1;for(var i=t.next.next;i!==t.prev;){if(Ii(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&Fi(i.prev,i,i.next)>=0)return!1;i=i.next;}return!0}function ki(t,e,r,n){var i=t.prev,o=t,a=t.next;if(Fi(i,o,a)>=0)return!1;for(var s=i.xo.x?i.x>a.x?i.x:a.x:o.x>a.x?o.x:a.x,p=i.y>o.y?i.y>a.y?i.y:a.y:o.y>a.y?o.y:a.y,c=Bi(s,u,e,r,n),h=Bi(l,p,e,r,n),f=t.prevZ,y=t.nextZ;f&&f.z>=c&&y&&y.z<=h;){if(f!==t.prev&&f!==t.next&&Ii(i.x,i.y,o.x,o.y,a.x,a.y,f.x,f.y)&&Fi(f.prev,f,f.next)>=0)return!1;if(f=f.prevZ,y!==t.prev&&y!==t.next&&Ii(i.x,i.y,o.x,o.y,a.x,a.y,y.x,y.y)&&Fi(y.prev,y,y.next)>=0)return!1;y=y.nextZ;}for(;f&&f.z>=c;){if(f!==t.prev&&f!==t.next&&Ii(i.x,i.y,o.x,o.y,a.x,a.y,f.x,f.y)&&Fi(f.prev,f,f.next)>=0)return!1;f=f.prevZ;}for(;y&&y.z<=h;){if(y!==t.prev&&y!==t.next&&Ii(i.x,i.y,o.x,o.y,a.x,a.y,y.x,y.y)&&Fi(y.prev,y,y.next)>=0)return!1;y=y.nextZ;}return!0}function zi(t,e,r){var n=t;do{var i=n.prev,o=n.next.next;!Pi(i,o)&&Ti(i,n,n.next,o)&&Oi(i,o)&&Oi(o,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(o.i/r),qi(n),qi(n.next),n=t=o),n=n.next;}while(n!==t);return n}function Si(t,e,r,n,i,o){var a=t;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&Ei(a,s)){var u=Li(a,s);return a=wi(a,a.next),u=wi(u,u.next),_i(a,e,r,n,i,o),void _i(u,e,r,n,i,o)}s=s.next;}a=a.next;}while(a!==t)}function Mi(t,e){return t.x-e.x}function Vi(t,e){if(e=function(t,e){var r,n=e,i=t.x,o=t.y,a=-1/0;do{if(o<=n.y&&o>=n.next.y&&n.next.y!==n.y){var s=n.x+(o-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(s<=i&&s>a){if(a=s,s===i){if(o===n.y)return n;if(o===n.next.y)return n.next}r=n.x=n.x&&n.x>=p&&i!==n.x&&Ii(or.x)&&Oi(n,t)&&(r=n,h=u),n=n.next;return r}(t,e)){var r=Li(e,t);wi(r,r.next);}}function Bi(t,e,r,n,i){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*i)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*i)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Ci(t){var e=t,r=t;do{e.x=0&&(t-a)*(n-s)-(r-a)*(e-s)>=0&&(r-a)*(o-s)-(i-a)*(n-s)>=0}function Ei(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&Ti(r,r.next,t,e))return!0;r=r.next;}while(r!==t);return!1}(t,e)&&Oi(t,e)&&Oi(e,t)&&function(t,e){var r=t,n=!1,i=(t.x+e.x)/2,o=(t.y+e.y)/2;do{r.y>o!=r.next.y>o&&r.next.y!==r.y&&i<(r.next.x-r.x)*(o-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next;}while(r!==t);return n}(t,e)}function Fi(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function Pi(t,e){return t.x===e.x&&t.y===e.y}function Ti(t,e,r,n){return!!(Pi(t,e)&&Pi(r,n)||Pi(t,n)&&Pi(r,e))||Fi(t,e,r)>0!=Fi(t,e,n)>0&&Fi(r,n,t)>0!=Fi(r,n,e)>0}function Oi(t,e){return Fi(t.prev,t,t.next)<0?Fi(t,e,t.next)>=0&&Fi(t,t.prev,e)>=0:Fi(t,e,t.prev)<0||Fi(t,t.next,e)<0}function Li(t,e){var r=new Ri(t.i,t.x,t.y),n=new Ri(e.i,e.x,e.y),i=t.next,o=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,o.next=n,n.prev=o,n}function ji(t,e,r,n){var i=new Ri(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function qi(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ);}function Ri(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1;}function Ui(t,e,r,n){for(var i=0,o=e,a=r-n;o0&&(n+=t[i-1].length,r.holes.push(n));}return r},mi.default=gi;var Di=Zi,Ni=Zi;function Zi(t,e,r,n,i){!function t(e,r,n,i,o){for(;i>n;){if(i-n>600){var a=i-n+1,s=r-n+1,u=Math.log(a),l=.5*Math.exp(2*u/3),p=.5*Math.sqrt(u*l*(a-l)/a)*(s-a/2<0?-1:1),c=Math.max(n,Math.floor(r-s*l/a+p)),h=Math.min(i,Math.floor(r+(a-s)*l/a+p));t(e,r,c,h,o);}var f=e[r],y=n,d=i;for(Ki(e,n,r),o(e[i],f)>0&&Ki(e,n,i);y0;)d--;}0===o(e[n],f)?Ki(e,n,d):Ki(e,++d,i),d<=r&&(n=d+1),r<=d&&(i=d-1);}}(t,e,r||0,n||t.length-1,i||Ji);}function Ki(t,e,r){var n=t[e];t[e]=t[r],t[r]=n;}function Ji(t,e){return te?1:0}function $i(t,e){var r=t.length;if(r<=1)return[t];for(var n,i,o=[],a=0;a1)for(var u=0;uPn)||t.y===e.y&&(t.y<0||t.y>Pn)}function no(t){return t.every(function(t){return t.x<0})||t.every(function(t){return t.x>Pn})||t.every(function(t){return t.y<0})||t.every(function(t){return t.y>Pn})}eo.prototype.populate=function(t,e){for(var r=0,n=t;r=1){var d=c[f-1];if(!ro(y,d)){u.vertexLength+4>zn.MAX_VERTEX_ARRAY_LENGTH&&(u=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray));var v=y.sub(d)._perp()._unit(),m=d.dist(y);h+m>32768&&(h=0),to(this.layoutVertexArray,y.x,y.y,v.x,v.y,0,0,h),to(this.layoutVertexArray,y.x,y.y,v.x,v.y,0,1,h),h+=m,to(this.layoutVertexArray,d.x,d.y,v.x,v.y,0,0,h),to(this.layoutVertexArray,d.x,d.y,v.x,v.y,0,1,h);var g=u.vertexLength;this.indexArray.emplaceBack(g,g+1,g+2),this.indexArray.emplaceBack(g+1,g+2,g+3),u.vertexLength+=4,u.primitiveLength+=2;}}}}u.vertexLength+o>zn.MAX_VERTEX_ARRAY_LENGTH&&(u=this.segments.prepareSegment(o,this.layoutVertexArray,this.indexArray));for(var x=[],b=[],w=u.vertexLength,_=0,A=i;_>3;}if(i--,1===n||2===n)o+=t.readSVarint(),a+=t.readSVarint(),1===n&&(e&&u.push(e),e=[]),e.push(new s(o,a));else{if(7!==n)throw new Error("unknown command "+n);e&&e.push(e[0].clone());}}return e&&u.push(e),u},uo.prototype.bbox=function(){var t=this._pbf;t.pos=this._geometry;for(var e=t.readVarint()+t.pos,r=1,n=0,i=0,o=0,a=1/0,s=-1/0,u=1/0,l=-1/0;t.pos>3;}if(n--,1===r||2===r)(i+=t.readSVarint())s&&(s=i),(o+=t.readSVarint())l&&(l=o);else if(7!==r)throw new Error("unknown command "+r)}return[a,u,s,l]},uo.prototype.toGeoJSON=function(t,e,r){var n,i,o=this.extent*Math.pow(2,r),a=this.extent*t,s=this.extent*e,u=this.loadGeometry(),l=uo.types[this.type];function p(t){for(var e=0;e>3;e=1===n?t.readString():2===n?t.readFloat():3===n?t.readDouble():4===n?t.readVarint64():5===n?t.readVarint():6===n?t.readSVarint():7===n?t.readBoolean():null;}return e}(r));}function yo(t,e,r){if(3===t){var n=new co(r,r.readVarint()+r.pos);n.length&&(e[n.name]=n);}}ho.prototype.feature=function(t){if(t<0||t>=this._features.length)throw new Error("feature index out of bounds");this._pbf.pos=this._features[t];var e=this._pbf.readVarint()+this._pbf.pos;return new so(this._pbf,e,this.extent,this._keys,this._values)};var vo={VectorTile:function(t,e){this.layers=t.readFields(yo,{},e);},VectorTileFeature:so,VectorTileLayer:co},mo=vo.VectorTileFeature.types,go=63,xo=Math.cos(Math.PI/180*37.5),bo=.5,wo=Math.pow(2,14)/bo;function _o(t,e,r,n,i,o,a){t.emplaceBack(e.x,e.y,n?1:0,i?1:-1,Math.round(go*r.x)+128,Math.round(go*r.y)+128,1+(0===o?0:o<0?-1:1)|(a*bo&63)<<2,a*bo>>6);}var Ao=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.layoutVertexArray=new Wr,this.indexArray=new pn,this.programConfigurations=new En(ao,t.layers,t.zoom),this.segments=new zn;};function ko(t,e){return(t/e.tileTotal*(e.end-e.start)+e.start)*(wo-1)}Ao.prototype.populate=function(t,e){for(var r=0,n=t;r=2&&t[u-1].equals(t[u-2]);)u--;for(var l=0;ll){var V=f.dist(x);if(V>2*p){var B=f.sub(f.sub(x)._mult(p/V)._round());this.distance+=B.dist(x),this.addCurrentVertex(B,this.distance,w.mult(1),0,0,!1,h,a),x=B;}}var C=x&&b,I=C?r:b?v:m;if(C&&"round"===I&&(Si&&(I="bevel"),"bevel"===I&&(S>2&&(I="flipbevel"),S100)k=_.clone().mult(-1);else{var E=w.x*_.y-w.y*_.x>0?-1:1,F=S*w.add(_).mag()/w.sub(_).mag();k._perp()._mult(F*E);}this.addCurrentVertex(f,this.distance,k,0,0,!1,h,a),this.addCurrentVertex(f,this.distance,k.mult(-1),0,0,!1,h,a);}else if("bevel"===I||"fakeround"===I){var P=w.x*_.y-w.y*_.x>0,T=-Math.sqrt(S*S-1);if(P?(d=0,y=T):(y=0,d=T),g||this.addCurrentVertex(f,this.distance,w,y,d,!1,h,a),"fakeround"===I){for(var O=Math.floor(8*(.5-(z-.5))),L=void 0,j=0;j=0;q--)L=w.mult((q+1)/(O+1))._add(_)._unit(),this.addPieSliceVertex(f,this.distance,L,P,h,a);}b&&this.addCurrentVertex(f,this.distance,_,-y,-d,!1,h,a);}else"butt"===I?(g||this.addCurrentVertex(f,this.distance,w,0,0,!1,h,a),b&&this.addCurrentVertex(f,this.distance,_,0,0,!1,h,a)):"square"===I?(g||(this.addCurrentVertex(f,this.distance,w,1,1,!1,h,a),this.e1=this.e2=-1),b&&this.addCurrentVertex(f,this.distance,_,-1,-1,!1,h,a)):"round"===I&&(g||(this.addCurrentVertex(f,this.distance,w,0,0,!1,h,a),this.addCurrentVertex(f,this.distance,w,1,1,!0,h,a),this.e1=this.e2=-1),b&&(this.addCurrentVertex(f,this.distance,_,-1,-1,!0,h,a),this.addCurrentVertex(f,this.distance,_,0,0,!1,h,a)));if(M&&A2*p){var U=f.add(b.sub(f)._mult(p/R)._round());this.distance+=U.dist(f),this.addCurrentVertex(U,this.distance,_.mult(1),0,0,!1,h,a),f=U;}}g=!1;}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,e);}},Ao.prototype.addCurrentVertex=function(t,e,r,n,i,o,a,s){var u,l=this.layoutVertexArray,p=this.indexArray;s&&(e=ko(e,s)),u=r.clone(),n&&u._sub(r.perp()._mult(n)),_o(l,t,u,o,!1,n,e),this.e3=a.vertexLength++,this.e1>=0&&this.e2>=0&&(p.emplaceBack(this.e1,this.e2,this.e3),a.primitiveLength++),this.e1=this.e2,this.e2=this.e3,u=r.mult(-1),i&&u._sub(r.perp()._mult(i)),_o(l,t,u,o,!0,-i,e),this.e3=a.vertexLength++,this.e1>=0&&this.e2>=0&&(p.emplaceBack(this.e1,this.e2,this.e3),a.primitiveLength++),this.e1=this.e2,this.e2=this.e3,e>wo/2&&!s&&(this.distance=0,this.addCurrentVertex(t,this.distance,r,n,i,o,a));},Ao.prototype.addPieSliceVertex=function(t,e,r,n,i,o){r=r.mult(n?-1:1);var a=this.layoutVertexArray,s=this.indexArray;o&&(e=ko(e,o)),_o(a,t,r,!1,n,0,e),this.e3=i.vertexLength++,this.e1>=0&&this.e2>=0&&(s.emplaceBack(this.e1,this.e2,this.e3),i.primitiveLength++),n?this.e2=this.e3:this.e1=this.e3;},hr("LineBucket",Ao,{omit:["layers"]});var zo=new Dr({"line-cap":new jr(E.layout_line["line-cap"]),"line-join":new qr(E.layout_line["line-join"]),"line-miter-limit":new jr(E.layout_line["line-miter-limit"]),"line-round-limit":new jr(E.layout_line["line-round-limit"])}),So={paint:new Dr({"line-opacity":new qr(E.paint_line["line-opacity"]),"line-color":new qr(E.paint_line["line-color"]),"line-translate":new jr(E.paint_line["line-translate"]),"line-translate-anchor":new jr(E.paint_line["line-translate-anchor"]),"line-width":new qr(E.paint_line["line-width"]),"line-gap-width":new qr(E.paint_line["line-gap-width"]),"line-offset":new qr(E.paint_line["line-offset"]),"line-blur":new qr(E.paint_line["line-blur"]),"line-dasharray":new Rr(E.paint_line["line-dasharray"]),"line-pattern":new Rr(E.paint_line["line-pattern"]),"line-gradient":new Ur(E.paint_line["line-gradient"])}),layout:zo},Mo=new(function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.possiblyEvaluate=function(e,r){return r=new Br(Math.floor(r.zoom),{now:r.now,fadeDuration:r.fadeDuration,zoomHistory:r.zoomHistory,transition:r.transition}),t.prototype.possiblyEvaluate.call(this,e,r)},e.prototype.evaluate=function(e,r,n){return r=h({},r,{zoom:Math.floor(r.zoom)}),t.prototype.evaluate.call(this,e,r,n)},e}(qr))(So.paint.properties["line-width"].specification);Mo.useIntegerZoom=!0;var Vo=function(t){function e(e){t.call(this,e,So);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setPaintProperty=function(e,r,n){t.prototype.setPaintProperty.call(this,e,r,n),"line-gradient"===e&&this._updateGradient();},e.prototype._updateGradient=function(){var t=this._transitionablePaint._values["line-gradient"].value.expression;this.gradient=hi(t,"lineProgress"),this.gradientTexture=null;},e.prototype.recalculate=function(e){t.prototype.recalculate.call(this,e),this.paint._values["line-floorwidth"]=Mo.possiblyEvaluate(this._transitioningPaint._values["line-width"].value,e);},e.prototype.createBucket=function(t){return new Ao(t)},e.prototype.queryRadius=function(t){var e=t,r=Bo(Gn("line-width",this,e),Gn("line-gap-width",this,e)),n=Gn("line-offset",this,e);return r/2+Math.abs(n)+Yn(this.paint.get("line-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,i,o){var a=Wn(t,this.paint.get("line-translate"),this.paint.get("line-translate-anchor"),i.angle,o),u=o/2*Bo(this.paint.get("line-width").evaluate(e),this.paint.get("line-gap-width").evaluate(e)),l=this.paint.get("line-offset").evaluate(e);return l&&(r=function(t,e){for(var r=[],n=new s(0,0),i=0;i0?e+2*t:t}var Co=$r([{name:"a_pos_offset",components:4,type:"Int16"},{name:"a_data",components:4,type:"Uint16"}]),Io=$r([{name:"a_projected_pos",components:3,type:"Float32"}],4),Eo=($r([{name:"a_fade_opacity",components:1,type:"Uint32"}],4),$r([{name:"a_placed",components:2,type:"Uint8"}],4)),Fo=($r([{type:"Int16",name:"anchorPointX"},{type:"Int16",name:"anchorPointY"},{type:"Int16",name:"x1"},{type:"Int16",name:"y1"},{type:"Int16",name:"x2"},{type:"Int16",name:"y2"},{type:"Uint32",name:"featureIndex"},{type:"Uint16",name:"sourceLayerIndex"},{type:"Uint16",name:"bucketIndex"},{type:"Int16",name:"radius"},{type:"Int16",name:"signedDistanceFromAnchor"}]),$r([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4)),Po=$r([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4);$r([{type:"Int16",name:"anchorX"},{type:"Int16",name:"anchorY"},{type:"Uint16",name:"glyphStartIndex"},{type:"Uint16",name:"numGlyphs"},{type:"Uint32",name:"vertexStartIndex"},{type:"Uint32",name:"lineStartIndex"},{type:"Uint32",name:"lineLength"},{type:"Uint16",name:"segment"},{type:"Uint16",name:"lowerSize"},{type:"Uint16",name:"upperSize"},{type:"Float32",name:"lineOffsetX"},{type:"Float32",name:"lineOffsetY"},{type:"Uint8",name:"writingMode"},{type:"Uint8",name:"hidden"}]),$r([{type:"Float32",name:"offsetX"}]),$r([{type:"Int16",name:"x"},{type:"Int16",name:"y"},{type:"Int16",name:"tileUnitDistanceFromAnchor"}]);function To(t,e,r){var n=e.layout.get("text-transform").evaluate(r);return"uppercase"===n?t=t.toLocaleUpperCase():"lowercase"===n&&(t=t.toLocaleLowerCase()),Vr.applyArabicShaping&&(t=Vr.applyArabicShaping(t)),t}var Oo={"!":"︕","#":"#",$:"$","%":"%","&":"&","(":"︵",")":"︶","*":"*","+":"+",",":"︐","-":"︲",".":"・","/":"/",":":"︓",";":"︔","<":"︿","=":"=",">":"﹀","?":"︖","@":"@","[":"﹇","\\":"\","]":"﹈","^":"^",_:"︳","`":"`","{":"︷","|":"―","}":"︸","~":"~","¢":"¢","£":"£","¥":"¥","¦":"¦","¬":"¬","¯":" ̄","–":"︲","—":"︱","‘":"﹃","’":"﹄","“":"﹁","”":"﹂","…":"︙","‧":"・","₩":"₩","、":"︑","。":"︒","〈":"︿","〉":"﹀","《":"︽","》":"︾","「":"﹁","」":"﹂","『":"﹃","』":"﹄","【":"︻","】":"︼","〔":"︹","〕":"︺","〖":"︗","〗":"︘","!":"︕","(":"︵",")":"︶",",":"︐","-":"︲",".":"・",":":"︓",";":"︔","<":"︿",">":"﹀","?":"︖","[":"﹇","]":"﹈","_":"︳","{":"︷","|":"―","}":"︸","⦅":"︵","⦆":"︶","。":"︒","「":"﹁","」":"﹂"};var Lo=function(t){function e(e,r,n,i){t.call(this,e,r),this.angle=n,void 0!==i&&(this.segment=i);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.clone=function(){return new e(this.x,this.y,this.angle,this.segment)},e}(s);function jo(t,e){var r=e.expression;if("constant"===r.kind)return{functionType:"constant",layoutSize:r.evaluate(new Br(t+1))};if("source"===r.kind)return{functionType:"source"};for(var n=r.zoomStops,i=0;i0)&&("constant"!==i.value.kind||i.value.value.length>0),u="constant"!==a.value.kind||a.value.value&&a.value.value.length>0;if(this.features=[],s||u){for(var l=e.iconDependencies,p=e.glyphDependencies,c=new Br(this.zoom),h=0,f=t;h=0;s--)o[s]={x:e[s].x,y:e[s].y,tileUnitDistanceFromAnchor:i},s>0&&(i+=e[s-1].dist(e[s]));for(var u=0;u0;this.addCollisionDebugVertices(s,u,l,p,c?this.collisionCircle:this.collisionBox,a.anchorPoint,r,c);}}}},Ko.prototype.deserializeCollisionBoxes=function(t,e,r,n,i){for(var o={},a=e;a0},Ko.prototype.hasIconData=function(){return this.icon.segments.get().length>0},Ko.prototype.hasCollisionBoxData=function(){return this.collisionBox.segments.get().length>0},Ko.prototype.hasCollisionCircleData=function(){return this.collisionCircle.segments.get().length>0},Ko.prototype.sortFeatures=function(t){var e=this;if(this.sortFeaturesByY&&this.sortedAngle!==t&&(this.sortedAngle=t,!(this.text.segments.get().length>1||this.icon.segments.get().length>1))){for(var r=[],n=0;ni.maxh||t>i.maxw||r<=i.maxh&&t<=i.maxw&&(a=i.maxw*i.maxh-t*r)o.free)){if(r===o.h)return this.allocShelf(s,t,r,n);r>o.h||rp)&&(c=2*Math.max(t,p)),(uu)&&(l=2*Math.max(r,u)),this.resize(c,l),this.packOne(t,r,n)):null},t.prototype.allocFreebin=function(t,e,r,n){var i=this.freebins.splice(t,1)[0];return i.id=n,i.w=e,i.h=r,i.refcount=0,this.bins[n]=i,this.ref(i),i},t.prototype.allocShelf=function(t,e,r,n){var i=this.shelves[t].alloc(e,r,n);return this.bins[n]=i,this.ref(i),i},t.prototype.shrink=function(){if(this.shelves.length>0){for(var t=0,e=0,r=0;rthis.free||e>this.h)return null;var n=this.x;return this.x+=t,this.free-=t,new function(t,e,r,n,i,o,a){this.id=t,this.x=e,this.y=r,this.w=n,this.h=i,this.maxw=o||n,this.maxh=a||i,this.refcount=0;}(r,n,this.y,t,e,t,this.h)},e.prototype.resize=function(t){return this.free+=t-this.w,this.w=t,!0},t}();}),ta=function(t,e){var r=e.pixelRatio;this.paddedRect=t,this.pixelRatio=r;},ea={tl:{configurable:!0},br:{configurable:!0},displaySize:{configurable:!0}};ea.tl.get=function(){return[this.paddedRect.x+1,this.paddedRect.y+1]},ea.br.get=function(){return[this.paddedRect.x+this.paddedRect.w-1,this.paddedRect.y+this.paddedRect.h-1]},ea.displaySize.get=function(){return[(this.paddedRect.w-2)/this.pixelRatio,(this.paddedRect.h-2)/this.pixelRatio]},Object.defineProperties(ta.prototype,ea);var ra=function(t){var e=new pi({width:0,height:0}),r={},n=new Qo(0,0,{autoResize:!0});for(var i in t){var o=t[i],a=n.packOne(o.data.width+2,o.data.height+2);e.resize({width:n.w,height:n.h}),pi.copy(o.data,e,{x:0,y:0},{x:a.x+1,y:a.y+1},o.data),r[i]=new ta(a,o);}n.shrink(),e.resize({width:n.w,height:n.h}),this.image=e,this.positions=r;};hr("ImagePosition",ta),hr("ImageAtlas",ra);var na=function(t,e,r,n,i){var o,a,s=8*i-n-1,u=(1<>1,p=-7,c=r?i-1:0,h=r?-1:1,f=t[e+c];for(c+=h,o=f&(1<<-p)-1,f>>=-p,p+=s;p>0;o=256*o+t[e+c],c+=h,p-=8);for(a=o&(1<<-p)-1,o>>=-p,p+=n;p>0;a=256*a+t[e+c],c+=h,p-=8);if(0===o)o=1-l;else{if(o===u)return a?NaN:1/0*(f?-1:1);a+=Math.pow(2,n),o-=l;}return(f?-1:1)*a*Math.pow(2,o-n)},ia=function(t,e,r,n,i,o){var a,s,u,l=8*o-i-1,p=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,f=n?0:o-1,y=n?1:-1,d=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,a=p):(a=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-a))<1&&(a--,u*=2),(e+=a+c>=1?h/u:h*Math.pow(2,1-c))*u>=2&&(a++,u/=2),a+c>=p?(s=0,a=p):a+c>=1?(s=(e*u-1)*Math.pow(2,i),a+=c):(s=e*Math.pow(2,c-1)*Math.pow(2,i),a=0));i>=8;t[r+f]=255&s,f+=y,s/=256,i-=8);for(a=a<0;t[r+f]=255&a,f+=y,a/=256,l-=8);t[r+f-y]|=128*d;},oa=aa;function aa(t){this.buf=ArrayBuffer.isView&&ArrayBuffer.isView(t)?t:new Uint8Array(t||0),this.pos=0,this.type=0,this.length=this.buf.length;}aa.Varint=0,aa.Fixed64=1,aa.Bytes=2,aa.Fixed32=5;function sa(t){return t.type===aa.Bytes?t.readVarint()+t.pos:t.pos+1}function ua(t,e,r){return r?4294967296*e+(t>>>0):4294967296*(e>>>0)+(t>>>0)}function la(t,e,r){var n=e<=16383?1:e<=2097151?2:e<=268435455?3:Math.ceil(Math.log(e)/(7*Math.LN2));r.realloc(n);for(var i=r.pos-1;i>=t;i--)r.buf[i+n]=r.buf[i];}function pa(t,e){for(var r=0;r>>8,t[r+2]=e>>>16,t[r+3]=e>>>24;}function wa(t,e){return(t[e]|t[e+1]<<8|t[e+2]<<16)+(t[e+3]<<24)}aa.prototype={destroy:function(){this.buf=null;},readFields:function(t,e,r){for(r=r||this.length;this.pos>3,o=this.pos;this.type=7&n,t(i,e,this),this.pos===o&&this.skip(n);}return e},readMessage:function(t,e){return this.readFields(t,e,this.readVarint()+this.pos)},readFixed32:function(){var t=xa(this.buf,this.pos);return this.pos+=4,t},readSFixed32:function(){var t=wa(this.buf,this.pos);return this.pos+=4,t},readFixed64:function(){var t=xa(this.buf,this.pos)+4294967296*xa(this.buf,this.pos+4);return this.pos+=8,t},readSFixed64:function(){var t=xa(this.buf,this.pos)+4294967296*wa(this.buf,this.pos+4);return this.pos+=8,t},readFloat:function(){var t=na(this.buf,this.pos,!0,23,4);return this.pos+=4,t},readDouble:function(){var t=na(this.buf,this.pos,!0,52,8);return this.pos+=8,t},readVarint:function(t){var e,r,n=this.buf;return e=127&(r=n[this.pos++]),r<128?e:(e|=(127&(r=n[this.pos++]))<<7,r<128?e:(e|=(127&(r=n[this.pos++]))<<14,r<128?e:(e|=(127&(r=n[this.pos++]))<<21,r<128?e:function(t,e,r){var n,i,o=r.buf;if(i=o[r.pos++],n=(112&i)>>4,i<128)return ua(t,n,e);if(i=o[r.pos++],n|=(127&i)<<3,i<128)return ua(t,n,e);if(i=o[r.pos++],n|=(127&i)<<10,i<128)return ua(t,n,e);if(i=o[r.pos++],n|=(127&i)<<17,i<128)return ua(t,n,e);if(i=o[r.pos++],n|=(127&i)<<24,i<128)return ua(t,n,e);if(i=o[r.pos++],n|=(1&i)<<31,i<128)return ua(t,n,e);throw new Error("Expected varint not more than 10 bytes")}(e|=(15&(r=n[this.pos]))<<28,t,this))))},readVarint64:function(){return this.readVarint(!0)},readSVarint:function(){var t=this.readVarint();return t%2==1?(t+1)/-2:t/2},readBoolean:function(){return Boolean(this.readVarint())},readString:function(){var t=this.readVarint()+this.pos,e=function(t,e,r){var n="",i=e;for(;i239?4:u>223?3:u>191?2:1;if(i+p>r)break;1===p?u<128&&(l=u):2===p?128==(192&(o=t[i+1]))&&(l=(31&u)<<6|63&o)<=127&&(l=null):3===p?(o=t[i+1],a=t[i+2],128==(192&o)&&128==(192&a)&&((l=(15&u)<<12|(63&o)<<6|63&a)<=2047||l>=55296&&l<=57343)&&(l=null)):4===p&&(o=t[i+1],a=t[i+2],s=t[i+3],128==(192&o)&&128==(192&a)&&128==(192&s)&&((l=(15&u)<<18|(63&o)<<12|(63&a)<<6|63&s)<=65535||l>=1114112)&&(l=null)),null===l?(l=65533,p=1):l>65535&&(l-=65536,n+=String.fromCharCode(l>>>10&1023|55296),l=56320|1023&l),n+=String.fromCharCode(l),i+=p;}return n}(this.buf,this.pos,t);return this.pos=t,e},readBytes:function(){var t=this.readVarint()+this.pos,e=this.buf.subarray(this.pos,t);return this.pos=t,e},readPackedVarint:function(t,e){var r=sa(this);for(t=t||[];this.pos127;);else if(e===aa.Bytes)this.pos=this.readVarint()+this.pos;else if(e===aa.Fixed32)this.pos+=4;else{if(e!==aa.Fixed64)throw new Error("Unimplemented type: "+e);this.pos+=8;}},writeTag:function(t,e){this.writeVarint(t<<3|e);},realloc:function(t){for(var e=this.length||16;e268435455||t<0?function(t,e){var r,n;t>=0?(r=t%4294967296|0,n=t/4294967296|0):(n=~(-t/4294967296),4294967295^(r=~(-t%4294967296))?r=r+1|0:(r=0,n=n+1|0));if(t>=0x10000000000000000||t<-0x10000000000000000)throw new Error("Given varint doesn't fit into 10 bytes");e.realloc(10),function(t,e,r){r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos]=127&t;}(r,0,e),function(t,e){var r=(7&t)<<4;if(e.buf[e.pos++]|=r|((t>>>=3)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;e.buf[e.pos++]=127&t;}(n,e);}(t,this):(this.realloc(4),this.buf[this.pos++]=127&t|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=t>>>7&127))));},writeSVarint:function(t){this.writeVarint(t<0?2*-t-1:2*t);},writeBoolean:function(t){this.writeVarint(Boolean(t));},writeString:function(t){t=String(t),this.realloc(4*t.length),this.pos++;var e=this.pos;this.pos=function(t,e,r){for(var n,i,o=0;o55295&&n<57344){if(!i){n>56319||o+1===e.length?(t[r++]=239,t[r++]=191,t[r++]=189):i=n;continue}if(n<56320){t[r++]=239,t[r++]=191,t[r++]=189,i=n;continue}n=i-55296<<10|n-56320|65536,i=null;}else i&&(t[r++]=239,t[r++]=191,t[r++]=189,i=null);n<128?t[r++]=n:(n<2048?t[r++]=n>>6|192:(n<65536?t[r++]=n>>12|224:(t[r++]=n>>18|240,t[r++]=n>>12&63|128),t[r++]=n>>6&63|128),t[r++]=63&n|128);}return r}(this.buf,t,this.pos);var r=this.pos-e;r>=128&&la(e,r,this),this.pos=e-1,this.writeVarint(r),this.pos+=r;},writeFloat:function(t){this.realloc(4),ia(this.buf,t,this.pos,!0,23,4),this.pos+=4;},writeDouble:function(t){this.realloc(8),ia(this.buf,t,this.pos,!0,52,8),this.pos+=8;},writeBytes:function(t){var e=t.length;this.writeVarint(e),this.realloc(e);for(var r=0;r=128&&la(r,n,this),this.pos=r-1,this.writeVarint(n),this.pos+=n;},writeMessage:function(t,e,r){this.writeTag(t,aa.Bytes),this.writeRawMessage(e,r);},writePackedVarint:function(t,e){this.writeMessage(t,pa,e);},writePackedSVarint:function(t,e){this.writeMessage(t,ca,e);},writePackedBoolean:function(t,e){this.writeMessage(t,ya,e);},writePackedFloat:function(t,e){this.writeMessage(t,ha,e);},writePackedDouble:function(t,e){this.writeMessage(t,fa,e);},writePackedFixed32:function(t,e){this.writeMessage(t,da,e);},writePackedSFixed32:function(t,e){this.writeMessage(t,va,e);},writePackedFixed64:function(t,e){this.writeMessage(t,ma,e);},writePackedSFixed64:function(t,e){this.writeMessage(t,ga,e);},writeBytesField:function(t,e){this.writeTag(t,aa.Bytes),this.writeBytes(e);},writeFixed32Field:function(t,e){this.writeTag(t,aa.Fixed32),this.writeFixed32(e);},writeSFixed32Field:function(t,e){this.writeTag(t,aa.Fixed32),this.writeSFixed32(e);},writeFixed64Field:function(t,e){this.writeTag(t,aa.Fixed64),this.writeFixed64(e);},writeSFixed64Field:function(t,e){this.writeTag(t,aa.Fixed64),this.writeSFixed64(e);},writeVarintField:function(t,e){this.writeTag(t,aa.Varint),this.writeVarint(e);},writeSVarintField:function(t,e){this.writeTag(t,aa.Varint),this.writeSVarint(e);},writeStringField:function(t,e){this.writeTag(t,aa.Bytes),this.writeString(e);},writeFloatField:function(t,e){this.writeTag(t,aa.Fixed32),this.writeFloat(e);},writeDoubleField:function(t,e){this.writeTag(t,aa.Fixed64),this.writeDouble(e);},writeBooleanField:function(t,e){this.writeVarintField(t,Boolean(e));}};var _a=3;function Aa(t,e,r){1===t&&r.readMessage(ka,e);}function ka(t,e,r){if(3===t){var n=r.readMessage(za,{}),i=n.id,o=n.bitmap,a=n.width,s=n.height,u=n.left,l=n.top,p=n.advance;e.push({id:i,bitmap:new li({width:a+2*_a,height:s+2*_a},o),metrics:{width:a,height:s,left:u,top:l,advance:p}});}}function za(t,e,r){1===t?e.id=r.readVarint():2===t?e.bitmap=r.readBytes():3===t?e.width=r.readVarint():4===t?e.height=r.readVarint():5===t?e.left=r.readSVarint():6===t?e.top=r.readSVarint():7===t&&(e.advance=r.readVarint());}var Sa=_a,Ma=function(t,e,r){this.target=t,this.parent=e,this.mapId=r,this.callbacks={},this.callbackID=0,y(["receive"],this),this.target.addEventListener("message",this.receive,!1);};Ma.prototype.send=function(t,e,r,n){var i=r?this.mapId+":"+this.callbackID++:null;r&&(this.callbacks[i]=r);var o=[];this.target.postMessage({targetMapId:n,sourceMapId:this.mapId,type:t,id:String(i),data:yr(e,o)},o);},Ma.prototype.receive=function(t){var e,r=this,n=t.data,i=n.id;if(!n.targetMapId||this.mapId===n.targetMapId){var o=function(t,e){var n=[];r.target.postMessage({sourceMapId:r.mapId,type:"",id:String(i),error:t?yr(t):null,data:yr(e,n)},n);};if(""===n.type)e=this.callbacks[n.id],delete this.callbacks[n.id],e&&n.error?e(dr(n.error)):e&&e(null,dr(n.data));else if(void 0!==n.id&&this.parent[n.type])this.parent[n.type](n.sourceMapId,dr(n.data),o);else if(void 0!==n.id&&this.parent.getWorkerSource){var a=n.type.split(".");this.parent.getWorkerSource(n.sourceMapId,a[0],a[1])[a[2]](dr(n.data),o);}else this.parent[n.type](dr(n.data));}},Ma.prototype.remove=function(){this.target.removeEventListener("message",this.receive,!1);};var Va=r(n(function(t,e){!function(t){function e(t,e,n){e=Math.pow(2,n)-e-1;var i=r(256*t,256*e,n),o=r(256*(t+1),256*(e+1),n);return i[0]+","+i[1]+","+o[0]+","+o[1]}function r(t,e,r){var n=2*Math.PI*6378137/256/Math.pow(2,r),i=t*n-2*Math.PI*6378137/2,o=e*n-2*Math.PI*6378137/2;return[i,o]}t.getURL=function(t,r,n,i,o,a){return a=a||{},t+"?"+["bbox="+e(n,i,o),"format="+(a.format||"image/png"),"service="+(a.service||"WMS"),"version="+(a.version||"1.1.1"),"request="+(a.request||"GetMap"),"srs="+(a.srs||"EPSG:3857"),"width="+(a.width||256),"height="+(a.height||256),"layers="+r].join("&")},t.getTileBBox=e,t.getMercCoords=r,Object.defineProperty(t,"__esModule",{value:!0});}(e);})),Ba=function(t,e,r){this.z=t,this.x=e,this.y=r,this.key=Ea(0,t,e,r);};Ba.prototype.equals=function(t){return this.z===t.z&&this.x===t.x&&this.y===t.y},Ba.prototype.url=function(t,e){var r=Va.getTileBBox(this.x,this.y,this.z),n=function(t,e,r){for(var n,i="",o=t;o>0;o--)i+=(e&(n=1<this.canonical.z?new Ia(t,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y):new Ia(t,this.wrap,t,this.canonical.x>>e,this.canonical.y>>e)},Ia.prototype.isChildOf=function(t){var e=this.canonical.z-t.canonical.z;return 0===t.overscaledZ||t.overscaledZ>e&&t.canonical.y===this.canonical.y>>e},Ia.prototype.children=function(t){if(this.overscaledZ>=t)return[new Ia(this.overscaledZ+1,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y)];var e=this.canonical.z+1,r=2*this.canonical.x,n=2*this.canonical.y;return[new Ia(e,this.wrap,e,r,n),new Ia(e,this.wrap,e,r+1,n),new Ia(e,this.wrap,e,r,n+1),new Ia(e,this.wrap,e,r+1,n+1)]},Ia.prototype.isLessThan=function(t){return this.wrapt.wrap)&&(this.overscaledZt.overscaledZ)&&(this.canonical.xt.canonical.x)&&this.canonical.y=this.dim+this.border||e<-this.border||e>=this.dim+this.border)throw new RangeError("out of range source coordinates for DEM data");return(e+this.border)*this.stride+(t+this.border)},hr("Level",Fa);var Pa=function(t,e,r){this.uid=t,this.scale=e||1,this.level=r||new Fa(256,512),this.loaded=!!r;};Pa.prototype.loadFromImage=function(t,e){if(t.height!==t.width)throw new RangeError("DEM tiles must be square");if(e&&"mapbox"!==e&&"terrarium"!==e)return b('"'+e+'" is not a valid encoding type. Valid types include "mapbox" and "terrarium".');var r=this.level=new Fa(t.width,t.width/2),n=t.data;this._unpackData(r,n,e||"mapbox");for(var i=0;i=0&&u[3]>=0&&this.grid.insert(o,u[0],u[1],u[2],u[3]);}},ja.prototype.loadVTLayers=function(){return this.vtLayers||(this.vtLayers=new vo.VectorTile(new oa(this.rawTileData)).layers,this.sourceLayerCoder=new Ta(this.vtLayers?Object.keys(this.vtLayers).sort():["_geojsonTileLayer"])),this.vtLayers},ja.prototype.query=function(t,e){var r=this;this.loadVTLayers();for(var n=t.params||{},i=Pn/t.tileSize/t.scale,o=Te(n.filter),a=t.queryGeometry,s=t.queryPadding*i,u=1/0,l=1/0,p=-1/0,c=-1/0,h=0;h=0)return!0;return!1}(o,u)){var l=this.sourceLayerCoder.decode(r),p=this.vtLayers[l].feature(n);if(i(new Br(this.tileID.overscaledZ),p))for(var c=0;c=200&&r.status<300&&r.response){var n;try{n=JSON.parse(r.response);}catch(t){return e(t)}e(null,n);}else 401===r.status&&t.url.match(/mapbox.com/)?e(new k(r.statusText+": you may have provided an invalid Mapbox access token. See https://www.mapbox.com/api-documentation/#access-tokens",r.status,t.url)):e(new k(r.statusText,r.status,t.url));},r.send(),r},t.getImage=function(t,e){return S(t,function(t,r){if(t)e(t);else if(r){var n=new self.Image,i=self.URL||self.webkitURL;n.onload=function(){e(null,n),i.revokeObjectURL(n.src);};var o=new self.Blob([new Uint8Array(r.data)],{type:"image/png"});n.cacheControl=r.cacheControl,n.expires=r.expires,n.src=r.data.byteLength?i.createObjectURL(o):"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=";}})},t.ResourceType=A,t.RGBAImage=pi,t.default$2=Qo,t.ImagePosition=ta,t.getArrayBuffer=S,t.default$3=function(t){return new oa(t).readFields(Aa,[])},t.default$4=mr,t.asyncAll=function(t,e,r){if(!t.length)return r(null,[]);var n=t.length,i=new Array(t.length),o=null;t.forEach(function(t,a){e(t,function(t,e){t&&(o=t),i[a]=e,0==--n&&r(o,i);});});},t.AlphaImage=li,t.default$5=E,t.endsWith=d,t.extend=h,t.sphericalToCartesian=function(t){var e=t[0],r=t[1],n=t[2];return r+=90,r*=Math.PI/180,n*=Math.PI/180,{x:e*Math.cos(r)*Math.sin(n),y:e*Math.sin(r)*Math.sin(n),z:e*Math.cos(n)}},t.Evented=I,t.validateStyle=rr,t.validateLight=nr,t.emitValidationErrors=ar,t.default$6=Q,t.number=wt,t.Properties=Dr,t.Transitionable=Er,t.Transitioning=Pr,t.PossiblyEvaluated=Lr,t.DataConstantProperty=jr,t.warnOnce=b,t.uniqueId=function(){return f++},t.default$7=Ma,t.pick=function(t,e){for(var r={},n=0;n@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g,function(t,r,n,i){var o=n||i;return e[r]=!o||o.toLowerCase(),""}),e["max-age"]){var r=parseInt(e["max-age"],10);isNaN(r)?delete e["max-age"]:e["max-age"]=r;}return e},t.default$11=ja,t.default$12=Oa,t.default$13=Te,t.default$14=Ko,t.CollisionBoxArray=dn,t.default$15=zn,t.TriangleIndexArray=pn,t.default$16=Br,t.default$17=a,t.keysDifference=function(t,e){var r=[];for(var n in t)n in e||r.push(n);return r},t.default$18=["type","source","source-layer","minzoom","maxzoom","filter","layout"],t.mat4=ri,t.vec4=ei,t.getSizeData=jo,t.evaluateSizeForFeature=function(t,e,r){var n=e;return"source"===t.functionType?r.lowerSize/10:"composite"===t.functionType?wt(r.lowerSize/10,r.upperSize/10,n.uSizeT):n.uSize},t.evaluateSizeForZoom=function(t,e,r){if("constant"===t.functionType)return{uSizeT:0,uSize:t.layoutSize};if("source"===t.functionType)return{uSizeT:0,uSize:0};if("camera"===t.functionType){var n=t.propertyValue,i=t.zoomRange,o=t.sizeRange,a=c(Se(n,r.specification).interpolationFactor(e,i.min,i.max),0,1);return{uSizeT:0,uSize:o.min+a*(o.max-o.min)}}var s=t.propertyValue,u=t.zoomRange;return{uSizeT:c(Se(s,r.specification).interpolationFactor(e,u.min,u.max),0,1),uSize:0}},t.addDynamicAttributes=Do,t.default$19=$o,t.WritingMode=Ra,t.multiPolygonIntersectsBufferedPoint=Rn,t.multiPolygonIntersectsMultiPolygon=Un,t.multiPolygonIntersectsBufferedMultiLine=Dn,t.polygonIntersectsPolygon=function(t,e){for(var r=0;r-i/2;){if(--a<0)return!1;s-=e[a].dist(o),o=e[a];}s+=e[a].dist(e[a+1]),a++;for(var l=[],u=0;sr;)u-=l.shift().angleDelta;if(u>n)return!1;a++,s+=c.dist(f);}return!0}function o(t,i,r,o,a,s,l,u,h){var c=o?.6*s*l:0,f=Math.max(o?o.right-o.left:0,a?a.right-a.left:0),p=0===t[0].x||t[0].x===h||0===t[0].y||t[0].y===h;return i-f*l=0&&_=0&&I=0&&v+f<=p){var z=new e.default$25(_,I,M,m);z._round(),a&&!n(i,z,l,a,s)||y.push(z);}}g+=S;}h||y.length||u||(y=t(i,g/2,o,a,s,l,u,!0,c));return y}(t,p?i/2*u%i:(f/2+2*s)*l*u%i,i,c,r,f*l,p,!1,h)}r.prototype.replace=function(e){this._layerConfigs={},this._layers={},this.update(e,[]);},r.prototype.update=function(t,r){for(var n=this,o=0,a=t;o0&&(g=Math.max(10*s,g),this._addLineCollisionCircles(e,t,i,i.segment,v,g,r,n,o,h));}else e.emplaceBack(i.x,i.y,p,c,d,f,r,n,o,0,0);this.boxEndIndex=e.length;};s.prototype._addLineCollisionCircles=function(e,t,i,r,n,o,a,s,l,u){var h=o/2,c=Math.floor(n/h),f=1+.4*Math.log(u)/Math.LN2,p=Math.floor(c*f/2),d=-o/2,g=i,v=r+1,y=d,m=-n/2,x=m-n/4;do{if(--v<0){if(y>m)return;v=0;break}y-=t[v].dist(g),g=t[v];}while(y>x);for(var w=t[v].dist(t[v+1]),S=-p;Sn&&(b+=M-n),!(b=t.length)return;w=t[v].dist(t[v+1]);}var _=b-y,I=t[v],z=t[v+1].sub(I)._unit()._mult(_)._add(I)._round(),T=Math.abs(b-d)0)for(var i=(this.length>>1)-1;i>=0;i--)this._down(i);}function c(e,t){return et?1:0}function f(t,i,r){void 0===i&&(i=1),void 0===r&&(r=!1);for(var n=1/0,o=1/0,a=-1/0,s=-1/0,u=t[0],h=0;ha)&&(a=c.x),(!h||c.y>s)&&(s=c.y);}var f=a-n,g=s-o,v=Math.min(f,g),y=v/2,m=new l(null,p);if(0===v)return new e.default$1(n,o);for(var x=n;xS.d||!S.d)&&(S=b,r&&console.log("found best %d after %d probes",Math.round(1e4*b.d)/1e4,M)),b.max-S.d<=i||(y=b.h/2,m.push(new d(b.p.x-y,b.p.y-y,y,t)),m.push(new d(b.p.x+y,b.p.y-y,y,t)),m.push(new d(b.p.x-y,b.p.y+y,y,t)),m.push(new d(b.p.x+y,b.p.y+y,y,t)),M+=4);}return r&&(console.log("num probes: "+M),console.log("best distance: "+S.d)),S.p}function p(e,t){return t.max-e.max}function d(t,i,r,n){this.p=new e.default$1(t,i),this.h=r,this.d=function(t,i){for(var r=!1,n=1/0,o=0;ot.y!=c.y>t.y&&t.x<(c.x-h.x)*(t.y-h.y)/(c.y-h.y)+h.x&&(r=!r),n=Math.min(n,e.distToSegmentSquared(t,h,c));}return(r?1:-1)*Math.sqrt(n)}(this.p,n),this.max=this.d+this.h*Math.SQRT2;}function g(t,i,r,n,o,a){t.createArrays(),t.symbolInstances=[];var s=512*t.overscaling;t.tilePixelRatio=e.default$8/s,t.compareText={},t.iconsNeedLinear=!1;var l=t.layers[0].layout,u=t.layers[0]._unevaluatedLayout._values,h={};if("composite"===t.textSizeData.functionType){var c=t.textSizeData.zoomRange,f=c.min,p=c.max;h.compositeTextSizes=[u["text-size"].possiblyEvaluate(new e.default$16(f)),u["text-size"].possiblyEvaluate(new e.default$16(p))];}if("composite"===t.iconSizeData.functionType){var d=t.iconSizeData.zoomRange,g=d.min,y=d.max;h.compositeIconSizes=[u["icon-size"].possiblyEvaluate(new e.default$16(g)),u["icon-size"].possiblyEvaluate(new e.default$16(y))];}h.layoutTextSize=u["text-size"].possiblyEvaluate(new e.default$16(t.zoom+1)),h.layoutIconSize=u["icon-size"].possiblyEvaluate(new e.default$16(t.zoom+1)),h.textMaxSize=u["text-size"].possiblyEvaluate(new e.default$16(18));for(var m=24*l.get("text-line-height"),x="map"===l.get("text-rotation-alignment")&&"line"===l.get("symbol-placement"),w=l.get("text-keep-upright"),S=0,M=t.features;S=e.default$8||h.y<0||h.y>=e.default$8||t.symbolInstances.push(function(t,i,r,n,o,l,u,h,c,f,p,d,g,v,m,x,w,S,M,b,_){var I,z,T=t.addToLineVertexArray(i,r),P=0,k=0,L=0,$=n.horizontal?n.horizontal.text:"",D=[];n.horizontal&&(I=new s(u,r,i,h,c,f,n.horizontal,p,d,g,t.overscaling),k+=y(t,i,n.horizontal,l,g,M,v,T,n.vertical?e.WritingMode.horizontal:e.WritingMode.horizontalOnly,D,b,_),n.vertical&&(L+=y(t,i,n.vertical,l,g,M,v,T,e.WritingMode.vertical,D,b,_)));var O=I?I.boxStartIndex:t.collisionBoxArray.length,C=I?I.boxEndIndex:t.collisionBoxArray.length;if(o){var A=function(t,i,r,n,o,a){var s,l,u,h,c=i.image,f=r.layout,p=i.top-1/c.pixelRatio,d=i.left-1/c.pixelRatio,g=i.bottom+1/c.pixelRatio,v=i.right+1/c.pixelRatio;if("none"!==f.get("icon-text-fit")&&o){var y=v-d,m=g-p,x=f.get("text-size").evaluate(a)/24,w=o.left*x,S=o.right*x,M=o.top*x,b=S-w,_=o.bottom*x-M,I=f.get("icon-text-fit-padding")[0],z=f.get("icon-text-fit-padding")[1],T=f.get("icon-text-fit-padding")[2],P=f.get("icon-text-fit-padding")[3],k="width"===f.get("icon-text-fit")?.5*(_-m):0,L="height"===f.get("icon-text-fit")?.5*(b-y):0,$="width"===f.get("icon-text-fit")||"both"===f.get("icon-text-fit")?b:y,D="height"===f.get("icon-text-fit")||"both"===f.get("icon-text-fit")?_:m;s=new e.default$1(w+L-P,M+k-I),l=new e.default$1(w+L+z+$,M+k-I),u=new e.default$1(w+L+z+$,M+k+T+D),h=new e.default$1(w+L-P,M+k+T+D);}else s=new e.default$1(d,p),l=new e.default$1(v,p),u=new e.default$1(v,g),h=new e.default$1(d,g);var O=r.layout.get("icon-rotate").evaluate(a)*Math.PI/180;if(O){var C=Math.sin(O),A=Math.cos(O),E=[A,-C,C,A];s._matMult(E),l._matMult(E),h._matMult(E),u._matMult(E);}return[{tl:s,tr:l,bl:h,br:u,tex:c.paddedRect,writingMode:void 0,glyphOffset:[0,0]}]}(0,o,l,0,n.horizontal,M);z=new s(u,r,i,h,c,f,o,m,x,!1,t.overscaling),P=4*A.length;var E=t.iconSizeData,N=null;"source"===E.functionType?N=[10*l.layout.get("icon-size").evaluate(M)]:"composite"===E.functionType&&(N=[10*_.compositeIconSizes[0].evaluate(M),10*_.compositeIconSizes[1].evaluate(M)]),t.addSymbols(t.icon,A,N,S,w,M,!1,i,T.lineStartIndex,T.lineLength);}var R=z?z.boxStartIndex:t.collisionBoxArray.length,B=z?z.boxEndIndex:t.collisionBoxArray.length;t.glyphOffsetArray.length>=e.default$14.MAX_GLYPHS&&e.warnOnce("Too many glyphs being rendered in a tile. See https://github.com/mapbox/mapbox-gl-js/issues/2907");var F=new a,G=new a;return{key:$,textBoxStartIndex:O,textBoxEndIndex:C,iconBoxStartIndex:R,iconBoxEndIndex:B,textOffset:v,iconOffset:S,anchor:i,line:r,featureIndex:h,feature:M,numGlyphVertices:k,numVerticalGlyphVertices:L,numIconVertices:P,textOpacityState:F,iconOpacityState:G,isDuplicate:!1,placedTextSymbolIndices:D,crossTileID:0}}(t,h,o,r,n,t.layers[0],t.collisionBoxArray,i.index,i.sourceLayerIndex,t.index,w,_,T,g,M,I,P,v,i,l,u));};if("line"===d.get("symbol-placement"))for(var $=0,D=function(t,i,r,n,o){for(var a=[],s=0;s=n&&f.x>=n||(c.x>=n?c=new e.default$1(n,c.y+(f.y-c.y)*((n-c.x)/(f.x-c.x)))._round():f.x>=n&&(f=new e.default$1(n,c.y+(f.y-c.y)*((n-c.x)/(f.x-c.x)))._round()),c.y>=o&&f.y>=o||(c.y>=o?c=new e.default$1(c.x+(f.x-c.x)*((o-c.y)/(f.y-c.y)),o)._round():f.y>=o&&(f=new e.default$1(c.x+(f.x-c.x)*((o-c.y)/(f.y-c.y)),o)._round()),u&&c.equals(u[u.length-1])||(u=[c],a.push(u)),u.push(f)))));}return a}(i.geometry,0,0,e.default$8,e.default$8);$=0;a--)if(r.dist(o[a])0&&(this.data[0]=this.data[this.length],this._down(0)),this.data.pop(),e}},peek:function(){return this.data[0]},_up:function(e){for(var t=this.data,i=this.compare,r=t[e];e>0;){var n=e-1>>1,o=t[n];if(i(r,o)>=0)break;t[e]=o,e=n;}t[e]=r;},_down:function(e){for(var t=this.data,i=this.compare,r=this.length>>1,n=t[e];e=0)break;t[e]=s,e=o;}t[e]=n;}},l.default=u;var x=function(t){var i=new e.AlphaImage({width:0,height:0}),r={},n=new e.default$2(0,0,{autoResize:!0});for(var o in t){var a=t[o],s=r[o]={};for(var l in a){var u=a[+l];if(u&&0!==u.bitmap.width&&0!==u.bitmap.height){var h=n.packOne(u.bitmap.width+2,u.bitmap.height+2);i.resize({width:n.w,height:n.h}),e.AlphaImage.copy(u.bitmap,i,{x:0,y:0},{x:h.x+1,y:h.y+1},u.bitmap),s[l]={rect:h,metrics:u.metrics};}}}n.shrink(),i.resize({width:n.w,height:n.h}),this.image=i,this.positions=r;};e.register("GlyphAtlas",x);var w=function(t){this.tileID=new e.OverscaledTileID(t.tileID.overscaledZ,t.tileID.wrap,t.tileID.canonical.z,t.tileID.canonical.x,t.tileID.canonical.y),this.uid=t.uid,this.zoom=t.zoom,this.pixelRatio=t.pixelRatio,this.tileSize=t.tileSize,this.source=t.source,this.overscaling=this.tileID.overscaleFactor(),this.showCollisionBoxes=t.showCollisionBoxes,this.collectResourceTiming=!!t.collectResourceTiming;};function S(t,i){for(var r=new e.default$16(i),n=0,o=t;n=z.maxzoom))if("none"!==z.visibility)S(I,o.zoom),(c[z.id]=z.createBucket({index:s.bucketLayerIDs.length,layers:I,zoom:o.zoom,pixelRatio:o.pixelRatio,overscaling:o.overscaling,collisionBoxArray:o.collisionBoxArray,sourceLayerIndex:y})).populate(m,f),s.bucketLayerIDs.push(I.map(function(e){return e.id}));}}}var T=e.mapObject(f.glyphDependencies,function(e){return Object.keys(e).map(Number)});Object.keys(T).length?r.send("getGlyphs",{uid:this.uid,stacks:T},function(e,t){l||(l=e,u=t,k.call(o));}):u={};var P=Object.keys(f.iconDependencies);function k(){if(l)return n(l);if(u&&h){var t=new x(u),i=new e.default$28(h);for(var r in c){var o=c[r];o instanceof e.default$14&&(S(o.layers,this.zoom),g(o,u,t.positions,h,i.positions,this.showCollisionBoxes));}this.status="done",n(null,{buckets:e.values(c).filter(function(e){return!e.isEmpty()}),featureIndex:s,collisionBoxArray:this.collisionBoxArray,glyphAtlasImage:t.image,iconAtlasImage:i.image});}}P.length?r.send("getImages",{icons:P},function(e,t){l||(l=e,h=t,k.call(o));}):h={},k.call(this);};var M=function(e){return!(!performance||!performance.getEntriesByName)&&performance.getEntriesByName(e)};function b(t,i){var r=e.getArrayBuffer(t.request,function(t,r){t?i(t):r&&i(null,{vectorTile:new e.default$29.VectorTile(new e.default$30(r.data)),rawData:r.data,cacheControl:r.cacheControl,expires:r.expires});});return function(){r.abort(),i();}}var _=function(e,t,i){this.actor=e,this.layerIndex=t,this.loadVectorData=i||b,this.loading={},this.loaded={};};_.prototype.loadTile=function(t,i){var r=this,n=t.uid;this.loading||(this.loading={});var o=this.loading[n]=new w(t);o.abort=this.loadVectorData(t,function(a,s){if(delete r.loading[n],a||!s)return i(a);var l=s.rawData,u={};s.expires&&(u.expires=s.expires),s.cacheControl&&(u.cacheControl=s.cacheControl);var h={};if(t.request&&t.request.collectResourceTiming){var c=M(t.request.url);c&&(h.resourceTiming=JSON.parse(JSON.stringify(c)));}o.vectorTile=s.vectorTile,o.parse(s.vectorTile,r.layerIndex,r.actor,function(t,r){if(t||!r)return i(t);i(null,e.extend({rawTileData:l.slice(0)},r,u,h));}),r.loaded=r.loaded||{},r.loaded[n]=o;});},_.prototype.reloadTile=function(e,t){var i=this.loaded,r=e.uid,n=this;if(i&&i[r]){var o=i[r];o.showCollisionBoxes=e.showCollisionBoxes;var a=function(e,i){var r=o.reloadCallback;r&&(delete o.reloadCallback,o.parse(o.vectorTile,n.layerIndex,n.actor,r)),t(e,i);};"parsing"===o.status?o.reloadCallback=a:"done"===o.status&&o.parse(o.vectorTile,this.layerIndex,this.actor,a);}},_.prototype.abortTile=function(e,t){var i=this.loading,r=e.uid;i&&i[r]&&i[r].abort&&(i[r].abort(),delete i[r]),t();},_.prototype.removeTile=function(e,t){var i=this.loaded,r=e.uid;i&&i[r]&&delete i[r],t();};var I=function(){this.loading={},this.loaded={};};I.prototype.loadTile=function(t,i){var r=t.uid,n=t.encoding,o=new e.default$31(r);this.loading[r]=o,o.loadFromImage(t.rawImageData,n),delete this.loading[r],this.loaded=this.loaded||{},this.loaded[r]=o,i(null,o);},I.prototype.removeTile=function(e){var t=this.loaded,i=e.uid;t&&t[i]&&delete t[i];};var z={RADIUS:6378137,FLATTENING:1/298.257223563,POLAR_RADIUS:6356752.3142};function T(e){var t=0;if(e&&e.length>0){t+=Math.abs(P(e[0]));for(var i=1;i2){for(a=0;a=0}(e)===t?e:e.reverse()}var A=e.default$29.VectorTileFeature.prototype.toGeoJSON,E=function(t){this._feature=t,this.extent=e.default$8,this.type=t.type,this.properties=t.tags,"id"in t&&!isNaN(t.id)&&(this.id=parseInt(t.id,10));};E.prototype.loadGeometry=function(){if(1===this._feature.type){for(var t=[],i=0,r=this._feature.geometry;i>31}function Q(e,t){for(var i=e.loadGeometry(),r=e.type,n=0,o=0,a=i.length,s=0;sn;){if(o-n>600){var s=o-n+1,l=r-n+1,u=Math.log(s),h=.5*Math.exp(2*u/3),c=.5*Math.sqrt(u*h*(s-h)/s)*(l-s/2<0?-1:1),f=Math.max(n,Math.floor(r-l*h/s+c)),p=Math.min(o,Math.floor(r+(s-l)*h/s+c));e(t,i,r,f,p,a);}var d=i[2*r+a],g=n,v=o;for(te(t,i,n,r),i[2*o+a]>d&&te(t,i,n,o);gd;)v--;}i[2*n+a]===d?te(t,i,n,v):te(t,i,++v,o),v<=r&&(n=v+1),r<=v&&(o=v-1);}}(t,i,s,n,o,a%2);e(t,i,r,n,s-1,a+1);e(t,i,r,s+1,o,a+1);};function te(e,t,i,r){ie(e,i,r),ie(t,2*i,2*r),ie(t,2*i+1,2*r+1);}function ie(e,t,i){var r=e[t];e[t]=e[i],e[i]=r;}var re=function(e,t,i,r,n,o,a){var s,l,u=[0,e.length-1,0],h=[];for(;u.length;){var c=u.pop(),f=u.pop(),p=u.pop();if(f-p<=a)for(var d=p;d<=f;d++)s=t[2*d],l=t[2*d+1],s>=i&&s<=n&&l>=r&&l<=o&&h.push(e[d]);else{var g=Math.floor((p+f)/2);s=t[2*g],l=t[2*g+1],s>=i&&s<=n&&l>=r&&l<=o&&h.push(e[g]);var v=(c+1)%2;(0===c?i<=s:r<=l)&&(u.push(p),u.push(g-1),u.push(v)),(0===c?n>=s:o>=l)&&(u.push(g+1),u.push(f),u.push(v));}}return h};var ne=function(e,t,i,r,n,o){var a=[0,e.length-1,0],s=[],l=n*n;for(;a.length;){var u=a.pop(),h=a.pop(),c=a.pop();if(h-c<=o)for(var f=c;f<=h;f++)oe(t[2*f],t[2*f+1],i,r)<=l&&s.push(e[f]);else{var p=Math.floor((c+h)/2),d=t[2*p],g=t[2*p+1];oe(d,g,i,r)<=l&&s.push(e[p]);var v=(u+1)%2;(0===u?i-n<=d:r-n<=g)&&(a.push(c),a.push(p-1),a.push(v)),(0===u?i+n>=d:r+n>=g)&&(a.push(p+1),a.push(h),a.push(v));}}return s};function oe(e,t,i,r){var n=e-i,o=t-r;return n*n+o*o}var ae=function(e,t,i,r,n){return new se(e,t,i,r,n)};function se(e,t,i,r,n){t=t||le,i=i||ue,n=n||Array,this.nodeSize=r||64,this.points=e,this.ids=new n(e.length),this.coords=new n(2*e.length);for(var o=0;o=1e4?Math.round(t/1e3)+"k":t>=1e3?Math.round(t/100)/10+"k":t;return me(me({},e.properties),{cluster:!0,cluster_id:e.id,point_count:t,point_count_abbreviated:i})}function ve(e){return e/360+.5}function ye(e){var t=Math.sin(e*Math.PI/180),i=.5-.25*Math.log((1+t)/(1-t))/Math.PI;return i<0?0:i>1?1:i}function me(e,t){for(var i in t)e[i]=t[i];return e}function xe(e){return e.x}function we(e){return e.y}function Se(e,t,i,r,n,o){var a=n-i,s=o-r;if(0!==a||0!==s){var l=((e-i)*a+(t-r)*s)/(a*a+s*s);l>1?(i=n,r=o):l>0&&(i+=a*l,r+=s*l);}return(a=e-i)*a+(s=t-r)*s}function Me(e,t,i,r){var n={id:e||null,type:t,geometry:i,tags:r,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};return function(e){var t=e.geometry,i=e.type;if("Point"===i||"MultiPoint"===i||"LineString"===i)be(e,t);else if("Polygon"===i||"MultiLineString"===i)for(var r=0;r0&&(a+=r?(n*u-l*o)/2:Math.sqrt(Math.pow(l-n,2)+Math.pow(u-o,2))),n=l,o=u;}var h=t.length-3;t[2]=1,function e(t,i,r,n){for(var o,a=n,s=t[i],l=t[i+1],u=t[r],h=t[r+1],c=i+3;ca&&(o=c,a=f);}a>n&&(o-i>3&&e(t,i,o,n),t[o+2]=a,r-o>3&&e(t,o,r,n));}(t,0,h,i),t[h+2]=1,t.size=Math.abs(a),t.start=0,t.end=t.size;}function Te(e,t,i,r){for(var n=0;n1?1:i}function Le(e,t,i,r,n,o,a,s){if(r/=t,o>=(i/=t)&&a<=r)return e;if(o>r||a=i&&d<=r)l.push(h);else if(!(p>r||d=i&&a<=r&&(t.push(e[o]),t.push(e[o+1]),t.push(e[o+2]));}}function De(e,t,i,r,n,o,a){for(var s,l,u=Oe(e),h=0===n?Ee:Ne,c=e.start,f=0;f=i&&(l=h(u,p,d,v,y,i),a&&(u.start=c+s*l)):m>r?x<=r&&(l=h(u,p,d,v,y,r),a&&(u.start=c+s*l)):Ae(u,p,d,g),x=i&&(l=h(u,p,d,v,y,i),w=!0),x>r&&m<=r&&(l=h(u,p,d,v,y,r),w=!0),!o&&w&&(a&&(u.end=c+s*l),t.push(u),u=Oe(e)),a&&(c+=s);}var S=e.length-3;p=e[S],d=e[S+1],g=e[S+2],(m=0===n?p:d)>=i&&m<=r&&Ae(u,p,d,g),S=u.length-3,o&&S>=3&&(u[S]!==u[0]||u[S+1]!==u[1])&&Ae(u,u[0],u[1],u[2]),u.length&&t.push(u);}function Oe(e){var t=[];return t.size=e.size,t.start=e.start,t.end=e.end,t}function Ce(e,t,i,r,n,o){for(var a=0;aa.maxX&&(a.maxX=h),c>a.maxY&&(a.maxY=c);}return a}function Je(e,t,i,r){var n=t.geometry,o=t.type,a=[];if("Point"===o||"MultiPoint"===o)for(var s=0;s0&&t.size<(n?a:r))i.numPoints+=t.length/3;else{for(var s=[],l=0;la)&&(i.numSimplified++,s.push(t[l]),s.push(t[l+1])),i.numPoints++;n&&function(e,t){for(var i=0,r=0,n=e.length,o=n-2;r0===t)for(r=0,n=e.length;r24)throw new Error("maxZoom should be in the 0-24 range");var r=function(e,t){var i=[];if("FeatureCollection"===e.type)for(var r=0;r=this.options.minZoom;n--){var o=+Date.now();this.trees[n+1]=ae(r,xe,we,this.options.nodeSize,Float32Array),r=this._cluster(r,n),t&&console.log("z%d: %d clusters in %dms",n,r.length,+Date.now()-o);}return this.trees[this.options.minZoom]=ae(r,xe,we,this.options.nodeSize,Float32Array),t&&console.timeEnd("total time"),this},getClusters:function(e,t){for(var i=this.trees[this._limitZoom(t)],r=i.range(ve(e[0]),ye(e[3]),ve(e[2]),ye(e[1])),n=[],o=0;o1&&console.time("creation"),f=this.tiles[c]=Ve(e,t,i,r,l),this.tileCoords.push({z:t,x:i,y:r}),u)){u>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",t,i,r,f.numFeatures,f.numPoints,f.numSimplified),console.timeEnd("creation"));var p="z"+t;this.stats[p]=(this.stats[p]||0)+1,this.total++;}if(f.source=e,n){if(t===l.maxZoom||t===n)continue;var d=1<1&&console.time("clipping");var g,v,y,m,x,w,S=.5*l.buffer/l.extent,M=.5-S,b=.5+S,_=1+S;g=v=y=m=null,x=Le(e,h,i-S,i+b,0,f.minX,f.maxX,l),w=Le(e,h,i+M,i+_,0,f.minX,f.maxX,l),e=null,x&&(g=Le(x,h,r-S,r+b,1,f.minY,f.maxY,l),v=Le(x,h,r+M,r+_,1,f.minY,f.maxY,l),x=null),w&&(y=Le(w,h,r-S,r+b,1,f.minY,f.maxY,l),m=Le(w,h,r+M,r+_,1,f.minY,f.maxY,l),w=null),u>1&&console.timeEnd("clipping"),s.push(g||[],t+1,2*i,2*r),s.push(v||[],t+1,2*i,2*r+1),s.push(y||[],t+1,2*i+1,2*r),s.push(m||[],t+1,2*i+1,2*r+1);}}},Ye.prototype.getTile=function(e,t,i){var r=this.options,n=r.extent,o=r.debug;if(e<0||e>24)return null;var a=1<1&&console.log("drilling down to z%d-%d-%d",e,t,i);for(var l,u=e,h=t,c=i;!l&&u>0;)u--,h=Math.floor(h/2),c=Math.floor(c/2),l=this.tiles[Ze(u,h,c)];return l&&l.source?(o>1&&console.log("found parent tile z%d-%d-%d",u,h,c),o>1&&console.time("drilling down"),this.splitTile(l.source,u,h,c,e,t,i),o>1&&console.timeEnd("drilling down"),this.tiles[s]?Fe(this.tiles[s],n):null):null};var Xe=function(t){function i(e,i,r){t.call(this,e,i,je),r&&(this.loadGeoJSON=r);}return t&&(i.__proto__=t),i.prototype=Object.create(t&&t.prototype),i.prototype.constructor=i,i.prototype.loadData=function(e,t){this._pendingCallback&&this._pendingCallback(null,{abandoned:!0}),this._pendingCallback=t,this._pendingLoadDataParams=e,this._state&&"Idle"!==this._state?this._state="NeedsLoadData":(this._state="Coalescing",this._loadData());},i.prototype._loadData=function(){var e=this;if(this._pendingCallback&&this._pendingLoadDataParams){var t=this._pendingCallback,i=this._pendingLoadDataParams;delete this._pendingCallback,delete this._pendingLoadDataParams,this.loadGeoJSON(i,function(r,n){if(r||!n)return t(r);if("object"!=typeof n)return t(new Error("Input data is not a valid GeoJSON object."));$(n,!0);try{e._geoJSONIndex=i.cluster?he(i.superclusterOptions).load(n.features):function(e,t){return new Ye(e,t)}(n,i.geojsonVtOptions);}catch(r){return t(r)}e.loaded={};var o={};if(i.request&&i.request.collectResourceTiming){var a=M(i.request.url);a&&(o.resourceTiming={},o.resourceTiming[i.source]=JSON.parse(JSON.stringify(a)));}t(null,o);});}},i.prototype.coalesce=function(){"Coalescing"===this._state?this._state="Idle":"NeedsLoadData"===this._state&&(this._state="Coalescing",this._loadData());},i.prototype.reloadTile=function(e,i){var r=this.loaded,n=e.uid;return r&&r[n]?t.prototype.reloadTile.call(this,e,i):this.loadTile(e,i)},i.prototype.loadGeoJSON=function(t,i){if(t.request)e.getJSON(t.request,i);else{if("string"!=typeof t.data)return i(new Error("Input data is not a valid GeoJSON object."));try{return i(null,JSON.parse(t.data))}catch(e){return i(new Error("Input data is not a valid GeoJSON object."))}}},i.prototype.removeSource=function(e,t){this._pendingCallback&&this._pendingCallback(null,{abandoned:!0}),t();},i}(_),qe=function(t){var i=this;this.self=t,this.actor=new e.default$7(t,this),this.layerIndexes={},this.workerSourceTypes={vector:_,geojson:Xe},this.workerSources={},this.demWorkerSources={},this.self.registerWorkerSource=function(e,t){if(i.workerSourceTypes[e])throw new Error('Worker source with name "'+e+'" already registered.');i.workerSourceTypes[e]=t;},this.self.registerRTLTextPlugin=function(t){if(e.plugin.isLoaded())throw new Error("RTL text plugin already registered.");e.plugin.applyArabicShaping=t.applyArabicShaping,e.plugin.processBidirectionalText=t.processBidirectionalText;};};return qe.prototype.setLayers=function(e,t,i){this.getLayerIndex(e).replace(t),i();},qe.prototype.updateLayers=function(e,t,i){this.getLayerIndex(e).update(t.layers,t.removedIds),i();},qe.prototype.loadTile=function(e,t,i){this.getWorkerSource(e,t.type,t.source).loadTile(t,i);},qe.prototype.loadDEMTile=function(e,t,i){this.getDEMWorkerSource(e,t.source).loadTile(t,i);},qe.prototype.reloadTile=function(e,t,i){this.getWorkerSource(e,t.type,t.source).reloadTile(t,i);},qe.prototype.abortTile=function(e,t,i){this.getWorkerSource(e,t.type,t.source).abortTile(t,i);},qe.prototype.removeTile=function(e,t,i){this.getWorkerSource(e,t.type,t.source).removeTile(t,i);},qe.prototype.removeDEMTile=function(e,t){this.getDEMWorkerSource(e,t.source).removeTile(t);},qe.prototype.removeSource=function(e,t,i){if(this.workerSources[e]&&this.workerSources[e][t.type]&&this.workerSources[e][t.type][t.source]){var r=this.workerSources[e][t.type][t.source];delete this.workerSources[e][t.type][t.source],void 0!==r.removeSource?r.removeSource(t,i):i();}},qe.prototype.loadWorkerSource=function(e,t,i){try{this.self.importScripts(t.url),i();}catch(e){i(e.toString());}},qe.prototype.loadRTLTextPlugin=function(t,i,r){try{e.plugin.isLoaded()||(this.self.importScripts(i),r(e.plugin.isLoaded()?null:new Error("RTL Text Plugin failed to import scripts from "+i)));}catch(e){r(e.toString());}},qe.prototype.getLayerIndex=function(e){var t=this.layerIndexes[e];return t||(t=this.layerIndexes[e]=new r),t},qe.prototype.getWorkerSource=function(e,t,i){var r=this;if(this.workerSources[e]||(this.workerSources[e]={}),this.workerSources[e][t]||(this.workerSources[e][t]={}),!this.workerSources[e][t][i]){var n={send:function(t,i,n){r.actor.send(t,i,n,e);}};this.workerSources[e][t][i]=new this.workerSourceTypes[t](n,this.getLayerIndex(e));}return this.workerSources[e][t][i]},qe.prototype.getDEMWorkerSource=function(e,t){return this.demWorkerSources[e]||(this.demWorkerSources[e]={}),this.demWorkerSources[e][t]||(this.demWorkerSources[e][t]=new I),this.demWorkerSources[e][t]},"undefined"!=typeof WorkerGlobalScope&&"undefined"!=typeof self&&self instanceof WorkerGlobalScope&&new qe(self),qe}); + +define(["./chunk1.js"],function(t){"use strict";var e=t.createCommonjsModule(function(t){function e(t){return!!("undefined"!=typeof window&&"undefined"!=typeof document&&Array.prototype&&Array.prototype.every&&Array.prototype.filter&&Array.prototype.forEach&&Array.prototype.indexOf&&Array.prototype.lastIndexOf&&Array.prototype.map&&Array.prototype.some&&Array.prototype.reduce&&Array.prototype.reduceRight&&Array.isArray&&Function.prototype&&Function.prototype.bind&&Object.keys&&Object.create&&Object.getPrototypeOf&&Object.getOwnPropertyNames&&Object.isSealed&&Object.isFrozen&&Object.isExtensible&&Object.getOwnPropertyDescriptor&&Object.defineProperty&&Object.defineProperties&&Object.seal&&Object.freeze&&Object.preventExtensions&&"JSON"in window&&"parse"in JSON&&"stringify"in JSON&&function(){if(!("Worker"in window&&"Blob"in window&&"URL"in window))return!1;var t,e,i=new Blob([""],{type:"text/javascript"}),n=URL.createObjectURL(i);try{e=new Worker(n),t=!0;}catch(e){t=!1;}e&&e.terminate();return URL.revokeObjectURL(n),t}()&&"Uint8ClampedArray"in window&&function(t){void 0===i[t]&&(i[t]=function(t){var i=document.createElement("canvas"),n=Object.create(e.webGLContextAttributes);return n.failIfMajorPerformanceCaveat=t,i.probablySupportsContext?i.probablySupportsContext("webgl",n)||i.probablySupportsContext("experimental-webgl",n):i.supportsContext?i.supportsContext("webgl",n)||i.supportsContext("experimental-webgl",n):i.getContext("webgl",n)||i.getContext("experimental-webgl",n)}(t));return i[t]}(t&&t.failIfMajorPerformanceCaveat))}t.exports?t.exports=e:window&&(window.mapboxgl=window.mapboxgl||{},window.mapboxgl.supported=e);var i={};e.webGLContextAttributes={antialias:!1,alpha:!0,stencil:!0,depth:!0};}),i=t.default.performance&&t.default.performance.now?t.default.performance.now.bind(t.default.performance):Date.now.bind(Date),n=t.default.requestAnimationFrame||t.default.mozRequestAnimationFrame||t.default.webkitRequestAnimationFrame||t.default.msRequestAnimationFrame,o=t.default.cancelAnimationFrame||t.default.mozCancelAnimationFrame||t.default.webkitCancelAnimationFrame||t.default.msCancelAnimationFrame,r={now:i,frame:function(t){return n(t)},cancelFrame:function(t){return o(t)},getImageData:function(e){var i=t.default.document.createElement("canvas"),n=i.getContext("2d");if(!n)throw new Error("failed to create canvas 2d context");return i.width=e.width,i.height=e.height,n.drawImage(e,0,0,e.width,e.height),n.getImageData(0,0,e.width,e.height)},hardwareConcurrency:t.default.navigator.hardwareConcurrency||4,get devicePixelRatio(){return t.default.devicePixelRatio},supportsWebp:!1};if(t.default.document){var a=t.default.document.createElement("img");a.onload=function(){r.supportsWebp=!0;},a.src="data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA=";}var s={create:function(e,i,n){var o=t.default.document.createElement(e);return i&&(o.className=i),n&&n.appendChild(o),o},createNS:function(e,i){return t.default.document.createElementNS(e,i)}},l=t.default.document?t.default.document.documentElement.style:null;function c(t){if(!l)return null;for(var e=0;e=0?0:e.button},s.remove=function(t){t.parentNode&&t.parentNode.removeChild(t);};var _={API_URL:"https://api.mapbox.com",REQUIRE_ACCESS_TOKEN:!0,ACCESS_TOKEN:null},g="See https://www.mapbox.com/api-documentation/#access-tokens";function v(t,e){var i=C(_.API_URL);if(t.protocol=i.protocol,t.authority=i.authority,"/"!==i.path&&(t.path=""+i.path+t.path),!_.REQUIRE_ACCESS_TOKEN)return S(t);if(!(e=e||_.ACCESS_TOKEN))throw new Error("An API access token is required to use Mapbox GL. "+g);if("s"===e[0])throw new Error("Use a public access token (pk.*) with Mapbox GL, not a secret access token (sk.*). "+g);return t.params.push("access_token="+e),S(t)}function y(t){return 0===t.indexOf("mapbox:")}var x=function(t,e){if(!y(t))return t;var i=C(t);return i.path="/fonts/v1"+i.path,v(i,e)},b=function(t,e){if(!y(t))return t;var i=C(t);return i.path="/v4/"+i.authority+".json",i.params.push("secure"),v(i,e)},w=function(t,e,i,n){var o=C(t);return y(t)?(o.path="/styles/v1"+o.path+"/sprite"+e+i,v(o,n)):(o.path+=""+e+i,S(o))},E=/(\.(png|jpg)\d*)(?=$)/,T=function(t,e,i){if(!e||!y(e))return t;var n=C(t),o=r.devicePixelRatio>=2||512===i?"@2x":"",a=r.supportsWebp?".webp":"$1";return n.path=n.path.replace(E,""+o+a),function(t){for(var e=0;e=0?1.2:1));}function O(t,e,i,n,o,r,a){for(var s=0;s65535)e(new Error("glyphs > 65535 not supported"));else{var l=r.requests[s];l||(l=r.requests[s]=[],N.loadGlyphRange(i,s,n.url,n.requestTransform,function(t,e){if(e)for(var i in e)r.glyphs[+i]=e[+i];for(var n=0,o=l;nthis.height)return t.warnOnce("LineAtlas out of space"),null;for(var r=0,a=0;a90||this.lat<-90)throw new Error("Invalid LngLat latitude value: must be between -90 and 90")};W.prototype.wrap=function(){return new W(t.wrap(this.lng,-180,180),this.lat)},W.prototype.toArray=function(){return[this.lng,this.lat]},W.prototype.toString=function(){return"LngLat("+this.lng+", "+this.lat+")"},W.prototype.toBounds=function(t){var e=360*t/40075017,i=e/Math.cos(Math.PI/180*this.lat);return new q(new W(this.lng-i,this.lat-e),new W(this.lng+i,this.lat+e))},W.convert=function(t){if(t instanceof W)return t;if(Array.isArray(t)&&(2===t.length||3===t.length))return new W(Number(t[0]),Number(t[1]));if(!Array.isArray(t)&&"object"==typeof t&&null!==t)return new W(Number(t.lng),Number(t.lat));throw new Error("`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, or an array of [, ]")};var q=function(t,e){t&&(e?this.setSouthWest(t).setNorthEast(e):4===t.length?this.setSouthWest([t[0],t[1]]).setNorthEast([t[2],t[3]]):this.setSouthWest(t[0]).setNorthEast(t[1]));};q.prototype.setNorthEast=function(t){return this._ne=t instanceof W?new W(t.lng,t.lat):W.convert(t),this},q.prototype.setSouthWest=function(t){return this._sw=t instanceof W?new W(t.lng,t.lat):W.convert(t),this},q.prototype.extend=function(t){var e,i,n=this._sw,o=this._ne;if(t instanceof W)e=t,i=t;else{if(!(t instanceof q))return Array.isArray(t)?t.every(Array.isArray)?this.extend(q.convert(t)):this.extend(W.convert(t)):this;if(e=t._sw,i=t._ne,!e||!i)return this}return n||o?(n.lng=Math.min(e.lng,n.lng),n.lat=Math.min(e.lat,n.lat),o.lng=Math.max(i.lng,o.lng),o.lat=Math.max(i.lat,o.lat)):(this._sw=new W(e.lng,e.lat),this._ne=new W(i.lng,i.lat)),this},q.prototype.getCenter=function(){return new W((this._sw.lng+this._ne.lng)/2,(this._sw.lat+this._ne.lat)/2)},q.prototype.getSouthWest=function(){return this._sw},q.prototype.getNorthEast=function(){return this._ne},q.prototype.getNorthWest=function(){return new W(this.getWest(),this.getNorth())},q.prototype.getSouthEast=function(){return new W(this.getEast(),this.getSouth())},q.prototype.getWest=function(){return this._sw.lng},q.prototype.getSouth=function(){return this._sw.lat},q.prototype.getEast=function(){return this._ne.lng},q.prototype.getNorth=function(){return this._ne.lat},q.prototype.toArray=function(){return[this._sw.toArray(),this._ne.toArray()]},q.prototype.toString=function(){return"LngLatBounds("+this._sw.toString()+", "+this._ne.toString()+")"},q.prototype.isEmpty=function(){return!(this._sw&&this._ne)},q.convert=function(t){return!t||t instanceof q?t:new q(t)};var X=function(t,e,i){this.bounds=q.convert(this.validateBounds(t)),this.minzoom=e||0,this.maxzoom=i||24;};X.prototype.validateBounds=function(t){return Array.isArray(t)&&4===t.length?[Math.max(-180,t[0]),Math.max(-90,t[1]),Math.min(180,t[2]),Math.min(90,t[3])]:[-180,-90,180,90]},X.prototype.contains=function(t){var e=Math.floor(this.lngX(this.bounds.getWest(),t.z)),i=Math.floor(this.latY(this.bounds.getNorth(),t.z)),n=Math.ceil(this.lngX(this.bounds.getEast(),t.z)),o=Math.ceil(this.latY(this.bounds.getSouth(),t.z));return t.x>=e&&t.x=i&&t.y0&&(l[new t.OverscaledTileID(e.overscaledZ,r,i.z,o,i.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,e.wrap,i.z,i.x,i.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,s,i.z,a,i.y-1).key]={backfilled:!1}),i.y+10&&(n.resourceTiming=e._resourceTiming,e._resourceTiming=[]),e.fire(new t.Event("data",n));}});},i.prototype.onAdd=function(t){this.map=t,this.load();},i.prototype.setData=function(e){var i=this;return this._data=e,this.fire(new t.Event("dataloading",{dataType:"source"})),this._updateWorkerData(function(e){if(e)return i.fire(new t.ErrorEvent(e));var n={dataType:"source",sourceDataType:"content"};i._collectResourceTiming&&i._resourceTiming&&i._resourceTiming.length>0&&(n.resourceTiming=i._resourceTiming,i._resourceTiming=[]),i.fire(new t.Event("data",n));}),this},i.prototype._updateWorkerData=function(e){var i,n,o=this,r=t.extend({},this.workerOptions),a=this._data;"string"==typeof a?(r.request=this.map._transformRequest((i=a,(n=t.default.document.createElement("a")).href=i,n.href),t.ResourceType.Source),r.request.collectResourceTiming=this._collectResourceTiming):r.data=JSON.stringify(a),this.workerID=this.dispatcher.send(this.type+"."+r.source+".loadData",r,function(t,i){o._removed||i&&i.abandoned||(o._loaded=!0,i&&i.resourceTiming&&i.resourceTiming[o.id]&&(o._resourceTiming=i.resourceTiming[o.id].slice(0)),o.dispatcher.send(o.type+"."+r.source+".coalesce",null,null,o.workerID),e(t));},this.workerID);},i.prototype.loadTile=function(t,e){var i=this,n=void 0===t.workerID?"loadTile":"reloadTile",o={type:this.type,uid:t.uid,tileID:t.tileID,zoom:t.tileID.overscaledZ,maxZoom:this.maxzoom,tileSize:this.tileSize,source:this.id,pixelRatio:r.devicePixelRatio,showCollisionBoxes:this.map.showCollisionBoxes};t.workerID=this.dispatcher.send(n,o,function(o,r){return t.unloadVectorData(),t.aborted?e(null):o?e(o):(t.loadVectorData(r,i.map.painter,"reloadTile"===n),e(null))},this.workerID);},i.prototype.abortTile=function(t){t.aborted=!0;},i.prototype.unloadTile=function(t){t.unloadVectorData(),this.dispatcher.send("removeTile",{uid:t.uid,type:this.type,source:this.id},null,t.workerID);},i.prototype.onRemove=function(){this._removed=!0,this.dispatcher.send("removeSource",{type:this.type,source:this.id},null,this.workerID);},i.prototype.serialize=function(){return t.extend({},this._options,{type:this.type,data:this._data})},i.prototype.hasTransition=function(){return!1},i}(t.Evented);var Q=t.createLayout([{name:"a_pos",type:"Int16",components:2},{name:"a_texture_pos",type:"Int16",components:2}]),tt=function(){this.boundProgram=null,this.boundLayoutVertexBuffer=null,this.boundPaintVertexBuffers=[],this.boundIndexBuffer=null,this.boundVertexOffset=null,this.boundDynamicVertexBuffer=null,this.vao=null;};tt.prototype.bind=function(t,e,i,n,o,r,a,s){this.context=t;for(var l=this.boundPaintVertexBuffers.length!==n.length,c=0;!l&&c>s.z,c=new t.default$1(s.x*l,s.y*l),u=new t.default$1(c.x+l,c.y+l),h=this.segments.prepareSegment(4,n,o);n.emplaceBack(c.x,c.y,c.x,c.y),n.emplaceBack(u.x,c.y,u.x,c.y),n.emplaceBack(c.x,u.y,c.x,u.y),n.emplaceBack(u.x,u.y,u.x,u.y);var p=h.vertexLength;o.emplaceBack(p,p+1,p+2),o.emplaceBack(p+1,p+2,p+3),h.vertexLength+=4,h.primitiveLength+=2;}this.maskedBoundsBuffer=i.createVertexBuffer(n,Q.members),this.maskedIndexBuffer=i.createIndexBuffer(o);}},lt.prototype.hasData=function(){return"loaded"===this.state||"reloading"===this.state||"expired"===this.state},lt.prototype.setExpiryData=function(e){var i=this.expirationTime;if(e.cacheControl){var n=t.parseCacheControl(e.cacheControl);n["max-age"]&&(this.expirationTime=Date.now()+1e3*n["max-age"]);}else e.expires&&(this.expirationTime=new Date(e.expires).getTime());if(this.expirationTime){var o=Date.now(),r=!1;if(this.expirationTime>o)r=!1;else if(i)if(this.expirationTimethis.max){var a=this._getAndRemoveByKey(this.order[0]);a&&this.onRemove(a);}return this},ct.prototype.has=function(t){return t.wrapped().key in this.data},ct.prototype.getAndRemove=function(t){return this.has(t)?this._getAndRemoveByKey(t.wrapped().key):null},ct.prototype._getAndRemoveByKey=function(t){var e=this.data[t].shift();return e.timeout&&clearTimeout(e.timeout),0===this.data[t].length&&delete this.data[t],this.order.splice(this.order.indexOf(t),1),e.value},ct.prototype.get=function(t){return this.has(t)?this.data[t.wrapped().key][0].value:null},ct.prototype.remove=function(t,e){if(!this.has(t))return this;var i=t.wrapped().key,n=void 0===e?0:this.data[i].indexOf(e),o=this.data[i][n];return this.data[i].splice(n,1),o.timeout&&clearTimeout(o.timeout),0===this.data[i].length&&delete this.data[i],this.onRemove(o.value),this.order.splice(this.order.indexOf(i),1),this},ct.prototype.setMaxSize=function(t){for(this.max=t;this.order.length>this.max;){var e=this._getAndRemoveByKey(this.order[0]);e&&this.onRemove(e);}return this};var ut=function(t,e,i){this.context=t;var n=t.gl;this.buffer=n.createBuffer(),this.dynamicDraw=Boolean(i),this.unbindVAO(),t.bindElementBuffer.set(this.buffer),n.bufferData(n.ELEMENT_ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?n.DYNAMIC_DRAW:n.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer;};ut.prototype.unbindVAO=function(){this.context.extVertexArrayObject&&this.context.bindVertexArrayOES.set(null);},ut.prototype.bind=function(){this.context.bindElementBuffer.set(this.buffer);},ut.prototype.updateData=function(t){var e=this.context.gl;this.unbindVAO(),this.bind(),e.bufferSubData(e.ELEMENT_ARRAY_BUFFER,0,t.arrayBuffer);},ut.prototype.destroy=function(){var t=this.context.gl;this.buffer&&(t.deleteBuffer(this.buffer),delete this.buffer);};var ht={Int8:"BYTE",Uint8:"UNSIGNED_BYTE",Int16:"SHORT",Uint16:"UNSIGNED_SHORT",Int32:"INT",Uint32:"UNSIGNED_INT",Float32:"FLOAT"},pt=function(t,e,i,n){this.length=e.length,this.attributes=i,this.itemSize=e.bytesPerElement,this.dynamicDraw=n,this.context=t;var o=t.gl;this.buffer=o.createBuffer(),t.bindVertexBuffer.set(this.buffer),o.bufferData(o.ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?o.DYNAMIC_DRAW:o.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer;};pt.prototype.bind=function(){this.context.bindVertexBuffer.set(this.buffer);},pt.prototype.updateData=function(t){var e=this.context.gl;this.bind(),e.bufferSubData(e.ARRAY_BUFFER,0,t.arrayBuffer);},pt.prototype.enableAttributes=function(t,e){for(var i=0;i1||(Math.abs(i)>1&&(1===Math.abs(i+o)?i+=o:1===Math.abs(i-o)&&(i-=o)),e.dem&&t.dem&&(t.dem.backfillBorder(e.dem,i,n),t.neighboringTiles&&t.neighboringTiles[r]&&(t.neighboringTiles[r].backfilled=!0)));}},i.prototype.getTile=function(t){return this.getTileByID(t.key)},i.prototype.getTileByID=function(t){return this._tiles[t]},i.prototype.getZoom=function(t){return t.zoom+t.scaleZoom(t.tileSize/this._source.tileSize)},i.prototype._findLoadedChildren=function(t,e,i){var n=!1;for(var o in this._tiles){var r=this._tiles[o];if(!(i[o]||!r.hasData()||r.tileID.overscaledZ<=t.overscaledZ||r.tileID.overscaledZ>e)){var a=Math.pow(2,r.tileID.canonical.z-t.canonical.z);if(Math.floor(r.tileID.canonical.x/a)===t.canonical.x&&Math.floor(r.tileID.canonical.y/a)===t.canonical.y)for(i[o]=r.tileID,n=!0;r&&r.tileID.overscaledZ-1>t.overscaledZ;){var s=r.tileID.scaledTo(r.tileID.overscaledZ-1);if(!s)break;(r=this._tiles[s.key])&&r.hasData()&&(delete i[o],i[s.key]=s);}}}return n},i.prototype.findLoadedParent=function(t,e,i){for(var n=t.overscaledZ-1;n>=e;n--){var o=t.scaledTo(n);if(!o)return;var r=String(o.key),a=this._tiles[r];if(a&&a.hasData())return i[r]=o,a;if(this._cache.has(o))return i[r]=o,this._cache.get(o)}},i.prototype.updateCacheSize=function(t){var e=(Math.ceil(t.width/this._source.tileSize)+1)*(Math.ceil(t.height/this._source.tileSize)+1),i=Math.floor(5*e),n="number"==typeof this._maxTileCacheSize?Math.min(this._maxTileCacheSize,i):i;this._cache.setMaxSize(n);},i.prototype.handleWrapJump=function(t){var e=(t-(void 0===this._prevLng?t:this._prevLng))/360,i=Math.round(e);if(this._prevLng=t,i){var n={};for(var o in this._tiles){var r=this._tiles[o];r.tileID=r.tileID.unwrapTo(r.tileID.wrap+i),n[r.tileID.key]=r;}for(var a in this._tiles=n,this._timers)clearTimeout(this._timers[a]),delete this._timers[a];for(var s in this._tiles){var l=this._tiles[s];this._setTileReloadTimer(s,l);}}},i.prototype.update=function(e){var n=this;if(this.transform=e,this._sourceLoaded&&!this._paused){var o;this.updateCacheSize(e),this.handleWrapJump(this.transform.center.lng),this._coveredTiles={},this.used?this._source.tileID?o=e.getVisibleUnwrappedCoordinates(this._source.tileID).map(function(e){return new t.OverscaledTileID(e.canonical.z,e.wrap,e.canonical.z,e.canonical.x,e.canonical.y)}):(o=e.coveringTiles({tileSize:this._source.tileSize,minzoom:this._source.minzoom,maxzoom:this._source.maxzoom,roundZoom:this._source.roundZoom,reparseOverscaled:this._source.reparseOverscaled}),this._source.hasTile&&(o=o.filter(function(t){return n._source.hasTile(t)}))):o=[];var a,s=(this._source.roundZoom?Math.round:Math.floor)(this.getZoom(e)),l=Math.max(s-i.maxOverzooming,this._source.minzoom),c=Math.max(s+i.maxUnderzooming,this._source.minzoom),u=this._updateRetainedTiles(o,s),h={};if(Kt(this._source.type))for(var p=Object.keys(u),d=0;d=r.now())){n._findLoadedChildren(m,c,u)&&(u[f]=m);var g=n.findLoadedParent(m,l,h);g&&n._addTile(g.tileID);}}for(a in h)u[a]||(n._coveredTiles[a]=!0);for(a in h)u[a]=h[a];for(var v=t.keysDifference(this._tiles,u),y=0;ythis._source.maxzoom){var p=l.children(this._source.maxzoom)[0],d=this.getTile(p);d&&d.hasData()?n[p.key]=p:h=!1;}else{this._findLoadedChildren(l,a,n);for(var f=l.children(this._source.maxzoom),m=0;m=r;--_){var g=l.scaledTo(_);if(o[g.key])break;if(o[g.key]=!0,!(c=this.getTile(g))&&u&&(c=this._addTile(g)),c&&(n[g.key]=g,u=c.wasRequested(),c.hasData()))break}}}return n},i.prototype._addTile=function(e){var i=this._tiles[e.key];if(i)return i;(i=this._cache.getAndRemove(e))&&(this._setTileReloadTimer(e.key,i),i.tileID=e);var n=Boolean(i);return n||(i=new lt(e,this._source.tileSize*e.overscaleFactor()),this._loadTile(i,this._tileLoaded.bind(this,i,e.key,i.state))),i?(i.uses++,this._tiles[e.key]=i,n||this._source.fire(new t.Event("dataloading",{tile:i,coord:i.tileID,dataType:"source"})),i):null},i.prototype._setTileReloadTimer=function(t,e){var i=this;t in this._timers&&(clearTimeout(this._timers[t]),delete this._timers[t]);var n=e.getExpiryTimeout();n&&(this._timers[t]=setTimeout(function(){i._reloadTile(t,"expired"),delete i._timers[t];},n));},i.prototype._removeTile=function(t){var e=this._tiles[t];e&&(e.uses--,delete this._tiles[t],this._timers[t]&&(clearTimeout(this._timers[t]),delete this._timers[t]),e.uses>0||(e.hasData()?this._cache.add(e.tileID,e,e.getExpiryTimeout()):(e.aborted=!0,this._abortTile(e),this._unloadTile(e))));},i.prototype.clearTiles=function(){for(var t in this._shouldReloadOnResume=!1,this._paused=!1,this._tiles)this._removeTile(t);this._cache.reset();},i.prototype.tilesIn=function(e,i){for(var n=[],o=this.getIds(),r=1/0,a=1/0,s=-1/0,l=-1/0,c=e[0].zoom,u=0;u=0&&g[1].y+_>=0){for(var v=[],y=0;y=r.now())return!0}return!1},i}(t.Evented);function Ht(e,i){var n=i.zoomTo(e.canonical.z);return new t.default$1((n.column-(e.canonical.x+e.wrap*Math.pow(2,e.canonical.z)))*t.default$8,(n.row-e.canonical.y)*t.default$8)}function Kt(t){return"raster"===t||"image"===t||"video"===t}function Yt(){return new t.default.Worker(Rn.workerUrl)}Xt.maxOverzooming=10,Xt.maxUnderzooming=3;var Jt,Qt=function(){this.active={};};function te(e,i){var n={};for(var o in e)"ref"!==o&&(n[o]=e[o]);return t.default$18.forEach(function(t){t in i&&(n[t]=i[t]);}),n}function ee(t){t=t.slice();for(var e=Object.create(null),i=0;ithis.width||n<0||e>this.height)return!o&&[];var r=[];if(t<=0&&e<=0&&this.width<=i&&this.height<=n){if(o)return!0;for(var a=0;a0:r},he.prototype._queryCircle=function(t,e,i,n){var o=t-i,r=t+i,a=e-i,s=e+i;if(r<0||o>this.width||s<0||a>this.height)return!n&&[];var l=[],c={hitTest:n,circle:{x:t,y:e,radius:i},seenUids:{box:{},circle:{}}};return this._forEachCell(o,a,r,s,this._queryCellCircle,l,c),n?l.length>0:l},he.prototype.query=function(t,e,i,n){return this._query(t,e,i,n,!1)},he.prototype.hitTest=function(t,e,i,n){return this._query(t,e,i,n,!0)},he.prototype.hitTestCircle=function(t,e,i){return this._queryCircle(t,e,i,!0)},he.prototype._queryCell=function(t,e,i,n,o,r,a){var s=a.seenUids,l=this.boxCells[o];if(null!==l)for(var c=this.bboxes,u=0,h=l;u=c[d+0]&&n>=c[d+1]){if(a.hitTest)return r.push(!0),!0;r.push({key:this.boxKeys[p],x1:c[d],y1:c[d+1],x2:c[d+2],y2:c[d+3]});}}}var f=this.circleCells[o];if(null!==f)for(var m=this.circles,_=0,g=f;_a*a+s*s},he.prototype._circleAndRectCollide=function(t,e,i,n,o,r,a){var s=(r-n)/2,l=Math.abs(t-(n+s));if(l>s+i)return!1;var c=(a-o)/2,u=Math.abs(e-(o+c));if(u>c+i)return!1;if(l<=s||u<=c)return!0;var h=l-s,p=u-c;return h*h+p*p<=i*i};var pe=t.default$19.layout;function de(e,i,n,o,r){var a=t.mat4.identity(new Float32Array(16));return i?(t.mat4.identity(a),t.mat4.scale(a,a,[1/r,1/r,1]),n||t.mat4.rotateZ(a,a,o.angle)):(t.mat4.scale(a,a,[o.width/2,-o.height/2,1]),t.mat4.translate(a,a,[1,-1,0]),t.mat4.multiply(a,a,e)),a}function fe(e,i,n,o,r){var a=t.mat4.identity(new Float32Array(16));return i?(t.mat4.multiply(a,a,e),t.mat4.scale(a,a,[r,r,1]),n||t.mat4.rotateZ(a,a,-o.angle)):(t.mat4.scale(a,a,[1,-1,1]),t.mat4.translate(a,a,[-1,-1,0]),t.mat4.scale(a,a,[2/o.width,2/o.height,1])),a}function me(e,i){var n=[e.x,e.y,0,1];Ie(n,n,i);var o=n[3];return{point:new t.default$1(n[0]/o,n[1]/o),signedDistanceFromCamera:o}}function _e(t,e){var i=t[0]/t[3],n=t[1]/t[3];return i>=-e[0]&&i<=e[0]&&n>=-e[1]&&n<=e[1]}function ge(e,i,n,o,r,a,s,l){var c=o?e.textSizeData:e.iconSizeData,u=t.evaluateSizeForZoom(c,n.transform.zoom,pe.properties[o?"text-size":"icon-size"]),h=[256/n.width*2+1,256/n.height*2+1],p=o?e.text.dynamicLayoutVertexArray:e.icon.dynamicLayoutVertexArray;p.clear();for(var d=e.lineVertexArray,f=o?e.text.placedSymbolArray:e.icon.placedSymbolArray,m=n.transform.width/n.transform.height,_=!1,g=0;gMath.abs(n.x-i.x)*o)return{useVertical:!0};return(e===t.WritingMode.vertical?i.yn.x)?{needsFlipping:!0}:null}function xe(e,i,n,o,r,a,s,l,c,u,h,p,d,f){var m,_=i/24,g=e.lineOffsetX*i,v=e.lineOffsetY*i;if(e.numGlyphs>1){var y=e.glyphStartIndex+e.numGlyphs,x=e.lineStartIndex,b=e.lineStartIndex+e.lineLength,w=ve(_,l,g,v,n,h,p,e,c,a,d,!1);if(!w)return{notEnoughRoom:!0};var E=me(w.first.point,s).point,T=me(w.last.point,s).point;if(o&&!n){var I=ye(e.writingMode,E,T,f);if(I)return I}m=[w.first];for(var C=e.glyphStartIndex+1;C0?R.point:be(p,A,S,1,r),M=ye(e.writingMode,S,D,f);if(M)return M}var L=we(_*l.getoffsetX(e.glyphStartIndex),g,v,n,h,p,e.segment,e.lineStartIndex,e.lineStartIndex+e.lineLength,c,a,d,!1);if(!L)return{notEnoughRoom:!0};m=[L];}for(var P=0,k=m;P0?1:-1,_=0;o&&(m*=-1,_=Math.PI),m<0&&(_+=Math.PI);for(var g=m>0?l+s:l+s+1,v=g,y=r,x=r,b=0,w=0,E=Math.abs(f);b+w<=E;){if((g+=m)=c)return null;if(x=y,void 0===(y=p[g])){var T=new t.default$1(u.getx(g),u.gety(g)),I=me(T,h);if(I.signedDistanceFromCamera>0)y=p[g]=I.point;else{var C=g-m;y=be(0===b?a:new t.default$1(u.getx(C),u.gety(C)),T,x,E-b+1,h);}}b+=w,w=x.dist(y);}var S=(E-b)/w,z=y.sub(x),A=z.mult(S)._add(x);return A._add(z._unit()._perp()._mult(n*m)),{point:A,angle:_+Math.atan2(y.y-x.y,y.x-x.x),tileDistance:d?{prevTileDistance:g-m===v?0:u.gettileUnitDistanceFromAnchor(g-m),lastSegmentViewportDistance:E-b}:null}}var Ee=new Float32Array([-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0]);function Te(t,e){for(var i=0;iC)Se(e,S,!1);else{var M=this.projectPoint(u,z,A),L=R*E;if(f.length>0){var P=M.x-f[f.length-4],k=M.y-f[f.length-3];if(L*L*2>P*P+k*k)if(S+8-I&&B=this.screenRightBoundary||n<100||e>this.screenBottomBoundary};var Ae=t.default$19.layout,Re=function(t,e,i,n){this.opacity=t?Math.max(0,Math.min(1,t.opacity+(t.placed?e:-e))):n&&i?1:0,this.placed=i;};Re.prototype.isHidden=function(){return 0===this.opacity&&!this.placed};var De=function(t,e,i,n,o){this.text=new Re(t?t.text:null,e,i,o),this.icon=new Re(t?t.icon:null,e,n,o);};De.prototype.isHidden=function(){return this.text.isHidden()&&this.icon.isHidden()};var Me=function(t,e,i){this.text=t,this.icon=e,this.skipFade=i;},Le=function(t,e){this.transform=t.clone(),this.collisionIndex=new Ce(this.transform),this.placements={},this.opacities={},this.stale=!1,this.fadeDuration=e,this.retainedQueryData={};};function Pe(t,e,i){t.emplaceBack(e?1:0,i?1:0),t.emplaceBack(e?1:0,i?1:0),t.emplaceBack(e?1:0,i?1:0),t.emplaceBack(e?1:0,i?1:0);}Le.prototype.placeLayerTile=function(e,i,n,o){var r=i.getBucket(e),a=i.latestFeatureIndex;if(r&&a&&e.id===r.layerIds[0]){var s=i.collisionBoxArray,l=r.layers[0].layout,c=Math.pow(2,this.transform.zoom-i.tileID.overscaledZ),u=i.tileSize/t.default$8,h=this.transform.calculatePosMatrix(i.tileID.toUnwrapped()),p=de(h,"map"===l.get("text-pitch-alignment"),"map"===l.get("text-rotation-alignment"),this.transform,ze(i,1,this.transform.zoom)),d=de(h,"map"===l.get("icon-pitch-alignment"),"map"===l.get("icon-rotation-alignment"),this.transform,ze(i,1,this.transform.zoom));this.retainedQueryData[r.bucketInstanceId]=new function(t,e,i,n,o){this.bucketInstanceId=t,this.featureIndex=e,this.sourceLayerIndex=i,this.bucketIndex=n,this.tileID=o;}(r.bucketInstanceId,a,r.sourceLayerIndex,r.index,i.tileID),this.placeLayerBucket(r,h,p,d,c,u,n,o,s);}},Le.prototype.placeLayerBucket=function(e,i,n,o,r,a,s,l,c){for(var u=e.layers[0].layout,h=t.evaluateSizeForZoom(e.textSizeData,this.transform.zoom,Ae.properties["text-size"]),p=!e.hasTextData()||u.get("text-optional"),d=!e.hasIconData()||u.get("icon-optional"),f=0,m=e.symbolInstances;f0,y=y&&x.offscreen);var I=_.collisionArrays.textCircles;if(I){var C=e.text.placedSymbolArray.get(_.placedTextSymbolIndices[0]),S=t.evaluateSizeForFeature(e.textSizeData,h,C);b=this.collisionIndex.placeCollisionCircles(I,u.get("text-allow-overlap"),r,a,_.key,C,e.lineVertexArray,e.glyphOffsetArray,S,i,n,s,"map"===u.get("text-pitch-alignment")),g=u.get("text-allow-overlap")||b.circles.length>0,y=y&&b.offscreen;}_.collisionArrays.iconFeatureIndex&&(T=_.collisionArrays.iconFeatureIndex),_.collisionArrays.iconBox&&(v=(w=this.collisionIndex.placeCollisionBox(_.collisionArrays.iconBox,u.get("icon-allow-overlap"),a,i)).box.length>0,y=y&&w.offscreen),p||d?d?p||(v=v&&g):g=v&&g:v=g=v&&g,g&&x&&this.collisionIndex.insertCollisionBox(x.box,u.get("text-ignore-placement"),e.bucketInstanceId,E),v&&w&&this.collisionIndex.insertCollisionBox(w.box,u.get("icon-ignore-placement"),e.bucketInstanceId,T),g&&b&&this.collisionIndex.insertCollisionCircles(b.circles,u.get("text-ignore-placement"),e.bucketInstanceId,E),this.placements[_.crossTileID]=new Me(g,v,y||e.justReloaded),l[_.crossTileID]=!0;}}e.justReloaded=!1;},Le.prototype.commit=function(t,e){this.commitTime=e;var i=!1,n=t&&0!==this.fadeDuration?(this.commitTime-t.commitTime)/this.fadeDuration:1,o=t?t.opacities:{};for(var r in this.placements){var a=this.placements[r],s=o[r];s?(this.opacities[r]=new De(s,n,a.text,a.icon),i=i||a.text!==s.text.placed||a.icon!==s.icon.placed):(this.opacities[r]=new De(null,n,a.text,a.icon,a.skipFade),i=i||a.text||a.icon);}for(var l in o){var c=o[l];if(!this.opacities[l]){var u=new De(c,n,!1,!1);u.isHidden()||(this.opacities[l]=u,i=i||c.text.placed||c.icon.placed);}}i?this.lastPlacementChangeTime=e:"number"!=typeof this.lastPlacementChangeTime&&(this.lastPlacementChangeTime=t?t.lastPlacementChangeTime:e);},Le.prototype.updateLayerOpacities=function(t,e){for(var i={},n=0,o=e;n0||s.numVerticalGlyphVertices>0,h=s.numIconVertices>0;if(u){for(var p=Ve(c.text),d=(s.numGlyphVertices+s.numVerticalGlyphVertices)/4,f=0;ft},Le.prototype.setStale=function(){this.stale=!0;};var ke=Math.pow(2,25),Be=Math.pow(2,24),Oe=Math.pow(2,17),Fe=Math.pow(2,16),Ne=Math.pow(2,9),Ue=Math.pow(2,8),Ze=Math.pow(2,1);function Ve(t){if(0===t.opacity&&!t.placed)return 0;if(1===t.opacity&&t.placed)return 4294967295;var e=t.placed?1:0,i=Math.floor(127*t.opacity);return i*ke+e*Be+i*Oe+e*Fe+i*Ne+e*Ue+i*Ze+e}var je=function(){this._currentTileIndex=0,this._seenCrossTileIDs={};};je.prototype.continuePlacement=function(t,e,i,n,o){for(;this._currentTileIndex2};this._currentPlacementIndex>=0;){var s=e[t[n._currentPlacementIndex]],l=n.placement.collisionIndex.transform.zoom;if("symbol"===s.type&&(!s.minzoom||s.minzoom<=l)&&(!s.maxzoom||s.maxzoom>l)){if(n._inProgressLayer||(n._inProgressLayer=new je),n._inProgressLayer.continuePlacement(i[s.source],n.placement,n._showCollisionBoxes,s,a))return;delete n._inProgressLayer;}n._currentPlacementIndex--;}this._done=!0;},$e.prototype.commit=function(t,e){return this.placement.commit(t,e),this.placement};var Ge=512/t.default$8/2,We=function(t,e,i){this.tileID=t,this.indexedSymbolInstances={},this.bucketInstanceId=i;for(var n=0,o=e;nt.overscaledZ)for(var l in s){var c=s[l];c.tileID.isChildOf(t)&&c.findMatches(e.symbolInstances,t,r);}else{var u=s[t.scaledTo(Number(a)).key];u&&u.findMatches(e.symbolInstances,t,r);}}for(var h=0,p=e.symbolInstances;h1?"@2x":"";function c(){if(s)n(s);else if(o&&a){var e=r.getImageData(a),i={};for(var l in o){var c=o[l],u=c.width,h=c.height,p=c.x,d=c.y,f=c.sdf,m=c.pixelRatio,_=new t.RGBAImage({width:u,height:h});t.RGBAImage.copy(e,_,{x:p,y:d},{x:0,y:0},{width:u,height:h}),i[l]={data:_,pixelRatio:m,sdf:f};}n(null,i);}}t.getJSON(i(w(e,l,".json"),t.ResourceType.SpriteJSON),function(t,e){s||(s=t,o=e,c());}),t.getImage(i(w(e,l,".png"),t.ResourceType.SpriteImage),function(t,e){s||(s=t,a=e,c());});}(e.sprite,this.map._transformRequest,function(e,i){if(e)n.fire(new t.ErrorEvent(e));else if(i)for(var o in i)n.imageManager.addImage(o,i[o]);n.imageManager.setLoaded(!0),n.fire(new t.Event("data",{dataType:"style"}));}):this.imageManager.setLoaded(!0),this.glyphManager.setURL(e.glyphs);var a=ee(this.stylesheet.layers);this._order=a.map(function(t){return t.id}),this._layers={};for(var s=0,l=a;s0)throw new Error("Unimplemented: "+o.map(function(t){return t.command}).join(", ")+".");return n.forEach(function(t){"setTransition"!==t.command&&i[t.command].apply(i,t.args);}),this.stylesheet=e,!0},i.prototype.addImage=function(e,i){if(this.getImage(e))return this.fire(new t.ErrorEvent(new Error("An image with this name already exists.")));this.imageManager.addImage(e,i),this.fire(new t.Event("data",{dataType:"style"}));},i.prototype.getImage=function(t){return this.imageManager.getImage(t)},i.prototype.removeImage=function(e){if(!this.getImage(e))return this.fire(new t.ErrorEvent(new Error("No image with this name exists.")));this.imageManager.removeImage(e),this.fire(new t.Event("data",{dataType:"style"}));},i.prototype.addSource=function(e,i,n){var o=this;if(this._checkLoaded(),void 0!==this.sourceCaches[e])throw new Error("There is already a source with this ID");if(!i.type)throw new Error("The type property must be defined, but the only the following properties were given: "+Object.keys(i).join(", ")+".");if(!(["vector","raster","geojson","video","image"].indexOf(i.type)>=0)||!this._validate(t.validateStyle.source,"sources."+e,i,null,n)){this.map&&this.map._collectResourceTiming&&(i.collectResourceTiming=!0);var r=this.sourceCaches[e]=new Xt(e,i,this.dispatcher);r.style=this,r.setEventedParent(this,function(){return{isSourceLoaded:o.loaded(),source:r.serialize(),sourceId:e}}),r.onAdd(this.map),this._changed=!0;}},i.prototype.removeSource=function(e){if(this._checkLoaded(),void 0===this.sourceCaches[e])throw new Error("There is no source with this ID");for(var i in this._layers)if(this._layers[i].source===e)return this.fire(new t.ErrorEvent(new Error('Source "'+e+'" cannot be removed while layer "'+i+'" is using it.')));var n=this.sourceCaches[e];delete this.sourceCaches[e],delete this._updatedSources[e],n.fire(new t.Event("data",{sourceDataType:"metadata",dataType:"source",sourceId:e})),n.setEventedParent(null),n.clearTiles(),n.onRemove&&n.onRemove(this.map),this._changed=!0;},i.prototype.setGeoJSONSourceData=function(t,e){this._checkLoaded(),this.sourceCaches[t].getSource().setData(e),this._changed=!0;},i.prototype.getSource=function(t){return this.sourceCaches[t]&&this.sourceCaches[t].getSource()},i.prototype.addLayer=function(e,i,n){this._checkLoaded();var o=e.id;if(this.getLayer(o))this.fire(new t.ErrorEvent(new Error('Layer with id "'+o+'" already exists on this map')));else if("object"==typeof e.source&&(this.addSource(o,e.source),e=t.clone(e),e=t.extend(e,{source:o})),!this._validate(t.validateStyle.layer,"layers."+o,e,{arrayIndex:-1},n)){var r=t.default$22(e);this._validateLayer(r),r.setEventedParent(this,{layer:{id:o}});var a=i?this._order.indexOf(i):this._order.length;if(i&&-1===a)this.fire(new t.ErrorEvent(new Error('Layer with id "'+i+'" does not exist on this map.')));else{if(this._order.splice(a,0,o),this._layerOrderChanged=!0,this._layers[o]=r,this._removedLayers[o]&&r.source){var s=this._removedLayers[o];delete this._removedLayers[o],s.type!==r.type?this._updatedSources[r.source]="clear":(this._updatedSources[r.source]="reload",this.sourceCaches[r.source].pause());}this._updateLayer(r);}}},i.prototype.moveLayer=function(e,i){if(this._checkLoaded(),this._changed=!0,this._layers[e]){if(e!==i){var n=this._order.indexOf(e);this._order.splice(n,1);var o=i?this._order.indexOf(i):this._order.length;i&&-1===o?this.fire(new t.ErrorEvent(new Error('Layer with id "'+i+'" does not exist on this map.'))):(this._order.splice(o,0,e),this._layerOrderChanged=!0);}}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be moved.")));},i.prototype.removeLayer=function(e){this._checkLoaded();var i=this._layers[e];if(i){i.setEventedParent(null);var n=this._order.indexOf(e);this._order.splice(n,1),this._layerOrderChanged=!0,this._changed=!0,this._removedLayers[e]=i,delete this._layers[e],delete this._updatedLayers[e],delete this._updatedPaintProps[e];}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be removed.")));},i.prototype.getLayer=function(t){return this._layers[t]},i.prototype.setLayerZoomRange=function(e,i,n){this._checkLoaded();var o=this.getLayer(e);o?o.minzoom===i&&o.maxzoom===n||(null!=i&&(o.minzoom=i),null!=n&&(o.maxzoom=n),this._updateLayer(o)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot have zoom extent.")));},i.prototype.setFilter=function(e,i){this._checkLoaded();var n=this.getLayer(e);if(n){if(!t.default$10(n.filter,i))return null==i?(n.filter=void 0,void this._updateLayer(n)):void(this._validate(t.validateStyle.filter,"layers."+n.id+".filter",i)||(n.filter=t.clone(i),this._updateLayer(n)))}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be filtered.")));},i.prototype.getFilter=function(e){return t.clone(this.getLayer(e).filter)},i.prototype.setLayoutProperty=function(e,i,n){this._checkLoaded();var o=this.getLayer(e);o?t.default$10(o.getLayoutProperty(i),n)||(o.setLayoutProperty(i,n),this._updateLayer(o)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")));},i.prototype.getLayoutProperty=function(t,e){return this.getLayer(t).getLayoutProperty(e)},i.prototype.setPaintProperty=function(e,i,n){this._checkLoaded();var o=this.getLayer(e);if(o){if(!t.default$10(o.getPaintProperty(i),n)){var r=o._transitionablePaint._values[i].value.isDataDriven();o.setPaintProperty(i,n),(o._transitionablePaint._values[i].value.isDataDriven()||r)&&this._updateLayer(o),this._changed=!0,this._updatedPaintProps[e]=!0;}}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")));},i.prototype.getPaintProperty=function(t,e){return this.getLayer(t).getPaintProperty(e)},i.prototype.getTransition=function(){return t.extend({duration:300,delay:0},this.stylesheet&&this.stylesheet.transition)},i.prototype.serialize=function(){var e=this;return t.filterObject({version:this.stylesheet.version,name:this.stylesheet.name,metadata:this.stylesheet.metadata,light:this.stylesheet.light,center:this.stylesheet.center,zoom:this.stylesheet.zoom,bearing:this.stylesheet.bearing,pitch:this.stylesheet.pitch,sprite:this.stylesheet.sprite,glyphs:this.stylesheet.glyphs,transition:this.stylesheet.transition,sources:t.mapObject(this.sourceCaches,function(t){return t.serialize()}),layers:this._order.map(function(t){return e._layers[t].serialize()})},function(t){return void 0!==t})},i.prototype._updateLayer=function(t){this._updatedLayers[t.id]=!0,t.source&&!this._updatedSources[t.source]&&(this._updatedSources[t.source]="reload",this.sourceCaches[t.source].pause()),this._changed=!0;},i.prototype._flattenRenderedFeatures=function(t){for(var e=[],i=this._order.length-1;i>=0;i--)for(var n=this._order[i],o=0,r=t;o 0.5) {\n gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5) * alpha;\n }\n\n if (v_notUsed > 0.5) {\n // This box not used, fade it out\n gl_FragColor *= .1;\n }\n}",vertexSource:"attribute vec2 a_pos;\nattribute vec2 a_anchor_pos;\nattribute vec2 a_extrude;\nattribute vec2 a_placed;\n\nuniform mat4 u_matrix;\nuniform vec2 u_extrude_scale;\nuniform float u_camera_to_center_distance;\n\nvarying float v_placed;\nvarying float v_notUsed;\n\nvoid main() {\n vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n highp float collision_perspective_ratio = clamp(\n 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),\n 0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles\n 4.0);\n\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio;\n\n v_placed = a_placed.x;\n v_notUsed = a_placed.y;\n}\n"},collisionCircle:{fragmentSource:"uniform float u_overscale_factor;\n\nvarying float v_placed;\nvarying float v_notUsed;\nvarying float v_radius;\nvarying vec2 v_extrude;\nvarying vec2 v_extrude_scale;\n\nvoid main() {\n float alpha = 0.5;\n\n // Red = collision, hide label\n vec4 color = vec4(1.0, 0.0, 0.0, 1.0) * alpha;\n\n // Blue = no collision, label is showing\n if (v_placed > 0.5) {\n color = vec4(0.0, 0.0, 1.0, 0.5) * alpha;\n }\n\n if (v_notUsed > 0.5) {\n // This box not used, fade it out\n color *= .2;\n }\n\n float extrude_scale_length = length(v_extrude_scale);\n float extrude_length = length(v_extrude) * extrude_scale_length;\n float stroke_width = 15.0 * extrude_scale_length / u_overscale_factor;\n float radius = v_radius * extrude_scale_length;\n\n float distance_to_edge = abs(extrude_length - radius);\n float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge);\n\n gl_FragColor = opacity_t * color;\n}\n",vertexSource:"attribute vec2 a_pos;\nattribute vec2 a_anchor_pos;\nattribute vec2 a_extrude;\nattribute vec2 a_placed;\n\nuniform mat4 u_matrix;\nuniform vec2 u_extrude_scale;\nuniform float u_camera_to_center_distance;\n\nvarying float v_placed;\nvarying float v_notUsed;\nvarying float v_radius;\n\nvarying vec2 v_extrude;\nvarying vec2 v_extrude_scale;\n\nvoid main() {\n vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n highp float collision_perspective_ratio = clamp(\n 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),\n 0.0, // Prevents oversized near-field circles in pitched/overzoomed tiles\n 4.0);\n\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n\n highp float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur\n gl_Position.xy += a_extrude * u_extrude_scale * padding_factor * gl_Position.w * collision_perspective_ratio;\n\n v_placed = a_placed.x;\n v_notUsed = a_placed.y;\n v_radius = abs(a_extrude.y); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius\n\n v_extrude = a_extrude * padding_factor;\n v_extrude_scale = u_extrude_scale * u_camera_to_center_distance * collision_perspective_ratio;\n}\n"},debug:{fragmentSource:"uniform highp vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n"},fill:{fragmentSource:"#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float opacity\n\n gl_FragColor = color * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n"},fillOutline:{fragmentSource:"#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_pos;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 outline_color\n #pragma mapbox: initialize lowp float opacity\n\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = 1.0 - smoothstep(0.0, 1.0, dist);\n gl_FragColor = outline_color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 outline_color\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world;\n}\n"},fillOutlinePattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec2 v_pos;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n // find distance to outline for alpha interpolation\n\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = 1.0 - smoothstep(0.0, 1.0, dist);\n\n\n gl_FragColor = mix(color1, color2, u_mix) * alpha * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_world;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\n\nattribute vec2 a_pos;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec2 v_pos;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);\n\n v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world;\n}\n"},fillPattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n gl_FragColor = mix(color1, color2, u_mix) * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\n\nattribute vec2 a_pos;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);\n}\n"},fillExtrusion:{fragmentSource:"varying vec4 v_color;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define highp vec4 color\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n #pragma mapbox: initialize highp vec4 color\n\n gl_FragColor = v_color;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec3 u_lightcolor;\nuniform lowp vec3 u_lightpos;\nuniform lowp float u_lightintensity;\n\nattribute vec2 a_pos;\nattribute vec4 a_normal_ed;\n\nvarying vec4 v_color;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\n#pragma mapbox: define highp vec4 color\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n #pragma mapbox: initialize highp vec4 color\n\n vec3 normal = a_normal_ed.xyz;\n\n base = max(0.0, base);\n height = max(0.0, height);\n\n float t = mod(normal.x, 2.0);\n\n gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1);\n\n // Relative luminance (how dark/bright is the surface color?)\n float colorvalue = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;\n\n v_color = vec4(0.0, 0.0, 0.0, 1.0);\n\n // Add slight ambient lighting so no extrusions are totally black\n vec4 ambientlight = vec4(0.03, 0.03, 0.03, 1.0);\n color += ambientlight;\n\n // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray\n float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0);\n\n // Adjust directional so that\n // the range of values for highlight/shading is narrower\n // with lower light intensity\n // and with lighter/brighter surface colors\n directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional);\n\n // Add gradient along z axis of side surfaces\n if (normal.y != 0.0) {\n directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);\n }\n\n // Assign final color based on surface + ambient light color, diffuse light directional, and light color\n // with lower bounds adjusted to hue of light\n // so that shading is tinted with the complementary (opposite) color to the light color\n v_color.r += clamp(color.r * directional * u_lightcolor.r, mix(0.0, 0.3, 1.0 - u_lightcolor.r), 1.0);\n v_color.g += clamp(color.g * directional * u_lightcolor.g, mix(0.0, 0.3, 1.0 - u_lightcolor.g), 1.0);\n v_color.b += clamp(color.b * directional * u_lightcolor.b, mix(0.0, 0.3, 1.0 - u_lightcolor.b), 1.0);\n}\n"},fillExtrusionPattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec4 v_lighting;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n vec4 mixedColor = mix(color1, color2, u_mix);\n\n gl_FragColor = mixedColor * v_lighting;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\nuniform float u_height_factor;\n\nuniform vec3 u_lightcolor;\nuniform lowp vec3 u_lightpos;\nuniform lowp float u_lightintensity;\n\nattribute vec2 a_pos;\nattribute vec4 a_normal_ed;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec4 v_lighting;\nvarying float v_directional;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n\n vec3 normal = a_normal_ed.xyz;\n float edgedistance = a_normal_ed.w;\n\n base = max(0.0, base);\n height = max(0.0, height);\n\n float t = mod(normal.x, 2.0);\n float z = t > 0.0 ? height : base;\n\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0\n ? a_pos // extrusion top\n : vec2(edgedistance, z * u_height_factor); // extrusion side\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, pos);\n\n v_lighting = vec4(0.0, 0.0, 0.0, 1.0);\n float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0);\n directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional);\n\n if (normal.y != 0.0) {\n directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);\n }\n\n v_lighting.rgb += clamp(directional * u_lightcolor, mix(vec3(0.0), vec3(0.3), 1.0 - u_lightcolor), vec3(1.0));\n}\n"},extrusionTexture:{fragmentSource:"uniform sampler2D u_image;\nuniform float u_opacity;\nvarying vec2 v_pos;\n\nvoid main() {\n gl_FragColor = texture2D(u_image, v_pos) * u_opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(0.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_world;\nattribute vec2 a_pos;\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1);\n\n v_pos.x = a_pos.x;\n v_pos.y = 1.0 - a_pos.y;\n}\n"},hillshadePrepare:{fragmentSource:"#ifdef GL_ES\nprecision highp float;\n#endif\n\nuniform sampler2D u_image;\nvarying vec2 v_pos;\nuniform vec2 u_dimension;\nuniform float u_zoom;\nuniform float u_maxzoom;\n\nfloat getElevation(vec2 coord, float bias) {\n // Convert encoded elevation value to meters\n vec4 data = texture2D(u_image, coord) * 255.0;\n return (data.r + data.g * 256.0 + data.b * 256.0 * 256.0) / 4.0;\n}\n\nvoid main() {\n vec2 epsilon = 1.0 / u_dimension;\n\n // queried pixels:\n // +-----------+\n // | | | |\n // | a | b | c |\n // | | | |\n // +-----------+\n // | | | |\n // | d | e | f |\n // | | | |\n // +-----------+\n // | | | |\n // | g | h | i |\n // | | | |\n // +-----------+\n\n float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y), 0.0);\n float b = getElevation(v_pos + vec2(0, -epsilon.y), 0.0);\n float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y), 0.0);\n float d = getElevation(v_pos + vec2(-epsilon.x, 0), 0.0);\n float e = getElevation(v_pos, 0.0);\n float f = getElevation(v_pos + vec2(epsilon.x, 0), 0.0);\n float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y), 0.0);\n float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);\n float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);\n\n // here we divide the x and y slopes by 8 * pixel size\n // where pixel size (aka meters/pixel) is:\n // circumference of the world / (pixels per tile * number of tiles)\n // which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom))\n // which can be reduced to: pow(2, 19.25619978527 - u_zoom)\n // we want to vertically exaggerate the hillshading though, because otherwise\n // it is barely noticeable at low zooms. to do this, we multiply this by some\n // scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value\n // Here we use a=0.3 which works out to the expression below. see \n // nickidlugash's awesome breakdown for more info\n // https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556\n float exaggeration = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;\n\n vec2 deriv = vec2(\n (c + f + f + i) - (a + d + d + g),\n (g + h + h + i) - (a + b + b + c)\n ) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);\n\n gl_FragColor = clamp(vec4(\n deriv.x / 2.0 + 0.5,\n deriv.y / 2.0 + 0.5,\n 1.0,\n 1.0), 0.0, 1.0);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = (a_texture_pos / 8192.0) / 2.0 + 0.25;\n}\n"},hillshade:{fragmentSource:"uniform sampler2D u_image;\nvarying vec2 v_pos;\n\nuniform vec2 u_latrange;\nuniform vec2 u_light;\nuniform vec4 u_shadow;\nuniform vec4 u_highlight;\nuniform vec4 u_accent;\n\n#define PI 3.141592653589793\n\nvoid main() {\n vec4 pixel = texture2D(u_image, v_pos);\n\n vec2 deriv = ((pixel.rg * 2.0) - 1.0);\n\n // We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude\n // to account for mercator projection distortion. see #4807 for details\n float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_latrange[1]));\n // We also multiply the slope by an arbitrary z-factor of 1.25\n float slope = atan(1.25 * length(deriv) / scaleFactor);\n float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);\n\n float intensity = u_light.x;\n // We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal\n // position property to account for 0deg corresponding to north/the top of the viewport in the style spec\n // and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal.\n float azimuth = u_light.y + PI;\n\n // We scale the slope exponentially based on intensity, using a calculation similar to\n // the exponential interpolation function in the style spec:\n // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228\n // so that higher intensity values create more opaque hillshading.\n float base = 1.875 - intensity * 1.75;\n float maxValue = 0.5 * PI;\n float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;\n\n // The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine\n // so that the accent color's rate of change eases in while the shade color's eases out.\n float accent = cos(scaledSlope);\n // We multiply both the accent and shade color by a clamped intensity value\n // so that intensities >= 0.5 do not additionally affect the color values\n // while intensity values < 0.5 make the overall color more transparent.\n vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);\n float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);\n vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);\n gl_FragColor = accent_color * (1.0 - shade_color.a) + shade_color;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = a_texture_pos / 8192.0;\n}\n"},line:{fragmentSource:"#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_width2;\nvarying vec2 v_normal;\nvarying float v_gamma_scale;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_gamma_scale;\nvarying highp float v_linesofar;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n\n v_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_width2 = vec2(outset, inset);\n}\n"},lineGradient:{fragmentSource:"\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nuniform sampler2D u_image;\n\nvarying vec2 v_width2;\nvarying vec2 v_normal;\nvarying float v_gamma_scale;\nvarying highp float v_lineprogress;\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n // For gradient lines, v_lineprogress is the ratio along the entire line,\n // scaled to [0, 2^15), and the gradient ramp is stored in a texture.\n vec4 color = texture2D(u_image, vec2(v_lineprogress, 0.5));\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"\n// the attribute conveying progress along a line is scaled to [0, 2^15)\n#define MAX_LINE_DISTANCE 32767.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_gamma_scale;\nvarying highp float v_lineprogress;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n\n v_lineprogress = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0 / MAX_LINE_DISTANCE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_width2 = vec2(outset, inset);\n}\n"},linePattern:{fragmentSource:"uniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_fade;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_linesofar;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0);\n float x_b = mod(v_linesofar / u_pattern_size_b.x, 1.0);\n\n // v_normal.y is 0 at the midpoint of the line, -1 at the lower edge, 1 at the upper edge\n // we clamp the line width outset to be between 0 and half the pattern height plus padding (2.0)\n // to ensure we don't sample outside the designated symbol on the sprite sheet.\n // 0.5 is added to shift the component to be bounded between 0 and 1 for interpolation of\n // the texture coordinate\n float y_a = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_a.y + 2.0) / 2.0) / u_pattern_size_a.y);\n float y_b = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_b.y + 2.0) / 2.0) / u_pattern_size_b.y);\n vec2 pos_a = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, vec2(x_a, y_a));\n vec2 pos_b = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, vec2(x_b, y_b));\n\n vec4 color = mix(texture2D(u_image, pos_a), texture2D(u_image, pos_b), u_fade);\n\n gl_FragColor = color * alpha * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\n// We scale the distance before adding it to the buffers so that we can store\n// long distances for long segments. Use this value to unscale the distance.\n#define LINE_DISTANCE_SCALE 2.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_linesofar;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_linesofar = a_linesofar;\n v_width2 = vec2(outset, inset);\n}\n"},lineSDF:{fragmentSource:"\nuniform sampler2D u_image;\nuniform float u_sdfgamma;\nuniform float u_mix;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying vec2 v_tex_a;\nvarying vec2 v_tex_b;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float width\n #pragma mapbox: initialize lowp float floorwidth\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n float sdfdist_a = texture2D(u_image, v_tex_a).a;\n float sdfdist_b = texture2D(u_image, v_tex_b).a;\n float sdfdist = mix(sdfdist_a, sdfdist_b, u_mix);\n alpha *= smoothstep(0.5 - u_sdfgamma / floorwidth, 0.5 + u_sdfgamma / floorwidth, sdfdist);\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\n// We scale the distance before adding it to the buffers so that we can store\n// long distances for long segments. Use this value to unscale the distance.\n#define LINE_DISTANCE_SCALE 2.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_patternscale_a;\nuniform float u_tex_y_a;\nuniform vec2 u_patternscale_b;\nuniform float u_tex_y_b;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying vec2 v_tex_a;\nvarying vec2 v_tex_b;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n #pragma mapbox: initialize lowp float floorwidth\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist =outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_tex_a = vec2(a_linesofar * u_patternscale_a.x / floorwidth, normal.y * u_patternscale_a.y + u_tex_y_a);\n v_tex_b = vec2(a_linesofar * u_patternscale_b.x / floorwidth, normal.y * u_patternscale_b.y + u_tex_y_b);\n\n v_width2 = vec2(outset, inset);\n}\n"},raster:{fragmentSource:"uniform float u_fade_t;\nuniform float u_opacity;\nuniform sampler2D u_image0;\nuniform sampler2D u_image1;\nvarying vec2 v_pos0;\nvarying vec2 v_pos1;\n\nuniform float u_brightness_low;\nuniform float u_brightness_high;\n\nuniform float u_saturation_factor;\nuniform float u_contrast_factor;\nuniform vec3 u_spin_weights;\n\nvoid main() {\n\n // read and cross-fade colors from the main and parent tiles\n vec4 color0 = texture2D(u_image0, v_pos0);\n vec4 color1 = texture2D(u_image1, v_pos1);\n if (color0.a > 0.0) {\n color0.rgb = color0.rgb / color0.a;\n }\n if (color1.a > 0.0) {\n color1.rgb = color1.rgb / color1.a;\n }\n vec4 color = mix(color0, color1, u_fade_t);\n color.a *= u_opacity;\n vec3 rgb = color.rgb;\n\n // spin\n rgb = vec3(\n dot(rgb, u_spin_weights.xyz),\n dot(rgb, u_spin_weights.zxy),\n dot(rgb, u_spin_weights.yzx));\n\n // saturation\n float average = (color.r + color.g + color.b) / 3.0;\n rgb += (average - rgb) * u_saturation_factor;\n\n // contrast\n rgb = (rgb - 0.5) * u_contrast_factor + 0.5;\n\n // brightness\n vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low);\n vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high);\n\n gl_FragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_tl_parent;\nuniform float u_scale_parent;\nuniform float u_buffer_scale;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos0;\nvarying vec2 v_pos1;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n // We are using Int16 for texture position coordinates to give us enough precision for\n // fractional coordinates. We use 8192 to scale the texture coordinates in the buffer\n // as an arbitrarily high number to preserve adequate precision when rendering.\n // This is also the same value as the EXTENT we are using for our tile buffer pos coordinates,\n // so math for modifying either is consistent.\n v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5;\n v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent;\n}\n"},symbolIcon:{fragmentSource:"uniform sampler2D u_texture;\n\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_tex;\nvarying float v_fade_opacity;\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n lowp float alpha = opacity * v_fade_opacity;\n gl_FragColor = texture2D(u_texture, v_tex) * alpha;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"const float PI = 3.141592653589793;\n\nattribute vec4 a_pos_offset;\nattribute vec4 a_data;\nattribute vec3 a_projected_pos;\nattribute float a_fade_opacity;\n\nuniform bool u_is_size_zoom_constant;\nuniform bool u_is_size_feature_constant;\nuniform highp float u_size_t; // used to interpolate between zoom stops when size is a composite function\nuniform highp float u_size; // used when size is both zoom and feature constant\nuniform highp float u_camera_to_center_distance;\nuniform highp float u_pitch;\nuniform bool u_rotate_symbol;\nuniform highp float u_aspect_ratio;\nuniform float u_fade_change;\n\n#pragma mapbox: define lowp float opacity\n\nuniform mat4 u_matrix;\nuniform mat4 u_label_plane_matrix;\nuniform mat4 u_gl_coord_matrix;\n\nuniform bool u_is_text;\nuniform bool u_pitch_with_map;\n\nuniform vec2 u_texsize;\n\nvarying vec2 v_tex;\nvarying float v_fade_opacity;\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 a_pos = a_pos_offset.xy;\n vec2 a_offset = a_pos_offset.zw;\n\n vec2 a_tex = a_data.xy;\n vec2 a_size = a_data.zw;\n\n highp float segment_angle = -a_projected_pos[2];\n\n float size;\n if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = mix(a_size[0], a_size[1], u_size_t) / 10.0;\n } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = a_size[0] / 10.0;\n } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {\n size = u_size;\n } else {\n size = u_size;\n }\n\n vec4 projectedPoint = u_matrix * vec4(a_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n // See comments in symbol_sdf.vertex\n highp float distance_ratio = u_pitch_with_map ?\n camera_to_anchor_distance / u_camera_to_center_distance :\n u_camera_to_center_distance / camera_to_anchor_distance;\n highp float perspective_ratio = clamp(\n 0.5 + 0.5 * distance_ratio,\n 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles\n 4.0);\n\n size *= perspective_ratio;\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n highp float symbol_rotation = 0.0;\n if (u_rotate_symbol) {\n // See comments in symbol_sdf.vertex\n vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);\n\n vec2 a = projectedPoint.xy / projectedPoint.w;\n vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;\n\n symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);\n }\n\n highp float angle_sin = sin(segment_angle + symbol_rotation);\n highp float angle_cos = cos(segment_angle + symbol_rotation);\n mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);\n\n vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);\n gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);\n\n v_tex = a_tex / u_texsize;\n vec2 fade_opacity = unpack_opacity(a_fade_opacity);\n float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;\n v_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));\n}\n"},symbolSDF:{fragmentSource:"#define SDF_PX 8.0\n#define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO\n\nuniform bool u_is_halo;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\n\nuniform sampler2D u_texture;\nuniform highp float u_gamma_scale;\nuniform bool u_is_text;\n\nvarying vec2 v_data0;\nvarying vec3 v_data1;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 fill_color\n #pragma mapbox: initialize highp vec4 halo_color\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float halo_width\n #pragma mapbox: initialize lowp float halo_blur\n\n vec2 tex = v_data0.xy;\n float gamma_scale = v_data1.x;\n float size = v_data1.y;\n float fade_opacity = v_data1[2];\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n lowp vec4 color = fill_color;\n highp float gamma = EDGE_GAMMA / (fontScale * u_gamma_scale);\n lowp float buff = (256.0 - 64.0) / 256.0;\n if (u_is_halo) {\n color = halo_color;\n gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);\n buff = (6.0 - halo_width / fontScale) / SDF_PX;\n }\n\n lowp float dist = texture2D(u_texture, tex).a;\n highp float gamma_scaled = gamma * gamma_scale;\n highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);\n\n gl_FragColor = color * (alpha * opacity * fade_opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"const float PI = 3.141592653589793;\n\nattribute vec4 a_pos_offset;\nattribute vec4 a_data;\nattribute vec3 a_projected_pos;\nattribute float a_fade_opacity;\n\n// contents of a_size vary based on the type of property value\n// used for {text,icon}-size.\n// For constants, a_size is disabled.\n// For source functions, we bind only one value per vertex: the value of {text,icon}-size evaluated for the current feature.\n// For composite functions:\n// [ text-size(lowerZoomStop, feature),\n// text-size(upperZoomStop, feature) ]\nuniform bool u_is_size_zoom_constant;\nuniform bool u_is_size_feature_constant;\nuniform highp float u_size_t; // used to interpolate between zoom stops when size is a composite function\nuniform highp float u_size; // used when size is both zoom and feature constant\n\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\n\nuniform mat4 u_matrix;\nuniform mat4 u_label_plane_matrix;\nuniform mat4 u_gl_coord_matrix;\n\nuniform bool u_is_text;\nuniform bool u_pitch_with_map;\nuniform highp float u_pitch;\nuniform bool u_rotate_symbol;\nuniform highp float u_aspect_ratio;\nuniform highp float u_camera_to_center_distance;\nuniform float u_fade_change;\n\nuniform vec2 u_texsize;\n\nvarying vec2 v_data0;\nvarying vec3 v_data1;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 fill_color\n #pragma mapbox: initialize highp vec4 halo_color\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float halo_width\n #pragma mapbox: initialize lowp float halo_blur\n\n vec2 a_pos = a_pos_offset.xy;\n vec2 a_offset = a_pos_offset.zw;\n\n vec2 a_tex = a_data.xy;\n vec2 a_size = a_data.zw;\n\n highp float segment_angle = -a_projected_pos[2];\n float size;\n\n if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = mix(a_size[0], a_size[1], u_size_t) / 10.0;\n } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = a_size[0] / 10.0;\n } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {\n size = u_size;\n } else {\n size = u_size;\n }\n\n vec4 projectedPoint = u_matrix * vec4(a_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n // If the label is pitched with the map, layout is done in pitched space,\n // which makes labels in the distance smaller relative to viewport space.\n // We counteract part of that effect by multiplying by the perspective ratio.\n // If the label isn't pitched with the map, we do layout in viewport space,\n // which makes labels in the distance larger relative to the features around\n // them. We counteract part of that effect by dividing by the perspective ratio.\n highp float distance_ratio = u_pitch_with_map ?\n camera_to_anchor_distance / u_camera_to_center_distance :\n u_camera_to_center_distance / camera_to_anchor_distance;\n highp float perspective_ratio = clamp(\n 0.5 + 0.5 * distance_ratio,\n 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles\n 4.0);\n\n size *= perspective_ratio;\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n highp float symbol_rotation = 0.0;\n if (u_rotate_symbol) {\n // Point labels with 'rotation-alignment: map' are horizontal with respect to tile units\n // To figure out that angle in projected space, we draw a short horizontal line in tile\n // space, project it, and measure its angle in projected space.\n vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);\n\n vec2 a = projectedPoint.xy / projectedPoint.w;\n vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;\n\n symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);\n }\n\n highp float angle_sin = sin(segment_angle + symbol_rotation);\n highp float angle_cos = cos(segment_angle + symbol_rotation);\n mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);\n\n vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);\n gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);\n float gamma_scale = gl_Position.w;\n\n vec2 tex = a_tex / u_texsize;\n vec2 fade_opacity = unpack_opacity(a_fade_opacity);\n float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;\n float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));\n\n v_data0 = vec2(tex.x, tex.y);\n v_data1 = vec3(gamma_scale, size, interpolated_fade_opacity);\n}\n"}},ii=/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g,ni=function(t){var e=ei[t],i={};e.fragmentSource=e.fragmentSource.replace(ii,function(t,e,n,o,r){return i[r]=!0,"define"===e?"\n#ifndef HAS_UNIFORM_u_"+r+"\nvarying "+n+" "+o+" "+r+";\n#else\nuniform "+n+" "+o+" u_"+r+";\n#endif\n":"\n#ifdef HAS_UNIFORM_u_"+r+"\n "+n+" "+o+" "+r+" = u_"+r+";\n#endif\n"}),e.vertexSource=e.vertexSource.replace(ii,function(t,e,n,o,r){var a="float"===o?"vec2":"vec4";return i[r]?"define"===e?"\n#ifndef HAS_UNIFORM_u_"+r+"\nuniform lowp float a_"+r+"_t;\nattribute "+n+" "+a+" a_"+r+";\nvarying "+n+" "+o+" "+r+";\n#else\nuniform "+n+" "+o+" u_"+r+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+r+"\n "+r+" = unpack_mix_"+a+"(a_"+r+", a_"+r+"_t);\n#else\n "+n+" "+o+" "+r+" = u_"+r+";\n#endif\n":"define"===e?"\n#ifndef HAS_UNIFORM_u_"+r+"\nuniform lowp float a_"+r+"_t;\nattribute "+n+" "+a+" a_"+r+";\n#else\nuniform "+n+" "+o+" u_"+r+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+r+"\n "+n+" "+o+" "+r+" = unpack_mix_"+a+"(a_"+r+", a_"+r+"_t);\n#else\n "+n+" "+o+" "+r+" = u_"+r+";\n#endif\n"});};for(var oi in ei)ni(oi);var ri=ei,ai=function(t,e,i,n){var o=t.gl;this.program=o.createProgram();var a=i.defines().concat("#define DEVICE_PIXEL_RATIO "+r.devicePixelRatio.toFixed(1));n&&a.push("#define OVERDRAW_INSPECTOR;");var s=a.concat(ri.prelude.fragmentSource,e.fragmentSource).join("\n"),l=a.concat(ri.prelude.vertexSource,e.vertexSource).join("\n"),c=o.createShader(o.FRAGMENT_SHADER);o.shaderSource(c,s),o.compileShader(c),o.attachShader(this.program,c);var u=o.createShader(o.VERTEX_SHADER);o.shaderSource(u,l),o.compileShader(u),o.attachShader(this.program,u);for(var h=i.layoutAttributes||[],p=0;p>16,s>>16),n.uniform2f(i.uniforms.u_pixel_coord_lower,65535&a,65535&s);};function yi(t,e,i,n,o){if(!_i(i.paint.get("fill-pattern"),t))for(var r=!0,a=0,s=n;a0){var l=r.now(),c=(l-e.timeAdded)/s,u=i?(l-i.timeAdded)/s:-1,h=n.getSource(),p=a.coveringZoomLevel({tileSize:h.tileSize,roundZoom:h.roundZoom}),d=!i||Math.abs(i.tileID.overscaledZ-p)>Math.abs(e.tileID.overscaledZ-p),f=d&&e.refreshedUponExpiration?1:t.clamp(d?c:1-u,0,1);return e.refreshedUponExpiration&&c>=1&&(e.refreshedUponExpiration=!1),i?{opacity:1,mix:1-f}:{opacity:f,mix:0}}return{opacity:1,mix:0}}function Ri(e,i,n){var o=e.context,a=o.gl;o.lineWidth.set(1*r.devicePixelRatio);var s=n.posMatrix,l=e.useProgram("debug");o.setDepthMode($t.disabled),o.setStencilMode(Gt.disabled),o.setColorMode(e.colorModeForRenderPass()),a.uniformMatrix4fv(l.uniforms.u_matrix,!1,s),a.uniform4f(l.uniforms.u_color,1,0,0,1),e.debugVAO.bind(o,l,e.debugBuffer,[]),a.drawArrays(a.LINE_STRIP,0,e.debugBuffer.length);for(var c=function(t,e,i,n){n=n||1;var o,r,a,s,l,c,u,h,p=[];for(o=0,r=t.length;o":[24,[4,18,20,9,4,0]],"?":[18,[3,16,3,17,4,19,5,20,7,21,11,21,13,20,14,19,15,17,15,15,14,13,13,12,9,10,9,7,-1,-1,9,2,8,1,9,0,10,1,9,2]],"@":[27,[18,13,17,15,15,16,12,16,10,15,9,14,8,11,8,8,9,6,11,5,14,5,16,6,17,8,-1,-1,12,16,10,14,9,11,9,8,10,6,11,5,-1,-1,18,16,17,8,17,6,19,5,21,5,23,7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12,21,9,20,7,19,5,17,4,15,3,12,3,9,4,6,5,4,7,2,9,1,12,0,15,0,18,1,20,2,21,3,-1,-1,19,16,18,8,18,6,19,5]],A:[18,[9,21,1,0,-1,-1,9,21,17,0,-1,-1,4,7,14,7]],B:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,-1,-1,4,11,13,11,16,10,17,9,18,7,18,4,17,2,16,1,13,0,4,0]],C:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5]],D:[21,[4,21,4,0,-1,-1,4,21,11,21,14,20,16,18,17,16,18,13,18,8,17,5,16,3,14,1,11,0,4,0]],E:[19,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11,-1,-1,4,0,17,0]],F:[18,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11]],G:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,18,8,-1,-1,13,8,18,8]],H:[22,[4,21,4,0,-1,-1,18,21,18,0,-1,-1,4,11,18,11]],I:[8,[4,21,4,0]],J:[16,[12,21,12,5,11,2,10,1,8,0,6,0,4,1,3,2,2,5,2,7]],K:[21,[4,21,4,0,-1,-1,18,21,4,7,-1,-1,9,12,18,0]],L:[17,[4,21,4,0,-1,-1,4,0,16,0]],M:[24,[4,21,4,0,-1,-1,4,21,12,0,-1,-1,20,21,12,0,-1,-1,20,21,20,0]],N:[22,[4,21,4,0,-1,-1,4,21,18,0,-1,-1,18,21,18,0]],O:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21]],P:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13,10,4,10]],Q:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21,-1,-1,12,4,18,-2]],R:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,4,11,-1,-1,11,11,18,0]],S:[20,[17,18,15,20,12,21,8,21,5,20,3,18,3,16,4,14,5,13,7,12,13,10,15,9,16,8,17,6,17,3,15,1,12,0,8,0,5,1,3,3]],T:[16,[8,21,8,0,-1,-1,1,21,15,21]],U:[22,[4,21,4,6,5,3,7,1,10,0,12,0,15,1,17,3,18,6,18,21]],V:[18,[1,21,9,0,-1,-1,17,21,9,0]],W:[24,[2,21,7,0,-1,-1,12,21,7,0,-1,-1,12,21,17,0,-1,-1,22,21,17,0]],X:[20,[3,21,17,0,-1,-1,17,21,3,0]],Y:[18,[1,21,9,11,9,0,-1,-1,17,21,9,11]],Z:[20,[17,21,3,0,-1,-1,3,21,17,21,-1,-1,3,0,17,0]],"[":[14,[4,25,4,-7,-1,-1,5,25,5,-7,-1,-1,4,25,11,25,-1,-1,4,-7,11,-7]],"\\":[14,[0,21,14,-3]],"]":[14,[9,25,9,-7,-1,-1,10,25,10,-7,-1,-1,3,25,10,25,-1,-1,3,-7,10,-7]],"^":[16,[6,15,8,18,10,15,-1,-1,3,12,8,17,13,12,-1,-1,8,17,8,0]],_:[16,[0,-2,16,-2]],"`":[10,[6,21,5,20,4,18,4,16,5,15,6,16,5,17]],a:[19,[15,14,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],b:[19,[4,21,4,0,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],c:[18,[15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],d:[19,[15,21,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],e:[18,[3,8,15,8,15,10,14,12,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],f:[12,[10,21,8,21,6,20,5,17,5,0,-1,-1,2,14,9,14]],g:[19,[15,14,15,-2,14,-5,13,-6,11,-7,8,-7,6,-6,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],h:[19,[4,21,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],i:[8,[3,21,4,20,5,21,4,22,3,21,-1,-1,4,14,4,0]],j:[10,[5,21,6,20,7,21,6,22,5,21,-1,-1,6,14,6,-3,5,-6,3,-7,1,-7]],k:[17,[4,21,4,0,-1,-1,14,14,4,4,-1,-1,8,8,15,0]],l:[8,[4,21,4,0]],m:[30,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0,-1,-1,15,10,18,13,20,14,23,14,25,13,26,10,26,0]],n:[19,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],o:[19,[8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3,16,6,16,8,15,11,13,13,11,14,8,14]],p:[19,[4,14,4,-7,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],q:[19,[15,14,15,-7,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],r:[13,[4,14,4,0,-1,-1,4,8,5,11,7,13,9,14,12,14]],s:[17,[14,11,13,13,10,14,7,14,4,13,3,11,4,9,6,8,11,7,13,6,14,4,14,3,13,1,10,0,7,0,4,1,3,3]],t:[12,[5,21,5,4,6,1,8,0,10,0,-1,-1,2,14,9,14]],u:[19,[4,14,4,4,5,1,7,0,10,0,12,1,15,4,-1,-1,15,14,15,0]],v:[16,[2,14,8,0,-1,-1,14,14,8,0]],w:[22,[3,14,7,0,-1,-1,11,14,7,0,-1,-1,11,14,15,0,-1,-1,19,14,15,0]],x:[17,[3,14,14,0,-1,-1,14,14,3,0]],y:[16,[2,14,8,0,-1,-1,14,14,8,0,6,-4,4,-6,2,-7,1,-7]],z:[17,[14,14,3,0,-1,-1,3,14,14,14,-1,-1,3,0,14,0]],"{":[14,[9,25,7,24,6,23,5,21,5,19,6,17,7,16,8,14,8,12,6,10,-1,-1,7,24,6,22,6,20,7,18,8,17,9,15,9,13,8,11,4,9,8,7,9,5,9,3,8,1,7,0,6,-2,6,-4,7,-6,-1,-1,6,8,8,6,8,4,7,2,6,1,5,-1,5,-3,6,-5,7,-6,9,-7]],"|":[8,[4,25,4,-7]],"}":[14,[5,25,7,24,8,23,9,21,9,19,8,17,7,16,6,14,6,12,8,10,-1,-1,7,24,8,22,8,20,7,18,6,17,5,15,5,13,6,11,10,9,6,7,5,5,5,3,6,1,7,0,8,-2,8,-4,7,-6,-1,-1,8,8,6,6,6,4,7,2,8,1,9,-1,9,-3,8,-5,7,-6,5,-7]],"~":[24,[3,6,3,8,4,11,6,12,8,12,10,11,14,8,16,7,18,7,20,8,21,10,-1,-1,3,8,4,10,6,11,8,11,10,10,14,7,16,6,18,6,20,7,21,10,21,12]]};var Mi={symbol:function(t,e,i,n){if("translucent"===t.renderPass){var o=t.context;o.setStencilMode(Gt.disabled),o.setColorMode(t.colorModeForRenderPass()),0!==i.paint.get("icon-opacity").constantOr(1)&&hi(t,e,i,n,!1,i.paint.get("icon-translate"),i.paint.get("icon-translate-anchor"),i.layout.get("icon-rotation-alignment"),i.layout.get("icon-pitch-alignment"),i.layout.get("icon-keep-upright")),0!==i.paint.get("text-opacity").constantOr(1)&&hi(t,e,i,n,!0,i.paint.get("text-translate"),i.paint.get("text-translate-anchor"),i.layout.get("text-rotation-alignment"),i.layout.get("text-pitch-alignment"),i.layout.get("text-keep-upright")),e.map.showCollisionBoxes&&function(t,e,i,n){li(t,e,i,n,!1),li(t,e,i,n,!0);}(t,e,i,n);}},circle:function(t,e,i,n){if("translucent"===t.renderPass){var o=i.paint.get("circle-opacity"),r=i.paint.get("circle-stroke-width"),a=i.paint.get("circle-stroke-opacity");if(0!==o.constantOr(1)||0!==r.constantOr(1)&&0!==a.constantOr(1)){var s=t.context,l=s.gl;s.setDepthMode(t.depthModeForSublayer(0,$t.ReadOnly)),s.setStencilMode(Gt.disabled),s.setColorMode(t.colorModeForRenderPass());for(var c=!0,u=0;u0?1-1/(1.001-o):-o),s.uniform1f(c.uniforms.u_contrast_factor,(r=i.paint.get("raster-contrast"))>0?1/(1-r):1+r),s.uniform3fv(c.uniforms.u_spin_weights,function(t){t*=Math.PI/180;var e=Math.sin(t),i=Math.cos(t);return[(2*i+1)/3,(-Math.sqrt(3)*e-i+1)/3,(Math.sqrt(3)*e-i+1)/3]}(i.paint.get("raster-hue-rotate"))),s.uniform1f(c.uniforms.u_buffer_scale,1),s.uniform1i(c.uniforms.u_image0,0),s.uniform1i(c.uniforms.u_image1,1);for(var u=n.length&&n[0].overscaledZ,h=0,p=n;he.row){var i=t;t=e,e=i;}return{x0:t.column,y0:t.row,x1:e.column,y1:e.row,dx:e.column-t.column,dy:e.row-t.row}}function ki(t,e,i,n,o){var r=Math.max(i,Math.floor(e.y0)),a=Math.min(n,Math.ceil(e.y1));if(t.x0===e.x0&&t.y0===e.y0?t.x0+e.dy/t.dy*t.dx0,h=e.dx<0,p=r;pl.dy&&(a=s,s=l,l=a),s.dy>c.dy&&(a=s,s=c,c=a),l.dy>c.dy&&(a=l,l=c,c=a),s.dy&&ki(c,s,n,o,r),l.dy&&ki(c,l,n,o,r);}Li.prototype.resize=function(t,e){var i=this.context.gl;if(this.width=t*r.devicePixelRatio,this.height=e*r.devicePixelRatio,this.context.viewport.set([0,0,this.width,this.height]),this.style)for(var n=0,o=this.style._order;n=0;this.currentLayer--){var g=n.style._layers[s[n.currentLayer]];g.source!==(m&&m.id)&&(_=[],(m=n.style.sourceCaches[g.source])&&(n.clearStencil(),_=m.getVisibleCoordinates(),m.getSource().isTileClipped&&n._renderTileClippingMasks(_))),n.renderLayer(n,m,g,_);}this.renderPass="translucent";var v,y=[];for(this.currentLayer=0,this.currentLayer;this.currentLayer0?e.pop():null},Li.prototype._createProgramCached=function(t,e){this.cache=this.cache||{};var i=""+t+(e.cacheKey||"")+(this._showOverdrawInspector?"/overdraw":"");return this.cache[i]||(this.cache[i]=new ai(this.context,ri[t],e,this._showOverdrawInspector)),this.cache[i]},Li.prototype.useProgram=function(t,e){var i=this._createProgramCached(t,e||this.emptyProgramConfiguration);return this.context.program.set(i.program),i};var Oi=t.default$20.vec4,Fi=t.default$20.mat4,Ni=t.default$20.mat2,Ui=function(t,e,i){this.tileSize=512,this._renderWorldCopies=void 0===i||i,this._minZoom=t||0,this._maxZoom=e||22,this.latRange=[-85.05113,85.05113],this.width=0,this.height=0,this._center=new W(0,0),this.zoom=0,this.angle=0,this._fov=.6435011087932844,this._pitch=0,this._unmodified=!0,this._posMatrixCache={},this._alignedPosMatrixCache={};},Zi={minZoom:{configurable:!0},maxZoom:{configurable:!0},renderWorldCopies:{configurable:!0},worldSize:{configurable:!0},centerPoint:{configurable:!0},size:{configurable:!0},bearing:{configurable:!0},pitch:{configurable:!0},fov:{configurable:!0},zoom:{configurable:!0},center:{configurable:!0},unmodified:{configurable:!0},x:{configurable:!0},y:{configurable:!0},point:{configurable:!0}};Ui.prototype.clone=function(){var t=new Ui(this._minZoom,this._maxZoom,this._renderWorldCopies);return t.tileSize=this.tileSize,t.latRange=this.latRange,t.width=this.width,t.height=this.height,t._center=this._center,t.zoom=this.zoom,t.angle=this.angle,t._fov=this._fov,t._pitch=this._pitch,t._unmodified=this._unmodified,t._calcMatrices(),t},Zi.minZoom.get=function(){return this._minZoom},Zi.minZoom.set=function(t){this._minZoom!==t&&(this._minZoom=t,this.zoom=Math.max(this.zoom,t));},Zi.maxZoom.get=function(){return this._maxZoom},Zi.maxZoom.set=function(t){this._maxZoom!==t&&(this._maxZoom=t,this.zoom=Math.min(this.zoom,t));},Zi.renderWorldCopies.get=function(){return this._renderWorldCopies},Zi.renderWorldCopies.set=function(t){void 0===t?t=!0:null===t&&(t=!1),this._renderWorldCopies=t;},Zi.worldSize.get=function(){return this.tileSize*this.scale},Zi.centerPoint.get=function(){return this.size._div(2)},Zi.size.get=function(){return new t.default$1(this.width,this.height)},Zi.bearing.get=function(){return-this.angle/Math.PI*180},Zi.bearing.set=function(e){var i=-t.wrap(e,-180,180)*Math.PI/180;this.angle!==i&&(this._unmodified=!1,this.angle=i,this._calcMatrices(),this.rotationMatrix=Ni.create(),Ni.rotate(this.rotationMatrix,this.rotationMatrix,this.angle));},Zi.pitch.get=function(){return this._pitch/Math.PI*180},Zi.pitch.set=function(e){var i=t.clamp(e,0,60)/180*Math.PI;this._pitch!==i&&(this._unmodified=!1,this._pitch=i,this._calcMatrices());},Zi.fov.get=function(){return this._fov/Math.PI*180},Zi.fov.set=function(t){t=Math.max(.01,Math.min(60,t)),this._fov!==t&&(this._unmodified=!1,this._fov=t/180*Math.PI,this._calcMatrices());},Zi.zoom.get=function(){return this._zoom},Zi.zoom.set=function(t){var e=Math.min(Math.max(t,this.minZoom),this.maxZoom);this._zoom!==e&&(this._unmodified=!1,this._zoom=e,this.scale=this.zoomScale(e),this.tileZoom=Math.floor(e),this.zoomFraction=e-this.tileZoom,this._constrain(),this._calcMatrices());},Zi.center.get=function(){return this._center},Zi.center.set=function(t){t.lat===this._center.lat&&t.lng===this._center.lng||(this._unmodified=!1,this._center=t,this._constrain(),this._calcMatrices());},Ui.prototype.coveringZoomLevel=function(t){return(t.roundZoom?Math.round:Math.floor)(this.zoom+this.scaleZoom(this.tileSize/t.tileSize))},Ui.prototype.getVisibleUnwrappedCoordinates=function(e){var i=this.pointCoordinate(new t.default$1(0,0),0),n=this.pointCoordinate(new t.default$1(this.width,0),0),o=Math.floor(i.column),r=Math.floor(n.column),a=[new t.UnwrappedTileID(0,e)];if(this._renderWorldCopies)for(var s=o;s<=r;s++)0!==s&&a.push(new t.UnwrappedTileID(s,e));return a},Ui.prototype.coveringTiles=function(e){var i=this.coveringZoomLevel(e),n=i;if(void 0!==e.minzoom&&ie.maxzoom&&(i=e.maxzoom);var o=this.pointCoordinate(this.centerPoint,i),r=new t.default$1(o.column-.5,o.row-.5);return function(e,i,n,o){void 0===o&&(o=!0);var r=1<=0&&l<=r)for(c=i;ca&&(o=a-m);}if(this.lngRange){var _=this.x,g=c.x/2;_-gl&&(n=l-g);}void 0===n&&void 0===o||(this.center=this.unproject(new t.default$1(void 0!==n?n:this.x,void 0!==o?o:this.y))),this._unmodified=u,this._constraining=!1;}},Ui.prototype._calcMatrices=function(){if(this.height){this.cameraToCenterDistance=.5/Math.tan(this._fov/2)*this.height;var t=this._fov/2,e=Math.PI/2+this._pitch,i=Math.sin(t)*this.cameraToCenterDistance/Math.sin(Math.PI-e-t),n=this.x,o=this.y,r=1.01*(Math.cos(Math.PI/2-this._pitch)*i+this.cameraToCenterDistance),a=new Float64Array(16);Fi.perspective(a,this._fov,this.width/this.height,1,r),Fi.scale(a,a,[1,-1,1]),Fi.translate(a,a,[0,0,-this.cameraToCenterDistance]),Fi.rotateX(a,a,this._pitch),Fi.rotateZ(a,a,this.angle),Fi.translate(a,a,[-n,-o,0]);var s=this.worldSize/(2*Math.PI*6378137*Math.abs(Math.cos(this.center.lat*(Math.PI/180))));Fi.scale(a,a,[1,1,s,1]),this.projMatrix=a;var l=this.width%2/2,c=this.height%2/2,u=Math.cos(this.angle),h=Math.sin(this.angle),p=n-Math.round(n)+u*l+h*c,d=o-Math.round(o)+u*c+h*l,f=new Float64Array(a);if(Fi.translate(f,f,[p>.5?p-1:p,d>.5?d-1:d,0]),this.alignedProjMatrix=f,a=Fi.create(),Fi.scale(a,a,[this.width/2,-this.height/2,1]),Fi.translate(a,a,[1,-1,0]),this.pixelMatrix=Fi.multiply(new Float64Array(16),a,this.projMatrix),!(a=Fi.invert(new Float64Array(16),this.pixelMatrix)))throw new Error("failed to invert matrix");this.pixelMatrixInverse=a,this._posMatrixCache={},this._alignedPosMatrixCache={};}},Ui.prototype.maxPitchScaleFactor=function(){if(!this.pixelMatrixInverse)return 1;var e=this.pointCoordinate(new t.default$1(0,0)).zoomTo(this.zoom),i=[e.column*this.tileSize,e.row*this.tileSize,0,1];return Oi.transformMat4(i,i,this.pixelMatrix)[3]/this.cameraToCenterDistance},Object.defineProperties(Ui.prototype,Zi);var Vi=function(){var e,i,n,o,r;t.bindAll(["_onHashChange","_updateHash"],this),this._updateHash=(e=this._updateHashUnthrottled.bind(this),i=300,n=!1,o=0,r=function(){o=0,n&&(e(),o=setTimeout(r,i),n=!1);},function(){return n=!0,o||r(),o});};Vi.prototype.addTo=function(e){return this._map=e,t.default.addEventListener("hashchange",this._onHashChange,!1),this._map.on("moveend",this._updateHash),this},Vi.prototype.remove=function(){return t.default.removeEventListener("hashchange",this._onHashChange,!1),this._map.off("moveend",this._updateHash),clearTimeout(this._updateHash()),delete this._map,this},Vi.prototype.getHashString=function(t){var e=this._map.getCenter(),i=Math.round(100*this._map.getZoom())/100,n=Math.ceil((i*Math.LN2+Math.log(512/360/.5))/Math.LN10),o=Math.pow(10,n),r=Math.round(e.lng*o)/o,a=Math.round(e.lat*o)/o,s=this._map.getBearing(),l=this._map.getPitch(),c="";return c+=t?"#/"+r+"/"+a+"/"+i:"#"+i+"/"+a+"/"+r,(s||l)&&(c+="/"+Math.round(10*s)/10),l&&(c+="/"+Math.round(l)),c},Vi.prototype._onHashChange=function(){var e=t.default.location.hash.replace("#","").split("/");return e.length>=3&&(this._map.jumpTo({center:[+e[2],+e[1]],zoom:+e[0],bearing:+(e[3]||0),pitch:+(e[4]||0)}),!0)},Vi.prototype._updateHashUnthrottled=function(){var e=this.getHashString();t.default.history.replaceState(t.default.history.state,"",e);};var ji=function(e){function i(i,n,o,r){void 0===r&&(r={});var a=s.mousePos(n.getCanvasContainer(),o),l=n.unproject(a);e.call(this,i,t.extend({point:a,lngLat:l,originalEvent:o},r)),this._defaultPrevented=!1,this.target=n;}e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i;var n={defaultPrevented:{configurable:!0}};return i.prototype.preventDefault=function(){this._defaultPrevented=!0;},n.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(i.prototype,n),i}(t.Event),$i=function(e){function i(i,n,o){var r=s.touchPos(n.getCanvasContainer(),o),a=r.map(function(t){return n.unproject(t)}),l=r.reduce(function(t,e,i,n){return t.add(e.div(n.length))},new t.default$1(0,0)),c=n.unproject(l);e.call(this,i,{points:r,point:l,lngLats:a,lngLat:c,originalEvent:o}),this._defaultPrevented=!1;}e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i;var n={defaultPrevented:{configurable:!0}};return i.prototype.preventDefault=function(){this._defaultPrevented=!0;},n.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(i.prototype,n),i}(t.Event),Gi=function(t){function e(e,i,n){t.call(this,e,{originalEvent:n}),this._defaultPrevented=!1;}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var i={defaultPrevented:{configurable:!0}};return e.prototype.preventDefault=function(){this._defaultPrevented=!0;},i.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(e.prototype,i),e}(t.Event),Wi=function(e){this._map=e,this._el=e.getCanvasContainer(),this._delta=0,t.bindAll(["_onWheel","_onTimeout","_onScrollFrame","_onScrollFinished"],this);};Wi.prototype.isEnabled=function(){return!!this._enabled},Wi.prototype.isActive=function(){return!!this._active},Wi.prototype.enable=function(t){this.isEnabled()||(this._enabled=!0,this._aroundCenter=t&&"center"===t.around);},Wi.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},Wi.prototype.onWheel=function(e){if(this.isEnabled()){var i=e.deltaMode===t.default.WheelEvent.DOM_DELTA_LINE?40*e.deltaY:e.deltaY,n=r.now(),o=n-(this._lastWheelEventTime||0);this._lastWheelEventTime=n,0!==i&&i%4.000244140625==0?this._type="wheel":0!==i&&Math.abs(i)<4?this._type="trackpad":o>400?(this._type=null,this._lastValue=i,this._timeout=setTimeout(this._onTimeout,40,e)):this._type||(this._type=Math.abs(o*i)<200?"trackpad":"wheel",this._timeout&&(clearTimeout(this._timeout),this._timeout=null,i+=this._lastValue)),e.shiftKey&&i&&(i/=4),this._type&&(this._lastWheelEvent=e,this._delta-=i,this.isActive()||this._start(e)),e.preventDefault();}},Wi.prototype._onTimeout=function(t){this._type="wheel",this._delta-=this._lastValue,this.isActive()||this._start(t);},Wi.prototype._start=function(e){if(this._delta){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),this._active=!0,this._map.fire(new t.Event("movestart",{originalEvent:e})),this._map.fire(new t.Event("zoomstart",{originalEvent:e})),this._finishTimeout&&clearTimeout(this._finishTimeout);var i=s.mousePos(this._el,e);this._around=W.convert(this._aroundCenter?this._map.getCenter():this._map.unproject(i)),this._aroundPoint=this._map.transform.locationPoint(this._around),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame));}},Wi.prototype._onScrollFrame=function(){var e=this;if(this._frameId=null,this.isActive()){var i=this._map.transform;if(0!==this._delta){var n="wheel"===this._type&&Math.abs(this._delta)>4.000244140625?1/450:.01,o=2/(1+Math.exp(-Math.abs(this._delta*n)));this._delta<0&&0!==o&&(o=1/o);var a="number"==typeof this._targetZoom?i.zoomScale(this._targetZoom):i.scale;this._targetZoom=Math.min(i.maxZoom,Math.max(i.minZoom,i.scaleZoom(a*o))),"wheel"===this._type&&(this._startZoom=i.zoom,this._easing=this._smoothOutEasing(200)),this._delta=0;}var s=!1;if("wheel"===this._type){var l=Math.min((r.now()-this._lastWheelEventTime)/200,1),c=this._easing(l);i.zoom=t.number(this._startZoom,this._targetZoom,c),l<1?this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame)):s=!0;}else i.zoom=this._targetZoom,s=!0;i.setLocationAtPoint(this._around,this._aroundPoint),this._map.fire(new t.Event("move",{originalEvent:this._lastWheelEvent})),this._map.fire(new t.Event("zoom",{originalEvent:this._lastWheelEvent})),s&&(this._active=!1,this._finishTimeout=setTimeout(function(){e._map.fire(new t.Event("zoomend",{originalEvent:e._lastWheelEvent})),e._map.fire(new t.Event("moveend",{originalEvent:e._lastWheelEvent})),delete e._targetZoom;},200));}},Wi.prototype._smoothOutEasing=function(e){var i=t.ease;if(this._prevEase){var n=this._prevEase,o=(r.now()-n.start)/n.duration,a=n.easing(o+.01)-n.easing(o),s=.27/Math.sqrt(a*a+1e-4)*.01,l=Math.sqrt(.0729-s*s);i=t.bezier(s,l,.25,1);}return this._prevEase={start:r.now(),duration:e,easing:i},i};var qi=function(e){this._map=e,this._el=e.getCanvasContainer(),this._container=e.getContainer(),t.bindAll(["_onMouseMove","_onMouseUp","_onKeyDown"],this);};qi.prototype.isEnabled=function(){return!!this._enabled},qi.prototype.isActive=function(){return!!this._active},qi.prototype.enable=function(){this.isEnabled()||(this._enabled=!0);},qi.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},qi.prototype.onMouseDown=function(e){this.isEnabled()&&e.shiftKey&&0===e.button&&(t.default.document.addEventListener("mousemove",this._onMouseMove,!1),t.default.document.addEventListener("keydown",this._onKeyDown,!1),t.default.document.addEventListener("mouseup",this._onMouseUp,!1),s.disableDrag(),this._startPos=s.mousePos(this._el,e),this._active=!0);},qi.prototype._onMouseMove=function(t){var e=this._startPos,i=s.mousePos(this._el,t);this._box||(this._box=s.create("div","mapboxgl-boxzoom",this._container),this._container.classList.add("mapboxgl-crosshair"),this._fireEvent("boxzoomstart",t));var n=Math.min(e.x,i.x),o=Math.max(e.x,i.x),r=Math.min(e.y,i.y),a=Math.max(e.y,i.y);s.setTransform(this._box,"translate("+n+"px,"+r+"px)"),this._box.style.width=o-n+"px",this._box.style.height=a-r+"px";},qi.prototype._onMouseUp=function(e){if(0===e.button){var i=this._startPos,n=s.mousePos(this._el,e),o=(new q).extend(this._map.unproject(i)).extend(this._map.unproject(n));this._finish(),s.suppressClick(),i.x===n.x&&i.y===n.y?this._fireEvent("boxzoomcancel",e):this._map.fitBounds(o,{linear:!0}).fire(new t.Event("boxzoomend",{originalEvent:e,boxZoomBounds:o}));}},qi.prototype._onKeyDown=function(t){27===t.keyCode&&(this._finish(),this._fireEvent("boxzoomcancel",t));},qi.prototype._finish=function(){this._active=!1,t.default.document.removeEventListener("mousemove",this._onMouseMove,!1),t.default.document.removeEventListener("keydown",this._onKeyDown,!1),t.default.document.removeEventListener("mouseup",this._onMouseUp,!1),this._container.classList.remove("mapboxgl-crosshair"),this._box&&(s.remove(this._box),this._box=null),s.enableDrag();},qi.prototype._fireEvent=function(e,i){return this._map.fire(new t.Event(e,{originalEvent:i}))};var Xi=t.bezier(0,0,.25,1),Hi=function(e,i){this._map=e,this._el=i.element||e.getCanvasContainer(),this._state="disabled",this._button=i.button||"right",this._bearingSnap=i.bearingSnap||0,this._pitchWithRotate=!1!==i.pitchWithRotate,t.bindAll(["_onMouseMove","_onMouseUp","_onBlur","_onDragFrame"],this);};Hi.prototype.isEnabled=function(){return"disabled"!==this._state},Hi.prototype.isActive=function(){return"active"===this._state},Hi.prototype.enable=function(){this.isEnabled()||(this._state="enabled");},Hi.prototype.disable=function(){if(this.isEnabled())switch(this._state){case"active":this._state="disabled",this._unbind(),this._deactivate(),this._fireEvent("rotateend"),this._pitchWithRotate&&this._fireEvent("pitchend"),this._fireEvent("moveend");break;case"pending":this._state="disabled",this._unbind();break;default:this._state="disabled";}},Hi.prototype.onMouseDown=function(e){if("enabled"===this._state){if("right"===this._button){if(this._eventButton=s.mouseButton(e),this._eventButton!==(e.ctrlKey?0:2))return}else{if(e.ctrlKey||0!==s.mouseButton(e))return;this._eventButton=0;}s.disableDrag(),t.default.document.addEventListener("mousemove",this._onMouseMove,{capture:!0}),t.default.document.addEventListener("mouseup",this._onMouseUp),t.default.addEventListener("blur",this._onBlur),this._state="pending",this._inertia=[[r.now(),this._map.getBearing()]],this._previousPos=s.mousePos(this._el,e),this._center=this._map.transform.centerPoint,e.preventDefault();}},Hi.prototype._onMouseMove=function(t){this._lastMoveEvent=t,this._pos=s.mousePos(this._el,t),"pending"===this._state&&(this._state="active",this._fireEvent("rotatestart",t),this._fireEvent("movestart",t),this._pitchWithRotate&&this._fireEvent("pitchstart",t)),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onDragFrame));},Hi.prototype._onDragFrame=function(){this._frameId=null;var t=this._lastMoveEvent;if(t){var e=this._map.transform,i=this._previousPos,n=this._pos,o=.8*(i.x-n.x),a=-.5*(i.y-n.y),s=e.bearing-o,l=e.pitch-a,c=this._inertia,u=c[c.length-1];this._drainInertiaBuffer(),c.push([r.now(),this._map._normalizeBearing(s,u[1])]),e.bearing=s,this._pitchWithRotate&&(this._fireEvent("pitch",t),e.pitch=l),this._fireEvent("rotate",t),this._fireEvent("move",t),delete this._lastMoveEvent,this._previousPos=this._pos;}},Hi.prototype._onMouseUp=function(t){if(s.mouseButton(t)===this._eventButton)switch(this._state){case"active":this._state="enabled",s.suppressClick(),this._unbind(),this._deactivate(),this._inertialRotate(t);break;case"pending":this._state="enabled",this._unbind();}},Hi.prototype._onBlur=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._fireEvent("rotateend",t),this._pitchWithRotate&&this._fireEvent("pitchend",t),this._fireEvent("moveend",t);break;case"pending":this._state="enabled",this._unbind();}},Hi.prototype._unbind=function(){t.default.document.removeEventListener("mousemove",this._onMouseMove,{capture:!0}),t.default.document.removeEventListener("mouseup",this._onMouseUp),t.default.removeEventListener("blur",this._onBlur),s.enableDrag();},Hi.prototype._deactivate=function(){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._lastMoveEvent,delete this._previousPos;},Hi.prototype._inertialRotate=function(t){var e=this;this._fireEvent("rotateend",t),this._drainInertiaBuffer();var i=this._map,n=i.getBearing(),o=this._inertia,r=function(){Math.abs(n)180&&(d=180);var f=d/180;c+=h*d*(f/2),Math.abs(i._normalizeBearing(c,0))0&&e-t[0][0]>160;)t.shift();};var Ki=t.bezier(0,0,.3,1),Yi=function(e){this._map=e,this._el=e.getCanvasContainer(),this._state="disabled",t.bindAll(["_onMove","_onMouseUp","_onTouchEnd","_onBlur","_onDragFrame"],this);};Yi.prototype.isEnabled=function(){return"disabled"!==this._state},Yi.prototype.isActive=function(){return"active"===this._state},Yi.prototype.enable=function(){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-drag-pan"),this._state="enabled");},Yi.prototype.disable=function(){if(this.isEnabled())switch(this._el.classList.remove("mapboxgl-touch-drag-pan"),this._state){case"active":this._state="disabled",this._unbind(),this._deactivate(),this._fireEvent("dragend"),this._fireEvent("moveend");break;case"pending":this._state="disabled",this._unbind();break;default:this._state="disabled";}},Yi.prototype.onMouseDown=function(e){"enabled"===this._state&&(e.ctrlKey||0!==s.mouseButton(e)||(s.addEventListener(t.default.document,"mousemove",this._onMove,{capture:!0}),s.addEventListener(t.default.document,"mouseup",this._onMouseUp),this._start(e)));},Yi.prototype.onTouchStart=function(e){"enabled"===this._state&&(e.touches.length>1||(s.addEventListener(t.default.document,"touchmove",this._onMove,{capture:!0,passive:!1}),s.addEventListener(t.default.document,"touchend",this._onTouchEnd),this._start(e)));},Yi.prototype._start=function(e){t.default.addEventListener("blur",this._onBlur),this._state="pending",this._previousPos=s.mousePos(this._el,e),this._inertia=[[r.now(),this._previousPos]];},Yi.prototype._onMove=function(t){this._lastMoveEvent=t,t.preventDefault(),this._pos=s.mousePos(this._el,t),this._drainInertiaBuffer(),this._inertia.push([r.now(),this._pos]),"pending"===this._state&&(this._state="active",this._fireEvent("dragstart",t),this._fireEvent("movestart",t)),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onDragFrame));},Yi.prototype._onDragFrame=function(){this._frameId=null;var t=this._lastMoveEvent;if(t){var e=this._map.transform;e.setLocationAtPoint(e.pointLocation(this._previousPos),this._pos),this._fireEvent("drag",t),this._fireEvent("move",t),this._previousPos=this._pos,delete this._lastMoveEvent;}},Yi.prototype._onMouseUp=function(t){if(0===s.mouseButton(t))switch(this._state){case"active":this._state="enabled",s.suppressClick(),this._unbind(),this._deactivate(),this._inertialPan(t);break;case"pending":this._state="enabled",this._unbind();}},Yi.prototype._onTouchEnd=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._inertialPan(t);break;case"pending":this._state="enabled",this._unbind();}},Yi.prototype._onBlur=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._fireEvent("dragend",t),this._fireEvent("moveend",t);break;case"pending":this._state="enabled",this._unbind();}},Yi.prototype._unbind=function(){s.removeEventListener(t.default.document,"touchmove",this._onMove,{capture:!0,passive:!1}),s.removeEventListener(t.default.document,"touchend",this._onTouchEnd),s.removeEventListener(t.default.document,"mousemove",this._onMove,{capture:!0}),s.removeEventListener(t.default.document,"mouseup",this._onMouseUp),s.removeEventListener(t.default,"blur",this._onBlur);},Yi.prototype._deactivate=function(){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._lastMoveEvent,delete this._previousPos,delete this._pos;},Yi.prototype._inertialPan=function(t){this._fireEvent("dragend",t),this._drainInertiaBuffer();var e=this._inertia;if(e.length<2)this._fireEvent("moveend",t);else{var i=e[e.length-1],n=e[0],o=i[1].sub(n[1]),r=(i[0]-n[0])/1e3;if(0===r||i[1].equals(n[1]))this._fireEvent("moveend",t);else{var a=o.mult(.3/r),s=a.mag();s>1400&&(s=1400,a._unit()._mult(s));var l=s/750,c=a.mult(-l/2);this._map.panBy(c,{duration:1e3*l,easing:Ki,noMoveStart:!0},{originalEvent:t});}}},Yi.prototype._fireEvent=function(e,i){return this._map.fire(new t.Event(e,i?{originalEvent:i}:{}))},Yi.prototype._drainInertiaBuffer=function(){for(var t=this._inertia,e=r.now();t.length>0&&e-t[0][0]>160;)t.shift();};var Ji=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onKeyDown"],this);};function Qi(t){return t*(2-t)}Ji.prototype.isEnabled=function(){return!!this._enabled},Ji.prototype.enable=function(){this.isEnabled()||(this._el.addEventListener("keydown",this._onKeyDown,!1),this._enabled=!0);},Ji.prototype.disable=function(){this.isEnabled()&&(this._el.removeEventListener("keydown",this._onKeyDown),this._enabled=!1);},Ji.prototype._onKeyDown=function(t){if(!(t.altKey||t.ctrlKey||t.metaKey)){var e=0,i=0,n=0,o=0,r=0;switch(t.keyCode){case 61:case 107:case 171:case 187:e=1;break;case 189:case 109:case 173:e=-1;break;case 37:t.shiftKey?i=-1:(t.preventDefault(),o=-1);break;case 39:t.shiftKey?i=1:(t.preventDefault(),o=1);break;case 38:t.shiftKey?n=1:(t.preventDefault(),r=-1);break;case 40:t.shiftKey?n=-1:(r=1,t.preventDefault());break;default:return}var a=this._map,s=a.getZoom(),l={duration:300,delayEndEvents:500,easing:Qi,zoom:e?Math.round(s)+e*(t.shiftKey?2:1):s,bearing:a.getBearing()+15*i,pitch:a.getPitch()+10*n,offset:[100*-o,100*-r],center:a.getCenter()};a.easeTo(l,{originalEvent:t});}};var tn=function(e){this._map=e,t.bindAll(["_onDblClick","_onZoomEnd"],this);};tn.prototype.isEnabled=function(){return!!this._enabled},tn.prototype.isActive=function(){return!!this._active},tn.prototype.enable=function(){this.isEnabled()||(this._enabled=!0);},tn.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},tn.prototype.onTouchStart=function(t){var e=this;this.isEnabled()&&(t.points.length>1||(this._tapped?(clearTimeout(this._tapped),this._tapped=null,this._zoom(t)):this._tapped=setTimeout(function(){e._tapped=null;},300)));},tn.prototype.onDblClick=function(t){this.isEnabled()&&(t.originalEvent.preventDefault(),this._zoom(t));},tn.prototype._zoom=function(t){this._active=!0,this._map.on("zoomend",this._onZoomEnd),this._map.zoomTo(this._map.getZoom()+(t.originalEvent.shiftKey?-1:1),{around:t.lngLat},t);},tn.prototype._onZoomEnd=function(){this._active=!1,this._map.off("zoomend",this._onZoomEnd);};var en=t.bezier(0,0,.15,1),nn=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onMove","_onEnd","_onTouchFrame"],this);};nn.prototype.isEnabled=function(){return!!this._enabled},nn.prototype.enable=function(t){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-zoom-rotate"),this._enabled=!0,this._aroundCenter=!!t&&"center"===t.around);},nn.prototype.disable=function(){this.isEnabled()&&(this._el.classList.remove("mapboxgl-touch-zoom-rotate"),this._enabled=!1);},nn.prototype.disableRotation=function(){this._rotationDisabled=!0;},nn.prototype.enableRotation=function(){this._rotationDisabled=!1;},nn.prototype.onStart=function(e){if(this.isEnabled()&&2===e.touches.length){var i=s.mousePos(this._el,e.touches[0]),n=s.mousePos(this._el,e.touches[1]);this._startVec=i.sub(n),this._gestureIntent=void 0,this._inertia=[],s.addEventListener(t.default.document,"touchmove",this._onMove,{passive:!1}),s.addEventListener(t.default.document,"touchend",this._onEnd);}},nn.prototype._getTouchEventData=function(t){var e=s.mousePos(this._el,t.touches[0]),i=s.mousePos(this._el,t.touches[1]),n=e.sub(i);return{vec:n,center:e.add(i).div(2),scale:n.mag()/this._startVec.mag(),bearing:this._rotationDisabled?0:180*n.angleWith(this._startVec)/Math.PI}},nn.prototype._onMove=function(e){if(2===e.touches.length){var i=this._getTouchEventData(e),n=i.vec,o=i.scale,r=i.bearing;if(!this._gestureIntent){var a=Math.abs(1-o)>.15;Math.abs(r)>10?this._gestureIntent="rotate":a&&(this._gestureIntent="zoom"),this._gestureIntent&&(this._map.fire(new t.Event(this._gestureIntent+"start",{originalEvent:e})),this._map.fire(new t.Event("movestart",{originalEvent:e})),this._startVec=n);}this._lastTouchEvent=e,this._frameId||(this._frameId=this._map._requestRenderFrame(this._onTouchFrame)),e.preventDefault();}},nn.prototype._onTouchFrame=function(){this._frameId=null;var e=this._gestureIntent;if(e){var i=this._map.transform;this._startScale||(this._startScale=i.scale,this._startBearing=i.bearing);var n=this._getTouchEventData(this._lastTouchEvent),o=n.center,a=n.bearing,s=n.scale,l=i.pointLocation(o),c=i.locationPoint(l);"rotate"===e&&(i.bearing=this._startBearing+a),i.zoom=i.scaleZoom(this._startScale*s),i.setLocationAtPoint(l,c),this._map.fire(new t.Event(e,{originalEvent:this._lastTouchEvent})),this._map.fire(new t.Event("move",{originalEvent:this._lastTouchEvent})),this._drainInertiaBuffer(),this._inertia.push([r.now(),s,o]);}},nn.prototype._onEnd=function(e){s.removeEventListener(t.default.document,"touchmove",this._onMove,{passive:!1}),s.removeEventListener(t.default.document,"touchend",this._onEnd);var i=this._gestureIntent,n=this._startScale;if(this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._gestureIntent,delete this._startScale,delete this._startBearing,delete this._lastTouchEvent,i){this._map.fire(new t.Event(i+"end",{originalEvent:e})),this._drainInertiaBuffer();var o=this._inertia,r=this._map;if(o.length<2)r.snapToNorth({},{originalEvent:e});else{var a=o[o.length-1],l=o[0],c=r.transform.scaleZoom(n*a[1]),u=r.transform.scaleZoom(n*l[1]),h=c-u,p=(a[0]-l[0])/1e3,d=a[2];if(0!==p&&c!==u){var f=.15*h/p;Math.abs(f)>2.5&&(f=f>0?2.5:-2.5);var m=1e3*Math.abs(f/(12*.15)),_=c+f*m/2e3;_<0&&(_=0),r.easeTo({zoom:_,duration:m,easing:en,around:this._aroundCenter?r.getCenter():r.unproject(d),noMoveStart:!0},{originalEvent:e});}else r.snapToNorth({},{originalEvent:e});}}},nn.prototype._drainInertiaBuffer=function(){for(var t=this._inertia,e=r.now();t.length>2&&e-t[0][0]>160;)t.shift();};var on={scrollZoom:Wi,boxZoom:qi,dragRotate:Hi,dragPan:Yi,keyboard:Ji,doubleClickZoom:tn,touchZoomRotate:nn};var rn=function(e){function i(i,n){e.call(this),this._moving=!1,this._zooming=!1,this.transform=i,this._bearingSnap=n.bearingSnap,t.bindAll(["_renderFrameCallback"],this);}return e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i,i.prototype.getCenter=function(){return this.transform.center},i.prototype.setCenter=function(t,e){return this.jumpTo({center:t},e)},i.prototype.panBy=function(e,i,n){return e=t.default$1.convert(e).mult(-1),this.panTo(this.transform.center,t.extend({offset:e},i),n)},i.prototype.panTo=function(e,i,n){return this.easeTo(t.extend({center:e},i),n)},i.prototype.getZoom=function(){return this.transform.zoom},i.prototype.setZoom=function(t,e){return this.jumpTo({zoom:t},e),this},i.prototype.zoomTo=function(e,i,n){return this.easeTo(t.extend({zoom:e},i),n)},i.prototype.zoomIn=function(t,e){return this.zoomTo(this.getZoom()+1,t,e),this},i.prototype.zoomOut=function(t,e){return this.zoomTo(this.getZoom()-1,t,e),this},i.prototype.getBearing=function(){return this.transform.bearing},i.prototype.setBearing=function(t,e){return this.jumpTo({bearing:t},e),this},i.prototype.rotateTo=function(e,i,n){return this.easeTo(t.extend({bearing:e},i),n)},i.prototype.resetNorth=function(e,i){return this.rotateTo(0,t.extend({duration:1e3},e),i),this},i.prototype.snapToNorth=function(t,e){return Math.abs(this.getBearing())e?1:0}),["bottom","left","right","top"]))return t.warnOnce("options.padding must be a positive number, or an Object with keys 'bottom', 'left', 'right', 'top'"),this;e=q.convert(e);var r=[(i.padding.left-i.padding.right)/2,(i.padding.top-i.padding.bottom)/2],a=Math.min(i.padding.right,i.padding.left),s=Math.min(i.padding.top,i.padding.bottom);i.offset=[i.offset[0]+r[0],i.offset[1]+r[1]];var l=t.default$1.convert(i.offset),c=this.transform,u=c.project(e.getNorthWest()),h=c.project(e.getSouthEast()),p=h.sub(u),d=(c.width-2*a-2*Math.abs(l.x))/p.x,f=(c.height-2*s-2*Math.abs(l.y))/p.y;return f<0||d<0?(t.warnOnce("Map cannot fit within canvas with the given bounds, padding, and/or offset."),this):(i.center=c.unproject(u.add(h).div(2)),i.zoom=Math.min(c.scaleZoom(c.scale*Math.min(d,f)),i.maxZoom),i.bearing=0,i.linear?this.easeTo(i,n):this.flyTo(i,n))},i.prototype.jumpTo=function(e,i){this.stop();var n=this.transform,o=!1,r=!1,a=!1;return"zoom"in e&&n.zoom!==+e.zoom&&(o=!0,n.zoom=+e.zoom),void 0!==e.center&&(n.center=W.convert(e.center)),"bearing"in e&&n.bearing!==+e.bearing&&(r=!0,n.bearing=+e.bearing),"pitch"in e&&n.pitch!==+e.pitch&&(a=!0,n.pitch=+e.pitch),this.fire(new t.Event("movestart",i)).fire(new t.Event("move",i)),o&&this.fire(new t.Event("zoomstart",i)).fire(new t.Event("zoom",i)).fire(new t.Event("zoomend",i)),r&&this.fire(new t.Event("rotatestart",i)).fire(new t.Event("rotate",i)).fire(new t.Event("rotateend",i)),a&&this.fire(new t.Event("pitchstart",i)).fire(new t.Event("pitch",i)).fire(new t.Event("pitchend",i)),this.fire(new t.Event("moveend",i))},i.prototype.easeTo=function(e,i){var n=this;this.stop(),!1===(e=t.extend({offset:[0,0],duration:500,easing:t.ease},e)).animate&&(e.duration=0);var o=this.transform,r=this.getZoom(),a=this.getBearing(),s=this.getPitch(),l="zoom"in e?+e.zoom:r,c="bearing"in e?this._normalizeBearing(e.bearing,a):a,u="pitch"in e?+e.pitch:s,h=o.centerPoint.add(t.default$1.convert(e.offset)),p=o.pointLocation(h),d=W.convert(e.center||p);this._normalizeCenter(d);var f,m,_=o.project(p),g=o.project(d).sub(_),v=o.zoomScale(l-r);return e.around&&(f=W.convert(e.around),m=o.locationPoint(f)),this._zooming=l!==r,this._rotating=a!==c,this._pitching=u!==s,this._prepareEase(i,e.noMoveStart),clearTimeout(this._easeEndTimeoutID),this._ease(function(e){if(n._zooming&&(o.zoom=t.number(r,l,e)),n._rotating&&(o.bearing=t.number(a,c,e)),n._pitching&&(o.pitch=t.number(s,u,e)),f)o.setLocationAtPoint(f,m);else{var p=o.zoomScale(o.zoom-r),d=l>r?Math.min(2,v):Math.max(.5,v),y=Math.pow(d,1-e),x=o.unproject(_.add(g.mult(e*y)).mult(p));o.setLocationAtPoint(o.renderWorldCopies?x.wrap():x,h);}n._fireMoveEvents(i);},function(){e.delayEndEvents?n._easeEndTimeoutID=setTimeout(function(){return n._afterEase(i)},e.delayEndEvents):n._afterEase(i);},e),this},i.prototype._prepareEase=function(e,i){this._moving=!0,i||this.fire(new t.Event("movestart",e)),this._zooming&&this.fire(new t.Event("zoomstart",e)),this._rotating&&this.fire(new t.Event("rotatestart",e)),this._pitching&&this.fire(new t.Event("pitchstart",e));},i.prototype._fireMoveEvents=function(e){this.fire(new t.Event("move",e)),this._zooming&&this.fire(new t.Event("zoom",e)),this._rotating&&this.fire(new t.Event("rotate",e)),this._pitching&&this.fire(new t.Event("pitch",e));},i.prototype._afterEase=function(e){var i=this._zooming,n=this._rotating,o=this._pitching;this._moving=!1,this._zooming=!1,this._rotating=!1,this._pitching=!1,i&&this.fire(new t.Event("zoomend",e)),n&&this.fire(new t.Event("rotateend",e)),o&&this.fire(new t.Event("pitchend",e)),this.fire(new t.Event("moveend",e));},i.prototype.flyTo=function(e,i){var n=this;this.stop(),e=t.extend({offset:[0,0],speed:1.2,curve:1.42,easing:t.ease},e);var o=this.transform,r=this.getZoom(),a=this.getBearing(),s=this.getPitch(),l="zoom"in e?t.clamp(+e.zoom,o.minZoom,o.maxZoom):r,c="bearing"in e?this._normalizeBearing(e.bearing,a):a,u="pitch"in e?+e.pitch:s,h=o.zoomScale(l-r),p=o.centerPoint.add(t.default$1.convert(e.offset)),d=o.pointLocation(p),f=W.convert(e.center||d);this._normalizeCenter(f);var m=o.project(d),_=o.project(f).sub(m),g=e.curve,v=Math.max(o.width,o.height),y=v/h,x=_.mag();if("minZoom"in e){var b=t.clamp(Math.min(e.minZoom,r,l),o.minZoom,o.maxZoom),w=v/o.zoomScale(b-r);g=Math.sqrt(w/x*2);}var E=g*g;function T(t){var e=(y*y-v*v+(t?-1:1)*E*E*x*x)/(2*(t?y:v)*E*x);return Math.log(Math.sqrt(e*e+1)-e)}function I(t){return(Math.exp(t)-Math.exp(-t))/2}function C(t){return(Math.exp(t)+Math.exp(-t))/2}var S=T(0),z=function(t){return C(S)/C(S+g*t)},A=function(t){return v*((C(S)*(I(e=S+g*t)/C(e))-I(S))/E)/x;var e;},R=(T(1)-S)/g;if(Math.abs(x)<1e-6||!isFinite(R)){if(Math.abs(v-y)<1e-6)return this.easeTo(e,i);var D=ye.maxDuration&&(e.duration=0),this._zooming=!0,this._rotating=a!==c,this._pitching=u!==s,this._prepareEase(i,!1),this._ease(function(e){var l=e*R,h=1/z(l);o.zoom=r+o.scaleZoom(h),n._rotating&&(o.bearing=t.number(a,c,e)),n._pitching&&(o.pitch=t.number(s,u,e));var d=o.unproject(m.add(_.mult(A(l))).mult(h));o.setLocationAtPoint(o.renderWorldCopies?d.wrap():d,p),n._fireMoveEvents(i);},function(){return n._afterEase(i)},e),this},i.prototype.isEasing=function(){return!!this._easeFrameId},i.prototype.stop=function(){if(this._easeFrameId&&(this._cancelRenderFrame(this._easeFrameId),delete this._easeFrameId,delete this._onEaseFrame),this._onEaseEnd){var t=this._onEaseEnd;delete this._onEaseEnd,t.call(this);}return this},i.prototype._ease=function(t,e,i){!1===i.animate||0===i.duration?(t(1),e()):(this._easeStart=r.now(),this._easeOptions=i,this._onEaseFrame=t,this._onEaseEnd=e,this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback));},i.prototype._renderFrameCallback=function(){var t=Math.min((r.now()-this._easeStart)/this._easeOptions.duration,1);this._onEaseFrame(this._easeOptions.easing(t)),t<1?this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback):this.stop();},i.prototype._normalizeBearing=function(e,i){e=t.wrap(e,-180,180);var n=Math.abs(e-i);return Math.abs(e-360-i)180?-360:i<-180?360:0;}},i}(t.Evented),an=function(e){void 0===e&&(e={}),this.options=e,t.bindAll(["_updateEditLink","_updateData","_updateCompact"],this);};an.prototype.getDefaultPosition=function(){return"bottom-right"},an.prototype.onAdd=function(t){var e=this.options&&this.options.compact;return this._map=t,this._container=s.create("div","mapboxgl-ctrl mapboxgl-ctrl-attrib"),e&&this._container.classList.add("mapboxgl-compact"),this._updateAttributions(),this._updateEditLink(),this._map.on("sourcedata",this._updateData),this._map.on("moveend",this._updateEditLink),void 0===e&&(this._map.on("resize",this._updateCompact),this._updateCompact()),this._container},an.prototype.onRemove=function(){s.remove(this._container),this._map.off("sourcedata",this._updateData),this._map.off("moveend",this._updateEditLink),this._map.off("resize",this._updateCompact),this._map=void 0;},an.prototype._updateEditLink=function(){var t=this._editLink;t||(t=this._editLink=this._container.querySelector(".mapbox-improve-map"));var e=[{key:"owner",value:this.styleOwner},{key:"id",value:this.styleId},{key:"access_token",value:_.ACCESS_TOKEN}];if(t){var i=e.reduce(function(t,i,n){return i.value&&(t+=i.key+"="+i.value+(n=0)return!1;return!0})).length?(this._container.innerHTML=t.join(" | "),this._container.classList.remove("mapboxgl-attrib-empty")):this._container.classList.add("mapboxgl-attrib-empty"),this._editLink=null;}},an.prototype._updateCompact=function(){this._map.getCanvasContainer().offsetWidth<=640?this._container.classList.add("mapboxgl-compact"):this._container.classList.remove("mapboxgl-compact");};var sn=function(){t.bindAll(["_updateLogo"],this);};sn.prototype.onAdd=function(t){this._map=t,this._container=s.create("div","mapboxgl-ctrl");var e=s.create("a","mapboxgl-ctrl-logo");return e.target="_blank",e.href="https://www.mapbox.com/",e.setAttribute("aria-label","Mapbox logo"),this._container.appendChild(e),this._container.style.display="none",this._map.on("sourcedata",this._updateLogo),this._updateLogo(),this._container},sn.prototype.onRemove=function(){s.remove(this._container),this._map.off("sourcedata",this._updateLogo);},sn.prototype.getDefaultPosition=function(){return"bottom-left"},sn.prototype._updateLogo=function(t){t&&"metadata"!==t.sourceDataType||(this._container.style.display=this._logoRequired()?"block":"none");},sn.prototype._logoRequired=function(){if(this._map.style){var t=this._map.style.sourceCaches;for(var e in t){if(t[e].getSource().mapbox_logo)return!0}return!1}};var ln=function(){this._queue=[],this._id=0,this._cleared=!1,this._currentlyRunning=!1;};ln.prototype.add=function(t){var e=++this._id;return this._queue.push({callback:t,id:e,cancelled:!1}),e},ln.prototype.remove=function(t){for(var e=this._currentlyRunning,i=0,n=e?this._queue.concat(e):this._queue;ie.maxZoom)throw new Error("maxZoom must be greater than minZoom");var n=new Ui(e.minZoom,e.maxZoom,e.renderWorldCopies);i.call(this,n,e),this._interactive=e.interactive,this._maxTileCacheSize=e.maxTileCacheSize,this._failIfMajorPerformanceCaveat=e.failIfMajorPerformanceCaveat,this._preserveDrawingBuffer=e.preserveDrawingBuffer,this._trackResize=e.trackResize,this._bearingSnap=e.bearingSnap,this._refreshExpiredTiles=e.refreshExpiredTiles,this._fadeDuration=e.fadeDuration,this._crossFadingFactor=1,this._collectResourceTiming=e.collectResourceTiming,this._renderTaskQueue=new ln;var o=e.transformRequest;if(this._transformRequest=o?function(t,e){return o(t,e)||{url:t}}:function(t){return{url:t}},"string"==typeof e.container){var r=t.default.document.getElementById(e.container);if(!r)throw new Error("Container '"+e.container+"' not found.");this._container=r;}else{if(!(e.container instanceof un))throw new Error("Invalid type: 'container' must be a String or HTMLElement.");this._container=e.container;}e.maxBounds&&this.setMaxBounds(e.maxBounds),t.bindAll(["_onWindowOnline","_onWindowResize","_contextLost","_contextRestored","_update","_render","_onData","_onDataLoading"],this),this._setupContainer(),this._setupPainter(),this.on("move",this._update.bind(this,!1)),this.on("zoom",this._update.bind(this,!0)),void 0!==t.default&&(t.default.addEventListener("online",this._onWindowOnline,!1),t.default.addEventListener("resize",this._onWindowResize,!1)),function(t,e){var i=t.getCanvasContainer(),n=null,o=!1;for(var r in on)t[r]=new on[r](t,e),e.interactive&&e[r]&&t[r].enable(e[r]);s.addEventListener(i,"mouseout",function(e){t.fire(new ji("mouseout",t,e));}),s.addEventListener(i,"mousedown",function(i){o=!0;var n=new ji("mousedown",t,i);t.fire(n),n.defaultPrevented||(e.interactive&&!t.doubleClickZoom.isActive()&&t.stop(),t.boxZoom.onMouseDown(i),t.boxZoom.isActive()||t.dragPan.isActive()||t.dragRotate.onMouseDown(i),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onMouseDown(i));}),s.addEventListener(i,"mouseup",function(e){var i=t.dragRotate.isActive();n&&!i&&t.fire(new ji("contextmenu",t,n)),n=null,o=!1,t.fire(new ji("mouseup",t,e));}),s.addEventListener(i,"mousemove",function(e){if(!t.dragPan.isActive()&&!t.dragRotate.isActive()){for(var n=e.toElement||e.target;n&&n!==i;)n=n.parentNode;n===i&&t.fire(new ji("mousemove",t,e));}}),s.addEventListener(i,"mouseover",function(e){for(var n=e.toElement||e.target;n&&n!==i;)n=n.parentNode;n===i&&t.fire(new ji("mouseover",t,e));}),s.addEventListener(i,"touchstart",function(i){var n=new $i("touchstart",t,i);t.fire(n),n.defaultPrevented||(e.interactive&&t.stop(),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onTouchStart(i),t.touchZoomRotate.onStart(i),t.doubleClickZoom.onTouchStart(n));},{passive:!1}),s.addEventListener(i,"touchmove",function(e){t.fire(new $i("touchmove",t,e));},{passive:!1}),s.addEventListener(i,"touchend",function(e){t.fire(new $i("touchend",t,e));}),s.addEventListener(i,"touchcancel",function(e){t.fire(new $i("touchcancel",t,e));}),s.addEventListener(i,"click",function(e){t.fire(new ji("click",t,e));}),s.addEventListener(i,"dblclick",function(e){var i=new ji("dblclick",t,e);t.fire(i),i.defaultPrevented||t.doubleClickZoom.onDblClick(i);}),s.addEventListener(i,"contextmenu",function(e){var i=t.dragRotate.isActive();o||i?o&&(n=e):t.fire(new ji("contextmenu",t,e)),e.preventDefault();}),s.addEventListener(i,"wheel",function(e){var i=new Gi("wheel",t,e);t.fire(i),i.defaultPrevented||t.scrollZoom.onWheel(e);},{passive:!1});}(this,e),this._hash=e.hash&&(new Vi).addTo(this),this._hash&&this._hash._onHashChange()||this.jumpTo({center:e.center,zoom:e.zoom,bearing:e.bearing,pitch:e.pitch}),this.resize(),e.style&&this.setStyle(e.style,{localIdeographFontFamily:e.localIdeographFontFamily}),e.attributionControl&&this.addControl(new an),this.addControl(new sn,e.logoPosition),this.on("style.load",function(){this.transform.unmodified&&this.jumpTo(this.style.stylesheet);}),this.on("data",this._onData),this.on("dataloading",this._onDataLoading);}i&&(n.__proto__=i),n.prototype=Object.create(i&&i.prototype),n.prototype.constructor=n;var o={showTileBoundaries:{configurable:!0},showCollisionBoxes:{configurable:!0},showOverdrawInspector:{configurable:!0},repaint:{configurable:!0},vertices:{configurable:!0}};return n.prototype.addControl=function(t,e){void 0===e&&t.getDefaultPosition&&(e=t.getDefaultPosition()),void 0===e&&(e="top-right");var i=t.onAdd(this),n=this._controlPositions[e];return-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},n.prototype.removeControl=function(t){return t.onRemove(this),this},n.prototype.resize=function(e){var i=this._containerDimensions(),n=i[0],o=i[1];return this._resizeCanvas(n,o),this.transform.resize(n,o),this.painter.resize(n,o),this.fire(new t.Event("movestart",e)).fire(new t.Event("move",e)).fire(new t.Event("resize",e)).fire(new t.Event("moveend",e))},n.prototype.getBounds=function(){var e=new q(this.transform.pointLocation(new t.default$1(0,this.transform.height)),this.transform.pointLocation(new t.default$1(this.transform.width,0)));return(this.transform.angle||this.transform.pitch)&&(e.extend(this.transform.pointLocation(new t.default$1(this.transform.size.x,0))),e.extend(this.transform.pointLocation(new t.default$1(0,this.transform.size.y)))),e},n.prototype.getMaxBounds=function(){return this.transform.latRange&&2===this.transform.latRange.length&&this.transform.lngRange&&2===this.transform.lngRange.length?new q([this.transform.lngRange[0],this.transform.latRange[0]],[this.transform.lngRange[1],this.transform.latRange[1]]):null},n.prototype.setMaxBounds=function(t){if(t){var e=q.convert(t);this.transform.lngRange=[e.getWest(),e.getEast()],this.transform.latRange=[e.getSouth(),e.getNorth()],this.transform._constrain(),this._update();}else null==t&&(this.transform.lngRange=null,this.transform.latRange=null,this._update());return this},n.prototype.setMinZoom=function(t){if((t=null==t?0:t)>=0&&t<=this.transform.maxZoom)return this.transform.minZoom=t,this._update(),this.getZoom()=this.transform.minZoom)return this.transform.maxZoom=t,this._update(),this.getZoom()>t&&this.setZoom(t),this;throw new Error("maxZoom must be greater than the current minZoom")},n.prototype.getRenderWorldCopies=function(){return this.transform.renderWorldCopies},n.prototype.setRenderWorldCopies=function(t){return this.transform.renderWorldCopies=t,this._update(),this},n.prototype.getMaxZoom=function(){return this.transform.maxZoom},n.prototype.project=function(t){return this.transform.locationPoint(W.convert(t))},n.prototype.unproject=function(e){return this.transform.pointLocation(t.default$1.convert(e))},n.prototype.isMoving=function(){return this._moving||this.dragPan.isActive()||this.dragRotate.isActive()||this.scrollZoom.isActive()},n.prototype.isZooming=function(){return this._zooming||this.scrollZoom.isActive()},n.prototype.isRotating=function(){return this._rotating||this.dragRotate.isActive()},n.prototype.on=function(t,e,n){var o,r=this;if(void 0===n)return i.prototype.on.call(this,t,e);var a=function(){if("mouseenter"===t||"mouseover"===t){var i=!1;return{layer:e,listener:n,delegates:{mousemove:function(o){var a=r.getLayer(e)?r.queryRenderedFeatures(o.point,{layers:[e]}):[];a.length?i||(i=!0,n.call(r,new ji(t,r,o.originalEvent,{features:a}))):i=!1;},mouseout:function(){i=!1;}}}}if("mouseleave"===t||"mouseout"===t){var a=!1;return{layer:e,listener:n,delegates:{mousemove:function(i){(r.getLayer(e)?r.queryRenderedFeatures(i.point,{layers:[e]}):[]).length?a=!0:a&&(a=!1,n.call(r,new ji(t,r,i.originalEvent)));},mouseout:function(e){a&&(a=!1,n.call(r,new ji(t,r,e.originalEvent)));}}}}return{layer:e,listener:n,delegates:(o={},o[t]=function(t){var i=r.getLayer(e)?r.queryRenderedFeatures(t.point,{layers:[e]}):[];i.length&&(t.features=i,n.call(r,t),delete t.features);},o)}}();for(var s in this._delegatedListeners=this._delegatedListeners||{},this._delegatedListeners[t]=this._delegatedListeners[t]||[],this._delegatedListeners[t].push(a),a.delegates)r.on(s,a.delegates[s]);return this},n.prototype.off=function(t,e,n){if(void 0===n)return i.prototype.off.call(this,t,e);if(this._delegatedListeners&&this._delegatedListeners[t])for(var o=this._delegatedListeners[t],r=0;r180;){var a=i.locationPoint(t);if(a.x>=0&&a.y>=0&&a.x<=i.width&&a.y<=i.height)break;t.lng>i.center.lng?t.lng-=360:t.lng+=360;}return t}mn.prototype._rotateCompassArrow=function(){var t="rotate("+this._map.transform.angle*(180/Math.PI)+"deg)";this._compassArrow.style.transform=t;},mn.prototype.onAdd=function(t){return this._map=t,this.options.showCompass&&(this._map.on("rotate",this._rotateCompassArrow),this._rotateCompassArrow(),this._handler=new Hi(t,{button:"left",element:this._compass}),this._handler.enable()),this._container},mn.prototype.onRemove=function(){s.remove(this._container),this.options.showCompass&&(this._map.off("rotate",this._rotateCompassArrow),this._handler.disable(),delete this._handler),delete this._map;},mn.prototype._createButton=function(t,e,i){var n=s.create("button",t,this._container);return n.type="button",n.setAttribute("aria-label",e),n.addEventListener("click",i),n};var gn={center:"translate(-50%,-50%)",top:"translate(-50%,0)","top-left":"translate(0,0)","top-right":"translate(-100%,0)",bottom:"translate(-50%,-100%)","bottom-left":"translate(0,-100%)","bottom-right":"translate(-100%,-100%)",left:"translate(0,-50%)",right:"translate(-100%,-50%)"};function vn(t,e,i){var n=t.classList;for(var o in gn)n.remove("mapboxgl-"+i+"-anchor-"+o);n.add("mapboxgl-"+i+"-anchor-"+e);}var yn=function(e){if((arguments[0]instanceof t.default.HTMLElement||2===arguments.length)&&(e=t.extend({element:e},arguments[1])),t.bindAll(["_update","_onMapClick"],this),this._anchor=e&&e.anchor||"center",this._color=e&&e.color||"#3FB1CE",e&&e.element)this._element=e.element,this._offset=t.default$1.convert(e&&e.offset||[0,0]);else{this._defaultMarker=!0,this._element=s.create("div");var i=s.createNS("http://www.w3.org/2000/svg","svg");i.setAttributeNS(null,"height","41px"),i.setAttributeNS(null,"width","27px"),i.setAttributeNS(null,"viewBox","0 0 27 41");var n=s.createNS("http://www.w3.org/2000/svg","g");n.setAttributeNS(null,"stroke","none"),n.setAttributeNS(null,"stroke-width","1"),n.setAttributeNS(null,"fill","none"),n.setAttributeNS(null,"fill-rule","evenodd");var o=s.createNS("http://www.w3.org/2000/svg","g");o.setAttributeNS(null,"fill-rule","nonzero");var r=s.createNS("http://www.w3.org/2000/svg","g");r.setAttributeNS(null,"transform","translate(3.0, 29.0)"),r.setAttributeNS(null,"fill","#000000");for(var a=0,l=[{rx:"10.5",ry:"5.25002273"},{rx:"10.5",ry:"5.25002273"},{rx:"9.5",ry:"4.77275007"},{rx:"8.5",ry:"4.29549936"},{rx:"7.5",ry:"3.81822308"},{rx:"6.5",ry:"3.34094679"},{rx:"5.5",ry:"2.86367051"},{rx:"4.5",ry:"2.38636864"}];a5280)Cn(e,c,p/5280,"mi");else Cn(e,c,p,"ft");}else if(i&&"nautical"===i.unit){Cn(e,c,h/1852,"nm");}else Cn(e,c,h,"m");}function Cn(t,e,i,n){var o,r,a,s=(o=i,(r=Math.pow(10,(""+Math.floor(o)).length-1))*(a=(a=o/r)>=10?10:a>=5?5:a>=3?3:a>=2?2:1)),l=s/i;"m"===n&&s>=1e3&&(s/=1e3,n="km"),t.style.width=e*l+"px",t.innerHTML=s+n;}Tn.prototype.getDefaultPosition=function(){return"bottom-left"},Tn.prototype._onMove=function(){In(this._map,this._container,this.options);},Tn.prototype.onAdd=function(t){return this._map=t,this._container=s.create("div","mapboxgl-ctrl mapboxgl-ctrl-scale",t.getContainer()),this._map.on("move",this._onMove),this._onMove(),this._container},Tn.prototype.onRemove=function(){s.remove(this._container),this._map.off("move",this._onMove),this._map=void 0;},Tn.prototype.setUnit=function(t){this.options.unit=t,In(this._map,this._container,this.options);};var Sn=function(){this._fullscreen=!1,t.bindAll(["_onClickFullscreen","_changeIcon"],this),"onfullscreenchange"in t.default.document?this._fullscreenchange="fullscreenchange":"onmozfullscreenchange"in t.default.document?this._fullscreenchange="mozfullscreenchange":"onwebkitfullscreenchange"in t.default.document?this._fullscreenchange="webkitfullscreenchange":"onmsfullscreenchange"in t.default.document&&(this._fullscreenchange="MSFullscreenChange"),this._className="mapboxgl-ctrl";};Sn.prototype.onAdd=function(e){return this._map=e,this._mapContainer=this._map.getContainer(),this._container=s.create("div",this._className+" mapboxgl-ctrl-group"),this._checkFullscreenSupport()?this._setupUI():(this._container.style.display="none",t.warnOnce("This device does not support fullscreen mode.")),this._container},Sn.prototype.onRemove=function(){s.remove(this._container),this._map=null,t.default.document.removeEventListener(this._fullscreenchange,this._changeIcon);},Sn.prototype._checkFullscreenSupport=function(){return!!(t.default.document.fullscreenEnabled||t.default.document.mozFullScreenEnabled||t.default.document.msFullscreenEnabled||t.default.document.webkitFullscreenEnabled)},Sn.prototype._setupUI=function(){var e=this._fullscreenButton=s.create("button",this._className+"-icon "+this._className+"-fullscreen",this._container);e.setAttribute("aria-label","Toggle fullscreen"),e.type="button",this._fullscreenButton.addEventListener("click",this._onClickFullscreen),t.default.document.addEventListener(this._fullscreenchange,this._changeIcon);},Sn.prototype._isFullscreen=function(){return this._fullscreen},Sn.prototype._changeIcon=function(){(t.default.document.fullscreenElement||t.default.document.mozFullScreenElement||t.default.document.webkitFullscreenElement||t.default.document.msFullscreenElement)===this._mapContainer!==this._fullscreen&&(this._fullscreen=!this._fullscreen,this._fullscreenButton.classList.toggle(this._className+"-shrink"),this._fullscreenButton.classList.toggle(this._className+"-fullscreen"));},Sn.prototype._onClickFullscreen=function(){this._isFullscreen()?t.default.document.exitFullscreen?t.default.document.exitFullscreen():t.default.document.mozCancelFullScreen?t.default.document.mozCancelFullScreen():t.default.document.msExitFullscreen?t.default.document.msExitFullscreen():t.default.document.webkitCancelFullScreen&&t.default.document.webkitCancelFullScreen():this._mapContainer.requestFullscreen?this._mapContainer.requestFullscreen():this._mapContainer.mozRequestFullScreen?this._mapContainer.mozRequestFullScreen():this._mapContainer.msRequestFullscreen?this._mapContainer.msRequestFullscreen():this._mapContainer.webkitRequestFullscreen&&this._mapContainer.webkitRequestFullscreen();};var zn={closeButton:!0,closeOnClick:!0},An=function(e){function i(i){e.call(this),this.options=t.extend(Object.create(zn),i),t.bindAll(["_update","_onClickClose"],this);}return e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i,i.prototype.addTo=function(e){return this._map=e,this._map.on("move",this._update),this.options.closeOnClick&&this._map.on("click",this._onClickClose),this._update(),this.fire(new t.Event("open")),this},i.prototype.isOpen=function(){return!!this._map},i.prototype.remove=function(){return this._content&&s.remove(this._content),this._container&&(s.remove(this._container),delete this._container),this._map&&(this._map.off("move",this._update),this._map.off("click",this._onClickClose),delete this._map),this.fire(new t.Event("close")),this},i.prototype.getLngLat=function(){return this._lngLat},i.prototype.setLngLat=function(t){return this._lngLat=W.convert(t),this._pos=null,this._update(),this},i.prototype.setText=function(e){return this.setDOMContent(t.default.document.createTextNode(e))},i.prototype.setHTML=function(e){var i,n=t.default.document.createDocumentFragment(),o=t.default.document.createElement("body");for(o.innerHTML=e;i=o.firstChild;)n.appendChild(i);return this.setDOMContent(n)},i.prototype.setDOMContent=function(t){return this._createContent(),this._content.appendChild(t),this._update(),this},i.prototype._createContent=function(){this._content&&s.remove(this._content),this._content=s.create("div","mapboxgl-popup-content",this._container),this.options.closeButton&&(this._closeButton=s.create("button","mapboxgl-popup-close-button",this._content),this._closeButton.type="button",this._closeButton.setAttribute("aria-label","Close popup"),this._closeButton.innerHTML="×",this._closeButton.addEventListener("click",this._onClickClose));},i.prototype._update=function(){if(this._map&&this._lngLat&&this._content){this._container||(this._container=s.create("div","mapboxgl-popup",this._map.getContainer()),this._tip=s.create("div","mapboxgl-popup-tip",this._container),this._container.appendChild(this._content)),this._map.transform.renderWorldCopies&&(this._lngLat=_n(this._lngLat,this._pos,this._map.transform));var e=this._pos=this._map.project(this._lngLat),i=this.options.anchor,n=function e(i){if(i){if("number"==typeof i){var n=Math.round(Math.sqrt(.5*Math.pow(i,2)));return{center:new t.default$1(0,0),top:new t.default$1(0,i),"top-left":new t.default$1(n,n),"top-right":new t.default$1(-n,n),bottom:new t.default$1(0,-i),"bottom-left":new t.default$1(n,-n),"bottom-right":new t.default$1(-n,-n),left:new t.default$1(i,0),right:new t.default$1(-i,0)}}if(i instanceof t.default$1||Array.isArray(i)){var o=t.default$1.convert(i);return{center:o,top:o,"top-left":o,"top-right":o,bottom:o,"bottom-left":o,"bottom-right":o,left:o,right:o}}return{center:t.default$1.convert(i.center||[0,0]),top:t.default$1.convert(i.top||[0,0]),"top-left":t.default$1.convert(i["top-left"]||[0,0]),"top-right":t.default$1.convert(i["top-right"]||[0,0]),bottom:t.default$1.convert(i.bottom||[0,0]),"bottom-left":t.default$1.convert(i["bottom-left"]||[0,0]),"bottom-right":t.default$1.convert(i["bottom-right"]||[0,0]),left:t.default$1.convert(i.left||[0,0]),right:t.default$1.convert(i.right||[0,0])}}return e(new t.default$1(0,0))}(this.options.offset);if(!i){var o,r=this._container.offsetWidth,a=this._container.offsetHeight;o=e.y+n.bottom.ythis._map.transform.height-a?["bottom"]:[],e.xthis._map.transform.width-r/2&&o.push("right"),i=0===o.length?"bottom":o.join("-");}var l=e.add(n[i]).round();s.setTransform(this._container,gn[i]+" translate("+l.x+"px,"+l.y+"px)"),vn(this._container,i,"popup");}},i.prototype._onClickClose=function(){this.remove();},i}(t.Evented);var Rn={version:"0.45.0",supported:e,workerCount:Math.max(Math.floor(r.hardwareConcurrency/2),1),setRTLTextPlugin:t.setRTLTextPlugin,Map:pn,NavigationControl:mn,GeolocateControl:wn,AttributionControl:an,ScaleControl:Tn,FullscreenControl:Sn,Popup:An,Marker:yn,Style:Qe,LngLat:W,LngLatBounds:q,Point:t.default$1,Evented:t.Evented,config:_,get accessToken(){return _.ACCESS_TOKEN},set accessToken(t){_.ACCESS_TOKEN=t;},workerUrl:""};return Rn}); + +// + +return mapboxgl; + +}))); + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],410:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createTable + +var chull = _dereq_('convex-hull') + +function constructVertex(d, a, b) { + var x = new Array(d) + for(var i=0; i row[1][2]) + quaternion[0] = -quaternion[0] + if (row[0][2] > row[2][0]) + quaternion[1] = -quaternion[1] + if (row[1][0] > row[0][1]) + quaternion[2] = -quaternion[2] + return true +} + +//will be replaced by gl-vec4 eventually +function vec4multMat4(out, a, m) { + var x = a[0], y = a[1], z = a[2], w = a[3]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; + return out; +} + +//gets upper-left of a 4x4 matrix into a 3x3 of vectors +function mat3from4(out, mat4x4) { + out[0][0] = mat4x4[0] + out[0][1] = mat4x4[1] + out[0][2] = mat4x4[2] + + out[1][0] = mat4x4[4] + out[1][1] = mat4x4[5] + out[1][2] = mat4x4[6] + + out[2][0] = mat4x4[8] + out[2][1] = mat4x4[9] + out[2][2] = mat4x4[10] +} + +function combine(out, a, b, scale1, scale2) { + out[0] = a[0] * scale1 + b[0] * scale2 + out[1] = a[1] * scale1 + b[1] * scale2 + out[2] = a[2] * scale1 + b[2] * scale2 +} +},{"./normalize":412,"gl-mat4/clone":248,"gl-mat4/create":249,"gl-mat4/determinant":250,"gl-mat4/invert":254,"gl-mat4/transpose":264,"gl-vec3/cross":317,"gl-vec3/dot":322,"gl-vec3/length":332,"gl-vec3/normalize":339}],412:[function(_dereq_,module,exports){ +module.exports = function normalize(out, mat) { + var m44 = mat[15] + // Cannot normalize. + if (m44 === 0) + return false + var scale = 1 / m44 + for (var i=0; i<16; i++) + out[i] = mat[i] * scale + return true +} +},{}],413:[function(_dereq_,module,exports){ +var lerp = _dereq_('gl-vec3/lerp') + +var recompose = _dereq_('mat4-recompose') +var decompose = _dereq_('mat4-decompose') +var determinant = _dereq_('gl-mat4/determinant') +var slerp = _dereq_('quat-slerp') + +var state0 = state() +var state1 = state() +var tmp = state() + +module.exports = interpolate +function interpolate(out, start, end, alpha) { + if (determinant(start) === 0 || determinant(end) === 0) + return false + + //decompose the start and end matrices into individual components + var r0 = decompose(start, state0.translate, state0.scale, state0.skew, state0.perspective, state0.quaternion) + var r1 = decompose(end, state1.translate, state1.scale, state1.skew, state1.perspective, state1.quaternion) + if (!r0 || !r1) + return false + + + //now lerp/slerp the start and end components into a temporary lerp(tmptranslate, state0.translate, state1.translate, alpha) + lerp(tmp.translate, state0.translate, state1.translate, alpha) + lerp(tmp.skew, state0.skew, state1.skew, alpha) + lerp(tmp.scale, state0.scale, state1.scale, alpha) + lerp(tmp.perspective, state0.perspective, state1.perspective, alpha) + slerp(tmp.quaternion, state0.quaternion, state1.quaternion, alpha) + + //and recompose into our 'out' matrix + recompose(out, tmp.translate, tmp.scale, tmp.skew, tmp.perspective, tmp.quaternion) + return true +} + +function state() { + return { + translate: vec3(), + scale: vec3(1), + skew: vec3(), + perspective: vec4(), + quaternion: vec4() + } +} + +function vec3(n) { + return [n||0,n||0,n||0] +} + +function vec4() { + return [0,0,0,1] +} +},{"gl-mat4/determinant":250,"gl-vec3/lerp":333,"mat4-decompose":411,"mat4-recompose":414,"quat-slerp":466}],414:[function(_dereq_,module,exports){ +/* +Input: translation ; a 3 component vector + scale ; a 3 component vector + skew ; skew factors XY,XZ,YZ represented as a 3 component vector + perspective ; a 4 component vector + quaternion ; a 4 component vector +Output: matrix ; a 4x4 matrix + +From: http://www.w3.org/TR/css3-transforms/#recomposing-to-a-3d-matrix +*/ + +var mat4 = { + identity: _dereq_('gl-mat4/identity'), + translate: _dereq_('gl-mat4/translate'), + multiply: _dereq_('gl-mat4/multiply'), + create: _dereq_('gl-mat4/create'), + scale: _dereq_('gl-mat4/scale'), + fromRotationTranslation: _dereq_('gl-mat4/fromRotationTranslation') +} + +var rotationMatrix = mat4.create() +var temp = mat4.create() + +module.exports = function recomposeMat4(matrix, translation, scale, skew, perspective, quaternion) { + mat4.identity(matrix) + + //apply translation & rotation + mat4.fromRotationTranslation(matrix, quaternion, translation) + + //apply perspective + matrix[3] = perspective[0] + matrix[7] = perspective[1] + matrix[11] = perspective[2] + matrix[15] = perspective[3] + + // apply skew + // temp is a identity 4x4 matrix initially + mat4.identity(temp) + + if (skew[2] !== 0) { + temp[9] = skew[2] + mat4.multiply(matrix, matrix, temp) + } + + if (skew[1] !== 0) { + temp[9] = 0 + temp[8] = skew[1] + mat4.multiply(matrix, matrix, temp) + } + + if (skew[0] !== 0) { + temp[8] = 0 + temp[4] = skew[0] + mat4.multiply(matrix, matrix, temp) + } + + //apply scale + mat4.scale(matrix, matrix, scale) + return matrix +} +},{"gl-mat4/create":249,"gl-mat4/fromRotationTranslation":252,"gl-mat4/identity":253,"gl-mat4/multiply":256,"gl-mat4/scale":262,"gl-mat4/translate":263}],415:[function(_dereq_,module,exports){ +'use strict'; +module.exports = Math.log2 || function (x) { + return Math.log(x) * Math.LOG2E; +}; + +},{}],416:[function(_dereq_,module,exports){ +'use strict' + +var bsearch = _dereq_('binary-search-bounds') +var m4interp = _dereq_('mat4-interpolate') +var invert44 = _dereq_('gl-mat4/invert') +var rotateX = _dereq_('gl-mat4/rotateX') +var rotateY = _dereq_('gl-mat4/rotateY') +var rotateZ = _dereq_('gl-mat4/rotateZ') +var lookAt = _dereq_('gl-mat4/lookAt') +var translate = _dereq_('gl-mat4/translate') +var scale = _dereq_('gl-mat4/scale') +var normalize = _dereq_('gl-vec3/normalize') + +var DEFAULT_CENTER = [0,0,0] + +module.exports = createMatrixCameraController + +function MatrixCameraController(initialMatrix) { + this._components = initialMatrix.slice() + this._time = [0] + this.prevMatrix = initialMatrix.slice() + this.nextMatrix = initialMatrix.slice() + this.computedMatrix = initialMatrix.slice() + this.computedInverse = initialMatrix.slice() + this.computedEye = [0,0,0] + this.computedUp = [0,0,0] + this.computedCenter = [0,0,0] + this.computedRadius = [0] + this._limits = [-Infinity, Infinity] +} + +var proto = MatrixCameraController.prototype + +proto.recalcMatrix = function(t) { + var time = this._time + var tidx = bsearch.le(time, t) + var mat = this.computedMatrix + if(tidx < 0) { + return + } + var comps = this._components + if(tidx === time.length-1) { + var ptr = 16*tidx + for(var i=0; i<16; ++i) { + mat[i] = comps[ptr++] + } + } else { + var dt = (time[tidx+1] - time[tidx]) + var ptr = 16*tidx + var prev = this.prevMatrix + var allEqual = true + for(var i=0; i<16; ++i) { + prev[i] = comps[ptr++] + } + var next = this.nextMatrix + for(var i=0; i<16; ++i) { + next[i] = comps[ptr++] + allEqual = allEqual && (prev[i] === next[i]) + } + if(dt < 1e-6 || allEqual) { + for(var i=0; i<16; ++i) { + mat[i] = prev[i] + } + } else { + m4interp(mat, prev, next, (t - time[tidx])/dt) + } + } + + var up = this.computedUp + up[0] = mat[1] + up[1] = mat[5] + up[2] = mat[9] + normalize(up, up) + + var imat = this.computedInverse + invert44(imat, mat) + var eye = this.computedEye + var w = imat[15] + eye[0] = imat[12]/w + eye[1] = imat[13]/w + eye[2] = imat[14]/w + + var center = this.computedCenter + var radius = Math.exp(this.computedRadius[0]) + for(var i=0; i<3; ++i) { + center[i] = eye[i] - mat[2+4*i] * radius + } +} + +proto.idle = function(t) { + if(t < this.lastT()) { + return + } + var mc = this._components + var ptr = mc.length-16 + for(var i=0; i<16; ++i) { + mc.push(mc[ptr++]) + } + this._time.push(t) +} + +proto.flush = function(t) { + var idx = bsearch.gt(this._time, t) - 2 + if(idx < 0) { + return + } + this._time.splice(0, idx) + this._components.splice(0, 16*idx) +} + +proto.lastT = function() { + return this._time[this._time.length-1] +} + +proto.lookAt = function(t, eye, center, up) { + this.recalcMatrix(t) + eye = eye || this.computedEye + center = center || DEFAULT_CENTER + up = up || this.computedUp + this.setMatrix(t, lookAt(this.computedMatrix, eye, center, up)) + var d2 = 0.0 + for(var i=0; i<3; ++i) { + d2 += Math.pow(center[i] - eye[i], 2) + } + d2 = Math.log(Math.sqrt(d2)) + this.computedRadius[0] = d2 +} + +proto.rotate = function(t, yaw, pitch, roll) { + this.recalcMatrix(t) + var mat = this.computedInverse + if(yaw) rotateY(mat, mat, yaw) + if(pitch) rotateX(mat, mat, pitch) + if(roll) rotateZ(mat, mat, roll) + this.setMatrix(t, invert44(this.computedMatrix, mat)) +} + +var tvec = [0,0,0] + +proto.pan = function(t, dx, dy, dz) { + tvec[0] = -(dx || 0.0) + tvec[1] = -(dy || 0.0) + tvec[2] = -(dz || 0.0) + this.recalcMatrix(t) + var mat = this.computedInverse + translate(mat, mat, tvec) + this.setMatrix(t, invert44(mat, mat)) +} + +proto.translate = function(t, dx, dy, dz) { + tvec[0] = dx || 0.0 + tvec[1] = dy || 0.0 + tvec[2] = dz || 0.0 + this.recalcMatrix(t) + var mat = this.computedMatrix + translate(mat, mat, tvec) + this.setMatrix(t, mat) +} + +proto.setMatrix = function(t, mat) { + if(t < this.lastT()) { + return + } + this._time.push(t) + for(var i=0; i<16; ++i) { + this._components.push(mat[i]) + } +} + +proto.setDistance = function(t, d) { + this.computedRadius[0] = d +} + +proto.setDistanceLimits = function(a,b) { + var lim = this._limits + lim[0] = a + lim[1] = b +} + +proto.getDistanceLimits = function(out) { + var lim = this._limits + if(out) { + out[0] = lim[0] + out[1] = lim[1] + return out + } + return lim +} + +function createMatrixCameraController(options) { + options = options || {} + var matrix = options.matrix || + [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + return new MatrixCameraController(matrix) +} + +},{"binary-search-bounds":79,"gl-mat4/invert":254,"gl-mat4/lookAt":255,"gl-mat4/rotateX":259,"gl-mat4/rotateY":260,"gl-mat4/rotateZ":261,"gl-mat4/scale":262,"gl-mat4/translate":263,"gl-vec3/normalize":339,"mat4-interpolate":413}],417:[function(_dereq_,module,exports){ +'use strict' + +module.exports = monotoneConvexHull2D + +var orient = _dereq_('robust-orientation')[3] + +function monotoneConvexHull2D(points) { + var n = points.length + + if(n < 3) { + var result = new Array(n) + for(var i=0; i 1 && orient( + points[lower[m-2]], + points[lower[m-1]], + p) <= 0) { + m -= 1 + lower.pop() + } + lower.push(idx) + + //Insert into upper list + m = upper.length + while(m > 1 && orient( + points[upper[m-2]], + points[upper[m-1]], + p) >= 0) { + m -= 1 + upper.pop() + } + upper.push(idx) + } + + //Merge lists together + var result = new Array(upper.length + lower.length - 2) + var ptr = 0 + for(var i=0, nl=lower.length; i0; --j) { + result[ptr++] = upper[j] + } + + //Return result + return result +} +},{"robust-orientation":486}],418:[function(_dereq_,module,exports){ +'use strict' + +module.exports = mouseListen + +var mouse = _dereq_('mouse-event') + +function mouseListen (element, callback) { + if (!callback) { + callback = element + element = window + } + + var buttonState = 0 + var x = 0 + var y = 0 + var mods = { + shift: false, + alt: false, + control: false, + meta: false + } + var attached = false + + function updateMods (ev) { + var changed = false + if ('altKey' in ev) { + changed = changed || ev.altKey !== mods.alt + mods.alt = !!ev.altKey + } + if ('shiftKey' in ev) { + changed = changed || ev.shiftKey !== mods.shift + mods.shift = !!ev.shiftKey + } + if ('ctrlKey' in ev) { + changed = changed || ev.ctrlKey !== mods.control + mods.control = !!ev.ctrlKey + } + if ('metaKey' in ev) { + changed = changed || ev.metaKey !== mods.meta + mods.meta = !!ev.metaKey + } + return changed + } + + function handleEvent (nextButtons, ev) { + var nextX = mouse.x(ev) + var nextY = mouse.y(ev) + if ('buttons' in ev) { + nextButtons = ev.buttons | 0 + } + if (nextButtons !== buttonState || + nextX !== x || + nextY !== y || + updateMods(ev)) { + buttonState = nextButtons | 0 + x = nextX || 0 + y = nextY || 0 + callback && callback(buttonState, x, y, mods) + } + } + + function clearState (ev) { + handleEvent(0, ev) + } + + function handleBlur () { + if (buttonState || + x || + y || + mods.shift || + mods.alt || + mods.meta || + mods.control) { + x = y = 0 + buttonState = 0 + mods.shift = mods.alt = mods.control = mods.meta = false + callback && callback(0, 0, 0, mods) + } + } + + function handleMods (ev) { + if (updateMods(ev)) { + callback && callback(buttonState, x, y, mods) + } + } + + function handleMouseMove (ev) { + if (mouse.buttons(ev) === 0) { + handleEvent(0, ev) + } else { + handleEvent(buttonState, ev) + } + } + + function handleMouseDown (ev) { + handleEvent(buttonState | mouse.buttons(ev), ev) + } + + function handleMouseUp (ev) { + handleEvent(buttonState & ~mouse.buttons(ev), ev) + } + + function attachListeners () { + if (attached) { + return + } + attached = true + + element.addEventListener('mousemove', handleMouseMove) + + element.addEventListener('mousedown', handleMouseDown) + + element.addEventListener('mouseup', handleMouseUp) + + element.addEventListener('mouseleave', clearState) + element.addEventListener('mouseenter', clearState) + element.addEventListener('mouseout', clearState) + element.addEventListener('mouseover', clearState) + + element.addEventListener('blur', handleBlur) + + element.addEventListener('keyup', handleMods) + element.addEventListener('keydown', handleMods) + element.addEventListener('keypress', handleMods) + + if (element !== window) { + window.addEventListener('blur', handleBlur) + + window.addEventListener('keyup', handleMods) + window.addEventListener('keydown', handleMods) + window.addEventListener('keypress', handleMods) + } + } + + function detachListeners () { + if (!attached) { + return + } + attached = false + + element.removeEventListener('mousemove', handleMouseMove) + + element.removeEventListener('mousedown', handleMouseDown) + + element.removeEventListener('mouseup', handleMouseUp) + + element.removeEventListener('mouseleave', clearState) + element.removeEventListener('mouseenter', clearState) + element.removeEventListener('mouseout', clearState) + element.removeEventListener('mouseover', clearState) + + element.removeEventListener('blur', handleBlur) + + element.removeEventListener('keyup', handleMods) + element.removeEventListener('keydown', handleMods) + element.removeEventListener('keypress', handleMods) + + if (element !== window) { + window.removeEventListener('blur', handleBlur) + + window.removeEventListener('keyup', handleMods) + window.removeEventListener('keydown', handleMods) + window.removeEventListener('keypress', handleMods) + } + } + + // Attach listeners + attachListeners() + + var result = { + element: element + } + + Object.defineProperties(result, { + enabled: { + get: function () { return attached }, + set: function (f) { + if (f) { + attachListeners() + } else { + detachListeners() + } + }, + enumerable: true + }, + buttons: { + get: function () { return buttonState }, + enumerable: true + }, + x: { + get: function () { return x }, + enumerable: true + }, + y: { + get: function () { return y }, + enumerable: true + }, + mods: { + get: function () { return mods }, + enumerable: true + } + }) + + return result +} + +},{"mouse-event":420}],419:[function(_dereq_,module,exports){ +var rootPosition = { left: 0, top: 0 } + +module.exports = mouseEventOffset +function mouseEventOffset (ev, target, out) { + target = target || ev.currentTarget || ev.srcElement + if (!Array.isArray(out)) { + out = [ 0, 0 ] + } + var cx = ev.clientX || 0 + var cy = ev.clientY || 0 + var rect = getBoundingClientOffset(target) + out[0] = cx - rect.left + out[1] = cy - rect.top + return out +} + +function getBoundingClientOffset (element) { + if (element === window || + element === document || + element === document.body) { + return rootPosition + } else { + return element.getBoundingClientRect() + } +} + +},{}],420:[function(_dereq_,module,exports){ +'use strict' + +function mouseButtons(ev) { + if(typeof ev === 'object') { + if('buttons' in ev) { + return ev.buttons + } else if('which' in ev) { + var b = ev.which + if(b === 2) { + return 4 + } else if(b === 3) { + return 2 + } else if(b > 0) { + return 1<<(b-1) + } + } else if('button' in ev) { + var b = ev.button + if(b === 1) { + return 4 + } else if(b === 2) { + return 2 + } else if(b >= 0) { + return 1< 0) { + stepVal.push(stride(i, order[j-1]) + "*" + shape(order[j-1]) ) + } + vars.push(step(i,order[j]) + "=(" + stepVal.join("-") + ")|0") + } + } + //Create index variables + for(var i=0; i=0; --i) { + sizeVariable.push(shape(order[i])) + } + //Previous phases and vertex_ids + vars.push(POOL_SIZE + "=(" + sizeVariable.join("*") + ")|0", + PHASES + "=mallocUint32(" + POOL_SIZE + ")", + VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")", + POINTER + "=0") + //Create cube variables for phases + vars.push(pcube(0) + "=0") + for(var j=1; j<(1<=0; --i) { + forLoopBegin(i, 0) + } + var phaseFuncArgs = [] + for(var i=0; i0; k=(k-1)&subset) { + faceArgs.push(VERTEX_IDS + "[" + POINTER + "+" + pdelta(k) + "]") + } + faceArgs.push(vert(0)) + for(var k=0; k0){", + index(order[i]), "=1;") + createLoop(i-1, mask|(1< 0") + } + if(typeof args.vertex !== "function") { + error("Must specify vertex creation function") + } + if(typeof args.cell !== "function") { + error("Must specify cell creation function") + } + if(typeof args.phase !== "function") { + error("Must specify phase function") + } + var getters = args.getters || [] + var typesig = new Array(arrays) + for(var i=0; i= 0) { + typesig[i] = true + } else { + typesig[i] = false + } + } + return compileSurfaceProcedure( + args.vertex, + args.cell, + args.phase, + scalars, + order, + typesig) +} +},{"typedarray-pool":522}],423:[function(_dereq_,module,exports){ +"use strict" + + + +var fill = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_1_arg1_=_inline_1_arg2_.apply(void 0,_inline_1_arg0_)}","args":[{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64}) + +module.exports = function(array, f) { + fill(array, f) + return array +} + +},{"cwise/lib/wrapper":137}],424:[function(_dereq_,module,exports){ +'use strict' + +module.exports = gradient + +var dup = _dereq_('dup') +var cwiseCompiler = _dereq_('cwise-compiler') + +var TEMPLATE_CACHE = {} +var GRADIENT_CACHE = {} + +var EmptyProc = { + body: "", + args: [], + thisVars: [], + localVars: [] +} + +var centralDiff = cwiseCompiler({ + args: [ 'array', 'array', 'array' ], + pre: EmptyProc, + post: EmptyProc, + body: { + args: [ { + name: 'out', + lvalue: true, + rvalue: false, + count: 1 + }, { + name: 'left', + lvalue: false, + rvalue: true, + count: 1 + }, { + name: 'right', + lvalue: false, + rvalue: true, + count: 1 + }], + body: "out=0.5*(left-right)", + thisVars: [], + localVars: [] + }, + funcName: 'cdiff' +}) + +var zeroOut = cwiseCompiler({ + args: [ 'array' ], + pre: EmptyProc, + post: EmptyProc, + body: { + args: [ { + name: 'out', + lvalue: true, + rvalue: false, + count: 1 + }], + body: "out=0", + thisVars: [], + localVars: [] + }, + funcName: 'zero' +}) + +function generateTemplate(d) { + if(d in TEMPLATE_CACHE) { + return TEMPLATE_CACHE[d] + } + var code = [] + for(var i=0; i= 0) { + pickStr.push('0') + } else if(facet.indexOf(-(i+1)) >= 0) { + pickStr.push('s['+i+']-1') + } else { + pickStr.push('-1') + loStr.push('1') + hiStr.push('s['+i+']-2') + } + } + var boundStr = '.lo(' + loStr.join() + ').hi(' + hiStr.join() + ')' + if(loStr.length === 0) { + boundStr = '' + } + + if(cod > 0) { + code.push('if(1') + for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { + continue + } + code.push('&&s[', i, ']>2') + } + code.push('){grad', cod, '(src.pick(', pickStr.join(), ')', boundStr) + for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { + continue + } + code.push(',dst.pick(', pickStr.join(), ',', i, ')', boundStr) + } + code.push(');') + } + + for(var i=0; i1){dst.set(', + pickStr.join(), ',', bnd, ',0.5*(src.get(', + cPickStr.join(), ')-src.get(', + dPickStr.join(), ')))}else{dst.set(', + pickStr.join(), ',', bnd, ',0)};') + } else { + code.push('if(s[', bnd, ']>1){diff(', outStr, + ',src.pick(', cPickStr.join(), ')', boundStr, + ',src.pick(', dPickStr.join(), ')', boundStr, + ');}else{zero(', outStr, ');};') + } + break + + case 'mirror': + if(cod === 0) { + code.push('dst.set(', pickStr.join(), ',', bnd, ',0);') + } else { + code.push('zero(', outStr, ');') + } + break + + case 'wrap': + var aPickStr = pickStr.slice() + var bPickStr = pickStr.slice() + if(facet[i] < 0) { + aPickStr[bnd] = 's[' + bnd + ']-2' + bPickStr[bnd] = '0' + + } else { + aPickStr[bnd] = 's[' + bnd + ']-1' + bPickStr[bnd] = '1' + } + if(cod === 0) { + code.push('if(s[', bnd, ']>2){dst.set(', + pickStr.join(), ',', bnd, ',0.5*(src.get(', + aPickStr.join(), ')-src.get(', + bPickStr.join(), ')))}else{dst.set(', + pickStr.join(), ',', bnd, ',0)};') + } else { + code.push('if(s[', bnd, ']>2){diff(', outStr, + ',src.pick(', aPickStr.join(), ')', boundStr, + ',src.pick(', bPickStr.join(), ')', boundStr, + ');}else{zero(', outStr, ');};') + } + break + + default: + throw new Error('ndarray-gradient: Invalid boundary condition') + } + } + + if(cod > 0) { + code.push('};') + } + } + + //Enumerate ridges, facets, etc. of hypercube + for(var i=0; i<(1<>", + rrshift: ">>>" +} +;(function(){ + for(var id in assign_ops) { + var op = assign_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a","b","c"], + body: "a=b"+op+"c"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array","array"], + body: {args:["a","b"], + body:"a"+op+"=b"}, + rvalue: true, + funcName: id+"eq" + }) + exports[id+"s"] = makeOp({ + args: ["array", "array", "scalar"], + body: {args:["a","b","s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"seq"] = makeOp({ + args: ["array","scalar"], + body: {args:["a","s"], + body:"a"+op+"=s"}, + rvalue: true, + funcName: id+"seq" + }) + } +})(); + +var unary_ops = { + not: "!", + bnot: "~", + neg: "-", + recip: "1.0/" +} +;(function(){ + for(var id in unary_ops) { + var op = unary_ops[id] + exports[id] = makeOp({ + args: ["array", "array"], + body: {args:["a","b"], + body:"a="+op+"b"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array"], + body: {args:["a"], + body:"a="+op+"a"}, + rvalue: true, + count: 2, + funcName: id+"eq" + }) + } +})(); + +var binary_ops = { + and: "&&", + or: "||", + eq: "===", + neq: "!==", + lt: "<", + gt: ">", + leq: "<=", + geq: ">=" +} +;(function() { + for(var id in binary_ops) { + var op = binary_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a", "b", "c"], + body:"a=b"+op+"c"}, + funcName: id + }) + exports[id+"s"] = makeOp({ + args: ["array","array","scalar"], + body: {args:["a", "b", "s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"eq"] = makeOp({ + args: ["array", "array"], + body: {args:["a", "b"], + body:"a=a"+op+"b"}, + rvalue:true, + count:2, + funcName: id+"eq" + }) + exports[id+"seq"] = makeOp({ + args: ["array", "scalar"], + body: {args:["a","s"], + body:"a=a"+op+"s"}, + rvalue:true, + count:2, + funcName: id+"seq" + }) + } +})(); + +var math_unary = [ + "abs", + "acos", + "asin", + "atan", + "ceil", + "cos", + "exp", + "floor", + "log", + "round", + "sin", + "sqrt", + "tan" +] +;(function() { + for(var i=0; ithis_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norminf" +}) + +exports.norm1 = compile({ + args:["array"], + pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"}, + body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norm1" +}) + +exports.sup = compile({ + args: [ "array" ], + pre: + { body: "this_h=-Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_", + args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ], + thisVars: [ "this_h" ], + localVars: [] }, + post: + { body: "return this_h", + args: [], + thisVars: [ "this_h" ], + localVars: [] } + }) + +exports.inf = compile({ + args: [ "array" ], + pre: + { body: "this_h=Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}", + args:[ + {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2}, + {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}], + thisVars:["this_i","this_v"], + localVars:["_inline_1_k"]}, + post:{ + body:"{return this_i}", + args:[], + thisVars:["this_i"], + localVars:[]} +}) + +exports.random = makeOp({ + args: ["array"], + pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]}, + body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]}, + funcName: "random" +}) + +exports.assign = makeOp({ + args:["array", "array"], + body: {args:["a", "b"], body:"a=b"}, + funcName: "assign" }) + +exports.assigns = makeOp({ + args:["array", "scalar"], + body: {args:["a", "b"], body:"a=b"}, + funcName: "assigns" }) + + +exports.equals = compile({ + args:["array", "array"], + pre: EmptyProc, + body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}, + {name:"y", lvalue:false, rvalue:true, count:1}], + body: "if(x!==y){return false}", + localVars: [], + thisVars: []}, + post: {args:[], localVars:[], thisVars:[], body:"return true"}, + funcName: "equals" +}) + + + +},{"cwise-compiler":134}],428:[function(_dereq_,module,exports){ +"use strict" + +var ndarray = _dereq_("ndarray") +var do_convert = _dereq_("./doConvert.js") + +module.exports = function convert(arr, result) { + var shape = [], c = arr, sz = 1 + while(Array.isArray(c)) { + shape.push(c.length) + sz *= c.length + c = c[0] + } + if(shape.length === 0) { + return ndarray() + } + if(!result) { + result = ndarray(new Float64Array(sz), shape) + } + do_convert(result, arr) + return result +} + +},{"./doConvert.js":429,"ndarray":433}],429:[function(_dereq_,module,exports){ +module.exports=_dereq_('cwise-compiler')({"args":["array","scalar","index"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{\nvar _inline_1_v=_inline_1_arg1_,_inline_1_i\nfor(_inline_1_i=0;_inline_1_i<_inline_1_arg2_.length-1;++_inline_1_i) {\n_inline_1_v=_inline_1_v[_inline_1_arg2_[_inline_1_i]]\n}\n_inline_1_arg0_=_inline_1_v[_inline_1_arg2_[_inline_1_arg2_.length-1]]\n}","args":[{"name":"_inline_1_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":4}],"thisVars":[],"localVars":["_inline_1_i","_inline_1_v"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"funcName":"convert","blockSize":64}) + +},{"cwise-compiler":134}],430:[function(_dereq_,module,exports){ +"use strict" + +var pool = _dereq_("typedarray-pool") + +var INSERTION_SORT_THRESHOLD = 32 + +function getMallocFree(dtype) { + switch(dtype) { + case "uint8": + return [pool.mallocUint8, pool.freeUint8] + case "uint16": + return [pool.mallocUint16, pool.freeUint16] + case "uint32": + return [pool.mallocUint32, pool.freeUint32] + case "int8": + return [pool.mallocInt8, pool.freeInt8] + case "int16": + return [pool.mallocInt16, pool.freeInt16] + case "int32": + return [pool.mallocInt32, pool.freeInt32] + case "float32": + return [pool.mallocFloat, pool.freeFloat] + case "float64": + return [pool.mallocDouble, pool.freeDouble] + default: + return null + } +} + +function shapeArgs(dimension) { + var args = [] + for(var i=0; i 1) { + var scratch_shape = [] + for(var i=1; i 1) { + + //Copy data into scratch + code.push("dptr=0;sptr=ptr") + for(var i=order.length-1; i>=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"left){", + "dptr=0", + "sptr=cptr-s0") + for(var i=1; ib){break __l}"].join("")) + for(var i=order.length-1; i>=1; --i) { + code.push( + "sptr+=e"+i, + "dptr+=f"+i, + "}") + } + + //Copy data back + code.push("dptr=cptr;sptr=cptr-s0") + for(var i=order.length-1; i>=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"left)&&("+dataRead("cptr-s0")+">scratch)){", + dataWrite("cptr", dataRead("cptr-s0")), + "cptr-=s0", + "}", + dataWrite("cptr", "scratch")) + } + + //Close outer loop body + code.push("}") + if(order.length > 1 && allocator) { + code.push("free(scratch)") + } + code.push("} return " + funcName) + + //Compile and link function + if(allocator) { + var result = new Function("malloc", "free", code.join("\n")) + return result(allocator[0], allocator[1]) + } else { + var result = new Function(code.join("\n")) + return result() + } +} + +function createQuickSort(order, dtype, insertionSort) { + var code = [ "'use strict'" ] + var funcName = ["ndarrayQuickSort", order.join("d"), dtype].join("") + var funcArgs = ["left", "right", "data", "offset" ].concat(shapeArgs(order.length)) + var allocator = getMallocFree(dtype) + var labelCounter=0 + + code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) + + var vars = [ + "sixth=((right-left+1)/6)|0", + "index1=left+sixth", + "index5=right-sixth", + "index3=(left+right)>>1", + "index2=index3-sixth", + "index4=index3+sixth", + "el1=index1", + "el2=index2", + "el3=index3", + "el4=index4", + "el5=index5", + "less=left+1", + "great=right-1", + "pivots_are_equal=true", + "tmp", + "tmp0", + "x", + "y", + "z", + "k", + "ptr0", + "ptr1", + "ptr2", + "comp_pivot1=0", + "comp_pivot2=0", + "comp=0" + ] + + if(order.length > 1) { + var ele_size = [] + for(var i=1; i=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j," 1) { + for(var i=0; i1) { + code.push("ptr_shift+=d"+j) + } else { + code.push("ptr0+=d"+j) + } + code.push("}") + } + } + + function lexicoLoop(label, ptrs, usePivot, body) { + if(ptrs.length === 1) { + code.push("ptr0="+toPointer(ptrs[0])) + } else { + for(var i=0; i 1) { + for(var i=0; i=1; --i) { + if(usePivot) { + code.push("pivot_ptr+=f"+i) + } + if(ptrs.length > 1) { + code.push("ptr_shift+=e"+i) + } else { + code.push("ptr0+=e"+i) + } + code.push("}") + } + } + + function cleanUp() { + if(order.length > 1 && allocator) { + code.push("free(pivot1)", "free(pivot2)") + } + } + + function compareSwap(a_id, b_id) { + var a = "el"+a_id + var b = "el"+b_id + if(order.length > 1) { + var lbl = "__l" + (++labelCounter) + lexicoLoop(lbl, [a, b], false, [ + "comp=",dataRead("ptr0"),"-",dataRead("ptr1"),"\n", + "if(comp>0){tmp0=", a, ";",a,"=",b,";", b,"=tmp0;break ", lbl,"}\n", + "if(comp<0){break ", lbl, "}" + ].join("")) + } else { + code.push(["if(", dataRead(toPointer(a)), ">", dataRead(toPointer(b)), "){tmp0=", a, ";",a,"=",b,";", b,"=tmp0}"].join("")) + } + } + + compareSwap(1, 2) + compareSwap(4, 5) + compareSwap(1, 3) + compareSwap(2, 3) + compareSwap(1, 4) + compareSwap(3, 4) + compareSwap(2, 5) + compareSwap(2, 3) + compareSwap(4, 5) + + if(order.length > 1) { + cacheLoop(["el1", "el2", "el3", "el4", "el5", "index1", "index3", "index5"], true, [ + "pivot1[pivot_ptr]=",dataRead("ptr1"),"\n", + "pivot2[pivot_ptr]=",dataRead("ptr3"),"\n", + "pivots_are_equal=pivots_are_equal&&(pivot1[pivot_ptr]===pivot2[pivot_ptr])\n", + "x=",dataRead("ptr0"),"\n", + "y=",dataRead("ptr2"),"\n", + "z=",dataRead("ptr4"),"\n", + dataWrite("ptr5", "x"),"\n", + dataWrite("ptr6", "y"),"\n", + dataWrite("ptr7", "z") + ].join("")) + } else { + code.push([ + "pivot1=", dataRead(toPointer("el2")), "\n", + "pivot2=", dataRead(toPointer("el4")), "\n", + "pivots_are_equal=pivot1===pivot2\n", + "x=", dataRead(toPointer("el1")), "\n", + "y=", dataRead(toPointer("el3")), "\n", + "z=", dataRead(toPointer("el5")), "\n", + dataWrite(toPointer("index1"), "x"), "\n", + dataWrite(toPointer("index3"), "y"), "\n", + dataWrite(toPointer("index5"), "z") + ].join("")) + } + + + function moveElement(dst, src) { + if(order.length > 1) { + cacheLoop([dst, src], false, + dataWrite("ptr0", dataRead("ptr1")) + ) + } else { + code.push(dataWrite(toPointer(dst), dataRead(toPointer(src)))) + } + } + + moveElement("index2", "left") + moveElement("index4", "right") + + function comparePivot(result, ptr, n) { + if(order.length > 1) { + var lbl = "__l" + (++labelCounter) + lexicoLoop(lbl, [ptr], true, [ + result,"=",dataRead("ptr0"),"-pivot",n,"[pivot_ptr]\n", + "if(",result,"!==0){break ", lbl, "}" + ].join("")) + } else { + code.push([result,"=", dataRead(toPointer(ptr)), "-pivot", n].join("")) + } + } + + function swapElements(a, b) { + if(order.length > 1) { + cacheLoop([a,b],false,[ + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", "tmp") + ].join("")) + } else { + code.push([ + "ptr0=",toPointer(a),"\n", + "ptr1=",toPointer(b),"\n", + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", "tmp") + ].join("")) + } + } + + function tripleSwap(k, less, great) { + if(order.length > 1) { + cacheLoop([k,less,great], false, [ + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", dataRead("ptr2")),"\n", + dataWrite("ptr2", "tmp") + ].join("")) + code.push("++"+less, "--"+great) + } else { + code.push([ + "ptr0=",toPointer(k),"\n", + "ptr1=",toPointer(less),"\n", + "ptr2=",toPointer(great),"\n", + "++",less,"\n", + "--",great,"\n", + "tmp=", dataRead("ptr0"), "\n", + dataWrite("ptr0", dataRead("ptr1")), "\n", + dataWrite("ptr1", dataRead("ptr2")), "\n", + dataWrite("ptr2", "tmp") + ].join("")) + } + } + + function swapAndDecrement(k, great) { + swapElements(k, great) + code.push("--"+great) + } + + code.push("if(pivots_are_equal){") + //Pivots are equal case + code.push("for(k=less;k<=great;++k){") + comparePivot("comp", "k", 1) + code.push("if(comp===0){continue}") + code.push("if(comp<0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + code.push("while(true){") + comparePivot("comp", "great", 1) + code.push("if(comp>0){") + code.push("great--") + code.push("}else if(comp<0){") + tripleSwap("k", "less", "great") + code.push("break") + code.push("}else{") + swapAndDecrement("k", "great") + code.push("break") + code.push("}") + code.push("}") + code.push("}") + code.push("}") + code.push("}else{") + //Pivots not equal case + code.push("for(k=less;k<=great;++k){") + comparePivot("comp_pivot1", "k", 1) + code.push("if(comp_pivot1<0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + comparePivot("comp_pivot2", "k", 2) + code.push("if(comp_pivot2>0){") + code.push("while(true){") + comparePivot("comp", "great", 2) + code.push("if(comp>0){") + code.push("if(--great1) { + cacheLoop([mem_dest, pivot_dest], true, [ + dataWrite("ptr0", dataRead("ptr1")), "\n", + dataWrite("ptr1", ["pivot",pivot,"[pivot_ptr]"].join("")) + ].join("")) + } else { + code.push( + dataWrite(toPointer(mem_dest), dataRead(toPointer(pivot_dest))), + dataWrite(toPointer(pivot_dest), "pivot"+pivot)) + } + } + + storePivot("left", "(less-1)", 1) + storePivot("right", "(great+1)", 2) + + //Recursive sort call + function doSort(left, right) { + code.push([ + "if((",right,"-",left,")<=",INSERTION_SORT_THRESHOLD,"){\n", + "insertionSort(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", + "}else{\n", + funcName, "(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", + "}" + ].join("")) + } + doSort("left", "(less-2)") + doSort("(great+2)", "right") + + //If pivots are equal, then early out + code.push("if(pivots_are_equal){") + cleanUp() + code.push("return") + code.push("}") + + function walkPointer(ptr, pivot, body) { + if(order.length > 1) { + code.push(["__l",++labelCounter,":while(true){"].join("")) + cacheLoop([ptr], true, [ + "if(", dataRead("ptr0"), "!==pivot", pivot, "[pivot_ptr]){break __l", labelCounter, "}" + ].join("")) + code.push(body, "}") + } else { + code.push(["while(", dataRead(toPointer(ptr)), "===pivot", pivot, "){", body, "}"].join("")) + } + } + + //Check bounds + code.push("if(lessindex5){") + + walkPointer("less", 1, "++less") + walkPointer("great", 2, "--great") + + code.push("for(k=less;k<=great;++k){") + comparePivot("comp_pivot1", "k", 1) + code.push("if(comp_pivot1===0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + comparePivot("comp_pivot2", "k", 2) + code.push("if(comp_pivot2===0){") + code.push("while(true){") + comparePivot("comp", "great", 2) + code.push("if(comp===0){") + code.push("if(--great 1 && allocator) { + var compiled = new Function("insertionSort", "malloc", "free", code.join("\n")) + return compiled(insertionSort, allocator[0], allocator[1]) + } + var compiled = new Function("insertionSort", code.join("\n")) + return compiled(insertionSort) +} + +function compileSort(order, dtype) { + var code = ["'use strict'"] + var funcName = ["ndarraySortWrapper", order.join("d"), dtype].join("") + var funcArgs = [ "array" ] + + code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) + + //Unpack local variables from array + var vars = ["data=array.data,offset=array.offset|0,shape=array.shape,stride=array.stride"] + for(var i=0; i 0) { + vars.push(["d",j,"=s",j,"-d",p,"*n",p].join("")) + } else { + vars.push(["d",j,"=s",j].join("")) + } + p = j + } + var k = order.length-1-i + if(k !== 0) { + if(q > 0) { + vars.push(["e",k,"=s",k,"-e",q,"*n",q, + ",f",k,"=",scratch_stride[k],"-f",q,"*n",q].join("")) + } else { + vars.push(["e",k,"=s",k,",f",k,"=",scratch_stride[k]].join("")) + } + q = k + } + } + + //Declare local variables + code.push("var " + vars.join(",")) + + //Create arguments for subroutine + var sortArgs = ["0", "n0-1", "data", "offset"].concat(shapeArgs(order.length)) + + //Call main sorting routine + code.push([ + "if(n0<=",INSERTION_SORT_THRESHOLD,"){", + "insertionSort(", sortArgs.join(","), ")}else{", + "quickSort(", sortArgs.join(","), + ")}" + ].join("")) + + //Return + code.push("}return " + funcName) + + //Link everything together + var result = new Function("insertionSort", "quickSort", code.join("\n")) + var insertionSort = createInsertionSort(order, dtype) + var quickSort = createQuickSort(order, dtype, insertionSort) + return result(insertionSort, quickSort) +} + +module.exports = compileSort +},{"typedarray-pool":522}],431:[function(_dereq_,module,exports){ +"use strict" + +var compile = _dereq_("./lib/compile_sort.js") +var CACHE = {} + +function sort(array) { + var order = array.order + var dtype = array.dtype + var typeSig = [order, dtype ] + var typeName = typeSig.join(":") + var compiled = CACHE[typeName] + if(!compiled) { + CACHE[typeName] = compiled = compile(order, dtype) + } + compiled(array) + return array +} + +module.exports = sort +},{"./lib/compile_sort.js":430}],432:[function(_dereq_,module,exports){ +'use strict' + +var interp = _dereq_('ndarray-linear-interpolate') + + +var do_warp = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=new Array(_inline_3_arg4_)}","args":[{"name":"_inline_3_arg0_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg1_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg2_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg3_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_4_arg2_(this_warped,_inline_4_arg0_),_inline_4_arg1_=_inline_4_arg3_.apply(void 0,this_warped)}","args":[{"name":"_inline_4_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_4_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg4_","lvalue":false,"rvalue":false,"count":0}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warpND","blockSize":64}) + +var do_warp_1 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_7_arg2_(this_warped,_inline_7_arg0_),_inline_7_arg1_=_inline_7_arg3_(_inline_7_arg4_,this_warped[0])}","args":[{"name":"_inline_7_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_7_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp1D","blockSize":64}) + +var do_warp_2 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_10_arg2_(this_warped,_inline_10_arg0_),_inline_10_arg1_=_inline_10_arg3_(_inline_10_arg4_,this_warped[0],this_warped[1])}","args":[{"name":"_inline_10_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_10_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp2D","blockSize":64}) + +var do_warp_3 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_13_arg2_(this_warped,_inline_13_arg0_),_inline_13_arg1_=_inline_13_arg3_(_inline_13_arg4_,this_warped[0],this_warped[1],this_warped[2])}","args":[{"name":"_inline_13_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_13_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp3D","blockSize":64}) + +module.exports = function warp(dest, src, func) { + switch(src.shape.length) { + case 1: + do_warp_1(dest, func, interp.d1, src) + break + case 2: + do_warp_2(dest, func, interp.d2, src) + break + case 3: + do_warp_3(dest, func, interp.d3, src) + break + default: + do_warp(dest, func, interp.bind(undefined, src), src.shape.length) + break + } + return dest +} + +},{"cwise/lib/wrapper":137,"ndarray-linear-interpolate":426}],433:[function(_dereq_,module,exports){ +var iota = _dereq_("iota-array") +var isBuffer = _dereq_("is-buffer") + +var hasTypedArrays = ((typeof Float64Array) !== "undefined") + +function compare1st(a, b) { + return a[0] - b[0] +} + +function order() { + var stride = this.stride + var terms = new Array(stride.length) + var i + for(i=0; iMath.abs(this.stride[1]))?[1,0]:[0,1]}})") + } else if(dimension === 3) { + code.push( +"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\ +if(s0>s1){\ +if(s1>s2){\ +return [2,1,0];\ +}else if(s0>s2){\ +return [1,2,0];\ +}else{\ +return [1,0,2];\ +}\ +}else if(s0>s2){\ +return [2,0,1];\ +}else if(s2>s1){\ +return [0,1,2];\ +}else{\ +return [0,2,1];\ +}}})") + } + } else { + code.push("ORDER})") + } + } + + //view.set(i0, ..., v): + code.push( +"proto.set=function "+className+"_set("+args.join(",")+",v){") + if(useGetters) { + code.push("return this.data.set("+index_str+",v)}") + } else { + code.push("return this.data["+index_str+"]=v}") + } + + //view.get(i0, ...): + code.push("proto.get=function "+className+"_get("+args.join(",")+"){") + if(useGetters) { + code.push("return this.data.get("+index_str+")}") + } else { + code.push("return this.data["+index_str+"]}") + } + + //view.index: + code.push( + "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}") + + //view.hi(): + code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+ + indices.map(function(i) { + return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("") + }).join(",")+","+ + indices.map(function(i) { + return "this.stride["+i + "]" + }).join(",")+",this.offset)}") + + //view.lo(): + var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" }) + var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" }) + code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(",")) + for(var i=0; i=0){\ +d=i"+i+"|0;\ +b+=c"+i+"*d;\ +a"+i+"-=d}") + } + code.push("return new "+className+"(this.data,"+ + indices.map(function(i) { + return "a"+i + }).join(",")+","+ + indices.map(function(i) { + return "c"+i + }).join(",")+",b)}") + + //view.step(): + code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+ + indices.map(function(i) { + return "a"+i+"=this.shape["+i+"]" + }).join(",")+","+ + indices.map(function(i) { + return "b"+i+"=this.stride["+i+"]" + }).join(",")+",c=this.offset,d=0,ceil=Math.ceil") + for(var i=0; i=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}") + } + code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") + + //Add return statement + code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+ + indices.map(function(i) { + return "shape["+i+"]" + }).join(",")+","+ + indices.map(function(i) { + return "stride["+i+"]" + }).join(",")+",offset)}") + + //Compile procedure + var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) + return procedure(CACHED_CONSTRUCTORS[dtype], order) +} + +function arrayDType(data) { + if(isBuffer(data)) { + return "buffer" + } + if(hasTypedArrays) { + switch(Object.prototype.toString.call(data)) { + case "[object Float64Array]": + return "float64" + case "[object Float32Array]": + return "float32" + case "[object Int8Array]": + return "int8" + case "[object Int16Array]": + return "int16" + case "[object Int32Array]": + return "int32" + case "[object Uint8Array]": + return "uint8" + case "[object Uint16Array]": + return "uint16" + case "[object Uint32Array]": + return "uint32" + case "[object Uint8ClampedArray]": + return "uint8_clamped" + } + } + if(Array.isArray(data)) { + return "array" + } + return "generic" +} + +var CACHED_CONSTRUCTORS = { + "float32":[], + "float64":[], + "int8":[], + "int16":[], + "int32":[], + "uint8":[], + "uint16":[], + "uint32":[], + "array":[], + "uint8_clamped":[], + "buffer":[], + "generic":[] +} + +;(function() { + for(var id in CACHED_CONSTRUCTORS) { + CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) + } +}); + +function wrappedNDArrayCtor(data, shape, stride, offset) { + if(data === undefined) { + var ctor = CACHED_CONSTRUCTORS.array[0] + return ctor([]) + } else if(typeof data === "number") { + data = [data] + } + if(shape === undefined) { + shape = [ data.length ] + } + var d = shape.length + if(stride === undefined) { + stride = new Array(d) + for(var i=d-1, sz=1; i>=0; --i) { + stride[i] = sz + sz *= shape[i] + } + } + if(offset === undefined) { + offset = 0 + for(var i=0; i>>0 + +module.exports = nextafter + +function nextafter(x, y) { + if(isNaN(x) || isNaN(y)) { + return NaN + } + if(x === y) { + return x + } + if(x === 0) { + if(y < 0) { + return -SMALLEST_DENORM + } else { + return SMALLEST_DENORM + } + } + var hi = doubleBits.hi(x) + var lo = doubleBits.lo(x) + if((y > x) === (x > 0)) { + if(lo === UINT_MAX) { + hi += 1 + lo = 0 + } else { + lo += 1 + } + } else { + if(lo === 0) { + lo = UINT_MAX + hi -= 1 + } else { + lo -= 1 + } + } + return doubleBits.pack(lo, hi) +} +},{"double-bits":152}],435:[function(_dereq_,module,exports){ + +var π = Math.PI +var _120 = radians(120) + +module.exports = normalize + +/** + * describe `path` in terms of cubic bézier + * curves and move commands + * + * @param {Array} path + * @return {Array} + */ + +function normalize(path){ + // init state + var prev + var result = [] + var bezierX = 0 + var bezierY = 0 + var startX = 0 + var startY = 0 + var quadX = null + var quadY = null + var x = 0 + var y = 0 + + for (var i = 0, len = path.length; i < len; i++) { + var seg = path[i] + var command = seg[0] + switch (command) { + case 'M': + startX = seg[1] + startY = seg[2] + break + case 'A': + seg = arc(x, y,seg[1],seg[2],radians(seg[3]),seg[4],seg[5],seg[6],seg[7]) + // split multi part + seg.unshift('C') + if (seg.length > 7) { + result.push(seg.splice(0, 7)) + seg.unshift('C') + } + break + case 'S': + // default control point + var cx = x + var cy = y + if (prev == 'C' || prev == 'S') { + cx += cx - bezierX // reflect the previous command's control + cy += cy - bezierY // point relative to the current point + } + seg = ['C', cx, cy, seg[1], seg[2], seg[3], seg[4]] + break + case 'T': + if (prev == 'Q' || prev == 'T') { + quadX = x * 2 - quadX // as with 'S' reflect previous control point + quadY = y * 2 - quadY + } else { + quadX = x + quadY = y + } + seg = quadratic(x, y, quadX, quadY, seg[1], seg[2]) + break + case 'Q': + quadX = seg[1] + quadY = seg[2] + seg = quadratic(x, y, seg[1], seg[2], seg[3], seg[4]) + break + case 'L': + seg = line(x, y, seg[1], seg[2]) + break + case 'H': + seg = line(x, y, seg[1], y) + break + case 'V': + seg = line(x, y, x, seg[1]) + break + case 'Z': + seg = line(x, y, startX, startY) + break + } + + // update state + prev = command + x = seg[seg.length - 2] + y = seg[seg.length - 1] + if (seg.length > 4) { + bezierX = seg[seg.length - 4] + bezierY = seg[seg.length - 3] + } else { + bezierX = x + bezierY = y + } + result.push(seg) + } + + return result +} + +function line(x1, y1, x2, y2){ + return ['C', x1, y1, x2, y2, x2, y2] +} + +function quadratic(x1, y1, cx, cy, x2, y2){ + return [ + 'C', + x1/3 + (2/3) * cx, + y1/3 + (2/3) * cy, + x2/3 + (2/3) * cx, + y2/3 + (2/3) * cy, + x2, + y2 + ] +} + +// This function is ripped from +// github.com/DmitryBaranovskiy/raphael/blob/4d97d4/raphael.js#L2216-L2304 +// which references w3.org/TR/SVG11/implnote.html#ArcImplementationNotes +// TODO: make it human readable + +function arc(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { + if (!recursive) { + var xy = rotate(x1, y1, -angle) + x1 = xy.x + y1 = xy.y + xy = rotate(x2, y2, -angle) + x2 = xy.x + y2 = xy.y + var x = (x1 - x2) / 2 + var y = (y1 - y2) / 2 + var h = (x * x) / (rx * rx) + (y * y) / (ry * ry) + if (h > 1) { + h = Math.sqrt(h) + rx = h * rx + ry = h * ry + } + var rx2 = rx * rx + var ry2 = ry * ry + var k = (large_arc_flag == sweep_flag ? -1 : 1) + * Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))) + if (k == Infinity) k = 1 // neutralize + var cx = k * rx * y / ry + (x1 + x2) / 2 + var cy = k * -ry * x / rx + (y1 + y2) / 2 + var f1 = Math.asin(((y1 - cy) / ry).toFixed(9)) + var f2 = Math.asin(((y2 - cy) / ry).toFixed(9)) + + f1 = x1 < cx ? π - f1 : f1 + f2 = x2 < cx ? π - f2 : f2 + if (f1 < 0) f1 = π * 2 + f1 + if (f2 < 0) f2 = π * 2 + f2 + if (sweep_flag && f1 > f2) f1 = f1 - π * 2 + if (!sweep_flag && f2 > f1) f2 = f2 - π * 2 + } else { + f1 = recursive[0] + f2 = recursive[1] + cx = recursive[2] + cy = recursive[3] + } + // greater than 120 degrees requires multiple segments + if (Math.abs(f2 - f1) > _120) { + var f2old = f2 + var x2old = x2 + var y2old = y2 + f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1) + x2 = cx + rx * Math.cos(f2) + y2 = cy + ry * Math.sin(f2) + var res = arc(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]) + } + var t = Math.tan((f2 - f1) / 4) + var hx = 4 / 3 * rx * t + var hy = 4 / 3 * ry * t + var curve = [ + 2 * x1 - (x1 + hx * Math.sin(f1)), + 2 * y1 - (y1 - hy * Math.cos(f1)), + x2 + hx * Math.sin(f2), + y2 - hy * Math.cos(f2), + x2, + y2 + ] + if (recursive) return curve + if (res) curve = curve.concat(res) + for (var i = 0; i < curve.length;) { + var rot = rotate(curve[i], curve[i+1], angle) + curve[i++] = rot.x + curve[i++] = rot.y + } + return curve +} + +function rotate(x, y, rad){ + return { + x: x * Math.cos(rad) - y * Math.sin(rad), + y: x * Math.sin(rad) + y * Math.cos(rad) + } +} + +function radians(degress){ + return degress * (π / 180) +} + +},{}],436:[function(_dereq_,module,exports){ +var DEFAULT_NORMALS_EPSILON = 1e-6; +var DEFAULT_FACE_EPSILON = 1e-6; + +//Estimate the vertex normals of a mesh +exports.vertexNormals = function(faces, positions, specifiedEpsilon) { + + var N = positions.length; + var normals = new Array(N); + var epsilon = specifiedEpsilon === void(0) ? DEFAULT_NORMALS_EPSILON : specifiedEpsilon; + + //Initialize normal array + for(var i=0; i epsilon) { + var norm = normals[c]; + var w = 1.0 / Math.sqrt(m01 * m21); + for(var k=0; k<3; ++k) { + var u = (k+1)%3; + var v = (k+2)%3; + norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]); + } + } + } + } + + //Scale all normals to unit length + for(var i=0; i epsilon) { + var w = 1.0 / Math.sqrt(m); + for(var k=0; k<3; ++k) { + norm[k] *= w; + } + } else { + for(var k=0; k<3; ++k) { + norm[k] = 0.0; + } + } + } + + //Return the resulting set of patches + return normals; +} + +//Compute face normals of a mesh +exports.faceNormals = function(faces, positions, specifiedEpsilon) { + + var N = faces.length; + var normals = new Array(N); + var epsilon = specifiedEpsilon === void(0) ? DEFAULT_FACE_EPSILON : specifiedEpsilon; + + for(var i=0; i epsilon) { + l = 1.0 / Math.sqrt(l); + } else { + l = 0.0; + } + for(var j=0; j<3; ++j) { + n[j] *= l; + } + normals[i] = n; + } + return normals; +} + + + +},{}],437:[function(_dereq_,module,exports){ +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + +'use strict'; +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; + +},{}],438:[function(_dereq_,module,exports){ +'use strict' + +module.exports = quatFromFrame + +function quatFromFrame( + out, + rx, ry, rz, + ux, uy, uz, + fx, fy, fz) { + var tr = rx + uy + fz + if(l > 0) { + var l = Math.sqrt(tr + 1.0) + out[0] = 0.5 * (uz - fy) / l + out[1] = 0.5 * (fx - rz) / l + out[2] = 0.5 * (ry - uy) / l + out[3] = 0.5 * l + } else { + var tf = Math.max(rx, uy, fz) + var l = Math.sqrt(2 * tf - tr + 1.0) + if(rx >= tf) { + //x y z order + out[0] = 0.5 * l + out[1] = 0.5 * (ux + ry) / l + out[2] = 0.5 * (fx + rz) / l + out[3] = 0.5 * (uz - fy) / l + } else if(uy >= tf) { + //y z x order + out[0] = 0.5 * (ry + ux) / l + out[1] = 0.5 * l + out[2] = 0.5 * (fy + uz) / l + out[3] = 0.5 * (fx - rz) / l + } else { + //z x y order + out[0] = 0.5 * (rz + fx) / l + out[1] = 0.5 * (uz + fy) / l + out[2] = 0.5 * l + out[3] = 0.5 * (ry - ux) / l + } + } + return out +} +},{}],439:[function(_dereq_,module,exports){ +'use strict' + +module.exports = createOrbitController + +var filterVector = _dereq_('filtered-vector') +var lookAt = _dereq_('gl-mat4/lookAt') +var mat4FromQuat = _dereq_('gl-mat4/fromQuat') +var invert44 = _dereq_('gl-mat4/invert') +var quatFromFrame = _dereq_('./lib/quatFromFrame') + +function len3(x,y,z) { + return Math.sqrt(Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2)) +} + +function len4(w,x,y,z) { + return Math.sqrt(Math.pow(w,2) + Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2)) +} + +function normalize4(out, a) { + var ax = a[0] + var ay = a[1] + var az = a[2] + var aw = a[3] + var al = len4(ax, ay, az, aw) + if(al > 1e-6) { + out[0] = ax/al + out[1] = ay/al + out[2] = az/al + out[3] = aw/al + } else { + out[0] = out[1] = out[2] = 0.0 + out[3] = 1.0 + } +} + +function OrbitCameraController(initQuat, initCenter, initRadius) { + this.radius = filterVector([initRadius]) + this.center = filterVector(initCenter) + this.rotation = filterVector(initQuat) + + this.computedRadius = this.radius.curve(0) + this.computedCenter = this.center.curve(0) + this.computedRotation = this.rotation.curve(0) + this.computedUp = [0.1,0,0] + this.computedEye = [0.1,0,0] + this.computedMatrix = [0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + + this.recalcMatrix(0) +} + +var proto = OrbitCameraController.prototype + +proto.lastT = function() { + return Math.max( + this.radius.lastT(), + this.center.lastT(), + this.rotation.lastT()) +} + +proto.recalcMatrix = function(t) { + this.radius.curve(t) + this.center.curve(t) + this.rotation.curve(t) + + var quat = this.computedRotation + normalize4(quat, quat) + + var mat = this.computedMatrix + mat4FromQuat(mat, quat) + + var center = this.computedCenter + var eye = this.computedEye + var up = this.computedUp + var radius = Math.exp(this.computedRadius[0]) + + eye[0] = center[0] + radius * mat[2] + eye[1] = center[1] + radius * mat[6] + eye[2] = center[2] + radius * mat[10] + up[0] = mat[1] + up[1] = mat[5] + up[2] = mat[9] + + for(var i=0; i<3; ++i) { + var rr = 0.0 + for(var j=0; j<3; ++j) { + rr += mat[i+4*j] * eye[j] + } + mat[12+i] = -rr + } +} + +proto.getMatrix = function(t, result) { + this.recalcMatrix(t) + var m = this.computedMatrix + if(result) { + for(var i=0; i<16; ++i) { + result[i] = m[i] + } + return result + } + return m +} + +proto.idle = function(t) { + this.center.idle(t) + this.radius.idle(t) + this.rotation.idle(t) +} + +proto.flush = function(t) { + this.center.flush(t) + this.radius.flush(t) + this.rotation.flush(t) +} + +proto.pan = function(t, dx, dy, dz) { + dx = dx || 0.0 + dy = dy || 0.0 + dz = dz || 0.0 + + this.recalcMatrix(t) + var mat = this.computedMatrix + + var ux = mat[1] + var uy = mat[5] + var uz = mat[9] + var ul = len3(ux, uy, uz) + ux /= ul + uy /= ul + uz /= ul + + var rx = mat[0] + var ry = mat[4] + var rz = mat[8] + var ru = rx * ux + ry * uy + rz * uz + rx -= ux * ru + ry -= uy * ru + rz -= uz * ru + var rl = len3(rx, ry, rz) + rx /= rl + ry /= rl + rz /= rl + + var fx = mat[2] + var fy = mat[6] + var fz = mat[10] + var fu = fx * ux + fy * uy + fz * uz + var fr = fx * rx + fy * ry + fz * rz + fx -= fu * ux + fr * rx + fy -= fu * uy + fr * ry + fz -= fu * uz + fr * rz + var fl = len3(fx, fy, fz) + fx /= fl + fy /= fl + fz /= fl + + var vx = rx * dx + ux * dy + var vy = ry * dx + uy * dy + var vz = rz * dx + uz * dy + + this.center.move(t, vx, vy, vz) + + //Update z-component of radius + var radius = Math.exp(this.computedRadius[0]) + radius = Math.max(1e-4, radius + dz) + this.radius.set(t, Math.log(radius)) +} + +proto.rotate = function(t, dx, dy, dz) { + this.recalcMatrix(t) + + dx = dx||0.0 + dy = dy||0.0 + + var mat = this.computedMatrix + + var rx = mat[0] + var ry = mat[4] + var rz = mat[8] + + var ux = mat[1] + var uy = mat[5] + var uz = mat[9] + + var fx = mat[2] + var fy = mat[6] + var fz = mat[10] + + var qx = dx * rx + dy * ux + var qy = dx * ry + dy * uy + var qz = dx * rz + dy * uz + + var bx = -(fy * qz - fz * qy) + var by = -(fz * qx - fx * qz) + var bz = -(fx * qy - fy * qx) + var bw = Math.sqrt(Math.max(0.0, 1.0 - Math.pow(bx,2) - Math.pow(by,2) - Math.pow(bz,2))) + var bl = len4(bx, by, bz, bw) + if(bl > 1e-6) { + bx /= bl + by /= bl + bz /= bl + bw /= bl + } else { + bx = by = bz = 0.0 + bw = 1.0 + } + + var rotation = this.computedRotation + var ax = rotation[0] + var ay = rotation[1] + var az = rotation[2] + var aw = rotation[3] + + var cx = ax*bw + aw*bx + ay*bz - az*by + var cy = ay*bw + aw*by + az*bx - ax*bz + var cz = az*bw + aw*bz + ax*by - ay*bx + var cw = aw*bw - ax*bx - ay*by - az*bz + + //Apply roll + if(dz) { + bx = fx + by = fy + bz = fz + var s = Math.sin(dz) / len3(bx, by, bz) + bx *= s + by *= s + bz *= s + bw = Math.cos(dx) + cx = cx*bw + cw*bx + cy*bz - cz*by + cy = cy*bw + cw*by + cz*bx - cx*bz + cz = cz*bw + cw*bz + cx*by - cy*bx + cw = cw*bw - cx*bx - cy*by - cz*bz + } + + var cl = len4(cx, cy, cz, cw) + if(cl > 1e-6) { + cx /= cl + cy /= cl + cz /= cl + cw /= cl + } else { + cx = cy = cz = 0.0 + cw = 1.0 + } + + this.rotation.set(t, cx, cy, cz, cw) +} + +proto.lookAt = function(t, eye, center, up) { + this.recalcMatrix(t) + + center = center || this.computedCenter + eye = eye || this.computedEye + up = up || this.computedUp + + var mat = this.computedMatrix + lookAt(mat, eye, center, up) + + var rotation = this.computedRotation + quatFromFrame(rotation, + mat[0], mat[1], mat[2], + mat[4], mat[5], mat[6], + mat[8], mat[9], mat[10]) + normalize4(rotation, rotation) + this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3]) + + var fl = 0.0 + for(var i=0; i<3; ++i) { + fl += Math.pow(center[i] - eye[i], 2) + } + this.radius.set(t, 0.5 * Math.log(Math.max(fl, 1e-6))) + + this.center.set(t, center[0], center[1], center[2]) +} + +proto.translate = function(t, dx, dy, dz) { + this.center.move(t, + dx||0.0, + dy||0.0, + dz||0.0) +} + +proto.setMatrix = function(t, matrix) { + + var rotation = this.computedRotation + quatFromFrame(rotation, + matrix[0], matrix[1], matrix[2], + matrix[4], matrix[5], matrix[6], + matrix[8], matrix[9], matrix[10]) + normalize4(rotation, rotation) + this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3]) + + var mat = this.computedMatrix + invert44(mat, matrix) + var w = mat[15] + if(Math.abs(w) > 1e-6) { + var cx = mat[12]/w + var cy = mat[13]/w + var cz = mat[14]/w + + this.recalcMatrix(t) + var r = Math.exp(this.computedRadius[0]) + this.center.set(t, cx-mat[2]*r, cy-mat[6]*r, cz-mat[10]*r) + this.radius.idle(t) + } else { + this.center.idle(t) + this.radius.idle(t) + } +} + +proto.setDistance = function(t, d) { + if(d > 0) { + this.radius.set(t, Math.log(d)) + } +} + +proto.setDistanceLimits = function(lo, hi) { + if(lo > 0) { + lo = Math.log(lo) + } else { + lo = -Infinity + } + if(hi > 0) { + hi = Math.log(hi) + } else { + hi = Infinity + } + hi = Math.max(hi, lo) + this.radius.bounds[0][0] = lo + this.radius.bounds[1][0] = hi +} + +proto.getDistanceLimits = function(out) { + var bounds = this.radius.bounds + if(out) { + out[0] = Math.exp(bounds[0][0]) + out[1] = Math.exp(bounds[1][0]) + return out + } + return [ Math.exp(bounds[0][0]), Math.exp(bounds[1][0]) ] +} + +proto.toJSON = function() { + this.recalcMatrix(this.lastT()) + return { + center: this.computedCenter.slice(), + rotation: this.computedRotation.slice(), + distance: Math.log(this.computedRadius[0]), + zoomMin: this.radius.bounds[0][0], + zoomMax: this.radius.bounds[1][0] + } +} + +proto.fromJSON = function(options) { + var t = this.lastT() + var c = options.center + if(c) { + this.center.set(t, c[0], c[1], c[2]) + } + var r = options.rotation + if(r) { + this.rotation.set(t, r[0], r[1], r[2], r[3]) + } + var d = options.distance + if(d && d > 0) { + this.radius.set(t, Math.log(d)) + } + this.setDistanceLimits(options.zoomMin, options.zoomMax) +} + +function createOrbitController(options) { + options = options || {} + var center = options.center || [0,0,0] + var rotation = options.rotation || [0,0,0,1] + var radius = options.radius || 1.0 + + center = [].slice.call(center, 0, 3) + rotation = [].slice.call(rotation, 0, 4) + normalize4(rotation, rotation) + + var result = new OrbitCameraController( + rotation, + center, + Math.log(radius)) + + result.setDistanceLimits(options.zoomMin, options.zoomMax) + + if('eye' in options || 'up' in options) { + result.lookAt(0, options.eye, options.center, options.up) + } + + return result +} +},{"./lib/quatFromFrame":438,"filtered-vector":215,"gl-mat4/fromQuat":251,"gl-mat4/invert":254,"gl-mat4/lookAt":255}],440:[function(_dereq_,module,exports){ +/*! + * pad-left + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT license. + */ + +'use strict'; + +var repeat = _dereq_('repeat-string'); + +module.exports = function padLeft(str, num, ch) { + ch = typeof ch !== 'undefined' ? (ch + '') : ' '; + return repeat(ch, num) + str; +}; +},{"repeat-string":479}],441:[function(_dereq_,module,exports){ +'use strict' + +/** + * @module parenthesis + */ + +function parse (str, opts) { + // pretend non-string parsed per-se + if (typeof str !== 'string') return [str] + + var res = [str] + + if (typeof opts === 'string' || Array.isArray(opts)) { + opts = {brackets: opts} + } + else if (!opts) opts = {} + + var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()'] + + var escape = opts.escape || '___' + + var flat = !!opts.flat + + brackets.forEach(function (bracket) { + // create parenthesis regex + var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join('')) + + var ids = [] + + function replaceToken(token, idx, str){ + // save token to res + var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1 + + ids.push(refId) + + return escape + refId + } + + res.forEach(function (str, i) { + var prevStr + + // replace paren tokens till there’s none + var a = 0 + while (str != prevStr) { + prevStr = str + str = str.replace(pRE, replaceToken) + if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.') + } + + res[i] = str + }) + + // wrap found refs to brackets + ids = ids.reverse() + res = res.map(function (str) { + ids.forEach(function (id) { + str = str.replace(new RegExp('(\\' + escape + id + '(?![0-9]))', 'g'), bracket[0] + '$1' + bracket[1]) + }) + return str + }) + }) + + var re = new RegExp('\\' + escape + '([0-9]+)') + + // transform references to tree + function nest (str, refs, escape) { + var res = [], match + + var a = 0 + while (match = re.exec(str)) { + if (a++ > 10e3) throw Error('Circular references in parenthesis') + + res.push(str.slice(0, match.index)) + + res.push(nest(refs[match[1]], refs)) + + str = str.slice(match.index + match[0].length) + } + + res.push(str) + + return res + } + + return flat ? res : nest(res[0], res) +} + +function stringify (arg, opts) { + if (opts && opts.flat) { + var escape = opts && opts.escape || '___' + + var str = arg[0], prevStr + + // pretend bad string stringified with no parentheses + if (!str) return '' + + + var re = new RegExp('\\' + escape + '([0-9]+)') + + var a = 0 + while (str != prevStr) { + if (a++ > 10e3) throw Error('Circular references in ' + arg) + prevStr = str + str = str.replace(re, replaceRef) + } + + return str + } + + return arg.reduce(function f (prev, curr) { + if (Array.isArray(curr)) { + curr = curr.reduce(f, '') + } + return prev + curr + }, '') + + function replaceRef(match, idx){ + if (arg[idx] == null) throw Error('Reference ' + idx + 'is undefined') + return arg[idx] + } +} + +function parenthesis (arg, opts) { + if (Array.isArray(arg)) { + return stringify(arg, opts) + } + else { + return parse(arg, opts) + } +} + +parenthesis.parse = parse +parenthesis.stringify = stringify + +module.exports = parenthesis + +},{}],442:[function(_dereq_,module,exports){ +'use strict' + +var pick = _dereq_('pick-by-alias') + +module.exports = parseRect + +function parseRect (arg) { + var rect + + // direct arguments sequence + if (arguments.length > 1) { + arg = arguments + } + + // svg viewbox + if (typeof arg === 'string') { + arg = arg.split(/\s/).map(parseFloat) + } + else if (typeof arg === 'number') { + arg = [arg] + } + + // 0, 0, 100, 100 - array-like + if (arg.length && typeof arg[0] === 'number') { + // [w, w] + if (arg.length === 1) { + rect = { + width: arg[0], + height: arg[0], + x: 0, y: 0 + } + } + // [w, h] + else if (arg.length === 2) { + rect = { + width: arg[0], + height: arg[1], + x: 0, y: 0 + } + } + // [l, t, r, b] + else { + rect = { + x: arg[0], + y: arg[1], + width: (arg[2] - arg[0]) || 0, + height: (arg[3] - arg[1]) || 0 + } + } + } + // {x, y, w, h} or {l, t, b, r} + else if (arg) { + arg = pick(arg, { + left: 'x l left Left', + top: 'y t top Top', + width: 'w width W Width', + height: 'h height W Width', + bottom: 'b bottom Bottom', + right: 'r right Right' + }) + + rect = { + x: arg.left || 0, + y: arg.top || 0 + } + + if (arg.width == null) { + if (arg.right) rect.width = arg.right - rect.x + else rect.width = 0 + } + else { + rect.width = arg.width + } + + if (arg.height == null) { + if (arg.bottom) rect.height = arg.bottom - rect.y + else rect.height = 0 + } + else { + rect.height = arg.height + } + } + + return rect +} + +},{"pick-by-alias":448}],443:[function(_dereq_,module,exports){ + +module.exports = parse + +/** + * expected argument lengths + * @type {Object} + */ + +var length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0} + +/** + * segment pattern + * @type {RegExp} + */ + +var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig + +/** + * parse an svg path data string. Generates an Array + * of commands where each command is an Array of the + * form `[command, arg1, arg2, ...]` + * + * @param {String} path + * @return {Array} + */ + +function parse(path) { + var data = [] + path.replace(segment, function(_, command, args){ + var type = command.toLowerCase() + args = parseValues(args) + + // overloaded moveTo + if (type == 'm' && args.length > 2) { + data.push([command].concat(args.splice(0, 2))) + type = 'l' + command = command == 'm' ? 'l' : 'L' + } + + while (true) { + if (args.length == length[type]) { + args.unshift(command) + return data.push(args) + } + if (args.length < length[type]) throw new Error('malformed path data') + data.push([command].concat(args.splice(0, length[type]))) + } + }) + return data +} + +var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig + +function parseValues(args) { + var numbers = args.match(number) + return numbers ? numbers.map(Number) : [] +} + +},{}],444:[function(_dereq_,module,exports){ +module.exports = function parseUnit(str, out) { + if (!out) + out = [ 0, '' ] + + str = String(str) + var num = parseFloat(str, 10) + out[0] = num + out[1] = str.match(/[\d.\-\+]*\s*(.*)/)[1] || '' + return out +} +},{}],445:[function(_dereq_,module,exports){ +(function (process){ +// Generated by CoffeeScript 1.12.2 +(function() { + var getNanoSeconds, hrtime, loadTime, moduleLoadTime, nodeLoadTime, upTime; + + if ((typeof performance !== "undefined" && performance !== null) && performance.now) { + module.exports = function() { + return performance.now(); + }; + } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { + module.exports = function() { + return (getNanoSeconds() - nodeLoadTime) / 1e6; + }; + hrtime = process.hrtime; + getNanoSeconds = function() { + var hr; + hr = hrtime(); + return hr[0] * 1e9 + hr[1]; + }; + moduleLoadTime = getNanoSeconds(); + upTime = process.uptime() * 1e9; + nodeLoadTime = moduleLoadTime - upTime; + } else if (Date.now) { + module.exports = function() { + return Date.now() - loadTime; + }; + loadTime = Date.now(); + } else { + module.exports = function() { + return new Date().getTime() - loadTime; + }; + loadTime = new Date().getTime(); + } + +}).call(this); + + + +}).call(this,_dereq_('_process')) + +},{"_process":465}],446:[function(_dereq_,module,exports){ +"use strict" + +module.exports = permutationSign + +var BRUTE_FORCE_CUTOFF = 32 + +var pool = _dereq_("typedarray-pool") + +function permutationSign(p) { + var n = p.length + if(n < BRUTE_FORCE_CUTOFF) { + //Use quadratic algorithm for small n + var sgn = 1 + for(var i=0; i0; --i) { + t = pinv[i] + s = p[i] + p[i] = p[t] + p[t] = s + pinv[i] = pinv[s] + pinv[s] = t + r = (r + s) * i + } + pool.freeUint32(pinv) + pool.freeUint32(p) + return r +} + +function unrank(n, r, p) { + switch(n) { + case 0: + if(p) { return p } + return [] + case 1: + if(p) { + p[0] = 0 + return p + } else { + return [0] + } + case 2: + if(p) { + if(r) { + p[0] = 0 + p[1] = 1 + } else { + p[0] = 1 + p[1] = 0 + } + return p + } else { + return r ? [0,1] : [1,0] + } + default: + break + } + p = p || new Array(n) + var s, t, i, nf=1 + p[0] = 0 + for(i=1; i0; --i) { + s = (r / nf)|0 + r = (r - s * nf)|0 + nf = (nf / i)|0 + t = p[i]|0 + p[i] = p[s]|0 + p[s] = t|0 + } + return p +} + +exports.rank = rank +exports.unrank = unrank + +},{"invert-permutation":398,"typedarray-pool":522}],448:[function(_dereq_,module,exports){ +'use strict' + + +module.exports = function pick (src, props, keepRest) { + var result = {}, prop, i + + if (typeof props === 'string') props = toList(props) + if (Array.isArray(props)) { + var res = {} + for (i = 0; i < props.length; i++) { + res[props[i]] = true + } + props = res + } + + // convert strings to lists + for (prop in props) { + props[prop] = toList(props[prop]) + } + + // keep-rest strategy requires unmatched props to be preserved + var occupied = {} + + for (prop in props) { + var aliases = props[prop] + + if (Array.isArray(aliases)) { + for (i = 0; i < aliases.length; i++) { + var alias = aliases[i] + + if (keepRest) { + occupied[alias] = true + } + + if (alias in src) { + result[prop] = src[alias] + + if (keepRest) { + for (var j = i; j < aliases.length; j++) { + occupied[aliases[j]] = true + } + } + + break + } + } + } + else if (prop in src) { + if (props[prop]) { + result[prop] = src[prop] + } + + if (keepRest) { + occupied[prop] = true + } + } + } + + if (keepRest) { + for (prop in src) { + if (occupied[prop]) continue + result[prop] = src[prop] + } + } + + return result +} + +var CACHE = {} + +function toList(arg) { + if (CACHE[arg]) return CACHE[arg] + if (typeof arg === 'string') { + arg = CACHE[arg] = arg.split(/\s*,\s*|\s+/) + } + return arg +} + +},{}],449:[function(_dereq_,module,exports){ +"use strict" + +module.exports = planarDual + +var compareAngle = _dereq_("compare-angle") + +function planarDual(cells, positions) { + + var numVertices = positions.length|0 + var numEdges = cells.length + var adj = [new Array(numVertices), new Array(numVertices)] + for(var i=0; i 0) { + nextCell = adj[i][b][0] + nextDir = i + break + } + } + nextVertex = nextCell[nextDir^1] + + for(var dir=0; dir<2; ++dir) { + var nbhd = adj[dir][b] + for(var k=0; k 0) { + nextCell = e + nextVertex = p + nextDir = dir + } + } + } + if(noCut) { + return nextVertex + } + if(nextCell) { + cut(nextCell, nextDir) + } + return nextVertex + } + + function extractCycle(v, dir) { + var e0 = adj[dir][v][0] + var cycle = [v] + cut(e0, dir) + var u = e0[dir^1] + var d0 = dir + while(true) { + while(u !== v) { + cycle.push(u) + u = next(cycle[cycle.length-2], u, false) + } + if(adj[0][v].length + adj[1][v].length === 0) { + break + } + var a = cycle[cycle.length-1] + var b = v + var c = cycle[1] + var d = next(a, b, true) + if(compareAngle(positions[a], positions[b], positions[c], positions[d]) < 0) { + break + } + cycle.push(v) + u = next(a, b) + } + return cycle + } + + function shouldGlue(pcycle, ncycle) { + return (ncycle[1] === ncycle[ncycle.length-1]) + } + + for(var i=0; i 0) { + var ni = adj[0][i].length + var ncycle = extractCycle(i,j) + if(shouldGlue(pcycle, ncycle)) { + //Glue together trivial cycles + pcycle.push.apply(pcycle, ncycle) + } else { + if(pcycle.length > 0) { + cycles.push(pcycle) + } + pcycle = ncycle + } + } + if(pcycle.length > 0) { + cycles.push(pcycle) + } + } + } + + //Combine paths and loops together + return cycles +} +},{"compare-angle":115}],450:[function(_dereq_,module,exports){ +'use strict' + +module.exports = trimLeaves + +var e2a = _dereq_('edges-to-adjacency-list') + +function trimLeaves(edges, positions) { + var adj = e2a(edges, positions.length) + var live = new Array(positions.length) + var nbhd = new Array(positions.length) + + var dead = [] + for(var i=0; i 0) { + var v = dead.pop() + live[v] = false + var n = adj[v] + for(var i=0; i 0 + } + + //Extract all clockwise faces + faces = faces.filter(ccw) + + //Detect which loops are contained in one another to handle parent-of relation + var numFaces = faces.length + var parent = new Array(numFaces) + var containment = new Array(numFaces) + for(var i=0; i 0) { + var top = toVisit.pop() + var nbhd = fadj[top] + uniq(nbhd, function(a,b) { + return a-b + }) + var nnbhr = nbhd.length + var p = parity[top] + var polyline + if(p === 0) { + var c = faces[top] + polyline = [c] + } + for(var i=0; i= 0) { + continue + } + parity[f] = p^1 + toVisit.push(f) + if(p === 0) { + var c = faces[f] + if(!sharedBoundary(c)) { + c.reverse() + polyline.push(c) + } + } + } + if(p === 0) { + result.push(polyline) + } + } + + return result +} +},{"./lib/trim-leaves":450,"edges-to-adjacency-list":157,"planar-dual":449,"point-in-big-polygon":455,"robust-sum":491,"two-product":520,"uniq":524}],452:[function(_dereq_,module,exports){ +'use strict' + +module.exports = _dereq_('./quad') +},{"./quad":454}],453:[function(_dereq_,module,exports){ +arguments[4][99][0].apply(exports,arguments) +},{"dup":99}],454:[function(_dereq_,module,exports){ +/** + * @module point-cluster/quad + * + * Bucket based quad tree clustering + */ + +'use strict' + +var search = _dereq_('binary-search-bounds') +var clamp = _dereq_('clamp') +var rect = _dereq_('parse-rect') +var getBounds = _dereq_('array-bounds') +var pick = _dereq_('pick-by-alias') +var defined = _dereq_('defined') +var flatten = _dereq_('flatten-vertex-data') +var isObj = _dereq_('is-obj') +var dtype = _dereq_('dtype') +var log2 = _dereq_('math-log2') + + +module.exports = function cluster (srcPoints, options) { + if (!options) { options = {} } + + srcPoints = flatten(srcPoints, 'float64') + + options = pick(options, { + bounds: 'range bounds dataBox databox', + maxDepth: 'depth maxDepth maxdepth level maxLevel maxlevel levels', + dtype: 'type dtype format out dst output destination' + // sort: 'sortBy sortby sort', + // pick: 'pick levelPoint', + // nodeSize: 'node nodeSize minNodeSize minSize size' + }) + + // let nodeSize = defined(options.nodeSize, 1) + var maxDepth = defined(options.maxDepth, 255) + var bounds = defined(options.bounds, getBounds(srcPoints, 2)) + if (bounds[0] === bounds[2]) { bounds[2]++ } + if (bounds[1] === bounds[3]) { bounds[3]++ } + + var points = normalize(srcPoints, bounds) + + // init variables + var n = srcPoints.length >>> 1 + var ids + if (!options.dtype) { options.dtype = 'array' } + + if (typeof options.dtype === 'string') { + ids = new (dtype(options.dtype))(n) + } + else if (options.dtype) { + ids = options.dtype + if (Array.isArray(ids)) { ids.length = n } + } + for (var i = 0; i < n; ++i) { + ids[i] = i + } + + // point indexes for levels [0: [a,b,c,d], 1: [a,b,c,d,e,f,...], ...] + var levels = [] + + // starting indexes of subranges in sub levels, levels.length * 4 + var sublevels = [] + + // unique group ids, sorted in z-curve fashion within levels + var groups = [] + + // level offsets in `ids` + var offsets = [] + + + // sort points + sort(0, 0, 1, ids, 0, 1) + + + // return reordered ids with provided methods + // save level offsets in output buffer + var offset = 0 + for (var level = 0; level < levels.length; level++) { + var levelItems = levels[level] + if (ids.set) { ids.set(levelItems, offset) } + else { + for (var i$1 = 0, l = levelItems.length; i$1 < l; i$1++) { + ids[i$1 + offset] = levelItems[i$1] + } + } + var nextOffset = offset + levels[level].length + offsets[level] = [offset, nextOffset] + offset = nextOffset + } + + ids.range = range + + return ids + + + + // FIXME: it is possible to create one typed array heap and reuse that to avoid memory blow + function sort (x, y, diam, ids, level, group) { + if (!ids.length) { return null } + + // save first point as level representative + var levelItems = levels[level] || (levels[level] = []) + var levelGroups = groups[level] || (groups[level] = []) + var sublevel = sublevels[level] || (sublevels[level] = []) + var offset = levelItems.length + + level++ + + // max depth reached - put all items into a first group + if (level > maxDepth) { + for (var i = 0; i < ids.length; i++) { + levelItems.push(ids[i]) + levelGroups.push(group) + sublevel.push(null, null, null, null) + } + + return offset + } + + levelItems.push(ids[0]) + levelGroups.push(group) + + if (ids.length <= 1) { + sublevel.push(null, null, null, null) + return offset + } + + + var d2 = diam * .5 + var cx = x + d2, cy = y + d2 + + // distribute points by 4 buckets + var lolo = [], lohi = [], hilo = [], hihi = [] + + for (var i$1 = 1, l = ids.length; i$1 < l; i$1++) { + var idx = ids[i$1], + x$1 = points[idx * 2], + y$1 = points[idx * 2 + 1] + x$1 < cx ? (y$1 < cy ? lolo.push(idx) : lohi.push(idx)) : (y$1 < cy ? hilo.push(idx) : hihi.push(idx)) + } + + group <<= 2 + sublevel.push( + sort(x, y, d2, lolo, level, group), + sort(x, cy, d2, lohi, level, group + 1), + sort(cx, y, d2, hilo, level, group + 2), + sort(cx, cy, d2, hihi, level, group + 3) + ) + + return offset + } + + // get all points within the passed range + function range () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var options + + if (isObj(args[args.length - 1])) { + var arg = args.pop() + + // detect if that was a rect object + if (!args.length && (arg.x != null || arg.l != null || arg.left != null)) { + args = [arg] + options = {} + } + + options = pick(arg, { + level: 'level maxLevel', + d: 'd diam diameter r radius px pxSize pixel pixelSize maxD size minSize', + lod: 'lod details ranges offsets' + }) + } + else { + options = {} + } + + if (!args.length) { args = bounds } + + var box = rect.apply( void 0, args ) + + var ref = [ + Math.min(box.x, box.x + box.width), + Math.min(box.y, box.y + box.height), + Math.max(box.x, box.x + box.width), + Math.max(box.y, box.y + box.height) + ]; + var minX = ref[0]; + var minY = ref[1]; + var maxX = ref[2]; + var maxY = ref[3]; + + var ref$1 = normalize([minX, minY, maxX, maxY], bounds ); + var nminX = ref$1[0]; + var nminY = ref$1[1]; + var nmaxX = ref$1[2]; + var nmaxY = ref$1[3]; + + var maxLevel = defined(options.level, levels.length) + + // limit maxLevel by px size + if (options.d != null) { + var d + if (typeof options.d === 'number') { d = [options.d, options.d] } + else if (options.d.length) { d = options.d } + + maxLevel = Math.min( + Math.max( + Math.ceil(-log2(Math.abs(d[0]) / (bounds[2] - bounds[0]))), + Math.ceil(-log2(Math.abs(d[1]) / (bounds[3] - bounds[1]))) + ), + maxLevel + ) + } + maxLevel = Math.min(maxLevel, levels.length) + + // return levels of details + if (options.lod) { + return lod(nminX, nminY, nmaxX, nmaxY, maxLevel) + } + + + + // do selection ids + var selection = [] + + // FIXME: probably we can do LOD here beforehead + select( 0, 0, 1, 0, 0, 1) + + function select ( lox, loy, d, level, from, to ) { + if (from === null || to === null) { return } + + var hix = lox + d + var hiy = loy + d + + // if box does not intersect level - ignore + if ( nminX > hix || nminY > hiy || nmaxX < lox || nmaxY < loy ) { return } + if ( level >= maxLevel ) { return } + if ( from === to ) { return } + + // if points fall into box range - take it + var levelItems = levels[level] + + if (to === undefined) { to = levelItems.length } + + for (var i = from; i < to; i++) { + var id = levelItems[i] + + var px = srcPoints[ id * 2 ] + var py = srcPoints[ id * 2 + 1 ] + + if ( px >= minX && px <= maxX && py >= minY && py <= maxY ) {selection.push(id) + } + } + + // for every subsection do select + var offsets = sublevels[ level ] + var off0 = offsets[ from * 4 + 0 ] + var off1 = offsets[ from * 4 + 1 ] + var off2 = offsets[ from * 4 + 2 ] + var off3 = offsets[ from * 4 + 3 ] + var end = nextOffset(offsets, from + 1) + + var d2 = d * .5 + var nextLevel = level + 1 + select( lox, loy, d2, nextLevel, off0, off1 || off2 || off3 || end) + select( lox, loy + d2, d2, nextLevel, off1, off2 || off3 || end) + select( lox + d2, loy, d2, nextLevel, off2, off3 || end) + select( lox + d2, loy + d2, d2, nextLevel, off3, end) + } + + function nextOffset(offsets, from) { + var offset = null, i = 0 + while(offset === null) { + offset = offsets[ from * 4 + i ] + i++ + if (i > offsets.length) { return null } + } + return offset + } + + return selection + } + + // get range offsets within levels to render lods appropriate for zoom level + // TODO: it is possible to store minSize of a point to optimize neede level calc + function lod (lox, loy, hix, hiy, maxLevel) { + var ranges = [] + + for (var level = 0; level < maxLevel; level++) { + var levelGroups = groups[level] + var from = offsets[level][0] + + var levelGroupStart = group(lox, loy, level) + var levelGroupEnd = group(hix, hiy, level) + + // FIXME: utilize sublevels to speed up search range here + var startOffset = search.ge(levelGroups, levelGroupStart) + var endOffset = search.gt(levelGroups, levelGroupEnd, startOffset, levelGroups.length - 1) + + ranges[level] = [startOffset + from, endOffset + from] + } + + return ranges + } + + // get group id closest to the x,y coordinate, corresponding to a level + function group (x, y, level) { + var group = 1 + + var cx = .5, cy = .5 + var diam = .5 + + for (var i = 0; i < level; i++) { + group <<= 2 + + group += x < cx ? (y < cy ? 0 : 1) : (y < cy ? 2 : 3) + + diam *= .5 + + cx += x < cx ? -diam : diam + cy += y < cy ? -diam : diam + } + + return group + } +} + + +// normalize points by bounds +function normalize (pts, bounds) { + var lox = bounds[0]; + var loy = bounds[1]; + var hix = bounds[2]; + var hiy = bounds[3]; + var scaleX = 1.0 / (hix - lox) + var scaleY = 1.0 / (hiy - loy) + var result = new Array(pts.length) + + for (var i = 0, n = pts.length / 2; i < n; i++) { + result[2*i] = clamp((pts[2*i] - lox) * scaleX, 0, 1) + result[2*i+1] = clamp((pts[2*i+1] - loy) * scaleY, 0, 1) + } + + return result +} +},{"array-bounds":53,"binary-search-bounds":453,"clamp":103,"defined":149,"dtype":154,"flatten-vertex-data":216,"is-obj":404,"math-log2":415,"parse-rect":442,"pick-by-alias":448}],455:[function(_dereq_,module,exports){ +module.exports = preprocessPolygon + +var orient = _dereq_('robust-orientation')[3] +var makeSlabs = _dereq_('slab-decomposition') +var makeIntervalTree = _dereq_('interval-tree-1d') +var bsearch = _dereq_('binary-search-bounds') + +function visitInterval() { + return true +} + +function intervalSearch(table) { + return function(x, y) { + var tree = table[x] + if(tree) { + return !!tree.queryPoint(y, visitInterval) + } + return false + } +} + +function buildVerticalIndex(segments) { + var table = {} + for(var i=0; i 0 && coordinates[bucket] === p[0]) { + root = slabs[bucket-1] + } else { + return 1 + } + } + var lastOrientation = 1 + while(root) { + var s = root.key + var o = orient(p, s[0], s[1]) + if(s[0][0] < s[1][0]) { + if(o < 0) { + root = root.left + } else if(o > 0) { + lastOrientation = -1 + root = root.right + } else { + return 0 + } + } else { + if(o > 0) { + root = root.left + } else if(o < 0) { + lastOrientation = 1 + root = root.right + } else { + return 0 + } + } + } + return lastOrientation + } +} + +function classifyEmpty(p) { + return 1 +} + +function createClassifyVertical(testVertical) { + return function classify(p) { + if(testVertical(p[0], p[1])) { + return 0 + } + return 1 + } +} + +function createClassifyPointDegen(testVertical, testNormal) { + return function classify(p) { + if(testVertical(p[0], p[1])) { + return 0 + } + return testNormal(p) + } +} + +function preprocessPolygon(loops) { + //Compute number of loops + var numLoops = loops.length + + //Unpack segments + var segments = [] + var vsegments = [] + var ptr = 0 + for(var i=0; i= -eps; + }, + pointBetween: function(p, left, right){ + // p must be collinear with left->right + // returns false if p == left, p == right, or left == right + var d_py_ly = p[1] - left[1]; + var d_rx_lx = right[0] - left[0]; + var d_px_lx = p[0] - left[0]; + var d_ry_ly = right[1] - left[1]; + + var dot = d_px_lx * d_rx_lx + d_py_ly * d_ry_ly; + // if `dot` is 0, then `p` == `left` or `left` == `right` (reject) + // if `dot` is less than 0, then `p` is to the left of `left` (reject) + if (dot < eps) + return false; + + var sqlen = d_rx_lx * d_rx_lx + d_ry_ly * d_ry_ly; + // if `dot` > `sqlen`, then `p` is to the right of `right` (reject) + // therefore, if `dot - sqlen` is greater than 0, then `p` is to the right of `right` (reject) + if (dot - sqlen > -eps) + return false; + + return true; + }, + pointsSameX: function(p1, p2){ + return Math.abs(p1[0] - p2[0]) < eps; + }, + pointsSameY: function(p1, p2){ + return Math.abs(p1[1] - p2[1]) < eps; + }, + pointsSame: function(p1, p2){ + return my.pointsSameX(p1, p2) && my.pointsSameY(p1, p2); + }, + pointsCompare: function(p1, p2){ + // returns -1 if p1 is smaller, 1 if p2 is smaller, 0 if equal + if (my.pointsSameX(p1, p2)) + return my.pointsSameY(p1, p2) ? 0 : (p1[1] < p2[1] ? -1 : 1); + return p1[0] < p2[0] ? -1 : 1; + }, + pointsCollinear: function(pt1, pt2, pt3){ + // does pt1->pt2->pt3 make a straight line? + // essentially this is just checking to see if the slope(pt1->pt2) === slope(pt2->pt3) + // if slopes are equal, then they must be collinear, because they share pt2 + var dx1 = pt1[0] - pt2[0]; + var dy1 = pt1[1] - pt2[1]; + var dx2 = pt2[0] - pt3[0]; + var dy2 = pt2[1] - pt3[1]; + return Math.abs(dx1 * dy2 - dx2 * dy1) < eps; + }, + linesIntersect: function(a0, a1, b0, b1){ + // returns false if the lines are coincident (e.g., parallel or on top of each other) + // + // returns an object if the lines intersect: + // { + // pt: [x, y], where the intersection point is at + // alongA: where intersection point is along A, + // alongB: where intersection point is along B + // } + // + // alongA and alongB will each be one of: -2, -1, 0, 1, 2 + // + // with the following meaning: + // + // -2 intersection point is before segment's first point + // -1 intersection point is directly on segment's first point + // 0 intersection point is between segment's first and second points (exclusive) + // 1 intersection point is directly on segment's second point + // 2 intersection point is after segment's second point + var adx = a1[0] - a0[0]; + var ady = a1[1] - a0[1]; + var bdx = b1[0] - b0[0]; + var bdy = b1[1] - b0[1]; + + var axb = adx * bdy - ady * bdx; + if (Math.abs(axb) < eps) + return false; // lines are coincident + + var dx = a0[0] - b0[0]; + var dy = a0[1] - b0[1]; + + var A = (bdx * dy - bdy * dx) / axb; + var B = (adx * dy - ady * dx) / axb; + + var ret = { + alongA: 0, + alongB: 0, + pt: [ + a0[0] + A * adx, + a0[1] + A * ady + ] + }; + + // categorize where intersection point is along A and B + + if (A <= -eps) + ret.alongA = -2; + else if (A < eps) + ret.alongA = -1; + else if (A - 1 <= -eps) + ret.alongA = 0; + else if (A - 1 < eps) + ret.alongA = 1; + else + ret.alongA = 2; + + if (B <= -eps) + ret.alongB = -2; + else if (B < eps) + ret.alongB = -1; + else if (B - 1 <= -eps) + ret.alongB = 0; + else if (B - 1 < eps) + ret.alongB = 1; + else + ret.alongB = 2; + + return ret; + }, + pointInsideRegion: function(pt, region){ + var x = pt[0]; + var y = pt[1]; + var last_x = region[region.length - 1][0]; + var last_y = region[region.length - 1][1]; + var inside = false; + for (var i = 0; i < region.length; i++){ + var curr_x = region[i][0]; + var curr_y = region[i][1]; + + // if y is between curr_y and last_y, and + // x is to the right of the boundary created by the line + if ((curr_y - y > eps) != (last_y - y > eps) && + (last_x - curr_x) * (y - curr_y) / (last_y - curr_y) + curr_x - x > eps) + inside = !inside + + last_x = curr_x; + last_y = curr_y; + } + return inside; + } + }; + return my; +} + +module.exports = Epsilon; + +},{}],459:[function(_dereq_,module,exports){ +// (c) Copyright 2017, Sean Connelly (@voidqk), http://syntheti.cc +// MIT License +// Project Home: https://github.com/voidqk/polybooljs + +// +// convert between PolyBool polygon format and GeoJSON formats (Polygon and MultiPolygon) +// + +var GeoJSON = { + // convert a GeoJSON object to a PolyBool polygon + toPolygon: function(PolyBool, geojson){ + + // converts list of LineString's to segments + function GeoPoly(coords){ + // check for empty coords + if (coords.length <= 0) + return PolyBool.segments({ inverted: false, regions: [] }); + + // convert LineString to segments + function LineString(ls){ + // remove tail which should be the same as head + var reg = ls.slice(0, ls.length - 1); + return PolyBool.segments({ inverted: false, regions: [reg] }); + } + + // the first LineString is considered the outside + var out = LineString(coords[0]); + + // the rest of the LineStrings are considered interior holes, so subtract them from the + // current result + for (var i = 1; i < coords.length; i++) + out = PolyBool.selectDifference(PolyBool.combine(out, LineString(coords[i]))); + + return out; + } + + if (geojson.type === 'Polygon'){ + // single polygon, so just convert it and we're done + return PolyBool.polygon(GeoPoly(geojson.coordinates)); + } + else if (geojson.type === 'MultiPolygon'){ + // multiple polygons, so union all the polygons together + var out = PolyBool.segments({ inverted: false, regions: [] }); + for (var i = 0; i < geojson.coordinates.length; i++) + out = PolyBool.selectUnion(PolyBool.combine(out, GeoPoly(geojson.coordinates[i]))); + return PolyBool.polygon(out); + } + throw new Error('PolyBool: Cannot convert GeoJSON object to PolyBool polygon'); + }, + + // convert a PolyBool polygon to a GeoJSON object + fromPolygon: function(PolyBool, eps, poly){ + // make sure out polygon is clean + poly = PolyBool.polygon(PolyBool.segments(poly)); + + // test if r1 is inside r2 + function regionInsideRegion(r1, r2){ + // we're guaranteed no lines intersect (because the polygon is clean), but a vertex + // could be on the edge -- so we just average pt[0] and pt[1] to produce a point on the + // edge of the first line, which cannot be on an edge + return eps.pointInsideRegion([ + (r1[0][0] + r1[1][0]) * 0.5, + (r1[0][1] + r1[1][1]) * 0.5 + ], r2); + } + + // calculate inside heirarchy + // + // _____________________ _______ roots -> A -> F + // | A | | F | | | + // | _______ _______ | | ___ | +-- B +-- G + // | | B | | C | | | | | | | | + // | | ___ | | ___ | | | | | | | +-- D + // | | | D | | | | E | | | | | G | | | + // | | |___| | | |___| | | | | | | +-- C + // | |_______| |_______| | | |___| | | + // |_____________________| |_______| +-- E + + function newNode(region){ + return { + region: region, + children: [] + }; + } + + var roots = newNode(null); + + function addChild(root, region){ + // first check if we're inside any children + for (var i = 0; i < root.children.length; i++){ + var child = root.children[i]; + if (regionInsideRegion(region, child.region)){ + // we are, so insert inside them instead + addChild(child, region); + return; + } + } + + // not inside any children, so check to see if any children are inside us + var node = newNode(region); + for (var i = 0; i < root.children.length; i++){ + var child = root.children[i]; + if (regionInsideRegion(child.region, region)){ + // oops... move the child beneath us, and remove them from root + node.children.push(child); + root.children.splice(i, 1); + i--; + } + } + + // now we can add ourselves + root.children.push(node); + } + + // add all regions to the root + for (var i = 0; i < poly.regions.length; i++){ + var region = poly.regions[i]; + if (region.length < 3) // regions must have at least 3 points (sanity check) + continue; + addChild(roots, region); + } + + // with our heirarchy, we can distinguish between exterior borders, and interior holes + // the root nodes are exterior, children are interior, children's children are exterior, + // children's children's children are interior, etc + + // while we're at it, exteriors are counter-clockwise, and interiors are clockwise + + function forceWinding(region, clockwise){ + // first, see if we're clockwise or counter-clockwise + // https://en.wikipedia.org/wiki/Shoelace_formula + var winding = 0; + var last_x = region[region.length - 1][0]; + var last_y = region[region.length - 1][1]; + var copy = []; + for (var i = 0; i < region.length; i++){ + var curr_x = region[i][0]; + var curr_y = region[i][1]; + copy.push([curr_x, curr_y]); // create a copy while we're at it + winding += curr_y * last_x - curr_x * last_y; + last_x = curr_x; + last_y = curr_y; + } + // this assumes Cartesian coordinates (Y is positive going up) + var isclockwise = winding < 0; + if (isclockwise !== clockwise) + copy.reverse(); + // while we're here, the last point must be the first point... + copy.push([copy[0][0], copy[0][1]]); + return copy; + } + + var geopolys = []; + + function addExterior(node){ + var poly = [forceWinding(node.region, false)]; + geopolys.push(poly); + // children of exteriors are interior + for (var i = 0; i < node.children.length; i++) + poly.push(getInterior(node.children[i])); + } + + function getInterior(node){ + // children of interiors are exterior + for (var i = 0; i < node.children.length; i++) + addExterior(node.children[i]); + // return the clockwise interior + return forceWinding(node.region, true); + } + + // root nodes are exterior + for (var i = 0; i < roots.children.length; i++) + addExterior(roots.children[i]); + + // lastly, construct the approrpriate GeoJSON object + + if (geopolys.length <= 0) // empty GeoJSON Polygon + return { type: 'Polygon', coordinates: [] }; + if (geopolys.length == 1) // use a GeoJSON Polygon + return { type: 'Polygon', coordinates: geopolys[0] }; + return { // otherwise, use a GeoJSON MultiPolygon + type: 'MultiPolygon', + coordinates: geopolys + }; + } +}; + +module.exports = GeoJSON; + +},{}],460:[function(_dereq_,module,exports){ +// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc +// MIT License +// Project Home: https://github.com/voidqk/polybooljs + +// +// this is the core work-horse +// + +var LinkedList = _dereq_('./linked-list'); + +function Intersecter(selfIntersection, eps, buildLog){ + // selfIntersection is true/false depending on the phase of the overall algorithm + + // + // segment creation + // + + function segmentNew(start, end){ + return { + id: buildLog ? buildLog.segmentId() : -1, + start: start, + end: end, + myFill: { + above: null, // is there fill above us? + below: null // is there fill below us? + }, + otherFill: null + }; + } + + function segmentCopy(start, end, seg){ + return { + id: buildLog ? buildLog.segmentId() : -1, + start: start, + end: end, + myFill: { + above: seg.myFill.above, + below: seg.myFill.below + }, + otherFill: null + }; + } + + // + // event logic + // + + var event_root = LinkedList.create(); + + function eventCompare(p1_isStart, p1_1, p1_2, p2_isStart, p2_1, p2_2){ + // compare the selected points first + var comp = eps.pointsCompare(p1_1, p2_1); + if (comp !== 0) + return comp; + // the selected points are the same + + if (eps.pointsSame(p1_2, p2_2)) // if the non-selected points are the same too... + return 0; // then the segments are equal + + if (p1_isStart !== p2_isStart) // if one is a start and the other isn't... + return p1_isStart ? 1 : -1; // favor the one that isn't the start + + // otherwise, we'll have to calculate which one is below the other manually + return eps.pointAboveOrOnLine(p1_2, + p2_isStart ? p2_1 : p2_2, // order matters + p2_isStart ? p2_2 : p2_1 + ) ? 1 : -1; + } + + function eventAdd(ev, other_pt){ + event_root.insertBefore(ev, function(here){ + // should ev be inserted before here? + var comp = eventCompare( + ev .isStart, ev .pt, other_pt, + here.isStart, here.pt, here.other.pt + ); + return comp < 0; + }); + } + + function eventAddSegmentStart(seg, primary){ + var ev_start = LinkedList.node({ + isStart: true, + pt: seg.start, + seg: seg, + primary: primary, + other: null, + status: null + }); + eventAdd(ev_start, seg.end); + return ev_start; + } + + function eventAddSegmentEnd(ev_start, seg, primary){ + var ev_end = LinkedList.node({ + isStart: false, + pt: seg.end, + seg: seg, + primary: primary, + other: ev_start, + status: null + }); + ev_start.other = ev_end; + eventAdd(ev_end, ev_start.pt); + } + + function eventAddSegment(seg, primary){ + var ev_start = eventAddSegmentStart(seg, primary); + eventAddSegmentEnd(ev_start, seg, primary); + return ev_start; + } + + function eventUpdateEnd(ev, end){ + // slides an end backwards + // (start)------------(end) to: + // (start)---(end) + + if (buildLog) + buildLog.segmentChop(ev.seg, end); + + ev.other.remove(); + ev.seg.end = end; + ev.other.pt = end; + eventAdd(ev.other, ev.pt); + } + + function eventDivide(ev, pt){ + var ns = segmentCopy(pt, ev.seg.end, ev.seg); + eventUpdateEnd(ev, pt); + return eventAddSegment(ns, ev.primary); + } + + function calculate(primaryPolyInverted, secondaryPolyInverted){ + // if selfIntersection is true then there is no secondary polygon, so that isn't used + + // + // status logic + // + + var status_root = LinkedList.create(); + + function statusCompare(ev1, ev2){ + var a1 = ev1.seg.start; + var a2 = ev1.seg.end; + var b1 = ev2.seg.start; + var b2 = ev2.seg.end; + + if (eps.pointsCollinear(a1, b1, b2)){ + if (eps.pointsCollinear(a2, b1, b2)) + return 1;//eventCompare(true, a1, a2, true, b1, b2); + return eps.pointAboveOrOnLine(a2, b1, b2) ? 1 : -1; + } + return eps.pointAboveOrOnLine(a1, b1, b2) ? 1 : -1; + } + + function statusFindSurrounding(ev){ + return status_root.findTransition(function(here){ + var comp = statusCompare(ev, here.ev); + return comp > 0; + }); + } + + function checkIntersection(ev1, ev2){ + // returns the segment equal to ev1, or false if nothing equal + + var seg1 = ev1.seg; + var seg2 = ev2.seg; + var a1 = seg1.start; + var a2 = seg1.end; + var b1 = seg2.start; + var b2 = seg2.end; + + if (buildLog) + buildLog.checkIntersection(seg1, seg2); + + var i = eps.linesIntersect(a1, a2, b1, b2); + + if (i === false){ + // segments are parallel or coincident + + // if points aren't collinear, then the segments are parallel, so no intersections + if (!eps.pointsCollinear(a1, a2, b1)) + return false; + // otherwise, segments are on top of each other somehow (aka coincident) + + if (eps.pointsSame(a1, b2) || eps.pointsSame(a2, b1)) + return false; // segments touch at endpoints... no intersection + + var a1_equ_b1 = eps.pointsSame(a1, b1); + var a2_equ_b2 = eps.pointsSame(a2, b2); + + if (a1_equ_b1 && a2_equ_b2) + return ev2; // segments are exactly equal + + var a1_between = !a1_equ_b1 && eps.pointBetween(a1, b1, b2); + var a2_between = !a2_equ_b2 && eps.pointBetween(a2, b1, b2); + + // handy for debugging: + // buildLog.log({ + // a1_equ_b1: a1_equ_b1, + // a2_equ_b2: a2_equ_b2, + // a1_between: a1_between, + // a2_between: a2_between + // }); + + if (a1_equ_b1){ + if (a2_between){ + // (a1)---(a2) + // (b1)----------(b2) + eventDivide(ev2, a2); + } + else{ + // (a1)----------(a2) + // (b1)---(b2) + eventDivide(ev1, b2); + } + return ev2; + } + else if (a1_between){ + if (!a2_equ_b2){ + // make a2 equal to b2 + if (a2_between){ + // (a1)---(a2) + // (b1)-----------------(b2) + eventDivide(ev2, a2); + } + else{ + // (a1)----------(a2) + // (b1)----------(b2) + eventDivide(ev1, b2); + } + } + + // (a1)---(a2) + // (b1)----------(b2) + eventDivide(ev2, a1); + } + } + else{ + // otherwise, lines intersect at i.pt, which may or may not be between the endpoints + + // is A divided between its endpoints? (exclusive) + if (i.alongA === 0){ + if (i.alongB === -1) // yes, at exactly b1 + eventDivide(ev1, b1); + else if (i.alongB === 0) // yes, somewhere between B's endpoints + eventDivide(ev1, i.pt); + else if (i.alongB === 1) // yes, at exactly b2 + eventDivide(ev1, b2); + } + + // is B divided between its endpoints? (exclusive) + if (i.alongB === 0){ + if (i.alongA === -1) // yes, at exactly a1 + eventDivide(ev2, a1); + else if (i.alongA === 0) // yes, somewhere between A's endpoints (exclusive) + eventDivide(ev2, i.pt); + else if (i.alongA === 1) // yes, at exactly a2 + eventDivide(ev2, a2); + } + } + return false; + } + + // + // main event loop + // + var segments = []; + while (!event_root.isEmpty()){ + var ev = event_root.getHead(); + + if (buildLog) + buildLog.vert(ev.pt[0]); + + if (ev.isStart){ + + if (buildLog) + buildLog.segmentNew(ev.seg, ev.primary); + + var surrounding = statusFindSurrounding(ev); + var above = surrounding.before ? surrounding.before.ev : null; + var below = surrounding.after ? surrounding.after.ev : null; + + if (buildLog){ + buildLog.tempStatus( + ev.seg, + above ? above.seg : false, + below ? below.seg : false + ); + } + + function checkBothIntersections(){ + if (above){ + var eve = checkIntersection(ev, above); + if (eve) + return eve; + } + if (below) + return checkIntersection(ev, below); + return false; + } + + var eve = checkBothIntersections(); + if (eve){ + // ev and eve are equal + // we'll keep eve and throw away ev + + // merge ev.seg's fill information into eve.seg + + if (selfIntersection){ + var toggle; // are we a toggling edge? + if (ev.seg.myFill.below === null) + toggle = true; + else + toggle = ev.seg.myFill.above !== ev.seg.myFill.below; + + // merge two segments that belong to the same polygon + // think of this as sandwiching two segments together, where `eve.seg` is + // the bottom -- this will cause the above fill flag to toggle + if (toggle) + eve.seg.myFill.above = !eve.seg.myFill.above; + } + else{ + // merge two segments that belong to different polygons + // each segment has distinct knowledge, so no special logic is needed + // note that this can only happen once per segment in this phase, because we + // are guaranteed that all self-intersections are gone + eve.seg.otherFill = ev.seg.myFill; + } + + if (buildLog) + buildLog.segmentUpdate(eve.seg); + + ev.other.remove(); + ev.remove(); + } + + if (event_root.getHead() !== ev){ + // something was inserted before us in the event queue, so loop back around and + // process it before continuing + if (buildLog) + buildLog.rewind(ev.seg); + continue; + } + + // + // calculate fill flags + // + if (selfIntersection){ + var toggle; // are we a toggling edge? + if (ev.seg.myFill.below === null) // if we are a new segment... + toggle = true; // then we toggle + else // we are a segment that has previous knowledge from a division + toggle = ev.seg.myFill.above !== ev.seg.myFill.below; // calculate toggle + + // next, calculate whether we are filled below us + if (!below){ // if nothing is below us... + // we are filled below us if the polygon is inverted + ev.seg.myFill.below = primaryPolyInverted; + } + else{ + // otherwise, we know the answer -- it's the same if whatever is below + // us is filled above it + ev.seg.myFill.below = below.seg.myFill.above; + } + + // since now we know if we're filled below us, we can calculate whether + // we're filled above us by applying toggle to whatever is below us + if (toggle) + ev.seg.myFill.above = !ev.seg.myFill.below; + else + ev.seg.myFill.above = ev.seg.myFill.below; + } + else{ + // now we fill in any missing transition information, since we are all-knowing + // at this point + + if (ev.seg.otherFill === null){ + // if we don't have other information, then we need to figure out if we're + // inside the other polygon + var inside; + if (!below){ + // if nothing is below us, then we're inside if the other polygon is + // inverted + inside = + ev.primary ? secondaryPolyInverted : primaryPolyInverted; + } + else{ // otherwise, something is below us + // so copy the below segment's other polygon's above + if (ev.primary === below.primary) + inside = below.seg.otherFill.above; + else + inside = below.seg.myFill.above; + } + ev.seg.otherFill = { + above: inside, + below: inside + }; + } + } + + if (buildLog){ + buildLog.status( + ev.seg, + above ? above.seg : false, + below ? below.seg : false + ); + } + + // insert the status and remember it for later removal + ev.other.status = surrounding.insert(LinkedList.node({ ev: ev })); + } + else{ + var st = ev.status; + + if (st === null){ + throw new Error('PolyBool: Zero-length segment detected; your epsilon is ' + + 'probably too small or too large'); + } + + // removing the status will create two new adjacent edges, so we'll need to check + // for those + if (status_root.exists(st.prev) && status_root.exists(st.next)) + checkIntersection(st.prev.ev, st.next.ev); + + if (buildLog) + buildLog.statusRemove(st.ev.seg); + + // remove the status + st.remove(); + + // if we've reached this point, we've calculated everything there is to know, so + // save the segment for reporting + if (!ev.primary){ + // make sure `seg.myFill` actually points to the primary polygon though + var s = ev.seg.myFill; + ev.seg.myFill = ev.seg.otherFill; + ev.seg.otherFill = s; + } + segments.push(ev.seg); + } + + // remove the event and continue + event_root.getHead().remove(); + } + + if (buildLog) + buildLog.done(); + + return segments; + } + + // return the appropriate API depending on what we're doing + if (!selfIntersection){ + // performing combination of polygons, so only deal with already-processed segments + return { + calculate: function(segments1, inverted1, segments2, inverted2){ + // segmentsX come from the self-intersection API, or this API + // invertedX is whether we treat that list of segments as an inverted polygon or not + // returns segments that can be used for further operations + segments1.forEach(function(seg){ + eventAddSegment(segmentCopy(seg.start, seg.end, seg), true); + }); + segments2.forEach(function(seg){ + eventAddSegment(segmentCopy(seg.start, seg.end, seg), false); + }); + return calculate(inverted1, inverted2); + } + }; + } + + // otherwise, performing self-intersection, so deal with regions + return { + addRegion: function(region){ + // regions are a list of points: + // [ [0, 0], [100, 0], [50, 100] ] + // you can add multiple regions before running calculate + var pt1; + var pt2 = region[region.length - 1]; + for (var i = 0; i < region.length; i++){ + pt1 = pt2; + pt2 = region[i]; + + var forward = eps.pointsCompare(pt1, pt2); + if (forward === 0) // points are equal, so we have a zero-length segment + continue; // just skip it + + eventAddSegment( + segmentNew( + forward < 0 ? pt1 : pt2, + forward < 0 ? pt2 : pt1 + ), + true + ); + } + }, + calculate: function(inverted){ + // is the polygon inverted? + // returns segments + return calculate(inverted, false); + } + }; +} + +module.exports = Intersecter; + +},{"./linked-list":461}],461:[function(_dereq_,module,exports){ +// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc +// MIT License +// Project Home: https://github.com/voidqk/polybooljs + +// +// simple linked list implementation that allows you to traverse down nodes and save positions +// + +var LinkedList = { + create: function(){ + var my = { + root: { root: true, next: null }, + exists: function(node){ + if (node === null || node === my.root) + return false; + return true; + }, + isEmpty: function(){ + return my.root.next === null; + }, + getHead: function(){ + return my.root.next; + }, + insertBefore: function(node, check){ + var last = my.root; + var here = my.root.next; + while (here !== null){ + if (check(here)){ + node.prev = here.prev; + node.next = here; + here.prev.next = node; + here.prev = node; + return; + } + last = here; + here = here.next; + } + last.next = node; + node.prev = last; + node.next = null; + }, + findTransition: function(check){ + var prev = my.root; + var here = my.root.next; + while (here !== null){ + if (check(here)) + break; + prev = here; + here = here.next; + } + return { + before: prev === my.root ? null : prev, + after: here, + insert: function(node){ + node.prev = prev; + node.next = here; + prev.next = node; + if (here !== null) + here.prev = node; + return node; + } + }; + } + }; + return my; + }, + node: function(data){ + data.prev = null; + data.next = null; + data.remove = function(){ + data.prev.next = data.next; + if (data.next) + data.next.prev = data.prev; + data.prev = null; + data.next = null; + }; + return data; + } +}; + +module.exports = LinkedList; + +},{}],462:[function(_dereq_,module,exports){ +// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc +// MIT License +// Project Home: https://github.com/voidqk/polybooljs + +// +// converts a list of segments into a list of regions, while also removing unnecessary verticies +// + +function SegmentChainer(segments, eps, buildLog){ + var chains = []; + var regions = []; + + segments.forEach(function(seg){ + var pt1 = seg.start; + var pt2 = seg.end; + if (eps.pointsSame(pt1, pt2)){ + console.warn('PolyBool: Warning: Zero-length segment detected; your epsilon is ' + + 'probably too small or too large'); + return; + } + + if (buildLog) + buildLog.chainStart(seg); + + // search for two chains that this segment matches + var first_match = { + index: 0, + matches_head: false, + matches_pt1: false + }; + var second_match = { + index: 0, + matches_head: false, + matches_pt1: false + }; + var next_match = first_match; + function setMatch(index, matches_head, matches_pt1){ + // return true if we've matched twice + next_match.index = index; + next_match.matches_head = matches_head; + next_match.matches_pt1 = matches_pt1; + if (next_match === first_match){ + next_match = second_match; + return false; + } + next_match = null; + return true; // we've matched twice, we're done here + } + for (var i = 0; i < chains.length; i++){ + var chain = chains[i]; + var head = chain[0]; + var head2 = chain[1]; + var tail = chain[chain.length - 1]; + var tail2 = chain[chain.length - 2]; + if (eps.pointsSame(head, pt1)){ + if (setMatch(i, true, true)) + break; + } + else if (eps.pointsSame(head, pt2)){ + if (setMatch(i, true, false)) + break; + } + else if (eps.pointsSame(tail, pt1)){ + if (setMatch(i, false, true)) + break; + } + else if (eps.pointsSame(tail, pt2)){ + if (setMatch(i, false, false)) + break; + } + } + + if (next_match === first_match){ + // we didn't match anything, so create a new chain + chains.push([ pt1, pt2 ]); + if (buildLog) + buildLog.chainNew(pt1, pt2); + return; + } + + if (next_match === second_match){ + // we matched a single chain + + if (buildLog) + buildLog.chainMatch(first_match.index); + + // add the other point to the apporpriate end, and check to see if we've closed the + // chain into a loop + + var index = first_match.index; + var pt = first_match.matches_pt1 ? pt2 : pt1; // if we matched pt1, then we add pt2, etc + var addToHead = first_match.matches_head; // if we matched at head, then add to the head + + var chain = chains[index]; + var grow = addToHead ? chain[0] : chain[chain.length - 1]; + var grow2 = addToHead ? chain[1] : chain[chain.length - 2]; + var oppo = addToHead ? chain[chain.length - 1] : chain[0]; + var oppo2 = addToHead ? chain[chain.length - 2] : chain[1]; + + if (eps.pointsCollinear(grow2, grow, pt)){ + // grow isn't needed because it's directly between grow2 and pt: + // grow2 ---grow---> pt + if (addToHead){ + if (buildLog) + buildLog.chainRemoveHead(first_match.index, pt); + chain.shift(); + } + else{ + if (buildLog) + buildLog.chainRemoveTail(first_match.index, pt); + chain.pop(); + } + grow = grow2; // old grow is gone... new grow is what grow2 was + } + + if (eps.pointsSame(oppo, pt)){ + // we're closing the loop, so remove chain from chains + chains.splice(index, 1); + + if (eps.pointsCollinear(oppo2, oppo, grow)){ + // oppo isn't needed because it's directly between oppo2 and grow: + // oppo2 ---oppo--->grow + if (addToHead){ + if (buildLog) + buildLog.chainRemoveTail(first_match.index, grow); + chain.pop(); + } + else{ + if (buildLog) + buildLog.chainRemoveHead(first_match.index, grow); + chain.shift(); + } + } + + if (buildLog) + buildLog.chainClose(first_match.index); + + // we have a closed chain! + regions.push(chain); + return; + } + + // not closing a loop, so just add it to the apporpriate side + if (addToHead){ + if (buildLog) + buildLog.chainAddHead(first_match.index, pt); + chain.unshift(pt); + } + else{ + if (buildLog) + buildLog.chainAddTail(first_match.index, pt); + chain.push(pt); + } + return; + } + + // otherwise, we matched two chains, so we need to combine those chains together + + function reverseChain(index){ + if (buildLog) + buildLog.chainReverse(index); + chains[index].reverse(); // gee, that's easy + } + + function appendChain(index1, index2){ + // index1 gets index2 appended to it, and index2 is removed + var chain1 = chains[index1]; + var chain2 = chains[index2]; + var tail = chain1[chain1.length - 1]; + var tail2 = chain1[chain1.length - 2]; + var head = chain2[0]; + var head2 = chain2[1]; + + if (eps.pointsCollinear(tail2, tail, head)){ + // tail isn't needed because it's directly between tail2 and head + // tail2 ---tail---> head + if (buildLog) + buildLog.chainRemoveTail(index1, tail); + chain1.pop(); + tail = tail2; // old tail is gone... new tail is what tail2 was + } + + if (eps.pointsCollinear(tail, head, head2)){ + // head isn't needed because it's directly between tail and head2 + // tail ---head---> head2 + if (buildLog) + buildLog.chainRemoveHead(index2, head); + chain2.shift(); + } + + if (buildLog) + buildLog.chainJoin(index1, index2); + chains[index1] = chain1.concat(chain2); + chains.splice(index2, 1); + } + + var F = first_match.index; + var S = second_match.index; + + if (buildLog) + buildLog.chainConnect(F, S); + + var reverseF = chains[F].length < chains[S].length; // reverse the shorter chain, if needed + if (first_match.matches_head){ + if (second_match.matches_head){ + if (reverseF){ + // <<<< F <<<< --- >>>> S >>>> + reverseChain(F); + // >>>> F >>>> --- >>>> S >>>> + appendChain(F, S); + } + else{ + // <<<< F <<<< --- >>>> S >>>> + reverseChain(S); + // <<<< F <<<< --- <<<< S <<<< logically same as: + // >>>> S >>>> --- >>>> F >>>> + appendChain(S, F); + } + } + else{ + // <<<< F <<<< --- <<<< S <<<< logically same as: + // >>>> S >>>> --- >>>> F >>>> + appendChain(S, F); + } + } + else{ + if (second_match.matches_head){ + // >>>> F >>>> --- >>>> S >>>> + appendChain(F, S); + } + else{ + if (reverseF){ + // >>>> F >>>> --- <<<< S <<<< + reverseChain(F); + // <<<< F <<<< --- <<<< S <<<< logically same as: + // >>>> S >>>> --- >>>> F >>>> + appendChain(S, F); + } + else{ + // >>>> F >>>> --- <<<< S <<<< + reverseChain(S); + // >>>> F >>>> --- >>>> S >>>> + appendChain(F, S); + } + } + } + }); + + return regions; +} + +module.exports = SegmentChainer; + +},{}],463:[function(_dereq_,module,exports){ +// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc +// MIT License +// Project Home: https://github.com/voidqk/polybooljs + +// +// filter a list of segments based on boolean operations +// + +function select(segments, selection, buildLog){ + var result = []; + segments.forEach(function(seg){ + var index = + (seg.myFill.above ? 8 : 0) + + (seg.myFill.below ? 4 : 0) + + ((seg.otherFill && seg.otherFill.above) ? 2 : 0) + + ((seg.otherFill && seg.otherFill.below) ? 1 : 0); + if (selection[index] !== 0){ + // copy the segment to the results, while also calculating the fill status + result.push({ + id: buildLog ? buildLog.segmentId() : -1, + start: seg.start, + end: seg.end, + myFill: { + above: selection[index] === 1, // 1 if filled above + below: selection[index] === 2 // 2 if filled below + }, + otherFill: null + }); + } + }); + + if (buildLog) + buildLog.selected(result); + + return result; +} + +var SegmentSelector = { + union: function(segments, buildLog){ // primary | secondary + // above1 below1 above2 below2 Keep? Value + // 0 0 0 0 => no 0 + // 0 0 0 1 => yes filled below 2 + // 0 0 1 0 => yes filled above 1 + // 0 0 1 1 => no 0 + // 0 1 0 0 => yes filled below 2 + // 0 1 0 1 => yes filled below 2 + // 0 1 1 0 => no 0 + // 0 1 1 1 => no 0 + // 1 0 0 0 => yes filled above 1 + // 1 0 0 1 => no 0 + // 1 0 1 0 => yes filled above 1 + // 1 0 1 1 => no 0 + // 1 1 0 0 => no 0 + // 1 1 0 1 => no 0 + // 1 1 1 0 => no 0 + // 1 1 1 1 => no 0 + return select(segments, [ + 0, 2, 1, 0, + 2, 2, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 + ], buildLog); + }, + intersect: function(segments, buildLog){ // primary & secondary + // above1 below1 above2 below2 Keep? Value + // 0 0 0 0 => no 0 + // 0 0 0 1 => no 0 + // 0 0 1 0 => no 0 + // 0 0 1 1 => no 0 + // 0 1 0 0 => no 0 + // 0 1 0 1 => yes filled below 2 + // 0 1 1 0 => no 0 + // 0 1 1 1 => yes filled below 2 + // 1 0 0 0 => no 0 + // 1 0 0 1 => no 0 + // 1 0 1 0 => yes filled above 1 + // 1 0 1 1 => yes filled above 1 + // 1 1 0 0 => no 0 + // 1 1 0 1 => yes filled below 2 + // 1 1 1 0 => yes filled above 1 + // 1 1 1 1 => no 0 + return select(segments, [ + 0, 0, 0, 0, + 0, 2, 0, 2, + 0, 0, 1, 1, + 0, 2, 1, 0 + ], buildLog); + }, + difference: function(segments, buildLog){ // primary - secondary + // above1 below1 above2 below2 Keep? Value + // 0 0 0 0 => no 0 + // 0 0 0 1 => no 0 + // 0 0 1 0 => no 0 + // 0 0 1 1 => no 0 + // 0 1 0 0 => yes filled below 2 + // 0 1 0 1 => no 0 + // 0 1 1 0 => yes filled below 2 + // 0 1 1 1 => no 0 + // 1 0 0 0 => yes filled above 1 + // 1 0 0 1 => yes filled above 1 + // 1 0 1 0 => no 0 + // 1 0 1 1 => no 0 + // 1 1 0 0 => no 0 + // 1 1 0 1 => yes filled above 1 + // 1 1 1 0 => yes filled below 2 + // 1 1 1 1 => no 0 + return select(segments, [ + 0, 0, 0, 0, + 2, 0, 2, 0, + 1, 1, 0, 0, + 0, 1, 2, 0 + ], buildLog); + }, + differenceRev: function(segments, buildLog){ // secondary - primary + // above1 below1 above2 below2 Keep? Value + // 0 0 0 0 => no 0 + // 0 0 0 1 => yes filled below 2 + // 0 0 1 0 => yes filled above 1 + // 0 0 1 1 => no 0 + // 0 1 0 0 => no 0 + // 0 1 0 1 => no 0 + // 0 1 1 0 => yes filled above 1 + // 0 1 1 1 => yes filled above 1 + // 1 0 0 0 => no 0 + // 1 0 0 1 => yes filled below 2 + // 1 0 1 0 => no 0 + // 1 0 1 1 => yes filled below 2 + // 1 1 0 0 => no 0 + // 1 1 0 1 => no 0 + // 1 1 1 0 => no 0 + // 1 1 1 1 => no 0 + return select(segments, [ + 0, 2, 1, 0, + 0, 0, 1, 1, + 0, 2, 0, 2, + 0, 0, 0, 0 + ], buildLog); + }, + xor: function(segments, buildLog){ // primary ^ secondary + // above1 below1 above2 below2 Keep? Value + // 0 0 0 0 => no 0 + // 0 0 0 1 => yes filled below 2 + // 0 0 1 0 => yes filled above 1 + // 0 0 1 1 => no 0 + // 0 1 0 0 => yes filled below 2 + // 0 1 0 1 => no 0 + // 0 1 1 0 => no 0 + // 0 1 1 1 => yes filled above 1 + // 1 0 0 0 => yes filled above 1 + // 1 0 0 1 => no 0 + // 1 0 1 0 => no 0 + // 1 0 1 1 => yes filled below 2 + // 1 1 0 0 => no 0 + // 1 1 0 1 => yes filled above 1 + // 1 1 1 0 => yes filled below 2 + // 1 1 1 1 => no 0 + return select(segments, [ + 0, 2, 1, 0, + 2, 0, 0, 1, + 1, 0, 0, 2, + 0, 1, 2, 0 + ], buildLog); + } +}; + +module.exports = SegmentSelector; + +},{}],464:[function(_dereq_,module,exports){ +//Optimized version for triangle closest point +// Based on Eberly's WildMagick codes +// http://www.geometrictools.com/LibMathematics/Distance/Distance.html +"use strict"; + +var diff = new Float64Array(4); +var edge0 = new Float64Array(4); +var edge1 = new Float64Array(4); + +function closestPoint2d(V0, V1, V2, point, result) { + //Reallocate buffers if necessary + if(diff.length < point.length) { + diff = new Float64Array(point.length); + edge0 = new Float64Array(point.length); + edge1 = new Float64Array(point.length); + } + //Compute edges + for(var i=0; i= a00) { + s = 1.0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } else { + s = 0; + if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else if (-b1 >= a11) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else { // region 3 + s = 0; + if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else if (-b1 >= a11) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else if (t < 0) { // region 5 + t = 0; + if (b0 >= 0) { + s = 0; + sqrDistance = c; + } else if (-b0 >= a00) { + s = 1; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } else { // region 0 + // minimum at interior point + var invDet = 1.0 / det; + s *= invDet; + t *= invDet; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + var tmp0, tmp1, numer, denom; + + if (s < 0) { // region 2 + tmp0 = a01 + b0; + tmp1 = a11 + b1; + if (tmp1 > tmp0) { + numer = tmp1 - tmp0; + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + s = 1; + t = 0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = numer/denom; + t = 1 - s; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + s = 0; + if (tmp1 <= 0) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else if (t < 0) { // region 6 + tmp0 = a01 + b1; + tmp1 = a00 + b0; + if (tmp1 > tmp0) { + numer = tmp1 - tmp0; + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + t = 1; + s = 0; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = numer/denom; + s = 1 - t; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + t = 0; + if (tmp1 <= 0) { + s = 1; + sqrDistance = a00 + 2.0*b0 + c; + } else if (b0 >= 0) { + s = 0; + sqrDistance = c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } + } else { // region 1 + numer = a11 + b1 - a01 - b0; + if (numer <= 0) { + s = 0; + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + s = 1; + t = 0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = numer/denom; + t = 1 - s; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } + } + } + var u = 1.0 - s - t; + for(var i=0; i 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],466:[function(_dereq_,module,exports){ +module.exports = _dereq_('gl-quat/slerp') +},{"gl-quat/slerp":280}],467:[function(_dereq_,module,exports){ +(function (global){ +var now = _dereq_('performance-now') + , root = typeof window === 'undefined' ? global : window + , vendors = ['moz', 'webkit'] + , suffix = 'AnimationFrame' + , raf = root['request' + suffix] + , caf = root['cancel' + suffix] || root['cancelRequest' + suffix] + +for(var i = 0; !raf && i < vendors.length; i++) { + raf = root[vendors[i] + 'Request' + suffix] + caf = root[vendors[i] + 'Cancel' + suffix] + || root[vendors[i] + 'CancelRequest' + suffix] +} + +// Some versions of FF have rAF but not cAF +if(!raf || !caf) { + var last = 0 + , id = 0 + , queue = [] + , frameDuration = 1000 / 60 + + raf = function(callback) { + if(queue.length === 0) { + var _now = now() + , next = Math.max(0, frameDuration - (_now - last)) + last = next + _now + setTimeout(function() { + var cp = queue.slice(0) + // Clear queue here to prevent + // callbacks from appending listeners + // to the current frame's queue + queue.length = 0 + for(var i = 0; i < cp.length; i++) { + if(!cp[i].cancelled) { + try{ + cp[i].callback(last) + } catch(e) { + setTimeout(function() { throw e }, 0) + } + } + } + }, Math.round(next)) + } + queue.push({ + handle: ++id, + callback: callback, + cancelled: false + }) + return id + } + + caf = function(handle) { + for(var i = 0; i < queue.length; i++) { + if(queue[i].handle === handle) { + queue[i].cancelled = true + } + } + } +} + +module.exports = function(fn) { + // Wrap in a new function to prevent + // `cancel` potentially being assigned + // to the native rAF function + return raf.call(root, fn) +} +module.exports.cancel = function() { + caf.apply(root, arguments) +} +module.exports.polyfill = function(object) { + if (!object) { + object = root; + } + object.requestAnimationFrame = raf + object.cancelAnimationFrame = caf +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"performance-now":445}],468:[function(_dereq_,module,exports){ +'use strict' + +var bnadd = _dereq_('big-rat/add') + +module.exports = add + +function add (a, b) { + var n = a.length + var r = new Array(n) + for (var i=0; i 0) { + var f = cells[ptr-1] + if(compareCell(c, f) === 0 && + orientation(f) !== o) { + ptr -= 1 + continue + } + } + cells[ptr++] = c + } + cells.length = ptr + return cells +} + +},{"cell-orientation":100,"compare-cell":116,"compare-oriented-cell":117}],473:[function(_dereq_,module,exports){ +'use strict' + +var getBounds = _dereq_('array-bounds') +var rgba = _dereq_('color-normalize') +var updateDiff = _dereq_('update-diff') +var pick = _dereq_('pick-by-alias') +var extend = _dereq_('object-assign') +var flatten = _dereq_('flatten-vertex-data') +var ref = _dereq_('to-float32'); +var float32 = ref.float32; +var fract32 = ref.fract32; + +module.exports = Error2D + +var WEIGHTS = [ + //direction, lineWidth shift, capSize shift + + // x-error bar + [1, 0, 0, 1, 0, 0], + [1, 0, 0, -1, 0, 0], + [-1, 0, 0, -1, 0, 0], + + [-1, 0, 0, -1, 0, 0], + [-1, 0, 0, 1, 0, 0], + [1, 0, 0, 1, 0, 0], + + // x-error right cap + [1, 0, -1, 0, 0, 1], + [1, 0, -1, 0, 0, -1], + [1, 0, 1, 0, 0, -1], + + [1, 0, 1, 0, 0, -1], + [1, 0, 1, 0, 0, 1], + [1, 0, -1, 0, 0, 1], + + // x-error left cap + [-1, 0, -1, 0, 0, 1], + [-1, 0, -1, 0, 0, -1], + [-1, 0, 1, 0, 0, -1], + + [-1, 0, 1, 0, 0, -1], + [-1, 0, 1, 0, 0, 1], + [-1, 0, -1, 0, 0, 1], + + // y-error bar + [0, 1, 1, 0, 0, 0], + [0, 1, -1, 0, 0, 0], + [0, -1, -1, 0, 0, 0], + + [0, -1, -1, 0, 0, 0], + [0, 1, 1, 0, 0, 0], + [0, -1, 1, 0, 0, 0], + + // y-error top cap + [0, 1, 0, -1, 1, 0], + [0, 1, 0, -1, -1, 0], + [0, 1, 0, 1, -1, 0], + + [0, 1, 0, 1, 1, 0], + [0, 1, 0, -1, 1, 0], + [0, 1, 0, 1, -1, 0], + + // y-error bottom cap + [0, -1, 0, -1, 1, 0], + [0, -1, 0, -1, -1, 0], + [0, -1, 0, 1, -1, 0], + + [0, -1, 0, 1, 1, 0], + [0, -1, 0, -1, 1, 0], + [0, -1, 0, 1, -1, 0] +] + + +function Error2D (regl, options) { + if (typeof regl === 'function') { + if (!options) { options = {} } + options.regl = regl + } + else { + options = regl + } + if (options.length) { options.positions = options } + regl = options.regl + + if (!regl.hasExtension('ANGLE_instanced_arrays')) { + throw Error('regl-error2d: `ANGLE_instanced_arrays` extension should be enabled'); + } + + // persistent variables + var gl = regl._gl, drawErrors, positionBuffer, positionFractBuffer, colorBuffer, errorBuffer, meshBuffer, + defaults = { + color: 'black', + capSize: 5, + lineWidth: 1, + opacity: 1, + viewport: null, + range: null, + offset: 0, + count: 0, + bounds: null, + positions: [], + errors: [] + }, groups = [] + + //color per-point + colorBuffer = regl.buffer({ + usage: 'dynamic', + type: 'uint8', + data: new Uint8Array(0) + }) + //xy-position per-point + positionBuffer = regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array(0) + }) + //xy-position float32-fraction + positionFractBuffer = regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array(0) + }) + //4 errors per-point + errorBuffer = regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array(0) + }) + //error bar mesh + meshBuffer = regl.buffer({ + usage: 'static', + type: 'float', + data: WEIGHTS + }) + + update(options) + + //drawing method + drawErrors = regl({ + vert: "\n\t\tprecision highp float;\n\n\t\tattribute vec2 position, positionFract;\n\t\tattribute vec4 error;\n\t\tattribute vec4 color;\n\n\t\tattribute vec2 direction, lineOffset, capOffset;\n\n\t\tuniform vec4 viewport;\n\t\tuniform float lineWidth, capSize;\n\t\tuniform vec2 scale, scaleFract, translate, translateFract;\n\n\t\tvarying vec4 fragColor;\n\n\t\tvoid main() {\n\t\t\tfragColor = color / 255.;\n\n\t\t\tvec2 pixelOffset = lineWidth * lineOffset + (capSize + lineWidth) * capOffset;\n\n\t\t\tvec2 dxy = -step(.5, direction.xy) * error.xz + step(direction.xy, vec2(-.5)) * error.yw;\n\n\t\t\tvec2 position = position + dxy;\n\n\t\t\tvec2 pos = (position + translate) * scale\n\t\t\t\t+ (positionFract + translateFract) * scale\n\t\t\t\t+ (position + translate) * scaleFract\n\t\t\t\t+ (positionFract + translateFract) * scaleFract;\n\n\t\t\tpos += pixelOffset / viewport.zw;\n\n\t\t\tgl_Position = vec4(pos * 2. - 1., 0, 1);\n\t\t}\n\t\t", + + frag: "\n\t\tprecision mediump float;\n\n\t\tvarying vec4 fragColor;\n\n\t\tuniform float opacity;\n\n\t\tvoid main() {\n\t\t\tgl_FragColor = fragColor;\n\t\t\tgl_FragColor.a *= opacity;\n\t\t}\n\t\t", + + uniforms: { + range: regl.prop('range'), + lineWidth: regl.prop('lineWidth'), + capSize: regl.prop('capSize'), + opacity: regl.prop('opacity'), + scale: regl.prop('scale'), + translate: regl.prop('translate'), + scaleFract: regl.prop('scaleFract'), + translateFract: regl.prop('translateFract'), + viewport: function (ctx, prop) { return [prop.viewport.x, prop.viewport.y, ctx.viewportWidth, ctx.viewportHeight]; } + }, + + attributes: { + //dynamic attributes + color: { + buffer: colorBuffer, + offset: function (ctx, prop) { return prop.offset * 4; }, + divisor: 1, + }, + position: { + buffer: positionBuffer, + offset: function (ctx, prop) { return prop.offset * 8; }, + divisor: 1 + }, + positionFract: { + buffer: positionFractBuffer, + offset: function (ctx, prop) { return prop.offset * 8; }, + divisor: 1 + }, + error: { + buffer: errorBuffer, + offset: function (ctx, prop) { return prop.offset * 16; }, + divisor: 1 + }, + + //static attributes + direction: { + buffer: meshBuffer, + stride: 24, + offset: 0 + }, + lineOffset: { + buffer: meshBuffer, + stride: 24, + offset: 8 + }, + capOffset: { + buffer: meshBuffer, + stride: 24, + offset: 16 + } + }, + + primitive: 'triangles', + + blend: { + enable: true, + color: [0,0,0,0], + equation: { + rgb: 'add', + alpha: 'add' + }, + func: { + srcRGB: 'src alpha', + dstRGB: 'one minus src alpha', + srcAlpha: 'one minus dst alpha', + dstAlpha: 'one' + } + }, + + depth: { + enable: false + }, + + scissor: { + enable: true, + box: regl.prop('viewport') + }, + viewport: regl.prop('viewport'), + stencil: false, + + instances: regl.prop('count'), + count: WEIGHTS.length + }) + + //expose API + extend(error2d, { + update: update, + draw: draw, + destroy: destroy, + regl: regl, + gl: gl, + canvas: gl.canvas, + groups: groups + }) + + return error2d + + function error2d (opts) { + //update + if (opts) { + update(opts) + } + + //destroy + else if (opts === null) { + destroy() + } + + draw() + } + + + //main draw method + function draw (options) { + if (typeof options === 'number') { return drawGroup(options) } + + //make options a batch + if (options && !Array.isArray(options)) { options = [options] } + + + regl._refresh() + + //render multiple polylines via regl batch + groups.forEach(function (s, i) { + if (!s) { return } + + if (options) { + if (!options[i]) { s.draw = false } + else { s.draw = true } + } + + //ignore draw flag for one pass + if (!s.draw) { + s.draw = true; + return + } + + drawGroup(i) + }) + } + + //draw single error group by id + function drawGroup (s) { + if (typeof s === 'number') { s = groups[s] } + if (s == null) { return } + + if (!(s && s.count && s.color && s.opacity && s.positions && s.positions.length > 1)) { return } + + s.scaleRatio = [ + s.scale[0] * s.viewport.width, + s.scale[1] * s.viewport.height + ] + + drawErrors(s) + + if (s.after) { s.after(s) } + } + + function update (options) { + if (!options) { return } + + //direct points argument + if (options.length != null) { + if (typeof options[0] === 'number') { options = [{positions: options}] } + } + + //make options a batch + else if (!Array.isArray(options)) { options = [options] } + + //global count of points + var pointCount = 0, errorCount = 0 + + error2d.groups = groups = options.map(function (options, i) { + var group = groups[i] + + if (!options) { return group } + else if (typeof options === 'function') { options = {after: options} } + else if (typeof options[0] === 'number') { options = {positions: options} } + + //copy options to avoid mutation & handle aliases + options = pick(options, { + color: 'color colors fill', + capSize: 'capSize cap capsize cap-size', + lineWidth: 'lineWidth line-width width line thickness', + opacity: 'opacity alpha', + range: 'range dataBox', + viewport: 'viewport viewBox', + errors: 'errors error', + positions: 'positions position data points' + }) + + if (!group) { + groups[i] = group = { + id: i, + scale: null, + translate: null, + scaleFract: null, + translateFract: null, + draw: true + } + options = extend({}, defaults, options) + } + + updateDiff(group, options, [{ + lineWidth: function (v) { return +v * .5; }, + capSize: function (v) { return +v * .5; }, + opacity: parseFloat, + errors: function (errors) { + errors = flatten(errors) + + errorCount += errors.length + return errors + }, + positions: function (positions, state) { + positions = flatten(positions, 'float64') + state.count = Math.floor(positions.length / 2) + state.bounds = getBounds(positions, 2) + state.offset = pointCount + + pointCount += state.count + + return positions + } + }, { + color: function (colors, state) { + var count = state.count + + if (!colors) { colors = 'transparent' } + + // 'black' or [0,0,0,0] case + if (!Array.isArray(colors) || typeof colors[0] === 'number') { + var color = colors + colors = Array(count) + for (var i = 0; i < count; i++) { + colors[i] = color + } + } + + if (colors.length < count) { throw Error('Not enough colors') } + + var colorData = new Uint8Array(count * 4) + + //convert colors to float arrays + for (var i$1 = 0; i$1 < count; i$1++) { + var c = rgba(colors[i$1], 'uint8') + colorData.set(c, i$1 * 4) + } + + return colorData + }, + + range: function (range, state, options) { + var bounds = state.bounds + if (!range) { range = bounds } + + state.scale = [1 / (range[2] - range[0]), 1 / (range[3] - range[1])] + state.translate = [-range[0], -range[1]] + + state.scaleFract = fract32(state.scale) + state.translateFract = fract32(state.translate) + + return range + }, + + viewport: function (vp) { + var viewport + + if (Array.isArray(vp)) { + viewport = { + x: vp[0], + y: vp[1], + width: vp[2] - vp[0], + height: vp[3] - vp[1] + } + } + else if (vp) { + viewport = { + x: vp.x || vp.left || 0, + y: vp.y || vp.top || 0 + } + + if (vp.right) { viewport.width = vp.right - viewport.x } + else { viewport.width = vp.w || vp.width || 0 } + + if (vp.bottom) { viewport.height = vp.bottom - viewport.y } + else { viewport.height = vp.h || vp.height || 0 } + } + else { + viewport = { + x: 0, y: 0, + width: gl.drawingBufferWidth, + height: gl.drawingBufferHeight + } + } + + return viewport + } + }]) + + return group + }) + + if (pointCount || errorCount) { + var len = groups.reduce(function (acc, group, i) { + return acc + (group ? group.count : 0) + }, 0) + + var positionData = new Float64Array(len * 2) + var colorData = new Uint8Array(len * 4) + var errorData = new Float32Array(len * 4) + + groups.forEach(function (group, i) { + if (!group) { return } + var positions = group.positions; + var count = group.count; + var offset = group.offset; + var color = group.color; + var errors = group.errors; + if (!count) { return } + + colorData.set(color, offset * 4) + errorData.set(errors, offset * 4) + positionData.set(positions, offset * 2) + }) + + positionBuffer(float32(positionData)) + positionFractBuffer(fract32(positionData)) + colorBuffer(colorData) + errorBuffer(errorData) + } + + } + + function destroy () { + positionBuffer.destroy() + positionFractBuffer.destroy() + colorBuffer.destroy() + errorBuffer.destroy() + meshBuffer.destroy() + } +} +},{"array-bounds":53,"color-normalize":108,"flatten-vertex-data":216,"object-assign":437,"pick-by-alias":448,"to-float32":515,"update-diff":526}],474:[function(_dereq_,module,exports){ +'use strict' + + +var rgba = _dereq_('color-normalize') +var getBounds = _dereq_('array-bounds') +var extend = _dereq_('object-assign') +var glslify = _dereq_('glslify') +var pick = _dereq_('pick-by-alias') +var flatten = _dereq_('flatten-vertex-data') +var triangulate = _dereq_('earcut') +var normalize = _dereq_('array-normalize') +var ref = _dereq_('to-float32'); +var float32 = ref.float32; +var fract32 = ref.fract32; +var WeakMap = _dereq_('es6-weak-map') +var parseRect = _dereq_('parse-rect') + + +module.exports = Line2D + + +/** @constructor */ +function Line2D (regl, options) { + if (!(this instanceof Line2D)) { return new Line2D(regl, options) } + + if (typeof regl === 'function') { + if (!options) { options = {} } + options.regl = regl + } + else { + options = regl + } + if (options.length) { options.positions = options } + regl = options.regl + + if (!regl.hasExtension('ANGLE_instanced_arrays')) { + throw Error('regl-error2d: `ANGLE_instanced_arrays` extension should be enabled'); + } + + // persistent variables + this.gl = regl._gl + this.regl = regl + + // list of options for lines + this.passes = [] + + // cached shaders instance + this.shaders = Line2D.shaders.has(regl) ? Line2D.shaders.get(regl) : Line2D.shaders.set(regl, Line2D.createShaders(regl)).get(regl) + + + // init defaults + this.update(options) +} + + +Line2D.dashMult = 2 +Line2D.maxPatternLength = 256 +Line2D.precisionThreshold = 3e6 +Line2D.maxPoints = 1e4 +Line2D.maxLines = 2048 + + +// cache of created draw calls per-regl instance +Line2D.shaders = new WeakMap() + + +// create static shaders once +Line2D.createShaders = function (regl) { + var offsetBuffer = regl.buffer({ + usage: 'static', + type: 'float', + data: [0,1, 0,0, 1,1, 1,0] + }) + + var shaderOptions = { + primitive: 'triangle strip', + instances: regl.prop('count'), + count: 4, + offset: 0, + + uniforms: { + miterMode: function (ctx, prop) { return prop.join === 'round' ? 2 : 1; }, + miterLimit: regl.prop('miterLimit'), + scale: regl.prop('scale'), + scaleFract: regl.prop('scaleFract'), + translateFract: regl.prop('translateFract'), + translate: regl.prop('translate'), + thickness: regl.prop('thickness'), + dashPattern: regl.prop('dashTexture'), + opacity: regl.prop('opacity'), + pixelRatio: regl.context('pixelRatio'), + id: regl.prop('id'), + dashSize: regl.prop('dashLength'), + viewport: function (c, p) { return [p.viewport.x, p.viewport.y, c.viewportWidth, c.viewportHeight]; }, + depth: regl.prop('depth') + }, + + blend: { + enable: true, + color: [0,0,0,0], + equation: { + rgb: 'add', + alpha: 'add' + }, + func: { + srcRGB: 'src alpha', + dstRGB: 'one minus src alpha', + srcAlpha: 'one minus dst alpha', + dstAlpha: 'one' + } + }, + depth: { + enable: function (c, p) { + return !p.overlay + } + }, + stencil: {enable: false}, + scissor: { + enable: true, + box: regl.prop('viewport') + }, + viewport: regl.prop('viewport') + } + + + // simplified rectangular line shader + var drawRectLine = regl(extend({ + vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 aCoord, bCoord, aCoordFract, bCoordFract;\nattribute vec4 color;\nattribute float lineEnd, lineTop;\n\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float thickness, pixelRatio, id, depth;\nuniform vec4 viewport;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\n\nvec2 project(vec2 position, vec2 positionFract, vec2 scale, vec2 scaleFract, vec2 translate, vec2 translateFract) {\n\t// the order is important\n\treturn position * scale + translate\n + positionFract * scale + translateFract\n + position * scaleFract\n + positionFract * scaleFract;\n}\n\nvoid main() {\n\tfloat lineStart = 1. - lineEnd;\n\tfloat lineOffset = lineTop * 2. - 1.;\n\n\tvec2 diff = (bCoord + bCoordFract - aCoord - aCoordFract);\n\ttangent = normalize(diff * scale * viewport.zw);\n\tvec2 normal = vec2(-tangent.y, tangent.x);\n\n\tvec2 position = project(aCoord, aCoordFract, scale, scaleFract, translate, translateFract) * lineStart\n\t\t+ project(bCoord, bCoordFract, scale, scaleFract, translate, translateFract) * lineEnd\n\n\t\t+ thickness * normal * .5 * lineOffset / viewport.zw;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tfragColor = color / 255.;\n}\n"]), + frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D dashPattern;\n\nuniform float dashSize, pixelRatio, thickness, opacity, id;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\n\nvoid main() {\n\tfloat alpha = 1.;\n\n\tfloat t = fract(dot(tangent, gl_FragCoord.xy) / dashSize) * .5 + .25;\n\tfloat dash = texture2D(dashPattern, vec2(t, .5)).r;\n\n\tgl_FragColor = fragColor;\n\tgl_FragColor.a *= alpha * opacity * dash;\n}\n"]), + + attributes: { + // if point is at the end of segment + lineEnd: { + buffer: offsetBuffer, + divisor: 0, + stride: 8, + offset: 0 + }, + // if point is at the top of segment + lineTop: { + buffer: offsetBuffer, + divisor: 0, + stride: 8, + offset: 4 + }, + // beginning of line coordinate + aCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 8, + divisor: 1 + }, + // end of line coordinate + bCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 16, + divisor: 1 + }, + aCoordFract: { + buffer: regl.prop('positionFractBuffer'), + stride: 8, + offset: 8, + divisor: 1 + }, + bCoordFract: { + buffer: regl.prop('positionFractBuffer'), + stride: 8, + offset: 16, + divisor: 1 + }, + color: { + buffer: regl.prop('colorBuffer'), + stride: 4, + offset: 0, + divisor: 1 + } + } + }, shaderOptions)) + + // create regl draw + var drawMiterLine + + try { + drawMiterLine = regl(extend({ + // culling removes polygon creasing + cull: { + enable: true, + face: 'back' + }, + + vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 aCoord, bCoord, nextCoord, prevCoord;\nattribute vec4 aColor, bColor;\nattribute float lineEnd, lineTop;\n\nuniform vec2 scale, translate;\nuniform float thickness, pixelRatio, id, depth;\nuniform vec4 viewport;\nuniform float miterLimit, miterMode;\n\nvarying vec4 fragColor;\nvarying vec4 startCutoff, endCutoff;\nvarying vec2 tangent;\nvarying vec2 startCoord, endCoord;\nvarying float enableStartMiter, enableEndMiter;\n\nconst float REVERSE_THRESHOLD = -.875;\nconst float MIN_DIFF = 1e-6;\n\n// TODO: possible optimizations: avoid overcalculating all for vertices and calc just one instead\n// TODO: precalculate dot products, normalize things beforehead etc.\n// TODO: refactor to rectangular algorithm\n\nfloat distToLine(vec2 p, vec2 a, vec2 b) {\n\tvec2 diff = b - a;\n\tvec2 perp = normalize(vec2(-diff.y, diff.x));\n\treturn dot(p - a, perp);\n}\n\nbool isNaN( float val ){\n return ( val < 0.0 || 0.0 < val || val == 0.0 ) ? false : true;\n}\n\nvoid main() {\n\tvec2 aCoord = aCoord, bCoord = bCoord, prevCoord = prevCoord, nextCoord = nextCoord;\n\n vec2 adjustedScale;\n adjustedScale.x = (abs(scale.x) < MIN_DIFF) ? MIN_DIFF : scale.x;\n adjustedScale.y = (abs(scale.y) < MIN_DIFF) ? MIN_DIFF : scale.y;\n\n vec2 scaleRatio = adjustedScale * viewport.zw;\n\tvec2 normalWidth = thickness / scaleRatio;\n\n\tfloat lineStart = 1. - lineEnd;\n\tfloat lineBot = 1. - lineTop;\n\n\tfragColor = (lineStart * aColor + lineEnd * bColor) / 255.;\n\n\tif (isNaN(aCoord.x) || isNaN(aCoord.y) || isNaN(bCoord.x) || isNaN(bCoord.y)) return;\n\n\tif (aCoord == prevCoord) prevCoord = aCoord + normalize(bCoord - aCoord);\n\tif (bCoord == nextCoord) nextCoord = bCoord - normalize(bCoord - aCoord);\n\n\tvec2 prevDiff = aCoord - prevCoord;\n\tvec2 currDiff = bCoord - aCoord;\n\tvec2 nextDiff = nextCoord - bCoord;\n\n\tvec2 prevTangent = normalize(prevDiff * scaleRatio);\n\tvec2 currTangent = normalize(currDiff * scaleRatio);\n\tvec2 nextTangent = normalize(nextDiff * scaleRatio);\n\n\tvec2 prevNormal = vec2(-prevTangent.y, prevTangent.x);\n\tvec2 currNormal = vec2(-currTangent.y, currTangent.x);\n\tvec2 nextNormal = vec2(-nextTangent.y, nextTangent.x);\n\n\tvec2 startJoinDirection = normalize(prevTangent - currTangent);\n\tvec2 endJoinDirection = normalize(currTangent - nextTangent);\n\n\t// collapsed/unidirectional segment cases\n\t// FIXME: there should be more elegant solution\n\tvec2 prevTanDiff = abs(prevTangent - currTangent);\n\tvec2 nextTanDiff = abs(nextTangent - currTangent);\n\tif (max(prevTanDiff.x, prevTanDiff.y) < MIN_DIFF) {\n\t\tstartJoinDirection = currNormal;\n\t}\n\tif (max(nextTanDiff.x, nextTanDiff.y) < MIN_DIFF) {\n\t\tendJoinDirection = currNormal;\n\t}\n\tif (aCoord == bCoord) {\n\t\tendJoinDirection = startJoinDirection;\n\t\tcurrNormal = prevNormal;\n\t\tcurrTangent = prevTangent;\n\t}\n\n\ttangent = currTangent;\n\n\t//calculate join shifts relative to normals\n\tfloat startJoinShift = dot(currNormal, startJoinDirection);\n\tfloat endJoinShift = dot(currNormal, endJoinDirection);\n\n\tfloat startMiterRatio = abs(1. / startJoinShift);\n\tfloat endMiterRatio = abs(1. / endJoinShift);\n\n\tvec2 startJoin = startJoinDirection * startMiterRatio;\n\tvec2 endJoin = endJoinDirection * endMiterRatio;\n\n\tvec2 startTopJoin, startBotJoin, endTopJoin, endBotJoin;\n\tstartTopJoin = sign(startJoinShift) * startJoin * .5;\n\tstartBotJoin = -startTopJoin;\n\n\tendTopJoin = sign(endJoinShift) * endJoin * .5;\n\tendBotJoin = -endTopJoin;\n\n\tvec2 aTopCoord = aCoord + normalWidth * startTopJoin;\n\tvec2 bTopCoord = bCoord + normalWidth * endTopJoin;\n\tvec2 aBotCoord = aCoord + normalWidth * startBotJoin;\n\tvec2 bBotCoord = bCoord + normalWidth * endBotJoin;\n\n\t//miter anti-clipping\n\tfloat baClipping = distToLine(bCoord, aCoord, aBotCoord) / dot(normalize(normalWidth * endBotJoin), normalize(normalWidth.yx * vec2(-startBotJoin.y, startBotJoin.x)));\n\tfloat abClipping = distToLine(aCoord, bCoord, bTopCoord) / dot(normalize(normalWidth * startBotJoin), normalize(normalWidth.yx * vec2(-endBotJoin.y, endBotJoin.x)));\n\n\t//prevent close to reverse direction switch\n\tbool prevReverse = dot(currTangent, prevTangent) <= REVERSE_THRESHOLD && abs(dot(currTangent, prevNormal)) * min(length(prevDiff), length(currDiff)) < length(normalWidth * currNormal);\n\tbool nextReverse = dot(currTangent, nextTangent) <= REVERSE_THRESHOLD && abs(dot(currTangent, nextNormal)) * min(length(nextDiff), length(currDiff)) < length(normalWidth * currNormal);\n\n\tif (prevReverse) {\n\t\t//make join rectangular\n\t\tvec2 miterShift = normalWidth * startJoinDirection * miterLimit * .5;\n\t\tfloat normalAdjust = 1. - min(miterLimit / startMiterRatio, 1.);\n\t\taBotCoord = aCoord + miterShift - normalAdjust * normalWidth * currNormal * .5;\n\t\taTopCoord = aCoord + miterShift + normalAdjust * normalWidth * currNormal * .5;\n\t}\n\telse if (!nextReverse && baClipping > 0. && baClipping < length(normalWidth * endBotJoin)) {\n\t\t//handle miter clipping\n\t\tbTopCoord -= normalWidth * endTopJoin;\n\t\tbTopCoord += normalize(endTopJoin * normalWidth) * baClipping;\n\t}\n\n\tif (nextReverse) {\n\t\t//make join rectangular\n\t\tvec2 miterShift = normalWidth * endJoinDirection * miterLimit * .5;\n\t\tfloat normalAdjust = 1. - min(miterLimit / endMiterRatio, 1.);\n\t\tbBotCoord = bCoord + miterShift - normalAdjust * normalWidth * currNormal * .5;\n\t\tbTopCoord = bCoord + miterShift + normalAdjust * normalWidth * currNormal * .5;\n\t}\n\telse if (!prevReverse && abClipping > 0. && abClipping < length(normalWidth * startBotJoin)) {\n\t\t//handle miter clipping\n\t\taBotCoord -= normalWidth * startBotJoin;\n\t\taBotCoord += normalize(startBotJoin * normalWidth) * abClipping;\n\t}\n\n\tvec2 aTopPosition = (aTopCoord) * adjustedScale + translate;\n\tvec2 aBotPosition = (aBotCoord) * adjustedScale + translate;\n\n\tvec2 bTopPosition = (bTopCoord) * adjustedScale + translate;\n\tvec2 bBotPosition = (bBotCoord) * adjustedScale + translate;\n\n\t//position is normalized 0..1 coord on the screen\n\tvec2 position = (aTopPosition * lineTop + aBotPosition * lineBot) * lineStart + (bTopPosition * lineTop + bBotPosition * lineBot) * lineEnd;\n\n\tstartCoord = aCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\tendCoord = bCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tenableStartMiter = step(dot(currTangent, prevTangent), .5);\n\tenableEndMiter = step(dot(currTangent, nextTangent), .5);\n\n\t//bevel miter cutoffs\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * miterLimit * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * miterLimit * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n\n\t//round miter cutoffs\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * abs(dot(startJoinDirection, currNormal)) * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * abs(dot(endJoinDirection, currNormal)) * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n}\n"]), + frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D dashPattern;\nuniform float dashSize, pixelRatio, thickness, opacity, id, miterMode;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\nvarying vec4 startCutoff, endCutoff;\nvarying vec2 startCoord, endCoord;\nvarying float enableStartMiter, enableEndMiter;\n\nfloat distToLine(vec2 p, vec2 a, vec2 b) {\n\tvec2 diff = b - a;\n\tvec2 perp = normalize(vec2(-diff.y, diff.x));\n\treturn dot(p - a, perp);\n}\n\nvoid main() {\n\tfloat alpha = 1., distToStart, distToEnd;\n\tfloat cutoff = thickness * .5;\n\n\t//bevel miter\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToStart + 1., 0.), 1.);\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToEnd + 1., 0.), 1.);\n\t\t}\n\t}\n\n\t// round miter\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - startCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - endCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\t}\n\n\tfloat t = fract(dot(tangent, gl_FragCoord.xy) / dashSize) * .5 + .25;\n\tfloat dash = texture2D(dashPattern, vec2(t, .5)).r;\n\n\tgl_FragColor = fragColor;\n\tgl_FragColor.a *= alpha * opacity * dash;\n}\n"]), + + attributes: { + // is line end + lineEnd: { + buffer: offsetBuffer, + divisor: 0, + stride: 8, + offset: 0 + }, + // is line top + lineTop: { + buffer: offsetBuffer, + divisor: 0, + stride: 8, + offset: 4 + }, + // left color + aColor: { + buffer: regl.prop('colorBuffer'), + stride: 4, + offset: 0, + divisor: 1 + }, + // right color + bColor: { + buffer: regl.prop('colorBuffer'), + stride: 4, + offset: 4, + divisor: 1 + }, + prevCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 0, + divisor: 1 + }, + aCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 8, + divisor: 1 + }, + bCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 16, + divisor: 1 + }, + nextCoord: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 24, + divisor: 1 + } + } + }, shaderOptions)) + } catch (e) { + // IE/bad Webkit fallback + drawMiterLine = drawRectLine + } + + // fill shader + var drawFill = regl({ + primitive: 'triangle', + elements: function (ctx, prop) { return prop.triangles; }, + offset: 0, + + vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 position, positionFract;\n\nuniform vec4 color;\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio, id;\nuniform vec4 viewport;\nuniform float opacity;\n\nvarying vec4 fragColor;\n\nconst float MAX_LINES = 256.;\n\nvoid main() {\n\tfloat depth = (MAX_LINES - 4. - id) / (MAX_LINES);\n\n\tvec2 position = position * scale + translate\n + positionFract * scale + translateFract\n + position * scaleFract\n + positionFract * scaleFract;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tfragColor = color / 255.;\n\tfragColor.a *= opacity;\n}\n"]), + frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n\tgl_FragColor = fragColor;\n}\n"]), + + uniforms: { + scale: regl.prop('scale'), + color: regl.prop('fill'), + scaleFract: regl.prop('scaleFract'), + translateFract: regl.prop('translateFract'), + translate: regl.prop('translate'), + opacity: regl.prop('opacity'), + pixelRatio: regl.context('pixelRatio'), + id: regl.prop('id'), + viewport: function (ctx, prop) { return [prop.viewport.x, prop.viewport.y, ctx.viewportWidth, ctx.viewportHeight]; } + }, + + attributes: { + position: { + buffer: regl.prop('positionBuffer'), + stride: 8, + offset: 8 + }, + positionFract: { + buffer: regl.prop('positionFractBuffer'), + stride: 8, + offset: 8 + } + }, + + blend: shaderOptions.blend, + + depth: { enable: false }, + scissor: shaderOptions.scissor, + stencil: shaderOptions.stencil, + viewport: shaderOptions.viewport + }) + + return { + fill: drawFill, rect: drawRectLine, miter: drawMiterLine + } +} + + +// used to for new lines instances +Line2D.defaults = { + dashes: null, + join: 'miter', + miterLimit: 1, + thickness: 10, + cap: 'square', + color: 'black', + opacity: 1, + overlay: false, + viewport: null, + range: null, + close: false, + fill: null +} + + +Line2D.prototype.render = function () { + var ref; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + if (args.length) { + (ref = this).update.apply(ref, args) + } + + this.draw() +} + + +Line2D.prototype.draw = function () { + var this$1 = this; + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + // render multiple polylines via regl batch + (args.length ? args : this.passes).forEach(function (s, i) { + var ref; + + // render array pass as a list of passes + if (s && Array.isArray(s)) { return (ref = this$1).draw.apply(ref, s) } + + if (typeof s === 'number') { s = this$1.passes[s] } + + if (!(s && s.count > 1 && s.opacity)) { return } + + this$1.regl._refresh() + + if (s.fill && s.triangles && s.triangles.length > 2) { + this$1.shaders.fill(s) + } + + if (!s.thickness) { return } + + // high scale is only available for rect mode with precision + if (s.scale[0] * s.viewport.width > Line2D.precisionThreshold || s.scale[1] * s.viewport.height > Line2D.precisionThreshold) { + this$1.shaders.rect(s) + } + + // thin this.passes or too many points are rendered as simplified rect shader + else if (s.join === 'rect' || (!s.join && (s.thickness <= 2 || s.count >= Line2D.maxPoints))) { + this$1.shaders.rect(s) + } + else { + this$1.shaders.miter(s) + } + }) + + return this +} + +Line2D.prototype.update = function (options) { + var this$1 = this; + + if (!options) { return } + + if (options.length != null) { + if (typeof options[0] === 'number') { options = [{positions: options}] } + } + + // make options a batch + else if (!Array.isArray(options)) { options = [options] } + + var ref = this; + var regl = ref.regl; + var gl = ref.gl; + + // process per-line settings + options.forEach(function (o, i) { + var state = this$1.passes[i] + + if (o === undefined) { return } + + // null-argument removes pass + if (o === null) { + this$1.passes[i] = null + return + } + + if (typeof o[0] === 'number') { o = {positions: o} } + + // handle aliases + o = pick(o, { + positions: 'positions points data coords', + thickness: 'thickness lineWidth lineWidths line-width linewidth width stroke-width strokewidth strokeWidth', + join: 'lineJoin linejoin join type mode', + miterLimit: 'miterlimit miterLimit', + dashes: 'dash dashes dasharray dash-array dashArray', + color: 'color colour stroke colors colours stroke-color strokeColor', + fill: 'fill fill-color fillColor', + opacity: 'alpha opacity', + overlay: 'overlay crease overlap intersect', + close: 'closed close closed-path closePath', + range: 'range dataBox', + viewport: 'viewport viewBox', + hole: 'holes hole hollow' + }) + + // init state + if (!state) { + this$1.passes[i] = state = { + id: i, + scale: null, + scaleFract: null, + translate: null, + translateFract: null, + count: 0, + hole: [], + depth: 0, + + dashLength: 1, + dashTexture: regl.texture({ + channels: 1, + data: new Uint8Array([255]), + width: 1, + height: 1, + mag: 'linear', + min: 'linear' + }), + + colorBuffer: regl.buffer({ + usage: 'dynamic', + type: 'uint8', + data: new Uint8Array() + }), + positionBuffer: regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array() + }), + positionFractBuffer: regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array() + }) + } + + o = extend({}, Line2D.defaults, o) + } + if (o.thickness != null) { state.thickness = parseFloat(o.thickness) } + if (o.opacity != null) { state.opacity = parseFloat(o.opacity) } + if (o.miterLimit != null) { state.miterLimit = parseFloat(o.miterLimit) } + if (o.overlay != null) { + state.overlay = !!o.overlay + if (i < Line2D.maxLines) { + state.depth = 2 * (Line2D.maxLines - 1 - i % Line2D.maxLines) / Line2D.maxLines - 1.; + } + } + if (o.join != null) { state.join = o.join } + if (o.hole != null) { state.hole = o.hole } + if (o.fill != null) { state.fill = !o.fill ? null : rgba(o.fill, 'uint8') } + if (o.viewport != null) { state.viewport = parseRect(o.viewport) } + + if (!state.viewport) { + state.viewport = parseRect([ + gl.drawingBufferWidth, + gl.drawingBufferHeight + ]) + } + + if (o.close != null) { state.close = o.close } + + // reset positions + if (o.positions === null) { o.positions = [] } + if (o.positions) { + var positions, count + + // if positions are an object with x/y + if (o.positions.x && o.positions.y) { + var xPos = o.positions.x + var yPos = o.positions.y + count = state.count = Math.max( + xPos.length, + yPos.length + ) + positions = new Float64Array(count * 2) + for (var i$1 = 0; i$1 < count; i$1++) { + positions[i$1 * 2] = xPos[i$1] + positions[i$1 * 2 + 1] = yPos[i$1] + } + } + else { + positions = flatten(o.positions, 'float64') + count = state.count = Math.floor(positions.length / 2) + } + + var bounds = state.bounds = getBounds(positions, 2) + + // create fill positions + // FIXME: fill positions can be set only along with positions + if (state.fill) { + var pos = [] + + // filter bad vertices and remap triangles to ensure shape + var ids = {} + var lastId = 0 + + for (var i$2 = 0, ptr = 0, l = state.count; i$2 < l; i$2++) { + var x = positions[i$2*2] + var y = positions[i$2*2 + 1] + if (isNaN(x) || isNaN(y) || x == null || y == null) { + x = positions[lastId*2] + y = positions[lastId*2 + 1] + ids[i$2] = lastId + } + else { + lastId = i$2 + } + pos[ptr++] = x + pos[ptr++] = y + } + + var triangles = triangulate(pos, state.hole || []) + + for (var i$3 = 0, l$1 = triangles.length; i$3 < l$1; i$3++) { + if (ids[triangles[i$3]] != null) { triangles[i$3] = ids[triangles[i$3]] } + } + + state.triangles = triangles + } + + // update position buffers + var npos = new Float64Array(positions) + normalize(npos, 2, bounds) + + var positionData = new Float64Array(count * 2 + 6) + + // rotate first segment join + if (state.close) { + if (positions[0] === positions[count*2 - 2] && + positions[1] === positions[count*2 - 1]) { + positionData[0] = npos[count*2 - 4] + positionData[1] = npos[count*2 - 3] + } + else { + positionData[0] = npos[count*2 - 2] + positionData[1] = npos[count*2 - 1] + } + } + else { + positionData[0] = npos[0] + positionData[1] = npos[1] + } + + positionData.set(npos, 2) + + // add last segment + if (state.close) { + // ignore coinciding start/end + if (positions[0] === positions[count*2 - 2] && + positions[1] === positions[count*2 - 1]) { + positionData[count*2 + 2] = npos[2] + positionData[count*2 + 3] = npos[3] + state.count -= 1 + } + else { + positionData[count*2 + 2] = npos[0] + positionData[count*2 + 3] = npos[1] + positionData[count*2 + 4] = npos[2] + positionData[count*2 + 5] = npos[3] + } + } + // add stub + else { + positionData[count*2 + 2] = npos[count*2 - 2] + positionData[count*2 + 3] = npos[count*2 - 1] + positionData[count*2 + 4] = npos[count*2 - 2] + positionData[count*2 + 5] = npos[count*2 - 1] + } + + state.positionBuffer(float32(positionData)) + state.positionFractBuffer(fract32(positionData)) + } + + if (o.range) { + state.range = o.range + } else if (!state.range) { + state.range = state.bounds + } + + if ((o.range || o.positions) && state.count) { + var bounds$1 = state.bounds + + var boundsW = bounds$1[2] - bounds$1[0], + boundsH = bounds$1[3] - bounds$1[1] + + var rangeW = state.range[2] - state.range[0], + rangeH = state.range[3] - state.range[1] + + state.scale = [ + boundsW / rangeW, + boundsH / rangeH + ] + state.translate = [ + -state.range[0] / rangeW + bounds$1[0] / rangeW || 0, + -state.range[1] / rangeH + bounds$1[1] / rangeH || 0 + ] + + state.scaleFract = fract32(state.scale) + state.translateFract = fract32(state.translate) + } + + if (o.dashes) { + var dashLength = 0., dashData + + if (!o.dashes || o.dashes.length < 2) { + dashLength = 1. + dashData = new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255]) + } + + else { + dashLength = 0.; + for(var i$4 = 0; i$4 < o.dashes.length; ++i$4) { + dashLength += o.dashes[i$4] + } + dashData = new Uint8Array(dashLength * Line2D.dashMult) + var ptr$1 = 0 + var fillColor = 255 + + // repeat texture two times to provide smooth 0-step + for (var k = 0; k < 2; k++) { + for(var i$5 = 0; i$5 < o.dashes.length; ++i$5) { + for(var j = 0, l$2 = o.dashes[i$5] * Line2D.dashMult * .5; j < l$2; ++j) { + dashData[ptr$1++] = fillColor + } + fillColor ^= 255 + } + } + } + + state.dashLength = dashLength + state.dashTexture({ + channels: 1, + data: dashData, + width: dashData.length, + height: 1, + mag: 'linear', + min: 'linear' + }, 0, 0) + } + + if (o.color) { + var count$1 = state.count + var colors = o.color + + if (!colors) { colors = 'transparent' } + + var colorData = new Uint8Array(count$1 * 4 + 4) + + // convert colors to typed arrays + if (!Array.isArray(colors) || typeof colors[0] === 'number') { + var c = rgba(colors, 'uint8') + + for (var i$6 = 0; i$6 < count$1 + 1; i$6++) { + colorData.set(c, i$6 * 4) + } + } else { + for (var i$7 = 0; i$7 < count$1; i$7++) { + var c$1 = rgba(colors[i$7], 'uint8') + colorData.set(c$1, i$7 * 4) + } + colorData.set(rgba(colors[0], 'uint8'), count$1 * 4) + } + + state.colorBuffer({ + usage: 'dynamic', + type: 'uint8', + data: colorData + }) + } + }) + + // remove unmentioned passes + if (options.length < this.passes.length) { + for (var i = options.length; i < this.passes.length; i++) { + var pass = this$1.passes[i] + if (!pass) { continue } + pass.colorBuffer.destroy() + pass.positionBuffer.destroy() + pass.dashTexture.destroy() + } + this.passes.length = options.length + } + + // remove null items + var passes = [] + for (var i$1 = 0; i$1 < this.passes.length; i$1++) { + if (this$1.passes[i$1] !== null) { passes.push(this$1.passes[i$1]) } + } + this.passes = passes + + return this +} + +Line2D.prototype.destroy = function () { + this.passes.forEach(function (pass) { + pass.colorBuffer.destroy() + pass.positionBuffer.destroy() + pass.dashTexture.destroy() + }) + + this.passes.length = 0 + + return this +} + +},{"array-bounds":53,"array-normalize":54,"color-normalize":108,"earcut":156,"es6-weak-map":209,"flatten-vertex-data":216,"glslify":392,"object-assign":437,"parse-rect":442,"pick-by-alias":448,"to-float32":515}],475:[function(_dereq_,module,exports){ +'use strict' + +var Scatter = _dereq_('./scatter') +var extend = _dereq_('object-assign') + +module.exports = function (regl, options) { + var scatter = new Scatter(regl, options) + + var render = scatter.render.bind(scatter) + + // expose API + extend(render, { + render: render, + update: scatter.update.bind(scatter), + draw: scatter.draw.bind(scatter), + destroy: scatter.destroy.bind(scatter), + regl: scatter.regl, + gl: scatter.gl, + canvas: scatter.gl.canvas, + groups: scatter.groups, + markers: scatter.markerCache, + palette: scatter.palette + }) + + return render +} +},{"./scatter":476,"object-assign":437}],476:[function(_dereq_,module,exports){ +'use strict' + +var rgba = _dereq_('color-normalize') +var getBounds = _dereq_('array-bounds') +var colorId = _dereq_('color-id') +var cluster = _dereq_('point-cluster') +var extend = _dereq_('object-assign') +var glslify = _dereq_('glslify') +var pick = _dereq_('pick-by-alias') +var updateDiff = _dereq_('update-diff') +var flatten = _dereq_('flatten-vertex-data') +var ie = _dereq_('is-iexplorer') +var f32 = _dereq_('to-float32') +var parseRect = _dereq_('parse-rect') + + +module.exports = Scatter + + +function Scatter (regl, options) { + var this$1 = this; + + if (!(this instanceof Scatter)) { return new Scatter(regl, options) } + + if (typeof regl === 'function') { + if (!options) { options = {} } + options.regl = regl + } + else { + options = regl + regl = null + } + + if (options && options.length) { options.positions = options } + + regl = options.regl + + // persistent variables + var gl = regl._gl, paletteTexture, palette = [], paletteIds = {}, + + // state + groups = [], + + // textures for marker keys + markerTextures = [null], + markerCache = [null] + + var maxColors = 255, maxSize = 100 + + // direct color buffer mode + // IE does not support palette anyways + this.tooManyColors = ie + + // texture with color palette + paletteTexture = regl.texture({ + data: new Uint8Array(maxColors * 4), + width: maxColors, + height: 1, + type: 'uint8', + format: 'rgba', + wrapS: 'clamp', + wrapT: 'clamp', + mag: 'nearest', + min: 'nearest' + }) + + extend(this, { + regl: regl, + gl: gl, + groups: groups, + markerCache: markerCache, + markerTextures: markerTextures, + palette: palette, + paletteIds: paletteIds, + paletteTexture: paletteTexture, + maxColors: maxColors, + maxSize: maxSize, + canvas: gl.canvas + }) + + this.update(options) + + // common shader options + var shaderOptions = { + uniforms: { + pixelRatio: regl.context('pixelRatio'), + palette: paletteTexture, + paletteSize: function (ctx, prop) { return [this$1.tooManyColors ? 0 : maxColors, paletteTexture.height]; }, + scale: regl.prop('scale'), + scaleFract: regl.prop('scaleFract'), + translate: regl.prop('translate'), + translateFract: regl.prop('translateFract'), + opacity: regl.prop('opacity'), + marker: regl.prop('markerTexture'), + }, + + attributes: { + // FIXME: optimize these parts + x: function (ctx, prop) { return prop.xAttr || { + buffer: prop.positionBuffer, + stride: 8, + offset: 0 + }; }, + y: function (ctx, prop) { return prop.yAttr || { + buffer: prop.positionBuffer, + stride: 8, + offset: 4 + }; }, + xFract: function (ctx, prop) { return prop.xAttr ? { constant: [0, 0] } : { + buffer: prop.positionFractBuffer, + stride: 8, + offset: 0 + }; }, + yFract: function (ctx, prop) { return prop.yAttr ? { constant: [0, 0] } : { + buffer: prop.positionFractBuffer, + stride: 8, + offset: 4 + }; }, + size: function (ctx, prop) { return prop.size.length ? { + buffer: prop.sizeBuffer, + stride: 2, + offset: 0 + } : { + constant: [ Math.round(prop.size * 255 / this$1.maxSize) ] + }; }, + borderSize: function (ctx, prop) { return prop.borderSize.length ? { + buffer: prop.sizeBuffer, + stride: 2, + offset: 1 + } : { + constant: [ Math.round(prop.borderSize * 255 / this$1.maxSize) ] + }; }, + colorId: function (ctx, prop) { return prop.color.length ? { + buffer: prop.colorBuffer, + stride: this$1.tooManyColors ? 8 : 4, + offset: 0 + } : { + constant: this$1.tooManyColors ? palette.slice(prop.color * 4, prop.color * 4 + 4) : [ prop.color ] + }; }, + borderColorId: function (ctx, prop) { return prop.borderColor.length ? { + buffer: prop.colorBuffer, + stride: this$1.tooManyColors ? 8 : 4, + offset: this$1.tooManyColors ? 4 : 2 + } : { + constant: this$1.tooManyColors ? palette.slice(prop.borderColor * 4, prop.borderColor * 4 + 4) : [ prop.borderColor ] + }; }, + isActive: function (ctx, prop) { return prop.activation === true ? { constant: [1] } : prop.activation ? prop.activation : { constant: [0] }; } + }, + + blend: { + enable: true, + color: [0,0,0,1], + + // photoshop blending + func: { + srcRGB: 'src alpha', + dstRGB: 'one minus src alpha', + srcAlpha: 'one minus dst alpha', + dstAlpha: 'one' + } + }, + + scissor: { + enable: true, + box: regl.prop('viewport') + }, + viewport: regl.prop('viewport'), + + stencil: {enable: false}, + depth: {enable: false}, + + elements: regl.prop('elements'), + count: regl.prop('count'), + offset: regl.prop('offset'), + + primitive: 'points' + } + + // draw sdf-marker + var markerOptions = extend({}, shaderOptions) + markerOptions.frag = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragWidth, fragBorderColorLevel, fragColorLevel;\n\nuniform sampler2D marker;\nuniform float pixelRatio, opacity;\n\nfloat smoothStep(float x, float y) {\n return 1.0 / (1.0 + exp(50.0*(x - y)));\n}\n\nvoid main() {\n float dist = texture2D(marker, gl_PointCoord).r, delta = fragWidth;\n\n // max-distance alpha\n if (dist < 0.003) discard;\n\n // null-border case\n if (fragBorderColorLevel == fragColorLevel || fragBorderColor.a == 0.) {\n float colorAmt = smoothstep(.5 - delta, .5 + delta, dist);\n gl_FragColor = vec4(fragColor.rgb, colorAmt * fragColor.a * opacity);\n }\n else {\n float borderColorAmt = smoothstep(fragBorderColorLevel - delta, fragBorderColorLevel + delta, dist);\n float colorAmt = smoothstep(fragColorLevel - delta, fragColorLevel + delta, dist);\n\n vec4 color = fragBorderColor;\n color.a *= borderColorAmt;\n color = mix(color, fragColor, colorAmt);\n color.a *= opacity;\n\n gl_FragColor = color;\n }\n\n}\n"]) + markerOptions.vert = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute float x, y, xFract, yFract;\nattribute float size, borderSize;\nattribute vec4 colorId, borderColorId;\nattribute float isActive;\n\nuniform vec2 scale, scaleFract, translate, translateFract, paletteSize;\nuniform float pixelRatio;\nuniform sampler2D palette;\n\nconst float maxSize = 100.;\nconst float borderLevel = .5;\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragPointSize, fragBorderRadius,\n fragWidth, fragBorderColorLevel, fragColorLevel;\n\nvec2 paletteCoord(float id) {\n return vec2(\n (mod(id, paletteSize.x) + .5) / paletteSize.x,\n (floor(id / paletteSize.x) + .5) / paletteSize.y\n );\n}\nvec2 paletteCoord(vec2 id) {\n return vec2(\n (id.x + .5) / paletteSize.x,\n (id.y + .5) / paletteSize.y\n );\n}\nvec4 getColor(vec4 id) {\n // zero-palette means we deal with direct buffer\n if (paletteSize.x == 0.) return id / 255.;\n return texture2D(palette, paletteCoord(id.xy));\n}\n\nvoid main() {\n if (isActive == 0.) return;\n\n vec2 position = vec2(x, y);\n vec2 positionFract = vec2(xFract, yFract);\n\n vec4 color = getColor(colorId);\n vec4 borderColor = getColor(borderColorId);\n\n float size = size * maxSize / 255.;\n float borderSize = borderSize * maxSize / 255.;\n\n gl_PointSize = 2. * size * pixelRatio;\n fragPointSize = size * pixelRatio;\n\n vec2 pos = (position + translate) * scale\n + (positionFract + translateFract) * scale\n + (position + translate) * scaleFract\n + (positionFract + translateFract) * scaleFract;\n\n gl_Position = vec4(pos * 2. - 1., 0, 1);\n\n fragColor = color;\n fragBorderColor = borderColor;\n fragWidth = 1. / gl_PointSize;\n\n fragBorderColorLevel = clamp(borderLevel - borderLevel * borderSize / size, 0., 1.);\n fragColorLevel = clamp(borderLevel + (1. - borderLevel) * borderSize / size, 0., 1.);\n}\n"]) + + this.drawMarker = regl(markerOptions) + + // draw circle + var circleOptions = extend({}, shaderOptions) + circleOptions.frag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor, fragBorderColor;\n\nuniform float opacity;\nvarying float fragBorderRadius, fragWidth;\n\nfloat smoothStep(float edge0, float edge1, float x) {\n\tfloat t;\n\tt = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n\treturn t * t * (3.0 - 2.0 * t);\n}\n\nvoid main() {\n\tfloat radius, alpha = 1.0, delta = fragWidth;\n\n\tradius = length(2.0 * gl_PointCoord.xy - 1.0);\n\n\tif (radius > 1.0 + delta) {\n\t\tdiscard;\n\t}\n\n\talpha -= smoothstep(1.0 - delta, 1.0 + delta, radius);\n\n\tfloat borderRadius = fragBorderRadius;\n\tfloat ratio = smoothstep(borderRadius - delta, borderRadius + delta, radius);\n\tvec4 color = mix(fragColor, fragBorderColor, ratio);\n\tcolor.a *= alpha * opacity;\n\tgl_FragColor = color;\n}\n"]) + circleOptions.vert = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute float x, y, xFract, yFract;\nattribute float size, borderSize;\nattribute vec4 colorId, borderColorId;\nattribute float isActive;\n\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio;\nuniform sampler2D palette;\nuniform vec2 paletteSize;\n\nconst float maxSize = 100.;\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragBorderRadius, fragWidth;\n\nvec2 paletteCoord(float id) {\n return vec2(\n (mod(id, paletteSize.x) + .5) / paletteSize.x,\n (floor(id / paletteSize.x) + .5) / paletteSize.y\n );\n}\nvec2 paletteCoord(vec2 id) {\n return vec2(\n (id.x + .5) / paletteSize.x,\n (id.y + .5) / paletteSize.y\n );\n}\n\nvec4 getColor(vec4 id) {\n // zero-palette means we deal with direct buffer\n if (paletteSize.x == 0.) return id / 255.;\n return texture2D(palette, paletteCoord(id.xy));\n}\n\nvoid main() {\n // ignore inactive points\n if (isActive == 0.) return;\n\n vec2 position = vec2(x, y);\n vec2 positionFract = vec2(xFract, yFract);\n\n vec4 color = getColor(colorId);\n vec4 borderColor = getColor(borderColorId);\n\n float size = size * maxSize / 255.;\n float borderSize = borderSize * maxSize / 255.;\n\n gl_PointSize = (size + borderSize) * pixelRatio;\n\n vec2 pos = (position + translate) * scale\n + (positionFract + translateFract) * scale\n + (position + translate) * scaleFract\n + (positionFract + translateFract) * scaleFract;\n\n gl_Position = vec4(pos * 2. - 1., 0, 1);\n\n fragBorderRadius = 1. - 2. * borderSize / (size + borderSize);\n fragColor = color;\n fragBorderColor = borderColor.a == 0. || borderSize == 0. ? vec4(color.rgb, 0.) : borderColor;\n fragWidth = 1. / gl_PointSize;\n}\n"]) + + // polyfill IE + if (ie) { + circleOptions.frag = circleOptions.frag.replace('smoothstep', 'smoothStep') + markerOptions.frag = markerOptions.frag.replace('smoothstep', 'smoothStep') + } + + this.drawCircle = regl(circleOptions) +} + +// single pass defaults +Scatter.defaults = { + color: 'black', + borderColor: 'transparent', + borderSize: 0, + size: 12, + opacity: 1, + marker: undefined, + viewport: null, + range: null, + pixelSize: null, + count: 0, + offset: 0, + bounds: null, + positions: [], + snap: 1e4 +} + + +// update & redraw +Scatter.prototype.render = function () { + var ref; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + if (args.length) { + (ref = this).update.apply(ref, args) + } + + this.draw() + + return this +} + + +// draw all groups or only indicated ones +Scatter.prototype.draw = function () { + var this$1 = this; + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = this; + var groups = ref.groups; + + // if directly array passed - treat as passes + if (args.length === 1 && Array.isArray(args[0]) && (args[0][0] === null || Array.isArray(args[0][0]))) { + args = args[0] + } + + // FIXME: remove once https://github.com/regl-project/regl/issues/474 resolved + this.regl._refresh() + + if (args.length) { + for (var i = 0; i < args.length; i++) { + this$1.drawItem(i, args[i]) + } + } + // draw all passes + else { + groups.forEach(function (group, i) { + this$1.drawItem(i) + }) + } + + return this +} + +// draw specific scatter group +Scatter.prototype.drawItem = function (id, els) { + var this$1 = this; + + var ref = this; + var groups = ref.groups; + var group = groups[id] + + // debug viewport + // let { viewport } = group + // gl.enable(gl.SCISSOR_TEST); + // gl.scissor(viewport.x, viewport.y, viewport.width, viewport.height); + // gl.clearColor(0, 0, 0, .5); + // gl.clear(gl.COLOR_BUFFER_BIT); + + if (typeof els === 'number') { + id = els + group = groups[els] + els = null + } + + if (!(group && group.count && group.opacity)) { return } + + // draw circles + if (group.activation[0]) { + // TODO: optimize this performance by making groups and regl.this props + this.drawCircle(this.getMarkerDrawOptions(0, group, els)) + } + + // draw all other available markers + var batch = [] + + for (var i = 1; i < group.activation.length; i++) { + if (!group.activation[i] || (group.activation[i] !== true && !group.activation[i].data.length)) { continue } + + batch.push.apply(batch, this$1.getMarkerDrawOptions(i, group, els)) + } + + if (batch.length) { + this.drawMarker(batch) + } +} + +// get options for the marker ids +Scatter.prototype.getMarkerDrawOptions = function(markerId, group, elements) { + var this$1 = this; + + var range = group.range; + var tree = group.tree; + var viewport = group.viewport; + var activation = group.activation; + var selectionBuffer = group.selectionBuffer; + var count = group.count; + var ref = this; + var regl = ref.regl; + + // direct points + if (!tree) { + // if elements array - draw unclustered points + if (elements) { + return [extend({}, group, { + markerTexture: this.markerTextures[markerId], + activation: activation[markerId], + count: elements.length, + elements: elements, + offset: 0 + })] + } + + return [ extend({}, group, { + markerTexture: this.markerTextures[markerId], + activation: activation[markerId], + offset: 0 + }) ] + } + + // clustered points + var batch = [] + + var lod = tree.range(range, { lod: true, px: [ + (range[2] - range[0]) / viewport.width, + (range[3] - range[1]) / viewport.height + ]}) + + // enable elements by using selection buffer + if (elements) { + var markerActivation = activation[markerId] + var mask = markerActivation.data + var data = new Uint8Array(count) + for (var i = 0; i < elements.length; i++) { + var id = elements[i] + data[id] = mask ? mask[id] : 1 + } + selectionBuffer.subdata(data) + } + + for (var l = lod.length; l--;) { + var ref$1 = lod[l]; + var from = ref$1[0]; + var to = ref$1[1]; + + batch.push(extend({}, group, { + markerTexture: this$1.markerTextures[markerId], + activation: elements ? selectionBuffer : activation[markerId], + offset: from, + count: to - from + })) + } + + return batch +} + +// update groups options +Scatter.prototype.update = function () { + var this$1 = this; + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (!args.length) { return } + + // passes are as single array + if (args.length === 1 && Array.isArray(args[0])) { args = args[0] } + + var ref = this; + var groups = ref.groups; + var gl = ref.gl; + var regl = ref.regl; + var maxSize = ref.maxSize; + var maxColors = ref.maxColors; + var palette = ref.palette; + + this.groups = groups = args.map(function (options, i) { + var group = groups[i] + + if (options === undefined) { return group } + + if (options === null) { options = { positions: null } } + else if (typeof options === 'function') { options = { ondraw: options } } + else if (typeof options[0] === 'number') { options = { positions: options } } + + // copy options to avoid mutation & handle aliases + options = pick(options, { + positions: 'positions data points', + snap: 'snap cluster lod tree', + size: 'sizes size radius', + borderSize: 'borderSizes borderSize border-size bordersize borderWidth borderWidths border-width borderwidth stroke-width strokeWidth strokewidth outline', + color: 'colors color fill fill-color fillColor', + borderColor: 'borderColors borderColor stroke stroke-color strokeColor', + marker: 'markers marker shape', + range: 'range dataBox databox', + viewport: 'viewport viewPort viewBox viewbox', + opacity: 'opacity alpha transparency', + bounds: 'bound bounds boundaries limits' + }) + + if (options.positions === null) { options.positions = [] } + + if (!group) { + groups[i] = group = { + id: i, + scale: null, + translate: null, + scaleFract: null, + translateFract: null, + + // buffers for active markers + activation: [], + + // buffer for filtered markers + selectionBuffer: regl.buffer({ + data: new Uint8Array(0), + usage: 'stream', + type: 'uint8' + }), + + // buffers with data: it is faster to switch them per-pass + // than provide one congregate buffer + sizeBuffer: regl.buffer({ + data: new Uint8Array(0), + usage: 'dynamic', + type: 'uint8' + }), + colorBuffer: regl.buffer({ + data: new Uint8Array(0), + usage: 'dynamic', + type: 'uint8' + }), + positionBuffer: regl.buffer({ + data: new Uint8Array(0), + usage: 'dynamic', + type: 'float' + }), + positionFractBuffer: regl.buffer({ + data: new Uint8Array(0), + usage: 'dynamic', + type: 'float' + }) + } + options = extend({}, Scatter.defaults, options) + } + + // force update triggers + if (options.positions && !('marker' in options)) { + options.marker = group.marker + delete group.marker + } + + // updating markers cause recalculating snapping + if (options.marker && !('positions' in options)) { + options.positions = group.positions + delete group.positions + } + + // global count of points + var hasSize = 0, hasColor = 0 + + updateDiff(group, options, [{ + snap: true, + size: function (s, group) { + if (s == null) { s = Scatter.defaults.size } + hasSize += s && s.length ? 1 : 0 + return s + }, + borderSize: function (s, group) { + if (s == null) { s = Scatter.defaults.borderSize } + hasSize += s && s.length ? 1 : 0 + return s + }, + opacity: parseFloat, + + // add colors to palette, save references + color: function (c, group) { + if (c == null) { c = Scatter.defaults.color } + c = this$1.updateColor(c) + hasColor++ + return c + }, + borderColor: function (c, group) { + if (c == null) { c = Scatter.defaults.borderColor } + c = this$1.updateColor(c) + hasColor++ + return c + }, + + bounds: function (bounds, group, options) { + if (!('range' in options)) { options.range = null } + return bounds + }, + + positions: function (positions, group, options) { + var snap = group.snap; + var positionBuffer = group.positionBuffer; + var positionFractBuffer = group.positionFractBuffer; + var selectionBuffer = group.selectionBuffer; + + // separate buffers for x/y coordinates + if (positions.x || positions.y) { + if (positions.x.length) { + group.xAttr = { + buffer: regl.buffer(positions.x), + offset: 0, + stride: 4, + count: positions.x.length + } + } + else { + group.xAttr = { + buffer: positions.x.buffer, + offset: positions.x.offset * 4 || 0, + stride: (positions.x.stride || 1) * 4, + count: positions.x.count + } + } + if (positions.y.length) { + group.yAttr = { + buffer: regl.buffer(positions.y), + offset: 0, + stride: 4, + count: positions.y.length + } + } + else { + group.yAttr = { + buffer: positions.y.buffer, + offset: positions.y.offset * 4 || 0, + stride: (positions.y.stride || 1) * 4, + count: positions.y.count + } + } + group.count = Math.max(group.xAttr.count, group.yAttr.count) + + return positions + } + + positions = flatten(positions, 'float64') + + var count = group.count = Math.floor(positions.length / 2) + var bounds = group.bounds = count ? getBounds(positions, 2) : null + + // if range is not provided updated - recalc it + if (!options.range && !group.range) { + delete group.range + options.range = bounds + } + + // reset marker + if (!options.marker && !group.marker) { + delete group.marker; + options.marker = null; + } + + // build cluster tree if required + if (snap && (snap === true || count > snap)) { + group.tree = cluster(positions, { bounds: bounds }) + } + // existing tree instance + else if (snap && snap.length) { + group.tree = snap + } + + if (group.tree) { + var opts = { + primitive: 'points', + usage: 'static', + data: group.tree, + type: 'uint32' + } + if (group.elements) { group.elements(opts) } + else { group.elements = regl.elements(opts) } + } + + // update position buffers + positionBuffer({ + data: f32.float(positions), + usage: 'dynamic' + }) + positionFractBuffer({ + data: f32.fract(positions), + usage: 'dynamic' + }) + + // expand selectionBuffer + selectionBuffer({ + data: new Uint8Array(count), + type: 'uint8', + usage: 'stream' + }) + + return positions + } + }, { + // create marker ids corresponding to known marker textures + marker: function (markers, group, options) { + var activation = group.activation; + + // reset marker elements + activation.forEach(function (buffer) { return buffer && buffer.destroy && buffer.destroy(); }) + activation.length = 0 + + // single sdf marker + if (!markers || typeof markers[0] === 'number') { + var id = this$1.addMarker(markers) + activation[id] = true + } + + // per-point markers use mask buffers to enable markers in vert shader + else { + var markerMasks = [] + + for (var i = 0, l = Math.min(markers.length, group.count); i < l; i++) { + var id$1 = this$1.addMarker(markers[i]) + + if (!markerMasks[id$1]) { markerMasks[id$1] = new Uint8Array(group.count) } + + // enable marker by default + markerMasks[id$1][i] = 1 + } + + for (var id$2 = 0; id$2 < markerMasks.length; id$2++) { + if (!markerMasks[id$2]) { continue } + + var opts = { + data: markerMasks[id$2], + type: 'uint8', + usage: 'static' + } + if (!activation[id$2]) { + activation[id$2] = regl.buffer(opts) + } + else { + activation[id$2](opts) + } + + activation[id$2].data = markerMasks[id$2] + } + } + + return markers + }, + + range: function (range, group, options) { + var bounds = group.bounds + + // FIXME: why do we need this? + if (!bounds) { return } + if (!range) { range = bounds } + + group.scale = [1 / (range[2] - range[0]), 1 / (range[3] - range[1])] + group.translate = [-range[0], -range[1]] + + group.scaleFract = f32.fract(group.scale) + group.translateFract = f32.fract(group.translate) + + return range + }, + + viewport: function (vp) { + var rect = parseRect(vp || [ + gl.drawingBufferWidth, + gl.drawingBufferHeight + ]) + + // normalize viewport to the canvas coordinates + // rect.y = gl.drawingBufferHeight - rect.height - rect.y + + return rect + } + }]) + + // update size buffer, if needed + if (hasSize) { + var count = group.count; + var size = group.size; + var borderSize = group.borderSize; + var sizeBuffer = group.sizeBuffer; + + var sizes = new Uint8Array(count*2) + if (size.length || borderSize.length) { + for (var i$1 = 0; i$1 < count; i$1++) { + // we downscale size to allow for fractions + sizes[i$1*2] = Math.round((size[i$1] == null ? size : size[i$1]) * 255 / maxSize) + sizes[i$1*2 + 1] = Math.round((borderSize[i$1] == null ? borderSize : borderSize[i$1]) * 255 / maxSize) + } + } + sizeBuffer({ + data: sizes, + usage: 'dynamic' + }) + } + + // update color buffer if needed + if (hasColor) { + var count$1 = group.count; + var color = group.color; + var borderColor = group.borderColor; + var colorBuffer = group.colorBuffer; + var colors + + // if too many colors - put colors to buffer directly + if (this$1.tooManyColors) { + if (color.length || borderColor.length) { + colors = new Uint8Array(count$1 * 8) + for (var i$2 = 0; i$2 < count$1; i$2++) { + var colorId = color[i$2] + colors[i$2*8] = palette[colorId*4] + colors[i$2*8 + 1] = palette[colorId*4 + 1] + colors[i$2*8 + 2] = palette[colorId*4 + 2] + colors[i$2*8 + 3] = palette[colorId*4 + 3] + + var borderColorId = borderColor[i$2] + colors[i$2*8 + 4] = palette[borderColorId*4] + colors[i$2*8 + 5] = palette[borderColorId*4 + 1] + colors[i$2*8 + 6] = palette[borderColorId*4 + 2] + colors[i$2*8 + 7] = palette[borderColorId*4 + 3] + } + } + } + + // if limited amount of colors - keep palette color picking + // that saves significant memory + else { + if (color.length || borderColor.length) { + // we need slight data increase by 2 due to vec4 borderId in shader + colors = new Uint8Array(count$1 * 4 + 2) + for (var i$3 = 0; i$3 < count$1; i$3++) { + // put color coords in palette texture + if (color[i$3] != null) { + colors[i$3*4] = color[i$3] % maxColors + colors[i$3*4 + 1] = Math.floor(color[i$3] / maxColors) + } + if (borderColor[i$3] != null) { + colors[i$3*4 + 2] = borderColor[i$3] % maxColors + colors[i$3*4 + 3] = Math.floor(borderColor[i$3] / maxColors) + } + } + } + } + + colorBuffer({ + data: colors || new Uint8Array(0), + type: 'uint8', + usage: 'dynamic' + }) + } + + return group + }) +} + + +// get (and create) marker texture id +Scatter.prototype.addMarker = function (sdf) { + var ref = this; + var markerTextures = ref.markerTextures; + var regl = ref.regl; + var markerCache = ref.markerCache; + + var pos = sdf == null ? 0 : markerCache.indexOf(sdf) + + if (pos >= 0) { return pos } + + // convert sdf to 0..255 range + var distArr + if (sdf instanceof Uint8Array || sdf instanceof Uint8ClampedArray) { + distArr = sdf + } + else { + distArr = new Uint8Array(sdf.length) + for (var i = 0, l = sdf.length; i < l; i++) { + distArr[i] = sdf[i] * 255 + } + } + + var radius = Math.floor(Math.sqrt(distArr.length)) + + pos = markerTextures.length + + markerCache.push(sdf) + markerTextures.push(regl.texture({ + channels: 1, + data: distArr, + radius: radius, + mag: 'linear', + min: 'linear' + })) + + return pos +} + +// register color to palette, return it's index or list of indexes +Scatter.prototype.updateColor = function (colors) { + var ref = this; + var paletteIds = ref.paletteIds; + var palette = ref.palette; + var maxColors = ref.maxColors; + + if (!Array.isArray(colors)) { + colors = [colors] + } + + var idx = [] + + // if color groups - flatten them + if (typeof colors[0] === 'number') { + var grouped = [] + + if (Array.isArray(colors)) { + for (var i = 0; i < colors.length; i+=4) { + grouped.push(colors.slice(i, i+4)) + } + } + else { + for (var i$1 = 0; i$1 < colors.length; i$1+=4) { + grouped.push(colors.subarray(i$1, i$1+4)) + } + } + + colors = grouped + } + + for (var i$2 = 0; i$2 < colors.length; i$2++) { + var color = colors[i$2] + + color = rgba(color, 'uint8') + + var id = colorId(color, false) + + // if new color - save it + if (paletteIds[id] == null) { + var pos = palette.length + paletteIds[id] = Math.floor(pos / 4) + palette[pos] = color[0] + palette[pos+1] = color[1] + palette[pos+2] = color[2] + palette[pos+3] = color[3] + } + + idx[i$2] = paletteIds[id] + } + + // detect if too many colors in palette + if (!this.tooManyColors && palette.length > maxColors * maxColors * 4) { this.tooManyColors = true } + + // limit max color + this.updatePalette(palette) + + // keep static index for single-color property + return idx.length === 1 ? idx[0] : idx +} + +Scatter.prototype.updatePalette = function (palette) { + if (this.tooManyColors) { return } + + var ref = this; + var maxColors = ref.maxColors; + var paletteTexture = ref.paletteTexture; + + var requiredHeight = Math.ceil(palette.length * .25 / maxColors) + + // pad data + if (requiredHeight > 1) { + palette = palette.slice() + for (var i = (palette.length * .25) % maxColors; i < requiredHeight * maxColors; i++) { + palette.push(0, 0, 0, 0) + } + } + + // ensure height + if (paletteTexture.height < requiredHeight) { + paletteTexture.resize(maxColors, requiredHeight) + } + + // update full data + paletteTexture.subimage({ + width: Math.min(palette.length * .25, maxColors), + height: requiredHeight, + data: palette + }, 0, 0) +} + +// remove unused stuff +Scatter.prototype.destroy = function () { + this.groups.forEach(function (group) { + group.sizeBuffer.destroy() + group.positionBuffer.destroy() + group.positionFractBuffer.destroy() + group.colorBuffer.destroy() + group.activation.forEach(function (b) { return b && b.destroy && b.destroy(); }) + group.selectionBuffer.destroy() + + if (group.elements) { group.elements.destroy() } + }) + this.groups.length = 0 + + this.paletteTexture.destroy() + + this.markerTextures.forEach(function (txt) { return txt && txt.destroy && txt.destroy(); }) + + return this +} +},{"array-bounds":53,"color-id":106,"color-normalize":108,"flatten-vertex-data":216,"glslify":392,"is-iexplorer":402,"object-assign":437,"parse-rect":442,"pick-by-alias":448,"point-cluster":452,"to-float32":515,"update-diff":526}],477:[function(_dereq_,module,exports){ +'use strict' + + +var createScatter = _dereq_('regl-scatter2d/scatter') +var pick = _dereq_('pick-by-alias') +var getBounds = _dereq_('array-bounds') +var raf = _dereq_('raf') +var arrRange = _dereq_('array-range') +var rect = _dereq_('parse-rect') +var flatten = _dereq_('flatten-vertex-data') + + +module.exports = SPLOM + + +// @constructor +function SPLOM (regl, options) { + if (!(this instanceof SPLOM)) { return new SPLOM(regl, options) } + + // render passes + this.traces = [] + + // passes for scatter, combined across traces + this.passes = {} + + this.regl = regl + + // main scatter drawing instance + this.scatter = createScatter(regl) + + this.canvas = this.scatter.canvas +} + + +// update & draw passes once per frame +SPLOM.prototype.render = function () { + var this$1 = this; + var ref; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + if (args.length) { + (ref = this).update.apply(ref, args) + } + + if (this.regl.attributes.preserveDrawingBuffer) { return this.draw() } + + // make sure draw is not called more often than once a frame + if (this.dirty) { + if (this.planned == null) { + this.planned = raf(function () { + this$1.draw() + this$1.dirty = true + this$1.planned = null + }) + } + } + else { + this.draw() + this.dirty = true + raf(function () { + this$1.dirty = false + }) + } + + return this +} + + +// update passes +SPLOM.prototype.update = function () { + var this$1 = this; + var ref; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + if (!args.length) { return } + + for (var i = 0; i < args.length; i++) { + this$1.updateItem(i, args[i]) + } + + // remove nulled passes + this.traces = this.traces.filter(Boolean) + + // FIXME: update passes independently + var passes = [] + var offset = 0 + for (var i$1 = 0; i$1 < this.traces.length; i$1++) { + var trace = this$1.traces[i$1] + var tracePasses = this$1.traces[i$1].passes + for (var j = 0; j < tracePasses.length; j++) { + passes.push(this$1.passes[tracePasses[j]]) + } + // save offset of passes + trace.passOffset = offset + offset += trace.passes.length + } + + (ref = this.scatter).update.apply(ref, passes) + + return this +} + + +// update trace by index, not supposed to be called directly +SPLOM.prototype.updateItem = function (i, options) { + var this$1 = this; + + var ref = this; + var regl = ref.regl; + + // remove pass if null + if (options === null) { + this.traces[i] = null + return this + } + + if (!options) { return this } + + var o = pick(options, { + data: 'data items columns rows values dimensions samples x', + snap: 'snap cluster', + size: 'sizes size radius', + color: 'colors color fill fill-color fillColor', + opacity: 'opacity alpha transparency opaque', + borderSize: 'borderSizes borderSize border-size bordersize borderWidth borderWidths border-width borderwidth stroke-width strokeWidth strokewidth outline', + borderColor: 'borderColors borderColor bordercolor stroke stroke-color strokeColor', + marker: 'markers marker shape', + range: 'range ranges databox dataBox', + viewport: 'viewport viewBox viewbox', + domain: 'domain domains area areas', + padding: 'pad padding paddings pads margin margins', + transpose: 'transpose transposed', + diagonal: 'diagonal diag showDiagonal', + upper: 'upper up top upperhalf upperHalf showupperhalf showUpper showUpperHalf', + lower: 'lower low bottom lowerhalf lowerHalf showlowerhalf showLowerHalf showLower' + }) + + // we provide regl buffer per-trace, since trace data can be changed + var trace = (this.traces[i] || (this.traces[i] = { + id: i, + buffer: regl.buffer({ + usage: 'dynamic', + type: 'float', + data: new Uint8Array() + }), + color: 'black', + marker: null, + size: 12, + borderColor: 'transparent', + borderSize: 1, + viewport: rect([regl._gl.drawingBufferWidth, regl._gl.drawingBufferHeight]), + padding: [0, 0, 0, 0], + opacity: 1, + diagonal: true, + upper: true, + lower: true + })) + + + // save styles + if (o.color != null) { + trace.color = o.color + } + if (o.size != null) { + trace.size = o.size + } + if (o.marker != null) { + trace.marker = o.marker + } + if (o.borderColor != null) { + trace.borderColor = o.borderColor + } + if (o.borderSize != null) { + trace.borderSize = o.borderSize + } + if (o.opacity != null) { + trace.opacity = o.opacity + } + if (o.viewport) { + trace.viewport = rect(o.viewport) + } + if (o.diagonal != null) { trace.diagonal = o.diagonal } + if (o.upper != null) { trace.upper = o.upper } + if (o.lower != null) { trace.lower = o.lower } + + // put flattened data into buffer + if (o.data) { + trace.buffer(flatten(o.data)) + trace.columns = o.data.length + trace.count = o.data[0].length + + // detect bounds per-column + trace.bounds = [] + + for (var i$1 = 0; i$1 < trace.columns; i$1++) { + trace.bounds[i$1] = getBounds(o.data[i$1], 1) + } + } + + // add proper range updating markers + var multirange + if (o.range) { + trace.range = o.range + multirange = trace.range && typeof trace.range[0] !== 'number' + } + + if (o.domain) { + trace.domain = o.domain + } + var multipadding = false + if (o.padding != null) { + // multiple paddings + if (Array.isArray(o.padding) && o.padding.length === trace.columns && typeof o.padding[o.padding.length - 1] === 'number') { + trace.padding = o.padding.map(getPad) + multipadding = true + } + // single padding + else { + trace.padding = getPad(o.padding) + } + } + + // create passes + var m = trace.columns + var n = trace.count + + var w = trace.viewport.width + var h = trace.viewport.height + var left = trace.viewport.x + var top = trace.viewport.y + var iw = w / m + var ih = h / m + + trace.passes = [] + + for (var i$2 = 0; i$2 < m; i$2++) { + for (var j = 0; j < m; j++) { + if (!trace.diagonal && j === i$2) { continue } + if (!trace.upper && i$2 > j) { continue } + if (!trace.lower && i$2 < j) { continue } + + var key = passId(trace.id, i$2, j) + + var pass = this$1.passes[key] || (this$1.passes[key] = {}) + + if (o.data) { + if (o.transpose) { + pass.positions = { + x: {buffer: trace.buffer, offset: j, count: n, stride: m}, + y: {buffer: trace.buffer, offset: i$2, count: n, stride: m} + } + } + else { + pass.positions = { + x: {buffer: trace.buffer, offset: j * n, count: n}, + y: {buffer: trace.buffer, offset: i$2 * n, count: n} + } + } + + pass.bounds = getBox(trace.bounds, i$2, j) + } + + if (o.domain || o.viewport || o.data) { + var pad = multipadding ? getBox(trace.padding, i$2, j) : trace.padding + if (trace.domain) { + var ref$1 = getBox(trace.domain, i$2, j); + var lox = ref$1[0]; + var loy = ref$1[1]; + var hix = ref$1[2]; + var hiy = ref$1[3]; + + pass.viewport = [ + left + lox * w + pad[0], + top + loy * h + pad[1], + left + hix * w - pad[2], + top + hiy * h - pad[3] + ] + } + // consider auto-domain equipartial + else { + pass.viewport = [ + left + j * iw + iw * pad[0], + top + i$2 * ih + ih * pad[1], + left + (j + 1) * iw - iw * pad[2], + top + (i$2 + 1) * ih - ih * pad[3] + ] + } + } + + if (o.color) { pass.color = trace.color } + if (o.size) { pass.size = trace.size } + if (o.marker) { pass.marker = trace.marker } + if (o.borderSize) { pass.borderSize = trace.borderSize } + if (o.borderColor) { pass.borderColor = trace.borderColor } + if (o.opacity) { pass.opacity = trace.opacity } + + if (o.range) { + pass.range = multirange ? getBox(trace.range, i$2, j) : trace.range || pass.bounds + } + + trace.passes.push(key) + } + } + + return this +} + + +// draw all or passed passes +SPLOM.prototype.draw = function () { + var this$1 = this; + var ref$2; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + if (!args.length) { + this.scatter.draw() + } + else { + var idx = [] + for (var i = 0; i < args.length; i++) { + // draw(0, 2, 5) - draw traces + if (typeof args[i] === 'number' ) { + var ref = this$1.traces[args[i]]; + var passes = ref.passes; + var passOffset = ref.passOffset; + idx.push.apply(idx, arrRange(passOffset, passOffset + passes.length)) + } + // draw([0, 1, 2 ...], [3, 4, 5]) - draw points + else if (args[i].length) { + var els = args[i] + var ref$1 = this$1.traces[i]; + var passes$1 = ref$1.passes; + var passOffset$1 = ref$1.passOffset; + passes$1 = passes$1.map(function (passId, i) { + idx[passOffset$1 + i] = els + }) + } + } + (ref$2 = this.scatter).draw.apply(ref$2, idx) + } + + return this +} + + +// dispose resources +SPLOM.prototype.destroy = function () { + this.traces.forEach(function (trace) { + if (trace.buffer && trace.buffer.destroy) { trace.buffer.destroy() } + }) + this.traces = null + this.passes = null + + this.scatter.destroy() + + return this +} + + +// return pass corresponding to trace i- j- square +function passId (trace, i, j) { + var id = (trace.id != null ? trace.id : trace) + var n = i + var m = j + var key = id << 16 | (n & 0xff) << 8 | m & 0xff + + return key +} + + +// return bounding box corresponding to a pass +function getBox (items, i, j) { + var ilox, iloy, ihix, ihiy, jlox, jloy, jhix, jhiy + var iitem = items[i], jitem = items[j] + + if (iitem.length > 2) { + ilox = iitem[0] + ihix = iitem[2] + iloy = iitem[1] + ihiy = iitem[3] + } + else if (iitem.length) { + ilox = iloy = iitem[0] + ihix = ihiy = iitem[1] + } + else { + ilox = iitem.x + iloy = iitem.y + ihix = iitem.x + iitem.width + ihiy = iitem.y + iitem.height + } + + if (jitem.length > 2) { + jlox = jitem[0] + jhix = jitem[2] + jloy = jitem[1] + jhiy = jitem[3] + } + else if (jitem.length) { + jlox = jloy = jitem[0] + jhix = jhiy = jitem[1] + } + else { + jlox = jitem.x + jloy = jitem.y + jhix = jitem.x + jitem.width + jhiy = jitem.y + jitem.height + } + + return [ jlox, iloy, jhix, ihiy ] +} + + +function getPad (arg) { + if (typeof arg === 'number') { return [arg, arg, arg, arg] } + else if (arg.length === 2) { return [arg[0], arg[1], arg[0], arg[1]] } + else { + var box = rect(arg) + return [box.x, box.y, box.x + box.width, box.y + box.height] + } +} + +},{"array-bounds":53,"array-range":55,"flatten-vertex-data":216,"parse-rect":442,"pick-by-alias":448,"raf":467,"regl-scatter2d/scatter":476}],478:[function(_dereq_,module,exports){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.createREGL = factory()); +}(this, (function () { 'use strict'; + +var isTypedArray = function (x) { + return ( + x instanceof Uint8Array || + x instanceof Uint16Array || + x instanceof Uint32Array || + x instanceof Int8Array || + x instanceof Int16Array || + x instanceof Int32Array || + x instanceof Float32Array || + x instanceof Float64Array || + x instanceof Uint8ClampedArray + ) +}; + +var extend = function (base, opts) { + var keys = Object.keys(opts); + for (var i = 0; i < keys.length; ++i) { + base[keys[i]] = opts[keys[i]]; + } + return base +}; + +// Error checking and parameter validation. +// +// Statements for the form `check.someProcedure(...)` get removed by +// a browserify transform for optimized/minified bundles. +// +/* globals atob */ +var endl = '\n'; + +// only used for extracting shader names. if atob not present, then errors +// will be slightly crappier +function decodeB64 (str) { + if (typeof atob !== 'undefined') { + return atob(str) + } + return 'base64:' + str +} + +function raise (message) { + var error = new Error('(regl) ' + message); + console.error(error); + throw error +} + +function check (pred, message) { + if (!pred) { + raise(message); + } +} + +function encolon (message) { + if (message) { + return ': ' + message + } + return '' +} + +function checkParameter (param, possibilities, message) { + if (!(param in possibilities)) { + raise('unknown parameter (' + param + ')' + encolon(message) + + '. possible values: ' + Object.keys(possibilities).join()); + } +} + +function checkIsTypedArray (data, message) { + if (!isTypedArray(data)) { + raise( + 'invalid parameter type' + encolon(message) + + '. must be a typed array'); + } +} + +function checkTypeOf (value, type, message) { + if (typeof value !== type) { + raise( + 'invalid parameter type' + encolon(message) + + '. expected ' + type + ', got ' + (typeof value)); + } +} + +function checkNonNegativeInt (value, message) { + if (!((value >= 0) && + ((value | 0) === value))) { + raise('invalid parameter type, (' + value + ')' + encolon(message) + + '. must be a nonnegative integer'); + } +} + +function checkOneOf (value, list, message) { + if (list.indexOf(value) < 0) { + raise('invalid value' + encolon(message) + '. must be one of: ' + list); + } +} + +var constructorKeys = [ + 'gl', + 'canvas', + 'container', + 'attributes', + 'pixelRatio', + 'extensions', + 'optionalExtensions', + 'profile', + 'onDone' +]; + +function checkConstructor (obj) { + Object.keys(obj).forEach(function (key) { + if (constructorKeys.indexOf(key) < 0) { + raise('invalid regl constructor argument "' + key + '". must be one of ' + constructorKeys); + } + }); +} + +function leftPad (str, n) { + str = str + ''; + while (str.length < n) { + str = ' ' + str; + } + return str +} + +function ShaderFile () { + this.name = 'unknown'; + this.lines = []; + this.index = {}; + this.hasErrors = false; +} + +function ShaderLine (number, line) { + this.number = number; + this.line = line; + this.errors = []; +} + +function ShaderError (fileNumber, lineNumber, message) { + this.file = fileNumber; + this.line = lineNumber; + this.message = message; +} + +function guessCommand () { + var error = new Error(); + var stack = (error.stack || error).toString(); + var pat = /compileProcedure.*\n\s*at.*\((.*)\)/.exec(stack); + if (pat) { + return pat[1] + } + var pat2 = /compileProcedure.*\n\s*at\s+(.*)(\n|$)/.exec(stack); + if (pat2) { + return pat2[1] + } + return 'unknown' +} + +function guessCallSite () { + var error = new Error(); + var stack = (error.stack || error).toString(); + var pat = /at REGLCommand.*\n\s+at.*\((.*)\)/.exec(stack); + if (pat) { + return pat[1] + } + var pat2 = /at REGLCommand.*\n\s+at\s+(.*)\n/.exec(stack); + if (pat2) { + return pat2[1] + } + return 'unknown' +} + +function parseSource (source, command) { + var lines = source.split('\n'); + var lineNumber = 1; + var fileNumber = 0; + var files = { + unknown: new ShaderFile(), + 0: new ShaderFile() + }; + files.unknown.name = files[0].name = command || guessCommand(); + files.unknown.lines.push(new ShaderLine(0, '')); + for (var i = 0; i < lines.length; ++i) { + var line = lines[i]; + var parts = /^\s*\#\s*(\w+)\s+(.+)\s*$/.exec(line); + if (parts) { + switch (parts[1]) { + case 'line': + var lineNumberInfo = /(\d+)(\s+\d+)?/.exec(parts[2]); + if (lineNumberInfo) { + lineNumber = lineNumberInfo[1] | 0; + if (lineNumberInfo[2]) { + fileNumber = lineNumberInfo[2] | 0; + if (!(fileNumber in files)) { + files[fileNumber] = new ShaderFile(); + } + } + } + break + case 'define': + var nameInfo = /SHADER_NAME(_B64)?\s+(.*)$/.exec(parts[2]); + if (nameInfo) { + files[fileNumber].name = (nameInfo[1] + ? decodeB64(nameInfo[2]) + : nameInfo[2]); + } + break + } + } + files[fileNumber].lines.push(new ShaderLine(lineNumber++, line)); + } + Object.keys(files).forEach(function (fileNumber) { + var file = files[fileNumber]; + file.lines.forEach(function (line) { + file.index[line.number] = line; + }); + }); + return files +} + +function parseErrorLog (errLog) { + var result = []; + errLog.split('\n').forEach(function (errMsg) { + if (errMsg.length < 5) { + return + } + var parts = /^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(errMsg); + if (parts) { + result.push(new ShaderError( + parts[1] | 0, + parts[2] | 0, + parts[3].trim())); + } else if (errMsg.length > 0) { + result.push(new ShaderError('unknown', 0, errMsg)); + } + }); + return result +} + +function annotateFiles (files, errors) { + errors.forEach(function (error) { + var file = files[error.file]; + if (file) { + var line = file.index[error.line]; + if (line) { + line.errors.push(error); + file.hasErrors = true; + return + } + } + files.unknown.hasErrors = true; + files.unknown.lines[0].errors.push(error); + }); +} + +function checkShaderError (gl, shader, source, type, command) { + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var errLog = gl.getShaderInfoLog(shader); + var typeName = type === gl.FRAGMENT_SHADER ? 'fragment' : 'vertex'; + checkCommandType(source, 'string', typeName + ' shader source must be a string', command); + var files = parseSource(source, command); + var errors = parseErrorLog(errLog); + annotateFiles(files, errors); + + Object.keys(files).forEach(function (fileNumber) { + var file = files[fileNumber]; + if (!file.hasErrors) { + return + } + + var strings = ['']; + var styles = ['']; + + function push (str, style) { + strings.push(str); + styles.push(style || ''); + } + + push('file number ' + fileNumber + ': ' + file.name + '\n', 'color:red;text-decoration:underline;font-weight:bold'); + + file.lines.forEach(function (line) { + if (line.errors.length > 0) { + push(leftPad(line.number, 4) + '| ', 'background-color:yellow; font-weight:bold'); + push(line.line + endl, 'color:red; background-color:yellow; font-weight:bold'); + + // try to guess token + var offset = 0; + line.errors.forEach(function (error) { + var message = error.message; + var token = /^\s*\'(.*)\'\s*\:\s*(.*)$/.exec(message); + if (token) { + var tokenPat = token[1]; + message = token[2]; + switch (tokenPat) { + case 'assign': + tokenPat = '='; + break + } + offset = Math.max(line.line.indexOf(tokenPat, offset), 0); + } else { + offset = 0; + } + + push(leftPad('| ', 6)); + push(leftPad('^^^', offset + 3) + endl, 'font-weight:bold'); + push(leftPad('| ', 6)); + push(message + endl, 'font-weight:bold'); + }); + push(leftPad('| ', 6) + endl); + } else { + push(leftPad(line.number, 4) + '| '); + push(line.line + endl, 'color:red'); + } + }); + if (typeof document !== 'undefined' && !window.chrome) { + styles[0] = strings.join('%c'); + console.log.apply(console, styles); + } else { + console.log(strings.join('')); + } + }); + + check.raise('Error compiling ' + typeName + ' shader, ' + files[0].name); + } +} + +function checkLinkError (gl, program, fragShader, vertShader, command) { + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var errLog = gl.getProgramInfoLog(program); + var fragParse = parseSource(fragShader, command); + var vertParse = parseSource(vertShader, command); + + var header = 'Error linking program with vertex shader, "' + + vertParse[0].name + '", and fragment shader "' + fragParse[0].name + '"'; + + if (typeof document !== 'undefined') { + console.log('%c' + header + endl + '%c' + errLog, + 'color:red;text-decoration:underline;font-weight:bold', + 'color:red'); + } else { + console.log(header + endl + errLog); + } + check.raise(header); + } +} + +function saveCommandRef (object) { + object._commandRef = guessCommand(); +} + +function saveDrawCommandInfo (opts, uniforms, attributes, stringStore) { + saveCommandRef(opts); + + function id (str) { + if (str) { + return stringStore.id(str) + } + return 0 + } + opts._fragId = id(opts.static.frag); + opts._vertId = id(opts.static.vert); + + function addProps (dict, set) { + Object.keys(set).forEach(function (u) { + dict[stringStore.id(u)] = true; + }); + } + + var uniformSet = opts._uniformSet = {}; + addProps(uniformSet, uniforms.static); + addProps(uniformSet, uniforms.dynamic); + + var attributeSet = opts._attributeSet = {}; + addProps(attributeSet, attributes.static); + addProps(attributeSet, attributes.dynamic); + + opts._hasCount = ( + 'count' in opts.static || + 'count' in opts.dynamic || + 'elements' in opts.static || + 'elements' in opts.dynamic); +} + +function commandRaise (message, command) { + var callSite = guessCallSite(); + raise(message + + ' in command ' + (command || guessCommand()) + + (callSite === 'unknown' ? '' : ' called from ' + callSite)); +} + +function checkCommand (pred, message, command) { + if (!pred) { + commandRaise(message, command || guessCommand()); + } +} + +function checkParameterCommand (param, possibilities, message, command) { + if (!(param in possibilities)) { + commandRaise( + 'unknown parameter (' + param + ')' + encolon(message) + + '. possible values: ' + Object.keys(possibilities).join(), + command || guessCommand()); + } +} + +function checkCommandType (value, type, message, command) { + if (typeof value !== type) { + commandRaise( + 'invalid parameter type' + encolon(message) + + '. expected ' + type + ', got ' + (typeof value), + command || guessCommand()); + } +} + +function checkOptional (block) { + block(); +} + +function checkFramebufferFormat (attachment, texFormats, rbFormats) { + if (attachment.texture) { + checkOneOf( + attachment.texture._texture.internalformat, + texFormats, + 'unsupported texture format for attachment'); + } else { + checkOneOf( + attachment.renderbuffer._renderbuffer.format, + rbFormats, + 'unsupported renderbuffer format for attachment'); + } +} + +var GL_CLAMP_TO_EDGE = 0x812F; + +var GL_NEAREST = 0x2600; +var GL_NEAREST_MIPMAP_NEAREST = 0x2700; +var GL_LINEAR_MIPMAP_NEAREST = 0x2701; +var GL_NEAREST_MIPMAP_LINEAR = 0x2702; +var GL_LINEAR_MIPMAP_LINEAR = 0x2703; + +var GL_BYTE = 5120; +var GL_UNSIGNED_BYTE = 5121; +var GL_SHORT = 5122; +var GL_UNSIGNED_SHORT = 5123; +var GL_INT = 5124; +var GL_UNSIGNED_INT = 5125; +var GL_FLOAT = 5126; + +var GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033; +var GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034; +var GL_UNSIGNED_SHORT_5_6_5 = 0x8363; +var GL_UNSIGNED_INT_24_8_WEBGL = 0x84FA; + +var GL_HALF_FLOAT_OES = 0x8D61; + +var TYPE_SIZE = {}; + +TYPE_SIZE[GL_BYTE] = +TYPE_SIZE[GL_UNSIGNED_BYTE] = 1; + +TYPE_SIZE[GL_SHORT] = +TYPE_SIZE[GL_UNSIGNED_SHORT] = +TYPE_SIZE[GL_HALF_FLOAT_OES] = +TYPE_SIZE[GL_UNSIGNED_SHORT_5_6_5] = +TYPE_SIZE[GL_UNSIGNED_SHORT_4_4_4_4] = +TYPE_SIZE[GL_UNSIGNED_SHORT_5_5_5_1] = 2; + +TYPE_SIZE[GL_INT] = +TYPE_SIZE[GL_UNSIGNED_INT] = +TYPE_SIZE[GL_FLOAT] = +TYPE_SIZE[GL_UNSIGNED_INT_24_8_WEBGL] = 4; + +function pixelSize (type, channels) { + if (type === GL_UNSIGNED_SHORT_5_5_5_1 || + type === GL_UNSIGNED_SHORT_4_4_4_4 || + type === GL_UNSIGNED_SHORT_5_6_5) { + return 2 + } else if (type === GL_UNSIGNED_INT_24_8_WEBGL) { + return 4 + } else { + return TYPE_SIZE[type] * channels + } +} + +function isPow2 (v) { + return !(v & (v - 1)) && (!!v) +} + +function checkTexture2D (info, mipData, limits) { + var i; + var w = mipData.width; + var h = mipData.height; + var c = mipData.channels; + + // Check texture shape + check(w > 0 && w <= limits.maxTextureSize && + h > 0 && h <= limits.maxTextureSize, + 'invalid texture shape'); + + // check wrap mode + if (info.wrapS !== GL_CLAMP_TO_EDGE || info.wrapT !== GL_CLAMP_TO_EDGE) { + check(isPow2(w) && isPow2(h), + 'incompatible wrap mode for texture, both width and height must be power of 2'); + } + + if (mipData.mipmask === 1) { + if (w !== 1 && h !== 1) { + check( + info.minFilter !== GL_NEAREST_MIPMAP_NEAREST && + info.minFilter !== GL_NEAREST_MIPMAP_LINEAR && + info.minFilter !== GL_LINEAR_MIPMAP_NEAREST && + info.minFilter !== GL_LINEAR_MIPMAP_LINEAR, + 'min filter requires mipmap'); + } + } else { + // texture must be power of 2 + check(isPow2(w) && isPow2(h), + 'texture must be a square power of 2 to support mipmapping'); + check(mipData.mipmask === (w << 1) - 1, + 'missing or incomplete mipmap data'); + } + + if (mipData.type === GL_FLOAT) { + if (limits.extensions.indexOf('oes_texture_float_linear') < 0) { + check(info.minFilter === GL_NEAREST && info.magFilter === GL_NEAREST, + 'filter not supported, must enable oes_texture_float_linear'); + } + check(!info.genMipmaps, + 'mipmap generation not supported with float textures'); + } + + // check image complete + var mipimages = mipData.images; + for (i = 0; i < 16; ++i) { + if (mipimages[i]) { + var mw = w >> i; + var mh = h >> i; + check(mipData.mipmask & (1 << i), 'missing mipmap data'); + + var img = mipimages[i]; + + check( + img.width === mw && + img.height === mh, + 'invalid shape for mip images'); + + check( + img.format === mipData.format && + img.internalformat === mipData.internalformat && + img.type === mipData.type, + 'incompatible type for mip image'); + + if (img.compressed) { + // TODO: check size for compressed images + } else if (img.data) { + // check(img.data.byteLength === mw * mh * + // Math.max(pixelSize(img.type, c), img.unpackAlignment), + var rowSize = Math.ceil(pixelSize(img.type, c) * mw / img.unpackAlignment) * img.unpackAlignment; + check(img.data.byteLength === rowSize * mh, + 'invalid data for image, buffer size is inconsistent with image format'); + } else if (img.element) { + // TODO: check element can be loaded + } else if (img.copy) { + // TODO: check compatible format and type + } + } else if (!info.genMipmaps) { + check((mipData.mipmask & (1 << i)) === 0, 'extra mipmap data'); + } + } + + if (mipData.compressed) { + check(!info.genMipmaps, + 'mipmap generation for compressed images not supported'); + } +} + +function checkTextureCube (texture, info, faces, limits) { + var w = texture.width; + var h = texture.height; + var c = texture.channels; + + // Check texture shape + check( + w > 0 && w <= limits.maxTextureSize && h > 0 && h <= limits.maxTextureSize, + 'invalid texture shape'); + check( + w === h, + 'cube map must be square'); + check( + info.wrapS === GL_CLAMP_TO_EDGE && info.wrapT === GL_CLAMP_TO_EDGE, + 'wrap mode not supported by cube map'); + + for (var i = 0; i < faces.length; ++i) { + var face = faces[i]; + check( + face.width === w && face.height === h, + 'inconsistent cube map face shape'); + + if (info.genMipmaps) { + check(!face.compressed, + 'can not generate mipmap for compressed textures'); + check(face.mipmask === 1, + 'can not specify mipmaps and generate mipmaps'); + } else { + // TODO: check mip and filter mode + } + + var mipmaps = face.images; + for (var j = 0; j < 16; ++j) { + var img = mipmaps[j]; + if (img) { + var mw = w >> j; + var mh = h >> j; + check(face.mipmask & (1 << j), 'missing mipmap data'); + check( + img.width === mw && + img.height === mh, + 'invalid shape for mip images'); + check( + img.format === texture.format && + img.internalformat === texture.internalformat && + img.type === texture.type, + 'incompatible type for mip image'); + + if (img.compressed) { + // TODO: check size for compressed images + } else if (img.data) { + check(img.data.byteLength === mw * mh * + Math.max(pixelSize(img.type, c), img.unpackAlignment), + 'invalid data for image, buffer size is inconsistent with image format'); + } else if (img.element) { + // TODO: check element can be loaded + } else if (img.copy) { + // TODO: check compatible format and type + } + } + } + } +} + +var check$1 = extend(check, { + optional: checkOptional, + raise: raise, + commandRaise: commandRaise, + command: checkCommand, + parameter: checkParameter, + commandParameter: checkParameterCommand, + constructor: checkConstructor, + type: checkTypeOf, + commandType: checkCommandType, + isTypedArray: checkIsTypedArray, + nni: checkNonNegativeInt, + oneOf: checkOneOf, + shaderError: checkShaderError, + linkError: checkLinkError, + callSite: guessCallSite, + saveCommandRef: saveCommandRef, + saveDrawInfo: saveDrawCommandInfo, + framebufferFormat: checkFramebufferFormat, + guessCommand: guessCommand, + texture2D: checkTexture2D, + textureCube: checkTextureCube +}); + +var VARIABLE_COUNTER = 0; + +var DYN_FUNC = 0; + +function DynamicVariable (type, data) { + this.id = (VARIABLE_COUNTER++); + this.type = type; + this.data = data; +} + +function escapeStr (str) { + return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') +} + +function splitParts (str) { + if (str.length === 0) { + return [] + } + + var firstChar = str.charAt(0); + var lastChar = str.charAt(str.length - 1); + + if (str.length > 1 && + firstChar === lastChar && + (firstChar === '"' || firstChar === "'")) { + return ['"' + escapeStr(str.substr(1, str.length - 2)) + '"'] + } + + var parts = /\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(str); + if (parts) { + return ( + splitParts(str.substr(0, parts.index)) + .concat(splitParts(parts[1])) + .concat(splitParts(str.substr(parts.index + parts[0].length))) + ) + } + + var subparts = str.split('.'); + if (subparts.length === 1) { + return ['"' + escapeStr(str) + '"'] + } + + var result = []; + for (var i = 0; i < subparts.length; ++i) { + result = result.concat(splitParts(subparts[i])); + } + return result +} + +function toAccessorString (str) { + return '[' + splitParts(str).join('][') + ']' +} + +function defineDynamic (type, data) { + return new DynamicVariable(type, toAccessorString(data + '')) +} + +function isDynamic (x) { + return (typeof x === 'function' && !x._reglType) || + x instanceof DynamicVariable +} + +function unbox (x, path) { + if (typeof x === 'function') { + return new DynamicVariable(DYN_FUNC, x) + } + return x +} + +var dynamic = { + DynamicVariable: DynamicVariable, + define: defineDynamic, + isDynamic: isDynamic, + unbox: unbox, + accessor: toAccessorString +}; + +/* globals requestAnimationFrame, cancelAnimationFrame */ +var raf = { + next: typeof requestAnimationFrame === 'function' + ? function (cb) { return requestAnimationFrame(cb) } + : function (cb) { return setTimeout(cb, 16) }, + cancel: typeof cancelAnimationFrame === 'function' + ? function (raf) { return cancelAnimationFrame(raf) } + : clearTimeout +}; + +/* globals performance */ +var clock = (typeof performance !== 'undefined' && performance.now) + ? function () { return performance.now() } + : function () { return +(new Date()) }; + +function createStringStore () { + var stringIds = {'': 0}; + var stringValues = ['']; + return { + id: function (str) { + var result = stringIds[str]; + if (result) { + return result + } + result = stringIds[str] = stringValues.length; + stringValues.push(str); + return result + }, + + str: function (id) { + return stringValues[id] + } + } +} + +// Context and canvas creation helper functions +function createCanvas (element, onDone, pixelRatio) { + var canvas = document.createElement('canvas'); + extend(canvas.style, { + border: 0, + margin: 0, + padding: 0, + top: 0, + left: 0 + }); + element.appendChild(canvas); + + if (element === document.body) { + canvas.style.position = 'absolute'; + extend(element.style, { + margin: 0, + padding: 0 + }); + } + + function resize () { + var w = window.innerWidth; + var h = window.innerHeight; + if (element !== document.body) { + var bounds = element.getBoundingClientRect(); + w = bounds.right - bounds.left; + h = bounds.bottom - bounds.top; + } + canvas.width = pixelRatio * w; + canvas.height = pixelRatio * h; + extend(canvas.style, { + width: w + 'px', + height: h + 'px' + }); + } + + window.addEventListener('resize', resize, false); + + function onDestroy () { + window.removeEventListener('resize', resize); + element.removeChild(canvas); + } + + resize(); + + return { + canvas: canvas, + onDestroy: onDestroy + } +} + +function createContext (canvas, contextAttributes) { + function get (name) { + try { + return canvas.getContext(name, contextAttributes) + } catch (e) { + return null + } + } + return ( + get('webgl') || + get('experimental-webgl') || + get('webgl-experimental') + ) +} + +function isHTMLElement (obj) { + return ( + typeof obj.nodeName === 'string' && + typeof obj.appendChild === 'function' && + typeof obj.getBoundingClientRect === 'function' + ) +} + +function isWebGLContext (obj) { + return ( + typeof obj.drawArrays === 'function' || + typeof obj.drawElements === 'function' + ) +} + +function parseExtensions (input) { + if (typeof input === 'string') { + return input.split() + } + check$1(Array.isArray(input), 'invalid extension array'); + return input +} + +function getElement (desc) { + if (typeof desc === 'string') { + check$1(typeof document !== 'undefined', 'not supported outside of DOM'); + return document.querySelector(desc) + } + return desc +} + +function parseArgs (args_) { + var args = args_ || {}; + var element, container, canvas, gl; + var contextAttributes = {}; + var extensions = []; + var optionalExtensions = []; + var pixelRatio = (typeof window === 'undefined' ? 1 : window.devicePixelRatio); + var profile = false; + var onDone = function (err) { + if (err) { + check$1.raise(err); + } + }; + var onDestroy = function () {}; + if (typeof args === 'string') { + check$1( + typeof document !== 'undefined', + 'selector queries only supported in DOM enviroments'); + element = document.querySelector(args); + check$1(element, 'invalid query string for element'); + } else if (typeof args === 'object') { + if (isHTMLElement(args)) { + element = args; + } else if (isWebGLContext(args)) { + gl = args; + canvas = gl.canvas; + } else { + check$1.constructor(args); + if ('gl' in args) { + gl = args.gl; + } else if ('canvas' in args) { + canvas = getElement(args.canvas); + } else if ('container' in args) { + container = getElement(args.container); + } + if ('attributes' in args) { + contextAttributes = args.attributes; + check$1.type(contextAttributes, 'object', 'invalid context attributes'); + } + if ('extensions' in args) { + extensions = parseExtensions(args.extensions); + } + if ('optionalExtensions' in args) { + optionalExtensions = parseExtensions(args.optionalExtensions); + } + if ('onDone' in args) { + check$1.type( + args.onDone, 'function', + 'invalid or missing onDone callback'); + onDone = args.onDone; + } + if ('profile' in args) { + profile = !!args.profile; + } + if ('pixelRatio' in args) { + pixelRatio = +args.pixelRatio; + check$1(pixelRatio > 0, 'invalid pixel ratio'); + } + } + } else { + check$1.raise('invalid arguments to regl'); + } + + if (element) { + if (element.nodeName.toLowerCase() === 'canvas') { + canvas = element; + } else { + container = element; + } + } + + if (!gl) { + if (!canvas) { + check$1( + typeof document !== 'undefined', + 'must manually specify webgl context outside of DOM environments'); + var result = createCanvas(container || document.body, onDone, pixelRatio); + if (!result) { + return null + } + canvas = result.canvas; + onDestroy = result.onDestroy; + } + gl = createContext(canvas, contextAttributes); + } + + if (!gl) { + onDestroy(); + onDone('webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org'); + return null + } + + return { + gl: gl, + canvas: canvas, + container: container, + extensions: extensions, + optionalExtensions: optionalExtensions, + pixelRatio: pixelRatio, + profile: profile, + onDone: onDone, + onDestroy: onDestroy + } +} + +function createExtensionCache (gl, config) { + var extensions = {}; + + function tryLoadExtension (name_) { + check$1.type(name_, 'string', 'extension name must be string'); + var name = name_.toLowerCase(); + var ext; + try { + ext = extensions[name] = gl.getExtension(name); + } catch (e) {} + return !!ext + } + + for (var i = 0; i < config.extensions.length; ++i) { + var name = config.extensions[i]; + if (!tryLoadExtension(name)) { + config.onDestroy(); + config.onDone('"' + name + '" extension is not supported by the current WebGL context, try upgrading your system or a different browser'); + return null + } + } + + config.optionalExtensions.forEach(tryLoadExtension); + + return { + extensions: extensions, + restore: function () { + Object.keys(extensions).forEach(function (name) { + if (!tryLoadExtension(name)) { + throw new Error('(regl): error restoring extension ' + name) + } + }); + } + } +} + +function loop (n, f) { + var result = Array(n); + for (var i = 0; i < n; ++i) { + result[i] = f(i); + } + return result +} + +var GL_BYTE$1 = 5120; +var GL_UNSIGNED_BYTE$2 = 5121; +var GL_SHORT$1 = 5122; +var GL_UNSIGNED_SHORT$1 = 5123; +var GL_INT$1 = 5124; +var GL_UNSIGNED_INT$1 = 5125; +var GL_FLOAT$2 = 5126; + +function nextPow16 (v) { + for (var i = 16; i <= (1 << 28); i *= 16) { + if (v <= i) { + return i + } + } + return 0 +} + +function log2 (v) { + var r, shift; + r = (v > 0xFFFF) << 4; + v >>>= r; + shift = (v > 0xFF) << 3; + v >>>= shift; r |= shift; + shift = (v > 0xF) << 2; + v >>>= shift; r |= shift; + shift = (v > 0x3) << 1; + v >>>= shift; r |= shift; + return r | (v >> 1) +} + +function createPool () { + var bufferPool = loop(8, function () { + return [] + }); + + function alloc (n) { + var sz = nextPow16(n); + var bin = bufferPool[log2(sz) >> 2]; + if (bin.length > 0) { + return bin.pop() + } + return new ArrayBuffer(sz) + } + + function free (buf) { + bufferPool[log2(buf.byteLength) >> 2].push(buf); + } + + function allocType (type, n) { + var result = null; + switch (type) { + case GL_BYTE$1: + result = new Int8Array(alloc(n), 0, n); + break + case GL_UNSIGNED_BYTE$2: + result = new Uint8Array(alloc(n), 0, n); + break + case GL_SHORT$1: + result = new Int16Array(alloc(2 * n), 0, n); + break + case GL_UNSIGNED_SHORT$1: + result = new Uint16Array(alloc(2 * n), 0, n); + break + case GL_INT$1: + result = new Int32Array(alloc(4 * n), 0, n); + break + case GL_UNSIGNED_INT$1: + result = new Uint32Array(alloc(4 * n), 0, n); + break + case GL_FLOAT$2: + result = new Float32Array(alloc(4 * n), 0, n); + break + default: + return null + } + if (result.length !== n) { + return result.subarray(0, n) + } + return result + } + + function freeType (array) { + free(array.buffer); + } + + return { + alloc: alloc, + free: free, + allocType: allocType, + freeType: freeType + } +} + +var pool = createPool(); + +// zero pool for initial zero data +pool.zero = createPool(); + +var GL_SUBPIXEL_BITS = 0x0D50; +var GL_RED_BITS = 0x0D52; +var GL_GREEN_BITS = 0x0D53; +var GL_BLUE_BITS = 0x0D54; +var GL_ALPHA_BITS = 0x0D55; +var GL_DEPTH_BITS = 0x0D56; +var GL_STENCIL_BITS = 0x0D57; + +var GL_ALIASED_POINT_SIZE_RANGE = 0x846D; +var GL_ALIASED_LINE_WIDTH_RANGE = 0x846E; + +var GL_MAX_TEXTURE_SIZE = 0x0D33; +var GL_MAX_VIEWPORT_DIMS = 0x0D3A; +var GL_MAX_VERTEX_ATTRIBS = 0x8869; +var GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; +var GL_MAX_VARYING_VECTORS = 0x8DFC; +var GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; +var GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; +var GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872; +var GL_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; +var GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; +var GL_MAX_RENDERBUFFER_SIZE = 0x84E8; + +var GL_VENDOR = 0x1F00; +var GL_RENDERER = 0x1F01; +var GL_VERSION = 0x1F02; +var GL_SHADING_LANGUAGE_VERSION = 0x8B8C; + +var GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; + +var GL_MAX_COLOR_ATTACHMENTS_WEBGL = 0x8CDF; +var GL_MAX_DRAW_BUFFERS_WEBGL = 0x8824; + +var GL_TEXTURE_2D = 0x0DE1; +var GL_TEXTURE_CUBE_MAP = 0x8513; +var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; +var GL_TEXTURE0 = 0x84C0; +var GL_RGBA = 0x1908; +var GL_FLOAT$1 = 0x1406; +var GL_UNSIGNED_BYTE$1 = 0x1401; +var GL_FRAMEBUFFER = 0x8D40; +var GL_FRAMEBUFFER_COMPLETE = 0x8CD5; +var GL_COLOR_ATTACHMENT0 = 0x8CE0; +var GL_COLOR_BUFFER_BIT$1 = 0x4000; + +var wrapLimits = function (gl, extensions) { + var maxAnisotropic = 1; + if (extensions.ext_texture_filter_anisotropic) { + maxAnisotropic = gl.getParameter(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); + } + + var maxDrawbuffers = 1; + var maxColorAttachments = 1; + if (extensions.webgl_draw_buffers) { + maxDrawbuffers = gl.getParameter(GL_MAX_DRAW_BUFFERS_WEBGL); + maxColorAttachments = gl.getParameter(GL_MAX_COLOR_ATTACHMENTS_WEBGL); + } + + // detect if reading float textures is available (Safari doesn't support) + var readFloat = !!extensions.oes_texture_float; + if (readFloat) { + var readFloatTexture = gl.createTexture(); + gl.bindTexture(GL_TEXTURE_2D, readFloatTexture); + gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT$1, null); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); + gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readFloatTexture, 0); + gl.bindTexture(GL_TEXTURE_2D, null); + + if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) !== GL_FRAMEBUFFER_COMPLETE) readFloat = false; + + else { + gl.viewport(0, 0, 1, 1); + gl.clearColor(1.0, 0.0, 0.0, 1.0); + gl.clear(GL_COLOR_BUFFER_BIT$1); + var pixels = pool.allocType(GL_FLOAT$1, 4); + gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT$1, pixels); + + if (gl.getError()) readFloat = false; + else { + gl.deleteFramebuffer(fbo); + gl.deleteTexture(readFloatTexture); + + readFloat = pixels[0] === 1.0; + } + + pool.freeType(pixels); + } + } + + // detect non power of two cube textures support (IE doesn't support) + var npotTextureCube = true; + var cubeTexture = gl.createTexture(); + var data = pool.allocType(GL_UNSIGNED_BYTE$1, 36); + gl.activeTexture(GL_TEXTURE0); + gl.bindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture); + gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE$1, data); + pool.freeType(data); + gl.bindTexture(GL_TEXTURE_CUBE_MAP, null); + gl.deleteTexture(cubeTexture); + npotTextureCube = !gl.getError(); + + return { + // drawing buffer bit depth + colorBits: [ + gl.getParameter(GL_RED_BITS), + gl.getParameter(GL_GREEN_BITS), + gl.getParameter(GL_BLUE_BITS), + gl.getParameter(GL_ALPHA_BITS) + ], + depthBits: gl.getParameter(GL_DEPTH_BITS), + stencilBits: gl.getParameter(GL_STENCIL_BITS), + subpixelBits: gl.getParameter(GL_SUBPIXEL_BITS), + + // supported extensions + extensions: Object.keys(extensions).filter(function (ext) { + return !!extensions[ext] + }), + + // max aniso samples + maxAnisotropic: maxAnisotropic, + + // max draw buffers + maxDrawbuffers: maxDrawbuffers, + maxColorAttachments: maxColorAttachments, + + // point and line size ranges + pointSizeDims: gl.getParameter(GL_ALIASED_POINT_SIZE_RANGE), + lineWidthDims: gl.getParameter(GL_ALIASED_LINE_WIDTH_RANGE), + maxViewportDims: gl.getParameter(GL_MAX_VIEWPORT_DIMS), + maxCombinedTextureUnits: gl.getParameter(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS), + maxCubeMapSize: gl.getParameter(GL_MAX_CUBE_MAP_TEXTURE_SIZE), + maxRenderbufferSize: gl.getParameter(GL_MAX_RENDERBUFFER_SIZE), + maxTextureUnits: gl.getParameter(GL_MAX_TEXTURE_IMAGE_UNITS), + maxTextureSize: gl.getParameter(GL_MAX_TEXTURE_SIZE), + maxAttributes: gl.getParameter(GL_MAX_VERTEX_ATTRIBS), + maxVertexUniforms: gl.getParameter(GL_MAX_VERTEX_UNIFORM_VECTORS), + maxVertexTextureUnits: gl.getParameter(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS), + maxVaryingVectors: gl.getParameter(GL_MAX_VARYING_VECTORS), + maxFragmentUniforms: gl.getParameter(GL_MAX_FRAGMENT_UNIFORM_VECTORS), + + // vendor info + glsl: gl.getParameter(GL_SHADING_LANGUAGE_VERSION), + renderer: gl.getParameter(GL_RENDERER), + vendor: gl.getParameter(GL_VENDOR), + version: gl.getParameter(GL_VERSION), + + // quirks + readFloat: readFloat, + npotTextureCube: npotTextureCube + } +}; + +function isNDArrayLike (obj) { + return ( + !!obj && + typeof obj === 'object' && + Array.isArray(obj.shape) && + Array.isArray(obj.stride) && + typeof obj.offset === 'number' && + obj.shape.length === obj.stride.length && + (Array.isArray(obj.data) || + isTypedArray(obj.data))) +} + +var values = function (obj) { + return Object.keys(obj).map(function (key) { return obj[key] }) +}; + +var flattenUtils = { + shape: arrayShape$1, + flatten: flattenArray +}; + +function flatten1D (array, nx, out) { + for (var i = 0; i < nx; ++i) { + out[i] = array[i]; + } +} + +function flatten2D (array, nx, ny, out) { + var ptr = 0; + for (var i = 0; i < nx; ++i) { + var row = array[i]; + for (var j = 0; j < ny; ++j) { + out[ptr++] = row[j]; + } + } +} + +function flatten3D (array, nx, ny, nz, out, ptr_) { + var ptr = ptr_; + for (var i = 0; i < nx; ++i) { + var row = array[i]; + for (var j = 0; j < ny; ++j) { + var col = row[j]; + for (var k = 0; k < nz; ++k) { + out[ptr++] = col[k]; + } + } + } +} + +function flattenRec (array, shape, level, out, ptr) { + var stride = 1; + for (var i = level + 1; i < shape.length; ++i) { + stride *= shape[i]; + } + var n = shape[level]; + if (shape.length - level === 4) { + var nx = shape[level + 1]; + var ny = shape[level + 2]; + var nz = shape[level + 3]; + for (i = 0; i < n; ++i) { + flatten3D(array[i], nx, ny, nz, out, ptr); + ptr += stride; + } + } else { + for (i = 0; i < n; ++i) { + flattenRec(array[i], shape, level + 1, out, ptr); + ptr += stride; + } + } +} + +function flattenArray (array, shape, type, out_) { + var sz = 1; + if (shape.length) { + for (var i = 0; i < shape.length; ++i) { + sz *= shape[i]; + } + } else { + sz = 0; + } + var out = out_ || pool.allocType(type, sz); + switch (shape.length) { + case 0: + break + case 1: + flatten1D(array, shape[0], out); + break + case 2: + flatten2D(array, shape[0], shape[1], out); + break + case 3: + flatten3D(array, shape[0], shape[1], shape[2], out, 0); + break + default: + flattenRec(array, shape, 0, out, 0); + } + return out +} + +function arrayShape$1 (array_) { + var shape = []; + for (var array = array_; array.length; array = array[0]) { + shape.push(array.length); + } + return shape +} + +var arrayTypes = { + "[object Int8Array]": 5120, + "[object Int16Array]": 5122, + "[object Int32Array]": 5124, + "[object Uint8Array]": 5121, + "[object Uint8ClampedArray]": 5121, + "[object Uint16Array]": 5123, + "[object Uint32Array]": 5125, + "[object Float32Array]": 5126, + "[object Float64Array]": 5121, + "[object ArrayBuffer]": 5121 +}; + +var int8 = 5120; +var int16 = 5122; +var int32 = 5124; +var uint8 = 5121; +var uint16 = 5123; +var uint32 = 5125; +var float = 5126; +var float32 = 5126; +var glTypes = { + int8: int8, + int16: int16, + int32: int32, + uint8: uint8, + uint16: uint16, + uint32: uint32, + float: float, + float32: float32 +}; + +var dynamic$1 = 35048; +var stream = 35040; +var usageTypes = { + dynamic: dynamic$1, + stream: stream, + "static": 35044 +}; + +var arrayFlatten = flattenUtils.flatten; +var arrayShape = flattenUtils.shape; + +var GL_STATIC_DRAW = 0x88E4; +var GL_STREAM_DRAW = 0x88E0; + +var GL_UNSIGNED_BYTE$3 = 5121; +var GL_FLOAT$3 = 5126; + +var DTYPES_SIZES = []; +DTYPES_SIZES[5120] = 1; // int8 +DTYPES_SIZES[5122] = 2; // int16 +DTYPES_SIZES[5124] = 4; // int32 +DTYPES_SIZES[5121] = 1; // uint8 +DTYPES_SIZES[5123] = 2; // uint16 +DTYPES_SIZES[5125] = 4; // uint32 +DTYPES_SIZES[5126] = 4; // float32 + +function typedArrayCode (data) { + return arrayTypes[Object.prototype.toString.call(data)] | 0 +} + +function copyArray (out, inp) { + for (var i = 0; i < inp.length; ++i) { + out[i] = inp[i]; + } +} + +function transpose ( + result, data, shapeX, shapeY, strideX, strideY, offset) { + var ptr = 0; + for (var i = 0; i < shapeX; ++i) { + for (var j = 0; j < shapeY; ++j) { + result[ptr++] = data[strideX * i + strideY * j + offset]; + } + } +} + +function wrapBufferState (gl, stats, config, attributeState) { + var bufferCount = 0; + var bufferSet = {}; + + function REGLBuffer (type) { + this.id = bufferCount++; + this.buffer = gl.createBuffer(); + this.type = type; + this.usage = GL_STATIC_DRAW; + this.byteLength = 0; + this.dimension = 1; + this.dtype = GL_UNSIGNED_BYTE$3; + + this.persistentData = null; + + if (config.profile) { + this.stats = {size: 0}; + } + } + + REGLBuffer.prototype.bind = function () { + gl.bindBuffer(this.type, this.buffer); + }; + + REGLBuffer.prototype.destroy = function () { + destroy(this); + }; + + var streamPool = []; + + function createStream (type, data) { + var buffer = streamPool.pop(); + if (!buffer) { + buffer = new REGLBuffer(type); + } + buffer.bind(); + initBufferFromData(buffer, data, GL_STREAM_DRAW, 0, 1, false); + return buffer + } + + function destroyStream (stream$$1) { + streamPool.push(stream$$1); + } + + function initBufferFromTypedArray (buffer, data, usage) { + buffer.byteLength = data.byteLength; + gl.bufferData(buffer.type, data, usage); + } + + function initBufferFromData (buffer, data, usage, dtype, dimension, persist) { + var shape; + buffer.usage = usage; + if (Array.isArray(data)) { + buffer.dtype = dtype || GL_FLOAT$3; + if (data.length > 0) { + var flatData; + if (Array.isArray(data[0])) { + shape = arrayShape(data); + var dim = 1; + for (var i = 1; i < shape.length; ++i) { + dim *= shape[i]; + } + buffer.dimension = dim; + flatData = arrayFlatten(data, shape, buffer.dtype); + initBufferFromTypedArray(buffer, flatData, usage); + if (persist) { + buffer.persistentData = flatData; + } else { + pool.freeType(flatData); + } + } else if (typeof data[0] === 'number') { + buffer.dimension = dimension; + var typedData = pool.allocType(buffer.dtype, data.length); + copyArray(typedData, data); + initBufferFromTypedArray(buffer, typedData, usage); + if (persist) { + buffer.persistentData = typedData; + } else { + pool.freeType(typedData); + } + } else if (isTypedArray(data[0])) { + buffer.dimension = data[0].length; + buffer.dtype = dtype || typedArrayCode(data[0]) || GL_FLOAT$3; + flatData = arrayFlatten( + data, + [data.length, data[0].length], + buffer.dtype); + initBufferFromTypedArray(buffer, flatData, usage); + if (persist) { + buffer.persistentData = flatData; + } else { + pool.freeType(flatData); + } + } else { + check$1.raise('invalid buffer data'); + } + } + } else if (isTypedArray(data)) { + buffer.dtype = dtype || typedArrayCode(data); + buffer.dimension = dimension; + initBufferFromTypedArray(buffer, data, usage); + if (persist) { + buffer.persistentData = new Uint8Array(new Uint8Array(data.buffer)); + } + } else if (isNDArrayLike(data)) { + shape = data.shape; + var stride = data.stride; + var offset = data.offset; + + var shapeX = 0; + var shapeY = 0; + var strideX = 0; + var strideY = 0; + if (shape.length === 1) { + shapeX = shape[0]; + shapeY = 1; + strideX = stride[0]; + strideY = 0; + } else if (shape.length === 2) { + shapeX = shape[0]; + shapeY = shape[1]; + strideX = stride[0]; + strideY = stride[1]; + } else { + check$1.raise('invalid shape'); + } + + buffer.dtype = dtype || typedArrayCode(data.data) || GL_FLOAT$3; + buffer.dimension = shapeY; + + var transposeData = pool.allocType(buffer.dtype, shapeX * shapeY); + transpose(transposeData, + data.data, + shapeX, shapeY, + strideX, strideY, + offset); + initBufferFromTypedArray(buffer, transposeData, usage); + if (persist) { + buffer.persistentData = transposeData; + } else { + pool.freeType(transposeData); + } + } else { + check$1.raise('invalid buffer data'); + } + } + + function destroy (buffer) { + stats.bufferCount--; + + for (var i = 0; i < attributeState.state.length; ++i) { + var record = attributeState.state[i]; + if (record.buffer === buffer) { + gl.disableVertexAttribArray(i); + record.buffer = null; + } + } + + var handle = buffer.buffer; + check$1(handle, 'buffer must not be deleted already'); + gl.deleteBuffer(handle); + buffer.buffer = null; + delete bufferSet[buffer.id]; + } + + function createBuffer (options, type, deferInit, persistent) { + stats.bufferCount++; + + var buffer = new REGLBuffer(type); + bufferSet[buffer.id] = buffer; + + function reglBuffer (options) { + var usage = GL_STATIC_DRAW; + var data = null; + var byteLength = 0; + var dtype = 0; + var dimension = 1; + if (Array.isArray(options) || + isTypedArray(options) || + isNDArrayLike(options)) { + data = options; + } else if (typeof options === 'number') { + byteLength = options | 0; + } else if (options) { + check$1.type( + options, 'object', + 'buffer arguments must be an object, a number or an array'); + + if ('data' in options) { + check$1( + data === null || + Array.isArray(data) || + isTypedArray(data) || + isNDArrayLike(data), + 'invalid data for buffer'); + data = options.data; + } + + if ('usage' in options) { + check$1.parameter(options.usage, usageTypes, 'invalid buffer usage'); + usage = usageTypes[options.usage]; + } + + if ('type' in options) { + check$1.parameter(options.type, glTypes, 'invalid buffer type'); + dtype = glTypes[options.type]; + } + + if ('dimension' in options) { + check$1.type(options.dimension, 'number', 'invalid dimension'); + dimension = options.dimension | 0; + } + + if ('length' in options) { + check$1.nni(byteLength, 'buffer length must be a nonnegative integer'); + byteLength = options.length | 0; + } + } + + buffer.bind(); + if (!data) { + // #475 + if (byteLength) gl.bufferData(buffer.type, byteLength, usage); + buffer.dtype = dtype || GL_UNSIGNED_BYTE$3; + buffer.usage = usage; + buffer.dimension = dimension; + buffer.byteLength = byteLength; + } else { + initBufferFromData(buffer, data, usage, dtype, dimension, persistent); + } + + if (config.profile) { + buffer.stats.size = buffer.byteLength * DTYPES_SIZES[buffer.dtype]; + } + + return reglBuffer + } + + function setSubData (data, offset) { + check$1(offset + data.byteLength <= buffer.byteLength, + 'invalid buffer subdata call, buffer is too small. ' + ' Can\'t write data of size ' + data.byteLength + ' starting from offset ' + offset + ' to a buffer of size ' + buffer.byteLength); + + gl.bufferSubData(buffer.type, offset, data); + } + + function subdata (data, offset_) { + var offset = (offset_ || 0) | 0; + var shape; + buffer.bind(); + if (isTypedArray(data)) { + setSubData(data, offset); + } else if (Array.isArray(data)) { + if (data.length > 0) { + if (typeof data[0] === 'number') { + var converted = pool.allocType(buffer.dtype, data.length); + copyArray(converted, data); + setSubData(converted, offset); + pool.freeType(converted); + } else if (Array.isArray(data[0]) || isTypedArray(data[0])) { + shape = arrayShape(data); + var flatData = arrayFlatten(data, shape, buffer.dtype); + setSubData(flatData, offset); + pool.freeType(flatData); + } else { + check$1.raise('invalid buffer data'); + } + } + } else if (isNDArrayLike(data)) { + shape = data.shape; + var stride = data.stride; + + var shapeX = 0; + var shapeY = 0; + var strideX = 0; + var strideY = 0; + if (shape.length === 1) { + shapeX = shape[0]; + shapeY = 1; + strideX = stride[0]; + strideY = 0; + } else if (shape.length === 2) { + shapeX = shape[0]; + shapeY = shape[1]; + strideX = stride[0]; + strideY = stride[1]; + } else { + check$1.raise('invalid shape'); + } + var dtype = Array.isArray(data.data) + ? buffer.dtype + : typedArrayCode(data.data); + + var transposeData = pool.allocType(dtype, shapeX * shapeY); + transpose(transposeData, + data.data, + shapeX, shapeY, + strideX, strideY, + data.offset); + setSubData(transposeData, offset); + pool.freeType(transposeData); + } else { + check$1.raise('invalid data for buffer subdata'); + } + return reglBuffer + } + + if (!deferInit) { + reglBuffer(options); + } + + reglBuffer._reglType = 'buffer'; + reglBuffer._buffer = buffer; + reglBuffer.subdata = subdata; + if (config.profile) { + reglBuffer.stats = buffer.stats; + } + reglBuffer.destroy = function () { destroy(buffer); }; + + return reglBuffer + } + + function restoreBuffers () { + values(bufferSet).forEach(function (buffer) { + buffer.buffer = gl.createBuffer(); + gl.bindBuffer(buffer.type, buffer.buffer); + gl.bufferData( + buffer.type, buffer.persistentData || buffer.byteLength, buffer.usage); + }); + } + + if (config.profile) { + stats.getTotalBufferSize = function () { + var total = 0; + // TODO: Right now, the streams are not part of the total count. + Object.keys(bufferSet).forEach(function (key) { + total += bufferSet[key].stats.size; + }); + return total + }; + } + + return { + create: createBuffer, + + createStream: createStream, + destroyStream: destroyStream, + + clear: function () { + values(bufferSet).forEach(destroy); + streamPool.forEach(destroy); + }, + + getBuffer: function (wrapper) { + if (wrapper && wrapper._buffer instanceof REGLBuffer) { + return wrapper._buffer + } + return null + }, + + restore: restoreBuffers, + + _initBuffer: initBufferFromData + } +} + +var points = 0; +var point = 0; +var lines = 1; +var line = 1; +var triangles = 4; +var triangle = 4; +var primTypes = { + points: points, + point: point, + lines: lines, + line: line, + triangles: triangles, + triangle: triangle, + "line loop": 2, + "line strip": 3, + "triangle strip": 5, + "triangle fan": 6 +}; + +var GL_POINTS = 0; +var GL_LINES = 1; +var GL_TRIANGLES = 4; + +var GL_BYTE$2 = 5120; +var GL_UNSIGNED_BYTE$4 = 5121; +var GL_SHORT$2 = 5122; +var GL_UNSIGNED_SHORT$2 = 5123; +var GL_INT$2 = 5124; +var GL_UNSIGNED_INT$2 = 5125; + +var GL_ELEMENT_ARRAY_BUFFER = 34963; + +var GL_STREAM_DRAW$1 = 0x88E0; +var GL_STATIC_DRAW$1 = 0x88E4; + +function wrapElementsState (gl, extensions, bufferState, stats) { + var elementSet = {}; + var elementCount = 0; + + var elementTypes = { + 'uint8': GL_UNSIGNED_BYTE$4, + 'uint16': GL_UNSIGNED_SHORT$2 + }; + + if (extensions.oes_element_index_uint) { + elementTypes.uint32 = GL_UNSIGNED_INT$2; + } + + function REGLElementBuffer (buffer) { + this.id = elementCount++; + elementSet[this.id] = this; + this.buffer = buffer; + this.primType = GL_TRIANGLES; + this.vertCount = 0; + this.type = 0; + } + + REGLElementBuffer.prototype.bind = function () { + this.buffer.bind(); + }; + + var bufferPool = []; + + function createElementStream (data) { + var result = bufferPool.pop(); + if (!result) { + result = new REGLElementBuffer(bufferState.create( + null, + GL_ELEMENT_ARRAY_BUFFER, + true, + false)._buffer); + } + initElements(result, data, GL_STREAM_DRAW$1, -1, -1, 0, 0); + return result + } + + function destroyElementStream (elements) { + bufferPool.push(elements); + } + + function initElements ( + elements, + data, + usage, + prim, + count, + byteLength, + type) { + elements.buffer.bind(); + if (data) { + var predictedType = type; + if (!type && ( + !isTypedArray(data) || + (isNDArrayLike(data) && !isTypedArray(data.data)))) { + predictedType = extensions.oes_element_index_uint + ? GL_UNSIGNED_INT$2 + : GL_UNSIGNED_SHORT$2; + } + bufferState._initBuffer( + elements.buffer, + data, + usage, + predictedType, + 3); + } else { + gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, byteLength, usage); + elements.buffer.dtype = dtype || GL_UNSIGNED_BYTE$4; + elements.buffer.usage = usage; + elements.buffer.dimension = 3; + elements.buffer.byteLength = byteLength; + } + + var dtype = type; + if (!type) { + switch (elements.buffer.dtype) { + case GL_UNSIGNED_BYTE$4: + case GL_BYTE$2: + dtype = GL_UNSIGNED_BYTE$4; + break + + case GL_UNSIGNED_SHORT$2: + case GL_SHORT$2: + dtype = GL_UNSIGNED_SHORT$2; + break + + case GL_UNSIGNED_INT$2: + case GL_INT$2: + dtype = GL_UNSIGNED_INT$2; + break + + default: + check$1.raise('unsupported type for element array'); + } + elements.buffer.dtype = dtype; + } + elements.type = dtype; + + // Check oes_element_index_uint extension + check$1( + dtype !== GL_UNSIGNED_INT$2 || + !!extensions.oes_element_index_uint, + '32 bit element buffers not supported, enable oes_element_index_uint first'); + + // try to guess default primitive type and arguments + var vertCount = count; + if (vertCount < 0) { + vertCount = elements.buffer.byteLength; + if (dtype === GL_UNSIGNED_SHORT$2) { + vertCount >>= 1; + } else if (dtype === GL_UNSIGNED_INT$2) { + vertCount >>= 2; + } + } + elements.vertCount = vertCount; + + // try to guess primitive type from cell dimension + var primType = prim; + if (prim < 0) { + primType = GL_TRIANGLES; + var dimension = elements.buffer.dimension; + if (dimension === 1) primType = GL_POINTS; + if (dimension === 2) primType = GL_LINES; + if (dimension === 3) primType = GL_TRIANGLES; + } + elements.primType = primType; + } + + function destroyElements (elements) { + stats.elementsCount--; + + check$1(elements.buffer !== null, 'must not double destroy elements'); + delete elementSet[elements.id]; + elements.buffer.destroy(); + elements.buffer = null; + } + + function createElements (options, persistent) { + var buffer = bufferState.create(null, GL_ELEMENT_ARRAY_BUFFER, true); + var elements = new REGLElementBuffer(buffer._buffer); + stats.elementsCount++; + + function reglElements (options) { + if (!options) { + buffer(); + elements.primType = GL_TRIANGLES; + elements.vertCount = 0; + elements.type = GL_UNSIGNED_BYTE$4; + } else if (typeof options === 'number') { + buffer(options); + elements.primType = GL_TRIANGLES; + elements.vertCount = options | 0; + elements.type = GL_UNSIGNED_BYTE$4; + } else { + var data = null; + var usage = GL_STATIC_DRAW$1; + var primType = -1; + var vertCount = -1; + var byteLength = 0; + var dtype = 0; + if (Array.isArray(options) || + isTypedArray(options) || + isNDArrayLike(options)) { + data = options; + } else { + check$1.type(options, 'object', 'invalid arguments for elements'); + if ('data' in options) { + data = options.data; + check$1( + Array.isArray(data) || + isTypedArray(data) || + isNDArrayLike(data), + 'invalid data for element buffer'); + } + if ('usage' in options) { + check$1.parameter( + options.usage, + usageTypes, + 'invalid element buffer usage'); + usage = usageTypes[options.usage]; + } + if ('primitive' in options) { + check$1.parameter( + options.primitive, + primTypes, + 'invalid element buffer primitive'); + primType = primTypes[options.primitive]; + } + if ('count' in options) { + check$1( + typeof options.count === 'number' && options.count >= 0, + 'invalid vertex count for elements'); + vertCount = options.count | 0; + } + if ('type' in options) { + check$1.parameter( + options.type, + elementTypes, + 'invalid buffer type'); + dtype = elementTypes[options.type]; + } + if ('length' in options) { + byteLength = options.length | 0; + } else { + byteLength = vertCount; + if (dtype === GL_UNSIGNED_SHORT$2 || dtype === GL_SHORT$2) { + byteLength *= 2; + } else if (dtype === GL_UNSIGNED_INT$2 || dtype === GL_INT$2) { + byteLength *= 4; + } + } + } + initElements( + elements, + data, + usage, + primType, + vertCount, + byteLength, + dtype); + } + + return reglElements + } + + reglElements(options); + + reglElements._reglType = 'elements'; + reglElements._elements = elements; + reglElements.subdata = function (data, offset) { + buffer.subdata(data, offset); + return reglElements + }; + reglElements.destroy = function () { + destroyElements(elements); + }; + + return reglElements + } + + return { + create: createElements, + createStream: createElementStream, + destroyStream: destroyElementStream, + getElements: function (elements) { + if (typeof elements === 'function' && + elements._elements instanceof REGLElementBuffer) { + return elements._elements + } + return null + }, + clear: function () { + values(elementSet).forEach(destroyElements); + } + } +} + +var FLOAT = new Float32Array(1); +var INT = new Uint32Array(FLOAT.buffer); + +var GL_UNSIGNED_SHORT$4 = 5123; + +function convertToHalfFloat (array) { + var ushorts = pool.allocType(GL_UNSIGNED_SHORT$4, array.length); + + for (var i = 0; i < array.length; ++i) { + if (isNaN(array[i])) { + ushorts[i] = 0xffff; + } else if (array[i] === Infinity) { + ushorts[i] = 0x7c00; + } else if (array[i] === -Infinity) { + ushorts[i] = 0xfc00; + } else { + FLOAT[0] = array[i]; + var x = INT[0]; + + var sgn = (x >>> 31) << 15; + var exp = ((x << 1) >>> 24) - 127; + var frac = (x >> 13) & ((1 << 10) - 1); + + if (exp < -24) { + // round non-representable denormals to 0 + ushorts[i] = sgn; + } else if (exp < -14) { + // handle denormals + var s = -14 - exp; + ushorts[i] = sgn + ((frac + (1 << 10)) >> s); + } else if (exp > 15) { + // round overflow to +/- Infinity + ushorts[i] = sgn + 0x7c00; + } else { + // otherwise convert directly + ushorts[i] = sgn + ((exp + 15) << 10) + frac; + } + } + } + + return ushorts +} + +function isArrayLike (s) { + return Array.isArray(s) || isTypedArray(s) +} + +var isPow2$1 = function (v) { + return !(v & (v - 1)) && (!!v) +}; + +var GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3; + +var GL_TEXTURE_2D$1 = 0x0DE1; +var GL_TEXTURE_CUBE_MAP$1 = 0x8513; +var GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 = 0x8515; + +var GL_RGBA$1 = 0x1908; +var GL_ALPHA = 0x1906; +var GL_RGB = 0x1907; +var GL_LUMINANCE = 0x1909; +var GL_LUMINANCE_ALPHA = 0x190A; + +var GL_RGBA4 = 0x8056; +var GL_RGB5_A1 = 0x8057; +var GL_RGB565 = 0x8D62; + +var GL_UNSIGNED_SHORT_4_4_4_4$1 = 0x8033; +var GL_UNSIGNED_SHORT_5_5_5_1$1 = 0x8034; +var GL_UNSIGNED_SHORT_5_6_5$1 = 0x8363; +var GL_UNSIGNED_INT_24_8_WEBGL$1 = 0x84FA; + +var GL_DEPTH_COMPONENT = 0x1902; +var GL_DEPTH_STENCIL = 0x84F9; + +var GL_SRGB_EXT = 0x8C40; +var GL_SRGB_ALPHA_EXT = 0x8C42; + +var GL_HALF_FLOAT_OES$1 = 0x8D61; + +var GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; +var GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; +var GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; +var GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; + +var GL_COMPRESSED_RGB_ATC_WEBGL = 0x8C92; +var GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93; +var GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE; + +var GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; +var GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; +var GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; +var GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; + +var GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; + +var GL_UNSIGNED_BYTE$5 = 0x1401; +var GL_UNSIGNED_SHORT$3 = 0x1403; +var GL_UNSIGNED_INT$3 = 0x1405; +var GL_FLOAT$4 = 0x1406; + +var GL_TEXTURE_WRAP_S = 0x2802; +var GL_TEXTURE_WRAP_T = 0x2803; + +var GL_REPEAT = 0x2901; +var GL_CLAMP_TO_EDGE$1 = 0x812F; +var GL_MIRRORED_REPEAT = 0x8370; + +var GL_TEXTURE_MAG_FILTER = 0x2800; +var GL_TEXTURE_MIN_FILTER = 0x2801; + +var GL_NEAREST$1 = 0x2600; +var GL_LINEAR = 0x2601; +var GL_NEAREST_MIPMAP_NEAREST$1 = 0x2700; +var GL_LINEAR_MIPMAP_NEAREST$1 = 0x2701; +var GL_NEAREST_MIPMAP_LINEAR$1 = 0x2702; +var GL_LINEAR_MIPMAP_LINEAR$1 = 0x2703; + +var GL_GENERATE_MIPMAP_HINT = 0x8192; +var GL_DONT_CARE = 0x1100; +var GL_FASTEST = 0x1101; +var GL_NICEST = 0x1102; + +var GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; + +var GL_UNPACK_ALIGNMENT = 0x0CF5; +var GL_UNPACK_FLIP_Y_WEBGL = 0x9240; +var GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; +var GL_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; + +var GL_BROWSER_DEFAULT_WEBGL = 0x9244; + +var GL_TEXTURE0$1 = 0x84C0; + +var MIPMAP_FILTERS = [ + GL_NEAREST_MIPMAP_NEAREST$1, + GL_NEAREST_MIPMAP_LINEAR$1, + GL_LINEAR_MIPMAP_NEAREST$1, + GL_LINEAR_MIPMAP_LINEAR$1 +]; + +var CHANNELS_FORMAT = [ + 0, + GL_LUMINANCE, + GL_LUMINANCE_ALPHA, + GL_RGB, + GL_RGBA$1 +]; + +var FORMAT_CHANNELS = {}; +FORMAT_CHANNELS[GL_LUMINANCE] = +FORMAT_CHANNELS[GL_ALPHA] = +FORMAT_CHANNELS[GL_DEPTH_COMPONENT] = 1; +FORMAT_CHANNELS[GL_DEPTH_STENCIL] = +FORMAT_CHANNELS[GL_LUMINANCE_ALPHA] = 2; +FORMAT_CHANNELS[GL_RGB] = +FORMAT_CHANNELS[GL_SRGB_EXT] = 3; +FORMAT_CHANNELS[GL_RGBA$1] = +FORMAT_CHANNELS[GL_SRGB_ALPHA_EXT] = 4; + +function objectName (str) { + return '[object ' + str + ']' +} + +var CANVAS_CLASS = objectName('HTMLCanvasElement'); +var CONTEXT2D_CLASS = objectName('CanvasRenderingContext2D'); +var BITMAP_CLASS = objectName('ImageBitmap'); +var IMAGE_CLASS = objectName('HTMLImageElement'); +var VIDEO_CLASS = objectName('HTMLVideoElement'); + +var PIXEL_CLASSES = Object.keys(arrayTypes).concat([ + CANVAS_CLASS, + CONTEXT2D_CLASS, + BITMAP_CLASS, + IMAGE_CLASS, + VIDEO_CLASS +]); + +// for every texture type, store +// the size in bytes. +var TYPE_SIZES = []; +TYPE_SIZES[GL_UNSIGNED_BYTE$5] = 1; +TYPE_SIZES[GL_FLOAT$4] = 4; +TYPE_SIZES[GL_HALF_FLOAT_OES$1] = 2; + +TYPE_SIZES[GL_UNSIGNED_SHORT$3] = 2; +TYPE_SIZES[GL_UNSIGNED_INT$3] = 4; + +var FORMAT_SIZES_SPECIAL = []; +FORMAT_SIZES_SPECIAL[GL_RGBA4] = 2; +FORMAT_SIZES_SPECIAL[GL_RGB5_A1] = 2; +FORMAT_SIZES_SPECIAL[GL_RGB565] = 2; +FORMAT_SIZES_SPECIAL[GL_DEPTH_STENCIL] = 4; + +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_S3TC_DXT1_EXT] = 0.5; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT1_EXT] = 0.5; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT3_EXT] = 1; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT5_EXT] = 1; + +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ATC_WEBGL] = 0.5; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL] = 1; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL] = 1; + +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG] = 0.5; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG] = 0.25; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG] = 0.5; +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG] = 0.25; + +FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ETC1_WEBGL] = 0.5; + +function isNumericArray (arr) { + return ( + Array.isArray(arr) && + (arr.length === 0 || + typeof arr[0] === 'number')) +} + +function isRectArray (arr) { + if (!Array.isArray(arr)) { + return false + } + var width = arr.length; + if (width === 0 || !isArrayLike(arr[0])) { + return false + } + return true +} + +function classString (x) { + return Object.prototype.toString.call(x) +} + +function isCanvasElement (object) { + return classString(object) === CANVAS_CLASS +} + +function isContext2D (object) { + return classString(object) === CONTEXT2D_CLASS +} + +function isBitmap (object) { + return classString(object) === BITMAP_CLASS +} + +function isImageElement (object) { + return classString(object) === IMAGE_CLASS +} + +function isVideoElement (object) { + return classString(object) === VIDEO_CLASS +} + +function isPixelData (object) { + if (!object) { + return false + } + var className = classString(object); + if (PIXEL_CLASSES.indexOf(className) >= 0) { + return true + } + return ( + isNumericArray(object) || + isRectArray(object) || + isNDArrayLike(object)) +} + +function typedArrayCode$1 (data) { + return arrayTypes[Object.prototype.toString.call(data)] | 0 +} + +function convertData (result, data) { + var n = data.length; + switch (result.type) { + case GL_UNSIGNED_BYTE$5: + case GL_UNSIGNED_SHORT$3: + case GL_UNSIGNED_INT$3: + case GL_FLOAT$4: + var converted = pool.allocType(result.type, n); + converted.set(data); + result.data = converted; + break + + case GL_HALF_FLOAT_OES$1: + result.data = convertToHalfFloat(data); + break + + default: + check$1.raise('unsupported texture type, must specify a typed array'); + } +} + +function preConvert (image, n) { + return pool.allocType( + image.type === GL_HALF_FLOAT_OES$1 + ? GL_FLOAT$4 + : image.type, n) +} + +function postConvert (image, data) { + if (image.type === GL_HALF_FLOAT_OES$1) { + image.data = convertToHalfFloat(data); + pool.freeType(data); + } else { + image.data = data; + } +} + +function transposeData (image, array, strideX, strideY, strideC, offset) { + var w = image.width; + var h = image.height; + var c = image.channels; + var n = w * h * c; + var data = preConvert(image, n); + + var p = 0; + for (var i = 0; i < h; ++i) { + for (var j = 0; j < w; ++j) { + for (var k = 0; k < c; ++k) { + data[p++] = array[strideX * j + strideY * i + strideC * k + offset]; + } + } + } + + postConvert(image, data); +} + +function getTextureSize (format, type, width, height, isMipmap, isCube) { + var s; + if (typeof FORMAT_SIZES_SPECIAL[format] !== 'undefined') { + // we have a special array for dealing with weird color formats such as RGB5A1 + s = FORMAT_SIZES_SPECIAL[format]; + } else { + s = FORMAT_CHANNELS[format] * TYPE_SIZES[type]; + } + + if (isCube) { + s *= 6; + } + + if (isMipmap) { + // compute the total size of all the mipmaps. + var total = 0; + + var w = width; + while (w >= 1) { + // we can only use mipmaps on a square image, + // so we can simply use the width and ignore the height: + total += s * w * w; + w /= 2; + } + return total + } else { + return s * width * height + } +} + +function createTextureSet ( + gl, extensions, limits, reglPoll, contextState, stats, config) { + // ------------------------------------------------------- + // Initialize constants and parameter tables here + // ------------------------------------------------------- + var mipmapHint = { + "don't care": GL_DONT_CARE, + 'dont care': GL_DONT_CARE, + 'nice': GL_NICEST, + 'fast': GL_FASTEST + }; + + var wrapModes = { + 'repeat': GL_REPEAT, + 'clamp': GL_CLAMP_TO_EDGE$1, + 'mirror': GL_MIRRORED_REPEAT + }; + + var magFilters = { + 'nearest': GL_NEAREST$1, + 'linear': GL_LINEAR + }; + + var minFilters = extend({ + 'mipmap': GL_LINEAR_MIPMAP_LINEAR$1, + 'nearest mipmap nearest': GL_NEAREST_MIPMAP_NEAREST$1, + 'linear mipmap nearest': GL_LINEAR_MIPMAP_NEAREST$1, + 'nearest mipmap linear': GL_NEAREST_MIPMAP_LINEAR$1, + 'linear mipmap linear': GL_LINEAR_MIPMAP_LINEAR$1 + }, magFilters); + + var colorSpace = { + 'none': 0, + 'browser': GL_BROWSER_DEFAULT_WEBGL + }; + + var textureTypes = { + 'uint8': GL_UNSIGNED_BYTE$5, + 'rgba4': GL_UNSIGNED_SHORT_4_4_4_4$1, + 'rgb565': GL_UNSIGNED_SHORT_5_6_5$1, + 'rgb5 a1': GL_UNSIGNED_SHORT_5_5_5_1$1 + }; + + var textureFormats = { + 'alpha': GL_ALPHA, + 'luminance': GL_LUMINANCE, + 'luminance alpha': GL_LUMINANCE_ALPHA, + 'rgb': GL_RGB, + 'rgba': GL_RGBA$1, + 'rgba4': GL_RGBA4, + 'rgb5 a1': GL_RGB5_A1, + 'rgb565': GL_RGB565 + }; + + var compressedTextureFormats = {}; + + if (extensions.ext_srgb) { + textureFormats.srgb = GL_SRGB_EXT; + textureFormats.srgba = GL_SRGB_ALPHA_EXT; + } + + if (extensions.oes_texture_float) { + textureTypes.float32 = textureTypes.float = GL_FLOAT$4; + } + + if (extensions.oes_texture_half_float) { + textureTypes['float16'] = textureTypes['half float'] = GL_HALF_FLOAT_OES$1; + } + + if (extensions.webgl_depth_texture) { + extend(textureFormats, { + 'depth': GL_DEPTH_COMPONENT, + 'depth stencil': GL_DEPTH_STENCIL + }); + + extend(textureTypes, { + 'uint16': GL_UNSIGNED_SHORT$3, + 'uint32': GL_UNSIGNED_INT$3, + 'depth stencil': GL_UNSIGNED_INT_24_8_WEBGL$1 + }); + } + + if (extensions.webgl_compressed_texture_s3tc) { + extend(compressedTextureFormats, { + 'rgb s3tc dxt1': GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 'rgba s3tc dxt1': GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + 'rgba s3tc dxt3': GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + 'rgba s3tc dxt5': GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + }); + } + + if (extensions.webgl_compressed_texture_atc) { + extend(compressedTextureFormats, { + 'rgb atc': GL_COMPRESSED_RGB_ATC_WEBGL, + 'rgba atc explicit alpha': GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL, + 'rgba atc interpolated alpha': GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL + }); + } + + if (extensions.webgl_compressed_texture_pvrtc) { + extend(compressedTextureFormats, { + 'rgb pvrtc 4bppv1': GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, + 'rgb pvrtc 2bppv1': GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, + 'rgba pvrtc 4bppv1': GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, + 'rgba pvrtc 2bppv1': GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG + }); + } + + if (extensions.webgl_compressed_texture_etc1) { + compressedTextureFormats['rgb etc1'] = GL_COMPRESSED_RGB_ETC1_WEBGL; + } + + // Copy over all texture formats + var supportedCompressedFormats = Array.prototype.slice.call( + gl.getParameter(GL_COMPRESSED_TEXTURE_FORMATS)); + Object.keys(compressedTextureFormats).forEach(function (name) { + var format = compressedTextureFormats[name]; + if (supportedCompressedFormats.indexOf(format) >= 0) { + textureFormats[name] = format; + } + }); + + var supportedFormats = Object.keys(textureFormats); + limits.textureFormats = supportedFormats; + + // associate with every format string its + // corresponding GL-value. + var textureFormatsInvert = []; + Object.keys(textureFormats).forEach(function (key) { + var val = textureFormats[key]; + textureFormatsInvert[val] = key; + }); + + // associate with every type string its + // corresponding GL-value. + var textureTypesInvert = []; + Object.keys(textureTypes).forEach(function (key) { + var val = textureTypes[key]; + textureTypesInvert[val] = key; + }); + + var magFiltersInvert = []; + Object.keys(magFilters).forEach(function (key) { + var val = magFilters[key]; + magFiltersInvert[val] = key; + }); + + var minFiltersInvert = []; + Object.keys(minFilters).forEach(function (key) { + var val = minFilters[key]; + minFiltersInvert[val] = key; + }); + + var wrapModesInvert = []; + Object.keys(wrapModes).forEach(function (key) { + var val = wrapModes[key]; + wrapModesInvert[val] = key; + }); + + // colorFormats[] gives the format (channels) associated to an + // internalformat + var colorFormats = supportedFormats.reduce(function (color, key) { + var glenum = textureFormats[key]; + if (glenum === GL_LUMINANCE || + glenum === GL_ALPHA || + glenum === GL_LUMINANCE || + glenum === GL_LUMINANCE_ALPHA || + glenum === GL_DEPTH_COMPONENT || + glenum === GL_DEPTH_STENCIL) { + color[glenum] = glenum; + } else if (glenum === GL_RGB5_A1 || key.indexOf('rgba') >= 0) { + color[glenum] = GL_RGBA$1; + } else { + color[glenum] = GL_RGB; + } + return color + }, {}); + + function TexFlags () { + // format info + this.internalformat = GL_RGBA$1; + this.format = GL_RGBA$1; + this.type = GL_UNSIGNED_BYTE$5; + this.compressed = false; + + // pixel storage + this.premultiplyAlpha = false; + this.flipY = false; + this.unpackAlignment = 1; + this.colorSpace = GL_BROWSER_DEFAULT_WEBGL; + + // shape info + this.width = 0; + this.height = 0; + this.channels = 0; + } + + function copyFlags (result, other) { + result.internalformat = other.internalformat; + result.format = other.format; + result.type = other.type; + result.compressed = other.compressed; + + result.premultiplyAlpha = other.premultiplyAlpha; + result.flipY = other.flipY; + result.unpackAlignment = other.unpackAlignment; + result.colorSpace = other.colorSpace; + + result.width = other.width; + result.height = other.height; + result.channels = other.channels; + } + + function parseFlags (flags, options) { + if (typeof options !== 'object' || !options) { + return + } + + if ('premultiplyAlpha' in options) { + check$1.type(options.premultiplyAlpha, 'boolean', + 'invalid premultiplyAlpha'); + flags.premultiplyAlpha = options.premultiplyAlpha; + } + + if ('flipY' in options) { + check$1.type(options.flipY, 'boolean', + 'invalid texture flip'); + flags.flipY = options.flipY; + } + + if ('alignment' in options) { + check$1.oneOf(options.alignment, [1, 2, 4, 8], + 'invalid texture unpack alignment'); + flags.unpackAlignment = options.alignment; + } + + if ('colorSpace' in options) { + check$1.parameter(options.colorSpace, colorSpace, + 'invalid colorSpace'); + flags.colorSpace = colorSpace[options.colorSpace]; + } + + if ('type' in options) { + var type = options.type; + check$1(extensions.oes_texture_float || + !(type === 'float' || type === 'float32'), + 'you must enable the OES_texture_float extension in order to use floating point textures.'); + check$1(extensions.oes_texture_half_float || + !(type === 'half float' || type === 'float16'), + 'you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures.'); + check$1(extensions.webgl_depth_texture || + !(type === 'uint16' || type === 'uint32' || type === 'depth stencil'), + 'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.'); + check$1.parameter(type, textureTypes, + 'invalid texture type'); + flags.type = textureTypes[type]; + } + + var w = flags.width; + var h = flags.height; + var c = flags.channels; + var hasChannels = false; + if ('shape' in options) { + check$1(Array.isArray(options.shape) && options.shape.length >= 2, + 'shape must be an array'); + w = options.shape[0]; + h = options.shape[1]; + if (options.shape.length === 3) { + c = options.shape[2]; + check$1(c > 0 && c <= 4, 'invalid number of channels'); + hasChannels = true; + } + check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid width'); + check$1(h >= 0 && h <= limits.maxTextureSize, 'invalid height'); + } else { + if ('radius' in options) { + w = h = options.radius; + check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid radius'); + } + if ('width' in options) { + w = options.width; + check$1(w >= 0 && w <= limits.maxTextureSize, 'invalid width'); + } + if ('height' in options) { + h = options.height; + check$1(h >= 0 && h <= limits.maxTextureSize, 'invalid height'); + } + if ('channels' in options) { + c = options.channels; + check$1(c > 0 && c <= 4, 'invalid number of channels'); + hasChannels = true; + } + } + flags.width = w | 0; + flags.height = h | 0; + flags.channels = c | 0; + + var hasFormat = false; + if ('format' in options) { + var formatStr = options.format; + check$1(extensions.webgl_depth_texture || + !(formatStr === 'depth' || formatStr === 'depth stencil'), + 'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.'); + check$1.parameter(formatStr, textureFormats, + 'invalid texture format'); + var internalformat = flags.internalformat = textureFormats[formatStr]; + flags.format = colorFormats[internalformat]; + if (formatStr in textureTypes) { + if (!('type' in options)) { + flags.type = textureTypes[formatStr]; + } + } + if (formatStr in compressedTextureFormats) { + flags.compressed = true; + } + hasFormat = true; + } + + // Reconcile channels and format + if (!hasChannels && hasFormat) { + flags.channels = FORMAT_CHANNELS[flags.format]; + } else if (hasChannels && !hasFormat) { + if (flags.channels !== CHANNELS_FORMAT[flags.format]) { + flags.format = flags.internalformat = CHANNELS_FORMAT[flags.channels]; + } + } else if (hasFormat && hasChannels) { + check$1( + flags.channels === FORMAT_CHANNELS[flags.format], + 'number of channels inconsistent with specified format'); + } + } + + function setFlags (flags) { + gl.pixelStorei(GL_UNPACK_FLIP_Y_WEBGL, flags.flipY); + gl.pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL, flags.premultiplyAlpha); + gl.pixelStorei(GL_UNPACK_COLORSPACE_CONVERSION_WEBGL, flags.colorSpace); + gl.pixelStorei(GL_UNPACK_ALIGNMENT, flags.unpackAlignment); + } + + // ------------------------------------------------------- + // Tex image data + // ------------------------------------------------------- + function TexImage () { + TexFlags.call(this); + + this.xOffset = 0; + this.yOffset = 0; + + // data + this.data = null; + this.needsFree = false; + + // html element + this.element = null; + + // copyTexImage info + this.needsCopy = false; + } + + function parseImage (image, options) { + var data = null; + if (isPixelData(options)) { + data = options; + } else if (options) { + check$1.type(options, 'object', 'invalid pixel data type'); + parseFlags(image, options); + if ('x' in options) { + image.xOffset = options.x | 0; + } + if ('y' in options) { + image.yOffset = options.y | 0; + } + if (isPixelData(options.data)) { + data = options.data; + } + } + + check$1( + !image.compressed || + data instanceof Uint8Array, + 'compressed texture data must be stored in a uint8array'); + + if (options.copy) { + check$1(!data, 'can not specify copy and data field for the same texture'); + var viewW = contextState.viewportWidth; + var viewH = contextState.viewportHeight; + image.width = image.width || (viewW - image.xOffset); + image.height = image.height || (viewH - image.yOffset); + image.needsCopy = true; + check$1(image.xOffset >= 0 && image.xOffset < viewW && + image.yOffset >= 0 && image.yOffset < viewH && + image.width > 0 && image.width <= viewW && + image.height > 0 && image.height <= viewH, + 'copy texture read out of bounds'); + } else if (!data) { + image.width = image.width || 1; + image.height = image.height || 1; + image.channels = image.channels || 4; + } else if (isTypedArray(data)) { + image.channels = image.channels || 4; + image.data = data; + if (!('type' in options) && image.type === GL_UNSIGNED_BYTE$5) { + image.type = typedArrayCode$1(data); + } + } else if (isNumericArray(data)) { + image.channels = image.channels || 4; + convertData(image, data); + image.alignment = 1; + image.needsFree = true; + } else if (isNDArrayLike(data)) { + var array = data.data; + if (!Array.isArray(array) && image.type === GL_UNSIGNED_BYTE$5) { + image.type = typedArrayCode$1(array); + } + var shape = data.shape; + var stride = data.stride; + var shapeX, shapeY, shapeC, strideX, strideY, strideC; + if (shape.length === 3) { + shapeC = shape[2]; + strideC = stride[2]; + } else { + check$1(shape.length === 2, 'invalid ndarray pixel data, must be 2 or 3D'); + shapeC = 1; + strideC = 1; + } + shapeX = shape[0]; + shapeY = shape[1]; + strideX = stride[0]; + strideY = stride[1]; + image.alignment = 1; + image.width = shapeX; + image.height = shapeY; + image.channels = shapeC; + image.format = image.internalformat = CHANNELS_FORMAT[shapeC]; + image.needsFree = true; + transposeData(image, array, strideX, strideY, strideC, data.offset); + } else if (isCanvasElement(data) || isContext2D(data)) { + if (isCanvasElement(data)) { + image.element = data; + } else { + image.element = data.canvas; + } + image.width = image.element.width; + image.height = image.element.height; + image.channels = 4; + } else if (isBitmap(data)) { + image.element = data; + image.width = data.width; + image.height = data.height; + image.channels = 4; + } else if (isImageElement(data)) { + image.element = data; + image.width = data.naturalWidth; + image.height = data.naturalHeight; + image.channels = 4; + } else if (isVideoElement(data)) { + image.element = data; + image.width = data.videoWidth; + image.height = data.videoHeight; + image.channels = 4; + } else if (isRectArray(data)) { + var w = image.width || data[0].length; + var h = image.height || data.length; + var c = image.channels; + if (isArrayLike(data[0][0])) { + c = c || data[0][0].length; + } else { + c = c || 1; + } + var arrayShape = flattenUtils.shape(data); + var n = 1; + for (var dd = 0; dd < arrayShape.length; ++dd) { + n *= arrayShape[dd]; + } + var allocData = preConvert(image, n); + flattenUtils.flatten(data, arrayShape, '', allocData); + postConvert(image, allocData); + image.alignment = 1; + image.width = w; + image.height = h; + image.channels = c; + image.format = image.internalformat = CHANNELS_FORMAT[c]; + image.needsFree = true; + } + + if (image.type === GL_FLOAT$4) { + check$1(limits.extensions.indexOf('oes_texture_float') >= 0, + 'oes_texture_float extension not enabled'); + } else if (image.type === GL_HALF_FLOAT_OES$1) { + check$1(limits.extensions.indexOf('oes_texture_half_float') >= 0, + 'oes_texture_half_float extension not enabled'); + } + + // do compressed texture validation here. + } + + function setImage (info, target, miplevel) { + var element = info.element; + var data = info.data; + var internalformat = info.internalformat; + var format = info.format; + var type = info.type; + var width = info.width; + var height = info.height; + var channels = info.channels; + + setFlags(info); + + if (element) { + gl.texImage2D(target, miplevel, format, format, type, element); + } else if (info.compressed) { + gl.compressedTexImage2D(target, miplevel, internalformat, width, height, 0, data); + } else if (info.needsCopy) { + reglPoll(); + gl.copyTexImage2D( + target, miplevel, format, info.xOffset, info.yOffset, width, height, 0); + } else { + var nullData = !data; + if (nullData) { + data = pool.zero.allocType(type, width * height * channels); + } + + gl.texImage2D(target, miplevel, format, width, height, 0, format, type, data); + + if (nullData && data) { + pool.zero.freeType(data); + } + } + } + + function setSubImage (info, target, x, y, miplevel) { + var element = info.element; + var data = info.data; + var internalformat = info.internalformat; + var format = info.format; + var type = info.type; + var width = info.width; + var height = info.height; + + setFlags(info); + + if (element) { + gl.texSubImage2D( + target, miplevel, x, y, format, type, element); + } else if (info.compressed) { + gl.compressedTexSubImage2D( + target, miplevel, x, y, internalformat, width, height, data); + } else if (info.needsCopy) { + reglPoll(); + gl.copyTexSubImage2D( + target, miplevel, x, y, info.xOffset, info.yOffset, width, height); + } else { + gl.texSubImage2D( + target, miplevel, x, y, width, height, format, type, data); + } + } + + // texImage pool + var imagePool = []; + + function allocImage () { + return imagePool.pop() || new TexImage() + } + + function freeImage (image) { + if (image.needsFree) { + pool.freeType(image.data); + } + TexImage.call(image); + imagePool.push(image); + } + + // ------------------------------------------------------- + // Mip map + // ------------------------------------------------------- + function MipMap () { + TexFlags.call(this); + + this.genMipmaps = false; + this.mipmapHint = GL_DONT_CARE; + this.mipmask = 0; + this.images = Array(16); + } + + function parseMipMapFromShape (mipmap, width, height) { + var img = mipmap.images[0] = allocImage(); + mipmap.mipmask = 1; + img.width = mipmap.width = width; + img.height = mipmap.height = height; + img.channels = mipmap.channels = 4; + } + + function parseMipMapFromObject (mipmap, options) { + var imgData = null; + if (isPixelData(options)) { + imgData = mipmap.images[0] = allocImage(); + copyFlags(imgData, mipmap); + parseImage(imgData, options); + mipmap.mipmask = 1; + } else { + parseFlags(mipmap, options); + if (Array.isArray(options.mipmap)) { + var mipData = options.mipmap; + for (var i = 0; i < mipData.length; ++i) { + imgData = mipmap.images[i] = allocImage(); + copyFlags(imgData, mipmap); + imgData.width >>= i; + imgData.height >>= i; + parseImage(imgData, mipData[i]); + mipmap.mipmask |= (1 << i); + } + } else { + imgData = mipmap.images[0] = allocImage(); + copyFlags(imgData, mipmap); + parseImage(imgData, options); + mipmap.mipmask = 1; + } + } + copyFlags(mipmap, mipmap.images[0]); + + // For textures of the compressed format WEBGL_compressed_texture_s3tc + // we must have that + // + // "When level equals zero width and height must be a multiple of 4. + // When level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4. " + // + // but we do not yet support having multiple mipmap levels for compressed textures, + // so we only test for level zero. + + if (mipmap.compressed && + (mipmap.internalformat === GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || + (mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || + (mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || + (mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) { + check$1(mipmap.width % 4 === 0 && + mipmap.height % 4 === 0, + 'for compressed texture formats, mipmap level 0 must have width and height that are a multiple of 4'); + } + } + + function setMipMap (mipmap, target) { + var images = mipmap.images; + for (var i = 0; i < images.length; ++i) { + if (!images[i]) { + return + } + setImage(images[i], target, i); + } + } + + var mipPool = []; + + function allocMipMap () { + var result = mipPool.pop() || new MipMap(); + TexFlags.call(result); + result.mipmask = 0; + for (var i = 0; i < 16; ++i) { + result.images[i] = null; + } + return result + } + + function freeMipMap (mipmap) { + var images = mipmap.images; + for (var i = 0; i < images.length; ++i) { + if (images[i]) { + freeImage(images[i]); + } + images[i] = null; + } + mipPool.push(mipmap); + } + + // ------------------------------------------------------- + // Tex info + // ------------------------------------------------------- + function TexInfo () { + this.minFilter = GL_NEAREST$1; + this.magFilter = GL_NEAREST$1; + + this.wrapS = GL_CLAMP_TO_EDGE$1; + this.wrapT = GL_CLAMP_TO_EDGE$1; + + this.anisotropic = 1; + + this.genMipmaps = false; + this.mipmapHint = GL_DONT_CARE; + } + + function parseTexInfo (info, options) { + if ('min' in options) { + var minFilter = options.min; + check$1.parameter(minFilter, minFilters); + info.minFilter = minFilters[minFilter]; + if (MIPMAP_FILTERS.indexOf(info.minFilter) >= 0 && !('faces' in options)) { + info.genMipmaps = true; + } + } + + if ('mag' in options) { + var magFilter = options.mag; + check$1.parameter(magFilter, magFilters); + info.magFilter = magFilters[magFilter]; + } + + var wrapS = info.wrapS; + var wrapT = info.wrapT; + if ('wrap' in options) { + var wrap = options.wrap; + if (typeof wrap === 'string') { + check$1.parameter(wrap, wrapModes); + wrapS = wrapT = wrapModes[wrap]; + } else if (Array.isArray(wrap)) { + check$1.parameter(wrap[0], wrapModes); + check$1.parameter(wrap[1], wrapModes); + wrapS = wrapModes[wrap[0]]; + wrapT = wrapModes[wrap[1]]; + } + } else { + if ('wrapS' in options) { + var optWrapS = options.wrapS; + check$1.parameter(optWrapS, wrapModes); + wrapS = wrapModes[optWrapS]; + } + if ('wrapT' in options) { + var optWrapT = options.wrapT; + check$1.parameter(optWrapT, wrapModes); + wrapT = wrapModes[optWrapT]; + } + } + info.wrapS = wrapS; + info.wrapT = wrapT; + + if ('anisotropic' in options) { + var anisotropic = options.anisotropic; + check$1(typeof anisotropic === 'number' && + anisotropic >= 1 && anisotropic <= limits.maxAnisotropic, + 'aniso samples must be between 1 and '); + info.anisotropic = options.anisotropic; + } + + if ('mipmap' in options) { + var hasMipMap = false; + switch (typeof options.mipmap) { + case 'string': + check$1.parameter(options.mipmap, mipmapHint, + 'invalid mipmap hint'); + info.mipmapHint = mipmapHint[options.mipmap]; + info.genMipmaps = true; + hasMipMap = true; + break + + case 'boolean': + hasMipMap = info.genMipmaps = options.mipmap; + break + + case 'object': + check$1(Array.isArray(options.mipmap), 'invalid mipmap type'); + info.genMipmaps = false; + hasMipMap = true; + break + + default: + check$1.raise('invalid mipmap type'); + } + if (hasMipMap && !('min' in options)) { + info.minFilter = GL_NEAREST_MIPMAP_NEAREST$1; + } + } + } + + function setTexInfo (info, target) { + gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, info.minFilter); + gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, info.magFilter); + gl.texParameteri(target, GL_TEXTURE_WRAP_S, info.wrapS); + gl.texParameteri(target, GL_TEXTURE_WRAP_T, info.wrapT); + if (extensions.ext_texture_filter_anisotropic) { + gl.texParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, info.anisotropic); + } + if (info.genMipmaps) { + gl.hint(GL_GENERATE_MIPMAP_HINT, info.mipmapHint); + gl.generateMipmap(target); + } + } + + // ------------------------------------------------------- + // Full texture object + // ------------------------------------------------------- + var textureCount = 0; + var textureSet = {}; + var numTexUnits = limits.maxTextureUnits; + var textureUnits = Array(numTexUnits).map(function () { + return null + }); + + function REGLTexture (target) { + TexFlags.call(this); + this.mipmask = 0; + this.internalformat = GL_RGBA$1; + + this.id = textureCount++; + + this.refCount = 1; + + this.target = target; + this.texture = gl.createTexture(); + + this.unit = -1; + this.bindCount = 0; + + this.texInfo = new TexInfo(); + + if (config.profile) { + this.stats = {size: 0}; + } + } + + function tempBind (texture) { + gl.activeTexture(GL_TEXTURE0$1); + gl.bindTexture(texture.target, texture.texture); + } + + function tempRestore () { + var prev = textureUnits[0]; + if (prev) { + gl.bindTexture(prev.target, prev.texture); + } else { + gl.bindTexture(GL_TEXTURE_2D$1, null); + } + } + + function destroy (texture) { + var handle = texture.texture; + check$1(handle, 'must not double destroy texture'); + var unit = texture.unit; + var target = texture.target; + if (unit >= 0) { + gl.activeTexture(GL_TEXTURE0$1 + unit); + gl.bindTexture(target, null); + textureUnits[unit] = null; + } + gl.deleteTexture(handle); + texture.texture = null; + texture.params = null; + texture.pixels = null; + texture.refCount = 0; + delete textureSet[texture.id]; + stats.textureCount--; + } + + extend(REGLTexture.prototype, { + bind: function () { + var texture = this; + texture.bindCount += 1; + var unit = texture.unit; + if (unit < 0) { + for (var i = 0; i < numTexUnits; ++i) { + var other = textureUnits[i]; + if (other) { + if (other.bindCount > 0) { + continue + } + other.unit = -1; + } + textureUnits[i] = texture; + unit = i; + break + } + if (unit >= numTexUnits) { + check$1.raise('insufficient number of texture units'); + } + if (config.profile && stats.maxTextureUnits < (unit + 1)) { + stats.maxTextureUnits = unit + 1; // +1, since the units are zero-based + } + texture.unit = unit; + gl.activeTexture(GL_TEXTURE0$1 + unit); + gl.bindTexture(texture.target, texture.texture); + } + return unit + }, + + unbind: function () { + this.bindCount -= 1; + }, + + decRef: function () { + if (--this.refCount <= 0) { + destroy(this); + } + } + }); + + function createTexture2D (a, b) { + var texture = new REGLTexture(GL_TEXTURE_2D$1); + textureSet[texture.id] = texture; + stats.textureCount++; + + function reglTexture2D (a, b) { + var texInfo = texture.texInfo; + TexInfo.call(texInfo); + var mipData = allocMipMap(); + + if (typeof a === 'number') { + if (typeof b === 'number') { + parseMipMapFromShape(mipData, a | 0, b | 0); + } else { + parseMipMapFromShape(mipData, a | 0, a | 0); + } + } else if (a) { + check$1.type(a, 'object', 'invalid arguments to regl.texture'); + parseTexInfo(texInfo, a); + parseMipMapFromObject(mipData, a); + } else { + // empty textures get assigned a default shape of 1x1 + parseMipMapFromShape(mipData, 1, 1); + } + + if (texInfo.genMipmaps) { + mipData.mipmask = (mipData.width << 1) - 1; + } + texture.mipmask = mipData.mipmask; + + copyFlags(texture, mipData); + + check$1.texture2D(texInfo, mipData, limits); + texture.internalformat = mipData.internalformat; + + reglTexture2D.width = mipData.width; + reglTexture2D.height = mipData.height; + + tempBind(texture); + setMipMap(mipData, GL_TEXTURE_2D$1); + setTexInfo(texInfo, GL_TEXTURE_2D$1); + tempRestore(); + + freeMipMap(mipData); + + if (config.profile) { + texture.stats.size = getTextureSize( + texture.internalformat, + texture.type, + mipData.width, + mipData.height, + texInfo.genMipmaps, + false); + } + reglTexture2D.format = textureFormatsInvert[texture.internalformat]; + reglTexture2D.type = textureTypesInvert[texture.type]; + + reglTexture2D.mag = magFiltersInvert[texInfo.magFilter]; + reglTexture2D.min = minFiltersInvert[texInfo.minFilter]; + + reglTexture2D.wrapS = wrapModesInvert[texInfo.wrapS]; + reglTexture2D.wrapT = wrapModesInvert[texInfo.wrapT]; + + return reglTexture2D + } + + function subimage (image, x_, y_, level_) { + check$1(!!image, 'must specify image data'); + + var x = x_ | 0; + var y = y_ | 0; + var level = level_ | 0; + + var imageData = allocImage(); + copyFlags(imageData, texture); + imageData.width = 0; + imageData.height = 0; + parseImage(imageData, image); + imageData.width = imageData.width || ((texture.width >> level) - x); + imageData.height = imageData.height || ((texture.height >> level) - y); + + check$1( + texture.type === imageData.type && + texture.format === imageData.format && + texture.internalformat === imageData.internalformat, + 'incompatible format for texture.subimage'); + check$1( + x >= 0 && y >= 0 && + x + imageData.width <= texture.width && + y + imageData.height <= texture.height, + 'texture.subimage write out of bounds'); + check$1( + texture.mipmask & (1 << level), + 'missing mipmap data'); + check$1( + imageData.data || imageData.element || imageData.needsCopy, + 'missing image data'); + + tempBind(texture); + setSubImage(imageData, GL_TEXTURE_2D$1, x, y, level); + tempRestore(); + + freeImage(imageData); + + return reglTexture2D + } + + function resize (w_, h_) { + var w = w_ | 0; + var h = (h_ | 0) || w; + if (w === texture.width && h === texture.height) { + return reglTexture2D + } + + reglTexture2D.width = texture.width = w; + reglTexture2D.height = texture.height = h; + + tempBind(texture); + + var data; + var channels = texture.channels; + var type = texture.type; + + for (var i = 0; texture.mipmask >> i; ++i) { + var _w = w >> i; + var _h = h >> i; + if (!_w || !_h) break + data = pool.zero.allocType(type, _w * _h * channels); + gl.texImage2D( + GL_TEXTURE_2D$1, + i, + texture.format, + _w, + _h, + 0, + texture.format, + texture.type, + data); + if (data) pool.zero.freeType(data); + } + tempRestore(); + + // also, recompute the texture size. + if (config.profile) { + texture.stats.size = getTextureSize( + texture.internalformat, + texture.type, + w, + h, + false, + false); + } + + return reglTexture2D + } + + reglTexture2D(a, b); + + reglTexture2D.subimage = subimage; + reglTexture2D.resize = resize; + reglTexture2D._reglType = 'texture2d'; + reglTexture2D._texture = texture; + if (config.profile) { + reglTexture2D.stats = texture.stats; + } + reglTexture2D.destroy = function () { + texture.decRef(); + }; + + return reglTexture2D + } + + function createTextureCube (a0, a1, a2, a3, a4, a5) { + var texture = new REGLTexture(GL_TEXTURE_CUBE_MAP$1); + textureSet[texture.id] = texture; + stats.cubeCount++; + + var faces = new Array(6); + + function reglTextureCube (a0, a1, a2, a3, a4, a5) { + var i; + var texInfo = texture.texInfo; + TexInfo.call(texInfo); + for (i = 0; i < 6; ++i) { + faces[i] = allocMipMap(); + } + + if (typeof a0 === 'number' || !a0) { + var s = (a0 | 0) || 1; + for (i = 0; i < 6; ++i) { + parseMipMapFromShape(faces[i], s, s); + } + } else if (typeof a0 === 'object') { + if (a1) { + parseMipMapFromObject(faces[0], a0); + parseMipMapFromObject(faces[1], a1); + parseMipMapFromObject(faces[2], a2); + parseMipMapFromObject(faces[3], a3); + parseMipMapFromObject(faces[4], a4); + parseMipMapFromObject(faces[5], a5); + } else { + parseTexInfo(texInfo, a0); + parseFlags(texture, a0); + if ('faces' in a0) { + var face_input = a0.faces; + check$1(Array.isArray(face_input) && face_input.length === 6, + 'cube faces must be a length 6 array'); + for (i = 0; i < 6; ++i) { + check$1(typeof face_input[i] === 'object' && !!face_input[i], + 'invalid input for cube map face'); + copyFlags(faces[i], texture); + parseMipMapFromObject(faces[i], face_input[i]); + } + } else { + for (i = 0; i < 6; ++i) { + parseMipMapFromObject(faces[i], a0); + } + } + } + } else { + check$1.raise('invalid arguments to cube map'); + } + + copyFlags(texture, faces[0]); + + if (!limits.npotTextureCube) { + check$1(isPow2$1(texture.width) && isPow2$1(texture.height), 'your browser does not support non power or two texture dimensions'); + } + + if (texInfo.genMipmaps) { + texture.mipmask = (faces[0].width << 1) - 1; + } else { + texture.mipmask = faces[0].mipmask; + } + + check$1.textureCube(texture, texInfo, faces, limits); + texture.internalformat = faces[0].internalformat; + + reglTextureCube.width = faces[0].width; + reglTextureCube.height = faces[0].height; + + tempBind(texture); + for (i = 0; i < 6; ++i) { + setMipMap(faces[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + i); + } + setTexInfo(texInfo, GL_TEXTURE_CUBE_MAP$1); + tempRestore(); + + if (config.profile) { + texture.stats.size = getTextureSize( + texture.internalformat, + texture.type, + reglTextureCube.width, + reglTextureCube.height, + texInfo.genMipmaps, + true); + } + + reglTextureCube.format = textureFormatsInvert[texture.internalformat]; + reglTextureCube.type = textureTypesInvert[texture.type]; + + reglTextureCube.mag = magFiltersInvert[texInfo.magFilter]; + reglTextureCube.min = minFiltersInvert[texInfo.minFilter]; + + reglTextureCube.wrapS = wrapModesInvert[texInfo.wrapS]; + reglTextureCube.wrapT = wrapModesInvert[texInfo.wrapT]; + + for (i = 0; i < 6; ++i) { + freeMipMap(faces[i]); + } + + return reglTextureCube + } + + function subimage (face, image, x_, y_, level_) { + check$1(!!image, 'must specify image data'); + check$1(typeof face === 'number' && face === (face | 0) && + face >= 0 && face < 6, 'invalid face'); + + var x = x_ | 0; + var y = y_ | 0; + var level = level_ | 0; + + var imageData = allocImage(); + copyFlags(imageData, texture); + imageData.width = 0; + imageData.height = 0; + parseImage(imageData, image); + imageData.width = imageData.width || ((texture.width >> level) - x); + imageData.height = imageData.height || ((texture.height >> level) - y); + + check$1( + texture.type === imageData.type && + texture.format === imageData.format && + texture.internalformat === imageData.internalformat, + 'incompatible format for texture.subimage'); + check$1( + x >= 0 && y >= 0 && + x + imageData.width <= texture.width && + y + imageData.height <= texture.height, + 'texture.subimage write out of bounds'); + check$1( + texture.mipmask & (1 << level), + 'missing mipmap data'); + check$1( + imageData.data || imageData.element || imageData.needsCopy, + 'missing image data'); + + tempBind(texture); + setSubImage(imageData, GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + face, x, y, level); + tempRestore(); + + freeImage(imageData); + + return reglTextureCube + } + + function resize (radius_) { + var radius = radius_ | 0; + if (radius === texture.width) { + return + } + + reglTextureCube.width = texture.width = radius; + reglTextureCube.height = texture.height = radius; + + tempBind(texture); + for (var i = 0; i < 6; ++i) { + for (var j = 0; texture.mipmask >> j; ++j) { + gl.texImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + i, + j, + texture.format, + radius >> j, + radius >> j, + 0, + texture.format, + texture.type, + null); + } + } + tempRestore(); + + if (config.profile) { + texture.stats.size = getTextureSize( + texture.internalformat, + texture.type, + reglTextureCube.width, + reglTextureCube.height, + false, + true); + } + + return reglTextureCube + } + + reglTextureCube(a0, a1, a2, a3, a4, a5); + + reglTextureCube.subimage = subimage; + reglTextureCube.resize = resize; + reglTextureCube._reglType = 'textureCube'; + reglTextureCube._texture = texture; + if (config.profile) { + reglTextureCube.stats = texture.stats; + } + reglTextureCube.destroy = function () { + texture.decRef(); + }; + + return reglTextureCube + } + + // Called when regl is destroyed + function destroyTextures () { + for (var i = 0; i < numTexUnits; ++i) { + gl.activeTexture(GL_TEXTURE0$1 + i); + gl.bindTexture(GL_TEXTURE_2D$1, null); + textureUnits[i] = null; + } + values(textureSet).forEach(destroy); + + stats.cubeCount = 0; + stats.textureCount = 0; + } + + if (config.profile) { + stats.getTotalTextureSize = function () { + var total = 0; + Object.keys(textureSet).forEach(function (key) { + total += textureSet[key].stats.size; + }); + return total + }; + } + + function restoreTextures () { + values(textureSet).forEach(function (texture) { + texture.texture = gl.createTexture(); + gl.bindTexture(texture.target, texture.texture); + for (var i = 0; i < 32; ++i) { + if ((texture.mipmask & (1 << i)) === 0) { + continue + } + if (texture.target === GL_TEXTURE_2D$1) { + gl.texImage2D(GL_TEXTURE_2D$1, + i, + texture.internalformat, + texture.width >> i, + texture.height >> i, + 0, + texture.internalformat, + texture.type, + null); + } else { + for (var j = 0; j < 6; ++j) { + gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 + j, + i, + texture.internalformat, + texture.width >> i, + texture.height >> i, + 0, + texture.internalformat, + texture.type, + null); + } + } + } + setTexInfo(texture.texInfo, texture.target); + }); + } + + return { + create2D: createTexture2D, + createCube: createTextureCube, + clear: destroyTextures, + getTexture: function (wrapper) { + return null + }, + restore: restoreTextures + } +} + +var GL_RENDERBUFFER = 0x8D41; + +var GL_RGBA4$1 = 0x8056; +var GL_RGB5_A1$1 = 0x8057; +var GL_RGB565$1 = 0x8D62; +var GL_DEPTH_COMPONENT16 = 0x81A5; +var GL_STENCIL_INDEX8 = 0x8D48; +var GL_DEPTH_STENCIL$1 = 0x84F9; + +var GL_SRGB8_ALPHA8_EXT = 0x8C43; + +var GL_RGBA32F_EXT = 0x8814; + +var GL_RGBA16F_EXT = 0x881A; +var GL_RGB16F_EXT = 0x881B; + +var FORMAT_SIZES = []; + +FORMAT_SIZES[GL_RGBA4$1] = 2; +FORMAT_SIZES[GL_RGB5_A1$1] = 2; +FORMAT_SIZES[GL_RGB565$1] = 2; + +FORMAT_SIZES[GL_DEPTH_COMPONENT16] = 2; +FORMAT_SIZES[GL_STENCIL_INDEX8] = 1; +FORMAT_SIZES[GL_DEPTH_STENCIL$1] = 4; + +FORMAT_SIZES[GL_SRGB8_ALPHA8_EXT] = 4; +FORMAT_SIZES[GL_RGBA32F_EXT] = 16; +FORMAT_SIZES[GL_RGBA16F_EXT] = 8; +FORMAT_SIZES[GL_RGB16F_EXT] = 6; + +function getRenderbufferSize (format, width, height) { + return FORMAT_SIZES[format] * width * height +} + +var wrapRenderbuffers = function (gl, extensions, limits, stats, config) { + var formatTypes = { + 'rgba4': GL_RGBA4$1, + 'rgb565': GL_RGB565$1, + 'rgb5 a1': GL_RGB5_A1$1, + 'depth': GL_DEPTH_COMPONENT16, + 'stencil': GL_STENCIL_INDEX8, + 'depth stencil': GL_DEPTH_STENCIL$1 + }; + + if (extensions.ext_srgb) { + formatTypes['srgba'] = GL_SRGB8_ALPHA8_EXT; + } + + if (extensions.ext_color_buffer_half_float) { + formatTypes['rgba16f'] = GL_RGBA16F_EXT; + formatTypes['rgb16f'] = GL_RGB16F_EXT; + } + + if (extensions.webgl_color_buffer_float) { + formatTypes['rgba32f'] = GL_RGBA32F_EXT; + } + + var formatTypesInvert = []; + Object.keys(formatTypes).forEach(function (key) { + var val = formatTypes[key]; + formatTypesInvert[val] = key; + }); + + var renderbufferCount = 0; + var renderbufferSet = {}; + + function REGLRenderbuffer (renderbuffer) { + this.id = renderbufferCount++; + this.refCount = 1; + + this.renderbuffer = renderbuffer; + + this.format = GL_RGBA4$1; + this.width = 0; + this.height = 0; + + if (config.profile) { + this.stats = {size: 0}; + } + } + + REGLRenderbuffer.prototype.decRef = function () { + if (--this.refCount <= 0) { + destroy(this); + } + }; + + function destroy (rb) { + var handle = rb.renderbuffer; + check$1(handle, 'must not double destroy renderbuffer'); + gl.bindRenderbuffer(GL_RENDERBUFFER, null); + gl.deleteRenderbuffer(handle); + rb.renderbuffer = null; + rb.refCount = 0; + delete renderbufferSet[rb.id]; + stats.renderbufferCount--; + } + + function createRenderbuffer (a, b) { + var renderbuffer = new REGLRenderbuffer(gl.createRenderbuffer()); + renderbufferSet[renderbuffer.id] = renderbuffer; + stats.renderbufferCount++; + + function reglRenderbuffer (a, b) { + var w = 0; + var h = 0; + var format = GL_RGBA4$1; + + if (typeof a === 'object' && a) { + var options = a; + if ('shape' in options) { + var shape = options.shape; + check$1(Array.isArray(shape) && shape.length >= 2, + 'invalid renderbuffer shape'); + w = shape[0] | 0; + h = shape[1] | 0; + } else { + if ('radius' in options) { + w = h = options.radius | 0; + } + if ('width' in options) { + w = options.width | 0; + } + if ('height' in options) { + h = options.height | 0; + } + } + if ('format' in options) { + check$1.parameter(options.format, formatTypes, + 'invalid renderbuffer format'); + format = formatTypes[options.format]; + } + } else if (typeof a === 'number') { + w = a | 0; + if (typeof b === 'number') { + h = b | 0; + } else { + h = w; + } + } else if (!a) { + w = h = 1; + } else { + check$1.raise('invalid arguments to renderbuffer constructor'); + } + + // check shape + check$1( + w > 0 && h > 0 && + w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize, + 'invalid renderbuffer size'); + + if (w === renderbuffer.width && + h === renderbuffer.height && + format === renderbuffer.format) { + return + } + + reglRenderbuffer.width = renderbuffer.width = w; + reglRenderbuffer.height = renderbuffer.height = h; + renderbuffer.format = format; + + gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer); + gl.renderbufferStorage(GL_RENDERBUFFER, format, w, h); + + check$1( + gl.getError() === 0, + 'invalid render buffer format'); + + if (config.profile) { + renderbuffer.stats.size = getRenderbufferSize(renderbuffer.format, renderbuffer.width, renderbuffer.height); + } + reglRenderbuffer.format = formatTypesInvert[renderbuffer.format]; + + return reglRenderbuffer + } + + function resize (w_, h_) { + var w = w_ | 0; + var h = (h_ | 0) || w; + + if (w === renderbuffer.width && h === renderbuffer.height) { + return reglRenderbuffer + } + + // check shape + check$1( + w > 0 && h > 0 && + w <= limits.maxRenderbufferSize && h <= limits.maxRenderbufferSize, + 'invalid renderbuffer size'); + + reglRenderbuffer.width = renderbuffer.width = w; + reglRenderbuffer.height = renderbuffer.height = h; + + gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer.renderbuffer); + gl.renderbufferStorage(GL_RENDERBUFFER, renderbuffer.format, w, h); + + check$1( + gl.getError() === 0, + 'invalid render buffer format'); + + // also, recompute size. + if (config.profile) { + renderbuffer.stats.size = getRenderbufferSize( + renderbuffer.format, renderbuffer.width, renderbuffer.height); + } + + return reglRenderbuffer + } + + reglRenderbuffer(a, b); + + reglRenderbuffer.resize = resize; + reglRenderbuffer._reglType = 'renderbuffer'; + reglRenderbuffer._renderbuffer = renderbuffer; + if (config.profile) { + reglRenderbuffer.stats = renderbuffer.stats; + } + reglRenderbuffer.destroy = function () { + renderbuffer.decRef(); + }; + + return reglRenderbuffer + } + + if (config.profile) { + stats.getTotalRenderbufferSize = function () { + var total = 0; + Object.keys(renderbufferSet).forEach(function (key) { + total += renderbufferSet[key].stats.size; + }); + return total + }; + } + + function restoreRenderbuffers () { + values(renderbufferSet).forEach(function (rb) { + rb.renderbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(GL_RENDERBUFFER, rb.renderbuffer); + gl.renderbufferStorage(GL_RENDERBUFFER, rb.format, rb.width, rb.height); + }); + gl.bindRenderbuffer(GL_RENDERBUFFER, null); + } + + return { + create: createRenderbuffer, + clear: function () { + values(renderbufferSet).forEach(destroy); + }, + restore: restoreRenderbuffers + } +}; + +// We store these constants so that the minifier can inline them +var GL_FRAMEBUFFER$1 = 0x8D40; +var GL_RENDERBUFFER$1 = 0x8D41; + +var GL_TEXTURE_2D$2 = 0x0DE1; +var GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 = 0x8515; + +var GL_COLOR_ATTACHMENT0$1 = 0x8CE0; +var GL_DEPTH_ATTACHMENT = 0x8D00; +var GL_STENCIL_ATTACHMENT = 0x8D20; +var GL_DEPTH_STENCIL_ATTACHMENT = 0x821A; + +var GL_FRAMEBUFFER_COMPLETE$1 = 0x8CD5; +var GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; +var GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; +var GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; +var GL_FRAMEBUFFER_UNSUPPORTED = 0x8CDD; + +var GL_HALF_FLOAT_OES$2 = 0x8D61; +var GL_UNSIGNED_BYTE$6 = 0x1401; +var GL_FLOAT$5 = 0x1406; + +var GL_RGB$1 = 0x1907; +var GL_RGBA$2 = 0x1908; + +var GL_DEPTH_COMPONENT$1 = 0x1902; + +var colorTextureFormatEnums = [ + GL_RGB$1, + GL_RGBA$2 +]; + +// for every texture format, store +// the number of channels +var textureFormatChannels = []; +textureFormatChannels[GL_RGBA$2] = 4; +textureFormatChannels[GL_RGB$1] = 3; + +// for every texture type, store +// the size in bytes. +var textureTypeSizes = []; +textureTypeSizes[GL_UNSIGNED_BYTE$6] = 1; +textureTypeSizes[GL_FLOAT$5] = 4; +textureTypeSizes[GL_HALF_FLOAT_OES$2] = 2; + +var GL_RGBA4$2 = 0x8056; +var GL_RGB5_A1$2 = 0x8057; +var GL_RGB565$2 = 0x8D62; +var GL_DEPTH_COMPONENT16$1 = 0x81A5; +var GL_STENCIL_INDEX8$1 = 0x8D48; +var GL_DEPTH_STENCIL$2 = 0x84F9; + +var GL_SRGB8_ALPHA8_EXT$1 = 0x8C43; + +var GL_RGBA32F_EXT$1 = 0x8814; + +var GL_RGBA16F_EXT$1 = 0x881A; +var GL_RGB16F_EXT$1 = 0x881B; + +var colorRenderbufferFormatEnums = [ + GL_RGBA4$2, + GL_RGB5_A1$2, + GL_RGB565$2, + GL_SRGB8_ALPHA8_EXT$1, + GL_RGBA16F_EXT$1, + GL_RGB16F_EXT$1, + GL_RGBA32F_EXT$1 +]; + +var statusCode = {}; +statusCode[GL_FRAMEBUFFER_COMPLETE$1] = 'complete'; +statusCode[GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT] = 'incomplete attachment'; +statusCode[GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS] = 'incomplete dimensions'; +statusCode[GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT] = 'incomplete, missing attachment'; +statusCode[GL_FRAMEBUFFER_UNSUPPORTED] = 'unsupported'; + +function wrapFBOState ( + gl, + extensions, + limits, + textureState, + renderbufferState, + stats) { + var framebufferState = { + cur: null, + next: null, + dirty: false, + setFBO: null + }; + + var colorTextureFormats = ['rgba']; + var colorRenderbufferFormats = ['rgba4', 'rgb565', 'rgb5 a1']; + + if (extensions.ext_srgb) { + colorRenderbufferFormats.push('srgba'); + } + + if (extensions.ext_color_buffer_half_float) { + colorRenderbufferFormats.push('rgba16f', 'rgb16f'); + } + + if (extensions.webgl_color_buffer_float) { + colorRenderbufferFormats.push('rgba32f'); + } + + var colorTypes = ['uint8']; + if (extensions.oes_texture_half_float) { + colorTypes.push('half float', 'float16'); + } + if (extensions.oes_texture_float) { + colorTypes.push('float', 'float32'); + } + + function FramebufferAttachment (target, texture, renderbuffer) { + this.target = target; + this.texture = texture; + this.renderbuffer = renderbuffer; + + var w = 0; + var h = 0; + if (texture) { + w = texture.width; + h = texture.height; + } else if (renderbuffer) { + w = renderbuffer.width; + h = renderbuffer.height; + } + this.width = w; + this.height = h; + } + + function decRef (attachment) { + if (attachment) { + if (attachment.texture) { + attachment.texture._texture.decRef(); + } + if (attachment.renderbuffer) { + attachment.renderbuffer._renderbuffer.decRef(); + } + } + } + + function incRefAndCheckShape (attachment, width, height) { + if (!attachment) { + return + } + if (attachment.texture) { + var texture = attachment.texture._texture; + var tw = Math.max(1, texture.width); + var th = Math.max(1, texture.height); + check$1(tw === width && th === height, + 'inconsistent width/height for supplied texture'); + texture.refCount += 1; + } else { + var renderbuffer = attachment.renderbuffer._renderbuffer; + check$1( + renderbuffer.width === width && renderbuffer.height === height, + 'inconsistent width/height for renderbuffer'); + renderbuffer.refCount += 1; + } + } + + function attach (location, attachment) { + if (attachment) { + if (attachment.texture) { + gl.framebufferTexture2D( + GL_FRAMEBUFFER$1, + location, + attachment.target, + attachment.texture._texture.texture, + 0); + } else { + gl.framebufferRenderbuffer( + GL_FRAMEBUFFER$1, + location, + GL_RENDERBUFFER$1, + attachment.renderbuffer._renderbuffer.renderbuffer); + } + } + } + + function parseAttachment (attachment) { + var target = GL_TEXTURE_2D$2; + var texture = null; + var renderbuffer = null; + + var data = attachment; + if (typeof attachment === 'object') { + data = attachment.data; + if ('target' in attachment) { + target = attachment.target | 0; + } + } + + check$1.type(data, 'function', 'invalid attachment data'); + + var type = data._reglType; + if (type === 'texture2d') { + texture = data; + check$1(target === GL_TEXTURE_2D$2); + } else if (type === 'textureCube') { + texture = data; + check$1( + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 && + target < GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 + 6, + 'invalid cube map target'); + } else if (type === 'renderbuffer') { + renderbuffer = data; + target = GL_RENDERBUFFER$1; + } else { + check$1.raise('invalid regl object for attachment'); + } + + return new FramebufferAttachment(target, texture, renderbuffer) + } + + function allocAttachment ( + width, + height, + isTexture, + format, + type) { + if (isTexture) { + var texture = textureState.create2D({ + width: width, + height: height, + format: format, + type: type + }); + texture._texture.refCount = 0; + return new FramebufferAttachment(GL_TEXTURE_2D$2, texture, null) + } else { + var rb = renderbufferState.create({ + width: width, + height: height, + format: format + }); + rb._renderbuffer.refCount = 0; + return new FramebufferAttachment(GL_RENDERBUFFER$1, null, rb) + } + } + + function unwrapAttachment (attachment) { + return attachment && (attachment.texture || attachment.renderbuffer) + } + + function resizeAttachment (attachment, w, h) { + if (attachment) { + if (attachment.texture) { + attachment.texture.resize(w, h); + } else if (attachment.renderbuffer) { + attachment.renderbuffer.resize(w, h); + } + } + } + + var framebufferCount = 0; + var framebufferSet = {}; + + function REGLFramebuffer () { + this.id = framebufferCount++; + framebufferSet[this.id] = this; + + this.framebuffer = gl.createFramebuffer(); + this.width = 0; + this.height = 0; + + this.colorAttachments = []; + this.depthAttachment = null; + this.stencilAttachment = null; + this.depthStencilAttachment = null; + } + + function decFBORefs (framebuffer) { + framebuffer.colorAttachments.forEach(decRef); + decRef(framebuffer.depthAttachment); + decRef(framebuffer.stencilAttachment); + decRef(framebuffer.depthStencilAttachment); + } + + function destroy (framebuffer) { + var handle = framebuffer.framebuffer; + check$1(handle, 'must not double destroy framebuffer'); + gl.deleteFramebuffer(handle); + framebuffer.framebuffer = null; + stats.framebufferCount--; + delete framebufferSet[framebuffer.id]; + } + + function updateFramebuffer (framebuffer) { + var i; + + gl.bindFramebuffer(GL_FRAMEBUFFER$1, framebuffer.framebuffer); + var colorAttachments = framebuffer.colorAttachments; + for (i = 0; i < colorAttachments.length; ++i) { + attach(GL_COLOR_ATTACHMENT0$1 + i, colorAttachments[i]); + } + for (i = colorAttachments.length; i < limits.maxColorAttachments; ++i) { + gl.framebufferTexture2D( + GL_FRAMEBUFFER$1, + GL_COLOR_ATTACHMENT0$1 + i, + GL_TEXTURE_2D$2, + null, + 0); + } + + gl.framebufferTexture2D( + GL_FRAMEBUFFER$1, + GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_2D$2, + null, + 0); + gl.framebufferTexture2D( + GL_FRAMEBUFFER$1, + GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D$2, + null, + 0); + gl.framebufferTexture2D( + GL_FRAMEBUFFER$1, + GL_STENCIL_ATTACHMENT, + GL_TEXTURE_2D$2, + null, + 0); + + attach(GL_DEPTH_ATTACHMENT, framebuffer.depthAttachment); + attach(GL_STENCIL_ATTACHMENT, framebuffer.stencilAttachment); + attach(GL_DEPTH_STENCIL_ATTACHMENT, framebuffer.depthStencilAttachment); + + // Check status code + var status = gl.checkFramebufferStatus(GL_FRAMEBUFFER$1); + if (status !== GL_FRAMEBUFFER_COMPLETE$1) { + check$1.raise('framebuffer configuration not supported, status = ' + + statusCode[status]); + } + + + gl.bindFramebuffer(GL_FRAMEBUFFER$1, framebufferState.next ? framebufferState.next.framebuffer : null); + framebufferState.cur = framebufferState.next; + + // FIXME: Clear error code here. This is a work around for a bug in + // headless-gl + gl.getError(); + } + + function createFBO (a0, a1) { + var framebuffer = new REGLFramebuffer(); + stats.framebufferCount++; + + function reglFramebuffer (a, b) { + var i; + + check$1(framebufferState.next !== framebuffer, + 'can not update framebuffer which is currently in use'); + + var extDrawBuffers = extensions.webgl_draw_buffers; + + var width = 0; + var height = 0; + + var needsDepth = true; + var needsStencil = true; + + var colorBuffer = null; + var colorTexture = true; + var colorFormat = 'rgba'; + var colorType = 'uint8'; + var colorCount = 1; + + var depthBuffer = null; + var stencilBuffer = null; + var depthStencilBuffer = null; + var depthStencilTexture = false; + + if (typeof a === 'number') { + width = a | 0; + height = (b | 0) || width; + } else if (!a) { + width = height = 1; + } else { + check$1.type(a, 'object', 'invalid arguments for framebuffer'); + var options = a; + + if ('shape' in options) { + var shape = options.shape; + check$1(Array.isArray(shape) && shape.length >= 2, + 'invalid shape for framebuffer'); + width = shape[0]; + height = shape[1]; + } else { + if ('radius' in options) { + width = height = options.radius; + } + if ('width' in options) { + width = options.width; + } + if ('height' in options) { + height = options.height; + } + } + + if ('color' in options || + 'colors' in options) { + colorBuffer = + options.color || + options.colors; + if (Array.isArray(colorBuffer)) { + check$1( + colorBuffer.length === 1 || extDrawBuffers, + 'multiple render targets not supported'); + } + } + + if (!colorBuffer) { + if ('colorCount' in options) { + colorCount = options.colorCount | 0; + check$1(colorCount > 0, 'invalid color buffer count'); + } + + if ('colorTexture' in options) { + colorTexture = !!options.colorTexture; + colorFormat = 'rgba4'; + } + + if ('colorType' in options) { + colorType = options.colorType; + if (!colorTexture) { + if (colorType === 'half float' || colorType === 'float16') { + check$1(extensions.ext_color_buffer_half_float, + 'you must enable EXT_color_buffer_half_float to use 16-bit render buffers'); + colorFormat = 'rgba16f'; + } else if (colorType === 'float' || colorType === 'float32') { + check$1(extensions.webgl_color_buffer_float, + 'you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers'); + colorFormat = 'rgba32f'; + } + } else { + check$1(extensions.oes_texture_float || + !(colorType === 'float' || colorType === 'float32'), + 'you must enable OES_texture_float in order to use floating point framebuffer objects'); + check$1(extensions.oes_texture_half_float || + !(colorType === 'half float' || colorType === 'float16'), + 'you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects'); + } + check$1.oneOf(colorType, colorTypes, 'invalid color type'); + } + + if ('colorFormat' in options) { + colorFormat = options.colorFormat; + if (colorTextureFormats.indexOf(colorFormat) >= 0) { + colorTexture = true; + } else if (colorRenderbufferFormats.indexOf(colorFormat) >= 0) { + colorTexture = false; + } else { + if (colorTexture) { + check$1.oneOf( + options.colorFormat, colorTextureFormats, + 'invalid color format for texture'); + } else { + check$1.oneOf( + options.colorFormat, colorRenderbufferFormats, + 'invalid color format for renderbuffer'); + } + } + } + } + + if ('depthTexture' in options || 'depthStencilTexture' in options) { + depthStencilTexture = !!(options.depthTexture || + options.depthStencilTexture); + check$1(!depthStencilTexture || extensions.webgl_depth_texture, + 'webgl_depth_texture extension not supported'); + } + + if ('depth' in options) { + if (typeof options.depth === 'boolean') { + needsDepth = options.depth; + } else { + depthBuffer = options.depth; + needsStencil = false; + } + } + + if ('stencil' in options) { + if (typeof options.stencil === 'boolean') { + needsStencil = options.stencil; + } else { + stencilBuffer = options.stencil; + needsDepth = false; + } + } + + if ('depthStencil' in options) { + if (typeof options.depthStencil === 'boolean') { + needsDepth = needsStencil = options.depthStencil; + } else { + depthStencilBuffer = options.depthStencil; + needsDepth = false; + needsStencil = false; + } + } + } + + // parse attachments + var colorAttachments = null; + var depthAttachment = null; + var stencilAttachment = null; + var depthStencilAttachment = null; + + // Set up color attachments + if (Array.isArray(colorBuffer)) { + colorAttachments = colorBuffer.map(parseAttachment); + } else if (colorBuffer) { + colorAttachments = [parseAttachment(colorBuffer)]; + } else { + colorAttachments = new Array(colorCount); + for (i = 0; i < colorCount; ++i) { + colorAttachments[i] = allocAttachment( + width, + height, + colorTexture, + colorFormat, + colorType); + } + } + + check$1(extensions.webgl_draw_buffers || colorAttachments.length <= 1, + 'you must enable the WEBGL_draw_buffers extension in order to use multiple color buffers.'); + check$1(colorAttachments.length <= limits.maxColorAttachments, + 'too many color attachments, not supported'); + + width = width || colorAttachments[0].width; + height = height || colorAttachments[0].height; + + if (depthBuffer) { + depthAttachment = parseAttachment(depthBuffer); + } else if (needsDepth && !needsStencil) { + depthAttachment = allocAttachment( + width, + height, + depthStencilTexture, + 'depth', + 'uint32'); + } + + if (stencilBuffer) { + stencilAttachment = parseAttachment(stencilBuffer); + } else if (needsStencil && !needsDepth) { + stencilAttachment = allocAttachment( + width, + height, + false, + 'stencil', + 'uint8'); + } + + if (depthStencilBuffer) { + depthStencilAttachment = parseAttachment(depthStencilBuffer); + } else if (!depthBuffer && !stencilBuffer && needsStencil && needsDepth) { + depthStencilAttachment = allocAttachment( + width, + height, + depthStencilTexture, + 'depth stencil', + 'depth stencil'); + } + + check$1( + (!!depthBuffer) + (!!stencilBuffer) + (!!depthStencilBuffer) <= 1, + 'invalid framebuffer configuration, can specify exactly one depth/stencil attachment'); + + var commonColorAttachmentSize = null; + + for (i = 0; i < colorAttachments.length; ++i) { + incRefAndCheckShape(colorAttachments[i], width, height); + check$1(!colorAttachments[i] || + (colorAttachments[i].texture && + colorTextureFormatEnums.indexOf(colorAttachments[i].texture._texture.format) >= 0) || + (colorAttachments[i].renderbuffer && + colorRenderbufferFormatEnums.indexOf(colorAttachments[i].renderbuffer._renderbuffer.format) >= 0), + 'framebuffer color attachment ' + i + ' is invalid'); + + if (colorAttachments[i] && colorAttachments[i].texture) { + var colorAttachmentSize = + textureFormatChannels[colorAttachments[i].texture._texture.format] * + textureTypeSizes[colorAttachments[i].texture._texture.type]; + + if (commonColorAttachmentSize === null) { + commonColorAttachmentSize = colorAttachmentSize; + } else { + // We need to make sure that all color attachments have the same number of bitplanes + // (that is, the same numer of bits per pixel) + // This is required by the GLES2.0 standard. See the beginning of Chapter 4 in that document. + check$1(commonColorAttachmentSize === colorAttachmentSize, + 'all color attachments much have the same number of bits per pixel.'); + } + } + } + incRefAndCheckShape(depthAttachment, width, height); + check$1(!depthAttachment || + (depthAttachment.texture && + depthAttachment.texture._texture.format === GL_DEPTH_COMPONENT$1) || + (depthAttachment.renderbuffer && + depthAttachment.renderbuffer._renderbuffer.format === GL_DEPTH_COMPONENT16$1), + 'invalid depth attachment for framebuffer object'); + incRefAndCheckShape(stencilAttachment, width, height); + check$1(!stencilAttachment || + (stencilAttachment.renderbuffer && + stencilAttachment.renderbuffer._renderbuffer.format === GL_STENCIL_INDEX8$1), + 'invalid stencil attachment for framebuffer object'); + incRefAndCheckShape(depthStencilAttachment, width, height); + check$1(!depthStencilAttachment || + (depthStencilAttachment.texture && + depthStencilAttachment.texture._texture.format === GL_DEPTH_STENCIL$2) || + (depthStencilAttachment.renderbuffer && + depthStencilAttachment.renderbuffer._renderbuffer.format === GL_DEPTH_STENCIL$2), + 'invalid depth-stencil attachment for framebuffer object'); + + // decrement references + decFBORefs(framebuffer); + + framebuffer.width = width; + framebuffer.height = height; + + framebuffer.colorAttachments = colorAttachments; + framebuffer.depthAttachment = depthAttachment; + framebuffer.stencilAttachment = stencilAttachment; + framebuffer.depthStencilAttachment = depthStencilAttachment; + + reglFramebuffer.color = colorAttachments.map(unwrapAttachment); + reglFramebuffer.depth = unwrapAttachment(depthAttachment); + reglFramebuffer.stencil = unwrapAttachment(stencilAttachment); + reglFramebuffer.depthStencil = unwrapAttachment(depthStencilAttachment); + + reglFramebuffer.width = framebuffer.width; + reglFramebuffer.height = framebuffer.height; + + updateFramebuffer(framebuffer); + + return reglFramebuffer + } + + function resize (w_, h_) { + check$1(framebufferState.next !== framebuffer, + 'can not resize a framebuffer which is currently in use'); + + var w = w_ | 0; + var h = (h_ | 0) || w; + if (w === framebuffer.width && h === framebuffer.height) { + return reglFramebuffer + } + + // resize all buffers + var colorAttachments = framebuffer.colorAttachments; + for (var i = 0; i < colorAttachments.length; ++i) { + resizeAttachment(colorAttachments[i], w, h); + } + resizeAttachment(framebuffer.depthAttachment, w, h); + resizeAttachment(framebuffer.stencilAttachment, w, h); + resizeAttachment(framebuffer.depthStencilAttachment, w, h); + + framebuffer.width = reglFramebuffer.width = w; + framebuffer.height = reglFramebuffer.height = h; + + updateFramebuffer(framebuffer); + + return reglFramebuffer + } + + reglFramebuffer(a0, a1); + + return extend(reglFramebuffer, { + resize: resize, + _reglType: 'framebuffer', + _framebuffer: framebuffer, + destroy: function () { + destroy(framebuffer); + decFBORefs(framebuffer); + }, + use: function (block) { + framebufferState.setFBO({ + framebuffer: reglFramebuffer + }, block); + } + }) + } + + function createCubeFBO (options) { + var faces = Array(6); + + function reglFramebufferCube (a) { + var i; + + check$1(faces.indexOf(framebufferState.next) < 0, + 'can not update framebuffer which is currently in use'); + + var extDrawBuffers = extensions.webgl_draw_buffers; + + var params = { + color: null + }; + + var radius = 0; + + var colorBuffer = null; + var colorFormat = 'rgba'; + var colorType = 'uint8'; + var colorCount = 1; + + if (typeof a === 'number') { + radius = a | 0; + } else if (!a) { + radius = 1; + } else { + check$1.type(a, 'object', 'invalid arguments for framebuffer'); + var options = a; + + if ('shape' in options) { + var shape = options.shape; + check$1( + Array.isArray(shape) && shape.length >= 2, + 'invalid shape for framebuffer'); + check$1( + shape[0] === shape[1], + 'cube framebuffer must be square'); + radius = shape[0]; + } else { + if ('radius' in options) { + radius = options.radius | 0; + } + if ('width' in options) { + radius = options.width | 0; + if ('height' in options) { + check$1(options.height === radius, 'must be square'); + } + } else if ('height' in options) { + radius = options.height | 0; + } + } + + if ('color' in options || + 'colors' in options) { + colorBuffer = + options.color || + options.colors; + if (Array.isArray(colorBuffer)) { + check$1( + colorBuffer.length === 1 || extDrawBuffers, + 'multiple render targets not supported'); + } + } + + if (!colorBuffer) { + if ('colorCount' in options) { + colorCount = options.colorCount | 0; + check$1(colorCount > 0, 'invalid color buffer count'); + } + + if ('colorType' in options) { + check$1.oneOf( + options.colorType, colorTypes, + 'invalid color type'); + colorType = options.colorType; + } + + if ('colorFormat' in options) { + colorFormat = options.colorFormat; + check$1.oneOf( + options.colorFormat, colorTextureFormats, + 'invalid color format for texture'); + } + } + + if ('depth' in options) { + params.depth = options.depth; + } + + if ('stencil' in options) { + params.stencil = options.stencil; + } + + if ('depthStencil' in options) { + params.depthStencil = options.depthStencil; + } + } + + var colorCubes; + if (colorBuffer) { + if (Array.isArray(colorBuffer)) { + colorCubes = []; + for (i = 0; i < colorBuffer.length; ++i) { + colorCubes[i] = colorBuffer[i]; + } + } else { + colorCubes = [ colorBuffer ]; + } + } else { + colorCubes = Array(colorCount); + var cubeMapParams = { + radius: radius, + format: colorFormat, + type: colorType + }; + for (i = 0; i < colorCount; ++i) { + colorCubes[i] = textureState.createCube(cubeMapParams); + } + } + + // Check color cubes + params.color = Array(colorCubes.length); + for (i = 0; i < colorCubes.length; ++i) { + var cube = colorCubes[i]; + check$1( + typeof cube === 'function' && cube._reglType === 'textureCube', + 'invalid cube map'); + radius = radius || cube.width; + check$1( + cube.width === radius && cube.height === radius, + 'invalid cube map shape'); + params.color[i] = { + target: GL_TEXTURE_CUBE_MAP_POSITIVE_X$2, + data: colorCubes[i] + }; + } + + for (i = 0; i < 6; ++i) { + for (var j = 0; j < colorCubes.length; ++j) { + params.color[j].target = GL_TEXTURE_CUBE_MAP_POSITIVE_X$2 + i; + } + // reuse depth-stencil attachments across all cube maps + if (i > 0) { + params.depth = faces[0].depth; + params.stencil = faces[0].stencil; + params.depthStencil = faces[0].depthStencil; + } + if (faces[i]) { + (faces[i])(params); + } else { + faces[i] = createFBO(params); + } + } + + return extend(reglFramebufferCube, { + width: radius, + height: radius, + color: colorCubes + }) + } + + function resize (radius_) { + var i; + var radius = radius_ | 0; + check$1(radius > 0 && radius <= limits.maxCubeMapSize, + 'invalid radius for cube fbo'); + + if (radius === reglFramebufferCube.width) { + return reglFramebufferCube + } + + var colors = reglFramebufferCube.color; + for (i = 0; i < colors.length; ++i) { + colors[i].resize(radius); + } + + for (i = 0; i < 6; ++i) { + faces[i].resize(radius); + } + + reglFramebufferCube.width = reglFramebufferCube.height = radius; + + return reglFramebufferCube + } + + reglFramebufferCube(options); + + return extend(reglFramebufferCube, { + faces: faces, + resize: resize, + _reglType: 'framebufferCube', + destroy: function () { + faces.forEach(function (f) { + f.destroy(); + }); + } + }) + } + + function restoreFramebuffers () { + values(framebufferSet).forEach(function (fb) { + fb.framebuffer = gl.createFramebuffer(); + updateFramebuffer(fb); + }); + } + + return extend(framebufferState, { + getFramebuffer: function (object) { + if (typeof object === 'function' && object._reglType === 'framebuffer') { + var fbo = object._framebuffer; + if (fbo instanceof REGLFramebuffer) { + return fbo + } + } + return null + }, + create: createFBO, + createCube: createCubeFBO, + clear: function () { + values(framebufferSet).forEach(destroy); + }, + restore: restoreFramebuffers + }) +} + +var GL_FLOAT$6 = 5126; + +function AttributeRecord () { + this.state = 0; + + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + this.w = 0.0; + + this.buffer = null; + this.size = 0; + this.normalized = false; + this.type = GL_FLOAT$6; + this.offset = 0; + this.stride = 0; + this.divisor = 0; +} + +function wrapAttributeState ( + gl, + extensions, + limits, + stringStore) { + var NUM_ATTRIBUTES = limits.maxAttributes; + var attributeBindings = new Array(NUM_ATTRIBUTES); + for (var i = 0; i < NUM_ATTRIBUTES; ++i) { + attributeBindings[i] = new AttributeRecord(); + } + + return { + Record: AttributeRecord, + scope: {}, + state: attributeBindings + } +} + +var GL_FRAGMENT_SHADER = 35632; +var GL_VERTEX_SHADER = 35633; + +var GL_ACTIVE_UNIFORMS = 0x8B86; +var GL_ACTIVE_ATTRIBUTES = 0x8B89; + +function wrapShaderState (gl, stringStore, stats, config) { + // =================================================== + // glsl compilation and linking + // =================================================== + var fragShaders = {}; + var vertShaders = {}; + + function ActiveInfo (name, id, location, info) { + this.name = name; + this.id = id; + this.location = location; + this.info = info; + } + + function insertActiveInfo (list, info) { + for (var i = 0; i < list.length; ++i) { + if (list[i].id === info.id) { + list[i].location = info.location; + return + } + } + list.push(info); + } + + function getShader (type, id, command) { + var cache = type === GL_FRAGMENT_SHADER ? fragShaders : vertShaders; + var shader = cache[id]; + + if (!shader) { + var source = stringStore.str(id); + shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + check$1.shaderError(gl, shader, source, type, command); + cache[id] = shader; + } + + return shader + } + + // =================================================== + // program linking + // =================================================== + var programCache = {}; + var programList = []; + + var PROGRAM_COUNTER = 0; + + function REGLProgram (fragId, vertId) { + this.id = PROGRAM_COUNTER++; + this.fragId = fragId; + this.vertId = vertId; + this.program = null; + this.uniforms = []; + this.attributes = []; + + if (config.profile) { + this.stats = { + uniformsCount: 0, + attributesCount: 0 + }; + } + } + + function linkProgram (desc, command) { + var i, info; + + // ------------------------------- + // compile & link + // ------------------------------- + var fragShader = getShader(GL_FRAGMENT_SHADER, desc.fragId); + var vertShader = getShader(GL_VERTEX_SHADER, desc.vertId); + + var program = desc.program = gl.createProgram(); + gl.attachShader(program, fragShader); + gl.attachShader(program, vertShader); + gl.linkProgram(program); + check$1.linkError( + gl, + program, + stringStore.str(desc.fragId), + stringStore.str(desc.vertId), + command); + + // ------------------------------- + // grab uniforms + // ------------------------------- + var numUniforms = gl.getProgramParameter(program, GL_ACTIVE_UNIFORMS); + if (config.profile) { + desc.stats.uniformsCount = numUniforms; + } + var uniforms = desc.uniforms; + for (i = 0; i < numUniforms; ++i) { + info = gl.getActiveUniform(program, i); + if (info) { + if (info.size > 1) { + for (var j = 0; j < info.size; ++j) { + var name = info.name.replace('[0]', '[' + j + ']'); + insertActiveInfo(uniforms, new ActiveInfo( + name, + stringStore.id(name), + gl.getUniformLocation(program, name), + info)); + } + } else { + insertActiveInfo(uniforms, new ActiveInfo( + info.name, + stringStore.id(info.name), + gl.getUniformLocation(program, info.name), + info)); + } + } + } + + // ------------------------------- + // grab attributes + // ------------------------------- + var numAttributes = gl.getProgramParameter(program, GL_ACTIVE_ATTRIBUTES); + if (config.profile) { + desc.stats.attributesCount = numAttributes; + } + + var attributes = desc.attributes; + for (i = 0; i < numAttributes; ++i) { + info = gl.getActiveAttrib(program, i); + if (info) { + insertActiveInfo(attributes, new ActiveInfo( + info.name, + stringStore.id(info.name), + gl.getAttribLocation(program, info.name), + info)); + } + } + } + + if (config.profile) { + stats.getMaxUniformsCount = function () { + var m = 0; + programList.forEach(function (desc) { + if (desc.stats.uniformsCount > m) { + m = desc.stats.uniformsCount; + } + }); + return m + }; + + stats.getMaxAttributesCount = function () { + var m = 0; + programList.forEach(function (desc) { + if (desc.stats.attributesCount > m) { + m = desc.stats.attributesCount; + } + }); + return m + }; + } + + function restoreShaders () { + fragShaders = {}; + vertShaders = {}; + for (var i = 0; i < programList.length; ++i) { + linkProgram(programList[i]); + } + } + + return { + clear: function () { + var deleteShader = gl.deleteShader.bind(gl); + values(fragShaders).forEach(deleteShader); + fragShaders = {}; + values(vertShaders).forEach(deleteShader); + vertShaders = {}; + + programList.forEach(function (desc) { + gl.deleteProgram(desc.program); + }); + programList.length = 0; + programCache = {}; + + stats.shaderCount = 0; + }, + + program: function (vertId, fragId, command) { + check$1.command(vertId >= 0, 'missing vertex shader', command); + check$1.command(fragId >= 0, 'missing fragment shader', command); + + var cache = programCache[fragId]; + if (!cache) { + cache = programCache[fragId] = {}; + } + var program = cache[vertId]; + if (!program) { + program = new REGLProgram(fragId, vertId); + stats.shaderCount++; + + linkProgram(program, command); + cache[vertId] = program; + programList.push(program); + } + return program + }, + + restore: restoreShaders, + + shader: getShader, + + frag: -1, + vert: -1 + } +} + +var GL_RGBA$3 = 6408; +var GL_UNSIGNED_BYTE$7 = 5121; +var GL_PACK_ALIGNMENT = 0x0D05; +var GL_FLOAT$7 = 0x1406; // 5126 + +function wrapReadPixels ( + gl, + framebufferState, + reglPoll, + context, + glAttributes, + extensions, + limits) { + function readPixelsImpl (input) { + var type; + if (framebufferState.next === null) { + check$1( + glAttributes.preserveDrawingBuffer, + 'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer'); + type = GL_UNSIGNED_BYTE$7; + } else { + check$1( + framebufferState.next.colorAttachments[0].texture !== null, + 'You cannot read from a renderbuffer'); + type = framebufferState.next.colorAttachments[0].texture._texture.type; + + if (extensions.oes_texture_float) { + check$1( + type === GL_UNSIGNED_BYTE$7 || type === GL_FLOAT$7, + 'Reading from a framebuffer is only allowed for the types \'uint8\' and \'float\''); + + if (type === GL_FLOAT$7) { + check$1(limits.readFloat, 'Reading \'float\' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float'); + } + } else { + check$1( + type === GL_UNSIGNED_BYTE$7, + 'Reading from a framebuffer is only allowed for the type \'uint8\''); + } + } + + var x = 0; + var y = 0; + var width = context.framebufferWidth; + var height = context.framebufferHeight; + var data = null; + + if (isTypedArray(input)) { + data = input; + } else if (input) { + check$1.type(input, 'object', 'invalid arguments to regl.read()'); + x = input.x | 0; + y = input.y | 0; + check$1( + x >= 0 && x < context.framebufferWidth, + 'invalid x offset for regl.read'); + check$1( + y >= 0 && y < context.framebufferHeight, + 'invalid y offset for regl.read'); + width = (input.width || (context.framebufferWidth - x)) | 0; + height = (input.height || (context.framebufferHeight - y)) | 0; + data = input.data || null; + } + + // sanity check input.data + if (data) { + if (type === GL_UNSIGNED_BYTE$7) { + check$1( + data instanceof Uint8Array, + 'buffer must be \'Uint8Array\' when reading from a framebuffer of type \'uint8\''); + } else if (type === GL_FLOAT$7) { + check$1( + data instanceof Float32Array, + 'buffer must be \'Float32Array\' when reading from a framebuffer of type \'float\''); + } + } + + check$1( + width > 0 && width + x <= context.framebufferWidth, + 'invalid width for read pixels'); + check$1( + height > 0 && height + y <= context.framebufferHeight, + 'invalid height for read pixels'); + + // Update WebGL state + reglPoll(); + + // Compute size + var size = width * height * 4; + + // Allocate data + if (!data) { + if (type === GL_UNSIGNED_BYTE$7) { + data = new Uint8Array(size); + } else if (type === GL_FLOAT$7) { + data = data || new Float32Array(size); + } + } + + // Type check + check$1.isTypedArray(data, 'data buffer for regl.read() must be a typedarray'); + check$1(data.byteLength >= size, 'data buffer for regl.read() too small'); + + // Run read pixels + gl.pixelStorei(GL_PACK_ALIGNMENT, 4); + gl.readPixels(x, y, width, height, GL_RGBA$3, + type, + data); + + return data + } + + function readPixelsFBO (options) { + var result; + framebufferState.setFBO({ + framebuffer: options.framebuffer + }, function () { + result = readPixelsImpl(options); + }); + return result + } + + function readPixels (options) { + if (!options || !('framebuffer' in options)) { + return readPixelsImpl(options) + } else { + return readPixelsFBO(options) + } + } + + return readPixels +} + +function slice (x) { + return Array.prototype.slice.call(x) +} + +function join (x) { + return slice(x).join('') +} + +function createEnvironment () { + // Unique variable id counter + var varCounter = 0; + + // Linked values are passed from this scope into the generated code block + // Calling link() passes a value into the generated scope and returns + // the variable name which it is bound to + var linkedNames = []; + var linkedValues = []; + function link (value) { + for (var i = 0; i < linkedValues.length; ++i) { + if (linkedValues[i] === value) { + return linkedNames[i] + } + } + + var name = 'g' + (varCounter++); + linkedNames.push(name); + linkedValues.push(value); + return name + } + + // create a code block + function block () { + var code = []; + function push () { + code.push.apply(code, slice(arguments)); + } + + var vars = []; + function def () { + var name = 'v' + (varCounter++); + vars.push(name); + + if (arguments.length > 0) { + code.push(name, '='); + code.push.apply(code, slice(arguments)); + code.push(';'); + } + + return name + } + + return extend(push, { + def: def, + toString: function () { + return join([ + (vars.length > 0 ? 'var ' + vars + ';' : ''), + join(code) + ]) + } + }) + } + + function scope () { + var entry = block(); + var exit = block(); + + var entryToString = entry.toString; + var exitToString = exit.toString; + + function save (object, prop) { + exit(object, prop, '=', entry.def(object, prop), ';'); + } + + return extend(function () { + entry.apply(entry, slice(arguments)); + }, { + def: entry.def, + entry: entry, + exit: exit, + save: save, + set: function (object, prop, value) { + save(object, prop); + entry(object, prop, '=', value, ';'); + }, + toString: function () { + return entryToString() + exitToString() + } + }) + } + + function conditional () { + var pred = join(arguments); + var thenBlock = scope(); + var elseBlock = scope(); + + var thenToString = thenBlock.toString; + var elseToString = elseBlock.toString; + + return extend(thenBlock, { + then: function () { + thenBlock.apply(thenBlock, slice(arguments)); + return this + }, + else: function () { + elseBlock.apply(elseBlock, slice(arguments)); + return this + }, + toString: function () { + var elseClause = elseToString(); + if (elseClause) { + elseClause = 'else{' + elseClause + '}'; + } + return join([ + 'if(', pred, '){', + thenToString(), + '}', elseClause + ]) + } + }) + } + + // procedure list + var globalBlock = block(); + var procedures = {}; + function proc (name, count) { + var args = []; + function arg () { + var name = 'a' + args.length; + args.push(name); + return name + } + + count = count || 0; + for (var i = 0; i < count; ++i) { + arg(); + } + + var body = scope(); + var bodyToString = body.toString; + + var result = procedures[name] = extend(body, { + arg: arg, + toString: function () { + return join([ + 'function(', args.join(), '){', + bodyToString(), + '}' + ]) + } + }); + + return result + } + + function compile () { + var code = ['"use strict";', + globalBlock, + 'return {']; + Object.keys(procedures).forEach(function (name) { + code.push('"', name, '":', procedures[name].toString(), ','); + }); + code.push('}'); + var src = join(code) + .replace(/;/g, ';\n') + .replace(/}/g, '}\n') + .replace(/{/g, '{\n'); + var proc = Function.apply(null, linkedNames.concat(src)); + return proc.apply(null, linkedValues) + } + + return { + global: globalBlock, + link: link, + block: block, + proc: proc, + scope: scope, + cond: conditional, + compile: compile + } +} + +// "cute" names for vector components +var CUTE_COMPONENTS = 'xyzw'.split(''); + +var GL_UNSIGNED_BYTE$8 = 5121; + +var ATTRIB_STATE_POINTER = 1; +var ATTRIB_STATE_CONSTANT = 2; + +var DYN_FUNC$1 = 0; +var DYN_PROP$1 = 1; +var DYN_CONTEXT$1 = 2; +var DYN_STATE$1 = 3; +var DYN_THUNK = 4; + +var S_DITHER = 'dither'; +var S_BLEND_ENABLE = 'blend.enable'; +var S_BLEND_COLOR = 'blend.color'; +var S_BLEND_EQUATION = 'blend.equation'; +var S_BLEND_FUNC = 'blend.func'; +var S_DEPTH_ENABLE = 'depth.enable'; +var S_DEPTH_FUNC = 'depth.func'; +var S_DEPTH_RANGE = 'depth.range'; +var S_DEPTH_MASK = 'depth.mask'; +var S_COLOR_MASK = 'colorMask'; +var S_CULL_ENABLE = 'cull.enable'; +var S_CULL_FACE = 'cull.face'; +var S_FRONT_FACE = 'frontFace'; +var S_LINE_WIDTH = 'lineWidth'; +var S_POLYGON_OFFSET_ENABLE = 'polygonOffset.enable'; +var S_POLYGON_OFFSET_OFFSET = 'polygonOffset.offset'; +var S_SAMPLE_ALPHA = 'sample.alpha'; +var S_SAMPLE_ENABLE = 'sample.enable'; +var S_SAMPLE_COVERAGE = 'sample.coverage'; +var S_STENCIL_ENABLE = 'stencil.enable'; +var S_STENCIL_MASK = 'stencil.mask'; +var S_STENCIL_FUNC = 'stencil.func'; +var S_STENCIL_OPFRONT = 'stencil.opFront'; +var S_STENCIL_OPBACK = 'stencil.opBack'; +var S_SCISSOR_ENABLE = 'scissor.enable'; +var S_SCISSOR_BOX = 'scissor.box'; +var S_VIEWPORT = 'viewport'; + +var S_PROFILE = 'profile'; + +var S_FRAMEBUFFER = 'framebuffer'; +var S_VERT = 'vert'; +var S_FRAG = 'frag'; +var S_ELEMENTS = 'elements'; +var S_PRIMITIVE = 'primitive'; +var S_COUNT = 'count'; +var S_OFFSET = 'offset'; +var S_INSTANCES = 'instances'; + +var SUFFIX_WIDTH = 'Width'; +var SUFFIX_HEIGHT = 'Height'; + +var S_FRAMEBUFFER_WIDTH = S_FRAMEBUFFER + SUFFIX_WIDTH; +var S_FRAMEBUFFER_HEIGHT = S_FRAMEBUFFER + SUFFIX_HEIGHT; +var S_VIEWPORT_WIDTH = S_VIEWPORT + SUFFIX_WIDTH; +var S_VIEWPORT_HEIGHT = S_VIEWPORT + SUFFIX_HEIGHT; +var S_DRAWINGBUFFER = 'drawingBuffer'; +var S_DRAWINGBUFFER_WIDTH = S_DRAWINGBUFFER + SUFFIX_WIDTH; +var S_DRAWINGBUFFER_HEIGHT = S_DRAWINGBUFFER + SUFFIX_HEIGHT; + +var NESTED_OPTIONS = [ + S_BLEND_FUNC, + S_BLEND_EQUATION, + S_STENCIL_FUNC, + S_STENCIL_OPFRONT, + S_STENCIL_OPBACK, + S_SAMPLE_COVERAGE, + S_VIEWPORT, + S_SCISSOR_BOX, + S_POLYGON_OFFSET_OFFSET +]; + +var GL_ARRAY_BUFFER$1 = 34962; +var GL_ELEMENT_ARRAY_BUFFER$1 = 34963; + +var GL_FRAGMENT_SHADER$1 = 35632; +var GL_VERTEX_SHADER$1 = 35633; + +var GL_TEXTURE_2D$3 = 0x0DE1; +var GL_TEXTURE_CUBE_MAP$2 = 0x8513; + +var GL_CULL_FACE = 0x0B44; +var GL_BLEND = 0x0BE2; +var GL_DITHER = 0x0BD0; +var GL_STENCIL_TEST = 0x0B90; +var GL_DEPTH_TEST = 0x0B71; +var GL_SCISSOR_TEST = 0x0C11; +var GL_POLYGON_OFFSET_FILL = 0x8037; +var GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809E; +var GL_SAMPLE_COVERAGE = 0x80A0; + +var GL_FLOAT$8 = 5126; +var GL_FLOAT_VEC2 = 35664; +var GL_FLOAT_VEC3 = 35665; +var GL_FLOAT_VEC4 = 35666; +var GL_INT$3 = 5124; +var GL_INT_VEC2 = 35667; +var GL_INT_VEC3 = 35668; +var GL_INT_VEC4 = 35669; +var GL_BOOL = 35670; +var GL_BOOL_VEC2 = 35671; +var GL_BOOL_VEC3 = 35672; +var GL_BOOL_VEC4 = 35673; +var GL_FLOAT_MAT2 = 35674; +var GL_FLOAT_MAT3 = 35675; +var GL_FLOAT_MAT4 = 35676; +var GL_SAMPLER_2D = 35678; +var GL_SAMPLER_CUBE = 35680; + +var GL_TRIANGLES$1 = 4; + +var GL_FRONT = 1028; +var GL_BACK = 1029; +var GL_CW = 0x0900; +var GL_CCW = 0x0901; +var GL_MIN_EXT = 0x8007; +var GL_MAX_EXT = 0x8008; +var GL_ALWAYS = 519; +var GL_KEEP = 7680; +var GL_ZERO = 0; +var GL_ONE = 1; +var GL_FUNC_ADD = 0x8006; +var GL_LESS = 513; + +var GL_FRAMEBUFFER$2 = 0x8D40; +var GL_COLOR_ATTACHMENT0$2 = 0x8CE0; + +var blendFuncs = { + '0': 0, + '1': 1, + 'zero': 0, + 'one': 1, + 'src color': 768, + 'one minus src color': 769, + 'src alpha': 770, + 'one minus src alpha': 771, + 'dst color': 774, + 'one minus dst color': 775, + 'dst alpha': 772, + 'one minus dst alpha': 773, + 'constant color': 32769, + 'one minus constant color': 32770, + 'constant alpha': 32771, + 'one minus constant alpha': 32772, + 'src alpha saturate': 776 +}; + +// There are invalid values for srcRGB and dstRGB. See: +// https://www.khronos.org/registry/webgl/specs/1.0/#6.13 +// https://github.com/KhronosGroup/WebGL/blob/0d3201f5f7ec3c0060bc1f04077461541f1987b9/conformance-suites/1.0.3/conformance/misc/webgl-specific.html#L56 +var invalidBlendCombinations = [ + 'constant color, constant alpha', + 'one minus constant color, constant alpha', + 'constant color, one minus constant alpha', + 'one minus constant color, one minus constant alpha', + 'constant alpha, constant color', + 'constant alpha, one minus constant color', + 'one minus constant alpha, constant color', + 'one minus constant alpha, one minus constant color' +]; + +var compareFuncs = { + 'never': 512, + 'less': 513, + '<': 513, + 'equal': 514, + '=': 514, + '==': 514, + '===': 514, + 'lequal': 515, + '<=': 515, + 'greater': 516, + '>': 516, + 'notequal': 517, + '!=': 517, + '!==': 517, + 'gequal': 518, + '>=': 518, + 'always': 519 +}; + +var stencilOps = { + '0': 0, + 'zero': 0, + 'keep': 7680, + 'replace': 7681, + 'increment': 7682, + 'decrement': 7683, + 'increment wrap': 34055, + 'decrement wrap': 34056, + 'invert': 5386 +}; + +var shaderType = { + 'frag': GL_FRAGMENT_SHADER$1, + 'vert': GL_VERTEX_SHADER$1 +}; + +var orientationType = { + 'cw': GL_CW, + 'ccw': GL_CCW +}; + +function isBufferArgs (x) { + return Array.isArray(x) || + isTypedArray(x) || + isNDArrayLike(x) +} + +// Make sure viewport is processed first +function sortState (state) { + return state.sort(function (a, b) { + if (a === S_VIEWPORT) { + return -1 + } else if (b === S_VIEWPORT) { + return 1 + } + return (a < b) ? -1 : 1 + }) +} + +function Declaration (thisDep, contextDep, propDep, append) { + this.thisDep = thisDep; + this.contextDep = contextDep; + this.propDep = propDep; + this.append = append; +} + +function isStatic (decl) { + return decl && !(decl.thisDep || decl.contextDep || decl.propDep) +} + +function createStaticDecl (append) { + return new Declaration(false, false, false, append) +} + +function createDynamicDecl (dyn, append) { + var type = dyn.type; + if (type === DYN_FUNC$1) { + var numArgs = dyn.data.length; + return new Declaration( + true, + numArgs >= 1, + numArgs >= 2, + append) + } else if (type === DYN_THUNK) { + var data = dyn.data; + return new Declaration( + data.thisDep, + data.contextDep, + data.propDep, + append) + } else { + return new Declaration( + type === DYN_STATE$1, + type === DYN_CONTEXT$1, + type === DYN_PROP$1, + append) + } +} + +var SCOPE_DECL = new Declaration(false, false, false, function () {}); + +function reglCore ( + gl, + stringStore, + extensions, + limits, + bufferState, + elementState, + textureState, + framebufferState, + uniformState, + attributeState, + shaderState, + drawState, + contextState, + timer, + config) { + var AttributeRecord = attributeState.Record; + + var blendEquations = { + 'add': 32774, + 'subtract': 32778, + 'reverse subtract': 32779 + }; + if (extensions.ext_blend_minmax) { + blendEquations.min = GL_MIN_EXT; + blendEquations.max = GL_MAX_EXT; + } + + var extInstancing = extensions.angle_instanced_arrays; + var extDrawBuffers = extensions.webgl_draw_buffers; + + // =================================================== + // =================================================== + // WEBGL STATE + // =================================================== + // =================================================== + var currentState = { + dirty: true, + profile: config.profile + }; + var nextState = {}; + var GL_STATE_NAMES = []; + var GL_FLAGS = {}; + var GL_VARIABLES = {}; + + function propName (name) { + return name.replace('.', '_') + } + + function stateFlag (sname, cap, init) { + var name = propName(sname); + GL_STATE_NAMES.push(sname); + nextState[name] = currentState[name] = !!init; + GL_FLAGS[name] = cap; + } + + function stateVariable (sname, func, init) { + var name = propName(sname); + GL_STATE_NAMES.push(sname); + if (Array.isArray(init)) { + currentState[name] = init.slice(); + nextState[name] = init.slice(); + } else { + currentState[name] = nextState[name] = init; + } + GL_VARIABLES[name] = func; + } + + // Dithering + stateFlag(S_DITHER, GL_DITHER); + + // Blending + stateFlag(S_BLEND_ENABLE, GL_BLEND); + stateVariable(S_BLEND_COLOR, 'blendColor', [0, 0, 0, 0]); + stateVariable(S_BLEND_EQUATION, 'blendEquationSeparate', + [GL_FUNC_ADD, GL_FUNC_ADD]); + stateVariable(S_BLEND_FUNC, 'blendFuncSeparate', + [GL_ONE, GL_ZERO, GL_ONE, GL_ZERO]); + + // Depth + stateFlag(S_DEPTH_ENABLE, GL_DEPTH_TEST, true); + stateVariable(S_DEPTH_FUNC, 'depthFunc', GL_LESS); + stateVariable(S_DEPTH_RANGE, 'depthRange', [0, 1]); + stateVariable(S_DEPTH_MASK, 'depthMask', true); + + // Color mask + stateVariable(S_COLOR_MASK, S_COLOR_MASK, [true, true, true, true]); + + // Face culling + stateFlag(S_CULL_ENABLE, GL_CULL_FACE); + stateVariable(S_CULL_FACE, 'cullFace', GL_BACK); + + // Front face orientation + stateVariable(S_FRONT_FACE, S_FRONT_FACE, GL_CCW); + + // Line width + stateVariable(S_LINE_WIDTH, S_LINE_WIDTH, 1); + + // Polygon offset + stateFlag(S_POLYGON_OFFSET_ENABLE, GL_POLYGON_OFFSET_FILL); + stateVariable(S_POLYGON_OFFSET_OFFSET, 'polygonOffset', [0, 0]); + + // Sample coverage + stateFlag(S_SAMPLE_ALPHA, GL_SAMPLE_ALPHA_TO_COVERAGE); + stateFlag(S_SAMPLE_ENABLE, GL_SAMPLE_COVERAGE); + stateVariable(S_SAMPLE_COVERAGE, 'sampleCoverage', [1, false]); + + // Stencil + stateFlag(S_STENCIL_ENABLE, GL_STENCIL_TEST); + stateVariable(S_STENCIL_MASK, 'stencilMask', -1); + stateVariable(S_STENCIL_FUNC, 'stencilFunc', [GL_ALWAYS, 0, -1]); + stateVariable(S_STENCIL_OPFRONT, 'stencilOpSeparate', + [GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP]); + stateVariable(S_STENCIL_OPBACK, 'stencilOpSeparate', + [GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP]); + + // Scissor + stateFlag(S_SCISSOR_ENABLE, GL_SCISSOR_TEST); + stateVariable(S_SCISSOR_BOX, 'scissor', + [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight]); + + // Viewport + stateVariable(S_VIEWPORT, S_VIEWPORT, + [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight]); + + // =================================================== + // =================================================== + // ENVIRONMENT + // =================================================== + // =================================================== + var sharedState = { + gl: gl, + context: contextState, + strings: stringStore, + next: nextState, + current: currentState, + draw: drawState, + elements: elementState, + buffer: bufferState, + shader: shaderState, + attributes: attributeState.state, + uniforms: uniformState, + framebuffer: framebufferState, + extensions: extensions, + + timer: timer, + isBufferArgs: isBufferArgs + }; + + var sharedConstants = { + primTypes: primTypes, + compareFuncs: compareFuncs, + blendFuncs: blendFuncs, + blendEquations: blendEquations, + stencilOps: stencilOps, + glTypes: glTypes, + orientationType: orientationType + }; + + check$1.optional(function () { + sharedState.isArrayLike = isArrayLike; + }); + + if (extDrawBuffers) { + sharedConstants.backBuffer = [GL_BACK]; + sharedConstants.drawBuffer = loop(limits.maxDrawbuffers, function (i) { + if (i === 0) { + return [0] + } + return loop(i, function (j) { + return GL_COLOR_ATTACHMENT0$2 + j + }) + }); + } + + var drawCallCounter = 0; + function createREGLEnvironment () { + var env = createEnvironment(); + var link = env.link; + var global = env.global; + env.id = drawCallCounter++; + + env.batchId = '0'; + + // link shared state + var SHARED = link(sharedState); + var shared = env.shared = { + props: 'a0' + }; + Object.keys(sharedState).forEach(function (prop) { + shared[prop] = global.def(SHARED, '.', prop); + }); + + // Inject runtime assertion stuff for debug builds + check$1.optional(function () { + env.CHECK = link(check$1); + env.commandStr = check$1.guessCommand(); + env.command = link(env.commandStr); + env.assert = function (block, pred, message) { + block( + 'if(!(', pred, '))', + this.CHECK, '.commandRaise(', link(message), ',', this.command, ');'); + }; + + sharedConstants.invalidBlendCombinations = invalidBlendCombinations; + }); + + // Copy GL state variables over + var nextVars = env.next = {}; + var currentVars = env.current = {}; + Object.keys(GL_VARIABLES).forEach(function (variable) { + if (Array.isArray(currentState[variable])) { + nextVars[variable] = global.def(shared.next, '.', variable); + currentVars[variable] = global.def(shared.current, '.', variable); + } + }); + + // Initialize shared constants + var constants = env.constants = {}; + Object.keys(sharedConstants).forEach(function (name) { + constants[name] = global.def(JSON.stringify(sharedConstants[name])); + }); + + // Helper function for calling a block + env.invoke = function (block, x) { + switch (x.type) { + case DYN_FUNC$1: + var argList = [ + 'this', + shared.context, + shared.props, + env.batchId + ]; + return block.def( + link(x.data), '.call(', + argList.slice(0, Math.max(x.data.length + 1, 4)), + ')') + case DYN_PROP$1: + return block.def(shared.props, x.data) + case DYN_CONTEXT$1: + return block.def(shared.context, x.data) + case DYN_STATE$1: + return block.def('this', x.data) + case DYN_THUNK: + x.data.append(env, block); + return x.data.ref + } + }; + + env.attribCache = {}; + + var scopeAttribs = {}; + env.scopeAttrib = function (name) { + var id = stringStore.id(name); + if (id in scopeAttribs) { + return scopeAttribs[id] + } + var binding = attributeState.scope[id]; + if (!binding) { + binding = attributeState.scope[id] = new AttributeRecord(); + } + var result = scopeAttribs[id] = link(binding); + return result + }; + + return env + } + + // =================================================== + // =================================================== + // PARSING + // =================================================== + // =================================================== + function parseProfile (options) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + var profileEnable; + if (S_PROFILE in staticOptions) { + var value = !!staticOptions[S_PROFILE]; + profileEnable = createStaticDecl(function (env, scope) { + return value + }); + profileEnable.enable = value; + } else if (S_PROFILE in dynamicOptions) { + var dyn = dynamicOptions[S_PROFILE]; + profileEnable = createDynamicDecl(dyn, function (env, scope) { + return env.invoke(scope, dyn) + }); + } + + return profileEnable + } + + function parseFramebuffer (options, env) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + if (S_FRAMEBUFFER in staticOptions) { + var framebuffer = staticOptions[S_FRAMEBUFFER]; + if (framebuffer) { + framebuffer = framebufferState.getFramebuffer(framebuffer); + check$1.command(framebuffer, 'invalid framebuffer object'); + return createStaticDecl(function (env, block) { + var FRAMEBUFFER = env.link(framebuffer); + var shared = env.shared; + block.set( + shared.framebuffer, + '.next', + FRAMEBUFFER); + var CONTEXT = shared.context; + block.set( + CONTEXT, + '.' + S_FRAMEBUFFER_WIDTH, + FRAMEBUFFER + '.width'); + block.set( + CONTEXT, + '.' + S_FRAMEBUFFER_HEIGHT, + FRAMEBUFFER + '.height'); + return FRAMEBUFFER + }) + } else { + return createStaticDecl(function (env, scope) { + var shared = env.shared; + scope.set( + shared.framebuffer, + '.next', + 'null'); + var CONTEXT = shared.context; + scope.set( + CONTEXT, + '.' + S_FRAMEBUFFER_WIDTH, + CONTEXT + '.' + S_DRAWINGBUFFER_WIDTH); + scope.set( + CONTEXT, + '.' + S_FRAMEBUFFER_HEIGHT, + CONTEXT + '.' + S_DRAWINGBUFFER_HEIGHT); + return 'null' + }) + } + } else if (S_FRAMEBUFFER in dynamicOptions) { + var dyn = dynamicOptions[S_FRAMEBUFFER]; + return createDynamicDecl(dyn, function (env, scope) { + var FRAMEBUFFER_FUNC = env.invoke(scope, dyn); + var shared = env.shared; + var FRAMEBUFFER_STATE = shared.framebuffer; + var FRAMEBUFFER = scope.def( + FRAMEBUFFER_STATE, '.getFramebuffer(', FRAMEBUFFER_FUNC, ')'); + + check$1.optional(function () { + env.assert(scope, + '!' + FRAMEBUFFER_FUNC + '||' + FRAMEBUFFER, + 'invalid framebuffer object'); + }); + + scope.set( + FRAMEBUFFER_STATE, + '.next', + FRAMEBUFFER); + var CONTEXT = shared.context; + scope.set( + CONTEXT, + '.' + S_FRAMEBUFFER_WIDTH, + FRAMEBUFFER + '?' + FRAMEBUFFER + '.width:' + + CONTEXT + '.' + S_DRAWINGBUFFER_WIDTH); + scope.set( + CONTEXT, + '.' + S_FRAMEBUFFER_HEIGHT, + FRAMEBUFFER + + '?' + FRAMEBUFFER + '.height:' + + CONTEXT + '.' + S_DRAWINGBUFFER_HEIGHT); + return FRAMEBUFFER + }) + } else { + return null + } + } + + function parseViewportScissor (options, framebuffer, env) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + function parseBox (param) { + if (param in staticOptions) { + var box = staticOptions[param]; + check$1.commandType(box, 'object', 'invalid ' + param, env.commandStr); + + var isStatic = true; + var x = box.x | 0; + var y = box.y | 0; + var w, h; + if ('width' in box) { + w = box.width | 0; + check$1.command(w >= 0, 'invalid ' + param, env.commandStr); + } else { + isStatic = false; + } + if ('height' in box) { + h = box.height | 0; + check$1.command(h >= 0, 'invalid ' + param, env.commandStr); + } else { + isStatic = false; + } + + return new Declaration( + !isStatic && framebuffer && framebuffer.thisDep, + !isStatic && framebuffer && framebuffer.contextDep, + !isStatic && framebuffer && framebuffer.propDep, + function (env, scope) { + var CONTEXT = env.shared.context; + var BOX_W = w; + if (!('width' in box)) { + BOX_W = scope.def(CONTEXT, '.', S_FRAMEBUFFER_WIDTH, '-', x); + } + var BOX_H = h; + if (!('height' in box)) { + BOX_H = scope.def(CONTEXT, '.', S_FRAMEBUFFER_HEIGHT, '-', y); + } + return [x, y, BOX_W, BOX_H] + }) + } else if (param in dynamicOptions) { + var dynBox = dynamicOptions[param]; + var result = createDynamicDecl(dynBox, function (env, scope) { + var BOX = env.invoke(scope, dynBox); + + check$1.optional(function () { + env.assert(scope, + BOX + '&&typeof ' + BOX + '==="object"', + 'invalid ' + param); + }); + + var CONTEXT = env.shared.context; + var BOX_X = scope.def(BOX, '.x|0'); + var BOX_Y = scope.def(BOX, '.y|0'); + var BOX_W = scope.def( + '"width" in ', BOX, '?', BOX, '.width|0:', + '(', CONTEXT, '.', S_FRAMEBUFFER_WIDTH, '-', BOX_X, ')'); + var BOX_H = scope.def( + '"height" in ', BOX, '?', BOX, '.height|0:', + '(', CONTEXT, '.', S_FRAMEBUFFER_HEIGHT, '-', BOX_Y, ')'); + + check$1.optional(function () { + env.assert(scope, + BOX_W + '>=0&&' + + BOX_H + '>=0', + 'invalid ' + param); + }); + + return [BOX_X, BOX_Y, BOX_W, BOX_H] + }); + if (framebuffer) { + result.thisDep = result.thisDep || framebuffer.thisDep; + result.contextDep = result.contextDep || framebuffer.contextDep; + result.propDep = result.propDep || framebuffer.propDep; + } + return result + } else if (framebuffer) { + return new Declaration( + framebuffer.thisDep, + framebuffer.contextDep, + framebuffer.propDep, + function (env, scope) { + var CONTEXT = env.shared.context; + return [ + 0, 0, + scope.def(CONTEXT, '.', S_FRAMEBUFFER_WIDTH), + scope.def(CONTEXT, '.', S_FRAMEBUFFER_HEIGHT)] + }) + } else { + return null + } + } + + var viewport = parseBox(S_VIEWPORT); + + if (viewport) { + var prevViewport = viewport; + viewport = new Declaration( + viewport.thisDep, + viewport.contextDep, + viewport.propDep, + function (env, scope) { + var VIEWPORT = prevViewport.append(env, scope); + var CONTEXT = env.shared.context; + scope.set( + CONTEXT, + '.' + S_VIEWPORT_WIDTH, + VIEWPORT[2]); + scope.set( + CONTEXT, + '.' + S_VIEWPORT_HEIGHT, + VIEWPORT[3]); + return VIEWPORT + }); + } + + return { + viewport: viewport, + scissor_box: parseBox(S_SCISSOR_BOX) + } + } + + function parseProgram (options) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + function parseShader (name) { + if (name in staticOptions) { + var id = stringStore.id(staticOptions[name]); + check$1.optional(function () { + shaderState.shader(shaderType[name], id, check$1.guessCommand()); + }); + var result = createStaticDecl(function () { + return id + }); + result.id = id; + return result + } else if (name in dynamicOptions) { + var dyn = dynamicOptions[name]; + return createDynamicDecl(dyn, function (env, scope) { + var str = env.invoke(scope, dyn); + var id = scope.def(env.shared.strings, '.id(', str, ')'); + check$1.optional(function () { + scope( + env.shared.shader, '.shader(', + shaderType[name], ',', + id, ',', + env.command, ');'); + }); + return id + }) + } + return null + } + + var frag = parseShader(S_FRAG); + var vert = parseShader(S_VERT); + + var program = null; + var progVar; + if (isStatic(frag) && isStatic(vert)) { + program = shaderState.program(vert.id, frag.id); + progVar = createStaticDecl(function (env, scope) { + return env.link(program) + }); + } else { + progVar = new Declaration( + (frag && frag.thisDep) || (vert && vert.thisDep), + (frag && frag.contextDep) || (vert && vert.contextDep), + (frag && frag.propDep) || (vert && vert.propDep), + function (env, scope) { + var SHADER_STATE = env.shared.shader; + var fragId; + if (frag) { + fragId = frag.append(env, scope); + } else { + fragId = scope.def(SHADER_STATE, '.', S_FRAG); + } + var vertId; + if (vert) { + vertId = vert.append(env, scope); + } else { + vertId = scope.def(SHADER_STATE, '.', S_VERT); + } + var progDef = SHADER_STATE + '.program(' + vertId + ',' + fragId; + check$1.optional(function () { + progDef += ',' + env.command; + }); + return scope.def(progDef + ')') + }); + } + + return { + frag: frag, + vert: vert, + progVar: progVar, + program: program + } + } + + function parseDraw (options, env) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + function parseElements () { + if (S_ELEMENTS in staticOptions) { + var elements = staticOptions[S_ELEMENTS]; + if (isBufferArgs(elements)) { + elements = elementState.getElements(elementState.create(elements, true)); + } else if (elements) { + elements = elementState.getElements(elements); + check$1.command(elements, 'invalid elements', env.commandStr); + } + var result = createStaticDecl(function (env, scope) { + if (elements) { + var result = env.link(elements); + env.ELEMENTS = result; + return result + } + env.ELEMENTS = null; + return null + }); + result.value = elements; + return result + } else if (S_ELEMENTS in dynamicOptions) { + var dyn = dynamicOptions[S_ELEMENTS]; + return createDynamicDecl(dyn, function (env, scope) { + var shared = env.shared; + + var IS_BUFFER_ARGS = shared.isBufferArgs; + var ELEMENT_STATE = shared.elements; + + var elementDefn = env.invoke(scope, dyn); + var elements = scope.def('null'); + var elementStream = scope.def(IS_BUFFER_ARGS, '(', elementDefn, ')'); + + var ifte = env.cond(elementStream) + .then(elements, '=', ELEMENT_STATE, '.createStream(', elementDefn, ');') + .else(elements, '=', ELEMENT_STATE, '.getElements(', elementDefn, ');'); + + check$1.optional(function () { + env.assert(ifte.else, + '!' + elementDefn + '||' + elements, + 'invalid elements'); + }); + + scope.entry(ifte); + scope.exit( + env.cond(elementStream) + .then(ELEMENT_STATE, '.destroyStream(', elements, ');')); + + env.ELEMENTS = elements; + + return elements + }) + } + + return null + } + + var elements = parseElements(); + + function parsePrimitive () { + if (S_PRIMITIVE in staticOptions) { + var primitive = staticOptions[S_PRIMITIVE]; + check$1.commandParameter(primitive, primTypes, 'invalid primitve', env.commandStr); + return createStaticDecl(function (env, scope) { + return primTypes[primitive] + }) + } else if (S_PRIMITIVE in dynamicOptions) { + var dynPrimitive = dynamicOptions[S_PRIMITIVE]; + return createDynamicDecl(dynPrimitive, function (env, scope) { + var PRIM_TYPES = env.constants.primTypes; + var prim = env.invoke(scope, dynPrimitive); + check$1.optional(function () { + env.assert(scope, + prim + ' in ' + PRIM_TYPES, + 'invalid primitive, must be one of ' + Object.keys(primTypes)); + }); + return scope.def(PRIM_TYPES, '[', prim, ']') + }) + } else if (elements) { + if (isStatic(elements)) { + if (elements.value) { + return createStaticDecl(function (env, scope) { + return scope.def(env.ELEMENTS, '.primType') + }) + } else { + return createStaticDecl(function () { + return GL_TRIANGLES$1 + }) + } + } else { + return new Declaration( + elements.thisDep, + elements.contextDep, + elements.propDep, + function (env, scope) { + var elements = env.ELEMENTS; + return scope.def(elements, '?', elements, '.primType:', GL_TRIANGLES$1) + }) + } + } + return null + } + + function parseParam (param, isOffset) { + if (param in staticOptions) { + var value = staticOptions[param] | 0; + check$1.command(!isOffset || value >= 0, 'invalid ' + param, env.commandStr); + return createStaticDecl(function (env, scope) { + if (isOffset) { + env.OFFSET = value; + } + return value + }) + } else if (param in dynamicOptions) { + var dynValue = dynamicOptions[param]; + return createDynamicDecl(dynValue, function (env, scope) { + var result = env.invoke(scope, dynValue); + if (isOffset) { + env.OFFSET = result; + check$1.optional(function () { + env.assert(scope, + result + '>=0', + 'invalid ' + param); + }); + } + return result + }) + } else if (isOffset && elements) { + return createStaticDecl(function (env, scope) { + env.OFFSET = '0'; + return 0 + }) + } + return null + } + + var OFFSET = parseParam(S_OFFSET, true); + + function parseVertCount () { + if (S_COUNT in staticOptions) { + var count = staticOptions[S_COUNT] | 0; + check$1.command( + typeof count === 'number' && count >= 0, 'invalid vertex count', env.commandStr); + return createStaticDecl(function () { + return count + }) + } else if (S_COUNT in dynamicOptions) { + var dynCount = dynamicOptions[S_COUNT]; + return createDynamicDecl(dynCount, function (env, scope) { + var result = env.invoke(scope, dynCount); + check$1.optional(function () { + env.assert(scope, + 'typeof ' + result + '==="number"&&' + + result + '>=0&&' + + result + '===(' + result + '|0)', + 'invalid vertex count'); + }); + return result + }) + } else if (elements) { + if (isStatic(elements)) { + if (elements) { + if (OFFSET) { + return new Declaration( + OFFSET.thisDep, + OFFSET.contextDep, + OFFSET.propDep, + function (env, scope) { + var result = scope.def( + env.ELEMENTS, '.vertCount-', env.OFFSET); + + check$1.optional(function () { + env.assert(scope, + result + '>=0', + 'invalid vertex offset/element buffer too small'); + }); + + return result + }) + } else { + return createStaticDecl(function (env, scope) { + return scope.def(env.ELEMENTS, '.vertCount') + }) + } + } else { + var result = createStaticDecl(function () { + return -1 + }); + check$1.optional(function () { + result.MISSING = true; + }); + return result + } + } else { + var variable = new Declaration( + elements.thisDep || OFFSET.thisDep, + elements.contextDep || OFFSET.contextDep, + elements.propDep || OFFSET.propDep, + function (env, scope) { + var elements = env.ELEMENTS; + if (env.OFFSET) { + return scope.def(elements, '?', elements, '.vertCount-', + env.OFFSET, ':-1') + } + return scope.def(elements, '?', elements, '.vertCount:-1') + }); + check$1.optional(function () { + variable.DYNAMIC = true; + }); + return variable + } + } + return null + } + + return { + elements: elements, + primitive: parsePrimitive(), + count: parseVertCount(), + instances: parseParam(S_INSTANCES, false), + offset: OFFSET + } + } + + function parseGLState (options, env) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + var STATE = {}; + + GL_STATE_NAMES.forEach(function (prop) { + var param = propName(prop); + + function parseParam (parseStatic, parseDynamic) { + if (prop in staticOptions) { + var value = parseStatic(staticOptions[prop]); + STATE[param] = createStaticDecl(function () { + return value + }); + } else if (prop in dynamicOptions) { + var dyn = dynamicOptions[prop]; + STATE[param] = createDynamicDecl(dyn, function (env, scope) { + return parseDynamic(env, scope, env.invoke(scope, dyn)) + }); + } + } + + switch (prop) { + case S_CULL_ENABLE: + case S_BLEND_ENABLE: + case S_DITHER: + case S_STENCIL_ENABLE: + case S_DEPTH_ENABLE: + case S_SCISSOR_ENABLE: + case S_POLYGON_OFFSET_ENABLE: + case S_SAMPLE_ALPHA: + case S_SAMPLE_ENABLE: + case S_DEPTH_MASK: + return parseParam( + function (value) { + check$1.commandType(value, 'boolean', prop, env.commandStr); + return value + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + 'typeof ' + value + '==="boolean"', + 'invalid flag ' + prop, env.commandStr); + }); + return value + }) + + case S_DEPTH_FUNC: + return parseParam( + function (value) { + check$1.commandParameter(value, compareFuncs, 'invalid ' + prop, env.commandStr); + return compareFuncs[value] + }, + function (env, scope, value) { + var COMPARE_FUNCS = env.constants.compareFuncs; + check$1.optional(function () { + env.assert(scope, + value + ' in ' + COMPARE_FUNCS, + 'invalid ' + prop + ', must be one of ' + Object.keys(compareFuncs)); + }); + return scope.def(COMPARE_FUNCS, '[', value, ']') + }) + + case S_DEPTH_RANGE: + return parseParam( + function (value) { + check$1.command( + isArrayLike(value) && + value.length === 2 && + typeof value[0] === 'number' && + typeof value[1] === 'number' && + value[0] <= value[1], + 'depth range is 2d array', + env.commandStr); + return value + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + env.shared.isArrayLike + '(' + value + ')&&' + + value + '.length===2&&' + + 'typeof ' + value + '[0]==="number"&&' + + 'typeof ' + value + '[1]==="number"&&' + + value + '[0]<=' + value + '[1]', + 'depth range must be a 2d array'); + }); + + var Z_NEAR = scope.def('+', value, '[0]'); + var Z_FAR = scope.def('+', value, '[1]'); + return [Z_NEAR, Z_FAR] + }) + + case S_BLEND_FUNC: + return parseParam( + function (value) { + check$1.commandType(value, 'object', 'blend.func', env.commandStr); + var srcRGB = ('srcRGB' in value ? value.srcRGB : value.src); + var srcAlpha = ('srcAlpha' in value ? value.srcAlpha : value.src); + var dstRGB = ('dstRGB' in value ? value.dstRGB : value.dst); + var dstAlpha = ('dstAlpha' in value ? value.dstAlpha : value.dst); + check$1.commandParameter(srcRGB, blendFuncs, param + '.srcRGB', env.commandStr); + check$1.commandParameter(srcAlpha, blendFuncs, param + '.srcAlpha', env.commandStr); + check$1.commandParameter(dstRGB, blendFuncs, param + '.dstRGB', env.commandStr); + check$1.commandParameter(dstAlpha, blendFuncs, param + '.dstAlpha', env.commandStr); + + check$1.command( + (invalidBlendCombinations.indexOf(srcRGB + ', ' + dstRGB) === -1), + 'unallowed blending combination (srcRGB, dstRGB) = (' + srcRGB + ', ' + dstRGB + ')', env.commandStr); + + return [ + blendFuncs[srcRGB], + blendFuncs[dstRGB], + blendFuncs[srcAlpha], + blendFuncs[dstAlpha] + ] + }, + function (env, scope, value) { + var BLEND_FUNCS = env.constants.blendFuncs; + + check$1.optional(function () { + env.assert(scope, + value + '&&typeof ' + value + '==="object"', + 'invalid blend func, must be an object'); + }); + + function read (prefix, suffix) { + var func = scope.def( + '"', prefix, suffix, '" in ', value, + '?', value, '.', prefix, suffix, + ':', value, '.', prefix); + + check$1.optional(function () { + env.assert(scope, + func + ' in ' + BLEND_FUNCS, + 'invalid ' + prop + '.' + prefix + suffix + ', must be one of ' + Object.keys(blendFuncs)); + }); + + return func + } + + var srcRGB = read('src', 'RGB'); + var dstRGB = read('dst', 'RGB'); + + check$1.optional(function () { + var INVALID_BLEND_COMBINATIONS = env.constants.invalidBlendCombinations; + + env.assert(scope, + INVALID_BLEND_COMBINATIONS + + '.indexOf(' + srcRGB + '+", "+' + dstRGB + ') === -1 ', + 'unallowed blending combination for (srcRGB, dstRGB)' + ); + }); + + var SRC_RGB = scope.def(BLEND_FUNCS, '[', srcRGB, ']'); + var SRC_ALPHA = scope.def(BLEND_FUNCS, '[', read('src', 'Alpha'), ']'); + var DST_RGB = scope.def(BLEND_FUNCS, '[', dstRGB, ']'); + var DST_ALPHA = scope.def(BLEND_FUNCS, '[', read('dst', 'Alpha'), ']'); + + return [SRC_RGB, DST_RGB, SRC_ALPHA, DST_ALPHA] + }) + + case S_BLEND_EQUATION: + return parseParam( + function (value) { + if (typeof value === 'string') { + check$1.commandParameter(value, blendEquations, 'invalid ' + prop, env.commandStr); + return [ + blendEquations[value], + blendEquations[value] + ] + } else if (typeof value === 'object') { + check$1.commandParameter( + value.rgb, blendEquations, prop + '.rgb', env.commandStr); + check$1.commandParameter( + value.alpha, blendEquations, prop + '.alpha', env.commandStr); + return [ + blendEquations[value.rgb], + blendEquations[value.alpha] + ] + } else { + check$1.commandRaise('invalid blend.equation', env.commandStr); + } + }, + function (env, scope, value) { + var BLEND_EQUATIONS = env.constants.blendEquations; + + var RGB = scope.def(); + var ALPHA = scope.def(); + + var ifte = env.cond('typeof ', value, '==="string"'); + + check$1.optional(function () { + function checkProp (block, name, value) { + env.assert(block, + value + ' in ' + BLEND_EQUATIONS, + 'invalid ' + name + ', must be one of ' + Object.keys(blendEquations)); + } + checkProp(ifte.then, prop, value); + + env.assert(ifte.else, + value + '&&typeof ' + value + '==="object"', + 'invalid ' + prop); + checkProp(ifte.else, prop + '.rgb', value + '.rgb'); + checkProp(ifte.else, prop + '.alpha', value + '.alpha'); + }); + + ifte.then( + RGB, '=', ALPHA, '=', BLEND_EQUATIONS, '[', value, '];'); + ifte.else( + RGB, '=', BLEND_EQUATIONS, '[', value, '.rgb];', + ALPHA, '=', BLEND_EQUATIONS, '[', value, '.alpha];'); + + scope(ifte); + + return [RGB, ALPHA] + }) + + case S_BLEND_COLOR: + return parseParam( + function (value) { + check$1.command( + isArrayLike(value) && + value.length === 4, + 'blend.color must be a 4d array', env.commandStr); + return loop(4, function (i) { + return +value[i] + }) + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + env.shared.isArrayLike + '(' + value + ')&&' + + value + '.length===4', + 'blend.color must be a 4d array'); + }); + return loop(4, function (i) { + return scope.def('+', value, '[', i, ']') + }) + }) + + case S_STENCIL_MASK: + return parseParam( + function (value) { + check$1.commandType(value, 'number', param, env.commandStr); + return value | 0 + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + 'typeof ' + value + '==="number"', + 'invalid stencil.mask'); + }); + return scope.def(value, '|0') + }) + + case S_STENCIL_FUNC: + return parseParam( + function (value) { + check$1.commandType(value, 'object', param, env.commandStr); + var cmp = value.cmp || 'keep'; + var ref = value.ref || 0; + var mask = 'mask' in value ? value.mask : -1; + check$1.commandParameter(cmp, compareFuncs, prop + '.cmp', env.commandStr); + check$1.commandType(ref, 'number', prop + '.ref', env.commandStr); + check$1.commandType(mask, 'number', prop + '.mask', env.commandStr); + return [ + compareFuncs[cmp], + ref, + mask + ] + }, + function (env, scope, value) { + var COMPARE_FUNCS = env.constants.compareFuncs; + check$1.optional(function () { + function assert () { + env.assert(scope, + Array.prototype.join.call(arguments, ''), + 'invalid stencil.func'); + } + assert(value + '&&typeof ', value, '==="object"'); + assert('!("cmp" in ', value, ')||(', + value, '.cmp in ', COMPARE_FUNCS, ')'); + }); + var cmp = scope.def( + '"cmp" in ', value, + '?', COMPARE_FUNCS, '[', value, '.cmp]', + ':', GL_KEEP); + var ref = scope.def(value, '.ref|0'); + var mask = scope.def( + '"mask" in ', value, + '?', value, '.mask|0:-1'); + return [cmp, ref, mask] + }) + + case S_STENCIL_OPFRONT: + case S_STENCIL_OPBACK: + return parseParam( + function (value) { + check$1.commandType(value, 'object', param, env.commandStr); + var fail = value.fail || 'keep'; + var zfail = value.zfail || 'keep'; + var zpass = value.zpass || 'keep'; + check$1.commandParameter(fail, stencilOps, prop + '.fail', env.commandStr); + check$1.commandParameter(zfail, stencilOps, prop + '.zfail', env.commandStr); + check$1.commandParameter(zpass, stencilOps, prop + '.zpass', env.commandStr); + return [ + prop === S_STENCIL_OPBACK ? GL_BACK : GL_FRONT, + stencilOps[fail], + stencilOps[zfail], + stencilOps[zpass] + ] + }, + function (env, scope, value) { + var STENCIL_OPS = env.constants.stencilOps; + + check$1.optional(function () { + env.assert(scope, + value + '&&typeof ' + value + '==="object"', + 'invalid ' + prop); + }); + + function read (name) { + check$1.optional(function () { + env.assert(scope, + '!("' + name + '" in ' + value + ')||' + + '(' + value + '.' + name + ' in ' + STENCIL_OPS + ')', + 'invalid ' + prop + '.' + name + ', must be one of ' + Object.keys(stencilOps)); + }); + + return scope.def( + '"', name, '" in ', value, + '?', STENCIL_OPS, '[', value, '.', name, ']:', + GL_KEEP) + } + + return [ + prop === S_STENCIL_OPBACK ? GL_BACK : GL_FRONT, + read('fail'), + read('zfail'), + read('zpass') + ] + }) + + case S_POLYGON_OFFSET_OFFSET: + return parseParam( + function (value) { + check$1.commandType(value, 'object', param, env.commandStr); + var factor = value.factor | 0; + var units = value.units | 0; + check$1.commandType(factor, 'number', param + '.factor', env.commandStr); + check$1.commandType(units, 'number', param + '.units', env.commandStr); + return [factor, units] + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + value + '&&typeof ' + value + '==="object"', + 'invalid ' + prop); + }); + + var FACTOR = scope.def(value, '.factor|0'); + var UNITS = scope.def(value, '.units|0'); + + return [FACTOR, UNITS] + }) + + case S_CULL_FACE: + return parseParam( + function (value) { + var face = 0; + if (value === 'front') { + face = GL_FRONT; + } else if (value === 'back') { + face = GL_BACK; + } + check$1.command(!!face, param, env.commandStr); + return face + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + value + '==="front"||' + + value + '==="back"', + 'invalid cull.face'); + }); + return scope.def(value, '==="front"?', GL_FRONT, ':', GL_BACK) + }) + + case S_LINE_WIDTH: + return parseParam( + function (value) { + check$1.command( + typeof value === 'number' && + value >= limits.lineWidthDims[0] && + value <= limits.lineWidthDims[1], + 'invalid line width, must be a positive number between ' + + limits.lineWidthDims[0] + ' and ' + limits.lineWidthDims[1], env.commandStr); + return value + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + 'typeof ' + value + '==="number"&&' + + value + '>=' + limits.lineWidthDims[0] + '&&' + + value + '<=' + limits.lineWidthDims[1], + 'invalid line width'); + }); + + return value + }) + + case S_FRONT_FACE: + return parseParam( + function (value) { + check$1.commandParameter(value, orientationType, param, env.commandStr); + return orientationType[value] + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + value + '==="cw"||' + + value + '==="ccw"', + 'invalid frontFace, must be one of cw,ccw'); + }); + return scope.def(value + '==="cw"?' + GL_CW + ':' + GL_CCW) + }) + + case S_COLOR_MASK: + return parseParam( + function (value) { + check$1.command( + isArrayLike(value) && value.length === 4, + 'color.mask must be length 4 array', env.commandStr); + return value.map(function (v) { return !!v }) + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + env.shared.isArrayLike + '(' + value + ')&&' + + value + '.length===4', + 'invalid color.mask'); + }); + return loop(4, function (i) { + return '!!' + value + '[' + i + ']' + }) + }) + + case S_SAMPLE_COVERAGE: + return parseParam( + function (value) { + check$1.command(typeof value === 'object' && value, param, env.commandStr); + var sampleValue = 'value' in value ? value.value : 1; + var sampleInvert = !!value.invert; + check$1.command( + typeof sampleValue === 'number' && + sampleValue >= 0 && sampleValue <= 1, + 'sample.coverage.value must be a number between 0 and 1', env.commandStr); + return [sampleValue, sampleInvert] + }, + function (env, scope, value) { + check$1.optional(function () { + env.assert(scope, + value + '&&typeof ' + value + '==="object"', + 'invalid sample.coverage'); + }); + var VALUE = scope.def( + '"value" in ', value, '?+', value, '.value:1'); + var INVERT = scope.def('!!', value, '.invert'); + return [VALUE, INVERT] + }) + } + }); + + return STATE + } + + function parseUniforms (uniforms, env) { + var staticUniforms = uniforms.static; + var dynamicUniforms = uniforms.dynamic; + + var UNIFORMS = {}; + + Object.keys(staticUniforms).forEach(function (name) { + var value = staticUniforms[name]; + var result; + if (typeof value === 'number' || + typeof value === 'boolean') { + result = createStaticDecl(function () { + return value + }); + } else if (typeof value === 'function') { + var reglType = value._reglType; + if (reglType === 'texture2d' || + reglType === 'textureCube') { + result = createStaticDecl(function (env) { + return env.link(value) + }); + } else if (reglType === 'framebuffer' || + reglType === 'framebufferCube') { + check$1.command(value.color.length > 0, + 'missing color attachment for framebuffer sent to uniform "' + name + '"', env.commandStr); + result = createStaticDecl(function (env) { + return env.link(value.color[0]) + }); + } else { + check$1.commandRaise('invalid data for uniform "' + name + '"', env.commandStr); + } + } else if (isArrayLike(value)) { + result = createStaticDecl(function (env) { + var ITEM = env.global.def('[', + loop(value.length, function (i) { + check$1.command( + typeof value[i] === 'number' || + typeof value[i] === 'boolean', + 'invalid uniform ' + name, env.commandStr); + return value[i] + }), ']'); + return ITEM + }); + } else { + check$1.commandRaise('invalid or missing data for uniform "' + name + '"', env.commandStr); + } + result.value = value; + UNIFORMS[name] = result; + }); + + Object.keys(dynamicUniforms).forEach(function (key) { + var dyn = dynamicUniforms[key]; + UNIFORMS[key] = createDynamicDecl(dyn, function (env, scope) { + return env.invoke(scope, dyn) + }); + }); + + return UNIFORMS + } + + function parseAttributes (attributes, env) { + var staticAttributes = attributes.static; + var dynamicAttributes = attributes.dynamic; + + var attributeDefs = {}; + + Object.keys(staticAttributes).forEach(function (attribute) { + var value = staticAttributes[attribute]; + var id = stringStore.id(attribute); + + var record = new AttributeRecord(); + if (isBufferArgs(value)) { + record.state = ATTRIB_STATE_POINTER; + record.buffer = bufferState.getBuffer( + bufferState.create(value, GL_ARRAY_BUFFER$1, false, true)); + record.type = 0; + } else { + var buffer = bufferState.getBuffer(value); + if (buffer) { + record.state = ATTRIB_STATE_POINTER; + record.buffer = buffer; + record.type = 0; + } else { + check$1.command(typeof value === 'object' && value, + 'invalid data for attribute ' + attribute, env.commandStr); + if ('constant' in value) { + var constant = value.constant; + record.buffer = 'null'; + record.state = ATTRIB_STATE_CONSTANT; + if (typeof constant === 'number') { + record.x = constant; + } else { + check$1.command( + isArrayLike(constant) && + constant.length > 0 && + constant.length <= 4, + 'invalid constant for attribute ' + attribute, env.commandStr); + CUTE_COMPONENTS.forEach(function (c, i) { + if (i < constant.length) { + record[c] = constant[i]; + } + }); + } + } else { + if (isBufferArgs(value.buffer)) { + buffer = bufferState.getBuffer( + bufferState.create(value.buffer, GL_ARRAY_BUFFER$1, false, true)); + } else { + buffer = bufferState.getBuffer(value.buffer); + } + check$1.command(!!buffer, 'missing buffer for attribute "' + attribute + '"', env.commandStr); + + var offset = value.offset | 0; + check$1.command(offset >= 0, + 'invalid offset for attribute "' + attribute + '"', env.commandStr); + + var stride = value.stride | 0; + check$1.command(stride >= 0 && stride < 256, + 'invalid stride for attribute "' + attribute + '", must be integer betweeen [0, 255]', env.commandStr); + + var size = value.size | 0; + check$1.command(!('size' in value) || (size > 0 && size <= 4), + 'invalid size for attribute "' + attribute + '", must be 1,2,3,4', env.commandStr); + + var normalized = !!value.normalized; + + var type = 0; + if ('type' in value) { + check$1.commandParameter( + value.type, glTypes, + 'invalid type for attribute ' + attribute, env.commandStr); + type = glTypes[value.type]; + } + + var divisor = value.divisor | 0; + if ('divisor' in value) { + check$1.command(divisor === 0 || extInstancing, + 'cannot specify divisor for attribute "' + attribute + '", instancing not supported', env.commandStr); + check$1.command(divisor >= 0, + 'invalid divisor for attribute "' + attribute + '"', env.commandStr); + } + + check$1.optional(function () { + var command = env.commandStr; + + var VALID_KEYS = [ + 'buffer', + 'offset', + 'divisor', + 'normalized', + 'type', + 'size', + 'stride' + ]; + + Object.keys(value).forEach(function (prop) { + check$1.command( + VALID_KEYS.indexOf(prop) >= 0, + 'unknown parameter "' + prop + '" for attribute pointer "' + attribute + '" (valid parameters are ' + VALID_KEYS + ')', + command); + }); + }); + + record.buffer = buffer; + record.state = ATTRIB_STATE_POINTER; + record.size = size; + record.normalized = normalized; + record.type = type || buffer.dtype; + record.offset = offset; + record.stride = stride; + record.divisor = divisor; + } + } + } + + attributeDefs[attribute] = createStaticDecl(function (env, scope) { + var cache = env.attribCache; + if (id in cache) { + return cache[id] + } + var result = { + isStream: false + }; + Object.keys(record).forEach(function (key) { + result[key] = record[key]; + }); + if (record.buffer) { + result.buffer = env.link(record.buffer); + result.type = result.type || (result.buffer + '.dtype'); + } + cache[id] = result; + return result + }); + }); + + Object.keys(dynamicAttributes).forEach(function (attribute) { + var dyn = dynamicAttributes[attribute]; + + function appendAttributeCode (env, block) { + var VALUE = env.invoke(block, dyn); + + var shared = env.shared; + + var IS_BUFFER_ARGS = shared.isBufferArgs; + var BUFFER_STATE = shared.buffer; + + // Perform validation on attribute + check$1.optional(function () { + env.assert(block, + VALUE + '&&(typeof ' + VALUE + '==="object"||typeof ' + + VALUE + '==="function")&&(' + + IS_BUFFER_ARGS + '(' + VALUE + ')||' + + BUFFER_STATE + '.getBuffer(' + VALUE + ')||' + + BUFFER_STATE + '.getBuffer(' + VALUE + '.buffer)||' + + IS_BUFFER_ARGS + '(' + VALUE + '.buffer)||' + + '("constant" in ' + VALUE + + '&&(typeof ' + VALUE + '.constant==="number"||' + + shared.isArrayLike + '(' + VALUE + '.constant))))', + 'invalid dynamic attribute "' + attribute + '"'); + }); + + // allocate names for result + var result = { + isStream: block.def(false) + }; + var defaultRecord = new AttributeRecord(); + defaultRecord.state = ATTRIB_STATE_POINTER; + Object.keys(defaultRecord).forEach(function (key) { + result[key] = block.def('' + defaultRecord[key]); + }); + + var BUFFER = result.buffer; + var TYPE = result.type; + block( + 'if(', IS_BUFFER_ARGS, '(', VALUE, ')){', + result.isStream, '=true;', + BUFFER, '=', BUFFER_STATE, '.createStream(', GL_ARRAY_BUFFER$1, ',', VALUE, ');', + TYPE, '=', BUFFER, '.dtype;', + '}else{', + BUFFER, '=', BUFFER_STATE, '.getBuffer(', VALUE, ');', + 'if(', BUFFER, '){', + TYPE, '=', BUFFER, '.dtype;', + '}else if("constant" in ', VALUE, '){', + result.state, '=', ATTRIB_STATE_CONSTANT, ';', + 'if(typeof ' + VALUE + '.constant === "number"){', + result[CUTE_COMPONENTS[0]], '=', VALUE, '.constant;', + CUTE_COMPONENTS.slice(1).map(function (n) { + return result[n] + }).join('='), '=0;', + '}else{', + CUTE_COMPONENTS.map(function (name, i) { + return ( + result[name] + '=' + VALUE + '.constant.length>' + i + + '?' + VALUE + '.constant[' + i + ']:0;' + ) + }).join(''), + '}}else{', + 'if(', IS_BUFFER_ARGS, '(', VALUE, '.buffer)){', + BUFFER, '=', BUFFER_STATE, '.createStream(', GL_ARRAY_BUFFER$1, ',', VALUE, '.buffer);', + '}else{', + BUFFER, '=', BUFFER_STATE, '.getBuffer(', VALUE, '.buffer);', + '}', + TYPE, '="type" in ', VALUE, '?', + shared.glTypes, '[', VALUE, '.type]:', BUFFER, '.dtype;', + result.normalized, '=!!', VALUE, '.normalized;'); + function emitReadRecord (name) { + block(result[name], '=', VALUE, '.', name, '|0;'); + } + emitReadRecord('size'); + emitReadRecord('offset'); + emitReadRecord('stride'); + emitReadRecord('divisor'); + + block('}}'); + + block.exit( + 'if(', result.isStream, '){', + BUFFER_STATE, '.destroyStream(', BUFFER, ');', + '}'); + + return result + } + + attributeDefs[attribute] = createDynamicDecl(dyn, appendAttributeCode); + }); + + return attributeDefs + } + + function parseContext (context) { + var staticContext = context.static; + var dynamicContext = context.dynamic; + var result = {}; + + Object.keys(staticContext).forEach(function (name) { + var value = staticContext[name]; + result[name] = createStaticDecl(function (env, scope) { + if (typeof value === 'number' || typeof value === 'boolean') { + return '' + value + } else { + return env.link(value) + } + }); + }); + + Object.keys(dynamicContext).forEach(function (name) { + var dyn = dynamicContext[name]; + result[name] = createDynamicDecl(dyn, function (env, scope) { + return env.invoke(scope, dyn) + }); + }); + + return result + } + + function parseArguments (options, attributes, uniforms, context, env) { + var staticOptions = options.static; + var dynamicOptions = options.dynamic; + + check$1.optional(function () { + var KEY_NAMES = [ + S_FRAMEBUFFER, + S_VERT, + S_FRAG, + S_ELEMENTS, + S_PRIMITIVE, + S_OFFSET, + S_COUNT, + S_INSTANCES, + S_PROFILE + ].concat(GL_STATE_NAMES); + + function checkKeys (dict) { + Object.keys(dict).forEach(function (key) { + check$1.command( + KEY_NAMES.indexOf(key) >= 0, + 'unknown parameter "' + key + '"', + env.commandStr); + }); + } + + checkKeys(staticOptions); + checkKeys(dynamicOptions); + }); + + var framebuffer = parseFramebuffer(options, env); + var viewportAndScissor = parseViewportScissor(options, framebuffer, env); + var draw = parseDraw(options, env); + var state = parseGLState(options, env); + var shader = parseProgram(options, env); + + function copyBox (name) { + var defn = viewportAndScissor[name]; + if (defn) { + state[name] = defn; + } + } + copyBox(S_VIEWPORT); + copyBox(propName(S_SCISSOR_BOX)); + + var dirty = Object.keys(state).length > 0; + + var result = { + framebuffer: framebuffer, + draw: draw, + shader: shader, + state: state, + dirty: dirty + }; + + result.profile = parseProfile(options, env); + result.uniforms = parseUniforms(uniforms, env); + result.attributes = parseAttributes(attributes, env); + result.context = parseContext(context, env); + return result + } + + // =================================================== + // =================================================== + // COMMON UPDATE FUNCTIONS + // =================================================== + // =================================================== + function emitContext (env, scope, context) { + var shared = env.shared; + var CONTEXT = shared.context; + + var contextEnter = env.scope(); + + Object.keys(context).forEach(function (name) { + scope.save(CONTEXT, '.' + name); + var defn = context[name]; + contextEnter(CONTEXT, '.', name, '=', defn.append(env, scope), ';'); + }); + + scope(contextEnter); + } + + // =================================================== + // =================================================== + // COMMON DRAWING FUNCTIONS + // =================================================== + // =================================================== + function emitPollFramebuffer (env, scope, framebuffer, skipCheck) { + var shared = env.shared; + + var GL = shared.gl; + var FRAMEBUFFER_STATE = shared.framebuffer; + var EXT_DRAW_BUFFERS; + if (extDrawBuffers) { + EXT_DRAW_BUFFERS = scope.def(shared.extensions, '.webgl_draw_buffers'); + } + + var constants = env.constants; + + var DRAW_BUFFERS = constants.drawBuffer; + var BACK_BUFFER = constants.backBuffer; + + var NEXT; + if (framebuffer) { + NEXT = framebuffer.append(env, scope); + } else { + NEXT = scope.def(FRAMEBUFFER_STATE, '.next'); + } + + if (!skipCheck) { + scope('if(', NEXT, '!==', FRAMEBUFFER_STATE, '.cur){'); + } + scope( + 'if(', NEXT, '){', + GL, '.bindFramebuffer(', GL_FRAMEBUFFER$2, ',', NEXT, '.framebuffer);'); + if (extDrawBuffers) { + scope(EXT_DRAW_BUFFERS, '.drawBuffersWEBGL(', + DRAW_BUFFERS, '[', NEXT, '.colorAttachments.length]);'); + } + scope('}else{', + GL, '.bindFramebuffer(', GL_FRAMEBUFFER$2, ',null);'); + if (extDrawBuffers) { + scope(EXT_DRAW_BUFFERS, '.drawBuffersWEBGL(', BACK_BUFFER, ');'); + } + scope( + '}', + FRAMEBUFFER_STATE, '.cur=', NEXT, ';'); + if (!skipCheck) { + scope('}'); + } + } + + function emitPollState (env, scope, args) { + var shared = env.shared; + + var GL = shared.gl; + + var CURRENT_VARS = env.current; + var NEXT_VARS = env.next; + var CURRENT_STATE = shared.current; + var NEXT_STATE = shared.next; + + var block = env.cond(CURRENT_STATE, '.dirty'); + + GL_STATE_NAMES.forEach(function (prop) { + var param = propName(prop); + if (param in args.state) { + return + } + + var NEXT, CURRENT; + if (param in NEXT_VARS) { + NEXT = NEXT_VARS[param]; + CURRENT = CURRENT_VARS[param]; + var parts = loop(currentState[param].length, function (i) { + return block.def(NEXT, '[', i, ']') + }); + block(env.cond(parts.map(function (p, i) { + return p + '!==' + CURRENT + '[' + i + ']' + }).join('||')) + .then( + GL, '.', GL_VARIABLES[param], '(', parts, ');', + parts.map(function (p, i) { + return CURRENT + '[' + i + ']=' + p + }).join(';'), ';')); + } else { + NEXT = block.def(NEXT_STATE, '.', param); + var ifte = env.cond(NEXT, '!==', CURRENT_STATE, '.', param); + block(ifte); + if (param in GL_FLAGS) { + ifte( + env.cond(NEXT) + .then(GL, '.enable(', GL_FLAGS[param], ');') + .else(GL, '.disable(', GL_FLAGS[param], ');'), + CURRENT_STATE, '.', param, '=', NEXT, ';'); + } else { + ifte( + GL, '.', GL_VARIABLES[param], '(', NEXT, ');', + CURRENT_STATE, '.', param, '=', NEXT, ';'); + } + } + }); + if (Object.keys(args.state).length === 0) { + block(CURRENT_STATE, '.dirty=false;'); + } + scope(block); + } + + function emitSetOptions (env, scope, options, filter) { + var shared = env.shared; + var CURRENT_VARS = env.current; + var CURRENT_STATE = shared.current; + var GL = shared.gl; + sortState(Object.keys(options)).forEach(function (param) { + var defn = options[param]; + if (filter && !filter(defn)) { + return + } + var variable = defn.append(env, scope); + if (GL_FLAGS[param]) { + var flag = GL_FLAGS[param]; + if (isStatic(defn)) { + if (variable) { + scope(GL, '.enable(', flag, ');'); + } else { + scope(GL, '.disable(', flag, ');'); + } + } else { + scope(env.cond(variable) + .then(GL, '.enable(', flag, ');') + .else(GL, '.disable(', flag, ');')); + } + scope(CURRENT_STATE, '.', param, '=', variable, ';'); + } else if (isArrayLike(variable)) { + var CURRENT = CURRENT_VARS[param]; + scope( + GL, '.', GL_VARIABLES[param], '(', variable, ');', + variable.map(function (v, i) { + return CURRENT + '[' + i + ']=' + v + }).join(';'), ';'); + } else { + scope( + GL, '.', GL_VARIABLES[param], '(', variable, ');', + CURRENT_STATE, '.', param, '=', variable, ';'); + } + }); + } + + function injectExtensions (env, scope) { + if (extInstancing) { + env.instancing = scope.def( + env.shared.extensions, '.angle_instanced_arrays'); + } + } + + function emitProfile (env, scope, args, useScope, incrementCounter) { + var shared = env.shared; + var STATS = env.stats; + var CURRENT_STATE = shared.current; + var TIMER = shared.timer; + var profileArg = args.profile; + + function perfCounter () { + if (typeof performance === 'undefined') { + return 'Date.now()' + } else { + return 'performance.now()' + } + } + + var CPU_START, QUERY_COUNTER; + function emitProfileStart (block) { + CPU_START = scope.def(); + block(CPU_START, '=', perfCounter(), ';'); + if (typeof incrementCounter === 'string') { + block(STATS, '.count+=', incrementCounter, ';'); + } else { + block(STATS, '.count++;'); + } + if (timer) { + if (useScope) { + QUERY_COUNTER = scope.def(); + block(QUERY_COUNTER, '=', TIMER, '.getNumPendingQueries();'); + } else { + block(TIMER, '.beginQuery(', STATS, ');'); + } + } + } + + function emitProfileEnd (block) { + block(STATS, '.cpuTime+=', perfCounter(), '-', CPU_START, ';'); + if (timer) { + if (useScope) { + block(TIMER, '.pushScopeStats(', + QUERY_COUNTER, ',', + TIMER, '.getNumPendingQueries(),', + STATS, ');'); + } else { + block(TIMER, '.endQuery();'); + } + } + } + + function scopeProfile (value) { + var prev = scope.def(CURRENT_STATE, '.profile'); + scope(CURRENT_STATE, '.profile=', value, ';'); + scope.exit(CURRENT_STATE, '.profile=', prev, ';'); + } + + var USE_PROFILE; + if (profileArg) { + if (isStatic(profileArg)) { + if (profileArg.enable) { + emitProfileStart(scope); + emitProfileEnd(scope.exit); + scopeProfile('true'); + } else { + scopeProfile('false'); + } + return + } + USE_PROFILE = profileArg.append(env, scope); + scopeProfile(USE_PROFILE); + } else { + USE_PROFILE = scope.def(CURRENT_STATE, '.profile'); + } + + var start = env.block(); + emitProfileStart(start); + scope('if(', USE_PROFILE, '){', start, '}'); + var end = env.block(); + emitProfileEnd(end); + scope.exit('if(', USE_PROFILE, '){', end, '}'); + } + + function emitAttributes (env, scope, args, attributes, filter) { + var shared = env.shared; + + function typeLength (x) { + switch (x) { + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + return 2 + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + return 3 + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + return 4 + default: + return 1 + } + } + + function emitBindAttribute (ATTRIBUTE, size, record) { + var GL = shared.gl; + + var LOCATION = scope.def(ATTRIBUTE, '.location'); + var BINDING = scope.def(shared.attributes, '[', LOCATION, ']'); + + var STATE = record.state; + var BUFFER = record.buffer; + var CONST_COMPONENTS = [ + record.x, + record.y, + record.z, + record.w + ]; + + var COMMON_KEYS = [ + 'buffer', + 'normalized', + 'offset', + 'stride' + ]; + + function emitBuffer () { + scope( + 'if(!', BINDING, '.buffer){', + GL, '.enableVertexAttribArray(', LOCATION, ');}'); + + var TYPE = record.type; + var SIZE; + if (!record.size) { + SIZE = size; + } else { + SIZE = scope.def(record.size, '||', size); + } + + scope('if(', + BINDING, '.type!==', TYPE, '||', + BINDING, '.size!==', SIZE, '||', + COMMON_KEYS.map(function (key) { + return BINDING + '.' + key + '!==' + record[key] + }).join('||'), + '){', + GL, '.bindBuffer(', GL_ARRAY_BUFFER$1, ',', BUFFER, '.buffer);', + GL, '.vertexAttribPointer(', [ + LOCATION, + SIZE, + TYPE, + record.normalized, + record.stride, + record.offset + ], ');', + BINDING, '.type=', TYPE, ';', + BINDING, '.size=', SIZE, ';', + COMMON_KEYS.map(function (key) { + return BINDING + '.' + key + '=' + record[key] + ';' + }).join(''), + '}'); + + if (extInstancing) { + var DIVISOR = record.divisor; + scope( + 'if(', BINDING, '.divisor!==', DIVISOR, '){', + env.instancing, '.vertexAttribDivisorANGLE(', [LOCATION, DIVISOR], ');', + BINDING, '.divisor=', DIVISOR, ';}'); + } + } + + function emitConstant () { + scope( + 'if(', BINDING, '.buffer){', + GL, '.disableVertexAttribArray(', LOCATION, ');', + '}if(', CUTE_COMPONENTS.map(function (c, i) { + return BINDING + '.' + c + '!==' + CONST_COMPONENTS[i] + }).join('||'), '){', + GL, '.vertexAttrib4f(', LOCATION, ',', CONST_COMPONENTS, ');', + CUTE_COMPONENTS.map(function (c, i) { + return BINDING + '.' + c + '=' + CONST_COMPONENTS[i] + ';' + }).join(''), + '}'); + } + + if (STATE === ATTRIB_STATE_POINTER) { + emitBuffer(); + } else if (STATE === ATTRIB_STATE_CONSTANT) { + emitConstant(); + } else { + scope('if(', STATE, '===', ATTRIB_STATE_POINTER, '){'); + emitBuffer(); + scope('}else{'); + emitConstant(); + scope('}'); + } + } + + attributes.forEach(function (attribute) { + var name = attribute.name; + var arg = args.attributes[name]; + var record; + if (arg) { + if (!filter(arg)) { + return + } + record = arg.append(env, scope); + } else { + if (!filter(SCOPE_DECL)) { + return + } + var scopeAttrib = env.scopeAttrib(name); + check$1.optional(function () { + env.assert(scope, + scopeAttrib + '.state', + 'missing attribute ' + name); + }); + record = {}; + Object.keys(new AttributeRecord()).forEach(function (key) { + record[key] = scope.def(scopeAttrib, '.', key); + }); + } + emitBindAttribute( + env.link(attribute), typeLength(attribute.info.type), record); + }); + } + + function emitUniforms (env, scope, args, uniforms, filter) { + var shared = env.shared; + var GL = shared.gl; + + var infix; + for (var i = 0; i < uniforms.length; ++i) { + var uniform = uniforms[i]; + var name = uniform.name; + var type = uniform.info.type; + var arg = args.uniforms[name]; + var UNIFORM = env.link(uniform); + var LOCATION = UNIFORM + '.location'; + + var VALUE; + if (arg) { + if (!filter(arg)) { + continue + } + if (isStatic(arg)) { + var value = arg.value; + check$1.command( + value !== null && typeof value !== 'undefined', + 'missing uniform "' + name + '"', env.commandStr); + if (type === GL_SAMPLER_2D || type === GL_SAMPLER_CUBE) { + check$1.command( + typeof value === 'function' && + ((type === GL_SAMPLER_2D && + (value._reglType === 'texture2d' || + value._reglType === 'framebuffer')) || + (type === GL_SAMPLER_CUBE && + (value._reglType === 'textureCube' || + value._reglType === 'framebufferCube'))), + 'invalid texture for uniform ' + name, env.commandStr); + var TEX_VALUE = env.link(value._texture || value.color[0]._texture); + scope(GL, '.uniform1i(', LOCATION, ',', TEX_VALUE + '.bind());'); + scope.exit(TEX_VALUE, '.unbind();'); + } else if ( + type === GL_FLOAT_MAT2 || + type === GL_FLOAT_MAT3 || + type === GL_FLOAT_MAT4) { + check$1.optional(function () { + check$1.command(isArrayLike(value), + 'invalid matrix for uniform ' + name, env.commandStr); + check$1.command( + (type === GL_FLOAT_MAT2 && value.length === 4) || + (type === GL_FLOAT_MAT3 && value.length === 9) || + (type === GL_FLOAT_MAT4 && value.length === 16), + 'invalid length for matrix uniform ' + name, env.commandStr); + }); + var MAT_VALUE = env.global.def('new Float32Array([' + + Array.prototype.slice.call(value) + '])'); + var dim = 2; + if (type === GL_FLOAT_MAT3) { + dim = 3; + } else if (type === GL_FLOAT_MAT4) { + dim = 4; + } + scope( + GL, '.uniformMatrix', dim, 'fv(', + LOCATION, ',false,', MAT_VALUE, ');'); + } else { + switch (type) { + case GL_FLOAT$8: + check$1.commandType(value, 'number', 'uniform ' + name, env.commandStr); + infix = '1f'; + break + case GL_FLOAT_VEC2: + check$1.command( + isArrayLike(value) && value.length === 2, + 'uniform ' + name, env.commandStr); + infix = '2f'; + break + case GL_FLOAT_VEC3: + check$1.command( + isArrayLike(value) && value.length === 3, + 'uniform ' + name, env.commandStr); + infix = '3f'; + break + case GL_FLOAT_VEC4: + check$1.command( + isArrayLike(value) && value.length === 4, + 'uniform ' + name, env.commandStr); + infix = '4f'; + break + case GL_BOOL: + check$1.commandType(value, 'boolean', 'uniform ' + name, env.commandStr); + infix = '1i'; + break + case GL_INT$3: + check$1.commandType(value, 'number', 'uniform ' + name, env.commandStr); + infix = '1i'; + break + case GL_BOOL_VEC2: + check$1.command( + isArrayLike(value) && value.length === 2, + 'uniform ' + name, env.commandStr); + infix = '2i'; + break + case GL_INT_VEC2: + check$1.command( + isArrayLike(value) && value.length === 2, + 'uniform ' + name, env.commandStr); + infix = '2i'; + break + case GL_BOOL_VEC3: + check$1.command( + isArrayLike(value) && value.length === 3, + 'uniform ' + name, env.commandStr); + infix = '3i'; + break + case GL_INT_VEC3: + check$1.command( + isArrayLike(value) && value.length === 3, + 'uniform ' + name, env.commandStr); + infix = '3i'; + break + case GL_BOOL_VEC4: + check$1.command( + isArrayLike(value) && value.length === 4, + 'uniform ' + name, env.commandStr); + infix = '4i'; + break + case GL_INT_VEC4: + check$1.command( + isArrayLike(value) && value.length === 4, + 'uniform ' + name, env.commandStr); + infix = '4i'; + break + } + scope(GL, '.uniform', infix, '(', LOCATION, ',', + isArrayLike(value) ? Array.prototype.slice.call(value) : value, + ');'); + } + continue + } else { + VALUE = arg.append(env, scope); + } + } else { + if (!filter(SCOPE_DECL)) { + continue + } + VALUE = scope.def(shared.uniforms, '[', stringStore.id(name), ']'); + } + + if (type === GL_SAMPLER_2D) { + scope( + 'if(', VALUE, '&&', VALUE, '._reglType==="framebuffer"){', + VALUE, '=', VALUE, '.color[0];', + '}'); + } else if (type === GL_SAMPLER_CUBE) { + scope( + 'if(', VALUE, '&&', VALUE, '._reglType==="framebufferCube"){', + VALUE, '=', VALUE, '.color[0];', + '}'); + } + + // perform type validation + check$1.optional(function () { + function check (pred, message) { + env.assert(scope, pred, + 'bad data or missing for uniform "' + name + '". ' + message); + } + + function checkType (type) { + check( + 'typeof ' + VALUE + '==="' + type + '"', + 'invalid type, expected ' + type); + } + + function checkVector (n, type) { + check( + shared.isArrayLike + '(' + VALUE + ')&&' + VALUE + '.length===' + n, + 'invalid vector, should have length ' + n, env.commandStr); + } + + function checkTexture (target) { + check( + 'typeof ' + VALUE + '==="function"&&' + + VALUE + '._reglType==="texture' + + (target === GL_TEXTURE_2D$3 ? '2d' : 'Cube') + '"', + 'invalid texture type', env.commandStr); + } + + switch (type) { + case GL_INT$3: + checkType('number'); + break + case GL_INT_VEC2: + checkVector(2, 'number'); + break + case GL_INT_VEC3: + checkVector(3, 'number'); + break + case GL_INT_VEC4: + checkVector(4, 'number'); + break + case GL_FLOAT$8: + checkType('number'); + break + case GL_FLOAT_VEC2: + checkVector(2, 'number'); + break + case GL_FLOAT_VEC3: + checkVector(3, 'number'); + break + case GL_FLOAT_VEC4: + checkVector(4, 'number'); + break + case GL_BOOL: + checkType('boolean'); + break + case GL_BOOL_VEC2: + checkVector(2, 'boolean'); + break + case GL_BOOL_VEC3: + checkVector(3, 'boolean'); + break + case GL_BOOL_VEC4: + checkVector(4, 'boolean'); + break + case GL_FLOAT_MAT2: + checkVector(4, 'number'); + break + case GL_FLOAT_MAT3: + checkVector(9, 'number'); + break + case GL_FLOAT_MAT4: + checkVector(16, 'number'); + break + case GL_SAMPLER_2D: + checkTexture(GL_TEXTURE_2D$3); + break + case GL_SAMPLER_CUBE: + checkTexture(GL_TEXTURE_CUBE_MAP$2); + break + } + }); + + var unroll = 1; + switch (type) { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + var TEX = scope.def(VALUE, '._texture'); + scope(GL, '.uniform1i(', LOCATION, ',', TEX, '.bind());'); + scope.exit(TEX, '.unbind();'); + continue + + case GL_INT$3: + case GL_BOOL: + infix = '1i'; + break + + case GL_INT_VEC2: + case GL_BOOL_VEC2: + infix = '2i'; + unroll = 2; + break + + case GL_INT_VEC3: + case GL_BOOL_VEC3: + infix = '3i'; + unroll = 3; + break + + case GL_INT_VEC4: + case GL_BOOL_VEC4: + infix = '4i'; + unroll = 4; + break + + case GL_FLOAT$8: + infix = '1f'; + break + + case GL_FLOAT_VEC2: + infix = '2f'; + unroll = 2; + break + + case GL_FLOAT_VEC3: + infix = '3f'; + unroll = 3; + break + + case GL_FLOAT_VEC4: + infix = '4f'; + unroll = 4; + break + + case GL_FLOAT_MAT2: + infix = 'Matrix2fv'; + break + + case GL_FLOAT_MAT3: + infix = 'Matrix3fv'; + break + + case GL_FLOAT_MAT4: + infix = 'Matrix4fv'; + break + } + + scope(GL, '.uniform', infix, '(', LOCATION, ','); + if (infix.charAt(0) === 'M') { + var matSize = Math.pow(type - GL_FLOAT_MAT2 + 2, 2); + var STORAGE = env.global.def('new Float32Array(', matSize, ')'); + scope( + 'false,(Array.isArray(', VALUE, ')||', VALUE, ' instanceof Float32Array)?', VALUE, ':(', + loop(matSize, function (i) { + return STORAGE + '[' + i + ']=' + VALUE + '[' + i + ']' + }), ',', STORAGE, ')'); + } else if (unroll > 1) { + scope(loop(unroll, function (i) { + return VALUE + '[' + i + ']' + })); + } else { + scope(VALUE); + } + scope(');'); + } + } + + function emitDraw (env, outer, inner, args) { + var shared = env.shared; + var GL = shared.gl; + var DRAW_STATE = shared.draw; + + var drawOptions = args.draw; + + function emitElements () { + var defn = drawOptions.elements; + var ELEMENTS; + var scope = outer; + if (defn) { + if ((defn.contextDep && args.contextDynamic) || defn.propDep) { + scope = inner; + } + ELEMENTS = defn.append(env, scope); + } else { + ELEMENTS = scope.def(DRAW_STATE, '.', S_ELEMENTS); + } + if (ELEMENTS) { + scope( + 'if(' + ELEMENTS + ')' + + GL + '.bindBuffer(' + GL_ELEMENT_ARRAY_BUFFER$1 + ',' + ELEMENTS + '.buffer.buffer);'); + } + return ELEMENTS + } + + function emitCount () { + var defn = drawOptions.count; + var COUNT; + var scope = outer; + if (defn) { + if ((defn.contextDep && args.contextDynamic) || defn.propDep) { + scope = inner; + } + COUNT = defn.append(env, scope); + check$1.optional(function () { + if (defn.MISSING) { + env.assert(outer, 'false', 'missing vertex count'); + } + if (defn.DYNAMIC) { + env.assert(scope, COUNT + '>=0', 'missing vertex count'); + } + }); + } else { + COUNT = scope.def(DRAW_STATE, '.', S_COUNT); + check$1.optional(function () { + env.assert(scope, COUNT + '>=0', 'missing vertex count'); + }); + } + return COUNT + } + + var ELEMENTS = emitElements(); + function emitValue (name) { + var defn = drawOptions[name]; + if (defn) { + if ((defn.contextDep && args.contextDynamic) || defn.propDep) { + return defn.append(env, inner) + } else { + return defn.append(env, outer) + } + } else { + return outer.def(DRAW_STATE, '.', name) + } + } + + var PRIMITIVE = emitValue(S_PRIMITIVE); + var OFFSET = emitValue(S_OFFSET); + + var COUNT = emitCount(); + if (typeof COUNT === 'number') { + if (COUNT === 0) { + return + } + } else { + inner('if(', COUNT, '){'); + inner.exit('}'); + } + + var INSTANCES, EXT_INSTANCING; + if (extInstancing) { + INSTANCES = emitValue(S_INSTANCES); + EXT_INSTANCING = env.instancing; + } + + var ELEMENT_TYPE = ELEMENTS + '.type'; + + var elementsStatic = drawOptions.elements && isStatic(drawOptions.elements); + + function emitInstancing () { + function drawElements () { + inner(EXT_INSTANCING, '.drawElementsInstancedANGLE(', [ + PRIMITIVE, + COUNT, + ELEMENT_TYPE, + OFFSET + '<<((' + ELEMENT_TYPE + '-' + GL_UNSIGNED_BYTE$8 + ')>>1)', + INSTANCES + ], ');'); + } + + function drawArrays () { + inner(EXT_INSTANCING, '.drawArraysInstancedANGLE(', + [PRIMITIVE, OFFSET, COUNT, INSTANCES], ');'); + } + + if (ELEMENTS) { + if (!elementsStatic) { + inner('if(', ELEMENTS, '){'); + drawElements(); + inner('}else{'); + drawArrays(); + inner('}'); + } else { + drawElements(); + } + } else { + drawArrays(); + } + } + + function emitRegular () { + function drawElements () { + inner(GL + '.drawElements(' + [ + PRIMITIVE, + COUNT, + ELEMENT_TYPE, + OFFSET + '<<((' + ELEMENT_TYPE + '-' + GL_UNSIGNED_BYTE$8 + ')>>1)' + ] + ');'); + } + + function drawArrays () { + inner(GL + '.drawArrays(' + [PRIMITIVE, OFFSET, COUNT] + ');'); + } + + if (ELEMENTS) { + if (!elementsStatic) { + inner('if(', ELEMENTS, '){'); + drawElements(); + inner('}else{'); + drawArrays(); + inner('}'); + } else { + drawElements(); + } + } else { + drawArrays(); + } + } + + if (extInstancing && (typeof INSTANCES !== 'number' || INSTANCES >= 0)) { + if (typeof INSTANCES === 'string') { + inner('if(', INSTANCES, '>0){'); + emitInstancing(); + inner('}else if(', INSTANCES, '<0){'); + emitRegular(); + inner('}'); + } else { + emitInstancing(); + } + } else { + emitRegular(); + } + } + + function createBody (emitBody, parentEnv, args, program, count) { + var env = createREGLEnvironment(); + var scope = env.proc('body', count); + check$1.optional(function () { + env.commandStr = parentEnv.commandStr; + env.command = env.link(parentEnv.commandStr); + }); + if (extInstancing) { + env.instancing = scope.def( + env.shared.extensions, '.angle_instanced_arrays'); + } + emitBody(env, scope, args, program); + return env.compile().body + } + + // =================================================== + // =================================================== + // DRAW PROC + // =================================================== + // =================================================== + function emitDrawBody (env, draw, args, program) { + injectExtensions(env, draw); + emitAttributes(env, draw, args, program.attributes, function () { + return true + }); + emitUniforms(env, draw, args, program.uniforms, function () { + return true + }); + emitDraw(env, draw, draw, args); + } + + function emitDrawProc (env, args) { + var draw = env.proc('draw', 1); + + injectExtensions(env, draw); + + emitContext(env, draw, args.context); + emitPollFramebuffer(env, draw, args.framebuffer); + + emitPollState(env, draw, args); + emitSetOptions(env, draw, args.state); + + emitProfile(env, draw, args, false, true); + + var program = args.shader.progVar.append(env, draw); + draw(env.shared.gl, '.useProgram(', program, '.program);'); + + if (args.shader.program) { + emitDrawBody(env, draw, args, args.shader.program); + } else { + var drawCache = env.global.def('{}'); + var PROG_ID = draw.def(program, '.id'); + var CACHED_PROC = draw.def(drawCache, '[', PROG_ID, ']'); + draw( + env.cond(CACHED_PROC) + .then(CACHED_PROC, '.call(this,a0);') + .else( + CACHED_PROC, '=', drawCache, '[', PROG_ID, ']=', + env.link(function (program) { + return createBody(emitDrawBody, env, args, program, 1) + }), '(', program, ');', + CACHED_PROC, '.call(this,a0);')); + } + + if (Object.keys(args.state).length > 0) { + draw(env.shared.current, '.dirty=true;'); + } + } + + // =================================================== + // =================================================== + // BATCH PROC + // =================================================== + // =================================================== + + function emitBatchDynamicShaderBody (env, scope, args, program) { + env.batchId = 'a1'; + + injectExtensions(env, scope); + + function all () { + return true + } + + emitAttributes(env, scope, args, program.attributes, all); + emitUniforms(env, scope, args, program.uniforms, all); + emitDraw(env, scope, scope, args); + } + + function emitBatchBody (env, scope, args, program) { + injectExtensions(env, scope); + + var contextDynamic = args.contextDep; + + var BATCH_ID = scope.def(); + var PROP_LIST = 'a0'; + var NUM_PROPS = 'a1'; + var PROPS = scope.def(); + env.shared.props = PROPS; + env.batchId = BATCH_ID; + + var outer = env.scope(); + var inner = env.scope(); + + scope( + outer.entry, + 'for(', BATCH_ID, '=0;', BATCH_ID, '<', NUM_PROPS, ';++', BATCH_ID, '){', + PROPS, '=', PROP_LIST, '[', BATCH_ID, '];', + inner, + '}', + outer.exit); + + function isInnerDefn (defn) { + return ((defn.contextDep && contextDynamic) || defn.propDep) + } + + function isOuterDefn (defn) { + return !isInnerDefn(defn) + } + + if (args.needsContext) { + emitContext(env, inner, args.context); + } + if (args.needsFramebuffer) { + emitPollFramebuffer(env, inner, args.framebuffer); + } + emitSetOptions(env, inner, args.state, isInnerDefn); + + if (args.profile && isInnerDefn(args.profile)) { + emitProfile(env, inner, args, false, true); + } + + if (!program) { + var progCache = env.global.def('{}'); + var PROGRAM = args.shader.progVar.append(env, inner); + var PROG_ID = inner.def(PROGRAM, '.id'); + var CACHED_PROC = inner.def(progCache, '[', PROG_ID, ']'); + inner( + env.shared.gl, '.useProgram(', PROGRAM, '.program);', + 'if(!', CACHED_PROC, '){', + CACHED_PROC, '=', progCache, '[', PROG_ID, ']=', + env.link(function (program) { + return createBody( + emitBatchDynamicShaderBody, env, args, program, 2) + }), '(', PROGRAM, ');}', + CACHED_PROC, '.call(this,a0[', BATCH_ID, '],', BATCH_ID, ');'); + } else { + emitAttributes(env, outer, args, program.attributes, isOuterDefn); + emitAttributes(env, inner, args, program.attributes, isInnerDefn); + emitUniforms(env, outer, args, program.uniforms, isOuterDefn); + emitUniforms(env, inner, args, program.uniforms, isInnerDefn); + emitDraw(env, outer, inner, args); + } + } + + function emitBatchProc (env, args) { + var batch = env.proc('batch', 2); + env.batchId = '0'; + + injectExtensions(env, batch); + + // Check if any context variables depend on props + var contextDynamic = false; + var needsContext = true; + Object.keys(args.context).forEach(function (name) { + contextDynamic = contextDynamic || args.context[name].propDep; + }); + if (!contextDynamic) { + emitContext(env, batch, args.context); + needsContext = false; + } + + // framebuffer state affects framebufferWidth/height context vars + var framebuffer = args.framebuffer; + var needsFramebuffer = false; + if (framebuffer) { + if (framebuffer.propDep) { + contextDynamic = needsFramebuffer = true; + } else if (framebuffer.contextDep && contextDynamic) { + needsFramebuffer = true; + } + if (!needsFramebuffer) { + emitPollFramebuffer(env, batch, framebuffer); + } + } else { + emitPollFramebuffer(env, batch, null); + } + + // viewport is weird because it can affect context vars + if (args.state.viewport && args.state.viewport.propDep) { + contextDynamic = true; + } + + function isInnerDefn (defn) { + return (defn.contextDep && contextDynamic) || defn.propDep + } + + // set webgl options + emitPollState(env, batch, args); + emitSetOptions(env, batch, args.state, function (defn) { + return !isInnerDefn(defn) + }); + + if (!args.profile || !isInnerDefn(args.profile)) { + emitProfile(env, batch, args, false, 'a1'); + } + + // Save these values to args so that the batch body routine can use them + args.contextDep = contextDynamic; + args.needsContext = needsContext; + args.needsFramebuffer = needsFramebuffer; + + // determine if shader is dynamic + var progDefn = args.shader.progVar; + if ((progDefn.contextDep && contextDynamic) || progDefn.propDep) { + emitBatchBody( + env, + batch, + args, + null); + } else { + var PROGRAM = progDefn.append(env, batch); + batch(env.shared.gl, '.useProgram(', PROGRAM, '.program);'); + if (args.shader.program) { + emitBatchBody( + env, + batch, + args, + args.shader.program); + } else { + var batchCache = env.global.def('{}'); + var PROG_ID = batch.def(PROGRAM, '.id'); + var CACHED_PROC = batch.def(batchCache, '[', PROG_ID, ']'); + batch( + env.cond(CACHED_PROC) + .then(CACHED_PROC, '.call(this,a0,a1);') + .else( + CACHED_PROC, '=', batchCache, '[', PROG_ID, ']=', + env.link(function (program) { + return createBody(emitBatchBody, env, args, program, 2) + }), '(', PROGRAM, ');', + CACHED_PROC, '.call(this,a0,a1);')); + } + } + + if (Object.keys(args.state).length > 0) { + batch(env.shared.current, '.dirty=true;'); + } + } + + // =================================================== + // =================================================== + // SCOPE COMMAND + // =================================================== + // =================================================== + function emitScopeProc (env, args) { + var scope = env.proc('scope', 3); + env.batchId = 'a2'; + + var shared = env.shared; + var CURRENT_STATE = shared.current; + + emitContext(env, scope, args.context); + + if (args.framebuffer) { + args.framebuffer.append(env, scope); + } + + sortState(Object.keys(args.state)).forEach(function (name) { + var defn = args.state[name]; + var value = defn.append(env, scope); + if (isArrayLike(value)) { + value.forEach(function (v, i) { + scope.set(env.next[name], '[' + i + ']', v); + }); + } else { + scope.set(shared.next, '.' + name, value); + } + }); + + emitProfile(env, scope, args, true, true) + + ;[S_ELEMENTS, S_OFFSET, S_COUNT, S_INSTANCES, S_PRIMITIVE].forEach( + function (opt) { + var variable = args.draw[opt]; + if (!variable) { + return + } + scope.set(shared.draw, '.' + opt, '' + variable.append(env, scope)); + }); + + Object.keys(args.uniforms).forEach(function (opt) { + scope.set( + shared.uniforms, + '[' + stringStore.id(opt) + ']', + args.uniforms[opt].append(env, scope)); + }); + + Object.keys(args.attributes).forEach(function (name) { + var record = args.attributes[name].append(env, scope); + var scopeAttrib = env.scopeAttrib(name); + Object.keys(new AttributeRecord()).forEach(function (prop) { + scope.set(scopeAttrib, '.' + prop, record[prop]); + }); + }); + + function saveShader (name) { + var shader = args.shader[name]; + if (shader) { + scope.set(shared.shader, '.' + name, shader.append(env, scope)); + } + } + saveShader(S_VERT); + saveShader(S_FRAG); + + if (Object.keys(args.state).length > 0) { + scope(CURRENT_STATE, '.dirty=true;'); + scope.exit(CURRENT_STATE, '.dirty=true;'); + } + + scope('a1(', env.shared.context, ',a0,', env.batchId, ');'); + } + + function isDynamicObject (object) { + if (typeof object !== 'object' || isArrayLike(object)) { + return + } + var props = Object.keys(object); + for (var i = 0; i < props.length; ++i) { + if (dynamic.isDynamic(object[props[i]])) { + return true + } + } + return false + } + + function splatObject (env, options, name) { + var object = options.static[name]; + if (!object || !isDynamicObject(object)) { + return + } + + var globals = env.global; + var keys = Object.keys(object); + var thisDep = false; + var contextDep = false; + var propDep = false; + var objectRef = env.global.def('{}'); + keys.forEach(function (key) { + var value = object[key]; + if (dynamic.isDynamic(value)) { + if (typeof value === 'function') { + value = object[key] = dynamic.unbox(value); + } + var deps = createDynamicDecl(value, null); + thisDep = thisDep || deps.thisDep; + propDep = propDep || deps.propDep; + contextDep = contextDep || deps.contextDep; + } else { + globals(objectRef, '.', key, '='); + switch (typeof value) { + case 'number': + globals(value); + break + case 'string': + globals('"', value, '"'); + break + case 'object': + if (Array.isArray(value)) { + globals('[', value.join(), ']'); + } + break + default: + globals(env.link(value)); + break + } + globals(';'); + } + }); + + function appendBlock (env, block) { + keys.forEach(function (key) { + var value = object[key]; + if (!dynamic.isDynamic(value)) { + return + } + var ref = env.invoke(block, value); + block(objectRef, '.', key, '=', ref, ';'); + }); + } + + options.dynamic[name] = new dynamic.DynamicVariable(DYN_THUNK, { + thisDep: thisDep, + contextDep: contextDep, + propDep: propDep, + ref: objectRef, + append: appendBlock + }); + delete options.static[name]; + } + + // =========================================================================== + // =========================================================================== + // MAIN DRAW COMMAND + // =========================================================================== + // =========================================================================== + function compileCommand (options, attributes, uniforms, context, stats) { + var env = createREGLEnvironment(); + + // link stats, so that we can easily access it in the program. + env.stats = env.link(stats); + + // splat options and attributes to allow for dynamic nested properties + Object.keys(attributes.static).forEach(function (key) { + splatObject(env, attributes, key); + }); + NESTED_OPTIONS.forEach(function (name) { + splatObject(env, options, name); + }); + + var args = parseArguments(options, attributes, uniforms, context, env); + + emitDrawProc(env, args); + emitScopeProc(env, args); + emitBatchProc(env, args); + + return env.compile() + } + + // =========================================================================== + // =========================================================================== + // POLL / REFRESH + // =========================================================================== + // =========================================================================== + return { + next: nextState, + current: currentState, + procs: (function () { + var env = createREGLEnvironment(); + var poll = env.proc('poll'); + var refresh = env.proc('refresh'); + var common = env.block(); + poll(common); + refresh(common); + + var shared = env.shared; + var GL = shared.gl; + var NEXT_STATE = shared.next; + var CURRENT_STATE = shared.current; + + common(CURRENT_STATE, '.dirty=false;'); + + emitPollFramebuffer(env, poll); + emitPollFramebuffer(env, refresh, null, true); + + // Refresh updates all attribute state changes + var INSTANCING; + if (extInstancing) { + INSTANCING = env.link(extInstancing); + } + for (var i = 0; i < limits.maxAttributes; ++i) { + var BINDING = refresh.def(shared.attributes, '[', i, ']'); + var ifte = env.cond(BINDING, '.buffer'); + ifte.then( + GL, '.enableVertexAttribArray(', i, ');', + GL, '.bindBuffer(', + GL_ARRAY_BUFFER$1, ',', + BINDING, '.buffer.buffer);', + GL, '.vertexAttribPointer(', + i, ',', + BINDING, '.size,', + BINDING, '.type,', + BINDING, '.normalized,', + BINDING, '.stride,', + BINDING, '.offset);' + ).else( + GL, '.disableVertexAttribArray(', i, ');', + GL, '.vertexAttrib4f(', + i, ',', + BINDING, '.x,', + BINDING, '.y,', + BINDING, '.z,', + BINDING, '.w);', + BINDING, '.buffer=null;'); + refresh(ifte); + if (extInstancing) { + refresh( + INSTANCING, '.vertexAttribDivisorANGLE(', + i, ',', + BINDING, '.divisor);'); + } + } + + Object.keys(GL_FLAGS).forEach(function (flag) { + var cap = GL_FLAGS[flag]; + var NEXT = common.def(NEXT_STATE, '.', flag); + var block = env.block(); + block('if(', NEXT, '){', + GL, '.enable(', cap, ')}else{', + GL, '.disable(', cap, ')}', + CURRENT_STATE, '.', flag, '=', NEXT, ';'); + refresh(block); + poll( + 'if(', NEXT, '!==', CURRENT_STATE, '.', flag, '){', + block, + '}'); + }); + + Object.keys(GL_VARIABLES).forEach(function (name) { + var func = GL_VARIABLES[name]; + var init = currentState[name]; + var NEXT, CURRENT; + var block = env.block(); + block(GL, '.', func, '('); + if (isArrayLike(init)) { + var n = init.length; + NEXT = env.global.def(NEXT_STATE, '.', name); + CURRENT = env.global.def(CURRENT_STATE, '.', name); + block( + loop(n, function (i) { + return NEXT + '[' + i + ']' + }), ');', + loop(n, function (i) { + return CURRENT + '[' + i + ']=' + NEXT + '[' + i + '];' + }).join('')); + poll( + 'if(', loop(n, function (i) { + return NEXT + '[' + i + ']!==' + CURRENT + '[' + i + ']' + }).join('||'), '){', + block, + '}'); + } else { + NEXT = common.def(NEXT_STATE, '.', name); + CURRENT = common.def(CURRENT_STATE, '.', name); + block( + NEXT, ');', + CURRENT_STATE, '.', name, '=', NEXT, ';'); + poll( + 'if(', NEXT, '!==', CURRENT, '){', + block, + '}'); + } + refresh(block); + }); + + return env.compile() + })(), + compile: compileCommand + } +} + +function stats () { + return { + bufferCount: 0, + elementsCount: 0, + framebufferCount: 0, + shaderCount: 0, + textureCount: 0, + cubeCount: 0, + renderbufferCount: 0, + maxTextureUnits: 0 + } +} + +var GL_QUERY_RESULT_EXT = 0x8866; +var GL_QUERY_RESULT_AVAILABLE_EXT = 0x8867; +var GL_TIME_ELAPSED_EXT = 0x88BF; + +var createTimer = function (gl, extensions) { + var extTimer = extensions.ext_disjoint_timer_query; + + if (!extTimer) { + return null + } + + // QUERY POOL BEGIN + var queryPool = []; + function allocQuery () { + return queryPool.pop() || extTimer.createQueryEXT() + } + function freeQuery (query) { + queryPool.push(query); + } + // QUERY POOL END + + var pendingQueries = []; + function beginQuery (stats) { + var query = allocQuery(); + extTimer.beginQueryEXT(GL_TIME_ELAPSED_EXT, query); + pendingQueries.push(query); + pushScopeStats(pendingQueries.length - 1, pendingQueries.length, stats); + } + + function endQuery () { + extTimer.endQueryEXT(GL_TIME_ELAPSED_EXT); + } + + // + // Pending stats pool. + // + function PendingStats () { + this.startQueryIndex = -1; + this.endQueryIndex = -1; + this.sum = 0; + this.stats = null; + } + var pendingStatsPool = []; + function allocPendingStats () { + return pendingStatsPool.pop() || new PendingStats() + } + function freePendingStats (pendingStats) { + pendingStatsPool.push(pendingStats); + } + // Pending stats pool end + + var pendingStats = []; + function pushScopeStats (start, end, stats) { + var ps = allocPendingStats(); + ps.startQueryIndex = start; + ps.endQueryIndex = end; + ps.sum = 0; + ps.stats = stats; + pendingStats.push(ps); + } + + // we should call this at the beginning of the frame, + // in order to update gpuTime + var timeSum = []; + var queryPtr = []; + function update () { + var ptr, i; + + var n = pendingQueries.length; + if (n === 0) { + return + } + + // Reserve space + queryPtr.length = Math.max(queryPtr.length, n + 1); + timeSum.length = Math.max(timeSum.length, n + 1); + timeSum[0] = 0; + queryPtr[0] = 0; + + // Update all pending timer queries + var queryTime = 0; + ptr = 0; + for (i = 0; i < pendingQueries.length; ++i) { + var query = pendingQueries[i]; + if (extTimer.getQueryObjectEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT)) { + queryTime += extTimer.getQueryObjectEXT(query, GL_QUERY_RESULT_EXT); + freeQuery(query); + } else { + pendingQueries[ptr++] = query; + } + timeSum[i + 1] = queryTime; + queryPtr[i + 1] = ptr; + } + pendingQueries.length = ptr; + + // Update all pending stat queries + ptr = 0; + for (i = 0; i < pendingStats.length; ++i) { + var stats = pendingStats[i]; + var start = stats.startQueryIndex; + var end = stats.endQueryIndex; + stats.sum += timeSum[end] - timeSum[start]; + var startPtr = queryPtr[start]; + var endPtr = queryPtr[end]; + if (endPtr === startPtr) { + stats.stats.gpuTime += stats.sum / 1e6; + freePendingStats(stats); + } else { + stats.startQueryIndex = startPtr; + stats.endQueryIndex = endPtr; + pendingStats[ptr++] = stats; + } + } + pendingStats.length = ptr; + } + + return { + beginQuery: beginQuery, + endQuery: endQuery, + pushScopeStats: pushScopeStats, + update: update, + getNumPendingQueries: function () { + return pendingQueries.length + }, + clear: function () { + queryPool.push.apply(queryPool, pendingQueries); + for (var i = 0; i < queryPool.length; i++) { + extTimer.deleteQueryEXT(queryPool[i]); + } + pendingQueries.length = 0; + queryPool.length = 0; + }, + restore: function () { + pendingQueries.length = 0; + queryPool.length = 0; + } + } +}; + +var GL_COLOR_BUFFER_BIT = 16384; +var GL_DEPTH_BUFFER_BIT = 256; +var GL_STENCIL_BUFFER_BIT = 1024; + +var GL_ARRAY_BUFFER = 34962; + +var CONTEXT_LOST_EVENT = 'webglcontextlost'; +var CONTEXT_RESTORED_EVENT = 'webglcontextrestored'; + +var DYN_PROP = 1; +var DYN_CONTEXT = 2; +var DYN_STATE = 3; + +function find (haystack, needle) { + for (var i = 0; i < haystack.length; ++i) { + if (haystack[i] === needle) { + return i + } + } + return -1 +} + +function wrapREGL (args) { + var config = parseArgs(args); + if (!config) { + return null + } + + var gl = config.gl; + var glAttributes = gl.getContextAttributes(); + var contextLost = gl.isContextLost(); + + var extensionState = createExtensionCache(gl, config); + if (!extensionState) { + return null + } + + var stringStore = createStringStore(); + var stats$$1 = stats(); + var extensions = extensionState.extensions; + var timer = createTimer(gl, extensions); + + var START_TIME = clock(); + var WIDTH = gl.drawingBufferWidth; + var HEIGHT = gl.drawingBufferHeight; + + var contextState = { + tick: 0, + time: 0, + viewportWidth: WIDTH, + viewportHeight: HEIGHT, + framebufferWidth: WIDTH, + framebufferHeight: HEIGHT, + drawingBufferWidth: WIDTH, + drawingBufferHeight: HEIGHT, + pixelRatio: config.pixelRatio + }; + var uniformState = {}; + var drawState = { + elements: null, + primitive: 4, // GL_TRIANGLES + count: -1, + offset: 0, + instances: -1 + }; + + var limits = wrapLimits(gl, extensions); + var attributeState = wrapAttributeState( + gl, + extensions, + limits, + stringStore); + var bufferState = wrapBufferState( + gl, + stats$$1, + config, + attributeState); + var elementState = wrapElementsState(gl, extensions, bufferState, stats$$1); + var shaderState = wrapShaderState(gl, stringStore, stats$$1, config); + var textureState = createTextureSet( + gl, + extensions, + limits, + function () { core.procs.poll(); }, + contextState, + stats$$1, + config); + var renderbufferState = wrapRenderbuffers(gl, extensions, limits, stats$$1, config); + var framebufferState = wrapFBOState( + gl, + extensions, + limits, + textureState, + renderbufferState, + stats$$1); + var core = reglCore( + gl, + stringStore, + extensions, + limits, + bufferState, + elementState, + textureState, + framebufferState, + uniformState, + attributeState, + shaderState, + drawState, + contextState, + timer, + config); + var readPixels = wrapReadPixels( + gl, + framebufferState, + core.procs.poll, + contextState, + glAttributes, extensions, limits); + + var nextState = core.next; + var canvas = gl.canvas; + + var rafCallbacks = []; + var lossCallbacks = []; + var restoreCallbacks = []; + var destroyCallbacks = [config.onDestroy]; + + var activeRAF = null; + function handleRAF () { + if (rafCallbacks.length === 0) { + if (timer) { + timer.update(); + } + activeRAF = null; + return + } + + // schedule next animation frame + activeRAF = raf.next(handleRAF); + + // poll for changes + poll(); + + // fire a callback for all pending rafs + for (var i = rafCallbacks.length - 1; i >= 0; --i) { + var cb = rafCallbacks[i]; + if (cb) { + cb(contextState, null, 0); + } + } + + // flush all pending webgl calls + gl.flush(); + + // poll GPU timers *after* gl.flush so we don't delay command dispatch + if (timer) { + timer.update(); + } + } + + function startRAF () { + if (!activeRAF && rafCallbacks.length > 0) { + activeRAF = raf.next(handleRAF); + } + } + + function stopRAF () { + if (activeRAF) { + raf.cancel(handleRAF); + activeRAF = null; + } + } + + function handleContextLoss (event) { + event.preventDefault(); + + // set context lost flag + contextLost = true; + + // pause request animation frame + stopRAF(); + + // lose context + lossCallbacks.forEach(function (cb) { + cb(); + }); + } + + function handleContextRestored (event) { + // clear error code + gl.getError(); + + // clear context lost flag + contextLost = false; + + // refresh state + extensionState.restore(); + shaderState.restore(); + bufferState.restore(); + textureState.restore(); + renderbufferState.restore(); + framebufferState.restore(); + if (timer) { + timer.restore(); + } + + // refresh state + core.procs.refresh(); + + // restart RAF + startRAF(); + + // restore context + restoreCallbacks.forEach(function (cb) { + cb(); + }); + } + + if (canvas) { + canvas.addEventListener(CONTEXT_LOST_EVENT, handleContextLoss, false); + canvas.addEventListener(CONTEXT_RESTORED_EVENT, handleContextRestored, false); + } + + function destroy () { + rafCallbacks.length = 0; + stopRAF(); + + if (canvas) { + canvas.removeEventListener(CONTEXT_LOST_EVENT, handleContextLoss); + canvas.removeEventListener(CONTEXT_RESTORED_EVENT, handleContextRestored); + } + + shaderState.clear(); + framebufferState.clear(); + renderbufferState.clear(); + textureState.clear(); + elementState.clear(); + bufferState.clear(); + + if (timer) { + timer.clear(); + } + + destroyCallbacks.forEach(function (cb) { + cb(); + }); + } + + function compileProcedure (options) { + check$1(!!options, 'invalid args to regl({...})'); + check$1.type(options, 'object', 'invalid args to regl({...})'); + + function flattenNestedOptions (options) { + var result = extend({}, options); + delete result.uniforms; + delete result.attributes; + delete result.context; + + if ('stencil' in result && result.stencil.op) { + result.stencil.opBack = result.stencil.opFront = result.stencil.op; + delete result.stencil.op; + } + + function merge (name) { + if (name in result) { + var child = result[name]; + delete result[name]; + Object.keys(child).forEach(function (prop) { + result[name + '.' + prop] = child[prop]; + }); + } + } + merge('blend'); + merge('depth'); + merge('cull'); + merge('stencil'); + merge('polygonOffset'); + merge('scissor'); + merge('sample'); + + return result + } + + function separateDynamic (object) { + var staticItems = {}; + var dynamicItems = {}; + Object.keys(object).forEach(function (option) { + var value = object[option]; + if (dynamic.isDynamic(value)) { + dynamicItems[option] = dynamic.unbox(value, option); + } else { + staticItems[option] = value; + } + }); + return { + dynamic: dynamicItems, + static: staticItems + } + } + + // Treat context variables separate from other dynamic variables + var context = separateDynamic(options.context || {}); + var uniforms = separateDynamic(options.uniforms || {}); + var attributes = separateDynamic(options.attributes || {}); + var opts = separateDynamic(flattenNestedOptions(options)); + + var stats$$1 = { + gpuTime: 0.0, + cpuTime: 0.0, + count: 0 + }; + + var compiled = core.compile(opts, attributes, uniforms, context, stats$$1); + + var draw = compiled.draw; + var batch = compiled.batch; + var scope = compiled.scope; + + // FIXME: we should modify code generation for batch commands so this + // isn't necessary + var EMPTY_ARRAY = []; + function reserve (count) { + while (EMPTY_ARRAY.length < count) { + EMPTY_ARRAY.push(null); + } + return EMPTY_ARRAY + } + + function REGLCommand (args, body) { + var i; + if (contextLost) { + check$1.raise('context lost'); + } + if (typeof args === 'function') { + return scope.call(this, null, args, 0) + } else if (typeof body === 'function') { + if (typeof args === 'number') { + for (i = 0; i < args; ++i) { + scope.call(this, null, body, i); + } + return + } else if (Array.isArray(args)) { + for (i = 0; i < args.length; ++i) { + scope.call(this, args[i], body, i); + } + return + } else { + return scope.call(this, args, body, 0) + } + } else if (typeof args === 'number') { + if (args > 0) { + return batch.call(this, reserve(args | 0), args | 0) + } + } else if (Array.isArray(args)) { + if (args.length) { + return batch.call(this, args, args.length) + } + } else { + return draw.call(this, args) + } + } + + return extend(REGLCommand, { + stats: stats$$1 + }) + } + + var setFBO = framebufferState.setFBO = compileProcedure({ + framebuffer: dynamic.define.call(null, DYN_PROP, 'framebuffer') + }); + + function clearImpl (_, options) { + var clearFlags = 0; + core.procs.poll(); + + var c = options.color; + if (c) { + gl.clearColor(+c[0] || 0, +c[1] || 0, +c[2] || 0, +c[3] || 0); + clearFlags |= GL_COLOR_BUFFER_BIT; + } + if ('depth' in options) { + gl.clearDepth(+options.depth); + clearFlags |= GL_DEPTH_BUFFER_BIT; + } + if ('stencil' in options) { + gl.clearStencil(options.stencil | 0); + clearFlags |= GL_STENCIL_BUFFER_BIT; + } + + check$1(!!clearFlags, 'called regl.clear with no buffer specified'); + gl.clear(clearFlags); + } + + function clear (options) { + check$1( + typeof options === 'object' && options, + 'regl.clear() takes an object as input'); + if ('framebuffer' in options) { + if (options.framebuffer && + options.framebuffer_reglType === 'framebufferCube') { + for (var i = 0; i < 6; ++i) { + setFBO(extend({ + framebuffer: options.framebuffer.faces[i] + }, options), clearImpl); + } + } else { + setFBO(options, clearImpl); + } + } else { + clearImpl(null, options); + } + } + + function frame (cb) { + check$1.type(cb, 'function', 'regl.frame() callback must be a function'); + rafCallbacks.push(cb); + + function cancel () { + // FIXME: should we check something other than equals cb here? + // what if a user calls frame twice with the same callback... + // + var i = find(rafCallbacks, cb); + check$1(i >= 0, 'cannot cancel a frame twice'); + function pendingCancel () { + var index = find(rafCallbacks, pendingCancel); + rafCallbacks[index] = rafCallbacks[rafCallbacks.length - 1]; + rafCallbacks.length -= 1; + if (rafCallbacks.length <= 0) { + stopRAF(); + } + } + rafCallbacks[i] = pendingCancel; + } + + startRAF(); + + return { + cancel: cancel + } + } + + // poll viewport + function pollViewport () { + var viewport = nextState.viewport; + var scissorBox = nextState.scissor_box; + viewport[0] = viewport[1] = scissorBox[0] = scissorBox[1] = 0; + contextState.viewportWidth = + contextState.framebufferWidth = + contextState.drawingBufferWidth = + viewport[2] = + scissorBox[2] = gl.drawingBufferWidth; + contextState.viewportHeight = + contextState.framebufferHeight = + contextState.drawingBufferHeight = + viewport[3] = + scissorBox[3] = gl.drawingBufferHeight; + } + + function poll () { + contextState.tick += 1; + contextState.time = now(); + pollViewport(); + core.procs.poll(); + } + + function refresh () { + pollViewport(); + core.procs.refresh(); + if (timer) { + timer.update(); + } + } + + function now () { + return (clock() - START_TIME) / 1000.0 + } + + refresh(); + + function addListener (event, callback) { + check$1.type(callback, 'function', 'listener callback must be a function'); + + var callbacks; + switch (event) { + case 'frame': + return frame(callback) + case 'lost': + callbacks = lossCallbacks; + break + case 'restore': + callbacks = restoreCallbacks; + break + case 'destroy': + callbacks = destroyCallbacks; + break + default: + check$1.raise('invalid event, must be one of frame,lost,restore,destroy'); + } + + callbacks.push(callback); + return { + cancel: function () { + for (var i = 0; i < callbacks.length; ++i) { + if (callbacks[i] === callback) { + callbacks[i] = callbacks[callbacks.length - 1]; + callbacks.pop(); + return + } + } + } + } + } + + var regl = extend(compileProcedure, { + // Clear current FBO + clear: clear, + + // Short cuts for dynamic variables + prop: dynamic.define.bind(null, DYN_PROP), + context: dynamic.define.bind(null, DYN_CONTEXT), + this: dynamic.define.bind(null, DYN_STATE), + + // executes an empty draw command + draw: compileProcedure({}), + + // Resources + buffer: function (options) { + return bufferState.create(options, GL_ARRAY_BUFFER, false, false) + }, + elements: function (options) { + return elementState.create(options, false) + }, + texture: textureState.create2D, + cube: textureState.createCube, + renderbuffer: renderbufferState.create, + framebuffer: framebufferState.create, + framebufferCube: framebufferState.createCube, + + // Expose context attributes + attributes: glAttributes, + + // Frame rendering + frame: frame, + on: addListener, + + // System limits + limits: limits, + hasExtension: function (name) { + return limits.extensions.indexOf(name.toLowerCase()) >= 0 + }, + + // Read pixels + read: readPixels, + + // Destroy regl and all associated resources + destroy: destroy, + + // Direct GL state manipulation + _gl: gl, + _refresh: refresh, + + poll: function () { + poll(); + if (timer) { + timer.update(); + } + }, + + // Current time + now: now, + + // regl Statistics Information + stats: stats$$1 + }); + + config.onDone(null, regl); + + return regl +} + +return wrapREGL; + +}))); + + +},{}],479:[function(_dereq_,module,exports){ +/*! + * repeat-string + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +/** + * Results cache + */ + +var res = ''; +var cache; + +/** + * Expose `repeat` + */ + +module.exports = repeat; + +/** + * Repeat the given `string` the specified `number` + * of times. + * + * **Example:** + * + * ```js + * var repeat = require('repeat-string'); + * repeat('A', 5); + * //=> AAAAA + * ``` + * + * @param {String} `string` The string to repeat + * @param {Number} `number` The number of times to repeat the string + * @return {String} Repeated string + * @api public + */ + +function repeat(str, num) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); + } + + // cover common, quick use cases + if (num === 1) return str; + if (num === 2) return str + str; + + var max = str.length * num; + if (cache !== str || typeof cache === 'undefined') { + cache = str; + res = ''; + } else if (res.length >= max) { + return res.substr(0, max); + } + + while (max > res.length && num > 1) { + if (num & 1) { + res += str; + } + + num >>= 1; + str += str; + } + + res += str; + res = res.substr(0, max); + return res; +} + +},{}],480:[function(_dereq_,module,exports){ +(function (global){ +module.exports = + global.performance && + global.performance.now ? function now() { + return performance.now() + } : Date.now || function now() { + return +new Date + } + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],481:[function(_dereq_,module,exports){ +"use strict" + +module.exports = compressExpansion + +function compressExpansion(e) { + var m = e.length + var Q = e[e.length-1] + var bottom = m + for(var i=m-2; i>=0; --i) { + var a = Q + var b = e[i] + Q = a + b + var bv = Q - a + var q = b - bv + if(q) { + e[--bottom] = Q + Q = q + } + } + var top = 0 + for(var i=bottom; i>1 + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") + } +} + +function determinant(m) { + if(m.length === 2) { + return ["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("") + } else { + var expr = [] + for(var i=0; i>1 + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") + } +} + +function makeProduct(a, b) { + if(a.charAt(0) === "m") { + if(b.charAt(0) === "w") { + var toks = a.split("[") + return ["w", b.substr(1), "m", toks[0].substr(1)].join("") + } else { + return ["prod(", a, ",", b, ")"].join("") + } + } else { + return makeProduct(b, a) + } +} + +function sign(s) { + if(s & 1 !== 0) { + return "-" + } + return "" +} + +function determinant(m) { + if(m.length === 2) { + return [["diff(", makeProduct(m[0][0], m[1][1]), ",", makeProduct(m[1][0], m[0][1]), ")"].join("")] + } else { + var expr = [] + for(var i=0; i 0) { + code.push(",") + } + code.push("[") + for(var k=0; k 0) { + code.push(",") + } + if(k === i) { + code.push("+b[", j, "]") + } else { + code.push("+A[", j, "][", k, "]") + } + } + code.push("]") + } + code.push("]),") + } + code.push("det(A)]}return ", funcName) + var proc = new Function("det", code.join("")) + if(n < 6) { + return proc(determinant[n]) + } + return proc(determinant) +} + +function robustLinearSolve0d() { + return [ 0 ] +} + +function robustLinearSolve1d(A, b) { + return [ [ b[0] ], [ A[0][0] ] ] +} + +var CACHE = [ + robustLinearSolve0d, + robustLinearSolve1d +] + +function generateDispatch() { + while(CACHE.length < NUM_EXPAND) { + CACHE.push(generateSolver(CACHE.length)) + } + var procArgs = [] + var code = ["function dispatchLinearSolve(A,b){switch(A.length){"] + for(var i=0; i>1 + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") + } +} + +function determinant(m) { + if(m.length === 2) { + return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")] + } else { + var expr = [] + for(var i=0; i 0) { + if(r <= 0) { + return det + } else { + s = l + r + } + } else if(l < 0) { + if(r >= 0) { + return det + } else { + s = -(l + r) + } + } else { + return det + } + var tol = ERRBOUND3 * s + if(det >= tol || det <= -tol) { + return det + } + return orientation3Exact(a, b, c) + }, + function orientation4(a,b,c,d) { + var adx = a[0] - d[0] + var bdx = b[0] - d[0] + var cdx = c[0] - d[0] + var ady = a[1] - d[1] + var bdy = b[1] - d[1] + var cdy = c[1] - d[1] + var adz = a[2] - d[2] + var bdz = b[2] - d[2] + var cdz = c[2] - d[2] + var bdxcdy = bdx * cdy + var cdxbdy = cdx * bdy + var cdxady = cdx * ady + var adxcdy = adx * cdy + var adxbdy = adx * bdy + var bdxady = bdx * ady + var det = adz * (bdxcdy - cdxbdy) + + bdz * (cdxady - adxcdy) + + cdz * (adxbdy - bdxady) + var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) + + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) + + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz) + var tol = ERRBOUND4 * permanent + if ((det > tol) || (-det > tol)) { + return det + } + return orientation4Exact(a,b,c,d) + } +] + +function slowOrient(args) { + var proc = CACHED[args.length] + if(!proc) { + proc = CACHED[args.length] = orientation(args.length) + } + return proc.apply(undefined, args) +} + +function generateOrientationProc() { + while(CACHED.length <= NUM_EXPAND) { + CACHED.push(orientation(CACHED.length)) + } + var args = [] + var procArgs = ["slow"] + for(var i=0; i<=NUM_EXPAND; ++i) { + args.push("a" + i) + procArgs.push("o" + i) + } + var code = [ + "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;" + ] + for(var i=2; i<=NUM_EXPAND; ++i) { + code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");") + } + code.push("}var s=new Array(arguments.length);for(var i=0;i 0 && y0 > 0) || (x0 < 0 && y0 < 0)) { + return false + } + + var x1 = orient(b0, a0, a1) + var y1 = orient(b1, a0, a1) + if((x1 > 0 && y1 > 0) || (x1 < 0 && y1 < 0)) { + return false + } + + //Check for degenerate collinear case + if(x0 === 0 && y0 === 0 && x1 === 0 && y1 === 0) { + return checkCollinear(a0, a1, b0, b1) + } + + return true +} +},{"robust-orientation":486}],490:[function(_dereq_,module,exports){ +"use strict" + +module.exports = robustSubtract + +//Easy case: Add two scalars +function scalarScalar(a, b) { + var x = a + b + var bv = x - a + var av = x - bv + var br = b - bv + var ar = a - av + var y = ar + br + if(y) { + return [y, x] + } + return [x] +} + +function robustSubtract(e, f) { + var ne = e.length|0 + var nf = f.length|0 + if(ne === 1 && nf === 1) { + return scalarScalar(e[0], -f[0]) + } + var n = ne + nf + var g = new Array(n) + var count = 0 + var eptr = 0 + var fptr = 0 + var abs = Math.abs + var ei = e[eptr] + var ea = abs(ei) + var fi = -f[fptr] + var fa = abs(fi) + var a, b + if(ea < fa) { + b = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + b = fi + fptr += 1 + if(fptr < nf) { + fi = -f[fptr] + fa = abs(fi) + } + } + if((eptr < ne && ea < fa) || (fptr >= nf)) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = -f[fptr] + fa = abs(fi) + } + } + var x = a + b + var bv = x - a + var y = b - bv + var q0 = y + var q1 = x + var _x, _bv, _av, _br, _ar + while(eptr < ne && fptr < nf) { + if(ea < fa) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = -f[fptr] + fa = abs(fi) + } + } + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + } + while(eptr < ne) { + a = ei + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + } + } + while(fptr < nf) { + a = fi + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + fptr += 1 + if(fptr < nf) { + fi = -f[fptr] + } + } + if(q0) { + g[count++] = q0 + } + if(q1) { + g[count++] = q1 + } + if(!count) { + g[count++] = 0.0 + } + g.length = count + return g +} +},{}],491:[function(_dereq_,module,exports){ +"use strict" + +module.exports = linearExpansionSum + +//Easy case: Add two scalars +function scalarScalar(a, b) { + var x = a + b + var bv = x - a + var av = x - bv + var br = b - bv + var ar = a - av + var y = ar + br + if(y) { + return [y, x] + } + return [x] +} + +function linearExpansionSum(e, f) { + var ne = e.length|0 + var nf = f.length|0 + if(ne === 1 && nf === 1) { + return scalarScalar(e[0], f[0]) + } + var n = ne + nf + var g = new Array(n) + var count = 0 + var eptr = 0 + var fptr = 0 + var abs = Math.abs + var ei = e[eptr] + var ea = abs(ei) + var fi = f[fptr] + var fa = abs(fi) + var a, b + if(ea < fa) { + b = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + b = fi + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + fa = abs(fi) + } + } + if((eptr < ne && ea < fa) || (fptr >= nf)) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + fa = abs(fi) + } + } + var x = a + b + var bv = x - a + var y = b - bv + var q0 = y + var q1 = x + var _x, _bv, _av, _br, _ar + while(eptr < ne && fptr < nf) { + if(ea < fa) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + fa = abs(fi) + } + } + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + } + while(eptr < ne) { + a = ei + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + } + } + while(fptr < nf) { + a = fi + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + } + } + if(q0) { + g[count++] = q0 + } + if(q1) { + g[count++] = q1 + } + if(!count) { + g[count++] = 0.0 + } + g.length = count + return g +} +},{}],492:[function(_dereq_,module,exports){ +"use strict" + +module.exports = function signum(x) { + if(x < 0) { return -1 } + if(x > 0) { return 1 } + return 0.0 +} +},{}],493:[function(_dereq_,module,exports){ +'use strict' + +module.exports = boundary + +var bnd = _dereq_('boundary-cells') +var reduce = _dereq_('reduce-simplicial-complex') + +function boundary(cells) { + return reduce(bnd(cells)) +} + +},{"boundary-cells":83,"reduce-simplicial-complex":472}],494:[function(_dereq_,module,exports){ +'use strict' + +module.exports = extractContour + +var ndarray = _dereq_('ndarray') +var pool = _dereq_('typedarray-pool') +var ndsort = _dereq_('ndarray-sort') + +var contourAlgorithm = _dereq_('./lib/codegen') + +function getDimension(cells) { + var numCells = cells.length + var d = 0 + for(var i=0; i>1,v=E[2*m+1];', + 'if(v===b){return m}', + 'if(b 0) { + code.push(',') + } + code.push('[') + for(var j=0; j 0) { + code.push(',') + } + code.push('B(C,E,c[', f[0], '],c[', f[1], '])') + } + code.push(']') + } + code.push(');') + } + + for(var i=d+1; i>1; --i) { + if(i < d+1) { + code.push('else ') + } + code.push('if(l===', i, '){') + + //Generate mask + var maskStr = [] + for(var j=0; j> 1 + , s = compareCells(cells[mid], c) + if(s <= 0) { + if(s === 0) { + r = mid + } + lo = mid + 1 + } else if(s > 0) { + hi = mid - 1 + } + } + return r +} +exports.findCell = findCell; + +//Builds an index for an n-cell. This is more general than dual, but less efficient +function incidence(from_cells, to_cells) { + var index = new Array(from_cells.length) + for(var i=0, il=index.length; i= from_cells.length || compareCells(from_cells[idx], b) !== 0) { + break + } + } + } + } + return index +} +exports.incidence = incidence + +//Computes the dual of the mesh. This is basically an optimized version of buildIndex for the situation where from_cells is just the list of vertices +function dual(cells, vertex_count) { + if(!vertex_count) { + return incidence(unique(skeleton(cells, 0)), cells, 0) + } + var res = new Array(vertex_count) + for(var i=0; i>> k) & 1) { + b.push(c[k]) + } + } + result.push(b) + } + } + return normalize(result) +} +exports.explode = explode + +//Enumerates all of the n-cells of a cell complex +function skeleton(cells, n) { + if(n < 0) { + return [] + } + var result = [] + , k0 = (1<<(n+1))-1 + for(var i=0; i> 1 + } + return (i >> 1) - 1 + } + + //Bubble element i down the heap + function heapDown(i) { + var w = heapWeight(i) + while(true) { + var tw = w + var left = 2*i + 1 + var right = 2*(i + 1) + var next = i + if(left < heapCount) { + var lw = heapWeight(left) + if(lw < tw) { + next = left + tw = lw + } + } + if(right < heapCount) { + var rw = heapWeight(right) + if(rw < tw) { + next = right + } + } + if(next === i) { + return i + } + heapSwap(i, next) + i = next + } + } + + //Bubbles element i up the heap + function heapUp(i) { + var w = heapWeight(i) + while(i > 0) { + var parent = heapParent(i) + if(parent >= 0) { + var pw = heapWeight(parent) + if(w < pw) { + heapSwap(i, parent) + i = parent + continue + } + } + return i + } + } + + //Pop minimum element + function heapPop() { + if(heapCount > 0) { + var head = heap[0] + heapSwap(0, heapCount-1) + heapCount -= 1 + heapDown(0) + return head + } + return -1 + } + + //Update heap item i + function heapUpdate(i, w) { + var a = heap[i] + if(weights[a] === w) { + return i + } + weights[a] = -Infinity + heapUp(i) + heapPop() + weights[a] = w + heapCount += 1 + return heapUp(heapCount-1) + } + + //Kills a vertex (assume vertex already removed from heap) + function kill(i) { + if(dead[i]) { + return + } + //Kill vertex + dead[i] = true + //Fixup topology + var s = inv[i] + var t = outv[i] + if(inv[t] >= 0) { + inv[t] = s + } + if(outv[s] >= 0) { + outv[s] = t + } + + //Update weights on s and t + if(index[s] >= 0) { + heapUpdate(index[s], computeWeight(s)) + } + if(index[t] >= 0) { + heapUpdate(index[t], computeWeight(t)) + } + } + + //Initialize weights and heap + var heap = [] + var index = new Array(n) + for(var i=0; i>1; i>=0; --i) { + heapDown(i) + } + + //Kill vertices + while(true) { + var hmin = heapPop() + if((hmin < 0) || (weights[hmin] > minArea)) { + break + } + kill(hmin) + } + + //Build collapsed vertex table + var npositions = [] + for(var i=0; i= 0 && tout >= 0 && tin !== tout) { + var cin = index[tin] + var cout = index[tout] + if(cin !== cout) { + ncells.push([ cin, cout ]) + } + } + }) + + //Normalize result + sc.unique(sc.normalize(ncells)) + + //Return final list of cells + return { + positions: npositions, + edges: ncells + } +} +},{"robust-orientation":486,"simplicial-complex":498}],501:[function(_dereq_,module,exports){ +"use strict" + +module.exports = orderSegments + +var orient = _dereq_("robust-orientation") + +function horizontalOrder(a, b) { + var bl, br + if(b[0][0] < b[1][0]) { + bl = b[0] + br = b[1] + } else if(b[0][0] > b[1][0]) { + bl = b[1] + br = b[0] + } else { + var alo = Math.min(a[0][1], a[1][1]) + var ahi = Math.max(a[0][1], a[1][1]) + var blo = Math.min(b[0][1], b[1][1]) + var bhi = Math.max(b[0][1], b[1][1]) + if(ahi < blo) { + return ahi - blo + } + if(alo > bhi) { + return alo - bhi + } + return ahi - bhi + } + var al, ar + if(a[0][1] < a[1][1]) { + al = a[0] + ar = a[1] + } else { + al = a[1] + ar = a[0] + } + var d = orient(br, bl, al) + if(d) { + return d + } + d = orient(br, bl, ar) + if(d) { + return d + } + return ar - br +} + +function orderSegments(b, a) { + var al, ar + if(a[0][0] < a[1][0]) { + al = a[0] + ar = a[1] + } else if(a[0][0] > a[1][0]) { + al = a[1] + ar = a[0] + } else { + return horizontalOrder(a, b) + } + var bl, br + if(b[0][0] < b[1][0]) { + bl = b[0] + br = b[1] + } else if(b[0][0] > b[1][0]) { + bl = b[1] + br = b[0] + } else { + return -horizontalOrder(b, a) + } + var d1 = orient(al, ar, br) + var d2 = orient(al, ar, bl) + if(d1 < 0) { + if(d2 <= 0) { + return d1 + } + } else if(d1 > 0) { + if(d2 >= 0) { + return d1 + } + } else if(d2) { + return d2 + } + d1 = orient(br, bl, ar) + d2 = orient(br, bl, al) + if(d1 < 0) { + if(d2 <= 0) { + return d1 + } + } else if(d1 > 0) { + if(d2 >= 0) { + return d1 + } + } else if(d2) { + return d2 + } + return ar[0] - br[0] +} +},{"robust-orientation":486}],502:[function(_dereq_,module,exports){ +"use strict" + +module.exports = createSlabDecomposition + +var bounds = _dereq_("binary-search-bounds") +var createRBTree = _dereq_("functional-red-black-tree") +var orient = _dereq_("robust-orientation") +var orderSegments = _dereq_("./lib/order-segments") + +function SlabDecomposition(slabs, coordinates, horizontal) { + this.slabs = slabs + this.coordinates = coordinates + this.horizontal = horizontal +} + +var proto = SlabDecomposition.prototype + +function compareHorizontal(e, y) { + return e.y - y +} + +function searchBucket(root, p) { + var lastNode = null + while(root) { + var seg = root.key + var l, r + if(seg[0][0] < seg[1][0]) { + l = seg[0] + r = seg[1] + } else { + l = seg[1] + r = seg[0] + } + var o = orient(l, r, p) + if(o < 0) { + root = root.left + } else if(o > 0) { + if(p[0] !== seg[1][0]) { + lastNode = root + root = root.right + } else { + var val = searchBucket(root.right, p) + if(val) { + return val + } + root = root.left + } + } else { + if(p[0] !== seg[1][0]) { + return root + } else { + var val = searchBucket(root.right, p) + if(val) { + return val + } + root = root.left + } + } + } + return lastNode +} + +proto.castUp = function(p) { + var bucket = bounds.le(this.coordinates, p[0]) + if(bucket < 0) { + return -1 + } + var root = this.slabs[bucket] + var hitNode = searchBucket(this.slabs[bucket], p) + var lastHit = -1 + if(hitNode) { + lastHit = hitNode.value + } + //Edge case: need to handle horizontal segments (sucks) + if(this.coordinates[bucket] === p[0]) { + var lastSegment = null + if(hitNode) { + lastSegment = hitNode.key + } + if(bucket > 0) { + var otherHitNode = searchBucket(this.slabs[bucket-1], p) + if(otherHitNode) { + if(lastSegment) { + if(orderSegments(otherHitNode.key, lastSegment) > 0) { + lastSegment = otherHitNode.key + lastHit = otherHitNode.value + } + } else { + lastHit = otherHitNode.value + lastSegment = otherHitNode.key + } + } + } + var horiz = this.horizontal[bucket] + if(horiz.length > 0) { + var hbucket = bounds.ge(horiz, p[1], compareHorizontal) + if(hbucket < horiz.length) { + var e = horiz[hbucket] + if(p[1] === e.y) { + if(e.closed) { + return e.index + } else { + while(hbucket < horiz.length-1 && horiz[hbucket+1].y === p[1]) { + hbucket = hbucket+1 + e = horiz[hbucket] + if(e.closed) { + return e.index + } + } + if(e.y === p[1] && !e.start) { + hbucket = hbucket+1 + if(hbucket >= horiz.length) { + return lastHit + } + e = horiz[hbucket] + } + } + } + //Check if e is above/below last segment + if(e.start) { + if(lastSegment) { + var o = orient(lastSegment[0], lastSegment[1], [p[0], e.y]) + if(lastSegment[0][0] > lastSegment[1][0]) { + o = -o + } + if(o > 0) { + lastHit = e.index + } + } else { + lastHit = e.index + } + } else if(e.y !== p[1]) { + lastHit = e.index + } + } + } + } + return lastHit +} + +function IntervalSegment(y, index, start, closed) { + this.y = y + this.index = index + this.start = start + this.closed = closed +} + +function Event(x, segment, create, index) { + this.x = x + this.segment = segment + this.create = create + this.index = index +} + + +function createSlabDecomposition(segments) { + var numSegments = segments.length + var numEvents = 2 * numSegments + var events = new Array(numEvents) + for(var i=0; i 1.0) { + t = 1.0 + } + var ti = 1.0 - t + var n = a.length + var r = new Array(n) + for(var i=0; i 0) || (a > 0 && b < 0)) { + var p = lerpW(s, b, t, a) + pos.push(p) + neg.push(p.slice()) + } + if(b < 0) { + neg.push(t.slice()) + } else if(b > 0) { + pos.push(t.slice()) + } else { + pos.push(t.slice()) + neg.push(t.slice()) + } + a = b + } + return { positive: pos, negative: neg } +} + +function positive(points, plane) { + var pos = [] + var a = planeT(points[points.length-1], plane) + for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { + pos.push(lerpW(s, b, t, a)) + } + if(b >= 0) { + pos.push(t.slice()) + } + a = b + } + return pos +} + +function negative(points, plane) { + var neg = [] + var a = planeT(points[points.length-1], plane) + for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { + neg.push(lerpW(s, b, t, a)) + } + if(b <= 0) { + neg.push(t.slice()) + } + a = b + } + return neg +} +},{"robust-dot-product":483,"robust-sum":491}],504:[function(_dereq_,module,exports){ +/* global window, exports, define */ + +!function() { + 'use strict' + + var re = { + not_string: /[^s]/, + not_bool: /[^t]/, + not_type: /[^T]/, + not_primitive: /[^v]/, + number: /[diefg]/, + numeric_arg: /[bcdiefguxX]/, + json: /[j]/, + not_json: /[^j]/, + text: /^[^\x25]+/, + modulo: /^\x25{2}/, + placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/, + key: /^([a-z_][a-z_\d]*)/i, + key_access: /^\.([a-z_][a-z_\d]*)/i, + index_access: /^\[(\d+)\]/, + sign: /^[\+\-]/ + } + + function sprintf(key) { + // `arguments` is not an array, but should be fine for this call + return sprintf_format(sprintf_parse(key), arguments) + } + + function vsprintf(fmt, argv) { + return sprintf.apply(null, [fmt].concat(argv || [])) + } + + function sprintf_format(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, match, pad, pad_character, pad_length, is_positive, sign + for (i = 0; i < tree_length; i++) { + if (typeof parse_tree[i] === 'string') { + output += parse_tree[i] + } + else if (Array.isArray(parse_tree[i])) { + match = parse_tree[i] // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor] + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k])) + } + arg = arg[match[2][k]] + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]] + } + else { // positional argument (implicit) + arg = argv[cursor++] + } + + if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && arg instanceof Function) { + arg = arg() + } + + if (re.numeric_arg.test(match[8]) && (typeof arg !== 'number' && isNaN(arg))) { + throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg)) + } + + if (re.number.test(match[8])) { + is_positive = arg >= 0 + } + + switch (match[8]) { + case 'b': + arg = parseInt(arg, 10).toString(2) + break + case 'c': + arg = String.fromCharCode(parseInt(arg, 10)) + break + case 'd': + case 'i': + arg = parseInt(arg, 10) + break + case 'j': + arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0) + break + case 'e': + arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential() + break + case 'f': + arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg) + break + case 'g': + arg = match[7] ? String(Number(arg.toPrecision(match[7]))) : parseFloat(arg) + break + case 'o': + arg = (parseInt(arg, 10) >>> 0).toString(8) + break + case 's': + arg = String(arg) + arg = (match[7] ? arg.substring(0, match[7]) : arg) + break + case 't': + arg = String(!!arg) + arg = (match[7] ? arg.substring(0, match[7]) : arg) + break + case 'T': + arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase() + arg = (match[7] ? arg.substring(0, match[7]) : arg) + break + case 'u': + arg = parseInt(arg, 10) >>> 0 + break + case 'v': + arg = arg.valueOf() + arg = (match[7] ? arg.substring(0, match[7]) : arg) + break + case 'x': + arg = (parseInt(arg, 10) >>> 0).toString(16) + break + case 'X': + arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase() + break + } + if (re.json.test(match[8])) { + output += arg + } + else { + if (re.number.test(match[8]) && (!is_positive || match[3])) { + sign = is_positive ? '+' : '-' + arg = arg.toString().replace(re.sign, '') + } + else { + sign = '' + } + pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' ' + pad_length = match[6] - (sign + arg).length + pad = match[6] ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : '' + output += match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg) + } + } + } + return output + } + + var sprintf_cache = Object.create(null) + + function sprintf_parse(fmt) { + if (sprintf_cache[fmt]) { + return sprintf_cache[fmt] + } + + var _fmt = fmt, match, parse_tree = [], arg_names = 0 + while (_fmt) { + if ((match = re.text.exec(_fmt)) !== null) { + parse_tree.push(match[0]) + } + else if ((match = re.modulo.exec(_fmt)) !== null) { + parse_tree.push('%') + } + else if ((match = re.placeholder.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1 + var field_list = [], replacement_field = match[2], field_match = [] + if ((field_match = re.key.exec(replacement_field)) !== null) { + field_list.push(field_match[1]) + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = re.key_access.exec(replacement_field)) !== null) { + field_list.push(field_match[1]) + } + else if ((field_match = re.index_access.exec(replacement_field)) !== null) { + field_list.push(field_match[1]) + } + else { + throw new SyntaxError('[sprintf] failed to parse named argument key') + } + } + } + else { + throw new SyntaxError('[sprintf] failed to parse named argument key') + } + match[2] = field_list + } + else { + arg_names |= 2 + } + if (arg_names === 3) { + throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported') + } + parse_tree.push(match) + } + else { + throw new SyntaxError('[sprintf] unexpected placeholder') + } + _fmt = _fmt.substring(match[0].length) + } + return sprintf_cache[fmt] = parse_tree + } + + /** + * export to either browser or node.js + */ + /* eslint-disable quote-props */ + if (typeof exports !== 'undefined') { + exports['sprintf'] = sprintf + exports['vsprintf'] = vsprintf + } + if (typeof window !== 'undefined') { + window['sprintf'] = sprintf + window['vsprintf'] = vsprintf + + if (typeof define === 'function' && define['amd']) { + define(function() { + return { + 'sprintf': sprintf, + 'vsprintf': vsprintf + } + }) + } + } + /* eslint-enable quote-props */ +}() + +},{}],505:[function(_dereq_,module,exports){ +'use strict' + +var paren = _dereq_('parenthesis') + +module.exports = function splitBy (string, separator, o) { + if (string == null) throw Error('First argument should be a string') + if (separator == null) throw Error('Separator should be a string or a RegExp') + + if (!o) o = {} + else if (typeof o === 'string' || Array.isArray(o)) { + o = {ignore: o} + } + + if (o.escape == null) o.escape = true + if (o.ignore == null) o.ignore = ['[]', '()', '{}', '<>', '""', "''", '``', '“”', '«»'] + else { + if (typeof o.ignore === 'string') {o.ignore = [o.ignore]} + + o.ignore = o.ignore.map(function (pair) { + // '"' → '""' + if (pair.length === 1) pair = pair + pair + return pair + }) + } + + var tokens = paren.parse(string, {flat: true, brackets: o.ignore}) + var str = tokens[0] + + var parts = str.split(separator) + + // join parts separated by escape + if (o.escape) { + var cleanParts = [] + for (var i = 0; i < parts.length; i++) { + var prev = parts[i] + var part = parts[i + 1] + + if (prev[prev.length - 1] === '\\' && prev[prev.length - 2] !== '\\') { + cleanParts.push(prev + separator + part) + i++ + } + else { + cleanParts.push(prev) + } + } + parts = cleanParts + } + + // open parens pack & apply unquotes, if any + for (var i = 0; i < parts.length; i++) { + tokens[0] = parts[i] + parts[i] = paren.stringify(tokens, {flat: true}) + } + + return parts +} + +},{"parenthesis":441}],506:[function(_dereq_,module,exports){ +"use strict" + +module.exports = stronglyConnectedComponents + +function stronglyConnectedComponents(adjList) { + var numVertices = adjList.length; + var index = new Array(numVertices) + var lowValue = new Array(numVertices) + var active = new Array(numVertices) + var child = new Array(numVertices) + var scc = new Array(numVertices) + var sccLinks = new Array(numVertices) + + //Initialize tables + for(var i=0; i 0) { + v = T[T.length-1] + var e = adjList[v] + if (child[v] < e.length) { // If we're not done iterating over the children, first try finishing that. + for(var i=child[v]; i= 0) { + // Node v is not yet assigned an scc, but once it is that scc can apparently reach scc[u]. + sccLinks[v].push(scc[u]) + } + } + child[v] = i // Remember where we left off. + } else { // If we're done iterating over the children, check whether we have an scc. + if(lowValue[v] === index[v]) { // TODO: It /might/ be true that T is always a prefix of S (at this point!!!), and if so, this could be used here. + var component = [] + var links = [], linkCount = 0 + for(var i=S.length-1; i>=0; --i) { + var w = S[i] + active[w] = false + component.push(w) + links.push(sccLinks[w]) + linkCount += sccLinks[w].length + scc[w] = components.length + if(w === v) { + S.length = i + break + } + } + components.push(component) + var allLinks = new Array(linkCount) + for(var i=0; i c)|0 },") + if(dtype === "generic") { + code.push("getters:[0],") + } + + //Generate vertex function + var cubeArgs = [] + var extraArgs = [] + for(var i=0; i>>7){") + } + for(var i=0; i<1<<(1< 128) { + if((i%128)===0) { + if(extraFuncs.length > 0) { + currentFunc.push("}}") + } + var efName = "vExtra" + extraFuncs.length + code.push("case ", (i>>>7), ":", efName, "(m&0x7f,", extraArgs.join(), ");break;") + currentFunc = [ + "function ", efName, "(m,", extraArgs.join(), "){switch(m){" + ] + extraFuncs.push(currentFunc) + } + } + currentFunc.push("case ", (i&0x7f), ":") + var crossings = new Array(dimension) + var denoms = new Array(dimension) + var crossingCount = new Array(dimension) + var bias = new Array(dimension) + var totalCrossings = 0 + for(var j=0; j j) { + continue + } + if(!(i&(1< 0) { + cStr = "+" + crossingCount[k] + "*c" + } + var weight = 0.5 * (crossings[k].length / totalCrossings) + var shift = 0.5 + 0.5 * (bias[k] / totalCrossings) + vertexStr.push("d" + k + "-" + shift + "-" + weight + "*(" + crossings[k].join("+") + cStr + ")/(" + denoms[k].join("+") + ")") + + } + } + currentFunc.push("a.push([", vertexStr.join(), "]);", + "break;") + } + code.push("}},") + if(extraFuncs.length > 0) { + currentFunc.push("}}") + } + + //Create face function + var faceArgs = [] + for(var i=0; i<(1<<(dimension-1)); ++i) { + faceArgs.push("v" + i) + } + faceArgs.push("c0", "c1", "p0", "p1", "a", "b", "c") + code.push("cell:function cellFunc(", faceArgs.join(), "){") + + var facets = triangulateCube(dimension-1) + code.push("if(p0){b.push(", + facets.map(function(f) { + return "[" + f.map(function(v) { + return "v" + v + }) + "]" + }).join(), ")}else{b.push(", + facets.map(function(f) { + var e = f.slice() + e.reverse() + return "[" + e.map(function(v) { + return "v" + v + }) + "]" + }).join(), + ")}}});function ", funcName, "(array,level){var verts=[],cells=[];contour(array,verts,cells,level);return {positions:verts,cells:cells};} return ", funcName, ";") + + for(var i=0; i 1) { + div = 1; + } + + if (div < -1) { + div = -1; + } + + return sign * Math.acos(div); +}; + +var getArcCenter = function getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp) { + var rxsq = Math.pow(rx, 2); + var rysq = Math.pow(ry, 2); + var pxpsq = Math.pow(pxp, 2); + var pypsq = Math.pow(pyp, 2); + + var radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq; + + if (radicant < 0) { + radicant = 0; + } + + radicant /= rxsq * pypsq + rysq * pxpsq; + radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1); + + var centerxp = radicant * rx / ry * pyp; + var centeryp = radicant * -ry / rx * pxp; + + var centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2; + var centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2; + + var vx1 = (pxp - centerxp) / rx; + var vy1 = (pyp - centeryp) / ry; + var vx2 = (-pxp - centerxp) / rx; + var vy2 = (-pyp - centeryp) / ry; + + var ang1 = vectorAngle(1, 0, vx1, vy1); + var ang2 = vectorAngle(vx1, vy1, vx2, vy2); + + if (sweepFlag === 0 && ang2 > 0) { + ang2 -= TAU; + } + + if (sweepFlag === 1 && ang2 < 0) { + ang2 += TAU; + } + + return [centerx, centery, ang1, ang2]; +}; + +var arcToBezier = function arcToBezier(_ref2) { + var px = _ref2.px, + py = _ref2.py, + cx = _ref2.cx, + cy = _ref2.cy, + rx = _ref2.rx, + ry = _ref2.ry, + _ref2$xAxisRotation = _ref2.xAxisRotation, + xAxisRotation = _ref2$xAxisRotation === undefined ? 0 : _ref2$xAxisRotation, + _ref2$largeArcFlag = _ref2.largeArcFlag, + largeArcFlag = _ref2$largeArcFlag === undefined ? 0 : _ref2$largeArcFlag, + _ref2$sweepFlag = _ref2.sweepFlag, + sweepFlag = _ref2$sweepFlag === undefined ? 0 : _ref2$sweepFlag; + + var curves = []; + + if (rx === 0 || ry === 0) { + return []; + } + + var sinphi = Math.sin(xAxisRotation * TAU / 360); + var cosphi = Math.cos(xAxisRotation * TAU / 360); + + var pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2; + var pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2; + + if (pxp === 0 && pyp === 0) { + return []; + } + + rx = Math.abs(rx); + ry = Math.abs(ry); + + var lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2); + + if (lambda > 1) { + rx *= Math.sqrt(lambda); + ry *= Math.sqrt(lambda); + } + + var _getArcCenter = getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp), + _getArcCenter2 = _slicedToArray(_getArcCenter, 4), + centerx = _getArcCenter2[0], + centery = _getArcCenter2[1], + ang1 = _getArcCenter2[2], + ang2 = _getArcCenter2[3]; + + // If 'ang2' == 90.0000000001, then `ratio` will evaluate to + // 1.0000000001. This causes `segments` to be greater than one, which is an + // unecessary split, and adds extra points to the bezier curve. To alleviate + // this issue, we round to 1.0 when the ratio is close to 1.0. + + + var ratio = Math.abs(ang2) / (TAU / 4); + if (Math.abs(1.0 - ratio) < 0.0000001) { + ratio = 1.0; + } + + var segments = Math.max(Math.ceil(ratio), 1); + + ang2 /= segments; + + for (var i = 0; i < segments; i++) { + curves.push(approxUnitArc(ang1, ang2)); + ang1 += ang2; + } + + return curves.map(function (curve) { + var _mapToEllipse = mapToEllipse(curve[0], rx, ry, cosphi, sinphi, centerx, centery), + x1 = _mapToEllipse.x, + y1 = _mapToEllipse.y; + + var _mapToEllipse2 = mapToEllipse(curve[1], rx, ry, cosphi, sinphi, centerx, centery), + x2 = _mapToEllipse2.x, + y2 = _mapToEllipse2.y; + + var _mapToEllipse3 = mapToEllipse(curve[2], rx, ry, cosphi, sinphi, centerx, centery), + x = _mapToEllipse3.x, + y = _mapToEllipse3.y; + + return { x1: x1, y1: y1, x2: x2, y2: y2, x: x, y: y }; + }); +}; + +exports.default = arcToBezier; +module.exports = exports.default; +},{}],510:[function(_dereq_,module,exports){ +'use strict' + +var parse = _dereq_('parse-svg-path') +var abs = _dereq_('abs-svg-path') +var normalize = _dereq_('normalize-svg-path') +var isSvgPath = _dereq_('is-svg-path') +var assert = _dereq_('assert') + +module.exports = pathBounds + + +function pathBounds(path) { + // ES6 string tpl call + if (Array.isArray(path) && path.length === 1 && typeof path[0] === 'string') path = path[0] + + // svg path string + if (typeof path === 'string') { + assert(isSvgPath(path), 'String is not an SVG path.') + path = parse(path) + } + + assert(Array.isArray(path), 'Argument should be a string or an array of path segments.') + + path = abs(path) + path = normalize(path) + + if (!path.length) return [0, 0, 0, 0] + + var bounds = [Infinity, Infinity, -Infinity, -Infinity] + + for (var i = 0, l = path.length; i < l; i++) { + var points = path[i].slice(1) + + for (var j = 0; j < points.length; j += 2) { + if (points[j + 0] < bounds[0]) bounds[0] = points[j + 0] + if (points[j + 1] < bounds[1]) bounds[1] = points[j + 1] + if (points[j + 0] > bounds[2]) bounds[2] = points[j + 0] + if (points[j + 1] > bounds[3]) bounds[3] = points[j + 1] + } + } + + return bounds +} + +},{"abs-svg-path":48,"assert":56,"is-svg-path":407,"normalize-svg-path":511,"parse-svg-path":443}],511:[function(_dereq_,module,exports){ +'use strict' + +module.exports = normalize + +var arcToCurve = _dereq_('svg-arc-to-cubic-bezier') + +function normalize(path){ + // init state + var prev + var result = [] + var bezierX = 0 + var bezierY = 0 + var startX = 0 + var startY = 0 + var quadX = null + var quadY = null + var x = 0 + var y = 0 + + for (var i = 0, len = path.length; i < len; i++) { + var seg = path[i] + var command = seg[0] + + switch (command) { + case 'M': + startX = seg[1] + startY = seg[2] + break + case 'A': + var curves = arcToCurve({ + px: x, + py: y, + cx: seg[6], + cy: seg[7], + rx: seg[1], + ry: seg[2], + xAxisRotation: seg[3], + largeArcFlag: seg[4], + sweepFlag: seg[5] + }) + + // null-curves + if (!curves.length) continue + + for (var j = 0, c; j < curves.length; j++) { + c = curves[j] + seg = ['C', c.x1, c.y1, c.x2, c.y2, c.x, c.y] + if (j < curves.length - 1) result.push(seg) + } + + break + case 'S': + // default control point + var cx = x + var cy = y + if (prev == 'C' || prev == 'S') { + cx += cx - bezierX // reflect the previous command's control + cy += cy - bezierY // point relative to the current point + } + seg = ['C', cx, cy, seg[1], seg[2], seg[3], seg[4]] + break + case 'T': + if (prev == 'Q' || prev == 'T') { + quadX = x * 2 - quadX // as with 'S' reflect previous control point + quadY = y * 2 - quadY + } else { + quadX = x + quadY = y + } + seg = quadratic(x, y, quadX, quadY, seg[1], seg[2]) + break + case 'Q': + quadX = seg[1] + quadY = seg[2] + seg = quadratic(x, y, seg[1], seg[2], seg[3], seg[4]) + break + case 'L': + seg = line(x, y, seg[1], seg[2]) + break + case 'H': + seg = line(x, y, seg[1], y) + break + case 'V': + seg = line(x, y, x, seg[1]) + break + case 'Z': + seg = line(x, y, startX, startY) + break + } + + // update state + prev = command + x = seg[seg.length - 2] + y = seg[seg.length - 1] + if (seg.length > 4) { + bezierX = seg[seg.length - 4] + bezierY = seg[seg.length - 3] + } else { + bezierX = x + bezierY = y + } + result.push(seg) + } + + return result +} + +function line(x1, y1, x2, y2){ + return ['C', x1, y1, x2, y2, x2, y2] +} + +function quadratic(x1, y1, cx, cy, x2, y2){ + return [ + 'C', + x1/3 + (2/3) * cx, + y1/3 + (2/3) * cy, + x2/3 + (2/3) * cx, + y2/3 + (2/3) * cy, + x2, + y2 + ] +} + +},{"svg-arc-to-cubic-bezier":509}],512:[function(_dereq_,module,exports){ +'use strict' + +var pathBounds = _dereq_('svg-path-bounds') +var parsePath = _dereq_('parse-svg-path') +var drawPath = _dereq_('draw-svg-path') +var isSvgPath = _dereq_('is-svg-path') +var bitmapSdf = _dereq_('bitmap-sdf') + +var canvas = document.createElement('canvas') +var ctx = canvas.getContext('2d') + + +module.exports = pathSdf + + +function pathSdf (path, options) { + if (!isSvgPath(path)) throw Error('Argument should be valid svg path string') + + if (!options) options = {} + + var w, h + if (options.shape) { + w = options.shape[0] + h = options.shape[1] + } + else { + w = canvas.width = options.w || options.width || 200 + h = canvas.height = options.h || options.height || 200 + } + var size = Math.min(w, h) + + var stroke = options.stroke || 0 + + var viewbox = options.viewbox || options.viewBox || pathBounds(path) + var scale = [w / (viewbox[2] - viewbox[0]), h / (viewbox[3] - viewbox[1])] + var maxScale = Math.min(scale[0] || 0, scale[1] || 0) / 2 + + //clear ctx + ctx.fillStyle = 'black' + ctx.fillRect(0, 0, w, h) + + ctx.fillStyle = 'white' + + if (stroke) { + if (typeof stroke != 'number') stroke = 1 + if (stroke > 0) { + ctx.strokeStyle = 'white' + } + else { + ctx.strokeStyle = 'black' + } + + ctx.lineWidth = Math.abs(stroke) + } + + ctx.translate(w * .5, h * .5) + ctx.scale(maxScale, maxScale) + + //if canvas svg paths api is available + if (isPath2DSupported()) { + var path2d = new Path2D(path) + ctx.fill(path2d) + stroke && ctx.stroke(path2d) + } + //fallback to bezier-curves + else { + var segments = parsePath(path) + drawPath(ctx, segments) + ctx.fill() + stroke && ctx.stroke() + } + + ctx.setTransform(1, 0, 0, 1, 0, 0); + + var data = bitmapSdf(ctx, { + cutoff: options.cutoff != null ? options.cutoff : .5, + radius: options.radius != null ? options.radius : size * .5 + }) + + return data +} + +function isPath2DSupported () { + var ctx = document.createElement('canvas').getContext('2d') + ctx.canvas.width = ctx.canvas.height = 1 + + var path = new Path2D('M0,0h1v1h-1v-1Z') + + ctx.fillStyle = 'black' + ctx.fill(path) + + var idata = ctx.getImageData(0,0,1,1) + + return idata && idata.data && idata.data[3] === 255 +} + +},{"bitmap-sdf":81,"draw-svg-path":153,"is-svg-path":407,"parse-svg-path":443,"svg-path-bounds":510}],513:[function(_dereq_,module,exports){ +(function (process){ +'use strict' + +module.exports = textGet + +var vectorizeText = _dereq_('vectorize-text') + +var globals = window || process.global || {} +var __TEXT_CACHE = globals.__TEXT_CACHE || {} +globals.__TEXT_CACHE = {} + +function unwrap(mesh) { + var cells = mesh.cells + var positions = mesh.positions + var data = new Float32Array(cells.length * 6) + var ptr = 0 + var shapeX = 0 + for(var i=0; i0) { + shapeX += 0.02 + } + } + + var data = new Float32Array(bufferSize) + var ptr = 0 + var xOffset = -0.5 * shapeX + for(var i=0; i= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); + + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex4") { + formattedString = this.toHex8String(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + + return formattedString || this.toHexString(); + }, + clone: function() { + return tinycolor(this.toString()); + }, + + _applyModification: function(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function() { + return this._applyModification(lighten, arguments); + }, + brighten: function() { + return this._applyModification(brighten, arguments); + }, + darken: function() { + return this._applyModification(darken, arguments); + }, + desaturate: function() { + return this._applyModification(desaturate, arguments); + }, + saturate: function() { + return this._applyModification(saturate, arguments); + }, + greyscale: function() { + return this._applyModification(greyscale, arguments); + }, + spin: function() { + return this._applyModification(spin, arguments); + }, + + _applyCombination: function(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function() { + return this._applyCombination(analogous, arguments); + }, + complement: function() { + return this._applyCombination(complement, arguments); + }, + monochromatic: function() { + return this._applyCombination(monochromatic, arguments); + }, + splitcomplement: function() { + return this._applyCombination(splitcomplement, arguments); + }, + triad: function() { + return this._applyCombination(triad, arguments); + }, + tetrad: function() { + return this._applyCombination(tetrad, arguments); + } +}; + +// If input is an object, force 1 into "1.0" to handle ratios properly +// String input requires "1.0" as input, so 1 will be treated as 1 +tinycolor.fromRatio = function(color, opts) { + if (typeof color == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } + else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + + return tinycolor(color, opts); +}; + +// Given a string or object, convert that input to RGB +// Possible string inputs: +// +// "red" +// "#f00" or "f00" +// "#ff0000" or "ff0000" +// "#ff000000" or "ff000000" +// "rgb 255 0 0" or "rgb (255, 0, 0)" +// "rgb 1.0 0 0" or "rgb (1, 0, 0)" +// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" +// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" +// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" +// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" +// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" +// +function inputToRGB(color) { + + var rgb = { r: 0, g: 0, b: 0 }; + var a = 1; + var s = null; + var v = null; + var l = null; + var ok = false; + var format = false; + + if (typeof color == "string") { + color = stringInputToObject(color); + } + + if (typeof color == "object") { + if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { + s = convertToPercentage(color.s); + v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, s, v); + ok = true; + format = "hsv"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { + s = convertToPercentage(color.s); + l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, s, l); + ok = true; + format = "hsl"; + } + + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + + a = boundAlpha(a); + + return { + ok: ok, + format: color.format || format, + r: mathMin(255, mathMax(rgb.r, 0)), + g: mathMin(255, mathMax(rgb.g, 0)), + b: mathMin(255, mathMax(rgb.b, 0)), + a: a + }; +} + + +// Conversion Functions +// -------------------- + +// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: +// + +// `rgbToRgb` +// Handle bounds / percentage checking to conform to CSS color spec +// +// *Assumes:* r, g, b in [0, 255] or [0, 1] +// *Returns:* { r, g, b } in [0, 255] +function rgbToRgb(r, g, b){ + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; +} + +// `rgbToHsl` +// Converts an RGB color value to HSL. +// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] +// *Returns:* { h, s, l } in [0,1] +function rgbToHsl(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + h /= 6; + } + + return { h: h, s: s, l: l }; +} + +// `hslToRgb` +// Converts an HSL color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] +function hslToRgb(h, s, l) { + var r, g, b; + + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + if(s === 0) { + r = g = b = l; // achromatic + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHsv` +// Converts an RGB color value to HSV +// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] +// *Returns:* { h, s, v } in [0,1] +function rgbToHsv(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if(max == min) { + h = 0; // achromatic + } + else { + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h, s: s, v: v }; +} + +// `hsvToRgb` +// Converts an HSV color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + + var i = Math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHex` +// Converts an RGB color to hex +// Assumes r, g, and b are contained in the set [0, 255] +// Returns a 3 or 6 character hex +function rgbToHex(r, g, b, allow3Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + + return hex.join(""); +} + +// `rgbaToHex` +// Converts an RGBA color plus alpha transparency to hex +// Assumes r, g, b are contained in the set [0, 255] and +// a in [0, 1]. Returns a 4 or 8 character rgba hex +function rgbaToHex(r, g, b, a, allow4Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)), + pad2(convertDecimalToHex(a)) + ]; + + // Return a 4 character hex if possible + if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); + } + + return hex.join(""); +} + +// `rgbaToArgbHex` +// Converts an RGBA color to an ARGB Hex8 string +// Rarely used, but required for "toFilter()" +function rgbaToArgbHex(r, g, b, a) { + + var hex = [ + pad2(convertDecimalToHex(a)), + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + return hex.join(""); +} + +// `equals` +// Can be called with any tinycolor input +tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) { return false; } + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); +}; + +tinycolor.random = function() { + return tinycolor.fromRatio({ + r: mathRandom(), + g: mathRandom(), + b: mathRandom() + }); +}; + + +// Modification Functions +// ---------------------- +// Thanks to less.js for some of the basics here +// + +function desaturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function saturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function greyscale(color) { + return tinycolor(color).desaturate(100); +} + +function lighten (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +function brighten(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var rgb = tinycolor(color).toRgb(); + rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); + rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); + rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); + return tinycolor(rgb); +} + +function darken (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. +// Values outside of this range will be wrapped into this range. +function spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (hsl.h + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); +} + +// Combination Functions +// --------------------- +// Thanks to jQuery xColor for some of the ideas behind these +// + +function complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); +} + +function triad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function tetrad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), + tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) + ]; +} + +function analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + + for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; +} + +function monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, s = hsv.s, v = hsv.v; + var ret = []; + var modification = 1 / results; + + while (results--) { + ret.push(tinycolor({ h: h, s: s, v: v})); + v = (v + modification) % 1; + } + + return ret; +} + +// Utility Functions +// --------------------- + +tinycolor.mix = function(color1, color2, amount) { + amount = (amount === 0) ? 0 : (amount || 50); + + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + + var p = amount / 100; + + var rgba = { + r: ((rgb2.r - rgb1.r) * p) + rgb1.r, + g: ((rgb2.g - rgb1.g) * p) + rgb1.g, + b: ((rgb2.b - rgb1.b) * p) + rgb1.b, + a: ((rgb2.a - rgb1.a) * p) + rgb1.a + }; + + return tinycolor(rgba); +}; + + +// Readability Functions +// --------------------- +// false +// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false +tinycolor.isReadable = function(color1, color2, wcag2) { + var readability = tinycolor.readability(color1, color2); + var wcag2Parms, out; + + out = false; + + wcag2Parms = validateWCAG2Parms(wcag2); + switch (wcag2Parms.level + wcag2Parms.size) { + case "AAsmall": + case "AAAlarge": + out = readability >= 4.5; + break; + case "AAlarge": + out = readability >= 3; + break; + case "AAAsmall": + out = readability >= 7; + break; + } + return out; + +}; + +// `mostReadable` +// Given a base color and a list of possible foreground or background +// colors for that base, returns the most readable color. +// Optionally returns Black or White if the most readable color is unreadable. +// *Example* +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" +tinycolor.mostReadable = function(baseColor, colorList, args) { + var bestColor = null; + var bestScore = 0; + var readability; + var includeFallbackColors, level, size ; + args = args || {}; + includeFallbackColors = args.includeFallbackColors ; + level = args.level; + size = args.size; + + for (var i= 0; i < colorList.length ; i++) { + readability = tinycolor.readability(baseColor, colorList[i]); + if (readability > bestScore) { + bestScore = readability; + bestColor = tinycolor(colorList[i]); + } + } + + if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { + return bestColor; + } + else { + args.includeFallbackColors=false; + return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); + } +}; + + +// Big List of Colors +// ------------------ +// +var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" +}; + +// Make it easy to access colors via `hexNames[hex]` +var hexNames = tinycolor.hexNames = flip(names); + + +// Utilities +// --------- + +// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` +function flip(o) { + var flipped = { }; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; +} + +// Return a valid alpha value [0,1] with all invalid values being set to 1 +function boundAlpha(a) { + a = parseFloat(a); + + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + + return a; +} + +// Take input from [0, n] and return it as [0, 1] +function bound01(n, max) { + if (isOnePointZero(n)) { n = "100%"; } + + var processPercent = isPercentage(n); + n = mathMin(max, mathMax(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if ((Math.abs(n - max) < 0.000001)) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return (n % max) / parseFloat(max); +} + +// Force a number between 0 and 1 +function clamp01(val) { + return mathMin(1, mathMax(0, val)); +} + +// Parse a base-16 hex value into a base-10 integer +function parseIntFromHex(val) { + return parseInt(val, 16); +} + +// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 +// +function isOnePointZero(n) { + return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; +} + +// Check to see if string passed in is a percentage +function isPercentage(n) { + return typeof n === "string" && n.indexOf('%') != -1; +} + +// Force a hex value to have 2 characters +function pad2(c) { + return c.length == 1 ? '0' + c : '' + c; +} + +// Replace a decimal with it's percentage value +function convertToPercentage(n) { + if (n <= 1) { + n = (n * 100) + "%"; + } + + return n; +} + +// Converts a decimal to a hex value +function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); +} +// Converts a hex value to a decimal +function convertHexToDecimal(h) { + return (parseIntFromHex(h) / 255); +} + +var matchers = (function() { + + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + + return { + CSS_UNIT: new RegExp(CSS_UNIT), + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; +})(); + +// `isValidCSSUnit` +// Take in a single string / number and check to see if it looks like a CSS unit +// (see `matchers` above for definition). +function isValidCSSUnit(color) { + return !!matchers.CSS_UNIT.exec(color); +} + +// `stringInputToObject` +// Permissive string parsing. Take in a number of formats, and output an object +// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` +function stringInputToObject(color) { + + color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } + else if (color == 'transparent') { + return { r: 0, g: 0, b: 0, a: 0, format: "name" }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if ((match = matchers.rgb.exec(color))) { + return { r: match[1], g: match[2], b: match[3] }; + } + if ((match = matchers.rgba.exec(color))) { + return { r: match[1], g: match[2], b: match[3], a: match[4] }; + } + if ((match = matchers.hsl.exec(color))) { + return { h: match[1], s: match[2], l: match[3] }; + } + if ((match = matchers.hsla.exec(color))) { + return { h: match[1], s: match[2], l: match[3], a: match[4] }; + } + if ((match = matchers.hsv.exec(color))) { + return { h: match[1], s: match[2], v: match[3] }; + } + if ((match = matchers.hsva.exec(color))) { + return { h: match[1], s: match[2], v: match[3], a: match[4] }; + } + if ((match = matchers.hex8.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex6.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if ((match = matchers.hex4.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + a: convertHexToDecimal(match[4] + '' + match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex3.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + format: named ? "name" : "hex" + }; + } + + return false; +} + +function validateWCAG2Parms(parms) { + // return valid WCAG2 parms for isReadable. + // If input parms are invalid, return {"level":"AA", "size":"small"} + var level, size; + parms = parms || {"level":"AA", "size":"small"}; + level = (parms.level || "AA").toUpperCase(); + size = (parms.size || "small").toLowerCase(); + if (level !== "AA" && level !== "AAA") { + level = "AA"; + } + if (size !== "small" && size !== "large") { + size = "small"; + } + return {"level":level, "size":size}; +} + +// Node: Export function +if (typeof module !== "undefined" && module.exports) { + module.exports = tinycolor; +} +// AMD/requirejs: Define the module +else if (typeof define === 'function' && define.amd) { + define(function () {return tinycolor;}); +} +// Browser: Expose to window +else { + window.tinycolor = tinycolor; +} + +})(Math); + +},{}],515:[function(_dereq_,module,exports){ +/* @module to-float32 */ + +'use strict' + +module.exports = float32 +module.exports.float32 = +module.exports.float = float32 +module.exports.fract32 = +module.exports.fract = fract32 + +// return fractional part of float32 array +function fract32 (arr) { + if (typeof arr === 'number') { + return float32(arr - float32(arr)) + } + + var fract = float32(arr) + for (var i = 0, l = fract.length; i < l; i++) { + fract[i] = arr[i] - fract[i] + } + return fract +} + +// make sure data is float32 array +function float32 (arr) { + if (arr instanceof Float32Array) return arr + if (typeof arr === 'number') { + return (new Float32Array([arr]))[0] + } + + var float = new Float32Array(arr) + float.set(arr) + return float +} + +},{}],516:[function(_dereq_,module,exports){ +'use strict' + +var parseUnit = _dereq_('parse-unit') + +module.exports = toPX + +var PIXELS_PER_INCH = 96 + +function getPropertyInPX(element, prop) { + var parts = parseUnit(getComputedStyle(element).getPropertyValue(prop)) + return parts[0] * toPX(parts[1], element) +} + +//This brutal hack is needed +function getSizeBrutal(unit, element) { + var testDIV = document.createElement('div') + testDIV.style['font-size'] = '128' + unit + element.appendChild(testDIV) + var size = getPropertyInPX(testDIV, 'font-size') / 128 + element.removeChild(testDIV) + return size +} + +function toPX(str, element) { + element = element || document.body + str = (str || 'px').trim().toLowerCase() + if(element === window || element === document) { + element = document.body + } + switch(str) { + case '%': //Ambiguous, not sure if we should use width or height + return element.clientHeight / 100.0 + case 'ch': + case 'ex': + return getSizeBrutal(str, element) + case 'em': + return getPropertyInPX(element, 'font-size') + case 'rem': + return getPropertyInPX(document.body, 'font-size') + case 'vw': + return window.innerWidth/100 + case 'vh': + return window.innerHeight/100 + case 'vmin': + return Math.min(window.innerWidth, window.innerHeight) / 100 + case 'vmax': + return Math.max(window.innerWidth, window.innerHeight) / 100 + case 'in': + return PIXELS_PER_INCH + case 'cm': + return PIXELS_PER_INCH / 2.54 + case 'mm': + return PIXELS_PER_INCH / 25.4 + case 'pt': + return PIXELS_PER_INCH / 72 + case 'pc': + return PIXELS_PER_INCH / 6 + } + return 1 +} +},{"parse-unit":444}],517:[function(_dereq_,module,exports){ +// https://github.com/topojson/topojson-client Version 2.1.0. Copyright 2016 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.topojson = global.topojson || {}))); +}(this, (function (exports) { 'use strict'; + +var identity = function(x) { + return x; +}; + +var transform = function(topology) { + if ((transform = topology.transform) == null) return identity; + var transform, + x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + point[0] = (x0 += point[0]) * kx + dx; + point[1] = (y0 += point[1]) * ky + dy; + return point; + }; +}; + +var bbox = function(topology) { + var bbox = topology.bbox; + + function bboxPoint(p0) { + p1[0] = p0[0], p1[1] = p0[1], t(p1); + if (p1[0] < x0) x0 = p1[0]; + if (p1[0] > x1) x1 = p1[0]; + if (p1[1] < y0) y0 = p1[1]; + if (p1[1] > y1) y1 = p1[1]; + } + + function bboxGeometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(bboxGeometry); break; + case "Point": bboxPoint(o.coordinates); break; + case "MultiPoint": o.coordinates.forEach(bboxPoint); break; + } + } + + if (!bbox) { + var t = transform(topology), p0, p1 = new Array(2), name, + x0 = Infinity, y0 = x0, x1 = -x0, y1 = -x0; + + topology.arcs.forEach(function(arc) { + var i = -1, n = arc.length; + while (++i < n) { + p0 = arc[i], p1[0] = p0[0], p1[1] = p0[1], t(p1, i); + if (p1[0] < x0) x0 = p1[0]; + if (p1[0] > x1) x1 = p1[0]; + if (p1[1] < y0) y0 = p1[1]; + if (p1[1] > y1) y1 = p1[1]; + } + }); + + for (name in topology.objects) { + bboxGeometry(topology.objects[name]); + } + + bbox = topology.bbox = [x0, y0, x1, y1]; + } + + return bbox; +}; + +var reverse = function(array, n) { + var t, j = array.length, i = j - n; + while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; +}; + +var feature = function(topology, o) { + return o.type === "GeometryCollection" + ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); })} + : feature$1(topology, o); +}; + +function feature$1(topology, o) { + var id = o.id, + bbox = o.bbox, + properties = o.properties == null ? {} : o.properties, + geometry = object(topology, o); + return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry} + : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry} + : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry}; +} + +function object(topology, o) { + var transformPoint = transform(topology), + arcs = topology.arcs; + + function arc(i, points) { + if (points.length) points.pop(); + for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) { + points.push(transformPoint(a[k].slice(), k)); + } + if (i < 0) reverse(points, n); + } + + function point(p) { + return transformPoint(p.slice()); + } + + function line(arcs) { + var points = []; + for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); + if (points.length < 2) points.push(points[0].slice()); + return points; + } + + function ring(arcs) { + var points = line(arcs); + while (points.length < 4) points.push(points[0].slice()); + return points; + } + + function polygon(arcs) { + return arcs.map(ring); + } + + function geometry(o) { + var type = o.type, coordinates; + switch (type) { + case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)}; + case "Point": coordinates = point(o.coordinates); break; + case "MultiPoint": coordinates = o.coordinates.map(point); break; + case "LineString": coordinates = line(o.arcs); break; + case "MultiLineString": coordinates = o.arcs.map(line); break; + case "Polygon": coordinates = polygon(o.arcs); break; + case "MultiPolygon": coordinates = o.arcs.map(polygon); break; + default: return null; + } + return {type: type, coordinates: coordinates}; + } + + return geometry(o); +} + +var stitch = function(topology, arcs) { + var stitchedArcs = {}, + fragmentByStart = {}, + fragmentByEnd = {}, + fragments = [], + emptyIndex = -1; + + // Stitch empty arcs first, since they may be subsumed by other arcs. + arcs.forEach(function(i, j) { + var arc = topology.arcs[i < 0 ? ~i : i], t; + if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { + t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; + } + }); + + arcs.forEach(function(i) { + var e = ends(i), + start = e[0], + end = e[1], + f, g; + + if (f = fragmentByEnd[start]) { + delete fragmentByEnd[f.end]; + f.push(i); + f.end = end; + if (g = fragmentByStart[end]) { + delete fragmentByStart[g.start]; + var fg = g === f ? f : f.concat(g); + fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else if (f = fragmentByStart[end]) { + delete fragmentByStart[f.start]; + f.unshift(i); + f.start = start; + if (g = fragmentByEnd[start]) { + delete fragmentByEnd[g.end]; + var gf = g === f ? f : g.concat(f); + fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else { + f = [i]; + fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; + } + }); + + function ends(i) { + var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; + if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); + else p1 = arc[arc.length - 1]; + return i < 0 ? [p1, p0] : [p0, p1]; + } + + function flush(fragmentByEnd, fragmentByStart) { + for (var k in fragmentByEnd) { + var f = fragmentByEnd[k]; + delete fragmentByStart[f.start]; + delete f.start; + delete f.end; + f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); + fragments.push(f); + } + } + + flush(fragmentByEnd, fragmentByStart); + flush(fragmentByStart, fragmentByEnd); + arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); + + return fragments; +}; + +var mesh = function(topology) { + return object(topology, meshArcs.apply(this, arguments)); +}; + +function meshArcs(topology, object$$1, filter) { + var arcs, i, n; + if (arguments.length > 1) arcs = extractArcs(topology, object$$1, filter); + else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i; + return {type: "MultiLineString", arcs: stitch(topology, arcs)}; +} + +function extractArcs(topology, object$$1, filter) { + var arcs = [], + geomsByArc = [], + geom; + + function extract0(i) { + var j = i < 0 ? ~i : i; + (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); + } + + function extract1(arcs) { + arcs.forEach(extract0); + } + + function extract2(arcs) { + arcs.forEach(extract1); + } + + function extract3(arcs) { + arcs.forEach(extract2); + } + + function geometry(o) { + switch (geom = o, o.type) { + case "GeometryCollection": o.geometries.forEach(geometry); break; + case "LineString": extract1(o.arcs); break; + case "MultiLineString": case "Polygon": extract2(o.arcs); break; + case "MultiPolygon": extract3(o.arcs); break; + } + } + + geometry(object$$1); + + geomsByArc.forEach(filter == null + ? function(geoms) { arcs.push(geoms[0].i); } + : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); + + return arcs; +} + +function planarRingArea(ring) { + var i = -1, n = ring.length, a, b = ring[n - 1], area = 0; + while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0]; + return Math.abs(area); // Note: doubled area! +} + +var merge = function(topology) { + return object(topology, mergeArcs.apply(this, arguments)); +}; + +function mergeArcs(topology, objects) { + var polygonsByArc = {}, + polygons = [], + groups = []; + + objects.forEach(geometry); + + function geometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(geometry); break; + case "Polygon": extract(o.arcs); break; + case "MultiPolygon": o.arcs.forEach(extract); break; + } + } + + function extract(polygon) { + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); + }); + }); + polygons.push(polygon); + } + + function area(ring) { + return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]); + } + + polygons.forEach(function(polygon) { + if (!polygon._) { + var group = [], + neighbors = [polygon]; + polygon._ = 1; + groups.push(group); + while (polygon = neighbors.pop()) { + group.push(polygon); + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { + if (!polygon._) { + polygon._ = 1; + neighbors.push(polygon); + } + }); + }); + }); + } + } + }); + + polygons.forEach(function(polygon) { + delete polygon._; + }); + + return { + type: "MultiPolygon", + arcs: groups.map(function(polygons) { + var arcs = [], n; + + // Extract the exterior (unique) arcs. + polygons.forEach(function(polygon) { + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { + arcs.push(arc); + } + }); + }); + }); + + // Stitch the arcs into one or more rings. + arcs = stitch(topology, arcs); + + // If more than one ring is returned, + // at most one of these rings can be the exterior; + // choose the one with the greatest absolute area. + if ((n = arcs.length) > 1) { + for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { + if ((ki = area(arcs[i])) > k) { + t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; + } + } + } + + return arcs; + }) + }; +} + +var bisect = function(a, x) { + var lo = 0, hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (a[mid] < x) lo = mid + 1; + else hi = mid; + } + return lo; +}; + +var neighbors = function(objects) { + var indexesByArc = {}, // arc index -> array of object indexes + neighbors = objects.map(function() { return []; }); + + function line(arcs, i) { + arcs.forEach(function(a) { + if (a < 0) a = ~a; + var o = indexesByArc[a]; + if (o) o.push(i); + else indexesByArc[a] = [i]; + }); + } + + function polygon(arcs, i) { + arcs.forEach(function(arc) { line(arc, i); }); + } + + function geometry(o, i) { + if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); + else if (o.type in geometryType) geometryType[o.type](o.arcs, i); + } + + var geometryType = { + LineString: line, + MultiLineString: polygon, + Polygon: polygon, + MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } + }; + + objects.forEach(geometry); + + for (var i in indexesByArc) { + for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { + for (var k = j + 1; k < m; ++k) { + var ij = indexes[j], ik = indexes[k], n; + if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); + if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); + } + } + } + + return neighbors; +}; + +var quantize = function(topology, n) { + if (!((n = Math.floor(n)) >= 2)) throw new Error("n must be ≥2"); + if (topology.transform) throw new Error("already quantized"); + var bb = bbox(topology), name, + dx = bb[0], kx = (bb[2] - dx) / (n - 1) || 1, + dy = bb[1], ky = (bb[3] - dy) / (n - 1) || 1; + + function quantizePoint(p) { + p[0] = Math.round((p[0] - dx) / kx); + p[1] = Math.round((p[1] - dy) / ky); + } + + function quantizeGeometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(quantizeGeometry); break; + case "Point": quantizePoint(o.coordinates); break; + case "MultiPoint": o.coordinates.forEach(quantizePoint); break; + } + } + + topology.arcs.forEach(function(arc) { + var i = 1, + j = 1, + n = arc.length, + pi = arc[0], + x0 = pi[0] = Math.round((pi[0] - dx) / kx), + y0 = pi[1] = Math.round((pi[1] - dy) / ky), + pj, + x1, + y1; + + for (; i < n; ++i) { + pi = arc[i]; + x1 = Math.round((pi[0] - dx) / kx); + y1 = Math.round((pi[1] - dy) / ky); + if (x1 !== x0 || y1 !== y0) { + pj = arc[j++]; + pj[0] = x1 - x0, x0 = x1; + pj[1] = y1 - y0, y0 = y1; + } + } + + if (j < 2) { + pj = arc[j++]; + pj[0] = 0; + pj[1] = 0; + } + + arc.length = j; + }); + + for (name in topology.objects) { + quantizeGeometry(topology.objects[name]); + } + + topology.transform = { + scale: [kx, ky], + translate: [dx, dy] + }; + + return topology; +}; + +var untransform = function(topology) { + if ((transform = topology.transform) == null) return identity; + var transform, + x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + var x1 = Math.round((point[0] - dx) / kx), + y1 = Math.round((point[1] - dy) / ky); + point[0] = x1 - x0, x0 = x1; + point[1] = y1 - y0, y0 = y1; + return point; + }; +}; + +exports.bbox = bbox; +exports.feature = feature; +exports.mesh = mesh; +exports.meshArcs = meshArcs; +exports.merge = merge; +exports.mergeArcs = mergeArcs; +exports.neighbors = neighbors; +exports.quantize = quantize; +exports.transform = transform; +exports.untransform = untransform; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],518:[function(_dereq_,module,exports){ +"use strict" + +module.exports = triangulateCube + +var perm = _dereq_("permutation-rank") +var sgn = _dereq_("permutation-parity") +var gamma = _dereq_("gamma") + +function triangulateCube(dimension) { + if(dimension < 0) { + return [ ] + } + if(dimension === 0) { + return [ [0] ] + } + var dfactorial = Math.round(gamma(dimension+1))|0 + var result = [] + for(var i=0; i Math.max(vy, vz)) { + u[2] = 1 + } else if(vy > Math.max(vx, vz)) { + u[0] = 1 + } else { + u[1] = 1 + } + + var vv = 0 + var uv = 0 + for(var i=0; i<3; ++i ) { + vv += v[i] * v[i] + uv += u[i] * v[i] + } + for(var i=0; i<3; ++i) { + u[i] -= (uv / vv) * v[i] + } + normalize3(u, u) + return u +} + +function TurntableController(zoomMin, zoomMax, center, up, right, radius, theta, phi) { + this.center = filterVector(center) + this.up = filterVector(up) + this.right = filterVector(right) + this.radius = filterVector([radius]) + this.angle = filterVector([theta, phi]) + this.angle.bounds = [[-Infinity,-Math.PI/2], [Infinity,Math.PI/2]] + this.setDistanceLimits(zoomMin, zoomMax) + + this.computedCenter = this.center.curve(0) + this.computedUp = this.up.curve(0) + this.computedRight = this.right.curve(0) + this.computedRadius = this.radius.curve(0) + this.computedAngle = this.angle.curve(0) + this.computedToward = [0,0,0] + this.computedEye = [0,0,0] + this.computedMatrix = new Array(16) + for(var i=0; i<16; ++i) { + this.computedMatrix[i] = 0.5 + } + + this.recalcMatrix(0) +} + +var proto = TurntableController.prototype + +proto.setDistanceLimits = function(minDist, maxDist) { + if(minDist > 0) { + minDist = Math.log(minDist) + } else { + minDist = -Infinity + } + if(maxDist > 0) { + maxDist = Math.log(maxDist) + } else { + maxDist = Infinity + } + maxDist = Math.max(maxDist, minDist) + this.radius.bounds[0][0] = minDist + this.radius.bounds[1][0] = maxDist +} + +proto.getDistanceLimits = function(out) { + var bounds = this.radius.bounds[0] + if(out) { + out[0] = Math.exp(bounds[0][0]) + out[1] = Math.exp(bounds[1][0]) + return out + } + return [ Math.exp(bounds[0][0]), Math.exp(bounds[1][0]) ] +} + +proto.recalcMatrix = function(t) { + //Recompute curves + this.center.curve(t) + this.up.curve(t) + this.right.curve(t) + this.radius.curve(t) + this.angle.curve(t) + + //Compute frame for camera matrix + var up = this.computedUp + var right = this.computedRight + var uu = 0.0 + var ur = 0.0 + for(var i=0; i<3; ++i) { + ur += up[i] * right[i] + uu += up[i] * up[i] + } + var ul = Math.sqrt(uu) + var rr = 0.0 + for(var i=0; i<3; ++i) { + right[i] -= up[i] * ur / uu + rr += right[i] * right[i] + up[i] /= ul + } + var rl = Math.sqrt(rr) + for(var i=0; i<3; ++i) { + right[i] /= rl + } + + //Compute toward vector + var toward = this.computedToward + cross(toward, up, right) + normalize3(toward, toward) + + //Compute angular parameters + var radius = Math.exp(this.computedRadius[0]) + var theta = this.computedAngle[0] + var phi = this.computedAngle[1] + + var ctheta = Math.cos(theta) + var stheta = Math.sin(theta) + var cphi = Math.cos(phi) + var sphi = Math.sin(phi) + + var center = this.computedCenter + + var wx = ctheta * cphi + var wy = stheta * cphi + var wz = sphi + + var sx = -ctheta * sphi + var sy = -stheta * sphi + var sz = cphi + + var eye = this.computedEye + var mat = this.computedMatrix + for(var i=0; i<3; ++i) { + var x = wx * right[i] + wy * toward[i] + wz * up[i] + mat[4*i+1] = sx * right[i] + sy * toward[i] + sz * up[i] + mat[4*i+2] = x + mat[4*i+3] = 0.0 + } + + var ax = mat[1] + var ay = mat[5] + var az = mat[9] + var bx = mat[2] + var by = mat[6] + var bz = mat[10] + var cx = ay * bz - az * by + var cy = az * bx - ax * bz + var cz = ax * by - ay * bx + var cl = len3(cx, cy, cz) + cx /= cl + cy /= cl + cz /= cl + mat[0] = cx + mat[4] = cy + mat[8] = cz + + for(var i=0; i<3; ++i) { + eye[i] = center[i] + mat[2+4*i]*radius + } + + for(var i=0; i<3; ++i) { + var rr = 0.0 + for(var j=0; j<3; ++j) { + rr += mat[i+4*j] * eye[j] + } + mat[12+i] = -rr + } + mat[15] = 1.0 +} + +proto.getMatrix = function(t, result) { + this.recalcMatrix(t) + var mat = this.computedMatrix + if(result) { + for(var i=0; i<16; ++i) { + result[i] = mat[i] + } + return result + } + return mat +} + +var zAxis = [0,0,0] +proto.rotate = function(t, dtheta, dphi, droll) { + this.angle.move(t, dtheta, dphi) + if(droll) { + this.recalcMatrix(t) + + var mat = this.computedMatrix + zAxis[0] = mat[2] + zAxis[1] = mat[6] + zAxis[2] = mat[10] + + var up = this.computedUp + var right = this.computedRight + var toward = this.computedToward + + for(var i=0; i<3; ++i) { + mat[4*i] = up[i] + mat[4*i+1] = right[i] + mat[4*i+2] = toward[i] + } + rotateM(mat, mat, droll, zAxis) + for(var i=0; i<3; ++i) { + up[i] = mat[4*i] + right[i] = mat[4*i+1] + } + + this.up.set(t, up[0], up[1], up[2]) + this.right.set(t, right[0], right[1], right[2]) + } +} + +proto.pan = function(t, dx, dy, dz) { + dx = dx || 0.0 + dy = dy || 0.0 + dz = dz || 0.0 + + this.recalcMatrix(t) + var mat = this.computedMatrix + + var dist = Math.exp(this.computedRadius[0]) + + var ux = mat[1] + var uy = mat[5] + var uz = mat[9] + var ul = len3(ux, uy, uz) + ux /= ul + uy /= ul + uz /= ul + + var rx = mat[0] + var ry = mat[4] + var rz = mat[8] + var ru = rx * ux + ry * uy + rz * uz + rx -= ux * ru + ry -= uy * ru + rz -= uz * ru + var rl = len3(rx, ry, rz) + rx /= rl + ry /= rl + rz /= rl + + var vx = rx * dx + ux * dy + var vy = ry * dx + uy * dy + var vz = rz * dx + uz * dy + this.center.move(t, vx, vy, vz) + + //Update z-component of radius + var radius = Math.exp(this.computedRadius[0]) + radius = Math.max(1e-4, radius + dz) + this.radius.set(t, Math.log(radius)) +} + +proto.translate = function(t, dx, dy, dz) { + this.center.move(t, + dx||0.0, + dy||0.0, + dz||0.0) +} + +//Recenters the coordinate axes +proto.setMatrix = function(t, mat, axes, noSnap) { + + //Get the axes for tare + var ushift = 1 + if(typeof axes === 'number') { + ushift = (axes)|0 + } + if(ushift < 0 || ushift > 3) { + ushift = 1 + } + var vshift = (ushift + 2) % 3 + var fshift = (ushift + 1) % 3 + + //Recompute state for new t value + if(!mat) { + this.recalcMatrix(t) + mat = this.computedMatrix + } + + //Get right and up vectors + var ux = mat[ushift] + var uy = mat[ushift+4] + var uz = mat[ushift+8] + if(!noSnap) { + var ul = len3(ux, uy, uz) + ux /= ul + uy /= ul + uz /= ul + } else { + var ax = Math.abs(ux) + var ay = Math.abs(uy) + var az = Math.abs(uz) + var am = Math.max(ax,ay,az) + if(ax === am) { + ux = (ux < 0) ? -1 : 1 + uy = uz = 0 + } else if(az === am) { + uz = (uz < 0) ? -1 : 1 + ux = uy = 0 + } else { + uy = (uy < 0) ? -1 : 1 + ux = uz = 0 + } + } + + var rx = mat[vshift] + var ry = mat[vshift+4] + var rz = mat[vshift+8] + var ru = rx * ux + ry * uy + rz * uz + rx -= ux * ru + ry -= uy * ru + rz -= uz * ru + var rl = len3(rx, ry, rz) + rx /= rl + ry /= rl + rz /= rl + + var fx = uy * rz - uz * ry + var fy = uz * rx - ux * rz + var fz = ux * ry - uy * rx + var fl = len3(fx, fy, fz) + fx /= fl + fy /= fl + fz /= fl + + this.center.jump(t, ex, ey, ez) + this.radius.idle(t) + this.up.jump(t, ux, uy, uz) + this.right.jump(t, rx, ry, rz) + + var phi, theta + if(ushift === 2) { + var cx = mat[1] + var cy = mat[5] + var cz = mat[9] + var cr = cx * rx + cy * ry + cz * rz + var cf = cx * fx + cy * fy + cz * fz + if(tu < 0) { + phi = -Math.PI/2 + } else { + phi = Math.PI/2 + } + theta = Math.atan2(cf, cr) + } else { + var tx = mat[2] + var ty = mat[6] + var tz = mat[10] + var tu = tx * ux + ty * uy + tz * uz + var tr = tx * rx + ty * ry + tz * rz + var tf = tx * fx + ty * fy + tz * fz + + phi = Math.asin(clamp1(tu)) + theta = Math.atan2(tf, tr) + } + + this.angle.jump(t, theta, phi) + + this.recalcMatrix(t) + var dx = mat[2] + var dy = mat[6] + var dz = mat[10] + + var imat = this.computedMatrix + invert44(imat, mat) + var w = imat[15] + var ex = imat[12] / w + var ey = imat[13] / w + var ez = imat[14] / w + + var gs = Math.exp(this.computedRadius[0]) + this.center.jump(t, ex-dx*gs, ey-dy*gs, ez-dz*gs) +} + +proto.lastT = function() { + return Math.max( + this.center.lastT(), + this.up.lastT(), + this.right.lastT(), + this.radius.lastT(), + this.angle.lastT()) +} + +proto.idle = function(t) { + this.center.idle(t) + this.up.idle(t) + this.right.idle(t) + this.radius.idle(t) + this.angle.idle(t) +} + +proto.flush = function(t) { + this.center.flush(t) + this.up.flush(t) + this.right.flush(t) + this.radius.flush(t) + this.angle.flush(t) +} + +proto.setDistance = function(t, d) { + if(d > 0) { + this.radius.set(t, Math.log(d)) + } +} + +proto.lookAt = function(t, eye, center, up) { + this.recalcMatrix(t) + + eye = eye || this.computedEye + center = center || this.computedCenter + up = up || this.computedUp + + var ux = up[0] + var uy = up[1] + var uz = up[2] + var ul = len3(ux, uy, uz) + if(ul < 1e-6) { + return + } + ux /= ul + uy /= ul + uz /= ul + + var tx = eye[0] - center[0] + var ty = eye[1] - center[1] + var tz = eye[2] - center[2] + var tl = len3(tx, ty, tz) + if(tl < 1e-6) { + return + } + tx /= tl + ty /= tl + tz /= tl + + var right = this.computedRight + var rx = right[0] + var ry = right[1] + var rz = right[2] + var ru = ux*rx + uy*ry + uz*rz + rx -= ru * ux + ry -= ru * uy + rz -= ru * uz + var rl = len3(rx, ry, rz) + + if(rl < 0.01) { + rx = uy * tz - uz * ty + ry = uz * tx - ux * tz + rz = ux * ty - uy * tx + rl = len3(rx, ry, rz) + if(rl < 1e-6) { + return + } + } + rx /= rl + ry /= rl + rz /= rl + + this.up.set(t, ux, uy, uz) + this.right.set(t, rx, ry, rz) + this.center.set(t, center[0], center[1], center[2]) + this.radius.set(t, Math.log(tl)) + + var fx = uy * rz - uz * ry + var fy = uz * rx - ux * rz + var fz = ux * ry - uy * rx + var fl = len3(fx, fy, fz) + fx /= fl + fy /= fl + fz /= fl + + var tu = ux*tx + uy*ty + uz*tz + var tr = rx*tx + ry*ty + rz*tz + var tf = fx*tx + fy*ty + fz*tz + + var phi = Math.asin(clamp1(tu)) + var theta = Math.atan2(tf, tr) + + var angleState = this.angle._state + var lastTheta = angleState[angleState.length-1] + var lastPhi = angleState[angleState.length-2] + lastTheta = lastTheta % (2.0 * Math.PI) + var dp = Math.abs(lastTheta + 2.0 * Math.PI - theta) + var d0 = Math.abs(lastTheta - theta) + var dn = Math.abs(lastTheta - 2.0 * Math.PI - theta) + if(dp < d0) { + lastTheta += 2.0 * Math.PI + } + if(dn < d0) { + lastTheta -= 2.0 * Math.PI + } + + this.angle.jump(this.angle.lastT(), lastTheta, lastPhi) + this.angle.set(t, theta, phi) +} + +function createTurntableController(options) { + options = options || {} + + var center = options.center || [0,0,0] + var up = options.up || [0,1,0] + var right = options.right || findOrthoPair(up) + var radius = options.radius || 1.0 + var theta = options.theta || 0.0 + var phi = options.phi || 0.0 + + center = [].slice.call(center, 0, 3) + + up = [].slice.call(up, 0, 3) + normalize3(up, up) + + right = [].slice.call(right, 0, 3) + normalize3(right, right) + + if('eye' in options) { + var eye = options.eye + var toward = [ + eye[0]-center[0], + eye[1]-center[1], + eye[2]-center[2] + ] + cross(right, toward, up) + if(len3(right[0], right[1], right[2]) < 1e-6) { + right = findOrthoPair(up) + } else { + normalize3(right, right) + } + + radius = len3(toward[0], toward[1], toward[2]) + + var ut = dot3(up, toward) / radius + var rt = dot3(right, toward) / radius + phi = Math.acos(ut) + theta = Math.acos(rt) + } + + //Use logarithmic coordinates for radius + radius = Math.log(radius) + + //Return the controller + return new TurntableController( + options.zoomMin, + options.zoomMax, + center, + up, + right, + radius, + theta, + phi) +} +},{"filtered-vector":215,"gl-mat4/invert":254,"gl-mat4/rotate":258,"gl-vec3/cross":317,"gl-vec3/dot":322,"gl-vec3/normalize":339}],520:[function(_dereq_,module,exports){ +"use strict" + +module.exports = twoProduct + +var SPLITTER = +(Math.pow(2, 27) + 1.0) + +function twoProduct(a, b, result) { + var x = a * b + + var c = SPLITTER * a + var abig = c - a + var ahi = c - abig + var alo = a - ahi + + var d = SPLITTER * b + var bbig = d - b + var bhi = d - bbig + var blo = b - bhi + + var err1 = x - (ahi * bhi) + var err2 = err1 - (alo * bhi) + var err3 = err2 - (ahi * blo) + + var y = alo * blo - err3 + + if(result) { + result[0] = y + result[1] = x + return result + } + + return [ y, x ] +} +},{}],521:[function(_dereq_,module,exports){ +"use strict" + +module.exports = fastTwoSum + +function fastTwoSum(a, b, result) { + var x = a + b + var bv = x - a + var av = x - bv + var br = b - bv + var ar = a - av + if(result) { + result[0] = ar + br + result[1] = x + return result + } + return [ar+br, x] +} +},{}],522:[function(_dereq_,module,exports){ +(function (global,Buffer){ +'use strict' + +var bits = _dereq_('bit-twiddle') +var dup = _dereq_('dup') + +//Legacy pool support +if(!global.__TYPEDARRAY_POOL) { + global.__TYPEDARRAY_POOL = { + UINT8 : dup([32, 0]) + , UINT16 : dup([32, 0]) + , UINT32 : dup([32, 0]) + , INT8 : dup([32, 0]) + , INT16 : dup([32, 0]) + , INT32 : dup([32, 0]) + , FLOAT : dup([32, 0]) + , DOUBLE : dup([32, 0]) + , DATA : dup([32, 0]) + , UINT8C : dup([32, 0]) + , BUFFER : dup([32, 0]) + } +} + +var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined' +var POOL = global.__TYPEDARRAY_POOL + +//Upgrade pool +if(!POOL.UINT8C) { + POOL.UINT8C = dup([32, 0]) +} +if(!POOL.BUFFER) { + POOL.BUFFER = dup([32, 0]) +} + +//New technique: Only allocate from ArrayBufferView and Buffer +var DATA = POOL.DATA + , BUFFER = POOL.BUFFER + +exports.free = function free(array) { + if(Buffer.isBuffer(array)) { + BUFFER[bits.log2(array.length)].push(array) + } else { + if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') { + array = array.buffer + } + if(!array) { + return + } + var n = array.length || array.byteLength + var log_n = bits.log2(n)|0 + DATA[log_n].push(array) + } +} + +function freeArrayBuffer(buffer) { + if(!buffer) { + return + } + var n = buffer.length || buffer.byteLength + var log_n = bits.log2(n) + DATA[log_n].push(buffer) +} + +function freeTypedArray(array) { + freeArrayBuffer(array.buffer) +} + +exports.freeUint8 = +exports.freeUint16 = +exports.freeUint32 = +exports.freeInt8 = +exports.freeInt16 = +exports.freeInt32 = +exports.freeFloat32 = +exports.freeFloat = +exports.freeFloat64 = +exports.freeDouble = +exports.freeUint8Clamped = +exports.freeDataView = freeTypedArray + +exports.freeArrayBuffer = freeArrayBuffer + +exports.freeBuffer = function freeBuffer(array) { + BUFFER[bits.log2(array.length)].push(array) +} + +exports.malloc = function malloc(n, dtype) { + if(dtype === undefined || dtype === 'arraybuffer') { + return mallocArrayBuffer(n) + } else { + switch(dtype) { + case 'uint8': + return mallocUint8(n) + case 'uint16': + return mallocUint16(n) + case 'uint32': + return mallocUint32(n) + case 'int8': + return mallocInt8(n) + case 'int16': + return mallocInt16(n) + case 'int32': + return mallocInt32(n) + case 'float': + case 'float32': + return mallocFloat(n) + case 'double': + case 'float64': + return mallocDouble(n) + case 'uint8_clamped': + return mallocUint8Clamped(n) + case 'buffer': + return mallocBuffer(n) + case 'data': + case 'dataview': + return mallocDataView(n) + + default: + return null + } + } + return null +} + +function mallocArrayBuffer(n) { + var n = bits.nextPow2(n) + var log_n = bits.log2(n) + var d = DATA[log_n] + if(d.length > 0) { + return d.pop() + } + return new ArrayBuffer(n) +} +exports.mallocArrayBuffer = mallocArrayBuffer + +function mallocUint8(n) { + return new Uint8Array(mallocArrayBuffer(n), 0, n) +} +exports.mallocUint8 = mallocUint8 + +function mallocUint16(n) { + return new Uint16Array(mallocArrayBuffer(2*n), 0, n) +} +exports.mallocUint16 = mallocUint16 + +function mallocUint32(n) { + return new Uint32Array(mallocArrayBuffer(4*n), 0, n) +} +exports.mallocUint32 = mallocUint32 + +function mallocInt8(n) { + return new Int8Array(mallocArrayBuffer(n), 0, n) +} +exports.mallocInt8 = mallocInt8 + +function mallocInt16(n) { + return new Int16Array(mallocArrayBuffer(2*n), 0, n) +} +exports.mallocInt16 = mallocInt16 + +function mallocInt32(n) { + return new Int32Array(mallocArrayBuffer(4*n), 0, n) +} +exports.mallocInt32 = mallocInt32 + +function mallocFloat(n) { + return new Float32Array(mallocArrayBuffer(4*n), 0, n) +} +exports.mallocFloat32 = exports.mallocFloat = mallocFloat + +function mallocDouble(n) { + return new Float64Array(mallocArrayBuffer(8*n), 0, n) +} +exports.mallocFloat64 = exports.mallocDouble = mallocDouble + +function mallocUint8Clamped(n) { + if(hasUint8C) { + return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n) + } else { + return mallocUint8(n) + } +} +exports.mallocUint8Clamped = mallocUint8Clamped + +function mallocDataView(n) { + return new DataView(mallocArrayBuffer(n), 0, n) +} +exports.mallocDataView = mallocDataView + +function mallocBuffer(n) { + n = bits.nextPow2(n) + var log_n = bits.log2(n) + var cache = BUFFER[log_n] + if(cache.length > 0) { + return cache.pop() + } + return new Buffer(n) +} +exports.mallocBuffer = mallocBuffer + +exports.clearCache = function clearCache() { + for(var i=0; i<32; ++i) { + POOL.UINT8[i].length = 0 + POOL.UINT16[i].length = 0 + POOL.UINT32[i].length = 0 + POOL.INT8[i].length = 0 + POOL.INT16[i].length = 0 + POOL.INT32[i].length = 0 + POOL.FLOAT[i].length = 0 + POOL.DOUBLE[i].length = 0 + POOL.UINT8C[i].length = 0 + DATA[i].length = 0 + BUFFER[i].length = 0 + } +} +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},_dereq_("buffer").Buffer) + +},{"bit-twiddle":80,"buffer":93,"dup":155}],523:[function(_dereq_,module,exports){ +"use strict"; "use restrict"; + +module.exports = UnionFind; + +function UnionFind(count) { + this.roots = new Array(count); + this.ranks = new Array(count); + + for(var i=0; i 8192) { + throw new Error("vectorize-text: String too long (sorry, this will get fixed later)") + } + var height = 3 * size + if(canvas.height < height) { + canvas.height = height + } + + context.fillStyle = "#000" + context.fillRect(0, 0, canvas.width, canvas.height) + + context.fillStyle = "#fff" + context.fillText(str, size, 2*size) + + //Cut pixels from image + var pixelData = context.getImageData(0, 0, width, height) + var pixels = ndarray(pixelData.data, [height, width, 4]) + + return pixels.pick(-1,-1,0).transpose(1,0) +} + +function getContour(pixels, doSimplify) { + var contour = surfaceNets(pixels, 128) + if(doSimplify) { + return simplify(contour.cells, contour.positions, 0.25) + } + return { + edges: contour.cells, + positions: contour.positions + } +} + +function processPixelsImpl(pixels, options, size, simplify) { + //Extract contour + var contour = getContour(pixels, simplify) + + //Apply warp to positions + var positions = transformPositions(contour.positions, options, size) + var edges = contour.edges + var flip = "ccw" === options.orientation + + //Clean up the PSLG, resolve self intersections, etc. + cleanPSLG(positions, edges) + + //If triangulate flag passed, triangulate the result + if(options.polygons || options.polygon || options.polyline) { + var result = toPolygonCrappy(edges, positions) + var nresult = new Array(result.length) + for(var i=0; iAssumes that an ES5 platform where, if {@code WeakMap} is + * already present, then it conforms to the anticipated ES6 + * specification. To run this file on an ES5 or almost ES5 + * implementation where the {@code WeakMap} specification does not + * quite conform, run repairES5.js first. + * + *

Even though WeakMapModule is not global, the linter thinks it + * is, which is why it is in the overrides list below. + * + *

NOTE: Before using this WeakMap emulation in a non-SES + * environment, see the note below about hiddenRecord. + * + * @author Mark S. Miller + * @requires crypto, ArrayBuffer, Uint8Array, navigator, console + * @overrides WeakMap, ses, Proxy + * @overrides WeakMapModule + */ + +/** + * This {@code WeakMap} emulation is observably equivalent to the + * ES-Harmony WeakMap, but with leakier garbage collection properties. + * + *

As with true WeakMaps, in this emulation, a key does not + * retain maps indexed by that key and (crucially) a map does not + * retain the keys it indexes. A map by itself also does not retain + * the values associated with that map. + * + *

However, the values associated with a key in some map are + * retained so long as that key is retained and those associations are + * not overridden. For example, when used to support membranes, all + * values exported from a given membrane will live for the lifetime + * they would have had in the absence of an interposed membrane. Even + * when the membrane is revoked, all objects that would have been + * reachable in the absence of revocation will still be reachable, as + * far as the GC can tell, even though they will no longer be relevant + * to ongoing computation. + * + *

The API implemented here is approximately the API as implemented + * in FF6.0a1 and agreed to by MarkM, Andreas Gal, and Dave Herman, + * rather than the offially approved proposal page. TODO(erights): + * upgrade the ecmascript WeakMap proposal page to explain this API + * change and present to EcmaScript committee for their approval. + * + *

The first difference between the emulation here and that in + * FF6.0a1 is the presence of non enumerable {@code get___, has___, + * set___, and delete___} methods on WeakMap instances to represent + * what would be the hidden internal properties of a primitive + * implementation. Whereas the FF6.0a1 WeakMap.prototype methods + * require their {@code this} to be a genuine WeakMap instance (i.e., + * an object of {@code [[Class]]} "WeakMap}), since there is nothing + * unforgeable about the pseudo-internal method names used here, + * nothing prevents these emulated prototype methods from being + * applied to non-WeakMaps with pseudo-internal methods of the same + * names. + * + *

Another difference is that our emulated {@code + * WeakMap.prototype} is not itself a WeakMap. A problem with the + * current FF6.0a1 API is that WeakMap.prototype is itself a WeakMap + * providing ambient mutability and an ambient communications + * channel. Thus, if a WeakMap is already present and has this + * problem, repairES5.js wraps it in a safe wrappper in order to + * prevent access to this channel. (See + * PATCH_MUTABLE_FROZEN_WEAKMAP_PROTO in repairES5.js). + */ + +/** + * If this is a full secureable ES5 platform and the ES-Harmony {@code WeakMap} is + * absent, install an approximate emulation. + * + *

If WeakMap is present but cannot store some objects, use our approximate + * emulation as a wrapper. + * + *

If this is almost a secureable ES5 platform, then WeakMap.js + * should be run after repairES5.js. + * + *

See {@code WeakMap} for documentation of the garbage collection + * properties of this WeakMap emulation. + */ +(function WeakMapModule() { + "use strict"; + + if (typeof ses !== 'undefined' && ses.ok && !ses.ok()) { + // already too broken, so give up + return; + } + + /** + * In some cases (current Firefox), we must make a choice betweeen a + * WeakMap which is capable of using all varieties of host objects as + * keys and one which is capable of safely using proxies as keys. See + * comments below about HostWeakMap and DoubleWeakMap for details. + * + * This function (which is a global, not exposed to guests) marks a + * WeakMap as permitted to do what is necessary to index all host + * objects, at the cost of making it unsafe for proxies. + * + * Do not apply this function to anything which is not a genuine + * fresh WeakMap. + */ + function weakMapPermitHostObjects(map) { + // identity of function used as a secret -- good enough and cheap + if (map.permitHostObjects___) { + map.permitHostObjects___(weakMapPermitHostObjects); + } + } + if (typeof ses !== 'undefined') { + ses.weakMapPermitHostObjects = weakMapPermitHostObjects; + } + + // IE 11 has no Proxy but has a broken WeakMap such that we need to patch + // it using DoubleWeakMap; this flag tells DoubleWeakMap so. + var doubleWeakMapCheckSilentFailure = false; + + // Check if there is already a good-enough WeakMap implementation, and if so + // exit without replacing it. + if (typeof WeakMap === 'function') { + var HostWeakMap = WeakMap; + // There is a WeakMap -- is it good enough? + if (typeof navigator !== 'undefined' && + /Firefox/.test(navigator.userAgent)) { + // We're now *assuming not*, because as of this writing (2013-05-06) + // Firefox's WeakMaps have a miscellany of objects they won't accept, and + // we don't want to make an exhaustive list, and testing for just one + // will be a problem if that one is fixed alone (as they did for Event). + + // If there is a platform that we *can* reliably test on, here's how to + // do it: + // var problematic = ... ; + // var testHostMap = new HostWeakMap(); + // try { + // testHostMap.set(problematic, 1); // Firefox 20 will throw here + // if (testHostMap.get(problematic) === 1) { + // return; + // } + // } catch (e) {} + + } else { + // IE 11 bug: WeakMaps silently fail to store frozen objects. + var testMap = new HostWeakMap(); + var testObject = Object.freeze({}); + testMap.set(testObject, 1); + if (testMap.get(testObject) !== 1) { + doubleWeakMapCheckSilentFailure = true; + // Fall through to installing our WeakMap. + } else { + module.exports = WeakMap; + return; + } + } + } + + var hop = Object.prototype.hasOwnProperty; + var gopn = Object.getOwnPropertyNames; + var defProp = Object.defineProperty; + var isExtensible = Object.isExtensible; + + /** + * Security depends on HIDDEN_NAME being both unguessable and + * undiscoverable by untrusted code. + * + *

Given the known weaknesses of Math.random() on existing + * browsers, it does not generate unguessability we can be confident + * of. + * + *

It is the monkey patching logic in this file that is intended + * to ensure undiscoverability. The basic idea is that there are + * three fundamental means of discovering properties of an object: + * The for/in loop, Object.keys(), and Object.getOwnPropertyNames(), + * as well as some proposed ES6 extensions that appear on our + * whitelist. The first two only discover enumerable properties, and + * we only use HIDDEN_NAME to name a non-enumerable property, so the + * only remaining threat should be getOwnPropertyNames and some + * proposed ES6 extensions that appear on our whitelist. We monkey + * patch them to remove HIDDEN_NAME from the list of properties they + * returns. + * + *

TODO(erights): On a platform with built-in Proxies, proxies + * could be used to trap and thereby discover the HIDDEN_NAME, so we + * need to monkey patch Proxy.create, Proxy.createFunction, etc, in + * order to wrap the provided handler with the real handler which + * filters out all traps using HIDDEN_NAME. + * + *

TODO(erights): Revisit Mike Stay's suggestion that we use an + * encapsulated function at a not-necessarily-secret name, which + * uses the Stiegler shared-state rights amplification pattern to + * reveal the associated value only to the WeakMap in which this key + * is associated with that value. Since only the key retains the + * function, the function can also remember the key without causing + * leakage of the key, so this doesn't violate our general gc + * goals. In addition, because the name need not be a guarded + * secret, we could efficiently handle cross-frame frozen keys. + */ + var HIDDEN_NAME_PREFIX = 'weakmap:'; + var HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'ident:' + Math.random() + '___'; + + if (typeof crypto !== 'undefined' && + typeof crypto.getRandomValues === 'function' && + typeof ArrayBuffer === 'function' && + typeof Uint8Array === 'function') { + var ab = new ArrayBuffer(25); + var u8s = new Uint8Array(ab); + crypto.getRandomValues(u8s); + HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'rand:' + + Array.prototype.map.call(u8s, function(u8) { + return (u8 % 36).toString(36); + }).join('') + '___'; + } + + function isNotHiddenName(name) { + return !( + name.substr(0, HIDDEN_NAME_PREFIX.length) == HIDDEN_NAME_PREFIX && + name.substr(name.length - 3) === '___'); + } + + /** + * Monkey patch getOwnPropertyNames to avoid revealing the + * HIDDEN_NAME. + * + *

The ES5.1 spec requires each name to appear only once, but as + * of this writing, this requirement is controversial for ES6, so we + * made this code robust against this case. If the resulting extra + * search turns out to be expensive, we can probably relax this once + * ES6 is adequately supported on all major browsers, iff no browser + * versions we support at that time have relaxed this constraint + * without providing built-in ES6 WeakMaps. + */ + defProp(Object, 'getOwnPropertyNames', { + value: function fakeGetOwnPropertyNames(obj) { + return gopn(obj).filter(isNotHiddenName); + } + }); + + /** + * getPropertyNames is not in ES5 but it is proposed for ES6 and + * does appear in our whitelist, so we need to clean it too. + */ + if ('getPropertyNames' in Object) { + var originalGetPropertyNames = Object.getPropertyNames; + defProp(Object, 'getPropertyNames', { + value: function fakeGetPropertyNames(obj) { + return originalGetPropertyNames(obj).filter(isNotHiddenName); + } + }); + } + + /** + *

To treat objects as identity-keys with reasonable efficiency + * on ES5 by itself (i.e., without any object-keyed collections), we + * need to add a hidden property to such key objects when we + * can. This raises several issues: + *

    + *
  • Arranging to add this property to objects before we lose the + * chance, and + *
  • Hiding the existence of this new property from most + * JavaScript code. + *
  • Preventing certification theft, where one object is + * created falsely claiming to be the key of an association + * actually keyed by another object. + *
  • Preventing value theft, where untrusted code with + * access to a key object but not a weak map nevertheless + * obtains access to the value associated with that key in that + * weak map. + *
+ * We do so by + *
    + *
  • Making the name of the hidden property unguessable, so "[]" + * indexing, which we cannot intercept, cannot be used to access + * a property without knowing the name. + *
  • Making the hidden property non-enumerable, so we need not + * worry about for-in loops or {@code Object.keys}, + *
  • monkey patching those reflective methods that would + * prevent extensions, to add this hidden property first, + *
  • monkey patching those methods that would reveal this + * hidden property. + *
+ * Unfortunately, because of same-origin iframes, we cannot reliably + * add this hidden property before an object becomes + * non-extensible. Instead, if we encounter a non-extensible object + * without a hidden record that we can detect (whether or not it has + * a hidden record stored under a name secret to us), then we just + * use the key object itself to represent its identity in a brute + * force leaky map stored in the weak map, losing all the advantages + * of weakness for these. + */ + function getHiddenRecord(key) { + if (key !== Object(key)) { + throw new TypeError('Not an object: ' + key); + } + var hiddenRecord = key[HIDDEN_NAME]; + if (hiddenRecord && hiddenRecord.key === key) { return hiddenRecord; } + if (!isExtensible(key)) { + // Weak map must brute force, as explained in doc-comment above. + return void 0; + } + + // The hiddenRecord and the key point directly at each other, via + // the "key" and HIDDEN_NAME properties respectively. The key + // field is for quickly verifying that this hidden record is an + // own property, not a hidden record from up the prototype chain. + // + // NOTE: Because this WeakMap emulation is meant only for systems like + // SES where Object.prototype is frozen without any numeric + // properties, it is ok to use an object literal for the hiddenRecord. + // This has two advantages: + // * It is much faster in a performance critical place + // * It avoids relying on Object.create(null), which had been + // problematic on Chrome 28.0.1480.0. See + // https://code.google.com/p/google-caja/issues/detail?id=1687 + hiddenRecord = { key: key }; + + // When using this WeakMap emulation on platforms where + // Object.prototype might not be frozen and Object.create(null) is + // reliable, use the following two commented out lines instead. + // hiddenRecord = Object.create(null); + // hiddenRecord.key = key; + + // Please contact us if you need this to work on platforms where + // Object.prototype might not be frozen and + // Object.create(null) might not be reliable. + + try { + defProp(key, HIDDEN_NAME, { + value: hiddenRecord, + writable: false, + enumerable: false, + configurable: false + }); + return hiddenRecord; + } catch (error) { + // Under some circumstances, isExtensible seems to misreport whether + // the HIDDEN_NAME can be defined. + // The circumstances have not been isolated, but at least affect + // Node.js v0.10.26 on TravisCI / Linux, but not the same version of + // Node.js on OS X. + return void 0; + } + } + + /** + * Monkey patch operations that would make their argument + * non-extensible. + * + *

The monkey patched versions throw a TypeError if their + * argument is not an object, so it should only be done to functions + * that should throw a TypeError anyway if their argument is not an + * object. + */ + (function(){ + var oldFreeze = Object.freeze; + defProp(Object, 'freeze', { + value: function identifyingFreeze(obj) { + getHiddenRecord(obj); + return oldFreeze(obj); + } + }); + var oldSeal = Object.seal; + defProp(Object, 'seal', { + value: function identifyingSeal(obj) { + getHiddenRecord(obj); + return oldSeal(obj); + } + }); + var oldPreventExtensions = Object.preventExtensions; + defProp(Object, 'preventExtensions', { + value: function identifyingPreventExtensions(obj) { + getHiddenRecord(obj); + return oldPreventExtensions(obj); + } + }); + })(); + + function constFunc(func) { + func.prototype = null; + return Object.freeze(func); + } + + var calledAsFunctionWarningDone = false; + function calledAsFunctionWarning() { + // Future ES6 WeakMap is currently (2013-09-10) expected to reject WeakMap() + // but we used to permit it and do it ourselves, so warn only. + if (!calledAsFunctionWarningDone && typeof console !== 'undefined') { + calledAsFunctionWarningDone = true; + console.warn('WeakMap should be invoked as new WeakMap(), not ' + + 'WeakMap(). This will be an error in the future.'); + } + } + + var nextId = 0; + + var OurWeakMap = function() { + if (!(this instanceof OurWeakMap)) { // approximate test for new ...() + calledAsFunctionWarning(); + } + + // We are currently (12/25/2012) never encountering any prematurely + // non-extensible keys. + var keys = []; // brute force for prematurely non-extensible keys. + var values = []; // brute force for corresponding values. + var id = nextId++; + + function get___(key, opt_default) { + var index; + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + return id in hiddenRecord ? hiddenRecord[id] : opt_default; + } else { + index = keys.indexOf(key); + return index >= 0 ? values[index] : opt_default; + } + } + + function has___(key) { + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + return id in hiddenRecord; + } else { + return keys.indexOf(key) >= 0; + } + } + + function set___(key, value) { + var index; + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + hiddenRecord[id] = value; + } else { + index = keys.indexOf(key); + if (index >= 0) { + values[index] = value; + } else { + // Since some browsers preemptively terminate slow turns but + // then continue computing with presumably corrupted heap + // state, we here defensively get keys.length first and then + // use it to update both the values and keys arrays, keeping + // them in sync. + index = keys.length; + values[index] = value; + // If we crash here, values will be one longer than keys. + keys[index] = key; + } + } + return this; + } + + function delete___(key) { + var hiddenRecord = getHiddenRecord(key); + var index, lastIndex; + if (hiddenRecord) { + return id in hiddenRecord && delete hiddenRecord[id]; + } else { + index = keys.indexOf(key); + if (index < 0) { + return false; + } + // Since some browsers preemptively terminate slow turns but + // then continue computing with potentially corrupted heap + // state, we here defensively get keys.length first and then use + // it to update both the keys and the values array, keeping + // them in sync. We update the two with an order of assignments, + // such that any prefix of these assignments will preserve the + // key/value correspondence, either before or after the delete. + // Note that this needs to work correctly when index === lastIndex. + lastIndex = keys.length - 1; + keys[index] = void 0; + // If we crash here, there's a void 0 in the keys array, but + // no operation will cause a "keys.indexOf(void 0)", since + // getHiddenRecord(void 0) will always throw an error first. + values[index] = values[lastIndex]; + // If we crash here, values[index] cannot be found here, + // because keys[index] is void 0. + keys[index] = keys[lastIndex]; + // If index === lastIndex and we crash here, then keys[index] + // is still void 0, since the aliasing killed the previous key. + keys.length = lastIndex; + // If we crash here, keys will be one shorter than values. + values.length = lastIndex; + return true; + } + } + + return Object.create(OurWeakMap.prototype, { + get___: { value: constFunc(get___) }, + has___: { value: constFunc(has___) }, + set___: { value: constFunc(set___) }, + delete___: { value: constFunc(delete___) } + }); + }; + + OurWeakMap.prototype = Object.create(Object.prototype, { + get: { + /** + * Return the value most recently associated with key, or + * opt_default if none. + */ + value: function get(key, opt_default) { + return this.get___(key, opt_default); + }, + writable: true, + configurable: true + }, + + has: { + /** + * Is there a value associated with key in this WeakMap? + */ + value: function has(key) { + return this.has___(key); + }, + writable: true, + configurable: true + }, + + set: { + /** + * Associate value with key in this WeakMap, overwriting any + * previous association if present. + */ + value: function set(key, value) { + return this.set___(key, value); + }, + writable: true, + configurable: true + }, + + 'delete': { + /** + * Remove any association for key in this WeakMap, returning + * whether there was one. + * + *

Note that the boolean return here does not work like the + * {@code delete} operator. The {@code delete} operator returns + * whether the deletion succeeds at bringing about a state in + * which the deleted property is absent. The {@code delete} + * operator therefore returns true if the property was already + * absent, whereas this {@code delete} method returns false if + * the association was already absent. + */ + value: function remove(key) { + return this.delete___(key); + }, + writable: true, + configurable: true + } + }); + + if (typeof HostWeakMap === 'function') { + (function() { + // If we got here, then the platform has a WeakMap but we are concerned + // that it may refuse to store some key types. Therefore, make a map + // implementation which makes use of both as possible. + + // In this mode we are always using double maps, so we are not proxy-safe. + // This combination does not occur in any known browser, but we had best + // be safe. + if (doubleWeakMapCheckSilentFailure && typeof Proxy !== 'undefined') { + Proxy = undefined; + } + + function DoubleWeakMap() { + if (!(this instanceof OurWeakMap)) { // approximate test for new ...() + calledAsFunctionWarning(); + } + + // Preferable, truly weak map. + var hmap = new HostWeakMap(); + + // Our hidden-property-based pseudo-weak-map. Lazily initialized in the + // 'set' implementation; thus we can avoid performing extra lookups if + // we know all entries actually stored are entered in 'hmap'. + var omap = undefined; + + // Hidden-property maps are not compatible with proxies because proxies + // can observe the hidden name and either accidentally expose it or fail + // to allow the hidden property to be set. Therefore, we do not allow + // arbitrary WeakMaps to switch to using hidden properties, but only + // those which need the ability, and unprivileged code is not allowed + // to set the flag. + // + // (Except in doubleWeakMapCheckSilentFailure mode in which case we + // disable proxies.) + var enableSwitching = false; + + function dget(key, opt_default) { + if (omap) { + return hmap.has(key) ? hmap.get(key) + : omap.get___(key, opt_default); + } else { + return hmap.get(key, opt_default); + } + } + + function dhas(key) { + return hmap.has(key) || (omap ? omap.has___(key) : false); + } + + var dset; + if (doubleWeakMapCheckSilentFailure) { + dset = function(key, value) { + hmap.set(key, value); + if (!hmap.has(key)) { + if (!omap) { omap = new OurWeakMap(); } + omap.set(key, value); + } + return this; + }; + } else { + dset = function(key, value) { + if (enableSwitching) { + try { + hmap.set(key, value); + } catch (e) { + if (!omap) { omap = new OurWeakMap(); } + omap.set___(key, value); + } + } else { + hmap.set(key, value); + } + return this; + }; + } + + function ddelete(key) { + var result = !!hmap['delete'](key); + if (omap) { return omap.delete___(key) || result; } + return result; + } + + return Object.create(OurWeakMap.prototype, { + get___: { value: constFunc(dget) }, + has___: { value: constFunc(dhas) }, + set___: { value: constFunc(dset) }, + delete___: { value: constFunc(ddelete) }, + permitHostObjects___: { value: constFunc(function(token) { + if (token === weakMapPermitHostObjects) { + enableSwitching = true; + } else { + throw new Error('bogus call to permitHostObjects___'); + } + })} + }); + } + DoubleWeakMap.prototype = OurWeakMap.prototype; + module.exports = DoubleWeakMap; + + // define .constructor to hide OurWeakMap ctor + Object.defineProperty(WeakMap.prototype, 'constructor', { + value: WeakMap, + enumerable: false, // as default .constructor is + configurable: true, + writable: true + }); + })(); + } else { + // There is no host WeakMap, so we must use the emulation. + + // Emulated WeakMaps are incompatible with native proxies (because proxies + // can observe the hidden name), so we must disable Proxy usage (in + // ArrayLike and Domado, currently). + if (typeof Proxy !== 'undefined') { + Proxy = undefined; + } + + module.exports = OurWeakMap; + } +})(); + +},{}],530:[function(_dereq_,module,exports){ +var hiddenStore = _dereq_('./hidden-store.js'); + +module.exports = createStore; + +function createStore() { + var key = {}; + + return function (obj) { + if ((typeof obj !== 'object' || obj === null) && + typeof obj !== 'function' + ) { + throw new Error('Weakmap-shim: Key must be object') + } + + var store = obj.valueOf(key); + return store && store.identity === key ? + store : hiddenStore(obj, key); + }; +} + +},{"./hidden-store.js":531}],531:[function(_dereq_,module,exports){ +module.exports = hiddenStore; + +function hiddenStore(obj, key) { + var store = { identity: key }; + var valueOf = obj.valueOf; + + Object.defineProperty(obj, "valueOf", { + value: function (value) { + return value !== key ? + valueOf.apply(this, arguments) : store; + }, + writable: true + }); + + return store; +} + +},{}],532:[function(_dereq_,module,exports){ +// Original - @Gozola. +// https://gist.github.com/Gozala/1269991 +// This is a reimplemented version (with a few bug fixes). + +var createStore = _dereq_('./create-store.js'); + +module.exports = weakMap; + +function weakMap() { + var privates = createStore(); + + return { + 'get': function (key, fallback) { + var store = privates(key) + return store.hasOwnProperty('value') ? + store.value : fallback + }, + 'set': function (key, value) { + privates(key).value = value; + return this; + }, + 'has': function(key) { + return 'value' in privates(key); + }, + 'delete': function (key) { + return delete privates(key).value; + } + } +} + +},{"./create-store.js":530}],533:[function(_dereq_,module,exports){ +var getContext = _dereq_('get-canvas-context') + +module.exports = function getWebGLContext (opt) { + return getContext('webgl', opt) +} + +},{"get-canvas-context":221}],534:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Traditional Chinese calendar for jQuery v2.0.2. + Written by Nicolas Riesco (enquiries@nicolasriesco.net) December 2016. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +var gregorianCalendar = main.instance(); + +/** Implementation of the traditional Chinese calendar. + Source of calendar tables https://github.com/isee15/Lunar-Solar-Calendar-Converter . + @class ChineseCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function ChineseCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +ChineseCalendar.prototype = new main.baseCalendar; + +assign(ChineseCalendar.prototype, { + /** The calendar name. + @memberof ChineseCalendar */ + name: 'Chinese', + /** Julian date of start of Gregorian epoch: 1 January 0001 CE. + @memberof GregorianCalendar */ + jdEpoch: 1721425.5, + /** true if has a year zero, false if not. + @memberof ChineseCalendar */ + hasYearZero: false, + /** The minimum month number. + This calendar uses month indices to account for intercalary months. + @memberof ChineseCalendar */ + minMonth: 0, + /** The first month in the year. + This calendar uses month indices to account for intercalary months. + @memberof ChineseCalendar */ + firstMonth: 0, + /** The minimum day number. + @memberof ChineseCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof ChineseCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Chinese', + epochs: ['BEC', 'EC'], + monthNumbers: function(date, padded) { + if (typeof date === 'string') { + var match = date.match(MONTH_NUMBER_REGEXP); + return (match) ? match[0] : ''; + } + + var year = this._validateYear(date); + var monthIndex = date.month(); + + var month = '' + this.toChineseMonth(year, monthIndex); + + if (padded && month.length < 2) { + month = "0" + month; + } + + if (this.isIntercalaryMonth(year, monthIndex)) { + month += 'i'; + } + + return month; + }, + monthNames: function(date) { + if (typeof date === 'string') { + var match = date.match(MONTH_NAME_REGEXP); + return (match) ? match[0] : ''; + } + + var year = this._validateYear(date); + var monthIndex = date.month(); + + var month = this.toChineseMonth(year, monthIndex); + + var monthName = ['一月','二月','三月','四月','五月','六月', + '七月','八月','九月','十月','十一月','十二月'][month - 1]; + + if (this.isIntercalaryMonth(year, monthIndex)) { + monthName = '闰' + monthName; + } + + return monthName; + }, + monthNamesShort: function(date) { + if (typeof date === 'string') { + var match = date.match(MONTH_SHORT_NAME_REGEXP); + return (match) ? match[0] : ''; + } + + var year = this._validateYear(date); + var monthIndex = date.month(); + + var month = this.toChineseMonth(year, monthIndex); + + var monthName = ['一','二','三','四','五','六', + '七','八','九','十','十一','十二'][month - 1]; + + if (this.isIntercalaryMonth(year, monthIndex)) { + monthName = '闰' + monthName; + } + + return monthName; + }, + parseMonth: function(year, monthString) { + year = this._validateYear(year); + var month = parseInt(monthString); + var isIntercalary; + + if (!isNaN(month)) { + var i = monthString[monthString.length - 1]; + isIntercalary = (i === 'i' || i === 'I'); + } else { + if (monthString[0] === '闰') { + isIntercalary = true; + monthString = monthString.substring(1); + } + if (monthString[monthString.length - 1] === '月') { + monthString = monthString.substring(0, monthString.length - 1); + } + month = 1 + + ['一','二','三','四','五','六', + '七','八','九','十','十一','十二'].indexOf(monthString); + } + + var monthIndex = this.toMonthIndex(year, month, isIntercalary); + return monthIndex; + }, + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 1, + isRTL: false + } + }, + + /** Check that a candidate date is from the same calendar and is valid. + @memberof BaseCalendar + @private + @param year {CDate|number} The date or the year to validate. + @param error {string} Error message if invalid. + @return {number} The year. + @throws Error if year out of range. */ + _validateYear: function(year, error) { + if (year.year) { + year = year.year(); + } + + if (typeof year !== 'number' || year < 1888 || year > 2111) { + throw error.replace(/\{0\}/, this.local.name); + } + + return year; + }, + + /** Retrieve the month index (i.e. accounting for intercalary months). + @memberof ChineseCalendar + @param year {number} The year. + @param month {number} The month (1 for first month). + @param [isIntercalary=false] {boolean} If month is intercalary. + @return {number} The month index (0 for first month). + @throws Error if an invalid month/year or a different calendar used. */ + toMonthIndex: function(year, month, isIntercalary) { + // compute intercalary month in the year (0 if none) + var intercalaryMonth = this.intercalaryMonth(year); + + // validate month + var invalidIntercalaryMonth = + (isIntercalary && month !== intercalaryMonth); + if (invalidIntercalaryMonth || month < 1 || month > 12) { + throw main.local.invalidMonth + .replace(/\{0\}/, this.local.name); + } + + // compute month index + var monthIndex; + + if (!intercalaryMonth) { + monthIndex = month - 1; + } else if(!isIntercalary && month <= intercalaryMonth) { + monthIndex = month - 1; + } else { + monthIndex = month; + } + + return monthIndex; + }, + + /** Retrieve the month (i.e. accounting for intercalary months). + @memberof ChineseCalendar + @param year {CDate|number} The date or the year to examine. + @param monthIndex {number} The month index (0 for first month). + @return {number} The month (1 for first month). + @throws Error if an invalid month/year or a different calendar used. */ + toChineseMonth: function(year, monthIndex) { + if (year.year) { + year = year.year(); + monthIndex = year.month(); + } + + // compute intercalary month in the year (0 if none) + var intercalaryMonth = this.intercalaryMonth(year); + + // validate month + var maxMonthIndex = (intercalaryMonth) ? 12 : 11; + if (monthIndex < 0 || monthIndex > maxMonthIndex) { + throw main.local.invalidMonth + .replace(/\{0\}/, this.local.name); + } + + // compute Chinese month + var month; + + if (!intercalaryMonth) { + month = monthIndex + 1; + } else if(monthIndex < intercalaryMonth) { + month = monthIndex + 1; + } else { + month = monthIndex; + } + + return month; + }, + + /** Determine the intercalary month of a year (if any). + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The intercalary month number, or 0 if none. + @throws Error if an invalid year or a different calendar used. */ + intercalaryMonth: function(year) { + year = this._validateYear(year); + + var monthDaysTable = LUNAR_MONTH_DAYS[year - LUNAR_MONTH_DAYS[0]]; + var intercalaryMonth = monthDaysTable >> 13; + + return intercalaryMonth; + }, + + /** Determine whether this date is an intercalary month. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [monthIndex] {number} The month index to examine. + @return {boolean} true if this is an intercalary month, false if not. + @throws Error if an invalid year or a different calendar used. */ + isIntercalaryMonth: function(year, monthIndex) { + if (year.year) { + year = year.year(); + monthIndex = year.month(); + } + + var intercalaryMonth = this.intercalaryMonth(year); + + return !!intercalaryMonth && intercalaryMonth === monthIndex; + }, + + /** Determine whether this date is in a leap year. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + return (this.intercalaryMonth(year) !== 0); + }, + + /** Determine the week of the year for a date - ISO 8601. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [monthIndex] {number} The month index to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, monthIndex, day) { + // compute Chinese new year + var validatedYear = + this._validateYear(year, main.local.invalidyear); + var packedDate = + CHINESE_NEW_YEAR[validatedYear - CHINESE_NEW_YEAR[0]]; + + var y = (packedDate >> 9) & 0xFFF; + var m = (packedDate >> 5) & 0x0F; + var d = packedDate & 0x1F; + + // find first Thrusday of the year + var firstThursday; + firstThursday = gregorianCalendar.newDate(y, m, d); + firstThursday.add(4 - (firstThursday.dayOfWeek() || 7), 'd'); + + // compute days from first Thursday + var offset = + this.toJD(year, monthIndex, day) - firstThursday.toJD(); + return 1 + Math.floor(offset / 7); + }, + + /** Retrieve the number of months in a year. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + return (this.leapYear(year)) ? 13 : 12; + }, + + /** Retrieve the number of days in a month. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [monthIndex] {number} The month index. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, monthIndex) { + if (year.year) { + monthIndex = year.month(); + year = year.year(); + } + + year = this._validateYear(year); + + var monthDaysTable = LUNAR_MONTH_DAYS[year - LUNAR_MONTH_DAYS[0]]; + + var intercalaryMonth = monthDaysTable >> 13; + var maxMonthIndex = (intercalaryMonth) ? 12 : 11; + if (monthIndex > maxMonthIndex) { + throw main.local.invalidMonth + .replace(/\{0\}/, this.local.name); + } + + var daysInMonth = (monthDaysTable & (1 << (12 - monthIndex))) ? + 30 : 29; + + return daysInMonth; + }, + + /** Determine whether this date is a week day. + @memberof ChineseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [monthIndex] {number} The month index to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, monthIndex, day) { + return (this.dayOfWeek(year, monthIndex, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof ChineseCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [monthIndex] {number} The month index to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, monthIndex, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = this._validateYear(date.year()); + monthIndex = date.month(); + day = date.day(); + + var isIntercalary = this.isIntercalaryMonth(year, monthIndex); + var month = this.toChineseMonth(year, monthIndex); + + var solar = toSolar(year, month, day, isIntercalary); + + return gregorianCalendar.toJD(solar.year, solar.month, solar.day); + }, + + /** Create a new date from a Julian date. + @memberof ChineseCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + var date = gregorianCalendar.fromJD(jd); + var lunar = toLunar(date.year(), date.month(), date.day()); + var monthIndex = this.toMonthIndex( + lunar.year, lunar.month, lunar.isIntercalary); + return this.newDate(lunar.year, monthIndex, lunar.day); + }, + + /** Create a new date from a string. + @memberof ChineseCalendar + @param dateString {string} String representing a Chinese date + @return {CDate} The new date. + @throws Error if an invalid date. */ + fromString: function(dateString) { + var match = dateString.match(DATE_REGEXP); + + var year = this._validateYear(+match[1]); + + var month = +match[2]; + var isIntercalary = !!match[3]; + var monthIndex = this.toMonthIndex(year, month, isIntercalary); + + var day = +match[4]; + + return this.newDate(year, monthIndex, day); + }, + + /** Add period(s) to a date. + Cater for no year zero. + @memberof ChineseCalendar + @param date {CDate} The starting date. + @param offset {number} The number of periods to adjust by. + @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. + @return {CDate} The updated date. + @throws Error if a different calendar used. */ + add: function(date, offset, period) { + var year = date.year(); + var monthIndex = date.month(); + var isIntercalary = this.isIntercalaryMonth(year, monthIndex); + var month = this.toChineseMonth(year, monthIndex); + + var cdate = Object.getPrototypeOf(ChineseCalendar.prototype) + .add.call(this, date, offset, period); + + if (period === 'y') { + // Resync month + var resultYear = cdate.year(); + var resultMonthIndex = cdate.month(); + + // Using the fact the month index of an intercalary month + // equals its month number: + var resultCanBeIntercalaryMonth = + this.isIntercalaryMonth(resultYear, month); + + var correctedMonthIndex = + (isIntercalary && resultCanBeIntercalaryMonth) ? + this.toMonthIndex(resultYear, month, true) : + this.toMonthIndex(resultYear, month, false); + + if (correctedMonthIndex !== resultMonthIndex) { + cdate.month(correctedMonthIndex); + } + } + + return cdate; + }, +}); + +// Used by ChineseCalendar.prototype.fromString +var DATE_REGEXP = /^\s*(-?\d\d\d\d|\d\d)[-/](\d?\d)([iI]?)[-/](\d?\d)/m; +var MONTH_NUMBER_REGEXP = /^\d?\d[iI]?/m; +var MONTH_NAME_REGEXP = /^闰?十?[一二三四五六七八九]?月/m; +var MONTH_SHORT_NAME_REGEXP = /^闰?十?[一二三四五六七八九]?/m; + +// Chinese calendar implementation +main.calendars.chinese = ChineseCalendar; + +// Chinese calendar tables from year 1888 to 2111 +// +// Source: +// https://github.com/isee15/Lunar-Solar-Calendar-Converter.git + +// Table of intercalary months and days per month from year 1888 to 2111 +// +// bit (12 - i): days in the i^th month +// (= 0 if i^th lunar month has 29 days) +// (= 1 if i^th lunar month has 30 days) +// (first month in lunar year is i = 0) +// bits (13,14,15,16): intercalary month +// (= 0 if lunar year has no intercalary month) +var LUNAR_MONTH_DAYS = [1887, 0x1694, 0x16aa, 0x4ad5, + 0xab6, 0xc4b7, 0x4ae, 0xa56, 0xb52a, 0x1d2a, 0xd54, 0x75aa, 0x156a, + 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4, + 0x135a, 0x495d, 0x95c, 0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8, + 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a, + 0xda8, 0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94, + 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d, 0x192a, + 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b, + 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5, 0x9b4, 0x14b6, 0x6a57, + 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae, + 0x14ae, 0xa4c, 0x7d26, 0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d, + 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da, + 0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4, + 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a, 0x1d4a, 0x10d65, + 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a, + 0x4b55, 0xad4, 0xf55b, 0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694, + 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526, + 0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c, + 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da, 0x1695d, 0x95a, 0x149a, + 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936, + 0xf497, 0x1496, 0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e, + 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c, + 0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4, + 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a, 0x1694, 0xd6aa, 0x15aa, + 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa, + 0xa9b5, 0x96c, 0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54, + 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25, 0x1aa4, + 0xfb52, 0x16b4, 0xaba, 0xa95b, 0x936, 0x1496, 0x9a4b, 0x154a, + 0x136a5, 0xda4, 0x15ac]; + +// Table of Chinese New Years from year 1888 to 2111 +// +// bits (0 to 4): solar day +// bits (5 to 8): solar month +// bits (9 to 20): solar year +var CHINESE_NEW_YEAR = [1887, 0xec04c, 0xec23f, 0xec435, 0xec649, + 0xec83e, 0xeca51, 0xecc46, 0xece3a, 0xed04d, 0xed242, 0xed436, + 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244, + 0xee439, 0xee64d, 0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052, + 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41, + 0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d, + 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651, 0xf1846, 0xf1a3a, + 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848, + 0xf2a3b, 0xf2c4f, 0xf2e45, 0xf3039, 0xf324d, 0xf3442, 0xf3636, + 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443, + 0xf4638, 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f, + 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49, 0xf603e, + 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b, + 0xf703f, 0xf7252, 0xf7447, 0xf763c, 0xf7850, 0xf7a45, 0xf7c39, + 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46, + 0xf8c3b, 0xf8e4f, 0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853, + 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641, + 0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e, + 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53, 0xfc048, 0xfc23c, + 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a, + 0xfd23d, 0xfd451, 0xfd646, 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37, + 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44, + 0xfee38, 0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51, + 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437, 0x10064b, 0x100841, + 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438, + 0x10164c, 0x101842, 0x101a35, 0x101c49, 0x101e3d, 0x102051, + 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b, + 0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845, + 0x103a38, 0x103c4c, 0x103e42, 0x104036, 0x104249, 0x10443d, + 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038, + 0x10524a, 0x10543e, 0x105652, 0x105847, 0x105a3b, 0x105c4f, + 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849, + 0x106a3d, 0x106c51, 0x106e47, 0x10703c, 0x10724f, 0x107444, + 0x107638, 0x10784c, 0x107a3f, 0x107c53, 0x107e48]; + +function toLunar(yearOrDate, monthOrResult, day, result) { + var solarDate; + var lunarDate; + + if(typeof yearOrDate === 'object') { + solarDate = yearOrDate; + lunarDate = monthOrResult || {}; + + } else { + var isValidYear = (typeof yearOrDate === 'number') && + (yearOrDate >= 1888) && (yearOrDate <= 2111); + if(!isValidYear) + throw new Error("Solar year outside range 1888-2111"); + + var isValidMonth = (typeof monthOrResult === 'number') && + (monthOrResult >= 1) && (monthOrResult <= 12); + if(!isValidMonth) + throw new Error("Solar month outside range 1 - 12"); + + var isValidDay = (typeof day === 'number') && (day >= 1) && (day <= 31); + if(!isValidDay) + throw new Error("Solar day outside range 1 - 31"); + + solarDate = { + year: yearOrDate, + month: monthOrResult, + day: day, + }; + lunarDate = result || {}; + } + + // Compute Chinese new year and lunar year + var chineseNewYearPackedDate = + CHINESE_NEW_YEAR[solarDate.year - CHINESE_NEW_YEAR[0]]; + + var packedDate = (solarDate.year << 9) | (solarDate.month << 5) + | solarDate.day; + + lunarDate.year = (packedDate >= chineseNewYearPackedDate) ? + solarDate.year : + solarDate.year - 1; + + chineseNewYearPackedDate = + CHINESE_NEW_YEAR[lunarDate.year - CHINESE_NEW_YEAR[0]]; + + var y = (chineseNewYearPackedDate >> 9) & 0xFFF; + var m = (chineseNewYearPackedDate >> 5) & 0x0F; + var d = chineseNewYearPackedDate & 0x1F; + + // Compute days from new year + var daysFromNewYear; + + var chineseNewYearJSDate = new Date(y, m -1, d); + var jsDate = new Date(solarDate.year, solarDate.month - 1, solarDate.day); + + daysFromNewYear = Math.round( + (jsDate - chineseNewYearJSDate) / (24 * 3600 * 1000)); + + // Compute lunar month and day + var monthDaysTable = LUNAR_MONTH_DAYS[lunarDate.year - LUNAR_MONTH_DAYS[0]]; + + var i; + for(i = 0; i < 13; i++) { + var daysInMonth = (monthDaysTable & (1 << (12 - i))) ? 30 : 29; + + if (daysFromNewYear < daysInMonth) { + break; + } + + daysFromNewYear -= daysInMonth; + } + + var intercalaryMonth = monthDaysTable >> 13; + if (!intercalaryMonth || i < intercalaryMonth) { + lunarDate.isIntercalary = false; + lunarDate.month = 1 + i; + } else if (i === intercalaryMonth) { + lunarDate.isIntercalary = true; + lunarDate.month = i; + } else { + lunarDate.isIntercalary = false; + lunarDate.month = i; + } + + lunarDate.day = 1 + daysFromNewYear; + + return lunarDate; +} + +function toSolar(yearOrDate, monthOrResult, day, isIntercalaryOrResult, result) { + var solarDate; + var lunarDate; + + if(typeof yearOrDate === 'object') { + lunarDate = yearOrDate; + solarDate = monthOrResult || {}; + + } else { + var isValidYear = (typeof yearOrDate === 'number') && + (yearOrDate >= 1888) && (yearOrDate <= 2111); + if(!isValidYear) + throw new Error("Lunar year outside range 1888-2111"); + + var isValidMonth = (typeof monthOrResult === 'number') && + (monthOrResult >= 1) && (monthOrResult <= 12); + if(!isValidMonth) + throw new Error("Lunar month outside range 1 - 12"); + + var isValidDay = (typeof day === 'number') && (day >= 1) && (day <= 30); + if(!isValidDay) + throw new Error("Lunar day outside range 1 - 30"); + + var isIntercalary; + if(typeof isIntercalaryOrResult === 'object') { + isIntercalary = false; + solarDate = isIntercalaryOrResult; + } else { + isIntercalary = !!isIntercalaryOrResult; + solarDate = result || {}; + } + + lunarDate = { + year: yearOrDate, + month: monthOrResult, + day: day, + isIntercalary: isIntercalary, + }; + } + + // Compute days from new year + var daysFromNewYear; + + daysFromNewYear = lunarDate.day - 1; + + var monthDaysTable = LUNAR_MONTH_DAYS[lunarDate.year - LUNAR_MONTH_DAYS[0]]; + var intercalaryMonth = monthDaysTable >> 13; + + var monthsFromNewYear; + if (!intercalaryMonth) { + monthsFromNewYear = lunarDate.month - 1; + } else if (lunarDate.month > intercalaryMonth) { + monthsFromNewYear = lunarDate.month; + } else if (lunarDate.isIntercalary) { + monthsFromNewYear = lunarDate.month; + } else { + monthsFromNewYear = lunarDate.month - 1; + } + + for(var i = 0; i < monthsFromNewYear; i++) { + var daysInMonth = (monthDaysTable & (1 << (12 - i))) ? 30 : 29; + daysFromNewYear += daysInMonth; + } + + // Compute Chinese new year + var packedDate = CHINESE_NEW_YEAR[lunarDate.year - CHINESE_NEW_YEAR[0]]; + + var y = (packedDate >> 9) & 0xFFF; + var m = (packedDate >> 5) & 0x0F; + var d = packedDate & 0x1F; + + // Compute solar date + var jsDate = new Date(y, m - 1, d + daysFromNewYear); + + solarDate.year = jsDate.getFullYear(); + solarDate.month = 1 + jsDate.getMonth(); + solarDate.day = jsDate.getDate(); + + return solarDate; +} + + +},{"../main":548,"object-assign":437}],535:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Coptic calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Coptic calendar. + See http://en.wikipedia.org/wiki/Coptic_calendar. + See also Calendrical Calculations: The Millennium Edition + (http://emr.cs.iit.edu/home/reingold/calendar-book/index.shtml). + @class CopticCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function CopticCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +CopticCalendar.prototype = new main.baseCalendar; + +assign(CopticCalendar.prototype, { + /** The calendar name. + @memberof CopticCalendar */ + name: 'Coptic', + /** Julian date of start of Coptic epoch: 29 August 284 CE (Gregorian). + @memberof CopticCalendar */ + jdEpoch: 1825029.5, + /** Days per month in a common year. + @memberof CopticCalendar */ + daysPerMonth: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 5], + /** true if has a year zero, false if not. + @memberof CopticCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof CopticCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof CopticCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof CopticCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof CopticCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Coptic', + epochs: ['BAM', 'AM'], + monthNames: ['Thout', 'Paopi', 'Hathor', 'Koiak', 'Tobi', 'Meshir', + 'Paremhat', 'Paremoude', 'Pashons', 'Paoni', 'Epip', 'Mesori', 'Pi Kogi Enavot'], + monthNamesShort: ['Tho', 'Pao', 'Hath', 'Koi', 'Tob', 'Mesh', + 'Pat', 'Pad', 'Pash', 'Pao', 'Epi', 'Meso', 'PiK'], + dayNames: ['Tkyriaka', 'Pesnau', 'Pshoment', 'Peftoou', 'Ptiou', 'Psoou', 'Psabbaton'], + dayNamesShort: ['Tky', 'Pes', 'Psh', 'Pef', 'Pti', 'Pso', 'Psa'], + dayNamesMin: ['Tk', 'Pes', 'Psh', 'Pef', 'Pt', 'Pso', 'Psa'], + digits: null, + dateFormat: 'dd/mm/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof CopticCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero + return year % 4 === 3 || year % 4 === -1; + }, + + /** Retrieve the number of months in a year. + @memberof CopticCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, + main.local.invalidYear || main.regionalOptions[''].invalidYear); + return 13; + }, + + /** Determine the week of the year for a date. + @memberof CopticCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number) the month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof CopticCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 13 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof CopticCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param month {number} The month to examine. + @param day {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof CopticCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number) the month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + if (year < 0) { year++; } // No year zero + return date.day() + (date.month() - 1) * 30 + + (year - 1) * 365 + Math.floor(year / 4) + this.jdEpoch - 1; + }, + + /** Create a new date from a Julian date. + @memberof CopticCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + var c = Math.floor(jd) + 0.5 - this.jdEpoch; + var year = Math.floor((c - Math.floor((c + 366) / 1461)) / 365) + 1; + if (year <= 0) { year--; } // No year zero + c = Math.floor(jd) + 0.5 - this.newDate(year, 1, 1).toJD(); + var month = Math.floor(c / 30) + 1; + var day = c - (month - 1) * 30 + 1; + return this.newDate(year, month, day); + } +}); + +// Coptic calendar implementation +main.calendars.coptic = CopticCalendar; + + +},{"../main":548,"object-assign":437}],536:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Discworld calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) January 2016. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Discworld calendar - Unseen University version. + See also http://wiki.lspace.org/mediawiki/Discworld_calendar + and http://discworld.wikia.com/wiki/Discworld_calendar. + @class DiscworldCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function DiscworldCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +DiscworldCalendar.prototype = new main.baseCalendar; + +assign(DiscworldCalendar.prototype, { + /** The calendar name. + @memberof DiscworldCalendar */ + name: 'Discworld', + /** Julian date of start of Discworld epoch: 1 January 0001 CE. + @memberof DiscworldCalendar */ + jdEpoch: 1721425.5, + /** Days per month in a common year. + @memberof DiscworldCalendar */ + daysPerMonth: [16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32], + /** true if has a year zero, false if not. + @memberof DiscworldCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof DiscworldCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof DiscworldCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof DiscworldCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof DiscworldCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Discworld', + epochs: ['BUC', 'UC'], + monthNames: ['Ick', 'Offle', 'February', 'March', 'April', 'May', 'June', + 'Grune', 'August', 'Spune', 'Sektober', 'Ember', 'December'], + monthNamesShort: ['Ick', 'Off', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Gru', 'Aug', 'Spu', 'Sek', 'Emb', 'Dec'], + dayNames: ['Sunday', 'Octeday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Oct', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Oc', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 2, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return false; + }, + + /** Retrieve the number of months in a year. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return 13; + }, + + /** Retrieve the number of days in a year. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return 400; + }, + + /** Determine the week of the year for a date. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 8) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1]; + }, + + /** Retrieve the number of days in a week. + @memberof DiscworldCalendar + @return {number} The number of days. */ + daysInWeek: function() { + return 8; + }, + + /** Retrieve the day of the week for a date. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The day of the week: 0 to number of days - 1. + @throws Error if an invalid date or a different calendar used. */ + dayOfWeek: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + return (date.day() + 1) % 8; + }, + + /** Determine whether this date is a week day. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + var dow = this.dayOfWeek(year, month, day); + return (dow >= 2 && dow <= 6); + }, + + /** Retrieve additional information about a date. + @memberof DiscworldCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {object} Additional information - contents depends on calendar. + @throws Error if an invalid date or a different calendar used. */ + extraInfo: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + return {century: centuries[Math.floor((date.year() - 1) / 100) + 1] || ''}; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof DiscworldCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year() + (date.year() < 0 ? 1 : 0); + month = date.month(); + day = date.day(); + return day + (month > 1 ? 16 : 0) + (month > 2 ? (month - 2) * 32 : 0) + + (year - 1) * 400 + this.jdEpoch - 1; + }, + + /** Create a new date from a Julian date. + @memberof DiscworldCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd + 0.5) - Math.floor(this.jdEpoch) - 1; + var year = Math.floor(jd / 400) + 1; + jd -= (year - 1) * 400; + jd += (jd > 15 ? 16 : 0); + var month = Math.floor(jd / 32) + 1; + var day = jd - (month - 1) * 32 + 1; + return this.newDate(year <= 0 ? year - 1 : year, month, day); + } +}); + +// Names of the centuries +var centuries = { + 20: 'Fruitbat', + 21: 'Anchovy' +}; + +// Discworld calendar implementation +main.calendars.discworld = DiscworldCalendar; + + +},{"../main":548,"object-assign":437}],537:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Ethiopian calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Ethiopian calendar. + See http://en.wikipedia.org/wiki/Ethiopian_calendar. + See also Calendrical Calculations: The Millennium Edition + (http://emr.cs.iit.edu/home/reingold/calendar-book/index.shtml). + @class EthiopianCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function EthiopianCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +EthiopianCalendar.prototype = new main.baseCalendar; + +assign(EthiopianCalendar.prototype, { + /** The calendar name. + @memberof EthiopianCalendar */ + name: 'Ethiopian', + /** Julian date of start of Ethiopian epoch: 27 August 8 CE (Gregorian). + @memberof EthiopianCalendar */ + jdEpoch: 1724220.5, + /** Days per month in a common year. + @memberof EthiopianCalendar */ + daysPerMonth: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 5], + /** true if has a year zero, false if not. + @memberof EthiopianCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof EthiopianCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof EthiopianCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof EthiopianCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof EthiopianCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Ethiopian', + epochs: ['BEE', 'EE'], + monthNames: ['Meskerem', 'Tikemet', 'Hidar', 'Tahesas', 'Tir', 'Yekatit', + 'Megabit', 'Miazia', 'Genbot', 'Sene', 'Hamle', 'Nehase', 'Pagume'], + monthNamesShort: ['Mes', 'Tik', 'Hid', 'Tah', 'Tir', 'Yek', + 'Meg', 'Mia', 'Gen', 'Sen', 'Ham', 'Neh', 'Pag'], + dayNames: ['Ehud', 'Segno', 'Maksegno', 'Irob', 'Hamus', 'Arb', 'Kidame'], + dayNamesShort: ['Ehu', 'Seg', 'Mak', 'Iro', 'Ham', 'Arb', 'Kid'], + dayNamesMin: ['Eh', 'Se', 'Ma', 'Ir', 'Ha', 'Ar', 'Ki'], + digits: null, + dateFormat: 'dd/mm/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof EthiopianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero + return year % 4 === 3 || year % 4 === -1; + }, + + /** Retrieve the number of months in a year. + @memberof EthiopianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, + main.local.invalidYear || main.regionalOptions[''].invalidYear); + return 13; + }, + + /** Determine the week of the year for a date. + @memberof EthiopianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof EthiopianCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 13 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof EthiopianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof EthiopianCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + if (year < 0) { year++; } // No year zero + return date.day() + (date.month() - 1) * 30 + + (year - 1) * 365 + Math.floor(year / 4) + this.jdEpoch - 1; + }, + + /** Create a new date from a Julian date. + @memberof EthiopianCalendar + @param jd {number} the Julian date to convert. + @return {CDate} the equivalent date. */ + fromJD: function(jd) { + var c = Math.floor(jd) + 0.5 - this.jdEpoch; + var year = Math.floor((c - Math.floor((c + 366) / 1461)) / 365) + 1; + if (year <= 0) { year--; } // No year zero + c = Math.floor(jd) + 0.5 - this.newDate(year, 1, 1).toJD(); + var month = Math.floor(c / 30) + 1; + var day = c - (month - 1) * 30 + 1; + return this.newDate(year, month, day); + } +}); + +// Ethiopian calendar implementation +main.calendars.ethiopian = EthiopianCalendar; + + +},{"../main":548,"object-assign":437}],538:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Hebrew calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Hebrew civil calendar. + Based on code from http://www.fourmilab.ch/documents/calendar/. + See also http://en.wikipedia.org/wiki/Hebrew_calendar. + @class HebrewCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function HebrewCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +HebrewCalendar.prototype = new main.baseCalendar; + +assign(HebrewCalendar.prototype, { + /** The calendar name. + @memberof HebrewCalendar */ + name: 'Hebrew', + /** Julian date of start of Hebrew epoch: 7 October 3761 BCE. + @memberof HebrewCalendar */ + jdEpoch: 347995.5, + /** Days per month in a common year. + @memberof HebrewCalendar */ + daysPerMonth: [30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 29], + /** true if has a year zero, false if not. + @memberof HebrewCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof HebrewCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof HebrewCalendar */ + firstMonth: 7, + /** The minimum day number. + @memberof HebrewCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof HebrewCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Hebrew', + epochs: ['BAM', 'AM'], + monthNames: ['Nisan', 'Iyar', 'Sivan', 'Tammuz', 'Av', 'Elul', + 'Tishrei', 'Cheshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar', 'Adar II'], + monthNamesShort: ['Nis', 'Iya', 'Siv', 'Tam', 'Av', 'Elu', 'Tis', 'Che', 'Kis', 'Tev', 'She', 'Ada', 'Ad2'], + dayNames: ['Yom Rishon', 'Yom Sheni', 'Yom Shlishi', 'Yom Revi\'i', 'Yom Chamishi', 'Yom Shishi', 'Yom Shabbat'], + dayNamesShort: ['Ris', 'She', 'Shl', 'Rev', 'Cha', 'Shi', 'Sha'], + dayNamesMin: ['Ri','She','Shl','Re','Ch','Shi','Sha'], + digits: null, + dateFormat: 'dd/mm/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return this._leapYear(date.year()); + }, + + /** Determine whether this date is in a leap year. + @memberof HebrewCalendar + @private + @param year {number} The year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + _leapYear: function(year) { + year = (year < 0 ? year + 1 : year); + return mod(year * 7 + 1, 19) < 7; + }, + + /** Retrieve the number of months in a year. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return this._leapYear(year.year ? year.year() : year) ? 13 : 12; + }, + + /** Determine the week of the year for a date. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a year. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + year = date.year(); + return this.toJD((year === -1 ? +1 : year + 1), 7, 1) - this.toJD(year, 7, 1); + }, + + /** Retrieve the number of days in a month. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + if (year.year) { + month = year.month(); + year = year.year(); + } + this._validate(year, month, this.minDay, main.local.invalidMonth); + return (month === 12 && this.leapYear(year) ? 30 : // Adar I + (month === 8 && mod(this.daysInYear(year), 10) === 5 ? 30 : // Cheshvan in shlemah year + (month === 9 && mod(this.daysInYear(year), 10) === 3 ? 29 : // Kislev in chaserah year + this.daysPerMonth[month - 1]))); + }, + + /** Determine whether this date is a week day. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return this.dayOfWeek(year, month, day) !== 6; + }, + + /** Retrieve additional information about a date - year type. + @memberof HebrewCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {object} Additional information - contents depends on calendar. + @throws Error if an invalid date or a different calendar used. */ + extraInfo: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + return {yearType: (this.leapYear(date) ? 'embolismic' : 'common') + ' ' + + ['deficient', 'regular', 'complete'][this.daysInYear(date) % 10 - 3]}; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof HebrewCalendar + @param year {CDate)|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + month = date.month(); + day = date.day(); + var adjYear = (year <= 0 ? year + 1 : year); + var jd = this.jdEpoch + this._delay1(adjYear) + + this._delay2(adjYear) + day + 1; + if (month < 7) { + for (var m = 7; m <= this.monthsInYear(year); m++) { + jd += this.daysInMonth(year, m); + } + for (var m = 1; m < month; m++) { + jd += this.daysInMonth(year, m); + } + } + else { + for (var m = 7; m < month; m++) { + jd += this.daysInMonth(year, m); + } + } + return jd; + }, + + /** Test for delay of start of new year and to avoid + Sunday, Wednesday, or Friday as start of the new year. + @memberof HebrewCalendar + @private + @param year {number} The year to examine. + @return {number} The days to offset by. */ + _delay1: function(year) { + var months = Math.floor((235 * year - 234) / 19); + var parts = 12084 + 13753 * months; + var day = months * 29 + Math.floor(parts / 25920); + if (mod(3 * (day + 1), 7) < 3) { + day++; + } + return day; + }, + + /** Check for delay in start of new year due to length of adjacent years. + @memberof HebrewCalendar + @private + @param year {number} The year to examine. + @return {number} The days to offset by. */ + _delay2: function(year) { + var last = this._delay1(year - 1); + var present = this._delay1(year); + var next = this._delay1(year + 1); + return ((next - present) === 356 ? 2 : ((present - last) === 382 ? 1 : 0)); + }, + + /** Create a new date from a Julian date. + @memberof HebrewCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd) + 0.5; + var year = Math.floor(((jd - this.jdEpoch) * 98496.0) / 35975351.0) - 1; + while (jd >= this.toJD((year === -1 ? +1 : year + 1), 7, 1)) { + year++; + } + var month = (jd < this.toJD(year, 1, 1)) ? 7 : 1; + while (jd > this.toJD(year, month, this.daysInMonth(year, month))) { + month++; + } + var day = jd - this.toJD(year, month, 1) + 1; + return this.newDate(year, month, day); + } +}); + +// Modulus function which works for non-integers. +function mod(a, b) { + return a - (b * Math.floor(a / b)); +} + +// Hebrew calendar implementation +main.calendars.hebrew = HebrewCalendar; + + +},{"../main":548,"object-assign":437}],539:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Islamic calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Islamic or '16 civil' calendar. + Based on code from http://www.iranchamber.com/calendar/converter/iranian_calendar_converter.php. + See also http://en.wikipedia.org/wiki/Islamic_calendar. + @class IslamicCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function IslamicCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +IslamicCalendar.prototype = new main.baseCalendar; + +assign(IslamicCalendar.prototype, { + /** The calendar name. + @memberof IslamicCalendar */ + name: 'Islamic', + /** Julian date of start of Islamic epoch: 16 July 622 CE. + @memberof IslamicCalendar */ + jdEpoch: 1948439.5, + /** Days per month in a common year. + @memberof IslamicCalendar */ + daysPerMonth: [30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29], + /** true if has a year zero, false if not. + @memberof IslamicCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof IslamicCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof IslamicCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof IslamicCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof IslamicCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Islamic', + epochs: ['BH', 'AH'], + monthNames: ['Muharram', 'Safar', 'Rabi\' al-awwal', 'Rabi\' al-thani', 'Jumada al-awwal', 'Jumada al-thani', + 'Rajab', 'Sha\'aban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'], + monthNamesShort: ['Muh', 'Saf', 'Rab1', 'Rab2', 'Jum1', 'Jum2', 'Raj', 'Sha\'', 'Ram', 'Shaw', 'DhuQ', 'DhuH'], + dayNames: ['Yawm al-ahad', 'Yawm al-ithnayn', 'Yawm ath-thulaathaa\'', + 'Yawm al-arbi\'aa\'', 'Yawm al-khamīs', 'Yawm al-jum\'a', 'Yawm as-sabt'], + dayNamesShort: ['Aha', 'Ith', 'Thu', 'Arb', 'Kha', 'Jum', 'Sab'], + dayNamesMin: ['Ah','It','Th','Ar','Kh','Ju','Sa'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 6, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof IslamicCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return (date.year() * 11 + 14) % 30 < 11; + }, + + /** Determine the week of the year for a date. + @memberof IslamicCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a year. + @memberof IslamicCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + return (this.leapYear(year) ? 355 : 354); + }, + + /** Retrieve the number of days in a month. + @memberof IslamicCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof IslamicCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return this.dayOfWeek(year, month, day) !== 5; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof IslamicCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + month = date.month(); + day = date.day(); + year = (year <= 0 ? year + 1 : year); + return day + Math.ceil(29.5 * (month - 1)) + (year - 1) * 354 + + Math.floor((3 + (11 * year)) / 30) + this.jdEpoch - 1; + }, + + /** Create a new date from a Julian date. + @memberof IslamicCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd) + 0.5; + var year = Math.floor((30 * (jd - this.jdEpoch) + 10646) / 10631); + year = (year <= 0 ? year - 1 : year); + var month = Math.min(12, Math.ceil((jd - 29 - this.toJD(year, 1, 1)) / 29.5) + 1); + var day = jd - this.toJD(year, month, 1) + 1; + return this.newDate(year, month, day); + } +}); + +// Islamic (16 civil) calendar implementation +main.calendars.islamic = IslamicCalendar; + + +},{"../main":548,"object-assign":437}],540:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Julian calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Julian calendar. + Based on code from http://www.fourmilab.ch/documents/calendar/. + See also http://en.wikipedia.org/wiki/Julian_calendar. + @class JulianCalendar + @augments BaseCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function JulianCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +JulianCalendar.prototype = new main.baseCalendar; + +assign(JulianCalendar.prototype, { + /** The calendar name. + @memberof JulianCalendar */ + name: 'Julian', + /** Julian date of start of Julian epoch: 1 January 0001 AD = 30 December 0001 BCE. + @memberof JulianCalendar */ + jdEpoch: 1721423.5, + /** Days per month in a common year. + @memberof JulianCalendar */ + daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + /** true if has a year zero, false if not. + @memberof JulianCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof JulianCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof JulianCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof JulianCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof JulianCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Julian', + epochs: ['BC', 'AD'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'mm/dd/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof JulianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = (date.year() < 0 ? date.year() + 1 : date.year()); // No year zero + return (year % 4) === 0; + }, + + /** Determine the week of the year for a date - ISO 8601. + @memberof JulianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Thursday of this week starting on Monday + var checkDate = this.newDate(year, month, day); + checkDate.add(4 - (checkDate.dayOfWeek() || 7), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof JulianCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof JulianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} True if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof JulianCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + month = date.month(); + day = date.day(); + if (year < 0) { year++; } // No year zero + // Jean Meeus algorithm, "Astronomical Algorithms", 1991 + if (month <= 2) { + year--; + month += 12; + } + return Math.floor(365.25 * (year + 4716)) + + Math.floor(30.6001 * (month + 1)) + day - 1524.5; + }, + + /** Create a new date from a Julian date. + @memberof JulianCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + // Jean Meeus algorithm, "Astronomical Algorithms", 1991 + var a = Math.floor(jd + 0.5); + var b = a + 1524; + var c = Math.floor((b - 122.1) / 365.25); + var d = Math.floor(365.25 * c); + var e = Math.floor((b - d) / 30.6001); + var month = e - Math.floor(e < 14 ? 1 : 13); + var year = c - Math.floor(month > 2 ? 4716 : 4715); + var day = b - d - Math.floor(30.6001 * e); + if (year <= 0) { year--; } // No year zero + return this.newDate(year, month, day); + } +}); + +// Julian calendar implementation +main.calendars.julian = JulianCalendar; + + +},{"../main":548,"object-assign":437}],541:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Mayan calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Mayan Long Count calendar. + See also http://en.wikipedia.org/wiki/Mayan_calendar. + @class MayanCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function MayanCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +MayanCalendar.prototype = new main.baseCalendar; + +assign(MayanCalendar.prototype, { + /** The calendar name. + @memberof MayanCalendar */ + name: 'Mayan', + /** Julian date of start of Mayan epoch: 11 August 3114 BCE. + @memberof MayanCalendar */ + jdEpoch: 584282.5, + /** true if has a year zero, false if not. + @memberof MayanCalendar */ + hasYearZero: true, + /** The minimum month number. + @memberof MayanCalendar */ + minMonth: 0, + /** The first month in the year. + @memberof MayanCalendar */ + firstMonth: 0, + /** The minimum day number. + @memberof MayanCalendar */ + minDay: 0, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof MayanCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. + @property haabMonths {string[]} The names of the Haab months. + @property tzolkinMonths {string[]} The names of the Tzolkin months. */ + regionalOptions: { // Localisations + '': { + name: 'Mayan', + epochs: ['', ''], + monthNames: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '10', '11', '12', '13', '14', '15', '16', '17'], + monthNamesShort: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '10', '11', '12', '13', '14', '15', '16', '17'], + dayNames: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], + dayNamesShort: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], + dayNamesMin: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], + digits: null, + dateFormat: 'YYYY.m.d', + firstDay: 0, + isRTL: false, + haabMonths: ['Pop', 'Uo', 'Zip', 'Zotz', 'Tzec', 'Xul', 'Yaxkin', 'Mol', 'Chen', 'Yax', + 'Zac', 'Ceh', 'Mac', 'Kankin', 'Muan', 'Pax', 'Kayab', 'Cumku', 'Uayeb'], + tzolkinMonths: ['Imix', 'Ik', 'Akbal', 'Kan', 'Chicchan', 'Cimi', 'Manik', 'Lamat', 'Muluc', 'Oc', + 'Chuen', 'Eb', 'Ben', 'Ix', 'Men', 'Cib', 'Caban', 'Etznab', 'Cauac', 'Ahau'] + } + }, + + /** Determine whether this date is in a leap year. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return false; + }, + + /** Format the year, if not a simple sequential number. + @memberof MayanCalendar + @param year {CDate|number} The date to format or the year to format. + @return {string} The formatted year. + @throws Error if an invalid year or a different calendar used. */ + formatYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + year = date.year(); + var baktun = Math.floor(year / 400); + year = year % 400; + year += (year < 0 ? 400 : 0); + var katun = Math.floor(year / 20); + return baktun + '.' + katun + '.' + (year % 20); + }, + + /** Convert from the formatted year back to a single number. + @memberof MayanCalendar + @param years {string} The year as n.n.n. + @return {number} The sequential year. + @throws Error if an invalid value is supplied. */ + forYear: function(years) { + years = years.split('.'); + if (years.length < 3) { + throw 'Invalid Mayan year'; + } + var year = 0; + for (var i = 0; i < years.length; i++) { + var y = parseInt(years[i], 10); + if (Math.abs(y) > 19 || (i > 0 && y < 0)) { + throw 'Invalid Mayan year'; + } + year = year * 20 + y; + } + return year; + }, + + /** Retrieve the number of months in a year. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return 18; + }, + + /** Determine the week of the year for a date. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + this._validate(year, month, day, main.local.invalidDate); + return 0; + }, + + /** Retrieve the number of days in a year. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return 360; + }, + + /** Retrieve the number of days in a month. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + this._validate(year, month, this.minDay, main.local.invalidMonth); + return 20; + }, + + /** Retrieve the number of days in a week. + @memberof MayanCalendar + @return {number} The number of days. */ + daysInWeek: function() { + return 5; // Just for formatting + }, + + /** Retrieve the day of the week for a date. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The day of the week: 0 to number of days - 1. + @throws Error if an invalid date or a different calendar used. */ + dayOfWeek: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + return date.day(); + }, + + /** Determine whether this date is a week day. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + this._validate(year, month, day, main.local.invalidDate); + return true; + }, + + /** Retrieve additional information about a date - Haab and Tzolkin equivalents. + @memberof MayanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {object} Additional information - contents depends on calendar. + @throws Error if an invalid date or a different calendar used. */ + extraInfo: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + var jd = date.toJD(); + var haab = this._toHaab(jd); + var tzolkin = this._toTzolkin(jd); + return {haabMonthName: this.local.haabMonths[haab[0] - 1], + haabMonth: haab[0], haabDay: haab[1], + tzolkinDayName: this.local.tzolkinMonths[tzolkin[0] - 1], + tzolkinDay: tzolkin[0], tzolkinTrecena: tzolkin[1]}; + }, + + /** Retrieve Haab date from a Julian date. + @memberof MayanCalendar + @private + @param jd {number} The Julian date. + @return {number[]} Corresponding Haab month and day. */ + _toHaab: function(jd) { + jd -= this.jdEpoch; + var day = mod(jd + 8 + ((18 - 1) * 20), 365); + return [Math.floor(day / 20) + 1, mod(day, 20)]; + }, + + /** Retrieve Tzolkin date from a Julian date. + @memberof MayanCalendar + @private + @param jd {number} The Julian date. + @return {number[]} Corresponding Tzolkin day and trecena. */ + _toTzolkin: function(jd) { + jd -= this.jdEpoch; + return [amod(jd + 20, 20), amod(jd + 4, 13)]; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof MayanCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + return date.day() + (date.month() * 20) + (date.year() * 360) + this.jdEpoch; + }, + + /** Create a new date from a Julian date. + @memberof MayanCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd) + 0.5 - this.jdEpoch; + var year = Math.floor(jd / 360); + jd = jd % 360; + jd += (jd < 0 ? 360 : 0); + var month = Math.floor(jd / 20); + var day = jd % 20; + return this.newDate(year, month, day); + } +}); + +// Modulus function which works for non-integers. +function mod(a, b) { + return a - (b * Math.floor(a / b)); +} + +// Modulus function which returns numerator if modulus is zero. +function amod(a, b) { + return mod(a - 1, b) + 1; +} + +// Mayan calendar implementation +main.calendars.mayan = MayanCalendar; + + +},{"../main":548,"object-assign":437}],542:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Nanakshahi calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) January 2016. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Nanakshahi calendar. + See also https://en.wikipedia.org/wiki/Nanakshahi_calendar. + @class NanakshahiCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function NanakshahiCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +NanakshahiCalendar.prototype = new main.baseCalendar; + +var gregorian = main.instance('gregorian'); + +assign(NanakshahiCalendar.prototype, { + /** The calendar name. + @memberof NanakshahiCalendar */ + name: 'Nanakshahi', + /** Julian date of start of Nanakshahi epoch: 14 March 1469 CE. + @memberof NanakshahiCalendar */ + jdEpoch: 2257673.5, + /** Days per month in a common year. + @memberof NanakshahiCalendar */ + daysPerMonth: [31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30], + /** true if has a year zero, false if not. + @memberof NanakshahiCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof NanakshahiCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof NanakshahiCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof NanakshahiCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof NanakshahiCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Nanakshahi', + epochs: ['BN', 'AN'], + monthNames: ['Chet', 'Vaisakh', 'Jeth', 'Harh', 'Sawan', 'Bhadon', + 'Assu', 'Katak', 'Maghar', 'Poh', 'Magh', 'Phagun'], + monthNamesShort: ['Che', 'Vai', 'Jet', 'Har', 'Saw', 'Bha', 'Ass', 'Kat', 'Mgr', 'Poh', 'Mgh', 'Pha'], + dayNames: ['Somvaar', 'Mangalvar', 'Budhvaar', 'Veervaar', 'Shukarvaar', 'Sanicharvaar', 'Etvaar'], + dayNamesShort: ['Som', 'Mangal', 'Budh', 'Veer', 'Shukar', 'Sanichar', 'Et'], + dayNamesMin: ['So', 'Ma', 'Bu', 'Ve', 'Sh', 'Sa', 'Et'], + digits: null, + dateFormat: 'dd-mm-yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof NanakshahiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, + main.local.invalidYear || main.regionalOptions[''].invalidYear); + return gregorian.leapYear(date.year() + (date.year() < 1 ? 1 : 0) + 1469); + }, + + /** Determine the week of the year for a date. + @memberof NanakshahiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Monday of this week starting on Monday + var checkDate = this.newDate(year, month, day); + checkDate.add(1 - (checkDate.dayOfWeek() || 7), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof NanakshahiCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof NanakshahiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof NanakshahiCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidMonth); + var year = date.year(); + if (year < 0) { year++; } // No year zero + var doy = date.day(); + for (var m = 1; m < date.month(); m++) { + doy += this.daysPerMonth[m - 1]; + } + return doy + gregorian.toJD(year + 1468, 3, 13); + }, + + /** Create a new date from a Julian date. + @memberof NanakshahiCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd + 0.5); + var year = Math.floor((jd - (this.jdEpoch - 1)) / 366); + while (jd >= this.toJD(year + 1, 1, 1)) { + year++; + } + var day = jd - Math.floor(this.toJD(year, 1, 1) + 0.5) + 1; + var month = 1; + while (day > this.daysInMonth(year, month)) { + day -= this.daysInMonth(year, month); + month++; + } + return this.newDate(year, month, day); + } +}); + +// Nanakshahi calendar implementation +main.calendars.nanakshahi = NanakshahiCalendar; + + +},{"../main":548,"object-assign":437}],543:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Nepali calendar for jQuery v2.0.2. + Written by Artur Neumann (ict.projects{at}nepal.inf.org) April 2013. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Nepali civil calendar. + Based on the ideas from + http://codeissue.com/articles/a04e050dea7468f/algorithm-to-convert-english-date-to-nepali-date-using-c-net + and http://birenj2ee.blogspot.com/2011/04/nepali-calendar-in-java.html + See also http://en.wikipedia.org/wiki/Nepali_calendar + and https://en.wikipedia.org/wiki/Bikram_Samwat. + @class NepaliCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function NepaliCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +NepaliCalendar.prototype = new main.baseCalendar; + +assign(NepaliCalendar.prototype, { + /** The calendar name. + @memberof NepaliCalendar */ + name: 'Nepali', + /** Julian date of start of Nepali epoch: 14 April 57 BCE. + @memberof NepaliCalendar */ + jdEpoch: 1700709.5, + /** Days per month in a common year. + @memberof NepaliCalendar */ + daysPerMonth: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + /** true if has a year zero, false if not. + @memberof NepaliCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof NepaliCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof NepaliCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof NepaliCalendar */ + minDay: 1, + /** The number of days in the year. + @memberof NepaliCalendar */ + daysPerYear: 365, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof NepaliCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Nepali', + epochs: ['BBS', 'ABS'], + monthNames: ['Baisakh', 'Jestha', 'Ashadh', 'Shrawan', 'Bhadra', 'Ashwin', + 'Kartik', 'Mangsir', 'Paush', 'Mangh', 'Falgun', 'Chaitra'], + monthNamesShort: ['Bai', 'Je', 'As', 'Shra', 'Bha', 'Ash', 'Kar', 'Mang', 'Pau', 'Ma', 'Fal', 'Chai'], + dayNames: ['Aaitabaar', 'Sombaar', 'Manglbaar', 'Budhabaar', 'Bihibaar', 'Shukrabaar', 'Shanibaar'], + dayNamesShort: ['Aaita', 'Som', 'Mangl', 'Budha', 'Bihi', 'Shukra', 'Shani'], + dayNamesMin: ['Aai', 'So', 'Man', 'Bu', 'Bi', 'Shu', 'Sha'], + digits: null, + dateFormat: 'dd/mm/yyyy', + firstDay: 1, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof NepaliCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + return this.daysInYear(year) !== this.daysPerYear; + }, + + /** Determine the week of the year for a date. + @memberof NepaliCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a year. + @memberof NepaliCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + year = date.year(); + if (typeof this.NEPALI_CALENDAR_DATA[year] === 'undefined') { + return this.daysPerYear; + } + var daysPerYear = 0; + for (var month_number = this.minMonth; month_number <= 12; month_number++) { + daysPerYear += this.NEPALI_CALENDAR_DATA[year][month_number]; + } + return daysPerYear; + }, + + /** Retrieve the number of days in a month. + @memberof NepaliCalendar + @param year {CDate|number| The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + if (year.year) { + month = year.month(); + year = year.year(); + } + this._validate(year, month, this.minDay, main.local.invalidMonth); + return (typeof this.NEPALI_CALENDAR_DATA[year] === 'undefined' ? + this.daysPerMonth[month - 1] : this.NEPALI_CALENDAR_DATA[year][month]); + }, + + /** Determine whether this date is a week day. + @memberof NepaliCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return this.dayOfWeek(year, month, day) !== 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof NepaliCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(nepaliYear, nepaliMonth, nepaliDay) { + var date = this._validate(nepaliYear, nepaliMonth, nepaliDay, main.local.invalidDate); + nepaliYear = date.year(); + nepaliMonth = date.month(); + nepaliDay = date.day(); + var gregorianCalendar = main.instance(); + var gregorianDayOfYear = 0; // We will add all the days that went by since + // the 1st. January and then we can get the Gregorian Date + var nepaliMonthToCheck = nepaliMonth; + var nepaliYearToCheck = nepaliYear; + this._createMissingCalendarData(nepaliYear); + // Get the correct year + var gregorianYear = nepaliYear - (nepaliMonthToCheck > 9 || (nepaliMonthToCheck === 9 && + nepaliDay >= this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]) ? 56 : 57); + // First we add the amount of days in the actual Nepali month as the day of year in the + // Gregorian one because at least this days are gone since the 1st. Jan. + if (nepaliMonth !== 9) { + gregorianDayOfYear = nepaliDay; + nepaliMonthToCheck--; + } + // Now we loop throw all Nepali month and add the amount of days to gregorianDayOfYear + // we do this till we reach Paush (9th month). 1st. January always falls in this month + while (nepaliMonthToCheck !== 9) { + if (nepaliMonthToCheck <= 0) { + nepaliMonthToCheck = 12; + nepaliYearToCheck--; + } + gregorianDayOfYear += this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][nepaliMonthToCheck]; + nepaliMonthToCheck--; + } + // If the date that has to be converted is in Paush (month no. 9) we have to do some other calculation + if (nepaliMonth === 9) { + // Add the days that are passed since the first day of Paush and substract the + // amount of days that lie between 1st. Jan and 1st Paush + gregorianDayOfYear += nepaliDay - this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]; + // For the first days of Paush we are now in negative values, + // because in the end of the gregorian year we substract + // 365 / 366 days (P.S. remember math in school + - gives -) + if (gregorianDayOfYear < 0) { + gregorianDayOfYear += gregorianCalendar.daysInYear(gregorianYear); + } + } + else { + gregorianDayOfYear += this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][9] - + this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]; + } + return gregorianCalendar.newDate(gregorianYear, 1 ,1).add(gregorianDayOfYear, 'd').toJD(); + }, + + /** Create a new date from a Julian date. + @memberof NepaliCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + var gregorianCalendar = main.instance(); + var gregorianDate = gregorianCalendar.fromJD(jd); + var gregorianYear = gregorianDate.year(); + var gregorianDayOfYear = gregorianDate.dayOfYear(); + var nepaliYear = gregorianYear + 56; //this is not final, it could be also +57 but +56 is always true for 1st Jan. + this._createMissingCalendarData(nepaliYear); + var nepaliMonth = 9; // Jan 1 always fall in Nepali month Paush which is the 9th month of Nepali calendar. + // Get the Nepali day in Paush (month 9) of 1st January + var dayOfFirstJanInPaush = this.NEPALI_CALENDAR_DATA[nepaliYear][0]; + // Check how many days are left of Paush . + // Days calculated from 1st Jan till the end of the actual Nepali month, + // we use this value to check if the gregorian Date is in the actual Nepali month. + var daysSinceJanFirstToEndOfNepaliMonth = + this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth] - dayOfFirstJanInPaush + 1; + // If the gregorian day-of-year is smaller o equal than the sum of days between the 1st January and + // the end of the actual nepali month we found the correct nepali month. + // Example: + // The 4th February 2011 is the gregorianDayOfYear 35 (31 days of January + 4) + // 1st January 2011 is in the nepali year 2067, where 1st. January is in the 17th day of Paush (9th month) + // In 2067 Paush has 30days, This means (30-17+1=14) there are 14days between 1st January and end of Paush + // (including 17th January) + // The gregorianDayOfYear (35) is bigger than 14, so we check the next month + // The next nepali month (Mangh) has 29 days + // 29+14=43, this is bigger than gregorianDayOfYear(35) so, we found the correct nepali month + while (gregorianDayOfYear > daysSinceJanFirstToEndOfNepaliMonth) { + nepaliMonth++; + if (nepaliMonth > 12) { + nepaliMonth = 1; + nepaliYear++; + } + daysSinceJanFirstToEndOfNepaliMonth += this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth]; + } + // The last step is to calculate the nepali day-of-month + // to continue our example from before: + // we calculated there are 43 days from 1st. January (17 Paush) till end of Mangh (29 days) + // when we subtract from this 43 days the day-of-year of the the Gregorian date (35), + // we know how far the searched day is away from the end of the Nepali month. + // So we simply subtract this number from the amount of days in this month (30) + var nepaliDayOfMonth = this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth] - + (daysSinceJanFirstToEndOfNepaliMonth - gregorianDayOfYear); + return this.newDate(nepaliYear, nepaliMonth, nepaliDayOfMonth); + }, + + /** Creates missing data in the NEPALI_CALENDAR_DATA table. + This data will not be correct but just give an estimated result. Mostly -/+ 1 day + @private + @param nepaliYear {number} The missing year number. */ + _createMissingCalendarData: function(nepaliYear) { + var tmp_calendar_data = this.daysPerMonth.slice(0); + tmp_calendar_data.unshift(17); + for (var nepaliYearToCreate = (nepaliYear - 1); nepaliYearToCreate < (nepaliYear + 2); nepaliYearToCreate++) { + if (typeof this.NEPALI_CALENDAR_DATA[nepaliYearToCreate] === 'undefined') { + this.NEPALI_CALENDAR_DATA[nepaliYearToCreate] = tmp_calendar_data; + } + } + }, + + NEPALI_CALENDAR_DATA: { + // These data are from http://www.ashesh.com.np + 1970: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1971: [18, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], + 1972: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 1973: [19, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 1974: [19, 31, 31, 32, 30, 31, 31, 30, 29, 30, 29, 30, 30], + 1975: [18, 31, 31, 32, 32, 30, 31, 30, 29, 30, 29, 30, 30], + 1976: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 1977: [18, 31, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31], + 1978: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1979: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 1980: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 1981: [18, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 1982: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1983: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 1984: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 1985: [18, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 1986: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1987: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 1988: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 1989: [18, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 1990: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1991: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], + // These data are from http://nepalicalendar.rat32.com/index.php + 1992: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 1993: [18, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 1994: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1995: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 1996: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 1997: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1998: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 1999: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2000: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2001: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2002: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2003: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2004: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2005: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2006: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2007: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2008: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], + 2009: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2010: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2011: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2012: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 2013: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2014: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2015: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2016: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 2017: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2018: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2019: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2020: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2021: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2022: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 2023: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2024: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2025: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2026: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2027: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2028: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2029: [18, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], + 2030: [17, 31, 32, 31, 32, 31, 30, 30, 30, 30, 30, 30, 31], + 2031: [17, 31, 32, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31], + 2032: [17, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32], + 2033: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2034: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2035: [17, 30, 32, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], + 2036: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2037: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2038: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2039: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 2040: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2041: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2042: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2043: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 2044: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2045: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2046: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2047: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2048: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2049: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 2050: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2051: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2052: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2053: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 2054: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2055: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 30, 29, 30], + 2056: [17, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], + 2057: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2058: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2059: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2060: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2061: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2062: [17, 30, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31], + 2063: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2064: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2065: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2066: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], + 2067: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2068: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2069: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2070: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], + 2071: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2072: [17, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2073: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], + 2074: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2075: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2076: [16, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + 2077: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], + 2078: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], + 2079: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], + 2080: [16, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], + // These data are from http://www.ashesh.com.np/nepali-calendar/ + 2081: [17, 31, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2082: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2083: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], + 2084: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], + 2085: [17, 31, 32, 31, 32, 31, 31, 30, 30, 29, 30, 30, 30], + 2086: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2087: [16, 31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30], + 2088: [16, 30, 31, 32, 32, 30, 31, 30, 30, 29, 30, 30, 30], + 2089: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2090: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2091: [16, 31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30], + 2092: [16, 31, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2093: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2094: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], + 2095: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 30, 30, 30], + 2096: [17, 30, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], + 2097: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], + 2098: [17, 31, 31, 32, 31, 31, 31, 29, 30, 29, 30, 30, 31], + 2099: [17, 31, 31, 32, 31, 31, 31, 30, 29, 29, 30, 30, 30], + 2100: [17, 31, 32, 31, 32, 30, 31, 30, 29, 30, 29, 30, 30] + } +}); + +// Nepali calendar implementation +main.calendars.nepali = NepaliCalendar; + + +},{"../main":548,"object-assign":437}],544:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Persian calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the Persian or Jalali calendar. + Based on code from http://www.iranchamber.com/calendar/converter/iranian_calendar_converter.php. + See also http://en.wikipedia.org/wiki/Iranian_calendar. + @class PersianCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function PersianCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +PersianCalendar.prototype = new main.baseCalendar; + +assign(PersianCalendar.prototype, { + /** The calendar name. + @memberof PersianCalendar */ + name: 'Persian', + /** Julian date of start of Persian epoch: 19 March 622 CE. + @memberof PersianCalendar */ + jdEpoch: 1948320.5, + /** Days per month in a common year. + @memberof PersianCalendar */ + daysPerMonth: [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29], + /** true if has a year zero, false if not. + @memberof PersianCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof PersianCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof PersianCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof PersianCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof PersianCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Persian', + epochs: ['BP', 'AP'], + monthNames: ['Farvardin', 'Ordibehesht', 'Khordad', 'Tir', 'Mordad', 'Shahrivar', + 'Mehr', 'Aban', 'Azar', 'Day', 'Bahman', 'Esfand'], + monthNamesShort: ['Far', 'Ord', 'Kho', 'Tir', 'Mor', 'Sha', 'Meh', 'Aba', 'Aza', 'Day', 'Bah', 'Esf'], + dayNames: ['Yekshambe', 'Doshambe', 'Seshambe', 'Chæharshambe', 'Panjshambe', 'Jom\'e', 'Shambe'], + dayNamesShort: ['Yek', 'Do', 'Se', 'Chæ', 'Panj', 'Jom', 'Sha'], + dayNamesMin: ['Ye','Do','Se','Ch','Pa','Jo','Sh'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 6, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof PersianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return (((((date.year() - (date.year() > 0 ? 474 : 473)) % 2820) + + 474 + 38) * 682) % 2816) < 682; + }, + + /** Determine the week of the year for a date. + @memberof PersianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Saturday of this week starting on Saturday + var checkDate = this.newDate(year, month, day); + checkDate.add(-((checkDate.dayOfWeek() + 1) % 7), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof PersianCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof PersianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return this.dayOfWeek(year, month, day) !== 5; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof PersianCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + year = date.year(); + month = date.month(); + day = date.day(); + var epBase = year - (year >= 0 ? 474 : 473); + var epYear = 474 + mod(epBase, 2820); + return day + (month <= 7 ? (month - 1) * 31 : (month - 1) * 30 + 6) + + Math.floor((epYear * 682 - 110) / 2816) + (epYear - 1) * 365 + + Math.floor(epBase / 2820) * 1029983 + this.jdEpoch - 1; + }, + + /** Create a new date from a Julian date. + @memberof PersianCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + jd = Math.floor(jd) + 0.5; + var depoch = jd - this.toJD(475, 1, 1); + var cycle = Math.floor(depoch / 1029983); + var cyear = mod(depoch, 1029983); + var ycycle = 2820; + if (cyear !== 1029982) { + var aux1 = Math.floor(cyear / 366); + var aux2 = mod(cyear, 366); + ycycle = Math.floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1; + } + var year = ycycle + (2820 * cycle) + 474; + year = (year <= 0 ? year - 1 : year); + var yday = jd - this.toJD(year, 1, 1) + 1; + var month = (yday <= 186 ? Math.ceil(yday / 31) : Math.ceil((yday - 6) / 30)); + var day = jd - this.toJD(year, month, 1) + 1; + return this.newDate(year, month, day); + } +}); + +// Modulus function which works for non-integers. +function mod(a, b) { + return a - (b * Math.floor(a / b)); +} + +// Persian (Jalali) calendar implementation +main.calendars.persian = PersianCalendar; +main.calendars.jalali = PersianCalendar; + + +},{"../main":548,"object-assign":437}],545:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Taiwanese (Minguo) calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +var gregorianCalendar = main.instance(); + +/** Implementation of the Taiwanese calendar. + See http://en.wikipedia.org/wiki/Minguo_calendar. + @class TaiwanCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function TaiwanCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +TaiwanCalendar.prototype = new main.baseCalendar; + +assign(TaiwanCalendar.prototype, { + /** The calendar name. + @memberof TaiwanCalendar */ + name: 'Taiwan', + /** Julian date of start of Taiwan epoch: 1 January 1912 CE (Gregorian). + @memberof TaiwanCalendar */ + jdEpoch: 2419402.5, + /** Difference in years between Taiwan and Gregorian calendars. + @memberof TaiwanCalendar */ + yearsOffset: 1911, + /** Days per month in a common year. + @memberof TaiwanCalendar */ + daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + /** true if has a year zero, false if not. + @memberof TaiwanCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof TaiwanCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof TaiwanCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof TaiwanCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof TaiwanCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Taiwan', + epochs: ['BROC', 'ROC'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 1, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof TaiwanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = this._t2gYear(date.year()); + return gregorianCalendar.leapYear(year); + }, + + /** Determine the week of the year for a date - ISO 8601. + @memberof TaiwanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = this._t2gYear(date.year()); + return gregorianCalendar.weekOfYear(year, date.month(), date.day()); + }, + + /** Retrieve the number of days in a month. + @memberof TaiwanCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof TaiwanCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof TaiwanCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + var year = this._t2gYear(date.year()); + return gregorianCalendar.toJD(year, date.month(), date.day()); + }, + + /** Create a new date from a Julian date. + @memberof TaiwanCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + var date = gregorianCalendar.fromJD(jd); + var year = this._g2tYear(date.year()); + return this.newDate(year, date.month(), date.day()); + }, + + /** Convert Taiwanese to Gregorian year. + @memberof TaiwanCalendar + @private + @param year {number} The Taiwanese year. + @return {number} The corresponding Gregorian year. */ + _t2gYear: function(year) { + return year + this.yearsOffset + (year >= -this.yearsOffset && year <= -1 ? 1 : 0); + }, + + /** Convert Gregorian to Taiwanese year. + @memberof TaiwanCalendar + @private + @param year {number} The Gregorian year. + @return {number} The corresponding Taiwanese year. */ + _g2tYear: function(year) { + return year - this.yearsOffset - (year >= 1 && year <= this.yearsOffset ? 1 : 0); + } +}); + +// Taiwan calendar implementation +main.calendars.taiwan = TaiwanCalendar; + + +},{"../main":548,"object-assign":437}],546:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Thai calendar for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +var gregorianCalendar = main.instance(); + +/** Implementation of the Thai calendar. + See http://en.wikipedia.org/wiki/Thai_calendar. + @class ThaiCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function ThaiCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +ThaiCalendar.prototype = new main.baseCalendar; + +assign(ThaiCalendar.prototype, { + /** The calendar name. + @memberof ThaiCalendar */ + name: 'Thai', + /** Julian date of start of Thai epoch: 1 January 543 BCE (Gregorian). + @memberof ThaiCalendar */ + jdEpoch: 1523098.5, + /** Difference in years between Thai and Gregorian calendars. + @memberof ThaiCalendar */ + yearsOffset: 543, + /** Days per month in a common year. + @memberof ThaiCalendar */ + daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + /** true if has a year zero, false if not. + @memberof ThaiCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof ThaiCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof ThaiCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof ThaiCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof ThaiCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Thai', + epochs: ['BBE', 'BE'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'dd/mm/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof ThaiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = this._t2gYear(date.year()); + return gregorianCalendar.leapYear(year); + }, + + /** Determine the week of the year for a date - ISO 8601. + @memberof ThaiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + var year = this._t2gYear(date.year()); + return gregorianCalendar.weekOfYear(year, date.month(), date.day()); + }, + + /** Retrieve the number of days in a month. + @memberof ThaiCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof ThaiCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof ThaiCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + var year = this._t2gYear(date.year()); + return gregorianCalendar.toJD(year, date.month(), date.day()); + }, + + /** Create a new date from a Julian date. + @memberof ThaiCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + var date = gregorianCalendar.fromJD(jd); + var year = this._g2tYear(date.year()); + return this.newDate(year, date.month(), date.day()); + }, + + /** Convert Thai to Gregorian year. + @memberof ThaiCalendar + @private + @param year {number} The Thai year. + @return {number} The corresponding Gregorian year. */ + _t2gYear: function(year) { + return year - this.yearsOffset - (year >= 1 && year <= this.yearsOffset ? 1 : 0); + }, + + /** Convert Gregorian to Thai year. + @memberof ThaiCalendar + @private + @param year {number} The Gregorian year. + @return {number} The corresponding Thai year. */ + _g2tYear: function(year) { + return year + this.yearsOffset + (year >= -this.yearsOffset && year <= -1 ? 1 : 0); + } +}); + +// Thai calendar implementation +main.calendars.thai = ThaiCalendar; + + +},{"../main":548,"object-assign":437}],547:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + UmmAlQura calendar for jQuery v2.0.2. + Written by Amro Osama March 2013. + Modified by Binnooh.com & www.elm.sa - 2014 - Added dates back to 1276 Hijri year. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var main = _dereq_('../main'); +var assign = _dereq_('object-assign'); + + +/** Implementation of the UmmAlQura or 'saudi' calendar. + See also http://en.wikipedia.org/wiki/Islamic_calendar#Saudi_Arabia.27s_Umm_al-Qura_calendar. + http://www.ummulqura.org.sa/About.aspx + http://www.staff.science.uu.nl/~gent0113/islam/ummalqura.htm + @class UmmAlQuraCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function UmmAlQuraCalendar(language) { + this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; +} + +UmmAlQuraCalendar.prototype = new main.baseCalendar; + +assign(UmmAlQuraCalendar.prototype, { + /** The calendar name. + @memberof UmmAlQuraCalendar */ + name: 'UmmAlQura', + //jdEpoch: 1948440, // Julian date of start of UmmAlQura epoch: 14 March 1937 CE + //daysPerMonth: // Days per month in a common year, replaced by a method. + /** true if has a year zero, false if not. + @memberof UmmAlQuraCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof UmmAlQuraCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof UmmAlQuraCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof UmmAlQuraCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof UmmAlQuraCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Umm al-Qura', + epochs: ['BH', 'AH'], + monthNames: ['Al-Muharram', 'Safar', 'Rabi\' al-awwal', 'Rabi\' Al-Thani', 'Jumada Al-Awwal', 'Jumada Al-Thani', + 'Rajab', 'Sha\'aban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'], + monthNamesShort: ['Muh', 'Saf', 'Rab1', 'Rab2', 'Jum1', 'Jum2', 'Raj', 'Sha\'', 'Ram', 'Shaw', 'DhuQ', 'DhuH'], + dayNames: ['Yawm al-Ahad', 'Yawm al-Ithnain', 'Yawm al-Thalāthā’', 'Yawm al-Arba‘ā’', 'Yawm al-Khamīs', 'Yawm al-Jum‘a', 'Yawm al-Sabt'], + dayNamesMin: ['Ah', 'Ith', 'Th', 'Ar', 'Kh', 'Ju', 'Sa'], + digits: null, + dateFormat: 'yyyy/mm/dd', + firstDay: 6, + isRTL: true + } + }, + + /** Determine whether this date is in a leap year. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function (year) { + var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); + return (this.daysInYear(date.year()) === 355); + }, + + /** Determine the week of the year for a date. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function (year, month, day) { + // Find Sunday of this week starting on Sunday + var checkDate = this.newDate(year, month, day); + checkDate.add(-checkDate.dayOfWeek(), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a year. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function (year) { + var daysCount = 0; + for (var i = 1; i <= 12; i++) { + daysCount += this.daysInMonth(year, i); + } + return daysCount; + }, + + /** Retrieve the number of days in a month. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function (year, month) { + var date = this._validate(year, month, this.minDay, main.local.invalidMonth); + var mcjdn = date.toJD() - 2400000 + 0.5; // Modified Chronological Julian Day Number (MCJDN) + // the MCJDN's of the start of the lunations in the Umm al-Qura calendar are stored in the 'ummalqura_dat' array + var index = 0; + for (var i = 0; i < ummalqura_dat.length; i++) { + if (ummalqura_dat[i] > mcjdn) { + return (ummalqura_dat[index] - ummalqura_dat[index - 1]); + } + index++; + } + return 30; // Unknown outside + }, + + /** Determine whether this date is a week day. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function (year, month, day) { + return this.dayOfWeek(year, month, day) !== 5; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof UmmAlQuraCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function (year, month, day) { + var date = this._validate(year, month, day, main.local.invalidDate); + var index = (12 * (date.year() - 1)) + date.month() - 15292; + var mcjdn = date.day() + ummalqura_dat[index - 1] - 1; + return mcjdn + 2400000 - 0.5; // Modified Chronological Julian Day Number (MCJDN) + }, + + /** Create a new date from a Julian date. + @memberof UmmAlQuraCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function (jd) { + var mcjdn = jd - 2400000 + 0.5; // Modified Chronological Julian Day Number (MCJDN) + // the MCJDN's of the start of the lunations in the Umm al-Qura calendar + // are stored in the 'ummalqura_dat' array + var index = 0; + for (var i = 0; i < ummalqura_dat.length; i++) { + if (ummalqura_dat[i] > mcjdn) break; + index++; + } + var lunation = index + 15292; //UmmAlQura Lunation Number + var ii = Math.floor((lunation - 1) / 12); + var year = ii + 1; + var month = lunation - 12 * ii; + var day = mcjdn - ummalqura_dat[index - 1] + 1; + return this.newDate(year, month, day); + }, + + /** Determine whether a date is valid for this calendar. + @memberof UmmAlQuraCalendar + @param year {number} The year to examine. + @param month {number} The month to examine. + @param day {number} The day to examine. + @return {boolean} true if a valid date, false if not. */ + isValid: function(year, month, day) { + var valid = main.baseCalendar.prototype.isValid.apply(this, arguments); + if (valid) { + year = (year.year != null ? year.year : year); + valid = (year >= 1276 && year <= 1500); + } + return valid; + }, + + /** Check that a candidate date is from the same calendar and is valid. + @memberof UmmAlQuraCalendar + @private + @param year {CDate|number} The date to validate or the year to validate. + @param month {number} The month to validate. + @param day {number} The day to validate. + @param error {string} Error message if invalid. + @throws Error if different calendars used or invalid date. */ + _validate: function(year, month, day, error) { + var date = main.baseCalendar.prototype._validate.apply(this, arguments); + if (date.year < 1276 || date.year > 1500) { + throw error.replace(/\{0\}/, this.local.name); + } + return date; + } +}); + +// UmmAlQura calendar implementation +main.calendars.ummalqura = UmmAlQuraCalendar; + +var ummalqura_dat = [ + 20, 50, 79, 109, 138, 168, 197, 227, 256, 286, 315, 345, 374, 404, 433, 463, 492, 522, 551, 581, + 611, 641, 670, 700, 729, 759, 788, 818, 847, 877, 906, 936, 965, 995, 1024, 1054, 1083, 1113, 1142, 1172, + 1201, 1231, 1260, 1290, 1320, 1350, 1379, 1409, 1438, 1468, 1497, 1527, 1556, 1586, 1615, 1645, 1674, 1704, 1733, 1763, + 1792, 1822, 1851, 1881, 1910, 1940, 1969, 1999, 2028, 2058, 2087, 2117, 2146, 2176, 2205, 2235, 2264, 2294, 2323, 2353, + 2383, 2413, 2442, 2472, 2501, 2531, 2560, 2590, 2619, 2649, 2678, 2708, 2737, 2767, 2796, 2826, 2855, 2885, 2914, 2944, + 2973, 3003, 3032, 3062, 3091, 3121, 3150, 3180, 3209, 3239, 3268, 3298, 3327, 3357, 3386, 3416, 3446, 3476, 3505, 3535, + 3564, 3594, 3623, 3653, 3682, 3712, 3741, 3771, 3800, 3830, 3859, 3889, 3918, 3948, 3977, 4007, 4036, 4066, 4095, 4125, + 4155, 4185, 4214, 4244, 4273, 4303, 4332, 4362, 4391, 4421, 4450, 4480, 4509, 4539, 4568, 4598, 4627, 4657, 4686, 4716, + 4745, 4775, 4804, 4834, 4863, 4893, 4922, 4952, 4981, 5011, 5040, 5070, 5099, 5129, 5158, 5188, 5218, 5248, 5277, 5307, + 5336, 5366, 5395, 5425, 5454, 5484, 5513, 5543, 5572, 5602, 5631, 5661, 5690, 5720, 5749, 5779, 5808, 5838, 5867, 5897, + 5926, 5956, 5985, 6015, 6044, 6074, 6103, 6133, 6162, 6192, 6221, 6251, 6281, 6311, 6340, 6370, 6399, 6429, 6458, 6488, + 6517, 6547, 6576, 6606, 6635, 6665, 6694, 6724, 6753, 6783, 6812, 6842, 6871, 6901, 6930, 6960, 6989, 7019, 7048, 7078, + 7107, 7137, 7166, 7196, 7225, 7255, 7284, 7314, 7344, 7374, 7403, 7433, 7462, 7492, 7521, 7551, 7580, 7610, 7639, 7669, + 7698, 7728, 7757, 7787, 7816, 7846, 7875, 7905, 7934, 7964, 7993, 8023, 8053, 8083, 8112, 8142, 8171, 8201, 8230, 8260, + 8289, 8319, 8348, 8378, 8407, 8437, 8466, 8496, 8525, 8555, 8584, 8614, 8643, 8673, 8702, 8732, 8761, 8791, 8821, 8850, + 8880, 8909, 8938, 8968, 8997, 9027, 9056, 9086, 9115, 9145, 9175, 9205, 9234, 9264, 9293, 9322, 9352, 9381, 9410, 9440, + 9470, 9499, 9529, 9559, 9589, 9618, 9648, 9677, 9706, 9736, 9765, 9794, 9824, 9853, 9883, 9913, 9943, 9972, 10002, 10032, + 10061, 10090, 10120, 10149, 10178, 10208, 10237, 10267, 10297, 10326, 10356, 10386, 10415, 10445, 10474, 10504, 10533, 10562, 10592, 10621, + 10651, 10680, 10710, 10740, 10770, 10799, 10829, 10858, 10888, 10917, 10947, 10976, 11005, 11035, 11064, 11094, 11124, 11153, 11183, 11213, + 11242, 11272, 11301, 11331, 11360, 11389, 11419, 11448, 11478, 11507, 11537, 11567, 11596, 11626, 11655, 11685, 11715, 11744, 11774, 11803, + 11832, 11862, 11891, 11921, 11950, 11980, 12010, 12039, 12069, 12099, 12128, 12158, 12187, 12216, 12246, 12275, 12304, 12334, 12364, 12393, + 12423, 12453, 12483, 12512, 12542, 12571, 12600, 12630, 12659, 12688, 12718, 12747, 12777, 12807, 12837, 12866, 12896, 12926, 12955, 12984, + 13014, 13043, 13072, 13102, 13131, 13161, 13191, 13220, 13250, 13280, 13310, 13339, 13368, 13398, 13427, 13456, 13486, 13515, 13545, 13574, + 13604, 13634, 13664, 13693, 13723, 13752, 13782, 13811, 13840, 13870, 13899, 13929, 13958, 13988, 14018, 14047, 14077, 14107, 14136, 14166, + 14195, 14224, 14254, 14283, 14313, 14342, 14372, 14401, 14431, 14461, 14490, 14520, 14550, 14579, 14609, 14638, 14667, 14697, 14726, 14756, + 14785, 14815, 14844, 14874, 14904, 14933, 14963, 14993, 15021, 15051, 15081, 15110, 15140, 15169, 15199, 15228, 15258, 15287, 15317, 15347, + 15377, 15406, 15436, 15465, 15494, 15524, 15553, 15582, 15612, 15641, 15671, 15701, 15731, 15760, 15790, 15820, 15849, 15878, 15908, 15937, + 15966, 15996, 16025, 16055, 16085, 16114, 16144, 16174, 16204, 16233, 16262, 16292, 16321, 16350, 16380, 16409, 16439, 16468, 16498, 16528, + 16558, 16587, 16617, 16646, 16676, 16705, 16734, 16764, 16793, 16823, 16852, 16882, 16912, 16941, 16971, 17001, 17030, 17060, 17089, 17118, + 17148, 17177, 17207, 17236, 17266, 17295, 17325, 17355, 17384, 17414, 17444, 17473, 17502, 17532, 17561, 17591, 17620, 17650, 17679, 17709, + 17738, 17768, 17798, 17827, 17857, 17886, 17916, 17945, 17975, 18004, 18034, 18063, 18093, 18122, 18152, 18181, 18211, 18241, 18270, 18300, + 18330, 18359, 18388, 18418, 18447, 18476, 18506, 18535, 18565, 18595, 18625, 18654, 18684, 18714, 18743, 18772, 18802, 18831, 18860, 18890, + 18919, 18949, 18979, 19008, 19038, 19068, 19098, 19127, 19156, 19186, 19215, 19244, 19274, 19303, 19333, 19362, 19392, 19422, 19452, 19481, + 19511, 19540, 19570, 19599, 19628, 19658, 19687, 19717, 19746, 19776, 19806, 19836, 19865, 19895, 19924, 19954, 19983, 20012, 20042, 20071, + 20101, 20130, 20160, 20190, 20219, 20249, 20279, 20308, 20338, 20367, 20396, 20426, 20455, 20485, 20514, 20544, 20573, 20603, 20633, 20662, + 20692, 20721, 20751, 20780, 20810, 20839, 20869, 20898, 20928, 20957, 20987, 21016, 21046, 21076, 21105, 21135, 21164, 21194, 21223, 21253, + 21282, 21312, 21341, 21371, 21400, 21430, 21459, 21489, 21519, 21548, 21578, 21607, 21637, 21666, 21696, 21725, 21754, 21784, 21813, 21843, + 21873, 21902, 21932, 21962, 21991, 22021, 22050, 22080, 22109, 22138, 22168, 22197, 22227, 22256, 22286, 22316, 22346, 22375, 22405, 22434, + 22464, 22493, 22522, 22552, 22581, 22611, 22640, 22670, 22700, 22730, 22759, 22789, 22818, 22848, 22877, 22906, 22936, 22965, 22994, 23024, + 23054, 23083, 23113, 23143, 23173, 23202, 23232, 23261, 23290, 23320, 23349, 23379, 23408, 23438, 23467, 23497, 23527, 23556, 23586, 23616, + 23645, 23674, 23704, 23733, 23763, 23792, 23822, 23851, 23881, 23910, 23940, 23970, 23999, 24029, 24058, 24088, 24117, 24147, 24176, 24206, + 24235, 24265, 24294, 24324, 24353, 24383, 24413, 24442, 24472, 24501, 24531, 24560, 24590, 24619, 24648, 24678, 24707, 24737, 24767, 24796, + 24826, 24856, 24885, 24915, 24944, 24974, 25003, 25032, 25062, 25091, 25121, 25150, 25180, 25210, 25240, 25269, 25299, 25328, 25358, 25387, + 25416, 25446, 25475, 25505, 25534, 25564, 25594, 25624, 25653, 25683, 25712, 25742, 25771, 25800, 25830, 25859, 25888, 25918, 25948, 25977, + 26007, 26037, 26067, 26096, 26126, 26155, 26184, 26214, 26243, 26272, 26302, 26332, 26361, 26391, 26421, 26451, 26480, 26510, 26539, 26568, + 26598, 26627, 26656, 26686, 26715, 26745, 26775, 26805, 26834, 26864, 26893, 26923, 26952, 26982, 27011, 27041, 27070, 27099, 27129, 27159, + 27188, 27218, 27248, 27277, 27307, 27336, 27366, 27395, 27425, 27454, 27484, 27513, 27542, 27572, 27602, 27631, 27661, 27691, 27720, 27750, + 27779, 27809, 27838, 27868, 27897, 27926, 27956, 27985, 28015, 28045, 28074, 28104, 28134, 28163, 28193, 28222, 28252, 28281, 28310, 28340, + 28369, 28399, 28428, 28458, 28488, 28517, 28547, 28577, + // From 1356 + 28607, 28636, 28665, 28695, 28724, 28754, 28783, 28813, 28843, 28872, 28901, 28931, 28960, 28990, 29019, 29049, 29078, 29108, 29137, 29167, + 29196, 29226, 29255, 29285, 29315, 29345, 29375, 29404, 29434, 29463, 29492, 29522, 29551, 29580, 29610, 29640, 29669, 29699, 29729, 29759, + 29788, 29818, 29847, 29876, 29906, 29935, 29964, 29994, 30023, 30053, 30082, 30112, 30141, 30171, 30200, 30230, 30259, 30289, 30318, 30348, + 30378, 30408, 30437, 30467, 30496, 30526, 30555, 30585, 30614, 30644, 30673, 30703, 30732, 30762, 30791, 30821, 30850, 30880, 30909, 30939, + 30968, 30998, 31027, 31057, 31086, 31116, 31145, 31175, 31204, 31234, 31263, 31293, 31322, 31352, 31381, 31411, 31441, 31471, 31500, 31530, + 31559, 31589, 31618, 31648, 31676, 31706, 31736, 31766, 31795, 31825, 31854, 31884, 31913, 31943, 31972, 32002, 32031, 32061, 32090, 32120, + 32150, 32180, 32209, 32239, 32268, 32298, 32327, 32357, 32386, 32416, 32445, 32475, 32504, 32534, 32563, 32593, 32622, 32652, 32681, 32711, + 32740, 32770, 32799, 32829, 32858, 32888, 32917, 32947, 32976, 33006, 33035, 33065, 33094, 33124, 33153, 33183, 33213, 33243, 33272, 33302, + 33331, 33361, 33390, 33420, 33450, 33479, 33509, 33539, 33568, 33598, 33627, 33657, 33686, 33716, 33745, 33775, 33804, 33834, 33863, 33893, + 33922, 33952, 33981, 34011, 34040, 34069, 34099, 34128, 34158, 34187, 34217, 34247, 34277, 34306, 34336, 34365, 34395, 34424, 34454, 34483, + 34512, 34542, 34571, 34601, 34631, 34660, 34690, 34719, 34749, 34778, 34808, 34837, 34867, 34896, 34926, 34955, 34985, 35015, 35044, 35074, + 35103, 35133, 35162, 35192, 35222, 35251, 35280, 35310, 35340, 35370, 35399, 35429, 35458, 35488, 35517, 35547, 35576, 35605, 35635, 35665, + 35694, 35723, 35753, 35782, 35811, 35841, 35871, 35901, 35930, 35960, 35989, 36019, 36048, 36078, 36107, 36136, 36166, 36195, 36225, 36254, + 36284, 36314, 36343, 36373, 36403, 36433, 36462, 36492, 36521, 36551, 36580, 36610, 36639, 36669, 36698, 36728, 36757, 36786, 36816, 36845, + 36875, 36904, 36934, 36963, 36993, 37022, 37052, 37081, 37111, 37141, 37170, 37200, 37229, 37259, 37288, 37318, 37347, 37377, 37406, 37436, + 37465, 37495, 37524, 37554, 37584, 37613, 37643, 37672, 37701, 37731, 37760, 37790, 37819, 37849, 37878, 37908, 37938, 37967, 37997, 38027, + 38056, 38085, 38115, 38144, 38174, 38203, 38233, 38262, 38292, 38322, 38351, 38381, 38410, 38440, 38469, 38499, 38528, 38558, 38587, 38617, + 38646, 38676, 38705, 38735, 38764, 38794, 38823, 38853, 38882, 38912, 38941, 38971, 39001, 39030, 39059, 39089, 39118, 39148, 39178, 39208, + 39237, 39267, 39297, 39326, 39355, 39385, 39414, 39444, 39473, 39503, 39532, 39562, 39592, 39621, 39650, 39680, 39709, 39739, 39768, 39798, + 39827, 39857, 39886, 39916, 39946, 39975, 40005, 40035, 40064, 40094, 40123, 40153, 40182, 40212, 40241, 40271, 40300, 40330, 40359, 40389, + 40418, 40448, 40477, 40507, 40536, 40566, 40595, 40625, 40655, 40685, 40714, 40744, 40773, 40803, 40832, 40862, 40892, 40921, 40951, 40980, + 41009, 41039, 41068, 41098, 41127, 41157, 41186, 41216, 41245, 41275, 41304, 41334, 41364, 41393, 41422, 41452, 41481, 41511, 41540, 41570, + 41599, 41629, 41658, 41688, 41718, 41748, 41777, 41807, 41836, 41865, 41894, 41924, 41953, 41983, 42012, 42042, 42072, 42102, 42131, 42161, + 42190, 42220, 42249, 42279, 42308, 42337, 42367, 42397, 42426, 42456, 42485, 42515, 42545, 42574, 42604, 42633, 42662, 42692, 42721, 42751, + 42780, 42810, 42839, 42869, 42899, 42929, 42958, 42988, 43017, 43046, 43076, 43105, 43135, 43164, 43194, 43223, 43253, 43283, 43312, 43342, + 43371, 43401, 43430, 43460, 43489, 43519, 43548, 43578, 43607, 43637, 43666, 43696, 43726, 43755, 43785, 43814, 43844, 43873, 43903, 43932, + 43962, 43991, 44021, 44050, 44080, 44109, 44139, 44169, 44198, 44228, 44258, 44287, 44317, 44346, 44375, 44405, 44434, 44464, 44493, 44523, + 44553, 44582, 44612, 44641, 44671, 44700, 44730, 44759, 44788, 44818, 44847, 44877, 44906, 44936, 44966, 44996, 45025, 45055, 45084, 45114, + 45143, 45172, 45202, 45231, 45261, 45290, 45320, 45350, 45380, 45409, 45439, 45468, 45498, 45527, 45556, 45586, 45615, 45644, 45674, 45704, + 45733, 45763, 45793, 45823, 45852, 45882, 45911, 45940, 45970, 45999, 46028, 46058, 46088, 46117, 46147, 46177, 46206, 46236, 46265, 46295, + 46324, 46354, 46383, 46413, 46442, 46472, 46501, 46531, 46560, 46590, 46620, 46649, 46679, 46708, 46738, 46767, 46797, 46826, 46856, 46885, + 46915, 46944, 46974, 47003, 47033, 47063, 47092, 47122, 47151, 47181, 47210, 47240, 47269, 47298, 47328, 47357, 47387, 47417, 47446, 47476, + 47506, 47535, 47565, 47594, 47624, 47653, 47682, 47712, 47741, 47771, 47800, 47830, 47860, 47890, 47919, 47949, 47978, 48008, 48037, 48066, + 48096, 48125, 48155, 48184, 48214, 48244, 48273, 48303, 48333, 48362, 48392, 48421, 48450, 48480, 48509, 48538, 48568, 48598, 48627, 48657, + 48687, 48717, 48746, 48776, 48805, 48834, 48864, 48893, 48922, 48952, 48982, 49011, 49041, 49071, 49100, 49130, 49160, 49189, 49218, 49248, + 49277, 49306, 49336, 49365, 49395, 49425, 49455, 49484, 49514, 49543, 49573, 49602, 49632, 49661, 49690, 49720, 49749, 49779, 49809, 49838, + 49868, 49898, 49927, 49957, 49986, 50016, 50045, 50075, 50104, 50133, 50163, 50192, 50222, 50252, 50281, 50311, 50340, 50370, 50400, 50429, + 50459, 50488, 50518, 50547, 50576, 50606, 50635, 50665, 50694, 50724, 50754, 50784, 50813, 50843, 50872, 50902, 50931, 50960, 50990, 51019, + 51049, 51078, 51108, 51138, 51167, 51197, 51227, 51256, 51286, 51315, 51345, 51374, 51403, 51433, 51462, 51492, 51522, 51552, 51582, 51611, + 51641, 51670, 51699, 51729, 51758, 51787, 51816, 51846, 51876, 51906, 51936, 51965, 51995, 52025, 52054, 52083, 52113, 52142, 52171, 52200, + 52230, 52260, 52290, 52319, 52349, 52379, 52408, 52438, 52467, 52497, 52526, 52555, 52585, 52614, 52644, 52673, 52703, 52733, 52762, 52792, + 52822, 52851, 52881, 52910, 52939, 52969, 52998, 53028, 53057, 53087, 53116, 53146, 53176, 53205, 53235, 53264, 53294, 53324, 53353, 53383, + 53412, 53441, 53471, 53500, 53530, 53559, 53589, 53619, 53648, 53678, 53708, 53737, 53767, 53796, 53825, 53855, 53884, 53913, 53943, 53973, + 54003, 54032, 54062, 54092, 54121, 54151, 54180, 54209, 54239, 54268, 54297, 54327, 54357, 54387, 54416, 54446, 54476, 54505, 54535, 54564, + 54593, 54623, 54652, 54681, 54711, 54741, 54770, 54800, 54830, 54859, 54889, 54919, 54948, 54977, 55007, 55036, 55066, 55095, 55125, 55154, + 55184, 55213, 55243, 55273, 55302, 55332, 55361, 55391, 55420, 55450, 55479, 55508, 55538, 55567, 55597, 55627, 55657, 55686, 55716, 55745, + 55775, 55804, 55834, 55863, 55892, 55922, 55951, 55981, 56011, 56040, 56070, 56100, 56129, 56159, 56188, 56218, 56247, 56276, 56306, 56335, + 56365, 56394, 56424, 56454, 56483, 56513, 56543, 56572, 56601, 56631, 56660, 56690, 56719, 56749, 56778, 56808, 56837, 56867, 56897, 56926, + 56956, 56985, 57015, 57044, 57074, 57103, 57133, 57162, 57192, 57221, 57251, 57280, 57310, 57340, 57369, 57399, 57429, 57458, 57487, 57517, + 57546, 57576, 57605, 57634, 57664, 57694, 57723, 57753, 57783, 57813, 57842, 57871, 57901, 57930, 57959, 57989, 58018, 58048, 58077, 58107, + 58137, 58167, 58196, 58226, 58255, 58285, 58314, 58343, 58373, 58402, 58432, 58461, 58491, 58521, 58551, 58580, 58610, 58639, 58669, 58698, + 58727, 58757, 58786, 58816, 58845, 58875, 58905, 58934, 58964, 58994, 59023, 59053, 59082, 59111, 59141, 59170, 59200, 59229, 59259, 59288, + 59318, 59348, 59377, 59407, 59436, 59466, 59495, 59525, 59554, 59584, 59613, 59643, 59672, 59702, 59731, 59761, 59791, 59820, 59850, 59879, + 59909, 59939, 59968, 59997, 60027, 60056, 60086, 60115, 60145, 60174, 60204, 60234, 60264, 60293, 60323, 60352, 60381, 60411, 60440, 60469, + 60499, 60528, 60558, 60588, 60618, 60648, 60677, 60707, 60736, 60765, 60795, 60824, 60853, 60883, 60912, 60942, 60972, 61002, 61031, 61061, + 61090, 61120, 61149, 61179, 61208, 61237, 61267, 61296, 61326, 61356, 61385, 61415, 61445, 61474, 61504, 61533, 61563, 61592, 61621, 61651, + 61680, 61710, 61739, 61769, 61799, 61828, 61858, 61888, 61917, 61947, 61976, 62006, 62035, 62064, 62094, 62123, 62153, 62182, 62212, 62242, + 62271, 62301, 62331, 62360, 62390, 62419, 62448, 62478, 62507, 62537, 62566, 62596, 62625, 62655, 62685, 62715, 62744, 62774, 62803, 62832, + 62862, 62891, 62921, 62950, 62980, 63009, 63039, 63069, 63099, 63128, 63157, 63187, 63216, 63246, 63275, 63305, 63334, 63363, 63393, 63423, + 63453, 63482, 63512, 63541, 63571, 63600, 63630, 63659, 63689, 63718, 63747, 63777, 63807, 63836, 63866, 63895, 63925, 63955, 63984, 64014, + 64043, 64073, 64102, 64131, 64161, 64190, 64220, 64249, 64279, 64309, 64339, 64368, 64398, 64427, 64457, 64486, 64515, 64545, 64574, 64603, + 64633, 64663, 64692, 64722, 64752, 64782, 64811, 64841, 64870, 64899, 64929, 64958, 64987, 65017, 65047, 65076, 65106, 65136, 65166, 65195, + 65225, 65254, 65283, 65313, 65342, 65371, 65401, 65431, 65460, 65490, 65520, 65549, 65579, 65608, 65638, 65667, 65697, 65726, 65755, 65785, + 65815, 65844, 65874, 65903, 65933, 65963, 65992, 66022, 66051, 66081, 66110, 66140, 66169, 66199, 66228, 66258, 66287, 66317, 66346, 66376, + 66405, 66435, 66465, 66494, 66524, 66553, 66583, 66612, 66641, 66671, 66700, 66730, 66760, 66789, 66819, 66849, 66878, 66908, 66937, 66967, + 66996, 67025, 67055, 67084, 67114, 67143, 67173, 67203, 67233, 67262, 67292, 67321, 67351, 67380, 67409, 67439, 67468, 67497, 67527, 67557, + 67587, 67617, 67646, 67676, 67705, 67735, 67764, 67793, 67823, 67852, 67882, 67911, 67941, 67971, 68000, 68030, 68060, 68089, 68119, 68148, + 68177, 68207, 68236, 68266, 68295, 68325, 68354, 68384, 68414, 68443, 68473, 68502, 68532, 68561, 68591, 68620, 68650, 68679, 68708, 68738, + 68768, 68797, 68827, 68857, 68886, 68916, 68946, 68975, 69004, 69034, 69063, 69092, 69122, 69152, 69181, 69211, 69240, 69270, 69300, 69330, + 69359, 69388, 69418, 69447, 69476, 69506, 69535, 69565, 69595, 69624, 69654, 69684, 69713, 69743, 69772, 69802, 69831, 69861, 69890, 69919, + 69949, 69978, 70008, 70038, 70067, 70097, 70126, 70156, 70186, 70215, 70245, 70274, 70303, 70333, 70362, 70392, 70421, 70451, 70481, 70510, + 70540, 70570, 70599, 70629, 70658, 70687, 70717, 70746, 70776, 70805, 70835, 70864, 70894, 70924, 70954, 70983, 71013, 71042, 71071, 71101, + 71130, 71159, 71189, 71218, 71248, 71278, 71308, 71337, 71367, 71397, 71426, 71455, 71485, 71514, 71543, 71573, 71602, 71632, 71662, 71691, + 71721, 71751, 71781, 71810, 71839, 71869, 71898, 71927, 71957, 71986, 72016, 72046, 72075, 72105, 72135, 72164, 72194, 72223, 72253, 72282, + 72311, 72341, 72370, 72400, 72429, 72459, 72489, 72518, 72548, 72577, 72607, 72637, 72666, 72695, 72725, 72754, 72784, 72813, 72843, 72872, + 72902, 72931, 72961, 72991, 73020, 73050, 73080, 73109, 73139, 73168, 73197, 73227, 73256, 73286, 73315, 73345, 73375, 73404, 73434, 73464, + 73493, 73523, 73552, 73581, 73611, 73640, 73669, 73699, 73729, 73758, 73788, 73818, 73848, 73877, 73907, 73936, 73965, 73995, 74024, 74053, + 74083, 74113, 74142, 74172, 74202, 74231, 74261, 74291, 74320, 74349, 74379, 74408, 74437, 74467, 74497, 74526, 74556, 74586, 74615, 74645, + 74675, 74704, 74733, 74763, 74792, 74822, 74851, 74881, 74910, 74940, 74969, 74999, 75029, 75058, 75088, 75117, 75147, 75176, 75206, 75235, + 75264, 75294, 75323, 75353, 75383, 75412, 75442, 75472, 75501, 75531, 75560, 75590, 75619, 75648, 75678, 75707, 75737, 75766, 75796, 75826, + 75856, 75885, 75915, 75944, 75974, 76003, 76032, 76062, 76091, 76121, 76150, 76180, 76210, 76239, 76269, 76299, 76328, 76358, 76387, 76416, + 76446, 76475, 76505, 76534, 76564, 76593, 76623, 76653, 76682, 76712, 76741, 76771, 76801, 76830, 76859, 76889, 76918, 76948, 76977, 77007, + 77036, 77066, 77096, 77125, 77155, 77185, 77214, 77243, 77273, 77302, 77332, 77361, 77390, 77420, 77450, 77479, 77509, 77539, 77569, 77598, + 77627, 77657, 77686, 77715, 77745, 77774, 77804, 77833, 77863, 77893, 77923, 77952, 77982, 78011, 78041, 78070, 78099, 78129, 78158, 78188, + 78217, 78247, 78277, 78307, 78336, 78366, 78395, 78425, 78454, 78483, 78513, 78542, 78572, 78601, 78631, 78661, 78690, 78720, 78750, 78779, + 78808, 78838, 78867, 78897, 78926, 78956, 78985, 79015, 79044, 79074, 79104, 79133, 79163, 79192, 79222, 79251, 79281, 79310, 79340, 79369, + 79399, 79428, 79458, 79487, 79517, 79546, 79576, 79606, 79635, 79665, 79695, 79724, 79753, 79783, 79812, 79841, 79871, 79900, 79930, 79960, + 79990]; + + +},{"../main":548,"object-assign":437}],548:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Calendars for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var assign = _dereq_('object-assign'); + + +function Calendars() { + this.regionalOptions = []; + this.regionalOptions[''] = { + invalidCalendar: 'Calendar {0} not found', + invalidDate: 'Invalid {0} date', + invalidMonth: 'Invalid {0} month', + invalidYear: 'Invalid {0} year', + differentCalendars: 'Cannot mix {0} and {1} dates' + }; + this.local = this.regionalOptions['']; + this.calendars = {}; + this._localCals = {}; +} + +/** Create the calendars plugin. +

Provides support for various world calendars in a consistent manner.

+ @class Calendars + @example _exports.instance('julian').newDate(2014, 12, 25) */ +assign(Calendars.prototype, { + + /** Obtain a calendar implementation and localisation. + @memberof Calendars + @param [name='gregorian'] {string} The name of the calendar, e.g. 'gregorian', 'persian', 'islamic'. + @param [language=''] {string} The language code to use for localisation (default is English). + @return {Calendar} The calendar and localisation. + @throws Error if calendar not found. */ + instance: function(name, language) { + name = (name || 'gregorian').toLowerCase(); + language = language || ''; + var cal = this._localCals[name + '-' + language]; + if (!cal && this.calendars[name]) { + cal = new this.calendars[name](language); + this._localCals[name + '-' + language] = cal; + } + if (!cal) { + throw (this.local.invalidCalendar || this.regionalOptions[''].invalidCalendar). + replace(/\{0\}/, name); + } + return cal; + }, + + /** Create a new date - for today if no other parameters given. + @memberof Calendars + @param year {CDate|number} The date to copy or the year for the date. + @param [month] {number} The month for the date. + @param [day] {number} The day for the date. + @param [calendar='gregorian'] {BaseCalendar|string} The underlying calendar or the name of the calendar. + @param [language=''] {string} The language to use for localisation (default English). + @return {CDate} The new date. + @throws Error if an invalid date. */ + newDate: function(year, month, day, calendar, language) { + calendar = (year != null && year.year ? year.calendar() : (typeof calendar === 'string' ? + this.instance(calendar, language) : calendar)) || this.instance(); + return calendar.newDate(year, month, day); + }, + + /** A simple digit substitution function for localising numbers via the Calendar digits option. + @member Calendars + @param digits {string[]} The substitute digits, for 0 through 9. + @return {function} The substitution function. */ + substituteDigits: function(digits) { + return function(value) { + return (value + '').replace(/[0-9]/g, function(digit) { + return digits[digit]; + }); + } + }, + + /** Digit substitution function for localising Chinese style numbers via the Calendar digits option. + @member Calendars + @param digits {string[]} The substitute digits, for 0 through 9. + @param powers {string[]} The characters denoting powers of 10, i.e. 1, 10, 100, 1000. + @return {function} The substitution function. */ + substituteChineseDigits: function(digits, powers) { + return function(value) { + var localNumber = ''; + var power = 0; + while (value > 0) { + var units = value % 10; + localNumber = (units === 0 ? '' : digits[units] + powers[power]) + localNumber; + power++; + value = Math.floor(value / 10); + } + if (localNumber.indexOf(digits[1] + powers[1]) === 0) { + localNumber = localNumber.substr(1); + } + return localNumber || digits[0]; + } + } +}); + +/** Generic date, based on a particular calendar. + @class CDate + @param calendar {BaseCalendar} The underlying calendar implementation. + @param year {number} The year for this date. + @param month {number} The month for this date. + @param day {number} The day for this date. + @return {CDate} The date object. + @throws Error if an invalid date. */ +function CDate(calendar, year, month, day) { + this._calendar = calendar; + this._year = year; + this._month = month; + this._day = day; + if (this._calendar._validateLevel === 0 && + !this._calendar.isValid(this._year, this._month, this._day)) { + throw (_exports.local.invalidDate || _exports.regionalOptions[''].invalidDate). + replace(/\{0\}/, this._calendar.local.name); + } +} + +/** Pad a numeric value with leading zeroes. + @private + @param value {number} The number to format. + @param length {number} The minimum length. + @return {string} The formatted number. */ +function pad(value, length) { + value = '' + value; + return '000000'.substring(0, length - value.length) + value; +} + +assign(CDate.prototype, { + + /** Create a new date. + @memberof CDate + @param [year] {CDate|number} The date to copy or the year for the date (default this date). + @param [month] {number} The month for the date. + @param [day] {number} The day for the date. + @return {CDate} The new date. + @throws Error if an invalid date. */ + newDate: function(year, month, day) { + return this._calendar.newDate((year == null ? this : year), month, day); + }, + + /** Set or retrieve the year for this date. + @memberof CDate + @param [year] {number} The year for the date. + @return {number|CDate} The date's year (if no parameter) or the updated date. + @throws Error if an invalid date. */ + year: function(year) { + return (arguments.length === 0 ? this._year : this.set(year, 'y')); + }, + + /** Set or retrieve the month for this date. + @memberof CDate + @param [month] {number} The month for the date. + @return {number|CDate} The date's month (if no parameter) or the updated date. + @throws Error if an invalid date. */ + month: function(month) { + return (arguments.length === 0 ? this._month : this.set(month, 'm')); + }, + + /** Set or retrieve the day for this date. + @memberof CDate + @param [day] {number} The day for the date. + @return {number|CData} The date's day (if no parameter) or the updated date. + @throws Error if an invalid date. */ + day: function(day) { + return (arguments.length === 0 ? this._day : this.set(day, 'd')); + }, + + /** Set new values for this date. + @memberof CDate + @param year {number} The year for the date. + @param month {number} The month for the date. + @param day {number} The day for the date. + @return {CDate} The updated date. + @throws Error if an invalid date. */ + date: function(year, month, day) { + if (!this._calendar.isValid(year, month, day)) { + throw (_exports.local.invalidDate || _exports.regionalOptions[''].invalidDate). + replace(/\{0\}/, this._calendar.local.name); + } + this._year = year; + this._month = month; + this._day = day; + return this; + }, + + /** Determine whether this date is in a leap year. + @memberof CDate + @return {boolean} true if this is a leap year, false if not. */ + leapYear: function() { + return this._calendar.leapYear(this); + }, + + /** Retrieve the epoch designator for this date, e.g. BCE or CE. + @memberof CDate + @return {string} The current epoch. */ + epoch: function() { + return this._calendar.epoch(this); + }, + + /** Format the year, if not a simple sequential number. + @memberof CDate + @return {string} The formatted year. */ + formatYear: function() { + return this._calendar.formatYear(this); + }, + + /** Retrieve the month of the year for this date, + i.e. the month's position within a numbered year. + @memberof CDate + @return {number} The month of the year: minMonth to months per year. */ + monthOfYear: function() { + return this._calendar.monthOfYear(this); + }, + + /** Retrieve the week of the year for this date. + @memberof CDate + @return {number} The week of the year: 1 to weeks per year. */ + weekOfYear: function() { + return this._calendar.weekOfYear(this); + }, + + /** Retrieve the number of days in the year for this date. + @memberof CDate + @return {number} The number of days in this year. */ + daysInYear: function() { + return this._calendar.daysInYear(this); + }, + + /** Retrieve the day of the year for this date. + @memberof CDate + @return {number} The day of the year: 1 to days per year. */ + dayOfYear: function() { + return this._calendar.dayOfYear(this); + }, + + /** Retrieve the number of days in the month for this date. + @memberof CDate + @return {number} The number of days. */ + daysInMonth: function() { + return this._calendar.daysInMonth(this); + }, + + /** Retrieve the day of the week for this date. + @memberof CDate + @return {number} The day of the week: 0 to number of days - 1. */ + dayOfWeek: function() { + return this._calendar.dayOfWeek(this); + }, + + /** Determine whether this date is a week day. + @memberof CDate + @return {boolean} true if a week day, false if not. */ + weekDay: function() { + return this._calendar.weekDay(this); + }, + + /** Retrieve additional information about this date. + @memberof CDate + @return {object} Additional information - contents depends on calendar. */ + extraInfo: function() { + return this._calendar.extraInfo(this); + }, + + /** Add period(s) to a date. + @memberof CDate + @param offset {number} The number of periods to adjust by. + @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. + @return {CDate} The updated date. */ + add: function(offset, period) { + return this._calendar.add(this, offset, period); + }, + + /** Set a portion of the date. + @memberof CDate + @param value {number} The new value for the period. + @param period {string} One of 'y' for year, 'm' for month, 'd' for day. + @return {CDate} The updated date. + @throws Error if not a valid date. */ + set: function(value, period) { + return this._calendar.set(this, value, period); + }, + + /** Compare this date to another date. + @memberof CDate + @param date {CDate} The other date. + @return {number} -1 if this date is before the other date, + 0 if they are equal, or +1 if this date is after the other date. */ + compareTo: function(date) { + if (this._calendar.name !== date._calendar.name) { + throw (_exports.local.differentCalendars || _exports.regionalOptions[''].differentCalendars). + replace(/\{0\}/, this._calendar.local.name).replace(/\{1\}/, date._calendar.local.name); + } + var c = (this._year !== date._year ? this._year - date._year : + this._month !== date._month ? this.monthOfYear() - date.monthOfYear() : + this._day - date._day); + return (c === 0 ? 0 : (c < 0 ? -1 : +1)); + }, + + /** Retrieve the calendar backing this date. + @memberof CDate + @return {BaseCalendar} The calendar implementation. */ + calendar: function() { + return this._calendar; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof CDate + @return {number} The equivalent Julian date. */ + toJD: function() { + return this._calendar.toJD(this); + }, + + /** Create a new date from a Julian date. + @memberof CDate + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + return this._calendar.fromJD(jd); + }, + + /** Convert this date to a standard (Gregorian) JavaScript Date. + @memberof CDate + @return {Date} The equivalent JavaScript date. */ + toJSDate: function() { + return this._calendar.toJSDate(this); + }, + + /** Create a new date from a standard (Gregorian) JavaScript Date. + @memberof CDate + @param jsd {Date} The JavaScript date to convert. + @return {CDate} The equivalent date. */ + fromJSDate: function(jsd) { + return this._calendar.fromJSDate(jsd); + }, + + /** Convert to a string for display. + @memberof CDate + @return {string} This date as a string. */ + toString: function() { + return (this.year() < 0 ? '-' : '') + pad(Math.abs(this.year()), 4) + + '-' + pad(this.month(), 2) + '-' + pad(this.day(), 2); + } +}); + +/** Basic functionality for all calendars. + Other calendars should extend this: +
OtherCalendar.prototype = new BaseCalendar;
+ @class BaseCalendar */ +function BaseCalendar() { + this.shortYearCutoff = '+10'; +} + +assign(BaseCalendar.prototype, { + _validateLevel: 0, // "Stack" to turn validation on/off + + /** Create a new date within this calendar - today if no parameters given. + @memberof BaseCalendar + @param year {CDate|number} The date to duplicate or the year for the date. + @param [month] {number} The month for the date. + @param [day] {number} The day for the date. + @return {CDate} The new date. + @throws Error if not a valid date or a different calendar used. */ + newDate: function(year, month, day) { + if (year == null) { + return this.today(); + } + if (year.year) { + this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + day = year.day(); + month = year.month(); + year = year.year(); + } + return new CDate(this, year, month, day); + }, + + /** Create a new date for today. + @memberof BaseCalendar + @return {CDate} Today's date. */ + today: function() { + return this.fromJSDate(new Date()); + }, + + /** Retrieve the epoch designator for this date. + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {string} The current epoch. + @throws Error if an invalid year or a different calendar used. */ + epoch: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, + _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); + return (date.year() < 0 ? this.local.epochs[0] : this.local.epochs[1]); + }, + + /** Format the year, if not a simple sequential number + @memberof BaseCalendar + @param year {CDate|number} The date to format or the year to format. + @return {string} The formatted year. + @throws Error if an invalid year or a different calendar used. */ + formatYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, + _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); + return (date.year() < 0 ? '-' : '') + pad(Math.abs(date.year()), 4) + }, + + /** Retrieve the number of months in a year. + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of months. + @throws Error if an invalid year or a different calendar used. */ + monthsInYear: function(year) { + this._validate(year, this.minMonth, this.minDay, + _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); + return 12; + }, + + /** Calculate the month's ordinal position within the year - + for those calendars that don't start at month 1! + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param month {number} The month to examine. + @return {number} The ordinal position, starting from minMonth. + @throws Error if an invalid year/month or a different calendar used. */ + monthOfYear: function(year, month) { + var date = this._validate(year, month, this.minDay, + _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); + return (date.month() + this.monthsInYear(date) - this.firstMonth) % + this.monthsInYear(date) + this.minMonth; + }, + + /** Calculate actual month from ordinal position, starting from minMonth. + @memberof BaseCalendar + @param year {number} The year to examine. + @param ord {number} The month's ordinal position. + @return {number} The month's number. + @throws Error if an invalid year/month. */ + fromMonthOfYear: function(year, ord) { + var m = (ord + this.firstMonth - 2 * this.minMonth) % + this.monthsInYear(year) + this.minMonth; + this._validate(year, m, this.minDay, + _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); + return m; + }, + + /** Retrieve the number of days in a year. + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {number} The number of days. + @throws Error if an invalid year or a different calendar used. */ + daysInYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, + _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); + return (this.leapYear(date) ? 366 : 365); + }, + + /** Retrieve the day of the year for a date. + @memberof BaseCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The day of the year. + @throws Error if an invalid date or a different calendar used. */ + dayOfYear: function(year, month, day) { + var date = this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + return date.toJD() - this.newDate(date.year(), + this.fromMonthOfYear(date.year(), this.minMonth), this.minDay).toJD() + 1; + }, + + /** Retrieve the number of days in a week. + @memberof BaseCalendar + @return {number} The number of days. */ + daysInWeek: function() { + return 7; + }, + + /** Retrieve the day of the week for a date. + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The day of the week: 0 to number of days - 1. + @throws Error if an invalid date or a different calendar used. */ + dayOfWeek: function(year, month, day) { + var date = this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + return (Math.floor(this.toJD(date)) + 2) % this.daysInWeek(); + }, + + /** Retrieve additional information about a date. + @memberof BaseCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {object} Additional information - contents depends on calendar. + @throws Error if an invalid date or a different calendar used. */ + extraInfo: function(year, month, day) { + this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + return {}; + }, + + /** Add period(s) to a date. + Cater for no year zero. + @memberof BaseCalendar + @param date {CDate} The starting date. + @param offset {number} The number of periods to adjust by. + @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. + @return {CDate} The updated date. + @throws Error if a different calendar used. */ + add: function(date, offset, period) { + this._validate(date, this.minMonth, this.minDay, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + return this._correctAdd(date, this._add(date, offset, period), offset, period); + }, + + /** Add period(s) to a date. + @memberof BaseCalendar + @private + @param date {CDate} The starting date. + @param offset {number} The number of periods to adjust by. + @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. + @return {CDate} The updated date. */ + _add: function(date, offset, period) { + this._validateLevel++; + if (period === 'd' || period === 'w') { + var jd = date.toJD() + offset * (period === 'w' ? this.daysInWeek() : 1); + var d = date.calendar().fromJD(jd); + this._validateLevel--; + return [d.year(), d.month(), d.day()]; + } + try { + var y = date.year() + (period === 'y' ? offset : 0); + var m = date.monthOfYear() + (period === 'm' ? offset : 0); + var d = date.day();// + (period === 'd' ? offset : 0) + + //(period === 'w' ? offset * this.daysInWeek() : 0); + var resyncYearMonth = function(calendar) { + while (m < calendar.minMonth) { + y--; + m += calendar.monthsInYear(y); + } + var yearMonths = calendar.monthsInYear(y); + while (m > yearMonths - 1 + calendar.minMonth) { + y++; + m -= yearMonths; + yearMonths = calendar.monthsInYear(y); + } + }; + if (period === 'y') { + if (date.month() !== this.fromMonthOfYear(y, m)) { // Hebrew + m = this.newDate(y, date.month(), this.minDay).monthOfYear(); + } + m = Math.min(m, this.monthsInYear(y)); + d = Math.min(d, this.daysInMonth(y, this.fromMonthOfYear(y, m))); + } + else if (period === 'm') { + resyncYearMonth(this); + d = Math.min(d, this.daysInMonth(y, this.fromMonthOfYear(y, m))); + } + var ymd = [y, this.fromMonthOfYear(y, m), d]; + this._validateLevel--; + return ymd; + } + catch (e) { + this._validateLevel--; + throw e; + } + }, + + /** Correct a candidate date after adding period(s) to a date. + Handle no year zero if necessary. + @memberof BaseCalendar + @private + @param date {CDate} The starting date. + @param ymd {number[]} The added date. + @param offset {number} The number of periods to adjust by. + @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. + @return {CDate} The updated date. */ + _correctAdd: function(date, ymd, offset, period) { + if (!this.hasYearZero && (period === 'y' || period === 'm')) { + if (ymd[0] === 0 || // In year zero + (date.year() > 0) !== (ymd[0] > 0)) { // Crossed year zero + var adj = {y: [1, 1, 'y'], m: [1, this.monthsInYear(-1), 'm'], + w: [this.daysInWeek(), this.daysInYear(-1), 'd'], + d: [1, this.daysInYear(-1), 'd']}[period]; + var dir = (offset < 0 ? -1 : +1); + ymd = this._add(date, offset * adj[0] + dir * adj[1], adj[2]); + } + } + return date.date(ymd[0], ymd[1], ymd[2]); + }, + + /** Set a portion of the date. + @memberof BaseCalendar + @param date {CDate} The starting date. + @param value {number} The new value for the period. + @param period {string} One of 'y' for year, 'm' for month, 'd' for day. + @return {CDate} The updated date. + @throws Error if an invalid date or a different calendar used. */ + set: function(date, value, period) { + this._validate(date, this.minMonth, this.minDay, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + var y = (period === 'y' ? value : date.year()); + var m = (period === 'm' ? value : date.month()); + var d = (period === 'd' ? value : date.day()); + if (period === 'y' || period === 'm') { + d = Math.min(d, this.daysInMonth(y, m)); + } + return date.date(y, m, d); + }, + + /** Determine whether a date is valid for this calendar. + @memberof BaseCalendar + @param year {number} The year to examine. + @param month {number} The month to examine. + @param day {number} The day to examine. + @return {boolean} true if a valid date, false if not. */ + isValid: function(year, month, day) { + this._validateLevel++; + var valid = (this.hasYearZero || year !== 0); + if (valid) { + var date = this.newDate(year, month, this.minDay); + valid = (month >= this.minMonth && month - this.minMonth < this.monthsInYear(date)) && + (day >= this.minDay && day - this.minDay < this.daysInMonth(date)); + } + this._validateLevel--; + return valid; + }, + + /** Convert the date to a standard (Gregorian) JavaScript Date. + @memberof BaseCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {Date} The equivalent JavaScript date. + @throws Error if an invalid date or a different calendar used. */ + toJSDate: function(year, month, day) { + var date = this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + return _exports.instance().fromJD(this.toJD(date)).toJSDate(); + }, + + /** Convert the date from a standard (Gregorian) JavaScript Date. + @memberof BaseCalendar + @param jsd {Date} The JavaScript date. + @return {CDate} The equivalent calendar date. */ + fromJSDate: function(jsd) { + return this.fromJD(_exports.instance().fromJSDate(jsd).toJD()); + }, + + /** Check that a candidate date is from the same calendar and is valid. + @memberof BaseCalendar + @private + @param year {CDate|number} The date to validate or the year to validate. + @param [month] {number} The month to validate. + @param [day] {number} The day to validate. + @param error {string} Rrror message if invalid. + @throws Error if different calendars used or invalid date. */ + _validate: function(year, month, day, error) { + if (year.year) { + if (this._validateLevel === 0 && this.name !== year.calendar().name) { + throw (_exports.local.differentCalendars || _exports.regionalOptions[''].differentCalendars). + replace(/\{0\}/, this.local.name).replace(/\{1\}/, year.calendar().local.name); + } + return year; + } + try { + this._validateLevel++; + if (this._validateLevel === 1 && !this.isValid(year, month, day)) { + throw error.replace(/\{0\}/, this.local.name); + } + var date = this.newDate(year, month, day); + this._validateLevel--; + return date; + } + catch (e) { + this._validateLevel--; + throw e; + } + } +}); + +/** Implementation of the Proleptic Gregorian Calendar. + See http://en.wikipedia.org/wiki/Gregorian_calendar + and http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar. + @class GregorianCalendar + @augments BaseCalendar + @param [language=''] {string} The language code (default English) for localisation. */ +function GregorianCalendar(language) { + this.local = this.regionalOptions[language] || this.regionalOptions['']; +} + +GregorianCalendar.prototype = new BaseCalendar; + +assign(GregorianCalendar.prototype, { + /** The calendar name. + @memberof GregorianCalendar */ + name: 'Gregorian', + /** Julian date of start of Gregorian epoch: 1 January 0001 CE. + @memberof GregorianCalendar */ + jdEpoch: 1721425.5, + /** Days per month in a common year. + @memberof GregorianCalendar */ + daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + /** true if has a year zero, false if not. + @memberof GregorianCalendar */ + hasYearZero: false, + /** The minimum month number. + @memberof GregorianCalendar */ + minMonth: 1, + /** The first month in the year. + @memberof GregorianCalendar */ + firstMonth: 1, + /** The minimum day number. + @memberof GregorianCalendar */ + minDay: 1, + + /** Localisations for the plugin. + Entries are objects indexed by the language code ('' being the default US/English). + Each object has the following attributes. + @memberof GregorianCalendar + @property name {string} The calendar name. + @property epochs {string[]} The epoch names. + @property monthNames {string[]} The long names of the months of the year. + @property monthNamesShort {string[]} The short names of the months of the year. + @property dayNames {string[]} The long names of the days of the week. + @property dayNamesShort {string[]} The short names of the days of the week. + @property dayNamesMin {string[]} The minimal names of the days of the week. + @property dateFormat {string} The date format for this calendar. + See the options on formatDate for details. + @property firstDay {number} The number of the first day of the week, starting at 0. + @property isRTL {number} true if this localisation reads right-to-left. */ + regionalOptions: { // Localisations + '': { + name: 'Gregorian', + epochs: ['BCE', 'CE'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + digits: null, + dateFormat: 'mm/dd/yyyy', + firstDay: 0, + isRTL: false + } + }, + + /** Determine whether this date is in a leap year. + @memberof GregorianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @return {boolean} true if this is a leap year, false if not. + @throws Error if an invalid year or a different calendar used. */ + leapYear: function(year) { + var date = this._validate(year, this.minMonth, this.minDay, + _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); + var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + }, + + /** Determine the week of the year for a date - ISO 8601. + @memberof GregorianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {number} The week of the year, starting from 1. + @throws Error if an invalid date or a different calendar used. */ + weekOfYear: function(year, month, day) { + // Find Thursday of this week starting on Monday + var checkDate = this.newDate(year, month, day); + checkDate.add(4 - (checkDate.dayOfWeek() || 7), 'd'); + return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; + }, + + /** Retrieve the number of days in a month. + @memberof GregorianCalendar + @param year {CDate|number} The date to examine or the year of the month. + @param [month] {number} The month. + @return {number} The number of days in this month. + @throws Error if an invalid month/year or a different calendar used. */ + daysInMonth: function(year, month) { + var date = this._validate(year, month, this.minDay, + _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); + return this.daysPerMonth[date.month() - 1] + + (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); + }, + + /** Determine whether this date is a week day. + @memberof GregorianCalendar + @param year {CDate|number} The date to examine or the year to examine. + @param [month] {number} The month to examine. + @param [day] {number} The day to examine. + @return {boolean} true if a week day, false if not. + @throws Error if an invalid date or a different calendar used. */ + weekDay: function(year, month, day) { + return (this.dayOfWeek(year, month, day) || 7) < 6; + }, + + /** Retrieve the Julian date equivalent for this date, + i.e. days since January 1, 4713 BCE Greenwich noon. + @memberof GregorianCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {number} The equivalent Julian date. + @throws Error if an invalid date or a different calendar used. */ + toJD: function(year, month, day) { + var date = this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + year = date.year(); + month = date.month(); + day = date.day(); + if (year < 0) { year++; } // No year zero + // Jean Meeus algorithm, "Astronomical Algorithms", 1991 + if (month < 3) { + month += 12; + year--; + } + var a = Math.floor(year / 100); + var b = 2 - a + Math.floor(a / 4); + return Math.floor(365.25 * (year + 4716)) + + Math.floor(30.6001 * (month + 1)) + day + b - 1524.5; + }, + + /** Create a new date from a Julian date. + @memberof GregorianCalendar + @param jd {number} The Julian date to convert. + @return {CDate} The equivalent date. */ + fromJD: function(jd) { + // Jean Meeus algorithm, "Astronomical Algorithms", 1991 + var z = Math.floor(jd + 0.5); + var a = Math.floor((z - 1867216.25) / 36524.25); + a = z + 1 + a - Math.floor(a / 4); + var b = a + 1524; + var c = Math.floor((b - 122.1) / 365.25); + var d = Math.floor(365.25 * c); + var e = Math.floor((b - d) / 30.6001); + var day = b - d - Math.floor(e * 30.6001); + var month = e - (e > 13.5 ? 13 : 1); + var year = c - (month > 2.5 ? 4716 : 4715); + if (year <= 0) { year--; } // No year zero + return this.newDate(year, month, day); + }, + + /** Convert this date to a standard (Gregorian) JavaScript Date. + @memberof GregorianCalendar + @param year {CDate|number} The date to convert or the year to convert. + @param [month] {number} The month to convert. + @param [day] {number} The day to convert. + @return {Date} The equivalent JavaScript date. + @throws Error if an invalid date or a different calendar used. */ + toJSDate: function(year, month, day) { + var date = this._validate(year, month, day, + _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); + var jsd = new Date(date.year(), date.month() - 1, date.day()); + jsd.setHours(0); + jsd.setMinutes(0); + jsd.setSeconds(0); + jsd.setMilliseconds(0); + // Hours may be non-zero on daylight saving cut-over: + // > 12 when midnight changeover, but then cannot generate + // midnight datetime, so jump to 1AM, otherwise reset. + jsd.setHours(jsd.getHours() > 12 ? jsd.getHours() + 2 : 0); + return jsd; + }, + + /** Create a new date from a standard (Gregorian) JavaScript Date. + @memberof GregorianCalendar + @param jsd {Date} The JavaScript date to convert. + @return {CDate} The equivalent date. */ + fromJSDate: function(jsd) { + return this.newDate(jsd.getFullYear(), jsd.getMonth() + 1, jsd.getDate()); + } +}); + +// Singleton manager +var _exports = module.exports = new Calendars(); + +// Date template +_exports.cdate = CDate; + +// Base calendar template +_exports.baseCalendar = BaseCalendar; + +// Gregorian calendar implementation +_exports.calendars.gregorian = GregorianCalendar; + + +},{"object-assign":437}],549:[function(_dereq_,module,exports){ +/* + * World Calendars + * https://github.com/alexcjohnson/world-calendars + * + * Batch-converted from kbwood/calendars + * Many thanks to Keith Wood and all of the contributors to the original project! + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* http://keith-wood.name/calendars.html + Calendars extras for jQuery v2.0.2. + Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. + Available under the MIT (http://keith-wood.name/licence.html) license. + Please attribute the author if you use it. */ + +var assign = _dereq_('object-assign'); +var main = _dereq_('./main'); + + +assign(main.regionalOptions[''], { + invalidArguments: 'Invalid arguments', + invalidFormat: 'Cannot format a date from another calendar', + missingNumberAt: 'Missing number at position {0}', + unknownNameAt: 'Unknown name at position {0}', + unexpectedLiteralAt: 'Unexpected literal at position {0}', + unexpectedText: 'Additional text found at end' +}); +main.local = main.regionalOptions['']; + +assign(main.cdate.prototype, { + + /** Format this date. + Found in the jquery.calendars.plus.js module. + @memberof CDate + @param [format] {string} The date format to use (see formatDate). + @param [settings] {object} Options for the formatDate function. + @return {string} The formatted date. */ + formatDate: function(format, settings) { + if (typeof format !== 'string') { + settings = format; + format = ''; + } + return this._calendar.formatDate(format || '', this, settings); + } +}); + +assign(main.baseCalendar.prototype, { + + UNIX_EPOCH: main.instance().newDate(1970, 1, 1).toJD(), + SECS_PER_DAY: 24 * 60 * 60, + TICKS_EPOCH: main.instance().jdEpoch, // 1 January 0001 CE + TICKS_PER_DAY: 24 * 60 * 60 * 10000000, + + /** Date form for ATOM (RFC 3339/ISO 8601). + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + ATOM: 'yyyy-mm-dd', + /** Date form for cookies. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + COOKIE: 'D, dd M yyyy', + /** Date form for full date. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + FULL: 'DD, MM d, yyyy', + /** Date form for ISO 8601. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + ISO_8601: 'yyyy-mm-dd', + /** Date form for Julian date. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + JULIAN: 'J', + /** Date form for RFC 822. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RFC_822: 'D, d M yy', + /** Date form for RFC 850. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RFC_850: 'DD, dd-M-yy', + /** Date form for RFC 1036. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RFC_1036: 'D, d M yy', + /** Date form for RFC 1123. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RFC_1123: 'D, d M yyyy', + /** Date form for RFC 2822. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RFC_2822: 'D, d M yyyy', + /** Date form for RSS (RFC 822). + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + RSS: 'D, d M yy', + /** Date form for Windows ticks. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + TICKS: '!', + /** Date form for Unix timestamp. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + TIMESTAMP: '@', + /** Date form for W3c (ISO 8601). + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar */ + W3C: 'yyyy-mm-dd', + + /** Format a date object into a string value. + The format can be combinations of the following: +
    +
  • d - day of month (no leading zero)
  • +
  • dd - day of month (two digit)
  • +
  • o - day of year (no leading zeros)
  • +
  • oo - day of year (three digit)
  • +
  • D - day name short
  • +
  • DD - day name long
  • +
  • w - week of year (no leading zero)
  • +
  • ww - week of year (two digit)
  • +
  • m - month of year (no leading zero)
  • +
  • mm - month of year (two digit)
  • +
  • M - month name short
  • +
  • MM - month name long
  • +
  • yy - year (two digit)
  • +
  • yyyy - year (four digit)
  • +
  • YYYY - formatted year
  • +
  • J - Julian date (days since January 1, 4713 BCE Greenwich noon)
  • +
  • @ - Unix timestamp (s since 01/01/1970)
  • +
  • ! - Windows ticks (100ns since 01/01/0001)
  • +
  • '...' - literal text
  • +
  • '' - single quote
  • +
+ Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar + @param [format] {string} The desired format of the date (defaults to calendar format). + @param date {CDate} The date value to format. + @param [settings] {object} Addition options, whose attributes include: + @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. + @property [dayNames] {string[]} Names of the days from Sunday. + @property [monthNamesShort] {string[]} Abbreviated names of the months. + @property [monthNames] {string[]} Names of the months. + @property [calculateWeek] {CalendarsPickerCalculateWeek} Function that determines week of the year. + @property [localNumbers=false] {boolean} true to localise numbers (if available), + false to use normal Arabic numerals. + @return {string} The date in the above format. + @throws Errors if the date is from a different calendar. */ + formatDate: function(format, date, settings) { + if (typeof format !== 'string') { + settings = date; + date = format; + format = ''; + } + if (!date) { + return ''; + } + if (date.calendar() !== this) { + throw main.local.invalidFormat || main.regionalOptions[''].invalidFormat; + } + format = format || this.local.dateFormat; + settings = settings || {}; + var dayNamesShort = settings.dayNamesShort || this.local.dayNamesShort; + var dayNames = settings.dayNames || this.local.dayNames; + var monthNumbers = settings.monthNumbers || this.local.monthNumbers; + var monthNamesShort = settings.monthNamesShort || this.local.monthNamesShort; + var monthNames = settings.monthNames || this.local.monthNames; + var calculateWeek = settings.calculateWeek || this.local.calculateWeek; + // Check whether a format character is doubled + var doubled = function(match, step) { + var matches = 1; + while (iFormat + matches < format.length && format.charAt(iFormat + matches) === match) { + matches++; + } + iFormat += matches - 1; + return Math.floor(matches / (step || 1)) > 1; + }; + // Format a number, with leading zeroes if necessary + var formatNumber = function(match, value, len, step) { + var num = '' + value; + if (doubled(match, step)) { + while (num.length < len) { + num = '0' + num; + } + } + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (doubled(match) ? longNames[value] : shortNames[value]); + }; + // Format month number + // (e.g. Chinese calendar needs to account for intercalary months) + var calendar = this; + var formatMonth = function(date) { + return (typeof monthNumbers === 'function') ? + monthNumbers.call(calendar, date, doubled('m')) : + localiseNumbers(formatNumber('m', date.month(), 2)); + }; + // Format a month name, short or long as requested + var formatMonthName = function(date, useLongName) { + if (useLongName) { + return (typeof monthNames === 'function') ? + monthNames.call(calendar, date) : + monthNames[date.month() - calendar.minMonth]; + } else { + return (typeof monthNamesShort === 'function') ? + monthNamesShort.call(calendar, date) : + monthNamesShort[date.month() - calendar.minMonth]; + } + }; + // Localise numbers if requested and available + var digits = this.local.digits; + var localiseNumbers = function(value) { + return (settings.localNumbers && digits ? digits(value) : value); + }; + var output = ''; + var literal = false; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) { + if (format.charAt(iFormat) === "'" && !doubled("'")) { + literal = false; + } + else { + output += format.charAt(iFormat); + } + } + else { + switch (format.charAt(iFormat)) { + case 'd': output += localiseNumbers(formatNumber('d', date.day(), 2)); break; + case 'D': output += formatName('D', date.dayOfWeek(), + dayNamesShort, dayNames); break; + case 'o': output += formatNumber('o', date.dayOfYear(), 3); break; + case 'w': output += formatNumber('w', date.weekOfYear(), 2); break; + case 'm': output += formatMonth(date); break; + case 'M': output += formatMonthName(date, doubled('M')); break; + case 'y': + output += (doubled('y', 2) ? date.year() : + (date.year() % 100 < 10 ? '0' : '') + date.year() % 100); + break; + case 'Y': + doubled('Y', 2); + output += date.formatYear(); + break; + case 'J': output += date.toJD(); break; + case '@': output += (date.toJD() - this.UNIX_EPOCH) * this.SECS_PER_DAY; break; + case '!': output += (date.toJD() - this.TICKS_EPOCH) * this.TICKS_PER_DAY; break; + case "'": + if (doubled("'")) { + output += "'"; + } + else { + literal = true; + } + break; + default: + output += format.charAt(iFormat); + } + } + } + return output; + }, + + /** Parse a string value into a date object. + See formatDate for the possible formats, plus: +
    +
  • * - ignore rest of string
  • +
+ Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar + @param format {string} The expected format of the date ('' for default calendar format). + @param value {string} The date in the above format. + @param [settings] {object} Additional options whose attributes include: + @property [shortYearCutoff] {number} The cutoff year for determining the century. + @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. + @property [dayNames] {string[]} Names of the days from Sunday. + @property [monthNamesShort] {string[]} Abbreviated names of the months. + @property [monthNames] {string[]} Names of the months. + @return {CDate} The extracted date value or null if value is blank. + @throws Errors if the format and/or value are missing, + if the value doesn't match the format, or if the date is invalid. */ + parseDate: function(format, value, settings) { + if (value == null) { + throw main.local.invalidArguments || main.regionalOptions[''].invalidArguments; + } + value = (typeof value === 'object' ? value.toString() : value + ''); + if (value === '') { + return null; + } + format = format || this.local.dateFormat; + settings = settings || {}; + var shortYearCutoff = settings.shortYearCutoff || this.shortYearCutoff; + shortYearCutoff = (typeof shortYearCutoff !== 'string' ? shortYearCutoff : + this.today().year() % 100 + parseInt(shortYearCutoff, 10)); + var dayNamesShort = settings.dayNamesShort || this.local.dayNamesShort; + var dayNames = settings.dayNames || this.local.dayNames; + var parseMonth = settings.parseMonth || this.local.parseMonth; + var monthNumbers = settings.monthNumbers || this.local.monthNumbers; + var monthNamesShort = settings.monthNamesShort || this.local.monthNamesShort; + var monthNames = settings.monthNames || this.local.monthNames; + var jd = -1; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var shortYear = false; + var literal = false; + // Check whether a format character is doubled + var doubled = function(match, step) { + var matches = 1; + while (iFormat + matches < format.length && format.charAt(iFormat + matches) === match) { + matches++; + } + iFormat += matches - 1; + return Math.floor(matches / (step || 1)) > 1; + }; + // Extract a number from the string value + var getNumber = function(match, step) { + var isDoubled = doubled(match, step); + var size = [2, 3, isDoubled ? 4 : 2, isDoubled ? 4 : 2, 10, 11, 20]['oyYJ@!'.indexOf(match) + 1]; + var digits = new RegExp('^-?\\d{1,' + size + '}'); + var num = value.substring(iValue).match(digits); + if (!num) { + throw (main.local.missingNumberAt || main.regionalOptions[''].missingNumberAt). + replace(/\{0\}/, iValue); + } + iValue += num[0].length; + return parseInt(num[0], 10); + }; + // Extract a month number from the string value + var calendar = this; + var getMonthNumber = function() { + if (typeof monthNumbers === 'function') { + doubled('m'); // update iFormat + var month = monthNumbers.call(calendar, value.substring(iValue)); + iValue += month.length; + return month; + } + + return getNumber('m'); + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames, step) { + var names = (doubled(match, step) ? longNames : shortNames); + for (var i = 0; i < names.length; i++) { + if (value.substr(iValue, names[i].length).toLowerCase() === names[i].toLowerCase()) { + iValue += names[i].length; + return i + calendar.minMonth; + } + } + throw (main.local.unknownNameAt || main.regionalOptions[''].unknownNameAt). + replace(/\{0\}/, iValue); + }; + // Extract a month number from the string value + var getMonthName = function() { + if (typeof monthNames === 'function') { + var month = doubled('M') ? + monthNames.call(calendar, value.substring(iValue)) : + monthNamesShort.call(calendar, value.substring(iValue)); + iValue += month.length; + return month; + } + + return getName('M', monthNamesShort, monthNames); + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) !== format.charAt(iFormat)) { + throw (main.local.unexpectedLiteralAt || + main.regionalOptions[''].unexpectedLiteralAt).replace(/\{0\}/, iValue); + } + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) { + if (format.charAt(iFormat) === "'" && !doubled("'")) { + literal = false; + } + else { + checkLiteral(); + } + } + else { + switch (format.charAt(iFormat)) { + case 'd': day = getNumber('d'); break; + case 'D': getName('D', dayNamesShort, dayNames); break; + case 'o': doy = getNumber('o'); break; + case 'w': getNumber('w'); break; + case 'm': month = getMonthNumber(); break; + case 'M': month = getMonthName(); break; + case 'y': + var iSave = iFormat; + shortYear = !doubled('y', 2); + iFormat = iSave; + year = getNumber('y', 2); + break; + case 'Y': year = getNumber('Y', 2); break; + case 'J': + jd = getNumber('J') + 0.5; + if (value.charAt(iValue) === '.') { + iValue++; + getNumber('J'); + } + break; + case '@': jd = getNumber('@') / this.SECS_PER_DAY + this.UNIX_EPOCH; break; + case '!': jd = getNumber('!') / this.TICKS_PER_DAY + this.TICKS_EPOCH; break; + case '*': iValue = value.length; break; + case "'": + if (doubled("'")) { + checkLiteral(); + } + else { + literal = true; + } + break; + default: checkLiteral(); + } + } + } + if (iValue < value.length) { + throw main.local.unexpectedText || main.regionalOptions[''].unexpectedText; + } + if (year === -1) { + year = this.today().year(); + } + else if (year < 100 && shortYear) { + year += (shortYearCutoff === -1 ? 1900 : this.today().year() - + this.today().year() % 100 - (year <= shortYearCutoff ? 0 : 100)); + } + if (typeof month === 'string') { + month = parseMonth.call(this, year, month); + } + if (doy > -1) { + month = 1; + day = doy; + for (var dim = this.daysInMonth(year, month); day > dim; dim = this.daysInMonth(year, month)) { + month++; + day -= dim; + } + } + return (jd > -1 ? this.fromJD(jd) : this.newDate(year, month, day)); + }, + + /** A date may be specified as an exact value or a relative one. + Found in the jquery.calendars.plus.js module. + @memberof BaseCalendar + @param dateSpec {CDate|number|string} The date as an object or string in the given format or + an offset - numeric days from today, or string amounts and periods, e.g. '+1m +2w'. + @param defaultDate {CDate} The date to use if no other supplied, may be null. + @param currentDate {CDate} The current date as a possible basis for relative dates, + if null today is used (optional) + @param [dateFormat] {string} The expected date format - see formatDate. + @param [settings] {object} Additional options whose attributes include: + @property [shortYearCutoff] {number} The cutoff year for determining the century. + @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. + @property [dayNames] {string[]} Names of the days from Sunday. + @property [monthNamesShort] {string[]} Abbreviated names of the months. + @property [monthNames] {string[]} Names of the months. + @return {CDate} The decoded date. */ + determineDate: function(dateSpec, defaultDate, currentDate, dateFormat, settings) { + if (currentDate && typeof currentDate !== 'object') { + settings = dateFormat; + dateFormat = currentDate; + currentDate = null; + } + if (typeof dateFormat !== 'string') { + settings = dateFormat; + dateFormat = ''; + } + var calendar = this; + var offsetString = function(offset) { + try { + return calendar.parseDate(dateFormat, offset, settings); + } + catch (e) { + // Ignore + } + offset = offset.toLowerCase(); + var date = (offset.match(/^c/) && currentDate ? + currentDate.newDate() : null) || calendar.today(); + var pattern = /([+-]?[0-9]+)\s*(d|w|m|y)?/g; + var matches = pattern.exec(offset); + while (matches) { + date.add(parseInt(matches[1], 10), matches[2] || 'd'); + matches = pattern.exec(offset); + } + return date; + }; + defaultDate = (defaultDate ? defaultDate.newDate() : null); + dateSpec = (dateSpec == null ? defaultDate : + (typeof dateSpec === 'string' ? offsetString(dateSpec) : (typeof dateSpec === 'number' ? + (isNaN(dateSpec) || dateSpec === Infinity || dateSpec === -Infinity ? defaultDate : + calendar.today().add(dateSpec, 'd')) : calendar.newDate(dateSpec)))); + return dateSpec; + } +}); + + +},{"./main":548,"object-assign":437}],550:[function(_dereq_,module,exports){ +module.exports = _dereq_('cwise-compiler')({ + args: ['array', { + offset: [1], + array: 0 + }, 'scalar', 'scalar', 'index'], + pre: { + "body": "{}", + "args": [], + "thisVars": [], + "localVars": [] + }, + post: { + "body": "{}", + "args": [], + "thisVars": [], + "localVars": [] + }, + body: { + "body": "{\n var _inline_1_da = _inline_1_arg0_ - _inline_1_arg3_\n var _inline_1_db = _inline_1_arg1_ - _inline_1_arg3_\n if((_inline_1_da >= 0) !== (_inline_1_db >= 0)) {\n _inline_1_arg2_.push(_inline_1_arg4_[0] + 0.5 + 0.5 * (_inline_1_da + _inline_1_db) / (_inline_1_da - _inline_1_db))\n }\n }", + "args": [{ + "name": "_inline_1_arg0_", + "lvalue": false, + "rvalue": true, + "count": 1 + }, { + "name": "_inline_1_arg1_", + "lvalue": false, + "rvalue": true, + "count": 1 + }, { + "name": "_inline_1_arg2_", + "lvalue": false, + "rvalue": true, + "count": 1 + }, { + "name": "_inline_1_arg3_", + "lvalue": false, + "rvalue": true, + "count": 2 + }, { + "name": "_inline_1_arg4_", + "lvalue": false, + "rvalue": true, + "count": 1 + }], + "thisVars": [], + "localVars": ["_inline_1_da", "_inline_1_db"] + }, + funcName: 'zeroCrossings' +}) + +},{"cwise-compiler":134}],551:[function(_dereq_,module,exports){ +"use strict" + +module.exports = findZeroCrossings + +var core = _dereq_("./lib/zc-core") + +function findZeroCrossings(array, level) { + var cross = [] + level = +level || 0.0 + core(array.hi(array.shape[0]-1), cross, level) + return cross +} +},{"./lib/zc-core":550}],552:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * All paths are tuned for maximum scalability of the arrowhead, + * ie throughout arrowwidth=0.3..3 the head is joined smoothly + * to the line, with the line coming from the left and ending at (0, 0). + * + * `backoff` is the distance to move the arrowhead and the end of the line, + * in order that the arrowhead points to the desired place, either at + * the tip of the arrow or (in the case of circle or square) + * the center of the symbol. + * + * `noRotate`, if truthy, says that this arrowhead should not rotate with the + * arrow. That's the case for squares, which should always be straight, and + * circles, for which it's irrelevant. + */ + +module.exports = [ + // no arrow + { + path: '', + backoff: 0 + }, + // wide with flat back + { + path: 'M-2.4,-3V3L0.6,0Z', + backoff: 0.6 + }, + // narrower with flat back + { + path: 'M-3.7,-2.5V2.5L1.3,0Z', + backoff: 1.3 + }, + // barbed + { + path: 'M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z', + backoff: 1.55 + }, + // wide line-drawn + { + path: 'M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z', + backoff: 1.6 + }, + // narrower line-drawn + { + path: 'M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z', + backoff: 2 + }, + // circle + { + path: 'M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z', + backoff: 0, + noRotate: true + }, + // square + { + path: 'M2,2V-2H-2V2Z', + backoff: 0, + noRotate: true + } +]; + +},{}],553:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ARROWPATHS = _dereq_('./arrow_paths'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var cartesianConstants = _dereq_('../../plots/cartesian/constants'); +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + + +module.exports = templatedArray('annotation', { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'calc+arraydraw', + + }, + + text: { + valType: 'string', + + editType: 'calc+arraydraw', + + }, + textangle: { + valType: 'angle', + dflt: 0, + + editType: 'calc+arraydraw', + + }, + font: fontAttrs({ + editType: 'calc+arraydraw', + colorEditType: 'arraydraw', + + }), + width: { + valType: 'number', + min: 1, + dflt: null, + + editType: 'calc+arraydraw', + + }, + height: { + valType: 'number', + min: 1, + dflt: null, + + editType: 'calc+arraydraw', + + }, + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + + editType: 'arraydraw', + + }, + align: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'center', + + editType: 'arraydraw', + + }, + valign: { + valType: 'enumerated', + values: ['top', 'middle', 'bottom'], + dflt: 'middle', + + editType: 'arraydraw', + + }, + bgcolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + editType: 'arraydraw', + + }, + bordercolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + editType: 'arraydraw', + + }, + borderpad: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc+arraydraw', + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc+arraydraw', + + }, + // arrow + showarrow: { + valType: 'boolean', + dflt: true, + + editType: 'calc+arraydraw', + + }, + arrowcolor: { + valType: 'color', + + editType: 'arraydraw', + + }, + arrowhead: { + valType: 'integer', + min: 0, + max: ARROWPATHS.length, + dflt: 1, + + editType: 'arraydraw', + + }, + startarrowhead: { + valType: 'integer', + min: 0, + max: ARROWPATHS.length, + dflt: 1, + + editType: 'arraydraw', + + }, + arrowside: { + valType: 'flaglist', + flags: ['end', 'start'], + extras: ['none'], + dflt: 'end', + + editType: 'arraydraw', + + }, + arrowsize: { + valType: 'number', + min: 0.3, + dflt: 1, + + editType: 'calc+arraydraw', + + }, + startarrowsize: { + valType: 'number', + min: 0.3, + dflt: 1, + + editType: 'calc+arraydraw', + + }, + arrowwidth: { + valType: 'number', + min: 0.1, + + editType: 'calc+arraydraw', + + }, + standoff: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'calc+arraydraw', + + }, + startstandoff: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'calc+arraydraw', + + }, + ax: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + ay: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + axref: { + valType: 'enumerated', + dflt: 'pixel', + values: [ + 'pixel', + cartesianConstants.idRegex.x.toString() + ], + + editType: 'calc', + + }, + ayref: { + valType: 'enumerated', + dflt: 'pixel', + values: [ + 'pixel', + cartesianConstants.idRegex.y.toString() + ], + + editType: 'calc', + + }, + // positioning + xref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.x.toString() + ], + + editType: 'calc', + + }, + x: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'auto', + + editType: 'calc+arraydraw', + + }, + xshift: { + valType: 'number', + dflt: 0, + + editType: 'calc+arraydraw', + + }, + yref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.y.toString() + ], + + editType: 'calc', + + }, + y: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'auto', + + editType: 'calc+arraydraw', + + }, + yshift: { + valType: 'number', + dflt: 0, + + editType: 'calc+arraydraw', + + }, + clicktoshow: { + valType: 'enumerated', + values: [false, 'onoff', 'onout'], + dflt: false, + + editType: 'arraydraw', + + }, + xclick: { + valType: 'any', + + editType: 'arraydraw', + + }, + yclick: { + valType: 'any', + + editType: 'arraydraw', + + }, + hovertext: { + valType: 'string', + + editType: 'arraydraw', + + }, + hoverlabel: { + bgcolor: { + valType: 'color', + + editType: 'arraydraw', + + }, + bordercolor: { + valType: 'color', + + editType: 'arraydraw', + + }, + font: fontAttrs({ + editType: 'arraydraw', + + }), + editType: 'arraydraw' + }, + captureevents: { + valType: 'boolean', + + editType: 'arraydraw', + + }, + editType: 'calc', + + _deprecated: { + ref: { + valType: 'string', + + editType: 'calc', + + } + } +}); + +},{"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750,"../../plots/font_attributes":771,"./arrow_paths":552}],554:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var draw = _dereq_('./draw').draw; + + +module.exports = function calcAutorange(gd) { + var fullLayout = gd._fullLayout; + var annotationList = Lib.filterVisible(fullLayout.annotations); + + if(annotationList.length && gd._fullData.length) { + return Lib.syncOrAsync([draw, annAutorange], gd); + } +}; + +function annAutorange(gd) { + var fullLayout = gd._fullLayout; + + // find the bounding boxes for each of these annotations' + // relative to their anchor points + // use the arrow and the text bg rectangle, + // as the whole anno may include hidden text in its bbox + Lib.filterVisible(fullLayout.annotations).forEach(function(ann) { + var xa = Axes.getFromId(gd, ann.xref); + var ya = Axes.getFromId(gd, ann.yref); + + ann._extremes = {}; + if(xa) calcAxisExpansion(ann, xa); + if(ya) calcAxisExpansion(ann, ya); + }); +} + +function calcAxisExpansion(ann, ax) { + var axId = ax._id; + var letter = axId.charAt(0); + var pos = ann[letter]; + var apos = ann['a' + letter]; + var ref = ann[letter + 'ref']; + var aref = ann['a' + letter + 'ref']; + var padplus = ann['_' + letter + 'padplus']; + var padminus = ann['_' + letter + 'padminus']; + var shift = {x: 1, y: -1}[letter] * ann[letter + 'shift']; + var headSize = 3 * ann.arrowsize * ann.arrowwidth || 0; + var headPlus = headSize + shift; + var headMinus = headSize - shift; + var startHeadSize = 3 * ann.startarrowsize * ann.arrowwidth || 0; + var startHeadPlus = startHeadSize + shift; + var startHeadMinus = startHeadSize - shift; + var extremes; + + if(aref === ref) { + // expand for the arrowhead (padded by arrowhead) + var extremeArrowHead = Axes.findExtremes(ax, [ax.r2c(pos)], { + ppadplus: headPlus, + ppadminus: headMinus + }); + // again for the textbox (padded by textbox) + var extremeText = Axes.findExtremes(ax, [ax.r2c(apos)], { + ppadplus: Math.max(padplus, startHeadPlus), + ppadminus: Math.max(padminus, startHeadMinus) + }); + extremes = { + min: [extremeArrowHead.min[0], extremeText.min[0]], + max: [extremeArrowHead.max[0], extremeText.max[0]] + }; + } else { + startHeadPlus = apos ? startHeadPlus + apos : startHeadPlus; + startHeadMinus = apos ? startHeadMinus - apos : startHeadMinus; + extremes = Axes.findExtremes(ax, [ax.r2c(pos)], { + ppadplus: Math.max(padplus, headPlus, startHeadPlus), + ppadminus: Math.max(padminus, headMinus, startHeadMinus) + }); + } + + ann._extremes[axId] = extremes; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744,"./draw":559}],555:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); +var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; + +module.exports = { + hasClickToShow: hasClickToShow, + onClick: onClick +}; + +/* + * hasClickToShow: does the given hoverData have ANY annotations which will + * turn ON if we click here? (used by hover events to set cursor) + * + * gd: graphDiv + * hoverData: a hoverData array, as included with the *plotly_hover* or + * *plotly_click* events in the `points` attribute + * + * returns: boolean + */ +function hasClickToShow(gd, hoverData) { + var sets = getToggleSets(gd, hoverData); + return sets.on.length > 0 || sets.explicitOff.length > 0; +} + +/* + * onClick: perform the toggling (via Plotly.update) implied by clicking + * at this hoverData + * + * gd: graphDiv + * hoverData: a hoverData array, as included with the *plotly_hover* or + * *plotly_click* events in the `points` attribute + * + * returns: Promise that the update is complete + */ +function onClick(gd, hoverData) { + var toggleSets = getToggleSets(gd, hoverData); + var onSet = toggleSets.on; + var offSet = toggleSets.off.concat(toggleSets.explicitOff); + var update = {}; + var annotationsOut = gd._fullLayout.annotations; + var i, editHelpers; + + if(!(onSet.length || offSet.length)) return; + + for(i = 0; i < onSet.length; i++) { + editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[onSet[i]]); + editHelpers.modifyItem('visible', true); + Lib.extendFlat(update, editHelpers.getUpdateObj()); + } + + for(i = 0; i < offSet.length; i++) { + editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[offSet[i]]); + editHelpers.modifyItem('visible', false); + Lib.extendFlat(update, editHelpers.getUpdateObj()); + } + + return Registry.call('update', gd, {}, update); +} + +/* + * getToggleSets: find the annotations which will turn on or off at this + * hoverData + * + * gd: graphDiv + * hoverData: a hoverData array, as included with the *plotly_hover* or + * *plotly_click* events in the `points` attribute + * + * returns: { + * on: Array (indices of annotations to turn on), + * off: Array (indices to turn off because you're not hovering on them), + * explicitOff: Array (indices to turn off because you *are* hovering on them) + * } + */ +function getToggleSets(gd, hoverData) { + var annotations = gd._fullLayout.annotations, + onSet = [], + offSet = [], + explicitOffSet = [], + hoverLen = (hoverData || []).length; + + var i, j, anni, showMode, pointj, xa, ya, toggleType; + + for(i = 0; i < annotations.length; i++) { + anni = annotations[i]; + showMode = anni.clicktoshow; + + if(showMode) { + for(j = 0; j < hoverLen; j++) { + pointj = hoverData[j]; + xa = pointj.xaxis; + ya = pointj.yaxis; + + if(xa._id === anni.xref && + ya._id === anni.yref && + xa.d2r(pointj.x) === clickData2r(anni._xclick, xa) && + ya.d2r(pointj.y) === clickData2r(anni._yclick, ya) + ) { + // match! toggle this annotation + // regardless of its clicktoshow mode + // but if it's onout mode, off is implicit + if(anni.visible) { + if(showMode === 'onout') toggleType = offSet; + else toggleType = explicitOffSet; + } + else { + toggleType = onSet; + } + toggleType.push(i); + break; + } + } + + if(j === hoverLen) { + // no match - only turn this annotation OFF, and only if + // showmode is 'onout' + if(anni.visible && showMode === 'onout') offSet.push(i); + } + } + } + + return {on: onSet, off: offSet, explicitOff: explicitOffSet}; +} + +// to handle log axes until v2 +function clickData2r(d, ax) { + return ax.type === 'log' ? ax.l2r(d) : ax.d2r(d); +} + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../registry":827}],556:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../color'); + +// defaults common to 'annotations' and 'annotations3d' +module.exports = function handleAnnotationCommonDefaults(annIn, annOut, fullLayout, coerce) { + coerce('opacity'); + var bgColor = coerce('bgcolor'); + + var borderColor = coerce('bordercolor'); + var borderOpacity = Color.opacity(borderColor); + + coerce('borderpad'); + + var borderWidth = coerce('borderwidth'); + var showArrow = coerce('showarrow'); + + coerce('text', showArrow ? ' ' : fullLayout._dfltTitle.annotation); + coerce('textangle'); + Lib.coerceFont(coerce, 'font', fullLayout.font); + + coerce('width'); + coerce('align'); + + var h = coerce('height'); + if(h) coerce('valign'); + + if(showArrow) { + var arrowside = coerce('arrowside'); + var arrowhead; + var arrowsize; + + if(arrowside.indexOf('end') !== -1) { + arrowhead = coerce('arrowhead'); + arrowsize = coerce('arrowsize'); + } + + if(arrowside.indexOf('start') !== -1) { + coerce('startarrowhead', arrowhead); + coerce('startarrowsize', arrowsize); + } + coerce('arrowcolor', borderOpacity ? annOut.bordercolor : Color.defaultLine); + coerce('arrowwidth', ((borderOpacity && borderWidth) || 1) * 2); + coerce('standoff'); + coerce('startstandoff'); + + } + + var hoverText = coerce('hovertext'); + var globalHoverLabel = fullLayout.hoverlabel || {}; + + if(hoverText) { + var hoverBG = coerce('hoverlabel.bgcolor', globalHoverLabel.bgcolor || + (Color.opacity(bgColor) ? Color.rgb(bgColor) : Color.defaultLine) + ); + + var hoverBorder = coerce('hoverlabel.bordercolor', globalHoverLabel.bordercolor || + Color.contrast(hoverBG) + ); + + Lib.coerceFont(coerce, 'hoverlabel.font', { + family: globalHoverLabel.font.family, + size: globalHoverLabel.font.size, + color: globalHoverLabel.font.color || hoverBorder + }); + } + + coerce('captureevents', !!hoverText); +}; + +},{"../../lib":696,"../color":570}],557:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var toLogRange = _dereq_('../../lib/to_log_range'); + +/* + * convertCoords: when converting an axis between log and linear + * you need to alter any annotations on that axis to keep them + * pointing at the same data point. + * In v2.0 this will become obsolete + * + * gd: the plot div + * ax: the axis being changed + * newType: the type it's getting + * doExtra: function(attr, val) from inside relayout that sets the attribute. + * Use this to make the changes as it's aware if any other changes in the + * same relayout call should override this conversion. + */ +module.exports = function convertCoords(gd, ax, newType, doExtra) { + ax = ax || {}; + + var toLog = (newType === 'log') && (ax.type === 'linear'), + fromLog = (newType === 'linear') && (ax.type === 'log'); + + if(!(toLog || fromLog)) return; + + var annotations = gd._fullLayout.annotations, + axLetter = ax._id.charAt(0), + ann, + attrPrefix; + + function convert(attr) { + var currentVal = ann[attr], + newVal = null; + + if(toLog) newVal = toLogRange(currentVal, ax.range); + else newVal = Math.pow(10, currentVal); + + // if conversion failed, delete the value so it gets a default value + if(!isNumeric(newVal)) newVal = null; + + doExtra(attrPrefix + attr, newVal); + } + + for(var i = 0; i < annotations.length; i++) { + ann = annotations[i]; + attrPrefix = 'annotations[' + i + '].'; + + if(ann[axLetter + 'ref'] === ax._id) convert(axLetter); + if(ann['a' + axLetter + 'ref'] === ax._id) convert('a' + axLetter); + } +}; + +},{"../../lib/to_log_range":722,"fast-isnumeric":214}],558:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var handleAnnotationCommonDefaults = _dereq_('./common_defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + handleArrayContainerDefaults(layoutIn, layoutOut, { + name: 'annotations', + handleItemDefaults: handleAnnotationDefaults + }); +}; + +function handleAnnotationDefaults(annIn, annOut, fullLayout) { + function coerce(attr, dflt) { + return Lib.coerce(annIn, annOut, attributes, attr, dflt); + } + + var visible = coerce('visible'); + var clickToShow = coerce('clicktoshow'); + + if(!(visible || clickToShow)) return; + + handleAnnotationCommonDefaults(annIn, annOut, fullLayout, coerce); + + var showArrow = annOut.showarrow; + + // positioning + var axLetters = ['x', 'y'], + arrowPosDflt = [-10, -30], + gdMock = {_fullLayout: fullLayout}; + for(var i = 0; i < 2; i++) { + var axLetter = axLetters[i]; + + // xref, yref + var axRef = Axes.coerceRef(annIn, annOut, gdMock, axLetter, '', 'paper'); + + if(axRef !== 'paper') { + var ax = Axes.getFromId(gdMock, axRef); + ax._annIndices.push(annOut._index); + } + + // x, y + Axes.coercePosition(annOut, gdMock, coerce, axRef, axLetter, 0.5); + + if(showArrow) { + var arrowPosAttr = 'a' + axLetter, + // axref, ayref + aaxRef = Axes.coerceRef(annIn, annOut, gdMock, arrowPosAttr, 'pixel'); + + // for now the arrow can only be on the same axis or specified as pixels + // TODO: sometime it might be interesting to allow it to be on *any* axis + // but that would require updates to drawing & autorange code and maybe more + if(aaxRef !== 'pixel' && aaxRef !== axRef) { + aaxRef = annOut[arrowPosAttr] = 'pixel'; + } + + // ax, ay + var aDflt = (aaxRef === 'pixel') ? arrowPosDflt[i] : 0.4; + Axes.coercePosition(annOut, gdMock, coerce, aaxRef, arrowPosAttr, aDflt); + } + + // xanchor, yanchor + coerce(axLetter + 'anchor'); + + // xshift, yshift + coerce(axLetter + 'shift'); + } + + // if you have one coordinate you should have both + Lib.noneOrAll(annIn, annOut, ['x', 'y']); + + // if you have one part of arrow length you should have both + if(showArrow) { + Lib.noneOrAll(annIn, annOut, ['ax', 'ay']); + } + + if(clickToShow) { + var xClick = coerce('xclick'); + var yClick = coerce('yclick'); + + // put the actual click data to bind to into private attributes + // so we don't have to do this little bit of logic on every hover event + annOut._xclick = (xClick === undefined) ? + annOut.x : + Axes.cleanPosition(xClick, gdMock, annOut.xref); + annOut._yclick = (yClick === undefined) ? + annOut.y : + Axes.cleanPosition(yClick, gdMock, annOut.yref); + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/cartesian/axes":744,"./attributes":553,"./common_defaults":556}],559:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Plots = _dereq_('../../plots/plots'); +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); +var Fx = _dereq_('../fx'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var setCursor = _dereq_('../../lib/setcursor'); +var dragElement = _dereq_('../dragelement'); +var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; + +var drawArrowHead = _dereq_('./draw_arrow_head'); + +// Annotations are stored in gd.layout.annotations, an array of objects +// index can point to one item in this array, +// or non-numeric to simply add a new one +// or -1 to modify all existing +// opt can be the full options object, or one key (to be set to value) +// or undefined to simply redraw +// if opt is blank, val can be 'add' or a full options object to add a new +// annotation at that point in the array, or 'remove' to delete this one + +module.exports = { + draw: draw, + drawOne: drawOne, + drawRaw: drawRaw +}; + +/* + * draw: draw all annotations without any new modifications + */ +function draw(gd) { + var fullLayout = gd._fullLayout; + + fullLayout._infolayer.selectAll('.annotation').remove(); + + for(var i = 0; i < fullLayout.annotations.length; i++) { + if(fullLayout.annotations[i].visible) { + drawOne(gd, i); + } + } + + return Plots.previousPromises(gd); +} + +/* + * drawOne: draw a single cartesian or paper-ref annotation, potentially with modifications + * + * index (int): the annotation to draw + */ +function drawOne(gd, index) { + var fullLayout = gd._fullLayout; + var options = fullLayout.annotations[index] || {}; + var xa = Axes.getFromId(gd, options.xref); + var ya = Axes.getFromId(gd, options.yref); + + drawRaw(gd, options, index, false, xa, ya); +} + +/** + * drawRaw: draw a single annotation, potentially with modifications + * + * @param {DOM element} gd + * @param {object} options : this annotation's fullLayout options + * @param {integer} index : index in 'annotations' container of the annotation to draw + * @param {string} subplotId : id of the annotation's subplot + * - use false for 2d (i.e. cartesian or paper-ref) annotations + * @param {object | undefined} xa : full x-axis object to compute subplot pos-to-px + * @param {object | undefined} ya : ... y-axis + */ +function drawRaw(gd, options, index, subplotId, xa, ya) { + var fullLayout = gd._fullLayout; + var gs = gd._fullLayout._size; + var edits = gd._context.edits; + + var className, containerStr; + + if(subplotId) { + className = 'annotation-' + subplotId; + containerStr = subplotId + '.annotations'; + } else { + className = 'annotation'; + containerStr = 'annotations'; + } + + var editHelpers = arrayEditor(gd.layout, containerStr, options); + var modifyBase = editHelpers.modifyBase; + var modifyItem = editHelpers.modifyItem; + var getUpdateObj = editHelpers.getUpdateObj; + + // remove the existing annotation if there is one + fullLayout._infolayer + .selectAll('.' + className + '[data-index="' + index + '"]') + .remove(); + + var annClipID = 'clip' + fullLayout._uid + '_ann' + index; + + // this annotation is gone - quit now after deleting it + // TODO: use d3 idioms instead of deleting and redrawing every time + if(!options._input || options.visible === false) { + d3.selectAll('#' + annClipID).remove(); + return; + } + + // calculated pixel positions + // x & y each will get text, head, and tail as appropriate + var annPosPx = {x: {}, y: {}}, + textangle = +options.textangle || 0; + + // create the components + // made a single group to contain all, so opacity can work right + // with border/arrow together this could handle a whole bunch of + // cleanup at this point, but works for now + var annGroup = fullLayout._infolayer.append('g') + .classed(className, true) + .attr('data-index', String(index)) + .style('opacity', options.opacity); + + // another group for text+background so that they can rotate together + var annTextGroup = annGroup.append('g') + .classed('annotation-text-g', true); + + var editTextPosition = edits[options.showarrow ? 'annotationTail' : 'annotationPosition']; + var textEvents = options.captureevents || edits.annotationText || editTextPosition; + + var annTextGroupInner = annTextGroup.append('g') + .style('pointer-events', textEvents ? 'all' : null) + .call(setCursor, 'pointer') + .on('click', function() { + gd._dragging = false; + + var eventData = { + index: index, + annotation: options._input, + fullAnnotation: options, + event: d3.event + }; + + if(subplotId) { + eventData.subplotId = subplotId; + } + + gd.emit('plotly_clickannotation', eventData); + }); + + if(options.hovertext) { + annTextGroupInner + .on('mouseover', function() { + var hoverOptions = options.hoverlabel; + var hoverFont = hoverOptions.font; + var bBox = this.getBoundingClientRect(); + var bBoxRef = gd.getBoundingClientRect(); + + Fx.loneHover({ + x0: bBox.left - bBoxRef.left, + x1: bBox.right - bBoxRef.left, + y: (bBox.top + bBox.bottom) / 2 - bBoxRef.top, + text: options.hovertext, + color: hoverOptions.bgcolor, + borderColor: hoverOptions.bordercolor, + fontFamily: hoverFont.family, + fontSize: hoverFont.size, + fontColor: hoverFont.color + }, { + container: fullLayout._hoverlayer.node(), + outerContainer: fullLayout._paper.node(), + gd: gd + }); + }) + .on('mouseout', function() { + Fx.loneUnhover(fullLayout._hoverlayer.node()); + }); + } + + var borderwidth = options.borderwidth, + borderpad = options.borderpad, + borderfull = borderwidth + borderpad; + + var annTextBG = annTextGroupInner.append('rect') + .attr('class', 'bg') + .style('stroke-width', borderwidth + 'px') + .call(Color.stroke, options.bordercolor) + .call(Color.fill, options.bgcolor); + + var isSizeConstrained = options.width || options.height; + + var annTextClip = fullLayout._topclips + .selectAll('#' + annClipID) + .data(isSizeConstrained ? [0] : []); + + annTextClip.enter().append('clipPath') + .classed('annclip', true) + .attr('id', annClipID) + .append('rect'); + annTextClip.exit().remove(); + + var font = options.font; + + var annText = annTextGroupInner.append('text') + .classed('annotation-text', true) + .text(options.text); + + function textLayout(s) { + s.call(Drawing.font, font) + .attr({ + 'text-anchor': { + left: 'start', + right: 'end' + }[options.align] || 'middle' + }); + + svgTextUtils.convertToTspans(s, gd, drawGraphicalElements); + return s; + } + + function drawGraphicalElements() { + // if the text has *only* a link, make the whole box into a link + var anchor3 = annText.selectAll('a'); + if(anchor3.size() === 1 && anchor3.text() === annText.text()) { + var wholeLink = annTextGroupInner.insert('a', ':first-child').attr({ + 'xlink:xlink:href': anchor3.attr('xlink:href'), + 'xlink:xlink:show': anchor3.attr('xlink:show') + }) + .style({cursor: 'pointer'}); + + wholeLink.node().appendChild(annTextBG.node()); + } + + var mathjaxGroup = annTextGroupInner.select('.annotation-text-math-group'); + var hasMathjax = !mathjaxGroup.empty(); + var anntextBB = Drawing.bBox( + (hasMathjax ? mathjaxGroup : annText).node()); + var textWidth = anntextBB.width; + var textHeight = anntextBB.height; + var annWidth = options.width || textWidth; + var annHeight = options.height || textHeight; + var outerWidth = Math.round(annWidth + 2 * borderfull); + var outerHeight = Math.round(annHeight + 2 * borderfull); + + function shiftFraction(v, anchor) { + if(anchor === 'auto') { + if(v < 1 / 3) anchor = 'left'; + else if(v > 2 / 3) anchor = 'right'; + else anchor = 'center'; + } + return { + center: 0, + middle: 0, + left: 0.5, + bottom: -0.5, + right: -0.5, + top: 0.5 + }[anchor]; + } + + var annotationIsOffscreen = false; + var letters = ['x', 'y']; + + for(var i = 0; i < letters.length; i++) { + var axLetter = letters[i], + axRef = options[axLetter + 'ref'] || axLetter, + tailRef = options['a' + axLetter + 'ref'], + ax = {x: xa, y: ya}[axLetter], + dimAngle = (textangle + (axLetter === 'x' ? 0 : -90)) * Math.PI / 180, + // note that these two can be either positive or negative + annSizeFromWidth = outerWidth * Math.cos(dimAngle), + annSizeFromHeight = outerHeight * Math.sin(dimAngle), + // but this one is the positive total size + annSize = Math.abs(annSizeFromWidth) + Math.abs(annSizeFromHeight), + anchor = options[axLetter + 'anchor'], + overallShift = options[axLetter + 'shift'] * (axLetter === 'x' ? 1 : -1), + posPx = annPosPx[axLetter], + basePx, + textPadShift, + alignPosition, + autoAlignFraction, + textShift; + + /* + * calculate the *primary* pixel position + * which is the arrowhead if there is one, + * otherwise the text anchor point + */ + if(ax) { + // check if annotation is off screen, to bypass DOM manipulations + var posFraction = ax.r2fraction(options[axLetter]); + if(posFraction < 0 || posFraction > 1) { + if(tailRef === axRef) { + posFraction = ax.r2fraction(options['a' + axLetter]); + if(posFraction < 0 || posFraction > 1) { + annotationIsOffscreen = true; + } + } else { + annotationIsOffscreen = true; + } + } + basePx = ax._offset + ax.r2p(options[axLetter]); + autoAlignFraction = 0.5; + } + else { + if(axLetter === 'x') { + alignPosition = options[axLetter]; + basePx = gs.l + gs.w * alignPosition; + } + else { + alignPosition = 1 - options[axLetter]; + basePx = gs.t + gs.h * alignPosition; + } + autoAlignFraction = options.showarrow ? 0.5 : alignPosition; + } + + // now translate this into pixel positions of head, tail, and text + // as well as paddings for autorange + if(options.showarrow) { + posPx.head = basePx; + + var arrowLength = options['a' + axLetter]; + + // with an arrow, the text rotates around the anchor point + textShift = annSizeFromWidth * shiftFraction(0.5, options.xanchor) - + annSizeFromHeight * shiftFraction(0.5, options.yanchor); + + if(tailRef === axRef) { + posPx.tail = ax._offset + ax.r2p(arrowLength); + // tail is data-referenced: autorange pads the text in px from the tail + textPadShift = textShift; + } + else { + posPx.tail = basePx + arrowLength; + // tail is specified in px from head, so autorange also pads vs head + textPadShift = textShift + arrowLength; + } + + posPx.text = posPx.tail + textShift; + + // constrain pixel/paper referenced so the draggers are at least + // partially visible + var maxPx = fullLayout[(axLetter === 'x') ? 'width' : 'height']; + if(axRef === 'paper') { + posPx.head = Lib.constrain(posPx.head, 1, maxPx - 1); + } + if(tailRef === 'pixel') { + var shiftPlus = -Math.max(posPx.tail - 3, posPx.text), + shiftMinus = Math.min(posPx.tail + 3, posPx.text) - maxPx; + if(shiftPlus > 0) { + posPx.tail += shiftPlus; + posPx.text += shiftPlus; + } + else if(shiftMinus > 0) { + posPx.tail -= shiftMinus; + posPx.text -= shiftMinus; + } + } + + posPx.tail += overallShift; + posPx.head += overallShift; + } + else { + // with no arrow, the text rotates and *then* we put the anchor + // relative to the new bounding box + textShift = annSize * shiftFraction(autoAlignFraction, anchor); + textPadShift = textShift; + posPx.text = basePx + textShift; + } + + posPx.text += overallShift; + textShift += overallShift; + textPadShift += overallShift; + + // padplus/minus are used by autorange + options['_' + axLetter + 'padplus'] = (annSize / 2) + textPadShift; + options['_' + axLetter + 'padminus'] = (annSize / 2) - textPadShift; + + // size/shift are used during dragging + options['_' + axLetter + 'size'] = annSize; + options['_' + axLetter + 'shift'] = textShift; + } + + // We have everything we need for calcAutorange at this point, + // we can safely exit - unless we're currently dragging the plot + if(!gd._dragging && annotationIsOffscreen) { + annTextGroupInner.remove(); + return; + } + + var xShift = 0; + var yShift = 0; + + if(options.align !== 'left') { + xShift = (annWidth - textWidth) * (options.align === 'center' ? 0.5 : 1); + } + if(options.valign !== 'top') { + yShift = (annHeight - textHeight) * (options.valign === 'middle' ? 0.5 : 1); + } + + if(hasMathjax) { + mathjaxGroup.select('svg').attr({ + x: borderfull + xShift - 1, + y: borderfull + yShift + }) + .call(Drawing.setClipUrl, isSizeConstrained ? annClipID : null); + } + else { + var texty = borderfull + yShift - anntextBB.top; + var textx = borderfull + xShift - anntextBB.left; + + annText.call(svgTextUtils.positionText, textx, texty) + .call(Drawing.setClipUrl, isSizeConstrained ? annClipID : null); + } + + annTextClip.select('rect').call(Drawing.setRect, borderfull, borderfull, + annWidth, annHeight); + + annTextBG.call(Drawing.setRect, borderwidth / 2, borderwidth / 2, + outerWidth - borderwidth, outerHeight - borderwidth); + + annTextGroupInner.call(Drawing.setTranslate, + Math.round(annPosPx.x.text - outerWidth / 2), + Math.round(annPosPx.y.text - outerHeight / 2)); + + /* + * rotate text and background + * we already calculated the text center position *as rotated* + * because we needed that for autoranging anyway, so now whether + * we have an arrow or not, we rotate about the text center. + */ + annTextGroup.attr({transform: 'rotate(' + textangle + ',' + + annPosPx.x.text + ',' + annPosPx.y.text + ')'}); + + /* + * add the arrow + * uses options[arrowwidth,arrowcolor,arrowhead] for styling + * dx and dy are normally zero, but when you are dragging the textbox + * while the head stays put, dx and dy are the pixel offsets + */ + var drawArrow = function(dx, dy) { + annGroup + .selectAll('.annotation-arrow-g') + .remove(); + + var headX = annPosPx.x.head, + headY = annPosPx.y.head, + tailX = annPosPx.x.tail + dx, + tailY = annPosPx.y.tail + dy, + textX = annPosPx.x.text + dx, + textY = annPosPx.y.text + dy, + + // find the edge of the text box, where we'll start the arrow: + // create transform matrix to rotate the text box corners + transform = Lib.rotationXYMatrix(textangle, textX, textY), + applyTransform = Lib.apply2DTransform(transform), + applyTransform2 = Lib.apply2DTransform2(transform), + + // calculate and transform bounding box + width = +annTextBG.attr('width'), + height = +annTextBG.attr('height'), + xLeft = textX - 0.5 * width, + xRight = xLeft + width, + yTop = textY - 0.5 * height, + yBottom = yTop + height, + edges = [ + [xLeft, yTop, xLeft, yBottom], + [xLeft, yBottom, xRight, yBottom], + [xRight, yBottom, xRight, yTop], + [xRight, yTop, xLeft, yTop] + ].map(applyTransform2); + + // Remove the line if it ends inside the box. Use ray + // casting for rotated boxes: see which edges intersect a + // line from the arrowhead to far away and reduce with xor + // to get the parity of the number of intersections. + if(edges.reduce(function(a, x) { + return a ^ + !!Lib.segmentsIntersect(headX, headY, headX + 1e6, headY + 1e6, + x[0], x[1], x[2], x[3]); + }, false)) { + // no line or arrow - so quit drawArrow now + return; + } + + edges.forEach(function(x) { + var p = Lib.segmentsIntersect(tailX, tailY, headX, headY, + x[0], x[1], x[2], x[3]); + if(p) { + tailX = p.x; + tailY = p.y; + } + }); + + var strokewidth = options.arrowwidth, + arrowColor = options.arrowcolor, + arrowSide = options.arrowside; + + var arrowGroup = annGroup.append('g') + .style({opacity: Color.opacity(arrowColor)}) + .classed('annotation-arrow-g', true); + + var arrow = arrowGroup.append('path') + .attr('d', 'M' + tailX + ',' + tailY + 'L' + headX + ',' + headY) + .style('stroke-width', strokewidth + 'px') + .call(Color.stroke, Color.rgb(arrowColor)); + + drawArrowHead(arrow, arrowSide, options); + + // the arrow dragger is a small square right at the head, then a line to the tail, + // all expanded by a stroke width of 6px plus the arrow line width + if(edits.annotationPosition && arrow.node().parentNode && !subplotId) { + var arrowDragHeadX = headX; + var arrowDragHeadY = headY; + if(options.standoff) { + var arrowLength = Math.sqrt(Math.pow(headX - tailX, 2) + Math.pow(headY - tailY, 2)); + arrowDragHeadX += options.standoff * (tailX - headX) / arrowLength; + arrowDragHeadY += options.standoff * (tailY - headY) / arrowLength; + } + var arrowDrag = arrowGroup.append('path') + .classed('annotation-arrow', true) + .classed('anndrag', true) + .classed('cursor-move', true) + .attr({ + d: 'M3,3H-3V-3H3ZM0,0L' + (tailX - arrowDragHeadX) + ',' + (tailY - arrowDragHeadY), + transform: 'translate(' + arrowDragHeadX + ',' + arrowDragHeadY + ')' + }) + .style('stroke-width', (strokewidth + 6) + 'px') + .call(Color.stroke, 'rgba(0,0,0,0)') + .call(Color.fill, 'rgba(0,0,0,0)'); + + var annx0, anny0; + + // dragger for the arrow & head: translates the whole thing + // (head/tail/text) all together + dragElement.init({ + element: arrowDrag.node(), + gd: gd, + prepFn: function() { + var pos = Drawing.getTranslate(annTextGroupInner); + + annx0 = pos.x; + anny0 = pos.y; + if(xa && xa.autorange) { + modifyBase(xa._name + '.autorange', true); + } + if(ya && ya.autorange) { + modifyBase(ya._name + '.autorange', true); + } + }, + moveFn: function(dx, dy) { + var annxy0 = applyTransform(annx0, anny0), + xcenter = annxy0[0] + dx, + ycenter = annxy0[1] + dy; + annTextGroupInner.call(Drawing.setTranslate, xcenter, ycenter); + + modifyItem('x', xa ? + xa.p2r(xa.r2p(options.x) + dx) : + (options.x + (dx / gs.w))); + modifyItem('y', ya ? + ya.p2r(ya.r2p(options.y) + dy) : + (options.y - (dy / gs.h))); + + if(options.axref === options.xref) { + modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx)); + } + + if(options.ayref === options.yref) { + modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy)); + } + + arrowGroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); + annTextGroup.attr({ + transform: 'rotate(' + textangle + ',' + + xcenter + ',' + ycenter + ')' + }); + }, + doneFn: function() { + Registry.call('relayout', gd, getUpdateObj()); + var notesBox = document.querySelector('.js-notes-box-panel'); + if(notesBox) notesBox.redraw(notesBox.selectedObj); + } + }); + } + }; + + if(options.showarrow) drawArrow(0, 0); + + // user dragging the annotation (text, not arrow) + if(editTextPosition) { + var baseTextTransform; + + // dragger for the textbox: if there's an arrow, just drag the + // textbox and tail, leave the head untouched + dragElement.init({ + element: annTextGroupInner.node(), + gd: gd, + prepFn: function() { + baseTextTransform = annTextGroup.attr('transform'); + }, + moveFn: function(dx, dy) { + var csr = 'pointer'; + if(options.showarrow) { + if(options.axref === options.xref) { + modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx)); + } else { + modifyItem('ax', options.ax + dx); + } + + if(options.ayref === options.yref) { + modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy)); + } else { + modifyItem('ay', options.ay + dy); + } + + drawArrow(dx, dy); + } + else if(!subplotId) { + var xUpdate, yUpdate; + if(xa) { + xUpdate = xa.p2r(xa.r2p(options.x) + dx); + + } else { + var widthFraction = options._xsize / gs.w, + xLeft = options.x + (options._xshift - options.xshift) / gs.w - + widthFraction / 2; + + xUpdate = dragElement.align(xLeft + dx / gs.w, + widthFraction, 0, 1, options.xanchor); + } + + if(ya) { + yUpdate = ya.p2r(ya.r2p(options.y) + dy); + } else { + var heightFraction = options._ysize / gs.h, + yBottom = options.y - (options._yshift + options.yshift) / gs.h - + heightFraction / 2; + + yUpdate = dragElement.align(yBottom - dy / gs.h, + heightFraction, 0, 1, options.yanchor); + } + modifyItem('x', xUpdate); + modifyItem('y', yUpdate); + if(!xa || !ya) { + csr = dragElement.getCursor( + xa ? 0.5 : xUpdate, + ya ? 0.5 : yUpdate, + options.xanchor, options.yanchor + ); + } + } + else return; + + annTextGroup.attr({ + transform: 'translate(' + dx + ',' + dy + ')' + baseTextTransform + }); + + setCursor(annTextGroupInner, csr); + }, + doneFn: function() { + setCursor(annTextGroupInner); + Registry.call('relayout', gd, getUpdateObj()); + var notesBox = document.querySelector('.js-notes-box-panel'); + if(notesBox) notesBox.redraw(notesBox.selectedObj); + } + }); + } + } + + if(edits.annotationText) { + annText.call(svgTextUtils.makeEditable, {delegate: annTextGroupInner, gd: gd}) + .call(textLayout) + .on('edit', function(_text) { + options.text = _text; + this.call(textLayout); + + modifyItem('text', _text); + + if(xa && xa.autorange) { + modifyBase(xa._name + '.autorange', true); + } + if(ya && ya.autorange) { + modifyBase(ya._name + '.autorange', true); + } + + Registry.call('relayout', gd, getUpdateObj()); + }); + } + else annText.call(textLayout); +} + +},{"../../lib":696,"../../lib/setcursor":716,"../../lib/svg_text_utils":720,"../../plot_api/plot_template":734,"../../plots/cartesian/axes":744,"../../plots/plots":808,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"../fx":612,"./draw_arrow_head":560,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],560:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Color = _dereq_('../color'); + +var ARROWPATHS = _dereq_('./arrow_paths'); + +/** + * Add arrowhead(s) to a path or line element + * + * @param {d3.selection} el3: a d3-selected line or path element + * + * @param {string} ends: 'none', 'start', 'end', or 'start+end' for which ends get arrowheads + * + * @param {object} options: style information. Must have all the following: + * @param {number} options.arrowhead: end head style - see ./arrow_paths + * @param {number} options.startarrowhead: start head style - see ./arrow_paths + * @param {number} options.arrowsize: relative size of the end head vs line width + * @param {number} options.startarrowsize: relative size of the start head vs line width + * @param {number} options.standoff: distance in px to move the end arrow point from its target + * @param {number} options.startstandoff: distance in px to move the start arrow point from its target + * @param {number} options.arrowwidth: width of the arrow line + * @param {string} options.arrowcolor: color of the arrow line, for the head to match + * Note that the opacity of this color is ignored, as it's assumed the container + * of both the line and head has opacity applied to it so there isn't greater opacity + * where they overlap. + */ +module.exports = function drawArrowHead(el3, ends, options) { + var el = el3.node(); + var headStyle = ARROWPATHS[options.arrowhead || 0]; + var startHeadStyle = ARROWPATHS[options.startarrowhead || 0]; + var scale = (options.arrowwidth || 1) * (options.arrowsize || 1); + var startScale = (options.arrowwidth || 1) * (options.startarrowsize || 1); + var doStart = ends.indexOf('start') >= 0; + var doEnd = ends.indexOf('end') >= 0; + var backOff = headStyle.backoff * scale + options.standoff; + var startBackOff = startHeadStyle.backoff * startScale + options.startstandoff; + + var start, end, startRot, endRot; + + if(el.nodeName === 'line') { + start = {x: +el3.attr('x1'), y: +el3.attr('y1')}; + end = {x: +el3.attr('x2'), y: +el3.attr('y2')}; + + var dx = start.x - end.x; + var dy = start.y - end.y; + + startRot = Math.atan2(dy, dx); + endRot = startRot + Math.PI; + if(backOff && startBackOff) { + if(backOff + startBackOff > Math.sqrt(dx * dx + dy * dy)) { + hideLine(); + return; + } + } + + if(backOff) { + if(backOff * backOff > dx * dx + dy * dy) { + hideLine(); + return; + } + var backOffX = backOff * Math.cos(startRot), + backOffY = backOff * Math.sin(startRot); + + end.x += backOffX; + end.y += backOffY; + el3.attr({x2: end.x, y2: end.y}); + + } + + if(startBackOff) { + if(startBackOff * startBackOff > dx * dx + dy * dy) { + hideLine(); + return; + } + var startBackOffX = startBackOff * Math.cos(startRot), + startbackOffY = startBackOff * Math.sin(startRot); + + start.x -= startBackOffX; + start.y -= startbackOffY; + el3.attr({x1: start.x, y1: start.y}); + + } + } + else if(el.nodeName === 'path') { + var pathlen = el.getTotalLength(), + // using dash to hide the backOff region of the path. + // if we ever allow dash for the arrow we'll have to + // do better than this hack... maybe just manually + // combine the two + dashArray = ''; + + if(pathlen < backOff + startBackOff) { + hideLine(); + return; + } + + + var start0 = el.getPointAtLength(0); + var dstart = el.getPointAtLength(0.1); + + startRot = Math.atan2(start0.y - dstart.y, start0.x - dstart.x); + start = el.getPointAtLength(Math.min(startBackOff, pathlen)); + + dashArray = '0px,' + startBackOff + 'px,'; + + var end0 = el.getPointAtLength(pathlen); + var dend = el.getPointAtLength(pathlen - 0.1); + + endRot = Math.atan2(end0.y - dend.y, end0.x - dend.x); + end = el.getPointAtLength(Math.max(0, pathlen - backOff)); + + var shortening = dashArray ? startBackOff + backOff : backOff; + dashArray += (pathlen - shortening) + 'px,' + pathlen + 'px'; + + el3.style('stroke-dasharray', dashArray); + } + + function hideLine() { el3.style('stroke-dasharray', '0px,100px'); } + + function drawhead(arrowHeadStyle, p, rot, arrowScale) { + if(!arrowHeadStyle.path) return; + if(arrowHeadStyle.noRotate) rot = 0; + + d3.select(el.parentNode).append('path') + .attr({ + 'class': el3.attr('class'), + d: arrowHeadStyle.path, + transform: + 'translate(' + p.x + ',' + p.y + ')' + + (rot ? 'rotate(' + (rot * 180 / Math.PI) + ')' : '') + + 'scale(' + arrowScale + ')' + }) + .style({ + fill: Color.rgb(options.arrowcolor), + 'stroke-width': 0 + }); + } + + if(doStart) drawhead(startHeadStyle, start, startRot, startScale); + if(doEnd) drawhead(headStyle, end, endRot, scale); +}; + +},{"../color":570,"./arrow_paths":552,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],561:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawModule = _dereq_('./draw'); +var clickModule = _dereq_('./click'); + +module.exports = { + moduleType: 'component', + name: 'annotations', + + layoutAttributes: _dereq_('./attributes'), + supplyLayoutDefaults: _dereq_('./defaults'), + includeBasePlot: _dereq_('../../plots/cartesian/include_components')('annotations'), + + calcAutorange: _dereq_('./calc_autorange'), + draw: drawModule.draw, + drawOne: drawModule.drawOne, + drawRaw: drawModule.drawRaw, + + hasClickToShow: clickModule.hasClickToShow, + onClick: clickModule.onClick, + + convertCoords: _dereq_('./convert_coords') +}; + +},{"../../plots/cartesian/include_components":755,"./attributes":553,"./calc_autorange":554,"./click":555,"./convert_coords":557,"./defaults":558,"./draw":559}],562:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var annAtts = _dereq_('../annotations/attributes'); +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +module.exports = overrideAll(templatedArray('annotation', { + visible: annAtts.visible, + x: { + valType: 'any', + + + }, + y: { + valType: 'any', + + + }, + z: { + valType: 'any', + + + }, + ax: { + valType: 'number', + + + }, + ay: { + valType: 'number', + + + }, + + xanchor: annAtts.xanchor, + xshift: annAtts.xshift, + yanchor: annAtts.yanchor, + yshift: annAtts.yshift, + + text: annAtts.text, + textangle: annAtts.textangle, + font: annAtts.font, + width: annAtts.width, + height: annAtts.height, + opacity: annAtts.opacity, + align: annAtts.align, + valign: annAtts.valign, + bgcolor: annAtts.bgcolor, + bordercolor: annAtts.bordercolor, + borderpad: annAtts.borderpad, + borderwidth: annAtts.borderwidth, + showarrow: annAtts.showarrow, + arrowcolor: annAtts.arrowcolor, + arrowhead: annAtts.arrowhead, + startarrowhead: annAtts.startarrowhead, + arrowside: annAtts.arrowside, + arrowsize: annAtts.arrowsize, + startarrowsize: annAtts.startarrowsize, + arrowwidth: annAtts.arrowwidth, + standoff: annAtts.standoff, + startstandoff: annAtts.startstandoff, + hovertext: annAtts.hovertext, + hoverlabel: annAtts.hoverlabel, + captureevents: annAtts.captureevents, + + // maybes later? + // clicktoshow: annAtts.clicktoshow, + // xclick: annAtts.xclick, + // yclick: annAtts.yclick, + + // not needed! + // axref: 'pixel' + // ayref: 'pixel' + // xref: 'x' + // yref: 'y + // zref: 'z' +}), 'calc', 'from-root'); + +},{"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../annotations/attributes":553}],563:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +module.exports = function convert(scene) { + var fullSceneLayout = scene.fullSceneLayout; + var anns = fullSceneLayout.annotations; + + for(var i = 0; i < anns.length; i++) { + mockAnnAxes(anns[i], scene); + } + + scene.fullLayout._infolayer + .selectAll('.annotation-' + scene.id) + .remove(); +}; + +function mockAnnAxes(ann, scene) { + var fullSceneLayout = scene.fullSceneLayout; + var domain = fullSceneLayout.domain; + var size = scene.fullLayout._size; + + var base = { + // this gets fill in on render + pdata: null, + + // to get setConvert to not execute cleanly + type: 'linear', + + // don't try to update them on `editable: true` + autorange: false, + + // set infinite range so that annotation draw routine + // does not try to remove 'outside-range' annotations, + // this case is handled in the render loop + range: [-Infinity, Infinity] + }; + + ann._xa = {}; + Lib.extendFlat(ann._xa, base); + Axes.setConvert(ann._xa); + ann._xa._offset = size.l + domain.x[0] * size.w; + ann._xa.l2p = function() { + return 0.5 * (1 + ann._pdata[0] / ann._pdata[3]) * size.w * (domain.x[1] - domain.x[0]); + }; + + ann._ya = {}; + Lib.extendFlat(ann._ya, base); + Axes.setConvert(ann._ya); + ann._ya._offset = size.t + (1 - domain.y[1]) * size.h; + ann._ya.l2p = function() { + return 0.5 * (1 - ann._pdata[1] / ann._pdata[3]) * size.h * (domain.y[1] - domain.y[0]); + }; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744}],564:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); +var handleAnnotationCommonDefaults = _dereq_('../annotations/common_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function handleDefaults(sceneLayoutIn, sceneLayoutOut, opts) { + handleArrayContainerDefaults(sceneLayoutIn, sceneLayoutOut, { + name: 'annotations', + handleItemDefaults: handleAnnotationDefaults, + fullLayout: opts.fullLayout + }); +}; + +function handleAnnotationDefaults(annIn, annOut, sceneLayout, opts) { + function coerce(attr, dflt) { + return Lib.coerce(annIn, annOut, attributes, attr, dflt); + } + + function coercePosition(axLetter) { + var axName = axLetter + 'axis'; + + // mock in such way that getFromId grabs correct 3D axis + var gdMock = { _fullLayout: {} }; + gdMock._fullLayout[axName] = sceneLayout[axName]; + + return Axes.coercePosition(annOut, gdMock, coerce, axLetter, axLetter, 0.5); + } + + + var visible = coerce('visible'); + if(!visible) return; + + handleAnnotationCommonDefaults(annIn, annOut, opts.fullLayout, coerce); + + coercePosition('x'); + coercePosition('y'); + coercePosition('z'); + + // if you have one coordinate you should all three + Lib.noneOrAll(annIn, annOut, ['x', 'y', 'z']); + + // hard-set here for completeness + annOut.xref = 'x'; + annOut.yref = 'y'; + annOut.zref = 'z'; + + coerce('xanchor'); + coerce('yanchor'); + coerce('xshift'); + coerce('yshift'); + + if(annOut.showarrow) { + annOut.axref = 'pixel'; + annOut.ayref = 'pixel'; + + // TODO maybe default values should be bigger than the 2D case? + coerce('ax', -10); + coerce('ay', -30); + + // if you have one part of arrow length you should have both + Lib.noneOrAll(annIn, annOut, ['ax', 'ay']); + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/cartesian/axes":744,"../annotations/common_defaults":556,"./attributes":562}],565:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var drawRaw = _dereq_('../annotations/draw').drawRaw; +var project = _dereq_('../../plots/gl3d/project'); +var axLetters = ['x', 'y', 'z']; + +module.exports = function draw(scene) { + var fullSceneLayout = scene.fullSceneLayout; + var dataScale = scene.dataScale; + var anns = fullSceneLayout.annotations; + + for(var i = 0; i < anns.length; i++) { + var ann = anns[i]; + var annotationIsOffscreen = false; + + for(var j = 0; j < 3; j++) { + var axLetter = axLetters[j]; + var pos = ann[axLetter]; + var ax = fullSceneLayout[axLetter + 'axis']; + var posFraction = ax.r2fraction(pos); + + if(posFraction < 0 || posFraction > 1) { + annotationIsOffscreen = true; + break; + } + } + + if(annotationIsOffscreen) { + scene.fullLayout._infolayer + .select('.annotation-' + scene.id + '[data-index="' + i + '"]') + .remove(); + } else { + ann._pdata = project(scene.glplot.cameraParams, [ + fullSceneLayout.xaxis.r2l(ann.x) * dataScale[0], + fullSceneLayout.yaxis.r2l(ann.y) * dataScale[1], + fullSceneLayout.zaxis.r2l(ann.z) * dataScale[2] + ]); + + drawRaw(scene.graphDiv, ann, i, scene.id, ann._xa, ann._ya); + } + } +}; + +},{"../../plots/gl3d/project":796,"../annotations/draw":559}],566:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +module.exports = { + moduleType: 'component', + name: 'annotations3d', + + schema: { + subplots: { + scene: {annotations: _dereq_('./attributes')} + } + }, + + layoutAttributes: _dereq_('./attributes'), + handleDefaults: _dereq_('./defaults'), + includeBasePlot: includeGL3D, + + convert: _dereq_('./convert'), + draw: _dereq_('./draw') +}; + +function includeGL3D(layoutIn, layoutOut) { + var GL3D = Registry.subplotsRegistry.gl3d; + if(!GL3D) return; + + var attrRegex = GL3D.attrRegex; + + var keys = Object.keys(layoutIn); + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + if(attrRegex.test(k) && (layoutIn[k].annotations || []).length) { + Lib.pushUnique(layoutOut._basePlotModules, GL3D); + Lib.pushUnique(layoutOut._subplots.gl3d, k); + } + } +} + +},{"../../lib":696,"../../registry":827,"./attributes":562,"./convert":563,"./defaults":564,"./draw":565}],567:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// a trimmed down version of: +// https://github.com/alexcjohnson/world-calendars/blob/master/dist/index.js + +module.exports = _dereq_('world-calendars/dist/main'); + +_dereq_('world-calendars/dist/plus'); + +_dereq_('world-calendars/dist/calendars/chinese'); +_dereq_('world-calendars/dist/calendars/coptic'); +_dereq_('world-calendars/dist/calendars/discworld'); +_dereq_('world-calendars/dist/calendars/ethiopian'); +_dereq_('world-calendars/dist/calendars/hebrew'); +_dereq_('world-calendars/dist/calendars/islamic'); +_dereq_('world-calendars/dist/calendars/julian'); +_dereq_('world-calendars/dist/calendars/mayan'); +_dereq_('world-calendars/dist/calendars/nanakshahi'); +_dereq_('world-calendars/dist/calendars/nepali'); +_dereq_('world-calendars/dist/calendars/persian'); +_dereq_('world-calendars/dist/calendars/taiwan'); +_dereq_('world-calendars/dist/calendars/thai'); +_dereq_('world-calendars/dist/calendars/ummalqura'); + +},{"world-calendars/dist/calendars/chinese":534,"world-calendars/dist/calendars/coptic":535,"world-calendars/dist/calendars/discworld":536,"world-calendars/dist/calendars/ethiopian":537,"world-calendars/dist/calendars/hebrew":538,"world-calendars/dist/calendars/islamic":539,"world-calendars/dist/calendars/julian":540,"world-calendars/dist/calendars/mayan":541,"world-calendars/dist/calendars/nanakshahi":542,"world-calendars/dist/calendars/nepali":543,"world-calendars/dist/calendars/persian":544,"world-calendars/dist/calendars/taiwan":545,"world-calendars/dist/calendars/thai":546,"world-calendars/dist/calendars/ummalqura":547,"world-calendars/dist/main":548,"world-calendars/dist/plus":549}],568:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var calendars = _dereq_('./calendars'); + +var Lib = _dereq_('../../lib'); +var constants = _dereq_('../../constants/numerical'); + +var EPOCHJD = constants.EPOCHJD; +var ONEDAY = constants.ONEDAY; + +var attributes = { + valType: 'enumerated', + values: Object.keys(calendars.calendars), + + editType: 'calc', + dflt: 'gregorian' +}; + +var handleDefaults = function(contIn, contOut, attr, dflt) { + var attrs = {}; + attrs[attr] = attributes; + + return Lib.coerce(contIn, contOut, attrs, attr, dflt); +}; + +var handleTraceDefaults = function(traceIn, traceOut, coords, layout) { + for(var i = 0; i < coords.length; i++) { + handleDefaults(traceIn, traceOut, coords[i] + 'calendar', layout.calendar); + } +}; + +// each calendar needs its own default canonical tick. I would love to use +// 2000-01-01 (or even 0000-01-01) for them all but they don't necessarily +// all support either of those dates. Instead I'll use the most significant +// number they *do* support, biased toward the present day. +var CANONICAL_TICK = { + chinese: '2000-01-01', + coptic: '2000-01-01', + discworld: '2000-01-01', + ethiopian: '2000-01-01', + hebrew: '5000-01-01', + islamic: '1000-01-01', + julian: '2000-01-01', + mayan: '5000-01-01', + nanakshahi: '1000-01-01', + nepali: '2000-01-01', + persian: '1000-01-01', + jalali: '1000-01-01', + taiwan: '1000-01-01', + thai: '2000-01-01', + ummalqura: '1400-01-01' +}; + +// Start on a Sunday - for week ticks +// Discworld and Mayan calendars don't have 7-day weeks but we're going to give them +// 7-day week ticks so start on our Sundays. +// If anyone really cares we can customize the auto tick spacings for these calendars. +var CANONICAL_SUNDAY = { + chinese: '2000-01-02', + coptic: '2000-01-03', + discworld: '2000-01-03', + ethiopian: '2000-01-05', + hebrew: '5000-01-01', + islamic: '1000-01-02', + julian: '2000-01-03', + mayan: '5000-01-01', + nanakshahi: '1000-01-05', + nepali: '2000-01-05', + persian: '1000-01-01', + jalali: '1000-01-01', + taiwan: '1000-01-04', + thai: '2000-01-04', + ummalqura: '1400-01-06' +}; + +var DFLTRANGE = { + chinese: ['2000-01-01', '2001-01-01'], + coptic: ['1700-01-01', '1701-01-01'], + discworld: ['1800-01-01', '1801-01-01'], + ethiopian: ['2000-01-01', '2001-01-01'], + hebrew: ['5700-01-01', '5701-01-01'], + islamic: ['1400-01-01', '1401-01-01'], + julian: ['2000-01-01', '2001-01-01'], + mayan: ['5200-01-01', '5201-01-01'], + nanakshahi: ['0500-01-01', '0501-01-01'], + nepali: ['2000-01-01', '2001-01-01'], + persian: ['1400-01-01', '1401-01-01'], + jalali: ['1400-01-01', '1401-01-01'], + taiwan: ['0100-01-01', '0101-01-01'], + thai: ['2500-01-01', '2501-01-01'], + ummalqura: ['1400-01-01', '1401-01-01'] +}; + +/* + * convert d3 templates to world-calendars templates, so our users only need + * to know d3's specifiers. Map space padding to no padding, and unknown fields + * to an ugly placeholder + */ +var UNKNOWN = '##'; +var d3ToWorldCalendars = { + 'd': {'0': 'dd', '-': 'd'}, // 2-digit or unpadded day of month + 'e': {'0': 'd', '-': 'd'}, // alternate, always unpadded day of month + 'a': {'0': 'D', '-': 'D'}, // short weekday name + 'A': {'0': 'DD', '-': 'DD'}, // full weekday name + 'j': {'0': 'oo', '-': 'o'}, // 3-digit or unpadded day of the year + 'W': {'0': 'ww', '-': 'w'}, // 2-digit or unpadded week of the year (Monday first) + 'm': {'0': 'mm', '-': 'm'}, // 2-digit or unpadded month number + 'b': {'0': 'M', '-': 'M'}, // short month name + 'B': {'0': 'MM', '-': 'MM'}, // full month name + 'y': {'0': 'yy', '-': 'yy'}, // 2-digit year (map unpadded to zero-padded) + 'Y': {'0': 'yyyy', '-': 'yyyy'}, // 4-digit year (map unpadded to zero-padded) + 'U': UNKNOWN, // Sunday-first week of the year + 'w': UNKNOWN, // day of the week [0(sunday),6] + // combined format, we replace the date part with the world-calendar version + // and the %X stays there for d3 to handle with time parts + 'c': {'0': 'D M d %X yyyy', '-': 'D M d %X yyyy'}, + 'x': {'0': 'mm/dd/yyyy', '-': 'mm/dd/yyyy'} +}; + +function worldCalFmt(fmt, x, calendar) { + var dateJD = Math.floor((x + 0.05) / ONEDAY) + EPOCHJD, + cDate = getCal(calendar).fromJD(dateJD), + i = 0, + modifier, directive, directiveLen, directiveObj, replacementPart; + while((i = fmt.indexOf('%', i)) !== -1) { + modifier = fmt.charAt(i + 1); + if(modifier === '0' || modifier === '-' || modifier === '_') { + directiveLen = 3; + directive = fmt.charAt(i + 2); + if(modifier === '_') modifier = '-'; + } + else { + directive = modifier; + modifier = '0'; + directiveLen = 2; + } + directiveObj = d3ToWorldCalendars[directive]; + if(!directiveObj) { + i += directiveLen; + } + else { + // code is recognized as a date part but world-calendars doesn't support it + if(directiveObj === UNKNOWN) replacementPart = UNKNOWN; + + // format the cDate according to the translated directive + else replacementPart = cDate.formatDate(directiveObj[modifier]); + + fmt = fmt.substr(0, i) + replacementPart + fmt.substr(i + directiveLen); + i += replacementPart.length; + } + } + return fmt; +} + +// cache world calendars, so we don't have to reinstantiate +// during each date-time conversion +var allCals = {}; +function getCal(calendar) { + var calendarObj = allCals[calendar]; + if(calendarObj) return calendarObj; + + calendarObj = allCals[calendar] = calendars.instance(calendar); + return calendarObj; +} + +function makeAttrs(description) { + return Lib.extendFlat({}, attributes, { description: description }); +} + +function makeTraceAttrsDescription(coord) { + return 'Sets the calendar system to use with `' + coord + '` date data.'; +} + +var xAttrs = { + xcalendar: makeAttrs(makeTraceAttrsDescription('x')) +}; + +var xyAttrs = Lib.extendFlat({}, xAttrs, { + ycalendar: makeAttrs(makeTraceAttrsDescription('y')) +}); + +var xyzAttrs = Lib.extendFlat({}, xyAttrs, { + zcalendar: makeAttrs(makeTraceAttrsDescription('z')) +}); + +var axisAttrs = makeAttrs([ + 'Sets the calendar system to use for `range` and `tick0`', + 'if this is a date axis. This does not set the calendar for', + 'interpreting data on this axis, that\'s specified in the trace', + 'or via the global `layout.calendar`' +].join(' ')); + +module.exports = { + moduleType: 'component', + name: 'calendars', + + schema: { + traces: { + scatter: xyAttrs, + bar: xyAttrs, + box: xyAttrs, + heatmap: xyAttrs, + contour: xyAttrs, + histogram: xyAttrs, + histogram2d: xyAttrs, + histogram2dcontour: xyAttrs, + scatter3d: xyzAttrs, + surface: xyzAttrs, + mesh3d: xyzAttrs, + scattergl: xyAttrs, + ohlc: xAttrs, + candlestick: xAttrs + }, + layout: { + calendar: makeAttrs([ + 'Sets the default calendar system to use for interpreting and', + 'displaying dates throughout the plot.' + ].join(' ')) + }, + subplots: { + xaxis: {calendar: axisAttrs}, + yaxis: {calendar: axisAttrs}, + scene: { + xaxis: {calendar: axisAttrs}, + // TODO: it's actually redundant to include yaxis and zaxis here + // because in the scene attributes these are the same object so merging + // into one merges into them all. However, I left them in for parity with + // cartesian, where yaxis is unused until we Plotschema.get() when we + // use its presence or absence to determine whether to delete attributes + // from yaxis if they only apply to x (rangeselector/rangeslider) + yaxis: {calendar: axisAttrs}, + zaxis: {calendar: axisAttrs} + }, + polar: { + radialaxis: {calendar: axisAttrs} + } + }, + transforms: { + filter: { + valuecalendar: makeAttrs([ + 'Sets the calendar system to use for `value`, if it is a date.' + ].join(' ')), + targetcalendar: makeAttrs([ + 'Sets the calendar system to use for `target`, if it is an', + 'array of dates. If `target` is a string (eg *x*) we use the', + 'corresponding trace attribute (eg `xcalendar`) if it exists,', + 'even if `targetcalendar` is provided.' + ].join(' ')) + } + } + }, + + layoutAttributes: attributes, + + handleDefaults: handleDefaults, + handleTraceDefaults: handleTraceDefaults, + + CANONICAL_SUNDAY: CANONICAL_SUNDAY, + CANONICAL_TICK: CANONICAL_TICK, + DFLTRANGE: DFLTRANGE, + + getCal: getCal, + worldCalFmt: worldCalFmt +}; + +},{"../../constants/numerical":673,"../../lib":696,"./calendars":567}],569:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +// IMPORTANT - default colors should be in hex for compatibility +exports.defaults = [ + '#1f77b4', // muted blue + '#ff7f0e', // safety orange + '#2ca02c', // cooked asparagus green + '#d62728', // brick red + '#9467bd', // muted purple + '#8c564b', // chestnut brown + '#e377c2', // raspberry yogurt pink + '#7f7f7f', // middle gray + '#bcbd22', // curry yellow-green + '#17becf' // blue-teal +]; + +exports.defaultLine = '#444'; + +exports.lightLine = '#eee'; + +exports.background = '#fff'; + +exports.borderLine = '#BEC8D9'; + +// with axis.color and Color.interp we aren't using lightLine +// itself anymore, instead interpolating between axis.color +// and the background color using tinycolor.mix. lightFraction +// gives back exactly lightLine if the other colors are defaults. +exports.lightFraction = 100 * (0xe - 0x4) / (0xf - 0x4); + +},{}],570:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var tinycolor = _dereq_('tinycolor2'); +var isNumeric = _dereq_('fast-isnumeric'); + +var color = module.exports = {}; + +var colorAttrs = _dereq_('./attributes'); +color.defaults = colorAttrs.defaults; +var defaultLine = color.defaultLine = colorAttrs.defaultLine; +color.lightLine = colorAttrs.lightLine; +var background = color.background = colorAttrs.background; + +/* + * tinyRGB: turn a tinycolor into an rgb string, but + * unlike the built-in tinycolor.toRgbString this never includes alpha + */ +color.tinyRGB = function(tc) { + var c = tc.toRgb(); + return 'rgb(' + Math.round(c.r) + ', ' + + Math.round(c.g) + ', ' + Math.round(c.b) + ')'; +}; + +color.rgb = function(cstr) { return color.tinyRGB(tinycolor(cstr)); }; + +color.opacity = function(cstr) { return cstr ? tinycolor(cstr).getAlpha() : 0; }; + +color.addOpacity = function(cstr, op) { + var c = tinycolor(cstr).toRgb(); + return 'rgba(' + Math.round(c.r) + ', ' + + Math.round(c.g) + ', ' + Math.round(c.b) + ', ' + op + ')'; +}; + +// combine two colors into one apparent color +// if back has transparency or is missing, +// color.background is assumed behind it +color.combine = function(front, back) { + var fc = tinycolor(front).toRgb(); + if(fc.a === 1) return tinycolor(front).toRgbString(); + + var bc = tinycolor(back || background).toRgb(), + bcflat = bc.a === 1 ? bc : { + r: 255 * (1 - bc.a) + bc.r * bc.a, + g: 255 * (1 - bc.a) + bc.g * bc.a, + b: 255 * (1 - bc.a) + bc.b * bc.a + }, + fcflat = { + r: bcflat.r * (1 - fc.a) + fc.r * fc.a, + g: bcflat.g * (1 - fc.a) + fc.g * fc.a, + b: bcflat.b * (1 - fc.a) + fc.b * fc.a + }; + return tinycolor(fcflat).toRgbString(); +}; + +/* + * Create a color that contrasts with cstr. + * + * If cstr is a dark color, we lighten it; if it's light, we darken. + * + * If lightAmount / darkAmount are used, we adjust by these percentages, + * otherwise we go all the way to white or black. + */ +color.contrast = function(cstr, lightAmount, darkAmount) { + var tc = tinycolor(cstr); + + if(tc.getAlpha() !== 1) tc = tinycolor(color.combine(cstr, background)); + + var newColor = tc.isDark() ? + (lightAmount ? tc.lighten(lightAmount) : background) : + (darkAmount ? tc.darken(darkAmount) : defaultLine); + + return newColor.toString(); +}; + +color.stroke = function(s, c) { + var tc = tinycolor(c); + s.style({'stroke': color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()}); +}; + +color.fill = function(s, c) { + var tc = tinycolor(c); + s.style({ + 'fill': color.tinyRGB(tc), + 'fill-opacity': tc.getAlpha() + }); +}; + +// search container for colors with the deprecated rgb(fractions) format +// and convert them to rgb(0-255 values) +color.clean = function(container) { + if(!container || typeof container !== 'object') return; + + var keys = Object.keys(container), + i, + j, + key, + val; + + for(i = 0; i < keys.length; i++) { + key = keys[i]; + val = container[key]; + + // only sanitize keys that end in "color" or "colorscale" + if(key.substr(key.length - 5) === 'color') { + if(Array.isArray(val)) { + for(j = 0; j < val.length; j++) val[j] = cleanOne(val[j]); + } + else container[key] = cleanOne(val); + } + else if(key.substr(key.length - 10) === 'colorscale' && Array.isArray(val)) { + // colorscales have the format [[0, color1], [frac, color2], ... [1, colorN]] + for(j = 0; j < val.length; j++) { + if(Array.isArray(val[j])) val[j][1] = cleanOne(val[j][1]); + } + } + // recurse into arrays of objects, and plain objects + else if(Array.isArray(val)) { + var el0 = val[0]; + if(!Array.isArray(el0) && el0 && typeof el0 === 'object') { + for(j = 0; j < val.length; j++) color.clean(val[j]); + } + } + else if(val && typeof val === 'object') color.clean(val); + } +}; + +function cleanOne(val) { + if(isNumeric(val) || typeof val !== 'string') return val; + + var valTrim = val.trim(); + if(valTrim.substr(0, 3) !== 'rgb') return val; + + var match = valTrim.match(/^rgba?\s*\(([^()]*)\)$/); + if(!match) return val; + + var parts = match[1].trim().split(/\s*[\s,]\s*/), + rgba = valTrim.charAt(3) === 'a' && parts.length === 4; + if(!rgba && parts.length !== 3) return val; + + for(var i = 0; i < parts.length; i++) { + if(!parts[i].length) return val; + parts[i] = Number(parts[i]); + + // all parts must be non-negative numbers + if(!(parts[i] >= 0)) return val; + // alpha>1 gets clipped to 1 + if(i === 3) { + if(parts[i] > 1) parts[i] = 1; + } + // r, g, b must be < 1 (ie 1 itself is not allowed) + else if(parts[i] >= 1) return val; + } + + var rgbStr = Math.round(parts[0] * 255) + ', ' + + Math.round(parts[1] * 255) + ', ' + + Math.round(parts[2] * 255); + + if(rgba) return 'rgba(' + rgbStr + ', ' + parts[3] + ')'; + return 'rgb(' + rgbStr + ')'; +} + +},{"./attributes":569,"fast-isnumeric":214,"tinycolor2":514}],571:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + + +module.exports = overrideAll({ +// TODO: only right is supported currently +// orient: { +// valType: 'enumerated', +// +// values: ['left', 'right', 'top', 'bottom'], +// dflt: 'right', +// +// }, + thicknessmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'pixels', + + }, + thickness: { + valType: 'number', + + min: 0, + dflt: 30, + + }, + lenmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'fraction', + + }, + len: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + x: { + valType: 'number', + dflt: 1.02, + min: -2, + max: 3, + + + }, + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + + }, + xpad: { + valType: 'number', + + min: 0, + dflt: 10, + + }, + y: { + valType: 'number', + + dflt: 0.5, + min: -2, + max: 3, + + }, + yanchor: { + valType: 'enumerated', + values: ['top', 'middle', 'bottom'], + + dflt: 'middle', + + }, + ypad: { + valType: 'number', + + min: 0, + dflt: 10, + + }, + // a possible line around the bar itself + outlinecolor: axesAttrs.linecolor, + outlinewidth: axesAttrs.linewidth, + // Should outlinewidth have {dflt: 0} ? + // another possible line outside the padding and tick labels + bordercolor: axesAttrs.linecolor, + borderwidth: { + valType: 'number', + + min: 0, + dflt: 0, + + }, + bgcolor: { + valType: 'color', + + dflt: 'rgba(0,0,0,0)', + + }, + // tick and title properties named and function exactly as in axes + tickmode: axesAttrs.tickmode, + nticks: axesAttrs.nticks, + tick0: axesAttrs.tick0, + dtick: axesAttrs.dtick, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}), + ticklen: axesAttrs.ticklen, + tickwidth: axesAttrs.tickwidth, + tickcolor: axesAttrs.tickcolor, + showticklabels: axesAttrs.showticklabels, + tickfont: fontAttrs({ + + }), + tickangle: axesAttrs.tickangle, + tickformat: axesAttrs.tickformat, + tickformatstops: axesAttrs.tickformatstops, + tickprefix: axesAttrs.tickprefix, + showtickprefix: axesAttrs.showtickprefix, + ticksuffix: axesAttrs.ticksuffix, + showticksuffix: axesAttrs.showticksuffix, + separatethousands: axesAttrs.separatethousands, + exponentformat: axesAttrs.exponentformat, + showexponent: axesAttrs.showexponent, + title: { + valType: 'string', + + + }, + titlefont: fontAttrs({ + + }), + titleside: { + valType: 'enumerated', + values: ['right', 'top', 'bottom'], + + dflt: 'top', + + } +}, 'colorbars', 'from-root'); + +},{"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/cartesian/layout_attributes":757,"../../plots/font_attributes":771}],572:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawColorbar = _dereq_('./draw'); + +/** + * connectColorbar: create a colorbar from a trace, using its module to + * describe the connection. + * + * @param {DOM element} gd + * + * @param {Array} cd + * calcdata entry for this trace. cd[0].trace is the trace itself, and the + * colorbar object will be stashed in cd[0].t.cb + * + * @param {object|function} moduleOpts + * may be a function(gd, cd) to override the standard handling below. If + * an object, should have these keys: + * @param {Optional(string)} moduleOpts.container + * name of the container inside the trace where the colorbar and colorscale + * attributes live (ie 'marker', 'line') - omit if they're at the trace root. + * @param {string} moduleOpts.min + * name of the attribute holding the value of the minimum color + * @param {string} moduleOpts.max + * name of the attribute holding the value of the maximum color + * @param {Optional(string)} moduleOpts.vals + * name of the attribute holding the (numeric) color data + * used only if min/max fail. May be omitted if these are always + * pre-calculated. + */ +module.exports = function connectColorbar(gd, cd, moduleOpts) { + if(typeof moduleOpts === 'function') return moduleOpts(gd, cd); + + var trace = cd[0].trace; + var cbId = 'cb' + trace.uid; + var containerName = moduleOpts.container; + var container = containerName ? trace[containerName] : trace; + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + if(!container || !container.showscale) return; + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + + cb.fillgradient(container.colorscale) + .zrange([container[moduleOpts.min], container[moduleOpts.max]]) + .options(container.colorbar)(); +}; + +},{"./draw":575}],573:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + cn: { + colorbar: 'colorbar', + cbbg: 'cbbg', + cbfill: 'cbfill', + cbfills: 'cbfills', + cbline: 'cbline', + cblines: 'cblines', + cbaxis: 'cbaxis', + cbtitleunshift: 'cbtitleunshift', + cbtitle: 'cbtitle', + cboutline: 'cboutline', + crisp: 'crisp', + jsPlaceholder: 'js-placeholder' + } +}; + +},{}],574:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Template = _dereq_('../../plot_api/plot_template'); + +var handleTickValueDefaults = _dereq_('../../plots/cartesian/tick_value_defaults'); +var handleTickMarkDefaults = _dereq_('../../plots/cartesian/tick_mark_defaults'); +var handleTickLabelDefaults = _dereq_('../../plots/cartesian/tick_label_defaults'); + +var attributes = _dereq_('./attributes'); + + +module.exports = function colorbarDefaults(containerIn, containerOut, layout) { + var colorbarOut = Template.newContainer(containerOut, 'colorbar'), + colorbarIn = containerIn.colorbar || {}; + + function coerce(attr, dflt) { + return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt); + } + + var thicknessmode = coerce('thicknessmode'); + coerce('thickness', (thicknessmode === 'fraction') ? + 30 / (layout.width - layout.margin.l - layout.margin.r) : + 30 + ); + + var lenmode = coerce('lenmode'); + coerce('len', (lenmode === 'fraction') ? + 1 : + layout.height - layout.margin.t - layout.margin.b + ); + + coerce('x'); + coerce('xanchor'); + coerce('xpad'); + coerce('y'); + coerce('yanchor'); + coerce('ypad'); + Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']); + + coerce('outlinecolor'); + coerce('outlinewidth'); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('bgcolor'); + + handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear'); + + var opts = {outerTicks: false, font: layout.font}; + handleTickLabelDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts); + handleTickMarkDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts); + + coerce('title', layout._dfltTitle.colorbar); + Lib.coerceFont(coerce, 'titlefont', layout.font); + coerce('titleside'); +}; + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../plots/cartesian/tick_label_defaults":764,"../../plots/cartesian/tick_mark_defaults":765,"../../plots/cartesian/tick_value_defaults":766,"./attributes":571}],575:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); + +var Plots = _dereq_('../../plots/plots'); +var Registry = _dereq_('../../registry'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var dragElement = _dereq_('../dragelement'); +var Lib = _dereq_('../../lib'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var setCursor = _dereq_('../../lib/setcursor'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); +var Titles = _dereq_('../titles'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var alignmentConstants = _dereq_('../../constants/alignment'); +var LINE_SPACING = alignmentConstants.LINE_SPACING; +var FROM_TL = alignmentConstants.FROM_TL; +var FROM_BR = alignmentConstants.FROM_BR; + +var handleAxisDefaults = _dereq_('../../plots/cartesian/axis_defaults'); +var handleAxisPositionDefaults = _dereq_('../../plots/cartesian/position_defaults'); +var axisLayoutAttrs = _dereq_('../../plots/cartesian/layout_attributes'); + +var attributes = _dereq_('./attributes'); +var cn = _dereq_('./constants').cn; + +module.exports = function draw(gd, id) { + // opts: options object, containing everything from attributes + // plus a few others that are the equivalent of the colorbar "data" + var opts = {}; + for(var k in attributes) { + opts[k] = null; + } + // fillcolor can be a d3 scale, domain is z values, range is colors + // or leave it out for no fill, + // or set to a string constant for single-color fill + opts.fillcolor = null; + // line.color has the same options as fillcolor + opts.line = {color: null, width: null, dash: null}; + // levels of lines to draw. + // note that this DOES NOT determine the extent of the bar + // that's given by the domain of fillcolor + // (or line.color if no fillcolor domain) + opts.levels = {start: null, end: null, size: null}; + // separate fill levels (for example, heatmap coloring of a + // contour map) if this is omitted, fillcolors will be + // evaluated halfway between levels + opts.filllevels = null; + // for continuous colorscales: fill with a gradient instead of explicit levels + // value should be the colorscale [[0, c0], [v1, c1], ..., [1, cEnd]] + opts.fillgradient = null; + // when using a gradient, we need the data range specified separately + opts.zrange = null; + + function component() { + var fullLayout = gd._fullLayout, + gs = fullLayout._size; + if((typeof opts.fillcolor !== 'function') && + (typeof opts.line.color !== 'function') && + !opts.fillgradient) { + fullLayout._infolayer.selectAll('g.' + id).remove(); + return; + } + var zrange = opts.zrange || (d3.extent(((typeof opts.fillcolor === 'function') ? + opts.fillcolor : opts.line.color).domain())); + var linelevels = []; + var filllevels = []; + var linecolormap = typeof opts.line.color === 'function' ? + opts.line.color : function() { return opts.line.color; }; + var fillcolormap = typeof opts.fillcolor === 'function' ? + opts.fillcolor : function() { return opts.fillcolor; }; + var l; + var i; + + var l0 = opts.levels.end + opts.levels.size / 100, + ls = opts.levels.size, + zr0 = (1.001 * zrange[0] - 0.001 * zrange[1]), + zr1 = (1.001 * zrange[1] - 0.001 * zrange[0]); + for(i = 0; i < 1e5; i++) { + l = opts.levels.start + i * ls; + if(ls > 0 ? (l >= l0) : (l <= l0)) break; + if(l > zr0 && l < zr1) linelevels.push(l); + } + + if(opts.fillgradient) { + filllevels = [0]; + } + else if(typeof opts.fillcolor === 'function') { + if(opts.filllevels) { + l0 = opts.filllevels.end + opts.filllevels.size / 100; + ls = opts.filllevels.size; + for(i = 0; i < 1e5; i++) { + l = opts.filllevels.start + i * ls; + if(ls > 0 ? (l >= l0) : (l <= l0)) break; + if(l > zrange[0] && l < zrange[1]) filllevels.push(l); + } + } + else { + filllevels = linelevels.map(function(v) { + return v - opts.levels.size / 2; + }); + filllevels.push(filllevels[filllevels.length - 1] + + opts.levels.size); + } + } + else if(opts.fillcolor && typeof opts.fillcolor === 'string') { + // doesn't matter what this value is, with a single value + // we'll make a single fill rect covering the whole bar + filllevels = [0]; + } + + if(opts.levels.size < 0) { + linelevels.reverse(); + filllevels.reverse(); + } + + // now make a Plotly Axes object to scale with and draw ticks + // TODO: does not support orientation other than right + + // we calculate pixel sizes based on the specified graph size, + // not the actual (in case something pushed the margins around) + // which is a little odd but avoids an odd iterative effect + // when the colorbar itself is pushing the margins. + // but then the fractional size is calculated based on the + // actual graph size, so that the axes will size correctly. + var plotHeight = gs.h, + plotWidth = gs.w, + thickPx = Math.round(opts.thickness * + (opts.thicknessmode === 'fraction' ? plotWidth : 1)), + thickFrac = thickPx / gs.w, + lenPx = Math.round(opts.len * + (opts.lenmode === 'fraction' ? plotHeight : 1)), + lenFrac = lenPx / gs.h, + xpadFrac = opts.xpad / gs.w, + yExtraPx = (opts.borderwidth + opts.outlinewidth) / 2, + ypadFrac = opts.ypad / gs.h, + + // x positioning: do it initially just for left anchor, + // then fix at the end (since we don't know the width yet) + xLeft = Math.round(opts.x * gs.w + opts.xpad), + // for dragging... this is getting a little muddled... + xLeftFrac = opts.x - thickFrac * + ({middle: 0.5, right: 1}[opts.xanchor]||0), + + // y positioning we can do correctly from the start + yBottomFrac = opts.y + lenFrac * + (({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5), + yBottomPx = Math.round(gs.h * (1 - yBottomFrac)), + yTopPx = yBottomPx - lenPx, + titleEl, + cbAxisIn = { + type: 'linear', + range: zrange, + tickmode: opts.tickmode, + nticks: opts.nticks, + tick0: opts.tick0, + dtick: opts.dtick, + tickvals: opts.tickvals, + ticktext: opts.ticktext, + ticks: opts.ticks, + ticklen: opts.ticklen, + tickwidth: opts.tickwidth, + tickcolor: opts.tickcolor, + showticklabels: opts.showticklabels, + tickfont: opts.tickfont, + tickangle: opts.tickangle, + tickformat: opts.tickformat, + exponentformat: opts.exponentformat, + separatethousands: opts.separatethousands, + showexponent: opts.showexponent, + showtickprefix: opts.showtickprefix, + tickprefix: opts.tickprefix, + showticksuffix: opts.showticksuffix, + ticksuffix: opts.ticksuffix, + title: opts.title, + titlefont: opts.titlefont, + showline: true, + anchor: 'free', + position: 1 + }, + cbAxisOut = { + type: 'linear', + _id: 'y' + id + }, + axisOptions = { + letter: 'y', + font: fullLayout.font, + noHover: true, + calendar: fullLayout.calendar // not really necessary (yet?) + }; + + // Coerce w.r.t. Axes layoutAttributes: + // re-use axes.js logic without updating _fullData + function coerce(attr, dflt) { + return Lib.coerce(cbAxisIn, cbAxisOut, axisLayoutAttrs, attr, dflt); + } + + // Prepare the Plotly axis object + handleAxisDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions, fullLayout); + handleAxisPositionDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions); + + // position can't go in through supplyDefaults + // because that restricts it to [0,1] + cbAxisOut.position = opts.x + xpadFrac + thickFrac; + + // save for other callers to access this axis + component.axis = cbAxisOut; + + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + cbAxisOut.titleside = opts.titleside; + cbAxisOut.titlex = opts.x + xpadFrac; + cbAxisOut.titley = yBottomFrac + + (opts.titleside === 'top' ? lenFrac - ypadFrac : ypadFrac); + } + + if(opts.line.color && opts.tickmode === 'auto') { + cbAxisOut.tickmode = 'linear'; + cbAxisOut.tick0 = opts.levels.start; + var dtick = opts.levels.size; + // expand if too many contours, so we don't get too many ticks + var autoNtick = Lib.constrain( + (yBottomPx - yTopPx) / 50, 4, 15) + 1, + dtFactor = (zrange[1] - zrange[0]) / + ((opts.nticks || autoNtick) * dtick); + if(dtFactor > 1) { + var dtexp = Math.pow(10, Math.floor( + Math.log(dtFactor) / Math.LN10)); + dtick *= dtexp * Lib.roundUp(dtFactor / dtexp, [2, 5, 10]); + // if the contours are at round multiples, reset tick0 + // so they're still at round multiples. Otherwise, + // keep the first label on the first contour level + if((Math.abs(opts.levels.start) / + opts.levels.size + 1e-6) % 1 < 2e-6) { + cbAxisOut.tick0 = 0; + } + } + cbAxisOut.dtick = dtick; + } + + // set domain after init, because we may want to + // allow it outside [0,1] + cbAxisOut.domain = [ + yBottomFrac + ypadFrac, + yBottomFrac + lenFrac - ypadFrac + ]; + cbAxisOut.setScale(); + + // now draw the elements + var container = Lib.ensureSingle(fullLayout._infolayer, 'g', id, function(s) { + s.classed(cn.colorbar, true) + .each(function() { + var s = d3.select(this); + s.append('rect').classed(cn.cbbg, true); + s.append('g').classed(cn.cbfills, true); + s.append('g').classed(cn.cblines, true); + s.append('g').classed(cn.cbaxis, true).classed(cn.crisp, true); + s.append('g').classed(cn.cbtitleunshift, true) + .append('g').classed(cn.cbtitle, true); + s.append('rect').classed(cn.cboutline, true); + s.select('.cbtitle').datum(0); + }); + }); + + container.attr('transform', 'translate(' + Math.round(gs.l) + + ',' + Math.round(gs.t) + ')'); + // TODO: this opposite transform is a hack until we make it + // more rational which items get this offset + var titleCont = container.select('.cbtitleunshift') + .attr('transform', 'translate(-' + + Math.round(gs.l) + ',-' + + Math.round(gs.t) + ')'); + + cbAxisOut._axislayer = container.select('.cbaxis'); + var titleHeight = 0; + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + // draw the title so we know how much room it needs + // when we squish the axis. This one only applies to + // top or bottom titles, not right side. + var x = gs.l + (opts.x + xpadFrac) * gs.w, + fontSize = cbAxisOut.titlefont.size, + y; + + if(opts.titleside === 'top') { + y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h + + gs.t + 3 + fontSize * 0.75; + } + else { + y = (1 - (yBottomFrac + ypadFrac)) * gs.h + + gs.t - 3 - fontSize * 0.25; + } + drawTitle(cbAxisOut._id + 'title', { + attributes: {x: x, y: y, 'text-anchor': 'start'} + }); + } + + function drawAxis() { + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + // squish the axis top to make room for the title + var titleGroup = container.select('.cbtitle'), + titleText = titleGroup.select('text'), + titleTrans = + [-opts.outlinewidth / 2, opts.outlinewidth / 2], + mathJaxNode = titleGroup + .select('.h' + cbAxisOut._id + 'title-math-group') + .node(), + lineSize = 15.6; + if(titleText.node()) { + lineSize = + parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING; + } + if(mathJaxNode) { + titleHeight = Drawing.bBox(mathJaxNode).height; + if(titleHeight > lineSize) { + // not entirely sure how mathjax is doing + // vertical alignment, but this seems to work. + titleTrans[1] -= (titleHeight - lineSize) / 2; + } + } + else if(titleText.node() && + !titleText.classed(cn.jsPlaceholder)) { + titleHeight = Drawing.bBox(titleText.node()).height; + } + if(titleHeight) { + // buffer btwn colorbar and title + // TODO: configurable + titleHeight += 5; + + if(opts.titleside === 'top') { + cbAxisOut.domain[1] -= titleHeight / gs.h; + titleTrans[1] *= -1; + } + else { + cbAxisOut.domain[0] += titleHeight / gs.h; + var nlines = svgTextUtils.lineCount(titleText); + titleTrans[1] += (1 - nlines) * lineSize; + } + + titleGroup.attr('transform', + 'translate(' + titleTrans + ')'); + + cbAxisOut.setScale(); + } + } + + container.selectAll('.cbfills,.cblines') + .attr('transform', 'translate(0,' + + Math.round(gs.h * (1 - cbAxisOut.domain[1])) + ')'); + + cbAxisOut._axislayer.attr('transform', 'translate(0,' + + Math.round(-gs.t) + ')'); + + var fills = container.select('.cbfills') + .selectAll('rect.cbfill') + .data(filllevels); + fills.enter().append('rect') + .classed(cn.cbfill, true) + .style('stroke', 'none'); + fills.exit().remove(); + + var zBounds = zrange + .map(cbAxisOut.c2p) + .map(Math.round) + .sort(function(a, b) { return a - b; }); + + fills.each(function(d, i) { + var z = [ + (i === 0) ? zrange[0] : + (filllevels[i] + filllevels[i - 1]) / 2, + (i === filllevels.length - 1) ? zrange[1] : + (filllevels[i] + filllevels[i + 1]) / 2 + ] + .map(cbAxisOut.c2p) + .map(Math.round); + + // offset the side adjoining the next rectangle so they + // overlap, to prevent antialiasing gaps + z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]); + + // Colorbar cannot currently support opacities so we + // use an opaque fill even when alpha channels present + var fillEl = d3.select(this).attr({ + x: xLeft, + width: Math.max(thickPx, 2), + y: d3.min(z), + height: Math.max(d3.max(z) - d3.min(z), 2), + }); + + if(opts.fillgradient) { + Drawing.gradient(fillEl, gd, id, 'vertical', + opts.fillgradient, 'fill'); + } + else { + // Tinycolor can't handle exponents and + // at this scale, removing it makes no difference. + var colorString = fillcolormap(d).replace('e-', ''); + fillEl.attr('fill', tinycolor(colorString).toHexString()); + } + }); + + var lines = container.select('.cblines') + .selectAll('path.cbline') + .data(opts.line.color && opts.line.width ? + linelevels : []); + lines.enter().append('path') + .classed(cn.cbline, true); + lines.exit().remove(); + lines.each(function(d) { + d3.select(this) + .attr('d', 'M' + xLeft + ',' + + (Math.round(cbAxisOut.c2p(d)) + (opts.line.width / 2) % 1) + + 'h' + thickPx) + .call(Drawing.lineGroupStyle, + opts.line.width, linecolormap(d), opts.line.dash); + }); + + // force full redraw of labels and ticks + cbAxisOut._axislayer.selectAll('g.' + cbAxisOut._id + 'tick,path') + .remove(); + + cbAxisOut._pos = xLeft + thickPx + + (opts.outlinewidth||0) / 2 - (opts.ticks === 'outside' ? 1 : 0); + cbAxisOut.side = 'right'; + + // separate out axis and title drawing, + // so we don't need such complicated logic in Titles.draw + // if title is on the top or bottom, we've already drawn it + // this title call only handles side=right + return Lib.syncOrAsync([ + function() { + return Axes.doTicksSingle(gd, cbAxisOut, true); + }, + function() { + if(['top', 'bottom'].indexOf(opts.titleside) === -1) { + var fontSize = cbAxisOut.titlefont.size, + y = cbAxisOut._offset + cbAxisOut._length / 2, + x = gs.l + (cbAxisOut.position || 0) * gs.w + ((cbAxisOut.side === 'right') ? + 10 + fontSize * ((cbAxisOut.showticklabels ? 1 : 0.5)) : + -10 - fontSize * ((cbAxisOut.showticklabels ? 0.5 : 0))); + + // the 'h' + is a hack to get around the fact that + // convertToTspans rotates any 'y...' class by 90 degrees. + // TODO: find a better way to control this. + drawTitle('h' + cbAxisOut._id + 'title', { + avoid: { + selection: d3.select(gd).selectAll('g.' + cbAxisOut._id + 'tick'), + side: opts.titleside, + offsetLeft: gs.l, + offsetTop: 0, + maxShift: fullLayout.width + }, + attributes: {x: x, y: y, 'text-anchor': 'middle'}, + transform: {rotate: '-90', offset: 0} + }); + } + }]); + } + + function drawTitle(titleClass, titleOpts) { + var trace = getTrace(); + var propName = 'colorbar.title'; + var containerName = trace._module.colorbar.container; + if(containerName) propName = containerName + '.' + propName; + + var dfltTitleOpts = { + propContainer: cbAxisOut, + propName: propName, + traceIndex: trace.index, + placeholder: fullLayout._dfltTitle.colorbar, + containerGroup: container.select('.cbtitle') + }; + + // this class-to-rotate thing with convertToTspans is + // getting hackier and hackier... delete groups with the + // wrong class (in case earlier the colorbar was drawn on + // a different side, I think?) + var otherClass = titleClass.charAt(0) === 'h' ? + titleClass.substr(1) : ('h' + titleClass); + container.selectAll('.' + otherClass + ',.' + otherClass + '-math-group') + .remove(); + + Titles.draw(gd, titleClass, + extendFlat(dfltTitleOpts, titleOpts || {})); + } + + function positionCB() { + // wait for the axis & title to finish rendering before + // continuing positioning + // TODO: why are we redrawing multiple times now with this? + // I guess autoMargin doesn't like being post-promise? + var innerWidth = thickPx + opts.outlinewidth / 2 + + Drawing.bBox(cbAxisOut._axislayer.node()).width; + titleEl = titleCont.select('text'); + if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) { + var mathJaxNode = titleCont + .select('.h' + cbAxisOut._id + 'title-math-group') + .node(), + titleWidth; + if(mathJaxNode && + ['top', 'bottom'].indexOf(opts.titleside) !== -1) { + titleWidth = Drawing.bBox(mathJaxNode).width; + } + else { + // note: the formula below works for all titlesides, + // (except for top/bottom mathjax, above) + // but the weird gs.l is because the titleunshift + // transform gets removed by Drawing.bBox + titleWidth = + Drawing.bBox(titleCont.node()).right - + xLeft - gs.l; + } + innerWidth = Math.max(innerWidth, titleWidth); + } + + var outerwidth = 2 * opts.xpad + innerWidth + + opts.borderwidth + opts.outlinewidth / 2, + outerheight = yBottomPx - yTopPx; + + container.select('.cbbg').attr({ + x: xLeft - opts.xpad - + (opts.borderwidth + opts.outlinewidth) / 2, + y: yTopPx - yExtraPx, + width: Math.max(outerwidth, 2), + height: Math.max(outerheight + 2 * yExtraPx, 2) + }) + .call(Color.fill, opts.bgcolor) + .call(Color.stroke, opts.bordercolor) + .style({'stroke-width': opts.borderwidth}); + + container.selectAll('.cboutline').attr({ + x: xLeft, + y: yTopPx + opts.ypad + + (opts.titleside === 'top' ? titleHeight : 0), + width: Math.max(thickPx, 2), + height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2) + }) + .call(Color.stroke, opts.outlinecolor) + .style({ + fill: 'None', + 'stroke-width': opts.outlinewidth + }); + + // fix positioning for xanchor!='left' + var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) * + outerwidth; + container.attr('transform', + 'translate(' + (gs.l - xoffset) + ',' + gs.t + ')'); + + // auto margin adjustment + var marginOpts = {}; + var tFrac = FROM_TL[opts.yanchor]; + var bFrac = FROM_BR[opts.yanchor]; + if(opts.lenmode === 'pixels') { + marginOpts.y = opts.y; + marginOpts.t = outerheight * tFrac; + marginOpts.b = outerheight * bFrac; + } + else { + marginOpts.t = marginOpts.b = 0; + marginOpts.yt = opts.y + opts.len * tFrac; + marginOpts.yb = opts.y - opts.len * bFrac; + } + + var lFrac = FROM_TL[opts.xanchor]; + var rFrac = FROM_BR[opts.xanchor]; + if(opts.thicknessmode === 'pixels') { + marginOpts.x = opts.x; + marginOpts.l = outerwidth * lFrac; + marginOpts.r = outerwidth * rFrac; + } + else { + var extraThickness = outerwidth - thickPx; + marginOpts.l = extraThickness * lFrac; + marginOpts.r = extraThickness * rFrac; + marginOpts.xl = opts.x - opts.thickness * lFrac; + marginOpts.xr = opts.x + opts.thickness * rFrac; + } + Plots.autoMargin(gd, id, marginOpts); + } + + var cbDone = Lib.syncOrAsync([ + Plots.previousPromises, + drawAxis, + Plots.previousPromises, + positionCB + ], gd); + + if(cbDone && cbDone.then) (gd._promises || []).push(cbDone); + + // dragging... + if(gd._context.edits.colorbarPosition) { + var t0, + xf, + yf; + + dragElement.init({ + element: container.node(), + gd: gd, + prepFn: function() { + t0 = container.attr('transform'); + setCursor(container); + }, + moveFn: function(dx, dy) { + container.attr('transform', + t0 + ' ' + 'translate(' + dx + ',' + dy + ')'); + + xf = dragElement.align(xLeftFrac + (dx / gs.w), thickFrac, + 0, 1, opts.xanchor); + yf = dragElement.align(yBottomFrac - (dy / gs.h), lenFrac, + 0, 1, opts.yanchor); + + var csr = dragElement.getCursor(xf, yf, + opts.xanchor, opts.yanchor); + setCursor(container, csr); + }, + doneFn: function() { + setCursor(container); + + if(xf !== undefined && yf !== undefined) { + Registry.call('restyle', + gd, + {'colorbar.x': xf, 'colorbar.y': yf}, + getTrace().index + ); + } + } + }); + } + return cbDone; + } + + function getTrace() { + var idNum = id.substr(2), + i, + trace; + for(i = 0; i < gd._fullData.length; i++) { + trace = gd._fullData[i]; + if(trace.uid === idNum) return trace; + } + } + + // setter/getters for every item defined in opts + Object.keys(opts).forEach(function(name) { + component[name] = function(v) { + // getter + if(!arguments.length) return opts[name]; + + // setter - for multi-part properties, + // set only the parts that are provided + opts[name] = Lib.isPlainObject(opts[name]) ? + Lib.extendFlat(opts[name], v) : + v; + + return component; + }; + }); + + // or use .options to set multiple options at once via a dictionary + component.options = function(o) { + for(var name in o) { + // in case something random comes through + // that's not an option, ignore it + if(typeof component[name] === 'function') { + component[name](o[name]); + } + } + return component; + }; + + component._opts = opts; + + return component; +}; + +},{"../../constants/alignment":668,"../../lib":696,"../../lib/extend":685,"../../lib/setcursor":716,"../../lib/svg_text_utils":720,"../../plots/cartesian/axes":744,"../../plots/cartesian/axis_defaults":746,"../../plots/cartesian/layout_attributes":757,"../../plots/cartesian/position_defaults":760,"../../plots/plots":808,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"../titles":661,"./attributes":571,"./constants":573,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"tinycolor2":514}],576:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + + +module.exports = function hasColorbar(container) { + return Lib.isPlainObject(container.colorbar); +}; + +},{"../../lib":696}],577:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var palettes = _dereq_('./scales.js'); +var paletteStr = Object.keys(palettes); + +function code(s) { + return '`' + s + '`'; +} + +/** + * Make colorscale attribute declarations for + * + * - colorscale, + * - (c|z)auto, (c|z)min, (c|z)max, + * - autocolorscale, reversescale, + * - showscale (optionally) + * - color (optionally) + * + * @param {string} context (dflt: '', i.e. from trace root): + * the container this is in ('', *marker*, *marker.line* etc) + * + * @param {object} opts: + * - cLetter {string} (dflt: 'c'): + * leading letter for 'min', 'max and 'auto' attribute (either 'z' or 'c') + * + * - colorAttr {string} (dflt: 'z' if `cLetter: 'z'`, 'color' if `cLetter: 'c'`): + * (for descriptions) sets the name of the color attribute that maps to the colorscale. + * + * N.B. if `colorAttr: 'color'`, we include the `color` declaration here. + * + * - onlyIfNumerical {string} (dflt: false' if `cLetter: 'z'`, true if `cLetter: 'c'`): + * (for descriptions) set to true if colorscale attribute only + * + * - colorscaleDflt {string}: + * overrides the colorscale dflt + * + * - autoColorDflt {boolean} (dflt true): + * normally autocolorscale.dflt is `true`, but pass `false` to override + * + * - noScale {boolean} (dflt: true if `context: 'marker.line'`, false otherwise): + * set to `false` to not include showscale attribute (e.g. for 'marker.line') + * + * - showScaleDflt {boolean} (dflt: true if `cLetter: 'z'`, false otherwise) + * + * - editTypeOverride {boolean} (dflt: ''): + * most of these attributes already require a recalc, but the ones that do not + * have editType *style* or *plot* unless you override (presumably with *calc*) + * + * - anim {boolean) (dflt: undefined): is 'color' animatable? + * + * @return {object} + */ +module.exports = function colorScaleAttrs(context, opts) { + context = context || ''; + opts = opts || {}; + + var cLetter = opts.cLetter || 'c'; + var onlyIfNumerical = ('onlyIfNumerical' in opts) ? opts.onlyIfNumerical : Boolean(context); + var noScale = ('noScale' in opts) ? opts.noScale : context === 'marker.line'; + var showScaleDflt = ('showScaleDflt' in opts) ? opts.showScaleDflt : cLetter === 'z'; + var colorscaleDflt = typeof opts.colorscaleDflt === 'string' ? palettes[opts.colorscaleDflt] : null; + var editTypeOverride = opts.editTypeOverride || ''; + var contextHead = context ? (context + '.') : ''; + + var colorAttr, colorAttrFull; + + if('colorAttr' in opts) { + colorAttr = opts.colorAttr; + colorAttrFull = opts.colorAttr; + } else { + colorAttr = {z: 'z', c: 'color'}[cLetter]; + colorAttrFull = 'in ' + code(contextHead + colorAttr); + } + + var effectDesc = onlyIfNumerical ? + ' Has an effect only if ' + colorAttrFull + 'is set to a numerical array.' : + ''; + + var auto = cLetter + 'auto'; + var min = cLetter + 'min'; + var max = cLetter + 'max'; + var minFull = code(contextHead + min); + var maxFull = code(contextHead + max); + var minmaxFull = minFull + ' and ' + maxFull; + var autoImpliedEdits = {}; + autoImpliedEdits[min] = autoImpliedEdits[max] = undefined; + var minmaxImpliedEdits = {}; + minmaxImpliedEdits[auto] = false; + + var attrs = {}; + + if(colorAttr === 'color') { + attrs.color = { + valType: 'color', + arrayOk: true, + + editType: editTypeOverride || 'style', + + }; + + if(opts.anim) { + attrs.color.anim = true; + } + } + + attrs[auto] = { + valType: 'boolean', + + dflt: true, + editType: 'calc', + impliedEdits: autoImpliedEdits, + + }; + + attrs[min] = { + valType: 'number', + + dflt: null, + editType: editTypeOverride || 'plot', + impliedEdits: minmaxImpliedEdits, + + }; + + attrs[max] = { + valType: 'number', + + dflt: null, + editType: editTypeOverride || 'plot', + impliedEdits: minmaxImpliedEdits, + + }; + + attrs.colorscale = { + valType: 'colorscale', + + editType: 'calc', + dflt: colorscaleDflt, + impliedEdits: {autocolorscale: false}, + + }; + + attrs.autocolorscale = { + valType: 'boolean', + + // gets overrode in 'heatmap' & 'surface' for backwards comp. + dflt: opts.autoColorDflt === false ? false : true, + editType: 'calc', + impliedEdits: {colorscale: undefined}, + + }; + + attrs.reversescale = { + valType: 'boolean', + + dflt: false, + editType: 'calc', + + }; + + if(!noScale) { + attrs.showscale = { + valType: 'boolean', + + dflt: showScaleDflt, + editType: 'calc', + + }; + } + + return attrs; +}; + +},{"./scales.js":589}],578:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var scales = _dereq_('./scales'); +var flipScale = _dereq_('./flip_scale'); + + +module.exports = function calc(trace, vals, containerStr, cLetter) { + var container = trace; + var inputContainer = trace._input; + var fullInputContainer = trace._fullInput; + + // set by traces with groupby transforms + var updateStyle = trace.updateStyle; + + function doUpdate(attr, inputVal, fullVal) { + if(fullVal === undefined) fullVal = inputVal; + + if(updateStyle) { + updateStyle(trace._input, containerStr ? (containerStr + '.' + attr) : attr, inputVal); + } + else { + inputContainer[attr] = inputVal; + } + + container[attr] = fullVal; + if(fullInputContainer && (trace !== trace._fullInput)) { + if(updateStyle) { + updateStyle(trace._fullInput, containerStr ? (containerStr + '.' + attr) : attr, fullVal); + } + else { + fullInputContainer[attr] = fullVal; + } + } + } + + if(containerStr) { + container = Lib.nestedProperty(container, containerStr).get(); + inputContainer = Lib.nestedProperty(inputContainer, containerStr).get(); + fullInputContainer = Lib.nestedProperty(fullInputContainer, containerStr).get() || {}; + } + + var autoAttr = cLetter + 'auto'; + var minAttr = cLetter + 'min'; + var maxAttr = cLetter + 'max'; + var auto = container[autoAttr]; + var min = container[minAttr]; + var max = container[maxAttr]; + var scl = container.colorscale; + + if(auto !== false || min === undefined) { + min = Lib.aggNums(Math.min, null, vals); + } + + if(auto !== false || max === undefined) { + max = Lib.aggNums(Math.max, null, vals); + } + + if(min === max) { + min -= 0.5; + max += 0.5; + } + + doUpdate(minAttr, min); + doUpdate(maxAttr, max); + + /* + * If auto was explicitly false but min or max was missing, + * we filled in the missing piece here but later the trace does + * not look auto. + * Otherwise make sure the trace still looks auto as far as later + * changes are concerned. + */ + doUpdate(autoAttr, (auto !== false || (min === undefined && max === undefined))); + + if(container.autocolorscale) { + if(min * max < 0) scl = scales.RdBu; + else if(min >= 0) scl = scales.Reds; + else scl = scales.Blues; + + // reversescale is handled at the containerOut level + doUpdate('colorscale', scl, container.reversescale ? flipScale(scl) : scl); + + // We pushed a colorscale back to input, which will change the default autocolorscale next time + // to avoid spurious redraws from Plotly.react, update resulting autocolorscale now + // This is a conscious decision so that changing the data later does not unexpectedly + // give you a new colorscale + if(!inputContainer.autocolorscale) { + doUpdate('autocolorscale', false); + } + } +}; + +},{"../../lib":696,"./flip_scale":582,"./scales":589}],579:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scales = _dereq_('./scales'); + + +module.exports = scales.RdBu; + +},{"./scales":589}],580:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); + +var hasColorbar = _dereq_('../colorbar/has_colorbar'); +var colorbarDefaults = _dereq_('../colorbar/defaults'); +var isValidScale = _dereq_('./is_valid_scale'); +var flipScale = _dereq_('./flip_scale'); + + +module.exports = function colorScaleDefaults(traceIn, traceOut, layout, coerce, opts) { + var prefix = opts.prefix, + cLetter = opts.cLetter, + containerStr = prefix.slice(0, prefix.length - 1), + containerIn = prefix ? + Lib.nestedProperty(traceIn, containerStr).get() || {} : + traceIn, + containerOut = prefix ? + Lib.nestedProperty(traceOut, containerStr).get() || {} : + traceOut, + minIn = containerIn[cLetter + 'min'], + maxIn = containerIn[cLetter + 'max'], + sclIn = containerIn.colorscale; + + var validMinMax = isNumeric(minIn) && isNumeric(maxIn) && (minIn < maxIn); + coerce(prefix + cLetter + 'auto', !validMinMax); + coerce(prefix + cLetter + 'min'); + coerce(prefix + cLetter + 'max'); + + // handles both the trace case (autocolorscale is false by default) and + // the marker and marker.line case (autocolorscale is true by default) + var autoColorscaleDflt; + if(sclIn !== undefined) autoColorscaleDflt = !isValidScale(sclIn); + coerce(prefix + 'autocolorscale', autoColorscaleDflt); + var sclOut = coerce(prefix + 'colorscale'); + + // reversescale is handled at the containerOut level + var reverseScale = coerce(prefix + 'reversescale'); + if(reverseScale) containerOut.colorscale = flipScale(sclOut); + + // ... until Scatter.colorbar can handle marker line colorbars + if(prefix === 'marker.line.') return; + + if(!opts.noScale) { + // handles both the trace case where the dflt is listed in attributes and + // the marker case where the dflt is determined by hasColorbar + var showScaleDflt; + if(prefix) showScaleDflt = hasColorbar(containerIn); + + var showScale = coerce(prefix + 'showscale', showScaleDflt); + if(showScale) colorbarDefaults(containerIn, containerOut, layout); + } +}; + +},{"../../lib":696,"../colorbar/defaults":574,"../colorbar/has_colorbar":576,"./flip_scale":582,"./is_valid_scale":586,"fast-isnumeric":214}],581:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** + * Extract colorscale into numeric domain and color range. + * + * @param {array} scl colorscale array of arrays + * @param {number} cmin minimum color value (used to clamp scale) + * @param {number} cmax maximum color value (used to clamp scale) + */ +module.exports = function extractScale(scl, cmin, cmax) { + var N = scl.length, + domain = new Array(N), + range = new Array(N); + + for(var i = 0; i < N; i++) { + var si = scl[i]; + + domain[i] = cmin + si[0] * (cmax - cmin); + range[i] = si[1]; + } + + return { + domain: domain, + range: range + }; +}; + +},{}],582:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function flipScale(scl) { + var N = scl.length, + sclNew = new Array(N), + si; + + for(var i = N - 1, j = 0; i >= 0; i--, j++) { + si = scl[i]; + sclNew[j] = [1 - si[0], si[1]]; + } + + return sclNew; +}; + +},{}],583:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scales = _dereq_('./scales'); +var defaultScale = _dereq_('./default_scale'); +var isValidScaleArray = _dereq_('./is_valid_scale_array'); + + +module.exports = function getScale(scl, dflt) { + if(!dflt) dflt = defaultScale; + if(!scl) return dflt; + + function parseScale() { + try { + scl = scales[scl] || JSON.parse(scl); + } + catch(e) { + scl = dflt; + } + } + + if(typeof scl === 'string') { + parseScale(); + // occasionally scl is double-JSON encoded... + if(typeof scl === 'string') parseScale(); + } + + if(!isValidScaleArray(scl)) return dflt; + return scl; +}; + +},{"./default_scale":579,"./is_valid_scale_array":587,"./scales":589}],584:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var Lib = _dereq_('../../lib'); +var isValidScale = _dereq_('./is_valid_scale'); + +module.exports = function hasColorscale(trace, containerStr) { + var container = containerStr ? + Lib.nestedProperty(trace, containerStr).get() || {} : + trace; + var color = container.color; + + var isArrayWithOneNumber = false; + if(Lib.isArrayOrTypedArray(color)) { + for(var i = 0; i < color.length; i++) { + if(isNumeric(color[i])) { + isArrayWithOneNumber = true; + break; + } + } + } + + return ( + Lib.isPlainObject(container) && ( + isArrayWithOneNumber || + container.showscale === true || + (isNumeric(container.cmin) && isNumeric(container.cmax)) || + isValidScale(container.colorscale) || + Lib.isPlainObject(container.colorbar) + ) + ); +}; + +},{"../../lib":696,"./is_valid_scale":586,"fast-isnumeric":214}],585:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.scales = _dereq_('./scales'); + +exports.defaultScale = _dereq_('./default_scale'); + +exports.attributes = _dereq_('./attributes'); + +exports.handleDefaults = _dereq_('./defaults'); + +exports.calc = _dereq_('./calc'); + +exports.hasColorscale = _dereq_('./has_colorscale'); + +exports.isValidScale = _dereq_('./is_valid_scale'); + +exports.getScale = _dereq_('./get_scale'); + +exports.flipScale = _dereq_('./flip_scale'); + +exports.extractScale = _dereq_('./extract_scale'); + +exports.makeColorScaleFunc = _dereq_('./make_color_scale_func'); + +},{"./attributes":577,"./calc":578,"./default_scale":579,"./defaults":580,"./extract_scale":581,"./flip_scale":582,"./get_scale":583,"./has_colorscale":584,"./is_valid_scale":586,"./make_color_scale_func":588,"./scales":589}],586:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scales = _dereq_('./scales'); +var isValidScaleArray = _dereq_('./is_valid_scale_array'); + + +module.exports = function isValidScale(scl) { + if(scales[scl] !== undefined) return true; + else return isValidScaleArray(scl); +}; + +},{"./is_valid_scale_array":587,"./scales":589}],587:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var tinycolor = _dereq_('tinycolor2'); + + +module.exports = function isValidScaleArray(scl) { + var highestVal = 0; + + if(!Array.isArray(scl) || scl.length < 2) return false; + + if(!scl[0] || !scl[scl.length - 1]) return false; + + if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; + + for(var i = 0; i < scl.length; i++) { + var si = scl[i]; + + if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) { + return false; + } + + highestVal = +si[0]; + } + + return true; +}; + +},{"tinycolor2":514}],588:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); +var isNumeric = _dereq_('fast-isnumeric'); + +var Color = _dereq_('../color'); + +/** + * General colorscale function generator. + * + * @param {object} specs output of Colorscale.extractScale or precomputed domain, range. + * - domain {array} + * - range {array} + * + * @param {object} opts + * - noNumericCheck {boolean} if true, scale func bypasses numeric checks + * - returnArray {boolean} if true, scale func return 4-item array instead of color strings + * + * @return {function} + */ +module.exports = function makeColorScaleFunc(specs, opts) { + opts = opts || {}; + + var domain = specs.domain, + range = specs.range, + N = range.length, + _range = new Array(N); + + for(var i = 0; i < N; i++) { + var rgba = tinycolor(range[i]).toRgb(); + _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a]; + } + + var _sclFunc = d3.scale.linear() + .domain(domain) + .range(_range) + .clamp(true); + + var noNumericCheck = opts.noNumericCheck, + returnArray = opts.returnArray, + sclFunc; + + if(noNumericCheck && returnArray) { + sclFunc = _sclFunc; + } + else if(noNumericCheck) { + sclFunc = function(v) { + return colorArray2rbga(_sclFunc(v)); + }; + } + else if(returnArray) { + sclFunc = function(v) { + if(isNumeric(v)) return _sclFunc(v); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + else { + sclFunc = function(v) { + if(isNumeric(v)) return colorArray2rbga(_sclFunc(v)); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + + // colorbar draw looks into the d3 scale closure for domain and range + + sclFunc.domain = _sclFunc.domain; + + sclFunc.range = function() { return range; }; + + return sclFunc; +}; + +function colorArray2rbga(colorArray) { + var colorObj = { + r: colorArray[0], + g: colorArray[1], + b: colorArray[2], + a: colorArray[3] + }; + + return tinycolor(colorObj).toRgbString(); +} + +},{"../color":570,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,"tinycolor2":514}],589:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + 'Greys': [ + [0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)'] + ], + + 'YlGnBu': [ + [0, 'rgb(8,29,88)'], [0.125, 'rgb(37,52,148)'], + [0.25, 'rgb(34,94,168)'], [0.375, 'rgb(29,145,192)'], + [0.5, 'rgb(65,182,196)'], [0.625, 'rgb(127,205,187)'], + [0.75, 'rgb(199,233,180)'], [0.875, 'rgb(237,248,217)'], + [1, 'rgb(255,255,217)'] + ], + + 'Greens': [ + [0, 'rgb(0,68,27)'], [0.125, 'rgb(0,109,44)'], + [0.25, 'rgb(35,139,69)'], [0.375, 'rgb(65,171,93)'], + [0.5, 'rgb(116,196,118)'], [0.625, 'rgb(161,217,155)'], + [0.75, 'rgb(199,233,192)'], [0.875, 'rgb(229,245,224)'], + [1, 'rgb(247,252,245)'] + ], + + 'YlOrRd': [ + [0, 'rgb(128,0,38)'], [0.125, 'rgb(189,0,38)'], + [0.25, 'rgb(227,26,28)'], [0.375, 'rgb(252,78,42)'], + [0.5, 'rgb(253,141,60)'], [0.625, 'rgb(254,178,76)'], + [0.75, 'rgb(254,217,118)'], [0.875, 'rgb(255,237,160)'], + [1, 'rgb(255,255,204)'] + ], + + 'Bluered': [ + [0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)'] + ], + + // modified RdBu based on + // www.sandia.gov/~kmorel/documents/ColorMaps/ColorMapsExpanded.pdf + 'RdBu': [ + [0, 'rgb(5,10,172)'], [0.35, 'rgb(106,137,247)'], + [0.5, 'rgb(190,190,190)'], [0.6, 'rgb(220,170,132)'], + [0.7, 'rgb(230,145,90)'], [1, 'rgb(178,10,28)'] + ], + + // Scale for non-negative numeric values + 'Reds': [ + [0, 'rgb(220,220,220)'], [0.2, 'rgb(245,195,157)'], + [0.4, 'rgb(245,160,105)'], [1, 'rgb(178,10,28)'] + ], + + // Scale for non-positive numeric values + 'Blues': [ + [0, 'rgb(5,10,172)'], [0.35, 'rgb(40,60,190)'], + [0.5, 'rgb(70,100,245)'], [0.6, 'rgb(90,120,245)'], + [0.7, 'rgb(106,137,247)'], [1, 'rgb(220,220,220)'] + ], + + 'Picnic': [ + [0, 'rgb(0,0,255)'], [0.1, 'rgb(51,153,255)'], + [0.2, 'rgb(102,204,255)'], [0.3, 'rgb(153,204,255)'], + [0.4, 'rgb(204,204,255)'], [0.5, 'rgb(255,255,255)'], + [0.6, 'rgb(255,204,255)'], [0.7, 'rgb(255,153,255)'], + [0.8, 'rgb(255,102,204)'], [0.9, 'rgb(255,102,102)'], + [1, 'rgb(255,0,0)'] + ], + + 'Rainbow': [ + [0, 'rgb(150,0,90)'], [0.125, 'rgb(0,0,200)'], + [0.25, 'rgb(0,25,255)'], [0.375, 'rgb(0,152,255)'], + [0.5, 'rgb(44,255,150)'], [0.625, 'rgb(151,255,0)'], + [0.75, 'rgb(255,234,0)'], [0.875, 'rgb(255,111,0)'], + [1, 'rgb(255,0,0)'] + ], + + 'Portland': [ + [0, 'rgb(12,51,131)'], [0.25, 'rgb(10,136,186)'], + [0.5, 'rgb(242,211,56)'], [0.75, 'rgb(242,143,56)'], + [1, 'rgb(217,30,30)'] + ], + + 'Jet': [ + [0, 'rgb(0,0,131)'], [0.125, 'rgb(0,60,170)'], + [0.375, 'rgb(5,255,255)'], [0.625, 'rgb(255,255,0)'], + [0.875, 'rgb(250,0,0)'], [1, 'rgb(128,0,0)'] + ], + + 'Hot': [ + [0, 'rgb(0,0,0)'], [0.3, 'rgb(230,0,0)'], + [0.6, 'rgb(255,210,0)'], [1, 'rgb(255,255,255)'] + ], + + 'Blackbody': [ + [0, 'rgb(0,0,0)'], [0.2, 'rgb(230,0,0)'], + [0.4, 'rgb(230,210,0)'], [0.7, 'rgb(255,255,255)'], + [1, 'rgb(160,200,255)'] + ], + + 'Earth': [ + [0, 'rgb(0,0,130)'], [0.1, 'rgb(0,180,180)'], + [0.2, 'rgb(40,210,40)'], [0.4, 'rgb(230,230,50)'], + [0.6, 'rgb(120,70,20)'], [1, 'rgb(255,255,255)'] + ], + + 'Electric': [ + [0, 'rgb(0,0,0)'], [0.15, 'rgb(30,0,100)'], + [0.4, 'rgb(120,0,100)'], [0.6, 'rgb(160,90,0)'], + [0.8, 'rgb(230,200,0)'], [1, 'rgb(255,250,220)'] + ], + + 'Viridis': [ + [0, '#440154'], [0.06274509803921569, '#48186a'], + [0.12549019607843137, '#472d7b'], [0.18823529411764706, '#424086'], + [0.25098039215686274, '#3b528b'], [0.3137254901960784, '#33638d'], + [0.3764705882352941, '#2c728e'], [0.4392156862745098, '#26828e'], + [0.5019607843137255, '#21918c'], [0.5647058823529412, '#1fa088'], + [0.6274509803921569, '#28ae80'], [0.6901960784313725, '#3fbc73'], + [0.7529411764705882, '#5ec962'], [0.8156862745098039, '#84d44b'], + [0.8784313725490196, '#addc30'], [0.9411764705882353, '#d8e219'], + [1, '#fde725'] + ], + + 'Cividis': [ + [0.000000, 'rgb(0,32,76)'], [0.058824, 'rgb(0,42,102)'], + [0.117647, 'rgb(0,52,110)'], [0.176471, 'rgb(39,63,108)'], + [0.235294, 'rgb(60,74,107)'], [0.294118, 'rgb(76,85,107)'], + [0.352941, 'rgb(91,95,109)'], [0.411765, 'rgb(104,106,112)'], + [0.470588, 'rgb(117,117,117)'], [0.529412, 'rgb(131,129,120)'], + [0.588235, 'rgb(146,140,120)'], [0.647059, 'rgb(161,152,118)'], + [0.705882, 'rgb(176,165,114)'], [0.764706, 'rgb(192,177,109)'], + [0.823529, 'rgb(209,191,102)'], [0.882353, 'rgb(225,204,92)'], + [0.941176, 'rgb(243,219,79)'], [1.000000, 'rgb(255,233,69)'] + ] +}; + +},{}],590:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// for automatic alignment on dragging, <1/3 means left align, +// >2/3 means right, and between is center. Pick the right fraction +// based on where you are, and return the fraction corresponding to +// that position on the object +module.exports = function align(v, dv, v0, v1, anchor) { + var vmin = (v - v0) / (v1 - v0), + vmax = vmin + dv / (v1 - v0), + vc = (vmin + vmax) / 2; + + // explicitly specified anchor + if(anchor === 'left' || anchor === 'bottom') return vmin; + if(anchor === 'center' || anchor === 'middle') return vc; + if(anchor === 'right' || anchor === 'top') return vmax; + + // automatic based on position + if(vmin < (2 / 3) - vc) return vmin; + if(vmax > (4 / 3) - vc) return vmax; + return vc; +}; + +},{}],591:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + + +// set cursors pointing toward the closest corner/side, +// to indicate alignment +// x and y are 0-1, fractions of the plot area +var cursorset = [ + ['sw-resize', 's-resize', 'se-resize'], + ['w-resize', 'move', 'e-resize'], + ['nw-resize', 'n-resize', 'ne-resize'] +]; + +module.exports = function getCursor(x, y, xanchor, yanchor) { + if(xanchor === 'left') x = 0; + else if(xanchor === 'center') x = 1; + else if(xanchor === 'right') x = 2; + else x = Lib.constrain(Math.floor(x * 3), 0, 2); + + if(yanchor === 'bottom') y = 0; + else if(yanchor === 'middle') y = 1; + else if(yanchor === 'top') y = 2; + else y = Lib.constrain(Math.floor(y * 3), 0, 2); + + return cursorset[y][x]; +}; + +},{"../../lib":696}],592:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var mouseOffset = _dereq_('mouse-event-offset'); +var hasHover = _dereq_('has-hover'); +var supportsPassive = _dereq_('has-passive-events'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +var constants = _dereq_('../../plots/cartesian/constants'); +var interactConstants = _dereq_('../../constants/interactions'); + +var dragElement = module.exports = {}; + +dragElement.align = _dereq_('./align'); +dragElement.getCursor = _dereq_('./cursor'); + +var unhover = _dereq_('./unhover'); +dragElement.unhover = unhover.wrapped; +dragElement.unhoverRaw = unhover.raw; + + +/** + * Abstracts click & drag interactions + * + * During the interaction, a "coverSlip" element - a transparent + * div covering the whole page - is created, which has two key effects: + * - Lets you drag beyond the boundaries of the plot itself without + * dropping (but if you drag all the way out of the browser window the + * interaction will end) + * - Freezes the cursor: whatever mouse cursor the drag element had when the + * interaction started gets copied to the coverSlip for use until mouseup + * + * If the user executes a drag bigger than MINDRAG, callbacks will fire as: + * prepFn, moveFn (1 or more times), doneFn + * If the user does not drag enough, prepFn and clickFn will fire. + * + * Note: If you cancel contextmenu, clickFn will fire even with a right click + * (unlike native events) so you'll get a `plotly_click` event. Cancel context eg: + * gd.addEventListener('contextmenu', function(e) { e.preventDefault(); }); + * TODO: we should probably turn this into a `config` parameter, so we can fix it + * such that if you *don't* cancel contextmenu, we can prevent partial drags, which + * put you in a weird state. + * + * If the user clicks multiple times quickly, clickFn will fire each time + * but numClicks will increase to help you recognize doubleclicks. + * + * @param {object} options with keys: + * element (required) the DOM element to drag + * prepFn (optional) function(event, startX, startY) + * executed on mousedown + * startX and startY are the clientX and clientY pixel position + * of the mousedown event + * moveFn (optional) function(dx, dy) + * executed on move, ONLY after we've exceeded MINDRAG + * (we keep executing moveFn if you move back to where you started) + * dx and dy are the net pixel offset of the drag, + * dragged is true/false, has the mouse moved enough to + * constitute a drag + * doneFn (optional) function(e) + * executed on mouseup, ONLY if we exceeded MINDRAG (so you can be + * sure that moveFn has been called at least once) + * numClicks is how many clicks we've registered within + * a doubleclick time + * e is the original mouseup event + * clickFn (optional) function(numClicks, e) + * executed on mouseup if we have NOT exceeded MINDRAG (ie moveFn + * has not been called at all) + * numClicks is how many clicks we've registered within + * a doubleclick time + * e is the original mousedown event + * clampFn (optional, function(dx, dy) return [dx2, dy2]) + * Provide custom clamping function for small displacements. + * By default, clamping is done using `minDrag` to x and y displacements + * independently. + */ +dragElement.init = function init(options) { + var gd = options.gd; + var numClicks = 1; + var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY; + var element = options.element; + + var startX, + startY, + newMouseDownTime, + cursor, + dragCover, + initialEvent, + initialTarget, + rightClick; + + if(!gd._mouseDownTime) gd._mouseDownTime = 0; + + element.style.pointerEvents = 'all'; + + element.onmousedown = onStart; + + if(!supportsPassive) { + element.ontouchstart = onStart; + } + else { + if(element._ontouchstart) { + element.removeEventListener('touchstart', element._ontouchstart); + } + element._ontouchstart = onStart; + element.addEventListener('touchstart', onStart, {passive: false}); + } + + function _clampFn(dx, dy, minDrag) { + if(Math.abs(dx) < minDrag) dx = 0; + if(Math.abs(dy) < minDrag) dy = 0; + return [dx, dy]; + } + + var clampFn = options.clampFn || _clampFn; + + function onStart(e) { + e.preventDefault(); + + // make dragging and dragged into properties of gd + // so that others can look at and modify them + gd._dragged = false; + gd._dragging = true; + var offset = pointerOffset(e); + startX = offset[0]; + startY = offset[1]; + initialTarget = e.target; + initialEvent = e; + rightClick = e.buttons === 2 || e.ctrlKey; + + // fix Fx.hover for touch events + if(typeof e.clientX === 'undefined' && typeof e.clientY === 'undefined') { + e.clientX = startX; + e.clientY = startY; + } + + newMouseDownTime = (new Date()).getTime(); + if(newMouseDownTime - gd._mouseDownTime < DBLCLICKDELAY) { + // in a click train + numClicks += 1; + } + else { + // new click train + numClicks = 1; + gd._mouseDownTime = newMouseDownTime; + } + + if(options.prepFn) options.prepFn(e, startX, startY); + + if(hasHover && !rightClick) { + dragCover = coverSlip(); + dragCover.style.cursor = window.getComputedStyle(element).cursor; + } + else if(!hasHover) { + // document acts as a dragcover for mobile, bc we can't create dragcover dynamically + dragCover = document; + cursor = window.getComputedStyle(document.documentElement).cursor; + document.documentElement.style.cursor = window.getComputedStyle(element).cursor; + } + + document.addEventListener('mousemove', onMove); + document.addEventListener('mouseup', onDone); + document.addEventListener('touchmove', onMove); + document.addEventListener('touchend', onDone); + + return; + } + + function onMove(e) { + e.preventDefault(); + + var offset = pointerOffset(e); + var minDrag = options.minDrag || constants.MINDRAG; + var dxdy = clampFn(offset[0] - startX, offset[1] - startY, minDrag); + var dx = dxdy[0]; + var dy = dxdy[1]; + + if(dx || dy) { + gd._dragged = true; + dragElement.unhover(gd); + } + + if(gd._dragged && options.moveFn && !rightClick) options.moveFn(dx, dy); + + return; + } + + function onDone(e) { + document.removeEventListener('mousemove', onMove); + document.removeEventListener('mouseup', onDone); + document.removeEventListener('touchmove', onMove); + document.removeEventListener('touchend', onDone); + + e.preventDefault(); + + if(hasHover) { + Lib.removeElement(dragCover); + } + else if(cursor) { + dragCover.documentElement.style.cursor = cursor; + cursor = null; + } + + if(!gd._dragging) { + gd._dragged = false; + return; + } + gd._dragging = false; + + // don't count as a dblClick unless the mouseUp is also within + // the dblclick delay + if((new Date()).getTime() - gd._mouseDownTime > DBLCLICKDELAY) { + numClicks = Math.max(numClicks - 1, 1); + } + + if(gd._dragged) { + if(options.doneFn) options.doneFn(); + } + else { + if(options.clickFn) options.clickFn(numClicks, initialEvent); + + // If we haven't dragged, this should be a click. But because of the + // coverSlip changing the element, the natural system might not generate one, + // so we need to make our own. But right clicks don't normally generate + // click events, only contextmenu events, which happen on mousedown. + if(!rightClick) { + var e2; + + try { + e2 = new MouseEvent('click', e); + } + catch(err) { + var offset = pointerOffset(e); + e2 = document.createEvent('MouseEvents'); + e2.initMouseEvent('click', + e.bubbles, e.cancelable, + e.view, e.detail, + e.screenX, e.screenY, + offset[0], offset[1], + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + e.button, e.relatedTarget); + } + + initialTarget.dispatchEvent(e2); + } + } + + finishDrag(gd); + + gd._dragged = false; + + return; + } +}; + +function coverSlip() { + var cover = document.createElement('div'); + + cover.className = 'dragcover'; + var cStyle = cover.style; + cStyle.position = 'fixed'; + cStyle.left = 0; + cStyle.right = 0; + cStyle.top = 0; + cStyle.bottom = 0; + cStyle.zIndex = 999999999; + cStyle.background = 'none'; + + document.body.appendChild(cover); + + return cover; +} + +dragElement.coverSlip = coverSlip; + +function finishDrag(gd) { + gd._dragging = false; + if(gd._replotPending) Registry.call('plot', gd); +} + +function pointerOffset(e) { + return mouseOffset( + e.changedTouches ? e.changedTouches[0] : e, + document.body + ); +} + +},{"../../constants/interactions":672,"../../lib":696,"../../plots/cartesian/constants":750,"../../registry":827,"./align":590,"./cursor":591,"./unhover":593,"has-hover":393,"has-passive-events":394,"mouse-event-offset":419}],593:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var Events = _dereq_('../../lib/events'); +var throttle = _dereq_('../../lib/throttle'); +var getGraphDiv = _dereq_('../../lib/get_graph_div'); + +var hoverConstants = _dereq_('../fx/constants'); + +var unhover = module.exports = {}; + + +unhover.wrapped = function(gd, evt, subplot) { + gd = getGraphDiv(gd); + + // Important, clear any queued hovers + if(gd._fullLayout) { + throttle.clear(gd._fullLayout._uid + hoverConstants.HOVERID); + } + + unhover.raw(gd, evt, subplot); +}; + + +// remove hover effects on mouse out, and emit unhover event +unhover.raw = function unhoverRaw(gd, evt) { + var fullLayout = gd._fullLayout; + var oldhoverdata = gd._hoverdata; + + if(!evt) evt = {}; + if(evt.target && + Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { + return; + } + + fullLayout._hoverlayer.selectAll('g').remove(); + fullLayout._hoverlayer.selectAll('line').remove(); + fullLayout._hoverlayer.selectAll('circle').remove(); + gd._hoverdata = undefined; + + if(evt.target && oldhoverdata) { + gd.emit('plotly_unhover', { + event: evt, + points: oldhoverdata + }); + } +}; + +},{"../../lib/events":684,"../../lib/get_graph_div":691,"../../lib/throttle":721,"../fx/constants":607}],594:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.dash = { + valType: 'string', + // string type usually doesn't take values... this one should really be + // a special type or at least a special coercion function, from the GUI + // you only get these values but elsewhere the user can supply a list of + // dash lengths in px, and it will be honored + values: ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot'], + dflt: 'solid', + + editType: 'style', + +}; + +},{}],595:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); +var tinycolor = _dereq_('tinycolor2'); + +var Registry = _dereq_('../../registry'); +var Color = _dereq_('../color'); +var Colorscale = _dereq_('../colorscale'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); + +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); +var alignment = _dereq_('../../constants/alignment'); +var LINE_SPACING = alignment.LINE_SPACING; +var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; + +var subTypes = _dereq_('../../traces/scatter/subtypes'); +var makeBubbleSizeFn = _dereq_('../../traces/scatter/make_bubble_size_func'); + +var drawing = module.exports = {}; + +// ----------------------------------------------------- +// styling functions for plot elements +// ----------------------------------------------------- + +drawing.font = function(s, family, size, color) { + // also allow the form font(s, {family, size, color}) + if(Lib.isPlainObject(family)) { + color = family.color; + size = family.size; + family = family.family; + } + if(family) s.style('font-family', family); + if(size + 1) s.style('font-size', size + 'px'); + if(color) s.call(Color.fill, color); +}; + +/* + * Positioning helpers + * Note: do not use `setPosition` with nodes modified by + * `svgTextUtils.convertToTspans`. Use `svgTextUtils.positionText` + * instead, so that elements get updated to match. + */ +drawing.setPosition = function(s, x, y) { s.attr('x', x).attr('y', y); }; +drawing.setSize = function(s, w, h) { s.attr('width', w).attr('height', h); }; +drawing.setRect = function(s, x, y, w, h) { + s.call(drawing.setPosition, x, y).call(drawing.setSize, w, h); +}; + +/** Translate node + * + * @param {object} d : calcdata point item + * @param {sel} sel : d3 selction of node to translate + * @param {object} xa : corresponding full xaxis object + * @param {object} ya : corresponding full yaxis object + * + * @return {boolean} : + * true if selection got translated + * false if selection could not get translated + */ +drawing.translatePoint = function(d, sel, xa, ya) { + var x = xa.c2p(d.x); + var y = ya.c2p(d.y); + + if(isNumeric(x) && isNumeric(y) && sel.node()) { + // for multiline text this works better + if(sel.node().nodeName === 'text') { + sel.attr('x', x).attr('y', y); + } else { + sel.attr('transform', 'translate(' + x + ',' + y + ')'); + } + } else { + return false; + } + + return true; +}; + +drawing.translatePoints = function(s, xa, ya) { + s.each(function(d) { + var sel = d3.select(this); + drawing.translatePoint(d, sel, xa, ya); + }); +}; + +drawing.hideOutsideRangePoint = function(d, sel, xa, ya, xcalendar, ycalendar) { + sel.attr( + 'display', + (xa.isPtWithinRange(d, xcalendar) && ya.isPtWithinRange(d, ycalendar)) ? null : 'none' + ); +}; + +drawing.hideOutsideRangePoints = function(traceGroups, subplot) { + if(!subplot._hasClipOnAxisFalse) return; + + var xa = subplot.xaxis; + var ya = subplot.yaxis; + + traceGroups.each(function(d) { + var trace = d[0].trace; + var xcalendar = trace.xcalendar; + var ycalendar = trace.ycalendar; + var selector = trace.type === 'bar' ? '.bartext' : '.point,.textpoint'; + + traceGroups.selectAll(selector).each(function(d) { + drawing.hideOutsideRangePoint(d, d3.select(this), xa, ya, xcalendar, ycalendar); + }); + }); +}; + +drawing.crispRound = function(gd, lineWidth, dflt) { + // for lines that disable antialiasing we want to + // make sure the width is an integer, and at least 1 if it's nonzero + + if(!lineWidth || !isNumeric(lineWidth)) return dflt || 0; + + // but not for static plots - these don't get antialiased anyway. + if(gd._context.staticPlot) return lineWidth; + + if(lineWidth < 1) return 1; + return Math.round(lineWidth); +}; + +drawing.singleLineStyle = function(d, s, lw, lc, ld) { + s.style('fill', 'none'); + var line = (((d || [])[0] || {}).trace || {}).line || {}, + lw1 = lw || line.width||0, + dash = ld || line.dash || ''; + + Color.stroke(s, lc || line.color); + drawing.dashLine(s, dash, lw1); +}; + +drawing.lineGroupStyle = function(s, lw, lc, ld) { + s.style('fill', 'none') + .each(function(d) { + var line = (((d || [])[0] || {}).trace || {}).line || {}, + lw1 = lw || line.width||0, + dash = ld || line.dash || ''; + + d3.select(this) + .call(Color.stroke, lc || line.color) + .call(drawing.dashLine, dash, lw1); + }); +}; + +drawing.dashLine = function(s, dash, lineWidth) { + lineWidth = +lineWidth || 0; + + dash = drawing.dashStyle(dash, lineWidth); + + s.style({ + 'stroke-dasharray': dash, + 'stroke-width': lineWidth + 'px' + }); +}; + +drawing.dashStyle = function(dash, lineWidth) { + lineWidth = +lineWidth || 1; + var dlw = Math.max(lineWidth, 3); + + if(dash === 'solid') dash = ''; + else if(dash === 'dot') dash = dlw + 'px,' + dlw + 'px'; + else if(dash === 'dash') dash = (3 * dlw) + 'px,' + (3 * dlw) + 'px'; + else if(dash === 'longdash') dash = (5 * dlw) + 'px,' + (5 * dlw) + 'px'; + else if(dash === 'dashdot') { + dash = (3 * dlw) + 'px,' + dlw + 'px,' + dlw + 'px,' + dlw + 'px'; + } + else if(dash === 'longdashdot') { + dash = (5 * dlw) + 'px,' + (2 * dlw) + 'px,' + dlw + 'px,' + (2 * dlw) + 'px'; + } + // otherwise user wrote the dasharray themselves - leave it be + + return dash; +}; + +// Same as fillGroupStyle, except in this case the selection may be a transition +drawing.singleFillStyle = function(sel) { + var node = d3.select(sel.node()); + var data = node.data(); + var fillcolor = (((data[0] || [])[0] || {}).trace || {}).fillcolor; + if(fillcolor) { + sel.call(Color.fill, fillcolor); + } +}; + +drawing.fillGroupStyle = function(s) { + s.style('stroke-width', 0) + .each(function(d) { + var shape = d3.select(this); + shape.call(Color.fill, d[0].trace.fillcolor); + }); +}; + +var SYMBOLDEFS = _dereq_('./symbol_defs'); + +drawing.symbolNames = []; +drawing.symbolFuncs = []; +drawing.symbolNeedLines = {}; +drawing.symbolNoDot = {}; +drawing.symbolNoFill = {}; +drawing.symbolList = []; + +Object.keys(SYMBOLDEFS).forEach(function(k) { + var symDef = SYMBOLDEFS[k]; + drawing.symbolList = drawing.symbolList.concat( + [symDef.n, k, symDef.n + 100, k + '-open']); + drawing.symbolNames[symDef.n] = k; + drawing.symbolFuncs[symDef.n] = symDef.f; + if(symDef.needLine) { + drawing.symbolNeedLines[symDef.n] = true; + } + if(symDef.noDot) { + drawing.symbolNoDot[symDef.n] = true; + } + else { + drawing.symbolList = drawing.symbolList.concat( + [symDef.n + 200, k + '-dot', symDef.n + 300, k + '-open-dot']); + } + if(symDef.noFill) { + drawing.symbolNoFill[symDef.n] = true; + } +}); +var MAXSYMBOL = drawing.symbolNames.length, + // add a dot in the middle of the symbol + DOTPATH = 'M0,0.5L0.5,0L0,-0.5L-0.5,0Z'; + +drawing.symbolNumber = function(v) { + if(typeof v === 'string') { + var vbase = 0; + if(v.indexOf('-open') > 0) { + vbase = 100; + v = v.replace('-open', ''); + } + if(v.indexOf('-dot') > 0) { + vbase += 200; + v = v.replace('-dot', ''); + } + v = drawing.symbolNames.indexOf(v); + if(v >= 0) { v += vbase; } + } + if((v % 100 >= MAXSYMBOL) || v >= 400) { return 0; } + return Math.floor(Math.max(v, 0)); +}; + +function makePointPath(symbolNumber, r) { + var base = symbolNumber % 100; + return drawing.symbolFuncs[base](r) + (symbolNumber >= 200 ? DOTPATH : ''); +} + +var HORZGRADIENT = {x1: 1, x2: 0, y1: 0, y2: 0}; +var VERTGRADIENT = {x1: 0, x2: 0, y1: 1, y2: 0}; +var stopFormatter = d3.format('~.1f'); +var gradientInfo = { + radial: {node: 'radialGradient'}, + radialreversed: {node: 'radialGradient', reversed: true}, + horizontal: {node: 'linearGradient', attrs: HORZGRADIENT}, + horizontalreversed: {node: 'linearGradient', attrs: HORZGRADIENT, reversed: true}, + vertical: {node: 'linearGradient', attrs: VERTGRADIENT}, + verticalreversed: {node: 'linearGradient', attrs: VERTGRADIENT, reversed: true} +}; + +/** + * gradient: create and apply a gradient fill + * + * @param {object} sel: d3 selection to apply this gradient to + * You can use `selection.call(Drawing.gradient, ...)` + * @param {DOM element} gd: the graph div `sel` is part of + * @param {string} gradientID: a unique (within this plot) identifier + * for this gradient, so that we don't create unnecessary definitions + * @param {string} type: 'radial', 'horizontal', or 'vertical', optionally with + * 'reversed' at the end. Normally radial goes center to edge, + * horizontal goes right to left, and vertical goes bottom to top + * @param {array} colorscale: as in attribute values, [[fraction, color], ...] + * @param {string} prop: the property to apply to, 'fill' or 'stroke' + */ +drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { + var len = colorscale.length; + var info = gradientInfo[type]; + var colorStops = new Array(len); + for(var i = 0; i < len; i++) { + if(info.reversed) { + colorStops[len - 1 - i] = [stopFormatter((1 - colorscale[i][0]) * 100), colorscale[i][1]]; + } + else { + colorStops[i] = [stopFormatter(colorscale[i][0] * 100), colorscale[i][1]]; + } + } + + var fullID = 'g' + gd._fullLayout._uid + '-' + gradientID; + + var gradient = gd._fullLayout._defs.select('.gradients') + .selectAll('#' + fullID) + .data([type + colorStops.join(';')], Lib.identity); + + gradient.exit().remove(); + + gradient.enter() + .append(info.node) + .each(function() { + var el = d3.select(this); + if(info.attrs) el.attr(info.attrs); + + el.attr('id', fullID); + + var stops = el.selectAll('stop') + .data(colorStops); + stops.exit().remove(); + stops.enter().append('stop'); + + stops.each(function(d) { + var tc = tinycolor(d[1]); + d3.select(this).attr({ + offset: d[0] + '%', + 'stop-color': Color.tinyRGB(tc), + 'stop-opacity': tc.getAlpha() + }); + }); + }); + + sel.style(prop, 'url(#' + fullID + ')') + .style(prop + '-opacity', null); +}; + +/* + * Make the gradients container and clear out any previous gradients. + * We never collect all the gradients we need in one place, + * so we can't ever remove gradients that have stopped being useful, + * except all at once before a full redraw. + * The upside of this is arbitrary points can share gradient defs + */ +drawing.initGradients = function(gd) { + var gradientsGroup = Lib.ensureSingle(gd._fullLayout._defs, 'g', 'gradients'); + gradientsGroup.selectAll('linearGradient,radialGradient').remove(); +}; + + +drawing.pointStyle = function(s, trace, gd) { + if(!s.size()) return; + + var fns = drawing.makePointStyleFns(trace); + + s.each(function(d) { + drawing.singlePointStyle(d, d3.select(this), trace, fns, gd); + }); +}; + +drawing.singlePointStyle = function(d, sel, trace, fns, gd) { + var marker = trace.marker; + var markerLine = marker.line; + + sel.style('opacity', + fns.selectedOpacityFn ? fns.selectedOpacityFn(d) : + (d.mo === undefined ? marker.opacity : d.mo) + ); + + if(fns.ms2mrc) { + var r; + + // handle multi-trace graph edit case + if(d.ms === 'various' || marker.size === 'various') { + r = 3; + } else { + r = fns.ms2mrc(d.ms); + } + + // store the calculated size so hover can use it + d.mrc = r; + + if(fns.selectedSizeFn) { + r = d.mrc = fns.selectedSizeFn(d); + } + + // turn the symbol into a sanitized number + var x = drawing.symbolNumber(d.mx || marker.symbol) || 0; + + // save if this marker is open + // because that impacts how to handle colors + d.om = x % 200 >= 100; + + sel.attr('d', makePointPath(x, r)); + } + + var perPointGradient = false; + var fillColor, lineColor, lineWidth; + + // 'so' is suspected outliers, for box plots + if(d.so) { + lineWidth = markerLine.outlierwidth; + lineColor = markerLine.outliercolor; + fillColor = marker.outliercolor; + } else { + var markerLineWidth = (markerLine || {}).width; + + lineWidth = ( + d.mlw + 1 || + markerLineWidth + 1 || + // TODO: we need the latter for legends... can we get rid of it? + (d.trace ? (d.trace.marker.line || {}).width : 0) + 1 + ) - 1 || 0; + + if('mlc' in d) lineColor = d.mlcc = fns.lineScale(d.mlc); + // weird case: array wasn't long enough to apply to every point + else if(Lib.isArrayOrTypedArray(markerLine.color)) lineColor = Color.defaultLine; + else lineColor = markerLine.color; + + if(Lib.isArrayOrTypedArray(marker.color)) { + fillColor = Color.defaultLine; + perPointGradient = true; + } + + if('mc' in d) { + fillColor = d.mcc = fns.markerScale(d.mc); + } else { + fillColor = marker.color || 'rgba(0,0,0,0)'; + } + + if(fns.selectedColorFn) { + fillColor = fns.selectedColorFn(d); + } + } + + if(d.om) { + // open markers can't have zero linewidth, default to 1px, + // and use fill color as stroke color + sel.call(Color.stroke, fillColor) + .style({ + 'stroke-width': (lineWidth || 1) + 'px', + fill: 'none' + }); + } else { + sel.style('stroke-width', lineWidth + 'px'); + + var markerGradient = marker.gradient; + + var gradientType = d.mgt; + if(gradientType) perPointGradient = true; + else gradientType = markerGradient && markerGradient.type; + + // for legend - arrays will propagate through here, but we don't need + // to treat it as per-point. + if(Array.isArray(gradientType)) { + gradientType = gradientType[0]; + if(!gradientInfo[gradientType]) gradientType = 0; + } + + if(gradientType && gradientType !== 'none') { + var gradientColor = d.mgc; + if(gradientColor) perPointGradient = true; + else gradientColor = markerGradient.color; + + var gradientID = trace.uid; + if(perPointGradient) gradientID += '-' + d.i; + + drawing.gradient(sel, gd, gradientID, gradientType, + [[0, gradientColor], [1, fillColor]], 'fill'); + } else { + Color.fill(sel, fillColor); + } + + if(lineWidth) { + Color.stroke(sel, lineColor); + } + } +}; + +drawing.makePointStyleFns = function(trace) { + var out = {}; + var marker = trace.marker; + + // allow array marker and marker line colors to be + // scaled by given max and min to colorscales + out.markerScale = drawing.tryColorscale(marker, ''); + out.lineScale = drawing.tryColorscale(marker, 'line'); + + if(Registry.traceIs(trace, 'symbols')) { + out.ms2mrc = subTypes.isBubble(trace) ? + makeBubbleSizeFn(trace) : + function() { return (marker.size || 6) / 2; }; + } + + if(trace.selectedpoints) { + Lib.extendFlat(out, drawing.makeSelectedPointStyleFns(trace)); + } + + return out; +}; + +drawing.makeSelectedPointStyleFns = function(trace) { + var out = {}; + + var selectedAttrs = trace.selected || {}; + var unselectedAttrs = trace.unselected || {}; + + var marker = trace.marker || {}; + var selectedMarker = selectedAttrs.marker || {}; + var unselectedMarker = unselectedAttrs.marker || {}; + + var mo = marker.opacity; + var smo = selectedMarker.opacity; + var usmo = unselectedMarker.opacity; + var smoIsDefined = smo !== undefined; + var usmoIsDefined = usmo !== undefined; + + if(Lib.isArrayOrTypedArray(mo) || smoIsDefined || usmoIsDefined) { + out.selectedOpacityFn = function(d) { + var base = d.mo === undefined ? marker.opacity : d.mo; + + if(d.selected) { + return smoIsDefined ? smo : base; + } else { + return usmoIsDefined ? usmo : DESELECTDIM * base; + } + }; + } + + var mc = marker.color; + var smc = selectedMarker.color; + var usmc = unselectedMarker.color; + + if(smc || usmc) { + out.selectedColorFn = function(d) { + var base = d.mcc || mc; + + if(d.selected) { + return smc || base; + } else { + return usmc || base; + } + }; + } + + var ms = marker.size; + var sms = selectedMarker.size; + var usms = unselectedMarker.size; + var smsIsDefined = sms !== undefined; + var usmsIsDefined = usms !== undefined; + + if(Registry.traceIs(trace, 'symbols') && (smsIsDefined || usmsIsDefined)) { + out.selectedSizeFn = function(d) { + var base = d.mrc || ms / 2; + + if(d.selected) { + return smsIsDefined ? sms / 2 : base; + } else { + return usmsIsDefined ? usms / 2 : base; + } + }; + } + + return out; +}; + +drawing.makeSelectedTextStyleFns = function(trace) { + var out = {}; + + var selectedAttrs = trace.selected || {}; + var unselectedAttrs = trace.unselected || {}; + + var textFont = trace.textfont || {}; + var selectedTextFont = selectedAttrs.textfont || {}; + var unselectedTextFont = unselectedAttrs.textfont || {}; + + var tc = textFont.color; + var stc = selectedTextFont.color; + var utc = unselectedTextFont.color; + + out.selectedTextColorFn = function(d) { + var base = d.tc || tc; + + if(d.selected) { + return stc || base; + } else { + if(utc) return utc; + else return stc ? base : Color.addOpacity(base, DESELECTDIM); + } + }; + + return out; +}; + +drawing.selectedPointStyle = function(s, trace) { + if(!s.size() || !trace.selectedpoints) return; + + var fns = drawing.makeSelectedPointStyleFns(trace); + var marker = trace.marker || {}; + var seq = []; + + if(fns.selectedOpacityFn) { + seq.push(function(pt, d) { + pt.style('opacity', fns.selectedOpacityFn(d)); + }); + } + + if(fns.selectedColorFn) { + seq.push(function(pt, d) { + Color.fill(pt, fns.selectedColorFn(d)); + }); + } + + if(fns.selectedSizeFn) { + seq.push(function(pt, d) { + var mx = d.mx || marker.symbol || 0; + var mrc2 = fns.selectedSizeFn(d); + + pt.attr('d', makePointPath(drawing.symbolNumber(mx), mrc2)); + + // save for Drawing.selectedTextStyle + d.mrc2 = mrc2; + }); + } + + if(seq.length) { + s.each(function(d) { + var pt = d3.select(this); + for(var i = 0; i < seq.length; i++) { + seq[i](pt, d); + } + }); + } +}; + +drawing.tryColorscale = function(marker, prefix) { + var cont = prefix ? Lib.nestedProperty(marker, prefix).get() : marker; + + if(cont) { + var scl = cont.colorscale; + var colorArray = cont.color; + + if(scl && Lib.isArrayOrTypedArray(colorArray)) { + return Colorscale.makeColorScaleFunc( + Colorscale.extractScale(scl, cont.cmin, cont.cmax) + ); + } + } + return Lib.identity; +}; + +var TEXTOFFSETSIGN = { + start: 1, end: -1, middle: 0, bottom: 1, top: -1 +}; + +function textPointPosition(s, textPosition, fontSize, markerRadius) { + var group = d3.select(s.node().parentNode); + + var v = textPosition.indexOf('top') !== -1 ? + 'top' : + textPosition.indexOf('bottom') !== -1 ? 'bottom' : 'middle'; + var h = textPosition.indexOf('left') !== -1 ? + 'end' : + textPosition.indexOf('right') !== -1 ? 'start' : 'middle'; + + // if markers are shown, offset a little more than + // the nominal marker size + // ie 2/1.6 * nominal, bcs some markers are a bit bigger + var r = markerRadius ? markerRadius / 0.8 + 1 : 0; + + var numLines = (svgTextUtils.lineCount(s) - 1) * LINE_SPACING + 1; + var dx = TEXTOFFSETSIGN[h] * r; + var dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + + (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; + + // fix the overall text group position + s.attr('text-anchor', h); + group.attr('transform', 'translate(' + dx + ',' + dy + ')'); +} + +function extracTextFontSize(d, trace) { + var fontSize = d.ts || trace.textfont.size; + return (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; +} + +// draw text at points +drawing.textPointStyle = function(s, trace, gd) { + if(!s.size()) return; + + var selectedTextColorFn; + + if(trace.selectedpoints) { + var fns = drawing.makeSelectedTextStyleFns(trace); + selectedTextColorFn = fns.selectedTextColorFn; + } + + s.each(function(d) { + var p = d3.select(this); + var text = Lib.extractOption(d, trace, 'tx', 'text'); + + if(!text && text !== 0) { + p.remove(); + return; + } + + var pos = d.tp || trace.textposition; + var fontSize = extracTextFontSize(d, trace); + var fontColor = selectedTextColorFn ? + selectedTextColorFn(d) : + (d.tc || trace.textfont.color); + + p.call(drawing.font, + d.tf || trace.textfont.family, + fontSize, + fontColor) + .text(text) + .call(svgTextUtils.convertToTspans, gd) + .call(textPointPosition, pos, fontSize, d.mrc); + }); +}; + +drawing.selectedTextStyle = function(s, trace) { + if(!s.size() || !trace.selectedpoints) return; + + var fns = drawing.makeSelectedTextStyleFns(trace); + + s.each(function(d) { + var tx = d3.select(this); + var tc = fns.selectedTextColorFn(d); + var tp = d.tp || trace.textposition; + var fontSize = extracTextFontSize(d, trace); + + Color.fill(tx, tc); + textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc); + }); +}; + +// generalized Catmull-Rom splines, per +// http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf +var CatmullRomExp = 0.5; +drawing.smoothopen = function(pts, smoothness) { + if(pts.length < 3) { return 'M' + pts.join('L');} + var path = 'M' + pts[0], + tangents = [], i; + for(i = 1; i < pts.length - 1; i++) { + tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); + } + path += 'Q' + tangents[0][0] + ' ' + pts[1]; + for(i = 2; i < pts.length - 1; i++) { + path += 'C' + tangents[i - 2][1] + ' ' + tangents[i - 1][0] + ' ' + pts[i]; + } + path += 'Q' + tangents[pts.length - 3][1] + ' ' + pts[pts.length - 1]; + return path; +}; + +drawing.smoothclosed = function(pts, smoothness) { + if(pts.length < 3) { return 'M' + pts.join('L') + 'Z'; } + var path = 'M' + pts[0], + pLast = pts.length - 1, + tangents = [makeTangent(pts[pLast], + pts[0], pts[1], smoothness)], + i; + for(i = 1; i < pLast; i++) { + tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); + } + tangents.push( + makeTangent(pts[pLast - 1], pts[pLast], pts[0], smoothness) + ); + + for(i = 1; i <= pLast; i++) { + path += 'C' + tangents[i - 1][1] + ' ' + tangents[i][0] + ' ' + pts[i]; + } + path += 'C' + tangents[pLast][1] + ' ' + tangents[0][0] + ' ' + pts[0] + 'Z'; + return path; +}; + +function makeTangent(prevpt, thispt, nextpt, smoothness) { + var d1x = prevpt[0] - thispt[0], + d1y = prevpt[1] - thispt[1], + d2x = nextpt[0] - thispt[0], + d2y = nextpt[1] - thispt[1], + d1a = Math.pow(d1x * d1x + d1y * d1y, CatmullRomExp / 2), + d2a = Math.pow(d2x * d2x + d2y * d2y, CatmullRomExp / 2), + numx = (d2a * d2a * d1x - d1a * d1a * d2x) * smoothness, + numy = (d2a * d2a * d1y - d1a * d1a * d2y) * smoothness, + denom1 = 3 * d2a * (d1a + d2a), + denom2 = 3 * d1a * (d1a + d2a); + return [ + [ + d3.round(thispt[0] + (denom1 && numx / denom1), 2), + d3.round(thispt[1] + (denom1 && numy / denom1), 2) + ], [ + d3.round(thispt[0] - (denom2 && numx / denom2), 2), + d3.round(thispt[1] - (denom2 && numy / denom2), 2) + ] + ]; +} + +// step paths - returns a generator function for paths +// with the given step shape +var STEPPATH = { + hv: function(p0, p1) { + return 'H' + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); + }, + vh: function(p0, p1) { + return 'V' + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); + }, + hvh: function(p0, p1) { + return 'H' + d3.round((p0[0] + p1[0]) / 2, 2) + 'V' + + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); + }, + vhv: function(p0, p1) { + return 'V' + d3.round((p0[1] + p1[1]) / 2, 2) + 'H' + + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); + } +}; +var STEPLINEAR = function(p0, p1) { + return 'L' + d3.round(p1[0], 2) + ',' + d3.round(p1[1], 2); +}; +drawing.steps = function(shape) { + var onestep = STEPPATH[shape] || STEPLINEAR; + return function(pts) { + var path = 'M' + d3.round(pts[0][0], 2) + ',' + d3.round(pts[0][1], 2); + for(var i = 1; i < pts.length; i++) { + path += onestep(pts[i - 1], pts[i]); + } + return path; + }; +}; + +// off-screen svg render testing element, shared by the whole page +// uses the id 'js-plotly-tester' and stores it in drawing.tester +drawing.makeTester = function() { + var tester = Lib.ensureSingleById(d3.select('body'), 'svg', 'js-plotly-tester', function(s) { + s.attr(xmlnsNamespaces.svgAttrs) + .style({ + position: 'absolute', + left: '-10000px', + top: '-10000px', + width: '9000px', + height: '9000px', + 'z-index': '1' + }); + }); + + // browsers differ on how they describe the bounding rect of + // the svg if its contents spill over... so make a 1x1px + // reference point we can measure off of. + var testref = Lib.ensureSingle(tester, 'path', 'js-reference-point', function(s) { + s.attr('d', 'M0,0H1V1H0Z') + .style({ + 'stroke-width': 0, + fill: 'black' + }); + }); + + drawing.tester = tester; + drawing.testref = testref; +}; + +/* + * use our offscreen tester to get a clientRect for an element, + * in a reference frame where it isn't translated (or transformed) and + * its anchor point is at (0,0) + * always returns a copy of the bbox, so the caller can modify it safely + * + * @param {SVGElement} node: the element to measure. If possible this should be + * a or MathJax element that's already passed through + * `convertToTspans` because in that case we can cache the results, but it's + * possible to pass in any svg element. + * + * @param {boolean} inTester: is this element already in `drawing.tester`? + * If you are measuring a dummy element, rather than one you really intend + * to use on the plot, making it in `drawing.tester` in the first place + * allows us to test faster because it cuts out cloning and appending it. + * + * @param {string} hash: for internal use only, if we already know the cache key + * for this element beforehand. + * + * @return {object}: a plain object containing the width, height, left, right, + * top, and bottom of `node` + */ +drawing.savedBBoxes = {}; +var savedBBoxesCount = 0; +var maxSavedBBoxes = 10000; + +drawing.bBox = function(node, inTester, hash) { + /* + * Cache elements we've already measured so we don't have to + * remeasure the same thing many times + * We have a few bBox callers though who pass a node larger than + * a or a MathJax , such as an axis group containing many labels. + * These will not generate a hash (unless we figure out an appropriate + * hash key for them) and thus we will not hash them. + */ + if(!hash) hash = nodeHash(node); + var out; + if(hash) { + out = drawing.savedBBoxes[hash]; + if(out) return Lib.extendFlat({}, out); + } + else if(node.childNodes.length === 1) { + /* + * If we have only one child element, which is itself hashable, make + * a new hash from this element plus its x,y,transform + * These bounding boxes *include* x,y,transform - mostly for use by + * callers trying to avoid overlaps (ie titles) + */ + var innerNode = node.childNodes[0]; + + hash = nodeHash(innerNode); + if(hash) { + var x = +innerNode.getAttribute('x') || 0; + var y = +innerNode.getAttribute('y') || 0; + var transform = innerNode.getAttribute('transform'); + + if(!transform) { + // in this case, just varying x and y, don't bother caching + // the final bBox because the alteration is quick. + var innerBB = drawing.bBox(innerNode, false, hash); + if(x) { + innerBB.left += x; + innerBB.right += x; + } + if(y) { + innerBB.top += y; + innerBB.bottom += y; + } + return innerBB; + } + /* + * else we have a transform - rather than make a complicated + * (and error-prone and probably slow) transform parser/calculator, + * just continue on calculating the boundingClientRect of the group + * and use the new composite hash to cache it. + * That said, `innerNode.transform.baseVal` is an array of + * `SVGTransform` objects, that *do* seem to have a nice matrix + * multiplication interface that we could use to avoid making + * another getBoundingClientRect call... + */ + hash += '~' + x + '~' + y + '~' + transform; + + out = drawing.savedBBoxes[hash]; + if(out) return Lib.extendFlat({}, out); + } + } + var testNode, tester; + if(inTester) { + testNode = node; + } + else { + tester = drawing.tester.node(); + + // copy the node to test into the tester + testNode = node.cloneNode(true); + tester.appendChild(testNode); + } + + // standardize its position (and newline tspans if any) + d3.select(testNode) + .attr('transform', null) + .call(svgTextUtils.positionText, 0, 0); + + var testRect = testNode.getBoundingClientRect(); + var refRect = drawing.testref + .node() + .getBoundingClientRect(); + + if(!inTester) tester.removeChild(testNode); + + var bb = { + height: testRect.height, + width: testRect.width, + left: testRect.left - refRect.left, + top: testRect.top - refRect.top, + right: testRect.right - refRect.left, + bottom: testRect.bottom - refRect.top + }; + + // make sure we don't have too many saved boxes, + // or a long session could overload on memory + // by saving boxes for long-gone elements + if(savedBBoxesCount >= maxSavedBBoxes) { + drawing.savedBBoxes = {}; + savedBBoxesCount = 0; + } + + // cache this bbox + if(hash) drawing.savedBBoxes[hash] = bb; + savedBBoxesCount++; + + return Lib.extendFlat({}, bb); +}; + +// capture everything about a node (at least in our usage) that +// impacts its bounding box, given that bBox clears x, y, and transform +function nodeHash(node) { + var inputText = node.getAttribute('data-unformatted'); + if(inputText === null) return; + return inputText + + node.getAttribute('data-math') + + node.getAttribute('text-anchor') + + node.getAttribute('style'); +} + +/* + * make a robust clipPath url from a local id + * note! We'd better not be exporting from a page + * with a or the svg will not be portable! + */ +drawing.setClipUrl = function(s, localId) { + if(!localId) { + s.attr('clip-path', null); + return; + } + + if(drawing.baseUrl === undefined) { + var base = d3.select('base'); + + // Stash base url once and for all! + // We may have to stash this elsewhere when + // we'll try to support for child windows + // more info -> https://github.com/plotly/plotly.js/issues/702 + if(base.size() && base.attr('href')) { + drawing.baseUrl = window.location.href.split('#')[0]; + } else { + drawing.baseUrl = ''; + } + } + + s.attr('clip-path', 'url(' + drawing.baseUrl + '#' + localId + ')'); +}; + +drawing.getTranslate = function(element) { + // Note the separator [^\d] between x and y in this regex + // We generally use ',' but IE will convert it to ' ' + var re = /.*\btranslate\((-?\d*\.?\d*)[^-\d]*(-?\d*\.?\d*)[^\d].*/, + getter = element.attr ? 'attr' : 'getAttribute', + transform = element[getter]('transform') || ''; + + var translate = transform.replace(re, function(match, p1, p2) { + return [p1, p2].join(' '); + }) + .split(' '); + + return { + x: +translate[0] || 0, + y: +translate[1] || 0 + }; +}; + +drawing.setTranslate = function(element, x, y) { + + var re = /(\btranslate\(.*?\);?)/, + getter = element.attr ? 'attr' : 'getAttribute', + setter = element.attr ? 'attr' : 'setAttribute', + transform = element[getter]('transform') || ''; + + x = x || 0; + y = y || 0; + + transform = transform.replace(re, '').trim(); + transform += ' translate(' + x + ', ' + y + ')'; + transform = transform.trim(); + + element[setter]('transform', transform); + + return transform; +}; + +drawing.getScale = function(element) { + + var re = /.*\bscale\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/, + getter = element.attr ? 'attr' : 'getAttribute', + transform = element[getter]('transform') || ''; + + var translate = transform.replace(re, function(match, p1, p2) { + return [p1, p2].join(' '); + }) + .split(' '); + + return { + x: +translate[0] || 1, + y: +translate[1] || 1 + }; +}; + +drawing.setScale = function(element, x, y) { + + var re = /(\bscale\(.*?\);?)/, + getter = element.attr ? 'attr' : 'getAttribute', + setter = element.attr ? 'attr' : 'setAttribute', + transform = element[getter]('transform') || ''; + + x = x || 1; + y = y || 1; + + transform = transform.replace(re, '').trim(); + transform += ' scale(' + x + ', ' + y + ')'; + transform = transform.trim(); + + element[setter]('transform', transform); + + return transform; +}; + +var SCALE_RE = /\s*sc.*/; + +drawing.setPointGroupScale = function(selection, xScale, yScale) { + xScale = xScale || 1; + yScale = yScale || 1; + + if(!selection) return; + + // The same scale transform for every point: + var scale = (xScale === 1 && yScale === 1) ? + '' : + ' scale(' + xScale + ',' + yScale + ')'; + + selection.each(function() { + var t = (this.getAttribute('transform') || '').replace(SCALE_RE, ''); + t += scale; + t = t.trim(); + this.setAttribute('transform', t); + }); +}; + +var TEXT_POINT_LAST_TRANSLATION_RE = /translate\([^)]*\)\s*$/; + +drawing.setTextPointsScale = function(selection, xScale, yScale) { + if(!selection) return; + + selection.each(function() { + var transforms; + var el = d3.select(this); + var text = el.select('text'); + + if(!text.node()) return; + + var x = parseFloat(text.attr('x') || 0); + var y = parseFloat(text.attr('y') || 0); + + var existingTransform = (el.attr('transform') || '').match(TEXT_POINT_LAST_TRANSLATION_RE); + + if(xScale === 1 && yScale === 1) { + transforms = []; + } else { + transforms = [ + 'translate(' + x + ',' + y + ')', + 'scale(' + xScale + ',' + yScale + ')', + 'translate(' + (-x) + ',' + (-y) + ')', + ]; + } + + if(existingTransform) { + transforms.push(existingTransform); + } + + el.attr('transform', transforms.join(' ')); + }); +}; + +},{"../../constants/alignment":668,"../../constants/interactions":672,"../../constants/xmlns_namespaces":674,"../../lib":696,"../../lib/svg_text_utils":720,"../../registry":827,"../../traces/scatter/make_bubble_size_func":1060,"../../traces/scatter/subtypes":1067,"../color":570,"../colorscale":585,"./symbol_defs":596,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,"tinycolor2":514}],596:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +/** Marker symbol definitions + * users can specify markers either by number or name + * add 100 (or '-open') and you get an open marker + * open markers have no fill and use line color as the stroke color + * add 200 (or '-dot') and you get a dot in the middle + * add both and you get both + */ + +module.exports = { + circle: { + n: 0, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + } + }, + square: { + n: 1, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + } + }, + diamond: { + n: 2, + f: function(r) { + var rd = d3.round(r * 1.3, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z'; + } + }, + cross: { + n: 3, + f: function(r) { + var rc = d3.round(r * 0.4, 2), + rc2 = d3.round(r * 1.2, 2); + return 'M' + rc2 + ',' + rc + 'H' + rc + 'V' + rc2 + 'H-' + rc + + 'V' + rc + 'H-' + rc2 + 'V-' + rc + 'H-' + rc + 'V-' + rc2 + + 'H' + rc + 'V-' + rc + 'H' + rc2 + 'Z'; + } + }, + x: { + n: 4, + f: function(r) { + var rx = d3.round(r * 0.8 / Math.sqrt(2), 2), + ne = 'l' + rx + ',' + rx, + se = 'l' + rx + ',-' + rx, + sw = 'l-' + rx + ',-' + rx, + nw = 'l-' + rx + ',' + rx; + return 'M0,' + rx + ne + se + sw + se + sw + nw + sw + nw + ne + nw + ne + 'Z'; + } + }, + 'triangle-up': { + n: 5, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + rt + ',' + r2 + 'H' + rt + 'L0,-' + rs + 'Z'; + } + }, + 'triangle-down': { + n: 6, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + rt + ',-' + r2 + 'H' + rt + 'L0,' + rs + 'Z'; + } + }, + 'triangle-left': { + n: 7, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M' + r2 + ',-' + rt + 'V' + rt + 'L-' + rs + ',0Z'; + } + }, + 'triangle-right': { + n: 8, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + r2 + ',-' + rt + 'V' + rt + 'L' + rs + ',0Z'; + } + }, + 'triangle-ne': { + n: 9, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M-' + r2 + ',-' + r1 + 'H' + r1 + 'V' + r2 + 'Z'; + } + }, + 'triangle-se': { + n: 10, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M' + r1 + ',-' + r2 + 'V' + r1 + 'H-' + r2 + 'Z'; + } + }, + 'triangle-sw': { + n: 11, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M' + r2 + ',' + r1 + 'H-' + r1 + 'V-' + r2 + 'Z'; + } + }, + 'triangle-nw': { + n: 12, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M-' + r1 + ',' + r2 + 'V-' + r1 + 'H' + r2 + 'Z'; + } + }, + pentagon: { + n: 13, + f: function(r) { + var x1 = d3.round(r * 0.951, 2), + x2 = d3.round(r * 0.588, 2), + y0 = d3.round(-r, 2), + y1 = d3.round(r * -0.309, 2), + y2 = d3.round(r * 0.809, 2); + return 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2 + 'H-' + x2 + + 'L-' + x1 + ',' + y1 + 'L0,' + y0 + 'Z'; + } + }, + hexagon: { + n: 14, + f: function(r) { + var y0 = d3.round(r, 2), + y1 = d3.round(r / 2, 2), + x = d3.round(r * Math.sqrt(3) / 2, 2); + return 'M' + x + ',-' + y1 + 'V' + y1 + 'L0,' + y0 + + 'L-' + x + ',' + y1 + 'V-' + y1 + 'L0,-' + y0 + 'Z'; + } + }, + hexagon2: { + n: 15, + f: function(r) { + var x0 = d3.round(r, 2), + x1 = d3.round(r / 2, 2), + y = d3.round(r * Math.sqrt(3) / 2, 2); + return 'M-' + x1 + ',' + y + 'H' + x1 + 'L' + x0 + + ',0L' + x1 + ',-' + y + 'H-' + x1 + 'L-' + x0 + ',0Z'; + } + }, + octagon: { + n: 16, + f: function(r) { + var a = d3.round(r * 0.924, 2), + b = d3.round(r * 0.383, 2); + return 'M-' + b + ',-' + a + 'H' + b + 'L' + a + ',-' + b + 'V' + b + + 'L' + b + ',' + a + 'H-' + b + 'L-' + a + ',' + b + 'V-' + b + 'Z'; + } + }, + star: { + n: 17, + f: function(r) { + var rs = r * 1.4, + x1 = d3.round(rs * 0.225, 2), + x2 = d3.round(rs * 0.951, 2), + x3 = d3.round(rs * 0.363, 2), + x4 = d3.round(rs * 0.588, 2), + y0 = d3.round(-rs, 2), + y1 = d3.round(rs * -0.309, 2), + y3 = d3.round(rs * 0.118, 2), + y4 = d3.round(rs * 0.809, 2), + y5 = d3.round(rs * 0.382, 2); + return 'M' + x1 + ',' + y1 + 'H' + x2 + 'L' + x3 + ',' + y3 + + 'L' + x4 + ',' + y4 + 'L0,' + y5 + 'L-' + x4 + ',' + y4 + + 'L-' + x3 + ',' + y3 + 'L-' + x2 + ',' + y1 + 'H-' + x1 + + 'L0,' + y0 + 'Z'; + } + }, + hexagram: { + n: 18, + f: function(r) { + var y = d3.round(r * 0.66, 2), + x1 = d3.round(r * 0.38, 2), + x2 = d3.round(r * 0.76, 2); + return 'M-' + x2 + ',0l-' + x1 + ',-' + y + 'h' + x2 + + 'l' + x1 + ',-' + y + 'l' + x1 + ',' + y + 'h' + x2 + + 'l-' + x1 + ',' + y + 'l' + x1 + ',' + y + 'h-' + x2 + + 'l-' + x1 + ',' + y + 'l-' + x1 + ',-' + y + 'h-' + x2 + 'Z'; + } + }, + 'star-triangle-up': { + n: 19, + f: function(r) { + var x = d3.round(r * Math.sqrt(3) * 0.8, 2), + y1 = d3.round(r * 0.8, 2), + y2 = d3.round(r * 1.6, 2), + rc = d3.round(r * 4, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + x + ',' + y1 + aPart + x + ',' + y1 + + aPart + '0,-' + y2 + aPart + '-' + x + ',' + y1 + 'Z'; + } + }, + 'star-triangle-down': { + n: 20, + f: function(r) { + var x = d3.round(r * Math.sqrt(3) * 0.8, 2), + y1 = d3.round(r * 0.8, 2), + y2 = d3.round(r * 1.6, 2), + rc = d3.round(r * 4, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M' + x + ',-' + y1 + aPart + '-' + x + ',-' + y1 + + aPart + '0,' + y2 + aPart + x + ',-' + y1 + 'Z'; + } + }, + 'star-square': { + n: 21, + f: function(r) { + var rp = d3.round(r * 1.1, 2), + rc = d3.round(r * 2, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + rp + ',-' + rp + aPart + '-' + rp + ',' + rp + + aPart + rp + ',' + rp + aPart + rp + ',-' + rp + + aPart + '-' + rp + ',-' + rp + 'Z'; + } + }, + 'star-diamond': { + n: 22, + f: function(r) { + var rp = d3.round(r * 1.4, 2), + rc = d3.round(r * 1.9, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + rp + ',0' + aPart + '0,' + rp + + aPart + rp + ',0' + aPart + '0,-' + rp + + aPart + '-' + rp + ',0' + 'Z'; + } + }, + 'diamond-tall': { + n: 23, + f: function(r) { + var x = d3.round(r * 0.7, 2), + y = d3.round(r * 1.4, 2); + return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; + } + }, + 'diamond-wide': { + n: 24, + f: function(r) { + var x = d3.round(r * 1.4, 2), + y = d3.round(r * 0.7, 2); + return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; + } + }, + hourglass: { + n: 25, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'H-' + rs + 'L' + rs + ',-' + rs + 'H-' + rs + 'Z'; + }, + noDot: true + }, + bowtie: { + n: 26, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'V-' + rs + 'L-' + rs + ',' + rs + 'V-' + rs + 'Z'; + }, + noDot: true + }, + 'circle-cross': { + n: 27, + f: function(r) { + var rs = d3.round(r, 2); + return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + + 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + }, + needLine: true, + noDot: true + }, + 'circle-x': { + n: 28, + f: function(r) { + var rs = d3.round(r, 2), + rc = d3.round(r / Math.sqrt(2), 2); + return 'M' + rc + ',' + rc + 'L-' + rc + ',-' + rc + + 'M' + rc + ',-' + rc + 'L-' + rc + ',' + rc + + 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + }, + needLine: true, + noDot: true + }, + 'square-cross': { + n: 29, + f: function(r) { + var rs = d3.round(r, 2); + return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + + 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + }, + needLine: true, + noDot: true + }, + 'square-x': { + n: 30, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + + 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs + + 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + }, + needLine: true, + noDot: true + }, + 'diamond-cross': { + n: 31, + f: function(r) { + var rd = d3.round(r * 1.3, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + + 'M0,-' + rd + 'V' + rd + 'M-' + rd + ',0H' + rd; + }, + needLine: true, + noDot: true + }, + 'diamond-x': { + n: 32, + f: function(r) { + var rd = d3.round(r * 1.3, 2), + r2 = d3.round(r * 0.65, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + + 'M-' + r2 + ',-' + r2 + 'L' + r2 + ',' + r2 + + 'M-' + r2 + ',' + r2 + 'L' + r2 + ',-' + r2; + }, + needLine: true, + noDot: true + }, + 'cross-thin': { + n: 33, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'x-thin': { + n: 34, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx + + 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; + }, + needLine: true, + noDot: true, + noFill: true + }, + asterisk: { + n: 35, + f: function(r) { + var rc = d3.round(r * 1.2, 2); + var rs = d3.round(r * 0.85, 2); + return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc + + 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + + 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs; + }, + needLine: true, + noDot: true, + noFill: true + }, + hash: { + n: 36, + f: function(r) { + var r1 = d3.round(r / 2, 2), + r2 = d3.round(r, 2); + return 'M' + r1 + ',' + r2 + 'V-' + r2 + + 'm-' + r2 + ',0V' + r2 + + 'M' + r2 + ',' + r1 + 'H-' + r2 + + 'm0,-' + r2 + 'H' + r2; + }, + needLine: true, + noFill: true + }, + 'y-up': { + n: 37, + f: function(r) { + var x = d3.round(r * 1.2, 2), + y0 = d3.round(r * 1.6, 2), + y1 = d3.round(r * 0.8, 2); + return 'M-' + x + ',' + y1 + 'L0,0M' + x + ',' + y1 + 'L0,0M0,-' + y0 + 'L0,0'; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'y-down': { + n: 38, + f: function(r) { + var x = d3.round(r * 1.2, 2), + y0 = d3.round(r * 1.6, 2), + y1 = d3.round(r * 0.8, 2); + return 'M-' + x + ',-' + y1 + 'L0,0M' + x + ',-' + y1 + 'L0,0M0,' + y0 + 'L0,0'; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'y-left': { + n: 39, + f: function(r) { + var y = d3.round(r * 1.2, 2), + x0 = d3.round(r * 1.6, 2), + x1 = d3.round(r * 0.8, 2); + return 'M' + x1 + ',' + y + 'L0,0M' + x1 + ',-' + y + 'L0,0M-' + x0 + ',0L0,0'; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'y-right': { + n: 40, + f: function(r) { + var y = d3.round(r * 1.2, 2), + x0 = d3.round(r * 1.6, 2), + x1 = d3.round(r * 0.8, 2); + return 'M-' + x1 + ',' + y + 'L0,0M-' + x1 + ',-' + y + 'L0,0M' + x0 + ',0L0,0'; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'line-ew': { + n: 41, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M' + rc + ',0H-' + rc; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'line-ns': { + n: 42, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M0,' + rc + 'V-' + rc; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'line-ne': { + n: 43, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; + }, + needLine: true, + noDot: true, + noFill: true + }, + 'line-nw': { + n: 44, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx; + }, + needLine: true, + noDot: true, + noFill: true + } +}; + +},{"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],597:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + visible: { + valType: 'boolean', + + editType: 'calc', + + }, + type: { + valType: 'enumerated', + values: ['percent', 'constant', 'sqrt', 'data'], + + editType: 'calc', + + }, + symmetric: { + valType: 'boolean', + + editType: 'calc', + + }, + array: { + valType: 'data_array', + editType: 'calc', + + }, + arrayminus: { + valType: 'data_array', + editType: 'calc', + + }, + value: { + valType: 'number', + min: 0, + dflt: 10, + + editType: 'calc', + + }, + valueminus: { + valType: 'number', + min: 0, + dflt: 10, + + editType: 'calc', + + }, + traceref: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'style' + }, + tracerefminus: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'style' + }, + copy_ystyle: { + valType: 'boolean', + + editType: 'plot' + }, + copy_zstyle: { + valType: 'boolean', + + editType: 'style' + }, + color: { + valType: 'color', + + editType: 'style', + + }, + thickness: { + valType: 'number', + min: 0, + dflt: 2, + + editType: 'style', + + }, + width: { + valType: 'number', + min: 0, + + editType: 'plot', + + }, + editType: 'calc', + + _deprecated: { + opacity: { + valType: 'number', + + editType: 'style', + + } + } +}; + +},{}],598:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Registry = _dereq_('../../registry'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var makeComputeError = _dereq_('./compute_error'); + + +module.exports = function calc(gd) { + var calcdata = gd.calcdata; + + for(var i = 0; i < calcdata.length; i++) { + var calcTrace = calcdata[i]; + var trace = calcTrace[0].trace; + + if(trace.visible === true && Registry.traceIs(trace, 'errorBarsOK')) { + var xa = Axes.getFromId(gd, trace.xaxis); + var ya = Axes.getFromId(gd, trace.yaxis); + calcOneAxis(calcTrace, trace, xa, 'x'); + calcOneAxis(calcTrace, trace, ya, 'y'); + } + } +}; + +function calcOneAxis(calcTrace, trace, axis, coord) { + var opts = trace['error_' + coord] || {}, + isVisible = (opts.visible && ['linear', 'log'].indexOf(axis.type) !== -1), + vals = []; + + if(!isVisible) return; + + var computeError = makeComputeError(opts); + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + + var iIn = calcPt.i; + + // for types that don't include `i` in each calcdata point + if(iIn === undefined) iIn = i; + + // for stacked area inserted points + // TODO: errorbars have been tested cursorily with stacked area, + // but not thoroughly. It's not even really clear what you want to do: + // Should it just be calculated based on that trace's size data? + // Should you add errors from below in quadrature? + // And what about normalization, where in principle the errors shrink + // again when you get up to the top end? + // One option would be to forbid errorbars with stacking until we + // decide how to handle these questions. + else if(iIn === null) continue; + + var calcCoord = calcPt[coord]; + + if(!isNumeric(axis.c2l(calcCoord))) continue; + + var errors = computeError(calcCoord, iIn); + if(isNumeric(errors[0]) && isNumeric(errors[1])) { + var shoe = calcPt[coord + 's'] = calcCoord - errors[0], + hat = calcPt[coord + 'h'] = calcCoord + errors[1]; + vals.push(shoe, hat); + } + } + + var extremes = Axes.findExtremes(axis, vals, {padded: true}); + var axId = axis._id; + trace._extremes[axId].min = trace._extremes[axId].min.concat(extremes.min); + trace._extremes[axId].max = trace._extremes[axId].max.concat(extremes.max); +} + +},{"../../plots/cartesian/axes":744,"../../registry":827,"./compute_error":599,"fast-isnumeric":214}],599:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Error bar computing function generator + * + * N.B. The generated function does not clean the dataPt entries. Non-numeric + * entries result in undefined error magnitudes. + * + * @param {object} opts error bar attributes + * + * @return {function} : + * @param {numeric} dataPt data point from where to compute the error magnitude + * @param {number} index index of dataPt in its corresponding data array + * @return {array} + * - error[0] : error magnitude in the negative direction + * - error[1] : " " " " positive " + */ +module.exports = function makeComputeError(opts) { + var type = opts.type, + symmetric = opts.symmetric; + + if(type === 'data') { + var array = opts.array || []; + + if(symmetric) { + return function computeError(dataPt, index) { + var val = +(array[index]); + return [val, val]; + }; + } + else { + var arrayminus = opts.arrayminus || []; + return function computeError(dataPt, index) { + var val = +array[index]; + var valMinus = +arrayminus[index]; + // in case one is present and the other is missing, fill in 0 + // so we still see the present one. Mostly useful during manual + // data entry. + if(!isNaN(val) || !isNaN(valMinus)) { + return [valMinus || 0, val || 0]; + } + return [NaN, NaN]; + }; + } + } + else { + var computeErrorValue = makeComputeErrorValue(type, opts.value), + computeErrorValueMinus = makeComputeErrorValue(type, opts.valueminus); + + if(symmetric || opts.valueminus === undefined) { + return function computeError(dataPt) { + var val = computeErrorValue(dataPt); + return [val, val]; + }; + } + else { + return function computeError(dataPt) { + return [ + computeErrorValueMinus(dataPt), + computeErrorValue(dataPt) + ]; + }; + } + } +}; + +/** + * Compute error bar magnitude (for all types except data) + * + * @param {string} type error bar type + * @param {numeric} value error bar value + * + * @return {function} : + * @param {numeric} dataPt + */ +function makeComputeErrorValue(type, value) { + if(type === 'percent') { + return function(dataPt) { + return Math.abs(dataPt * value / 100); + }; + } + if(type === 'constant') { + return function() { + return Math.abs(value); + }; + } + if(type === 'sqrt') { + return function(dataPt) { + return Math.sqrt(Math.abs(dataPt)); + }; + } +} + +},{}],600:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Template = _dereq_('../../plot_api/plot_template'); + +var attributes = _dereq_('./attributes'); + + +module.exports = function(traceIn, traceOut, defaultColor, opts) { + var objName = 'error_' + opts.axis; + var containerOut = Template.newContainer(traceOut, objName); + var containerIn = traceIn[objName] || {}; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + var hasErrorBars = ( + containerIn.array !== undefined || + containerIn.value !== undefined || + containerIn.type === 'sqrt' + ); + + var visible = coerce('visible', hasErrorBars); + + if(visible === false) return; + + var type = coerce('type', 'array' in containerIn ? 'data' : 'percent'), + symmetric = true; + + if(type !== 'sqrt') { + symmetric = coerce('symmetric', + !((type === 'data' ? 'arrayminus' : 'valueminus') in containerIn)); + } + + if(type === 'data') { + coerce('array'); + coerce('traceref'); + if(!symmetric) { + coerce('arrayminus'); + coerce('tracerefminus'); + } + } + else if(type === 'percent' || type === 'constant') { + coerce('value'); + if(!symmetric) coerce('valueminus'); + } + + var copyAttr = 'copy_' + opts.inherit + 'style'; + if(opts.inherit) { + var inheritObj = traceOut['error_' + opts.inherit]; + if((inheritObj || {}).visible) { + coerce(copyAttr, !(containerIn.color || + isNumeric(containerIn.thickness) || + isNumeric(containerIn.width))); + } + } + if(!opts.inherit || !containerOut[copyAttr]) { + coerce('color', defaultColor); + coerce('thickness'); + coerce('width', Registry.traceIs(traceOut, 'gl3d') ? 0 : 4); + } +}; + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../registry":827,"./attributes":597,"fast-isnumeric":214}],601:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var attributes = _dereq_('./attributes'); + +var xyAttrs = { + error_x: Lib.extendFlat({}, attributes), + error_y: Lib.extendFlat({}, attributes) +}; +delete xyAttrs.error_x.copy_zstyle; +delete xyAttrs.error_y.copy_zstyle; +delete xyAttrs.error_y.copy_ystyle; + +var xyzAttrs = { + error_x: Lib.extendFlat({}, attributes), + error_y: Lib.extendFlat({}, attributes), + error_z: Lib.extendFlat({}, attributes) +}; +delete xyzAttrs.error_x.copy_ystyle; +delete xyzAttrs.error_y.copy_ystyle; +delete xyzAttrs.error_z.copy_ystyle; +delete xyzAttrs.error_z.copy_zstyle; + +module.exports = { + moduleType: 'component', + name: 'errorbars', + + schema: { + traces: { + scatter: xyAttrs, + bar: xyAttrs, + histogram: xyAttrs, + scatter3d: overrideAll(xyzAttrs, 'calc', 'nested'), + scattergl: overrideAll(xyAttrs, 'calc', 'nested') + } + }, + + supplyDefaults: _dereq_('./defaults'), + + calc: _dereq_('./calc'), + makeComputeError: _dereq_('./compute_error'), + + plot: _dereq_('./plot'), + style: _dereq_('./style'), + hoverInfo: hoverInfo +}; + +function hoverInfo(calcPoint, trace, hoverPoint) { + if((trace.error_y || {}).visible) { + hoverPoint.yerr = calcPoint.yh - calcPoint.y; + if(!trace.error_y.symmetric) hoverPoint.yerrneg = calcPoint.y - calcPoint.ys; + } + if((trace.error_x || {}).visible) { + hoverPoint.xerr = calcPoint.xh - calcPoint.x; + if(!trace.error_x.symmetric) hoverPoint.xerrneg = calcPoint.x - calcPoint.xs; + } +} + +},{"../../lib":696,"../../plot_api/edit_types":727,"./attributes":597,"./calc":598,"./compute_error":599,"./defaults":600,"./plot":602,"./style":603}],602:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Drawing = _dereq_('../drawing'); +var subTypes = _dereq_('../../traces/scatter/subtypes'); + +module.exports = function plot(traces, plotinfo, transitionOpts) { + var isNew; + + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + var hasAnimation = transitionOpts && transitionOpts.duration > 0; + + traces.each(function(d) { + var trace = d[0].trace, + // || {} is in case the trace (specifically scatterternary) + // doesn't support error bars at all, but does go through + // the scatter.plot mechanics, which calls ErrorBars.plot + // internally + xObj = trace.error_x || {}, + yObj = trace.error_y || {}; + + var keyFunc; + + if(trace.ids) { + keyFunc = function(d) {return d.id;}; + } + + var sparse = ( + subTypes.hasMarkers(trace) && + trace.marker.maxdisplayed > 0 + ); + + if(!yObj.visible && !xObj.visible) d = []; + + var errorbars = d3.select(this).selectAll('g.errorbar') + .data(d, keyFunc); + + errorbars.exit().remove(); + + if(!d.length) return; + + if(!xObj.visible) errorbars.selectAll('path.xerror').remove(); + if(!yObj.visible) errorbars.selectAll('path.yerror').remove(); + + errorbars.style('opacity', 1); + + var enter = errorbars.enter().append('g') + .classed('errorbar', true); + + if(hasAnimation) { + enter.style('opacity', 0).transition() + .duration(transitionOpts.duration) + .style('opacity', 1); + } + + Drawing.setClipUrl(errorbars, plotinfo.layerClipId); + + errorbars.each(function(d) { + var errorbar = d3.select(this); + var coords = errorCoords(d, xa, ya); + + if(sparse && !d.vis) return; + + var path; + + var yerror = errorbar.select('path.yerror'); + if(yObj.visible && isNumeric(coords.x) && + isNumeric(coords.yh) && + isNumeric(coords.ys)) { + var yw = yObj.width; + + path = 'M' + (coords.x - yw) + ',' + + coords.yh + 'h' + (2 * yw) + // hat + 'm-' + yw + ',0V' + coords.ys; // bar + + + if(!coords.noYS) path += 'm-' + yw + ',0h' + (2 * yw); // shoe + + isNew = !yerror.size(); + + if(isNew) { + yerror = errorbar.append('path') + .style('vector-effect', 'non-scaling-stroke') + .classed('yerror', true); + } else if(hasAnimation) { + yerror = yerror + .transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing); + } + + yerror.attr('d', path); + } + else yerror.remove(); + + var xerror = errorbar.select('path.xerror'); + if(xObj.visible && isNumeric(coords.y) && + isNumeric(coords.xh) && + isNumeric(coords.xs)) { + var xw = (xObj.copy_ystyle ? yObj : xObj).width; + + path = 'M' + coords.xh + ',' + + (coords.y - xw) + 'v' + (2 * xw) + // hat + 'm0,-' + xw + 'H' + coords.xs; // bar + + if(!coords.noXS) path += 'm0,-' + xw + 'v' + (2 * xw); // shoe + + isNew = !xerror.size(); + + if(isNew) { + xerror = errorbar.append('path') + .style('vector-effect', 'non-scaling-stroke') + .classed('xerror', true); + } else if(hasAnimation) { + xerror = xerror + .transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing); + } + + xerror.attr('d', path); + } + else xerror.remove(); + }); + }); +}; + +// compute the coordinates of the error-bar objects +function errorCoords(d, xa, ya) { + var out = { + x: xa.c2p(d.x), + y: ya.c2p(d.y) + }; + + // calculate the error bar size and hat and shoe locations + if(d.yh !== undefined) { + out.yh = ya.c2p(d.yh); + out.ys = ya.c2p(d.ys); + + // if the shoes go off-scale (ie log scale, error bars past zero) + // clip the bar and hide the shoes + if(!isNumeric(out.ys)) { + out.noYS = true; + out.ys = ya.c2p(d.ys, true); + } + } + + if(d.xh !== undefined) { + out.xh = xa.c2p(d.xh); + out.xs = xa.c2p(d.xs); + + if(!isNumeric(out.xs)) { + out.noXS = true; + out.xs = xa.c2p(d.xs, true); + } + } + + return out; +} + +},{"../../traces/scatter/subtypes":1067,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],603:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Color = _dereq_('../color'); + + +module.exports = function style(traces) { + traces.each(function(d) { + var trace = d[0].trace, + yObj = trace.error_y || {}, + xObj = trace.error_x || {}; + + var s = d3.select(this); + + s.selectAll('path.yerror') + .style('stroke-width', yObj.thickness + 'px') + .call(Color.stroke, yObj.color); + + if(xObj.copy_ystyle) xObj = yObj; + + s.selectAll('path.xerror') + .style('stroke-width', xObj.thickness + 'px') + .call(Color.stroke, xObj.color); + }); +}; + +},{"../color":570,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],604:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); + +module.exports = { + hoverlabel: { + bgcolor: { + valType: 'color', + + arrayOk: true, + editType: 'none', + + }, + bordercolor: { + valType: 'color', + + arrayOk: true, + editType: 'none', + + }, + font: fontAttrs({ + arrayOk: true, + editType: 'none', + + }), + namelength: { + valType: 'integer', + min: -1, + arrayOk: true, + + editType: 'none', + + }, + editType: 'calc' + } +}; + +},{"../../plots/font_attributes":771}],605:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); + +module.exports = function calc(gd) { + var calcdata = gd.calcdata; + var fullLayout = gd._fullLayout; + + function makeCoerceHoverInfo(trace) { + return function(val) { + return Lib.coerceHoverinfo({hoverinfo: val}, {_module: trace._module}, fullLayout); + }; + } + + for(var i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var trace = cd[0].trace; + + // don't include hover calc fields for pie traces + // as calcdata items might be sorted by value and + // won't match the data array order. + if(Registry.traceIs(trace, 'pie')) continue; + + var fillFn = Registry.traceIs(trace, '2dMap') ? paste : Lib.fillArray; + + fillFn(trace.hoverinfo, cd, 'hi', makeCoerceHoverInfo(trace)); + + if(!trace.hoverlabel) continue; + + fillFn(trace.hoverlabel.bgcolor, cd, 'hbg'); + fillFn(trace.hoverlabel.bordercolor, cd, 'hbc'); + fillFn(trace.hoverlabel.font.size, cd, 'hts'); + fillFn(trace.hoverlabel.font.color, cd, 'htc'); + fillFn(trace.hoverlabel.font.family, cd, 'htf'); + fillFn(trace.hoverlabel.namelength, cd, 'hnl'); + } +}; + +function paste(traceAttr, cd, cdAttr, fn) { + fn = fn || Lib.identity; + + if(Array.isArray(traceAttr)) { + cd[0][cdAttr] = fn(traceAttr); + } +} + +},{"../../lib":696,"../../registry":827}],606:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var hover = _dereq_('./hover').hover; + +module.exports = function click(gd, evt, subplot) { + var annotationsDone = Registry.getComponentMethod('annotations', 'onClick')(gd, gd._hoverdata); + + // fallback to fail-safe in case the plot type's hover method doesn't pass the subplot. + // Ternary, for example, didn't, but it was caught because tested. + if(subplot !== undefined) { + // The true flag at the end causes it to re-run the hover computation to figure out *which* + // point is being clicked. Without this, clicking is somewhat unreliable. + hover(gd, evt, subplot, true); + } + + function emitClick() { gd.emit('plotly_click', {points: gd._hoverdata, event: evt}); } + + if(gd._hoverdata && evt && evt.target) { + if(annotationsDone && annotationsDone.then) { + annotationsDone.then(emitClick); + } + else emitClick(); + + // why do we get a double event without this??? + if(evt.stopImmediatePropagation) evt.stopImmediatePropagation(); + } +}; + +},{"../../registry":827,"./hover":610}],607:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + // hover labels for multiple horizontal bars get tilted by this angle + YANGLE: 60, + + // size and display constants for hover text + + // pixel size of hover arrows + HOVERARROWSIZE: 6, + // pixels padding around text + HOVERTEXTPAD: 3, + // hover font + HOVERFONTSIZE: 13, + HOVERFONT: 'Arial, sans-serif', + + // minimum time (msec) between hover calls + HOVERMINTIME: 50, + + // ID suffix (with fullLayout._uid) for hover events in the throttle cache + HOVERID: '-hover' +}; + +},{}],608:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attributes = _dereq_('./attributes'); +var handleHoverLabelDefaults = _dereq_('./hoverlabel_defaults'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + handleHoverLabelDefaults(traceIn, traceOut, coerce, layout.hoverlabel); +}; + +},{"../../lib":696,"./attributes":604,"./hoverlabel_defaults":611}],609:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +// look for either subplot or xaxis and yaxis attributes +// does not handle splom case +exports.getSubplot = function getSubplot(trace) { + return trace.subplot || (trace.xaxis + trace.yaxis) || trace.geo; +}; + +// is trace in given list of subplots? +// does handle splom case +exports.isTraceInSubplots = function isTraceInSubplot(trace, subplots) { + if(trace.type === 'splom') { + var xaxes = trace.xaxes || []; + var yaxes = trace.yaxes || []; + for(var i = 0; i < xaxes.length; i++) { + for(var j = 0; j < yaxes.length; j++) { + if(subplots.indexOf(xaxes[i] + yaxes[j]) !== -1) { + return true; + } + } + } + return false; + } + + return subplots.indexOf(exports.getSubplot(trace)) !== -1; +}; + +// convenience functions for mapping all relevant axes +exports.flat = function flat(subplots, v) { + var out = new Array(subplots.length); + for(var i = 0; i < subplots.length; i++) { + out[i] = v; + } + return out; +}; + +exports.p2c = function p2c(axArray, v) { + var out = new Array(axArray.length); + for(var i = 0; i < axArray.length; i++) { + out[i] = axArray[i].p2c(v); + } + return out; +}; + +exports.getDistanceFunction = function getDistanceFunction(mode, dx, dy, dxy) { + if(mode === 'closest') return dxy || exports.quadrature(dx, dy); + return mode === 'x' ? dx : dy; +}; + +exports.getClosest = function getClosest(cd, distfn, pointData) { + // do we already have a point number? (array mode only) + if(pointData.index !== false) { + if(pointData.index >= 0 && pointData.index < cd.length) { + pointData.distance = 0; + } + else pointData.index = false; + } + else { + // apply the distance function to each data point + // this is the longest loop... if this bogs down, we may need + // to create pre-sorted data (by x or y), not sure how to + // do this for 'closest' + for(var i = 0; i < cd.length; i++) { + var newDistance = distfn(cd[i]); + if(newDistance <= pointData.distance) { + pointData.index = i; + pointData.distance = newDistance; + } + } + } + return pointData; +}; + +/* + * pseudo-distance function for hover effects on areas: inside the region + * distance is finite (`passVal`), outside it's Infinity. + * + * @param {number} v0: signed difference between the current position and the left edge + * @param {number} v1: signed difference between the current position and the right edge + * @param {number} passVal: the value to return on success + */ +exports.inbox = function inbox(v0, v1, passVal) { + return (v0 * v1 < 0 || v0 === 0) ? passVal : Infinity; +}; + +exports.quadrature = function quadrature(dx, dy) { + return function(di) { + var x = dx(di), + y = dy(di); + return Math.sqrt(x * x + y * y); + }; +}; + +/** Fill event data point object for hover and selection. + * Invokes _module.eventData if present. + * + * N.B. note that point 'index' corresponds to input data array index + * whereas 'number' is its post-transform version. + * + * If the hovered/selected pt corresponds to an multiple input points + * (e.g. for histogram and transformed traces), 'pointNumbers` and 'pointIndices' + * are include in the event data. + * + * @param {object} pt + * @param {object} trace + * @param {object} cd + * @return {object} + */ +exports.makeEventData = function makeEventData(pt, trace, cd) { + // hover uses 'index', select uses 'pointNumber' + var pointNumber = 'index' in pt ? pt.index : pt.pointNumber; + + var out = { + data: trace._input, + fullData: trace, + curveNumber: trace.index, + pointNumber: pointNumber + }; + + if(trace._indexToPoints) { + var pointIndices = trace._indexToPoints[pointNumber]; + + if(pointIndices.length === 1) { + out.pointIndex = pointIndices[0]; + } else { + out.pointIndices = pointIndices; + } + } else { + out.pointIndex = pointNumber; + } + + if(trace._module.eventData) { + out = trace._module.eventData(out, pt, trace, cd, pointNumber); + } else { + if('xVal' in pt) out.x = pt.xVal; + else if('x' in pt) out.x = pt.x; + + if('yVal' in pt) out.y = pt.yVal; + else if('y' in pt) out.y = pt.y; + + if(pt.xa) out.xaxis = pt.xa; + if(pt.ya) out.yaxis = pt.ya; + if(pt.zLabelVal !== undefined) out.z = pt.zLabelVal; + } + + exports.appendArrayPointValue(out, trace, pointNumber); + + return out; +}; + +/** Appends values inside array attributes corresponding to given point number + * + * @param {object} pointData : point data object (gets mutated here) + * @param {object} trace : full trace object + * @param {number|Array(number)} pointNumber : point number. May be a length-2 array + * [row, col] to dig into 2D arrays + */ +exports.appendArrayPointValue = function(pointData, trace, pointNumber) { + var arrayAttrs = trace._arrayAttrs; + + if(!arrayAttrs) { + return; + } + + for(var i = 0; i < arrayAttrs.length; i++) { + var astr = arrayAttrs[i]; + var key = getPointKey(astr); + + if(pointData[key] === undefined) { + var val = Lib.nestedProperty(trace, astr).get(); + var pointVal = getPointData(val, pointNumber); + + if(pointVal !== undefined) pointData[key] = pointVal; + } + } +}; + +/** + * Appends values inside array attributes corresponding to given point number array + * For use when pointData references a plot entity that arose (or potentially arose) + * from multiple points in the input data + * + * @param {object} pointData : point data object (gets mutated here) + * @param {object} trace : full trace object + * @param {Array(number)|Array(Array(number))} pointNumbers : Array of point numbers. + * Each entry in the array may itself be a length-2 array [row, col] to dig into 2D arrays + */ +exports.appendArrayMultiPointValues = function(pointData, trace, pointNumbers) { + var arrayAttrs = trace._arrayAttrs; + + if(!arrayAttrs) { + return; + } + + for(var i = 0; i < arrayAttrs.length; i++) { + var astr = arrayAttrs[i]; + var key = getPointKey(astr); + + if(pointData[key] === undefined) { + var val = Lib.nestedProperty(trace, astr).get(); + var keyVal = new Array(pointNumbers.length); + + for(var j = 0; j < pointNumbers.length; j++) { + keyVal[j] = getPointData(val, pointNumbers[j]); + } + pointData[key] = keyVal; + } + } +}; + +var pointKeyMap = { + ids: 'id', + locations: 'location', + labels: 'label', + values: 'value', + 'marker.colors': 'color' +}; + +function getPointKey(astr) { + return pointKeyMap[astr] || astr; +} + +function getPointData(val, pointNumber) { + if(Array.isArray(pointNumber)) { + if(Array.isArray(val) && Array.isArray(val[pointNumber[0]])) { + return val[pointNumber[0]][pointNumber[1]]; + } + } else { + return val[pointNumber]; + } +} + +},{"../../lib":696}],610:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); +var tinycolor = _dereq_('tinycolor2'); + +var Lib = _dereq_('../../lib'); +var Events = _dereq_('../../lib/events'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var overrideCursor = _dereq_('../../lib/override_cursor'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); +var dragElement = _dereq_('../dragelement'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Registry = _dereq_('../../registry'); + +var helpers = _dereq_('./helpers'); +var constants = _dereq_('./constants'); + +// hover labels for multiple horizontal bars get tilted by some angle, +// then need to be offset differently if they overlap +var YANGLE = constants.YANGLE; +var YA_RADIANS = Math.PI * YANGLE / 180; + +// expansion of projected height +var YFACTOR = 1 / Math.sin(YA_RADIANS); + +// to make the appropriate post-rotation x offset, +// you need both x and y offsets +var YSHIFTX = Math.cos(YA_RADIANS); +var YSHIFTY = Math.sin(YA_RADIANS); + +// size and display constants for hover text +var HOVERARROWSIZE = constants.HOVERARROWSIZE; +var HOVERTEXTPAD = constants.HOVERTEXTPAD; + +// fx.hover: highlight data on hover +// evt can be a mousemove event, or an object with data about what points +// to hover on +// {xpx,ypx[,hovermode]} - pixel locations from top left +// (with optional overriding hovermode) +// {xval,yval[,hovermode]} - data values +// [{curveNumber,(pointNumber|xval and/or yval)}] - +// array of specific points to highlight +// pointNumber is a single integer if gd.data[curveNumber] is 1D, +// or a two-element array if it's 2D +// xval and yval are data values, +// 1D data may specify either or both, +// 2D data must specify both +// subplot is an id string (default "xy") +// makes use of gl.hovermode, which can be: +// x (find the points with the closest x values, ie a column), +// closest (find the single closest point) +// internally there are two more that occasionally get used: +// y (pick out a row - only used for multiple horizontal bar charts) +// array (used when the user specifies an explicit +// array of points to hover on) +// +// We wrap the hovers in a timer, to limit their frequency. +// The actual rendering is done by private function _hover. +exports.hover = function hover(gd, evt, subplot, noHoverEvent) { + gd = Lib.getGraphDiv(gd); + + Lib.throttle( + gd._fullLayout._uid + constants.HOVERID, + constants.HOVERMINTIME, + function() { _hover(gd, evt, subplot, noHoverEvent); } + ); +}; + +/* + * Draw a single hover item in a pre-existing svg container somewhere + * hoverItem should have keys: + * - x and y (or x0, x1, y0, and y1): + * the pixel position to mark, relative to opts.container + * - xLabel, yLabel, zLabel, text, and name: + * info to go in the label + * - color: + * the background color for the label. + * - idealAlign (optional): + * 'left' or 'right' for which side of the x/y box to try to put this on first + * - borderColor (optional): + * color for the border, defaults to strongest contrast with color + * - fontFamily (optional): + * string, the font for this label, defaults to constants.HOVERFONT + * - fontSize (optional): + * the label font size, defaults to constants.HOVERFONTSIZE + * - fontColor (optional): + * defaults to borderColor + * opts should have keys: + * - bgColor: + * the background color this is against, used if the trace is + * non-opaque, and for the name, which goes outside the box + * - container: + * a or element to add the hover label to + * - outerContainer: + * normally a parent of `container`, sets the bounding box to use to + * constrain the hover label and determine whether to show it on the left or right + */ +exports.loneHover = function loneHover(hoverItem, opts) { + var pointData = { + color: hoverItem.color || Color.defaultLine, + x0: hoverItem.x0 || hoverItem.x || 0, + x1: hoverItem.x1 || hoverItem.x || 0, + y0: hoverItem.y0 || hoverItem.y || 0, + y1: hoverItem.y1 || hoverItem.y || 0, + xLabel: hoverItem.xLabel, + yLabel: hoverItem.yLabel, + zLabel: hoverItem.zLabel, + text: hoverItem.text, + name: hoverItem.name, + idealAlign: hoverItem.idealAlign, + + // optional extra bits of styling + borderColor: hoverItem.borderColor, + fontFamily: hoverItem.fontFamily, + fontSize: hoverItem.fontSize, + fontColor: hoverItem.fontColor, + + // filler to make createHoverText happy + trace: { + index: 0, + hoverinfo: '' + }, + xa: {_offset: 0}, + ya: {_offset: 0}, + index: 0 + }; + + var container3 = d3.select(opts.container); + var outerContainer3 = opts.outerContainer ? + d3.select(opts.outerContainer) : container3; + + var fullOpts = { + hovermode: 'closest', + rotateLabels: false, + bgColor: opts.bgColor || Color.background, + container: container3, + outerContainer: outerContainer3 + }; + + var hoverLabel = createHoverText([pointData], fullOpts, opts.gd); + alignHoverText(hoverLabel, fullOpts.rotateLabels); + + return hoverLabel.node(); +}; + +exports.multiHovers = function multiHovers(hoverItems, opts) { + + if(!Array.isArray(hoverItems)) { + hoverItems = [hoverItems]; + } + + var pointsData = hoverItems.map(function(hoverItem) { + return { + color: hoverItem.color || Color.defaultLine, + x0: hoverItem.x0 || hoverItem.x || 0, + x1: hoverItem.x1 || hoverItem.x || 0, + y0: hoverItem.y0 || hoverItem.y || 0, + y1: hoverItem.y1 || hoverItem.y || 0, + xLabel: hoverItem.xLabel, + yLabel: hoverItem.yLabel, + zLabel: hoverItem.zLabel, + text: hoverItem.text, + name: hoverItem.name, + idealAlign: hoverItem.idealAlign, + + // optional extra bits of styling + borderColor: hoverItem.borderColor, + fontFamily: hoverItem.fontFamily, + fontSize: hoverItem.fontSize, + fontColor: hoverItem.fontColor, + + // filler to make createHoverText happy + trace: { + index: 0, + hoverinfo: '' + }, + xa: {_offset: 0}, + ya: {_offset: 0}, + index: 0 + }; + }); + + + var container3 = d3.select(opts.container), + outerContainer3 = opts.outerContainer ? + d3.select(opts.outerContainer) : container3; + + var fullOpts = { + hovermode: 'closest', + rotateLabels: false, + bgColor: opts.bgColor || Color.background, + container: container3, + outerContainer: outerContainer3 + }; + + var hoverLabel = createHoverText(pointsData, fullOpts, opts.gd); + + // Fix vertical overlap + var tooltipSpacing = 5; + var lastBottomY = 0; + hoverLabel + .sort(function(a, b) {return a.y0 - b.y0;}) + .each(function(d) { + var topY = d.y0 - d.by / 2; + + if((topY - tooltipSpacing) < lastBottomY) { + d.offset = (lastBottomY - topY) + tooltipSpacing; + } else { + d.offset = 0; + } + + lastBottomY = topY + d.by + d.offset; + }); + + + alignHoverText(hoverLabel, fullOpts.rotateLabels); + + return hoverLabel.node(); +}; + +// The actual implementation is here: +function _hover(gd, evt, subplot, noHoverEvent) { + if(!subplot) subplot = 'xy'; + + // if the user passed in an array of subplots, + // use those instead of finding overlayed plots + var subplots = Array.isArray(subplot) ? subplot : [subplot]; + + var fullLayout = gd._fullLayout; + var plots = fullLayout._plots || []; + var plotinfo = plots[subplot]; + var hasCartesian = fullLayout._has('cartesian'); + + // list of all overlaid subplots to look at + if(plotinfo) { + var overlayedSubplots = plotinfo.overlays.map(function(pi) { + return pi.id; + }); + + subplots = subplots.concat(overlayedSubplots); + } + + var len = subplots.length; + var xaArray = new Array(len); + var yaArray = new Array(len); + var supportsCompare = false; + + for(var i = 0; i < len; i++) { + var spId = subplots[i]; + + // 'cartesian' case + var plotObj = plots[spId]; + if(plotObj) { + supportsCompare = true; + + // TODO make sure that fullLayout_plots axis refs + // get updated properly so that we don't have + // to use Axes.getFromId in general. + + xaArray[i] = Axes.getFromId(gd, plotObj.xaxis._id); + yaArray[i] = Axes.getFromId(gd, plotObj.yaxis._id); + continue; + } + + // other subplot types + var _subplot = fullLayout[spId]._subplot; + xaArray[i] = _subplot.xaxis; + yaArray[i] = _subplot.yaxis; + } + + var hovermode = evt.hovermode || fullLayout.hovermode; + + if(hovermode && !supportsCompare) hovermode = 'closest'; + + if(['x', 'y', 'closest'].indexOf(hovermode) === -1 || !gd.calcdata || + gd.querySelector('.zoombox') || gd._dragging) { + return dragElement.unhoverRaw(gd, evt); + } + + var hoverdistance = fullLayout.hoverdistance === -1 ? Infinity : fullLayout.hoverdistance; + var spikedistance = fullLayout.spikedistance === -1 ? Infinity : fullLayout.spikedistance; + + // hoverData: the set of candidate points we've found to highlight + var hoverData = []; + + // searchData: the data to search in. Mostly this is just a copy of + // gd.calcdata, filtered to the subplot and overlays we're on + // but if a point array is supplied it will be a mapping + // of indicated curves + var searchData = []; + + // [x|y]valArray: the axis values of the hover event + // mapped onto each of the currently selected overlaid subplots + var xvalArray, yvalArray; + + var itemnum, curvenum, cd, trace, subplotId, subploti, mode, + xval, yval, pointData, closedataPreviousLength; + + // spikePoints: the set of candidate points we've found to draw spikes to + var spikePoints = { + hLinePoint: null, + vLinePoint: null + }; + + // does subplot have one (or more) horizontal traces? + // This is used to determine whether we rotate the labels or not + var hasOneHorizontalTrace = false; + + // Figure out what we're hovering on: + // mouse location or user-supplied data + + if(Array.isArray(evt)) { + // user specified an array of points to highlight + hovermode = 'array'; + for(itemnum = 0; itemnum < evt.length; itemnum++) { + cd = gd.calcdata[evt[itemnum].curveNumber||0]; + trace = cd[0].trace; + if(cd[0].trace.hoverinfo !== 'skip') { + searchData.push(cd); + if(trace.orientation === 'h') { + hasOneHorizontalTrace = true; + } + } + } + } + else { + for(curvenum = 0; curvenum < gd.calcdata.length; curvenum++) { + cd = gd.calcdata[curvenum]; + trace = cd[0].trace; + if(trace.hoverinfo !== 'skip' && helpers.isTraceInSubplots(trace, subplots)) { + searchData.push(cd); + if(trace.orientation === 'h') { + hasOneHorizontalTrace = true; + } + } + } + + // [x|y]px: the pixels (from top left) of the mouse location + // on the currently selected plot area + // add pointerX|Y property for drawing the spikes in spikesnap 'cursor' situation + var hasUserCalledHover = !evt.target; + var xpx, ypx; + + if(hasUserCalledHover) { + if('xpx' in evt) xpx = evt.xpx; + else xpx = xaArray[0]._length / 2; + + if('ypx' in evt) ypx = evt.ypx; + else ypx = yaArray[0]._length / 2; + } + else { + // fire the beforehover event and quit if it returns false + // note that we're only calling this on real mouse events, so + // manual calls to fx.hover will always run. + if(Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { + return; + } + + var dbb = evt.target.getBoundingClientRect(); + + xpx = evt.clientX - dbb.left; + ypx = evt.clientY - dbb.top; + + // in case hover was called from mouseout into hovertext, + // it's possible you're not actually over the plot anymore + if(xpx < 0 || xpx > xaArray[0]._length || ypx < 0 || ypx > yaArray[0]._length) { + return dragElement.unhoverRaw(gd, evt); + } + } + + evt.pointerX = xpx + xaArray[0]._offset; + evt.pointerY = ypx + yaArray[0]._offset; + + if('xval' in evt) xvalArray = helpers.flat(subplots, evt.xval); + else xvalArray = helpers.p2c(xaArray, xpx); + + if('yval' in evt) yvalArray = helpers.flat(subplots, evt.yval); + else yvalArray = helpers.p2c(yaArray, ypx); + + if(!isNumeric(xvalArray[0]) || !isNumeric(yvalArray[0])) { + Lib.warn('Fx.hover failed', evt, gd); + return dragElement.unhoverRaw(gd, evt); + } + } + + // the pixel distance to beat as a matching point + // in 'x' or 'y' mode this resets for each trace + var distance = Infinity; + + // find the closest point in each trace + // this is minimum dx and/or dy, depending on mode + // and the pixel position for the label (labelXpx, labelYpx) + for(curvenum = 0; curvenum < searchData.length; curvenum++) { + cd = searchData[curvenum]; + + // filter out invisible or broken data + if(!cd || !cd[0] || !cd[0].trace || cd[0].trace.visible !== true) continue; + + trace = cd[0].trace; + + // Explicitly bail out for these two. I don't know how to otherwise prevent + // the rest of this function from running and failing + if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue; + + if(trace.type === 'splom') { + // splom traces do not generate overlay subplots, + // it is safe to assume here splom traces correspond to the 0th subplot + subploti = 0; + subplotId = subplots[subploti]; + } else { + subplotId = helpers.getSubplot(trace); + subploti = subplots.indexOf(subplotId); + } + + // within one trace mode can sometimes be overridden + mode = hovermode; + + // container for new point, also used to pass info into module.hoverPoints + pointData = { + // trace properties + cd: cd, + trace: trace, + xa: xaArray[subploti], + ya: yaArray[subploti], + + // max distances for hover and spikes - for points that want to show but do not + // want to override other points, set distance/spikeDistance equal to max*Distance + // and it will not get filtered out but it will be guaranteed to have a greater + // distance than any point that calculated a real distance. + maxHoverDistance: hoverdistance, + maxSpikeDistance: spikedistance, + + // point properties - override all of these + index: false, // point index in trace - only used by plotly.js hoverdata consumers + distance: Math.min(distance, hoverdistance), // pixel distance or pseudo-distance + + // distance/pseudo-distance for spikes. This distance should always be calculated + // as if in "closest" mode, and should only be set if this point should + // generate a spike. + spikeDistance: Infinity, + + // in some cases the spikes have different positioning from the hover label + // they don't need x0/x1, just one position + xSpike: undefined, + ySpike: undefined, + + // where and how to display the hover label + color: Color.defaultLine, // trace color + name: trace.name, + x0: undefined, + x1: undefined, + y0: undefined, + y1: undefined, + xLabelVal: undefined, + yLabelVal: undefined, + zLabelVal: undefined, + text: undefined + }; + + // add ref to subplot object (non-cartesian case) + if(fullLayout[subplotId]) { + pointData.subplot = fullLayout[subplotId]._subplot; + } + // add ref to splom scene + if(fullLayout._splomScenes && fullLayout._splomScenes[trace.uid]) { + pointData.scene = fullLayout._splomScenes[trace.uid]; + } + + closedataPreviousLength = hoverData.length; + + // for a highlighting array, figure out what + // we're searching for with this element + if(mode === 'array') { + var selection = evt[curvenum]; + if('pointNumber' in selection) { + pointData.index = selection.pointNumber; + mode = 'closest'; + } + else { + mode = ''; + if('xval' in selection) { + xval = selection.xval; + mode = 'x'; + } + if('yval' in selection) { + yval = selection.yval; + mode = mode ? 'closest' : 'y'; + } + } + } + else { + xval = xvalArray[subploti]; + yval = yvalArray[subploti]; + } + + // Now if there is range to look in, find the points to hover. + if(hoverdistance !== 0) { + if(trace._module && trace._module.hoverPoints) { + var newPoints = trace._module.hoverPoints(pointData, xval, yval, mode, fullLayout._hoverlayer); + if(newPoints) { + var newPoint; + for(var newPointNum = 0; newPointNum < newPoints.length; newPointNum++) { + newPoint = newPoints[newPointNum]; + if(isNumeric(newPoint.x0) && isNumeric(newPoint.y0)) { + hoverData.push(cleanPoint(newPoint, hovermode)); + } + } + } + } + else { + Lib.log('Unrecognized trace type in hover:', trace); + } + } + + // in closest mode, remove any existing (farther) points + // and don't look any farther than this latest point (or points, some + // traces like box & violin make multiple hover labels at once) + if(hovermode === 'closest' && hoverData.length > closedataPreviousLength) { + hoverData.splice(0, closedataPreviousLength); + distance = hoverData[0].distance; + } + + // Now if there is range to look in, find the points to draw the spikelines + // Do it only if there is no hoverData + if(hasCartesian && (spikedistance !== 0)) { + if(hoverData.length === 0) { + pointData.distance = spikedistance; + pointData.index = false; + var closestPoints = trace._module.hoverPoints(pointData, xval, yval, 'closest', fullLayout._hoverlayer); + if(closestPoints) { + closestPoints = closestPoints.filter(function(point) { + // some hover points, like scatter fills, do not allow spikes, + // so will generate a hover point but without a valid spikeDistance + return point.spikeDistance <= spikedistance; + }); + } + if(closestPoints && closestPoints.length) { + var tmpPoint; + var closestVPoints = closestPoints.filter(function(point) { + return point.xa.showspikes; + }); + if(closestVPoints.length) { + var closestVPt = closestVPoints[0]; + if(isNumeric(closestVPt.x0) && isNumeric(closestVPt.y0)) { + tmpPoint = fillSpikePoint(closestVPt); + if(!spikePoints.vLinePoint || (spikePoints.vLinePoint.spikeDistance > tmpPoint.spikeDistance)) { + spikePoints.vLinePoint = tmpPoint; + } + } + } + + var closestHPoints = closestPoints.filter(function(point) { + return point.ya.showspikes; + }); + if(closestHPoints.length) { + var closestHPt = closestHPoints[0]; + if(isNumeric(closestHPt.x0) && isNumeric(closestHPt.y0)) { + tmpPoint = fillSpikePoint(closestHPt); + if(!spikePoints.hLinePoint || (spikePoints.hLinePoint.spikeDistance > tmpPoint.spikeDistance)) { + spikePoints.hLinePoint = tmpPoint; + } + } + } + } + } + } + } + + function selectClosestPoint(pointsData, spikedistance) { + var resultPoint = null; + var minDistance = Infinity; + var thisSpikeDistance; + for(var i = 0; i < pointsData.length; i++) { + thisSpikeDistance = pointsData[i].spikeDistance; + if(thisSpikeDistance < minDistance && thisSpikeDistance <= spikedistance) { + resultPoint = pointsData[i]; + minDistance = thisSpikeDistance; + } + } + return resultPoint; + } + + function fillSpikePoint(point) { + if(!point) return null; + return { + xa: point.xa, + ya: point.ya, + x: point.xSpike !== undefined ? point.xSpike : (point.x0 + point.x1) / 2, + y: point.ySpike !== undefined ? point.ySpike : (point.y0 + point.y1) / 2, + distance: point.distance, + spikeDistance: point.spikeDistance, + curveNumber: point.trace.index, + color: point.color, + pointNumber: point.index + }; + } + + var spikelineOpts = { + fullLayout: fullLayout, + container: fullLayout._hoverlayer, + outerContainer: fullLayout._paperdiv, + event: evt + }; + var oldspikepoints = gd._spikepoints, + newspikepoints = { + vLinePoint: spikePoints.vLinePoint, + hLinePoint: spikePoints.hLinePoint + }; + gd._spikepoints = newspikepoints; + + // Now if it is not restricted by spikedistance option, set the points to draw the spikelines + if(hasCartesian && (spikedistance !== 0)) { + if(hoverData.length !== 0) { + var tmpHPointData = hoverData.filter(function(point) { + return point.ya.showspikes; + }); + var tmpHPoint = selectClosestPoint(tmpHPointData, spikedistance); + spikePoints.hLinePoint = fillSpikePoint(tmpHPoint); + + var tmpVPointData = hoverData.filter(function(point) { + return point.xa.showspikes; + }); + var tmpVPoint = selectClosestPoint(tmpVPointData, spikedistance); + spikePoints.vLinePoint = fillSpikePoint(tmpVPoint); + } + } + + // if hoverData is empty check for the spikes to draw and quit if there are none + if(hoverData.length === 0) { + var result = dragElement.unhoverRaw(gd, evt); + if(hasCartesian && ((spikePoints.hLinePoint !== null) || (spikePoints.vLinePoint !== null))) { + if(spikesChanged(oldspikepoints)) { + createSpikelines(spikePoints, spikelineOpts); + } + } + return result; + } + + if(hasCartesian) { + if(spikesChanged(oldspikepoints)) { + createSpikelines(spikePoints, spikelineOpts); + } + } + + hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; }); + + // lastly, emit custom hover/unhover events + var oldhoverdata = gd._hoverdata; + var newhoverdata = []; + + // pull out just the data that's useful to + // other people and send it to the event + for(itemnum = 0; itemnum < hoverData.length; itemnum++) { + var pt = hoverData[itemnum]; + newhoverdata.push(helpers.makeEventData(pt, pt.trace, pt.cd)); + } + + gd._hoverdata = newhoverdata; + + var rotateLabels = ( + (hovermode === 'y' && (searchData.length > 1 || hoverData.length > 1)) || + (hovermode === 'closest' && hasOneHorizontalTrace && hoverData.length > 1) + ); + + var bgColor = Color.combine( + fullLayout.plot_bgcolor || Color.background, + fullLayout.paper_bgcolor + ); + + var labelOpts = { + hovermode: hovermode, + rotateLabels: rotateLabels, + bgColor: bgColor, + container: fullLayout._hoverlayer, + outerContainer: fullLayout._paperdiv, + commonLabelOpts: fullLayout.hoverlabel, + hoverdistance: fullLayout.hoverdistance + }; + + var hoverLabels = createHoverText(hoverData, labelOpts, gd); + + hoverAvoidOverlaps(hoverData, rotateLabels ? 'xa' : 'ya', fullLayout); + + alignHoverText(hoverLabels, rotateLabels); + + // TODO: tagName hack is needed to appease geo.js's hack of using evt.target=true + // we should improve the "fx" API so other plots can use it without these hack. + if(evt.target && evt.target.tagName) { + var hasClickToShow = Registry.getComponentMethod('annotations', 'hasClickToShow')(gd, newhoverdata); + overrideCursor(d3.select(evt.target), hasClickToShow ? 'pointer' : ''); + } + + // don't emit events if called manually + if(!evt.target || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return; + + if(oldhoverdata) { + gd.emit('plotly_unhover', { + event: evt, + points: oldhoverdata + }); + } + + gd.emit('plotly_hover', { + event: evt, + points: gd._hoverdata, + xaxes: xaArray, + yaxes: yaArray, + xvals: xvalArray, + yvals: yvalArray + }); +} + +function createHoverText(hoverData, opts, gd) { + var hovermode = opts.hovermode; + var rotateLabels = opts.rotateLabels; + var bgColor = opts.bgColor; + var container = opts.container; + var outerContainer = opts.outerContainer; + var commonLabelOpts = opts.commonLabelOpts || {}; + + // opts.fontFamily/Size are used for the common label + // and as defaults for each hover label, though the individual labels + // can override this. + var fontFamily = opts.fontFamily || constants.HOVERFONT; + var fontSize = opts.fontSize || constants.HOVERFONTSIZE; + + var c0 = hoverData[0]; + var xa = c0.xa; + var ya = c0.ya; + var commonAttr = hovermode === 'y' ? 'yLabel' : 'xLabel'; + var t0 = c0[commonAttr]; + var t00 = (String(t0) || '').split(' ')[0]; + var outerContainerBB = outerContainer.node().getBoundingClientRect(); + var outerTop = outerContainerBB.top; + var outerWidth = outerContainerBB.width; + var outerHeight = outerContainerBB.height; + + // show the common label, if any, on the axis + // never show a common label in array mode, + // even if sometimes there could be one + var showCommonLabel = ( + (t0 !== undefined) && + (c0.distance <= opts.hoverdistance) && + (hovermode === 'x' || hovermode === 'y') + ); + + // all hover traces hoverinfo must contain the hovermode + // to have common labels + if(showCommonLabel) { + var allHaveZ = true; + var i, traceHoverinfo; + for(i = 0; i < hoverData.length; i++) { + if(allHaveZ && hoverData[i].zLabel === undefined) allHaveZ = false; + + traceHoverinfo = hoverData[i].hoverinfo || hoverData[i].trace.hoverinfo; + var parts = Array.isArray(traceHoverinfo) ? traceHoverinfo : traceHoverinfo.split('+'); + if(parts.indexOf('all') === -1 && + parts.indexOf(hovermode) === -1) { + showCommonLabel = false; + break; + } + } + + // xyz labels put all info in their main label, so have no need of a common label + if(allHaveZ) showCommonLabel = false; + } + + var commonLabel = container.selectAll('g.axistext') + .data(showCommonLabel ? [0] : []); + commonLabel.enter().append('g') + .classed('axistext', true); + commonLabel.exit().remove(); + + commonLabel.each(function() { + var label = d3.select(this); + var lpath = Lib.ensureSingle(label, 'path', '', function(s) { + s.style({'stroke-width': '1px'}); + }); + var ltext = Lib.ensureSingle(label, 'text', '', function(s) { + // prohibit tex interpretation until we can handle + // tex and regular text together + s.attr('data-notex', 1); + }); + + var commonBgColor = commonLabelOpts.bgcolor || Color.defaultLine; + var commonStroke = commonLabelOpts.bordercolor || Color.contrast(commonBgColor); + var contrastColor = Color.contrast(commonBgColor); + + lpath.style({ + fill: commonBgColor, + stroke: commonStroke + }); + + ltext.text(t0) + .call(Drawing.font, + commonLabelOpts.font.family || fontFamily, + commonLabelOpts.font.size || fontSize, + commonLabelOpts.font.color || contrastColor + ) + .call(svgTextUtils.positionText, 0, 0) + .call(svgTextUtils.convertToTspans, gd); + + label.attr('transform', ''); + + var tbb = ltext.node().getBoundingClientRect(); + if(hovermode === 'x') { + ltext.attr('text-anchor', 'middle') + .call(svgTextUtils.positionText, 0, (xa.side === 'top' ? + (outerTop - tbb.bottom - HOVERARROWSIZE - HOVERTEXTPAD) : + (outerTop - tbb.top + HOVERARROWSIZE + HOVERTEXTPAD))); + + var topsign = xa.side === 'top' ? '-' : ''; + lpath.attr('d', 'M0,0' + + 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE + + 'H' + (HOVERTEXTPAD + tbb.width / 2) + + 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) + + 'H-' + (HOVERTEXTPAD + tbb.width / 2) + + 'V' + topsign + HOVERARROWSIZE + 'H-' + HOVERARROWSIZE + 'Z'); + + label.attr('transform', 'translate(' + + (xa._offset + (c0.x0 + c0.x1) / 2) + ',' + + (ya._offset + (xa.side === 'top' ? 0 : ya._length)) + ')'); + } + else { + ltext.attr('text-anchor', ya.side === 'right' ? 'start' : 'end') + .call(svgTextUtils.positionText, + (ya.side === 'right' ? 1 : -1) * (HOVERTEXTPAD + HOVERARROWSIZE), + outerTop - tbb.top - tbb.height / 2); + + var leftsign = ya.side === 'right' ? '' : '-'; + lpath.attr('d', 'M0,0' + + 'L' + leftsign + HOVERARROWSIZE + ',' + HOVERARROWSIZE + + 'V' + (HOVERTEXTPAD + tbb.height / 2) + + 'h' + leftsign + (HOVERTEXTPAD * 2 + tbb.width) + + 'V-' + (HOVERTEXTPAD + tbb.height / 2) + + 'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z'); + + label.attr('transform', 'translate(' + + (xa._offset + (ya.side === 'right' ? xa._length : 0)) + ',' + + (ya._offset + (c0.y0 + c0.y1) / 2) + ')'); + } + // remove the "close but not quite" points + // because of error bars, only take up to a space + hoverData = hoverData.filter(function(d) { + return (d.zLabelVal !== undefined) || + (d[commonAttr] || '').split(' ')[0] === t00; + }); + }); + + // show all the individual labels + + // first create the objects + var hoverLabels = container.selectAll('g.hovertext') + .data(hoverData, function(d) { + return [d.trace.index, d.index, d.x0, d.y0, d.name, d.attr, d.xa, d.ya || ''].join(','); + }); + hoverLabels.enter().append('g') + .classed('hovertext', true) + .each(function() { + var g = d3.select(this); + // trace name label (rect and text.name) + g.append('rect') + .call(Color.fill, Color.addOpacity(bgColor, 0.8)); + g.append('text').classed('name', true); + // trace data label (path and text.nums) + g.append('path') + .style('stroke-width', '1px'); + g.append('text').classed('nums', true) + .call(Drawing.font, fontFamily, fontSize); + }); + hoverLabels.exit().remove(); + + // then put the text in, position the pointer to the data, + // and figure out sizes + hoverLabels.each(function(d) { + var g = d3.select(this).attr('transform', ''); + var name = ''; + var text = ''; + + // combine possible non-opaque trace color with bgColor + var color0 = d.bgcolor || d.color; + // color for 'nums' part of the label + var numsColor = Color.combine( + Color.opacity(color0) ? color0 : Color.defaultLine, + bgColor + ); + // color for 'name' part of the label + var nameColor = Color.combine( + Color.opacity(d.color) ? d.color : Color.defaultLine, + bgColor + ); + // find a contrasting color for border and text + var contrastColor = d.borderColor || Color.contrast(numsColor); + + // to get custom 'name' labels pass cleanPoint + if(d.nameOverride !== undefined) d.name = d.nameOverride; + + if(d.name) { + // strip out our pseudo-html elements from d.name (if it exists at all) + name = svgTextUtils.plainText(d.name || ''); + + var nameLength = Math.round(d.nameLength); + + if(nameLength > -1 && name.length > nameLength) { + if(nameLength > 3) name = name.substr(0, nameLength - 3) + '...'; + else name = name.substr(0, nameLength); + } + } + + if(d.zLabel !== undefined) { + if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
'; + if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
'; + text += (text ? 'z: ' : '') + d.zLabel; + } + else if(showCommonLabel && d[hovermode + 'Label'] === t0) { + text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || ''; + } + else if(d.xLabel === undefined) { + if(d.yLabel !== undefined) text = d.yLabel; + } + else if(d.yLabel === undefined) text = d.xLabel; + else text = '(' + d.xLabel + ', ' + d.yLabel + ')'; + + if((d.text || d.text === 0) && !Array.isArray(d.text)) { + text += (text ? '
' : '') + d.text; + } + + // used by other modules (initially just ternary) that + // manage their own hoverinfo independent of cleanPoint + // the rest of this will still apply, so such modules + // can still put things in (x|y|z)Label, text, and name + // and hoverinfo will still determine their visibility + if(d.extraText !== undefined) text += (text ? '
' : '') + d.extraText; + + // if 'text' is empty at this point, + // put 'name' in main label and don't show secondary label + if(text === '') { + // if 'name' is also empty, remove entire label + if(name === '') g.remove(); + text = name; + } + + // main label + var tx = g.select('text.nums') + .call(Drawing.font, + d.fontFamily || fontFamily, + d.fontSize || fontSize, + d.fontColor || contrastColor) + .text(text) + .attr('data-notex', 1) + .call(svgTextUtils.positionText, 0, 0) + .call(svgTextUtils.convertToTspans, gd); + + var tx2 = g.select('text.name'); + var tx2width = 0; + + // secondary label for non-empty 'name' + if(name && name !== text) { + tx2.call(Drawing.font, + d.fontFamily || fontFamily, + d.fontSize || fontSize, + nameColor) + .text(name) + .attr('data-notex', 1) + .call(svgTextUtils.positionText, 0, 0) + .call(svgTextUtils.convertToTspans, gd); + tx2width = tx2.node().getBoundingClientRect().width + 2 * HOVERTEXTPAD; + } + else { + tx2.remove(); + g.select('rect').remove(); + } + + g.select('path') + .style({ + fill: numsColor, + stroke: contrastColor + }); + var tbb = tx.node().getBoundingClientRect(); + var htx = d.xa._offset + (d.x0 + d.x1) / 2; + var hty = d.ya._offset + (d.y0 + d.y1) / 2; + var dx = Math.abs(d.x1 - d.x0); + var dy = Math.abs(d.y1 - d.y0); + var txTotalWidth = tbb.width + HOVERARROWSIZE + HOVERTEXTPAD + tx2width; + var anchorStartOK, anchorEndOK; + + d.ty0 = outerTop - tbb.top; + d.bx = tbb.width + 2 * HOVERTEXTPAD; + d.by = tbb.height + 2 * HOVERTEXTPAD; + d.anchor = 'start'; + d.txwidth = tbb.width; + d.tx2width = tx2width; + d.offset = 0; + + if(rotateLabels) { + d.pos = htx; + anchorStartOK = hty + dy / 2 + txTotalWidth <= outerHeight; + anchorEndOK = hty - dy / 2 - txTotalWidth >= 0; + if((d.idealAlign === 'top' || !anchorStartOK) && anchorEndOK) { + hty -= dy / 2; + d.anchor = 'end'; + } else if(anchorStartOK) { + hty += dy / 2; + d.anchor = 'start'; + } else d.anchor = 'middle'; + } + else { + d.pos = hty; + anchorStartOK = htx + dx / 2 + txTotalWidth <= outerWidth; + anchorEndOK = htx - dx / 2 - txTotalWidth >= 0; + if((d.idealAlign === 'left' || !anchorStartOK) && anchorEndOK) { + htx -= dx / 2; + d.anchor = 'end'; + } else if(anchorStartOK) { + htx += dx / 2; + d.anchor = 'start'; + } else d.anchor = 'middle'; + } + + tx.attr('text-anchor', d.anchor); + if(tx2width) tx2.attr('text-anchor', d.anchor); + g.attr('transform', 'translate(' + htx + ',' + hty + ')' + + (rotateLabels ? 'rotate(' + YANGLE + ')' : '')); + }); + + return hoverLabels; +} + +// Make groups of touching points, and within each group +// move each point so that no labels overlap, but the average +// label position is the same as it was before moving. Indicentally, +// this is equivalent to saying all the labels are on equal linear +// springs about their initial position. Initially, each point is +// its own group, but as we find overlaps we will clump the points. +// +// Also, there are hard constraints at the edges of the graphs, +// that push all groups to the middle so they are visible. I don't +// know what happens if the group spans all the way from one edge to +// the other, though it hardly matters - there's just too much +// information then. +function hoverAvoidOverlaps(hoverData, ax, fullLayout) { + var nummoves = 0; + + var axSign = 1; + + // make groups of touching points + var pointgroups = hoverData.map(function(d, i) { + var axis = d[ax]; + var axIsX = axis._id.charAt(0) === 'x'; + var rng = axis.range; + if(!i && rng && ((rng[0] > rng[1]) !== axIsX)) axSign = -1; + return [{ + i: i, + traceIndex: d.trace.index, + dp: 0, + pos: d.pos, + posref: d.posref, + size: d.by * (axIsX ? YFACTOR : 1) / 2, + pmin: 0, + pmax: (axIsX ? fullLayout.width : fullLayout.height) + }]; + }) + .sort(function(a, b) { + return (a[0].posref - b[0].posref) || + // for equal positions, sort trace indices increasing or decreasing + // depending on whether the axis is reversed or not... so stacked + // traces will generally keep their order even if one trace adds + // nothing to the stack. + (axSign * (b[0].traceIndex - a[0].traceIndex)); + }); + + var donepositioning, topOverlap, bottomOverlap, i, j, pti, sumdp; + + function constrainGroup(grp) { + var minPt = grp[0]; + var maxPt = grp[grp.length - 1]; + + // overlap with the top - positive vals are overlaps + topOverlap = minPt.pmin - minPt.pos - minPt.dp + minPt.size; + + // overlap with the bottom - positive vals are overlaps + bottomOverlap = maxPt.pos + maxPt.dp + maxPt.size - minPt.pmax; + + // check for min overlap first, so that we always + // see the largest labels + // allow for .01px overlap, so we don't get an + // infinite loop from rounding errors + if(topOverlap > 0.01) { + for(j = grp.length - 1; j >= 0; j--) grp[j].dp += topOverlap; + donepositioning = false; + } + if(bottomOverlap < 0.01) return; + if(topOverlap < -0.01) { + // make sure we're not pushing back and forth + for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; + donepositioning = false; + } + if(!donepositioning) return; + + // no room to fix positioning, delete off-screen points + + // first see how many points we need to delete + var deleteCount = 0; + for(i = 0; i < grp.length; i++) { + pti = grp[i]; + if(pti.pos + pti.dp + pti.size > minPt.pmax) deleteCount++; + } + + // start by deleting points whose data is off screen + for(i = grp.length - 1; i >= 0; i--) { + if(deleteCount <= 0) break; + pti = grp[i]; + + // pos has already been constrained to [pmin,pmax] + // so look for points close to that to delete + if(pti.pos > minPt.pmax - 1) { + pti.del = true; + deleteCount--; + } + } + for(i = 0; i < grp.length; i++) { + if(deleteCount <= 0) break; + pti = grp[i]; + + // pos has already been constrained to [pmin,pmax] + // so look for points close to that to delete + if(pti.pos < minPt.pmin + 1) { + pti.del = true; + deleteCount--; + + // shift the whole group minus into this new space + bottomOverlap = pti.size * 2; + for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; + } + } + // then delete points that go off the bottom + for(i = grp.length - 1; i >= 0; i--) { + if(deleteCount <= 0) break; + pti = grp[i]; + if(pti.pos + pti.dp + pti.size > minPt.pmax) { + pti.del = true; + deleteCount--; + } + } + } + + // loop through groups, combining them if they overlap, + // until nothing moves + while(!donepositioning && nummoves <= hoverData.length) { + // to avoid infinite loops, don't move more times + // than there are traces + nummoves++; + + // assume nothing will move in this iteration, + // reverse this if it does + donepositioning = true; + i = 0; + while(i < pointgroups.length - 1) { + // the higher (g0) and lower (g1) point group + var g0 = pointgroups[i]; + var g1 = pointgroups[i + 1]; + + // the lowest point in the higher group (p0) + // the highest point in the lower group (p1) + var p0 = g0[g0.length - 1]; + var p1 = g1[0]; + topOverlap = p0.pos + p0.dp + p0.size - p1.pos - p1.dp + p1.size; + + // Only group points that lie on the same axes + if(topOverlap > 0.01 && (p0.pmin === p1.pmin) && (p0.pmax === p1.pmax)) { + // push the new point(s) added to this group out of the way + for(j = g1.length - 1; j >= 0; j--) g1[j].dp += topOverlap; + + // add them to the group + g0.push.apply(g0, g1); + pointgroups.splice(i + 1, 1); + + // adjust for minimum average movement + sumdp = 0; + for(j = g0.length - 1; j >= 0; j--) sumdp += g0[j].dp; + bottomOverlap = sumdp / g0.length; + for(j = g0.length - 1; j >= 0; j--) g0[j].dp -= bottomOverlap; + donepositioning = false; + } + else i++; + } + + // check if we're going off the plot on either side and fix + pointgroups.forEach(constrainGroup); + } + + // now put these offsets into hoverData + for(i = pointgroups.length - 1; i >= 0; i--) { + var grp = pointgroups[i]; + for(j = grp.length - 1; j >= 0; j--) { + var pt = grp[j]; + var hoverPt = hoverData[pt.i]; + hoverPt.offset = pt.dp; + hoverPt.del = pt.del; + } + } +} + +function alignHoverText(hoverLabels, rotateLabels) { + // finally set the text positioning relative to the data and draw the + // box around it + hoverLabels.each(function(d) { + var g = d3.select(this); + if(d.del) { + g.remove(); + return; + } + + var horzSign = d.anchor === 'end' ? -1 : 1; + var tx = g.select('text.nums'); + var alignShift = {start: 1, end: -1, middle: 0}[d.anchor]; + var txx = alignShift * (HOVERARROWSIZE + HOVERTEXTPAD); + var tx2x = txx + alignShift * (d.txwidth + HOVERTEXTPAD); + var offsetX = 0; + var offsetY = d.offset; + + if(d.anchor === 'middle') { + txx -= d.tx2width / 2; + tx2x += d.txwidth / 2 + HOVERTEXTPAD; + } + if(rotateLabels) { + offsetY *= -YSHIFTY; + offsetX = d.offset * YSHIFTX; + } + + g.select('path').attr('d', d.anchor === 'middle' ? + // middle aligned: rect centered on data + ('M-' + (d.bx / 2 + d.tx2width / 2) + ',' + (offsetY - d.by / 2) + + 'h' + d.bx + 'v' + d.by + 'h-' + d.bx + 'Z') : + // left or right aligned: side rect with arrow to data + ('M0,0L' + (horzSign * HOVERARROWSIZE + offsetX) + ',' + (HOVERARROWSIZE + offsetY) + + 'v' + (d.by / 2 - HOVERARROWSIZE) + + 'h' + (horzSign * d.bx) + + 'v-' + d.by + + 'H' + (horzSign * HOVERARROWSIZE + offsetX) + + 'V' + (offsetY - HOVERARROWSIZE) + + 'Z')); + + tx.call(svgTextUtils.positionText, + txx + offsetX, offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD); + + if(d.tx2width) { + g.select('text.name') + .call(svgTextUtils.positionText, + tx2x + alignShift * HOVERTEXTPAD + offsetX, + offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD); + g.select('rect') + .call(Drawing.setRect, + tx2x + (alignShift - 1) * d.tx2width / 2 + offsetX, + offsetY - d.by / 2 - 1, + d.tx2width, d.by + 2); + } + }); +} + +function cleanPoint(d, hovermode) { + var index = d.index; + var trace = d.trace || {}; + var cd0 = d.cd[0]; + var cd = d.cd[index] || {}; + + var getVal = Array.isArray(index) ? + function(calcKey, traceKey) { + return Lib.castOption(cd0, index, calcKey) || + Lib.extractOption({}, trace, '', traceKey); + } : + function(calcKey, traceKey) { + return Lib.extractOption(cd, trace, calcKey, traceKey); + }; + + function fill(key, calcKey, traceKey) { + var val = getVal(calcKey, traceKey); + if(val) d[key] = val; + } + + fill('hoverinfo', 'hi', 'hoverinfo'); + fill('bgcolor', 'hbg', 'hoverlabel.bgcolor'); + fill('borderColor', 'hbc', 'hoverlabel.bordercolor'); + fill('fontFamily', 'htf', 'hoverlabel.font.family'); + fill('fontSize', 'hts', 'hoverlabel.font.size'); + fill('fontColor', 'htc', 'hoverlabel.font.color'); + fill('nameLength', 'hnl', 'hoverlabel.namelength'); + + d.posref = hovermode === 'y' ? + (d.xa._offset + (d.x0 + d.x1) / 2) : + (d.ya._offset + (d.y0 + d.y1) / 2); + + // then constrain all the positions to be on the plot + d.x0 = Lib.constrain(d.x0, 0, d.xa._length); + d.x1 = Lib.constrain(d.x1, 0, d.xa._length); + d.y0 = Lib.constrain(d.y0, 0, d.ya._length); + d.y1 = Lib.constrain(d.y1, 0, d.ya._length); + + // and convert the x and y label values into formatted text + if(d.xLabelVal !== undefined) { + d.xLabel = ('xLabel' in d) ? d.xLabel : Axes.hoverLabelText(d.xa, d.xLabelVal); + d.xVal = d.xa.c2d(d.xLabelVal); + } + if(d.yLabelVal !== undefined) { + d.yLabel = ('yLabel' in d) ? d.yLabel : Axes.hoverLabelText(d.ya, d.yLabelVal); + d.yVal = d.ya.c2d(d.yLabelVal); + } + + // Traces like heatmaps generate the zLabel in their hoverPoints function + if(d.zLabelVal !== undefined && d.zLabel === undefined) { + d.zLabel = String(d.zLabelVal); + } + + // for box means and error bars, add the range to the label + if(!isNaN(d.xerr) && !(d.xa.type === 'log' && d.xerr <= 0)) { + var xeText = Axes.tickText(d.xa, d.xa.c2l(d.xerr), 'hover').text; + if(d.xerrneg !== undefined) { + d.xLabel += ' +' + xeText + ' / -' + + Axes.tickText(d.xa, d.xa.c2l(d.xerrneg), 'hover').text; + } + else d.xLabel += ' ± ' + xeText; + + // small distance penalty for error bars, so that if there are + // traces with errors and some without, the error bar label will + // hoist up to the point + if(hovermode === 'x') d.distance += 1; + } + if(!isNaN(d.yerr) && !(d.ya.type === 'log' && d.yerr <= 0)) { + var yeText = Axes.tickText(d.ya, d.ya.c2l(d.yerr), 'hover').text; + if(d.yerrneg !== undefined) { + d.yLabel += ' +' + yeText + ' / -' + + Axes.tickText(d.ya, d.ya.c2l(d.yerrneg), 'hover').text; + } + else d.yLabel += ' ± ' + yeText; + + if(hovermode === 'y') d.distance += 1; + } + + var infomode = d.hoverinfo || d.trace.hoverinfo; + + if(infomode !== 'all') { + infomode = Array.isArray(infomode) ? infomode : infomode.split('+'); + if(infomode.indexOf('x') === -1) d.xLabel = undefined; + if(infomode.indexOf('y') === -1) d.yLabel = undefined; + if(infomode.indexOf('z') === -1) d.zLabel = undefined; + if(infomode.indexOf('text') === -1) d.text = undefined; + if(infomode.indexOf('name') === -1) d.name = undefined; + } + + return d; +} + +function createSpikelines(closestPoints, opts) { + var container = opts.container; + var fullLayout = opts.fullLayout; + var evt = opts.event; + var showY = !!closestPoints.hLinePoint; + var showX = !!closestPoints.vLinePoint; + + var xa, ya; + + // Remove old spikeline items + container.selectAll('.spikeline').remove(); + + if(!(showX || showY)) return; + + var contrastColor = Color.combine(fullLayout.plot_bgcolor, fullLayout.paper_bgcolor); + + // Horizontal line (to y-axis) + if(showY) { + var hLinePoint = closestPoints.hLinePoint; + var hLinePointX, hLinePointY; + + xa = hLinePoint && hLinePoint.xa; + ya = hLinePoint && hLinePoint.ya; + var ySnap = ya.spikesnap; + + if(ySnap === 'cursor') { + hLinePointX = evt.pointerX; + hLinePointY = evt.pointerY; + } else { + hLinePointX = xa._offset + hLinePoint.x; + hLinePointY = ya._offset + hLinePoint.y; + } + var dfltHLineColor = tinycolor.readability(hLinePoint.color, contrastColor) < 1.5 ? + Color.contrast(contrastColor) : hLinePoint.color; + var yMode = ya.spikemode; + var yThickness = ya.spikethickness; + var yColor = ya.spikecolor || dfltHLineColor; + var yBB = ya._boundingBox; + var xEdge = ((yBB.left + yBB.right) / 2) < hLinePointX ? yBB.right : yBB.left; + var xBase, xEndSpike; + + if(yMode.indexOf('toaxis') !== -1 || yMode.indexOf('across') !== -1) { + if(yMode.indexOf('toaxis') !== -1) { + xBase = xEdge; + xEndSpike = hLinePointX; + } + if(yMode.indexOf('across') !== -1) { + xBase = ya._counterSpan[0]; + xEndSpike = ya._counterSpan[1]; + } + + // Foreground horizontal line (to y-axis) + container.insert('line', ':first-child') + .attr({ + x1: xBase, + x2: xEndSpike, + y1: hLinePointY, + y2: hLinePointY, + 'stroke-width': yThickness, + stroke: yColor, + 'stroke-dasharray': Drawing.dashStyle(ya.spikedash, yThickness) + }) + .classed('spikeline', true) + .classed('crisp', true); + + // Background horizontal Line (to y-axis) + container.insert('line', ':first-child') + .attr({ + x1: xBase, + x2: xEndSpike, + y1: hLinePointY, + y2: hLinePointY, + 'stroke-width': yThickness + 2, + stroke: contrastColor + }) + .classed('spikeline', true) + .classed('crisp', true); + } + // Y axis marker + if(yMode.indexOf('marker') !== -1) { + container.insert('circle', ':first-child') + .attr({ + cx: xEdge + (ya.side !== 'right' ? yThickness : -yThickness), + cy: hLinePointY, + r: yThickness, + fill: yColor + }) + .classed('spikeline', true); + } + } + + if(showX) { + var vLinePoint = closestPoints.vLinePoint; + var vLinePointX, vLinePointY; + + xa = vLinePoint && vLinePoint.xa; + ya = vLinePoint && vLinePoint.ya; + var xSnap = xa.spikesnap; + + if(xSnap === 'cursor') { + vLinePointX = evt.pointerX; + vLinePointY = evt.pointerY; + } else { + vLinePointX = xa._offset + vLinePoint.x; + vLinePointY = ya._offset + vLinePoint.y; + } + var dfltVLineColor = tinycolor.readability(vLinePoint.color, contrastColor) < 1.5 ? + Color.contrast(contrastColor) : vLinePoint.color; + var xMode = xa.spikemode; + var xThickness = xa.spikethickness; + var xColor = xa.spikecolor || dfltVLineColor; + var xBB = xa._boundingBox; + var yEdge = ((xBB.top + xBB.bottom) / 2) < vLinePointY ? xBB.bottom : xBB.top; + var yBase, yEndSpike; + + if(xMode.indexOf('toaxis') !== -1 || xMode.indexOf('across') !== -1) { + if(xMode.indexOf('toaxis') !== -1) { + yBase = yEdge; + yEndSpike = vLinePointY; + } + if(xMode.indexOf('across') !== -1) { + yBase = xa._counterSpan[0]; + yEndSpike = xa._counterSpan[1]; + } + + // Foreground vertical line (to x-axis) + container.insert('line', ':first-child') + .attr({ + x1: vLinePointX, + x2: vLinePointX, + y1: yBase, + y2: yEndSpike, + 'stroke-width': xThickness, + stroke: xColor, + 'stroke-dasharray': Drawing.dashStyle(xa.spikedash, xThickness) + }) + .classed('spikeline', true) + .classed('crisp', true); + + // Background vertical line (to x-axis) + container.insert('line', ':first-child') + .attr({ + x1: vLinePointX, + x2: vLinePointX, + y1: yBase, + y2: yEndSpike, + 'stroke-width': xThickness + 2, + stroke: contrastColor + }) + .classed('spikeline', true) + .classed('crisp', true); + } + + // X axis marker + if(xMode.indexOf('marker') !== -1) { + container.insert('circle', ':first-child') + .attr({ + cx: vLinePointX, + cy: yEdge - (xa.side !== 'top' ? xThickness : -xThickness), + r: xThickness, + fill: xColor + }) + .classed('spikeline', true); + } + } +} + +function hoverChanged(gd, evt, oldhoverdata) { + // don't emit any events if nothing changed + if(!oldhoverdata || oldhoverdata.length !== gd._hoverdata.length) return true; + + for(var i = oldhoverdata.length - 1; i >= 0; i--) { + var oldPt = oldhoverdata[i]; + var newPt = gd._hoverdata[i]; + if(oldPt.curveNumber !== newPt.curveNumber || + String(oldPt.pointNumber) !== String(newPt.pointNumber)) { + return true; + } + } + return false; +} + +function spikesChanged(gd, oldspikepoints) { + // don't relayout the plot because of new spikelines if spikelines points didn't change + if(!oldspikepoints) return true; + if(oldspikepoints.vLinePoint !== gd._spikepoints.vLinePoint || + oldspikepoints.hLinePoint !== gd._spikepoints.hLinePoint + ) return true; + return false; +} + +},{"../../lib":696,"../../lib/events":684,"../../lib/override_cursor":707,"../../lib/svg_text_utils":720,"../../plots/cartesian/axes":744,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"./constants":607,"./helpers":609,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,"tinycolor2":514}],611:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { + opts = opts || {}; + + coerce('hoverlabel.bgcolor', opts.bgcolor); + coerce('hoverlabel.bordercolor', opts.bordercolor); + coerce('hoverlabel.namelength', opts.namelength); + Lib.coerceFont(coerce, 'hoverlabel.font', opts.font); +}; + +},{"../../lib":696}],612:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Lib = _dereq_('../../lib'); +var dragElement = _dereq_('../dragelement'); +var helpers = _dereq_('./helpers'); +var layoutAttributes = _dereq_('./layout_attributes'); +var hoverModule = _dereq_('./hover'); + +module.exports = { + moduleType: 'component', + name: 'fx', + + constants: _dereq_('./constants'), + schema: { + layout: layoutAttributes + }, + + attributes: _dereq_('./attributes'), + layoutAttributes: layoutAttributes, + + supplyLayoutGlobalDefaults: _dereq_('./layout_global_defaults'), + supplyDefaults: _dereq_('./defaults'), + supplyLayoutDefaults: _dereq_('./layout_defaults'), + + calc: _dereq_('./calc'), + + getDistanceFunction: helpers.getDistanceFunction, + getClosest: helpers.getClosest, + inbox: helpers.inbox, + quadrature: helpers.quadrature, + appendArrayPointValue: helpers.appendArrayPointValue, + + castHoverOption: castHoverOption, + castHoverinfo: castHoverinfo, + + hover: hoverModule.hover, + unhover: dragElement.unhover, + + loneHover: hoverModule.loneHover, + multiHovers: hoverModule.multiHovers, + loneUnhover: loneUnhover, + + click: _dereq_('./click') +}; + +function loneUnhover(containerOrSelection) { + // duck type whether the arg is a d3 selection because ie9 doesn't + // handle instanceof like modern browsers do. + var selection = Lib.isD3Selection(containerOrSelection) ? + containerOrSelection : + d3.select(containerOrSelection); + + selection.selectAll('g.hovertext').remove(); + selection.selectAll('.spikeline').remove(); +} + +// helpers for traces that use Fx.loneHover + +function castHoverOption(trace, ptNumber, attr) { + return Lib.castOption(trace, ptNumber, 'hoverlabel.' + attr); +} + +function castHoverinfo(trace, fullLayout, ptNumber) { + function _coerce(val) { + return Lib.coerceHoverinfo({hoverinfo: val}, {_module: trace._module}, fullLayout); + } + + return Lib.castOption(trace, ptNumber, 'hoverinfo', _coerce); +} + +},{"../../lib":696,"../dragelement":592,"./attributes":604,"./calc":605,"./click":606,"./constants":607,"./defaults":608,"./helpers":609,"./hover":610,"./layout_attributes":613,"./layout_defaults":614,"./layout_global_defaults":615,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],613:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var constants = _dereq_('./constants'); + +var fontAttrs = _dereq_('../../plots/font_attributes')({ + editType: 'none', + +}); +fontAttrs.family.dflt = constants.HOVERFONT; +fontAttrs.size.dflt = constants.HOVERFONTSIZE; + +module.exports = { + clickmode: { + valType: 'flaglist', + + flags: ['event', 'select'], + dflt: 'event', + editType: 'plot', + extras: ['none'], + + }, + dragmode: { + valType: 'enumerated', + + values: ['zoom', 'pan', 'select', 'lasso', 'orbit', 'turntable'], + dflt: 'zoom', + editType: 'modebar', + + }, + hovermode: { + valType: 'enumerated', + + values: ['x', 'y', 'closest', false], + editType: 'modebar', + + }, + hoverdistance: { + valType: 'integer', + min: -1, + dflt: 20, + + editType: 'none', + + }, + spikedistance: { + valType: 'integer', + min: -1, + dflt: 20, + + editType: 'none', + + }, + hoverlabel: { + bgcolor: { + valType: 'color', + + editType: 'none', + + }, + bordercolor: { + valType: 'color', + + editType: 'none', + + }, + font: fontAttrs, + namelength: { + valType: 'integer', + min: -1, + dflt: 15, + + editType: 'none', + + }, + editType: 'none' + }, + selectdirection: { + valType: 'enumerated', + + values: ['h', 'v', 'd', 'any'], + dflt: 'any', + + editType: 'none' + } +}; + +},{"../../plots/font_attributes":771,"./constants":607}],614:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var layoutAttributes = _dereq_('./layout_attributes'); + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + + var clickmode = coerce('clickmode'); + + var dragMode = coerce('dragmode'); + if(dragMode === 'select') coerce('selectdirection'); + + var hovermodeDflt; + if(layoutOut._has('cartesian')) { + if(clickmode.indexOf('select') > -1) { + hovermodeDflt = 'closest'; + } else { + // flag for 'horizontal' plots: + // determines the state of the mode bar 'compare' hovermode button + layoutOut._isHoriz = isHoriz(fullData); + hovermodeDflt = layoutOut._isHoriz ? 'y' : 'x'; + } + } + else hovermodeDflt = 'closest'; + + var hoverMode = coerce('hovermode', hovermodeDflt); + if(hoverMode) { + coerce('hoverdistance'); + coerce('spikedistance'); + } + + // if only mapbox or geo subplots is present on graph, + // reset 'zoom' dragmode to 'pan' until 'zoom' is implemented, + // so that the correct modebar button is active + var hasMapbox = layoutOut._has('mapbox'); + var hasGeo = layoutOut._has('geo'); + var len = layoutOut._basePlotModules.length; + + if(layoutOut.dragmode === 'zoom' && ( + ((hasMapbox || hasGeo) && len === 1) || + (hasMapbox && hasGeo && len === 2) + )) { + layoutOut.dragmode = 'pan'; + } +}; + +function isHoriz(fullData) { + var out = true; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(trace.orientation !== 'h') { + out = false; + break; + } + } + + return out; +} + +},{"../../lib":696,"./layout_attributes":613}],615:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleHoverLabelDefaults = _dereq_('./hoverlabel_defaults'); +var layoutAttributes = _dereq_('./layout_attributes'); + +module.exports = function supplyLayoutGlobalDefaults(layoutIn, layoutOut) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + + handleHoverLabelDefaults(layoutIn, layoutOut, coerce); +}; + +},{"../../lib":696,"./hoverlabel_defaults":611,"./layout_attributes":613}],616:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var counterRegex = _dereq_('../../lib/regex').counter; +var domainAttrs = _dereq_('../../plots/domain').attributes; +var cartesianIdRegex = _dereq_('../../plots/cartesian/constants').idRegex; +var Template = _dereq_('../../plot_api/plot_template'); + +var gridAttrs = { + rows: { + valType: 'integer', + min: 1, + + editType: 'plot', + + }, + roworder: { + valType: 'enumerated', + values: ['top to bottom', 'bottom to top'], + dflt: 'top to bottom', + + editType: 'plot', + + }, + columns: { + valType: 'integer', + min: 1, + + editType: 'plot', + + }, + subplots: { + valType: 'info_array', + freeLength: true, + dimensions: 2, + items: {valType: 'enumerated', values: [counterRegex('xy').toString(), ''], editType: 'plot'}, + + editType: 'plot', + + }, + xaxes: { + valType: 'info_array', + freeLength: true, + items: {valType: 'enumerated', values: [cartesianIdRegex.x.toString(), ''], editType: 'plot'}, + + editType: 'plot', + + }, + yaxes: { + valType: 'info_array', + freeLength: true, + items: {valType: 'enumerated', values: [cartesianIdRegex.y.toString(), ''], editType: 'plot'}, + + editType: 'plot', + + }, + pattern: { + valType: 'enumerated', + values: ['independent', 'coupled'], + dflt: 'coupled', + + editType: 'plot', + + }, + xgap: { + valType: 'number', + min: 0, + max: 1, + + editType: 'plot', + + }, + ygap: { + valType: 'number', + min: 0, + max: 1, + + editType: 'plot', + + }, + domain: domainAttrs({name: 'grid', editType: 'plot', noGridCell: true}, { + + }), + xside: { + valType: 'enumerated', + values: ['bottom', 'bottom plot', 'top plot', 'top'], + dflt: 'bottom plot', + + editType: 'plot', + + }, + yside: { + valType: 'enumerated', + values: ['left', 'left plot', 'right plot', 'right'], + dflt: 'left plot', + + editType: 'plot', + + }, + editType: 'plot' +}; + +function getAxes(layout, grid, axLetter) { + var gridVal = grid[axLetter + 'axes']; + var splomVal = Object.keys((layout._splomAxes || {})[axLetter] || {}); + + if(Array.isArray(gridVal)) return gridVal; + if(splomVal.length) return splomVal; +} + +// the shape of the grid - this needs to be done BEFORE supplyDataDefaults +// so that non-subplot traces can place themselves in the grid +function sizeDefaults(layoutIn, layoutOut) { + var gridIn = layoutIn.grid || {}; + var xAxes = getAxes(layoutOut, gridIn, 'x'); + var yAxes = getAxes(layoutOut, gridIn, 'y'); + + if(!layoutIn.grid && !xAxes && !yAxes) return; + + var hasSubplotGrid = Array.isArray(gridIn.subplots) && Array.isArray(gridIn.subplots[0]); + var hasXaxes = Array.isArray(xAxes); + var hasYaxes = Array.isArray(yAxes); + var isSplomGenerated = ( + hasXaxes && xAxes !== gridIn.xaxes && + hasYaxes && yAxes !== gridIn.yaxes + ); + + var dfltRows, dfltColumns; + + if(hasSubplotGrid) { + dfltRows = gridIn.subplots.length; + dfltColumns = gridIn.subplots[0].length; + } + else { + if(hasYaxes) dfltRows = yAxes.length; + if(hasXaxes) dfltColumns = xAxes.length; + } + + var gridOut = Template.newContainer(layoutOut, 'grid'); + + function coerce(attr, dflt) { + return Lib.coerce(gridIn, gridOut, gridAttrs, attr, dflt); + } + + var rows = coerce('rows', dfltRows); + var columns = coerce('columns', dfltColumns); + + if(!(rows * columns > 1)) { + delete layoutOut.grid; + return; + } + + if(!hasSubplotGrid && !hasXaxes && !hasYaxes) { + var useDefaultSubplots = coerce('pattern') === 'independent'; + if(useDefaultSubplots) hasSubplotGrid = true; + } + gridOut._hasSubplotGrid = hasSubplotGrid; + + var rowOrder = coerce('roworder'); + var reversed = rowOrder === 'top to bottom'; + + var dfltGapX = hasSubplotGrid ? 0.2 : 0.1; + var dfltGapY = hasSubplotGrid ? 0.3 : 0.1; + + var dfltSideX, dfltSideY; + if(isSplomGenerated && layoutOut._splomGridDflt) { + dfltSideX = layoutOut._splomGridDflt.xside; + dfltSideY = layoutOut._splomGridDflt.yside; + } + + gridOut._domains = { + x: fillGridPositions('x', coerce, dfltGapX, dfltSideX, columns), + y: fillGridPositions('y', coerce, dfltGapY, dfltSideY, rows, reversed) + }; +} + +// coerce x or y sizing attributes and return an array of domains for this direction +function fillGridPositions(axLetter, coerce, dfltGap, dfltSide, len, reversed) { + var dirGap = coerce(axLetter + 'gap', dfltGap); + var domain = coerce('domain.' + axLetter); + coerce(axLetter + 'side', dfltSide); + + var out = new Array(len); + var start = domain[0]; + var step = (domain[1] - start) / (len - dirGap); + var cellDomain = step * (1 - dirGap); + for(var i = 0; i < len; i++) { + var cellStart = start + step * i; + out[reversed ? (len - 1 - i) : i] = [cellStart, cellStart + cellDomain]; + } + return out; +} + +// the (cartesian) contents of the grid - this needs to happen AFTER supplyDataDefaults +// so that we know what cartesian subplots are available +function contentDefaults(layoutIn, layoutOut) { + var gridOut = layoutOut.grid; + // make sure we got to the end of handleGridSizing + if(!gridOut || !gridOut._domains) return; + + var gridIn = layoutIn.grid || {}; + var subplots = layoutOut._subplots; + var hasSubplotGrid = gridOut._hasSubplotGrid; + var rows = gridOut.rows; + var columns = gridOut.columns; + var useDefaultSubplots = gridOut.pattern === 'independent'; + + var i, j, xId, yId, subplotId, subplotsOut, yPos; + + var axisMap = gridOut._axisMap = {}; + + if(hasSubplotGrid) { + var subplotsIn = gridIn.subplots || []; + subplotsOut = gridOut.subplots = new Array(rows); + var index = 1; + + for(i = 0; i < rows; i++) { + var rowOut = subplotsOut[i] = new Array(columns); + var rowIn = subplotsIn[i] || []; + for(j = 0; j < columns; j++) { + if(useDefaultSubplots) { + subplotId = (index === 1) ? 'xy' : ('x' + index + 'y' + index); + index++; + } + else subplotId = rowIn[j]; + + rowOut[j] = ''; + + if(subplots.cartesian.indexOf(subplotId) !== -1) { + yPos = subplotId.indexOf('y'); + xId = subplotId.slice(0, yPos); + yId = subplotId.slice(yPos); + if((axisMap[xId] !== undefined && axisMap[xId] !== j) || + (axisMap[yId] !== undefined && axisMap[yId] !== i) + ) { + continue; + } + + rowOut[j] = subplotId; + axisMap[xId] = j; + axisMap[yId] = i; + } + } + } + } + else { + var xAxes = getAxes(layoutOut, gridIn, 'x'); + var yAxes = getAxes(layoutOut, gridIn, 'y'); + gridOut.xaxes = fillGridAxes(xAxes, subplots.xaxis, columns, axisMap, 'x'); + gridOut.yaxes = fillGridAxes(yAxes, subplots.yaxis, rows, axisMap, 'y'); + } + + var anchors = gridOut._anchors = {}; + var reversed = gridOut.roworder === 'top to bottom'; + + for(var axisId in axisMap) { + var axLetter = axisId.charAt(0); + var side = gridOut[axLetter + 'side']; + + var i0, inc, iFinal; + + if(side.length < 8) { + // grid edge - ie not "* plot" - make these as free axes + // since we're not guaranteed to have a subplot there at all + anchors[axisId] = 'free'; + } + else if(axLetter === 'x') { + if((side.charAt(0) === 't') === reversed) { + i0 = 0; + inc = 1; + iFinal = rows; + } + else { + i0 = rows - 1; + inc = -1; + iFinal = -1; + } + if(hasSubplotGrid) { + var column = axisMap[axisId]; + for(i = i0; i !== iFinal; i += inc) { + subplotId = subplotsOut[i][column]; + if(!subplotId) continue; + yPos = subplotId.indexOf('y'); + if(subplotId.slice(0, yPos) === axisId) { + anchors[axisId] = subplotId.slice(yPos); + break; + } + } + } + else { + for(i = i0; i !== iFinal; i += inc) { + yId = gridOut.yaxes[i]; + if(subplots.cartesian.indexOf(axisId + yId) !== -1) { + anchors[axisId] = yId; + break; + } + } + } + } + else { + if((side.charAt(0) === 'l')) { + i0 = 0; + inc = 1; + iFinal = columns; + } + else { + i0 = columns - 1; + inc = -1; + iFinal = -1; + } + if(hasSubplotGrid) { + var row = axisMap[axisId]; + for(i = i0; i !== iFinal; i += inc) { + subplotId = subplotsOut[row][i]; + if(!subplotId) continue; + yPos = subplotId.indexOf('y'); + if(subplotId.slice(yPos) === axisId) { + anchors[axisId] = subplotId.slice(0, yPos); + break; + } + } + } + else { + for(i = i0; i !== iFinal; i += inc) { + xId = gridOut.xaxes[i]; + if(subplots.cartesian.indexOf(xId + axisId) !== -1) { + anchors[axisId] = xId; + break; + } + } + } + } + } +} + +function fillGridAxes(axesIn, axesAllowed, len, axisMap, axLetter) { + var out = new Array(len); + var i; + + function fillOneAxis(i, axisId) { + if(axesAllowed.indexOf(axisId) !== -1 && axisMap[axisId] === undefined) { + out[i] = axisId; + axisMap[axisId] = i; + } + else out[i] = ''; + } + + if(Array.isArray(axesIn)) { + for(i = 0; i < len; i++) { + fillOneAxis(i, axesIn[i]); + } + } + else { + // default axis list is the first `len` axis ids + fillOneAxis(0, axLetter); + for(i = 1; i < len; i++) { + fillOneAxis(i, axLetter + (i + 1)); + } + } + + return out; +} + +module.exports = { + moduleType: 'component', + name: 'grid', + + schema: { + layout: {grid: gridAttrs} + }, + + layoutAttributes: gridAttrs, + sizeDefaults: sizeDefaults, + contentDefaults: contentDefaults +}; + +},{"../../lib":696,"../../lib/regex":712,"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750,"../../plots/domain":770}],617:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var cartesianConstants = _dereq_('../../plots/cartesian/constants'); +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + + +module.exports = templatedArray('image', { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'arraydraw', + + }, + + source: { + valType: 'string', + + editType: 'arraydraw', + + }, + + layer: { + valType: 'enumerated', + values: ['below', 'above'], + dflt: 'above', + + editType: 'arraydraw', + + }, + + sizex: { + valType: 'number', + + dflt: 0, + editType: 'arraydraw', + + }, + + sizey: { + valType: 'number', + + dflt: 0, + editType: 'arraydraw', + + }, + + sizing: { + valType: 'enumerated', + values: ['fill', 'contain', 'stretch'], + dflt: 'contain', + + editType: 'arraydraw', + + }, + + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + editType: 'arraydraw', + + }, + + x: { + valType: 'any', + + dflt: 0, + editType: 'arraydraw', + + }, + + y: { + valType: 'any', + + dflt: 0, + editType: 'arraydraw', + + }, + + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + editType: 'arraydraw', + + }, + + yanchor: { + valType: 'enumerated', + values: ['top', 'middle', 'bottom'], + dflt: 'top', + + editType: 'arraydraw', + + }, + + xref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.x.toString() + ], + dflt: 'paper', + + editType: 'arraydraw', + + }, + + yref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.y.toString() + ], + dflt: 'paper', + + editType: 'arraydraw', + + }, + editType: 'arraydraw' +}); + +},{"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750}],618:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var toLogRange = _dereq_('../../lib/to_log_range'); + +/* + * convertCoords: when converting an axis between log and linear + * you need to alter any images on that axis to keep them + * pointing at the same data point. + * In v2.0 this will become obsolete (or perhaps size will still need conversion?) + * we convert size by declaring that the maximum extent *in data units* should be + * the same, assuming the image is anchored by its center (could remove that restriction + * if we think it's important) even though the actual left and right values will not be + * quite the same since the scale becomes nonlinear (and central anchor means the pixel + * center of the image, not the data units center) + * + * gd: the plot div + * ax: the axis being changed + * newType: the type it's getting + * doExtra: function(attr, val) from inside relayout that sets the attribute. + * Use this to make the changes as it's aware if any other changes in the + * same relayout call should override this conversion. + */ +module.exports = function convertCoords(gd, ax, newType, doExtra) { + ax = ax || {}; + + var toLog = (newType === 'log') && (ax.type === 'linear'), + fromLog = (newType === 'linear') && (ax.type === 'log'); + + if(!(toLog || fromLog)) return; + + var images = gd._fullLayout.images, + axLetter = ax._id.charAt(0), + image, + attrPrefix; + + for(var i = 0; i < images.length; i++) { + image = images[i]; + attrPrefix = 'images[' + i + '].'; + + if(image[axLetter + 'ref'] === ax._id) { + var currentPos = image[axLetter], + currentSize = image['size' + axLetter], + newPos = null, + newSize = null; + + if(toLog) { + newPos = toLogRange(currentPos, ax.range); + + // this is the inverse of the conversion we do in fromLog below + // so that the conversion is reversible (notice the fromLog conversion + // is like sinh, and this one looks like arcsinh) + var dx = currentSize / Math.pow(10, newPos) / 2; + newSize = 2 * Math.log(dx + Math.sqrt(1 + dx * dx)) / Math.LN10; + } + else { + newPos = Math.pow(10, currentPos); + newSize = newPos * (Math.pow(10, currentSize / 2) - Math.pow(10, -currentSize / 2)); + } + + // if conversion failed, delete the value so it can get a default later on + if(!isNumeric(newPos)) { + newPos = null; + newSize = null; + } + else if(!isNumeric(newSize)) newSize = null; + + doExtra(attrPrefix + axLetter, newPos); + doExtra(attrPrefix + 'size' + axLetter, newSize); + } + } +}; + +},{"../../lib/to_log_range":722,"fast-isnumeric":214}],619:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var name = 'images'; + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + var opts = { + name: name, + handleItemDefaults: imageDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + + +function imageDefaults(imageIn, imageOut, fullLayout) { + + function coerce(attr, dflt) { + return Lib.coerce(imageIn, imageOut, attributes, attr, dflt); + } + + var source = coerce('source'); + var visible = coerce('visible', !!source); + + if(!visible) return imageOut; + + coerce('layer'); + coerce('xanchor'); + coerce('yanchor'); + coerce('sizex'); + coerce('sizey'); + coerce('sizing'); + coerce('opacity'); + + var gdMock = { _fullLayout: fullLayout }, + axLetters = ['x', 'y']; + + for(var i = 0; i < 2; i++) { + // 'paper' is the fallback axref + var axLetter = axLetters[i], + axRef = Axes.coerceRef(imageIn, imageOut, gdMock, axLetter, 'paper'); + + Axes.coercePosition(imageOut, gdMock, coerce, axRef, axLetter, 0); + } + + return imageOut; +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/cartesian/axes":744,"./attributes":617}],620:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../drawing'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + imageDataAbove = [], + imageDataSubplot = {}, + imageDataBelow = [], + subplot, + i; + + // Sort into top, subplot, and bottom layers + for(i = 0; i < fullLayout.images.length; i++) { + var img = fullLayout.images[i]; + + if(img.visible) { + if(img.layer === 'below' && img.xref !== 'paper' && img.yref !== 'paper') { + subplot = img.xref + img.yref; + + var plotinfo = fullLayout._plots[subplot]; + + if(!plotinfo) { + // Fall back to _imageLowerLayer in case the requested subplot doesn't exist. + // This can happen if you reference the image to an x / y axis combination + // that doesn't have any data on it (and layer is below) + imageDataBelow.push(img); + continue; + } + + if(plotinfo.mainplot) { + subplot = plotinfo.mainplot.id; + } + + if(!imageDataSubplot[subplot]) { + imageDataSubplot[subplot] = []; + } + imageDataSubplot[subplot].push(img); + } else if(img.layer === 'above') { + imageDataAbove.push(img); + } else { + imageDataBelow.push(img); + } + } + } + + + var anchors = { + x: { + left: { sizing: 'xMin', offset: 0 }, + center: { sizing: 'xMid', offset: -1 / 2 }, + right: { sizing: 'xMax', offset: -1 } + }, + y: { + top: { sizing: 'YMin', offset: 0 }, + middle: { sizing: 'YMid', offset: -1 / 2 }, + bottom: { sizing: 'YMax', offset: -1 } + } + }; + + + // Images must be converted to dataURL's for exporting. + function setImage(d) { + var thisImage = d3.select(this); + + if(this.img && this.img.src === d.source) { + return; + } + + thisImage.attr('xmlns', xmlnsNamespaces.svg); + + var imagePromise = new Promise(function(resolve) { + + var img = new Image(); + this.img = img; + + // If not set, a `tainted canvas` error is thrown + img.setAttribute('crossOrigin', 'anonymous'); + img.onerror = errorHandler; + img.onload = function() { + var canvas = document.createElement('canvas'); + canvas.width = this.width; + canvas.height = this.height; + + var ctx = canvas.getContext('2d'); + ctx.drawImage(this, 0, 0); + + var dataURL = canvas.toDataURL('image/png'); + + thisImage.attr('xlink:href', dataURL); + + // resolve promise in onload handler instead of on 'load' to support IE11 + // see https://github.com/plotly/plotly.js/issues/1685 + // for more details + resolve(); + }; + + + thisImage.on('error', errorHandler); + + img.src = d.source; + + function errorHandler() { + thisImage.remove(); + resolve(); + } + }.bind(this)); + + gd._promises.push(imagePromise); + } + + function applyAttributes(d) { + var thisImage = d3.select(this); + + // Axes if specified + var xa = Axes.getFromId(gd, d.xref), + ya = Axes.getFromId(gd, d.yref); + + var size = fullLayout._size, + width = xa ? Math.abs(xa.l2p(d.sizex) - xa.l2p(0)) : d.sizex * size.w, + height = ya ? Math.abs(ya.l2p(d.sizey) - ya.l2p(0)) : d.sizey * size.h; + + // Offsets for anchor positioning + var xOffset = width * anchors.x[d.xanchor].offset, + yOffset = height * anchors.y[d.yanchor].offset; + + var sizing = anchors.x[d.xanchor].sizing + anchors.y[d.yanchor].sizing; + + // Final positions + var xPos = (xa ? xa.r2p(d.x) + xa._offset : d.x * size.w + size.l) + xOffset, + yPos = (ya ? ya.r2p(d.y) + ya._offset : size.h - d.y * size.h + size.t) + yOffset; + + + // Construct the proper aspectRatio attribute + switch(d.sizing) { + case 'fill': + sizing += ' slice'; + break; + + case 'stretch': + sizing = 'none'; + break; + } + + thisImage.attr({ + x: xPos, + y: yPos, + width: width, + height: height, + preserveAspectRatio: sizing, + opacity: d.opacity + }); + + + // Set proper clipping on images + var xId = xa ? xa._id : '', + yId = ya ? ya._id : '', + clipAxes = xId + yId; + + thisImage.call(Drawing.setClipUrl, clipAxes ? + ('clip' + fullLayout._uid + clipAxes) : + null + ); + } + + var imagesBelow = fullLayout._imageLowerLayer.selectAll('image') + .data(imageDataBelow), + imagesAbove = fullLayout._imageUpperLayer.selectAll('image') + .data(imageDataAbove); + + imagesBelow.enter().append('image'); + imagesAbove.enter().append('image'); + + imagesBelow.exit().remove(); + imagesAbove.exit().remove(); + + imagesBelow.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); + imagesAbove.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); + + var allSubplots = Object.keys(fullLayout._plots); + for(i = 0; i < allSubplots.length; i++) { + subplot = allSubplots[i]; + var subplotObj = fullLayout._plots[subplot]; + + // filter out overlaid plots (which havd their images on the main plot) + // and gl2d plots (which don't support below images, at least not yet) + if(!subplotObj.imagelayer) continue; + + var imagesOnSubplot = subplotObj.imagelayer.selectAll('image') + // even if there are no images on this subplot, we need to run + // enter and exit in case there were previously + .data(imageDataSubplot[subplot] || []); + + imagesOnSubplot.enter().append('image'); + imagesOnSubplot.exit().remove(); + + imagesOnSubplot.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); + } +}; + +},{"../../constants/xmlns_namespaces":674,"../../plots/cartesian/axes":744,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],621:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'component', + name: 'images', + + layoutAttributes: _dereq_('./attributes'), + supplyLayoutDefaults: _dereq_('./defaults'), + includeBasePlot: _dereq_('../../plots/cartesian/include_components')('images'), + + draw: _dereq_('./draw'), + + convertCoords: _dereq_('./convert_coords') +}; + +},{"../../plots/cartesian/include_components":755,"./attributes":617,"./convert_coords":618,"./defaults":619,"./draw":620}],622:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Determine the position anchor property of x/y xanchor/yanchor components. + * + * - values < 1/3 align the low side at that fraction, + * - values [1/3, 2/3] align the center at that fraction, + * - values > 2/3 align the right at that fraction. + */ + +exports.isRightAnchor = function isRightAnchor(opts) { + return ( + opts.xanchor === 'right' || + (opts.xanchor === 'auto' && opts.x >= 2 / 3) + ); +}; + +exports.isCenterAnchor = function isCenterAnchor(opts) { + return ( + opts.xanchor === 'center' || + (opts.xanchor === 'auto' && opts.x > 1 / 3 && opts.x < 2 / 3) + ); +}; + +exports.isBottomAnchor = function isBottomAnchor(opts) { + return ( + opts.yanchor === 'bottom' || + (opts.yanchor === 'auto' && opts.y <= 1 / 3) + ); +}; + +exports.isMiddleAnchor = function isMiddleAnchor(opts) { + return ( + opts.yanchor === 'middle' || + (opts.yanchor === 'auto' && opts.y > 1 / 3 && opts.y < 2 / 3) + ); +}; + +},{}],623:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var colorAttrs = _dereq_('../color/attributes'); + + +module.exports = { + bgcolor: { + valType: 'color', + + editType: 'legend', + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'legend', + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'legend', + + }, + font: fontAttrs({ + editType: 'legend', + + }), + orientation: { + valType: 'enumerated', + values: ['v', 'h'], + dflt: 'v', + + editType: 'legend', + + }, + traceorder: { + valType: 'flaglist', + flags: ['reversed', 'grouped'], + extras: ['normal'], + + editType: 'legend', + + }, + tracegroupgap: { + valType: 'number', + min: 0, + dflt: 10, + + editType: 'legend', + + }, + x: { + valType: 'number', + min: -2, + max: 3, + dflt: 1.02, + + editType: 'legend', + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + editType: 'legend', + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 1, + + editType: 'legend', + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'auto', + + editType: 'legend', + + }, + editType: 'legend' +}; + +},{"../../plots/font_attributes":771,"../color/attributes":569}],624:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + scrollBarWidth: 6, + scrollBarMinHeight: 20, + scrollBarColor: '#808BA4', + scrollBarMargin: 4, + textOffsetX: 40 +}; + +},{}],625:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Template = _dereq_('../../plot_api/plot_template'); + +var attributes = _dereq_('./attributes'); +var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes'); +var helpers = _dereq_('./helpers'); + + +module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { + var containerIn = layoutIn.legend || {}; + + var legendTraceCount = 0; + var legendReallyHasATrace = false; + var defaultOrder = 'normal'; + + var defaultX, defaultY, defaultXAnchor, defaultYAnchor; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(!trace.visible) continue; + + // Note that we explicitly count any trace that is either shown or + // *would* be shown by default, toward the two traces you need to + // ensure the legend is shown by default, because this can still help + // disambiguate. + if(trace.showlegend || trace._dfltShowLegend) { + legendTraceCount++; + if(trace.showlegend) { + legendReallyHasATrace = true; + // Always show the legend by default if there's a pie, + // or if there's only one trace but it's explicitly shown + if(Registry.traceIs(trace, 'pie') || + trace._input.showlegend === true + ) { + legendTraceCount++; + } + } + } + + if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') || + ['tonextx', 'tonexty'].indexOf(trace.fill) !== -1) { + defaultOrder = helpers.isGrouped({traceorder: defaultOrder}) ? + 'grouped+reversed' : 'reversed'; + } + + if(trace.legendgroup !== undefined && trace.legendgroup !== '') { + defaultOrder = helpers.isReversed({traceorder: defaultOrder}) ? + 'reversed+grouped' : 'grouped'; + } + } + + var showLegend = Lib.coerce(layoutIn, layoutOut, + basePlotLayoutAttributes, 'showlegend', + legendReallyHasATrace && legendTraceCount > 1); + + if(showLegend === false) return; + + var containerOut = Template.newContainer(layoutOut, 'legend'); + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + coerce('bgcolor', layoutOut.paper_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); + Lib.coerceFont(coerce, 'font', layoutOut.font); + + coerce('orientation'); + if(containerOut.orientation === 'h') { + var xaxis = layoutIn.xaxis; + if(xaxis && xaxis.rangeslider && xaxis.rangeslider.visible) { + defaultX = 0; + defaultXAnchor = 'left'; + defaultY = 1.1; + defaultYAnchor = 'bottom'; + } + else { + defaultX = 0; + defaultXAnchor = 'left'; + defaultY = -0.1; + defaultYAnchor = 'top'; + } + } + + coerce('traceorder', defaultOrder); + if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap'); + + coerce('x', defaultX); + coerce('xanchor', defaultXAnchor); + coerce('y', defaultY); + coerce('yanchor', defaultYAnchor); + Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); +}; + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../plots/layout_attributes":799,"../../registry":827,"./attributes":623,"./helpers":629}],626:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); +var Plots = _dereq_('../../plots/plots'); +var Registry = _dereq_('../../registry'); +var Events = _dereq_('../../lib/events'); +var dragElement = _dereq_('../dragelement'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var handleClick = _dereq_('./handle_click'); + +var constants = _dereq_('./constants'); +var interactConstants = _dereq_('../../constants/interactions'); +var alignmentConstants = _dereq_('../../constants/alignment'); +var LINE_SPACING = alignmentConstants.LINE_SPACING; +var FROM_TL = alignmentConstants.FROM_TL; +var FROM_BR = alignmentConstants.FROM_BR; + +var getLegendData = _dereq_('./get_legend_data'); +var style = _dereq_('./style'); +var helpers = _dereq_('./helpers'); +var anchorUtils = _dereq_('./anchor_utils'); + +var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY; + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout; + var clipId = 'legend' + fullLayout._uid; + + if(!fullLayout._infolayer || !gd.calcdata) return; + + if(!gd._legendMouseDownTime) gd._legendMouseDownTime = 0; + + var opts = fullLayout.legend; + var legendData = fullLayout.showlegend && getLegendData(gd.calcdata, opts); + var hiddenSlices = fullLayout.hiddenlabels || []; + + if(!fullLayout.showlegend || !legendData.length) { + fullLayout._infolayer.selectAll('.legend').remove(); + fullLayout._topdefs.select('#' + clipId).remove(); + + Plots.autoMargin(gd, 'legend'); + return; + } + + var maxLength = 0; + for(var i = 0; i < legendData.length; i++) { + for(var j = 0; j < legendData[i].length; j++) { + var item = legendData[i][j][0]; + var trace = item.trace; + var isPie = Registry.traceIs(trace, 'pie'); + var name = isPie ? item.label : trace.name; + maxLength = Math.max(maxLength, name && name.length || 0); + } + } + + var firstRender = false; + var legend = Lib.ensureSingle(fullLayout._infolayer, 'g', 'legend', function(s) { + s.attr('pointer-events', 'all'); + firstRender = true; + }); + + var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', clipId, function(s) { + s.append('rect'); + }); + + var bg = Lib.ensureSingle(legend, 'rect', 'bg', function(s) { + s.attr('shape-rendering', 'crispEdges'); + }); + + bg.call(Color.stroke, opts.bordercolor) + .call(Color.fill, opts.bgcolor) + .style('stroke-width', opts.borderwidth + 'px'); + + var scrollBox = Lib.ensureSingle(legend, 'g', 'scrollbox'); + + var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) { + s.attr({ + rx: 20, + ry: 3, + width: 0, + height: 0 + }) + .call(Color.fill, '#808BA4'); + }); + + var groups = scrollBox.selectAll('g.groups') + .data(legendData); + + groups.enter().append('g') + .attr('class', 'groups'); + + groups.exit().remove(); + + var traces = groups.selectAll('g.traces') + .data(Lib.identity); + + traces.enter().append('g').attr('class', 'traces'); + traces.exit().remove(); + + traces.call(style, gd) + .style('opacity', function(d) { + var trace = d[0].trace; + if(Registry.traceIs(trace, 'pie')) { + return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1; + } else { + return trace.visible === 'legendonly' ? 0.5 : 1; + } + }) + .each(function() { + d3.select(this) + .call(drawTexts, gd, maxLength) + .call(setupTraceToggle, gd); + }); + + Lib.syncOrAsync([Plots.previousPromises, + function() { + if(firstRender) { + computeLegendDimensions(gd, groups, traces); + expandMargin(gd); + } + + // Position and size the legend + var lxMin = 0, + lxMax = fullLayout.width, + lyMin = 0, + lyMax = fullLayout.height; + + computeLegendDimensions(gd, groups, traces); + + if(opts._height > lyMax) { + // If the legend doesn't fit in the plot area, + // do not expand the vertical margins. + expandHorizontalMargin(gd); + } else { + expandMargin(gd); + } + + // Scroll section must be executed after repositionLegend. + // It requires the legend width, height, x and y to position the scrollbox + // and these values are mutated in repositionLegend. + var gs = fullLayout._size, + lx = gs.l + gs.w * opts.x, + ly = gs.t + gs.h * (1 - opts.y); + + if(anchorUtils.isRightAnchor(opts)) { + lx -= opts._width; + } + else if(anchorUtils.isCenterAnchor(opts)) { + lx -= opts._width / 2; + } + + if(anchorUtils.isBottomAnchor(opts)) { + ly -= opts._height; + } + else if(anchorUtils.isMiddleAnchor(opts)) { + ly -= opts._height / 2; + } + + // Make sure the legend left and right sides are visible + var legendWidth = opts._width, + legendWidthMax = gs.w; + + if(legendWidth > legendWidthMax) { + lx = gs.l; + legendWidth = legendWidthMax; + } + else { + if(lx + legendWidth > lxMax) lx = lxMax - legendWidth; + if(lx < lxMin) lx = lxMin; + legendWidth = Math.min(lxMax - lx, opts._width); + } + + // Make sure the legend top and bottom are visible + // (legends with a scroll bar are not allowed to stretch beyond the extended + // margins) + var legendHeight = opts._height, + legendHeightMax = gs.h; + + if(legendHeight > legendHeightMax) { + ly = gs.t; + legendHeight = legendHeightMax; + } + else { + if(ly + legendHeight > lyMax) ly = lyMax - legendHeight; + if(ly < lyMin) ly = lyMin; + legendHeight = Math.min(lyMax - ly, opts._height); + } + + // Set size and position of all the elements that make up a legend: + // legend, background and border, scroll box and scroll bar + Drawing.setTranslate(legend, lx, ly); + + // to be safe, remove previous listeners + scrollBar.on('.drag', null); + legend.on('wheel', null); + + if(opts._height <= legendHeight || gd._context.staticPlot) { + // if scrollbar should not be shown. + bg.attr({ + width: legendWidth - opts.borderwidth, + height: legendHeight - opts.borderwidth, + x: opts.borderwidth / 2, + y: opts.borderwidth / 2 + }); + + Drawing.setTranslate(scrollBox, 0, 0); + + clipPath.select('rect').attr({ + width: legendWidth - 2 * opts.borderwidth, + height: legendHeight - 2 * opts.borderwidth, + x: opts.borderwidth, + y: opts.borderwidth + }); + + Drawing.setClipUrl(scrollBox, clipId); + + Drawing.setRect(scrollBar, 0, 0, 0, 0); + delete opts._scrollY; + } + else { + var scrollBarHeight = Math.max(constants.scrollBarMinHeight, + legendHeight * legendHeight / opts._height); + var scrollBarYMax = legendHeight - + scrollBarHeight - + 2 * constants.scrollBarMargin; + var scrollBoxYMax = opts._height - legendHeight; + var scrollRatio = scrollBarYMax / scrollBoxYMax; + + var scrollBoxY = Math.min(opts._scrollY || 0, scrollBoxYMax); + + // increase the background and clip-path width + // by the scrollbar width and margin + bg.attr({ + width: legendWidth - + 2 * opts.borderwidth + + constants.scrollBarWidth + + constants.scrollBarMargin, + height: legendHeight - opts.borderwidth, + x: opts.borderwidth / 2, + y: opts.borderwidth / 2 + }); + + clipPath.select('rect').attr({ + width: legendWidth - + 2 * opts.borderwidth + + constants.scrollBarWidth + + constants.scrollBarMargin, + height: legendHeight - 2 * opts.borderwidth, + x: opts.borderwidth, + y: opts.borderwidth + scrollBoxY + }); + + Drawing.setClipUrl(scrollBox, clipId); + + scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); + + legend.on('wheel', function() { + scrollBoxY = Lib.constrain( + opts._scrollY + + d3.event.deltaY / scrollBarYMax * scrollBoxYMax, + 0, scrollBoxYMax); + scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); + if(scrollBoxY !== 0 && scrollBoxY !== scrollBoxYMax) { + d3.event.preventDefault(); + } + }); + + var eventY0, scrollBoxY0; + + var drag = d3.behavior.drag() + .on('dragstart', function() { + eventY0 = d3.event.sourceEvent.clientY; + scrollBoxY0 = scrollBoxY; + }) + .on('drag', function() { + var e = d3.event.sourceEvent; + if(e.buttons === 2 || e.ctrlKey) return; + + scrollBoxY = Lib.constrain( + (e.clientY - eventY0) / scrollRatio + scrollBoxY0, + 0, scrollBoxYMax); + scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); + }); + + scrollBar.call(drag); + } + + + function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) { + opts._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY; + Drawing.setTranslate(scrollBox, 0, -scrollBoxY); + + Drawing.setRect( + scrollBar, + legendWidth, + constants.scrollBarMargin + scrollBoxY * scrollRatio, + constants.scrollBarWidth, + scrollBarHeight + ); + clipPath.select('rect').attr({ + y: opts.borderwidth + scrollBoxY + }); + } + + if(gd._context.edits.legendPosition) { + var xf, yf, x0, y0; + + legend.classed('cursor-move', true); + + dragElement.init({ + element: legend.node(), + gd: gd, + prepFn: function() { + var transform = Drawing.getTranslate(legend); + + x0 = transform.x; + y0 = transform.y; + }, + moveFn: function(dx, dy) { + var newX = x0 + dx, + newY = y0 + dy; + + Drawing.setTranslate(legend, newX, newY); + + xf = dragElement.align(newX, 0, gs.l, gs.l + gs.w, opts.xanchor); + yf = dragElement.align(newY, 0, gs.t + gs.h, gs.t, opts.yanchor); + }, + doneFn: function() { + if(xf !== undefined && yf !== undefined) { + Registry.call('relayout', gd, {'legend.x': xf, 'legend.y': yf}); + } + }, + clickFn: function(numClicks, e) { + var clickedTrace = fullLayout._infolayer.selectAll('g.traces').filter(function() { + var bbox = this.getBoundingClientRect(); + return ( + e.clientX >= bbox.left && e.clientX <= bbox.right && + e.clientY >= bbox.top && e.clientY <= bbox.bottom + ); + }); + if(clickedTrace.size() > 0) { + clickOrDoubleClick(gd, legend, clickedTrace, numClicks, e); + } + } + }); + } + }], gd); +}; + +function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) { + var trace = legendItem.data()[0][0].trace; + + var evtData = { + event: evt, + node: legendItem.node(), + curveNumber: trace.index, + expandedIndex: trace._expandedIndex, + data: gd.data, + layout: gd.layout, + frames: gd._transitionData._frames, + config: gd._context, + fullData: gd._fullData, + fullLayout: gd._fullLayout + }; + + if(trace._group) { + evtData.group = trace._group; + } + if(trace.type === 'pie') { + evtData.label = legendItem.datum()[0].label; + } + + var clickVal = Events.triggerHandler(gd, 'plotly_legendclick', evtData); + if(clickVal === false) return; + + if(numClicks === 1) { + legend._clickTimeout = setTimeout(function() { + handleClick(legendItem, gd, numClicks); + }, DBLCLICKDELAY); + } + else if(numClicks === 2) { + if(legend._clickTimeout) clearTimeout(legend._clickTimeout); + gd._legendMouseDownTime = 0; + + var dblClickVal = Events.triggerHandler(gd, 'plotly_legenddoubleclick', evtData); + if(dblClickVal !== false) handleClick(legendItem, gd, numClicks); + } +} + +function drawTexts(g, gd, maxLength) { + var legendItem = g.data()[0][0]; + var fullLayout = gd._fullLayout; + var trace = legendItem.trace; + var isPie = Registry.traceIs(trace, 'pie'); + var traceIndex = trace.index; + var name = isPie ? legendItem.label : trace.name; + var isEditable = gd._context.edits.legendText && !isPie; + + var textEl = Lib.ensureSingle(g, 'text', 'legendtext'); + + textEl.attr('text-anchor', 'start') + .classed('user-select-none', true) + .call(Drawing.font, fullLayout.legend.font) + .text(isEditable ? ensureLength(name, maxLength) : name); + + svgTextUtils.positionText(textEl, constants.textOffsetX, 0); + + function textLayout(s) { + svgTextUtils.convertToTspans(s, gd, function() { + computeTextDimensions(g, gd); + }); + } + + if(isEditable) { + textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name}) + .call(textLayout) + .on('edit', function(newName) { + this.text(ensureLength(newName, maxLength)) + .call(textLayout); + + var fullInput = legendItem.trace._fullInput || {}; + var update = {}; + + if(Registry.hasTransform(fullInput, 'groupby')) { + var groupbyIndices = Registry.getTransformIndices(fullInput, 'groupby'); + var index = groupbyIndices[groupbyIndices.length - 1]; + + var kcont = Lib.keyedContainer(fullInput, 'transforms[' + index + '].styles', 'target', 'value.name'); + + kcont.set(legendItem.trace._group, newName); + + update = kcont.constructUpdate(); + } else { + update.name = newName; + } + + return Registry.call('restyle', gd, update, traceIndex); + }); + } else { + textLayout(textEl); + } +} + +/* + * Make sure we have a reasonably clickable region. + * If this string is missing or very short, pad it with spaces out to at least + * 4 characters, up to the max length of other labels, on the assumption that + * most characters are wider than spaces so a string of spaces will usually be + * no wider than the real labels. + */ +function ensureLength(str, maxLength) { + var targetLength = Math.max(4, maxLength); + if(str && str.trim().length >= targetLength / 2) return str; + str = str || ''; + for(var i = targetLength - str.length; i > 0; i--) str += ' '; + return str; +} + +function setupTraceToggle(g, gd) { + var newMouseDownTime, + numClicks = 1; + + var traceToggle = Lib.ensureSingle(g, 'rect', 'legendtoggle', function(s) { + s.style('cursor', 'pointer') + .attr('pointer-events', 'all') + .call(Color.fill, 'rgba(0,0,0,0)'); + }); + + traceToggle.on('mousedown', function() { + newMouseDownTime = (new Date()).getTime(); + if(newMouseDownTime - gd._legendMouseDownTime < DBLCLICKDELAY) { + // in a click train + numClicks += 1; + } + else { + // new click train + numClicks = 1; + gd._legendMouseDownTime = newMouseDownTime; + } + }); + traceToggle.on('mouseup', function() { + if(gd._dragged || gd._editing) return; + var legend = gd._fullLayout.legend; + + if((new Date()).getTime() - gd._legendMouseDownTime > DBLCLICKDELAY) { + numClicks = Math.max(numClicks - 1, 1); + } + + clickOrDoubleClick(gd, legend, g, numClicks, d3.event); + }); +} + +function computeTextDimensions(g, gd) { + var legendItem = g.data()[0][0]; + + if(!legendItem.trace.showlegend) { + g.remove(); + return; + } + + var mathjaxGroup = g.select('g[class*=math-group]'); + var mathjaxNode = mathjaxGroup.node(); + var opts = gd._fullLayout.legend; + var lineHeight = opts.font.size * LINE_SPACING; + var height, width; + + if(mathjaxNode) { + var mathjaxBB = Drawing.bBox(mathjaxNode); + + height = mathjaxBB.height; + width = mathjaxBB.width; + + Drawing.setTranslate(mathjaxGroup, 0, (height / 4)); + } + else { + var text = g.select('.legendtext'); + var textLines = svgTextUtils.lineCount(text); + var textNode = text.node(); + + height = lineHeight * textLines; + width = textNode ? Drawing.bBox(textNode).width : 0; + + // approximation to height offset to center the font + // to avoid getBoundingClientRect + var textY = lineHeight * (0.3 + (1 - textLines) / 2); + svgTextUtils.positionText(text, constants.textOffsetX, textY); + } + + height = Math.max(height, 16) + 3; + + legendItem.height = height; + legendItem.width = width; +} + +function computeLegendDimensions(gd, groups, traces) { + var fullLayout = gd._fullLayout; + var opts = fullLayout.legend; + var borderwidth = opts.borderwidth; + var isGrouped = helpers.isGrouped(opts); + + var extraWidth = 0; + + opts._width = 0; + opts._height = 0; + + if(helpers.isVertical(opts)) { + if(isGrouped) { + groups.each(function(d, i) { + Drawing.setTranslate(this, 0, i * opts.tracegroupgap); + }); + } + + traces.each(function(d) { + var legendItem = d[0], + textHeight = legendItem.height, + textWidth = legendItem.width; + + Drawing.setTranslate(this, + borderwidth, + (5 + borderwidth + opts._height + textHeight / 2)); + + opts._height += textHeight; + opts._width = Math.max(opts._width, textWidth); + }); + + opts._width += 45 + borderwidth * 2; + opts._height += 10 + borderwidth * 2; + + if(isGrouped) { + opts._height += (opts._lgroupsLength - 1) * opts.tracegroupgap; + } + + extraWidth = 40; + } + else if(isGrouped) { + var groupXOffsets = [opts._width], + groupData = groups.data(); + + for(var i = 0, n = groupData.length; i < n; i++) { + var textWidths = groupData[i].map(function(legendItemArray) { + return legendItemArray[0].width; + }); + + var groupWidth = 40 + Math.max.apply(null, textWidths); + + opts._width += opts.tracegroupgap + groupWidth; + + groupXOffsets.push(opts._width); + } + + groups.each(function(d, i) { + Drawing.setTranslate(this, groupXOffsets[i], 0); + }); + + groups.each(function() { + var group = d3.select(this), + groupTraces = group.selectAll('g.traces'), + groupHeight = 0; + + groupTraces.each(function(d) { + var legendItem = d[0], + textHeight = legendItem.height; + + Drawing.setTranslate(this, + 0, + (5 + borderwidth + groupHeight + textHeight / 2)); + + groupHeight += textHeight; + }); + + opts._height = Math.max(opts._height, groupHeight); + }); + + opts._height += 10 + borderwidth * 2; + opts._width += borderwidth * 2; + } + else { + var rowHeight = 0, + maxTraceHeight = 0, + maxTraceWidth = 0, + offsetX = 0, + fullTracesWidth = 0, + traceGap = opts.tracegroupgap || 5, + oneRowLegend; + + // calculate largest width for traces and use for width of all legend items + traces.each(function(d) { + maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); + fullTracesWidth += 40 + d[0].width + traceGap; + }); + + // check if legend fits in one row + oneRowLegend = fullLayout._size.w > borderwidth + fullTracesWidth - traceGap; + traces.each(function(d) { + var legendItem = d[0], + traceWidth = oneRowLegend ? 40 + d[0].width : maxTraceWidth; + + if((borderwidth + offsetX + traceGap + traceWidth) > fullLayout._size.w) { + offsetX = 0; + rowHeight = rowHeight + maxTraceHeight; + opts._height = opts._height + maxTraceHeight; + // reset for next row + maxTraceHeight = 0; + } + + Drawing.setTranslate(this, + (borderwidth + offsetX), + (5 + borderwidth + legendItem.height / 2) + rowHeight); + + opts._width += traceGap + traceWidth; + opts._height = Math.max(opts._height, legendItem.height); + + // keep track of tallest trace in group + offsetX += traceGap + traceWidth; + maxTraceHeight = Math.max(legendItem.height, maxTraceHeight); + }); + + opts._width += borderwidth * 2; + opts._height += 10 + borderwidth * 2; + + } + + // make sure we're only getting full pixels + opts._width = Math.ceil(opts._width); + opts._height = Math.ceil(opts._height); + + var isEditable = ( + gd._context.edits.legendText || + gd._context.edits.legendPosition + ); + + traces.each(function(d) { + var legendItem = d[0]; + var bg = d3.select(this).select('.legendtoggle'); + + Drawing.setRect(bg, + 0, + -legendItem.height / 2, + (isEditable ? 0 : opts._width) + extraWidth, + legendItem.height + ); + }); +} + +function expandMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + xanchor = 'right'; + } + else if(anchorUtils.isCenterAnchor(opts)) { + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(opts)) { + yanchor = 'bottom'; + } + else if(anchorUtils.isMiddleAnchor(opts)) { + yanchor = 'middle'; + } + + // lastly check if the margin auto-expand has changed + Plots.autoMargin(gd, 'legend', { + x: opts.x, + y: opts.y, + l: opts._width * (FROM_TL[xanchor]), + r: opts._width * (FROM_BR[xanchor]), + b: opts._height * (FROM_BR[yanchor]), + t: opts._height * (FROM_TL[yanchor]) + }); +} + +function expandHorizontalMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + xanchor = 'right'; + } + else if(anchorUtils.isCenterAnchor(opts)) { + xanchor = 'center'; + } + + // lastly check if the margin auto-expand has changed + Plots.autoMargin(gd, 'legend', { + x: opts.x, + y: 0.5, + l: opts._width * (FROM_TL[xanchor]), + r: opts._width * (FROM_BR[xanchor]), + b: 0, + t: 0 + }); +} + +},{"../../constants/alignment":668,"../../constants/interactions":672,"../../lib":696,"../../lib/events":684,"../../lib/svg_text_utils":720,"../../plots/plots":808,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"./anchor_utils":622,"./constants":624,"./get_legend_data":627,"./handle_click":628,"./helpers":629,"./style":631,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],627:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var helpers = _dereq_('./helpers'); + + +module.exports = function getLegendData(calcdata, opts) { + var lgroupToTraces = {}, + lgroups = [], + hasOneNonBlankGroup = false, + slicesShown = {}, + lgroupi = 0; + + var i, j; + + function addOneItem(legendGroup, legendItem) { + // each '' legend group is treated as a separate group + if(legendGroup === '' || !helpers.isGrouped(opts)) { + var uniqueGroup = '~~i' + lgroupi; // TODO: check this against fullData legendgroups? + + lgroups.push(uniqueGroup); + lgroupToTraces[uniqueGroup] = [[legendItem]]; + lgroupi++; + } + else if(lgroups.indexOf(legendGroup) === -1) { + lgroups.push(legendGroup); + hasOneNonBlankGroup = true; + lgroupToTraces[legendGroup] = [[legendItem]]; + } + else lgroupToTraces[legendGroup].push([legendItem]); + } + + // build an { legendgroup: [cd0, cd0], ... } object + for(i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var cd0 = cd[0]; + var trace = cd0.trace; + var lgroup = trace.legendgroup; + + if(!trace.visible || !trace.showlegend) continue; + + if(Registry.traceIs(trace, 'pie')) { + if(!slicesShown[lgroup]) slicesShown[lgroup] = {}; + + for(j = 0; j < cd.length; j++) { + var labelj = cd[j].label; + + if(!slicesShown[lgroup][labelj]) { + addOneItem(lgroup, { + label: labelj, + color: cd[j].color, + i: cd[j].i, + trace: trace, + pts: cd[j].pts + }); + + slicesShown[lgroup][labelj] = true; + } + } + } + + else addOneItem(lgroup, cd0); + } + + // won't draw a legend in this case + if(!lgroups.length) return []; + + // rearrange lgroupToTraces into a d3-friendly array of arrays + var lgroupsLength = lgroups.length, + ltraces, + legendData; + + if(hasOneNonBlankGroup && helpers.isGrouped(opts)) { + legendData = new Array(lgroupsLength); + + for(i = 0; i < lgroupsLength; i++) { + ltraces = lgroupToTraces[lgroups[i]]; + legendData[i] = helpers.isReversed(opts) ? ltraces.reverse() : ltraces; + } + } + else { + // collapse all groups into one if all groups are blank + legendData = [new Array(lgroupsLength)]; + + for(i = 0; i < lgroupsLength; i++) { + ltraces = lgroupToTraces[lgroups[i]][0]; + legendData[0][helpers.isReversed(opts) ? lgroupsLength - i - 1 : i] = ltraces; + } + lgroupsLength = 1; + } + + // needed in repositionLegend + opts._lgroupsLength = lgroupsLength; + return legendData; +}; + +},{"../../registry":827,"./helpers":629}],628:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); + +var SHOWISOLATETIP = true; + +module.exports = function handleClick(g, gd, numClicks) { + if(gd._dragged || gd._editing) return; + + var hiddenSlices = gd._fullLayout.hiddenlabels ? + gd._fullLayout.hiddenlabels.slice() : + []; + + var legendItem = g.data()[0][0]; + var fullData = gd._fullData; + var fullTrace = legendItem.trace; + var legendgroup = fullTrace.legendgroup; + + var i, j, kcont, key, keys, val; + var attrUpdate = {}; + var attrIndices = []; + var carrs = []; + var carrIdx = []; + + function insertUpdate(traceIndex, key, value) { + var attrIndex = attrIndices.indexOf(traceIndex); + var valueArray = attrUpdate[key]; + if(!valueArray) { + valueArray = attrUpdate[key] = []; + } + + if(attrIndices.indexOf(traceIndex) === -1) { + attrIndices.push(traceIndex); + attrIndex = attrIndices.length - 1; + } + + valueArray[attrIndex] = value; + + return attrIndex; + } + + function setVisibility(fullTrace, visibility) { + var fullInput = fullTrace._fullInput; + if(Registry.hasTransform(fullInput, 'groupby')) { + var kcont = carrs[fullInput.index]; + if(!kcont) { + var groupbyIndices = Registry.getTransformIndices(fullInput, 'groupby'); + var lastGroupbyIndex = groupbyIndices[groupbyIndices.length - 1]; + kcont = Lib.keyedContainer(fullInput, 'transforms[' + lastGroupbyIndex + '].styles', 'target', 'value.visible'); + carrs[fullInput.index] = kcont; + } + + var curState = kcont.get(fullTrace._group); + + // If not specified, assume visible. This happens if there are other style + // properties set for a group but not the visibility. There are many similar + // ways to do this (e.g. why not just `curState = fullTrace.visible`??? The + // answer is: because it breaks other things like groupby trace names in + // subtle ways.) + if(curState === undefined) { + curState = true; + } + + if(curState !== false) { + // true -> legendonly. All others toggle to true: + kcont.set(fullTrace._group, visibility); + } + carrIdx[fullInput.index] = insertUpdate(fullInput.index, 'visible', fullInput.visible === false ? false : true); + } else { + // false -> false (not possible since will not be visible in legend) + // true -> legendonly + // legendonly -> true + var nextVisibility = fullInput.visible === false ? false : visibility; + + insertUpdate(fullInput.index, 'visible', nextVisibility); + } + } + + if(numClicks === 1 && SHOWISOLATETIP && gd.data && gd._context.showTips) { + Lib.notifier(Lib._(gd, 'Double-click on legend to isolate one trace'), 'long'); + SHOWISOLATETIP = false; + } else { + SHOWISOLATETIP = false; + } + + if(Registry.traceIs(fullTrace, 'pie')) { + var thisLabel = legendItem.label, + thisLabelIndex = hiddenSlices.indexOf(thisLabel); + + if(numClicks === 1) { + if(thisLabelIndex === -1) hiddenSlices.push(thisLabel); + else hiddenSlices.splice(thisLabelIndex, 1); + } else if(numClicks === 2) { + hiddenSlices = []; + gd.calcdata[0].forEach(function(d) { + if(thisLabel !== d.label) { + hiddenSlices.push(d.label); + } + }); + if(gd._fullLayout.hiddenlabels && gd._fullLayout.hiddenlabels.length === hiddenSlices.length && thisLabelIndex === -1) { + hiddenSlices = []; + } + } + + Registry.call('relayout', gd, 'hiddenlabels', hiddenSlices); + } else { + var hasLegendgroup = legendgroup && legendgroup.length; + var traceIndicesInGroup = []; + var tracei; + if(hasLegendgroup) { + for(i = 0; i < fullData.length; i++) { + tracei = fullData[i]; + if(!tracei.visible) continue; + if(tracei.legendgroup === legendgroup) { + traceIndicesInGroup.push(i); + } + } + } + + if(numClicks === 1) { + var nextVisibility; + + switch(fullTrace.visible) { + case true: + nextVisibility = 'legendonly'; + break; + case false: + nextVisibility = false; + break; + case 'legendonly': + nextVisibility = true; + break; + } + + if(hasLegendgroup) { + for(i = 0; i < fullData.length; i++) { + if(fullData[i].visible !== false && fullData[i].legendgroup === legendgroup) { + setVisibility(fullData[i], nextVisibility); + } + } + } else { + setVisibility(fullTrace, nextVisibility); + } + } else if(numClicks === 2) { + // Compute the clicked index. expandedIndex does what we want for expanded traces + // but also culls hidden traces. That means we have some work to do. + var isClicked, isInGroup, otherState; + var isIsolated = true; + for(i = 0; i < fullData.length; i++) { + isClicked = fullData[i] === fullTrace; + if(isClicked) continue; + + isInGroup = (hasLegendgroup && fullData[i].legendgroup === legendgroup); + + if(!isInGroup && fullData[i].visible === true && !Registry.traceIs(fullData[i], 'notLegendIsolatable')) { + isIsolated = false; + break; + } + } + + for(i = 0; i < fullData.length; i++) { + // False is sticky; we don't change it. + if(fullData[i].visible === false) continue; + + if(Registry.traceIs(fullData[i], 'notLegendIsolatable')) { + continue; + } + + switch(fullTrace.visible) { + case 'legendonly': + setVisibility(fullData[i], true); + break; + case true: + otherState = isIsolated ? true : 'legendonly'; + isClicked = fullData[i] === fullTrace; + isInGroup = isClicked || (hasLegendgroup && fullData[i].legendgroup === legendgroup); + setVisibility(fullData[i], isInGroup ? true : otherState); + break; + } + } + } + + for(i = 0; i < carrs.length; i++) { + kcont = carrs[i]; + if(!kcont) continue; + var update = kcont.constructUpdate(); + + var updateKeys = Object.keys(update); + for(j = 0; j < updateKeys.length; j++) { + key = updateKeys[j]; + val = attrUpdate[key] = attrUpdate[key] || []; + val[carrIdx[i]] = update[key]; + } + } + + // The length of the value arrays should be equal and any unspecified + // values should be explicitly undefined for them to get properly culled + // as updates and not accidentally reset to the default value. This fills + // out sparse arrays with the required number of undefined values: + keys = Object.keys(attrUpdate); + for(i = 0; i < keys.length; i++) { + key = keys[i]; + for(j = 0; j < attrIndices.length; j++) { + // Use hasOwnPropety to protect against falsey values: + if(!attrUpdate[key].hasOwnProperty(j)) { + attrUpdate[key][j] = undefined; + } + } + } + + Registry.call('restyle', gd, attrUpdate, attrIndices); + } +}; + +},{"../../lib":696,"../../registry":827}],629:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.isGrouped = function isGrouped(legendLayout) { + return (legendLayout.traceorder || '').indexOf('grouped') !== -1; +}; + +exports.isVertical = function isVertical(legendLayout) { + return legendLayout.orientation !== 'h'; +}; + +exports.isReversed = function isReversed(legendLayout) { + return (legendLayout.traceorder || '').indexOf('reversed') !== -1; +}; + +},{}],630:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + moduleType: 'component', + name: 'legend', + + layoutAttributes: _dereq_('./attributes'), + supplyLayoutDefaults: _dereq_('./defaults'), + + draw: _dereq_('./draw'), + style: _dereq_('./style') +}; + +},{"./attributes":623,"./defaults":625,"./draw":626,"./style":631}],631:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); + +var subTypes = _dereq_('../../traces/scatter/subtypes'); +var stylePie = _dereq_('../../traces/pie/style_one'); + +module.exports = function style(s, gd) { + s.each(function(d) { + var traceGroup = d3.select(this); + + var layers = Lib.ensureSingle(traceGroup, 'g', 'layers'); + layers.style('opacity', d[0].trace.opacity); + + var fill = layers + .selectAll('g.legendfill') + .data([d]); + fill.enter().append('g') + .classed('legendfill', true); + + var line = layers + .selectAll('g.legendlines') + .data([d]); + line.enter().append('g') + .classed('legendlines', true); + + var symbol = layers + .selectAll('g.legendsymbols') + .data([d]); + symbol.enter().append('g') + .classed('legendsymbols', true); + + symbol.selectAll('g.legendpoints') + .data([d]) + .enter().append('g') + .classed('legendpoints', true); + }) + .each(styleBars) + .each(styleBoxes) + .each(stylePies) + .each(styleLines) + .each(stylePoints) + .each(styleCandles) + .each(styleOHLC); + + function styleLines(d) { + var trace = d[0].trace; + var showFill = trace.visible && trace.fill && trace.fill !== 'none'; + var showLine = subTypes.hasLines(trace); + var contours = trace.contours; + var showGradientLine = false; + var showGradientFill = false; + + if(contours) { + var coloring = contours.coloring; + + if(coloring === 'lines') { + showGradientLine = true; + } + else { + showLine = coloring === 'none' || coloring === 'heatmap' || + contours.showlines; + } + + if(contours.type === 'constraint') { + showFill = contours._operation !== '='; + } + else if(coloring === 'fill' || coloring === 'heatmap') { + showGradientFill = true; + } + } + + // with fill and no markers or text, move the line and fill up a bit + // so it's more centered + var markersOrText = subTypes.hasMarkers(trace) || subTypes.hasText(trace); + var anyFill = showFill || showGradientFill; + var anyLine = showLine || showGradientLine; + var pathStart = (markersOrText || !anyFill) ? 'M5,0' : + // with a line leave it slightly below center, to leave room for the + // line thickness and because the line is usually more prominent + anyLine ? 'M5,-2' : 'M5,-3'; + + var this3 = d3.select(this); + + var fill = this3.select('.legendfill').selectAll('path') + .data(showFill || showGradientFill ? [d] : []); + fill.enter().append('path').classed('js-fill', true); + fill.exit().remove(); + fill.attr('d', pathStart + 'h30v6h-30z') + .call(showFill ? Drawing.fillGroupStyle : fillGradient); + + var line = this3.select('.legendlines').selectAll('path') + .data(showLine || showGradientLine ? [d] : []); + line.enter().append('path').classed('js-line', true); + line.exit().remove(); + + // this is ugly... but you can't apply a gradient to a perfectly + // horizontal or vertical line. Presumably because then + // the system doesn't know how to scale vertical variation, even + // though there *is* no vertical variation in this case. + // so add an invisibly small angle to the line + // This issue (and workaround) exist across (Mac) Chrome, FF, and Safari + line.attr('d', pathStart + (showGradientLine ? 'l30,0.0001' : 'h30')) + .call(showLine ? Drawing.lineGroupStyle : lineGradient); + + function fillGradient(s) { + if(s.size()) { + var gradientID = 'legendfill-' + trace.uid; + Drawing.gradient(s, gd, gradientID, 'horizontalreversed', + trace.colorscale, 'fill'); + } + } + + function lineGradient(s) { + if(s.size()) { + var gradientID = 'legendline-' + trace.uid; + Drawing.lineGroupStyle(s); + Drawing.gradient(s, gd, gradientID, 'horizontalreversed', + trace.colorscale, 'stroke'); + } + } + + } + + function stylePoints(d) { + var d0 = d[0]; + var trace = d0.trace; + var showMarkers = subTypes.hasMarkers(trace); + var showText = subTypes.hasText(trace); + var showLines = subTypes.hasLines(trace); + var dMod, tMod; + + // 'scatter3d' don't use gd.calcdata, + // use d0.trace to infer arrayOk attributes + + function boundVal(attrIn, arrayToValFn, bounds) { + var valIn = Lib.nestedProperty(trace, attrIn).get(); + var valToBound = (Lib.isArrayOrTypedArray(valIn) && arrayToValFn) ? + arrayToValFn(valIn) : + valIn; + + if(bounds) { + if(valToBound < bounds[0]) return bounds[0]; + else if(valToBound > bounds[1]) return bounds[1]; + } + return valToBound; + } + + function pickFirst(array) { return array[0]; } + + // constrain text, markers, etc so they'll fit on the legend + if(showMarkers || showText || showLines) { + var dEdit = {}; + var tEdit = {}; + + if(showMarkers) { + dEdit.mc = boundVal('marker.color', pickFirst); + dEdit.mx = boundVal('marker.symbol', pickFirst); + dEdit.mo = boundVal('marker.opacity', Lib.mean, [0.2, 1]); + dEdit.mlc = boundVal('marker.line.color', pickFirst); + dEdit.mlw = boundVal('marker.line.width', Lib.mean, [0, 5]); + tEdit.marker = { + sizeref: 1, + sizemin: 1, + sizemode: 'diameter' + }; + + var ms = boundVal('marker.size', Lib.mean, [2, 16]); + dEdit.ms = ms; + tEdit.marker.size = ms; + } + + if(showLines) { + tEdit.line = { + width: boundVal('line.width', pickFirst, [0, 10]) + }; + } + + if(showText) { + dEdit.tx = 'Aa'; + dEdit.tp = boundVal('textposition', pickFirst); + dEdit.ts = 10; + dEdit.tc = boundVal('textfont.color', pickFirst); + dEdit.tf = boundVal('textfont.family', pickFirst); + } + + dMod = [Lib.minExtend(d0, dEdit)]; + tMod = Lib.minExtend(trace, tEdit); + + // always show legend items in base state + tMod.selectedpoints = null; + } + + var ptgroup = d3.select(this).select('g.legendpoints'); + + var pts = ptgroup.selectAll('path.scatterpts') + .data(showMarkers ? dMod : []); + // make sure marker is on the bottom, in case it enters after text + pts.enter().insert('path', ':first-child') + .classed('scatterpts', true) + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + pts.call(Drawing.pointStyle, tMod, gd); + + // 'mrc' is set in pointStyle and used in textPointStyle: + // constrain it here + if(showMarkers) dMod[0].mrc = 3; + + var txt = ptgroup.selectAll('g.pointtext') + .data(showText ? dMod : []); + txt.enter() + .append('g').classed('pointtext', true) + .append('text').attr('transform', 'translate(20,0)'); + txt.exit().remove(); + txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd); + } + + function styleBars(d) { + var trace = d[0].trace, + marker = trace.marker || {}, + markerLine = marker.line || {}, + barpath = d3.select(this).select('g.legendpoints') + .selectAll('path.legendbar') + .data(Registry.traceIs(trace, 'bar') ? [d] : []); + barpath.enter().append('path').classed('legendbar', true) + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + barpath.exit().remove(); + barpath.each(function(d) { + var p = d3.select(this), + d0 = d[0], + w = (d0.mlw + 1 || markerLine.width + 1) - 1; + + p.style('stroke-width', w + 'px') + .call(Color.fill, d0.mc || marker.color); + + if(w) { + p.call(Color.stroke, d0.mlc || markerLine.color); + } + }); + } + + function styleBoxes(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendbox') + .data(Registry.traceIs(trace, 'box-violin') && trace.visible ? [d] : []); + pts.enter().append('path').classed('legendbox', true) + // if we want the median bar, prepend M6,0H-6 + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + pts.each(function() { + var w = trace.line.width, + p = d3.select(this); + + p.style('stroke-width', w + 'px') + .call(Color.fill, trace.fillcolor); + + if(w) { + Color.stroke(p, trace.line.color); + } + }); + } + + function styleCandles(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendcandle') + .data(trace.type === 'candlestick' && trace.visible ? [d, d] : []); + pts.enter().append('path').classed('legendcandle', true) + .attr('d', function(_, i) { + if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing + return 'M15,0H8M8,-6V6H-8Z'; // decreasing + }) + .attr('transform', 'translate(20,0)') + .style('stroke-miterlimit', 1); + pts.exit().remove(); + pts.each(function(_, i) { + var container = trace[i ? 'increasing' : 'decreasing']; + var w = container.line.width, + p = d3.select(this); + + p.style('stroke-width', w + 'px') + .call(Color.fill, container.fillcolor); + + if(w) { + Color.stroke(p, container.line.color); + } + }); + } + + function styleOHLC(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendohlc') + .data(trace.type === 'ohlc' && trace.visible ? [d, d] : []); + pts.enter().append('path').classed('legendohlc', true) + .attr('d', function(_, i) { + if(i) return 'M-15,0H0M-8,-6V0'; // increasing + return 'M15,0H0M8,6V0'; // decreasing + }) + .attr('transform', 'translate(20,0)') + .style('stroke-miterlimit', 1); + pts.exit().remove(); + pts.each(function(_, i) { + var container = trace[i ? 'increasing' : 'decreasing']; + var w = container.line.width, + p = d3.select(this); + + p.style('fill', 'none') + .call(Drawing.dashLine, container.line.dash, w); + + if(w) { + Color.stroke(p, container.line.color); + } + }); + } + + function stylePies(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendpie') + .data(Registry.traceIs(trace, 'pie') && trace.visible ? [d] : []); + pts.enter().append('path').classed('legendpie', true) + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + + if(pts.size()) pts.call(stylePie, d[0], trace); + } +}; + +},{"../../lib":696,"../../registry":827,"../../traces/pie/style_one":1029,"../../traces/scatter/subtypes":1067,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],632:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Plots = _dereq_('../../plots/plots'); +var axisIds = _dereq_('../../plots/cartesian/axis_ids'); +var Lib = _dereq_('../../lib'); +var Icons = _dereq_('../../../build/ploticon'); + +var _ = Lib._; + +var modeBarButtons = module.exports = {}; + +/** + * ModeBar buttons configuration + * + * @param {string} name + * name / id of the buttons (for tracking) + * @param {string} title + * text that appears while hovering over the button, + * enter null, false or '' for no hover text + * @param {string} icon + * svg icon object associated with the button + * can be linked to Plotly.Icons to use the default plotly icons + * @param {string} [gravity] + * icon positioning + * @param {function} click + * click handler associated with the button, a function of + * 'gd' (the main graph object) and + * 'ev' (the event object) + * @param {string} [attr] + * attribute associated with button, + * use this with 'val' to keep track of the state + * @param {*} [val] + * initial 'attr' value, can be a function of gd + * @param {boolean} [toggle] + * is the button a toggle button? + */ + +modeBarButtons.toImage = { + name: 'toImage', + title: function(gd) { + var opts = gd._context.toImageButtonOptions || {}; + var format = opts.format || 'png'; + return format === 'png' ? + _(gd, 'Download plot as a png') : // legacy text + _(gd, 'Download plot'); // generic non-PNG text + }, + icon: Icons.camera, + click: function(gd) { + var toImageButtonOptions = gd._context.toImageButtonOptions; + var opts = {format: toImageButtonOptions.format || 'png'}; + + Lib.notifier(_(gd, 'Taking snapshot - this may take a few seconds'), 'long'); + + if(opts.format !== 'svg' && Lib.isIE()) { + Lib.notifier(_(gd, 'IE only supports svg. Changing format to svg.'), 'long'); + opts.format = 'svg'; + } + + ['filename', 'width', 'height', 'scale'].forEach(function(key) { + if(toImageButtonOptions[key]) { + opts[key] = toImageButtonOptions[key]; + } + }); + + Registry.call('downloadImage', gd, opts) + .then(function(filename) { + Lib.notifier(_(gd, 'Snapshot succeeded') + ' - ' + filename, 'long'); + }) + .catch(function() { + Lib.notifier(_(gd, 'Sorry, there was a problem downloading your snapshot!'), 'long'); + }); + } +}; + +modeBarButtons.sendDataToCloud = { + name: 'sendDataToCloud', + title: function(gd) { return _(gd, 'Edit in Chart Studio'); }, + icon: Icons.disk, + click: function(gd) { + Plots.sendDataToCloud(gd); + } +}; + +modeBarButtons.zoom2d = { + name: 'zoom2d', + title: function(gd) { return _(gd, 'Zoom'); }, + attr: 'dragmode', + val: 'zoom', + icon: Icons.zoombox, + click: handleCartesian +}; + +modeBarButtons.pan2d = { + name: 'pan2d', + title: function(gd) { return _(gd, 'Pan'); }, + attr: 'dragmode', + val: 'pan', + icon: Icons.pan, + click: handleCartesian +}; + +modeBarButtons.select2d = { + name: 'select2d', + title: function(gd) { return _(gd, 'Box Select'); }, + attr: 'dragmode', + val: 'select', + icon: Icons.selectbox, + click: handleCartesian +}; + +modeBarButtons.lasso2d = { + name: 'lasso2d', + title: function(gd) { return _(gd, 'Lasso Select'); }, + attr: 'dragmode', + val: 'lasso', + icon: Icons.lasso, + click: handleCartesian +}; + +modeBarButtons.zoomIn2d = { + name: 'zoomIn2d', + title: function(gd) { return _(gd, 'Zoom in'); }, + attr: 'zoom', + val: 'in', + icon: Icons.zoom_plus, + click: handleCartesian +}; + +modeBarButtons.zoomOut2d = { + name: 'zoomOut2d', + title: function(gd) { return _(gd, 'Zoom out'); }, + attr: 'zoom', + val: 'out', + icon: Icons.zoom_minus, + click: handleCartesian +}; + +modeBarButtons.autoScale2d = { + name: 'autoScale2d', + title: function(gd) { return _(gd, 'Autoscale'); }, + attr: 'zoom', + val: 'auto', + icon: Icons.autoscale, + click: handleCartesian +}; + +modeBarButtons.resetScale2d = { + name: 'resetScale2d', + title: function(gd) { return _(gd, 'Reset axes'); }, + attr: 'zoom', + val: 'reset', + icon: Icons.home, + click: handleCartesian +}; + +modeBarButtons.hoverClosestCartesian = { + name: 'hoverClosestCartesian', + title: function(gd) { return _(gd, 'Show closest data on hover'); }, + attr: 'hovermode', + val: 'closest', + icon: Icons.tooltip_basic, + gravity: 'ne', + click: handleCartesian +}; + +modeBarButtons.hoverCompareCartesian = { + name: 'hoverCompareCartesian', + title: function(gd) { return _(gd, 'Compare data on hover'); }, + attr: 'hovermode', + val: function(gd) { + return gd._fullLayout._isHoriz ? 'y' : 'x'; + }, + icon: Icons.tooltip_compare, + gravity: 'ne', + click: handleCartesian +}; + +function handleCartesian(gd, ev) { + var button = ev.currentTarget; + var astr = button.getAttribute('data-attr'); + var val = button.getAttribute('data-val') || true; + var fullLayout = gd._fullLayout; + var aobj = {}; + var axList = axisIds.list(gd, null, true); + var allSpikesEnabled = 'on'; + + var ax, i; + + if(astr === 'zoom') { + var mag = (val === 'in') ? 0.5 : 2, + r0 = (1 + mag) / 2, + r1 = (1 - mag) / 2; + + var axName; + + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + + if(!ax.fixedrange) { + axName = ax._name; + if(val === 'auto') aobj[axName + '.autorange'] = true; + else if(val === 'reset') { + if(ax._rangeInitial === undefined) { + aobj[axName + '.autorange'] = true; + } + else { + var rangeInitial = ax._rangeInitial.slice(); + aobj[axName + '.range[0]'] = rangeInitial[0]; + aobj[axName + '.range[1]'] = rangeInitial[1]; + } + if(ax._showSpikeInitial !== undefined) { + aobj[axName + '.showspikes'] = ax._showSpikeInitial; + if(allSpikesEnabled === 'on' && !ax._showSpikeInitial) { + allSpikesEnabled = 'off'; + } + } + } + else { + var rangeNow = [ + ax.r2l(ax.range[0]), + ax.r2l(ax.range[1]), + ]; + + var rangeNew = [ + r0 * rangeNow[0] + r1 * rangeNow[1], + r0 * rangeNow[1] + r1 * rangeNow[0] + ]; + + aobj[axName + '.range[0]'] = ax.l2r(rangeNew[0]); + aobj[axName + '.range[1]'] = ax.l2r(rangeNew[1]); + } + } + } + fullLayout._cartesianSpikesEnabled = allSpikesEnabled; + } + else { + // if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y' + if(astr === 'hovermode' && (val === 'x' || val === 'y')) { + val = fullLayout._isHoriz ? 'y' : 'x'; + button.setAttribute('data-val', val); + } else if(astr === 'hovermode' && val === 'closest') { + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + if(allSpikesEnabled === 'on' && !ax.showspikes) { + allSpikesEnabled = 'off'; + } + } + fullLayout._cartesianSpikesEnabled = allSpikesEnabled; + } + + aobj[astr] = val; + } + + Registry.call('relayout', gd, aobj); +} + +modeBarButtons.zoom3d = { + name: 'zoom3d', + title: function(gd) { return _(gd, 'Zoom'); }, + attr: 'scene.dragmode', + val: 'zoom', + icon: Icons.zoombox, + click: handleDrag3d +}; + +modeBarButtons.pan3d = { + name: 'pan3d', + title: function(gd) { return _(gd, 'Pan'); }, + attr: 'scene.dragmode', + val: 'pan', + icon: Icons.pan, + click: handleDrag3d +}; + +modeBarButtons.orbitRotation = { + name: 'orbitRotation', + title: function(gd) { return _(gd, 'Orbital rotation'); }, + attr: 'scene.dragmode', + val: 'orbit', + icon: Icons['3d_rotate'], + click: handleDrag3d +}; + +modeBarButtons.tableRotation = { + name: 'tableRotation', + title: function(gd) { return _(gd, 'Turntable rotation'); }, + attr: 'scene.dragmode', + val: 'turntable', + icon: Icons['z-axis'], + click: handleDrag3d +}; + +function handleDrag3d(gd, ev) { + var button = ev.currentTarget; + var attr = button.getAttribute('data-attr'); + var val = button.getAttribute('data-val') || true; + var sceneIds = gd._fullLayout._subplots.gl3d; + var layoutUpdate = {}; + + var parts = attr.split('.'); + + for(var i = 0; i < sceneIds.length; i++) { + layoutUpdate[sceneIds[i] + '.' + parts[1]] = val; + } + + // for multi-type subplots + var val2d = (val === 'pan') ? val : 'zoom'; + layoutUpdate.dragmode = val2d; + + Registry.call('relayout', gd, layoutUpdate); +} + +modeBarButtons.resetCameraDefault3d = { + name: 'resetCameraDefault3d', + title: function(gd) { return _(gd, 'Reset camera to default'); }, + attr: 'resetDefault', + icon: Icons.home, + click: handleCamera3d +}; + +modeBarButtons.resetCameraLastSave3d = { + name: 'resetCameraLastSave3d', + title: function(gd) { return _(gd, 'Reset camera to last save'); }, + attr: 'resetLastSave', + icon: Icons.movie, + click: handleCamera3d +}; + +function handleCamera3d(gd, ev) { + var button = ev.currentTarget; + var attr = button.getAttribute('data-attr'); + var fullLayout = gd._fullLayout; + var sceneIds = fullLayout._subplots.gl3d; + var aobj = {}; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i], + key = sceneId + '.camera', + scene = fullLayout[sceneId]._scene; + + if(attr === 'resetDefault') { + aobj[key] = null; + } + else if(attr === 'resetLastSave') { + aobj[key] = Lib.extendDeep({}, scene.cameraInitial); + } + } + + Registry.call('relayout', gd, aobj); +} + +modeBarButtons.hoverClosest3d = { + name: 'hoverClosest3d', + title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: handleHover3d +}; + +function handleHover3d(gd, ev) { + var button = ev.currentTarget; + var val = button._previousVal || false; + var layout = gd.layout; + var fullLayout = gd._fullLayout; + var sceneIds = fullLayout._subplots.gl3d; + + var axes = ['xaxis', 'yaxis', 'zaxis']; + var spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor']; + + // initialize 'current spike' object to be stored in the DOM + var currentSpikes = {}; + var axisSpikes = {}; + var layoutUpdate = {}; + + if(val) { + layoutUpdate = Lib.extendDeep(layout, val); + button._previousVal = null; + } + else { + layoutUpdate = { + 'allaxes.showspikes': false + }; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i], + sceneLayout = fullLayout[sceneId], + sceneSpikes = currentSpikes[sceneId] = {}; + + sceneSpikes.hovermode = sceneLayout.hovermode; + layoutUpdate[sceneId + '.hovermode'] = false; + + // copy all the current spike attrs + for(var j = 0; j < 3; j++) { + var axis = axes[j]; + axisSpikes = sceneSpikes[axis] = {}; + + for(var k = 0; k < spikeAttrs.length; k++) { + var spikeAttr = spikeAttrs[k]; + axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr]; + } + } + } + + button._previousVal = Lib.extendDeep({}, currentSpikes); + } + + Registry.call('relayout', gd, layoutUpdate); +} + +modeBarButtons.zoomInGeo = { + name: 'zoomInGeo', + title: function(gd) { return _(gd, 'Zoom in'); }, + attr: 'zoom', + val: 'in', + icon: Icons.zoom_plus, + click: handleGeo +}; + +modeBarButtons.zoomOutGeo = { + name: 'zoomOutGeo', + title: function(gd) { return _(gd, 'Zoom out'); }, + attr: 'zoom', + val: 'out', + icon: Icons.zoom_minus, + click: handleGeo +}; + +modeBarButtons.resetGeo = { + name: 'resetGeo', + title: function(gd) { return _(gd, 'Reset'); }, + attr: 'reset', + val: null, + icon: Icons.autoscale, + click: handleGeo +}; + +modeBarButtons.hoverClosestGeo = { + name: 'hoverClosestGeo', + title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +function handleGeo(gd, ev) { + var button = ev.currentTarget; + var attr = button.getAttribute('data-attr'); + var val = button.getAttribute('data-val') || true; + var fullLayout = gd._fullLayout; + var geoIds = fullLayout._subplots.geo; + + for(var i = 0; i < geoIds.length; i++) { + var id = geoIds[i]; + var geoLayout = fullLayout[id]; + + if(attr === 'zoom') { + var scale = geoLayout.projection.scale; + var newScale = (val === 'in') ? 2 * scale : 0.5 * scale; + + Registry.call('relayout', gd, id + '.projection.scale', newScale); + } else if(attr === 'reset') { + resetView(gd, 'geo'); + } + } +} + +modeBarButtons.hoverClosestGl2d = { + name: 'hoverClosestGl2d', + title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +modeBarButtons.hoverClosestPie = { + name: 'hoverClosestPie', + title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, + attr: 'hovermode', + val: 'closest', + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +function toggleHover(gd) { + var fullLayout = gd._fullLayout; + + var onHoverVal; + if(fullLayout._has('cartesian')) { + onHoverVal = fullLayout._isHoriz ? 'y' : 'x'; + } + else onHoverVal = 'closest'; + + var newHover = gd._fullLayout.hovermode ? false : onHoverVal; + + Registry.call('relayout', gd, 'hovermode', newHover); +} + +// buttons when more then one plot types are present + +modeBarButtons.toggleHover = { + name: 'toggleHover', + title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: function(gd, ev) { + toggleHover(gd); + + // the 3d hovermode update must come + // last so that layout.hovermode update does not + // override scene?.hovermode?.layout. + handleHover3d(gd, ev); + } +}; + +modeBarButtons.resetViews = { + name: 'resetViews', + title: function(gd) { return _(gd, 'Reset views'); }, + icon: Icons.home, + click: function(gd, ev) { + var button = ev.currentTarget; + + button.setAttribute('data-attr', 'zoom'); + button.setAttribute('data-val', 'reset'); + handleCartesian(gd, ev); + + button.setAttribute('data-attr', 'resetLastSave'); + handleCamera3d(gd, ev); + + resetView(gd, 'geo'); + resetView(gd, 'mapbox'); + } +}; + +modeBarButtons.toggleSpikelines = { + name: 'toggleSpikelines', + title: function(gd) { return _(gd, 'Toggle Spike Lines'); }, + icon: Icons.spikeline, + attr: '_cartesianSpikesEnabled', + val: 'on', + click: function(gd) { + var fullLayout = gd._fullLayout; + + fullLayout._cartesianSpikesEnabled = fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on'; + + var aobj = setSpikelineVisibility(gd); + + Registry.call('relayout', gd, aobj); + } +}; + +function setSpikelineVisibility(gd) { + var fullLayout = gd._fullLayout; + var axList = axisIds.list(gd, null, true); + var aobj = {}; + + var ax, axName; + + for(var i = 0; i < axList.length; i++) { + ax = axList[i]; + axName = ax._name; + aobj[axName + '.showspikes'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : ax._showSpikeInitial; + } + + return aobj; +} + +modeBarButtons.resetViewMapbox = { + name: 'resetViewMapbox', + title: function(gd) { return _(gd, 'Reset view'); }, + attr: 'reset', + icon: Icons.home, + click: function(gd) { + resetView(gd, 'mapbox'); + } +}; + +function resetView(gd, subplotType) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots[subplotType]; + var aObj = {}; + + for(var i = 0; i < subplotIds.length; i++) { + var id = subplotIds[i]; + var subplotObj = fullLayout[id]._subplot; + var viewInitial = subplotObj.viewInitial; + var viewKeys = Object.keys(viewInitial); + + for(var j = 0; j < viewKeys.length; j++) { + var key = viewKeys[j]; + aObj[id + '.' + key] = viewInitial[key]; + } + } + + Registry.call('relayout', gd, aObj); +} + +},{"../../../build/ploticon":2,"../../lib":696,"../../plots/cartesian/axis_ids":747,"../../plots/plots":808,"../../registry":827}],633:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.manage = _dereq_('./manage'); + +},{"./manage":634}],634:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var axisIds = _dereq_('../../plots/cartesian/axis_ids'); +var scatterSubTypes = _dereq_('../../traces/scatter/subtypes'); +var Registry = _dereq_('../../registry'); + +var createModeBar = _dereq_('./modebar'); +var modeBarButtons = _dereq_('./buttons'); + +/** + * ModeBar wrapper around 'create' and 'update', + * chooses buttons to pass to ModeBar constructor based on + * plot type and plot config. + * + * @param {object} gd main plot object + * + */ +module.exports = function manageModeBar(gd) { + var fullLayout = gd._fullLayout, + context = gd._context, + modeBar = fullLayout._modeBar; + + if(!context.displayModeBar) { + if(modeBar) { + modeBar.destroy(); + delete fullLayout._modeBar; + } + return; + } + + if(!Array.isArray(context.modeBarButtonsToRemove)) { + throw new Error([ + '*modeBarButtonsToRemove* configuration options', + 'must be an array.' + ].join(' ')); + } + + if(!Array.isArray(context.modeBarButtonsToAdd)) { + throw new Error([ + '*modeBarButtonsToAdd* configuration options', + 'must be an array.' + ].join(' ')); + } + + var customButtons = context.modeBarButtons; + var buttonGroups; + + if(Array.isArray(customButtons) && customButtons.length) { + buttonGroups = fillCustomButton(customButtons); + } + else { + buttonGroups = getButtonGroups( + gd, + context.modeBarButtonsToRemove, + context.modeBarButtonsToAdd + ); + } + + if(modeBar) modeBar.update(gd, buttonGroups); + else fullLayout._modeBar = createModeBar(gd, buttonGroups); +}; + +// logic behind which buttons are displayed by default +function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { + var fullLayout = gd._fullLayout; + var fullData = gd._fullData; + + var hasCartesian = fullLayout._has('cartesian'); + var hasGL3D = fullLayout._has('gl3d'); + var hasGeo = fullLayout._has('geo'); + var hasPie = fullLayout._has('pie'); + var hasGL2D = fullLayout._has('gl2d'); + var hasTernary = fullLayout._has('ternary'); + var hasMapbox = fullLayout._has('mapbox'); + var hasPolar = fullLayout._has('polar'); + var allAxesFixed = areAllAxesFixed(fullLayout); + + var groups = []; + + function addGroup(newGroup) { + if(!newGroup.length) return; + + var out = []; + + for(var i = 0; i < newGroup.length; i++) { + var button = newGroup[i]; + if(buttonsToRemove.indexOf(button) !== -1) continue; + out.push(modeBarButtons[button]); + } + + groups.push(out); + } + + // buttons common to all plot types + addGroup(['toImage', 'sendDataToCloud']); + + var zoomGroup = []; + var hoverGroup = []; + var resetGroup = []; + var dragModeGroup = []; + + if((hasCartesian || hasGL2D || hasPie || hasTernary) + hasGeo + hasGL3D + hasMapbox + hasPolar > 1) { + // graphs with more than one plot types get 'union buttons' + // which reset the view or toggle hover labels across all subplots. + hoverGroup = ['toggleHover']; + resetGroup = ['resetViews']; + } + else if(hasGeo) { + zoomGroup = ['zoomInGeo', 'zoomOutGeo']; + hoverGroup = ['hoverClosestGeo']; + resetGroup = ['resetGeo']; + } + else if(hasGL3D) { + hoverGroup = ['hoverClosest3d']; + resetGroup = ['resetCameraDefault3d', 'resetCameraLastSave3d']; + } + else if(hasMapbox) { + hoverGroup = ['toggleHover']; + resetGroup = ['resetViewMapbox']; + } + else if(hasGL2D) { + hoverGroup = ['hoverClosestGl2d']; + } + else if(hasPie) { + hoverGroup = ['hoverClosestPie']; + } + else { // hasPolar, hasTernary + // always show at least one hover icon. + hoverGroup = ['toggleHover']; + } + // if we have cartesian, allow switching between closest and compare + // regardless of what other types are on the plot, since they'll all + // just treat any truthy hovermode as 'closest' + if(hasCartesian) { + hoverGroup = ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian']; + } + + if((hasCartesian || hasGL2D) && !allAxesFixed) { + zoomGroup = ['zoomIn2d', 'zoomOut2d', 'autoScale2d']; + if(resetGroup[0] !== 'resetViews') resetGroup = ['resetScale2d']; + } + + if(hasGL3D) { + dragModeGroup = ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation']; + } + else if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) { + dragModeGroup = ['zoom2d', 'pan2d']; + } + else if(hasMapbox || hasGeo) { + dragModeGroup = ['pan2d']; + } + else if(hasPolar) { + dragModeGroup = ['zoom2d']; + } + if(isSelectable(fullData)) { + dragModeGroup.push('select2d', 'lasso2d'); + } + + addGroup(dragModeGroup); + addGroup(zoomGroup.concat(resetGroup)); + addGroup(hoverGroup); + + return appendButtonsToGroups(groups, buttonsToAdd); +} + +function areAllAxesFixed(fullLayout) { + var axList = axisIds.list({_fullLayout: fullLayout}, null, true); + + for(var i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) { + return false; + } + } + + return true; +} + +// look for traces that support selection +// to be updated as we add more selectPoints handlers +function isSelectable(fullData) { + var selectable = false; + + for(var i = 0; i < fullData.length; i++) { + if(selectable) break; + + var trace = fullData[i]; + + if(!trace._module || !trace._module.selectPoints) continue; + + if(Registry.traceIs(trace, 'scatter-like')) { + if(scatterSubTypes.hasMarkers(trace) || scatterSubTypes.hasText(trace)) { + selectable = true; + } + } else if(Registry.traceIs(trace, 'box-violin')) { + if(trace.boxpoints === 'all' || trace.points === 'all') { + selectable = true; + } + } + // assume that in general if the trace module has selectPoints, + // then it's selectable. Scatter is an exception to this because it must + // have markers or text, not just be a scatter type. + else selectable = true; + } + + return selectable; +} + +function appendButtonsToGroups(groups, buttons) { + if(buttons.length) { + if(Array.isArray(buttons[0])) { + for(var i = 0; i < buttons.length; i++) { + groups.push(buttons[i]); + } + } + else groups.push(buttons); + } + + return groups; +} + +// fill in custom buttons referring to default mode bar buttons +function fillCustomButton(customButtons) { + for(var i = 0; i < customButtons.length; i++) { + var buttonGroup = customButtons[i]; + + for(var j = 0; j < buttonGroup.length; j++) { + var button = buttonGroup[j]; + + if(typeof button === 'string') { + if(modeBarButtons[button] !== undefined) { + customButtons[i][j] = modeBarButtons[button]; + } + else { + throw new Error([ + '*modeBarButtons* configuration options', + 'invalid button name' + ].join(' ')); + } + } + } + } + + return customButtons; +} + +},{"../../plots/cartesian/axis_ids":747,"../../registry":827,"../../traces/scatter/subtypes":1067,"./buttons":632,"./modebar":635}],635:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var Icons = _dereq_('../../../build/ploticon'); +var Parser = new DOMParser(); + +/** + * UI controller for interactive plots + * @Class + * @Param {object} opts + * @Param {object} opts.buttons nested arrays of grouped buttons config objects + * @Param {object} opts.container container div to append modeBar + * @Param {object} opts.graphInfo primary plot object containing data and layout + */ +function ModeBar(opts) { + this.container = opts.container; + this.element = document.createElement('div'); + + this.update(opts.graphInfo, opts.buttons); + + this.container.appendChild(this.element); +} + +var proto = ModeBar.prototype; + +/** + * Update modeBar (buttons and logo) + * + * @param {object} graphInfo primary plot object containing data and layout + * @param {array of arrays} buttons nested arrays of grouped buttons to initialize + * + */ +proto.update = function(graphInfo, buttons) { + this.graphInfo = graphInfo; + + var context = this.graphInfo._context, + fullLayout = this.graphInfo._fullLayout, + modeBarId = 'modebar-' + fullLayout._uid; + + this.element.setAttribute('id', modeBarId); + this._uid = modeBarId; + + if(context.displayModeBar === 'hover') { + this.element.className = 'modebar modebar--hover'; + } + else this.element.className = 'modebar'; + + if(fullLayout.modebar.orientation === 'v') { + this.element.className += ' vertical'; + buttons = buttons.reverse(); + } + + Lib.deleteRelatedStyleRule(modeBarId); + Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId, 'background-color: ' + fullLayout.modebar.bgcolor); + Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn .icon path', 'fill: ' + fullLayout.modebar.color); + Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn:hover .icon path', 'fill: ' + fullLayout.modebar.activecolor); + Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn.active .icon path', 'fill: ' + fullLayout.modebar.activecolor); + + // if buttons or logo have changed, redraw modebar interior + var needsNewButtons = !this.hasButtons(buttons); + var needsNewLogo = (this.hasLogo !== context.displaylogo); + var needsNewLocale = (this.locale !== context.locale); + + this.locale = context.locale; + + if(needsNewButtons || needsNewLogo || needsNewLocale) { + this.removeAllButtons(); + + this.updateButtons(buttons); + + if(context.displaylogo) { + if(fullLayout.modebar.orientation === 'v') { + this.element.prepend(this.getLogo()); + } else { + this.element.appendChild(this.getLogo()); + } + + this.hasLogo = true; + } + } + + this.updateActiveButton(); +}; + +proto.updateButtons = function(buttons) { + var _this = this; + + this.buttons = buttons; + this.buttonElements = []; + this.buttonsNames = []; + + this.buttons.forEach(function(buttonGroup) { + var group = _this.createGroup(); + + buttonGroup.forEach(function(buttonConfig) { + var buttonName = buttonConfig.name; + if(!buttonName) { + throw new Error('must provide button \'name\' in button config'); + } + if(_this.buttonsNames.indexOf(buttonName) !== -1) { + throw new Error('button name \'' + buttonName + '\' is taken'); + } + _this.buttonsNames.push(buttonName); + + var button = _this.createButton(buttonConfig); + _this.buttonElements.push(button); + group.appendChild(button); + }); + + _this.element.appendChild(group); + }); +}; + +/** + * Empty div for containing a group of buttons + * @Return {HTMLelement} + */ +proto.createGroup = function() { + var group = document.createElement('div'); + group.className = 'modebar-group'; + + return group; +}; + +/** + * Create a new button div and set constant and configurable attributes + * @Param {object} config (see ./buttons.js for more info) + * @Return {HTMLelement} + */ +proto.createButton = function(config) { + var _this = this, + button = document.createElement('a'); + + button.setAttribute('rel', 'tooltip'); + button.className = 'modebar-btn'; + + var title = config.title; + if(title === undefined) title = config.name; + // for localization: allow title to be a callable that takes gd as arg + else if(typeof title === 'function') title = title(this.graphInfo); + + if(title || title === 0) button.setAttribute('data-title', title); + + if(config.attr !== undefined) button.setAttribute('data-attr', config.attr); + + var val = config.val; + if(val !== undefined) { + if(typeof val === 'function') val = val(this.graphInfo); + button.setAttribute('data-val', val); + } + + var click = config.click; + if(typeof click !== 'function') { + throw new Error('must provide button \'click\' function in button config'); + } + else { + button.addEventListener('click', function(ev) { + config.click(_this.graphInfo, ev); + + // only needed for 'hoverClosestGeo' which does not call relayout + _this.updateActiveButton(ev.currentTarget); + }); + } + + button.setAttribute('data-toggle', config.toggle || false); + if(config.toggle) d3.select(button).classed('active', true); + + var icon = config.icon; + if(typeof icon === 'function') { + button.appendChild(icon()); + } + else { + button.appendChild(this.createIcon(icon || Icons.question)); + } + button.setAttribute('data-gravity', config.gravity || 'n'); + + return button; +}; + +/** + * Add an icon to a button + * @Param {object} thisIcon + * @Param {number} thisIcon.width + * @Param {string} thisIcon.path + * @Param {string} thisIcon.color + * @Return {HTMLelement} + */ +proto.createIcon = function(thisIcon) { + var iconHeight = isNumeric(thisIcon.height) ? + Number(thisIcon.height) : + thisIcon.ascent - thisIcon.descent, + svgNS = 'http://www.w3.org/2000/svg', + icon; + + if(thisIcon.path) { + icon = document.createElementNS(svgNS, 'svg'); + icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' ')); + icon.setAttribute('class', 'icon'); + + var path = document.createElementNS(svgNS, 'path'); + path.setAttribute('d', thisIcon.path); + + if(thisIcon.transform) { + path.setAttribute('transform', thisIcon.transform); + } + else if(thisIcon.ascent !== undefined) { + // Legacy icon transform calculation + path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')'); + } + + icon.appendChild(path); + } + + if(thisIcon.svg) { + var svgDoc = Parser.parseFromString(thisIcon.svg, 'application/xml'); + icon = svgDoc.childNodes[0]; + } + + icon.setAttribute('height', '1em'); + icon.setAttribute('width', '1em'); + + return icon; +}; + +/** + * Updates active button with attribute specified in layout + * @Param {object} graphInfo plot object containing data and layout + * @Return {HTMLelement} + */ +proto.updateActiveButton = function(buttonClicked) { + var fullLayout = this.graphInfo._fullLayout, + dataAttrClicked = (buttonClicked !== undefined) ? + buttonClicked.getAttribute('data-attr') : + null; + + this.buttonElements.forEach(function(button) { + var thisval = button.getAttribute('data-val') || true, + dataAttr = button.getAttribute('data-attr'), + isToggleButton = (button.getAttribute('data-toggle') === 'true'), + button3 = d3.select(button); + + // Use 'data-toggle' and 'buttonClicked' to toggle buttons + // that have no one-to-one equivalent in fullLayout + if(isToggleButton) { + if(dataAttr === dataAttrClicked) { + button3.classed('active', !button3.classed('active')); + } + } + else { + var val = (dataAttr === null) ? + dataAttr : + Lib.nestedProperty(fullLayout, dataAttr).get(); + + button3.classed('active', val === thisval); + } + + }); +}; + +/** + * Check if modeBar is configured as button configuration argument + * + * @Param {object} buttons 2d array of grouped button config objects + * @Return {boolean} + */ +proto.hasButtons = function(buttons) { + var currentButtons = this.buttons; + + if(!currentButtons) return false; + + if(buttons.length !== currentButtons.length) return false; + + for(var i = 0; i < buttons.length; ++i) { + if(buttons[i].length !== currentButtons[i].length) return false; + for(var j = 0; j < buttons[i].length; j++) { + if(buttons[i][j].name !== currentButtons[i][j].name) return false; + } + } + + return true; +}; + +/** + * @return {HTMLDivElement} The logo image wrapped in a group + */ +proto.getLogo = function() { + var group = this.createGroup(), + a = document.createElement('a'); + + a.href = 'https://plot.ly/'; + a.target = '_blank'; + a.setAttribute('data-title', Lib._(this.graphInfo, 'Produced with Plotly')); + a.className = 'modebar-btn plotlyjsicon modebar-btn--logo'; + + a.appendChild(this.createIcon(Icons.newplotlylogo)); + + group.appendChild(a); + return group; +}; + +proto.removeAllButtons = function() { + while(this.element.firstChild) { + this.element.removeChild(this.element.firstChild); + } + + this.hasLogo = false; +}; + +proto.destroy = function() { + Lib.removeElement(this.container.querySelector('.modebar')); + Lib.deleteRelatedStyleRule(this._uid); +}; + +function createModeBar(gd, buttons) { + var fullLayout = gd._fullLayout; + + var modeBar = new ModeBar({ + graphInfo: gd, + container: fullLayout._paperdiv.node(), + buttons: buttons + }); + + if(fullLayout._privateplot) { + d3.select(modeBar.element).append('span') + .classed('badge-private float--left', true) + .text('PRIVATE'); + } + + return modeBar; +} + +module.exports = createModeBar; + +},{"../../../build/ploticon":2,"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],636:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var colorAttrs = _dereq_('../color/attributes'); +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +var buttonAttrs = templatedArray('button', { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'plot', + + }, + step: { + valType: 'enumerated', + + values: ['month', 'year', 'day', 'hour', 'minute', 'second', 'all'], + dflt: 'month', + editType: 'plot', + + }, + stepmode: { + valType: 'enumerated', + + values: ['backward', 'todate'], + dflt: 'backward', + editType: 'plot', + + }, + count: { + valType: 'number', + + min: 0, + dflt: 1, + editType: 'plot', + + }, + label: { + valType: 'string', + + editType: 'plot', + + }, + editType: 'plot', + +}); + +module.exports = { + visible: { + valType: 'boolean', + + editType: 'plot', + + }, + + buttons: buttonAttrs, + + x: { + valType: 'number', + min: -2, + max: 3, + + editType: 'plot', + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + editType: 'plot', + + }, + y: { + valType: 'number', + min: -2, + max: 3, + + editType: 'plot', + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'bottom', + + editType: 'plot', + + }, + + font: fontAttrs({ + editType: 'plot', + + }), + + bgcolor: { + valType: 'color', + dflt: colorAttrs.lightLine, + + editType: 'plot', + + }, + activecolor: { + valType: 'color', + + editType: 'plot', + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'plot', + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'plot', + + }, + editType: 'plot' +}; + +},{"../../plot_api/plot_template":734,"../../plots/font_attributes":771,"../color/attributes":569}],637:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + + // 'y' position pad above counter axis domain + yPad: 0.02, + + // minimum button width (regardless of text size) + minButtonWidth: 30, + + // buttons rect radii + rx: 3, + ry: 3, + + // light fraction used to compute the 'activecolor' default + lightAmount: 25, + darkAmount: 10 +}; + +},{}],638:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../color'); +var Template = _dereq_('../../plot_api/plot_template'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var constants = _dereq_('./constants'); + + +module.exports = function handleDefaults(containerIn, containerOut, layout, counterAxes, calendar) { + var selectorIn = containerIn.rangeselector || {}; + var selectorOut = Template.newContainer(containerOut, 'rangeselector'); + + function coerce(attr, dflt) { + return Lib.coerce(selectorIn, selectorOut, attributes, attr, dflt); + } + + var buttons = handleArrayContainerDefaults(selectorIn, selectorOut, { + name: 'buttons', + handleItemDefaults: buttonDefaults, + calendar: calendar + }); + + var visible = coerce('visible', buttons.length > 0); + if(visible) { + var posDflt = getPosDflt(containerOut, layout, counterAxes); + coerce('x', posDflt[0]); + coerce('y', posDflt[1]); + Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + Lib.coerceFont(coerce, 'font', layout.font); + + var bgColor = coerce('bgcolor'); + coerce('activecolor', Color.contrast(bgColor, constants.lightAmount, constants.darkAmount)); + coerce('bordercolor'); + coerce('borderwidth'); + } +}; + +function buttonDefaults(buttonIn, buttonOut, selectorOut, opts) { + var calendar = opts.calendar; + + function coerce(attr, dflt) { + return Lib.coerce(buttonIn, buttonOut, attributes.buttons, attr, dflt); + } + + var visible = coerce('visible'); + + if(visible) { + var step = coerce('step'); + if(step !== 'all') { + if(calendar && calendar !== 'gregorian' && (step === 'month' || step === 'year')) { + buttonOut.stepmode = 'backward'; + } + else { + coerce('stepmode'); + } + + coerce('count'); + } + + coerce('label'); + } +} + +function getPosDflt(containerOut, layout, counterAxes) { + var anchoredList = counterAxes.filter(function(ax) { + return layout[ax].anchor === containerOut._id; + }); + + var posY = 0; + for(var i = 0; i < anchoredList.length; i++) { + var domain = layout[anchoredList[i]].domain; + if(domain) posY = Math.max(domain[1], posY); + } + + return [containerOut.domain[0], posY + constants.yPad]; +} + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../plots/array_container_defaults":740,"../color":570,"./attributes":636,"./constants":637}],639:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Plots = _dereq_('../../plots/plots'); +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var axisIds = _dereq_('../../plots/cartesian/axis_ids'); +var anchorUtils = _dereq_('../legend/anchor_utils'); + +var alignmentConstants = _dereq_('../../constants/alignment'); +var LINE_SPACING = alignmentConstants.LINE_SPACING; +var FROM_TL = alignmentConstants.FROM_TL; +var FROM_BR = alignmentConstants.FROM_BR; + +var constants = _dereq_('./constants'); +var getUpdateObject = _dereq_('./get_update_object'); + + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout; + + var selectors = fullLayout._infolayer.selectAll('.rangeselector') + .data(makeSelectorData(gd), selectorKeyFunc); + + selectors.enter().append('g') + .classed('rangeselector', true); + + selectors.exit().remove(); + + selectors.style({ + cursor: 'pointer', + 'pointer-events': 'all' + }); + + selectors.each(function(d) { + var selector = d3.select(this), + axisLayout = d, + selectorLayout = axisLayout.rangeselector; + + var buttons = selector.selectAll('g.button') + .data(Lib.filterVisible(selectorLayout.buttons)); + + buttons.enter().append('g') + .classed('button', true); + + buttons.exit().remove(); + + buttons.each(function(d) { + var button = d3.select(this); + var update = getUpdateObject(axisLayout, d); + + d._isActive = isActive(axisLayout, d, update); + + button.call(drawButtonRect, selectorLayout, d); + button.call(drawButtonText, selectorLayout, d, gd); + + button.on('click', function() { + if(gd._dragged) return; + + Registry.call('relayout', gd, update); + }); + + button.on('mouseover', function() { + d._isHovered = true; + button.call(drawButtonRect, selectorLayout, d); + }); + + button.on('mouseout', function() { + d._isHovered = false; + button.call(drawButtonRect, selectorLayout, d); + }); + }); + + reposition(gd, buttons, selectorLayout, axisLayout._name, selector); + }); + +}; + +function makeSelectorData(gd) { + var axes = axisIds.list(gd, 'x', true); + var data = []; + + for(var i = 0; i < axes.length; i++) { + var axis = axes[i]; + + if(axis.rangeselector && axis.rangeselector.visible) { + data.push(axis); + } + } + + return data; +} + +function selectorKeyFunc(d) { + return d._id; +} + +function isActive(axisLayout, opts, update) { + if(opts.step === 'all') { + return axisLayout.autorange === true; + } + else { + var keys = Object.keys(update); + + return ( + axisLayout.range[0] === update[keys[0]] && + axisLayout.range[1] === update[keys[1]] + ); + } +} + +function drawButtonRect(button, selectorLayout, d) { + var rect = Lib.ensureSingle(button, 'rect', 'selector-rect', function(s) { + s.attr('shape-rendering', 'crispEdges'); + }); + + rect.attr({ + 'rx': constants.rx, + 'ry': constants.ry + }); + + rect.call(Color.stroke, selectorLayout.bordercolor) + .call(Color.fill, getFillColor(selectorLayout, d)) + .style('stroke-width', selectorLayout.borderwidth + 'px'); +} + +function getFillColor(selectorLayout, d) { + return (d._isActive || d._isHovered) ? + selectorLayout.activecolor : + selectorLayout.bgcolor; +} + +function drawButtonText(button, selectorLayout, d, gd) { + function textLayout(s) { + svgTextUtils.convertToTspans(s, gd); + } + + var text = Lib.ensureSingle(button, 'text', 'selector-text', function(s) { + s.classed('user-select-none', true) + .attr('text-anchor', 'middle'); + }); + + text.call(Drawing.font, selectorLayout.font) + .text(getLabel(d)) + .call(textLayout); +} + +function getLabel(opts) { + if(opts.label) return opts.label; + + if(opts.step === 'all') return 'all'; + + return opts.count + opts.step.charAt(0); +} + +function reposition(gd, buttons, opts, axName, selector) { + var width = 0; + var height = 0; + + var borderWidth = opts.borderwidth; + + buttons.each(function() { + var button = d3.select(this); + var text = button.select('.selector-text'); + + var tHeight = opts.font.size * LINE_SPACING; + var hEff = Math.max(tHeight * svgTextUtils.lineCount(text), 16) + 3; + + height = Math.max(height, hEff); + }); + + buttons.each(function() { + var button = d3.select(this); + var rect = button.select('.selector-rect'); + var text = button.select('.selector-text'); + + var tWidth = text.node() && Drawing.bBox(text.node()).width; + var tHeight = opts.font.size * LINE_SPACING; + var tLines = svgTextUtils.lineCount(text); + + var wEff = Math.max(tWidth + 10, constants.minButtonWidth); + + // TODO add MathJax support + + // TODO add buttongap attribute + + button.attr('transform', 'translate(' + + (borderWidth + width) + ',' + borderWidth + + ')'); + + rect.attr({ + x: 0, + y: 0, + width: wEff, + height: height + }); + + svgTextUtils.positionText(text, wEff / 2, + height / 2 - ((tLines - 1) * tHeight / 2) + 3); + + width += wEff + 5; + }); + + var graphSize = gd._fullLayout._size; + var lx = graphSize.l + graphSize.w * opts.x; + var ly = graphSize.t + graphSize.h * (1 - opts.y); + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + lx -= width; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(opts)) { + lx -= width / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(opts)) { + ly -= height; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(opts)) { + ly -= height / 2; + yanchor = 'middle'; + } + + width = Math.ceil(width); + height = Math.ceil(height); + lx = Math.round(lx); + ly = Math.round(ly); + + Plots.autoMargin(gd, axName + '-range-selector', { + x: opts.x, + y: opts.y, + l: width * FROM_TL[xanchor], + r: width * FROM_BR[xanchor], + b: height * FROM_BR[yanchor], + t: height * FROM_TL[yanchor] + }); + + selector.attr('transform', 'translate(' + lx + ',' + ly + ')'); +} + +},{"../../constants/alignment":668,"../../lib":696,"../../lib/svg_text_utils":720,"../../plots/cartesian/axis_ids":747,"../../plots/plots":808,"../../registry":827,"../color":570,"../drawing":595,"../legend/anchor_utils":622,"./constants":637,"./get_update_object":640,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],640:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +module.exports = function getUpdateObject(axisLayout, buttonLayout) { + var axName = axisLayout._name; + var update = {}; + + if(buttonLayout.step === 'all') { + update[axName + '.autorange'] = true; + } + else { + var xrange = getXRange(axisLayout, buttonLayout); + + update[axName + '.range[0]'] = xrange[0]; + update[axName + '.range[1]'] = xrange[1]; + } + + return update; +}; + +function getXRange(axisLayout, buttonLayout) { + var currentRange = axisLayout.range; + var base = new Date(axisLayout.r2l(currentRange[1])); + + var step = buttonLayout.step, + count = buttonLayout.count; + + var range0; + + switch(buttonLayout.stepmode) { + case 'backward': + range0 = axisLayout.l2r(+d3.time[step].utc.offset(base, -count)); + break; + + case 'todate': + var base2 = d3.time[step].utc.offset(base, -count); + + range0 = axisLayout.l2r(+d3.time[step].utc.ceil(base2)); + break; + } + + var range1 = currentRange[1]; + + return [range0, range1]; +} + +},{"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],641:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'component', + name: 'rangeselector', + + schema: { + subplots: { + xaxis: {rangeselector: _dereq_('./attributes')} + } + }, + + layoutAttributes: _dereq_('./attributes'), + handleDefaults: _dereq_('./defaults'), + + draw: _dereq_('./draw') +}; + +},{"./attributes":636,"./defaults":638,"./draw":639}],642:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = _dereq_('../color/attributes'); + +module.exports = { + bgcolor: { + valType: 'color', + dflt: colorAttributes.background, + + editType: 'plot', + + }, + bordercolor: { + valType: 'color', + dflt: colorAttributes.defaultLine, + + editType: 'plot', + + }, + borderwidth: { + valType: 'integer', + dflt: 0, + min: 0, + + editType: 'plot', + + }, + autorange: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + impliedEdits: {'range[0]': undefined, 'range[1]': undefined}, + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'any', editType: 'calc', impliedEdits: {'^autorange': false}}, + {valType: 'any', editType: 'calc', impliedEdits: {'^autorange': false}} + ], + editType: 'calc', + impliedEdits: {'autorange': false}, + + }, + thickness: { + valType: 'number', + dflt: 0.15, + min: 0, + max: 1, + + editType: 'plot', + + }, + visible: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + editType: 'calc' +}; + +},{"../color/attributes":569}],643:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var listAxes = _dereq_('../../plots/cartesian/axis_ids').list; +var getAutoRange = _dereq_('../../plots/cartesian/autorange').getAutoRange; +var constants = _dereq_('./constants'); + +module.exports = function calcAutorange(gd) { + var axes = listAxes(gd, 'x', true); + + // Compute new slider range using axis autorange if necessary. + // + // Copy back range to input range slider container to skip + // this step in subsequent draw calls. + + for(var i = 0; i < axes.length; i++) { + var ax = axes[i]; + var opts = ax[constants.name]; + + if(opts && opts.visible && opts.autorange) { + opts._input.autorange = true; + opts._input.range = opts.range = getAutoRange(gd, ax); + } + } +}; + +},{"../../plots/cartesian/autorange":743,"../../plots/cartesian/axis_ids":747,"./constants":644}],644:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + + // attribute container name + name: 'rangeslider', + + // class names + + containerClassName: 'rangeslider-container', + bgClassName: 'rangeslider-bg', + rangePlotClassName: 'rangeslider-rangeplot', + + maskMinClassName: 'rangeslider-mask-min', + maskMaxClassName: 'rangeslider-mask-max', + slideBoxClassName: 'rangeslider-slidebox', + + grabberMinClassName: 'rangeslider-grabber-min', + grabAreaMinClassName: 'rangeslider-grabarea-min', + handleMinClassName: 'rangeslider-handle-min', + + grabberMaxClassName: 'rangeslider-grabber-max', + grabAreaMaxClassName: 'rangeslider-grabarea-max', + handleMaxClassName: 'rangeslider-handle-max', + + maskMinOppAxisClassName: 'rangeslider-mask-min-opp-axis', + maskMaxOppAxisClassName: 'rangeslider-mask-max-opp-axis', + + // style constants + + maskColor: 'rgba(0,0,0,0.4)', + maskOppAxisColor: 'rgba(0,0,0,0.2)', + + slideBoxFill: 'transparent', + slideBoxCursor: 'ew-resize', + + grabAreaFill: 'transparent', + grabAreaCursor: 'col-resize', + grabAreaWidth: 10, + + handleWidth: 4, + handleRadius: 1, + handleStrokeWidth: 1, + + extraPad: 15 +}; + +},{}],645:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Template = _dereq_('../../plot_api/plot_template'); +var axisIds = _dereq_('../../plots/cartesian/axis_ids'); + +var attributes = _dereq_('./attributes'); +var oppAxisAttrs = _dereq_('./oppaxis_attributes'); + +module.exports = function handleDefaults(layoutIn, layoutOut, axName) { + var axIn = layoutIn[axName]; + var axOut = layoutOut[axName]; + + if(!(axIn.rangeslider || layoutOut._requestRangeslider[axOut._id])) return; + + // not super proud of this (maybe store _ in axis object instead + if(!Lib.isPlainObject(axIn.rangeslider)) { + axIn.rangeslider = {}; + } + + var containerIn = axIn.rangeslider; + var containerOut = Template.newContainer(axOut, 'rangeslider'); + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + var rangeContainerIn, rangeContainerOut; + function coerceRange(attr, dflt) { + return Lib.coerce(rangeContainerIn, rangeContainerOut, oppAxisAttrs, attr, dflt); + } + + var visible = coerce('visible'); + if(!visible) return; + + coerce('bgcolor', layoutOut.plot_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('thickness'); + + coerce('autorange', !axOut.isValidRange(containerIn.range)); + coerce('range'); + + var subplots = layoutOut._subplots; + if(subplots) { + var yIds = subplots.cartesian + .filter(function(subplotId) { + return subplotId.substr(0, subplotId.indexOf('y')) === axisIds.name2id(axName); + }) + .map(function(subplotId) { + return subplotId.substr(subplotId.indexOf('y'), subplotId.length); + }); + var yNames = Lib.simpleMap(yIds, axisIds.id2name); + for(var i = 0; i < yNames.length; i++) { + var yName = yNames[i]; + + rangeContainerIn = containerIn[yName] || {}; + rangeContainerOut = Template.newContainer(containerOut, yName, 'yaxis'); + + var yAxOut = layoutOut[yName]; + + var rangemodeDflt; + if(rangeContainerIn.range && yAxOut.isValidRange(rangeContainerIn.range)) { + rangemodeDflt = 'fixed'; + } + + var rangeMode = coerceRange('rangemode', rangemodeDflt); + if(rangeMode !== 'match') { + coerceRange('range', yAxOut.range.slice()); + } + } + } + + // to map back range slider (auto) range + containerOut._input = containerIn; +}; + +},{"../../lib":696,"../../plot_api/plot_template":734,"../../plots/cartesian/axis_ids":747,"./attributes":642,"./oppaxis_attributes":648}],646:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Plots = _dereq_('../../plots/plots'); + +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); +var Titles = _dereq_('../titles'); + +var Cartesian = _dereq_('../../plots/cartesian'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var dragElement = _dereq_('../dragelement'); +var setCursor = _dereq_('../../lib/setcursor'); + +var constants = _dereq_('./constants'); + +module.exports = function(gd) { + var fullLayout = gd._fullLayout, + rangeSliderData = makeRangeSliderData(fullLayout); + + /* + * + * + * < .... range plot /> + * + * + * + * + * + * + * + * + * + * + * ... + */ + + function keyFunction(axisOpts) { + return axisOpts._name; + } + + var rangeSliders = fullLayout._infolayer + .selectAll('g.' + constants.containerClassName) + .data(rangeSliderData, keyFunction); + + rangeSliders.enter().append('g') + .classed(constants.containerClassName, true) + .attr('pointer-events', 'all'); + + // remove exiting sliders and their corresponding clip paths + rangeSliders.exit().each(function(axisOpts) { + var opts = axisOpts[constants.name]; + fullLayout._topdefs.select('#' + opts._clipId).remove(); + }).remove(); + + // return early if no range slider is visible + if(rangeSliderData.length === 0) return; + + // for all present range sliders + rangeSliders.each(function(axisOpts) { + var rangeSlider = d3.select(this), + opts = axisOpts[constants.name], + oppAxisOpts = fullLayout[Axes.id2name(axisOpts.anchor)], + oppAxisRangeOpts = opts[Axes.id2name(axisOpts.anchor)]; + + // update range + // Expand slider range to the axis range + // TODO: what if the ranges are reversed? + if(opts.range) { + var outRange = opts.range; + var axRange = axisOpts.range; + + outRange[0] = axisOpts.l2r(Math.min(axisOpts.r2l(outRange[0]), axisOpts.r2l(axRange[0]))); + outRange[1] = axisOpts.l2r(Math.max(axisOpts.r2l(outRange[1]), axisOpts.r2l(axRange[1]))); + opts._input.range = outRange.slice(); + } + + axisOpts.cleanRange('rangeslider.range'); + + + // update range slider dimensions + + var margin = fullLayout.margin; + var graphSize = fullLayout._size; + var domain = axisOpts.domain; + var tickHeight = (axisOpts._boundingBox || {}).height || 0; + + var oppBottom = Infinity; + var subplotData = Axes.getSubplots(gd, axisOpts); + for(var i = 0; i < subplotData.length; i++) { + var oppAxis = Axes.getFromId(gd, subplotData[i].substr(subplotData[i].indexOf('y'))); + oppBottom = Math.min(oppBottom, oppAxis.domain[0]); + } + + opts._id = constants.name + axisOpts._id; + opts._clipId = opts._id + '-' + fullLayout._uid; + + opts._width = graphSize.w * (domain[1] - domain[0]); + opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness; + opts._offsetShift = Math.floor(opts.borderwidth / 2); + + var x = Math.round(margin.l + (graphSize.w * domain[0])); + + var y = Math.round( + graphSize.t + graphSize.h * (1 - oppBottom) + + tickHeight + + opts._offsetShift + constants.extraPad + ); + + rangeSlider.attr('transform', 'translate(' + x + ',' + y + ')'); + + // update data <--> pixel coordinate conversion methods + + var range0 = axisOpts.r2l(opts.range[0]), + range1 = axisOpts.r2l(opts.range[1]), + dist = range1 - range0; + + opts.p2d = function(v) { + return (v / opts._width) * dist + range0; + }; + + opts.d2p = function(v) { + return (v - range0) / dist * opts._width; + }; + + opts._rl = [range0, range1]; + + if(oppAxisRangeOpts.rangemode !== 'match') { + var range0OppAxis = oppAxisOpts.r2l(oppAxisRangeOpts.range[0]), + range1OppAxis = oppAxisOpts.r2l(oppAxisRangeOpts.range[1]), + distOppAxis = range1OppAxis - range0OppAxis; + + opts.d2pOppAxis = function(v) { + return (v - range0OppAxis) / distOppAxis * opts._height; + }; + } + + // update inner nodes + + rangeSlider + .call(drawBg, gd, axisOpts, opts) + .call(addClipPath, gd, axisOpts, opts) + .call(drawRangePlot, gd, axisOpts, opts) + .call(drawMasks, gd, axisOpts, opts, oppAxisRangeOpts) + .call(drawSlideBox, gd, axisOpts, opts) + .call(drawGrabbers, gd, axisOpts, opts); + + // setup drag element + setupDragElement(rangeSlider, gd, axisOpts, opts); + + // update current range + setPixelRange(rangeSlider, gd, axisOpts, opts, oppAxisOpts, oppAxisRangeOpts); + + // title goes next to range slider instead of tick labels, so + // just take it over and draw it from here + if(axisOpts.side === 'bottom') { + Titles.draw(gd, axisOpts._id + 'title', { + propContainer: axisOpts, + propName: axisOpts._name + '.title', + placeholder: fullLayout._dfltTitle.x, + attributes: { + x: axisOpts._offset + axisOpts._length / 2, + y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.titlefont.size, + 'text-anchor': 'middle' + } + }); + } + + // update margins + Plots.autoMargin(gd, opts._id, { + x: domain[0], + y: oppBottom, + l: 0, + r: 0, + t: 0, + b: opts._height + margin.b + tickHeight, + pad: constants.extraPad + opts._offsetShift * 2 + }); + }); +}; + +function makeRangeSliderData(fullLayout) { + var axes = Axes.list({ _fullLayout: fullLayout }, 'x', true), + name = constants.name, + out = []; + + if(fullLayout._has('gl2d')) return out; + + for(var i = 0; i < axes.length; i++) { + var ax = axes[i]; + + if(ax[name] && ax[name].visible) out.push(ax); + } + + return out; +} + +function setupDragElement(rangeSlider, gd, axisOpts, opts) { + var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(), + grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(), + grabAreaMax = rangeSlider.select('rect.' + constants.grabAreaMaxClassName).node(); + + rangeSlider.on('mousedown', function() { + var event = d3.event, + target = event.target, + startX = event.clientX, + offsetX = startX - rangeSlider.node().getBoundingClientRect().left, + minVal = opts.d2p(axisOpts._rl[0]), + maxVal = opts.d2p(axisOpts._rl[1]); + + var dragCover = dragElement.coverSlip(); + + dragCover.addEventListener('mousemove', mouseMove); + dragCover.addEventListener('mouseup', mouseUp); + + function mouseMove(e) { + var delta = +e.clientX - startX; + var pixelMin, pixelMax, cursor; + + switch(target) { + case slideBox: + cursor = 'ew-resize'; + pixelMin = minVal + delta; + pixelMax = maxVal + delta; + break; + + case grabAreaMin: + cursor = 'col-resize'; + pixelMin = minVal + delta; + pixelMax = maxVal; + break; + + case grabAreaMax: + cursor = 'col-resize'; + pixelMin = minVal; + pixelMax = maxVal + delta; + break; + + default: + cursor = 'ew-resize'; + pixelMin = offsetX; + pixelMax = offsetX + delta; + break; + } + + if(pixelMax < pixelMin) { + var tmp = pixelMax; + pixelMax = pixelMin; + pixelMin = tmp; + } + + opts._pixelMin = pixelMin; + opts._pixelMax = pixelMax; + + setCursor(d3.select(dragCover), cursor); + setDataRange(rangeSlider, gd, axisOpts, opts); + } + + function mouseUp() { + dragCover.removeEventListener('mousemove', mouseMove); + dragCover.removeEventListener('mouseup', mouseUp); + Lib.removeElement(dragCover); + } + }); +} + +function setDataRange(rangeSlider, gd, axisOpts, opts) { + + function clamp(v) { + return axisOpts.l2r(Lib.constrain(v, opts._rl[0], opts._rl[1])); + } + + var dataMin = clamp(opts.p2d(opts._pixelMin)), + dataMax = clamp(opts.p2d(opts._pixelMax)); + + window.requestAnimationFrame(function() { + Registry.call('relayout', gd, axisOpts._name + '.range', [dataMin, dataMax]); + }); +} + +function setPixelRange(rangeSlider, gd, axisOpts, opts, oppAxisOpts, oppAxisRangeOpts) { + var hw2 = constants.handleWidth / 2; + + function clamp(v) { + return Lib.constrain(v, 0, opts._width); + } + + function clampOppAxis(v) { + return Lib.constrain(v, 0, opts._height); + } + + function clampHandle(v) { + return Lib.constrain(v, -hw2, opts._width + hw2); + } + + var pixelMin = clamp(opts.d2p(axisOpts._rl[0])), + pixelMax = clamp(opts.d2p(axisOpts._rl[1])); + + rangeSlider.select('rect.' + constants.slideBoxClassName) + .attr('x', pixelMin) + .attr('width', pixelMax - pixelMin); + + rangeSlider.select('rect.' + constants.maskMinClassName) + .attr('width', pixelMin); + + rangeSlider.select('rect.' + constants.maskMaxClassName) + .attr('x', pixelMax) + .attr('width', opts._width - pixelMax); + + if(oppAxisRangeOpts.rangemode !== 'match') { + var pixelMinOppAxis = opts._height - clampOppAxis(opts.d2pOppAxis(oppAxisOpts._rl[1])), + pixelMaxOppAxis = opts._height - clampOppAxis(opts.d2pOppAxis(oppAxisOpts._rl[0])); + + rangeSlider.select('rect.' + constants.maskMinOppAxisClassName) + .attr('x', pixelMin) + .attr('height', pixelMinOppAxis) + .attr('width', pixelMax - pixelMin); + + rangeSlider.select('rect.' + constants.maskMaxOppAxisClassName) + .attr('x', pixelMin) + .attr('y', pixelMaxOppAxis) + .attr('height', opts._height - pixelMaxOppAxis) + .attr('width', pixelMax - pixelMin); + + rangeSlider.select('rect.' + constants.slideBoxClassName) + .attr('y', pixelMinOppAxis) + .attr('height', pixelMaxOppAxis - pixelMinOppAxis); + } + + // add offset for crispier corners + // https://github.com/plotly/plotly.js/pull/1409 + var offset = 0.5; + + var xMin = Math.round(clampHandle(pixelMin - hw2)) - offset, + xMax = Math.round(clampHandle(pixelMax - hw2)) + offset; + + rangeSlider.select('g.' + constants.grabberMinClassName) + .attr('transform', 'translate(' + xMin + ',' + offset + ')'); + + rangeSlider.select('g.' + constants.grabberMaxClassName) + .attr('transform', 'translate(' + xMax + ',' + offset + ')'); +} + +function drawBg(rangeSlider, gd, axisOpts, opts) { + var bg = Lib.ensureSingle(rangeSlider, 'rect', constants.bgClassName, function(s) { + s.attr({ + x: 0, + y: 0, + 'shape-rendering': 'crispEdges' + }); + }); + + var borderCorrect = (opts.borderwidth % 2) === 0 ? + opts.borderwidth : + opts.borderwidth - 1; + + var offsetShift = -opts._offsetShift; + var lw = Drawing.crispRound(gd, opts.borderwidth); + + bg.attr({ + width: opts._width + borderCorrect, + height: opts._height + borderCorrect, + transform: 'translate(' + offsetShift + ',' + offsetShift + ')', + fill: opts.bgcolor, + stroke: opts.bordercolor, + 'stroke-width': lw + }); +} + +function addClipPath(rangeSlider, gd, axisOpts, opts) { + var fullLayout = gd._fullLayout; + + var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', opts._clipId, function(s) { + s.append('rect').attr({ x: 0, y: 0 }); + }); + + clipPath.select('rect').attr({ + width: opts._width, + height: opts._height + }); +} + +function drawRangePlot(rangeSlider, gd, axisOpts, opts) { + var subplotData = Axes.getSubplots(gd, axisOpts), + calcData = gd.calcdata; + + var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName) + .data(subplotData, Lib.identity); + + rangePlots.enter().append('g') + .attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; }) + .call(Drawing.setClipUrl, opts._clipId); + + rangePlots.order(); + + rangePlots.exit().remove(); + + var mainplotinfo; + + rangePlots.each(function(id, i) { + var plotgroup = d3.select(this), + isMainPlot = (i === 0); + + var oppAxisOpts = Axes.getFromId(gd, id, 'y'), + oppAxisName = oppAxisOpts._name, + oppAxisRangeOpts = opts[oppAxisName]; + + var mockFigure = { + data: [], + layout: { + xaxis: { + type: axisOpts.type, + domain: [0, 1], + range: opts.range.slice(), + calendar: axisOpts.calendar + }, + width: opts._width, + height: opts._height, + margin: { t: 0, b: 0, l: 0, r: 0 } + }, + _context: gd._context + }; + + mockFigure.layout[oppAxisName] = { + type: oppAxisOpts.type, + domain: [0, 1], + range: oppAxisRangeOpts.rangemode !== 'match' ? oppAxisRangeOpts.range.slice() : oppAxisOpts.range.slice(), + calendar: oppAxisOpts.calendar + }; + + Plots.supplyDefaults(mockFigure); + + var xa = mockFigure._fullLayout.xaxis; + var ya = mockFigure._fullLayout[oppAxisName]; + + var plotinfo = { + id: id, + plotgroup: plotgroup, + xaxis: xa, + yaxis: ya, + isRangePlot: true + }; + + if(isMainPlot) mainplotinfo = plotinfo; + else { + plotinfo.mainplot = 'xy'; + plotinfo.mainplotinfo = mainplotinfo; + } + + Cartesian.rangePlot(gd, plotinfo, filterRangePlotCalcData(calcData, id)); + }); +} + +function filterRangePlotCalcData(calcData, subplotId) { + var out = []; + + for(var i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i], + trace = calcTrace[0].trace; + + if(trace.xaxis + trace.yaxis === subplotId) { + out.push(calcTrace); + } + } + + return out; +} + +function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) { + var maskMin = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinClassName, function(s) { + s.attr({ + x: 0, + y: 0, + 'shape-rendering': 'crispEdges' + }); + }); + + maskMin + .attr('height', opts._height) + .call(Color.fill, constants.maskColor); + + var maskMax = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxClassName, function(s) { + s.attr({ + y: 0, + 'shape-rendering': 'crispEdges' + }); + }); + + maskMax + .attr('height', opts._height) + .call(Color.fill, constants.maskColor); + + // masks used for oppAxis zoom + if(oppAxisRangeOpts.rangemode !== 'match') { + var maskMinOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinOppAxisClassName, function(s) { + s.attr({ + y: 0, + 'shape-rendering': 'crispEdges' + }); + }); + + maskMinOppAxis + .attr('width', opts._width) + .call(Color.fill, constants.maskOppAxisColor); + + var maskMaxOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxOppAxisClassName, function(s) { + s.attr({ + y: 0, + 'shape-rendering': 'crispEdges' + }); + }); + + maskMaxOppAxis + .attr('width', opts._width) + .style('border-top', constants.maskOppBorder) + .call(Color.fill, constants.maskOppAxisColor); + } +} + +function drawSlideBox(rangeSlider, gd, axisOpts, opts) { + if(gd._context.staticPlot) return; + + var slideBox = Lib.ensureSingle(rangeSlider, 'rect', constants.slideBoxClassName, function(s) { + s.attr({ + y: 0, + cursor: constants.slideBoxCursor, + 'shape-rendering': 'crispEdges' + }); + }); + + slideBox.attr({ + height: opts._height, + fill: constants.slideBoxFill + }); +} + +function drawGrabbers(rangeSlider, gd, axisOpts, opts) { + // + var grabberMin = Lib.ensureSingle(rangeSlider, 'g', constants.grabberMinClassName); + var grabberMax = Lib.ensureSingle(rangeSlider, 'g', constants.grabberMaxClassName); + + // + var handleFixAttrs = { + x: 0, + width: constants.handleWidth, + rx: constants.handleRadius, + fill: Color.background, + stroke: Color.defaultLine, + 'stroke-width': constants.handleStrokeWidth, + 'shape-rendering': 'crispEdges' + }; + var handleDynamicAttrs = { + y: Math.round(opts._height / 4), + height: Math.round(opts._height / 2), + }; + var handleMin = Lib.ensureSingle(grabberMin, 'rect', constants.handleMinClassName, function(s) { + s.attr(handleFixAttrs); + }); + handleMin.attr(handleDynamicAttrs); + + var handleMax = Lib.ensureSingle(grabberMax, 'rect', constants.handleMaxClassName, function(s) { + s.attr(handleFixAttrs); + }); + handleMax.attr(handleDynamicAttrs); + + // + if(gd._context.staticPlot) return; + + var grabAreaFixAttrs = { + width: constants.grabAreaWidth, + x: 0, + y: 0, + fill: constants.grabAreaFill, + cursor: constants.grabAreaCursor + }; + + var grabAreaMin = Lib.ensureSingle(grabberMin, 'rect', constants.grabAreaMinClassName, function(s) { + s.attr(grabAreaFixAttrs); + }); + grabAreaMin.attr('height', opts._height); + + var grabAreaMax = Lib.ensureSingle(grabberMax, 'rect', constants.grabAreaMaxClassName, function(s) { + s.attr(grabAreaFixAttrs); + }); + grabAreaMax.attr('height', opts._height); +} + +},{"../../lib":696,"../../lib/setcursor":716,"../../plots/cartesian":756,"../../plots/cartesian/axes":744,"../../plots/plots":808,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"../titles":661,"./constants":644,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],647:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attrs = _dereq_('./attributes'); +var oppAxisAttrs = _dereq_('./oppaxis_attributes'); + +module.exports = { + moduleType: 'component', + name: 'rangeslider', + + schema: { + subplots: { + xaxis: { + rangeslider: Lib.extendFlat({}, attrs, { + yaxis: oppAxisAttrs + }) + } + } + }, + + layoutAttributes: _dereq_('./attributes'), + handleDefaults: _dereq_('./defaults'), + calcAutorange: _dereq_('./calc_autorange'), + draw: _dereq_('./draw') +}; + +},{"../../lib":696,"./attributes":642,"./calc_autorange":643,"./defaults":645,"./draw":646,"./oppaxis_attributes":648}],648:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + // not really a 'subplot' attribute container, + // but this is the flag we use to denote attributes that + // support yaxis, yaxis2, yaxis3, ... counters + _isSubplotObj: true, + + rangemode: { + valType: 'enumerated', + values: ['auto', 'fixed', 'match'], + dflt: 'match', + + editType: 'calc', + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'any', editType: 'plot'}, + {valType: 'any', editType: 'plot'} + ], + editType: 'plot', + + }, + editType: 'calc' +}; + +},{}],649:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var annAttrs = _dereq_('../annotations/attributes'); +var scatterLineAttrs = _dereq_('../../traces/scatter/attributes').line; +var dash = _dereq_('../drawing/attributes').dash; +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +module.exports = templatedArray('shape', { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'calc+arraydraw', + + }, + + type: { + valType: 'enumerated', + values: ['circle', 'rect', 'path', 'line'], + + editType: 'calc+arraydraw', + + }, + + layer: { + valType: 'enumerated', + values: ['below', 'above'], + dflt: 'above', + + editType: 'arraydraw', + + }, + + xref: extendFlat({}, annAttrs.xref, { + + }), + xsizemode: { + valType: 'enumerated', + values: ['scaled', 'pixel'], + dflt: 'scaled', + + editType: 'calc+arraydraw', + + }, + xanchor: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + x0: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + x1: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + + yref: extendFlat({}, annAttrs.yref, { + + }), + ysizemode: { + valType: 'enumerated', + values: ['scaled', 'pixel'], + dflt: 'scaled', + + editType: 'calc+arraydraw', + + }, + yanchor: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + y0: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + y1: { + valType: 'any', + + editType: 'calc+arraydraw', + + }, + + path: { + valType: 'string', + + editType: 'calc+arraydraw', + + }, + + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + + editType: 'arraydraw', + + }, + line: { + color: extendFlat({}, scatterLineAttrs.color, {editType: 'arraydraw'}), + width: extendFlat({}, scatterLineAttrs.width, {editType: 'calc+arraydraw'}), + dash: extendFlat({}, dash, {editType: 'arraydraw'}), + + editType: 'calc+arraydraw' + }, + fillcolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + editType: 'arraydraw', + + }, + editType: 'arraydraw' +}); + +},{"../../lib/extend":685,"../../plot_api/plot_template":734,"../../traces/scatter/attributes":1043,"../annotations/attributes":553,"../drawing/attributes":594}],650:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var constants = _dereq_('./constants'); +var helpers = _dereq_('./helpers'); + + +module.exports = function calcAutorange(gd) { + var fullLayout = gd._fullLayout, + shapeList = Lib.filterVisible(fullLayout.shapes); + + if(!shapeList.length || !gd._fullData.length) return; + + for(var i = 0; i < shapeList.length; i++) { + var shape = shapeList[i]; + shape._extremes = {}; + + var ax, bounds; + + if(shape.xref !== 'paper') { + var vx0 = shape.xsizemode === 'pixel' ? shape.xanchor : shape.x0, + vx1 = shape.xsizemode === 'pixel' ? shape.xanchor : shape.x1; + ax = Axes.getFromId(gd, shape.xref); + + bounds = shapeBounds(ax, vx0, vx1, shape.path, constants.paramIsX); + if(bounds) { + shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcXPaddingOptions(shape)); + } + } + + if(shape.yref !== 'paper') { + var vy0 = shape.ysizemode === 'pixel' ? shape.yanchor : shape.y0, + vy1 = shape.ysizemode === 'pixel' ? shape.yanchor : shape.y1; + ax = Axes.getFromId(gd, shape.yref); + + bounds = shapeBounds(ax, vy0, vy1, shape.path, constants.paramIsY); + if(bounds) { + shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcYPaddingOptions(shape)); + } + } + } +}; + +function calcXPaddingOptions(shape) { + return calcPaddingOptions(shape.line.width, shape.xsizemode, shape.x0, shape.x1, shape.path, false); +} + +function calcYPaddingOptions(shape) { + return calcPaddingOptions(shape.line.width, shape.ysizemode, shape.y0, shape.y1, shape.path, true); +} + +function calcPaddingOptions(lineWidth, sizeMode, v0, v1, path, isYAxis) { + var ppad = lineWidth / 2, + axisDirectionReverted = isYAxis; + + if(sizeMode === 'pixel') { + var coords = path ? + helpers.extractPathCoords(path, isYAxis ? constants.paramIsY : constants.paramIsX) : + [v0, v1]; + var maxValue = Lib.aggNums(Math.max, null, coords), + minValue = Lib.aggNums(Math.min, null, coords), + beforePad = minValue < 0 ? Math.abs(minValue) + ppad : ppad, + afterPad = maxValue > 0 ? maxValue + ppad : ppad; + + return { + ppad: ppad, + ppadplus: axisDirectionReverted ? beforePad : afterPad, + ppadminus: axisDirectionReverted ? afterPad : beforePad + }; + } else { + return {ppad: ppad}; + } +} + +function shapeBounds(ax, v0, v1, path, paramsToUse) { + var convertVal = (ax.type === 'category') ? ax.r2c : ax.d2c; + + if(v0 !== undefined) return [convertVal(v0), convertVal(v1)]; + if(!path) return; + + var min = Infinity, + max = -Infinity, + segments = path.match(constants.segmentRE), + i, + segment, + drawnParam, + params, + val; + + if(ax.type === 'date') convertVal = helpers.decodeDate(convertVal); + + for(i = 0; i < segments.length; i++) { + segment = segments[i]; + drawnParam = paramsToUse[segment.charAt(0)].drawn; + if(drawnParam === undefined) continue; + + params = segments[i].substr(1).match(constants.paramRE); + if(!params || params.length < drawnParam) continue; + + val = convertVal(params[drawnParam]); + if(val < min) min = val; + if(val > max) max = val; + } + if(max >= min) return [min, max]; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744,"./constants":651,"./helpers":654}],651:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + segmentRE: /[MLHVQCTSZ][^MLHVQCTSZ]*/g, + paramRE: /[^\s,]+/g, + + // which numbers in each path segment are x (or y) values + // drawn is which param is a drawn point, as opposed to a + // control point (which doesn't count toward autorange. + // TODO: this means curved paths could extend beyond the + // autorange bounds. This is a bit tricky to get right + // unless we revert to bounding boxes, but perhaps there's + // a calculation we could do...) + paramIsX: { + M: {0: true, drawn: 0}, + L: {0: true, drawn: 0}, + H: {0: true, drawn: 0}, + V: {}, + Q: {0: true, 2: true, drawn: 2}, + C: {0: true, 2: true, 4: true, drawn: 4}, + T: {0: true, drawn: 0}, + S: {0: true, 2: true, drawn: 2}, + // A: {0: true, 5: true}, + Z: {} + }, + + paramIsY: { + M: {1: true, drawn: 1}, + L: {1: true, drawn: 1}, + H: {}, + V: {0: true, drawn: 0}, + Q: {1: true, 3: true, drawn: 3}, + C: {1: true, 3: true, 5: true, drawn: 5}, + T: {1: true, drawn: 1}, + S: {1: true, 3: true, drawn: 5}, + // A: {1: true, 6: true}, + Z: {} + }, + + numParams: { + M: 2, + L: 2, + H: 1, + V: 1, + Q: 4, + C: 6, + T: 2, + S: 4, + // A: 7, + Z: 0 + } +}; + +},{}],652:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var helpers = _dereq_('./helpers'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + handleArrayContainerDefaults(layoutIn, layoutOut, { + name: 'shapes', + handleItemDefaults: handleShapeDefaults + }); +}; + +function handleShapeDefaults(shapeIn, shapeOut, fullLayout) { + function coerce(attr, dflt) { + return Lib.coerce(shapeIn, shapeOut, attributes, attr, dflt); + } + + var visible = coerce('visible'); + + if(!visible) return; + + coerce('layer'); + coerce('opacity'); + coerce('fillcolor'); + coerce('line.color'); + coerce('line.width'); + coerce('line.dash'); + + var dfltType = shapeIn.path ? 'path' : 'rect', + shapeType = coerce('type', dfltType), + xSizeMode = coerce('xsizemode'), + ySizeMode = coerce('ysizemode'); + + // positioning + var axLetters = ['x', 'y']; + for(var i = 0; i < 2; i++) { + var axLetter = axLetters[i], + attrAnchor = axLetter + 'anchor', + sizeMode = axLetter === 'x' ? xSizeMode : ySizeMode, + gdMock = {_fullLayout: fullLayout}, + ax, + pos2r, + r2pos; + + // xref, yref + var axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, '', 'paper'); + + if(axRef !== 'paper') { + ax = Axes.getFromId(gdMock, axRef); + ax._shapeIndices.push(shapeOut._index); + r2pos = helpers.rangeToShapePosition(ax); + pos2r = helpers.shapePositionToRange(ax); + } + else { + pos2r = r2pos = Lib.identity; + } + + // Coerce x0, x1, y0, y1 + if(shapeType !== 'path') { + var dflt0 = 0.25, + dflt1 = 0.75; + + // hack until V2.0 when log has regular range behavior - make it look like other + // ranges to send to coerce, then put it back after + // this is all to give reasonable default position behavior on log axes, which is + // a pretty unimportant edge case so we could just ignore this. + var attr0 = axLetter + '0', + attr1 = axLetter + '1', + in0 = shapeIn[attr0], + in1 = shapeIn[attr1]; + shapeIn[attr0] = pos2r(shapeIn[attr0], true); + shapeIn[attr1] = pos2r(shapeIn[attr1], true); + + if(sizeMode === 'pixel') { + coerce(attr0, 0); + coerce(attr1, 10); + } else { + Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr0, dflt0); + Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr1, dflt1); + } + + // hack part 2 + shapeOut[attr0] = r2pos(shapeOut[attr0]); + shapeOut[attr1] = r2pos(shapeOut[attr1]); + shapeIn[attr0] = in0; + shapeIn[attr1] = in1; + } + + // Coerce xanchor and yanchor + if(sizeMode === 'pixel') { + // Hack for log axis described above + var inAnchor = shapeIn[attrAnchor]; + shapeIn[attrAnchor] = pos2r(shapeIn[attrAnchor], true); + + Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attrAnchor, 0.25); + + // Hack part 2 + shapeOut[attrAnchor] = r2pos(shapeOut[attrAnchor]); + shapeIn[attrAnchor] = inAnchor; + } + } + + if(shapeType === 'path') { + coerce('path'); + } + else { + Lib.noneOrAll(shapeIn, shapeOut, ['x0', 'x1', 'y0', 'y1']); + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/cartesian/axes":744,"./attributes":649,"./helpers":654}],653:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); +var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; + +var dragElement = _dereq_('../dragelement'); +var setCursor = _dereq_('../../lib/setcursor'); + +var constants = _dereq_('./constants'); +var helpers = _dereq_('./helpers'); + + +// Shapes are stored in gd.layout.shapes, an array of objects +// index can point to one item in this array, +// or non-numeric to simply add a new one +// or -1 to modify all existing +// opt can be the full options object, or one key (to be set to value) +// or undefined to simply redraw +// if opt is blank, val can be 'add' or a full options object to add a new +// annotation at that point in the array, or 'remove' to delete this one + +module.exports = { + draw: draw, + drawOne: drawOne +}; + +function draw(gd) { + var fullLayout = gd._fullLayout; + + // Remove previous shapes before drawing new in shapes in fullLayout.shapes + fullLayout._shapeUpperLayer.selectAll('path').remove(); + fullLayout._shapeLowerLayer.selectAll('path').remove(); + + for(var k in fullLayout._plots) { + var shapelayer = fullLayout._plots[k].shapelayer; + if(shapelayer) shapelayer.selectAll('path').remove(); + } + + for(var i = 0; i < fullLayout.shapes.length; i++) { + if(fullLayout.shapes[i].visible) { + drawOne(gd, i); + } + } + + // may need to resurrect this if we put text (LaTeX) in shapes + // return Plots.previousPromises(gd); +} + +function drawOne(gd, index) { + // remove the existing shape if there is one. + // because indices can change, we need to look in all shape layers + gd._fullLayout._paperdiv + .selectAll('.shapelayer [data-index="' + index + '"]') + .remove(); + + var options = gd._fullLayout.shapes[index] || {}; + + // this shape is gone - quit now after deleting it + // TODO: use d3 idioms instead of deleting and redrawing every time + if(!options._input || options.visible === false) return; + + if(options.layer !== 'below') { + drawShape(gd._fullLayout._shapeUpperLayer); + } + else if(options.xref === 'paper' || options.yref === 'paper') { + drawShape(gd._fullLayout._shapeLowerLayer); + } + else { + var plotinfo = gd._fullLayout._plots[options.xref + options.yref]; + if(plotinfo) { + var mainPlot = plotinfo.mainplotinfo || plotinfo; + drawShape(mainPlot.shapelayer); + } + else { + // Fall back to _shapeLowerLayer in case the requested subplot doesn't exist. + // This can happen if you reference the shape to an x / y axis combination + // that doesn't have any data on it (and layer is below) + drawShape(gd._fullLayout._shapeLowerLayer); + } + } + + function drawShape(shapeLayer) { + var attrs = { + 'data-index': index, + 'fill-rule': 'evenodd', + d: getPathString(gd, options) + }, + lineColor = options.line.width ? + options.line.color : 'rgba(0,0,0,0)'; + + var path = shapeLayer.append('path') + .attr(attrs) + .style('opacity', options.opacity) + .call(Color.stroke, lineColor) + .call(Color.fill, options.fillcolor) + .call(Drawing.dashLine, options.line.dash, options.line.width); + + setClipPath(path, gd, options); + + if(gd._context.edits.shapePosition) setupDragElement(gd, path, options, index, shapeLayer); + } +} + +function setClipPath(shapePath, gd, shapeOptions) { + // note that for layer="below" the clipAxes can be different from the + // subplot we're drawing this in. This could cause problems if the shape + // spans two subplots. See https://github.com/plotly/plotly.js/issues/1452 + var clipAxes = (shapeOptions.xref + shapeOptions.yref).replace(/paper/g, ''); + + shapePath.call(Drawing.setClipUrl, clipAxes ? + ('clip' + gd._fullLayout._uid + clipAxes) : + null + ); +} + +function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer) { + var MINWIDTH = 10; + var MINHEIGHT = 10; + + var xPixelSized = shapeOptions.xsizemode === 'pixel'; + var yPixelSized = shapeOptions.ysizemode === 'pixel'; + var isLine = shapeOptions.type === 'line'; + var isPath = shapeOptions.type === 'path'; + + var editHelpers = arrayEditor(gd.layout, 'shapes', shapeOptions); + var modifyItem = editHelpers.modifyItem; + + var x0, y0, x1, y1, xAnchor, yAnchor; + var n0, s0, w0, e0, optN, optS, optW, optE; + var pathIn; + + // setup conversion functions + var xa = Axes.getFromId(gd, shapeOptions.xref), + ya = Axes.getFromId(gd, shapeOptions.yref), + x2p = helpers.getDataToPixel(gd, xa), + y2p = helpers.getDataToPixel(gd, ya, true), + p2x = helpers.getPixelToData(gd, xa), + p2y = helpers.getPixelToData(gd, ya, true); + + var sensoryElement = obtainSensoryElement(); + var dragOptions = { + element: sensoryElement.node(), + gd: gd, + prepFn: startDrag, + doneFn: endDrag, + clickFn: abortDrag + }, + dragMode; + + dragElement.init(dragOptions); + + sensoryElement.node().onmousemove = updateDragMode; + + function obtainSensoryElement() { + return isLine ? createLineDragHandles() : shapePath; + } + + function createLineDragHandles() { + var minSensoryWidth = 10, + sensoryWidth = Math.max(shapeOptions.line.width, minSensoryWidth); + + // Helper shapes group + // Note that by setting the `data-index` attr, it is ensured that + // the helper group is purged in this modules `draw` function + var g = shapeLayer.append('g') + .attr('data-index', index); + + // Helper path for moving + g.append('path') + .attr('d', shapePath.attr('d')) + .style({ + 'cursor': 'move', + 'stroke-width': sensoryWidth, + 'stroke-opacity': '0' // ensure not visible + }); + + // Helper circles for resizing + var circleStyle = { + 'fill-opacity': '0' // ensure not visible + }; + var circleRadius = sensoryWidth / 2 > minSensoryWidth ? sensoryWidth / 2 : minSensoryWidth; + + g.append('circle') + .attr({ + 'data-line-point': 'start-point', + 'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x0 : x2p(shapeOptions.x0), + 'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y0 : y2p(shapeOptions.y0), + 'r': circleRadius + }) + .style(circleStyle) + .classed('cursor-grab', true); + + g.append('circle') + .attr({ + 'data-line-point': 'end-point', + 'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x1 : x2p(shapeOptions.x1), + 'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y1 : y2p(shapeOptions.y1), + 'r': circleRadius + }) + .style(circleStyle) + .classed('cursor-grab', true); + + return g; + } + + function updateDragMode(evt) { + if(isLine) { + if(evt.target.tagName === 'path') { + dragMode = 'move'; + } else { + dragMode = evt.target.attributes['data-line-point'].value === 'start-point' ? + 'resize-over-start-point' : 'resize-over-end-point'; + } + } else { + // element might not be on screen at time of setup, + // so obtain bounding box here + var dragBBox = dragOptions.element.getBoundingClientRect(); + + // choose 'move' or 'resize' + // based on initial position of cursor within the drag element + var w = dragBBox.right - dragBBox.left, + h = dragBBox.bottom - dragBBox.top, + x = evt.clientX - dragBBox.left, + y = evt.clientY - dragBBox.top, + cursor = (!isPath && w > MINWIDTH && h > MINHEIGHT && !evt.shiftKey) ? + dragElement.getCursor(x / w, 1 - y / h) : + 'move'; + + setCursor(shapePath, cursor); + + // possible values 'move', 'sw', 'w', 'se', 'e', 'ne', 'n', 'nw' and 'w' + dragMode = cursor.split('-')[0]; + } + } + + function startDrag(evt) { + // setup update strings and initial values + if(xPixelSized) { + xAnchor = x2p(shapeOptions.xanchor); + } + if(yPixelSized) { + yAnchor = y2p(shapeOptions.yanchor); + } + + if(shapeOptions.type === 'path') { + pathIn = shapeOptions.path; + } + else { + x0 = xPixelSized ? shapeOptions.x0 : x2p(shapeOptions.x0); + y0 = yPixelSized ? shapeOptions.y0 : y2p(shapeOptions.y0); + x1 = xPixelSized ? shapeOptions.x1 : x2p(shapeOptions.x1); + y1 = yPixelSized ? shapeOptions.y1 : y2p(shapeOptions.y1); + } + + if(x0 < x1) { + w0 = x0; + optW = 'x0'; + e0 = x1; + optE = 'x1'; + } + else { + w0 = x1; + optW = 'x1'; + e0 = x0; + optE = 'x0'; + } + + // For fixed size shapes take opposing direction of y-axis into account. + // Hint: For data sized shapes this is done by the y2p function. + if((!yPixelSized && y0 < y1) || (yPixelSized && y0 > y1)) { + n0 = y0; + optN = 'y0'; + s0 = y1; + optS = 'y1'; + } + else { + n0 = y1; + optN = 'y1'; + s0 = y0; + optS = 'y0'; + } + + // setup dragMode and the corresponding handler + updateDragMode(evt); + renderVisualCues(shapeLayer, shapeOptions); + deactivateClipPathTemporarily(shapePath, shapeOptions, gd); + dragOptions.moveFn = (dragMode === 'move') ? moveShape : resizeShape; + } + + function endDrag() { + setCursor(shapePath); + removeVisualCues(shapeLayer); + + // Don't rely on clipPath being activated during re-layout + setClipPath(shapePath, gd, shapeOptions); + Registry.call('relayout', gd, editHelpers.getUpdateObj()); + } + + function abortDrag() { + removeVisualCues(shapeLayer); + } + + function moveShape(dx, dy) { + if(shapeOptions.type === 'path') { + var noOp = function(coord) { return coord; }, + moveX = noOp, + moveY = noOp; + + if(xPixelSized) { + modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); + } else { + moveX = function moveX(x) { return p2x(x2p(x) + dx); }; + if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); + } + + if(yPixelSized) { + modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); + } else { + moveY = function moveY(y) { return p2y(y2p(y) + dy); }; + if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); + } + + modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); + } + else { + if(xPixelSized) { + modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); + } else { + modifyItem('x0', shapeOptions.x0 = p2x(x0 + dx)); + modifyItem('x1', shapeOptions.x1 = p2x(x1 + dx)); + } + + if(yPixelSized) { + modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); + } else { + modifyItem('y0', shapeOptions.y0 = p2y(y0 + dy)); + modifyItem('y1', shapeOptions.y1 = p2y(y1 + dy)); + } + } + + shapePath.attr('d', getPathString(gd, shapeOptions)); + renderVisualCues(shapeLayer, shapeOptions); + } + + function resizeShape(dx, dy) { + if(isPath) { + // TODO: implement path resize, don't forget to update dragMode code + var noOp = function(coord) { return coord; }, + moveX = noOp, + moveY = noOp; + + if(xPixelSized) { + modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); + } else { + moveX = function moveX(x) { return p2x(x2p(x) + dx); }; + if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); + } + + if(yPixelSized) { + modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); + } else { + moveY = function moveY(y) { return p2y(y2p(y) + dy); }; + if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); + } + + modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); + } + else if(isLine) { + if(dragMode === 'resize-over-start-point') { + var newX0 = x0 + dx; + var newY0 = yPixelSized ? y0 - dy : y0 + dy; + modifyItem('x0', shapeOptions.x0 = xPixelSized ? newX0 : p2x(newX0)); + modifyItem('y0', shapeOptions.y0 = yPixelSized ? newY0 : p2y(newY0)); + } else if(dragMode === 'resize-over-end-point') { + var newX1 = x1 + dx; + var newY1 = yPixelSized ? y1 - dy : y1 + dy; + modifyItem('x1', shapeOptions.x1 = xPixelSized ? newX1 : p2x(newX1)); + modifyItem('y1', shapeOptions.y1 = yPixelSized ? newY1 : p2y(newY1)); + } + } + else { + var newN = (~dragMode.indexOf('n')) ? n0 + dy : n0, + newS = (~dragMode.indexOf('s')) ? s0 + dy : s0, + newW = (~dragMode.indexOf('w')) ? w0 + dx : w0, + newE = (~dragMode.indexOf('e')) ? e0 + dx : e0; + + // Do things in opposing direction for y-axis. + // Hint: for data-sized shapes the reversal of axis direction is done in p2y. + if(~dragMode.indexOf('n') && yPixelSized) newN = n0 - dy; + if(~dragMode.indexOf('s') && yPixelSized) newS = s0 - dy; + + // Update shape eventually. Again, be aware of the + // opposing direction of the y-axis of fixed size shapes. + if((!yPixelSized && newS - newN > MINHEIGHT) || + (yPixelSized && newN - newS > MINHEIGHT)) { + modifyItem(optN, shapeOptions[optN] = yPixelSized ? newN : p2y(newN)); + modifyItem(optS, shapeOptions[optS] = yPixelSized ? newS : p2y(newS)); + } + if(newE - newW > MINWIDTH) { + modifyItem(optW, shapeOptions[optW] = xPixelSized ? newW : p2x(newW)); + modifyItem(optE, shapeOptions[optE] = xPixelSized ? newE : p2x(newE)); + } + } + + shapePath.attr('d', getPathString(gd, shapeOptions)); + renderVisualCues(shapeLayer, shapeOptions); + } + + function renderVisualCues(shapeLayer, shapeOptions) { + if(xPixelSized || yPixelSized) { + renderAnchor(); + } + + function renderAnchor() { + var isNotPath = shapeOptions.type !== 'path'; + + // d3 join with dummy data to satisfy d3 data-binding + var visualCues = shapeLayer.selectAll('.visual-cue').data([0]); + + // Enter + var strokeWidth = 1; + visualCues.enter() + .append('path') + .attr({ + 'fill': '#fff', + 'fill-rule': 'evenodd', + 'stroke': '#000', + 'stroke-width': strokeWidth + }) + .classed('visual-cue', true); + + // Update + var posX = x2p( + xPixelSized ? + shapeOptions.xanchor : + Lib.midRange( + isNotPath ? + [shapeOptions.x0, shapeOptions.x1] : + helpers.extractPathCoords(shapeOptions.path, constants.paramIsX)) + ); + var posY = y2p( + yPixelSized ? + shapeOptions.yanchor : + Lib.midRange( + isNotPath ? + [shapeOptions.y0, shapeOptions.y1] : + helpers.extractPathCoords(shapeOptions.path, constants.paramIsY)) + ); + + posX = helpers.roundPositionForSharpStrokeRendering(posX, strokeWidth); + posY = helpers.roundPositionForSharpStrokeRendering(posY, strokeWidth); + + if(xPixelSized && yPixelSized) { + var crossPath = 'M' + (posX - 1 - strokeWidth) + ',' + (posY - 1 - strokeWidth) + + 'h-8v2h8 v8h2v-8 h8v-2h-8 v-8h-2 Z'; + visualCues.attr('d', crossPath); + } else if(xPixelSized) { + var vBarPath = 'M' + (posX - 1 - strokeWidth) + ',' + (posY - 9 - strokeWidth) + + 'v18 h2 v-18 Z'; + visualCues.attr('d', vBarPath); + } else { + var hBarPath = 'M' + (posX - 9 - strokeWidth) + ',' + (posY - 1 - strokeWidth) + + 'h18 v2 h-18 Z'; + visualCues.attr('d', hBarPath); + } + } + } + + function removeVisualCues(shapeLayer) { + shapeLayer.selectAll('.visual-cue').remove(); + } + + function deactivateClipPathTemporarily(shapePath, shapeOptions, gd) { + var xref = shapeOptions.xref, + yref = shapeOptions.yref, + xa = Axes.getFromId(gd, xref), + ya = Axes.getFromId(gd, yref); + + var clipAxes = ''; + if(xref !== 'paper' && !xa.autorange) clipAxes += xref; + if(yref !== 'paper' && !ya.autorange) clipAxes += yref; + + shapePath.call(Drawing.setClipUrl, clipAxes ? + 'clip' + gd._fullLayout._uid + clipAxes : + null + ); + } +} + +function getPathString(gd, options) { + var type = options.type, + xa = Axes.getFromId(gd, options.xref), + ya = Axes.getFromId(gd, options.yref), + gs = gd._fullLayout._size, + x2r, x2p, y2r, y2p, + x0, x1, y0, y1; + + if(xa) { + x2r = helpers.shapePositionToRange(xa); + x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); }; + } + else { + x2p = function(v) { return gs.l + gs.w * v; }; + } + + if(ya) { + y2r = helpers.shapePositionToRange(ya); + y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); }; + } + else { + y2p = function(v) { return gs.t + gs.h * (1 - v); }; + } + + if(type === 'path') { + if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); + if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); + return convertPath(options, x2p, y2p); + } + + if(options.xsizemode === 'pixel') { + var xAnchorPos = x2p(options.xanchor); + x0 = xAnchorPos + options.x0; + x1 = xAnchorPos + options.x1; + } + else { + x0 = x2p(options.x0); + x1 = x2p(options.x1); + } + + if(options.ysizemode === 'pixel') { + var yAnchorPos = y2p(options.yanchor); + y0 = yAnchorPos - options.y0; + y1 = yAnchorPos - options.y1; + } + else { + y0 = y2p(options.y0); + y1 = y2p(options.y1); + } + + if(type === 'line') return 'M' + x0 + ',' + y0 + 'L' + x1 + ',' + y1; + if(type === 'rect') return 'M' + x0 + ',' + y0 + 'H' + x1 + 'V' + y1 + 'H' + x0 + 'Z'; + // circle + var cx = (x0 + x1) / 2, + cy = (y0 + y1) / 2, + rx = Math.abs(cx - x0), + ry = Math.abs(cy - y0), + rArc = 'A' + rx + ',' + ry, + rightPt = (cx + rx) + ',' + cy, + topPt = cx + ',' + (cy - ry); + return 'M' + rightPt + rArc + ' 0 1,1 ' + topPt + + rArc + ' 0 0,1 ' + rightPt + 'Z'; +} + + +function convertPath(options, x2p, y2p) { + var pathIn = options.path, + xSizemode = options.xsizemode, + ySizemode = options.ysizemode, + xAnchor = options.xanchor, + yAnchor = options.yanchor; + + + return pathIn.replace(constants.segmentRE, function(segment) { + var paramNumber = 0, + segmentType = segment.charAt(0), + xParams = constants.paramIsX[segmentType], + yParams = constants.paramIsY[segmentType], + nParams = constants.numParams[segmentType]; + + var paramString = segment.substr(1).replace(constants.paramRE, function(param) { + if(xParams[paramNumber]) { + if(xSizemode === 'pixel') param = x2p(xAnchor) + Number(param); + else param = x2p(param); + } + else if(yParams[paramNumber]) { + if(ySizemode === 'pixel') param = y2p(yAnchor) - Number(param); + else param = y2p(param); + } + paramNumber++; + + if(paramNumber > nParams) param = 'X'; + return param; + }); + + if(paramNumber > nParams) { + paramString = paramString.replace(/[\s,]*X.*/, ''); + Lib.log('Ignoring extra params in segment ' + segment); + } + + return segmentType + paramString; + }); +} + +function movePath(pathIn, moveX, moveY) { + return pathIn.replace(constants.segmentRE, function(segment) { + var paramNumber = 0, + segmentType = segment.charAt(0), + xParams = constants.paramIsX[segmentType], + yParams = constants.paramIsY[segmentType], + nParams = constants.numParams[segmentType]; + + var paramString = segment.substr(1).replace(constants.paramRE, function(param) { + if(paramNumber >= nParams) return param; + + if(xParams[paramNumber]) param = moveX(param); + else if(yParams[paramNumber]) param = moveY(param); + + paramNumber++; + + return param; + }); + + return segmentType + paramString; + }); +} + +},{"../../lib":696,"../../lib/setcursor":716,"../../plot_api/plot_template":734,"../../plots/cartesian/axes":744,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"./constants":651,"./helpers":654}],654:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var constants = _dereq_('./constants'); + +var Lib = _dereq_('../../lib'); + +// special position conversion functions... category axis positions can't be +// specified by their data values, because they don't make a continuous mapping. +// so these have to be specified in terms of the category serial numbers, +// but can take fractional values. Other axis types we specify position based on +// the actual data values. +// TODO: in V2.0 (when log axis ranges are in data units) range and shape position +// will be identical, so rangeToShapePosition and shapePositionToRange can be +// removed entirely. + +exports.rangeToShapePosition = function(ax) { + return (ax.type === 'log') ? ax.r2d : function(v) { return v; }; +}; + +exports.shapePositionToRange = function(ax) { + return (ax.type === 'log') ? ax.d2r : function(v) { return v; }; +}; + +exports.decodeDate = function(convertToPx) { + return function(v) { + if(v.replace) v = v.replace('_', ' '); + return convertToPx(v); + }; +}; + +exports.encodeDate = function(convertToDate) { + return function(v) { return convertToDate(v).replace(' ', '_'); }; +}; + +exports.extractPathCoords = function(path, paramsToUse) { + var extractedCoordinates = []; + + var segments = path.match(constants.segmentRE); + segments.forEach(function(segment) { + var relevantParamIdx = paramsToUse[segment.charAt(0)].drawn; + if(relevantParamIdx === undefined) return; + + var params = segment.substr(1).match(constants.paramRE); + if(!params || params.length < relevantParamIdx) return; + + extractedCoordinates.push(Lib.cleanNumber(params[relevantParamIdx])); + }); + + return extractedCoordinates; +}; + +exports.getDataToPixel = function(gd, axis, isVertical) { + var gs = gd._fullLayout._size, + dataToPixel; + + if(axis) { + var d2r = exports.shapePositionToRange(axis); + + dataToPixel = function(v) { + return axis._offset + axis.r2p(d2r(v, true)); + }; + + if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); + } + else if(isVertical) { + dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; + } + else { + dataToPixel = function(v) { return gs.l + gs.w * v; }; + } + + return dataToPixel; +}; + +exports.getPixelToData = function(gd, axis, isVertical) { + var gs = gd._fullLayout._size, + pixelToData; + + if(axis) { + var r2d = exports.rangeToShapePosition(axis); + pixelToData = function(p) { return r2d(axis.p2r(p - axis._offset)); }; + } + else if(isVertical) { + pixelToData = function(p) { return 1 - (p - gs.t) / gs.h; }; + } + else { + pixelToData = function(p) { return (p - gs.l) / gs.w; }; + } + + return pixelToData; +}; + +/** + * Based on the given stroke width, rounds the passed + * position value to represent either a full or half pixel. + * + * In case of an odd stroke width (e.g. 1), this measure ensures + * that a stroke positioned at the returned position isn't rendered + * blurry due to anti-aliasing. + * + * In case of an even stroke width (e.g. 2), this measure ensures + * that the position value is transformed to a full pixel value + * so that anti-aliasing doesn't take effect either. + * + * @param {number} pos The raw position value to be transformed + * @param {number} strokeWidth The stroke width + * @returns {number} either an integer or a .5 decimal number + */ +exports.roundPositionForSharpStrokeRendering = function(pos, strokeWidth) { + var strokeWidthIsOdd = Math.round(strokeWidth % 2) === 1; + var posValAsInt = Math.round(pos); + + return strokeWidthIsOdd ? posValAsInt + 0.5 : posValAsInt; +}; + +},{"../../lib":696,"./constants":651}],655:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawModule = _dereq_('./draw'); + +module.exports = { + moduleType: 'component', + name: 'shapes', + + layoutAttributes: _dereq_('./attributes'), + supplyLayoutDefaults: _dereq_('./defaults'), + includeBasePlot: _dereq_('../../plots/cartesian/include_components')('shapes'), + + calcAutorange: _dereq_('./calc_autorange'), + draw: drawModule.draw, + drawOne: drawModule.drawOne +}; + +},{"../../plots/cartesian/include_components":755,"./attributes":649,"./calc_autorange":650,"./defaults":652,"./draw":653}],656:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var padAttrs = _dereq_('../../plots/pad_attributes'); +var extendDeepAll = _dereq_('../../lib/extend').extendDeepAll; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var animationAttrs = _dereq_('../../plots/animation_attributes'); +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; +var constants = _dereq_('./constants'); + +var stepsAttrs = templatedArray('step', { + visible: { + valType: 'boolean', + + dflt: true, + + }, + method: { + valType: 'enumerated', + values: ['restyle', 'relayout', 'animate', 'update', 'skip'], + dflt: 'restyle', + + + }, + args: { + valType: 'info_array', + + freeLength: true, + items: [ + { valType: 'any' }, + { valType: 'any' }, + { valType: 'any' } + ], + + }, + label: { + valType: 'string', + + + }, + value: { + valType: 'string', + + + }, + execute: { + valType: 'boolean', + + dflt: true, + + } +}); + +module.exports = overrideAll(templatedArray('slider', { + visible: { + valType: 'boolean', + + dflt: true, + + }, + + active: { + valType: 'number', + + min: 0, + dflt: 0, + + }, + + steps: stepsAttrs, + + lenmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'fraction', + + }, + len: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + x: { + valType: 'number', + min: -2, + max: 3, + dflt: 0, + + + }, + pad: extendDeepAll({}, padAttrs, { + + }, {t: {dflt: 20}}), + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 0, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'top', + + + }, + + transition: { + duration: { + valType: 'number', + + min: 0, + dflt: 150, + + }, + easing: { + valType: 'enumerated', + values: animationAttrs.transition.easing.values, + + dflt: 'cubic-in-out', + + } + }, + + currentvalue: { + visible: { + valType: 'boolean', + + dflt: true, + + }, + + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + + }, + + offset: { + valType: 'number', + dflt: 10, + + + }, + + prefix: { + valType: 'string', + + + }, + + suffix: { + valType: 'string', + + + }, + + font: fontAttrs({ + + }) + }, + + font: fontAttrs({ + + }), + + activebgcolor: { + valType: 'color', + + dflt: constants.gripBgActiveColor, + + }, + bgcolor: { + valType: 'color', + + dflt: constants.railBgColor, + + }, + bordercolor: { + valType: 'color', + dflt: constants.railBorderColor, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: constants.railBorderWidth, + + + }, + ticklen: { + valType: 'number', + min: 0, + dflt: constants.tickLength, + + + }, + tickcolor: { + valType: 'color', + dflt: constants.tickColor, + + + }, + tickwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + minorticklen: { + valType: 'number', + min: 0, + dflt: constants.minorTickLength, + + + } +}), 'arraydraw', 'from-root'); + +},{"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../../plots/animation_attributes":739,"../../plots/font_attributes":771,"../../plots/pad_attributes":807,"./constants":657}],657:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + + // layout attribute name + name: 'sliders', + + // class names + containerClassName: 'slider-container', + groupClassName: 'slider-group', + inputAreaClass: 'slider-input-area', + railRectClass: 'slider-rail-rect', + railTouchRectClass: 'slider-rail-touch-rect', + gripRectClass: 'slider-grip-rect', + tickRectClass: 'slider-tick-rect', + inputProxyClass: 'slider-input-proxy', + labelsClass: 'slider-labels', + labelGroupClass: 'slider-label-group', + labelClass: 'slider-label', + currentValueClass: 'slider-current-value', + + railHeight: 5, + + // DOM attribute name in button group keeping track + // of active update menu + menuIndexAttrName: 'slider-active-index', + + // id root pass to Plots.autoMargin + autoMarginIdRoot: 'slider-', + + // min item width / height + minWidth: 30, + minHeight: 30, + + // padding around item text + textPadX: 40, + + // arrow offset off right edge + arrowOffsetX: 4, + + railRadius: 2, + railWidth: 5, + railBorder: 4, + railBorderWidth: 1, + railBorderColor: '#bec8d9', + railBgColor: '#f8fafc', + + // The distance of the rail from the edge of the touchable area + // Slightly less than the step inset because of the curved edges + // of the rail + railInset: 8, + + // The distance from the extremal tick marks to the edge of the + // touchable area. This is basically the same as the grip radius, + // but for other styles it wouldn't really need to be. + stepInset: 10, + + gripRadius: 10, + gripWidth: 20, + gripHeight: 20, + gripBorder: 20, + gripBorderWidth: 1, + gripBorderColor: '#bec8d9', + gripBgColor: '#f6f8fa', + gripBgActiveColor: '#dbdde0', + + labelPadding: 8, + labelOffset: 0, + + tickWidth: 1, + tickColor: '#333', + tickOffset: 25, + tickLength: 7, + + minorTickOffset: 25, + minorTickColor: '#333', + minorTickLength: 4, + + // Extra space below the current value label: + currentValuePadding: 8, + currentValueInset: 0, +}; + +},{}],658:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var constants = _dereq_('./constants'); + +var name = constants.name; +var stepAttrs = attributes.steps; + + +module.exports = function slidersDefaults(layoutIn, layoutOut) { + handleArrayContainerDefaults(layoutIn, layoutOut, { + name: name, + handleItemDefaults: sliderDefaults + }); +}; + +function sliderDefaults(sliderIn, sliderOut, layoutOut) { + + function coerce(attr, dflt) { + return Lib.coerce(sliderIn, sliderOut, attributes, attr, dflt); + } + + var steps = handleArrayContainerDefaults(sliderIn, sliderOut, { + name: 'steps', + handleItemDefaults: stepDefaults + }); + + var stepCount = 0; + for(var i = 0; i < steps.length; i++) { + if(steps[i].visible) stepCount++; + } + + var visible; + // If it has fewer than two options, it's not really a slider + if(stepCount < 2) visible = sliderOut.visible = false; + else visible = coerce('visible'); + if(!visible) return; + + sliderOut._stepCount = stepCount; + var visSteps = sliderOut._visibleSteps = Lib.filterVisible(steps); + + var active = coerce('active'); + if(!(steps[active] || {}).visible) sliderOut.active = visSteps[0]._index; + + coerce('x'); + coerce('y'); + Lib.noneOrAll(sliderIn, sliderOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + coerce('len'); + coerce('lenmode'); + + coerce('pad.t'); + coerce('pad.r'); + coerce('pad.b'); + coerce('pad.l'); + + Lib.coerceFont(coerce, 'font', layoutOut.font); + + var currentValueIsVisible = coerce('currentvalue.visible'); + + if(currentValueIsVisible) { + coerce('currentvalue.xanchor'); + coerce('currentvalue.prefix'); + coerce('currentvalue.suffix'); + coerce('currentvalue.offset'); + + Lib.coerceFont(coerce, 'currentvalue.font', sliderOut.font); + } + + coerce('transition.duration'); + coerce('transition.easing'); + + coerce('bgcolor'); + coerce('activebgcolor'); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('ticklen'); + coerce('tickwidth'); + coerce('tickcolor'); + coerce('minorticklen'); +} + +function stepDefaults(valueIn, valueOut) { + function coerce(attr, dflt) { + return Lib.coerce(valueIn, valueOut, stepAttrs, attr, dflt); + } + + var visible; + if(valueIn.method !== 'skip' && !Array.isArray(valueIn.args)) { + visible = valueOut.visible = false; + } + else visible = coerce('visible'); + + if(visible) { + coerce('method'); + coerce('args'); + var label = coerce('label', 'step-' + valueOut._index); + coerce('value', label); + coerce('execute'); + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"./attributes":656,"./constants":657}],659:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Plots = _dereq_('../../plots/plots'); +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var anchorUtils = _dereq_('../legend/anchor_utils'); +var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; + +var constants = _dereq_('./constants'); +var alignmentConstants = _dereq_('../../constants/alignment'); +var LINE_SPACING = alignmentConstants.LINE_SPACING; +var FROM_TL = alignmentConstants.FROM_TL; +var FROM_BR = alignmentConstants.FROM_BR; + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + sliderData = makeSliderData(fullLayout, gd); + + // draw a container for *all* sliders: + var sliders = fullLayout._infolayer + .selectAll('g.' + constants.containerClassName) + .data(sliderData.length > 0 ? [0] : []); + + sliders.enter().append('g') + .classed(constants.containerClassName, true) + .style('cursor', 'ew-resize'); + + function clearSlider(sliderOpts) { + if(sliderOpts._commandObserver) { + sliderOpts._commandObserver.remove(); + delete sliderOpts._commandObserver; + } + + // Most components don't need to explicitly remove autoMargin, because + // marginPushers does this - but slider updates don't go through + // a full replot so we need to explicitly remove it. + Plots.autoMargin(gd, autoMarginId(sliderOpts)); + } + + sliders.exit().each(function() { + d3.select(this).selectAll('g.' + constants.groupClassName) + .each(clearSlider); + }) + .remove(); + + // Return early if no menus visible: + if(sliderData.length === 0) return; + + var sliderGroups = sliders.selectAll('g.' + constants.groupClassName) + .data(sliderData, keyFunction); + + sliderGroups.enter().append('g') + .classed(constants.groupClassName, true); + + sliderGroups.exit() + .each(clearSlider) + .remove(); + + // Find the dimensions of the sliders: + for(var i = 0; i < sliderData.length; i++) { + var sliderOpts = sliderData[i]; + findDimensions(gd, sliderOpts); + } + + sliderGroups.each(function(sliderOpts) { + var gSlider = d3.select(this); + + computeLabelSteps(sliderOpts); + + Plots.manageCommandObserver(gd, sliderOpts, sliderOpts._visibleSteps, function(data) { + // NB: Same as below. This is *not* always the same as sliderOpts since + // if a new set of steps comes in, the reference in this callback would + // be invalid. We need to refetch it from the slider group, which is + // the join data that creates this slider. So if this slider still exists, + // the group should be valid, *to the best of my knowledge.* If not, + // we'd have to look it up by d3 data join index/key. + var opts = gSlider.data()[0]; + + if(opts.active === data.index) return; + if(opts._dragging) return; + + setActive(gd, gSlider, opts, data.index, false, true); + }); + + drawSlider(gd, d3.select(this), sliderOpts); + }); +}; + +function autoMarginId(sliderOpts) { + return constants.autoMarginIdRoot + sliderOpts._index; +} + +// This really only just filters by visibility: +function makeSliderData(fullLayout, gd) { + var contOpts = fullLayout[constants.name], + sliderData = []; + + for(var i = 0; i < contOpts.length; i++) { + var item = contOpts[i]; + if(!item.visible) continue; + item._gd = gd; + sliderData.push(item); + } + + return sliderData; +} + +// This is set in the defaults step: +function keyFunction(opts) { + return opts._index; +} + +// Compute the dimensions (mutates sliderOpts): +function findDimensions(gd, sliderOpts) { + var sliderLabels = Drawing.tester.selectAll('g.' + constants.labelGroupClass) + .data(sliderOpts._visibleSteps); + + sliderLabels.enter().append('g') + .classed(constants.labelGroupClass, true); + + // loop over fake buttons to find width / height + var maxLabelWidth = 0; + var labelHeight = 0; + sliderLabels.each(function(stepOpts) { + var labelGroup = d3.select(this); + + var text = drawLabel(labelGroup, {step: stepOpts}, sliderOpts); + + var textNode = text.node(); + if(textNode) { + var bBox = Drawing.bBox(textNode); + labelHeight = Math.max(labelHeight, bBox.height); + maxLabelWidth = Math.max(maxLabelWidth, bBox.width); + } + }); + + sliderLabels.remove(); + + var dims = sliderOpts._dims = {}; + + dims.inputAreaWidth = Math.max( + constants.railWidth, + constants.gripHeight + ); + + // calculate some overall dimensions - some of these are needed for + // calculating the currentValue dimensions + var graphSize = gd._fullLayout._size; + dims.lx = graphSize.l + graphSize.w * sliderOpts.x; + dims.ly = graphSize.t + graphSize.h * (1 - sliderOpts.y); + + if(sliderOpts.lenmode === 'fraction') { + // fraction: + dims.outerLength = Math.round(graphSize.w * sliderOpts.len); + } else { + // pixels: + dims.outerLength = sliderOpts.len; + } + + // The length of the rail, *excluding* padding on either end: + dims.inputAreaStart = 0; + dims.inputAreaLength = Math.round(dims.outerLength - sliderOpts.pad.l - sliderOpts.pad.r); + + var textableInputLength = dims.inputAreaLength - 2 * constants.stepInset; + var availableSpacePerLabel = textableInputLength / (sliderOpts._stepCount - 1); + var computedSpacePerLabel = maxLabelWidth + constants.labelPadding; + dims.labelStride = Math.max(1, Math.ceil(computedSpacePerLabel / availableSpacePerLabel)); + dims.labelHeight = labelHeight; + + // loop over all possible values for currentValue to find the + // area we need for it + dims.currentValueMaxWidth = 0; + dims.currentValueHeight = 0; + dims.currentValueTotalHeight = 0; + dims.currentValueMaxLines = 1; + + if(sliderOpts.currentvalue.visible) { + // Get the dimensions of the current value label: + var dummyGroup = Drawing.tester.append('g'); + + sliderLabels.each(function(stepOpts) { + var curValPrefix = drawCurrentValue(dummyGroup, sliderOpts, stepOpts.label); + var curValSize = (curValPrefix.node() && Drawing.bBox(curValPrefix.node())) || {width: 0, height: 0}; + var lines = svgTextUtils.lineCount(curValPrefix); + dims.currentValueMaxWidth = Math.max(dims.currentValueMaxWidth, Math.ceil(curValSize.width)); + dims.currentValueHeight = Math.max(dims.currentValueHeight, Math.ceil(curValSize.height)); + dims.currentValueMaxLines = Math.max(dims.currentValueMaxLines, lines); + }); + + dims.currentValueTotalHeight = dims.currentValueHeight + sliderOpts.currentvalue.offset; + + dummyGroup.remove(); + } + + dims.height = dims.currentValueTotalHeight + constants.tickOffset + sliderOpts.ticklen + constants.labelOffset + dims.labelHeight + sliderOpts.pad.t + sliderOpts.pad.b; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(sliderOpts)) { + dims.lx -= dims.outerLength; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(sliderOpts)) { + dims.lx -= dims.outerLength / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(sliderOpts)) { + dims.ly -= dims.height; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(sliderOpts)) { + dims.ly -= dims.height / 2; + yanchor = 'middle'; + } + + dims.outerLength = Math.ceil(dims.outerLength); + dims.height = Math.ceil(dims.height); + dims.lx = Math.round(dims.lx); + dims.ly = Math.round(dims.ly); + + var marginOpts = { + y: sliderOpts.y, + b: dims.height * FROM_BR[yanchor], + t: dims.height * FROM_TL[yanchor] + }; + + if(sliderOpts.lenmode === 'fraction') { + marginOpts.l = 0; + marginOpts.xl = sliderOpts.x - sliderOpts.len * FROM_TL[xanchor]; + marginOpts.r = 0; + marginOpts.xr = sliderOpts.x + sliderOpts.len * FROM_BR[xanchor]; + } + else { + marginOpts.x = sliderOpts.x; + marginOpts.l = dims.outerLength * FROM_TL[xanchor]; + marginOpts.r = dims.outerLength * FROM_BR[xanchor]; + } + + Plots.autoMargin(gd, autoMarginId(sliderOpts), marginOpts); +} + +function drawSlider(gd, sliderGroup, sliderOpts) { + // This is related to the other long notes in this file regarding what happens + // when slider steps disappear. This particular fix handles what happens when + // the *current* slider step is removed. The drawing functions will error out + // when they fail to find it, so the fix for now is that it will just draw the + // slider in the first position but will not execute the command. + if(!((sliderOpts.steps[sliderOpts.active] || {}).visible)) { + sliderOpts.active = sliderOpts._visibleSteps[0]._index; + } + + // These are carefully ordered for proper z-ordering: + sliderGroup + .call(drawCurrentValue, sliderOpts) + .call(drawRail, sliderOpts) + .call(drawLabelGroup, sliderOpts) + .call(drawTicks, sliderOpts) + .call(drawTouchRect, gd, sliderOpts) + .call(drawGrip, gd, sliderOpts); + + var dims = sliderOpts._dims; + + // Position the rectangle: + Drawing.setTranslate(sliderGroup, dims.lx + sliderOpts.pad.l, dims.ly + sliderOpts.pad.t); + + sliderGroup.call(setGripPosition, sliderOpts, false); + sliderGroup.call(drawCurrentValue, sliderOpts); + +} + +function drawCurrentValue(sliderGroup, sliderOpts, valueOverride) { + if(!sliderOpts.currentvalue.visible) return; + + var dims = sliderOpts._dims; + var x0, textAnchor; + + switch(sliderOpts.currentvalue.xanchor) { + case 'right': + // This is anchored left and adjusted by the width of the longest label + // so that the prefix doesn't move. The goal of this is to emphasize + // what's actually changing and make the update less distracting. + x0 = dims.inputAreaLength - constants.currentValueInset - dims.currentValueMaxWidth; + textAnchor = 'left'; + break; + case 'center': + x0 = dims.inputAreaLength * 0.5; + textAnchor = 'middle'; + break; + default: + x0 = constants.currentValueInset; + textAnchor = 'left'; + } + + var text = Lib.ensureSingle(sliderGroup, 'text', constants.labelClass, function(s) { + s.classed('user-select-none', true) + .attr({ + 'text-anchor': textAnchor, + 'data-notex': 1 + }); + }); + + var str = sliderOpts.currentvalue.prefix ? sliderOpts.currentvalue.prefix : ''; + + if(typeof valueOverride === 'string') { + str += valueOverride; + } else { + var curVal = sliderOpts.steps[sliderOpts.active].label; + str += curVal; + } + + if(sliderOpts.currentvalue.suffix) { + str += sliderOpts.currentvalue.suffix; + } + + text.call(Drawing.font, sliderOpts.currentvalue.font) + .text(str) + .call(svgTextUtils.convertToTspans, sliderOpts._gd); + + var lines = svgTextUtils.lineCount(text); + + var y0 = (dims.currentValueMaxLines + 1 - lines) * + sliderOpts.currentvalue.font.size * LINE_SPACING; + + svgTextUtils.positionText(text, x0, y0); + + return text; +} + +function drawGrip(sliderGroup, gd, sliderOpts) { + var grip = Lib.ensureSingle(sliderGroup, 'rect', constants.gripRectClass, function(s) { + s.call(attachGripEvents, gd, sliderGroup, sliderOpts) + .style('pointer-events', 'all'); + }); + + grip.attr({ + width: constants.gripWidth, + height: constants.gripHeight, + rx: constants.gripRadius, + ry: constants.gripRadius, + }) + .call(Color.stroke, sliderOpts.bordercolor) + .call(Color.fill, sliderOpts.bgcolor) + .style('stroke-width', sliderOpts.borderwidth + 'px'); +} + +function drawLabel(item, data, sliderOpts) { + var text = Lib.ensureSingle(item, 'text', constants.labelClass, function(s) { + s.classed('user-select-none', true) + .attr({ + 'text-anchor': 'middle', + 'data-notex': 1 + }); + }); + + text.call(Drawing.font, sliderOpts.font) + .text(data.step.label) + .call(svgTextUtils.convertToTspans, sliderOpts._gd); + + return text; +} + +function drawLabelGroup(sliderGroup, sliderOpts) { + var labels = Lib.ensureSingle(sliderGroup, 'g', constants.labelsClass); + var dims = sliderOpts._dims; + + var labelItems = labels.selectAll('g.' + constants.labelGroupClass) + .data(dims.labelSteps); + + labelItems.enter().append('g') + .classed(constants.labelGroupClass, true); + + labelItems.exit().remove(); + + labelItems.each(function(d) { + var item = d3.select(this); + + item.call(drawLabel, d, sliderOpts); + + Drawing.setTranslate(item, + normalizedValueToPosition(sliderOpts, d.fraction), + constants.tickOffset + + sliderOpts.ticklen + + // position is the baseline of the top line of text only, even + // if the label spans multiple lines + sliderOpts.font.size * LINE_SPACING + + constants.labelOffset + + dims.currentValueTotalHeight + ); + }); + +} + +function handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, doTransition) { + var quantizedPosition = Math.round(normalizedPosition * (sliderOpts._stepCount - 1)); + var quantizedIndex = sliderOpts._visibleSteps[quantizedPosition]._index; + + if(quantizedIndex !== sliderOpts.active) { + setActive(gd, sliderGroup, sliderOpts, quantizedIndex, true, doTransition); + } +} + +function setActive(gd, sliderGroup, sliderOpts, index, doCallback, doTransition) { + var previousActive = sliderOpts.active; + sliderOpts.active = index; + + // due to templating, it's possible this slider doesn't even exist yet + arrayEditor(gd.layout, constants.name, sliderOpts) + .applyUpdate('active', index); + + var step = sliderOpts.steps[sliderOpts.active]; + + sliderGroup.call(setGripPosition, sliderOpts, doTransition); + sliderGroup.call(drawCurrentValue, sliderOpts); + + gd.emit('plotly_sliderchange', { + slider: sliderOpts, + step: sliderOpts.steps[sliderOpts.active], + interaction: doCallback, + previousActive: previousActive + }); + + if(step && step.method && doCallback) { + if(sliderGroup._nextMethod) { + // If we've already queued up an update, just overwrite it with the most recent: + sliderGroup._nextMethod.step = step; + sliderGroup._nextMethod.doCallback = doCallback; + sliderGroup._nextMethod.doTransition = doTransition; + } else { + sliderGroup._nextMethod = {step: step, doCallback: doCallback, doTransition: doTransition}; + sliderGroup._nextMethodRaf = window.requestAnimationFrame(function() { + var _step = sliderGroup._nextMethod.step; + if(!_step.method) return; + + if(_step.execute) { + Plots.executeAPICommand(gd, _step.method, _step.args); + } + + sliderGroup._nextMethod = null; + sliderGroup._nextMethodRaf = null; + }); + } + } +} + +function attachGripEvents(item, gd, sliderGroup) { + var node = sliderGroup.node(); + var $gd = d3.select(gd); + + // NB: This is *not* the same as sliderOpts itself! These callbacks + // are in a closure so this array won't actually be correct if the + // steps have changed since this was initialized. The sliderGroup, + // however, has not changed since that *is* the slider, so it must + // be present to receive mouse events. + function getSliderOpts() { + return sliderGroup.data()[0]; + } + + item.on('mousedown', function() { + var sliderOpts = getSliderOpts(); + gd.emit('plotly_sliderstart', {slider: sliderOpts}); + + var grip = sliderGroup.select('.' + constants.gripRectClass); + + d3.event.stopPropagation(); + d3.event.preventDefault(); + grip.call(Color.fill, sliderOpts.activebgcolor); + + var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); + handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, true); + sliderOpts._dragging = true; + + $gd.on('mousemove', function() { + var sliderOpts = getSliderOpts(); + var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); + handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, false); + }); + + $gd.on('mouseup', function() { + var sliderOpts = getSliderOpts(); + sliderOpts._dragging = false; + grip.call(Color.fill, sliderOpts.bgcolor); + $gd.on('mouseup', null); + $gd.on('mousemove', null); + + gd.emit('plotly_sliderend', { + slider: sliderOpts, + step: sliderOpts.steps[sliderOpts.active] + }); + }); + }); +} + +function drawTicks(sliderGroup, sliderOpts) { + var tick = sliderGroup.selectAll('rect.' + constants.tickRectClass) + .data(sliderOpts._visibleSteps); + var dims = sliderOpts._dims; + + tick.enter().append('rect') + .classed(constants.tickRectClass, true); + + tick.exit().remove(); + + tick.attr({ + width: sliderOpts.tickwidth + 'px', + 'shape-rendering': 'crispEdges' + }); + + tick.each(function(d, i) { + var isMajor = i % dims.labelStride === 0; + var item = d3.select(this); + + item + .attr({height: isMajor ? sliderOpts.ticklen : sliderOpts.minorticklen}) + .call(Color.fill, isMajor ? sliderOpts.tickcolor : sliderOpts.tickcolor); + + Drawing.setTranslate(item, + normalizedValueToPosition(sliderOpts, i / (sliderOpts._stepCount - 1)) - 0.5 * sliderOpts.tickwidth, + (isMajor ? constants.tickOffset : constants.minorTickOffset) + dims.currentValueTotalHeight + ); + }); + +} + +function computeLabelSteps(sliderOpts) { + var dims = sliderOpts._dims; + dims.labelSteps = []; + var nsteps = sliderOpts._stepCount; + + for(var i = 0; i < nsteps; i += dims.labelStride) { + dims.labelSteps.push({ + fraction: i / (nsteps - 1), + step: sliderOpts._visibleSteps[i] + }); + } +} + +function setGripPosition(sliderGroup, sliderOpts, doTransition) { + var grip = sliderGroup.select('rect.' + constants.gripRectClass); + + var quantizedIndex = 0; + for(var i = 0; i < sliderOpts._stepCount; i++) { + if(sliderOpts._visibleSteps[i]._index === sliderOpts.active) { + quantizedIndex = i; + break; + } + } + + var x = normalizedValueToPosition(sliderOpts, quantizedIndex / (sliderOpts._stepCount - 1)); + + // If this is true, then *this component* is already invoking its own command + // and has triggered its own animation. + if(sliderOpts._invokingCommand) return; + + var el = grip; + if(doTransition && sliderOpts.transition.duration > 0) { + el = el.transition() + .duration(sliderOpts.transition.duration) + .ease(sliderOpts.transition.easing); + } + + // Drawing.setTranslate doesn't work here becasue of the transition duck-typing. + // It's also not necessary because there are no other transitions to preserve. + el.attr('transform', 'translate(' + (x - constants.gripWidth * 0.5) + ',' + (sliderOpts._dims.currentValueTotalHeight) + ')'); +} + +// Convert a number from [0-1] to a pixel position relative to the slider group container: +function normalizedValueToPosition(sliderOpts, normalizedPosition) { + var dims = sliderOpts._dims; + return dims.inputAreaStart + constants.stepInset + + (dims.inputAreaLength - 2 * constants.stepInset) * Math.min(1, Math.max(0, normalizedPosition)); +} + +// Convert a position relative to the slider group to a nubmer in [0, 1] +function positionToNormalizedValue(sliderOpts, position) { + var dims = sliderOpts._dims; + return Math.min(1, Math.max(0, (position - constants.stepInset - dims.inputAreaStart) / (dims.inputAreaLength - 2 * constants.stepInset - 2 * dims.inputAreaStart))); +} + +function drawTouchRect(sliderGroup, gd, sliderOpts) { + var dims = sliderOpts._dims; + var rect = Lib.ensureSingle(sliderGroup, 'rect', constants.railTouchRectClass, function(s) { + s.call(attachGripEvents, gd, sliderGroup, sliderOpts) + .style('pointer-events', 'all'); + }); + + rect.attr({ + width: dims.inputAreaLength, + height: Math.max(dims.inputAreaWidth, constants.tickOffset + sliderOpts.ticklen + dims.labelHeight) + }) + .call(Color.fill, sliderOpts.bgcolor) + .attr('opacity', 0); + + Drawing.setTranslate(rect, 0, dims.currentValueTotalHeight); +} + +function drawRail(sliderGroup, sliderOpts) { + var dims = sliderOpts._dims; + var computedLength = dims.inputAreaLength - constants.railInset * 2; + var rect = Lib.ensureSingle(sliderGroup, 'rect', constants.railRectClass); + + rect.attr({ + width: computedLength, + height: constants.railWidth, + rx: constants.railRadius, + ry: constants.railRadius, + 'shape-rendering': 'crispEdges' + }) + .call(Color.stroke, sliderOpts.bordercolor) + .call(Color.fill, sliderOpts.bgcolor) + .style('stroke-width', sliderOpts.borderwidth + 'px'); + + Drawing.setTranslate(rect, + constants.railInset, + (dims.inputAreaWidth - constants.railWidth) * 0.5 + dims.currentValueTotalHeight + ); +} + +},{"../../constants/alignment":668,"../../lib":696,"../../lib/svg_text_utils":720,"../../plot_api/plot_template":734,"../../plots/plots":808,"../color":570,"../drawing":595,"../legend/anchor_utils":622,"./constants":657,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],660:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var constants = _dereq_('./constants'); + +module.exports = { + moduleType: 'component', + name: constants.name, + + layoutAttributes: _dereq_('./attributes'), + supplyLayoutDefaults: _dereq_('./defaults'), + + draw: _dereq_('./draw') +}; + +},{"./attributes":656,"./constants":657,"./defaults":658,"./draw":659}],661:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Plots = _dereq_('../../plots/plots'); +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../drawing'); +var Color = _dereq_('../color'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var interactConstants = _dereq_('../../constants/interactions'); + +module.exports = { + draw: draw +}; + +var numStripRE = / [XY][0-9]* /; + +/** + * Titles - (re)draw titles on the axes and plot: + * @param {DOM element} gd - the graphDiv + * @param {string} titleClass - the css class of this title + * @param {object} options - how and what to draw + * propContainer - the layout object containing `title` and `titlefont` + * attributes that apply to this title + * propName - the full name of the title property (for Plotly.relayout) + * [traceIndex] - include only if this property applies to one trace + * (such as a colorbar title) - then editing pipes to Plotly.restyle + * instead of Plotly.relayout + * placeholder - placeholder text for an empty editable title + * [avoid] {object} - include if this title should move to avoid other elements + * selection - d3 selection of elements to avoid + * side - which direction to move if there is a conflict + * [offsetLeft] - if these elements are subject to a translation + * wrt the title element + * [offsetTop] + * attributes {object} - position and alignment attributes + * x - pixels + * y - pixels + * text-anchor - start|middle|end + * transform {object} - how to transform the title after positioning + * rotate - degrees + * offset - shift up/down in the rotated frame (unused?) + * containerGroup - if an svg element already exists to hold this + * title, include here. Otherwise it will go in fullLayout._infolayer + * + * @return {selection} d3 selection of title container group + */ +function draw(gd, titleClass, options) { + var cont = options.propContainer; + var prop = options.propName; + var placeholder = options.placeholder; + var traceIndex = options.traceIndex; + var avoid = options.avoid || {}; + var attributes = options.attributes; + var transform = options.transform; + var group = options.containerGroup; + + var fullLayout = gd._fullLayout; + var titlefont = cont.titlefont || {}; + var font = titlefont.family; + var fontSize = titlefont.size; + var fontColor = titlefont.color; + + var opacity = 1; + var isplaceholder = false; + var txt = (cont.title || '').trim(); + + // only make this title editable if we positively identify its property + // as one that has editing enabled. + var editAttr; + if(prop === 'title') editAttr = 'titleText'; + else if(prop.indexOf('axis') !== -1) editAttr = 'axisTitleText'; + else if(prop.indexOf('colorbar' !== -1)) editAttr = 'colorbarTitleText'; + var editable = gd._context.edits[editAttr]; + + if(txt === '') opacity = 0; + // look for placeholder text while stripping out numbers from eg X2, Y3 + // this is just for backward compatibility with the old version that had + // "Click to enter X2 title" and may have gotten saved in some old plots, + // we don't want this to show up when these are displayed. + else if(txt.replace(numStripRE, ' % ') === placeholder.replace(numStripRE, ' % ')) { + opacity = 0.2; + isplaceholder = true; + if(!editable) txt = ''; + } + + var elShouldExist = txt || editable; + + if(!group) { + group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass); + } + + var el = group.selectAll('text') + .data(elShouldExist ? [0] : []); + el.enter().append('text'); + el.text(txt) + // this is hacky, but convertToTspans uses the class + // to determine whether to rotate mathJax... + // so we need to clear out any old class and put the + // correct one (only relevant for colorbars, at least + // for now) - ie don't use .classed + .attr('class', titleClass); + el.exit().remove(); + + if(!elShouldExist) return group; + + function titleLayout(titleEl) { + Lib.syncOrAsync([drawTitle, scootTitle], titleEl); + } + + function drawTitle(titleEl) { + var transformVal; + + if(transform) { + transformVal = ''; + if(transform.rotate) { + transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')'; + } + if(transform.offset) { + transformVal += 'translate(0, ' + transform.offset + ')'; + } + } else { + transformVal = null; + } + + titleEl.attr('transform', transformVal); + + titleEl.style({ + 'font-family': font, + 'font-size': d3.round(fontSize, 2) + 'px', + fill: Color.rgb(fontColor), + opacity: opacity * Color.opacity(fontColor), + 'font-weight': Plots.fontWeight + }) + .attr(attributes) + .call(svgTextUtils.convertToTspans, gd); + + return Plots.previousPromises(gd); + } + + function scootTitle(titleElIn) { + var titleGroup = d3.select(titleElIn.node().parentNode); + + if(avoid && avoid.selection && avoid.side && txt) { + titleGroup.attr('transform', null); + + // move toward avoid.side (= left, right, top, bottom) if needed + // can include pad (pixels, default 2) + var shift = 0; + var backside = { + left: 'right', + right: 'left', + top: 'bottom', + bottom: 'top' + }[avoid.side]; + var shiftSign = (['left', 'top'].indexOf(avoid.side) !== -1) ? + -1 : 1; + var pad = isNumeric(avoid.pad) ? avoid.pad : 2; + var titlebb = Drawing.bBox(titleGroup.node()); + var paperbb = { + left: 0, + top: 0, + right: fullLayout.width, + bottom: fullLayout.height + }; + var maxshift = avoid.maxShift || ( + (paperbb[avoid.side] - titlebb[avoid.side]) * + ((avoid.side === 'left' || avoid.side === 'top') ? -1 : 1)); + // Prevent the title going off the paper + if(maxshift < 0) shift = maxshift; + else { + // so we don't have to offset each avoided element, + // give the title the opposite offset + var offsetLeft = avoid.offsetLeft || 0; + var offsetTop = avoid.offsetTop || 0; + titlebb.left -= offsetLeft; + titlebb.right -= offsetLeft; + titlebb.top -= offsetTop; + titlebb.bottom -= offsetTop; + + // iterate over a set of elements (avoid.selection) + // to avoid collisions with + avoid.selection.each(function() { + var avoidbb = Drawing.bBox(this); + + if(Lib.bBoxIntersect(titlebb, avoidbb, pad)) { + shift = Math.max(shift, shiftSign * ( + avoidbb[avoid.side] - titlebb[backside]) + pad); + } + }); + shift = Math.min(maxshift, shift); + } + if(shift > 0 || maxshift < 0) { + var shiftTemplate = { + left: [-shift, 0], + right: [shift, 0], + top: [0, -shift], + bottom: [0, shift] + }[avoid.side]; + titleGroup.attr('transform', + 'translate(' + shiftTemplate + ')'); + } + } + } + + el.call(titleLayout); + + function setPlaceholder() { + opacity = 0; + isplaceholder = true; + el.text(placeholder) + .on('mouseover.opacity', function() { + d3.select(this).transition() + .duration(interactConstants.SHOW_PLACEHOLDER).style('opacity', 1); + }) + .on('mouseout.opacity', function() { + d3.select(this).transition() + .duration(interactConstants.HIDE_PLACEHOLDER).style('opacity', 0); + }); + } + + if(editable) { + if(!txt) setPlaceholder(); + else el.on('.opacity', null); + + el.call(svgTextUtils.makeEditable, {gd: gd}) + .on('edit', function(text) { + if(traceIndex !== undefined) { + Registry.call('restyle', gd, prop, text, traceIndex); + } else { + Registry.call('relayout', gd, prop, text); + } + }) + .on('cancel', function() { + this.text(this.attr('data-unformatted')) + .call(titleLayout); + }) + .on('input', function(d) { + this.text(d || ' ') + .call(svgTextUtils.positionText, attributes.x, attributes.y); + }); + } + el.classed('js-placeholder', isplaceholder); + + return group; +} + +},{"../../constants/interactions":672,"../../lib":696,"../../lib/svg_text_utils":720,"../../plots/plots":808,"../../registry":827,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],662:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var colorAttrs = _dereq_('../color/attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var padAttrs = _dereq_('../../plots/pad_attributes'); +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +var buttonsAttrs = templatedArray('button', { + visible: { + valType: 'boolean', + + + }, + method: { + valType: 'enumerated', + values: ['restyle', 'relayout', 'animate', 'update', 'skip'], + dflt: 'restyle', + + + }, + args: { + valType: 'info_array', + + freeLength: true, + items: [ + {valType: 'any'}, + {valType: 'any'}, + {valType: 'any'} + ], + + }, + label: { + valType: 'string', + + dflt: '', + + }, + execute: { + valType: 'boolean', + + dflt: true, + + } +}); + +module.exports = overrideAll(templatedArray('updatemenu', { + _arrayAttrRegexps: [/^updatemenus\[(0|[1-9][0-9]+)\]\.buttons/], + + visible: { + valType: 'boolean', + + + }, + + type: { + valType: 'enumerated', + values: ['dropdown', 'buttons'], + dflt: 'dropdown', + + + }, + + direction: { + valType: 'enumerated', + values: ['left', 'right', 'up', 'down'], + dflt: 'down', + + + }, + + active: { + valType: 'integer', + + min: -1, + dflt: 0, + + }, + + showactive: { + valType: 'boolean', + + dflt: true, + + }, + + buttons: buttonsAttrs, + + x: { + valType: 'number', + min: -2, + max: 3, + dflt: -0.05, + + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'right', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 1, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'top', + + + }, + + pad: extendFlat({}, padAttrs, { + + }), + + font: fontAttrs({ + + }), + + bgcolor: { + valType: 'color', + + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.borderLine, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'arraydraw', + + } +}), 'arraydraw', 'from-root'); + +},{"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../../plots/font_attributes":771,"../../plots/pad_attributes":807,"../color/attributes":569}],663:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + + // layout attribute name + name: 'updatemenus', + + // class names + containerClassName: 'updatemenu-container', + headerGroupClassName: 'updatemenu-header-group', + headerClassName: 'updatemenu-header', + headerArrowClassName: 'updatemenu-header-arrow', + dropdownButtonGroupClassName: 'updatemenu-dropdown-button-group', + dropdownButtonClassName: 'updatemenu-dropdown-button', + buttonClassName: 'updatemenu-button', + itemRectClassName: 'updatemenu-item-rect', + itemTextClassName: 'updatemenu-item-text', + + // DOM attribute name in button group keeping track + // of active update menu + menuIndexAttrName: 'updatemenu-active-index', + + // id root pass to Plots.autoMargin + autoMarginIdRoot: 'updatemenu-', + + // options when 'active: -1' + blankHeaderOpts: { label: ' ' }, + + // min item width / height + minWidth: 30, + minHeight: 30, + + // padding around item text + textPadX: 24, + arrowPadX: 16, + + // item rect radii + rx: 2, + ry: 2, + + // item text x offset off left edge + textOffsetX: 12, + + // item text y offset (w.r.t. middle) + textOffsetY: 3, + + // arrow offset off right edge + arrowOffsetX: 4, + + // gap between header and buttons + gapButtonHeader: 5, + + // gap between between buttons + gapButton: 2, + + // color given to active buttons + activeColor: '#F4FAFF', + + // color given to hovered buttons + hoverColor: '#F4FAFF', + + // symbol for menu open arrow + arrowSymbol: { + left: '◄', + right: '►', + up: '▲', + down: '▼' + } +}; + +},{}],664:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var constants = _dereq_('./constants'); + +var name = constants.name; +var buttonAttrs = attributes.buttons; + + +module.exports = function updateMenusDefaults(layoutIn, layoutOut) { + var opts = { + name: name, + handleItemDefaults: menuDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + +function menuDefaults(menuIn, menuOut, layoutOut) { + + function coerce(attr, dflt) { + return Lib.coerce(menuIn, menuOut, attributes, attr, dflt); + } + + var buttons = handleArrayContainerDefaults(menuIn, menuOut, { + name: 'buttons', + handleItemDefaults: buttonDefaults + }); + + var visible = coerce('visible', buttons.length > 0); + if(!visible) return; + + coerce('active'); + coerce('direction'); + coerce('type'); + coerce('showactive'); + + coerce('x'); + coerce('y'); + Lib.noneOrAll(menuIn, menuOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + coerce('pad.t'); + coerce('pad.r'); + coerce('pad.b'); + coerce('pad.l'); + + Lib.coerceFont(coerce, 'font', layoutOut.font); + + coerce('bgcolor', layoutOut.paper_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); +} + +function buttonDefaults(buttonIn, buttonOut) { + function coerce(attr, dflt) { + return Lib.coerce(buttonIn, buttonOut, buttonAttrs, attr, dflt); + } + + var visible = coerce('visible', + (buttonIn.method === 'skip' || Array.isArray(buttonIn.args))); + if(visible) { + coerce('method'); + coerce('args'); + coerce('label'); + coerce('execute'); + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"./attributes":662,"./constants":663}],665:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Plots = _dereq_('../../plots/plots'); +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var anchorUtils = _dereq_('../legend/anchor_utils'); +var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; + +var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING; + +var constants = _dereq_('./constants'); +var ScrollBox = _dereq_('./scrollbox'); + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + menuData = Lib.filterVisible(fullLayout[constants.name]); + + /* Update menu data is bound to the header-group. + * The items in the header group are always present. + * + * Upon clicking on a header its corresponding button + * data is bound to the button-group. + * + * We draw all headers in one group before all buttons + * so that the buttons *always* appear above the headers. + * + * Note that only one set of buttons are visible at once. + * + * + * + * + * + * + * + * + * + * ... + * + * + * + * + * ... + */ + + function clearAutoMargin(menuOpts) { + Plots.autoMargin(gd, autoMarginId(menuOpts)); + } + + // draw update menu container + var menus = fullLayout._menulayer + .selectAll('g.' + constants.containerClassName) + .data(menuData.length > 0 ? [0] : []); + + menus.enter().append('g') + .classed(constants.containerClassName, true) + .style('cursor', 'pointer'); + + menus.exit().each(function() { + // Most components don't need to explicitly remove autoMargin, because + // marginPushers does this - but updatemenu updates don't go through + // a full replot so we need to explicitly remove it. + // This is for removing *all* updatemenus, removing individuals is + // handled below, in headerGroups.exit + d3.select(this).selectAll('g.' + constants.headerGroupClassName) + .each(clearAutoMargin); + }).remove(); + + // return early if no update menus are visible + if(menuData.length === 0) return; + + // join header group + var headerGroups = menus.selectAll('g.' + constants.headerGroupClassName) + .data(menuData, keyFunction); + + headerGroups.enter().append('g') + .classed(constants.headerGroupClassName, true); + + // draw dropdown button container + var gButton = Lib.ensureSingle(menus, 'g', constants.dropdownButtonGroupClassName, function(s) { + s.style('pointer-events', 'all'); + }); + + // find dimensions before plotting anything (this mutates menuOpts) + for(var i = 0; i < menuData.length; i++) { + var menuOpts = menuData[i]; + findDimensions(gd, menuOpts); + } + + // setup scrollbox + var scrollBoxId = 'updatemenus' + fullLayout._uid, + scrollBox = new ScrollBox(gd, gButton, scrollBoxId); + + // remove exiting header, remove dropped buttons and reset margins + if(headerGroups.enter().size()) { + // make sure gButton is on top of all headers + gButton.node().parentNode.appendChild(gButton.node()); + gButton.call(removeAllButtons); + } + + headerGroups.exit().each(function(menuOpts) { + gButton.call(removeAllButtons); + clearAutoMargin(menuOpts); + }).remove(); + + // draw headers! + headerGroups.each(function(menuOpts) { + var gHeader = d3.select(this); + + var _gButton = menuOpts.type === 'dropdown' ? gButton : null; + Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) { + setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, scrollBox, data.index, true); + }); + + if(menuOpts.type === 'dropdown') { + drawHeader(gd, gHeader, gButton, scrollBox, menuOpts); + + // if this menu is active, update the dropdown container + if(isActive(gButton, menuOpts)) { + drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); + } + } else { + drawButtons(gd, gHeader, null, null, menuOpts); + } + + }); +}; + +// Note that '_index' is set at the default step, +// it corresponds to the menu index in the user layout update menu container. +// Because a menu can be set invisible, +// this is a more 'consistent' field than the index in the menuData. +function keyFunction(menuOpts) { + return menuOpts._index; +} + +function isFolded(gButton) { + return +gButton.attr(constants.menuIndexAttrName) === -1; +} + +function isActive(gButton, menuOpts) { + return +gButton.attr(constants.menuIndexAttrName) === menuOpts._index; +} + +function setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex, isSilentUpdate) { + // update 'active' attribute in menuOpts + menuOpts.active = buttonIndex; + + // due to templating, it's possible this slider doesn't even exist yet + arrayEditor(gd.layout, constants.name, menuOpts) + .applyUpdate('active', buttonIndex); + + if(menuOpts.type === 'buttons') { + drawButtons(gd, gHeader, null, null, menuOpts); + } + else if(menuOpts.type === 'dropdown') { + // fold up buttons and redraw header + gButton.attr(constants.menuIndexAttrName, '-1'); + + drawHeader(gd, gHeader, gButton, scrollBox, menuOpts); + + if(!isSilentUpdate) { + drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); + } + } +} + +function drawHeader(gd, gHeader, gButton, scrollBox, menuOpts) { + var header = Lib.ensureSingle(gHeader, 'g', constants.headerClassName, function(s) { + s.style('pointer-events', 'all'); + }); + + var dims = menuOpts._dims; + var active = menuOpts.active; + var headerOpts = menuOpts.buttons[active] || constants.blankHeaderOpts; + var posOpts = { y: menuOpts.pad.t, yPad: 0, x: menuOpts.pad.l, xPad: 0, index: 0 }; + var positionOverrides = { + width: dims.headerWidth, + height: dims.headerHeight + }; + + header + .call(drawItem, menuOpts, headerOpts, gd) + .call(setItemPosition, menuOpts, posOpts, positionOverrides); + + // draw drop arrow at the right edge + var arrow = Lib.ensureSingle(gHeader, 'text', constants.headerArrowClassName, function(s) { + s.classed('user-select-none', true) + .attr('text-anchor', 'end') + .call(Drawing.font, menuOpts.font) + .text(constants.arrowSymbol[menuOpts.direction]); + }); + + arrow.attr({ + x: dims.headerWidth - constants.arrowOffsetX + menuOpts.pad.l, + y: dims.headerHeight / 2 + constants.textOffsetY + menuOpts.pad.t + }); + + header.on('click', function() { + gButton.call(removeAllButtons, + String(isActive(gButton, menuOpts) ? -1 : menuOpts._index) + ); + + drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); + }); + + header.on('mouseover', function() { + header.call(styleOnMouseOver); + }); + + header.on('mouseout', function() { + header.call(styleOnMouseOut, menuOpts); + }); + + // translate header group + Drawing.setTranslate(gHeader, dims.lx, dims.ly); +} + +function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) { + // If this is a set of buttons, set pointer events = all since we play + // some minor games with which container is which in order to simplify + // the drawing of *either* buttons or menus + if(!gButton) { + gButton = gHeader; + gButton.attr('pointer-events', 'all'); + } + + var buttonData = (!isFolded(gButton) || menuOpts.type === 'buttons') ? + menuOpts.buttons : + []; + + var klass = menuOpts.type === 'dropdown' ? constants.dropdownButtonClassName : constants.buttonClassName; + + var buttons = gButton.selectAll('g.' + klass) + .data(Lib.filterVisible(buttonData)); + + var enter = buttons.enter().append('g') + .classed(klass, true); + + var exit = buttons.exit(); + + if(menuOpts.type === 'dropdown') { + enter.attr('opacity', '0') + .transition() + .attr('opacity', '1'); + + exit.transition() + .attr('opacity', '0') + .remove(); + } else { + exit.remove(); + } + + var x0 = 0; + var y0 = 0; + var dims = menuOpts._dims; + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + + if(menuOpts.type === 'dropdown') { + if(isVertical) { + y0 = dims.headerHeight + constants.gapButtonHeader; + } else { + x0 = dims.headerWidth + constants.gapButtonHeader; + } + } + + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'up') { + y0 = -constants.gapButtonHeader + constants.gapButton - dims.openHeight; + } + + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'left') { + x0 = -constants.gapButtonHeader + constants.gapButton - dims.openWidth; + } + + var posOpts = { + x: dims.lx + x0 + menuOpts.pad.l, + y: dims.ly + y0 + menuOpts.pad.t, + yPad: constants.gapButton, + xPad: constants.gapButton, + index: 0, + }; + + var scrollBoxPosition = { + l: posOpts.x + menuOpts.borderwidth, + t: posOpts.y + menuOpts.borderwidth + }; + + buttons.each(function(buttonOpts, buttonIndex) { + var button = d3.select(this); + + button + .call(drawItem, menuOpts, buttonOpts, gd) + .call(setItemPosition, menuOpts, posOpts); + + button.on('click', function() { + // skip `dragend` events + if(d3.event.defaultPrevented) return; + + setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex); + + if(buttonOpts.execute) { + Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args); + } + + gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active}); + }); + + button.on('mouseover', function() { + button.call(styleOnMouseOver); + }); + + button.on('mouseout', function() { + button.call(styleOnMouseOut, menuOpts); + buttons.call(styleButtons, menuOpts); + }); + }); + + buttons.call(styleButtons, menuOpts); + + if(isVertical) { + scrollBoxPosition.w = Math.max(dims.openWidth, dims.headerWidth); + scrollBoxPosition.h = posOpts.y - scrollBoxPosition.t; + } + else { + scrollBoxPosition.w = posOpts.x - scrollBoxPosition.l; + scrollBoxPosition.h = Math.max(dims.openHeight, dims.headerHeight); + } + + scrollBoxPosition.direction = menuOpts.direction; + + if(scrollBox) { + if(buttons.size()) { + drawScrollBox(gd, gHeader, gButton, scrollBox, menuOpts, scrollBoxPosition); + } + else { + hideScrollBox(scrollBox); + } + } +} + +function drawScrollBox(gd, gHeader, gButton, scrollBox, menuOpts, position) { + // enable the scrollbox + var direction = menuOpts.direction; + var isVertical = (direction === 'up' || direction === 'down'); + var dims = menuOpts._dims; + + var active = menuOpts.active, + translateX, translateY, + i; + if(isVertical) { + translateY = 0; + for(i = 0; i < active; i++) { + translateY += dims.heights[i] + constants.gapButton; + } + } + else { + translateX = 0; + for(i = 0; i < active; i++) { + translateX += dims.widths[i] + constants.gapButton; + } + } + + scrollBox.enable(position, translateX, translateY); + + if(scrollBox.hbar) { + scrollBox.hbar + .attr('opacity', '0') + .transition() + .attr('opacity', '1'); + } + + if(scrollBox.vbar) { + scrollBox.vbar + .attr('opacity', '0') + .transition() + .attr('opacity', '1'); + } +} + +function hideScrollBox(scrollBox) { + var hasHBar = !!scrollBox.hbar, + hasVBar = !!scrollBox.vbar; + + if(hasHBar) { + scrollBox.hbar + .transition() + .attr('opacity', '0') + .each('end', function() { + hasHBar = false; + if(!hasVBar) scrollBox.disable(); + }); + } + + if(hasVBar) { + scrollBox.vbar + .transition() + .attr('opacity', '0') + .each('end', function() { + hasVBar = false; + if(!hasHBar) scrollBox.disable(); + }); + } +} + +function drawItem(item, menuOpts, itemOpts, gd) { + item.call(drawItemRect, menuOpts) + .call(drawItemText, menuOpts, itemOpts, gd); +} + +function drawItemRect(item, menuOpts) { + var rect = Lib.ensureSingle(item, 'rect', constants.itemRectClassName, function(s) { + s.attr({ + rx: constants.rx, + ry: constants.ry, + 'shape-rendering': 'crispEdges' + }); + }); + + rect.call(Color.stroke, menuOpts.bordercolor) + .call(Color.fill, menuOpts.bgcolor) + .style('stroke-width', menuOpts.borderwidth + 'px'); +} + +function drawItemText(item, menuOpts, itemOpts, gd) { + var text = Lib.ensureSingle(item, 'text', constants.itemTextClassName, function(s) { + s.classed('user-select-none', true) + .attr({ + 'text-anchor': 'start', + 'data-notex': 1 + }); + }); + + text.call(Drawing.font, menuOpts.font) + .text(itemOpts.label) + .call(svgTextUtils.convertToTspans, gd); +} + +function styleButtons(buttons, menuOpts) { + var active = menuOpts.active; + + buttons.each(function(buttonOpts, i) { + var button = d3.select(this); + + if(i === active && menuOpts.showactive) { + button.select('rect.' + constants.itemRectClassName) + .call(Color.fill, constants.activeColor); + } + }); +} + +function styleOnMouseOver(item) { + item.select('rect.' + constants.itemRectClassName) + .call(Color.fill, constants.hoverColor); +} + +function styleOnMouseOut(item, menuOpts) { + item.select('rect.' + constants.itemRectClassName) + .call(Color.fill, menuOpts.bgcolor); +} + +// find item dimensions (this mutates menuOpts) +function findDimensions(gd, menuOpts) { + var dims = menuOpts._dims = { + width1: 0, + height1: 0, + heights: [], + widths: [], + totalWidth: 0, + totalHeight: 0, + openWidth: 0, + openHeight: 0, + lx: 0, + ly: 0 + }; + + var fakeButtons = Drawing.tester.selectAll('g.' + constants.dropdownButtonClassName) + .data(Lib.filterVisible(menuOpts.buttons)); + + fakeButtons.enter().append('g') + .classed(constants.dropdownButtonClassName, true); + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + + // loop over fake buttons to find width / height + fakeButtons.each(function(buttonOpts, i) { + var button = d3.select(this); + + button.call(drawItem, menuOpts, buttonOpts, gd); + + var text = button.select('.' + constants.itemTextClassName); + + // width is given by max width of all buttons + var tWidth = text.node() && Drawing.bBox(text.node()).width; + var wEff = Math.max(tWidth + constants.textPadX, constants.minWidth); + + // height is determined by item text + var tHeight = menuOpts.font.size * LINE_SPACING; + var tLines = svgTextUtils.lineCount(text); + var hEff = Math.max(tHeight * tLines, constants.minHeight) + constants.textOffsetY; + + hEff = Math.ceil(hEff); + wEff = Math.ceil(wEff); + + // Store per-item sizes since a row of horizontal buttons, for example, + // don't all need to be the same width: + dims.widths[i] = wEff; + dims.heights[i] = hEff; + + // Height and width of individual element: + dims.height1 = Math.max(dims.height1, hEff); + dims.width1 = Math.max(dims.width1, wEff); + + if(isVertical) { + dims.totalWidth = Math.max(dims.totalWidth, wEff); + dims.openWidth = dims.totalWidth; + dims.totalHeight += hEff + constants.gapButton; + dims.openHeight += hEff + constants.gapButton; + } else { + dims.totalWidth += wEff + constants.gapButton; + dims.openWidth += wEff + constants.gapButton; + dims.totalHeight = Math.max(dims.totalHeight, hEff); + dims.openHeight = dims.totalHeight; + } + }); + + if(isVertical) { + dims.totalHeight -= constants.gapButton; + } else { + dims.totalWidth -= constants.gapButton; + } + + + dims.headerWidth = dims.width1 + constants.arrowPadX; + dims.headerHeight = dims.height1; + + if(menuOpts.type === 'dropdown') { + if(isVertical) { + dims.width1 += constants.arrowPadX; + dims.totalHeight = dims.height1; + } else { + dims.totalWidth = dims.width1; + } + dims.totalWidth += constants.arrowPadX; + } + + fakeButtons.remove(); + + var paddedWidth = dims.totalWidth + menuOpts.pad.l + menuOpts.pad.r; + var paddedHeight = dims.totalHeight + menuOpts.pad.t + menuOpts.pad.b; + + var graphSize = gd._fullLayout._size; + dims.lx = graphSize.l + graphSize.w * menuOpts.x; + dims.ly = graphSize.t + graphSize.h * (1 - menuOpts.y); + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(menuOpts)) { + dims.lx -= paddedWidth; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(menuOpts)) { + dims.lx -= paddedWidth / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(menuOpts)) { + dims.ly -= paddedHeight; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(menuOpts)) { + dims.ly -= paddedHeight / 2; + yanchor = 'middle'; + } + + dims.totalWidth = Math.ceil(dims.totalWidth); + dims.totalHeight = Math.ceil(dims.totalHeight); + dims.lx = Math.round(dims.lx); + dims.ly = Math.round(dims.ly); + + Plots.autoMargin(gd, autoMarginId(menuOpts), { + x: menuOpts.x, + y: menuOpts.y, + l: paddedWidth * ({right: 1, center: 0.5}[xanchor] || 0), + r: paddedWidth * ({left: 1, center: 0.5}[xanchor] || 0), + b: paddedHeight * ({top: 1, middle: 0.5}[yanchor] || 0), + t: paddedHeight * ({bottom: 1, middle: 0.5}[yanchor] || 0) + }); +} + +function autoMarginId(menuOpts) { + return constants.autoMarginIdRoot + menuOpts._index; +} + +// set item positions (mutates posOpts) +function setItemPosition(item, menuOpts, posOpts, overrideOpts) { + overrideOpts = overrideOpts || {}; + var rect = item.select('.' + constants.itemRectClassName); + var text = item.select('.' + constants.itemTextClassName); + var borderWidth = menuOpts.borderwidth; + var index = posOpts.index; + var dims = menuOpts._dims; + + Drawing.setTranslate(item, borderWidth + posOpts.x, borderWidth + posOpts.y); + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + var finalHeight = overrideOpts.height || (isVertical ? dims.heights[index] : dims.height1); + + rect.attr({ + x: 0, + y: 0, + width: overrideOpts.width || (isVertical ? dims.width1 : dims.widths[index]), + height: finalHeight + }); + + var tHeight = menuOpts.font.size * LINE_SPACING; + var tLines = svgTextUtils.lineCount(text); + var spanOffset = ((tLines - 1) * tHeight / 2); + + svgTextUtils.positionText(text, constants.textOffsetX, + finalHeight / 2 - spanOffset + constants.textOffsetY); + + if(isVertical) { + posOpts.y += dims.heights[index] + posOpts.yPad; + } else { + posOpts.x += dims.widths[index] + posOpts.xPad; + } + + posOpts.index++; +} + +function removeAllButtons(gButton, newMenuIndexAttr) { + gButton + .attr(constants.menuIndexAttrName, newMenuIndexAttr || '-1') + .selectAll('g.' + constants.dropdownButtonClassName).remove(); +} + +},{"../../constants/alignment":668,"../../lib":696,"../../lib/svg_text_utils":720,"../../plot_api/plot_template":734,"../../plots/plots":808,"../color":570,"../drawing":595,"../legend/anchor_utils":622,"./constants":663,"./scrollbox":667,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],666:[function(_dereq_,module,exports){ +arguments[4][660][0].apply(exports,arguments) +},{"./attributes":662,"./constants":663,"./defaults":664,"./draw":665,"dup":660}],667:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = ScrollBox; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Color = _dereq_('../color'); +var Drawing = _dereq_('../drawing'); + +var Lib = _dereq_('../../lib'); + +/** + * Helper class to setup a scroll box + * + * @class + * @param gd Plotly's graph div + * @param container Container to be scroll-boxed (as a D3 selection) + * @param {string} id Id for the clip path to implement the scroll box + */ +function ScrollBox(gd, container, id) { + this.gd = gd; + this.container = container; + this.id = id; + + // See ScrollBox.prototype.enable for further definition + this.position = null; // scrollbox position + this.translateX = null; // scrollbox horizontal translation + this.translateY = null; // scrollbox vertical translation + this.hbar = null; // horizontal scrollbar D3 selection + this.vbar = null; // vertical scrollbar D3 selection + + // element to capture pointer events + this.bg = this.container.selectAll('rect.scrollbox-bg').data([0]); + + this.bg.exit() + .on('.drag', null) + .on('wheel', null) + .remove(); + + this.bg.enter().append('rect') + .classed('scrollbox-bg', true) + .style('pointer-events', 'all') + .attr({ + opacity: 0, + x: 0, + y: 0, + width: 0, + height: 0 + }); +} + +// scroll bar dimensions +ScrollBox.barWidth = 2; +ScrollBox.barLength = 20; +ScrollBox.barRadius = 2; +ScrollBox.barPad = 1; +ScrollBox.barColor = '#808BA4'; + +/** + * If needed, setup a clip path and scrollbars + * + * @method + * @param {Object} position + * @param {number} position.l Left side position (in pixels) + * @param {number} position.t Top side (in pixels) + * @param {number} position.w Width (in pixels) + * @param {number} position.h Height (in pixels) + * @param {string} [position.direction='down'] + * Either 'down', 'left', 'right' or 'up' + * @param {number} [translateX=0] Horizontal offset (in pixels) + * @param {number} [translateY=0] Vertical offset (in pixels) + */ +ScrollBox.prototype.enable = function enable(position, translateX, translateY) { + var fullLayout = this.gd._fullLayout, + fullWidth = fullLayout.width, + fullHeight = fullLayout.height; + + // compute position of scrollbox + this.position = position; + + var l = this.position.l, + w = this.position.w, + t = this.position.t, + h = this.position.h, + direction = this.position.direction, + isDown = (direction === 'down'), + isLeft = (direction === 'left'), + isRight = (direction === 'right'), + isUp = (direction === 'up'), + boxW = w, + boxH = h, + boxL, boxR, + boxT, boxB; + + if(!isDown && !isLeft && !isRight && !isUp) { + this.position.direction = 'down'; + isDown = true; + } + + var isVertical = isDown || isUp; + if(isVertical) { + boxL = l; + boxR = boxL + boxW; + + if(isDown) { + // anchor to top side + boxT = t; + boxB = Math.min(boxT + boxH, fullHeight); + boxH = boxB - boxT; + } + else { + // anchor to bottom side + boxB = t + boxH; + boxT = Math.max(boxB - boxH, 0); + boxH = boxB - boxT; + } + } + else { + boxT = t; + boxB = boxT + boxH; + + if(isLeft) { + // anchor to right side + boxR = l + boxW; + boxL = Math.max(boxR - boxW, 0); + boxW = boxR - boxL; + } + else { + // anchor to left side + boxL = l; + boxR = Math.min(boxL + boxW, fullWidth); + boxW = boxR - boxL; + } + } + + this._box = { + l: boxL, + t: boxT, + w: boxW, + h: boxH + }; + + // compute position of horizontal scroll bar + var needsHorizontalScrollBar = (w > boxW), + hbarW = ScrollBox.barLength + 2 * ScrollBox.barPad, + hbarH = ScrollBox.barWidth + 2 * ScrollBox.barPad, + // draw horizontal scrollbar on the bottom side + hbarL = l, + hbarT = t + h; + + if(hbarT + hbarH > fullHeight) hbarT = fullHeight - hbarH; + + var hbar = this.container.selectAll('rect.scrollbar-horizontal').data( + (needsHorizontalScrollBar) ? [0] : []); + + hbar.exit() + .on('.drag', null) + .remove(); + + hbar.enter().append('rect') + .classed('scrollbar-horizontal', true) + .call(Color.fill, ScrollBox.barColor); + + if(needsHorizontalScrollBar) { + this.hbar = hbar.attr({ + 'rx': ScrollBox.barRadius, + 'ry': ScrollBox.barRadius, + 'x': hbarL, + 'y': hbarT, + 'width': hbarW, + 'height': hbarH + }); + + // hbar center moves between hbarXMin and hbarXMin + hbarTranslateMax + this._hbarXMin = hbarL + hbarW / 2; + this._hbarTranslateMax = boxW - hbarW; + } + else { + delete this.hbar; + delete this._hbarXMin; + delete this._hbarTranslateMax; + } + + // compute position of vertical scroll bar + var needsVerticalScrollBar = (h > boxH), + vbarW = ScrollBox.barWidth + 2 * ScrollBox.barPad, + vbarH = ScrollBox.barLength + 2 * ScrollBox.barPad, + // draw vertical scrollbar on the right side + vbarL = l + w, + vbarT = t; + + if(vbarL + vbarW > fullWidth) vbarL = fullWidth - vbarW; + + var vbar = this.container.selectAll('rect.scrollbar-vertical').data( + (needsVerticalScrollBar) ? [0] : []); + + vbar.exit() + .on('.drag', null) + .remove(); + + vbar.enter().append('rect') + .classed('scrollbar-vertical', true) + .call(Color.fill, ScrollBox.barColor); + + if(needsVerticalScrollBar) { + this.vbar = vbar.attr({ + 'rx': ScrollBox.barRadius, + 'ry': ScrollBox.barRadius, + 'x': vbarL, + 'y': vbarT, + 'width': vbarW, + 'height': vbarH + }); + + // vbar center moves between vbarYMin and vbarYMin + vbarTranslateMax + this._vbarYMin = vbarT + vbarH / 2; + this._vbarTranslateMax = boxH - vbarH; + } + else { + delete this.vbar; + delete this._vbarYMin; + delete this._vbarTranslateMax; + } + + // setup a clip path (if scroll bars are needed) + var clipId = this.id, + clipL = boxL - 0.5, + clipR = (needsVerticalScrollBar) ? boxR + vbarW + 0.5 : boxR + 0.5, + clipT = boxT - 0.5, + clipB = (needsHorizontalScrollBar) ? boxB + hbarH + 0.5 : boxB + 0.5; + + var clipPath = fullLayout._topdefs.selectAll('#' + clipId) + .data((needsHorizontalScrollBar || needsVerticalScrollBar) ? [0] : []); + + clipPath.exit().remove(); + + clipPath.enter() + .append('clipPath').attr('id', clipId) + .append('rect'); + + if(needsHorizontalScrollBar || needsVerticalScrollBar) { + this._clipRect = clipPath.select('rect').attr({ + x: Math.floor(clipL), + y: Math.floor(clipT), + width: Math.ceil(clipR) - Math.floor(clipL), + height: Math.ceil(clipB) - Math.floor(clipT) + }); + + this.container.call(Drawing.setClipUrl, clipId); + + this.bg.attr({ + x: l, + y: t, + width: w, + height: h + }); + } + else { + this.bg.attr({ + width: 0, + height: 0 + }); + this.container + .on('wheel', null) + .on('.drag', null) + .call(Drawing.setClipUrl, null); + delete this._clipRect; + } + + // set up drag listeners (if scroll bars are needed) + if(needsHorizontalScrollBar || needsVerticalScrollBar) { + var onBoxDrag = d3.behavior.drag() + .on('dragstart', function() { + d3.event.sourceEvent.preventDefault(); + }) + .on('drag', this._onBoxDrag.bind(this)); + + this.container + .on('wheel', null) + .on('wheel', this._onBoxWheel.bind(this)) + .on('.drag', null) + .call(onBoxDrag); + + var onBarDrag = d3.behavior.drag() + .on('dragstart', function() { + d3.event.sourceEvent.preventDefault(); + d3.event.sourceEvent.stopPropagation(); + }) + .on('drag', this._onBarDrag.bind(this)); + + if(needsHorizontalScrollBar) { + this.hbar + .on('.drag', null) + .call(onBarDrag); + } + + if(needsVerticalScrollBar) { + this.vbar + .on('.drag', null) + .call(onBarDrag); + } + } + + // set scrollbox translation + this.setTranslate(translateX, translateY); +}; + +/** + * If present, remove clip-path and scrollbars + * + * @method + */ +ScrollBox.prototype.disable = function disable() { + if(this.hbar || this.vbar) { + this.bg.attr({ + width: 0, + height: 0 + }); + this.container + .on('wheel', null) + .on('.drag', null) + .call(Drawing.setClipUrl, null); + delete this._clipRect; + } + + if(this.hbar) { + this.hbar.on('.drag', null); + this.hbar.remove(); + delete this.hbar; + delete this._hbarXMin; + delete this._hbarTranslateMax; + } + + if(this.vbar) { + this.vbar.on('.drag', null); + this.vbar.remove(); + delete this.vbar; + delete this._vbarYMin; + delete this._vbarTranslateMax; + } +}; + +/** + * Handles scroll box drag events + * + * @method + */ +ScrollBox.prototype._onBoxDrag = function onBarDrag() { + var translateX = this.translateX, + translateY = this.translateY; + + if(this.hbar) { + translateX -= d3.event.dx; + } + + if(this.vbar) { + translateY -= d3.event.dy; + } + + this.setTranslate(translateX, translateY); +}; + +/** + * Handles scroll box wheel events + * + * @method + */ +ScrollBox.prototype._onBoxWheel = function onBarWheel() { + var translateX = this.translateX, + translateY = this.translateY; + + if(this.hbar) { + translateX += d3.event.deltaY; + } + + if(this.vbar) { + translateY += d3.event.deltaY; + } + + this.setTranslate(translateX, translateY); +}; + +/** + * Handles scroll bar drag events + * + * @method + */ +ScrollBox.prototype._onBarDrag = function onBarDrag() { + var translateX = this.translateX, + translateY = this.translateY; + + if(this.hbar) { + var xMin = translateX + this._hbarXMin, + xMax = xMin + this._hbarTranslateMax, + x = Lib.constrain(d3.event.x, xMin, xMax), + xf = (x - xMin) / (xMax - xMin); + + var translateXMax = this.position.w - this._box.w; + + translateX = xf * translateXMax; + } + + if(this.vbar) { + var yMin = translateY + this._vbarYMin, + yMax = yMin + this._vbarTranslateMax, + y = Lib.constrain(d3.event.y, yMin, yMax), + yf = (y - yMin) / (yMax - yMin); + + var translateYMax = this.position.h - this._box.h; + + translateY = yf * translateYMax; + } + + this.setTranslate(translateX, translateY); +}; + +/** + * Set clip path and scroll bar translate transform + * + * @method + * @param {number} [translateX=0] Horizontal offset (in pixels) + * @param {number} [translateY=0] Vertical offset (in pixels) + */ +ScrollBox.prototype.setTranslate = function setTranslate(translateX, translateY) { + // store translateX and translateY (needed by mouse event handlers) + var translateXMax = this.position.w - this._box.w, + translateYMax = this.position.h - this._box.h; + + translateX = Lib.constrain(translateX || 0, 0, translateXMax); + translateY = Lib.constrain(translateY || 0, 0, translateYMax); + + this.translateX = translateX; + this.translateY = translateY; + + this.container.call(Drawing.setTranslate, + this._box.l - this.position.l - translateX, + this._box.t - this.position.t - translateY); + + if(this._clipRect) { + this._clipRect.attr({ + x: Math.floor(this.position.l + translateX - 0.5), + y: Math.floor(this.position.t + translateY - 0.5) + }); + } + + if(this.hbar) { + var xf = translateX / translateXMax; + + this.hbar.call(Drawing.setTranslate, + translateX + xf * this._hbarTranslateMax, + translateY); + } + + if(this.vbar) { + var yf = translateY / translateYMax; + + this.vbar.call(Drawing.setTranslate, + translateX, + translateY + yf * this._vbarTranslateMax); + } +}; + +},{"../../lib":696,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],668:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// fraction of some size to get to a named position +module.exports = { + // from bottom left: this is the origin of our paper-reference + // positioning system + FROM_BL: { + left: 0, + center: 0.5, + right: 1, + bottom: 0, + middle: 0.5, + top: 1 + }, + // from top left: this is the screen pixel positioning origin + FROM_TL: { + left: 0, + center: 0.5, + right: 1, + bottom: 1, + middle: 0.5, + top: 0 + }, + // from bottom right: sometimes you just need the opposite of ^^ + FROM_BR: { + left: 1, + center: 0.5, + right: 0, + bottom: 0, + middle: 0.5, + top: 1 + }, + // multiple of fontSize to get the vertical offset between lines + LINE_SPACING: 1.3, + + // multiple of fontSize to shift from the baseline to the midline + // (to use when we don't calculate this shift from Drawing.bBox) + // To be precise this should be half the cap height (capital letter) + // of the font, and according to wikipedia: + // an "average" font might have a cap height of 70% of the em + // https://en.wikipedia.org/wiki/Em_(typography)#History + MID_SHIFT: 0.35, + + OPPOSITE_SIDE: { + left: 'right', + right: 'left', + top: 'bottom', + bottom: 'top' + } +}; + +},{}],669:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + COMPARISON_OPS: ['=', '!=', '<', '>=', '>', '<='], + COMPARISON_OPS2: ['=', '<', '>=', '>', '<='], + INTERVAL_OPS: ['[]', '()', '[)', '(]', '][', ')(', '](', ')['], + SET_OPS: ['{}', '}{'], + CONSTRAINT_REDUCTION: { + // for contour constraints, open/closed endpoints are equivalent + '=': '=', + + '<': '<', + '<=': '<', + + '>': '>', + '>=': '>', + + '[]': '[]', + '()': '[]', + '[)': '[]', + '(]': '[]', + + '][': '][', + ')(': '][', + '](': '][', + ')[': '][' + } +}; + +},{}],670:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + solid: [[], 0], + dot: [[0.5, 1], 200], + dash: [[0.5, 1], 50], + longdash: [[0.5, 1], 10], + dashdot: [[0.5, 0.625, 0.875, 1], 50], + longdashdot: [[0.5, 0.7, 0.8, 1], 10] +}; + +},{}],671:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + circle: '●', + 'circle-open': '○', + square: '■', + 'square-open': '□', + diamond: '◆', + 'diamond-open': '◇', + cross: '+', + x: '❌' +}; + +},{}],672:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + /** + * Timing information for interactive elements + */ + SHOW_PLACEHOLDER: 100, + HIDE_PLACEHOLDER: 1000, + + // ms between first mousedown and 2nd mouseup to constitute dblclick... + // we don't seem to have access to the system setting + DBLCLICKDELAY: 300, + + // opacity dimming fraction for points that are not in selection + DESELECTDIM: 0.2 +}; + +},{}],673:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + /** + * Standardize all missing data in calcdata to use undefined + * never null or NaN. + * That way we can use !==undefined, or !== BADNUM, + * to test for real data + */ + BADNUM: undefined, + + /* + * Limit certain operations to well below floating point max value + * to avoid glitches: Make sure that even when you multiply it by the + * number of pixels on a giant screen it still works + */ + FP_SAFE: Number.MAX_VALUE / 10000, + + /* + * conversion of date units to milliseconds + * year and month constants are marked "AVG" + * to remind us that not all years and months + * have the same length + */ + ONEAVGYEAR: 31557600000, // 365.25 days + ONEAVGMONTH: 2629800000, // 1/12 of ONEAVGYEAR + ONEDAY: 86400000, + ONEHOUR: 3600000, + ONEMIN: 60000, + ONESEC: 1000, + + /* + * For fast conversion btwn world calendars and epoch ms, the Julian Day Number + * of the unix epoch. From calendars.instance().newDate(1970, 1, 1).toJD() + */ + EPOCHJD: 2440587.5, + + /* + * Are two values nearly equal? Compare to 1PPM + */ + ALMOST_EQUAL: 1 - 1e-6, + + /* + * If we're asked to clip a non-positive log value, how far off-screen + * do we put it? + */ + LOG_CLIP: 10, + + /* + * not a number, but for displaying numbers: the "minus sign" symbol is + * wider than the regular ascii dash "-" + */ + MINUS_SIGN: '\u2212' +}; + +},{}],674:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +exports.xmlns = 'http://www.w3.org/2000/xmlns/'; +exports.svg = 'http://www.w3.org/2000/svg'; +exports.xlink = 'http://www.w3.org/1999/xlink'; + +// the 'old' d3 quirk got fix in v3.5.7 +// https://github.com/mbostock/d3/commit/a6f66e9dd37f764403fc7c1f26be09ab4af24fed +exports.svgAttrs = { + xmlns: exports.svg, + 'xmlns:xlink': exports.xlink +}; + +},{}],675:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// package version injected by `npm run preprocess` +exports.version = '1.42.2'; + +// inject promise polyfill +_dereq_('es6-promise').polyfill(); + +// inject plot css +_dereq_('../build/plotcss'); + +// inject default MathJax config +_dereq_('./fonts/mathjax_config'); + +// include registry module and expose register method +var Registry = _dereq_('./registry'); +var register = exports.register = Registry.register; + +// expose plot api methods +var plotApi = _dereq_('./plot_api'); +var methodNames = Object.keys(plotApi); +for(var i = 0; i < methodNames.length; i++) { + var name = methodNames[i]; + exports[name] = plotApi[name]; + register({ + moduleType: 'apiMethod', + name: name, + fn: plotApi[name] + }); +} + +// scatter is the only trace included by default +register(_dereq_('./traces/scatter')); + +// register all registrable components modules +register([ + _dereq_('./components/fx'), + _dereq_('./components/legend'), + _dereq_('./components/annotations'), + _dereq_('./components/annotations3d'), + _dereq_('./components/shapes'), + _dereq_('./components/images'), + _dereq_('./components/updatemenus'), + _dereq_('./components/sliders'), + _dereq_('./components/rangeslider'), + _dereq_('./components/rangeselector'), + _dereq_('./components/grid'), + _dereq_('./components/errorbars') +]); + +// locales en and en-US are required for default behavior +register([ + _dereq_('./locale-en'), + _dereq_('./locale-en-us') +]); + +// plot icons +exports.Icons = _dereq_('../build/ploticon'); + +// unofficial 'beta' plot methods, use at your own risk +exports.Plots = _dereq_('./plots/plots'); +exports.Fx = _dereq_('./components/fx'); +exports.Snapshot = _dereq_('./snapshot'); +exports.PlotSchema = _dereq_('./plot_api/plot_schema'); +exports.Queue = _dereq_('./lib/queue'); + +// export d3 used in the bundle +exports.d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +},{"../build/plotcss":1,"../build/ploticon":2,"./components/annotations":561,"./components/annotations3d":566,"./components/errorbars":601,"./components/fx":612,"./components/grid":616,"./components/images":621,"./components/legend":630,"./components/rangeselector":641,"./components/rangeslider":647,"./components/shapes":655,"./components/sliders":660,"./components/updatemenus":666,"./fonts/mathjax_config":676,"./lib/queue":711,"./locale-en":725,"./locale-en-us":724,"./plot_api":729,"./plot_api/plot_schema":733,"./plots/plots":808,"./registry":827,"./snapshot":832,"./traces/scatter":1055,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"es6-promise":203}],676:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* global MathJax:false */ + +/** + * Check and configure MathJax + */ +if(typeof MathJax !== 'undefined') { + exports.MathJax = true; + + var globalConfig = (window.PlotlyConfig || {}).MathJaxConfig !== 'local'; + + if(globalConfig) { + MathJax.Hub.Config({ + messageStyle: 'none', + skipStartupTypeset: true, + displayAlign: 'left', + tex2jax: { + inlineMath: [['$', '$'], ['\\(', '\\)']] + } + }); + MathJax.Hub.Configured(); + } + +} else { + exports.MathJax = false; +} + +},{}],677:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var modModule = _dereq_('./mod'); +var mod = modModule.mod; +var modHalf = modModule.modHalf; + +var PI = Math.PI; +var twoPI = 2 * PI; + +function deg2rad(deg) { return deg / 180 * PI; } + +function rad2deg(rad) { return rad / PI * 180; } + +/** + * is sector a full circle? + * ... this comes up a lot in SVG path-drawing routines + * + * N.B. we consider all sectors that span more that 2pi 'full' circles + * + * @param {2-item array} aBnds : angular bounds in *radians* + * @return {boolean} + */ +function isFullCircle(aBnds) { + return Math.abs(aBnds[1] - aBnds[0]) > twoPI - 1e-15; +} + +/** + * angular delta between angle 'a' and 'b' + * solution taken from: https://stackoverflow.com/a/2007279 + * + * @param {number} a : first angle in *radians* + * @param {number} b : second angle in *radians* + * @return {number} angular delta in *radians* + */ +function angleDelta(a, b) { + return modHalf(b - a, twoPI); +} + +/** + * angular distance between angle 'a' and 'b' + * + * @param {number} a : first angle in *radians* + * @param {number} b : second angle in *radians* + * @return {number} angular distance in *radians* + */ +function angleDist(a, b) { + return Math.abs(angleDelta(a, b)); +} + +/** + * is angle inside sector? + * + * @param {number} a : angle to test in *radians* + * @param {2-item array} aBnds : sector's angular bounds in *radians* + * @param {boolean} + */ +function isAngleInsideSector(a, aBnds) { + if(isFullCircle(aBnds)) return true; + + var s0, s1; + + if(aBnds[0] < aBnds[1]) { + s0 = aBnds[0]; + s1 = aBnds[1]; + } else { + s0 = aBnds[1]; + s1 = aBnds[0]; + } + + s0 = mod(s0, twoPI); + s1 = mod(s1, twoPI); + if(s0 > s1) s1 += twoPI; + + var a0 = mod(a, twoPI); + var a1 = a0 + twoPI; + + return (a0 >= s0 && a0 <= s1) || (a1 >= s0 && a1 <= s1); +} + +/** + * is pt (r,a) inside sector? + * + * @param {number} r : pt's radial coordinate + * @param {number} a : pt's angular coordinate in *radians* + * @param {2-item array} rBnds : sector's radial bounds + * @param {2-item array} aBnds : sector's angular bounds in *radians* + * @return {boolean} + */ +function isPtInsideSector(r, a, rBnds, aBnds) { + if(!isAngleInsideSector(a, aBnds)) return false; + + var r0, r1; + + if(rBnds[0] < rBnds[1]) { + r0 = rBnds[0]; + r1 = rBnds[1]; + } else { + r0 = rBnds[1]; + r1 = rBnds[0]; + } + + return r >= r0 && r <= r1; +} + +// common to pathArc, pathSector and pathAnnulus +function _path(r0, r1, a0, a1, cx, cy, isClosed) { + cx = cx || 0; + cy = cy || 0; + + var isCircle = isFullCircle([a0, a1]); + var aStart, aMid, aEnd; + var rStart, rEnd; + + if(isCircle) { + aStart = 0; + aMid = PI; + aEnd = twoPI; + } else { + if(a0 < a1) { + aStart = a0; + aEnd = a1; + } else { + aStart = a1; + aEnd = a0; + } + } + + if(r0 < r1) { + rStart = r0; + rEnd = r1; + } else { + rStart = r1; + rEnd = r0; + } + + // N.B. svg coordinates here, where y increases downward + function pt(r, a) { + return [r * Math.cos(a) + cx, cy - r * Math.sin(a)]; + } + + var largeArc = Math.abs(aEnd - aStart) <= PI ? 0 : 1; + function arc(r, a, cw) { + return 'A' + [r, r] + ' ' + [0, largeArc, cw] + ' ' + pt(r, a); + } + + var p; + + if(isCircle) { + if(rStart === null) { + p = 'M' + pt(rEnd, aStart) + + arc(rEnd, aMid, 0) + + arc(rEnd, aEnd, 0) + 'Z'; + } else { + p = 'M' + pt(rStart, aStart) + + arc(rStart, aMid, 0) + + arc(rStart, aEnd, 0) + 'Z' + + 'M' + pt(rEnd, aStart) + + arc(rEnd, aMid, 1) + + arc(rEnd, aEnd, 1) + 'Z'; + } + } else { + if(rStart === null) { + p = 'M' + pt(rEnd, aStart) + arc(rEnd, aEnd, 0); + if(isClosed) p += 'L0,0Z'; + } else { + p = 'M' + pt(rStart, aStart) + + 'L' + pt(rEnd, aStart) + + arc(rEnd, aEnd, 0) + + 'L' + pt(rStart, aEnd) + + arc(rStart, aStart, 1) + 'Z'; + } + } + + return p; +} + +/** + * path an arc + * + * @param {number} r : radius + * @param {number} a0 : first angular coordinate in *radians* + * @param {number} a1 : second angular coordinate in *radians* + * @param {number (optional)} cx : x coordinate of center + * @param {number (optional)} cy : y coordinate of center + * @return {string} svg path + */ +function pathArc(r, a0, a1, cx, cy) { + return _path(null, r, a0, a1, cx, cy, 0); +} + +/** + * path a sector + * + * @param {number} r : radius + * @param {number} a0 : first angular coordinate in *radians* + * @param {number} a1 : second angular coordinate in *radians* + * @param {number (optional)} cx : x coordinate of center + * @param {number (optional)} cy : y coordinate of center + * @return {string} svg path + */ +function pathSector(r, a0, a1, cx, cy) { + return _path(null, r, a0, a1, cx, cy, 1); +} + +/** + * path an annulus + * + * @param {number} r0 : first radial coordinate + * @param {number} r1 : second radial coordinate + * @param {number} a0 : first angular coordinate in *radians* + * @param {number} a1 : second angular coordinate in *radians* + * @param {number (optional)} cx : x coordinate of center + * @param {number (optional)} cy : y coordinate of center + * @return {string} svg path + */ +function pathAnnulus(r0, r1, a0, a1, cx, cy) { + return _path(r0, r1, a0, a1, cx, cy, 1); +} + +module.exports = { + deg2rad: deg2rad, + rad2deg: rad2deg, + angleDelta: angleDelta, + angleDist: angleDist, + isFullCircle: isFullCircle, + isAngleInsideSector: isAngleInsideSector, + isPtInsideSector: isPtInsideSector, + pathArc: pathArc, + pathSector: pathSector, + pathAnnulus: pathAnnulus +}; + +},{"./mod":703}],678:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArray = Array.isArray; + +// IE9 fallbacks + +var ab = (typeof ArrayBuffer === 'undefined' || !ArrayBuffer.isView) ? + {isView: function() { return false; }} : + ArrayBuffer; + +var dv = (typeof DataView === 'undefined') ? + function() {} : + DataView; + +function isTypedArray(a) { + return ab.isView(a) && !(a instanceof dv); +} +exports.isTypedArray = isTypedArray; + +function isArrayOrTypedArray(a) { + return isArray(a) || isTypedArray(a); +} +exports.isArrayOrTypedArray = isArrayOrTypedArray; + +/* + * Test whether an input object is 1D. + * + * Assumes we already know the object is an array. + * + * Looks only at the first element, if the dimensionality is + * not consistent we won't figure that out here. + */ +function isArray1D(a) { + return !isArrayOrTypedArray(a[0]); +} +exports.isArray1D = isArray1D; + +/* + * Ensures an array has the right amount of storage space. If it doesn't + * exist, it creates an array. If it does exist, it returns it if too + * short or truncates it in-place. + * + * The goal is to just reuse memory to avoid a bit of excessive garbage + * collection. + */ +exports.ensureArray = function(out, n) { + // TODO: typed array support here? This is only used in + // traces/carpet/compute_control_points + if(!isArray(out)) out = []; + + // If too long, truncate. (If too short, it will grow + // automatically so we don't care about that case) + out.length = n; + + return out; +}; + +/* + * TypedArray-compatible concatenation of n arrays + * if all arrays are the same type it will preserve that type, + * otherwise it falls back on Array. + * Also tries to avoid copying, in case one array has zero length + * But never mutates an existing array + */ +exports.concat = function() { + var args = []; + var allArray = true; + var totalLen = 0; + + var _constructor, arg0, i, argi, posi, leni, out, j; + + for(i = 0; i < arguments.length; i++) { + argi = arguments[i]; + leni = argi.length; + if(leni) { + if(arg0) args.push(argi); + else { + arg0 = argi; + posi = leni; + } + + if(isArray(argi)) { + _constructor = false; + } + else { + allArray = false; + if(!totalLen) { + _constructor = argi.constructor; + } + else if(_constructor !== argi.constructor) { + // TODO: in principle we could upgrade here, + // ie keep typed array but convert all to Float64Array? + _constructor = false; + } + } + + totalLen += leni; + } + } + + if(!totalLen) return []; + if(!args.length) return arg0; + + if(allArray) return arg0.concat.apply(arg0, args); + if(_constructor) { + // matching typed arrays + out = new _constructor(totalLen); + out.set(arg0); + for(i = 0; i < args.length; i++) { + argi = args[i]; + out.set(argi, posi); + posi += argi.length; + } + return out; + } + + // mismatched types or Array + typed + out = new Array(totalLen); + for(j = 0; j < arg0.length; j++) out[j] = arg0[j]; + for(i = 0; i < args.length; i++) { + argi = args[i]; + for(j = 0; j < argi.length; j++) out[posi + j] = argi[j]; + posi += j; + } + return out; +}; + +},{}],679:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var BADNUM = _dereq_('../constants/numerical').BADNUM; + +// precompile for speed +var JUNK = /^['"%,$#\s']+|[, ]|['"%,$#\s']+$/g; + +/** + * cleanNumber: remove common leading and trailing cruft + * Always returns either a number or BADNUM. + */ +module.exports = function cleanNumber(v) { + if(typeof v === 'string') { + v = v.replace(JUNK, ''); + } + + if(isNumeric(v)) return Number(v); + + return BADNUM; +}; + +},{"../constants/numerical":673,"fast-isnumeric":214}],680:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Clear gl frame (if any). This is a common pattern as + * we usually set `preserveDrawingBuffer: true` during + * gl context creation (e.g. via `reglUtils.prepare`). + * + * @param {DOM node or object} gd : graph div object + */ +module.exports = function clearGlCanvases(gd) { + var fullLayout = gd._fullLayout; + + if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { + fullLayout._glcanvas.each(function(d) { + if(d.regl) d.regl.clear({color: true, depth: true}); + }); + } +}; + +},{}],681:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Clear responsive handlers (if any). + * + * @param {DOM node or object} gd : graph div object + */ +module.exports = function clearResponsive(gd) { + if(gd._responsiveChartHandler) { + window.removeEventListener('resize', gd._responsiveChartHandler); + delete gd._responsiveChartHandler; + } +}; + +},{}],682:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var tinycolor = _dereq_('tinycolor2'); + +var baseTraceAttrs = _dereq_('../plots/attributes'); +var getColorscale = _dereq_('../components/colorscale/get_scale'); +var colorscaleNames = Object.keys(_dereq_('../components/colorscale/scales')); +var nestedProperty = _dereq_('./nested_property'); +var counterRegex = _dereq_('./regex').counter; +var DESELECTDIM = _dereq_('../constants/interactions').DESELECTDIM; +var modHalf = _dereq_('./mod').modHalf; +var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; + +exports.valObjectMeta = { + data_array: { + // You can use *dflt=[] to force said array to exist though. + + + + coerceFunction: function(v, propOut, dflt) { + // TODO maybe `v: {type: 'float32', vals: [/* ... */]}` also + if(isArrayOrTypedArray(v)) propOut.set(v); + else if(dflt !== undefined) propOut.set(dflt); + } + }, + enumerated: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(opts.coerceNumber) v = +v; + if(opts.values.indexOf(v) === -1) propOut.set(dflt); + else propOut.set(v); + }, + validateFunction: function(v, opts) { + if(opts.coerceNumber) v = +v; + + var values = opts.values; + for(var i = 0; i < values.length; i++) { + var k = String(values[i]); + + if((k.charAt(0) === '/' && k.charAt(k.length - 1) === '/')) { + var regex = new RegExp(k.substr(1, k.length - 2)); + if(regex.test(v)) return true; + } else if(v === values[i]) return true; + } + return false; + } + }, + 'boolean': { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === true || v === false) propOut.set(v); + else propOut.set(dflt); + } + }, + number: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(!isNumeric(v) || + (opts.min !== undefined && v < opts.min) || + (opts.max !== undefined && v > opts.max)) { + propOut.set(dflt); + } + else propOut.set(+v); + } + }, + integer: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(v % 1 || !isNumeric(v) || + (opts.min !== undefined && v < opts.min) || + (opts.max !== undefined && v > opts.max)) { + propOut.set(dflt); + } + else propOut.set(+v); + } + }, + string: { + + + // TODO 'values shouldn't be in there (edge case: 'dash' in Scatter) + + coerceFunction: function(v, propOut, dflt, opts) { + if(typeof v !== 'string') { + var okToCoerce = (typeof v === 'number'); + + if(opts.strict === true || !okToCoerce) propOut.set(dflt); + else propOut.set(String(v)); + } + else if(opts.noBlank && !v) propOut.set(dflt); + else propOut.set(v); + } + }, + color: { + + + + coerceFunction: function(v, propOut, dflt) { + if(tinycolor(v).isValid()) propOut.set(v); + else propOut.set(dflt); + } + }, + colorlist: { + + + + coerceFunction: function(v, propOut, dflt) { + function isColor(color) { + return tinycolor(color).isValid(); + } + if(!Array.isArray(v) || !v.length) propOut.set(dflt); + else if(v.every(isColor)) propOut.set(v); + else propOut.set(dflt); + } + }, + colorscale: { + + + + coerceFunction: function(v, propOut, dflt) { + propOut.set(getColorscale(v, dflt)); + } + }, + angle: { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === 'auto') propOut.set('auto'); + else if(!isNumeric(v)) propOut.set(dflt); + else propOut.set(modHalf(+v, 360)); + } + }, + subplotid: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + var regex = opts.regex || counterRegex(dflt); + if(typeof v === 'string' && regex.test(v)) { + propOut.set(v); + return; + } + propOut.set(dflt); + }, + validateFunction: function(v, opts) { + var dflt = opts.dflt; + + if(v === dflt) return true; + if(typeof v !== 'string') return false; + if(counterRegex(dflt).test(v)) return true; + + return false; + } + }, + flaglist: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(typeof v !== 'string') { + propOut.set(dflt); + return; + } + if((opts.extras || []).indexOf(v) !== -1) { + propOut.set(v); + return; + } + var vParts = v.split('+'), + i = 0; + while(i < vParts.length) { + var vi = vParts[i]; + if(opts.flags.indexOf(vi) === -1 || vParts.indexOf(vi) < i) { + vParts.splice(i, 1); + } + else i++; + } + if(!vParts.length) propOut.set(dflt); + else propOut.set(vParts.join('+')); + } + }, + any: { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === undefined) propOut.set(dflt); + else propOut.set(v); + } + }, + info_array: { + + + // set `dimensions=2` for a 2D array or '1-2' for either + // `items` may be a single object instead of an array, in which case + // `freeLength` must be true. + // if `dimensions='1-2'` and items is a 1D array, then the value can + // either be a matching 1D array or an array of such matching 1D arrays + + coerceFunction: function(v, propOut, dflt, opts) { + + // simplified coerce function just for array items + function coercePart(v, opts, dflt) { + var out; + var propPart = {set: function(v) { out = v; }}; + + if(dflt === undefined) dflt = opts.dflt; + + exports.valObjectMeta[opts.valType].coerceFunction(v, propPart, dflt, opts); + + return out; + } + + var twoD = opts.dimensions === 2 || (opts.dimensions === '1-2' && Array.isArray(v) && Array.isArray(v[0])); + + if(!Array.isArray(v)) { + propOut.set(dflt); + return; + } + + var items = opts.items; + var vOut = []; + var arrayItems = Array.isArray(items); + var arrayItems2D = arrayItems && twoD && Array.isArray(items[0]); + var innerItemsOnly = twoD && arrayItems && !arrayItems2D; + var len = (arrayItems && !innerItemsOnly) ? items.length : v.length; + + var i, j, row, item, len2, vNew; + + dflt = Array.isArray(dflt) ? dflt : []; + + if(twoD) { + for(i = 0; i < len; i++) { + vOut[i] = []; + row = Array.isArray(v[i]) ? v[i] : []; + if(innerItemsOnly) len2 = items.length; + else if(arrayItems) len2 = items[i].length; + else len2 = row.length; + + for(j = 0; j < len2; j++) { + if(innerItemsOnly) item = items[j]; + else if(arrayItems) item = items[i][j]; + else item = items; + + vNew = coercePart(row[j], item, (dflt[i] || [])[j]); + if(vNew !== undefined) vOut[i][j] = vNew; + } + } + } + else { + for(i = 0; i < len; i++) { + vNew = coercePart(v[i], arrayItems ? items[i] : items, dflt[i]); + if(vNew !== undefined) vOut[i] = vNew; + } + } + + propOut.set(vOut); + }, + validateFunction: function(v, opts) { + if(!Array.isArray(v)) return false; + + var items = opts.items; + var arrayItems = Array.isArray(items); + var twoD = opts.dimensions === 2; + + // when free length is off, input and declared lengths must match + if(!opts.freeLength && v.length !== items.length) return false; + + // valid when all input items are valid + for(var i = 0; i < v.length; i++) { + if(twoD) { + if(!Array.isArray(v[i]) || (!opts.freeLength && v[i].length !== items[i].length)) { + return false; + } + for(var j = 0; j < v[i].length; j++) { + if(!validate(v[i][j], arrayItems ? items[i][j] : items)) { + return false; + } + } + } + else if(!validate(v[i], arrayItems ? items[i] : items)) return false; + } + + return true; + } + } +}; + +/** + * Ensures that container[attribute] has a valid value. + * + * attributes[attribute] is an object with possible keys: + * - valType: data_array, enumerated, boolean, ... as in valObjectMeta + * - values: (enumerated only) array of allowed vals + * - min, max: (number, integer only) inclusive bounds on allowed vals + * either or both may be omitted + * - dflt: if attribute is invalid or missing, use this default + * if dflt is provided as an argument to lib.coerce it takes precedence + * as a convenience, returns the value it finally set + */ +exports.coerce = function(containerIn, containerOut, attributes, attribute, dflt) { + var opts = nestedProperty(attributes, attribute).get(); + var propIn = nestedProperty(containerIn, attribute); + var propOut = nestedProperty(containerOut, attribute); + var v = propIn.get(); + + var template = containerOut._template; + if(v === undefined && template) { + v = nestedProperty(template, attribute).get(); + // already used the template value, so short-circuit the second check + template = 0; + } + + if(dflt === undefined) dflt = opts.dflt; + + /** + * arrayOk: value MAY be an array, then we do no value checking + * at this point, because it can be more complicated than the + * individual form (eg. some array vals can be numbers, even if the + * single values must be color strings) + */ + if(opts.arrayOk && isArrayOrTypedArray(v)) { + propOut.set(v); + return v; + } + + var coerceFunction = exports.valObjectMeta[opts.valType].coerceFunction; + coerceFunction(v, propOut, dflt, opts); + + var out = propOut.get(); + // in case v was provided but invalid, try the template again so it still + // overrides the regular default + if(template && out === dflt && !validate(v, opts)) { + v = nestedProperty(template, attribute).get(); + coerceFunction(v, propOut, dflt, opts); + out = propOut.get(); + } + return out; +}; + +/** + * Variation on coerce + * + * Uses coerce to get attribute value if user input is valid, + * returns attribute default if user input it not valid or + * returns false if there is no user input. + */ +exports.coerce2 = function(containerIn, containerOut, attributes, attribute, dflt) { + var propIn = nestedProperty(containerIn, attribute), + propOut = exports.coerce(containerIn, containerOut, attributes, attribute, dflt), + valIn = propIn.get(); + + return (valIn !== undefined && valIn !== null) ? propOut : false; +}; + +/* + * Shortcut to coerce the three font attributes + * + * 'coerce' is a lib.coerce wrapper with implied first three arguments + */ +exports.coerceFont = function(coerce, attr, dfltObj) { + var out = {}; + + dfltObj = dfltObj || {}; + + out.family = coerce(attr + '.family', dfltObj.family); + out.size = coerce(attr + '.size', dfltObj.size); + out.color = coerce(attr + '.color', dfltObj.color); + + return out; +}; + +/** Coerce shortcut for 'hoverinfo' + * handling 1-vs-multi-trace dflt logic + * + * @param {object} traceIn : user trace object + * @param {object} traceOut : full trace object (requires _module ref) + * @param {object} layoutOut : full layout object (require _dataLength ref) + * @return {any} : the coerced value + */ +exports.coerceHoverinfo = function(traceIn, traceOut, layoutOut) { + var moduleAttrs = traceOut._module.attributes; + var attrs = moduleAttrs.hoverinfo ? moduleAttrs : baseTraceAttrs; + + var valObj = attrs.hoverinfo; + var dflt; + + if(layoutOut._dataLength === 1) { + var flags = valObj.dflt === 'all' ? + valObj.flags.slice() : + valObj.dflt.split('+'); + + flags.splice(flags.indexOf('name'), 1); + dflt = flags.join('+'); + } + + return exports.coerce(traceIn, traceOut, attrs, 'hoverinfo', dflt); +}; + +/** Coerce shortcut for [un]selected.marker.opacity, + * which has special default logic, to ensure that it corresponds to the + * default selection behavior while allowing to be overtaken by any other + * [un]selected attribute. + * + * N.B. This must be called *after* coercing all the other [un]selected attrs, + * to give the intended result. + * + * @param {object} traceOut : fullData item + * @param {function} coerce : lib.coerce wrapper with implied first three arguments + */ +exports.coerceSelectionMarkerOpacity = function(traceOut, coerce) { + if(!traceOut.marker) return; + + var mo = traceOut.marker.opacity; + // you can still have a `marker` container with no markers if there's text + if(mo === undefined) return; + + var smoDflt; + var usmoDflt; + + // Don't give [un]selected.marker.opacity a default value if + // marker.opacity is an array: handle this during style step. + // + // Only give [un]selected.marker.opacity a default value if you don't + // set any other [un]selected attributes. + if(!isArrayOrTypedArray(mo) && !traceOut.selected && !traceOut.unselected) { + smoDflt = mo; + usmoDflt = DESELECTDIM * mo; + } + + coerce('selected.marker.opacity', smoDflt); + coerce('unselected.marker.opacity', usmoDflt); +}; + +function validate(value, opts) { + var valObjectDef = exports.valObjectMeta[opts.valType]; + + if(opts.arrayOk && isArrayOrTypedArray(value)) return true; + + if(valObjectDef.validateFunction) { + return valObjectDef.validateFunction(value, opts); + } + + var failed = {}, + out = failed, + propMock = { set: function(v) { out = v; } }; + + // 'failed' just something mutable that won't be === anything else + + valObjectDef.coerceFunction(value, propMock, failed, opts); + return out !== failed; +} +exports.validate = validate; + +},{"../components/colorscale/get_scale":583,"../components/colorscale/scales":589,"../constants/interactions":672,"../plots/attributes":741,"./array":678,"./mod":703,"./nested_property":704,"./regex":712,"fast-isnumeric":214,"tinycolor2":514}],683:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Loggers = _dereq_('./loggers'); +var mod = _dereq_('./mod').mod; + +var constants = _dereq_('../constants/numerical'); +var BADNUM = constants.BADNUM; +var ONEDAY = constants.ONEDAY; +var ONEHOUR = constants.ONEHOUR; +var ONEMIN = constants.ONEMIN; +var ONESEC = constants.ONESEC; +var EPOCHJD = constants.EPOCHJD; + +var Registry = _dereq_('../registry'); + +var utcFormat = d3.time.format.utc; + +var DATETIME_REGEXP = /^\s*(-?\d\d\d\d|\d\d)(-(\d?\d)(-(\d?\d)([ Tt]([01]?\d|2[0-3])(:([0-5]\d)(:([0-5]\d(\.\d+)?))?(Z|z|[+\-]\d\d:?\d\d)?)?)?)?)?\s*$/m; +// special regex for chinese calendars to support yyyy-mmi-dd etc for intercalary months +var DATETIME_REGEXP_CN = /^\s*(-?\d\d\d\d|\d\d)(-(\d?\di?)(-(\d?\d)([ Tt]([01]?\d|2[0-3])(:([0-5]\d)(:([0-5]\d(\.\d+)?))?(Z|z|[+\-]\d\d:?\d\d)?)?)?)?)?\s*$/m; + +// for 2-digit years, the first year we map them onto +var YFIRST = new Date().getFullYear() - 70; + +function isWorldCalendar(calendar) { + return ( + calendar && + Registry.componentsRegistry.calendars && + typeof calendar === 'string' && calendar !== 'gregorian' + ); +} + +/* + * dateTick0: get the canonical tick for this calendar + * + * bool sunday is for week ticks, shift it to a Sunday. + */ +exports.dateTick0 = function(calendar, sunday) { + if(isWorldCalendar(calendar)) { + return sunday ? + Registry.getComponentMethod('calendars', 'CANONICAL_SUNDAY')[calendar] : + Registry.getComponentMethod('calendars', 'CANONICAL_TICK')[calendar]; + } + else { + return sunday ? '2000-01-02' : '2000-01-01'; + } +}; + +/* + * dfltRange: for each calendar, give a valid default range + */ +exports.dfltRange = function(calendar) { + if(isWorldCalendar(calendar)) { + return Registry.getComponentMethod('calendars', 'DFLTRANGE')[calendar]; + } + else { + return ['2000-01-01', '2001-01-01']; + } +}; + +// is an object a javascript date? +exports.isJSDate = function(v) { + return typeof v === 'object' && v !== null && typeof v.getTime === 'function'; +}; + +// The absolute limits of our date-time system +// This is a little weird: we use MIN_MS and MAX_MS in dateTime2ms +// but we use dateTime2ms to calculate them (after defining it!) +var MIN_MS, MAX_MS; + +/** + * dateTime2ms - turn a date object or string s into milliseconds + * (relative to 1970-01-01, per javascript standard) + * optional calendar (string) to use a non-gregorian calendar + * + * Returns BADNUM if it doesn't find a date + * + * strings should have the form: + * + * -?YYYY-mm-ddHH:MM:SS.sss? + * + * : space (our normal standard) or T or t (ISO-8601) + * : Z, z, or [+\-]HH:?MM and we THROW IT AWAY + * this format comes from https://tools.ietf.org/html/rfc3339#section-5.6 + * but we allow it even with a space as the separator + * + * May truncate after any full field, and sss can be any length + * even >3 digits, though javascript dates truncate to milliseconds, + * we keep as much as javascript numeric precision can hold, but we only + * report back up to 100 microsecond precision, because most dates support + * this precision (close to 1970 support more, very far away support less) + * + * Expanded to support negative years to -9999 but you must always + * give 4 digits, except for 2-digit positive years which we assume are + * near the present time. + * Note that we follow ISO 8601:2004: there *is* a year 0, which + * is 1BC/BCE, and -1===2BC etc. + * + * World calendars: not all of these *have* agreed extensions to this full range, + * if you have another calendar system but want a date range outside its validity, + * you can use a gregorian date string prefixed with 'G' or 'g'. + * + * Where to cut off 2-digit years between 1900s and 2000s? + * from http://support.microsoft.com/kb/244664: + * 1930-2029 (the most retro of all...) + * but in my mac chrome from eg. d=new Date(Date.parse('8/19/50')): + * 1950-2049 + * by Java, from http://stackoverflow.com/questions/2024273/: + * now-80 - now+19 + * or FileMaker Pro, from + * http://www.filemaker.com/12help/html/add_view_data.4.21.html: + * now-70 - now+29 + * but python strptime etc, via + * http://docs.python.org/py3k/library/time.html: + * 1969-2068 (super forward-looking, but static, not sliding!) + * + * lets go with now-70 to now+29, and if anyone runs into this problem + * they can learn the hard way not to use 2-digit years, as no choice we + * make now will cover all possibilities. mostly this will all be taken + * care of in initial parsing, should only be an issue for hand-entered data + * currently (2016) this range is: + * 1946-2045 + */ +exports.dateTime2ms = function(s, calendar) { + // first check if s is a date object + if(exports.isJSDate(s)) { + // Convert to the UTC milliseconds that give the same + // hours as this date has in the local timezone + var tzOffset = s.getTimezoneOffset() * ONEMIN; + var offsetTweak = (s.getUTCMinutes() - s.getMinutes()) * ONEMIN + + (s.getUTCSeconds() - s.getSeconds()) * ONESEC + + (s.getUTCMilliseconds() - s.getMilliseconds()); + + if(offsetTweak) { + var comb = 3 * ONEMIN; + tzOffset = tzOffset - comb / 2 + mod(offsetTweak - tzOffset + comb / 2, comb); + } + s = Number(s) - tzOffset; + if(s >= MIN_MS && s <= MAX_MS) return s; + return BADNUM; + } + // otherwise only accept strings and numbers + if(typeof s !== 'string' && typeof s !== 'number') return BADNUM; + + s = String(s); + + var isWorld = isWorldCalendar(calendar); + + // to handle out-of-range dates in international calendars, accept + // 'G' as a prefix to force the built-in gregorian calendar. + var s0 = s.charAt(0); + if(isWorld && (s0 === 'G' || s0 === 'g')) { + s = s.substr(1); + calendar = ''; + } + + var isChinese = isWorld && calendar.substr(0, 7) === 'chinese'; + + var match = s.match(isChinese ? DATETIME_REGEXP_CN : DATETIME_REGEXP); + if(!match) return BADNUM; + var y = match[1], + m = match[3] || '1', + d = Number(match[5] || 1), + H = Number(match[7] || 0), + M = Number(match[9] || 0), + S = Number(match[11] || 0); + + if(isWorld) { + // disallow 2-digit years for world calendars + if(y.length === 2) return BADNUM; + y = Number(y); + + var cDate; + try { + var calInstance = Registry.getComponentMethod('calendars', 'getCal')(calendar); + if(isChinese) { + var isIntercalary = m.charAt(m.length - 1) === 'i'; + m = parseInt(m, 10); + cDate = calInstance.newDate(y, calInstance.toMonthIndex(y, m, isIntercalary), d); + } + else { + cDate = calInstance.newDate(y, Number(m), d); + } + } + catch(e) { return BADNUM; } // Invalid ... date + + if(!cDate) return BADNUM; + + return ((cDate.toJD() - EPOCHJD) * ONEDAY) + + (H * ONEHOUR) + (M * ONEMIN) + (S * ONESEC); + } + + if(y.length === 2) { + y = (Number(y) + 2000 - YFIRST) % 100 + YFIRST; + } + else y = Number(y); + + // new Date uses months from 0; subtract 1 here just so we + // don't have to do it again during the validity test below + m -= 1; + + // javascript takes new Date(0..99,m,d) to mean 1900-1999, so + // to support years 0-99 we need to use setFullYear explicitly + // Note that 2000 is a leap year. + var date = new Date(Date.UTC(2000, m, d, H, M)); + date.setUTCFullYear(y); + + if(date.getUTCMonth() !== m) return BADNUM; + if(date.getUTCDate() !== d) return BADNUM; + + return date.getTime() + S * ONESEC; +}; + +MIN_MS = exports.MIN_MS = exports.dateTime2ms('-9999'); +MAX_MS = exports.MAX_MS = exports.dateTime2ms('9999-12-31 23:59:59.9999'); + +// is string s a date? (see above) +exports.isDateTime = function(s, calendar) { + return (exports.dateTime2ms(s, calendar) !== BADNUM); +}; + +// pad a number with zeroes, to given # of digits before the decimal point +function lpad(val, digits) { + return String(val + Math.pow(10, digits)).substr(1); +} + +/** + * Turn ms into string of the form YYYY-mm-dd HH:MM:SS.ssss + * Crop any trailing zeros in time, except never stop right after hours + * (we could choose to crop '-01' from date too but for now we always + * show the whole date) + * Optional range r is the data range that applies, also in ms. + * If rng is big, the later parts of time will be omitted + */ +var NINETYDAYS = 90 * ONEDAY; +var THREEHOURS = 3 * ONEHOUR; +var FIVEMIN = 5 * ONEMIN; +exports.ms2DateTime = function(ms, r, calendar) { + if(typeof ms !== 'number' || !(ms >= MIN_MS && ms <= MAX_MS)) return BADNUM; + + if(!r) r = 0; + + var msecTenths = Math.floor(mod(ms + 0.05, 1) * 10), + msRounded = Math.round(ms - msecTenths / 10), + dateStr, h, m, s, msec10, d; + + if(isWorldCalendar(calendar)) { + var dateJD = Math.floor(msRounded / ONEDAY) + EPOCHJD, + timeMs = Math.floor(mod(ms, ONEDAY)); + try { + dateStr = Registry.getComponentMethod('calendars', 'getCal')(calendar) + .fromJD(dateJD).formatDate('yyyy-mm-dd'); + } + catch(e) { + // invalid date in this calendar - fall back to Gyyyy-mm-dd + dateStr = utcFormat('G%Y-%m-%d')(new Date(msRounded)); + } + + // yyyy does NOT guarantee 4-digit years. YYYY mostly does, but does + // other things for a few calendars, so we can't trust it. Just pad + // it manually (after the '-' if there is one) + if(dateStr.charAt(0) === '-') { + while(dateStr.length < 11) dateStr = '-0' + dateStr.substr(1); + } + else { + while(dateStr.length < 10) dateStr = '0' + dateStr; + } + + // TODO: if this is faster, we could use this block for extracting + // the time components of regular gregorian too + h = (r < NINETYDAYS) ? Math.floor(timeMs / ONEHOUR) : 0; + m = (r < NINETYDAYS) ? Math.floor((timeMs % ONEHOUR) / ONEMIN) : 0; + s = (r < THREEHOURS) ? Math.floor((timeMs % ONEMIN) / ONESEC) : 0; + msec10 = (r < FIVEMIN) ? (timeMs % ONESEC) * 10 + msecTenths : 0; + } + else { + d = new Date(msRounded); + + dateStr = utcFormat('%Y-%m-%d')(d); + + // <90 days: add hours and minutes - never *only* add hours + h = (r < NINETYDAYS) ? d.getUTCHours() : 0; + m = (r < NINETYDAYS) ? d.getUTCMinutes() : 0; + // <3 hours: add seconds + s = (r < THREEHOURS) ? d.getUTCSeconds() : 0; + // <5 minutes: add ms (plus one extra digit, this is msec*10) + msec10 = (r < FIVEMIN) ? d.getUTCMilliseconds() * 10 + msecTenths : 0; + } + + return includeTime(dateStr, h, m, s, msec10); +}; + +// For converting old-style milliseconds to date strings, +// we use the local timezone rather than UTC like we use +// everywhere else, both for backward compatibility and +// because that's how people mostly use javasript date objects. +// Clip one extra day off our date range though so we can't get +// thrown beyond the range by the timezone shift. +exports.ms2DateTimeLocal = function(ms) { + if(!(ms >= MIN_MS + ONEDAY && ms <= MAX_MS - ONEDAY)) return BADNUM; + + var msecTenths = Math.floor(mod(ms + 0.05, 1) * 10), + d = new Date(Math.round(ms - msecTenths / 10)), + dateStr = d3.time.format('%Y-%m-%d')(d), + h = d.getHours(), + m = d.getMinutes(), + s = d.getSeconds(), + msec10 = d.getUTCMilliseconds() * 10 + msecTenths; + + return includeTime(dateStr, h, m, s, msec10); +}; + +function includeTime(dateStr, h, m, s, msec10) { + // include each part that has nonzero data in or after it + if(h || m || s || msec10) { + dateStr += ' ' + lpad(h, 2) + ':' + lpad(m, 2); + if(s || msec10) { + dateStr += ':' + lpad(s, 2); + if(msec10) { + var digits = 4; + while(msec10 % 10 === 0) { + digits -= 1; + msec10 /= 10; + } + dateStr += '.' + lpad(msec10, digits); + } + } + } + return dateStr; +} + +// normalize date format to date string, in case it starts as +// a Date object or milliseconds +// optional dflt is the return value if cleaning fails +exports.cleanDate = function(v, dflt, calendar) { + // let us use cleanDate to provide a missing default without an error + if(v === BADNUM) return dflt; + if(exports.isJSDate(v) || (typeof v === 'number' && isFinite(v))) { + // do not allow milliseconds (old) or jsdate objects (inherently + // described as gregorian dates) with world calendars + if(isWorldCalendar(calendar)) { + Loggers.error('JS Dates and milliseconds are incompatible with world calendars', v); + return dflt; + } + + // NOTE: if someone puts in a year as a number rather than a string, + // this will mistakenly convert it thinking it's milliseconds from 1970 + // that is: '2012' -> Jan. 1, 2012, but 2012 -> 2012 epoch milliseconds + v = exports.ms2DateTimeLocal(+v); + if(!v && dflt !== undefined) return dflt; + } + else if(!exports.isDateTime(v, calendar)) { + Loggers.error('unrecognized date', v); + return dflt; + } + return v; +}; + +/* + * Date formatting for ticks and hovertext + */ + +/* + * modDateFormat: Support world calendars, and add one item to + * d3's vocabulary: + * %{n}f where n is the max number of digits of fractional seconds + */ +var fracMatch = /%\d?f/g; +function modDateFormat(fmt, x, formatter, calendar) { + + fmt = fmt.replace(fracMatch, function(match) { + var digits = Math.min(+(match.charAt(1)) || 6, 6), + fracSecs = ((x / 1000 % 1) + 2) + .toFixed(digits) + .substr(2).replace(/0+$/, '') || '0'; + return fracSecs; + }); + + var d = new Date(Math.floor(x + 0.05)); + + if(isWorldCalendar(calendar)) { + try { + fmt = Registry.getComponentMethod('calendars', 'worldCalFmt')(fmt, x, calendar); + } + catch(e) { + return 'Invalid'; + } + } + return formatter(fmt)(d); +} + +/* + * formatTime: create a time string from: + * x: milliseconds + * tr: tickround ('M', 'S', or # digits) + * only supports UTC times (where every day is 24 hours and 0 is at midnight) + */ +var MAXSECONDS = [59, 59.9, 59.99, 59.999, 59.9999]; +function formatTime(x, tr) { + var timePart = mod(x + 0.05, ONEDAY); + + var timeStr = lpad(Math.floor(timePart / ONEHOUR), 2) + ':' + + lpad(mod(Math.floor(timePart / ONEMIN), 60), 2); + + if(tr !== 'M') { + if(!isNumeric(tr)) tr = 0; // should only be 'S' + + /* + * this is a weird one - and shouldn't come up unless people + * monkey with tick0 in weird ways, but we need to do something! + * IN PARTICULAR we had better not display garbage (see below) + * for numbers we always round to the nearest increment of the + * precision we're showing, and this seems like the right way to + * handle seconds and milliseconds, as they have a decimal point + * and people will interpret that to mean rounding like numbers. + * but for larger increments we floor the value: it's always + * 2013 until the ball drops on the new year. We could argue about + * which field it is where we start rounding (should 12:08:59 + * round to 12:09 if we're stopping at minutes?) but for now I'll + * say we round seconds but floor everything else. BUT that means + * we need to never round up to 60 seconds, ie 23:59:60 + */ + var sec = Math.min(mod(x / ONESEC, 60), MAXSECONDS[tr]); + + var secStr = (100 + sec).toFixed(tr).substr(1); + if(tr > 0) { + secStr = secStr.replace(/0+$/, '').replace(/[\.]$/, ''); + } + + timeStr += ':' + secStr; + } + return timeStr; +} + +/* + * formatDate: turn a date into tick or hover label text. + * + * x: milliseconds, the value to convert + * fmt: optional, an explicit format string (d3 format, even for world calendars) + * tr: tickround ('y', 'm', 'd', 'M', 'S', or # digits) + * used if no explicit fmt is provided + * formatter: locale-aware d3 date formatter for standard gregorian calendars + * should be the result of exports.getD3DateFormat(gd) + * calendar: optional string, the world calendar system to use + * + * returns the date/time as a string, potentially with the leading portion + * on a separate line (after '\n') + * Note that this means if you provide an explicit format which includes '\n' + * the axis may choose to strip things after it when they don't change from + * one tick to the next (as it does with automatic formatting) + */ +exports.formatDate = function(x, fmt, tr, formatter, calendar, extraFormat) { + calendar = isWorldCalendar(calendar) && calendar; + + if(!fmt) { + if(tr === 'y') fmt = extraFormat.year; + else if(tr === 'm') fmt = extraFormat.month; + else if(tr === 'd') { + fmt = extraFormat.dayMonth + '\n' + extraFormat.year; + } + else { + return formatTime(x, tr) + '\n' + modDateFormat(extraFormat.dayMonthYear, x, formatter, calendar); + } + } + + return modDateFormat(fmt, x, formatter, calendar); +}; + +/* + * incrementMonth: make a new milliseconds value from the given one, + * having changed the month + * + * special case for world calendars: multiples of 12 are treated as years, + * even for calendar systems that don't have (always or ever) 12 months/year + * TODO: perhaps we need a different code for year increments to support this? + * + * ms (number): the initial millisecond value + * dMonth (int): the (signed) number of months to shift + * calendar (string): the calendar system to use + * + * changing month does not (and CANNOT) always preserve day, since + * months have different lengths. The worst example of this is: + * d = new Date(1970,0,31); d.setMonth(1) -> Feb 31 turns into Mar 3 + * + * But we want to be able to iterate over the last day of each month, + * regardless of what its number is. + * So shift 3 days forward, THEN set the new month, then unshift: + * 1/31 -> 2/28 (or 29) -> 3/31 -> 4/30 -> ... + * + * Note that odd behavior still exists if you start from the 26th-28th: + * 1/28 -> 2/28 -> 3/31 + * but at least you can't shift any dates into the wrong month, + * and ticks on these days incrementing by month would be very unusual + */ +var THREEDAYS = 3 * ONEDAY; +exports.incrementMonth = function(ms, dMonth, calendar) { + calendar = isWorldCalendar(calendar) && calendar; + + // pull time out and operate on pure dates, then add time back at the end + // this gives maximum precision - not that we *normally* care if we're + // incrementing by month, but better to be safe! + var timeMs = mod(ms, ONEDAY); + ms = Math.round(ms - timeMs); + + if(calendar) { + try { + var dateJD = Math.round(ms / ONEDAY) + EPOCHJD, + calInstance = Registry.getComponentMethod('calendars', 'getCal')(calendar), + cDate = calInstance.fromJD(dateJD); + + if(dMonth % 12) calInstance.add(cDate, dMonth, 'm'); + else calInstance.add(cDate, dMonth / 12, 'y'); + + return (cDate.toJD() - EPOCHJD) * ONEDAY + timeMs; + } + catch(e) { + Loggers.error('invalid ms ' + ms + ' in calendar ' + calendar); + // then keep going in gregorian even though the result will be 'Invalid' + } + } + + var y = new Date(ms + THREEDAYS); + return y.setUTCMonth(y.getUTCMonth() + dMonth) + timeMs - THREEDAYS; +}; + +/* + * findExactDates: what fraction of data is exact days, months, or years? + * + * data: array of millisecond values + * calendar (string) the calendar to test against + */ +exports.findExactDates = function(data, calendar) { + var exactYears = 0, + exactMonths = 0, + exactDays = 0, + blankCount = 0, + d, + di; + + var calInstance = ( + isWorldCalendar(calendar) && + Registry.getComponentMethod('calendars', 'getCal')(calendar) + ); + + for(var i = 0; i < data.length; i++) { + di = data[i]; + + // not date data at all + if(!isNumeric(di)) { + blankCount ++; + continue; + } + + // not an exact date + if(di % ONEDAY) continue; + + if(calInstance) { + try { + d = calInstance.fromJD(di / ONEDAY + EPOCHJD); + if(d.day() === 1) { + if(d.month() === 1) exactYears++; + else exactMonths++; + } + else exactDays++; + } + catch(e) { + // invalid date in this calendar - ignore it here. + } + } + else { + d = new Date(di); + if(d.getUTCDate() === 1) { + if(d.getUTCMonth() === 0) exactYears++; + else exactMonths++; + } + else exactDays++; + } + } + exactMonths += exactYears; + exactDays += exactMonths; + + var dataCount = data.length - blankCount; + + return { + exactYears: exactYears / dataCount, + exactMonths: exactMonths / dataCount, + exactDays: exactDays / dataCount + }; +}; + +},{"../constants/numerical":673,"../registry":827,"./loggers":700,"./mod":703,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],684:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* global jQuery:false */ + +var EventEmitter = _dereq_('events').EventEmitter; + +var Events = { + + init: function(plotObj) { + + /* + * If we have already instantiated an emitter for this plot + * return early. + */ + if(plotObj._ev instanceof EventEmitter) return plotObj; + + var ev = new EventEmitter(); + var internalEv = new EventEmitter(); + + /* + * Assign to plot._ev while we still live in a land + * where plot is a DOM element with stuff attached to it. + * In the future we can make plot the event emitter itself. + */ + plotObj._ev = ev; + + /* + * Create a second event handler that will manage events *internally*. + * This allows parts of plotly to respond to thing like relayout without + * having to use the user-facing event handler. They cannot peacefully + * coexist on the same handler because a user invoking + * plotObj.removeAllListeners() would detach internal events, breaking + * plotly. + */ + plotObj._internalEv = internalEv; + + /* + * Assign bound methods from the ev to the plot object. These methods + * will reference the 'this' of plot._ev even though they are methods + * of plot. This will keep the event machinery away from the plot object + * which currently is often a DOM element but presents an API that will + * continue to function when plot becomes an emitter. Not all EventEmitter + * methods have been bound to `plot` as some do not currently add value to + * the Plotly event API. + */ + plotObj.on = ev.on.bind(ev); + plotObj.once = ev.once.bind(ev); + plotObj.removeListener = ev.removeListener.bind(ev); + plotObj.removeAllListeners = ev.removeAllListeners.bind(ev); + + /* + * Create functions for managing internal events. These are *only* triggered + * by the mirroring of external events via the emit function. + */ + plotObj._internalOn = internalEv.on.bind(internalEv); + plotObj._internalOnce = internalEv.once.bind(internalEv); + plotObj._removeInternalListener = internalEv.removeListener.bind(internalEv); + plotObj._removeAllInternalListeners = internalEv.removeAllListeners.bind(internalEv); + + /* + * We must wrap emit to continue to support JQuery events. The idea + * is to check to see if the user is using JQuery events, if they are + * we emit JQuery events to trigger user handlers as well as the EventEmitter + * events. + */ + plotObj.emit = function(event, data) { + if(typeof jQuery !== 'undefined') { + jQuery(plotObj).trigger(event, data); + } + + ev.emit(event, data); + internalEv.emit(event, data); + }; + + return plotObj; + }, + + /* + * This function behaves like jQuery's triggerHandler. It calls + * all handlers for a particular event and returns the return value + * of the LAST handler. This function also triggers jQuery's + * triggerHandler for backwards compatibility. + */ + triggerHandler: function(plotObj, event, data) { + var jQueryHandlerValue; + var nodeEventHandlerValue; + + /* + * If jQuery exists run all its handlers for this event and + * collect the return value of the LAST handler function + */ + if(typeof jQuery !== 'undefined') { + jQueryHandlerValue = jQuery(plotObj).triggerHandler(event, data); + } + + /* + * Now run all the node style event handlers + */ + var ev = plotObj._ev; + if(!ev) return jQueryHandlerValue; + + var handlers = ev._events[event]; + if(!handlers) return jQueryHandlerValue; + + // making sure 'this' is the EventEmitter instance + function apply(handler) { + // The 'once' case, we can't just call handler() as we need + // the return value here. So, + // - remove handler + // - call listener and grab return value! + // - stash 'fired' key to not call handler twice + if(handler.listener) { + ev.removeListener(event, handler.listener); + if(!handler.fired) { + handler.fired = true; + return handler.listener.apply(ev, [data]); + } + } else { + return handler.apply(ev, [data]); + } + } + + // handlers can be function or an array of functions + handlers = Array.isArray(handlers) ? handlers : [handlers]; + + var i; + for(i = 0; i < handlers.length - 1; i++) { + apply(handlers[i]); + } + // now call the final handler and collect its value + nodeEventHandlerValue = apply(handlers[i]); + + /* + * Return either the jQuery handler value if it exists or the + * nodeEventHandler value. jQuery event value supersedes nodejs + * events for backwards compatibility reasons. + */ + return jQueryHandlerValue !== undefined ? + jQueryHandlerValue : + nodeEventHandlerValue; + }, + + purge: function(plotObj) { + delete plotObj._ev; + delete plotObj.on; + delete plotObj.once; + delete plotObj.removeListener; + delete plotObj.removeAllListeners; + delete plotObj.emit; + + delete plotObj._ev; + delete plotObj._internalEv; + delete plotObj._internalOn; + delete plotObj._internalOnce; + delete plotObj._removeInternalListener; + delete plotObj._removeAllInternalListeners; + + return plotObj; + } + +}; + +module.exports = Events; + +},{"events":92}],685:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isPlainObject = _dereq_('./is_plain_object.js'); +var isArray = Array.isArray; + +function primitivesLoopSplice(source, target) { + var i, value; + for(i = 0; i < source.length; i++) { + value = source[i]; + if(value !== null && typeof(value) === 'object') { + return false; + } + if(value !== void(0)) { + target[i] = value; + } + } + return true; +} + +exports.extendFlat = function() { + return _extend(arguments, false, false, false); +}; + +exports.extendDeep = function() { + return _extend(arguments, true, false, false); +}; + +exports.extendDeepAll = function() { + return _extend(arguments, true, true, false); +}; + +exports.extendDeepNoArrays = function() { + return _extend(arguments, true, false, true); +}; + +/* + * Inspired by https://github.com/justmoon/node-extend/blob/master/index.js + * All credit to the jQuery authors for perfecting this amazing utility. + * + * API difference with jQuery version: + * - No optional boolean (true -> deep extend) first argument, + * use `extendFlat` for first-level only extend and + * use `extendDeep` for a deep extend. + * + * Other differences with jQuery version: + * - Uses a modern (and faster) isPlainObject routine. + * - Expected to work with object {} and array [] arguments only. + * - Does not check for circular structure. + * FYI: jQuery only does a check across one level. + * Warning: this might result in infinite loops. + * + */ +function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) { + var target = inputs[0], + length = inputs.length; + + var input, key, src, copy, copyIsArray, clone, allPrimitives; + + // TODO does this do the right thing for typed arrays? + + if(length === 2 && isArray(target) && isArray(inputs[1]) && target.length === 0) { + + allPrimitives = primitivesLoopSplice(inputs[1], target); + + if(allPrimitives) { + return target; + } else { + target.splice(0, target.length); // reset target and continue to next block + } + } + + for(var i = 1; i < length; i++) { + input = inputs[i]; + + for(key in input) { + src = target[key]; + copy = input[key]; + + // Stop early and just transfer the array if array copies are disallowed: + if(noArrayCopies && isArray(copy)) { + target[key] = copy; + } + + // recurse if we're merging plain objects or arrays + else if(isDeep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if(copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // never move original objects, clone them + target[key] = _extend([clone, copy], isDeep, keepAllKeys, noArrayCopies); + } + + // don't bring in undefined values, except for extendDeepAll + else if(typeof copy !== 'undefined' || keepAllKeys) { + target[key] = copy; + } + } + } + + return target; +} + +},{"./is_plain_object.js":697}],686:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Return news array containing only the unique items + * found in input array. + * + * IMPORTANT: Note that items are considered unique + * if `String({})` is unique. For example; + * + * Lib.filterUnique([ { a: 1 }, { b: 2 } ]) + * + * returns [{ a: 1 }] + * + * and + * + * Lib.filterUnique([ '1', 1 ]) + * + * returns ['1'] + * + * + * @param {array} array base array + * @return {array} new filtered array + */ +module.exports = function filterUnique(array) { + var seen = {}, + out = [], + j = 0; + + for(var i = 0; i < array.length; i++) { + var item = array[i]; + + if(seen[item] !== 1) { + seen[item] = 1; + out[j++] = item; + } + } + + return out; +}; + +},{}],687:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** Filter out object items with visible !== true + * insider array container. + * + * @param {array of objects} container + * @return {array of objects} of length <= container + * + */ +module.exports = function filterVisible(container) { + var filterFn = isCalcData(container) ? calcDataFilter : baseFilter; + var out = []; + + for(var i = 0; i < container.length; i++) { + var item = container[i]; + if(filterFn(item)) out.push(item); + } + + return out; +}; + +function baseFilter(item) { + return item.visible === true; +} + +function calcDataFilter(item) { + return item[0].trace.visible === true; +} + +function isCalcData(cont) { + return ( + Array.isArray(cont) && + Array.isArray(cont[0]) && + cont[0][0] && + cont[0][0].trace + ); +} + +},{}],688:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var countryRegex = _dereq_('country-regex'); +var Lib = _dereq_('../lib'); + + +// make list of all country iso3 ids from at runtime +var countryIds = Object.keys(countryRegex); + +var locationmodeToIdFinder = { + 'ISO-3': Lib.identity, + 'USA-states': Lib.identity, + 'country names': countryNameToISO3 +}; + +exports.locationToFeature = function(locationmode, location, features) { + if(!location || typeof location !== 'string') return false; + + var locationId = getLocationId(locationmode, location); + + if(locationId) { + for(var i = 0; i < features.length; i++) { + var feature = features[i]; + + if(feature.id === locationId) return feature; + } + + Lib.log([ + 'Location with id', locationId, + 'does not have a matching topojson feature at this resolution.' + ].join(' ')); + } + + return false; +}; + +function getLocationId(locationmode, location) { + var idFinder = locationmodeToIdFinder[locationmode]; + return idFinder(location); +} + +function countryNameToISO3(countryName) { + for(var i = 0; i < countryIds.length; i++) { + var iso3 = countryIds[i], + regex = new RegExp(countryRegex[iso3]); + + if(regex.test(countryName.trim().toLowerCase())) return iso3; + } + + Lib.log('Unrecognized country name: ' + countryName + '.'); + + return false; +} + +},{"../lib":696,"country-regex":122}],689:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var BADNUM = _dereq_('../constants/numerical').BADNUM; + +/** + * Convert calcTrace to GeoJSON 'MultiLineString' coordinate arrays + * + * @param {object} calcTrace + * gd.calcdata item. + * Note that calcTrace[i].lonlat is assumed to be defined + * + * @return {array} + * return line coords array (or array of arrays) + * + */ +exports.calcTraceToLineCoords = function(calcTrace) { + var trace = calcTrace[0].trace; + var connectgaps = trace.connectgaps; + + var coords = []; + var lineString = []; + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + var lonlat = calcPt.lonlat; + + if(lonlat[0] !== BADNUM) { + lineString.push(lonlat); + } else if(!connectgaps && lineString.length > 0) { + coords.push(lineString); + lineString = []; + } + } + + if(lineString.length > 0) { + coords.push(lineString); + } + + return coords; +}; + + +/** + * Make line ('LineString' or 'MultiLineString') GeoJSON + * + * @param {array} coords + * results form calcTraceToLineCoords + * @return {object} out + * GeoJSON object + * + */ +exports.makeLine = function(coords) { + if(coords.length === 1) { + return { + type: 'LineString', + coordinates: coords[0] + }; + } else { + return { + type: 'MultiLineString', + coordinates: coords + }; + } +}; + +/** + * Make polygon ('Polygon' or 'MultiPolygon') GeoJSON + * + * @param {array} coords + * results form calcTraceToLineCoords + * @return {object} out + * GeoJSON object + */ +exports.makePolygon = function(coords) { + if(coords.length === 1) { + return { + type: 'Polygon', + coordinates: coords + }; + } else { + var _coords = new Array(coords.length); + + for(var i = 0; i < coords.length; i++) { + _coords[i] = [coords[i]]; + } + + return { + type: 'MultiPolygon', + coordinates: _coords + }; + } +}; + +/** + * Make blank GeoJSON + * + * @return {object} + * Blank GeoJSON object + * + */ +exports.makeBlank = function() { + return { + type: 'Point', + coordinates: [] + }; +}; + +},{"../constants/numerical":673}],690:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var mod = _dereq_('./mod').mod; + +/* + * look for intersection of two line segments + * (1->2 and 3->4) - returns array [x,y] if they do, null if not + */ +exports.segmentsIntersect = segmentsIntersect; +function segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { + var a = x2 - x1, + b = x3 - x1, + c = x4 - x3, + d = y2 - y1, + e = y3 - y1, + f = y4 - y3, + det = a * f - c * d; + // parallel lines? intersection is undefined + // ignore the case where they are colinear + if(det === 0) return null; + var t = (b * f - c * e) / det, + u = (b * d - a * e) / det; + // segments do not intersect? + if(u < 0 || u > 1 || t < 0 || t > 1) return null; + + return {x: x1 + a * t, y: y1 + d * t}; +} + +/* + * find the minimum distance between two line segments (1->2 and 3->4) + */ +exports.segmentDistance = function segmentDistance(x1, y1, x2, y2, x3, y3, x4, y4) { + if(segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return 0; + + // the two segments and their lengths squared + var x12 = x2 - x1; + var y12 = y2 - y1; + var x34 = x4 - x3; + var y34 = y4 - y3; + var l2_12 = x12 * x12 + y12 * y12; + var l2_34 = x34 * x34 + y34 * y34; + + // calculate distance squared, then take the sqrt at the very end + var dist2 = Math.min( + perpDistance2(x12, y12, l2_12, x3 - x1, y3 - y1), + perpDistance2(x12, y12, l2_12, x4 - x1, y4 - y1), + perpDistance2(x34, y34, l2_34, x1 - x3, y1 - y3), + perpDistance2(x34, y34, l2_34, x2 - x3, y2 - y3) + ); + + return Math.sqrt(dist2); +}; + +/* + * distance squared from segment ab to point c + * [xab, yab] is the vector b-a + * [xac, yac] is the vector c-a + * l2_ab is the length squared of (b-a), just to simplify calculation + */ +function perpDistance2(xab, yab, l2_ab, xac, yac) { + var fc_ab = (xac * xab + yac * yab); + if(fc_ab < 0) { + // point c is closer to point a + return xac * xac + yac * yac; + } + else if(fc_ab > l2_ab) { + // point c is closer to point b + var xbc = xac - xab; + var ybc = yac - yab; + return xbc * xbc + ybc * ybc; + } + else { + // perpendicular distance is the shortest + var crossProduct = xac * yab - yac * xab; + return crossProduct * crossProduct / l2_ab; + } +} + +// a very short-term cache for getTextLocation, just because +// we're often looping over the same locations multiple times +// invalidated as soon as we look at a different path +var locationCache, workingPath, workingTextWidth; + +// turn a path and position along it into x, y, and angle for the given text +exports.getTextLocation = function getTextLocation(path, totalPathLen, positionOnPath, textWidth) { + if(path !== workingPath || textWidth !== workingTextWidth) { + locationCache = {}; + workingPath = path; + workingTextWidth = textWidth; + } + if(locationCache[positionOnPath]) { + return locationCache[positionOnPath]; + } + + // for the angle, use points on the path separated by the text width + // even though due to curvature, the text will cover a bit more than that + var p0 = path.getPointAtLength(mod(positionOnPath - textWidth / 2, totalPathLen)); + var p1 = path.getPointAtLength(mod(positionOnPath + textWidth / 2, totalPathLen)); + // note: atan handles 1/0 nicely + var theta = Math.atan((p1.y - p0.y) / (p1.x - p0.x)); + // center the text at 2/3 of the center position plus 1/3 the p0/p1 midpoint + // that's the average position of this segment, assuming it's roughly quadratic + var pCenter = path.getPointAtLength(mod(positionOnPath, totalPathLen)); + var x = (pCenter.x * 4 + p0.x + p1.x) / 6; + var y = (pCenter.y * 4 + p0.y + p1.y) / 6; + + var out = {x: x, y: y, theta: theta}; + locationCache[positionOnPath] = out; + return out; +}; + +exports.clearLocationCache = function() { + workingPath = null; +}; + +/* + * Find the segment of `path` that's within the visible area + * given by `bounds` {left, right, top, bottom}, to within a + * precision of `buffer` px + * + * returns: undefined if nothing is visible, else object: + * { + * min: position where the path first enters bounds, or 0 if it + * starts within bounds + * max: position where the path last exits bounds, or the path length + * if it finishes within bounds + * len: max - min, ie the length of visible path + * total: the total path length - just included so the caller doesn't + * need to call path.getTotalLength() again + * isClosed: true iff the start and end points of the path are both visible + * and are at the same point + * } + * + * Works by starting from either end and repeatedly finding the distance from + * that point to the plot area, and if it's outside the plot, moving along the + * path by that distance (because the plot must be at least that far away on + * the path). Note that if a path enters, exits, and re-enters the plot, we + * will not capture this behavior. + */ +exports.getVisibleSegment = function getVisibleSegment(path, bounds, buffer) { + var left = bounds.left; + var right = bounds.right; + var top = bounds.top; + var bottom = bounds.bottom; + + var pMin = 0; + var pTotal = path.getTotalLength(); + var pMax = pTotal; + + var pt0, ptTotal; + + function getDistToPlot(len) { + var pt = path.getPointAtLength(len); + + // hold on to the start and end points for `closed` + if(len === 0) pt0 = pt; + else if(len === pTotal) ptTotal = pt; + + var dx = (pt.x < left) ? left - pt.x : (pt.x > right ? pt.x - right : 0); + var dy = (pt.y < top) ? top - pt.y : (pt.y > bottom ? pt.y - bottom : 0); + return Math.sqrt(dx * dx + dy * dy); + } + + var distToPlot = getDistToPlot(pMin); + while(distToPlot) { + pMin += distToPlot + buffer; + if(pMin > pMax) return; + distToPlot = getDistToPlot(pMin); + } + + distToPlot = getDistToPlot(pMax); + while(distToPlot) { + pMax -= distToPlot + buffer; + if(pMin > pMax) return; + distToPlot = getDistToPlot(pMax); + } + + return { + min: pMin, + max: pMax, + len: pMax - pMin, + total: pTotal, + isClosed: pMin === 0 && pMax === pTotal && + Math.abs(pt0.x - ptTotal.x) < 0.1 && + Math.abs(pt0.y - ptTotal.y) < 0.1 + }; +}; + +/** + * Find point on SVG path corresponding to a given constraint coordinate + * + * @param {SVGPathElement} path + * @param {Number} val : constraint coordinate value + * @param {String} coord : 'x' or 'y' the constraint coordinate + * @param {Object} opts : + * - {Number} pathLength : supply total path length before hand + * - {Number} tolerance + * - {Number} iterationLimit + * @return {SVGPoint} + */ +exports.findPointOnPath = function findPointOnPath(path, val, coord, opts) { + opts = opts || {}; + + var pathLength = opts.pathLength || path.getTotalLength(); + var tolerance = opts.tolerance || 1e-3; + var iterationLimit = opts.iterationLimit || 30; + + // if path starts at a val greater than the path tail (like on vertical violins), + // we must flip the sign of the computed diff. + var mul = path.getPointAtLength(0)[coord] > path.getPointAtLength(pathLength)[coord] ? -1 : 1; + + var i = 0; + var b0 = 0; + var b1 = pathLength; + var mid; + var pt; + var diff; + + while(i < iterationLimit) { + mid = (b0 + b1) / 2; + pt = path.getPointAtLength(mid); + diff = pt[coord] - val; + + if(Math.abs(diff) < tolerance) { + return pt; + } else { + if(mul * diff > 0) { + b1 = mid; + } else { + b0 = mid; + } + i++; + } + } + return pt; +}; + +},{"./mod":703}],691:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Allow referencing a graph DOM element either directly + * or by its id string + * + * @param {HTMLDivElement|string} gd: a graph element or its id + * + * @returns {HTMLDivElement} the DOM element of the graph + */ +module.exports = function(gd) { + var gdElement; + + if(typeof gd === 'string') { + gdElement = document.getElementById(gd); + + if(gdElement === null) { + throw new Error('No DOM element with id \'' + gd + '\' exists on the page.'); + } + + return gdElement; + } + else if(gd === null || gd === undefined) { + throw new Error('DOM element provided is null or undefined'); + } + + return gd; // otherwise assume that gd is a DOM element +}; + +},{}],692:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var tinycolor = _dereq_('tinycolor2'); +var rgba = _dereq_('color-normalize'); + +var Colorscale = _dereq_('../components/colorscale'); +var colorDflt = _dereq_('../components/color/attributes').defaultLine; +var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; + +var colorDfltRgba = rgba(colorDflt); +var opacityDflt = 1; + +function calculateColor(colorIn, opacityIn) { + var colorOut = colorIn; + colorOut[3] *= opacityIn; + return colorOut; +} + +function validateColor(colorIn) { + if(isNumeric(colorIn)) return colorDfltRgba; + + var colorOut = rgba(colorIn); + + return colorOut.length ? colorOut : colorDfltRgba; +} + +function validateOpacity(opacityIn) { + return isNumeric(opacityIn) ? opacityIn : opacityDflt; +} + +function formatColor(containerIn, opacityIn, len) { + var colorIn = containerIn.color; + var isArrayColorIn = isArrayOrTypedArray(colorIn); + var isArrayOpacityIn = isArrayOrTypedArray(opacityIn); + var colorOut = []; + + var sclFunc, getColor, getOpacity, colori, opacityi; + + if(containerIn.colorscale !== undefined) { + sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + containerIn.colorscale, + containerIn.cmin, + containerIn.cmax + ) + ); + } + else { + sclFunc = validateColor; + } + + if(isArrayColorIn) { + getColor = function(c, i) { + // FIXME: there is double work, considering that sclFunc does the opposite + return c[i] === undefined ? colorDfltRgba : rgba(sclFunc(c[i])); + }; + } + else getColor = validateColor; + + if(isArrayOpacityIn) { + getOpacity = function(o, i) { + return o[i] === undefined ? opacityDflt : validateOpacity(o[i]); + }; + } + else getOpacity = validateOpacity; + + if(isArrayColorIn || isArrayOpacityIn) { + for(var i = 0; i < len; i++) { + colori = getColor(colorIn, i); + opacityi = getOpacity(opacityIn, i); + colorOut[i] = calculateColor(colori, opacityi); + } + } + else colorOut = calculateColor(rgba(colorIn), opacityIn); + + return colorOut; +} + +function parseColorScale(colorscale, alpha) { + if(alpha === undefined) alpha = 1; + + return colorscale.map(function(elem) { + var index = elem[0]; + var color = tinycolor(elem[1]); + var rgb = color.toRgb(); + return { + index: index, + rgb: [rgb.r, rgb.g, rgb.b, alpha] + }; + }); +} + +module.exports = { + formatColor: formatColor, + parseColorScale: parseColorScale +}; + +},{"../components/color/attributes":569,"../components/colorscale":585,"./array":678,"color-normalize":108,"fast-isnumeric":214,"tinycolor2":514}],693:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var identity = _dereq_('./identity'); + +function wrap(d) {return [d];} + +module.exports = { + + // The D3 data binding concept and the General Update Pattern promotes the idea of + // traversing into the scenegraph by using the `.data(fun, keyFun)` call. + // The `fun` is most often a `repeat`, ie. the elements beneath a `` element need + // access to the same data, or a `descend`, which fans a scenegraph node into a bunch of + // of elements, e.g. points, lines, rows, requiring an array as input. + // The role of the `keyFun` is to identify what elements are being entered/exited/updated, + // otherwise D3 reverts to using a plain index which would screw up `transition`s. + keyFun: function(d) {return d.key;}, + repeat: wrap, + descend: identity, + + // Plotly.js uses a convention of storing the actual contents of the `calcData` as the + // element zero of a container array. These helpers are just used for clarity as a + // newcomer to the codebase may not know what the `[0]` is, and whether there can be further + // elements (not atm). + wrap: wrap, + unwrap: function(d) {return d[0];} +}; + +},{"./identity":695}],694:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var toSuperScript = _dereq_('superscript-text'); +var fixEntities = _dereq_('./svg_text_utils').convertEntities; + +function fixSuperScript(x) { + var idx = 0; + + while((idx = x.indexOf('', idx)) >= 0) { + var nidx = x.indexOf('', idx); + if(nidx < idx) break; + + x = x.slice(0, idx) + toSuperScript(x.slice(idx + 5, nidx)) + x.slice(nidx + 6); + } + + return x; +} + +function fixBR(x) { + return x.replace(/\/g, '\n'); +} + +function stripTags(x) { + return x.replace(/\<.*\>/g, ''); +} + +function convertHTMLToUnicode(html) { + return '' + + fixEntities( + stripTags( + fixSuperScript( + fixBR( + html)))); +} + +module.exports = convertHTMLToUnicode; + +},{"./svg_text_utils":720,"superscript-text":507}],695:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// Simple helper functions +// none of these need any external deps + +module.exports = function identity(d) { return d; }; + +},{}],696:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var numConstants = _dereq_('../constants/numerical'); +var FP_SAFE = numConstants.FP_SAFE; +var BADNUM = numConstants.BADNUM; + +var lib = module.exports = {}; + +lib.nestedProperty = _dereq_('./nested_property'); +lib.keyedContainer = _dereq_('./keyed_container'); +lib.relativeAttr = _dereq_('./relative_attr'); +lib.isPlainObject = _dereq_('./is_plain_object'); +lib.toLogRange = _dereq_('./to_log_range'); +lib.relinkPrivateKeys = _dereq_('./relink_private'); + +var arrayModule = _dereq_('./array'); +lib.isTypedArray = arrayModule.isTypedArray; +lib.isArrayOrTypedArray = arrayModule.isArrayOrTypedArray; +lib.isArray1D = arrayModule.isArray1D; +lib.ensureArray = arrayModule.ensureArray; +lib.concat = arrayModule.concat; + +var modModule = _dereq_('./mod'); +lib.mod = modModule.mod; +lib.modHalf = modModule.modHalf; + +var coerceModule = _dereq_('./coerce'); +lib.valObjectMeta = coerceModule.valObjectMeta; +lib.coerce = coerceModule.coerce; +lib.coerce2 = coerceModule.coerce2; +lib.coerceFont = coerceModule.coerceFont; +lib.coerceHoverinfo = coerceModule.coerceHoverinfo; +lib.coerceSelectionMarkerOpacity = coerceModule.coerceSelectionMarkerOpacity; +lib.validate = coerceModule.validate; + +var datesModule = _dereq_('./dates'); +lib.dateTime2ms = datesModule.dateTime2ms; +lib.isDateTime = datesModule.isDateTime; +lib.ms2DateTime = datesModule.ms2DateTime; +lib.ms2DateTimeLocal = datesModule.ms2DateTimeLocal; +lib.cleanDate = datesModule.cleanDate; +lib.isJSDate = datesModule.isJSDate; +lib.formatDate = datesModule.formatDate; +lib.incrementMonth = datesModule.incrementMonth; +lib.dateTick0 = datesModule.dateTick0; +lib.dfltRange = datesModule.dfltRange; +lib.findExactDates = datesModule.findExactDates; +lib.MIN_MS = datesModule.MIN_MS; +lib.MAX_MS = datesModule.MAX_MS; + +var searchModule = _dereq_('./search'); +lib.findBin = searchModule.findBin; +lib.sorterAsc = searchModule.sorterAsc; +lib.sorterDes = searchModule.sorterDes; +lib.distinctVals = searchModule.distinctVals; +lib.roundUp = searchModule.roundUp; +lib.sort = searchModule.sort; +lib.findIndexOfMin = searchModule.findIndexOfMin; + +var statsModule = _dereq_('./stats'); +lib.aggNums = statsModule.aggNums; +lib.len = statsModule.len; +lib.mean = statsModule.mean; +lib.midRange = statsModule.midRange; +lib.variance = statsModule.variance; +lib.stdev = statsModule.stdev; +lib.interp = statsModule.interp; + +var matrixModule = _dereq_('./matrix'); +lib.init2dArray = matrixModule.init2dArray; +lib.transposeRagged = matrixModule.transposeRagged; +lib.dot = matrixModule.dot; +lib.translationMatrix = matrixModule.translationMatrix; +lib.rotationMatrix = matrixModule.rotationMatrix; +lib.rotationXYMatrix = matrixModule.rotationXYMatrix; +lib.apply2DTransform = matrixModule.apply2DTransform; +lib.apply2DTransform2 = matrixModule.apply2DTransform2; + +var anglesModule = _dereq_('./angles'); +lib.deg2rad = anglesModule.deg2rad; +lib.rad2deg = anglesModule.rad2deg; +lib.angleDelta = anglesModule.angleDelta; +lib.angleDist = anglesModule.angleDist; +lib.isFullCircle = anglesModule.isFullCircle; +lib.isAngleInsideSector = anglesModule.isAngleInsideSector; +lib.isPtInsideSector = anglesModule.isPtInsideSector; +lib.pathArc = anglesModule.pathArc; +lib.pathSector = anglesModule.pathSector; +lib.pathAnnulus = anglesModule.pathAnnulus; + +var geom2dModule = _dereq_('./geometry2d'); +lib.segmentsIntersect = geom2dModule.segmentsIntersect; +lib.segmentDistance = geom2dModule.segmentDistance; +lib.getTextLocation = geom2dModule.getTextLocation; +lib.clearLocationCache = geom2dModule.clearLocationCache; +lib.getVisibleSegment = geom2dModule.getVisibleSegment; +lib.findPointOnPath = geom2dModule.findPointOnPath; + +var extendModule = _dereq_('./extend'); +lib.extendFlat = extendModule.extendFlat; +lib.extendDeep = extendModule.extendDeep; +lib.extendDeepAll = extendModule.extendDeepAll; +lib.extendDeepNoArrays = extendModule.extendDeepNoArrays; + +var loggersModule = _dereq_('./loggers'); +lib.log = loggersModule.log; +lib.warn = loggersModule.warn; +lib.error = loggersModule.error; + +var regexModule = _dereq_('./regex'); +lib.counterRegex = regexModule.counter; + +var throttleModule = _dereq_('./throttle'); +lib.throttle = throttleModule.throttle; +lib.throttleDone = throttleModule.done; +lib.clearThrottle = throttleModule.clear; + +lib.getGraphDiv = _dereq_('./get_graph_div'); + +lib.clearResponsive = _dereq_('./clear_responsive'); + +lib.makeTraceGroups = _dereq_('./make_trace_groups'); + +lib._ = _dereq_('./localize'); + +lib.notifier = _dereq_('./notifier'); + +lib.filterUnique = _dereq_('./filter_unique'); +lib.filterVisible = _dereq_('./filter_visible'); +lib.pushUnique = _dereq_('./push_unique'); + +lib.cleanNumber = _dereq_('./clean_number'); + +lib.ensureNumber = function num(v) { + if(!isNumeric(v)) return BADNUM; + v = Number(v); + if(v < -FP_SAFE || v > FP_SAFE) return BADNUM; + return isNumeric(v) ? Number(v) : BADNUM; +}; + +/** + * Is v a valid array index? Accepts numeric strings as well as numbers. + * + * @param {any} v: the value to test + * @param {Optional[integer]} len: the array length we are indexing + * + * @return {bool}: v is a valid array index + */ +lib.isIndex = function(v, len) { + if(len !== undefined && v >= len) return false; + return isNumeric(v) && (v >= 0) && (v % 1 === 0); +}; + +lib.noop = _dereq_('./noop'); +lib.identity = _dereq_('./identity'); + +/** + * create an array of length 'cnt' filled with 'v' at all indices + * + * @param {any} v + * @param {number} cnt + * @return {array} + */ +lib.repeat = function(v, cnt) { + var out = new Array(cnt); + for(var i = 0; i < cnt; i++) { + out[i] = v; + } + return out; +}; + +/** + * swap x and y of the same attribute in container cont + * specify attr with a ? in place of x/y + * you can also swap other things than x/y by providing part1 and part2 + */ +lib.swapAttrs = function(cont, attrList, part1, part2) { + if(!part1) part1 = 'x'; + if(!part2) part2 = 'y'; + for(var i = 0; i < attrList.length; i++) { + var attr = attrList[i], + xp = lib.nestedProperty(cont, attr.replace('?', part1)), + yp = lib.nestedProperty(cont, attr.replace('?', part2)), + temp = xp.get(); + xp.set(yp.get()); + yp.set(temp); + } +}; + +/** + * SVG painter's algo worked around with reinsertion + */ +lib.raiseToTop = function raiseToTop(elem) { + elem.parentNode.appendChild(elem); +}; + +/** + * cancel a possibly pending transition; returned selection may be used by caller + */ +lib.cancelTransition = function(selection) { + return selection.transition().duration(0); +}; + +// constrain - restrict a number v to be between v0 and v1 +lib.constrain = function(v, v0, v1) { + if(v0 > v1) return Math.max(v1, Math.min(v0, v)); + return Math.max(v0, Math.min(v1, v)); +}; + +/** + * do two bounding boxes from getBoundingClientRect, + * ie {left,right,top,bottom,width,height}, overlap? + * takes optional padding pixels + */ +lib.bBoxIntersect = function(a, b, pad) { + pad = pad || 0; + return (a.left <= b.right + pad && + b.left <= a.right + pad && + a.top <= b.bottom + pad && + b.top <= a.bottom + pad); +}; + +/* + * simpleMap: alternative to Array.map that only + * passes on the element and up to 2 extra args you + * provide (but not the array index or the whole array) + * + * array: the array to map it to + * func: the function to apply + * x1, x2: optional extra args + */ +lib.simpleMap = function(array, func, x1, x2) { + var len = array.length, + out = new Array(len); + for(var i = 0; i < len; i++) out[i] = func(array[i], x1, x2); + return out; +}; + +/** + * Random string generator + * + * @param {object} existing + * pass in strings to avoid as keys with truthy values + * @param {int} bits + * bits of information in the output string, default 24 + * @param {int} base + * base of string representation, default 16. Should be a power of 2. + */ +lib.randstr = function randstr(existing, bits, base, _recursion) { + if(!base) base = 16; + if(bits === undefined) bits = 24; + if(bits <= 0) return '0'; + + var digits = Math.log(Math.pow(2, bits)) / Math.log(base); + var res = ''; + var i, b, x; + + for(i = 2; digits === Infinity; i *= 2) { + digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; + } + + var rem = digits - Math.floor(digits); + + for(i = 0; i < Math.floor(digits); i++) { + x = Math.floor(Math.random() * base).toString(base); + res = x + res; + } + + if(rem) { + b = Math.pow(base, rem); + x = Math.floor(Math.random() * b).toString(base); + res = x + res; + } + + var parsed = parseInt(res, base); + if((existing && existing[res]) || + (parsed !== Infinity && parsed >= Math.pow(2, bits))) { + if(_recursion > 10) { + lib.warn('randstr failed uniqueness'); + return res; + } + return randstr(existing, bits, base, (_recursion || 0) + 1); + } + else return res; +}; + +lib.OptionControl = function(opt, optname) { + /* + * An environment to contain all option setters and + * getters that collectively modify opts. + * + * You can call up opts from any function in new object + * as this.optname || this.opt + * + * See FitOpts for example of usage + */ + if(!opt) opt = {}; + if(!optname) optname = 'opt'; + + var self = {}; + self.optionList = []; + + self._newoption = function(optObj) { + optObj[optname] = opt; + self[optObj.name] = optObj; + self.optionList.push(optObj); + }; + + self['_' + optname] = opt; + return self; +}; + +/** + * lib.smooth: smooth arrayIn by convolving with + * a hann window with given full width at half max + * bounce the ends in, so the output has the same length as the input + */ +lib.smooth = function(arrayIn, FWHM) { + FWHM = Math.round(FWHM) || 0; // only makes sense for integers + if(FWHM < 2) return arrayIn; + + var alen = arrayIn.length, + alen2 = 2 * alen, + wlen = 2 * FWHM - 1, + w = new Array(wlen), + arrayOut = new Array(alen), + i, + j, + k, + v; + + // first make the window array + for(i = 0; i < wlen; i++) { + w[i] = (1 - Math.cos(Math.PI * (i + 1) / FWHM)) / (2 * FWHM); + } + + // now do the convolution + for(i = 0; i < alen; i++) { + v = 0; + for(j = 0; j < wlen; j++) { + k = i + j + 1 - FWHM; + + // multibounce + if(k < -alen) k -= alen2 * Math.round(k / alen2); + else if(k >= alen2) k -= alen2 * Math.floor(k / alen2); + + // single bounce + if(k < 0) k = - 1 - k; + else if(k >= alen) k = alen2 - 1 - k; + + v += arrayIn[k] * w[j]; + } + arrayOut[i] = v; + } + + return arrayOut; +}; + +/** + * syncOrAsync: run a sequence of functions synchronously + * as long as its returns are not promises (ie have no .then) + * includes one argument arg to send to all functions... + * this is mainly just to prevent us having to make wrapper functions + * when the only purpose of the wrapper is to reference gd + * and a final step to be executed at the end + * TODO: if there's an error and everything is sync, + * this doesn't happen yet because we want to make sure + * that it gets reported + */ +lib.syncOrAsync = function(sequence, arg, finalStep) { + var ret, fni; + + function continueAsync() { + return lib.syncOrAsync(sequence, arg, finalStep); + } + + while(sequence.length) { + fni = sequence.splice(0, 1)[0]; + ret = fni(arg); + + if(ret && ret.then) { + return ret.then(continueAsync) + .then(undefined, lib.promiseError); + } + } + + return finalStep && finalStep(arg); +}; + + +/** + * Helper to strip trailing slash, from + * http://stackoverflow.com/questions/6680825/return-string-without-trailing-slash + */ +lib.stripTrailingSlash = function(str) { + if(str.substr(-1) === '/') return str.substr(0, str.length - 1); + return str; +}; + +lib.noneOrAll = function(containerIn, containerOut, attrList) { + /** + * some attributes come together, so if you have one of them + * in the input, you should copy the default values of the others + * to the input as well. + */ + if(!containerIn) return; + + var hasAny = false, + hasAll = true, + i, + val; + + for(i = 0; i < attrList.length; i++) { + val = containerIn[attrList[i]]; + if(val !== undefined && val !== null) hasAny = true; + else hasAll = false; + } + + if(hasAny && !hasAll) { + for(i = 0; i < attrList.length; i++) { + containerIn[attrList[i]] = containerOut[attrList[i]]; + } + } +}; + +/** merges calcdata field (given by cdAttr) with traceAttr values + * + * N.B. Loop over minimum of cd.length and traceAttr.length + * i.e. it does not try to fill in beyond traceAttr.length-1 + * + * @param {array} traceAttr : trace attribute + * @param {object} cd : calcdata trace + * @param {string} cdAttr : calcdata key + */ +lib.mergeArray = function(traceAttr, cd, cdAttr) { + if(lib.isArrayOrTypedArray(traceAttr)) { + var imax = Math.min(traceAttr.length, cd.length); + for(var i = 0; i < imax; i++) cd[i][cdAttr] = traceAttr[i]; + } +}; + +/** fills calcdata field (given by cdAttr) with traceAttr values + * or function of traceAttr values (e.g. some fallback) + * + * N.B. Loops over all cd items. + * + * @param {array} traceAttr : trace attribute + * @param {object} cd : calcdata trace + * @param {string} cdAttr : calcdata key + * @param {function} [fn] : optional function to apply to each array item + */ +lib.fillArray = function(traceAttr, cd, cdAttr, fn) { + fn = fn || lib.identity; + + if(lib.isArrayOrTypedArray(traceAttr)) { + for(var i = 0; i < cd.length; i++) { + cd[i][cdAttr] = fn(traceAttr[i]); + } + } +}; + +/** Handler for trace-wide vs per-point options + * + * @param {object} trace : (full) trace object + * @param {number} ptNumber : index of the point in question + * @param {string} astr : attribute string + * @param {function} [fn] : optional function to apply to each array item + * + * @return {any} + */ +lib.castOption = function(trace, ptNumber, astr, fn) { + fn = fn || lib.identity; + + var val = lib.nestedProperty(trace, astr).get(); + + if(lib.isArrayOrTypedArray(val)) { + if(Array.isArray(ptNumber) && lib.isArrayOrTypedArray(val[ptNumber[0]])) { + return fn(val[ptNumber[0]][ptNumber[1]]); + } else { + return fn(val[ptNumber]); + } + } else { + return val; + } +}; + +/** Extract option from calcdata item, correctly falling back to + * trace value if not found. + * + * @param {object} calcPt : calcdata[i][j] item + * @param {object} trace : (full) trace object + * @param {string} calcKey : calcdata key + * @param {string} traceKey : aka trace attribute string + * @return {any} + */ +lib.extractOption = function(calcPt, trace, calcKey, traceKey) { + if(calcKey in calcPt) return calcPt[calcKey]; + + // fallback to trace value, + // must check if value isn't itself an array + // which means the trace attribute has a corresponding + // calcdata key, but its value is falsy + var traceVal = lib.nestedProperty(trace, traceKey).get(); + if(!Array.isArray(traceVal)) return traceVal; +}; + +function makePtIndex2PtNumber(indexToPoints) { + var ptIndex2ptNumber = {}; + for(var k in indexToPoints) { + var pts = indexToPoints[k]; + for(var j = 0; j < pts.length; j++) { + ptIndex2ptNumber[pts[j]] = +k; + } + } + return ptIndex2ptNumber; +} + +/** Tag selected calcdata items + * + * N.B. note that point 'index' corresponds to input data array index + * whereas 'number' is its post-transform version. + * + * @param {array} calcTrace + * @param {object} trace + * - selectedpoints {array} + * - _indexToPoints {object} + * @param {ptNumber2cdIndex} ptNumber2cdIndex (optional) + * optional map object for trace types that do not have 1-to-1 point number to + * calcdata item index correspondence (e.g. histogram) + */ +lib.tagSelected = function(calcTrace, trace, ptNumber2cdIndex) { + var selectedpoints = trace.selectedpoints; + var indexToPoints = trace._indexToPoints; + var ptIndex2ptNumber; + + // make pt index-to-number map object, which takes care of transformed traces + if(indexToPoints) { + ptIndex2ptNumber = makePtIndex2PtNumber(indexToPoints); + } + + function isCdIndexValid(v) { + return v !== undefined && v < calcTrace.length; + } + + for(var i = 0; i < selectedpoints.length; i++) { + var ptIndex = selectedpoints[i]; + + if(lib.isIndex(ptIndex)) { + var ptNumber = ptIndex2ptNumber ? ptIndex2ptNumber[ptIndex] : ptIndex; + var cdIndex = ptNumber2cdIndex ? ptNumber2cdIndex[ptNumber] : ptNumber; + + if(isCdIndexValid(cdIndex)) { + calcTrace[cdIndex].selected = 1; + } + } + } +}; + +lib.selIndices2selPoints = function(trace) { + var selectedpoints = trace.selectedpoints; + var indexToPoints = trace._indexToPoints; + + if(indexToPoints) { + var ptIndex2ptNumber = makePtIndex2PtNumber(indexToPoints); + var out = []; + + for(var i = 0; i < selectedpoints.length; i++) { + var ptIndex = selectedpoints[i]; + if(lib.isIndex(ptIndex)) { + var ptNumber = ptIndex2ptNumber[ptIndex]; + if(lib.isIndex(ptNumber)) { + out.push(ptNumber); + } + } + } + + return out; + } else { + return selectedpoints; + } +}; + +/** Returns target as set by 'target' transform attribute + * + * @param {object} trace : full trace object + * @param {object} transformOpts : transform option object + * - target (string} : + * either an attribute string referencing an array in the trace object, or + * a set array. + * + * @return {array or false} : the target array (NOT a copy!!) or false if invalid + */ +lib.getTargetArray = function(trace, transformOpts) { + var target = transformOpts.target; + + if(typeof target === 'string' && target) { + var array = lib.nestedProperty(trace, target).get(); + return Array.isArray(array) ? array : false; + } else if(Array.isArray(target)) { + return target; + } + + return false; +}; + +/** + * modified version of jQuery's extend to strip out private objs and functions, + * and cut arrays down to first or 1 elements + * because extend-like algorithms are hella slow + * obj2 is assumed to already be clean of these things (including no arrays) + */ +lib.minExtend = function(obj1, obj2) { + var objOut = {}; + if(typeof obj2 !== 'object') obj2 = {}; + var arrayLen = 3, + keys = Object.keys(obj1), + i, + k, + v; + for(i = 0; i < keys.length; i++) { + k = keys[i]; + v = obj1[k]; + if(k.charAt(0) === '_' || typeof v === 'function') continue; + else if(k === 'module') objOut[k] = v; + else if(Array.isArray(v)) objOut[k] = v.slice(0, arrayLen); + else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); + else objOut[k] = v; + } + + keys = Object.keys(obj2); + for(i = 0; i < keys.length; i++) { + k = keys[i]; + v = obj2[k]; + if(typeof v !== 'object' || !(k in objOut) || typeof objOut[k] !== 'object') { + objOut[k] = v; + } + } + + return objOut; +}; + +lib.titleCase = function(s) { + return s.charAt(0).toUpperCase() + s.substr(1); +}; + +lib.containsAny = function(s, fragments) { + for(var i = 0; i < fragments.length; i++) { + if(s.indexOf(fragments[i]) !== -1) return true; + } + return false; +}; + +lib.isPlotDiv = function(el) { + var el3 = d3.select(el); + return el3.node() instanceof HTMLElement && + el3.size() && + el3.classed('js-plotly-plot'); +}; + +lib.removeElement = function(el) { + var elParent = el && el.parentNode; + if(elParent) elParent.removeChild(el); +}; + +/** + * for dynamically adding style rules + * makes one stylesheet that contains all rules added + * by all calls to this function + */ +lib.addStyleRule = function(selector, styleString) { + lib.addRelatedStyleRule('global', selector, styleString); +}; + +/** + * for dynamically adding style rules + * to a stylesheet uniquely identified by a uid + */ +lib.addRelatedStyleRule = function(uid, selector, styleString) { + var id = 'plotly.js-style-' + uid, + style = document.getElementById(id); + if(!style) { + style = document.createElement('style'); + style.setAttribute('id', id); + // WebKit hack :( + style.appendChild(document.createTextNode('')); + document.head.appendChild(style); + } + var styleSheet = style.sheet; + + if(styleSheet.insertRule) { + styleSheet.insertRule(selector + '{' + styleString + '}', 0); + } + else if(styleSheet.addRule) { + styleSheet.addRule(selector, styleString, 0); + } + else lib.warn('addStyleRule failed'); +}; + +/** + * to remove from the page a stylesheet identified by a given uid + */ +lib.deleteRelatedStyleRule = function(uid) { + var id = 'plotly.js-style-' + uid, + style = document.getElementById(id); + if(style) lib.removeElement(style); +}; + +lib.isIE = function() { + return typeof window.navigator.msSaveBlob !== 'undefined'; +}; + +/** + * Duck typing to recognize a d3 selection, mostly for IE9's benefit + * because it doesn't handle instanceof like modern browsers + */ +lib.isD3Selection = function(obj) { + return obj && (typeof obj.classed === 'function'); +}; + +/** + * Append element to DOM only if not present. + * + * @param {d3 selection} parent : parent selection of the element in question + * @param {string} nodeType : node type of element to append + * @param {string} className (optional) : class name of element in question + * @param {fn} enterFn (optional) : optional fn applied to entering elements only + * @return {d3 selection} selection of new layer + * + * Previously, we were using the following pattern: + * + * ``` + * var sel = parent.selectAll('.' + className) + * .data([0]); + * + * sel.enter().append(nodeType) + * .classed(className, true); + * + * return sel; + * ``` + * + * in numerous places in our codebase to achieve the same behavior. + * + * The logic below performs much better, mostly as we are using + * `.select` instead `.selectAll` that is `querySelector` instead of + * `querySelectorAll`. + * + */ +lib.ensureSingle = function(parent, nodeType, className, enterFn) { + var sel = parent.select(nodeType + (className ? '.' + className : '')); + if(sel.size()) return sel; + + var layer = parent.append(nodeType); + if(className) layer.classed(className, true); + if(enterFn) layer.call(enterFn); + + return layer; +}; + +/** + * Same as Lib.ensureSingle, but using id as selector. + * This version is mostly used for clipPath nodes. + * + * @param {d3 selection} parent : parent selection of the element in question + * @param {string} nodeType : node type of element to append + * @param {string} id : id of element in question + * @param {fn} enterFn (optional) : optional fn applied to entering elements only + * @return {d3 selection} selection of new layer + */ +lib.ensureSingleById = function(parent, nodeType, id, enterFn) { + var sel = parent.select(nodeType + '#' + id); + if(sel.size()) return sel; + + var layer = parent.append(nodeType).attr('id', id); + if(enterFn) layer.call(enterFn); + + return layer; +}; + +/** + * Converts a string path to an object. + * + * When given a string containing an array element, it will create a `null` + * filled array of the given size. + * + * @example + * lib.objectFromPath('nested.test[2].path', 'value'); + * // returns { nested: { test: [null, null, { path: 'value' }]} + * + * @param {string} path to nested value + * @param {*} any value to be set + * + * @return {Object} the constructed object with a full nested path + */ +lib.objectFromPath = function(path, value) { + var keys = path.split('.'), + tmpObj, + obj = tmpObj = {}; + + for(var i = 0; i < keys.length; i++) { + var key = keys[i]; + var el = null; + + var parts = keys[i].match(/(.*)\[([0-9]+)\]/); + + if(parts) { + key = parts[1]; + el = parts[2]; + + tmpObj = tmpObj[key] = []; + + if(i === keys.length - 1) { + tmpObj[el] = value; + } else { + tmpObj[el] = {}; + } + + tmpObj = tmpObj[el]; + } else { + + if(i === keys.length - 1) { + tmpObj[key] = value; + } else { + tmpObj[key] = {}; + } + + tmpObj = tmpObj[key]; + } + } + + return obj; +}; + +/** + * Iterate through an object in-place, converting dotted properties to objects. + * + * Examples: + * + * lib.expandObjectPaths({'nested.test.path': 'value'}); + * => { nested: { test: {path: 'value'}}} + * + * It also handles array notation, e.g.: + * + * lib.expandObjectPaths({'foo[1].bar': 'value'}); + * => { foo: [null, {bar: value}] } + * + * It handles merges the results when two properties are specified in parallel: + * + * lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20}); + * => { foo: [{bar: 10}, {bar: 20}] } + * + * It does NOT, however, merge mulitple mutliply-nested arrays:: + * + * lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4}) + * => { marker: [null, {range: 4}] } + */ + +// Store this to avoid recompiling regex on *every* prop since this may happen many +// many times for animations. Could maybe be inside the function. Not sure about +// scoping vs. recompilation tradeoff, but at least it's not just inlining it into +// the inner loop. +var dottedPropertyRegex = /^([^\[\.]+)\.(.+)?/; +var indexedPropertyRegex = /^([^\.]+)\[([0-9]+)\](\.)?(.+)?/; + +lib.expandObjectPaths = function(data) { + var match, key, prop, datum, idx, dest, trailingPath; + if(typeof data === 'object' && !Array.isArray(data)) { + for(key in data) { + if(data.hasOwnProperty(key)) { + if((match = key.match(dottedPropertyRegex))) { + datum = data[key]; + prop = match[1]; + + delete data[key]; + + data[prop] = lib.extendDeepNoArrays(data[prop] || {}, lib.objectFromPath(key, lib.expandObjectPaths(datum))[prop]); + } else if((match = key.match(indexedPropertyRegex))) { + datum = data[key]; + + prop = match[1]; + idx = parseInt(match[2]); + + delete data[key]; + + data[prop] = data[prop] || []; + + if(match[3] === '.') { + // This is the case where theere are subsequent properties into which + // we must recurse, e.g. transforms[0].value + trailingPath = match[4]; + dest = data[prop][idx] = data[prop][idx] || {}; + + // NB: Extend deep no arrays prevents this from working on multiple + // nested properties in the same object, e.g. + // + // { + // foo[0].bar[1].range + // foo[0].bar[0].range + // } + // + // In this case, the extendDeepNoArrays will overwrite one array with + // the other, so that both properties *will not* be present in the + // result. Fixing this would require a more intelligent tracking + // of changes and merging than extendDeepNoArrays currently accomplishes. + lib.extendDeepNoArrays(dest, lib.objectFromPath(trailingPath, lib.expandObjectPaths(datum))); + } else { + // This is the case where this property is the end of the line, + // e.g. xaxis.range[0] + data[prop][idx] = lib.expandObjectPaths(datum); + } + } else { + data[key] = lib.expandObjectPaths(data[key]); + } + } + } + } + + return data; +}; + +/** + * Converts value to string separated by the provided separators. + * + * @example + * lib.numSeparate(2016, '.,'); + * // returns '2016' + * + * @example + * lib.numSeparate(3000, '.,', true); + * // returns '3,000' + * + * @example + * lib.numSeparate(1234.56, '|,') + * // returns '1,234|56' + * + * @param {string|number} value the value to be converted + * @param {string} separators string of decimal, then thousands separators + * @param {boolean} separatethousands boolean, 4-digit integers are separated if true + * + * @return {string} the value that has been separated + */ +lib.numSeparate = function(value, separators, separatethousands) { + if(!separatethousands) separatethousands = false; + + if(typeof separators !== 'string' || separators.length === 0) { + throw new Error('Separator string required for formatting!'); + } + + if(typeof value === 'number') { + value = String(value); + } + + var thousandsRe = /(\d+)(\d{3})/, + decimalSep = separators.charAt(0), + thouSep = separators.charAt(1); + + var x = value.split('.'), + x1 = x[0], + x2 = x.length > 1 ? decimalSep + x[1] : ''; + + // Years are ignored for thousands separators + if(thouSep && (x.length > 1 || x1.length > 4 || separatethousands)) { + while(thousandsRe.test(x1)) { + x1 = x1.replace(thousandsRe, '$1' + thouSep + '$2'); + } + } + + return x1 + x2; +}; + +var TEMPLATE_STRING_REGEX = /%{([^\s%{}]*)}/g; +var SIMPLE_PROPERTY_REGEX = /^\w*$/; + +/* + * Substitute values from an object into a string + * + * Examples: + * Lib.templateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf' + * Lib.templateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf' + * + * @param {string} input string containing %{...} template strings + * @param {obj} data object containing substitution values + * + * @return {string} templated string + */ + +lib.templateString = function(string, obj) { + // Not all that useful, but cache nestedProperty instantiation + // just in case it speeds things up *slightly*: + var getterCache = {}; + + return string.replace(TEMPLATE_STRING_REGEX, function(dummy, key) { + if(SIMPLE_PROPERTY_REGEX.test(key)) { + return obj[key] || ''; + } + getterCache[key] = getterCache[key] || lib.nestedProperty(obj, key).get; + return getterCache[key]() || ''; + }); +}; + +/* + * alphanumeric string sort, tailored for subplot IDs like scene2, scene10, x10y13 etc + */ +var char0 = 48; +var char9 = 57; +lib.subplotSort = function(a, b) { + var l = Math.min(a.length, b.length) + 1; + var numA = 0; + var numB = 0; + for(var i = 0; i < l; i++) { + var charA = a.charCodeAt(i) || 0; + var charB = b.charCodeAt(i) || 0; + var isNumA = charA >= char0 && charA <= char9; + var isNumB = charB >= char0 && charB <= char9; + + if(isNumA) numA = 10 * numA + charA - char0; + if(isNumB) numB = 10 * numB + charB - char0; + + if(!isNumA || !isNumB) { + if(numA !== numB) return numA - numB; + if(charA !== charB) return charA - charB; + } + } + return numB - numA; +}; + +// repeatable pseudorandom generator +var randSeed = 2000000000; + +lib.seedPseudoRandom = function() { + randSeed = 2000000000; +}; + +lib.pseudoRandom = function() { + var lastVal = randSeed; + randSeed = (69069 * randSeed + 1) % 4294967296; + // don't let consecutive vals be too close together + // gets away from really trying to be random, in favor of better local uniformity + if(Math.abs(randSeed - lastVal) < 429496729) return lib.pseudoRandom(); + return randSeed / 4294967296; +}; + +},{"../constants/numerical":673,"./angles":677,"./array":678,"./clean_number":679,"./clear_responsive":681,"./coerce":682,"./dates":683,"./extend":685,"./filter_unique":686,"./filter_visible":687,"./geometry2d":690,"./get_graph_div":691,"./identity":695,"./is_plain_object":697,"./keyed_container":698,"./localize":699,"./loggers":700,"./make_trace_groups":701,"./matrix":702,"./mod":703,"./nested_property":704,"./noop":705,"./notifier":706,"./push_unique":710,"./regex":712,"./relative_attr":713,"./relink_private":714,"./search":715,"./stats":718,"./throttle":721,"./to_log_range":722,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],697:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// more info: http://stackoverflow.com/questions/18531624/isplainobject-thing +module.exports = function isPlainObject(obj) { + + // We need to be a little less strict in the `imagetest` container because + // of how async image requests are handled. + // + // N.B. isPlainObject(new Constructor()) will return true in `imagetest` + if(window && window.process && window.process.versions) { + return Object.prototype.toString.call(obj) === '[object Object]'; + } + + return ( + Object.prototype.toString.call(obj) === '[object Object]' && + Object.getPrototypeOf(obj) === Object.prototype + ); +}; + +},{}],698:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var nestedProperty = _dereq_('./nested_property'); + +var SIMPLE_PROPERTY_REGEX = /^\w*$/; + +// bitmask for deciding what's updated. Sometimes the name needs to be updated, +// sometimes the value needs to be updated, and sometimes both do. This is just +// a simple way to track what's updated such that it's a simple OR operation to +// assimilate new updates. +// +// The only exception is the UNSET bit that tracks when we need to explicitly +// unset and remove the property. This concrn arises because of the special +// way in which nestedProperty handles null/undefined. When you specify `null`, +// it prunes any unused items in the tree. I ran into some issues with it getting +// null vs undefined confused, so UNSET is just a bit that forces the property +// update to send `null`, removing the property explicitly rather than setting +// it to undefined. +var NONE = 0; +var NAME = 1; +var VALUE = 2; +var BOTH = 3; +var UNSET = 4; + +module.exports = function keyedContainer(baseObj, path, keyName, valueName) { + keyName = keyName || 'name'; + valueName = valueName || 'value'; + var i, arr, baseProp; + var changeTypes = {}; + + if(path && path.length) { + baseProp = nestedProperty(baseObj, path); + arr = baseProp.get(); + } else { + arr = baseObj; + } + + path = path || ''; + + // Construct an index: + var indexLookup = {}; + if(arr) { + for(i = 0; i < arr.length; i++) { + indexLookup[arr[i][keyName]] = i; + } + } + + var isSimpleValueProp = SIMPLE_PROPERTY_REGEX.test(valueName); + + var obj = { + set: function(name, value) { + var changeType = value === null ? UNSET : NONE; + + // create the base array if necessary + if(!arr) { + if(!baseProp || changeType === UNSET) return; + + arr = []; + baseProp.set(arr); + } + + var idx = indexLookup[name]; + if(idx === undefined) { + if(changeType === UNSET) return; + + changeType = changeType | BOTH; + idx = arr.length; + indexLookup[name] = idx; + } else if(value !== (isSimpleValueProp ? arr[idx][valueName] : nestedProperty(arr[idx], valueName).get())) { + changeType = changeType | VALUE; + } + + var newValue = arr[idx] = arr[idx] || {}; + newValue[keyName] = name; + + if(isSimpleValueProp) { + newValue[valueName] = value; + } else { + nestedProperty(newValue, valueName).set(value); + } + + // If it's not an unset, force that bit to be unset. This is all related to the fact + // that undefined and null are a bit specially implemented in nestedProperties. + if(value !== null) { + changeType = changeType & ~UNSET; + } + + changeTypes[idx] = changeTypes[idx] | changeType; + + return obj; + }, + get: function(name) { + if(!arr) return; + + var idx = indexLookup[name]; + + if(idx === undefined) { + return undefined; + } else if(isSimpleValueProp) { + return arr[idx][valueName]; + } else { + return nestedProperty(arr[idx], valueName).get(); + } + }, + rename: function(name, newName) { + var idx = indexLookup[name]; + + if(idx === undefined) return obj; + changeTypes[idx] = changeTypes[idx] | NAME; + + indexLookup[newName] = idx; + delete indexLookup[name]; + + arr[idx][keyName] = newName; + + return obj; + }, + remove: function(name) { + var idx = indexLookup[name]; + + if(idx === undefined) return obj; + + var object = arr[idx]; + if(Object.keys(object).length > 2) { + // This object contains more than just the key/value, so unset + // the value without modifying the entry otherwise: + changeTypes[idx] = changeTypes[idx] | VALUE; + return obj.set(name, null); + } + + if(isSimpleValueProp) { + for(i = idx; i < arr.length; i++) { + changeTypes[i] = changeTypes[i] | BOTH; + } + for(i = idx; i < arr.length; i++) { + indexLookup[arr[i][keyName]]--; + } + arr.splice(idx, 1); + delete(indexLookup[name]); + } else { + // Perform this update *strictly* so we can check whether the result's + // been pruned. If so, it's a removal. If not, it's a value unset only. + nestedProperty(object, valueName).set(null); + + // Now check if the top level nested property has any keys left. If so, + // the object still has values so we only want to unset the key. If not, + // the entire object can be removed since there's no other data. + // var topLevelKeys = Object.keys(object[valueName.split('.')[0]] || []); + + changeTypes[idx] = changeTypes[idx] | VALUE | UNSET; + } + + return obj; + }, + constructUpdate: function() { + var astr, idx; + var update = {}; + var changed = Object.keys(changeTypes); + for(var i = 0; i < changed.length; i++) { + idx = changed[i]; + astr = path + '[' + idx + ']'; + if(arr[idx]) { + if(changeTypes[idx] & NAME) { + update[astr + '.' + keyName] = arr[idx][keyName]; + } + if(changeTypes[idx] & VALUE) { + if(isSimpleValueProp) { + update[astr + '.' + valueName] = (changeTypes[idx] & UNSET) ? null : arr[idx][valueName]; + } else { + update[astr + '.' + valueName] = (changeTypes[idx] & UNSET) ? null : nestedProperty(arr[idx], valueName).get(); + } + } + } else { + update[astr] = null; + } + } + + return update; + } + }; + + return obj; +}; + +},{"./nested_property":704}],699:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../registry'); + +/** + * localize: translate a string for the current locale + * + * @param {object} gd: the graphDiv for context + * gd._context.locale determines the language (& optional region/country) + * the dictionary for each locale may either be supplied in + * gd._context.locales or globally via Plotly.register + * @param {string} s: the string to translate + */ +module.exports = function localize(gd, s) { + var locale = gd._context.locale; + + /* + * Priority of lookup: + * contextDicts[locale], + * registeredDicts[locale], + * contextDicts[baseLocale], (if baseLocale is distinct) + * registeredDicts[baseLocale] + * Return the first translation we find. + * This way if you have a regionalization you are allowed to specify + * only what's different from the base locale, everything else will + * fall back on the base. + */ + for(var i = 0; i < 2; i++) { + var locales = gd._context.locales; + for(var j = 0; j < 2; j++) { + var dict = (locales[locale] || {}).dictionary; + if(dict) { + var out = dict[s]; + if(out) return out; + } + locales = Registry.localeRegistry; + } + + var baseLocale = locale.split('-')[0]; + if(baseLocale === locale) break; + locale = baseLocale; + } + + return s; +}; + +},{"../registry":827}],700:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* eslint-disable no-console */ + +var config = _dereq_('../plot_api/plot_config'); + +var loggers = module.exports = {}; + +/** + * ------------------------------------------ + * debugging tools + * ------------------------------------------ + */ + +loggers.log = function() { + if(config.logging > 1) { + var messages = ['LOG:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + apply(console.trace || console.log, messages); + } +}; + +loggers.warn = function() { + if(config.logging > 0) { + var messages = ['WARN:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + apply(console.trace || console.log, messages); + } +}; + +loggers.error = function() { + if(config.logging > 0) { + var messages = ['ERROR:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + apply(console.error, messages); + } +}; + +/* + * Robust apply, for IE9 where console.log doesn't support + * apply like other functions do + */ +function apply(f, args) { + if(f && f.apply) { + try { + // `this` should always be console, since here we're always + // applying a method of the console object. + f.apply(console, args); + return; + } + catch(e) { /* in case apply failed, fall back on the code below */ } + } + + // no apply - just try calling the function on each arg independently + for(var i = 0; i < args.length; i++) { + try { + f(args[i]); + } + catch(e) { + // still fails - last resort simple console.log + console.log(args[i]); + } + } +} + +},{"../plot_api/plot_config":732}],701:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** + * General helper to manage trace groups based on calcdata + * + * @param {d3.selection} traceLayer: a selection containing a single group + * to draw these traces into + * @param {array} cdModule: array of calcdata items for this + * module and subplot combination. Assumes the calcdata item for each + * trace is an array with the fullData trace attached to the first item. + * @param {string} cls: the class attribute to give each trace group + * so you can give multiple classes separated by spaces + */ +module.exports = function makeTraceGroups(traceLayer, cdModule, cls) { + var traces = traceLayer.selectAll('g.' + cls.replace(/\s/g, '.')) + .data(cdModule, function(cd) { return cd[0].trace.uid; }); + + traces.exit().remove(); + + traces.enter().append('g') + .attr('class', cls); + + traces.order(); + + return traces; +}; + +},{}],702:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +exports.init2dArray = function(rowLength, colLength) { + var array = new Array(rowLength); + for(var i = 0; i < rowLength; i++) array[i] = new Array(colLength); + return array; +}; + +/** + * transpose a (possibly ragged) 2d array z. inspired by + * http://stackoverflow.com/questions/17428587/ + * transposing-a-2d-array-in-javascript + */ +exports.transposeRagged = function(z) { + var maxlen = 0, + zlen = z.length, + i, + j; + // Maximum row length: + for(i = 0; i < zlen; i++) maxlen = Math.max(maxlen, z[i].length); + + var t = new Array(maxlen); + for(i = 0; i < maxlen; i++) { + t[i] = new Array(zlen); + for(j = 0; j < zlen; j++) t[i][j] = z[j][i]; + } + + return t; +}; + +// our own dot function so that we don't need to include numeric +exports.dot = function(x, y) { + if(!(x.length && y.length) || x.length !== y.length) return null; + + var len = x.length, + out, + i; + + if(x[0].length) { + // mat-vec or mat-mat + out = new Array(len); + for(i = 0; i < len; i++) out[i] = exports.dot(x[i], y); + } + else if(y[0].length) { + // vec-mat + var yTranspose = exports.transposeRagged(y); + out = new Array(yTranspose.length); + for(i = 0; i < yTranspose.length; i++) out[i] = exports.dot(x, yTranspose[i]); + } + else { + // vec-vec + out = 0; + for(i = 0; i < len; i++) out += x[i] * y[i]; + } + + return out; +}; + +// translate by (x,y) +exports.translationMatrix = function(x, y) { + return [[1, 0, x], [0, 1, y], [0, 0, 1]]; +}; + +// rotate by alpha around (0,0) +exports.rotationMatrix = function(alpha) { + var a = alpha * Math.PI / 180; + return [[Math.cos(a), -Math.sin(a), 0], + [Math.sin(a), Math.cos(a), 0], + [0, 0, 1]]; +}; + +// rotate by alpha around (x,y) +exports.rotationXYMatrix = function(a, x, y) { + return exports.dot( + exports.dot(exports.translationMatrix(x, y), + exports.rotationMatrix(a)), + exports.translationMatrix(-x, -y)); +}; + +// applies a 2D transformation matrix to either x and y params or an [x,y] array +exports.apply2DTransform = function(transform) { + return function() { + var args = arguments; + if(args.length === 3) { + args = args[0]; + }// from map + var xy = arguments.length === 1 ? args[0] : [args[0], args[1]]; + return exports.dot(transform, [xy[0], xy[1], 1]).slice(0, 2); + }; +}; + +// applies a 2D transformation matrix to an [x1,y1,x2,y2] array (to transform a segment) +exports.apply2DTransform2 = function(transform) { + var at = exports.apply2DTransform(transform); + return function(xys) { + return at(xys.slice(0, 2)).concat(at(xys.slice(2, 4))); + }; +}; + +},{}],703:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * sanitized modulus function that always returns in the range [0, d) + * rather than (-d, 0] if v is negative + */ +function mod(v, d) { + var out = v % d; + return out < 0 ? out + d : out; +} + +/** + * sanitized modulus function that always returns in the range [-d/2, d/2] + * rather than (-d, 0] if v is negative + */ +function modHalf(v, d) { + return Math.abs(v) > (d / 2) ? + v - Math.round(v / d) * d : + v; +} + +module.exports = { + mod: mod, + modHalf: modHalf +}; + +},{}],704:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; + +/** + * convert a string s (such as 'xaxis.range[0]') + * representing a property of nested object into set and get methods + * also return the string and object so we don't have to keep track of them + * allows [-1] for an array index, to set a property inside all elements + * of an array + * eg if obj = {arr: [{a: 1}, {a: 2}]} + * you can do p = nestedProperty(obj, 'arr[-1].a') + * but you cannot set the array itself this way, to do that + * just set the whole array. + * eg if obj = {arr: [1, 2, 3]} + * you can't do nestedProperty(obj, 'arr[-1]').set(5) + * but you can do nestedProperty(obj, 'arr').set([5, 5, 5]) + */ +module.exports = function nestedProperty(container, propStr) { + if(isNumeric(propStr)) propStr = String(propStr); + else if(typeof propStr !== 'string' || + propStr.substr(propStr.length - 4) === '[-1]') { + throw 'bad property string'; + } + + var j = 0, + propParts = propStr.split('.'), + indexed, + indices, + i; + + // check for parts of the nesting hierarchy that are numbers (ie array elements) + while(j < propParts.length) { + // look for non-bracket chars, then any number of [##] blocks + indexed = String(propParts[j]).match(/^([^\[\]]*)((\[\-?[0-9]*\])+)$/); + if(indexed) { + if(indexed[1]) propParts[j] = indexed[1]; + // allow propStr to start with bracketed array indices + else if(j === 0) propParts.splice(0, 1); + else throw 'bad property string'; + + indices = indexed[2] + .substr(1, indexed[2].length - 2) + .split(']['); + + for(i = 0; i < indices.length; i++) { + j++; + propParts.splice(j, 0, Number(indices[i])); + } + } + j++; + } + + if(typeof container !== 'object') { + return badContainer(container, propStr, propParts); + } + + return { + set: npSet(container, propParts, propStr), + get: npGet(container, propParts), + astr: propStr, + parts: propParts, + obj: container + }; +}; + +function npGet(cont, parts) { + return function() { + var curCont = cont, + curPart, + allSame, + out, + i, + j; + + for(i = 0; i < parts.length - 1; i++) { + curPart = parts[i]; + if(curPart === -1) { + allSame = true; + out = []; + for(j = 0; j < curCont.length; j++) { + out[j] = npGet(curCont[j], parts.slice(i + 1))(); + if(out[j] !== out[0]) allSame = false; + } + return allSame ? out[0] : out; + } + if(typeof curPart === 'number' && !isArrayOrTypedArray(curCont)) { + return undefined; + } + curCont = curCont[curPart]; + if(typeof curCont !== 'object' || curCont === null) { + return undefined; + } + } + + // only hit this if parts.length === 1 + if(typeof curCont !== 'object' || curCont === null) return undefined; + + out = curCont[parts[i]]; + if(out === null) return undefined; + return out; + }; +} + +/* + * Can this value be deleted? We can delete `undefined`, and `null` except INSIDE an + * *args* array. + * + * Previously we also deleted some `{}` and `[]`, in order to try and make set/unset + * a net noop; but this causes far more complication than it's worth, and still had + * lots of exceptions. See https://github.com/plotly/plotly.js/issues/1410 + * + * *args* arrays get passed directly to API methods and we should respect null if + * the user put it there, but otherwise null is deleted as we use it as code + * in restyle/relayout/update for "delete this value" whereas undefined means + * "ignore this edit" + */ +var ARGS_PATTERN = /(^|\.)args\[/; +function isDeletable(val, propStr) { + return (val === undefined) || (val === null && !propStr.match(ARGS_PATTERN)); +} + +function npSet(cont, parts, propStr) { + return function(val) { + var curCont = cont, + propPart = '', + containerLevels = [[cont, propPart]], + toDelete = isDeletable(val, propStr), + curPart, + i; + + for(i = 0; i < parts.length - 1; i++) { + curPart = parts[i]; + + if(typeof curPart === 'number' && !isArrayOrTypedArray(curCont)) { + throw 'array index but container is not an array'; + } + + // handle special -1 array index + if(curPart === -1) { + toDelete = !setArrayAll(curCont, parts.slice(i + 1), val, propStr); + if(toDelete) break; + else return; + } + + if(!checkNewContainer(curCont, curPart, parts[i + 1], toDelete)) { + break; + } + + curCont = curCont[curPart]; + + if(typeof curCont !== 'object' || curCont === null) { + throw 'container is not an object'; + } + + propPart = joinPropStr(propPart, curPart); + + containerLevels.push([curCont, propPart]); + } + + if(toDelete) { + if(i === parts.length - 1) { + delete curCont[parts[i]]; + + // The one bit of pruning we still do: drop `undefined` from the end of arrays. + // In case someone has already unset previous items, continue until we hit a + // non-undefined value. + if(Array.isArray(curCont) && +parts[i] === curCont.length - 1) { + while(curCont.length && curCont[curCont.length - 1] === undefined) { + curCont.pop(); + } + } + } + } + else curCont[parts[i]] = val; + }; +} + +function joinPropStr(propStr, newPart) { + var toAdd = newPart; + if(isNumeric(newPart)) toAdd = '[' + newPart + ']'; + else if(propStr) toAdd = '.' + newPart; + + return propStr + toAdd; +} + +// handle special -1 array index +function setArrayAll(containerArray, innerParts, val, propStr) { + var arrayVal = isArrayOrTypedArray(val), + allSet = true, + thisVal = val, + thisPropStr = propStr.replace('-1', 0), + deleteThis = arrayVal ? false : isDeletable(val, thisPropStr), + firstPart = innerParts[0], + i; + + for(i = 0; i < containerArray.length; i++) { + thisPropStr = propStr.replace('-1', i); + if(arrayVal) { + thisVal = val[i % val.length]; + deleteThis = isDeletable(thisVal, thisPropStr); + } + if(deleteThis) allSet = false; + if(!checkNewContainer(containerArray, i, firstPart, deleteThis)) { + continue; + } + npSet(containerArray[i], innerParts, propStr.replace('-1', i))(thisVal); + } + return allSet; +} + +/** + * make new sub-container as needed. + * returns false if there's no container and none is needed + * because we're only deleting an attribute + */ +function checkNewContainer(container, part, nextPart, toDelete) { + if(container[part] === undefined) { + if(toDelete) return false; + + if(typeof nextPart === 'number') container[part] = []; + else container[part] = {}; + } + return true; +} + +function badContainer(container, propStr, propParts) { + return { + set: function() { throw 'bad container'; }, + get: function() {}, + astr: propStr, + parts: propParts, + obj: container + }; +} + +},{"./array":678,"fast-isnumeric":214}],705:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// Simple helper functions +// none of these need any external deps + +module.exports = function noop() {}; + +},{}],706:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var NOTEDATA = []; + +/** + * notifier + * @param {String} text The person's user name + * @param {Number} [delay=1000] The delay time in milliseconds + * or 'long' which provides 2000 ms delay time. + * @return {undefined} this function does not return a value + */ +module.exports = function(text, displayLength) { + if(NOTEDATA.indexOf(text) !== -1) return; + + NOTEDATA.push(text); + + var ts = 1000; + if(isNumeric(displayLength)) ts = displayLength; + else if(displayLength === 'long') ts = 3000; + + var notifierContainer = d3.select('body') + .selectAll('.plotly-notifier') + .data([0]); + notifierContainer.enter() + .append('div') + .classed('plotly-notifier', true); + + var notes = notifierContainer.selectAll('.notifier-note').data(NOTEDATA); + + function killNote(transition) { + transition + .duration(700) + .style('opacity', 0) + .each('end', function(thisText) { + var thisIndex = NOTEDATA.indexOf(thisText); + if(thisIndex !== -1) NOTEDATA.splice(thisIndex, 1); + d3.select(this).remove(); + }); + } + + notes.enter().append('div') + .classed('notifier-note', true) + .style('opacity', 0) + .each(function(thisText) { + var note = d3.select(this); + + note.append('button') + .classed('notifier-close', true) + .html('×') + .on('click', function() { + note.transition().call(killNote); + }); + + var p = note.append('p'); + var lines = thisText.split(//g); + for(var i = 0; i < lines.length; i++) { + if(i) p.append('br'); + p.append('span').text(lines[i]); + } + + note.transition() + .duration(700) + .style('opacity', 1) + .transition() + .delay(ts) + .call(killNote); + }); +}; + +},{"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],707:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var setCursor = _dereq_('./setcursor'); + +var STASHATTR = 'data-savedcursor'; +var NO_CURSOR = '!!'; + +/* + * works with our CSS cursor classes (see css/_cursor.scss) + * to override a previous cursor set on d3 single-element selections, + * by moving the name of the original cursor to the data-savedcursor attr. + * omit cursor to revert to the previously set value. + */ +module.exports = function overrideCursor(el3, csr) { + var savedCursor = el3.attr(STASHATTR); + if(csr) { + if(!savedCursor) { + var classes = (el3.attr('class') || '').split(' '); + for(var i = 0; i < classes.length; i++) { + var cls = classes[i]; + if(cls.indexOf('cursor-') === 0) { + el3.attr(STASHATTR, cls.substr(7)) + .classed(cls, false); + } + } + if(!el3.attr(STASHATTR)) { + el3.attr(STASHATTR, NO_CURSOR); + } + } + setCursor(el3, csr); + } + else if(savedCursor) { + el3.attr(STASHATTR, null); + + if(savedCursor === NO_CURSOR) setCursor(el3); + else setCursor(el3, savedCursor); + } +}; + +},{"./setcursor":716}],708:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var dot = _dereq_('./matrix').dot; +var BADNUM = _dereq_('../constants/numerical').BADNUM; + +var polygon = module.exports = {}; + +/** + * Turn an array of [x, y] pairs into a polygon object + * that can test if points are inside it + * + * @param ptsIn Array of [x, y] pairs + * + * @returns polygon Object {xmin, xmax, ymin, ymax, pts, contains} + * (x|y)(min|max) are the bounding rect of the polygon + * pts is the original array, with the first pair repeated at the end + * contains is a function: (pt, omitFirstEdge) + * pt is the [x, y] pair to test + * omitFirstEdge truthy means points exactly on the first edge don't + * count. This is for use adding one polygon to another so we + * don't double-count the edge where they meet. + * returns boolean: is pt inside the polygon (including on its edges) + */ +polygon.tester = function tester(ptsIn) { + var pts = ptsIn.slice(), + xmin = pts[0][0], + xmax = xmin, + ymin = pts[0][1], + ymax = ymin, + i; + + pts.push(pts[0]); + for(i = 1; i < pts.length; i++) { + xmin = Math.min(xmin, pts[i][0]); + xmax = Math.max(xmax, pts[i][0]); + ymin = Math.min(ymin, pts[i][1]); + ymax = Math.max(ymax, pts[i][1]); + } + + // do we have a rectangle? Handle this here, so we can use the same + // tester for the rectangular case without sacrificing speed + + var isRect = false, + rectFirstEdgeTest; + + if(pts.length === 5) { + if(pts[0][0] === pts[1][0]) { // vert, horz, vert, horz + if(pts[2][0] === pts[3][0] && + pts[0][1] === pts[3][1] && + pts[1][1] === pts[2][1]) { + isRect = true; + rectFirstEdgeTest = function(pt) { return pt[0] === pts[0][0]; }; + } + } + else if(pts[0][1] === pts[1][1]) { // horz, vert, horz, vert + if(pts[2][1] === pts[3][1] && + pts[0][0] === pts[3][0] && + pts[1][0] === pts[2][0]) { + isRect = true; + rectFirstEdgeTest = function(pt) { return pt[1] === pts[0][1]; }; + } + } + } + + function rectContains(pt, omitFirstEdge) { + var x = pt[0], + y = pt[1]; + + if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { + // pt is outside the bounding box of polygon + return false; + } + if(omitFirstEdge && rectFirstEdgeTest(pt)) return false; + + return true; + } + + function contains(pt, omitFirstEdge) { + var x = pt[0], + y = pt[1]; + + if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { + // pt is outside the bounding box of polygon + return false; + } + + var imax = pts.length, + x1 = pts[0][0], + y1 = pts[0][1], + crossings = 0, + i, + x0, + y0, + xmini, + ycross; + + for(i = 1; i < imax; i++) { + // find all crossings of a vertical line upward from pt with + // polygon segments + // crossings exactly at xmax don't count, unless the point is + // exactly on the segment, then it counts as inside. + x0 = x1; + y0 = y1; + x1 = pts[i][0]; + y1 = pts[i][1]; + xmini = Math.min(x0, x1); + + // outside the bounding box of this segment, it's only a crossing + // if it's below the box. + if(x < xmini || x > Math.max(x0, x1) || y > Math.max(y0, y1)) { + continue; + } + else if(y < Math.min(y0, y1)) { + // don't count the left-most point of the segment as a crossing + // because we don't want to double-count adjacent crossings + // UNLESS the polygon turns past vertical at exactly this x + // Note that this is repeated below, but we can't factor it out + // because + if(x !== xmini) crossings++; + } + // inside the bounding box, check the actual line intercept + else { + // vertical segment - we know already that the point is exactly + // on the segment, so mark the crossing as exactly at the point. + if(x1 === x0) ycross = y; + // any other angle + else ycross = y0 + (x - x0) * (y1 - y0) / (x1 - x0); + + // exactly on the edge: counts as inside the polygon, unless it's the + // first edge and we're omitting it. + if(y === ycross) { + if(i === 1 && omitFirstEdge) return false; + return true; + } + + if(y <= ycross && x !== xmini) crossings++; + } + } + + // if we've gotten this far, odd crossings means inside, even is outside + return crossings % 2 === 1; + } + + // detect if poly is degenerate + var degenerate = true; + var lastPt = pts[0]; + for(i = 1; i < pts.length; i++) { + if(lastPt[0] !== pts[i][0] || lastPt[1] !== pts[i][1]) { + degenerate = false; + break; + } + } + + return { + xmin: xmin, + xmax: xmax, + ymin: ymin, + ymax: ymax, + pts: pts, + contains: isRect ? rectContains : contains, + isRect: isRect, + degenerate: degenerate + }; +}; + +/** + * Test if a segment of a points array is bent or straight + * + * @param pts Array of [x, y] pairs + * @param start the index of the proposed start of the straight section + * @param end the index of the proposed end point + * @param tolerance the max distance off the line connecting start and end + * before the line counts as bent + * @returns boolean: true means this segment is bent, false means straight + */ +var isBent = polygon.isSegmentBent = function isBent(pts, start, end, tolerance) { + var startPt = pts[start], + segment = [pts[end][0] - startPt[0], pts[end][1] - startPt[1]], + segmentSquared = dot(segment, segment), + segmentLen = Math.sqrt(segmentSquared), + unitPerp = [-segment[1] / segmentLen, segment[0] / segmentLen], + i, + part, + partParallel; + + for(i = start + 1; i < end; i++) { + part = [pts[i][0] - startPt[0], pts[i][1] - startPt[1]]; + partParallel = dot(part, segment); + + if(partParallel < 0 || partParallel > segmentSquared || + Math.abs(dot(part, unitPerp)) > tolerance) return true; + } + return false; +}; + +/** + * Make a filtering polygon, to minimize the number of segments + * + * @param pts Array of [x, y] pairs (must start with at least 1 pair) + * @param tolerance the maximum deviation from straight allowed for + * removing points to simplify the polygon + * + * @returns Object {addPt, raw, filtered} + * addPt is a function(pt: [x, y] pair) to add a raw point and + * continue filtering + * raw is all the input points + * filtered is the resulting filtered Array of [x, y] pairs + */ +polygon.filter = function filter(pts, tolerance) { + var ptsFiltered = [pts[0]], + doneRawIndex = 0, + doneFilteredIndex = 0; + + function addPt(pt) { + pts.push(pt); + var prevFilterLen = ptsFiltered.length, + iLast = doneRawIndex; + ptsFiltered.splice(doneFilteredIndex + 1); + + for(var i = iLast + 1; i < pts.length; i++) { + if(i === pts.length - 1 || isBent(pts, iLast, i + 1, tolerance)) { + ptsFiltered.push(pts[i]); + if(ptsFiltered.length < prevFilterLen - 2) { + doneRawIndex = i; + doneFilteredIndex = ptsFiltered.length - 1; + } + iLast = i; + } + } + } + + if(pts.length > 1) { + var lastPt = pts.pop(); + addPt(lastPt); + } + + return { + addPt: addPt, + raw: pts, + filtered: ptsFiltered + }; +}; + +},{"../constants/numerical":673,"./matrix":702}],709:[function(_dereq_,module,exports){ +(function (global){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var showNoWebGlMsg = _dereq_('./show_no_webgl_msg'); + +// Note that this module should be ONLY required into +// files corresponding to regl trace modules +// so that bundles with non-regl only don't include +// regl and all its bytes. +var createRegl = _dereq_('regl'); + +/** + * Idempotent version of createRegl. Create regl instances + * in the correct canvases with the correct attributes and + * options + * + * @param {DOM node or object} gd : graph div object + * @param {array} extensions : list of extension to pass to createRegl + * + * @return {boolean} true if all createRegl calls succeeded, false otherwise + */ +module.exports = function prepareRegl(gd, extensions) { + var fullLayout = gd._fullLayout; + var success = true; + + fullLayout._glcanvas.each(function(d) { + if(d.regl) return; + // only parcoords needs pick layer + if(d.pick && !fullLayout._has('parcoords')) return; + + try { + d.regl = createRegl({ + canvas: this, + attributes: { + antialias: !d.pick, + preserveDrawingBuffer: true + }, + pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio, + extensions: extensions || [] + }); + } catch(e) { + success = false; + } + + if(success) { + this.addEventListener('webglcontextlost', function(event) { + if(gd && gd.emit) { + gd.emit('plotly_webglcontextlost', { + event: event, + layer: d.key + }); + } + }, false); + } + }); + + if(!success) { + showNoWebGlMsg({container: fullLayout._glcontainer.node()}); + } + return success; +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./show_no_webgl_msg":717,"regl":478}],710:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Push array with unique items + * + * Ignores falsy items, except 0 so we can use it to construct arrays of indices. + * + * @param {array} array + * array to be filled + * @param {any} item + * item to be or not to be inserted + * @return {array} + * ref to array (now possibly containing one more item) + * + */ +module.exports = function pushUnique(array, item) { + if(item instanceof RegExp) { + var itemStr = item.toString(), + i; + for(i = 0; i < array.length; i++) { + if(array[i] instanceof RegExp && array[i].toString() === itemStr) { + return array; + } + } + array.push(item); + } + else if((item || item === 0) && array.indexOf(item) === -1) array.push(item); + + return array; +}; + +},{}],711:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../lib'); +var config = _dereq_('../plot_api/plot_config'); + + +/** + * Copy arg array *without* removing `undefined` values from objects. + * + * @param gd + * @param args + * @returns {Array} + */ +function copyArgArray(gd, args) { + var copy = []; + var arg; + + for(var i = 0; i < args.length; i++) { + arg = args[i]; + + if(arg === gd) copy[i] = arg; + else if(typeof arg === 'object') { + copy[i] = Array.isArray(arg) ? + Lib.extendDeep([], arg) : + Lib.extendDeepAll({}, arg); + } + else copy[i] = arg; + } + + return copy; +} + + +// ----------------------------------------------------- +// Undo/Redo queue for plots +// ----------------------------------------------------- + + +var queue = {}; + +// TODO: disable/enable undo and redo buttons appropriately + +/** + * Add an item to the undoQueue for a graphDiv + * + * @param gd + * @param undoFunc Function undo this operation + * @param undoArgs Args to supply undoFunc with + * @param redoFunc Function to redo this operation + * @param redoArgs Args to supply redoFunc with + */ +queue.add = function(gd, undoFunc, undoArgs, redoFunc, redoArgs) { + var queueObj, + queueIndex; + + // make sure we have the queue and our position in it + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + queueIndex = gd.undoQueue.index; + + // if we're already playing an undo or redo, or if this is an auto operation + // (like pane resize... any others?) then we don't save this to the undo queue + if(gd.autoplay) { + if(!gd.undoQueue.inSequence) gd.autoplay = false; + return; + } + + // if we're not in a sequence or are just starting, we need a new queue item + if(!gd.undoQueue.sequence || gd.undoQueue.beginSequence) { + queueObj = {undo: {calls: [], args: []}, redo: {calls: [], args: []}}; + gd.undoQueue.queue.splice(queueIndex, gd.undoQueue.queue.length - queueIndex, queueObj); + gd.undoQueue.index += 1; + } else { + queueObj = gd.undoQueue.queue[queueIndex - 1]; + } + gd.undoQueue.beginSequence = false; + + // we unshift to handle calls for undo in a forward for loop later + if(queueObj) { + queueObj.undo.calls.unshift(undoFunc); + queueObj.undo.args.unshift(undoArgs); + queueObj.redo.calls.push(redoFunc); + queueObj.redo.args.push(redoArgs); + } + + if(gd.undoQueue.queue.length > config.queueLength) { + gd.undoQueue.queue.shift(); + gd.undoQueue.index--; + } +}; + +/** + * Begin a sequence of undoQueue changes + * + * @param gd + */ +queue.startSequence = function(gd) { + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + gd.undoQueue.sequence = true; + gd.undoQueue.beginSequence = true; +}; + +/** + * Stop a sequence of undoQueue changes + * + * Call this *after* you're sure your undo chain has ended + * + * @param gd + */ +queue.stopSequence = function(gd) { + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + gd.undoQueue.sequence = false; + gd.undoQueue.beginSequence = false; +}; + +/** + * Move one step back in the undo queue, and undo the object there. + * + * @param gd + */ +queue.undo = function undo(gd) { + var queueObj, i; + + if(gd.framework && gd.framework.isPolar) { + gd.framework.undo(); + return; + } + if(gd.undoQueue === undefined || + isNaN(gd.undoQueue.index) || + gd.undoQueue.index <= 0) { + return; + } + + // index is pointing to next *forward* queueObj, point to the one we're undoing + gd.undoQueue.index--; + + // get the queueObj for instructions on how to undo + queueObj = gd.undoQueue.queue[gd.undoQueue.index]; + + // this sequence keeps things from adding to the queue during undo/redo + gd.undoQueue.inSequence = true; + for(i = 0; i < queueObj.undo.calls.length; i++) { + queue.plotDo(gd, queueObj.undo.calls[i], queueObj.undo.args[i]); + } + gd.undoQueue.inSequence = false; + gd.autoplay = false; +}; + +/** + * Redo the current object in the undo, then move forward in the queue. + * + * @param gd + */ +queue.redo = function redo(gd) { + var queueObj, i; + + if(gd.framework && gd.framework.isPolar) { + gd.framework.redo(); + return; + } + if(gd.undoQueue === undefined || + isNaN(gd.undoQueue.index) || + gd.undoQueue.index >= gd.undoQueue.queue.length) { + return; + } + + // get the queueObj for instructions on how to undo + queueObj = gd.undoQueue.queue[gd.undoQueue.index]; + + // this sequence keeps things from adding to the queue during undo/redo + gd.undoQueue.inSequence = true; + for(i = 0; i < queueObj.redo.calls.length; i++) { + queue.plotDo(gd, queueObj.redo.calls[i], queueObj.redo.args[i]); + } + gd.undoQueue.inSequence = false; + gd.autoplay = false; + + // index is pointing to the thing we just redid, move it + gd.undoQueue.index++; +}; + +/** + * Called by undo/redo to make the actual changes. + * + * Not meant to be called publically, but included for mocking out in tests. + * + * @param gd + * @param func + * @param args + */ +queue.plotDo = function(gd, func, args) { + gd.autoplay = true; + + // this *won't* copy gd and it preserves `undefined` properties! + args = copyArgArray(gd, args); + + // call the supplied function + func.apply(null, args); +}; + +module.exports = queue; + +},{"../lib":696,"../plot_api/plot_config":732}],712:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * make a regex for matching counter ids/names ie xaxis, xaxis2, xaxis10... + * + * @param {string} head: the head of the pattern, eg 'x' matches 'x', 'x2', 'x10' etc. + * 'xy' is a special case for cartesian subplots: it matches 'x2y3' etc + * @param {Optional(string)} tail: a fixed piece after the id + * eg counterRegex('scene', '.annotations') for scene2.annotations etc. + * @param {boolean} openEnded: if true, the string may continue past the match. + */ +exports.counter = function(head, tail, openEnded) { + var fullTail = (tail || '') + (openEnded ? '' : '$'); + if(head === 'xy') { + return new RegExp('^x([2-9]|[1-9][0-9]+)?y([2-9]|[1-9][0-9]+)?' + fullTail); + } + return new RegExp('^' + head + '([2-9]|[1-9][0-9]+)?' + fullTail); +}; + +},{}],713:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// ASCEND: chop off the last nesting level - either [] or . - to ascend +// the attribute tree. the remaining attrString is in match[1] +var ASCEND = /^(.*)(\.[^\.\[\]]+|\[\d\])$/; + +// SIMPLEATTR: is this an un-nested attribute? (no dots or brackets) +var SIMPLEATTR = /^[^\.\[\]]+$/; + +/* + * calculate a relative attribute string, similar to a relative path + * + * @param {string} baseAttr: + * an attribute string, such as 'annotations[3].x'. The "current location" + * is the attribute string minus the last component ('annotations[3]') + * @param {string} relativeAttr: + * a route to the desired attribute string, using '^' to ascend + * + * @return {string} attrString: + * for example: + * relativeAttr('annotations[3].x', 'y') = 'annotations[3].y' + * relativeAttr('annotations[3].x', '^[2].z') = 'annotations[2].z' + * relativeAttr('annotations[3].x', '^^margin') = 'margin' + * relativeAttr('annotations[3].x', '^^margin.r') = 'margin.r' + */ +module.exports = function(baseAttr, relativeAttr) { + while(relativeAttr) { + var match = baseAttr.match(ASCEND); + + if(match) baseAttr = match[1]; + else if(baseAttr.match(SIMPLEATTR)) baseAttr = ''; + else throw new Error('bad relativeAttr call:' + [baseAttr, relativeAttr]); + + if(relativeAttr.charAt(0) === '^') relativeAttr = relativeAttr.slice(1); + else break; + } + + if(baseAttr && relativeAttr.charAt(0) !== '[') { + return baseAttr + '.' + relativeAttr; + } + return baseAttr + relativeAttr; +}; + +},{}],714:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; +var isPlainObject = _dereq_('./is_plain_object'); + +/** + * Relink private _keys and keys with a function value from one container + * to the new container. + * Relink means copying if object is pass-by-value and adding a reference + * if object is pass-by-ref. + * This prevents deepCopying massive structures like a webgl context. + */ +module.exports = function relinkPrivateKeys(toContainer, fromContainer) { + for(var k in fromContainer) { + var fromVal = fromContainer[k]; + var toVal = toContainer[k]; + + if(toVal === fromVal) { + continue; + } + if(k.charAt(0) === '_' || typeof fromVal === 'function') { + + // if it already exists at this point, it's something + // that we recreate each time around, so ignore it + if(k in toContainer) continue; + + toContainer[k] = fromVal; + } + else if(isArrayOrTypedArray(fromVal) && isArrayOrTypedArray(toVal) && isPlainObject(fromVal[0])) { + + // filter out data_array items that can contain user objects + // most of the time the toVal === fromVal check will catch these early + // but if the user makes new ones we also don't want to recurse in. + if(k === 'customdata' || k === 'ids') continue; + + // recurse into arrays containers + var minLen = Math.min(fromVal.length, toVal.length); + for(var j = 0; j < minLen; j++) { + if((toVal[j] !== fromVal[j]) && isPlainObject(fromVal[j]) && isPlainObject(toVal[j])) { + relinkPrivateKeys(toVal[j], fromVal[j]); + } + } + } + else if(isPlainObject(fromVal) && isPlainObject(toVal)) { + + // recurse into objects, but only if they still exist + relinkPrivateKeys(toVal, fromVal); + + if(!Object.keys(toVal).length) delete toContainer[k]; + } + } +}; + +},{"./array":678,"./is_plain_object":697}],715:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var loggers = _dereq_('./loggers'); +var identity = _dereq_('./identity'); + +// don't trust floating point equality - fraction of bin size to call +// "on the line" and ensure that they go the right way specified by +// linelow +var roundingError = 1e-9; + + +/** + * findBin - find the bin for val - note that it can return outside the + * bin range any pos. or neg. integer for linear bins, or -1 or + * bins.length-1 for explicit. + * bins is either an object {start,size,end} or an array length #bins+1 + * bins can be either increasing or decreasing but must be monotonic + * for linear bins, we can just calculate. For listed bins, run a binary + * search linelow (truthy) says the bin boundary should be attributed to + * the lower bin rather than the default upper bin + */ +exports.findBin = function(val, bins, linelow) { + if(isNumeric(bins.start)) { + return linelow ? + Math.ceil((val - bins.start) / bins.size - roundingError) - 1 : + Math.floor((val - bins.start) / bins.size + roundingError); + } + else { + var n1 = 0; + var n2 = bins.length; + var c = 0; + var binSize = (n2 > 1) ? (bins[n2 - 1] - bins[0]) / (n2 - 1) : 1; + var n, test; + if(binSize >= 0) { + test = linelow ? lessThan : lessOrEqual; + } else { + test = linelow ? greaterOrEqual : greaterThan; + } + val += binSize * roundingError * (linelow ? -1 : 1) * (binSize >= 0 ? 1 : -1); + // c is just to avoid infinite loops if there's an error + while(n1 < n2 && c++ < 100) { + n = Math.floor((n1 + n2) / 2); + if(test(bins[n], val)) n1 = n + 1; + else n2 = n; + } + if(c > 90) loggers.log('Long binary search...'); + return n1 - 1; + } +}; + +function lessThan(a, b) { return a < b; } +function lessOrEqual(a, b) { return a <= b; } +function greaterThan(a, b) { return a > b; } +function greaterOrEqual(a, b) { return a >= b; } + +exports.sorterAsc = function(a, b) { return a - b; }; +exports.sorterDes = function(a, b) { return b - a; }; + +/** + * find distinct values in an array, lumping together ones that appear to + * just be off by a rounding error + * return the distinct values and the minimum difference between any two + */ +exports.distinctVals = function(valsIn) { + var vals = valsIn.slice(); // otherwise we sort the original array... + vals.sort(exports.sorterAsc); + + var l = vals.length - 1, + minDiff = (vals[l] - vals[0]) || 1, + errDiff = minDiff / (l || 1) / 10000, + v2 = [vals[0]]; + + for(var i = 0; i < l; i++) { + // make sure values aren't just off by a rounding error + if(vals[i + 1] > vals[i] + errDiff) { + minDiff = Math.min(minDiff, vals[i + 1] - vals[i]); + v2.push(vals[i + 1]); + } + } + + return {vals: v2, minDiff: minDiff}; +}; + +/** + * return the smallest element from (sorted) array arrayIn that's bigger than val, + * or (reverse) the largest element smaller than val + * used to find the best tick given the minimum (non-rounded) tick + * particularly useful for date/time where things are not powers of 10 + * binary search is probably overkill here... + */ +exports.roundUp = function(val, arrayIn, reverse) { + var low = 0, + high = arrayIn.length - 1, + mid, + c = 0, + dlow = reverse ? 0 : 1, + dhigh = reverse ? 1 : 0, + rounded = reverse ? Math.ceil : Math.floor; + // c is just to avoid infinite loops if there's an error + while(low < high && c++ < 100) { + mid = rounded((low + high) / 2); + if(arrayIn[mid] <= val) low = mid + dlow; + else high = mid - dhigh; + } + return arrayIn[low]; +}; + +/** + * Tweak to Array.sort(sortFn) that improves performance for pre-sorted arrays + * + * Note that newer browsers (such as Chrome v70+) are starting to pick up + * on pre-sorted arrays which may render the following optimization unnecessary + * in the future. + * + * Motivation: sometimes we need to sort arrays but the input is likely to + * already be sorted. Browsers don't seem to pick up on pre-sorted arrays, + * and in fact Chrome is actually *slower* sorting pre-sorted arrays than purely + * random arrays. FF is at least faster if the array is pre-sorted, but still + * not as fast as it could be. + * Here's how this plays out sorting a length-1e6 array: + * + * Calls to Sort FN | Chrome bare | FF bare | Chrome tweak | FF tweak + * | v68.0 Mac | v61.0 Mac| | + * ------------------+---------------+-----------+----------------+------------ + * ordered | 30.4e6 | 10.1e6 | 1e6 | 1e6 + * reversed | 29.4e6 | 9.9e6 | 1e6 + reverse | 1e6 + reverse + * random | ~21e6 | ~18.7e6 | ~21e6 | ~18.7e6 + * + * So this is a substantial win for pre-sorted (ordered or exactly reversed) + * arrays. Including this wrapper on an unsorted array adds a penalty that will + * in general be only a few calls to the sort function. The only case this + * penalty will be significant is if the array is mostly sorted but there are + * a few unsorted items near the end, but the penalty is still at most N calls + * out of (for N=1e6) ~20N total calls + * + * @param {Array} array: the array, to be sorted in place + * @param {function} sortFn: As in Array.sort, function(a, b) that puts + * item a before item b if the return is negative, a after b if positive, + * and no change if zero. + * @return {Array}: the original array, sorted in place. + */ +exports.sort = function(array, sortFn) { + var notOrdered = 0; + var notReversed = 0; + for(var i = 1; i < array.length; i++) { + var pairOrder = sortFn(array[i], array[i - 1]); + if(pairOrder < 0) notOrdered = 1; + else if(pairOrder > 0) notReversed = 1; + if(notOrdered && notReversed) return array.sort(sortFn); + } + return notReversed ? array : array.reverse(); +}; + +/** + * find index in array 'arr' that minimizes 'fn' + * + * @param {array} arr : array where to search + * @param {fn (optional)} fn : function to minimize, + * if not given, fn is the identity function + * @return {integer} + */ +exports.findIndexOfMin = function(arr, fn) { + fn = fn || identity; + + var min = Infinity; + var ind; + + for(var i = 0; i < arr.length; i++) { + var v = fn(arr[i]); + if(v < min) { + min = v; + ind = i; + } + } + return ind; +}; + +},{"./identity":695,"./loggers":700,"fast-isnumeric":214}],716:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// works with our CSS cursor classes (see css/_cursor.scss) +// to apply cursors to d3 single-element selections. +// omit cursor to revert to the default. +module.exports = function setCursor(el3, csr) { + (el3.attr('class') || '').split(' ').forEach(function(cls) { + if(cls.indexOf('cursor-') === 0) el3.classed(cls, false); + }); + + if(csr) el3.classed('cursor-' + csr, true); +}; + +},{}],717:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../components/color'); + +var noop = function() {}; + + +/** + * Prints a no webgl error message into the scene container + * @param {scene instance} scene + * + * Expects 'scene' to have property 'container' + * + */ +module.exports = function showNoWebGlMsg(scene) { + for(var prop in scene) { + if(typeof scene[prop] === 'function') scene[prop] = noop; + } + + scene.destroy = function() { + scene.container.parentNode.removeChild(scene.container); + }; + + var div = document.createElement('div'); + div.className = 'no-webgl'; + div.style.cursor = 'pointer'; + div.style.fontSize = '24px'; + div.style.color = Color.defaults[0]; + div.style.position = 'absolute'; + div.style.left = div.style.top = '0px'; + div.style.width = div.style.height = '100%'; + div.style['background-color'] = Color.lightLine; + div.style['z-index'] = 30; + + var p = document.createElement('p'); + p.textContent = 'WebGL is not supported by your browser - visit https://get.webgl.org for more info'; + p.style.position = 'relative'; + p.style.top = '50%'; + p.style.left = '50%'; + p.style.height = '30%'; + p.style.width = '50%'; + p.style.margin = '-15% 0 0 -25%'; + + div.appendChild(p); + scene.container.appendChild(div); + scene.container.style.background = '#FFFFFF'; + scene.container.onclick = function() { + window.open('https://get.webgl.org'); + }; + + // return before setting up camera and onrender methods + return false; +}; + +},{"../components/color":570}],718:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; + +/** + * aggNums() returns the result of an aggregate function applied to an array of + * values, where non-numerical values have been tossed out. + * + * @param {function} f - aggregation function (e.g., Math.min) + * @param {Number} v - initial value (continuing from previous calls) + * if there's no continuing value, use null for selector-type + * functions (max,min), or 0 for summations + * @param {Array} a - array to aggregate (may be nested, we will recurse, + * but all elements must have the same dimension) + * @param {Number} len - maximum length of a to aggregate + * @return {Number} - result of f applied to a starting from v + */ +exports.aggNums = function(f, v, a, len) { + var i, + b; + if(!len || len > a.length) len = a.length; + if(!isNumeric(v)) v = false; + if(isArrayOrTypedArray(a[0])) { + b = new Array(len); + for(i = 0; i < len; i++) b[i] = exports.aggNums(f, v, a[i]); + a = b; + } + + for(i = 0; i < len; i++) { + if(!isNumeric(v)) v = a[i]; + else if(isNumeric(a[i])) v = f(+v, +a[i]); + } + return v; +}; + +/** + * mean & std dev functions using aggNums, so it handles non-numerics nicely + * even need to use aggNums instead of .length, to toss out non-numerics + */ +exports.len = function(data) { + return exports.aggNums(function(a) { return a + 1; }, 0, data); +}; + +exports.mean = function(data, len) { + if(!len) len = exports.len(data); + return exports.aggNums(function(a, b) { return a + b; }, 0, data) / len; +}; + +exports.midRange = function(numArr) { + if(numArr === undefined || numArr.length === 0) return undefined; + return (exports.aggNums(Math.max, null, numArr) + exports.aggNums(Math.min, null, numArr)) / 2; +}; + +exports.variance = function(data, len, mean) { + if(!len) len = exports.len(data); + if(!isNumeric(mean)) mean = exports.mean(data, len); + + return exports.aggNums(function(a, b) { + return a + Math.pow(b - mean, 2); + }, 0, data) / len; +}; + +exports.stdev = function(data, len, mean) { + return Math.sqrt(exports.variance(data, len, mean)); +}; + +/** + * interp() computes a percentile (quantile) for a given distribution. + * We interpolate the distribution (to compute quantiles, we follow method #10 here: + * http://www.amstat.org/publications/jse/v14n3/langford.html). + * Typically the index or rank (n * arr.length) may be non-integer. + * For reference: ends are clipped to the extreme values in the array; + * For box plots: index you get is half a point too high (see + * http://en.wikipedia.org/wiki/Percentile#Nearest_rank) but note that this definition + * indexes from 1 rather than 0, so we subtract 1/2 (instead of add). + * + * @param {Array} arr - This array contains the values that make up the distribution. + * @param {Number} n - Between 0 and 1, n = p/100 is such that we compute the p^th percentile. + * For example, the 50th percentile (or median) corresponds to n = 0.5 + * @return {Number} - percentile + */ +exports.interp = function(arr, n) { + if(!isNumeric(n)) throw 'n should be a finite number'; + n = n * arr.length - 0.5; + if(n < 0) return arr[0]; + if(n > arr.length - 1) return arr[arr.length - 1]; + var frac = n % 1; + return frac * arr[Math.ceil(n)] + (1 - frac) * arr[Math.floor(n)]; +}; + +},{"./array":678,"fast-isnumeric":214}],719:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var rgba = _dereq_('color-normalize'); + +function str2RgbaArray(color) { + if(!color) return [0, 0, 0, 1]; + return rgba(color); +} + +module.exports = str2RgbaArray; + +},{"color-normalize":108}],720:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* global MathJax:false */ + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../lib'); +var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); +var LINE_SPACING = _dereq_('../constants/alignment').LINE_SPACING; + +// text converter + +function getSize(_selection, _dimension) { + return _selection.node().getBoundingClientRect()[_dimension]; +} + +var FIND_TEX = /([^$]*)([$]+[^$]*[$]+)([^$]*)/; + +exports.convertToTspans = function(_context, gd, _callback) { + var str = _context.text(); + + // Until we get tex integrated more fully (so it can be used along with non-tex) + // allow some elements to prohibit it by attaching 'data-notex' to the original + var tex = (!_context.attr('data-notex')) && + (typeof MathJax !== 'undefined') && + str.match(FIND_TEX); + + var parent = d3.select(_context.node().parentNode); + if(parent.empty()) return; + var svgClass = (_context.attr('class')) ? _context.attr('class').split(' ')[0] : 'text'; + svgClass += '-math'; + parent.selectAll('svg.' + svgClass).remove(); + parent.selectAll('g.' + svgClass + '-group').remove(); + _context.style('display', null) + .attr({ + // some callers use data-unformatted *from the element* in 'cancel' + // so we need it here even if we're going to turn it into math + // these two (plus style and text-anchor attributes) form the key we're + // going to use for Drawing.bBox + 'data-unformatted': str, + 'data-math': 'N' + }); + + function showText() { + if(!parent.empty()) { + svgClass = _context.attr('class') + '-math'; + parent.select('svg.' + svgClass).remove(); + } + _context.text('') + .style('white-space', 'pre'); + + var hasLink = buildSVGText(_context.node(), str); + + if(hasLink) { + // at least in Chrome, pointer-events does not seem + // to be honored in children of elements + // so if we have an anchor, we have to make the + // whole element respond + _context.style('pointer-events', 'all'); + } + + exports.positionText(_context); + + if(_callback) _callback.call(_context); + } + + if(tex) { + ((gd && gd._promises) || []).push(new Promise(function(resolve) { + _context.style('display', 'none'); + var fontSize = parseInt(_context.node().style.fontSize, 10); + var config = {fontSize: fontSize}; + + texToSVG(tex[2], config, function(_svgEl, _glyphDefs, _svgBBox) { + parent.selectAll('svg.' + svgClass).remove(); + parent.selectAll('g.' + svgClass + '-group').remove(); + + var newSvg = _svgEl && _svgEl.select('svg'); + if(!newSvg || !newSvg.node()) { + showText(); + resolve(); + return; + } + + var mathjaxGroup = parent.append('g') + .classed(svgClass + '-group', true) + .attr({ + 'pointer-events': 'none', + 'data-unformatted': str, + 'data-math': 'Y' + }); + + mathjaxGroup.node().appendChild(newSvg.node()); + + // stitch the glyph defs + if(_glyphDefs && _glyphDefs.node()) { + newSvg.node().insertBefore(_glyphDefs.node().cloneNode(true), + newSvg.node().firstChild); + } + + newSvg.attr({ + 'class': svgClass, + height: _svgBBox.height, + preserveAspectRatio: 'xMinYMin meet' + }) + .style({overflow: 'visible', 'pointer-events': 'none'}); + + var fill = _context.node().style.fill || 'black'; + newSvg.select('g').attr({fill: fill, stroke: fill}); + + var newSvgW = getSize(newSvg, 'width'), + newSvgH = getSize(newSvg, 'height'), + newX = +_context.attr('x') - newSvgW * + {start: 0, middle: 0.5, end: 1}[_context.attr('text-anchor') || 'start'], + // font baseline is about 1/4 fontSize below centerline + textHeight = fontSize || getSize(_context, 'height'), + dy = -textHeight / 4; + + if(svgClass[0] === 'y') { + mathjaxGroup.attr({ + transform: 'rotate(' + [-90, +_context.attr('x'), +_context.attr('y')] + + ') translate(' + [-newSvgW / 2, dy - newSvgH / 2] + ')' + }); + newSvg.attr({x: +_context.attr('x'), y: +_context.attr('y')}); + } + else if(svgClass[0] === 'l') { + newSvg.attr({x: _context.attr('x'), y: dy - (newSvgH / 2)}); + } + else if(svgClass[0] === 'a') { + newSvg.attr({x: 0, y: dy}); + } + else { + newSvg.attr({x: newX, y: (+_context.attr('y') + dy - newSvgH / 2)}); + } + + if(_callback) _callback.call(_context, mathjaxGroup); + resolve(mathjaxGroup); + }); + })); + } + else showText(); + + return _context; +}; + + +// MathJax + +var LT_MATCH = /(<|<|<)/g; +var GT_MATCH = /(>|>|>)/g; + +function cleanEscapesForTex(s) { + return s.replace(LT_MATCH, '\\lt ') + .replace(GT_MATCH, '\\gt '); +} + +function texToSVG(_texString, _config, _callback) { + + var originalRenderer, + originalConfig, + originalProcessSectionDelay, + tmpDiv; + + MathJax.Hub.Queue( + function() { + originalConfig = Lib.extendDeepAll({}, MathJax.Hub.config); + + originalProcessSectionDelay = MathJax.Hub.processSectionDelay; + if(MathJax.Hub.processSectionDelay !== undefined) { + // MathJax 2.5+ + MathJax.Hub.processSectionDelay = 0; + } + + return MathJax.Hub.Config({ + messageStyle: 'none', + tex2jax: { + inlineMath: [['$', '$'], ['\\(', '\\)']] + }, + displayAlign: 'left', + }); + }, + function() { + // Get original renderer + originalRenderer = MathJax.Hub.config.menuSettings.renderer; + if(originalRenderer !== 'SVG') { + return MathJax.Hub.setRenderer('SVG'); + } + }, + function() { + var randomID = 'math-output-' + Lib.randstr({}, 64); + tmpDiv = d3.select('body').append('div') + .attr({id: randomID}) + .style({visibility: 'hidden', position: 'absolute'}) + .style({'font-size': _config.fontSize + 'px'}) + .text(cleanEscapesForTex(_texString)); + + return MathJax.Hub.Typeset(tmpDiv.node()); + }, + function() { + var glyphDefs = d3.select('body').select('#MathJax_SVG_glyphs'); + + if(tmpDiv.select('.MathJax_SVG').empty() || !tmpDiv.select('svg').node()) { + Lib.log('There was an error in the tex syntax.', _texString); + _callback(); + } + else { + var svgBBox = tmpDiv.select('svg').node().getBoundingClientRect(); + _callback(tmpDiv.select('.MathJax_SVG'), glyphDefs, svgBBox); + } + + tmpDiv.remove(); + + if(originalRenderer !== 'SVG') { + return MathJax.Hub.setRenderer(originalRenderer); + } + }, + function() { + if(originalProcessSectionDelay !== undefined) { + MathJax.Hub.processSectionDelay = originalProcessSectionDelay; + } + return MathJax.Hub.Config(originalConfig); + }); +} + +var TAG_STYLES = { + // would like to use baseline-shift for sub/sup but FF doesn't support it + // so we need to use dy along with the uber hacky shift-back-to + // baseline below + sup: 'font-size:70%', + sub: 'font-size:70%', + b: 'font-weight:bold', + i: 'font-style:italic', + a: 'cursor:pointer', + span: '', + em: 'font-style:italic;font-weight:bold' +}; + +// baseline shifts for sub and sup +var SHIFT_DY = { + sub: '0.3em', + sup: '-0.6em' +}; +// reset baseline by adding a tspan (empty except for a zero-width space) +// with dy of -70% * SHIFT_DY (because font-size=70%) +var RESET_DY = { + sub: '-0.21em', + sup: '0.42em' +}; +var ZERO_WIDTH_SPACE = '\u200b'; + +/* + * Whitelist of protocols in user-supplied urls. Mostly we want to avoid javascript + * and related attack vectors. The empty items are there for IE, that in various + * versions treats relative paths as having different flavors of no protocol, while + * other browsers have these explicitly inherit the protocol of the page they're in. + */ +var PROTOCOLS = ['http:', 'https:', 'mailto:', '', undefined, ':']; + +var STRIP_TAGS = new RegExp(']*)?/?>', 'g'); + +var NEWLINES = /(\r\n?|\n)/g; + +var SPLIT_TAGS = /(<[^<>]*>)/; + +var ONE_TAG = /<(\/?)([^ >]*)(\s+(.*))?>/i; + +var BR_TAG = //i; + +/* + * style and href: pull them out of either single or double quotes. Also + * - target: (_blank|_self|_parent|_top|framename) + * note that you can't use target to get a popup but if you use popup, + * a `framename` will be passed along as the name of the popup window. + * per the spec, cannot contain whitespace. + * for backward compatibility we default to '_blank' + * - popup: a custom one for us to enable popup (new window) links. String + * for window.open -> strWindowFeatures, like 'menubar=yes,width=500,height=550' + * note that at least in Chrome, you need to give at least one property + * in this string or the page will open in a new tab anyway. We follow this + * convention and will not make a popup if this string is empty. + * per the spec, cannot contain whitespace. + * + * Because we hack in other attributes with style (sub & sup), drop any trailing + * semicolon in user-supplied styles so we can consistently append the tag-dependent style + * + * These are for tag attributes; Chrome anyway will convert entities in + * attribute values, but not in attribute names + * you can test this by for example: + * > p = document.createElement('p') + * > p.innerHTML = 'Hi' + * > p.innerHTML + * <- 'Hi' + */ +var STYLEMATCH = /(^|[\s"'])style\s*=\s*("([^"]*);?"|'([^']*);?')/i; +var HREFMATCH = /(^|[\s"'])href\s*=\s*("([^"]*)"|'([^']*)')/i; +var TARGETMATCH = /(^|[\s"'])target\s*=\s*("([^"\s]*)"|'([^'\s]*)')/i; +var POPUPMATCH = /(^|[\s"'])popup\s*=\s*("([\w=,]*)"|'([\w=,]*)')/i; + +// dedicated matcher for these quoted regexes, that can return their results +// in two different places +function getQuotedMatch(_str, re) { + if(!_str) return null; + var match = _str.match(re); + var result = match && (match[3] || match[4]); + return result && convertEntities(result); +} + +var COLORMATCH = /(^|;)\s*color:/; + +exports.plainText = function(_str) { + // strip out our pseudo-html so we have a readable + // version to put into text fields + return (_str || '').replace(STRIP_TAGS, ' '); +}; + +/* + * N.B. HTML entities are listed without the leading '&' and trailing ';' + * https://www.freeformatter.com/html-entities.html + * + * FWIW if we wanted to support the full set, it has 2261 entries: + * https://www.w3.org/TR/html5/entities.json + * though I notice that some of these are duplicates and/or are missing ";" + * eg: "&", "&", "&", and "&" all map to "&" + * We no longer need to include numeric entities here, these are now handled + * by String.fromCodePoint/fromCharCode + * + * Anyway the only ones that are really important to allow are the HTML special + * chars <, >, and &, because these ones can trigger special processing if not + * replaced by the corresponding entity. + */ +var entityToUnicode = { + mu: 'μ', + amp: '&', + lt: '<', + gt: '>', + nbsp: ' ', + times: '×', + plusmn: '±', + deg: '°' +}; + +// NOTE: in general entities can contain uppercase too (so [a-zA-Z]) but all the +// ones we support use only lowercase. If we ever change that, update the regex. +var ENTITY_MATCH = /&(#\d+|#x[\da-fA-F]+|[a-z]+);/g; +function convertEntities(_str) { + return _str.replace(ENTITY_MATCH, function(fullMatch, innerMatch) { + var outChar; + if(innerMatch.charAt(0) === '#') { + // cannot use String.fromCodePoint in IE + outChar = fromCodePoint( + innerMatch.charAt(1) === 'x' ? + parseInt(innerMatch.substr(2), 16) : + parseInt(innerMatch.substr(1), 10) + ); + } + else outChar = entityToUnicode[innerMatch]; + + // as in regular HTML, if we didn't decode the entity just + // leave the raw text in place. + return outChar || fullMatch; + }); +} +exports.convertEntities = convertEntities; + +function fromCodePoint(code) { + // Don't allow overflow. In Chrome this turns into � but I feel like it's + // more useful to just not convert it at all. + if(code > 0x10FFFF) return; + var stringFromCodePoint = String.fromCodePoint; + if(stringFromCodePoint) return stringFromCodePoint(code); + + // IE doesn't have String.fromCodePoint + // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint + var stringFromCharCode = String.fromCharCode; + if(code <= 0xFFFF) return stringFromCharCode(code); + return stringFromCharCode( + (code >> 10) + 0xD7C0, + (code % 0x400) + 0xDC00 + ); +} + +/* + * buildSVGText: convert our pseudo-html into SVG tspan elements, and attach these + * to containerNode + * + * @param {svg text element} containerNode: the node to insert this text into + * @param {string} str: the pseudo-html string to convert to svg + * + * @returns {bool}: does the result contain any links? We need to handle the text element + * somewhat differently if it does, so just keep track of this when it happens. + */ +function buildSVGText(containerNode, str) { + /* + * Normalize behavior between IE and others wrt newlines and whitespace:pre + * this combination makes IE barf https://github.com/plotly/plotly.js/issues/746 + * Chrome and FF display \n, \r, or \r\n as a space in this mode. + * I feel like at some point we turned these into
but currently we don't so + * I'm just going to cement what we do now in Chrome and FF + */ + str = str.replace(NEWLINES, ' '); + + var hasLink = false; + + // as we're building the text, keep track of what elements we're nested inside + // nodeStack will be an array of {node, type, style, href, target, popup} + // where only type: 'a' gets the last 3 and node is only added when it's created + var nodeStack = []; + var currentNode; + var currentLine = -1; + + function newLine() { + currentLine++; + + var lineNode = document.createElementNS(xmlnsNamespaces.svg, 'tspan'); + d3.select(lineNode).attr({ + class: 'line', + dy: (currentLine * LINE_SPACING) + 'em' + }); + containerNode.appendChild(lineNode); + + currentNode = lineNode; + + var oldNodeStack = nodeStack; + nodeStack = [{node: lineNode}]; + + if(oldNodeStack.length > 1) { + for(var i = 1; i < oldNodeStack.length; i++) { + enterNode(oldNodeStack[i]); + } + } + } + + function enterNode(nodeSpec) { + var type = nodeSpec.type; + var nodeAttrs = {}; + var nodeType; + + if(type === 'a') { + nodeType = 'a'; + var target = nodeSpec.target; + var href = nodeSpec.href; + var popup = nodeSpec.popup; + if(href) { + nodeAttrs = { + 'xlink:xlink:show': (target === '_blank' || target.charAt(0) !== '_') ? 'new' : 'replace', + target: target, + 'xlink:xlink:href': href + }; + if(popup) { + // security: href and target are not inserted as code but + // as attributes. popup is, but limited to /[A-Za-z0-9_=,]/ + nodeAttrs.onclick = 'window.open(this.href.baseVal,this.target.baseVal,"' + + popup + '");return false;'; + } + } + } + else nodeType = 'tspan'; + + if(nodeSpec.style) nodeAttrs.style = nodeSpec.style; + + var newNode = document.createElementNS(xmlnsNamespaces.svg, nodeType); + + if(type === 'sup' || type === 'sub') { + addTextNode(currentNode, ZERO_WIDTH_SPACE); + currentNode.appendChild(newNode); + + var resetter = document.createElementNS(xmlnsNamespaces.svg, 'tspan'); + addTextNode(resetter, ZERO_WIDTH_SPACE); + d3.select(resetter).attr('dy', RESET_DY[type]); + nodeAttrs.dy = SHIFT_DY[type]; + + currentNode.appendChild(newNode); + currentNode.appendChild(resetter); + } + else { + currentNode.appendChild(newNode); + } + + d3.select(newNode).attr(nodeAttrs); + + currentNode = nodeSpec.node = newNode; + nodeStack.push(nodeSpec); + } + + function addTextNode(node, text) { + node.appendChild(document.createTextNode(text)); + } + + function exitNode(type) { + // A bare closing tag can't close the root node. If we encounter this it + // means there's an extra closing tag that can just be ignored: + if(nodeStack.length === 1) { + Lib.log('Ignoring unexpected end tag .', str); + return; + } + + var innerNode = nodeStack.pop(); + + if(type !== innerNode.type) { + Lib.log('Start tag <' + innerNode.type + '> doesnt match end tag <' + + type + '>. Pretending it did match.', str); + } + currentNode = nodeStack[nodeStack.length - 1].node; + } + + var hasLines = BR_TAG.test(str); + + if(hasLines) newLine(); + else { + currentNode = containerNode; + nodeStack = [{node: containerNode}]; + } + + var parts = str.split(SPLIT_TAGS); + for(var i = 0; i < parts.length; i++) { + var parti = parts[i]; + var match = parti.match(ONE_TAG); + var tagType = match && match[2].toLowerCase(); + var tagStyle = TAG_STYLES[tagType]; + + if(tagType === 'br') { + newLine(); + } + else if(tagStyle === undefined) { + addTextNode(currentNode, convertEntities(parti)); + } + else { + // tag - open or close + if(match[1]) { + exitNode(tagType); + } + else { + var extra = match[4]; + + var nodeSpec = {type: tagType}; + + // now add style, from both the tag name and any extra css + // Most of the svg css that users will care about is just like html, + // but font color is different (uses fill). Let our users ignore this. + var css = getQuotedMatch(extra, STYLEMATCH); + if(css) { + css = css.replace(COLORMATCH, '$1 fill:'); + if(tagStyle) css += ';' + tagStyle; + } + else if(tagStyle) css = tagStyle; + + if(css) nodeSpec.style = css; + + if(tagType === 'a') { + hasLink = true; + + var href = getQuotedMatch(extra, HREFMATCH); + + if(href) { + // check safe protocols + var dummyAnchor = document.createElement('a'); + dummyAnchor.href = href; + if(PROTOCOLS.indexOf(dummyAnchor.protocol) !== -1) { + // Decode href to allow both already encoded and not encoded + // URIs. Without decoding prior encoding, an already encoded + // URI would be encoded twice producing a semantically different URI. + nodeSpec.href = encodeURI(decodeURI(href)); + nodeSpec.target = getQuotedMatch(extra, TARGETMATCH) || '_blank'; + nodeSpec.popup = getQuotedMatch(extra, POPUPMATCH); + } + } + } + + enterNode(nodeSpec); + } + } + } + + return hasLink; +} + +exports.lineCount = function lineCount(s) { + return s.selectAll('tspan.line').size() || 1; +}; + +exports.positionText = function positionText(s, x, y) { + return s.each(function() { + var text = d3.select(this); + + function setOrGet(attr, val) { + if(val === undefined) { + val = text.attr(attr); + if(val === null) { + text.attr(attr, 0); + val = 0; + } + } + else text.attr(attr, val); + return val; + } + + var thisX = setOrGet('x', x); + var thisY = setOrGet('y', y); + + if(this.nodeName === 'text') { + text.selectAll('tspan.line').attr({x: thisX, y: thisY}); + } + }); +}; + +function alignHTMLWith(_base, container, options) { + var alignH = options.horizontalAlign, + alignV = options.verticalAlign || 'top', + bRect = _base.node().getBoundingClientRect(), + cRect = container.node().getBoundingClientRect(), + thisRect, + getTop, + getLeft; + + if(alignV === 'bottom') { + getTop = function() { return bRect.bottom - thisRect.height; }; + } else if(alignV === 'middle') { + getTop = function() { return bRect.top + (bRect.height - thisRect.height) / 2; }; + } else { // default: top + getTop = function() { return bRect.top; }; + } + + if(alignH === 'right') { + getLeft = function() { return bRect.right - thisRect.width; }; + } else if(alignH === 'center') { + getLeft = function() { return bRect.left + (bRect.width - thisRect.width) / 2; }; + } else { // default: left + getLeft = function() { return bRect.left; }; + } + + return function() { + thisRect = this.node().getBoundingClientRect(); + this.style({ + top: (getTop() - cRect.top) + 'px', + left: (getLeft() - cRect.left) + 'px', + 'z-index': 1000 + }); + return this; + }; +} + +/* + * Editable title + * @param {d3.selection} context: the element being edited. Normally text, + * but if it isn't, you should provide the styling options + * @param {object} options: + * @param {div} options.gd: graphDiv + * @param {d3.selection} options.delegate: item to bind events to if not this + * @param {boolean} options.immediate: start editing now (true) or on click (false, default) + * @param {string} options.fill: font color if not as shown + * @param {string} options.background: background color if not as shown + * @param {string} options.text: initial text, if not as shown + * @param {string} options.horizontalAlign: alignment of the edit box wrt. the bound element + * @param {string} options.verticalAlign: alignment of the edit box wrt. the bound element + */ + +exports.makeEditable = function(context, options) { + var gd = options.gd; + var _delegate = options.delegate; + var dispatch = d3.dispatch('edit', 'input', 'cancel'); + var handlerElement = _delegate || context; + + context.style({'pointer-events': _delegate ? 'none' : 'all'}); + + if(context.size() !== 1) throw new Error('boo'); + + function handleClick() { + appendEditable(); + context.style({opacity: 0}); + // also hide any mathjax svg + var svgClass = handlerElement.attr('class'), + mathjaxClass; + if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; + else mathjaxClass = '[class*=-math-group]'; + if(mathjaxClass) { + d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0}); + } + } + + function selectElementContents(_el) { + var el = _el.node(); + var range = document.createRange(); + range.selectNodeContents(el); + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + el.focus(); + } + + function appendEditable() { + var plotDiv = d3.select(gd); + var container = plotDiv.select('.svg-container'); + var div = container.append('div'); + var cStyle = context.node().style; + var fontSize = parseFloat(cStyle.fontSize || 12); + + var initialText = options.text; + if(initialText === undefined) initialText = context.attr('data-unformatted'); + + div.classed('plugin-editable editable', true) + .style({ + position: 'absolute', + 'font-family': cStyle.fontFamily || 'Arial', + 'font-size': fontSize, + color: options.fill || cStyle.fill || 'black', + opacity: 1, + 'background-color': options.background || 'transparent', + outline: '#ffffff33 1px solid', + margin: [-fontSize / 8 + 1, 0, 0, -1].join('px ') + 'px', + padding: '0', + 'box-sizing': 'border-box' + }) + .attr({contenteditable: true}) + .text(initialText) + .call(alignHTMLWith(context, container, options)) + .on('blur', function() { + gd._editing = false; + context.text(this.textContent) + .style({opacity: 1}); + var svgClass = d3.select(this).attr('class'), + mathjaxClass; + if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; + else mathjaxClass = '[class*=-math-group]'; + if(mathjaxClass) { + d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0}); + } + var text = this.textContent; + d3.select(this).transition().duration(0).remove(); + d3.select(document).on('mouseup', null); + dispatch.edit.call(context, text); + }) + .on('focus', function() { + var editDiv = this; + gd._editing = true; + d3.select(document).on('mouseup', function() { + if(d3.event.target === editDiv) return false; + if(document.activeElement === div.node()) div.node().blur(); + }); + }) + .on('keyup', function() { + if(d3.event.which === 27) { + gd._editing = false; + context.style({opacity: 1}); + d3.select(this) + .style({opacity: 0}) + .on('blur', function() { return false; }) + .transition().remove(); + dispatch.cancel.call(context, this.textContent); + } + else { + dispatch.input.call(context, this.textContent); + d3.select(this).call(alignHTMLWith(context, container, options)); + } + }) + .on('keydown', function() { + if(d3.event.which === 13) this.blur(); + }) + .call(selectElementContents); + } + + if(options.immediate) handleClick(); + else handlerElement.on('click', handleClick); + + return d3.rebind(context, dispatch, 'on'); +}; + +},{"../constants/alignment":668,"../constants/xmlns_namespaces":674,"../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],721:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var timerCache = {}; + +/** + * Throttle a callback. `callback` executes synchronously only if + * more than `minInterval` milliseconds have already elapsed since the latest + * call (if any). Otherwise we wait until `minInterval` is over and execute the + * last callback received while waiting. + * So the first and last events in a train are always executed (eventually) + * but some of the events in the middle can be dropped. + * + * @param {string} id: an identifier to mark events to throttle together + * @param {number} minInterval: minimum time, in milliseconds, between + * invocations of `callback` + * @param {function} callback: the function to throttle. `callback` itself + * should be a purely synchronous function. + */ +exports.throttle = function throttle(id, minInterval, callback) { + var cache = timerCache[id]; + var now = Date.now(); + + if(!cache) { + /* + * Throw out old items before making a new one, to prevent the cache + * getting overgrown, for example from old plots that have been replaced. + * 1 minute age is arbitrary. + */ + for(var idi in timerCache) { + if(timerCache[idi].ts < now - 60000) { + delete timerCache[idi]; + } + } + cache = timerCache[id] = {ts: 0, timer: null}; + } + + _clearTimeout(cache); + + function exec() { + callback(); + cache.ts = Date.now(); + if(cache.onDone) { + cache.onDone(); + cache.onDone = null; + } + } + + if(now > cache.ts + minInterval) { + exec(); + return; + } + + cache.timer = setTimeout(function() { + exec(); + cache.timer = null; + }, minInterval); +}; + +exports.done = function(id) { + var cache = timerCache[id]; + if(!cache || !cache.timer) return Promise.resolve(); + + return new Promise(function(resolve) { + var previousOnDone = cache.onDone; + cache.onDone = function onDone() { + if(previousOnDone) previousOnDone(); + resolve(); + cache.onDone = null; + }; + }); +}; + +/** + * Clear the throttle cache for one or all timers + * @param {optional string} id: + * if provided, clear just this timer + * if omitted, clear all timers (mainly useful for testing) + */ +exports.clear = function(id) { + if(id) { + _clearTimeout(timerCache[id]); + delete timerCache[id]; + } + else { + for(var idi in timerCache) exports.clear(idi); + } +}; + +function _clearTimeout(cache) { + if(cache && cache.timer !== null) { + clearTimeout(cache.timer); + cache.timer = null; + } +} + +},{}],722:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +/** + * convert a linear value into a logged value, folding negative numbers into + * the given range + */ +module.exports = function toLogRange(val, range) { + if(val > 0) return Math.log(val) / Math.LN10; + + // move a negative value reference to a log axis - just put the + // result at the lowest range value on the plot (or if the range also went negative, + // one millionth of the top of the range) + var newVal = Math.log(Math.min(range[0], range[1])) / Math.LN10; + if(!isNumeric(newVal)) newVal = Math.log(Math.max(range[0], range[1])) / Math.LN10 - 6; + return newVal; +}; + +},{"fast-isnumeric":214}],723:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var topojsonUtils = module.exports = {}; + +var locationmodeToLayer = _dereq_('../plots/geo/constants').locationmodeToLayer; +var topojsonFeature = _dereq_('topojson-client').feature; + + +topojsonUtils.getTopojsonName = function(geoLayout) { + return [ + geoLayout.scope.replace(/ /g, '-'), '_', + geoLayout.resolution.toString(), 'm' + ].join(''); +}; + +topojsonUtils.getTopojsonPath = function(topojsonURL, topojsonName) { + return topojsonURL + topojsonName + '.json'; +}; + +topojsonUtils.getTopojsonFeatures = function(trace, topojson) { + var layer = locationmodeToLayer[trace.locationmode], + obj = topojson.objects[layer]; + + return topojsonFeature(topojson, obj).features; +}; + +},{"../plots/geo/constants":773,"topojson-client":517}],724:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'locale', + name: 'en-US', + dictionary: { + 'Click to enter Colorscale title': 'Click to enter Colorscale title' + }, + format: { + date: '%m/%d/%Y' + } +}; + +},{}],725:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'locale', + name: 'en', + dictionary: { + 'Click to enter Colorscale title': 'Click to enter Colourscale title' + }, + format: { + days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + months: [ + 'January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December' + ], + shortMonths: [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ], + periods: ['AM', 'PM'], + dateTime: '%a %b %e %X %Y', + date: '%d/%m/%Y', + time: '%H:%M:%S', + decimal: '.', + thousands: ',', + grouping: [3], + currency: ['$', ''], + year: '%Y', + month: '%b %Y', + dayMonth: '%b %-d', + dayMonthYear: '%b %-d, %Y' + } +}; + +},{}],726:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../registry'); + +/* + * containerArrayMatch: does this attribute string point into a + * layout container array? + * + * @param {String} astr: an attribute string, like *annotations[2].text* + * + * @returns {Object | false} Returns false if `astr` doesn't match a container + * array. If it does, returns: + * {array: {String}, index: {Number}, property: {String}} + * ie the attribute string for the array, the index within the array (or '' + * if the whole array) and the property within that (or '' if the whole array + * or the whole object) + */ +module.exports = function containerArrayMatch(astr) { + var rootContainers = Registry.layoutArrayContainers, + regexpContainers = Registry.layoutArrayRegexes, + rootPart = astr.split('[')[0], + arrayStr, + match; + + // look for regexp matches first, because they may be nested inside root matches + // eg updatemenus[i].buttons is nested inside updatemenus + for(var i = 0; i < regexpContainers.length; i++) { + match = astr.match(regexpContainers[i]); + if(match && match.index === 0) { + arrayStr = match[0]; + break; + } + } + + // now look for root matches + if(!arrayStr) arrayStr = rootContainers[rootContainers.indexOf(rootPart)]; + + if(!arrayStr) return false; + + var tail = astr.substr(arrayStr.length); + if(!tail) return {array: arrayStr, index: '', property: ''}; + + match = tail.match(/^\[(0|[1-9][0-9]*)\](\.(.+))?$/); + if(!match) return false; + + return {array: arrayStr, index: Number(match[1]), property: match[3] || ''}; +}; + +},{"../registry":827}],727:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var extendFlat = Lib.extendFlat; +var isPlainObject = Lib.isPlainObject; + +var traceOpts = { + valType: 'flaglist', + extras: ['none'], + flags: ['calc', 'clearAxisTypes', 'plot', 'style', 'markerSize', 'colorbars'], + +}; + +var layoutOpts = { + valType: 'flaglist', + extras: ['none'], + flags: [ + 'calc', 'plot', 'legend', 'ticks', 'axrange', + 'layoutstyle', 'modebar', 'camera', 'arraydraw' + ], + +}; + +// flags for inside restyle/relayout include a few extras +// that shouldn't be used in attributes, to deal with certain +// combinations and conditionals efficiently +var traceEditTypeFlags = traceOpts.flags.slice() + .concat(['fullReplot']); + +var layoutEditTypeFlags = layoutOpts.flags.slice() + .concat('layoutReplot'); + +module.exports = { + traces: traceOpts, + layout: layoutOpts, + /* + * default (all false) edit flags for restyle (traces) + * creates a new object each call, so the caller can mutate freely + */ + traceFlags: function() { return falseObj(traceEditTypeFlags); }, + + /* + * default (all false) edit flags for relayout + * creates a new object each call, so the caller can mutate freely + */ + layoutFlags: function() { return falseObj(layoutEditTypeFlags); }, + + /* + * update `flags` with the `editType` values found in `attr` + */ + update: function(flags, attr) { + var editType = attr.editType; + if(editType && editType !== 'none') { + var editTypeParts = editType.split('+'); + for(var i = 0; i < editTypeParts.length; i++) { + flags[editTypeParts[i]] = true; + } + } + }, + + overrideAll: overrideAll +}; + +function falseObj(keys) { + var out = {}; + for(var i = 0; i < keys.length; i++) out[keys[i]] = false; + return out; +} + +/** + * For attributes that are largely copied from elsewhere into a plot type that doesn't + * support partial redraws - overrides the editType field of all attributes in the object + * + * @param {object} attrs: the attributes to override. Will not be mutated. + * @param {string} editTypeOverride: the new editType to use + * @param {'nested'|'from-root'} overrideContainers: + * - 'nested' will override editType for nested containers but not the root. + * - 'from-root' will also override editType of the root container. + * Containers below the absolute top level (trace or layout root) DO need an + * editType even if they are not `valObject`s themselves (eg `scatter.marker`) + * to handle the case where you edit the whole container. + * + * @return {object} a new attributes object with `editType` modified as directed + */ +function overrideAll(attrs, editTypeOverride, overrideContainers) { + var out = extendFlat({}, attrs); + for(var key in out) { + var attr = out[key]; + if(isPlainObject(attr)) { + out[key] = overrideOne(attr, editTypeOverride, overrideContainers, key); + } + } + if(overrideContainers === 'from-root') out.editType = editTypeOverride; + + return out; +} + +function overrideOne(attr, editTypeOverride, overrideContainers, key) { + if(attr.valType) { + var out = extendFlat({}, attr); + out.editType = editTypeOverride; + + if(Array.isArray(attr.items)) { + out.items = new Array(attr.items.length); + for(var i = 0; i < attr.items.length; i++) { + out.items[i] = overrideOne(attr.items[i], editTypeOverride, 'from-root'); + } + } + return out; + } + else { + // don't provide an editType for the _deprecated container + return overrideAll(attr, editTypeOverride, + (key.charAt(0) === '_') ? 'nested' : 'from-root'); + } +} + +},{"../lib":696}],728:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var m4FromQuat = _dereq_('gl-mat4/fromQuat'); + +var Registry = _dereq_('../registry'); +var Lib = _dereq_('../lib'); +var Plots = _dereq_('../plots/plots'); +var AxisIds = _dereq_('../plots/cartesian/axis_ids'); +var cleanId = AxisIds.cleanId; +var getFromTrace = AxisIds.getFromTrace; +var Color = _dereq_('../components/color'); + + +// clear the promise queue if one of them got rejected +exports.clearPromiseQueue = function(gd) { + if(Array.isArray(gd._promises) && gd._promises.length > 0) { + Lib.log('Clearing previous rejected promises from queue.'); + } + + gd._promises = []; +}; + +// make a few changes to the layout right away +// before it gets used for anything +// backward compatibility and cleanup of nonstandard options +exports.cleanLayout = function(layout) { + var i, j; + + if(!layout) layout = {}; + + // cannot have (x|y)axis1, numbering goes axis, axis2, axis3... + if(layout.xaxis1) { + if(!layout.xaxis) layout.xaxis = layout.xaxis1; + delete layout.xaxis1; + } + if(layout.yaxis1) { + if(!layout.yaxis) layout.yaxis = layout.yaxis1; + delete layout.yaxis1; + } + if(layout.scene1) { + if(!layout.scene) layout.scene = layout.scene1; + delete layout.scene1; + } + + var axisAttrRegex = (Plots.subplotsRegistry.cartesian || {}).attrRegex; + var sceneAttrRegex = (Plots.subplotsRegistry.gl3d || {}).attrRegex; + + var keys = Object.keys(layout); + for(i = 0; i < keys.length; i++) { + var key = keys[i]; + + // modifications to cartesian axes + if(axisAttrRegex && axisAttrRegex.test(key)) { + var ax = layout[key]; + if(ax.anchor && ax.anchor !== 'free') { + ax.anchor = cleanId(ax.anchor); + } + if(ax.overlaying) ax.overlaying = cleanId(ax.overlaying); + + // old method of axis type - isdate and islog (before category existed) + if(!ax.type) { + if(ax.isdate) ax.type = 'date'; + else if(ax.islog) ax.type = 'log'; + else if(ax.isdate === false && ax.islog === false) ax.type = 'linear'; + } + if(ax.autorange === 'withzero' || ax.autorange === 'tozero') { + ax.autorange = true; + ax.rangemode = 'tozero'; + } + delete ax.islog; + delete ax.isdate; + delete ax.categories; // replaced by _categories + + // prune empty domain arrays made before the new nestedProperty + if(emptyContainer(ax, 'domain')) delete ax.domain; + + // autotick -> tickmode + if(ax.autotick !== undefined) { + if(ax.tickmode === undefined) { + ax.tickmode = ax.autotick ? 'auto' : 'linear'; + } + delete ax.autotick; + } + } + + // modifications for 3D scenes + else if(sceneAttrRegex && sceneAttrRegex.test(key)) { + var scene = layout[key]; + + // clean old Camera coords + var cameraposition = scene.cameraposition; + + if(Array.isArray(cameraposition) && cameraposition[0].length === 4) { + var rotation = cameraposition[0], + center = cameraposition[1], + radius = cameraposition[2], + mat = m4FromQuat([], rotation), + eye = []; + + for(j = 0; j < 3; ++j) { + eye[j] = center[j] + radius * mat[2 + 4 * j]; + } + + scene.camera = { + eye: {x: eye[0], y: eye[1], z: eye[2]}, + center: {x: center[0], y: center[1], z: center[2]}, + up: {x: mat[1], y: mat[5], z: mat[9]} + }; + + delete scene.cameraposition; + } + } + } + + var annotationsLen = Array.isArray(layout.annotations) ? layout.annotations.length : 0; + for(i = 0; i < annotationsLen; i++) { + var ann = layout.annotations[i]; + + if(!Lib.isPlainObject(ann)) continue; + + if(ann.ref) { + if(ann.ref === 'paper') { + ann.xref = 'paper'; + ann.yref = 'paper'; + } + else if(ann.ref === 'data') { + ann.xref = 'x'; + ann.yref = 'y'; + } + delete ann.ref; + } + + cleanAxRef(ann, 'xref'); + cleanAxRef(ann, 'yref'); + } + + var shapesLen = Array.isArray(layout.shapes) ? layout.shapes.length : 0; + for(i = 0; i < shapesLen; i++) { + var shape = layout.shapes[i]; + + if(!Lib.isPlainObject(shape)) continue; + + cleanAxRef(shape, 'xref'); + cleanAxRef(shape, 'yref'); + } + + var legend = layout.legend; + if(legend) { + // check for old-style legend positioning (x or y is +/- 100) + if(legend.x > 3) { + legend.x = 1.02; + legend.xanchor = 'left'; + } + else if(legend.x < -2) { + legend.x = -0.02; + legend.xanchor = 'right'; + } + + if(legend.y > 3) { + legend.y = 1.02; + legend.yanchor = 'bottom'; + } + else if(legend.y < -2) { + legend.y = -0.02; + legend.yanchor = 'top'; + } + } + + /* + * Moved from rotate -> orbit for dragmode + */ + if(layout.dragmode === 'rotate') layout.dragmode = 'orbit'; + + // sanitize rgb(fractions) and rgba(fractions) that old tinycolor + // supported, but new tinycolor does not because they're not valid css + Color.clean(layout); + + return layout; +}; + +function cleanAxRef(container, attr) { + var valIn = container[attr], + axLetter = attr.charAt(0); + if(valIn && valIn !== 'paper') { + container[attr] = cleanId(valIn, axLetter); + } +} + +/* + * cleanData: Make a few changes to the data for backward compatibility + * before it gets used for anything. Modifies the data traces users provide. + * + * Important: if you're going to add something here that modifies a data array, + * update it in place so the new array === the old one. + */ +exports.cleanData = function(data) { + for(var tracei = 0; tracei < data.length; tracei++) { + var trace = data[tracei]; + var i; + + // use xbins to bin data in x, and ybins to bin data in y + if(trace.type === 'histogramy' && 'xbins' in trace && !('ybins' in trace)) { + trace.ybins = trace.xbins; + delete trace.xbins; + } + + // error_y.opacity is obsolete - merge into color + if(trace.error_y && 'opacity' in trace.error_y) { + var dc = Color.defaults, + yeColor = trace.error_y.color || + (Registry.traceIs(trace, 'bar') ? Color.defaultLine : dc[tracei % dc.length]); + trace.error_y.color = Color.addOpacity( + Color.rgb(yeColor), + Color.opacity(yeColor) * trace.error_y.opacity); + delete trace.error_y.opacity; + } + + // convert bardir to orientation, and put the data into + // the axes it's eventually going to be used with + if('bardir' in trace) { + if(trace.bardir === 'h' && (Registry.traceIs(trace, 'bar') || + trace.type.substr(0, 9) === 'histogram')) { + trace.orientation = 'h'; + exports.swapXYData(trace); + } + delete trace.bardir; + } + + // now we have only one 1D histogram type, and whether + // it uses x or y data depends on trace.orientation + if(trace.type === 'histogramy') exports.swapXYData(trace); + if(trace.type === 'histogramx' || trace.type === 'histogramy') { + trace.type = 'histogram'; + } + + // scl->scale, reversescl->reversescale + if('scl' in trace) { + trace.colorscale = trace.scl; + delete trace.scl; + } + if('reversescl' in trace) { + trace.reversescale = trace.reversescl; + delete trace.reversescl; + } + + // axis ids x1 -> x, y1-> y + if(trace.xaxis) trace.xaxis = cleanId(trace.xaxis, 'x'); + if(trace.yaxis) trace.yaxis = cleanId(trace.yaxis, 'y'); + + // scene ids scene1 -> scene + if(Registry.traceIs(trace, 'gl3d') && trace.scene) { + trace.scene = Plots.subplotsRegistry.gl3d.cleanId(trace.scene); + } + + if(!Registry.traceIs(trace, 'pie') && !Registry.traceIs(trace, 'bar')) { + if(Array.isArray(trace.textposition)) { + for(i = 0; i < trace.textposition.length; i++) { + trace.textposition[i] = cleanTextPosition(trace.textposition[i]); + } + } + else if(trace.textposition) { + trace.textposition = cleanTextPosition(trace.textposition); + } + } + + // fix typo in colorscale definition + var _module = Registry.getModule(trace); + if(_module && _module.colorbar) { + var containerName = _module.colorbar.container; + var container = containerName ? trace[containerName] : trace; + if(container && container.colorscale) { + if(container.colorscale === 'YIGnBu') container.colorscale = 'YlGnBu'; + if(container.colorscale === 'YIOrRd') container.colorscale = 'YlOrRd'; + } + } + + // fix typo in surface 'highlight*' definitions + if(trace.type === 'surface' && Lib.isPlainObject(trace.contours)) { + var dims = ['x', 'y', 'z']; + + for(i = 0; i < dims.length; i++) { + var opts = trace.contours[dims[i]]; + + if(!Lib.isPlainObject(opts)) continue; + + if(opts.highlightColor) { + opts.highlightcolor = opts.highlightColor; + delete opts.highlightColor; + } + + if(opts.highlightWidth) { + opts.highlightwidth = opts.highlightWidth; + delete opts.highlightWidth; + } + } + } + + // fixes from converting finance from transforms to real trace types + if(trace.type === 'candlestick' || trace.type === 'ohlc') { + var increasingShowlegend = (trace.increasing || {}).showlegend !== false; + var decreasingShowlegend = (trace.decreasing || {}).showlegend !== false; + var increasingName = cleanFinanceDir(trace.increasing); + var decreasingName = cleanFinanceDir(trace.decreasing); + + // now figure out something smart to do with the separate direction + // names we removed + if((increasingName !== false) && (decreasingName !== false)) { + // both sub-names existed: base name previously had no effect + // so ignore it and try to find a shared part of the sub-names + + var newName = commonPrefix( + increasingName, decreasingName, + increasingShowlegend, decreasingShowlegend + ); + // if no common part, leave whatever name was (or wasn't) there + if(newName) trace.name = newName; + } + else if((increasingName || decreasingName) && !trace.name) { + // one sub-name existed but not the base name - just use the sub-name + trace.name = increasingName || decreasingName; + } + } + + // transforms backward compatibility fixes + if(Array.isArray(trace.transforms)) { + var transforms = trace.transforms; + + for(i = 0; i < transforms.length; i++) { + var transform = transforms[i]; + + if(!Lib.isPlainObject(transform)) continue; + + switch(transform.type) { + case 'filter': + if(transform.filtersrc) { + transform.target = transform.filtersrc; + delete transform.filtersrc; + } + + if(transform.calendar) { + if(!transform.valuecalendar) { + transform.valuecalendar = transform.calendar; + } + delete transform.calendar; + } + break; + + case 'groupby': + // Name has changed from `style` to `styles`, so use `style` but prefer `styles`: + transform.styles = transform.styles || transform.style; + + if(transform.styles && !Array.isArray(transform.styles)) { + var prevStyles = transform.styles; + var styleKeys = Object.keys(prevStyles); + + transform.styles = []; + for(var j = 0; j < styleKeys.length; j++) { + transform.styles.push({ + target: styleKeys[j], + value: prevStyles[styleKeys[j]] + }); + } + } + break; + } + } + } + + // prune empty containers made before the new nestedProperty + if(emptyContainer(trace, 'line')) delete trace.line; + if('marker' in trace) { + if(emptyContainer(trace.marker, 'line')) delete trace.marker.line; + if(emptyContainer(trace, 'marker')) delete trace.marker; + } + + // sanitize rgb(fractions) and rgba(fractions) that old tinycolor + // supported, but new tinycolor does not because they're not valid css + Color.clean(trace); + + // remove obsolete autobin(x|y) attributes, but only if true + // if false, this needs to happen in Histogram.calc because it + // can be a one-time autobin so we need to know the results before + // we can push them back into the trace. + if(trace.autobinx) { + delete trace.autobinx; + delete trace.xbins; + } + if(trace.autobiny) { + delete trace.autobiny; + delete trace.ybins; + } + } +}; + +function cleanFinanceDir(dirContainer) { + if(!Lib.isPlainObject(dirContainer)) return false; + + var dirName = dirContainer.name; + + delete dirContainer.name; + delete dirContainer.showlegend; + + return (typeof dirName === 'string' || typeof dirName === 'number') && String(dirName); +} + +function commonPrefix(name1, name2, show1, show2) { + // if only one is shown in the legend, use that + if(show1 && !show2) return name1; + if(show2 && !show1) return name2; + + // if both or neither are in the legend, check if one is blank (or whitespace) + // and use the other one + // note that hover labels can still use the name even if the legend doesn't + if(!name1.trim()) return name2; + if(!name2.trim()) return name1; + + var minLen = Math.min(name1.length, name2.length); + var i; + for(i = 0; i < minLen; i++) { + if(name1.charAt(i) !== name2.charAt(i)) break; + } + + var out = name1.substr(0, i); + return out.trim(); +} + +// textposition - support partial attributes (ie just 'top') +// and incorrect use of middle / center etc. +function cleanTextPosition(textposition) { + var posY = 'middle', + posX = 'center'; + if(textposition.indexOf('top') !== -1) posY = 'top'; + else if(textposition.indexOf('bottom') !== -1) posY = 'bottom'; + + if(textposition.indexOf('left') !== -1) posX = 'left'; + else if(textposition.indexOf('right') !== -1) posX = 'right'; + + return posY + ' ' + posX; +} + +function emptyContainer(outer, innerStr) { + return (innerStr in outer) && + (typeof outer[innerStr] === 'object') && + (Object.keys(outer[innerStr]).length === 0); +} + + +// swap all the data and data attributes associated with x and y +exports.swapXYData = function(trace) { + var i; + Lib.swapAttrs(trace, ['?', '?0', 'd?', '?bins', 'nbins?', 'autobin?', '?src', 'error_?']); + if(Array.isArray(trace.z) && Array.isArray(trace.z[0])) { + if(trace.transpose) delete trace.transpose; + else trace.transpose = true; + } + if(trace.error_x && trace.error_y) { + var errorY = trace.error_y, + copyYstyle = ('copy_ystyle' in errorY) ? errorY.copy_ystyle : + !(errorY.color || errorY.thickness || errorY.width); + Lib.swapAttrs(trace, ['error_?.copy_ystyle']); + if(copyYstyle) { + Lib.swapAttrs(trace, ['error_?.color', 'error_?.thickness', 'error_?.width']); + } + } + if(typeof trace.hoverinfo === 'string') { + var hoverInfoParts = trace.hoverinfo.split('+'); + for(i = 0; i < hoverInfoParts.length; i++) { + if(hoverInfoParts[i] === 'x') hoverInfoParts[i] = 'y'; + else if(hoverInfoParts[i] === 'y') hoverInfoParts[i] = 'x'; + } + trace.hoverinfo = hoverInfoParts.join('+'); + } +}; + +// coerce traceIndices input to array of trace indices +exports.coerceTraceIndices = function(gd, traceIndices) { + if(isNumeric(traceIndices)) { + return [traceIndices]; + } + else if(!Array.isArray(traceIndices) || !traceIndices.length) { + return gd.data.map(function(_, i) { return i; }); + } + else if(Array.isArray(traceIndices)) { + var traceIndicesOut = []; + for(var i = 0; i < traceIndices.length; i++) { + if(Lib.isIndex(traceIndices[i], gd.data.length)) { + traceIndicesOut.push(traceIndices[i]); + } else { + Lib.warn('trace index (', traceIndices[i], ') is not a number or is out of bounds'); + } + } + return traceIndicesOut; + } + + return traceIndices; +}; + +/** + * Manages logic around array container item creation / deletion / update + * that nested property alone can't handle. + * + * @param {Object} np + * nested property of update attribute string about trace or layout object + * @param {*} newVal + * update value passed to restyle / relayout / update + * @param {Object} undoit + * undo hash (N.B. undoit may be mutated here). + * + */ +exports.manageArrayContainers = function(np, newVal, undoit) { + var obj = np.obj, + parts = np.parts, + pLength = parts.length, + pLast = parts[pLength - 1]; + + var pLastIsNumber = isNumeric(pLast); + + // delete item + if(pLastIsNumber && newVal === null) { + + // Clear item in array container when new value is null + var contPath = parts.slice(0, pLength - 1).join('.'), + cont = Lib.nestedProperty(obj, contPath).get(); + cont.splice(pLast, 1); + + // Note that nested property clears null / undefined at end of + // array container, but not within them. + } + // create item + else if(pLastIsNumber && np.get() === undefined) { + + // When adding a new item, make sure undo command will remove it + if(np.get() === undefined) undoit[np.astr] = null; + + np.set(newVal); + } + // update item + else { + + // If the last part of attribute string isn't a number, + // np.set is all we need. + np.set(newVal); + } +}; + +/* + * Match the part to strip off to turn an attribute into its parent + * really it should be either '.some_characters' or '[number]' + * but we're a little more permissive here and match either + * '.not_brackets_or_dot' or '[not_brackets_or_dot]' + */ +var ATTR_TAIL_RE = /(\.[^\[\]\.]+|\[[^\[\]\.]+\])$/; + +function getParent(attr) { + var tail = attr.search(ATTR_TAIL_RE); + if(tail > 0) return attr.substr(0, tail); +} + +/* + * hasParent: does an attribute object contain a parent of the given attribute? + * for example, given 'images[2].x' do we also have 'images' or 'images[2]'? + * + * @param {Object} aobj + * update object, whose keys are attribute strings and values are their new settings + * @param {string} attr + * the attribute string to test against + * @returns {Boolean} + * is a parent of attr present in aobj? + */ +exports.hasParent = function(aobj, attr) { + var attrParent = getParent(attr); + while(attrParent) { + if(attrParent in aobj) return true; + attrParent = getParent(attrParent); + } + return false; +}; + +/** + * Empty out types for all axes containing these traces so we auto-set them again + * + * @param {object} gd + * @param {[integer]} traces: trace indices to search for axes to clear the types of + * @param {object} layoutUpdate: any update being done concurrently to the layout, + * which may supercede clearing the axis types + */ +var axLetters = ['x', 'y', 'z']; +exports.clearAxisTypes = function(gd, traces, layoutUpdate) { + for(var i = 0; i < traces.length; i++) { + var trace = gd._fullData[i]; + for(var j = 0; j < 3; j++) { + var ax = getFromTrace(gd, trace, axLetters[j]); + + // do not clear log type - that's never an auto result so must have been intentional + if(ax && ax.type !== 'log') { + var axAttr = ax._name; + var sceneName = ax._id.substr(1); + if(sceneName.substr(0, 5) === 'scene') { + if(layoutUpdate[sceneName] !== undefined) continue; + axAttr = sceneName + '.' + axAttr; + } + var typeAttr = axAttr + '.type'; + + if(layoutUpdate[axAttr] === undefined && layoutUpdate[typeAttr] === undefined) { + Lib.nestedProperty(gd.layout, typeAttr).set(null); + } + } + } + } +}; + +},{"../components/color":570,"../lib":696,"../plots/cartesian/axis_ids":747,"../plots/plots":808,"../registry":827,"fast-isnumeric":214,"gl-mat4/fromQuat":251}],729:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var main = _dereq_('./plot_api'); + +exports.plot = main.plot; +exports.newPlot = main.newPlot; +exports.restyle = main.restyle; +exports.relayout = main.relayout; +exports.redraw = main.redraw; +exports.update = main.update; +exports.react = main.react; +exports.extendTraces = main.extendTraces; +exports.prependTraces = main.prependTraces; +exports.addTraces = main.addTraces; +exports.deleteTraces = main.deleteTraces; +exports.moveTraces = main.moveTraces; +exports.purge = main.purge; +exports.addFrames = main.addFrames; +exports.deleteFrames = main.deleteFrames; +exports.animate = main.animate; +exports.setPlotConfig = main.setPlotConfig; + +exports.toImage = _dereq_('./to_image'); +exports.validate = _dereq_('./validate'); +exports.downloadImage = _dereq_('../snapshot/download'); + +var templateApi = _dereq_('./template_api'); +exports.makeTemplate = templateApi.makeTemplate; +exports.validateTemplate = templateApi.validateTemplate; + +},{"../snapshot/download":829,"./plot_api":731,"./template_api":736,"./to_image":737,"./validate":738}],730:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var nestedProperty = _dereq_('../lib/nested_property'); +var isPlainObject = _dereq_('../lib/is_plain_object'); +var noop = _dereq_('../lib/noop'); +var Loggers = _dereq_('../lib/loggers'); +var sorterAsc = _dereq_('../lib/search').sorterAsc; +var Registry = _dereq_('../registry'); + + +exports.containerArrayMatch = _dereq_('./container_array_match'); + +var isAddVal = exports.isAddVal = function isAddVal(val) { + return val === 'add' || isPlainObject(val); +}; + +var isRemoveVal = exports.isRemoveVal = function isRemoveVal(val) { + return val === null || val === 'remove'; +}; + +/* + * applyContainerArrayChanges: for managing arrays of layout components in relayout + * handles them all with a consistent interface. + * + * Here are the supported actions -> relayout calls -> edits we get here + * (as prepared in _relayout): + * + * add an empty obj -> {'annotations[2]': 'add'} -> {2: {'': 'add'}} + * add a specific obj -> {'annotations[2]': {attrs}} -> {2: {'': {attrs}}} + * delete an obj -> {'annotations[2]': 'remove'} -> {2: {'': 'remove'}} + * -> {'annotations[2]': null} -> {2: {'': null}} + * delete the whole array -> {'annotations': 'remove'} -> {'': {'': 'remove'}} + * -> {'annotations': null} -> {'': {'': null}} + * edit an object -> {'annotations[2].text': 'boo'} -> {2: {'text': 'boo'}} + * + * You can combine many edits to different objects. Objects are added and edited + * in ascending order, then removed in descending order. + * For example, starting with [a, b, c], if you want to: + * - replace b with d: + * {'annotations[1]': d, 'annotations[2]': null} (b is item 2 after adding d) + * - add a new item d between a and b, and edit b: + * {'annotations[1]': d, 'annotations[2].x': newX} (b is item 2 after adding d) + * - delete b and edit c: + * {'annotations[1]': null, 'annotations[2].x': newX} (c is edited before b is removed) + * + * You CANNOT combine adding/deleting an item at index `i` with edits to the same index `i` + * You CANNOT combine replacing/deleting the whole array with anything else (for the same array). + * + * @param {HTMLDivElement} gd + * the DOM element of the graph container div + * @param {Lib.nestedProperty} componentType: the array we are editing + * @param {Object} edits + * the changes to make; keys are indices to edit, values are themselves objects: + * {attr: newValue} of changes to make to that index (with add/remove behavior + * in special values of the empty attr) + * @param {Object} flags + * the flags for which actions we're going to perform to display these (and + * any other) changes. If we're already `recalc`ing, we don't need to redraw + * individual items + * + * @returns {bool} `true` if it managed to complete drawing of the changes + * `false` would mean the parent should replot. + */ +exports.applyContainerArrayChanges = function applyContainerArrayChanges(gd, np, edits, flags) { + var componentType = np.astr, + supplyComponentDefaults = Registry.getComponentMethod(componentType, 'supplyLayoutDefaults'), + draw = Registry.getComponentMethod(componentType, 'draw'), + drawOne = Registry.getComponentMethod(componentType, 'drawOne'), + replotLater = flags.replot || flags.recalc || (supplyComponentDefaults === noop) || + (draw === noop), + layout = gd.layout, + fullLayout = gd._fullLayout; + + if(edits['']) { + if(Object.keys(edits).length > 1) { + Loggers.warn('Full array edits are incompatible with other edits', + componentType); + } + + var fullVal = edits['']['']; + + if(isRemoveVal(fullVal)) np.set(null); + else if(Array.isArray(fullVal)) np.set(fullVal); + else { + Loggers.warn('Unrecognized full array edit value', componentType, fullVal); + return true; + } + + if(replotLater) return false; + + supplyComponentDefaults(layout, fullLayout); + draw(gd); + return true; + } + + var componentNums = Object.keys(edits).map(Number).sort(sorterAsc), + componentArrayIn = np.get(), + componentArray = componentArrayIn || [], + // componentArrayFull is used just to keep splices in line between + // full and input arrays, so private keys can be copied over after + // redoing supplyDefaults + // TODO: this assumes componentArray is in gd.layout - which will not be + // true after we extend this to restyle + componentArrayFull = nestedProperty(fullLayout, componentType).get(); + + var deletes = [], + firstIndexChange = -1, + maxIndex = componentArray.length, + i, + j, + componentNum, + objEdits, + objKeys, + objVal, + adding; + + // first make the add and edit changes + for(i = 0; i < componentNums.length; i++) { + componentNum = componentNums[i]; + objEdits = edits[componentNum]; + objKeys = Object.keys(objEdits); + objVal = objEdits[''], + adding = isAddVal(objVal); + + if(componentNum < 0 || componentNum > componentArray.length - (adding ? 0 : 1)) { + Loggers.warn('index out of range', componentType, componentNum); + continue; + } + + if(objVal !== undefined) { + if(objKeys.length > 1) { + Loggers.warn( + 'Insertion & removal are incompatible with edits to the same index.', + componentType, componentNum); + } + + if(isRemoveVal(objVal)) { + deletes.push(componentNum); + } + else if(adding) { + if(objVal === 'add') objVal = {}; + componentArray.splice(componentNum, 0, objVal); + if(componentArrayFull) componentArrayFull.splice(componentNum, 0, {}); + } + else { + Loggers.warn('Unrecognized full object edit value', + componentType, componentNum, objVal); + } + + if(firstIndexChange === -1) firstIndexChange = componentNum; + } + else { + for(j = 0; j < objKeys.length; j++) { + nestedProperty(componentArray[componentNum], objKeys[j]).set(objEdits[objKeys[j]]); + } + } + } + + // now do deletes + for(i = deletes.length - 1; i >= 0; i--) { + componentArray.splice(deletes[i], 1); + // TODO: this drops private keys that had been stored in componentArrayFull + // does this have any ill effects? + if(componentArrayFull) componentArrayFull.splice(deletes[i], 1); + } + + if(!componentArray.length) np.set(null); + else if(!componentArrayIn) np.set(componentArray); + + if(replotLater) return false; + + supplyComponentDefaults(layout, fullLayout); + + // finally draw all the components we need to + // if we added or removed any, redraw all after it + if(drawOne !== noop) { + var indicesToDraw; + if(firstIndexChange === -1) { + // there's no re-indexing to do, so only redraw components that changed + indicesToDraw = componentNums; + } + else { + // in case the component array was shortened, we still need do call + // drawOne on the latter items so they get properly removed + maxIndex = Math.max(componentArray.length, maxIndex); + indicesToDraw = []; + for(i = 0; i < componentNums.length; i++) { + componentNum = componentNums[i]; + if(componentNum >= firstIndexChange) break; + indicesToDraw.push(componentNum); + } + for(i = firstIndexChange; i < maxIndex; i++) { + indicesToDraw.push(i); + } + } + for(i = 0; i < indicesToDraw.length; i++) { + drawOne(gd, indicesToDraw[i]); + } + } + else draw(gd); + + return true; +}; + +},{"../lib/is_plain_object":697,"../lib/loggers":700,"../lib/nested_property":704,"../lib/noop":705,"../lib/search":715,"../registry":827,"./container_array_match":726}],731:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); +var hasHover = _dereq_('has-hover'); + +var Lib = _dereq_('../lib'); +var Events = _dereq_('../lib/events'); +var Queue = _dereq_('../lib/queue'); + +var Registry = _dereq_('../registry'); +var PlotSchema = _dereq_('./plot_schema'); +var Plots = _dereq_('../plots/plots'); +var Polar = _dereq_('../plots/polar/legacy'); + +var Axes = _dereq_('../plots/cartesian/axes'); +var Drawing = _dereq_('../components/drawing'); +var Color = _dereq_('../components/color'); +var connectColorbar = _dereq_('../components/colorbar/connect'); +var initInteractions = _dereq_('../plots/cartesian/graph_interact').initInteractions; +var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); +var svgTextUtils = _dereq_('../lib/svg_text_utils'); + +var defaultConfig = _dereq_('./plot_config'); +var manageArrays = _dereq_('./manage_arrays'); +var helpers = _dereq_('./helpers'); +var subroutines = _dereq_('./subroutines'); +var editTypes = _dereq_('./edit_types'); + +var AX_NAME_PATTERN = _dereq_('../plots/cartesian/constants').AX_NAME_PATTERN; + +var numericNameWarningCount = 0; +var numericNameWarningCountLimit = 5; + +/** + * Main plot-creation function + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * @param {array of objects} data + * array of traces, containing the data and display information for each trace + * @param {object} layout + * object describing the overall display of the plot, + * all the stuff that doesn't pertain to any individual trace + * @param {object} config + * configuration options (see ./plot_config.js for more info) + * + * OR + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * @param {object} figure + * object containing `data`, `layout`, `config`, and `frames` members + * + */ +exports.plot = function(gd, data, layout, config) { + var frames; + + gd = Lib.getGraphDiv(gd); + + // Events.init is idempotent and bails early if gd has already been init'd + Events.init(gd); + + if(Lib.isPlainObject(data)) { + var obj = data; + data = obj.data; + layout = obj.layout; + config = obj.config; + frames = obj.frames; + } + + var okToPlot = Events.triggerHandler(gd, 'plotly_beforeplot', [data, layout, config]); + if(okToPlot === false) return Promise.reject(); + + // if there's no data or layout, and this isn't yet a plotly plot + // container, log a warning to help plotly.js users debug + if(!data && !layout && !Lib.isPlotDiv(gd)) { + Lib.warn('Calling Plotly.plot as if redrawing ' + + 'but this container doesn\'t yet have a plot.', gd); + } + + function addFrames() { + if(frames) { + return exports.addFrames(gd, frames); + } + } + + // transfer configuration options to gd until we move over to + // a more OO like model + setPlotContext(gd, config); + + if(!layout) layout = {}; + + // hook class for plots main container (in case of plotly.js + // this won't be #embedded-graph or .js-tab-contents) + d3.select(gd).classed('js-plotly-plot', true); + + // off-screen getBoundingClientRect testing space, + // in #js-plotly-tester (and stored as Drawing.tester) + // so we can share cached text across tabs + Drawing.makeTester(); + + // clear stashed base url + delete Drawing.baseUrl; + + // collect promises for any async actions during plotting + // any part of the plotting code can push to gd._promises, then + // before we move to the next step, we check that they're all + // complete, and empty out the promise list again. + if(!Array.isArray(gd._promises)) gd._promises = []; + + var graphWasEmpty = ((gd.data || []).length === 0 && Array.isArray(data)); + + // if there is already data on the graph, append the new data + // if you only want to redraw, pass a non-array for data + if(Array.isArray(data)) { + helpers.cleanData(data); + + if(graphWasEmpty) gd.data = data; + else gd.data.push.apply(gd.data, data); + + // for routines outside graph_obj that want a clean tab + // (rather than appending to an existing one) gd.empty + // is used to determine whether to make a new tab + gd.empty = false; + } + + if(!gd.layout || graphWasEmpty) gd.layout = helpers.cleanLayout(layout); + + // if the user is trying to drag the axes, allow new data and layout + // to come in but don't allow a replot. + if(gd._dragging && !gd._transitioning) { + // signal to drag handler that after everything else is done + // we need to replot, because something has changed + gd._replotPending = true; + return Promise.reject(); + } else { + // we're going ahead with a replot now + gd._replotPending = false; + } + + Plots.supplyDefaults(gd); + + var fullLayout = gd._fullLayout; + var hasCartesian = fullLayout._has('cartesian'); + + // Legacy polar plots + if(!fullLayout._has('polar') && data && data[0] && data[0].r) { + Lib.log('Legacy polar charts are deprecated!'); + return plotPolar(gd, data, layout); + } + + // so we don't try to re-call Plotly.plot from inside + // legend and colorbar, if margins changed + fullLayout._replotting = true; + + // make or remake the framework if we need to + if(graphWasEmpty) makePlotFramework(gd); + + // polar need a different framework + if(gd.framework !== makePlotFramework) { + gd.framework = makePlotFramework; + makePlotFramework(gd); + } + + // clear gradient defs on each .plot call, because we know we'll loop through all traces + Drawing.initGradients(gd); + + // save initial show spikes once per graph + if(graphWasEmpty) Axes.saveShowSpikeInitial(gd); + + // prepare the data and find the autorange + + // generate calcdata, if we need to + // to force redoing calcdata, just delete it before calling Plotly.plot + var recalc = !gd.calcdata || gd.calcdata.length !== (gd._fullData || []).length; + if(recalc) Plots.doCalcdata(gd); + + // in case it has changed, attach fullData traces to calcdata + for(var i = 0; i < gd.calcdata.length; i++) { + gd.calcdata[i][0].trace = gd._fullData[i]; + } + + // make the figure responsive + if(gd._context.responsive) { + if(!gd._responsiveChartHandler) { + // Keep a reference to the resize handler to purge it down the road + gd._responsiveChartHandler = function() {Plots.resize(gd);}; + + // Listen to window resize + window.addEventListener('resize', gd._responsiveChartHandler); + } + } else { + Lib.clearResponsive(gd); + } + + /* + * start async-friendly code - now we're actually drawing things + */ + + var oldmargins = JSON.stringify(fullLayout._size); + + // draw framework first so that margin-pushing + // components can position themselves correctly + var drawFrameworkCalls = 0; + function drawFramework() { + var basePlotModules = fullLayout._basePlotModules; + + for(var i = 0; i < basePlotModules.length; i++) { + if(basePlotModules[i].drawFramework) { + basePlotModules[i].drawFramework(gd); + } + } + + if(!fullLayout._glcanvas && fullLayout._has('gl')) { + fullLayout._glcanvas = fullLayout._glcontainer.selectAll('.gl-canvas').data([{ + key: 'contextLayer', + context: true, + pick: false + }, { + key: 'focusLayer', + context: false, + pick: false + }, { + key: 'pickLayer', + context: false, + pick: true + }], function(d) { return d.key; }); + + fullLayout._glcanvas.enter().append('canvas') + .attr('class', function(d) { + return 'gl-canvas gl-canvas-' + d.key.replace('Layer', ''); + }) + .style({ + 'position': 'absolute', + 'top': 0, + 'left': 0, + 'width': '100%', + 'height': '100%', + 'overflow': 'visible', + 'pointer-events': 'none' + }); + } + + if(fullLayout._glcanvas) { + fullLayout._glcanvas + .attr('width', fullLayout.width) + .attr('height', fullLayout.height); + + var regl = fullLayout._glcanvas.data()[0].regl; + if(regl) { + // Unfortunately, this can happen when relayouting to large + // width/height on some browsers. + if(Math.floor(fullLayout.width) !== regl._gl.drawingBufferWidth || + Math.floor(fullLayout.height) !== regl._gl.drawingBufferHeight + ) { + var msg = 'WebGL context buffer and canvas dimensions do not match due to browser/WebGL bug.'; + if(drawFrameworkCalls) { + Lib.error(msg); + } else { + Lib.log(msg + ' Clearing graph and plotting again.'); + Plots.cleanPlot([], {}, gd._fullData, fullLayout); + Plots.supplyDefaults(gd); + fullLayout = gd._fullLayout; + Plots.doCalcdata(gd); + drawFrameworkCalls++; + return drawFramework(); + } + } + } + } + + return Plots.previousPromises(gd); + } + + // draw anything that can affect margins. + function marginPushers() { + var calcdata = gd.calcdata; + var i, cd, trace; + + // First reset the list of things that are allowed to change the margins + // So any deleted traces or components will be wiped out of the + // automargin calculation. + // This means *every* margin pusher must be listed here, even if it + // doesn't actually try to push the margins until later. + Plots.clearAutoMarginIds(gd); + + subroutines.drawMarginPushers(gd); + Axes.allowAutoMargin(gd); + + for(i = 0; i < calcdata.length; i++) { + cd = calcdata[i]; + trace = cd[0].trace; + var colorbarOpts = trace._module.colorbar; + if(trace.visible !== true || !colorbarOpts) { + Plots.autoMargin(gd, 'cb' + trace.uid); + } + else connectColorbar(gd, cd, colorbarOpts); + } + + Plots.doAutoMargin(gd); + return Plots.previousPromises(gd); + } + + // in case the margins changed, draw margin pushers again + function marginPushersAgain() { + if(JSON.stringify(fullLayout._size) === oldmargins) return; + + return Lib.syncOrAsync([ + marginPushers, + subroutines.layoutStyles + ], gd); + } + + function positionAndAutorange() { + if(!recalc) { + doAutoRangeAndConstraints(); + return; + } + + // TODO: autosize extra for text markers and images + // see https://github.com/plotly/plotly.js/issues/1111 + return Lib.syncOrAsync([ + Registry.getComponentMethod('shapes', 'calcAutorange'), + Registry.getComponentMethod('annotations', 'calcAutorange'), + doAutoRangeAndConstraints, + Registry.getComponentMethod('rangeslider', 'calcAutorange') + ], gd); + } + + function doAutoRangeAndConstraints() { + if(gd._transitioning) return; + + subroutines.doAutoRangeAndConstraints(gd); + + // store initial ranges *after* enforcing constraints, otherwise + // we will never look like we're at the initial ranges + if(graphWasEmpty) Axes.saveRangeInitial(gd); + } + + // draw ticks, titles, and calculate axis scaling (._b, ._m) + function drawAxes() { + return Axes.doTicks(gd, graphWasEmpty ? '' : 'redraw'); + } + + var seq = [ + Plots.previousPromises, + addFrames, + drawFramework, + marginPushers, + marginPushersAgain + ]; + + if(hasCartesian) seq.push(positionAndAutorange); + + seq.push(subroutines.layoutStyles); + if(hasCartesian) seq.push(drawAxes); + + seq.push( + subroutines.drawData, + subroutines.finalDraw, + initInteractions, + Plots.addLinks, + Plots.rehover, + // TODO: doAutoMargin is only needed here for axis automargin, which + // happens outside of marginPushers where all the other automargins are + // calculated. Would be much better to separate margin calculations from + // component drawing - see https://github.com/plotly/plotly.js/issues/2704 + Plots.doAutoMargin, + Plots.previousPromises + ); + + // even if everything we did was synchronous, return a promise + // so that the caller doesn't care which route we took + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(); + + return plotDone.then(function() { + emitAfterPlot(gd); + return gd; + }); +}; + +function emitAfterPlot(gd) { + var fullLayout = gd._fullLayout; + + if(fullLayout._redrawFromAutoMarginCount) { + fullLayout._redrawFromAutoMarginCount--; + } else { + gd.emit('plotly_afterplot'); + } +} + +exports.setPlotConfig = function setPlotConfig(obj) { + return Lib.extendFlat(defaultConfig, obj); +}; + +function setBackground(gd, bgColor) { + try { + gd._fullLayout._paper.style('background', bgColor); + } catch(e) { + Lib.error(e); + } +} + +function opaqueSetBackground(gd, bgColor) { + var blend = Color.combine(bgColor, 'white'); + setBackground(gd, blend); +} + +function setPlotContext(gd, config) { + if(!gd._context) gd._context = Lib.extendDeep({}, defaultConfig); + var context = gd._context; + + var i, keys, key; + + if(config) { + keys = Object.keys(config); + for(i = 0; i < keys.length; i++) { + key = keys[i]; + if(key === 'editable' || key === 'edits') continue; + if(key in context) { + if(key === 'setBackground' && config[key] === 'opaque') { + context[key] = opaqueSetBackground; + } else { + context[key] = config[key]; + } + } + } + + // map plot3dPixelRatio to plotGlPixelRatio for backward compatibility + if(config.plot3dPixelRatio && !context.plotGlPixelRatio) { + context.plotGlPixelRatio = context.plot3dPixelRatio; + } + + // now deal with editable and edits - first editable overrides + // everything, then edits refines + var editable = config.editable; + if(editable !== undefined) { + // we're not going to *use* context.editable, we're only going to + // use context.edits... but keep it for the record + context.editable = editable; + + keys = Object.keys(context.edits); + for(i = 0; i < keys.length; i++) { + context.edits[keys[i]] = editable; + } + } + if(config.edits) { + keys = Object.keys(config.edits); + for(i = 0; i < keys.length; i++) { + key = keys[i]; + if(key in context.edits) { + context.edits[key] = config.edits[key]; + } + } + } + } + + // staticPlot forces a bunch of others: + if(context.staticPlot) { + context.editable = false; + context.edits = {}; + context.autosizable = false; + context.scrollZoom = false; + context.doubleClick = false; + context.showTips = false; + context.showLink = false; + context.displayModeBar = false; + } + + // make sure hover-only devices have mode bar visible + if(context.displayModeBar === 'hover' && !hasHover) { + context.displayModeBar = true; + } + + // default and fallback for setBackground + if(context.setBackground === 'transparent' || typeof context.setBackground !== 'function') { + context.setBackground = setBackground; + } + + // Check if gd has a specified widht/height to begin with + context._hasZeroHeight = context._hasZeroHeight || gd.clientHeight === 0; + context._hasZeroWidth = context._hasZeroWidth || gd.clientWidth === 0; +} + +function plotPolar(gd, data, layout) { + // build or reuse the container skeleton + var plotContainer = d3.select(gd).selectAll('.plot-container') + .data([0]); + plotContainer.enter() + .insert('div', ':first-child') + .classed('plot-container plotly', true); + var paperDiv = plotContainer.selectAll('.svg-container') + .data([0]); + paperDiv.enter().append('div') + .classed('svg-container', true) + .style('position', 'relative'); + + // empty it everytime for now + paperDiv.html(''); + + // fulfill gd requirements + if(data) gd.data = data; + if(layout) gd.layout = layout; + Polar.manager.fillLayout(gd); + + // resize canvas + paperDiv.style({ + width: gd._fullLayout.width + 'px', + height: gd._fullLayout.height + 'px' + }); + + // instantiate framework + gd.framework = Polar.manager.framework(gd); + + // plot + gd.framework({data: gd.data, layout: gd.layout}, paperDiv.node()); + + // set undo point + gd.framework.setUndoPoint(); + + // get the resulting svg for extending it + var polarPlotSVG = gd.framework.svg(); + + // editable title + var opacity = 1; + var txt = gd._fullLayout.title; + if(txt === '' || !txt) opacity = 0; + + var titleLayout = function() { + this.call(svgTextUtils.convertToTspans, gd); + // TODO: html/mathjax + // TODO: center title + }; + + var title = polarPlotSVG.select('.title-group text') + .call(titleLayout); + + if(gd._context.edits.titleText) { + var placeholderText = Lib._(gd, 'Click to enter Plot title'); + if(!txt || txt === placeholderText) { + opacity = 0.2; + // placeholder is not going through convertToTspans + // so needs explicit data-unformatted + title.attr({'data-unformatted': placeholderText}) + .text(placeholderText) + .style({opacity: opacity}) + .on('mouseover.opacity', function() { + d3.select(this).transition().duration(100) + .style('opacity', 1); + }) + .on('mouseout.opacity', function() { + d3.select(this).transition().duration(1000) + .style('opacity', 0); + }); + } + + var setContenteditable = function() { + this.call(svgTextUtils.makeEditable, {gd: gd}) + .on('edit', function(text) { + gd.framework({layout: {title: text}}); + this.text(text) + .call(titleLayout); + this.call(setContenteditable); + }) + .on('cancel', function() { + var txt = this.attr('data-unformatted'); + this.text(txt).call(titleLayout); + }); + }; + title.call(setContenteditable); + } + + gd._context.setBackground(gd, gd._fullLayout.paper_bgcolor); + Plots.addLinks(gd); + + return Promise.resolve(); +} + +// convenience function to force a full redraw, mostly for use by plotly.js +exports.redraw = function(gd) { + gd = Lib.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error('This element is not a Plotly plot: ' + gd); + } + + helpers.cleanData(gd.data); + helpers.cleanLayout(gd.layout); + + gd.calcdata = undefined; + return exports.plot(gd).then(function() { + gd.emit('plotly_redraw'); + return gd; + }); +}; + +/** + * Convenience function to make idempotent plot option obvious to users. + * + * @param gd + * @param {Object[]} data + * @param {Object} layout + * @param {Object} config + */ +exports.newPlot = function(gd, data, layout, config) { + gd = Lib.getGraphDiv(gd); + + // remove gl contexts + Plots.cleanPlot([], {}, gd._fullData || [], gd._fullLayout || {}); + + Plots.purge(gd); + return exports.plot(gd, data, layout, config); +}; + +/** + * Wrap negative indicies to their positive counterparts. + * + * @param {Number[]} indices An array of indices + * @param {Number} maxIndex The maximum index allowable (arr.length - 1) + */ +function positivifyIndices(indices, maxIndex) { + var parentLength = maxIndex + 1, + positiveIndices = [], + i, + index; + + for(i = 0; i < indices.length; i++) { + index = indices[i]; + if(index < 0) { + positiveIndices.push(parentLength + index); + } else { + positiveIndices.push(index); + } + } + return positiveIndices; +} + +/** + * Ensures that an index array for manipulating gd.data is valid. + * + * Intended for use with addTraces, deleteTraces, and moveTraces. + * + * @param gd + * @param indices + * @param arrayName + */ +function assertIndexArray(gd, indices, arrayName) { + var i, + index; + + for(i = 0; i < indices.length; i++) { + index = indices[i]; + + // validate that indices are indeed integers + if(index !== parseInt(index, 10)) { + throw new Error('all values in ' + arrayName + ' must be integers'); + } + + // check that all indices are in bounds for given gd.data array length + if(index >= gd.data.length || index < -gd.data.length) { + throw new Error(arrayName + ' must be valid indices for gd.data.'); + } + + // check that indices aren't repeated + if(indices.indexOf(index, i + 1) > -1 || + index >= 0 && indices.indexOf(-gd.data.length + index) > -1 || + index < 0 && indices.indexOf(gd.data.length + index) > -1) { + throw new Error('each index in ' + arrayName + ' must be unique.'); + } + } +} + +/** + * Private function used by Plotly.moveTraces to check input args + * + * @param gd + * @param currentIndices + * @param newIndices + */ +function checkMoveTracesArgs(gd, currentIndices, newIndices) { + + // check that gd has attribute 'data' and 'data' is array + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array.'); + } + + // validate currentIndices array + if(typeof currentIndices === 'undefined') { + throw new Error('currentIndices is a required argument.'); + } else if(!Array.isArray(currentIndices)) { + currentIndices = [currentIndices]; + } + assertIndexArray(gd, currentIndices, 'currentIndices'); + + // validate newIndices array if it exists + if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + if(typeof newIndices !== 'undefined') { + assertIndexArray(gd, newIndices, 'newIndices'); + } + + // check currentIndices and newIndices are the same length if newIdices exists + if(typeof newIndices !== 'undefined' && currentIndices.length !== newIndices.length) { + throw new Error('current and new indices must be of equal length.'); + } + +} +/** + * A private function to reduce the type checking clutter in addTraces. + * + * @param gd + * @param traces + * @param newIndices + */ +function checkAddTracesArgs(gd, traces, newIndices) { + var i, value; + + // check that gd has attribute 'data' and 'data' is array + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array.'); + } + + // make sure traces exists + if(typeof traces === 'undefined') { + throw new Error('traces must be defined.'); + } + + // make sure traces is an array + if(!Array.isArray(traces)) { + traces = [traces]; + } + + // make sure each value in traces is an object + for(i = 0; i < traces.length; i++) { + value = traces[i]; + if(typeof value !== 'object' || (Array.isArray(value) || value === null)) { + throw new Error('all values in traces array must be non-array objects'); + } + } + + // make sure we have an index for each trace + if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + if(typeof newIndices !== 'undefined' && newIndices.length !== traces.length) { + throw new Error( + 'if indices is specified, traces.length must equal indices.length' + ); + } +} + +/** + * A private function to reduce the type checking clutter in spliceTraces. + * Get all update Properties from gd.data. Validate inputs and outputs. + * Used by prependTrace and extendTraces + * + * @param gd + * @param update + * @param indices + * @param maxPoints + */ +function assertExtendTracesArgs(gd, update, indices, maxPoints) { + + var maxPointsIsObject = Lib.isPlainObject(maxPoints); + + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array'); + } + if(!Lib.isPlainObject(update)) { + throw new Error('update must be a key:value object'); + } + + if(typeof indices === 'undefined') { + throw new Error('indices must be an integer or array of integers'); + } + + assertIndexArray(gd, indices, 'indices'); + + for(var key in update) { + + /* + * Verify that the attribute to be updated contains as many trace updates + * as indices. Failure must result in throw and no-op + */ + if(!Array.isArray(update[key]) || update[key].length !== indices.length) { + throw new Error('attribute ' + key + ' must be an array of length equal to indices array length'); + } + + /* + * if maxPoints is an object it must match keys and array lengths of 'update' 1:1 + */ + if(maxPointsIsObject && + (!(key in maxPoints) || !Array.isArray(maxPoints[key]) || + maxPoints[key].length !== update[key].length)) { + throw new Error('when maxPoints is set as a key:value object it must contain a 1:1 ' + + 'corrispondence with the keys and number of traces in the update object'); + } + } +} + +/** + * A private function to reduce the type checking clutter in spliceTraces. + * + * @param {Object|HTMLDivElement} gd + * @param {Object} update + * @param {Number[]} indices + * @param {Number||Object} maxPoints + * @return {Object[]} + */ +function getExtendProperties(gd, update, indices, maxPoints) { + + var maxPointsIsObject = Lib.isPlainObject(maxPoints), + updateProps = []; + var trace, target, prop, insert, maxp; + + // allow scalar index to represent a single trace position + if(!Array.isArray(indices)) indices = [indices]; + + // negative indices are wrapped around to their positive value. Equivalent to python indexing. + indices = positivifyIndices(indices, gd.data.length - 1); + + // loop through all update keys and traces and harvest validated data. + for(var key in update) { + + for(var j = 0; j < indices.length; j++) { + + /* + * Choose the trace indexed by the indices map argument and get the prop setter-getter + * instance that references the key and value for this particular trace. + */ + trace = gd.data[indices[j]]; + prop = Lib.nestedProperty(trace, key); + + /* + * Target is the existing gd.data.trace.dataArray value like "x" or "marker.size" + * Target must exist as an Array to allow the extend operation to be performed. + */ + target = prop.get(); + insert = update[key][j]; + + if(!Lib.isArrayOrTypedArray(insert)) { + throw new Error('attribute: ' + key + ' index: ' + j + ' must be an array'); + } + if(!Lib.isArrayOrTypedArray(target)) { + throw new Error('cannot extend missing or non-array attribute: ' + key); + } + if(target.constructor !== insert.constructor) { + throw new Error('cannot extend array with an array of a different type: ' + key); + } + + /* + * maxPoints may be an object map or a scalar. If object select the key:value, else + * Use the scalar maxPoints for all key and trace combinations. + */ + maxp = maxPointsIsObject ? maxPoints[key][j] : maxPoints; + + // could have chosen null here, -1 just tells us to not take a window + if(!isNumeric(maxp)) maxp = -1; + + /* + * Wrap the nestedProperty in an object containing required data + * for lengthening and windowing this particular trace - key combination. + * Flooring maxp mirrors the behaviour of floats in the Array.slice JSnative function. + */ + updateProps.push({ + prop: prop, + target: target, + insert: insert, + maxp: Math.floor(maxp) + }); + } + } + + // all target and insertion data now validated + return updateProps; +} + +/** + * A private function to key Extend and Prepend traces DRY + * + * @param {Object|HTMLDivElement} gd + * @param {Object} update + * @param {Number[]} indices + * @param {Number||Object} maxPoints + * @param {Function} updateArray + * @return {Object} + */ +function spliceTraces(gd, update, indices, maxPoints, updateArray) { + assertExtendTracesArgs(gd, update, indices, maxPoints); + + var updateProps = getExtendProperties(gd, update, indices, maxPoints); + var undoUpdate = {}; + var undoPoints = {}; + + for(var i = 0; i < updateProps.length; i++) { + var prop = updateProps[i].prop; + var maxp = updateProps[i].maxp; + + // return new array and remainder + var out = updateArray(updateProps[i].target, updateProps[i].insert, maxp); + prop.set(out[0]); + + // build the inverse update object for the undo operation + if(!Array.isArray(undoUpdate[prop.astr])) undoUpdate[prop.astr] = []; + undoUpdate[prop.astr].push(out[1]); + + // build the matching maxPoints undo object containing original trace lengths + if(!Array.isArray(undoPoints[prop.astr])) undoPoints[prop.astr] = []; + undoPoints[prop.astr].push(updateProps[i].target.length); + } + + return {update: undoUpdate, maxPoints: undoPoints}; +} + +function concatTypedArray(arr0, arr1) { + var arr2 = new arr0.constructor(arr0.length + arr1.length); + arr2.set(arr0); + arr2.set(arr1, arr0.length); + return arr2; +} + +/** + * extend && prepend traces at indices with update arrays, window trace lengths to maxPoints + * + * Extend and Prepend have identical APIs. Prepend inserts an array at the head while Extend + * inserts an array off the tail. Prepend truncates the tail of the array - counting maxPoints + * from the head, whereas Extend truncates the head of the array, counting backward maxPoints + * from the tail. + * + * If maxPoints is undefined, nonNumeric, negative or greater than extended trace length no + * truncation / windowing will be performed. If its zero, well the whole trace is truncated. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object} update The key:array map of target attributes to extend + * @param {Number|Number[]} indices The locations of traces to be extended + * @param {Number|Object} [maxPoints] Number of points for trace window after lengthening. + * + */ +exports.extendTraces = function extendTraces(gd, update, indices, maxPoints) { + gd = Lib.getGraphDiv(gd); + + function updateArray(target, insert, maxp) { + var newArray, remainder; + + if(Lib.isTypedArray(target)) { + if(maxp < 0) { + var none = new target.constructor(0); + var both = concatTypedArray(target, insert); + + if(maxp < 0) { + newArray = both; + remainder = none; + } else { + newArray = none; + remainder = both; + } + } else { + newArray = new target.constructor(maxp); + remainder = new target.constructor(target.length + insert.length - maxp); + + if(maxp === insert.length) { + newArray.set(insert); + remainder.set(target); + } else if(maxp < insert.length) { + var numberOfItemsFromInsert = insert.length - maxp; + + newArray.set(insert.subarray(numberOfItemsFromInsert)); + remainder.set(target); + remainder.set(insert.subarray(0, numberOfItemsFromInsert), target.length); + } else { + var numberOfItemsFromTarget = maxp - insert.length; + var targetBegin = target.length - numberOfItemsFromTarget; + + newArray.set(target.subarray(targetBegin)); + newArray.set(insert, numberOfItemsFromTarget); + remainder.set(target.subarray(0, targetBegin)); + } + } + } else { + newArray = target.concat(insert); + remainder = (maxp >= 0 && maxp < newArray.length) ? + newArray.splice(0, newArray.length - maxp) : + []; + } + + return [newArray, remainder]; + } + + var undo = spliceTraces(gd, update, indices, maxPoints, updateArray); + var promise = exports.redraw(gd); + var undoArgs = [gd, undo.update, indices, undo.maxPoints]; + Queue.add(gd, exports.prependTraces, undoArgs, extendTraces, arguments); + + return promise; +}; + +exports.prependTraces = function prependTraces(gd, update, indices, maxPoints) { + gd = Lib.getGraphDiv(gd); + + function updateArray(target, insert, maxp) { + var newArray, remainder; + + if(Lib.isTypedArray(target)) { + if(maxp <= 0) { + var none = new target.constructor(0); + var both = concatTypedArray(insert, target); + + if(maxp < 0) { + newArray = both; + remainder = none; + } else { + newArray = none; + remainder = both; + } + } else { + newArray = new target.constructor(maxp); + remainder = new target.constructor(target.length + insert.length - maxp); + + if(maxp === insert.length) { + newArray.set(insert); + remainder.set(target); + } else if(maxp < insert.length) { + var numberOfItemsFromInsert = insert.length - maxp; + + newArray.set(insert.subarray(0, numberOfItemsFromInsert)); + remainder.set(insert.subarray(numberOfItemsFromInsert)); + remainder.set(target, numberOfItemsFromInsert); + } else { + var numberOfItemsFromTarget = maxp - insert.length; + + newArray.set(insert); + newArray.set(target.subarray(0, numberOfItemsFromTarget), insert.length); + remainder.set(target.subarray(numberOfItemsFromTarget)); + } + } + } else { + newArray = insert.concat(target); + remainder = (maxp >= 0 && maxp < newArray.length) ? + newArray.splice(maxp, newArray.length) : + []; + } + + return [newArray, remainder]; + } + + var undo = spliceTraces(gd, update, indices, maxPoints, updateArray); + var promise = exports.redraw(gd); + var undoArgs = [gd, undo.update, indices, undo.maxPoints]; + Queue.add(gd, exports.extendTraces, undoArgs, prependTraces, arguments); + + return promise; +}; + +/** + * Add data traces to an existing graph div. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're adding to + * @param {Object[]|Object} traces The object or array of objects to add + * @param {Number[]|Number} [newIndices=[gd.data.length]] Locations to add traces + * + */ +exports.addTraces = function addTraces(gd, traces, newIndices) { + gd = Lib.getGraphDiv(gd); + + var currentIndices = [], + undoFunc = exports.deleteTraces, + redoFunc = addTraces, + undoArgs = [gd, currentIndices], + redoArgs = [gd, traces], // no newIndices here + i, + promise; + + // all validation is done elsewhere to remove clutter here + checkAddTracesArgs(gd, traces, newIndices); + + // make sure traces is an array + if(!Array.isArray(traces)) { + traces = [traces]; + } + + // make sure traces do not repeat existing ones + traces = traces.map(function(trace) { + return Lib.extendFlat({}, trace); + }); + + helpers.cleanData(traces); + + // add the traces to gd.data (no redrawing yet!) + for(i = 0; i < traces.length; i++) { + gd.data.push(traces[i]); + } + + // to continue, we need to call moveTraces which requires currentIndices + for(i = 0; i < traces.length; i++) { + currentIndices.push(-traces.length + i); + } + + // if the user didn't define newIndices, they just want the traces appended + // i.e., we can simply redraw and be done + if(typeof newIndices === 'undefined') { + promise = exports.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + return promise; + } + + // make sure indices is property defined + if(!Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + + try { + + // this is redundant, but necessary to not catch later possible errors! + checkMoveTracesArgs(gd, currentIndices, newIndices); + } + catch(error) { + + // something went wrong, reset gd to be safe and rethrow error + gd.data.splice(gd.data.length - traces.length, traces.length); + throw error; + } + + // if we're here, the user has defined specific places to place the new traces + // this requires some extra work that moveTraces will do + Queue.startSequence(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + promise = exports.moveTraces(gd, currentIndices, newIndices); + Queue.stopSequence(gd); + return promise; +}; + +/** + * Delete traces at `indices` from gd.data array. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're removing from + * @param {Number|Number[]} indices The indices + */ +exports.deleteTraces = function deleteTraces(gd, indices) { + gd = Lib.getGraphDiv(gd); + + var traces = [], + undoFunc = exports.addTraces, + redoFunc = deleteTraces, + undoArgs = [gd, traces, indices], + redoArgs = [gd, indices], + i, + deletedTrace; + + // make sure indices are defined + if(typeof indices === 'undefined') { + throw new Error('indices must be an integer or array of integers.'); + } else if(!Array.isArray(indices)) { + indices = [indices]; + } + assertIndexArray(gd, indices, 'indices'); + + // convert negative indices to positive indices + indices = positivifyIndices(indices, gd.data.length - 1); + + // we want descending here so that splicing later doesn't affect indexing + indices.sort(Lib.sorterDes); + for(i = 0; i < indices.length; i += 1) { + deletedTrace = gd.data.splice(indices[i], 1)[0]; + traces.push(deletedTrace); + } + + var promise = exports.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return promise; +}; + +/** + * Move traces at currentIndices array to locations in newIndices array. + * + * If newIndices is omitted, currentIndices will be moved to the end. E.g., + * these are equivalent: + * + * Plotly.moveTraces(gd, [1, 2, 3], [-3, -2, -1]) + * Plotly.moveTraces(gd, [1, 2, 3]) + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're removing from + * @param {Number|Number[]} currentIndices The locations of traces to be moved + * @param {Number|Number[]} [newIndices] The locations to move traces to + * + * Example calls: + * + * // move trace i to location x + * Plotly.moveTraces(gd, i, x) + * + * // move trace i to end of array + * Plotly.moveTraces(gd, i) + * + * // move traces i, j, k to end of array (i != j != k) + * Plotly.moveTraces(gd, [i, j, k]) + * + * // move traces [i, j, k] to [x, y, z] (i != j != k) (x != y != z) + * Plotly.moveTraces(gd, [i, j, k], [x, y, z]) + * + * // reorder all traces (assume there are 5--a, b, c, d, e) + * Plotly.moveTraces(gd, [b, d, e, a, c]) // same as 'move to end' + */ +exports.moveTraces = function moveTraces(gd, currentIndices, newIndices) { + gd = Lib.getGraphDiv(gd); + + var newData = [], + movingTraceMap = [], + undoFunc = moveTraces, + redoFunc = moveTraces, + undoArgs = [gd, newIndices, currentIndices], + redoArgs = [gd, currentIndices, newIndices], + i; + + // to reduce complexity here, check args elsewhere + // this throws errors where appropriate + checkMoveTracesArgs(gd, currentIndices, newIndices); + + // make sure currentIndices is an array + currentIndices = Array.isArray(currentIndices) ? currentIndices : [currentIndices]; + + // if undefined, define newIndices to point to the end of gd.data array + if(typeof newIndices === 'undefined') { + newIndices = []; + for(i = 0; i < currentIndices.length; i++) { + newIndices.push(-currentIndices.length + i); + } + } + + // make sure newIndices is an array if it's user-defined + newIndices = Array.isArray(newIndices) ? newIndices : [newIndices]; + + // convert negative indices to positive indices (they're the same length) + currentIndices = positivifyIndices(currentIndices, gd.data.length - 1); + newIndices = positivifyIndices(newIndices, gd.data.length - 1); + + // at this point, we've coerced the index arrays into predictable forms + + // get the traces that aren't being moved around + for(i = 0; i < gd.data.length; i++) { + + // if index isn't in currentIndices, include it in ignored! + if(currentIndices.indexOf(i) === -1) { + newData.push(gd.data[i]); + } + } + + // get a mapping of indices to moving traces + for(i = 0; i < currentIndices.length; i++) { + movingTraceMap.push({newIndex: newIndices[i], trace: gd.data[currentIndices[i]]}); + } + + // reorder this mapping by newIndex, ascending + movingTraceMap.sort(function(a, b) { + return a.newIndex - b.newIndex; + }); + + // now, add the moving traces back in, in order! + for(i = 0; i < movingTraceMap.length; i += 1) { + newData.splice(movingTraceMap[i].newIndex, 0, movingTraceMap[i].trace); + } + + gd.data = newData; + + var promise = exports.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return promise; +}; + +/** + * restyle: update trace attributes of an existing plot + * + * Can be called two ways. + * + * Signature 1: + * @param {String | HTMLDivElement} gd + * the id or DOM element of the graph container div + * @param {String} astr + * attribute string (like `'marker.symbol'`) to update + * @param {*} val + * value to give this attribute + * @param {Number[] | Number} [traces] + * integer or array of integers for the traces to alter (all if omitted) + * + * Signature 2: + * @param {String | HTMLDivElement} gd + * (as in signature 1) + * @param {Object} aobj + * attribute object `{astr1: val1, astr2: val2 ...}` + * allows setting multiple attributes simultaneously + * @param {Number[] | Number} [traces] + * (as in signature 1) + * + * `val` (or `val1`, `val2` ... in the object form) can be an array, + * to apply different values to each trace. + * + * If the array is too short, it will wrap around (useful for + * style files that want to specify cyclical default values). + */ +exports.restyle = function restyle(gd, astr, val, _traces) { + gd = Lib.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + var aobj = {}; + if(typeof astr === 'string') aobj[astr] = val; + else if(Lib.isPlainObject(astr)) { + // the 3-arg form + aobj = Lib.extendFlat({}, astr); + if(_traces === undefined) _traces = val; + } + else { + Lib.warn('Restyle fail.', astr, val, _traces); + return Promise.reject(); + } + + if(Object.keys(aobj).length) gd.changed = true; + + var traces = helpers.coerceTraceIndices(gd, _traces); + + var specs = _restyle(gd, aobj, traces); + var flags = specs.flags; + + // clear calcdata and/or axis types if required so they get regenerated + if(flags.calc) gd.calcdata = undefined; + if(flags.clearAxisTypes) helpers.clearAxisTypes(gd, traces, {}); + + // fill in redraw sequence + var seq = []; + + if(flags.fullReplot) { + seq.push(exports.plot); + } else { + seq.push(Plots.previousPromises); + + // maybe only call Plots.supplyDataDefaults in the splom case, + // to skip over long and slow axes defaults + Plots.supplyDefaults(gd); + + if(flags.markerSize) { + Plots.doCalcdata(gd); + addAxRangeSequence(seq); + + // TODO + // if all axes have autorange:false, then + // proceed to subroutines.doTraceStyle(), + // otherwise we must go through addAxRangeSequence, + // which in general must redraws 'all' axes + } + + if(flags.style) seq.push(subroutines.doTraceStyle); + if(flags.colorbars) seq.push(subroutines.doColorBars); + + seq.push(emitAfterPlot); + } + + seq.push(Plots.rehover); + + Queue.add(gd, + restyle, [gd, specs.undoit, specs.traces], + restyle, [gd, specs.redoit, specs.traces] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(); + + return plotDone.then(function() { + gd.emit('plotly_restyle', specs.eventData); + return gd; + }); +}; + +// for undo: undefined initial vals must be turned into nulls +// so that we unset rather than ignore them +function undefinedToNull(val) { + if(val === undefined) return null; + return val; +} + +function _restyle(gd, aobj, traces) { + var fullLayout = gd._fullLayout, + fullData = gd._fullData, + data = gd.data, + i; + + // initialize flags + var flags = editTypes.traceFlags(); + + // copies of the change (and previous values of anything affected) + // for the undo / redo queue + var redoit = {}, + undoit = {}, + axlist; + + // make a new empty vals array for undoit + function a0() { return traces.map(function() { return undefined; }); } + + // for autoranging multiple axes + function addToAxlist(axid) { + var axName = Axes.id2name(axid); + if(axlist.indexOf(axName) === -1) axlist.push(axName); + } + + function autorangeAttr(axName) { return 'LAYOUT' + axName + '.autorange'; } + + function rangeAttr(axName) { return 'LAYOUT' + axName + '.range'; } + + // for attrs that interact (like scales & autoscales), save the + // old vals before making the change + // val=undefined will not set a value, just record what the value was. + // val=null will delete the attribute + // attr can be an array to set several at once (all to the same val) + function doextra(attr, val, i) { + if(Array.isArray(attr)) { + attr.forEach(function(a) { doextra(a, val, i); }); + return; + } + // quit if explicitly setting this elsewhere + if(attr in aobj || helpers.hasParent(aobj, attr)) return; + + var extraparam; + if(attr.substr(0, 6) === 'LAYOUT') { + extraparam = Lib.nestedProperty(gd.layout, attr.replace('LAYOUT', '')); + } else { + extraparam = Lib.nestedProperty(data[traces[i]], attr); + } + + if(!(attr in undoit)) { + undoit[attr] = a0(); + } + if(undoit[attr][i] === undefined) { + undoit[attr][i] = undefinedToNull(extraparam.get()); + } + if(val !== undefined) { + extraparam.set(val); + } + } + + function allBins(binAttr) { + return function(j) { + return fullData[j][binAttr]; + }; + } + + function arrayBins(binAttr) { + return function(vij, j) { + return vij === false ? fullData[traces[j]][binAttr] : null; + }; + } + + // now make the changes to gd.data (and occasionally gd.layout) + // and figure out what kind of graphics update we need to do + for(var ai in aobj) { + if(helpers.hasParent(aobj, ai)) { + throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously'); + } + + var vi = aobj[ai], + cont, + contFull, + param, + oldVal, + newVal, + valObject; + + // Backward compatibility shim for turning histogram autobin on, + // or freezing previous autobinned values. + // Replace obsolete `autobin(x|y): true` with `(x|y)bins: null` + // and `autobin(x|y): false` with the `(x|y)bins` in `fullData` + if(ai === 'autobinx' || ai === 'autobiny') { + ai = ai.charAt(ai.length - 1) + 'bins'; + if(Array.isArray(vi)) vi = vi.map(arrayBins(ai)); + else if(vi === false) vi = traces.map(allBins(ai)); + else vi = null; + } + + redoit[ai] = vi; + + if(ai.substr(0, 6) === 'LAYOUT') { + param = Lib.nestedProperty(gd.layout, ai.replace('LAYOUT', '')); + undoit[ai] = [undefinedToNull(param.get())]; + // since we're allowing val to be an array, allow it here too, + // even though that's meaningless + param.set(Array.isArray(vi) ? vi[0] : vi); + // ironically, the layout attrs in restyle only require replot, + // not relayout + flags.calc = true; + continue; + } + + // set attribute in gd.data + undoit[ai] = a0(); + for(i = 0; i < traces.length; i++) { + cont = data[traces[i]]; + contFull = fullData[traces[i]]; + param = Lib.nestedProperty(cont, ai); + oldVal = param.get(); + newVal = Array.isArray(vi) ? vi[i % vi.length] : vi; + + if(newVal === undefined) continue; + + var finalPart = param.parts[param.parts.length - 1]; + var prefix = ai.substr(0, ai.length - finalPart.length - 1); + var prefixDot = prefix ? prefix + '.' : ''; + var innerContFull = prefix ? + Lib.nestedProperty(contFull, prefix).get() : contFull; + + valObject = PlotSchema.getTraceValObject(contFull, param.parts); + + if(valObject && valObject.impliedEdits && newVal !== null) { + for(var impliedKey in valObject.impliedEdits) { + doextra(Lib.relativeAttr(ai, impliedKey), valObject.impliedEdits[impliedKey], i); + } + } + + // changing colorbar size modes, + // make the resulting size not change + // note that colorbar fractional sizing is based on the + // original plot size, before anything (like a colorbar) + // increases the margins + else if((finalPart === 'thicknessmode' || finalPart === 'lenmode') && + oldVal !== newVal && + (newVal === 'fraction' || newVal === 'pixels') && + innerContFull + ) { + var gs = fullLayout._size; + var orient = innerContFull.orient; + var topOrBottom = (orient === 'top') || (orient === 'bottom'); + if(finalPart === 'thicknessmode') { + var thicknorm = topOrBottom ? gs.h : gs.w; + doextra(prefixDot + 'thickness', innerContFull.thickness * + (newVal === 'fraction' ? 1 / thicknorm : thicknorm), i); + } + else { + var lennorm = topOrBottom ? gs.w : gs.h; + doextra(prefixDot + 'len', innerContFull.len * + (newVal === 'fraction' ? 1 / lennorm : lennorm), i); + } + } + + else if(ai === 'type' && (newVal === 'pie') !== (oldVal === 'pie')) { + var labelsTo = 'x', + valuesTo = 'y'; + if((newVal === 'bar' || oldVal === 'bar') && cont.orientation === 'h') { + labelsTo = 'y'; + valuesTo = 'x'; + } + Lib.swapAttrs(cont, ['?', '?src'], 'labels', labelsTo); + Lib.swapAttrs(cont, ['d?', '?0'], 'label', labelsTo); + Lib.swapAttrs(cont, ['?', '?src'], 'values', valuesTo); + + if(oldVal === 'pie') { + Lib.nestedProperty(cont, 'marker.color') + .set(Lib.nestedProperty(cont, 'marker.colors').get()); + + // super kludgy - but if all pies are gone we won't remove them otherwise + fullLayout._pielayer.selectAll('g.trace').remove(); + } else if(Registry.traceIs(cont, 'cartesian')) { + Lib.nestedProperty(cont, 'marker.colors') + .set(Lib.nestedProperty(cont, 'marker.color').get()); + } + } + + undoit[ai][i] = undefinedToNull(oldVal); + // set the new value - if val is an array, it's one el per trace + // first check for attributes that get more complex alterations + var swapAttrs = [ + 'swapxy', 'swapxyaxes', 'orientation', 'orientationaxes' + ]; + if(swapAttrs.indexOf(ai) !== -1) { + // setting an orientation: make sure it's changing + // before we swap everything else + if(ai === 'orientation') { + param.set(newVal); + // obnoxious that we need this level of coupling... but in order to + // properly handle setting orientation to `null` we need to mimic + // the logic inside Bars.supplyDefaults for default orientation + var defaultOrientation = (cont.x && !cont.y) ? 'h' : 'v'; + if((param.get() || defaultOrientation) === contFull.orientation) { + continue; + } + } + // orientationaxes has no value, + // it flips everything and the axes + else if(ai === 'orientationaxes') { + cont.orientation = + {v: 'h', h: 'v'}[contFull.orientation]; + } + helpers.swapXYData(cont); + flags.calc = flags.clearAxisTypes = true; + } + else if(Plots.dataArrayContainers.indexOf(param.parts[0]) !== -1) { + // TODO: use manageArrays.applyContainerArrayChanges here too + helpers.manageArrayContainers(param, newVal, undoit); + flags.calc = true; + } + else { + if(valObject) { + // must redo calcdata when restyling array values of arrayOk attributes + // ... but no need to this for regl-based traces + if(valObject.arrayOk && + !Registry.traceIs(contFull, 'regl') && + (Lib.isArrayOrTypedArray(newVal) || Lib.isArrayOrTypedArray(oldVal)) + ) { + flags.calc = true; + } + else editTypes.update(flags, valObject); + } + else { + /* + * if we couldn't find valObject, assume a full recalc. + * This can happen if you're changing type and making + * some other edits too, so the modules we're + * looking at don't have these attributes in them. + */ + flags.calc = true; + } + + // all the other ones, just modify that one attribute + param.set(newVal); + } + } + + // swap the data attributes of the relevant x and y axes? + if(['swapxyaxes', 'orientationaxes'].indexOf(ai) !== -1) { + Axes.swap(gd, traces); + } + + // swap hovermode if set to "compare x/y data" + if(ai === 'orientationaxes') { + var hovermode = Lib.nestedProperty(gd.layout, 'hovermode'); + if(hovermode.get() === 'x') { + hovermode.set('y'); + } else if(hovermode.get() === 'y') { + hovermode.set('x'); + } + } + + // Major enough changes deserve autoscale and + // non-reversed axes so people don't get confused + // + // Note: autobin (or its new analog bin clearing) is not included here + // since we're not pushing bins back to gd.data, so if we have bin + // info it was explicitly provided by the user. + if(['orientation', 'type'].indexOf(ai) !== -1) { + axlist = []; + for(i = 0; i < traces.length; i++) { + var trace = data[traces[i]]; + + if(Registry.traceIs(trace, 'cartesian')) { + addToAxlist(trace.xaxis || 'x'); + addToAxlist(trace.yaxis || 'y'); + } + } + + doextra(axlist.map(autorangeAttr), true, 0); + doextra(axlist.map(rangeAttr), [0, 1], 0); + } + } + + if(flags.calc || flags.plot) { + flags.fullReplot = true; + } + + return { + flags: flags, + undoit: undoit, + redoit: redoit, + traces: traces, + eventData: Lib.extendDeepNoArrays([], [redoit, traces]) + }; +} + +/** + * relayout: update layout attributes of an existing plot + * + * Can be called two ways: + * + * Signature 1: + * @param {String | HTMLDivElement} gd + * the id or dom element of the graph container div + * @param {String} astr + * attribute string (like `'xaxis.range[0]'`) to update + * @param {*} val + * value to give this attribute + * + * Signature 2: + * @param {String | HTMLDivElement} gd + * (as in signature 1) + * @param {Object} aobj + * attribute object `{astr1: val1, astr2: val2 ...}` + * allows setting multiple attributes simultaneously + */ +exports.relayout = function relayout(gd, astr, val) { + gd = Lib.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + if(gd.framework && gd.framework.isPolar) { + return Promise.resolve(gd); + } + + var aobj = {}; + if(typeof astr === 'string') { + aobj[astr] = val; + } else if(Lib.isPlainObject(astr)) { + aobj = Lib.extendFlat({}, astr); + } else { + Lib.warn('Relayout fail.', astr, val); + return Promise.reject(); + } + + if(Object.keys(aobj).length) gd.changed = true; + + var specs = _relayout(gd, aobj); + var flags = specs.flags; + + // clear calcdata if required + if(flags.calc) gd.calcdata = undefined; + + // fill in redraw sequence + + // even if we don't have anything left in aobj, + // something may have happened within relayout that we + // need to wait for + var seq = [Plots.previousPromises]; + + if(flags.layoutReplot) { + seq.push(subroutines.layoutReplot); + } + else if(Object.keys(aobj).length) { + axRangeSupplyDefaultsByPass(gd, flags, specs) || Plots.supplyDefaults(gd); + + if(flags.legend) seq.push(subroutines.doLegend); + if(flags.layoutstyle) seq.push(subroutines.layoutStyles); + if(flags.axrange) addAxRangeSequence(seq, specs.rangesAltered); + if(flags.ticks) seq.push(subroutines.doTicksRelayout); + if(flags.modebar) seq.push(subroutines.doModeBar); + if(flags.camera) seq.push(subroutines.doCamera); + + seq.push(emitAfterPlot); + } + + seq.push(Plots.rehover); + + Queue.add(gd, + relayout, [gd, specs.undoit], + relayout, [gd, specs.redoit] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); + + return plotDone.then(function() { + gd.emit('plotly_relayout', specs.eventData); + return gd; + }); +}; + +// Optimization mostly for large splom traces where +// Plots.supplyDefaults can take > 100ms +function axRangeSupplyDefaultsByPass(gd, flags, specs) { + var k; + + if(!flags.axrange) return false; + + for(k in flags) { + if(k !== 'axrange' && flags[k]) return false; + } + + for(k in specs.rangesAltered) { + var axName = Axes.id2name(k); + var axIn = gd.layout[axName]; + var axOut = gd._fullLayout[axName]; + axOut.autorange = axIn.autorange; + axOut.range = axIn.range.slice(); + axOut.cleanRange(); + } + return true; +} + +function addAxRangeSequence(seq, rangesAltered) { + // N.B. leave as sequence of subroutines (for now) instead of + // subroutine of its own so that finalDraw always gets + // executed after drawData + var doTicks = rangesAltered ? + function(gd) { return Axes.doTicks(gd, Object.keys(rangesAltered), true); } : + function(gd) { return Axes.doTicks(gd, 'redraw'); }; + + seq.push( + subroutines.doAutoRangeAndConstraints, + doTicks, + subroutines.drawData, + subroutines.finalDraw + ); +} + +var AX_RANGE_RE = /^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/; +var AX_AUTORANGE_RE = /^[xyz]axis[0-9]*\.autorange$/; +var AX_DOMAIN_RE = /^[xyz]axis[0-9]*\.domain(\[[0|1]\])?$/; + +function _relayout(gd, aobj) { + var layout = gd.layout, + fullLayout = gd._fullLayout, + keys = Object.keys(aobj), + axes = Axes.list(gd), + arrayEdits = {}, + arrayStr, + i, + j; + + // look for 'allaxes', split out into all axes + // in case of 3D the axis are nested within a scene which is held in _id + for(i = 0; i < keys.length; i++) { + if(keys[i].indexOf('allaxes') === 0) { + for(j = 0; j < axes.length; j++) { + var scene = axes[j]._id.substr(1), + axisAttr = (scene.indexOf('scene') !== -1) ? (scene + '.') : '', + newkey = keys[i].replace('allaxes', axisAttr + axes[j]._name); + + if(!aobj[newkey]) aobj[newkey] = aobj[keys[i]]; + } + + delete aobj[keys[i]]; + } + } + + // initialize flags + var flags = editTypes.layoutFlags(); + + // copies of the change (and previous values of anything affected) + // for the undo / redo queue + var redoit = {}, + undoit = {}; + + // for attrs that interact (like scales & autoscales), save the + // old vals before making the change + // val=undefined will not set a value, just record what the value was. + // attr can be an array to set several at once (all to the same val) + function doextra(attr, val) { + if(Array.isArray(attr)) { + attr.forEach(function(a) { doextra(a, val); }); + return; + } + + // if we have another value for this attribute (explicitly or + // via a parent) do not override with this auto-generated extra + if(attr in aobj || helpers.hasParent(aobj, attr)) return; + + var p = Lib.nestedProperty(layout, attr); + if(!(attr in undoit)) { + undoit[attr] = undefinedToNull(p.get()); + } + if(val !== undefined) p.set(val); + } + + // for constraint enforcement: keep track of all axes (as {id: name}) + // we're editing the (auto)range of, so we can tell the others constrained + // to scale with them that it's OK for them to shrink + var rangesAltered = {}; + var axId; + + function recordAlteredAxis(pleafPlus) { + var axId = Axes.name2id(pleafPlus.split('.')[0]); + rangesAltered[axId] = 1; + return axId; + } + + // alter gd.layout + for(var ai in aobj) { + if(helpers.hasParent(aobj, ai)) { + throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously'); + } + + var p = Lib.nestedProperty(layout, ai); + var vi = aobj[ai]; + var plen = p.parts.length; + // p.parts may end with an index integer if the property is an array + var pend = plen - 1; + while(pend > 0 && typeof p.parts[pend] !== 'string') pend--; + // last property in chain (leaf node) + var pleaf = p.parts[pend]; + // leaf plus immediate parent + var pleafPlus = p.parts[pend - 1] + '.' + pleaf; + // trunk nodes (everything except the leaf) + var ptrunk = p.parts.slice(0, pend).join('.'); + var parentIn = Lib.nestedProperty(gd.layout, ptrunk).get(); + var parentFull = Lib.nestedProperty(fullLayout, ptrunk).get(); + var vOld = p.get(); + + if(vi === undefined) continue; + + redoit[ai] = vi; + + // axis reverse is special - it is its own inverse + // op and has no flag. + undoit[ai] = (pleaf === 'reverse') ? vi : undefinedToNull(vOld); + + var valObject = PlotSchema.getLayoutValObject(fullLayout, p.parts); + + if(valObject && valObject.impliedEdits && vi !== null) { + for(var impliedKey in valObject.impliedEdits) { + doextra(Lib.relativeAttr(ai, impliedKey), valObject.impliedEdits[impliedKey]); + } + } + + // Setting width or height to null must reset the graph's width / height + // back to its initial value as computed during the first pass in Plots.plotAutoSize. + // + // To do so, we must manually set them back here using the _initialAutoSize cache. + // can't use impliedEdits for this because behavior depends on vi + if(['width', 'height'].indexOf(ai) !== -1) { + if(vi) { + doextra('autosize', null); + // currently we don't support autosize one dim only - so + // explicitly set the other one. Note that doextra will + // ignore this if the same relayout call also provides oppositeAttr + var oppositeAttr = ai === 'height' ? 'width' : 'height'; + doextra(oppositeAttr, fullLayout[oppositeAttr]); + } + else { + fullLayout[ai] = gd._initialAutoSize[ai]; + } + } + else if(ai === 'autosize') { + // depends on vi here too, so again can't use impliedEdits + doextra('width', vi ? null : fullLayout.width); + doextra('height', vi ? null : fullLayout.height); + } + // check autorange vs range + else if(pleafPlus.match(AX_RANGE_RE)) { + recordAlteredAxis(pleafPlus); + Lib.nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); + } + else if(pleafPlus.match(AX_AUTORANGE_RE)) { + recordAlteredAxis(pleafPlus); + Lib.nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); + var axFull = Lib.nestedProperty(fullLayout, ptrunk).get(); + if(axFull._inputDomain) { + // if we're autoranging and this axis has a constrained domain, + // reset it so we don't get locked into a shrunken size + axFull._input.domain = axFull._inputDomain.slice(); + } + } + else if(pleafPlus.match(AX_DOMAIN_RE)) { + Lib.nestedProperty(fullLayout, ptrunk + '._inputDomain').set(null); + } + + // toggling axis type between log and linear: we need to convert + // positions for components that are still using linearized values, + // not data values like newer components. + // previously we did this for log <-> not-log, but now only do it + // for log <-> linear + if(pleaf === 'type') { + var ax = parentIn, + toLog = parentFull.type === 'linear' && vi === 'log', + fromLog = parentFull.type === 'log' && vi === 'linear'; + + if(toLog || fromLog) { + if(!ax || !ax.range) { + // 2D never gets here, but 3D does + // I don't think this is needed, but left here in case there + // are edge cases I'm not thinking of. + doextra(ptrunk + '.autorange', true); + } + else if(!parentFull.autorange) { + // toggling log without autorange: need to also recalculate ranges + // because log axes use linearized values for range endpoints + var r0 = ax.range[0], + r1 = ax.range[1]; + if(toLog) { + // if both limits are negative, autorange + if(r0 <= 0 && r1 <= 0) { + doextra(ptrunk + '.autorange', true); + } + // if one is negative, set it 6 orders below the other. + if(r0 <= 0) r0 = r1 / 1e6; + else if(r1 <= 0) r1 = r0 / 1e6; + // now set the range values as appropriate + doextra(ptrunk + '.range[0]', Math.log(r0) / Math.LN10); + doextra(ptrunk + '.range[1]', Math.log(r1) / Math.LN10); + } + else { + doextra(ptrunk + '.range[0]', Math.pow(10, r0)); + doextra(ptrunk + '.range[1]', Math.pow(10, r1)); + } + } + else if(toLog) { + // just make sure the range is positive and in the right + // order, it'll get recalculated later + ax.range = (ax.range[1] > ax.range[0]) ? [1, 2] : [2, 1]; + } + + // clear polar view initial stash for radial range so that + // value get recomputed in correct units + if(Array.isArray(fullLayout._subplots.polar) && + fullLayout._subplots.polar.length && + fullLayout[p.parts[0]] && + p.parts[1] === 'radialaxis' + ) { + delete fullLayout[p.parts[0]]._subplot.viewInitial['radialaxis.range']; + } + + // Annotations and images also need to convert to/from linearized coords + // Shapes do not need this :) + Registry.getComponentMethod('annotations', 'convertCoords')(gd, parentFull, vi, doextra); + Registry.getComponentMethod('images', 'convertCoords')(gd, parentFull, vi, doextra); + } + else { + // any other type changes: the range from the previous type + // will not make sense, so autorange it. + doextra(ptrunk + '.autorange', true); + doextra(ptrunk + '.range', null); + } + Lib.nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); + } + else if(pleaf.match(AX_NAME_PATTERN)) { + var fullProp = Lib.nestedProperty(fullLayout, ai).get(), + newType = (vi || {}).type; + + // This can potentially cause strange behavior if the autotype is not + // numeric (linear, because we don't auto-log) but the previous type + // was log. That's a very strange edge case though + if(!newType || newType === '-') newType = 'linear'; + Registry.getComponentMethod('annotations', 'convertCoords')(gd, fullProp, newType, doextra); + Registry.getComponentMethod('images', 'convertCoords')(gd, fullProp, newType, doextra); + } + + // alter gd.layout + + // collect array component edits for execution all together + // so we can ensure consistent behavior adding/removing items + // and order-independence for add/remove/edit all together in + // one relayout call + var containerArrayMatch = manageArrays.containerArrayMatch(ai); + if(containerArrayMatch) { + arrayStr = containerArrayMatch.array; + i = containerArrayMatch.index; + var propStr = containerArrayMatch.property; + var componentArray = Lib.nestedProperty(layout, arrayStr); + var obji = (componentArray || [])[i] || {}; + var updateValObject = valObject || {editType: 'calc'}; + + if(i !== '' && propStr === '') { + // special handling of undoit if we're adding or removing an element + // ie 'annotations[2]' which can be {...} (add) or null, + // does not work when replacing the entire array + if(manageArrays.isAddVal(vi)) { + undoit[ai] = null; + } else if(manageArrays.isRemoveVal(vi)) { + undoit[ai] = obji; + } else { + Lib.warn('unrecognized full object value', aobj); + } + } + editTypes.update(flags, updateValObject); + + // prepare the edits object we'll send to applyContainerArrayChanges + if(!arrayEdits[arrayStr]) arrayEdits[arrayStr] = {}; + var objEdits = arrayEdits[arrayStr][i]; + if(!objEdits) objEdits = arrayEdits[arrayStr][i] = {}; + objEdits[propStr] = vi; + + delete aobj[ai]; + } + // handle axis reversal explicitly, as there's no 'reverse' attribute + else if(pleaf === 'reverse') { + if(parentIn.range) parentIn.range.reverse(); + else { + doextra(ptrunk + '.autorange', true); + parentIn.range = [1, 0]; + } + + if(parentFull.autorange) flags.calc = true; + else flags.plot = true; + } + else { + if((fullLayout._has('scatter-like') && fullLayout._has('regl')) && + (ai === 'dragmode' && + (vi === 'lasso' || vi === 'select') && + !(vOld === 'lasso' || vOld === 'select')) + ) { + flags.plot = true; + } + else if(valObject) editTypes.update(flags, valObject); + else flags.calc = true; + + p.set(vi); + } + } + + // now we've collected component edits - execute them all together + for(arrayStr in arrayEdits) { + var finished = manageArrays.applyContainerArrayChanges(gd, + Lib.nestedProperty(layout, arrayStr), arrayEdits[arrayStr], flags); + if(!finished) flags.plot = true; + } + + // figure out if we need to recalculate axis constraints + var constraints = fullLayout._axisConstraintGroups || []; + for(axId in rangesAltered) { + for(i = 0; i < constraints.length; i++) { + var group = constraints[i]; + if(group[axId]) { + // Always recalc if we're changing constrained ranges. + // Otherwise it's possible to violate the constraints by + // specifying arbitrary ranges for all axes in the group. + // this way some ranges may expand beyond what's specified, + // as they do at first draw, to satisfy the constraints. + flags.calc = true; + for(var groupAxId in group) { + if(!rangesAltered[groupAxId]) { + Axes.getFromId(gd, groupAxId)._constraintShrinkable = true; + } + } + } + } + } + + // If the autosize changed or height or width was explicitly specified, + // this triggers a redraw + // TODO: do we really need special aobj.height/width handling here? + // couldn't editType do this? + if(updateAutosize(gd) || aobj.height || aobj.width) flags.plot = true; + + if(flags.plot || flags.calc) { + flags.layoutReplot = true; + } + + // now all attribute mods are done, as are + // redo and undo so we can save them + + return { + flags: flags, + rangesAltered: rangesAltered, + undoit: undoit, + redoit: redoit, + eventData: Lib.extendDeep({}, redoit) + }; +} + +/* + * updateAutosize: we made a change, does it change the autosize result? + * puts the new size into fullLayout + * returns true if either height or width changed + */ +function updateAutosize(gd) { + var fullLayout = gd._fullLayout; + var oldWidth = fullLayout.width; + var oldHeight = fullLayout.height; + + // calculate autosizing + if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, fullLayout); + + return (fullLayout.width !== oldWidth) || (fullLayout.height !== oldHeight); +} + +/** + * update: update trace and layout attributes of an existing plot + * + * @param {String | HTMLDivElement} gd + * the id or DOM element of the graph container div + * @param {Object} traceUpdate + * attribute object `{astr1: val1, astr2: val2 ...}` + * corresponding to updates in the plot's traces + * @param {Object} layoutUpdate + * attribute object `{astr1: val1, astr2: val2 ...}` + * corresponding to updates in the plot's layout + * @param {Number[] | Number} [traces] + * integer or array of integers for the traces to alter (all if omitted) + * + */ +exports.update = function update(gd, traceUpdate, layoutUpdate, _traces) { + gd = Lib.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + if(gd.framework && gd.framework.isPolar) { + return Promise.resolve(gd); + } + + if(!Lib.isPlainObject(traceUpdate)) traceUpdate = {}; + if(!Lib.isPlainObject(layoutUpdate)) layoutUpdate = {}; + + if(Object.keys(traceUpdate).length) gd.changed = true; + if(Object.keys(layoutUpdate).length) gd.changed = true; + + var traces = helpers.coerceTraceIndices(gd, _traces); + + var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces); + var restyleFlags = restyleSpecs.flags; + + var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate)); + var relayoutFlags = relayoutSpecs.flags; + + // clear calcdata and/or axis types if required + if(restyleFlags.calc || relayoutFlags.calc) gd.calcdata = undefined; + if(restyleFlags.clearAxisTypes) helpers.clearAxisTypes(gd, traces, layoutUpdate); + + // fill in redraw sequence + var seq = []; + + if(restyleFlags.fullReplot && relayoutFlags.layoutReplot) { + var data = gd.data, + layout = gd.layout; + + // clear existing data/layout on gd + // so that Plotly.plot doesn't try to extend them + gd.data = undefined; + gd.layout = undefined; + + seq.push(function() { return exports.plot(gd, data, layout); }); + } + else if(restyleFlags.fullReplot) { + seq.push(exports.plot); + } + else if(relayoutFlags.layoutReplot) { + seq.push(subroutines.layoutReplot); + } + else { + seq.push(Plots.previousPromises); + axRangeSupplyDefaultsByPass(gd, relayoutFlags, relayoutSpecs) || Plots.supplyDefaults(gd); + + if(restyleFlags.style) seq.push(subroutines.doTraceStyle); + if(restyleFlags.colorbars) seq.push(subroutines.doColorBars); + if(relayoutFlags.legend) seq.push(subroutines.doLegend); + if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles); + if(relayoutFlags.axrange) addAxRangeSequence(seq, relayoutSpecs.rangesAltered); + if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout); + if(relayoutFlags.modebar) seq.push(subroutines.doModeBar); + if(relayoutFlags.camera) seq.push(subroutines.doCamera); + + seq.push(emitAfterPlot); + } + + seq.push(Plots.rehover); + + Queue.add(gd, + update, [gd, restyleSpecs.undoit, relayoutSpecs.undoit, restyleSpecs.traces], + update, [gd, restyleSpecs.redoit, relayoutSpecs.redoit, restyleSpecs.traces] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); + + return plotDone.then(function() { + gd.emit('plotly_update', { + data: restyleSpecs.eventData, + layout: relayoutSpecs.eventData + }); + + return gd; + }); +}; + +/** + * Plotly.react: + * A plot/update method that takes the full plot state (same API as plot/newPlot) + * and diffs to determine the minimal update pathway + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * @param {array of objects} data + * array of traces, containing the data and display information for each trace + * @param {object} layout + * object describing the overall display of the plot, + * all the stuff that doesn't pertain to any individual trace + * @param {object} config + * configuration options (see ./plot_config.js for more info) + * + * OR + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * @param {object} figure + * object containing `data`, `layout`, `config`, and `frames` members + * + */ +exports.react = function(gd, data, layout, config) { + var frames, plotDone; + + function addFrames() { return exports.addFrames(gd, frames); } + + gd = Lib.getGraphDiv(gd); + + var oldFullData = gd._fullData; + var oldFullLayout = gd._fullLayout; + + // you can use this as the initial draw as well as to update + if(!Lib.isPlotDiv(gd) || !oldFullData || !oldFullLayout) { + plotDone = exports.newPlot(gd, data, layout, config); + } + else { + + if(Lib.isPlainObject(data)) { + var obj = data; + data = obj.data; + layout = obj.layout; + config = obj.config; + frames = obj.frames; + } + + var configChanged = false; + // assume that if there's a config at all, we're reacting to it too, + // and completely replace the previous config + if(config) { + var oldConfig = Lib.extendDeep({}, gd._context); + gd._context = undefined; + setPlotContext(gd, config); + configChanged = diffConfig(oldConfig, gd._context); + } + + gd.data = data || []; + helpers.cleanData(gd.data); + gd.layout = layout || {}; + helpers.cleanLayout(gd.layout); + + // "true" skips updating calcdata and remapping arrays from calcTransforms, + // which supplyDefaults usually does at the end, but we may need to NOT do + // if the diff (which we haven't determined yet) says we'll recalc + Plots.supplyDefaults(gd, {skipUpdateCalc: true}); + + var newFullData = gd._fullData; + var newFullLayout = gd._fullLayout; + var immutable = newFullLayout.datarevision === undefined; + var transition = newFullLayout.transition; + + var relayoutFlags = diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition); + var newDataRevision = relayoutFlags.newDataRevision; + var restyleFlags = diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision); + + // TODO: how to translate this part of relayout to Plotly.react? + // // Setting width or height to null must reset the graph's width / height + // // back to its initial value as computed during the first pass in Plots.plotAutoSize. + // // + // // To do so, we must manually set them back here using the _initialAutoSize cache. + // if(['width', 'height'].indexOf(ai) !== -1 && vi === null) { + // fullLayout[ai] = gd._initialAutoSize[ai]; + // } + + if(updateAutosize(gd)) relayoutFlags.layoutReplot = true; + + // clear calcdata if required + if(restyleFlags.calc || relayoutFlags.calc) gd.calcdata = undefined; + // otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier + else Plots.supplyDefaultsUpdateCalc(gd.calcdata, newFullData); + + // Note: what restyle/relayout use impliedEdits and clearAxisTypes for + // must be handled by the user when using Plotly.react. + + // fill in redraw sequence + var seq = []; + + if(frames) { + gd._transitionData = {}; + Plots.createTransitionData(gd); + seq.push(addFrames); + } + + // Transition pathway, + // only used when 'transition' is set by user and + // when at least one animatable attribute has changed, + // N.B. config changed aren't animatable + if(newFullLayout.transition && !configChanged && (restyleFlags.anim || relayoutFlags.anim)) { + Plots.doCalcdata(gd); + subroutines.doAutoRangeAndConstraints(gd); + + seq.push(function() { + return Plots.transition2(gd, restyleFlags, relayoutFlags, oldFullLayout); + }); + } + else if(restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) { + gd._fullLayout._skipDefaults = true; + seq.push(exports.plot); + } + else { + for(var componentType in relayoutFlags.arrays) { + var indices = relayoutFlags.arrays[componentType]; + if(indices.length) { + var drawOne = Registry.getComponentMethod(componentType, 'drawOne'); + if(drawOne !== Lib.noop) { + for(var i = 0; i < indices.length; i++) { + drawOne(gd, indices[i]); + } + } + else { + var draw = Registry.getComponentMethod(componentType, 'draw'); + if(draw === Lib.noop) { + throw new Error('cannot draw components: ' + componentType); + } + draw(gd); + } + } + } + + seq.push(Plots.previousPromises); + if(restyleFlags.style) seq.push(subroutines.doTraceStyle); + if(restyleFlags.colorbars) seq.push(subroutines.doColorBars); + if(relayoutFlags.legend) seq.push(subroutines.doLegend); + if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles); + if(relayoutFlags.axrange) addAxRangeSequence(seq); + if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout); + if(relayoutFlags.modebar) seq.push(subroutines.doModeBar); + if(relayoutFlags.camera) seq.push(subroutines.doCamera); + seq.push(emitAfterPlot); + } + + seq.push(Plots.rehover); + + plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); + } + + return plotDone.then(function() { + gd.emit('plotly_react', { + data: data, + layout: layout + }); + + return gd; + }); + +}; + +function diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision) { + if(oldFullData.length !== newFullData.length) { + return { + fullReplot: true, + calc: true + }; + } + + var flags = editTypes.traceFlags(); + flags.arrays = {}; + var i, trace; + + function getTraceValObject(parts) { + return PlotSchema.getTraceValObject(trace, parts); + } + + var diffOpts = { + getValObject: getTraceValObject, + flags: flags, + immutable: immutable, + transition: transition, + newDataRevision: newDataRevision, + gd: gd + }; + + var seenUIDs = {}; + + for(i = 0; i < oldFullData.length; i++) { + trace = newFullData[i]._fullInput; + if(Plots.hasMakesDataTransform(trace)) trace = newFullData[i]; + if(seenUIDs[trace.uid]) continue; + seenUIDs[trace.uid] = 1; + + getDiffFlags(oldFullData[i]._fullInput, trace, [], diffOpts); + } + + if(flags.calc || flags.plot) { + flags.fullReplot = true; + } + + return flags; +} + +function diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition) { + var flags = editTypes.layoutFlags(); + flags.arrays = {}; + flags.rangesAltered = {}; + flags.autorangedAxes = {}; + + function getLayoutValObject(parts) { + return PlotSchema.getLayoutValObject(newFullLayout, parts); + } + + var diffOpts = { + getValObject: getLayoutValObject, + flags: flags, + immutable: immutable, + transition: transition, + gd: gd + }; + + getDiffFlags(oldFullLayout, newFullLayout, [], diffOpts); + + if(flags.plot || flags.calc) { + flags.layoutReplot = true; + } + + return flags; +} + +function getDiffFlags(oldContainer, newContainer, outerparts, opts) { + var valObject, key, astr; + + var getValObject = opts.getValObject; + var flags = opts.flags; + var immutable = opts.immutable; + var inArray = opts.inArray; + var arrayIndex = opts.arrayIndex; + + function changed() { + var editType = valObject.editType; + if(inArray && editType.indexOf('arraydraw') !== -1) { + Lib.pushUnique(flags.arrays[inArray], arrayIndex); + return; + } + editTypes.update(flags, valObject); + + // track animatable changes + if(opts.transition) { + if(flags.anim === 'all' && !valObject.anim) { + flags.anim = 'some'; + } else if(!flags.anim && valObject.anim) { + flags.anim = 'all'; + } + } + + // track cartesian axes with altered ranges + if(AX_RANGE_RE.test(astr) || AX_AUTORANGE_RE.test(astr)) { + flags.rangesAltered[outerparts[0]] = 1; + } + + // track datarevision changes + if(key === 'datarevision') { + flags.newDataRevision = 1; + } + } + + function valObjectCanBeDataArray(valObject) { + return valObject.valType === 'data_array' || valObject.arrayOk; + } + + for(key in oldContainer) { + // short-circuit based on previous calls or previous keys that already maximized the pathway + if(flags.calc && !opts.transition) return; + + var oldVal = oldContainer[key]; + var newVal = newContainer[key]; + var parts = outerparts.concat(key); + astr = parts.join('.'); + + // track auto-ranged cartesian axes, changed or not + if(AX_AUTORANGE_RE.test(astr) && newVal === true) { + flags.autorangedAxes[outerparts[0]] = 1; + } + + if(key.charAt(0) === '_' || typeof oldVal === 'function' || oldVal === newVal) continue; + + // FIXME: ax.tick0 and dtick get filled in during plotting (except for geo subplots), + // and unlike other auto values they don't make it back into the input, + // so newContainer won't have them. + if((key === 'tick0' || key === 'dtick') && outerparts[0] !== 'geo') { + var tickMode = newContainer.tickmode; + if(tickMode === 'auto' || tickMode === 'array' || !tickMode) continue; + } + // FIXME: Similarly for axis ranges for 3D + // contourcarpet doesn't HAVE zmin/zmax, they're just auto-added. It needs them. + if(key === 'range' && newContainer.autorange) continue; + if((key === 'zmin' || key === 'zmax') && newContainer.type === 'contourcarpet') continue; + + valObject = getValObject(parts); + + // in case type changed, we may not even *have* a valObject. + if(!valObject) continue; + + if(valObject._compareAsJSON && JSON.stringify(oldVal) === JSON.stringify(newVal)) continue; + + var valType = valObject.valType; + var i; + + var canBeDataArray = valObjectCanBeDataArray(valObject); + var wasArray = Array.isArray(oldVal); + var nowArray = Array.isArray(newVal); + + // hack for traces that modify the data in supplyDefaults, like + // converting 1D to 2D arrays, which will always create new objects + if(wasArray && nowArray) { + var inputKey = '_input_' + key; + var oldValIn = oldContainer[inputKey]; + var newValIn = newContainer[inputKey]; + if(Array.isArray(oldValIn) && oldValIn === newValIn) continue; + } + + if(newVal === undefined) { + if(canBeDataArray && wasArray) flags.calc = true; + else changed(); + } + else if(valObject._isLinkedToArray) { + var arrayEditIndices = []; + var extraIndices = false; + if(!inArray) flags.arrays[key] = arrayEditIndices; + + var minLen = Math.min(oldVal.length, newVal.length); + var maxLen = Math.max(oldVal.length, newVal.length); + if(minLen !== maxLen) { + if(valObject.editType === 'arraydraw') { + extraIndices = true; + } + else { + changed(); + continue; + } + } + + for(i = 0; i < minLen; i++) { + getDiffFlags(oldVal[i], newVal[i], parts.concat(i), + // add array indices, but not if we're already in an array + Lib.extendFlat({inArray: key, arrayIndex: i}, opts)); + } + + // put this at the end so that we know our collected array indices are sorted + // but the check for length changes happens up front so we can short-circuit + // diffing if appropriate + if(extraIndices) { + for(i = minLen; i < maxLen; i++) { + arrayEditIndices.push(i); + } + } + } + else if(!valType && Lib.isPlainObject(oldVal)) { + getDiffFlags(oldVal, newVal, parts, opts); + } + else if(canBeDataArray) { + if(wasArray && nowArray) { + + // don't try to diff two data arrays. If immutable we know the data changed, + // if not, assume it didn't and let `layout.datarevision` tell us if it did + if(immutable) { + flags.calc = true; + } + + // look for animatable attributes when the data changed + if(immutable || opts.newDataRevision) { + changed(); + } + } + else if(wasArray !== nowArray) { + flags.calc = true; + } + else changed(); + } + else if(wasArray && nowArray) { + // info array, colorscale, 'any' - these are short, just stringify. + // I don't *think* that covers up any real differences post-validation, does it? + // otherwise we need to dive in 1 (info_array) or 2 (colorscale) levels and compare + // all elements. + if(oldVal.length !== newVal.length || String(oldVal) !== String(newVal)) { + changed(); + } + } + else { + changed(); + } + } + + for(key in newContainer) { + if(!(key in oldContainer || key.charAt(0) === '_' || typeof newContainer[key] === 'function')) { + valObject = getValObject(outerparts.concat(key)); + + if(valObjectCanBeDataArray(valObject) && Array.isArray(newContainer[key])) { + flags.calc = true; + return; + } + else changed(); + } + } +} + +/* + * simple diff for config - for now, just treat all changes as equivalent + */ +function diffConfig(oldConfig, newConfig) { + var key; + + for(key in oldConfig) { + if(key.charAt(0) === '_') continue; + var oldVal = oldConfig[key]; + var newVal = newConfig[key]; + if(oldVal !== newVal) { + if(Lib.isPlainObject(oldVal) && Lib.isPlainObject(newVal)) { + if(diffConfig(oldVal, newVal)) { + return true; + } + } + else if(Array.isArray(oldVal) && Array.isArray(newVal)) { + if(oldVal.length !== newVal.length) { + return true; + } + for(var i = 0; i < oldVal.length; i++) { + if(oldVal[i] !== newVal[i]) { + if(Lib.isPlainObject(oldVal[i]) && Lib.isPlainObject(newVal[i])) { + if(diffConfig(oldVal[i], newVal[i])) { + return true; + } + } + else { + return true; + } + } + } + } + else { + return true; + } + } + } +} + +/** + * Animate to a frame, sequence of frame, frame group, or frame definition + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {string or object or array of strings or array of objects} frameOrGroupNameOrFrameList + * a single frame, array of frames, or group to which to animate. The intent is + * inferred by the type of the input. Valid inputs are: + * + * - string, e.g. 'groupname': animate all frames of a given `group` in the order + * in which they are defined via `Plotly.addFrames`. + * + * - array of strings, e.g. ['frame1', frame2']: a list of frames by name to which + * to animate in sequence + * + * - object: {data: ...}: a frame definition to which to animate. The frame is not + * and does not need to be added via `Plotly.addFrames`. It may contain any of + * the properties of a frame, including `data`, `layout`, and `traces`. The + * frame is used as provided and does not use the `baseframe` property. + * + * - array of objects, e.g. [{data: ...}, {data: ...}]: a list of frame objects, + * each following the same rules as a single `object`. + * + * @param {object} animationOpts + * configuration for the animation + */ +exports.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) { + gd = Lib.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error( + 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + + 'to create a plot before animating it. For more details, see ' + + 'https://plot.ly/javascript/animations/' + ); + } + + var trans = gd._transitionData; + + // This is the queue of frames that will be animated as soon as possible. They + // are popped immediately upon the *start* of a transition: + if(!trans._frameQueue) { + trans._frameQueue = []; + } + + animationOpts = Plots.supplyAnimationDefaults(animationOpts); + var transitionOpts = animationOpts.transition; + var frameOpts = animationOpts.frame; + + // Since frames are popped immediately, an empty queue only means all frames have + // *started* to transition, not that the animation is complete. To solve that, + // track a separate counter that increments at the same time as frames are added + // to the queue, but decrements only when the transition is complete. + if(trans._frameWaitingCnt === undefined) { + trans._frameWaitingCnt = 0; + } + + function getTransitionOpts(i) { + if(Array.isArray(transitionOpts)) { + if(i >= transitionOpts.length) { + return transitionOpts[0]; + } else { + return transitionOpts[i]; + } + } else { + return transitionOpts; + } + } + + function getFrameOpts(i) { + if(Array.isArray(frameOpts)) { + if(i >= frameOpts.length) { + return frameOpts[0]; + } else { + return frameOpts[i]; + } + } else { + return frameOpts; + } + } + + // Execute a callback after the wrapper function has been called n times. + // This is used to defer the resolution until a transition has resovled *and* + // the frame has completed. If it's not done this way, then we get a race + // condition in which the animation might resolve before a transition is complete + // or vice versa. + function callbackOnNthTime(cb, n) { + var cnt = 0; + return function() { + if(cb && ++cnt === n) { + return cb(); + } + }; + } + + return new Promise(function(resolve, reject) { + function discardExistingFrames() { + if(trans._frameQueue.length === 0) { + return; + } + + while(trans._frameQueue.length) { + var next = trans._frameQueue.pop(); + if(next.onInterrupt) { + next.onInterrupt(); + } + } + + gd.emit('plotly_animationinterrupted', []); + } + + function queueFrames(frameList) { + if(frameList.length === 0) return; + + for(var i = 0; i < frameList.length; i++) { + var computedFrame; + + if(frameList[i].type === 'byname') { + // If it's a named frame, compute it: + computedFrame = Plots.computeFrame(gd, frameList[i].name); + } else { + // Otherwise we must have been given a simple object, so treat + // the input itself as the computed frame. + computedFrame = frameList[i].data; + } + + var frameOpts = getFrameOpts(i); + var transitionOpts = getTransitionOpts(i); + + // It doesn't make much sense for the transition duration to be greater than + // the frame duration, so limit it: + transitionOpts.duration = Math.min(transitionOpts.duration, frameOpts.duration); + + var nextFrame = { + frame: computedFrame, + name: frameList[i].name, + frameOpts: frameOpts, + transitionOpts: transitionOpts, + }; + if(i === frameList.length - 1) { + // The last frame in this .animate call stores the promise resolve + // and reject callbacks. This is how we ensure that the animation + // loop (which may exist as a result of a *different* .animate call) + // still resolves or rejecdts this .animate call's promise. once it's + // complete. + nextFrame.onComplete = callbackOnNthTime(resolve, 2); + nextFrame.onInterrupt = reject; + } + + trans._frameQueue.push(nextFrame); + } + + // Set it as never having transitioned to a frame. This will cause the animation + // loop to immediately transition to the next frame (which, for immediate mode, + // is the first frame in the list since all others would have been discarded + // below) + if(animationOpts.mode === 'immediate') { + trans._lastFrameAt = -Infinity; + } + + // Only it's not already running, start a RAF loop. This could be avoided in the + // case that there's only one frame, but it significantly complicated the logic + // and only sped things up by about 5% or so for a lorenz attractor simulation. + // It would be a fine thing to implement, but the benefit of that optimization + // doesn't seem worth the extra complexity. + if(!trans._animationRaf) { + beginAnimationLoop(); + } + } + + function stopAnimationLoop() { + gd.emit('plotly_animated'); + + // Be sure to unset also since it's how we know whether a loop is already running: + window.cancelAnimationFrame(trans._animationRaf); + trans._animationRaf = null; + } + + function nextFrame() { + if(trans._currentFrame && trans._currentFrame.onComplete) { + // Execute the callback and unset it to ensure it doesn't + // accidentally get called twice + trans._currentFrame.onComplete(); + } + + var newFrame = trans._currentFrame = trans._frameQueue.shift(); + + if(newFrame) { + // Since it's sometimes necessary to do deep digging into frame data, + // we'll consider it not 100% impossible for nulls or numbers to sneak through, + // so check when casting the name, just to be absolutely certain: + var stringName = newFrame.name ? newFrame.name.toString() : null; + gd._fullLayout._currentFrame = stringName; + + trans._lastFrameAt = Date.now(); + trans._timeToNext = newFrame.frameOpts.duration; + + // This is simply called and it's left to .transition to decide how to manage + // interrupting current transitions. That means we don't need to worry about + // how it resolves or what happens after this: + Plots.transition(gd, + newFrame.frame.data, + newFrame.frame.layout, + helpers.coerceTraceIndices(gd, newFrame.frame.traces), + newFrame.frameOpts, + newFrame.transitionOpts + ).then(function() { + if(newFrame.onComplete) { + newFrame.onComplete(); + } + + }); + + gd.emit('plotly_animatingframe', { + name: stringName, + frame: newFrame.frame, + animation: { + frame: newFrame.frameOpts, + transition: newFrame.transitionOpts, + } + }); + } else { + // If there are no more frames, then stop the RAF loop: + stopAnimationLoop(); + } + } + + function beginAnimationLoop() { + gd.emit('plotly_animating'); + + // If no timer is running, then set last frame = long ago so that the next + // frame is immediately transitioned: + trans._lastFrameAt = -Infinity; + trans._timeToNext = 0; + trans._runningTransitions = 0; + trans._currentFrame = null; + + var doFrame = function() { + // This *must* be requested before nextFrame since nextFrame may decide + // to cancel it if there's nothing more to animated: + trans._animationRaf = window.requestAnimationFrame(doFrame); + + // Check if we're ready for a new frame: + if(Date.now() - trans._lastFrameAt > trans._timeToNext) { + nextFrame(); + } + }; + + doFrame(); + } + + // This is an animate-local counter that helps match up option input list + // items with the particular frame. + var configCounter = 0; + function setTransitionConfig(frame) { + if(Array.isArray(transitionOpts)) { + if(configCounter >= transitionOpts.length) { + frame.transitionOpts = transitionOpts[configCounter]; + } else { + frame.transitionOpts = transitionOpts[0]; + } + } else { + frame.transitionOpts = transitionOpts; + } + configCounter++; + return frame; + } + + // Disambiguate what's sort of frames have been received + var i, frame; + var frameList = []; + var allFrames = frameOrGroupNameOrFrameList === undefined || frameOrGroupNameOrFrameList === null; + var isFrameArray = Array.isArray(frameOrGroupNameOrFrameList); + var isSingleFrame = !allFrames && !isFrameArray && Lib.isPlainObject(frameOrGroupNameOrFrameList); + + if(isSingleFrame) { + // In this case, a simple object has been passed to animate. + frameList.push({ + type: 'object', + data: setTransitionConfig(Lib.extendFlat({}, frameOrGroupNameOrFrameList)) + }); + } else if(allFrames || ['string', 'number'].indexOf(typeof frameOrGroupNameOrFrameList) !== -1) { + // In this case, null or undefined has been passed so that we want to + // animate *all* currently defined frames + for(i = 0; i < trans._frames.length; i++) { + frame = trans._frames[i]; + + if(!frame) continue; + + if(allFrames || String(frame.group) === String(frameOrGroupNameOrFrameList)) { + frameList.push({ + type: 'byname', + name: String(frame.name), + data: setTransitionConfig({name: frame.name}) + }); + } + } + } else if(isFrameArray) { + for(i = 0; i < frameOrGroupNameOrFrameList.length; i++) { + var frameOrName = frameOrGroupNameOrFrameList[i]; + if(['number', 'string'].indexOf(typeof frameOrName) !== -1) { + frameOrName = String(frameOrName); + // In this case, there's an array and this frame is a string name: + frameList.push({ + type: 'byname', + name: frameOrName, + data: setTransitionConfig({name: frameOrName}) + }); + } else if(Lib.isPlainObject(frameOrName)) { + frameList.push({ + type: 'object', + data: setTransitionConfig(Lib.extendFlat({}, frameOrName)) + }); + } + } + } + + // Verify that all of these frames actually exist; return and reject if not: + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frame.type === 'byname' && !trans._frameHash[frame.data.name]) { + Lib.warn('animate failure: frame not found: "' + frame.data.name + '"'); + reject(); + return; + } + } + + // If the mode is either next or immediate, then all currently queued frames must + // be dumped and the corresponding .animate promises rejected. + if(['next', 'immediate'].indexOf(animationOpts.mode) !== -1) { + discardExistingFrames(); + } + + if(animationOpts.direction === 'reverse') { + frameList.reverse(); + } + + var currentFrame = gd._fullLayout._currentFrame; + if(currentFrame && animationOpts.fromcurrent) { + var idx = -1; + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frame.type === 'byname' && frame.name === currentFrame) { + idx = i; + break; + } + } + + if(idx > 0 && idx < frameList.length - 1) { + var filteredFrameList = []; + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frameList[i].type !== 'byname' || i > idx) { + filteredFrameList.push(frame); + } + } + frameList = filteredFrameList; + } + } + + if(frameList.length > 0) { + queueFrames(frameList); + } else { + // This is the case where there were simply no frames. It's a little strange + // since there's not much to do: + gd.emit('plotly_animated'); + resolve(); + } + }); +}; + +/** + * Register new frames + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {array of objects} frameList + * list of frame definitions, in which each object includes any of: + * - name: {string} name of frame to add + * - data: {array of objects} trace data + * - layout {object} layout definition + * - traces {array} trace indices + * - baseframe {string} name of frame from which this frame gets defaults + * + * @param {array of integers} indices + * an array of integer indices matching the respective frames in `frameList`. If not + * provided, an index will be provided in serial order. If already used, the frame + * will be overwritten. + */ +exports.addFrames = function(gd, frameList, indices) { + gd = Lib.getGraphDiv(gd); + + if(frameList === null || frameList === undefined) { + return Promise.resolve(); + } + + if(!Lib.isPlotDiv(gd)) { + throw new Error( + 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + + 'to create a plot before adding frames. For more details, see ' + + 'https://plot.ly/javascript/animations/' + ); + } + + var i, frame, j, idx; + var _frames = gd._transitionData._frames; + var _frameHash = gd._transitionData._frameHash; + + + if(!Array.isArray(frameList)) { + throw new Error('addFrames failure: frameList must be an Array of frame definitions' + frameList); + } + + // Create a sorted list of insertions since we run into lots of problems if these + // aren't in ascending order of index: + // + // Strictly for sorting. Make sure this is guaranteed to never collide with any + // already-exisisting indices: + var bigIndex = _frames.length + frameList.length * 2; + + var insertions = []; + var _frameHashLocal = {}; + for(i = frameList.length - 1; i >= 0; i--) { + if(!Lib.isPlainObject(frameList[i])) continue; + + // The entire logic for checking for this type of name collision can be removed once we migrate to ES6 and + // use a Map instead of an Object instance, as Map keys aren't converted to strings. + var lookupName = frameList[i].name; + var name = (_frameHash[lookupName] || _frameHashLocal[lookupName] || {}).name; + var newName = frameList[i].name; + var collisionPresent = _frameHash[name] || _frameHashLocal[name]; + + if(name && newName && typeof newName === 'number' && collisionPresent && numericNameWarningCount < numericNameWarningCountLimit) { + numericNameWarningCount++; + + Lib.warn('addFrames: overwriting frame "' + (_frameHash[name] || _frameHashLocal[name]).name + + '" with a frame whose name of type "number" also equates to "' + + name + '". This is valid but may potentially lead to unexpected ' + + 'behavior since all plotly.js frame names are stored internally ' + + 'as strings.'); + + if(numericNameWarningCount === numericNameWarningCountLimit) { + Lib.warn('addFrames: This API call has yielded too many of these warnings. ' + + 'For the rest of this call, further warnings about numeric frame ' + + 'names will be suppressed.'); + } + } + + _frameHashLocal[lookupName] = {name: lookupName}; + + insertions.push({ + frame: Plots.supplyFrameDefaults(frameList[i]), + index: (indices && indices[i] !== undefined && indices[i] !== null) ? indices[i] : bigIndex + i + }); + } + + // Sort this, taking note that undefined insertions end up at the end: + insertions.sort(function(a, b) { + if(a.index > b.index) return -1; + if(a.index < b.index) return 1; + return 0; + }); + + var ops = []; + var revops = []; + var frameCount = _frames.length; + + for(i = insertions.length - 1; i >= 0; i--) { + frame = insertions[i].frame; + + if(typeof frame.name === 'number') { + Lib.warn('Warning: addFrames accepts frames with numeric names, but the numbers are' + + 'implicitly cast to strings'); + + } + + if(!frame.name) { + // Repeatedly assign a default name, incrementing the counter each time until + // we get a name that's not in the hashed lookup table: + while(_frameHash[(frame.name = 'frame ' + gd._transitionData._counter++)]); + } + + if(_frameHash[frame.name]) { + // If frame is present, overwrite its definition: + for(j = 0; j < _frames.length; j++) { + if((_frames[j] || {}).name === frame.name) break; + } + ops.push({type: 'replace', index: j, value: frame}); + revops.unshift({type: 'replace', index: j, value: _frames[j]}); + } else { + // Otherwise insert it at the end of the list: + idx = Math.max(0, Math.min(insertions[i].index, frameCount)); + + ops.push({type: 'insert', index: idx, value: frame}); + revops.unshift({type: 'delete', index: idx}); + frameCount++; + } + } + + var undoFunc = Plots.modifyFrames, + redoFunc = Plots.modifyFrames, + undoArgs = [gd, revops], + redoArgs = [gd, ops]; + + if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return Plots.modifyFrames(gd, ops); +}; + +/** + * Delete frame + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {array of integers} frameList + * list of integer indices of frames to be deleted + */ +exports.deleteFrames = function(gd, frameList) { + gd = Lib.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error('This element is not a Plotly plot: ' + gd); + } + + var i, idx; + var _frames = gd._transitionData._frames; + var ops = []; + var revops = []; + + if(!frameList) { + frameList = []; + for(i = 0; i < _frames.length; i++) { + frameList.push(i); + } + } + + frameList = frameList.slice(0); + frameList.sort(); + + for(i = frameList.length - 1; i >= 0; i--) { + idx = frameList[i]; + ops.push({type: 'delete', index: idx}); + revops.unshift({type: 'insert', index: idx, value: _frames[idx]}); + } + + var undoFunc = Plots.modifyFrames, + redoFunc = Plots.modifyFrames, + undoArgs = [gd, revops], + redoArgs = [gd, ops]; + + if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return Plots.modifyFrames(gd, ops); +}; + +/** + * Purge a graph container div back to its initial pre-Plotly.plot state + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + */ +exports.purge = function purge(gd) { + gd = Lib.getGraphDiv(gd); + + var fullLayout = gd._fullLayout || {}; + var fullData = gd._fullData || []; + + // remove gl contexts + Plots.cleanPlot([], {}, fullData, fullLayout); + + // purge properties + Plots.purge(gd); + + // purge event emitter methods + Events.purge(gd); + + // remove plot container + if(fullLayout._container) fullLayout._container.remove(); + + // in contrast to Plotly.Plots.purge which does NOT clear _context! + delete gd._context; + + return gd; +}; + +// ------------------------------------------------------- +// makePlotFramework: Create the plot container and axes +// ------------------------------------------------------- +function makePlotFramework(gd) { + var gd3 = d3.select(gd); + var fullLayout = gd._fullLayout; + + // Plot container + fullLayout._container = gd3.selectAll('.plot-container').data([0]); + fullLayout._container.enter().insert('div', ':first-child') + .classed('plot-container', true) + .classed('plotly', true); + + // Make the svg container + fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]); + fullLayout._paperdiv.enter().append('div') + .classed('svg-container', true) + .style('position', 'relative'); + + // Make the graph containers + // start fresh each time we get here, so we know the order comes out + // right, rather than enter/exit which can muck up the order + // TODO: sort out all the ordering so we don't have to + // explicitly delete anything + // FIXME: parcoords reuses this object, not the best pattern + fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container') + .data([{}]); + + fullLayout._glcontainer.enter().append('div') + .classed('gl-container', true); + + fullLayout._paperdiv.selectAll('.main-svg').remove(); + + fullLayout._paper = fullLayout._paperdiv.insert('svg', ':first-child') + .classed('main-svg', true); + + fullLayout._toppaper = fullLayout._paperdiv.append('svg') + .classed('main-svg', true); + + if(!fullLayout._uid) { + var otherUids = {}; + d3.selectAll('defs').each(function() { + if(this.id) otherUids[this.id.split('-')[1]] = 1; + }); + fullLayout._uid = Lib.randstr(otherUids); + } + + fullLayout._paperdiv.selectAll('.main-svg') + .attr(xmlnsNamespaces.svgAttrs); + + fullLayout._defs = fullLayout._paper.append('defs') + .attr('id', 'defs-' + fullLayout._uid); + + fullLayout._clips = fullLayout._defs.append('g') + .classed('clips', true); + + fullLayout._topdefs = fullLayout._toppaper.append('defs') + .attr('id', 'topdefs-' + fullLayout._uid); + + fullLayout._topclips = fullLayout._topdefs.append('g') + .classed('clips', true); + + fullLayout._bgLayer = fullLayout._paper.append('g') + .classed('bglayer', true); + + fullLayout._draggers = fullLayout._paper.append('g') + .classed('draglayer', true); + + // lower shape/image layer - note that this is behind + // all subplots data/grids but above the backgrounds + // except inset subplots, whose backgrounds are drawn + // inside their own group so that they appear above + // the data for the main subplot + // lower shapes and images which are fully referenced to + // a subplot still get drawn within the subplot's group + // so they will work correctly on insets + var layerBelow = fullLayout._paper.append('g') + .classed('layer-below', true); + fullLayout._imageLowerLayer = layerBelow.append('g') + .classed('imagelayer', true); + fullLayout._shapeLowerLayer = layerBelow.append('g') + .classed('shapelayer', true); + + // single cartesian layer for the whole plot + fullLayout._cartesianlayer = fullLayout._paper.append('g').classed('cartesianlayer', true); + + // single polar layer for the whole plot + fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true); + + // single ternary layer for the whole plot + fullLayout._ternarylayer = fullLayout._paper.append('g').classed('ternarylayer', true); + + // single geo layer for the whole plot + fullLayout._geolayer = fullLayout._paper.append('g').classed('geolayer', true); + + // single pie layer for the whole plot + fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true); + + // fill in image server scrape-svg + fullLayout._glimages = fullLayout._paper.append('g').classed('glimages', true); + + // lastly upper shapes, info (legend, annotations) and hover layers go on top + // these are in a different svg element normally, but get collapsed into a single + // svg when exporting (after inserting 3D) + // upper shapes/images are only those drawn above the whole plot, including subplots + var layerAbove = fullLayout._toppaper.append('g') + .classed('layer-above', true); + fullLayout._imageUpperLayer = layerAbove.append('g') + .classed('imagelayer', true); + fullLayout._shapeUpperLayer = layerAbove.append('g') + .classed('shapelayer', true); + + fullLayout._infolayer = fullLayout._toppaper.append('g').classed('infolayer', true); + fullLayout._menulayer = fullLayout._toppaper.append('g').classed('menulayer', true); + fullLayout._zoomlayer = fullLayout._toppaper.append('g').classed('zoomlayer', true); + fullLayout._hoverlayer = fullLayout._toppaper.append('g').classed('hoverlayer', true); + + gd.emit('plotly_framework'); +} + +},{"../components/color":570,"../components/colorbar/connect":572,"../components/drawing":595,"../constants/xmlns_namespaces":674,"../lib":696,"../lib/events":684,"../lib/queue":711,"../lib/svg_text_utils":720,"../plots/cartesian/axes":744,"../plots/cartesian/constants":750,"../plots/cartesian/graph_interact":754,"../plots/plots":808,"../plots/polar/legacy":816,"../registry":827,"./edit_types":727,"./helpers":728,"./manage_arrays":730,"./plot_config":732,"./plot_schema":733,"./subroutines":735,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,"has-hover":393}],732:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * This will be transferred over to gd and overridden by + * config args to Plotly.plot. + * + * The defaults are the appropriate settings for plotly.js, + * so we get the right experience without any config argument. + */ + +module.exports = { + + // no interactivity, for export or image generation + staticPlot: false, + + // base URL for the 'Edit in Chart Studio' (aka sendDataToCloud) mode bar button + // and the showLink/sendData on-graph link + plotlyServerURL: 'https://plot.ly', + + /* + * we can edit titles, move annotations, etc - sets all pieces of `edits` + * unless a separate `edits` config item overrides individual parts + */ + editable: false, + edits: { + /* + * annotationPosition: the main anchor of the annotation, which is the + * text (if no arrow) or the arrow (which drags the whole thing leaving + * the arrow length & direction unchanged) + */ + annotationPosition: false, + // just for annotations with arrows, change the length and direction of the arrow + annotationTail: false, + annotationText: false, + axisTitleText: false, + colorbarPosition: false, + colorbarTitleText: false, + legendPosition: false, + // edit the trace name fields from the legend + legendText: false, + shapePosition: false, + // the global `layout.title` + titleText: false + }, + + /* + * DO autosize once regardless of layout.autosize + * (use default width or height values otherwise) + */ + autosizable: false, + + /* + * responsive: determines whether to change the layout size when window is resized. + * In v2, this option will be removed and will always be true. + */ + responsive: false, + + // set the length of the undo/redo queue + queueLength: 0, + + // if we DO autosize, do we fill the container or the screen? + fillFrame: false, + + // if we DO autosize, set the frame margins in percents of plot size + frameMargins: 0, + + // mousewheel or two-finger scroll zooms the plot + scrollZoom: false, + + // double click interaction (false, 'reset', 'autosize' or 'reset+autosize') + doubleClick: 'reset+autosize', + + // new users see some hints about interactivity + showTips: true, + + // enable axis pan/zoom drag handles + showAxisDragHandles: true, + + /* + * enable direct range entry at the pan/zoom drag points + * (drag handles must be enabled above) + */ + showAxisRangeEntryBoxes: true, + + // link to open this plot in plotly + showLink: false, + + // if we show a link, does it contain data or just link to a plotly file? + sendData: true, + + // text appearing in the sendData link + linkText: 'Edit chart', + + // false or function adding source(s) to linkText + showSources: false, + + // display the mode bar (true, false, or 'hover') + displayModeBar: 'hover', + + /* + * remove mode bar button by name + * (see ../components/modebar/buttons.js for the list of names) + */ + modeBarButtonsToRemove: [], + + /* + * add mode bar button using config objects + * (see ./components/modebar/buttons.js for list of arguments) + */ + modeBarButtonsToAdd: [], + + /* + * fully custom mode bar buttons as nested array, + * where the outer arrays represents button groups, and + * the inner arrays have buttons config objects or names of default buttons + * (see ../components/modebar/buttons.js for more info) + */ + modeBarButtons: false, + + // statically override options for toImage modebar button + // allowed keys are format, filename, width, height, scale + // see ../components/modebar/buttons.js + toImageButtonOptions: {}, + + // add the plotly logo on the end of the mode bar + displaylogo: true, + + // increase the pixel ratio for Gl plot images + plotGlPixelRatio: 2, + + /* + * background setting function + * 'transparent' sets the background `layout.paper_color` + * 'opaque' blends bg color with white ensuring an opaque background + * or any other custom function of gd + */ + setBackground: 'transparent', + + // URL to topojson files used in geo charts + topojsonURL: 'https://cdn.plot.ly/', + + /* + * Mapbox access token (required to plot mapbox trace types) + * If using an Mapbox Atlas server, set this option to '', + * so that plotly.js won't attempt to authenticate to the public Mapbox server. + */ + mapboxAccessToken: null, + + /* + * Turn all console logging on or off (errors will be thrown) + * This should ONLY be set via Plotly.setPlotConfig + * 0: no logs + * 1: warnings and errors, but not informational messages + * 2: verbose logs + */ + logging: 1, + + /* + * Set global transform to be applied to all traces with no + * specification needed + */ + globalTransforms: [], + + /* + * Which localization should we use? + * Should be a string like 'en' or 'en-US'. + */ + locale: 'en-US', + + /* + * Localization definitions + * Locales can be provided either here (specific to one chart) or globally + * by registering them as modules. + * Should be an object of objects {locale: {dictionary: {...}, format: {...}}} + * { + * da: { + * dictionary: {'Reset axes': 'Nulstil aksler', ...}, + * format: {months: [...], shortMonths: [...]} + * }, + * ... + * } + * All parts are optional. When looking for translation or format fields, we + * look first for an exact match in a config locale, then in a registered + * module. If those fail, we strip off any regionalization ('en-US' -> 'en') + * and try each (config, registry) again. The final fallback for translation + * is untranslated (which is US English) and for formats is the base English + * (the only consequence being the last fallback date format %x is DD/MM/YYYY + * instead of MM/DD/YYYY). Currently `grouping` and `currency` are ignored + * for our automatic number formatting, but can be used in custom formats. + */ + locales: {} +}; + +},{}],733:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../registry'); +var Lib = _dereq_('../lib'); + +var baseAttributes = _dereq_('../plots/attributes'); +var baseLayoutAttributes = _dereq_('../plots/layout_attributes'); +var frameAttributes = _dereq_('../plots/frame_attributes'); +var animationAttributes = _dereq_('../plots/animation_attributes'); + +// polar attributes are not part of the Registry yet +var polarAreaAttrs = _dereq_('../plots/polar/legacy/area_attributes'); +var polarAxisAttrs = _dereq_('../plots/polar/legacy/axis_attributes'); + +var editTypes = _dereq_('./edit_types'); + +var extendFlat = Lib.extendFlat; +var extendDeepAll = Lib.extendDeepAll; +var isPlainObject = Lib.isPlainObject; + +var IS_SUBPLOT_OBJ = '_isSubplotObj'; +var IS_LINKED_TO_ARRAY = '_isLinkedToArray'; +var ARRAY_ATTR_REGEXPS = '_arrayAttrRegexps'; +var DEPRECATED = '_deprecated'; +var UNDERSCORE_ATTRS = [IS_SUBPLOT_OBJ, IS_LINKED_TO_ARRAY, ARRAY_ATTR_REGEXPS, DEPRECATED]; + +exports.IS_SUBPLOT_OBJ = IS_SUBPLOT_OBJ; +exports.IS_LINKED_TO_ARRAY = IS_LINKED_TO_ARRAY; +exports.DEPRECATED = DEPRECATED; +exports.UNDERSCORE_ATTRS = UNDERSCORE_ATTRS; + +/** Outputs the full plotly.js plot schema + * + * @return {object} + * - defs + * - traces + * - layout + * - transforms + * - frames + * - animations + * - config (coming soon ...) + */ +exports.get = function() { + var traces = {}; + + Registry.allTypes.concat('area').forEach(function(type) { + traces[type] = getTraceAttributes(type); + }); + + var transforms = {}; + + Object.keys(Registry.transformsRegistry).forEach(function(type) { + transforms[type] = getTransformAttributes(type); + }); + + return { + defs: { + valObjects: Lib.valObjectMeta, + metaKeys: UNDERSCORE_ATTRS.concat(['description', 'role', 'editType', 'impliedEdits']), + editType: { + traces: editTypes.traces, + layout: editTypes.layout + }, + impliedEdits: { + + } + }, + + traces: traces, + layout: getLayoutAttributes(), + + transforms: transforms, + + frames: getFramesAttributes(), + animation: formatAttributes(animationAttributes) + }; +}; + +/** + * Crawl the attribute tree, recursively calling a callback function + * + * @param {object} attrs + * The node of the attribute tree (e.g. the root) from which recursion originates + * @param {Function} callback + * A callback function with the signature: + * @callback callback + * @param {object} attr an attribute + * @param {String} attrName name string + * @param {object[]} attrs all the attributes + * @param {Number} level the recursion level, 0 at the root + * @param {String} fullAttrString full attribute name (ie 'marker.line') + * @param {Number} [specifiedLevel] + * The level in the tree, in order to let the callback function detect descend or backtrack, + * typically unsupplied (implied 0), just used by the self-recursive call. + * The necessity arises because the tree traversal is not controlled by callback return values. + * The decision to not use callback return values for controlling tree pruning arose from + * the goal of keeping the crawler backwards compatible. Observe that one of the pruning conditions + * precedes the callback call. + * @param {string} [attrString] + * the path to the current attribute, as an attribute string (ie 'marker.line') + * typically unsupplied, but you may supply it if you want to disambiguate which attrs tree you + * are starting from + * + * @return {object} transformOut + * copy of transformIn that contains attribute defaults + */ +exports.crawl = function(attrs, callback, specifiedLevel, attrString) { + var level = specifiedLevel || 0; + attrString = attrString || ''; + + Object.keys(attrs).forEach(function(attrName) { + var attr = attrs[attrName]; + + if(UNDERSCORE_ATTRS.indexOf(attrName) !== -1) return; + + var fullAttrString = (attrString ? attrString + '.' : '') + attrName; + callback(attr, attrName, attrs, level, fullAttrString); + + if(exports.isValObject(attr)) return; + + if(isPlainObject(attr) && attrName !== 'impliedEdits') { + exports.crawl(attr, callback, level + 1, fullAttrString); + } + }); +}; + +/** Is object a value object (or a container object)? + * + * @param {object} obj + * @return {boolean} + * returns true for a valid value object and + * false for tree nodes in the attribute hierarchy + */ +exports.isValObject = function(obj) { + return obj && obj.valType !== undefined; +}; + +/** + * Find all data array attributes in a given trace object - including + * `arrayOk` attributes. + * + * @param {object} trace + * full trace object that contains a reference to `_module.attributes` + * + * @return {array} arrayAttributes + * list of array attributes for the given trace + */ +exports.findArrayAttributes = function(trace) { + var arrayAttributes = []; + var stack = []; + var isArrayStack = []; + var baseContainer, baseAttrName; + + function callback(attr, attrName, attrs, level) { + stack = stack.slice(0, level).concat([attrName]); + isArrayStack = isArrayStack.slice(0, level).concat([attr && attr._isLinkedToArray]); + + var splittableAttr = ( + attr && + (attr.valType === 'data_array' || attr.arrayOk === true) && + !(stack[level - 1] === 'colorbar' && (attrName === 'ticktext' || attrName === 'tickvals')) + ); + + // Manually exclude 'colorbar.tickvals' and 'colorbar.ticktext' for now + // which are declared as `valType: 'data_array'` but scale independently of + // the coordinate arrays. + // + // Down the road, we might want to add a schema field (e.g `uncorrelatedArray: true`) + // to distinguish attributes of the likes. + + if(!splittableAttr) return; + + crawlIntoTrace(baseContainer, 0, ''); + } + + function crawlIntoTrace(container, i, astrPartial) { + var item = container[stack[i]]; + var newAstrPartial = astrPartial + stack[i]; + if(i === stack.length - 1) { + if(Lib.isArrayOrTypedArray(item)) { + arrayAttributes.push(baseAttrName + newAstrPartial); + } + } + else { + if(isArrayStack[i]) { + if(Array.isArray(item)) { + for(var j = 0; j < item.length; j++) { + if(Lib.isPlainObject(item[j])) { + crawlIntoTrace(item[j], i + 1, newAstrPartial + '[' + j + '].'); + } + } + } + } + else if(Lib.isPlainObject(item)) { + crawlIntoTrace(item, i + 1, newAstrPartial + '.'); + } + } + } + + baseContainer = trace; + baseAttrName = ''; + exports.crawl(baseAttributes, callback); + if(trace._module && trace._module.attributes) { + exports.crawl(trace._module.attributes, callback); + } + + var transforms = trace.transforms; + if(transforms) { + for(var i = 0; i < transforms.length; i++) { + var transform = transforms[i]; + var module = transform._module; + + if(module) { + baseAttrName = 'transforms[' + i + '].'; + baseContainer = transform; + + exports.crawl(module.attributes, callback); + } + } + } + + return arrayAttributes; +}; + +/* + * Find the valObject for one attribute in an existing trace + * + * @param {object} trace + * full trace object that contains a reference to `_module.attributes` + * @param {object} parts + * an array of parts, like ['transforms', 1, 'value'] + * typically from nestedProperty(...).parts + * + * @return {object|false} + * the valObject for this attribute, or the last found parent + * in some cases the innermost valObject will not exist, for example + * `valType: 'any'` attributes where we might set a part of the attribute. + * In that case, stop at the deepest valObject we *do* find. + */ +exports.getTraceValObject = function(trace, parts) { + var head = parts[0]; + var i = 1; // index to start recursing from + var moduleAttrs, valObject; + + if(head === 'transforms') { + if(parts.length === 1) { + return baseAttributes.transforms; + } + var transforms = trace.transforms; + if(!Array.isArray(transforms) || !transforms.length) return false; + var tNum = parts[1]; + if(!isIndex(tNum) || tNum >= transforms.length) { + return false; + } + moduleAttrs = (Registry.transformsRegistry[transforms[tNum].type] || {}).attributes; + valObject = moduleAttrs && moduleAttrs[parts[2]]; + i = 3; // start recursing only inside the transform + } + else if(trace.type === 'area') { + valObject = polarAreaAttrs[head]; + } + else { + // first look in the module for this trace + // components have already merged their trace attributes in here + var _module = trace._module; + if(!_module) _module = (Registry.modules[trace.type || baseAttributes.type.dflt] || {})._module; + if(!_module) return false; + + moduleAttrs = _module.attributes; + valObject = moduleAttrs && moduleAttrs[head]; + + // then look in the subplot attributes + if(!valObject) { + var subplotModule = _module.basePlotModule; + if(subplotModule && subplotModule.attributes) { + valObject = subplotModule.attributes[head]; + } + } + + // finally look in the global attributes + if(!valObject) valObject = baseAttributes[head]; + } + + return recurseIntoValObject(valObject, parts, i); +}; + +/* + * Find the valObject for one layout attribute + * + * @param {array} parts + * an array of parts, like ['annotations', 1, 'x'] + * typically from nestedProperty(...).parts + * + * @return {object|false} + * the valObject for this attribute, or the last found parent + * in some cases the innermost valObject will not exist, for example + * `valType: 'any'` attributes where we might set a part of the attribute. + * In that case, stop at the deepest valObject we *do* find. + */ +exports.getLayoutValObject = function(fullLayout, parts) { + var valObject = layoutHeadAttr(fullLayout, parts[0]); + + return recurseIntoValObject(valObject, parts, 1); +}; + +function layoutHeadAttr(fullLayout, head) { + var i, key, _module, attributes; + + // look for attributes of the subplot types used on the plot + var basePlotModules = fullLayout._basePlotModules; + if(basePlotModules) { + var out; + for(i = 0; i < basePlotModules.length; i++) { + _module = basePlotModules[i]; + if(_module.attrRegex && _module.attrRegex.test(head)) { + // if a module defines overrides, these take precedence + // initially this is to allow gl2d different editTypes from svg cartesian + if(_module.layoutAttrOverrides) return _module.layoutAttrOverrides; + + // otherwise take the first attributes we find + if(!out && _module.layoutAttributes) out = _module.layoutAttributes; + } + + // a module can also override the behavior of base (and component) module layout attrs + // again see gl2d for initial use case + var baseOverrides = _module.baseLayoutAttrOverrides; + if(baseOverrides && head in baseOverrides) return baseOverrides[head]; + } + if(out) return out; + } + + // look for layout attributes contributed by traces on the plot + var modules = fullLayout._modules; + if(modules) { + for(i = 0; i < modules.length; i++) { + attributes = modules[i].layoutAttributes; + if(attributes && head in attributes) { + return attributes[head]; + } + } + } + + /* + * Next look in components. + * Components that define a schema have already merged this into + * base and subplot attribute defs, so ignore these. + * Others (older style) all put all their attributes + * inside a container matching the module `name` + * eg `attributes` (array) or `legend` (object) + */ + for(key in Registry.componentsRegistry) { + _module = Registry.componentsRegistry[key]; + if(!_module.schema && (head === _module.name)) { + return _module.layoutAttributes; + } + } + + if(head in baseLayoutAttributes) return baseLayoutAttributes[head]; + + // Polar doesn't populate _modules or _basePlotModules + // just fall back on these when the others fail + if(head === 'radialaxis' || head === 'angularaxis') { + return polarAxisAttrs[head]; + } + return polarAxisAttrs.layout[head] || false; +} + +function recurseIntoValObject(valObject, parts, i) { + if(!valObject) return false; + + if(valObject._isLinkedToArray) { + // skip array index, abort if we try to dive into an array without an index + if(isIndex(parts[i])) i++; + else if(i < parts.length) return false; + } + + // now recurse as far as we can. Occasionally we have an attribute + // setting an internal part below what's in the schema; just return + // the innermost schema item we find. + for(; i < parts.length; i++) { + var newValObject = valObject[parts[i]]; + if(isPlainObject(newValObject)) valObject = newValObject; + else break; + + if(i === parts.length - 1) break; + + if(valObject._isLinkedToArray) { + i++; + if(!isIndex(parts[i])) return false; + } + else if(valObject.valType === 'info_array') { + i++; + var index = parts[i]; + if(!isIndex(index)) return false; + + var items = valObject.items; + if(Array.isArray(items)) { + if(index >= items.length) return false; + if(valObject.dimensions === 2) { + i++; + if(parts.length === i) return valObject; + var index2 = parts[i]; + if(!isIndex(index2)) return false; + valObject = items[index][index2]; + } + else valObject = items[index]; + } + else { + valObject = items; + } + } + } + + return valObject; +} + +// note: this is different from Lib.isIndex, this one doesn't accept numeric +// strings, only actual numbers. +function isIndex(val) { + return val === Math.round(val) && val >= 0; +} + +function getTraceAttributes(type) { + var _module, basePlotModule; + + if(type === 'area') { + _module = { attributes: polarAreaAttrs }; + basePlotModule = {}; + } + else { + _module = Registry.modules[type]._module, + basePlotModule = _module.basePlotModule; + } + + var attributes = {}; + + // make 'type' the first attribute in the object + attributes.type = null; + + + var copyBaseAttributes = extendDeepAll({}, baseAttributes); + var copyModuleAttributes = extendDeepAll({}, _module.attributes); + + // prune global-level trace attributes that are already defined in a trace + exports.crawl(copyModuleAttributes, function(attr, attrName, attrs, level, fullAttrString) { + Lib.nestedProperty(copyBaseAttributes, fullAttrString).set(undefined); + // Prune undefined attributes + if(attr === undefined) Lib.nestedProperty(copyModuleAttributes, fullAttrString).set(undefined); + }); + + // base attributes (same for all trace types) + extendDeepAll(attributes, copyBaseAttributes); + + // module attributes + extendDeepAll(attributes, copyModuleAttributes); + + // subplot attributes + if(basePlotModule.attributes) { + extendDeepAll(attributes, basePlotModule.attributes); + } + + // 'type' gets overwritten by baseAttributes; reset it here + attributes.type = type; + + var out = { + meta: _module.meta || {}, + attributes: formatAttributes(attributes), + }; + + // trace-specific layout attributes + if(_module.layoutAttributes) { + var layoutAttributes = {}; + + extendDeepAll(layoutAttributes, _module.layoutAttributes); + out.layoutAttributes = formatAttributes(layoutAttributes); + } + + return out; +} + +function getLayoutAttributes() { + var layoutAttributes = {}; + var key, _module; + + // global layout attributes + extendDeepAll(layoutAttributes, baseLayoutAttributes); + + // add base plot module layout attributes + for(key in Registry.subplotsRegistry) { + _module = Registry.subplotsRegistry[key]; + + if(!_module.layoutAttributes) continue; + + if(Array.isArray(_module.attr)) { + for(var i = 0; i < _module.attr.length; i++) { + handleBasePlotModule(layoutAttributes, _module, _module.attr[i]); + } + } else { + var astr = _module.attr === 'subplot' ? _module.name : _module.attr; + handleBasePlotModule(layoutAttributes, _module, astr); + } + } + + // polar layout attributes + layoutAttributes = assignPolarLayoutAttrs(layoutAttributes); + + // add registered components layout attributes + for(key in Registry.componentsRegistry) { + _module = Registry.componentsRegistry[key]; + var schema = _module.schema; + + /* + * Components with defined schema have already been merged in at register time + * but a few components define attributes that apply only to xaxis + * not yaxis (rangeselector, rangeslider) - delete from y schema. + * Note that the input attributes for xaxis/yaxis are the same object + * so it's not possible to only add them to xaxis from the start. + * If we ever have such asymmetry the other way, or anywhere else, + * we will need to extend both this code and mergeComponentAttrsToSubplot + * (which will not find yaxis only for example) + */ + if(schema && (schema.subplots || schema.layout)) { + var subplots = schema.subplots; + if(subplots && subplots.xaxis && !subplots.yaxis) { + for(var xkey in subplots.xaxis) delete layoutAttributes.yaxis[xkey]; + } + } + // older style without schema need to be explicitly merged in now + else if(_module.layoutAttributes) { + insertAttrs(layoutAttributes, _module.layoutAttributes, _module.name); + } + } + + return { + layoutAttributes: formatAttributes(layoutAttributes) + }; +} + +function getTransformAttributes(type) { + var _module = Registry.transformsRegistry[type]; + var attributes = extendDeepAll({}, _module.attributes); + + // add registered components transform attributes + Object.keys(Registry.componentsRegistry).forEach(function(k) { + var _module = Registry.componentsRegistry[k]; + + if(_module.schema && _module.schema.transforms && _module.schema.transforms[type]) { + Object.keys(_module.schema.transforms[type]).forEach(function(v) { + insertAttrs(attributes, _module.schema.transforms[type][v], v); + }); + } + }); + + return { + attributes: formatAttributes(attributes) + }; +} + +function getFramesAttributes() { + var attrs = { + frames: Lib.extendDeepAll({}, frameAttributes) + }; + + formatAttributes(attrs); + + return attrs.frames; +} + +function formatAttributes(attrs) { + mergeValTypeAndRole(attrs); + formatArrayContainers(attrs); + stringify(attrs); + + return attrs; +} + +function mergeValTypeAndRole(attrs) { + + function makeSrcAttr(attrName) { + return { + valType: 'string', + + + editType: 'none' + }; + } + + function callback(attr, attrName, attrs) { + if(exports.isValObject(attr)) { + if(attr.valType === 'data_array') { + // all 'data_array' attrs have role 'data' + attr.role = 'data'; + // all 'data_array' attrs have a corresponding 'src' attr + attrs[attrName + 'src'] = makeSrcAttr(attrName); + } + else if(attr.arrayOk === true) { + // all 'arrayOk' attrs have a corresponding 'src' attr + attrs[attrName + 'src'] = makeSrcAttr(attrName); + } + } + else if(isPlainObject(attr)) { + // all attrs container objects get role 'object' + attr.role = 'object'; + } + } + + exports.crawl(attrs, callback); +} + +function formatArrayContainers(attrs) { + + function callback(attr, attrName, attrs) { + if(!attr) return; + + var itemName = attr[IS_LINKED_TO_ARRAY]; + + if(!itemName) return; + + delete attr[IS_LINKED_TO_ARRAY]; + + attrs[attrName] = { items: {} }; + attrs[attrName].items[itemName] = attr; + attrs[attrName].role = 'object'; + } + + exports.crawl(attrs, callback); +} + +// this can take around 10ms and should only be run from PlotSchema.get(), +// to ensure JSON.stringify(PlotSchema.get()) gives the intended result. +function stringify(attrs) { + function walk(attr) { + for(var k in attr) { + if(isPlainObject(attr[k])) { + walk(attr[k]); + } else if(Array.isArray(attr[k])) { + for(var i = 0; i < attr[k].length; i++) { + walk(attr[k][i]); + } + } else { + // as JSON.stringify(/test/) // => {} + if(attr[k] instanceof RegExp) { + attr[k] = attr[k].toString(); + } + } + } + } + + walk(attrs); +} + +function assignPolarLayoutAttrs(layoutAttributes) { + extendFlat(layoutAttributes, { + radialaxis: polarAxisAttrs.radialaxis, + angularaxis: polarAxisAttrs.angularaxis + }); + + extendFlat(layoutAttributes, polarAxisAttrs.layout); + + return layoutAttributes; +} + +function handleBasePlotModule(layoutAttributes, _module, astr) { + var np = Lib.nestedProperty(layoutAttributes, astr), + attrs = extendDeepAll({}, _module.layoutAttributes); + + attrs[IS_SUBPLOT_OBJ] = true; + np.set(attrs); +} + +function insertAttrs(baseAttrs, newAttrs, astr) { + var np = Lib.nestedProperty(baseAttrs, astr); + + np.set(extendDeepAll(np.get() || {}, newAttrs)); +} + +},{"../lib":696,"../plots/animation_attributes":739,"../plots/attributes":741,"../plots/frame_attributes":772,"../plots/layout_attributes":799,"../plots/polar/legacy/area_attributes":814,"../plots/polar/legacy/axis_attributes":815,"../registry":827,"./edit_types":727}],734:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../lib'); +var plotAttributes = _dereq_('../plots/attributes'); + +var TEMPLATEITEMNAME = 'templateitemname'; + +var templateAttrs = { + name: { + valType: 'string', + + editType: 'none', + + } +}; +templateAttrs[TEMPLATEITEMNAME] = { + valType: 'string', + + editType: 'calc', + +}; + +/** + * templatedArray: decorate an attributes object with templating (and array) + * properties. + * + * @param {string} name: the singular form of the array name. Sets + * `_isLinkedToArray` to this, so the schema knows to treat this as an array. + * @param {object} attrs: the item attributes. Since all callers are expected + * to be constructing this object on the spot, we mutate it here for + * performance, rather than extending a new object with it. + * + * @returns {object}: the decorated `attrs` object + */ +exports.templatedArray = function(name, attrs) { + attrs._isLinkedToArray = name; + attrs.name = templateAttrs.name; + attrs[TEMPLATEITEMNAME] = templateAttrs[TEMPLATEITEMNAME]; + return attrs; +}; + +/** + * traceTemplater: logic for matching traces to trace templates + * + * @param {object} dataTemplate: collection of {traceType: [{template}, ...]} + * ie each type the template applies to contains a list of template objects, + * to be provided cyclically to data traces of that type. + * + * @returns {object}: {newTrace}, a function: + * newTrace(traceIn): that takes the input traceIn, coerces its type, then + * uses that type to find the next template to apply. returns the output + * traceOut with template attached, ready to continue supplyDefaults. + */ +exports.traceTemplater = function(dataTemplate) { + var traceCounts = {}; + var traceType, typeTemplates; + + for(traceType in dataTemplate) { + typeTemplates = dataTemplate[traceType]; + if(Array.isArray(typeTemplates) && typeTemplates.length) { + traceCounts[traceType] = 0; + } + } + + function newTrace(traceIn) { + traceType = Lib.coerce(traceIn, {}, plotAttributes, 'type'); + var traceOut = {type: traceType, _template: null}; + if(traceType in traceCounts) { + typeTemplates = dataTemplate[traceType]; + // cycle through traces in the template set for this type + var typei = traceCounts[traceType] % typeTemplates.length; + traceCounts[traceType]++; + traceOut._template = typeTemplates[typei]; + } + else { + // TODO: anything we should do for types missing from the template? + // try to apply some other type? Or just bail as we do here? + // Actually I think yes, we should apply other types; would be nice + // if all scatter* could inherit from each other, and if histogram + // could inherit from bar, etc... but how to specify this? And do we + // compose them, or if a type is present require it to be complete? + // Actually this could apply to layout too - 3D annotations + // inheriting from 2D, axes of different types inheriting from each + // other... + } + return traceOut; + } + + return { + newTrace: newTrace + // TODO: function to figure out what's left & what didn't work + }; +}; + +/** + * newContainer: Create a new sub-container inside `container` and propagate any + * applicable template to it. If there's no template, still propagates + * `undefined` so relinkPrivate will not retain an old template! + * + * @param {object} container: the outer container, should already have _template + * if there *is* a template for this plot + * @param {string} name: the key of the new container to make + * @param {string} baseName: if applicable, a base attribute to take the + * template from, ie for xaxis3 the base would be xaxis + * + * @returns {object}: an object for inclusion _full*, empty except for the + * appropriate template piece + */ +exports.newContainer = function(container, name, baseName) { + var template = container._template; + var part = template && (template[name] || (baseName && template[baseName])); + if(!Lib.isPlainObject(part)) part = null; + + var out = container[name] = {_template: part}; + return out; +}; + +/** + * arrayTemplater: special logic for templating both defaults and specific items + * in a container array (annotations etc) + * + * @param {object} container: the outer container, should already have _template + * if there *is* a template for this plot + * @param {string} name: the name of the array to template (ie 'annotations') + * will be used to find default ('annotationdefaults' object) and specific + * ('annotations' array) template specs. + * @param {string} inclusionAttr: the attribute determining this item's + * inclusion in the output, usually 'visible' or 'enabled' + * + * @returns {object}: {newItem, defaultItems}, both functions: + * newItem(itemIn): create an output item, bare except for the correct + * template and name(s), as the base for supplyDefaults + * defaultItems(): to be called after all newItem calls, return any + * specific template items that have not already beeen included, + * also as bare output items ready for supplyDefaults. + */ +exports.arrayTemplater = function(container, name, inclusionAttr) { + var template = container._template; + var defaultsTemplate = template && template[arrayDefaultKey(name)]; + var templateItems = template && template[name]; + if(!Array.isArray(templateItems) || !templateItems.length) { + templateItems = []; + } + + var usedNames = {}; + + function newItem(itemIn) { + // include name and templateitemname in the output object for ALL + // container array items. Note: you could potentially use different + // name and templateitemname, if you're using one template to make + // another template. templateitemname would be the name in the original + // template, and name is the new "subclassed" item name. + var out = {name: itemIn.name, _input: itemIn}; + var templateItemName = out[TEMPLATEITEMNAME] = itemIn[TEMPLATEITEMNAME]; + + // no itemname: use the default template + if(!validItemName(templateItemName)) { + out._template = defaultsTemplate; + return out; + } + + // look for an item matching this itemname + // note these do not inherit from the default template, only the item. + for(var i = 0; i < templateItems.length; i++) { + var templateItem = templateItems[i]; + if(templateItem.name === templateItemName) { + // Note: it's OK to use a template item more than once + // but using it at least once will stop it from generating + // a default item at the end. + usedNames[templateItemName] = 1; + out._template = templateItem; + return out; + } + } + + // Didn't find a matching template item, so since this item is intended + // to only be modifications it's most likely broken. Hide it unless + // it's explicitly marked visible - in which case it gets NO template, + // not even the default. + out[inclusionAttr] = itemIn[inclusionAttr] || false; + // special falsy value we can look for in validateTemplate + out._template = false; + return out; + } + + function defaultItems() { + var out = []; + for(var i = 0; i < templateItems.length; i++) { + var templateItem = templateItems[i]; + var name = templateItem.name; + // only allow named items to be added as defaults, + // and only allow each name once + if(validItemName(name) && !usedNames[name]) { + var outi = { + _template: templateItem, + name: name, + _input: {_templateitemname: name} + }; + outi[TEMPLATEITEMNAME] = templateItem[TEMPLATEITEMNAME]; + out.push(outi); + usedNames[name] = 1; + } + } + return out; + } + + return { + newItem: newItem, + defaultItems: defaultItems + }; +}; + +function validItemName(name) { + return name && typeof name === 'string'; +} + +function arrayDefaultKey(name) { + var lastChar = name.length - 1; + if(name.charAt(lastChar) !== 's') { + Lib.warn('bad argument to arrayDefaultKey: ' + name); + } + return name.substr(0, name.length - 1) + 'defaults'; +} +exports.arrayDefaultKey = arrayDefaultKey; + +/** + * arrayEditor: helper for editing array items that may have come from + * template defaults (in which case they will not exist in the input yet) + * + * @param {object} parentIn: the input container (eg gd.layout) + * @param {string} containerStr: the attribute string for the container inside + * `parentIn`. + * @param {object} itemOut: the _full* item (eg gd._fullLayout.annotations[0]) + * that we'll be editing. Assumed to have been created by `arrayTemplater`. + * + * @returns {object}: {modifyBase, modifyItem, getUpdateObj, applyUpdate}, all functions: + * modifyBase(attr, value): Add an update that's *not* related to the item. + * `attr` is the full attribute string. + * modifyItem(attr, value): Add an update to the item. `attr` is just the + * portion of the attribute string inside the item. + * getUpdateObj(): Get the final constructed update object, to use in + * `restyle` or `relayout`. Also resets the update object in case this + * update was canceled. + * applyUpdate(attr, value): optionally add an update `attr: value`, + * then apply it to `parent` which should be the parent of `containerIn`, + * ie the object to which `containerStr` is the attribute string. + */ +exports.arrayEditor = function(parentIn, containerStr, itemOut) { + var lengthIn = (Lib.nestedProperty(parentIn, containerStr).get() || []).length; + var index = itemOut._index; + // Check that we are indeed off the end of this container. + // Otherwise a devious user could put a key `_templateitemname` in their + // own input and break lots of things. + var templateItemName = (index >= lengthIn) && (itemOut._input || {})._templateitemname; + if(templateItemName) index = lengthIn; + var itemStr = containerStr + '[' + index + ']'; + + var update; + function resetUpdate() { + update = {}; + if(templateItemName) { + update[itemStr] = {}; + update[itemStr][TEMPLATEITEMNAME] = templateItemName; + } + } + resetUpdate(); + + function modifyBase(attr, value) { + update[attr] = value; + } + + function modifyItem(attr, value) { + if(templateItemName) { + // we're making a new object: edit that object + Lib.nestedProperty(update[itemStr], attr).set(value); + } + else { + // we're editing an existing object: include *just* the edit + update[itemStr + '.' + attr] = value; + } + } + + function getUpdateObj() { + var updateOut = update; + resetUpdate(); + return updateOut; + } + + function applyUpdate(attr, value) { + if(attr) modifyItem(attr, value); + var updateToApply = getUpdateObj(); + for(var key in updateToApply) { + Lib.nestedProperty(parentIn, key).set(updateToApply[key]); + } + } + + return { + modifyBase: modifyBase, + modifyItem: modifyItem, + getUpdateObj: getUpdateObj, + applyUpdate: applyUpdate + }; +}; + +},{"../lib":696,"../plots/attributes":741}],735:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Registry = _dereq_('../registry'); +var Plots = _dereq_('../plots/plots'); + +var Lib = _dereq_('../lib'); +var clearGlCanvases = _dereq_('../lib/clear_gl_canvases'); + +var Color = _dereq_('../components/color'); +var Drawing = _dereq_('../components/drawing'); +var Titles = _dereq_('../components/titles'); +var ModeBar = _dereq_('../components/modebar'); + +var Axes = _dereq_('../plots/cartesian/axes'); +var alignmentConstants = _dereq_('../constants/alignment'); +var axisConstraints = _dereq_('../plots/cartesian/constraints'); +var enforceAxisConstraints = axisConstraints.enforce; +var cleanAxisConstraints = axisConstraints.clean; +var doAutoRange = _dereq_('../plots/cartesian/autorange').doAutoRange; + +exports.layoutStyles = function(gd) { + return Lib.syncOrAsync([Plots.doAutoMargin, lsInner], gd); +}; + +function overlappingDomain(xDomain, yDomain, domains) { + for(var i = 0; i < domains.length; i++) { + var existingX = domains[i][0], + existingY = domains[i][1]; + + if(existingX[0] >= xDomain[1] || existingX[1] <= xDomain[0]) { + continue; + } + if(existingY[0] < yDomain[1] && existingY[1] > yDomain[0]) { + return true; + } + } + return false; +} + +function lsInner(gd) { + var fullLayout = gd._fullLayout; + var gs = fullLayout._size; + var pad = gs.p; + var axList = Axes.list(gd, '', true); + var i, subplot, plotinfo, xa, ya; + + fullLayout._paperdiv.style({ + width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px', + height: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroHeight && !gd.layout.height) ? '100%' : fullLayout.height + 'px' + }) + .selectAll('.main-svg') + .call(Drawing.setSize, fullLayout.width, fullLayout.height); + gd._context.setBackground(gd, fullLayout.paper_bgcolor); + + exports.drawMainTitle(gd); + ModeBar.manage(gd); + + // _has('cartesian') means SVG specifically, not GL2D - but GL2D + // can still get here because it makes some of the SVG structure + // for shared features like selections. + if(!fullLayout._has('cartesian')) { + return gd._promises.length && Promise.all(gd._promises); + } + + function getLinePosition(ax, counterAx, side) { + var lwHalf = ax._lw / 2; + + if(ax._id.charAt(0) === 'x') { + if(!counterAx) return gs.t + gs.h * (1 - (ax.position || 0)) + (lwHalf % 1); + else if(side === 'top') return counterAx._offset - pad - lwHalf; + return counterAx._offset + counterAx._length + pad + lwHalf; + } + + if(!counterAx) return gs.l + gs.w * (ax.position || 0) + (lwHalf % 1); + else if(side === 'right') return counterAx._offset + counterAx._length + pad + lwHalf; + return counterAx._offset - pad - lwHalf; + } + + // some preparation of axis position info + for(i = 0; i < axList.length; i++) { + var ax = axList[i]; + + // reset scale in case the margins have changed + ax.setScale(); + + var counterAx = ax._anchorAxis; + + // clear axis line positions, to be set in the subplot loop below + ax._linepositions = {}; + + // stash crispRounded linewidth so we don't need to pass gd all over the place + ax._lw = Drawing.crispRound(gd, ax.linewidth, 1); + + // figure out the main axis line and main mirror line position. + // it's easier to follow the logic if we handle these separately from + // ax._linepositions, which are only used by mirror=allticks + // for non-main-subplot ticks, and mirror=all(ticks)? for zero line + // hiding logic + ax._mainLinePosition = getLinePosition(ax, counterAx, ax.side); + ax._mainMirrorPosition = (ax.mirror && counterAx) ? + getLinePosition(ax, counterAx, + alignmentConstants.OPPOSITE_SIDE[ax.side]) : null; + + // Figure out which subplot to draw ticks, labels, & axis lines on + // do this as a separate loop so we already have all the + // _mainAxis and _anchorAxis links set + ax._mainSubplot = findMainSubplot(ax, fullLayout); + } + + // figure out which backgrounds we need to draw, + // and in which layers to put them + var lowerBackgroundIDs = []; + var backgroundIds = []; + var lowerDomains = []; + // no need to draw background when paper and plot color are the same color, + // activate mode just for large splom (which benefit the most from this + // optimization), but this could apply to all cartesian subplots. + var noNeedForBg = ( + Color.opacity(fullLayout.paper_bgcolor) === 1 && + Color.opacity(fullLayout.plot_bgcolor) === 1 && + fullLayout.paper_bgcolor === fullLayout.plot_bgcolor + ); + + for(subplot in fullLayout._plots) { + plotinfo = fullLayout._plots[subplot]; + + if(plotinfo.mainplot) { + // mainplot is a reference to the main plot this one is overlaid on + // so if it exists, this is an overlaid plot and we don't need to + // give it its own background + if(plotinfo.bg) { + plotinfo.bg.remove(); + } + plotinfo.bg = undefined; + } else { + var xDomain = plotinfo.xaxis.domain; + var yDomain = plotinfo.yaxis.domain; + var plotgroup = plotinfo.plotgroup; + + if(overlappingDomain(xDomain, yDomain, lowerDomains)) { + var pgNode = plotgroup.node(); + var plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); + pgNode.insertBefore(plotgroupBg.node(), pgNode.childNodes[0]); + backgroundIds.push(subplot); + } else { + plotgroup.select('rect.bg').remove(); + lowerDomains.push([xDomain, yDomain]); + if(!noNeedForBg) { + lowerBackgroundIDs.push(subplot); + backgroundIds.push(subplot); + } + } + } + } + + // now create all the lower-layer backgrounds at once now that + // we have the list of subplots that need them + var lowerBackgrounds = fullLayout._bgLayer.selectAll('.bg') + .data(lowerBackgroundIDs); + + lowerBackgrounds.enter().append('rect') + .classed('bg', true); + + lowerBackgrounds.exit().remove(); + + lowerBackgrounds.each(function(subplot) { + fullLayout._plots[subplot].bg = d3.select(this); + }); + + // style all backgrounds + for(i = 0; i < backgroundIds.length; i++) { + plotinfo = fullLayout._plots[backgroundIds[i]]; + xa = plotinfo.xaxis; + ya = plotinfo.yaxis; + + if(plotinfo.bg) { + plotinfo.bg + .call(Drawing.setRect, + xa._offset - pad, ya._offset - pad, + xa._length + 2 * pad, ya._length + 2 * pad) + .call(Color.fill, fullLayout.plot_bgcolor) + .style('stroke-width', 0); + } + } + + if(!fullLayout._hasOnlyLargeSploms) { + for(subplot in fullLayout._plots) { + plotinfo = fullLayout._plots[subplot]; + xa = plotinfo.xaxis; + ya = plotinfo.yaxis; + + // Clip so that data only shows up on the plot area. + var clipId = plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot'; + + var plotClip = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipId, function(s) { + s.classed('plotclip', true) + .append('rect'); + }); + + plotinfo.clipRect = plotClip.select('rect').attr({ + width: xa._length, + height: ya._length + }); + + Drawing.setTranslate(plotinfo.plot, xa._offset, ya._offset); + + var plotClipId; + var layerClipId; + + if(plotinfo._hasClipOnAxisFalse) { + plotClipId = null; + layerClipId = clipId; + } else { + plotClipId = clipId; + layerClipId = null; + } + + Drawing.setClipUrl(plotinfo.plot, plotClipId); + + // stash layer clipId value (null or same as clipId) + // to DRY up Drawing.setClipUrl calls on trace-module and trace layers + // downstream + plotinfo.layerClipId = layerClipId; + } + } + + var xLinesXLeft, xLinesXRight, xLinesYBottom, xLinesYTop, + leftYLineWidth, rightYLineWidth; + var yLinesYBottom, yLinesYTop, yLinesXLeft, yLinesXRight, + connectYBottom, connectYTop; + var extraSubplot; + + function xLinePath(y) { + return 'M' + xLinesXLeft + ',' + y + 'H' + xLinesXRight; + } + + function xLinePathFree(y) { + return 'M' + xa._offset + ',' + y + 'h' + xa._length; + } + + function yLinePath(x) { + return 'M' + x + ',' + yLinesYTop + 'V' + yLinesYBottom; + } + + function yLinePathFree(x) { + return 'M' + x + ',' + ya._offset + 'v' + ya._length; + } + + function mainPath(ax, pathFn, pathFnFree) { + if(!ax.showline || subplot !== ax._mainSubplot) return ''; + if(!ax._anchorAxis) return pathFnFree(ax._mainLinePosition); + var out = pathFn(ax._mainLinePosition); + if(ax.mirror) out += pathFn(ax._mainMirrorPosition); + return out; + } + + for(subplot in fullLayout._plots) { + plotinfo = fullLayout._plots[subplot]; + xa = plotinfo.xaxis; + ya = plotinfo.yaxis; + + /* + * x lines get longer where they meet y lines, to make a crisp corner. + * The x lines get the padding (margin.pad) plus the y line width to + * fill up the corner nicely. Free x lines are excluded - they always + * span exactly the data area of the plot + * + * | XXXXX + * | XXXXX + * | + * +------ + * x1 + * ----- + * x2 + */ + var xPath = 'M0,0'; + if(shouldShowLinesOrTicks(xa, subplot)) { + leftYLineWidth = findCounterAxisLineWidth(xa, 'left', ya, axList); + xLinesXLeft = xa._offset - (leftYLineWidth ? (pad + leftYLineWidth) : 0); + rightYLineWidth = findCounterAxisLineWidth(xa, 'right', ya, axList); + xLinesXRight = xa._offset + xa._length + (rightYLineWidth ? (pad + rightYLineWidth) : 0); + xLinesYBottom = getLinePosition(xa, ya, 'bottom'); + xLinesYTop = getLinePosition(xa, ya, 'top'); + + // save axis line positions for extra ticks to reference + // each subplot that gets ticks from "allticks" gets an entry: + // [left or bottom, right or top] + extraSubplot = (!xa._anchorAxis || subplot !== xa._mainSubplot); + if(extraSubplot && (xa.mirror === 'allticks' || xa.mirror === 'all')) { + xa._linepositions[subplot] = [xLinesYBottom, xLinesYTop]; + } + + xPath = mainPath(xa, xLinePath, xLinePathFree); + if(extraSubplot && xa.showline && (xa.mirror === 'all' || xa.mirror === 'allticks')) { + xPath += xLinePath(xLinesYBottom) + xLinePath(xLinesYTop); + } + + plotinfo.xlines + .style('stroke-width', xa._lw + 'px') + .call(Color.stroke, xa.showline ? + xa.linecolor : 'rgba(0,0,0,0)'); + } + plotinfo.xlines.attr('d', xPath); + + /* + * y lines that meet x axes get longer only by margin.pad, because + * the x axes fill in the corner space. Free y axes, like free x axes, + * always span exactly the data area of the plot + * + * | | XXXX + * y2| y1| XXXX + * | | XXXX + * | + * +----- + */ + var yPath = 'M0,0'; + if(shouldShowLinesOrTicks(ya, subplot)) { + connectYBottom = findCounterAxisLineWidth(ya, 'bottom', xa, axList); + yLinesYBottom = ya._offset + ya._length + (connectYBottom ? pad : 0); + connectYTop = findCounterAxisLineWidth(ya, 'top', xa, axList); + yLinesYTop = ya._offset - (connectYTop ? pad : 0); + yLinesXLeft = getLinePosition(ya, xa, 'left'); + yLinesXRight = getLinePosition(ya, xa, 'right'); + + extraSubplot = (!ya._anchorAxis || subplot !== ya._mainSubplot); + if(extraSubplot && (ya.mirror === 'allticks' || ya.mirror === 'all')) { + ya._linepositions[subplot] = [yLinesXLeft, yLinesXRight]; + } + + yPath = mainPath(ya, yLinePath, yLinePathFree); + if(extraSubplot && ya.showline && (ya.mirror === 'all' || ya.mirror === 'allticks')) { + yPath += yLinePath(yLinesXLeft) + yLinePath(yLinesXRight); + } + + plotinfo.ylines + .style('stroke-width', ya._lw + 'px') + .call(Color.stroke, ya.showline ? + ya.linecolor : 'rgba(0,0,0,0)'); + } + plotinfo.ylines.attr('d', yPath); + } + + Axes.makeClipPaths(gd); + + return gd._promises.length && Promise.all(gd._promises); +} + +function findMainSubplot(ax, fullLayout) { + var subplotList = fullLayout._subplots; + var ids = subplotList.cartesian.concat(subplotList.gl2d || []); + var mockGd = {_fullLayout: fullLayout}; + + var isX = ax._id.charAt(0) === 'x'; + var anchorAx = ax._mainAxis._anchorAxis; + var mainSubplotID = ''; + var nextBestMainSubplotID = ''; + var anchorID = ''; + + // First try the main ID with the anchor + if(anchorAx) { + anchorID = anchorAx._mainAxis._id; + mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id); + } + + // Then look for a subplot with the counteraxis overlaying the anchor + // If that fails just use the first subplot including this axis + if(!mainSubplotID || !fullLayout._plots[mainSubplotID]) { + mainSubplotID = ''; + + for(var j = 0; j < ids.length; j++) { + var id = ids[j]; + var yIndex = id.indexOf('y'); + var idPart = isX ? id.substr(0, yIndex) : id.substr(yIndex); + var counterPart = isX ? id.substr(yIndex) : id.substr(0, yIndex); + + if(idPart === ax._id) { + if(!nextBestMainSubplotID) nextBestMainSubplotID = id; + var counterAx = Axes.getFromId(mockGd, counterPart); + if(anchorID && counterAx.overlaying === anchorID) { + mainSubplotID = id; + break; + } + } + } + } + + return mainSubplotID || nextBestMainSubplotID; +} + +function shouldShowLinesOrTicks(ax, subplot) { + return (ax.ticks || ax.showline) && + (subplot === ax._mainSubplot || ax.mirror === 'all' || ax.mirror === 'allticks'); +} + +/* + * should we draw a line on counterAx at this side of ax? + * It's assumed that counterAx is known to overlay the subplot we're working on + * but it may not be its main axis. + */ +function shouldShowLineThisSide(ax, side, counterAx) { + // does counterAx get a line at all? + if(!counterAx.showline || !counterAx._lw) return false; + + // are we drawing *all* lines for counterAx? + if(counterAx.mirror === 'all' || counterAx.mirror === 'allticks') return true; + + var anchorAx = counterAx._anchorAxis; + + // is this a free axis? free axes can only have a subplot side-line with all(ticks)? mirroring + if(!anchorAx) return false; + + // in order to handle cases where the user forgot to anchor this axis correctly + // (because its default anchor has the same domain on the relevant end) + // check whether the relevant position is the same. + var sideIndex = alignmentConstants.FROM_BL[side]; + if(counterAx.side === side) { + return anchorAx.domain[sideIndex] === ax.domain[sideIndex]; + } + return counterAx.mirror && anchorAx.domain[1 - sideIndex] === ax.domain[1 - sideIndex]; +} + +/* + * Is there another axis intersecting `side` end of `ax`? + * First look at `counterAx` (the axis for this subplot), + * then at all other potential counteraxes on or overlaying this subplot. + * Take the line width from the first one that has a line. + */ +function findCounterAxisLineWidth(ax, side, counterAx, axList) { + if(shouldShowLineThisSide(ax, side, counterAx)) { + return counterAx._lw; + } + for(var i = 0; i < axList.length; i++) { + var axi = axList[i]; + if(axi._mainAxis === counterAx._mainAxis && shouldShowLineThisSide(ax, side, axi)) { + return axi._lw; + } + } + return 0; +} + +exports.drawMainTitle = function(gd) { + var fullLayout = gd._fullLayout; + + Titles.draw(gd, 'gtitle', { + propContainer: fullLayout, + propName: 'title', + placeholder: fullLayout._dfltTitle.plot, + attributes: { + x: fullLayout.width / 2, + y: fullLayout._size.t / 2, + 'text-anchor': 'middle' + } + }); +}; + +exports.doTraceStyle = function(gd) { + var calcdata = gd.calcdata; + var editStyleCalls = []; + var i; + + for(i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var cd0 = cd[0] || {}; + var trace = cd0.trace || {}; + var _module = trace._module || {}; + + // See if we need to do arraysToCalcdata + // call it regardless of what change we made, in case + // supplyDefaults brought in an array that was already + // in gd.data but not in gd._fullData previously + var arraysToCalcdata = _module.arraysToCalcdata; + if(arraysToCalcdata) arraysToCalcdata(cd, trace); + + var editStyle = _module.editStyle; + if(editStyle) editStyleCalls.push({fn: editStyle, cd0: cd0}); + } + + if(editStyleCalls.length) { + for(i = 0; i < editStyleCalls.length; i++) { + var edit = editStyleCalls[i]; + edit.fn(gd, edit.cd0); + } + clearGlCanvases(gd); + exports.redrawReglTraces(gd); + } + + Plots.style(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + + return Plots.previousPromises(gd); +}; + +exports.doColorBars = function(gd) { + for(var i = 0; i < gd.calcdata.length; i++) { + var cdi0 = gd.calcdata[i][0]; + + if((cdi0.t || {}).cb) { + var trace = cdi0.trace, + cb = cdi0.t.cb; + + if(Registry.traceIs(trace, 'contour')) { + cb.line({ + width: trace.contours.showlines !== false ? + trace.line.width : 0, + dash: trace.line.dash, + color: trace.contours.coloring === 'line' ? + cb._opts.line.color : trace.line.color + }); + } + var moduleOpts = trace._module.colorbar; + var containerName = moduleOpts.container; + var opts = (containerName ? trace[containerName] : trace).colorbar; + cb.options(opts)(); + } + } + + return Plots.previousPromises(gd); +}; + +// force plot() to redo the layout and replot with the modified layout +exports.layoutReplot = function(gd) { + var layout = gd.layout; + gd.layout = undefined; + return Registry.call('plot', gd, '', layout); +}; + +exports.doLegend = function(gd) { + Registry.getComponentMethod('legend', 'draw')(gd); + return Plots.previousPromises(gd); +}; + +exports.doTicksRelayout = function(gd) { + Axes.doTicks(gd, 'redraw'); + + if(gd._fullLayout._hasOnlyLargeSploms) { + Registry.subplotsRegistry.splom.updateGrid(gd); + clearGlCanvases(gd); + exports.redrawReglTraces(gd); + } + + exports.drawMainTitle(gd); + return Plots.previousPromises(gd); +}; + +exports.doModeBar = function(gd) { + var fullLayout = gd._fullLayout; + + ModeBar.manage(gd); + + for(var i = 0; i < fullLayout._basePlotModules.length; i++) { + var updateFx = fullLayout._basePlotModules[i].updateFx; + if(updateFx) updateFx(gd); + } + + return Plots.previousPromises(gd); +}; + +exports.doCamera = function(gd) { + var fullLayout = gd._fullLayout; + var sceneIds = fullLayout._subplots.gl3d; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneLayout = fullLayout[sceneIds[i]]; + var scene = sceneLayout._scene; + + scene.setCamera(sceneLayout.camera); + } +}; + +exports.drawData = function(gd) { + var fullLayout = gd._fullLayout; + var calcdata = gd.calcdata; + var i; + + // remove old colorbars explicitly + for(i = 0; i < calcdata.length; i++) { + var trace = calcdata[i][0].trace; + if(trace.visible !== true || !trace._module.colorbar) { + fullLayout._infolayer.select('.cb' + trace.uid).remove(); + } + } + + clearGlCanvases(gd); + + // loop over the base plot modules present on graph + var basePlotModules = fullLayout._basePlotModules; + for(i = 0; i < basePlotModules.length; i++) { + basePlotModules[i].plot(gd); + } + + exports.redrawReglTraces(gd); + + // styling separate from drawing + Plots.style(gd); + + // show annotations and shapes + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('annotations', 'draw')(gd); + + // Mark the first render as complete + fullLayout._replotting = false; + + return Plots.previousPromises(gd); +}; + +// Draw (or redraw) all regl-based traces in one go, +// useful during drag and selection where buffers of targeted traces are updated, +// but all traces need to be redrawn following clearGlCanvases. +// +// Note that _module.plot for regl trace does NOT draw things +// on the canvas, they only update the buffers. +// Drawing is perform here. +// +// TODO try adding per-subplot option using gl.SCISSOR_TEST for +// non-overlaying, disjoint subplots. +// +// TODO try to include parcoords in here. +// https://github.com/plotly/plotly.js/issues/3069 +exports.redrawReglTraces = function(gd) { + var fullLayout = gd._fullLayout; + + if(fullLayout._has('regl')) { + var fullData = gd._fullData; + var cartesianIds = []; + var polarIds = []; + var i, sp; + + if(fullLayout._hasOnlyLargeSploms) { + fullLayout._splomGrid.draw(); + } + + // N.B. + // - Loop over fullData (not _splomScenes) to preserve splom trace-to-trace ordering + // - Fill list if subplot ids (instead of fullLayout._subplots) to handle cases where all traces + // of a given module are `visible !== true` + for(i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(trace.visible === true) { + if(trace.type === 'splom') { + fullLayout._splomScenes[trace.uid].draw(); + } else if(trace.type === 'scattergl') { + Lib.pushUnique(cartesianIds, trace.xaxis + trace.yaxis); + } else if(trace.type === 'scatterpolargl') { + Lib.pushUnique(polarIds, trace.subplot); + } + } + } + + for(i = 0; i < cartesianIds.length; i++) { + sp = fullLayout._plots[cartesianIds[i]]; + if(sp._scene) sp._scene.draw(); + } + + for(i = 0; i < polarIds.length; i++) { + sp = fullLayout[polarIds[i]]._subplot; + if(sp._scene) sp._scene.draw(); + } + } +}; + +exports.doAutoRangeAndConstraints = function(gd) { + var axList = Axes.list(gd, '', true); + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + cleanAxisConstraints(gd, ax); + doAutoRange(gd, ax); + } + + enforceAxisConstraints(gd); +}; + +// An initial paint must be completed before these components can be +// correctly sized and the whole plot re-margined. fullLayout._replotting must +// be set to false before these will work properly. +exports.finalDraw = function(gd) { + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('images', 'draw')(gd); + Registry.getComponentMethod('annotations', 'draw')(gd); + // TODO: rangesliders really belong in marginPushers but they need to be + // drawn after data - can we at least get the margin pushing part separated + // out and done earlier? + Registry.getComponentMethod('rangeslider', 'draw')(gd); + // TODO: rangeselector only needs to be here (in addition to drawMarginPushers) + // because the margins need to be fully determined before we can call + // autorange and update axis ranges (which rangeselector needs to know which + // button is active). Can we break out its automargin step from its draw step? + Registry.getComponentMethod('rangeselector', 'draw')(gd); +}; + +exports.drawMarginPushers = function(gd) { + Registry.getComponentMethod('legend', 'draw')(gd); + Registry.getComponentMethod('rangeselector', 'draw')(gd); + Registry.getComponentMethod('sliders', 'draw')(gd); + Registry.getComponentMethod('updatemenus', 'draw')(gd); +}; + +},{"../components/color":570,"../components/drawing":595,"../components/modebar":633,"../components/titles":661,"../constants/alignment":668,"../lib":696,"../lib/clear_gl_canvases":680,"../plots/cartesian/autorange":743,"../plots/cartesian/axes":744,"../plots/cartesian/constraints":752,"../plots/plots":808,"../registry":827,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],736:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../lib'); +var isPlainObject = Lib.isPlainObject; +var PlotSchema = _dereq_('./plot_schema'); +var Plots = _dereq_('../plots/plots'); +var plotAttributes = _dereq_('../plots/attributes'); +var Template = _dereq_('./plot_template'); +var dfltConfig = _dereq_('./plot_config'); + +/** + * Plotly.makeTemplate: create a template off an existing figure to reuse + * style attributes on other figures. + * + * Note: separated from the rest of templates because otherwise we get circular + * references due to PlotSchema. + * + * @param {object|DOM element} figure: The figure to base the template on + * should contain a trace array `figure.data` + * and a layout object `figure.layout` + * @returns {object} template: the extracted template - can then be used as + * `layout.template` in another figure. + */ +exports.makeTemplate = function(figure) { + figure = Lib.extendDeep({_context: dfltConfig}, {data: figure.data, layout: figure.layout}); + Plots.supplyDefaults(figure); + var data = figure.data || []; + var layout = figure.layout || {}; + // copy over a few items to help follow the schema + layout._basePlotModules = figure._fullLayout._basePlotModules; + layout._modules = figure._fullLayout._modules; + + var template = { + data: {}, + layout: {} + }; + + /* + * Note: we do NOT validate template values, we just take what's in the + * user inputs data and layout, not the validated values in fullData and + * fullLayout. Even if we were to validate here, there's no guarantee that + * these values would still be valid when applied to a new figure, which + * may contain different trace modes, different axes, etc. So it's + * important that when applying a template we still validate the template + * values, rather than just using them as defaults. + */ + + data.forEach(function(trace) { + // TODO: What if no style info is extracted for this trace. We may + // not want an empty object as the null value. + // TODO: allow transforms to contribute to templates? + // as it stands they are ignored, which may be for the best... + + var traceTemplate = {}; + walkStyleKeys(trace, traceTemplate, getTraceInfo.bind(null, trace)); + + var traceType = Lib.coerce(trace, {}, plotAttributes, 'type'); + var typeTemplates = template.data[traceType]; + if(!typeTemplates) typeTemplates = template.data[traceType] = []; + typeTemplates.push(traceTemplate); + }); + + walkStyleKeys(layout, template.layout, getLayoutInfo.bind(null, layout)); + + /* + * Compose the new template with an existing one to the same effect + * + * NOTE: there's a possibility of slightly different behavior: if the plot + * has an invalid value and the old template has a valid value for the same + * attribute, the plot will use the old template value but this routine + * will pull the invalid value (resulting in the original default). + * In the general case it's not possible to solve this with a single value, + * since valid options can be context-dependent. It could be solved with + * a *list* of values, but that would be huge complexity for little gain. + */ + delete template.layout.template; + var oldTemplate = layout.template; + if(isPlainObject(oldTemplate)) { + var oldLayoutTemplate = oldTemplate.layout; + + var i, traceType, oldTypeTemplates, oldTypeLen, typeTemplates, typeLen; + + if(isPlainObject(oldLayoutTemplate)) { + mergeTemplates(oldLayoutTemplate, template.layout); + } + var oldDataTemplate = oldTemplate.data; + if(isPlainObject(oldDataTemplate)) { + for(traceType in template.data) { + oldTypeTemplates = oldDataTemplate[traceType]; + if(Array.isArray(oldTypeTemplates)) { + typeTemplates = template.data[traceType]; + typeLen = typeTemplates.length; + oldTypeLen = oldTypeTemplates.length; + for(i = 0; i < typeLen; i++) { + mergeTemplates(oldTypeTemplates[i % oldTypeLen], typeTemplates[i]); + } + for(i = typeLen; i < oldTypeLen; i++) { + typeTemplates.push(Lib.extendDeep({}, oldTypeTemplates[i])); + } + } + } + for(traceType in oldDataTemplate) { + if(!(traceType in template.data)) { + template.data[traceType] = Lib.extendDeep([], oldDataTemplate[traceType]); + } + } + } + } + + return template; +}; + +function mergeTemplates(oldTemplate, newTemplate) { + // we don't care about speed here, just make sure we have a totally + // distinct object from the previous template + oldTemplate = Lib.extendDeep({}, oldTemplate); + + // sort keys so we always get annotationdefaults before annotations etc + // so arrayTemplater will work right + var oldKeys = Object.keys(oldTemplate).sort(); + var i, j; + + function mergeOne(oldVal, newVal, key) { + if(isPlainObject(newVal) && isPlainObject(oldVal)) { + mergeTemplates(oldVal, newVal); + } + else if(Array.isArray(newVal) && Array.isArray(oldVal)) { + // Note: omitted `inclusionAttr` from arrayTemplater here, + // it's irrelevant as we only want the resulting `_template`. + var templater = Template.arrayTemplater({_template: oldTemplate}, key); + for(j = 0; j < newVal.length; j++) { + var item = newVal[j]; + var oldItem = templater.newItem(item)._template; + if(oldItem) mergeTemplates(oldItem, item); + } + var defaultItems = templater.defaultItems(); + for(j = 0; j < defaultItems.length; j++) newVal.push(defaultItems[j]._template); + + // templateitemname only applies to receiving plots + for(j = 0; j < newVal.length; j++) delete newVal[j].templateitemname; + } + } + + for(i = 0; i < oldKeys.length; i++) { + var key = oldKeys[i]; + var oldVal = oldTemplate[key]; + if(key in newTemplate) { + mergeOne(oldVal, newTemplate[key], key); + } + else newTemplate[key] = oldVal; + + // if this is a base key from the old template (eg xaxis), look for + // extended keys (eg xaxis2) in the new template to merge into + if(getBaseKey(key) === key) { + for(var key2 in newTemplate) { + var baseKey2 = getBaseKey(key2); + if(key2 !== baseKey2 && baseKey2 === key && !(key2 in oldTemplate)) { + mergeOne(oldVal, newTemplate[key2], key); + } + } + } + } +} + +function getBaseKey(key) { + return key.replace(/[0-9]+$/, ''); +} + +function walkStyleKeys(parent, templateOut, getAttributeInfo, path, basePath) { + var pathAttr = basePath && getAttributeInfo(basePath); + for(var key in parent) { + var child = parent[key]; + var nextPath = getNextPath(parent, key, path); + var nextBasePath = getNextPath(parent, key, basePath); + var attr = getAttributeInfo(nextBasePath); + if(!attr) { + var baseKey = getBaseKey(key); + if(baseKey !== key) { + nextBasePath = getNextPath(parent, baseKey, basePath); + attr = getAttributeInfo(nextBasePath); + } + } + + // we'll get an attr if path starts with a valid part, then has an + // invalid ending. Make sure we got all the way to the end. + if(pathAttr && (pathAttr === attr)) continue; + + if(!attr || attr._noTemplating || + attr.valType === 'data_array' || + (attr.arrayOk && Array.isArray(child)) + ) { + continue; + } + + if(!attr.valType && isPlainObject(child)) { + walkStyleKeys(child, templateOut, getAttributeInfo, nextPath, nextBasePath); + } + else if(attr._isLinkedToArray && Array.isArray(child)) { + var dfltDone = false; + var namedIndex = 0; + var usedNames = {}; + for(var i = 0; i < child.length; i++) { + var item = child[i]; + if(isPlainObject(item)) { + var name = item.name; + if(name) { + if(!usedNames[name]) { + // named array items: allow all attributes except data arrays + walkStyleKeys(item, templateOut, getAttributeInfo, + getNextPath(child, namedIndex, nextPath), + getNextPath(child, namedIndex, nextBasePath)); + namedIndex++; + usedNames[name] = 1; + } + } + else if(!dfltDone) { + var dfltKey = Template.arrayDefaultKey(key); + var dfltPath = getNextPath(parent, dfltKey, path); + + // getAttributeInfo will fail if we try to use dfltKey directly. + // Instead put this item into the next array element, then + // pull it out and move it to dfltKey. + var pathInArray = getNextPath(child, namedIndex, nextPath); + walkStyleKeys(item, templateOut, getAttributeInfo, pathInArray, + getNextPath(child, namedIndex, nextBasePath)); + var itemPropInArray = Lib.nestedProperty(templateOut, pathInArray); + var dfltProp = Lib.nestedProperty(templateOut, dfltPath); + dfltProp.set(itemPropInArray.get()); + itemPropInArray.set(null); + + dfltDone = true; + } + } + } + } + else { + var templateProp = Lib.nestedProperty(templateOut, nextPath); + templateProp.set(child); + } + } +} + +function getLayoutInfo(layout, path) { + return PlotSchema.getLayoutValObject( + layout, Lib.nestedProperty({}, path).parts + ); +} + +function getTraceInfo(trace, path) { + return PlotSchema.getTraceValObject( + trace, Lib.nestedProperty({}, path).parts + ); +} + +function getNextPath(parent, key, path) { + var nextPath; + if(!path) nextPath = key; + else if(Array.isArray(parent)) nextPath = path + '[' + key + ']'; + else nextPath = path + '.' + key; + + return nextPath; +} + +/** + * validateTemplate: Test for consistency between the given figure and + * a template, either already included in the figure or given separately. + * Note that not every issue we identify here is necessarily a problem, + * it depends on what you're using the template for. + * + * @param {object|DOM element} figure: the plot, with {data, layout} members, + * to test the template against + * @param {Optional(object)} template: the template, with its own {data, layout}, + * to test. If omitted, we will look for a template already attached as the + * plot's `layout.template` attribute. + * + * @returns {array} array of error objects each containing: + * - {string} code + * error code ('missing', 'unused', 'reused', 'noLayout', 'noData') + * - {string} msg + * a full readable description of the issue. + */ +exports.validateTemplate = function(figureIn, template) { + var figure = Lib.extendDeep({}, { + _context: dfltConfig, + data: figureIn.data, + layout: figureIn.layout + }); + var layout = figure.layout || {}; + if(!isPlainObject(template)) template = layout.template || {}; + var layoutTemplate = template.layout; + var dataTemplate = template.data; + var errorList = []; + + figure.layout = layout; + figure.layout.template = template; + Plots.supplyDefaults(figure); + + var fullLayout = figure._fullLayout; + var fullData = figure._fullData; + + var layoutPaths = {}; + function crawlLayoutForContainers(obj, paths) { + for(var key in obj) { + if(key.charAt(0) !== '_' && isPlainObject(obj[key])) { + var baseKey = getBaseKey(key); + var nextPaths = []; + var i; + for(i = 0; i < paths.length; i++) { + nextPaths.push(getNextPath(obj, key, paths[i])); + if(baseKey !== key) nextPaths.push(getNextPath(obj, baseKey, paths[i])); + } + for(i = 0; i < nextPaths.length; i++) { + layoutPaths[nextPaths[i]] = 1; + } + crawlLayoutForContainers(obj[key], nextPaths); + } + } + } + + function crawlLayoutTemplateForContainers(obj, path) { + for(var key in obj) { + if(key.indexOf('defaults') === -1 && isPlainObject(obj[key])) { + var nextPath = getNextPath(obj, key, path); + if(layoutPaths[nextPath]) { + crawlLayoutTemplateForContainers(obj[key], nextPath); + } + else { + errorList.push({code: 'unused', path: nextPath}); + } + } + } + } + + if(!isPlainObject(layoutTemplate)) { + errorList.push({code: 'layout'}); + } + else { + crawlLayoutForContainers(fullLayout, ['layout']); + crawlLayoutTemplateForContainers(layoutTemplate, 'layout'); + } + + if(!isPlainObject(dataTemplate)) { + errorList.push({code: 'data'}); + } + else { + var typeCount = {}; + var traceType; + for(var i = 0; i < fullData.length; i++) { + var fullTrace = fullData[i]; + traceType = fullTrace.type; + typeCount[traceType] = (typeCount[traceType] || 0) + 1; + if(!fullTrace._fullInput._template) { + // this takes care of the case of traceType in the data but not + // the template + errorList.push({ + code: 'missing', + index: fullTrace._fullInput.index, + traceType: traceType + }); + } + } + for(traceType in dataTemplate) { + var templateCount = dataTemplate[traceType].length; + var dataCount = typeCount[traceType] || 0; + if(templateCount > dataCount) { + errorList.push({ + code: 'unused', + traceType: traceType, + templateCount: templateCount, + dataCount: dataCount + }); + } + else if(dataCount > templateCount) { + errorList.push({ + code: 'reused', + traceType: traceType, + templateCount: templateCount, + dataCount: dataCount + }); + } + } + } + + // _template: false is when someone tried to modify an array item + // but there was no template with matching name + function crawlForMissingTemplates(obj, path) { + for(var key in obj) { + if(key.charAt(0) === '_') continue; + var val = obj[key]; + var nextPath = getNextPath(obj, key, path); + if(isPlainObject(val)) { + if(Array.isArray(obj) && val._template === false && val.templateitemname) { + errorList.push({ + code: 'missing', + path: nextPath, + templateitemname: val.templateitemname + }); + } + crawlForMissingTemplates(val, nextPath); + } + else if(Array.isArray(val) && hasPlainObject(val)) { + crawlForMissingTemplates(val, nextPath); + } + } + } + crawlForMissingTemplates({data: fullData, layout: fullLayout}, ''); + + if(errorList.length) return errorList.map(format); +}; + +function hasPlainObject(arr) { + for(var i = 0; i < arr.length; i++) { + if(isPlainObject(arr[i])) return true; + } +} + +function format(opts) { + var msg; + switch(opts.code) { + case 'data': + msg = 'The template has no key data.'; + break; + case 'layout': + msg = 'The template has no key layout.'; + break; + case 'missing': + if(opts.path) { + msg = 'There are no templates for item ' + opts.path + + ' with name ' + opts.templateitemname; + } + else { + msg = 'There are no templates for trace ' + opts.index + + ', of type ' + opts.traceType + '.'; + } + break; + case 'unused': + if(opts.path) { + msg = 'The template item at ' + opts.path + + ' was not used in constructing the plot.'; + } + else if(opts.dataCount) { + msg = 'Some of the templates of type ' + opts.traceType + + ' were not used. The template has ' + opts.templateCount + + ' traces, the data only has ' + opts.dataCount + + ' of this type.'; + } + else { + msg = 'The template has ' + opts.templateCount + + ' traces of type ' + opts.traceType + + ' but there are none in the data.'; + } + break; + case 'reused': + msg = 'Some of the templates of type ' + opts.traceType + + ' were used more than once. The template has ' + + opts.templateCount + ' traces, the data has ' + + opts.dataCount + ' of this type.'; + break; + } + opts.msg = msg; + + return opts; +} + +},{"../lib":696,"../plots/attributes":741,"../plots/plots":808,"./plot_config":732,"./plot_schema":733,"./plot_template":734}],737:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var plotApi = _dereq_('./plot_api'); +var Lib = _dereq_('../lib'); + +var helpers = _dereq_('../snapshot/helpers'); +var toSVG = _dereq_('../snapshot/tosvg'); +var svgToImg = _dereq_('../snapshot/svgtoimg'); + +var attrs = { + format: { + valType: 'enumerated', + values: ['png', 'jpeg', 'webp', 'svg'], + dflt: 'png', + + }, + width: { + valType: 'number', + min: 1, + + }, + height: { + valType: 'number', + min: 1, + + }, + scale: { + valType: 'number', + min: 0, + dflt: 1, + + }, + setBackground: { + valType: 'any', + dflt: false, + + }, + imageDataOnly: { + valType: 'boolean', + dflt: false, + + } +}; + +var IMAGE_URL_PREFIX = /^data:image\/\w+;base64,/; + +/** Plotly.toImage + * + * @param {object | string | HTML div} gd + * can either be a data/layout/config object + * or an existing graph
+ * or an id to an existing graph
+ * @param {object} opts (see above) + * @return {promise} + */ +function toImage(gd, opts) { + opts = opts || {}; + + var data; + var layout; + var config; + + if(Lib.isPlainObject(gd)) { + data = gd.data || []; + layout = gd.layout || {}; + config = gd.config || {}; + } else { + gd = Lib.getGraphDiv(gd); + data = Lib.extendDeep([], gd.data); + layout = Lib.extendDeep({}, gd.layout); + config = gd._context; + } + + function isImpliedOrValid(attr) { + return !(attr in opts) || Lib.validate(opts[attr], attrs[attr]); + } + + if(!isImpliedOrValid('width') || !isImpliedOrValid('height')) { + throw new Error('Height and width should be pixel values.'); + } + + if(!isImpliedOrValid('format')) { + throw new Error('Image format is not jpeg, png, svg or webp.'); + } + + var fullOpts = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts, fullOpts, attrs, attr, dflt); + } + + var format = coerce('format'); + var width = coerce('width'); + var height = coerce('height'); + var scale = coerce('scale'); + var setBackground = coerce('setBackground'); + var imageDataOnly = coerce('imageDataOnly'); + + // put the cloned div somewhere off screen before attaching to DOM + var clonedGd = document.createElement('div'); + clonedGd.style.position = 'absolute'; + clonedGd.style.left = '-5000px'; + document.body.appendChild(clonedGd); + + // extend layout with image options + var layoutImage = Lib.extendFlat({}, layout); + if(width) layoutImage.width = width; + if(height) layoutImage.height = height; + + // extend config for static plot + var configImage = Lib.extendFlat({}, config, { + staticPlot: true, + setBackground: setBackground + }); + + var redrawFunc = helpers.getRedrawFunc(clonedGd); + + function wait() { + return new Promise(function(resolve) { + setTimeout(resolve, helpers.getDelay(clonedGd._fullLayout)); + }); + } + + function convert() { + return new Promise(function(resolve, reject) { + var svg = toSVG(clonedGd, format, scale); + var width = clonedGd._fullLayout.width; + var height = clonedGd._fullLayout.height; + + plotApi.purge(clonedGd); + document.body.removeChild(clonedGd); + + if(format === 'svg') { + if(imageDataOnly) { + return resolve(svg); + } else { + return resolve('data:image/svg+xml,' + encodeURIComponent(svg)); + } + } + + var canvas = document.createElement('canvas'); + canvas.id = Lib.randstr(); + + svgToImg({ + format: format, + width: width, + height: height, + scale: scale, + canvas: canvas, + svg: svg, + // ask svgToImg to return a Promise + // rather than EventEmitter + // leave EventEmitter for backward + // compatibility + promise: true + }) + .then(resolve) + .catch(reject); + }); + } + + function urlToImageData(url) { + if(imageDataOnly) { + return url.replace(IMAGE_URL_PREFIX, ''); + } else { + return url; + } + } + + return new Promise(function(resolve, reject) { + plotApi.plot(clonedGd, data, layoutImage, configImage) + .then(redrawFunc) + .then(wait) + .then(convert) + .then(function(url) { resolve(urlToImageData(url)); }) + .catch(function(err) { reject(err); }); + }); +} + +module.exports = toImage; + +},{"../lib":696,"../snapshot/helpers":831,"../snapshot/svgtoimg":833,"../snapshot/tosvg":835,"./plot_api":731}],738:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var Plots = _dereq_('../plots/plots'); +var PlotSchema = _dereq_('./plot_schema'); +var dfltConfig = _dereq_('./plot_config'); + +var isPlainObject = Lib.isPlainObject; +var isArray = Array.isArray; +var isArrayOrTypedArray = Lib.isArrayOrTypedArray; + +/** + * Validate a data array and layout object. + * + * @param {array} data + * @param {object} layout + * + * @return {array} array of error objects each containing: + * - {string} code + * error code ('object', 'array', 'schema', 'unused', 'invisible' or 'value') + * - {string} container + * container where the error occurs ('data' or 'layout') + * - {number} trace + * trace index of the 'data' container where the error occurs + * - {array} path + * nested path to the key that causes the error + * - {string} astr + * attribute string variant of 'path' compatible with Plotly.restyle and + * Plotly.relayout. + * - {string} msg + * error message (shown in console in logger config argument is enable) + */ +module.exports = function validate(data, layout) { + var schema = PlotSchema.get(); + var errorList = []; + var gd = {_context: Lib.extendFlat({}, dfltConfig)}; + + var dataIn, layoutIn; + + if(isArray(data)) { + gd.data = Lib.extendDeep([], data); + dataIn = data; + } + else { + gd.data = []; + dataIn = []; + errorList.push(format('array', 'data')); + } + + if(isPlainObject(layout)) { + gd.layout = Lib.extendDeep({}, layout); + layoutIn = layout; + } + else { + gd.layout = {}; + layoutIn = {}; + if(arguments.length > 1) { + errorList.push(format('object', 'layout')); + } + } + + // N.B. dataIn and layoutIn are in general not the same as + // gd.data and gd.layout after supplyDefaults as some attributes + // in gd.data and gd.layout (still) get mutated during this step. + + Plots.supplyDefaults(gd); + + var dataOut = gd._fullData, + len = dataIn.length; + + for(var i = 0; i < len; i++) { + var traceIn = dataIn[i], + base = ['data', i]; + + if(!isPlainObject(traceIn)) { + errorList.push(format('object', base)); + continue; + } + + var traceOut = dataOut[i], + traceType = traceOut.type, + traceSchema = schema.traces[traceType].attributes; + + // PlotSchema does something fancy with trace 'type', reset it here + // to make the trace schema compatible with Lib.validate. + traceSchema.type = { + valType: 'enumerated', + values: [traceType] + }; + + if(traceOut.visible === false && traceIn.visible !== false) { + errorList.push(format('invisible', base)); + } + + crawl(traceIn, traceOut, traceSchema, errorList, base); + + var transformsIn = traceIn.transforms, + transformsOut = traceOut.transforms; + + if(transformsIn) { + if(!isArray(transformsIn)) { + errorList.push(format('array', base, ['transforms'])); + } + + base.push('transforms'); + + for(var j = 0; j < transformsIn.length; j++) { + var path = ['transforms', j], + transformType = transformsIn[j].type; + + if(!isPlainObject(transformsIn[j])) { + errorList.push(format('object', base, path)); + continue; + } + + var transformSchema = schema.transforms[transformType] ? + schema.transforms[transformType].attributes : + {}; + + // add 'type' to transform schema to validate the transform type + transformSchema.type = { + valType: 'enumerated', + values: Object.keys(schema.transforms) + }; + + crawl(transformsIn[j], transformsOut[j], transformSchema, errorList, base, path); + } + } + } + + var layoutOut = gd._fullLayout, + layoutSchema = fillLayoutSchema(schema, dataOut); + + crawl(layoutIn, layoutOut, layoutSchema, errorList, 'layout'); + + // return undefined if no validation errors were found + return (errorList.length === 0) ? void(0) : errorList; +}; + +function crawl(objIn, objOut, schema, list, base, path) { + path = path || []; + + var keys = Object.keys(objIn); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + + // transforms are handled separately + if(k === 'transforms') continue; + + var p = path.slice(); + p.push(k); + + var valIn = objIn[k], + valOut = objOut[k]; + + var nestedSchema = getNestedSchema(schema, k); + var isInfoArray = (nestedSchema || {}).valType === 'info_array'; + var isColorscale = (nestedSchema || {}).valType === 'colorscale'; + var items = (nestedSchema || {}).items; + + if(!isInSchema(schema, k)) { + list.push(format('schema', base, p)); + } + else if(isPlainObject(valIn) && isPlainObject(valOut)) { + crawl(valIn, valOut, nestedSchema, list, base, p); + } + else if(isInfoArray && isArray(valIn)) { + if(valIn.length > valOut.length) { + list.push(format('unused', base, p.concat(valOut.length))); + } + var len = valOut.length; + var arrayItems = Array.isArray(items); + if(arrayItems) len = Math.min(len, items.length); + var m, n, item, valInPart, valOutPart; + if(nestedSchema.dimensions === 2) { + for(n = 0; n < len; n++) { + if(isArray(valIn[n])) { + if(valIn[n].length > valOut[n].length) { + list.push(format('unused', base, p.concat(n, valOut[n].length))); + } + var len2 = valOut[n].length; + for(m = 0; m < (arrayItems ? Math.min(len2, items[n].length) : len2); m++) { + item = arrayItems ? items[n][m] : items; + valInPart = valIn[n][m]; + valOutPart = valOut[n][m]; + if(!Lib.validate(valInPart, item)) { + list.push(format('value', base, p.concat(n, m), valInPart)); + } + else if(valOutPart !== valInPart && valOutPart !== +valInPart) { + list.push(format('dynamic', base, p.concat(n, m), valInPart, valOutPart)); + } + } + } + else { + list.push(format('array', base, p.concat(n), valIn[n])); + } + } + } + else { + for(n = 0; n < len; n++) { + item = arrayItems ? items[n] : items; + valInPart = valIn[n]; + valOutPart = valOut[n]; + if(!Lib.validate(valInPart, item)) { + list.push(format('value', base, p.concat(n), valInPart)); + } + else if(valOutPart !== valInPart && valOutPart !== +valInPart) { + list.push(format('dynamic', base, p.concat(n), valInPart, valOutPart)); + } + } + } + } + else if(nestedSchema.items && !isInfoArray && isArray(valIn)) { + var _nestedSchema = items[Object.keys(items)[0]], + indexList = []; + + var j, _p; + + // loop over valOut items while keeping track of their + // corresponding input container index (given by _index) + for(j = 0; j < valOut.length; j++) { + var _index = valOut[j]._index || j; + + _p = p.slice(); + _p.push(_index); + + if(isPlainObject(valIn[_index]) && isPlainObject(valOut[j])) { + indexList.push(_index); + var valInj = valIn[_index]; + var valOutj = valOut[j]; + if(isPlainObject(valInj) && valInj.visible !== false && valOutj.visible === false) { + list.push(format('invisible', base, _p)); + } + else crawl(valInj, valOutj, _nestedSchema, list, base, _p); + } + } + + // loop over valIn to determine where it went wrong for some items + for(j = 0; j < valIn.length; j++) { + _p = p.slice(); + _p.push(j); + + if(!isPlainObject(valIn[j])) { + list.push(format('object', base, _p, valIn[j])); + } + else if(indexList.indexOf(j) === -1) { + list.push(format('unused', base, _p)); + } + } + } + else if(!isPlainObject(valIn) && isPlainObject(valOut)) { + list.push(format('object', base, p, valIn)); + } + else if(!isArrayOrTypedArray(valIn) && isArrayOrTypedArray(valOut) && !isInfoArray && !isColorscale) { + list.push(format('array', base, p, valIn)); + } + else if(!(k in objOut)) { + list.push(format('unused', base, p, valIn)); + } + else if(!Lib.validate(valIn, nestedSchema)) { + list.push(format('value', base, p, valIn)); + } + else if(nestedSchema.valType === 'enumerated' && + ((nestedSchema.coerceNumber && valIn !== +valOut) || valIn !== valOut) + ) { + list.push(format('dynamic', base, p, valIn, valOut)); + } + } + + return list; +} + +// the 'full' layout schema depends on the traces types presents +function fillLayoutSchema(schema, dataOut) { + var layoutSchema = schema.layout.layoutAttributes; + + for(var i = 0; i < dataOut.length; i++) { + var traceOut = dataOut[i]; + var traceSchema = schema.traces[traceOut.type]; + var traceLayoutAttr = traceSchema.layoutAttributes; + + if(traceLayoutAttr) { + if(traceOut.subplot) { + Lib.extendFlat(layoutSchema[traceSchema.attributes.subplot.dflt], traceLayoutAttr); + } else { + Lib.extendFlat(layoutSchema, traceLayoutAttr); + } + } + } + + return layoutSchema; +} + +// validation error codes +var code2msgFunc = { + object: function(base, astr) { + var prefix; + + if(base === 'layout' && astr === '') prefix = 'The layout argument'; + else if(base[0] === 'data' && astr === '') { + prefix = 'Trace ' + base[1] + ' in the data argument'; + } + else prefix = inBase(base) + 'key ' + astr; + + return prefix + ' must be linked to an object container'; + }, + array: function(base, astr) { + var prefix; + + if(base === 'data') prefix = 'The data argument'; + else prefix = inBase(base) + 'key ' + astr; + + return prefix + ' must be linked to an array container'; + }, + schema: function(base, astr) { + return inBase(base) + 'key ' + astr + ' is not part of the schema'; + }, + unused: function(base, astr, valIn) { + var target = isPlainObject(valIn) ? 'container' : 'key'; + + return inBase(base) + target + ' ' + astr + ' did not get coerced'; + }, + dynamic: function(base, astr, valIn, valOut) { + return [ + inBase(base) + 'key', + astr, + '(set to \'' + valIn + '\')', + 'got reset to', + '\'' + valOut + '\'', + 'during defaults.' + ].join(' '); + }, + invisible: function(base, astr) { + return ( + astr ? (inBase(base) + 'item ' + astr) : ('Trace ' + base[1]) + ) + ' got defaulted to be not visible'; + }, + value: function(base, astr, valIn) { + return [ + inBase(base) + 'key ' + astr, + 'is set to an invalid value (' + valIn + ')' + ].join(' '); + } +}; + +function inBase(base) { + if(isArray(base)) return 'In data trace ' + base[1] + ', '; + + return 'In ' + base + ', '; +} + +function format(code, base, path, valIn, valOut) { + path = path || ''; + + var container, trace; + + // container is either 'data' or 'layout + // trace is the trace index if 'data', null otherwise + + if(isArray(base)) { + container = base[0]; + trace = base[1]; + } + else { + container = base; + trace = null; + } + + var astr = convertPathToAttributeString(path); + var msg = code2msgFunc[code](base, astr, valIn, valOut); + + // log to console if logger config option is enabled + Lib.log(msg); + + return { + code: code, + container: container, + trace: trace, + path: path, + astr: astr, + msg: msg + }; +} + +function isInSchema(schema, key) { + var parts = splitKey(key), + keyMinusId = parts.keyMinusId, + id = parts.id; + + if((keyMinusId in schema) && schema[keyMinusId]._isSubplotObj && id) { + return true; + } + + return (key in schema); +} + +function getNestedSchema(schema, key) { + if(key in schema) return schema[key]; + + var parts = splitKey(key); + + return schema[parts.keyMinusId]; +} + +var idRegex = Lib.counterRegex('([a-z]+)'); + +function splitKey(key) { + var idMatch = key.match(idRegex); + + return { + keyMinusId: idMatch && idMatch[1], + id: idMatch && idMatch[2] + }; +} + +function convertPathToAttributeString(path) { + if(!isArray(path)) return String(path); + + var astr = ''; + + for(var i = 0; i < path.length; i++) { + var p = path[i]; + + if(typeof p === 'number') { + astr = astr.substr(0, astr.length - 1) + '[' + p + ']'; + } + else { + astr += p; + } + + if(i < path.length - 1) astr += '.'; + } + + return astr; +} + +},{"../lib":696,"../plots/plots":808,"./plot_config":732,"./plot_schema":733}],739:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + mode: { + valType: 'enumerated', + dflt: 'afterall', + + values: ['immediate', 'next', 'afterall'], + + }, + direction: { + valType: 'enumerated', + + values: ['forward', 'reverse'], + dflt: 'forward', + + }, + fromcurrent: { + valType: 'boolean', + dflt: false, + + + }, + frame: { + duration: { + valType: 'number', + + min: 0, + dflt: 500, + + }, + redraw: { + valType: 'boolean', + + dflt: true, + + }, + }, + transition: { + duration: { + valType: 'number', + + min: 0, + dflt: 500, + editType: 'none', + + }, + easing: { + valType: 'enumerated', + dflt: 'cubic-in-out', + values: [ + 'linear', + 'quad', + 'cubic', + 'sin', + 'exp', + 'circle', + 'elastic', + 'back', + 'bounce', + 'linear-in', + 'quad-in', + 'cubic-in', + 'sin-in', + 'exp-in', + 'circle-in', + 'elastic-in', + 'back-in', + 'bounce-in', + 'linear-out', + 'quad-out', + 'cubic-out', + 'sin-out', + 'exp-out', + 'circle-out', + 'elastic-out', + 'back-out', + 'bounce-out', + 'linear-in-out', + 'quad-in-out', + 'cubic-in-out', + 'sin-in-out', + 'exp-in-out', + 'circle-in-out', + 'elastic-in-out', + 'back-in-out', + 'bounce-in-out' + ], + + editType: 'none', + + }, + } +}; + +},{}],740:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var Template = _dereq_('../plot_api/plot_template'); + +/** Convenience wrapper for making array container logic DRY and consistent + * + * @param {object} parentObjIn + * user input object where the container in question is linked + * (i.e. either a user trace object or the user layout object) + * + * @param {object} parentObjOut + * full object where the coerced container will be linked + * (i.e. either a full trace object or the full layout object) + * + * @param {object} opts + * options object: + * - name {string} + * name of the key linking the container in question + * - inclusionAttr {string} + * name of the item attribute for inclusion/exclusion. Default is 'visible'. + * Since inclusion is true, use eg 'enabled' instead of 'disabled'. + * - handleItemDefaults {function} + * defaults method to be called on each item in the array container in question + * + * Its arguments are: + * - itemIn {object} item in user layout + * - itemOut {object} item in full layout + * - parentObj {object} (as in closure) + * - opts {object} (as in closure) + * N.B. + * + * - opts is passed to handleItemDefaults so it can also store + * links to supplementary data (e.g. fullData for layout components) + * + */ +module.exports = function handleArrayContainerDefaults(parentObjIn, parentObjOut, opts) { + var name = opts.name; + var inclusionAttr = opts.inclusionAttr || 'visible'; + + var previousContOut = parentObjOut[name]; + + var contIn = Lib.isArrayOrTypedArray(parentObjIn[name]) ? parentObjIn[name] : []; + var contOut = parentObjOut[name] = []; + var templater = Template.arrayTemplater(parentObjOut, name, inclusionAttr); + var i, itemOut; + + for(i = 0; i < contIn.length; i++) { + var itemIn = contIn[i]; + + if(!Lib.isPlainObject(itemIn)) { + itemOut = templater.newItem({}); + itemOut[inclusionAttr] = false; + } + else { + itemOut = templater.newItem(itemIn); + } + + itemOut._index = i; + + if(itemOut[inclusionAttr] !== false) { + opts.handleItemDefaults(itemIn, itemOut, parentObjOut, opts); + } + + contOut.push(itemOut); + } + + var defaultItems = templater.defaultItems(); + for(i = 0; i < defaultItems.length; i++) { + itemOut = defaultItems[i]; + itemOut._index = contOut.length; + opts.handleItemDefaults({}, itemOut, parentObjOut, opts, {}); + contOut.push(itemOut); + } + + // in case this array gets its defaults rebuilt independent of the whole layout, + // relink the private keys just for this array. + if(Lib.isArrayOrTypedArray(previousContOut)) { + var len = Math.min(previousContOut.length, contOut.length); + for(i = 0; i < len; i++) { + Lib.relinkPrivateKeys(contOut[i], previousContOut[i]); + } + } + + return contOut; +}; + +},{"../lib":696,"../plot_api/plot_template":734}],741:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fxAttrs = _dereq_('../components/fx/attributes'); + +module.exports = { + type: { + valType: 'enumerated', + + values: [], // listed dynamically + dflt: 'scatter', + editType: 'calc+clearAxisTypes', + _noTemplating: true // we handle this at a higher level + }, + visible: { + valType: 'enumerated', + values: [true, false, 'legendonly'], + + dflt: true, + editType: 'calc', + + }, + showlegend: { + valType: 'boolean', + + dflt: true, + editType: 'style', + + }, + legendgroup: { + valType: 'string', + + dflt: '', + editType: 'style', + + }, + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + editType: 'style', + + }, + name: { + valType: 'string', + + editType: 'style', + + }, + uid: { + valType: 'string', + + editType: 'plot' + }, + ids: { + valType: 'data_array', + editType: 'calc', + anim: true, + + }, + customdata: { + valType: 'data_array', + editType: 'calc', + + }, + + // N.B. these cannot be 'data_array' as they do not have the same length as + // other data arrays and arrayOk attributes in general + // + // Maybe add another valType: + // https://github.com/plotly/plotly.js/issues/1894 + selectedpoints: { + valType: 'any', + + editType: 'calc', + + }, + + hoverinfo: { + valType: 'flaglist', + + flags: ['x', 'y', 'z', 'text', 'name'], + extras: ['all', 'none', 'skip'], + arrayOk: true, + dflt: 'all', + editType: 'none', + + }, + hoverlabel: fxAttrs.hoverlabel, + stream: { + token: { + valType: 'string', + noBlank: true, + strict: true, + + editType: 'calc', + + }, + maxpoints: { + valType: 'number', + min: 0, + max: 10000, + dflt: 500, + + editType: 'calc', + + }, + editType: 'calc' + }, + transforms: { + _isLinkedToArray: 'transform', + editType: 'calc', + + } +}; + +},{"../components/fx/attributes":604}],742:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + xaxis: { + valType: 'subplotid', + + dflt: 'x', + editType: 'calc+clearAxisTypes', + + }, + yaxis: { + valType: 'subplotid', + + dflt: 'y', + editType: 'calc+clearAxisTypes', + + } +}; + +},{}],743:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var FP_SAFE = _dereq_('../../constants/numerical').FP_SAFE; + +module.exports = { + getAutoRange: getAutoRange, + makePadFn: makePadFn, + doAutoRange: doAutoRange, + findExtremes: findExtremes, + concatExtremes: concatExtremes +}; + +/** + * getAutoRange + * + * Collects all _extremes values corresponding to a given axis + * and computes its auto range. + * + * Note that getAutoRange uses return values from findExtremes. + * + * @param {object} gd: + * graph div object with filled-in fullData and fullLayout, in particular + * with filled-in '_extremes' containers: + * { + * val: calcdata value, + * pad: extra pixels beyond this value, + * extrapad: bool, does this point want 5% extra padding + * } + * @param {object} ax: + * full axis object, in particular with filled-in '_traceIndices' + * and '_annIndices' / '_shapeIndices' if applicable + * @return {array} + * an array of [min, max]. These are calcdata for log and category axes + * and data for linear and date axes. + * + * TODO: we want to change log to data as well, but it's hard to do this + * maintaining backward compatibility. category will always have to use calcdata + * though, because otherwise values between categories (or outside all categories) + * would be impossible. + */ +function getAutoRange(gd, ax) { + var i, j; + var newRange = []; + + var getPad = makePadFn(ax); + var extremes = concatExtremes(gd, ax); + var minArray = extremes.min; + var maxArray = extremes.max; + + if(minArray.length === 0 || maxArray.length === 0) { + return Lib.simpleMap(ax.range, ax.r2l); + } + + var minmin = minArray[0].val; + var maxmax = maxArray[0].val; + + for(i = 1; i < minArray.length; i++) { + if(minmin !== maxmax) break; + minmin = Math.min(minmin, minArray[i].val); + } + for(i = 1; i < maxArray.length; i++) { + if(minmin !== maxmax) break; + maxmax = Math.max(maxmax, maxArray[i].val); + } + + var axReverse = false; + + if(ax.range) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + axReverse = rng[1] < rng[0]; + } + // one-time setting to easily reverse the axis + // when plotting from code + if(ax.autorange === 'reversed') { + axReverse = true; + ax.autorange = true; + } + + var rangeMode = ax.rangemode; + var toZero = rangeMode === 'tozero'; + var nonNegative = rangeMode === 'nonnegative'; + var axLen = ax._length; + // don't allow padding to reduce the data to < 10% of the length + var minSpan = axLen / 10; + + var mbest = 0; + var minpt, maxpt, minbest, maxbest, dp, dv; + + for(i = 0; i < minArray.length; i++) { + minpt = minArray[i]; + for(j = 0; j < maxArray.length; j++) { + maxpt = maxArray[j]; + dv = maxpt.val - minpt.val; + if(dv > 0) { + dp = axLen - getPad(minpt) - getPad(maxpt); + if(dp > minSpan) { + if(dv / dp > mbest) { + minbest = minpt; + maxbest = maxpt; + mbest = dv / dp; + } + } + else if(dv / axLen > mbest) { + // in case of padding longer than the axis + // at least include the unpadded data values. + minbest = {val: minpt.val, pad: 0}; + maxbest = {val: maxpt.val, pad: 0}; + mbest = dv / axLen; + } + } + } + } + + function getMaxPad(prev, pt) { + return Math.max(prev, getPad(pt)); + } + + if(minmin === maxmax) { + var lower = minmin - 1; + var upper = minmin + 1; + if(toZero) { + if(minmin === 0) { + // The only value we have on this axis is 0, and we want to + // autorange so zero is one end. + // In principle this could be [0, 1] or [-1, 0] but usually + // 'tozero' pins 0 to the low end, so follow that. + newRange = [0, 1]; + } + else { + var maxPad = (minmin > 0 ? maxArray : minArray).reduce(getMaxPad, 0); + // we're pushing a single value away from the edge due to its + // padding, with the other end clamped at zero + // 0.5 means don't push it farther than the center. + var rangeEnd = minmin / (1 - Math.min(0.5, maxPad / axLen)); + newRange = minmin > 0 ? [0, rangeEnd] : [rangeEnd, 0]; + } + } else if(nonNegative) { + newRange = [Math.max(0, lower), Math.max(1, upper)]; + } else { + newRange = [lower, upper]; + } + } + else { + if(toZero) { + if(minbest.val >= 0) { + minbest = {val: 0, pad: 0}; + } + if(maxbest.val <= 0) { + maxbest = {val: 0, pad: 0}; + } + } + else if(nonNegative) { + if(minbest.val - mbest * getPad(minbest) < 0) { + minbest = {val: 0, pad: 0}; + } + if(maxbest.val <= 0) { + maxbest = {val: 1, pad: 0}; + } + } + + // in case it changed again... + mbest = (maxbest.val - minbest.val) / + (axLen - getPad(minbest) - getPad(maxbest)); + + newRange = [ + minbest.val - mbest * getPad(minbest), + maxbest.val + mbest * getPad(maxbest) + ]; + } + + // maintain reversal + if(axReverse) newRange.reverse(); + + return Lib.simpleMap(newRange, ax.l2r || Number); +} + +/* + * calculate the pixel padding for ax._min and ax._max entries with + * optional extrapad as 5% of the total axis length + */ +function makePadFn(ax) { + // 5% padding for points that specify extrapad: true + var extrappad = ax._length / 20; + + // domain-constrained axes: base extrappad on the unconstrained + // domain so it's consistent as the domain changes + if((ax.constrain === 'domain') && ax._inputDomain) { + extrappad *= (ax._inputDomain[1] - ax._inputDomain[0]) / + (ax.domain[1] - ax.domain[0]); + } + + return function getPad(pt) { return pt.pad + (pt.extrapad ? extrappad : 0); }; +} + +function concatExtremes(gd, ax) { + var axId = ax._id; + var fullData = gd._fullData; + var fullLayout = gd._fullLayout; + var minArray = []; + var maxArray = []; + var i, j, d; + + function _concat(cont, indices) { + for(i = 0; i < indices.length; i++) { + var item = cont[indices[i]]; + var extremes = (item._extremes || {})[axId]; + if(item.visible === true && extremes) { + for(j = 0; j < extremes.min.length; j++) { + d = extremes.min[j]; + collapseMinArray(minArray, d.val, d.pad, {extrapad: d.extrapad}); + } + for(j = 0; j < extremes.max.length; j++) { + d = extremes.max[j]; + collapseMaxArray(maxArray, d.val, d.pad, {extrapad: d.extrapad}); + } + } + } + } + + _concat(fullData, ax._traceIndices); + _concat(fullLayout.annotations || [], ax._annIndices || []); + _concat(fullLayout.shapes || [], ax._shapeIndices || []); + + return {min: minArray, max: maxArray}; +} + +function doAutoRange(gd, ax) { + if(!ax._length) ax.setScale(); + + var axIn; + + if(ax.autorange) { + ax.range = getAutoRange(gd, ax); + + ax._r = ax.range.slice(); + ax._rl = Lib.simpleMap(ax._r, ax.r2l); + + // doAutoRange will get called on fullLayout, + // but we want to report its results back to layout + + axIn = ax._input; + axIn.range = ax.range.slice(); + axIn.autorange = ax.autorange; + } + + if(ax._anchorAxis && ax._anchorAxis.rangeslider) { + var axeRangeOpts = ax._anchorAxis.rangeslider[ax._name]; + if(axeRangeOpts) { + if(axeRangeOpts.rangemode === 'auto') { + axeRangeOpts.range = getAutoRange(gd, ax); + } + } + axIn = ax._anchorAxis._input; + axIn.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts); + } +} + +/** + * findExtremes + * + * Find min/max extremes of an array of coordinates on a given axis. + * + * Note that findExtremes is called during `calc`, when we don't yet know the axis + * length; all the inputs should be based solely on the trace data, nothing + * about the axis layout. + * + * Note that `ppad` and `vpad` as well as their asymmetric variants refer to + * the before and after padding of the passed `data` array, not to the whole axis. + * + * @param {object} ax: full axis object + * relies on + * - ax.type + * - ax._m (just its sign) + * - ax.d2l + * @param {array} data: + * array of numbers (i.e. already run though ax.d2c) + * @param {object} options: + * available keys are: + * vpad: (number or number array) pad values (data value +-vpad) + * ppad: (number or number array) pad pixels (pixel location +-ppad) + * ppadplus, ppadminus, vpadplus, vpadminus: + * separate padding for each side, overrides symmetric + * padded: (boolean) add 5% padding to both ends + * (unless one end is overridden by tozero) + * tozero: (boolean) make sure to include zero if axis is linear, + * and make it a tight bound if possible + * + * @return {object} + * - min {array of objects} + * - max {array of objects} + * each object item has fields: + * - val {number} + * - pad {number} + * - extrappad {number} + */ +function findExtremes(ax, data, options) { + if(!options) options = {}; + if(!ax._m) ax.setScale(); + + var minArray = []; + var maxArray = []; + + var len = data.length; + var extrapad = options.padded || false; + var tozero = options.tozero && (ax.type === 'linear' || ax.type === '-'); + var isLog = ax.type === 'log'; + var hasArrayOption = false; + var i, v, di, dmin, dmax, ppadiplus, ppadiminus, vmin, vmax; + + function makePadAccessor(item) { + if(Array.isArray(item)) { + hasArrayOption = true; + return function(i) { return Math.max(Number(item[i]||0), 0); }; + } + else { + var v = Math.max(Number(item||0), 0); + return function() { return v; }; + } + } + + var ppadplus = makePadAccessor((ax._m > 0 ? + options.ppadplus : options.ppadminus) || options.ppad || 0); + var ppadminus = makePadAccessor((ax._m > 0 ? + options.ppadminus : options.ppadplus) || options.ppad || 0); + var vpadplus = makePadAccessor(options.vpadplus || options.vpad); + var vpadminus = makePadAccessor(options.vpadminus || options.vpad); + + if(!hasArrayOption) { + // with no arrays other than `data` we don't need to consider + // every point, only the extreme data points + vmin = Infinity; + vmax = -Infinity; + + if(isLog) { + for(i = 0; i < len; i++) { + v = data[i]; + // data is not linearized yet so we still have to filter out negative logs + if(v < vmin && v > 0) vmin = v; + if(v > vmax && v < FP_SAFE) vmax = v; + } + } else { + for(i = 0; i < len; i++) { + v = data[i]; + if(v < vmin && v > -FP_SAFE) vmin = v; + if(v > vmax && v < FP_SAFE) vmax = v; + } + } + + data = [vmin, vmax]; + len = 2; + } + + var collapseOpts = {tozero: tozero, extrapad: extrapad}; + + function addItem(i) { + di = data[i]; + if(!isNumeric(di)) return; + ppadiplus = ppadplus(i); + ppadiminus = ppadminus(i); + vmin = di - vpadminus(i); + vmax = di + vpadplus(i); + // special case for log axes: if vpad makes this object span + // more than an order of mag, clip it to one order. This is so + // we don't have non-positive errors or absurdly large lower + // range due to rounding errors + if(isLog && vmin < vmax / 10) vmin = vmax / 10; + + dmin = ax.c2l(vmin); + dmax = ax.c2l(vmax); + + if(tozero) { + dmin = Math.min(0, dmin); + dmax = Math.max(0, dmax); + } + if(goodNumber(dmin)) { + collapseMinArray(minArray, dmin, ppadiminus, collapseOpts); + } + if(goodNumber(dmax)) { + collapseMaxArray(maxArray, dmax, ppadiplus, collapseOpts); + } + } + + // For efficiency covering monotonic or near-monotonic data, + // check a few points at both ends first and then sweep + // through the middle + var iMax = Math.min(6, len); + for(i = 0; i < iMax; i++) addItem(i); + for(i = len - 1; i >= iMax; i--) addItem(i); + + return {min: minArray, max: maxArray}; +} + +function collapseMinArray(array, newVal, newPad, opts) { + collapseArray(array, newVal, newPad, opts, lessOrEqual); +} + +function collapseMaxArray(array, newVal, newPad, opts) { + collapseArray(array, newVal, newPad, opts, greaterOrEqual); +} + +/** + * collapseArray + * + * Takes items from 'array' and compares them to 'newVal', 'newPad'. + * + * @param {array} array: + * current set of min or max extremes + * @param {number} newVal: + * new value to compare against + * @param {number} newPad: + * pad value associated with 'newVal' + * @param {object} opts: + * - tozero {boolean} + * - extrapad {number} + * @param {function} atLeastAsExtreme: + * comparison function, use + * - lessOrEqual for min 'array' and + * - greaterOrEqual for max 'array' + * + * In practice, 'array' is either + * - 'extremes[ax._id].min' or + * - 'extremes[ax._id].max + * found in traces and layout items that affect autorange. + * + * Since we don't yet know the relationship between pixels and values + * (that's what we're trying to figure out!) AND we don't yet know how + * many pixels `extrapad` represents (it's going to be 5% of the length, + * but we don't want to have to redo calc just because length changed) + * two point must satisfy three criteria simultaneously for one to supersede the other: + * - at least as extreme a `val` + * - at least as big a `pad` + * - an unpadded point cannot supersede a padded point, but any other combination can + * + * Then: + * - If the item supersedes the new point, set includeThis false + * - If the new pt supersedes the item, delete it from 'array' + */ +function collapseArray(array, newVal, newPad, opts, atLeastAsExtreme) { + var tozero = opts.tozero; + var extrapad = opts.extrapad; + var includeThis = true; + + for(var j = 0; j < array.length && includeThis; j++) { + var v = array[j]; + if(atLeastAsExtreme(v.val, newVal) && v.pad >= newPad && (v.extrapad || !extrapad)) { + includeThis = false; + break; + } else if(atLeastAsExtreme(newVal, v.val) && v.pad <= newPad && (extrapad || !v.extrapad)) { + array.splice(j, 1); + j--; + } + } + if(includeThis) { + var clipAtZero = (tozero && newVal === 0); + array.push({ + val: newVal, + pad: clipAtZero ? 0 : newPad, + extrapad: clipAtZero ? false : extrapad + }); + } +} + +// In order to stop overflow errors, don't consider points +// too close to the limits of js floating point +function goodNumber(v) { + return isNumeric(v) && Math.abs(v) < FP_SAFE; +} + +function lessOrEqual(v0, v1) { return v0 <= v1; } +function greaterOrEqual(v0, v1) { return v0 >= v1; } + +},{"../../constants/numerical":673,"../../lib":696,"fast-isnumeric":214}],744:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); +var Plots = _dereq_('../../plots/plots'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var Titles = _dereq_('../../components/titles'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); + +var axAttrs = _dereq_('./layout_attributes'); +var cleanTicks = _dereq_('./clean_ticks'); + +var constants = _dereq_('../../constants/numerical'); +var ONEAVGYEAR = constants.ONEAVGYEAR; +var ONEAVGMONTH = constants.ONEAVGMONTH; +var ONEDAY = constants.ONEDAY; +var ONEHOUR = constants.ONEHOUR; +var ONEMIN = constants.ONEMIN; +var ONESEC = constants.ONESEC; +var MINUS_SIGN = constants.MINUS_SIGN; +var BADNUM = constants.BADNUM; + +var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT; +var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING; + +var axes = module.exports = {}; + +axes.setConvert = _dereq_('./set_convert'); +var autoType = _dereq_('./axis_autotype'); + +var axisIds = _dereq_('./axis_ids'); +axes.id2name = axisIds.id2name; +axes.name2id = axisIds.name2id; +axes.cleanId = axisIds.cleanId; +axes.list = axisIds.list; +axes.listIds = axisIds.listIds; +axes.getFromId = axisIds.getFromId; +axes.getFromTrace = axisIds.getFromTrace; + +var autorange = _dereq_('./autorange'); +axes.getAutoRange = autorange.getAutoRange; +axes.findExtremes = autorange.findExtremes; + +/* + * find the list of possible axes to reference with an xref or yref attribute + * and coerce it to that list + * + * attr: the attribute we're generating a reference for. Should end in 'x' or 'y' + * but can be prefixed, like 'ax' for annotation's arrow x + * dflt: the default to coerce to, or blank to use the first axis (falling back on + * extraOption if there is no axis) + * extraOption: aside from existing axes with this letter, what non-axis value is allowed? + * Only required if it's different from `dflt` + */ +axes.coerceRef = function(containerIn, containerOut, gd, attr, dflt, extraOption) { + var axLetter = attr.charAt(attr.length - 1); + var axlist = gd._fullLayout._subplots[axLetter + 'axis']; + var refAttr = attr + 'ref'; + var attrDef = {}; + + if(!dflt) dflt = axlist[0] || extraOption; + if(!extraOption) extraOption = dflt; + + // data-ref annotations are not supported in gl2d yet + + attrDef[refAttr] = { + valType: 'enumerated', + values: axlist.concat(extraOption ? [extraOption] : []), + dflt: dflt + }; + + // xref, yref + return Lib.coerce(containerIn, containerOut, attrDef, refAttr); +}; + +/* + * coerce position attributes (range-type) that can be either on axes or absolute + * (paper or pixel) referenced. The biggest complication here is that we don't know + * before looking at the axis whether the value must be a number or not (it may be + * a date string), so we can't use the regular valType='number' machinery + * + * axRef (string): the axis this position is referenced to, or: + * paper: fraction of the plot area + * pixel: pixels relative to some starting position + * attr (string): the attribute in containerOut we are coercing + * dflt (number): the default position, as a fraction or pixels. If the attribute + * is to be axis-referenced, this will be converted to an axis data value + * + * Also cleans the values, since the attribute definition itself has to say + * valType: 'any' to handle date axes. This allows us to accept: + * - for category axes: category names, and convert them here into serial numbers. + * Note that this will NOT work for axis range endpoints, because we don't know + * the category list yet (it's set by ax.makeCalcdata during calc) + * but it works for component (note, shape, images) positions. + * - for date axes: JS Dates or milliseconds, and convert to date strings + * - for other types: coerce them to numbers + */ +axes.coercePosition = function(containerOut, gd, coerce, axRef, attr, dflt) { + var cleanPos, pos; + + if(axRef === 'paper' || axRef === 'pixel') { + cleanPos = Lib.ensureNumber; + pos = coerce(attr, dflt); + } else { + var ax = axes.getFromId(gd, axRef); + dflt = ax.fraction2r(dflt); + pos = coerce(attr, dflt); + cleanPos = ax.cleanPos; + } + + containerOut[attr] = cleanPos(pos); +}; + +axes.cleanPosition = function(pos, gd, axRef) { + var cleanPos = (axRef === 'paper' || axRef === 'pixel') ? + Lib.ensureNumber : + axes.getFromId(gd, axRef).cleanPos; + + return cleanPos(pos); +}; + +var getDataConversions = axes.getDataConversions = function(gd, trace, target, targetArray) { + var ax; + + // If target points to an axis, use the type we already have for that + // axis to find the data type. Otherwise use the values to autotype. + var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ? + target : + targetArray; + + // In the case of an array target, make a mock data array + // and call supplyDefaults to the data type and + // setup the data-to-calc method. + if(Array.isArray(d2cTarget)) { + ax = { + type: autoType(targetArray), + _categories: [] + }; + axes.setConvert(ax); + + // build up ax._categories (usually done during ax.makeCalcdata() + if(ax.type === 'category') { + for(var i = 0; i < targetArray.length; i++) { + ax.d2c(targetArray[i]); + } + } + } else { + ax = axes.getFromTrace(gd, trace, d2cTarget); + } + + // if 'target' has corresponding axis + // -> use setConvert method + if(ax) return {d2c: ax.d2c, c2d: ax.c2d}; + + // special case for 'ids' + // -> cast to String + if(d2cTarget === 'ids') return {d2c: toString, c2d: toString}; + + // otherwise (e.g. numeric-array of 'marker.color' or 'marker.size') + // -> cast to Number + + return {d2c: toNum, c2d: toNum}; +}; + +function toNum(v) { return +v; } +function toString(v) { return String(v); } + +axes.getDataToCoordFunc = function(gd, trace, target, targetArray) { + return getDataConversions(gd, trace, target, targetArray).d2c; +}; + +// get counteraxis letter for this axis (name or id) +// this can also be used as the id for default counter axis +axes.counterLetter = function(id) { + var axLetter = id.charAt(0); + if(axLetter === 'x') return 'y'; + if(axLetter === 'y') return 'x'; +}; + +// incorporate a new minimum difference and first tick into +// forced +// note that _forceTick0 is linearized, so needs to be turned into +// a range value for setting tick0 +axes.minDtick = function(ax, newDiff, newFirst, allow) { + // doesn't make sense to do forced min dTick on log or category axes, + // and the plot itself may decide to cancel (ie non-grouped bars) + if(['log', 'category'].indexOf(ax.type) !== -1 || !allow) { + ax._minDtick = 0; + } + // undefined means there's nothing there yet + else if(ax._minDtick === undefined) { + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } + else if(ax._minDtick) { + // existing minDtick is an integer multiple of newDiff + // (within rounding err) + // and forceTick0 can be shifted to newFirst + if((ax._minDtick / newDiff + 1e-6) % 1 < 2e-6 && + (((newFirst - ax._forceTick0) / newDiff % 1) + + 1.000001) % 1 < 2e-6) { + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } + // if the converse is true (newDiff is a multiple of minDtick and + // newFirst can be shifted to forceTick0) then do nothing - same + // forcing stands. Otherwise, cancel forced minimum + else if((newDiff / ax._minDtick + 1e-6) % 1 > 2e-6 || + (((newFirst - ax._forceTick0) / ax._minDtick % 1) + + 1.000001) % 1 > 2e-6) { + ax._minDtick = 0; + } + } +}; + +// save a copy of the initial axis ranges in fullLayout +// use them in mode bar and dblclick events +axes.saveRangeInitial = function(gd, overwrite) { + var axList = axes.list(gd, '', true), + hasOneAxisChanged = false; + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + + var isNew = (ax._rangeInitial === undefined); + var hasChanged = ( + isNew || !( + ax.range[0] === ax._rangeInitial[0] && + ax.range[1] === ax._rangeInitial[1] + ) + ); + + if((isNew && ax.autorange === false) || (overwrite && hasChanged)) { + ax._rangeInitial = ax.range.slice(); + hasOneAxisChanged = true; + } + } + + return hasOneAxisChanged; +}; + +// save a copy of the initial spike visibility +axes.saveShowSpikeInitial = function(gd, overwrite) { + var axList = axes.list(gd, '', true), + hasOneAxisChanged = false, + allSpikesEnabled = 'on'; + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + + var isNew = (ax._showSpikeInitial === undefined); + var hasChanged = ( + isNew || !( + ax.showspikes === ax._showspikes + ) + ); + + if((isNew) || (overwrite && hasChanged)) { + ax._showSpikeInitial = ax.showspikes; + hasOneAxisChanged = true; + } + + if(allSpikesEnabled === 'on' && !ax.showspikes) { + allSpikesEnabled = 'off'; + } + } + gd._fullLayout._cartesianSpikesEnabled = allSpikesEnabled; + return hasOneAxisChanged; +}; + +axes.autoBin = function(data, ax, nbins, is2d, calendar, size) { + var dataMin = Lib.aggNums(Math.min, null, data); + var dataMax = Lib.aggNums(Math.max, null, data); + + if(ax.type === 'category') { + return { + start: dataMin - 0.5, + end: dataMax + 0.5, + size: Math.max(1, Math.round(size) || 1), + _dataSpan: dataMax - dataMin, + }; + } + + if(!calendar) calendar = ax.calendar; + + // piggyback off tick code to make "nice" bin sizes and edges + var dummyAx; + if(ax.type === 'log') { + dummyAx = { + type: 'linear', + range: [dataMin, dataMax] + }; + } + else { + dummyAx = { + type: ax.type, + range: Lib.simpleMap([dataMin, dataMax], ax.c2r, 0, calendar), + calendar: calendar + }; + } + axes.setConvert(dummyAx); + + size = size && cleanTicks.dtick(size, dummyAx.type); + + if(size) { + dummyAx.dtick = size; + dummyAx.tick0 = cleanTicks.tick0(undefined, dummyAx.type, calendar); + } + else { + var size0; + if(nbins) size0 = ((dataMax - dataMin) / nbins); + else { + // totally auto: scale off std deviation so the highest bin is + // somewhat taller than the total number of bins, but don't let + // the size get smaller than the 'nice' rounded down minimum + // difference between values + var distinctData = Lib.distinctVals(data); + var msexp = Math.pow(10, Math.floor( + Math.log(distinctData.minDiff) / Math.LN10)); + var minSize = msexp * Lib.roundUp( + distinctData.minDiff / msexp, [0.9, 1.9, 4.9, 9.9], true); + size0 = Math.max(minSize, 2 * Lib.stdev(data) / + Math.pow(data.length, is2d ? 0.25 : 0.4)); + + // fallback if ax.d2c output BADNUMs + // e.g. when user try to plot categorical bins + // on a layout.xaxis.type: 'linear' + if(!isNumeric(size0)) size0 = 1; + } + + axes.autoTicks(dummyAx, size0); + } + + + var finalSize = dummyAx.dtick; + var binStart = axes.tickIncrement( + axes.tickFirst(dummyAx), finalSize, 'reverse', calendar); + var binEnd, bincount; + + // check for too many data points right at the edges of bins + // (>50% within 1% of bin edges) or all data points integral + // and offset the bins accordingly + if(typeof finalSize === 'number') { + binStart = autoShiftNumericBins(binStart, data, dummyAx, dataMin, dataMax); + + bincount = 1 + Math.floor((dataMax - binStart) / finalSize); + binEnd = binStart + bincount * finalSize; + } + else { + // month ticks - should be the only nonlinear kind we have at this point. + // dtick (as supplied by axes.autoTick) only has nonlinear values on + // date and log axes, but even if you display a histogram on a log axis + // we bin it on a linear axis (which one could argue against, but that's + // a separate issue) + if(dummyAx.dtick.charAt(0) === 'M') { + binStart = autoShiftMonthBins(binStart, data, finalSize, dataMin, calendar); + } + + // calculate the endpoint for nonlinear ticks - you have to + // just increment until you're done + binEnd = binStart; + bincount = 0; + while(binEnd <= dataMax) { + binEnd = axes.tickIncrement(binEnd, finalSize, false, calendar); + bincount++; + } + } + + return { + start: ax.c2r(binStart, 0, calendar), + end: ax.c2r(binEnd, 0, calendar), + size: finalSize, + _dataSpan: dataMax - dataMin + }; +}; + + +function autoShiftNumericBins(binStart, data, ax, dataMin, dataMax) { + var edgecount = 0, + midcount = 0, + intcount = 0, + blankCount = 0; + + function nearEdge(v) { + // is a value within 1% of a bin edge? + return (1 + (v - binStart) * 100 / ax.dtick) % 100 < 2; + } + + for(var i = 0; i < data.length; i++) { + if(data[i] % 1 === 0) intcount++; + else if(!isNumeric(data[i])) blankCount++; + + if(nearEdge(data[i])) edgecount++; + if(nearEdge(data[i] + ax.dtick / 2)) midcount++; + } + var dataCount = data.length - blankCount; + + if(intcount === dataCount && ax.type !== 'date') { + // all integers: if bin size is <1, it's because + // that was specifically requested (large nbins) + // so respect that... but center the bins containing + // integers on those integers + if(ax.dtick < 1) { + binStart = dataMin - 0.5 * ax.dtick; + } + // otherwise start half an integer down regardless of + // the bin size, just enough to clear up endpoint + // ambiguity about which integers are in which bins. + else { + binStart -= 0.5; + if(binStart + ax.dtick < dataMin) binStart += ax.dtick; + } + } + else if(midcount < dataCount * 0.1) { + if(edgecount > dataCount * 0.3 || + nearEdge(dataMin) || nearEdge(dataMax)) { + // lots of points at the edge, not many in the middle + // shift half a bin + var binshift = ax.dtick / 2; + binStart += (binStart + binshift < dataMin) ? binshift : -binshift; + } + } + return binStart; +} + + +function autoShiftMonthBins(binStart, data, dtick, dataMin, calendar) { + var stats = Lib.findExactDates(data, calendar); + // number of data points that needs to be an exact value + // to shift that increment to (near) the bin center + var threshold = 0.8; + + if(stats.exactDays > threshold) { + var numMonths = Number(dtick.substr(1)); + + if((stats.exactYears > threshold) && (numMonths % 12 === 0)) { + // The exact middle of a non-leap-year is 1.5 days into July + // so if we start the bins here, all but leap years will + // get hover-labeled as exact years. + binStart = axes.tickIncrement(binStart, 'M6', 'reverse') + ONEDAY * 1.5; + } + else if(stats.exactMonths > threshold) { + // Months are not as clean, but if we shift half the *longest* + // month (31/2 days) then 31-day months will get labeled exactly + // and shorter months will get labeled with the correct month + // but shifted 12-36 hours into it. + binStart = axes.tickIncrement(binStart, 'M1', 'reverse') + ONEDAY * 15.5; + } + else { + // Shifting half a day is exact, but since these are month bins it + // will always give a somewhat odd-looking label, until we do something + // smarter like showing the bin boundaries (or the bounds of the actual + // data in each bin) + binStart -= ONEDAY / 2; + } + var nextBinStart = axes.tickIncrement(binStart, dtick); + + if(nextBinStart <= dataMin) return nextBinStart; + } + return binStart; +} + +// ---------------------------------------------------- +// Ticks and grids +// ---------------------------------------------------- + +// ensure we have tick0, dtick, and tick rounding calculated +axes.prepTicks = function(ax) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + + // calculate max number of (auto) ticks to display based on plot size + if(ax.tickmode === 'auto' || !ax.dtick) { + var nt = ax.nticks, + minPx; + if(!nt) { + if(ax.type === 'category') { + minPx = ax.tickfont ? (ax.tickfont.size || 12) * 1.2 : 15; + nt = ax._length / minPx; + } + else { + minPx = ax._id.charAt(0) === 'y' ? 40 : 80; + nt = Lib.constrain(ax._length / minPx, 4, 9) + 1; + } + + // radial axes span half their domain, + // multiply nticks value by two to get correct number of auto ticks. + if(ax._name === 'radialaxis') nt *= 2; + } + + // add a couple of extra digits for filling in ticks when we + // have explicit tickvals without tick text + if(ax.tickmode === 'array') nt *= 100; + + axes.autoTicks(ax, Math.abs(rng[1] - rng[0]) / nt); + // check for a forced minimum dtick + if(ax._minDtick > 0 && ax.dtick < ax._minDtick * 2) { + ax.dtick = ax._minDtick; + ax.tick0 = ax.l2r(ax._forceTick0); + } + } + + // check for missing tick0 + if(!ax.tick0) { + ax.tick0 = (ax.type === 'date') ? '2000-01-01' : 0; + } + + // ensure we don't try to make ticks below our minimum precision + // see https://github.com/plotly/plotly.js/issues/2892 + if(ax.type === 'date' && ax.dtick < 0.1) ax.dtick = 0.1; + + // now figure out rounding of tick values + autoTickRound(ax); +}; + +// calculate the ticks: text, values, positioning +// if ticks are set to automatic, determine the right values (tick0,dtick) +// in any case, set tickround to # of digits to round tick labels to, +// or codes to this effect for log and date scales +axes.calcTicks = function calcTicks(ax) { + axes.prepTicks(ax); + var rng = Lib.simpleMap(ax.range, ax.r2l); + + // now that we've figured out the auto values for formatting + // in case we're missing some ticktext, we can break out for array ticks + if(ax.tickmode === 'array') return arrayTicks(ax); + + // find the first tick + ax._tmin = axes.tickFirst(ax); + + // add a tiny bit so we get ticks which may have rounded out + var startTick = rng[0] * 1.0001 - rng[1] * 0.0001; + var endTick = rng[1] * 1.0001 - rng[0] * 0.0001; + // check for reversed axis + var axrev = (rng[1] < rng[0]); + + // No visible ticks? Quit. + // I've only seen this on category axes with all categories off the edge. + if((ax._tmin < startTick) !== axrev) return []; + + // return the full set of tick vals + var vals = []; + if(ax.type === 'category') { + endTick = (axrev) ? Math.max(-0.5, endTick) : + Math.min(ax._categories.length - 0.5, endTick); + } + + var xPrevious = null; + var maxTicks = Math.max(1000, ax._length || 0); + for(var x = ax._tmin; + (axrev) ? (x >= endTick) : (x <= endTick); + x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) { + // prevent infinite loops - no more than one tick per pixel, + // and make sure each value is different from the previous + if(vals.length > maxTicks || x === xPrevious) break; + xPrevious = x; + + vals.push(x); + } + + // If same angle over a full circle, the last tick vals is a duplicate. + // TODO must do something similar for angular date axes. + if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) { + vals.pop(); + } + + // save the last tick as well as first, so we can + // show the exponent only on the last one + ax._tmax = vals[vals.length - 1]; + + // for showing the rest of a date when the main tick label is only the + // latter part: ax._prevDateHead holds what we showed most recently. + // Start with it cleared and mark that we're in calcTicks (ie calculating a + // whole string of these so we should care what the previous date head was!) + ax._prevDateHead = ''; + ax._inCalcTicks = true; + + var ticksOut = new Array(vals.length); + for(var i = 0; i < vals.length; i++) ticksOut[i] = axes.tickText(ax, vals[i]); + + ax._inCalcTicks = false; + + return ticksOut; +}; + +function arrayTicks(ax) { + var vals = ax.tickvals, + text = ax.ticktext, + ticksOut = new Array(vals.length), + rng = Lib.simpleMap(ax.range, ax.r2l), + r0expanded = rng[0] * 1.0001 - rng[1] * 0.0001, + r1expanded = rng[1] * 1.0001 - rng[0] * 0.0001, + tickMin = Math.min(r0expanded, r1expanded), + tickMax = Math.max(r0expanded, r1expanded), + vali, + i, + j = 0; + + // without a text array, just format the given values as any other ticks + // except with more precision to the numbers + if(!Array.isArray(text)) text = []; + + // make sure showing ticks doesn't accidentally add new categories + var tickVal2l = ax.type === 'category' ? ax.d2l_noadd : ax.d2l; + + // array ticks on log axes always show the full number + // (if no explicit ticktext overrides it) + if(ax.type === 'log' && String(ax.dtick).charAt(0) !== 'L') { + ax.dtick = 'L' + Math.pow(10, Math.floor(Math.min(ax.range[0], ax.range[1])) - 1); + } + + for(i = 0; i < vals.length; i++) { + vali = tickVal2l(vals[i]); + if(vali > tickMin && vali < tickMax) { + if(text[i] === undefined) ticksOut[j] = axes.tickText(ax, vali); + else ticksOut[j] = tickTextObj(ax, vali, String(text[i])); + j++; + } + } + + if(j < vals.length) ticksOut.splice(j, vals.length - j); + + return ticksOut; +} + +var roundBase10 = [2, 5, 10], + roundBase24 = [1, 2, 3, 6, 12], + roundBase60 = [1, 2, 5, 10, 15, 30], + // 2&3 day ticks are weird, but need something btwn 1&7 + roundDays = [1, 2, 3, 7, 14], + // approx. tick positions for log axes, showing all (1) and just 1, 2, 5 (2) + // these don't have to be exact, just close enough to round to the right value + roundLog1 = [-0.046, 0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1], + roundLog2 = [-0.301, 0, 0.301, 0.699, 1], + // N.B. `thetaunit; 'radians' angular axes must be converted to degrees + roundAngles = [15, 30, 45, 90, 180]; + +function roundDTick(roughDTick, base, roundingSet) { + return base * Lib.roundUp(roughDTick / base, roundingSet); +} + +// autoTicks: calculate best guess at pleasant ticks for this axis +// inputs: +// ax - an axis object +// roughDTick - rough tick spacing (to be turned into a nice round number) +// outputs (into ax): +// tick0: starting point for ticks (not necessarily on the graph) +// usually 0 for numeric (=10^0=1 for log) or jan 1, 2000 for dates +// dtick: the actual, nice round tick spacing, usually a little larger than roughDTick +// if the ticks are spaced linearly (linear scale, categories, +// log with only full powers, date ticks < month), +// this will just be a number +// months: M# +// years: M# where # is 12*number of years +// log with linear ticks: L# where # is the linear tick spacing +// log showing powers plus some intermediates: +// D1 shows all digits, D2 shows 2 and 5 +axes.autoTicks = function(ax, roughDTick) { + var base; + + function getBase(v) { + return Math.pow(v, Math.floor(Math.log(roughDTick) / Math.LN10)); + } + + if(ax.type === 'date') { + ax.tick0 = Lib.dateTick0(ax.calendar); + // the criteria below are all based on the rough spacing we calculate + // being > half of the final unit - so precalculate twice the rough val + var roughX2 = 2 * roughDTick; + + if(roughX2 > ONEAVGYEAR) { + roughDTick /= ONEAVGYEAR; + base = getBase(10); + ax.dtick = 'M' + (12 * roundDTick(roughDTick, base, roundBase10)); + } + else if(roughX2 > ONEAVGMONTH) { + roughDTick /= ONEAVGMONTH; + ax.dtick = 'M' + roundDTick(roughDTick, 1, roundBase24); + } + else if(roughX2 > ONEDAY) { + ax.dtick = roundDTick(roughDTick, ONEDAY, roundDays); + // get week ticks on sunday + // this will also move the base tick off 2000-01-01 if dtick is + // 2 or 3 days... but that's a weird enough case that we'll ignore it. + ax.tick0 = Lib.dateTick0(ax.calendar, true); + } + else if(roughX2 > ONEHOUR) { + ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24); + } + else if(roughX2 > ONEMIN) { + ax.dtick = roundDTick(roughDTick, ONEMIN, roundBase60); + } + else if(roughX2 > ONESEC) { + ax.dtick = roundDTick(roughDTick, ONESEC, roundBase60); + } + else { + // milliseconds + base = getBase(10); + ax.dtick = roundDTick(roughDTick, base, roundBase10); + } + } + else if(ax.type === 'log') { + ax.tick0 = 0; + var rng = Lib.simpleMap(ax.range, ax.r2l); + + if(roughDTick > 0.7) { + // only show powers of 10 + ax.dtick = Math.ceil(roughDTick); + } + else if(Math.abs(rng[1] - rng[0]) < 1) { + // span is less than one power of 10 + var nt = 1.5 * Math.abs((rng[1] - rng[0]) / roughDTick); + + // ticks on a linear scale, labeled fully + roughDTick = Math.abs(Math.pow(10, rng[1]) - + Math.pow(10, rng[0])) / nt; + base = getBase(10); + ax.dtick = 'L' + roundDTick(roughDTick, base, roundBase10); + } + else { + // include intermediates between powers of 10, + // labeled with small digits + // ax.dtick = "D2" (show 2 and 5) or "D1" (show all digits) + ax.dtick = (roughDTick > 0.3) ? 'D2' : 'D1'; + } + } + else if(ax.type === 'category') { + ax.tick0 = 0; + ax.dtick = Math.ceil(Math.max(roughDTick, 1)); + } + else if(isAngular(ax)) { + ax.tick0 = 0; + base = 1; + ax.dtick = roundDTick(roughDTick, base, roundAngles); + } + else { + // auto ticks always start at 0 + ax.tick0 = 0; + base = getBase(10); + ax.dtick = roundDTick(roughDTick, base, roundBase10); + } + + // prevent infinite loops + if(ax.dtick === 0) ax.dtick = 1; + + // TODO: this is from log axis histograms with autorange off + if(!isNumeric(ax.dtick) && typeof ax.dtick !== 'string') { + var olddtick = ax.dtick; + ax.dtick = 1; + throw 'ax.dtick error: ' + String(olddtick); + } +}; + +// after dtick is already known, find tickround = precision +// to display in tick labels +// for numeric ticks, integer # digits after . to round to +// for date ticks, the last date part to show (y,m,d,H,M,S) +// or an integer # digits past seconds +function autoTickRound(ax) { + var dtick = ax.dtick; + + ax._tickexponent = 0; + if(!isNumeric(dtick) && typeof dtick !== 'string') { + dtick = 1; + } + + if(ax.type === 'category') { + ax._tickround = null; + } + if(ax.type === 'date') { + // If tick0 is unusual, give tickround a bit more information + // not necessarily *all* the information in tick0 though, if it's really odd + // minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19 + // take off a leading minus (year < 0) and i (intercalary month) so length is consistent + var tick0ms = ax.r2l(ax.tick0), + tick0str = ax.l2r(tick0ms).replace(/(^-|i)/g, ''), + tick0len = tick0str.length; + + if(String(dtick).charAt(0) === 'M') { + // any tick0 more specific than a year: alway show the full date + if(tick0len > 10 || tick0str.substr(5) !== '01-01') ax._tickround = 'd'; + // show the month unless ticks are full multiples of a year + else ax._tickround = (+(dtick.substr(1)) % 12 === 0) ? 'y' : 'm'; + } + else if((dtick >= ONEDAY && tick0len <= 10) || (dtick >= ONEDAY * 15)) ax._tickround = 'd'; + else if((dtick >= ONEMIN && tick0len <= 16) || (dtick >= ONEHOUR)) ax._tickround = 'M'; + else if((dtick >= ONESEC && tick0len <= 19) || (dtick >= ONEMIN)) ax._tickround = 'S'; + else { + // tickround is a number of digits of fractional seconds + // of any two adjacent ticks, at least one will have the maximum fractional digits + // of all possible ticks - so take the max. length of tick0 and the next one + var tick1len = ax.l2r(tick0ms + dtick).replace(/^-/, '').length; + ax._tickround = Math.max(tick0len, tick1len) - 20; + + // We shouldn't get here... but in case there's a situation I'm + // not thinking of where tick0str and tick1str are identical or + // something, fall back on maximum precision + if(ax._tickround < 0) ax._tickround = 4; + } + } + else if(isNumeric(dtick) || dtick.charAt(0) === 'L') { + // linear or log (except D1, D2) + var rng = ax.range.map(ax.r2d || Number); + if(!isNumeric(dtick)) dtick = Number(dtick.substr(1)); + // 2 digits past largest digit of dtick + ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); + + var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); + + var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); + if(Math.abs(rangeexp) > 3) { + if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) { + ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); + } + else ax._tickexponent = rangeexp; + } + } + // D1 or D2 (log) + else ax._tickround = null; +} + +// months and years don't have constant millisecond values +// (but a year is always 12 months so we only need months) +// log-scale ticks are also not consistently spaced, except +// for pure powers of 10 +// numeric ticks always have constant differences, other datetime ticks +// can all be calculated as constant number of milliseconds +axes.tickIncrement = function(x, dtick, axrev, calendar) { + var axSign = axrev ? -1 : 1; + + // includes linear, all dates smaller than month, and pure 10^n in log + if(isNumeric(dtick)) return x + axSign * dtick; + + // everything else is a string, one character plus a number + var tType = dtick.charAt(0), + dtSigned = axSign * Number(dtick.substr(1)); + + // Dates: months (or years - see Lib.incrementMonth) + if(tType === 'M') return Lib.incrementMonth(x, dtSigned, calendar); + + // Log scales: Linear, Digits + else if(tType === 'L') return Math.log(Math.pow(10, x) + dtSigned) / Math.LN10; + + // log10 of 2,5,10, or all digits (logs just have to be + // close enough to round) + else if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1, + x2 = x + axSign * 0.01, + frac = Lib.roundUp(Lib.mod(x2, 1), tickset, axrev); + + return Math.floor(x2) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } + else throw 'unrecognized dtick ' + String(dtick); +}; + +// calculate the first tick on an axis +axes.tickFirst = function(ax) { + var r2l = ax.r2l || Number, + rng = Lib.simpleMap(ax.range, r2l), + axrev = rng[1] < rng[0], + sRound = axrev ? Math.floor : Math.ceil, + // add a tiny extra bit to make sure we get ticks + // that may have been rounded out + r0 = rng[0] * 1.0001 - rng[1] * 0.0001, + dtick = ax.dtick, + tick0 = r2l(ax.tick0); + + if(isNumeric(dtick)) { + var tmin = sRound((r0 - tick0) / dtick) * dtick + tick0; + + // make sure no ticks outside the category list + if(ax.type === 'category') { + tmin = Lib.constrain(tmin, 0, ax._categories.length - 1); + } + return tmin; + } + + var tType = dtick.charAt(0), + dtNum = Number(dtick.substr(1)); + + // Dates: months (or years) + if(tType === 'M') { + var cnt = 0, + t0 = tick0, + t1, + mult, + newDTick; + + // This algorithm should work for *any* nonlinear (but close to linear!) + // tick spacing. Limit to 10 iterations, for gregorian months it's normally <=3. + while(cnt < 10) { + t1 = axes.tickIncrement(t0, dtick, axrev, ax.calendar); + if((t1 - r0) * (t0 - r0) <= 0) { + // t1 and t0 are on opposite sides of r0! we've succeeded! + if(axrev) return Math.min(t0, t1); + return Math.max(t0, t1); + } + mult = (r0 - ((t0 + t1) / 2)) / (t1 - t0); + newDTick = tType + ((Math.abs(Math.round(mult)) || 1) * dtNum); + t0 = axes.tickIncrement(t0, newDTick, mult < 0 ? !axrev : axrev, ax.calendar); + cnt++; + } + Lib.error('tickFirst did not converge', ax); + return t0; + } + + // Log scales: Linear, Digits + else if(tType === 'L') { + return Math.log(sRound( + (Math.pow(10, r0) - tick0) / dtNum) * dtNum + tick0) / Math.LN10; + } + else if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1, + frac = Lib.roundUp(Lib.mod(r0, 1), tickset, axrev); + + return Math.floor(r0) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } + else throw 'unrecognized dtick ' + String(dtick); +}; + +// draw the text for one tick. +// px,py are the location on gd.paper +// prefix is there so the x axis ticks can be dropped a line +// ax is the axis layout, x is the tick value +// hover is a (truthy) flag for whether to show numbers with a bit +// more precision for hovertext +axes.tickText = function(ax, x, hover) { + var out = tickTextObj(ax, x), + hideexp, + arrayMode = ax.tickmode === 'array', + extraPrecision = hover || arrayMode, + i, + tickVal2l = ax.type === 'category' ? ax.d2l_noadd : ax.d2l; + + if(arrayMode && Array.isArray(ax.ticktext)) { + var rng = Lib.simpleMap(ax.range, ax.r2l), + minDiff = Math.abs(rng[1] - rng[0]) / 10000; + for(i = 0; i < ax.ticktext.length; i++) { + if(Math.abs(x - tickVal2l(ax.tickvals[i])) < minDiff) break; + } + if(i < ax.ticktext.length) { + out.text = String(ax.ticktext[i]); + return out; + } + } + + function isHidden(showAttr) { + var first_or_last; + + if(showAttr === undefined) return true; + if(hover) return showAttr === 'none'; + + first_or_last = { + first: ax._tmin, + last: ax._tmax + }[showAttr]; + + return showAttr !== 'all' && x !== first_or_last; + } + + if(hover) { + hideexp = 'never'; + } else { + hideexp = ax.exponentformat !== 'none' && isHidden(ax.showexponent) ? 'hide' : ''; + } + + if(ax.type === 'date') formatDate(ax, out, hover, extraPrecision); + else if(ax.type === 'log') formatLog(ax, out, hover, extraPrecision, hideexp); + else if(ax.type === 'category') formatCategory(ax, out); + else if(isAngular(ax)) formatAngle(ax, out, hover, extraPrecision, hideexp); + else formatLinear(ax, out, hover, extraPrecision, hideexp); + + // add prefix and suffix + if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; + if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; + + return out; +}; + +/** + * create text for a hover label on this axis, with special handling of + * log axes (where negative values can't be displayed but can appear in hover text) + * + * @param {object} ax: the axis to format text for + * @param {number} val: calcdata value to format + * @param {Optional(number)} val2: a second value to display + * + * @returns {string} `val` formatted as a string appropriate to this axis, or + * `val` and `val2` as a range (ie ' - ') if `val2` is provided and + * it's different from `val`. + */ +axes.hoverLabelText = function(ax, val, val2) { + if(val2 !== BADNUM && val2 !== val) { + return axes.hoverLabelText(ax, val) + ' - ' + axes.hoverLabelText(ax, val2); + } + + var logOffScale = (ax.type === 'log' && val <= 0); + var tx = axes.tickText(ax, ax.c2l(logOffScale ? -val : val), 'hover').text; + + if(logOffScale) { + return val === 0 ? '0' : MINUS_SIGN + tx; + } + + // TODO: should we do something special if the axis calendar and + // the data calendar are different? Somehow display both dates with + // their system names? Right now it will just display in the axis calendar + // but users could add the other one as text. + return tx; +}; + +function tickTextObj(ax, x, text) { + var tf = ax.tickfont || {}; + + return { + x: x, + dx: 0, + dy: 0, + text: text || '', + fontSize: tf.size, + font: tf.family, + fontColor: tf.color + }; +} + +function formatDate(ax, out, hover, extraPrecision) { + var tr = ax._tickround, + fmt = (hover && ax.hoverformat) || axes.getTickFormat(ax); + + if(extraPrecision) { + // second or sub-second precision: extra always shows max digits. + // for other fields, extra precision just adds one field. + if(isNumeric(tr)) tr = 4; + else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 4}[tr]; + } + + var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar, ax._extraFormat), + headStr; + + var splitIndex = dateStr.indexOf('\n'); + if(splitIndex !== -1) { + headStr = dateStr.substr(splitIndex + 1); + dateStr = dateStr.substr(0, splitIndex); + } + + if(extraPrecision) { + // if extraPrecision led to trailing zeros, strip them off + // actually, this can lead to removing even more zeros than + // in the original rounding, but that's fine because in these + // contexts uniformity is not so important (if there's even + // anything to be uniform with!) + + // can we remove the whole time part? + if(dateStr === '00:00:00' || dateStr === '00:00') { + dateStr = headStr; + headStr = ''; + } + else if(dateStr.length === 8) { + // strip off seconds if they're zero (zero fractional seconds + // are already omitted) + // but we never remove minutes and leave just hours + dateStr = dateStr.replace(/:00$/, ''); + } + } + + if(headStr) { + if(hover) { + // hover puts it all on one line, so headPart works best up front + // except for year headPart: turn this into "Jan 1, 2000" etc. + if(tr === 'd') dateStr += ', ' + headStr; + else dateStr = headStr + (dateStr ? ', ' + dateStr : ''); + } + else if(!ax._inCalcTicks || (headStr !== ax._prevDateHead)) { + dateStr += '
' + headStr; + ax._prevDateHead = headStr; + } + } + + out.text = dateStr; +} + +function formatLog(ax, out, hover, extraPrecision, hideexp) { + var dtick = ax.dtick; + var x = out.x; + var tickformat = ax.tickformat; + var dtChar0 = typeof dtick === 'string' && dtick.charAt(0); + + if(hideexp === 'never') { + // If this is a hover label, then we must *never* hide the exponent + // for the sake of display, which could give the wrong value by + // potentially many orders of magnitude. If hideexp was 'never', then + // it's now succeeded by preventing the other condition from automating + // this choice. Thus we can unset it so that the axis formatting takes + // precedence. + hideexp = ''; + } + + if(extraPrecision && (dtChar0 !== 'L')) { + dtick = 'L3'; + dtChar0 = 'L'; + } + + if(tickformat || (dtChar0 === 'L')) { + out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision); + } + else if(isNumeric(dtick) || ((dtChar0 === 'D') && (Lib.mod(x + 0.01, 1) < 0.1))) { + var p = Math.round(x); + var absP = Math.abs(p); + var exponentFormat = ax.exponentformat; + if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && beyondSI(p))) { + if(p === 0) out.text = 1; + else if(p === 1) out.text = '10'; + else out.text = '10' + (p > 1 ? '' : MINUS_SIGN) + absP + ''; + + out.fontSize *= 1.25; + } + else if((exponentFormat === 'e' || exponentFormat === 'E') && absP > 2) { + out.text = '1' + exponentFormat + (p > 0 ? '+' : MINUS_SIGN) + absP; + } + else { + out.text = numFormat(Math.pow(10, x), ax, '', 'fakehover'); + if(dtick === 'D1' && ax._id.charAt(0) === 'y') { + out.dy -= out.fontSize / 6; + } + } + } + else if(dtChar0 === 'D') { + out.text = String(Math.round(Math.pow(10, Lib.mod(x, 1)))); + out.fontSize *= 0.75; + } + else throw 'unrecognized dtick ' + String(dtick); + + // if 9's are printed on log scale, move the 10's away a bit + if(ax.dtick === 'D1') { + var firstChar = String(out.text).charAt(0); + if(firstChar === '0' || firstChar === '1') { + if(ax._id.charAt(0) === 'y') { + out.dx -= out.fontSize / 4; + } + else { + out.dy += out.fontSize / 2; + out.dx += (ax.range[1] > ax.range[0] ? 1 : -1) * + out.fontSize * (x < 0 ? 0.5 : 0.25); + } + } + } +} + +function formatCategory(ax, out) { + var tt = ax._categories[Math.round(out.x)]; + if(tt === undefined) tt = ''; + out.text = String(tt); +} + +function formatLinear(ax, out, hover, extraPrecision, hideexp) { + if(hideexp === 'never') { + // If this is a hover label, then we must *never* hide the exponent + // for the sake of display, which could give the wrong value by + // potentially many orders of magnitude. If hideexp was 'never', then + // it's now succeeded by preventing the other condition from automating + // this choice. Thus we can unset it so that the axis formatting takes + // precedence. + hideexp = ''; + } else if(ax.showexponent === 'all' && Math.abs(out.x / ax.dtick) < 1e-6) { + // don't add an exponent to zero if we're showing all exponents + // so the only reason you'd show an exponent on zero is if it's the + // ONLY tick to get an exponent (first or last) + hideexp = 'hide'; + } + out.text = numFormat(out.x, ax, hideexp, extraPrecision); +} + +function formatAngle(ax, out, hover, extraPrecision, hideexp) { + if(ax.thetaunit === 'radians' && !hover) { + var num = out.x / 180; + + if(num === 0) { + out.text = '0'; + } else { + var frac = num2frac(num); + + if(frac[1] >= 100) { + out.text = numFormat(Lib.deg2rad(out.x), ax, hideexp, extraPrecision); + } else { + var isNeg = out.x < 0; + + if(frac[1] === 1) { + if(frac[0] === 1) out.text = 'π'; + else out.text = frac[0] + 'π'; + } else { + out.text = [ + '', frac[0], '', + '⁄', + '', frac[1], '', + 'π' + ].join(''); + } + + if(isNeg) out.text = MINUS_SIGN + out.text; + } + } + } else { + out.text = numFormat(out.x, ax, hideexp, extraPrecision); + } +} + +// inspired by +// https://github.com/yisibl/num2fraction/blob/master/index.js +function num2frac(num) { + function almostEq(a, b) { + return Math.abs(a - b) <= 1e-6; + } + + function findGCD(a, b) { + return almostEq(b, 0) ? a : findGCD(b, a % b); + } + + function findPrecision(n) { + var e = 1; + while(!almostEq(Math.round(n * e) / e, n)) { + e *= 10; + } + return e; + } + + var precision = findPrecision(num); + var number = num * precision; + var gcd = Math.abs(findGCD(number, precision)); + + return [ + // numerator + Math.round(number / gcd), + // denominator + Math.round(precision / gcd) + ]; +} + +// format a number (tick value) according to the axis settings +// new, more reliable procedure than d3.round or similar: +// add half the rounding increment, then stringify and truncate +// also automatically switch to sci. notation +var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; + +function isSIFormat(exponentFormat) { + return exponentFormat === 'SI' || exponentFormat === 'B'; +} + +// are we beyond the range of common SI prefixes? +// 10^-16 -> 1x10^-16 +// 10^-15 -> 1f +// ... +// 10^14 -> 100T +// 10^15 -> 1x10^15 +// 10^16 -> 1x10^16 +function beyondSI(exponent) { + return exponent > 14 || exponent < -15; +} + +function numFormat(v, ax, fmtoverride, hover) { + // negative? + var isNeg = v < 0, + // max number of digits past decimal point to show + tickRound = ax._tickround, + exponentFormat = fmtoverride || ax.exponentformat || 'B', + exponent = ax._tickexponent, + tickformat = axes.getTickFormat(ax), + separatethousands = ax.separatethousands; + + // special case for hover: set exponent just for this value, and + // add a couple more digits of precision over tick labels + if(hover) { + // make a dummy axis obj to get the auto rounding and exponent + var ah = { + exponentformat: exponentFormat, + dtick: ax.showexponent === 'none' ? ax.dtick : + (isNumeric(v) ? Math.abs(v) || 1 : 1), + // if not showing any exponents, don't change the exponent + // from what we calculate + range: ax.showexponent === 'none' ? ax.range.map(ax.r2d) : [0, v || 1] + }; + autoTickRound(ah); + tickRound = (Number(ah._tickround) || 0) + 4; + exponent = ah._tickexponent; + if(ax.hoverformat) tickformat = ax.hoverformat; + } + + if(tickformat) return ax._numFormat(tickformat)(v).replace(/-/g, MINUS_SIGN); + + // 'epsilon' - rounding increment + var e = Math.pow(10, -tickRound) / 2; + + // exponentFormat codes: + // 'e' (1.2e+6, default) + // 'E' (1.2E+6) + // 'SI' (1.2M) + // 'B' (same as SI except 10^9=B not G) + // 'none' (1200000) + // 'power' (1.2x10^6) + // 'hide' (1.2, use 3rd argument=='hide' to eg + // only show exponent on last tick) + if(exponentFormat === 'none') exponent = 0; + + // take the sign out, put it back manually at the end + // - makes cases easier + v = Math.abs(v); + if(v < e) { + // 0 is just 0, but may get exponent if it's the last tick + v = '0'; + isNeg = false; + } + else { + v += e; + // take out a common exponent, if any + if(exponent) { + v *= Math.pow(10, -exponent); + tickRound += exponent; + } + // round the mantissa + if(tickRound === 0) v = String(Math.floor(v)); + else if(tickRound < 0) { + v = String(Math.round(v)); + v = v.substr(0, v.length + tickRound); + for(var i = tickRound; i < 0; i++) v += '0'; + } + else { + v = String(v); + var dp = v.indexOf('.') + 1; + if(dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ''); + } + // insert appropriate decimal point and thousands separator + v = Lib.numSeparate(v, ax._separators, separatethousands); + } + + // add exponent + if(exponent && exponentFormat !== 'hide') { + if(isSIFormat(exponentFormat) && beyondSI(exponent)) exponentFormat = 'power'; + + var signedExponent; + if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; + else if(exponentFormat !== 'power') signedExponent = '+' + exponent; + else signedExponent = String(exponent); + + if(exponentFormat === 'e' || exponentFormat === 'E') { + v += exponentFormat + signedExponent; + } + else if(exponentFormat === 'power') { + v += '×10' + signedExponent + ''; + } + else if(exponentFormat === 'B' && exponent === 9) { + v += 'B'; + } + else if(isSIFormat(exponentFormat)) { + v += SIPREFIXES[exponent / 3 + 5]; + } + } + + // put sign back in and return + // replace standard minus character (which is technically a hyphen) + // with a true minus sign + if(isNeg) return MINUS_SIGN + v; + return v; +} + +axes.getTickFormat = function(ax) { + var i; + + function convertToMs(dtick) { + return typeof dtick !== 'string' ? dtick : Number(dtick.replace('M', '')) * ONEAVGMONTH; + } + + function compareLogTicks(left, right) { + var priority = ['L', 'D']; + if(typeof left === typeof right) { + if(typeof left === 'number') { + return left - right; + } else { + var leftPriority = priority.indexOf(left.charAt(0)); + var rightPriority = priority.indexOf(right.charAt(0)); + if(leftPriority === rightPriority) { + return Number(left.replace(/(L|D)/g, '')) - Number(right.replace(/(L|D)/g, '')); + } else { + return leftPriority - rightPriority; + } + } + } else { + return typeof left === 'number' ? 1 : -1; + } + } + + function isProperStop(dtick, range, convert) { + var convertFn = convert || function(x) { return x;}; + var leftDtick = range[0]; + var rightDtick = range[1]; + return ((!leftDtick && typeof leftDtick !== 'number') || convertFn(leftDtick) <= convertFn(dtick)) && + ((!rightDtick && typeof rightDtick !== 'number') || convertFn(rightDtick) >= convertFn(dtick)); + } + + function isProperLogStop(dtick, range) { + var isLeftDtickNull = range[0] === null; + var isRightDtickNull = range[1] === null; + var isDtickInRangeLeft = compareLogTicks(dtick, range[0]) >= 0; + var isDtickInRangeRight = compareLogTicks(dtick, range[1]) <= 0; + return (isLeftDtickNull || isDtickInRangeLeft) && (isRightDtickNull || isDtickInRangeRight); + } + + var tickstop, stopi; + if(ax.tickformatstops && ax.tickformatstops.length > 0) { + switch(ax.type) { + case 'date': + case 'linear': { + for(i = 0; i < ax.tickformatstops.length; i++) { + stopi = ax.tickformatstops[i]; + if(stopi.enabled && isProperStop(ax.dtick, stopi.dtickrange, convertToMs)) { + tickstop = stopi; + break; + } + } + break; + } + case 'log': { + for(i = 0; i < ax.tickformatstops.length; i++) { + stopi = ax.tickformatstops[i]; + if(stopi.enabled && isProperLogStop(ax.dtick, stopi.dtickrange)) { + tickstop = stopi; + break; + } + } + break; + } + default: + } + } + return tickstop ? tickstop.value : ax.tickformat; +}; + +// getSubplots - extract all subplot IDs we need +// as an array of items like 'xy', 'x2y', 'x2y2'... +// sorted by x (x,x2,x3...) then y +// optionally restrict to only subplots containing axis object ax +axes.getSubplots = function(gd, ax) { + var subplotObj = gd._fullLayout._subplots; + var allSubplots = subplotObj.cartesian.concat(subplotObj.gl2d || []); + + var out = ax ? axes.findSubplotsWithAxis(allSubplots, ax) : allSubplots; + + out.sort(function(a, b) { + var aParts = a.substr(1).split('y'); + var bParts = b.substr(1).split('y'); + + if(aParts[0] === bParts[0]) return +aParts[1] - +bParts[1]; + return +aParts[0] - +bParts[0]; + }); + + return out; +}; + +// find all subplots with axis 'ax' +axes.findSubplotsWithAxis = function(subplots, ax) { + var axMatch = new RegExp( + (ax._id.charAt(0) === 'x') ? ('^' + ax._id + 'y') : (ax._id + '$') + ); + var subplotsWithAxis = []; + + for(var i = 0; i < subplots.length; i++) { + var sp = subplots[i]; + if(axMatch.test(sp)) subplotsWithAxis.push(sp); + } + + return subplotsWithAxis; +}; + +// makeClipPaths: prepare clipPaths for all single axes and all possible xy pairings +axes.makeClipPaths = function(gd) { + var fullLayout = gd._fullLayout; + + // for more info: https://github.com/plotly/plotly.js/issues/2595 + if(fullLayout._hasOnlyLargeSploms) return; + + var fullWidth = {_offset: 0, _length: fullLayout.width, _id: ''}; + var fullHeight = {_offset: 0, _length: fullLayout.height, _id: ''}; + var xaList = axes.list(gd, 'x', true); + var yaList = axes.list(gd, 'y', true); + var clipList = []; + var i, j; + + for(i = 0; i < xaList.length; i++) { + clipList.push({x: xaList[i], y: fullHeight}); + for(j = 0; j < yaList.length; j++) { + if(i === 0) clipList.push({x: fullWidth, y: yaList[j]}); + clipList.push({x: xaList[i], y: yaList[j]}); + } + } + + // selectors don't work right with camelCase tags, + // have to use class instead + // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I + var axClips = fullLayout._clips.selectAll('.axesclip') + .data(clipList, function(d) { return d.x._id + d.y._id; }); + + axClips.enter().append('clipPath') + .classed('axesclip', true) + .attr('id', function(d) { return 'clip' + fullLayout._uid + d.x._id + d.y._id; }) + .append('rect'); + + axClips.exit().remove(); + + axClips.each(function(d) { + d3.select(this).select('rect').attr({ + x: d.x._offset || 0, + y: d.y._offset || 0, + width: d.x._length || 1, + height: d.y._length || 1 + }); + }); +}; + +/** + * Main multi-axis drawing routine! + * + * @param {DOM element} gd : graph div + * @param {string or array of strings} arg : polymorphic argument + * @param {boolean} skipTitle : optional flag to skip axis title draw/update + * + * Signature 1: Axes.doTicks(gd, 'redraw') + * use this to clear and redraw all axes on graph + * + * Signature 2: Axes.doTicks(gd, '') + * use this to draw all axes on graph w/o the selectAll().remove() + * of the 'redraw' signature + * + * Signature 3: Axes.doTicks(gd, [axId, axId2, ...]) + * where the items are axis id string, + * use this to update multiple axes in one call + * + * N.B doTicks updates: + * - ax._r (stored range for use by zoom/pan) + * - ax._rl (stored linearized range for use by zoom/pan) + */ +axes.doTicks = function(gd, arg, skipTitle) { + var fullLayout = gd._fullLayout; + + if(arg === 'redraw') { + fullLayout._paper.selectAll('g.subplot').each(function(d) { + var id = d[0]; + var plotinfo = fullLayout._plots[id]; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick').remove(); + plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick').remove(); + if(plotinfo.gridlayer) plotinfo.gridlayer.selectAll('path').remove(); + if(plotinfo.zerolinelayer) plotinfo.zerolinelayer.selectAll('path').remove(); + fullLayout._infolayer.select('.g-' + xa._id + 'title').remove(); + fullLayout._infolayer.select('.g-' + ya._id + 'title').remove(); + }); + } + + var axList = (!arg || arg === 'redraw') ? axes.listIds(gd) : arg; + + Lib.syncOrAsync(axList.map(function(axid) { + return function() { + if(!axid) return; + + var axDone = axes.doTicksSingle(gd, axid, skipTitle); + + var ax = axes.getFromId(gd, axid); + ax._r = ax.range.slice(); + ax._rl = Lib.simpleMap(ax._r, ax.r2l); + + return axDone; + }; + })); +}; + +/** + * Per-axis drawing routine! + * + * This routine draws axis ticks and much more (... grids, labels, title etc.) + * Supports multiple argument signatures. + * N.B. this thing is async in general (because of MathJax rendering) + * + * @param {DOM element} gd : graph div + * @param {string or object} arg : polymorphic argument + * @param {boolean} skipTitle : optional flag to skip axis title draw/update + * @return {promise} + * + * Signature 1: Axes.doTicks(gd, ax) + * where ax is an axis object as in fullLayout + * + * Signature 2: Axes.doTicks(gd, axId) + * where axId is a axis id string + */ +axes.doTicksSingle = function(gd, arg, skipTitle) { + var fullLayout = gd._fullLayout; + var independent = false; + var ax; + + if(Lib.isPlainObject(arg)) { + ax = arg; + independent = true; + } else { + ax = axes.getFromId(gd, arg); + } + + // set scaling to pixels + ax.setScale(); + + var axid = ax._id; + var axLetter = axid.charAt(0); + var counterLetter = axes.counterLetter(axid); + var vals = ax._vals = axes.calcTicks(ax); + var datafn = function(d) { return [d.text, d.x, ax.mirror, d.font, d.fontSize, d.fontColor].join('_'); }; + var tcls = axid + 'tick'; + var gcls = axid + 'grid'; + var zcls = axid + 'zl'; + var pad = (ax.linewidth || 1) / 2; + var labelStandoff = (ax.ticks === 'outside' ? ax.ticklen : 0); + var labelShift = 0; + var gridWidth = Drawing.crispRound(gd, ax.gridwidth, 1); + var zeroLineWidth = Drawing.crispRound(gd, ax.zerolinewidth, gridWidth); + var tickWidth = Drawing.crispRound(gd, ax.tickwidth, 1); + var sides, transfn, tickpathfn, subplots; + var tickLabels; + var i; + + if(ax._counterangle && ax.ticks === 'outside') { + var caRad = ax._counterangle * Math.PI / 180; + labelStandoff = ax.ticklen * Math.cos(caRad) + 1; + labelShift = ax.ticklen * Math.sin(caRad); + } + + if(ax.showticklabels && (ax.ticks === 'outside' || ax.showline)) { + labelStandoff += 0.2 * ax.tickfont.size; + } + + // positioning arguments for x vs y axes + if(axLetter === 'x') { + sides = ['bottom', 'top']; + transfn = ax._transfn || function(d) { + return 'translate(' + (ax._offset + ax.l2p(d.x)) + ',0)'; + }; + tickpathfn = function(shift, len) { + if(ax._counterangle) { + var caRad = ax._counterangle * Math.PI / 180; + return 'M0,' + shift + 'l' + (Math.sin(caRad) * len) + ',' + (Math.cos(caRad) * len); + } + else return 'M0,' + shift + 'v' + len; + }; + } + else if(axLetter === 'y') { + sides = ['left', 'right']; + transfn = ax._transfn || function(d) { + return 'translate(0,' + (ax._offset + ax.l2p(d.x)) + ')'; + }; + tickpathfn = function(shift, len) { + if(ax._counterangle) { + var caRad = ax._counterangle * Math.PI / 180; + return 'M' + shift + ',0l' + (Math.cos(caRad) * len) + ',' + (-Math.sin(caRad) * len); + } + else return 'M' + shift + ',0h' + len; + }; + } + else if(isAngular(ax)) { + sides = ['left', 'right']; + transfn = ax._transfn; + tickpathfn = function(shift, len) { + return 'M' + shift + ',0h' + len; + }; + } + else { + Lib.warn('Unrecognized doTicks axis:', axid); + return; + } + + var axside = ax.side || sides[0]; + // which direction do the side[0], side[1], and free ticks go? + // then we flip if outside XOR y axis + var ticksign = [-1, 1, axside === sides[1] ? 1 : -1]; + if((ax.ticks !== 'inside') === (axLetter === 'x')) { + ticksign = ticksign.map(function(v) { return -v; }); + } + + if(!ax.visible) return; + + if(ax._tickFilter) { + vals = vals.filter(ax._tickFilter); + } + + // Remove zero lines, grid lines, and inside ticks if they're within + // 1 pixel of the end. + // The key case here is removing zero lines when the axis bound is zero. + // Don't clip angular values. + var valsClipped = ax._valsClipped = isAngular(ax) ? + vals : + vals.filter(function(d) { return clipEnds(ax, d.x); }); + + function drawTicks(container, tickpath) { + var ticks = container.selectAll('path.' + tcls) + .data(ax.ticks === 'inside' ? valsClipped : vals, datafn); + + if(tickpath && ax.ticks) { + ticks.enter().append('path').classed(tcls, 1).classed('ticks', 1) + .classed('crisp', 1) + .call(Color.stroke, ax.tickcolor) + .style('stroke-width', tickWidth + 'px') + .attr('d', tickpath); + ticks.attr('transform', transfn); + ticks.exit().remove(); + } + else ticks.remove(); + } + + function drawLabels(container, position) { + // tick labels - for now just the main labels. + // TODO: mirror labels, esp for subplots + tickLabels = container.selectAll('g.' + tcls).data(vals, datafn); + + if(!isNumeric(position)) { + tickLabels.remove(); + drawAxTitle(); + return; + } + if(!ax.showticklabels) { + tickLabels.remove(); + drawAxTitle(); + calcBoundingBox(); + return; + } + + var labelx, labely, labelanchor, labelpos0, flipit; + if(axLetter === 'x') { + flipit = (axside === 'bottom') ? 1 : -1; + labelx = function(d) { return d.dx + labelShift * flipit; }; + labelpos0 = position + (labelStandoff + pad) * flipit; + labely = function(d) { + return d.dy + labelpos0 + d.fontSize * + ((axside === 'bottom') ? 1 : -0.2); + }; + labelanchor = function(angle) { + if(!isNumeric(angle) || angle === 0 || angle === 180) { + return 'middle'; + } + return (angle * flipit < 0) ? 'end' : 'start'; + }; + } + else if(axLetter === 'y') { + flipit = (axside === 'right') ? 1 : -1; + labely = function(d) { + return d.dy + d.fontSize * MID_SHIFT - labelShift * flipit; + }; + labelx = function(d) { + return d.dx + position + (labelStandoff + pad + + ((Math.abs(ax.tickangle) === 90) ? d.fontSize / 2 : 0)) * flipit; + }; + labelanchor = function(angle) { + if(isNumeric(angle) && Math.abs(angle) === 90) { + return 'middle'; + } + return axside === 'right' ? 'start' : 'end'; + }; + } + else if(isAngular(ax)) { + ax._labelShift = labelShift; + ax._labelStandoff = labelStandoff; + ax._pad = pad; + + labelx = ax._labelx; + labely = ax._labely; + labelanchor = ax._labelanchor; + } + + var maxFontSize = 0, + autoangle = 0, + labelsReady = []; + tickLabels.enter().append('g').classed(tcls, 1) + .append('text') + // only so tex has predictable alignment that we can + // alter later + .attr('text-anchor', 'middle') + .each(function(d) { + var thisLabel = d3.select(this), + newPromise = gd._promises.length; + thisLabel + .call(svgTextUtils.positionText, labelx(d), labely(d)) + .call(Drawing.font, d.font, d.fontSize, d.fontColor) + .text(d.text) + .call(svgTextUtils.convertToTspans, gd); + newPromise = gd._promises[newPromise]; + if(newPromise) { + // if we have an async label, we'll deal with that + // all here so take it out of gd._promises and + // instead position the label and promise this in + // labelsReady + labelsReady.push(gd._promises.pop().then(function() { + positionLabels(thisLabel, ax.tickangle); + })); + } + else { + // sync label: just position it now. + positionLabels(thisLabel, ax.tickangle); + } + }); + tickLabels.exit().remove(); + + tickLabels.each(function(d) { + maxFontSize = Math.max(maxFontSize, d.fontSize); + }); + + if(isAngular(ax)) { + tickLabels.each(function(d) { + d3.select(this).select('text') + .call(svgTextUtils.positionText, labelx(d), labely(d)); + }); + } + + // How much to shift a multi-line label to center it vertically. + function getAnchorHeight(lineCount, lineHeight, angle) { + var h = (lineCount - 1) * lineHeight; + if(axLetter === 'x') { + if(angle < -60 || 60 < angle) { + return -0.5 * h; + } else if(axside === 'top') { + return -h; + } + } else { + angle *= axside === 'left' ? 1 : -1; + if(angle < -30) { + return -h; + } else if(angle < 30) { + return -0.5 * h; + } + } + return 0; + } + + function positionLabels(s, angle) { + s.each(function(d) { + var anchor = labelanchor(angle, d); + var thisLabel = d3.select(this), + mathjaxGroup = thisLabel.select('.text-math-group'), + transform = transfn.call(thisLabel.node(), d) + + ((isNumeric(angle) && +angle !== 0) ? + (' rotate(' + angle + ',' + labelx(d) + ',' + + (labely(d) - d.fontSize / 2) + ')') : + ''); + var anchorHeight = getAnchorHeight( + svgTextUtils.lineCount(thisLabel), + LINE_SPACING * d.fontSize, + isNumeric(angle) ? +angle : 0); + if(anchorHeight) { + transform += ' translate(0, ' + anchorHeight + ')'; + } + if(mathjaxGroup.empty()) { + thisLabel.select('text').attr({ + transform: transform, + 'text-anchor': anchor + }); + } + else { + var mjShift = + Drawing.bBox(mathjaxGroup.node()).width * + {end: -0.5, start: 0.5}[anchor]; + mathjaxGroup.attr('transform', transform + + (mjShift ? 'translate(' + mjShift + ',0)' : '')); + } + }); + } + + // make sure all labels are correctly positioned at their base angle + // the positionLabels call above is only for newly drawn labels. + // do this without waiting, using the last calculated angle to + // minimize flicker, then do it again when we know all labels are + // there, putting back the prescribed angle to check for overlaps. + positionLabels(tickLabels, ax._lastangle || ax.tickangle); + + function allLabelsReady() { + return labelsReady.length && Promise.all(labelsReady); + } + + function fixLabelOverlaps() { + positionLabels(tickLabels, ax.tickangle); + + // check for auto-angling if x labels overlap + // don't auto-angle at all for log axes with + // base and digit format + if(axLetter === 'x' && !isNumeric(ax.tickangle) && + (ax.type !== 'log' || String(ax.dtick).charAt(0) !== 'D')) { + var lbbArray = []; + tickLabels.each(function(d) { + var s = d3.select(this), + thisLabel = s.select('.text-math-group'), + x = ax.l2p(d.x); + if(thisLabel.empty()) thisLabel = s.select('text'); + + var bb = Drawing.bBox(thisLabel.node()); + + lbbArray.push({ + // ignore about y, just deal with x overlaps + top: 0, + bottom: 10, + height: 10, + left: x - bb.width / 2, + // impose a 2px gap + right: x + bb.width / 2 + 2, + width: bb.width + 2 + }); + }); + for(i = 0; i < lbbArray.length - 1; i++) { + if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) { + // any overlap at all - set 30 degrees + autoangle = 30; + break; + } + } + if(autoangle) { + var tickspacing = Math.abs( + (vals[vals.length - 1].x - vals[0].x) * ax._m + ) / (vals.length - 1); + if(tickspacing < maxFontSize * 2.5) { + autoangle = 90; + } + positionLabels(tickLabels, autoangle); + } + ax._lastangle = autoangle; + } + + // update the axis title + // (so it can move out of the way if needed) + // TODO: separate out scoot so we don't need to do + // a full redraw of the title (mostly relevant for MathJax) + drawAxTitle(); + return axid + ' done'; + } + + function calcBoundingBox() { + if(ax.showticklabels) { + var gdBB = gd.getBoundingClientRect(); + var bBox = container.node().getBoundingClientRect(); + + /* + * the way we're going to use this, the positioning that matters + * is relative to the origin of gd. This is important particularly + * if gd is scrollable, and may have been scrolled between the time + * we calculate this and the time we use it + */ + + ax._boundingBox = { + width: bBox.width, + height: bBox.height, + left: bBox.left - gdBB.left, + right: bBox.right - gdBB.left, + top: bBox.top - gdBB.top, + bottom: bBox.bottom - gdBB.top + }; + } else { + var gs = fullLayout._size; + var pos; + + // set dummy bbox for ticklabel-less axes + + if(axLetter === 'x') { + pos = ax.anchor === 'free' ? + gs.t + gs.h * (1 - ax.position) : + gs.t + gs.h * (1 - ax._anchorAxis.domain[{bottom: 0, top: 1}[ax.side]]); + + ax._boundingBox = { + top: pos, + bottom: pos, + left: ax._offset, + right: ax._offset + ax._length, + width: ax._length, + height: 0 + }; + } else { + pos = ax.anchor === 'free' ? + gs.l + gs.w * ax.position : + gs.l + gs.w * ax._anchorAxis.domain[{left: 0, right: 1}[ax.side]]; + + ax._boundingBox = { + left: pos, + right: pos, + bottom: ax._offset + ax._length, + top: ax._offset, + height: ax._length, + width: 0 + }; + } + } + + /* + * for spikelines: what's the full domain of positions in the + * opposite direction that are associated with this axis? + * This means any axes that we make a subplot with, plus the + * position of the axis itself if it's free. + */ + if(subplots) { + var fullRange = ax._counterSpan = [Infinity, -Infinity]; + + for(i = 0; i < subplots.length; i++) { + var subplot = fullLayout._plots[subplots[i]]; + var counterAxis = subplot[(axLetter === 'x') ? 'yaxis' : 'xaxis']; + + extendRange(fullRange, [ + counterAxis._offset, + counterAxis._offset + counterAxis._length + ]); + } + + if(ax.anchor === 'free') { + extendRange(fullRange, (axLetter === 'x') ? + [ax._boundingBox.bottom, ax._boundingBox.top] : + [ax._boundingBox.right, ax._boundingBox.left]); + } + } + + function extendRange(range, newRange) { + range[0] = Math.min(range[0], newRange[0]); + range[1] = Math.max(range[1], newRange[1]); + } + } + + function doAutoMargins() { + var pushKey = ax._name + '.automargin'; + if(axLetter !== 'x' && axLetter !== 'y') { return; } + if(!ax.automargin) { + Plots.autoMargin(gd, pushKey); + return; + } + + var s = ax.side[0]; + var push = {x: 0, y: 0, r: 0, l: 0, t: 0, b: 0}; + + if(axLetter === 'x') { + push.y = (ax.anchor === 'free' ? ax.position : + ax._anchorAxis.domain[s === 't' ? 1 : 0]); + push[s] += ax._boundingBox.height; + } + else { + push.x = (ax.anchor === 'free' ? ax.position : + ax._anchorAxis.domain[s === 'r' ? 1 : 0]); + push[s] += ax._boundingBox.width; + } + + if(ax.title !== fullLayout._dfltTitle[axLetter]) { + push[s] += ax.titlefont.size; + } + + Plots.autoMargin(gd, pushKey, push); + } + + var done = Lib.syncOrAsync([ + allLabelsReady, + fixLabelOverlaps, + calcBoundingBox, + doAutoMargins + ]); + if(done && done.then) gd._promises.push(done); + return done; + } + + function drawAxTitle() { + if(skipTitle) return; + + // now this only applies to regular cartesian axes; colorbars and + // others ALWAYS call doTicks with skipTitle=true so they can + // configure their own titles. + + // rangeslider takes over a bottom title so drop it here + if(ax.rangeslider && ax.rangeslider.visible && ax._boundingBox && ax.side === 'bottom') return; + + var avoid = { + selection: tickLabels, + side: ax.side + }; + var axLetter = axid.charAt(0); + var gs = gd._fullLayout._size; + var offsetBase = 1.5; + var fontSize = ax.titlefont.size; + + var transform, counterAxis, x, y; + + if(tickLabels.size()) { + var translation = Drawing.getTranslate(tickLabels.node().parentNode); + avoid.offsetLeft = translation.x; + avoid.offsetTop = translation.y; + } + + var titleStandoff = 10 + fontSize * offsetBase + + (ax.linewidth ? ax.linewidth - 1 : 0); + + if(axLetter === 'x') { + counterAxis = (ax.anchor === 'free') ? + {_offset: gs.t + (1 - (ax.position || 0)) * gs.h, _length: 0} : + axisIds.getFromId(gd, ax.anchor); + + x = ax._offset + ax._length / 2; + + if(ax.side === 'top') { + y = -titleStandoff - fontSize * (ax.showticklabels ? 1 : 0); + } + else { + y = counterAxis._length + titleStandoff + + fontSize * (ax.showticklabels ? 1.5 : 0.5); + } + y += counterAxis._offset; + + if(!avoid.side) avoid.side = 'bottom'; + } + else { + counterAxis = (ax.anchor === 'free') ? + {_offset: gs.l + (ax.position || 0) * gs.w, _length: 0} : + axisIds.getFromId(gd, ax.anchor); + + y = ax._offset + ax._length / 2; + if(ax.side === 'right') { + x = counterAxis._length + titleStandoff + + fontSize * (ax.showticklabels ? 1 : 0.5); + } + else { + x = -titleStandoff - fontSize * (ax.showticklabels ? 0.5 : 0); + } + x += counterAxis._offset; + + transform = {rotate: '-90', offset: 0}; + if(!avoid.side) avoid.side = 'left'; + } + + Titles.draw(gd, axid + 'title', { + propContainer: ax, + propName: ax._name + '.title', + placeholder: fullLayout._dfltTitle[axLetter], + avoid: avoid, + transform: transform, + attributes: {x: x, y: y, 'text-anchor': 'middle'} + }); + } + + function drawGrid(plotinfo, counteraxis) { + if(fullLayout._hasOnlyLargeSploms) return; + + var gridcontainer = plotinfo.gridlayer.selectAll('.' + axid); + var zlcontainer = plotinfo.zerolinelayer; + var gridpath = ax._gridpath || ((axLetter === 'x' ? + ('M0,' + counteraxis._offset + 'v') : + ('M' + counteraxis._offset + ',0h') + ) + counteraxis._length); + var grid = gridcontainer.selectAll('path.' + gcls) + .data((ax.showgrid === false) ? [] : valsClipped, datafn); + grid.enter().append('path').classed(gcls, 1) + .classed('crisp', 1) + .attr('d', gridpath) + .each(function(d) { + if(ax.zeroline && (ax.type === 'linear' || ax.type === '-') && + Math.abs(d.x) < ax.dtick / 100) { + d3.select(this).remove(); + } + }); + grid.attr('transform', transfn) + .call(Color.stroke, ax.gridcolor || '#ddd') + .style('stroke-width', gridWidth + 'px'); + if(typeof gridpath === 'function') grid.attr('d', gridpath); + grid.exit().remove(); + + // zero line + if(zlcontainer) { + var zlData = {x: 0, id: axid}; + var showZl = axes.shouldShowZeroLine(gd, ax, counteraxis); + var zl = zlcontainer.selectAll('path.' + zcls) + .data(showZl ? [zlData] : []); + zl.enter().append('path').classed(zcls, 1).classed('zl', 1) + .classed('crisp', 1) + .attr('d', gridpath) + .each(function() { + // use the fact that only one element can enter to trigger a sort. + // If several zerolines enter at the same time we will sort once per, + // but generally this should be a minimal overhead. + zlcontainer.selectAll('path').sort(function(da, db) { + return axisIds.idSort(da.id, db.id); + }); + }); + zl.attr('transform', transfn) + .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) + .style('stroke-width', zeroLineWidth + 'px'); + zl.exit().remove(); + } + } + + if(independent) { + drawTicks(ax._axislayer, tickpathfn(ax._pos + pad * ticksign[2], ticksign[2] * ax.ticklen)); + if(ax._counteraxis) { + var fictionalPlotinfo = { + gridlayer: ax._gridlayer, + zerolinelayer: ax._zerolinelayer + }; + drawGrid(fictionalPlotinfo, ax._counteraxis); + } + return drawLabels(ax._axislayer, ax._pos); + } + else if(fullLayout._has('cartesian')) { + subplots = axes.getSubplots(gd, ax); + + // keep track of which subplots (by main conteraxis) we've already + // drawn grids for, so we don't overdraw overlaying subplots + var finishedGrids = {}; + + subplots.map(function(subplot) { + var plotinfo = fullLayout._plots[subplot]; + var counterAxis = plotinfo[counterLetter + 'axis']; + + var mainCounterID = counterAxis._mainAxis._id; + if(finishedGrids[mainCounterID]) return; + finishedGrids[mainCounterID] = 1; + + drawGrid(plotinfo, counterAxis, subplot); + }); + + var mainSubplot = ax._mainSubplot; + var mainPlotinfo = fullLayout._plots[mainSubplot]; + var tickSubplots = []; + + if(ax.ticks) { + var mainSign = ticksign[2]; + var tickpath = tickpathfn(ax._mainLinePosition + pad * mainSign, mainSign * ax.ticklen); + if(ax._anchorAxis && ax.mirror && ax.mirror !== true) { + tickpath += tickpathfn(ax._mainMirrorPosition - pad * mainSign, -mainSign * ax.ticklen); + } + drawTicks(mainPlotinfo[axLetter + 'axislayer'], tickpath); + + tickSubplots = Object.keys(ax._linepositions || {}); + } + + tickSubplots.map(function(subplot) { + var plotinfo = fullLayout._plots[subplot]; + + var container = plotinfo[axLetter + 'axislayer']; + + // [bottom or left, top or right] + // free and main are handled above + var linepositions = ax._linepositions[subplot] || []; + + function tickPathSide(sidei) { + var tsign = ticksign[sidei]; + return tickpathfn(linepositions[sidei] + pad * tsign, tsign * ax.ticklen); + } + + drawTicks(container, tickPathSide(0) + tickPathSide(1)); + }); + + var mainContainer = mainPlotinfo[axLetter + 'axislayer']; + + return drawLabels(mainContainer, ax._mainLinePosition); + } +}; + +axes.shouldShowZeroLine = function(gd, ax, counterAxis) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + return ( + (rng[0] * rng[1] <= 0) && + ax.zeroline && + (ax.type === 'linear' || ax.type === '-') && + ax._valsClipped.length && + ( + clipEnds(ax, 0) || + !anyCounterAxLineAtZero(gd, ax, counterAxis, rng) || + hasBarsOrFill(gd, ax) + ) + ); +}; + +function clipEnds(ax, l) { + var p = ax.l2p(l); + return (p > 1 && p < ax._length - 1); +} + +function anyCounterAxLineAtZero(gd, ax, counterAxis, rng) { + var mainCounterAxis = counterAxis._mainAxis; + if(!mainCounterAxis) return; + + var fullLayout = gd._fullLayout; + var axLetter = ax._id.charAt(0); + var counterLetter = axes.counterLetter(ax._id); + + var zeroPosition = ax._offset + ( + ((Math.abs(rng[0]) < Math.abs(rng[1])) === (axLetter === 'x')) ? + 0 : ax._length + ); + + function lineNearZero(ax2) { + if(!ax2.showline || !ax2.linewidth) return false; + var tolerance = Math.max((ax2.linewidth + ax.zerolinewidth) / 2, 1); + + function closeEnough(pos2) { + return typeof pos2 === 'number' && Math.abs(pos2 - zeroPosition) < tolerance; + } + + if(closeEnough(ax2._mainLinePosition) || closeEnough(ax2._mainMirrorPosition)) { + return true; + } + var linePositions = ax2._linepositions || {}; + for(var k in linePositions) { + if(closeEnough(linePositions[k][0]) || closeEnough(linePositions[k][1])) { + return true; + } + } + } + + var plotinfo = fullLayout._plots[counterAxis._mainSubplot]; + if(!(plotinfo.mainplotinfo || plotinfo).overlays.length) { + return lineNearZero(counterAxis, zeroPosition); + } + + var counterLetterAxes = axes.list(gd, counterLetter); + for(var i = 0; i < counterLetterAxes.length; i++) { + var counterAxis2 = counterLetterAxes[i]; + if( + counterAxis2._mainAxis === mainCounterAxis && + lineNearZero(counterAxis2, zeroPosition) + ) { + return true; + } + } +} + +function hasBarsOrFill(gd, ax) { + var fullData = gd._fullData; + var subplot = ax._mainSubplot; + var axLetter = ax._id.charAt(0); + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(trace.visible === true && + (trace.xaxis + trace.yaxis) === subplot && + ( + Registry.traceIs(trace, 'bar') && trace.orientation === {x: 'h', y: 'v'}[axLetter] || + trace.fill && trace.fill.charAt(trace.fill.length - 1) === axLetter + ) + ) { + return true; + } + } + return false; +} + +/** + * Find all margin pushers for 2D axes and reserve them for later use + * Both label and rangeslider automargin calculations happen later so + * we need to explicitly allow their ids in order to not delete them. + * + * TODO: can we pull the actual automargin calls forward to avoid this hack? + * We're probably also doing multiple redraws in this case, would be faster + * if we can just do the whole calculation ahead of time and draw once. + */ +axes.allowAutoMargin = function(gd) { + var axList = axes.list(gd, '', true); + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + if(ax.automargin) { + Plots.allowAutoMargin(gd, ax._name + '.automargin'); + } + if(ax.rangeslider && ax.rangeslider.visible) { + Plots.allowAutoMargin(gd, 'rangeslider' + ax._id); + } + } +}; + +// swap all the presentation attributes of the axes showing these traces +axes.swap = function(gd, traces) { + var axGroups = makeAxisGroups(gd, traces); + + for(var i = 0; i < axGroups.length; i++) { + swapAxisGroup(gd, axGroups[i].x, axGroups[i].y); + } +}; + +function makeAxisGroups(gd, traces) { + var groups = [], + i, + j; + + for(i = 0; i < traces.length; i++) { + var groupsi = [], + xi = gd._fullData[traces[i]].xaxis, + yi = gd._fullData[traces[i]].yaxis; + if(!xi || !yi) continue; // not a 2D cartesian trace? + + for(j = 0; j < groups.length; j++) { + if(groups[j].x.indexOf(xi) !== -1 || groups[j].y.indexOf(yi) !== -1) { + groupsi.push(j); + } + } + + if(!groupsi.length) { + groups.push({x: [xi], y: [yi]}); + continue; + } + + var group0 = groups[groupsi[0]], + groupj; + + if(groupsi.length > 1) { + for(j = 1; j < groupsi.length; j++) { + groupj = groups[groupsi[j]]; + mergeAxisGroups(group0.x, groupj.x); + mergeAxisGroups(group0.y, groupj.y); + } + } + mergeAxisGroups(group0.x, [xi]); + mergeAxisGroups(group0.y, [yi]); + } + + return groups; +} + +function mergeAxisGroups(intoSet, fromSet) { + for(var i = 0; i < fromSet.length; i++) { + if(intoSet.indexOf(fromSet[i]) === -1) intoSet.push(fromSet[i]); + } +} + +function swapAxisGroup(gd, xIds, yIds) { + var i, + j, + xFullAxes = [], + yFullAxes = [], + layout = gd.layout; + + for(i = 0; i < xIds.length; i++) xFullAxes.push(axes.getFromId(gd, xIds[i])); + for(i = 0; i < yIds.length; i++) yFullAxes.push(axes.getFromId(gd, yIds[i])); + + var allAxKeys = Object.keys(axAttrs); + + var noSwapAttrs = [ + 'anchor', 'domain', 'overlaying', 'position', 'side', 'tickangle', 'editType' + ]; + var numericTypes = ['linear', 'log']; + + for(i = 0; i < allAxKeys.length; i++) { + var keyi = allAxKeys[i], + xVal = xFullAxes[0][keyi], + yVal = yFullAxes[0][keyi], + allEqual = true, + coerceLinearX = false, + coerceLinearY = false; + if(keyi.charAt(0) === '_' || typeof xVal === 'function' || + noSwapAttrs.indexOf(keyi) !== -1) { + continue; + } + for(j = 1; j < xFullAxes.length && allEqual; j++) { + var xVali = xFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(xVal) !== -1 && + numericTypes.indexOf(xVali) !== -1 && xVal !== xVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearX = true; + } + else if(xVali !== xVal) allEqual = false; + } + for(j = 1; j < yFullAxes.length && allEqual; j++) { + var yVali = yFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(yVal) !== -1 && + numericTypes.indexOf(yVali) !== -1 && yVal !== yVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearY = true; + } + else if(yFullAxes[j][keyi] !== yVal) allEqual = false; + } + if(allEqual) { + if(coerceLinearX) layout[xFullAxes[0]._name].type = 'linear'; + if(coerceLinearY) layout[yFullAxes[0]._name].type = 'linear'; + swapAxisAttrs(layout, keyi, xFullAxes, yFullAxes, gd._fullLayout._dfltTitle); + } + } + + // now swap x&y for any annotations anchored to these x & y + for(i = 0; i < gd._fullLayout.annotations.length; i++) { + var ann = gd._fullLayout.annotations[i]; + if(xIds.indexOf(ann.xref) !== -1 && + yIds.indexOf(ann.yref) !== -1) { + Lib.swapAttrs(layout.annotations[i], ['?']); + } + } +} + +function swapAxisAttrs(layout, key, xFullAxes, yFullAxes, dfltTitle) { + // in case the value is the default for either axis, + // look at the first axis in each list and see if + // this key's value is undefined + var np = Lib.nestedProperty, + xVal = np(layout[xFullAxes[0]._name], key).get(), + yVal = np(layout[yFullAxes[0]._name], key).get(), + i; + if(key === 'title') { + // special handling of placeholder titles + if(xVal === dfltTitle.x) { + xVal = dfltTitle.y; + } + if(yVal === dfltTitle.y) { + yVal = dfltTitle.x; + } + } + + for(i = 0; i < xFullAxes.length; i++) { + np(layout, xFullAxes[i]._name + '.' + key).set(yVal); + } + for(i = 0; i < yFullAxes.length; i++) { + np(layout, yFullAxes[i]._name + '.' + key).set(xVal); + } +} + +function isAngular(ax) { + return ax._id === 'angularaxis'; +} + +},{"../../components/color":570,"../../components/drawing":595,"../../components/titles":661,"../../constants/alignment":668,"../../constants/numerical":673,"../../lib":696,"../../lib/svg_text_utils":720,"../../plots/plots":808,"../../registry":827,"./autorange":743,"./axis_autotype":745,"./axis_ids":747,"./clean_ticks":749,"./layout_attributes":757,"./set_convert":763,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],745:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function autoType(array, calendar) { + if(moreDates(array, calendar)) return 'date'; + if(category(array)) return 'category'; + if(linearOK(array)) return 'linear'; + else return '-'; +}; + +// is there at least one number in array? If not, we should leave +// ax.type empty so it can be autoset later +function linearOK(array) { + if(!array) return false; + + for(var i = 0; i < array.length; i++) { + if(isNumeric(array[i])) return true; + } + + return false; +} + +// does the array a have mostly dates rather than numbers? +// note: some values can be neither (such as blanks, text) +// 2- or 4-digit integers can be both, so require twice as many +// dates as non-dates, to exclude cases with mostly 2 & 4 digit +// numbers and a few dates +// as with categories, consider DISTINCT values only. +function moreDates(a, calendar) { + // test at most 1000 points, evenly spaced + var inc = Math.max(1, (a.length - 1) / 1000); + var dcnt = 0; + var ncnt = 0; + var seen = {}; + + for(var i = 0; i < a.length; i += inc) { + var ai = a[Math.round(i)]; + var stri = String(ai); + if(seen[stri]) continue; + seen[stri] = 1; + + if(Lib.isDateTime(ai, calendar)) dcnt += 1; + if(isNumeric(ai)) ncnt += 1; + } + + return (dcnt > ncnt * 2); +} + +// are the (x,y)-values in gd.data mostly text? +// require twice as many DISTINCT categories as distinct numbers +function category(a) { + // test at most 1000 points + var inc = Math.max(1, (a.length - 1) / 1000); + var curvenums = 0; + var curvecats = 0; + var seen = {}; + + for(var i = 0; i < a.length; i += inc) { + var ai = a[Math.round(i)]; + var stri = String(ai); + if(seen[stri]) continue; + seen[stri] = 1; + + if(typeof ai === 'boolean') curvecats++; + else if(Lib.cleanNumber(ai) !== BADNUM) curvenums++; + else if(typeof ai === 'string') curvecats++; + } + + return curvecats > curvenums * 2; +} + +},{"../../constants/numerical":673,"../../lib":696,"fast-isnumeric":214}],746:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +var layoutAttributes = _dereq_('./layout_attributes'); +var handleTickValueDefaults = _dereq_('./tick_value_defaults'); +var handleTickMarkDefaults = _dereq_('./tick_mark_defaults'); +var handleTickLabelDefaults = _dereq_('./tick_label_defaults'); +var handleCategoryOrderDefaults = _dereq_('./category_order_defaults'); +var handleLineGridDefaults = _dereq_('./line_grid_defaults'); +var setConvert = _dereq_('./set_convert'); + +/** + * options: object containing: + * + * letter: 'x' or 'y' + * title: name of the axis (ie 'Colorbar') to go in default title + * font: the default font to inherit + * outerTicks: boolean, should ticks default to outside? + * showGrid: boolean, should gridlines be shown by default? + * noHover: boolean, this axis doesn't support hover effects? + * data: the plot data, used to manage categories + * bgColor: the plot background color, to calculate default gridline colors + */ +module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, options, layoutOut) { + var letter = options.letter; + var font = options.font || {}; + var splomStash = options.splomStash || {}; + + var visible = coerce('visible', !options.cheateronly); + + var axType = containerOut.type; + + if(axType === 'date') { + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); + handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar); + } + + setConvert(containerOut, layoutOut); + + var autoRange = coerce('autorange', !containerOut.isValidRange(containerIn.range)); + if(autoRange && (axType === 'linear' || axType === '-')) coerce('rangemode'); + + coerce('range'); + containerOut.cleanRange(); + + handleCategoryOrderDefaults(containerIn, containerOut, coerce, options); + + if(axType !== 'category' && !options.noHover) coerce('hoverformat'); + + if(!visible) return containerOut; + + var dfltColor = coerce('color'); + // if axis.color was provided, use it for fonts too; otherwise, + // inherit from global font color in case that was provided. + // Compare to dflt rather than to containerIn, so we can provide color via + // template too. + var dfltFontColor = (dfltColor !== layoutAttributes.color.dflt) ? dfltColor : font.color; + // try to get default title from splom trace, fallback to graph-wide value + var dfltTitle = splomStash.label || layoutOut._dfltTitle[letter]; + + coerce('title', dfltTitle); + Lib.coerceFont(coerce, 'titlefont', { + family: font.family, + size: Math.round(font.size * 1.2), + color: dfltFontColor + }); + + handleTickValueDefaults(containerIn, containerOut, coerce, axType); + handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); + handleTickMarkDefaults(containerIn, containerOut, coerce, options); + handleLineGridDefaults(containerIn, containerOut, coerce, { + dfltColor: dfltColor, + bgColor: options.bgColor, + showGrid: options.showGrid, + attributes: layoutAttributes + }); + + if(containerOut.showline || containerOut.ticks) coerce('mirror'); + + if(options.automargin) coerce('automargin'); + + return containerOut; +}; + +},{"../../lib":696,"../../registry":827,"./category_order_defaults":748,"./layout_attributes":757,"./line_grid_defaults":759,"./set_convert":763,"./tick_label_defaults":764,"./tick_mark_defaults":765,"./tick_value_defaults":766}],747:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); + +var constants = _dereq_('./constants'); + + +// convert between axis names (xaxis, xaxis2, etc, elements of gd.layout) +// and axis id's (x, x2, etc). Would probably have ditched 'xaxis' +// completely in favor of just 'x' if it weren't ingrained in the API etc. +exports.id2name = function id2name(id) { + if(typeof id !== 'string' || !id.match(constants.AX_ID_PATTERN)) return; + var axNum = id.substr(1); + if(axNum === '1') axNum = ''; + return id.charAt(0) + 'axis' + axNum; +}; + +exports.name2id = function name2id(name) { + if(!name.match(constants.AX_NAME_PATTERN)) return; + var axNum = name.substr(5); + if(axNum === '1') axNum = ''; + return name.charAt(0) + axNum; +}; + +exports.cleanId = function cleanId(id, axLetter) { + if(!id.match(constants.AX_ID_PATTERN)) return; + if(axLetter && id.charAt(0) !== axLetter) return; + + var axNum = id.substr(1).replace(/^0+/, ''); + if(axNum === '1') axNum = ''; + return id.charAt(0) + axNum; +}; + +// get all axis objects, as restricted in listNames +exports.list = function(gd, axLetter, only2d) { + var fullLayout = gd._fullLayout; + if(!fullLayout) return []; + + var idList = exports.listIds(gd, axLetter); + var out = new Array(idList.length); + var i; + + for(i = 0; i < idList.length; i++) { + var idi = idList[i]; + out[i] = fullLayout[idi.charAt(0) + 'axis' + idi.substr(1)]; + } + + if(!only2d) { + var sceneIds3D = fullLayout._subplots.gl3d || []; + + for(i = 0; i < sceneIds3D.length; i++) { + var scene = fullLayout[sceneIds3D[i]]; + + if(axLetter) out.push(scene[axLetter + 'axis']); + else out.push(scene.xaxis, scene.yaxis, scene.zaxis); + } + } + + return out; +}; + +// get all axis ids, optionally restricted by letter +// this only makes sense for 2d axes +exports.listIds = function(gd, axLetter) { + var fullLayout = gd._fullLayout; + if(!fullLayout) return []; + + var subplotLists = fullLayout._subplots; + if(axLetter) return subplotLists[axLetter + 'axis']; + return subplotLists.xaxis.concat(subplotLists.yaxis); +}; + +// get an axis object from its id 'x','x2' etc +// optionally, id can be a subplot (ie 'x2y3') and type gets x or y from it +exports.getFromId = function(gd, id, type) { + var fullLayout = gd._fullLayout; + + if(type === 'x') id = id.replace(/y[0-9]*/, ''); + else if(type === 'y') id = id.replace(/x[0-9]*/, ''); + + return fullLayout[exports.id2name(id)]; +}; + +// get an axis object of specified type from the containing trace +exports.getFromTrace = function(gd, fullTrace, type) { + var fullLayout = gd._fullLayout; + var ax = null; + + if(Registry.traceIs(fullTrace, 'gl3d')) { + var scene = fullTrace.scene; + if(scene.substr(0, 5) === 'scene') { + ax = fullLayout[scene][type + 'axis']; + } + } + else { + ax = exports.getFromId(gd, fullTrace[type + 'axis'] || type); + } + + return ax; +}; + +// sort x, x2, x10, y, y2, y10... +exports.idSort = function(id1, id2) { + var letter1 = id1.charAt(0); + var letter2 = id2.charAt(0); + if(letter1 !== letter2) return letter1 > letter2 ? 1 : -1; + return +(id1.substr(1) || 1) - +(id2.substr(1) || 1); +}; + +},{"../../registry":827,"./constants":750}],748:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +function findCategories(ax, opts) { + var dataAttr = opts.dataAttr || ax._id.charAt(0); + var lookup = {}; + var axData; + var i, j; + + if(opts.axData) { + // non-x/y case + axData = opts.axData; + } else { + // x/y case + axData = []; + for(i = 0; i < opts.data.length; i++) { + var trace = opts.data[i]; + if(trace[dataAttr + 'axis'] === ax._id) { + axData.push(trace); + } + } + } + + for(i = 0; i < axData.length; i++) { + var vals = axData[i][dataAttr]; + for(j = 0; j < vals.length; j++) { + var v = vals[j]; + if(v !== null && v !== undefined) { + lookup[v] = 1; + } + } + } + + return Object.keys(lookup); +} + +/** + * Fills in category* default and initial categories. + * + * @param {object} containerIn : input axis object + * @param {object} containerOut : full axis object + * @param {function} coerce : Lib.coerce fn wrapper + * @param {object} opts : + * - data {array} : (full) data trace + * OR + * - axData {array} : (full) data associated with axis being coerced here + * - dataAttr {string} : attribute name corresponding to coordinate array + */ +module.exports = function handleCategoryOrderDefaults(containerIn, containerOut, coerce, opts) { + if(containerOut.type !== 'category') return; + + var arrayIn = containerIn.categoryarray; + var isValidArray = (Array.isArray(arrayIn) && arrayIn.length > 0); + + // override default 'categoryorder' value when non-empty array is supplied + var orderDefault; + if(isValidArray) orderDefault = 'array'; + + var order = coerce('categoryorder', orderDefault); + var array; + + // coerce 'categoryarray' only in array order case + if(order === 'array') { + array = coerce('categoryarray'); + } + + // cannot set 'categoryorder' to 'array' with an invalid 'categoryarray' + if(!isValidArray && order === 'array') { + order = containerOut.categoryorder = 'trace'; + } + + // set up things for makeCalcdata + if(order === 'trace') { + containerOut._initialCategories = []; + } else if(order === 'array') { + containerOut._initialCategories = array.slice(); + } else { + array = findCategories(containerOut, opts).sort(); + if(order === 'category ascending') { + containerOut._initialCategories = array; + } else if(order === 'category descending') { + containerOut._initialCategories = array.reverse(); + } + } +}; + +},{}],749:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var Lib = _dereq_('../../lib'); +var ONEDAY = _dereq_('../../constants/numerical').ONEDAY; + +/** + * Return a validated dtick value for this axis + * + * @param {any} dtick: the candidate dtick. valid values are numbers and strings, + * and further constrained depending on the axis type. + * @param {string} axType: the axis type + */ +exports.dtick = function(dtick, axType) { + var isLog = axType === 'log'; + var isDate = axType === 'date'; + var isCat = axType === 'category'; + var dtickDflt = isDate ? ONEDAY : 1; + + if(!dtick) return dtickDflt; + + if(isNumeric(dtick)) { + dtick = Number(dtick); + if(dtick <= 0) return dtickDflt; + if(isCat) { + // category dtick must be positive integers + return Math.max(1, Math.round(dtick)); + } + if(isDate) { + // date dtick must be at least 0.1ms (our current precision) + return Math.max(0.1, dtick); + } + return dtick; + } + + if(typeof dtick !== 'string' || !(isDate || isLog)) { + return dtickDflt; + } + + var prefix = dtick.charAt(0); + var dtickNum = dtick.substr(1); + dtickNum = isNumeric(dtickNum) ? Number(dtickNum) : 0; + + if((dtickNum <= 0) || !( + // "M" gives ticks every (integer) n months + (isDate && prefix === 'M' && dtickNum === Math.round(dtickNum)) || + // "L" gives ticks linearly spaced in data (not in position) every (float) f + (isLog && prefix === 'L') || + // "D1" gives powers of 10 with all small digits between, "D2" gives only 2 and 5 + (isLog && prefix === 'D' && (dtickNum === 1 || dtickNum === 2)) + )) { + return dtickDflt; + } + + return dtick; +}; + +/** + * Return a validated tick0 for this axis + * + * @param {any} tick0: the candidate tick0. Valid values are numbers and strings, + * further constrained depending on the axis type + * @param {string} axType: the axis type + * @param {string} calendar: for date axes, the calendar to validate/convert with + * @param {any} dtick: an already valid dtick. Only used for D1 and D2 log dticks, + * which do not support tick0 at all. + */ +exports.tick0 = function(tick0, axType, calendar, dtick) { + if(axType === 'date') { + return Lib.cleanDate(tick0, Lib.dateTick0(calendar)); + } + if(dtick === 'D1' || dtick === 'D2') { + // D1 and D2 modes ignore tick0 entirely + return undefined; + } + // Aside from date axes, tick0 must be numeric + return isNumeric(tick0) ? Number(tick0) : 0; +}; + +},{"../../constants/numerical":673,"../../lib":696,"fast-isnumeric":214}],750:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; +var counterRegex = _dereq_('../../lib/regex').counter; + + +module.exports = { + + idRegex: { + x: counterRegex('x'), + y: counterRegex('y') + }, + + attrRegex: counterRegex('[xy]axis'), + + // axis match regular expression + xAxisMatch: counterRegex('xaxis'), + yAxisMatch: counterRegex('yaxis'), + + // pattern matching axis ids and names + // note that this is more permissive than counterRegex, as + // id2name, name2id, and cleanId accept "x1" etc + AX_ID_PATTERN: /^[xyz][0-9]*$/, + AX_NAME_PATTERN: /^[xyz]axis[0-9]*$/, + + // and for 2D subplots + SUBPLOT_PATTERN: /^x([0-9]*)y([0-9]*)$/, + + // pixels to move mouse before you stop clamping to starting point + MINDRAG: 8, + + // smallest dimension allowed for a select box + MINSELECT: 12, + + // smallest dimension allowed for a zoombox + MINZOOM: 20, + + // width of axis drag regions + DRAGGERSIZE: 20, + + // max pixels off straight before a lasso select line counts as bent + BENDPX: 1.5, + + // delay before a redraw (relayout) after smooth panning and zooming + REDRAWDELAY: 50, + + // throttling limit (ms) for selectPoints calls + SELECTDELAY: 100, + + // cache ID suffix for throttle + SELECTID: '-select', + + // last resort axis ranges for x and y axes if we have no data + DFLTRANGEX: [-1, 6], + DFLTRANGEY: [-1, 4], + + // Layers to keep trace types in the right order + // N.B. each 'unique' plot method must have its own layer + traceLayerClasses: [ + 'heatmaplayer', + 'contourcarpetlayer', 'contourlayer', + 'barlayer', + 'carpetlayer', + 'violinlayer', + 'boxlayer', + 'ohlclayer', + 'scattercarpetlayer', 'scatterlayer' + ], + + layerValue2layerClass: { + 'above traces': 'above', + 'below traces': 'below' + } +}; + +},{"../../lib/regex":712}],751:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var id2name = _dereq_('./axis_ids').id2name; + + +module.exports = function handleConstraintDefaults(containerIn, containerOut, coerce, allAxisIds, layoutOut) { + var constraintGroups = layoutOut._axisConstraintGroups; + var thisID = containerOut._id; + var letter = thisID.charAt(0); + + if(containerOut.fixedrange) return; + + // coerce the constraint mechanics even if this axis has no scaleanchor + // because it may be the anchor of another axis. + coerce('constrain'); + Lib.coerce(containerIn, containerOut, { + constraintoward: { + valType: 'enumerated', + values: letter === 'x' ? ['left', 'center', 'right'] : ['bottom', 'middle', 'top'], + dflt: letter === 'x' ? 'center' : 'middle' + } + }, 'constraintoward'); + + if(!containerIn.scaleanchor) return; + + var constraintOpts = getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut); + + var scaleanchor = Lib.coerce(containerIn, containerOut, { + scaleanchor: { + valType: 'enumerated', + values: constraintOpts.linkableAxes + } + }, 'scaleanchor'); + + if(scaleanchor) { + var scaleratio = coerce('scaleratio'); + // TODO: I suppose I could do attribute.min: Number.MIN_VALUE to avoid zero, + // but that seems hacky. Better way to say "must be a positive number"? + // Of course if you use several super-tiny values you could eventually + // force a product of these to zero and all hell would break loose... + // Likewise with super-huge values. + if(!scaleratio) scaleratio = containerOut.scaleratio = 1; + + updateConstraintGroups(constraintGroups, constraintOpts.thisGroup, + thisID, scaleanchor, scaleratio); + } + else if(allAxisIds.indexOf(containerIn.scaleanchor) !== -1) { + Lib.warn('ignored ' + containerOut._name + '.scaleanchor: "' + + containerIn.scaleanchor + '" to avoid either an infinite loop ' + + 'and possibly inconsistent scaleratios, or because the target' + + 'axis has fixed range.'); + } +}; + +function getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut) { + // If this axis is already part of a constraint group, we can't + // scaleanchor any other axis in that group, or we'd make a loop. + // Filter allAxisIds to enforce this, also matching axis types. + + var thisType = layoutOut[id2name(thisID)].type; + + var i, j, idj, axj; + + var linkableAxes = []; + for(j = 0; j < allAxisIds.length; j++) { + idj = allAxisIds[j]; + if(idj === thisID) continue; + + axj = layoutOut[id2name(idj)]; + if(axj.type === thisType && !axj.fixedrange) linkableAxes.push(idj); + } + + for(i = 0; i < constraintGroups.length; i++) { + if(constraintGroups[i][thisID]) { + var thisGroup = constraintGroups[i]; + + var linkableAxesNoLoops = []; + for(j = 0; j < linkableAxes.length; j++) { + idj = linkableAxes[j]; + if(!thisGroup[idj]) linkableAxesNoLoops.push(idj); + } + return {linkableAxes: linkableAxesNoLoops, thisGroup: thisGroup}; + } + } + + return {linkableAxes: linkableAxes, thisGroup: null}; +} + + +/* + * Add this axis to the axis constraint groups, which is the collection + * of axes that are all constrained together on scale. + * + * constraintGroups: a list of objects. each object is + * {axis_id: scale_within_group}, where scale_within_group is + * only important relative to the rest of the group, and defines + * the relative scales between all axes in the group + * + * thisGroup: the group the current axis is already in + * thisID: the id if the current axis + * scaleanchor: the id of the axis to scale it with + * scaleratio: the ratio of this axis to the scaleanchor axis + */ +function updateConstraintGroups(constraintGroups, thisGroup, thisID, scaleanchor, scaleratio) { + var i, j, groupi, keyj, thisGroupIndex; + + if(thisGroup === null) { + thisGroup = {}; + thisGroup[thisID] = 1; + thisGroupIndex = constraintGroups.length; + constraintGroups.push(thisGroup); + } + else { + thisGroupIndex = constraintGroups.indexOf(thisGroup); + } + + var thisGroupKeys = Object.keys(thisGroup); + + // we know that this axis isn't in any other groups, but we don't know + // about the scaleanchor axis. If it is, we need to merge the groups. + for(i = 0; i < constraintGroups.length; i++) { + groupi = constraintGroups[i]; + if(i !== thisGroupIndex && groupi[scaleanchor]) { + var baseScale = groupi[scaleanchor]; + for(j = 0; j < thisGroupKeys.length; j++) { + keyj = thisGroupKeys[j]; + groupi[keyj] = baseScale * scaleratio * thisGroup[keyj]; + } + constraintGroups.splice(thisGroupIndex, 1); + return; + } + } + + // otherwise, we insert the new scaleanchor axis as the base scale (1) + // in its group, and scale the rest of the group to it + if(scaleratio !== 1) { + for(j = 0; j < thisGroupKeys.length; j++) { + thisGroup[thisGroupKeys[j]] *= scaleratio; + } + } + thisGroup[scaleanchor] = 1; +} + +},{"../../lib":696,"./axis_ids":747}],752:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var id2name = _dereq_('./axis_ids').id2name; +var scaleZoom = _dereq_('./scale_zoom'); +var makePadFn = _dereq_('./autorange').makePadFn; +var concatExtremes = _dereq_('./autorange').concatExtremes; + +var ALMOST_EQUAL = _dereq_('../../constants/numerical').ALMOST_EQUAL; + +var FROM_BL = _dereq_('../../constants/alignment').FROM_BL; + + +exports.enforce = function enforceAxisConstraints(gd) { + var fullLayout = gd._fullLayout; + var constraintGroups = fullLayout._axisConstraintGroups || []; + + var i, j, axisID, ax, normScale, mode, factor; + + for(i = 0; i < constraintGroups.length; i++) { + var group = constraintGroups[i]; + var axisIDs = Object.keys(group); + + var minScale = Infinity; + var maxScale = 0; + // mostly matchScale will be the same as minScale + // ie we expand axis ranges to encompass *everything* + // that's currently in any of their ranges, but during + // autorange of a subset of axes we will ignore other + // axes for this purpose. + var matchScale = Infinity; + var normScales = {}; + var axes = {}; + var hasAnyDomainConstraint = false; + + // find the (normalized) scale of each axis in the group + for(j = 0; j < axisIDs.length; j++) { + axisID = axisIDs[j]; + axes[axisID] = ax = fullLayout[id2name(axisID)]; + + if(ax._inputDomain) ax.domain = ax._inputDomain.slice(); + else ax._inputDomain = ax.domain.slice(); + + if(!ax._inputRange) ax._inputRange = ax.range.slice(); + + // set axis scale here so we can use _m rather than + // having to calculate it from length and range + ax.setScale(); + + // abs: inverted scales still satisfy the constraint + normScales[axisID] = normScale = Math.abs(ax._m) / group[axisID]; + minScale = Math.min(minScale, normScale); + if(ax.constrain === 'domain' || !ax._constraintShrinkable) { + matchScale = Math.min(matchScale, normScale); + } + + // this has served its purpose, so remove it + delete ax._constraintShrinkable; + maxScale = Math.max(maxScale, normScale); + + if(ax.constrain === 'domain') hasAnyDomainConstraint = true; + } + + // Do we have a constraint mismatch? Give a small buffer for rounding errors + if(minScale > ALMOST_EQUAL * maxScale && !hasAnyDomainConstraint) continue; + + // now increase any ranges we need to until all normalized scales are equal + for(j = 0; j < axisIDs.length; j++) { + axisID = axisIDs[j]; + normScale = normScales[axisID]; + ax = axes[axisID]; + mode = ax.constrain; + + // even if the scale didn't change, if we're shrinking domain + // we need to recalculate in case `constraintoward` changed + if(normScale !== matchScale || mode === 'domain') { + factor = normScale / matchScale; + + if(mode === 'range') { + scaleZoom(ax, factor); + } + else { + // mode === 'domain' + + var inputDomain = ax._inputDomain; + var domainShrunk = (ax.domain[1] - ax.domain[0]) / + (inputDomain[1] - inputDomain[0]); + var rangeShrunk = (ax.r2l(ax.range[1]) - ax.r2l(ax.range[0])) / + (ax.r2l(ax._inputRange[1]) - ax.r2l(ax._inputRange[0])); + + factor /= domainShrunk; + + if(factor * rangeShrunk < 1) { + // we've asked to magnify the axis more than we can just by + // enlarging the domain - so we need to constrict range + ax.domain = ax._input.domain = inputDomain.slice(); + scaleZoom(ax, factor); + continue; + } + + if(rangeShrunk < 1) { + // the range has previously been constricted by ^^, but we've + // switched to the domain-constricted regime, so reset range + ax.range = ax._input.range = ax._inputRange.slice(); + factor *= rangeShrunk; + } + + if(ax.autorange) { + /* + * range & factor may need to change because range was + * calculated for the larger scaling, so some pixel + * paddings may get cut off when we reduce the domain. + * + * This is easier than the regular autorange calculation + * because we already know the scaling `m`, but we still + * need to cut out impossible constraints (like + * annotations with super-long arrows). That's what + * outerMin/Max are for - if the expansion was going to + * go beyond the original domain, it must be impossible + */ + var rl0 = ax.r2l(ax.range[0]); + var rl1 = ax.r2l(ax.range[1]); + var rangeCenter = (rl0 + rl1) / 2; + var rangeMin = rangeCenter; + var rangeMax = rangeCenter; + var halfRange = Math.abs(rl1 - rangeCenter); + // extra tiny bit for rounding errors, in case we actually + // *are* expanding to the full domain + var outerMin = rangeCenter - halfRange * factor * 1.0001; + var outerMax = rangeCenter + halfRange * factor * 1.0001; + var getPad = makePadFn(ax); + + updateDomain(ax, factor); + ax.setScale(); + var m = Math.abs(ax._m); + var extremes = concatExtremes(gd, ax); + var minArray = extremes.min; + var maxArray = extremes.max; + var newVal; + var k; + + for(k = 0; k < minArray.length; k++) { + newVal = minArray[k].val - getPad(minArray[k]) / m; + if(newVal > outerMin && newVal < rangeMin) { + rangeMin = newVal; + } + } + + for(k = 0; k < maxArray.length; k++) { + newVal = maxArray[k].val + getPad(maxArray[k]) / m; + if(newVal < outerMax && newVal > rangeMax) { + rangeMax = newVal; + } + } + + var domainExpand = (rangeMax - rangeMin) / (2 * halfRange); + factor /= domainExpand; + + rangeMin = ax.l2r(rangeMin); + rangeMax = ax.l2r(rangeMax); + ax.range = ax._input.range = (rl0 < rl1) ? + [rangeMin, rangeMax] : [rangeMax, rangeMin]; + } + + updateDomain(ax, factor); + } + } + } + } +}; + +// For use before autoranging, check if this axis was previously constrained +// by domain but no longer is +exports.clean = function cleanConstraints(gd, ax) { + if(ax._inputDomain) { + var isConstrained = false; + var axId = ax._id; + var constraintGroups = gd._fullLayout._axisConstraintGroups; + for(var j = 0; j < constraintGroups.length; j++) { + if(constraintGroups[j][axId]) { + isConstrained = true; + break; + } + } + if(!isConstrained || ax.constrain !== 'domain') { + ax._input.domain = ax.domain = ax._inputDomain; + delete ax._inputDomain; + } + } +}; + +function updateDomain(ax, factor) { + var inputDomain = ax._inputDomain; + var centerFraction = FROM_BL[ax.constraintoward]; + var center = inputDomain[0] + (inputDomain[1] - inputDomain[0]) * centerFraction; + + ax.domain = ax._input.domain = [ + center + (inputDomain[0] - center) / factor, + center + (inputDomain[1] - center) / factor + ]; +} + +},{"../../constants/alignment":668,"../../constants/numerical":673,"./autorange":743,"./axis_ids":747,"./scale_zoom":761}],753:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); +var supportsPassive = _dereq_('has-passive-events'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Fx = _dereq_('../../components/fx'); +var setCursor = _dereq_('../../lib/setcursor'); +var dragElement = _dereq_('../../components/dragelement'); +var FROM_TL = _dereq_('../../constants/alignment').FROM_TL; +var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); +var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; + +var Plots = _dereq_('../plots'); + +var doTicksSingle = _dereq_('./axes').doTicksSingle; +var getFromId = _dereq_('./axis_ids').getFromId; +var prepSelect = _dereq_('./select').prepSelect; +var clearSelect = _dereq_('./select').clearSelect; +var selectOnClick = _dereq_('./select').selectOnClick; +var scaleZoom = _dereq_('./scale_zoom'); + +var constants = _dereq_('./constants'); +var MINDRAG = constants.MINDRAG; +var MINZOOM = constants.MINZOOM; + + +// flag for showing "doubleclick to zoom out" only at the beginning +var SHOWZOOMOUTTIP = true; + +// dragBox: create an element to drag one or more axis ends +// inputs: +// plotinfo - which subplot are we making dragboxes on? +// x,y,w,h - left, top, width, height of the box +// ns - how does this drag the vertical axis? +// 'n' - top only +// 's' - bottom only +// 'ns' - top and bottom together, difference unchanged +// ew - same for horizontal axis +function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { + // mouseDown stores ms of first mousedown event in the last + // DBLCLICKDELAY ms on the drag bars + // numClicks stores how many mousedowns have been seen + // within DBLCLICKDELAY so we can check for click or doubleclick events + // dragged stores whether a drag has occurred, so we don't have to + // redraw unnecessarily, ie if no move bigger than MINDRAG or MINZOOM px + var zoomlayer = gd._fullLayout._zoomlayer; + var isMainDrag = (ns + ew === 'nsew'); + var singleEnd = (ns + ew).length === 1; + + // main subplot x and y (i.e. found in plotinfo - the main ones) + var xa0, ya0; + // {ax._id: ax} hash objects + var xaHash, yaHash; + // xaHash/yaHash values (arrays) + var xaxes, yaxes; + // main axis offsets + var xs, ys; + // main axis lengths + var pw, ph; + // contains keys 'xaHash', 'yaHash', 'xaxes', and 'yaxes' + // which are the x/y {ax._id: ax} hash objects and their values + // for linked axis relative to this subplot + var links; + // set to ew/ns val when active, set to '' when inactive + var xActive, yActive; + // are all axes in this subplot are fixed? + var allFixedRanges; + // is subplot constrained? + var isSubplotConstrained; + // do we need to edit x/y ranges? + var editX, editY; + // graph-wide optimization flags + var hasScatterGl, hasSplom, hasSVG; + // collected changes to be made to the plot by relayout at the end + var updates; + + function recomputeAxisLists() { + xa0 = plotinfo.xaxis; + ya0 = plotinfo.yaxis; + pw = xa0._length; + ph = ya0._length; + xs = xa0._offset; + ys = ya0._offset; + + xaHash = {}; + xaHash[xa0._id] = xa0; + yaHash = {}; + yaHash[ya0._id] = ya0; + + // if we're dragging two axes at once, also drag overlays + if(ns && ew) { + var overlays = plotinfo.overlays; + for(var i = 0; i < overlays.length; i++) { + var xa = overlays[i].xaxis; + xaHash[xa._id] = xa; + var ya = overlays[i].yaxis; + yaHash[ya._id] = ya; + } + } + + xaxes = hashValues(xaHash); + yaxes = hashValues(yaHash); + xActive = isDirectionActive(xaxes, ew); + yActive = isDirectionActive(yaxes, ns); + allFixedRanges = !yActive && !xActive; + + links = calcLinks(gd, xaHash, yaHash); + isSubplotConstrained = links.isSubplotConstrained; + editX = ew || isSubplotConstrained; + editY = ns || isSubplotConstrained; + + var fullLayout = gd._fullLayout; + hasScatterGl = fullLayout._has('scattergl'); + hasSplom = fullLayout._has('splom'); + hasSVG = fullLayout._has('svg'); + } + + recomputeAxisLists(); + + var cursor = getDragCursor(yActive + xActive, gd._fullLayout.dragmode, isMainDrag); + var dragger = makeRectDragger(plotinfo, ns + ew + 'drag', cursor, x, y, w, h); + + // still need to make the element if the axes are disabled + // but nuke its events (except for maindrag which needs them for hover) + // and stop there + if(allFixedRanges && !isMainDrag) { + dragger.onmousedown = null; + dragger.style.pointerEvents = 'none'; + return dragger; + } + + var dragOptions = { + element: dragger, + gd: gd, + plotinfo: plotinfo + }; + + dragOptions.prepFn = function(e, startX, startY) { + var dragModePrev = dragOptions.dragmode; + var dragModeNow = gd._fullLayout.dragmode; + if(dragModeNow !== dragModePrev) { + dragOptions.dragmode = dragModeNow; + } + + recomputeAxisLists(); + + if(!allFixedRanges) { + if(isMainDrag) { + // main dragger handles all drag modes, and changes + // to pan (or to zoom if it already is pan) on shift + if(e.shiftKey) { + if(dragModeNow === 'pan') dragModeNow = 'zoom'; + else if(!isSelectOrLasso(dragModeNow)) dragModeNow = 'pan'; + } + else if(e.ctrlKey) { + dragModeNow = 'pan'; + } + } + // all other draggers just pan + else dragModeNow = 'pan'; + } + + if(dragModeNow === 'lasso') dragOptions.minDrag = 1; + else dragOptions.minDrag = undefined; + + if(isSelectOrLasso(dragModeNow)) { + dragOptions.xaxes = xaxes; + dragOptions.yaxes = yaxes; + // this attaches moveFn, clickFn, doneFn on dragOptions + prepSelect(e, startX, startY, dragOptions, dragModeNow); + } else { + dragOptions.clickFn = clickFn; + if(isSelectOrLasso(dragModePrev)) { + // TODO Fix potential bug + // Note: clearing / resetting selection state only happens, when user + // triggers at least one interaction in pan/zoom mode. Otherwise, the + // select/lasso outlines are deleted (in plots.js.cleanPlot) but the selection + // cache isn't cleared. So when the user switches back to select/lasso and + // 'adds to a selection' with Shift, the "old", seemingly removed outlines + // are redrawn again because the selection cache still holds their coordinates. + // However, this isn't easily solved, since plots.js would need + // to have a reference to the dragOptions object (which holds the + // selection cache). + clearAndResetSelect(); + } + + if(!allFixedRanges) { + if(dragModeNow === 'zoom') { + dragOptions.moveFn = zoomMove; + dragOptions.doneFn = zoomDone; + + // zoomMove takes care of the threshold, but we need to + // minimize this so that constrained zoom boxes will flip + // orientation at the right place + dragOptions.minDrag = 1; + + zoomPrep(e, startX, startY); + } else if(dragModeNow === 'pan') { + dragOptions.moveFn = plotDrag; + dragOptions.doneFn = dragTail; + } + } + } + }; + + function clearAndResetSelect() { + // clear selection polygon cache (if any) + dragOptions.plotinfo.selection = false; + // clear selection outlines + clearSelect(zoomlayer); + } + + function clickFn(numClicks, evt) { + var clickmode = gd._fullLayout.clickmode; + + removeZoombox(gd); + + if(numClicks === 2 && !singleEnd) doubleClick(); + + if(isMainDrag) { + if(clickmode.indexOf('select') > -1) { + selectOnClick(evt, gd, xaxes, yaxes, plotinfo.id, dragOptions); + } + + if(clickmode.indexOf('event') > -1) { + Fx.click(gd, evt, plotinfo.id); + } + } + else if(numClicks === 1 && singleEnd) { + var ax = ns ? ya0 : xa0, + end = (ns === 's' || ew === 'w') ? 0 : 1, + attrStr = ax._name + '.range[' + end + ']', + initialText = getEndText(ax, end), + hAlign = 'left', + vAlign = 'middle'; + + if(ax.fixedrange) return; + + if(ns) { + vAlign = (ns === 'n') ? 'top' : 'bottom'; + if(ax.side === 'right') hAlign = 'right'; + } + else if(ew === 'e') hAlign = 'right'; + + if(gd._context.showAxisRangeEntryBoxes) { + d3.select(dragger) + .call(svgTextUtils.makeEditable, { + gd: gd, + immediate: true, + background: gd._fullLayout.paper_bgcolor, + text: String(initialText), + fill: ax.tickfont ? ax.tickfont.color : '#444', + horizontalAlign: hAlign, + verticalAlign: vAlign + }) + .on('edit', function(text) { + var v = ax.d2r(text); + if(v !== undefined) { + Registry.call('relayout', gd, attrStr, v); + } + }); + } + } + } + + dragElement.init(dragOptions); + + var x0, + y0, + box, + lum, + path0, + dimmed, + zoomMode, + zb, + corners; + + // zoom takes over minDrag, so it also has to take over gd._dragged + var zoomDragged; + + function zoomPrep(e, startX, startY) { + var dragBBox = dragger.getBoundingClientRect(); + x0 = startX - dragBBox.left; + y0 = startY - dragBBox.top; + box = {l: x0, r: x0, w: 0, t: y0, b: y0, h: 0}; + lum = gd._hmpixcount ? + (gd._hmlumcount / gd._hmpixcount) : + tinycolor(gd._fullLayout.plot_bgcolor).getLuminance(); + path0 = 'M0,0H' + pw + 'V' + ph + 'H0V0'; + dimmed = false; + zoomMode = 'xy'; + zoomDragged = false; + + zb = makeZoombox(zoomlayer, lum, xs, ys, path0); + + corners = makeCorners(zoomlayer, xs, ys); + } + + function zoomMove(dx0, dy0) { + if(gd._transitioningWithDuration) { + return false; + } + + var x1 = Math.max(0, Math.min(pw, dx0 + x0)), + y1 = Math.max(0, Math.min(ph, dy0 + y0)), + dx = Math.abs(x1 - x0), + dy = Math.abs(y1 - y0); + + box.l = Math.min(x0, x1); + box.r = Math.max(x0, x1); + box.t = Math.min(y0, y1); + box.b = Math.max(y0, y1); + + function noZoom() { + zoomMode = ''; + box.r = box.l; + box.t = box.b; + corners.attr('d', 'M0,0Z'); + } + + if(isSubplotConstrained) { + if(dx > MINZOOM || dy > MINZOOM) { + zoomMode = 'xy'; + if(dx / pw > dy / ph) { + dy = dx * ph / pw; + if(y0 > y1) box.t = y0 - dy; + else box.b = y0 + dy; + } + else { + dx = dy * pw / ph; + if(x0 > x1) box.l = x0 - dx; + else box.r = x0 + dx; + } + corners.attr('d', xyCorners(box)); + } + else { + noZoom(); + } + } + // look for small drags in one direction or the other, + // and only drag the other axis + else if(!yActive || dy < Math.min(Math.max(dx * 0.6, MINDRAG), MINZOOM)) { + if(dx < MINDRAG || !xActive) { + noZoom(); + } else { + box.t = 0; + box.b = ph; + zoomMode = 'x'; + corners.attr('d', xCorners(box, y0)); + } + } + else if(!xActive || dx < Math.min(dy * 0.6, MINZOOM)) { + box.l = 0; + box.r = pw; + zoomMode = 'y'; + corners.attr('d', yCorners(box, x0)); + } + else { + zoomMode = 'xy'; + corners.attr('d', xyCorners(box)); + } + box.w = box.r - box.l; + box.h = box.b - box.t; + + if(zoomMode) zoomDragged = true; + gd._dragged = zoomDragged; + + updateZoombox(zb, corners, box, path0, dimmed, lum); + dimmed = true; + } + + function zoomDone() { + updates = {}; + + // more strict than dragged, which allows you to come back to where you started + // and still count as dragged + if(Math.min(box.h, box.w) < MINDRAG * 2) { + return removeZoombox(gd); + } + + // TODO: edit linked axes in zoomAxRanges and in dragTail + if(zoomMode === 'xy' || zoomMode === 'x') { + zoomAxRanges(xaxes, box.l / pw, box.r / pw, updates, links.xaxes); + } + if(zoomMode === 'xy' || zoomMode === 'y') { + zoomAxRanges(yaxes, (ph - box.b) / ph, (ph - box.t) / ph, updates, links.yaxes); + } + + removeZoombox(gd); + dragTail(); + showDoubleClickNotifier(gd); + } + + // scroll zoom, on all draggers except corners + var scrollViewBox = [0, 0, pw, ph]; + // wait a little after scrolling before redrawing + var redrawTimer = null; + var REDRAWDELAY = constants.REDRAWDELAY; + var mainplot = plotinfo.mainplot ? gd._fullLayout._plots[plotinfo.mainplot] : plotinfo; + + function zoomWheel(e) { + // deactivate mousewheel scrolling on embedded graphs + // devs can override this with layout._enablescrollzoom, + // but _ ensures this setting won't leave their page + if(!gd._context.scrollZoom && !gd._fullLayout._enablescrollzoom) { + return; + } + + clearAndResetSelect(); + + // If a transition is in progress, then disable any behavior: + if(gd._transitioningWithDuration) { + e.preventDefault(); + e.stopPropagation(); + return; + } + + var pc = gd.querySelector('.plotly'); + + recomputeAxisLists(); + + // if the plot has scrollbars (more than a tiny excess) + // disable scrollzoom too. + if(pc.scrollHeight - pc.clientHeight > 10 || + pc.scrollWidth - pc.clientWidth > 10) { + return; + } + + clearTimeout(redrawTimer); + + var wheelDelta = -e.deltaY; + if(!isFinite(wheelDelta)) wheelDelta = e.wheelDelta / 10; + if(!isFinite(wheelDelta)) { + Lib.log('Did not find wheel motion attributes: ', e); + return; + } + + var zoom = Math.exp(-Math.min(Math.max(wheelDelta, -20), 20) / 200), + gbb = mainplot.draglayer.select('.nsewdrag') + .node().getBoundingClientRect(), + xfrac = (e.clientX - gbb.left) / gbb.width, + yfrac = (gbb.bottom - e.clientY) / gbb.height, + i; + + function zoomWheelOneAxis(ax, centerFraction, zoom) { + if(ax.fixedrange) return; + + var axRange = Lib.simpleMap(ax.range, ax.r2l), + v0 = axRange[0] + (axRange[1] - axRange[0]) * centerFraction; + function doZoom(v) { return ax.l2r(v0 + (v - v0) * zoom); } + ax.range = axRange.map(doZoom); + } + + if(editX) { + // if we're only zooming this axis because of constraints, + // zoom it about the center + if(!ew) xfrac = 0.5; + + for(i = 0; i < xaxes.length; i++) { + zoomWheelOneAxis(xaxes[i], xfrac, zoom); + } + + scrollViewBox[2] *= zoom; + scrollViewBox[0] += scrollViewBox[2] * xfrac * (1 / zoom - 1); + } + if(editY) { + if(!ns) yfrac = 0.5; + + for(i = 0; i < yaxes.length; i++) { + zoomWheelOneAxis(yaxes[i], yfrac, zoom); + } + + scrollViewBox[3] *= zoom; + scrollViewBox[1] += scrollViewBox[3] * (1 - yfrac) * (1 / zoom - 1); + } + + // viewbox redraw at first + updateSubplots(scrollViewBox); + ticksAndAnnotations(ns, ew); + + // then replot after a delay to make sure + // no more scrolling is coming + redrawTimer = setTimeout(function() { + scrollViewBox = [0, 0, pw, ph]; + dragTail(); + }, REDRAWDELAY); + + e.preventDefault(); + return; + } + + // everything but the corners gets wheel zoom + if(ns.length * ew.length !== 1) { + attachWheelEventHandler(dragger, zoomWheel); + } + + // plotDrag: move the plot in response to a drag + function plotDrag(dx, dy) { + // If a transition is in progress, then disable any behavior: + if(gd._transitioningWithDuration) { + return; + } + + if(xActive === 'ew' || yActive === 'ns') { + if(xActive) dragAxList(xaxes, dx); + if(yActive) dragAxList(yaxes, dy); + updateSubplots([xActive ? -dx : 0, yActive ? -dy : 0, pw, ph]); + ticksAndAnnotations(yActive, xActive); + return; + } + + // dz: set a new value for one end (0 or 1) of an axis array axArray, + // and return a pixel shift for that end for the viewbox + // based on pixel drag distance d + // TODO: this makes (generally non-fatal) errors when you get + // near floating point limits + function dz(axArray, end, d) { + var otherEnd = 1 - end, + movedAx, + newLinearizedEnd; + for(var i = 0; i < axArray.length; i++) { + var axi = axArray[i]; + if(axi.fixedrange) continue; + movedAx = axi; + newLinearizedEnd = axi._rl[otherEnd] + + (axi._rl[end] - axi._rl[otherEnd]) / dZoom(d / axi._length); + var newEnd = axi.l2r(newLinearizedEnd); + + // if l2r comes back false or undefined, it means we've dragged off + // the end of valid ranges - so stop. + if(newEnd !== false && newEnd !== undefined) axi.range[end] = newEnd; + } + return movedAx._length * (movedAx._rl[end] - newLinearizedEnd) / + (movedAx._rl[end] - movedAx._rl[otherEnd]); + } + + if(isSubplotConstrained && xActive && yActive) { + // dragging a corner of a constrained subplot: + // respect the fixed corner, but harmonize dx and dy + var dxySign = ((xActive === 'w') === (yActive === 'n')) ? 1 : -1; + var dxyFraction = (dx / pw + dxySign * dy / ph) / 2; + dx = dxyFraction * pw; + dy = dxySign * dxyFraction * ph; + } + + if(xActive === 'w') dx = dz(xaxes, 0, dx); + else if(xActive === 'e') dx = dz(xaxes, 1, -dx); + else if(!xActive) dx = 0; + + if(yActive === 'n') dy = dz(yaxes, 1, dy); + else if(yActive === 's') dy = dz(yaxes, 0, -dy); + else if(!yActive) dy = 0; + + var x0 = (xActive === 'w') ? dx : 0; + var y0 = (yActive === 'n') ? dy : 0; + + if(isSubplotConstrained) { + var i; + if(!xActive && yActive.length === 1) { + // dragging one end of the y axis of a constrained subplot + // scale the other axis the same about its middle + for(i = 0; i < xaxes.length; i++) { + xaxes[i].range = xaxes[i]._r.slice(); + scaleZoom(xaxes[i], 1 - dy / ph); + } + dx = dy * pw / ph; + x0 = dx / 2; + } + if(!yActive && xActive.length === 1) { + for(i = 0; i < yaxes.length; i++) { + yaxes[i].range = yaxes[i]._r.slice(); + scaleZoom(yaxes[i], 1 - dx / pw); + } + dy = dx * ph / pw; + y0 = dy / 2; + } + } + + updateSubplots([x0, y0, pw - dx, ph - dy]); + ticksAndAnnotations(yActive, xActive); + } + + // Draw ticks and annotations (and other components) when ranges change. + // Also records the ranges that have changed for use by update at the end. + function ticksAndAnnotations(ns, ew) { + var activeAxIds = [], + i; + + function pushActiveAxIds(axList) { + for(i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) activeAxIds.push(axList[i]._id); + } + } + + if(editX) { + pushActiveAxIds(xaxes); + pushActiveAxIds(links.xaxes); + } + if(editY) { + pushActiveAxIds(yaxes); + pushActiveAxIds(links.yaxes); + } + + updates = {}; + for(i = 0; i < activeAxIds.length; i++) { + var axId = activeAxIds[i]; + doTicksSingle(gd, axId, true); + var ax = getFromId(gd, axId); + updates[ax._name + '.range[0]'] = ax.range[0]; + updates[ax._name + '.range[1]'] = ax.range[1]; + } + + function redrawObjs(objArray, method, shortCircuit) { + for(i = 0; i < objArray.length; i++) { + var obji = objArray[i]; + + if((ew && activeAxIds.indexOf(obji.xref) !== -1) || + (ns && activeAxIds.indexOf(obji.yref) !== -1)) { + method(gd, i); + // once is enough for images (which doesn't use the `i` arg anyway) + if(shortCircuit) return; + } + } + } + + // annotations and shapes 'draw' method is slow, + // use the finer-grained 'drawOne' method instead + + redrawObjs(gd._fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(gd._fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(gd._fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true); + } + + function doubleClick() { + if(gd._transitioningWithDuration) return; + + var doubleClickConfig = gd._context.doubleClick, + axList = (xActive ? xaxes : []).concat(yActive ? yaxes : []), + attrs = {}; + + var ax, i, rangeInitial; + + // For reset+autosize mode: + // If *any* of the main axes is not at its initial range + // (or autoranged, if we have no initial range, to match the logic in + // doubleClickConfig === 'reset' below), we reset. + // If they are *all* at their initial ranges, then we autosize. + if(doubleClickConfig === 'reset+autosize') { + + doubleClickConfig = 'autosize'; + + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + if((ax._rangeInitial && ( + ax.range[0] !== ax._rangeInitial[0] || + ax.range[1] !== ax._rangeInitial[1] + )) || + (!ax._rangeInitial && !ax.autorange) + ) { + doubleClickConfig = 'reset'; + break; + } + } + } + + if(doubleClickConfig === 'autosize') { + // don't set the linked axes here, so relayout marks them as shrinkable + // and we autosize just to the requested axis/axes + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + if(!ax.fixedrange) attrs[ax._name + '.autorange'] = true; + } + } + else if(doubleClickConfig === 'reset') { + // when we're resetting, reset all linked axes too, so we get back + // to the fully-auto-with-constraints situation + if(xActive || isSubplotConstrained) axList = axList.concat(links.xaxes); + if(yActive && !isSubplotConstrained) axList = axList.concat(links.yaxes); + + if(isSubplotConstrained) { + if(!xActive) axList = axList.concat(xaxes); + else if(!yActive) axList = axList.concat(yaxes); + } + + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + + if(!ax._rangeInitial) { + attrs[ax._name + '.autorange'] = true; + } + else { + rangeInitial = ax._rangeInitial; + attrs[ax._name + '.range[0]'] = rangeInitial[0]; + attrs[ax._name + '.range[1]'] = rangeInitial[1]; + } + } + } + + gd.emit('plotly_doubleclick', null); + Registry.call('relayout', gd, attrs); + } + + // dragTail - finish a drag event with a redraw + function dragTail() { + // put the subplot viewboxes back to default (Because we're going to) + // be repositioning the data in the relayout. But DON'T call + // ticksAndAnnotations again - it's unnecessary and would overwrite `updates` + updateSubplots([0, 0, pw, ph]); + + // since we may have been redrawing some things during the drag, we may have + // accumulated MathJax promises - wait for them before we relayout. + Lib.syncOrAsync([ + Plots.previousPromises, + function() { Registry.call('relayout', gd, updates); } + ], gd); + } + + // x/y scaleFactor stash, + // minimizes number of per-point DOM updates in updateSubplots below + var xScaleFactorOld, yScaleFactorOld; + + // updateSubplots - find all plot viewboxes that should be + // affected by this drag, and update them. look for all plots + // sharing an affected axis (including the one being dragged), + // includes also scattergl and splom logic. + function updateSubplots(viewBox) { + var fullLayout = gd._fullLayout; + var plotinfos = fullLayout._plots; + var subplots = fullLayout._subplots.cartesian; + var i, sp, xa, ya; + + if(hasSplom) { + Registry.subplotsRegistry.splom.drag(gd); + } + + if(hasScatterGl) { + for(i = 0; i < subplots.length; i++) { + sp = plotinfos[subplots[i]]; + xa = sp.xaxis; + ya = sp.yaxis; + + if(sp._scene) { + var xrng = Lib.simpleMap(xa.range, xa.r2l); + var yrng = Lib.simpleMap(ya.range, ya.r2l); + sp._scene.update({range: [xrng[0], yrng[0], xrng[1], yrng[1]]}); + } + } + } + + if(hasSplom || hasScatterGl) { + clearGlCanvases(gd); + redrawReglTraces(gd); + } + + if(hasSVG) { + var xScaleFactor = viewBox[2] / xa0._length; + var yScaleFactor = viewBox[3] / ya0._length; + + for(i = 0; i < subplots.length; i++) { + sp = plotinfos[subplots[i]]; + xa = sp.xaxis; + ya = sp.yaxis; + + var editX2 = editX && !xa.fixedrange && xaHash[xa._id]; + var editY2 = editY && !ya.fixedrange && yaHash[ya._id]; + + var xScaleFactor2, yScaleFactor2; + var clipDx, clipDy; + + if(editX2) { + xScaleFactor2 = xScaleFactor; + clipDx = ew ? viewBox[0] : getShift(xa, xScaleFactor2); + } else { + xScaleFactor2 = getLinkedScaleFactor(xa, xScaleFactor, yScaleFactor); + clipDx = scaleAndGetShift(xa, xScaleFactor2); + } + + if(editY2) { + yScaleFactor2 = yScaleFactor; + clipDy = ns ? viewBox[1] : getShift(ya, yScaleFactor2); + } else { + yScaleFactor2 = getLinkedScaleFactor(ya, xScaleFactor, yScaleFactor); + clipDy = scaleAndGetShift(ya, yScaleFactor2); + } + + // don't scale at all if neither axis is scalable here + if(!xScaleFactor2 && !yScaleFactor2) { + continue; + } + + // but if only one is, reset the other axis scaling + if(!xScaleFactor2) xScaleFactor2 = 1; + if(!yScaleFactor2) yScaleFactor2 = 1; + + var plotDx = xa._offset - clipDx / xScaleFactor2; + var plotDy = ya._offset - clipDy / yScaleFactor2; + + // TODO could be more efficient here: + // setTranslate and setScale do a lot of extra work + // when working independently, should perhaps combine + // them into a single routine. + sp.clipRect + .call(Drawing.setTranslate, clipDx, clipDy) + .call(Drawing.setScale, xScaleFactor2, yScaleFactor2); + + sp.plot + .call(Drawing.setTranslate, plotDx, plotDy) + .call(Drawing.setScale, 1 / xScaleFactor2, 1 / yScaleFactor2); + + // apply an inverse scale to individual points to counteract + // the scale of the trace group. + // apply only when scale changes, as adjusting the scale of + // all the points can be expansive. + if(xScaleFactor2 !== xScaleFactorOld || yScaleFactor2 !== yScaleFactorOld) { + Drawing.setPointGroupScale(sp.zoomScalePts, xScaleFactor2, yScaleFactor2); + Drawing.setTextPointsScale(sp.zoomScaleTxt, xScaleFactor2, yScaleFactor2); + } + + Drawing.hideOutsideRangePoints(sp.clipOnAxisFalseTraces, sp); + + // update x/y scaleFactor stash + xScaleFactorOld = xScaleFactor2; + yScaleFactorOld = yScaleFactor2; + } + } + } + + // Find the appropriate scaling for this axis, if it's linked to the + // dragged axes by constraints. 0 is special, it means this axis shouldn't + // ever be scaled (will be converted to 1 if the other axis is scaled) + function getLinkedScaleFactor(ax, xScaleFactor, yScaleFactor) { + if(ax.fixedrange) return 0; + + if(editX && links.xaHash[ax._id]) { + return xScaleFactor; + } + if(editY && (isSubplotConstrained ? links.xaHash : links.yaHash)[ax._id]) { + return yScaleFactor; + } + return 0; + } + + function scaleAndGetShift(ax, scaleFactor) { + if(scaleFactor) { + ax.range = ax._r.slice(); + scaleZoom(ax, scaleFactor); + return getShift(ax, scaleFactor); + } + return 0; + } + + function getShift(ax, scaleFactor) { + return ax._length * (1 - scaleFactor) * FROM_TL[ax.constraintoward || 'middle']; + } + + return dragger; +} + +function makeDragger(plotinfo, nodeName, dragClass, cursor) { + var dragger3 = Lib.ensureSingle(plotinfo.draglayer, nodeName, dragClass, function(s) { + s.classed('drag', true) + .style({fill: 'transparent', 'stroke-width': 0}) + .attr('data-subplot', plotinfo.id); + }); + + dragger3.call(setCursor, cursor); + + return dragger3.node(); +} + +function makeRectDragger(plotinfo, dragClass, cursor, x, y, w, h) { + var dragger = makeDragger(plotinfo, 'rect', dragClass, cursor); + d3.select(dragger).call(Drawing.setRect, x, y, w, h); + return dragger; +} + +function isDirectionActive(axList, activeVal) { + for(var i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) return activeVal; + } + return ''; +} + +function getEndText(ax, end) { + var initialVal = ax.range[end], + diff = Math.abs(initialVal - ax.range[1 - end]), + dig; + + // TODO: this should basically be ax.r2d but we're doing extra + // rounding here... can we clean up at all? + if(ax.type === 'date') { + return initialVal; + } + else if(ax.type === 'log') { + dig = Math.ceil(Math.max(0, -Math.log(diff) / Math.LN10)) + 3; + return d3.format('.' + dig + 'g')(Math.pow(10, initialVal)); + } + else { // linear numeric (or category... but just show numbers here) + dig = Math.floor(Math.log(Math.abs(initialVal)) / Math.LN10) - + Math.floor(Math.log(diff) / Math.LN10) + 4; + return d3.format('.' + String(dig) + 'g')(initialVal); + } +} + +function zoomAxRanges(axList, r0Fraction, r1Fraction, updates, linkedAxes) { + var i, + axi, + axRangeLinear0, + axRangeLinearSpan; + + for(i = 0; i < axList.length; i++) { + axi = axList[i]; + if(axi.fixedrange) continue; + + axRangeLinear0 = axi._rl[0]; + axRangeLinearSpan = axi._rl[1] - axRangeLinear0; + axi.range = [ + axi.l2r(axRangeLinear0 + axRangeLinearSpan * r0Fraction), + axi.l2r(axRangeLinear0 + axRangeLinearSpan * r1Fraction) + ]; + + updates[axi._name + '.range[0]'] = axi.range[0]; + updates[axi._name + '.range[1]'] = axi.range[1]; + } + + // zoom linked axes about their centers + if(linkedAxes && linkedAxes.length) { + var linkedR0Fraction = (r0Fraction + (1 - r1Fraction)) / 2; + + zoomAxRanges(linkedAxes, linkedR0Fraction, 1 - linkedR0Fraction, updates); + } +} + +function dragAxList(axList, pix) { + for(var i = 0; i < axList.length; i++) { + var axi = axList[i]; + if(!axi.fixedrange) { + axi.range = [ + axi.l2r(axi._rl[0] - pix / axi._m), + axi.l2r(axi._rl[1] - pix / axi._m) + ]; + } + } +} + +// common transform for dragging one end of an axis +// d>0 is compressing scale (cursor is over the plot, +// the axis end should move with the cursor) +// d<0 is expanding (cursor is off the plot, axis end moves +// nonlinearly so you can expand far) +function dZoom(d) { + return 1 - ((d >= 0) ? Math.min(d, 0.9) : + 1 / (1 / Math.max(d, -0.3) + 3.222)); +} + +function getDragCursor(nsew, dragmode, isMainDrag) { + if(!nsew) return 'pointer'; + if(nsew === 'nsew') { + // in this case here, clear cursor and + // use the cursor style set on + if(isMainDrag) return ''; + if(dragmode === 'pan') return 'move'; + return 'crosshair'; + } + return nsew.toLowerCase() + '-resize'; +} + +function makeZoombox(zoomlayer, lum, xs, ys, path0) { + return zoomlayer.append('path') + .attr('class', 'zoombox') + .style({ + 'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)', + 'stroke-width': 0 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', path0 + 'Z'); +} + +function makeCorners(zoomlayer, xs, ys) { + return zoomlayer.append('path') + .attr('class', 'zoombox-corners') + .style({ + fill: Color.background, + stroke: Color.defaultLine, + 'stroke-width': 1, + opacity: 0 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', 'M0,0Z'); +} + +function updateZoombox(zb, corners, box, path0, dimmed, lum) { + zb.attr('d', + path0 + 'M' + (box.l) + ',' + (box.t) + 'v' + (box.h) + + 'h' + (box.w) + 'v-' + (box.h) + 'h-' + (box.w) + 'Z'); + transitionZoombox(zb, corners, dimmed, lum); +} + +function transitionZoombox(zb, corners, dimmed, lum) { + if(!dimmed) { + zb.transition() + .style('fill', lum > 0.2 ? 'rgba(0,0,0,0.4)' : + 'rgba(255,255,255,0.3)') + .duration(200); + corners.transition() + .style('opacity', 1) + .duration(200); + } +} + +function removeZoombox(gd) { + d3.select(gd) + .selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners') + .remove(); +} + +function showDoubleClickNotifier(gd) { + if(SHOWZOOMOUTTIP && gd.data && gd._context.showTips) { + Lib.notifier(Lib._(gd, 'Double-click to zoom back out'), 'long'); + SHOWZOOMOUTTIP = false; + } +} + +function isSelectOrLasso(dragmode) { + return dragmode === 'lasso' || dragmode === 'select'; +} + +function xCorners(box, y0) { + return 'M' + + (box.l - 0.5) + ',' + (y0 - MINZOOM - 0.5) + + 'h-3v' + (2 * MINZOOM + 1) + 'h3ZM' + + (box.r + 0.5) + ',' + (y0 - MINZOOM - 0.5) + + 'h3v' + (2 * MINZOOM + 1) + 'h-3Z'; +} + +function yCorners(box, x0) { + return 'M' + + (x0 - MINZOOM - 0.5) + ',' + (box.t - 0.5) + + 'v-3h' + (2 * MINZOOM + 1) + 'v3ZM' + + (x0 - MINZOOM - 0.5) + ',' + (box.b + 0.5) + + 'v3h' + (2 * MINZOOM + 1) + 'v-3Z'; +} + +function xyCorners(box) { + var clen = Math.floor(Math.min(box.b - box.t, box.r - box.l, MINZOOM) / 2); + return 'M' + + (box.l - 3.5) + ',' + (box.t - 0.5 + clen) + 'h3v' + (-clen) + + 'h' + clen + 'v-3h-' + (clen + 3) + 'ZM' + + (box.r + 3.5) + ',' + (box.t - 0.5 + clen) + 'h-3v' + (-clen) + + 'h' + (-clen) + 'v-3h' + (clen + 3) + 'ZM' + + (box.r + 3.5) + ',' + (box.b + 0.5 - clen) + 'h-3v' + clen + + 'h' + (-clen) + 'v3h' + (clen + 3) + 'ZM' + + (box.l - 3.5) + ',' + (box.b + 0.5 - clen) + 'h3v' + clen + + 'h' + clen + 'v3h-' + (clen + 3) + 'Z'; +} + +function calcLinks(gd, xaHash, yaHash) { + var constraintGroups = gd._fullLayout._axisConstraintGroups; + var isSubplotConstrained = false; + var xLinks = {}; + var yLinks = {}; + var xID, yID, xLinkID, yLinkID; + + for(var i = 0; i < constraintGroups.length; i++) { + var group = constraintGroups[i]; + // check if any of the x axes we're dragging is in this constraint group + for(xID in xaHash) { + if(group[xID]) { + // put the rest of these axes into xLinks, if we're not already + // dragging them, so we know to scale these axes automatically too + // to match the changes in the dragged x axes + for(xLinkID in group) { + if(!(xLinkID.charAt(0) === 'x' ? xaHash : yaHash)[xLinkID]) { + xLinks[xLinkID] = 1; + } + } + + // check if the x and y axes of THIS drag are linked + for(yID in yaHash) { + if(group[yID]) isSubplotConstrained = true; + } + } + } + + // now check if any of the y axes we're dragging is in this constraint group + // only look for outside links, as we've already checked for links within the dragger + for(yID in yaHash) { + if(group[yID]) { + for(yLinkID in group) { + if(!(yLinkID.charAt(0) === 'x' ? xaHash : yaHash)[yLinkID]) { + yLinks[yLinkID] = 1; + } + } + } + } + } + + if(isSubplotConstrained) { + // merge xLinks and yLinks if the subplot is constrained, + // since we'll always apply both anyway and the two will contain + // duplicates + Lib.extendFlat(xLinks, yLinks); + yLinks = {}; + } + + var xaHashLinked = {}; + var xaxesLinked = []; + for(xLinkID in xLinks) { + var xa = getFromId(gd, xLinkID); + xaxesLinked.push(xa); + xaHashLinked[xa._id] = xa; + } + + var yaHashLinked = {}; + var yaxesLinked = []; + for(yLinkID in yLinks) { + var ya = getFromId(gd, yLinkID); + yaxesLinked.push(ya); + yaHashLinked[ya._id] = ya; + } + + return { + xaHash: xaHashLinked, + yaHash: yaHashLinked, + xaxes: xaxesLinked, + yaxes: yaxesLinked, + isSubplotConstrained: isSubplotConstrained + }; +} + +// still seems to be some confusion about onwheel vs onmousewheel... +function attachWheelEventHandler(element, handler) { + if(!supportsPassive) { + if(element.onwheel !== undefined) element.onwheel = handler; + else if(element.onmousewheel !== undefined) element.onmousewheel = handler; + } + else { + var wheelEventName = element.onwheel !== undefined ? 'wheel' : 'mousewheel'; + + if(element._onwheel) { + element.removeEventListener(wheelEventName, element._onwheel); + } + element._onwheel = handler; + + element.addEventListener(wheelEventName, handler, {passive: false}); + } +} + +function hashValues(hash) { + var out = []; + for(var k in hash) out.push(hash[k]); + return out; +} + +module.exports = { + makeDragBox: makeDragBox, + + makeDragger: makeDragger, + makeRectDragger: makeRectDragger, + makeZoombox: makeZoombox, + makeCorners: makeCorners, + + updateZoombox: updateZoombox, + xyCorners: xyCorners, + transitionZoombox: transitionZoombox, + removeZoombox: removeZoombox, + showDoubleClickNotifier: showDoubleClickNotifier, + + attachWheelEventHandler: attachWheelEventHandler +}; + +},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../constants/alignment":668,"../../lib":696,"../../lib/clear_gl_canvases":680,"../../lib/setcursor":716,"../../lib/svg_text_utils":720,"../../plot_api/subroutines":735,"../../registry":827,"../plots":808,"./axes":744,"./axis_ids":747,"./constants":750,"./scale_zoom":761,"./select":762,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"has-passive-events":394,"tinycolor2":514}],754:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Fx = _dereq_('../../components/fx'); +var dragElement = _dereq_('../../components/dragelement'); +var setCursor = _dereq_('../../lib/setcursor'); + +var makeDragBox = _dereq_('./dragbox').makeDragBox; +var DRAGGERSIZE = _dereq_('./constants').DRAGGERSIZE; + +exports.initInteractions = function initInteractions(gd) { + var fullLayout = gd._fullLayout; + + if(gd._context.staticPlot) { + // this sweeps up more than just cartesian drag elements... + d3.select(gd).selectAll('.drag').remove(); + return; + } + + if(!fullLayout._has('cartesian') && !fullLayout._has('splom')) return; + + var subplots = Object.keys(fullLayout._plots || {}).sort(function(a, b) { + // sort overlays last, then by x axis number, then y axis number + if((fullLayout._plots[a].mainplot && true) === + (fullLayout._plots[b].mainplot && true)) { + var aParts = a.split('y'), + bParts = b.split('y'); + return (aParts[0] === bParts[0]) ? + (Number(aParts[1] || 1) - Number(bParts[1] || 1)) : + (Number(aParts[0] || 1) - Number(bParts[0] || 1)); + } + return fullLayout._plots[a].mainplot ? 1 : -1; + }); + + subplots.forEach(function(subplot) { + var plotinfo = fullLayout._plots[subplot]; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + // main and corner draggers need not be repeated for + // overlaid subplots - these draggers drag them all + if(!plotinfo.mainplot) { + // main dragger goes over the grids and data, so we use its + // mousemove events for all data hover effects + var maindrag = makeDragBox(gd, plotinfo, xa._offset, ya._offset, + xa._length, ya._length, 'ns', 'ew'); + + maindrag.onmousemove = function(evt) { + // This is on `gd._fullLayout`, *not* fullLayout because the reference + // changes by the time this is called again. + gd._fullLayout._rehover = function() { + if(gd._fullLayout._hoversubplot === subplot) { + Fx.hover(gd, evt, subplot); + } + }; + + Fx.hover(gd, evt, subplot); + + // Note that we have *not* used the cached fullLayout variable here + // since that may be outdated when this is called as a callback later on + gd._fullLayout._lasthover = maindrag; + gd._fullLayout._hoversubplot = subplot; + }; + + /* + * IMPORTANT: + * We must check for the presence of the drag cover here. + * If we don't, a 'mouseout' event is triggered on the + * maindrag before each 'click' event, which has the effect + * of clearing the hoverdata; thus, cancelling the click event. + */ + maindrag.onmouseout = function(evt) { + if(gd._dragging) return; + + // When the mouse leaves this maindrag, unset the hovered subplot. + // This may cause problems if it leaves the subplot directly *onto* + // another subplot, but that's a tiny corner case at the moment. + gd._fullLayout._hoversubplot = null; + + dragElement.unhover(gd, evt); + }; + + // corner draggers + if(gd._context.showAxisDragHandles) { + makeDragBox(gd, plotinfo, xa._offset - DRAGGERSIZE, ya._offset - DRAGGERSIZE, + DRAGGERSIZE, DRAGGERSIZE, 'n', 'w'); + makeDragBox(gd, plotinfo, xa._offset + xa._length, ya._offset - DRAGGERSIZE, + DRAGGERSIZE, DRAGGERSIZE, 'n', 'e'); + makeDragBox(gd, plotinfo, xa._offset - DRAGGERSIZE, ya._offset + ya._length, + DRAGGERSIZE, DRAGGERSIZE, 's', 'w'); + makeDragBox(gd, plotinfo, xa._offset + xa._length, ya._offset + ya._length, + DRAGGERSIZE, DRAGGERSIZE, 's', 'e'); + } + } + if(gd._context.showAxisDragHandles) { + // x axis draggers - if you have overlaid plots, + // these drag each axis separately + if(subplot === xa._mainSubplot) { + // the y position of the main x axis line + var y0 = xa._mainLinePosition; + if(xa.side === 'top') y0 -= DRAGGERSIZE; + makeDragBox(gd, plotinfo, xa._offset + xa._length * 0.1, y0, + xa._length * 0.8, DRAGGERSIZE, '', 'ew'); + makeDragBox(gd, plotinfo, xa._offset, y0, + xa._length * 0.1, DRAGGERSIZE, '', 'w'); + makeDragBox(gd, plotinfo, xa._offset + xa._length * 0.9, y0, + xa._length * 0.1, DRAGGERSIZE, '', 'e'); + } + // y axis draggers + if(subplot === ya._mainSubplot) { + // the x position of the main y axis line + var x0 = ya._mainLinePosition; + if(ya.side !== 'right') x0 -= DRAGGERSIZE; + makeDragBox(gd, plotinfo, x0, ya._offset + ya._length * 0.1, + DRAGGERSIZE, ya._length * 0.8, 'ns', ''); + makeDragBox(gd, plotinfo, x0, ya._offset + ya._length * 0.9, + DRAGGERSIZE, ya._length * 0.1, 's', ''); + makeDragBox(gd, plotinfo, x0, ya._offset, + DRAGGERSIZE, ya._length * 0.1, 'n', ''); + } + } + }); + + // In case you mousemove over some hovertext, send it to Fx.hover too + // we do this so that we can put the hover text in front of everything, + // but still be able to interact with everything as if it isn't there + var hoverLayer = fullLayout._hoverlayer.node(); + + hoverLayer.onmousemove = function(evt) { + evt.target = gd._fullLayout._lasthover; + Fx.hover(gd, evt, fullLayout._hoversubplot); + }; + + hoverLayer.onclick = function(evt) { + evt.target = gd._fullLayout._lasthover; + Fx.click(gd, evt); + }; + + // also delegate mousedowns... TODO: does this actually work? + hoverLayer.onmousedown = function(evt) { + gd._fullLayout._lasthover.onmousedown(evt); + }; + + exports.updateFx(gd); +}; + +// Minimal set of update needed on 'modebar' edits. +// We only need to update the cursor style. +// +// Note that changing the axis configuration and/or the fixedrange attribute +// should trigger a full initInteractions. +exports.updateFx = function(gd) { + var fullLayout = gd._fullLayout; + var cursor = fullLayout.dragmode === 'pan' ? 'move' : 'crosshair'; + setCursor(fullLayout._draggers, cursor); +}; + +},{"../../components/dragelement":592,"../../components/fx":612,"../../lib/setcursor":716,"./constants":750,"./dragbox":753,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],755:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +/** + * Factory function for checking component arrays for subplot references. + * + * @param {string} containerArrayName: the top-level array in gd.layout to check + * If an item in this container is found that references a cartesian x and/or y axis, + * ensure cartesian is marked as a base plot module and record the axes (and subplot + * if both refs are axes) in gd._fullLayout + * + * @return {function}: with args layoutIn (gd.layout) and layoutOut (gd._fullLayout) + * as expected of a component includeBasePlot method + */ +module.exports = function makeIncludeComponents(containerArrayName) { + return function includeComponents(layoutIn, layoutOut) { + var array = layoutIn[containerArrayName]; + if(!Array.isArray(array)) return; + + var Cartesian = Registry.subplotsRegistry.cartesian; + var idRegex = Cartesian.idRegex; + var subplots = layoutOut._subplots; + var xaList = subplots.xaxis; + var yaList = subplots.yaxis; + var cartesianList = subplots.cartesian; + var hasCartesianOrGL2D = layoutOut._has('cartesian') || layoutOut._has('gl2d'); + + for(var i = 0; i < array.length; i++) { + var itemi = array[i]; + if(!Lib.isPlainObject(itemi)) continue; + + var xref = itemi.xref; + var yref = itemi.yref; + + var hasXref = idRegex.x.test(xref); + var hasYref = idRegex.y.test(yref); + if(hasXref || hasYref) { + if(!hasCartesianOrGL2D) Lib.pushUnique(layoutOut._basePlotModules, Cartesian); + + var newAxis = false; + if(hasXref && xaList.indexOf(xref) === -1) { + xaList.push(xref); + newAxis = true; + } + if(hasYref && yaList.indexOf(yref) === -1) { + yaList.push(yref); + newAxis = true; + } + + /* + * Notice the logic here: only add a subplot for a component if + * it's referencing both x and y axes AND it's creating a new axis + * so for example if your plot already has xy and x2y2, an annotation + * on x2y or xy2 will not create a new subplot. + */ + if(newAxis && hasXref && hasYref) { + cartesianList.push(xref + yref); + } + } + } + }; +}; + +},{"../../lib":696,"../../registry":827}],756:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Plots = _dereq_('../plots'); +var Drawing = _dereq_('../../components/drawing'); + +var getModuleCalcData = _dereq_('../get_data').getModuleCalcData; +var axisIds = _dereq_('./axis_ids'); +var constants = _dereq_('./constants'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +var ensureSingle = Lib.ensureSingle; + +function ensureSingleAndAddDatum(parent, nodeType, className) { + return Lib.ensureSingle(parent, nodeType, className, function(s) { + s.datum(className); + }); +} + +exports.name = 'cartesian'; + +exports.attr = ['xaxis', 'yaxis']; + +exports.idRoot = ['x', 'y']; + +exports.idRegex = constants.idRegex; + +exports.attrRegex = constants.attrRegex; + +exports.attributes = _dereq_('./attributes'); + +exports.layoutAttributes = _dereq_('./layout_attributes'); + +exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); + +exports.transitionAxes = _dereq_('./transition_axes').transitionAxes; +exports.transitionAxes2 = _dereq_('./transition_axes').transitionAxes2; + +exports.finalizeSubplots = function(layoutIn, layoutOut) { + var subplots = layoutOut._subplots; + var xList = subplots.xaxis; + var yList = subplots.yaxis; + var spSVG = subplots.cartesian; + var spAll = spSVG.concat(subplots.gl2d || []); + var allX = {}; + var allY = {}; + var i, xi, yi; + + for(i = 0; i < spAll.length; i++) { + var parts = spAll[i].split('y'); + allX[parts[0]] = 1; + allY['y' + parts[1]] = 1; + } + + // check for x axes with no subplot, and make one from the anchor of that x axis + for(i = 0; i < xList.length; i++) { + xi = xList[i]; + if(!allX[xi]) { + yi = (layoutIn[axisIds.id2name(xi)] || {}).anchor; + if(!constants.idRegex.y.test(yi)) yi = 'y'; + spSVG.push(xi + yi); + spAll.push(xi + yi); + + if(!allY[yi]) { + allY[yi] = 1; + Lib.pushUnique(yList, yi); + } + } + } + + // same for y axes with no subplot + for(i = 0; i < yList.length; i++) { + yi = yList[i]; + if(!allY[yi]) { + xi = (layoutIn[axisIds.id2name(yi)] || {}).anchor; + if(!constants.idRegex.x.test(xi)) xi = 'x'; + spSVG.push(xi + yi); + spAll.push(xi + yi); + + if(!allX[xi]) { + allX[xi] = 1; + Lib.pushUnique(xList, xi); + } + } + } + + // finally, if we've gotten here we're supposed to show cartesian... + // so if there are NO subplots at all, make one from the first + // x & y axes in the input layout + if(!spAll.length) { + xi = ''; + yi = ''; + for(var ki in layoutIn) { + if(constants.attrRegex.test(ki)) { + var axLetter = ki.charAt(0); + if(axLetter === 'x') { + if(!xi || (+ki.substr(5) < +xi.substr(5))) { + xi = ki; + } + } + else if(!yi || (+ki.substr(5) < +yi.substr(5))) { + yi = ki; + } + } + } + xi = xi ? axisIds.name2id(xi) : 'x'; + yi = yi ? axisIds.name2id(yi) : 'y'; + xList.push(xi); + yList.push(yi); + spSVG.push(xi + yi); + } +}; + +/** + * Cartesian.plot + * + * @param {DOM div | object} gd + * @param {array | null} (optional) traces + * array of traces indices to plot + * if undefined, plots all cartesian traces, + * if null, plots no traces + * @param {object} (optional) transitionOpts + * transition option object + * @param {function} (optional) makeOnCompleteCallback + * transition make callback function from Plots.transition + */ +exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout; + var subplots = fullLayout._subplots.cartesian; + var calcdata = gd.calcdata; + var i; + + if(traces === null) { + // this means no updates required, must return here + // so that plotOne doesn't remove the trace layers + return; + } else if(!Array.isArray(traces)) { + // If traces is not provided, then it's a complete replot and missing + // traces are removed + traces = []; + for(i = 0; i < calcdata.length; i++) traces.push(i); + } + + for(i = 0; i < subplots.length; i++) { + var subplot = subplots[i]; + var subplotInfo = fullLayout._plots[subplot]; + + // Get all calcdata for this subplot: + var cdSubplot = []; + var pcd; + + for(var j = 0; j < calcdata.length; j++) { + var cd = calcdata[j]; + var trace = cd[0].trace; + + // Skip trace if whitelist provided and it's not whitelisted: + // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue; + if(trace.xaxis + trace.yaxis === subplot) { + // XXX: Should trace carpet dependencies. Only replot all carpet plots if the carpet + // axis has actually changed: + // + // If this trace is specifically requested, add it to the list: + if(traces.indexOf(trace.index) !== -1 || trace.carpet) { + // Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate + // traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill + // is outdated. So this retroactively adds the previous trace if the + // traces are interdependent. + if( + pcd && + pcd[0].trace.xaxis + pcd[0].trace.yaxis === subplot && + ['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1 && + cdSubplot.indexOf(pcd) === -1 + ) { + cdSubplot.push(pcd); + } + + cdSubplot.push(cd); + } + + // Track the previous trace on this subplot for the retroactive-add step + // above: + pcd = cd; + } + } + + plotOne(gd, subplotInfo, cdSubplot, transitionOpts, makeOnCompleteCallback); + } +}; + +function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback) { + var traceLayerClasses = constants.traceLayerClasses; + var fullLayout = gd._fullLayout; + var modules = fullLayout._modules; + var _module, cdModuleAndOthers, cdModule; + + var layerData = []; + var zoomScaleQueryParts = []; + + for(var i = 0; i < modules.length; i++) { + _module = modules[i]; + var name = _module.name; + var categories = Registry.modules[name].categories; + + if(categories.svg) { + var className = (_module.layerName || name + 'layer'); + var plotMethod = _module.plot; + + // plot all visible traces of this type on this subplot at once + cdModuleAndOthers = getModuleCalcData(cdSubplot, plotMethod); + cdModule = cdModuleAndOthers[0]; + // don't need to search the found traces again - in fact we need to NOT + // so that if two modules share the same plotter we don't double-plot + cdSubplot = cdModuleAndOthers[1]; + + if(cdModule.length) { + layerData.push({ + i: traceLayerClasses.indexOf(className), + className: className, + plotMethod: plotMethod, + cdModule: cdModule + }); + } + + if(categories.zoomScale) { + zoomScaleQueryParts.push('.' + className); + } + } + } + + layerData.sort(function(a, b) { return a.i - b.i; }); + + var layers = plotinfo.plot.selectAll('g.mlayer') + .data(layerData, function(d) { return d.className; }); + + layers.enter().append('g') + .attr('class', function(d) { return d.className; }) + .classed('mlayer', true); + + layers.exit().remove(); + + layers.order(); + + layers.each(function(d) { + var sel = d3.select(this); + var className = d.className; + + d.plotMethod( + gd, plotinfo, d.cdModule, sel, + transitionOpts, makeOnCompleteCallback + ); + + // layers that allow `cliponaxis: false` + if(className !== 'scatterlayer' && className !== 'barlayer') { + Drawing.setClipUrl(sel, plotinfo.layerClipId); + } + }); + + // call Scattergl.plot separately + if(fullLayout._has('scattergl')) { + _module = Registry.getModule('scattergl'); + cdModule = getModuleCalcData(cdSubplot, _module)[0]; + _module.plot(gd, plotinfo, cdModule); + } + + // stash "hot" selections for faster interaction on drag and scroll + if(!gd._context.staticPlot) { + if(plotinfo._hasClipOnAxisFalse) { + plotinfo.clipOnAxisFalseTraces = plotinfo.plot + .selectAll('.scatterlayer, .barlayer') + .selectAll('.trace'); + } + + if(zoomScaleQueryParts.length) { + var traces = plotinfo.plot + .selectAll(zoomScaleQueryParts.join(',')) + .selectAll('.trace'); + + plotinfo.zoomScalePts = traces.selectAll('path.point'); + plotinfo.zoomScaleTxt = traces.selectAll('.textpoint'); + } + } +} + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldPlots = oldFullLayout._plots || {}; + var newPlots = newFullLayout._plots || {}; + var oldSubplotList = oldFullLayout._subplots || {}; + var plotinfo; + var i, k; + + // when going from a large splom graph to something else, + // we need to clear so that the new cartesian subplot + // can have the correct layer ordering + if(oldFullLayout._hasOnlyLargeSploms && !newFullLayout._hasOnlyLargeSploms) { + for(k in oldPlots) { + plotinfo = oldPlots[k]; + if(plotinfo.plotgroup) plotinfo.plotgroup.remove(); + } + } + + var hadGl = (oldFullLayout._has && oldFullLayout._has('gl')); + var hasGl = (newFullLayout._has && newFullLayout._has('gl')); + + if(hadGl && !hasGl) { + for(k in oldPlots) { + plotinfo = oldPlots[k]; + if(plotinfo._scene) plotinfo._scene.destroy(); + } + } + + // delete any titles we don't need anymore + // check if axis list has changed, and if so clear old titles + if(oldSubplotList.xaxis && oldSubplotList.yaxis) { + var oldAxIDs = axisIds.listIds({_fullLayout: oldFullLayout}); + for(i = 0; i < oldAxIDs.length; i++) { + var oldAxId = oldAxIDs[i]; + if(!newFullLayout[axisIds.id2name(oldAxId)]) { + oldFullLayout._infolayer.selectAll('.g-' + oldAxId + 'title').remove(); + } + } + } + + // if we've gotten rid of all cartesian traces, remove all the subplot svg items + var hadCartesian = (oldFullLayout._has && oldFullLayout._has('cartesian')); + var hasCartesian = (newFullLayout._has && newFullLayout._has('cartesian')); + + if(hadCartesian && !hasCartesian) { + purgeSubplotLayers(oldFullLayout._cartesianlayer.selectAll('.subplot'), oldFullLayout); + oldFullLayout._defs.selectAll('.axesclip').remove(); + delete oldFullLayout._axisConstraintGroups; + } + // otherwise look for subplots we need to remove + else if(oldSubplotList.cartesian) { + for(i = 0; i < oldSubplotList.cartesian.length; i++) { + var oldSubplotId = oldSubplotList.cartesian[i]; + if(!newPlots[oldSubplotId]) { + var selector = '.' + oldSubplotId + ',.' + oldSubplotId + '-x,.' + oldSubplotId + '-y'; + oldFullLayout._cartesianlayer.selectAll(selector).remove(); + removeSubplotExtras(oldSubplotId, oldFullLayout); + } + } + } +}; + +exports.drawFramework = function(gd) { + var fullLayout = gd._fullLayout; + var subplotData = makeSubplotData(gd); + + var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot') + .data(subplotData, String); + + subplotLayers.enter().append('g') + .attr('class', function(d) { return 'subplot ' + d[0]; }); + + subplotLayers.order(); + + subplotLayers.exit() + .call(purgeSubplotLayers, fullLayout); + + subplotLayers.each(function(d) { + var id = d[0]; + var plotinfo = fullLayout._plots[id]; + + plotinfo.plotgroup = d3.select(this); + makeSubplotLayer(gd, plotinfo); + + // make separate drag layers for each subplot, + // but append them to paper rather than the plot groups, + // so they end up on top of the rest + plotinfo.draglayer = ensureSingle(fullLayout._draggers, 'g', id); + }); +}; + +exports.rangePlot = function(gd, plotinfo, cdSubplot) { + makeSubplotLayer(gd, plotinfo); + plotOne(gd, plotinfo, cdSubplot); + Plots.style(gd); +}; + +function makeSubplotData(gd) { + var fullLayout = gd._fullLayout; + var ids = fullLayout._subplots.cartesian; + var len = ids.length; + var i, j, id, plotinfo, xa, ya; + + // split 'regular' and 'overlaying' subplots + var regulars = []; + var overlays = []; + + for(i = 0; i < len; i++) { + id = ids[i]; + plotinfo = fullLayout._plots[id]; + xa = plotinfo.xaxis; + ya = plotinfo.yaxis; + + var xa2 = xa._mainAxis; + var ya2 = ya._mainAxis; + var mainplot = xa2._id + ya2._id; + var mainplotinfo = fullLayout._plots[mainplot]; + plotinfo.overlays = []; + + if(mainplot !== id && mainplotinfo) { + plotinfo.mainplot = mainplot; + plotinfo.mainplotinfo = mainplotinfo; + overlays.push(id); + } else { + plotinfo.mainplot = undefined; + plotinfo.mainPlotinfo = undefined; + regulars.push(id); + } + } + + // fill in list of overlaying subplots in 'main plot' + for(i = 0; i < overlays.length; i++) { + id = overlays[i]; + plotinfo = fullLayout._plots[id]; + plotinfo.mainplotinfo.overlays.push(plotinfo); + } + + // put 'regular' subplot data before 'overlaying' + var subplotIds = regulars.concat(overlays); + var subplotData = new Array(len); + + for(i = 0; i < len; i++) { + id = subplotIds[i]; + plotinfo = fullLayout._plots[id]; + xa = plotinfo.xaxis; + ya = plotinfo.yaxis; + + // use info about axis layer and overlaying pattern + // to clean what need to be cleaned up in exit selection + var d = [id, xa.layer, ya.layer, xa.overlaying || '', ya.overlaying || '']; + for(j = 0; j < plotinfo.overlays.length; j++) { + d.push(plotinfo.overlays[j].id); + } + subplotData[i] = d; + } + + return subplotData; +} + +function makeSubplotLayer(gd, plotinfo) { + var plotgroup = plotinfo.plotgroup; + var id = plotinfo.id; + var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer]; + var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer]; + var hasOnlyLargeSploms = gd._fullLayout._hasOnlyLargeSploms; + + if(!plotinfo.mainplot) { + if(hasOnlyLargeSploms) { + // TODO could do even better + // - we don't need plot (but we would have to mock it in lsInner + // and other places + // - we don't (x|y)lines and (x|y)axislayer for most subplots + // usually just the bottom x and left y axes. + plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above'); + plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above'); + plotinfo.xaxislayer = ensureSingle(plotgroup, 'g', 'xaxislayer-above'); + plotinfo.yaxislayer = ensureSingle(plotgroup, 'g', 'yaxislayer-above'); + } + else { + var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot'); + plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer'); + plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer'); + + plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer'); + plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer'); + + ensureSingle(plotgroup, 'path', 'xlines-below'); + ensureSingle(plotgroup, 'path', 'ylines-below'); + plotinfo.overlinesBelow = ensureSingle(plotgroup, 'g', 'overlines-below'); + + ensureSingle(plotgroup, 'g', 'xaxislayer-below'); + ensureSingle(plotgroup, 'g', 'yaxislayer-below'); + plotinfo.overaxesBelow = ensureSingle(plotgroup, 'g', 'overaxes-below'); + + plotinfo.plot = ensureSingle(plotgroup, 'g', 'plot'); + plotinfo.overplot = ensureSingle(plotgroup, 'g', 'overplot'); + + plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above'); + plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above'); + plotinfo.overlinesAbove = ensureSingle(plotgroup, 'g', 'overlines-above'); + + ensureSingle(plotgroup, 'g', 'xaxislayer-above'); + ensureSingle(plotgroup, 'g', 'yaxislayer-above'); + plotinfo.overaxesAbove = ensureSingle(plotgroup, 'g', 'overaxes-above'); + + // set refs to correct layers as determined by 'axis.layer' + plotinfo.xlines = plotgroup.select('.xlines-' + xLayer); + plotinfo.ylines = plotgroup.select('.ylines-' + yLayer); + plotinfo.xaxislayer = plotgroup.select('.xaxislayer-' + xLayer); + plotinfo.yaxislayer = plotgroup.select('.yaxislayer-' + yLayer); + } + } + else { + var mainplotinfo = plotinfo.mainplotinfo; + var mainplotgroup = mainplotinfo.plotgroup; + var xId = id + '-x'; + var yId = id + '-y'; + + // now make the components of overlaid subplots + // overlays don't have backgrounds, and append all + // their other components to the corresponding + // extra groups of their main plots. + + plotinfo.gridlayer = mainplotinfo.gridlayer; + plotinfo.zerolinelayer = mainplotinfo.zerolinelayer; + + ensureSingle(mainplotinfo.overlinesBelow, 'path', xId); + ensureSingle(mainplotinfo.overlinesBelow, 'path', yId); + ensureSingle(mainplotinfo.overaxesBelow, 'g', xId); + ensureSingle(mainplotinfo.overaxesBelow, 'g', yId); + + plotinfo.plot = ensureSingle(mainplotinfo.overplot, 'g', id); + + ensureSingle(mainplotinfo.overlinesAbove, 'path', xId); + ensureSingle(mainplotinfo.overlinesAbove, 'path', yId); + ensureSingle(mainplotinfo.overaxesAbove, 'g', xId); + ensureSingle(mainplotinfo.overaxesAbove, 'g', yId); + + // set refs to correct layers as determined by 'abovetraces' + plotinfo.xlines = mainplotgroup.select('.overlines-' + xLayer).select('.' + xId); + plotinfo.ylines = mainplotgroup.select('.overlines-' + yLayer).select('.' + yId); + plotinfo.xaxislayer = mainplotgroup.select('.overaxes-' + xLayer).select('.' + xId); + plotinfo.yaxislayer = mainplotgroup.select('.overaxes-' + yLayer).select('.' + yId); + } + + // common attributes for all subplots, overlays or not + + if(!hasOnlyLargeSploms) { + ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id); + ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id); + plotinfo.gridlayer.selectAll('g') + .map(function(d) { return d[0]; }) + .sort(axisIds.idSort); + } + + plotinfo.xlines + .style('fill', 'none') + .classed('crisp', true); + + plotinfo.ylines + .style('fill', 'none') + .classed('crisp', true); +} + +function purgeSubplotLayers(layers, fullLayout) { + if(!layers) return; + + var overlayIdsToRemove = {}; + + layers.each(function(d) { + var id = d[0]; + var plotgroup = d3.select(this); + + plotgroup.remove(); + removeSubplotExtras(id, fullLayout); + overlayIdsToRemove[id] = true; + + // do not remove individual axis s here + // as other subplots may need them + }); + + // must remove overlaid subplot trace layers 'manually' + + for(var k in fullLayout._plots) { + var subplotInfo = fullLayout._plots[k]; + var overlays = subplotInfo.overlays || []; + + for(var j = 0; j < overlays.length; j++) { + var overlayInfo = overlays[j]; + + if(overlayIdsToRemove[overlayInfo.id]) { + overlayInfo.plot.selectAll('.trace').remove(); + } + } + } +} + +function removeSubplotExtras(subplotId, fullLayout) { + fullLayout._draggers.selectAll('g.' + subplotId).remove(); + fullLayout._defs.select('#clip' + fullLayout._uid + subplotId + 'plot').remove(); +} + +exports.toSVG = function(gd) { + var imageRoot = gd._fullLayout._glimages; + var root = d3.select(gd).selectAll('.svg-container'); + var canvases = root.filter(function(d, i) {return i === root.size() - 1;}) + .selectAll('.gl-canvas-context, .gl-canvas-focus'); + + function canvasToImage() { + var canvas = this; + var imageData = canvas.toDataURL('image/png'); + var image = imageRoot.append('svg:image'); + + image.attr({ + xmlns: xmlnsNamespaces.svg, + 'xlink:href': imageData, + preserveAspectRatio: 'none', + x: 0, + y: 0, + width: canvas.width, + height: canvas.height + }); + } + + canvases.each(canvasToImage); +}; + +exports.updateFx = _dereq_('./graph_interact').updateFx; + +},{"../../components/drawing":595,"../../constants/xmlns_namespaces":674,"../../lib":696,"../../registry":827,"../get_data":781,"../plots":808,"./attributes":742,"./axis_ids":747,"./constants":750,"./graph_interact":754,"./layout_attributes":757,"./layout_defaults":758,"./transition_axes":767,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],757:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../font_attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +var constants = _dereq_('./constants'); + + +module.exports = { + visible: { + valType: 'boolean', + + editType: 'plot', + + }, + color: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'ticks', + + }, + title: { + valType: 'string', + + editType: 'ticks', + + }, + titlefont: fontAttrs({ + editType: 'ticks', + + }), + type: { + valType: 'enumerated', + // '-' means we haven't yet run autotype or couldn't find any data + // it gets turned into linear in gd._fullLayout but not copied back + // to gd.data like the others are. + values: ['-', 'linear', 'log', 'date', 'category'], + dflt: '-', + + editType: 'calc', + // we forget when an axis has been autotyped, just writing the auto + // value back to the input - so it doesn't make sense to template this. + // Note: we do NOT prohibit this in `coerce`, so if someone enters a + // type in the template explicitly it will be honored as the default. + _noTemplating: true, + + }, + autorange: { + valType: 'enumerated', + values: [true, false, 'reversed'], + dflt: true, + + editType: 'axrange', + impliedEdits: {'range[0]': undefined, 'range[1]': undefined}, + + }, + rangemode: { + valType: 'enumerated', + values: ['normal', 'tozero', 'nonnegative'], + dflt: 'normal', + + editType: 'plot', + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'any', editType: 'axrange', impliedEdits: {'^autorange': false}, anim: true}, + {valType: 'any', editType: 'axrange', impliedEdits: {'^autorange': false}, anim: true} + ], + editType: 'axrange', + impliedEdits: {'autorange': false}, + anim: true, + + }, + fixedrange: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + // scaleanchor: not used directly, just put here for reference + // values are any opposite-letter axis id + scaleanchor: { + valType: 'enumerated', + values: [ + constants.idRegex.x.toString(), + constants.idRegex.y.toString() + ], + + editType: 'plot', + + }, + scaleratio: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'plot', + + }, + constrain: { + valType: 'enumerated', + values: ['range', 'domain'], + dflt: 'range', + + editType: 'plot', + + }, + // constraintoward: not used directly, just put here for reference + constraintoward: { + valType: 'enumerated', + values: ['left', 'center', 'right', 'top', 'middle', 'bottom'], + + editType: 'plot', + + }, + // ticks + tickmode: { + valType: 'enumerated', + values: ['auto', 'linear', 'array'], + + editType: 'ticks', + impliedEdits: {tick0: undefined, dtick: undefined}, + + }, + nticks: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'ticks', + + }, + tick0: { + valType: 'any', + + editType: 'ticks', + impliedEdits: {tickmode: 'linear'}, + + }, + dtick: { + valType: 'any', + + editType: 'ticks', + impliedEdits: {tickmode: 'linear'}, + + }, + tickvals: { + valType: 'data_array', + editType: 'ticks', + + }, + ticktext: { + valType: 'data_array', + editType: 'ticks', + + }, + ticks: { + valType: 'enumerated', + values: ['outside', 'inside', ''], + + editType: 'ticks', + + }, + mirror: { + valType: 'enumerated', + values: [true, 'ticks', false, 'all', 'allticks'], + dflt: false, + + editType: 'ticks+layoutstyle', + + }, + ticklen: { + valType: 'number', + min: 0, + dflt: 5, + + editType: 'ticks', + + }, + tickwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'ticks', + + }, + tickcolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'ticks', + + }, + showticklabels: { + valType: 'boolean', + dflt: true, + + editType: 'ticks', + + }, + automargin: { + valType: 'boolean', + dflt: false, + + editType: 'ticks', + + }, + showspikes: { + valType: 'boolean', + dflt: false, + + editType: 'modebar', + + }, + spikecolor: { + valType: 'color', + dflt: null, + + editType: 'none', + + }, + spikethickness: { + valType: 'number', + dflt: 3, + + editType: 'none', + + }, + spikedash: extendFlat({}, dash, {dflt: 'dash', editType: 'none'}), + spikemode: { + valType: 'flaglist', + flags: ['toaxis', 'across', 'marker'], + + dflt: 'toaxis', + editType: 'none', + + }, + spikesnap: { + valType: 'enumerated', + values: ['data', 'cursor'], + dflt: 'data', + + editType: 'none', + + }, + tickfont: fontAttrs({ + editType: 'ticks', + + }), + tickangle: { + valType: 'angle', + dflt: 'auto', + + editType: 'ticks', + + }, + tickprefix: { + valType: 'string', + dflt: '', + + editType: 'ticks', + + }, + showtickprefix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'ticks', + + }, + ticksuffix: { + valType: 'string', + dflt: '', + + editType: 'ticks', + + }, + showticksuffix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'ticks', + + }, + showexponent: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'ticks', + + }, + exponentformat: { + valType: 'enumerated', + values: ['none', 'e', 'E', 'power', 'SI', 'B'], + dflt: 'B', + + editType: 'ticks', + + }, + separatethousands: { + valType: 'boolean', + dflt: false, + + editType: 'ticks', + + }, + tickformat: { + valType: 'string', + dflt: '', + + editType: 'ticks', + + }, + tickformatstops: templatedArray('tickformatstop', { + enabled: { + valType: 'boolean', + + dflt: true, + editType: 'ticks', + + }, + dtickrange: { + valType: 'info_array', + + items: [ + {valType: 'any', editType: 'ticks'}, + {valType: 'any', editType: 'ticks'} + ], + editType: 'ticks', + + }, + value: { + valType: 'string', + dflt: '', + + editType: 'ticks', + + }, + editType: 'ticks' + }), + hoverformat: { + valType: 'string', + dflt: '', + + editType: 'none', + + }, + // lines and grids + showline: { + valType: 'boolean', + dflt: false, + + editType: 'ticks+layoutstyle', + + }, + linecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'layoutstyle', + + }, + linewidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'ticks+layoutstyle', + + }, + showgrid: { + valType: 'boolean', + + editType: 'ticks', + + }, + gridcolor: { + valType: 'color', + dflt: colorAttrs.lightLine, + + editType: 'ticks', + + }, + gridwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'ticks', + + }, + zeroline: { + valType: 'boolean', + + editType: 'ticks', + + }, + zerolinecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'ticks', + + }, + zerolinewidth: { + valType: 'number', + dflt: 1, + + editType: 'ticks', + + }, + // positioning attributes + // anchor: not used directly, just put here for reference + // values are any opposite-letter axis id + anchor: { + valType: 'enumerated', + values: [ + 'free', + constants.idRegex.x.toString(), + constants.idRegex.y.toString() + ], + + editType: 'plot', + + }, + // side: not used directly, as values depend on direction + // values are top, bottom for x axes, and left, right for y + side: { + valType: 'enumerated', + values: ['top', 'bottom', 'left', 'right'], + + editType: 'plot', + + }, + // overlaying: not used directly, just put here for reference + // values are false and any other same-letter axis id that's not + // itself overlaying anything + overlaying: { + valType: 'enumerated', + values: [ + 'free', + constants.idRegex.x.toString(), + constants.idRegex.y.toString() + ], + + editType: 'plot', + + }, + layer: { + valType: 'enumerated', + values: ['above traces', 'below traces'], + dflt: 'above traces', + + editType: 'plot', + + }, + domain: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1, editType: 'plot'}, + {valType: 'number', min: 0, max: 1, editType: 'plot'} + ], + dflt: [0, 1], + editType: 'plot', + + }, + position: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + + editType: 'plot', + + }, + categoryorder: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + /* , 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later + ], + dflt: 'trace', + + editType: 'calc', + + }, + categoryarray: { + valType: 'data_array', + + editType: 'calc', + + }, + editType: 'calc', + + _deprecated: { + autotick: { + valType: 'boolean', + + editType: 'ticks', + + } + } +}; + +},{"../../components/color/attributes":569,"../../components/drawing/attributes":594,"../../lib/extend":685,"../../plot_api/plot_template":734,"../font_attributes":771,"./constants":750}],758:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var Template = _dereq_('../../plot_api/plot_template'); +var basePlotLayoutAttributes = _dereq_('../layout_attributes'); + +var layoutAttributes = _dereq_('./layout_attributes'); +var handleTypeDefaults = _dereq_('./type_defaults'); +var handleAxisDefaults = _dereq_('./axis_defaults'); +var handleConstraintDefaults = _dereq_('./constraint_defaults'); +var handlePositionDefaults = _dereq_('./position_defaults'); + +var axisIds = _dereq_('./axis_ids'); +var id2name = axisIds.id2name; +var name2id = axisIds.name2id; + +var Registry = _dereq_('../../registry'); +var traceIs = Registry.traceIs; +var getComponentMethod = Registry.getComponentMethod; + +function appendList(cont, k, item) { + if(Array.isArray(cont[k])) cont[k].push(item); + else cont[k] = [item]; +} + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + var ax2traces = {}; + var xaCheater = {}; + var xaNonCheater = {}; + var outerTicks = {}; + var noGrids = {}; + var i, j; + + // look for axes in the data + for(i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + if(!traceIs(trace, 'cartesian') && !traceIs(trace, 'gl2d')) continue; + + var xaName; + if(trace.xaxis) { + xaName = id2name(trace.xaxis); + appendList(ax2traces, xaName, trace); + } else if(trace.xaxes) { + for(j = 0; j < trace.xaxes.length; j++) { + appendList(ax2traces, id2name(trace.xaxes[j]), trace); + } + } + + var yaName; + if(trace.yaxis) { + yaName = id2name(trace.yaxis); + appendList(ax2traces, yaName, trace); + } else if(trace.yaxes) { + for(j = 0; j < trace.yaxes.length; j++) { + appendList(ax2traces, id2name(trace.yaxes[j]), trace); + } + } + + // Two things trigger axis visibility: + // 1. is not carpet + // 2. carpet that's not cheater + if(!traceIs(trace, 'carpet') || (trace.type === 'carpet' && !trace._cheater)) { + if(xaName) xaNonCheater[xaName] = 1; + } + + // The above check for definitely-not-cheater is not adequate. This + // second list tracks which axes *could* be a cheater so that the + // full condition triggering hiding is: + // *could* be a cheater and *is not definitely visible* + if(trace.type === 'carpet' && trace._cheater) { + if(xaName) xaCheater[xaName] = 1; + } + + // check for default formatting tweaks + if(traceIs(trace, '2dMap')) { + outerTicks[xaName] = 1; + outerTicks[yaName] = 1; + } + + if(traceIs(trace, 'oriented')) { + var positionAxis = trace.orientation === 'h' ? yaName : xaName; + noGrids[positionAxis] = 1; + } + } + + var subplots = layoutOut._subplots; + var xIds = subplots.xaxis; + var yIds = subplots.yaxis; + var xNames = Lib.simpleMap(xIds, id2name); + var yNames = Lib.simpleMap(yIds, id2name); + var axNames = xNames.concat(yNames); + + // plot_bgcolor only makes sense if there's a (2D) plot! + // TODO: bgcolor for each subplot, to inherit from the main one + var plot_bgcolor = Color.background; + if(xIds.length && yIds.length) { + plot_bgcolor = Lib.coerce(layoutIn, layoutOut, basePlotLayoutAttributes, 'plot_bgcolor'); + } + + var bgColor = Color.combine(plot_bgcolor, layoutOut.paper_bgcolor); + + var axName, axLetter, axLayoutIn, axLayoutOut; + + function coerce(attr, dflt) { + return Lib.coerce(axLayoutIn, axLayoutOut, layoutAttributes, attr, dflt); + } + + function coerce2(attr, dflt) { + return Lib.coerce2(axLayoutIn, axLayoutOut, layoutAttributes, attr, dflt); + } + + function getCounterAxes(axLetter) { + return (axLetter === 'x') ? yIds : xIds; + } + + var counterAxes = {x: getCounterAxes('x'), y: getCounterAxes('y')}; + + function getOverlayableAxes(axLetter, axName) { + var list = (axLetter === 'x') ? xNames : yNames; + var out = []; + + for(var j = 0; j < list.length; j++) { + var axName2 = list[j]; + + if(axName2 !== axName && !(layoutIn[axName2] || {}).overlaying) { + out.push(name2id(axName2)); + } + } + + return out; + } + + // first pass creates the containers, determines types, and handles most of the settings + for(i = 0; i < axNames.length; i++) { + axName = axNames[i]; + axLetter = axName.charAt(0); + + if(!Lib.isPlainObject(layoutIn[axName])) { + layoutIn[axName] = {}; + } + + axLayoutIn = layoutIn[axName]; + axLayoutOut = Template.newContainer(layoutOut, axName, axLetter + 'axis'); + + var traces = ax2traces[axName] || []; + axLayoutOut._traceIndices = traces.map(function(t) { return t._expandedIndex; }); + axLayoutOut._annIndices = []; + axLayoutOut._shapeIndices = []; + + // set up some private properties + axLayoutOut._name = axName; + var id = axLayoutOut._id = name2id(axName); + + var overlayableAxes = getOverlayableAxes(axLetter, axName); + + var defaultOptions = { + letter: axLetter, + font: layoutOut.font, + outerTicks: outerTicks[axName], + showGrid: !noGrids[axName], + data: traces, + bgColor: bgColor, + calendar: layoutOut.calendar, + automargin: true, + cheateronly: axLetter === 'x' && xaCheater[axName] && !xaNonCheater[axName], + splomStash: ((layoutOut._splomAxes || {})[axLetter] || {})[id] + }; + + handleTypeDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions); + handleAxisDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions, layoutOut); + + var spikecolor = coerce2('spikecolor'), + spikethickness = coerce2('spikethickness'), + spikedash = coerce2('spikedash'), + spikemode = coerce2('spikemode'), + spikesnap = coerce2('spikesnap'), + showSpikes = coerce('showspikes', !!spikecolor || !!spikethickness || !!spikedash || !!spikemode || !!spikesnap); + + if(!showSpikes) { + delete axLayoutOut.spikecolor; + delete axLayoutOut.spikethickness; + delete axLayoutOut.spikedash; + delete axLayoutOut.spikemode; + delete axLayoutOut.spikesnap; + } + + var positioningOptions = { + letter: axLetter, + counterAxes: counterAxes[axLetter], + overlayableAxes: overlayableAxes, + grid: layoutOut.grid + }; + + handlePositionDefaults(axLayoutIn, axLayoutOut, coerce, positioningOptions); + + axLayoutOut._input = axLayoutIn; + } + + // quick second pass for range slider and selector defaults + var rangeSliderDefaults = getComponentMethod('rangeslider', 'handleDefaults'); + var rangeSelectorDefaults = getComponentMethod('rangeselector', 'handleDefaults'); + + for(i = 0; i < xNames.length; i++) { + axName = xNames[i]; + axLayoutIn = layoutIn[axName]; + axLayoutOut = layoutOut[axName]; + + rangeSliderDefaults(layoutIn, layoutOut, axName); + + if(axLayoutOut.type === 'date') { + rangeSelectorDefaults( + axLayoutIn, + axLayoutOut, + layoutOut, + yNames, + axLayoutOut.calendar + ); + } + + coerce('fixedrange'); + } + + for(i = 0; i < yNames.length; i++) { + axName = yNames[i]; + axLayoutIn = layoutIn[axName]; + axLayoutOut = layoutOut[axName]; + + var anchoredAxis = layoutOut[id2name(axLayoutOut.anchor)]; + + var fixedRangeDflt = ( + anchoredAxis && + anchoredAxis.rangeslider && + anchoredAxis.rangeslider.visible + ); + + coerce('fixedrange', fixedRangeDflt); + } + + // Finally, handle scale constraints. We need to do this after all axes have + // coerced both `type` (so we link only axes of the same type) and + // `fixedrange` (so we can avoid linking from OR TO a fixed axis). + + // sets of axes linked by `scaleanchor` along with the scaleratios compounded + // together, populated in handleConstraintDefaults + layoutOut._axisConstraintGroups = []; + var allAxisIds = counterAxes.x.concat(counterAxes.y); + + for(i = 0; i < axNames.length; i++) { + axName = axNames[i]; + axLetter = axName.charAt(0); + + axLayoutIn = layoutIn[axName]; + axLayoutOut = layoutOut[axName]; + + handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, allAxisIds, layoutOut); + } +}; + +},{"../../components/color":570,"../../lib":696,"../../plot_api/plot_template":734,"../../registry":827,"../layout_attributes":799,"./axis_defaults":746,"./axis_ids":747,"./constraint_defaults":751,"./layout_attributes":757,"./position_defaults":760,"./type_defaults":768}],759:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorMix = _dereq_('tinycolor2').mix; +var lightFraction = _dereq_('../../components/color/attributes').lightFraction; +var Lib = _dereq_('../../lib'); + +/** + * @param {object} opts : + * - dfltColor {string} : default axis color + * - bgColor {string} : combined subplot bg color + * - blend {number, optional} : blend percentage (to compute dflt grid color) + * - showLine {boolean} : show line by default + * - showGrid {boolean} : show grid by default + * - noZeroLine {boolean} : don't coerce zeroline* attributes + * - attributes {object} : attribute object associated with input containers + */ +module.exports = function handleLineGridDefaults(containerIn, containerOut, coerce, opts) { + opts = opts || {}; + + var dfltColor = opts.dfltColor; + + function coerce2(attr, dflt) { + return Lib.coerce2(containerIn, containerOut, opts.attributes, attr, dflt); + } + + var lineColor = coerce2('linecolor', dfltColor); + var lineWidth = coerce2('linewidth'); + var showLine = coerce('showline', opts.showLine || !!lineColor || !!lineWidth); + + if(!showLine) { + delete containerOut.linecolor; + delete containerOut.linewidth; + } + + var gridColorDflt = colorMix(dfltColor, opts.bgColor, opts.blend || lightFraction).toRgbString(); + var gridColor = coerce2('gridcolor', gridColorDflt); + var gridWidth = coerce2('gridwidth'); + var showGridLines = coerce('showgrid', opts.showGrid || !!gridColor || !!gridWidth); + + if(!showGridLines) { + delete containerOut.gridcolor; + delete containerOut.gridwidth; + } + + if(!opts.noZeroLine) { + var zeroLineColor = coerce2('zerolinecolor', dfltColor); + var zeroLineWidth = coerce2('zerolinewidth'); + var showZeroLine = coerce('zeroline', opts.showGrid || !!zeroLineColor || !!zeroLineWidth); + + if(!showZeroLine) { + delete containerOut.zerolinecolor; + delete containerOut.zerolinewidth; + } + } +}; + +},{"../../components/color/attributes":569,"../../lib":696,"tinycolor2":514}],760:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); + + +module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) { + var counterAxes = options.counterAxes || []; + var overlayableAxes = options.overlayableAxes || []; + var letter = options.letter; + var grid = options.grid; + + var dfltAnchor, dfltDomain, dfltSide, dfltPosition; + + if(grid) { + dfltDomain = grid._domains[letter][grid._axisMap[containerOut._id]]; + dfltAnchor = grid._anchors[containerOut._id]; + if(dfltDomain) { + dfltSide = grid[letter + 'side'].split(' ')[0]; + dfltPosition = grid.domain[letter][dfltSide === 'right' || dfltSide === 'top' ? 1 : 0]; + } + } + + // Even if there's a grid, this axis may not be in it - fall back on non-grid defaults + dfltDomain = dfltDomain || [0, 1]; + dfltAnchor = dfltAnchor || (isNumeric(containerIn.position) ? 'free' : (counterAxes[0] || 'free')); + dfltSide = dfltSide || (letter === 'x' ? 'bottom' : 'left'); + dfltPosition = dfltPosition || 0; + + var anchor = Lib.coerce(containerIn, containerOut, { + anchor: { + valType: 'enumerated', + values: ['free'].concat(counterAxes), + dflt: dfltAnchor + } + }, 'anchor'); + + if(anchor === 'free') coerce('position', dfltPosition); + + Lib.coerce(containerIn, containerOut, { + side: { + valType: 'enumerated', + values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'], + dflt: dfltSide + } + }, 'side'); + + var overlaying = false; + if(overlayableAxes.length) { + overlaying = Lib.coerce(containerIn, containerOut, { + overlaying: { + valType: 'enumerated', + values: [false].concat(overlayableAxes), + dflt: false + } + }, 'overlaying'); + } + + if(!overlaying) { + // TODO: right now I'm copying this domain over to overlaying axes + // in ax.setscale()... but this means we still need (imperfect) logic + // in the axes popover to hide domain for the overlaying axis. + // perhaps I should make a private version _domain that all axes get??? + var domain = coerce('domain', dfltDomain); + if(domain[0] > domain[1] - 0.01) containerOut.domain = dfltDomain; + Lib.noneOrAll(containerIn.domain, containerOut.domain, dfltDomain); + } + + coerce('layer'); + + return containerOut; +}; + +},{"../../lib":696,"fast-isnumeric":214}],761:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var FROM_BL = _dereq_('../../constants/alignment').FROM_BL; + +module.exports = function scaleZoom(ax, factor, centerFraction) { + if(centerFraction === undefined) { + centerFraction = FROM_BL[ax.constraintoward || 'center']; + } + + var rangeLinear = [ax.r2l(ax.range[0]), ax.r2l(ax.range[1])]; + var center = rangeLinear[0] + (rangeLinear[1] - rangeLinear[0]) * centerFraction; + + ax.range = ax._input.range = [ + ax.l2r(center + (rangeLinear[0] - center) * factor), + ax.l2r(center + (rangeLinear[1] - center) * factor) + ]; +}; + +},{"../../constants/alignment":668}],762:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var polybool = _dereq_('polybooljs'); + +var Registry = _dereq_('../../registry'); +var Color = _dereq_('../../components/color'); +var Fx = _dereq_('../../components/fx'); + +var polygon = _dereq_('../../lib/polygon'); +var throttle = _dereq_('../../lib/throttle'); +var makeEventData = _dereq_('../../components/fx/helpers').makeEventData; +var getFromId = _dereq_('./axis_ids').getFromId; +var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); +var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; + +var constants = _dereq_('./constants'); +var MINSELECT = constants.MINSELECT; + +var filteredPolygon = polygon.filter; +var polygonTester = polygon.tester; + +function getAxId(ax) { return ax._id; } + +function prepSelect(e, startX, startY, dragOptions, mode) { + var gd = dragOptions.gd; + var fullLayout = gd._fullLayout; + var zoomLayer = fullLayout._zoomlayer; + var dragBBox = dragOptions.element.getBoundingClientRect(); + var plotinfo = dragOptions.plotinfo; + var xs = plotinfo.xaxis._offset; + var ys = plotinfo.yaxis._offset; + var x0 = startX - dragBBox.left; + var y0 = startY - dragBBox.top; + var x1 = x0; + var y1 = y0; + var path0 = 'M' + x0 + ',' + y0; + var pw = dragOptions.xaxes[0]._length; + var ph = dragOptions.yaxes[0]._length; + var allAxes = dragOptions.xaxes.concat(dragOptions.yaxes); + var subtract = e.altKey; + + var filterPoly, selectionTester, mergedPolygons, currentPolygon; + var i, searchInfo, eventData; + + coerceSelectionsCache(e, gd, dragOptions); + + if(mode === 'lasso') { + filterPoly = filteredPolygon([[x0, y0]], constants.BENDPX); + } + + var outlines = zoomLayer.selectAll('path.select-outline-' + plotinfo.id).data([1, 2]); + + outlines.enter() + .append('path') + .attr('class', function(d) { return 'select-outline select-outline-' + d + ' select-outline-' + plotinfo.id; }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', path0 + 'Z'); + + var corners = zoomLayer.append('path') + .attr('class', 'zoombox-corners') + .style({ + fill: Color.background, + stroke: Color.defaultLine, + 'stroke-width': 1 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', 'M0,0Z'); + + + var throttleID = fullLayout._uid + constants.SELECTID; + var selection = []; + + // find the traces to search for selection points + var searchTraces = determineSearchTraces(gd, dragOptions.xaxes, + dragOptions.yaxes, dragOptions.subplot); + + function axValue(ax) { + var index = (ax._id.charAt(0) === 'y') ? 1 : 0; + return function(v) { return ax.p2d(v[index]); }; + } + + function ascending(a, b) { return a - b; } + + // allow subplots to override fillRangeItems routine + var fillRangeItems; + + if(plotinfo.fillRangeItems) { + fillRangeItems = plotinfo.fillRangeItems; + } else { + if(mode === 'select') { + fillRangeItems = function(eventData, poly) { + var ranges = eventData.range = {}; + + for(i = 0; i < allAxes.length; i++) { + var ax = allAxes[i]; + var axLetter = ax._id.charAt(0); + + ranges[ax._id] = [ + ax.p2d(poly[axLetter + 'min']), + ax.p2d(poly[axLetter + 'max']) + ].sort(ascending); + } + }; + } else { + fillRangeItems = function(eventData, poly, filterPoly) { + var dataPts = eventData.lassoPoints = {}; + + for(i = 0; i < allAxes.length; i++) { + var ax = allAxes[i]; + dataPts[ax._id] = filterPoly.filtered.map(axValue(ax)); + } + }; + } + } + + dragOptions.moveFn = function(dx0, dy0) { + x1 = Math.max(0, Math.min(pw, dx0 + x0)); + y1 = Math.max(0, Math.min(ph, dy0 + y0)); + + var dx = Math.abs(x1 - x0), + dy = Math.abs(y1 - y0); + + if(mode === 'select') { + var direction = fullLayout.selectdirection; + + if(fullLayout.selectdirection === 'any') { + if(dy < Math.min(dx * 0.6, MINSELECT)) direction = 'h'; + else if(dx < Math.min(dy * 0.6, MINSELECT)) direction = 'v'; + else direction = 'd'; + } + else { + direction = fullLayout.selectdirection; + } + + if(direction === 'h') { + // horizontal motion: make a vertical box + currentPolygon = [[x0, 0], [x0, ph], [x1, ph], [x1, 0]]; + currentPolygon.xmin = Math.min(x0, x1); + currentPolygon.xmax = Math.max(x0, x1); + currentPolygon.ymin = Math.min(0, ph); + currentPolygon.ymax = Math.max(0, ph); + // extras to guide users in keeping a straight selection + corners.attr('d', 'M' + currentPolygon.xmin + ',' + (y0 - MINSELECT) + + 'h-4v' + (2 * MINSELECT) + 'h4Z' + + 'M' + (currentPolygon.xmax - 1) + ',' + (y0 - MINSELECT) + + 'h4v' + (2 * MINSELECT) + 'h-4Z'); + + } + else if(direction === 'v') { + // vertical motion: make a horizontal box + currentPolygon = [[0, y0], [0, y1], [pw, y1], [pw, y0]]; + currentPolygon.xmin = Math.min(0, pw); + currentPolygon.xmax = Math.max(0, pw); + currentPolygon.ymin = Math.min(y0, y1); + currentPolygon.ymax = Math.max(y0, y1); + corners.attr('d', 'M' + (x0 - MINSELECT) + ',' + currentPolygon.ymin + + 'v-4h' + (2 * MINSELECT) + 'v4Z' + + 'M' + (x0 - MINSELECT) + ',' + (currentPolygon.ymax - 1) + + 'v4h' + (2 * MINSELECT) + 'v-4Z'); + } + else if(direction === 'd') { + // diagonal motion + currentPolygon = [[x0, y0], [x0, y1], [x1, y1], [x1, y0]]; + currentPolygon.xmin = Math.min(x0, x1); + currentPolygon.xmax = Math.max(x0, x1); + currentPolygon.ymin = Math.min(y0, y1); + currentPolygon.ymax = Math.max(y0, y1); + corners.attr('d', 'M0,0Z'); + } + } + else if(mode === 'lasso') { + filterPoly.addPt([x1, y1]); + currentPolygon = filterPoly.filtered; + } + + // create outline & tester + if(dragOptions.selectionDefs && dragOptions.selectionDefs.length) { + mergedPolygons = mergePolygons(dragOptions.mergedPolygons, currentPolygon, subtract); + currentPolygon.subtract = subtract; + selectionTester = multiTester(dragOptions.selectionDefs.concat([currentPolygon])); + } + else { + mergedPolygons = [currentPolygon]; + selectionTester = polygonTester(currentPolygon); + } + + // draw selection + drawSelection(mergedPolygons, outlines); + + + throttle.throttle( + throttleID, + constants.SELECTDELAY, + function() { + selection = []; + + var thisSelection, traceSelections = [], traceSelection; + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + + traceSelection = searchInfo._module.selectPoints(searchInfo, selectionTester); + traceSelections.push(traceSelection); + + thisSelection = fillSelectionItem(traceSelection, searchInfo); + + if(selection.length) { + for(var j = 0; j < thisSelection.length; j++) { + selection.push(thisSelection[j]); + } + } + else selection = thisSelection; + } + + eventData = {points: selection}; + updateSelectedState(gd, searchTraces, eventData); + fillRangeItems(eventData, currentPolygon, filterPoly); + dragOptions.gd.emit('plotly_selecting', eventData); + } + ); + }; + + dragOptions.clickFn = function(numClicks, evt) { + var clickmode = fullLayout.clickmode; + + corners.remove(); + + throttle.done(throttleID).then(function() { + throttle.clear(throttleID); + if(numClicks === 2) { + // clear selection on doubleclick + outlines.remove(); + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + searchInfo._module.selectPoints(searchInfo, false); + } + + updateSelectedState(gd, searchTraces); + + clearSelectionsCache(dragOptions); + + gd.emit('plotly_deselect', null); + } else { + if(clickmode.indexOf('select') > -1) { + selectOnClick(evt, gd, dragOptions.xaxes, dragOptions.yaxes, + dragOptions.subplot, dragOptions, outlines); + } + + if(clickmode === 'event') { + // TODO: remove in v2 - this was probably never intended to work as it does, + // but in case anyone depends on it we don't want to break it now. + // Note that click-to-select introduced pre v2 also emitts proper + // event data when clickmode is having 'select' in its flag list. + gd.emit('plotly_selected', undefined); + } + } + + Fx.click(gd, evt); + }); + }; + + dragOptions.doneFn = function() { + corners.remove(); + + throttle.done(throttleID).then(function() { + throttle.clear(throttleID); + dragOptions.gd.emit('plotly_selected', eventData); + + if(currentPolygon && dragOptions.selectionDefs) { + // save last polygons + currentPolygon.subtract = subtract; + dragOptions.selectionDefs.push(currentPolygon); + + // we have to keep reference to arrays container + dragOptions.mergedPolygons.length = 0; + [].push.apply(dragOptions.mergedPolygons, mergedPolygons); + } + }); + }; +} + +function selectOnClick(evt, gd, xAxes, yAxes, subplot, dragOptions, polygonOutlines) { + var hoverData = gd._hoverdata; + var clickmode = gd._fullLayout.clickmode; + var sendEvents = clickmode.indexOf('event') > -1; + var selection = []; + var searchTraces, searchInfo, currentSelectionDef, selectionTester, traceSelection; + var thisTracesSelection, pointOrBinSelected, subtract, eventData, i; + + if(isHoverDataSet(hoverData)) { + coerceSelectionsCache(evt, gd, dragOptions); + searchTraces = determineSearchTraces(gd, xAxes, yAxes, subplot); + var clickedPtInfo = extractClickedPtInfo(hoverData, searchTraces); + var isBinnedTrace = clickedPtInfo.pointNumbers.length > 0; + + + // Note: potentially costly operation isPointOrBinSelected is + // called as late as possible through the use of an assignment + // in an if condition. + if(isBinnedTrace ? + isOnlyThisBinSelected(searchTraces, clickedPtInfo) : + isOnlyOnePointSelected(searchTraces) && + (pointOrBinSelected = isPointOrBinSelected(clickedPtInfo))) + { + if(polygonOutlines) polygonOutlines.remove(); + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + searchInfo._module.selectPoints(searchInfo, false); + } + + updateSelectedState(gd, searchTraces); + + clearSelectionsCache(dragOptions); + + if(sendEvents) { + gd.emit('plotly_deselect', null); + } + } else { + subtract = evt.shiftKey && + (pointOrBinSelected !== undefined ? + pointOrBinSelected : + isPointOrBinSelected(clickedPtInfo)); + currentSelectionDef = newPointSelectionDef(clickedPtInfo.pointNumber, clickedPtInfo.searchInfo, subtract); + + var allSelectionDefs = dragOptions.selectionDefs.concat([currentSelectionDef]); + selectionTester = multiTester(allSelectionDefs); + + for(i = 0; i < searchTraces.length; i++) { + traceSelection = searchTraces[i]._module.selectPoints(searchTraces[i], selectionTester); + thisTracesSelection = fillSelectionItem(traceSelection, searchTraces[i]); + + if(selection.length) { + for(var j = 0; j < thisTracesSelection.length; j++) { + selection.push(thisTracesSelection[j]); + } + } + else selection = thisTracesSelection; + } + + eventData = {points: selection}; + updateSelectedState(gd, searchTraces, eventData); + + if(currentSelectionDef && dragOptions) { + dragOptions.selectionDefs.push(currentSelectionDef); + } + + if(polygonOutlines) drawSelection(dragOptions.mergedPolygons, polygonOutlines); + + if(sendEvents) { + gd.emit('plotly_selected', eventData); + } + } + } +} + +/** + * Constructs a new point selection definition object. + */ +function newPointSelectionDef(pointNumber, searchInfo, subtract) { + return { + pointNumber: pointNumber, + searchInfo: searchInfo, + subtract: subtract + }; +} + +function isPointSelectionDef(o) { + return 'pointNumber' in o && 'searchInfo' in o; +} + +/* + * Constructs a new point number tester. + */ +function newPointNumTester(pointSelectionDef) { + return { + xmin: 0, + xmax: 0, + ymin: 0, + ymax: 0, + pts: [], + contains: function(pt, omitFirstEdge, pointNumber, searchInfo) { + var idxWantedTrace = pointSelectionDef.searchInfo.cd[0].trace._expandedIndex; + var idxActualTrace = searchInfo.cd[0].trace._expandedIndex; + return idxActualTrace === idxWantedTrace && + pointNumber === pointSelectionDef.pointNumber; + }, + isRect: false, + degenerate: false, + subtract: pointSelectionDef.subtract + }; +} + +/** + * Wraps multiple selection testers. + * + * @param {Array} list - An array of selection testers. + * + * @return a selection tester object with a contains function + * that can be called to evaluate a point against all wrapped + * selection testers that were passed in list. + */ +function multiTester(list) { + var testers = []; + var xmin = isPointSelectionDef(list[0]) ? 0 : list[0][0][0]; + var xmax = xmin; + var ymin = isPointSelectionDef(list[0]) ? 0 : list[0][0][1]; + var ymax = ymin; + + for(var i = 0; i < list.length; i++) { + if(isPointSelectionDef(list[i])) { + testers.push(newPointNumTester(list[i])); + } else { + var tester = polygon.tester(list[i]); + tester.subtract = list[i].subtract; + testers.push(tester); + xmin = Math.min(xmin, tester.xmin); + xmax = Math.max(xmax, tester.xmax); + ymin = Math.min(ymin, tester.ymin); + ymax = Math.max(ymax, tester.ymax); + } + } + + /** + * Tests if the given point is within this tester. + * + * @param {Array} pt - [0] is the x coordinate, [1] is the y coordinate of the point. + * @param {*} arg - An optional parameter to pass down to wrapped testers. + * @param {number} pointNumber - The point number of the point within the underlying data array. + * @param {number} searchInfo - An object identifying the trace the point is contained in. + * + * @return {boolean} true if point is considered to be selected, false otherwise. + */ + function contains(pt, arg, pointNumber, searchInfo) { + var contained = false; + for(var i = 0; i < testers.length; i++) { + if(testers[i].contains(pt, arg, pointNumber, searchInfo)) { + // if contained by subtract tester - exclude the point + contained = testers[i].subtract === false; + } + } + + return contained; + } + + return { + xmin: xmin, + xmax: xmax, + ymin: ymin, + ymax: ymax, + pts: [], + contains: contains, + isRect: false, + degenerate: false + }; +} + +function coerceSelectionsCache(evt, gd, dragOptions) { + var fullLayout = gd._fullLayout; + var zoomLayer = fullLayout._zoomlayer; + var plotinfo = dragOptions.plotinfo; + + var selectingOnSameSubplot = ( + fullLayout._lastSelectedSubplot && + fullLayout._lastSelectedSubplot === plotinfo.id + ); + var hasModifierKey = evt.shiftKey || evt.altKey; + if(selectingOnSameSubplot && hasModifierKey && + (plotinfo.selection && plotinfo.selection.selectionDefs) && !dragOptions.selectionDefs) { + // take over selection definitions from prev mode, if any + dragOptions.selectionDefs = plotinfo.selection.selectionDefs; + dragOptions.mergedPolygons = plotinfo.selection.mergedPolygons; + } else if(!hasModifierKey || !plotinfo.selection) { + clearSelectionsCache(dragOptions); + } + + // clear selection outline when selecting a different subplot + if(!selectingOnSameSubplot) { + clearSelect(zoomLayer); + fullLayout._lastSelectedSubplot = plotinfo.id; + } +} + +function clearSelectionsCache(dragOptions) { + var plotinfo = dragOptions.plotinfo; + + plotinfo.selection = {}; + plotinfo.selection.selectionDefs = dragOptions.selectionDefs = []; + plotinfo.selection.mergedPolygons = dragOptions.mergedPolygons = []; +} + +function determineSearchTraces(gd, xAxes, yAxes, subplot) { + var searchTraces = []; + var xAxisIds = xAxes.map(getAxId); + var yAxisIds = yAxes.map(getAxId); + var cd, trace, i; + + for(i = 0; i < gd.calcdata.length; i++) { + cd = gd.calcdata[i]; + trace = cd[0].trace; + + if(trace.visible !== true || !trace._module || !trace._module.selectPoints) continue; + + if(subplot && (trace.subplot === subplot || trace.geo === subplot)) { + searchTraces.push(createSearchInfo(trace._module, cd, xAxes[0], yAxes[0])); + } else if( + trace.type === 'splom' && + // FIXME: make sure we don't have more than single axis for splom + trace._xaxes[xAxisIds[0]] && trace._yaxes[yAxisIds[0]] + ) { + var info = createSearchInfo(trace._module, cd, xAxes[0], yAxes[0]); + info.scene = gd._fullLayout._splomScenes[trace.uid]; + searchTraces.push(info); + } else { + if(xAxisIds.indexOf(trace.xaxis) === -1) continue; + if(yAxisIds.indexOf(trace.yaxis) === -1) continue; + + searchTraces.push(createSearchInfo(trace._module, cd, + getFromId(gd, trace.xaxis), getFromId(gd, trace.yaxis))); + } + } + + return searchTraces; + + function createSearchInfo(module, calcData, xaxis, yaxis) { + return { + _module: module, + cd: calcData, + xaxis: xaxis, + yaxis: yaxis + }; + } +} + +function drawSelection(polygons, outlines) { + var paths = []; + var i, d; + + for(i = 0; i < polygons.length; i++) { + var ppts = polygons[i]; + paths.push(ppts.join('L') + 'L' + ppts[0]); + } + + d = polygons.length > 0 ? + 'M' + paths.join('M') + 'Z' : + 'M0,0Z'; + outlines.attr('d', d); +} + +function isHoverDataSet(hoverData) { + return hoverData && + Array.isArray(hoverData) && + hoverData[0].hoverOnBox !== true; +} + +function extractClickedPtInfo(hoverData, searchTraces) { + var hoverDatum = hoverData[0]; + var pointNumber = -1; + var pointNumbers = []; + var searchInfo, i; + + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + if(hoverDatum.fullData._expandedIndex === searchInfo.cd[0].trace._expandedIndex) { + + // Special case for box (and violin) + if(hoverDatum.hoverOnBox === true) { + break; + } + + // Hint: in some traces like histogram, one graphical element + // doesn't correspond to one particular data point, but to + // bins of data points. Thus, hoverDatum can have a binNumber + // property instead of pointNumber. + if(hoverDatum.pointNumber !== undefined) { + pointNumber = hoverDatum.pointNumber; + } else if(hoverDatum.binNumber !== undefined) { + pointNumber = hoverDatum.binNumber; + pointNumbers = hoverDatum.pointNumbers; + } + + break; + } + } + + return { + pointNumber: pointNumber, + pointNumbers: pointNumbers, + searchInfo: searchInfo + }; +} + +function isPointOrBinSelected(clickedPtInfo) { + var trace = clickedPtInfo.searchInfo.cd[0].trace; + var ptNum = clickedPtInfo.pointNumber; + var ptNums = clickedPtInfo.pointNumbers; + var ptNumsSet = ptNums.length > 0; + + // When pointsNumbers is set (e.g. histogram's binning), + // it is assumed that when the first point of + // a bin is selected, all others are as well + var ptNumToTest = ptNumsSet ? ptNums[0] : ptNum; + + // TODO potential performance improvement + // Primarily we need this function to determine if a click adds + // or subtracts from a selection. + // In cases `trace.selectedpoints` is a huge array, indexOf + // might be slow. One remedy would be to introduce a hash somewhere. + return trace.selectedpoints ? trace.selectedpoints.indexOf(ptNumToTest) > -1 : false; +} + +function isOnlyThisBinSelected(searchTraces, clickedPtInfo) { + var tracesWithSelectedPts = []; + var searchInfo, trace, isSameTrace, i; + + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + if(searchInfo.cd[0].trace.selectedpoints && searchInfo.cd[0].trace.selectedpoints.length > 0) { + tracesWithSelectedPts.push(searchInfo); + } + } + + if(tracesWithSelectedPts.length === 1) { + isSameTrace = tracesWithSelectedPts[0] === clickedPtInfo.searchInfo; + if(isSameTrace) { + trace = clickedPtInfo.searchInfo.cd[0].trace; + if(trace.selectedpoints.length === clickedPtInfo.pointNumbers.length) { + for(i = 0; i < clickedPtInfo.pointNumbers.length; i++) { + if(trace.selectedpoints.indexOf(clickedPtInfo.pointNumbers[i]) < 0) { + return false; + } + } + return true; + } + } + } + + return false; +} + +function isOnlyOnePointSelected(searchTraces) { + var len = 0; + var searchInfo, trace, i; + + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + trace = searchInfo.cd[0].trace; + if(trace.selectedpoints) { + if(trace.selectedpoints.length > 1) return false; + + len += trace.selectedpoints.length; + if(len > 1) return false; + } + } + + return len === 1; +} + +function updateSelectedState(gd, searchTraces, eventData) { + var i, searchInfo, cd, trace; + + if(eventData) { + var pts = eventData.points || []; + + for(i = 0; i < searchTraces.length; i++) { + trace = searchTraces[i].cd[0].trace; + trace.selectedpoints = []; + trace._input.selectedpoints = []; + } + + for(i = 0; i < pts.length; i++) { + var pt = pts[i]; + var data = pt.data; + var fullData = pt.fullData; + + if(pt.pointIndices) { + [].push.apply(data.selectedpoints, pt.pointIndices); + [].push.apply(fullData.selectedpoints, pt.pointIndices); + } else { + data.selectedpoints.push(pt.pointIndex); + fullData.selectedpoints.push(pt.pointIndex); + } + } + } + else { + for(i = 0; i < searchTraces.length; i++) { + trace = searchTraces[i].cd[0].trace; + delete trace.selectedpoints; + delete trace._input.selectedpoints; + } + } + + var hasRegl = false; + + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + cd = searchInfo.cd; + trace = cd[0].trace; + + if(Registry.traceIs(trace, 'regl')) { + hasRegl = true; + } + + var _module = searchInfo._module; + var fn = _module.styleOnSelect || _module.style; + if(fn) fn(gd, cd); + } + + if(hasRegl) { + clearGlCanvases(gd); + redrawReglTraces(gd); + } +} + +function mergePolygons(list, poly, subtract) { + var res; + + if(subtract) { + res = polybool.difference({ + regions: list, + inverted: false + }, { + regions: [poly], + inverted: false + }); + + return res.regions; + } + + res = polybool.union({ + regions: list, + inverted: false + }, { + regions: [poly], + inverted: false + }); + + return res.regions; +} + +function fillSelectionItem(selection, searchInfo) { + if(Array.isArray(selection)) { + var cd = searchInfo.cd; + var trace = searchInfo.cd[0].trace; + + for(var i = 0; i < selection.length; i++) { + selection[i] = makeEventData(selection[i], trace, cd); + } + } + + return selection; +} + +function clearSelect(zoomlayer) { + // until we get around to persistent selections, remove the outline + // here. The selection itself will be removed when the plot redraws + // at the end. + zoomlayer.selectAll('.select-outline').remove(); +} + +module.exports = { + prepSelect: prepSelect, + clearSelect: clearSelect, + selectOnClick: selectOnClick +}; + +},{"../../components/color":570,"../../components/fx":612,"../../components/fx/helpers":609,"../../lib/clear_gl_canvases":680,"../../lib/polygon":708,"../../lib/throttle":721,"../../plot_api/subroutines":735,"../../registry":827,"./axis_ids":747,"./constants":750,"polybooljs":456}],763:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var cleanNumber = Lib.cleanNumber; +var ms2DateTime = Lib.ms2DateTime; +var dateTime2ms = Lib.dateTime2ms; +var ensureNumber = Lib.ensureNumber; + +var numConstants = _dereq_('../../constants/numerical'); +var FP_SAFE = numConstants.FP_SAFE; +var BADNUM = numConstants.BADNUM; +var LOG_CLIP = numConstants.LOG_CLIP; + +var constants = _dereq_('./constants'); +var axisIds = _dereq_('./axis_ids'); + +function fromLog(v) { + return Math.pow(10, v); +} + +/** + * Define the conversion functions for an axis data is used in 5 ways: + * + * d: data, in whatever form it's provided + * c: calcdata: turned into numbers, but not linearized + * l: linearized - same as c except for log axes (and other nonlinear + * mappings later?) this is used when we need to know if it's + * *possible* to show some data on this axis, without caring about + * the current range + * p: pixel value - mapped to the screen with current size and zoom + * r: ranges, tick0, and annotation positions match one of the above + * but are handled differently for different types: + * - linear and date: data format (d) + * - category: calcdata format (c), and will stay that way because + * the data format has no continuous mapping + * - log: linearized (l) format + * TODO: in v2.0 we plan to change it to data format. At that point + * shapes will work the same way as ranges, tick0, and annotations + * so they can use this conversion too. + * + * Creates/updates these conversion functions, and a few more utilities + * like cleanRange, and makeCalcdata + * + * also clears the autotick constraints ._minDtick, ._forceTick0 + */ +module.exports = function setConvert(ax, fullLayout) { + fullLayout = fullLayout || {}; + + var axLetter = (ax._id || 'x').charAt(0); + + function toLog(v, clip) { + if(v > 0) return Math.log(v) / Math.LN10; + + else if(v <= 0 && clip && ax.range && ax.range.length === 2) { + // clip NaN (ie past negative infinity) to LOG_CLIP axis + // length past the negative edge + var r0 = ax.range[0], + r1 = ax.range[1]; + return 0.5 * (r0 + r1 - 2 * LOG_CLIP * Math.abs(r0 - r1)); + } + + else return BADNUM; + } + + /* + * wrapped dateTime2ms that: + * - accepts ms numbers for backward compatibility + * - inserts a dummy arg so calendar is the 3rd arg (see notes below). + * - defaults to ax.calendar + */ + function dt2ms(v, _, calendar) { + // NOTE: Changed this behavior: previously we took any numeric value + // to be a ms, even if it was a string that could be a bare year. + // Now we convert it as a date if at all possible, and only try + // as (local) ms if that fails. + var ms = dateTime2ms(v, calendar || ax.calendar); + if(ms === BADNUM) { + if(isNumeric(v)) { + v = +v; + // keep track of tenths of ms, that `new Date` will drop + // same logic as in Lib.ms2DateTime + var msecTenths = Math.floor(Lib.mod(v + 0.05, 1) * 10); + var msRounded = Math.round(v - msecTenths / 10); + ms = dateTime2ms(new Date(msRounded)) + msecTenths / 10; + } + else return BADNUM; + } + return ms; + } + + // wrapped ms2DateTime to insert default ax.calendar + function ms2dt(v, r, calendar) { + return ms2DateTime(v, r, calendar || ax.calendar); + } + + function getCategoryName(v) { + return ax._categories[Math.round(v)]; + } + + /* + * setCategoryIndex: return the index of category v, + * inserting it in the list if it's not already there + * + * this will enter the categories in the order it + * encounters them, ie all the categories from the + * first data set, then all the ones from the second + * that aren't in the first etc. + * + * it is assumed that this function is being invoked in the + * already sorted category order; otherwise there would be + * a disconnect between the array and the index returned + */ + function setCategoryIndex(v) { + if(v !== null && v !== undefined) { + if(ax._categoriesMap === undefined) { + ax._categoriesMap = {}; + } + + if(ax._categoriesMap[v] !== undefined) { + return ax._categoriesMap[v]; + } else { + ax._categories.push(v); + + var curLength = ax._categories.length - 1; + ax._categoriesMap[v] = curLength; + + return curLength; + } + } + return BADNUM; + } + + function getCategoryIndex(v) { + // d2l/d2c variant that that won't add categories but will also + // allow numbers to be mapped to the linearized axis positions + if(ax._categoriesMap) { + var index = ax._categoriesMap[v]; + if(index !== undefined) return index; + } + + if(isNumeric(v)) return +v; + } + + function l2p(v) { + if(!isNumeric(v)) return BADNUM; + + // include 2 fractional digits on pixel, for PDF zooming etc + return d3.round(ax._b + ax._m * v, 2); + } + + function p2l(px) { return (px - ax._b) / ax._m; } + + // conversions among c/l/p are fairly simple - do them together for all axis types + ax.c2l = (ax.type === 'log') ? toLog : ensureNumber; + ax.l2c = (ax.type === 'log') ? fromLog : ensureNumber; + + ax.l2p = l2p; + ax.p2l = p2l; + + ax.c2p = (ax.type === 'log') ? function(v, clip) { return l2p(toLog(v, clip)); } : l2p; + ax.p2c = (ax.type === 'log') ? function(px) { return fromLog(p2l(px)); } : p2l; + + /* + * now type-specific conversions for **ALL** other combinations + * they're all written out, instead of being combinations of each other, for + * both clarity and speed. + */ + if(['linear', '-'].indexOf(ax.type) !== -1) { + // all are data vals, but d and r need cleaning + ax.d2r = ax.r2d = ax.d2c = ax.r2c = ax.d2l = ax.r2l = cleanNumber; + ax.c2d = ax.c2r = ax.l2d = ax.l2r = ensureNumber; + + ax.d2p = ax.r2p = function(v) { return ax.l2p(cleanNumber(v)); }; + ax.p2d = ax.p2r = p2l; + + ax.cleanPos = ensureNumber; + } + else if(ax.type === 'log') { + // d and c are data vals, r and l are logged (but d and r need cleaning) + ax.d2r = ax.d2l = function(v, clip) { return toLog(cleanNumber(v), clip); }; + ax.r2d = ax.r2c = function(v) { return fromLog(cleanNumber(v)); }; + + ax.d2c = ax.r2l = cleanNumber; + ax.c2d = ax.l2r = ensureNumber; + + ax.c2r = toLog; + ax.l2d = fromLog; + + ax.d2p = function(v, clip) { return ax.l2p(ax.d2r(v, clip)); }; + ax.p2d = function(px) { return fromLog(p2l(px)); }; + + ax.r2p = function(v) { return ax.l2p(cleanNumber(v)); }; + ax.p2r = p2l; + + ax.cleanPos = ensureNumber; + } + else if(ax.type === 'date') { + // r and d are date strings, l and c are ms + + /* + * Any of these functions with r and d on either side, calendar is the + * **3rd** argument. log has reserved the second argument. + * + * Unless you need the special behavior of the second arg (ms2DateTime + * uses this to limit precision, toLog uses true to clip negatives + * to offscreen low rather than undefined), it's safe to pass 0. + */ + ax.d2r = ax.r2d = Lib.identity; + + ax.d2c = ax.r2c = ax.d2l = ax.r2l = dt2ms; + ax.c2d = ax.c2r = ax.l2d = ax.l2r = ms2dt; + + ax.d2p = ax.r2p = function(v, _, calendar) { return ax.l2p(dt2ms(v, 0, calendar)); }; + ax.p2d = ax.p2r = function(px, r, calendar) { return ms2dt(p2l(px), r, calendar); }; + + ax.cleanPos = function(v) { return Lib.cleanDate(v, BADNUM, ax.calendar); }; + } + else if(ax.type === 'category') { + // d is categories (string) + // c and l are indices (numbers) + // r is categories or numbers + + ax.d2c = ax.d2l = setCategoryIndex; + ax.r2d = ax.c2d = ax.l2d = getCategoryName; + + ax.d2r = ax.d2l_noadd = getCategoryIndex; + + ax.r2c = function(v) { + var index = getCategoryIndex(v); + return index !== undefined ? index : ax.fraction2r(0.5); + }; + + ax.l2r = ax.c2r = ensureNumber; + ax.r2l = getCategoryIndex; + + ax.d2p = function(v) { return ax.l2p(ax.r2c(v)); }; + ax.p2d = function(px) { return getCategoryName(p2l(px)); }; + ax.r2p = ax.d2p; + ax.p2r = p2l; + + ax.cleanPos = function(v) { + if(typeof v === 'string' && v !== '') return v; + return ensureNumber(v); + }; + } + + // find the range value at the specified (linear) fraction of the axis + ax.fraction2r = function(v) { + var rl0 = ax.r2l(ax.range[0]), + rl1 = ax.r2l(ax.range[1]); + return ax.l2r(rl0 + v * (rl1 - rl0)); + }; + + // find the fraction of the range at the specified range value + ax.r2fraction = function(v) { + var rl0 = ax.r2l(ax.range[0]), + rl1 = ax.r2l(ax.range[1]); + return (ax.r2l(v) - rl0) / (rl1 - rl0); + }; + + /* + * cleanRange: make sure range is a couplet of valid & distinct values + * keep numbers away from the limits of floating point numbers, + * and dates away from the ends of our date system (+/- 9999 years) + * + * optional param rangeAttr: operate on a different attribute, like + * ax._r, rather than ax.range + */ + ax.cleanRange = function(rangeAttr, opts) { + if(!opts) opts = {}; + if(!rangeAttr) rangeAttr = 'range'; + + var range = Lib.nestedProperty(ax, rangeAttr).get(); + var i, dflt; + + if(ax.type === 'date') dflt = Lib.dfltRange(ax.calendar); + else if(axLetter === 'y') dflt = constants.DFLTRANGEY; + else dflt = opts.dfltRange || constants.DFLTRANGEX; + + // make sure we don't later mutate the defaults + dflt = dflt.slice(); + + if(!range || range.length !== 2) { + Lib.nestedProperty(ax, rangeAttr).set(dflt); + return; + } + + if(ax.type === 'date') { + // check if milliseconds or js date objects are provided for range + // and convert to date strings + range[0] = Lib.cleanDate(range[0], BADNUM, ax.calendar); + range[1] = Lib.cleanDate(range[1], BADNUM, ax.calendar); + } + + for(i = 0; i < 2; i++) { + if(ax.type === 'date') { + if(!Lib.isDateTime(range[i], ax.calendar)) { + ax[rangeAttr] = dflt; + break; + } + + if(ax.r2l(range[0]) === ax.r2l(range[1])) { + // split by +/- 1 second + var linCenter = Lib.constrain(ax.r2l(range[0]), + Lib.MIN_MS + 1000, Lib.MAX_MS - 1000); + range[0] = ax.l2r(linCenter - 1000); + range[1] = ax.l2r(linCenter + 1000); + break; + } + } + else { + if(!isNumeric(range[i])) { + if(isNumeric(range[1 - i])) { + range[i] = range[1 - i] * (i ? 10 : 0.1); + } + else { + ax[rangeAttr] = dflt; + break; + } + } + + if(range[i] < -FP_SAFE) range[i] = -FP_SAFE; + else if(range[i] > FP_SAFE) range[i] = FP_SAFE; + + if(range[0] === range[1]) { + // somewhat arbitrary: split by 1 or 1ppm, whichever is bigger + var inc = Math.max(1, Math.abs(range[0] * 1e-6)); + range[0] -= inc; + range[1] += inc; + } + } + } + }; + + // set scaling to pixels + ax.setScale = function(usePrivateRange) { + var gs = fullLayout._size; + + // TODO cleaner way to handle this case + if(!ax._categories) ax._categories = []; + // Add a map to optimize the performance of category collection + if(!ax._categoriesMap) ax._categoriesMap = {}; + + // make sure we have a domain (pull it in from the axis + // this one is overlaying if necessary) + if(ax.overlaying) { + var ax2 = axisIds.getFromId({ _fullLayout: fullLayout }, ax.overlaying); + ax.domain = ax2.domain; + } + + // While transitions are occuring, occurring, we get a double-transform + // issue if we transform the drawn layer *and* use the new axis range to + // draw the data. This allows us to construct setConvert using the pre- + // interaction values of the range: + var rangeAttr = (usePrivateRange && ax._r) ? '_r' : 'range', + calendar = ax.calendar; + ax.cleanRange(rangeAttr); + + var rl0 = ax.r2l(ax[rangeAttr][0], calendar), + rl1 = ax.r2l(ax[rangeAttr][1], calendar); + + if(axLetter === 'y') { + ax._offset = gs.t + (1 - ax.domain[1]) * gs.h; + ax._length = gs.h * (ax.domain[1] - ax.domain[0]); + ax._m = ax._length / (rl0 - rl1); + ax._b = -ax._m * rl1; + } + else { + ax._offset = gs.l + ax.domain[0] * gs.w; + ax._length = gs.w * (ax.domain[1] - ax.domain[0]); + ax._m = ax._length / (rl1 - rl0); + ax._b = -ax._m * rl0; + } + + if(!isFinite(ax._m) || !isFinite(ax._b)) { + fullLayout._replotting = false; + throw new Error('Something went wrong with axis scaling'); + } + }; + + // makeCalcdata: takes an x or y array and converts it + // to a position on the axis object "ax" + // inputs: + // trace - a data object from gd.data + // axLetter - a string, either 'x' or 'y', for which item + // to convert (TODO: is this now always the same as + // the first letter of ax._id?) + // in case the expected data isn't there, make a list of + // integers based on the opposite data + ax.makeCalcdata = function(trace, axLetter) { + var arrayIn, arrayOut, i, len; + + var axType = ax.type; + var cal = axType === 'date' && trace[axLetter + 'calendar']; + + if(axLetter in trace) { + arrayIn = trace[axLetter]; + len = trace._length || arrayIn.length; + + if(Lib.isTypedArray(arrayIn) && (axType === 'linear' || axType === 'log')) { + if(len === arrayIn.length) { + return arrayIn; + } else if(arrayIn.subarray) { + return arrayIn.subarray(0, len); + } + } + + arrayOut = new Array(len); + for(i = 0; i < len; i++) { + arrayOut[i] = ax.d2c(arrayIn[i], 0, cal); + } + } + else { + var v0 = ((axLetter + '0') in trace) ? ax.d2c(trace[axLetter + '0'], 0, cal) : 0; + var dv = (trace['d' + axLetter]) ? Number(trace['d' + axLetter]) : 1; + + // the opposing data, for size if we have x and dx etc + arrayIn = trace[{x: 'y', y: 'x'}[axLetter]]; + len = trace._length || arrayIn.length; + arrayOut = new Array(len); + + for(i = 0; i < len; i++) { + arrayOut[i] = v0 + i * dv; + } + } + + return arrayOut; + }; + + ax.isValidRange = function(range) { + return ( + Array.isArray(range) && + range.length === 2 && + isNumeric(ax.r2l(range[0])) && + isNumeric(ax.r2l(range[1])) + ); + }; + + ax.isPtWithinRange = function(d, calendar) { + var coord = ax.c2l(d[axLetter], null, calendar); + var r0 = ax.r2l(ax.range[0]); + var r1 = ax.r2l(ax.range[1]); + + if(r0 < r1) { + return r0 <= coord && coord <= r1; + } else { + // Reversed axis case. + return r1 <= coord && coord <= r0; + } + }; + + ax.clearCalc = function() { + // initialize the category list, if there is one, so we start over + // to be filled in later by ax.d2c + ax._categories = (ax._initialCategories || []).slice(); + + // Build the lookup map for initialized categories + ax._categoriesMap = {}; + for(var j = 0; j < ax._categories.length; j++) { + ax._categoriesMap[ax._categories[j]] = j; + } + }; + + // Propagate localization into the axis so that + // methods in Axes can use it w/o having to pass fullLayout + // Default (non-d3) number formatting uses separators directly + // dates and d3-formatted numbers use the d3 locale + // Fall back on default format for dummy axes that don't care about formatting + var locale = fullLayout._d3locale; + if(ax.type === 'date') { + ax._dateFormat = locale ? locale.timeFormat.utc : d3.time.format.utc; + ax._extraFormat = fullLayout._extraFormat; + } + // occasionally we need _numFormat to pass through + // even though it won't be needed by this axis + ax._separators = fullLayout.separators; + ax._numFormat = locale ? locale.numberFormat : d3.format; + + // and for bar charts and box plots: reset forced minimum tick spacing + delete ax._minDtick; + delete ax._forceTick0; +}; + +},{"../../constants/numerical":673,"../../lib":696,"./axis_ids":747,"./constants":750,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],764:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var layoutAttributes = _dereq_('./layout_attributes'); +var handleArrayContainerDefaults = _dereq_('../array_container_defaults'); + +module.exports = function handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options) { + var showAttrDflt = getShowAttrDflt(containerIn); + + var tickPrefix = coerce('tickprefix'); + if(tickPrefix) coerce('showtickprefix', showAttrDflt); + + var tickSuffix = coerce('ticksuffix', options.tickSuffixDflt); + if(tickSuffix) coerce('showticksuffix', showAttrDflt); + + var showTickLabels = coerce('showticklabels'); + if(showTickLabels) { + var font = options.font || {}; + var contColor = containerOut.color; + // as with titlefont.color, inherit axis.color only if one was + // explicitly provided + var dfltFontColor = (contColor && contColor !== layoutAttributes.color.dflt) ? + contColor : font.color; + Lib.coerceFont(coerce, 'tickfont', { + family: font.family, + size: font.size, + color: dfltFontColor + }); + coerce('tickangle'); + + if(axType !== 'category') { + var tickFormat = coerce('tickformat'); + var tickformatStops = containerIn.tickformatstops; + if(Array.isArray(tickformatStops) && tickformatStops.length) { + handleArrayContainerDefaults(containerIn, containerOut, { + name: 'tickformatstops', + inclusionAttr: 'enabled', + handleItemDefaults: tickformatstopDefaults + }); + } + if(!tickFormat && axType !== 'date') { + coerce('showexponent', showAttrDflt); + coerce('exponentformat'); + coerce('separatethousands'); + } + } + } +}; + +/* + * Attributes 'showexponent', 'showtickprefix' and 'showticksuffix' + * share values. + * + * If only 1 attribute is set, + * the remaining attributes inherit that value. + * + * If 2 attributes are set to the same value, + * the remaining attribute inherits that value. + * + * If 2 attributes are set to different values, + * the remaining is set to its dflt value. + * + */ +function getShowAttrDflt(containerIn) { + var showAttrsAll = ['showexponent', + 'showtickprefix', + 'showticksuffix'], + showAttrs = showAttrsAll.filter(function(a) { + return containerIn[a] !== undefined; + }), + sameVal = function(a) { + return containerIn[a] === containerIn[showAttrs[0]]; + }; + + if(showAttrs.every(sameVal) || showAttrs.length === 1) { + return containerIn[showAttrs[0]]; + } +} + +function tickformatstopDefaults(valueIn, valueOut) { + function coerce(attr, dflt) { + return Lib.coerce(valueIn, valueOut, layoutAttributes.tickformatstops, attr, dflt); + } + + var enabled = coerce('enabled'); + if(enabled) { + coerce('dtickrange'); + coerce('value'); + } +} + +},{"../../lib":696,"../array_container_defaults":740,"./layout_attributes":757}],765:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var layoutAttributes = _dereq_('./layout_attributes'); + + +/** + * options: inherits outerTicks from axes.handleAxisDefaults + */ +module.exports = function handleTickDefaults(containerIn, containerOut, coerce, options) { + var tickLen = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'ticklen'), + tickWidth = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickwidth'), + tickColor = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickcolor', containerOut.color), + showTicks = coerce('ticks', (options.outerTicks || tickLen || tickWidth || tickColor) ? 'outside' : ''); + + if(!showTicks) { + delete containerOut.ticklen; + delete containerOut.tickwidth; + delete containerOut.tickcolor; + } +}; + +},{"../../lib":696,"./layout_attributes":757}],766:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var cleanTicks = _dereq_('./clean_ticks'); + + +module.exports = function handleTickValueDefaults(containerIn, containerOut, coerce, axType) { + var tickmode; + + if(containerIn.tickmode === 'array' && + (axType === 'log' || axType === 'date')) { + tickmode = containerOut.tickmode = 'auto'; + } + else { + var tickmodeDefault = + Array.isArray(containerIn.tickvals) ? 'array' : + containerIn.dtick ? 'linear' : + 'auto'; + tickmode = coerce('tickmode', tickmodeDefault); + } + + if(tickmode === 'auto') coerce('nticks'); + else if(tickmode === 'linear') { + // dtick is usually a positive number, but there are some + // special strings available for log or date axes + // tick0 also has special logic + var dtick = containerOut.dtick = cleanTicks.dtick( + containerIn.dtick, axType); + containerOut.tick0 = cleanTicks.tick0( + containerIn.tick0, axType, containerOut.calendar, dtick); + } + else { + var tickvals = coerce('tickvals'); + if(tickvals === undefined) containerOut.tickmode = 'auto'; + else coerce('ticktext'); + } +}; + +},{"./clean_ticks":749}],767:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Drawing = _dereq_('../../components/drawing'); +var Axes = _dereq_('./axes'); +var axisRegex = _dereq_('./constants').attrRegex; + +function transitionAxes(gd, newLayout, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout; + var axes = []; + + function computeUpdates(layout) { + var ai, attrList, match, axis, update; + var updates = {}; + + for(ai in layout) { + attrList = ai.split('.'); + match = attrList[0].match(axisRegex); + if(match) { + var axisLetter = ai.charAt(0); + var axisName = attrList[0]; + axis = fullLayout[axisName]; + update = {}; + + if(Array.isArray(layout[ai])) { + update.to = layout[ai].slice(0); + } else { + if(Array.isArray(layout[ai].range)) { + update.to = layout[ai].range.slice(0); + } + } + if(!update.to) continue; + + update.axisName = axisName; + update.length = axis._length; + + axes.push(axisLetter); + + updates[axisLetter] = update; + } + } + + return updates; + } + + function computeAffectedSubplots(fullLayout, updatedAxisIds, updates) { + var plotName; + var plotinfos = fullLayout._plots; + var affectedSubplots = []; + var toX, toY; + + for(plotName in plotinfos) { + var plotinfo = plotinfos[plotName]; + + if(affectedSubplots.indexOf(plotinfo) !== -1) continue; + + var x = plotinfo.xaxis._id; + var y = plotinfo.yaxis._id; + var fromX = plotinfo.xaxis.range; + var fromY = plotinfo.yaxis.range; + + // Store the initial range at the beginning of this transition: + plotinfo.xaxis._r = plotinfo.xaxis.range.slice(); + plotinfo.yaxis._r = plotinfo.yaxis.range.slice(); + + if(updates[x]) { + toX = updates[x].to; + } else { + toX = fromX; + } + if(updates[y]) { + toY = updates[y].to; + } else { + toY = fromY; + } + + if(fromX[0] === toX[0] && fromX[1] === toX[1] && fromY[0] === toY[0] && fromY[1] === toY[1]) continue; + + if(updatedAxisIds.indexOf(x) !== -1 || updatedAxisIds.indexOf(y) !== -1) { + affectedSubplots.push(plotinfo); + } + } + + return affectedSubplots; + } + + var updates = computeUpdates(newLayout); + var updatedAxisIds = Object.keys(updates); + var affectedSubplots = computeAffectedSubplots(fullLayout, updatedAxisIds, updates); + + function updateLayoutObjs() { + function redrawObjs(objArray, method, shortCircuit) { + for(var i = 0; i < objArray.length; i++) { + method(gd, i); + + // once is enough for images (which doesn't use the `i` arg anyway) + if(shortCircuit) return; + } + } + + redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true); + } + + if(!affectedSubplots.length) { + updateLayoutObjs(); + return false; + } + + function ticksAndAnnotations(xa, ya) { + var activeAxIds = [], + i; + + activeAxIds = [xa._id, ya._id]; + + for(i = 0; i < activeAxIds.length; i++) { + Axes.doTicksSingle(gd, activeAxIds[i], true); + } + + function redrawObjs(objArray, method, shortCircuit) { + for(i = 0; i < objArray.length; i++) { + var obji = objArray[i]; + + if((activeAxIds.indexOf(obji.xref) !== -1) || + (activeAxIds.indexOf(obji.yref) !== -1)) { + method(gd, i); + } + + // once is enough for images (which doesn't use the `i` arg anyway) + if(shortCircuit) return; + } + } + + redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true); + } + + function unsetSubplotTransform(subplot) { + var xa2 = subplot.xaxis; + var ya2 = subplot.yaxis; + + fullLayout._defs.select('#' + subplot.clipId + '> rect') + .call(Drawing.setTranslate, 0, 0) + .call(Drawing.setScale, 1, 1); + + subplot.plot + .call(Drawing.setTranslate, xa2._offset, ya2._offset) + .call(Drawing.setScale, 1, 1); + + var traceGroups = subplot.plot.selectAll('.scatterlayer .trace'); + + // This is specifically directed at scatter traces, applying an inverse + // scale to individual points to counteract the scale of the trace + // as a whole: + traceGroups.selectAll('.point') + .call(Drawing.setPointGroupScale, 1, 1); + traceGroups.selectAll('.textpoint') + .call(Drawing.setTextPointsScale, 1, 1); + traceGroups + .call(Drawing.hideOutsideRangePoints, subplot); + } + + function updateSubplot(subplot, progress) { + var axis, r0, r1; + var xUpdate = updates[subplot.xaxis._id]; + var yUpdate = updates[subplot.yaxis._id]; + + var viewBox = []; + + if(xUpdate) { + axis = gd._fullLayout[xUpdate.axisName]; + r0 = axis._r; + r1 = xUpdate.to; + viewBox[0] = (r0[0] * (1 - progress) + progress * r1[0] - r0[0]) / (r0[1] - r0[0]) * subplot.xaxis._length; + var dx1 = r0[1] - r0[0]; + var dx2 = r1[1] - r1[0]; + + axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]; + axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]; + + viewBox[2] = subplot.xaxis._length * ((1 - progress) + progress * dx2 / dx1); + } else { + viewBox[0] = 0; + viewBox[2] = subplot.xaxis._length; + } + + if(yUpdate) { + axis = gd._fullLayout[yUpdate.axisName]; + r0 = axis._r; + r1 = yUpdate.to; + viewBox[1] = (r0[1] * (1 - progress) + progress * r1[1] - r0[1]) / (r0[0] - r0[1]) * subplot.yaxis._length; + var dy1 = r0[1] - r0[0]; + var dy2 = r1[1] - r1[0]; + + axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]; + axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]; + + viewBox[3] = subplot.yaxis._length * ((1 - progress) + progress * dy2 / dy1); + } else { + viewBox[1] = 0; + viewBox[3] = subplot.yaxis._length; + } + + ticksAndAnnotations(subplot.xaxis, subplot.yaxis); + + var xa2 = subplot.xaxis; + var ya2 = subplot.yaxis; + + var editX = !!xUpdate; + var editY = !!yUpdate; + + var xScaleFactor = editX ? xa2._length / viewBox[2] : 1, + yScaleFactor = editY ? ya2._length / viewBox[3] : 1; + + var clipDx = editX ? viewBox[0] : 0, + clipDy = editY ? viewBox[1] : 0; + + var fracDx = editX ? (viewBox[0] / viewBox[2] * xa2._length) : 0, + fracDy = editY ? (viewBox[1] / viewBox[3] * ya2._length) : 0; + + var plotDx = xa2._offset - fracDx, + plotDy = ya2._offset - fracDy; + + subplot.clipRect + .call(Drawing.setTranslate, clipDx, clipDy) + .call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor); + + subplot.plot + .call(Drawing.setTranslate, plotDx, plotDy) + .call(Drawing.setScale, xScaleFactor, yScaleFactor); + + // apply an inverse scale to individual points to counteract + // the scale of the trace group. + Drawing.setPointGroupScale(subplot.zoomScalePts, 1 / xScaleFactor, 1 / yScaleFactor); + Drawing.setTextPointsScale(subplot.zoomScaleTxt, 1 / xScaleFactor, 1 / yScaleFactor); + } + + var onComplete; + if(makeOnCompleteCallback) { + // This module makes the choice whether or not it notifies Plotly.transition + // about completion: + onComplete = makeOnCompleteCallback(); + } + + function transitionComplete() { + var aobj = {}; + for(var i = 0; i < updatedAxisIds.length; i++) { + var axi = gd._fullLayout[updates[updatedAxisIds[i]].axisName]; + var to = updates[updatedAxisIds[i]].to; + aobj[axi._name + '.range[0]'] = to[0]; + aobj[axi._name + '.range[1]'] = to[1]; + + axi.range = to.slice(); + } + + // Signal that this transition has completed: + onComplete && onComplete(); + + return Registry.call('relayout', gd, aobj).then(function() { + for(var i = 0; i < affectedSubplots.length; i++) { + unsetSubplotTransform(affectedSubplots[i]); + } + }); + } + + function transitionInterrupt() { + var aobj = {}; + for(var i = 0; i < updatedAxisIds.length; i++) { + var axi = gd._fullLayout[updatedAxisIds[i] + 'axis']; + aobj[axi._name + '.range[0]'] = axi.range[0]; + aobj[axi._name + '.range[1]'] = axi.range[1]; + + axi.range = axi._r.slice(); + } + + return Registry.call('relayout', gd, aobj).then(function() { + for(var i = 0; i < affectedSubplots.length; i++) { + unsetSubplotTransform(affectedSubplots[i]); + } + }); + } + + var t1, t2, raf; + var easeFn = d3.ease(transitionOpts.easing); + + gd._transitionData._interruptCallbacks.push(function() { + window.cancelAnimationFrame(raf); + raf = null; + return transitionInterrupt(); + }); + + function doFrame() { + t2 = Date.now(); + + var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration); + var progress = easeFn(tInterp); + + for(var i = 0; i < affectedSubplots.length; i++) { + updateSubplot(affectedSubplots[i], progress); + } + + if(t2 - t1 > transitionOpts.duration) { + transitionComplete(); + raf = window.cancelAnimationFrame(doFrame); + } else { + raf = window.requestAnimationFrame(doFrame); + } + } + + t1 = Date.now(); + raf = window.requestAnimationFrame(doFrame); + + return Promise.resolve(); +} + +function transitionAxes2(gd, edits, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout; + + function ticksAndAnnotations(xa, ya) { + var activeAxIds = [xa._id, ya._id]; + var i; + + for(i = 0; i < activeAxIds.length; i++) { + Axes.doTicksSingle(gd, activeAxIds[i], true); + } + + function redrawObjs(objArray, method, shortCircuit) { + for(i = 0; i < objArray.length; i++) { + var obji = objArray[i]; + + if((activeAxIds.indexOf(obji.xref) !== -1) || + (activeAxIds.indexOf(obji.yref) !== -1)) { + method(gd, i); + } + + // once is enough for images (which doesn't use the `i` arg anyway) + if(shortCircuit) return; + } + } + + redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true); + } + + function unsetSubplotTransform(plotinfo) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + fullLayout._defs.select('#' + plotinfo.clipId + '> rect') + .call(Drawing.setTranslate, 0, 0) + .call(Drawing.setScale, 1, 1); + + plotinfo.plot + .call(Drawing.setTranslate, xa._offset, ya._offset) + .call(Drawing.setScale, 1, 1); + + var traceGroups = plotinfo.plot.selectAll('.scatterlayer .trace'); + + // This is specifically directed at scatter traces, applying an inverse + // scale to individual points to counteract the scale of the trace + // as a whole: + traceGroups.selectAll('.point') + .call(Drawing.setPointGroupScale, 1, 1); + traceGroups.selectAll('.textpoint') + .call(Drawing.setTextPointsScale, 1, 1); + traceGroups + .call(Drawing.hideOutsideRangePoints, plotinfo); + } + + function updateSubplot(edit, progress) { + var plotinfo = edit.plotinfo; + var xa1 = plotinfo.xaxis; + var ya1 = plotinfo.yaxis; + + var xr0 = edit.xr0; + var xr1 = edit.xr1; + var xlen = xa1._length; + var yr0 = edit.yr0; + var yr1 = edit.yr1; + var ylen = ya1._length; + + var editX = xr0[0] !== xr1[0] || xr0[1] !== xr1[1]; + var editY = yr0[0] !== yr1[0] || yr0[1] !== yr1[1]; + var viewBox = []; + + if(editX) { + var dx0 = xr0[1] - xr0[0]; + var dx1 = xr1[1] - xr1[0]; + viewBox[0] = (xr0[0] * (1 - progress) + progress * xr1[0] - xr0[0]) / (xr0[1] - xr0[0]) * xlen; + viewBox[2] = xlen * ((1 - progress) + progress * dx1 / dx0); + xa1.range[0] = xr0[0] * (1 - progress) + progress * xr1[0]; + xa1.range[1] = xr0[1] * (1 - progress) + progress * xr1[1]; + } else { + viewBox[0] = 0; + viewBox[2] = xlen; + } + + if(editY) { + var dy0 = yr0[1] - yr0[0]; + var dy1 = yr1[1] - yr1[0]; + viewBox[1] = (yr0[1] * (1 - progress) + progress * yr1[1] - yr0[1]) / (yr0[0] - yr0[1]) * ylen; + viewBox[3] = ylen * ((1 - progress) + progress * dy1 / dy0); + ya1.range[0] = yr0[0] * (1 - progress) + progress * yr1[0]; + ya1.range[1] = yr0[1] * (1 - progress) + progress * yr1[1]; + } else { + viewBox[1] = 0; + viewBox[3] = ylen; + } + + ticksAndAnnotations(plotinfo.xaxis, plotinfo.yaxis); + + var xScaleFactor = editX ? xlen / viewBox[2] : 1; + var yScaleFactor = editY ? ylen / viewBox[3] : 1; + var clipDx = editX ? viewBox[0] : 0; + var clipDy = editY ? viewBox[1] : 0; + var fracDx = editX ? (viewBox[0] / viewBox[2] * xlen) : 0; + var fracDy = editY ? (viewBox[1] / viewBox[3] * ylen) : 0; + var plotDx = xa1._offset - fracDx; + var plotDy = ya1._offset - fracDy; + + plotinfo.clipRect + .call(Drawing.setTranslate, clipDx, clipDy) + .call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor); + + plotinfo.plot + .call(Drawing.setTranslate, plotDx, plotDy) + .call(Drawing.setScale, xScaleFactor, yScaleFactor); + + // apply an inverse scale to individual points to counteract + // the scale of the trace group. + Drawing.setPointGroupScale(plotinfo.zoomScalePts, 1 / xScaleFactor, 1 / yScaleFactor); + Drawing.setTextPointsScale(plotinfo.zoomScaleTxt, 1 / xScaleFactor, 1 / yScaleFactor); + } + + var onComplete; + if(makeOnCompleteCallback) { + // This module makes the choice whether or not it notifies Plotly.transition + // about completion: + onComplete = makeOnCompleteCallback(); + } + + function transitionComplete() { + var aobj = {}; + var k; + + for(k in edits) { + var edit = edits[k]; + aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr1.slice(); + aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr1.slice(); + } + + // Signal that this transition has completed: + onComplete && onComplete(); + + return Registry.call('relayout', gd, aobj).then(function() { + for(k in edits) { + unsetSubplotTransform(edits[k].plotinfo); + } + }); + } + + var t1, t2, raf; + var easeFn = d3.ease(transitionOpts.easing); + + gd._transitionData._interruptCallbacks.push(function() { + window.cancelAnimationFrame(raf); + raf = null; + return transitionComplete(); + }); + + function doFrame() { + t2 = Date.now(); + + var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration); + var progress = easeFn(tInterp); + + for(var k in edits) { + updateSubplot(edits[k], progress); + } + + if(t2 - t1 > transitionOpts.duration) { + transitionComplete(); + raf = window.cancelAnimationFrame(doFrame); + } else { + raf = window.requestAnimationFrame(doFrame); + } + } + + t1 = Date.now(); + raf = window.requestAnimationFrame(doFrame); + + return Promise.resolve(); +} + +module.exports = { + transitionAxes: transitionAxes, + transitionAxes2: transitionAxes2 +}; + +},{"../../components/drawing":595,"../../registry":827,"./axes":744,"./constants":750,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],768:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var autoType = _dereq_('./axis_autotype'); + +/* + * data: the plot data to use in choosing auto type + * name: axis object name (ie 'xaxis') if one should be stored + */ +module.exports = function handleTypeDefaults(containerIn, containerOut, coerce, options) { + var axType = coerce('type', (options.splomStash || {}).type); + + if(axType === '-') { + setAutoType(containerOut, options.data); + + if(containerOut.type === '-') { + containerOut.type = 'linear'; + } else { + // copy autoType back to input axis + // note that if this object didn't exist + // in the input layout, we have to put it in + // this happens in the main supplyDefaults function + containerIn.type = containerOut.type; + } + } +}; + +function setAutoType(ax, data) { + // new logic: let people specify any type they want, + // only autotype if type is '-' + if(ax.type !== '-') return; + + var id = ax._id; + var axLetter = id.charAt(0); + + // support 3d + if(id.indexOf('scene') !== -1) id = axLetter; + + var d0 = getFirstNonEmptyTrace(data, id, axLetter); + if(!d0) return; + + // first check for histograms, as the count direction + // should always default to a linear axis + if(d0.type === 'histogram' && + axLetter === {v: 'y', h: 'x'}[d0.orientation || 'v']) { + ax.type = 'linear'; + return; + } + + var calAttr = axLetter + 'calendar'; + var calendar = d0[calAttr]; + var i; + + // check all boxes on this x axis to see + // if they're dates, numbers, or categories + if(isBoxWithoutPositionCoords(d0, axLetter)) { + var posLetter = getBoxPosLetter(d0); + var boxPositions = []; + + for(i = 0; i < data.length; i++) { + var trace = data[i]; + if(!Registry.traceIs(trace, 'box-violin') || + (trace[axLetter + 'axis'] || axLetter) !== id) continue; + + if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]); + else if(trace.name !== undefined) boxPositions.push(trace.name); + else boxPositions.push('text'); + + if(trace[calAttr] !== calendar) calendar = undefined; + } + + ax.type = autoType(boxPositions, calendar); + } + else if(d0.type === 'splom') { + var dimensions = d0.dimensions; + var diag = d0._diag; + for(i = 0; i < dimensions.length; i++) { + var dim = dimensions[i]; + if(dim.visible && (diag[i][0] === id || diag[i][1] === id)) { + ax.type = autoType(dim.values, calendar); + break; + } + } + } + else { + ax.type = autoType(d0[axLetter] || [d0[axLetter + '0']], calendar); + } +} + +function getFirstNonEmptyTrace(data, id, axLetter) { + for(var i = 0; i < data.length; i++) { + var trace = data[i]; + + if(trace.type === 'splom' && + trace._length > 0 && + (trace['_' + axLetter + 'axes'] || {})[id] + ) { + return trace; + } + + if((trace[axLetter + 'axis'] || axLetter) === id) { + if(isBoxWithoutPositionCoords(trace, axLetter)) { + return trace; + } + else if((trace[axLetter] || []).length || trace[axLetter + '0']) { + return trace; + } + } + } +} + +function getBoxPosLetter(trace) { + return {v: 'x', h: 'y'}[trace.orientation || 'v']; +} + +function isBoxWithoutPositionCoords(trace, axLetter) { + var posLetter = getBoxPosLetter(trace), + isBox = Registry.traceIs(trace, 'box-violin'), + isCandlestick = Registry.traceIs(trace._fullInput || {}, 'candlestick'); + + return ( + isBox && + !isCandlestick && + axLetter === posLetter && + trace[posLetter] === undefined && + trace[posLetter + '0'] === undefined + ); +} + +},{"../../registry":827,"./axis_autotype":745}],769:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../registry'); +var Lib = _dereq_('../lib'); + +/* + * Create or update an observer. This function is designed to be + * idempotent so that it can be called over and over as the component + * updates, and will attach and detach listeners as needed. + * + * @param {optional object} container + * An object on which the observer is stored. This is the mechanism + * by which it is idempotent. If it already exists, another won't be + * added. Each time it's called, the value lookup table is updated. + * @param {array} commandList + * An array of commands, following either `buttons` of `updatemenus` + * or `steps` of `sliders`. + * @param {function} onchange + * A listener called when the value is changed. Receives data object + * with information about the new state. + */ +exports.manageCommandObserver = function(gd, container, commandList, onchange) { + var ret = {}; + var enabled = true; + + if(container && container._commandObserver) { + ret = container._commandObserver; + } + + if(!ret.cache) { + ret.cache = {}; + } + + // Either create or just recompute this: + ret.lookupTable = {}; + + var binding = exports.hasSimpleAPICommandBindings(gd, commandList, ret.lookupTable); + + if(container && container._commandObserver) { + if(!binding) { + // If container exists and there are no longer any bindings, + // remove existing: + if(container._commandObserver.remove) { + container._commandObserver.remove(); + container._commandObserver = null; + return ret; + } + } else { + // If container exists and there *are* bindings, then the lookup + // table should have been updated and check is already attached, + // so there's nothing to be done: + return ret; + + + } + } + + // Determine whether there's anything to do for this binding: + + if(binding) { + // Build the cache: + bindingValueHasChanged(gd, binding, ret.cache); + + ret.check = function check() { + if(!enabled) return; + + var update = bindingValueHasChanged(gd, binding, ret.cache); + + if(update.changed && onchange) { + // Disable checks for the duration of this command in order to avoid + // infinite loops: + if(ret.lookupTable[update.value] !== undefined) { + ret.disable(); + Promise.resolve(onchange({ + value: update.value, + type: binding.type, + prop: binding.prop, + traces: binding.traces, + index: ret.lookupTable[update.value] + })).then(ret.enable, ret.enable); + } + } + + return update.changed; + }; + + var checkEvents = [ + 'plotly_relayout', + 'plotly_redraw', + 'plotly_restyle', + 'plotly_update', + 'plotly_animatingframe', + 'plotly_afterplot' + ]; + + for(var i = 0; i < checkEvents.length; i++) { + gd._internalOn(checkEvents[i], ret.check); + } + + ret.remove = function() { + for(var i = 0; i < checkEvents.length; i++) { + gd._removeInternalListener(checkEvents[i], ret.check); + } + }; + } else { + // TODO: It'd be really neat to actually give a *reason* for this, but at least a warning + // is a start + Lib.log('Unable to automatically bind plot updates to API command'); + + ret.lookupTable = {}; + ret.remove = function() {}; + } + + ret.disable = function disable() { + enabled = false; + }; + + ret.enable = function enable() { + enabled = true; + }; + + if(container) { + container._commandObserver = ret; + } + + return ret; +}; + +/* + * This function checks to see if an array of objects containing + * method and args properties is compatible with automatic two-way + * binding. The criteria right now are that + * + * 1. multiple traces may be affected + * 2. only one property may be affected + * 3. the same property must be affected by all commands + */ +exports.hasSimpleAPICommandBindings = function(gd, commandList, bindingsByValue) { + var i; + var n = commandList.length; + + var refBinding; + + for(i = 0; i < n; i++) { + var binding; + var command = commandList[i]; + var method = command.method; + var args = command.args; + + if(!Array.isArray(args)) args = []; + + // If any command has no method, refuse to bind: + if(!method) { + return false; + } + var bindings = exports.computeAPICommandBindings(gd, method, args); + + // Right now, handle one and *only* one property being set: + if(bindings.length !== 1) { + return false; + } + + if(!refBinding) { + refBinding = bindings[0]; + if(Array.isArray(refBinding.traces)) { + refBinding.traces.sort(); + } + } else { + binding = bindings[0]; + if(binding.type !== refBinding.type) { + return false; + } + if(binding.prop !== refBinding.prop) { + return false; + } + if(Array.isArray(refBinding.traces)) { + if(Array.isArray(binding.traces)) { + binding.traces.sort(); + for(var j = 0; j < refBinding.traces.length; j++) { + if(refBinding.traces[j] !== binding.traces[j]) { + return false; + } + } + } else { + return false; + } + } else { + if(binding.prop !== refBinding.prop) { + return false; + } + } + } + + binding = bindings[0]; + var value = binding.value; + if(Array.isArray(value)) { + if(value.length === 1) { + value = value[0]; + } else { + return false; + } + } + if(bindingsByValue) { + bindingsByValue[value] = i; + } + } + + return refBinding; +}; + +function bindingValueHasChanged(gd, binding, cache) { + var container, value, obj; + var changed = false; + + if(binding.type === 'data') { + // If it's data, we need to get a trace. Based on the limited scope + // of what we cover, we can just take the first trace from the list, + // or otherwise just the first trace: + container = gd._fullData[binding.traces !== null ? binding.traces[0] : 0]; + } else if(binding.type === 'layout') { + container = gd._fullLayout; + } else { + return false; + } + + value = Lib.nestedProperty(container, binding.prop).get(); + + obj = cache[binding.type] = cache[binding.type] || {}; + + if(obj.hasOwnProperty(binding.prop)) { + if(obj[binding.prop] !== value) { + changed = true; + } + } + + obj[binding.prop] = value; + + return { + changed: changed, + value: value + }; +} + +/* + * Execute an API command. There's really not much to this; it just provides + * a common hook so that implementations don't need to be synchronized across + * multiple components with the ability to invoke API commands. + * + * @param {string} method + * The name of the plotly command to execute. Must be one of 'animate', + * 'restyle', 'relayout', 'update'. + * @param {array} args + * A list of arguments passed to the API command + */ +exports.executeAPICommand = function(gd, method, args) { + if(method === 'skip') return Promise.resolve(); + + var _method = Registry.apiMethodRegistry[method]; + var allArgs = [gd]; + if(!Array.isArray(args)) args = []; + + for(var i = 0; i < args.length; i++) { + allArgs.push(args[i]); + } + + return _method.apply(null, allArgs).catch(function(err) { + Lib.warn('API call to Plotly.' + method + ' rejected.', err); + return Promise.reject(err); + }); +}; + +exports.computeAPICommandBindings = function(gd, method, args) { + var bindings; + + if(!Array.isArray(args)) args = []; + + switch(method) { + case 'restyle': + bindings = computeDataBindings(gd, args); + break; + case 'relayout': + bindings = computeLayoutBindings(gd, args); + break; + case 'update': + bindings = computeDataBindings(gd, [args[0], args[2]]) + .concat(computeLayoutBindings(gd, [args[1]])); + break; + case 'animate': + bindings = computeAnimateBindings(gd, args); + break; + default: + // This is the case where intelligent logic about what affects + // this command is not implemented. It causes no ill effects. + // For example, addFrames simply won't bind to a control component. + bindings = []; + } + return bindings; +}; + +function computeAnimateBindings(gd, args) { + // We'll assume that the only relevant modification an animation + // makes that's meaningfully tracked is the frame: + if(Array.isArray(args[0]) && args[0].length === 1 && ['string', 'number'].indexOf(typeof args[0][0]) !== -1) { + return [{type: 'layout', prop: '_currentFrame', value: args[0][0].toString()}]; + } else { + return []; + } +} + +function computeLayoutBindings(gd, args) { + var bindings = []; + + var astr = args[0]; + var aobj = {}; + if(typeof astr === 'string') { + aobj[astr] = args[1]; + } else if(Lib.isPlainObject(astr)) { + aobj = astr; + } else { + return bindings; + } + + crawl(aobj, function(path, attrName, attr) { + bindings.push({type: 'layout', prop: path, value: attr}); + }, '', 0); + + return bindings; +} + +function computeDataBindings(gd, args) { + var traces, astr, val, aobj; + var bindings = []; + + // Logic copied from Plotly.restyle: + astr = args[0]; + val = args[1]; + traces = args[2]; + aobj = {}; + if(typeof astr === 'string') { + aobj[astr] = val; + } else if(Lib.isPlainObject(astr)) { + // the 3-arg form + aobj = astr; + + if(traces === undefined) { + traces = val; + } + } else { + return bindings; + } + + if(traces === undefined) { + // Explicitly assign this to null instead of undefined: + traces = null; + } + + crawl(aobj, function(path, attrName, attr) { + var thisTraces; + if(Array.isArray(attr)) { + var nAttr = Math.min(attr.length, gd.data.length); + if(traces) { + nAttr = Math.min(nAttr, traces.length); + } + thisTraces = []; + for(var j = 0; j < nAttr; j++) { + thisTraces[j] = traces ? traces[j] : j; + } + } else { + thisTraces = traces ? traces.slice(0) : null; + } + + // Convert [7] to just 7 when traces is null: + if(thisTraces === null) { + if(Array.isArray(attr)) { + attr = attr[0]; + } + } else if(Array.isArray(thisTraces)) { + if(!Array.isArray(attr)) { + var tmp = attr; + attr = []; + for(var i = 0; i < thisTraces.length; i++) { + attr[i] = tmp; + } + } + attr.length = Math.min(thisTraces.length, attr.length); + } + + bindings.push({ + type: 'data', + prop: path, + traces: thisTraces, + value: attr + }); + }, '', 0); + + return bindings; +} + +function crawl(attrs, callback, path, depth) { + Object.keys(attrs).forEach(function(attrName) { + var attr = attrs[attrName]; + + if(attrName[0] === '_') return; + + var thisPath = path + (depth > 0 ? '.' : '') + attrName; + + if(Lib.isPlainObject(attr)) { + crawl(attr, callback, thisPath, depth + 1); + } else { + // Only execute the callback on leaf nodes: + callback(thisPath, attrName, attr); + } + }); +} + +},{"../lib":696,"../registry":827}],770:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var extendFlat = _dereq_('../lib/extend').extendFlat; + +/** + * Make a xy domain attribute group + * + * @param {object} opts + * @param {string} + * opts.name: name to be inserted in the default description + * @param {boolean} + * opts.trace: set to true for trace containers + * @param {string} + * opts.editType: editType for all pieces + * @param {boolean} + * opts.noGridCell: set to true to omit `row` and `column` + * + * @param {object} extra + * @param {string} + * extra.description: extra description. N.B we use + * a separate extra container to make it compatible with + * the compress_attributes transform. + * + * @return {object} attributes object containing {x,y} as specified + */ +exports.attributes = function(opts, extra) { + opts = opts || {}; + extra = extra || {}; + + var base = { + valType: 'info_array', + + editType: opts.editType, + items: [ + {valType: 'number', min: 0, max: 1, editType: opts.editType}, + {valType: 'number', min: 0, max: 1, editType: opts.editType} + ], + dflt: [0, 1] + }; + + var namePart = opts.name ? opts.name + ' ' : ''; + var contPart = opts.trace ? 'trace ' : 'subplot '; + var descPart = extra.description ? ' ' + extra.description : ''; + + var out = { + x: extendFlat({}, base, { + + }), + y: extendFlat({}, base, { + + }), + editType: opts.editType + }; + + if(!opts.noGridCell) { + out.row = { + valType: 'integer', + min: 0, + dflt: 0, + + editType: opts.editType, + + }; + out.column = { + valType: 'integer', + min: 0, + dflt: 0, + + editType: opts.editType, + + }; + } + + return out; +}; + +exports.defaults = function(containerOut, layout, coerce, dfltDomains) { + var dfltX = (dfltDomains && dfltDomains.x) || [0, 1]; + var dfltY = (dfltDomains && dfltDomains.y) || [0, 1]; + + var grid = layout.grid; + if(grid) { + var column = coerce('domain.column'); + if(column !== undefined) { + if(column < grid.columns) dfltX = grid._domains.x[column]; + else delete containerOut.domain.column; + } + + var row = coerce('domain.row'); + if(row !== undefined) { + if(row < grid.rows) dfltY = grid._domains.y[row]; + else delete containerOut.domain.row; + } + } + + coerce('domain.x', dfltX); + coerce('domain.y', dfltY); +}; + +},{"../lib/extend":685}],771:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * make a font attribute group + * + * @param {object} opts + * @param {string} + * opts.description: where & how this font is used + * @param {optional bool} arrayOk: + * should each part (family, size, color) be arrayOk? default false. + * @param {string} editType: + * the editType for all pieces of this font + * @param {optional string} colorEditType: + * a separate editType just for color + * + * @return {object} attributes object containing {family, size, color} as specified + */ +module.exports = function(opts) { + var editType = opts.editType; + var colorEditType = opts.colorEditType; + if(colorEditType === undefined) colorEditType = editType; + var attrs = { + family: { + valType: 'string', + + noBlank: true, + strict: true, + editType: editType, + + }, + size: { + valType: 'number', + + min: 1, + editType: editType + }, + color: { + valType: 'color', + + editType: colorEditType + }, + editType: editType, + // blank strings so compress_attributes can remove + // TODO - that's uber hacky... better solution? + + }; + + if(opts.arrayOk) { + attrs.family.arrayOk = true; + attrs.size.arrayOk = true; + attrs.color.arrayOk = true; + } + + return attrs; +}; + +},{}],772:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + _isLinkedToArray: 'frames_entry', + + group: { + valType: 'string', + + + }, + name: { + valType: 'string', + + + }, + traces: { + valType: 'any', + + + }, + baseframe: { + valType: 'string', + + + }, + data: { + valType: 'any', + + + }, + layout: { + valType: 'any', + + + } +}; + +},{}],773:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// projection names to d3 function name +exports.projNames = { + // d3.geo.projection + 'equirectangular': 'equirectangular', + 'mercator': 'mercator', + 'orthographic': 'orthographic', + 'natural earth': 'naturalEarth', + 'kavrayskiy7': 'kavrayskiy7', + 'miller': 'miller', + 'robinson': 'robinson', + 'eckert4': 'eckert4', + 'azimuthal equal area': 'azimuthalEqualArea', + 'azimuthal equidistant': 'azimuthalEquidistant', + 'conic equal area': 'conicEqualArea', + 'conic conformal': 'conicConformal', + 'conic equidistant': 'conicEquidistant', + 'gnomonic': 'gnomonic', + 'stereographic': 'stereographic', + 'mollweide': 'mollweide', + 'hammer': 'hammer', + 'transverse mercator': 'transverseMercator', + 'albers usa': 'albersUsa', + 'winkel tripel': 'winkel3', + 'aitoff': 'aitoff', + 'sinusoidal': 'sinusoidal' +}; + +// name of the axes +exports.axesNames = ['lonaxis', 'lataxis']; + +// max longitudinal angular span (EXPERIMENTAL) +exports.lonaxisSpan = { + 'orthographic': 180, + 'azimuthal equal area': 360, + 'azimuthal equidistant': 360, + 'conic conformal': 180, + 'gnomonic': 160, + 'stereographic': 180, + 'transverse mercator': 180, + '*': 360 +}; + +// max latitudinal angular span (EXPERIMENTAL) +exports.lataxisSpan = { + 'conic conformal': 150, + 'stereographic': 179.5, + '*': 180 +}; + +// defaults for each scope +exports.scopeDefaults = { + world: { + lonaxisRange: [-180, 180], + lataxisRange: [-90, 90], + projType: 'equirectangular', + projRotate: [0, 0, 0] + }, + usa: { + lonaxisRange: [-180, -50], + lataxisRange: [15, 80], + projType: 'albers usa' + }, + europe: { + lonaxisRange: [-30, 60], + lataxisRange: [30, 85], + projType: 'conic conformal', + projRotate: [15, 0, 0], + projParallels: [0, 60] + }, + asia: { + lonaxisRange: [22, 160], + lataxisRange: [-15, 55], + projType: 'mercator', + projRotate: [0, 0, 0] + }, + africa: { + lonaxisRange: [-30, 60], + lataxisRange: [-40, 40], + projType: 'mercator', + projRotate: [0, 0, 0] + }, + 'north america': { + lonaxisRange: [-180, -45], + lataxisRange: [5, 85], + projType: 'conic conformal', + projRotate: [-100, 0, 0], + projParallels: [29.5, 45.5] + }, + 'south america': { + lonaxisRange: [-100, -30], + lataxisRange: [-60, 15], + projType: 'mercator', + projRotate: [0, 0, 0] + } +}; + +// angular pad to avoid rounding error around clip angles +exports.clipPad = 1e-3; + +// map projection precision +exports.precision = 0.1; + +// default land and water fill colors +exports.landColor = '#F0DC82'; +exports.waterColor = '#3399FF'; + +// locationmode to layer name +exports.locationmodeToLayer = { + 'ISO-3': 'countries', + 'USA-states': 'subunits', + 'country names': 'countries' +}; + +// SVG element for a sphere (use to frame maps) +exports.sphereSVG = {type: 'Sphere'}; + +// N.B. base layer names must be the same as in the topojson files + +// base layer with a fill color +exports.fillLayers = { + ocean: 1, + land: 1, + lakes: 1 +}; + +// base layer with a only a line color +exports.lineLayers = { + subunits: 1, + countries: 1, + coastlines: 1, + rivers: 1, + frame: 1 +}; + +exports.layers = [ + 'bg', + 'ocean', 'land', 'lakes', + 'subunits', 'countries', 'coastlines', 'rivers', + 'lataxis', 'lonaxis', 'frame', + 'backplot', + 'frontplot' +]; + +exports.layersForChoropleth = [ + 'bg', + 'ocean', 'land', + 'subunits', 'countries', 'coastlines', + 'lataxis', 'lonaxis', 'frame', + 'backplot', + 'rivers', 'lakes', + 'frontplot' +]; + +exports.layerNameToAdjective = { + ocean: 'ocean', + land: 'land', + lakes: 'lake', + subunits: 'subunit', + countries: 'country', + coastlines: 'coastline', + rivers: 'river', + frame: 'frame' +}; + +},{}],774:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* global PlotlyGeoAssets:false */ + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Fx = _dereq_('../../components/fx'); +var Plots = _dereq_('../plots'); +var Axes = _dereq_('../cartesian/axes'); +var dragElement = _dereq_('../../components/dragelement'); +var prepSelect = _dereq_('../cartesian/select').prepSelect; +var selectOnClick = _dereq_('../cartesian/select').selectOnClick; + +var createGeoZoom = _dereq_('./zoom'); +var constants = _dereq_('./constants'); + +var topojsonUtils = _dereq_('../../lib/topojson_utils'); +var topojsonFeature = _dereq_('topojson-client').feature; + +_dereq_('./projections')(d3); + +function Geo(opts) { + this.id = opts.id; + this.graphDiv = opts.graphDiv; + this.container = opts.container; + this.topojsonURL = opts.topojsonURL; + this.isStatic = opts.staticPlot; + + this.topojsonName = null; + this.topojson = null; + + this.projection = null; + this.viewInitial = null; + this.fitScale = null; + this.bounds = null; + this.midPt = null; + + this.hasChoropleth = false; + this.traceHash = {}; + + this.layers = {}; + this.basePaths = {}; + this.dataPaths = {}; + this.dataPoints = {}; + + this.clipDef = null; + this.clipRect = null; + this.bgRect = null; + + this.makeFramework(); +} + +var proto = Geo.prototype; + +module.exports = function createGeo(opts) { + return new Geo(opts); +}; + +proto.plot = function(geoCalcData, fullLayout, promises) { + var _this = this; + var geoLayout = fullLayout[this.id]; + var topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout); + + if(_this.topojson === null || topojsonNameNew !== _this.topojsonName) { + _this.topojsonName = topojsonNameNew; + + if(PlotlyGeoAssets.topojson[_this.topojsonName] === undefined) { + promises.push(_this.fetchTopojson().then(function(topojson) { + PlotlyGeoAssets.topojson[_this.topojsonName] = topojson; + _this.topojson = topojson; + _this.update(geoCalcData, fullLayout); + })); + } else { + _this.topojson = PlotlyGeoAssets.topojson[_this.topojsonName]; + _this.update(geoCalcData, fullLayout); + } + } else { + _this.update(geoCalcData, fullLayout); + } +}; + +proto.fetchTopojson = function() { + var topojsonPath = topojsonUtils.getTopojsonPath( + this.topojsonURL, + this.topojsonName + ); + return new Promise(function(resolve, reject) { + d3.json(topojsonPath, function(err, topojson) { + if(err) { + if(err.status === 404) { + return reject(new Error([ + 'plotly.js could not find topojson file at', + topojsonPath, '.', + 'Make sure the *topojsonURL* plot config option', + 'is set properly.' + ].join(' '))); + } else { + return reject(new Error([ + 'unexpected error while fetching topojson file at', + topojsonPath + ].join(' '))); + } + } + resolve(topojson); + }); + }); +}; + +proto.update = function(geoCalcData, fullLayout) { + var geoLayout = fullLayout[this.id]; + + var hasInvalidBounds = this.updateProjection(fullLayout, geoLayout); + if(hasInvalidBounds) return; + + // important: maps with choropleth traces have a different layer order + this.hasChoropleth = false; + for(var i = 0; i < geoCalcData.length; i++) { + if(geoCalcData[i][0].trace.type === 'choropleth') { + this.hasChoropleth = true; + break; + } + } + + if(!this.viewInitial) { + this.saveViewInitial(geoLayout); + } + + this.updateBaseLayers(fullLayout, geoLayout); + this.updateDims(fullLayout, geoLayout); + this.updateFx(fullLayout, geoLayout); + + Plots.generalUpdatePerTraceModule(this.graphDiv, this, geoCalcData, geoLayout); + + var scatterLayer = this.layers.frontplot.select('.scatterlayer'); + this.dataPoints.point = scatterLayer.selectAll('.point'); + this.dataPoints.text = scatterLayer.selectAll('text'); + this.dataPaths.line = scatterLayer.selectAll('.js-line'); + + var choroplethLayer = this.layers.backplot.select('.choroplethlayer'); + this.dataPaths.choropleth = choroplethLayer.selectAll('path'); + + this.render(); +}; + +proto.updateProjection = function(fullLayout, geoLayout) { + var gs = fullLayout._size; + var domain = geoLayout.domain; + var projLayout = geoLayout.projection; + var rotation = projLayout.rotation || {}; + var center = geoLayout.center || {}; + + var projection = this.projection = getProjection(geoLayout); + + // set 'pre-fit' projection + projection + .center([center.lon - rotation.lon, center.lat - rotation.lat]) + .rotate([-rotation.lon, -rotation.lat, rotation.roll]) + .parallels(projLayout.parallels); + + // setup subplot extent [[x0,y0], [x1,y1]] + var extent = [[ + gs.l + gs.w * domain.x[0], + gs.t + gs.h * (1 - domain.y[1]) + ], [ + gs.l + gs.w * domain.x[1], + gs.t + gs.h * (1 - domain.y[0]) + ]]; + + var lonaxis = geoLayout.lonaxis; + var lataxis = geoLayout.lataxis; + var rangeBox = makeRangeBox(lonaxis.range, lataxis.range); + + // fit projection 'scale' and 'translate' to set lon/lat ranges + projection.fitExtent(extent, rangeBox); + + var b = this.bounds = projection.getBounds(rangeBox); + var s = this.fitScale = projection.scale(); + var t = projection.translate(); + + if( + !isFinite(b[0][0]) || !isFinite(b[0][1]) || + !isFinite(b[1][0]) || !isFinite(b[1][1]) || + isNaN(t[0]) || isNaN(t[0]) + ) { + var gd = this.graphDiv; + var attrToUnset = ['projection.rotation', 'center', 'lonaxis.range', 'lataxis.range']; + var msg = 'Invalid geo settings, relayout\'ing to default view.'; + var updateObj = {}; + + // clear all attribute that could cause invalid bounds, + // clear viewInitial to update reset-view behavior + + for(var i = 0; i < attrToUnset.length; i++) { + updateObj[this.id + '.' + attrToUnset[i]] = null; + } + + this.viewInitial = null; + + Lib.warn(msg); + gd._promises.push(Registry.call('relayout', gd, updateObj)); + return msg; + } + + // px coordinates of view mid-point, + // useful to update `geo.center` after interactions + var midPt = this.midPt = [ + (b[0][0] + b[1][0]) / 2, + (b[0][1] + b[1][1]) / 2 + ]; + + // adjust projection to user setting + projection + .scale(projLayout.scale * s) + .translate([t[0] + (midPt[0] - t[0]), t[1] + (midPt[1] - t[1])]) + .clipExtent(b); + + // the 'albers usa' projection does not expose a 'center' method + // so here's this hack to make it respond to 'geoLayout.center' + if(geoLayout._isAlbersUsa) { + var centerPx = projection([center.lon, center.lat]); + var tt = projection.translate(); + + projection.translate([ + tt[0] - (centerPx[0] - tt[0]), + tt[1] - (centerPx[1] - tt[1]) + ]); + } +}; + +proto.updateBaseLayers = function(fullLayout, geoLayout) { + var _this = this; + var topojson = _this.topojson; + var layers = _this.layers; + var basePaths = _this.basePaths; + + function isAxisLayer(d) { + return (d === 'lonaxis' || d === 'lataxis'); + } + + function isLineLayer(d) { + return Boolean(constants.lineLayers[d]); + } + + function isFillLayer(d) { + return Boolean(constants.fillLayers[d]); + } + + var allLayers = this.hasChoropleth ? + constants.layersForChoropleth : + constants.layers; + + var layerData = allLayers.filter(function(d) { + return (isLineLayer(d) || isFillLayer(d)) ? geoLayout['show' + d] : + isAxisLayer(d) ? geoLayout[d].showgrid : + true; + }); + + var join = _this.framework.selectAll('.layer') + .data(layerData, String); + + join.exit().each(function(d) { + delete layers[d]; + delete basePaths[d]; + d3.select(this).remove(); + }); + + join.enter().append('g') + .attr('class', function(d) { return 'layer ' + d; }) + .each(function(d) { + var layer = layers[d] = d3.select(this); + + if(d === 'bg') { + _this.bgRect = layer.append('rect') + .style('pointer-events', 'all'); + } else if(isAxisLayer(d)) { + basePaths[d] = layer.append('path') + .style('fill', 'none'); + } else if(d === 'backplot') { + layer.append('g') + .classed('choroplethlayer', true); + } else if(d === 'frontplot') { + layer.append('g') + .classed('scatterlayer', true); + } else if(isLineLayer(d)) { + basePaths[d] = layer.append('path') + .style('fill', 'none') + .style('stroke-miterlimit', 2); + } else if(isFillLayer(d)) { + basePaths[d] = layer.append('path') + .style('stroke', 'none'); + } + }); + + join.order(); + + join.each(function(d) { + var path = basePaths[d]; + var adj = constants.layerNameToAdjective[d]; + + if(d === 'frame') { + path.datum(constants.sphereSVG); + } else if(isLineLayer(d) || isFillLayer(d)) { + path.datum(topojsonFeature(topojson, topojson.objects[d])); + } else if(isAxisLayer(d)) { + path.datum(makeGraticule(d, geoLayout)) + .call(Color.stroke, geoLayout[d].gridcolor) + .call(Drawing.dashLine, '', geoLayout[d].gridwidth); + } + + if(isLineLayer(d)) { + path.call(Color.stroke, geoLayout[adj + 'color']) + .call(Drawing.dashLine, '', geoLayout[adj + 'width']); + } else if(isFillLayer(d)) { + path.call(Color.fill, geoLayout[adj + 'color']); + } + }); +}; + +proto.updateDims = function(fullLayout, geoLayout) { + var b = this.bounds; + var hFrameWidth = (geoLayout.framewidth || 0) / 2; + + var l = b[0][0] - hFrameWidth; + var t = b[0][1] - hFrameWidth; + var w = b[1][0] - l + hFrameWidth; + var h = b[1][1] - t + hFrameWidth; + + Drawing.setRect(this.clipRect, l, t, w, h); + + this.bgRect + .call(Drawing.setRect, l, t, w, h) + .call(Color.fill, geoLayout.bgcolor); + + this.xaxis._offset = l; + this.xaxis._length = w; + + this.yaxis._offset = t; + this.yaxis._length = h; +}; + +proto.updateFx = function(fullLayout, geoLayout) { + var _this = this; + var gd = _this.graphDiv; + var bgRect = _this.bgRect; + var dragMode = fullLayout.dragmode; + var clickMode = fullLayout.clickmode; + + if(_this.isStatic) return; + + function zoomReset() { + var viewInitial = _this.viewInitial; + var updateObj = {}; + + for(var k in viewInitial) { + updateObj[_this.id + '.' + k] = viewInitial[k]; + } + + Registry.call('relayout', gd, updateObj); + gd.emit('plotly_doubleclick', null); + } + + function invert(lonlat) { + return _this.projection.invert([ + lonlat[0] + _this.xaxis._offset, + lonlat[1] + _this.yaxis._offset + ]); + } + + var fillRangeItems; + + if(dragMode === 'select') { + fillRangeItems = function(eventData, poly) { + var ranges = eventData.range = {}; + ranges[_this.id] = [ + invert([poly.xmin, poly.ymin]), + invert([poly.xmax, poly.ymax]) + ]; + }; + } else if(dragMode === 'lasso') { + fillRangeItems = function(eventData, poly, pts) { + var dataPts = eventData.lassoPoints = {}; + dataPts[_this.id] = pts.filtered.map(invert); + }; + } + + // Note: dragOptions is needed to be declared for all dragmodes because + // it's the object that holds persistent selection state. + var dragOptions = { + element: _this.bgRect.node(), + gd: gd, + plotinfo: { + id: _this.id, + xaxis: _this.xaxis, + yaxis: _this.yaxis, + fillRangeItems: fillRangeItems + }, + xaxes: [_this.xaxis], + yaxes: [_this.yaxis], + subplot: _this.id, + clickFn: function(numClicks) { + if(numClicks === 2) { + fullLayout._zoomlayer.selectAll('.select-outline').remove(); + } + } + }; + + if(dragMode === 'pan') { + bgRect.node().onmousedown = null; + bgRect.call(createGeoZoom(_this, geoLayout)); + bgRect.on('dblclick.zoom', zoomReset); + } + else if(dragMode === 'select' || dragMode === 'lasso') { + bgRect.on('.zoom', null); + + dragOptions.prepFn = function(e, startX, startY) { + prepSelect(e, startX, startY, dragOptions, dragMode); + }; + + dragElement.init(dragOptions); + } + + bgRect.on('mousemove', function() { + var lonlat = _this.projection.invert(d3.mouse(this)); + + if(!lonlat || isNaN(lonlat[0]) || isNaN(lonlat[1])) { + return dragElement.unhover(gd, d3.event); + } + + _this.xaxis.p2c = function() { return lonlat[0]; }; + _this.yaxis.p2c = function() { return lonlat[1]; }; + + Fx.hover(gd, d3.event, _this.id); + }); + + bgRect.on('mouseout', function() { + if(gd._dragging) return; + dragElement.unhover(gd, d3.event); + }); + + bgRect.on('click', function() { + // For select and lasso the dragElement is handling clicks + if(dragMode !== 'select' && dragMode !== 'lasso') { + if(clickMode.indexOf('select') > -1) { + selectOnClick(d3.event, gd, [_this.xaxis], [_this.yaxis], + _this.id, dragOptions); + } + + if(clickMode.indexOf('event') > -1) { + // TODO: like pie and mapbox, this doesn't support right-click + // actually this one is worse, as right-click starts a pan, or leaves + // select in a weird state. + // Also, only tangentially related, we should cancel hover during pan + Fx.click(gd, d3.event); + } + } + }); +}; + +proto.makeFramework = function() { + var _this = this; + var fullLayout = _this.graphDiv._fullLayout; + var clipId = 'clip' + fullLayout._uid + _this.id; + + _this.clipDef = fullLayout._clips.append('clipPath') + .attr('id', clipId); + + _this.clipRect = _this.clipDef.append('rect'); + + _this.framework = d3.select(_this.container).append('g') + .attr('class', 'geo ' + _this.id) + .call(Drawing.setClipUrl, clipId); + + // sane lonlat to px + _this.project = function(v) { + var px = _this.projection(v); + return px ? + [px[0] - _this.xaxis._offset, px[1] - _this.yaxis._offset] : + [null, null]; + }; + + _this.xaxis = { + _id: 'x', + c2p: function(v) { return _this.project(v)[0]; } + }; + + _this.yaxis = { + _id: 'y', + c2p: function(v) { return _this.project(v)[1]; } + }; + + // mock axis for hover formatting + _this.mockAxis = { + type: 'linear', + showexponent: 'all', + exponentformat: 'B' + }; + Axes.setConvert(_this.mockAxis, fullLayout); +}; + +proto.saveViewInitial = function(geoLayout) { + var center = geoLayout.center || {}; + var projLayout = geoLayout.projection; + var rotation = projLayout.rotation || {}; + + if(geoLayout._isScoped) { + this.viewInitial = { + 'center.lon': center.lon, + 'center.lat': center.lat, + 'projection.scale': projLayout.scale + }; + } else if(geoLayout._isClipped) { + this.viewInitial = { + 'projection.scale': projLayout.scale, + 'projection.rotation.lon': rotation.lon, + 'projection.rotation.lat': rotation.lat + }; + } else { + this.viewInitial = { + 'center.lon': center.lon, + 'center.lat': center.lat, + 'projection.scale': projLayout.scale, + 'projection.rotation.lon': rotation.lon + }; + } +}; + +// [hot code path] (re)draw all paths which depend on the projection +proto.render = function() { + var projection = this.projection; + var pathFn = projection.getPath(); + var k; + + function translatePoints(d) { + var lonlatPx = projection(d.lonlat); + return lonlatPx ? + 'translate(' + lonlatPx[0] + ',' + lonlatPx[1] + ')' : + null; + } + + function hideShowPoints(d) { + return projection.isLonLatOverEdges(d.lonlat) ? 'none' : null; + } + + for(k in this.basePaths) { + this.basePaths[k].attr('d', pathFn); + } + + for(k in this.dataPaths) { + this.dataPaths[k].attr('d', function(d) { return pathFn(d.geojson); }); + } + + for(k in this.dataPoints) { + this.dataPoints[k] + .attr('display', hideShowPoints) + .attr('transform', translatePoints); + } +}; + +// Helper that wraps d3.geo[/* projection name /*]() which: +// +// - adds 'fitExtent' (available in d3 v4) +// - adds 'getPath', 'getBounds' convenience methods +// - scopes logic related to 'clipAngle' +// - adds 'isLonLatOverEdges' method +// - sets projection precision +// - sets methods that aren't always defined depending +// on the projection type to a dummy 'd3-esque' function, +// +// This wrapper alleviates subsequent code of (many) annoying if-statements. +function getProjection(geoLayout) { + var projLayout = geoLayout.projection; + var projType = projLayout.type; + + var projection = d3.geo[constants.projNames[projType]](); + + var clipAngle = geoLayout._isClipped ? + constants.lonaxisSpan[projType] / 2 : + null; + + var methods = ['center', 'rotate', 'parallels', 'clipExtent']; + var dummyFn = function(_) { return _ ? projection : []; }; + + for(var i = 0; i < methods.length; i++) { + var m = methods[i]; + if(typeof projection[m] !== 'function') { + projection[m] = dummyFn; + } + } + + projection.isLonLatOverEdges = function(lonlat) { + if(projection(lonlat) === null) { + return true; + } + + if(clipAngle) { + var r = projection.rotate(); + var angle = d3.geo.distance(lonlat, [-r[0], -r[1]]); + var maxAngle = clipAngle * Math.PI / 180; + return angle > maxAngle; + } else { + return false; + } + }; + + projection.getPath = function() { + return d3.geo.path().projection(projection); + }; + + projection.getBounds = function(object) { + return projection.getPath().bounds(object); + }; + + // adapted from d3 v4: + // https://github.com/d3/d3-geo/blob/master/src/projection/fit.js + projection.fitExtent = function(extent, object) { + var w = extent[1][0] - extent[0][0]; + var h = extent[1][1] - extent[0][1]; + var clip = projection.clipExtent && projection.clipExtent(); + + projection + .scale(150) + .translate([0, 0]); + + if(clip) projection.clipExtent(null); + + var b = projection.getBounds(object); + var k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])); + var x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2; + var y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + + if(clip) projection.clipExtent(clip); + + return projection + .scale(k * 150) + .translate([x, y]); + }; + + projection.precision(constants.precision); + + if(clipAngle) { + projection.clipAngle(clipAngle - constants.clipPad); + } + + return projection; +} + +function makeGraticule(axisName, geoLayout) { + var axisLayout = geoLayout[axisName]; + var dtick = axisLayout.dtick; + var scopeDefaults = constants.scopeDefaults[geoLayout.scope]; + var lonaxisRange = scopeDefaults.lonaxisRange; + var lataxisRange = scopeDefaults.lataxisRange; + var step = axisName === 'lonaxis' ? [dtick] : [0, dtick]; + + return d3.geo.graticule() + .extent([ + [lonaxisRange[0], lataxisRange[0]], + [lonaxisRange[1], lataxisRange[1]] + ]) + .step(step); +} + +// Returns polygon GeoJSON corresponding to lon/lat range box +// with well-defined direction +// +// Note that clipPad padding is added around range to avoid aliasing. +function makeRangeBox(lon, lat) { + var clipPad = constants.clipPad; + var lon0 = lon[0] + clipPad; + var lon1 = lon[1] - clipPad; + var lat0 = lat[0] + clipPad; + var lat1 = lat[1] - clipPad; + + // to cross antimeridian w/o ambiguity + if(lon0 > 0 && lon1 < 0) lon1 += 360; + + var dlon4 = (lon1 - lon0) / 4; + + return { + type: 'Polygon', + coordinates: [[ + [lon0, lat0], + [lon0, lat1], + [lon0 + dlon4, lat1], + [lon0 + 2 * dlon4, lat1], + [lon0 + 3 * dlon4, lat1], + [lon1, lat1], + [lon1, lat0], + [lon1 - dlon4, lat0], + [lon1 - 2 * dlon4, lat0], + [lon1 - 3 * dlon4, lat0], + [lon0, lat0] + ]] + }; +} + +},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/topojson_utils":723,"../../registry":827,"../cartesian/axes":744,"../cartesian/select":762,"../plots":808,"./constants":773,"./projections":779,"./zoom":780,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"topojson-client":517}],775:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createGeo = _dereq_('./geo'); +var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; +var counterRegex = _dereq_('../../lib').counterRegex; + +var GEO = 'geo'; + +exports.name = GEO; + +exports.attr = GEO; + +exports.idRoot = GEO; + +exports.idRegex = exports.attrRegex = counterRegex(GEO); + +exports.attributes = _dereq_('./layout/attributes'); + +exports.layoutAttributes = _dereq_('./layout/layout_attributes'); + +exports.supplyLayoutDefaults = _dereq_('./layout/defaults'); + +exports.plot = function plotGeo(gd) { + var fullLayout = gd._fullLayout; + var calcData = gd.calcdata; + var geoIds = fullLayout._subplots[GEO]; + + /** + * If 'plotly-geo-assets.js' is not included, + * initialize object to keep reference to every loaded topojson + */ + if(window.PlotlyGeoAssets === undefined) { + window.PlotlyGeoAssets = {topojson: {}}; + } + + for(var i = 0; i < geoIds.length; i++) { + var geoId = geoIds[i]; + var geoCalcData = getSubplotCalcData(calcData, GEO, geoId); + var geoLayout = fullLayout[geoId]; + var geo = geoLayout._subplot; + + if(!geo) { + geo = createGeo({ + id: geoId, + graphDiv: gd, + container: fullLayout._geolayer.node(), + topojsonURL: gd._context.topojsonURL, + staticPlot: gd._context.staticPlot + }); + + fullLayout[geoId]._subplot = geo; + } + + geo.plot(geoCalcData, fullLayout, gd._promises); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldGeoKeys = oldFullLayout._subplots[GEO] || []; + + for(var i = 0; i < oldGeoKeys.length; i++) { + var oldGeoKey = oldGeoKeys[i]; + var oldGeo = oldFullLayout[oldGeoKey]._subplot; + + if(!newFullLayout[oldGeoKey] && !!oldGeo) { + oldGeo.framework.remove(); + oldGeo.clipDef.remove(); + } + } +}; + +exports.updateFx = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots[GEO]; + + for(var i = 0; i < subplotIds.length; i++) { + var subplotLayout = fullLayout[subplotIds[i]]; + var subplotObj = subplotLayout._subplot; + subplotObj.updateFx(fullLayout, subplotLayout); + } +}; + +},{"../../lib":696,"../../plots/get_data":781,"./geo":774,"./layout/attributes":776,"./layout/defaults":777,"./layout/layout_attributes":778}],776:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + geo: { + valType: 'subplotid', + + dflt: 'geo', + editType: 'calc', + + } +}; + +},{}],777:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var handleSubplotDefaults = _dereq_('../../subplot_defaults'); +var constants = _dereq_('../constants'); +var layoutAttributes = _dereq_('./layout_attributes'); + +var axesNames = constants.axesNames; + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'geo', + attributes: layoutAttributes, + handleDefaults: handleGeoDefaults, + partition: 'y' + }); +}; + +function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) { + var show; + + var resolution = coerce('resolution'); + var scope = coerce('scope'); + var scopeParams = constants.scopeDefaults[scope]; + + var projType = coerce('projection.type', scopeParams.projType); + var isAlbersUsa = geoLayoutOut._isAlbersUsa = projType === 'albers usa'; + + // no other scopes are allowed for 'albers usa' projection + if(isAlbersUsa) scope = geoLayoutOut.scope = 'usa'; + + var isScoped = geoLayoutOut._isScoped = (scope !== 'world'); + var isConic = geoLayoutOut._isConic = projType.indexOf('conic') !== -1; + geoLayoutOut._isClipped = !!constants.lonaxisSpan[projType]; + + for(var i = 0; i < axesNames.length; i++) { + var axisName = axesNames[i]; + var dtickDflt = [30, 10][i]; + var rangeDflt; + + if(isScoped) { + rangeDflt = scopeParams[axisName + 'Range']; + } else { + var dfltSpans = constants[axisName + 'Span']; + var hSpan = (dfltSpans[projType] || dfltSpans['*']) / 2; + var rot = coerce( + 'projection.rotation.' + axisName.substr(0, 3), + scopeParams.projRotate[i] + ); + rangeDflt = [rot - hSpan, rot + hSpan]; + } + + var range = coerce(axisName + '.range', rangeDflt); + + coerce(axisName + '.tick0', range[0]); + coerce(axisName + '.dtick', dtickDflt); + + show = coerce(axisName + '.showgrid'); + if(show) { + coerce(axisName + '.gridcolor'); + coerce(axisName + '.gridwidth'); + } + } + + var lonRange = geoLayoutOut.lonaxis.range; + var latRange = geoLayoutOut.lataxis.range; + + // to cross antimeridian w/o ambiguity + var lon0 = lonRange[0]; + var lon1 = lonRange[1]; + if(lon0 > 0 && lon1 < 0) lon1 += 360; + + var centerLon = (lon0 + lon1) / 2; + var projLon; + + if(!isAlbersUsa) { + var dfltProjRotate = isScoped ? scopeParams.projRotate : [centerLon, 0, 0]; + + projLon = coerce('projection.rotation.lon', dfltProjRotate[0]); + coerce('projection.rotation.lat', dfltProjRotate[1]); + coerce('projection.rotation.roll', dfltProjRotate[2]); + + show = coerce('showcoastlines', !isScoped); + if(show) { + coerce('coastlinecolor'); + coerce('coastlinewidth'); + } + + show = coerce('showocean'); + if(show) coerce('oceancolor'); + } + + var centerLonDflt; + var centerLatDflt; + + if(isAlbersUsa) { + // 'albers usa' does not have a 'center', + // these values were found using via: + // projection.invert([geoLayout.center.lon, geoLayoutIn.center.lat]) + centerLonDflt = -96.6; + centerLatDflt = 38.7; + } else { + centerLonDflt = isScoped ? centerLon : projLon; + centerLatDflt = (latRange[0] + latRange[1]) / 2; + } + + coerce('center.lon', centerLonDflt); + coerce('center.lat', centerLatDflt); + + if(isConic) { + var dfltProjParallels = scopeParams.projParallels || [0, 60]; + coerce('projection.parallels', dfltProjParallels); + } + + coerce('projection.scale'); + + show = coerce('showland'); + if(show) coerce('landcolor'); + + show = coerce('showlakes'); + if(show) coerce('lakecolor'); + + show = coerce('showrivers'); + if(show) { + coerce('rivercolor'); + coerce('riverwidth'); + } + + show = coerce('showcountries', isScoped && scope !== 'usa'); + if(show) { + coerce('countrycolor'); + coerce('countrywidth'); + } + + if(scope === 'usa' || (scope === 'north america' && resolution === 50)) { + // Only works for: + // USA states at 110m + // USA states + Canada provinces at 50m + coerce('showsubunits', true); + coerce('subunitcolor'); + coerce('subunitwidth'); + } + + if(!isScoped) { + // Does not work in non-world scopes + show = coerce('showframe', true); + if(show) { + coerce('framecolor'); + coerce('framewidth'); + } + } + + coerce('bgcolor'); +} + +},{"../../subplot_defaults":822,"../constants":773,"./layout_attributes":778}],778:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = _dereq_('../../../components/color/attributes'); +var domainAttrs = _dereq_('../../domain').attributes; +var constants = _dereq_('../constants'); +var overrideAll = _dereq_('../../../plot_api/edit_types').overrideAll; + +var geoAxesAttrs = { + range: { + valType: 'info_array', + + items: [ + {valType: 'number'}, + {valType: 'number'} + ], + + }, + showgrid: { + valType: 'boolean', + + dflt: false, + + }, + tick0: { + valType: 'number', + + + }, + dtick: { + valType: 'number', + + + }, + gridcolor: { + valType: 'color', + + dflt: colorAttrs.lightLine, + + }, + gridwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + } +}; + +module.exports = overrideAll({ + domain: domainAttrs({name: 'geo'}, { + + }), + + resolution: { + valType: 'enumerated', + values: [110, 50], + + dflt: 110, + coerceNumber: true, + + }, + scope: { + valType: 'enumerated', + + values: Object.keys(constants.scopeDefaults), + dflt: 'world', + + }, + projection: { + type: { + valType: 'enumerated', + + values: Object.keys(constants.projNames), + + }, + rotation: { + lon: { + valType: 'number', + + + }, + lat: { + valType: 'number', + + + }, + roll: { + valType: 'number', + + + } + }, + parallels: { + valType: 'info_array', + + items: [ + {valType: 'number'}, + {valType: 'number'} + ], + + }, + scale: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + }, + center: { + lon: { + valType: 'number', + + + }, + lat: { + valType: 'number', + + + } + }, + showcoastlines: { + valType: 'boolean', + + + }, + coastlinecolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + coastlinewidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showland: { + valType: 'boolean', + + dflt: false, + + }, + landcolor: { + valType: 'color', + + dflt: constants.landColor, + + }, + showocean: { + valType: 'boolean', + + dflt: false, + + }, + oceancolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + showlakes: { + valType: 'boolean', + + dflt: false, + + }, + lakecolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + showrivers: { + valType: 'boolean', + + dflt: false, + + }, + rivercolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + riverwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showcountries: { + valType: 'boolean', + + + }, + countrycolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + countrywidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showsubunits: { + valType: 'boolean', + + + }, + subunitcolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + subunitwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showframe: { + valType: 'boolean', + + + }, + framecolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + framewidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + bgcolor: { + valType: 'color', + + dflt: colorAttrs.background, + + }, + lonaxis: geoAxesAttrs, + lataxis: geoAxesAttrs +}, 'plot', 'from-root'); + +},{"../../../components/color/attributes":569,"../../../plot_api/edit_types":727,"../../domain":770,"../constants":773}],779:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* + * Generated by https://github.com/etpinard/d3-geo-projection-picker + * + * which is hand-picks projection from https://github.com/d3/d3-geo-projection + * + * into a CommonJS require-able module. + */ + +'use strict'; + +/* eslint-disable */ + +function addProjectionsToD3(d3) { + d3.geo.project = function(object, projection) { + var stream = projection.stream; + if (!stream) throw new Error("not yet supported"); + return (object && d3_geo_projectObjectType.hasOwnProperty(object.type) ? d3_geo_projectObjectType[object.type] : d3_geo_projectGeometry)(object, stream); + }; + function d3_geo_projectFeature(object, stream) { + return { + type: "Feature", + id: object.id, + properties: object.properties, + geometry: d3_geo_projectGeometry(object.geometry, stream) + }; + } + function d3_geo_projectGeometry(geometry, stream) { + if (!geometry) return null; + if (geometry.type === "GeometryCollection") return { + type: "GeometryCollection", + geometries: object.geometries.map(function(geometry) { + return d3_geo_projectGeometry(geometry, stream); + }) + }; + if (!d3_geo_projectGeometryType.hasOwnProperty(geometry.type)) return null; + var sink = d3_geo_projectGeometryType[geometry.type]; + d3.geo.stream(geometry, stream(sink)); + return sink.result(); + } + var d3_geo_projectObjectType = { + Feature: d3_geo_projectFeature, + FeatureCollection: function(object, stream) { + return { + type: "FeatureCollection", + features: object.features.map(function(feature) { + return d3_geo_projectFeature(feature, stream); + }) + }; + } + }; + var d3_geo_projectPoints = [], d3_geo_projectLines = []; + var d3_geo_projectPoint = { + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + result: function() { + var result = !d3_geo_projectPoints.length ? null : d3_geo_projectPoints.length < 2 ? { + type: "Point", + coordinates: d3_geo_projectPoints[0] + } : { + type: "MultiPoint", + coordinates: d3_geo_projectPoints + }; + d3_geo_projectPoints = []; + return result; + } + }; + var d3_geo_projectLine = { + lineStart: d3_geo_projectNoop, + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + lineEnd: function() { + if (d3_geo_projectPoints.length) d3_geo_projectLines.push(d3_geo_projectPoints), + d3_geo_projectPoints = []; + }, + result: function() { + var result = !d3_geo_projectLines.length ? null : d3_geo_projectLines.length < 2 ? { + type: "LineString", + coordinates: d3_geo_projectLines[0] + } : { + type: "MultiLineString", + coordinates: d3_geo_projectLines + }; + d3_geo_projectLines = []; + return result; + } + }; + var d3_geo_projectPolygon = { + polygonStart: d3_geo_projectNoop, + lineStart: d3_geo_projectNoop, + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + lineEnd: function() { + var n = d3_geo_projectPoints.length; + if (n) { + do d3_geo_projectPoints.push(d3_geo_projectPoints[0].slice()); while (++n < 4); + d3_geo_projectLines.push(d3_geo_projectPoints), d3_geo_projectPoints = []; + } + }, + polygonEnd: d3_geo_projectNoop, + result: function() { + if (!d3_geo_projectLines.length) return null; + var polygons = [], holes = []; + d3_geo_projectLines.forEach(function(ring) { + if (d3_geo_projectClockwise(ring)) polygons.push([ ring ]); else holes.push(ring); + }); + holes.forEach(function(hole) { + var point = hole[0]; + polygons.some(function(polygon) { + if (d3_geo_projectContains(polygon[0], point)) { + polygon.push(hole); + return true; + } + }) || polygons.push([ hole ]); + }); + d3_geo_projectLines = []; + return !polygons.length ? null : polygons.length > 1 ? { + type: "MultiPolygon", + coordinates: polygons + } : { + type: "Polygon", + coordinates: polygons[0] + }; + } + }; + var d3_geo_projectGeometryType = { + Point: d3_geo_projectPoint, + MultiPoint: d3_geo_projectPoint, + LineString: d3_geo_projectLine, + MultiLineString: d3_geo_projectLine, + Polygon: d3_geo_projectPolygon, + MultiPolygon: d3_geo_projectPolygon, + Sphere: d3_geo_projectPolygon + }; + function d3_geo_projectNoop() {} + function d3_geo_projectClockwise(ring) { + if ((n = ring.length) < 4) return false; + var i = 0, n, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; + while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; + return area <= 0; + } + function d3_geo_projectContains(ring, point) { + var x = point[0], y = point[1], contains = false; + for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) { + var pi = ring[i], xi = pi[0], yi = pi[1], pj = ring[j], xj = pj[0], yj = pj[1]; + if (yi > y ^ yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) contains = !contains; + } + return contains; + } + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, halfπ = π / 2, sqrtπ = Math.sqrt(π), radians = π / 180, degrees = 180 / π; + function sinci(x) { + return x ? x / Math.sin(x) : 1; + } + function sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); + } + function acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); + } + function asqrt(x) { + return x > 0 ? Math.sqrt(x) : 0; + } + var projection = d3.geo.projection, projectionMutator = d3.geo.projectionMutator; + d3.geo.interrupt = function(project) { + var lobes = [ [ [ [ -π, 0 ], [ 0, halfπ ], [ π, 0 ] ] ], [ [ [ -π, 0 ], [ 0, -halfπ ], [ π, 0 ] ] ] ]; + var bounds; + function forward(λ, φ) { + var sign = φ < 0 ? -1 : +1, hemilobes = lobes[+(φ < 0)]; + for (var i = 0, n = hemilobes.length - 1; i < n && λ > hemilobes[i][2][0]; ++i) ; + var coordinates = project(λ - hemilobes[i][1][0], φ); + coordinates[0] += project(hemilobes[i][1][0], sign * φ > sign * hemilobes[i][0][1] ? hemilobes[i][0][1] : φ)[0]; + return coordinates; + } + function reset() { + bounds = lobes.map(function(hemilobes) { + return hemilobes.map(function(lobe) { + var x0 = project(lobe[0][0], lobe[0][1])[0], x1 = project(lobe[2][0], lobe[2][1])[0], y0 = project(lobe[1][0], lobe[0][1])[1], y1 = project(lobe[1][0], lobe[1][1])[1], t; + if (y0 > y1) t = y0, y0 = y1, y1 = t; + return [ [ x0, y0 ], [ x1, y1 ] ]; + }); + }); + } + if (project.invert) forward.invert = function(x, y) { + var hemibounds = bounds[+(y < 0)], hemilobes = lobes[+(y < 0)]; + for (var i = 0, n = hemibounds.length; i < n; ++i) { + var b = hemibounds[i]; + if (b[0][0] <= x && x < b[1][0] && b[0][1] <= y && y < b[1][1]) { + var coordinates = project.invert(x - project(hemilobes[i][1][0], 0)[0], y); + coordinates[0] += hemilobes[i][1][0]; + return pointEqual(forward(coordinates[0], coordinates[1]), [ x, y ]) ? coordinates : null; + } + } + }; + var projection = d3.geo.projection(forward), stream_ = projection.stream; + projection.stream = function(stream) { + var rotate = projection.rotate(), rotateStream = stream_(stream), sphereStream = (projection.rotate([ 0, 0 ]), + stream_(stream)); + projection.rotate(rotate); + rotateStream.sphere = function() { + d3.geo.stream(sphere(), sphereStream); + }; + return rotateStream; + }; + projection.lobes = function(_) { + if (!arguments.length) return lobes.map(function(lobes) { + return lobes.map(function(lobe) { + return [ [ lobe[0][0] * 180 / π, lobe[0][1] * 180 / π ], [ lobe[1][0] * 180 / π, lobe[1][1] * 180 / π ], [ lobe[2][0] * 180 / π, lobe[2][1] * 180 / π ] ]; + }); + }); + lobes = _.map(function(lobes) { + return lobes.map(function(lobe) { + return [ [ lobe[0][0] * π / 180, lobe[0][1] * π / 180 ], [ lobe[1][0] * π / 180, lobe[1][1] * π / 180 ], [ lobe[2][0] * π / 180, lobe[2][1] * π / 180 ] ]; + }); + }); + reset(); + return projection; + }; + function sphere() { + var ε = 1e-6, coordinates = []; + for (var i = 0, n = lobes[0].length; i < n; ++i) { + var lobe = lobes[0][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; + coordinates.push(resample([ [ λ0 + ε, φ0 + ε ], [ λ0 + ε, φ1 - ε ], [ λ2 - ε, φ1 - ε ], [ λ2 - ε, φ2 + ε ] ], 30)); + } + for (var i = lobes[1].length - 1; i >= 0; --i) { + var lobe = lobes[1][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; + coordinates.push(resample([ [ λ2 - ε, φ2 - ε ], [ λ2 - ε, φ1 + ε ], [ λ0 + ε, φ1 + ε ], [ λ0 + ε, φ0 - ε ] ], 30)); + } + return { + type: "Polygon", + coordinates: [ d3.merge(coordinates) ] + }; + } + function resample(coordinates, m) { + var i = -1, n = coordinates.length, p0 = coordinates[0], p1, dx, dy, resampled = []; + while (++i < n) { + p1 = coordinates[i]; + dx = (p1[0] - p0[0]) / m; + dy = (p1[1] - p0[1]) / m; + for (var j = 0; j < m; ++j) resampled.push([ p0[0] + j * dx, p0[1] + j * dy ]); + p0 = p1; + } + resampled.push(p1); + return resampled; + } + function pointEqual(a, b) { + return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; + } + return projection; + }; + function eckert4(λ, φ) { + var k = (2 + halfπ) * Math.sin(φ); + φ /= 2; + for (var i = 0, δ = Infinity; i < 10 && Math.abs(δ) > ε; i++) { + var cosφ = Math.cos(φ); + φ -= δ = (φ + Math.sin(φ) * (cosφ + 2) - k) / (2 * cosφ * (1 + cosφ)); + } + return [ 2 / Math.sqrt(π * (4 + π)) * λ * (1 + Math.cos(φ)), 2 * Math.sqrt(π / (4 + π)) * Math.sin(φ) ]; + } + eckert4.invert = function(x, y) { + var A = .5 * y * Math.sqrt((4 + π) / π), k = asin(A), c = Math.cos(k); + return [ x / (2 / Math.sqrt(π * (4 + π)) * (1 + c)), asin((k + A * (c + 2)) / (2 + halfπ)) ]; + }; + (d3.geo.eckert4 = function() { + return projection(eckert4); + }).raw = eckert4; + var hammerAzimuthalEqualArea = d3.geo.azimuthalEqualArea.raw; + function hammer(A, B) { + if (arguments.length < 2) B = A; + if (B === 1) return hammerAzimuthalEqualArea; + if (B === Infinity) return hammerQuarticAuthalic; + function forward(λ, φ) { + var coordinates = hammerAzimuthalEqualArea(λ / B, φ); + coordinates[0] *= A; + return coordinates; + } + forward.invert = function(x, y) { + var coordinates = hammerAzimuthalEqualArea.invert(x / A, y); + coordinates[0] *= B; + return coordinates; + }; + return forward; + } + function hammerProjection() { + var B = 2, m = projectionMutator(hammer), p = m(B); + p.coefficient = function(_) { + if (!arguments.length) return B; + return m(B = +_); + }; + return p; + } + function hammerQuarticAuthalic(λ, φ) { + return [ λ * Math.cos(φ) / Math.cos(φ /= 2), 2 * Math.sin(φ) ]; + } + hammerQuarticAuthalic.invert = function(x, y) { + var φ = 2 * asin(y / 2); + return [ x * Math.cos(φ / 2) / Math.cos(φ), φ ]; + }; + (d3.geo.hammer = hammerProjection).raw = hammer; + function kavrayskiy7(λ, φ) { + return [ 3 * λ / (2 * π) * Math.sqrt(π * π / 3 - φ * φ), φ ]; + } + kavrayskiy7.invert = function(x, y) { + return [ 2 / 3 * π * x / Math.sqrt(π * π / 3 - y * y), y ]; + }; + (d3.geo.kavrayskiy7 = function() { + return projection(kavrayskiy7); + }).raw = kavrayskiy7; + function miller(λ, φ) { + return [ λ, 1.25 * Math.log(Math.tan(π / 4 + .4 * φ)) ]; + } + miller.invert = function(x, y) { + return [ x, 2.5 * Math.atan(Math.exp(.8 * y)) - .625 * π ]; + }; + (d3.geo.miller = function() { + return projection(miller); + }).raw = miller; + function mollweideBromleyθ(Cp) { + return function(θ) { + var Cpsinθ = Cp * Math.sin(θ), i = 30, δ; + do θ -= δ = (θ + Math.sin(θ) - Cpsinθ) / (1 + Math.cos(θ)); while (Math.abs(δ) > ε && --i > 0); + return θ / 2; + }; + } + function mollweideBromley(Cx, Cy, Cp) { + var θ = mollweideBromleyθ(Cp); + function forward(λ, φ) { + return [ Cx * λ * Math.cos(φ = θ(φ)), Cy * Math.sin(φ) ]; + } + forward.invert = function(x, y) { + var θ = asin(y / Cy); + return [ x / (Cx * Math.cos(θ)), asin((2 * θ + Math.sin(2 * θ)) / Cp) ]; + }; + return forward; + } + var mollweideθ = mollweideBromleyθ(π), mollweide = mollweideBromley(Math.SQRT2 / halfπ, Math.SQRT2, π); + (d3.geo.mollweide = function() { + return projection(mollweide); + }).raw = mollweide; + function naturalEarth(λ, φ) { + var φ2 = φ * φ, φ4 = φ2 * φ2; + return [ λ * (.8707 - .131979 * φ2 + φ4 * (-.013791 + φ4 * (.003971 * φ2 - .001529 * φ4))), φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) ]; + } + naturalEarth.invert = function(x, y) { + var φ = y, i = 25, δ; + do { + var φ2 = φ * φ, φ4 = φ2 * φ2; + φ -= δ = (φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) - y) / (1.007226 + φ2 * (.015085 * 3 + φ4 * (-.044475 * 7 + .028874 * 9 * φ2 - .005916 * 11 * φ4))); + } while (Math.abs(δ) > ε && --i > 0); + return [ x / (.8707 + (φ2 = φ * φ) * (-.131979 + φ2 * (-.013791 + φ2 * φ2 * φ2 * (.003971 - .001529 * φ2)))), φ ]; + }; + (d3.geo.naturalEarth = function() { + return projection(naturalEarth); + }).raw = naturalEarth; + var robinsonConstants = [ [ .9986, -.062 ], [ 1, 0 ], [ .9986, .062 ], [ .9954, .124 ], [ .99, .186 ], [ .9822, .248 ], [ .973, .31 ], [ .96, .372 ], [ .9427, .434 ], [ .9216, .4958 ], [ .8962, .5571 ], [ .8679, .6176 ], [ .835, .6769 ], [ .7986, .7346 ], [ .7597, .7903 ], [ .7186, .8435 ], [ .6732, .8936 ], [ .6213, .9394 ], [ .5722, .9761 ], [ .5322, 1 ] ]; + robinsonConstants.forEach(function(d) { + d[1] *= 1.0144; + }); + function robinson(λ, φ) { + var i = Math.min(18, Math.abs(φ) * 36 / π), i0 = Math.floor(i), di = i - i0, ax = (k = robinsonConstants[i0])[0], ay = k[1], bx = (k = robinsonConstants[++i0])[0], by = k[1], cx = (k = robinsonConstants[Math.min(19, ++i0)])[0], cy = k[1], k; + return [ λ * (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), (φ > 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) ]; + } + robinson.invert = function(x, y) { + var yy = y / halfπ, φ = yy * 90, i = Math.min(18, Math.abs(φ / 5)), i0 = Math.max(0, Math.floor(i)); + do { + var ay = robinsonConstants[i0][1], by = robinsonConstants[i0 + 1][1], cy = robinsonConstants[Math.min(19, i0 + 2)][1], u = cy - ay, v = cy - 2 * by + ay, t = 2 * (Math.abs(yy) - by) / u, c = v / u, di = t * (1 - c * t * (1 - 2 * c * t)); + if (di >= 0 || i0 === 1) { + φ = (y >= 0 ? 5 : -5) * (di + i); + var j = 50, δ; + do { + i = Math.min(18, Math.abs(φ) / 5); + i0 = Math.floor(i); + di = i - i0; + ay = robinsonConstants[i0][1]; + by = robinsonConstants[i0 + 1][1]; + cy = robinsonConstants[Math.min(19, i0 + 2)][1]; + φ -= (δ = (y >= 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) - y) * degrees; + } while (Math.abs(δ) > ε2 && --j > 0); + break; + } + } while (--i0 >= 0); + var ax = robinsonConstants[i0][0], bx = robinsonConstants[i0 + 1][0], cx = robinsonConstants[Math.min(19, i0 + 2)][0]; + return [ x / (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), φ * radians ]; + }; + (d3.geo.robinson = function() { + return projection(robinson); + }).raw = robinson; + function sinusoidal(λ, φ) { + return [ λ * Math.cos(φ), φ ]; + } + sinusoidal.invert = function(x, y) { + return [ x / Math.cos(y), y ]; + }; + (d3.geo.sinusoidal = function() { + return projection(sinusoidal); + }).raw = sinusoidal; + function aitoff(λ, φ) { + var cosφ = Math.cos(φ), sinciα = sinci(acos(cosφ * Math.cos(λ /= 2))); + return [ 2 * cosφ * Math.sin(λ) * sinciα, Math.sin(φ) * sinciα ]; + } + aitoff.invert = function(x, y) { + if (x * x + 4 * y * y > π * π + ε) return; + var λ = x, φ = y, i = 25; + do { + var sinλ = Math.sin(λ), sinλ_2 = Math.sin(λ / 2), cosλ_2 = Math.cos(λ / 2), sinφ = Math.sin(φ), cosφ = Math.cos(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = 2 * E * cosφ * sinλ_2 - x, fy = E * sinφ - y, δxδλ = F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ), δxδφ = F * (.5 * sinλ * sin_2φ - E * 2 * sinφ * sinλ_2), δyδλ = F * .25 * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ), denominator = δxδφ * δyδλ - δyδφ * δxδλ; + if (!denominator) break; + var δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; + λ -= δλ, φ -= δφ; + } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); + return [ λ, φ ]; + }; + (d3.geo.aitoff = function() { + return projection(aitoff); + }).raw = aitoff; + function winkel3(λ, φ) { + var coordinates = aitoff(λ, φ); + return [ (coordinates[0] + λ / halfπ) / 2, (coordinates[1] + φ) / 2 ]; + } + winkel3.invert = function(x, y) { + var λ = x, φ = y, i = 25; + do { + var cosφ = Math.cos(φ), sinφ = Math.sin(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sinλ = Math.sin(λ), cosλ_2 = Math.cos(λ / 2), sinλ_2 = Math.sin(λ / 2), sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = .5 * (2 * E * cosφ * sinλ_2 + λ / halfπ) - x, fy = .5 * (E * sinφ + φ) - y, δxδλ = .5 * F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ) + .5 / halfπ, δxδφ = F * (sinλ * sin_2φ / 4 - E * sinφ * sinλ_2), δyδλ = .125 * F * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = .5 * F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ) + .5, denominator = δxδφ * δyδλ - δyδφ * δxδλ, δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; + λ -= δλ, φ -= δφ; + } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); + return [ λ, φ ]; + }; + (d3.geo.winkel3 = function() { + return projection(winkel3); + }).raw = winkel3; +} + +module.exports = addProjectionsToD3; + +},{}],780:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Lib = _dereq_('../../lib'); + +var radians = Math.PI / 180; +var degrees = 180 / Math.PI; +var zoomstartStyle = {cursor: 'pointer'}; +var zoomendStyle = {cursor: 'auto'}; + +function createGeoZoom(geo, geoLayout) { + var projection = geo.projection; + var zoomConstructor; + + if(geoLayout._isScoped) { + zoomConstructor = zoomScoped; + } else if(geoLayout._isClipped) { + zoomConstructor = zoomClipped; + } else { + zoomConstructor = zoomNonClipped; + } + + // TODO add a conic-specific zoom + + return zoomConstructor(geo, projection); +} + +module.exports = createGeoZoom; + +// common to all zoom types +function initZoom(geo, projection) { + return d3.behavior.zoom() + .translate(projection.translate()) + .scale(projection.scale()); +} + +// sync zoom updates with user & full layout +function sync(geo, projection, cb) { + var id = geo.id; + var gd = geo.graphDiv; + var userOpts = gd.layout[id]; + var fullOpts = gd._fullLayout[id]; + + var eventData = {}; + + function set(propStr, val) { + var fullNp = Lib.nestedProperty(fullOpts, propStr); + + if(fullNp.get() !== val) { + fullNp.set(val); + Lib.nestedProperty(userOpts, propStr).set(val); + eventData[id + '.' + propStr] = val; + } + } + + cb(set); + set('projection.scale', projection.scale() / geo.fitScale); + gd.emit('plotly_relayout', eventData); +} + +// zoom for scoped projections +function zoomScoped(geo, projection) { + var zoom = initZoom(geo, projection); + + function handleZoomstart() { + d3.select(this).style(zoomstartStyle); + } + + function handleZoom() { + projection + .scale(d3.event.scale) + .translate(d3.event.translate); + geo.render(); + } + + function syncCb(set) { + var center = projection.invert(geo.midPt); + + set('center.lon', center[0]); + set('center.lat', center[1]); + } + + function handleZoomend() { + d3.select(this).style(zoomendStyle); + sync(geo, projection, syncCb); + } + + zoom + .on('zoomstart', handleZoomstart) + .on('zoom', handleZoom) + .on('zoomend', handleZoomend); + + return zoom; +} + +// zoom for non-clipped projections +function zoomNonClipped(geo, projection) { + var zoom = initZoom(geo, projection); + + var INSIDETOLORANCEPXS = 2; + + var mouse0, rotate0, translate0, lastRotate, zoomPoint, + mouse1, rotate1, point1, didZoom; + + function position(x) { return projection.invert(x); } + + function outside(x) { + var pos = position(x); + if(!pos) return true; + + var pt = projection(pos); + return ( + Math.abs(pt[0] - x[0]) > INSIDETOLORANCEPXS || + Math.abs(pt[1] - x[1]) > INSIDETOLORANCEPXS + ); + } + + function handleZoomstart() { + d3.select(this).style(zoomstartStyle); + + mouse0 = d3.mouse(this); + rotate0 = projection.rotate(); + translate0 = projection.translate(); + lastRotate = rotate0; + zoomPoint = position(mouse0); + } + + function handleZoom() { + mouse1 = d3.mouse(this); + + if(outside(mouse0)) { + zoom.scale(projection.scale()); + zoom.translate(projection.translate()); + return; + } + + projection.scale(d3.event.scale); + projection.translate([translate0[0], d3.event.translate[1]]); + + if(!zoomPoint) { + mouse0 = mouse1; + zoomPoint = position(mouse0); + } + else if(position(mouse1)) { + point1 = position(mouse1); + rotate1 = [lastRotate[0] + (point1[0] - zoomPoint[0]), rotate0[1], rotate0[2]]; + projection.rotate(rotate1); + lastRotate = rotate1; + } + + didZoom = true; + geo.render(); + } + + function handleZoomend() { + d3.select(this).style(zoomendStyle); + if(didZoom) sync(geo, projection, syncCb); + } + + function syncCb(set) { + var rotate = projection.rotate(); + var center = projection.invert(geo.midPt); + + set('projection.rotation.lon', -rotate[0]); + set('center.lon', center[0]); + set('center.lat', center[1]); + } + + zoom + .on('zoomstart', handleZoomstart) + .on('zoom', handleZoom) + .on('zoomend', handleZoomend); + + return zoom; +} + +// zoom for clipped projections +// inspired by https://www.jasondavies.com/maps/d3.geo.zoom.js +function zoomClipped(geo, projection) { + var view = {r: projection.rotate(), k: projection.scale()}, + zoom = initZoom(geo, projection), + event = d3_eventDispatch(zoom, 'zoomstart', 'zoom', 'zoomend'), + zooming = 0, + zoomOn = zoom.on; + + var zoomPoint; + + zoom.on('zoomstart', function() { + d3.select(this).style(zoomstartStyle); + + var mouse0 = d3.mouse(this), + rotate0 = projection.rotate(), + lastRotate = rotate0, + translate0 = projection.translate(), + q = quaternionFromEuler(rotate0); + + zoomPoint = position(projection, mouse0); + + zoomOn.call(zoom, 'zoom', function() { + var mouse1 = d3.mouse(this); + + projection.scale(view.k = d3.event.scale); + + if(!zoomPoint) { + // if no zoomPoint, the mouse wasn't over the actual geography yet + // maybe this point is the start... we'll find out next time! + mouse0 = mouse1; + zoomPoint = position(projection, mouse0); + } + // check if the point is on the map + // if not, don't do anything new but scale + // if it is, then we can assume between will exist below + // so we don't need the 'bank' function, whatever that is. + else if(position(projection, mouse1)) { + // go back to original projection temporarily + // except for scale... that's kind of independent? + projection + .rotate(rotate0) + .translate(translate0); + + // calculate the new params + var point1 = position(projection, mouse1), + between = rotateBetween(zoomPoint, point1), + newEuler = eulerFromQuaternion(multiply(q, between)), + rotateAngles = view.r = unRoll(newEuler, zoomPoint, lastRotate); + + if(!isFinite(rotateAngles[0]) || !isFinite(rotateAngles[1]) || + !isFinite(rotateAngles[2])) { + rotateAngles = lastRotate; + } + + // update the projection + projection.rotate(rotateAngles); + lastRotate = rotateAngles; + } + + zoomed(event.of(this, arguments)); + }); + + zoomstarted(event.of(this, arguments)); + }) + .on('zoomend', function() { + d3.select(this).style(zoomendStyle); + zoomOn.call(zoom, 'zoom', null); + zoomended(event.of(this, arguments)); + sync(geo, projection, syncCb); + }) + .on('zoom.redraw', function() { + geo.render(); + }); + + function zoomstarted(dispatch) { + if(!zooming++) dispatch({type: 'zoomstart'}); + } + + function zoomed(dispatch) { + dispatch({type: 'zoom'}); + } + + function zoomended(dispatch) { + if(!--zooming) dispatch({type: 'zoomend'}); + } + + function syncCb(set) { + var _rotate = projection.rotate(); + set('projection.rotation.lon', -_rotate[0]); + set('projection.rotation.lat', -_rotate[1]); + } + + return d3.rebind(zoom, event, 'on'); +} + +// -- helper functions for zoomClipped + +function position(projection, point) { + var spherical = projection.invert(point); + return spherical && isFinite(spherical[0]) && isFinite(spherical[1]) && cartesian(spherical); +} + +function quaternionFromEuler(euler) { + var lambda = 0.5 * euler[0] * radians, + phi = 0.5 * euler[1] * radians, + gamma = 0.5 * euler[2] * radians, + sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda), + sinPhi = Math.sin(phi), cosPhi = Math.cos(phi), + sinGamma = Math.sin(gamma), cosGamma = Math.cos(gamma); + return [ + cosLambda * cosPhi * cosGamma + sinLambda * sinPhi * sinGamma, + sinLambda * cosPhi * cosGamma - cosLambda * sinPhi * sinGamma, + cosLambda * sinPhi * cosGamma + sinLambda * cosPhi * sinGamma, + cosLambda * cosPhi * sinGamma - sinLambda * sinPhi * cosGamma + ]; +} + +function multiply(a, b) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + return [ + a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3, + a0 * b1 + a1 * b0 + a2 * b3 - a3 * b2, + a0 * b2 - a1 * b3 + a2 * b0 + a3 * b1, + a0 * b3 + a1 * b2 - a2 * b1 + a3 * b0 + ]; +} + +function rotateBetween(a, b) { + if(!a || !b) return; + var axis = cross(a, b), + norm = Math.sqrt(dot(axis, axis)), + halfgamma = 0.5 * Math.acos(Math.max(-1, Math.min(1, dot(a, b)))), + k = Math.sin(halfgamma) / norm; + return norm && [Math.cos(halfgamma), axis[2] * k, -axis[1] * k, axis[0] * k]; +} + +// input: +// rotateAngles: a calculated set of Euler angles +// pt: a point (cartesian in 3-space) to keep fixed +// roll0: an initial roll, to be preserved +// output: +// a set of Euler angles that preserve the projection of pt +// but set roll (output[2]) equal to roll0 +// note that this doesn't depend on the particular projection, +// just on the rotation angles +function unRoll(rotateAngles, pt, lastRotate) { + // calculate the fixed point transformed by these Euler angles + // but with the desired roll undone + var ptRotated = rotateCartesian(pt, 2, rotateAngles[0]); + ptRotated = rotateCartesian(ptRotated, 1, rotateAngles[1]); + ptRotated = rotateCartesian(ptRotated, 0, rotateAngles[2] - lastRotate[2]); + + var x = pt[0], + y = pt[1], + z = pt[2], + f = ptRotated[0], + g = ptRotated[1], + h = ptRotated[2], + + // the following essentially solves: + // ptRotated = rotateCartesian(rotateCartesian(pt, 2, newYaw), 1, newPitch) + // for newYaw and newPitch, as best it can + theta = Math.atan2(y, x) * degrees, + a = Math.sqrt(x * x + y * y), + b, + newYaw1; + + if(Math.abs(g) > a) { + newYaw1 = (g > 0 ? 90 : -90) - theta; + b = 0; + } else { + newYaw1 = Math.asin(g / a) * degrees - theta; + b = Math.sqrt(a * a - g * g); + } + + var newYaw2 = 180 - newYaw1 - 2 * theta, + newPitch1 = (Math.atan2(h, f) - Math.atan2(z, b)) * degrees, + newPitch2 = (Math.atan2(h, f) - Math.atan2(z, -b)) * degrees; + + // which is closest to lastRotate[0,1]: newYaw/Pitch or newYaw2/Pitch2? + var dist1 = angleDistance(lastRotate[0], lastRotate[1], newYaw1, newPitch1), + dist2 = angleDistance(lastRotate[0], lastRotate[1], newYaw2, newPitch2); + + if(dist1 <= dist2) return [newYaw1, newPitch1, lastRotate[2]]; + else return [newYaw2, newPitch2, lastRotate[2]]; +} + +function angleDistance(yaw0, pitch0, yaw1, pitch1) { + var dYaw = angleMod(yaw1 - yaw0), + dPitch = angleMod(pitch1 - pitch0); + return Math.sqrt(dYaw * dYaw + dPitch * dPitch); +} + +// reduce an angle in degrees to [-180,180] +function angleMod(angle) { + return (angle % 360 + 540) % 360 - 180; +} + +// rotate a cartesian vector +// axis is 0 (x), 1 (y), or 2 (z) +// angle is in degrees +function rotateCartesian(vector, axis, angle) { + var angleRads = angle * radians, + vectorOut = vector.slice(), + ax1 = (axis === 0) ? 1 : 0, + ax2 = (axis === 2) ? 1 : 2, + cosa = Math.cos(angleRads), + sina = Math.sin(angleRads); + + vectorOut[ax1] = vector[ax1] * cosa - vector[ax2] * sina; + vectorOut[ax2] = vector[ax2] * cosa + vector[ax1] * sina; + + return vectorOut; +} +function eulerFromQuaternion(q) { + return [ + Math.atan2(2 * (q[0] * q[1] + q[2] * q[3]), 1 - 2 * (q[1] * q[1] + q[2] * q[2])) * degrees, + Math.asin(Math.max(-1, Math.min(1, 2 * (q[0] * q[2] - q[3] * q[1])))) * degrees, + Math.atan2(2 * (q[0] * q[3] + q[1] * q[2]), 1 - 2 * (q[2] * q[2] + q[3] * q[3])) * degrees + ]; +} + +function cartesian(spherical) { + var lambda = spherical[0] * radians, + phi = spherical[1] * radians, + cosPhi = Math.cos(phi); + return [ + cosPhi * Math.cos(lambda), + cosPhi * Math.sin(lambda), + Math.sin(phi) + ]; +} + +function dot(a, b) { + var s = 0; + for(var i = 0, n = a.length; i < n; ++i) s += a[i] * b[i]; + return s; +} + +function cross(a, b) { + return [ + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0] + ]; +} + +// Like d3.dispatch, but for custom events abstracting native UI events. These +// events have a target component (such as a brush), a target element (such as +// the svg:g element containing the brush) and the standard arguments `d` (the +// target element's data) and `i` (the selection index of the target element). +function d3_eventDispatch(target) { + var i = 0, + n = arguments.length, + argumentz = []; + + while(++i < n) argumentz.push(arguments[i]); + + var dispatch = d3.dispatch.apply(null, argumentz); + + // Creates a dispatch context for the specified `thiz` (typically, the target + // DOM element that received the source event) and `argumentz` (typically, the + // data `d` and index `i` of the target element). The returned function can be + // used to dispatch an event to any registered listeners; the function takes a + // single argument as input, being the event to dispatch. The event must have + // a "type" attribute which corresponds to a type registered in the + // constructor. This context will automatically populate the "sourceEvent" and + // "target" attributes of the event, as well as setting the `d3.event` global + // for the duration of the notification. + dispatch.of = function(thiz, argumentz) { + return function(e1) { + var e0; + try { + e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + + return dispatch; +} + +},{"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],781:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../registry'); +var SUBPLOT_PATTERN = _dereq_('./cartesian/constants').SUBPLOT_PATTERN; + +/** + * Get calcdata trace(s) associated with a given subplot + * + * @param {array} calcData: as in gd.calcdata + * @param {string} type: subplot type + * @param {string} subplotId: subplot id to look for + * + * @return {array} array of calcdata traces + */ +exports.getSubplotCalcData = function(calcData, type, subplotId) { + var basePlotModule = Registry.subplotsRegistry[type]; + if(!basePlotModule) return []; + + var attr = basePlotModule.attr; + var subplotCalcData = []; + + for(var i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i]; + var trace = calcTrace[0].trace; + + if(trace[attr] === subplotId) subplotCalcData.push(calcTrace); + } + + return subplotCalcData; +}; +/** + * Get calcdata trace(s) that can be plotted with a given module + * NOTE: this isn't necessarily just exactly matching trace type, + * if multiple trace types use the same plotting routine, they will be + * collected here. + * In order to not plot the same thing multiple times, we return two arrays, + * the calcdata we *will* plot with this module, and the ones we *won't* + * + * @param {array} calcdata: as in gd.calcdata + * @param {object|string|fn} arg1: + * the plotting module, or its name, or its plot method + * + * @return {array[array]} [foundCalcdata, remainingCalcdata] + */ +exports.getModuleCalcData = function(calcdata, arg1) { + var moduleCalcData = []; + var remainingCalcData = []; + + var plotMethod; + if(typeof arg1 === 'string') { + plotMethod = Registry.getModule(arg1).plot; + } else if(typeof arg1 === 'function') { + plotMethod = arg1; + } else { + plotMethod = arg1.plot; + } + if(!plotMethod) { + return [moduleCalcData, calcdata]; + } + + for(var i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var trace = cd[0].trace; + // N.B. 'legendonly' traces do not make it past here + if(trace.visible !== true) continue; + + // group calcdata trace not by 'module' (as the name of this function + // would suggest), but by 'module plot method' so that if some traces + // share the same module plot method (e.g. bar and histogram), we + // only call it one! + if(trace._module.plot === plotMethod) { + moduleCalcData.push(cd); + } else { + remainingCalcData.push(cd); + } + } + + return [moduleCalcData, remainingCalcData]; +}; + +/** + * Get the data trace(s) associated with a given subplot. + * + * @param {array} data plotly full data array. + * @param {string} type subplot type to look for. + * @param {string} subplotId subplot id to look for. + * + * @return {array} list of trace objects. + * + */ +exports.getSubplotData = function getSubplotData(data, type, subplotId) { + if(!Registry.subplotsRegistry[type]) return []; + + var attr = Registry.subplotsRegistry[type].attr; + var subplotData = []; + var trace, subplotX, subplotY; + + if(type === 'gl2d') { + var spmatch = subplotId.match(SUBPLOT_PATTERN); + subplotX = 'x' + spmatch[1]; + subplotY = 'y' + spmatch[2]; + } + + for(var i = 0; i < data.length; i++) { + trace = data[i]; + + if(type === 'gl2d' && Registry.traceIs(trace, 'gl2d')) { + if(trace[attr[0]] === subplotX && trace[attr[1]] === subplotY) { + subplotData.push(trace); + } + } + else { + if(trace[attr] === subplotId) subplotData.push(trace); + } + } + + return subplotData; +}; + +},{"../registry":827,"./cartesian/constants":750}],782:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var mouseChange = _dereq_('mouse-change'); +var mouseWheel = _dereq_('mouse-wheel'); +var mouseOffset = _dereq_('mouse-event-offset'); +var cartesianConstants = _dereq_('../cartesian/constants'); +var hasPassive = _dereq_('has-passive-events'); + +module.exports = createCamera; + +function Camera2D(element, plot) { + this.element = element; + this.plot = plot; + this.mouseListener = null; + this.wheelListener = null; + this.lastInputTime = Date.now(); + this.lastPos = [0, 0]; + this.boxEnabled = false; + this.boxInited = false; + this.boxStart = [0, 0]; + this.boxEnd = [0, 0]; + this.dragStart = [0, 0]; +} + + +function createCamera(scene) { + var element = scene.mouseContainer, + plot = scene.glplot, + result = new Camera2D(element, plot); + + function unSetAutoRange() { + scene.xaxis.autorange = false; + scene.yaxis.autorange = false; + } + + function getSubplotConstraint() { + // note: this assumes we only have one x and one y axis on this subplot + // when this constraint is lifted this block won't make sense + var constraints = scene.graphDiv._fullLayout._axisConstraintGroups; + var xaId = scene.xaxis._id; + var yaId = scene.yaxis._id; + for(var i = 0; i < constraints.length; i++) { + if(constraints[i][xaId] !== -1) { + if(constraints[i][yaId] !== -1) return true; + break; + } + } + return false; + } + + result.mouseListener = mouseChange(element, handleInteraction); + + // enable simple touch interactions + element.addEventListener('touchstart', function(ev) { + var xy = mouseOffset(ev.changedTouches[0], element); + handleInteraction(0, xy[0], xy[1]); + handleInteraction(1, xy[0], xy[1]); + + ev.preventDefault(); + }, hasPassive ? {passive: false} : false); + element.addEventListener('touchmove', function(ev) { + ev.preventDefault(); + var xy = mouseOffset(ev.changedTouches[0], element); + handleInteraction(1, xy[0], xy[1]); + + ev.preventDefault(); + }, hasPassive ? {passive: false} : false); + element.addEventListener('touchend', function(ev) { + handleInteraction(0, result.lastPos[0], result.lastPos[1]); + + ev.preventDefault(); + }, hasPassive ? {passive: false} : false); + + function handleInteraction(buttons, x, y) { + var dataBox = scene.calcDataBox(), + viewBox = plot.viewBox; + + var lastX = result.lastPos[0], + lastY = result.lastPos[1]; + + var MINDRAG = cartesianConstants.MINDRAG * plot.pixelRatio; + var MINZOOM = cartesianConstants.MINZOOM * plot.pixelRatio; + + var dx, dy; + + x *= plot.pixelRatio; + y *= plot.pixelRatio; + + // mouseChange gives y about top; convert to about bottom + y = (viewBox[3] - viewBox[1]) - y; + + function updateRange(i0, start, end) { + var range0 = Math.min(start, end), + range1 = Math.max(start, end); + + if(range0 !== range1) { + dataBox[i0] = range0; + dataBox[i0 + 2] = range1; + result.dataBox = dataBox; + scene.setRanges(dataBox); + } + else { + scene.selectBox.selectBox = [0, 0, 1, 1]; + scene.glplot.setDirty(); + } + } + + switch(scene.fullLayout.dragmode) { + case 'zoom': + if(buttons) { + var dataX = x / + (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) + + dataBox[0]; + var dataY = y / + (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) + + dataBox[1]; + + if(!result.boxInited) { + result.boxStart[0] = dataX; + result.boxStart[1] = dataY; + result.dragStart[0] = x; + result.dragStart[1] = y; + } + + result.boxEnd[0] = dataX; + result.boxEnd[1] = dataY; + + // we need to mark the box as initialized right away + // so that we can tell the start and end points apart + result.boxInited = true; + + // but don't actually enable the box until the cursor moves + if(!result.boxEnabled && ( + result.boxStart[0] !== result.boxEnd[0] || + result.boxStart[1] !== result.boxEnd[1]) + ) { + result.boxEnabled = true; + } + + // constrain aspect ratio if the axes require it + var smallDx = Math.abs(result.dragStart[0] - x) < MINZOOM; + var smallDy = Math.abs(result.dragStart[1] - y) < MINZOOM; + if(getSubplotConstraint() && !(smallDx && smallDy)) { + dx = result.boxEnd[0] - result.boxStart[0]; + dy = result.boxEnd[1] - result.boxStart[1]; + var dydx = (dataBox[3] - dataBox[1]) / (dataBox[2] - dataBox[0]); + + if(Math.abs(dx * dydx) > Math.abs(dy)) { + result.boxEnd[1] = result.boxStart[1] + + Math.abs(dx) * dydx * (dy >= 0 ? 1 : -1); + + // gl-select-box clips to the plot area bounds, + // which breaks the axis constraint, so don't allow + // this box to go out of bounds + if(result.boxEnd[1] < dataBox[1]) { + result.boxEnd[1] = dataBox[1]; + result.boxEnd[0] = result.boxStart[0] + + (dataBox[1] - result.boxStart[1]) / Math.abs(dydx); + } + else if(result.boxEnd[1] > dataBox[3]) { + result.boxEnd[1] = dataBox[3]; + result.boxEnd[0] = result.boxStart[0] + + (dataBox[3] - result.boxStart[1]) / Math.abs(dydx); + } + } + else { + result.boxEnd[0] = result.boxStart[0] + + Math.abs(dy) / dydx * (dx >= 0 ? 1 : -1); + + if(result.boxEnd[0] < dataBox[0]) { + result.boxEnd[0] = dataBox[0]; + result.boxEnd[1] = result.boxStart[1] + + (dataBox[0] - result.boxStart[0]) * Math.abs(dydx); + } + else if(result.boxEnd[0] > dataBox[2]) { + result.boxEnd[0] = dataBox[2]; + result.boxEnd[1] = result.boxStart[1] + + (dataBox[2] - result.boxStart[0]) * Math.abs(dydx); + } + } + } + // otherwise clamp small changes to the origin so we get 1D zoom + else { + if(smallDx) result.boxEnd[0] = result.boxStart[0]; + if(smallDy) result.boxEnd[1] = result.boxStart[1]; + } + } + else if(result.boxEnabled) { + dx = result.boxStart[0] !== result.boxEnd[0]; + dy = result.boxStart[1] !== result.boxEnd[1]; + if(dx || dy) { + if(dx) { + updateRange(0, result.boxStart[0], result.boxEnd[0]); + scene.xaxis.autorange = false; + } + if(dy) { + updateRange(1, result.boxStart[1], result.boxEnd[1]); + scene.yaxis.autorange = false; + } + scene.relayoutCallback(); + } + else { + scene.glplot.setDirty(); + } + result.boxEnabled = false; + result.boxInited = false; + } + // if box was inited but button released then - reset the box + else if(result.boxInited) { + result.boxInited = false; + } + break; + + case 'pan': + result.boxEnabled = false; + result.boxInited = false; + + if(buttons) { + if(!result.panning) { + result.dragStart[0] = x; + result.dragStart[1] = y; + } + + if(Math.abs(result.dragStart[0] - x) < MINDRAG) x = result.dragStart[0]; + if(Math.abs(result.dragStart[1] - y) < MINDRAG) y = result.dragStart[1]; + + dx = (lastX - x) * (dataBox[2] - dataBox[0]) / + (plot.viewBox[2] - plot.viewBox[0]); + dy = (lastY - y) * (dataBox[3] - dataBox[1]) / + (plot.viewBox[3] - plot.viewBox[1]); + + dataBox[0] += dx; + dataBox[2] += dx; + dataBox[1] += dy; + dataBox[3] += dy; + + scene.setRanges(dataBox); + + result.panning = true; + result.lastInputTime = Date.now(); + unSetAutoRange(); + scene.cameraChanged(); + scene.handleAnnotations(); + } + else if(result.panning) { + result.panning = false; + scene.relayoutCallback(); + } + break; + } + + result.lastPos[0] = x; + result.lastPos[1] = y; + } + + result.wheelListener = mouseWheel(element, function(dx, dy) { + if(!scene.scrollZoom) return false; + + var dataBox = scene.calcDataBox(), + viewBox = plot.viewBox; + + var lastX = result.lastPos[0], + lastY = result.lastPos[1]; + + var scale = Math.exp(5.0 * dy / (viewBox[3] - viewBox[1])); + + var cx = lastX / + (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) + + dataBox[0]; + var cy = lastY / + (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) + + dataBox[1]; + + dataBox[0] = (dataBox[0] - cx) * scale + cx; + dataBox[2] = (dataBox[2] - cx) * scale + cx; + dataBox[1] = (dataBox[1] - cy) * scale + cy; + dataBox[3] = (dataBox[3] - cy) * scale + cy; + + scene.setRanges(dataBox); + + result.lastInputTime = Date.now(); + unSetAutoRange(); + scene.cameraChanged(); + scene.handleAnnotations(); + scene.relayoutCallback(); + + return true; + }, true); + + return result; +} + +},{"../cartesian/constants":750,"has-passive-events":394,"mouse-change":418,"mouse-event-offset":419,"mouse-wheel":421}],783:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Axes = _dereq_('../cartesian/axes'); + +var convertHTMLToUnicode = _dereq_('../../lib/html2unicode'); +var str2RGBArray = _dereq_('../../lib/str2rgbarray'); + +function Axes2DOptions(scene) { + this.scene = scene; + this.gl = scene.gl; + this.pixelRatio = scene.pixelRatio; + + this.screenBox = [0, 0, 1, 1]; + this.viewBox = [0, 0, 1, 1]; + this.dataBox = [-1, -1, 1, 1]; + + this.borderLineEnable = [false, false, false, false]; + this.borderLineWidth = [1, 1, 1, 1]; + this.borderLineColor = [ + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1] + ]; + + this.ticks = [[], []]; + this.tickEnable = [true, true, false, false]; + this.tickPad = [15, 15, 15, 15]; + this.tickAngle = [0, 0, 0, 0]; + this.tickColor = [ + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1] + ]; + this.tickMarkLength = [0, 0, 0, 0]; + this.tickMarkWidth = [0, 0, 0, 0]; + this.tickMarkColor = [ + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1] + ]; + + this.labels = ['x', 'y']; + this.labelEnable = [true, true, false, false]; + this.labelAngle = [0, Math.PI / 2, 0, 3.0 * Math.PI / 2]; + this.labelPad = [15, 15, 15, 15]; + this.labelSize = [12, 12]; + this.labelFont = ['sans-serif', 'sans-serif']; + this.labelColor = [ + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1] + ]; + + this.title = ''; + this.titleEnable = true; + this.titleCenter = [0, 0, 0, 0]; + this.titleAngle = 0; + this.titleColor = [0, 0, 0, 1]; + this.titleFont = 'sans-serif'; + this.titleSize = 18; + + this.gridLineEnable = [true, true]; + this.gridLineColor = [ + [0, 0, 0, 0.5], + [0, 0, 0, 0.5] + ]; + this.gridLineWidth = [1, 1]; + + this.zeroLineEnable = [true, true]; + this.zeroLineWidth = [1, 1]; + this.zeroLineColor = [ + [0, 0, 0, 1], + [0, 0, 0, 1] + ]; + + this.borderColor = false; + this.backgroundColor = [0, 0, 0, 0]; + + this.static = this.scene.staticPlot; +} + +var proto = Axes2DOptions.prototype; + +var AXES = ['xaxis', 'yaxis']; + +proto.merge = function(options) { + + // titles are rendered in SVG + this.titleEnable = false; + this.backgroundColor = str2RGBArray(options.plot_bgcolor); + + var axisName, ax, axTitle, axMirror; + var hasAxisInDfltPos, hasAxisInAltrPos, hasSharedAxis, mirrorLines, mirrorTicks; + var i, j; + + for(i = 0; i < 2; ++i) { + axisName = AXES[i]; + var axisLetter = axisName.charAt(0); + + // get options relevant to this subplot, + // '_name' is e.g. xaxis, xaxis2, yaxis, yaxis4 ... + ax = options[this.scene[axisName]._name]; + + axTitle = ax.title === this.scene.fullLayout._dfltTitle[axisLetter] ? '' : ax.title; + + for(j = 0; j <= 2; j += 2) { + this.labelEnable[i + j] = false; + this.labels[i + j] = convertHTMLToUnicode(axTitle); + this.labelColor[i + j] = str2RGBArray(ax.titlefont.color); + this.labelFont[i + j] = ax.titlefont.family; + this.labelSize[i + j] = ax.titlefont.size; + this.labelPad[i + j] = this.getLabelPad(axisName, ax); + + this.tickEnable[i + j] = false; + this.tickColor[i + j] = str2RGBArray((ax.tickfont || {}).color); + this.tickAngle[i + j] = (ax.tickangle === 'auto') ? + 0 : + Math.PI * -ax.tickangle / 180; + this.tickPad[i + j] = this.getTickPad(ax); + + this.tickMarkLength[i + j] = 0; + this.tickMarkWidth[i + j] = ax.tickwidth || 0; + this.tickMarkColor[i + j] = str2RGBArray(ax.tickcolor); + + this.borderLineEnable[i + j] = false; + this.borderLineColor[i + j] = str2RGBArray(ax.linecolor); + this.borderLineWidth[i + j] = ax.linewidth || 0; + } + + hasSharedAxis = this.hasSharedAxis(ax); + hasAxisInDfltPos = this.hasAxisInDfltPos(axisName, ax) && !hasSharedAxis; + hasAxisInAltrPos = this.hasAxisInAltrPos(axisName, ax) && !hasSharedAxis; + + axMirror = ax.mirror || false; + mirrorLines = hasSharedAxis ? + (String(axMirror).indexOf('all') !== -1) : // 'all' or 'allticks' + !!axMirror; // all but false + mirrorTicks = hasSharedAxis ? + (axMirror === 'allticks') : + (String(axMirror).indexOf('ticks') !== -1); // 'ticks' or 'allticks' + + // Axis titles and tick labels can only appear of one side of the scene + // and are never show on subplots that share existing axes. + + if(hasAxisInDfltPos) this.labelEnable[i] = true; + else if(hasAxisInAltrPos) this.labelEnable[i + 2] = true; + + if(hasAxisInDfltPos) this.tickEnable[i] = ax.showticklabels; + else if(hasAxisInAltrPos) this.tickEnable[i + 2] = ax.showticklabels; + + // Grid lines and ticks can appear on both sides of the scene + // and can appear on subplot that share existing axes via `ax.mirror`. + + if(hasAxisInDfltPos || mirrorLines) this.borderLineEnable[i] = ax.showline; + if(hasAxisInAltrPos || mirrorLines) this.borderLineEnable[i + 2] = ax.showline; + + if(hasAxisInDfltPos || mirrorTicks) this.tickMarkLength[i] = this.getTickMarkLength(ax); + if(hasAxisInAltrPos || mirrorTicks) this.tickMarkLength[i + 2] = this.getTickMarkLength(ax); + + this.gridLineEnable[i] = ax.showgrid; + this.gridLineColor[i] = str2RGBArray(ax.gridcolor); + this.gridLineWidth[i] = ax.gridwidth; + + this.zeroLineEnable[i] = ax.zeroline; + this.zeroLineColor[i] = str2RGBArray(ax.zerolinecolor); + this.zeroLineWidth[i] = ax.zerolinewidth; + } +}; + +// is an axis shared with an already-drawn subplot ? +proto.hasSharedAxis = function(ax) { + var scene = this.scene; + var subplotIds = scene.fullLayout._subplots.gl2d; + var list = Axes.findSubplotsWithAxis(subplotIds, ax); + + // if index === 0, then the subplot is already drawn as subplots + // are drawn in order. + return (list.indexOf(scene.id) !== 0); +}; + +// has an axis in default position (i.e. bottom/left) ? +proto.hasAxisInDfltPos = function(axisName, ax) { + var axSide = ax.side; + + if(axisName === 'xaxis') return (axSide === 'bottom'); + else if(axisName === 'yaxis') return (axSide === 'left'); +}; + +// has an axis in alternate position (i.e. top/right) ? +proto.hasAxisInAltrPos = function(axisName, ax) { + var axSide = ax.side; + + if(axisName === 'xaxis') return (axSide === 'top'); + else if(axisName === 'yaxis') return (axSide === 'right'); +}; + +proto.getLabelPad = function(axisName, ax) { + var offsetBase = 1.5, + fontSize = ax.titlefont.size, + showticklabels = ax.showticklabels; + + if(axisName === 'xaxis') { + return (ax.side === 'top') ? + -10 + fontSize * (offsetBase + (showticklabels ? 1 : 0)) : + -10 + fontSize * (offsetBase + (showticklabels ? 0.5 : 0)); + } + else if(axisName === 'yaxis') { + return (ax.side === 'right') ? + 10 + fontSize * (offsetBase + (showticklabels ? 1 : 0.5)) : + 10 + fontSize * (offsetBase + (showticklabels ? 0.5 : 0)); + } +}; + +proto.getTickPad = function(ax) { + return (ax.ticks === 'outside') ? 10 + ax.ticklen : 15; +}; + +proto.getTickMarkLength = function(ax) { + if(!ax.ticks) return 0; + + var ticklen = ax.ticklen; + + return (ax.ticks === 'inside') ? -ticklen : ticklen; +}; + + +function createAxes2D(scene) { + return new Axes2DOptions(scene); +} + +module.exports = createAxes2D; + +},{"../../lib/html2unicode":694,"../../lib/str2rgbarray":719,"../cartesian/axes":744}],784:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var Scene2D = _dereq_('./scene2d'); +var layoutGlobalAttrs = _dereq_('../layout_attributes'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); +var constants = _dereq_('../cartesian/constants'); +var Cartesian = _dereq_('../cartesian'); +var fxAttrs = _dereq_('../../components/fx/layout_attributes'); +var getSubplotData = _dereq_('../get_data').getSubplotData; + +exports.name = 'gl2d'; + +exports.attr = ['xaxis', 'yaxis']; + +exports.idRoot = ['x', 'y']; + +exports.idRegex = constants.idRegex; + +exports.attrRegex = constants.attrRegex; + +exports.attributes = _dereq_('../cartesian/attributes'); + +exports.supplyLayoutDefaults = function(layoutIn, layoutOut, fullData) { + if(!layoutOut._has('cartesian')) { + Cartesian.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } +}; + +// gl2d uses svg axis attributes verbatim, but overrides editType +// this could potentially be just `layoutAttributes` but it would +// still need special handling somewhere to give it precedence over +// the svg version when both are in use on one plot +exports.layoutAttrOverrides = overrideAll(Cartesian.layoutAttributes, 'plot', 'from-root'); + +// similar overrides for base plot attributes (and those added by components) +exports.baseLayoutAttrOverrides = overrideAll({ + plot_bgcolor: layoutGlobalAttrs.plot_bgcolor, + hoverlabel: fxAttrs.hoverlabel + // dragmode needs calc but only when transitioning TO lasso or select + // so for now it's left inside _relayout + // dragmode: fxAttrs.dragmode +}, 'plot', 'nested'); + +exports.plot = function plotGl2d(gd) { + var fullLayout = gd._fullLayout; + var fullData = gd._fullData; + var subplotIds = fullLayout._subplots.gl2d; + + for(var i = 0; i < subplotIds.length; i++) { + var subplotId = subplotIds[i], + subplotObj = fullLayout._plots[subplotId], + fullSubplotData = getSubplotData(fullData, 'gl2d', subplotId); + + // ref. to corresp. Scene instance + var scene = subplotObj._scene2d; + + // If Scene is not instantiated, create one! + if(scene === undefined) { + scene = new Scene2D({ + id: subplotId, + graphDiv: gd, + container: gd.querySelector('.gl-container'), + staticPlot: gd._context.staticPlot, + plotGlPixelRatio: gd._context.plotGlPixelRatio + }, + fullLayout + ); + + // set ref to Scene instance + subplotObj._scene2d = scene; + } + + scene.plot(fullSubplotData, gd.calcdata, fullLayout, gd.layout); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldSceneKeys = oldFullLayout._subplots.gl2d || []; + + for(var i = 0; i < oldSceneKeys.length; i++) { + var id = oldSceneKeys[i], + oldSubplot = oldFullLayout._plots[id]; + + // old subplot wasn't gl2d; nothing to do + if(!oldSubplot._scene2d) continue; + + // if no traces are present, delete gl2d subplot + var subplotData = getSubplotData(newFullData, 'gl2d', id); + if(subplotData.length === 0) { + oldSubplot._scene2d.destroy(); + delete oldFullLayout._plots[id]; + } + } + + // since we use cartesian interactions, do cartesian clean + Cartesian.clean.apply(this, arguments); +}; + +exports.drawFramework = function(gd) { + if(!gd._context.staticPlot) { + Cartesian.drawFramework(gd); + } +}; + +exports.toSVG = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots.gl2d; + + for(var i = 0; i < subplotIds.length; i++) { + var subplot = fullLayout._plots[subplotIds[i]], + scene = subplot._scene2d; + + var imageData = scene.toImage('png'); + var image = fullLayout._glimages.append('svg:image'); + + image.attr({ + xmlns: xmlnsNamespaces.svg, + 'xlink:href': imageData, + x: 0, + y: 0, + width: '100%', + height: '100%', + preserveAspectRatio: 'none' + }); + + scene.destroy(); + } +}; + +exports.updateFx = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots.gl2d; + + for(var i = 0; i < subplotIds.length; i++) { + var subplotObj = fullLayout._plots[subplotIds[i]]._scene2d; + subplotObj.updateFx(fullLayout.dragmode); + } +}; + +},{"../../components/fx/layout_attributes":613,"../../constants/xmlns_namespaces":674,"../../plot_api/edit_types":727,"../cartesian":756,"../cartesian/attributes":742,"../cartesian/constants":750,"../get_data":781,"../layout_attributes":799,"./scene2d":785}],785:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Fx = _dereq_('../../components/fx'); + +var createPlot2D = _dereq_('gl-plot2d'); +var createSpikes = _dereq_('gl-spikes2d'); +var createSelectBox = _dereq_('gl-select-box'); +var getContext = _dereq_('webgl-context'); + +var createOptions = _dereq_('./convert'); +var createCamera = _dereq_('./camera'); +var convertHTMLToUnicode = _dereq_('../../lib/html2unicode'); +var showNoWebGlMsg = _dereq_('../../lib/show_no_webgl_msg'); +var axisConstraints = _dereq_('../cartesian/constraints'); +var enforceAxisConstraints = axisConstraints.enforce; +var cleanAxisConstraints = axisConstraints.clean; +var doAutoRange = _dereq_('../cartesian/autorange').doAutoRange; + +var AXES = ['xaxis', 'yaxis']; +var STATIC_CANVAS, STATIC_CONTEXT; + +var SUBPLOT_PATTERN = _dereq_('../cartesian/constants').SUBPLOT_PATTERN; + + +function Scene2D(options, fullLayout) { + this.container = options.container; + this.graphDiv = options.graphDiv; + this.pixelRatio = options.plotGlPixelRatio || window.devicePixelRatio; + this.id = options.id; + this.staticPlot = !!options.staticPlot; + this.scrollZoom = this.graphDiv._context.scrollZoom; + + this.fullData = null; + this.updateRefs(fullLayout); + + this.makeFramework(); + if(this.stopped) return; + + // update options + this.glplotOptions = createOptions(this); + this.glplotOptions.merge(fullLayout); + + // create the plot + this.glplot = createPlot2D(this.glplotOptions); + + // create camera + this.camera = createCamera(this); + + // trace set + this.traces = {}; + + // create axes spikes + this.spikes = createSpikes(this.glplot); + + this.selectBox = createSelectBox(this.glplot, { + innerFill: false, + outerFill: true + }); + + // last button state + this.lastButtonState = 0; + + // last pick result + this.pickResult = null; + + // is the mouse over the plot? + // it's OK if this says true when it's not, so long as + // when we get a mouseout we set it to false before handling + this.isMouseOver = true; + + // flag to stop render loop + this.stopped = false; + + // redraw the plot + this.redraw = this.draw.bind(this); + this.redraw(); +} + +module.exports = Scene2D; + +var proto = Scene2D.prototype; + +proto.makeFramework = function() { + + // create canvas and gl context + if(this.staticPlot) { + if(!STATIC_CONTEXT) { + STATIC_CANVAS = document.createElement('canvas'); + + STATIC_CONTEXT = getContext({ + canvas: STATIC_CANVAS, + preserveDrawingBuffer: false, + premultipliedAlpha: true, + antialias: true + }); + + if(!STATIC_CONTEXT) { + throw new Error('Error creating static canvas/context for image server'); + } + } + + this.canvas = STATIC_CANVAS; + this.gl = STATIC_CONTEXT; + } + else { + var liveCanvas = this.container.querySelector('.gl-canvas-focus'); + + var gl = getContext({ + canvas: liveCanvas, + preserveDrawingBuffer: true, + premultipliedAlpha: true + }); + + if(!gl) { + showNoWebGlMsg(this); + this.stopped = true; + return; + } + + this.canvas = liveCanvas; + this.gl = gl; + } + + // position the canvas + var canvas = this.canvas; + + canvas.style.width = '100%'; + canvas.style.height = '100%'; + canvas.style.position = 'absolute'; + canvas.style.top = '0px'; + canvas.style.left = '0px'; + canvas.style['pointer-events'] = 'none'; + + this.updateSize(canvas); + + // disabling user select on the canvas + // sanitizes double-clicks interactions + // ref: https://github.com/plotly/plotly.js/issues/744 + canvas.className += ' user-select-none'; + + // create SVG container for hover text + var svgContainer = this.svgContainer = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'svg'); + svgContainer.style.position = 'absolute'; + svgContainer.style.top = svgContainer.style.left = '0px'; + svgContainer.style.width = svgContainer.style.height = '100%'; + svgContainer.style['z-index'] = 20; + svgContainer.style['pointer-events'] = 'none'; + + // create div to catch the mouse event + var mouseContainer = this.mouseContainer = document.createElement('div'); + mouseContainer.style.position = 'absolute'; + mouseContainer.style['pointer-events'] = 'auto'; + + this.pickCanvas = this.container.querySelector('.gl-canvas-pick'); + + + // append canvas, hover svg and mouse div to container + var container = this.container; + container.appendChild(svgContainer); + container.appendChild(mouseContainer); + + var self = this; + mouseContainer.addEventListener('mouseout', function() { + self.isMouseOver = false; + self.unhover(); + }); + mouseContainer.addEventListener('mouseover', function() { + self.isMouseOver = true; + }); +}; + +proto.toImage = function(format) { + if(!format) format = 'png'; + + this.stopped = true; + + if(this.staticPlot) this.container.appendChild(STATIC_CANVAS); + + // update canvas size + this.updateSize(this.canvas); + + + // grab context and yank out pixels + var gl = this.glplot.gl, + w = gl.drawingBufferWidth, + h = gl.drawingBufferHeight; + + // force redraw + gl.clearColor(1, 1, 1, 0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + this.glplot.setDirty(); + this.glplot.draw(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + var pixels = new Uint8Array(w * h * 4); + gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + // flip pixels + for(var j = 0, k = h - 1; j < k; ++j, --k) { + for(var i = 0; i < w; ++i) { + for(var l = 0; l < 4; ++l) { + var tmp = pixels[4 * (w * j + i) + l]; + pixels[4 * (w * j + i) + l] = pixels[4 * (w * k + i) + l]; + pixels[4 * (w * k + i) + l] = tmp; + } + } + } + + var canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + + var context = canvas.getContext('2d'); + var imageData = context.createImageData(w, h); + imageData.data.set(pixels); + context.putImageData(imageData, 0, 0); + + var dataURL; + + switch(format) { + case 'jpeg': + dataURL = canvas.toDataURL('image/jpeg'); + break; + case 'webp': + dataURL = canvas.toDataURL('image/webp'); + break; + default: + dataURL = canvas.toDataURL('image/png'); + } + + if(this.staticPlot) this.container.removeChild(STATIC_CANVAS); + + return dataURL; +}; + +proto.updateSize = function(canvas) { + if(!canvas) canvas = this.canvas; + + var pixelRatio = this.pixelRatio, + fullLayout = this.fullLayout; + + var width = fullLayout.width, + height = fullLayout.height, + pixelWidth = Math.ceil(pixelRatio * width) |0, + pixelHeight = Math.ceil(pixelRatio * height) |0; + + // check for resize + if(canvas.width !== pixelWidth || canvas.height !== pixelHeight) { + canvas.width = pixelWidth; + canvas.height = pixelHeight; + } + + return canvas; +}; + +proto.computeTickMarks = function() { + this.xaxis.setScale(); + this.yaxis.setScale(); + + var nextTicks = [ + Axes.calcTicks(this.xaxis), + Axes.calcTicks(this.yaxis) + ]; + + for(var j = 0; j < 2; ++j) { + for(var i = 0; i < nextTicks[j].length; ++i) { + // coercing tick value (may not be a string) to a string + nextTicks[j][i].text = convertHTMLToUnicode(nextTicks[j][i].text + ''); + } + } + + return nextTicks; +}; + +function compareTicks(a, b) { + for(var i = 0; i < 2; ++i) { + var aticks = a[i], + bticks = b[i]; + + if(aticks.length !== bticks.length) return true; + + for(var j = 0; j < aticks.length; ++j) { + if(aticks[j].x !== bticks[j].x) return true; + } + } + + return false; +} + +proto.updateRefs = function(newFullLayout) { + this.fullLayout = newFullLayout; + + var spmatch = this.id.match(SUBPLOT_PATTERN); + var xaxisName = 'xaxis' + spmatch[1]; + var yaxisName = 'yaxis' + spmatch[2]; + + this.xaxis = this.fullLayout[xaxisName]; + this.yaxis = this.fullLayout[yaxisName]; +}; + +proto.relayoutCallback = function() { + var graphDiv = this.graphDiv, + xaxis = this.xaxis, + yaxis = this.yaxis, + layout = graphDiv.layout; + + // update user layout + layout.xaxis.autorange = xaxis.autorange; + layout.xaxis.range = xaxis.range.slice(0); + layout.yaxis.autorange = yaxis.autorange; + layout.yaxis.range = yaxis.range.slice(0); + + // make a meaningful value to be passed on to the possible 'plotly_relayout' subscriber(s) + // scene.camera has no many useful projection or scale information + // helps determine which one is the latest input (if async) + var update = { + lastInputTime: this.camera.lastInputTime + }; + + update[xaxis._name] = xaxis.range.slice(0); + update[yaxis._name] = yaxis.range.slice(0); + + graphDiv.emit('plotly_relayout', update); +}; + +proto.cameraChanged = function() { + var camera = this.camera; + + this.glplot.setDataBox(this.calcDataBox()); + + var nextTicks = this.computeTickMarks(); + var curTicks = this.glplotOptions.ticks; + + if(compareTicks(nextTicks, curTicks)) { + this.glplotOptions.ticks = nextTicks; + this.glplotOptions.dataBox = camera.dataBox; + this.glplot.update(this.glplotOptions); + this.handleAnnotations(); + } +}; + +proto.handleAnnotations = function() { + var gd = this.graphDiv, + annotations = this.fullLayout.annotations; + + for(var i = 0; i < annotations.length; i++) { + var ann = annotations[i]; + + if(ann.xref === this.xaxis._id && ann.yref === this.yaxis._id) { + Registry.getComponentMethod('annotations', 'drawOne')(gd, i); + } + } +}; + +proto.destroy = function() { + if(!this.glplot) return; + + var traces = this.traces; + + if(traces) { + Object.keys(traces).map(function(key) { + traces[key].dispose(); + delete traces[key]; + }); + } + + this.glplot.dispose(); + + this.container.removeChild(this.svgContainer); + this.container.removeChild(this.mouseContainer); + + this.fullData = null; + this.glplot = null; + this.stopped = true; + this.camera.mouseListener.enabled = false; + this.mouseContainer.removeEventListener('wheel', this.camera.wheelListener); + this.camera = null; +}; + +proto.plot = function(fullData, calcData, fullLayout) { + var glplot = this.glplot; + + this.updateRefs(fullLayout); + this.xaxis.clearCalc(); + this.yaxis.clearCalc(); + this.updateTraces(fullData, calcData); + this.updateFx(fullLayout.dragmode); + + var width = fullLayout.width, + height = fullLayout.height; + + this.updateSize(this.canvas); + + var options = this.glplotOptions; + options.merge(fullLayout); + options.screenBox = [0, 0, width, height]; + + var mockGraphDiv = {_fullLayout: { + _axisConstraintGroups: this.graphDiv._fullLayout._axisConstraintGroups, + xaxis: this.xaxis, + yaxis: this.yaxis + }}; + + cleanAxisConstraints(mockGraphDiv, this.xaxis); + cleanAxisConstraints(mockGraphDiv, this.yaxis); + + var size = fullLayout._size, + domainX = this.xaxis.domain, + domainY = this.yaxis.domain; + + options.viewBox = [ + size.l + domainX[0] * size.w, + size.b + domainY[0] * size.h, + (width - size.r) - (1 - domainX[1]) * size.w, + (height - size.t) - (1 - domainY[1]) * size.h + ]; + + this.mouseContainer.style.width = size.w * (domainX[1] - domainX[0]) + 'px'; + this.mouseContainer.style.height = size.h * (domainY[1] - domainY[0]) + 'px'; + this.mouseContainer.height = size.h * (domainY[1] - domainY[0]); + this.mouseContainer.style.left = size.l + domainX[0] * size.w + 'px'; + this.mouseContainer.style.top = size.t + (1 - domainY[1]) * size.h + 'px'; + + var ax, i; + + for(i = 0; i < 2; ++i) { + ax = this[AXES[i]]; + ax._length = options.viewBox[i + 2] - options.viewBox[i]; + + doAutoRange(this.graphDiv, ax); + ax.setScale(); + } + + enforceAxisConstraints(mockGraphDiv); + + options.ticks = this.computeTickMarks(); + + options.dataBox = this.calcDataBox(); + + options.merge(fullLayout); + glplot.update(options); + + // force redraw so that promise is returned when rendering is completed + this.glplot.draw(); +}; + +proto.calcDataBox = function() { + var xaxis = this.xaxis, + yaxis = this.yaxis, + xrange = xaxis.range, + yrange = yaxis.range, + xr2l = xaxis.r2l, + yr2l = yaxis.r2l; + + return [xr2l(xrange[0]), yr2l(yrange[0]), xr2l(xrange[1]), yr2l(yrange[1])]; +}; + +proto.setRanges = function(dataBox) { + var xaxis = this.xaxis, + yaxis = this.yaxis, + xl2r = xaxis.l2r, + yl2r = yaxis.l2r; + + xaxis.range = [xl2r(dataBox[0]), xl2r(dataBox[2])]; + yaxis.range = [yl2r(dataBox[1]), yl2r(dataBox[3])]; +}; + +proto.updateTraces = function(fullData, calcData) { + var traceIds = Object.keys(this.traces); + var i, j, fullTrace; + + this.fullData = fullData; + + // remove empty traces + trace_id_loop: + for(i = 0; i < traceIds.length; i++) { + var oldUid = traceIds[i], + oldTrace = this.traces[oldUid]; + + for(j = 0; j < fullData.length; j++) { + fullTrace = fullData[j]; + + if(fullTrace.uid === oldUid && fullTrace.type === oldTrace.type) { + continue trace_id_loop; + } + } + + oldTrace.dispose(); + delete this.traces[oldUid]; + } + + // update / create trace objects + for(i = 0; i < fullData.length; i++) { + fullTrace = fullData[i]; + var calcTrace = calcData[i], + traceObj = this.traces[fullTrace.uid]; + + if(traceObj) traceObj.update(fullTrace, calcTrace); + else { + traceObj = fullTrace._module.plot(this, fullTrace, calcTrace); + this.traces[fullTrace.uid] = traceObj; + } + } + + // order object per traces + this.glplot.objects.sort(function(a, b) { + return a._trace.index - b._trace.index; + }); +}; + +proto.updateFx = function(dragmode) { + // switch to svg interactions in lasso/select mode + if(dragmode === 'lasso' || dragmode === 'select') { + this.pickCanvas.style['pointer-events'] = 'none'; + this.mouseContainer.style['pointer-events'] = 'none'; + } else { + this.pickCanvas.style['pointer-events'] = 'auto'; + this.mouseContainer.style['pointer-events'] = 'auto'; + } + + // set proper cursor + if(dragmode === 'pan') { + this.mouseContainer.style.cursor = 'move'; + } + else if(dragmode === 'zoom') { + this.mouseContainer.style.cursor = 'crosshair'; + } + else { + this.mouseContainer.style.cursor = null; + } +}; + +proto.emitPointAction = function(nextSelection, eventType) { + var uid = nextSelection.trace.uid; + var ptNumber = nextSelection.pointIndex; + var trace; + + for(var i = 0; i < this.fullData.length; i++) { + if(this.fullData[i].uid === uid) { + trace = this.fullData[i]; + } + } + + var pointData = { + x: nextSelection.traceCoord[0], + y: nextSelection.traceCoord[1], + curveNumber: trace.index, + pointNumber: ptNumber, + data: trace._input, + fullData: this.fullData, + xaxis: this.xaxis, + yaxis: this.yaxis + }; + + Fx.appendArrayPointValue(pointData, trace, ptNumber); + + this.graphDiv.emit(eventType, {points: [pointData]}); +}; + +proto.draw = function() { + if(this.stopped) return; + + requestAnimationFrame(this.redraw); + + var glplot = this.glplot, + camera = this.camera, + mouseListener = camera.mouseListener, + mouseUp = this.lastButtonState === 1 && mouseListener.buttons === 0, + fullLayout = this.fullLayout; + + this.lastButtonState = mouseListener.buttons; + + this.cameraChanged(); + + var x = mouseListener.x * glplot.pixelRatio; + var y = this.canvas.height - glplot.pixelRatio * mouseListener.y; + + var result; + + if(camera.boxEnabled && fullLayout.dragmode === 'zoom') { + this.selectBox.enabled = true; + + var selectBox = this.selectBox.selectBox = [ + Math.min(camera.boxStart[0], camera.boxEnd[0]), + Math.min(camera.boxStart[1], camera.boxEnd[1]), + Math.max(camera.boxStart[0], camera.boxEnd[0]), + Math.max(camera.boxStart[1], camera.boxEnd[1]) + ]; + + // 1D zoom + for(var i = 0; i < 2; i++) { + if(camera.boxStart[i] === camera.boxEnd[i]) { + selectBox[i] = glplot.dataBox[i]; + selectBox[i + 2] = glplot.dataBox[i + 2]; + } + } + + glplot.setDirty(); + } + else if(!camera.panning && this.isMouseOver) { + this.selectBox.enabled = false; + + var size = fullLayout._size, + domainX = this.xaxis.domain, + domainY = this.yaxis.domain; + + result = glplot.pick( + (x / glplot.pixelRatio) + size.l + domainX[0] * size.w, + (y / glplot.pixelRatio) - (size.t + (1 - domainY[1]) * size.h) + ); + + var nextSelection = result && result.object._trace.handlePick(result); + + if(nextSelection && mouseUp) { + this.emitPointAction(nextSelection, 'plotly_click'); + } + + if(result && result.object._trace.hoverinfo !== 'skip' && fullLayout.hovermode) { + + if(nextSelection && ( + !this.lastPickResult || + this.lastPickResult.traceUid !== nextSelection.trace.uid || + this.lastPickResult.dataCoord[0] !== nextSelection.dataCoord[0] || + this.lastPickResult.dataCoord[1] !== nextSelection.dataCoord[1]) + ) { + var selection = nextSelection; + + this.lastPickResult = { + traceUid: nextSelection.trace ? nextSelection.trace.uid : null, + dataCoord: nextSelection.dataCoord.slice() + }; + this.spikes.update({ center: result.dataCoord }); + + selection.screenCoord = [ + ((glplot.viewBox[2] - glplot.viewBox[0]) * + (result.dataCoord[0] - glplot.dataBox[0]) / + (glplot.dataBox[2] - glplot.dataBox[0]) + glplot.viewBox[0]) / + glplot.pixelRatio, + (this.canvas.height - (glplot.viewBox[3] - glplot.viewBox[1]) * + (result.dataCoord[1] - glplot.dataBox[1]) / + (glplot.dataBox[3] - glplot.dataBox[1]) - glplot.viewBox[1]) / + glplot.pixelRatio + ]; + + // this needs to happen before the next block that deletes traceCoord data + // also it's important to copy, otherwise data is lost by the time event data is read + this.emitPointAction(nextSelection, 'plotly_hover'); + + var trace = this.fullData[selection.trace.index] || {}; + var ptNumber = selection.pointIndex; + var hoverinfo = Fx.castHoverinfo(trace, fullLayout, ptNumber); + + if(hoverinfo && hoverinfo !== 'all') { + var parts = hoverinfo.split('+'); + if(parts.indexOf('x') === -1) selection.traceCoord[0] = undefined; + if(parts.indexOf('y') === -1) selection.traceCoord[1] = undefined; + if(parts.indexOf('z') === -1) selection.traceCoord[2] = undefined; + if(parts.indexOf('text') === -1) selection.textLabel = undefined; + if(parts.indexOf('name') === -1) selection.name = undefined; + } + + Fx.loneHover({ + x: selection.screenCoord[0], + y: selection.screenCoord[1], + xLabel: this.hoverFormatter('xaxis', selection.traceCoord[0]), + yLabel: this.hoverFormatter('yaxis', selection.traceCoord[1]), + zLabel: selection.traceCoord[2], + text: selection.textLabel, + name: selection.name, + color: Fx.castHoverOption(trace, ptNumber, 'bgcolor') || selection.color, + borderColor: Fx.castHoverOption(trace, ptNumber, 'bordercolor'), + fontFamily: Fx.castHoverOption(trace, ptNumber, 'font.family'), + fontSize: Fx.castHoverOption(trace, ptNumber, 'font.size'), + fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color') + }, { + container: this.svgContainer, + gd: this.graphDiv + }); + } + } + } + + // Remove hover effects if we're not over a point OR + // if we're zooming or panning (in which case result is not set) + if(!result) { + this.unhover(); + } + + glplot.draw(); +}; + +proto.unhover = function() { + if(this.lastPickResult) { + this.spikes.update({}); + this.lastPickResult = null; + this.graphDiv.emit('plotly_unhover'); + Fx.loneUnhover(this.svgContainer); + } +}; + +proto.hoverFormatter = function(axisName, val) { + if(val === undefined) return undefined; + + var axis = this[axisName]; + return Axes.tickText(axis, axis.c2l(val), 'hover').text; +}; + +},{"../../components/fx":612,"../../lib/html2unicode":694,"../../lib/show_no_webgl_msg":717,"../../plots/cartesian/axes":744,"../../registry":827,"../cartesian/autorange":743,"../cartesian/constants":750,"../cartesian/constraints":752,"./camera":782,"./convert":783,"gl-plot2d":275,"gl-select-box":286,"gl-spikes2d":295,"webgl-context":533}],786:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = createCamera; + +var now = _dereq_('right-now'); +var createView = _dereq_('3d-view'); +var mouseChange = _dereq_('mouse-change'); +var mouseWheel = _dereq_('mouse-wheel'); +var mouseOffset = _dereq_('mouse-event-offset'); +var supportsPassive = _dereq_('has-passive-events'); + +function createCamera(element, options) { + element = element || document.body; + options = options || {}; + + var limits = [ 0.01, Infinity ]; + if('distanceLimits' in options) { + limits[0] = options.distanceLimits[0]; + limits[1] = options.distanceLimits[1]; + } + if('zoomMin' in options) { + limits[0] = options.zoomMin; + } + if('zoomMax' in options) { + limits[1] = options.zoomMax; + } + + var view = createView({ + center: options.center || [0, 0, 0], + up: options.up || [0, 1, 0], + eye: options.eye || [0, 0, 10], + mode: options.mode || 'orbit', + distanceLimits: limits + }); + + var pmatrix = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var distance = 0.0; + var width = element.clientWidth; + var height = element.clientHeight; + + var camera = { + keyBindingMode: 'rotate', + view: view, + element: element, + delay: options.delay || 16, + rotateSpeed: options.rotateSpeed || 1, + zoomSpeed: options.zoomSpeed || 1, + translateSpeed: options.translateSpeed || 1, + flipX: !!options.flipX, + flipY: !!options.flipY, + modes: view.modes, + tick: function() { + var t = now(); + var delay = this.delay; + var ctime = t - 2 * delay; + view.idle(t - delay); + view.recalcMatrix(ctime); + view.flush(t - (100 + delay * 2)); + var allEqual = true; + var matrix = view.computedMatrix; + for(var i = 0; i < 16; ++i) { + allEqual = allEqual && (pmatrix[i] === matrix[i]); + pmatrix[i] = matrix[i]; + } + var sizeChanged = + element.clientWidth === width && + element.clientHeight === height; + width = element.clientWidth; + height = element.clientHeight; + if(allEqual) return !sizeChanged; + distance = Math.exp(view.computedRadius[0]); + return true; + }, + lookAt: function(center, eye, up) { + view.lookAt(view.lastT(), center, eye, up); + }, + rotate: function(pitch, yaw, roll) { + view.rotate(view.lastT(), pitch, yaw, roll); + }, + pan: function(dx, dy, dz) { + view.pan(view.lastT(), dx, dy, dz); + }, + translate: function(dx, dy, dz) { + view.translate(view.lastT(), dx, dy, dz); + } + }; + + Object.defineProperties(camera, { + matrix: { + get: function() { + return view.computedMatrix; + }, + set: function(mat) { + view.setMatrix(view.lastT(), mat); + return view.computedMatrix; + }, + enumerable: true + }, + mode: { + get: function() { + return view.getMode(); + }, + set: function(mode) { + var curUp = view.computedUp.slice(); + var curEye = view.computedEye.slice(); + var curCenter = view.computedCenter.slice(); + view.setMode(mode); + if(mode === 'turntable') { + // Hacky time warping stuff to generate smooth animation + var t0 = now(); + view._active.lookAt(t0, curEye, curCenter, curUp); + view._active.lookAt(t0 + 500, curEye, curCenter, [0, 0, 1]); + view._active.flush(t0); + } + return view.getMode(); + }, + enumerable: true + }, + center: { + get: function() { + return view.computedCenter; + }, + set: function(ncenter) { + view.lookAt(view.lastT(), null, ncenter); + return view.computedCenter; + }, + enumerable: true + }, + eye: { + get: function() { + return view.computedEye; + }, + set: function(neye) { + view.lookAt(view.lastT(), neye); + return view.computedEye; + }, + enumerable: true + }, + up: { + get: function() { + return view.computedUp; + }, + set: function(nup) { + view.lookAt(view.lastT(), null, null, nup); + return view.computedUp; + }, + enumerable: true + }, + distance: { + get: function() { + return distance; + }, + set: function(d) { + view.setDistance(view.lastT(), d); + return d; + }, + enumerable: true + }, + distanceLimits: { + get: function() { + return view.getDistanceLimits(limits); + }, + set: function(v) { + view.setDistanceLimits(v); + return v; + }, + enumerable: true + } + }); + + element.addEventListener('contextmenu', function(ev) { + ev.preventDefault(); + return false; + }); + + var lastX = 0, lastY = 0, lastMods = {shift: false, control: false, alt: false, meta: false}; + camera.mouseListener = mouseChange(element, handleInteraction); + + // enable simple touch interactions + element.addEventListener('touchstart', function(ev) { + var xy = mouseOffset(ev.changedTouches[0], element); + handleInteraction(0, xy[0], xy[1], lastMods); + handleInteraction(1, xy[0], xy[1], lastMods); + + ev.preventDefault(); + }, supportsPassive ? {passive: false} : false); + element.addEventListener('touchmove', function(ev) { + var xy = mouseOffset(ev.changedTouches[0], element); + handleInteraction(1, xy[0], xy[1], lastMods); + + ev.preventDefault(); + }, supportsPassive ? {passive: false} : false); + element.addEventListener('touchend', function(ev) { + handleInteraction(0, lastX, lastY, lastMods); + + ev.preventDefault(); + }, supportsPassive ? {passive: false} : false); + + function handleInteraction(buttons, x, y, mods) { + var keyBindingMode = camera.keyBindingMode; + + if(keyBindingMode === false) return; + + var rotate = keyBindingMode === 'rotate'; + var pan = keyBindingMode === 'pan'; + var zoom = keyBindingMode === 'zoom'; + + var ctrl = !!mods.control; + var alt = !!mods.alt; + var shift = !!mods.shift; + var left = !!(buttons & 1); + var right = !!(buttons & 2); + var middle = !!(buttons & 4); + + var scale = 1.0 / element.clientHeight; + var dx = scale * (x - lastX); + var dy = scale * (y - lastY); + + var flipX = camera.flipX ? 1 : -1; + var flipY = camera.flipY ? 1 : -1; + + var t = now(); + + var drot = Math.PI * camera.rotateSpeed; + + if((rotate && left && !ctrl && !alt && !shift) || (left && !ctrl && !alt && shift)) { + // Rotate + view.rotate(t, flipX * drot * dx, -flipY * drot * dy, 0); + } + + if((pan && left && !ctrl && !alt && !shift) || right || (left && ctrl && !alt && !shift)) { + // Pan + view.pan(t, -camera.translateSpeed * dx * distance, camera.translateSpeed * dy * distance, 0); + } + + if((zoom && left && !ctrl && !alt && !shift) || middle || (left && !ctrl && alt && !shift)) { + // Zoom + var kzoom = -camera.zoomSpeed * dy / window.innerHeight * (t - view.lastT()) * 100; + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)); + } + + lastX = x; + lastY = y; + lastMods = mods; + + return true; + } + + camera.wheelListener = mouseWheel(element, function(dx, dy) { + if(camera.keyBindingMode === false) return; + + var flipX = camera.flipX ? 1 : -1; + var flipY = camera.flipY ? 1 : -1; + var t = now(); + if(Math.abs(dx) > Math.abs(dy)) { + view.rotate(t, 0, 0, -dx * flipX * Math.PI * camera.rotateSpeed / window.innerWidth); + } else { + var kzoom = -camera.zoomSpeed * flipY * dy / window.innerHeight * (t - view.lastT()) / 20.0; + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)); + } + }, true); + + return camera; +} + +},{"3d-view":45,"has-passive-events":394,"mouse-change":418,"mouse-event-offset":419,"mouse-wheel":421,"right-now":480}],787:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var fxAttrs = _dereq_('../../components/fx/layout_attributes'); + +var Scene = _dereq_('./scene'); +var getSubplotData = _dereq_('../get_data').getSubplotData; +var Lib = _dereq_('../../lib'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +var GL3D = 'gl3d'; +var SCENE = 'scene'; + + +exports.name = GL3D; + +exports.attr = SCENE; + +exports.idRoot = SCENE; + +exports.idRegex = exports.attrRegex = Lib.counterRegex('scene'); + +exports.attributes = _dereq_('./layout/attributes'); + +exports.layoutAttributes = _dereq_('./layout/layout_attributes'); + +exports.baseLayoutAttrOverrides = overrideAll({ + hoverlabel: fxAttrs.hoverlabel +}, 'plot', 'nested'); + +exports.supplyLayoutDefaults = _dereq_('./layout/defaults'); + +exports.plot = function plotGl3d(gd) { + var fullLayout = gd._fullLayout; + var fullData = gd._fullData; + var sceneIds = fullLayout._subplots[GL3D]; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i], + fullSceneData = getSubplotData(fullData, GL3D, sceneId), + sceneLayout = fullLayout[sceneId], + scene = sceneLayout._scene; + + if(!scene) { + scene = new Scene({ + id: sceneId, + graphDiv: gd, + container: gd.querySelector('.gl-container'), + staticPlot: gd._context.staticPlot, + plotGlPixelRatio: gd._context.plotGlPixelRatio + }, + fullLayout + ); + + // set ref to Scene instance + sceneLayout._scene = scene; + } + + // save 'initial' camera settings for modebar button + if(!scene.cameraInitial) { + scene.cameraInitial = Lib.extendDeep({}, sceneLayout.camera); + } + + scene.plot(fullSceneData, fullLayout, gd.layout); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldSceneKeys = oldFullLayout._subplots[GL3D] || []; + + for(var i = 0; i < oldSceneKeys.length; i++) { + var oldSceneKey = oldSceneKeys[i]; + + if(!newFullLayout[oldSceneKey] && !!oldFullLayout[oldSceneKey]._scene) { + oldFullLayout[oldSceneKey]._scene.destroy(); + + if(oldFullLayout._infolayer) { + oldFullLayout._infolayer + .selectAll('.annotation-' + oldSceneKey) + .remove(); + } + } + } +}; + +exports.toSVG = function(gd) { + var fullLayout = gd._fullLayout; + var sceneIds = fullLayout._subplots[GL3D]; + var size = fullLayout._size; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneLayout = fullLayout[sceneIds[i]]; + var domain = sceneLayout.domain; + var scene = sceneLayout._scene; + + var imageData = scene.toImage('png'); + var image = fullLayout._glimages.append('svg:image'); + + image.attr({ + xmlns: xmlnsNamespaces.svg, + 'xlink:href': imageData, + x: size.l + size.w * domain.x[0], + y: size.t + size.h * (1 - domain.y[1]), + width: size.w * (domain.x[1] - domain.x[0]), + height: size.h * (domain.y[1] - domain.y[0]), + preserveAspectRatio: 'none' + }); + + scene.destroy(); + } +}; + +// clean scene ids, 'scene1' -> 'scene' +exports.cleanId = function cleanId(id) { + if(!id.match(/^scene[0-9]*$/)) return; + + var sceneNum = id.substr(5); + if(sceneNum === '1') sceneNum = ''; + + return SCENE + sceneNum; +}; + +exports.updateFx = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots[GL3D]; + + for(var i = 0; i < subplotIds.length; i++) { + var subplotObj = fullLayout[subplotIds[i]]._scene; + subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode); + } +}; + +},{"../../components/fx/layout_attributes":613,"../../constants/xmlns_namespaces":674,"../../lib":696,"../../plot_api/edit_types":727,"../get_data":781,"./layout/attributes":788,"./layout/defaults":792,"./layout/layout_attributes":793,"./scene":797}],788:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + scene: { + valType: 'subplotid', + + dflt: 'scene', + editType: 'calc+clearAxisTypes', + + } +}; + +},{}],789:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Color = _dereq_('../../../components/color'); +var axesAttrs = _dereq_('../../cartesian/layout_attributes'); +var extendFlat = _dereq_('../../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../../plot_api/edit_types').overrideAll; + +module.exports = overrideAll({ + visible: axesAttrs.visible, + showspikes: { + valType: 'boolean', + + dflt: true, + + }, + spikesides: { + valType: 'boolean', + + dflt: true, + + }, + spikethickness: { + valType: 'number', + + min: 0, + dflt: 2, + + }, + spikecolor: { + valType: 'color', + + dflt: Color.defaultLine, + + }, + showbackground: { + valType: 'boolean', + + dflt: false, + + }, + backgroundcolor: { + valType: 'color', + + dflt: 'rgba(204, 204, 204, 0.5)', + + }, + showaxeslabels: { + valType: 'boolean', + + dflt: true, + + }, + color: axesAttrs.color, + categoryorder: axesAttrs.categoryorder, + categoryarray: axesAttrs.categoryarray, + title: axesAttrs.title, + titlefont: axesAttrs.titlefont, + type: axesAttrs.type, + autorange: axesAttrs.autorange, + rangemode: axesAttrs.rangemode, + range: extendFlat({}, axesAttrs.range, { + items: [ + {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}}, + {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}} + ], + anim: false + }), + // ticks + tickmode: axesAttrs.tickmode, + nticks: axesAttrs.nticks, + tick0: axesAttrs.tick0, + dtick: axesAttrs.dtick, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + ticks: axesAttrs.ticks, + mirror: axesAttrs.mirror, + ticklen: axesAttrs.ticklen, + tickwidth: axesAttrs.tickwidth, + tickcolor: axesAttrs.tickcolor, + showticklabels: axesAttrs.showticklabels, + tickfont: axesAttrs.tickfont, + tickangle: axesAttrs.tickangle, + tickprefix: axesAttrs.tickprefix, + showtickprefix: axesAttrs.showtickprefix, + ticksuffix: axesAttrs.ticksuffix, + showticksuffix: axesAttrs.showticksuffix, + showexponent: axesAttrs.showexponent, + exponentformat: axesAttrs.exponentformat, + separatethousands: axesAttrs.separatethousands, + tickformat: axesAttrs.tickformat, + tickformatstops: axesAttrs.tickformatstops, + hoverformat: axesAttrs.hoverformat, + // lines and grids + showline: axesAttrs.showline, + linecolor: axesAttrs.linecolor, + linewidth: axesAttrs.linewidth, + showgrid: axesAttrs.showgrid, + gridcolor: extendFlat({}, axesAttrs.gridcolor, // shouldn't this be on-par with 2D? + {dflt: 'rgb(204, 204, 204)'}), + gridwidth: axesAttrs.gridwidth, + zeroline: axesAttrs.zeroline, + zerolinecolor: axesAttrs.zerolinecolor, + zerolinewidth: axesAttrs.zerolinewidth +}, 'plot', 'from-root'); + +},{"../../../components/color":570,"../../../lib/extend":685,"../../../plot_api/edit_types":727,"../../cartesian/layout_attributes":757}],790:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var colorMix = _dereq_('tinycolor2').mix; + +var Lib = _dereq_('../../../lib'); +var Template = _dereq_('../../../plot_api/plot_template'); + +var layoutAttributes = _dereq_('./axis_attributes'); +var handleTypeDefaults = _dereq_('../../cartesian/type_defaults'); +var handleAxisDefaults = _dereq_('../../cartesian/axis_defaults'); + +var axesNames = ['xaxis', 'yaxis', 'zaxis']; + +// TODO: hard-coded lightness fraction based on gridline default colors +// that differ from other subplot types. +var gridLightness = 100 * (204 - 0x44) / (255 - 0x44); + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) { + var containerIn, containerOut; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, layoutAttributes, attr, dflt); + } + + for(var j = 0; j < axesNames.length; j++) { + var axName = axesNames[j]; + containerIn = layoutIn[axName] || {}; + + containerOut = Template.newContainer(layoutOut, axName); + containerOut._id = axName[0] + options.scene; + containerOut._name = axName; + + handleTypeDefaults(containerIn, containerOut, coerce, options); + + handleAxisDefaults( + containerIn, + containerOut, + coerce, + { + font: options.font, + letter: axName[0], + data: options.data, + showGrid: true, + bgColor: options.bgColor, + calendar: options.calendar + }, + options.fullLayout); + + coerce('gridcolor', colorMix(containerOut.color, options.bgColor, gridLightness).toRgbString()); + coerce('title', axName[0]); // shouldn't this be on-par with 2D? + + containerOut.setScale = Lib.noop; + + if(coerce('showspikes')) { + coerce('spikesides'); + coerce('spikethickness'); + coerce('spikecolor', containerOut.color); + } + + coerce('showaxeslabels'); + if(coerce('showbackground')) coerce('backgroundcolor'); + } +}; + +},{"../../../lib":696,"../../../plot_api/plot_template":734,"../../cartesian/axis_defaults":746,"../../cartesian/type_defaults":768,"./axis_attributes":789,"tinycolor2":514}],791:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var convertHTMLToUnicode = _dereq_('../../../lib/html2unicode'); +var str2RgbaArray = _dereq_('../../../lib/str2rgbarray'); + +var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; + +function AxesOptions() { + this.bounds = [ + [-10, -10, -10], + [10, 10, 10] + ]; + + this.ticks = [ [], [], [] ]; + this.tickEnable = [ true, true, true ]; + this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ]; + this.tickSize = [ 12, 12, 12 ]; + this.tickAngle = [ 0, 0, 0 ]; + this.tickColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + this.tickPad = [ 18, 18, 18 ]; + + this.labels = [ 'x', 'y', 'z' ]; + this.labelEnable = [ true, true, true ]; + this.labelFont = ['Open Sans', 'Open Sans', 'Open Sans']; + this.labelSize = [ 20, 20, 20 ]; + this.labelColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + this.labelPad = [ 30, 30, 30 ]; + + this.lineEnable = [ true, true, true ]; + this.lineMirror = [ false, false, false ]; + this.lineWidth = [ 1, 1, 1 ]; + this.lineColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + + this.lineTickEnable = [ true, true, true ]; + this.lineTickMirror = [ false, false, false ]; + this.lineTickLength = [ 10, 10, 10 ]; + this.lineTickWidth = [ 1, 1, 1 ]; + this.lineTickColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + + this.gridEnable = [ true, true, true ]; + this.gridWidth = [ 1, 1, 1 ]; + this.gridColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + + this.zeroEnable = [ true, true, true ]; + this.zeroLineColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; + this.zeroLineWidth = [ 2, 2, 2 ]; + + this.backgroundEnable = [ true, true, true ]; + this.backgroundColor = [ [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5] ]; + + // some default values are stored for applying model transforms + this._defaultTickPad = this.tickPad.slice(); + this._defaultLabelPad = this.labelPad.slice(); + this._defaultLineTickLength = this.lineTickLength.slice(); +} + +var proto = AxesOptions.prototype; + +proto.merge = function(sceneLayout) { + var opts = this; + for(var i = 0; i < 3; ++i) { + var axes = sceneLayout[AXES_NAMES[i]]; + + if(!axes.visible) { + opts.tickEnable[i] = false; + opts.labelEnable[i] = false; + opts.lineEnable[i] = false; + opts.lineTickEnable[i] = false; + opts.gridEnable[i] = false; + opts.zeroEnable[i] = false; + opts.backgroundEnable[i] = false; + continue; + } + + // Axes labels + opts.labels[i] = convertHTMLToUnicode(axes.title); + if('titlefont' in axes) { + if(axes.titlefont.color) opts.labelColor[i] = str2RgbaArray(axes.titlefont.color); + if(axes.titlefont.family) opts.labelFont[i] = axes.titlefont.family; + if(axes.titlefont.size) opts.labelSize[i] = axes.titlefont.size; + } + + // Lines + if('showline' in axes) opts.lineEnable[i] = axes.showline; + if('linecolor' in axes) opts.lineColor[i] = str2RgbaArray(axes.linecolor); + if('linewidth' in axes) opts.lineWidth[i] = axes.linewidth; + + if('showgrid' in axes) opts.gridEnable[i] = axes.showgrid; + if('gridcolor' in axes) opts.gridColor[i] = str2RgbaArray(axes.gridcolor); + if('gridwidth' in axes) opts.gridWidth[i] = axes.gridwidth; + + // Remove zeroline if axis type is log + // otherwise the zeroline is incorrectly drawn at 1 on log axes + if(axes.type === 'log') opts.zeroEnable[i] = false; + else if('zeroline' in axes) opts.zeroEnable[i] = axes.zeroline; + if('zerolinecolor' in axes) opts.zeroLineColor[i] = str2RgbaArray(axes.zerolinecolor); + if('zerolinewidth' in axes) opts.zeroLineWidth[i] = axes.zerolinewidth; + + // tick lines + if('ticks' in axes && !!axes.ticks) opts.lineTickEnable[i] = true; + else opts.lineTickEnable[i] = false; + + if('ticklen' in axes) { + opts.lineTickLength[i] = opts._defaultLineTickLength[i] = axes.ticklen; + } + if('tickcolor' in axes) opts.lineTickColor[i] = str2RgbaArray(axes.tickcolor); + if('tickwidth' in axes) opts.lineTickWidth[i] = axes.tickwidth; + if('tickangle' in axes) { + opts.tickAngle[i] = (axes.tickangle === 'auto') ? + -3600 : // i.e. special number to set auto option + Math.PI * -axes.tickangle / 180; + } + + // tick labels + if('showticklabels' in axes) opts.tickEnable[i] = axes.showticklabels; + if('tickfont' in axes) { + if(axes.tickfont.color) opts.tickColor[i] = str2RgbaArray(axes.tickfont.color); + if(axes.tickfont.family) opts.tickFont[i] = axes.tickfont.family; + if(axes.tickfont.size) opts.tickSize[i] = axes.tickfont.size; + } + + if('mirror' in axes) { + if(['ticks', 'all', 'allticks'].indexOf(axes.mirror) !== -1) { + opts.lineTickMirror[i] = true; + opts.lineMirror[i] = true; + } else if(axes.mirror === true) { + opts.lineTickMirror[i] = false; + opts.lineMirror[i] = true; + } else { + opts.lineTickMirror[i] = false; + opts.lineMirror[i] = false; + } + } else opts.lineMirror[i] = false; + + // grid background + if('showbackground' in axes && axes.showbackground !== false) { + opts.backgroundEnable[i] = true; + opts.backgroundColor[i] = str2RgbaArray(axes.backgroundcolor); + } else opts.backgroundEnable[i] = false; + } +}; + + +function createAxesOptions(plotlyOptions) { + var result = new AxesOptions(); + result.merge(plotlyOptions); + return result; +} + +module.exports = createAxesOptions; + +},{"../../../lib/html2unicode":694,"../../../lib/str2rgbarray":719}],792:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../../lib'); +var Color = _dereq_('../../../components/color'); +var Registry = _dereq_('../../../registry'); + +var handleSubplotDefaults = _dereq_('../../subplot_defaults'); +var supplyGl3dAxisLayoutDefaults = _dereq_('./axis_defaults'); +var layoutAttributes = _dereq_('./layout_attributes'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + var hasNon3D = layoutOut._basePlotModules.length > 1; + + // some layout-wide attribute are used in all scenes + // if 3D is the only visible plot type + function getDfltFromLayout(attr) { + if(hasNon3D) return; + + var isValid = Lib.validate(layoutIn[attr], layoutAttributes[attr]); + if(isValid) return layoutIn[attr]; + } + + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'gl3d', + attributes: layoutAttributes, + handleDefaults: handleGl3dDefaults, + fullLayout: layoutOut, + font: layoutOut.font, + fullData: fullData, + getDfltFromLayout: getDfltFromLayout, + paper_bgcolor: layoutOut.paper_bgcolor, + calendar: layoutOut.calendar + }); +}; + +function handleGl3dDefaults(sceneLayoutIn, sceneLayoutOut, coerce, opts) { + /* + * Scene numbering proceeds as follows + * scene + * scene2 + * scene3 + * + * and d.scene will be undefined or some number or number string + * + * Also write back a blank scene object to user layout so that some + * attributes like aspectratio can be written back dynamically. + */ + + var bgcolor = coerce('bgcolor'), + bgColorCombined = Color.combine(bgcolor, opts.paper_bgcolor); + + var cameraKeys = ['up', 'center', 'eye']; + + for(var j = 0; j < cameraKeys.length; j++) { + coerce('camera.' + cameraKeys[j] + '.x'); + coerce('camera.' + cameraKeys[j] + '.y'); + coerce('camera.' + cameraKeys[j] + '.z'); + } + + /* + * coerce to positive number (min 0) but also do not accept 0 (>0 not >=0) + * note that 0's go false with the !! call + */ + var hasAspect = !!coerce('aspectratio.x') && + !!coerce('aspectratio.y') && + !!coerce('aspectratio.z'); + + var defaultAspectMode = hasAspect ? 'manual' : 'auto'; + var aspectMode = coerce('aspectmode', defaultAspectMode); + + /* + * We need aspectratio object in all the Layouts as it is dynamically set + * in the calculation steps, ie, we cant set the correct data now, it happens later. + * We must also account for the case the user sends bad ratio data with 'manual' set + * for the mode. In this case we must force change it here as the default coerce + * misses it above. + */ + if(!hasAspect) { + sceneLayoutIn.aspectratio = sceneLayoutOut.aspectratio = {x: 1, y: 1, z: 1}; + + if(aspectMode === 'manual') sceneLayoutOut.aspectmode = 'auto'; + + /* + * kind of like autorange - we need the calculated aspectmode back in + * the input layout or relayout can cause problems later + */ + sceneLayoutIn.aspectmode = sceneLayoutOut.aspectmode; + } + + supplyGl3dAxisLayoutDefaults(sceneLayoutIn, sceneLayoutOut, { + font: opts.font, + scene: opts.id, + data: opts.fullData, + bgColor: bgColorCombined, + calendar: opts.calendar, + fullLayout: opts.fullLayout + }); + + Registry.getComponentMethod('annotations3d', 'handleDefaults')( + sceneLayoutIn, sceneLayoutOut, opts + ); + + coerce('dragmode', opts.getDfltFromLayout('dragmode')); + coerce('hovermode', opts.getDfltFromLayout('hovermode')); +} + +},{"../../../components/color":570,"../../../lib":696,"../../../registry":827,"../../subplot_defaults":822,"./axis_defaults":790,"./layout_attributes":793}],793:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var gl3dAxisAttrs = _dereq_('./axis_attributes'); +var domainAttrs = _dereq_('../../domain').attributes; +var extendFlat = _dereq_('../../../lib/extend').extendFlat; +var counterRegex = _dereq_('../../../lib').counterRegex; + +function makeCameraVector(x, y, z) { + return { + x: { + valType: 'number', + + dflt: x, + editType: 'camera' + }, + y: { + valType: 'number', + + dflt: y, + editType: 'camera' + }, + z: { + valType: 'number', + + dflt: z, + editType: 'camera' + }, + editType: 'camera' + }; +} + +module.exports = { + _arrayAttrRegexps: [counterRegex('scene', '.annotations', true)], + + bgcolor: { + valType: 'color', + + dflt: 'rgba(0,0,0,0)', + editType: 'plot' + }, + camera: { + up: extendFlat(makeCameraVector(0, 0, 1), { + + }), + center: extendFlat(makeCameraVector(0, 0, 0), { + + }), + eye: extendFlat(makeCameraVector(1.25, 1.25, 1.25), { + + }), + editType: 'camera' + }, + domain: domainAttrs({name: 'scene', editType: 'plot'}), + aspectmode: { + valType: 'enumerated', + + values: ['auto', 'cube', 'data', 'manual'], + dflt: 'auto', + editType: 'plot', + impliedEdits: { + 'aspectratio.x': undefined, + 'aspectratio.y': undefined, + 'aspectratio.z': undefined + }, + + }, + aspectratio: { // must be positive (0's are coerced to 1) + x: { + valType: 'number', + + min: 0, + editType: 'plot', + impliedEdits: {'^aspectmode': 'manual'} + }, + y: { + valType: 'number', + + min: 0, + editType: 'plot', + impliedEdits: {'^aspectmode': 'manual'} + }, + z: { + valType: 'number', + + min: 0, + editType: 'plot', + impliedEdits: {'^aspectmode': 'manual'} + }, + editType: 'plot', + impliedEdits: {aspectmode: 'manual'}, + + }, + + xaxis: gl3dAxisAttrs, + yaxis: gl3dAxisAttrs, + zaxis: gl3dAxisAttrs, + + dragmode: { + valType: 'enumerated', + + values: ['orbit', 'turntable', 'zoom', 'pan', false], + dflt: 'turntable', + editType: 'plot', + + }, + hovermode: { + valType: 'enumerated', + + values: ['closest', false], + dflt: 'closest', + editType: 'modebar', + + }, + editType: 'plot', + + _deprecated: { + cameraposition: { + valType: 'info_array', + + editType: 'camera', + + } + } +}; + +},{"../../../lib":696,"../../../lib/extend":685,"../../domain":770,"./axis_attributes":789}],794:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var str2RGBArray = _dereq_('../../../lib/str2rgbarray'); + +var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; + +function SpikeOptions() { + this.enabled = [true, true, true]; + this.colors = [[0, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 0, 1]]; + this.drawSides = [true, true, true]; + this.lineWidth = [1, 1, 1]; +} + +var proto = SpikeOptions.prototype; + +proto.merge = function(sceneLayout) { + for(var i = 0; i < 3; ++i) { + var axes = sceneLayout[AXES_NAMES[i]]; + + if(!axes.visible) { + this.enabled[i] = false; + this.drawSides[i] = false; + continue; + } + + this.enabled[i] = axes.showspikes; + this.colors[i] = str2RGBArray(axes.spikecolor); + this.drawSides[i] = axes.spikesides; + this.lineWidth[i] = axes.spikethickness; + } +}; + +function createSpikeOptions(layout) { + var result = new SpikeOptions(); + result.merge(layout); + return result; +} + +module.exports = createSpikeOptions; + +},{"../../../lib/str2rgbarray":719}],795:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* eslint block-scoped-var: 0*/ +/* eslint no-redeclare: 0*/ + +'use strict'; + +module.exports = computeTickMarks; + +var Axes = _dereq_('../../cartesian/axes'); +var Lib = _dereq_('../../../lib'); +var convertHTMLToUnicode = _dereq_('../../../lib/html2unicode'); + +var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; + +var centerPoint = [0, 0, 0]; + +function contourLevelsFromTicks(ticks) { + var result = new Array(3); + for(var i = 0; i < 3; ++i) { + var tlevel = ticks[i]; + var clevel = new Array(tlevel.length); + for(var j = 0; j < tlevel.length; ++j) { + clevel[j] = tlevel[j].x; + } + result[i] = clevel; + } + return result; +} + +function computeTickMarks(scene) { + var axesOptions = scene.axesOptions; + var glRange = scene.glplot.axesPixels; + var sceneLayout = scene.fullSceneLayout; + + var ticks = [[], [], []]; + + for(var i = 0; i < 3; ++i) { + var axes = sceneLayout[AXES_NAMES[i]]; + + axes._length = (glRange[i].hi - glRange[i].lo) * + glRange[i].pixelsPerDataUnit / scene.dataScale[i]; + + if(Math.abs(axes._length) === Infinity) { + ticks[i] = []; + } else { + axes._input_range = axes.range.slice(); + axes.range[0] = (glRange[i].lo) / scene.dataScale[i]; + axes.range[1] = (glRange[i].hi) / scene.dataScale[i]; + axes._m = 1.0 / (scene.dataScale[i] * glRange[i].pixelsPerDataUnit); + + if(axes.range[0] === axes.range[1]) { + axes.range[0] -= 1; + axes.range[1] += 1; + } + // this is necessary to short-circuit the 'y' handling + // in autotick part of calcTicks... Treating all axes as 'y' in this case + // running the autoticks here, then setting + // autoticks to false to get around the 2D handling in calcTicks. + var tickModeCached = axes.tickmode; + if(axes.tickmode === 'auto') { + axes.tickmode = 'linear'; + var nticks = axes.nticks || Lib.constrain((axes._length / 40), 4, 9); + Axes.autoTicks(axes, Math.abs(axes.range[1] - axes.range[0]) / nticks); + } + var dataTicks = Axes.calcTicks(axes); + for(var j = 0; j < dataTicks.length; ++j) { + dataTicks[j].x = dataTicks[j].x * scene.dataScale[i]; + dataTicks[j].text = convertHTMLToUnicode(dataTicks[j].text); + } + ticks[i] = dataTicks; + + + axes.tickmode = tickModeCached; + } + } + + axesOptions.ticks = ticks; + + // Calculate tick lengths dynamically + for(var i = 0; i < 3; ++i) { + centerPoint[i] = 0.5 * (scene.glplot.bounds[0][i] + scene.glplot.bounds[1][i]); + for(var j = 0; j < 2; ++j) { + axesOptions.bounds[j][i] = scene.glplot.bounds[j][i]; + } + } + + scene.contourLevels = contourLevelsFromTicks(ticks); +} + +},{"../../../lib":696,"../../../lib/html2unicode":694,"../../cartesian/axes":744}],796:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +function xformMatrix(m, v) { + var out = [0, 0, 0, 0]; + var i, j; + + for(i = 0; i < 4; ++i) { + for(j = 0; j < 4; ++j) { + out[j] += m[4 * i + j] * v[i]; + } + } + + return out; +} + +function project(camera, v) { + var p = xformMatrix(camera.projection, + xformMatrix(camera.view, + xformMatrix(camera.model, [v[0], v[1], v[2], 1]))); + return p; +} + +module.exports = project; + +},{}],797:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createPlot = _dereq_('gl-plot3d'); +var getContext = _dereq_('webgl-context'); +var passiveSupported = _dereq_('has-passive-events'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +var Axes = _dereq_('../../plots/cartesian/axes'); +var Fx = _dereq_('../../components/fx'); + +var str2RGBAarray = _dereq_('../../lib/str2rgbarray'); +var showNoWebGlMsg = _dereq_('../../lib/show_no_webgl_msg'); + +var createCamera = _dereq_('./camera'); +var project = _dereq_('./project'); +var createAxesOptions = _dereq_('./layout/convert'); +var createSpikeOptions = _dereq_('./layout/spikes'); +var computeTickMarks = _dereq_('./layout/tick_marks'); + + +var STATIC_CANVAS, STATIC_CONTEXT; + +function render(scene) { + var trace; + + // update size of svg container + var svgContainer = scene.svgContainer; + var clientRect = scene.container.getBoundingClientRect(); + var width = clientRect.width, height = clientRect.height; + svgContainer.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); + svgContainer.setAttributeNS(null, 'width', width); + svgContainer.setAttributeNS(null, 'height', height); + + computeTickMarks(scene); + scene.glplot.axes.update(scene.axesOptions); + + // check if pick has changed + var keys = Object.keys(scene.traces); + var lastPicked = null; + var selection = scene.glplot.selection; + for(var i = 0; i < keys.length; ++i) { + trace = scene.traces[keys[i]]; + if(trace.data.hoverinfo !== 'skip' && trace.handlePick(selection)) { + lastPicked = trace; + } + + if(trace.setContourLevels) trace.setContourLevels(); + } + + function formatter(axisName, val) { + var axis = scene.fullSceneLayout[axisName]; + + return Axes.tickText(axis, axis.d2l(val), 'hover').text; + } + + var oldEventData; + + if(lastPicked !== null) { + var pdata = project(scene.glplot.cameraParams, selection.dataCoordinate); + trace = lastPicked.data; + var ptNumber = selection.index; + var hoverinfo = Fx.castHoverinfo(trace, scene.fullLayout, ptNumber); + var hoverinfoParts = hoverinfo.split('+'); + var isHoverinfoAll = hoverinfo === 'all'; + + var xVal = formatter('xaxis', selection.traceCoordinate[0]); + var yVal = formatter('yaxis', selection.traceCoordinate[1]); + var zVal = formatter('zaxis', selection.traceCoordinate[2]); + + if(!isHoverinfoAll) { + if(hoverinfoParts.indexOf('x') === -1) xVal = undefined; + if(hoverinfoParts.indexOf('y') === -1) yVal = undefined; + if(hoverinfoParts.indexOf('z') === -1) zVal = undefined; + if(hoverinfoParts.indexOf('text') === -1) selection.textLabel = undefined; + if(hoverinfoParts.indexOf('name') === -1) lastPicked.name = undefined; + } + + var tx; + + if(trace.type === 'cone' || trace.type === 'streamtube') { + var vectorTx = []; + if(isHoverinfoAll || hoverinfoParts.indexOf('u') !== -1) { + vectorTx.push('u: ' + formatter('xaxis', selection.traceCoordinate[3])); + } + if(isHoverinfoAll || hoverinfoParts.indexOf('v') !== -1) { + vectorTx.push('v: ' + formatter('yaxis', selection.traceCoordinate[4])); + } + if(isHoverinfoAll || hoverinfoParts.indexOf('w') !== -1) { + vectorTx.push('w: ' + formatter('zaxis', selection.traceCoordinate[5])); + } + if(isHoverinfoAll || hoverinfoParts.indexOf('norm') !== -1) { + vectorTx.push('norm: ' + selection.traceCoordinate[6].toPrecision(3)); + } + if(trace.type === 'streamtube' && (isHoverinfoAll || hoverinfoParts.indexOf('divergence') !== -1)) { + vectorTx.push('divergence: ' + selection.traceCoordinate[7].toPrecision(3)); + } + if(selection.textLabel) { + vectorTx.push(selection.textLabel); + } + tx = vectorTx.join('
'); + } else { + tx = selection.textLabel; + } + + if(scene.fullSceneLayout.hovermode) { + Fx.loneHover({ + x: (0.5 + 0.5 * pdata[0] / pdata[3]) * width, + y: (0.5 - 0.5 * pdata[1] / pdata[3]) * height, + xLabel: xVal, + yLabel: yVal, + zLabel: zVal, + text: tx, + name: lastPicked.name, + color: Fx.castHoverOption(trace, ptNumber, 'bgcolor') || lastPicked.color, + borderColor: Fx.castHoverOption(trace, ptNumber, 'bordercolor'), + fontFamily: Fx.castHoverOption(trace, ptNumber, 'font.family'), + fontSize: Fx.castHoverOption(trace, ptNumber, 'font.size'), + fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color') + }, { + container: svgContainer, + gd: scene.graphDiv + }); + } + + // TODO not sure if streamtube x/y/z should be emitted as x/y/z + var pointData = { + x: selection.traceCoordinate[0], + y: selection.traceCoordinate[1], + z: selection.traceCoordinate[2], + data: trace._input, + fullData: trace, + curveNumber: trace.index, + pointNumber: ptNumber + }; + + if(trace._module.eventData) { + pointData = trace._module.eventData(pointData, selection, trace, {}, ptNumber); + } + + Fx.appendArrayPointValue(pointData, trace, ptNumber); + + var eventData = {points: [pointData]}; + + if(selection.buttons && selection.distance < 5) { + scene.graphDiv.emit('plotly_click', eventData); + } + else { + scene.graphDiv.emit('plotly_hover', eventData); + } + + oldEventData = eventData; + } + else { + Fx.loneUnhover(svgContainer); + scene.graphDiv.emit('plotly_unhover', oldEventData); + } + + scene.drawAnnotations(scene); +} + +function initializeGLPlot(scene, fullLayout, canvas, gl) { + var gd = scene.graphDiv; + + var glplotOptions = { + canvas: canvas, + gl: gl, + container: scene.container, + axes: scene.axesOptions, + spikes: scene.spikeOptions, + pickRadius: 10, + snapToData: true, + autoScale: true, + autoBounds: false + }; + + // for static plots, we reuse the WebGL context + // as WebKit doesn't collect them reliably + if(scene.staticMode) { + if(!STATIC_CONTEXT) { + STATIC_CANVAS = document.createElement('canvas'); + STATIC_CONTEXT = getContext({ + canvas: STATIC_CANVAS, + preserveDrawingBuffer: true, + premultipliedAlpha: true, + antialias: true + }); + if(!STATIC_CONTEXT) { + throw new Error('error creating static canvas/context for image server'); + } + } + glplotOptions.pixelRatio = scene.pixelRatio; + glplotOptions.gl = STATIC_CONTEXT; + glplotOptions.canvas = STATIC_CANVAS; + } + + try { + scene.glplot = createPlot(glplotOptions); + } + catch(e) { + /* + * createPlot will throw when webgl is not enabled in the client. + * Lets return an instance of the module with all functions noop'd. + * The destroy method - which will remove the container from the DOM + * is overridden with a function that removes the container only. + */ + return showNoWebGlMsg(scene); + } + + var relayoutCallback = function(scene) { + if(scene.fullSceneLayout.dragmode === false) return; + + var update = {}; + update[scene.id + '.camera'] = getLayoutCamera(scene.camera); + scene.saveCamera(gd.layout); + scene.graphDiv.emit('plotly_relayout', update); + }; + + scene.glplot.canvas.addEventListener('mouseup', relayoutCallback.bind(null, scene)); + scene.glplot.canvas.addEventListener('wheel', relayoutCallback.bind(null, scene), passiveSupported ? {passive: false} : false); + + if(!scene.staticMode) { + scene.glplot.canvas.addEventListener('webglcontextlost', function(event) { + if(gd && gd.emit) { + gd.emit('plotly_webglcontextlost', { + event: event, + layer: scene.id + }); + } + }, false); + } + + if(!scene.camera) { + var cameraData = scene.fullSceneLayout.camera; + scene.camera = createCamera(scene.container, { + center: [cameraData.center.x, cameraData.center.y, cameraData.center.z], + eye: [cameraData.eye.x, cameraData.eye.y, cameraData.eye.z], + up: [cameraData.up.x, cameraData.up.y, cameraData.up.z], + zoomMin: 0.1, + zoomMax: 100, + mode: 'orbit' + }); + } + + scene.glplot.camera = scene.camera; + + scene.glplot.oncontextloss = function() { + scene.recoverContext(); + }; + + scene.glplot.onrender = render.bind(null, scene); + + // List of scene objects + scene.traces = {}; + + return true; +} + +function Scene(options, fullLayout) { + + // create sub container for plot + var sceneContainer = document.createElement('div'); + var plotContainer = options.container; + + // keep a ref to the graph div to fire hover+click events + this.graphDiv = options.graphDiv; + + // create SVG container for hover text + var svgContainer = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'svg'); + svgContainer.style.position = 'absolute'; + svgContainer.style.top = svgContainer.style.left = '0px'; + svgContainer.style.width = svgContainer.style.height = '100%'; + svgContainer.style['z-index'] = 20; + svgContainer.style['pointer-events'] = 'none'; + sceneContainer.appendChild(svgContainer); + this.svgContainer = svgContainer; + + // Tag the container with the sceneID + sceneContainer.id = options.id; + sceneContainer.style.position = 'absolute'; + sceneContainer.style.top = sceneContainer.style.left = '0px'; + sceneContainer.style.width = sceneContainer.style.height = '100%'; + plotContainer.appendChild(sceneContainer); + + this.fullLayout = fullLayout; + this.id = options.id || 'scene'; + this.fullSceneLayout = fullLayout[this.id]; + + // Saved from last call to plot() + this.plotArgs = [ [], {}, {} ]; + + /* + * Move this to calc step? Why does it work here? + */ + this.axesOptions = createAxesOptions(fullLayout[this.id]); + this.spikeOptions = createSpikeOptions(fullLayout[this.id]); + this.container = sceneContainer; + this.staticMode = !!options.staticPlot; + this.pixelRatio = options.plotGlPixelRatio || 2; + + // Coordinate rescaling + this.dataScale = [1, 1, 1]; + + this.contourLevels = [ [], [], [] ]; + + this.convertAnnotations = Registry.getComponentMethod('annotations3d', 'convert'); + this.drawAnnotations = Registry.getComponentMethod('annotations3d', 'draw'); + + if(!initializeGLPlot(this, fullLayout)) return; // todo check the necessity for this line +} + +var proto = Scene.prototype; + +proto.recoverContext = function() { + var scene = this; + var gl = this.glplot.gl; + var canvas = this.glplot.canvas; + this.glplot.dispose(); + + function tryRecover() { + if(gl.isContextLost()) { + requestAnimationFrame(tryRecover); + return; + } + if(!initializeGLPlot(scene, scene.fullLayout, canvas, gl)) { + Lib.error('Catastrophic and unrecoverable WebGL error. Context lost.'); + return; + } + scene.plot.apply(scene, scene.plotArgs); + } + requestAnimationFrame(tryRecover); +}; + +var axisProperties = [ 'xaxis', 'yaxis', 'zaxis' ]; + +function computeTraceBounds(scene, trace, bounds) { + var sceneLayout = scene.fullSceneLayout; + + for(var d = 0; d < 3; d++) { + var axisName = axisProperties[d]; + var axLetter = axisName.charAt(0); + var ax = sceneLayout[axisName]; + var coords = trace[axLetter]; + var calendar = trace[axLetter + 'calendar']; + var len = trace['_' + axLetter + 'length']; + + if(!Lib.isArrayOrTypedArray(coords)) { + bounds[0][d] = Math.min(bounds[0][d], 0); + bounds[1][d] = Math.max(bounds[1][d], len - 1); + } else { + var v; + + for(var i = 0; i < (len || coords.length); i++) { + if(Lib.isArrayOrTypedArray(coords[i])) { + for(var j = 0; j < coords[i].length; ++j) { + v = ax.d2l(coords[i][j], 0, calendar); + if(!isNaN(v) && isFinite(v)) { + bounds[0][d] = Math.min(bounds[0][d], v); + bounds[1][d] = Math.max(bounds[1][d], v); + } + } + } else { + v = ax.d2l(coords[i], 0, calendar); + if(!isNaN(v) && isFinite(v)) { + bounds[0][d] = Math.min(bounds[0][d], v); + bounds[1][d] = Math.max(bounds[1][d], v); + } + } + } + } + } +} + +proto.plot = function(sceneData, fullLayout, layout) { + + // Save parameters + this.plotArgs = [sceneData, fullLayout, layout]; + + if(this.glplot.contextLost) return; + + var data, trace; + var i, j, axis, axisType; + var fullSceneLayout = fullLayout[this.id]; + var sceneLayout = layout[this.id]; + + if(fullSceneLayout.bgcolor) this.glplot.clearColor = str2RGBAarray(fullSceneLayout.bgcolor); + else this.glplot.clearColor = [0, 0, 0, 0]; + + this.glplot.snapToData = true; + + // Update layout + this.fullLayout = fullLayout; + this.fullSceneLayout = fullSceneLayout; + + this.glplotLayout = fullSceneLayout; + this.axesOptions.merge(fullSceneLayout); + this.spikeOptions.merge(fullSceneLayout); + + // Update camera and camera mode + this.setCamera(fullSceneLayout.camera); + this.updateFx(fullSceneLayout.dragmode, fullSceneLayout.hovermode); + + // Update scene + this.glplot.update({}); + + // Update axes functions BEFORE updating traces + this.setConvert(axis); + + // Convert scene data + if(!sceneData) sceneData = []; + else if(!Array.isArray(sceneData)) sceneData = [sceneData]; + + // Compute trace bounding box + var dataBounds = [ + [Infinity, Infinity, Infinity], + [-Infinity, -Infinity, -Infinity] + ]; + for(i = 0; i < sceneData.length; ++i) { + data = sceneData[i]; + if(data.visible !== true) continue; + + computeTraceBounds(this, data, dataBounds); + } + var dataScale = [1, 1, 1]; + for(j = 0; j < 3; ++j) { + if(dataBounds[1][j] === dataBounds[0][j]) { + dataScale[j] = 1.0; + } + else { + dataScale[j] = 1.0 / (dataBounds[1][j] - dataBounds[0][j]); + } + } + + // Save scale + this.dataScale = dataScale; + + // after computeTraceBounds where ax._categories are filled in + this.convertAnnotations(this); + + // Update traces + for(i = 0; i < sceneData.length; ++i) { + data = sceneData[i]; + if(data.visible !== true) { + continue; + } + trace = this.traces[data.uid]; + if(trace) { + if(trace.data.type === data.type) { + trace.update(data); + } else { + trace.dispose(); + trace = data._module.plot(this, data); + this.traces[data.uid] = trace; + } + } else { + trace = data._module.plot(this, data); + this.traces[data.uid] = trace; + } + trace.name = data.name; + } + + // Remove empty traces + var traceIds = Object.keys(this.traces); + + trace_id_loop: + for(i = 0; i < traceIds.length; ++i) { + for(j = 0; j < sceneData.length; ++j) { + if(sceneData[j].uid === traceIds[i] && sceneData[j].visible === true) { + continue trace_id_loop; + } + } + trace = this.traces[traceIds[i]]; + trace.dispose(); + delete this.traces[traceIds[i]]; + } + + // order object per trace index + this.glplot.objects.sort(function(a, b) { + return a._trace.data.index - b._trace.data.index; + }); + + // Update ranges (needs to be called *after* objects are added due to updates) + var sceneBounds = [[0, 0, 0], [0, 0, 0]], + axisDataRange = [], + axisTypeRatios = {}; + + for(i = 0; i < 3; ++i) { + axis = fullSceneLayout[axisProperties[i]]; + axisType = axis.type; + + if(axisType in axisTypeRatios) { + axisTypeRatios[axisType].acc *= dataScale[i]; + axisTypeRatios[axisType].count += 1; + } + else { + axisTypeRatios[axisType] = { + acc: dataScale[i], + count: 1 + }; + } + + if(axis.autorange) { + sceneBounds[0][i] = Infinity; + sceneBounds[1][i] = -Infinity; + + var objects = this.glplot.objects; + var annotations = this.fullSceneLayout.annotations || []; + var axLetter = axis._name.charAt(0); + + for(j = 0; j < objects.length; j++) { + var obj = objects[j]; + var objBounds = obj.bounds; + var pad = obj._trace.data._pad || 0; + + if(obj.constructor.name === 'ErrorBars' && axis._lowerLogErrorBound) { + sceneBounds[0][i] = Math.min(sceneBounds[0][i], axis._lowerLogErrorBound); + } else { + sceneBounds[0][i] = Math.min(sceneBounds[0][i], objBounds[0][i] / dataScale[i] - pad); + } + sceneBounds[1][i] = Math.max(sceneBounds[1][i], objBounds[1][i] / dataScale[i] + pad); + } + + for(j = 0; j < annotations.length; j++) { + var ann = annotations[j]; + + // N.B. not taking into consideration the arrowhead + if(ann.visible) { + var pos = axis.r2l(ann[axLetter]); + sceneBounds[0][i] = Math.min(sceneBounds[0][i], pos); + sceneBounds[1][i] = Math.max(sceneBounds[1][i], pos); + } + } + + if('rangemode' in axis && axis.rangemode === 'tozero') { + sceneBounds[0][i] = Math.min(sceneBounds[0][i], 0); + sceneBounds[1][i] = Math.max(sceneBounds[1][i], 0); + } + if(sceneBounds[0][i] > sceneBounds[1][i]) { + sceneBounds[0][i] = -1; + sceneBounds[1][i] = 1; + } else { + var d = sceneBounds[1][i] - sceneBounds[0][i]; + sceneBounds[0][i] -= d / 32.0; + sceneBounds[1][i] += d / 32.0; + } + + if(axis.autorange === 'reversed') { + // swap bounds: + var tmp = sceneBounds[0][i]; + sceneBounds[0][i] = sceneBounds[1][i]; + sceneBounds[1][i] = tmp; + } + } else { + var range = axis.range; + sceneBounds[0][i] = axis.r2l(range[0]); + sceneBounds[1][i] = axis.r2l(range[1]); + } + if(sceneBounds[0][i] === sceneBounds[1][i]) { + sceneBounds[0][i] -= 1; + sceneBounds[1][i] += 1; + } + axisDataRange[i] = sceneBounds[1][i] - sceneBounds[0][i]; + + // Update plot bounds + this.glplot.bounds[0][i] = sceneBounds[0][i] * dataScale[i]; + this.glplot.bounds[1][i] = sceneBounds[1][i] * dataScale[i]; + } + + var axesScaleRatio = [1, 1, 1]; + + // Compute axis scale per category + for(i = 0; i < 3; ++i) { + axis = fullSceneLayout[axisProperties[i]]; + axisType = axis.type; + var axisRatio = axisTypeRatios[axisType]; + axesScaleRatio[i] = Math.pow(axisRatio.acc, 1.0 / axisRatio.count) / dataScale[i]; + } + + /* + * Dynamically set the aspect ratio depending on the users aspect settings + */ + var axisAutoScaleFactor = 4; + var aspectRatio; + + if(fullSceneLayout.aspectmode === 'auto') { + + if(Math.max.apply(null, axesScaleRatio) / Math.min.apply(null, axesScaleRatio) <= axisAutoScaleFactor) { + + /* + * USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL + */ + + aspectRatio = axesScaleRatio; + } else { + + /* + * USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL + */ + aspectRatio = [1, 1, 1]; + } + + } else if(fullSceneLayout.aspectmode === 'cube') { + aspectRatio = [1, 1, 1]; + + } else if(fullSceneLayout.aspectmode === 'data') { + aspectRatio = axesScaleRatio; + + } else if(fullSceneLayout.aspectmode === 'manual') { + var userRatio = fullSceneLayout.aspectratio; + aspectRatio = [userRatio.x, userRatio.y, userRatio.z]; + + } else { + throw new Error('scene.js aspectRatio was not one of the enumerated types'); + } + + /* + * Write aspect Ratio back to user data and fullLayout so that it is modifies as user + * manipulates the aspectmode settings and the fullLayout is up-to-date. + */ + fullSceneLayout.aspectratio.x = sceneLayout.aspectratio.x = aspectRatio[0]; + fullSceneLayout.aspectratio.y = sceneLayout.aspectratio.y = aspectRatio[1]; + fullSceneLayout.aspectratio.z = sceneLayout.aspectratio.z = aspectRatio[2]; + + /* + * Finally assign the computed aspecratio to the glplot module. This will have an effect + * on the next render cycle. + */ + this.glplot.aspect = aspectRatio; + + + // Update frame position for multi plots + var domain = fullSceneLayout.domain || null, + size = fullLayout._size || null; + + if(domain && size) { + var containerStyle = this.container.style; + containerStyle.position = 'absolute'; + containerStyle.left = (size.l + domain.x[0] * size.w) + 'px'; + containerStyle.top = (size.t + (1 - domain.y[1]) * size.h) + 'px'; + containerStyle.width = (size.w * (domain.x[1] - domain.x[0])) + 'px'; + containerStyle.height = (size.h * (domain.y[1] - domain.y[0])) + 'px'; + } + + // force redraw so that promise is returned when rendering is completed + this.glplot.redraw(); +}; + +proto.destroy = function() { + if(!this.glplot) return; + + this.camera.mouseListener.enabled = false; + this.container.removeEventListener('wheel', this.camera.wheelListener); + this.camera = this.glplot.camera = null; + this.glplot.dispose(); + this.container.parentNode.removeChild(this.container); + this.glplot = null; +}; + +// getOrbitCamera :: plotly_coords -> orbit_camera_coords +// inverse of getLayoutCamera +function getOrbitCamera(camera) { + return [ + [camera.eye.x, camera.eye.y, camera.eye.z], + [camera.center.x, camera.center.y, camera.center.z], + [camera.up.x, camera.up.y, camera.up.z] + ]; +} + +// getLayoutCamera :: orbit_camera_coords -> plotly_coords +// inverse of getOrbitCamera +function getLayoutCamera(camera) { + return { + up: {x: camera.up[0], y: camera.up[1], z: camera.up[2]}, + center: {x: camera.center[0], y: camera.center[1], z: camera.center[2]}, + eye: {x: camera.eye[0], y: camera.eye[1], z: camera.eye[2]} + }; +} + +// get camera position in plotly coords from 'orbit-camera' coords +proto.getCamera = function getCamera() { + this.glplot.camera.view.recalcMatrix(this.camera.view.lastT()); + return getLayoutCamera(this.glplot.camera); +}; + +// set camera position with a set of plotly coords +proto.setCamera = function setCamera(cameraData) { + this.glplot.camera.lookAt.apply(this, getOrbitCamera(cameraData)); +}; + +// save camera to user layout (i.e. gd.layout) +proto.saveCamera = function saveCamera(layout) { + var cameraData = this.getCamera(), + cameraNestedProp = Lib.nestedProperty(layout, this.id + '.camera'), + cameraDataLastSave = cameraNestedProp.get(), + hasChanged = false; + + function same(x, y, i, j) { + var vectors = ['up', 'center', 'eye'], + components = ['x', 'y', 'z']; + return y[vectors[i]] && (x[vectors[i]][components[j]] === y[vectors[i]][components[j]]); + } + + if(cameraDataLastSave === undefined) hasChanged = true; + else { + for(var i = 0; i < 3; i++) { + for(var j = 0; j < 3; j++) { + if(!same(cameraData, cameraDataLastSave, i, j)) { + hasChanged = true; + break; + } + } + } + } + + if(hasChanged) cameraNestedProp.set(cameraData); + + return hasChanged; +}; + +proto.updateFx = function(dragmode, hovermode) { + var camera = this.camera; + + if(camera) { + // rotate and orbital are synonymous + if(dragmode === 'orbit') { + camera.mode = 'orbit'; + camera.keyBindingMode = 'rotate'; + + } else if(dragmode === 'turntable') { + camera.up = [0, 0, 1]; + camera.mode = 'turntable'; + camera.keyBindingMode = 'rotate'; + + } else { + + // none rotation modes [pan or zoom] + camera.keyBindingMode = dragmode; + } + } + + // to put dragmode and hovermode on the same grounds from relayout + this.fullSceneLayout.hovermode = hovermode; +}; + +proto.toImage = function(format) { + if(!format) format = 'png'; + + if(this.staticMode) this.container.appendChild(STATIC_CANVAS); + + // Force redraw + this.glplot.redraw(); + + // Grab context and yank out pixels + var gl = this.glplot.gl; + var w = gl.drawingBufferWidth; + var h = gl.drawingBufferHeight; + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + var pixels = new Uint8Array(w * h * 4); + gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + // Flip pixels + for(var j = 0, k = h - 1; j < k; ++j, --k) { + for(var i = 0; i < w; ++i) { + for(var l = 0; l < 4; ++l) { + var tmp = pixels[4 * (w * j + i) + l]; + pixels[4 * (w * j + i) + l] = pixels[4 * (w * k + i) + l]; + pixels[4 * (w * k + i) + l] = tmp; + } + } + } + + var canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + var context = canvas.getContext('2d'); + var imageData = context.createImageData(w, h); + imageData.data.set(pixels); + context.putImageData(imageData, 0, 0); + + var dataURL; + + switch(format) { + case 'jpeg': + dataURL = canvas.toDataURL('image/jpeg'); + break; + case 'webp': + dataURL = canvas.toDataURL('image/webp'); + break; + default: + dataURL = canvas.toDataURL('image/png'); + } + + if(this.staticMode) this.container.removeChild(STATIC_CANVAS); + + return dataURL; +}; + +proto.setConvert = function() { + for(var i = 0; i < 3; i++) { + var ax = this.fullSceneLayout[axisProperties[i]]; + Axes.setConvert(ax, this.fullLayout); + ax.setScale = Lib.noop; + } +}; + +module.exports = Scene; + +},{"../../components/fx":612,"../../lib":696,"../../lib/show_no_webgl_msg":717,"../../lib/str2rgbarray":719,"../../plots/cartesian/axes":744,"../../registry":827,"./camera":786,"./layout/convert":791,"./layout/spikes":794,"./layout/tick_marks":795,"./project":796,"gl-plot3d":277,"has-passive-events":394,"webgl-context":533}],798:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function zip3(x, y, z, len) { + len = len || x.length; + + var result = new Array(len); + for(var i = 0; i < len; i++) { + result[i] = [x[i], y[i], z[i]]; + } + return result; +}; + +},{}],799:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('./font_attributes'); +var animationAttrs = _dereq_('./animation_attributes'); +var colorAttrs = _dereq_('../components/color/attributes'); +var extendFlat = _dereq_('../lib/extend').extendFlat; + +var globalFont = fontAttrs({ + editType: 'calc', + +}); +globalFont.family.dflt = '"Open Sans", verdana, arial, sans-serif'; +globalFont.size.dflt = 12; +globalFont.color.dflt = colorAttrs.defaultLine; + +module.exports = { + font: globalFont, + title: { + valType: 'string', + + editType: 'layoutstyle', + + }, + titlefont: fontAttrs({ + editType: 'layoutstyle', + + }), + autosize: { + valType: 'boolean', + + dflt: false, + // autosize, width, and height get special editType treatment in _relayout + // so we can handle noop resizes more efficiently + editType: 'none', + + }, + width: { + valType: 'number', + + min: 10, + dflt: 700, + editType: 'plot', + + }, + height: { + valType: 'number', + + min: 10, + dflt: 450, + editType: 'plot', + + }, + margin: { + l: { + valType: 'number', + + min: 0, + dflt: 80, + editType: 'plot', + + }, + r: { + valType: 'number', + + min: 0, + dflt: 80, + editType: 'plot', + + }, + t: { + valType: 'number', + + min: 0, + dflt: 100, + editType: 'plot', + + }, + b: { + valType: 'number', + + min: 0, + dflt: 80, + editType: 'plot', + + }, + pad: { + valType: 'number', + + min: 0, + dflt: 0, + editType: 'plot', + + }, + autoexpand: { + valType: 'boolean', + + dflt: true, + editType: 'plot' + }, + editType: 'plot' + }, + paper_bgcolor: { + valType: 'color', + + dflt: colorAttrs.background, + editType: 'plot', + + }, + plot_bgcolor: { + // defined here, but set in cartesian.supplyLayoutDefaults + // because it needs to know if there are (2D) axes or not + valType: 'color', + + dflt: colorAttrs.background, + editType: 'layoutstyle', + + }, + separators: { + valType: 'string', + + editType: 'plot', + + }, + hidesources: { + valType: 'boolean', + + dflt: false, + editType: 'plot', + + }, + showlegend: { + // handled in legend.supplyLayoutDefaults + // but included here because it's not in the legend object + valType: 'boolean', + + editType: 'legend', + + }, + colorway: { + valType: 'colorlist', + dflt: colorAttrs.defaults, + + editType: 'calc', + + }, + datarevision: { + valType: 'any', + + editType: 'calc', + + }, + template: { + valType: 'any', + + editType: 'calc', + + }, + modebar: { + orientation: { + valType: 'enumerated', + values: ['v', 'h'], + dflt: 'h', + + editType: 'modebar', + + }, + bgcolor: { + valType: 'color', + + editType: 'modebar', + + }, + color: { + valType: 'color', + + editType: 'modebar', + + }, + activecolor: { + valType: 'color', + + editType: 'modebar', + + }, + editType: 'modebar' + }, + + transition: extendFlat({}, animationAttrs.transition, { + + editType: 'none' + }) +}; + +},{"../components/color/attributes":569,"../lib/extend":685,"./animation_attributes":739,"./font_attributes":771}],800:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var requiredVersion = '0.45.0'; + +module.exports = { + requiredVersion: requiredVersion, + + styleUrlPrefix: 'mapbox://styles/mapbox/', + styleUrlSuffix: 'v9', + + controlContainerClassName: 'mapboxgl-control-container', + + wrongVersionErrorMsg: [ + 'Your custom plotly.js bundle is not using the correct mapbox-gl version', + 'Please install mapbox-gl@' + requiredVersion + '.' + ].join('\n'), + + noAccessTokenErrorMsg: [ + 'Missing Mapbox access token.', + 'Mapbox trace type require a Mapbox access token to be registered.', + 'For example:', + ' Plotly.plot(gd, data, layout, { mapboxAccessToken: \'my-access-token\' });', + 'More info here: https://www.mapbox.com/help/define-access-token/' + ].join('\n'), + + mapOnErrorMsg: 'Mapbox error.', + + // a subset of node_modules/mapbox-gl/dist/mapbox-gl.css + styleRules: { + map: 'overflow:hidden;position:relative;', + 'missing-css': 'display:none', + } +}; + +},{}],801:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +/** + * Convert plotly.js 'textposition' to mapbox-gl 'anchor' and 'offset' + * (with the help of the icon size). + * + * @param {string} textpostion : plotly.js textposition value + * @param {number} iconSize : plotly.js icon size (e.g. marker.size for traces) + * + * @return {object} + * - anchor + * - offset + */ +module.exports = function convertTextOpts(textposition, iconSize) { + var parts = textposition.split(' '), + vPos = parts[0], + hPos = parts[1]; + + // ballpack values + var factor = Lib.isArrayOrTypedArray(iconSize) ? Lib.mean(iconSize) : iconSize, + xInc = 0.5 + (factor / 100), + yInc = 1.5 + (factor / 100); + + var anchorVals = ['', ''], + offset = [0, 0]; + + switch(vPos) { + case 'top': + anchorVals[0] = 'top'; + offset[1] = -yInc; + break; + case 'bottom': + anchorVals[0] = 'bottom'; + offset[1] = yInc; + break; + } + + switch(hPos) { + case 'left': + anchorVals[1] = 'right'; + offset[0] = -xInc; + break; + case 'right': + anchorVals[1] = 'left'; + offset[0] = xInc; + break; + } + + // Mapbox text-anchor must be one of: + // center, left, right, top, bottom, + // top-left, top-right, bottom-left, bottom-right + + var anchor; + if(anchorVals[0] && anchorVals[1]) anchor = anchorVals.join('-'); + else if(anchorVals[0]) anchor = anchorVals[0]; + else if(anchorVals[1]) anchor = anchorVals[1]; + else anchor = 'center'; + + return { anchor: anchor, offset: offset }; +}; + +},{"../../lib":696}],802:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var mapboxgl = _dereq_('mapbox-gl'); + +var Lib = _dereq_('../../lib'); +var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +var createMapbox = _dereq_('./mapbox'); +var constants = _dereq_('./constants'); + +var MAPBOX = 'mapbox'; + +for(var k in constants.styleRules) { + Lib.addStyleRule('.mapboxgl-' + k, constants.styleRules[k]); +} + +exports.name = MAPBOX; + +exports.attr = 'subplot'; + +exports.idRoot = MAPBOX; + +exports.idRegex = exports.attrRegex = Lib.counterRegex(MAPBOX); + +exports.attributes = { + subplot: { + valType: 'subplotid', + + dflt: 'mapbox', + editType: 'calc', + + } +}; + +exports.layoutAttributes = _dereq_('./layout_attributes'); + +exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); + +exports.plot = function plotMapbox(gd) { + var fullLayout = gd._fullLayout; + var calcData = gd.calcdata; + var mapboxIds = fullLayout._subplots[MAPBOX]; + + if(mapboxgl.version !== constants.requiredVersion) { + throw new Error(constants.wrongVersionErrorMsg); + } + + var accessToken = findAccessToken(gd, mapboxIds); + mapboxgl.accessToken = accessToken; + + for(var i = 0; i < mapboxIds.length; i++) { + var id = mapboxIds[i], + subplotCalcData = getSubplotCalcData(calcData, MAPBOX, id), + opts = fullLayout[id], + mapbox = opts._subplot; + + if(!mapbox) { + mapbox = createMapbox({ + gd: gd, + container: fullLayout._glcontainer.node(), + id: id, + fullLayout: fullLayout, + staticPlot: gd._context.staticPlot + }); + + fullLayout[id]._subplot = mapbox; + } + + if(!mapbox.viewInitial) { + mapbox.viewInitial = { + center: Lib.extendFlat({}, opts.center), + zoom: opts.zoom, + bearing: opts.bearing, + pitch: opts.pitch + }; + } + + mapbox.plot(subplotCalcData, fullLayout, gd._promises); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldMapboxKeys = oldFullLayout._subplots[MAPBOX] || []; + + for(var i = 0; i < oldMapboxKeys.length; i++) { + var oldMapboxKey = oldMapboxKeys[i]; + + if(!newFullLayout[oldMapboxKey] && !!oldFullLayout[oldMapboxKey]._subplot) { + oldFullLayout[oldMapboxKey]._subplot.destroy(); + } + } +}; + +exports.toSVG = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots[MAPBOX]; + var size = fullLayout._size; + + for(var i = 0; i < subplotIds.length; i++) { + var opts = fullLayout[subplotIds[i]], + domain = opts.domain, + mapbox = opts._subplot; + + var imageData = mapbox.toImage('png'); + var image = fullLayout._glimages.append('svg:image'); + + image.attr({ + xmlns: xmlnsNamespaces.svg, + 'xlink:href': imageData, + x: size.l + size.w * domain.x[0], + y: size.t + size.h * (1 - domain.y[1]), + width: size.w * (domain.x[1] - domain.x[0]), + height: size.h * (domain.y[1] - domain.y[0]), + preserveAspectRatio: 'none' + }); + + mapbox.destroy(); + } +}; + +function findAccessToken(gd, mapboxIds) { + var fullLayout = gd._fullLayout, + context = gd._context; + + // special case for Mapbox Atlas users + if(context.mapboxAccessToken === '') return ''; + + // Take the first token we find in a mapbox subplot. + // These default to the context value but may be overridden. + for(var i = 0; i < mapboxIds.length; i++) { + var opts = fullLayout[mapboxIds[i]]; + + if(opts.accesstoken) { + return opts.accesstoken; + } + } + + throw new Error(constants.noAccessTokenErrorMsg); +} + +exports.updateFx = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds = fullLayout._subplots[MAPBOX]; + + for(var i = 0; i < subplotIds.length; i++) { + var subplotObj = fullLayout[subplotIds[i]]._subplot; + subplotObj.updateFx(fullLayout); + } +}; + +},{"../../constants/xmlns_namespaces":674,"../../lib":696,"../../plots/get_data":781,"./constants":800,"./layout_attributes":804,"./layout_defaults":805,"./mapbox":806,"mapbox-gl":409}],803:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var convertTextOpts = _dereq_('./convert_text_opts'); + +function MapboxLayer(mapbox, index) { + this.mapbox = mapbox; + this.map = mapbox.map; + + this.uid = mapbox.uid + '-' + 'layer' + index; + + this.idSource = this.uid + '-source'; + this.idLayer = this.uid + '-layer'; + + // some state variable to check if a remove/add step is needed + this.sourceType = null; + this.source = null; + this.layerType = null; + this.below = null; + + // is layer currently visible + this.visible = false; +} + +var proto = MapboxLayer.prototype; + +proto.update = function update(opts) { + if(!this.visible) { + // IMPORTANT: must create source before layer to not cause errors + this.updateSource(opts); + this.updateLayer(opts); + } else if(this.needsNewSource(opts)) { + // IMPORTANT: must delete layer before source to not cause errors + this.removeLayer(); + this.updateSource(opts); + this.updateLayer(opts); + } else if(this.needsNewLayer(opts)) { + this.updateLayer(opts); + } else { + this.updateStyle(opts); + } + + this.visible = isVisible(opts); +}; + +proto.needsNewSource = function(opts) { + // for some reason changing layer to 'fill' or 'symbol' + // w/o changing the source throws an exception in mapbox-gl 0.18 ; + // stay safe and make new source on type changes + return ( + this.sourceType !== opts.sourcetype || + this.source !== opts.source || + this.layerType !== opts.type + ); +}; + +proto.needsNewLayer = function(opts) { + return ( + this.layerType !== opts.type || + this.below !== opts.below + ); +}; + +proto.updateSource = function(opts) { + var map = this.map; + + if(map.getSource(this.idSource)) map.removeSource(this.idSource); + + this.sourceType = opts.sourcetype; + this.source = opts.source; + + if(!isVisible(opts)) return; + + var sourceOpts = convertSourceOpts(opts); + + map.addSource(this.idSource, sourceOpts); +}; + +proto.updateLayer = function(opts) { + var map = this.map; + var convertedOpts = convertOpts(opts); + + this.removeLayer(); + this.layerType = opts.type; + + if(isVisible(opts)) { + map.addLayer({ + id: this.idLayer, + source: this.idSource, + 'source-layer': opts.sourcelayer || '', + type: opts.type, + layout: convertedOpts.layout, + paint: convertedOpts.paint + }, opts.below); + } +}; + +proto.updateStyle = function(opts) { + if(isVisible(opts)) { + var convertedOpts = convertOpts(opts); + this.mapbox.setOptions(this.idLayer, 'setLayoutProperty', convertedOpts.layout); + this.mapbox.setOptions(this.idLayer, 'setPaintProperty', convertedOpts.paint); + } +}; + +proto.removeLayer = function() { + var map = this.map; + if(map.getLayer(this.idLayer)) { + map.removeLayer(this.idLayer); + } +}; + +proto.dispose = function dispose() { + var map = this.map; + map.removeLayer(this.idLayer); + map.removeSource(this.idSource); +}; + +function isVisible(opts) { + var source = opts.source; + + return opts.visible && ( + Lib.isPlainObject(source) || + (typeof source === 'string' && source.length > 0) + ); +} + +function convertOpts(opts) { + var layout = {}, + paint = {}; + + switch(opts.type) { + + case 'circle': + Lib.extendFlat(paint, { + 'circle-radius': opts.circle.radius, + 'circle-color': opts.color, + 'circle-opacity': opts.opacity + }); + break; + + case 'line': + Lib.extendFlat(paint, { + 'line-width': opts.line.width, + 'line-color': opts.color, + 'line-opacity': opts.opacity + }); + break; + + case 'fill': + Lib.extendFlat(paint, { + 'fill-color': opts.color, + 'fill-outline-color': opts.fill.outlinecolor, + 'fill-opacity': opts.opacity + + // no way to pass specify outline width at the moment + }); + break; + + case 'symbol': + var symbol = opts.symbol, + textOpts = convertTextOpts(symbol.textposition, symbol.iconsize); + + Lib.extendFlat(layout, { + 'icon-image': symbol.icon + '-15', + 'icon-size': symbol.iconsize / 10, + + 'text-field': symbol.text, + 'text-size': symbol.textfont.size, + 'text-anchor': textOpts.anchor, + 'text-offset': textOpts.offset + + // TODO font family + // 'text-font': symbol.textfont.family.split(', '), + }); + + Lib.extendFlat(paint, { + 'icon-color': opts.color, + 'text-color': symbol.textfont.color, + 'text-opacity': opts.opacity + }); + break; + } + + return { layout: layout, paint: paint }; +} + +function convertSourceOpts(opts) { + var sourceType = opts.sourcetype; + var source = opts.source; + var sourceOpts = {type: sourceType}; + var field; + + if(sourceType === 'geojson') { + field = 'data'; + } else if(sourceType === 'vector') { + field = typeof source === 'string' ? 'url' : 'tiles'; + } + + sourceOpts[field] = source; + return sourceOpts; +} + +module.exports = function createMapboxLayer(mapbox, index, opts) { + var mapboxLayer = new MapboxLayer(mapbox, index); + + mapboxLayer.update(opts); + + return mapboxLayer; +}; + +},{"../../lib":696,"./convert_text_opts":801}],804:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var defaultLine = _dereq_('../../components/color').defaultLine; +var domainAttrs = _dereq_('../domain').attributes; +var fontAttrs = _dereq_('../font_attributes'); +var textposition = _dereq_('../../traces/scatter/attributes').textposition; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +var fontAttr = fontAttrs({ + +}); +fontAttr.family.dflt = 'Open Sans Regular, Arial Unicode MS Regular'; + +module.exports = overrideAll({ + _arrayAttrRegexps: [Lib.counterRegex('mapbox', '.layers', true)], + + domain: domainAttrs({name: 'mapbox'}), + + accesstoken: { + valType: 'string', + noBlank: true, + strict: true, + + + }, + style: { + valType: 'any', + values: ['basic', 'streets', 'outdoors', 'light', 'dark', 'satellite', 'satellite-streets'], + dflt: 'basic', + + + }, + + center: { + lon: { + valType: 'number', + dflt: 0, + + + }, + lat: { + valType: 'number', + dflt: 0, + + + } + }, + zoom: { + valType: 'number', + dflt: 1, + + + }, + bearing: { + valType: 'number', + dflt: 0, + + + }, + pitch: { + valType: 'number', + dflt: 0, + + + }, + + layers: templatedArray('layer', { + visible: { + valType: 'boolean', + + dflt: true, + + }, + sourcetype: { + valType: 'enumerated', + values: ['geojson', 'vector'], + dflt: 'geojson', + + + }, + + source: { + valType: 'any', + + + }, + + sourcelayer: { + valType: 'string', + dflt: '', + + + }, + + type: { + valType: 'enumerated', + values: ['circle', 'line', 'fill', 'symbol'], + dflt: 'circle', + + + }, + + // attributes shared between all types + below: { + valType: 'string', + dflt: '', + + + }, + color: { + valType: 'color', + dflt: defaultLine, + + + }, + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + + + }, + + // type-specific style attributes + circle: { + radius: { + valType: 'number', + dflt: 15, + + + } + }, + + line: { + width: { + valType: 'number', + dflt: 2, + + + } + }, + + fill: { + outlinecolor: { + valType: 'color', + dflt: defaultLine, + + + } + }, + + symbol: { + icon: { + valType: 'string', + dflt: 'marker', + + + }, + iconsize: { + valType: 'number', + dflt: 10, + + + }, + text: { + valType: 'string', + dflt: '', + + + }, + textfont: fontAttr, + textposition: Lib.extendFlat({}, textposition, { arrayOk: false }) + } + }) +}, 'plot', 'from-root'); + +},{"../../components/color":570,"../../lib":696,"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../../traces/scatter/attributes":1043,"../domain":770,"../font_attributes":771}],805:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleSubplotDefaults = _dereq_('../subplot_defaults'); +var handleArrayContainerDefaults = _dereq_('../array_container_defaults'); +var layoutAttributes = _dereq_('./layout_attributes'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'mapbox', + attributes: layoutAttributes, + handleDefaults: handleDefaults, + partition: 'y', + accessToken: layoutOut._mapboxAccessToken + }); +}; + +function handleDefaults(containerIn, containerOut, coerce, opts) { + coerce('accesstoken', opts.accessToken); + coerce('style'); + coerce('center.lon'); + coerce('center.lat'); + coerce('zoom'); + coerce('bearing'); + coerce('pitch'); + + handleArrayContainerDefaults(containerIn, containerOut, { + name: 'layers', + handleItemDefaults: handleLayerDefaults + }); + + // copy ref to input container to update 'center' and 'zoom' on map move + containerOut._input = containerIn; +} + +function handleLayerDefaults(layerIn, layerOut) { + function coerce(attr, dflt) { + return Lib.coerce(layerIn, layerOut, layoutAttributes.layers, attr, dflt); + } + + var visible = coerce('visible'); + if(visible) { + var sourceType = coerce('sourcetype'); + coerce('source'); + + if(sourceType === 'vector') coerce('sourcelayer'); + + // maybe add smart default based off GeoJSON geometry? + var type = coerce('type'); + + coerce('below'); + coerce('color'); + coerce('opacity'); + + if(type === 'circle') { + coerce('circle.radius'); + } + + if(type === 'line') { + coerce('line.width'); + } + + if(type === 'fill') { + coerce('fill.outlinecolor'); + } + + if(type === 'symbol') { + coerce('symbol.icon'); + coerce('symbol.iconsize'); + + coerce('symbol.text'); + Lib.coerceFont(coerce, 'symbol.textfont'); + coerce('symbol.textposition'); + } + } +} + +},{"../../lib":696,"../array_container_defaults":740,"../subplot_defaults":822,"./layout_attributes":804}],806:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var mapboxgl = _dereq_('mapbox-gl'); + +var Fx = _dereq_('../../components/fx'); +var Lib = _dereq_('../../lib'); +var dragElement = _dereq_('../../components/dragelement'); +var prepSelect = _dereq_('../cartesian/select').prepSelect; +var selectOnClick = _dereq_('../cartesian/select').selectOnClick; +var constants = _dereq_('./constants'); +var layoutAttributes = _dereq_('./layout_attributes'); +var createMapboxLayer = _dereq_('./layers'); + +function Mapbox(opts) { + this.id = opts.id; + this.gd = opts.gd; + this.container = opts.container; + this.isStatic = opts.staticPlot; + + var fullLayout = opts.fullLayout; + + // unique id for this Mapbox instance + this.uid = fullLayout._uid + '-' + this.id; + + // full mapbox options (N.B. needs to be updated on every updates) + this.opts = fullLayout[this.id]; + + // create framework on instantiation for a smoother first plot call + this.div = null; + this.xaxis = null; + this.yaxis = null; + this.createFramework(fullLayout); + + // state variables used to infer how and what to update + this.map = null; + this.accessToken = null; + this.styleObj = null; + this.traceHash = {}; + this.layerList = []; +} + +var proto = Mapbox.prototype; + +module.exports = function createMapbox(opts) { + return new Mapbox(opts); +}; + +proto.plot = function(calcData, fullLayout, promises) { + var self = this; + + // feed in new mapbox options + var opts = self.opts = fullLayout[this.id]; + + // remove map and create a new map if access token has change + if(self.map && (opts.accesstoken !== self.accessToken)) { + self.map.remove(); + self.map = null; + self.styleObj = null; + self.traceHash = []; + self.layerList = {}; + } + + var promise; + + if(!self.map) { + promise = new Promise(function(resolve, reject) { + self.createMap(calcData, fullLayout, resolve, reject); + }); + } else { + promise = new Promise(function(resolve, reject) { + self.updateMap(calcData, fullLayout, resolve, reject); + }); + } + + promises.push(promise); +}; + +proto.createMap = function(calcData, fullLayout, resolve, reject) { + var self = this; + var gd = self.gd; + var opts = self.opts; + + // store style id and URL or object + var styleObj = self.styleObj = getStyleObj(opts.style); + + // store access token associated with this map + self.accessToken = opts.accesstoken; + + // create the map! + var map = self.map = new mapboxgl.Map({ + container: self.div, + + style: styleObj.style, + center: convertCenter(opts.center), + zoom: opts.zoom, + bearing: opts.bearing, + pitch: opts.pitch, + + interactive: !self.isStatic, + preserveDrawingBuffer: self.isStatic, + + doubleClickZoom: false, + boxZoom: false + }); + + // clear navigation container + var className = constants.controlContainerClassName; + var controlContainer = self.div.getElementsByClassName(className)[0]; + self.div.removeChild(controlContainer); + + // make sure canvas does not inherit left and top css + map._canvas.style.left = '0px'; + map._canvas.style.top = '0px'; + + self.rejectOnError(reject); + + map.once('load', function() { + self.updateData(calcData); + self.updateLayout(fullLayout); + self.resolveOnRender(resolve); + }); + + if(self.isStatic) return; + + var wheeling = false; + + // keep track of pan / zoom in user layout and emit relayout event + map.on('moveend', function(eventData) { + if(!self.map) return; + + var view = self.getView(); + + opts._input.center = opts.center = view.center; + opts._input.zoom = opts.zoom = view.zoom; + opts._input.bearing = opts.bearing = view.bearing; + opts._input.pitch = opts.pitch = view.pitch; + + // 'moveend' gets triggered by map.setCenter, map.setZoom, + // map.setBearing and map.setPitch. + // + // Here, we make sure that 'plotly_relayout' is + // triggered here only when the 'moveend' originates from a + // mouse target (filtering out API calls) to not + // duplicate 'plotly_relayout' events. + + if(eventData.originalEvent || wheeling) { + emitRelayoutFromView(view); + } + wheeling = false; + }); + + map.on('wheel', function() { + wheeling = true; + }); + + map.on('mousemove', function(evt) { + var bb = self.div.getBoundingClientRect(); + + // some hackery to get Fx.hover to work + evt.clientX = evt.point.x + bb.left; + evt.clientY = evt.point.y + bb.top; + + evt.target.getBoundingClientRect = function() { return bb; }; + + self.xaxis.p2c = function() { return evt.lngLat.lng; }; + self.yaxis.p2c = function() { return evt.lngLat.lat; }; + + Fx.hover(gd, evt, self.id); + }); + + function unhover() { + Fx.loneUnhover(fullLayout._toppaper); + } + + map.on('dragstart', unhover); + map.on('zoomstart', unhover); + + map.on('dblclick', function() { + gd.emit('plotly_doubleclick', null); + + var viewInitial = self.viewInitial; + + map.setCenter(convertCenter(viewInitial.center)); + map.setZoom(viewInitial.zoom); + map.setBearing(viewInitial.bearing); + map.setPitch(viewInitial.pitch); + + var viewNow = self.getView(); + + opts._input.center = opts.center = viewNow.center; + opts._input.zoom = opts.zoom = viewNow.zoom; + opts._input.bearing = opts.bearing = viewNow.bearing; + opts._input.pitch = opts.pitch = viewNow.pitch; + + emitRelayoutFromView(viewNow); + }); + + function emitRelayoutFromView(view) { + var id = self.id; + var evtData = {}; + for(var k in view) { + evtData[id + '.' + k] = view[k]; + } + gd.emit('plotly_relayout', evtData); + } + + // define event handlers on map creation, to keep one ref per map, + // so that map.on / map.off in updateFx works as expected + self.clearSelect = function() { + gd._fullLayout._zoomlayer.selectAll('.select-outline').remove(); + }; + + /** + * Returns a click handler function that is supposed + * to handle clicks in pan mode. + */ + self.onClickInPanFn = function(dragOptions) { + return function(evt) { + var clickMode = gd._fullLayout.clickmode; + + if(clickMode.indexOf('select') > -1) { + selectOnClick(evt.originalEvent, gd, [self.xaxis], [self.yaxis], self.id, dragOptions); + } + + if(clickMode.indexOf('event') > -1) { + // TODO: this does not support right-click. If we want to support it, we + // would likely need to change mapbox to use dragElement instead of straight + // mapbox event binding. Or perhaps better, make a simple wrapper with the + // right mousedown, mousemove, and mouseup handlers just for a left/right click + // pie would use this too. + Fx.click(gd, evt.originalEvent); + } + }; + }; +}; + +proto.updateMap = function(calcData, fullLayout, resolve, reject) { + var self = this; + var map = self.map; + + self.rejectOnError(reject); + + var styleObj = getStyleObj(self.opts.style); + + if(self.styleObj.id !== styleObj.id) { + self.styleObj = styleObj; + map.setStyle(styleObj.style); + + map.once('styledata', function() { + // need to rebuild trace layers on reload + // to avoid 'lost event' errors + self.traceHash = {}; + self.updateData(calcData); + self.updateLayout(fullLayout); + self.resolveOnRender(resolve); + }); + } else { + self.updateData(calcData); + self.updateLayout(fullLayout); + self.resolveOnRender(resolve); + } +}; + +proto.updateData = function(calcData) { + var traceHash = this.traceHash; + var traceObj, trace, i, j; + + // update or create trace objects + for(i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i]; + + trace = calcTrace[0].trace; + traceObj = traceHash[trace.uid]; + + if(traceObj) { + traceObj.update(calcTrace); + } else if(trace._module) { + traceHash[trace.uid] = trace._module.plot(this, calcTrace); + } + } + + // remove empty trace objects + var ids = Object.keys(traceHash); + id_loop: + for(i = 0; i < ids.length; i++) { + var id = ids[i]; + + for(j = 0; j < calcData.length; j++) { + trace = calcData[j][0].trace; + if(id === trace.uid) continue id_loop; + } + + traceObj = traceHash[id]; + traceObj.dispose(); + delete traceHash[id]; + } +}; + +proto.updateLayout = function(fullLayout) { + var map = this.map, + opts = this.opts; + + map.setCenter(convertCenter(opts.center)); + map.setZoom(opts.zoom); + map.setBearing(opts.bearing); + map.setPitch(opts.pitch); + + this.updateLayers(); + this.updateFramework(fullLayout); + this.updateFx(fullLayout); + this.map.resize(); +}; + +proto.resolveOnRender = function(resolve) { + var map = this.map; + + map.on('render', function onRender() { + if(map.loaded()) { + map.off('render', onRender); + // resolve at end of render loop + setTimeout(resolve, 0); + } + }); +}; + +proto.rejectOnError = function(reject) { + var map = this.map; + + function handler() { + reject(new Error(constants.mapOnErrorMsg)); + } + + map.once('error', handler); + map.once('style.error', handler); + map.once('source.error', handler); + map.once('tile.error', handler); + map.once('layer.error', handler); +}; + +proto.createFramework = function(fullLayout) { + var self = this; + + var div = self.div = document.createElement('div'); + div.id = self.uid; + div.style.position = 'absolute'; + self.container.appendChild(div); + + // create mock x/y axes for hover routine + self.xaxis = { + _id: 'x', + c2p: function(v) { return self.project(v).x; } + }; + self.yaxis = { + _id: 'y', + c2p: function(v) { return self.project(v).y; } + }; + + self.updateFramework(fullLayout); +}; + +proto.updateFx = function(fullLayout) { + var self = this; + var map = self.map; + var gd = self.gd; + + if(self.isStatic) return; + + function invert(pxpy) { + var obj = self.map.unproject(pxpy); + return [obj.lng, obj.lat]; + } + + var dragMode = fullLayout.dragmode; + var fillRangeItems; + + if(dragMode === 'select') { + fillRangeItems = function(eventData, poly) { + var ranges = eventData.range = {}; + ranges[self.id] = [ + invert([poly.xmin, poly.ymin]), + invert([poly.xmax, poly.ymax]) + ]; + }; + } else { + fillRangeItems = function(eventData, poly, pts) { + var dataPts = eventData.lassoPoints = {}; + dataPts[self.id] = pts.filtered.map(invert); + }; + } + + // Note: dragOptions is needed to be declared for all dragmodes because + // it's the object that holds persistent selection state. + // Merge old dragOptions with new to keep possibly initialized + // persistent selection state. + var oldDragOptions = self.dragOptions; + self.dragOptions = Lib.extendDeep(oldDragOptions || {}, { + element: self.div, + gd: gd, + plotinfo: { + id: self.id, + xaxis: self.xaxis, + yaxis: self.yaxis, + fillRangeItems: fillRangeItems + }, + xaxes: [self.xaxis], + yaxes: [self.yaxis], + subplot: self.id + }); + + // Unregister the old handler before potentially registering + // a new one. Otherwise multiple click handlers might + // be registered resulting in unwanted behavior. + map.off('click', self.onClickInPanHandler); + if(dragMode === 'select' || dragMode === 'lasso') { + map.dragPan.disable(); + map.on('zoomstart', self.clearSelect); + + self.dragOptions.prepFn = function(e, startX, startY) { + prepSelect(e, startX, startY, self.dragOptions, dragMode); + }; + + dragElement.init(self.dragOptions); + } else { + map.dragPan.enable(); + map.off('zoomstart', self.clearSelect); + self.div.onmousedown = null; + + // TODO: this does not support right-click. If we want to support it, we + // would likely need to change mapbox to use dragElement instead of straight + // mapbox event binding. Or perhaps better, make a simple wrapper with the + // right mousedown, mousemove, and mouseup handlers just for a left/right click + // pie would use this too. + self.onClickInPanHandler = self.onClickInPanFn(self.dragOptions); + map.on('click', self.onClickInPanHandler); + } +}; + +proto.updateFramework = function(fullLayout) { + var domain = fullLayout[this.id].domain; + var size = fullLayout._size; + + var style = this.div.style; + style.width = size.w * (domain.x[1] - domain.x[0]) + 'px'; + style.height = size.h * (domain.y[1] - domain.y[0]) + 'px'; + style.left = size.l + domain.x[0] * size.w + 'px'; + style.top = size.t + (1 - domain.y[1]) * size.h + 'px'; + + this.xaxis._offset = size.l + domain.x[0] * size.w; + this.xaxis._length = size.w * (domain.x[1] - domain.x[0]); + + this.yaxis._offset = size.t + (1 - domain.y[1]) * size.h; + this.yaxis._length = size.h * (domain.y[1] - domain.y[0]); +}; + +proto.updateLayers = function() { + var opts = this.opts; + var layers = opts.layers; + var layerList = this.layerList; + var i; + + // if the layer arrays don't match, + // don't try to be smart, + // delete them all, and start all over. + + if(layers.length !== layerList.length) { + for(i = 0; i < layerList.length; i++) { + layerList[i].dispose(); + } + + layerList = this.layerList = []; + + for(i = 0; i < layers.length; i++) { + layerList.push(createMapboxLayer(this, i, layers[i])); + } + } else { + for(i = 0; i < layers.length; i++) { + layerList[i].update(layers[i]); + } + } +}; + +proto.destroy = function() { + if(this.map) { + this.map.remove(); + this.map = null; + this.container.removeChild(this.div); + } +}; + +proto.toImage = function() { + this.map.stop(); + return this.map.getCanvas().toDataURL(); +}; + +// convenience wrapper to create set multiple layer +// 'layout' or 'paint options at once. +proto.setOptions = function(id, methodName, opts) { + for(var k in opts) { + this.map[methodName](id, k, opts[k]); + } +}; + +// convenience method to project a [lon, lat] array to pixel coords +proto.project = function(v) { + return this.map.project(new mapboxgl.LngLat(v[0], v[1])); +}; + +// get map's current view values in plotly.js notation +proto.getView = function() { + var map = this.map; + + var mapCenter = map.getCenter(); + var center = { lon: mapCenter.lng, lat: mapCenter.lat }; + + return { + center: center, + zoom: map.getZoom(), + bearing: map.getBearing(), + pitch: map.getPitch() + }; +}; + +function getStyleObj(val) { + var styleValues = layoutAttributes.style.values; + var styleDflt = layoutAttributes.style.dflt; + var styleObj = {}; + + if(Lib.isPlainObject(val)) { + styleObj.id = val.id; + styleObj.style = val; + } else if(typeof val === 'string') { + styleObj.id = val; + styleObj.style = (styleValues.indexOf(val) !== -1) ? + convertStyleVal(val) : + val; + } else { + styleObj.id = styleDflt; + styleObj.style = convertStyleVal(styleDflt); + } + + styleObj.transition = {duration: 0, delay: 0}; + + return styleObj; +} + +// if style is part of the 'official' mapbox values, add URL prefix and suffix +function convertStyleVal(val) { + return constants.styleUrlPrefix + val + '-' + constants.styleUrlSuffix; +} + +function convertCenter(center) { + return [center.lon, center.lat]; +} + +},{"../../components/dragelement":592,"../../components/fx":612,"../../lib":696,"../cartesian/select":762,"./constants":800,"./layers":803,"./layout_attributes":804,"mapbox-gl":409}],807:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// This is used exclusively by components inside component arrays, +// hence the 'arraydraw' editType. If this ever gets used elsewhere +// we could generalize it as a function ala font_attributes +module.exports = { + t: { + valType: 'number', + dflt: 0, + + editType: 'arraydraw', + + }, + r: { + valType: 'number', + dflt: 0, + + editType: 'arraydraw', + + }, + b: { + valType: 'number', + dflt: 0, + + editType: 'arraydraw', + + }, + l: { + valType: 'number', + dflt: 0, + + editType: 'arraydraw', + + }, + editType: 'arraydraw' +}; + +},{}],808:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Registry = _dereq_('../registry'); +var PlotSchema = _dereq_('../plot_api/plot_schema'); +var Template = _dereq_('../plot_api/plot_template'); +var Lib = _dereq_('../lib'); +var Color = _dereq_('../components/color'); +var BADNUM = _dereq_('../constants/numerical').BADNUM; + +var axisIDs = _dereq_('../plots/cartesian/axis_ids'); + +var animationAttrs = _dereq_('./animation_attributes'); +var frameAttrs = _dereq_('./frame_attributes'); + +var relinkPrivateKeys = Lib.relinkPrivateKeys; +var _ = Lib._; + +var plots = module.exports = {}; + +// Expose registry methods on Plots for backward-compatibility +Lib.extendFlat(plots, Registry); + +plots.attributes = _dereq_('./attributes'); +plots.attributes.type.values = plots.allTypes; +plots.fontAttrs = _dereq_('./font_attributes'); +plots.layoutAttributes = _dereq_('./layout_attributes'); + +// TODO make this a plot attribute? +plots.fontWeight = 'normal'; + +var transformsRegistry = plots.transformsRegistry; + +var commandModule = _dereq_('./command'); +plots.executeAPICommand = commandModule.executeAPICommand; +plots.computeAPICommandBindings = commandModule.computeAPICommandBindings; +plots.manageCommandObserver = commandModule.manageCommandObserver; +plots.hasSimpleAPICommandBindings = commandModule.hasSimpleAPICommandBindings; + +// in some cases the browser doesn't seem to know how big +// the text is at first, so it needs to draw it, +// then wait a little, then draw it again +plots.redrawText = function(gd) { + gd = Lib.getGraphDiv(gd); + + // do not work if polar is present + if((gd.data && gd.data[0] && gd.data[0].r)) return; + + return new Promise(function(resolve) { + setTimeout(function() { + Registry.getComponentMethod('annotations', 'draw')(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + + (gd.calcdata || []).forEach(function(d) { + if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); + }); + + resolve(plots.previousPromises(gd)); + }, 300); + }); +}; + +// resize plot about the container size +plots.resize = function(gd) { + gd = Lib.getGraphDiv(gd); + + return new Promise(function(resolve, reject) { + + function isHidden(gd) { + var display = window.getComputedStyle(gd).display; + return !display || display === 'none'; + } + + if(!gd || isHidden(gd)) { + reject(new Error('Resize must be passed a displayed plot div element.')); + } + + if(gd._redrawTimer) clearTimeout(gd._redrawTimer); + + gd._redrawTimer = setTimeout(function() { + // return if there is nothing to resize or is hidden + if(!gd.layout || (gd.layout.width && gd.layout.height) || isHidden(gd)) { + resolve(gd); + return; + } + + delete gd.layout.width; + delete gd.layout.height; + + // autosizing doesn't count as a change that needs saving + var oldchanged = gd.changed; + + // nor should it be included in the undo queue + gd.autoplay = true; + + Registry.call('relayout', gd, {autosize: true}).then(function() { + gd.changed = oldchanged; + resolve(gd); + }); + }, 100); + }); +}; + + +// for use in Lib.syncOrAsync, check if there are any +// pending promises in this plot and wait for them +plots.previousPromises = function(gd) { + if((gd._promises || []).length) { + return Promise.all(gd._promises) + .then(function() { gd._promises = []; }); + } +}; + +/** + * Adds the 'Edit chart' link. + * Note that now Plotly.plot() calls this so it can regenerate whenever it replots + * + * Add source links to your graph inside the 'showSources' config argument. + */ +plots.addLinks = function(gd) { + // Do not do anything if showLink and showSources are not set to true in config + if(!gd._context.showLink && !gd._context.showSources) return; + + var fullLayout = gd._fullLayout; + + var linkContainer = Lib.ensureSingle(fullLayout._paper, 'text', 'js-plot-link-container', function(s) { + s.style({ + 'font-family': '"Open Sans", Arial, sans-serif', + 'font-size': '12px', + 'fill': Color.defaultLine, + 'pointer-events': 'all' + }) + .each(function() { + var links = d3.select(this); + links.append('tspan').classed('js-link-to-tool', true); + links.append('tspan').classed('js-link-spacer', true); + links.append('tspan').classed('js-sourcelinks', true); + }); + }); + + // The text node inside svg + var text = linkContainer.node(); + var attrs = {y: fullLayout._paper.attr('height') - 9}; + + // If text's width is bigger than the layout + // Check that text is a child node or document.body + // because otherwise IE/Edge might throw an exception + // when calling getComputedTextLength(). + // Apparently offsetParent is null for invisibles. + if(document.body.contains(text) && text.getComputedTextLength() >= (fullLayout.width - 20)) { + // Align the text at the left + attrs['text-anchor'] = 'start'; + attrs.x = 5; + } + else { + // Align the text at the right + attrs['text-anchor'] = 'end'; + attrs.x = fullLayout._paper.attr('width') - 7; + } + + linkContainer.attr(attrs); + + var toolspan = linkContainer.select('.js-link-to-tool'), + spacespan = linkContainer.select('.js-link-spacer'), + sourcespan = linkContainer.select('.js-sourcelinks'); + + if(gd._context.showSources) gd._context.showSources(gd); + + // 'view in plotly' link for embedded plots + if(gd._context.showLink) positionPlayWithData(gd, toolspan); + + // separator if we have both sources and tool link + spacespan.text((toolspan.text() && sourcespan.text()) ? ' - ' : ''); +}; + +// note that now this function is only adding the brand in +// iframes and 3rd-party apps +function positionPlayWithData(gd, container) { + container.text(''); + var link = container.append('a') + .attr({ + 'xlink:xlink:href': '#', + 'class': 'link--impt link--embedview', + 'font-weight': 'bold' + }) + .text(gd._context.linkText + ' ' + String.fromCharCode(187)); + + if(gd._context.sendData) { + link.on('click', function() { + plots.sendDataToCloud(gd); + }); + } + else { + var path = window.location.pathname.split('/'); + var query = window.location.search; + link.attr({ + 'xlink:xlink:show': 'new', + 'xlink:xlink:href': '/' + path[2].split('.')[0] + '/' + path[1] + query + }); + } +} + +plots.sendDataToCloud = function(gd) { + gd.emit('plotly_beforeexport'); + + var baseUrl = (window.PLOTLYENV || {}).BASE_URL || gd._context.plotlyServerURL; + + var hiddenformDiv = d3.select(gd) + .append('div') + .attr('id', 'hiddenform') + .style('display', 'none'); + + var hiddenform = hiddenformDiv + .append('form') + .attr({ + action: baseUrl + '/external', + method: 'post', + target: '_blank' + }); + + var hiddenformInput = hiddenform + .append('input') + .attr({ + type: 'text', + name: 'data' + }); + + hiddenformInput.node().value = plots.graphJson(gd, false, 'keepdata'); + hiddenform.node().submit(); + hiddenformDiv.remove(); + + gd.emit('plotly_afterexport'); + return false; +}; + +var d3FormatKeys = [ + 'days', 'shortDays', 'months', 'shortMonths', 'periods', + 'dateTime', 'date', 'time', + 'decimal', 'thousands', 'grouping', 'currency' +]; + +var extraFormatKeys = [ + 'year', 'month', 'dayMonth', 'dayMonthYear' +]; + +/* + * Fill in default values + * @param {DOM element} gd + * @param {object} opts + * @param {boolean} opts.skipUpdateCalc: normally if the existing gd.calcdata looks + * compatible with the new gd._fullData we finish by linking the new _fullData traces + * to the old gd.calcdata, so it's correctly set if we're not going to recalc. But also, + * if there are calcTransforms on the trace, we first remap data arrays from the old full + * trace into the new one. Use skipUpdateCalc to defer this (needed by Plotly.react) + * + * gd.data, gd.layout: + * are precisely what the user specified (except as modified by cleanData/cleanLayout), + * these fields shouldn't be modified (except for filling in some auto values) + * nor used directly after the supply defaults step. + * + * gd._fullData, gd._fullLayout: + * are complete descriptions of how to draw the plot, + * use these fields in all required computations. + * + * gd._fullLayout._modules + * is a list of all the trace modules required to draw the plot. + * + * gd._fullLayout._visibleModules + * subset of _modules, a list of modules corresponding to visible:true traces. + * + * gd._fullLayout._basePlotModules + * is a list of all the plot modules required to draw the plot. + * + * gd._fullLayout._transformModules + * is a list of all the transform modules invoked. + * + */ +plots.supplyDefaults = function(gd, opts) { + var skipUpdateCalc = opts && opts.skipUpdateCalc; + var oldFullLayout = gd._fullLayout || {}; + + if(oldFullLayout._skipDefaults) { + delete oldFullLayout._skipDefaults; + return; + } + + var newFullLayout = gd._fullLayout = {}; + var newLayout = gd.layout || {}; + + var oldFullData = gd._fullData || []; + var newFullData = gd._fullData = []; + var newData = gd.data || []; + + var oldCalcdata = gd.calcdata || []; + + var context = gd._context || {}; + + var i; + + // Create all the storage space for frames, but only if doesn't already exist + if(!gd._transitionData) plots.createTransitionData(gd); + + // So we only need to do this once (and since we have gd here) + // get the translated placeholder titles. + // These ones get used as default values so need to be known at supplyDefaults + // others keep their blank defaults but render the placeholder as desired later + // TODO: make these work the same way, only inserting the placeholder text at draw time? + // The challenge is that this has slightly different behavior right now in editable mode: + // using the placeholder as default makes this text permanently (but lightly) visible, + // but explicit '' for these titles gives you a placeholder that's hidden until you mouse + // over it - so you're not distracted by it if you really don't want a title, but if you do + // and you're new to plotly you may not be able to find it. + // When editable=false the two behave the same, no title is drawn. + newFullLayout._dfltTitle = { + plot: _(gd, 'Click to enter Plot title'), + x: _(gd, 'Click to enter X axis title'), + y: _(gd, 'Click to enter Y axis title'), + colorbar: _(gd, 'Click to enter Colorscale title'), + annotation: _(gd, 'new text') + }; + newFullLayout._traceWord = _(gd, 'trace'); + + var formatObj = getFormatObj(gd, d3FormatKeys); + + // stash the token from context so mapbox subplots can use it as default + newFullLayout._mapboxAccessToken = context.mapboxAccessToken; + + // first fill in what we can of layout without looking at data + // because fullData needs a few things from layout + if(oldFullLayout._initialAutoSizeIsDone) { + + // coerce the updated layout while preserving width and height + var oldWidth = oldFullLayout.width, + oldHeight = oldFullLayout.height; + + plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout, formatObj); + + if(!newLayout.width) newFullLayout.width = oldWidth; + if(!newLayout.height) newFullLayout.height = oldHeight; + plots.sanitizeMargins(newFullLayout); + } + else { + + // coerce the updated layout and autosize if needed + plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout, formatObj); + + var missingWidthOrHeight = (!newLayout.width || !newLayout.height), + autosize = newFullLayout.autosize, + autosizable = context.autosizable, + initialAutoSize = missingWidthOrHeight && (autosize || autosizable); + + if(initialAutoSize) plots.plotAutoSize(gd, newLayout, newFullLayout); + else if(missingWidthOrHeight) plots.sanitizeMargins(newFullLayout); + + // for backwards-compatibility with Plotly v1.x.x + if(!autosize && missingWidthOrHeight) { + newLayout.width = newFullLayout.width; + newLayout.height = newFullLayout.height; + } + } + + newFullLayout._d3locale = getFormatter(formatObj, newFullLayout.separators); + newFullLayout._extraFormat = getFormatObj(gd, extraFormatKeys); + + newFullLayout._initialAutoSizeIsDone = true; + + // keep track of how many traces are inputted + newFullLayout._dataLength = newData.length; + + // clear the lists of trace and baseplot modules, and subplots + newFullLayout._modules = []; + newFullLayout._visibleModules = []; + newFullLayout._basePlotModules = []; + var subplots = newFullLayout._subplots = emptySubplotLists(); + + // initialize axis and subplot hash objects for splom-generated grids + var splomAxes = newFullLayout._splomAxes = {x: {}, y: {}}; + var splomSubplots = newFullLayout._splomSubplots = {}; + // initialize splom grid defaults + newFullLayout._splomGridDflt = {}; + + // for stacked area traces to share config across traces + newFullLayout._scatterStackOpts = {}; + // for the first scatter trace on each subplot (so it knows tonext->tozero) + newFullLayout._firstScatter = {}; + + // for traces to request a default rangeslider on their x axes + // eg set `_requestRangeslider.x2 = true` for xaxis2 + newFullLayout._requestRangeslider = {}; + + // pull uids from old data to use as new defaults + newFullLayout._traceUids = getTraceUids(oldFullData, newData); + + // then do the data + newFullLayout._globalTransforms = (gd._context || {}).globalTransforms; + plots.supplyDataDefaults(newData, newFullData, newLayout, newFullLayout); + + // redo grid size defaults with info about splom x/y axes, + // and fill in generated cartesian axes and subplots + var splomXa = Object.keys(splomAxes.x); + var splomYa = Object.keys(splomAxes.y); + if(splomXa.length > 1 && splomYa.length > 1) { + Registry.getComponentMethod('grid', 'sizeDefaults')(newLayout, newFullLayout); + + for(i = 0; i < splomXa.length; i++) { + Lib.pushUnique(subplots.xaxis, splomXa[i]); + } + for(i = 0; i < splomYa.length; i++) { + Lib.pushUnique(subplots.yaxis, splomYa[i]); + } + for(var k in splomSubplots) { + Lib.pushUnique(subplots.cartesian, k); + } + } + + // attach helper method to check whether a plot type is present on graph + newFullLayout._has = plots._hasPlotType.bind(newFullLayout); + + if(oldFullData.length === newFullData.length) { + for(i = 0; i < newFullData.length; i++) { + relinkPrivateKeys(newFullData[i], oldFullData[i]); + } + } + + // finally, fill in the pieces of layout that may need to look at data + plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData, gd._transitionData); + + // Special cases that introduce interactions between traces. + // This is after relinkPrivateKeys so we can use those in crossTraceDefaults + // and after layout module defaults, so we can use eg barmode + var _modules = newFullLayout._visibleModules; + var crossTraceDefaultsFuncs = []; + for(i = 0; i < _modules.length; i++) { + var funci = _modules[i].crossTraceDefaults; + // some trace types share crossTraceDefaults (ie histogram2d, histogram2dcontour) + if(funci) Lib.pushUnique(crossTraceDefaultsFuncs, funci); + } + for(i = 0; i < crossTraceDefaultsFuncs.length; i++) { + crossTraceDefaultsFuncs[i](newFullData, newFullLayout); + } + + // turn on flag to optimize large splom-only graphs + // mostly by omitting SVG layers during Cartesian.drawFramework + newFullLayout._hasOnlyLargeSploms = ( + newFullLayout._basePlotModules.length === 1 && + newFullLayout._basePlotModules[0].name === 'splom' && + splomXa.length > 15 && + splomYa.length > 15 && + newFullLayout.shapes.length === 0 && + newFullLayout.images.length === 0 + ); + + // TODO remove in v2.0.0 + // add has-plot-type refs to fullLayout for backward compatibility + newFullLayout._hasCartesian = newFullLayout._has('cartesian'); + newFullLayout._hasGeo = newFullLayout._has('geo'); + newFullLayout._hasGL3D = newFullLayout._has('gl3d'); + newFullLayout._hasGL2D = newFullLayout._has('gl2d'); + newFullLayout._hasTernary = newFullLayout._has('ternary'); + newFullLayout._hasPie = newFullLayout._has('pie'); + + // relink / initialize subplot axis objects + plots.linkSubplots(newFullData, newFullLayout, oldFullData, oldFullLayout); + + // clean subplots and other artifacts from previous plot calls + plots.cleanPlot(newFullData, newFullLayout, oldFullData, oldFullLayout); + + // relink functions and _ attributes to promote consistency between plots + relinkPrivateKeys(newFullLayout, oldFullLayout); + + // TODO may return a promise + plots.doAutoMargin(gd); + + // set scale after auto margin routine + var axList = axisIDs.list(gd); + for(i = 0; i < axList.length; i++) { + var ax = axList[i]; + ax.setScale(); + } + + // update object references in calcdata + if(!skipUpdateCalc && oldCalcdata.length === newFullData.length) { + plots.supplyDefaultsUpdateCalc(oldCalcdata, newFullData); + } +}; + +plots.supplyDefaultsUpdateCalc = function(oldCalcdata, newFullData) { + for(var i = 0; i < newFullData.length; i++) { + var newTrace = newFullData[i]; + var cd0 = oldCalcdata[i][0]; + if(cd0 && cd0.trace) { + var oldTrace = cd0.trace; + if(oldTrace._hasCalcTransform) { + var arrayAttrs = oldTrace._arrayAttrs; + var j, astr, oldArrayVal; + + for(j = 0; j < arrayAttrs.length; j++) { + astr = arrayAttrs[j]; + oldArrayVal = Lib.nestedProperty(oldTrace, astr).get().slice(); + Lib.nestedProperty(newTrace, astr).set(oldArrayVal); + } + } + cd0.trace = newTrace; + } + } +}; + +/** + * Create a list of uid strings satisfying (in this order of importance): + * 1. all unique, all strings + * 2. matches input uids if provided + * 3. matches previous data uids + */ +function getTraceUids(oldFullData, newData) { + var len = newData.length; + var oldFullInput = []; + var i, prevFullInput; + for(i = 0; i < oldFullData.length; i++) { + var thisFullInput = oldFullData[i]._fullInput; + if(thisFullInput !== prevFullInput) oldFullInput.push(thisFullInput); + prevFullInput = thisFullInput; + } + var oldLen = oldFullInput.length; + var out = new Array(len); + var seenUids = {}; + + function setUid(uid, i) { + out[i] = uid; + seenUids[uid] = 1; + } + + function tryUid(uid, i) { + if(uid && typeof uid === 'string' && !seenUids[uid]) { + setUid(uid, i); + return true; + } + } + + for(i = 0; i < len; i++) { + if(tryUid(newData[i].uid, i)) continue; + if(i < oldLen && tryUid(oldFullInput[i].uid, i)) continue; + setUid(Lib.randstr(seenUids), i); + } + + return out; +} + +/** + * Make a container for collecting subplots we need to display. + * + * Finds all subplot types we need to enumerate once and caches it, + * but makes a new output object each time. + * Single-trace subplots (which have no `id`) such as pie, table, etc + * do not need to be collected because we just draw all visible traces. + */ +var collectableSubplotTypes; +function emptySubplotLists() { + var out = {}; + var i, j; + + if(!collectableSubplotTypes) { + collectableSubplotTypes = []; + + var subplotsRegistry = Registry.subplotsRegistry; + + for(var subplotType in subplotsRegistry) { + var subplotModule = subplotsRegistry[subplotType]; + var subplotAttr = subplotModule.attr; + + if(subplotAttr) { + collectableSubplotTypes.push(subplotType); + + // special case, currently just for cartesian: + // we need to enumerate axes, not just subplots + if(Array.isArray(subplotAttr)) { + for(j = 0; j < subplotAttr.length; j++) { + Lib.pushUnique(collectableSubplotTypes, subplotAttr[j]); + } + } + } + } + } + + for(i = 0; i < collectableSubplotTypes.length; i++) { + out[collectableSubplotTypes[i]] = []; + } + return out; +} + +/** + * getFormatObj: use _context to get the format object from locale. + * Used to get d3.locale argument object and extraFormat argument object + * + * Regarding d3.locale argument : + * decimal and thousands can be overridden later by layout.separators + * grouping and currency are not presently used by our automatic number + * formatting system but can be used by custom formats. + * + * @returns {object} d3.locale format object + */ +function getFormatObj(gd, formatKeys) { + var locale = gd._context.locale; + if(!locale) locale === 'en-US'; + + var formatDone = false; + var formatObj = {}; + + function includeFormat(newFormat) { + var formatFinished = true; + for(var i = 0; i < formatKeys.length; i++) { + var formatKey = formatKeys[i]; + if(!formatObj[formatKey]) { + if(newFormat[formatKey]) { + formatObj[formatKey] = newFormat[formatKey]; + } + else formatFinished = false; + } + } + if(formatFinished) formatDone = true; + } + + // same as localize, look for format parts in each format spec in the chain + for(var i = 0; i < 2; i++) { + var locales = gd._context.locales; + for(var j = 0; j < 2; j++) { + var formatj = (locales[locale] || {}).format; + if(formatj) { + includeFormat(formatj); + if(formatDone) break; + } + locales = Registry.localeRegistry; + } + + var baseLocale = locale.split('-')[0]; + if(formatDone || baseLocale === locale) break; + locale = baseLocale; + } + + // lastly pick out defaults from english (non-US, as DMY is so much more common) + if(!formatDone) includeFormat(Registry.localeRegistry.en.format); + + return formatObj; +} + +/** + * getFormatter: combine the final separators with the locale formatting object + * we pulled earlier to generate number and time formatters + * TODO: remove separators in v2, only use locale, so we don't need this step? + * + * @param {object} formatObj: d3.locale format object + * @param {string} separators: length-2 string to override decimal and thousands + * separators in number formatting + * + * @returns {object} {numberFormat, timeFormat} d3 formatter factory functions + * for numbers and time + */ +function getFormatter(formatObj, separators) { + formatObj.decimal = separators.charAt(0); + formatObj.thousands = separators.charAt(1); + + return d3.locale(formatObj); +} + +// Create storage for all of the data related to frames and transitions: +plots.createTransitionData = function(gd) { + // Set up the default keyframe if it doesn't exist: + if(!gd._transitionData) { + gd._transitionData = {}; + } + + if(!gd._transitionData._frames) { + gd._transitionData._frames = []; + } + + if(!gd._transitionData._frameHash) { + gd._transitionData._frameHash = {}; + } + + if(!gd._transitionData._counter) { + gd._transitionData._counter = 0; + } + + if(!gd._transitionData._interruptCallbacks) { + gd._transitionData._interruptCallbacks = []; + } +}; + +// helper function to be bound to fullLayout to check +// whether a certain plot type is present on plot +// or trace has a category +plots._hasPlotType = function(category) { + var i; + + // check base plot modules + var basePlotModules = this._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + if(basePlotModules[i].name === category) return true; + } + + // check trace modules (including non-visible:true) + var modules = this._modules || []; + for(i = 0; i < modules.length; i++) { + var name = modules[i].name; + if(name === category) return true; + // N.B. this is modules[i] along with 'categories' as a hash object + var _module = Registry.modules[name]; + if(_module && _module.categories[category]) return true; + } + + return false; +}; + +plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var i, j; + + var basePlotModules = oldFullLayout._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.clean) { + _module.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); + } + } + + var hadGl = oldFullLayout._has && oldFullLayout._has('gl'); + var hasGl = newFullLayout._has && newFullLayout._has('gl'); + + if(hadGl && !hasGl) { + if(oldFullLayout._glcontainer !== undefined) { + oldFullLayout._glcontainer.selectAll('.gl-canvas').remove(); + oldFullLayout._glcontainer.selectAll('.no-webgl').remove(); + oldFullLayout._glcanvas = null; + } + } + + var hasInfoLayer = !!oldFullLayout._infolayer; + + oldLoop: + for(i = 0; i < oldFullData.length; i++) { + var oldTrace = oldFullData[i], + oldUid = oldTrace.uid; + + for(j = 0; j < newFullData.length; j++) { + var newTrace = newFullData[j]; + + if(oldUid === newTrace.uid) continue oldLoop; + } + + // clean old colorbars + if(hasInfoLayer) { + oldFullLayout._infolayer.select('.cb' + oldUid).remove(); + } + } + + if(oldFullLayout._zoomlayer) { + oldFullLayout._zoomlayer.selectAll('.select-outline').remove(); + } +}; + +plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var i, j; + + var oldSubplots = oldFullLayout._plots || {}; + var newSubplots = newFullLayout._plots = {}; + var newSubplotList = newFullLayout._subplots; + + var mockGd = { + _fullData: newFullData, + _fullLayout: newFullLayout + }; + + var ids = newSubplotList.cartesian.concat(newSubplotList.gl2d || []); + + for(i = 0; i < ids.length; i++) { + var id = ids[i]; + var oldSubplot = oldSubplots[id]; + var xaxis = axisIDs.getFromId(mockGd, id, 'x'); + var yaxis = axisIDs.getFromId(mockGd, id, 'y'); + var plotinfo; + + // link or create subplot object + if(oldSubplot) { + plotinfo = newSubplots[id] = oldSubplot; + } else { + plotinfo = newSubplots[id] = {}; + plotinfo.id = id; + } + + // update x and y axis layout object refs + plotinfo.xaxis = xaxis; + plotinfo.yaxis = yaxis; + + // By default, we clip at the subplot level, + // but if one trace on a given subplot has *cliponaxis* set to false, + // we need to clip at the trace module layer level; + // find this out here, once of for all. + plotinfo._hasClipOnAxisFalse = false; + + for(j = 0; j < newFullData.length; j++) { + var trace = newFullData[j]; + + if( + trace.xaxis === plotinfo.xaxis._id && + trace.yaxis === plotinfo.yaxis._id && + trace.cliponaxis === false + ) { + plotinfo._hasClipOnAxisFalse = true; + break; + } + } + } + + // while we're at it, link overlaying axes to their main axes and + // anchored axes to the axes they're anchored to + var axList = axisIDs.list(mockGd, null, true); + for(i = 0; i < axList.length; i++) { + var ax = axList[i]; + var mainAx = null; + + if(ax.overlaying) { + mainAx = axisIDs.getFromId(mockGd, ax.overlaying); + + // you cannot overlay an axis that's already overlaying another + if(mainAx && mainAx.overlaying) { + ax.overlaying = false; + mainAx = null; + } + } + ax._mainAxis = mainAx || ax; + + /* + * For now force overlays to overlay completely... so they + * can drag together correctly and share backgrounds. + * Later perhaps we make separate axis domain and + * tick/line domain or something, so they can still share + * the (possibly larger) dragger and background but don't + * have to both be drawn over that whole domain + */ + if(mainAx) ax.domain = mainAx.domain.slice(); + + ax._anchorAxis = ax.anchor === 'free' ? + null : + axisIDs.getFromId(mockGd, ax.anchor); + } +}; + +// This function clears any trace attributes with valType: color and +// no set dflt filed in the plot schema. This is needed because groupby (which +// is the only transform for which this currently applies) supplies parent +// trace defaults, then expanded trace defaults. The result is that `null` +// colors are default-supplied and inherited as a color instead of a null. +// The result is that expanded trace default colors have no effect, with +// the final result that groups are indistinguishable. This function clears +// those colors so that individual groupby groups get unique colors. +plots.clearExpandedTraceDefaultColors = function(trace) { + var colorAttrs, path, i; + + // This uses weird closure state in order to satisfy the linter rule + // that we can't create functions in a loop. + function locateColorAttrs(attr, attrName, attrs, level) { + path[level] = attrName; + path.length = level + 1; + if(attr.valType === 'color' && attr.dflt === undefined) { + colorAttrs.push(path.join('.')); + } + } + + path = []; + + // Get the cached colorAttrs: + colorAttrs = trace._module._colorAttrs; + + // Or else compute and cache the colorAttrs on the module: + if(!colorAttrs) { + trace._module._colorAttrs = colorAttrs = []; + PlotSchema.crawl( + trace._module.attributes, + locateColorAttrs + ); + } + + for(i = 0; i < colorAttrs.length; i++) { + var origprop = Lib.nestedProperty(trace, '_input.' + colorAttrs[i]); + + if(!origprop.get()) { + Lib.nestedProperty(trace, colorAttrs[i]).set(null); + } + } +}; + + +plots.supplyDataDefaults = function(dataIn, dataOut, layout, fullLayout) { + var modules = fullLayout._modules; + var visibleModules = fullLayout._visibleModules; + var basePlotModules = fullLayout._basePlotModules; + var cnt = 0; + var colorCnt = 0; + + var i, fullTrace, trace; + + fullLayout._transformModules = []; + + function pushModule(fullTrace) { + dataOut.push(fullTrace); + + var _module = fullTrace._module; + if(!_module) return; + + Lib.pushUnique(modules, _module); + if(fullTrace.visible === true) Lib.pushUnique(visibleModules, _module); + Lib.pushUnique(basePlotModules, fullTrace._module.basePlotModule); + cnt++; + + // TODO: do we really want color not to increment for explicitly invisible traces? + // This logic is weird, but matches previous behavior: traces that you explicitly + // set to visible:false do not increment the color, but traces WE determine to be + // empty or invalid (and thus set to visible:false) DO increment color. + // I kind of think we should just let all traces increment color, visible or not. + // see mock: axes-autotype-empty vs. a test of restyling visible: false that + // I can't find right now... + if(fullTrace._input.visible !== false) colorCnt++; + } + + var carpetIndex = {}; + var carpetDependents = []; + var dataTemplate = (layout.template || {}).data || {}; + var templater = Template.traceTemplater(dataTemplate); + + for(i = 0; i < dataIn.length; i++) { + trace = dataIn[i]; + + // reuse uid we may have pulled out of oldFullData + // Note: templater supplies trace type + fullTrace = templater.newTrace(trace); + fullTrace.uid = fullLayout._traceUids[i]; + plots.supplyTraceDefaults(trace, fullTrace, colorCnt, fullLayout, i); + + fullTrace.index = i; + fullTrace._input = trace; + fullTrace._expandedIndex = cnt; + + if(fullTrace.transforms && fullTrace.transforms.length) { + var sdInvisible = trace.visible !== false && fullTrace.visible === false; + + var expandedTraces = applyTransforms(fullTrace, dataOut, layout, fullLayout); + + for(var j = 0; j < expandedTraces.length; j++) { + var expandedTrace = expandedTraces[j]; + + // No further templating during transforms. + var fullExpandedTrace = { + _template: fullTrace._template, + type: fullTrace.type, + // set uid using parent uid and expanded index + // to promote consistency between update calls + uid: fullTrace.uid + j + }; + + // If the first supplyDefaults created `visible: false`, + // clear it before running supplyDefaults a second time, + // because sometimes there are items we still want to coerce + // inside trace modules before determining that the trace is + // again `visible: false`, for example partial visibilities + // in `splom` traces. + if(sdInvisible && expandedTrace.visible === false) { + delete expandedTrace.visible; + } + + plots.supplyTraceDefaults(expandedTrace, fullExpandedTrace, cnt, fullLayout, i); + + // relink private (i.e. underscore) keys expanded trace to full expanded trace so + // that transform supply-default methods can set _ keys for future use. + relinkPrivateKeys(fullExpandedTrace, expandedTrace); + + // add info about parent data trace + fullExpandedTrace.index = i; + fullExpandedTrace._input = trace; + fullExpandedTrace._fullInput = fullTrace; + + // add info about the expanded data + fullExpandedTrace._expandedIndex = cnt; + fullExpandedTrace._expandedInput = expandedTrace; + + pushModule(fullExpandedTrace); + } + } + else { + // add identify refs for consistency with transformed traces + fullTrace._fullInput = fullTrace; + fullTrace._expandedInput = fullTrace; + + pushModule(fullTrace); + } + + if(Registry.traceIs(fullTrace, 'carpetAxis')) { + carpetIndex[fullTrace.carpet] = fullTrace; + } + + if(Registry.traceIs(fullTrace, 'carpetDependent')) { + carpetDependents.push(i); + } + } + + for(i = 0; i < carpetDependents.length; i++) { + fullTrace = dataOut[carpetDependents[i]]; + + if(!fullTrace.visible) continue; + + var carpetAxis = carpetIndex[fullTrace.carpet]; + fullTrace._carpet = carpetAxis; + + if(!carpetAxis || !carpetAxis.visible) { + fullTrace.visible = false; + continue; + } + + fullTrace.xaxis = carpetAxis.xaxis; + fullTrace.yaxis = carpetAxis.yaxis; + } +}; + +plots.supplyAnimationDefaults = function(opts) { + opts = opts || {}; + var i; + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs, attr, dflt); + } + + coerce('mode'); + coerce('direction'); + coerce('fromcurrent'); + + if(Array.isArray(opts.frame)) { + optsOut.frame = []; + for(i = 0; i < opts.frame.length; i++) { + optsOut.frame[i] = plots.supplyAnimationFrameDefaults(opts.frame[i] || {}); + } + } else { + optsOut.frame = plots.supplyAnimationFrameDefaults(opts.frame || {}); + } + + if(Array.isArray(opts.transition)) { + optsOut.transition = []; + for(i = 0; i < opts.transition.length; i++) { + optsOut.transition[i] = plots.supplyAnimationTransitionDefaults(opts.transition[i] || {}); + } + } else { + optsOut.transition = plots.supplyAnimationTransitionDefaults(opts.transition || {}); + } + + return optsOut; +}; + +plots.supplyAnimationFrameDefaults = function(opts) { + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs.frame, attr, dflt); + } + + coerce('duration'); + coerce('redraw'); + + return optsOut; +}; + +plots.supplyAnimationTransitionDefaults = function(opts) { + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs.transition, attr, dflt); + } + + coerce('duration'); + coerce('easing'); + + return optsOut; +}; + +plots.supplyFrameDefaults = function(frameIn) { + var frameOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(frameIn, frameOut, frameAttrs, attr, dflt); + } + + coerce('group'); + coerce('name'); + coerce('traces'); + coerce('baseframe'); + coerce('data'); + coerce('layout'); + + return frameOut; +}; + +plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, traceInIndex) { + var colorway = layout.colorway || Color.defaults; + var defaultColor = colorway[colorIndex % colorway.length]; + + var i; + + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, plots.attributes, attr, dflt); + } + + var visible = coerce('visible'); + + coerce('type'); + coerce('name', layout._traceWord + ' ' + traceInIndex); + + // we want even invisible traces to make their would-be subplots visible + // so coerce the subplot id(s) now no matter what + var _module = plots.getModule(traceOut); + + traceOut._module = _module; + if(_module) { + var basePlotModule = _module.basePlotModule; + var subplotAttr = basePlotModule.attr; + var subplotAttrs = basePlotModule.attributes; + if(subplotAttr && subplotAttrs) { + var subplots = layout._subplots; + var subplotId = ''; + + // TODO - currently if we draw an empty gl2d subplot, it draws + // nothing then gets stuck and you can't get it back without newPlot + // sort this out in the regl refactor? but for now just drop empty gl2d subplots + if(basePlotModule.name !== 'gl2d' || visible) { + if(Array.isArray(subplotAttr)) { + for(i = 0; i < subplotAttr.length; i++) { + var attri = subplotAttr[i]; + var vali = Lib.coerce(traceIn, traceOut, subplotAttrs, attri); + + if(subplots[attri]) Lib.pushUnique(subplots[attri], vali); + subplotId += vali; + } + } + else { + subplotId = Lib.coerce(traceIn, traceOut, subplotAttrs, subplotAttr); + } + + if(subplots[basePlotModule.name]) { + Lib.pushUnique(subplots[basePlotModule.name], subplotId); + } + } + } + } + + function coerceUnlessPruned(attr, dflt, cb) { + if(_module && (attr in _module.attributes) && _module.attributes[attr] === undefined) { + // Pruned + } else { + if(cb && typeof cb === 'function') { + cb(); + } else { + coerce(attr, dflt); + } + } + } + + if(visible) { + coerce('customdata'); + coerce('ids'); + + if(Registry.traceIs(traceOut, 'showLegend')) { + traceOut._dfltShowLegend = true; + coerce('showlegend'); + coerce('legendgroup'); + } + else { + traceOut._dfltShowLegend = false; + } + + coerceUnlessPruned('hoverlabel', '', function() { + Registry.getComponentMethod( + 'fx', + 'supplyDefaults' + )(traceIn, traceOut, defaultColor, layout); + }); + + // TODO add per-base-plot-module trace defaults step + + if(_module) { + _module.supplyDefaults(traceIn, traceOut, defaultColor, layout); + Lib.coerceHoverinfo(traceIn, traceOut, layout); + } + + if(!Registry.traceIs(traceOut, 'noOpacity')) coerce('opacity'); + + if(Registry.traceIs(traceOut, 'notLegendIsolatable')) { + // This clears out the legendonly state for traces like carpet that + // cannot be isolated in the legend + traceOut.visible = !!traceOut.visible; + } + + if(_module && _module.selectPoints) { + coerce('selectedpoints'); + } + + plots.supplyTransformDefaults(traceIn, traceOut, layout); + } + + return traceOut; +}; + +/** + * hasMakesDataTransform: does this trace have a transform that makes its own + * data, either by grabbing it from somewhere else or by creating it from input + * parameters? If so, we should still keep going with supplyDefaults + * even if the trace is invisible, which may just be because it has no data yet. + */ +function hasMakesDataTransform(trace) { + var transforms = trace.transforms; + if(Array.isArray(transforms) && transforms.length) { + for(var i = 0; i < transforms.length; i++) { + var ti = transforms[i]; + var _module = ti._module || transformsRegistry[ti.type]; + if(_module && _module.makesData) return true; + } + } + return false; +} + +plots.hasMakesDataTransform = hasMakesDataTransform; + +plots.supplyTransformDefaults = function(traceIn, traceOut, layout) { + // For now we only allow transforms on 1D traces, ie those that specify a _length. + // If we were to implement 2D transforms, we'd need to have each transform + // describe its own applicability and disable itself when it doesn't apply. + // Also allow transforms that make their own data, but not in globalTransforms + if(!(traceOut._length || hasMakesDataTransform(traceIn))) return; + + var globalTransforms = layout._globalTransforms || []; + var transformModules = layout._transformModules || []; + + if(!Array.isArray(traceIn.transforms) && globalTransforms.length === 0) return; + + var containerIn = traceIn.transforms || [], + transformList = globalTransforms.concat(containerIn), + containerOut = traceOut.transforms = []; + + for(var i = 0; i < transformList.length; i++) { + var transformIn = transformList[i], + type = transformIn.type, + _module = transformsRegistry[type], + transformOut; + + /* + * Supply defaults may run twice. First pass runs all supply defaults steps + * and adds the _module to any output transforms. + * If transforms exist another pass is run so that any generated traces also + * go through supply defaults. This has the effect of rerunning + * supplyTransformDefaults. If the transform does not have a `transform` + * function it could not have generated any new traces and the second stage + * is unnecessary. We detect this case with the following variables. + */ + var isFirstStage = !(transformIn._module && transformIn._module === _module), + doLaterStages = _module && typeof _module.transform === 'function'; + + if(!_module) Lib.warn('Unrecognized transform type ' + type + '.'); + + if(_module && _module.supplyDefaults && (isFirstStage || doLaterStages)) { + transformOut = _module.supplyDefaults(transformIn, traceOut, layout, traceIn); + transformOut.type = type; + transformOut._module = _module; + + Lib.pushUnique(transformModules, _module); + } + else { + transformOut = Lib.extendFlat({}, transformIn); + } + + containerOut.push(transformOut); + } +}; + +function applyTransforms(fullTrace, fullData, layout, fullLayout) { + var container = fullTrace.transforms, + dataOut = [fullTrace]; + + for(var i = 0; i < container.length; i++) { + var transform = container[i], + _module = transformsRegistry[transform.type]; + + if(_module && _module.transform) { + dataOut = _module.transform(dataOut, { + transform: transform, + fullTrace: fullTrace, + fullData: fullData, + layout: layout, + fullLayout: fullLayout, + transformIndex: i + }); + } + } + + return dataOut; +} + +plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, plots.layoutAttributes, attr, dflt); + } + + var template = layoutIn.template; + if(Lib.isPlainObject(template)) { + layoutOut.template = template; + layoutOut._template = template.layout; + layoutOut._dataTemplate = template.data; + } + + var globalFont = Lib.coerceFont(coerce, 'font'); + + coerce('title', layoutOut._dfltTitle.plot); + + Lib.coerceFont(coerce, 'titlefont', { + family: globalFont.family, + size: Math.round(globalFont.size * 1.4), + color: globalFont.color + }); + + // Make sure that autosize is defaulted to *true* + // on layouts with no set width and height for backward compatibly, + // in particular https://plot.ly/javascript/responsive-fluid-layout/ + // + // Before https://github.com/plotly/plotly.js/pull/635 , + // layouts with no set width and height were set temporary set to 'initial' + // to pass through the autosize routine + // + // This behavior is subject to change in v2. + coerce('autosize', !(layoutIn.width && layoutIn.height)); + + coerce('width'); + coerce('height'); + coerce('margin.l'); + coerce('margin.r'); + coerce('margin.t'); + coerce('margin.b'); + coerce('margin.pad'); + coerce('margin.autoexpand'); + + if(layoutIn.width && layoutIn.height) plots.sanitizeMargins(layoutOut); + + Registry.getComponentMethod('grid', 'sizeDefaults')(layoutIn, layoutOut); + + coerce('paper_bgcolor'); + + coerce('separators', formatObj.decimal + formatObj.thousands); + coerce('hidesources'); + + coerce('colorway'); + + coerce('datarevision'); + + coerce('modebar.orientation'); + coerce('modebar.bgcolor', Color.addOpacity(layoutOut.paper_bgcolor, 0.5)); + var modebarDefaultColor = Color.contrast(Color.rgb(layoutOut.modebar.bgcolor)); + coerce('modebar.color', Color.addOpacity(modebarDefaultColor, 0.3)); + coerce('modebar.activecolor', Color.addOpacity(modebarDefaultColor, 0.7)); + + // do not include defaults in fullLayout when users do not set transition + if(Lib.isPlainObject(layoutIn.transition)) { + coerce('transition.duration'); + coerce('transition.easing'); + } + + Registry.getComponentMethod( + 'calendars', + 'handleDefaults' + )(layoutIn, layoutOut, 'calendar'); + + Registry.getComponentMethod( + 'fx', + 'supplyLayoutGlobalDefaults' + )(layoutIn, layoutOut, coerce); +}; + +plots.plotAutoSize = function plotAutoSize(gd, layout, fullLayout) { + var context = gd._context || {}, + frameMargins = context.frameMargins, + newWidth, + newHeight; + + var isPlotDiv = Lib.isPlotDiv(gd); + + if(isPlotDiv) gd.emit('plotly_autosize'); + + // embedded in an iframe - just take the full iframe size + // if we get to this point, with no aspect ratio restrictions + if(context.fillFrame) { + newWidth = window.innerWidth; + newHeight = window.innerHeight; + + // somehow we get a few extra px height sometimes... + // just hide it + document.body.style.overflow = 'hidden'; + } + else { + // plotly.js - let the developers do what they want, either + // provide height and width for the container div, + // specify size in layout, or take the defaults, + // but don't enforce any ratio restrictions + var computedStyle = isPlotDiv ? window.getComputedStyle(gd) : {}; + + newWidth = parseFloat(computedStyle.width) || parseFloat(computedStyle.maxWidth) || fullLayout.width; + newHeight = parseFloat(computedStyle.height) || parseFloat(computedStyle.maxHeight) || fullLayout.height; + + if(isNumeric(frameMargins) && frameMargins > 0) { + var factor = 1 - 2 * frameMargins; + newWidth = Math.round(factor * newWidth); + newHeight = Math.round(factor * newHeight); + } + } + + var minWidth = plots.layoutAttributes.width.min, + minHeight = plots.layoutAttributes.height.min; + if(newWidth < minWidth) newWidth = minWidth; + if(newHeight < minHeight) newHeight = minHeight; + + var widthHasChanged = !layout.width && + (Math.abs(fullLayout.width - newWidth) > 1), + heightHasChanged = !layout.height && + (Math.abs(fullLayout.height - newHeight) > 1); + + if(heightHasChanged || widthHasChanged) { + if(widthHasChanged) fullLayout.width = newWidth; + if(heightHasChanged) fullLayout.height = newHeight; + } + + // cache initial autosize value, used in relayout when + // width or height values are set to null + if(!gd._initialAutoSize) { + gd._initialAutoSize = { width: newWidth, height: newHeight }; + } + + plots.sanitizeMargins(fullLayout); +}; + +plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData, transitionData) { + var componentsRegistry = Registry.componentsRegistry; + var basePlotModules = layoutOut._basePlotModules; + var component, i, _module; + + var Cartesian = Registry.subplotsRegistry.cartesian; + + // check if any components need to add more base plot modules + // that weren't captured by traces + for(component in componentsRegistry) { + _module = componentsRegistry[component]; + + if(_module.includeBasePlot) { + _module.includeBasePlot(layoutIn, layoutOut); + } + } + + // make sure we *at least* have some cartesian axes + if(!basePlotModules.length) { + basePlotModules.push(Cartesian); + } + + // ensure all cartesian axes have at least one subplot + if(layoutOut._has('cartesian')) { + Registry.getComponentMethod('grid', 'contentDefaults')(layoutIn, layoutOut); + Cartesian.finalizeSubplots(layoutIn, layoutOut); + } + + // sort subplot lists + for(var subplotType in layoutOut._subplots) { + layoutOut._subplots[subplotType].sort(Lib.subplotSort); + } + + // base plot module layout defaults + for(i = 0; i < basePlotModules.length; i++) { + _module = basePlotModules[i]; + + // e.g. pie does not have a layout-defaults step + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } + + // trace module layout defaults + // use _modules rather than _visibleModules so that even + // legendonly traces can include settings - eg barmode, which affects + // legend.traceorder default value. + var modules = layoutOut._modules; + for(i = 0; i < modules.length; i++) { + _module = modules[i]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } + + // transform module layout defaults + var transformModules = layoutOut._transformModules; + for(i = 0; i < transformModules.length; i++) { + _module = transformModules[i]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData, transitionData); + } + } + + for(component in componentsRegistry) { + _module = componentsRegistry[component]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } +}; + +// Remove all plotly attributes from a div so it can be replotted fresh +// TODO: these really need to be encapsulated into a much smaller set... +plots.purge = function(gd) { + // note: we DO NOT remove _context because it doesn't change when we insert + // a new plot, and may have been set outside of our scope. + + var fullLayout = gd._fullLayout || {}; + if(fullLayout._glcontainer !== undefined) { + fullLayout._glcontainer.selectAll('.gl-canvas').remove(); + fullLayout._glcontainer.remove(); + fullLayout._glcanvas = null; + } + if(fullLayout._geocontainer !== undefined) fullLayout._geocontainer.remove(); + + // remove modebar + if(fullLayout._modeBar) fullLayout._modeBar.destroy(); + + if(gd._transitionData) { + // Ensure any dangling callbacks are simply dropped if the plot is purged. + // This is more or less only actually important for testing. + if(gd._transitionData._interruptCallbacks) { + gd._transitionData._interruptCallbacks.length = 0; + } + + if(gd._transitionData._animationRaf) { + window.cancelAnimationFrame(gd._transitionData._animationRaf); + } + } + + // remove any planned throttles + Lib.clearThrottle(); + + // remove responsive handler + Lib.clearResponsive(gd); + + // data and layout + delete gd.data; + delete gd.layout; + delete gd._fullData; + delete gd._fullLayout; + delete gd.calcdata; + delete gd.framework; + delete gd.empty; + + delete gd.fid; + + delete gd.undoqueue; // action queue + delete gd.undonum; + delete gd.autoplay; // are we doing an action that doesn't go in undo queue? + delete gd.changed; + + // these get recreated on Plotly.plot anyway, but just to be safe + // (and to have a record of them...) + delete gd._promises; + delete gd._redrawTimer; + delete gd._hmlumcount; + delete gd._hmpixcount; + delete gd._transitionData; + delete gd._transitioning; + delete gd._initialAutoSize; + delete gd._transitioningWithDuration; + + // created during certain events, that *should* clean them up + // themselves, but may not if there was an error + delete gd._dragging; + delete gd._dragged; + delete gd._hoverdata; + delete gd._snapshotInProgress; + delete gd._editing; + delete gd._replotPending; + delete gd._mouseDownTime; + delete gd._legendMouseDownTime; + + // remove all event listeners + if(gd.removeAllListeners) gd.removeAllListeners(); +}; + +plots.style = function(gd) { + var _modules = gd._fullLayout._visibleModules; + var styleModules = []; + var i; + + // some trace modules reuse the same style method, + // make sure to not unnecessary call them multiple times. + + for(i = 0; i < _modules.length; i++) { + var _module = _modules[i]; + if(_module.style) { + Lib.pushUnique(styleModules, _module.style); + } + } + + for(i = 0; i < styleModules.length; i++) { + styleModules[i](gd); + } +}; + +plots.sanitizeMargins = function(fullLayout) { + // polar doesn't do margins... + if(!fullLayout || !fullLayout.margin) return; + + var width = fullLayout.width, + height = fullLayout.height, + margin = fullLayout.margin, + plotWidth = width - (margin.l + margin.r), + plotHeight = height - (margin.t + margin.b), + correction; + + // if margin.l + margin.r = 0 then plotWidth > 0 + // as width >= 10 by supplyDefaults + // similarly for margin.t + margin.b + + if(plotWidth < 0) { + correction = (width - 1) / (margin.l + margin.r); + margin.l = Math.floor(correction * margin.l); + margin.r = Math.floor(correction * margin.r); + } + + if(plotHeight < 0) { + correction = (height - 1) / (margin.t + margin.b); + margin.t = Math.floor(correction * margin.t); + margin.b = Math.floor(correction * margin.b); + } +}; + +plots.clearAutoMarginIds = function(gd) { + gd._fullLayout._pushmarginIds = {}; +}; + +plots.allowAutoMargin = function(gd, id) { + gd._fullLayout._pushmarginIds[id] = 1; +}; + +function setupAutoMargin(fullLayout) { + if(!fullLayout._pushmargin) fullLayout._pushmargin = {}; + if(!fullLayout._pushmarginIds) fullLayout._pushmarginIds = {}; +} + +/** + * autoMargin: called by components that may need to expand the margins to + * be rendered on-plot. + * + * @param {DOM element} gd + * @param {string} id - an identifier unique (within this plot) to this object, + * so we can remove a previous margin expansion from the same object. + * @param {object} o - the margin requirements of this object, or omit to delete + * this entry (like if it's hidden). Keys are: + * x, y: plot fraction of the anchor point. + * xl, xr, yt, yb: if the object has an extent defined in plot fraction, + * you can specify both edges as plot fractions in each dimension + * l, r, t, b: the pixels to pad past the plot fraction x[l|r] and y[t|b] + * pad: extra pixels to add in all directions, default 12 (why?) + */ +plots.autoMargin = function(gd, id, o) { + var fullLayout = gd._fullLayout; + + setupAutoMargin(fullLayout); + + var pushMargin = fullLayout._pushmargin; + var pushMarginIds = fullLayout._pushmarginIds; + + if(fullLayout.margin.autoexpand !== false) { + if(!o) { + delete pushMargin[id]; + delete pushMarginIds[id]; + } + else { + var pad = o.pad; + if(pad === undefined) { + var margin = fullLayout.margin; + // if no explicit pad is given, use 12px unless there's a + // specified margin that's smaller than that + pad = Math.min(12, margin.l, margin.r, margin.t, margin.b); + } + + // if the item is too big, just give it enough automargin to + // make sure you can still grab it and bring it back + if(o.l + o.r > fullLayout.width * 0.5) o.l = o.r = 0; + if(o.b + o.t > fullLayout.height * 0.5) o.b = o.t = 0; + + var xl = o.xl !== undefined ? o.xl : o.x; + var xr = o.xr !== undefined ? o.xr : o.x; + var yt = o.yt !== undefined ? o.yt : o.y; + var yb = o.yb !== undefined ? o.yb : o.y; + + pushMargin[id] = { + l: {val: xl, size: o.l + pad}, + r: {val: xr, size: o.r + pad}, + b: {val: yb, size: o.b + pad}, + t: {val: yt, size: o.t + pad} + }; + pushMarginIds[id] = 1; + } + + if(!fullLayout._replotting) plots.doAutoMargin(gd); + } +}; + +plots.doAutoMargin = function(gd) { + var fullLayout = gd._fullLayout; + if(!fullLayout._size) fullLayout._size = {}; + setupAutoMargin(fullLayout); + + var gs = fullLayout._size, + oldmargins = JSON.stringify(gs); + + // adjust margins for outside components + // fullLayout.margin is the requested margin, + // fullLayout._size has margins and plotsize after adjustment + var ml = Math.max(fullLayout.margin.l || 0, 0); + var mr = Math.max(fullLayout.margin.r || 0, 0); + var mt = Math.max(fullLayout.margin.t || 0, 0); + var mb = Math.max(fullLayout.margin.b || 0, 0); + var pushMargin = fullLayout._pushmargin; + var pushMarginIds = fullLayout._pushmarginIds; + + if(fullLayout.margin.autoexpand !== false) { + + for(var k in pushMargin) { + if(!pushMarginIds[k]) delete pushMargin[k]; + } + + // fill in the requested margins + pushMargin.base = { + l: {val: 0, size: ml}, + r: {val: 1, size: mr}, + t: {val: 1, size: mt}, + b: {val: 0, size: mb} + }; + + // now cycle through all the combinations of l and r + // (and t and b) to find the required margins + + for(var k1 in pushMargin) { + + var pushleft = pushMargin[k1].l || {}, + pushbottom = pushMargin[k1].b || {}, + fl = pushleft.val, + pl = pushleft.size, + fb = pushbottom.val, + pb = pushbottom.size; + + for(var k2 in pushMargin) { + if(isNumeric(pl) && pushMargin[k2].r) { + var fr = pushMargin[k2].r.val, + pr = pushMargin[k2].r.size; + + if(fr > fl) { + var newl = (pl * fr + + (pr - fullLayout.width) * fl) / (fr - fl), + newr = (pr * (1 - fl) + + (pl - fullLayout.width) * (1 - fr)) / (fr - fl); + if(newl >= 0 && newr >= 0 && newl + newr > ml + mr) { + ml = newl; + mr = newr; + } + } + } + + if(isNumeric(pb) && pushMargin[k2].t) { + var ft = pushMargin[k2].t.val, + pt = pushMargin[k2].t.size; + + if(ft > fb) { + var newb = (pb * ft + + (pt - fullLayout.height) * fb) / (ft - fb), + newt = (pt * (1 - fb) + + (pb - fullLayout.height) * (1 - ft)) / (ft - fb); + if(newb >= 0 && newt >= 0 && newb + newt > mb + mt) { + mb = newb; + mt = newt; + } + } + } + } + } + } + + gs.l = Math.round(ml); + gs.r = Math.round(mr); + gs.t = Math.round(mt); + gs.b = Math.round(mb); + gs.p = Math.round(fullLayout.margin.pad); + gs.w = Math.round(fullLayout.width) - gs.l - gs.r; + gs.h = Math.round(fullLayout.height) - gs.t - gs.b; + + // if things changed and we're not already redrawing, trigger a redraw + if(!fullLayout._replotting && + oldmargins !== '{}' && + oldmargins !== JSON.stringify(fullLayout._size) + ) { + if('_redrawFromAutoMarginCount' in fullLayout) { + fullLayout._redrawFromAutoMarginCount++; + } else { + fullLayout._redrawFromAutoMarginCount = 1; + } + return Registry.call('plot', gd); + } +}; + +/** + * JSONify the graph data and layout + * + * This function needs to recurse because some src can be inside + * sub-objects. + * + * It also strips out functions and private (starts with _) elements. + * Therefore, we can add temporary things to data and layout that don't + * get saved. + * + * @param gd The graphDiv + * @param {Boolean} dataonly If true, don't return layout. + * @param {'keepref'|'keepdata'|'keepall'} [mode='keepref'] Filter what's kept + * keepref: remove data for which there's a src present + * eg if there's xsrc present (and xsrc is well-formed, + * ie has : and some chars before it), strip out x + * keepdata: remove all src tags, don't remove the data itself + * keepall: keep data and src + * @param {String} output If you specify 'object', the result will not be stringified + * @param {Boolean} useDefaults If truthy, use _fullLayout and _fullData + * @returns {Object|String} + */ +plots.graphJson = function(gd, dataonly, mode, output, useDefaults) { + // if the defaults aren't supplied yet, we need to do that... + if((useDefaults && dataonly && !gd._fullData) || + (useDefaults && !dataonly && !gd._fullLayout)) { + plots.supplyDefaults(gd); + } + + var data = (useDefaults) ? gd._fullData : gd.data, + layout = (useDefaults) ? gd._fullLayout : gd.layout, + frames = (gd._transitionData || {})._frames; + + function stripObj(d) { + if(typeof d === 'function') { + return null; + } + if(Lib.isPlainObject(d)) { + var o = {}, v, src; + for(v in d) { + // remove private elements and functions + // _ is for private, [ is a mistake ie [object Object] + if(typeof d[v] === 'function' || + ['_', '['].indexOf(v.charAt(0)) !== -1) { + continue; + } + + // look for src/data matches and remove the appropriate one + if(mode === 'keepdata') { + // keepdata: remove all ...src tags + if(v.substr(v.length - 3) === 'src') { + continue; + } + } + else if(mode === 'keepstream') { + // keep sourced data if it's being streamed. + // similar to keepref, but if the 'stream' object exists + // in a trace, we will keep the data array. + src = d[v + 'src']; + if(typeof src === 'string' && src.indexOf(':') > 0) { + if(!Lib.isPlainObject(d.stream)) { + continue; + } + } + } + else if(mode !== 'keepall') { + // keepref: remove sourced data but only + // if the source tag is well-formed + src = d[v + 'src']; + if(typeof src === 'string' && src.indexOf(':') > 0) { + continue; + } + } + + // OK, we're including this... recurse into it + o[v] = stripObj(d[v]); + } + return o; + } + + if(Array.isArray(d)) { + return d.map(stripObj); + } + + if(Lib.isTypedArray(d)) { + return Lib.simpleMap(d, Lib.identity); + } + + // convert native dates to date strings... + // mostly for external users exporting to plotly + if(Lib.isJSDate(d)) return Lib.ms2DateTimeLocal(+d); + + return d; + } + + var obj = { + data: (data || []).map(function(v) { + var d = stripObj(v); + // fit has some little arrays in it that don't contain data, + // just fit params and meta + if(dataonly) { delete d.fit; } + return d; + }) + }; + if(!dataonly) { obj.layout = stripObj(layout); } + + if(gd.framework && gd.framework.isPolar) obj = gd.framework.getConfig(); + + if(frames) obj.frames = stripObj(frames); + + return (output === 'object') ? obj : JSON.stringify(obj); +}; + +/** + * Modify a keyframe using a list of operations: + * + * @param {array of objects} operations + * Sequence of operations to be performed on the keyframes + */ +plots.modifyFrames = function(gd, operations) { + var i, op, frame; + var _frames = gd._transitionData._frames; + var _frameHash = gd._transitionData._frameHash; + + for(i = 0; i < operations.length; i++) { + op = operations[i]; + + switch(op.type) { + // No reason this couldn't exist, but is currently unused/untested: + /* case 'rename': + frame = _frames[op.index]; + delete _frameHash[frame.name]; + _frameHash[op.name] = frame; + frame.name = op.name; + break;*/ + case 'replace': + frame = op.value; + var oldName = (_frames[op.index] || {}).name; + var newName = frame.name; + _frames[op.index] = _frameHash[newName] = frame; + + if(newName !== oldName) { + // If name has changed in addition to replacement, then update + // the lookup table: + delete _frameHash[oldName]; + _frameHash[newName] = frame; + } + + break; + case 'insert': + frame = op.value; + _frameHash[frame.name] = frame; + _frames.splice(op.index, 0, frame); + break; + case 'delete': + frame = _frames[op.index]; + delete _frameHash[frame.name]; + _frames.splice(op.index, 1); + break; + } + } + + return Promise.resolve(); +}; + +/* + * Compute a keyframe. Merge a keyframe into its base frame(s) and + * expand properties. + * + * @param {object} frameLookup + * An object containing frames keyed by name (i.e. gd._transitionData._frameHash) + * @param {string} frame + * The name of the keyframe to be computed + * + * Returns: a new object with the merged content + */ +plots.computeFrame = function(gd, frameName) { + var frameLookup = gd._transitionData._frameHash; + var i, traceIndices, traceIndex, destIndex; + + // Null or undefined will fail on .toString(). We'll allow numbers since we + // make it clear frames must be given string names, but we'll allow numbers + // here since they're otherwise fine for looking up frames as long as they're + // properly cast to strings. We really just want to ensure here that this + // 1) doesn't fail, and + // 2) doens't give an incorrect answer (which String(frameName) would) + if(!frameName) { + throw new Error('computeFrame must be given a string frame name'); + } + + var framePtr = frameLookup[frameName.toString()]; + + // Return false if the name is invalid: + if(!framePtr) { + return false; + } + + var frameStack = [framePtr]; + var frameNameStack = [framePtr.name]; + + // Follow frame pointers: + while(framePtr.baseframe && (framePtr = frameLookup[framePtr.baseframe.toString()])) { + // Avoid infinite loops: + if(frameNameStack.indexOf(framePtr.name) !== -1) break; + + frameStack.push(framePtr); + frameNameStack.push(framePtr.name); + } + + // A new object for the merged result: + var result = {}; + + // Merge, starting with the last and ending with the desired frame: + while((framePtr = frameStack.pop())) { + if(framePtr.layout) { + result.layout = plots.extendLayout(result.layout, framePtr.layout); + } + + if(framePtr.data) { + if(!result.data) { + result.data = []; + } + traceIndices = framePtr.traces; + + if(!traceIndices) { + // If not defined, assume serial order starting at zero + traceIndices = []; + for(i = 0; i < framePtr.data.length; i++) { + traceIndices[i] = i; + } + } + + if(!result.traces) { + result.traces = []; + } + + for(i = 0; i < framePtr.data.length; i++) { + // Loop through this frames data, find out where it should go, + // and merge it! + traceIndex = traceIndices[i]; + if(traceIndex === undefined || traceIndex === null) { + continue; + } + + destIndex = result.traces.indexOf(traceIndex); + if(destIndex === -1) { + destIndex = result.data.length; + result.traces[destIndex] = traceIndex; + } + + result.data[destIndex] = plots.extendTrace(result.data[destIndex], framePtr.data[i]); + } + } + } + + return result; +}; + +/* + * Recompute the lookup table that maps frame name -> frame object. addFrames/ + * deleteFrames already manages this data one at a time, so the only time this + * is necessary is if you poke around manually in `gd._transitionData._frames` + * and create and haven't updated the lookup table. + */ +plots.recomputeFrameHash = function(gd) { + var hash = gd._transitionData._frameHash = {}; + var frames = gd._transitionData._frames; + for(var i = 0; i < frames.length; i++) { + var frame = frames[i]; + if(frame && frame.name) { + hash[frame.name] = frame; + } + } +}; + +/** + * Extend an object, treating container arrays very differently by extracting + * their contents and merging them separately. + * + * This exists so that we can extendDeepNoArrays and avoid stepping into data + * arrays without knowledge of the plot schema, but so that we may also manually + * recurse into known container arrays, such as transforms. + * + * See extendTrace and extendLayout below for usage. + */ +plots.extendObjectWithContainers = function(dest, src, containerPaths) { + var containerProp, containerVal, i, j, srcProp, destProp, srcContainer, destContainer; + var copy = Lib.extendDeepNoArrays({}, src || {}); + var expandedObj = Lib.expandObjectPaths(copy); + var containerObj = {}; + + // Step through and extract any container properties. Otherwise extendDeepNoArrays + // will clobber any existing properties with an empty array and then supplyDefaults + // will reset everything to defaults. + if(containerPaths && containerPaths.length) { + for(i = 0; i < containerPaths.length; i++) { + containerProp = Lib.nestedProperty(expandedObj, containerPaths[i]); + containerVal = containerProp.get(); + + if(containerVal === undefined) { + Lib.nestedProperty(containerObj, containerPaths[i]).set(null); + } + else { + containerProp.set(null); + Lib.nestedProperty(containerObj, containerPaths[i]).set(containerVal); + } + } + } + + dest = Lib.extendDeepNoArrays(dest || {}, expandedObj); + + if(containerPaths && containerPaths.length) { + for(i = 0; i < containerPaths.length; i++) { + srcProp = Lib.nestedProperty(containerObj, containerPaths[i]); + srcContainer = srcProp.get(); + + if(!srcContainer) continue; + + destProp = Lib.nestedProperty(dest, containerPaths[i]); + destContainer = destProp.get(); + + if(!Array.isArray(destContainer)) { + destContainer = []; + destProp.set(destContainer); + } + + for(j = 0; j < srcContainer.length; j++) { + var srcObj = srcContainer[j]; + + if(srcObj === null) destContainer[j] = null; + else { + destContainer[j] = plots.extendObjectWithContainers(destContainer[j], srcObj); + } + } + + destProp.set(destContainer); + } + } + + return dest; +}; + +plots.dataArrayContainers = ['transforms', 'dimensions']; +plots.layoutArrayContainers = Registry.layoutArrayContainers; + +/* + * Extend a trace definition. This method: + * + * 1. directly transfers any array references + * 2. manually recurses into container arrays like transforms + * + * The result is the original object reference with the new contents merged in. + */ +plots.extendTrace = function(destTrace, srcTrace) { + return plots.extendObjectWithContainers(destTrace, srcTrace, plots.dataArrayContainers); +}; + +/* + * Extend a layout definition. This method: + * + * 1. directly transfers any array references (not critically important for + * layout since there aren't really data arrays) + * 2. manually recurses into container arrays like annotations + * + * The result is the original object reference with the new contents merged in. + */ +plots.extendLayout = function(destLayout, srcLayout) { + return plots.extendObjectWithContainers(destLayout, srcLayout, plots.layoutArrayContainers); +}; + +/** + * Transition to a set of new data and layout properties + * + * @param {DOM element} gd + * the DOM element of the graph container div + * @param {Object[]} data + * an array of data objects following the normal Plotly data definition format + * @param {Object} layout + * a layout object, following normal Plotly layout format + * @param {Number[]} traces + * indices of the corresponding traces specified in `data` + * @param {Object} frameOpts + * options for the frame (i.e. whether to redraw post-transition) + * @param {Object} transitionOpts + * options for the transition + */ +plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts) { + var i, traceIdx; + + var dataLength = Array.isArray(data) ? data.length : 0; + var traceIndices = traces.slice(0, dataLength); + + var transitionedTraces = []; + + function prepareTransitions() { + var i; + + for(i = 0; i < traceIndices.length; i++) { + var traceIdx = traceIndices[i]; + var trace = gd._fullData[traceIdx]; + var module = trace._module; + + // There's nothing to do if this module is not defined: + if(!module) continue; + + // Don't register the trace as transitioned if it doesn't know what to do. + // If it *is* registered, it will receive a callback that it's responsible + // for calling in order to register the transition as having completed. + if(module.animatable) { + transitionedTraces.push(traceIdx); + } + + gd.data[traceIndices[i]] = plots.extendTrace(gd.data[traceIndices[i]], data[i]); + } + + // Follow the same procedure. Clone it so we don't mangle the input, then + // expand any object paths so we can merge deep into gd.layout: + var layoutUpdate = Lib.expandObjectPaths(Lib.extendDeepNoArrays({}, layout)); + + // Before merging though, we need to modify the incoming layout. We only + // know how to *transition* layout ranges, so it's imperative that a new + // range not be sent to the layout before the transition has started. So + // we must remove the things we can transition: + var axisAttrRe = /^[xy]axis[0-9]*$/; + for(var attr in layoutUpdate) { + if(!axisAttrRe.test(attr)) continue; + delete layoutUpdate[attr].range; + } + + plots.extendLayout(gd.layout, layoutUpdate); + + // Supply defaults after applying the incoming properties. Note that any attempt + // to simplify this step and reduce the amount of work resulted in the reconstruction + // of essentially the whole supplyDefaults step, so that it seems sensible to just use + // supplyDefaults even though it's heavier than would otherwise be desired for + // transitions: + + // first delete calcdata so supplyDefaults knows a calc step is coming + delete gd.calcdata; + + plots.supplyDefaults(gd); + plots.doCalcdata(gd); + + return Promise.resolve(); + } + + function executeCallbacks(list) { + var p = Promise.resolve(); + if(!list) return p; + while(list.length) { + p = p.then((list.shift())); + } + return p; + } + + function flushCallbacks(list) { + if(!list) return; + while(list.length) { + list.shift(); + } + } + + var aborted = false; + + function executeTransitions() { + gd.emit('plotly_transitioning', []); + + return new Promise(function(resolve) { + // This flag is used to disabled things like autorange: + gd._transitioning = true; + + // When instantaneous updates are coming through quickly, it's too much to simply disable + // all interaction, so store this flag so we can disambiguate whether mouse interactions + // should be fully disabled or not: + if(transitionOpts.duration > 0) { + gd._transitioningWithDuration = true; + } + + + // If another transition is triggered, this callback will be executed simply because it's + // in the interruptCallbacks queue. If this transition completes, it will instead flush + // that queue and forget about this callback. + gd._transitionData._interruptCallbacks.push(function() { + aborted = true; + }); + + if(frameOpts.redraw) { + gd._transitionData._interruptCallbacks.push(function() { + return Registry.call('redraw', gd); + }); + } + + // Emit this and make sure it happens last: + gd._transitionData._interruptCallbacks.push(function() { + gd.emit('plotly_transitioninterrupted', []); + }); + + // Construct callbacks that are executed on transition end. This ensures the d3 transitions + // are *complete* before anything else is done. + var numCallbacks = 0; + var numCompleted = 0; + function makeCallback() { + numCallbacks++; + return function() { + numCompleted++; + // When all are complete, perform a redraw: + if(!aborted && numCompleted === numCallbacks) { + completeTransition(resolve); + } + }; + } + + var traceTransitionOpts; + var j; + var basePlotModules = gd._fullLayout._basePlotModules; + var hasAxisTransition = false; + + if(layout) { + for(j = 0; j < basePlotModules.length; j++) { + if(basePlotModules[j].transitionAxes) { + var newLayout = Lib.expandObjectPaths(layout); + hasAxisTransition = basePlotModules[j].transitionAxes(gd, newLayout, transitionOpts, makeCallback) || hasAxisTransition; + } + } + } + + // Here handle the exception that we refuse to animate scales and axes at the same + // time. In other words, if there's an axis transition, then set the data transition + // to instantaneous. + if(hasAxisTransition) { + traceTransitionOpts = Lib.extendFlat({}, transitionOpts); + traceTransitionOpts.duration = 0; + // This means do not transition traces, + // this happens on layout-only (e.g. axis range) animations + transitionedTraces = null; + } else { + traceTransitionOpts = transitionOpts; + } + + for(j = 0; j < basePlotModules.length; j++) { + // Note that we pass a callback to *create* the callback that must be invoked on completion. + // This is since not all traces know about transitions, so it greatly simplifies matters if + // the trace is responsible for creating a callback, if needed, and then executing it when + // the time is right. + basePlotModules[j].plot(gd, transitionedTraces, traceTransitionOpts, makeCallback); + } + + // If nothing else creates a callback, then this will trigger the completion in the next tick: + setTimeout(makeCallback()); + + }); + } + + function completeTransition(callback) { + // This a simple workaround for tests which purge the graph before animations + // have completed. That's not a very common case, so this is the simplest + // fix. + if(!gd._transitionData) return; + + flushCallbacks(gd._transitionData._interruptCallbacks); + + return Promise.resolve().then(function() { + if(frameOpts.redraw) { + return Registry.call('redraw', gd); + } + }).then(function() { + // Set transitioning false again once the redraw has occurred. This is used, for example, + // to prevent the trailing redraw from autoranging: + gd._transitioning = false; + gd._transitioningWithDuration = false; + + gd.emit('plotly_transitioned', []); + }).then(callback); + } + + function interruptPreviousTransitions() { + // Fail-safe against purged plot: + if(!gd._transitionData) return; + + // If a transition is interrupted, set this to false. At the moment, the only thing that would + // interrupt a transition is another transition, so that it will momentarily be set to true + // again, but this determines whether autorange or dragbox work, so it's for the sake of + // cleanliness: + gd._transitioning = false; + + return executeCallbacks(gd._transitionData._interruptCallbacks); + } + + for(i = 0; i < traceIndices.length; i++) { + traceIdx = traceIndices[i]; + var contFull = gd._fullData[traceIdx]; + var module = contFull._module; + + if(!module) continue; + } + + var seq = [plots.previousPromises, interruptPreviousTransitions, prepareTransitions, plots.rehover, executeTransitions]; + + var transitionStarting = Lib.syncOrAsync(seq, gd); + + if(!transitionStarting || !transitionStarting.then) { + transitionStarting = Promise.resolve(); + } + + return transitionStarting.then(function() { + return gd; + }); +}; + +/** + * Transition used in Plotly.react + */ +plots.transition2 = function(gd, restyleFlags, relayoutFlags, oldFullLayout) { + var aborted = false; + var redraw = true; + var edits; + + function prepareTransitions() { + var fullLayout = gd._fullLayout; + var subplots = fullLayout._plots; + var rangesAltered = relayoutFlags.rangesAltered; + var autorangedAxes = relayoutFlags.autorangedAxes; + + // no need to redraw at end of transition, + // if all changes are animatable + redraw = false; + if(restyleFlags.anim === 'some') redraw = true; + if(relayoutFlags.anim === 'some') redraw = true; + + edits = {}; + for(var k in subplots) { + var plotinfo = subplots[k]; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + if(rangesAltered[xa._name] || rangesAltered[ya._name] || + autorangedAxes[xa._name] || autorangedAxes[ya._name] + ) { + edits[k] = { + plotinfo: plotinfo, + xr0: oldFullLayout[xa._name].range.slice(), + yr0: oldFullLayout[ya._name].range.slice(), + xr1: xa.range.slice(), + yr1: ya.range.slice() + }; + } + } + + return Promise.resolve(); + } + + function executeCallbacks(list) { + var p = Promise.resolve(); + if(!list) return p; + while(list.length) { + p = p.then((list.shift())); + } + return p; + } + + function flushCallbacks(list) { + if(!list) return; + while(list.length) { + list.shift(); + } + } + + function executeTransitions() { + gd.emit('plotly_transitioning', []); + + return new Promise(function(resolve) { + var fullData = gd._fullData; + var fullLayout = gd._fullLayout; + var transitionOpts = fullLayout.transition; + var basePlotModules = fullLayout._basePlotModules; + var i; + + // This flag is used to disabled things like autorange: + gd._transitioning = true; + + // When instantaneous updates are coming through quickly, it's too much to simply disable + // all interaction, so store this flag so we can disambiguate whether mouse interactions + // should be fully disabled or not: + if(transitionOpts.duration > 0) { + gd._transitioningWithDuration = true; + } + + // If another transition is triggered, this callback will be executed simply because it's + // in the interruptCallbacks queue. If this transition completes, it will instead flush + // that queue and forget about this callback. + gd._transitionData._interruptCallbacks.push(function() { + aborted = true; + }); + + if(redraw) { + gd._transitionData._interruptCallbacks.push(function() { + return Registry.call('redraw', gd); + }); + } + + // Emit this and make sure it happens last: + gd._transitionData._interruptCallbacks.push(function() { + gd.emit('plotly_transitioninterrupted', []); + }); + + // Construct callbacks that are executed on transition end. This ensures the d3 transitions + // are *complete* before anything else is done. + var numCallbacks = 0; + var numCompleted = 0; + function makeCallback() { + numCallbacks++; + return function() { + numCompleted++; + // When all are complete, perform a redraw: + if(!aborted && numCompleted === numCallbacks) { + completeTransition(resolve); + } + }; + } + + // Here handle the exception that we refuse to animate traces and axes at the same + // time. In other words, if there's an axis transition, then set the data transition + // to instantaneous. + var traceTransitionOpts; + var transitionedTraces = []; + + if(Object.keys(edits).length) { + for(i = 0; i < basePlotModules.length; i++) { + if(basePlotModules[i].transitionAxes2) { + basePlotModules[i].transitionAxes2(gd, edits, transitionOpts, makeCallback); + } + } + + traceTransitionOpts = Lib.extendFlat({}, transitionOpts); + traceTransitionOpts.duration = 0; + // This means do not transition traces, + // this happens on layout-only (e.g. axis range) animations + transitionedTraces = null; + } else { + traceTransitionOpts = transitionOpts; + for(i = 0; i < fullData.length; i++) { + transitionedTraces.push(i); + } + } + + // Note that we pass a callback to *create* the callback that must be invoked on completion. + // This is since not all traces know about transitions, so it greatly simplifies matters if + // the trace is responsible for creating a callback, if needed, and then executing it when + // the time is right. + for(i = 0; i < basePlotModules.length; i++) { + basePlotModules[i].plot(gd, transitionedTraces, traceTransitionOpts, makeCallback); + } + + // If nothing else creates a callback, then this will trigger the completion in the next tick: + setTimeout(makeCallback()); + }); + } + + function completeTransition(callback) { + // This a simple workaround for tests which purge the graph before animations + // have completed. That's not a very common case, so this is the simplest + // fix. + if(!gd._transitionData) return; + + flushCallbacks(gd._transitionData._interruptCallbacks); + + return Promise.resolve().then(function() { + if(redraw) { + return Registry.call('redraw', gd); + } + }).then(function() { + // Set transitioning false again once the redraw has occurred. This is used, for example, + // to prevent the trailing redraw from autoranging: + gd._transitioning = false; + gd._transitioningWithDuration = false; + + gd.emit('plotly_transitioned', []); + }).then(callback); + } + + function interruptPreviousTransitions() { + // Fail-safe against purged plot: + if(!gd._transitionData) return; + + // If a transition is interrupted, set this to false. At the moment, the only thing that would + // interrupt a transition is another transition, so that it will momentarily be set to true + // again, but this determines whether autorange or dragbox work, so it's for the sake of + // cleanliness: + gd._transitioning = false; + + return executeCallbacks(gd._transitionData._interruptCallbacks); + } + + var seq = [ + plots.previousPromises, + interruptPreviousTransitions, + prepareTransitions, + plots.rehover, + executeTransitions + ]; + + var transitionStarting = Lib.syncOrAsync(seq, gd); + + if(!transitionStarting || !transitionStarting.then) { + transitionStarting = Promise.resolve(); + } + + return transitionStarting.then(function() { + return gd; + }); +}; + +plots.doCalcdata = function(gd, traces) { + var axList = axisIDs.list(gd), + fullData = gd._fullData, + fullLayout = gd._fullLayout; + + var trace, _module, i, j; + + // XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without + // *all* needing doCalcdata: + var calcdata = new Array(fullData.length); + var oldCalcdata = (gd.calcdata || []).slice(0); + gd.calcdata = calcdata; + + // extra helper variables + + // how many box/violins plots do we have (in case they're grouped) + fullLayout._numBoxes = 0; + fullLayout._numViolins = 0; + + // initialize violin per-scale-group stats container + fullLayout._violinScaleGroupStats = {}; + + // for calculating avg luminosity of heatmaps + gd._hmpixcount = 0; + gd._hmlumcount = 0; + + // for sharing colors across pies (and for legend) + fullLayout._piecolormap = {}; + + // If traces were specified and this trace was not included, + // then transfer it over from the old calcdata: + for(i = 0; i < fullData.length; i++) { + if(Array.isArray(traces) && traces.indexOf(i) === -1) { + calcdata[i] = oldCalcdata[i]; + continue; + } + } + + for(i = 0; i < fullData.length; i++) { + trace = fullData[i]; + + trace._arrayAttrs = PlotSchema.findArrayAttributes(trace); + + // keep track of trace extremes (for autorange) in here + trace._extremes = {}; + } + + // add polar axes to axis list + var polarIds = fullLayout._subplots.polar || []; + for(i = 0; i < polarIds.length; i++) { + axList.push( + fullLayout[polarIds[i]].radialaxis, + fullLayout[polarIds[i]].angularaxis + ); + } + + clearAxesCalc(axList); + + var hasCalcTransform = false; + + // transform loop + for(i = 0; i < fullData.length; i++) { + trace = fullData[i]; + + if(trace.visible === true && trace.transforms) { + _module = trace._module; + + // we need one round of trace module calc before + // the calc transform to 'fill in' the categories list + // used for example in the data-to-coordinate method + if(_module && _module.calc) { + var cdi = _module.calc(gd, trace); + + // must clear scene 'batches', so that 2nd + // _module.calc call starts from scratch + if(cdi[0] && cdi[0].t && cdi[0].t._scene) { + delete cdi[0].t._scene.dirty; + } + } + + for(j = 0; j < trace.transforms.length; j++) { + var transform = trace.transforms[j]; + + _module = transformsRegistry[transform.type]; + if(_module && _module.calcTransform) { + trace._hasCalcTransform = true; + hasCalcTransform = true; + _module.calcTransform(gd, trace, transform); + } + } + } + } + + // clear stuff that should recomputed in 'regular' loop + if(hasCalcTransform) clearAxesCalc(axList); + + function calci(i, isContainer) { + trace = fullData[i]; + _module = trace._module; + + if(!!_module.isContainer !== isContainer) return; + + var cd = []; + + if(trace.visible === true) { + + // clear existing ref in case it got relinked + delete trace._indexToPoints; + // keep ref of index-to-points map object of the *last* enabled transform, + // this index-to-points map object is required to determine the calcdata indices + // that correspond to input indices (e.g. from 'selectedpoints') + var transforms = trace.transforms || []; + for(j = transforms.length - 1; j >= 0; j--) { + if(transforms[j].enabled) { + trace._indexToPoints = transforms[j]._indexToPoints; + break; + } + } + + if(_module && _module.calc) { + cd = _module.calc(gd, trace); + } + } + + // Make sure there is a first point. + // + // This ensures there is a calcdata item for every trace, + // even if cartesian logic doesn't handle it (for things like legends). + if(!Array.isArray(cd) || !cd[0]) { + cd = [{x: BADNUM, y: BADNUM}]; + } + + // add the trace-wide properties to the first point, + // per point properties to every point + // t is the holder for trace-wide properties + if(!cd[0].t) cd[0].t = {}; + cd[0].trace = trace; + + calcdata[i] = cd; + } + + // 'regular' loop - make sure container traces (eg carpet) calc before + // contained traces (eg contourcarpet) + for(i = 0; i < fullData.length; i++) calci(i, true); + for(i = 0; i < fullData.length; i++) calci(i, false); + + doCrossTraceCalc(gd); + + Registry.getComponentMethod('fx', 'calc')(gd); + Registry.getComponentMethod('errorbars', 'calc')(gd); +}; + +function clearAxesCalc(axList) { + for(var i = 0; i < axList.length; i++) { + axList[i].clearCalc(); + } +} + +function doCrossTraceCalc(gd) { + var fullLayout = gd._fullLayout; + var modules = fullLayout._visibleModules; + var hash = {}; + var i, j, k; + + // position and range calculations for traces that + // depend on each other ie bars (stacked or grouped) + // and boxes (grouped) push each other out of the way + + for(j = 0; j < modules.length; j++) { + var _module = modules[j]; + var fn = _module.crossTraceCalc; + if(fn) { + var spType = _module.basePlotModule.name; + if(hash[spType]) { + Lib.pushUnique(hash[spType], fn); + } else { + hash[spType] = [fn]; + } + } + } + + for(k in hash) { + var methods = hash[k]; + var subplots = fullLayout._subplots[k]; + + if(Array.isArray(subplots)) { + for(i = 0; i < subplots.length; i++) { + var sp = subplots[i]; + var spInfo = k === 'cartesian' ? + fullLayout._plots[sp] : + fullLayout[sp]; + + for(j = 0; j < methods.length; j++) { + methods[j](gd, spInfo, sp); + } + } + } + else { + for(j = 0; j < methods.length; j++) { + methods[j](gd); + } + } + } +} + +plots.rehover = function(gd) { + if(gd._fullLayout._rehover) { + gd._fullLayout._rehover(); + } +}; + +plots.generalUpdatePerTraceModule = function(gd, subplot, subplotCalcData, subplotLayout) { + var traceHashOld = subplot.traceHash; + var traceHash = {}; + var i; + + // build up moduleName -> calcData hash + for(i = 0; i < subplotCalcData.length; i++) { + var calcTraces = subplotCalcData[i], + trace = calcTraces[0].trace; + + // skip over visible === false traces + // as they don't have `_module` ref + if(trace.visible) { + traceHash[trace.type] = traceHash[trace.type] || []; + traceHash[trace.type].push(calcTraces); + } + } + + // when a trace gets deleted, make sure that its module's + // plot method is called so that it is properly + // removed from the DOM. + for(var moduleNameOld in traceHashOld) { + if(!traceHash[moduleNameOld]) { + var fakeCalcTrace = traceHashOld[moduleNameOld][0], + fakeTrace = fakeCalcTrace[0].trace; + + fakeTrace.visible = false; + traceHash[moduleNameOld] = [fakeCalcTrace]; + } + } + + // call module plot method + for(var moduleName in traceHash) { + var moduleCalcData = traceHash[moduleName]; + var _module = moduleCalcData[0][0].trace._module; + + _module.plot(gd, subplot, Lib.filterVisible(moduleCalcData), subplotLayout); + } + + // update moduleName -> calcData hash + subplot.traceHash = traceHash; +}; + +},{"../components/color":570,"../constants/numerical":673,"../lib":696,"../plot_api/plot_schema":733,"../plot_api/plot_template":734,"../plots/cartesian/axis_ids":747,"../registry":827,"./animation_attributes":739,"./attributes":741,"./command":769,"./font_attributes":771,"./frame_attributes":772,"./layout_attributes":799,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],809:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + attr: 'subplot', + name: 'polar', + + axisNames: ['angularaxis', 'radialaxis'], + axisName2dataArray: {angularaxis: 'theta', radialaxis: 'r'}, + + layerNames: [ + 'draglayer', + 'plotbg', + 'backplot', + 'angular-grid', + 'radial-grid', + 'frontplot', + 'angular-line', + 'radial-line', + 'angular-axis', + 'radial-axis' + ], + + radialDragBoxSize: 50, + angularDragBoxSize: 30, + cornerLen: 25, + cornerHalfWidth: 2, + + // pixels to move mouse before you stop clamping to starting point + MINDRAG: 8, + // smallest radial distance [px] allowed for a zoombox + MINZOOM: 20, + // distance [px] off (r=0) or (r=radius) where we transition + // from single-sided to two-sided radial zoom + OFFEDGE: 20 +}; + +},{}],810:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var polygonTester = _dereq_('../../lib/polygon').tester; + +var findIndexOfMin = Lib.findIndexOfMin; +var isAngleInsideSector = Lib.isAngleInsideSector; +var angleDelta = Lib.angleDelta; +var angleDist = Lib.angleDist; + +/** + * is pt (r,a) inside polygon made up vertices at angles 'vangles' + * inside a given polar sector + * + * @param {number} r : pt's radial coordinate + * @param {number} a : pt's angular coordinate in *radians* + * @param {2-item array} rBnds : sector's radial bounds + * @param {2-item array} aBnds : sector's angular bounds *radians* + * @param {array} vangles : angles of polygon vertices in *radians* + * @return {boolean} + */ +function isPtInsidePolygon(r, a, rBnds, aBnds, vangles) { + if(!isAngleInsideSector(a, aBnds)) return false; + + var r0, r1; + + if(rBnds[0] < rBnds[1]) { + r0 = rBnds[0]; + r1 = rBnds[1]; + } else { + r0 = rBnds[1]; + r1 = rBnds[0]; + } + + var polygonIn = polygonTester(makePolygon(r0, aBnds[0], aBnds[1], vangles)); + var polygonOut = polygonTester(makePolygon(r1, aBnds[0], aBnds[1], vangles)); + var xy = [r * Math.cos(a), r * Math.sin(a)]; + return polygonOut.contains(xy) && !polygonIn.contains(xy); +} + +// find intersection of 'v0' <-> 'v1' edge with a ray at angle 'a' +// (i.e. a line that starts from the origin at angle 'a') +// given an (xp,yp) pair on the 'v0' <-> 'v1' line +// (N.B. 'v0' and 'v1' are angles in radians) +function findIntersectionXY(v0, v1, a, xpyp) { + var xstar, ystar; + + var xp = xpyp[0]; + var yp = xpyp[1]; + var dsin = clampTiny(Math.sin(v1) - Math.sin(v0)); + var dcos = clampTiny(Math.cos(v1) - Math.cos(v0)); + var tanA = Math.tan(a); + var cotanA = clampTiny(1 / tanA); + var m = dsin / dcos; + var b = yp - m * xp; + + if(cotanA) { + if(dsin && dcos) { + // given + // g(x) := v0 -> v1 line = m*x + b + // h(x) := ray at angle 'a' = m*x = tanA*x + // solve g(xstar) = h(xstar) + xstar = b / (tanA - m); + ystar = tanA * xstar; + } else if(dcos) { + // horizontal v0 -> v1 + xstar = yp * cotanA; + ystar = yp; + } else { + // vertical v0 -> v1 + xstar = xp; + ystar = xp * tanA; + } + } else { + // vertical ray + if(dsin && dcos) { + xstar = 0; + ystar = b; + } else if(dcos) { + xstar = 0; + ystar = yp; + } else { + // does this case exists? + xstar = ystar = NaN; + } + } + + return [xstar, ystar]; +} + +// solves l^2 = (f(x)^2 - yp)^2 + (x - xp)^2 +// rearranged into 0 = a*x^2 + b * x + c +// +// where f(x) = m*x + t + yp +// and (x0, x1) = (-b +/- del) / (2*a) +function findXYatLength(l, m, xp, yp) { + var t = -m * xp; + var a = m * m + 1; + var b = 2 * (m * t - xp); + var c = t * t + xp * xp - l * l; + var del = Math.sqrt(b * b - 4 * a * c); + var x0 = (-b + del) / (2 * a); + var x1 = (-b - del) / (2 * a); + return [ + [x0, m * x0 + t + yp], + [x1, m * x1 + t + yp] + ]; +} + +function makeRegularPolygon(r, vangles) { + var len = vangles.length; + var vertices = new Array(len + 1); + var i; + for(i = 0; i < len; i++) { + var va = vangles[i]; + vertices[i] = [r * Math.cos(va), r * Math.sin(va)]; + } + vertices[i] = vertices[0].slice(); + return vertices; +} + +function makeClippedPolygon(r, a0, a1, vangles) { + var len = vangles.length; + var vertices = []; + var i, j; + + function a2xy(a) { + return [r * Math.cos(a), r * Math.sin(a)]; + } + + function findXY(va0, va1, s) { + return findIntersectionXY(va0, va1, s, a2xy(va0)); + } + + function cycleIndex(ind) { + return Lib.mod(ind, len); + } + + function isInside(v) { + return isAngleInsideSector(v, [a0, a1]); + } + + // find index in sector closest to a0 + // use it to find intersection of v[i0] <-> v[i0-1] edge with sector radius + var i0 = findIndexOfMin(vangles, function(v) { + return isInside(v) ? angleDist(v, a0) : Infinity; + }); + var xy0 = findXY(vangles[i0], vangles[cycleIndex(i0 - 1)], a0); + vertices.push(xy0); + + // fill in in-sector vertices + for(i = i0, j = 0; j < len; i++, j++) { + var va = vangles[cycleIndex(i)]; + if(!isInside(va)) break; + vertices.push(a2xy(va)); + } + + // find index in sector closest to a1, + // use it to find intersection of v[iN] <-> v[iN+1] edge with sector radius + var iN = findIndexOfMin(vangles, function(v) { + return isInside(v) ? angleDist(v, a1) : Infinity; + }); + var xyN = findXY(vangles[iN], vangles[cycleIndex(iN + 1)], a1); + vertices.push(xyN); + + vertices.push([0, 0]); + vertices.push(vertices[0].slice()); + + return vertices; +} + +function makePolygon(r, a0, a1, vangles) { + return Lib.isFullCircle([a0, a1]) ? + makeRegularPolygon(r, vangles) : + makeClippedPolygon(r, a0, a1, vangles); +} + +function findPolygonOffset(r, a0, a1, vangles) { + var minX = Infinity; + var minY = Infinity; + var vertices = makePolygon(r, a0, a1, vangles); + + for(var i = 0; i < vertices.length; i++) { + var v = vertices[i]; + minX = Math.min(minX, v[0]); + minY = Math.min(minY, -v[1]); + } + return [minX, minY]; +} + +/** + * find vertex angles (in 'vangles') the enclose angle 'a' + * + * @param {number} a : angle in *radians* + * @param {array} vangles : angles of polygon vertices in *radians* + * @return {2-item array} + */ +function findEnclosingVertexAngles(a, vangles) { + var minFn = function(v) { + var adelta = angleDelta(v, a); + return adelta > 0 ? adelta : Infinity; + }; + var i0 = findIndexOfMin(vangles, minFn); + var i1 = Lib.mod(i0 + 1, vangles.length); + return [vangles[i0], vangles[i1]]; +} + +// to more easily catch 'almost zero' numbers in if-else blocks +function clampTiny(v) { + return Math.abs(v) > 1e-10 ? v : 0; +} + +function transformForSVG(pts0, cx, cy) { + cx = cx || 0; + cy = cy || 0; + + var len = pts0.length; + var pts1 = new Array(len); + + for(var i = 0; i < len; i++) { + var pt = pts0[i]; + pts1[i] = [cx + pt[0], cy - pt[1]]; + } + return pts1; +} + +/** + * path polygon + * + * @param {number} r : polygon 'radius' + * @param {number} a0 : first angular coordinate in *radians* + * @param {number} a1 : second angular coordinate in *radians* + * @param {array} vangles : angles of polygon vertices in *radians* + * @param {number (optional)} cx : x coordinate of center + * @param {number (optional)} cy : y coordinate of center + * @return {string} svg path + * + */ +function pathPolygon(r, a0, a1, vangles, cx, cy) { + var poly = makePolygon(r, a0, a1, vangles); + return 'M' + transformForSVG(poly, cx, cy).join('L'); +} + +/** + * path a polygon 'annulus' + * i.e. a polygon with a concentric hole + * + * N.B. this routine uses the evenodd SVG rule + * + * @param {number} r0 : first radial coordinate + * @param {number} r1 : second radial coordinate + * @param {number} a0 : first angular coordinate in *radians* + * @param {number} a1 : second angular coordinate in *radians* + * @param {array} vangles : angles of polygon vertices in *radians* + * @param {number (optional)} cx : x coordinate of center + * @param {number (optional)} cy : y coordinate of center + * @return {string} svg path + * + */ +function pathPolygonAnnulus(r0, r1, a0, a1, vangles, cx, cy) { + var rStart, rEnd; + + if(r0 < r1) { + rStart = r0; + rEnd = r1; + } else { + rStart = r1; + rEnd = r0; + } + + var inner = transformForSVG(makePolygon(rStart, a0, a1, vangles), cx, cy); + var outer = transformForSVG(makePolygon(rEnd, a0, a1, vangles), cx, cy); + return 'M' + outer.reverse().join('L') + 'M' + inner.join('L'); +} + +module.exports = { + isPtInsidePolygon: isPtInsidePolygon, + findPolygonOffset: findPolygonOffset, + findEnclosingVertexAngles: findEnclosingVertexAngles, + findIntersectionXY: findIntersectionXY, + findXYatLength: findXYatLength, + clampTiny: clampTiny, + pathPolygon: pathPolygon, + pathPolygonAnnulus: pathPolygonAnnulus +}; + +},{"../../lib":696,"../../lib/polygon":708}],811:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var getSubplotCalcData = _dereq_('../get_data').getSubplotCalcData; +var counterRegex = _dereq_('../../lib').counterRegex; + +var createPolar = _dereq_('./polar'); +var constants = _dereq_('./constants'); + +var attr = constants.attr; +var name = constants.name; +var counter = counterRegex(name); + +var attributes = {}; +attributes[attr] = { + valType: 'subplotid', + + dflt: name, + editType: 'calc', + +}; + +function plot(gd) { + var fullLayout = gd._fullLayout; + var calcData = gd.calcdata; + var subplotIds = fullLayout._subplots[name]; + + for(var i = 0; i < subplotIds.length; i++) { + var id = subplotIds[i]; + var subplotCalcData = getSubplotCalcData(calcData, name, id); + var subplot = fullLayout[id]._subplot; + + if(!subplot) { + subplot = createPolar(gd, id); + fullLayout[id]._subplot = subplot; + } + + subplot.plot(subplotCalcData, fullLayout, gd._promises); + } +} + +function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldIds = oldFullLayout._subplots[name] || []; + var hadGl = (oldFullLayout._has && oldFullLayout._has('gl')); + var hasGl = (newFullLayout._has && newFullLayout._has('gl')); + var mustCleanScene = hadGl && !hasGl; + + for(var i = 0; i < oldIds.length; i++) { + var id = oldIds[i]; + var oldSubplot = oldFullLayout[id]._subplot; + + if(!newFullLayout[id] && !!oldSubplot) { + oldSubplot.framework.remove(); + oldSubplot.layers['radial-axis-title'].remove(); + + for(var k in oldSubplot.clipPaths) { + oldSubplot.clipPaths[k].remove(); + } + } + + if(mustCleanScene && oldSubplot._scene) { + oldSubplot._scene.destroy(); + oldSubplot._scene = null; + } + } +} + +module.exports = { + attr: attr, + name: name, + idRoot: name, + idRegex: counter, + attrRegex: counter, + attributes: attributes, + layoutAttributes: _dereq_('./layout_attributes'), + supplyLayoutDefaults: _dereq_('./layout_defaults'), + plot: plot, + clean: clean, + toSVG: _dereq_('../cartesian').toSVG +}; + +},{"../../lib":696,"../cartesian":756,"../get_data":781,"./constants":809,"./layout_attributes":812,"./layout_defaults":813,"./polar":820}],812:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = _dereq_('../../components/color/attributes'); +var axesAttrs = _dereq_('../cartesian/layout_attributes'); +var domainAttrs = _dereq_('../domain').attributes; +var extendFlat = _dereq_('../../lib').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var axisLineGridAttr = overrideAll({ + color: axesAttrs.color, + showline: extendFlat({}, axesAttrs.showline, {dflt: true}), + linecolor: axesAttrs.linecolor, + linewidth: axesAttrs.linewidth, + showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}), + gridcolor: axesAttrs.gridcolor, + gridwidth: axesAttrs.gridwidth + + // TODO add spike* attributes down the road + + // should we add zeroline* attributes? + +}, 'plot', 'from-root'); + +var axisTickAttrs = overrideAll({ + tickmode: axesAttrs.tickmode, + nticks: axesAttrs.nticks, + tick0: axesAttrs.tick0, + dtick: axesAttrs.dtick, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + ticks: axesAttrs.ticks, + ticklen: axesAttrs.ticklen, + tickwidth: axesAttrs.tickwidth, + tickcolor: axesAttrs.tickcolor, + showticklabels: axesAttrs.showticklabels, + showtickprefix: axesAttrs.showtickprefix, + tickprefix: axesAttrs.tickprefix, + showticksuffix: axesAttrs.showticksuffix, + ticksuffix: axesAttrs.ticksuffix, + showexponent: axesAttrs.showexponent, + exponentformat: axesAttrs.exponentformat, + separatethousands: axesAttrs.separatethousands, + tickfont: axesAttrs.tickfont, + tickangle: axesAttrs.tickangle, + tickformat: axesAttrs.tickformat, + tickformatstops: axesAttrs.tickformatstops, + layer: axesAttrs.layer +}, 'plot', 'from-root'); + +var radialAxisAttrs = { + visible: extendFlat({}, axesAttrs.visible, {dflt: true}), + type: axesAttrs.type, + + autorange: extendFlat({}, axesAttrs.autorange, {editType: 'plot'}), + rangemode: { + valType: 'enumerated', + values: ['tozero', 'nonnegative', 'normal'], + dflt: 'tozero', + + editType: 'calc', + + }, + range: extendFlat({}, axesAttrs.range, { + items: [ + {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}}, + {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}} + ], + editType: 'plot' + }), + + categoryorder: axesAttrs.categoryorder, + categoryarray: axesAttrs.categoryarray, + + angle: { + valType: 'angle', + editType: 'plot', + + + }, + + side: { + valType: 'enumerated', + // TODO add 'center' for `showline: false` radial axes + values: ['clockwise', 'counterclockwise'], + dflt: 'clockwise', + editType: 'plot', + + + }, + + + title: extendFlat({}, axesAttrs.title, {editType: 'plot', dflt: ''}), + titlefont: overrideAll(axesAttrs.titlefont, 'plot', 'from-root'), + // might need a 'titleside' and even 'titledirection' down the road + + hoverformat: axesAttrs.hoverformat, + + editType: 'calc' +}; + +extendFlat( + radialAxisAttrs, + + // N.B. radialaxis grid lines are circular, + // but radialaxis lines are straight from circle center to outer bound + axisLineGridAttr, + axisTickAttrs +); + +var angularAxisAttrs = { + visible: extendFlat({}, axesAttrs.visible, {dflt: true}), + type: { + valType: 'enumerated', + // 'linear' should maybe be called 'angle' or 'angular' here + // to make clear that axis here is periodic and more tightly match + // `thetaunit`? + // + // skip 'date' for first push + // no 'log' for now + values: ['-', 'linear', 'category'], + dflt: '-', + + editType: 'calc', + _noTemplating: true, + + }, + + categoryorder: axesAttrs.categoryorder, + categoryarray: axesAttrs.categoryarray, + + thetaunit: { + valType: 'enumerated', + values: ['radians', 'degrees'], + dflt: 'degrees', + + editType: 'calc', + + }, + + period: { + valType: 'number', + editType: 'calc', + min: 0, + + + // Examples for date axes: + // + // - period that equals the timeseries length + // http://flowingdata.com/2017/01/24/one-dataset-visualized-25-ways/18-polar-coordinates/ + // - and 1-year periods (focusing on seasonal change0 + // http://otexts.org/fpp2/seasonal-plots.html + // https://blogs.scientificamerican.com/sa-visual/why-are-so-many-babies-born-around-8-00-a-m/ + // http://www.seasonaladjustment.com/2012/09/05/clock-plot-visualising-seasonality-using-r-and-ggplot2-part-3/ + // https://i.pinimg.com/736x/49/b9/72/49b972ccb3206a1a6d6f870dac543280.jpg + // https://www.climate-lab-book.ac.uk/spirals/ + }, + + direction: { + valType: 'enumerated', + values: ['counterclockwise', 'clockwise'], + dflt: 'counterclockwise', + + editType: 'calc', + + }, + + rotation: { + valType: 'angle', + editType: 'calc', + + + }, + + hoverformat: axesAttrs.hoverformat, + + editType: 'calc' +}; + +extendFlat( + angularAxisAttrs, + + // N.B. angular grid lines are straight lines from circle center to outer bound + // the angular line is circular bounding the polar plot area. + axisLineGridAttr, + + // N.B. ticksuffix defaults to '°' for angular axes with `thetaunit: 'degrees'` + axisTickAttrs +); + +module.exports = { + // TODO for x/y/zoom system for paper-based zooming: + // x: {}, + // y: {}, + // zoom: {}, + + domain: domainAttrs({name: 'polar', editType: 'plot'}), + + sector: { + valType: 'info_array', + items: [ + {valType: 'number', editType: 'plot'}, + {valType: 'number', editType: 'plot'} + ], + dflt: [0, 360], + + editType: 'plot', + + }, + hole: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + editType: 'plot', + + + }, + + bgcolor: { + valType: 'color', + + editType: 'plot', + dflt: colorAttrs.background, + + }, + + radialaxis: radialAxisAttrs, + angularaxis: angularAxisAttrs, + + gridshape: { + valType: 'enumerated', + values: ['circular', 'linear'], + dflt: 'circular', + + editType: 'plot', + + }, + + // TODO maybe? + // annotations: + + editType: 'calc' +}; + +},{"../../components/color/attributes":569,"../../lib":696,"../../plot_api/edit_types":727,"../cartesian/layout_attributes":757,"../domain":770}],813:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var Template = _dereq_('../../plot_api/plot_template'); + +var handleSubplotDefaults = _dereq_('../subplot_defaults'); +var getSubplotData = _dereq_('../get_data').getSubplotData; + +var handleTickValueDefaults = _dereq_('../cartesian/tick_value_defaults'); +var handleTickMarkDefaults = _dereq_('../cartesian/tick_mark_defaults'); +var handleTickLabelDefaults = _dereq_('../cartesian/tick_label_defaults'); +var handleCategoryOrderDefaults = _dereq_('../cartesian/category_order_defaults'); +var handleLineGridDefaults = _dereq_('../cartesian/line_grid_defaults'); +var autoType = _dereq_('../cartesian/axis_autotype'); + +var layoutAttributes = _dereq_('./layout_attributes'); +var setConvert = _dereq_('./set_convert'); +var constants = _dereq_('./constants'); +var axisNames = constants.axisNames; + +function handleDefaults(contIn, contOut, coerce, opts) { + var bgColor = coerce('bgcolor'); + opts.bgColor = Color.combine(bgColor, opts.paper_bgcolor); + + var sector = coerce('sector'); + coerce('hole'); + + // could optimize, subplotData is not always needed! + var subplotData = getSubplotData(opts.fullData, constants.name, opts.id); + var layoutOut = opts.layoutOut; + var axName; + + function coerceAxis(attr, dflt) { + return coerce(axName + '.' + attr, dflt); + } + + for(var i = 0; i < axisNames.length; i++) { + axName = axisNames[i]; + + if(!Lib.isPlainObject(contIn[axName])) { + contIn[axName] = {}; + } + + var axIn = contIn[axName]; + var axOut = Template.newContainer(contOut, axName); + axOut._id = axOut._name = axName; + axOut._traceIndices = subplotData.map(function(t) { return t._expandedIndex; }); + + var dataAttr = constants.axisName2dataArray[axName]; + var axType = handleAxisTypeDefaults(axIn, axOut, coerceAxis, subplotData, dataAttr); + + handleCategoryOrderDefaults(axIn, axOut, coerceAxis, { + axData: subplotData, + dataAttr: dataAttr + }); + + var visible = coerceAxis('visible'); + setConvert(axOut, contOut, layoutOut); + + var dfltColor; + var dfltFontColor; + + if(visible) { + dfltColor = coerceAxis('color'); + dfltFontColor = (dfltColor === axIn.color) ? dfltColor : opts.font.color; + } + + // We don't want to make downstream code call ax.setScale, + // as both radial and angular axes don't have a set domain. + // Furthermore, angular axes don't have a set range. + // + // Mocked domains and ranges are set by the polar subplot instances, + // but Axes.findExtremes uses the sign of _m to determine which padding value + // to use. + // + // By setting, _m to 1 here, we make Axes.findExtremes think that + // range[1] > range[0], and vice-versa for `autorange: 'reversed'` below. + axOut._m = 1; + + switch(axName) { + case 'radialaxis': + var autoRange = coerceAxis('autorange', !axOut.isValidRange(axIn.range)); + axIn.autorange = autoRange; + if(autoRange && (axType === 'linear' || axType === '-')) coerceAxis('rangemode'); + if(autoRange === 'reversed') axOut._m = -1; + + coerceAxis('range'); + axOut.cleanRange('range', {dfltRange: [0, 1]}); + + if(visible) { + coerceAxis('side'); + coerceAxis('angle', sector[0]); + + coerceAxis('title'); + Lib.coerceFont(coerceAxis, 'titlefont', { + family: opts.font.family, + size: Math.round(opts.font.size * 1.2), + color: dfltFontColor + }); + } + break; + + case 'angularaxis': + // We do not support 'true' date angular axes yet, + // users can still plot dates on angular axes by setting + // `angularaxis.type: 'category'`. + // + // Here, if a date angular axes is detected, we make + // all its corresponding traces invisible, so that + // when we do add support for data angular axes, the new + // behavior won't conflict with existing behavior + if(axType === 'date') { + Lib.log('Polar plots do not support date angular axes yet.'); + + for(var j = 0; j < subplotData.length; j++) { + subplotData[j].visible = false; + } + + // turn this into a 'dummy' linear axis so that + // the subplot still renders ok + axType = axIn.type = axOut.type = 'linear'; + } + + if(axType === 'linear') { + coerceAxis('thetaunit'); + } else { + coerceAxis('period'); + } + + var direction = coerceAxis('direction'); + coerceAxis('rotation', {counterclockwise: 0, clockwise: 90}[direction]); + break; + } + + if(visible) { + handleTickValueDefaults(axIn, axOut, coerceAxis, axOut.type); + handleTickLabelDefaults(axIn, axOut, coerceAxis, axOut.type, { + tickSuffixDflt: axOut.thetaunit === 'degrees' ? '°' : undefined + }); + handleTickMarkDefaults(axIn, axOut, coerceAxis, {outerTicks: true}); + + var showTickLabels = coerceAxis('showticklabels'); + if(showTickLabels) { + Lib.coerceFont(coerceAxis, 'tickfont', { + family: opts.font.family, + size: opts.font.size, + color: dfltFontColor + }); + coerceAxis('tickangle'); + coerceAxis('tickformat'); + } + + handleLineGridDefaults(axIn, axOut, coerceAxis, { + dfltColor: dfltColor, + bgColor: opts.bgColor, + // default grid color is darker here (60%, vs cartesian default ~91%) + // because the grid is not square so the eye needs heavier cues to follow + blend: 60, + showLine: true, + showGrid: true, + noZeroLine: true, + attributes: layoutAttributes[axName] + }); + + coerceAxis('layer'); + } + + if(axType !== 'category') coerceAxis('hoverformat'); + + axOut._input = axIn; + } + + if(contOut.angularaxis.type === 'category') { + coerce('gridshape'); + } +} + +function handleAxisTypeDefaults(axIn, axOut, coerce, subplotData, dataAttr) { + var axType = coerce('type'); + + if(axType === '-') { + var trace; + + for(var i = 0; i < subplotData.length; i++) { + if(subplotData[i].visible) { + trace = subplotData[i]; + break; + } + } + + if(trace && trace[dataAttr]) { + axOut.type = autoType(trace[dataAttr], 'gregorian'); + } + + if(axOut.type === '-') { + axOut.type = 'linear'; + } else { + // copy autoType back to input axis + // note that if this object didn't exist + // in the input layout, we have to put it in + // this happens in the main supplyDefaults function + axIn.type = axOut.type; + } + } + + return axOut.type; +} + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: constants.name, + attributes: layoutAttributes, + handleDefaults: handleDefaults, + font: layoutOut.font, + paper_bgcolor: layoutOut.paper_bgcolor, + fullData: fullData, + layoutOut: layoutOut + }); +}; + +},{"../../components/color":570,"../../lib":696,"../../plot_api/plot_template":734,"../cartesian/axis_autotype":745,"../cartesian/category_order_defaults":748,"../cartesian/line_grid_defaults":759,"../cartesian/tick_label_defaults":764,"../cartesian/tick_mark_defaults":765,"../cartesian/tick_value_defaults":766,"../get_data":781,"../subplot_defaults":822,"./constants":809,"./layout_attributes":812,"./set_convert":821}],814:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../../../traces/scatter/attributes'); +var scatterMarkerAttrs = scatterAttrs.marker; +var extendFlat = _dereq_('../../../lib/extend').extendFlat; + +var deprecationWarning = [ + 'Area traces are deprecated!', + 'Please switch to the *barpolar* trace type.' +].join(' '); + +module.exports = { + r: extendFlat({}, scatterAttrs.r, { + + }), + t: extendFlat({}, scatterAttrs.t, { + + }), + marker: { + color: extendFlat({}, scatterMarkerAttrs.color, { + + }), + size: extendFlat({}, scatterMarkerAttrs.size, { + + }), + symbol: extendFlat({}, scatterMarkerAttrs.symbol, { + + }), + opacity: extendFlat({}, scatterMarkerAttrs.opacity, { + + }), + editType: 'calc' + } +}; + +},{"../../../lib/extend":685,"../../../traces/scatter/attributes":1043}],815:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var axesAttrs = _dereq_('../../cartesian/layout_attributes'); +var extendFlat = _dereq_('../../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../../plot_api/edit_types').overrideAll; + +var deprecationWarning = [ + 'Legacy polar charts are deprecated!', + 'Please switch to *polar* subplots.' +].join(' '); + +var domainAttr = extendFlat({}, axesAttrs.domain, { + +}); + +function mergeAttrs(axisName, nonCommonAttrs) { + var commonAttrs = { + showline: { + valType: 'boolean', + + + }, + showticklabels: { + valType: 'boolean', + + + }, + tickorientation: { + valType: 'enumerated', + values: ['horizontal', 'vertical'], + + + }, + ticklen: { + valType: 'number', + min: 0, + + + }, + tickcolor: { + valType: 'color', + + + }, + ticksuffix: { + valType: 'string', + + + }, + endpadding: { + valType: 'number', + + description: deprecationWarning, + }, + visible: { + valType: 'boolean', + + + } + }; + + return extendFlat({}, nonCommonAttrs, commonAttrs); +} + +module.exports = overrideAll({ + radialaxis: mergeAttrs('radial', { + range: { + valType: 'info_array', + + items: [ + { valType: 'number' }, + { valType: 'number' } + ], + + }, + domain: domainAttr, + orientation: { + valType: 'number', + + + } + }), + + angularaxis: mergeAttrs('angular', { + range: { + valType: 'info_array', + + items: [ + { valType: 'number', dflt: 0 }, + { valType: 'number', dflt: 360 } + ], + + }, + domain: domainAttr + }), + + // attributes that appear at layout root + layout: { + direction: { + valType: 'enumerated', + values: ['clockwise', 'counterclockwise'], + + + }, + orientation: { + valType: 'angle', + + + } + } +}, 'plot', 'nested'); + +},{"../../../lib/extend":685,"../../../plot_api/edit_types":727,"../../cartesian/layout_attributes":757}],816:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Polar = module.exports = _dereq_('./micropolar'); + +Polar.manager = _dereq_('./micropolar_manager'); + +},{"./micropolar":817,"./micropolar_manager":818}],817:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Lib = _dereq_('../../../lib'); +var extendDeepAll = Lib.extendDeepAll; +var MID_SHIFT = _dereq_('../../../constants/alignment').MID_SHIFT; + +var µ = module.exports = { version: '0.2.2' }; + +µ.Axis = function module() { + var config = { + data: [], + layout: {} + }, inputConfig = {}, liveConfig = {}; + var svg, container, dispatch = d3.dispatch('hover'), radialScale, angularScale; + var exports = {}; + function render(_container) { + container = _container || container; + var data = config.data; + var axisConfig = config.layout; + if (typeof container == 'string' || container.nodeName) container = d3.select(container); + container.datum(data).each(function(_data, _index) { + var dataOriginal = _data.slice(); + liveConfig = { + data: µ.util.cloneJson(dataOriginal), + layout: µ.util.cloneJson(axisConfig) + }; + var colorIndex = 0; + dataOriginal.forEach(function(d, i) { + if (!d.color) { + d.color = axisConfig.defaultColorRange[colorIndex]; + colorIndex = (colorIndex + 1) % axisConfig.defaultColorRange.length; + } + if (!d.strokeColor) { + d.strokeColor = d.geometry === 'LinePlot' ? d.color : d3.rgb(d.color).darker().toString(); + } + liveConfig.data[i].color = d.color; + liveConfig.data[i].strokeColor = d.strokeColor; + liveConfig.data[i].strokeDash = d.strokeDash; + liveConfig.data[i].strokeSize = d.strokeSize; + }); + var data = dataOriginal.filter(function(d, i) { + var visible = d.visible; + return typeof visible === 'undefined' || visible === true; + }); + var isStacked = false; + var dataWithGroupId = data.map(function(d, i) { + isStacked = isStacked || typeof d.groupId !== 'undefined'; + return d; + }); + if (isStacked) { + var grouped = d3.nest().key(function(d, i) { + return typeof d.groupId != 'undefined' ? d.groupId : 'unstacked'; + }).entries(dataWithGroupId); + var dataYStack = []; + var stacked = grouped.map(function(d, i) { + if (d.key === 'unstacked') return d.values; else { + var prevArray = d.values[0].r.map(function(d, i) { + return 0; + }); + d.values.forEach(function(d, i, a) { + d.yStack = [ prevArray ]; + dataYStack.push(prevArray); + prevArray = µ.util.sumArrays(d.r, prevArray); + }); + return d.values; + } + }); + data = d3.merge(stacked); + } + data.forEach(function(d, i) { + d.t = Array.isArray(d.t[0]) ? d.t : [ d.t ]; + d.r = Array.isArray(d.r[0]) ? d.r : [ d.r ]; + }); + var radius = Math.min(axisConfig.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; + radius = Math.max(10, radius); + var chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; + var extent; + if (isStacked) { + var highestStackedValue = d3.max(µ.util.sumArrays(µ.util.arrayLast(data).r[0], µ.util.arrayLast(dataYStack))); + extent = [ 0, highestStackedValue ]; + } else extent = d3.extent(µ.util.flattenArray(data.map(function(d, i) { + return d.r; + }))); + if (axisConfig.radialAxis.domain != µ.DATAEXTENT) extent[0] = 0; + radialScale = d3.scale.linear().domain(axisConfig.radialAxis.domain != µ.DATAEXTENT && axisConfig.radialAxis.domain ? axisConfig.radialAxis.domain : extent).range([ 0, radius ]); + liveConfig.layout.radialAxis.domain = radialScale.domain(); + var angularDataMerged = µ.util.flattenArray(data.map(function(d, i) { + return d.t; + })); + var isOrdinal = typeof angularDataMerged[0] === 'string'; + var ticks; + if (isOrdinal) { + angularDataMerged = µ.util.deduplicate(angularDataMerged); + ticks = angularDataMerged.slice(); + angularDataMerged = d3.range(angularDataMerged.length); + data = data.map(function(d, i) { + var result = d; + d.t = [ angularDataMerged ]; + if (isStacked) result.yStack = d.yStack; + return result; + }); + } + var hasOnlyLineOrDotPlot = data.filter(function(d, i) { + return d.geometry === 'LinePlot' || d.geometry === 'DotPlot'; + }).length === data.length; + var needsEndSpacing = axisConfig.needsEndSpacing === null ? isOrdinal || !hasOnlyLineOrDotPlot : axisConfig.needsEndSpacing; + var useProvidedDomain = axisConfig.angularAxis.domain && axisConfig.angularAxis.domain != µ.DATAEXTENT && !isOrdinal && axisConfig.angularAxis.domain[0] >= 0; + var angularDomain = useProvidedDomain ? axisConfig.angularAxis.domain : d3.extent(angularDataMerged); + var angularDomainStep = Math.abs(angularDataMerged[1] - angularDataMerged[0]); + if (hasOnlyLineOrDotPlot && !isOrdinal) angularDomainStep = 0; + var angularDomainWithPadding = angularDomain.slice(); + if (needsEndSpacing && isOrdinal) angularDomainWithPadding[1] += angularDomainStep; + var tickCount = axisConfig.angularAxis.ticksCount || 4; + if (tickCount > 8) tickCount = tickCount / (tickCount / 8) + tickCount % 8; + if (axisConfig.angularAxis.ticksStep) { + tickCount = (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / tickCount; + } + var angularTicksStep = axisConfig.angularAxis.ticksStep || (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / (tickCount * (axisConfig.minorTicks + 1)); + if (ticks) angularTicksStep = Math.max(Math.round(angularTicksStep), 1); + if (!angularDomainWithPadding[2]) angularDomainWithPadding[2] = angularTicksStep; + var angularAxisRange = d3.range.apply(this, angularDomainWithPadding); + angularAxisRange = angularAxisRange.map(function(d, i) { + return parseFloat(d.toPrecision(12)); + }); + angularScale = d3.scale.linear().domain(angularDomainWithPadding.slice(0, 2)).range(axisConfig.direction === 'clockwise' ? [ 0, 360 ] : [ 360, 0 ]); + liveConfig.layout.angularAxis.domain = angularScale.domain(); + liveConfig.layout.angularAxis.endPadding = needsEndSpacing ? angularDomainStep : 0; + svg = d3.select(this).select('svg.chart-root'); + if (typeof svg === 'undefined' || svg.empty()) { + var skeleton = "' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '"; + var doc = new DOMParser().parseFromString(skeleton, 'application/xml'); + var newSvg = this.appendChild(this.ownerDocument.importNode(doc.documentElement, true)); + svg = d3.select(newSvg); + } + svg.select('.guides-group').style({ + 'pointer-events': 'none' + }); + svg.select('.angular.axis-group').style({ + 'pointer-events': 'none' + }); + svg.select('.radial.axis-group').style({ + 'pointer-events': 'none' + }); + var chartGroup = svg.select('.chart-group'); + var lineStyle = { + fill: 'none', + stroke: axisConfig.tickColor + }; + var fontStyle = { + 'font-size': axisConfig.font.size, + 'font-family': axisConfig.font.family, + fill: axisConfig.font.color, + 'text-shadow': [ '-1px 0px', '1px -1px', '-1px 1px', '1px 1px' ].map(function(d, i) { + return ' ' + d + ' 0 ' + axisConfig.font.outlineColor; + }).join(',') + }; + var legendContainer; + if (axisConfig.showLegend) { + legendContainer = svg.select('.legend-group').attr({ + transform: 'translate(' + [ radius, axisConfig.margin.top ] + ')' + }).style({ + display: 'block' + }); + var elements = data.map(function(d, i) { + var datumClone = µ.util.cloneJson(d); + datumClone.symbol = d.geometry === 'DotPlot' ? d.dotType || 'circle' : d.geometry != 'LinePlot' ? 'square' : 'line'; + datumClone.visibleInLegend = typeof d.visibleInLegend === 'undefined' || d.visibleInLegend; + datumClone.color = d.geometry === 'LinePlot' ? d.strokeColor : d.color; + return datumClone; + }); + + µ.Legend().config({ + data: data.map(function(d, i) { + return d.name || 'Element' + i; + }), + legendConfig: extendDeepAll({}, + µ.Legend.defaultConfig().legendConfig, + { + container: legendContainer, + elements: elements, + reverseOrder: axisConfig.legend.reverseOrder + } + ) + })(); + + var legendBBox = legendContainer.node().getBBox(); + radius = Math.min(axisConfig.width - legendBBox.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; + radius = Math.max(10, radius); + chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; + radialScale.range([ 0, radius ]); + liveConfig.layout.radialAxis.domain = radialScale.domain(); + legendContainer.attr('transform', 'translate(' + [ chartCenter[0] + radius, chartCenter[1] - radius ] + ')'); + } else { + legendContainer = svg.select('.legend-group').style({ + display: 'none' + }); + } + svg.attr({ + width: axisConfig.width, + height: axisConfig.height + }).style({ + opacity: axisConfig.opacity + }); + chartGroup.attr('transform', 'translate(' + chartCenter + ')').style({ + cursor: 'crosshair' + }); + var centeringOffset = [ (axisConfig.width - (axisConfig.margin.left + axisConfig.margin.right + radius * 2 + (legendBBox ? legendBBox.width : 0))) / 2, (axisConfig.height - (axisConfig.margin.top + axisConfig.margin.bottom + radius * 2)) / 2 ]; + centeringOffset[0] = Math.max(0, centeringOffset[0]); + centeringOffset[1] = Math.max(0, centeringOffset[1]); + svg.select('.outer-group').attr('transform', 'translate(' + centeringOffset + ')'); + if (axisConfig.title) { + var title = svg.select('g.title-group text').style(fontStyle).text(axisConfig.title); + var titleBBox = title.node().getBBox(); + title.attr({ + x: chartCenter[0] - titleBBox.width / 2, + y: chartCenter[1] - radius - 20 + }); + } + var radialAxis = svg.select('.radial.axis-group'); + if (axisConfig.radialAxis.gridLinesVisible) { + var gridCircles = radialAxis.selectAll('circle.grid-circle').data(radialScale.ticks(5)); + gridCircles.enter().append('circle').attr({ + 'class': 'grid-circle' + }).style(lineStyle); + gridCircles.attr('r', radialScale); + gridCircles.exit().remove(); + } + radialAxis.select('circle.outside-circle').attr({ + r: radius + }).style(lineStyle); + var backgroundCircle = svg.select('circle.background-circle').attr({ + r: radius + }).style({ + fill: axisConfig.backgroundColor, + stroke: axisConfig.stroke + }); + function currentAngle(d, i) { + return angularScale(d) % 360 + axisConfig.orientation; + } + if (axisConfig.radialAxis.visible) { + var axis = d3.svg.axis().scale(radialScale).ticks(5).tickSize(5); + radialAxis.call(axis).attr({ + transform: 'rotate(' + axisConfig.radialAxis.orientation + ')' + }); + radialAxis.selectAll('.domain').style(lineStyle); + radialAxis.selectAll('g>text').text(function(d, i) { + return this.textContent + axisConfig.radialAxis.ticksSuffix; + }).style(fontStyle).style({ + 'text-anchor': 'start' + }).attr({ + x: 0, + y: 0, + dx: 0, + dy: 0, + transform: function(d, i) { + if (axisConfig.radialAxis.tickOrientation === 'horizontal') { + return 'rotate(' + -axisConfig.radialAxis.orientation + ') translate(' + [ 0, fontStyle['font-size'] ] + ')'; + } else return 'translate(' + [ 0, fontStyle['font-size'] ] + ')'; + } + }); + radialAxis.selectAll('g>line').style({ + stroke: 'black' + }); + } + var angularAxis = svg.select('.angular.axis-group').selectAll('g.angular-tick').data(angularAxisRange); + var angularAxisEnter = angularAxis.enter().append('g').classed('angular-tick', true); + angularAxis.attr({ + transform: function(d, i) { + return 'rotate(' + currentAngle(d, i) + ')'; + } + }).style({ + display: axisConfig.angularAxis.visible ? 'block' : 'none' + }); + angularAxis.exit().remove(); + angularAxisEnter.append('line').classed('grid-line', true).classed('major', function(d, i) { + return i % (axisConfig.minorTicks + 1) == 0; + }).classed('minor', function(d, i) { + return !(i % (axisConfig.minorTicks + 1) == 0); + }).style(lineStyle); + angularAxisEnter.selectAll('.minor').style({ + stroke: axisConfig.minorTickColor + }); + angularAxis.select('line.grid-line').attr({ + x1: axisConfig.tickLength ? radius - axisConfig.tickLength : 0, + x2: radius + }).style({ + display: axisConfig.angularAxis.gridLinesVisible ? 'block' : 'none' + }); + angularAxisEnter.append('text').classed('axis-text', true).style(fontStyle); + var ticksText = angularAxis.select('text.axis-text').attr({ + x: radius + axisConfig.labelOffset, + dy: MID_SHIFT + 'em', + transform: function(d, i) { + var angle = currentAngle(d, i); + var rad = radius + axisConfig.labelOffset; + var orient = axisConfig.angularAxis.tickOrientation; + if (orient == 'horizontal') return 'rotate(' + -angle + ' ' + rad + ' 0)'; else if (orient == 'radial') return angle < 270 && angle > 90 ? 'rotate(180 ' + rad + ' 0)' : null; else return 'rotate(' + (angle <= 180 && angle > 0 ? -90 : 90) + ' ' + rad + ' 0)'; + } + }).style({ + 'text-anchor': 'middle', + display: axisConfig.angularAxis.labelsVisible ? 'block' : 'none' + }).text(function(d, i) { + if (i % (axisConfig.minorTicks + 1) != 0) return ''; + if (ticks) { + return ticks[d] + axisConfig.angularAxis.ticksSuffix; + } else return d + axisConfig.angularAxis.ticksSuffix; + }).style(fontStyle); + if (axisConfig.angularAxis.rewriteTicks) ticksText.text(function(d, i) { + if (i % (axisConfig.minorTicks + 1) != 0) return ''; + return axisConfig.angularAxis.rewriteTicks(this.textContent, i); + }); + var rightmostTickEndX = d3.max(chartGroup.selectAll('.angular-tick text')[0].map(function(d, i) { + return d.getCTM().e + d.getBBox().width; + })); + legendContainer.attr({ + transform: 'translate(' + [ radius + rightmostTickEndX, axisConfig.margin.top ] + ')' + }); + var hasGeometry = svg.select('g.geometry-group').selectAll('g').size() > 0; + var geometryContainer = svg.select('g.geometry-group').selectAll('g.geometry').data(data); + geometryContainer.enter().append('g').attr({ + 'class': function(d, i) { + return 'geometry geometry' + i; + } + }); + geometryContainer.exit().remove(); + if (data[0] || hasGeometry) { + var geometryConfigs = []; + data.forEach(function(d, i) { + var geometryConfig = {}; + geometryConfig.radialScale = radialScale; + geometryConfig.angularScale = angularScale; + geometryConfig.container = geometryContainer.filter(function(dB, iB) { + return iB == i; + }); + geometryConfig.geometry = d.geometry; + geometryConfig.orientation = axisConfig.orientation; + geometryConfig.direction = axisConfig.direction; + geometryConfig.index = i; + geometryConfigs.push({ + data: d, + geometryConfig: geometryConfig + }); + }); + var geometryConfigsGrouped = d3.nest().key(function(d, i) { + return typeof d.data.groupId != 'undefined' || 'unstacked'; + }).entries(geometryConfigs); + var geometryConfigsGrouped2 = []; + geometryConfigsGrouped.forEach(function(d, i) { + if (d.key === 'unstacked') geometryConfigsGrouped2 = geometryConfigsGrouped2.concat(d.values.map(function(d, i) { + return [ d ]; + })); else geometryConfigsGrouped2.push(d.values); + }); + geometryConfigsGrouped2.forEach(function(d, i) { + var geometry; + if (Array.isArray(d)) geometry = d[0].geometryConfig.geometry; else geometry = d.geometryConfig.geometry; + var finalGeometryConfig = d.map(function(dB, iB) { + return extendDeepAll(µ[geometry].defaultConfig(), dB); + }); + µ[geometry]().config(finalGeometryConfig)(); + }); + } + var guides = svg.select('.guides-group'); + var tooltipContainer = svg.select('.tooltips-group'); + var angularTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + fontSize: 8 + })(); + var radialTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + fontSize: 8 + })(); + var geometryTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + hasTick: true + })(); + var angularValue, radialValue; + if (!isOrdinal) { + var angularGuideLine = guides.select('line').attr({ + x1: 0, + y1: 0, + y2: 0 + }).style({ + stroke: 'grey', + 'pointer-events': 'none' + }); + chartGroup.on('mousemove.angular-guide', function(d, i) { + var mouseAngle = µ.util.getMousePos(backgroundCircle).angle; + angularGuideLine.attr({ + x2: -radius, + transform: 'rotate(' + mouseAngle + ')' + }).style({ + opacity: .5 + }); + var angleWithOriginOffset = (mouseAngle + 180 + 360 - axisConfig.orientation) % 360; + angularValue = angularScale.invert(angleWithOriginOffset); + var pos = µ.util.convertToCartesian(radius + 12, mouseAngle + 180); + angularTooltip.text(µ.util.round(angularValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); + }).on('mouseout.angular-guide', function(d, i) { + guides.select('line').style({ + opacity: 0 + }); + }); + } + var angularGuideCircle = guides.select('circle').style({ + stroke: 'grey', + fill: 'none' + }); + chartGroup.on('mousemove.radial-guide', function(d, i) { + var r = µ.util.getMousePos(backgroundCircle).radius; + angularGuideCircle.attr({ + r: r + }).style({ + opacity: .5 + }); + radialValue = radialScale.invert(µ.util.getMousePos(backgroundCircle).radius); + var pos = µ.util.convertToCartesian(r, axisConfig.radialAxis.orientation); + radialTooltip.text(µ.util.round(radialValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); + }).on('mouseout.radial-guide', function(d, i) { + angularGuideCircle.style({ + opacity: 0 + }); + geometryTooltip.hide(); + angularTooltip.hide(); + radialTooltip.hide(); + }); + svg.selectAll('.geometry-group .mark').on('mouseover.tooltip', function(d, i) { + var el = d3.select(this); + var color = this.style.fill; + var newColor = 'black'; + var opacity = this.style.opacity || 1; + el.attr({ + 'data-opacity': opacity + }); + if (color && color !== 'none') { + el.attr({ + 'data-fill': color + }); + newColor = d3.hsl(color).darker().toString(); + el.style({ + fill: newColor, + opacity: 1 + }); + var textData = { + t: µ.util.round(d[0]), + r: µ.util.round(d[1]) + }; + if (isOrdinal) textData.t = ticks[d[0]]; + var text = 't: ' + textData.t + ', r: ' + textData.r; + var bbox = this.getBoundingClientRect(); + var svgBBox = svg.node().getBoundingClientRect(); + var pos = [ bbox.left + bbox.width / 2 - centeringOffset[0] - svgBBox.left, bbox.top + bbox.height / 2 - centeringOffset[1] - svgBBox.top ]; + geometryTooltip.config({ + color: newColor + }).text(text); + geometryTooltip.move(pos); + } else { + color = this.style.stroke || 'black'; + el.attr({ + 'data-stroke': color + }); + newColor = d3.hsl(color).darker().toString(); + el.style({ + stroke: newColor, + opacity: 1 + }); + } + }).on('mousemove.tooltip', function(d, i) { + if (d3.event.which != 0) return false; + if (d3.select(this).attr('data-fill')) geometryTooltip.show(); + }).on('mouseout.tooltip', function(d, i) { + geometryTooltip.hide(); + var el = d3.select(this); + var fillColor = el.attr('data-fill'); + if (fillColor) el.style({ + fill: fillColor, + opacity: el.attr('data-opacity') + }); else el.style({ + stroke: el.attr('data-stroke'), + opacity: el.attr('data-opacity') + }); + }); + }); + return exports; + } + exports.render = function(_container) { + render(_container); + return this; + }; + exports.config = function(_x) { + if (!arguments.length) return config; + var xClone = µ.util.cloneJson(_x); + xClone.data.forEach(function(d, i) { + if (!config.data[i]) config.data[i] = {}; + extendDeepAll(config.data[i], µ.Axis.defaultConfig().data[0]); + extendDeepAll(config.data[i], d); + }); + extendDeepAll(config.layout, µ.Axis.defaultConfig().layout); + extendDeepAll(config.layout, xClone.layout); + return this; + }; + exports.getLiveConfig = function() { + return liveConfig; + }; + exports.getinputConfig = function() { + return inputConfig; + }; + exports.radialScale = function(_x) { + return radialScale; + }; + exports.angularScale = function(_x) { + return angularScale; + }; + exports.svg = function() { + return svg; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.Axis.defaultConfig = function(d, i) { + var config = { + data: [ { + t: [ 1, 2, 3, 4 ], + r: [ 10, 11, 12, 13 ], + name: 'Line1', + geometry: 'LinePlot', + color: null, + strokeDash: 'solid', + strokeColor: null, + strokeSize: '1', + visibleInLegend: true, + opacity: 1 + } ], + layout: { + defaultColorRange: d3.scale.category10().range(), + title: null, + height: 450, + width: 500, + margin: { + top: 40, + right: 40, + bottom: 40, + left: 40 + }, + font: { + size: 12, + color: 'gray', + outlineColor: 'white', + family: 'Tahoma, sans-serif' + }, + direction: 'clockwise', + orientation: 0, + labelOffset: 10, + radialAxis: { + domain: null, + orientation: -45, + ticksSuffix: '', + visible: true, + gridLinesVisible: true, + tickOrientation: 'horizontal', + rewriteTicks: null + }, + angularAxis: { + domain: [ 0, 360 ], + ticksSuffix: '', + visible: true, + gridLinesVisible: true, + labelsVisible: true, + tickOrientation: 'horizontal', + rewriteTicks: null, + ticksCount: null, + ticksStep: null + }, + minorTicks: 0, + tickLength: null, + tickColor: 'silver', + minorTickColor: '#eee', + backgroundColor: 'none', + needsEndSpacing: null, + showLegend: true, + legend: { + reverseOrder: false + }, + opacity: 1 + } + }; + return config; +}; + +µ.util = {}; + +µ.DATAEXTENT = 'dataExtent'; + +µ.AREA = 'AreaChart'; + +µ.LINE = 'LinePlot'; + +µ.DOT = 'DotPlot'; + +µ.BAR = 'BarChart'; + +µ.util._override = function(_objA, _objB) { + for (var x in _objA) if (x in _objB) _objB[x] = _objA[x]; +}; + +µ.util._extend = function(_objA, _objB) { + for (var x in _objA) _objB[x] = _objA[x]; +}; + +µ.util._rndSnd = function() { + return Math.random() * 2 - 1 + (Math.random() * 2 - 1) + (Math.random() * 2 - 1); +}; + +µ.util.dataFromEquation2 = function(_equation, _step) { + var step = _step || 6; + var data = d3.range(0, 360 + step, step).map(function(deg, index) { + var theta = deg * Math.PI / 180; + var radius = _equation(theta); + return [ deg, radius ]; + }); + return data; +}; + +µ.util.dataFromEquation = function(_equation, _step, _name) { + var step = _step || 6; + var t = [], r = []; + d3.range(0, 360 + step, step).forEach(function(deg, index) { + var theta = deg * Math.PI / 180; + var radius = _equation(theta); + t.push(deg); + r.push(radius); + }); + var result = { + t: t, + r: r + }; + if (_name) result.name = _name; + return result; +}; + +µ.util.ensureArray = function(_val, _count) { + if (typeof _val === 'undefined') return null; + var arr = [].concat(_val); + return d3.range(_count).map(function(d, i) { + return arr[i] || arr[0]; + }); +}; + +µ.util.fillArrays = function(_obj, _valueNames, _count) { + _valueNames.forEach(function(d, i) { + _obj[d] = µ.util.ensureArray(_obj[d], _count); + }); + return _obj; +}; + +µ.util.cloneJson = function(json) { + return JSON.parse(JSON.stringify(json)); +}; + +µ.util.validateKeys = function(obj, keys) { + if (typeof keys === 'string') keys = keys.split('.'); + var next = keys.shift(); + return obj[next] && (!keys.length || objHasKeys(obj[next], keys)); +}; + +µ.util.sumArrays = function(a, b) { + return d3.zip(a, b).map(function(d, i) { + return d3.sum(d); + }); +}; + +µ.util.arrayLast = function(a) { + return a[a.length - 1]; +}; + +µ.util.arrayEqual = function(a, b) { + var i = Math.max(a.length, b.length, 1); + while (i-- >= 0 && a[i] === b[i]) ; + return i === -2; +}; + +µ.util.flattenArray = function(arr) { + var r = []; + while (!µ.util.arrayEqual(r, arr)) { + r = arr; + arr = [].concat.apply([], arr); + } + return arr; +}; + +µ.util.deduplicate = function(arr) { + return arr.filter(function(v, i, a) { + return a.indexOf(v) == i; + }); +}; + +µ.util.convertToCartesian = function(radius, theta) { + var thetaRadians = theta * Math.PI / 180; + var x = radius * Math.cos(thetaRadians); + var y = radius * Math.sin(thetaRadians); + return [ x, y ]; +}; + +µ.util.round = function(_value, _digits) { + var digits = _digits || 2; + var mult = Math.pow(10, digits); + return Math.round(_value * mult) / mult; +}; + +µ.util.getMousePos = function(_referenceElement) { + var mousePos = d3.mouse(_referenceElement.node()); + var mouseX = mousePos[0]; + var mouseY = mousePos[1]; + var mouse = {}; + mouse.x = mouseX; + mouse.y = mouseY; + mouse.pos = mousePos; + mouse.angle = (Math.atan2(mouseY, mouseX) + Math.PI) * 180 / Math.PI; + mouse.radius = Math.sqrt(mouseX * mouseX + mouseY * mouseY); + return mouse; +}; + +µ.util.duplicatesCount = function(arr) { + var uniques = {}, val; + var dups = {}; + for (var i = 0, len = arr.length; i < len; i++) { + val = arr[i]; + if (val in uniques) { + uniques[val]++; + dups[val] = uniques[val]; + } else { + uniques[val] = 1; + } + } + return dups; +}; + +µ.util.duplicates = function(arr) { + return Object.keys(µ.util.duplicatesCount(arr)); +}; + +µ.util.translator = function(obj, sourceBranch, targetBranch, reverse) { + if (reverse) { + var targetBranchCopy = targetBranch.slice(); + targetBranch = sourceBranch; + sourceBranch = targetBranchCopy; + } + var value = sourceBranch.reduce(function(previousValue, currentValue) { + if (typeof previousValue != 'undefined') return previousValue[currentValue]; + }, obj); + if (typeof value === 'undefined') return; + sourceBranch.reduce(function(previousValue, currentValue, index) { + if (typeof previousValue == 'undefined') return; + if (index === sourceBranch.length - 1) delete previousValue[currentValue]; + return previousValue[currentValue]; + }, obj); + targetBranch.reduce(function(previousValue, currentValue, index) { + if (typeof previousValue[currentValue] === 'undefined') previousValue[currentValue] = {}; + if (index === targetBranch.length - 1) previousValue[currentValue] = value; + return previousValue[currentValue]; + }, obj); +}; + +µ.PolyChart = function module() { + var config = [ µ.PolyChart.defaultConfig() ]; + var dispatch = d3.dispatch('hover'); + var dashArray = { + solid: 'none', + dash: [ 5, 2 ], + dot: [ 2, 5 ] + }; + var colorScale; + function exports() { + var geometryConfig = config[0].geometryConfig; + var container = geometryConfig.container; + if (typeof container == 'string') container = d3.select(container); + container.datum(config).each(function(_config, _index) { + var isStack = !!_config[0].data.yStack; + var data = _config.map(function(d, i) { + if (isStack) return d3.zip(d.data.t[0], d.data.r[0], d.data.yStack[0]); else return d3.zip(d.data.t[0], d.data.r[0]); + }); + var angularScale = geometryConfig.angularScale; + var domainMin = geometryConfig.radialScale.domain()[0]; + var generator = {}; + generator.bar = function(d, i, pI) { + var dataConfig = _config[pI].data; + var h = geometryConfig.radialScale(d[1]) - geometryConfig.radialScale(0); + var stackTop = geometryConfig.radialScale(d[2] || 0); + var w = dataConfig.barWidth; + d3.select(this).attr({ + 'class': 'mark bar', + d: 'M' + [ [ h + stackTop, -w / 2 ], [ h + stackTop, w / 2 ], [ stackTop, w / 2 ], [ stackTop, -w / 2 ] ].join('L') + 'Z', + transform: function(d, i) { + return 'rotate(' + (geometryConfig.orientation + angularScale(d[0])) + ')'; + } + }); + }; + generator.dot = function(d, i, pI) { + var stackedData = d[2] ? [ d[0], d[1] + d[2] ] : d; + var symbol = d3.svg.symbol().size(_config[pI].data.dotSize).type(_config[pI].data.dotType)(d, i); + d3.select(this).attr({ + 'class': 'mark dot', + d: symbol, + transform: function(d, i) { + var coord = convertToCartesian(getPolarCoordinates(stackedData)); + return 'translate(' + [ coord.x, coord.y ] + ')'; + } + }); + }; + var line = d3.svg.line.radial().interpolate(_config[0].data.lineInterpolation).radius(function(d) { + return geometryConfig.radialScale(d[1]); + }).angle(function(d) { + return geometryConfig.angularScale(d[0]) * Math.PI / 180; + }); + generator.line = function(d, i, pI) { + var lineData = d[2] ? data[pI].map(function(d, i) { + return [ d[0], d[1] + d[2] ]; + }) : data[pI]; + d3.select(this).each(generator['dot']).style({ + opacity: function(dB, iB) { + return +_config[pI].data.dotVisible; + }, + fill: markStyle.stroke(d, i, pI) + }).attr({ + 'class': 'mark dot' + }); + if (i > 0) return; + var lineSelection = d3.select(this.parentNode).selectAll('path.line').data([ 0 ]); + lineSelection.enter().insert('path'); + lineSelection.attr({ + 'class': 'line', + d: line(lineData), + transform: function(dB, iB) { + return 'rotate(' + (geometryConfig.orientation + 90) + ')'; + }, + 'pointer-events': 'none' + }).style({ + fill: function(dB, iB) { + return markStyle.fill(d, i, pI); + }, + 'fill-opacity': 0, + stroke: function(dB, iB) { + return markStyle.stroke(d, i, pI); + }, + 'stroke-width': function(dB, iB) { + return markStyle['stroke-width'](d, i, pI); + }, + 'stroke-dasharray': function(dB, iB) { + return markStyle['stroke-dasharray'](d, i, pI); + }, + opacity: function(dB, iB) { + return markStyle.opacity(d, i, pI); + }, + display: function(dB, iB) { + return markStyle.display(d, i, pI); + } + }); + }; + var angularRange = geometryConfig.angularScale.range(); + var triangleAngle = Math.abs(angularRange[1] - angularRange[0]) / data[0].length * Math.PI / 180; + var arc = d3.svg.arc().startAngle(function(d) { + return -triangleAngle / 2; + }).endAngle(function(d) { + return triangleAngle / 2; + }).innerRadius(function(d) { + return geometryConfig.radialScale(domainMin + (d[2] || 0)); + }).outerRadius(function(d) { + return geometryConfig.radialScale(domainMin + (d[2] || 0)) + geometryConfig.radialScale(d[1]); + }); + generator.arc = function(d, i, pI) { + d3.select(this).attr({ + 'class': 'mark arc', + d: arc, + transform: function(d, i) { + return 'rotate(' + (geometryConfig.orientation + angularScale(d[0]) + 90) + ')'; + } + }); + }; + var markStyle = { + fill: function(d, i, pI) { + return _config[pI].data.color; + }, + stroke: function(d, i, pI) { + return _config[pI].data.strokeColor; + }, + 'stroke-width': function(d, i, pI) { + return _config[pI].data.strokeSize + 'px'; + }, + 'stroke-dasharray': function(d, i, pI) { + return dashArray[_config[pI].data.strokeDash]; + }, + opacity: function(d, i, pI) { + return _config[pI].data.opacity; + }, + display: function(d, i, pI) { + return typeof _config[pI].data.visible === 'undefined' || _config[pI].data.visible ? 'block' : 'none'; + } + }; + var geometryLayer = d3.select(this).selectAll('g.layer').data(data); + geometryLayer.enter().append('g').attr({ + 'class': 'layer' + }); + var geometry = geometryLayer.selectAll('path.mark').data(function(d, i) { + return d; + }); + geometry.enter().append('path').attr({ + 'class': 'mark' + }); + geometry.style(markStyle).each(generator[geometryConfig.geometryType]); + geometry.exit().remove(); + geometryLayer.exit().remove(); + function getPolarCoordinates(d, i) { + var r = geometryConfig.radialScale(d[1]); + var t = (geometryConfig.angularScale(d[0]) + geometryConfig.orientation) * Math.PI / 180; + return { + r: r, + t: t + }; + } + function convertToCartesian(polarCoordinates) { + var x = polarCoordinates.r * Math.cos(polarCoordinates.t); + var y = polarCoordinates.r * Math.sin(polarCoordinates.t); + return { + x: x, + y: y + }; + } + }); + } + exports.config = function(_x) { + if (!arguments.length) return config; + _x.forEach(function(d, i) { + if (!config[i]) config[i] = {}; + extendDeepAll(config[i], µ.PolyChart.defaultConfig()); + extendDeepAll(config[i], d); + }); + return this; + }; + exports.getColorScale = function() { + return colorScale; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.PolyChart.defaultConfig = function() { + var config = { + data: { + name: 'geom1', + t: [ [ 1, 2, 3, 4 ] ], + r: [ [ 1, 2, 3, 4 ] ], + dotType: 'circle', + dotSize: 64, + dotVisible: false, + barWidth: 20, + color: '#ffa500', + strokeSize: 1, + strokeColor: 'silver', + strokeDash: 'solid', + opacity: 1, + index: 0, + visible: true, + visibleInLegend: true + }, + geometryConfig: { + geometry: 'LinePlot', + geometryType: 'arc', + direction: 'clockwise', + orientation: 0, + container: 'body', + radialScale: null, + angularScale: null, + colorScale: d3.scale.category20() + } + }; + return config; +}; + +µ.BarChart = function module() { + return µ.PolyChart(); +}; + +µ.BarChart.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'bar' + } + }; + return config; +}; + +µ.AreaChart = function module() { + return µ.PolyChart(); +}; + +µ.AreaChart.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'arc' + } + }; + return config; +}; + +µ.DotPlot = function module() { + return µ.PolyChart(); +}; + +µ.DotPlot.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'dot', + dotType: 'circle' + } + }; + return config; +}; + +µ.LinePlot = function module() { + return µ.PolyChart(); +}; + +µ.LinePlot.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'line' + } + }; + return config; +}; + +µ.Legend = function module() { + var config = µ.Legend.defaultConfig(); + var dispatch = d3.dispatch('hover'); + function exports() { + var legendConfig = config.legendConfig; + var flattenData = config.data.map(function(d, i) { + return [].concat(d).map(function(dB, iB) { + var element = extendDeepAll({}, legendConfig.elements[i]); + element.name = dB; + element.color = [].concat(legendConfig.elements[i].color)[iB]; + return element; + }); + }); + var data = d3.merge(flattenData); + data = data.filter(function(d, i) { + return legendConfig.elements[i] && (legendConfig.elements[i].visibleInLegend || typeof legendConfig.elements[i].visibleInLegend === 'undefined'); + }); + if (legendConfig.reverseOrder) data = data.reverse(); + var container = legendConfig.container; + if (typeof container == 'string' || container.nodeName) container = d3.select(container); + var colors = data.map(function(d, i) { + return d.color; + }); + var lineHeight = legendConfig.fontSize; + var isContinuous = legendConfig.isContinuous == null ? typeof data[0] === 'number' : legendConfig.isContinuous; + var height = isContinuous ? legendConfig.height : lineHeight * data.length; + var legendContainerGroup = container.classed('legend-group', true); + var svg = legendContainerGroup.selectAll('svg').data([ 0 ]); + var svgEnter = svg.enter().append('svg').attr({ + width: 300, + height: height + lineHeight, + xmlns: 'http://www.w3.org/2000/svg', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + version: '1.1' + }); + svgEnter.append('g').classed('legend-axis', true); + svgEnter.append('g').classed('legend-marks', true); + var dataNumbered = d3.range(data.length); + var colorScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered).range(colors); + var dataScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered)[isContinuous ? 'range' : 'rangePoints']([ 0, height ]); + var shapeGenerator = function(_type, _size) { + var squareSize = _size * 3; + if (_type === 'line') { + return 'M' + [ [ -_size / 2, -_size / 12 ], [ _size / 2, -_size / 12 ], [ _size / 2, _size / 12 ], [ -_size / 2, _size / 12 ] ] + 'Z'; + } else if (d3.svg.symbolTypes.indexOf(_type) != -1) return d3.svg.symbol().type(_type).size(squareSize)(); else return d3.svg.symbol().type('square').size(squareSize)(); + }; + if (isContinuous) { + var gradient = svg.select('.legend-marks').append('defs').append('linearGradient').attr({ + id: 'grad1', + x1: '0%', + y1: '0%', + x2: '0%', + y2: '100%' + }).selectAll('stop').data(colors); + gradient.enter().append('stop'); + gradient.attr({ + offset: function(d, i) { + return i / (colors.length - 1) * 100 + '%'; + } + }).style({ + 'stop-color': function(d, i) { + return d; + } + }); + svg.append('rect').classed('legend-mark', true).attr({ + height: legendConfig.height, + width: legendConfig.colorBandWidth, + fill: 'url(#grad1)' + }); + } else { + var legendElement = svg.select('.legend-marks').selectAll('path.legend-mark').data(data); + legendElement.enter().append('path').classed('legend-mark', true); + legendElement.attr({ + transform: function(d, i) { + return 'translate(' + [ lineHeight / 2, dataScale(i) + lineHeight / 2 ] + ')'; + }, + d: function(d, i) { + var symbolType = d.symbol; + return shapeGenerator(symbolType, lineHeight); + }, + fill: function(d, i) { + return colorScale(i); + } + }); + legendElement.exit().remove(); + } + var legendAxis = d3.svg.axis().scale(dataScale).orient('right'); + var axis = svg.select('g.legend-axis').attr({ + transform: 'translate(' + [ isContinuous ? legendConfig.colorBandWidth : lineHeight, lineHeight / 2 ] + ')' + }).call(legendAxis); + axis.selectAll('.domain').style({ + fill: 'none', + stroke: 'none' + }); + axis.selectAll('line').style({ + fill: 'none', + stroke: isContinuous ? legendConfig.textColor : 'none' + }); + axis.selectAll('text').style({ + fill: legendConfig.textColor, + 'font-size': legendConfig.fontSize + }).text(function(d, i) { + return data[i].name; + }); + return exports; + } + exports.config = function(_x) { + if (!arguments.length) return config; + extendDeepAll(config, _x); + return this; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.Legend.defaultConfig = function(d, i) { + var config = { + data: [ 'a', 'b', 'c' ], + legendConfig: { + elements: [ { + symbol: 'line', + color: 'red' + }, { + symbol: 'square', + color: 'yellow' + }, { + symbol: 'diamond', + color: 'limegreen' + } ], + height: 150, + colorBandWidth: 30, + fontSize: 12, + container: 'body', + isContinuous: null, + textColor: 'grey', + reverseOrder: false + } + }; + return config; +}; + +µ.tooltipPanel = function() { + var tooltipEl, tooltipTextEl, backgroundEl; + var config = { + container: null, + hasTick: false, + fontSize: 12, + color: 'white', + padding: 5 + }; + var id = 'tooltip-' + µ.tooltipPanel.uid++; + var tickSize = 10; + var exports = function() { + tooltipEl = config.container.selectAll('g.' + id).data([ 0 ]); + var tooltipEnter = tooltipEl.enter().append('g').classed(id, true).style({ + 'pointer-events': 'none', + display: 'none' + }); + backgroundEl = tooltipEnter.append('path').style({ + fill: 'white', + 'fill-opacity': .9 + }).attr({ + d: 'M0 0' + }); + tooltipTextEl = tooltipEnter.append('text').attr({ + dx: config.padding + tickSize, + dy: +config.fontSize * .3 + }); + return exports; + }; + exports.text = function(_text) { + var l = d3.hsl(config.color).l; + var strokeColor = l >= .5 ? '#aaa' : 'white'; + var fillColor = l >= .5 ? 'black' : 'white'; + var text = _text || ''; + tooltipTextEl.style({ + fill: fillColor, + 'font-size': config.fontSize + 'px' + }).text(text); + var padding = config.padding; + var bbox = tooltipTextEl.node().getBBox(); + var boxStyle = { + fill: config.color, + stroke: strokeColor, + 'stroke-width': '2px' + }; + var backGroundW = bbox.width + padding * 2 + tickSize; + var backGroundH = bbox.height + padding * 2; + backgroundEl.attr({ + d: 'M' + [ [ tickSize, -backGroundH / 2 ], [ tickSize, -backGroundH / 4 ], [ config.hasTick ? 0 : tickSize, 0 ], [ tickSize, backGroundH / 4 ], [ tickSize, backGroundH / 2 ], [ backGroundW, backGroundH / 2 ], [ backGroundW, -backGroundH / 2 ] ].join('L') + 'Z' + }).style(boxStyle); + tooltipEl.attr({ + transform: 'translate(' + [ tickSize, -backGroundH / 2 + padding * 2 ] + ')' + }); + tooltipEl.style({ + display: 'block' + }); + return exports; + }; + exports.move = function(_pos) { + if (!tooltipEl) return; + tooltipEl.attr({ + transform: 'translate(' + [ _pos[0], _pos[1] ] + ')' + }).style({ + display: 'block' + }); + return exports; + }; + exports.hide = function() { + if (!tooltipEl) return; + tooltipEl.style({ + display: 'none' + }); + return exports; + }; + exports.show = function() { + if (!tooltipEl) return; + tooltipEl.style({ + display: 'block' + }); + return exports; + }; + exports.config = function(_x) { + extendDeepAll(config, _x); + return exports; + }; + return exports; +}; + +µ.tooltipPanel.uid = 1; + +µ.adapter = {}; + +µ.adapter.plotly = function module() { + var exports = {}; + exports.convert = function(_inputConfig, reverse) { + var outputConfig = {}; + if (_inputConfig.data) { + outputConfig.data = _inputConfig.data.map(function(d, i) { + var r = extendDeepAll({}, d); + var toTranslate = [ + [ r, [ 'marker', 'color' ], [ 'color' ] ], + [ r, [ 'marker', 'opacity' ], [ 'opacity' ] ], + [ r, [ 'marker', 'line', 'color' ], [ 'strokeColor' ] ], + [ r, [ 'marker', 'line', 'dash' ], [ 'strokeDash' ] ], + [ r, [ 'marker', 'line', 'width' ], [ 'strokeSize' ] ], + [ r, [ 'marker', 'symbol' ], [ 'dotType' ] ], + [ r, [ 'marker', 'size' ], [ 'dotSize' ] ], + [ r, [ 'marker', 'barWidth' ], [ 'barWidth' ] ], + [ r, [ 'line', 'interpolation' ], [ 'lineInterpolation' ] ], + [ r, [ 'showlegend' ], [ 'visibleInLegend' ] ] + ]; + toTranslate.forEach(function(d, i) { + µ.util.translator.apply(null, d.concat(reverse)); + }); + + if (!reverse) delete r.marker; + if (reverse) delete r.groupId; + if (!reverse) { + if (r.type === 'scatter') { + if (r.mode === 'lines') r.geometry = 'LinePlot'; else if (r.mode === 'markers') r.geometry = 'DotPlot'; else if (r.mode === 'lines+markers') { + r.geometry = 'LinePlot'; + r.dotVisible = true; + } + } else if (r.type === 'area') r.geometry = 'AreaChart'; else if (r.type === 'bar') r.geometry = 'BarChart'; + delete r.mode; + delete r.type; + } else { + if (r.geometry === 'LinePlot') { + r.type = 'scatter'; + if (r.dotVisible === true) { + delete r.dotVisible; + r.mode = 'lines+markers'; + } else r.mode = 'lines'; + } else if (r.geometry === 'DotPlot') { + r.type = 'scatter'; + r.mode = 'markers'; + } else if (r.geometry === 'AreaChart') r.type = 'area'; else if (r.geometry === 'BarChart') r.type = 'bar'; + delete r.geometry; + } + return r; + }); + if (!reverse && _inputConfig.layout && _inputConfig.layout.barmode === 'stack') { + var duplicates = µ.util.duplicates(outputConfig.data.map(function(d, i) { + return d.geometry; + })); + outputConfig.data.forEach(function(d, i) { + var idx = duplicates.indexOf(d.geometry); + if (idx != -1) outputConfig.data[i].groupId = idx; + }); + } + } + if (_inputConfig.layout) { + var r = extendDeepAll({}, _inputConfig.layout); + var toTranslate = [ + [ r, [ 'plot_bgcolor' ], [ 'backgroundColor' ] ], + [ r, [ 'showlegend' ], [ 'showLegend' ] ], + [ r, [ 'radialaxis' ], [ 'radialAxis' ] ], + [ r, [ 'angularaxis' ], [ 'angularAxis' ] ], + [ r.angularaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.angularaxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], + [ r.angularaxis, [ 'nticks' ], [ 'ticksCount' ] ], + [ r.angularaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.angularaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.angularaxis, [ 'range' ], [ 'domain' ] ], + [ r.angularaxis, [ 'endpadding' ], [ 'endPadding' ] ], + [ r.radialaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.radialaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.radialaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.radialaxis, [ 'range' ], [ 'domain' ] ], + [ r.angularAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.angularAxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], + [ r.angularAxis, [ 'nticks' ], [ 'ticksCount' ] ], + [ r.angularAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.angularAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.angularAxis, [ 'range' ], [ 'domain' ] ], + [ r.angularAxis, [ 'endpadding' ], [ 'endPadding' ] ], + [ r.radialAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.radialAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.radialAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.radialAxis, [ 'range' ], [ 'domain' ] ], + [ r.font, [ 'outlinecolor' ], [ 'outlineColor' ] ], + [ r.legend, [ 'traceorder' ], [ 'reverseOrder' ] ], + [ r, [ 'labeloffset' ], [ 'labelOffset' ] ], + [ r, [ 'defaultcolorrange' ], [ 'defaultColorRange' ] ] + ]; + toTranslate.forEach(function(d, i) { + µ.util.translator.apply(null, d.concat(reverse)); + }); + + if (!reverse) { + if (r.angularAxis && typeof r.angularAxis.ticklen !== 'undefined') r.tickLength = r.angularAxis.ticklen; + if (r.angularAxis && typeof r.angularAxis.tickcolor !== 'undefined') r.tickColor = r.angularAxis.tickcolor; + } else { + if (typeof r.tickLength !== 'undefined') { + r.angularaxis.ticklen = r.tickLength; + delete r.tickLength; + } + if (r.tickColor) { + r.angularaxis.tickcolor = r.tickColor; + delete r.tickColor; + } + } + if (r.legend && typeof r.legend.reverseOrder != 'boolean') { + r.legend.reverseOrder = r.legend.reverseOrder != 'normal'; + } + if (r.legend && typeof r.legend.traceorder == 'boolean') { + r.legend.traceorder = r.legend.traceorder ? 'reversed' : 'normal'; + delete r.legend.reverseOrder; + } + if (r.margin && typeof r.margin.t != 'undefined') { + var source = [ 't', 'r', 'b', 'l', 'pad' ]; + var target = [ 'top', 'right', 'bottom', 'left', 'pad' ]; + var margin = {}; + d3.entries(r.margin).forEach(function(dB, iB) { + margin[target[source.indexOf(dB.key)]] = dB.value; + }); + r.margin = margin; + } + if (reverse) { + delete r.needsEndSpacing; + delete r.minorTickColor; + delete r.minorTicks; + delete r.angularaxis.ticksCount; + delete r.angularaxis.ticksCount; + delete r.angularaxis.ticksStep; + delete r.angularaxis.rewriteTicks; + delete r.angularaxis.nticks; + delete r.radialaxis.ticksCount; + delete r.radialaxis.ticksCount; + delete r.radialaxis.ticksStep; + delete r.radialaxis.rewriteTicks; + delete r.radialaxis.nticks; + } + outputConfig.layout = r; + } + return outputConfig; + }; + return exports; +}; + +},{"../../../constants/alignment":668,"../../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],818:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* eslint-disable new-cap */ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Lib = _dereq_('../../../lib'); +var Color = _dereq_('../../../components/color'); + +var micropolar = _dereq_('./micropolar'); +var UndoManager = _dereq_('./undo_manager'); +var extendDeepAll = Lib.extendDeepAll; + +var manager = module.exports = {}; + +manager.framework = function(_gd) { + var config, previousConfigClone, plot, convertedInput, container; + var undoManager = new UndoManager(); + + function exports(_inputConfig, _container) { + if(_container) container = _container; + d3.select(d3.select(container).node().parentNode).selectAll('.svg-container>*:not(.chart-root)').remove(); + + config = (!config) ? + _inputConfig : + extendDeepAll(config, _inputConfig); + + if(!plot) plot = micropolar.Axis(); + convertedInput = micropolar.adapter.plotly().convert(config); + plot.config(convertedInput).render(container); + _gd.data = config.data; + _gd.layout = config.layout; + manager.fillLayout(_gd); + return config; + } + exports.isPolar = true; + exports.svg = function() { return plot.svg(); }; + exports.getConfig = function() { return config; }; + exports.getLiveConfig = function() { + return micropolar.adapter.plotly().convert(plot.getLiveConfig(), true); + }; + exports.getLiveScales = function() { return {t: plot.angularScale(), r: plot.radialScale()}; }; + exports.setUndoPoint = function() { + var that = this; + var configClone = micropolar.util.cloneJson(config); + (function(_configClone, _previousConfigClone) { + undoManager.add({ + undo: function() { + if(_previousConfigClone) that(_previousConfigClone); + }, + redo: function() { + that(_configClone); + } + }); + })(configClone, previousConfigClone); + previousConfigClone = micropolar.util.cloneJson(configClone); + }; + exports.undo = function() { undoManager.undo(); }; + exports.redo = function() { undoManager.redo(); }; + return exports; +}; + +manager.fillLayout = function(_gd) { + var container = d3.select(_gd).selectAll('.plot-container'), + paperDiv = container.selectAll('.svg-container'), + paper = _gd.framework && _gd.framework.svg && _gd.framework.svg(), + dflts = { + width: 800, + height: 600, + paper_bgcolor: Color.background, + _container: container, + _paperdiv: paperDiv, + _paper: paper + }; + + _gd._fullLayout = extendDeepAll(dflts, _gd.layout); +}; + +},{"../../../components/color":570,"../../../lib":696,"./micropolar":817,"./undo_manager":819,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],819:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// Modified from https://github.com/ArthurClemens/Javascript-Undo-Manager +// Copyright (c) 2010-2013 Arthur Clemens, arthur@visiblearea.com +module.exports = function UndoManager() { + var undoCommands = [], + index = -1, + isExecuting = false, + callback; + + function execute(command, action) { + if(!command) return this; + + isExecuting = true; + command[action](); + isExecuting = false; + + return this; + } + + return { + add: function(command) { + if(isExecuting) return this; + undoCommands.splice(index + 1, undoCommands.length - index); + undoCommands.push(command); + index = undoCommands.length - 1; + return this; + }, + setCallback: function(callbackFunc) { callback = callbackFunc; }, + undo: function() { + var command = undoCommands[index]; + if(!command) return this; + execute(command, 'undo'); + index -= 1; + if(callback) callback(command.undo); + return this; + }, + redo: function() { + var command = undoCommands[index + 1]; + if(!command) return this; + execute(command, 'redo'); + index += 1; + if(callback) callback(command.redo); + return this; + }, + clear: function() { + undoCommands = []; + index = -1; + }, + hasUndo: function() { return index !== -1; }, + hasRedo: function() { return index < (undoCommands.length - 1); }, + getCommands: function() { return undoCommands; }, + getPreviousCommand: function() { return undoCommands[index - 1]; }, + getIndex: function() { return index; } + }; +}; + +},{}],820:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Plots = _dereq_('../plots'); +var setConvertCartesian = _dereq_('../cartesian/set_convert'); +var setConvertPolar = _dereq_('./set_convert'); +var doAutoRange = _dereq_('../cartesian/autorange').doAutoRange; +var doTicksSingle = _dereq_('../cartesian/axes').doTicksSingle; +var dragBox = _dereq_('../cartesian/dragbox'); +var dragElement = _dereq_('../../components/dragelement'); +var Fx = _dereq_('../../components/fx'); +var Titles = _dereq_('../../components/titles'); +var prepSelect = _dereq_('../cartesian/select').prepSelect; +var selectOnClick = _dereq_('../cartesian/select').selectOnClick; +var clearSelect = _dereq_('../cartesian/select').clearSelect; +var setCursor = _dereq_('../../lib/setcursor'); +var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); +var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; + +var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT; +var constants = _dereq_('./constants'); +var helpers = _dereq_('./helpers'); + +var _ = Lib._; +var mod = Lib.mod; +var deg2rad = Lib.deg2rad; +var rad2deg = Lib.rad2deg; + +function Polar(gd, id) { + this.id = id; + this.gd = gd; + + this._hasClipOnAxisFalse = null; + this.vangles = null; + this.radialAxisAngle = null; + this.traceHash = {}; + this.layers = {}; + this.clipPaths = {}; + this.clipIds = {}; + this.viewInitial = {}; + + var fullLayout = gd._fullLayout; + var clipIdBase = 'clip' + fullLayout._uid + id; + + this.clipIds.forTraces = clipIdBase + '-for-traces'; + this.clipPaths.forTraces = fullLayout._clips.append('clipPath') + .attr('id', this.clipIds.forTraces); + this.clipPaths.forTraces.append('path'); + + this.framework = fullLayout._polarlayer.append('g') + .attr('class', id); + + // unfortunately, we have to keep track of some axis tick settings + // so that we don't have to call doTicksSingle with its special redraw flag + this.radialTickLayout = null; + this.angularTickLayout = null; +} + +var proto = Polar.prototype; + +module.exports = function createPolar(gd, id) { + return new Polar(gd, id); +}; + +proto.plot = function(polarCalcData, fullLayout) { + var _this = this; + var polarLayout = fullLayout[_this.id]; + + _this._hasClipOnAxisFalse = false; + for(var i = 0; i < polarCalcData.length; i++) { + var trace = polarCalcData[i][0].trace; + if(trace.cliponaxis === false) { + _this._hasClipOnAxisFalse = true; + break; + } + } + + _this.updateLayers(fullLayout, polarLayout); + _this.updateLayout(fullLayout, polarLayout); + Plots.generalUpdatePerTraceModule(_this.gd, _this, polarCalcData, polarLayout); + _this.updateFx(fullLayout, polarLayout); +}; + +proto.updateLayers = function(fullLayout, polarLayout) { + var _this = this; + var layers = _this.layers; + var radialLayout = polarLayout.radialaxis; + var angularLayout = polarLayout.angularaxis; + var layerNames = constants.layerNames; + + var frontPlotIndex = layerNames.indexOf('frontplot'); + var layerData = layerNames.slice(0, frontPlotIndex); + var isAngularAxisBelowTraces = angularLayout.layer === 'below traces'; + var isRadialAxisBelowTraces = radialLayout.layer === 'below traces'; + + if(isAngularAxisBelowTraces) layerData.push('angular-line'); + if(isRadialAxisBelowTraces) layerData.push('radial-line'); + if(isAngularAxisBelowTraces) layerData.push('angular-axis'); + if(isRadialAxisBelowTraces) layerData.push('radial-axis'); + + layerData.push('frontplot'); + + if(!isAngularAxisBelowTraces) layerData.push('angular-line'); + if(!isRadialAxisBelowTraces) layerData.push('radial-line'); + if(!isAngularAxisBelowTraces) layerData.push('angular-axis'); + if(!isRadialAxisBelowTraces) layerData.push('radial-axis'); + + var join = _this.framework.selectAll('.polarsublayer') + .data(layerData, String); + + join.enter().append('g') + .attr('class', function(d) { return 'polarsublayer ' + d;}) + .each(function(d) { + var sel = layers[d] = d3.select(this); + + switch(d) { + case 'frontplot': + // TODO add option to place in 'backplot' layer?? + sel.append('g').classed('barlayer', true); + sel.append('g').classed('scatterlayer', true); + break; + case 'backplot': + sel.append('g').classed('maplayer', true); + break; + case 'plotbg': + layers.bg = sel.append('path'); + break; + case 'radial-grid': + sel.style('fill', 'none'); + sel.append('g').classed('x', 1); + break; + case 'angular-grid': + sel.style('fill', 'none'); + sel.append('g').classed('angularaxis', 1); + break; + case 'radial-line': + sel.append('line').style('fill', 'none'); + break; + case 'angular-line': + sel.append('path').style('fill', 'none'); + break; + } + }); + + join.order(); +}; + +/* Polar subplots juggle with 6 'axis objects' (!), these are: + * + * - polarLayout.radialaxis (aka radialLayout in this file): + * - polarLayout.angularaxis (aka angularLayout in this file): + * used for data -> calcdata conversions (aka d2c) during the calc step + * + * - this.radialAxis + * extends polarLayout.radialaxis, adds mocked 'domain' and + * few other keys in order to reuse Cartesian doAutoRange and doTicksSingle, + * used for calcdata -> geometric conversions (aka c2g) during the plot step + * + setGeometry setups ax.c2g for given ax.range + * + setScale setups ax._m,ax._b for given ax.range + * + * - this.angularAxis + * extends polarLayout.angularaxis, adds mocked 'range' and 'domain' and + * a few other keys in order to reuse Cartesian doTicksSingle, + * used for calcdata -> geometric conversions (aka c2g) during the plot step + * + setGeometry setups ax.c2g given ax.rotation, ax.direction & ax._categories, + * and mocks ax.range + * + setScale setups ax._m,ax._b with that mocked ax.range + * + * - this.xaxis + * - this.yaxis + * setup so that polar traces can reuse plot methods of Cartesian traces + * which mostly rely on 2pixel methods (e.g ax.c2p) + */ +proto.updateLayout = function(fullLayout, polarLayout) { + var _this = this; + var layers = _this.layers; + var gs = fullLayout._size; + + // axis attributes + var radialLayout = polarLayout.radialaxis; + var angularLayout = polarLayout.angularaxis; + // layout domains + var xDomain = polarLayout.domain.x; + var yDomain = polarLayout.domain.y; + // offsets from paper edge to layout domain box + _this.xOffset = gs.l + gs.w * xDomain[0]; + _this.yOffset = gs.t + gs.h * (1 - yDomain[1]); + // lengths of the layout domain box + var xLength = _this.xLength = gs.w * (xDomain[1] - xDomain[0]); + var yLength = _this.yLength = gs.h * (yDomain[1] - yDomain[0]); + // sector to plot + var sector = polarLayout.sector; + _this.sectorInRad = sector.map(deg2rad); + var sectorBBox = _this.sectorBBox = computeSectorBBox(sector); + var dxSectorBBox = sectorBBox[2] - sectorBBox[0]; + var dySectorBBox = sectorBBox[3] - sectorBBox[1]; + // aspect ratios + var arDomain = yLength / xLength; + var arSector = Math.abs(dySectorBBox / dxSectorBBox); + // actual lengths and domains of subplot box + var xLength2, yLength2; + var xDomain2, yDomain2; + var gap; + if(arDomain > arSector) { + xLength2 = xLength; + yLength2 = xLength * arSector; + gap = (yLength - yLength2) / gs.h / 2; + xDomain2 = [xDomain[0], xDomain[1]]; + yDomain2 = [yDomain[0] + gap, yDomain[1] - gap]; + } else { + xLength2 = yLength / arSector; + yLength2 = yLength; + gap = (xLength - xLength2) / gs.w / 2; + xDomain2 = [xDomain[0] + gap, xDomain[1] - gap]; + yDomain2 = [yDomain[0], yDomain[1]]; + } + _this.xLength2 = xLength2; + _this.yLength2 = yLength2; + _this.xDomain2 = xDomain2; + _this.yDomain2 = yDomain2; + // actual offsets from paper edge to the subplot box top-left corner + var xOffset2 = _this.xOffset2 = gs.l + gs.w * xDomain2[0]; + var yOffset2 = _this.yOffset2 = gs.t + gs.h * (1 - yDomain2[1]); + // circle radius in px + var radius = _this.radius = xLength2 / dxSectorBBox; + // 'inner' radius in px (when polar.hole is set) + var innerRadius = _this.innerRadius = polarLayout.hole * radius; + // circle center position in px + var cx = _this.cx = xOffset2 - radius * sectorBBox[0]; + var cy = _this.cy = yOffset2 + radius * sectorBBox[3]; + // circle center in the coordinate system of plot area + var cxx = _this.cxx = cx - xOffset2; + var cyy = _this.cyy = cy - yOffset2; + + _this.radialAxis = _this.mockAxis(fullLayout, polarLayout, radialLayout, { + _axislayer: layers['radial-axis'], + _gridlayer: layers['radial-grid'], + // make this an 'x' axis to make positioning (especially rotation) easier + _id: 'x', + // convert to 'x' axis equivalent + side: { + counterclockwise: 'top', + clockwise: 'bottom' + }[radialLayout.side], + // spans length 1 radius + domain: [innerRadius / gs.w, radius / gs.w] + }); + + _this.angularAxis = _this.mockAxis(fullLayout, polarLayout, angularLayout, { + _axislayer: layers['angular-axis'], + _gridlayer: layers['angular-grid'], + side: 'right', + // to get auto nticks right + domain: [0, Math.PI], + // don't pass through autorange logic + autorange: false + }); + + _this.doAutoRange(fullLayout, polarLayout); + // N.B. this sets _this.vangles + _this.updateAngularAxis(fullLayout, polarLayout); + // N.B. this sets _this.radialAxisAngle + _this.updateRadialAxis(fullLayout, polarLayout); + _this.updateRadialAxisTitle(fullLayout, polarLayout); + + _this.xaxis = _this.mockCartesianAxis(fullLayout, polarLayout, { + _id: 'x', + domain: xDomain2 + }); + + _this.yaxis = _this.mockCartesianAxis(fullLayout, polarLayout, { + _id: 'y', + domain: yDomain2 + }); + + var dPath = _this.pathSubplot(); + + _this.clipPaths.forTraces.select('path') + .attr('d', dPath) + .attr('transform', strTranslate(cxx, cyy)); + + layers.frontplot + .attr('transform', strTranslate(xOffset2, yOffset2)) + .call(Drawing.setClipUrl, _this._hasClipOnAxisFalse ? null : _this.clipIds.forTraces); + + layers.bg + .attr('d', dPath) + .attr('transform', strTranslate(cx, cy)) + .call(Color.fill, polarLayout.bgcolor); + + // remove crispEdges - all the off-square angles in polar plots + // make these counterproductive. + _this.framework.selectAll('.crisp').classed('crisp', 0); +}; + +proto.mockAxis = function(fullLayout, polarLayout, axLayout, opts) { + var commonOpts = { + // to get _boundingBox computation right when showticklabels is false + anchor: 'free', + position: 0, + _pos: 0, + // dummy truthy value to make doTicksSingle draw the grid + _counteraxis: true, + // don't use automargins routine for labels + automargin: false + }; + + var ax = Lib.extendFlat(commonOpts, axLayout, opts); + setConvertPolar(ax, polarLayout, fullLayout); + return ax; +}; + +proto.mockCartesianAxis = function(fullLayout, polarLayout, opts) { + var _this = this; + var axId = opts._id; + + var ax = Lib.extendFlat({type: 'linear'}, opts); + setConvertCartesian(ax, fullLayout); + + var bboxIndices = { + x: [0, 2], + y: [1, 3] + }; + + ax.setRange = function() { + var sectorBBox = _this.sectorBBox; + var ind = bboxIndices[axId]; + var rl = _this.radialAxis._rl; + var drl = (rl[1] - rl[0]) / (1 - polarLayout.hole); + ax.range = [sectorBBox[ind[0]] * drl, sectorBBox[ind[1]] * drl]; + }; + + ax.isPtWithinRange = axId === 'x' ? + function(d) { return _this.isPtInside(d); } : + function() { return true; }; + + ax.setRange(); + ax.setScale(); + return ax; +}; + +proto.doAutoRange = function(fullLayout, polarLayout) { + var gd = this.gd; + var radialAxis = this.radialAxis; + var radialLayout = polarLayout.radialaxis; + + radialAxis.setScale(); + doAutoRange(gd, radialAxis); + + var rng = radialAxis.range; + radialLayout.range = rng.slice(); + radialLayout._input.range = rng.slice(); + + radialAxis._rl = [ + radialAxis.r2l(rng[0], null, 'gregorian'), + radialAxis.r2l(rng[1], null, 'gregorian') + ]; +}; + +proto.updateRadialAxis = function(fullLayout, polarLayout) { + var _this = this; + var gd = _this.gd; + var layers = _this.layers; + var radius = _this.radius; + var innerRadius = _this.innerRadius; + var cx = _this.cx; + var cy = _this.cy; + var radialLayout = polarLayout.radialaxis; + var a0 = mod(polarLayout.sector[0], 360); + var ax = _this.radialAxis; + var hasRoomForIt = innerRadius < radius; + + _this.fillViewInitialKey('radialaxis.angle', radialLayout.angle); + _this.fillViewInitialKey('radialaxis.range', ax.range.slice()); + + ax.setGeometry(); + + // rotate auto tick labels by 180 if in quadrant II and III to make them + // readable from left-to-right + // + // TODO try moving deeper in doTicksSingle for better results? + if(ax.tickangle === 'auto' && (a0 > 90 && a0 <= 270)) { + ax.tickangle = 180; + } + + // easier to set rotate angle with custom translate function + ax._transfn = function(d) { + return 'translate(' + (ax.l2p(d.x) + innerRadius) + ',0)'; + }; + + // set special grid path function + ax._gridpath = function(d) { + return _this.pathArc(ax.r2p(d.x) + innerRadius); + }; + + var newTickLayout = strTickLayout(radialLayout); + if(_this.radialTickLayout !== newTickLayout) { + layers['radial-axis'].selectAll('.xtick').remove(); + _this.radialTickLayout = newTickLayout; + } + + if(hasRoomForIt) { + ax.setScale(); + doTicksSingle(gd, ax, true); + } + + // stash 'actual' radial axis angle for drag handlers (in degrees) + var angle = _this.radialAxisAngle = _this.vangles ? + rad2deg(snapToVertexAngle(deg2rad(radialLayout.angle), _this.vangles)) : + radialLayout.angle; + + var trans = strTranslate(cx, cy) + strRotate(-angle); + + updateElement( + layers['radial-axis'], + hasRoomForIt && (radialLayout.showticklabels || radialLayout.ticks), + {transform: trans} + ); + + // move all grid paths to about circle center, + // undo individual grid lines translations + updateElement( + layers['radial-grid'], + hasRoomForIt && radialLayout.showgrid, + {transform: strTranslate(cx, cy)} + ).selectAll('path').attr('transform', null); + + updateElement( + layers['radial-line'].select('line'), + hasRoomForIt && radialLayout.showline, + { + x1: innerRadius, + y1: 0, + x2: radius, + y2: 0, + transform: trans + } + ) + .attr('stroke-width', radialLayout.linewidth) + .call(Color.stroke, radialLayout.linecolor); +}; + +proto.updateRadialAxisTitle = function(fullLayout, polarLayout, _angle) { + var _this = this; + var gd = _this.gd; + var radius = _this.radius; + var cx = _this.cx; + var cy = _this.cy; + var radialLayout = polarLayout.radialaxis; + var titleClass = _this.id + 'title'; + + var angle = _angle !== undefined ? _angle : _this.radialAxisAngle; + var angleRad = deg2rad(angle); + var cosa = Math.cos(angleRad); + var sina = Math.sin(angleRad); + + var pad = 0; + if(radialLayout.title) { + var h = Drawing.bBox(_this.layers['radial-axis'].node()).height; + var ts = radialLayout.titlefont.size; + pad = radialLayout.side === 'counterclockwise' ? + -h - ts * 0.4 : + h + ts * 0.8; + } + + _this.layers['radial-axis-title'] = Titles.draw(gd, titleClass, { + propContainer: radialLayout, + propName: _this.id + '.radialaxis.title', + placeholder: _(gd, 'Click to enter radial axis title'), + attributes: { + x: cx + (radius / 2) * cosa + pad * sina, + y: cy - (radius / 2) * sina + pad * cosa, + 'text-anchor': 'middle' + }, + transform: {rotate: -angle} + }); +}; + +proto.updateAngularAxis = function(fullLayout, polarLayout) { + var _this = this; + var gd = _this.gd; + var layers = _this.layers; + var radius = _this.radius; + var innerRadius = _this.innerRadius; + var cx = _this.cx; + var cy = _this.cy; + var angularLayout = polarLayout.angularaxis; + var ax = _this.angularAxis; + + _this.fillViewInitialKey('angularaxis.rotation', angularLayout.rotation); + + ax.setGeometry(); + + // 't'ick to 'g'eometric radians is used all over the place here + var t2g = function(d) { return ax.t2g(d.x); }; + + // run rad2deg on tick0 and ditck for thetaunit: 'radians' axes + if(ax.type === 'linear' && ax.thetaunit === 'radians') { + ax.tick0 = rad2deg(ax.tick0); + ax.dtick = rad2deg(ax.dtick); + } + + // Use tickval filter for category axes instead of tweaking + // the range w.r.t sector, so that sectors that cross 360 can + // show all their ticks. + if(ax.type === 'category') { + ax._tickFilter = function(d) { + return Lib.isAngleInsideSector(t2g(d), _this.sectorInRad); + }; + } + + ax._transfn = function(d) { + var sel = d3.select(this); + var hasElement = sel && sel.node(); + + // don't translate grid lines + if(hasElement && sel.classed('angularaxisgrid')) return ''; + + var rad = t2g(d); + var out = strTranslate(cx + radius * Math.cos(rad), cy - radius * Math.sin(rad)); + + // must also rotate ticks, but don't rotate labels + if(hasElement && sel.classed('ticks')) { + out += strRotate(-rad2deg(rad)); + } + + return out; + }; + + ax._gridpath = function(d) { + var rad = t2g(d); + var cosRad = Math.cos(rad); + var sinRad = Math.sin(rad); + return 'M' + [cx + innerRadius * cosRad, cy - innerRadius * sinRad] + + 'L' + [cx + radius * cosRad, cy - radius * sinRad]; + }; + + var offset4fontsize = (angularLayout.ticks !== 'outside' ? 0.7 : 0.5); + + ax._labelx = function(d) { + var rad = t2g(d); + var labelStandoff = ax._labelStandoff; + var pad = ax._pad; + + var offset4tx = signSin(rad) === 0 ? + 0 : + Math.cos(rad) * (labelStandoff + pad + offset4fontsize * d.fontSize); + var offset4tick = signCos(rad) * (d.dx + labelStandoff + pad); + + return offset4tx + offset4tick; + }; + + ax._labely = function(d) { + var rad = t2g(d); + var labelStandoff = ax._labelStandoff; + var labelShift = ax._labelShift; + var pad = ax._pad; + + var offset4tx = d.dy + d.fontSize * MID_SHIFT - labelShift; + var offset4tick = -Math.sin(rad) * (labelStandoff + pad + offset4fontsize * d.fontSize); + + return offset4tx + offset4tick; + }; + + ax._labelanchor = function(angle, d) { + var rad = t2g(d); + return signSin(rad) === 0 ? + (signCos(rad) > 0 ? 'start' : 'end') : + 'middle'; + }; + + var newTickLayout = strTickLayout(angularLayout); + if(_this.angularTickLayout !== newTickLayout) { + layers['angular-axis'].selectAll('.' + ax._id + 'tick').remove(); + _this.angularTickLayout = newTickLayout; + } + + ax.setScale(); + doTicksSingle(gd, ax, true); + + // angle of polygon vertices in geometric radians (null means circles) + // TODO what to do when ax.period > ax._categories ?? + var vangles; + if(polarLayout.gridshape === 'linear') { + vangles = ax._vals.map(t2g); + + // ax._vals should be always ordered, make them + // always turn counterclockwise for convenience here + if(Lib.angleDelta(vangles[0], vangles[1]) < 0) { + vangles = vangles.slice().reverse(); + } + } else { + vangles = null; + } + _this.vangles = vangles; + + // TODO maybe two arcs is better here? + // maybe split style attributes between inner and outer angular axes? + + updateElement(layers['angular-line'].select('path'), angularLayout.showline, { + d: _this.pathSubplot(), + transform: strTranslate(cx, cy) + }) + .attr('stroke-width', angularLayout.linewidth) + .call(Color.stroke, angularLayout.linecolor); +}; + +proto.updateFx = function(fullLayout, polarLayout) { + if(!this.gd._context.staticPlot) { + this.updateAngularDrag(fullLayout); + this.updateRadialDrag(fullLayout, polarLayout, 0); + this.updateRadialDrag(fullLayout, polarLayout, 1); + this.updateMainDrag(fullLayout); + } +}; + +proto.updateMainDrag = function(fullLayout) { + var _this = this; + var gd = _this.gd; + var layers = _this.layers; + var zoomlayer = fullLayout._zoomlayer; + var MINZOOM = constants.MINZOOM; + var OFFEDGE = constants.OFFEDGE; + var radius = _this.radius; + var innerRadius = _this.innerRadius; + var cx = _this.cx; + var cy = _this.cy; + var cxx = _this.cxx; + var cyy = _this.cyy; + var sectorInRad = _this.sectorInRad; + var vangles = _this.vangles; + var radialAxis = _this.radialAxis; + var clampTiny = helpers.clampTiny; + var findXYatLength = helpers.findXYatLength; + var findEnclosingVertexAngles = helpers.findEnclosingVertexAngles; + var chw = constants.cornerHalfWidth; + var chl = constants.cornerLen / 2; + + var mainDrag = dragBox.makeDragger(layers, 'path', 'maindrag', 'crosshair'); + + d3.select(mainDrag) + .attr('d', _this.pathSubplot()) + .attr('transform', strTranslate(cx, cy)); + + var dragOpts = { + element: mainDrag, + gd: gd, + subplot: _this.id, + plotinfo: { + id: _this.id, + xaxis: _this.xaxis, + yaxis: _this.yaxis + }, + xaxes: [_this.xaxis], + yaxes: [_this.yaxis] + }; + + // mouse px position at drag start (0), move (1) + var x0, y0; + // radial distance from circle center at drag start (0), move (1) + var r0, r1; + // zoombox persistent quantities + var path0, dimmed, lum; + // zoombox, corners elements + var zb, corners; + + function norm(x, y) { + return Math.sqrt(x * x + y * y); + } + + function xy2r(x, y) { + return norm(x - cxx, y - cyy); + } + + function xy2a(x, y) { + return Math.atan2(cyy - y, x - cxx); + } + + function ra2xy(r, a) { + return [r * Math.cos(a), r * Math.sin(-a)]; + } + + function pathCorner(r, a) { + if(r === 0) return _this.pathSector(2 * chw); + + var da = chl / r; + var am = a - da; + var ap = a + da; + var rb = Math.max(0, Math.min(r, radius)); + var rm = rb - chw; + var rp = rb + chw; + + return 'M' + ra2xy(rm, am) + + 'A' + [rm, rm] + ' 0,0,0 ' + ra2xy(rm, ap) + + 'L' + ra2xy(rp, ap) + + 'A' + [rp, rp] + ' 0,0,1 ' + ra2xy(rp, am) + + 'Z'; + } + + // (x,y) is the pt at middle of the va0 <-> va1 edge + // + // ... we could eventually add another mode for cursor + // angles 'close to' enough to a particular vertex. + function pathCornerForPolygons(r, va0, va1) { + if(r === 0) return _this.pathSector(2 * chw); + + var xy0 = ra2xy(r, va0); + var xy1 = ra2xy(r, va1); + var x = clampTiny((xy0[0] + xy1[0]) / 2); + var y = clampTiny((xy0[1] + xy1[1]) / 2); + var innerPts, outerPts; + + if(x && y) { + var m = y / x; + var mperp = -1 / m; + var midPts = findXYatLength(chw, m, x, y); + innerPts = findXYatLength(chl, mperp, midPts[0][0], midPts[0][1]); + outerPts = findXYatLength(chl, mperp, midPts[1][0], midPts[1][1]); + } else { + var dx, dy; + if(y) { + // horizontal handles + dx = chl; + dy = chw; + } else { + // vertical handles + dx = chw; + dy = chl; + } + innerPts = [[x - dx, y - dy], [x + dx, y - dy]]; + outerPts = [[x - dx, y + dy], [x + dx, y + dy]]; + } + + return 'M' + innerPts.join('L') + + 'L' + outerPts.reverse().join('L') + 'Z'; + } + + function zoomPrep() { + r0 = null; + r1 = null; + path0 = _this.pathSubplot(); + dimmed = false; + + var polarLayoutNow = gd._fullLayout[_this.id]; + lum = tinycolor(polarLayoutNow.bgcolor).getLuminance(); + + zb = dragBox.makeZoombox(zoomlayer, lum, cx, cy, path0); + zb.attr('fill-rule', 'evenodd'); + corners = dragBox.makeCorners(zoomlayer, cx, cy); + clearSelect(zoomlayer); + } + + // N.B. this sets scoped 'r0' and 'r1' + // return true if 'valid' zoom distance, false otherwise + function clampAndSetR0R1(rr0, rr1) { + rr1 = Math.max(Math.min(rr1, radius), innerRadius); + + // starting or ending drag near center (outer edge), + // clamps radial distance at origin (at r=radius) + if(rr0 < OFFEDGE) rr0 = 0; + else if((radius - rr0) < OFFEDGE) rr0 = radius; + else if(rr1 < OFFEDGE) rr1 = 0; + else if((radius - rr1) < OFFEDGE) rr1 = radius; + + // make sure r0 < r1, + // to get correct fill pattern in path1 below + if(Math.abs(rr1 - rr0) > MINZOOM) { + if(rr0 < rr1) { + r0 = rr0; + r1 = rr1; + } else { + r0 = rr1; + r1 = rr0; + } + return true; + } else { + r0 = null; + r1 = null; + return false; + } + } + + function applyZoomMove(path1, cpath) { + path1 = path1 || path0; + cpath = cpath || 'M0,0Z'; + + zb.attr('d', path1); + corners.attr('d', cpath); + dragBox.transitionZoombox(zb, corners, dimmed, lum); + dimmed = true; + } + + function zoomMove(dx, dy) { + var x1 = x0 + dx; + var y1 = y0 + dy; + var rr0 = xy2r(x0, y0); + var rr1 = Math.min(xy2r(x1, y1), radius); + var a0 = xy2a(x0, y0); + var path1; + var cpath; + + if(clampAndSetR0R1(rr0, rr1)) { + path1 = path0 + _this.pathSector(r1); + if(r0) path1 += _this.pathSector(r0); + // keep 'starting' angle + cpath = pathCorner(r0, a0) + pathCorner(r1, a0); + } + applyZoomMove(path1, cpath); + } + + function findPolygonRadius(x, y, va0, va1) { + var xy = helpers.findIntersectionXY(va0, va1, va0, [x - cxx, cyy - y]); + return norm(xy[0], xy[1]); + } + + function zoomMoveForPolygons(dx, dy) { + var x1 = x0 + dx; + var y1 = y0 + dy; + var a0 = xy2a(x0, y0); + var a1 = xy2a(x1, y1); + var vangles0 = findEnclosingVertexAngles(a0, vangles); + var vangles1 = findEnclosingVertexAngles(a1, vangles); + var rr0 = findPolygonRadius(x0, y0, vangles0[0], vangles0[1]); + var rr1 = Math.min(findPolygonRadius(x1, y1, vangles1[0], vangles1[1]), radius); + var path1; + var cpath; + + if(clampAndSetR0R1(rr0, rr1)) { + path1 = path0 + _this.pathSector(r1); + if(r0) path1 += _this.pathSector(r0); + // keep 'starting' angle here too + cpath = [ + pathCornerForPolygons(r0, vangles0[0], vangles0[1]), + pathCornerForPolygons(r1, vangles0[0], vangles0[1]) + ].join(' '); + } + applyZoomMove(path1, cpath); + } + + function zoomDone() { + dragBox.removeZoombox(gd); + + if(r0 === null || r1 === null) return; + + dragBox.showDoubleClickNotifier(gd); + + var rl = radialAxis._rl; + var m = (rl[1] - rl[0]) / (1 - innerRadius / radius) / radius; + var newRng = [ + rl[0] + (r0 - innerRadius) * m, + rl[0] + (r1 - innerRadius) * m + ]; + Registry.call('relayout', gd, _this.id + '.radialaxis.range', newRng); + } + + function zoomClick(numClicks, evt) { + var clickMode = gd._fullLayout.clickmode; + + dragBox.removeZoombox(gd); + + // TODO double once vs twice logic (autorange vs fixed range) + if(numClicks === 2) { + var updateObj = {}; + for(var k in _this.viewInitial) { + updateObj[_this.id + '.' + k] = _this.viewInitial[k]; + } + + gd.emit('plotly_doubleclick', null); + Registry.call('relayout', gd, updateObj); + } + + if(clickMode.indexOf('select') > -1 && numClicks === 1) { + selectOnClick(evt, gd, [_this.xaxis], [_this.yaxis], _this.id, dragOpts); + } + + if(clickMode.indexOf('event') > -1) { + Fx.click(gd, evt, _this.id); + } + } + + dragOpts.prepFn = function(evt, startX, startY) { + var dragModeNow = gd._fullLayout.dragmode; + + var bbox = mainDrag.getBoundingClientRect(); + x0 = startX - bbox.left; + y0 = startY - bbox.top; + + // need to offset x/y as bbox center does not + // match origin for asymmetric polygons + if(vangles) { + var offset = helpers.findPolygonOffset(radius, sectorInRad[0], sectorInRad[1], vangles); + x0 += cxx + offset[0]; + y0 += cyy + offset[1]; + } + + switch(dragModeNow) { + case 'zoom': + if(vangles) { + dragOpts.moveFn = zoomMoveForPolygons; + } else { + dragOpts.moveFn = zoomMove; + } + dragOpts.clickFn = zoomClick; + dragOpts.doneFn = zoomDone; + zoomPrep(evt, startX, startY); + break; + case 'select': + case 'lasso': + prepSelect(evt, startX, startY, dragOpts, dragModeNow); + break; + } + }; + + mainDrag.onmousemove = function(evt) { + Fx.hover(gd, evt, _this.id); + gd._fullLayout._lasthover = mainDrag; + gd._fullLayout._hoversubplot = _this.id; + }; + + mainDrag.onmouseout = function(evt) { + if(gd._dragging) return; + dragElement.unhover(gd, evt); + }; + + dragElement.init(dragOpts); +}; + +proto.updateRadialDrag = function(fullLayout, polarLayout, rngIndex) { + var _this = this; + var gd = _this.gd; + var layers = _this.layers; + var radius = _this.radius; + var innerRadius = _this.innerRadius; + var cx = _this.cx; + var cy = _this.cy; + var radialAxis = _this.radialAxis; + var bl = constants.radialDragBoxSize; + var bl2 = bl / 2; + + if(!radialAxis.visible) return; + + var angle0 = deg2rad(_this.radialAxisAngle); + var rl = radialAxis._rl; + var rl0 = rl[0]; + var rl1 = rl[1]; + var rbase = rl[rngIndex]; + var m = 0.75 * (rl[1] - rl[0]) / (1 - polarLayout.hole) / radius; + + var tx, ty, className; + if(rngIndex) { + tx = cx + (radius + bl2) * Math.cos(angle0); + ty = cy - (radius + bl2) * Math.sin(angle0); + className = 'radialdrag'; + } else { + // the 'inner' box can get called: + // - when polar.hole>0 + // - when polar.sector isn't a full circle + // otherwise it is hidden behind the main drag. + tx = cx + (innerRadius - bl2) * Math.cos(angle0); + ty = cy - (innerRadius - bl2) * Math.sin(angle0); + className = 'radialdrag-inner'; + } + + var radialDrag = dragBox.makeRectDragger(layers, className, 'crosshair', -bl2, -bl2, bl, bl); + var dragOpts = {element: radialDrag, gd: gd}; + + updateElement(d3.select(radialDrag), radialAxis.visible && innerRadius < radius, { + transform: strTranslate(tx, ty) + }); + + // move function (either rotate or re-range flavor) + var moveFn2; + // rotate angle on done + var angle1; + // re-range range[1] (or range[0]) on done + var rprime; + + function moveFn(dx, dy) { + if(moveFn2) { + moveFn2(dx, dy); + } else { + var dvec = [dx, -dy]; + var rvec = [Math.cos(angle0), Math.sin(angle0)]; + var comp = Math.abs(Lib.dot(dvec, rvec) / Math.sqrt(Lib.dot(dvec, dvec))); + + // mostly perpendicular motions rotate, + // mostly parallel motions re-range + if(!isNaN(comp)) { + moveFn2 = comp < 0.5 ? rotateMove : rerangeMove; + } + } + } + + function doneFn() { + if(angle1 !== null) { + Registry.call('relayout', gd, _this.id + '.radialaxis.angle', angle1); + } else if(rprime !== null) { + Registry.call('relayout', gd, _this.id + '.radialaxis.range[' + rngIndex + ']', rprime); + } + } + + function rotateMove(dx, dy) { + // disable for inner drag boxes + if(rngIndex === 0) return; + + var x1 = tx + dx; + var y1 = ty + dy; + + angle1 = Math.atan2(cy - y1, x1 - cx); + if(_this.vangles) angle1 = snapToVertexAngle(angle1, _this.vangles); + angle1 = rad2deg(angle1); + + var transform = strTranslate(cx, cy) + strRotate(-angle1); + layers['radial-axis'].attr('transform', transform); + layers['radial-line'].select('line').attr('transform', transform); + + var fullLayoutNow = _this.gd._fullLayout; + var polarLayoutNow = fullLayoutNow[_this.id]; + _this.updateRadialAxisTitle(fullLayoutNow, polarLayoutNow, angle1); + } + + function rerangeMove(dx, dy) { + // project (dx, dy) unto unit radial axis vector + var dr = Lib.dot([dx, -dy], [Math.cos(angle0), Math.sin(angle0)]); + rprime = rbase - m * dr; + + // make sure rprime does not change the range[0] -> range[1] sign + if((m > 0) !== (rngIndex ? rprime > rl0 : rprime < rl1)) { + rprime = null; + return; + } + + // update radial range -> update c2g -> update _m,_b + radialAxis.range[rngIndex] = rprime; + radialAxis._rl[rngIndex] = rprime; + radialAxis.setGeometry(); + radialAxis.setScale(); + + _this.xaxis.setRange(); + _this.xaxis.setScale(); + _this.yaxis.setRange(); + _this.yaxis.setScale(); + + doTicksSingle(gd, radialAxis, true); + layers['radial-grid'] + .attr('transform', strTranslate(cx, cy)) + .selectAll('path').attr('transform', null); + + var hasRegl = false; + + for(var traceType in _this.traceHash) { + var moduleCalcData = _this.traceHash[traceType]; + var moduleCalcDataVisible = Lib.filterVisible(moduleCalcData); + var _module = moduleCalcData[0][0].trace._module; + var polarLayoutNow = gd._fullLayout[_this.id]; + _module.plot(gd, _this, moduleCalcDataVisible, polarLayoutNow); + if(Registry.traceIs(traceType, 'gl') && moduleCalcDataVisible.length) hasRegl = true; + } + + if(hasRegl) { + clearGlCanvases(gd); + redrawReglTraces(gd); + } + } + + dragOpts.prepFn = function() { + moveFn2 = null; + angle1 = null; + rprime = null; + + dragOpts.moveFn = moveFn; + dragOpts.doneFn = doneFn; + + clearSelect(fullLayout._zoomlayer); + }; + + dragOpts.clampFn = function(dx, dy) { + if(Math.sqrt(dx * dx + dy * dy) < constants.MINDRAG) { + dx = 0; + dy = 0; + } + return [dx, dy]; + }; + + dragElement.init(dragOpts); +}; + +proto.updateAngularDrag = function(fullLayout) { + var _this = this; + var gd = _this.gd; + var layers = _this.layers; + var radius = _this.radius; + var angularAxis = _this.angularAxis; + var cx = _this.cx; + var cy = _this.cy; + var cxx = _this.cxx; + var cyy = _this.cyy; + var dbs = constants.angularDragBoxSize; + + var angularDrag = dragBox.makeDragger(layers, 'path', 'angulardrag', 'move'); + var dragOpts = {element: angularDrag, gd: gd}; + + d3.select(angularDrag) + .attr('d', _this.pathAnnulus(radius, radius + dbs)) + .attr('transform', strTranslate(cx, cy)) + .call(setCursor, 'move'); + + function xy2a(x, y) { + return Math.atan2(cyy + dbs - y, x - cxx - dbs); + } + + // scatter trace, points and textpoints selections + var scatterTraces = layers.frontplot.select('.scatterlayer').selectAll('.trace'); + var scatterPoints = scatterTraces.selectAll('.point'); + var scatterTextPoints = scatterTraces.selectAll('.textpoint'); + + // mouse px position at drag start (0), move (1) + var x0, y0; + // angular axis angle rotation at drag start (0), move (1) + var rot0, rot1; + // induced radial axis rotation (only used on polygon grids) + var rrot1; + // angle about circle center at drag start + var a0; + + function moveFn(dx, dy) { + var fullLayoutNow = _this.gd._fullLayout; + var polarLayoutNow = fullLayoutNow[_this.id]; + var x1 = x0 + dx; + var y1 = y0 + dy; + var a1 = xy2a(x1, y1); + var da = rad2deg(a1 - a0); + rot1 = rot0 + da; + + layers.frontplot.attr('transform', + strTranslate(_this.xOffset2, _this.yOffset2) + strRotate([-da, cxx, cyy]) + ); + + if(_this.vangles) { + rrot1 = _this.radialAxisAngle + da; + + var trans = strTranslate(cx, cy) + strRotate(-da); + var trans2 = strTranslate(cx, cy) + strRotate(-rrot1); + + layers.bg.attr('transform', trans); + layers['radial-grid'].attr('transform', trans); + layers['angular-line'].select('path').attr('transform', trans); + layers['radial-axis'].attr('transform', trans2); + layers['radial-line'].select('line').attr('transform', trans2); + _this.updateRadialAxisTitle(fullLayoutNow, polarLayoutNow, rrot1); + } else { + _this.clipPaths.forTraces.select('path').attr('transform', + strTranslate(cxx, cyy) + strRotate(da) + ); + } + + // 'un-rotate' marker and text points + scatterPoints.each(function() { + var sel = d3.select(this); + var xy = Drawing.getTranslate(sel); + sel.attr('transform', strTranslate(xy.x, xy.y) + strRotate([da])); + }); + scatterTextPoints.each(function() { + var sel = d3.select(this); + var tx = sel.select('text'); + var xy = Drawing.getTranslate(sel); + // N.B rotate -> translate ordering matters + sel.attr('transform', strRotate([da, tx.attr('x'), tx.attr('y')]) + strTranslate(xy.x, xy.y)); + }); + + // update rotation -> range -> _m,_b + angularAxis.rotation = Lib.modHalf(rot1, 360); + angularAxis.setGeometry(); + angularAxis.setScale(); + + doTicksSingle(gd, angularAxis, true); + + if(_this._hasClipOnAxisFalse && !Lib.isFullCircle(_this.sectorInRad)) { + scatterTraces.call(Drawing.hideOutsideRangePoints, _this); + } + + var hasRegl = false; + + for(var traceType in _this.traceHash) { + if(Registry.traceIs(traceType, 'gl')) { + var moduleCalcData = _this.traceHash[traceType]; + var moduleCalcDataVisible = Lib.filterVisible(moduleCalcData); + var _module = moduleCalcData[0][0].trace._module; + _module.plot(gd, _this, moduleCalcDataVisible, polarLayoutNow); + if(moduleCalcDataVisible.length) hasRegl = true; + } + } + + if(hasRegl) { + clearGlCanvases(gd); + redrawReglTraces(gd); + } + } + + function doneFn() { + scatterTextPoints.select('text').attr('transform', null); + + var updateObj = {}; + updateObj[_this.id + '.angularaxis.rotation'] = rot1; + + if(_this.vangles) { + updateObj[_this.id + '.radialaxis.angle'] = rrot1; + } + + Registry.call('relayout', gd, updateObj); + } + + dragOpts.prepFn = function(evt, startX, startY) { + var polarLayoutNow = fullLayout[_this.id]; + rot0 = polarLayoutNow.angularaxis.rotation; + + var bbox = angularDrag.getBoundingClientRect(); + x0 = startX - bbox.left; + y0 = startY - bbox.top; + a0 = xy2a(x0, y0); + + dragOpts.moveFn = moveFn; + dragOpts.doneFn = doneFn; + + clearSelect(fullLayout._zoomlayer); + }; + + // I don't what we should do in this case, skip we now + if(_this.vangles && !Lib.isFullCircle(_this.sectorInRad)) { + dragOpts.prepFn = Lib.noop; + setCursor(d3.select(angularDrag), null); + } + + dragElement.init(dragOpts); +}; + +proto.isPtInside = function(d) { + var sectorInRad = this.sectorInRad; + var vangles = this.vangles; + var thetag = this.angularAxis.c2g(d.theta); + var radialAxis = this.radialAxis; + var r = radialAxis.c2l(d.r); + var rl = radialAxis._rl; + + var fn = vangles ? helpers.isPtInsidePolygon : Lib.isPtInsideSector; + return fn(r, thetag, rl, sectorInRad, vangles); +}; + +proto.pathArc = function(r) { + var sectorInRad = this.sectorInRad; + var vangles = this.vangles; + var fn = vangles ? helpers.pathPolygon : Lib.pathArc; + return fn(r, sectorInRad[0], sectorInRad[1], vangles); +}; + +proto.pathSector = function(r) { + var sectorInRad = this.sectorInRad; + var vangles = this.vangles; + var fn = vangles ? helpers.pathPolygon : Lib.pathSector; + return fn(r, sectorInRad[0], sectorInRad[1], vangles); +}; + +proto.pathAnnulus = function(r0, r1) { + var sectorInRad = this.sectorInRad; + var vangles = this.vangles; + var fn = vangles ? helpers.pathPolygonAnnulus : Lib.pathAnnulus; + return fn(r0, r1, sectorInRad[0], sectorInRad[1], vangles); +}; + +proto.pathSubplot = function() { + var r0 = this.innerRadius; + var r1 = this.radius; + return r0 ? this.pathAnnulus(r0, r1) : this.pathSector(r1); +}; + +proto.fillViewInitialKey = function(key, val) { + if(!(key in this.viewInitial)) { + this.viewInitial[key] = val; + } +}; + +function strTickLayout(axLayout) { + var out = axLayout.ticks + String(axLayout.ticklen) + String(axLayout.showticklabels); + if('side' in axLayout) out += axLayout.side; + return out; +} + +// Finds the bounding box of a given circle sector, +// inspired by https://math.stackexchange.com/q/1852703 +// +// assumes: +// - sector[0] < sector[1] +// - counterclockwise rotation +function computeSectorBBox(sector) { + var s0 = sector[0]; + var s1 = sector[1]; + var arc = s1 - s0; + var a0 = mod(s0, 360); + var a1 = a0 + arc; + + var ax0 = Math.cos(deg2rad(a0)); + var ay0 = Math.sin(deg2rad(a0)); + var ax1 = Math.cos(deg2rad(a1)); + var ay1 = Math.sin(deg2rad(a1)); + + var x0, y0, x1, y1; + + if((a0 <= 90 && a1 >= 90) || (a0 > 90 && a1 >= 450)) { + y1 = 1; + } else if(ay0 <= 0 && ay1 <= 0) { + y1 = 0; + } else { + y1 = Math.max(ay0, ay1); + } + + if((a0 <= 180 && a1 >= 180) || (a0 > 180 && a1 >= 540)) { + x0 = -1; + } else if(ax0 >= 0 && ax1 >= 0) { + x0 = 0; + } else { + x0 = Math.min(ax0, ax1); + } + + if((a0 <= 270 && a1 >= 270) || (a0 > 270 && a1 >= 630)) { + y0 = -1; + } else if(ay0 >= 0 && ay1 >= 0) { + y0 = 0; + } else { + y0 = Math.min(ay0, ay1); + } + + if(a1 >= 360) { + x1 = 1; + } else if(ax0 <= 0 && ax1 <= 0) { + x1 = 0; + } else { + x1 = Math.max(ax0, ax1); + } + + return [x0, y0, x1, y1]; +} + +function snapToVertexAngle(a, vangles) { + var fn = function(v) { return Lib.angleDist(a, v); }; + var ind = Lib.findIndexOfMin(vangles, fn); + return vangles[ind]; +} + +function updateElement(sel, showAttr, attrs) { + if(showAttr) { + sel.attr('display', null); + sel.attr(attrs); + } else if(sel) { + sel.attr('display', 'none'); + } + return sel; +} + +function strTranslate(x, y) { + return 'translate(' + x + ',' + y + ')'; +} + +function strRotate(angle) { + return 'rotate(' + angle + ')'; +} + +// because Math.sign(Math.cos(Math.PI / 2)) === 1 +// oh javascript ;) +function sign(v) { + return Math.abs(v) < 1e-10 ? 0 : + v > 0 ? 1 : -1; +} + +function signCos(v) { + return sign(Math.cos(v)); +} + +function signSin(v) { + return sign(Math.sin(v)); +} + +},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../components/titles":661,"../../constants/alignment":668,"../../lib":696,"../../lib/clear_gl_canvases":680,"../../lib/setcursor":716,"../../plot_api/subroutines":735,"../../registry":827,"../cartesian/autorange":743,"../cartesian/axes":744,"../cartesian/dragbox":753,"../cartesian/select":762,"../cartesian/set_convert":763,"../plots":808,"./constants":809,"./helpers":810,"./set_convert":821,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"tinycolor2":514}],821:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var setConvertCartesian = _dereq_('../cartesian/set_convert'); + +var deg2rad = Lib.deg2rad; +var rad2deg = Lib.rad2deg; + +/** + * setConvert for polar axes! + * + * @param {object} ax + * axis in question (works for both radial and angular axes) + * @param {object} polarLayout + * full polar layout of the subplot associated with 'ax' + * @param {object} fullLayout + * full layout + * + * Here, reuse some of the Cartesian setConvert logic, + * but we must extend some of it, as both radial and angular axes + * don't have domains and angular axes don't have _true_ ranges. + * + * Moreover, we introduce two new coordinate systems: + * - 'g' for geometric coordinates and + * - 't' for angular ticks + * + * Radial axis coordinate systems: + * - d, c and l: same as for cartesian axes + * - g: like calcdata but translated about `radialaxis.range[0]` & `polar.hole` + * + * Angular axis coordinate systems: + * - d: data, in whatever form it's provided + * - c: calcdata, turned into radians (for linear axes) + * or category indices (category axes) + * - t: tick calcdata, just like 'c' but in degrees for linear axes + * - g: geometric calcdata, radians coordinates that take into account + * axis rotation and direction + * + * Then, 'g'eometric data is ready to be converted to (x,y). + */ +module.exports = function setConvert(ax, polarLayout, fullLayout) { + setConvertCartesian(ax, fullLayout); + + switch(ax._id) { + case 'x': + case 'radialaxis': + setConvertRadial(ax, polarLayout); + break; + case 'angularaxis': + setConvertAngular(ax, polarLayout); + break; + } +}; + +function setConvertRadial(ax, polarLayout) { + var subplot = polarLayout._subplot; + + ax.setGeometry = function() { + var rl0 = ax._rl[0]; + var rl1 = ax._rl[1]; + + var b = subplot.innerRadius; + var m = (subplot.radius - b) / (rl1 - rl0); + var b2 = b / m; + + var rFilter = rl0 > rl1 ? + function(v) { return v <= 0; } : + function(v) { return v >= 0; }; + + ax.c2g = function(v) { + var r = ax.c2l(v) - rl0; + return (rFilter(r) ? r : 0) + b2; + }; + + ax.g2c = function(v) { + return ax.l2c(v + rl0 - b2); + }; + + ax.g2p = function(v) { return v * m; }; + ax.c2p = function(v) { return ax.g2p(ax.c2g(v)); }; + }; +} + +function toRadians(v, unit) { + return unit === 'degrees' ? deg2rad(v) : v; +} + +function fromRadians(v, unit) { + return unit === 'degrees' ? rad2deg(v) : v; +} + +function setConvertAngular(ax, polarLayout) { + var axType = ax.type; + + if(axType === 'linear') { + var _d2c = ax.d2c; + var _c2d = ax.c2d; + + ax.d2c = function(v, unit) { return toRadians(_d2c(v), unit); }; + ax.c2d = function(v, unit) { return _c2d(fromRadians(v, unit)); }; + } + + // override makeCalcdata to handle thetaunit and special theta0/dtheta logic + ax.makeCalcdata = function(trace, coord) { + var arrayIn = trace[coord]; + var len = trace._length; + var arrayOut, i; + + var _d2c = function(v) { return ax.d2c(v, trace.thetaunit); }; + + if(arrayIn) { + if(Lib.isTypedArray(arrayIn) && axType === 'linear') { + if(len === arrayIn.length) { + return arrayIn; + } else if(arrayIn.subarray) { + return arrayIn.subarray(0, len); + } + } + + arrayOut = new Array(len); + for(i = 0; i < len; i++) { + arrayOut[i] = _d2c(arrayIn[i]); + } + } else { + var coord0 = coord + '0'; + var dcoord = 'd' + coord; + var v0 = (coord0 in trace) ? _d2c(trace[coord0]) : 0; + var dv = (trace[dcoord]) ? _d2c(trace[dcoord]) : (ax.period || 2 * Math.PI) / len; + + arrayOut = new Array(len); + for(i = 0; i < len; i++) { + arrayOut[i] = v0 + i * dv; + } + } + + return arrayOut; + }; + + // N.B. we mock the axis 'range' here + ax.setGeometry = function() { + var sector = polarLayout.sector; + var sectorInRad = sector.map(deg2rad); + var dir = {clockwise: -1, counterclockwise: 1}[ax.direction]; + var rot = deg2rad(ax.rotation); + + var rad2g = function(v) { return dir * v + rot; }; + var g2rad = function(v) { return (v - rot) / dir; }; + + var rad2c, c2rad; + var rad2t, t2rad; + + switch(axType) { + case 'linear': + c2rad = rad2c = Lib.identity; + t2rad = deg2rad; + rad2t = rad2deg; + + // Set the angular range in degrees to make auto-tick computation cleaner, + // changing rotation/direction should not affect the angular tick value. + ax.range = Lib.isFullCircle(sectorInRad) ? + [sector[0], sector[0] + 360] : + sectorInRad.map(g2rad).map(rad2deg); + break; + + case 'category': + var catLen = ax._categories.length; + var _period = ax.period ? Math.max(ax.period, catLen) : catLen; + + c2rad = t2rad = function(v) { return v * 2 * Math.PI / _period; }; + rad2c = rad2t = function(v) { return v * _period / Math.PI / 2; }; + + ax.range = [0, _period]; + break; + } + + ax.c2g = function(v) { return rad2g(c2rad(v)); }; + ax.g2c = function(v) { return rad2c(g2rad(v)); }; + + ax.t2g = function(v) { return rad2g(t2rad(v)); }; + ax.g2t = function(v) { return rad2t(g2rad(v)); }; + }; +} + +},{"../../lib":696,"../cartesian/set_convert":763}],822:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../lib'); +var Template = _dereq_('../plot_api/plot_template'); +var handleDomainDefaults = _dereq_('./domain').defaults; + + +/** + * Find and supply defaults to all subplots of a given type + * This handles subplots that are contained within one container - so + * gl3d, geo, ternary... but not 2d axes which have separate x and y axes + * finds subplots, coerces their `domain` attributes, then calls the + * given handleDefaults function to fill in everything else. + * + * layoutIn: the complete user-supplied input layout + * layoutOut: the complete finished layout + * fullData: the finished data array, used only to find subplots + * opts: { + * type: subplot type string + * attributes: subplot attributes object + * partition: 'x' or 'y', which direction to divide domain space by default + * (default 'x', ie side-by-side subplots) + * TODO: this option is only here because 3D and geo made opposite + * choices in this regard previously and I didn't want to change it. + * Instead we should do: + * - something consistent + * - something more square (4 cuts 2x2, 5/6 cuts 2x3, etc.) + * - something that includes all subplot types in one arrangement, + * now that we can have them together! + * handleDefaults: function of (subplotLayoutIn, subplotLayoutOut, coerce, opts) + * this opts object is passed through to handleDefaults, so attach any + * additional items needed by this function here as well + * } + */ +module.exports = function handleSubplotDefaults(layoutIn, layoutOut, fullData, opts) { + var subplotType = opts.type; + var subplotAttributes = opts.attributes; + var handleDefaults = opts.handleDefaults; + var partition = opts.partition || 'x'; + + var ids = layoutOut._subplots[subplotType]; + var idsLength = ids.length; + + var baseId = idsLength && ids[0].replace(/\d+$/, ''); + + var subplotLayoutIn, subplotLayoutOut; + + function coerce(attr, dflt) { + return Lib.coerce(subplotLayoutIn, subplotLayoutOut, subplotAttributes, attr, dflt); + } + + for(var i = 0; i < idsLength; i++) { + var id = ids[i]; + + // ternary traces get a layout ternary for free! + if(layoutIn[id]) subplotLayoutIn = layoutIn[id]; + else subplotLayoutIn = layoutIn[id] = {}; + + subplotLayoutOut = Template.newContainer(layoutOut, id, baseId); + + var dfltDomains = {}; + dfltDomains[partition] = [i / idsLength, (i + 1) / idsLength]; + handleDomainDefaults(subplotLayoutOut, layoutOut, coerce, dfltDomains); + + opts.id = id; + handleDefaults(subplotLayoutIn, subplotLayoutOut, coerce, opts); + } +}; + +},{"../lib":696,"../plot_api/plot_template":734,"./domain":770}],823:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Ternary = _dereq_('./ternary'); + +var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; +var counterRegex = _dereq_('../../lib').counterRegex; +var TERNARY = 'ternary'; + +exports.name = TERNARY; + +var attr = exports.attr = 'subplot'; + +exports.idRoot = TERNARY; + +exports.idRegex = exports.attrRegex = counterRegex(TERNARY); + +var attributes = exports.attributes = {}; +attributes[attr] = { + valType: 'subplotid', + + dflt: 'ternary', + editType: 'calc', + +}; + +exports.layoutAttributes = _dereq_('./layout_attributes'); + +exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); + +exports.plot = function plotTernary(gd) { + var fullLayout = gd._fullLayout; + var calcData = gd.calcdata; + var ternaryIds = fullLayout._subplots[TERNARY]; + + for(var i = 0; i < ternaryIds.length; i++) { + var ternaryId = ternaryIds[i], + ternaryCalcData = getSubplotCalcData(calcData, TERNARY, ternaryId), + ternary = fullLayout[ternaryId]._subplot; + + // If ternary is not instantiated, create one! + if(!ternary) { + ternary = new Ternary({ + id: ternaryId, + graphDiv: gd, + container: fullLayout._ternarylayer.node() + }, + fullLayout + ); + + fullLayout[ternaryId]._subplot = ternary; + } + + ternary.plot(ternaryCalcData, fullLayout, gd._promises); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldTernaryKeys = oldFullLayout._subplots[TERNARY] || []; + + for(var i = 0; i < oldTernaryKeys.length; i++) { + var oldTernaryKey = oldTernaryKeys[i]; + var oldTernary = oldFullLayout[oldTernaryKey]._subplot; + + if(!newFullLayout[oldTernaryKey] && !!oldTernary) { + oldTernary.plotContainer.remove(); + oldTernary.clipDef.remove(); + oldTernary.clipDefRelative.remove(); + oldTernary.layers['a-title'].remove(); + oldTernary.layers['b-title'].remove(); + oldTernary.layers['c-title'].remove(); + } + } +}; + +},{"../../lib":696,"../../plots/get_data":781,"./layout_attributes":824,"./layout_defaults":825,"./ternary":826}],824:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = _dereq_('../../components/color/attributes'); +var domainAttrs = _dereq_('../domain').attributes; +var axesAttrs = _dereq_('../cartesian/layout_attributes'); + +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var ternaryAxesAttrs = { + title: axesAttrs.title, + titlefont: axesAttrs.titlefont, + color: axesAttrs.color, + // ticks + tickmode: axesAttrs.tickmode, + nticks: extendFlat({}, axesAttrs.nticks, {dflt: 6, min: 1}), + tick0: axesAttrs.tick0, + dtick: axesAttrs.dtick, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + ticks: axesAttrs.ticks, + ticklen: axesAttrs.ticklen, + tickwidth: axesAttrs.tickwidth, + tickcolor: axesAttrs.tickcolor, + showticklabels: axesAttrs.showticklabels, + showtickprefix: axesAttrs.showtickprefix, + tickprefix: axesAttrs.tickprefix, + showticksuffix: axesAttrs.showticksuffix, + ticksuffix: axesAttrs.ticksuffix, + showexponent: axesAttrs.showexponent, + exponentformat: axesAttrs.exponentformat, + separatethousands: axesAttrs.separatethousands, + tickfont: axesAttrs.tickfont, + tickangle: axesAttrs.tickangle, + tickformat: axesAttrs.tickformat, + tickformatstops: axesAttrs.tickformatstops, + hoverformat: axesAttrs.hoverformat, + // lines and grids + showline: extendFlat({}, axesAttrs.showline, {dflt: true}), + linecolor: axesAttrs.linecolor, + linewidth: axesAttrs.linewidth, + showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}), + gridcolor: axesAttrs.gridcolor, + gridwidth: axesAttrs.gridwidth, + layer: axesAttrs.layer, + // range + min: { + valType: 'number', + dflt: 0, + + min: 0, + + } +}; + +module.exports = overrideAll({ + domain: domainAttrs({name: 'ternary'}), + + bgcolor: { + valType: 'color', + + dflt: colorAttrs.background, + + }, + sum: { + valType: 'number', + + dflt: 1, + min: 0, + + }, + aaxis: ternaryAxesAttrs, + baxis: ternaryAxesAttrs, + caxis: ternaryAxesAttrs +}, 'plot', 'from-root'); + +},{"../../components/color/attributes":569,"../../lib/extend":685,"../../plot_api/edit_types":727,"../cartesian/layout_attributes":757,"../domain":770}],825:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Color = _dereq_('../../components/color'); +var Template = _dereq_('../../plot_api/plot_template'); +var Lib = _dereq_('../../lib'); + +var handleSubplotDefaults = _dereq_('../subplot_defaults'); +var handleTickLabelDefaults = _dereq_('../cartesian/tick_label_defaults'); +var handleTickMarkDefaults = _dereq_('../cartesian/tick_mark_defaults'); +var handleTickValueDefaults = _dereq_('../cartesian/tick_value_defaults'); +var handleLineGridDefaults = _dereq_('../cartesian/line_grid_defaults'); +var layoutAttributes = _dereq_('./layout_attributes'); + +var axesNames = ['aaxis', 'baxis', 'caxis']; + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'ternary', + attributes: layoutAttributes, + handleDefaults: handleTernaryDefaults, + font: layoutOut.font, + paper_bgcolor: layoutOut.paper_bgcolor + }); +}; + +function handleTernaryDefaults(ternaryLayoutIn, ternaryLayoutOut, coerce, options) { + var bgColor = coerce('bgcolor'); + var sum = coerce('sum'); + options.bgColor = Color.combine(bgColor, options.paper_bgcolor); + var axName, containerIn, containerOut; + + // TODO: allow most (if not all) axis attributes to be set + // in the outer container and used as defaults in the individual axes? + + for(var j = 0; j < axesNames.length; j++) { + axName = axesNames[j]; + containerIn = ternaryLayoutIn[axName] || {}; + containerOut = Template.newContainer(ternaryLayoutOut, axName); + containerOut._name = axName; + + handleAxisDefaults(containerIn, containerOut, options); + } + + // if the min values contradict each other, set them all to default (0) + // and delete *all* the inputs so the user doesn't get confused later by + // changing one and having them all change. + var aaxis = ternaryLayoutOut.aaxis, + baxis = ternaryLayoutOut.baxis, + caxis = ternaryLayoutOut.caxis; + if(aaxis.min + baxis.min + caxis.min >= sum) { + aaxis.min = 0; + baxis.min = 0; + caxis.min = 0; + if(ternaryLayoutIn.aaxis) delete ternaryLayoutIn.aaxis.min; + if(ternaryLayoutIn.baxis) delete ternaryLayoutIn.baxis.min; + if(ternaryLayoutIn.caxis) delete ternaryLayoutIn.caxis.min; + } +} + +function handleAxisDefaults(containerIn, containerOut, options) { + var axAttrs = layoutAttributes[containerOut._name]; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, axAttrs, attr, dflt); + } + + containerOut.type = 'linear'; // no other types allowed for ternary + + var dfltColor = coerce('color'); + // if axis.color was provided, use it for fonts too; otherwise, + // inherit from global font color in case that was provided. + var dfltFontColor = (dfltColor !== axAttrs.color.dflt) ? dfltColor : options.font.color; + + var axName = containerOut._name, + letterUpper = axName.charAt(0).toUpperCase(), + dfltTitle = 'Component ' + letterUpper; + + var title = coerce('title', dfltTitle); + containerOut._hovertitle = title === dfltTitle ? title : letterUpper; + + Lib.coerceFont(coerce, 'titlefont', { + family: options.font.family, + size: Math.round(options.font.size * 1.2), + color: dfltFontColor + }); + + // range is just set by 'min' - max is determined by the other axes mins + coerce('min'); + + handleTickValueDefaults(containerIn, containerOut, coerce, 'linear'); + handleTickLabelDefaults(containerIn, containerOut, coerce, 'linear', {}); + handleTickMarkDefaults(containerIn, containerOut, coerce, + { outerTicks: true }); + + var showTickLabels = coerce('showticklabels'); + if(showTickLabels) { + Lib.coerceFont(coerce, 'tickfont', { + family: options.font.family, + size: options.font.size, + color: dfltFontColor + }); + coerce('tickangle'); + coerce('tickformat'); + } + + handleLineGridDefaults(containerIn, containerOut, coerce, { + dfltColor: dfltColor, + bgColor: options.bgColor, + // default grid color is darker here (60%, vs cartesian default ~91%) + // because the grid is not square so the eye needs heavier cues to follow + blend: 60, + showLine: true, + showGrid: true, + noZeroLine: true, + attributes: axAttrs + }); + + coerce('hoverformat'); + coerce('layer'); +} + +},{"../../components/color":570,"../../lib":696,"../../plot_api/plot_template":734,"../cartesian/line_grid_defaults":759,"../cartesian/tick_label_defaults":764,"../cartesian/tick_mark_defaults":765,"../cartesian/tick_value_defaults":766,"../subplot_defaults":822,"./layout_attributes":824}],826:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var _ = Lib._; +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var setConvert = _dereq_('../cartesian/set_convert'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var Plots = _dereq_('../plots'); +var Axes = _dereq_('../cartesian/axes'); +var dragElement = _dereq_('../../components/dragelement'); +var Fx = _dereq_('../../components/fx'); +var Titles = _dereq_('../../components/titles'); +var prepSelect = _dereq_('../cartesian/select').prepSelect; +var selectOnClick = _dereq_('../cartesian/select').selectOnClick; +var clearSelect = _dereq_('../cartesian/select').clearSelect; +var constants = _dereq_('../cartesian/constants'); + +function Ternary(options, fullLayout) { + this.id = options.id; + this.graphDiv = options.graphDiv; + this.init(fullLayout); + this.makeFramework(fullLayout); + + // unfortunately, we have to keep track of some axis tick settings + // as ternary subplots do not implement the 'ticks' editType + this.aTickLayout = null; + this.bTickLayout = null; + this.cTickLayout = null; +} + +module.exports = Ternary; + +var proto = Ternary.prototype; + +proto.init = function(fullLayout) { + this.container = fullLayout._ternarylayer; + this.defs = fullLayout._defs; + this.layoutId = fullLayout._uid; + this.traceHash = {}; + this.layers = {}; +}; + +proto.plot = function(ternaryCalcData, fullLayout) { + var _this = this; + var ternaryLayout = fullLayout[_this.id]; + var graphSize = fullLayout._size; + + _this._hasClipOnAxisFalse = false; + for(var i = 0; i < ternaryCalcData.length; i++) { + var trace = ternaryCalcData[i][0].trace; + + if(trace.cliponaxis === false) { + _this._hasClipOnAxisFalse = true; + break; + } + } + + _this.updateLayers(ternaryLayout); + _this.adjustLayout(ternaryLayout, graphSize); + Plots.generalUpdatePerTraceModule(_this.graphDiv, _this, ternaryCalcData, ternaryLayout); + _this.layers.plotbg.select('path').call(Color.fill, ternaryLayout.bgcolor); +}; + +proto.makeFramework = function(fullLayout) { + var _this = this; + var ternaryLayout = fullLayout[_this.id]; + + var clipId = _this.clipId = 'clip' + _this.layoutId + _this.id; + var clipIdRelative = _this.clipIdRelative = 'clip-relative' + _this.layoutId + _this.id; + + // clippath for this ternary subplot + _this.clipDef = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipId, function(s) { + s.append('path').attr('d', 'M0,0Z'); + }); + + // 'relative' clippath (i.e. no translation) for this ternary subplot + _this.clipDefRelative = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipIdRelative, function(s) { + s.append('path').attr('d', 'M0,0Z'); + }); + + // container for everything in this ternary subplot + _this.plotContainer = Lib.ensureSingle(_this.container, 'g', _this.id); + _this.updateLayers(ternaryLayout); + + Drawing.setClipUrl(_this.layers.backplot, clipId); + Drawing.setClipUrl(_this.layers.grids, clipId); +}; + +proto.updateLayers = function(ternaryLayout) { + var _this = this; + var layers = _this.layers; + + // inside that container, we have one container for the data, and + // one each for the three axes around it. + + var plotLayers = ['draglayer', 'plotbg', 'backplot', 'grids']; + + if(ternaryLayout.aaxis.layer === 'below traces') { + plotLayers.push('aaxis', 'aline'); + } + if(ternaryLayout.baxis.layer === 'below traces') { + plotLayers.push('baxis', 'bline'); + } + if(ternaryLayout.caxis.layer === 'below traces') { + plotLayers.push('caxis', 'cline'); + } + + plotLayers.push('frontplot'); + + if(ternaryLayout.aaxis.layer === 'above traces') { + plotLayers.push('aaxis', 'aline'); + } + if(ternaryLayout.baxis.layer === 'above traces') { + plotLayers.push('baxis', 'bline'); + } + if(ternaryLayout.caxis.layer === 'above traces') { + plotLayers.push('caxis', 'cline'); + } + + var toplevel = _this.plotContainer.selectAll('g.toplevel') + .data(plotLayers, String); + + var grids = ['agrid', 'bgrid', 'cgrid']; + + toplevel.enter().append('g') + .attr('class', function(d) { return 'toplevel ' + d; }) + .each(function(d) { + var s = d3.select(this); + layers[d] = s; + + // containers for different trace types. + // NOTE - this is different from cartesian, where all traces + // are in front of grids. Here I'm putting maps behind the grids + // so the grids will always be visible if they're requested. + // Perhaps we want that for cartesian too? + if(d === 'frontplot') { + s.append('g').classed('scatterlayer', true); + } else if(d === 'backplot') { + s.append('g').classed('maplayer', true); + } else if(d === 'plotbg') { + s.append('path').attr('d', 'M0,0Z'); + } else if(d === 'aline' || d === 'bline' || d === 'cline') { + s.append('path'); + } else if(d === 'grids') { + grids.forEach(function(d) { + layers[d] = s.append('g').classed('grid ' + d, true); + + var fictID = (d === 'bgrid') ? 'x' : 'y'; + layers[d].append('g').classed(fictID, true); + }); + } + }); + + toplevel.order(); +}; + +var w_over_h = Math.sqrt(4 / 3); + +proto.adjustLayout = function(ternaryLayout, graphSize) { + var _this = this, + domain = ternaryLayout.domain, + xDomainCenter = (domain.x[0] + domain.x[1]) / 2, + yDomainCenter = (domain.y[0] + domain.y[1]) / 2, + xDomain = domain.x[1] - domain.x[0], + yDomain = domain.y[1] - domain.y[0], + wmax = xDomain * graphSize.w, + hmax = yDomain * graphSize.h, + sum = ternaryLayout.sum, + amin = ternaryLayout.aaxis.min, + bmin = ternaryLayout.baxis.min, + cmin = ternaryLayout.caxis.min; + + var x0, y0, w, h, xDomainFinal, yDomainFinal; + + if(wmax > w_over_h * hmax) { + h = hmax; + w = h * w_over_h; + } + else { + w = wmax; + h = w / w_over_h; + } + + xDomainFinal = xDomain * w / wmax; + yDomainFinal = yDomain * h / hmax; + + x0 = graphSize.l + graphSize.w * xDomainCenter - w / 2; + y0 = graphSize.t + graphSize.h * (1 - yDomainCenter) - h / 2; + + _this.x0 = x0; + _this.y0 = y0; + _this.w = w; + _this.h = h; + _this.sum = sum; + + // set up the x and y axis objects we'll use to lay out the points + _this.xaxis = { + type: 'linear', + range: [amin + 2 * cmin - sum, sum - amin - 2 * bmin], + domain: [ + xDomainCenter - xDomainFinal / 2, + xDomainCenter + xDomainFinal / 2 + ], + _id: 'x' + }; + setConvert(_this.xaxis, _this.graphDiv._fullLayout); + _this.xaxis.setScale(); + _this.xaxis.isPtWithinRange = function(d) { + return ( + d.a >= _this.aaxis.range[0] && + d.a <= _this.aaxis.range[1] && + d.b >= _this.baxis.range[1] && + d.b <= _this.baxis.range[0] && + d.c >= _this.caxis.range[1] && + d.c <= _this.caxis.range[0] + ); + }; + + _this.yaxis = { + type: 'linear', + range: [amin, sum - bmin - cmin], + domain: [ + yDomainCenter - yDomainFinal / 2, + yDomainCenter + yDomainFinal / 2 + ], + _id: 'y' + }; + setConvert(_this.yaxis, _this.graphDiv._fullLayout); + _this.yaxis.setScale(); + _this.yaxis.isPtWithinRange = function() { return true; }; + + // set up the modified axes for tick drawing + var yDomain0 = _this.yaxis.domain[0]; + + // aaxis goes up the left side. Set it up as a y axis, but with + // fictitious angles and domain, but then rotate and translate + // it into place at the end + var aaxis = _this.aaxis = extendFlat({}, ternaryLayout.aaxis, { + visible: true, + range: [amin, sum - bmin - cmin], + side: 'left', + _counterangle: 30, + // tickangle = 'auto' means 0 anyway for a y axis, need to coerce to 0 here + // so we can shift by 30. + tickangle: (+ternaryLayout.aaxis.tickangle || 0) - 30, + domain: [yDomain0, yDomain0 + yDomainFinal * w_over_h], + _axislayer: _this.layers.aaxis, + _gridlayer: _this.layers.agrid, + anchor: 'free', + position: 0, + _pos: 0, // _this.xaxis.domain[0] * graphSize.w, + _id: 'y', + _length: w, + _gridpath: 'M0,0l' + h + ',-' + (w / 2), + automargin: false // don't use automargins routine for labels + }); + setConvert(aaxis, _this.graphDiv._fullLayout); + aaxis.setScale(); + + // baxis goes across the bottom (backward). We can set it up as an x axis + // without any enclosing transformation. + var baxis = _this.baxis = extendFlat({}, ternaryLayout.baxis, { + visible: true, + range: [sum - amin - cmin, bmin], + side: 'bottom', + _counterangle: 30, + domain: _this.xaxis.domain, + _axislayer: _this.layers.baxis, + _gridlayer: _this.layers.bgrid, + _counteraxis: _this.aaxis, + anchor: 'free', + position: 0, + _pos: 0, // (1 - yDomain0) * graphSize.h, + _id: 'x', + _length: w, + _gridpath: 'M0,0l-' + (w / 2) + ',-' + h, + automargin: false // don't use automargins routine for labels + }); + setConvert(baxis, _this.graphDiv._fullLayout); + baxis.setScale(); + aaxis._counteraxis = baxis; + + // caxis goes down the right side. Set it up as a y axis, with + // post-transformation similar to aaxis + var caxis = _this.caxis = extendFlat({}, ternaryLayout.caxis, { + visible: true, + range: [sum - amin - bmin, cmin], + side: 'right', + _counterangle: 30, + tickangle: (+ternaryLayout.caxis.tickangle || 0) + 30, + domain: [yDomain0, yDomain0 + yDomainFinal * w_over_h], + _axislayer: _this.layers.caxis, + _gridlayer: _this.layers.cgrid, + _counteraxis: _this.baxis, + anchor: 'free', + position: 0, + _pos: 0, // _this.xaxis.domain[1] * graphSize.w, + _id: 'y', + _length: w, + _gridpath: 'M0,0l-' + h + ',' + (w / 2), + automargin: false // don't use automargins routine for labels + }); + setConvert(caxis, _this.graphDiv._fullLayout); + caxis.setScale(); + + var triangleClip = 'M' + x0 + ',' + (y0 + h) + 'h' + w + 'l-' + (w / 2) + ',-' + h + 'Z'; + _this.clipDef.select('path').attr('d', triangleClip); + _this.layers.plotbg.select('path').attr('d', triangleClip); + + var triangleClipRelative = 'M0,' + h + 'h' + w + 'l-' + (w / 2) + ',-' + h + 'Z'; + _this.clipDefRelative.select('path').attr('d', triangleClipRelative); + + var plotTransform = 'translate(' + x0 + ',' + y0 + ')'; + _this.plotContainer.selectAll('.scatterlayer,.maplayer') + .attr('transform', plotTransform); + + _this.clipDefRelative.select('path').attr('transform', null); + + // TODO: shift axes to accommodate linewidth*sin(30) tick mark angle + + // TODO: there's probably an easier way to handle these translations/offsets now... + var bTransform = 'translate(' + (x0 - baxis._offset) + ',' + (y0 + h) + ')'; + + _this.layers.baxis.attr('transform', bTransform); + _this.layers.bgrid.attr('transform', bTransform); + + var aTransform = 'translate(' + (x0 + w / 2) + ',' + y0 + + ')rotate(30)translate(0,' + -aaxis._offset + ')'; + _this.layers.aaxis.attr('transform', aTransform); + _this.layers.agrid.attr('transform', aTransform); + + var cTransform = 'translate(' + (x0 + w / 2) + ',' + y0 + + ')rotate(-30)translate(0,' + -caxis._offset + ')'; + _this.layers.caxis.attr('transform', cTransform); + _this.layers.cgrid.attr('transform', cTransform); + + _this.drawAxes(true); + + // remove crispEdges - all the off-square angles in ternary plots + // make these counterproductive. + _this.plotContainer.selectAll('.crisp').classed('crisp', false); + + _this.layers.aline.select('path') + .attr('d', aaxis.showline ? + 'M' + x0 + ',' + (y0 + h) + 'l' + (w / 2) + ',-' + h : 'M0,0') + .call(Color.stroke, aaxis.linecolor || '#000') + .style('stroke-width', (aaxis.linewidth || 0) + 'px'); + _this.layers.bline.select('path') + .attr('d', baxis.showline ? + 'M' + x0 + ',' + (y0 + h) + 'h' + w : 'M0,0') + .call(Color.stroke, baxis.linecolor || '#000') + .style('stroke-width', (baxis.linewidth || 0) + 'px'); + _this.layers.cline.select('path') + .attr('d', caxis.showline ? + 'M' + (x0 + w / 2) + ',' + y0 + 'l' + (w / 2) + ',' + h : 'M0,0') + .call(Color.stroke, caxis.linecolor || '#000') + .style('stroke-width', (caxis.linewidth || 0) + 'px'); + + if(!_this.graphDiv._context.staticPlot) { + _this.initInteractions(); + } + + Drawing.setClipUrl( + _this.layers.frontplot, + _this._hasClipOnAxisFalse ? null : _this.clipId + ); +}; + +proto.drawAxes = function(doTitles) { + var _this = this; + var gd = _this.graphDiv; + var titlesuffix = _this.id.substr(7) + 'title'; + var layers = _this.layers; + var aaxis = _this.aaxis; + var baxis = _this.baxis; + var caxis = _this.caxis; + var newTickLayout; + + newTickLayout = strTickLayout(aaxis); + if(_this.aTickLayout !== newTickLayout) { + layers.aaxis.selectAll('.ytick').remove(); + _this.aTickLayout = newTickLayout; + } + + newTickLayout = strTickLayout(baxis); + if(_this.bTickLayout !== newTickLayout) { + layers.baxis.selectAll('.xtick').remove(); + _this.bTickLayout = newTickLayout; + } + + newTickLayout = strTickLayout(caxis); + if(_this.cTickLayout !== newTickLayout) { + layers.caxis.selectAll('.ytick').remove(); + _this.cTickLayout = newTickLayout; + } + + // 3rd arg true below skips titles, so we can configure them + // correctly later on. + Axes.doTicksSingle(gd, aaxis, true); + Axes.doTicksSingle(gd, baxis, true); + Axes.doTicksSingle(gd, caxis, true); + + if(doTitles) { + var apad = Math.max(aaxis.showticklabels ? aaxis.tickfont.size / 2 : 0, + (caxis.showticklabels ? caxis.tickfont.size * 0.75 : 0) + + (caxis.ticks === 'outside' ? caxis.ticklen * 0.87 : 0)); + _this.layers['a-title'] = Titles.draw(gd, 'a' + titlesuffix, { + propContainer: aaxis, + propName: _this.id + '.aaxis.title', + placeholder: _(gd, 'Click to enter Component A title'), + attributes: { + x: _this.x0 + _this.w / 2, + y: _this.y0 - aaxis.titlefont.size / 3 - apad, + 'text-anchor': 'middle' + } + }); + + + var bpad = (baxis.showticklabels ? baxis.tickfont.size : 0) + + (baxis.ticks === 'outside' ? baxis.ticklen : 0) + 3; + + _this.layers['b-title'] = Titles.draw(gd, 'b' + titlesuffix, { + propContainer: baxis, + propName: _this.id + '.baxis.title', + placeholder: _(gd, 'Click to enter Component B title'), + attributes: { + x: _this.x0 - bpad, + y: _this.y0 + _this.h + baxis.titlefont.size * 0.83 + bpad, + 'text-anchor': 'middle' + } + }); + + _this.layers['c-title'] = Titles.draw(gd, 'c' + titlesuffix, { + propContainer: caxis, + propName: _this.id + '.caxis.title', + placeholder: _(gd, 'Click to enter Component C title'), + attributes: { + x: _this.x0 + _this.w + bpad, + y: _this.y0 + _this.h + caxis.titlefont.size * 0.83 + bpad, + 'text-anchor': 'middle' + } + }); + } +}; + +function strTickLayout(axLayout) { + return axLayout.ticks + String(axLayout.ticklen) + String(axLayout.showticklabels); +} + + +// hard coded paths for zoom corners +// uses the same sizing as cartesian, length is MINZOOM/2, width is 3px +var CLEN = constants.MINZOOM / 2 + 0.87; +var BLPATH = 'm-0.87,.5h' + CLEN + 'v3h-' + (CLEN + 5.2) + + 'l' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + + 'l2.6,1.5l-' + (CLEN / 2) + ',' + (CLEN * 0.87) + 'Z'; +var BRPATH = 'm0.87,.5h-' + CLEN + 'v3h' + (CLEN + 5.2) + + 'l-' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + + 'l-2.6,1.5l' + (CLEN / 2) + ',' + (CLEN * 0.87) + 'Z'; +var TOPPATH = 'm0,1l' + (CLEN / 2) + ',' + (CLEN * 0.87) + + 'l2.6,-1.5l-' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + + 'l-' + (CLEN / 2 + 2.6) + ',' + (CLEN * 0.87 + 4.5) + + 'l2.6,1.5l' + (CLEN / 2) + ',-' + (CLEN * 0.87) + 'Z'; +var STARTMARKER = 'm0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z'; + +// I guess this could be shared with cartesian... but for now it's separate. +var SHOWZOOMOUTTIP = true; + +proto.initInteractions = function() { + var _this = this, + dragger = _this.layers.plotbg.select('path').node(), + gd = _this.graphDiv, + zoomContainer = gd._fullLayout._zoomlayer; + + // use plotbg for the main interactions + var dragOptions = { + element: dragger, + gd: gd, + plotinfo: { + id: _this.id, + xaxis: _this.xaxis, + yaxis: _this.yaxis + }, + subplot: _this.id, + prepFn: function(e, startX, startY) { + // these aren't available yet when initInteractions + // is called + dragOptions.xaxes = [_this.xaxis]; + dragOptions.yaxes = [_this.yaxis]; + var dragModeNow = gd._fullLayout.dragmode; + + if(dragModeNow === 'lasso') dragOptions.minDrag = 1; + else dragOptions.minDrag = undefined; + + if(dragModeNow === 'zoom') { + dragOptions.moveFn = zoomMove; + dragOptions.clickFn = clickZoomPan; + dragOptions.doneFn = zoomDone; + zoomPrep(e, startX, startY); + } + else if(dragModeNow === 'pan') { + dragOptions.moveFn = plotDrag; + dragOptions.clickFn = clickZoomPan; + dragOptions.doneFn = dragDone; + panPrep(); + clearSelect(zoomContainer); + } + else if(dragModeNow === 'select' || dragModeNow === 'lasso') { + prepSelect(e, startX, startY, dragOptions, dragModeNow); + } + } + }; + + var x0, y0, mins0, span0, mins, lum, path0, dimmed, zb, corners; + + function clickZoomPan(numClicks, evt) { + var clickMode = gd._fullLayout.clickmode; + + removeZoombox(gd); + + if(numClicks === 2) { + var attrs = {}; + attrs[_this.id + '.aaxis.min'] = 0; + attrs[_this.id + '.baxis.min'] = 0; + attrs[_this.id + '.caxis.min'] = 0; + gd.emit('plotly_doubleclick', null); + Registry.call('relayout', gd, attrs); + } + + if(clickMode.indexOf('select') > -1 && numClicks === 1) { + selectOnClick(evt, gd, [_this.xaxis], [_this.yaxis], _this.id, dragOptions); + } + + if(clickMode.indexOf('event') > -1) { + Fx.click(gd, evt, _this.id); + } + } + + function zoomPrep(e, startX, startY) { + var dragBBox = dragger.getBoundingClientRect(); + x0 = startX - dragBBox.left; + y0 = startY - dragBBox.top; + mins0 = { + a: _this.aaxis.range[0], + b: _this.baxis.range[1], + c: _this.caxis.range[1] + }; + mins = mins0; + span0 = _this.aaxis.range[1] - mins0.a; + lum = tinycolor(_this.graphDiv._fullLayout[_this.id].bgcolor).getLuminance(); + path0 = 'M0,' + _this.h + 'L' + (_this.w / 2) + ', 0L' + _this.w + ',' + _this.h + 'Z'; + dimmed = false; + + zb = zoomContainer.append('path') + .attr('class', 'zoombox') + .attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')') + .style({ + 'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)', + 'stroke-width': 0 + }) + .attr('d', path0); + + corners = zoomContainer.append('path') + .attr('class', 'zoombox-corners') + .attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')') + .style({ + fill: Color.background, + stroke: Color.defaultLine, + 'stroke-width': 1, + opacity: 0 + }) + .attr('d', 'M0,0Z'); + + clearSelect(zoomContainer); + } + + function getAFrac(x, y) { return 1 - (y / _this.h); } + function getBFrac(x, y) { return 1 - ((x + (_this.h - y) / Math.sqrt(3)) / _this.w); } + function getCFrac(x, y) { return ((x - (_this.h - y) / Math.sqrt(3)) / _this.w); } + + function zoomMove(dx0, dy0) { + var x1 = x0 + dx0, + y1 = y0 + dy0, + afrac = Math.max(0, Math.min(1, getAFrac(x0, y0), getAFrac(x1, y1))), + bfrac = Math.max(0, Math.min(1, getBFrac(x0, y0), getBFrac(x1, y1))), + cfrac = Math.max(0, Math.min(1, getCFrac(x0, y0), getCFrac(x1, y1))), + xLeft = ((afrac / 2) + cfrac) * _this.w, + xRight = (1 - (afrac / 2) - bfrac) * _this.w, + xCenter = (xLeft + xRight) / 2, + xSpan = xRight - xLeft, + yBottom = (1 - afrac) * _this.h, + yTop = yBottom - xSpan / w_over_h; + + if(xSpan < constants.MINZOOM) { + mins = mins0; + zb.attr('d', path0); + corners.attr('d', 'M0,0Z'); + } + else { + mins = { + a: mins0.a + afrac * span0, + b: mins0.b + bfrac * span0, + c: mins0.c + cfrac * span0 + }; + zb.attr('d', path0 + 'M' + xLeft + ',' + yBottom + + 'H' + xRight + 'L' + xCenter + ',' + yTop + + 'L' + xLeft + ',' + yBottom + 'Z'); + corners.attr('d', 'M' + x0 + ',' + y0 + STARTMARKER + + 'M' + xLeft + ',' + yBottom + BLPATH + + 'M' + xRight + ',' + yBottom + BRPATH + + 'M' + xCenter + ',' + yTop + TOPPATH); + } + + if(!dimmed) { + zb.transition() + .style('fill', lum > 0.2 ? 'rgba(0,0,0,0.4)' : + 'rgba(255,255,255,0.3)') + .duration(200); + corners.transition() + .style('opacity', 1) + .duration(200); + dimmed = true; + } + } + + function zoomDone() { + removeZoombox(gd); + + if(mins === mins0) return; + + var attrs = {}; + attrs[_this.id + '.aaxis.min'] = mins.a; + attrs[_this.id + '.baxis.min'] = mins.b; + attrs[_this.id + '.caxis.min'] = mins.c; + + Registry.call('relayout', gd, attrs); + + if(SHOWZOOMOUTTIP && gd.data && gd._context.showTips) { + Lib.notifier(_(gd, 'Double-click to zoom back out'), 'long'); + SHOWZOOMOUTTIP = false; + } + } + + function panPrep() { + mins0 = { + a: _this.aaxis.range[0], + b: _this.baxis.range[1], + c: _this.caxis.range[1] + }; + mins = mins0; + } + + function plotDrag(dx, dy) { + var dxScaled = dx / _this.xaxis._m, + dyScaled = dy / _this.yaxis._m; + mins = { + a: mins0.a - dyScaled, + b: mins0.b + (dxScaled + dyScaled) / 2, + c: mins0.c - (dxScaled - dyScaled) / 2 + }; + var minsorted = [mins.a, mins.b, mins.c].sort(), + minindices = { + a: minsorted.indexOf(mins.a), + b: minsorted.indexOf(mins.b), + c: minsorted.indexOf(mins.c) + }; + if(minsorted[0] < 0) { + if(minsorted[1] + minsorted[0] / 2 < 0) { + minsorted[2] += minsorted[0] + minsorted[1]; + minsorted[0] = minsorted[1] = 0; + } + else { + minsorted[2] += minsorted[0] / 2; + minsorted[1] += minsorted[0] / 2; + minsorted[0] = 0; + } + mins = { + a: minsorted[minindices.a], + b: minsorted[minindices.b], + c: minsorted[minindices.c] + }; + dy = (mins0.a - mins.a) * _this.yaxis._m; + dx = (mins0.c - mins.c - mins0.b + mins.b) * _this.xaxis._m; + } + + // move the data (translate, don't redraw) + var plotTransform = 'translate(' + (_this.x0 + dx) + ',' + (_this.y0 + dy) + ')'; + _this.plotContainer.selectAll('.scatterlayer,.maplayer') + .attr('transform', plotTransform); + + var plotTransform2 = 'translate(' + -dx + ',' + -dy + ')'; + _this.clipDefRelative.select('path').attr('transform', plotTransform2); + + // move the ticks + _this.aaxis.range = [mins.a, _this.sum - mins.b - mins.c]; + _this.baxis.range = [_this.sum - mins.a - mins.c, mins.b]; + _this.caxis.range = [_this.sum - mins.a - mins.b, mins.c]; + + _this.drawAxes(false); + _this.plotContainer.selectAll('.crisp').classed('crisp', false); + + if(_this._hasClipOnAxisFalse) { + _this.plotContainer + .select('.scatterlayer').selectAll('.trace') + .call(Drawing.hideOutsideRangePoints, _this); + } + } + + function dragDone() { + var attrs = {}; + attrs[_this.id + '.aaxis.min'] = mins.a; + attrs[_this.id + '.baxis.min'] = mins.b; + attrs[_this.id + '.caxis.min'] = mins.c; + + Registry.call('relayout', gd, attrs); + } + + // finally, set up hover and click + // these event handlers must already be set before dragElement.init + // so it can stash them and override them. + dragger.onmousemove = function(evt) { + Fx.hover(gd, evt, _this.id); + gd._fullLayout._lasthover = dragger; + gd._fullLayout._hoversubplot = _this.id; + }; + + dragger.onmouseout = function(evt) { + if(gd._dragging) return; + + dragElement.unhover(gd, evt); + }; + + dragElement.init(dragOptions); +}; + +function removeZoombox(gd) { + d3.select(gd) + .selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners') + .remove(); +} + +},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../components/titles":661,"../../lib":696,"../../lib/extend":685,"../../registry":827,"../cartesian/axes":744,"../cartesian/constants":750,"../cartesian/select":762,"../cartesian/set_convert":763,"../plots":808,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"tinycolor2":514}],827:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Loggers = _dereq_('./lib/loggers'); +var noop = _dereq_('./lib/noop'); +var pushUnique = _dereq_('./lib/push_unique'); +var isPlainObject = _dereq_('./lib/is_plain_object'); +var ExtendModule = _dereq_('./lib/extend'); + +var basePlotAttributes = _dereq_('./plots/attributes'); +var baseLayoutAttributes = _dereq_('./plots/layout_attributes'); + +var extendFlat = ExtendModule.extendFlat; +var extendDeepAll = ExtendModule.extendDeepAll; + +exports.modules = {}; +exports.allCategories = {}; +exports.allTypes = []; +exports.subplotsRegistry = {}; +exports.transformsRegistry = {}; +exports.componentsRegistry = {}; +exports.layoutArrayContainers = []; +exports.layoutArrayRegexes = []; +exports.traceLayoutAttributes = {}; +exports.localeRegistry = {}; +exports.apiMethodRegistry = {}; + +/** + * Top-level register routine, exported as Plotly.register + * + * @param {object array or array of objects} _modules : + * module object or list of module object to register. + * + * A valid `moduleType: 'trace'` module has fields: + * - name {string} : the trace type + * - categories {array} : categories associated with this trace type, + * tested with Register.traceIs() + * - meta {object} : meta info (mostly for plot-schema) + * + * A valid `moduleType: 'locale'` module has fields: + * - name {string} : the locale name. Should be a 2-digit language string ('en', 'de') + * optionally with a country/region code ('en-GB', 'de-CH'). If a country + * code is used but the base language locale has not yet been supplied, + * we will use this locale for the base as well. + * - dictionary {object} : the dictionary mapping input strings to localized strings + * generally the keys should be the literal input strings, but + * if default translations are provided you can use any string as a key. + * - format {object} : a `d3.locale` format specifier for this locale + * any omitted keys we'll fall back on en-US. + * + * A valid `moduleType: 'transform'` module has fields: + * - name {string} : transform name + * - transform {function} : default-level transform function + * - calcTransform {function} : calc-level transform function + * - attributes {object} : transform attributes declarations + * - supplyDefaults {function} : attributes default-supply function + * + * A valid `moduleType: 'component'` module has fields: + * - name {string} : the component name, used it with Register.getComponentMethod() + * to employ component method. + * + * A valid `moduleType: 'apiMethod'` module has fields: + * - name {string} : the api method name. + * - fn {function} : the api method called with Register.call(); + * + */ +exports.register = function register(_modules) { + if(!_modules) { + throw new Error('No argument passed to Plotly.register.'); + } else if(_modules && !Array.isArray(_modules)) { + _modules = [_modules]; + } + + for(var i = 0; i < _modules.length; i++) { + var newModule = _modules[i]; + + if(!newModule) { + throw new Error('Invalid module was attempted to be registered!'); + } + + switch(newModule.moduleType) { + case 'trace': + registerTraceModule(newModule); + break; + case 'transform': + registerTransformModule(newModule); + break; + case 'component': + registerComponentModule(newModule); + break; + case 'locale': + registerLocale(newModule); + break; + case 'apiMethod': + var name = newModule.name; + exports.apiMethodRegistry[name] = newModule.fn; + break; + default: + throw new Error('Invalid module was attempted to be registered!'); + } + } +}; + +/** + * Get registered module using trace object or trace type + * + * @param {object||string} trace + * trace object with prop 'type' or trace type as a string + * @return {object} + * module object corresponding to trace type + */ +exports.getModule = function(trace) { + var _module = exports.modules[getTraceType(trace)]; + if(!_module) return false; + return _module._module; +}; + +/** + * Determine if this trace type is in a given category + * + * @param {object||string} traceType + * a trace (object) or trace type (string) + * @param {string} category + * category in question + * @return {boolean} + */ +exports.traceIs = function(traceType, category) { + traceType = getTraceType(traceType); + + // old plot.ly workspace hack, nothing to see here + if(traceType === 'various') return false; + + var _module = exports.modules[traceType]; + + if(!_module) { + if(traceType && traceType !== 'area') { + Loggers.log('Unrecognized trace type ' + traceType + '.'); + } + + _module = exports.modules[basePlotAttributes.type.dflt]; + } + + return !!_module.categories[category]; +}; + +/** + * Determine if this trace has a transform of the given type and return + * array of matching indices. + * + * @param {object} data + * a trace object (member of data or fullData) + * @param {string} type + * type of trace to test + * @return {array} + * array of matching indices. If none found, returns [] + */ +exports.getTransformIndices = function(data, type) { + var indices = []; + var transforms = data.transforms || []; + for(var i = 0; i < transforms.length; i++) { + if(transforms[i].type === type) { + indices.push(i); + } + } + return indices; +}; + +/** + * Determine if this trace has a transform of the given type + * + * @param {object} data + * a trace object (member of data or fullData) + * @param {string} type + * type of trace to test + * @return {boolean} + */ +exports.hasTransform = function(data, type) { + var transforms = data.transforms || []; + for(var i = 0; i < transforms.length; i++) { + if(transforms[i].type === type) { + return true; + } + } + return false; +}; + +/** + * Retrieve component module method. Falls back on noop if either the + * module or the method is missing, so the result can always be safely called + * + * @param {string} name + * name of component (as declared in component module) + * @param {string} method + * name of component module method + * @return {function} + */ +exports.getComponentMethod = function(name, method) { + var _module = exports.componentsRegistry[name]; + + if(!_module) return noop; + return _module[method] || noop; +}; + +/** + * Call registered api method. + * + * @param {string} name : api method name + * @param {...array} args : arguments passed to api method + * @return {any} : returns api method output + */ +exports.call = function() { + var name = arguments[0]; + var args = [].slice.call(arguments, 1); + return exports.apiMethodRegistry[name].apply(null, args); +}; + +function registerTraceModule(_module) { + var thisType = _module.name; + var categoriesIn = _module.categories; + var meta = _module.meta; + + if(exports.modules[thisType]) { + Loggers.log('Type ' + thisType + ' already registered'); + return; + } + + if(!exports.subplotsRegistry[_module.basePlotModule.name]) { + registerSubplot(_module.basePlotModule); + } + + var categoryObj = {}; + for(var i = 0; i < categoriesIn.length; i++) { + categoryObj[categoriesIn[i]] = true; + exports.allCategories[categoriesIn[i]] = true; + } + + exports.modules[thisType] = { + _module: _module, + categories: categoryObj + }; + + if(meta && Object.keys(meta).length) { + exports.modules[thisType].meta = meta; + } + + exports.allTypes.push(thisType); + + for(var componentName in exports.componentsRegistry) { + mergeComponentAttrsToTrace(componentName, thisType); + } + + /* + * Collect all trace layout attributes in one place for easier lookup later + * but don't merge them into the base schema as it would confuse the docs + * (at least after https://github.com/plotly/documentation/issues/202 gets done!) + */ + if(_module.layoutAttributes) { + extendFlat(exports.traceLayoutAttributes, _module.layoutAttributes); + } +} + +function registerSubplot(_module) { + var plotType = _module.name; + + if(exports.subplotsRegistry[plotType]) { + Loggers.log('Plot type ' + plotType + ' already registered.'); + return; + } + + // relayout array handling will look for component module methods with this + // name and won't find them because this is a subplot module... but that + // should be fine, it will just fall back on redrawing the plot. + findArrayRegexps(_module); + + // not sure what's best for the 'cartesian' type at this point + exports.subplotsRegistry[plotType] = _module; + + for(var componentName in exports.componentsRegistry) { + mergeComponentAttrsToSubplot(componentName, _module.name); + } +} + +function registerComponentModule(_module) { + if(typeof _module.name !== 'string') { + throw new Error('Component module *name* must be a string.'); + } + + var name = _module.name; + exports.componentsRegistry[name] = _module; + + if(_module.layoutAttributes) { + if(_module.layoutAttributes._isLinkedToArray) { + pushUnique(exports.layoutArrayContainers, name); + } + findArrayRegexps(_module); + } + + for(var traceType in exports.modules) { + mergeComponentAttrsToTrace(name, traceType); + } + + for(var subplotName in exports.subplotsRegistry) { + mergeComponentAttrsToSubplot(name, subplotName); + } + + for(var transformType in exports.transformsRegistry) { + mergeComponentAttrsToTransform(name, transformType); + } + + if(_module.schema && _module.schema.layout) { + extendDeepAll(baseLayoutAttributes, _module.schema.layout); + } +} + +function registerTransformModule(_module) { + if(typeof _module.name !== 'string') { + throw new Error('Transform module *name* must be a string.'); + } + + var prefix = 'Transform module ' + _module.name; + var hasTransform = typeof _module.transform === 'function'; + var hasCalcTransform = typeof _module.calcTransform === 'function'; + + if(!hasTransform && !hasCalcTransform) { + throw new Error(prefix + ' is missing a *transform* or *calcTransform* method.'); + } + if(hasTransform && hasCalcTransform) { + Loggers.log([ + prefix + ' has both a *transform* and *calcTransform* methods.', + 'Please note that all *transform* methods are executed', + 'before all *calcTransform* methods.' + ].join(' ')); + } + if(!isPlainObject(_module.attributes)) { + Loggers.log(prefix + ' registered without an *attributes* object.'); + } + if(typeof _module.supplyDefaults !== 'function') { + Loggers.log(prefix + ' registered without a *supplyDefaults* method.'); + } + + exports.transformsRegistry[_module.name] = _module; + + for(var componentName in exports.componentsRegistry) { + mergeComponentAttrsToTransform(componentName, _module.name); + } +} + +function registerLocale(_module) { + var locale = _module.name; + var baseLocale = locale.split('-')[0]; + + var newDict = _module.dictionary; + var newFormat = _module.format; + var hasDict = newDict && Object.keys(newDict).length; + var hasFormat = newFormat && Object.keys(newFormat).length; + + var locales = exports.localeRegistry; + + var localeObj = locales[locale]; + if(!localeObj) locales[locale] = localeObj = {}; + + // Should we use this dict for the base locale? + // In case we're overwriting a previous dict for this locale, check + // whether the base matches the full locale dict now. If we're not + // overwriting, locales[locale] is undefined so this just checks if + // baseLocale already had a dict or not. + // Same logic for dateFormats + if(baseLocale !== locale) { + var baseLocaleObj = locales[baseLocale]; + if(!baseLocaleObj) locales[baseLocale] = baseLocaleObj = {}; + + if(hasDict && baseLocaleObj.dictionary === localeObj.dictionary) { + baseLocaleObj.dictionary = newDict; + } + if(hasFormat && baseLocaleObj.format === localeObj.format) { + baseLocaleObj.format = newFormat; + } + } + + if(hasDict) localeObj.dictionary = newDict; + if(hasFormat) localeObj.format = newFormat; +} + +function findArrayRegexps(_module) { + if(_module.layoutAttributes) { + var arrayAttrRegexps = _module.layoutAttributes._arrayAttrRegexps; + if(arrayAttrRegexps) { + for(var i = 0; i < arrayAttrRegexps.length; i++) { + pushUnique(exports.layoutArrayRegexes, arrayAttrRegexps[i]); + } + } + } +} + +function mergeComponentAttrsToTrace(componentName, traceType) { + var componentSchema = exports.componentsRegistry[componentName].schema; + if(!componentSchema || !componentSchema.traces) return; + + var traceAttrs = componentSchema.traces[traceType]; + if(traceAttrs) { + extendDeepAll(exports.modules[traceType]._module.attributes, traceAttrs); + } +} + +function mergeComponentAttrsToTransform(componentName, transformType) { + var componentSchema = exports.componentsRegistry[componentName].schema; + if(!componentSchema || !componentSchema.transforms) return; + + var transformAttrs = componentSchema.transforms[transformType]; + if(transformAttrs) { + extendDeepAll(exports.transformsRegistry[transformType].attributes, transformAttrs); + } +} + +function mergeComponentAttrsToSubplot(componentName, subplotName) { + var componentSchema = exports.componentsRegistry[componentName].schema; + if(!componentSchema || !componentSchema.subplots) return; + + var subplotModule = exports.subplotsRegistry[subplotName]; + var subplotAttrs = subplotModule.layoutAttributes; + var subplotAttr = subplotModule.attr === 'subplot' ? subplotModule.name : subplotModule.attr; + if(Array.isArray(subplotAttr)) subplotAttr = subplotAttr[0]; + + var componentLayoutAttrs = componentSchema.subplots[subplotAttr]; + if(subplotAttrs && componentLayoutAttrs) { + extendDeepAll(subplotAttrs, componentLayoutAttrs); + } +} + +function getTraceType(traceType) { + if(typeof traceType === 'object') traceType = traceType.type; + return traceType; +} + +},{"./lib/extend":685,"./lib/is_plain_object":697,"./lib/loggers":700,"./lib/noop":705,"./lib/push_unique":710,"./plots/attributes":741,"./plots/layout_attributes":799}],828:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../lib'); + +var extendFlat = Lib.extendFlat; +var extendDeep = Lib.extendDeep; + +// Put default plotTile layouts here +function cloneLayoutOverride(tileClass) { + var override; + + switch(tileClass) { + case 'themes__thumb': + override = { + autosize: true, + width: 150, + height: 150, + title: '', + showlegend: false, + margin: {l: 5, r: 5, t: 5, b: 5, pad: 0}, + annotations: [] + }; + break; + + case 'thumbnail': + override = { + title: '', + hidesources: true, + showlegend: false, + borderwidth: 0, + bordercolor: '', + margin: {l: 1, r: 1, t: 1, b: 1, pad: 0}, + annotations: [] + }; + break; + + default: + override = {}; + } + + + return override; +} + +function keyIsAxis(keyName) { + var types = ['xaxis', 'yaxis', 'zaxis']; + return (types.indexOf(keyName.slice(0, 5)) > -1); +} + + +module.exports = function clonePlot(graphObj, options) { + + // Polar plot compatibility + if(graphObj.framework && graphObj.framework.isPolar) { + graphObj = graphObj.framework.getConfig(); + } + + var i; + var oldData = graphObj.data; + var oldLayout = graphObj.layout; + var newData = extendDeep([], oldData); + var newLayout = extendDeep({}, oldLayout, cloneLayoutOverride(options.tileClass)); + var context = graphObj._context || {}; + + if(options.width) newLayout.width = options.width; + if(options.height) newLayout.height = options.height; + + if(options.tileClass === 'thumbnail' || options.tileClass === 'themes__thumb') { + // kill annotations + newLayout.annotations = []; + var keys = Object.keys(newLayout); + + for(i = 0; i < keys.length; i++) { + if(keyIsAxis(keys[i])) { + newLayout[keys[i]].title = ''; + } + } + + // kill colorbar and pie labels + for(i = 0; i < newData.length; i++) { + var trace = newData[i]; + trace.showscale = false; + if(trace.marker) trace.marker.showscale = false; + if(trace.type === 'pie') trace.textposition = 'none'; + } + } + + if(Array.isArray(options.annotations)) { + for(i = 0; i < options.annotations.length; i++) { + newLayout.annotations.push(options.annotations[i]); + } + } + + // TODO: does this scene modification really belong here? + // If we still need it, can it move into the gl3d module? + var sceneIds = Object.keys(newLayout).filter(function(key) { + return key.match(/^scene\d*$/); + }); + if(sceneIds.length) { + var axesImageOverride = {}; + if(options.tileClass === 'thumbnail') { + axesImageOverride = { + title: '', + showaxeslabels: false, + showticklabels: false, + linetickenable: false + }; + } + for(i = 0; i < sceneIds.length; i++) { + var scene = newLayout[sceneIds[i]]; + + if(!scene.xaxis) { + scene.xaxis = {}; + } + + if(!scene.yaxis) { + scene.yaxis = {}; + } + + if(!scene.zaxis) { + scene.zaxis = {}; + } + + extendFlat(scene.xaxis, axesImageOverride); + extendFlat(scene.yaxis, axesImageOverride); + extendFlat(scene.zaxis, axesImageOverride); + + // TODO what does this do? + scene._scene = null; + } + } + + var gd = document.createElement('div'); + if(options.tileClass) gd.className = options.tileClass; + + var plotTile = { + gd: gd, + td: gd, // for external (image server) compatibility + layout: newLayout, + data: newData, + config: { + staticPlot: (options.staticPlot === undefined) ? + true : + options.staticPlot, + plotGlPixelRatio: (options.plotGlPixelRatio === undefined) ? + 2 : + options.plotGlPixelRatio, + displaylogo: options.displaylogo || false, + showLink: options.showLink || false, + showTips: options.showTips || false, + mapboxAccessToken: context.mapboxAccessToken + } + }; + + if(options.setBackground !== 'transparent') { + plotTile.config.setBackground = options.setBackground || 'opaque'; + } + + // attaching the default Layout the gd, so you can grab it later + plotTile.gd.defaultLayout = cloneLayoutOverride(options.tileClass); + + return plotTile; +}; + +},{"../lib":696}],829:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var toImage = _dereq_('../plot_api/to_image'); +var Lib = _dereq_('../lib'); // for isIE +var fileSaver = _dereq_('./filesaver'); + +/** Plotly.downloadImage + * + * @param {object | string | HTML div} gd + * can either be a data/layout/config object + * or an existing graph
+ * or an id to an existing graph
+ * @param {object} opts (see ../plot_api/to_image) + * @return {promise} + */ +function downloadImage(gd, opts) { + var _gd; + if(!Lib.isPlainObject(gd)) _gd = Lib.getGraphDiv(gd); + + // check for undefined opts + opts = opts || {}; + // default to png + opts.format = opts.format || 'png'; + + return new Promise(function(resolve, reject) { + if(_gd && _gd._snapshotInProgress) { + reject(new Error('Snapshotting already in progress.')); + } + + // see comments within svgtoimg for additional + // discussion of problems with IE + // can now draw to canvas, but CORS tainted canvas + // does not allow toDataURL + // svg format will work though + if(Lib.isIE() && opts.format !== 'svg') { + reject(new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.')); + } + + if(_gd) _gd._snapshotInProgress = true; + var promise = toImage(gd, opts); + + var filename = opts.filename || gd.fn || 'newplot'; + filename += '.' + opts.format; + + promise.then(function(result) { + if(_gd) _gd._snapshotInProgress = false; + return fileSaver(result, filename); + }).then(function(name) { + resolve(name); + }).catch(function(err) { + if(_gd) _gd._snapshotInProgress = false; + reject(err); + }); + }); +} + +module.exports = downloadImage; + +},{"../lib":696,"../plot_api/to_image":737,"./filesaver":830}],830:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* +* substantial portions of this code from FileSaver.js +* https://github.com/eligrey/FileSaver.js +* License: https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md +* FileSaver.js +* A saveAs() FileSaver implementation. +* 1.1.20160328 +* +* By Eli Grey, http://eligrey.com +* License: MIT +* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md +*/ + +'use strict'; + +var fileSaver = function(url, name) { + var saveLink = document.createElement('a'); + var canUseSaveLink = 'download' in saveLink; + var isSafari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent); + var promise = new Promise(function(resolve, reject) { + // IE <10 is explicitly unsupported + if(typeof navigator !== 'undefined' && /MSIE [1-9]\./.test(navigator.userAgent)) { + reject(new Error('IE < 10 unsupported')); + } + + // First try a.download, then web filesystem, then object URLs + if(isSafari) { + // Safari doesn't allow downloading of blob urls + document.location.href = 'data:application/octet-stream' + url.slice(url.search(/[,;]/)); + resolve(name); + } + + if(!name) { + name = 'download'; + } + + if(canUseSaveLink) { + saveLink.href = url; + saveLink.download = name; + document.body.appendChild(saveLink); + saveLink.click(); + document.body.removeChild(saveLink); + resolve(name); + } + + // IE 10+ (native saveAs) + if(typeof navigator !== 'undefined' && navigator.msSaveBlob) { + // At this point we are only dealing with a SVG encoded as + // a data URL (since IE only supports SVG) + var encoded = url.split(/^data:image\/svg\+xml,/)[1]; + var svg = decodeURIComponent(encoded); + navigator.msSaveBlob(new Blob([svg]), name); + resolve(name); + } + + reject(new Error('download error')); + }); + + return promise; +}; + +module.exports = fileSaver; + +},{}],831:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.getDelay = function(fullLayout) { + if(!fullLayout._has) return 0; + + return ( + fullLayout._has('gl3d') || + fullLayout._has('gl2d') || + fullLayout._has('mapbox') + ) ? 500 : 0; +}; + +exports.getRedrawFunc = function(gd) { + var fullLayout = gd._fullLayout || {}; + var hasPolar = fullLayout._has && fullLayout._has('polar'); + var hasLegacyPolar = !hasPolar && gd.data && gd.data[0] && gd.data[0].r; + + // do not work for legacy polar + if(hasLegacyPolar) return; + + return function() { + (gd.calcdata || []).forEach(function(d) { + if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); + }); + }; +}; + +},{}],832:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var helpers = _dereq_('./helpers'); + +var Snapshot = { + getDelay: helpers.getDelay, + getRedrawFunc: helpers.getRedrawFunc, + clone: _dereq_('./cloneplot'), + toSVG: _dereq_('./tosvg'), + svgToImg: _dereq_('./svgtoimg'), + toImage: _dereq_('./toimage'), + downloadImage: _dereq_('./download') +}; + +module.exports = Snapshot; + +},{"./cloneplot":828,"./download":829,"./helpers":831,"./svgtoimg":833,"./toimage":834,"./tosvg":835}],833:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var EventEmitter = _dereq_('events').EventEmitter; + +function svgToImg(opts) { + var ev = opts.emitter || new EventEmitter(); + + var promise = new Promise(function(resolve, reject) { + var Image = window.Image; + var svg = opts.svg; + var format = opts.format || 'png'; + + // IE only support svg + if(Lib.isIE() && format !== 'svg') { + var ieSvgError = new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.'); + reject(ieSvgError); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', ieSvgError); + } else { + return promise; + } + } + + var canvas = opts.canvas; + var scale = opts.scale || 1; + var w0 = opts.width || 300; + var h0 = opts.height || 150; + var w1 = scale * w0; + var h1 = scale * h0; + + var ctx = canvas.getContext('2d'); + var img = new Image(); + + // for Safari support, eliminate createObjectURL + // this decision could cause problems if content + // is not restricted to svg + var url = 'data:image/svg+xml,' + encodeURIComponent(svg); + + canvas.width = w1; + canvas.height = h1; + + img.onload = function() { + var imgData; + + // don't need to draw to canvas if svg + // save some time and also avoid failure on IE + if(format !== 'svg') { + ctx.drawImage(img, 0, 0, w1, h1); + } + + switch(format) { + case 'jpeg': + imgData = canvas.toDataURL('image/jpeg'); + break; + case 'png': + imgData = canvas.toDataURL('image/png'); + break; + case 'webp': + imgData = canvas.toDataURL('image/webp'); + break; + case 'svg': + imgData = url; + break; + default: + var errorMsg = 'Image format is not jpeg, png, svg or webp.'; + reject(new Error(errorMsg)); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', errorMsg); + } + } + resolve(imgData); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + ev.emit('success', imgData); + } + }; + + img.onerror = function(err) { + reject(err); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', err); + } + }; + + img.src = url; + }); + + // temporary for backward compatibility + // move to only Promise in 2.0.0 + // and eliminate the EventEmitter + if(opts.promise) { + return promise; + } + + return ev; +} + +module.exports = svgToImg; + +},{"../lib":696,"events":92}],834:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var EventEmitter = _dereq_('events').EventEmitter; + +var Registry = _dereq_('../registry'); +var Lib = _dereq_('../lib'); + +var helpers = _dereq_('./helpers'); +var clonePlot = _dereq_('./cloneplot'); +var toSVG = _dereq_('./tosvg'); +var svgToImg = _dereq_('./svgtoimg'); + +/** + * @param {object} gd figure Object + * @param {object} opts option object + * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg' + */ +function toImage(gd, opts) { + + // first clone the GD so we can operate in a clean environment + var ev = new EventEmitter(); + + var clone = clonePlot(gd, {format: 'png'}); + var clonedGd = clone.gd; + + // put the cloned div somewhere off screen before attaching to DOM + clonedGd.style.position = 'absolute'; + clonedGd.style.left = '-5000px'; + document.body.appendChild(clonedGd); + + function wait() { + var delay = helpers.getDelay(clonedGd._fullLayout); + + setTimeout(function() { + var svg = toSVG(clonedGd); + + var canvas = document.createElement('canvas'); + canvas.id = Lib.randstr(); + + ev = svgToImg({ + format: opts.format, + width: clonedGd._fullLayout.width, + height: clonedGd._fullLayout.height, + canvas: canvas, + emitter: ev, + svg: svg + }); + + ev.clean = function() { + if(clonedGd) document.body.removeChild(clonedGd); + }; + + }, delay); + } + + var redrawFunc = helpers.getRedrawFunc(clonedGd); + + Registry.call('plot', clonedGd, clone.data, clone.layout, clone.config) + .then(redrawFunc) + .then(wait) + .catch(function(err) { + ev.emit('error', err); + }); + + + return ev; +} + +module.exports = toImage; + +},{"../lib":696,"../registry":827,"./cloneplot":828,"./helpers":831,"./svgtoimg":833,"./tosvg":835,"events":92}],835:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../lib'); +var Drawing = _dereq_('../components/drawing'); +var Color = _dereq_('../components/color'); + +var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); +var DOUBLEQUOTE_REGEX = /"/g; +var DUMMY_SUB = 'TOBESTRIPPED'; +var DUMMY_REGEX = new RegExp('("' + DUMMY_SUB + ')|(' + DUMMY_SUB + '")', 'g'); + +function htmlEntityDecode(s) { + var hiddenDiv = d3.select('body').append('div').style({display: 'none'}).html(''); + var replaced = s.replace(/(&[^;]*;)/gi, function(d) { + if(d === '<') { return '<'; } // special handling for brackets + if(d === '&rt;') { return '>'; } + if(d.indexOf('<') !== -1 || d.indexOf('>') !== -1) { return ''; } + return hiddenDiv.html(d).text(); // everything else, let the browser decode it to unicode + }); + hiddenDiv.remove(); + return replaced; +} + +function xmlEntityEncode(str) { + return str.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g, '&'); +} + +module.exports = function toSVG(gd, format, scale) { + var fullLayout = gd._fullLayout; + var svg = fullLayout._paper; + var toppaper = fullLayout._toppaper; + var width = fullLayout.width; + var height = fullLayout.height; + var i; + + // make background color a rect in the svg, then revert after scraping + // all other alterations have been dealt with by properly preparing the svg + // in the first place... like setting cursors with css classes so we don't + // have to remove them, and providing the right namespaces in the svg to + // begin with + svg.insert('rect', ':first-child') + .call(Drawing.setRect, 0, 0, width, height) + .call(Color.fill, fullLayout.paper_bgcolor); + + // subplot-specific to-SVG methods + // which notably add the contents of the gl-container + // into the main svg node + var basePlotModules = fullLayout._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.toSVG) _module.toSVG(gd); + } + + // add top items above them assumes everything in toppaper is either + // a group or a defs, and if it's empty (like hoverlayer) we can ignore it. + if(toppaper) { + var nodes = toppaper.node().childNodes; + + // make copy of nodes as childNodes prop gets mutated in loop below + var topGroups = Array.prototype.slice.call(nodes); + + for(i = 0; i < topGroups.length; i++) { + var topGroup = topGroups[i]; + + if(topGroup.childNodes.length) svg.node().appendChild(topGroup); + } + } + + // remove draglayer for Adobe Illustrator compatibility + if(fullLayout._draggers) { + fullLayout._draggers.remove(); + } + + // in case the svg element had an explicit background color, remove this + // we want the rect to get the color so it's the right size; svg bg will + // fill whatever container it's displayed in regardless of plot size. + svg.node().style.background = ''; + + svg.selectAll('text') + .attr({'data-unformatted': null, 'data-math': null}) + .each(function() { + var txt = d3.select(this); + + // hidden text is pre-formatting mathjax, the browser ignores it + // but in a static plot it's useless and it can confuse batik + // we've tried to standardize on display:none but make sure we still + // catch visibility:hidden if it ever arises + if(this.style.visibility === 'hidden' || this.style.display === 'none') { + txt.remove(); + return; + } + else { + // clear other visibility/display values to default + // to not potentially confuse non-browser SVG implementations + txt.style({visibility: null, display: null}); + } + + // Font family styles break things because of quotation marks, + // so we must remove them *after* the SVG DOM has been serialized + // to a string (browsers convert singles back) + var ff = this.style.fontFamily; + if(ff && ff.indexOf('"') !== -1) { + txt.style('font-family', ff.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + }); + + svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, .cbfill').each(function() { + var pt = d3.select(this); + + // similar to font family styles above, + // we must remove " after the SVG DOM has been serialized + var fill = this.style.fill; + if(fill && fill.indexOf('url(') !== -1) { + pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + + var stroke = this.style.stroke; + if(stroke && stroke.indexOf('url(') !== -1) { + pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + }); + + if(format === 'pdf' || format === 'eps') { + // these formats make the extra line MathJax adds around symbols look super thick in some cases + // it looks better if this is removed entirely. + svg.selectAll('#MathJax_SVG_glyphs path') + .attr('stroke-width', 0); + } + + // fix for IE namespacing quirk? + // http://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie + svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns', xmlnsNamespaces.svg); + svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns:xlink', xmlnsNamespaces.xlink); + + if(format === 'svg' && scale) { + svg.attr('width', scale * width); + svg.attr('height', scale * height); + svg.attr('viewBox', '0 0 ' + width + ' ' + height); + } + + var s = new window.XMLSerializer().serializeToString(svg.node()); + s = htmlEntityDecode(s); + s = xmlEntityEncode(s); + + // Fix quotations around font strings and gradient URLs + s = s.replace(DUMMY_REGEX, '\''); + + // IE is very strict, so we will need to clean + // svg with the following regex + // yes this is messy, but do not know a better way + // Even with this IE will not work due to tainted canvas + // see https://github.com/kangax/fabric.js/issues/1957 + // http://stackoverflow.com/questions/18112047/canvas-todataurl-working-in-all-browsers-except-ie10 + // Leave here just in case the CORS/tainted IE issue gets resolved + if(Lib.isIE()) { + // replace double quote with single quote + s = s.replace(/"/gi, '\''); + // url in svg are single quoted + // since we changed double to single + // we'll need to change these to double-quoted + s = s.replace(/(\('#)([^']*)('\))/gi, '(\"#$2\")'); + // font names with spaces will be escaped single-quoted + // we'll need to change these to double-quoted + s = s.replace(/(\\')/gi, '\"'); + } + + return s; +}; + +},{"../components/color":570,"../components/drawing":595,"../constants/xmlns_namespaces":674,"../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],836:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var mergeArray = _dereq_('../../lib').mergeArray; + + +// arrayOk attributes, merge them into calcdata array +module.exports = function arraysToCalcdata(cd, trace) { + for(var i = 0; i < cd.length; i++) cd[i].i = i; + + mergeArray(trace.text, cd, 'tx'); + mergeArray(trace.hovertext, cd, 'htx'); + + var marker = trace.marker; + if(marker) { + mergeArray(marker.opacity, cd, 'mo'); + mergeArray(marker.color, cd, 'mc'); + + var markerLine = marker.line; + if(markerLine) { + mergeArray(markerLine.color, cd, 'mlc'); + mergeArray(markerLine.width, cd, 'mlw'); + } + } +}; + +},{"../../lib":696}],837:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var textFontAttrs = fontAttrs({ + editType: 'calc', + arrayOk: true, + colorEditType: 'style', + +}); + +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +var markerLineWidth = extendFlat({}, + scatterMarkerLineAttrs.width, { dflt: 0 }); + +var markerLine = extendFlat({ + width: markerLineWidth, + editType: 'calc' +}, colorAttributes('marker.line')); + +var marker = extendFlat({ + line: markerLine, + editType: 'calc' +}, colorAttributes('marker'), { + colorbar: colorbarAttrs, + opacity: { + valType: 'number', + arrayOk: true, + dflt: 1, + min: 0, + max: 1, + + editType: 'style', + + } +}); + +module.exports = { + x: scatterAttrs.x, + x0: scatterAttrs.x0, + dx: scatterAttrs.dx, + y: scatterAttrs.y, + y0: scatterAttrs.y0, + dy: scatterAttrs.dy, + + text: scatterAttrs.text, + hovertext: scatterAttrs.hovertext, + + textposition: { + valType: 'enumerated', + + values: ['inside', 'outside', 'auto', 'none'], + dflt: 'none', + arrayOk: true, + editType: 'calc', + + }, + + textfont: extendFlat({}, textFontAttrs, { + + }), + + insidetextfont: extendFlat({}, textFontAttrs, { + + }), + + outsidetextfont: extendFlat({}, textFontAttrs, { + + }), + + constraintext: { + valType: 'enumerated', + values: ['inside', 'outside', 'both', 'none'], + + dflt: 'both', + editType: 'calc', + + }, + + cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, { + + }), + + orientation: { + valType: 'enumerated', + + values: ['v', 'h'], + editType: 'calc+clearAxisTypes', + + }, + + base: { + valType: 'any', + dflt: null, + arrayOk: true, + + editType: 'calc', + + }, + + offset: { + valType: 'number', + dflt: null, + arrayOk: true, + + editType: 'calc', + + }, + + width: { + valType: 'number', + dflt: null, + min: 0, + arrayOk: true, + + editType: 'calc', + + }, + + marker: marker, + + selected: { + marker: { + opacity: scatterAttrs.selected.marker.opacity, + color: scatterAttrs.selected.marker.color, + editType: 'style' + }, + textfont: scatterAttrs.selected.textfont, + editType: 'style' + }, + unselected: { + marker: { + opacity: scatterAttrs.unselected.marker.opacity, + color: scatterAttrs.unselected.marker.color, + editType: 'style' + }, + textfont: scatterAttrs.unselected.textfont, + editType: 'style' + }, + + r: scatterAttrs.r, + t: scatterAttrs.t, + + _deprecated: { + bardir: { + valType: 'enumerated', + + editType: 'calc', + values: ['v', 'h'], + + } + } +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/font_attributes":771,"../scatter/attributes":1043}],838:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var arraysToCalcdata = _dereq_('./arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); + +module.exports = function calc(gd, trace) { + var xa = Axes.getFromId(gd, trace.xaxis || 'x'); + var ya = Axes.getFromId(gd, trace.yaxis || 'y'); + var size, pos; + + if(trace.orientation === 'h') { + size = xa.makeCalcdata(trace, 'x'); + pos = ya.makeCalcdata(trace, 'y'); + } else { + size = ya.makeCalcdata(trace, 'y'); + pos = xa.makeCalcdata(trace, 'x'); + } + + // create the "calculated data" to plot + var serieslen = Math.min(pos.length, size.length); + var cd = new Array(serieslen); + + // set position and size + for(var i = 0; i < serieslen; i++) { + cd[i] = { p: pos[i], s: size[i] }; + + if(trace.ids) { + cd[i].id = String(trace.ids[i]); + } + } + + // auto-z and autocolorscale if applicable + if(hasColorscale(trace, 'marker')) { + colorscaleCalc(trace, trace.marker.color, 'marker', 'c'); + } + if(hasColorscale(trace, 'marker.line')) { + colorscaleCalc(trace, trace.marker.line.color, 'marker.line', 'c'); + } + + arraysToCalcdata(cd, trace); + calcSelection(cd, trace); + + return cd; +}; + +},{"../../components/colorscale/calc":578,"../../components/colorscale/has_colorscale":584,"../../plots/cartesian/axes":744,"../scatter/calc_selection":1045,"./arrays_to_calcdata":836}],839:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var Registry = _dereq_('../../registry'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Sieve = _dereq_('./sieve.js'); + +/* + * Bar chart stacking/grouping positioning and autoscaling calculations + * for each direction separately calculate the ranges and positions + * note that this handles histograms too + * now doing this one subplot at a time + */ + +function crossTraceCalc(gd, plotinfo) { + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + var fullTraces = gd._fullData, + calcTraces = gd.calcdata, + calcTracesHorizontal = [], + calcTracesVertical = [], + i; + for(i = 0; i < fullTraces.length; i++) { + var fullTrace = fullTraces[i]; + if( + fullTrace.visible === true && + Registry.traceIs(fullTrace, 'bar') && + fullTrace.xaxis === xa._id && + fullTrace.yaxis === ya._id + ) { + if(fullTrace.orientation === 'h') { + calcTracesHorizontal.push(calcTraces[i]); + } + else { + calcTracesVertical.push(calcTraces[i]); + } + } + } + + setGroupPositions(gd, xa, ya, calcTracesVertical); + setGroupPositions(gd, ya, xa, calcTracesHorizontal); +} + +function setGroupPositions(gd, pa, sa, calcTraces) { + if(!calcTraces.length) return; + + var barmode = gd._fullLayout.barmode, + overlay = (barmode === 'overlay'), + group = (barmode === 'group'), + excluded, + included, + i, calcTrace, fullTrace; + + initBase(gd, pa, sa, calcTraces); + + if(overlay) { + setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces); + } + else if(group) { + // exclude from the group those traces for which the user set an offset + excluded = []; + included = []; + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + fullTrace = calcTrace[0].trace; + + if(fullTrace.offset === undefined) included.push(calcTrace); + else excluded.push(calcTrace); + } + + if(included.length) { + setGroupPositionsInGroupMode(gd, pa, sa, included); + } + if(excluded.length) { + setGroupPositionsInOverlayMode(gd, pa, sa, excluded); + } + } + else { + // exclude from the stack those traces for which the user set a base + excluded = []; + included = []; + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + fullTrace = calcTrace[0].trace; + + if(fullTrace.base === undefined) included.push(calcTrace); + else excluded.push(calcTrace); + } + + if(included.length) { + setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included); + } + if(excluded.length) { + setGroupPositionsInOverlayMode(gd, pa, sa, excluded); + } + } + + collectExtents(calcTraces, pa); +} + +function initBase(gd, pa, sa, calcTraces) { + var i, j; + + for(i = 0; i < calcTraces.length; i++) { + var cd = calcTraces[i]; + var trace = cd[0].trace; + var base = trace.base; + var b; + + // not sure if it really makes sense to have dates for bar size data... + // ideally if we want to make gantt charts or something we'd treat + // the actual size (trace.x or y) as time delta but base as absolute + // time. But included here for completeness. + var scalendar = trace.orientation === 'h' ? trace.xcalendar : trace.ycalendar; + + if(isArrayOrTypedArray(base)) { + for(j = 0; j < Math.min(base.length, cd.length); j++) { + b = sa.d2c(base[j], 0, scalendar); + if(isNumeric(b)) { + cd[j].b = +b; + cd[j].hasB = 1; + } + else cd[j].b = 0; + } + for(; j < cd.length; j++) { + cd[j].b = 0; + } + } else { + b = sa.d2c(base, 0, scalendar); + var hasBase = isNumeric(b); + b = hasBase ? b : 0; + for(j = 0; j < cd.length; j++) { + cd[j].b = b; + if(hasBase) cd[j].hasB = 1; + } + } + } +} + + +function setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces) { + var barnorm = gd._fullLayout.barnorm, + separateNegativeValues = false, + dontMergeOverlappingData = !barnorm; + + // update position axis and set bar offsets and widths + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i]; + + var sieve = new Sieve( + [calcTrace], separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidth(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + // + // (note that `setGroupPositionsInOverlayMode` handles the case barnorm + // is defined, because this function is also invoked for traces that + // can't be grouped or stacked) + if(barnorm) { + sieveBars(gd, sa, sieve); + normalizeBars(gd, sa, sieve); + } + else { + setBaseAndTop(gd, sa, sieve); + } + } +} + + +function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces) { + var fullLayout = gd._fullLayout, + barnorm = fullLayout.barnorm, + separateNegativeValues = false, + dontMergeOverlappingData = !barnorm, + sieve = new Sieve( + calcTraces, separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidthInGroupMode(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + if(barnorm) { + sieveBars(gd, sa, sieve); + normalizeBars(gd, sa, sieve); + } + else { + setBaseAndTop(gd, sa, sieve); + } +} + + +function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces) { + var fullLayout = gd._fullLayout, + barmode = fullLayout.barmode, + stack = (barmode === 'stack'), + relative = (barmode === 'relative'), + barnorm = gd._fullLayout.barnorm, + separateNegativeValues = relative, + dontMergeOverlappingData = !(barnorm || stack || relative), + sieve = new Sieve( + calcTraces, separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidth(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + stackBars(gd, sa, sieve); + + // flag the outmost bar (for text display purposes) + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i]; + + for(var j = 0; j < calcTrace.length; j++) { + var bar = calcTrace[j]; + + if(bar.s === BADNUM) continue; + + var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, bar.s)); + if(isOutmostBar) bar._outmost = true; + } + } + + // Note that marking the outmost bars has to be done + // before `normalizeBars` changes `bar.b` and `bar.s`. + if(barnorm) normalizeBars(gd, sa, sieve); +} + + +function setOffsetAndWidth(gd, pa, sieve) { + var fullLayout = gd._fullLayout, + bargap = fullLayout.bargap, + bargroupgap = fullLayout.bargroupgap || 0, + minDiff = sieve.minDiff, + calcTraces = sieve.traces, + i, calcTrace, calcTrace0, + t; + + // set bar offsets and widths + var barGroupWidth = minDiff * (1 - bargap), + barWidthPlusGap = barGroupWidth, + barWidth = barWidthPlusGap * (1 - bargroupgap); + + // computer bar group center and bar offset + var offsetFromCenter = -barWidth / 2; + + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + + // store bar width and offset for this trace + t = calcTrace0.t; + t.barwidth = barWidth; + t.poffset = offsetFromCenter; + t.bargroupwidth = barGroupWidth; + t.bardelta = minDiff; + } + + // stack bars that only differ by rounding + sieve.binWidth = calcTraces[0][0].t.barwidth / 100; + + // if defined, apply trace offset and width + applyAttributes(sieve); + + // store the bar center in each calcdata item + setBarCenterAndWidth(gd, pa, sieve); + + // update position axes + updatePositionAxis(gd, pa, sieve); +} + + +function setOffsetAndWidthInGroupMode(gd, pa, sieve) { + var fullLayout = gd._fullLayout, + bargap = fullLayout.bargap, + bargroupgap = fullLayout.bargroupgap || 0, + positions = sieve.positions, + distinctPositions = sieve.distinctPositions, + minDiff = sieve.minDiff, + calcTraces = sieve.traces, + i, calcTrace, calcTrace0, + t; + + // if there aren't any overlapping positions, + // let them have full width even if mode is group + var overlap = (positions.length !== distinctPositions.length); + + var nTraces = calcTraces.length, + barGroupWidth = minDiff * (1 - bargap), + barWidthPlusGap = (overlap) ? barGroupWidth / nTraces : barGroupWidth, + barWidth = barWidthPlusGap * (1 - bargroupgap); + + for(i = 0; i < nTraces; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + + // computer bar group center and bar offset + var offsetFromCenter = (overlap) ? + ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 : + -barWidth / 2; + + // store bar width and offset for this trace + t = calcTrace0.t; + t.barwidth = barWidth; + t.poffset = offsetFromCenter; + t.bargroupwidth = barGroupWidth; + t.bardelta = minDiff; + } + + // stack bars that only differ by rounding + sieve.binWidth = calcTraces[0][0].t.barwidth / 100; + + // if defined, apply trace width + applyAttributes(sieve); + + // store the bar center in each calcdata item + setBarCenterAndWidth(gd, pa, sieve); + + // update position axes + updatePositionAxis(gd, pa, sieve, overlap); +} + + +function applyAttributes(sieve) { + var calcTraces = sieve.traces, + i, calcTrace, calcTrace0, fullTrace, + j, + t; + + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + fullTrace = calcTrace0.trace; + t = calcTrace0.t; + + var offset = fullTrace._offset || fullTrace.offset, + initialPoffset = t.poffset, + newPoffset; + + if(isArrayOrTypedArray(offset)) { + // if offset is an array, then clone it into t.poffset. + newPoffset = Array.prototype.slice.call(offset, 0, calcTrace.length); + + // guard against non-numeric items + for(j = 0; j < newPoffset.length; j++) { + if(!isNumeric(newPoffset[j])) { + newPoffset[j] = initialPoffset; + } + } + + // if the length of the array is too short, + // then extend it with the initial value of t.poffset + for(j = newPoffset.length; j < calcTrace.length; j++) { + newPoffset.push(initialPoffset); + } + + t.poffset = newPoffset; + } + else if(offset !== undefined) { + t.poffset = offset; + } + + var width = fullTrace._width || fullTrace.width; + var initialBarwidth = t.barwidth; + + if(isArrayOrTypedArray(width)) { + // if width is an array, then clone it into t.barwidth. + var newBarwidth = Array.prototype.slice.call(width, 0, calcTrace.length); + + // guard against non-numeric items + for(j = 0; j < newBarwidth.length; j++) { + if(!isNumeric(newBarwidth[j])) newBarwidth[j] = initialBarwidth; + } + + // if the length of the array is too short, + // then extend it with the initial value of t.barwidth + for(j = newBarwidth.length; j < calcTrace.length; j++) { + newBarwidth.push(initialBarwidth); + } + + t.barwidth = newBarwidth; + + // if user didn't set offset, + // then correct t.poffset to ensure bars remain centered + if(offset === undefined) { + newPoffset = []; + for(j = 0; j < calcTrace.length; j++) { + newPoffset.push( + initialPoffset + (initialBarwidth - newBarwidth[j]) / 2 + ); + } + t.poffset = newPoffset; + } + } + else if(width !== undefined) { + t.barwidth = width; + + // if user didn't set offset, + // then correct t.poffset to ensure bars remain centered + if(offset === undefined) { + t.poffset = initialPoffset + (initialBarwidth - width) / 2; + } + } + } +} + + +function setBarCenterAndWidth(gd, pa, sieve) { + var calcTraces = sieve.traces, + pLetter = getAxisLetter(pa); + + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i], + t = calcTrace[0].t, + poffset = t.poffset, + poffsetIsArray = Array.isArray(poffset), + barwidth = t.barwidth, + barwidthIsArray = Array.isArray(barwidth); + + for(var j = 0; j < calcTrace.length; j++) { + var calcBar = calcTrace[j]; + + // store the actual bar width and position, for use by hover + var width = calcBar.w = (barwidthIsArray) ? barwidth[j] : barwidth; + calcBar[pLetter] = calcBar.p + + ((poffsetIsArray) ? poffset[j] : poffset) + + width / 2; + + + } + } +} + + +function updatePositionAxis(gd, pa, sieve, allowMinDtick) { + var calcTraces = sieve.traces, + distinctPositions = sieve.distinctPositions, + distinctPositions0 = distinctPositions[0], + minDiff = sieve.minDiff, + vpad = minDiff / 2; + + Axes.minDtick(pa, minDiff, distinctPositions0, allowMinDtick); + + // If the user set the bar width or the offset, + // then bars can be shifted away from their positions + // and widths can be larger than minDiff. + // + // Here, we compute pMin and pMax to expand the position axis, + // so that all bars are fully within the axis range. + var pMin = Math.min.apply(Math, distinctPositions) - vpad, + pMax = Math.max.apply(Math, distinctPositions) + vpad; + + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i], + calcTrace0 = calcTrace[0], + fullTrace = calcTrace0.trace; + + if(fullTrace.width === undefined && fullTrace.offset === undefined) { + continue; + } + + var t = calcTrace0.t, + poffset = t.poffset, + barwidth = t.barwidth, + poffsetIsArray = Array.isArray(poffset), + barwidthIsArray = Array.isArray(barwidth); + + for(var j = 0; j < calcTrace.length; j++) { + var calcBar = calcTrace[j], + calcBarOffset = (poffsetIsArray) ? poffset[j] : poffset, + calcBarWidth = (barwidthIsArray) ? barwidth[j] : barwidth, + p = calcBar.p, + l = p + calcBarOffset, + r = l + calcBarWidth; + + pMin = Math.min(pMin, l); + pMax = Math.max(pMax, r); + } + } + + var extremes = Axes.findExtremes(pa, [pMin, pMax], {padded: false}); + putExtremes(calcTraces, pa, extremes); +} + +function expandRange(range, newValue) { + if(isNumeric(range[0])) range[0] = Math.min(range[0], newValue); + else range[0] = newValue; + + if(isNumeric(range[1])) range[1] = Math.max(range[1], newValue); + else range[1] = newValue; +} + +function setBaseAndTop(gd, sa, sieve) { + // store these bar bases and tops in calcdata + // and make sure the size axis includes zero, + // along with the bases and tops of each bar. + var traces = sieve.traces, + sLetter = getAxisLetter(sa), + sRange = [null, null]; + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j], + barBase = bar.b, + barTop = barBase + bar.s; + + bar[sLetter] = barTop; + + if(isNumeric(sa.c2l(barTop))) expandRange(sRange, barTop); + if(bar.hasB && isNumeric(sa.c2l(barBase))) expandRange(sRange, barBase); + } + } + + var extremes = Axes.findExtremes(sa, sRange, {tozero: true, padded: true}); + putExtremes(traces, sa, extremes); +} + + +function stackBars(gd, sa, sieve) { + var fullLayout = gd._fullLayout, + barnorm = fullLayout.barnorm, + sLetter = getAxisLetter(sa), + traces = sieve.traces, + i, trace, + j, bar; + + var sRange = [null, null]; + + for(i = 0; i < traces.length; i++) { + trace = traces[i]; + + for(j = 0; j < trace.length; j++) { + bar = trace[j]; + + if(bar.s === BADNUM) continue; + + // stack current bar and get previous sum + var barBase = sieve.put(bar.p, bar.b + bar.s), + barTop = barBase + bar.b + bar.s; + + // store the bar base and top in each calcdata item + bar.b = barBase; + bar[sLetter] = barTop; + + if(!barnorm) { + if(isNumeric(sa.c2l(barTop))) expandRange(sRange, barTop); + if(bar.hasB && isNumeric(sa.c2l(barBase))) expandRange(sRange, barBase); + } + } + } + + // if barnorm is set, let normalizeBars update the axis range + if(!barnorm) { + var extremes = Axes.findExtremes(sa, sRange, {tozero: true, padded: true}); + putExtremes(traces, sa, extremes); + } +} + + +function sieveBars(gd, sa, sieve) { + var traces = sieve.traces; + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + + if(bar.s !== BADNUM) sieve.put(bar.p, bar.b + bar.s); + } + } +} + + +function normalizeBars(gd, sa, sieve) { + // Note: + // + // normalizeBars requires that either sieveBars or stackBars has been + // previously invoked. + + var traces = sieve.traces, + sLetter = getAxisLetter(sa), + sTop = (gd._fullLayout.barnorm === 'fraction') ? 1 : 100, + sTiny = sTop / 1e9, // in case of rounding error in sum + sMin = sa.l2c(sa.c2l(0)), + sMax = (gd._fullLayout.barmode === 'stack') ? sTop : sMin, + sRange = [sMin, sMax], + padded = false; + + function maybeExpand(newValue) { + if(isNumeric(sa.c2l(newValue)) && + ((newValue < sMin - sTiny) || (newValue > sMax + sTiny) || !isNumeric(sMin)) + ) { + padded = true; + expandRange(sRange, newValue); + } + } + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + + if(bar.s === BADNUM) continue; + + var scale = Math.abs(sTop / sieve.get(bar.p, bar.s)); + bar.b *= scale; + bar.s *= scale; + + var barBase = bar.b, + barTop = barBase + bar.s; + bar[sLetter] = barTop; + + maybeExpand(barTop); + if(bar.hasB) maybeExpand(barBase); + } + } + + // update range of size axis + var extremes = Axes.findExtremes(sa, sRange, {tozero: true, padded: padded}); + putExtremes(traces, sa, extremes); +} + + +function getAxisLetter(ax) { + return ax._id.charAt(0); +} + +function putExtremes(cd, ax, extremes) { + for(var i = 0; i < cd.length; i++) { + cd[i][0].trace._extremes[ax._id] = extremes; + } +} + +// find the full position span of bars at each position +// for use by hover, to ensure labels move in if bars are +// narrower than the space they're in. +// run once per trace group (subplot & direction) and +// the same mapping is attached to all calcdata traces +function collectExtents(calcTraces, pa) { + var posLetter = pa._id.charAt(0); + var extents = {}; + var pMin = Infinity; + var pMax = -Infinity; + + var i, j, cd; + for(i = 0; i < calcTraces.length; i++) { + cd = calcTraces[i]; + for(j = 0; j < cd.length; j++) { + var p = cd[j].p; + if(isNumeric(p)) { + pMin = Math.min(pMin, p); + pMax = Math.max(pMax, p); + } + } + } + + // this is just for positioning of hover labels, and nobody will care if + // the label is 1px too far out; so round positions to 1/10K in case + // position values don't exactly match from trace to trace + var roundFactor = 10000 / (pMax - pMin); + var round = extents.round = function(p) { + return String(Math.round(roundFactor * (p - pMin))); + }; + + var poffset, poffsetIsArray; + + for(i = 0; i < calcTraces.length; i++) { + cd = calcTraces[i]; + cd[0].t.extents = extents; + poffset = cd[0].t.poffset; + poffsetIsArray = Array.isArray(poffset); + + for(j = 0; j < cd.length; j++) { + var di = cd[j]; + var p0 = di[posLetter] - di.w / 2; + + if(isNumeric(p0)) { + var p1 = di[posLetter] + di.w / 2; + var pVal = round(di.p); + if(extents[pVal]) { + extents[pVal] = [Math.min(p0, extents[pVal][0]), Math.max(p1, extents[pVal][1])]; + } else { + extents[pVal] = [p0, p1]; + } + } + + di.p0 = di.p + ((poffsetIsArray) ? poffset[j] : poffset); + di.p1 = di.p0 + di.w; + di.s0 = di.b; + di.s1 = di.s0 + di.s; + } + } +} + +module.exports = { + crossTraceCalc: crossTraceCalc, + setGroupPositions: setGroupPositions +}; + +},{"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axes":744,"../../registry":827,"./sieve.js":848,"fast-isnumeric":214}],840:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var Registry = _dereq_('../../registry'); + +var handleXYDefaults = _dereq_('../scatter/xy_defaults'); +var handleStyleDefaults = _dereq_('../bar/style_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var coerceFont = Lib.coerceFont; + + var len = handleXYDefaults(traceIn, traceOut, layout, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v'); + coerce('base'); + coerce('offset'); + coerce('width'); + + coerce('text'); + coerce('hovertext'); + + var textPosition = coerce('textposition'); + + var hasBoth = Array.isArray(textPosition) || textPosition === 'auto', + hasInside = hasBoth || textPosition === 'inside', + hasOutside = hasBoth || textPosition === 'outside'; + + if(hasInside || hasOutside) { + var textFont = coerceFont(coerce, 'textfont', layout.font); + + // Note that coercing `insidetextfont` is always needed – + // even if `textposition` is `outside` for each trace – since + // an outside label can become an inside one, for example because + // of a bar being stacked on top of it. + var insideTextFontDefault = Lib.extendFlat({}, textFont); + var isTraceTextfontColorSet = traceIn.textfont && traceIn.textfont.color; + var isColorInheritedFromLayoutFont = !isTraceTextfontColorSet; + if(isColorInheritedFromLayoutFont) { + delete insideTextFontDefault.color; + } + coerceFont(coerce, 'insidetextfont', insideTextFontDefault); + + if(hasOutside) coerceFont(coerce, 'outsidetextfont', textFont); + + coerce('constraintext'); + coerce('selected.textfont.color'); + coerce('unselected.textfont.color'); + coerce('cliponaxis'); + } + + handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); + + // override defaultColor for error bars with defaultLine + var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'x', inherit: 'y'}); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../components/color":570,"../../lib":696,"../../registry":827,"../bar/style_defaults":850,"../scatter/xy_defaults":1069,"./attributes":837}],841:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var tinycolor = _dereq_('tinycolor2'); + +exports.coerceString = function(attributeDefinition, value, defaultValue) { + if(typeof value === 'string') { + if(value || !attributeDefinition.noBlank) return value; + } + else if(typeof value === 'number') { + if(!attributeDefinition.strict) return String(value); + } + + return (defaultValue !== undefined) ? + defaultValue : + attributeDefinition.dflt; +}; + +exports.coerceNumber = function(attributeDefinition, value, defaultValue) { + if(isNumeric(value)) { + value = +value; + + var min = attributeDefinition.min, + max = attributeDefinition.max, + isOutOfBounds = (min !== undefined && value < min) || + (max !== undefined && value > max); + + if(!isOutOfBounds) return value; + } + + return (defaultValue !== undefined) ? + defaultValue : + attributeDefinition.dflt; +}; + +exports.coerceColor = function(attributeDefinition, value, defaultValue) { + if(tinycolor(value).isValid()) return value; + + return (defaultValue !== undefined) ? + defaultValue : + attributeDefinition.dflt; +}; + +exports.coerceEnumerated = function(attributeDefinition, value, defaultValue) { + if(attributeDefinition.coerceNumber) value = +value; + + if(attributeDefinition.values.indexOf(value) !== -1) return value; + + return (defaultValue !== undefined) ? + defaultValue : + attributeDefinition.dflt; +}; + +exports.getValue = function(arrayOrScalar, index) { + var value; + if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar; + else if(index < arrayOrScalar.length) value = arrayOrScalar[index]; + return value; +}; + +},{"fast-isnumeric":214,"tinycolor2":514}],842:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = _dereq_('../../components/fx'); +var Registry = _dereq_('../../registry'); +var Color = _dereq_('../../components/color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); + +function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var trace = cd[0].trace; + var t = cd[0].t; + var isClosest = (hovermode === 'closest'); + var maxHoverDistance = pointData.maxHoverDistance; + var maxSpikeDistance = pointData.maxSpikeDistance; + + var posVal, sizeVal, posLetter, sizeLetter, dx, dy, pRangeCalc; + + function thisBarMinPos(di) { return di[posLetter] - di.w / 2; } + function thisBarMaxPos(di) { return di[posLetter] + di.w / 2; } + + var minPos = isClosest ? + thisBarMinPos : + function(di) { + /* + * In compare mode, accept a bar if you're on it *or* its group. + * Nearly always it's the group that matters, but in case the bar + * was explicitly set wider than its group we'd better accept the + * whole bar. + * + * use `bardelta` instead of `bargroupwidth` so we accept hover + * in the gap. That way hover doesn't flash on and off as you + * mouse over the plot in compare modes. + * In 'closest' mode though the flashing seems inevitable, + * without far more complex logic + */ + return Math.min(thisBarMinPos(di), di.p - t.bardelta / 2); + }; + + var maxPos = isClosest ? + thisBarMaxPos : + function(di) { + return Math.max(thisBarMaxPos(di), di.p + t.bardelta / 2); + }; + + function _positionFn(_minPos, _maxPos) { + // add a little to the pseudo-distance for wider bars, so that like scatter, + // if you are over two overlapping bars, the narrower one wins. + return Fx.inbox(_minPos - posVal, _maxPos - posVal, + maxHoverDistance + Math.min(1, Math.abs(_maxPos - _minPos) / pRangeCalc) - 1); + } + + function positionFn(di) { + return _positionFn(minPos(di), maxPos(di)); + } + + function thisBarPositionFn(di) { + return _positionFn(thisBarMinPos(di), thisBarMaxPos(di)); + } + + function sizeFn(di) { + // add a gradient so hovering near the end of a + // bar makes it a little closer match + return Fx.inbox(di.b - sizeVal, di[sizeLetter] - sizeVal, + maxHoverDistance + (di[sizeLetter] - sizeVal) / (di[sizeLetter] - di.b) - 1); + } + + if(trace.orientation === 'h') { + posVal = yval; + sizeVal = xval; + posLetter = 'y'; + sizeLetter = 'x'; + dx = sizeFn; + dy = positionFn; + } + else { + posVal = xval; + sizeVal = yval; + posLetter = 'x'; + sizeLetter = 'y'; + dy = sizeFn; + dx = positionFn; + } + + var pa = pointData[posLetter + 'a']; + var sa = pointData[sizeLetter + 'a']; + + pRangeCalc = Math.abs(pa.r2c(pa.range[1]) - pa.r2c(pa.range[0])); + + function dxy(di) { return (dx(di) + dy(di)) / 2; } + var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); + Fx.getClosest(cd, distfn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index === false) return; + + // if we get here and we're not in 'closest' mode, push min/max pos back + // onto the group - even though that means occasionally the mouse will be + // over the hover label. + if(!isClosest) { + minPos = function(di) { + return Math.min(thisBarMinPos(di), di.p - t.bargroupwidth / 2); + }; + maxPos = function(di) { + return Math.max(thisBarMaxPos(di), di.p + t.bargroupwidth / 2); + }; + } + + // the closest data point + var index = pointData.index; + var di = cd[index]; + + var size = (trace.base) ? di.b + di.s : di.s; + pointData[sizeLetter + '0'] = pointData[sizeLetter + '1'] = sa.c2p(di[sizeLetter], true); + pointData[sizeLetter + 'LabelVal'] = size; + + var extent = t.extents[t.extents.round(di.p)]; + pointData[posLetter + '0'] = pa.c2p(isClosest ? minPos(di) : extent[0], true); + pointData[posLetter + '1'] = pa.c2p(isClosest ? maxPos(di) : extent[1], true); + pointData[posLetter + 'LabelVal'] = di.p; + + // spikelines always want "closest" distance regardless of hovermode + pointData.spikeDistance = (sizeFn(di) + thisBarPositionFn(di)) / 2 + maxSpikeDistance - maxHoverDistance; + // they also want to point to the data value, regardless of where the label goes + // in case of bars shifted within groups + pointData[posLetter + 'Spike'] = pa.c2p(di.p, true); + + pointData.color = getTraceColor(trace, di); + fillHoverText(di, trace, pointData); + Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData); + + return [pointData]; +} + +function getTraceColor(trace, di) { + var mc = di.mcc || trace.marker.color; + var mlc = di.mlcc || trace.marker.line.color; + var mlw = di.mlw || trace.marker.line.width; + + if(Color.opacity(mc)) return mc; + else if(Color.opacity(mlc) && mlw) return mlc; +} + +module.exports = { + hoverPoints: hoverPoints, + getTraceColor: getTraceColor +}; + +},{"../../components/color":570,"../../components/fx":612,"../../registry":827,"../scatter/fill_hover_text":1051}],843:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Bar = {}; + +Bar.attributes = _dereq_('./attributes'); +Bar.layoutAttributes = _dereq_('./layout_attributes'); +Bar.supplyDefaults = _dereq_('./defaults'); +Bar.supplyLayoutDefaults = _dereq_('./layout_defaults'); +Bar.calc = _dereq_('./calc'); +Bar.crossTraceCalc = _dereq_('./cross_trace_calc').crossTraceCalc; +Bar.colorbar = _dereq_('../scatter/marker_colorbar'); +Bar.arraysToCalcdata = _dereq_('./arrays_to_calcdata'); +Bar.plot = _dereq_('./plot'); +Bar.style = _dereq_('./style').style; +Bar.styleOnSelect = _dereq_('./style').styleOnSelect; +Bar.hoverPoints = _dereq_('./hover').hoverPoints; +Bar.selectPoints = _dereq_('./select'); + +Bar.moduleType = 'trace'; +Bar.name = 'bar'; +Bar.basePlotModule = _dereq_('../../plots/cartesian'); +Bar.categories = ['cartesian', 'svg', 'bar', 'oriented', 'errorBarsOK', 'showLegend', 'zoomScale']; +Bar.meta = { + +}; + +module.exports = Bar; + +},{"../../plots/cartesian":756,"../scatter/marker_colorbar":1061,"./arrays_to_calcdata":836,"./attributes":837,"./calc":838,"./cross_trace_calc":839,"./defaults":840,"./hover":842,"./layout_attributes":844,"./layout_defaults":845,"./plot":846,"./select":847,"./style":849}],844:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + barmode: { + valType: 'enumerated', + values: ['stack', 'group', 'overlay', 'relative'], + dflt: 'group', + + editType: 'calc', + + }, + barnorm: { + valType: 'enumerated', + values: ['', 'fraction', 'percent'], + dflt: '', + + editType: 'calc', + + }, + bargap: { + valType: 'number', + min: 0, + max: 1, + + editType: 'calc', + + }, + bargroupgap: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + + editType: 'calc', + + } +}; + +},{}],845:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); + +var layoutAttributes = _dereq_('./layout_attributes'); + + +module.exports = function(layoutIn, layoutOut, fullData) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + + var hasBars = false, + shouldBeGapless = false, + gappedAnyway = false, + usedSubplots = {}; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + if(Registry.traceIs(trace, 'bar') && trace.visible) hasBars = true; + else continue; + + // if we have at least 2 grouped bar traces on the same subplot, + // we should default to a gap anyway, even if the data is histograms + if(layoutIn.barmode !== 'overlay' && layoutIn.barmode !== 'stack') { + var subploti = trace.xaxis + trace.yaxis; + if(usedSubplots[subploti]) gappedAnyway = true; + usedSubplots[subploti] = true; + } + + if(trace.visible && trace.type === 'histogram') { + var pa = Axes.getFromId({_fullLayout: layoutOut}, + trace[trace.orientation === 'v' ? 'xaxis' : 'yaxis']); + if(pa.type !== 'category') shouldBeGapless = true; + } + } + + if(!hasBars) return; + + var mode = coerce('barmode'); + if(mode !== 'overlay') coerce('barnorm'); + + coerce('bargap', (shouldBeGapless && !gappedAnyway) ? 0 : 0.2); + coerce('bargroupgap'); +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../../registry":827,"./layout_attributes":844}],846:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); + +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Registry = _dereq_('../../registry'); + +var attributes = _dereq_('./attributes'), + attributeText = attributes.text, + attributeTextPosition = attributes.textposition; +var helpers = _dereq_('./helpers'); +var style = _dereq_('./style'); + +// padding in pixels around text +var TEXTPAD = 3; + +module.exports = function plot(gd, plotinfo, cdbar, barLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var fullLayout = gd._fullLayout; + + var bartraces = Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + + if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; + + var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); + + var bars = pointGroup.selectAll('g.point').data(Lib.identity); + + bars.enter().append('g') + .classed('point', true); + + bars.exit().remove(); + + bars.each(function(di, i) { + var bar = d3.select(this); + + // now display the bar + // clipped xf/yf (2nd arg true): non-positive + // log values go off-screen by plotwidth + // so you see them continue if you drag the plot + var x0, x1, y0, y1; + if(trace.orientation === 'h') { + y0 = ya.c2p(di.p0, true); + y1 = ya.c2p(di.p1, true); + x0 = xa.c2p(di.s0, true); + x1 = xa.c2p(di.s1, true); + + // for selections + di.ct = [x1, (y0 + y1) / 2]; + } + else { + x0 = xa.c2p(di.p0, true); + x1 = xa.c2p(di.p1, true); + y0 = ya.c2p(di.s0, true); + y1 = ya.c2p(di.s1, true); + + // for selections + di.ct = [(x0 + x1) / 2, y1]; + } + + if(!isNumeric(x0) || !isNumeric(x1) || + !isNumeric(y0) || !isNumeric(y1) || + x0 === x1 || y0 === y1) { + bar.remove(); + return; + } + + var lw = (di.mlw + 1 || trace.marker.line.width + 1 || + (di.trace ? di.trace.marker.line.width : 0) + 1) - 1, + offset = d3.round((lw / 2) % 1, 2); + + function roundWithLine(v) { + // if there are explicit gaps, don't round, + // it can make the gaps look crappy + return (fullLayout.bargap === 0 && fullLayout.bargroupgap === 0) ? + d3.round(Math.round(v) - offset, 2) : v; + } + + function expandToVisible(v, vc) { + // if it's not in danger of disappearing entirely, + // round more precisely + return Math.abs(v - vc) >= 2 ? roundWithLine(v) : + // but if it's very thin, expand it so it's + // necessarily visible, even if it might overlap + // its neighbor + (v > vc ? Math.ceil(v) : Math.floor(v)); + } + + if(!gd._context.staticPlot) { + // if bars are not fully opaque or they have a line + // around them, round to integer pixels, mainly for + // safari so we prevent overlaps from its expansive + // pixelation. if the bars ARE fully opaque and have + // no line, expand to a full pixel to make sure we + // can see them + var op = Color.opacity(di.mc || trace.marker.color), + fixpx = (op < 1 || lw > 0.01) ? + roundWithLine : expandToVisible; + x0 = fixpx(x0, x1); + x1 = fixpx(x1, x0); + y0 = fixpx(y0, y1); + y1 = fixpx(y1, y0); + } + + Lib.ensureSingle(bar, 'path') + .style('vector-effect', 'non-scaling-stroke') + .attr('d', + 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z') + .call(Drawing.setClipUrl, plotinfo.layerClipId); + + appendBarText(gd, bar, cd, i, x0, x1, y0, y1); + + if(plotinfo.layerClipId) { + Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar); + } + }); + + // lastly, clip points groups of `cliponaxis !== false` traces + // on `plotinfo._hasClipOnAxisFalse === true` subplots + var hasClipOnAxisFalse = cd0.trace.cliponaxis === false; + Drawing.setClipUrl(plotGroup, hasClipOnAxisFalse ? null : plotinfo.layerClipId); + }); + + // error bars are on the top + Registry.getComponentMethod('errorbars', 'plot')(bartraces, plotinfo); +}; + +function appendBarText(gd, bar, calcTrace, i, x0, x1, y0, y1) { + var textPosition; + + function appendTextNode(bar, text, textFont) { + var textSelection = Lib.ensureSingle(bar, 'text') + .text(text) + .attr({ + 'class': 'bartext bartext-' + textPosition, + transform: '', + 'text-anchor': 'middle', + // prohibit tex interpretation until we can handle + // tex and regular text together + 'data-notex': 1 + }) + .call(Drawing.font, textFont) + .call(svgTextUtils.convertToTspans, gd); + + return textSelection; + } + + // get trace attributes + var trace = calcTrace[0].trace, + orientation = trace.orientation; + + var text = getText(trace, i); + textPosition = getTextPosition(trace, i); + + if(!text || textPosition === 'none') { + bar.select('text').remove(); + return; + } + + var layoutFont = gd._fullLayout.font; + var barColor = style.getBarColor(calcTrace[i], trace); + var insideTextFont = style.getInsideTextFont(trace, i, layoutFont, barColor); + var outsideTextFont = style.getOutsideTextFont(trace, i, layoutFont); + + // compute text position + var barmode = gd._fullLayout.barmode, + inStackMode = (barmode === 'stack'), + inRelativeMode = (barmode === 'relative'), + inStackOrRelativeMode = inStackMode || inRelativeMode, + + calcBar = calcTrace[i], + isOutmostBar = !inStackOrRelativeMode || calcBar._outmost, + + barWidth = Math.abs(x1 - x0) - 2 * TEXTPAD, // padding excluded + barHeight = Math.abs(y1 - y0) - 2 * TEXTPAD, // padding excluded + + textSelection, + textBB, + textWidth, + textHeight; + + if(textPosition === 'outside') { + if(!isOutmostBar && !calcBar.hasB) textPosition = 'inside'; + } + + if(textPosition === 'auto') { + if(isOutmostBar) { + // draw text using insideTextFont and check if it fits inside bar + textPosition = 'inside'; + textSelection = appendTextNode(bar, text, insideTextFont); + + textBB = Drawing.bBox(textSelection.node()), + textWidth = textBB.width, + textHeight = textBB.height; + + var textHasSize = (textWidth > 0 && textHeight > 0), + fitsInside = + (textWidth <= barWidth && textHeight <= barHeight), + fitsInsideIfRotated = + (textWidth <= barHeight && textHeight <= barWidth), + fitsInsideIfShrunk = (orientation === 'h') ? + (barWidth >= textWidth * (barHeight / textHeight)) : + (barHeight >= textHeight * (barWidth / textWidth)); + if(textHasSize && + (fitsInside || fitsInsideIfRotated || fitsInsideIfShrunk)) { + textPosition = 'inside'; + } + else { + textPosition = 'outside'; + textSelection.remove(); + textSelection = null; + } + } + else textPosition = 'inside'; + } + + if(!textSelection) { + textSelection = appendTextNode(bar, text, + (textPosition === 'outside') ? + outsideTextFont : insideTextFont); + + textBB = Drawing.bBox(textSelection.node()), + textWidth = textBB.width, + textHeight = textBB.height; + + if(textWidth <= 0 || textHeight <= 0) { + textSelection.remove(); + return; + } + } + + // compute text transform + var transform, constrained; + if(textPosition === 'outside') { + constrained = trace.constraintext === 'both' || trace.constraintext === 'outside'; + transform = getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, + orientation, constrained); + } + else { + constrained = trace.constraintext === 'both' || trace.constraintext === 'inside'; + transform = getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, + orientation, constrained); + } + + textSelection.attr('transform', transform); +} + +function getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, orientation, constrained) { + // compute text and target positions + var textWidth = textBB.width, + textHeight = textBB.height, + textX = (textBB.left + textBB.right) / 2, + textY = (textBB.top + textBB.bottom) / 2, + barWidth = Math.abs(x1 - x0), + barHeight = Math.abs(y1 - y0), + targetWidth, + targetHeight, + targetX, + targetY; + + // apply text padding + var textpad; + if(barWidth > (2 * TEXTPAD) && barHeight > (2 * TEXTPAD)) { + textpad = TEXTPAD; + barWidth -= 2 * textpad; + barHeight -= 2 * textpad; + } + else textpad = 0; + + // compute rotation and scale + var rotate, + scale; + + if(textWidth <= barWidth && textHeight <= barHeight) { + // no scale or rotation is required + rotate = false; + scale = 1; + } + else if(textWidth <= barHeight && textHeight <= barWidth) { + // only rotation is required + rotate = true; + scale = 1; + } + else if((textWidth < textHeight) === (barWidth < barHeight)) { + // only scale is required + rotate = false; + scale = constrained ? Math.min(barWidth / textWidth, barHeight / textHeight) : 1; + } + else { + // both scale and rotation are required + rotate = true; + scale = constrained ? Math.min(barHeight / textWidth, barWidth / textHeight) : 1; + } + + if(rotate) rotate = 90; // rotate clockwise + + // compute text and target positions + if(rotate) { + targetWidth = scale * textHeight; + targetHeight = scale * textWidth; + } + else { + targetWidth = scale * textWidth; + targetHeight = scale * textHeight; + } + + if(orientation === 'h') { + if(x1 < x0) { + // bar end is on the left hand side + targetX = x1 + textpad + targetWidth / 2; + targetY = (y0 + y1) / 2; + } + else { + targetX = x1 - textpad - targetWidth / 2; + targetY = (y0 + y1) / 2; + } + } + else { + if(y1 > y0) { + // bar end is on the bottom + targetX = (x0 + x1) / 2; + targetY = y1 - textpad - targetHeight / 2; + } + else { + targetX = (x0 + x1) / 2; + targetY = y1 + textpad + targetHeight / 2; + } + } + + return getTransform(textX, textY, targetX, targetY, scale, rotate); +} + +function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, orientation, constrained) { + var barWidth = (orientation === 'h') ? + Math.abs(y1 - y0) : + Math.abs(x1 - x0), + textpad; + + // Keep the padding so the text doesn't sit right against + // the bars, but don't factor it into barWidth + if(barWidth > 2 * TEXTPAD) { + textpad = TEXTPAD; + } + + // compute rotation and scale + var scale = 1; + if(constrained) { + scale = (orientation === 'h') ? + Math.min(1, barWidth / textBB.height) : + Math.min(1, barWidth / textBB.width); + } + + // compute text and target positions + var textX = (textBB.left + textBB.right) / 2, + textY = (textBB.top + textBB.bottom) / 2, + targetWidth, + targetHeight, + targetX, + targetY; + + targetWidth = scale * textBB.width; + targetHeight = scale * textBB.height; + + if(orientation === 'h') { + if(x1 < x0) { + // bar end is on the left hand side + targetX = x1 - textpad - targetWidth / 2; + targetY = (y0 + y1) / 2; + } + else { + targetX = x1 + textpad + targetWidth / 2; + targetY = (y0 + y1) / 2; + } + } + else { + if(y1 > y0) { + // bar end is on the bottom + targetX = (x0 + x1) / 2; + targetY = y1 + textpad + targetHeight / 2; + } + else { + targetX = (x0 + x1) / 2; + targetY = y1 - textpad - targetHeight / 2; + } + } + + return getTransform(textX, textY, targetX, targetY, scale, false); +} + +function getTransform(textX, textY, targetX, targetY, scale, rotate) { + var transformScale, + transformRotate, + transformTranslate; + + if(scale < 1) transformScale = 'scale(' + scale + ') '; + else { + scale = 1; + transformScale = ''; + } + + transformRotate = (rotate) ? + 'rotate(' + rotate + ' ' + textX + ' ' + textY + ') ' : ''; + + // Note that scaling also affects the center of the text box + var translateX = (targetX - scale * textX), + translateY = (targetY - scale * textY); + transformTranslate = 'translate(' + translateX + ' ' + translateY + ')'; + + return transformTranslate + transformScale + transformRotate; +} + +function getText(trace, index) { + var value = helpers.getValue(trace.text, index); + return helpers.coerceString(attributeText, value); +} + +function getTextPosition(trace, index) { + var value = helpers.getValue(trace.textposition, index); + return helpers.coerceEnumerated(attributeTextPosition, value); +} + +},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../lib/svg_text_utils":720,"../../registry":827,"./attributes":837,"./helpers":841,"./style":849,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],847:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var i; + + if(selectionTester === false) { + // clear selection + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + var di = cd[i]; + + if(selectionTester.contains(di.ct, false, i, searchInfo)) { + selection.push({ + pointNumber: i, + x: xa.c2d(di.x), + y: ya.c2d(di.y) + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + + return selection; +}; + +},{}],848:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = Sieve; + +var Lib = _dereq_('../../lib'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +/** + * Helper class to sieve data from traces into bins + * + * @class + * @param {Array} traces + * Array of calculated traces + * @param {boolean} [separateNegativeValues] + * If true, then split data at the same position into a bar + * for positive values and another for negative values + * @param {boolean} [dontMergeOverlappingData] + * If true, then don't merge overlapping bars into a single bar + */ +function Sieve(traces, separateNegativeValues, dontMergeOverlappingData) { + this.traces = traces; + this.separateNegativeValues = separateNegativeValues; + this.dontMergeOverlappingData = dontMergeOverlappingData; + + // for single-bin histograms - see histogram/calc + var width1 = Infinity; + + var positions = []; + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + if(bar.p !== BADNUM) positions.push(bar.p); + } + if(trace[0] && trace[0].width1) { + width1 = Math.min(trace[0].width1, width1); + } + } + this.positions = positions; + + var dv = Lib.distinctVals(positions); + this.distinctPositions = dv.vals; + if(dv.vals.length === 1 && width1 !== Infinity) this.minDiff = width1; + else this.minDiff = Math.min(dv.minDiff, width1); + + this.binWidth = this.minDiff; + + this.bins = {}; +} + +/** + * Sieve datum + * + * @method + * @param {number} position + * @param {number} value + * @returns {number} Previous bin value + */ +Sieve.prototype.put = function put(position, value) { + var label = this.getLabel(position, value), + oldValue = this.bins[label] || 0; + + this.bins[label] = oldValue + value; + + return oldValue; +}; + +/** + * Get current bin value for a given datum + * + * @method + * @param {number} position Position of datum + * @param {number} [value] Value of datum + * (required if this.separateNegativeValues is true) + * @returns {number} Current bin value + */ +Sieve.prototype.get = function put(position, value) { + var label = this.getLabel(position, value); + return this.bins[label] || 0; +}; + +/** + * Get bin label for a given datum + * + * @method + * @param {number} position Position of datum + * @param {number} [value] Value of datum + * (required if this.separateNegativeValues is true) + * @returns {string} Bin label + * (prefixed with a 'v' if value is negative and this.separateNegativeValues is + * true; otherwise prefixed with '^') + */ +Sieve.prototype.getLabel = function getLabel(position, value) { + var prefix = (value < 0 && this.separateNegativeValues) ? 'v' : '^', + label = (this.dontMergeOverlappingData) ? + position : + Math.round(position / this.binWidth); + return prefix + label; +}; + +},{"../../constants/numerical":673,"../../lib":696}],849:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); + +var attributes = _dereq_('./attributes'), + attributeTextFont = attributes.textfont, + attributeInsideTextFont = attributes.insidetextfont, + attributeOutsideTextFont = attributes.outsidetextfont; +var helpers = _dereq_('./helpers'); + +function style(gd, cd) { + var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.bars'); + var barcount = s.size(); + var fullLayout = gd._fullLayout; + + // trace styling + s.style('opacity', function(d) { return d[0].trace.opacity; }) + + // for gapless (either stacked or neighboring grouped) bars use + // crispEdges to turn off antialiasing so an artificial gap + // isn't introduced. + .each(function(d) { + if((fullLayout.barmode === 'stack' && barcount > 1) || + (fullLayout.bargap === 0 && + fullLayout.bargroupgap === 0 && + !d[0].trace.marker.line.width)) { + d3.select(this).attr('shape-rendering', 'crispEdges'); + } + }); + + s.selectAll('g.points').each(function(d) { + var sel = d3.select(this); + var trace = d[0].trace; + stylePoints(sel, trace, gd); + }); + + Registry.getComponentMethod('errorbars', 'style')(s); +} + +function stylePoints(sel, trace, gd) { + var pts = sel.selectAll('path'); + var txs = sel.selectAll('text'); + + Drawing.pointStyle(pts, trace, gd); + + txs.each(function(d) { + var tx = d3.select(this); + var font = determineFont(tx, d, trace, gd); + Drawing.font(tx, font); + }); +} + +function styleOnSelect(gd, cd) { + var s = cd[0].node3; + var trace = cd[0].trace; + + if(trace.selectedpoints) { + stylePointsInSelectionMode(s, trace, gd); + } else { + stylePoints(s, trace, gd); + } +} + +function stylePointsInSelectionMode(s, trace, gd) { + Drawing.selectedPointStyle(s.selectAll('path'), trace); + styleTextInSelectionMode(s.selectAll('text'), trace, gd); +} + +function styleTextInSelectionMode(txs, trace, gd) { + txs.each(function(d) { + var tx = d3.select(this); + var font; + + if(d.selected) { + font = Lib.extendFlat({}, determineFont(tx, d, trace, gd)); + + var selectedFontColor = trace.selected.textfont && trace.selected.textfont.color; + if(selectedFontColor) { + font.color = selectedFontColor; + } + + Drawing.font(tx, font); + } else { + Drawing.selectedTextStyle(tx, trace); + } + }); +} + +function determineFont(tx, d, trace, gd) { + var layoutFont = gd._fullLayout.font; + var textFont = trace.textfont; + + if(tx.classed('bartext-inside')) { + var barColor = getBarColor(d, trace); + textFont = getInsideTextFont(trace, d.i, layoutFont, barColor); + } else if(tx.classed('bartext-outside')) { + textFont = getOutsideTextFont(trace, d.i, layoutFont); + } + + return textFont; +} + +function getTextFont(trace, index, defaultValue) { + return getFontValue( + attributeTextFont, trace.textfont, index, defaultValue); +} + +function getInsideTextFont(trace, index, layoutFont, barColor) { + var defaultFont = getTextFont(trace, index, layoutFont); + + var wouldFallBackToLayoutFont = + (trace._input.textfont === undefined || trace._input.textfont.color === undefined) || + (Array.isArray(trace.textfont.color) && trace.textfont.color[index] === undefined); + if(wouldFallBackToLayoutFont) { + defaultFont = { + color: Color.contrast(barColor), + family: defaultFont.family, + size: defaultFont.size + }; + } + + return getFontValue( + attributeInsideTextFont, trace.insidetextfont, index, defaultFont); +} + +function getOutsideTextFont(trace, index, layoutFont) { + var defaultFont = getTextFont(trace, index, layoutFont); + return getFontValue( + attributeOutsideTextFont, trace.outsidetextfont, index, defaultFont); +} + +function getFontValue(attributeDefinition, attributeValue, index, defaultValue) { + attributeValue = attributeValue || {}; + + var familyValue = helpers.getValue(attributeValue.family, index), + sizeValue = helpers.getValue(attributeValue.size, index), + colorValue = helpers.getValue(attributeValue.color, index); + + return { + family: helpers.coerceString( + attributeDefinition.family, familyValue, defaultValue.family), + size: helpers.coerceNumber( + attributeDefinition.size, sizeValue, defaultValue.size), + color: helpers.coerceColor( + attributeDefinition.color, colorValue, defaultValue.color) + }; +} + +function getBarColor(cd, trace) { + return cd.mc || trace.marker.color; +} + +module.exports = { + style: style, + styleOnSelect: styleOnSelect, + getInsideTextFont: getInsideTextFont, + getOutsideTextFont: getOutsideTextFont, + getBarColor: getBarColor +}; + +},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../registry":827,"./attributes":837,"./helpers":841,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],850:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../../components/color'); +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); + +module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout) { + coerce('marker.color', defaultColor); + + if(hasColorscale(traceIn, 'marker')) { + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'} + ); + } + + coerce('marker.line.color', Color.defaultLine); + + if(hasColorscale(traceIn, 'marker.line')) { + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'} + ); + } + + coerce('marker.line.width'); + coerce('marker.opacity'); + coerce('selected.marker.color'); + coerce('unselected.marker.color'); +}; + +},{"../../components/color":570,"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584}],851:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var scatterPolarAttrs = _dereq_('../scatterpolar/attributes'); +var barAttrs = _dereq_('../bar/attributes'); + +module.exports = { + r: scatterPolarAttrs.r, + theta: scatterPolarAttrs.theta, + r0: scatterPolarAttrs.r0, + dr: scatterPolarAttrs.dr, + theta0: scatterPolarAttrs.theta0, + dtheta: scatterPolarAttrs.dtheta, + thetaunit: scatterPolarAttrs.thetaunit, + + // orientation: { + // valType: 'enumerated', + // + // values: ['radial', 'angular'], + // editType: 'calc+clearAxisTypes', + // + // }, + + base: extendFlat({}, barAttrs.base, { + + }), + offset: extendFlat({}, barAttrs.offset, { + + }), + width: extendFlat({}, barAttrs.width, { + + }), + + text: extendFlat({}, barAttrs.text, { + + }), + // hovertext: barAttrs.hovertext, + + // textposition: {}, + // textfont: {}, + // insidetextfont: {}, + // outsidetextfont: {}, + // constraintext: {}, + // cliponaxis: extendFlat({}, barAttrs.cliponaxis, {dflt: false}), + + marker: barAttrs.marker, + + hoverinfo: scatterPolarAttrs.hoverinfo, + + selected: barAttrs.selected, + unselected: barAttrs.unselected + + // error_x (error_r, error_theta) + // error_y +}; + +},{"../../lib/extend":685,"../bar/attributes":837,"../scatterpolar/attributes":1105}],852:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var arraysToCalcdata = _dereq_('../bar/arrays_to_calcdata'); +var setGroupPositions = _dereq_('../bar/cross_trace_calc').setGroupPositions; +var calcSelection = _dereq_('../scatter/calc_selection'); +var traceIs = _dereq_('../../registry').traceIs; +var extendFlat = _dereq_('../../lib').extendFlat; + +function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var subplotId = trace.subplot; + var radialAxis = fullLayout[subplotId].radialaxis; + var angularAxis = fullLayout[subplotId].angularaxis; + var rArray = radialAxis.makeCalcdata(trace, 'r'); + var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); + var len = trace._length; + var cd = new Array(len); + + // 'size' axis variables + var sArray = rArray; + // 'pos' axis variables + var pArray = thetaArray; + + for(var i = 0; i < len; i++) { + cd[i] = {p: pArray[i], s: sArray[i]}; + } + + // convert width and offset in 'c' coordinate, + // set 'c' value(s) in trace._width and trace._offset, + // to make Bar.crossTraceCalc "just work" + function d2c(attr) { + var val = trace[attr]; + if(val !== undefined) { + trace['_' + attr] = Array.isArray(val) ? + angularAxis.makeCalcdata(trace, attr) : + angularAxis.d2c(val, trace.thetaunit); + } + } + + if(angularAxis.type === 'linear') { + d2c('width'); + d2c('offset'); + } + + if(hasColorscale(trace, 'marker')) { + colorscaleCalc(trace, trace.marker.color, 'marker', 'c'); + } + if(hasColorscale(trace, 'marker.line')) { + colorscaleCalc(trace, trace.marker.line.color, 'marker.line', 'c'); + } + + arraysToCalcdata(cd, trace); + calcSelection(cd, trace); + + return cd; +} + +function crossTraceCalc(gd, polarLayout, subplotId) { + var calcdata = gd.calcdata; + var barPolarCd = []; + + for(var i = 0; i < calcdata.length; i++) { + var cdi = calcdata[i]; + var trace = cdi[0].trace; + + if(trace.visible === true && traceIs(trace, 'bar') && + trace.subplot === subplotId + ) { + barPolarCd.push(cdi); + } + } + + // to make _extremes is filled in correctly so that + // polar._subplot.radialAxis can get auotrange'd + // TODO clean up! + // I think we want to call getAutorange on polar.radialaxis + // NOT on polar._subplot.radialAxis + var rAxis = extendFlat({}, polarLayout.radialaxis, {_id: 'x'}); + var aAxis = polarLayout.angularaxis; + + // 'bargap', 'barmode' are in _fullLayout.polar + // TODO clean up setGroupPositions API instead + var mockGd = {_fullLayout: polarLayout}; + + setGroupPositions(mockGd, aAxis, rAxis, barPolarCd); +} + +module.exports = { + calc: calc, + crossTraceCalc: crossTraceCalc +}; + +},{"../../components/colorscale/calc":578,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../registry":827,"../bar/arrays_to_calcdata":836,"../bar/cross_trace_calc":839,"../scatter/calc_selection":1045}],853:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleRThetaDefaults = _dereq_('../scatterpolar/defaults').handleRThetaDefaults; +var handleStyleDefaults = _dereq_('../bar/style_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + // coerce('orientation', (traceOut.theta && !traceOut.r) ? 'angular' : 'radial'); + + coerce('thetaunit'); + coerce('base'); + coerce('offset'); + coerce('width'); + + coerce('text'); + // coerce('hovertext'); + + // var textPosition = coerce('textposition'); + // var hasBoth = Array.isArray(textPosition) || textPosition === 'auto'; + // var hasInside = hasBoth || textPosition === 'inside'; + // var hasOutside = hasBoth || textPosition === 'outside'; + + // if(hasInside || hasOutside) { + // var textFont = coerceFont(coerce, 'textfont', layout.font); + // if(hasInside) coerceFont(coerce, 'insidetextfont', textFont); + // if(hasOutside) coerceFont(coerce, 'outsidetextfont', textFont); + // coerce('constraintext'); + // coerce('selected.textfont.color'); + // coerce('unselected.textfont.color'); + // coerce('cliponaxis'); + // } + + handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../bar/style_defaults":850,"../scatterpolar/defaults":1107,"./attributes":851}],854:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Fx = _dereq_('../../components/fx'); +var Lib = _dereq_('../../lib'); +var getTraceColor = _dereq_('../bar/hover').getTraceColor; +var fillHoverText = _dereq_('../scatter/fill_hover_text'); +var makeHoverPointText = _dereq_('../scatterpolar/hover').makeHoverPointText; +var isPtInsidePolygon = _dereq_('../../plots/polar/helpers').isPtInsidePolygon; + +module.exports = function hoverPoints(pointData, xval, yval) { + var cd = pointData.cd; + var trace = cd[0].trace; + + var subplot = pointData.subplot; + var radialAxis = subplot.radialAxis; + var angularAxis = subplot.angularAxis; + var vangles = subplot.vangles; + var inboxFn = vangles ? isPtInsidePolygon : Lib.isPtInsideSector; + var maxHoverDistance = pointData.maxHoverDistance; + var period = angularAxis._period || 2 * Math.PI; + + var rVal = Math.abs(radialAxis.g2p(Math.sqrt(xval * xval + yval * yval))); + var thetaVal = Math.atan2(yval, xval); + + // polar.(x|y)axis.p2c doesn't get the reversed radial axis range case right + if(radialAxis.range[0] > radialAxis.range[1]) { + thetaVal += Math.PI; + } + + var distFn = function(di) { + if(inboxFn(rVal, thetaVal, [di.rp0, di.rp1], [di.thetag0, di.thetag1], vangles)) { + return maxHoverDistance + + // add a little to the pseudo-distance for wider bars, so that like scatter, + // if you are over two overlapping bars, the narrower one wins. + Math.min(1, Math.abs(di.thetag1 - di.thetag0) / period) - 1 + + // add a gradient so hovering near the end of a + // bar makes it a little closer match + (di.rp1 - rVal) / (di.rp1 - di.rp0) - 1; + } else { + return Infinity; + } + }; + + Fx.getClosest(cd, distFn, pointData); + if(pointData.index === false) return; + + var index = pointData.index; + var cdi = cd[index]; + + pointData.x0 = pointData.x1 = cdi.ct[0]; + pointData.y0 = pointData.y1 = cdi.ct[1]; + + var _cdi = Lib.extendFlat({}, cdi, {r: cdi.s, theta: cdi.p}); + fillHoverText(cdi, trace, pointData); + makeHoverPointText(_cdi, trace, subplot, pointData); + pointData.color = getTraceColor(trace, cdi); + pointData.xLabelVal = pointData.yLabelVal = undefined; + + if(cdi.s < 0) { + pointData.idealAlign = 'left'; + } + + return [pointData]; +}; + +},{"../../components/fx":612,"../../lib":696,"../../plots/polar/helpers":810,"../bar/hover":842,"../scatter/fill_hover_text":1051,"../scatterpolar/hover":1108}],855:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'barpolar', + basePlotModule: _dereq_('../../plots/polar'), + categories: ['polar', 'bar', 'showLegend'], + + attributes: _dereq_('./attributes'), + layoutAttributes: _dereq_('./layout_attributes'), + supplyDefaults: _dereq_('./defaults'), + supplyLayoutDefaults: _dereq_('./layout_defaults'), + + calc: _dereq_('./calc').calc, + crossTraceCalc: _dereq_('./calc').crossTraceCalc, + + plot: _dereq_('./plot'), + colorbar: _dereq_('../scatter/marker_colorbar'), + style: _dereq_('../bar/style').style, + + hoverPoints: _dereq_('./hover'), + selectPoints: _dereq_('../bar/select'), + + meta: { + + + } +}; + +},{"../../plots/polar":811,"../bar/select":847,"../bar/style":849,"../scatter/marker_colorbar":1061,"./attributes":851,"./calc":852,"./defaults":853,"./hover":854,"./layout_attributes":856,"./layout_defaults":857,"./plot":858}],856:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + barmode: { + valType: 'enumerated', + values: ['stack', 'overlay'], + dflt: 'stack', + + editType: 'calc', + + }, + bargap: { + valType: 'number', + dflt: 0.1, + min: 0, + max: 1, + + editType: 'calc', + + } +}; + +},{}],857:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attrs = _dereq_('./layout_attributes'); + +module.exports = function(layoutIn, layoutOut, fullData) { + var subplotsDone = {}; + var sp; + + function coerce(attr, dflt) { + return Lib.coerce(layoutIn[sp] || {}, layoutOut[sp], attrs, attr, dflt); + } + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + if(trace.type === 'barpolar' && trace.visible === true) { + sp = trace.subplot; + if(!subplotsDone[sp]) { + coerce('barmode'); + coerce('bargap'); + subplotsDone[sp] = 1; + } + } + } +}; + +},{"../../lib":696,"./layout_attributes":856}],858:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); +var helpers = _dereq_('../../plots/polar/helpers'); + +module.exports = function plot(gd, subplot, cdbar) { + var xa = subplot.xaxis; + var ya = subplot.yaxis; + var radialAxis = subplot.radialAxis; + var angularAxis = subplot.angularAxis; + var pathFn = makePathFn(subplot); + var barLayer = subplot.layers.frontplot.select('g.barlayer'); + + Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function(cd) { + var plotGroup = cd[0].node3 = d3.select(this); + var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); + var bars = pointGroup.selectAll('g.point').data(Lib.identity); + + bars.enter().append('g') + .style('vector-effect', 'non-scaling-stroke') + .style('stroke-miterlimit', 2) + .classed('point', true); + + bars.exit().remove(); + + bars.each(function(di) { + var bar = d3.select(this); + + var rp0 = di.rp0 = radialAxis.c2p(di.s0); + var rp1 = di.rp1 = radialAxis.c2p(di.s1); + var thetag0 = di.thetag0 = angularAxis.c2g(di.p0); + var thetag1 = di.thetag1 = angularAxis.c2g(di.p1); + + var dPath; + + if(!isNumeric(rp0) || !isNumeric(rp1) || + !isNumeric(thetag0) || !isNumeric(thetag1) || + rp0 === rp1 || thetag0 === thetag1 + ) { + // do not remove blank bars, to keep data-to-node + // mapping intact during radial drag, that we + // can skip calling _module.style during interactions + dPath = 'M0,0Z'; + } else { + // this 'center' pt is used for selections and hover labels + var rg1 = radialAxis.c2g(di.s1); + var thetagMid = (thetag0 + thetag1) / 2; + di.ct = [ + xa.c2p(rg1 * Math.cos(thetagMid)), + ya.c2p(rg1 * Math.sin(thetagMid)) + ]; + + dPath = pathFn(rp0, rp1, thetag0, thetag1); + } + + Lib.ensureSingle(bar, 'path').attr('d', dPath); + }); + + // clip plotGroup, when trace layer isn't clipped + Drawing.setClipUrl(plotGroup, subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null); + }); +}; + +function makePathFn(subplot) { + var cxx = subplot.cxx; + var cyy = subplot.cyy; + + if(subplot.vangles) { + return function(r0, r1, _a0, _a1) { + var a0, a1; + + if(Lib.angleDelta(_a0, _a1) > 0) { + a0 = _a0; + a1 = _a1; + } else { + a0 = _a1; + a1 = _a0; + } + + var va0 = helpers.findEnclosingVertexAngles(a0, subplot.vangles)[0]; + var va1 = helpers.findEnclosingVertexAngles(a1, subplot.vangles)[1]; + var vaBar = [va0, (a0 + a1) / 2, va1]; + return helpers.pathPolygonAnnulus(r0, r1, a0, a1, vaBar, cxx, cyy); + }; + } + + return function(r0, r1, a0, a1) { + return Lib.pathAnnulus(r0, r1, a0, a1, cxx, cyy); + }; +} + +},{"../../components/drawing":595,"../../lib":696,"../../plots/polar/helpers":810,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],859:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +module.exports = { + y: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + x0: { + valType: 'any', + + editType: 'calc+clearAxisTypes', + + }, + y0: { + valType: 'any', + + editType: 'calc+clearAxisTypes', + + }, + name: { + valType: 'string', + + editType: 'calc+clearAxisTypes', + + }, + text: extendFlat({}, scatterAttrs.text, { + + }), + whiskerwidth: { + valType: 'number', + min: 0, + max: 1, + dflt: 0.5, + + editType: 'calc', + + }, + notched: { + valType: 'boolean', + + editType: 'calc', + + }, + notchwidth: { + valType: 'number', + min: 0, + max: 0.5, + dflt: 0.25, + + editType: 'calc', + + }, + boxpoints: { + valType: 'enumerated', + values: ['all', 'outliers', 'suspectedoutliers', false], + dflt: 'outliers', + + editType: 'calc', + + }, + boxmean: { + valType: 'enumerated', + values: [true, 'sd', false], + dflt: false, + + editType: 'calc', + + }, + jitter: { + valType: 'number', + min: 0, + max: 1, + + editType: 'calc', + + }, + pointpos: { + valType: 'number', + min: -2, + max: 2, + + editType: 'calc', + + }, + orientation: { + valType: 'enumerated', + values: ['v', 'h'], + + editType: 'calc+clearAxisTypes', + + }, + marker: { + outliercolor: { + valType: 'color', + dflt: 'rgba(0, 0, 0, 0)', + + editType: 'style', + + }, + symbol: extendFlat({}, scatterMarkerAttrs.symbol, + {arrayOk: false, editType: 'plot'}), + opacity: extendFlat({}, scatterMarkerAttrs.opacity, + {arrayOk: false, dflt: 1, editType: 'style'}), + size: extendFlat({}, scatterMarkerAttrs.size, + {arrayOk: false, editType: 'calc'}), + color: extendFlat({}, scatterMarkerAttrs.color, + {arrayOk: false, editType: 'style'}), + line: { + color: extendFlat({}, scatterMarkerLineAttrs.color, + {arrayOk: false, dflt: colorAttrs.defaultLine, editType: 'style'} + ), + width: extendFlat({}, scatterMarkerLineAttrs.width, + {arrayOk: false, dflt: 0, editType: 'style'} + ), + outliercolor: { + valType: 'color', + + editType: 'style', + + }, + outlierwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'style', + + }, + editType: 'style' + }, + editType: 'plot' + }, + line: { + color: { + valType: 'color', + + editType: 'style', + + }, + width: { + valType: 'number', + + min: 0, + dflt: 2, + editType: 'style', + + }, + editType: 'plot' + }, + fillcolor: scatterAttrs.fillcolor, + + selected: { + marker: scatterAttrs.selected.marker, + editType: 'style' + }, + unselected: { + marker: scatterAttrs.unselected.marker, + editType: 'style' + }, + + hoveron: { + valType: 'flaglist', + flags: ['boxes', 'points'], + dflt: 'boxes+points', + + editType: 'style', + + } +}; + +},{"../../components/color/attributes":569,"../../lib/extend":685,"../scatter/attributes":1043}],860:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var _ = Lib._; +var Axes = _dereq_('../../plots/cartesian/axes'); + +// outlier definition based on http://www.physics.csbsju.edu/stats/box2.html +module.exports = function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var xa = Axes.getFromId(gd, trace.xaxis || 'x'); + var ya = Axes.getFromId(gd, trace.yaxis || 'y'); + var cd = []; + + // N.B. violin reuses same Box.calc + var numKey = trace.type === 'violin' ? '_numViolins' : '_numBoxes'; + + var i; + var valAxis, valLetter; + var posAxis, posLetter; + + if(trace.orientation === 'h') { + valAxis = xa; + valLetter = 'x'; + posAxis = ya; + posLetter = 'y'; + } else { + valAxis = ya; + valLetter = 'y'; + posAxis = xa; + posLetter = 'x'; + } + + var val = valAxis.makeCalcdata(trace, valLetter); + var pos = getPos(trace, posLetter, posAxis, val, fullLayout[numKey]); + + var dv = Lib.distinctVals(pos); + var posDistinct = dv.vals; + var dPos = dv.minDiff / 2; + var posBins = makeBins(posDistinct, dPos); + + var pLen = posDistinct.length; + var ptsPerBin = initNestedArray(pLen); + + // bin pts info per position bins + for(i = 0; i < trace._length; i++) { + var v = val[i]; + if(!isNumeric(v)) continue; + + var n = Lib.findBin(pos[i], posBins); + if(n >= 0 && n < pLen) { + var pt = {v: v, i: i}; + arraysToCalcdata(pt, trace, i); + ptsPerBin[n].push(pt); + } + } + + // build calcdata trace items, one item per distinct position + for(i = 0; i < pLen; i++) { + if(ptsPerBin[i].length > 0) { + var pts = ptsPerBin[i].sort(sortByVal); + var boxVals = pts.map(extractVal); + var bvLen = boxVals.length; + + var cdi = { + pos: posDistinct[i], + pts: pts + }; + + cdi.min = boxVals[0]; + cdi.max = boxVals[bvLen - 1]; + cdi.mean = Lib.mean(boxVals, bvLen); + cdi.sd = Lib.stdev(boxVals, bvLen, cdi.mean); + + // first quartile + cdi.q1 = Lib.interp(boxVals, 0.25); + // median + cdi.med = Lib.interp(boxVals, 0.5); + // third quartile + cdi.q3 = Lib.interp(boxVals, 0.75); + + // lower and upper fences - last point inside + // 1.5 interquartile ranges from quartiles + cdi.lf = Math.min( + cdi.q1, + boxVals[Math.min( + Lib.findBin(2.5 * cdi.q1 - 1.5 * cdi.q3, boxVals, true) + 1, + bvLen - 1 + )] + ); + cdi.uf = Math.max( + cdi.q3, + boxVals[Math.max( + Lib.findBin(2.5 * cdi.q3 - 1.5 * cdi.q1, boxVals), + 0 + )] + ); + + // lower and upper outliers - 3 IQR out (don't clip to max/min, + // this is only for discriminating suspected & far outliers) + cdi.lo = 4 * cdi.q1 - 3 * cdi.q3; + cdi.uo = 4 * cdi.q3 - 3 * cdi.q1; + + + // lower and upper notches ~95% Confidence Intervals for median + var iqr = cdi.q3 - cdi.q1; + var mci = 1.57 * iqr / Math.sqrt(bvLen); + cdi.ln = cdi.med - mci; + cdi.un = cdi.med + mci; + + cd.push(cdi); + } + } + + calcSelection(cd, trace); + var extremes = Axes.findExtremes(valAxis, val, {padded: true}); + trace._extremes[valAxis._id] = extremes; + + if(cd.length > 0) { + cd[0].t = { + num: fullLayout[numKey], + dPos: dPos, + posLetter: posLetter, + valLetter: valLetter, + labels: { + med: _(gd, 'median:'), + min: _(gd, 'min:'), + q1: _(gd, 'q1:'), + q3: _(gd, 'q3:'), + max: _(gd, 'max:'), + mean: trace.boxmean === 'sd' ? _(gd, 'mean ± σ:') : _(gd, 'mean:'), + lf: _(gd, 'lower fence:'), + uf: _(gd, 'upper fence:') + } + }; + + fullLayout[numKey]++; + return cd; + } else { + return [{t: {empty: true}}]; + } +}; + +// In vertical (horizontal) box plots: +// if no x (y) data, use x0 (y0), or name +// so if you want one box +// per trace, set x0 (y0) to the x (y) value or category for this trace +// (or set x (y) to a constant array matching y (x)) +function getPos(trace, posLetter, posAxis, val, num) { + if(posLetter in trace) { + return posAxis.makeCalcdata(trace, posLetter); + } + + var pos0; + + if(posLetter + '0' in trace) { + pos0 = trace[posLetter + '0']; + } else if('name' in trace && ( + posAxis.type === 'category' || ( + isNumeric(trace.name) && + ['linear', 'log'].indexOf(posAxis.type) !== -1 + ) || ( + Lib.isDateTime(trace.name) && + posAxis.type === 'date' + ) + )) { + pos0 = trace.name; + } else { + pos0 = num; + } + + var pos0c = posAxis.d2c(pos0, 0, trace[posLetter + 'calendar']); + return val.map(function() { return pos0c; }); +} + +function makeBins(x, dx) { + var len = x.length; + var bins = new Array(len + 1); + + for(var i = 0; i < len; i++) { + bins[i] = x[i] - dx; + } + bins[len] = x[len - 1] + dx; + + return bins; +} + +function initNestedArray(len) { + var arr = new Array(len); + for(var i = 0; i < len; i++) { + arr[i] = []; + } + return arr; +} + +function arraysToCalcdata(pt, trace, i) { + var trace2calc = { + text: 'tx' + }; + + for(var k in trace2calc) { + if(Array.isArray(trace[k])) { + pt[trace2calc[k]] = trace[k][i]; + } + } +} + +function calcSelection(cd, trace) { + if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { + for(var i = 0; i < cd.length; i++) { + var pts = cd[i].pts || []; + var ptNumber2cdIndex = {}; + + for(var j = 0; j < pts.length; j++) { + ptNumber2cdIndex[pts[j].i] = j; + } + + Lib.tagSelected(pts, trace, ptNumber2cdIndex); + } + } +} + +function sortByVal(a, b) { return a.v - b.v; } + +function extractVal(o) { return o.v; } + +},{"../../lib":696,"../../plots/cartesian/axes":744,"fast-isnumeric":214}],861:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); + +var orientations = ['v', 'h']; + +function crossTraceCalc(gd, plotinfo) { + var calcdata = gd.calcdata; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + for(var i = 0; i < orientations.length; i++) { + var orientation = orientations[i]; + var posAxis = orientation === 'h' ? ya : xa; + var boxList = []; + var minPad = 0; + var maxPad = 0; + + // make list of boxes / candlesticks + // For backward compatibility, candlesticks are treated as if they *are* box traces here + for(var j = 0; j < calcdata.length; j++) { + var cd = calcdata[j]; + var t = cd[0].t; + var trace = cd[0].trace; + + if(trace.visible === true && + (trace.type === 'box' || trace.type === 'candlestick') && + !t.empty && + (trace.orientation || 'v') === orientation && + trace.xaxis === xa._id && + trace.yaxis === ya._id + ) { + boxList.push(j); + + if(trace.boxpoints) { + minPad = Math.max(minPad, trace.jitter - trace.pointpos - 1); + maxPad = Math.max(maxPad, trace.jitter + trace.pointpos - 1); + } + } + } + + setPositionOffset('box', gd, boxList, posAxis, [minPad, maxPad]); + } +} + +function setPositionOffset(traceType, gd, boxList, posAxis, pad) { + var calcdata = gd.calcdata; + var fullLayout = gd._fullLayout; + var pointList = []; + + // N.B. reused in violin + var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes'; + + var i, j, calcTrace; + + // make list of box points + for(i = 0; i < boxList.length; i++) { + calcTrace = calcdata[boxList[i]]; + for(j = 0; j < calcTrace.length; j++) { + pointList.push(calcTrace[j].pos); + } + } + + if(!pointList.length) return; + + // box plots - update dPos based on multiple traces + // and then use for posAxis autorange + var boxdv = Lib.distinctVals(pointList); + var dPos = boxdv.minDiff / 2; + + // if there's no duplication of x points, + // disable 'group' mode by setting counter to 1 + if(pointList.length === boxdv.vals.length) { + fullLayout[numKey] = 1; + } + + // check for forced minimum dtick + Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true); + + var gap = fullLayout[traceType + 'gap']; + var groupgap = fullLayout[traceType + 'groupgap']; + var padfactor = (1 - gap) * (1 - groupgap) * dPos / fullLayout[numKey]; + + // autoscale the x axis - including space for points if they're off the side + // TODO: this will overdo it if the outermost boxes don't have + // their points as far out as the other boxes + var extremes = Axes.findExtremes(posAxis, boxdv.vals, { + vpadminus: dPos + pad[0] * padfactor, + vpadplus: dPos + pad[1] * padfactor + }); + + for(i = 0; i < boxList.length; i++) { + calcTrace = calcdata[boxList[i]]; + // set the width of all boxes + calcTrace[0].t.dPos = dPos; + // link extremes to all boxes + calcTrace[0].trace._extremes[posAxis._id] = extremes; + } + +} + +module.exports = { + crossTraceCalc: crossTraceCalc, + setPositionOffset: setPositionOffset +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744}],862:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); +var Color = _dereq_('../../components/color'); + +var attributes = _dereq_('./attributes'); + +function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + handleSampleDefaults(traceIn, traceOut, coerce, layout); + if(traceOut.visible === false) return; + + coerce('line.color', (traceIn.marker || {}).color || defaultColor); + coerce('line.width'); + coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5)); + + coerce('whiskerwidth'); + coerce('boxmean'); + + var notched = coerce('notched', traceIn.notchwidth !== undefined); + if(notched) coerce('notchwidth'); + + handlePointsDefaults(traceIn, traceOut, coerce, {prefix: 'box'}); +} + +function handleSampleDefaults(traceIn, traceOut, coerce, layout) { + var y = coerce('y'); + var x = coerce('x'); + var hasX = x && x.length; + + var defaultOrientation, len; + + if(y && y.length) { + defaultOrientation = 'v'; + if(hasX) { + len = Math.min(x.length, y.length); + } + else { + coerce('x0'); + len = y.length; + } + } else if(hasX) { + defaultOrientation = 'h'; + coerce('y0'); + len = x.length; + } else { + traceOut.visible = false; + return; + } + traceOut._length = len; + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); + + coerce('orientation', defaultOrientation); +} + +function handlePointsDefaults(traceIn, traceOut, coerce, opts) { + var prefix = opts.prefix; + + var outlierColorDflt = Lib.coerce2(traceIn, traceOut, attributes, 'marker.outliercolor'); + var lineoutliercolor = coerce('marker.line.outliercolor'); + + var points = coerce( + prefix + 'points', + (outlierColorDflt || lineoutliercolor) ? 'suspectedoutliers' : undefined + ); + + if(points) { + coerce('jitter', points === 'all' ? 0.3 : 0); + coerce('pointpos', points === 'all' ? -1.5 : 0); + + coerce('marker.symbol'); + coerce('marker.opacity'); + coerce('marker.size'); + coerce('marker.color', traceOut.line.color); + coerce('marker.line.color'); + coerce('marker.line.width'); + + if(points === 'suspectedoutliers') { + coerce('marker.line.outliercolor', traceOut.marker.color); + coerce('marker.line.outlierwidth'); + } + + coerce('selected.marker.color'); + coerce('unselected.marker.color'); + coerce('selected.marker.size'); + coerce('unselected.marker.size'); + + coerce('text'); + } else { + delete traceOut.marker; + } + + coerce('hoveron'); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +} + +module.exports = { + supplyDefaults: supplyDefaults, + handleSampleDefaults: handleSampleDefaults, + handlePointsDefaults: handlePointsDefaults +}; + +},{"../../components/color":570,"../../lib":696,"../../registry":827,"./attributes":859}],863:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function eventData(out, pt) { + + // Note: hoverOnBox property is needed for click-to-select + // to ignore when a box was clicked. This is the reason box + // implements this custom eventData function. + if(pt.hoverOnBox) out.hoverOnBox = pt.hoverOnBox; + + if('xVal' in pt) out.x = pt.xVal; + if('yVal' in pt) out.y = pt.yVal; + if(pt.xa) out.xaxis = pt.xa; + if(pt.ya) out.yaxis = pt.ya; + + return out; +}; + +},{}],864:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); +var Fx = _dereq_('../../components/fx'); +var Color = _dereq_('../../components/color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); + +function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var trace = cd[0].trace; + var hoveron = trace.hoveron; + var closeBoxData = []; + var closePtData; + + if(hoveron.indexOf('boxes') !== -1) { + closeBoxData = closeBoxData.concat(hoverOnBoxes(pointData, xval, yval, hovermode)); + } + + if(hoveron.indexOf('points') !== -1) { + closePtData = hoverOnPoints(pointData, xval, yval); + } + + // If there's a point in range and hoveron has points, show the best single point only. + // If hoveron has boxes and there's no point in range (or hoveron doesn't have points), show the box stats. + if(hovermode === 'closest') { + if(closePtData) return [closePtData]; + return closeBoxData; + } + + // Otherwise in compare mode, allow a point AND the box stats to be labeled + // If there are multiple boxes in range (ie boxmode = 'overlay') we'll see stats for all of them. + if(closePtData) { + closeBoxData.push(closePtData); + return closeBoxData; + } + return closeBoxData; +} + +function hoverOnBoxes(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var xa = pointData.xa; + var ya = pointData.ya; + var trace = cd[0].trace; + var t = cd[0].t; + var isViolin = trace.type === 'violin'; + var closeBoxData = []; + + var pLetter, vLetter, pAxis, vAxis, vVal, pVal, dx, dy, dPos, + hoverPseudoDistance, spikePseudoDistance; + + var boxDelta = t.bdPos; + var posAcceptance = t.wHover; + var shiftPos = function(di) { return di.pos + t.bPos - pVal; }; + + if(isViolin && trace.side !== 'both') { + if(trace.side === 'positive') { + dPos = function(di) { + var pos = shiftPos(di); + return Fx.inbox(pos, pos + posAcceptance, hoverPseudoDistance); + }; + } + if(trace.side === 'negative') { + dPos = function(di) { + var pos = shiftPos(di); + return Fx.inbox(pos - posAcceptance, pos, hoverPseudoDistance); + }; + } + } else { + dPos = function(di) { + var pos = shiftPos(di); + return Fx.inbox(pos - posAcceptance, pos + posAcceptance, hoverPseudoDistance); + }; + } + + var dVal; + + if(isViolin) { + dVal = function(di) { + return Fx.inbox(di.span[0] - vVal, di.span[1] - vVal, hoverPseudoDistance); + }; + } else { + dVal = function(di) { + return Fx.inbox(di.min - vVal, di.max - vVal, hoverPseudoDistance); + }; + } + + if(trace.orientation === 'h') { + vVal = xval; + pVal = yval; + dx = dVal; + dy = dPos; + pLetter = 'y'; + pAxis = ya; + vLetter = 'x'; + vAxis = xa; + } else { + vVal = yval; + pVal = xval; + dx = dPos; + dy = dVal; + pLetter = 'x'; + pAxis = xa; + vLetter = 'y'; + vAxis = ya; + } + + // if two boxes are overlaying, let the narrowest one win + var pseudoDistance = Math.min(1, boxDelta / Math.abs(pAxis.r2c(pAxis.range[1]) - pAxis.r2c(pAxis.range[0]))); + hoverPseudoDistance = pointData.maxHoverDistance - pseudoDistance; + spikePseudoDistance = pointData.maxSpikeDistance - pseudoDistance; + + function dxy(di) { return (dx(di) + dy(di)) / 2; } + var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); + Fx.getClosest(cd, distfn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + // and create the item(s) in closedata for this point + if(pointData.index === false) return []; + + var di = cd[pointData.index]; + var lc = trace.line.color; + var mc = (trace.marker || {}).color; + + if(Color.opacity(lc) && trace.line.width) pointData.color = lc; + else if(Color.opacity(mc) && trace.boxpoints) pointData.color = mc; + else pointData.color = trace.fillcolor; + + pointData[pLetter + '0'] = pAxis.c2p(di.pos + t.bPos - boxDelta, true); + pointData[pLetter + '1'] = pAxis.c2p(di.pos + t.bPos + boxDelta, true); + + pointData[pLetter + 'LabelVal'] = di.pos; + + var spikePosAttr = pLetter + 'Spike'; + pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance; + pointData[spikePosAttr] = pAxis.c2p(di.pos, true); + + // box plots: each "point" gets many labels + var usedVals = {}; + var attrs = ['med', 'min', 'q1', 'q3', 'max']; + + if(trace.boxmean || (trace.meanline || {}).visible) { + attrs.push('mean'); + } + if(trace.boxpoints || trace.points) { + attrs.push('lf', 'uf'); + } + + for(var i = 0; i < attrs.length; i++) { + var attr = attrs[i]; + + if(!(attr in di) || (di[attr] in usedVals)) continue; + usedVals[di[attr]] = true; + + // copy out to a new object for each value to label + var val = di[attr]; + var valPx = vAxis.c2p(val, true); + var pointData2 = Lib.extendFlat({}, pointData); + + pointData2[vLetter + '0'] = pointData2[vLetter + '1'] = valPx; + pointData2[vLetter + 'LabelVal'] = val; + pointData2[vLetter + 'Label'] = (t.labels ? t.labels[attr] + ' ' : '') + Axes.hoverLabelText(vAxis, val); + + // Note: introduced to be able to distinguish a + // clicked point from a box during click-to-select + pointData2.hoverOnBox = true; + + if(attr === 'mean' && ('sd' in di) && trace.boxmean === 'sd') { + pointData2[vLetter + 'err'] = di.sd; + } + // only keep name and spikes on the first item (median) + pointData.name = ''; + pointData.spikeDistance = undefined; + pointData[spikePosAttr] = undefined; + + closeBoxData.push(pointData2); + } + + return closeBoxData; +} + +function hoverOnPoints(pointData, xval, yval) { + var cd = pointData.cd; + var xa = pointData.xa; + var ya = pointData.ya; + var trace = cd[0].trace; + var xPx = xa.c2p(xval); + var yPx = ya.c2p(yval); + var closePtData; + + var dx = function(di) { + var rad = Math.max(3, di.mrc || 0); + return Math.max(Math.abs(xa.c2p(di.x) - xPx) - rad, 1 - 3 / rad); + }; + var dy = function(di) { + var rad = Math.max(3, di.mrc || 0); + return Math.max(Math.abs(ya.c2p(di.y) - yPx) - rad, 1 - 3 / rad); + }; + var distfn = Fx.quadrature(dx, dy); + + // show one point per trace + var ijClosest = false; + var di, pt; + + for(var i = 0; i < cd.length; i++) { + di = cd[i]; + + for(var j = 0; j < (di.pts || []).length; j++) { + pt = di.pts[j]; + + var newDistance = distfn(pt); + if(newDistance <= pointData.distance) { + pointData.distance = newDistance; + ijClosest = [i, j]; + } + } + } + + if(!ijClosest) return false; + + di = cd[ijClosest[0]]; + pt = di.pts[ijClosest[1]]; + + var xc = xa.c2p(pt.x, true); + var yc = ya.c2p(pt.y, true); + var rad = pt.mrc || 1; + + closePtData = Lib.extendFlat({}, pointData, { + // corresponds to index in x/y input data array + index: pt.i, + color: (trace.marker || {}).color, + name: trace.name, + x0: xc - rad, + x1: xc + rad, + xLabelVal: pt.x, + y0: yc - rad, + y1: yc + rad, + yLabelVal: pt.y, + spikeDistance: pointData.distance + }); + var pLetter = trace.orientation === 'h' ? 'y' : 'x'; + var pa = trace.orientation === 'h' ? ya : xa; + closePtData[pLetter + 'Spike'] = pa.c2p(di.pos, true); + fillHoverText(pt, trace, closePtData); + + return closePtData; +} + +module.exports = { + hoverPoints: hoverPoints, + hoverOnBoxes: hoverOnBoxes, + hoverOnPoints: hoverOnPoints +}; + +},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051}],865:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Box = {}; + +Box.attributes = _dereq_('./attributes'); +Box.layoutAttributes = _dereq_('./layout_attributes'); +Box.supplyDefaults = _dereq_('./defaults').supplyDefaults; +Box.supplyLayoutDefaults = _dereq_('./layout_defaults').supplyLayoutDefaults; +Box.calc = _dereq_('./calc'); +Box.crossTraceCalc = _dereq_('./cross_trace_calc').crossTraceCalc; +Box.plot = _dereq_('./plot').plot; +Box.style = _dereq_('./style').style; +Box.styleOnSelect = _dereq_('./style').styleOnSelect; +Box.hoverPoints = _dereq_('./hover').hoverPoints; +Box.eventData = _dereq_('./event_data'); +Box.selectPoints = _dereq_('./select'); + +Box.moduleType = 'trace'; +Box.name = 'box'; +Box.basePlotModule = _dereq_('../../plots/cartesian'); +Box.categories = ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'boxLayout', 'zoomScale']; +Box.meta = { + +}; + +module.exports = Box; + +},{"../../plots/cartesian":756,"./attributes":859,"./calc":860,"./cross_trace_calc":861,"./defaults":862,"./event_data":863,"./hover":864,"./layout_attributes":866,"./layout_defaults":867,"./plot":868,"./select":869,"./style":870}],866:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + boxmode: { + valType: 'enumerated', + values: ['group', 'overlay'], + dflt: 'overlay', + + editType: 'calc', + + }, + boxgap: { + valType: 'number', + min: 0, + max: 1, + dflt: 0.3, + + editType: 'calc', + + }, + boxgroupgap: { + valType: 'number', + min: 0, + max: 1, + dflt: 0.3, + + editType: 'calc', + + } +}; + +},{}],867:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var layoutAttributes = _dereq_('./layout_attributes'); + +function _supply(layoutIn, layoutOut, fullData, coerce, traceType) { + var hasTraceType; + var category = traceType + 'Layout'; + for(var i = 0; i < fullData.length; i++) { + if(Registry.traceIs(fullData[i], category)) { + hasTraceType = true; + break; + } + } + if(!hasTraceType) return; + + coerce(traceType + 'mode'); + coerce(traceType + 'gap'); + coerce(traceType + 'groupgap'); +} + +function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + _supply(layoutIn, layoutOut, fullData, coerce, 'box'); +} + +module.exports = { + supplyLayoutDefaults: supplyLayoutDefaults, + _supply: _supply +}; + +},{"../../lib":696,"../../registry":827,"./layout_attributes":866}],868:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); + +// constants for dynamic jitter (ie less jitter for sparser points) +var JITTERCOUNT = 5; // points either side of this to include +var JITTERSPREAD = 0.01; // fraction of IQR to count as "dense" + +function plot(gd, plotinfo, cdbox, boxLayer) { + var fullLayout = gd._fullLayout; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var numBoxes = fullLayout._numBoxes; + var groupFraction = (1 - fullLayout.boxgap); + var group = (fullLayout.boxmode === 'group' && numBoxes > 1); + + Lib.makeTraceGroups(boxLayer, cdbox, 'trace boxes').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var t = cd0.t; + var trace = cd0.trace; + if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; + // box half width + var bdPos = t.dPos * groupFraction * (1 - fullLayout.boxgroupgap) / (group ? numBoxes : 1); + // box center offset + var bPos = group ? 2 * t.dPos * (-0.5 + (t.num + 0.5) / numBoxes) * groupFraction : 0; + // whisker width + var wdPos = bdPos * trace.whiskerwidth; + + if(trace.visible !== true || t.empty) { + plotGroup.remove(); + return; + } + + var posAxis, valAxis; + + if(trace.orientation === 'h') { + posAxis = ya; + valAxis = xa; + } else { + posAxis = xa; + valAxis = ya; + } + + // save the box size and box position for use by hover + t.bPos = bPos; + t.bdPos = bdPos; + t.wdPos = wdPos; + // half-width within which to accept hover for this box + // always split the distance to the closest box + t.wHover = t.dPos * (group ? groupFraction / numBoxes : 1); + + plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, t); + plotPoints(plotGroup, {x: xa, y: ya}, trace, t); + plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, t); + }); +} + +function plotBoxAndWhiskers(sel, axes, trace, t) { + var posAxis = axes.pos; + var valAxis = axes.val; + var bPos = t.bPos; + var wdPos = t.wdPos || 0; + var bPosPxOffset = t.bPosPxOffset || 0; + var whiskerWidth = trace.whiskerwidth || 0; + var notched = trace.notched || false; + var nw = notched ? 1 - 2 * trace.notchwidth : 1; + + // to support for one-sided box + var bdPos0; + var bdPos1; + if(Array.isArray(t.bdPos)) { + bdPos0 = t.bdPos[0]; + bdPos1 = t.bdPos[1]; + } else { + bdPos0 = t.bdPos; + bdPos1 = t.bdPos; + } + + var paths = sel.selectAll('path.box').data(( + trace.type !== 'violin' || + trace.box.visible + ) ? Lib.identity : []); + + paths.enter().append('path') + .style('vector-effect', 'non-scaling-stroke') + .attr('class', 'box'); + + paths.exit().remove(); + + paths.each(function(d) { + var pos = d.pos; + var posc = posAxis.c2p(pos + bPos, true) + bPosPxOffset; + var pos0 = posAxis.c2p(pos + bPos - bdPos0, true) + bPosPxOffset; + var pos1 = posAxis.c2p(pos + bPos + bdPos1, true) + bPosPxOffset; + var posw0 = posAxis.c2p(pos + bPos - wdPos, true) + bPosPxOffset; + var posw1 = posAxis.c2p(pos + bPos + wdPos, true) + bPosPxOffset; + var posm0 = posAxis.c2p(pos + bPos - bdPos0 * nw, true) + bPosPxOffset; + var posm1 = posAxis.c2p(pos + bPos + bdPos1 * nw, true) + bPosPxOffset; + var q1 = valAxis.c2p(d.q1, true); + var q3 = valAxis.c2p(d.q3, true); + // make sure median isn't identical to either of the + // quartiles, so we can see it + var m = Lib.constrain( + valAxis.c2p(d.med, true), + Math.min(q1, q3) + 1, Math.max(q1, q3) - 1 + ); + + // for compatibility with box, violin, and candlestick + // perhaps we should put this into cd0.t instead so it's more explicit, + // but what we have now is: + // - box always has d.lf, but boxpoints can be anything + // - violin has d.lf and should always use it (boxpoints is undefined) + // - candlestick has only min/max + var useExtremes = (d.lf === undefined) || (trace.boxpoints === false); + var lf = valAxis.c2p(useExtremes ? d.min : d.lf, true); + var uf = valAxis.c2p(useExtremes ? d.max : d.uf, true); + var ln = valAxis.c2p(d.ln, true); + var un = valAxis.c2p(d.un, true); + + if(trace.orientation === 'h') { + d3.select(this).attr('d', + 'M' + m + ',' + posm0 + 'V' + posm1 + // median line + 'M' + q1 + ',' + pos0 + 'V' + pos1 + // left edge + (notched ? 'H' + ln + 'L' + m + ',' + posm1 + 'L' + un + ',' + pos1 : '') + // top notched edge + 'H' + q3 + // end of the top edge + 'V' + pos0 + // right edge + (notched ? 'H' + un + 'L' + m + ',' + posm0 + 'L' + ln + ',' + pos0 : '') + // bottom notched edge + 'Z' + // end of the box + 'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers + ((whiskerWidth === 0) ? '' : // whisker caps + 'M' + lf + ',' + posw0 + 'V' + posw1 + 'M' + uf + ',' + posw0 + 'V' + posw1)); + } else { + d3.select(this).attr('d', + 'M' + posm0 + ',' + m + 'H' + posm1 + // median line + 'M' + pos0 + ',' + q1 + 'H' + pos1 + // top of the box + (notched ? 'V' + ln + 'L' + posm1 + ',' + m + 'L' + pos1 + ',' + un : '') + // notched right edge + 'V' + q3 + // end of the right edge + 'H' + pos0 + // bottom of the box + (notched ? 'V' + un + 'L' + posm0 + ',' + m + 'L' + pos0 + ',' + ln : '') + // notched left edge + 'Z' + // end of the box + 'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers + ((whiskerWidth === 0) ? '' : // whisker caps + 'M' + posw0 + ',' + lf + 'H' + posw1 + 'M' + posw0 + ',' + uf + 'H' + posw1)); + } + }); +} + +function plotPoints(sel, axes, trace, t) { + var xa = axes.x; + var ya = axes.y; + var bdPos = t.bdPos; + var bPos = t.bPos; + + // to support violin points + var mode = trace.boxpoints || trace.points; + + // repeatable pseudo-random number generator + Lib.seedPseudoRandom(); + + // since box plot points get an extra level of nesting, each + // box needs the trace styling info + var fn = function(d) { + d.forEach(function(v) { + v.t = t; + v.trace = trace; + }); + return d; + }; + + var gPoints = sel.selectAll('g.points') + .data(mode ? fn : []); + + gPoints.enter().append('g') + .attr('class', 'points'); + + gPoints.exit().remove(); + + var paths = gPoints.selectAll('path') + .data(function(d) { + var i; + + var pts = mode === 'all' ? + d.pts : + d.pts.filter(function(pt) { return (pt.v < d.lf || pt.v > d.uf); }); + + // normally use IQR, but if this is 0 or too small, use max-min + var typicalSpread = Math.max((d.max - d.min) / 10, d.q3 - d.q1); + var minSpread = typicalSpread * 1e-9; + var spreadLimit = typicalSpread * JITTERSPREAD; + var jitterFactors = []; + var maxJitterFactor = 0; + var newJitter; + + // dynamic jitter + if(trace.jitter) { + if(typicalSpread === 0) { + // edge case of no spread at all: fall back to max jitter + maxJitterFactor = 1; + jitterFactors = new Array(pts.length); + for(i = 0; i < pts.length; i++) { + jitterFactors[i] = 1; + } + } else { + for(i = 0; i < pts.length; i++) { + var i0 = Math.max(0, i - JITTERCOUNT); + var pmin = pts[i0].v; + var i1 = Math.min(pts.length - 1, i + JITTERCOUNT); + var pmax = pts[i1].v; + + if(mode !== 'all') { + if(pts[i].v < d.lf) pmax = Math.min(pmax, d.lf); + else pmin = Math.max(pmin, d.uf); + } + + var jitterFactor = Math.sqrt(spreadLimit * (i1 - i0) / (pmax - pmin + minSpread)) || 0; + jitterFactor = Lib.constrain(Math.abs(jitterFactor), 0, 1); + + jitterFactors.push(jitterFactor); + maxJitterFactor = Math.max(jitterFactor, maxJitterFactor); + } + } + newJitter = trace.jitter * 2 / (maxJitterFactor || 1); + } + + // fills in 'x' and 'y' in calcdata 'pts' item + for(i = 0; i < pts.length; i++) { + var pt = pts[i]; + var v = pt.v; + + var jitterOffset = trace.jitter ? + (newJitter * jitterFactors[i] * (Lib.pseudoRandom() - 0.5)) : + 0; + + var posPx = d.pos + bPos + bdPos * (trace.pointpos + jitterOffset); + + if(trace.orientation === 'h') { + pt.y = posPx; + pt.x = v; + } else { + pt.x = posPx; + pt.y = v; + } + + // tag suspected outliers + if(mode === 'suspectedoutliers' && v < d.uo && v > d.lo) { + pt.so = true; + } + } + + return pts; + }); + + paths.enter().append('path') + .classed('point', true); + + paths.exit().remove(); + + paths.call(Drawing.translatePoints, xa, ya); +} + +function plotBoxMean(sel, axes, trace, t) { + var posAxis = axes.pos; + var valAxis = axes.val; + var bPos = t.bPos; + var bPosPxOffset = t.bPosPxOffset || 0; + + // to support violin mean lines + var mode = trace.boxmean || (trace.meanline || {}).visible; + + // to support for one-sided box + var bdPos0; + var bdPos1; + if(Array.isArray(t.bdPos)) { + bdPos0 = t.bdPos[0]; + bdPos1 = t.bdPos[1]; + } else { + bdPos0 = t.bdPos; + bdPos1 = t.bdPos; + } + + var paths = sel.selectAll('path.mean').data(( + (trace.type === 'box' && trace.boxmean) || + (trace.type === 'violin' && trace.box.visible && trace.meanline.visible) + ) ? Lib.identity : []); + + paths.enter().append('path') + .attr('class', 'mean') + .style({ + fill: 'none', + 'vector-effect': 'non-scaling-stroke' + }); + + paths.exit().remove(); + + paths.each(function(d) { + var posc = posAxis.c2p(d.pos + bPos, true) + bPosPxOffset; + var pos0 = posAxis.c2p(d.pos + bPos - bdPos0, true) + bPosPxOffset; + var pos1 = posAxis.c2p(d.pos + bPos + bdPos1, true) + bPosPxOffset; + var m = valAxis.c2p(d.mean, true); + var sl = valAxis.c2p(d.mean - d.sd, true); + var sh = valAxis.c2p(d.mean + d.sd, true); + + if(trace.orientation === 'h') { + d3.select(this).attr('d', + 'M' + m + ',' + pos0 + 'V' + pos1 + + (mode === 'sd' ? + 'm0,0L' + sl + ',' + posc + 'L' + m + ',' + pos0 + 'L' + sh + ',' + posc + 'Z' : + '') + ); + } else { + d3.select(this).attr('d', + 'M' + pos0 + ',' + m + 'H' + pos1 + + (mode === 'sd' ? + 'm0,0L' + posc + ',' + sl + 'L' + pos0 + ',' + m + 'L' + posc + ',' + sh + 'Z' : + '') + ); + } + }); +} + +module.exports = { + plot: plot, + plotBoxAndWhiskers: plotBoxAndWhiskers, + plotPoints: plotPoints, + plotBoxMean: plotBoxMean +}; + +},{"../../components/drawing":595,"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],869:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var i, j; + + if(selectionTester === false) { + for(i = 0; i < cd.length; i++) { + for(j = 0; j < (cd[i].pts || []).length; j++) { + // clear selection + cd[i].pts[j].selected = 0; + } + } + } else { + for(i = 0; i < cd.length; i++) { + for(j = 0; j < (cd[i].pts || []).length; j++) { + var pt = cd[i].pts[j]; + var x = xa.c2p(pt.x); + var y = ya.c2p(pt.y); + + if(selectionTester.contains([x, y], null, pt.i, searchInfo)) { + selection.push({ + pointNumber: pt.i, + x: xa.c2d(pt.x), + y: ya.c2d(pt.y) + }); + pt.selected = 1; + } else { + pt.selected = 0; + } + } + } + } + + return selection; +}; + +},{}],870:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); + +function style(gd, cd) { + var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.boxes'); + + s.style('opacity', function(d) { return d[0].trace.opacity; }); + + s.each(function(d) { + var el = d3.select(this); + var trace = d[0].trace; + var lineWidth = trace.line.width; + + function styleBox(boxSel, lineWidth, lineColor, fillColor) { + boxSel.style('stroke-width', lineWidth + 'px') + .call(Color.stroke, lineColor) + .call(Color.fill, fillColor); + } + + var allBoxes = el.selectAll('path.box'); + + if(trace.type === 'candlestick') { + allBoxes.each(function(boxData) { + var thisBox = d3.select(this); + var container = trace[boxData.dir]; // dir = 'increasing' or 'decreasing' + styleBox(thisBox, container.line.width, container.line.color, container.fillcolor); + // TODO: custom selection style for candlesticks + thisBox.style('opacity', trace.selectedpoints && !boxData.selected ? 0.3 : 1); + }); + } + else { + styleBox(allBoxes, lineWidth, trace.line.color, trace.fillcolor); + el.selectAll('path.mean') + .style({ + 'stroke-width': lineWidth, + 'stroke-dasharray': (2 * lineWidth) + 'px,' + lineWidth + 'px' + }) + .call(Color.stroke, trace.line.color); + + var pts = el.selectAll('path.point'); + Drawing.pointStyle(pts, trace, gd); + } + }); +} + +function styleOnSelect(gd, cd) { + var s = cd[0].node3; + var trace = cd[0].trace; + var pts = s.selectAll('path.point'); + + if(trace.selectedpoints) { + Drawing.selectedPointStyle(pts, trace); + } else { + Drawing.pointStyle(pts, trace, gd); + } +} + +module.exports = { + style: style, + styleOnSelect: styleOnSelect +}; + +},{"../../components/color":570,"../../components/drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],871:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var extendFlat = _dereq_('../../lib').extendFlat; +var OHLCattrs = _dereq_('../ohlc/attributes'); +var boxAttrs = _dereq_('../box/attributes'); + +function directionAttrs(lineColorDefault) { + return { + line: { + color: extendFlat({}, boxAttrs.line.color, {dflt: lineColorDefault}), + width: boxAttrs.line.width, + editType: 'style' + }, + + fillcolor: boxAttrs.fillcolor, + editType: 'style' + }; +} + +module.exports = { + x: OHLCattrs.x, + open: OHLCattrs.open, + high: OHLCattrs.high, + low: OHLCattrs.low, + close: OHLCattrs.close, + + line: { + width: extendFlat({}, boxAttrs.line.width, { + + }), + editType: 'style' + }, + + increasing: directionAttrs(OHLCattrs.increasing.line.color.dflt), + + decreasing: directionAttrs(OHLCattrs.decreasing.line.color.dflt), + + text: OHLCattrs.text, + whiskerwidth: extendFlat({}, boxAttrs.whiskerwidth, { dflt: 0 }), + + hoverlabel: OHLCattrs.hoverlabel, +}; + +},{"../../lib":696,"../box/attributes":859,"../ohlc/attributes":991}],872:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var calcCommon = _dereq_('../ohlc/calc').calcCommon; + +module.exports = function(gd, trace) { + var fullLayout = gd._fullLayout; + var xa = Axes.getFromId(gd, trace.xaxis); + var ya = Axes.getFromId(gd, trace.yaxis); + + var x = xa.makeCalcdata(trace, 'x'); + + var cd = calcCommon(gd, trace, x, ya, ptFunc); + + if(cd.length) { + Lib.extendFlat(cd[0].t, { + num: fullLayout._numBoxes, + dPos: Lib.distinctVals(x).minDiff / 2, + posLetter: 'x', + valLetter: 'y', + }); + + fullLayout._numBoxes++; + return cd; + } else { + return [{t: {empty: true}}]; + } +}; + +function ptFunc(o, h, l, c) { + return { + min: l, + q1: Math.min(o, c), + med: c, + q3: Math.max(o, c), + max: h, + }; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../ohlc/calc":992}],873:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); +var handleOHLC = _dereq_('../ohlc/ohlc_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleOHLC(traceIn, traceOut, coerce, layout); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('line.width'); + + handleDirection(traceIn, traceOut, coerce, 'increasing'); + handleDirection(traceIn, traceOut, coerce, 'decreasing'); + + coerce('text'); + coerce('whiskerwidth'); + + layout._requestRangeslider[traceOut.xaxis] = true; +}; + +function handleDirection(traceIn, traceOut, coerce, direction) { + var lineColor = coerce(direction + '.line.color'); + coerce(direction + '.line.width', traceOut.line.width); + coerce(direction + '.fillcolor', Color.addOpacity(lineColor, 0.5)); +} + +},{"../../components/color":570,"../../lib":696,"../ohlc/ohlc_defaults":996,"./attributes":871}],874:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'candlestick', + basePlotModule: _dereq_('../../plots/cartesian'), + categories: ['cartesian', 'svg', 'showLegend', 'candlestick', 'boxLayout'], + meta: { + + }, + + attributes: _dereq_('./attributes'), + layoutAttributes: _dereq_('../box/layout_attributes'), + supplyLayoutDefaults: _dereq_('../box/layout_defaults').supplyLayoutDefaults, + crossTraceCalc: _dereq_('../box/cross_trace_calc').crossTraceCalc, + supplyDefaults: _dereq_('./defaults'), + calc: _dereq_('./calc'), + plot: _dereq_('../box/plot').plot, + layerName: 'boxlayer', + style: _dereq_('../box/style').style, + hoverPoints: _dereq_('../ohlc/hover').hoverPoints, + selectPoints: _dereq_('../ohlc/select') +}; + +},{"../../plots/cartesian":756,"../box/cross_trace_calc":861,"../box/layout_attributes":866,"../box/layout_defaults":867,"../box/plot":868,"../box/style":870,"../ohlc/hover":994,"../ohlc/select":998,"./attributes":871,"./calc":872,"./defaults":873}],875:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var handleAxisDefaults = _dereq_('./axis_defaults'); +var Template = _dereq_('../../plot_api/plot_template'); + +module.exports = function handleABDefaults(traceIn, traceOut, fullLayout, coerce, dfltColor) { + var a = coerce('a'); + + if(!a) { + coerce('da'); + coerce('a0'); + } + + var b = coerce('b'); + + if(!b) { + coerce('db'); + coerce('b0'); + } + + mimickAxisDefaults(traceIn, traceOut, fullLayout, dfltColor); +}; + +function mimickAxisDefaults(traceIn, traceOut, fullLayout, dfltColor) { + var axesList = ['aaxis', 'baxis']; + + axesList.forEach(function(axName) { + var axLetter = axName.charAt(0); + var axIn = traceIn[axName] || {}; + var axOut = Template.newContainer(traceOut, axName); + + var defaultOptions = { + tickfont: 'x', + id: axLetter + 'axis', + letter: axLetter, + font: traceOut.font, + name: axName, + data: traceIn[axLetter], + calendar: traceOut.calendar, + dfltColor: dfltColor, + bgColor: fullLayout.paper_bgcolor, + fullLayout: fullLayout + }; + + handleAxisDefaults(axIn, axOut, defaultOptions); + axOut._categories = axOut._categories || []; + + // so we don't have to repeat autotype unnecessarily, + // copy an autotype back to traceIn + if(!traceIn[axName] && axIn.type !== '-') { + traceIn[axName] = {type: axIn.type}; + } + }); +} + +},{"../../plot_api/plot_template":734,"./axis_defaults":880}],876:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +module.exports = function(a) { + return minMax(a, 0); +}; + +function minMax(a, depth) { + // Limit to ten dimensional datasets. This seems *exceedingly* unlikely to + // ever cause problems or even be a concern. It's include strictly so that + // circular arrays could never cause this to loop. + if(!isArrayOrTypedArray(a) || depth >= 10) { + return null; + } + + var min = Infinity; + var max = -Infinity; + var n = a.length; + for(var i = 0; i < n; i++) { + var datum = a[i]; + + if(isArrayOrTypedArray(datum)) { + var result = minMax(datum, depth + 1); + + if(result) { + min = Math.min(result[0], min); + max = Math.max(result[1], max); + } + } else { + min = Math.min(datum, min); + max = Math.max(datum, max); + } + } + + return [min, max]; +} + +},{"../../lib":696}],877:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var axisAttrs = _dereq_('./axis_attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); + +var carpetFont = fontAttrs({ + editType: 'calc', + +}); +// TODO: inherit from global font +carpetFont.family.dflt = '"Open Sans", verdana, arial, sans-serif'; +carpetFont.size.dflt = 12; +carpetFont.color.dflt = colorAttrs.defaultLine; + +module.exports = { + carpet: { + valType: 'string', + + editType: 'calc', + + }, + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + y: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + a: { + valType: 'data_array', + editType: 'calc', + + }, + a0: { + valType: 'number', + dflt: 0, + + editType: 'calc', + + }, + da: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + b: { + valType: 'data_array', + editType: 'calc', + + }, + b0: { + valType: 'number', + dflt: 0, + + editType: 'calc', + + }, + db: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + cheaterslope: { + valType: 'number', + + dflt: 1, + editType: 'calc', + + }, + aaxis: axisAttrs, + baxis: axisAttrs, + font: carpetFont, + color: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'plot', + + }, + transforms: undefined +}; + +},{"../../components/color/attributes":569,"../../plots/font_attributes":771,"./axis_attributes":879}],878:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +/* This function retrns a set of control points that define a curve aligned along + * either the a or b axis. Exactly one of a or b must be an array defining the range + * spanned. + * + * Honestly this is the most complicated function I've implemente here so far because + * of the way it handles knot insertion and direction/axis-agnostic slices. + */ +module.exports = function(carpet, carpetcd, a, b) { + var idx, tangent, tanIsoIdx, tanIsoPar, segment, refidx; + var p0, p1, v0, v1, start, end, range; + + var axis = isArrayOrTypedArray(a) ? 'a' : 'b'; + var ax = axis === 'a' ? carpet.aaxis : carpet.baxis; + var smoothing = ax.smoothing; + var toIdx = axis === 'a' ? carpet.a2i : carpet.b2j; + var pt = axis === 'a' ? a : b; + var iso = axis === 'a' ? b : a; + var n = axis === 'a' ? carpetcd.a.length : carpetcd.b.length; + var m = axis === 'a' ? carpetcd.b.length : carpetcd.a.length; + var isoIdx = Math.floor(axis === 'a' ? carpet.b2j(iso) : carpet.a2i(iso)); + + var xy = axis === 'a' ? function(value) { + return carpet.evalxy([], value, isoIdx); + } : function(value) { + return carpet.evalxy([], isoIdx, value); + }; + + if(smoothing) { + tanIsoIdx = Math.max(0, Math.min(m - 2, isoIdx)); + tanIsoPar = isoIdx - tanIsoIdx; + tangent = axis === 'a' ? function(i, ti) { + return carpet.dxydi([], i, tanIsoIdx, ti, tanIsoPar); + } : function(j, tj) { + return carpet.dxydj([], tanIsoIdx, j, tanIsoPar, tj); + }; + } + + var vstart = toIdx(pt[0]); + var vend = toIdx(pt[1]); + + // So that we can make this work in two directions, flip all of the + // math functions if the direction is from higher to lower indices: + // + // Note that the tolerance is directional! + var dir = vstart < vend ? 1 : -1; + var tol = (vend - vstart) * 1e-8; + var dirfloor = dir > 0 ? Math.floor : Math.ceil; + var dirceil = dir > 0 ? Math.ceil : Math.floor; + var dirmin = dir > 0 ? Math.min : Math.max; + var dirmax = dir > 0 ? Math.max : Math.min; + + var idx0 = dirfloor(vstart + tol); + var idx1 = dirceil(vend - tol); + + p0 = xy(vstart); + var segments = [[p0]]; + + for(idx = idx0; idx * dir < idx1 * dir; idx += dir) { + segment = []; + start = dirmax(vstart, idx); + end = dirmin(vend, idx + dir); + range = end - start; + + // In order to figure out which cell we're in for the derivative (remember, + // the derivatives are *not* constant across grid lines), let's just average + // the start and end points. This cuts out just a tiny bit of logic and + // there's really no computational difference: + refidx = Math.max(0, Math.min(n - 2, Math.floor(0.5 * (start + end)))); + + p1 = xy(end); + if(smoothing) { + v0 = tangent(refidx, start - refidx); + v1 = tangent(refidx, end - refidx); + + segment.push([ + p0[0] + v0[0] / 3 * range, + p0[1] + v0[1] / 3 * range + ]); + + segment.push([ + p1[0] - v1[0] / 3 * range, + p1[1] - v1[1] / 3 * range + ]); + } + + segment.push(p1); + + segments.push(segment); + p0 = p1; + } + + return segments; +}; + +},{"../../lib":696}],879:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); +var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +module.exports = { + color: { + valType: 'color', + + editType: 'calc', + + }, + smoothing: { + valType: 'number', + dflt: 1, + min: 0, + max: 1.3, + + editType: 'calc' + }, + title: { + valType: 'string', + + editType: 'calc', + + }, + titlefont: fontAttrs({ + editType: 'calc', + + }), + titleoffset: { + valType: 'number', + + dflt: 10, + editType: 'calc', + + }, + type: { + valType: 'enumerated', + // '-' means we haven't yet run autotype or couldn't find any data + // it gets turned into linear in gd._fullLayout but not copied back + // to gd.data like the others are. + values: ['-', 'linear', 'date', 'category'], + dflt: '-', + + editType: 'calc', + + }, + autorange: { + valType: 'enumerated', + values: [true, false, 'reversed'], + dflt: true, + + editType: 'calc', + + }, + rangemode: { + valType: 'enumerated', + values: ['normal', 'tozero', 'nonnegative'], + dflt: 'normal', + + editType: 'calc', + + }, + range: { + valType: 'info_array', + + editType: 'calc', + items: [ + {valType: 'any', editType: 'calc'}, + {valType: 'any', editType: 'calc'} + ], + + }, + + fixedrange: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + cheatertype: { + valType: 'enumerated', + values: ['index', 'value'], + dflt: 'value', + + editType: 'calc' + }, + tickmode: { + valType: 'enumerated', + values: ['linear', 'array'], + dflt: 'array', + + editType: 'calc' + }, + nticks: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + tickvals: { + valType: 'data_array', + editType: 'calc', + + }, + ticktext: { + valType: 'data_array', + editType: 'calc', + + }, + showticklabels: { + valType: 'enumerated', + values: ['start', 'end', 'both', 'none'], + dflt: 'start', + + editType: 'calc', + + }, + tickfont: fontAttrs({ + editType: 'calc', + + }), + tickangle: { + valType: 'angle', + dflt: 'auto', + + editType: 'calc', + + }, + tickprefix: { + valType: 'string', + dflt: '', + + editType: 'calc', + + }, + showtickprefix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'calc', + + }, + ticksuffix: { + valType: 'string', + dflt: '', + + editType: 'calc', + + }, + showticksuffix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'calc', + + }, + showexponent: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + editType: 'calc', + + }, + exponentformat: { + valType: 'enumerated', + values: ['none', 'e', 'E', 'power', 'SI', 'B'], + dflt: 'B', + + editType: 'calc', + + }, + separatethousands: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + tickformat: { + valType: 'string', + dflt: '', + + editType: 'calc', + + }, + tickformatstops: overrideAll(axesAttrs.tickformatstops, 'calc', 'from-root'), + categoryorder: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + /* , 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later + ], + dflt: 'trace', + + editType: 'calc', + + }, + categoryarray: { + valType: 'data_array', + + editType: 'calc', + + }, + labelpadding: { + valType: 'integer', + + dflt: 10, + editType: 'calc', + + }, + labelprefix: { + valType: 'string', + + editType: 'calc', + + }, + labelsuffix: { + valType: 'string', + dflt: '', + + editType: 'calc', + + }, + // lines and grids + showline: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + linecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + editType: 'calc', + + }, + linewidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc', + + }, + gridcolor: { + valType: 'color', + + editType: 'calc', + + }, + gridwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc', + + }, + showgrid: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + minorgridcount: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + minorgridwidth: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc', + + }, + minorgridcolor: { + valType: 'color', + dflt: colorAttrs.lightLine, + + editType: 'calc', + + }, + startline: { + valType: 'boolean', + + editType: 'calc', + + }, + startlinecolor: { + valType: 'color', + + editType: 'calc', + + }, + startlinewidth: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + endline: { + valType: 'boolean', + + editType: 'calc', + + }, + endlinewidth: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + endlinecolor: { + valType: 'color', + + editType: 'calc', + + }, + tick0: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + dtick: { + valType: 'number', + min: 0, + dflt: 1, + + editType: 'calc', + + }, + arraytick0: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + arraydtick: { + valType: 'integer', + min: 1, + dflt: 1, + + editType: 'calc', + + }, + editType: 'calc' +}; + +},{"../../components/color/attributes":569,"../../plot_api/edit_types":727,"../../plots/cartesian/layout_attributes":757,"../../plots/font_attributes":771}],880:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var carpetAttrs = _dereq_('./attributes'); + +var addOpacity = _dereq_('../../components/color').addOpacity; +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var handleTickValueDefaults = _dereq_('../../plots/cartesian/tick_value_defaults'); +var handleTickLabelDefaults = _dereq_('../../plots/cartesian/tick_label_defaults'); +var handleCategoryOrderDefaults = _dereq_('../../plots/cartesian/category_order_defaults'); +var setConvert = _dereq_('../../plots/cartesian/set_convert'); +var autoType = _dereq_('../../plots/cartesian/axis_autotype'); + +/** + * options: object containing: + * + * letter: 'a' or 'b' + * title: name of the axis (ie 'Colorbar') to go in default title + * name: axis object name (ie 'xaxis') if one should be stored + * font: the default font to inherit + * outerTicks: boolean, should ticks default to outside? + * showGrid: boolean, should gridlines be shown by default? + * data: the plot data to use in choosing auto type + * bgColor: the plot background color, to calculate default gridline colors + */ +module.exports = function handleAxisDefaults(containerIn, containerOut, options) { + var letter = options.letter, + font = options.font || {}, + attributes = carpetAttrs[letter + 'axis']; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + function coerce2(attr, dflt) { + return Lib.coerce2(containerIn, containerOut, attributes, attr, dflt); + } + + // set up some private properties + if(options.name) { + containerOut._name = options.name; + containerOut._id = options.name; + } + + // now figure out type and do some more initialization + var axType = coerce('type'); + if(axType === '-') { + if(options.data) setAutoType(containerOut, options.data); + + if(containerOut.type === '-') { + containerOut.type = 'linear'; + } + else { + // copy autoType back to input axis + // note that if this object didn't exist + // in the input layout, we have to put it in + // this happens in the main supplyDefaults function + axType = containerIn.type = containerOut.type; + } + } + + coerce('smoothing'); + coerce('cheatertype'); + + coerce('showticklabels'); + coerce('labelprefix', letter + ' = '); + coerce('labelsuffix'); + coerce('showtickprefix'); + coerce('showticksuffix'); + + coerce('separatethousands'); + coerce('tickformat'); + coerce('exponentformat'); + coerce('showexponent'); + coerce('categoryorder'); + + coerce('tickmode'); + coerce('tickvals'); + coerce('ticktext'); + coerce('tick0'); + coerce('dtick'); + + if(containerOut.tickmode === 'array') { + coerce('arraytick0'); + coerce('arraydtick'); + } + + coerce('labelpadding'); + + containerOut._hovertitle = letter; + + + if(axType === 'date') { + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); + handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar); + } + + // we need some of the other functions setConvert attaches, but for + // path finding, override pixel scaling to simple passthrough (identity) + setConvert(containerOut, options.fullLayout); + containerOut.c2p = Lib.identity; + + var dfltColor = coerce('color', options.dfltColor); + // if axis.color was provided, use it for fonts too; otherwise, + // inherit from global font color in case that was provided. + var dfltFontColor = (dfltColor === containerIn.color) ? dfltColor : font.color; + + coerce('title'); + Lib.coerceFont(coerce, 'titlefont', { + family: font.family, + size: Math.round(font.size * 1.2), + color: dfltFontColor + }); + + coerce('titleoffset'); + + coerce('tickangle'); + + var autoRange = coerce('autorange', !containerOut.isValidRange(containerIn.range)); + + if(autoRange) coerce('rangemode'); + + coerce('range'); + containerOut.cleanRange(); + + coerce('fixedrange'); + + handleTickValueDefaults(containerIn, containerOut, coerce, axType); + handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); + handleCategoryOrderDefaults(containerIn, containerOut, coerce, { + data: options.data, + dataAttr: letter + }); + + var gridColor = coerce2('gridcolor', addOpacity(dfltColor, 0.3)); + var gridWidth = coerce2('gridwidth'); + var showGrid = coerce('showgrid'); + + if(!showGrid) { + delete containerOut.gridcolor; + delete containerOut.gridwidth; + } + + var startLineColor = coerce2('startlinecolor', dfltColor); + var startLineWidth = coerce2('startlinewidth', gridWidth); + var showStartLine = coerce('startline', containerOut.showgrid || !!startLineColor || !!startLineWidth); + + if(!showStartLine) { + delete containerOut.startlinecolor; + delete containerOut.startlinewidth; + } + + var endLineColor = coerce2('endlinecolor', dfltColor); + var endLineWidth = coerce2('endlinewidth', gridWidth); + var showEndLine = coerce('endline', containerOut.showgrid || !!endLineColor || !!endLineWidth); + + if(!showEndLine) { + delete containerOut.endlinecolor; + delete containerOut.endlinewidth; + } + + if(!showGrid) { + delete containerOut.gridcolor; + delete containerOut.gridWidth; + } else { + coerce('minorgridcount'); + coerce('minorgridwidth', gridWidth); + coerce('minorgridcolor', addOpacity(gridColor, 0.06)); + + if(!containerOut.minorgridcount) { + delete containerOut.minorgridwidth; + delete containerOut.minorgridcolor; + } + } + + if(containerOut.showticklabels === 'none') { + delete containerOut.tickfont; + delete containerOut.tickangle; + delete containerOut.showexponent; + delete containerOut.exponentformat; + delete containerOut.tickformat; + delete containerOut.showticksuffix; + delete containerOut.showtickprefix; + } + + if(!containerOut.showticksuffix) { + delete containerOut.ticksuffix; + } + + if(!containerOut.showtickprefix) { + delete containerOut.tickprefix; + } + + // It needs to be coerced, then something above overrides this deep in the axis code, + // but no, we *actually* want to coerce this. + coerce('tickmode'); + + if(!containerOut.title || (containerOut.title && containerOut.title.length === 0)) { + delete containerOut.titlefont; + delete containerOut.titleoffset; + } + + return containerOut; +}; + +function setAutoType(ax, data) { + // new logic: let people specify any type they want, + // only autotype if type is '-' + if(ax.type !== '-') return; + + var id = ax._id, + axLetter = id.charAt(0); + + var calAttr = axLetter + 'calendar', + calendar = ax[calAttr]; + + ax.type = autoType(data, calendar); +} + +},{"../../components/color":570,"../../lib":696,"../../plots/cartesian/axis_autotype":745,"../../plots/cartesian/category_order_defaults":748,"../../plots/cartesian/set_convert":763,"../../plots/cartesian/tick_label_defaults":764,"../../plots/cartesian/tick_value_defaults":766,"../../registry":827,"./attributes":877}],881:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var isArray1D = _dereq_('../../lib').isArray1D; +var cheaterBasis = _dereq_('./cheater_basis'); +var arrayMinmax = _dereq_('./array_minmax'); +var calcGridlines = _dereq_('./calc_gridlines'); +var calcLabels = _dereq_('./calc_labels'); +var calcClipPath = _dereq_('./calc_clippath'); +var clean2dArray = _dereq_('../heatmap/clean_2d_array'); +var smoothFill2dArray = _dereq_('./smooth_fill_2d_array'); +var convertColumnData = _dereq_('../heatmap/convert_column_xyz'); +var setConvert = _dereq_('./set_convert'); + +module.exports = function calc(gd, trace) { + var xa = Axes.getFromId(gd, trace.xaxis); + var ya = Axes.getFromId(gd, trace.yaxis); + var aax = trace.aaxis; + var bax = trace.baxis; + + var x = trace.x; + var y = trace.y; + var cols = []; + if(x && isArray1D(x)) cols.push('x'); + if(y && isArray1D(y)) cols.push('y'); + + if(cols.length) { + convertColumnData(trace, aax, bax, 'a', 'b', cols); + } + + var a = trace._a = trace._a || trace.a; + var b = trace._b = trace._b || trace.b; + x = trace._x || trace.x; + y = trace._y || trace.y; + + var t = {}; + + if(trace._cheater) { + var avals = aax.cheatertype === 'index' ? a.length : a; + var bvals = bax.cheatertype === 'index' ? b.length : b; + x = cheaterBasis(avals, bvals, trace.cheaterslope); + } + + trace._x = x = clean2dArray(x); + trace._y = y = clean2dArray(y); + + // Fill in any undefined values with elliptic smoothing. This doesn't take + // into account the spacing of the values. That is, the derivatives should + // be modified to use a and b values. It's not that hard, but this is already + // moderate overkill for just filling in missing values. + smoothFill2dArray(x, a, b); + smoothFill2dArray(y, a, b); + + setConvert(trace); + + // create conversion functions that depend on the data + trace.setScale(); + + // This is a rather expensive scan. Nothing guarantees monotonicity, + // so we need to scan through all data to get proper ranges: + var xrange = arrayMinmax(x); + var yrange = arrayMinmax(y); + + var dx = 0.5 * (xrange[1] - xrange[0]); + var xc = 0.5 * (xrange[1] + xrange[0]); + + var dy = 0.5 * (yrange[1] - yrange[0]); + var yc = 0.5 * (yrange[1] + yrange[0]); + + // Expand the axes to fit the plot, except just grow it by a factor of 1.3 + // because the labels should be taken into account except that's difficult + // hence 1.3. + var grow = 1.3; + xrange = [xc - dx * grow, xc + dx * grow]; + yrange = [yc - dy * grow, yc + dy * grow]; + + trace._extremes[xa._id] = Axes.findExtremes(xa, xrange, {padded: true}); + trace._extremes[ya._id] = Axes.findExtremes(ya, yrange, {padded: true}); + + // Enumerate the gridlines, both major and minor, and store them on the trace + // object: + calcGridlines(trace, 'a', 'b'); + calcGridlines(trace, 'b', 'a'); + + // Calculate the text labels for each major gridline and store them on the + // trace object: + calcLabels(trace, aax); + calcLabels(trace, bax); + + // Tabulate points for the four segments that bound the axes so that we can + // map to pixel coordinates in the plot function and create a clip rect: + t.clipsegments = calcClipPath(trace._xctrl, trace._yctrl, aax, bax); + + t.x = x; + t.y = y; + t.a = a; + t.b = b; + + return [t]; +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../heatmap/clean_2d_array":947,"../heatmap/convert_column_xyz":949,"./array_minmax":876,"./calc_clippath":882,"./calc_gridlines":883,"./calc_labels":884,"./cheater_basis":886,"./set_convert":899,"./smooth_fill_2d_array":900}],882:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function makeClipPath(xctrl, yctrl, aax, bax) { + var i, x, y; + var segments = []; + + var asmoothing = !!aax.smoothing; + var bsmoothing = !!bax.smoothing; + var nea1 = xctrl[0].length - 1; + var neb1 = xctrl.length - 1; + + // Along the lower a axis: + for(i = 0, x = [], y = []; i <= nea1; i++) { + x[i] = xctrl[0][i]; + y[i] = yctrl[0][i]; + } + segments.push({x: x, y: y, bicubic: asmoothing}); + + // Along the upper b axis: + for(i = 0, x = [], y = []; i <= neb1; i++) { + x[i] = xctrl[i][nea1]; + y[i] = yctrl[i][nea1]; + } + segments.push({x: x, y: y, bicubic: bsmoothing}); + + // Backwards along the upper a axis: + for(i = nea1, x = [], y = []; i >= 0; i--) { + x[nea1 - i] = xctrl[neb1][i]; + y[nea1 - i] = yctrl[neb1][i]; + } + segments.push({x: x, y: y, bicubic: asmoothing}); + + // Backwards along the lower b axis: + for(i = neb1, x = [], y = []; i >= 0; i--) { + x[neb1 - i] = xctrl[i][0]; + y[neb1 - i] = yctrl[i][0]; + } + segments.push({x: x, y: y, bicubic: bsmoothing}); + + return segments; +}; + +},{}],883:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = function calcGridlines(trace, axisLetter, crossAxisLetter) { + var i, j, j0; + var eps, bounds, n1, n2, n, value, v; + var j1, v0, v1, d; + + var data = trace['_' + axisLetter]; + var axis = trace[axisLetter + 'axis']; + + var gridlines = axis._gridlines = []; + var minorgridlines = axis._minorgridlines = []; + var boundarylines = axis._boundarylines = []; + + var crossData = trace['_' + crossAxisLetter]; + var crossAxis = trace[crossAxisLetter + 'axis']; + + if(axis.tickmode === 'array') { + axis.tickvals = data.slice(); + } + + var xcp = trace._xctrl; + var ycp = trace._yctrl; + var nea = xcp[0].length; + var neb = xcp.length; + var na = trace._a.length; + var nb = trace._b.length; + + Axes.prepTicks(axis); + + // don't leave tickvals in axis looking like an attribute + if(axis.tickmode === 'array') delete axis.tickvals; + + // The default is an empty array that will cause the join to remove the gridline if + // it's just disappeared: + // axis._startline = axis._endline = []; + + // If the cross axis uses bicubic interpolation, then the grid + // lines fall once every three expanded grid row/cols: + var stride = axis.smoothing ? 3 : 1; + + function constructValueGridline(value) { + var i, j, j0, tj, pxy, i0, ti, xy, dxydi0, dxydi1, dxydj0, dxydj1; + var xpoints = []; + var ypoints = []; + var ret = {}; + // Search for the fractional grid index giving this line: + if(axisLetter === 'b') { + // For the position we use just the i-j coordinates: + j = trace.b2j(value); + + // The derivatives for catmull-rom splines are discontinuous across cell + // boundaries though, so we need to provide both the cell and the position + // within the cell separately: + j0 = Math.floor(Math.max(0, Math.min(nb - 2, j))); + tj = j - j0; + + ret.length = nb; + ret.crossLength = na; + + ret.xy = function(i) { + return trace.evalxy([], i, j); + }; + + ret.dxy = function(i0, ti) { + return trace.dxydi([], i0, j0, ti, tj); + }; + + for(i = 0; i < na; i++) { + i0 = Math.min(na - 2, i); + ti = i - i0; + xy = trace.evalxy([], i, j); + + if(crossAxis.smoothing && i > 0) { + // First control point: + dxydi0 = trace.dxydi([], i - 1, j0, 0, tj); + xpoints.push(pxy[0] + dxydi0[0] / 3); + ypoints.push(pxy[1] + dxydi0[1] / 3); + + // Second control point: + dxydi1 = trace.dxydi([], i - 1, j0, 1, tj); + xpoints.push(xy[0] - dxydi1[0] / 3); + ypoints.push(xy[1] - dxydi1[1] / 3); + } + + xpoints.push(xy[0]); + ypoints.push(xy[1]); + + pxy = xy; + } + } else { + i = trace.a2i(value); + i0 = Math.floor(Math.max(0, Math.min(na - 2, i))); + ti = i - i0; + + ret.length = na; + ret.crossLength = nb; + + ret.xy = function(j) { + return trace.evalxy([], i, j); + }; + + ret.dxy = function(j0, tj) { + return trace.dxydj([], i0, j0, ti, tj); + }; + + for(j = 0; j < nb; j++) { + j0 = Math.min(nb - 2, j); + tj = j - j0; + xy = trace.evalxy([], i, j); + + if(crossAxis.smoothing && j > 0) { + // First control point: + dxydj0 = trace.dxydj([], i0, j - 1, ti, 0); + xpoints.push(pxy[0] + dxydj0[0] / 3); + ypoints.push(pxy[1] + dxydj0[1] / 3); + + // Second control point: + dxydj1 = trace.dxydj([], i0, j - 1, ti, 1); + xpoints.push(xy[0] - dxydj1[0] / 3); + ypoints.push(xy[1] - dxydj1[1] / 3); + } + + xpoints.push(xy[0]); + ypoints.push(xy[1]); + + pxy = xy; + } + } + + ret.axisLetter = axisLetter; + ret.axis = axis; + ret.crossAxis = crossAxis; + ret.value = value; + ret.constvar = crossAxisLetter; + ret.index = n; + ret.x = xpoints; + ret.y = ypoints; + ret.smoothing = crossAxis.smoothing; + + return ret; + } + + function constructArrayGridline(idx) { + var j, i0, j0, ti, tj; + var xpoints = []; + var ypoints = []; + var ret = {}; + ret.length = data.length; + ret.crossLength = crossData.length; + + if(axisLetter === 'b') { + j0 = Math.max(0, Math.min(nb - 2, idx)); + tj = Math.min(1, Math.max(0, idx - j0)); + + ret.xy = function(i) { + return trace.evalxy([], i, idx); + }; + + ret.dxy = function(i0, ti) { + return trace.dxydi([], i0, j0, ti, tj); + }; + + // In the tickmode: array case, this operation is a simple + // transfer of data: + for(j = 0; j < nea; j++) { + xpoints[j] = xcp[idx * stride][j]; + ypoints[j] = ycp[idx * stride][j]; + } + } else { + i0 = Math.max(0, Math.min(na - 2, idx)); + ti = Math.min(1, Math.max(0, idx - i0)); + + ret.xy = function(j) { + return trace.evalxy([], idx, j); + }; + + ret.dxy = function(j0, tj) { + return trace.dxydj([], i0, j0, ti, tj); + }; + + // In the tickmode: array case, this operation is a simple + // transfer of data: + for(j = 0; j < neb; j++) { + xpoints[j] = xcp[j][idx * stride]; + ypoints[j] = ycp[j][idx * stride]; + } + } + + ret.axisLetter = axisLetter; + ret.axis = axis; + ret.crossAxis = crossAxis; + ret.value = data[idx]; + ret.constvar = crossAxisLetter; + ret.index = idx; + ret.x = xpoints; + ret.y = ypoints; + ret.smoothing = crossAxis.smoothing; + + return ret; + } + + if(axis.tickmode === 'array') { + // var j0 = axis.startline ? 1 : 0; + // var j1 = data.length - (axis.endline ? 1 : 0); + + eps = 5e-15; + bounds = [ + Math.floor(((data.length - 1) - axis.arraytick0) / axis.arraydtick * (1 + eps)), + Math.ceil((- axis.arraytick0) / axis.arraydtick / (1 + eps)) + ].sort(function(a, b) {return a - b;}); + + // Unpack sorted values so we can be sure to avoid infinite loops if something + // is backwards: + n1 = bounds[0] - 1; + n2 = bounds[1] + 1; + + // If the axes fall along array lines, then this is a much simpler process since + // we already have all the control points we need + for(n = n1; n < n2; n++) { + j = axis.arraytick0 + axis.arraydtick * n; + if(j < 0 || j > data.length - 1) continue; + gridlines.push(extendFlat(constructArrayGridline(j), { + color: axis.gridcolor, + width: axis.gridwidth + })); + } + + for(n = n1; n < n2; n++) { + j0 = axis.arraytick0 + axis.arraydtick * n; + j1 = Math.min(j0 + axis.arraydtick, data.length - 1); + + // TODO: fix the bounds computation so we don't have to do a large range and then throw + // out unneeded numbers + if(j0 < 0 || j0 > data.length - 1) continue; + if(j1 < 0 || j1 > data.length - 1) continue; + + v0 = data[j0]; + v1 = data[j1]; + + for(i = 0; i < axis.minorgridcount; i++) { + d = j1 - j0; + + // TODO: fix the bounds computation so we don't have to do a large range and then throw + // out unneeded numbers + if(d <= 0) continue; + + // XXX: This calculation isn't quite right. Off by one somewhere? + v = v0 + (v1 - v0) * (i + 1) / (axis.minorgridcount + 1) * (axis.arraydtick / d); + + // TODO: fix the bounds computation so we don't have to do a large range and then throw + // out unneeded numbers + if(v < data[0] || v > data[data.length - 1]) continue; + minorgridlines.push(extendFlat(constructValueGridline(v), { + color: axis.minorgridcolor, + width: axis.minorgridwidth + })); + } + } + + if(axis.startline) { + boundarylines.push(extendFlat(constructArrayGridline(0), { + color: axis.startlinecolor, + width: axis.startlinewidth + })); + } + + if(axis.endline) { + boundarylines.push(extendFlat(constructArrayGridline(data.length - 1), { + color: axis.endlinecolor, + width: axis.endlinewidth + })); + } + } else { + // If the lines do not fall along the axes, then we have to interpolate + // the contro points and so some math to figure out where the lines are + // in the first place. + + // Compute the integer boudns of tick0 + n * dtick that fall within the range + // (roughly speaking): + // Give this a nice generous epsilon. We use at as * (1 + eps) in order to make + // inequalities a little tolerant in a more or less correct manner: + eps = 5e-15; + bounds = [ + Math.floor((data[data.length - 1] - axis.tick0) / axis.dtick * (1 + eps)), + Math.ceil((data[0] - axis.tick0) / axis.dtick / (1 + eps)) + ].sort(function(a, b) {return a - b;}); + + // Unpack sorted values so we can be sure to avoid infinite loops if something + // is backwards: + n1 = bounds[0]; + n2 = bounds[1]; + + for(n = n1; n <= n2; n++) { + value = axis.tick0 + axis.dtick * n; + + gridlines.push(extendFlat(constructValueGridline(value), { + color: axis.gridcolor, + width: axis.gridwidth + })); + } + + for(n = n1 - 1; n < n2 + 1; n++) { + value = axis.tick0 + axis.dtick * n; + + for(i = 0; i < axis.minorgridcount; i++) { + v = value + axis.dtick * (i + 1) / (axis.minorgridcount + 1); + if(v < data[0] || v > data[data.length - 1]) continue; + minorgridlines.push(extendFlat(constructValueGridline(v), { + color: axis.minorgridcolor, + width: axis.minorgridwidth + })); + } + } + + if(axis.startline) { + boundarylines.push(extendFlat(constructValueGridline(data[0]), { + color: axis.startlinecolor, + width: axis.startlinewidth + })); + } + + if(axis.endline) { + boundarylines.push(extendFlat(constructValueGridline(data[data.length - 1]), { + color: axis.endlinecolor, + width: axis.endlinewidth + })); + } + } +}; + +},{"../../lib/extend":685,"../../plots/cartesian/axes":744}],884:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = function calcLabels(trace, axis) { + var i, tobj, prefix, suffix, gridline; + + var labels = axis._labels = []; + var gridlines = axis._gridlines; + + for(i = 0; i < gridlines.length; i++) { + gridline = gridlines[i]; + + if(['start', 'both'].indexOf(axis.showticklabels) !== -1) { + tobj = Axes.tickText(axis, gridline.value); + + extendFlat(tobj, { + prefix: prefix, + suffix: suffix, + endAnchor: true, + xy: gridline.xy(0), + dxy: gridline.dxy(0, 0), + axis: gridline.axis, + length: gridline.crossAxis.length, + font: gridline.axis.tickfont, + isFirst: i === 0, + isLast: i === gridlines.length - 1 + }); + + labels.push(tobj); + } + + if(['end', 'both'].indexOf(axis.showticklabels) !== -1) { + tobj = Axes.tickText(axis, gridline.value); + + extendFlat(tobj, { + endAnchor: false, + xy: gridline.xy(gridline.crossLength - 1), + dxy: gridline.dxy(gridline.crossLength - 2, 1), + axis: gridline.axis, + length: gridline.crossAxis.length, + font: gridline.axis.tickfont, + isFirst: i === 0, + isLast: i === gridlines.length - 1 + }); + + labels.push(tobj); + } + } +}; + +},{"../../lib/extend":685,"../../plots/cartesian/axes":744}],885:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Compute the tangent vector according to catmull-rom cubic splines (centripetal, + * I think). That differs from the control point in two ways: + * 1. It is a vector, not a position relative to the point + * 2. the vector is longer than the position relative to p1 by a factor of 3 + * + * Close to the boundaries, we'll use these as *quadratic control points, so that + * to make a nice grid, we'll need to divide the tangent by 2 instead of 3. (The + * math works out this way if you work through the bezier derivatives) + */ +var CatmullRomExp = 0.5; +module.exports = function makeControlPoints(p0, p1, p2, smoothness) { + var d1x = p0[0] - p1[0], + d1y = p0[1] - p1[1], + d2x = p2[0] - p1[0], + d2y = p2[1] - p1[1], + d1a = Math.pow(d1x * d1x + d1y * d1y, CatmullRomExp / 2), + d2a = Math.pow(d2x * d2x + d2y * d2y, CatmullRomExp / 2), + numx = (d2a * d2a * d1x - d1a * d1a * d2x) * smoothness, + numy = (d2a * d2a * d1y - d1a * d1a * d2y) * smoothness, + denom1 = d2a * (d1a + d2a) * 3, + denom2 = d1a * (d1a + d2a) * 3; + return [[ + p1[0] + (denom1 && numx / denom1), + p1[1] + (denom1 && numy / denom1) + ], [ + p1[0] - (denom2 && numx / denom2), + p1[1] - (denom2 && numy / denom2) + ]]; +}; + +},{}],886:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +/* + * Construct a 2D array of cheater values given a, b, and a slope. + * If + */ +module.exports = function(a, b, cheaterslope) { + var i, j, ascal, bscal, aval, bval; + var data = []; + + var na = isArrayOrTypedArray(a) ? a.length : a; + var nb = isArrayOrTypedArray(b) ? b.length : b; + var adata = isArrayOrTypedArray(a) ? a : null; + var bdata = isArrayOrTypedArray(b) ? b : null; + + // If we're using data, scale it so that for data that's just barely + // not evenly spaced, the switch to value-based indexing is continuous. + // This means evenly spaced data should look the same whether value + // or index cheatertype. + if(adata) { + ascal = (adata.length - 1) / (adata[adata.length - 1] - adata[0]) / (na - 1); + } + + if(bdata) { + bscal = (bdata.length - 1) / (bdata[bdata.length - 1] - bdata[0]) / (nb - 1); + } + + var xval; + var xmin = Infinity; + var xmax = -Infinity; + for(j = 0; j < nb; j++) { + data[j] = []; + bval = bdata ? (bdata[j] - bdata[0]) * bscal : j / (nb - 1); + for(i = 0; i < na; i++) { + aval = adata ? (adata[i] - adata[0]) * ascal : i / (na - 1); + xval = aval - bval * cheaterslope; + xmin = Math.min(xval, xmin); + xmax = Math.max(xval, xmax); + data[j][i] = xval; + } + } + + // Normalize cheater values to the 0-1 range. This comes into play when you have + // multiple cheater plots. After careful consideration, it seems better if cheater + // values are normalized to a consistent range. Otherwise one cheater affects the + // layout of other cheaters on the same axis. + var slope = 1.0 / (xmax - xmin); + var offset = -xmin * slope; + for(j = 0; j < nb; j++) { + for(i = 0; i < na; i++) { + data[j][i] = slope * data[j][i] + offset; + } + } + + return data; +}; + +},{"../../lib":696}],887:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var makeControlPoints = _dereq_('./catmull_rom'); +var ensureArray = _dereq_('../../lib').ensureArray; + +/* + * Turns a coarse grid into a fine grid with control points. + * + * Here's an ASCII representation: + * + * o ----- o ----- o ----- o + * | | | | + * | | | | + * | | | | + * o ----- o ----- o ----- o + * | | | | + * | | | | + * ^ | | | | + * | o ----- o ----- o ----- o + * b | | | | | + * | | | | | + * | | | | | + * o ----- o ----- o ----- o + * ------> + * a + * + * First of all, note that we want to do this in *cartesian* space. This means + * we might run into problems when there are extreme differences in x/y scaling, + * but the alternative is that the topology of the contours might actually be + * view-dependent, which seems worse. As a fallback, the only parameter that + * actually affects the result is the *aspect ratio*, so that we can at least + * improve the situation a bit without going all the way to screen coordinates. + * + * This function flattens the points + tangents into a slightly denser grid of + * *control points*. The resulting grid looks like this: + * + * 9 +--o-o--+ -o-o--+--o-o--+ + * 8 o o o o o o o o o o + * | | | | + * 7 o o o o o o o o o o + * 6 +--o-o--+ -o-o--+--o-o--+ + * 5 o o o o o o o o o o + * | | | | + * ^ 4 o o o o o o o o o o + * | 3 +--o-o--+ -o-o--+--o-o--+ + * b | 2 o o o o o o o o o o + * | | | | | + * | 1 o o o o o o o o o o + * 0 +--o-o--+ -o-o--+--o-o--+ + * 0 1 2 3 4 5 6 7 8 9 + * ------> + * a + * + * where `o`s represent newly-computed control points. the resulting dimension is + * + * (m - 1) * 3 + 1 + * = 3 * m - 2 + * + * We could simply store the tangents separately, but that's a nightmare to organize + * in two dimensions since we'll be slicing grid lines in both directions and since + * that basically requires very nearly just as much storage as just storing the dense + * grid. + * + * Wow! + */ + + +/* + * Catmull-rom is biased at the boundaries toward the interior and we actually + * can't use catmull-rom to compute the control point closest to (but inside) + * the boundary. + * + * A note on plotly's spline interpolation. It uses the catmull rom control point + * closest to the boundary *as* a quadratic control point. This seems incorrect, + * so I've elected not to follow that. Given control points 0 and 1, regular plotly + * splines give *equivalent* cubic control points: + * + * Input: + * + * boundary + * | | + * p0 p2 p3 --> interior + * 0.0 0.667 1.0 + * | | + * + * Cubic-equivalent of what plotly splines draw:: + * + * boundary + * | | + * p0 p1 p2 p3 --> interior + * 0.0 0.4444 0.8888 1.0 + * | | + * + * What this function fills in: + * + * boundary + * | | + * p0 p1 p2 p3 --> interior + * 0.0 0.333 0.667 1.0 + * | | + * + * Parameters: + * p0: boundary point + * p2: catmull rom point based on computation at p3 + * p3: first grid point + * + * Of course it works whichever way it's oriented; you just need to interpret the + * input/output accordingly. + */ +function inferCubicControlPoint(p0, p2, p3) { + // Extend p1 away from p0 by 50%. This is the equivalent quadratic point that + // would give the same slope as catmull rom at p0. + var p2e0 = -0.5 * p3[0] + 1.5 * p2[0]; + var p2e1 = -0.5 * p3[1] + 1.5 * p2[1]; + + return [ + (2 * p2e0 + p0[0]) / 3, + (2 * p2e1 + p0[1]) / 3, + ]; +} + +module.exports = function computeControlPoints(xe, ye, x, y, asmoothing, bsmoothing) { + var i, j, ie, je, xej, yej, xj, yj, cp, p1; + // At this point, we know these dimensions are correct and representative of + // the whole 2D arrays: + var na = x[0].length; + var nb = x.length; + + // (n)umber of (e)xpanded points: + var nea = asmoothing ? 3 * na - 2 : na; + var neb = bsmoothing ? 3 * nb - 2 : nb; + + xe = ensureArray(xe, neb); + ye = ensureArray(ye, neb); + + for(ie = 0; ie < neb; ie++) { + xe[ie] = ensureArray(xe[ie], nea); + ye[ie] = ensureArray(ye[ie], nea); + } + + // This loop fills in the X'd points: + // + // . . . . + // . . . . + // | | | | + // | | | | + // X ----- X ----- X ----- X + // | | | | + // | | | | + // | | | | + // X ----- X ----- X ----- X + // + // + // ie = (i) (e)xpanded: + for(j = 0, je = 0; j < nb; j++, je += bsmoothing ? 3 : 1) { + xej = xe[je]; + yej = ye[je]; + xj = x[j]; + yj = y[j]; + + // je = (j) (e)xpanded: + for(i = 0, ie = 0; i < na; i++, ie += asmoothing ? 3 : 1) { + xej[ie] = xj[i]; + yej[ie] = yj[i]; + } + } + + if(asmoothing) { + // If there's a-smoothing, this loop fills in the X'd points with catmull-rom + // control points computed along the a-axis: + // . . . . + // . . . . + // | | | | + // | | | | + // o -Y-X- o -X-X- o -X-Y- o + // | | | | + // | | | | + // | | | | + // o -Y-X- o -X-X- o -X-Y- o + // + // i: 0 1 2 3 + // ie: 0 1 3 3 4 5 6 7 8 9 + // + // ------> + // a + // + for(j = 0, je = 0; j < nb; j++, je += bsmoothing ? 3 : 1) { + // Fill in the points marked X for this a-row: + for(i = 1, ie = 3; i < na - 1; i++, ie += 3) { + cp = makeControlPoints( + [x[j][i - 1], y[j][i - 1]], + [x[j][i ], y[j][i]], + [x[j][i + 1], y[j][i + 1]], + asmoothing + ); + + xe[je][ie - 1] = cp[0][0]; + ye[je][ie - 1] = cp[0][1]; + xe[je][ie + 1] = cp[1][0]; + ye[je][ie + 1] = cp[1][1]; + } + + // The very first cubic interpolation point (to the left for i = 1 above) is + // used as a *quadratic* interpolation point by the spline drawing function + // which isn't really correct. But for the sake of consistency, we'll use it + // as such. Since we're using cubic splines, that means we need to shorten the + // tangent by 1/3 and also construct a new cubic spline control point 1/3 from + // the original to the i = 0 point. + p1 = inferCubicControlPoint( + [xe[je][0], ye[je][0]], + [xe[je][2], ye[je][2]], + [xe[je][3], ye[je][3]] + ); + xe[je][1] = p1[0]; + ye[je][1] = p1[1]; + + // Ditto last points, sans explanation: + p1 = inferCubicControlPoint( + [xe[je][nea - 1], ye[je][nea - 1]], + [xe[je][nea - 3], ye[je][nea - 3]], + [xe[je][nea - 4], ye[je][nea - 4]] + ); + xe[je][nea - 2] = p1[0]; + ye[je][nea - 2] = p1[1]; + } + } + + if(bsmoothing) { + // If there's a-smoothing, this loop fills in the X'd points with catmull-rom + // control points computed along the b-axis: + // . . . . + // X X X X X X X X X X + // | | | | + // X X X X X X X X X X + // o -o-o- o -o-o- o -o-o- o + // X X X X X X X X X X + // | | | | + // Y Y Y Y Y Y Y Y Y Y + // o -o-o- o -o-o- o -o-o- o + // + // i: 0 1 2 3 + // ie: 0 1 3 3 4 5 6 7 8 9 + // + // ------> + // a + // + for(ie = 0; ie < nea; ie++) { + for(je = 3; je < neb - 3; je += 3) { + cp = makeControlPoints( + [xe[je - 3][ie], ye[je - 3][ie]], + [xe[je][ie], ye[je][ie]], + [xe[je + 3][ie], ye[je + 3][ie]], + bsmoothing + ); + + xe[je - 1][ie] = cp[0][0]; + ye[je - 1][ie] = cp[0][1]; + xe[je + 1][ie] = cp[1][0]; + ye[je + 1][ie] = cp[1][1]; + } + // Do the same boundary condition magic for these control points marked Y above: + p1 = inferCubicControlPoint( + [xe[0][ie], ye[0][ie]], + [xe[2][ie], ye[2][ie]], + [xe[3][ie], ye[3][ie]] + ); + xe[1][ie] = p1[0]; + ye[1][ie] = p1[1]; + + p1 = inferCubicControlPoint( + [xe[neb - 1][ie], ye[neb - 1][ie]], + [xe[neb - 3][ie], ye[neb - 3][ie]], + [xe[neb - 4][ie], ye[neb - 4][ie]] + ); + xe[neb - 2][ie] = p1[0]; + ye[neb - 2][ie] = p1[1]; + } + } + + if(asmoothing && bsmoothing) { + // Do one more pass, this time recomputing exactly what we just computed. + // It's overdetermined since we're peforming catmull-rom in two directions, + // so we'll just average the overdetermined. These points don't lie along the + // grid lines, so note that only grid lines will follow normal plotly spline + // interpolation. + // + // Unless of course there was no b smoothing. Then these intermediate points + // don't actually exist and this section is bypassed. + // . . . . + // o X X o X X o X X o + // | | | | + // o X X o X X o X X o + // o -o-o- o -o-o- o -o-o- o + // o X X o X X o X X o + // | | | | + // o Y Y o Y Y o Y Y o + // o -o-o- o -o-o- o -o-o- o + // + // i: 0 1 2 3 + // ie: 0 1 3 3 4 5 6 7 8 9 + // + // ------> + // a + // + for(je = 1; je < neb; je += (je + 1) % 3 === 0 ? 2 : 1) { + // Fill in the points marked X for this a-row: + for(ie = 3; ie < nea - 3; ie += 3) { + cp = makeControlPoints( + [xe[je][ie - 3], ye[je][ie - 3]], + [xe[je][ie], ye[je][ie]], + [xe[je][ie + 3], ye[je][ie + 3]], + asmoothing + ); + + xe[je][ie - 1] = 0.5 * (xe[je][ie - 1] + cp[0][0]); + ye[je][ie - 1] = 0.5 * (ye[je][ie - 1] + cp[0][1]); + xe[je][ie + 1] = 0.5 * (xe[je][ie + 1] + cp[1][0]); + ye[je][ie + 1] = 0.5 * (ye[je][ie + 1] + cp[1][1]); + } + + // This case is just slightly different. The computation is the same, + // but having computed this, we'll average with the existing result. + p1 = inferCubicControlPoint( + [xe[je][0], ye[je][0]], + [xe[je][2], ye[je][2]], + [xe[je][3], ye[je][3]] + ); + xe[je][1] = 0.5 * (xe[je][1] + p1[0]); + ye[je][1] = 0.5 * (ye[je][1] + p1[1]); + + p1 = inferCubicControlPoint( + [xe[je][nea - 1], ye[je][nea - 1]], + [xe[je][nea - 3], ye[je][nea - 3]], + [xe[je][nea - 4], ye[je][nea - 4]] + ); + xe[je][nea - 2] = 0.5 * (xe[je][nea - 2] + p1[0]); + ye[je][nea - 2] = 0.5 * (ye[je][nea - 2] + p1[1]); + } + } + + return [xe, ye]; +}; + +},{"../../lib":696,"./catmull_rom":885}],888:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + RELATIVE_CULL_TOLERANCE: 1e-6 +}; + +},{}],889:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Evaluates the derivative of a list of control point arrays. That is, it expects an array or arrays + * that are expanded relative to the raw data to include the bicubic control points, if applicable. If + * only linear interpolation is desired, then the data points correspond 1-1 along that axis to the + * data itself. Since it's catmull-rom splines in either direction note in particular that the + * derivatives are discontinuous across cell boundaries. That's the reason you need both the *cell* + * and the *point within the cell*. + * + * Also note that the discontinuity of the derivative is in magnitude only. The direction *is* + * continuous across cell boundaries. + * + * For example, to compute the derivative of the xcoordinate halfway betwen the 7 and 8th i-gridpoints + * and the 10th and 11th j-gridpoints given bicubic smoothing in both dimensions, you'd write: + * + * var deriv = createIDerivativeEvaluator([x], 1, 1); + * + * var dxdi = deriv([], 7, 10, 0.5, 0.5); + * // => [0.12345] + * + * Since there'd be a bunch of duplicate computation to compute multiple derivatives, you can double + * this up by providing more arrays: + * + * var deriv = createIDerivativeEvaluator([x, y], 1, 1); + * + * var dxdi = deriv([], 7, 10, 0.5, 0.5); + * // => [0.12345, 0.78910] + * + * NB: It's presumed that at this point all data has been sanitized and is valid numerical data arrays + * of the correct dimension. + */ +module.exports = function(arrays, asmoothing, bsmoothing) { + if(asmoothing && bsmoothing) { + return function(out, i0, j0, u, v) { + if(!out) out = []; + var f0, f1, f2, f3, ak, k; + + // Since it's a grid of control points, the actual indices are * 3: + i0 *= 3; + j0 *= 3; + + // Precompute some numbers: + var u2 = u * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ouu2 = ou * u * 2; + var a = -3 * ou2; + var b = 3 * (ou2 - ouu2); + var c = 3 * (ouu2 - u2); + var d = 3 * u2; + + var v2 = v * v; + var v3 = v2 * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ov3 = ov2 * ov; + + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + // Compute the derivatives in the u-direction: + f0 = a * ak[j0 ][i0] + b * ak[j0 ][i0 + 1] + c * ak[j0 ][i0 + 2] + d * ak[j0 ][i0 + 3]; + f1 = a * ak[j0 + 1][i0] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 1][i0 + 2] + d * ak[j0 + 1][i0 + 3]; + f2 = a * ak[j0 + 2][i0] + b * ak[j0 + 2][i0 + 1] + c * ak[j0 + 2][i0 + 2] + d * ak[j0 + 2][i0 + 3]; + f3 = a * ak[j0 + 3][i0] + b * ak[j0 + 3][i0 + 1] + c * ak[j0 + 3][i0 + 2] + d * ak[j0 + 3][i0 + 3]; + + // Now just interpolate in the v-direction since it's all separable: + out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; + } + + return out; + }; + } else if(asmoothing) { + // Handle smooth in the a-direction but linear in the b-direction by performing four + // linear interpolations followed by one cubic interpolation of the result + return function(out, i0, j0, u, v) { + if(!out) out = []; + var f0, f1, k, ak; + i0 *= 3; + var u2 = u * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ouu2 = ou * u * 2; + var a = -3 * ou2; + var b = 3 * (ou2 - ouu2); + var c = 3 * (ouu2 - u2); + var d = 3 * u2; + var ov = 1 - v; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = a * ak[j0 ][i0] + b * ak[j0 ][i0 + 1] + c * ak[j0 ][i0 + 2] + d * ak[j0 ][i0 + 3]; + f1 = a * ak[j0 + 1][i0] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 1][i0 + 2] + d * ak[j0 + 1][i0 + 3]; + + out[k] = ov * f0 + v * f1; + } + return out; + }; + } else if(bsmoothing) { + // Same as the above case, except reversed. I've disabled the no-unused vars rule + // so that this function is fully interpolation-agnostic. Otherwise it would need + // to be called differently in different cases. Which wouldn't be the worst, but + /* eslint-disable no-unused-vars */ + return function(out, i0, j0, u, v) { + /* eslint-enable no-unused-vars */ + if(!out) out = []; + var f0, f1, f2, f3, k, ak; + j0 *= 3; + var v2 = v * v; + var v3 = v2 * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ov3 = ov2 * ov; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ak[j0][i0 + 1] - ak[j0][i0]; + f1 = ak[j0 + 1][i0 + 1] - ak[j0 + 1][i0]; + f2 = ak[j0 + 2][i0 + 1] - ak[j0 + 2][i0]; + f3 = ak[j0 + 3][i0 + 1] - ak[j0 + 3][i0]; + + out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; + } + return out; + }; + } else { + // Finally, both directions are linear: + /* eslint-disable no-unused-vars */ + return function(out, i0, j0, u, v) { + /* eslint-enable no-unused-vars */ + if(!out) out = []; + var f0, f1, k, ak; + var ov = 1 - v; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ak[j0][i0 + 1] - ak[j0][i0]; + f1 = ak[j0 + 1][i0 + 1] - ak[j0 + 1][i0]; + + out[k] = ov * f0 + v * f1; + } + return out; + }; + } +}; + +},{}],890:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function(arrays, asmoothing, bsmoothing) { + if(asmoothing && bsmoothing) { + return function(out, i0, j0, u, v) { + if(!out) out = []; + var f0, f1, f2, f3, ak, k; + + // Since it's a grid of control points, the actual indices are * 3: + i0 *= 3; + j0 *= 3; + + // Precompute some numbers: + var u2 = u * u; + var u3 = u2 * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ou3 = ou2 * ou; + + var v2 = v * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ovv2 = ov * v * 2; + var a = -3 * ov2; + var b = 3 * (ov2 - ovv2); + var c = 3 * (ovv2 - v2); + var d = 3 * v2; + + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + + // Compute the derivatives in the v-direction: + f0 = a * ak[j0][i0] + b * ak[j0 + 1][i0] + c * ak[j0 + 2][i0] + d * ak[j0 + 3][i0]; + f1 = a * ak[j0][i0 + 1] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 2][i0 + 1] + d * ak[j0 + 3][i0 + 1]; + f2 = a * ak[j0][i0 + 2] + b * ak[j0 + 1][i0 + 2] + c * ak[j0 + 2][i0 + 2] + d * ak[j0 + 3][i0 + 2]; + f3 = a * ak[j0][i0 + 3] + b * ak[j0 + 1][i0 + 3] + c * ak[j0 + 2][i0 + 3] + d * ak[j0 + 3][i0 + 3]; + + // Now just interpolate in the v-direction since it's all separable: + out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; + } + + return out; + }; + } else if(asmoothing) { + // Handle smooth in the a-direction but linear in the b-direction by performing four + // linear interpolations followed by one cubic interpolation of the result + return function(out, i0, j0, v, u) { + if(!out) out = []; + var f0, f1, f2, f3, k, ak; + i0 *= 3; + var u2 = u * u; + var u3 = u2 * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ou3 = ou2 * ou; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + + f0 = ak[j0 + 1][i0] - ak[j0][i0]; + f1 = ak[j0 + 1][i0 + 1] - ak[j0][i0 + 1]; + f2 = ak[j0 + 1][i0 + 2] - ak[j0][i0 + 2]; + f3 = ak[j0 + 1][i0 + 3] - ak[j0][i0 + 3]; + + out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; + + // mathematically equivalent: + // f0 = ou3 * ak[j0 ][i0] + 3 * (ou2 * u * ak[j0 ][i0 + 1] + ou * u2 * ak[j0 ][i0 + 2]) + u3 * ak[j0 ][i0 + 3]; + // f1 = ou3 * ak[j0 + 1][i0] + 3 * (ou2 * u * ak[j0 + 1][i0 + 1] + ou * u2 * ak[j0 + 1][i0 + 2]) + u3 * ak[j0 + 1][i0 + 3]; + // out[k] = f1 - f0; + } + return out; + }; + } else if(bsmoothing) { + // Same as the above case, except reversed: + /* eslint-disable no-unused-vars */ + return function(out, i0, j0, u, v) { + /* eslint-enable no-unused-vars */ + if(!out) out = []; + var f0, f1, k, ak; + j0 *= 3; + var ou = 1 - u; + var v2 = v * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ovv2 = ov * v * 2; + var a = -3 * ov2; + var b = 3 * (ov2 - ovv2); + var c = 3 * (ovv2 - v2); + var d = 3 * v2; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = a * ak[j0][i0] + b * ak[j0 + 1][i0] + c * ak[j0 + 2][i0] + d * ak[j0 + 3][i0]; + f1 = a * ak[j0][i0 + 1] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 2][i0 + 1] + d * ak[j0 + 3][i0 + 1]; + + out[k] = ou * f0 + u * f1; + } + return out; + }; + } else { + // Finally, both directions are linear: + /* eslint-disable no-unused-vars */ + return function(out, i0, j0, v, u) { + /* eslint-enable no-unused-vars */ + if(!out) out = []; + var f0, f1, k, ak; + var ov = 1 - v; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ak[j0 + 1][i0] - ak[j0][i0]; + f1 = ak[j0 + 1][i0 + 1] - ak[j0][i0 + 1]; + + out[k] = ov * f0 + v * f1; + } + return out; + }; + } + +}; + +},{}],891:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Return a function that evaluates a set of linear or bicubic control points. + * This will get evaluated a lot, so we'll at least do a bit of extra work to + * flatten some of the choices. In particular, we'll unroll the linear/bicubic + * combinations and we'll allow computing results in parallel to cut down + * on repeated arithmetic. + * + * Take note that we don't search for the correct range in this function. The + * reason is for consistency due to the corrresponding derivative function. In + * particular, the derivatives aren't continuous across cells, so it's important + * to be able control whether the derivative at a cell boundary is approached + * from one side or the other. + */ +module.exports = function(arrays, na, nb, asmoothing, bsmoothing) { + var imax = na - 2; + var jmax = nb - 2; + + if(asmoothing && bsmoothing) { + return function(out, i, j) { + if(!out) out = []; + var f0, f1, f2, f3, ak, k; + + var i0 = Math.max(0, Math.min(Math.floor(i), imax)); + var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); + var u = Math.max(0, Math.min(1, i - i0)); + var v = Math.max(0, Math.min(1, j - j0)); + + // Since it's a grid of control points, the actual indices are * 3: + i0 *= 3; + j0 *= 3; + + // Precompute some numbers: + var u2 = u * u; + var u3 = u2 * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ou3 = ou2 * ou; + + var v2 = v * v; + var v3 = v2 * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ov3 = ov2 * ov; + + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ou3 * ak[j0][i0] + 3 * (ou2 * u * ak[j0][i0 + 1] + ou * u2 * ak[j0][i0 + 2]) + u3 * ak[j0][i0 + 3]; + f1 = ou3 * ak[j0 + 1][i0] + 3 * (ou2 * u * ak[j0 + 1][i0 + 1] + ou * u2 * ak[j0 + 1][i0 + 2]) + u3 * ak[j0 + 1][i0 + 3]; + f2 = ou3 * ak[j0 + 2][i0] + 3 * (ou2 * u * ak[j0 + 2][i0 + 1] + ou * u2 * ak[j0 + 2][i0 + 2]) + u3 * ak[j0 + 2][i0 + 3]; + f3 = ou3 * ak[j0 + 3][i0] + 3 * (ou2 * u * ak[j0 + 3][i0 + 1] + ou * u2 * ak[j0 + 3][i0 + 2]) + u3 * ak[j0 + 3][i0 + 3]; + out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; + } + + return out; + }; + } else if(asmoothing) { + // Handle smooth in the a-direction but linear in the b-direction by performing four + // linear interpolations followed by one cubic interpolation of the result + return function(out, i, j) { + if(!out) out = []; + + var i0 = Math.max(0, Math.min(Math.floor(i), imax)); + var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); + var u = Math.max(0, Math.min(1, i - i0)); + var v = Math.max(0, Math.min(1, j - j0)); + + var f0, f1, f2, f3, k, ak; + i0 *= 3; + var u2 = u * u; + var u3 = u2 * u; + var ou = 1 - u; + var ou2 = ou * ou; + var ou3 = ou2 * ou; + var ov = 1 - v; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ov * ak[j0][i0] + v * ak[j0 + 1][i0]; + f1 = ov * ak[j0][i0 + 1] + v * ak[j0 + 1][i0 + 1]; + f2 = ov * ak[j0][i0 + 2] + v * ak[j0 + 1][i0 + 1]; + f3 = ov * ak[j0][i0 + 3] + v * ak[j0 + 1][i0 + 1]; + + out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; + } + return out; + }; + } else if(bsmoothing) { + // Same as the above case, except reversed: + return function(out, i, j) { + if(!out) out = []; + + var i0 = Math.max(0, Math.min(Math.floor(i), imax)); + var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); + var u = Math.max(0, Math.min(1, i - i0)); + var v = Math.max(0, Math.min(1, j - j0)); + + var f0, f1, f2, f3, k, ak; + j0 *= 3; + var v2 = v * v; + var v3 = v2 * v; + var ov = 1 - v; + var ov2 = ov * ov; + var ov3 = ov2 * ov; + var ou = 1 - u; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ou * ak[j0][i0] + u * ak[j0][i0 + 1]; + f1 = ou * ak[j0 + 1][i0] + u * ak[j0 + 1][i0 + 1]; + f2 = ou * ak[j0 + 2][i0] + u * ak[j0 + 2][i0 + 1]; + f3 = ou * ak[j0 + 3][i0] + u * ak[j0 + 3][i0 + 1]; + + out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; + } + return out; + }; + } else { + // Finally, both directions are linear: + return function(out, i, j) { + if(!out) out = []; + + var i0 = Math.max(0, Math.min(Math.floor(i), imax)); + var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); + var u = Math.max(0, Math.min(1, i - i0)); + var v = Math.max(0, Math.min(1, j - j0)); + + var f0, f1, k, ak; + var ov = 1 - v; + var ou = 1 - u; + for(k = 0; k < arrays.length; k++) { + ak = arrays[k]; + f0 = ou * ak[j0][i0] + u * ak[j0][i0 + 1]; + f1 = ou * ak[j0 + 1][i0] + u * ak[j0 + 1][i0 + 1]; + + out[k] = ov * f0 + v * f1; + } + return out; + }; + } + +}; + +},{}],892:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleXYDefaults = _dereq_('./xy_defaults'); +var handleABDefaults = _dereq_('./ab_defaults'); +var attributes = _dereq_('./attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, dfltColor, fullLayout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + traceOut._clipPathId = 'clip' + traceOut.uid + 'carpet'; + + var defaultColor = coerce('color', colorAttrs.defaultLine); + Lib.coerceFont(coerce, 'font'); + + coerce('carpet'); + + handleABDefaults(traceIn, traceOut, fullLayout, coerce, defaultColor); + + if(!traceOut.a || !traceOut.b) { + traceOut.visible = false; + return; + } + + if(traceOut.a.length < 3) { + traceOut.aaxis.smoothing = 0; + } + + if(traceOut.b.length < 3) { + traceOut.baxis.smoothing = 0; + } + + // NB: the input is x/y arrays. You should know that the *first* dimension of x and y + // corresponds to b and the second to a. This sounds backwards but ends up making sense + // the important part to know is that when you write y[j][i], j goes from 0 to b.length - 1 + // and i goes from 0 to a.length - 1. + var validData = handleXYDefaults(traceIn, traceOut, coerce); + if(!validData) { + traceOut.visible = false; + } + + if(traceOut._cheater) { + coerce('cheaterslope'); + } +}; + +},{"../../components/color/attributes":569,"../../lib":696,"./ab_defaults":875,"./attributes":877,"./xy_defaults":901}],893:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Carpet = {}; + +Carpet.attributes = _dereq_('./attributes'); +Carpet.supplyDefaults = _dereq_('./defaults'); +Carpet.plot = _dereq_('./plot'); +Carpet.calc = _dereq_('./calc'); +Carpet.animatable = true; +Carpet.isContainer = true; // so carpet traces get `calc` before other traces + +Carpet.moduleType = 'trace'; +Carpet.name = 'carpet'; +Carpet.basePlotModule = _dereq_('../../plots/cartesian'); +Carpet.categories = ['cartesian', 'svg', 'carpet', 'carpetAxis', 'notLegendIsolatable']; +Carpet.meta = { + +}; + +module.exports = Carpet; + +},{"../../plots/cartesian":756,"./attributes":877,"./calc":881,"./defaults":892,"./plot":898}],894:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Given a trace, look up the carpet axis by carpet. + */ +module.exports = function(gd, trace) { + var n = gd._fullData.length; + var firstAxis; + for(var i = 0; i < n; i++) { + var maybeCarpet = gd._fullData[i]; + + if(maybeCarpet.index === trace.index) continue; + + if(maybeCarpet.type === 'carpet') { + if(!firstAxis) { + firstAxis = maybeCarpet; + } + + if(maybeCarpet.carpet === trace.carpet) { + return maybeCarpet; + } + } + } + + return firstAxis; +}; + +},{}],895:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function makePath(xp, yp, isBicubic) { + // Prevent d3 errors that would result otherwise: + if(xp.length === 0) return ''; + + var i, path = []; + var stride = isBicubic ? 3 : 1; + for(i = 0; i < xp.length; i += stride) { + path.push(xp[i] + ',' + yp[i]); + + if(isBicubic && i < xp.length - stride) { + path.push('C'); + path.push([ + xp[i + 1] + ',' + yp[i + 1], + xp[i + 2] + ',' + yp[i + 2] + ' ', + ].join(' ')); + } + } + return path.join(isBicubic ? '' : 'L'); +}; + +},{}],896:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +/* + * Map an array of x or y coordinates (c) to screen-space pixel coordinates (p). + * The output array is optional, but if provided, it will be reused without + * reallocation to the extent possible. + */ +module.exports = function mapArray(out, data, func) { + var i; + + if(!isArrayOrTypedArray(out)) { + // If not an array, make it an array: + out = []; + } else if(out.length > data.length) { + // If too long, truncate. (If too short, it will grow + // automatically so we don't care about that case) + out = out.slice(0, data.length); + } + + for(i = 0; i < data.length; i++) { + out[i] = func(data[i]); + } + + return out; +}; + +},{"../../lib":696}],897:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function orientText(trace, xaxis, yaxis, xy, dxy, refDxy) { + var dx = dxy[0] * trace.dpdx(xaxis); + var dy = dxy[1] * trace.dpdy(yaxis); + var flip = 1; + + var offsetMultiplier = 1.0; + if(refDxy) { + var l1 = Math.sqrt(dxy[0] * dxy[0] + dxy[1] * dxy[1]); + var l2 = Math.sqrt(refDxy[0] * refDxy[0] + refDxy[1] * refDxy[1]); + var dot = (dxy[0] * refDxy[0] + dxy[1] * refDxy[1]) / l1 / l2; + offsetMultiplier = Math.max(0.0, dot); + } + + var angle = Math.atan2(dy, dx) * 180 / Math.PI; + if(angle < -90) { + angle += 180; + flip = -flip; + } else if(angle > 90) { + angle -= 180; + flip = -flip; + } + + return { + angle: angle, + flip: flip, + p: trace.c2p(xy, xaxis, yaxis), + offsetMultplier: offsetMultiplier + }; +}; + +},{}],898:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../../components/drawing'); +var map1dArray = _dereq_('./map_1d_array'); +var makepath = _dereq_('./makepath'); +var orientText = _dereq_('./orient_text'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var Lib = _dereq_('../../lib'); +var alignmentConstants = _dereq_('../../constants/alignment'); + +module.exports = function plot(gd, plotinfo, cdcarpet, carpetLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var fullLayout = gd._fullLayout; + var clipLayer = fullLayout._clips; + + Lib.makeTraceGroups(carpetLayer, cdcarpet, 'trace').each(function(cd) { + var axisLayer = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + var aax = trace.aaxis; + var bax = trace.baxis; + + var minorLayer = Lib.ensureSingle(axisLayer, 'g', 'minorlayer'); + var majorLayer = Lib.ensureSingle(axisLayer, 'g', 'majorlayer'); + var boundaryLayer = Lib.ensureSingle(axisLayer, 'g', 'boundarylayer'); + var labelLayer = Lib.ensureSingle(axisLayer, 'g', 'labellayer'); + + axisLayer.style('opacity', trace.opacity); + + drawGridLines(xa, ya, majorLayer, aax, 'a', aax._gridlines, true); + drawGridLines(xa, ya, majorLayer, bax, 'b', bax._gridlines, true); + drawGridLines(xa, ya, minorLayer, aax, 'a', aax._minorgridlines, true); + drawGridLines(xa, ya, minorLayer, bax, 'b', bax._minorgridlines, true); + + // NB: These are not ommitted if the lines are not active. The joins must be executed + // in order for them to get cleaned up without a full redraw + drawGridLines(xa, ya, boundaryLayer, aax, 'a-boundary', aax._boundarylines); + drawGridLines(xa, ya, boundaryLayer, bax, 'b-boundary', bax._boundarylines); + + var labelOrientationA = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, aax._labels, 'a-label'); + var labelOrientationB = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, bax._labels, 'b-label'); + + drawAxisTitles(gd, labelLayer, trace, cd0, xa, ya, labelOrientationA, labelOrientationB); + + drawClipPath(trace, cd0, clipLayer, xa, ya); + }); +}; + +function drawClipPath(trace, t, layer, xaxis, yaxis) { + var seg, xp, yp, i; + + var clip = layer.select('#' + trace._clipPathId); + + if(!clip.size()) { + clip = layer.append('clipPath') + .classed('carpetclip', true); + } + + var path = Lib.ensureSingle(clip, 'path', 'carpetboundary'); + var segments = t.clipsegments; + var segs = []; + + for(i = 0; i < segments.length; i++) { + seg = segments[i]; + xp = map1dArray([], seg.x, xaxis.c2p); + yp = map1dArray([], seg.y, yaxis.c2p); + segs.push(makepath(xp, yp, seg.bicubic)); + } + + // This could be optimized ever so slightly to avoid no-op L segments + // at the corners, but it's so negligible that I don't think it's worth + // the extra complexity + var clipPathData = 'M' + segs.join('L') + 'Z'; + clip.attr('id', trace._clipPathId); + path.attr('d', clipPathData); +} + +function drawGridLines(xaxis, yaxis, layer, axis, axisLetter, gridlines) { + var lineClass = 'const-' + axisLetter + '-lines'; + var gridJoin = layer.selectAll('.' + lineClass).data(gridlines); + + gridJoin.enter().append('path') + .classed(lineClass, true) + .style('vector-effect', 'non-scaling-stroke'); + + gridJoin.each(function(d) { + var gridline = d; + var x = gridline.x; + var y = gridline.y; + + var xp = map1dArray([], x, xaxis.c2p); + var yp = map1dArray([], y, yaxis.c2p); + + var path = 'M' + makepath(xp, yp, gridline.smoothing); + + var el = d3.select(this); + + el.attr('d', path) + .style('stroke-width', gridline.width) + .style('stroke', gridline.color) + .style('fill', 'none'); + }); + + gridJoin.exit().remove(); +} + +function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) { + var labelJoin = layer.selectAll('text.' + labelClass).data(labels); + + labelJoin.enter().append('text') + .classed(labelClass, true); + + var maxExtent = 0; + var labelOrientation = {}; + + labelJoin.each(function(label, i) { + // Most of the positioning is done in calc_labels. Only the parts that depend upon + // the screen space representation of the x and y axes are here: + var orientation; + if(label.axis.tickangle === 'auto') { + orientation = orientText(trace, xaxis, yaxis, label.xy, label.dxy); + } else { + var angle = (label.axis.tickangle + 180.0) * Math.PI / 180.0; + orientation = orientText(trace, xaxis, yaxis, label.xy, [Math.cos(angle), Math.sin(angle)]); + } + + if(!i) { + // TODO: offsetMultiplier? Not currently used anywhere... + labelOrientation = {angle: orientation.angle, flip: orientation.flip}; + } + var direction = (label.endAnchor ? -1 : 1) * orientation.flip; + + var labelEl = d3.select(this) + .attr({ + 'text-anchor': direction > 0 ? 'start' : 'end', + 'data-notex': 1 + }) + .call(Drawing.font, label.font) + .text(label.text) + .call(svgTextUtils.convertToTspans, gd); + + var bbox = Drawing.bBox(this); + + labelEl.attr('transform', + // Translate to the correct point: + 'translate(' + orientation.p[0] + ',' + orientation.p[1] + ') ' + + // Rotate to line up with grid line tangent: + 'rotate(' + orientation.angle + ')' + + // Adjust the baseline and indentation: + 'translate(' + label.axis.labelpadding * direction + ',' + bbox.height * 0.3 + ')' + ); + + maxExtent = Math.max(maxExtent, bbox.width + label.axis.labelpadding); + }); + + labelJoin.exit().remove(); + + labelOrientation.maxExtent = maxExtent; + return labelOrientation; +} + +function drawAxisTitles(gd, layer, trace, t, xa, ya, labelOrientationA, labelOrientationB) { + var a, b, xy, dxy; + + a = 0.5 * (trace.a[0] + trace.a[trace.a.length - 1]); + b = trace.b[0]; + xy = trace.ab2xy(a, b, true); + dxy = trace.dxyda_rough(a, b); + if(labelOrientationA.angle === undefined) { + Lib.extendFlat(labelOrientationA, orientText(trace, xa, ya, xy, trace.dxydb_rough(a, b))); + } + drawAxisTitle(gd, layer, trace, t, xy, dxy, trace.aaxis, xa, ya, labelOrientationA, 'a-title'); + + a = trace.a[0]; + b = 0.5 * (trace.b[0] + trace.b[trace.b.length - 1]); + xy = trace.ab2xy(a, b, true); + dxy = trace.dxydb_rough(a, b); + if(labelOrientationB.angle === undefined) { + Lib.extendFlat(labelOrientationB, orientText(trace, xa, ya, xy, trace.dxyda_rough(a, b))); + } + drawAxisTitle(gd, layer, trace, t, xy, dxy, trace.baxis, xa, ya, labelOrientationB, 'b-title'); +} + +var lineSpacing = alignmentConstants.LINE_SPACING; +var midShift = ((1 - alignmentConstants.MID_SHIFT) / lineSpacing) + 1; + +function drawAxisTitle(gd, layer, trace, t, xy, dxy, axis, xa, ya, labelOrientation, labelClass) { + var data = []; + if(axis.title) data.push(axis.title); + var titleJoin = layer.selectAll('text.' + labelClass).data(data); + var offset = labelOrientation.maxExtent; + + titleJoin.enter().append('text') + .classed(labelClass, true); + + // There's only one, but we'll do it as a join so it's updated nicely: + titleJoin.each(function() { + var orientation = orientText(trace, xa, ya, xy, dxy); + + if(['start', 'both'].indexOf(axis.showticklabels) === -1) { + offset = 0; + } + + // In addition to the size of the labels, add on some extra padding: + var titleSize = axis.titlefont.size; + offset += titleSize + axis.titleoffset; + + var labelNorm = labelOrientation.angle + (labelOrientation.flip < 0 ? 180 : 0); + var angleDiff = (labelNorm - orientation.angle + 450) % 360; + var reverseTitle = angleDiff > 90 && angleDiff < 270; + + var el = d3.select(this); + + el.text(axis.title || '') + .call(svgTextUtils.convertToTspans, gd); + + if(reverseTitle) { + offset = (-svgTextUtils.lineCount(el) + midShift) * lineSpacing * titleSize - offset; + } + + el.attr('transform', + 'translate(' + orientation.p[0] + ',' + orientation.p[1] + ') ' + + 'rotate(' + orientation.angle + ') ' + + 'translate(0,' + offset + ')' + ) + .classed('user-select-none', true) + .attr('text-anchor', 'middle') + .call(Drawing.font, axis.titlefont); + }); + + titleJoin.exit().remove(); +} + +},{"../../components/drawing":595,"../../constants/alignment":668,"../../lib":696,"../../lib/svg_text_utils":720,"./makepath":895,"./map_1d_array":896,"./orient_text":897,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],899:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var constants = _dereq_('./constants'); +var search = _dereq_('../../lib/search').findBin; +var computeControlPoints = _dereq_('./compute_control_points'); +var createSplineEvaluator = _dereq_('./create_spline_evaluator'); +var createIDerivativeEvaluator = _dereq_('./create_i_derivative_evaluator'); +var createJDerivativeEvaluator = _dereq_('./create_j_derivative_evaluator'); + +/* + * Create conversion functions to go from one basis to another. In particular the letter + * abbreviations are: + * + * i: i/j coordinates along the grid. Integer values correspond to data points + * a: real-valued coordinates along the a/b axes + * c: cartesian x-y coordinates + * p: screen-space pixel coordinates + */ +module.exports = function setConvert(trace) { + var a = trace._a; + var b = trace._b; + var na = a.length; + var nb = b.length; + var aax = trace.aaxis; + var bax = trace.baxis; + + // Grab the limits once rather than recomputing the bounds for every point + // independently: + var amin = a[0]; + var amax = a[na - 1]; + var bmin = b[0]; + var bmax = b[nb - 1]; + var arange = a[a.length - 1] - a[0]; + var brange = b[b.length - 1] - b[0]; + + // Compute the tolerance so that points are visible slightly outside the + // defined carpet axis: + var atol = arange * constants.RELATIVE_CULL_TOLERANCE; + var btol = brange * constants.RELATIVE_CULL_TOLERANCE; + + // Expand the limits to include the relative tolerance: + amin -= atol; + amax += atol; + bmin -= btol; + bmax += btol; + + trace.isVisible = function(a, b) { + return a > amin && a < amax && b > bmin && b < bmax; + }; + + trace.isOccluded = function(a, b) { + return a < amin || a > amax || b < bmin || b > bmax; + }; + + trace.setScale = function() { + var x = trace._x; + var y = trace._y; + + // This is potentially a very expensive step! It does the bulk of the work of constructing + // an expanded basis of control points. Note in particular that it overwrites the existing + // basis without creating a new array since that would potentially thrash the garbage + // collector. + var result = computeControlPoints(trace._xctrl, trace._yctrl, x, y, aax.smoothing, bax.smoothing); + trace._xctrl = result[0]; + trace._yctrl = result[1]; + + // This step is the second step in the process, but it's somewhat simpler. It just unrolls + // some logic since it would be unnecessarily expensive to compute both interpolations + // nearly identically but separately and to include a bunch of linear vs. bicubic logic in + // every single call. + trace.evalxy = createSplineEvaluator([trace._xctrl, trace._yctrl], na, nb, aax.smoothing, bax.smoothing); + + trace.dxydi = createIDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); + trace.dxydj = createJDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); + }; + + /* + * Convert from i/j data grid coordinates to a/b values. Note in particular that this + * is *linear* interpolation, even if the data is interpolated bicubically. + */ + trace.i2a = function(i) { + var i0 = Math.max(0, Math.floor(i[0]), na - 2); + var ti = i[0] - i0; + return (1 - ti) * a[i0] + ti * a[i0 + 1]; + }; + + trace.j2b = function(j) { + var j0 = Math.max(0, Math.floor(j[1]), na - 2); + var tj = j[1] - j0; + return (1 - tj) * b[j0] + tj * b[j0 + 1]; + }; + + trace.ij2ab = function(ij) { + return [trace.i2a(ij[0]), trace.j2b(ij[1])]; + }; + + /* + * Convert from a/b coordinates to i/j grid-numbered coordinates. This requires searching + * through the a/b data arrays and assumes they are monotonic, which is presumed to have + * been enforced already. + */ + trace.a2i = function(aval) { + var i0 = Math.max(0, Math.min(search(aval, a), na - 2)); + var a0 = a[i0]; + var a1 = a[i0 + 1]; + return Math.max(0, Math.min(na - 1, i0 + (aval - a0) / (a1 - a0))); + }; + + trace.b2j = function(bval) { + var j0 = Math.max(0, Math.min(search(bval, b), nb - 2)); + var b0 = b[j0]; + var b1 = b[j0 + 1]; + return Math.max(0, Math.min(nb - 1, j0 + (bval - b0) / (b1 - b0))); + }; + + trace.ab2ij = function(ab) { + return [trace.a2i(ab[0]), trace.b2j(ab[1])]; + }; + + /* + * Convert from i/j coordinates to x/y caretesian coordinates. This means either bilinear + * or bicubic spline evaluation, but the hard part is already done at this point. + */ + trace.i2c = function(i, j) { + return trace.evalxy([], i, j); + }; + + trace.ab2xy = function(aval, bval, extrapolate) { + if(!extrapolate && (aval < a[0] || aval > a[na - 1] | bval < b[0] || bval > b[nb - 1])) { + return [false, false]; + } + var i = trace.a2i(aval); + var j = trace.b2j(bval); + + var pt = trace.evalxy([], i, j); + + if(extrapolate) { + // This section uses the boundary derivatives to extrapolate linearly outside + // the defined range. Consider a scatter line with one point inside the carpet + // axis and one point outside. If we don't extrapolate, we can't draw the line + // at all. + var iex = 0; + var jex = 0; + var der = []; + + var i0, ti, j0, tj; + if(aval < a[0]) { + i0 = 0; + ti = 0; + iex = (aval - a[0]) / (a[1] - a[0]); + } else if(aval > a[na - 1]) { + i0 = na - 2; + ti = 1; + iex = (aval - a[na - 1]) / (a[na - 1] - a[na - 2]); + } else { + i0 = Math.max(0, Math.min(na - 2, Math.floor(i))); + ti = i - i0; + } + + if(bval < b[0]) { + j0 = 0; + tj = 0; + jex = (bval - b[0]) / (b[1] - b[0]); + } else if(bval > b[nb - 1]) { + j0 = nb - 2; + tj = 1; + jex = (bval - b[nb - 1]) / (b[nb - 1] - b[nb - 2]); + } else { + j0 = Math.max(0, Math.min(nb - 2, Math.floor(j))); + tj = j - j0; + } + + if(iex) { + trace.dxydi(der, i0, j0, ti, tj); + pt[0] += der[0] * iex; + pt[1] += der[1] * iex; + } + + if(jex) { + trace.dxydj(der, i0, j0, ti, tj); + pt[0] += der[0] * jex; + pt[1] += der[1] * jex; + } + } + + return pt; + }; + + + trace.c2p = function(xy, xa, ya) { + return [xa.c2p(xy[0]), ya.c2p(xy[1])]; + }; + + trace.p2x = function(p, xa, ya) { + return [xa.p2c(p[0]), ya.p2c(p[1])]; + }; + + trace.dadi = function(i /* , u*/) { + // Right now only a piecewise linear a or b basis is permitted since smoother interpolation + // would cause monotonicity problems. As a retult, u is entirely disregarded in this + // computation, though we'll specify it as a parameter for the sake of completeness and + // future-proofing. It would be possible to use monotonic cubic interpolation, for example. + // + // See: https://en.wikipedia.org/wiki/Monotone_cubic_interpolation + + // u = u || 0; + + var i0 = Math.max(0, Math.min(a.length - 2, i)); + + // The step (demoninator) is implicitly 1 since that's the grid spacing. + return a[i0 + 1] - a[i0]; + }; + + trace.dbdj = function(j /* , v*/) { + // See above caveats for dadi which also apply here + var j0 = Math.max(0, Math.min(b.length - 2, j)); + + // The step (demoninator) is implicitly 1 since that's the grid spacing. + return b[j0 + 1] - b[j0]; + }; + + // Takes: grid cell coordinate (i, j) and fractional grid cell coordinates (u, v) + // Returns: (dx/da, dy/db) + // + // NB: separate grid cell + fractional grid cell coordinate format is due to the discontinuous + // derivative, as described better in create_i_derivative_evaluator.js + trace.dxyda = function(i0, j0, u, v) { + var dxydi = trace.dxydi(null, i0, j0, u, v); + var dadi = trace.dadi(i0, u); + + return [dxydi[0] / dadi, dxydi[1] / dadi]; + }; + + trace.dxydb = function(i0, j0, u, v) { + var dxydj = trace.dxydj(null, i0, j0, u, v); + var dbdj = trace.dbdj(j0, v); + + return [dxydj[0] / dbdj, dxydj[1] / dbdj]; + }; + + // Sometimes we don't care about precision and all we really want is decent rough + // directions (as is the case with labels). In that case, we can do a very rough finite + // difference and spare having to worry about precise grid coordinates: + trace.dxyda_rough = function(a, b, reldiff) { + var h = arange * (reldiff || 0.1); + var plus = trace.ab2xy(a + h, b, true); + var minus = trace.ab2xy(a - h, b, true); + + return [ + (plus[0] - minus[0]) * 0.5 / h, + (plus[1] - minus[1]) * 0.5 / h + ]; + }; + + trace.dxydb_rough = function(a, b, reldiff) { + var h = brange * (reldiff || 0.1); + var plus = trace.ab2xy(a, b + h, true); + var minus = trace.ab2xy(a, b - h, true); + + return [ + (plus[0] - minus[0]) * 0.5 / h, + (plus[1] - minus[1]) * 0.5 / h + ]; + }; + + trace.dpdx = function(xa) { + return xa._m; + }; + + trace.dpdy = function(ya) { + return ya._m; + }; +}; + +},{"../../lib/search":715,"./compute_control_points":887,"./constants":888,"./create_i_derivative_evaluator":889,"./create_j_derivative_evaluator":890,"./create_spline_evaluator":891}],900:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +/* + * Given a 2D array as well as a basis in either direction, this function fills in the + * 2D array using a combination of smoothing and extrapolation. This is rather important + * for carpet plots since it's used for layout so that we can't simply omit or blank out + * points. We need a reasonable guess so that the interpolation puts points somewhere + * even if we were to somehow represent that the data was missing later on. + * + * input: + * - data: 2D array of arrays + * - a: array such that a.length === data[0].length + * - b: array such that b.length === data.length + */ +module.exports = function smoothFill2dArray(data, a, b) { + var i, j, k; + var ip = []; + var jp = []; + // var neighborCnts = []; + + var ni = data[0].length; + var nj = data.length; + + function avgSurrounding(i, j) { + // As a low-quality start, we can simply average surrounding points (in a not + // non-uniform grid aware manner): + var sum = 0.0; + var val; + var cnt = 0; + if(i > 0 && (val = data[j][i - 1]) !== undefined) { + cnt++; + sum += val; + } + if(i < ni - 1 && (val = data[j][i + 1]) !== undefined) { + cnt++; + sum += val; + } + if(j > 0 && (val = data[j - 1][i]) !== undefined) { + cnt++; + sum += val; + } + if(j < nj - 1 && (val = data[j + 1][i]) !== undefined) { + cnt++; + sum += val; + } + return sum / Math.max(1, cnt); + + } + + // This loop iterates over all cells. Any cells that are null will be noted and those + // are the only points we will loop over and update via laplace's equation. Points with + // any neighbors will receive the average. If there are no neighboring points, then they + // will be set to zero. Also as we go, track the maximum magnitude so that we can scale + // our tolerance accordingly. + var dmax = 0.0; + for(i = 0; i < ni; i++) { + for(j = 0; j < nj; j++) { + if(data[j][i] === undefined) { + ip.push(i); + jp.push(j); + + data[j][i] = avgSurrounding(i, j); + // neighborCnts.push(result.neighbors); + } + dmax = Math.max(dmax, Math.abs(data[j][i])); + } + } + + if(!ip.length) return data; + + // The tolerance doesn't need to be excessive. It's just for display positioning + var dxp, dxm, dap, dam, dbp, dbm, c, d, diff, reldiff, overrelaxation; + var tol = 1e-5; + var resid = 0; + var itermax = 100; + var iter = 0; + var n = ip.length; + do { + resid = 0; + // Normally we'd loop in two dimensions, but not all points are blank and need + // an update, so we instead loop only over the points that were tabulated above + for(k = 0; k < n; k++) { + i = ip[k]; + j = jp[k]; + // neighborCnt = neighborCnts[k]; + + // Track a counter for how many contributions there are. We'll use this counter + // to average at the end, which reduces to laplace's equation with neumann boundary + // conditions on the first derivative (second derivative is zero so that we get + // a nice linear extrapolation at the boundaries). + var boundaryCnt = 0; + var newVal = 0; + + var d0, d1, x0, x1, i0, j0; + if(i === 0) { + // If this lies along the i = 0 boundary, extrapolate from the two points + // to the right of this point. Note that the finite differences take into + // account non-uniform grid spacing: + i0 = Math.min(ni - 1, 2); + x0 = a[i0]; + x1 = a[1]; + d0 = data[j][i0]; + d1 = data[j][1]; + newVal += d1 + (d1 - d0) * (a[0] - x1) / (x1 - x0); + boundaryCnt++; + } else if(i === ni - 1) { + // If along the high i boundary, extrapolate from the two points to the + // left of this point + i0 = Math.max(0, ni - 3); + x0 = a[i0]; + x1 = a[ni - 2]; + d0 = data[j][i0]; + d1 = data[j][ni - 2]; + newVal += d1 + (d1 - d0) * (a[ni - 1] - x1) / (x1 - x0); + boundaryCnt++; + } + + if((i === 0 || i === ni - 1) && (j > 0 && j < nj - 1)) { + // If along the min(i) or max(i) boundaries, also smooth vertically as long + // as we're not in a corner. Note that the finite differences used here + // are also aware of nonuniform grid spacing: + dxp = b[j + 1] - b[j]; + dxm = b[j] - b[j - 1]; + newVal += (dxm * data[j + 1][i] + dxp * data[j - 1][i]) / (dxm + dxp); + boundaryCnt++; + } + + if(j === 0) { + // If along the j = 0 boundary, extrpolate this point from the two points + // above it + j0 = Math.min(nj - 1, 2); + x0 = b[j0]; + x1 = b[1]; + d0 = data[j0][i]; + d1 = data[1][i]; + newVal += d1 + (d1 - d0) * (b[0] - x1) / (x1 - x0); + boundaryCnt++; + } else if(j === nj - 1) { + // Same for the max j boundary from the cells below it: + j0 = Math.max(0, nj - 3); + x0 = b[j0]; + x1 = b[nj - 2]; + d0 = data[j0][i]; + d1 = data[nj - 2][i]; + newVal += d1 + (d1 - d0) * (b[nj - 1] - x1) / (x1 - x0); + boundaryCnt++; + } + + if((j === 0 || j === nj - 1) && (i > 0 && i < ni - 1)) { + // Now average points to the left/right as long as not in a corner: + dxp = a[i + 1] - a[i]; + dxm = a[i] - a[i - 1]; + newVal += (dxm * data[j][i + 1] + dxp * data[j][i - 1]) / (dxm + dxp); + boundaryCnt++; + } + + if(!boundaryCnt) { + // If none of the above conditions were triggered, then this is an interior + // point and we can just do a laplace equation update. As above, these differences + // are aware of nonuniform grid spacing: + dap = a[i + 1] - a[i]; + dam = a[i] - a[i - 1]; + dbp = b[j + 1] - b[j]; + dbm = b[j] - b[j - 1]; + + // These are just some useful constants for the iteration, which is perfectly + // straightforward but a little long to derive from f_xx + f_yy = 0. + c = dap * dam * (dap + dam); + d = dbp * dbm * (dbp + dbm); + + newVal = (c * (dbm * data[j + 1][i] + dbp * data[j - 1][i]) + + d * (dam * data[j][i + 1] + dap * data[j][i - 1])) / + (d * (dam + dap) + c * (dbm + dbp)); + } else { + // If we did have contributions from the boundary conditions, then average + // the result from the various contributions: + newVal /= boundaryCnt; + } + + // Jacobi updates are ridiculously slow to converge, so this approach uses a + // Gauss-seidel iteration which is dramatically faster. + diff = newVal - data[j][i]; + reldiff = diff / dmax; + resid += reldiff * reldiff; + + // Gauss-Seidel-ish iteration, omega chosen based on heuristics and some + // quick tests. + // + // NB: Don't overrelax the boundarie. Otherwise set an overrelaxation factor + // which is a little low but safely optimal-ish: + overrelaxation = boundaryCnt ? 0 : 0.85; + + // If there are four non-null neighbors, then we want a simple average without + // overrelaxation. If all the surrouding points are null, then we want the full + // overrelaxation + // + // Based on experiments, this actually seems to slow down convergence just a bit. + // I'll leave it here for reference in case this needs to be revisited, but + // it seems to work just fine without this. + // if (overrelaxation) overrelaxation *= (4 - neighborCnt) / 4; + + data[j][i] += diff * (1 + overrelaxation); + } + + resid = Math.sqrt(resid); + } while(iter++ < itermax && resid > tol); + + Lib.log('Smoother converged to', resid, 'after', iter, 'iterations'); + + return data; +}; + +},{"../../lib":696}],901:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isArray1D = _dereq_('../../lib').isArray1D; + +module.exports = function handleXYDefaults(traceIn, traceOut, coerce) { + var x = coerce('x'); + var hasX = x && x.length; + var y = coerce('y'); + var hasY = y && y.length; + if(!hasX && !hasY) return false; + + traceOut._cheater = !x; + + if((!hasX || isArray1D(x)) && (!hasY || isArray1D(y))) { + var len = hasX ? x.length : Infinity; + if(hasY) len = Math.min(len, y.length); + if(traceOut.a && traceOut.a.length) len = Math.min(len, traceOut.a.length); + if(traceOut.b && traceOut.b.length) len = Math.min(len, traceOut.b.length); + traceOut._length = len; + } + else traceOut._length = null; + + return true; +}; + +},{"../../lib":696}],902:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterGeoAttrs = _dereq_('../scattergeo/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterGeoMarkerLineAttrs = scatterGeoAttrs.marker.line; + +module.exports = extendFlat({ + locations: { + valType: 'data_array', + editType: 'calc', + + }, + locationmode: scatterGeoAttrs.locationmode, + z: { + valType: 'data_array', + editType: 'calc', + + }, + text: extendFlat({}, scatterGeoAttrs.text, { + + }), + marker: { + line: { + color: scatterGeoMarkerLineAttrs.color, + width: extendFlat({}, scatterGeoMarkerLineAttrs.width, {dflt: 1}), + editType: 'calc' + }, + opacity: { + valType: 'number', + arrayOk: true, + min: 0, + max: 1, + dflt: 1, + + editType: 'style', + + }, + editType: 'calc' + }, + + selected: { + marker: { + opacity: scatterGeoAttrs.selected.marker.opacity, + editType: 'plot' + }, + editType: 'plot' + }, + unselected: { + marker: { + opacity: scatterGeoAttrs.unselected.marker.opacity, + editType: 'plot' + }, + editType: 'plot' + }, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + editType: 'calc', + flags: ['location', 'z', 'text', 'name'] + }) +}, + + colorscaleAttrs('', { + cLetter: 'z', + editTypeOverride: 'calc' + }), + {colorbar: colorbarAttrs} +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../scattergeo/attributes":1083}],903:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); + +module.exports = function calc(gd, trace) { + var len = trace._length; + var calcTrace = new Array(len); + + for(var i = 0; i < len; i++) { + var calcPt = calcTrace[i] = {}; + var loc = trace.locations[i]; + var z = trace.z[i]; + + calcPt.loc = typeof loc === 'string' ? loc : null; + calcPt.z = isNumeric(z) ? z : BADNUM; + } + + arraysToCalcdata(calcTrace, trace); + colorscaleCalc(trace, trace.z, '', 'z'); + calcSelection(calcTrace, trace); + + return calcTrace; +}; + +},{"../../components/colorscale/calc":578,"../../constants/numerical":673,"../scatter/arrays_to_calcdata":1042,"../scatter/calc_selection":1045,"fast-isnumeric":214}],904:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var locations = coerce('locations'); + var z = coerce('z'); + + if(!(locations && locations.length && Lib.isArrayOrTypedArray(z) && z.length)) { + traceOut.visible = false; + return; + } + traceOut._length = Math.min(locations.length, z.length); + + coerce('locationmode'); + + coerce('text'); + + coerce('marker.line.color'); + coerce('marker.line.width'); + coerce('marker.opacity'); + + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'} + ); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"./attributes":902}],905:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function eventData(out, pt) { + out.location = pt.location; + out.z = pt.z; + + return out; +}; + +},{}],906:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var attributes = _dereq_('./attributes'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); + +module.exports = function hoverPoints(pointData, xval, yval) { + var cd = pointData.cd; + var trace = cd[0].trace; + var geo = pointData.subplot; + + var pt, i, j, isInside; + + for(i = 0; i < cd.length; i++) { + pt = cd[i]; + isInside = false; + + if(pt._polygons) { + for(j = 0; j < pt._polygons.length; j++) { + if(pt._polygons[j].contains([xval, yval])) { + isInside = !isInside; + } + // for polygons that cross antimeridian as xval is in [-180, 180] + if(pt._polygons[j].contains([xval + 360, yval])) { + isInside = !isInside; + } + } + + if(isInside) break; + } + } + + if(!isInside || !pt) return; + + pointData.x0 = pointData.x1 = pointData.xa.c2p(pt.ct); + pointData.y0 = pointData.y1 = pointData.ya.c2p(pt.ct); + + pointData.index = pt.index; + pointData.location = pt.loc; + pointData.z = pt.z; + + makeHoverInfo(pointData, trace, pt, geo.mockAxis); + + return [pointData]; +}; + +function makeHoverInfo(pointData, trace, pt, axis) { + var hoverinfo = pt.hi || trace.hoverinfo; + + var parts = (hoverinfo === 'all') ? + attributes.hoverinfo.flags : + hoverinfo.split('+'); + + var hasName = (parts.indexOf('name') !== -1); + var hasLocation = (parts.indexOf('location') !== -1); + var hasZ = (parts.indexOf('z') !== -1); + var hasText = (parts.indexOf('text') !== -1); + var hasIdAsNameLabel = !hasName && hasLocation; + + var text = []; + + function formatter(val) { + return Axes.tickText(axis, axis.c2l(val), 'hover').text; + } + + if(hasIdAsNameLabel) { + pointData.nameOverride = pt.loc; + } else { + if(hasName) pointData.nameOverride = trace.name; + if(hasLocation) text.push(pt.loc); + } + + if(hasZ) text.push(formatter(pt.z)); + if(hasText) { + fillHoverText(pt, trace, text); + } + + pointData.extraText = text.join('
'); +} + +},{"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051,"./attributes":902}],907:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Choropleth = {}; + +Choropleth.attributes = _dereq_('./attributes'); +Choropleth.supplyDefaults = _dereq_('./defaults'); +Choropleth.colorbar = _dereq_('../heatmap/colorbar'); +Choropleth.calc = _dereq_('./calc'); +Choropleth.plot = _dereq_('./plot'); +Choropleth.style = _dereq_('./style').style; +Choropleth.styleOnSelect = _dereq_('./style').styleOnSelect; +Choropleth.hoverPoints = _dereq_('./hover'); +Choropleth.eventData = _dereq_('./event_data'); +Choropleth.selectPoints = _dereq_('./select'); + +Choropleth.moduleType = 'trace'; +Choropleth.name = 'choropleth'; +Choropleth.basePlotModule = _dereq_('../../plots/geo'); +Choropleth.categories = ['geo', 'noOpacity']; +Choropleth.meta = { + +}; + +module.exports = Choropleth; + +},{"../../plots/geo":775,"../heatmap/colorbar":948,"./attributes":902,"./calc":903,"./defaults":904,"./event_data":905,"./hover":906,"./plot":908,"./select":909,"./style":910}],908:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); +var polygon = _dereq_('../../lib/polygon'); + +var getTopojsonFeatures = _dereq_('../../lib/topojson_utils').getTopojsonFeatures; +var locationToFeature = _dereq_('../../lib/geo_location_utils').locationToFeature; +var style = _dereq_('./style').style; + +module.exports = function plot(gd, geo, calcData) { + for(var i = 0; i < calcData.length; i++) { + calcGeoJSON(calcData[i], geo.topojson); + } + + var choroplethLayer = geo.layers.backplot.select('.choroplethlayer'); + Lib.makeTraceGroups(choroplethLayer, calcData, 'trace choropleth').each(function(calcTrace) { + var sel = calcTrace[0].node3 = d3.select(this); + + var paths = sel.selectAll('path.choroplethlocation') + .data(Lib.identity); + + paths.enter().append('path') + .classed('choroplethlocation', true); + + paths.exit().remove(); + + // call style here within topojson request callback + style(gd, calcTrace); + }); +}; + +function calcGeoJSON(calcTrace, topojson) { + var trace = calcTrace[0].trace; + var len = calcTrace.length; + var features = getTopojsonFeatures(trace, topojson); + + for(var i = 0; i < len; i++) { + var calcPt = calcTrace[i]; + var feature = locationToFeature(trace.locationmode, calcPt.loc, features); + + if(!feature) { + calcPt.geojson = null; + continue; + } + + + calcPt.geojson = feature; + calcPt.ct = feature.properties.ct; + calcPt.index = i; + calcPt._polygons = feature2polygons(feature); + } +} + +function feature2polygons(feature) { + var geometry = feature.geometry; + var coords = geometry.coordinates; + var loc = feature.id; + + var polygons = []; + var appendPolygon, j, k, m; + + function doesCrossAntiMerdian(pts) { + for(var l = 0; l < pts.length - 1; l++) { + if(pts[l][0] > 0 && pts[l + 1][0] < 0) return l; + } + return null; + } + + if(loc === 'RUS' || loc === 'FJI') { + // Russia and Fiji have landmasses that cross the antimeridian, + // we need to add +360 to their longitude coordinates, so that + // polygon 'contains' doesn't get confused when crossing the antimeridian. + // + // Note that other countries have polygons on either side of the antimeridian + // (e.g. some Aleutian island for the USA), but those don't confuse + // the 'contains' method; these are skipped here. + appendPolygon = function(_pts) { + var pts; + + if(doesCrossAntiMerdian(_pts) === null) { + pts = _pts; + } else { + pts = new Array(_pts.length); + for(m = 0; m < _pts.length; m++) { + // do nut mutate calcdata[i][j].geojson !! + pts[m] = [ + _pts[m][0] < 0 ? _pts[m][0] + 360 : _pts[m][0], + _pts[m][1] + ]; + } + } + + polygons.push(polygon.tester(pts)); + }; + } else if(loc === 'ATA') { + // Antarctica has a landmass that wraps around every longitudes which + // confuses the 'contains' methods. + appendPolygon = function(pts) { + var crossAntiMeridianIndex = doesCrossAntiMerdian(pts); + + // polygon that do not cross anti-meridian need no special handling + if(crossAntiMeridianIndex === null) { + return polygons.push(polygon.tester(pts)); + } + + // stitch polygon by adding pt over South Pole, + // so that it covers the projected region covers all latitudes + // + // Note that the algorithm below only works for polygons that + // start and end on longitude -180 (like the ones built by + // https://github.com/etpinard/sane-topojson). + var stitch = new Array(pts.length + 1); + var si = 0; + + for(m = 0; m < pts.length; m++) { + if(m > crossAntiMeridianIndex) { + stitch[si++] = [pts[m][0] + 360, pts[m][1]]; + } else if(m === crossAntiMeridianIndex) { + stitch[si++] = pts[m]; + stitch[si++] = [pts[m][0], -90]; + } else { + stitch[si++] = pts[m]; + } + } + + // polygon.tester by default appends pt[0] to the points list, + // we must remove it here, to avoid a jump in longitude from 180 to -180, + // that would confuse the 'contains' method + var tester = polygon.tester(stitch); + tester.pts.pop(); + polygons.push(tester); + }; + } else { + // otherwise using same array ref is fine + appendPolygon = function(pts) { + polygons.push(polygon.tester(pts)); + }; + } + + switch(geometry.type) { + case 'MultiPolygon': + for(j = 0; j < coords.length; j++) { + for(k = 0; k < coords[j].length; k++) { + appendPolygon(coords[j][k]); + } + } + break; + case 'Polygon': + for(j = 0; j < coords.length; j++) { + appendPolygon(coords[j]); + } + break; + } + + return polygons; +} + +},{"../../lib":696,"../../lib/geo_location_utils":688,"../../lib/polygon":708,"../../lib/topojson_utils":723,"./style":910,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],909:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + + var i, di, ct, x, y; + + if(selectionTester === false) { + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + di = cd[i]; + ct = di.ct; + + if(!ct) continue; + + x = xa.c2p(ct); + y = ya.c2p(ct); + + if(selectionTester.contains([x, y], null, i, searchInfo)) { + selection.push({ + pointNumber: i, + lon: ct[0], + lat: ct[1] + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + + return selection; +}; + +},{}],910:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Colorscale = _dereq_('../../components/colorscale'); + +function style(gd, calcTrace) { + if(calcTrace) styleTrace(gd, calcTrace); +} + +function styleTrace(gd, calcTrace) { + var trace = calcTrace[0].trace; + var s = calcTrace[0].node3; + var locs = s.selectAll('.choroplethlocation'); + var marker = trace.marker || {}; + var markerLine = marker.line || {}; + + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + trace.colorscale, + trace.zmin, + trace.zmax + ) + ); + + locs.each(function(d) { + d3.select(this) + .attr('fill', sclFunc(d.z)) + .call(Color.stroke, d.mlc || markerLine.color) + .call(Drawing.dashLine, '', d.mlw || markerLine.width || 0) + .style('opacity', marker.opacity); + }); + + Drawing.selectedPointStyle(locs, trace, gd); +} + +function styleOnSelect(gd, calcTrace) { + var s = calcTrace[0].node3; + var trace = calcTrace[0].trace; + + if(trace.selectedpoints) { + Drawing.selectedPointStyle(s.selectAll('.choroplethlocation'), trace, gd); + } else { + styleTrace(gd, calcTrace); + } +} + +module.exports = { + style: style, + styleOnSelect: styleOnSelect +}; + +},{"../../components/color":570,"../../components/colorscale":585,"../../components/drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],911:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var mesh3dAttrs = _dereq_('../mesh3d/attributes'); +var baseAttrs = _dereq_('../../plots/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var attrs = { + x: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + y: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + z: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + + u: { + valType: 'data_array', + editType: 'calc', + + }, + v: { + valType: 'data_array', + editType: 'calc', + + }, + w: { + valType: 'data_array', + editType: 'calc', + + }, + + // TODO add way to specify cone positions independently of the vector field + // provided, similar to MATLAB's coneplot Cx/Cy/Cz meshgrids, + // see https://www.mathworks.com/help/matlab/ref/coneplot.html + // + // Alternatively, if our goal is only to 'fill in gaps' in the vector data, + // we could try to extend the heatmap 'connectgaps' algorithm to 3D. + // From AJ: this particular algorithm which amounts to a Poisson equation, + // both for interpolation and extrapolation - is the right one to use for + // cones too. It makes a field with zero divergence, which is a good + // baseline assumption for vector fields. + // + // cones: { + // // potential attributes to add: + // // + // // - meshmode: 'cartesian-product', 'pts', 'grid' + // // + // // under `meshmode: 'grid'` + // // - (x|y|z)grid.start + // // - (x|y|z)grid.end + // // - (x|y|z)grid.size + // + // x: { + // valType: 'data_array', + // editType: 'calc', + // + // }, + // y: { + // valType: 'data_array', + // editType: 'calc', + // + // }, + // z: { + // valType: 'data_array', + // editType: 'calc', + // + // }, + // + // editType: 'calc', + // + // }, + + sizemode: { + valType: 'enumerated', + values: ['scaled', 'absolute'], + + editType: 'calc', + dflt: 'scaled', + + }, + sizeref: { + valType: 'number', + + editType: 'calc', + min: 0, + + }, + + anchor: { + valType: 'enumerated', + + editType: 'calc', + values: ['tip', 'tail', 'cm', 'center'], + dflt: 'cm', + + }, + + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'calc', + + } +}; + +extendFlat(attrs, colorscaleAttrs('', { + colorAttr: 'u/v/w norm', + showScaleDflt: true, + editTypeOverride: 'calc' +}), { + colorbar: colorbarAttrs +}); + +var fromMesh3d = ['opacity', 'lightposition', 'lighting']; + +fromMesh3d.forEach(function(k) { + attrs[k] = mesh3dAttrs[k]; +}); + +attrs.hoverinfo = extendFlat({}, baseAttrs.hoverinfo, { + editType: 'calc', + flags: ['x', 'y', 'z', 'u', 'v', 'w', 'norm', 'text', 'name'], + dflt: 'x+y+z+norm+text+name' +}); + +attrs.transforms = undefined; + +module.exports = attrs; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../mesh3d/attributes":986}],912:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); + +module.exports = function calc(gd, trace) { + var u = trace.u; + var v = trace.v; + var w = trace.w; + var len = Math.min( + trace.x.length, trace.y.length, trace.z.length, + u.length, v.length, w.length + ); + var normMax = -Infinity; + var normMin = Infinity; + + for(var i = 0; i < len; i++) { + var uu = u[i]; + var vv = v[i]; + var ww = w[i]; + var norm = Math.sqrt(uu * uu + vv * vv + ww * ww); + + normMax = Math.max(normMax, norm); + normMin = Math.min(normMin, norm); + } + + trace._len = len; + trace._normMax = normMax; + + colorscaleCalc(trace, [normMin, normMax], '', 'c'); +}; + +},{"../../components/colorscale/calc":578}],913:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var conePlot = _dereq_('gl-cone3d'); +var createConeMesh = _dereq_('gl-cone3d').createConeMesh; + +var simpleMap = _dereq_('../../lib').simpleMap; +var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; +var zip3 = _dereq_('../../plots/gl3d/zip3'); + +function Cone(scene, uid) { + this.scene = scene; + this.uid = uid; + this.mesh = null; + this.data = null; +} + +var proto = Cone.prototype; + +proto.handlePick = function(selection) { + if(selection.object === this.mesh) { + var selectIndex = selection.index = selection.data.index; + var xx = this.data.x[selectIndex]; + var yy = this.data.y[selectIndex]; + var zz = this.data.z[selectIndex]; + var uu = this.data.u[selectIndex]; + var vv = this.data.v[selectIndex]; + var ww = this.data.w[selectIndex]; + + selection.traceCoordinate = [ + xx, yy, zz, + uu, vv, ww, + Math.sqrt(uu * uu + vv * vv + ww * ww) + ]; + + var text = this.data.text; + if(Array.isArray(text) && text[selectIndex] !== undefined) { + selection.textLabel = text[selectIndex]; + } else if(text) { + selection.textLabel = text; + } + + return true; + } +}; + +var axisName2scaleIndex = {xaxis: 0, yaxis: 1, zaxis: 2}; +var anchor2coneOffset = {tip: 1, tail: 0, cm: 0.25, center: 0.5}; +var anchor2coneSpan = {tip: 1, tail: 1, cm: 0.75, center: 0.5}; + +function convert(scene, trace) { + var sceneLayout = scene.fullSceneLayout; + var dataScale = scene.dataScale; + var coneOpts = {}; + + function toDataCoords(arr, axisName) { + var ax = sceneLayout[axisName]; + var scale = dataScale[axisName2scaleIndex[axisName]]; + return simpleMap(arr, function(v) { return ax.d2l(v) * scale; }); + } + + coneOpts.vectors = zip3( + toDataCoords(trace.u, 'xaxis'), + toDataCoords(trace.v, 'yaxis'), + toDataCoords(trace.w, 'zaxis'), + trace._len + ); + + coneOpts.positions = zip3( + toDataCoords(trace.x, 'xaxis'), + toDataCoords(trace.y, 'yaxis'), + toDataCoords(trace.z, 'zaxis'), + trace._len + ); + + coneOpts.colormap = parseColorScale(trace.colorscale); + coneOpts.vertexIntensityBounds = [trace.cmin / trace._normMax, trace.cmax / trace._normMax]; + coneOpts.coneOffset = anchor2coneOffset[trace.anchor]; + + if(trace.sizemode === 'scaled') { + // unitless sizeref + coneOpts.coneSize = trace.sizeref || 0.5; + } else { + // sizeref here has unit of velocity + coneOpts.coneSize = trace.sizeref && trace._normMax ? + trace.sizeref / trace._normMax : + 0.5; + } + + var meshData = conePlot(coneOpts); + + // pass gl-mesh3d lighting attributes + var lp = trace.lightposition; + meshData.lightPosition = [lp.x, lp.y, lp.z]; + meshData.ambient = trace.lighting.ambient; + meshData.diffuse = trace.lighting.diffuse; + meshData.specular = trace.lighting.specular; + meshData.roughness = trace.lighting.roughness; + meshData.fresnel = trace.lighting.fresnel; + meshData.opacity = trace.opacity; + + // stash autorange pad value + trace._pad = anchor2coneSpan[trace.anchor] * meshData.vectorScale * meshData.coneScale * trace._normMax; + + return meshData; +} + +proto.update = function(data) { + this.data = data; + + var meshData = convert(this.scene, data); + this.mesh.update(meshData); +}; + +proto.dispose = function() { + this.scene.glplot.remove(this.mesh); + this.mesh.dispose(); +}; + +function createConeTrace(scene, data) { + var gl = scene.glplot.gl; + + var meshData = convert(scene, data); + var mesh = createConeMesh(gl, meshData); + + var cone = new Cone(scene, data.uid); + cone.mesh = mesh; + cone.data = data; + mesh._trace = cone; + + scene.glplot.add(mesh); + + return cone; +} + +module.exports = createConeTrace; + +},{"../../lib":696,"../../lib/gl_format_color":692,"../../plots/gl3d/zip3":798,"gl-cone3d":231}],914:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var u = coerce('u'); + var v = coerce('v'); + var w = coerce('w'); + + var x = coerce('x'); + var y = coerce('y'); + var z = coerce('z'); + + if( + !u || !u.length || !v || !v.length || !w || !w.length || + !x || !x.length || !y || !y.length || !z || !z.length + ) { + traceOut.visible = false; + return; + } + + coerce('sizeref'); + coerce('sizemode'); + + coerce('anchor'); + + coerce('lighting.ambient'); + coerce('lighting.diffuse'); + coerce('lighting.specular'); + coerce('lighting.roughness'); + coerce('lighting.fresnel'); + coerce('lightposition.x'); + coerce('lightposition.y'); + coerce('lightposition.z'); + + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); + + coerce('text'); + + // disable 1D transforms (for now) + traceOut._length = null; +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"./attributes":911}],915:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'cone', + basePlotModule: _dereq_('../../plots/gl3d'), + categories: ['gl3d'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + colorbar: { + min: 'cmin', + max: 'cmax' + }, + calc: _dereq_('./calc'), + plot: _dereq_('./convert'), + + meta: { + + } +}; + +},{"../../plots/gl3d":787,"./attributes":911,"./calc":912,"./convert":913,"./defaults":914}],916:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var heatmapAttrs = _dereq_('../heatmap/attributes'); +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; +var fontAttrs = _dereq_('../../plots/font_attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var filterOps = _dereq_('../../constants/filter_ops'); +var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2; +var INTERVAL_OPS = filterOps.INTERVAL_OPS; + +var scatterLineAttrs = scatterAttrs.line; + +module.exports = extendFlat({ + z: heatmapAttrs.z, + x: heatmapAttrs.x, + x0: heatmapAttrs.x0, + dx: heatmapAttrs.dx, + y: heatmapAttrs.y, + y0: heatmapAttrs.y0, + dy: heatmapAttrs.dy, + text: heatmapAttrs.text, + transpose: heatmapAttrs.transpose, + xtype: heatmapAttrs.xtype, + ytype: heatmapAttrs.ytype, + zhoverformat: heatmapAttrs.zhoverformat, + + connectgaps: heatmapAttrs.connectgaps, + + fillcolor: { + valType: 'color', + + editType: 'calc', + + }, + + autocontour: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + impliedEdits: { + 'contours.start': undefined, + 'contours.end': undefined, + 'contours.size': undefined + }, + + }, + ncontours: { + valType: 'integer', + dflt: 15, + min: 1, + + editType: 'calc', + + }, + + contours: { + type: { + valType: 'enumerated', + values: ['levels', 'constraint'], + dflt: 'levels', + + editType: 'calc', + + }, + start: { + valType: 'number', + dflt: null, + + editType: 'plot', + impliedEdits: {'^autocontour': false}, + + }, + end: { + valType: 'number', + dflt: null, + + editType: 'plot', + impliedEdits: {'^autocontour': false}, + + }, + size: { + valType: 'number', + dflt: null, + min: 0, + + editType: 'plot', + impliedEdits: {'^autocontour': false}, + + }, + coloring: { + valType: 'enumerated', + values: ['fill', 'heatmap', 'lines', 'none'], + dflt: 'fill', + + editType: 'calc', + + }, + showlines: { + valType: 'boolean', + dflt: true, + + editType: 'plot', + + }, + showlabels: { + valType: 'boolean', + dflt: false, + + editType: 'plot', + + }, + labelfont: fontAttrs({ + editType: 'plot', + colorEditType: 'style', + + }), + labelformat: { + valType: 'string', + dflt: '', + + editType: 'plot', + + }, + operation: { + valType: 'enumerated', + values: [].concat(COMPARISON_OPS2).concat(INTERVAL_OPS), + + dflt: '=', + editType: 'calc', + + }, + value: { + valType: 'any', + dflt: 0, + + editType: 'calc', + + }, + editType: 'calc', + impliedEdits: {'autocontour': false} + }, + + line: { + color: extendFlat({}, scatterLineAttrs.color, { + editType: 'style+colorbars', + + }), + width: extendFlat({}, scatterLineAttrs.width, { + editType: 'style+colorbars' + }), + dash: dash, + smoothing: extendFlat({}, scatterLineAttrs.smoothing, { + + }), + editType: 'plot' + } +}, + colorscaleAttrs('', { + cLetter: 'z', + autoColorDflt: false, + editTypeOverride: 'calc' + }), + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../components/drawing/attributes":594,"../../constants/filter_ops":669,"../../lib/extend":685,"../../plots/font_attributes":771,"../heatmap/attributes":945,"../scatter/attributes":1043}],917:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var heatmapCalc = _dereq_('../heatmap/calc'); +var setContours = _dereq_('./set_contours'); + +// most is the same as heatmap calc, then adjust it +// though a few things inside heatmap calc still look for +// contour maps, because the makeBoundArray calls are too entangled +module.exports = function calc(gd, trace) { + var cd = heatmapCalc(gd, trace); + setContours(trace); + return cd; +}; + +},{"../heatmap/calc":946,"./set_contours":935}],918:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function(pathinfo, operation, perimeter, trace) { + // Abandon all hope, ye who enter here. + var i, v1, v2; + var pi0 = pathinfo[0]; + var na = pi0.x.length; + var nb = pi0.y.length; + var z = pi0.z; + var contours = trace.contours; + + var boundaryMax = -Infinity; + var boundaryMin = Infinity; + + for(i = 0; i < nb; i++) { + boundaryMin = Math.min(boundaryMin, z[i][0]); + boundaryMin = Math.min(boundaryMin, z[i][na - 1]); + boundaryMax = Math.max(boundaryMax, z[i][0]); + boundaryMax = Math.max(boundaryMax, z[i][na - 1]); + } + + for(i = 1; i < na - 1; i++) { + boundaryMin = Math.min(boundaryMin, z[0][i]); + boundaryMin = Math.min(boundaryMin, z[nb - 1][i]); + boundaryMax = Math.max(boundaryMax, z[0][i]); + boundaryMax = Math.max(boundaryMax, z[nb - 1][i]); + } + + pi0.prefixBoundary = false; + + switch(operation) { + case '>': + if(contours.value > boundaryMax) { + pi0.prefixBoundary = true; + } + break; + case '<': + if(contours.value < boundaryMin) { + pi0.prefixBoundary = true; + } + break; + case '[]': + v1 = Math.min.apply(null, contours.value); + v2 = Math.max.apply(null, contours.value); + if(v2 < boundaryMin || v1 > boundaryMax) { + pi0.prefixBoundary = true; + } + break; + case '][': + v1 = Math.min.apply(null, contours.value); + v2 = Math.max.apply(null, contours.value); + if(v1 < boundaryMin && v2 > boundaryMax) { + pi0.prefixBoundary = true; + } + break; + } +}; + +},{}],919:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawColorbar = _dereq_('../../components/colorbar/draw'); + +var makeColorMap = _dereq_('./make_color_map'); +var endPlus = _dereq_('./end_plus'); + + +module.exports = function colorbar(gd, cd) { + var trace = cd[0].trace; + var cbId = 'cb' + trace.uid; + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + + if(!trace.showscale) return; + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + + var contours = trace.contours; + var line = trace.line; + var cs = contours.size || 1; + var coloring = contours.coloring; + + var colorMap = makeColorMap(trace, {isColorbar: true}); + + cb.fillgradient(coloring === 'heatmap' ? trace.colorscale : '') + .zrange(coloring === 'heatmap' ? [trace.zmin, trace.zmax] : '') + .fillcolor((coloring === 'fill') ? colorMap : '') + .line({ + color: coloring === 'lines' ? colorMap : line.color, + width: contours.showlines !== false ? line.width : 0, + dash: line.dash + }) + .levels({ + start: contours.start, + end: endPlus(contours), + size: cs + }) + .options(trace.colorbar)(); +}; + +},{"../../components/colorbar/draw":575,"./end_plus":927,"./make_color_map":932}],920:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; +module.exports = { + // some constants to help with marching squares algorithm + // where does the path start for each index? + BOTTOMSTART: [1, 9, 13, 104, 713], + TOPSTART: [4, 6, 7, 104, 713], + LEFTSTART: [8, 12, 14, 208, 1114], + RIGHTSTART: [2, 3, 11, 208, 1114], + + // which way [dx,dy] do we leave a given index? + // saddles are already disambiguated + NEWDELTA: [ + null, [-1, 0], [0, -1], [-1, 0], + [1, 0], null, [0, -1], [-1, 0], + [0, 1], [0, 1], null, [0, 1], + [1, 0], [1, 0], [0, -1] + ], + + // for each saddle, the first index here is used + // for dx||dy<0, the second for dx||dy>0 + CHOOSESADDLE: { + 104: [4, 1], + 208: [2, 8], + 713: [7, 13], + 1114: [11, 14] + }, + + // after one index has been used for a saddle, which do we + // substitute to be used up later? + SADDLEREMAINDER: {1: 4, 2: 8, 4: 1, 7: 13, 8: 2, 11: 14, 13: 7, 14: 11}, + + // length of a contour, as a multiple of the plot area diagonal, per label + LABELDISTANCE: 2, + + // number of contour levels after which we start increasing the number of + // labels we draw. Many contours means they will generally be close + // together, so it will be harder to follow a long way to find a label + LABELINCREASE: 10, + + // minimum length of a contour line, as a multiple of the label length, + // at which we draw *any* labels + LABELMIN: 3, + + // max number of labels to draw on a single contour path, no matter how long + LABELMAX: 10, + + // constants for the label position cost function + LABELOPTIMIZER: { + // weight given to edge proximity + EDGECOST: 1, + // weight given to the angle off horizontal + ANGLECOST: 1, + // weight given to distance from already-placed labels + NEIGHBORCOST: 5, + // cost multiplier for labels on the same level + SAMELEVELFACTOR: 10, + // minimum distance (as a multiple of the label length) + // for labels on the same level + SAMELEVELDISTANCE: 5, + // maximum cost before we won't even place the label + MAXCOST: 100, + // number of evenly spaced points to look at in the first + // iteration of the search + INITIALSEARCHPOINTS: 10, + // number of binary search iterations after the initial wide search + ITERATIONS: 5 + } +}; + +},{}],921:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; +var isNumeric = _dereq_('fast-isnumeric'); + +var handleLabelDefaults = _dereq_('./label_defaults'); + +var Color = _dereq_('../../components/color'); +var addOpacity = Color.addOpacity; +var opacity = Color.opacity; + +var filterOps = _dereq_('../../constants/filter_ops'); +var CONSTRAINT_REDUCTION = filterOps.CONSTRAINT_REDUCTION; +var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2; + +module.exports = function handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor, opts) { + var contours = traceOut.contours; + var showLines, lineColor, fillColor; + + var operation = coerce('contours.operation'); + contours._operation = CONSTRAINT_REDUCTION[operation]; + + handleConstraintValueDefaults(coerce, contours); + + if(operation === '=') { + showLines = contours.showlines = true; + } + else { + showLines = coerce('contours.showlines'); + fillColor = coerce('fillcolor', addOpacity( + (traceIn.line || {}).color || defaultColor, 0.5 + )); + } + + if(showLines) { + var lineDfltColor = fillColor && opacity(fillColor) ? + addOpacity(traceOut.fillcolor, 1) : + defaultColor; + lineColor = coerce('line.color', lineDfltColor); + coerce('line.width', 2); + coerce('line.dash'); + } + + coerce('line.smoothing'); + + handleLabelDefaults(coerce, layout, lineColor, opts); +}; + +function handleConstraintValueDefaults(coerce, contours) { + var zvalue; + + if(COMPARISON_OPS2.indexOf(contours.operation) === -1) { + // Requires an array of two numbers: + coerce('contours.value', [0, 1]); + + if(!Array.isArray(contours.value)) { + if(isNumeric(contours.value)) { + zvalue = parseFloat(contours.value); + contours.value = [zvalue, zvalue + 1]; + } + } else if(contours.value.length > 2) { + contours.value = contours.value.slice(2); + } else if(contours.length === 0) { + contours.value = [0, 1]; + } else if(contours.length < 2) { + zvalue = parseFloat(contours.value[0]); + contours.value = [zvalue, zvalue + 1]; + } else { + contours.value = [ + parseFloat(contours.value[0]), + parseFloat(contours.value[1]) + ]; + } + } else { + // Requires a single scalar: + coerce('contours.value', 0); + + if(!isNumeric(contours.value)) { + if(Array.isArray(contours.value)) { + contours.value = parseFloat(contours.value[0]); + } else { + contours.value = 0; + } + } + } +} + +},{"../../components/color":570,"../../constants/filter_ops":669,"./label_defaults":931,"fast-isnumeric":214}],922:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var filterOps = _dereq_('../../constants/filter_ops'); +var isNumeric = _dereq_('fast-isnumeric'); + +// This syntax conforms to the existing filter transform syntax, but we don't care +// about open vs. closed intervals for simply drawing contours constraints: +module.exports = { + '[]': makeRangeSettings('[]'), + '][': makeRangeSettings(']['), + '>': makeInequalitySettings('>'), + '<': makeInequalitySettings('<'), + '=': makeInequalitySettings('=') +}; + +// This does not in any way shape or form support calendars. It's adapted from +// transforms/filter.js. +function coerceValue(operation, value) { + var hasArrayValue = Array.isArray(value); + + var coercedValue; + + function coerce(value) { + return isNumeric(value) ? (+value) : null; + } + + if(filterOps.COMPARISON_OPS2.indexOf(operation) !== -1) { + coercedValue = hasArrayValue ? coerce(value[0]) : coerce(value); + } else if(filterOps.INTERVAL_OPS.indexOf(operation) !== -1) { + coercedValue = hasArrayValue ? + [coerce(value[0]), coerce(value[1])] : + [coerce(value), coerce(value)]; + } else if(filterOps.SET_OPS.indexOf(operation) !== -1) { + coercedValue = hasArrayValue ? value.map(coerce) : [coerce(value)]; + } + + return coercedValue; +} + +// Returns a parabola scaled so that the min/max is either +/- 1 and zero at the two values +// provided. The data is mapped by this function when constructing intervals so that it's +// very easy to construct contours as normal. +function makeRangeSettings(operation) { + return function(value) { + value = coerceValue(operation, value); + + // Ensure proper ordering: + var min = Math.min(value[0], value[1]); + var max = Math.max(value[0], value[1]); + + return { + start: min, + end: max, + size: max - min + }; + }; +} + +function makeInequalitySettings(operation) { + return function(value) { + value = coerceValue(operation, value); + + return { + start: value, + end: Infinity, + size: Infinity + }; + }; +} + +},{"../../constants/filter_ops":669,"fast-isnumeric":214}],923:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function handleContourDefaults(traceIn, traceOut, coerce, coerce2) { + var contourStart = coerce2('contours.start'); + var contourEnd = coerce2('contours.end'); + var missingEnd = (contourStart === false) || (contourEnd === false); + + // normally we only need size if autocontour is off. But contour.calc + // pushes its calculated contour size back to the input trace, so for + // things like restyle that can call supplyDefaults without calc + // after the initial draw, we can just reuse the previous calculation + var contourSize = coerce('contours.size'); + var autoContour; + + if(missingEnd) autoContour = traceOut.autocontour = true; + else autoContour = coerce('autocontour', false); + + if(autoContour || !contourSize) coerce('ncontours'); +}; + +},{}],924:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +// The contour extraction is great, except it totally fails for constraints because we +// need weird range loops and flipped contours instead of the usual format. This function +// does some weird manipulation of the extracted pathinfo data such that it magically +// draws contours correctly *as* constraints. +module.exports = function(pathinfo, operation) { + var i, pi0, pi1; + + var op0 = function(arr) { return arr.reverse(); }; + var op1 = function(arr) { return arr; }; + + switch(operation) { + case '=': + case '<': + return pathinfo; + case '>': + if(pathinfo.length !== 1) { + Lib.warn('Contour data invalid for the specified inequality operation.'); + } + + // In this case there should be exactly two contour levels in pathinfo. We + // simply concatenate the info into one pathinfo and flip all of the data + // in one. This will draw the contour as closed. + pi0 = pathinfo[0]; + + for(i = 0; i < pi0.edgepaths.length; i++) { + pi0.edgepaths[i] = op0(pi0.edgepaths[i]); + } + + for(i = 0; i < pi0.paths.length; i++) { + pi0.paths[i] = op0(pi0.paths[i]); + } + return pathinfo; + case '][': + var tmp = op0; + op0 = op1; + op1 = tmp; + // It's a nice rule, except this definitely *is* what's intended here. + /* eslint-disable: no-fallthrough */ + case '[]': + /* eslint-enable: no-fallthrough */ + if(pathinfo.length !== 2) { + Lib.warn('Contour data invalid for the specified inequality range operation.'); + } + + // In this case there should be exactly two contour levels in pathinfo. We + // simply concatenate the info into one pathinfo and flip all of the data + // in one. This will draw the contour as closed. + pi0 = copyPathinfo(pathinfo[0]); + pi1 = copyPathinfo(pathinfo[1]); + + for(i = 0; i < pi0.edgepaths.length; i++) { + pi0.edgepaths[i] = op0(pi0.edgepaths[i]); + } + + for(i = 0; i < pi0.paths.length; i++) { + pi0.paths[i] = op0(pi0.paths[i]); + } + + while(pi1.edgepaths.length) { + pi0.edgepaths.push(op1(pi1.edgepaths.shift())); + } + while(pi1.paths.length) { + pi0.paths.push(op1(pi1.paths.shift())); + } + return [pi0]; + } +}; + +function copyPathinfo(pi) { + return Lib.extendFlat({}, pi, { + edgepaths: Lib.extendDeep([], pi.edgepaths), + paths: Lib.extendDeep([], pi.paths) + }); +} + +},{"../../lib":696}],925:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleXYZDefaults = _dereq_('../heatmap/xyz_defaults'); +var handleConstraintDefaults = _dereq_('./constraint_defaults'); +var handleContoursDefaults = _dereq_('./contours_defaults'); +var handleStyleDefaults = _dereq_('./style_defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + function coerce2(attr) { + return Lib.coerce2(traceIn, traceOut, attributes, attr); + } + + var len = handleXYZDefaults(traceIn, traceOut, coerce, layout); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + var isConstraint = (coerce('contours.type') === 'constraint'); + coerce('connectgaps', Lib.isArray1D(traceOut.z)); + + if(isConstraint) { + handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor); + } + else { + handleContoursDefaults(traceIn, traceOut, coerce, coerce2); + handleStyleDefaults(traceIn, traceOut, coerce, layout); + } +}; + +},{"../../lib":696,"../heatmap/xyz_defaults":960,"./attributes":916,"./constraint_defaults":921,"./contours_defaults":923,"./style_defaults":937}],926:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var constraintMapping = _dereq_('./constraint_mapping'); +var endPlus = _dereq_('./end_plus'); + +module.exports = function emptyPathinfo(contours, plotinfo, cd0) { + var contoursFinal = (contours.type === 'constraint') ? + constraintMapping[contours._operation](contours.value) : + contours; + + var cs = contoursFinal.size; + var pathinfo = []; + var end = endPlus(contoursFinal); + + var carpet = cd0.trace._carpetTrace; + + var basePathinfo = carpet ? { + // store axes so we can convert to px + xaxis: carpet.aaxis, + yaxis: carpet.baxis, + // full data arrays to use for interpolation + x: cd0.a, + y: cd0.b + } : { + xaxis: plotinfo.xaxis, + yaxis: plotinfo.yaxis, + x: cd0.x, + y: cd0.y + }; + + for(var ci = contoursFinal.start; ci < end; ci += cs) { + pathinfo.push(Lib.extendFlat({ + level: ci, + // all the cells with nontrivial marching index + crossings: {}, + // starting points on the edges of the lattice for each contour + starts: [], + // all unclosed paths (may have less items than starts, + // if a path is closed by rounding) + edgepaths: [], + // all closed paths + paths: [], + z: cd0.z, + smoothing: cd0.trace.line.smoothing + }, basePathinfo)); + + if(pathinfo.length > 1000) { + Lib.warn('Too many contours, clipping at 1000', contours); + break; + } + } + return pathinfo; +}; + +},{"../../lib":696,"./constraint_mapping":922,"./end_plus":927}],927:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* + * tiny helper to move the end of the contours a little to prevent + * losing the last contour to rounding errors + */ +module.exports = function endPlus(contours) { + return contours.end + contours.size / 1e6; +}; + +},{}],928:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var constants = _dereq_('./constants'); + +module.exports = function findAllPaths(pathinfo, xtol, ytol) { + var cnt, + startLoc, + i, + pi, + j; + + // Default just passes these values through as they were before: + xtol = xtol || 0.01; + ytol = ytol || 0.01; + + for(i = 0; i < pathinfo.length; i++) { + pi = pathinfo[i]; + + for(j = 0; j < pi.starts.length; j++) { + startLoc = pi.starts[j]; + makePath(pi, startLoc, 'edge', xtol, ytol); + } + + cnt = 0; + while(Object.keys(pi.crossings).length && cnt < 10000) { + cnt++; + startLoc = Object.keys(pi.crossings)[0].split(',').map(Number); + makePath(pi, startLoc, undefined, xtol, ytol); + } + if(cnt === 10000) Lib.log('Infinite loop in contour?'); + } +}; + +function equalPts(pt1, pt2, xtol, ytol) { + return Math.abs(pt1[0] - pt2[0]) < xtol && + Math.abs(pt1[1] - pt2[1]) < ytol; +} + +// distance in index units - uses the 3rd and 4th items in points +function ptDist(pt1, pt2) { + var dx = pt1[2] - pt2[2], + dy = pt1[3] - pt2[3]; + return Math.sqrt(dx * dx + dy * dy); +} + +function makePath(pi, loc, edgeflag, xtol, ytol) { + var startLocStr = loc.join(','); + var locStr = startLocStr; + var mi = pi.crossings[locStr]; + var marchStep = startStep(mi, edgeflag, loc); + // start by going backward a half step and finding the crossing point + var pts = [getInterpPx(pi, loc, [-marchStep[0], -marchStep[1]])]; + var startStepStr = marchStep.join(','); + var m = pi.z.length; + var n = pi.z[0].length; + var cnt; + + // now follow the path + for(cnt = 0; cnt < 10000; cnt++) { // just to avoid infinite loops + if(mi > 20) { + mi = constants.CHOOSESADDLE[mi][(marchStep[0] || marchStep[1]) < 0 ? 0 : 1]; + pi.crossings[locStr] = constants.SADDLEREMAINDER[mi]; + } + else { + delete pi.crossings[locStr]; + } + + marchStep = constants.NEWDELTA[mi]; + if(!marchStep) { + Lib.log('Found bad marching index:', mi, loc, pi.level); + break; + } + + // find the crossing a half step forward, and then take the full step + pts.push(getInterpPx(pi, loc, marchStep)); + loc[0] += marchStep[0]; + loc[1] += marchStep[1]; + + // don't include the same point multiple times + if(equalPts(pts[pts.length - 1], pts[pts.length - 2], xtol, ytol)) pts.pop(); + locStr = loc.join(','); + + var atEdge = (marchStep[0] && (loc[0] < 0 || loc[0] > n - 2)) || + (marchStep[1] && (loc[1] < 0 || loc[1] > m - 2)), + closedLoop = (locStr === startLocStr) && (marchStep.join(',') === startStepStr); + + // have we completed a loop, or reached an edge? + if((closedLoop) || (edgeflag && atEdge)) break; + + mi = pi.crossings[locStr]; + } + + if(cnt === 10000) { + Lib.log('Infinite loop in contour?'); + } + var closedpath = equalPts(pts[0], pts[pts.length - 1], xtol, ytol); + var totaldist = 0; + var distThresholdFactor = 0.2 * pi.smoothing; + var alldists = []; + var cropstart = 0; + var distgroup, cnt2, cnt3, newpt, ptcnt, ptavg, thisdist, + i, j, edgepathi, edgepathj; + + /* + * Check for points that are too close together (<1/5 the average dist + * *in grid index units* (important for log axes and nonuniform grids), + * less if less smoothed) and just take the center (or avg of center 2). + * This cuts down on funny behavior when a point is very close to a + * contour level. + */ + for(cnt = 1; cnt < pts.length; cnt++) { + thisdist = ptDist(pts[cnt], pts[cnt - 1]); + totaldist += thisdist; + alldists.push(thisdist); + } + + var distThreshold = totaldist / alldists.length * distThresholdFactor; + + function getpt(i) { return pts[i % pts.length]; } + + for(cnt = pts.length - 2; cnt >= cropstart; cnt--) { + distgroup = alldists[cnt]; + if(distgroup < distThreshold) { + cnt3 = 0; + for(cnt2 = cnt - 1; cnt2 >= cropstart; cnt2--) { + if(distgroup + alldists[cnt2] < distThreshold) { + distgroup += alldists[cnt2]; + } + else break; + } + + // closed path with close points wrapping around the boundary? + if(closedpath && cnt === pts.length - 2) { + for(cnt3 = 0; cnt3 < cnt2; cnt3++) { + if(distgroup + alldists[cnt3] < distThreshold) { + distgroup += alldists[cnt3]; + } + else break; + } + } + ptcnt = cnt - cnt2 + cnt3 + 1; + ptavg = Math.floor((cnt + cnt2 + cnt3 + 2) / 2); + + // either endpoint included: keep the endpoint + if(!closedpath && cnt === pts.length - 2) newpt = pts[pts.length - 1]; + else if(!closedpath && cnt2 === -1) newpt = pts[0]; + + // odd # of points - just take the central one + else if(ptcnt % 2) newpt = getpt(ptavg); + + // even # of pts - average central two + else { + newpt = [(getpt(ptavg)[0] + getpt(ptavg + 1)[0]) / 2, + (getpt(ptavg)[1] + getpt(ptavg + 1)[1]) / 2]; + } + + pts.splice(cnt2 + 1, cnt - cnt2 + 1, newpt); + cnt = cnt2 + 1; + if(cnt3) cropstart = cnt3; + if(closedpath) { + if(cnt === pts.length - 2) pts[cnt3] = pts[pts.length - 1]; + else if(cnt === 0) pts[pts.length - 1] = pts[0]; + } + } + } + pts.splice(0, cropstart); + + // done with the index parts - remove them so path generation works right + // because it depends on only having [xpx, ypx] + for(cnt = 0; cnt < pts.length; cnt++) pts[cnt].length = 2; + + // don't return single-point paths (ie all points were the same + // so they got deleted?) + if(pts.length < 2) return; + else if(closedpath) { + pts.pop(); + pi.paths.push(pts); + } + else { + if(!edgeflag) { + Lib.log('Unclosed interior contour?', + pi.level, startLocStr, pts.join('L')); + } + + // edge path - does it start where an existing edge path ends, or vice versa? + var merged = false; + for(i = 0; i < pi.edgepaths.length; i++) { + edgepathi = pi.edgepaths[i]; + if(!merged && equalPts(edgepathi[0], pts[pts.length - 1], xtol, ytol)) { + pts.pop(); + merged = true; + + // now does it ALSO meet the end of another (or the same) path? + var doublemerged = false; + for(j = 0; j < pi.edgepaths.length; j++) { + edgepathj = pi.edgepaths[j]; + if(equalPts(edgepathj[edgepathj.length - 1], pts[0], xtol, ytol)) { + doublemerged = true; + pts.shift(); + pi.edgepaths.splice(i, 1); + if(j === i) { + // the path is now closed + pi.paths.push(pts.concat(edgepathj)); + } + else { + if(j > i) j--; + pi.edgepaths[j] = edgepathj.concat(pts, edgepathi); + } + break; + } + } + if(!doublemerged) { + pi.edgepaths[i] = pts.concat(edgepathi); + } + } + } + for(i = 0; i < pi.edgepaths.length; i++) { + if(merged) break; + edgepathi = pi.edgepaths[i]; + if(equalPts(edgepathi[edgepathi.length - 1], pts[0], xtol, ytol)) { + pts.shift(); + pi.edgepaths[i] = edgepathi.concat(pts); + merged = true; + } + } + + if(!merged) pi.edgepaths.push(pts); + } +} + +// special function to get the marching step of the +// first point in the path (leading to loc) +function startStep(mi, edgeflag, loc) { + var dx = 0, + dy = 0; + if(mi > 20 && edgeflag) { + // these saddles start at +/- x + if(mi === 208 || mi === 1114) { + // if we're starting at the left side, we must be going right + dx = loc[0] === 0 ? 1 : -1; + } + else { + // if we're starting at the bottom, we must be going up + dy = loc[1] === 0 ? 1 : -1; + } + } + else if(constants.BOTTOMSTART.indexOf(mi) !== -1) dy = 1; + else if(constants.LEFTSTART.indexOf(mi) !== -1) dx = 1; + else if(constants.TOPSTART.indexOf(mi) !== -1) dy = -1; + else dx = -1; + return [dx, dy]; +} + +/* + * Find the pixel coordinates of a particular crossing + * + * @param {object} pi: the pathinfo object at this level + * @param {array} loc: the grid index [x, y] of the crossing + * @param {array} step: the direction [dx, dy] we're moving on the grid + * + * @return {array} [xpx, ypx, xi, yi]: the first two are the pixel location, + * the next two are the interpolated grid indices, which we use for + * distance calculations to delete points that are too close together. + * This is important when the grid is nonuniform (and most dramatically when + * we're on log axes and include invalid (0 or negative) values. + * It's crucial to delete these extra two before turning an array of these + * points into a path, because those routines require length-2 points. + */ +function getInterpPx(pi, loc, step) { + var locx = loc[0] + Math.max(step[0], 0), + locy = loc[1] + Math.max(step[1], 0), + zxy = pi.z[locy][locx], + xa = pi.xaxis, + ya = pi.yaxis; + + if(step[1]) { + var dx = (pi.level - zxy) / (pi.z[locy][locx + 1] - zxy); + + return [xa.c2p((1 - dx) * pi.x[locx] + dx * pi.x[locx + 1], true), + ya.c2p(pi.y[locy], true), + locx + dx, locy]; + } + else { + var dy = (pi.level - zxy) / (pi.z[locy + 1][locx] - zxy); + return [xa.c2p(pi.x[locx], true), + ya.c2p((1 - dy) * pi.y[locy] + dy * pi.y[locy + 1], true), + locx, locy + dy]; + } +} + +},{"../../lib":696,"./constants":920}],929:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../../components/color'); + +var heatmapHoverPoints = _dereq_('../heatmap/hover'); + +module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) { + var hoverData = heatmapHoverPoints(pointData, xval, yval, hovermode, hoverLayer, true); + + if(hoverData) { + hoverData.forEach(function(hoverPt) { + var trace = hoverPt.trace; + if(trace.contours.type === 'constraint') { + if(trace.fillcolor && Color.opacity(trace.fillcolor)) { + hoverPt.color = Color.addOpacity(trace.fillcolor, 1); + } + else if(trace.contours.showlines && Color.opacity(trace.line.color)) { + hoverPt.color = Color.addOpacity(trace.line.color, 1); + } + } + }); + } + + return hoverData; +}; + +},{"../../components/color":570,"../heatmap/hover":952}],930:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Contour = {}; + +Contour.attributes = _dereq_('./attributes'); +Contour.supplyDefaults = _dereq_('./defaults'); +Contour.calc = _dereq_('./calc'); +Contour.plot = _dereq_('./plot').plot; +Contour.style = _dereq_('./style'); +Contour.colorbar = _dereq_('./colorbar'); +Contour.hoverPoints = _dereq_('./hover'); + +Contour.moduleType = 'trace'; +Contour.name = 'contour'; +Contour.basePlotModule = _dereq_('../../plots/cartesian'); +Contour.categories = ['cartesian', 'svg', '2dMap', 'contour', 'showLegend']; +Contour.meta = { + +}; + +module.exports = Contour; + +},{"../../plots/cartesian":756,"./attributes":916,"./calc":917,"./colorbar":919,"./defaults":925,"./hover":929,"./plot":934,"./style":936}],931:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +module.exports = function handleLabelDefaults(coerce, layout, lineColor, opts) { + if(!opts) opts = {}; + var showLabels = coerce('contours.showlabels'); + if(showLabels) { + var globalFont = layout.font; + Lib.coerceFont(coerce, 'contours.labelfont', { + family: globalFont.family, + size: globalFont.size, + color: lineColor + }); + coerce('contours.labelformat'); + } + + if(opts.hasHover !== false) coerce('zhoverformat'); +}; + +},{"../../lib":696}],932:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Colorscale = _dereq_('../../components/colorscale'); +var endPlus = _dereq_('./end_plus'); + +module.exports = function makeColorMap(trace) { + var contours = trace.contours, + start = contours.start, + end = endPlus(contours), + cs = contours.size || 1, + nc = Math.floor((end - start) / cs) + 1, + extra = contours.coloring === 'lines' ? 0 : 1; + + if(!isFinite(cs)) { + cs = 1; + nc = 1; + } + + var scl = trace.colorscale, + len = scl.length; + + var domain = new Array(len), + range = new Array(len); + + var si, i; + + if(contours.coloring === 'heatmap') { + if(trace.zauto && trace.autocontour === false) { + trace.zmin = start - cs / 2; + trace.zmax = trace.zmin + nc * cs; + } + + for(i = 0; i < len; i++) { + si = scl[i]; + + domain[i] = si[0] * (trace.zmax - trace.zmin) + trace.zmin; + range[i] = si[1]; + } + + // do the contours extend beyond the colorscale? + // if so, extend the colorscale with constants + var zRange = d3.extent([trace.zmin, trace.zmax, contours.start, + contours.start + cs * (nc - 1)]), + zmin = zRange[trace.zmin < trace.zmax ? 0 : 1], + zmax = zRange[trace.zmin < trace.zmax ? 1 : 0]; + + if(zmin !== trace.zmin) { + domain.splice(0, 0, zmin); + range.splice(0, 0, Range[0]); + } + + if(zmax !== trace.zmax) { + domain.push(zmax); + range.push(range[range.length - 1]); + } + } + else { + for(i = 0; i < len; i++) { + si = scl[i]; + + domain[i] = (si[0] * (nc + extra - 1) - (extra / 2)) * cs + start; + range[i] = si[1]; + } + } + + return Colorscale.makeColorScaleFunc({ + domain: domain, + range: range, + }, { + noNumericCheck: true + }); +}; + +},{"../../components/colorscale":585,"./end_plus":927,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],933:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var constants = _dereq_('./constants'); + +// Calculate all the marching indices, for ALL levels at once. +// since we want to be exhaustive we'll check for contour crossings +// at every intersection, rather than just following a path +// TODO: shorten the inner loop to only the relevant levels +module.exports = function makeCrossings(pathinfo) { + var z = pathinfo[0].z, + m = z.length, + n = z[0].length, // we already made sure z isn't ragged in interp2d + twoWide = m === 2 || n === 2, + xi, + yi, + startIndices, + ystartIndices, + label, + corners, + mi, + pi, + i; + + for(yi = 0; yi < m - 1; yi++) { + ystartIndices = []; + if(yi === 0) ystartIndices = ystartIndices.concat(constants.BOTTOMSTART); + if(yi === m - 2) ystartIndices = ystartIndices.concat(constants.TOPSTART); + + for(xi = 0; xi < n - 1; xi++) { + startIndices = ystartIndices.slice(); + if(xi === 0) startIndices = startIndices.concat(constants.LEFTSTART); + if(xi === n - 2) startIndices = startIndices.concat(constants.RIGHTSTART); + + label = xi + ',' + yi; + corners = [[z[yi][xi], z[yi][xi + 1]], + [z[yi + 1][xi], z[yi + 1][xi + 1]]]; + for(i = 0; i < pathinfo.length; i++) { + pi = pathinfo[i]; + mi = getMarchingIndex(pi.level, corners); + if(!mi) continue; + + pi.crossings[label] = mi; + if(startIndices.indexOf(mi) !== -1) { + pi.starts.push([xi, yi]); + if(twoWide && startIndices.indexOf(mi, + startIndices.indexOf(mi) + 1) !== -1) { + // the same square has starts from opposite sides + // it's not possible to have starts on opposite edges + // of a corner, only a start and an end... + // but if the array is only two points wide (either way) + // you can have starts on opposite sides. + pi.starts.push([xi, yi]); + } + } + } + } + } +}; + +// modified marching squares algorithm, +// so we disambiguate the saddle points from the start +// and we ignore the cases with no crossings +// the index I'm using is based on: +// http://en.wikipedia.org/wiki/Marching_squares +// except that the saddles bifurcate and I represent them +// as the decimal combination of the two appropriate +// non-saddle indices +function getMarchingIndex(val, corners) { + var mi = (corners[0][0] > val ? 0 : 1) + + (corners[0][1] > val ? 0 : 2) + + (corners[1][1] > val ? 0 : 4) + + (corners[1][0] > val ? 0 : 8); + if(mi === 5 || mi === 10) { + var avg = (corners[0][0] + corners[0][1] + + corners[1][0] + corners[1][1]) / 4; + // two peaks with a big valley + if(val > avg) return (mi === 5) ? 713 : 1114; + // two valleys with a big ridge + return (mi === 5) ? 104 : 208; + } + return (mi === 15) ? 0 : mi; +} + +},{"./constants":920}],934:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var setConvert = _dereq_('../../plots/cartesian/set_convert'); + +var heatmapPlot = _dereq_('../heatmap/plot'); +var makeCrossings = _dereq_('./make_crossings'); +var findAllPaths = _dereq_('./find_all_paths'); +var emptyPathinfo = _dereq_('./empty_pathinfo'); +var convertToConstraints = _dereq_('./convert_to_constraints'); +var closeBoundaries = _dereq_('./close_boundaries'); +var constants = _dereq_('./constants'); +var costConstants = constants.LABELOPTIMIZER; + +exports.plot = function plot(gd, plotinfo, cdcontours, contourLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var fullLayout = gd._fullLayout; + + Lib.makeTraceGroups(contourLayer, cdcontours, 'contour').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + var x = cd0.x; + var y = cd0.y; + var contours = trace.contours; + var pathinfo = emptyPathinfo(contours, plotinfo, cd0); + + // use a heatmap to fill - draw it behind the lines + var heatmapColoringLayer = Lib.ensureSingle(plotGroup, 'g', 'heatmapcoloring'); + var cdheatmaps = []; + if(contours.coloring === 'heatmap') { + if(trace.zauto && (trace.autocontour === false)) { + trace._input.zmin = trace.zmin = + contours.start - contours.size / 2; + trace._input.zmax = trace.zmax = + trace.zmin + pathinfo.length * contours.size; + } + cdheatmaps = [cd]; + } + heatmapPlot(gd, plotinfo, cdheatmaps, heatmapColoringLayer); + + makeCrossings(pathinfo); + findAllPaths(pathinfo); + + var leftedge = xa.c2p(x[0], true), + rightedge = xa.c2p(x[x.length - 1], true), + bottomedge = ya.c2p(y[0], true), + topedge = ya.c2p(y[y.length - 1], true), + perimeter = [ + [leftedge, topedge], + [rightedge, topedge], + [rightedge, bottomedge], + [leftedge, bottomedge] + ]; + + var fillPathinfo = pathinfo; + if(contours.type === 'constraint') { + fillPathinfo = convertToConstraints(pathinfo, contours._operation); + closeBoundaries(fillPathinfo, contours._operation, perimeter, trace); + } + + // draw everything + makeBackground(plotGroup, perimeter, contours); + makeFills(plotGroup, fillPathinfo, perimeter, contours); + makeLinesAndLabels(plotGroup, pathinfo, gd, cd0, contours, perimeter); + clipGaps(plotGroup, plotinfo, fullLayout._clips, cd0, perimeter); + }); +}; + +function makeBackground(plotgroup, perimeter, contours) { + var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg'); + + var bgfill = bggroup.selectAll('path') + .data(contours.coloring === 'fill' ? [0] : []); + bgfill.enter().append('path'); + bgfill.exit().remove(); + bgfill + .attr('d', 'M' + perimeter.join('L') + 'Z') + .style('stroke', 'none'); +} + +function makeFills(plotgroup, pathinfo, perimeter, contours) { + var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill'); + + var fillitems = fillgroup.selectAll('path') + .data(contours.coloring === 'fill' || (contours.type === 'constraint' && contours._operation !== '=') ? pathinfo : []); + fillitems.enter().append('path'); + fillitems.exit().remove(); + fillitems.each(function(pi) { + // join all paths for this level together into a single path + // first follow clockwise around the perimeter to close any open paths + // if the whole perimeter is above this level, start with a path + // enclosing the whole thing. With all that, the parity should mean + // that we always fill everything above the contour, nothing below + var fullpath = joinAllPaths(pi, perimeter); + + if(!fullpath) d3.select(this).remove(); + else d3.select(this).attr('d', fullpath).style('stroke', 'none'); + }); +} + +function initFullPath(pi, perimeter) { + var prefixBoundary = pi.prefixBoundary; + if(prefixBoundary === undefined) { + var edgeVal2 = Math.min(pi.z[0][0], pi.z[0][1]); + prefixBoundary = (!pi.edgepaths.length && edgeVal2 > pi.level); + } + + if(prefixBoundary) { + // TODO: why does ^^ not work for constraints? + // pi.prefixBoundary gets set by closeBoundaries + return 'M' + perimeter.join('L') + 'Z'; + } + return ''; +} + +function joinAllPaths(pi, perimeter) { + var fullpath = initFullPath(pi, perimeter), + i = 0, + startsleft = pi.edgepaths.map(function(v, i) { return i; }), + newloop = true, + endpt, + newendpt, + cnt, + nexti, + possiblei, + addpath; + + function istop(pt) { return Math.abs(pt[1] - perimeter[0][1]) < 0.01; } + function isbottom(pt) { return Math.abs(pt[1] - perimeter[2][1]) < 0.01; } + function isleft(pt) { return Math.abs(pt[0] - perimeter[0][0]) < 0.01; } + function isright(pt) { return Math.abs(pt[0] - perimeter[2][0]) < 0.01; } + + while(startsleft.length) { + addpath = Drawing.smoothopen(pi.edgepaths[i], pi.smoothing); + fullpath += newloop ? addpath : addpath.replace(/^M/, 'L'); + startsleft.splice(startsleft.indexOf(i), 1); + endpt = pi.edgepaths[i][pi.edgepaths[i].length - 1]; + nexti = -1; + + // now loop through sides, moving our endpoint until we find a new start + for(cnt = 0; cnt < 4; cnt++) { // just to prevent infinite loops + if(!endpt) { + Lib.log('Missing end?', i, pi); + break; + } + + if(istop(endpt) && !isright(endpt)) newendpt = perimeter[1]; // right top + else if(isleft(endpt)) newendpt = perimeter[0]; // left top + else if(isbottom(endpt)) newendpt = perimeter[3]; // right bottom + else if(isright(endpt)) newendpt = perimeter[2]; // left bottom + + for(possiblei = 0; possiblei < pi.edgepaths.length; possiblei++) { + var ptNew = pi.edgepaths[possiblei][0]; + // is ptNew on the (horz. or vert.) segment from endpt to newendpt? + if(Math.abs(endpt[0] - newendpt[0]) < 0.01) { + if(Math.abs(endpt[0] - ptNew[0]) < 0.01 && + (ptNew[1] - endpt[1]) * (newendpt[1] - ptNew[1]) >= 0) { + newendpt = ptNew; + nexti = possiblei; + } + } + else if(Math.abs(endpt[1] - newendpt[1]) < 0.01) { + if(Math.abs(endpt[1] - ptNew[1]) < 0.01 && + (ptNew[0] - endpt[0]) * (newendpt[0] - ptNew[0]) >= 0) { + newendpt = ptNew; + nexti = possiblei; + } + } + else { + Lib.log('endpt to newendpt is not vert. or horz.', + endpt, newendpt, ptNew); + } + } + + endpt = newendpt; + + if(nexti >= 0) break; + fullpath += 'L' + newendpt; + } + + if(nexti === pi.edgepaths.length) { + Lib.log('unclosed perimeter path'); + break; + } + + i = nexti; + + // if we closed back on a loop we already included, + // close it and start a new loop + newloop = (startsleft.indexOf(i) === -1); + if(newloop) { + i = startsleft[0]; + fullpath += 'Z'; + } + } + + // finally add the interior paths + for(i = 0; i < pi.paths.length; i++) { + fullpath += Drawing.smoothclosed(pi.paths[i], pi.smoothing); + } + + return fullpath; +} + +function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours, perimeter) { + var lineContainer = Lib.ensureSingle(plotgroup, 'g', 'contourlines'); + var showLines = contours.showlines !== false; + var showLabels = contours.showlabels; + var clipLinesForLabels = showLines && showLabels; + + // Even if we're not going to show lines, we need to create them + // if we're showing labels, because the fill paths include the perimeter + // so can't be used to position the labels correctly. + // In this case we'll remove the lines after making the labels. + var linegroup = exports.createLines(lineContainer, showLines || showLabels, pathinfo); + + var lineClip = exports.createLineClip(lineContainer, clipLinesForLabels, + gd._fullLayout._clips, cd0.trace.uid); + + var labelGroup = plotgroup.selectAll('g.contourlabels') + .data(showLabels ? [0] : []); + + labelGroup.exit().remove(); + + labelGroup.enter().append('g') + .classed('contourlabels', true); + + if(showLabels) { + var labelClipPathData = [perimeter]; + + var labelData = []; + + // invalidate the getTextLocation cache in case paths changed + Lib.clearLocationCache(); + + var contourFormat = exports.labelFormatter(contours, cd0.t.cb, gd._fullLayout); + + var dummyText = Drawing.tester.append('text') + .attr('data-notex', 1) + .call(Drawing.font, contours.labelfont); + + var xLen = pathinfo[0].xaxis._length; + var yLen = pathinfo[0].yaxis._length; + + // visible bounds of the contour trace (and the midpoints, to + // help with cost calculations) + var bounds = { + left: Math.max(perimeter[0][0], 0), + right: Math.min(perimeter[2][0], xLen), + top: Math.max(perimeter[0][1], 0), + bottom: Math.min(perimeter[2][1], yLen) + }; + bounds.middle = (bounds.top + bounds.bottom) / 2; + bounds.center = (bounds.left + bounds.right) / 2; + + var plotDiagonal = Math.sqrt(xLen * xLen + yLen * yLen); + + // the path length to use to scale the number of labels to draw: + var normLength = constants.LABELDISTANCE * plotDiagonal / + Math.max(1, pathinfo.length / constants.LABELINCREASE); + + linegroup.each(function(d) { + var textOpts = exports.calcTextOpts(d.level, contourFormat, dummyText, gd); + + d3.select(this).selectAll('path').each(function() { + var path = this; + var pathBounds = Lib.getVisibleSegment(path, bounds, textOpts.height / 2); + if(!pathBounds) return; + + if(pathBounds.len < (textOpts.width + textOpts.height) * constants.LABELMIN) return; + + var maxLabels = Math.min(Math.ceil(pathBounds.len / normLength), + constants.LABELMAX); + + for(var i = 0; i < maxLabels; i++) { + var loc = exports.findBestTextLocation(path, pathBounds, textOpts, + labelData, bounds); + + if(!loc) break; + + exports.addLabelData(loc, textOpts, labelData, labelClipPathData); + } + }); + }); + + dummyText.remove(); + + exports.drawLabels(labelGroup, labelData, gd, lineClip, + clipLinesForLabels ? labelClipPathData : null); + } + + if(showLabels && !showLines) linegroup.remove(); +} + +exports.createLines = function(lineContainer, makeLines, pathinfo) { + var smoothing = pathinfo[0].smoothing; + + var linegroup = lineContainer.selectAll('g.contourlevel') + .data(makeLines ? pathinfo : []); + + linegroup.exit().remove(); + linegroup.enter().append('g') + .classed('contourlevel', true); + + if(makeLines) { + // pedgepaths / ppaths are used by contourcarpet, for the paths transformed from a/b to x/y + // edgepaths / paths are used by contour since it's in x/y from the start + var opencontourlines = linegroup.selectAll('path.openline') + .data(function(d) { return d.pedgepaths || d.edgepaths; }); + + opencontourlines.exit().remove(); + opencontourlines.enter().append('path') + .classed('openline', true); + + opencontourlines + .attr('d', function(d) { + return Drawing.smoothopen(d, smoothing); + }) + .style('stroke-miterlimit', 1) + .style('vector-effect', 'non-scaling-stroke'); + + var closedcontourlines = linegroup.selectAll('path.closedline') + .data(function(d) { return d.ppaths || d.paths; }); + + closedcontourlines.exit().remove(); + closedcontourlines.enter().append('path') + .classed('closedline', true); + + closedcontourlines + .attr('d', function(d) { + return Drawing.smoothclosed(d, smoothing); + }) + .style('stroke-miterlimit', 1) + .style('vector-effect', 'non-scaling-stroke'); + } + + return linegroup; +}; + +exports.createLineClip = function(lineContainer, clipLinesForLabels, clips, uid) { + var clipId = clipLinesForLabels ? ('clipline' + uid) : null; + + var lineClip = clips.selectAll('#' + clipId) + .data(clipLinesForLabels ? [0] : []); + lineClip.exit().remove(); + + lineClip.enter().append('clipPath') + .classed('contourlineclip', true) + .attr('id', clipId); + + Drawing.setClipUrl(lineContainer, clipId); + + return lineClip; +}; + +exports.labelFormatter = function(contours, colorbar, fullLayout) { + if(contours.labelformat) { + return fullLayout._d3locale.numberFormat(contours.labelformat); + } + else { + var formatAxis; + if(colorbar) { + formatAxis = colorbar.axis; + } + else { + formatAxis = { + type: 'linear', + _id: 'ycontour', + showexponent: 'all', + exponentformat: 'B' + }; + + if(contours.type === 'constraint') { + var value = contours.value; + if(Array.isArray(value)) { + formatAxis.range = [value[0], value[value.length - 1]]; + } + else formatAxis.range = [value, value]; + } + else { + formatAxis.range = [contours.start, contours.end]; + formatAxis.nticks = (contours.end - contours.start) / contours.size; + } + + if(formatAxis.range[0] === formatAxis.range[1]) { + formatAxis.range[1] += formatAxis.range[0] || 1; + } + if(!formatAxis.nticks) formatAxis.nticks = 1000; + + setConvert(formatAxis, fullLayout); + Axes.prepTicks(formatAxis); + formatAxis._tmin = null; + formatAxis._tmax = null; + } + return function(v) { + return Axes.tickText(formatAxis, v).text; + }; + } +}; + +exports.calcTextOpts = function(level, contourFormat, dummyText, gd) { + var text = contourFormat(level); + dummyText.text(text) + .call(svgTextUtils.convertToTspans, gd); + var bBox = Drawing.bBox(dummyText.node(), true); + + return { + text: text, + width: bBox.width, + height: bBox.height, + level: level, + dy: (bBox.top + bBox.bottom) / 2 + }; +}; + +exports.findBestTextLocation = function(path, pathBounds, textOpts, labelData, plotBounds) { + var textWidth = textOpts.width; + + var p0, dp, pMax, pMin, loc; + if(pathBounds.isClosed) { + dp = pathBounds.len / costConstants.INITIALSEARCHPOINTS; + p0 = pathBounds.min + dp / 2; + pMax = pathBounds.max; + } + else { + dp = (pathBounds.len - textWidth) / (costConstants.INITIALSEARCHPOINTS + 1); + p0 = pathBounds.min + dp + textWidth / 2; + pMax = pathBounds.max - (dp + textWidth) / 2; + } + + var cost = Infinity; + for(var j = 0; j < costConstants.ITERATIONS; j++) { + for(var p = p0; p < pMax; p += dp) { + var newLocation = Lib.getTextLocation(path, pathBounds.total, p, textWidth); + var newCost = locationCost(newLocation, textOpts, labelData, plotBounds); + if(newCost < cost) { + cost = newCost; + loc = newLocation; + pMin = p; + } + } + if(cost > costConstants.MAXCOST * 2) break; + + // subsequent iterations just look half steps away from the + // best we found in the previous iteration + if(j) dp /= 2; + p0 = pMin - dp / 2; + pMax = p0 + dp * 1.5; + } + if(cost <= costConstants.MAXCOST) return loc; +}; + +/* + * locationCost: a cost function for label locations + * composed of three kinds of penalty: + * - for open paths, being close to the end of the path + * - the angle away from horizontal + * - being too close to already placed neighbors + */ +function locationCost(loc, textOpts, labelData, bounds) { + var halfWidth = textOpts.width / 2; + var halfHeight = textOpts.height / 2; + var x = loc.x; + var y = loc.y; + var theta = loc.theta; + var dx = Math.cos(theta) * halfWidth; + var dy = Math.sin(theta) * halfWidth; + + // cost for being near an edge + var normX = ((x > bounds.center) ? (bounds.right - x) : (x - bounds.left)) / + (dx + Math.abs(Math.sin(theta) * halfHeight)); + var normY = ((y > bounds.middle) ? (bounds.bottom - y) : (y - bounds.top)) / + (Math.abs(dy) + Math.cos(theta) * halfHeight); + if(normX < 1 || normY < 1) return Infinity; + var cost = costConstants.EDGECOST * (1 / (normX - 1) + 1 / (normY - 1)); + + // cost for not being horizontal + cost += costConstants.ANGLECOST * theta * theta; + + // cost for being close to other labels + var x1 = x - dx; + var y1 = y - dy; + var x2 = x + dx; + var y2 = y + dy; + for(var i = 0; i < labelData.length; i++) { + var labeli = labelData[i]; + var dxd = Math.cos(labeli.theta) * labeli.width / 2; + var dyd = Math.sin(labeli.theta) * labeli.width / 2; + var dist = Lib.segmentDistance( + x1, y1, + x2, y2, + labeli.x - dxd, labeli.y - dyd, + labeli.x + dxd, labeli.y + dyd + ) * 2 / (textOpts.height + labeli.height); + + var sameLevel = labeli.level === textOpts.level; + var distOffset = sameLevel ? costConstants.SAMELEVELDISTANCE : 1; + + if(dist <= distOffset) return Infinity; + + var distFactor = costConstants.NEIGHBORCOST * + (sameLevel ? costConstants.SAMELEVELFACTOR : 1); + + cost += distFactor / (dist - distOffset); + } + + return cost; +} + +exports.addLabelData = function(loc, textOpts, labelData, labelClipPathData) { + var halfWidth = textOpts.width / 2; + var halfHeight = textOpts.height / 2; + + var x = loc.x; + var y = loc.y; + var theta = loc.theta; + + var sin = Math.sin(theta); + var cos = Math.cos(theta); + var dxw = halfWidth * cos; + var dxh = halfHeight * sin; + var dyw = halfWidth * sin; + var dyh = -halfHeight * cos; + var bBoxPts = [ + [x - dxw - dxh, y - dyw - dyh], + [x + dxw - dxh, y + dyw - dyh], + [x + dxw + dxh, y + dyw + dyh], + [x - dxw + dxh, y - dyw + dyh], + ]; + + labelData.push({ + text: textOpts.text, + x: x, + y: y, + dy: textOpts.dy, + theta: theta, + level: textOpts.level, + width: textOpts.width, + height: textOpts.height + }); + + labelClipPathData.push(bBoxPts); +}; + +exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPathData) { + var labels = labelGroup.selectAll('text') + .data(labelData, function(d) { + return d.text + ',' + d.x + ',' + d.y + ',' + d.theta; + }); + + labels.exit().remove(); + + labels.enter().append('text') + .attr({ + 'data-notex': 1, + 'text-anchor': 'middle' + }) + .each(function(d) { + var x = d.x + Math.sin(d.theta) * d.dy; + var y = d.y - Math.cos(d.theta) * d.dy; + d3.select(this) + .text(d.text) + .attr({ + x: x, + y: y, + transform: 'rotate(' + (180 * d.theta / Math.PI) + ' ' + x + ' ' + y + ')' + }) + .call(svgTextUtils.convertToTspans, gd); + }); + + if(labelClipPathData) { + var clipPath = ''; + for(var i = 0; i < labelClipPathData.length; i++) { + clipPath += 'M' + labelClipPathData[i].join('L') + 'Z'; + } + + var lineClipPath = Lib.ensureSingle(lineClip, 'path', ''); + lineClipPath.attr('d', clipPath); + } +}; + +function clipGaps(plotGroup, plotinfo, clips, cd0, perimeter) { + var clipId = 'clip' + cd0.trace.uid; + + var clipPath = clips.selectAll('#' + clipId) + .data(cd0.trace.connectgaps ? [] : [0]); + clipPath.enter().append('clipPath') + .classed('contourclip', true) + .attr('id', clipId); + clipPath.exit().remove(); + + if(cd0.trace.connectgaps === false) { + var clipPathInfo = { + // fraction of the way from missing to present point + // to draw the boundary. + // if you make this 1 (or 1-epsilon) then a point in + // a sea of missing data will disappear entirely. + level: 0.9, + crossings: {}, + starts: [], + edgepaths: [], + paths: [], + xaxis: plotinfo.xaxis, + yaxis: plotinfo.yaxis, + x: cd0.x, + y: cd0.y, + // 0 = no data, 1 = data + z: makeClipMask(cd0), + smoothing: 0 + }; + + makeCrossings([clipPathInfo]); + findAllPaths([clipPathInfo]); + var fullpath = joinAllPaths(clipPathInfo, perimeter); + + var path = Lib.ensureSingle(clipPath, 'path', ''); + path.attr('d', fullpath); + } + else clipId = null; + + plotGroup.call(Drawing.setClipUrl, clipId); +} + +function makeClipMask(cd0) { + var empties = cd0.trace._emptypoints, + z = [], + m = cd0.z.length, + n = cd0.z[0].length, + i, + row = [], + emptyPoint; + + for(i = 0; i < n; i++) row.push(1); + for(i = 0; i < m; i++) z.push(row.slice()); + for(i = 0; i < empties.length; i++) { + emptyPoint = empties[i]; + z[emptyPoint[0]][emptyPoint[1]] = 0; + } + // save this mask to determine whether to show this data in hover + cd0.zmask = z; + return z; +} + +},{"../../components/drawing":595,"../../lib":696,"../../lib/svg_text_utils":720,"../../plots/cartesian/axes":744,"../../plots/cartesian/set_convert":763,"../heatmap/plot":957,"./close_boundaries":918,"./constants":920,"./convert_to_constraints":924,"./empty_pathinfo":926,"./find_all_paths":928,"./make_crossings":933,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],935:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); + + +module.exports = function setContours(trace) { + var contours = trace.contours; + + // check if we need to auto-choose contour levels + if(trace.autocontour) { + var zmin = trace.zmin; + var zmax = trace.zmax; + if(zmin === undefined || zmax === undefined) { + zmin = Lib.aggNums(Math.min, null, trace._z); + zmax = Lib.aggNums(Math.max, null, trace._z); + } + var dummyAx = autoContours(zmin, zmax, trace.ncontours); + + contours.size = dummyAx.dtick; + + contours.start = Axes.tickFirst(dummyAx); + dummyAx.range.reverse(); + contours.end = Axes.tickFirst(dummyAx); + + if(contours.start === zmin) contours.start += contours.size; + if(contours.end === zmax) contours.end -= contours.size; + + // if you set a small ncontours, *and* the ends are exactly on zmin/zmax + // there's an edge case where start > end now. Make sure there's at least + // one meaningful contour, put it midway between the crossed values + if(contours.start > contours.end) { + contours.start = contours.end = (contours.start + contours.end) / 2; + } + + // copy auto-contour info back to the source data. + // previously we copied the whole contours object back, but that had + // other info (coloring, showlines) that should be left to supplyDefaults + if(!trace._input.contours) trace._input.contours = {}; + Lib.extendFlat(trace._input.contours, { + start: contours.start, + end: contours.end, + size: contours.size + }); + trace._input.autocontour = true; + } + else if(contours.type !== 'constraint') { + // sanity checks on manually-supplied start/end/size + var start = contours.start, + end = contours.end, + inputContours = trace._input.contours; + + if(start > end) { + contours.start = inputContours.start = end; + end = contours.end = inputContours.end = start; + start = contours.start; + } + + if(!(contours.size > 0)) { + var sizeOut; + if(start === end) sizeOut = 1; + else sizeOut = autoContours(start, end, trace.ncontours).dtick; + + inputContours.size = contours.size = sizeOut; + } + } +}; + + +/* + * autoContours: make a dummy axis object with dtick we can use + * as contours.size, and if needed we can use Axes.tickFirst + * with this axis object to calculate the start and end too + * + * start: the value to start the contours at + * end: the value to end at (must be > start) + * ncontours: max number of contours to make, like roughDTick + * + * returns: an axis object + */ +function autoContours(start, end, ncontours) { + var dummyAx = { + type: 'linear', + range: [start, end] + }; + + Axes.autoTicks( + dummyAx, + (end - start) / (ncontours || 15) + ); + + return dummyAx; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744}],936:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Drawing = _dereq_('../../components/drawing'); +var heatmapStyle = _dereq_('../heatmap/style'); + +var makeColorMap = _dereq_('./make_color_map'); + + +module.exports = function style(gd) { + var contours = d3.select(gd).selectAll('g.contour'); + + contours.style('opacity', function(d) { + return d[0].trace.opacity; + }); + + contours.each(function(d) { + var c = d3.select(this); + var trace = d[0].trace; + var contours = trace.contours; + var line = trace.line; + var cs = contours.size || 1; + var start = contours.start; + + // for contourcarpet only - is this a constraint-type contour trace? + var isConstraintType = contours.type === 'constraint'; + var colorLines = !isConstraintType && contours.coloring === 'lines'; + var colorFills = !isConstraintType && contours.coloring === 'fill'; + + var colorMap = (colorLines || colorFills) ? makeColorMap(trace) : null; + + c.selectAll('g.contourlevel').each(function(d) { + d3.select(this).selectAll('path') + .call(Drawing.lineGroupStyle, + line.width, + colorLines ? colorMap(d.level) : line.color, + line.dash); + }); + + var labelFont = contours.labelfont; + c.selectAll('g.contourlabels text').each(function(d) { + Drawing.font(d3.select(this), { + family: labelFont.family, + size: labelFont.size, + color: labelFont.color || (colorLines ? colorMap(d.level) : line.color) + }); + }); + + if(isConstraintType) { + c.selectAll('g.contourfill path') + .style('fill', trace.fillcolor); + } + else if(colorFills) { + var firstFill; + + c.selectAll('g.contourfill path') + .style('fill', function(d) { + if(firstFill === undefined) firstFill = d.level; + return colorMap(d.level + 0.5 * cs); + }); + + if(firstFill === undefined) firstFill = start; + + c.selectAll('g.contourbg path') + .style('fill', colorMap(firstFill - 0.5 * cs)); + } + }); + + heatmapStyle(gd); +}; + +},{"../../components/drawing":595,"../heatmap/style":958,"./make_color_map":932,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],937:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var handleLabelDefaults = _dereq_('./label_defaults'); + + +module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout, opts) { + var coloring = coerce('contours.coloring'); + + var showLines; + var lineColor = ''; + if(coloring === 'fill') showLines = coerce('contours.showlines'); + + if(showLines !== false) { + if(coloring !== 'lines') lineColor = coerce('line.color', '#000'); + coerce('line.width', 0.5); + coerce('line.dash'); + } + + if(coloring !== 'none') { + // plots/plots always coerces showlegend to true, but in this case + // we default to false and (by default) show a colorbar instead + if(traceIn.showlegend !== true) traceOut.showlegend = false; + traceOut._dfltShowLegend = false; + + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'} + ); + } + + coerce('line.smoothing'); + + handleLabelDefaults(coerce, layout, lineColor, opts); +}; + +},{"../../components/colorscale/defaults":580,"./label_defaults":931}],938:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var heatmapAttrs = _dereq_('../heatmap/attributes'); +var contourAttrs = _dereq_('../contour/attributes'); +var contourContourAttrs = contourAttrs.contours; +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterLineAttrs = scatterAttrs.line; + +module.exports = extendFlat({ + carpet: { + valType: 'string', + + editType: 'calc', + + }, + z: heatmapAttrs.z, + a: heatmapAttrs.x, + a0: heatmapAttrs.x0, + da: heatmapAttrs.dx, + b: heatmapAttrs.y, + b0: heatmapAttrs.y0, + db: heatmapAttrs.dy, + text: heatmapAttrs.text, + transpose: heatmapAttrs.transpose, + atype: heatmapAttrs.xtype, + btype: heatmapAttrs.ytype, + + fillcolor: contourAttrs.fillcolor, + + autocontour: contourAttrs.autocontour, + ncontours: contourAttrs.ncontours, + + contours: { + type: contourContourAttrs.type, + start: contourContourAttrs.start, + end: contourContourAttrs.end, + size: contourContourAttrs.size, + coloring: { + // from contourAttrs.contours.coloring but no 'heatmap' option + valType: 'enumerated', + values: ['fill', 'lines', 'none'], + dflt: 'fill', + + editType: 'calc', + + }, + showlines: contourContourAttrs.showlines, + showlabels: contourContourAttrs.showlabels, + labelfont: contourContourAttrs.labelfont, + labelformat: contourContourAttrs.labelformat, + operation: contourContourAttrs.operation, + value: contourContourAttrs.value, + editType: 'calc', + impliedEdits: {'autocontour': false} + }, + + line: { + color: extendFlat({}, scatterLineAttrs.color, { + + }), + width: scatterLineAttrs.width, + dash: scatterLineAttrs.dash, + smoothing: extendFlat({}, scatterLineAttrs.smoothing, { + + }), + editType: 'plot' + }, + transforms: undefined +}, + + colorscaleAttrs('', { + cLetter: 'z', + autoColorDflt: false + }), + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../contour/attributes":916,"../heatmap/attributes":945,"../scatter/attributes":1043}],939:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var isArray1D = _dereq_('../../lib').isArray1D; + +var convertColumnData = _dereq_('../heatmap/convert_column_xyz'); +var clean2dArray = _dereq_('../heatmap/clean_2d_array'); +var maxRowLength = _dereq_('../heatmap/max_row_length'); +var interp2d = _dereq_('../heatmap/interp2d'); +var findEmpties = _dereq_('../heatmap/find_empties'); +var makeBoundArray = _dereq_('../heatmap/make_bound_array'); +var supplyDefaults = _dereq_('./defaults'); +var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); +var setContours = _dereq_('../contour/set_contours'); + +// most is the same as heatmap calc, then adjust it +// though a few things inside heatmap calc still look for +// contour maps, because the makeBoundArray calls are too entangled +module.exports = function calc(gd, trace) { + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); + if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; + + if(!trace.a || !trace.b) { + // Look up the original incoming carpet data: + var carpetdata = gd.data[carpet.index]; + + // Look up the incoming trace data, *except* perform a shallow + // copy so that we're not actually modifying it when we use it + // to supply defaults: + var tracedata = gd.data[trace.index]; + // var tracedata = extendFlat({}, gd.data[trace.index]); + + // If the data is not specified + if(!tracedata.a) tracedata.a = carpetdata.a; + if(!tracedata.b) tracedata.b = carpetdata.b; + + supplyDefaults(tracedata, trace, trace._defaultColor, gd._fullLayout); + } + + var cd = heatmappishCalc(gd, trace); + + setContours(trace); + + return cd; +}; + +function heatmappishCalc(gd, trace) { + // prepare the raw data + // run makeCalcdata on x and y even for heatmaps, in case of category mappings + var carpet = trace._carpetTrace; + var aax = carpet.aaxis; + var bax = carpet.baxis; + var a, + a0, + da, + b, + b0, + db, + z; + + // cancel minimum tick spacings (only applies to bars and boxes) + aax._minDtick = 0; + bax._minDtick = 0; + + if(isArray1D(trace.z)) convertColumnData(trace, aax, bax, 'a', 'b', ['z']); + a = trace._a = trace._a || trace.a; + b = trace._b = trace._b || trace.b; + + a = a ? aax.makeCalcdata(trace, '_a') : []; + b = b ? bax.makeCalcdata(trace, '_b') : []; + a0 = trace.a0 || 0; + da = trace.da || 1; + b0 = trace.b0 || 0; + db = trace.db || 1; + + z = trace._z = clean2dArray(trace._z || trace.z, trace.transpose); + + trace._emptypoints = findEmpties(z); + interp2d(z, trace._emptypoints); + + // create arrays of brick boundaries, to be used by autorange and heatmap.plot + var xlen = maxRowLength(z), + xIn = trace.xtype === 'scaled' ? '' : a, + xArray = makeBoundArray(trace, xIn, a0, da, xlen, aax), + yIn = trace.ytype === 'scaled' ? '' : b, + yArray = makeBoundArray(trace, yIn, b0, db, z.length, bax); + + var cd0 = { + a: xArray, + b: yArray, + z: z, + }; + + if(trace.contours.type === 'levels' && trace.contours.coloring !== 'none') { + // auto-z and autocolorscale if applicable + colorscaleCalc(trace, z, '', 'z'); + } + + return [cd0]; +} + +},{"../../components/colorscale/calc":578,"../../lib":696,"../carpet/lookup_carpetid":894,"../contour/set_contours":935,"../heatmap/clean_2d_array":947,"../heatmap/convert_column_xyz":949,"../heatmap/find_empties":951,"../heatmap/interp2d":954,"../heatmap/make_bound_array":955,"../heatmap/max_row_length":956,"./defaults":940}],940:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleXYZDefaults = _dereq_('../heatmap/xyz_defaults'); +var attributes = _dereq_('./attributes'); +var handleConstraintDefaults = _dereq_('../contour/constraint_defaults'); +var handleContoursDefaults = _dereq_('../contour/contours_defaults'); +var handleStyleDefaults = _dereq_('../contour/style_defaults'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + function coerce2(attr) { + return Lib.coerce2(traceIn, traceOut, attributes, attr); + } + + coerce('carpet'); + + // If either a or b is not present, then it's not a valid trace *unless* the carpet + // axis has the a or b values we're looking for. So if these are not found, just defer + // that decision until the calc step. + // + // NB: the calc step will modify the original data input by assigning whichever of + // a or b are missing. This is necessary because panning goes right from supplyDefaults + // to plot (skipping calc). That means on subsequent updates, this *will* need to be + // able to find a and b. + // + // The long-term proper fix is that this should perhaps use underscored attributes to + // at least modify the user input to a slightly lesser extent. Fully removing the + // input mutation is challenging. The underscore approach is not currently taken since + // it requires modification to all of the functions below that expect the coerced + // attribute name to match the property name -- except '_a' !== 'a' so that is not + // straightforward. + if(traceIn.a && traceIn.b) { + + var len = handleXYZDefaults(traceIn, traceOut, coerce, layout, 'a', 'b'); + + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + var isConstraint = (coerce('contours.type') === 'constraint'); + + if(isConstraint) { + handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor, {hasHover: false}); + } else { + handleContoursDefaults(traceIn, traceOut, coerce, coerce2); + handleStyleDefaults(traceIn, traceOut, coerce, layout, {hasHover: false}); + } + } else { + traceOut._defaultColor = defaultColor; + traceOut._length = null; + } +}; + +},{"../../lib":696,"../contour/constraint_defaults":921,"../contour/contours_defaults":923,"../contour/style_defaults":937,"../heatmap/xyz_defaults":960,"./attributes":938}],941:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ContourCarpet = {}; + +ContourCarpet.attributes = _dereq_('./attributes'); +ContourCarpet.supplyDefaults = _dereq_('./defaults'); +ContourCarpet.colorbar = _dereq_('../contour/colorbar'); +ContourCarpet.calc = _dereq_('./calc'); +ContourCarpet.plot = _dereq_('./plot'); +ContourCarpet.style = _dereq_('../contour/style'); + +ContourCarpet.moduleType = 'trace'; +ContourCarpet.name = 'contourcarpet'; +ContourCarpet.basePlotModule = _dereq_('../../plots/cartesian'); +ContourCarpet.categories = ['cartesian', 'svg', 'carpet', 'contour', 'symbols', 'showLegend', 'hasLines', 'carpetDependent']; +ContourCarpet.meta = { + + +}; + +module.exports = ContourCarpet; + +},{"../../plots/cartesian":756,"../contour/colorbar":919,"../contour/style":936,"./attributes":938,"./calc":939,"./defaults":940,"./plot":944}],942:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Drawing = _dereq_('../../components/drawing'); +var axisAlignedLine = _dereq_('../carpet/axis_aligned_line'); +var Lib = _dereq_('../../lib'); + +module.exports = function joinAllPaths(trace, pi, perimeter, ab2p, carpet, carpetcd, xa, ya) { + var i; + var fullpath = ''; + + var startsleft = pi.edgepaths.map(function(v, i) { return i; }); + var newloop = true; + var endpt, newendpt, cnt, nexti, possiblei, addpath; + + var atol = Math.abs(perimeter[0][0] - perimeter[2][0]) * 1e-4; + var btol = Math.abs(perimeter[0][1] - perimeter[2][1]) * 1e-4; + + function istop(pt) { return Math.abs(pt[1] - perimeter[0][1]) < btol; } + function isbottom(pt) { return Math.abs(pt[1] - perimeter[2][1]) < btol; } + function isleft(pt) { return Math.abs(pt[0] - perimeter[0][0]) < atol; } + function isright(pt) { return Math.abs(pt[0] - perimeter[2][0]) < atol; } + + function pathto(pt0, pt1) { + var i, j, segments, axis; + var path = ''; + + if((istop(pt0) && !isright(pt0)) || (isbottom(pt0) && !isleft(pt0))) { + axis = carpet.aaxis; + segments = axisAlignedLine(carpet, carpetcd, [pt0[0], pt1[0]], 0.5 * (pt0[1] + pt1[1])); + } else { + axis = carpet.baxis; + segments = axisAlignedLine(carpet, carpetcd, 0.5 * (pt0[0] + pt1[0]), [pt0[1], pt1[1]]); + } + + for(i = 1; i < segments.length; i++) { + path += axis.smoothing ? 'C' : 'L'; + for(j = 0; j < segments[i].length; j++) { + var pt = segments[i][j]; + path += [xa.c2p(pt[0]), ya.c2p(pt[1])] + ' '; + } + } + + return path; + } + + i = 0; + endpt = null; + while(startsleft.length) { + var startpt = pi.edgepaths[i][0]; + + if(endpt) { + fullpath += pathto(endpt, startpt); + } + + addpath = Drawing.smoothopen(pi.edgepaths[i].map(ab2p), pi.smoothing); + fullpath += newloop ? addpath : addpath.replace(/^M/, 'L'); + startsleft.splice(startsleft.indexOf(i), 1); + endpt = pi.edgepaths[i][pi.edgepaths[i].length - 1]; + nexti = -1; + + // now loop through sides, moving our endpoint until we find a new start + for(cnt = 0; cnt < 4; cnt++) { // just to prevent infinite loops + if(!endpt) { + Lib.log('Missing end?', i, pi); + break; + } + + if(istop(endpt) && !isright(endpt)) { + newendpt = perimeter[1]; // left top ---> right top + } else if(isleft(endpt)) { + newendpt = perimeter[0]; // left bottom ---> left top + } else if(isbottom(endpt)) { + newendpt = perimeter[3]; // right bottom + } else if(isright(endpt)) { + newendpt = perimeter[2]; // left bottom + } + + for(possiblei = 0; possiblei < pi.edgepaths.length; possiblei++) { + var ptNew = pi.edgepaths[possiblei][0]; + // is ptNew on the (horz. or vert.) segment from endpt to newendpt? + if(Math.abs(endpt[0] - newendpt[0]) < atol) { + if(Math.abs(endpt[0] - ptNew[0]) < atol && (ptNew[1] - endpt[1]) * (newendpt[1] - ptNew[1]) >= 0) { + newendpt = ptNew; + nexti = possiblei; + } + } else if(Math.abs(endpt[1] - newendpt[1]) < btol) { + if(Math.abs(endpt[1] - ptNew[1]) < btol && (ptNew[0] - endpt[0]) * (newendpt[0] - ptNew[0]) >= 0) { + newendpt = ptNew; + nexti = possiblei; + } + } else { + Lib.log('endpt to newendpt is not vert. or horz.', endpt, newendpt, ptNew); + } + } + + if(nexti >= 0) break; + fullpath += pathto(endpt, newendpt); + endpt = newendpt; + } + + if(nexti === pi.edgepaths.length) { + Lib.log('unclosed perimeter path'); + break; + } + + i = nexti; + + // if we closed back on a loop we already included, + // close it and start a new loop + newloop = (startsleft.indexOf(i) === -1); + if(newloop) { + i = startsleft[0]; + fullpath += pathto(endpt, newendpt) + 'Z'; + endpt = null; + } + } + + // finally add the interior paths + for(i = 0; i < pi.paths.length; i++) { + fullpath += Drawing.smoothclosed(pi.paths[i].map(ab2p), pi.smoothing); + } + + return fullpath; +}; + +},{"../../components/drawing":595,"../../lib":696,"../carpet/axis_aligned_line":878}],943:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function mapPathinfo(pathinfo, map) { + var i, j, k, pi, pedgepaths, ppaths, pedgepath, ppath, path; + + for(i = 0; i < pathinfo.length; i++) { + pi = pathinfo[i]; + pedgepaths = pi.pedgepaths = []; + ppaths = pi.ppaths = []; + for(j = 0; j < pi.edgepaths.length; j++) { + path = pi.edgepaths[j]; + pedgepath = []; + for(k = 0; k < path.length; k++) { + pedgepath[k] = map(path[k]); + } + pedgepaths.push(pedgepath); + } + for(j = 0; j < pi.paths.length; j++) { + path = pi.paths[j]; + ppath = []; + for(k = 0; k < path.length; k++) { + ppath[k] = map(path[k]); + } + ppaths.push(ppath); + } + } +}; + +},{}],944:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var map1dArray = _dereq_('../carpet/map_1d_array'); +var makepath = _dereq_('../carpet/makepath'); +var Drawing = _dereq_('../../components/drawing'); +var Lib = _dereq_('../../lib'); + +var makeCrossings = _dereq_('../contour/make_crossings'); +var findAllPaths = _dereq_('../contour/find_all_paths'); +var contourPlot = _dereq_('../contour/plot'); +var constants = _dereq_('../contour/constants'); +var convertToConstraints = _dereq_('../contour/convert_to_constraints'); +var joinAllPaths = _dereq_('./join_all_paths'); +var emptyPathinfo = _dereq_('../contour/empty_pathinfo'); +var mapPathinfo = _dereq_('./map_pathinfo'); +var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); +var closeBoundaries = _dereq_('../contour/close_boundaries'); + +module.exports = function plot(gd, plotinfo, cdcontours, contourcarpetLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + Lib.makeTraceGroups(contourcarpetLayer, cdcontours, 'contour').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); + var carpetcd = gd.calcdata[carpet.index][0]; + + if(!carpet.visible || carpet.visible === 'legendonly') return; + + var a = cd0.a; + var b = cd0.b; + var contours = trace.contours; + var pathinfo = emptyPathinfo(contours, plotinfo, cd0); + var isConstraint = contours.type === 'constraint'; + var operation = contours._operation; + var coloring = isConstraint ? (operation === '=' ? 'lines' : 'fill') : contours.coloring; + + // Map [a, b] (data) --> [i, j] (pixels) + function ab2p(ab) { + var pt = carpet.ab2xy(ab[0], ab[1], true); + return [xa.c2p(pt[0]), ya.c2p(pt[1])]; + } + + // Define the perimeter in a/b coordinates: + var perimeter = [ + [a[0], b[b.length - 1]], + [a[a.length - 1], b[b.length - 1]], + [a[a.length - 1], b[0]], + [a[0], b[0]] + ]; + + // Extract the contour levels: + makeCrossings(pathinfo); + var atol = (a[a.length - 1] - a[0]) * 1e-8; + var btol = (b[b.length - 1] - b[0]) * 1e-8; + findAllPaths(pathinfo, atol, btol); + + // Constraints might need to be draw inverted, which is not something contours + // handle by default since they're assumed fully opaque so that they can be + // drawn overlapping. This function flips the paths as necessary so that they're + // drawn correctly. + // + // TODO: Perhaps this should be generalized and *all* paths should be drawn as + // closed regions so that translucent contour levels would be valid. + // See: https://github.com/plotly/plotly.js/issues/1356 + var fillPathinfo = pathinfo; + if(contours.type === 'constraint') { + fillPathinfo = convertToConstraints(pathinfo, operation); + closeBoundaries(fillPathinfo, operation, perimeter, trace); + } + + // Map the paths in a/b coordinates to pixel coordinates: + mapPathinfo(pathinfo, ab2p); + + // draw everything + + // Compute the boundary path + var seg, xp, yp, i; + var segs = []; + for(i = carpetcd.clipsegments.length - 1; i >= 0; i--) { + seg = carpetcd.clipsegments[i]; + xp = map1dArray([], seg.x, xa.c2p); + yp = map1dArray([], seg.y, ya.c2p); + xp.reverse(); + yp.reverse(); + segs.push(makepath(xp, yp, seg.bicubic)); + } + + var boundaryPath = 'M' + segs.join('L') + 'Z'; + + // Draw the baseline background fill that fills in the space behind any other + // contour levels: + makeBackground(plotGroup, carpetcd.clipsegments, xa, ya, isConstraint, coloring); + + // Draw the specific contour fills. As a simplification, they're assumed to be + // fully opaque so that it's easy to draw them simply overlapping. The alternative + // would be to flip adjacent paths and draw closed paths for each level instead. + makeFills(trace, plotGroup, xa, ya, fillPathinfo, perimeter, ab2p, carpet, carpetcd, coloring, boundaryPath); + + // Draw contour lines: + makeLinesAndLabels(plotGroup, pathinfo, gd, cd0, contours, plotinfo, carpet); + + // Clip the boundary of the plot + Drawing.setClipUrl(plotGroup, carpet._clipPathId); + }); +}; + +function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours, plotinfo, carpet) { + var lineContainer = Lib.ensureSingle(plotgroup, 'g', 'contourlines'); + var showLines = contours.showlines !== false; + var showLabels = contours.showlabels; + var clipLinesForLabels = showLines && showLabels; + + // Even if we're not going to show lines, we need to create them + // if we're showing labels, because the fill paths include the perimeter + // so can't be used to position the labels correctly. + // In this case we'll remove the lines after making the labels. + var linegroup = contourPlot.createLines(lineContainer, showLines || showLabels, pathinfo); + + var lineClip = contourPlot.createLineClip(lineContainer, clipLinesForLabels, + gd._fullLayout._defs, cd0.trace.uid); + + var labelGroup = plotgroup.selectAll('g.contourlabels') + .data(showLabels ? [0] : []); + + labelGroup.exit().remove(); + + labelGroup.enter().append('g') + .classed('contourlabels', true); + + if(showLabels) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var xLen = xa._length; + var yLen = ya._length; + // for simplicity use the xy box for label clipping outline. + var labelClipPathData = [[ + [0, 0], + [xLen, 0], + [xLen, yLen], + [0, yLen] + ]]; + + + var labelData = []; + + // invalidate the getTextLocation cache in case paths changed + Lib.clearLocationCache(); + + var contourFormat = contourPlot.labelFormatter(contours, cd0.t.cb, gd._fullLayout); + + var dummyText = Drawing.tester.append('text') + .attr('data-notex', 1) + .call(Drawing.font, contours.labelfont); + + // use `bounds` only to keep labels away from the x/y boundaries + // `constrainToCarpet` below ensures labels don't go off the + // carpet edges + var bounds = { + left: 0, + right: xLen, + center: xLen / 2, + top: 0, + bottom: yLen, + middle: yLen / 2 + }; + + var plotDiagonal = Math.sqrt(xLen * xLen + yLen * yLen); + + // the path length to use to scale the number of labels to draw: + var normLength = constants.LABELDISTANCE * plotDiagonal / + Math.max(1, pathinfo.length / constants.LABELINCREASE); + + linegroup.each(function(d) { + var textOpts = contourPlot.calcTextOpts(d.level, contourFormat, dummyText, gd); + + d3.select(this).selectAll('path').each(function(pathData) { + var path = this; + var pathBounds = Lib.getVisibleSegment(path, bounds, textOpts.height / 2); + if(!pathBounds) return; + + constrainToCarpet(path, pathData, d, pathBounds, carpet, textOpts.height); + + if(pathBounds.len < (textOpts.width + textOpts.height) * constants.LABELMIN) return; + + var maxLabels = Math.min(Math.ceil(pathBounds.len / normLength), + constants.LABELMAX); + + for(var i = 0; i < maxLabels; i++) { + var loc = contourPlot.findBestTextLocation(path, pathBounds, textOpts, + labelData, bounds); + + if(!loc) break; + + contourPlot.addLabelData(loc, textOpts, labelData, labelClipPathData); + } + }); + }); + + dummyText.remove(); + + contourPlot.drawLabels(labelGroup, labelData, gd, lineClip, + clipLinesForLabels ? labelClipPathData : null); + } + + if(showLabels && !showLines) linegroup.remove(); +} + +// figure out if this path goes off the edge of the carpet +// and shorten the part we call visible to keep labels away from the edge +function constrainToCarpet(path, pathData, levelData, pathBounds, carpet, textHeight) { + var pathABData; + for(var i = 0; i < levelData.pedgepaths.length; i++) { + if(pathData === levelData.pedgepaths[i]) { + pathABData = levelData.edgepaths[i]; + } + } + if(!pathABData) return; + + var aMin = carpet.a[0]; + var aMax = carpet.a[carpet.a.length - 1]; + var bMin = carpet.b[0]; + var bMax = carpet.b[carpet.b.length - 1]; + + function getOffset(abPt, pathVector) { + var offset = 0; + var edgeVector; + var dAB = 0.1; + if(Math.abs(abPt[0] - aMin) < dAB || Math.abs(abPt[0] - aMax) < dAB) { + edgeVector = normalizeVector(carpet.dxydb_rough(abPt[0], abPt[1], dAB)); + offset = Math.max(offset, textHeight * vectorTan(pathVector, edgeVector) / 2); + } + + if(Math.abs(abPt[1] - bMin) < dAB || Math.abs(abPt[1] - bMax) < dAB) { + edgeVector = normalizeVector(carpet.dxyda_rough(abPt[0], abPt[1], dAB)); + offset = Math.max(offset, textHeight * vectorTan(pathVector, edgeVector) / 2); + } + return offset; + } + + var startVector = getUnitVector(path, 0, 1); + var endVector = getUnitVector(path, pathBounds.total, pathBounds.total - 1); + var minStart = getOffset(pathABData[0], startVector); + var maxEnd = pathBounds.total - getOffset(pathABData[pathABData.length - 1], endVector); + + if(pathBounds.min < minStart) pathBounds.min = minStart; + if(pathBounds.max > maxEnd) pathBounds.max = maxEnd; + + pathBounds.len = pathBounds.max - pathBounds.min; +} + +function getUnitVector(path, p0, p1) { + var pt0 = path.getPointAtLength(p0); + var pt1 = path.getPointAtLength(p1); + var dx = pt1.x - pt0.x; + var dy = pt1.y - pt0.y; + var len = Math.sqrt(dx * dx + dy * dy); + return [dx / len, dy / len]; +} + +function normalizeVector(v) { + var len = Math.sqrt(v[0] * v[0] + v[1] * v[1]); + return [v[0] / len, v[1] / len]; +} + +function vectorTan(v0, v1) { + var cos = Math.abs(v0[0] * v1[0] + v0[1] * v1[1]); + var sin = Math.sqrt(1 - cos * cos); + return sin / cos; +} + +function makeBackground(plotgroup, clipsegments, xaxis, yaxis, isConstraint, coloring) { + var seg, xp, yp, i; + var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg'); + + var bgfill = bggroup.selectAll('path') + .data((coloring === 'fill' && !isConstraint) ? [0] : []); + bgfill.enter().append('path'); + bgfill.exit().remove(); + + var segs = []; + for(i = 0; i < clipsegments.length; i++) { + seg = clipsegments[i]; + xp = map1dArray([], seg.x, xaxis.c2p); + yp = map1dArray([], seg.y, yaxis.c2p); + segs.push(makepath(xp, yp, seg.bicubic)); + } + + bgfill + .attr('d', 'M' + segs.join('L') + 'Z') + .style('stroke', 'none'); +} + +function makeFills(trace, plotgroup, xa, ya, pathinfo, perimeter, ab2p, carpet, carpetcd, coloring, boundaryPath) { + var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill'); + + var fillitems = fillgroup.selectAll('path') + .data(coloring === 'fill' ? pathinfo : []); + fillitems.enter().append('path'); + fillitems.exit().remove(); + fillitems.each(function(pi) { + // join all paths for this level together into a single path + // first follow clockwise around the perimeter to close any open paths + // if the whole perimeter is above this level, start with a path + // enclosing the whole thing. With all that, the parity should mean + // that we always fill everything above the contour, nothing below + var fullpath = joinAllPaths(trace, pi, perimeter, ab2p, carpet, carpetcd, xa, ya); + + if(pi.prefixBoundary) { + fullpath = boundaryPath + fullpath; + } + + if(!fullpath) { + d3.select(this).remove(); + } else { + d3.select(this) + .attr('d', fullpath) + .style('stroke', 'none'); + } + }); +} + +},{"../../components/drawing":595,"../../lib":696,"../carpet/lookup_carpetid":894,"../carpet/makepath":895,"../carpet/map_1d_array":896,"../contour/close_boundaries":918,"../contour/constants":920,"../contour/convert_to_constraints":924,"../contour/empty_pathinfo":926,"../contour/find_all_paths":928,"../contour/make_crossings":933,"../contour/plot":934,"./join_all_paths":942,"./map_pathinfo":943,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],945:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = extendFlat({ + z: { + valType: 'data_array', + editType: 'calc', + + }, + x: extendFlat({}, scatterAttrs.x, {impliedEdits: {xtype: 'array'}}), + x0: extendFlat({}, scatterAttrs.x0, {impliedEdits: {xtype: 'scaled'}}), + dx: extendFlat({}, scatterAttrs.dx, {impliedEdits: {xtype: 'scaled'}}), + y: extendFlat({}, scatterAttrs.y, {impliedEdits: {ytype: 'array'}}), + y0: extendFlat({}, scatterAttrs.y0, {impliedEdits: {ytype: 'scaled'}}), + dy: extendFlat({}, scatterAttrs.dy, {impliedEdits: {ytype: 'scaled'}}), + + text: { + valType: 'data_array', + editType: 'calc', + + }, + transpose: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + xtype: { + valType: 'enumerated', + values: ['array', 'scaled'], + + editType: 'calc+clearAxisTypes', + + }, + ytype: { + valType: 'enumerated', + values: ['array', 'scaled'], + + editType: 'calc+clearAxisTypes', + + }, + zsmooth: { + valType: 'enumerated', + values: ['fast', 'best', false], + dflt: false, + + editType: 'calc', + + }, + connectgaps: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + xgap: { + valType: 'number', + dflt: 0, + min: 0, + + editType: 'plot', + + }, + ygap: { + valType: 'number', + dflt: 0, + min: 0, + + editType: 'plot', + + }, + zhoverformat: { + valType: 'string', + dflt: '', + + editType: 'none', + + }, + transforms: undefined +}, + colorscaleAttrs('', { + cLetter: 'z', + autoColorDflt: false + }), + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../scatter/attributes":1043}],946:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var histogram2dCalc = _dereq_('../histogram2d/calc'); +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var convertColumnData = _dereq_('./convert_column_xyz'); +var maxRowLength = _dereq_('./max_row_length'); +var clean2dArray = _dereq_('./clean_2d_array'); +var interp2d = _dereq_('./interp2d'); +var findEmpties = _dereq_('./find_empties'); +var makeBoundArray = _dereq_('./make_bound_array'); + + +module.exports = function calc(gd, trace) { + // prepare the raw data + // run makeCalcdata on x and y even for heatmaps, in case of category mappings + var xa = Axes.getFromId(gd, trace.xaxis || 'x'), + ya = Axes.getFromId(gd, trace.yaxis || 'y'), + isContour = Registry.traceIs(trace, 'contour'), + isHist = Registry.traceIs(trace, 'histogram'), + isGL2D = Registry.traceIs(trace, 'gl2d'), + zsmooth = isContour ? 'best' : trace.zsmooth, + x, + x0, + dx, + y, + y0, + dy, + z, + i, + binned; + + // cancel minimum tick spacings (only applies to bars and boxes) + xa._minDtick = 0; + ya._minDtick = 0; + + if(isHist) { + binned = histogram2dCalc(gd, trace); + x = binned.x; + x0 = binned.x0; + dx = binned.dx; + y = binned.y; + y0 = binned.y0; + dy = binned.dy; + z = binned.z; + } + else { + var zIn = trace.z; + if(Lib.isArray1D(zIn)) { + convertColumnData(trace, xa, ya, 'x', 'y', ['z']); + x = trace._x; + y = trace._y; + zIn = trace._z; + } else { + x = trace.x ? xa.makeCalcdata(trace, 'x') : []; + y = trace.y ? ya.makeCalcdata(trace, 'y') : []; + } + + x0 = trace.x0 || 0; + dx = trace.dx || 1; + y0 = trace.y0 || 0; + dy = trace.dy || 1; + + z = clean2dArray(zIn, trace.transpose); + + if(isContour || trace.connectgaps) { + trace._emptypoints = findEmpties(z); + interp2d(z, trace._emptypoints); + } + } + + function noZsmooth(msg) { + zsmooth = trace._input.zsmooth = trace.zsmooth = false; + Lib.warn('cannot use zsmooth: "fast": ' + msg); + } + + // check whether we really can smooth (ie all boxes are about the same size) + if(zsmooth === 'fast') { + if(xa.type === 'log' || ya.type === 'log') { + noZsmooth('log axis found'); + } + else if(!isHist) { + if(x.length) { + var avgdx = (x[x.length - 1] - x[0]) / (x.length - 1), + maxErrX = Math.abs(avgdx / 100); + for(i = 0; i < x.length - 1; i++) { + if(Math.abs(x[i + 1] - x[i] - avgdx) > maxErrX) { + noZsmooth('x scale is not linear'); + break; + } + } + } + if(y.length && zsmooth === 'fast') { + var avgdy = (y[y.length - 1] - y[0]) / (y.length - 1), + maxErrY = Math.abs(avgdy / 100); + for(i = 0; i < y.length - 1; i++) { + if(Math.abs(y[i + 1] - y[i] - avgdy) > maxErrY) { + noZsmooth('y scale is not linear'); + break; + } + } + } + } + } + + // create arrays of brick boundaries, to be used by autorange and heatmap.plot + var xlen = maxRowLength(z); + var xIn = trace.xtype === 'scaled' ? '' : x; + var xArray = makeBoundArray(trace, xIn, x0, dx, xlen, xa); + var yIn = trace.ytype === 'scaled' ? '' : y; + var yArray = makeBoundArray(trace, yIn, y0, dy, z.length, ya); + + // handled in gl2d convert step + if(!isGL2D) { + trace._extremes[xa._id] = Axes.findExtremes(xa, xArray); + trace._extremes[ya._id] = Axes.findExtremes(ya, yArray); + } + + var cd0 = { + x: xArray, + y: yArray, + z: z, + text: trace._text || trace.text + }; + + if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn; + if(yIn && yIn.length === yArray.length - 1) cd0.yCenter = yIn; + + if(isHist) { + cd0.xRanges = binned.xRanges; + cd0.yRanges = binned.yRanges; + cd0.pts = binned.pts; + } + + // auto-z and autocolorscale if applicable + if(!isContour || trace.contours.type !== 'constraint') { + colorscaleCalc(trace, z, '', 'z'); + } + + if(isContour && trace.contours && trace.contours.coloring === 'heatmap') { + var dummyTrace = { + type: trace.type === 'contour' ? 'heatmap' : 'histogram2d', + xcalendar: trace.xcalendar, + ycalendar: trace.ycalendar + }; + cd0.xfill = makeBoundArray(dummyTrace, xIn, x0, dx, xlen, xa); + cd0.yfill = makeBoundArray(dummyTrace, yIn, y0, dy, z.length, ya); + } + + return [cd0]; +}; + +},{"../../components/colorscale/calc":578,"../../lib":696,"../../plots/cartesian/axes":744,"../../registry":827,"../histogram2d/calc":977,"./clean_2d_array":947,"./convert_column_xyz":949,"./find_empties":951,"./interp2d":954,"./make_bound_array":955,"./max_row_length":956}],947:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +module.exports = function clean2dArray(zOld, transpose) { + var rowlen, collen, getCollen, old2new, i, j; + + function cleanZvalue(v) { + if(!isNumeric(v)) return undefined; + return +v; + } + + if(transpose) { + rowlen = 0; + for(i = 0; i < zOld.length; i++) rowlen = Math.max(rowlen, zOld[i].length); + if(rowlen === 0) return false; + getCollen = function(zOld) { return zOld.length; }; + old2new = function(zOld, i, j) { return zOld[j][i]; }; + } + else { + rowlen = zOld.length; + getCollen = function(zOld, i) { return zOld[i].length; }; + old2new = function(zOld, i, j) { return zOld[i][j]; }; + } + + var zNew = new Array(rowlen); + + for(i = 0; i < rowlen; i++) { + collen = getCollen(zOld, i); + zNew[i] = new Array(collen); + for(j = 0; j < collen; j++) zNew[i][j] = cleanZvalue(old2new(zOld, i, j)); + } + + return zNew; +}; + +},{"fast-isnumeric":214}],948:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + min: 'zmin', + max: 'zmax' +}; + +},{}],949:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, arrayVarNames) { + var colLen = trace._length; + var col1 = trace[var1Name].slice(0, colLen); + var col2 = trace[var2Name].slice(0, colLen); + var textCol = trace.text; + var hasColumnText = (textCol !== undefined && Lib.isArray1D(textCol)); + var col1Calendar = trace[var1Name + 'calendar']; + var col2Calendar = trace[var2Name + 'calendar']; + + var i, j, arrayVar, newArray, arrayVarName; + + for(i = 0; i < colLen; i++) { + col1[i] = ax1.d2c(col1[i], 0, col1Calendar); + col2[i] = ax2.d2c(col2[i], 0, col2Calendar); + } + + var col1dv = Lib.distinctVals(col1), + col1vals = col1dv.vals, + col2dv = Lib.distinctVals(col2), + col2vals = col2dv.vals, + newArrays = []; + + for(i = 0; i < arrayVarNames.length; i++) { + newArrays[i] = Lib.init2dArray(col2vals.length, col1vals.length); + } + + var i1, i2, text; + + if(hasColumnText) text = Lib.init2dArray(col2vals.length, col1vals.length); + + for(i = 0; i < colLen; i++) { + if(col1[i] !== BADNUM && col2[i] !== BADNUM) { + i1 = Lib.findBin(col1[i] + col1dv.minDiff / 2, col1vals); + i2 = Lib.findBin(col2[i] + col2dv.minDiff / 2, col2vals); + + for(j = 0; j < arrayVarNames.length; j++) { + arrayVarName = arrayVarNames[j]; + arrayVar = trace[arrayVarName]; + newArray = newArrays[j]; + newArray[i2][i1] = arrayVar[i]; + } + + if(hasColumnText) text[i2][i1] = textCol[i]; + } + } + + trace['_' + var1Name] = col1vals; + trace['_' + var2Name] = col2vals; + for(j = 0; j < arrayVarNames.length; j++) { + trace['_' + arrayVarNames[j]] = newArrays[j]; + } + if(hasColumnText) trace._text = text; +}; + +},{"../../constants/numerical":673,"../../lib":696}],950:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleXYZDefaults = _dereq_('./xyz_defaults'); +var handleStyleDefaults = _dereq_('./style_defaults'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var validData = handleXYZDefaults(traceIn, traceOut, coerce, layout); + if(!validData) { + traceOut.visible = false; + return; + } + + coerce('text'); + + handleStyleDefaults(traceIn, traceOut, coerce, layout); + + coerce('connectgaps', Lib.isArray1D(traceOut.z) && (traceOut.zsmooth !== false)); + + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"./attributes":945,"./style_defaults":959,"./xyz_defaults":960}],951:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var maxRowLength = _dereq_('./max_row_length'); + +/* Return a list of empty points in 2D array z + * each empty point z[i][j] gives an array [i, j, neighborCount] + * neighborCount is the count of 4 nearest neighbors that DO exist + * this is to give us an order of points to evaluate for interpolation. + * if no neighbors exist, we iteratively look for neighbors that HAVE + * neighbors, and add a fractional neighborCount + */ +module.exports = function findEmpties(z) { + var empties = [], + neighborHash = {}, + noNeighborList = [], + nextRow = z[0], + row = [], + blank = [0, 0, 0], + rowLength = maxRowLength(z), + prevRow, + i, + j, + thisPt, + p, + neighborCount, + newNeighborHash, + foundNewNeighbors; + + for(i = 0; i < z.length; i++) { + prevRow = row; + row = nextRow; + nextRow = z[i + 1] || []; + for(j = 0; j < rowLength; j++) { + if(row[j] === undefined) { + neighborCount = (row[j - 1] !== undefined ? 1 : 0) + + (row[j + 1] !== undefined ? 1 : 0) + + (prevRow[j] !== undefined ? 1 : 0) + + (nextRow[j] !== undefined ? 1 : 0); + + if(neighborCount) { + // for this purpose, don't count off-the-edge points + // as undefined neighbors + if(i === 0) neighborCount++; + if(j === 0) neighborCount++; + if(i === z.length - 1) neighborCount++; + if(j === row.length - 1) neighborCount++; + + // if all neighbors that could exist do, we don't + // need this for finding farther neighbors + if(neighborCount < 4) { + neighborHash[[i, j]] = [i, j, neighborCount]; + } + + empties.push([i, j, neighborCount]); + } + else noNeighborList.push([i, j]); + } + } + } + + while(noNeighborList.length) { + newNeighborHash = {}; + foundNewNeighbors = false; + + // look for cells that now have neighbors but didn't before + for(p = noNeighborList.length - 1; p >= 0; p--) { + thisPt = noNeighborList[p]; + i = thisPt[0]; + j = thisPt[1]; + + neighborCount = ((neighborHash[[i - 1, j]] || blank)[2] + + (neighborHash[[i + 1, j]] || blank)[2] + + (neighborHash[[i, j - 1]] || blank)[2] + + (neighborHash[[i, j + 1]] || blank)[2]) / 20; + + if(neighborCount) { + newNeighborHash[thisPt] = [i, j, neighborCount]; + noNeighborList.splice(p, 1); + foundNewNeighbors = true; + } + } + + if(!foundNewNeighbors) { + throw 'findEmpties iterated with no new neighbors'; + } + + // put these new cells into the main neighbor list + for(thisPt in newNeighborHash) { + neighborHash[thisPt] = newNeighborHash[thisPt]; + empties.push(newNeighborHash[thisPt]); + } + } + + // sort the full list in descending order of neighbor count + return empties.sort(function(a, b) { return b[2] - a[2]; }); +}; + +},{"./max_row_length":956}],952:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = _dereq_('../../components/fx'); +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) { + var cd0 = pointData.cd[0]; + var trace = cd0.trace; + var xa = pointData.xa; + var ya = pointData.ya; + var x = cd0.x; + var y = cd0.y; + var z = cd0.z; + var xc = cd0.xCenter; + var yc = cd0.yCenter; + var zmask = cd0.zmask; + var range = [trace.zmin, trace.zmax]; + var zhoverformat = trace.zhoverformat; + var x2 = x; + var y2 = y; + + var xl, yl, nx, ny; + + if(pointData.index !== false) { + try { + nx = Math.round(pointData.index[1]); + ny = Math.round(pointData.index[0]); + } + catch(e) { + Lib.error('Error hovering on heatmap, ' + + 'pointNumber must be [row,col], found:', pointData.index); + return; + } + if(nx < 0 || nx >= z[0].length || ny < 0 || ny > z.length) { + return; + } + } + else if(Fx.inbox(xval - x[0], xval - x[x.length - 1], 0) > 0 || + Fx.inbox(yval - y[0], yval - y[y.length - 1], 0) > 0) { + return; + } + else { + if(contour) { + var i2; + x2 = [2 * x[0] - x[1]]; + + for(i2 = 1; i2 < x.length; i2++) { + x2.push((x[i2] + x[i2 - 1]) / 2); + } + x2.push([2 * x[x.length - 1] - x[x.length - 2]]); + + y2 = [2 * y[0] - y[1]]; + for(i2 = 1; i2 < y.length; i2++) { + y2.push((y[i2] + y[i2 - 1]) / 2); + } + y2.push([2 * y[y.length - 1] - y[y.length - 2]]); + } + nx = Math.max(0, Math.min(x2.length - 2, Lib.findBin(xval, x2))); + ny = Math.max(0, Math.min(y2.length - 2, Lib.findBin(yval, y2))); + } + + var x0 = xa.c2p(x[nx]), + x1 = xa.c2p(x[nx + 1]), + y0 = ya.c2p(y[ny]), + y1 = ya.c2p(y[ny + 1]); + + if(contour) { + x1 = x0; + xl = x[nx]; + y1 = y0; + yl = y[ny]; + } + else { + xl = xc ? xc[nx] : ((x[nx] + x[nx + 1]) / 2); + yl = yc ? yc[ny] : ((y[ny] + y[ny + 1]) / 2); + if(trace.zsmooth) { + x0 = x1 = xa.c2p(xl); + y0 = y1 = ya.c2p(yl); + } + } + + var zVal = z[ny][nx]; + if(zmask && !zmask[ny][nx]) zVal = undefined; + + var text; + if(Array.isArray(cd0.text) && Array.isArray(cd0.text[ny])) { + text = cd0.text[ny][nx]; + } + + var zLabel; + // dummy axis for formatting the z value + var dummyAx = { + type: 'linear', + range: range, + hoverformat: zhoverformat, + _separators: xa._separators, + _numFormat: xa._numFormat + }; + var zLabelObj = Axes.tickText(dummyAx, zVal, 'hover'); + zLabel = zLabelObj.text; + + return [Lib.extendFlat(pointData, { + index: [ny, nx], + // never let a 2D override 1D type as closest point + distance: pointData.maxHoverDistance, + spikeDistance: pointData.maxSpikeDistance, + x0: x0, + x1: x1, + y0: y0, + y1: y1, + xLabelVal: xl, + yLabelVal: yl, + zLabelVal: zVal, + zLabel: zLabel, + text: text + })]; +}; + +},{"../../components/fx":612,"../../lib":696,"../../plots/cartesian/axes":744}],953:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Heatmap = {}; + +Heatmap.attributes = _dereq_('./attributes'); +Heatmap.supplyDefaults = _dereq_('./defaults'); +Heatmap.calc = _dereq_('./calc'); +Heatmap.plot = _dereq_('./plot'); +Heatmap.colorbar = _dereq_('./colorbar'); +Heatmap.style = _dereq_('./style'); +Heatmap.hoverPoints = _dereq_('./hover'); + +Heatmap.moduleType = 'trace'; +Heatmap.name = 'heatmap'; +Heatmap.basePlotModule = _dereq_('../../plots/cartesian'); +Heatmap.categories = ['cartesian', 'svg', '2dMap']; +Heatmap.meta = { + +}; + +module.exports = Heatmap; + +},{"../../plots/cartesian":756,"./attributes":945,"./calc":946,"./colorbar":948,"./defaults":950,"./hover":952,"./plot":957,"./style":958}],954:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var INTERPTHRESHOLD = 1e-2; +var NEIGHBORSHIFTS = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + +function correctionOvershoot(maxFractionalChange) { + // start with less overshoot, until we know it's converging, + // then ramp up the overshoot for faster convergence + return 0.5 - 0.25 * Math.min(1, maxFractionalChange * 0.5); +} + +/* + * interp2d: Fill in missing data from a 2D array using an iterative + * poisson equation solver with zero-derivative BC at edges. + * Amazingly, this just amounts to repeatedly averaging all the existing + * nearest neighbors, at least if we don't take x/y scaling into account, + * which is the right approach here where x and y may not even have the + * same units. + * + * @param {array of arrays} z + * The 2D array to fill in. Will be mutated here. Assumed to already be + * cleaned, so all entries are numbers except gaps, which are `undefined`. + * @param {array of arrays} emptyPoints + * Each entry [i, j, neighborCount] for empty points z[i][j] and the number + * of neighbors that are *not* missing. Assumed to be sorted from most to + * least neighbors, as produced by heatmap/find_empties. + */ +module.exports = function interp2d(z, emptyPoints) { + var maxFractionalChange = 1; + var i; + + // one pass to fill in a starting value for all the empties + iterateInterp2d(z, emptyPoints); + + // we're don't need to iterate lone empties - remove them + for(i = 0; i < emptyPoints.length; i++) { + if(emptyPoints[i][2] < 4) break; + } + // but don't remove these points from the original array, + // we'll use them for masking, so make a copy. + emptyPoints = emptyPoints.slice(i); + + for(i = 0; i < 100 && maxFractionalChange > INTERPTHRESHOLD; i++) { + maxFractionalChange = iterateInterp2d(z, emptyPoints, + correctionOvershoot(maxFractionalChange)); + } + if(maxFractionalChange > INTERPTHRESHOLD) { + Lib.log('interp2d didn\'t converge quickly', maxFractionalChange); + } + + return z; +}; + +function iterateInterp2d(z, emptyPoints, overshoot) { + var maxFractionalChange = 0, + thisPt, + i, + j, + p, + q, + neighborShift, + neighborRow, + neighborVal, + neighborCount, + neighborSum, + initialVal, + minNeighbor, + maxNeighbor; + + for(p = 0; p < emptyPoints.length; p++) { + thisPt = emptyPoints[p]; + i = thisPt[0]; + j = thisPt[1]; + initialVal = z[i][j]; + neighborSum = 0; + neighborCount = 0; + + for(q = 0; q < 4; q++) { + neighborShift = NEIGHBORSHIFTS[q]; + neighborRow = z[i + neighborShift[0]]; + if(!neighborRow) continue; + neighborVal = neighborRow[j + neighborShift[1]]; + if(neighborVal !== undefined) { + if(neighborSum === 0) { + minNeighbor = maxNeighbor = neighborVal; + } + else { + minNeighbor = Math.min(minNeighbor, neighborVal); + maxNeighbor = Math.max(maxNeighbor, neighborVal); + } + neighborCount++; + neighborSum += neighborVal; + } + } + + if(neighborCount === 0) { + throw 'iterateInterp2d order is wrong: no defined neighbors'; + } + + // this is the laplace equation interpolation: + // each point is just the average of its neighbors + // note that this ignores differential x/y scaling + // which I think is the right approach, since we + // don't know what that scaling means + z[i][j] = neighborSum / neighborCount; + + if(initialVal === undefined) { + if(neighborCount < 4) maxFractionalChange = 1; + } + else { + // we can make large empty regions converge faster + // if we overshoot the change vs the previous value + z[i][j] = (1 + overshoot) * z[i][j] - overshoot * initialVal; + + if(maxNeighbor > minNeighbor) { + maxFractionalChange = Math.max(maxFractionalChange, + Math.abs(z[i][j] - initialVal) / (maxNeighbor - minNeighbor)); + } + } + } + + return maxFractionalChange; +} + +},{"../../lib":696}],955:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +module.exports = function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks, ax) { + var arrayOut = [], + isContour = Registry.traceIs(trace, 'contour'), + isHist = Registry.traceIs(trace, 'histogram'), + isGL2D = Registry.traceIs(trace, 'gl2d'), + v0, + dv, + i; + + var isArrayOfTwoItemsOrMore = isArrayOrTypedArray(arrayIn) && arrayIn.length > 1; + + if(isArrayOfTwoItemsOrMore && !isHist && (ax.type !== 'category')) { + var len = arrayIn.length; + + // given vals are brick centers + // hopefully length === numbricks, but use this method even if too few are supplied + // and extend it linearly based on the last two points + if(len <= numbricks) { + // contour plots only want the centers + if(isContour || isGL2D) arrayOut = arrayIn.slice(0, numbricks); + else if(numbricks === 1) { + arrayOut = [arrayIn[0] - 0.5, arrayIn[0] + 0.5]; + } + else { + arrayOut = [1.5 * arrayIn[0] - 0.5 * arrayIn[1]]; + + for(i = 1; i < len; i++) { + arrayOut.push((arrayIn[i - 1] + arrayIn[i]) * 0.5); + } + + arrayOut.push(1.5 * arrayIn[len - 1] - 0.5 * arrayIn[len - 2]); + } + + if(len < numbricks) { + var lastPt = arrayOut[arrayOut.length - 1], + delta = lastPt - arrayOut[arrayOut.length - 2]; + + for(i = len; i < numbricks; i++) { + lastPt += delta; + arrayOut.push(lastPt); + } + } + } + else { + // hopefully length === numbricks+1, but do something regardless: + // given vals are brick boundaries + return isContour ? + arrayIn.slice(0, numbricks) : // we must be strict for contours + arrayIn.slice(0, numbricks + 1); + } + } + else { + dv = dvIn || 1; + + var calendar = trace[ax._id.charAt(0) + 'calendar']; + + if(isHist || ax.type === 'category') v0 = ax.r2c(v0In, 0, calendar) || 0; + else if(isArrayOrTypedArray(arrayIn) && arrayIn.length === 1) v0 = arrayIn[0]; + else if(v0In === undefined) v0 = 0; + else v0 = ax.d2c(v0In, 0, calendar); + + for(i = (isContour || isGL2D) ? 0 : -0.5; i < numbricks; i++) { + arrayOut.push(v0 + dv * i); + } + } + + return arrayOut; +}; + +},{"../../lib":696,"../../registry":827}],956:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function maxRowLength(z) { + var len = 0; + + for(var i = 0; i < z.length; i++) { + len = Math.max(len, z[i].length); + } + + return len; +}; + +},{}],957:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Colorscale = _dereq_('../../components/colorscale'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +var maxRowLength = _dereq_('./max_row_length'); + +module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + Lib.makeTraceGroups(heatmapLayer, cdheatmaps, 'hm').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + + var z = cd0.z; + var x = cd0.x; + var y = cd0.y; + var xc = cd0.xCenter; + var yc = cd0.yCenter; + var isContour = Registry.traceIs(trace, 'contour'); + var zsmooth = isContour ? 'best' : trace.zsmooth; + + // get z dims + var m = z.length; + var n = maxRowLength(z); + var xrev = false; + var yrev = false; + + var left, right, temp, top, bottom, i; + + // TODO: if there are multiple overlapping categorical heatmaps, + // or if we allow category sorting, then the categories may not be + // sequential... may need to reorder and/or expand z + + // Get edges of png in pixels (xa.c2p() maps axes coordinates to pixel coordinates) + // figure out if either axis is reversed (y is usually reversed, in pixel coords) + // also clip the image to maximum 50% outside the visible plot area + // bigger image lets you pan more naturally, but slows performance. + // TODO: use low-resolution images outside the visible plot for panning + // these while loops find the first and last brick bounds that are defined + // (in case of log of a negative) + i = 0; + while(left === undefined && i < x.length - 1) { + left = xa.c2p(x[i]); + i++; + } + i = x.length - 1; + while(right === undefined && i > 0) { + right = xa.c2p(x[i]); + i--; + } + + if(right < left) { + temp = right; + right = left; + left = temp; + xrev = true; + } + + i = 0; + while(top === undefined && i < y.length - 1) { + top = ya.c2p(y[i]); + i++; + } + i = y.length - 1; + while(bottom === undefined && i > 0) { + bottom = ya.c2p(y[i]); + i--; + } + + if(bottom < top) { + temp = top; + top = bottom; + bottom = temp; + yrev = true; + } + + // for contours with heatmap fill, we generate the boundaries based on + // brick centers but then use the brick edges for drawing the bricks + if(isContour) { + xc = x; + yc = y; + x = cd0.xfill; + y = cd0.yfill; + } + + // make an image that goes at most half a screen off either side, to keep + // time reasonable when you zoom in. if zsmooth is true/fast, don't worry + // about this, because zooming doesn't increase number of pixels + // if zsmooth is best, don't include anything off screen because it takes too long + if(zsmooth !== 'fast') { + var extra = zsmooth === 'best' ? 0 : 0.5; + left = Math.max(-extra * xa._length, left); + right = Math.min((1 + extra) * xa._length, right); + top = Math.max(-extra * ya._length, top); + bottom = Math.min((1 + extra) * ya._length, bottom); + } + + var imageWidth = Math.round(right - left), + imageHeight = Math.round(bottom - top); + + // setup image nodes + + // if image is entirely off-screen, don't even draw it + var isOffScreen = (imageWidth <= 0 || imageHeight <= 0); + + if(isOffScreen) { + var noImage = plotGroup.selectAll('image').data([]); + noImage.exit().remove(); + return; + } + + // generate image data + + var canvasW, canvasH; + if(zsmooth === 'fast') { + canvasW = n; + canvasH = m; + } else { + canvasW = imageWidth; + canvasH = imageHeight; + } + + var canvas = document.createElement('canvas'); + canvas.width = canvasW; + canvas.height = canvasH; + var context = canvas.getContext('2d'); + + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + trace.colorscale, + trace.zmin, + trace.zmax + ), + { noNumericCheck: true, returnArray: true } + ); + + // map brick boundaries to image pixels + var xpx, + ypx; + if(zsmooth === 'fast') { + xpx = xrev ? + function(index) { return n - 1 - index; } : + Lib.identity; + ypx = yrev ? + function(index) { return m - 1 - index; } : + Lib.identity; + } + else { + xpx = function(index) { + return Lib.constrain(Math.round(xa.c2p(x[index]) - left), + 0, imageWidth); + }; + ypx = function(index) { + return Lib.constrain(Math.round(ya.c2p(y[index]) - top), + 0, imageHeight); + }; + } + + // build the pixel map brick-by-brick + // cruise through z-matrix row-by-row + // build a brick at each z-matrix value + var yi = ypx(0); + var yb = [yi, yi]; + var xbi = xrev ? 0 : 1; + var ybi = yrev ? 0 : 1; + // for collecting an average luminosity of the heatmap + var pixcount = 0; + var rcount = 0; + var gcount = 0; + var bcount = 0; + + var xb, j, xi, v, row, c; + + function setColor(v, pixsize) { + if(v !== undefined) { + var c = sclFunc(v); + c[0] = Math.round(c[0]); + c[1] = Math.round(c[1]); + c[2] = Math.round(c[2]); + + pixcount += pixsize; + rcount += c[0] * pixsize; + gcount += c[1] * pixsize; + bcount += c[2] * pixsize; + return c; + } + return [0, 0, 0, 0]; + } + + function interpColor(r0, r1, xinterp, yinterp) { + var z00 = r0[xinterp.bin0]; + if(z00 === undefined) return setColor(undefined, 1); + + var z01 = r0[xinterp.bin1], + z10 = r1[xinterp.bin0], + z11 = r1[xinterp.bin1], + dx = (z01 - z00) || 0, + dy = (z10 - z00) || 0, + dxy; + + // the bilinear interpolation term needs different calculations + // for all the different permutations of missing data + // among the neighbors of the main point, to ensure + // continuity across brick boundaries. + if(z01 === undefined) { + if(z11 === undefined) dxy = 0; + else if(z10 === undefined) dxy = 2 * (z11 - z00); + else dxy = (2 * z11 - z10 - z00) * 2 / 3; + } + else if(z11 === undefined) { + if(z10 === undefined) dxy = 0; + else dxy = (2 * z00 - z01 - z10) * 2 / 3; + } + else if(z10 === undefined) dxy = (2 * z11 - z01 - z00) * 2 / 3; + else dxy = (z11 + z00 - z01 - z10); + + return setColor(z00 + xinterp.frac * dx + yinterp.frac * (dy + xinterp.frac * dxy)); + } + + if(zsmooth) { // best or fast, works fastest with imageData + var pxIndex = 0, + pixels; + + try { + pixels = new Uint8Array(imageWidth * imageHeight * 4); + } + catch(e) { + pixels = new Array(imageWidth * imageHeight * 4); + } + + if(zsmooth === 'best') { + var xForPx = xc || x; + var yForPx = yc || y; + var xPixArray = new Array(xForPx.length); + var yPixArray = new Array(yForPx.length); + var xinterpArray = new Array(imageWidth); + var findInterpX = xc ? findInterpFromCenters : findInterp; + var findInterpY = yc ? findInterpFromCenters : findInterp; + var yinterp, r0, r1; + + // first make arrays of x and y pixel locations of brick boundaries + for(i = 0; i < xForPx.length; i++) xPixArray[i] = Math.round(xa.c2p(xForPx[i]) - left); + for(i = 0; i < yForPx.length; i++) yPixArray[i] = Math.round(ya.c2p(yForPx[i]) - top); + + // then make arrays of interpolations + // (bin0=closest, bin1=next, frac=fractional dist.) + for(i = 0; i < imageWidth; i++) xinterpArray[i] = findInterpX(i, xPixArray); + + // now do the interpolations and fill the png + for(j = 0; j < imageHeight; j++) { + yinterp = findInterpY(j, yPixArray); + r0 = z[yinterp.bin0]; + r1 = z[yinterp.bin1]; + for(i = 0; i < imageWidth; i++, pxIndex += 4) { + c = interpColor(r0, r1, xinterpArray[i], yinterp); + putColor(pixels, pxIndex, c); + } + } + } + else { // zsmooth = fast + for(j = 0; j < m; j++) { + row = z[j]; + yb = ypx(j); + for(i = 0; i < imageWidth; i++) { + c = setColor(row[i], 1); + pxIndex = (yb * imageWidth + xpx(i)) * 4; + putColor(pixels, pxIndex, c); + } + } + } + + var imageData = context.createImageData(imageWidth, imageHeight); + try { + imageData.data.set(pixels); + } + catch(e) { + var pxArray = imageData.data, + dlen = pxArray.length; + for(j = 0; j < dlen; j ++) { + pxArray[j] = pixels[j]; + } + } + + context.putImageData(imageData, 0, 0); + } else { // zsmooth = false -> filling potentially large bricks works fastest with fillRect + + // gaps do not need to be exact integers, but if they *are* we will get + // cleaner edges by rounding at least one edge + var xGap = trace.xgap; + var yGap = trace.ygap; + var xGapLeft = Math.floor(xGap / 2); + var yGapTop = Math.floor(yGap / 2); + + for(j = 0; j < m; j++) { + row = z[j]; + yb.reverse(); + yb[ybi] = ypx(j + 1); + if(yb[0] === yb[1] || yb[0] === undefined || yb[1] === undefined) { + continue; + } + xi = xpx(0); + xb = [xi, xi]; + for(i = 0; i < n; i++) { + // build one color brick! + xb.reverse(); + xb[xbi] = xpx(i + 1); + if(xb[0] === xb[1] || xb[0] === undefined || xb[1] === undefined) { + continue; + } + v = row[i]; + c = setColor(v, (xb[1] - xb[0]) * (yb[1] - yb[0])); + context.fillStyle = 'rgba(' + c.join(',') + ')'; + + context.fillRect(xb[0] + xGapLeft, yb[0] + yGapTop, + xb[1] - xb[0] - xGap, yb[1] - yb[0] - yGap); + } + } + } + + rcount = Math.round(rcount / pixcount); + gcount = Math.round(gcount / pixcount); + bcount = Math.round(bcount / pixcount); + var avgColor = tinycolor('rgb(' + rcount + ',' + gcount + ',' + bcount + ')'); + + gd._hmpixcount = (gd._hmpixcount||0) + pixcount; + gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance(); + + var image3 = plotGroup.selectAll('image') + .data(cd); + + image3.enter().append('svg:image').attr({ + xmlns: xmlnsNamespaces.svg, + preserveAspectRatio: 'none' + }); + + image3.attr({ + height: imageHeight, + width: imageWidth, + x: left, + y: top, + 'xlink:href': canvas.toDataURL('image/png') + }); + }); +}; + +// get interpolated bin value. Returns {bin0:closest bin, frac:fractional dist to next, bin1:next bin} +function findInterp(pixel, pixArray) { + var maxBin = pixArray.length - 2; + var bin = Lib.constrain(Lib.findBin(pixel, pixArray), 0, maxBin); + var pix0 = pixArray[bin]; + var pix1 = pixArray[bin + 1]; + var interp = Lib.constrain(bin + (pixel - pix0) / (pix1 - pix0) - 0.5, 0, maxBin); + var bin0 = Math.round(interp); + var frac = Math.abs(interp - bin0); + + if(!interp || interp === maxBin || !frac) { + return { + bin0: bin0, + bin1: bin0, + frac: 0 + }; + } + return { + bin0: bin0, + frac: frac, + bin1: Math.round(bin0 + frac / (interp - bin0)) + }; +} + +function findInterpFromCenters(pixel, centerPixArray) { + var maxBin = centerPixArray.length - 1; + var bin = Lib.constrain(Lib.findBin(pixel, centerPixArray), 0, maxBin); + var pix0 = centerPixArray[bin]; + var pix1 = centerPixArray[bin + 1]; + var frac = ((pixel - pix0) / (pix1 - pix0)) || 0; + if(frac <= 0) { + return { + bin0: bin, + bin1: bin, + frac: 0 + }; + } + if(frac < 0.5) { + return { + bin0: bin, + bin1: bin + 1, + frac: frac + }; + } + return { + bin0: bin + 1, + bin1: bin, + frac: 1 - frac + }; +} + +function putColor(pixels, pxIndex, c) { + pixels[pxIndex] = c[0]; + pixels[pxIndex + 1] = c[1]; + pixels[pxIndex + 2] = c[2]; + pixels[pxIndex + 3] = Math.round(c[3] * 255); +} + +},{"../../components/colorscale":585,"../../constants/xmlns_namespaces":674,"../../lib":696,"../../registry":827,"./max_row_length":956,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"tinycolor2":514}],958:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +module.exports = function style(gd) { + d3.select(gd).selectAll('.hm image') + .style('opacity', function(d) { + return d.trace.opacity; + }); +}; + +},{"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],959:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function handleStyleDefaults(traceIn, traceOut, coerce) { + var zsmooth = coerce('zsmooth'); + if(zsmooth === false) { + // ensure that xgap and ygap are coerced only when zsmooth allows them to have an effect. + coerce('xgap'); + coerce('ygap'); + } + + coerce('zhoverformat'); +}; + +},{}],960:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var Lib = _dereq_('../../lib'); + +var Registry = _dereq_('../../registry'); + +module.exports = function handleXYZDefaults(traceIn, traceOut, coerce, layout, xName, yName) { + var z = coerce('z'); + xName = xName || 'x'; + yName = yName || 'y'; + var x, y; + + if(z === undefined || !z.length) return 0; + + if(Lib.isArray1D(traceIn.z)) { + x = coerce(xName); + y = coerce(yName); + + // column z must be accompanied by xName and yName arrays + if(!(x && x.length && y && y.length)) return 0; + + traceOut._length = Math.min(x.length, y.length, z.length); + } + else { + x = coordDefaults(xName, coerce); + y = coordDefaults(yName, coerce); + + // TODO put z validation elsewhere + if(!isValidZ(z)) return 0; + + coerce('transpose'); + + traceOut._length = null; + } + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, [xName, yName], layout); + + return true; +}; + +function coordDefaults(coordStr, coerce) { + var coord = coerce(coordStr), + coordType = coord ? + coerce(coordStr + 'type', 'array') : + 'scaled'; + + if(coordType === 'scaled') { + coerce(coordStr + '0'); + coerce('d' + coordStr); + } + + return coord; +} + +function isValidZ(z) { + var allRowsAreArrays = true, + oneRowIsFilled = false, + hasOneNumber = false, + zi; + + /* + * Without this step: + * + * hasOneNumber = false breaks contour but not heatmap + * allRowsAreArrays = false breaks contour but not heatmap + * oneRowIsFilled = false breaks both + */ + + for(var i = 0; i < z.length; i++) { + zi = z[i]; + if(!Lib.isArrayOrTypedArray(zi)) { + allRowsAreArrays = false; + break; + } + if(zi.length > 0) oneRowIsFilled = true; + for(var j = 0; j < zi.length; j++) { + if(isNumeric(zi[j])) { + hasOneNumber = true; + break; + } + } + } + + return (allRowsAreArrays && oneRowIsFilled && hasOneNumber); +} + +},{"../../lib":696,"../../registry":827,"fast-isnumeric":214}],961:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +var heatmapAttrs = _dereq_('../heatmap/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + + +var commonList = [ + 'z', + 'x', 'x0', 'dx', + 'y', 'y0', 'dy', + 'text', 'transpose', + 'xtype', 'ytype' +]; + +var attrs = {}; + +for(var i = 0; i < commonList.length; i++) { + var k = commonList[i]; + attrs[k] = heatmapAttrs[k]; +} + +extendFlat( + attrs, + colorscaleAttrs('', {cLetter: 'z', autoColorDflt: false}), + {colorbar: colorbarAttrs} +); + +module.exports = overrideAll(attrs, 'calc', 'nested'); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/edit_types":727,"../heatmap/attributes":945}],962:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createHeatmap2D = _dereq_('gl-heatmap2d'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var str2RGBArray = _dereq_('../../lib/str2rgbarray'); + + +function Heatmap(scene, uid) { + this.scene = scene; + this.uid = uid; + this.type = 'heatmapgl'; + + this.name = ''; + this.hoverinfo = 'all'; + + this.xData = []; + this.yData = []; + this.zData = []; + this.textLabels = []; + + this.idToIndex = []; + this.bounds = [0, 0, 0, 0]; + + this.options = { + z: [], + x: [], + y: [], + shape: [0, 0], + colorLevels: [0], + colorValues: [0, 0, 0, 1] + }; + + this.heatmap = createHeatmap2D(scene.glplot, this.options); + this.heatmap._trace = this; +} + +var proto = Heatmap.prototype; + +proto.handlePick = function(pickResult) { + var options = this.options, + shape = options.shape, + index = pickResult.pointId, + xIndex = index % shape[0], + yIndex = Math.floor(index / shape[0]), + zIndex = index; + + return { + trace: this, + dataCoord: pickResult.dataCoord, + traceCoord: [ + options.x[xIndex], + options.y[yIndex], + options.z[zIndex] + ], + textLabel: this.textLabels[index], + name: this.name, + pointIndex: [yIndex, xIndex], + hoverinfo: this.hoverinfo + }; +}; + +proto.update = function(fullTrace, calcTrace) { + var calcPt = calcTrace[0]; + + this.index = fullTrace.index; + this.name = fullTrace.name; + this.hoverinfo = fullTrace.hoverinfo; + + // convert z from 2D -> 1D + var z = calcPt.z; + this.options.z = [].concat.apply([], z); + + var rowLen = z[0].length, + colLen = z.length; + this.options.shape = [rowLen, colLen]; + + this.options.x = calcPt.x; + this.options.y = calcPt.y; + + var colorOptions = convertColorscale(fullTrace); + this.options.colorLevels = colorOptions.colorLevels; + this.options.colorValues = colorOptions.colorValues; + + // convert text from 2D -> 1D + this.textLabels = [].concat.apply([], fullTrace.text); + + this.heatmap.update(this.options); + + var xa = this.scene.xaxis; + var ya = this.scene.yaxis; + fullTrace._extremes[xa._id] = Axes.findExtremes(xa, calcPt.x); + fullTrace._extremes[ya._id] = Axes.findExtremes(ya, calcPt.y); +}; + +proto.dispose = function() { + this.heatmap.dispose(); +}; + +function convertColorscale(fullTrace) { + var scl = fullTrace.colorscale, + zmin = fullTrace.zmin, + zmax = fullTrace.zmax; + + var N = scl.length, + domain = new Array(N), + range = new Array(4 * N); + + for(var i = 0; i < N; i++) { + var si = scl[i]; + var color = str2RGBArray(si[1]); + + domain[i] = zmin + si[0] * (zmax - zmin); + + for(var j = 0; j < 4; j++) { + range[(4 * i) + j] = color[j]; + } + } + + return { + colorLevels: domain, + colorValues: range + }; +} + +function createHeatmap(scene, fullTrace, calcTrace) { + var plot = new Heatmap(scene, fullTrace.uid); + plot.update(fullTrace, calcTrace); + return plot; +} + +module.exports = createHeatmap; + +},{"../../lib/str2rgbarray":719,"../../plots/cartesian/axes":744,"gl-heatmap2d":241}],963:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var HeatmapGl = {}; + +HeatmapGl.attributes = _dereq_('./attributes'); +HeatmapGl.supplyDefaults = _dereq_('../heatmap/defaults'); +HeatmapGl.colorbar = _dereq_('../heatmap/colorbar'); + +HeatmapGl.calc = _dereq_('../heatmap/calc'); +HeatmapGl.plot = _dereq_('./convert'); + +HeatmapGl.moduleType = 'trace'; +HeatmapGl.name = 'heatmapgl'; +HeatmapGl.basePlotModule = _dereq_('../../plots/gl2d'); +HeatmapGl.categories = ['gl', 'gl2d', '2dMap']; +HeatmapGl.meta = { + +}; + +module.exports = HeatmapGl; + +},{"../../plots/gl2d":784,"../heatmap/calc":946,"../heatmap/colorbar":948,"../heatmap/defaults":950,"./attributes":961,"./convert":962}],964:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var barAttrs = _dereq_('../bar/attributes'); +var makeBinAttrs = _dereq_('./bin_attributes'); + +module.exports = { + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + y: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + + text: barAttrs.text, + orientation: barAttrs.orientation, + + histfunc: { + valType: 'enumerated', + values: ['count', 'sum', 'avg', 'min', 'max'], + + dflt: 'count', + editType: 'calc', + + }, + histnorm: { + valType: 'enumerated', + values: ['', 'percent', 'probability', 'density', 'probability density'], + dflt: '', + + editType: 'calc', + + }, + + cumulative: { + enabled: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + + direction: { + valType: 'enumerated', + values: ['increasing', 'decreasing'], + dflt: 'increasing', + + editType: 'calc', + + }, + + currentbin: { + valType: 'enumerated', + values: ['include', 'exclude', 'half'], + dflt: 'include', + + editType: 'calc', + + }, + editType: 'calc' + }, + nbinsx: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + xbins: makeBinAttrs('x', true), + + nbinsy: { + valType: 'integer', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + ybins: makeBinAttrs('y', true), + autobinx: { + valType: 'boolean', + dflt: null, + + editType: 'calc', + + }, + autobiny: { + valType: 'boolean', + dflt: null, + + editType: 'calc', + impliedEdits: { + 'ybins.start': undefined, + 'ybins.end': undefined, + 'ybins.size': undefined + }, + + }, + + marker: barAttrs.marker, + + selected: barAttrs.selected, + unselected: barAttrs.unselected, + + _deprecated: { + bardir: barAttrs._deprecated.bardir + } +}; + +},{"../bar/attributes":837,"./bin_attributes":966}],965:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = function doAvg(size, counts) { + var nMax = size.length, + total = 0; + for(var i = 0; i < nMax; i++) { + if(counts[i]) { + size[i] /= counts[i]; + total += size[i]; + } + else size[i] = null; + } + return total; +}; + +},{}],966:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function makeBinAttrs(axLetter, match) { + return { + start: { + valType: 'any', // for date axes + + editType: 'calc', + + }, + end: { + valType: 'any', // for date axes + + editType: 'calc', + + }, + size: { + valType: 'any', // for date axes + + editType: 'calc', + + }, + editType: 'calc' + }; +}; + +},{}],967:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + + +module.exports = { + count: function(n, i, size) { + size[n]++; + return 1; + }, + + sum: function(n, i, size, counterData) { + var v = counterData[i]; + if(isNumeric(v)) { + v = Number(v); + size[n] += v; + return v; + } + return 0; + }, + + avg: function(n, i, size, counterData, counts) { + var v = counterData[i]; + if(isNumeric(v)) { + v = Number(v); + size[n] += v; + counts[n]++; + } + return 0; + }, + + min: function(n, i, size, counterData) { + var v = counterData[i]; + if(isNumeric(v)) { + v = Number(v); + if(!isNumeric(size[n])) { + size[n] = v; + return v; + } + else if(size[n] > v) { + var delta = v - size[n]; + size[n] = v; + return delta; + } + } + return 0; + }, + + max: function(n, i, size, counterData) { + var v = counterData[i]; + if(isNumeric(v)) { + v = Number(v); + if(!isNumeric(size[n])) { + size[n] = v; + return v; + } + else if(size[n] < v) { + var delta = v - size[n]; + size[n] = v; + return delta; + } + } + return 0; + } +}; + +},{"fast-isnumeric":214}],968:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var numConstants = _dereq_('../../constants/numerical'); +var oneYear = numConstants.ONEAVGYEAR; +var oneMonth = numConstants.ONEAVGMONTH; +var oneDay = numConstants.ONEDAY; +var oneHour = numConstants.ONEHOUR; +var oneMin = numConstants.ONEMIN; +var oneSec = numConstants.ONESEC; +var tickIncrement = _dereq_('../../plots/cartesian/axes').tickIncrement; + + +/* + * make a function that will find rounded bin edges + * @param {number} leftGap: how far from the left edge of any bin is the closest data value? + * @param {number} rightGap: how far from the right edge of any bin is the closest data value? + * @param {Array[number]} binEdges: the actual edge values used in binning + * @param {object} pa: the position axis + * @param {string} calendar: the data calendar + * + * @return {function(v, isRightEdge)}: + * find the start (isRightEdge is falsy) or end (truthy) label value for a bin edge `v` + */ +module.exports = function getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar) { + // the rounding digit is the largest digit that changes in *all* of 4 regions: + // - inside the rightGap before binEdges[0] (shifted 10% to the left) + // - inside the leftGap after binEdges[0] (expanded by 10% of rightGap on each end) + // - same for binEdges[1] + var dv0 = -1.1 * rightGap; + var dv1 = -0.1 * rightGap; + var dv2 = leftGap - dv1; + var edge0 = binEdges[0]; + var edge1 = binEdges[1]; + var leftDigit = Math.min( + biggestDigitChanged(edge0 + dv1, edge0 + dv2, pa, calendar), + biggestDigitChanged(edge1 + dv1, edge1 + dv2, pa, calendar) + ); + var rightDigit = Math.min( + biggestDigitChanged(edge0 + dv0, edge0 + dv1, pa, calendar), + biggestDigitChanged(edge1 + dv0, edge1 + dv1, pa, calendar) + ); + + // normally we try to make the label for the right edge different from + // the left edge label, so it's unambiguous which bin gets data on the edge. + // but if this results in more than 3 extra digits (or for dates, more than + // 2 fields ie hr&min or min&sec, which is 3600x), it'll be more clutter than + // useful so keep the label cleaner instead + var digit, disambiguateEdges; + if(leftDigit > rightDigit && rightDigit < Math.abs(edge1 - edge0) / 4000) { + digit = leftDigit; + disambiguateEdges = false; + } + else { + digit = Math.min(leftDigit, rightDigit); + disambiguateEdges = true; + } + + if(pa.type === 'date' && digit > oneDay) { + var dashExclude = (digit === oneYear) ? 1 : 6; + var increment = (digit === oneYear) ? 'M12' : 'M1'; + + return function(v, isRightEdge) { + var dateStr = pa.c2d(v, oneYear, calendar); + var dashPos = dateStr.indexOf('-', dashExclude); + if(dashPos > 0) dateStr = dateStr.substr(0, dashPos); + var roundedV = pa.d2c(dateStr, 0, calendar); + + if(roundedV < v) { + var nextV = tickIncrement(roundedV, increment, false, calendar); + if((roundedV + nextV) / 2 < v + leftGap) roundedV = nextV; + } + + if(isRightEdge && disambiguateEdges) { + return tickIncrement(roundedV, increment, true, calendar); + } + + return roundedV; + }; + } + + return function(v, isRightEdge) { + var roundedV = digit * Math.round(v / digit); + // if we rounded down and we could round up and still be < leftGap + // (or what leftGap values round to), do that + if(roundedV + (digit / 10) < v && roundedV + (digit * 0.9) < v + leftGap) { + roundedV += digit; + } + // finally for the right edge back off one digit - but only if we can do that + // and not clip off any data that's potentially in the bin + if(isRightEdge && disambiguateEdges) { + roundedV -= digit; + } + return roundedV; + }; +}; + +/* + * Find the largest digit that changes within a (calcdata) region [v1, v2] + * if dates, "digit" means date/time part when it's bigger than a second + * returns the unit value to round to this digit, eg 0.01 to round to hundredths, or + * 100 to round to hundreds. returns oneMonth or oneYear for month or year rounding, + * so that Math.min will work, rather than 'M1' and 'M12' + */ +function biggestDigitChanged(v1, v2, pa, calendar) { + // are we crossing zero? can't say anything. + // in principle this doesn't apply to dates but turns out this doesn't matter. + if(v1 * v2 <= 0) return Infinity; + + var dv = Math.abs(v2 - v1); + var isDate = pa.type === 'date'; + var digit = biggestGuaranteedDigitChanged(dv, isDate); + // see if a larger digit also changed + for(var i = 0; i < 10; i++) { + // numbers: next digit needs to be >10x but <100x then gets rounded down. + // dates: next digit can be as much as 60x (then rounded down) + var nextDigit = biggestGuaranteedDigitChanged(digit * 80, isDate); + // if we get to years, the chain stops + if(digit === nextDigit) break; + if(didDigitChange(nextDigit, v1, v2, isDate, pa, calendar)) digit = nextDigit; + else break; + } + return digit; +} + +/* + * Find the largest digit that *definitely* changes in a region [v, v + dv] for any v + * for nonuniform date regions (months/years) pick the largest + */ +function biggestGuaranteedDigitChanged(dv, isDate) { + if(isDate && dv > oneSec) { + // this is supposed to be the biggest *guaranteed* change + // so compare to the longest month and year across any calendar, + // and we'll iterate back up later + // note: does not support rounding larger than one year. We could add + // that if anyone wants it, but seems unusual and not strictly necessary. + if(dv > oneDay) { + if(dv > oneYear * 1.1) return oneYear; + if(dv > oneMonth * 1.1) return oneMonth; + return oneDay; + } + + if(dv > oneHour) return oneHour; + if(dv > oneMin) return oneMin; + return oneSec; + } + return Math.pow(10, Math.floor(Math.log(dv) / Math.LN10)); +} + +function didDigitChange(digit, v1, v2, isDate, pa, calendar) { + if(isDate && digit > oneDay) { + var dateParts1 = dateParts(v1, pa, calendar); + var dateParts2 = dateParts(v2, pa, calendar); + var parti = (digit === oneYear) ? 0 : 1; + return dateParts1[parti] !== dateParts2[parti]; + + } + return Math.floor(v2 / digit) - Math.floor(v1 / digit) > 0.1; +} + +function dateParts(v, pa, calendar) { + var parts = pa.c2d(v, oneYear, calendar).split('-'); + if(parts[0] === '') { + parts.unshift(); + parts[0] = '-' + parts[0]; + } + return parts; +} + +},{"../../constants/numerical":673,"../../plots/cartesian/axes":744}],969:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var arraysToCalcdata = _dereq_('../bar/arrays_to_calcdata'); +var binFunctions = _dereq_('./bin_functions'); +var normFunctions = _dereq_('./norm_functions'); +var doAvg = _dereq_('./average'); +var getBinSpanLabelRound = _dereq_('./bin_label_vals'); + +module.exports = function calc(gd, trace) { + // ignore as much processing as possible (and including in autorange) if not visible + if(trace.visible !== true) return; + + // depending on orientation, set position and size axes and data ranges + // note: this logic for choosing orientation is duplicated in graph_obj->setstyles + var pos = []; + var size = []; + var pa = Axes.getFromId(gd, trace.orientation === 'h' ? + (trace.yaxis || 'y') : (trace.xaxis || 'x')); + var mainData = trace.orientation === 'h' ? 'y' : 'x'; + var counterData = {x: 'y', y: 'x'}[mainData]; + var calendar = trace[mainData + 'calendar']; + var cumulativeSpec = trace.cumulative; + var i; + + var binsAndPos = calcAllAutoBins(gd, trace, pa, mainData); + var binSpec = binsAndPos[0]; + var pos0 = binsAndPos[1]; + + var nonuniformBins = typeof binSpec.size === 'string'; + var binEdges = []; + var bins = nonuniformBins ? binEdges : binSpec; + // make the empty bin array + var inc = []; + var counts = []; + var inputPoints = []; + var total = 0; + var norm = trace.histnorm; + var func = trace.histfunc; + var densityNorm = norm.indexOf('density') !== -1; + var i2, binEnd, n; + + if(cumulativeSpec.enabled && densityNorm) { + // we treat "cumulative" like it means "integral" if you use a density norm, + // which in the end means it's the same as without "density" + norm = norm.replace(/ ?density$/, ''); + densityNorm = false; + } + + var extremeFunc = func === 'max' || func === 'min'; + var sizeInit = extremeFunc ? null : 0; + var binFunc = binFunctions.count; + var normFunc = normFunctions[norm]; + var isAvg = false; + var pr2c = function(v) { return pa.r2c(v, 0, calendar); }; + var rawCounterData; + + if(Lib.isArrayOrTypedArray(trace[counterData]) && func !== 'count') { + rawCounterData = trace[counterData]; + isAvg = func === 'avg'; + binFunc = binFunctions[func]; + } + + // create the bins (and any extra arrays needed) + // assume more than 1e6 bins is an error, so we don't crash the browser + i = pr2c(binSpec.start); + + // decrease end a little in case of rounding errors + binEnd = pr2c(binSpec.end) + (i - Axes.tickIncrement(i, binSpec.size, false, calendar)) / 1e6; + + while(i < binEnd && pos.length < 1e6) { + i2 = Axes.tickIncrement(i, binSpec.size, false, calendar); + pos.push((i + i2) / 2); + size.push(sizeInit); + inputPoints.push([]); + // nonuniform bins (like months) we need to search, + // rather than straight calculate the bin we're in + binEdges.push(i); + // nonuniform bins also need nonuniform normalization factors + if(densityNorm) inc.push(1 / (i2 - i)); + if(isAvg) counts.push(0); + // break to avoid infinite loops + if(i2 <= i) break; + i = i2; + } + binEdges.push(i); + + // for date axes we need bin bounds to be calcdata. For nonuniform bins + // we already have this, but uniform with start/end/size they're still strings. + if(!nonuniformBins && pa.type === 'date') { + bins = { + start: pr2c(bins.start), + end: pr2c(bins.end), + size: bins.size + }; + } + + // bin the data + // and make histogram-specific pt-number-to-cd-index map object + var nMax = size.length; + var uniqueValsPerBin = true; + var leftGap = Infinity; + var rightGap = Infinity; + var ptNumber2cdIndex = {}; + for(i = 0; i < pos0.length; i++) { + var posi = pos0[i]; + n = Lib.findBin(posi, bins); + if(n >= 0 && n < nMax) { + total += binFunc(n, i, size, rawCounterData, counts); + if(uniqueValsPerBin && inputPoints[n].length && posi !== pos0[inputPoints[n][0]]) { + uniqueValsPerBin = false; + } + inputPoints[n].push(i); + ptNumber2cdIndex[i] = n; + + leftGap = Math.min(leftGap, posi - binEdges[n]); + rightGap = Math.min(rightGap, binEdges[n + 1] - posi); + } + } + + var roundFn; + if(!uniqueValsPerBin) { + roundFn = getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar); + } + + // average and/or normalize the data, if needed + if(isAvg) total = doAvg(size, counts); + if(normFunc) normFunc(size, total, inc); + + // after all normalization etc, now we can accumulate if desired + if(cumulativeSpec.enabled) cdf(size, cumulativeSpec.direction, cumulativeSpec.currentbin); + + + var seriesLen = Math.min(pos.length, size.length); + var cd = []; + var firstNonzero = 0; + var lastNonzero = seriesLen - 1; + + // look for empty bins at the ends to remove, so autoscale omits them + for(i = 0; i < seriesLen; i++) { + if(size[i]) { + firstNonzero = i; + break; + } + } + for(i = seriesLen - 1; i >= firstNonzero; i--) { + if(size[i]) { + lastNonzero = i; + break; + } + } + + // create the "calculated data" to plot + for(i = firstNonzero; i <= lastNonzero; i++) { + if((isNumeric(pos[i]) && isNumeric(size[i]))) { + var cdi = { + p: pos[i], + s: size[i], + b: 0 + }; + + // setup hover and event data fields, + // N.B. pts and "hover" positions ph0/ph1 don't seem to make much sense + // for cumulative distributions + if(!cumulativeSpec.enabled) { + cdi.pts = inputPoints[i]; + if(uniqueValsPerBin) { + cdi.ph0 = cdi.ph1 = (inputPoints[i].length) ? pos0[inputPoints[i][0]] : pos[i]; + } + else { + cdi.ph0 = roundFn(binEdges[i]); + cdi.ph1 = roundFn(binEdges[i + 1], true); + } + } + cd.push(cdi); + } + } + + if(cd.length === 1) { + // when we collapse to a single bin, calcdata no longer describes bin size + // so we need to explicitly specify it + cd[0].width1 = Axes.tickIncrement(cd[0].p, binSpec.size, false, calendar) - cd[0].p; + } + + arraysToCalcdata(cd, trace); + + if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { + Lib.tagSelected(cd, trace, ptNumber2cdIndex); + } + + return cd; +}; + +/* + * calcAllAutoBins: we want all histograms on the same axes to share bin specs + * if they're grouped or stacked. If the user has explicitly specified differing + * bin specs, there's nothing we can do, but if possible we will try to use the + * smallest bins of any of the auto values for all histograms grouped/stacked + * together. + */ +function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) { + var binAttr = mainData + 'bins'; + var fullLayout = gd._fullLayout; + var isOverlay = fullLayout.barmode === 'overlay'; + var i, traces, tracei, calendar, pos0, autoVals, cumulativeSpec; + + var cleanBound = (pa.type === 'date') ? + function(v) { return (v || v === 0) ? Lib.cleanDate(v, null, pa.calendar) : null; } : + function(v) { return isNumeric(v) ? Number(v) : null; }; + + function setBound(attr, bins, newBins) { + if(bins[attr + 'Found']) { + bins[attr] = cleanBound(bins[attr]); + if(bins[attr] === null) bins[attr] = newBins[attr]; + } + else { + autoVals[attr] = bins[attr] = newBins[attr]; + Lib.nestedProperty(traces[0], binAttr + '.' + attr).set(newBins[attr]); + } + } + + var binOpts = fullLayout._histogramBinOpts[trace._groupName]; + + // all but the first trace in this group has already been marked finished + // clear this flag, so next time we run calc we will run autobin again + if(trace._autoBinFinished) { + delete trace._autoBinFinished; + } + else { + traces = binOpts.traces; + var sizeFound = binOpts.sizeFound; + var allPos = []; + autoVals = traces[0]._autoBin = {}; + // Note: we're including `legendonly` traces here for autobin purposes, + // so that showing & hiding from the legend won't affect bins. + // But this complicates things a bit since those traces don't `calc`, + // hence `isFirstVisible`. + var isFirstVisible = true; + for(i = 0; i < traces.length; i++) { + tracei = traces[i]; + pos0 = tracei._pos0 = pa.makeCalcdata(tracei, mainData); + allPos = Lib.concat(allPos, pos0); + delete tracei._autoBinFinished; + if(trace.visible === true) { + if(isFirstVisible) { + isFirstVisible = false; + } + else { + delete tracei._autoBin; + tracei._autoBinFinished = 1; + } + } + } + calendar = traces[0][mainData + 'calendar']; + var newBinSpec = Axes.autoBin( + allPos, pa, binOpts.nbins, false, calendar, sizeFound && binOpts.size); + + // Edge case: single-valued histogram overlaying others + // Use them all together to calculate the bin size for the single-valued one + if(isOverlay && newBinSpec._dataSpan === 0 && pa.type !== 'category') { + // Several single-valued histograms! Stop infinite recursion, + // just return an extra flag that tells handleSingleValueOverlays + // to sort out this trace too + if(_overlayEdgeCase) return [newBinSpec, pos0, true]; + + newBinSpec = handleSingleValueOverlays(gd, trace, pa, mainData, binAttr); + } + + // adjust for CDF edge cases + cumulativeSpec = tracei.cumulative; + if(cumulativeSpec.enabled && (cumulativeSpec.currentbin !== 'include')) { + if(cumulativeSpec.direction === 'decreasing') { + newBinSpec.start = pa.c2r(Axes.tickIncrement( + pa.r2c(newBinSpec.start, 0, calendar), + newBinSpec.size, true, calendar + )); + } + else { + newBinSpec.end = pa.c2r(Axes.tickIncrement( + pa.r2c(newBinSpec.end, 0, calendar), + newBinSpec.size, false, calendar + )); + } + } + + binOpts.size = newBinSpec.size; + if(!sizeFound) { + autoVals.size = newBinSpec.size; + Lib.nestedProperty(traces[0], binAttr + '.size').set(newBinSpec.size); + } + + setBound('start', binOpts, newBinSpec); + setBound('end', binOpts, newBinSpec); + } + + pos0 = trace._pos0; + delete trace._pos0; + + // Each trace can specify its own start/end, or if omitted + // we ensure they're beyond the bounds of this trace's data, + // and we need to make sure start is aligned with the main start + var traceInputBins = trace._input[binAttr] || {}; + var traceBinOptsCalc = Lib.extendFlat({}, binOpts); + var mainStart = binOpts.start; + var startIn = pa.r2l(traceInputBins.start); + var hasStart = startIn !== undefined; + if((binOpts.startFound || hasStart) && startIn !== pa.r2l(mainStart)) { + // We have an explicit start to reconcile across traces + // if this trace has an explicit start, shift it down to a bin edge + // if another trace had an explicit start, shift it down to a + // bin edge past our data + var traceStart = hasStart ? + startIn : + Lib.aggNums(Math.min, null, pos0); + + var dummyAx = { + type: pa.type === 'category' ? 'linear' : pa.type, + r2l: pa.r2l, + dtick: binOpts.size, + tick0: mainStart, + calendar: calendar, + range: ([traceStart, Axes.tickIncrement(traceStart, binOpts.size, false, calendar)]).map(pa.l2r) + }; + var newStart = Axes.tickFirst(dummyAx); + if(newStart > pa.r2l(traceStart)) { + newStart = Axes.tickIncrement(newStart, binOpts.size, true, calendar); + } + traceBinOptsCalc.start = pa.l2r(newStart); + if(!hasStart) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.start); + } + + var mainEnd = binOpts.end; + var endIn = pa.r2l(traceInputBins.end); + var hasEnd = endIn !== undefined; + if((binOpts.endFound || hasEnd) && endIn !== pa.r2l(mainEnd)) { + // Reconciling an explicit end is easier, as it doesn't need to + // match bin edges + var traceEnd = hasEnd ? + endIn : + Lib.aggNums(Math.max, null, pos0); + + traceBinOptsCalc.end = pa.l2r(traceEnd); + if(!hasEnd) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.end); + } + + // Backward compatibility for one-time autobinning. + // autobin: true is handled in cleanData, but autobin: false + // needs to be here where we have determined the values. + var autoBinAttr = 'autobin' + mainData; + if(trace._input[autoBinAttr] === false) { + trace._input[binAttr] = Lib.extendFlat({}, trace[binAttr] || {}); + delete trace._input[autoBinAttr]; + delete trace[autoBinAttr]; + } + + return [traceBinOptsCalc, pos0]; +} + +/* + * Adjust single-value histograms in overlay mode to make as good a + * guess as we can at autobin values the user would like. + * + * Returns the binSpec for the trace that sparked all this + */ +function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) { + var overlaidTraceGroup = getConnectedHistograms(gd, trace); + var pastThisTrace = false; + var minSize = Infinity; + var singleValuedTraces = [trace]; + var i, tracei; + + // first collect all the: + // - min bin size from all multi-valued traces + // - single-valued traces + for(i = 0; i < overlaidTraceGroup.length; i++) { + tracei = overlaidTraceGroup[i]; + if(tracei === trace) pastThisTrace = true; + else if(!pastThisTrace) { + // This trace has already had its autobins calculated + // (so must not have been single-valued). + minSize = Math.min(minSize, tracei[binAttr].size); + } + else { + var resulti = calcAllAutoBins(gd, tracei, pa, mainData, true); + var binSpeci = resulti[0]; + var isSingleValued = resulti[2]; + + // so we can use this result when we get to tracei in the normal + // course of events, mark it as done and put _pos0 back + tracei._autoBinFinished = 1; + tracei._pos0 = resulti[1]; + + if(isSingleValued) { + singleValuedTraces.push(tracei); + } + else { + minSize = Math.min(minSize, binSpeci.size); + } + } + } + + // find the real data values for each single-valued trace + // hunt through pos0 for the first valid value + var dataVals = new Array(singleValuedTraces.length); + for(i = 0; i < singleValuedTraces.length; i++) { + var pos0 = singleValuedTraces[i]._pos0; + for(var j = 0; j < pos0.length; j++) { + if(pos0[j] !== undefined) { + dataVals[i] = pos0[j]; + break; + } + } + } + + // are ALL traces are single-valued? use the min difference between + // all of their values (which defaults to 1 if there's still only one) + if(!isFinite(minSize)) { + minSize = Lib.distinctVals(dataVals).minDiff; + } + + // now apply the min size we found to all single-valued traces + for(i = 0; i < singleValuedTraces.length; i++) { + tracei = singleValuedTraces[i]; + var calendar = tracei[mainData + 'calendar']; + + tracei._input[binAttr] = tracei[binAttr] = { + start: pa.c2r(dataVals[i] - minSize / 2, 0, calendar), + end: pa.c2r(dataVals[i] + minSize / 2, 0, calendar), + size: minSize + }; + } + + return trace[binAttr]; +} + +/* + * Return an array of histograms that share axes and orientation. + * + * Only considers histograms. In principle we could include bars in a + * similar way to how we do manually binned histograms, though this + * would have tons of edge cases and value judgments to make. + */ +function getConnectedHistograms(gd, trace) { + var xid = trace.xaxis; + var yid = trace.yaxis; + var orientation = trace.orientation; + + var out = []; + var fullData = gd._fullData; + for(var i = 0; i < fullData.length; i++) { + var tracei = fullData[i]; + if(tracei.type === 'histogram' && + tracei.visible === true && + tracei.orientation === orientation && + tracei.xaxis === xid && tracei.yaxis === yid + ) { + out.push(tracei); + } + } + + return out; +} + + +function cdf(size, direction, currentBin) { + var i, vi, prevSum; + + function firstHalfPoint(i) { + prevSum = size[i]; + size[i] /= 2; + } + + function nextHalfPoint(i) { + vi = size[i]; + size[i] = prevSum + vi / 2; + prevSum += vi; + } + + if(currentBin === 'half') { + + if(direction === 'increasing') { + firstHalfPoint(0); + for(i = 1; i < size.length; i++) { + nextHalfPoint(i); + } + } + else { + firstHalfPoint(size.length - 1); + for(i = size.length - 2; i >= 0; i--) { + nextHalfPoint(i); + } + } + } + else if(direction === 'increasing') { + for(i = 1; i < size.length; i++) { + size[i] += size[i - 1]; + } + + // 'exclude' is identical to 'include' just shifted one bin over + if(currentBin === 'exclude') { + size.unshift(0); + size.pop(); + } + } + else { + for(i = size.length - 2; i >= 0; i--) { + size[i] += size[i + 1]; + } + + if(currentBin === 'exclude') { + size.push(0); + size.shift(); + } + } +} + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../bar/arrays_to_calcdata":836,"./average":965,"./bin_functions":967,"./bin_label_vals":968,"./norm_functions":975,"fast-isnumeric":214}],970:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var nestedProperty = Lib.nestedProperty; + +var attributes = _dereq_('./attributes'); + +var BINATTRS = { + x: [ + {aStr: 'xbins.start', name: 'start'}, + {aStr: 'xbins.end', name: 'end'}, + {aStr: 'xbins.size', name: 'size'}, + {aStr: 'nbinsx', name: 'nbins'} + ], + y: [ + {aStr: 'ybins.start', name: 'start'}, + {aStr: 'ybins.end', name: 'end'}, + {aStr: 'ybins.size', name: 'size'}, + {aStr: 'nbinsy', name: 'nbins'} + ] +}; + +// handle bin attrs and relink auto-determined values so fullData is complete +module.exports = function crossTraceDefaults(fullData, fullLayout) { + var allBinOpts = fullLayout._histogramBinOpts = {}; + var isOverlay = fullLayout.barmode === 'overlay'; + var i, j, traceOut, traceIn, binDirection, group, binOpts; + + function coerce(attr) { + return Lib.coerce(traceOut._input, traceOut, attributes, attr); + } + + for(i = 0; i < fullData.length; i++) { + traceOut = fullData[i]; + if(traceOut.type !== 'histogram') continue; + + // TODO: this shouldn't be relinked as it's only used within calc + // https://github.com/plotly/plotly.js/issues/749 + delete traceOut._autoBinFinished; + + binDirection = traceOut.orientation === 'v' ? 'x' : 'y'; + // in overlay mode make a separate group for each trace + // otherwise collect all traces of the same subplot & orientation + group = isOverlay ? traceOut.uid : (traceOut.xaxis + traceOut.yaxis + binDirection); + traceOut._groupName = group; + + binOpts = allBinOpts[group]; + + if(binOpts) { + binOpts.traces.push(traceOut); + } + else { + binOpts = allBinOpts[group] = { + traces: [traceOut], + direction: binDirection + }; + } + } + + for(group in allBinOpts) { + binOpts = allBinOpts[group]; + binDirection = binOpts.direction; + var attrs = BINATTRS[binDirection]; + for(j = 0; j < attrs.length; j++) { + var attrSpec = attrs[j]; + var attr = attrSpec.name; + + // nbins(x|y) is moot if we have a size. This depends on + // nbins coming after size in binAttrs. + if(attr === 'nbins' && binOpts.sizeFound) continue; + + var aStr = attrSpec.aStr; + for(i = 0; i < binOpts.traces.length; i++) { + traceOut = binOpts.traces[i]; + traceIn = traceOut._input; + if(nestedProperty(traceIn, aStr).get() !== undefined) { + binOpts[attr] = coerce(aStr); + binOpts[attr + 'Found'] = true; + break; + } + var autoVals = traceOut._autoBin; + if(autoVals && autoVals[attr]) { + // if this is the *first* autoval + nestedProperty(traceOut, aStr).set(autoVals[attr]); + } + } + // start and end we need to coerce anyway, after having collected the + // first of each into binOpts, in case a trace wants to restrict its + // data to a certain range + if(attr === 'start' || attr === 'end') { + for(; i < binOpts.traces.length; i++) { + traceOut = binOpts.traces[i]; + coerce(aStr, (traceOut._autoBin || {})[attr]); + } + } + + if(attr === 'nbins' && !binOpts.sizeFound && !binOpts.nbinsFound) { + traceOut = binOpts.traces[0]; + binOpts[attr] = coerce(aStr); + } + } + } +}; + +},{"../../lib":696,"./attributes":964}],971:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); + +var handleStyleDefaults = _dereq_('../bar/style_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var x = coerce('x'); + var y = coerce('y'); + + var cumulative = coerce('cumulative.enabled'); + if(cumulative) { + coerce('cumulative.direction'); + coerce('cumulative.currentbin'); + } + + coerce('text'); + + var orientation = coerce('orientation', (y && !x) ? 'h' : 'v'); + var sampleLetter = orientation === 'v' ? 'x' : 'y'; + var aggLetter = orientation === 'v' ? 'y' : 'x'; + + var len = (x && y) ? Math.min(x.length && y.length) : (traceOut[sampleLetter] || []).length; + + if(!len) { + traceOut.visible = false; + return; + } + + traceOut._length = len; + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); + + var hasAggregationData = traceOut[aggLetter]; + if(hasAggregationData) coerce('histfunc'); + coerce('histnorm'); + + // Note: bin defaults are now handled in Histogram.crossTraceDefaults + // autobin(x|y) are only included here to appease Plotly.validate + coerce('autobin' + sampleLetter); + + handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); + + // override defaultColor for error bars with defaultLine + var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'x', inherit: 'y'}); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../components/color":570,"../../lib":696,"../../registry":827,"../bar/style_defaults":850,"./attributes":964}],972:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function eventData(out, pt, trace, cd, pointNumber) { + // standard cartesian event data + out.x = 'xVal' in pt ? pt.xVal : pt.x; + out.y = 'yVal' in pt ? pt.yVal : pt.y; + + if(pt.xa) out.xaxis = pt.xa; + if(pt.ya) out.yaxis = pt.ya; + + // specific to histogram - CDFs do not have pts (yet?) + if(!(trace.cumulative || {}).enabled) { + var pts = Array.isArray(pointNumber) ? + cd[0].pts[pointNumber[0]][pointNumber[1]] : + cd[pointNumber].pts; + + out.pointNumbers = pts; + out.binNumber = out.pointNumber; + delete out.pointNumber; + delete out.pointIndex; + + var pointIndices; + if(trace._indexToPoints) { + pointIndices = []; + for(var i = 0; i < pts.length; i++) { + pointIndices = pointIndices.concat(trace._indexToPoints[pts[i]]); + } + } else { + pointIndices = pts; + } + + out.pointIndices = pointIndices; + } + + return out; +}; + +},{}],973:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var barHover = _dereq_('../bar/hover').hoverPoints; +var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText; + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var pts = barHover(pointData, xval, yval, hovermode); + + if(!pts) return; + + pointData = pts[0]; + var di = pointData.cd[pointData.index]; + var trace = pointData.cd[0].trace; + + if(!trace.cumulative.enabled) { + var posLetter = trace.orientation === 'h' ? 'y' : 'x'; + + pointData[posLetter + 'Label'] = hoverLabelText(pointData[posLetter + 'a'], di.ph0, di.ph1); + } + + return pts; +}; + +},{"../../plots/cartesian/axes":744,"../bar/hover":842}],974:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** + * Histogram has its own attribute, defaults and calc steps, + * but uses bar's plot to display + * and bar's crossTraceCalc (formerly known as setPositions) for stacking and grouping + */ + +/** + * histogram errorBarsOK is debatable, but it's put in for backward compat. + * there are use cases for it - sqrt for a simple histogram works right now, + * constant and % work but they're not so meaningful. I guess it could be cool + * to allow quadrature combination of errors in summed histograms... + */ + + +var Histogram = {}; + +Histogram.attributes = _dereq_('./attributes'); +Histogram.layoutAttributes = _dereq_('../bar/layout_attributes'); +Histogram.supplyDefaults = _dereq_('./defaults'); +Histogram.crossTraceDefaults = _dereq_('./cross_trace_defaults'); +Histogram.supplyLayoutDefaults = _dereq_('../bar/layout_defaults'); +Histogram.calc = _dereq_('./calc'); +Histogram.crossTraceCalc = _dereq_('../bar/cross_trace_calc').crossTraceCalc; +Histogram.plot = _dereq_('../bar/plot'); +Histogram.layerName = 'barlayer'; +Histogram.style = _dereq_('../bar/style').style; +Histogram.styleOnSelect = _dereq_('../bar/style').styleOnSelect; +Histogram.colorbar = _dereq_('../scatter/marker_colorbar'); +Histogram.hoverPoints = _dereq_('./hover'); +Histogram.selectPoints = _dereq_('../bar/select'); +Histogram.eventData = _dereq_('./event_data'); + +Histogram.moduleType = 'trace'; +Histogram.name = 'histogram'; +Histogram.basePlotModule = _dereq_('../../plots/cartesian'); +Histogram.categories = ['cartesian', 'svg', 'bar', 'histogram', 'oriented', 'errorBarsOK', 'showLegend']; +Histogram.meta = { + +}; + +module.exports = Histogram; + +},{"../../plots/cartesian":756,"../bar/cross_trace_calc":839,"../bar/layout_attributes":844,"../bar/layout_defaults":845,"../bar/plot":846,"../bar/select":847,"../bar/style":849,"../scatter/marker_colorbar":1061,"./attributes":964,"./calc":969,"./cross_trace_defaults":970,"./defaults":971,"./event_data":972,"./hover":973}],975:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + percent: function(size, total) { + var nMax = size.length, + norm = 100 / total; + for(var n = 0; n < nMax; n++) size[n] *= norm; + }, + probability: function(size, total) { + var nMax = size.length; + for(var n = 0; n < nMax; n++) size[n] /= total; + }, + density: function(size, total, inc, yinc) { + var nMax = size.length; + yinc = yinc || 1; + for(var n = 0; n < nMax; n++) size[n] *= inc[n] * yinc; + }, + 'probability density': function(size, total, inc, yinc) { + var nMax = size.length; + if(yinc) total /= yinc; + for(var n = 0; n < nMax; n++) size[n] *= inc[n] / total; + } +}; + +},{}],976:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var histogramAttrs = _dereq_('../histogram/attributes'); +var makeBinAttrs = _dereq_('../histogram/bin_attributes'); +var heatmapAttrs = _dereq_('../heatmap/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = extendFlat( + { + x: histogramAttrs.x, + y: histogramAttrs.y, + + z: { + valType: 'data_array', + editType: 'calc', + + }, + marker: { + color: { + valType: 'data_array', + editType: 'calc', + + }, + editType: 'calc' + }, + + histnorm: histogramAttrs.histnorm, + histfunc: histogramAttrs.histfunc, + nbinsx: histogramAttrs.nbinsx, + xbins: makeBinAttrs('x'), + nbinsy: histogramAttrs.nbinsy, + ybins: makeBinAttrs('y'), + autobinx: histogramAttrs.autobinx, + autobiny: histogramAttrs.autobiny, + + xgap: heatmapAttrs.xgap, + ygap: heatmapAttrs.ygap, + zsmooth: heatmapAttrs.zsmooth, + zhoverformat: heatmapAttrs.zhoverformat + }, + colorscaleAttrs('', { + cLetter: 'z', + autoColorDflt: false + }), + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../heatmap/attributes":945,"../histogram/attributes":964,"../histogram/bin_attributes":966}],977:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); + +var binFunctions = _dereq_('../histogram/bin_functions'); +var normFunctions = _dereq_('../histogram/norm_functions'); +var doAvg = _dereq_('../histogram/average'); +var getBinSpanLabelRound = _dereq_('../histogram/bin_label_vals'); + + +module.exports = function calc(gd, trace) { + var xa = Axes.getFromId(gd, trace.xaxis || 'x'); + var x = trace.x ? xa.makeCalcdata(trace, 'x') : []; + var ya = Axes.getFromId(gd, trace.yaxis || 'y'); + var y = trace.y ? ya.makeCalcdata(trace, 'y') : []; + var xcalendar = trace.xcalendar; + var ycalendar = trace.ycalendar; + var xr2c = function(v) { return xa.r2c(v, 0, xcalendar); }; + var yr2c = function(v) { return ya.r2c(v, 0, ycalendar); }; + var xc2r = function(v) { return xa.c2r(v, 0, xcalendar); }; + var yc2r = function(v) { return ya.c2r(v, 0, ycalendar); }; + + var i, j, n, m; + + var serieslen = trace._length; + if(x.length > serieslen) x.splice(serieslen, x.length - serieslen); + if(y.length > serieslen) y.splice(serieslen, y.length - serieslen); + + // calculate the bins + doAutoBin(trace, 'x', x, xa, xr2c, xc2r, xcalendar); + doAutoBin(trace, 'y', y, ya, yr2c, yc2r, ycalendar); + + // make the empty bin array & scale the map + var z = []; + var onecol = []; + var zerocol = []; + var nonuniformBinsX = (typeof(trace.xbins.size) === 'string'); + var nonuniformBinsY = (typeof(trace.ybins.size) === 'string'); + var xEdges = []; + var yEdges = []; + var xbins = nonuniformBinsX ? xEdges : trace.xbins; + var ybins = nonuniformBinsY ? yEdges : trace.ybins; + var total = 0; + var counts = []; + var inputPoints = []; + var norm = trace.histnorm; + var func = trace.histfunc; + var densitynorm = (norm.indexOf('density') !== -1); + var extremefunc = (func === 'max' || func === 'min'); + var sizeinit = (extremefunc ? null : 0); + var binfunc = binFunctions.count; + var normfunc = normFunctions[norm]; + var doavg = false; + var xinc = []; + var yinc = []; + + // set a binning function other than count? + // for binning functions: check first for 'z', + // then 'mc' in case we had a colored scatter plot + // and want to transfer these colors to the 2D histo + // TODO: axe this, make it the responsibility of the app changing type? or an impliedEdit? + var rawCounterData = ('z' in trace) ? + trace.z : + (('marker' in trace && Array.isArray(trace.marker.color)) ? + trace.marker.color : ''); + if(rawCounterData && func !== 'count') { + doavg = func === 'avg'; + binfunc = binFunctions[func]; + } + + // decrease end a little in case of rounding errors + var binSpec = trace.xbins, + binStart = xr2c(binSpec.start), + binEnd = xr2c(binSpec.end) + + (binStart - Axes.tickIncrement(binStart, binSpec.size, false, xcalendar)) / 1e6; + + for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binSpec.size, false, xcalendar)) { + onecol.push(sizeinit); + xEdges.push(i); + if(doavg) zerocol.push(0); + } + xEdges.push(i); + + var nx = onecol.length; + var x0c = xr2c(trace.xbins.start); + var dx = (i - x0c) / nx; + var x0 = xc2r(x0c + dx / 2); + + binSpec = trace.ybins; + binStart = yr2c(binSpec.start); + binEnd = yr2c(binSpec.end) + + (binStart - Axes.tickIncrement(binStart, binSpec.size, false, ycalendar)) / 1e6; + + for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binSpec.size, false, ycalendar)) { + z.push(onecol.slice()); + yEdges.push(i); + var ipCol = new Array(nx); + for(j = 0; j < nx; j++) ipCol[j] = []; + inputPoints.push(ipCol); + if(doavg) counts.push(zerocol.slice()); + } + yEdges.push(i); + + var ny = z.length; + var y0c = yr2c(trace.ybins.start); + var dy = (i - y0c) / ny; + var y0 = yc2r(y0c + dy / 2); + + if(densitynorm) { + xinc = makeIncrements(onecol.length, xbins, dx, nonuniformBinsX); + yinc = makeIncrements(z.length, ybins, dy, nonuniformBinsY); + } + + // for date axes we need bin bounds to be calcdata. For nonuniform bins + // we already have this, but uniform with start/end/size they're still strings. + if(!nonuniformBinsX && xa.type === 'date') xbins = binsToCalc(xr2c, xbins); + if(!nonuniformBinsY && ya.type === 'date') ybins = binsToCalc(yr2c, ybins); + + // put data into bins + var uniqueValsPerX = true; + var uniqueValsPerY = true; + var xVals = new Array(nx); + var yVals = new Array(ny); + var xGapLow = Infinity; + var xGapHigh = Infinity; + var yGapLow = Infinity; + var yGapHigh = Infinity; + for(i = 0; i < serieslen; i++) { + var xi = x[i]; + var yi = y[i]; + n = Lib.findBin(xi, xbins); + m = Lib.findBin(yi, ybins); + if(n >= 0 && n < nx && m >= 0 && m < ny) { + total += binfunc(n, i, z[m], rawCounterData, counts[m]); + inputPoints[m][n].push(i); + + if(uniqueValsPerX) { + if(xVals[n] === undefined) xVals[n] = xi; + else if(xVals[n] !== xi) uniqueValsPerX = false; + } + if(uniqueValsPerY) { + if(yVals[n] === undefined) yVals[n] = yi; + else if(yVals[n] !== yi) uniqueValsPerY = false; + } + + xGapLow = Math.min(xGapLow, xi - xEdges[n]); + xGapHigh = Math.min(xGapHigh, xEdges[n + 1] - xi); + yGapLow = Math.min(yGapLow, yi - yEdges[m]); + yGapHigh = Math.min(yGapHigh, yEdges[m + 1] - yi); + } + } + // normalize, if needed + if(doavg) { + for(m = 0; m < ny; m++) total += doAvg(z[m], counts[m]); + } + if(normfunc) { + for(m = 0; m < ny; m++) normfunc(z[m], total, xinc, yinc[m]); + } + + return { + x: x, + xRanges: getRanges(xEdges, uniqueValsPerX && xVals, xGapLow, xGapHigh, xa, xcalendar), + x0: x0, + dx: dx, + y: y, + yRanges: getRanges(yEdges, uniqueValsPerY && yVals, yGapLow, yGapHigh, ya, ycalendar), + y0: y0, + dy: dy, + z: z, + pts: inputPoints + }; +}; + +function doAutoBin(trace, axLetter, data, ax, r2c, c2r, calendar) { + var binAttr = axLetter + 'bins'; + var binSpec = trace[binAttr]; + if(!binSpec) binSpec = trace[binAttr] = {}; + var inputBinSpec = trace._input[binAttr] || {}; + var autoBin = trace._autoBin = {}; + + // clear out any previously added autobin info + if(!inputBinSpec.size) delete binSpec.size; + if(inputBinSpec.start === undefined) delete binSpec.start; + if(inputBinSpec.end === undefined) delete binSpec.end; + + var autoSize = !binSpec.size; + var autoStart = binSpec.start === undefined; + var autoEnd = binSpec.end === undefined; + + if(autoSize || autoStart || autoEnd) { + var newBinSpec = Axes.autoBin(data, ax, trace['nbins' + axLetter], '2d', calendar, binSpec.size); + if(trace.type === 'histogram2dcontour') { + // the "true" 2nd argument reverses the tick direction (which we can't + // just do with a minus sign because of month bins) + if(autoStart) { + newBinSpec.start = c2r(Axes.tickIncrement( + r2c(newBinSpec.start), newBinSpec.size, true, calendar)); + } + if(autoEnd) { + newBinSpec.end = c2r(Axes.tickIncrement( + r2c(newBinSpec.end), newBinSpec.size, false, calendar)); + } + } + if(autoSize) binSpec.size = autoBin.size = newBinSpec.size; + if(autoStart) binSpec.start = autoBin.start = newBinSpec.start; + if(autoEnd) binSpec.end = autoBin.end = newBinSpec.end; + } + + // Backward compatibility for one-time autobinning. + // autobin: true is handled in cleanData, but autobin: false + // needs to be here where we have determined the values. + var autoBinAttr = 'autobin' + axLetter; + if(trace._input[autoBinAttr] === false) { + trace._input[binAttr] = Lib.extendFlat({}, binSpec); + delete trace._input[autoBinAttr]; + delete trace[autoBinAttr]; + } +} + +function makeIncrements(len, bins, dv, nonuniform) { + var out = new Array(len); + var i; + if(nonuniform) { + for(i = 0; i < len; i++) out[i] = 1 / (bins[i + 1] - bins[i]); + } + else { + var inc = 1 / dv; + for(i = 0; i < len; i++) out[i] = inc; + } + return out; +} + +function binsToCalc(r2c, bins) { + return { + start: r2c(bins.start), + end: r2c(bins.end), + size: bins.size + }; +} + +function getRanges(edges, uniqueVals, gapLow, gapHigh, ax, calendar) { + var i; + var len = edges.length - 1; + var out = new Array(len); + if(uniqueVals) { + for(i = 0; i < len; i++) out[i] = [uniqueVals[i], uniqueVals[i]]; + } + else { + var roundFn = getBinSpanLabelRound(gapLow, gapHigh, edges, ax, calendar); + for(i = 0; i < len; i++) out[i] = [roundFn(edges[i]), roundFn(edges[i + 1], true)]; + } + return out; +} + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../histogram/average":965,"../histogram/bin_functions":967,"../histogram/bin_label_vals":968,"../histogram/norm_functions":975}],978:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var isNumeric = _dereq_('fast-isnumeric'); + +var BADNUM = _dereq_('../../constants/numerical').BADNUM; +var axisIds = _dereq_('../../plots/cartesian/axis_ids'); +var Lib = _dereq_('../../lib'); + +var attributes = _dereq_('./attributes'); + +var BINDIRECTIONS = ['x', 'y']; + +// Handle bin attrs and relink auto-determined values so fullData is complete +// does not have cross-trace coupling, but moved out here so we have axis types +// and relinked trace._autoBin +module.exports = function crossTraceDefaults(fullData, fullLayout) { + var i, j, traceOut, binDirection; + + function coerce(attr) { + return Lib.coerce(traceOut._input, traceOut, attributes, attr); + } + + for(i = 0; i < fullData.length; i++) { + traceOut = fullData[i]; + var type = traceOut.type; + if(type !== 'histogram2d' && type !== 'histogram2dcontour') continue; + + for(j = 0; j < BINDIRECTIONS.length; j++) { + binDirection = BINDIRECTIONS[j]; + var binAttr = binDirection + 'bins'; + var autoBins = (traceOut._autoBin || {})[binDirection] || {}; + coerce(binAttr + '.start', autoBins.start); + coerce(binAttr + '.end', autoBins.end); + coerce(binAttr + '.size', autoBins.size); + + cleanBins(traceOut, binDirection, fullLayout, autoBins); + + if(!(traceOut[binAttr] || {}).size) coerce('nbins' + binDirection); + } + } +}; + +function cleanBins(trace, binDirection, fullLayout, autoBins) { + var ax = fullLayout[axisIds.id2name(trace[binDirection + 'axis'])]; + var axType = ax.type; + var binAttr = binDirection + 'bins'; + var bins = trace[binAttr]; + var calendar = trace[binDirection + 'calendar']; + + if(!bins) bins = trace[binAttr] = {}; + + var cleanBound = (axType === 'date') ? + function(v, dflt) { return (v || v === 0) ? Lib.cleanDate(v, BADNUM, calendar) : dflt; } : + function(v, dflt) { return isNumeric(v) ? Number(v) : dflt; }; + + bins.start = cleanBound(bins.start, autoBins.start); + bins.end = cleanBound(bins.end, autoBins.end); + + // logic for bin size is very similar to dtick (cartesian/tick_value_defaults) + // but without the extra string options for log axes + // ie the only strings we accept are M for months + var sizeDflt = autoBins.size; + var binSize = bins.size; + + if(isNumeric(binSize)) { + bins.size = (binSize > 0) ? Number(binSize) : sizeDflt; + } + else if(typeof binSize !== 'string') { + bins.size = sizeDflt; + } + else { + // date special case: "M" gives bins every (integer) n months + var prefix = binSize.charAt(0); + var sizeNum = binSize.substr(1); + + sizeNum = isNumeric(sizeNum) ? Number(sizeNum) : 0; + if((sizeNum <= 0) || !( + axType === 'date' && prefix === 'M' && sizeNum === Math.round(sizeNum) + )) { + bins.size = sizeDflt; + } + } +} + +},{"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axis_ids":747,"./attributes":976,"fast-isnumeric":214}],979:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleSampleDefaults = _dereq_('./sample_defaults'); +var handleStyleDefaults = _dereq_('../heatmap/style_defaults'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + handleSampleDefaults(traceIn, traceOut, coerce, layout); + if(traceOut.visible === false) return; + + handleStyleDefaults(traceIn, traceOut, coerce, layout); + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'} + ); +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"../heatmap/style_defaults":959,"./attributes":976,"./sample_defaults":982}],980:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var heatmapHover = _dereq_('../heatmap/hover'); +var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText; + +module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) { + var pts = heatmapHover(pointData, xval, yval, hovermode, hoverLayer, contour); + + if(!pts) return; + + pointData = pts[0]; + var indices = pointData.index; + var ny = indices[0]; + var nx = indices[1]; + var cd0 = pointData.cd[0]; + var xRange = cd0.xRanges[nx]; + var yRange = cd0.yRanges[ny]; + + pointData.xLabel = hoverLabelText(pointData.xa, xRange[0], xRange[1]); + pointData.yLabel = hoverLabelText(pointData.ya, yRange[0], yRange[1]); + + return pts; +}; + +},{"../../plots/cartesian/axes":744,"../heatmap/hover":952}],981:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Histogram2D = {}; + +Histogram2D.attributes = _dereq_('./attributes'); +Histogram2D.supplyDefaults = _dereq_('./defaults'); +Histogram2D.crossTraceDefaults = _dereq_('./cross_trace_defaults'); +Histogram2D.calc = _dereq_('../heatmap/calc'); +Histogram2D.plot = _dereq_('../heatmap/plot'); +Histogram2D.layerName = 'heatmaplayer'; +Histogram2D.colorbar = _dereq_('../heatmap/colorbar'); +Histogram2D.style = _dereq_('../heatmap/style'); +Histogram2D.hoverPoints = _dereq_('./hover'); +Histogram2D.eventData = _dereq_('../histogram/event_data'); + +Histogram2D.moduleType = 'trace'; +Histogram2D.name = 'histogram2d'; +Histogram2D.basePlotModule = _dereq_('../../plots/cartesian'); +Histogram2D.categories = ['cartesian', 'svg', '2dMap', 'histogram']; +Histogram2D.meta = { + + +}; + +module.exports = Histogram2D; + +},{"../../plots/cartesian":756,"../heatmap/calc":946,"../heatmap/colorbar":948,"../heatmap/plot":957,"../heatmap/style":958,"../histogram/event_data":972,"./attributes":976,"./cross_trace_defaults":978,"./defaults":979,"./hover":980}],982:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); + +module.exports = function handleSampleDefaults(traceIn, traceOut, coerce, layout) { + var x = coerce('x'); + var y = coerce('y'); + + // we could try to accept x0 and dx, etc... + // but that's a pretty weird use case. + // for now require both x and y explicitly specified. + if(!(x && x.length && y && y.length)) { + traceOut.visible = false; + return; + } + + traceOut._length = Math.min(x.length, y.length); + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); + + // if marker.color is an array, we can use it in aggregation instead of z + var hasAggregationData = coerce('z') || coerce('marker.color'); + + if(hasAggregationData) coerce('histfunc'); + coerce('histnorm'); + + // Note: bin defaults are now handled in Histogram2D.crossTraceDefaults + // autobin(x|y) are only included here to appease Plotly.validate + coerce('autobinx'); + coerce('autobiny'); +}; + +},{"../../registry":827}],983:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var histogram2dAttrs = _dereq_('../histogram2d/attributes'); +var contourAttrs = _dereq_('../contour/attributes'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = extendFlat({ + x: histogram2dAttrs.x, + y: histogram2dAttrs.y, + z: histogram2dAttrs.z, + marker: histogram2dAttrs.marker, + + histnorm: histogram2dAttrs.histnorm, + histfunc: histogram2dAttrs.histfunc, + nbinsx: histogram2dAttrs.nbinsx, + xbins: histogram2dAttrs.xbins, + nbinsy: histogram2dAttrs.nbinsy, + ybins: histogram2dAttrs.ybins, + autobinx: histogram2dAttrs.autobinx, + autobiny: histogram2dAttrs.autobiny, + + autocontour: contourAttrs.autocontour, + ncontours: contourAttrs.ncontours, + contours: contourAttrs.contours, + line: contourAttrs.line, + zhoverformat: histogram2dAttrs.zhoverformat +}, + colorscaleAttrs('', { + cLetter: 'z', + editTypeOverride: 'calc' + }), + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../contour/attributes":916,"../histogram2d/attributes":976}],984:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var handleSampleDefaults = _dereq_('../histogram2d/sample_defaults'); +var handleContoursDefaults = _dereq_('../contour/contours_defaults'); +var handleStyleDefaults = _dereq_('../contour/style_defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + function coerce2(attr) { + return Lib.coerce2(traceIn, traceOut, attributes, attr); + } + + handleSampleDefaults(traceIn, traceOut, coerce, layout); + if(traceOut.visible === false) return; + + handleContoursDefaults(traceIn, traceOut, coerce, coerce2); + handleStyleDefaults(traceIn, traceOut, coerce, layout); +}; + +},{"../../lib":696,"../contour/contours_defaults":923,"../contour/style_defaults":937,"../histogram2d/sample_defaults":982,"./attributes":983}],985:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Histogram2dContour = {}; + +Histogram2dContour.attributes = _dereq_('./attributes'); +Histogram2dContour.supplyDefaults = _dereq_('./defaults'); +Histogram2dContour.crossTraceDefaults = _dereq_('../histogram2d/cross_trace_defaults'); +Histogram2dContour.calc = _dereq_('../contour/calc'); +Histogram2dContour.plot = _dereq_('../contour/plot').plot; +Histogram2dContour.layerName = 'contourlayer'; +Histogram2dContour.style = _dereq_('../contour/style'); +Histogram2dContour.colorbar = _dereq_('../contour/colorbar'); +Histogram2dContour.hoverPoints = _dereq_('../contour/hover'); + +Histogram2dContour.moduleType = 'trace'; +Histogram2dContour.name = 'histogram2dcontour'; +Histogram2dContour.basePlotModule = _dereq_('../../plots/cartesian'); +Histogram2dContour.categories = ['cartesian', 'svg', '2dMap', 'contour', 'histogram', 'showLegend']; +Histogram2dContour.meta = { + + +}; + +module.exports = Histogram2dContour; + +},{"../../plots/cartesian":756,"../contour/calc":917,"../contour/colorbar":919,"../contour/hover":929,"../contour/plot":934,"../contour/style":936,"../histogram2d/cross_trace_defaults":978,"./attributes":983,"./defaults":984}],986:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var surfaceAtts = _dereq_('../surface/attributes'); +var baseAttrs = _dereq_('../../plots/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = extendFlat({ + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + y: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + z: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + + i: { + valType: 'data_array', + editType: 'calc', + + }, + j: { + valType: 'data_array', + editType: 'calc', + + + }, + k: { + valType: 'data_array', + editType: 'calc', + + + }, + + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'calc', + + }, + + delaunayaxis: { + valType: 'enumerated', + + values: [ 'x', 'y', 'z' ], + dflt: 'z', + editType: 'calc', + + }, + + alphahull: { + valType: 'number', + + dflt: -1, + editType: 'calc', + + }, + + intensity: { + valType: 'data_array', + editType: 'calc', + + }, + + // Color field + color: { + valType: 'color', + + editType: 'calc', + + }, + vertexcolor: { + valType: 'data_array', + + editType: 'calc', + + }, + facecolor: { + valType: 'data_array', + + editType: 'calc', + + }, + transforms: undefined +}, + +colorscaleAttrs('', { + colorAttr: '`intensity`', + showScaleDflt: true, + editTypeOverride: 'calc' +}), { + + colorbar: colorbarAttrs, + + opacity: surfaceAtts.opacity, + + // Flat shaded mode + flatshading: { + valType: 'boolean', + + dflt: false, + editType: 'calc', + + }, + + contour: { + show: extendFlat({}, surfaceAtts.contours.x.show, { + + }), + color: surfaceAtts.contours.x.color, + width: surfaceAtts.contours.x.width, + editType: 'calc' + }, + + lightposition: { + x: extendFlat({}, surfaceAtts.lightposition.x, {dflt: 1e5}), + y: extendFlat({}, surfaceAtts.lightposition.y, {dflt: 1e5}), + z: extendFlat({}, surfaceAtts.lightposition.z, {dflt: 0}), + editType: 'calc' + }, + lighting: extendFlat({ + vertexnormalsepsilon: { + valType: 'number', + + min: 0.00, + max: 1, + dflt: 1e-12, // otherwise finely tessellated things eg. the brain will have no specular light reflection + editType: 'calc', + + }, + facenormalsepsilon: { + valType: 'number', + + min: 0.00, + max: 1, + dflt: 1e-6, // even the brain model doesn't appear to need finer than this + editType: 'calc', + + }, + editType: 'calc' + }, surfaceAtts.lighting), + + hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {editType: 'calc'}) +}); + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../surface/attributes":1130}],987:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); + +module.exports = function calc(gd, trace) { + if(trace.intensity) { + colorscaleCalc(trace, trace.intensity, '', 'c'); + } +}; + +},{"../../components/colorscale/calc":578}],988:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createMesh = _dereq_('gl-mesh3d'); +var triangulate = _dereq_('delaunay-triangulate'); +var alphaShape = _dereq_('alpha-shape'); +var convexHull = _dereq_('convex-hull'); + +var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; +var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); +var zip3 = _dereq_('../../plots/gl3d/zip3'); + +function Mesh3DTrace(scene, mesh, uid) { + this.scene = scene; + this.uid = uid; + this.mesh = mesh; + this.name = ''; + this.color = '#fff'; + this.data = null; + this.showContour = false; +} + +var proto = Mesh3DTrace.prototype; + +proto.handlePick = function(selection) { + if(selection.object === this.mesh) { + var selectIndex = selection.index = selection.data.index; + + selection.traceCoordinate = [ + this.data.x[selectIndex], + this.data.y[selectIndex], + this.data.z[selectIndex] + ]; + + var text = this.data.text; + if(Array.isArray(text) && text[selectIndex] !== undefined) { + selection.textLabel = text[selectIndex]; + } else if(text) { + selection.textLabel = text; + } + + return true; + } +}; + +function parseColorArray(colors) { + return colors.map(str2RgbaArray); +} + +proto.update = function(data) { + var scene = this.scene, + layout = scene.fullSceneLayout; + + this.data = data; + + // Unpack position data + function toDataCoords(axis, coord, scale, calendar) { + return coord.map(function(x) { + return axis.d2l(x, 0, calendar) * scale; + }); + } + + var positions = zip3( + toDataCoords(layout.xaxis, data.x, scene.dataScale[0], data.xcalendar), + toDataCoords(layout.yaxis, data.y, scene.dataScale[1], data.ycalendar), + toDataCoords(layout.zaxis, data.z, scene.dataScale[2], data.zcalendar)); + + var cells; + if(data.i && data.j && data.k) { + cells = zip3(data.i, data.j, data.k); + } + else if(data.alphahull === 0) { + cells = convexHull(positions); + } + else if(data.alphahull > 0) { + cells = alphaShape(data.alphahull, positions); + } + else { + var d = ['x', 'y', 'z'].indexOf(data.delaunayaxis); + cells = triangulate(positions.map(function(c) { + return [c[(d + 1) % 3], c[(d + 2) % 3]]; + })); + } + + var config = { + positions: positions, + cells: cells, + lightPosition: [data.lightposition.x, data.lightposition.y, data.lightposition.z], + ambient: data.lighting.ambient, + diffuse: data.lighting.diffuse, + specular: data.lighting.specular, + roughness: data.lighting.roughness, + fresnel: data.lighting.fresnel, + vertexNormalsEpsilon: data.lighting.vertexnormalsepsilon, + faceNormalsEpsilon: data.lighting.facenormalsepsilon, + opacity: data.opacity, + contourEnable: data.contour.show, + contourColor: str2RgbaArray(data.contour.color).slice(0, 3), + contourWidth: data.contour.width, + useFacetNormals: data.flatshading + }; + + if(data.intensity) { + this.color = '#fff'; + config.vertexIntensity = data.intensity; + config.vertexIntensityBounds = [data.cmin, data.cmax]; + config.colormap = parseColorScale(data.colorscale); + } + else if(data.vertexcolor) { + this.color = data.vertexcolor[0]; + config.vertexColors = parseColorArray(data.vertexcolor); + } + else if(data.facecolor) { + this.color = data.facecolor[0]; + config.cellColors = parseColorArray(data.facecolor); + } + else { + this.color = data.color; + config.meshColor = str2RgbaArray(data.color); + } + + // Update mesh + this.mesh.update(config); +}; + +proto.dispose = function() { + this.scene.glplot.remove(this.mesh); + this.mesh.dispose(); +}; + +function createMesh3DTrace(scene, data) { + var gl = scene.glplot.gl; + var mesh = createMesh({gl: gl}); + var result = new Mesh3DTrace(scene, mesh, data.uid); + mesh._trace = result; + result.update(data); + scene.glplot.add(mesh); + return result; +} + +module.exports = createMesh3DTrace; + +},{"../../lib/gl_format_color":692,"../../lib/str2rgbarray":719,"../../plots/gl3d/zip3":798,"alpha-shape":52,"convex-hull":118,"delaunay-triangulate":150,"gl-mesh3d":268}],989:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + // read in face/vertex properties + function readComponents(array) { + var ret = array.map(function(attr) { + var result = coerce(attr); + + if(result && Lib.isArrayOrTypedArray(result)) return result; + return null; + }); + + return ret.every(function(x) { + return x && x.length === ret[0].length; + }) && ret; + } + + var coords = readComponents(['x', 'y', 'z']); + var indices = readComponents(['i', 'j', 'k']); + + if(!coords) { + traceOut.visible = false; + return; + } + + if(indices) { + // otherwise, convert all face indices to ints + indices.forEach(function(index) { + for(var i = 0; i < index.length; ++i) index[i] |= 0; + }); + } + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); + + // Coerce remaining properties + [ + 'lighting.ambient', + 'lighting.diffuse', + 'lighting.specular', + 'lighting.roughness', + 'lighting.fresnel', + 'lighting.vertexnormalsepsilon', + 'lighting.facenormalsepsilon', + 'lightposition.x', + 'lightposition.y', + 'lightposition.z', + 'contour.show', + 'contour.color', + 'contour.width', + 'colorscale', + 'reversescale', + 'flatshading', + 'alphahull', + 'delaunayaxis', + 'opacity' + ].forEach(function(x) { coerce(x); }); + + if('intensity' in traceIn) { + coerce('intensity'); + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); + } else { + traceOut.showscale = false; + + if('facecolor' in traceIn) coerce('facecolor'); + else if('vertexcolor' in traceIn) coerce('vertexcolor'); + else coerce('color', defaultColor); + } + + coerce('text'); + + // disable 1D transforms + // x/y/z should match lengths, and i/j/k should match as well, but + // the two sets have different lengths so transforms wouldn't work. + traceOut._length = null; +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"../../registry":827,"./attributes":986}],990:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Mesh3D = {}; + +Mesh3D.attributes = _dereq_('./attributes'); +Mesh3D.supplyDefaults = _dereq_('./defaults'); +Mesh3D.calc = _dereq_('./calc'); +Mesh3D.colorbar = { + min: 'cmin', + max: 'cmax' +}; +Mesh3D.plot = _dereq_('./convert'); + +Mesh3D.moduleType = 'trace'; +Mesh3D.name = 'mesh3d', +Mesh3D.basePlotModule = _dereq_('../../plots/gl3d'); +Mesh3D.categories = ['gl3d']; +Mesh3D.meta = { + +}; + +module.exports = Mesh3D; + +},{"../../plots/gl3d":787,"./attributes":986,"./calc":987,"./convert":988,"./defaults":989}],991:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var extendFlat = _dereq_('../../lib').extendFlat; +var scatterAttrs = _dereq_('../scatter/attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; +var fxAttrs = _dereq_('../../components/fx/attributes'); + +var INCREASING_COLOR = '#3D9970'; +var DECREASING_COLOR = '#FF4136'; + +var lineAttrs = scatterAttrs.line; + +function directionAttrs(lineColorDefault) { + return { + line: { + color: extendFlat({}, lineAttrs.color, {dflt: lineColorDefault}), + width: lineAttrs.width, + dash: dash, + editType: 'style' + }, + editType: 'style' + }; +} + +module.exports = { + + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + + open: { + valType: 'data_array', + editType: 'calc', + + }, + + high: { + valType: 'data_array', + editType: 'calc', + + }, + + low: { + valType: 'data_array', + editType: 'calc', + + }, + + close: { + valType: 'data_array', + editType: 'calc', + + }, + + line: { + width: extendFlat({}, lineAttrs.width, { + + }), + dash: extendFlat({}, dash, { + + }), + editType: 'style' + }, + + increasing: directionAttrs(INCREASING_COLOR), + + decreasing: directionAttrs(DECREASING_COLOR), + + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'calc', + + }, + + tickwidth: { + valType: 'number', + min: 0, + max: 0.5, + dflt: 0.3, + + editType: 'calc', + + }, + + hoverlabel: extendFlat({}, fxAttrs.hoverlabel, { + split: { + valType: 'boolean', + + dflt: false, + editType: 'style', + + } + }), +}; + +},{"../../components/drawing/attributes":594,"../../components/fx/attributes":604,"../../lib":696,"../scatter/attributes":1043}],992:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var _ = Lib._; +var Axes = _dereq_('../../plots/cartesian/axes'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +function calc(gd, trace) { + var xa = Axes.getFromId(gd, trace.xaxis); + var ya = Axes.getFromId(gd, trace.yaxis); + + var tickLen = convertTickWidth(gd, xa, trace); + var minDiff = trace._minDiff; + trace._minDiff = null; + var x = trace._xcalc; + trace._xcalc = null; + + var cd = calcCommon(gd, trace, x, ya, ptFunc); + + trace._extremes[xa._id] = Axes.findExtremes(xa, x, {vpad: minDiff / 2}); + if(cd.length) { + Lib.extendFlat(cd[0].t, { + wHover: minDiff / 2, + tickLen: tickLen + }); + return cd; + } else { + return [{t: {empty: true}}]; + } +} + +function ptFunc(o, h, l, c) { + return { + o: o, + h: h, + l: l, + c: c + }; +} + + +// shared between OHLC and candlestick +// ptFunc makes a calcdata point specific to each trace type, from oi, hi, li, ci +function calcCommon(gd, trace, x, ya, ptFunc) { + var o = ya.makeCalcdata(trace, 'open'); + var h = ya.makeCalcdata(trace, 'high'); + var l = ya.makeCalcdata(trace, 'low'); + var c = ya.makeCalcdata(trace, 'close'); + + var hasTextArray = Array.isArray(trace.text); + + // we're optimists - before we have any changing data, assume increasing + var increasing = true; + var cPrev = null; + + var cd = []; + for(var i = 0; i < x.length; i++) { + var xi = x[i]; + var oi = o[i]; + var hi = h[i]; + var li = l[i]; + var ci = c[i]; + + if(xi !== BADNUM && oi !== BADNUM && hi !== BADNUM && li !== BADNUM && ci !== BADNUM) { + if(ci === oi) { + // if open == close, look for a change from the previous close + if(cPrev !== null && ci !== cPrev) increasing = ci > cPrev; + // else (c === cPrev or cPrev is null) no change + } + else increasing = ci > oi; + + cPrev = ci; + + var pt = ptFunc(oi, hi, li, ci); + + pt.pos = xi; + pt.yc = (oi + ci) / 2; + pt.i = i; + pt.dir = increasing ? 'increasing' : 'decreasing'; + + if(hasTextArray) pt.tx = trace.text[i]; + + cd.push(pt); + } + } + + trace._extremes[ya._id] = Axes.findExtremes(ya, l.concat(h), {padded: true}); + + if(cd.length) { + cd[0].t = { + labels: { + open: _(gd, 'open:') + ' ', + high: _(gd, 'high:') + ' ', + low: _(gd, 'low:') + ' ', + close: _(gd, 'close:') + ' ' + } + }; + } + + return cd; +} + +/* + * find min x-coordinates difference of all traces + * attached to this x-axis and stash the result in _minDiff + * in all traces; when a trace uses this in its + * calc step it deletes _minDiff, so that next calc this is + * done again in case the data changed. + * also since we need it here, stash _xcalc on the trace + */ +function convertTickWidth(gd, xa, trace) { + var minDiff = trace._minDiff; + + if(!minDiff) { + var fullData = gd._fullData, + ohlcTracesOnThisXaxis = []; + + minDiff = Infinity; + + var i; + + for(i = 0; i < fullData.length; i++) { + var tracei = fullData[i]; + + if(tracei.type === 'ohlc' && + tracei.visible === true && + tracei.xaxis === xa._id + ) { + ohlcTracesOnThisXaxis.push(tracei); + + var xcalc = xa.makeCalcdata(tracei, 'x'); + tracei._xcalc = xcalc; + + var _minDiff = Lib.distinctVals(xcalc).minDiff; + if(_minDiff && isFinite(_minDiff)) { + minDiff = Math.min(minDiff, _minDiff); + } + } + } + + // if minDiff is still Infinity here, set it to 1 + if(minDiff === Infinity) minDiff = 1; + + for(i = 0; i < ohlcTracesOnThisXaxis.length; i++) { + ohlcTracesOnThisXaxis[i]._minDiff = minDiff; + } + } + + return minDiff * trace.tickwidth; +} + +module.exports = { + calc: calc, + calcCommon: calcCommon +}; + +},{"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axes":744}],993:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleOHLC = _dereq_('./ohlc_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleOHLC(traceIn, traceOut, coerce, layout); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('line.width'); + coerce('line.dash'); + + handleDirection(traceIn, traceOut, coerce, 'increasing'); + handleDirection(traceIn, traceOut, coerce, 'decreasing'); + + coerce('text'); + coerce('tickwidth'); + + layout._requestRangeslider[traceOut.xaxis] = true; +}; + +function handleDirection(traceIn, traceOut, coerce, direction) { + coerce(direction + '.line.color'); + coerce(direction + '.line.width', traceOut.line.width); + coerce(direction + '.line.dash', traceOut.line.dash); +} + +},{"../../lib":696,"./attributes":991,"./ohlc_defaults":996}],994:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); +var Fx = _dereq_('../../components/fx'); +var Color = _dereq_('../../components/color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); + +var DIRSYMBOL = { + increasing: '▲', + decreasing: '▼' +}; + +function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var trace = cd[0].trace; + + if(trace.hoverlabel.split) { + return hoverSplit(pointData, xval, yval, hovermode); + } + + return hoverOnPoints(pointData, xval, yval, hovermode); +} + +function getClosestPoint(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var xa = pointData.xa; + var trace = cd[0].trace; + var t = cd[0].t; + + var type = trace.type; + var minAttr = type === 'ohlc' ? 'l' : 'min'; + var maxAttr = type === 'ohlc' ? 'h' : 'max'; + + var hoverPseudoDistance, spikePseudoDistance; + + // potentially shift xval for grouped candlesticks + var centerShift = t.bPos || 0; + var shiftPos = function(di) { return di.pos + centerShift - xval; }; + + // ohlc and candlestick call displayHalfWidth different things... + var displayHalfWidth = t.bdPos || t.tickLen; + var hoverHalfWidth = t.wHover; + + // if two figures are overlaying, let the narrowest one win + var pseudoDistance = Math.min(1, displayHalfWidth / Math.abs(xa.r2c(xa.range[1]) - xa.r2c(xa.range[0]))); + hoverPseudoDistance = pointData.maxHoverDistance - pseudoDistance; + spikePseudoDistance = pointData.maxSpikeDistance - pseudoDistance; + + function dx(di) { + var pos = shiftPos(di); + return Fx.inbox(pos - hoverHalfWidth, pos + hoverHalfWidth, hoverPseudoDistance); + } + + function dy(di) { + return Fx.inbox(di[minAttr] - yval, di[maxAttr] - yval, hoverPseudoDistance); + } + + function dxy(di) { return (dx(di) + dy(di)) / 2; } + + var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); + Fx.getClosest(cd, distfn, pointData); + + if(pointData.index === false) return null; + + var di = cd[pointData.index]; + var dir = di.dir; + var container = trace[dir]; + var lc = container.line.color; + + if(Color.opacity(lc) && container.line.width) pointData.color = lc; + else pointData.color = container.fillcolor; + + pointData.x0 = xa.c2p(di.pos + centerShift - displayHalfWidth, true); + pointData.x1 = xa.c2p(di.pos + centerShift + displayHalfWidth, true); + + pointData.xLabelVal = di.pos; + + pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance; + pointData.xSpike = xa.c2p(di.pos, true); + + return pointData; +} + +function hoverSplit(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var ya = pointData.ya; + var trace = cd[0].trace; + var t = cd[0].t; + var closeBoxData = []; + + var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); + // skip the rest (for this trace) if we didn't find a close point + if(!closestPoint) return []; + + var cdIndex = closestPoint.index; + var di = cd[cdIndex]; + var hoverinfo = di.hi || trace.hoverinfo; + var hoverParts = hoverinfo.split('+'); + var isAll = hoverinfo === 'all'; + var hasY = isAll || hoverParts.indexOf('y') !== -1; + + // similar to hoverOnPoints, we return nothing + // if all or y is not present. + if(!hasY) return []; + + var attrs = ['high', 'open', 'close', 'low']; + + // several attributes can have the same y-coordinate. We will + // bunch them together in a single text block. For this, we keep + // a dictionary mapping y-coord -> point data. + var usedVals = {}; + + for(var i = 0; i < attrs.length; i++) { + var attr = attrs[i]; + + var val = trace[attr][closestPoint.index]; + var valPx = ya.c2p(val, true); + var pointData2; + if(val in usedVals) { + pointData2 = usedVals[val]; + pointData2.yLabel += '
' + t.labels[attr] + Axes.hoverLabelText(ya, val); + } + else { + // copy out to a new object for each new y-value to label + pointData2 = Lib.extendFlat({}, closestPoint); + + pointData2.y0 = pointData2.y1 = valPx; + pointData2.yLabelVal = val; + pointData2.yLabel = t.labels[attr] + Axes.hoverLabelText(ya, val); + + pointData2.name = ''; + + closeBoxData.push(pointData2); + usedVals[val] = pointData2; + } + } + + return closeBoxData; +} + +function hoverOnPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var ya = pointData.ya; + var trace = cd[0].trace; + var t = cd[0].t; + + var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); + // skip the rest (for this trace) if we didn't find a close point + if(!closestPoint) return []; + + // we don't make a calcdata point if we're missing any piece (x/o/h/l/c) + // so we need to fix the index here to point to the data arrays + var cdIndex = closestPoint.index; + var di = cd[cdIndex]; + var i = closestPoint.index = di.i; + var dir = di.dir; + + function getLabelLine(attr) { + return t.labels[attr] + Axes.hoverLabelText(ya, trace[attr][i]); + } + + var hoverinfo = di.hi || trace.hoverinfo; + var hoverParts = hoverinfo.split('+'); + var isAll = hoverinfo === 'all'; + var hasY = isAll || hoverParts.indexOf('y') !== -1; + var hasText = isAll || hoverParts.indexOf('text') !== -1; + + var textParts = hasY ? [ + getLabelLine('open'), + getLabelLine('high'), + getLabelLine('low'), + getLabelLine('close') + ' ' + DIRSYMBOL[dir] + ] : []; + if(hasText) fillHoverText(di, trace, textParts); + + // don't make .yLabelVal or .text, since we're managing hoverinfo + // put it all in .extraText + closestPoint.extraText = textParts.join('
'); + + // this puts the label *and the spike* at the midpoint of the box, ie + // halfway between open and close, not between high and low. + closestPoint.y0 = closestPoint.y1 = ya.c2p(di.yc, true); + + return [closestPoint]; +} + +module.exports = { + hoverPoints: hoverPoints, + hoverSplit: hoverSplit, + hoverOnPoints: hoverOnPoints +}; + +},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051}],995:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'ohlc', + basePlotModule: _dereq_('../../plots/cartesian'), + categories: ['cartesian', 'svg', 'showLegend'], + meta: { + + }, + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + calc: _dereq_('./calc').calc, + plot: _dereq_('./plot'), + style: _dereq_('./style'), + hoverPoints: _dereq_('./hover').hoverPoints, + selectPoints: _dereq_('./select') +}; + +},{"../../plots/cartesian":756,"./attributes":991,"./calc":992,"./defaults":993,"./hover":994,"./plot":997,"./select":998,"./style":999}],996:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); + + +module.exports = function handleOHLC(traceIn, traceOut, coerce, layout) { + var x = coerce('x'); + var open = coerce('open'); + var high = coerce('high'); + var low = coerce('low'); + var close = coerce('close'); + + coerce('hoverlabel.split'); + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x'], layout); + + if(!(open && high && low && close)) return; + + var len = Math.min(open.length, high.length, low.length, close.length); + + if(x) len = Math.min(len, x.length); + + traceOut._length = len; + + return len; +}; + +},{"../../registry":827}],997:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); + +module.exports = function plot(gd, plotinfo, cdOHLC, ohlcLayer) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + Lib.makeTraceGroups(ohlcLayer, cdOHLC, 'trace ohlc').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var t = cd0.t; + var trace = cd0.trace; + if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; + + if(trace.visible !== true || t.empty) { + plotGroup.remove(); + return; + } + + var tickLen = t.tickLen; + + var paths = plotGroup.selectAll('path').data(Lib.identity); + + paths.enter().append('path'); + + paths.exit().remove(); + + paths.attr('d', function(d) { + var x = xa.c2p(d.pos, true); + var xo = xa.c2p(d.pos - tickLen, true); + var xc = xa.c2p(d.pos + tickLen, true); + + var yo = ya.c2p(d.o, true); + var yh = ya.c2p(d.h, true); + var yl = ya.c2p(d.l, true); + var yc = ya.c2p(d.c, true); + + return 'M' + xo + ',' + yo + 'H' + x + + 'M' + x + ',' + yh + 'V' + yl + + 'M' + xc + ',' + yc + 'H' + x; + }); + }); +}; + +},{"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],998:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var i; + // for (potentially grouped) candlesticks + var posOffset = cd[0].t.bPos || 0; + + if(selectionTester === false) { + // clear selection + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + var di = cd[i]; + + if(selectionTester.contains([xa.c2p(di.pos + posOffset), ya.c2p(di.yc)], null, di.i, searchInfo)) { + selection.push({ + pointNumber: di.i, + x: xa.c2d(di.pos), + y: ya.c2d(di.yc) + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + + return selection; +}; + +},{}],999:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../../components/drawing'); +var Color = _dereq_('../../components/color'); + +module.exports = function style(gd, cd) { + var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.ohlclayer').selectAll('g.trace'); + + s.style('opacity', function(d) { + return d[0].trace.opacity; + }); + + s.each(function(d) { + var trace = d[0].trace; + + d3.select(this).selectAll('path').each(function(di) { + var dirLine = trace[di.dir].line; + d3.select(this) + .style('fill', 'none') + .call(Color.stroke, dirLine.color) + .call(Drawing.dashLine, dirLine.dash, dirLine.width) + // TODO: custom selection style for OHLC + .style('opacity', trace.selectedpoints && !di.selected ? 0.3 : 1); + }); + }); +}; + +},{"../../components/color":570,"../../components/drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1000:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var plotAttrs = _dereq_('../../plots/attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var domainAttrs = _dereq_('../../plots/domain').attributes; +var scatterAttrs = _dereq_('../scatter/attributes'); +var scatterLineAttrs = scatterAttrs.line; +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var line = extendFlat({ + editType: 'calc' +}, colorAttributes('line', {editType: 'calc'}), + { + showscale: scatterLineAttrs.showscale, + colorbar: colorbarAttrs, + shape: { + valType: 'enumerated', + values: ['linear', 'hspline'], + dflt: 'linear', + + editType: 'plot', + + } + }); + +module.exports = { + domain: domainAttrs({name: 'parcats', trace: true, editType: 'calc'}), + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['count', 'probability'], + editType: 'plot', + arrayOk: false + // plotAttrs.hoverinfo description is appropriate + }), + hoveron: { + valType: 'enumerated', + values: ['category', 'color', 'dimension'], + dflt: 'category', + + editType: 'plot', + + }, + arrangement: { + valType: 'enumerated', + values: ['perpendicular', 'freeform', 'fixed'], + dflt: 'perpendicular', + + editType: 'plot', + + }, + bundlecolors: { + valType: 'boolean', + dflt: true, + + editType: 'plot', + + }, + sortpaths: { + valType: 'enumerated', + values: ['forward', 'backward'], + dflt: 'forward', + + editType: 'plot', + + }, + labelfont: fontAttrs({ + editType: 'calc', + + }), + + tickfont: fontAttrs({ + editType: 'calc', + + }), + + dimensions: { + _isLinkedToArray: 'dimension', + label: { + valType: 'string', + + editType: 'calc', + + }, + categoryorder: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + ], + dflt: 'trace', + + editType: 'calc', + + }, + categoryarray: { + valType: 'data_array', + + editType: 'calc', + + }, + ticktext: { + valType: 'data_array', + + editType: 'calc', + + }, + values: { + valType: 'data_array', + + dflt: [], + editType: 'calc', + + }, + displayindex: { + valType: 'integer', + + editType: 'calc', + + }, + editType: 'calc', + + visible: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + } + }, + + line: line, + counts: { + valType: 'number', + min: 0, + dflt: 1, + arrayOk: true, + + editType: 'calc', + + }, + + // Hide unsupported top-level properties from plot-schema + customdata: undefined, + hoverlabel: undefined, + ids: undefined, + legendgroup: undefined, + opacity: undefined, + selectedpoints: undefined, + showlegend: undefined +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../../plots/domain":770,"../../plots/font_attributes":771,"../scatter/attributes":1043}],1001:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; +var parcatsPlot = _dereq_('./plot'); + +var PARCATS = 'parcats'; +exports.name = PARCATS; + +exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { + + var cdModuleAndOthers = getModuleCalcData(gd.calcdata, PARCATS); + + if(cdModuleAndOthers.length) { + var calcData = cdModuleAndOthers[0]; + parcatsPlot(gd, calcData, transitionOpts, makeOnCompleteCallback); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadTable = (oldFullLayout._has && oldFullLayout._has('parcats')); + var hasTable = (newFullLayout._has && newFullLayout._has('parcats')); + + if(hadTable && !hasTable) { + oldFullLayout._paperdiv.selectAll('.parcats').remove(); + } +}; + +},{"../../plots/get_data":781,"./plot":1006}],1002:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// Requirements +// ============ +var wrap = _dereq_('../../lib/gup').wrap; +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); +var filterUnique = _dereq_('../../lib/filter_unique.js'); +var Drawing = _dereq_('../../components/drawing'); +var Lib = _dereq_('../../lib'); + +/** + * Create a wrapped ParcatsModel object from trace + * + * Note: trace defaults have already been applied + * @param {Object} gd + * @param {Object} trace + * @return {Array.} + */ +module.exports = function calc(gd, trace) { + var visibleDims = Lib.filterVisible(trace.dimensions); + + if(visibleDims.length === 0) return []; + + var uniqueInfoDims = visibleDims.map(function(dim) { + var categoryValues; + if(dim.categoryorder === 'trace') { + // Use order of first occurrence in trace + categoryValues = null; + } else if(dim.categoryorder === 'array') { + // Use categories specified in `categoryarray` first, + // then add extra to the end in trace order + categoryValues = dim.categoryarray; + } else { + // Get all categories up front so we can order them + // Should we check for numbers as sort numerically? + categoryValues = filterUnique(dim.values).sort(); + if(dim.categoryorder === 'category descending') { + categoryValues = categoryValues.reverse(); + } + } + return getUniqueInfo(dim.values, categoryValues); + }); + + var counts, + count, + totalCount; + if(Lib.isArrayOrTypedArray(trace.counts)) { + counts = trace.counts; + } else { + counts = [trace.counts]; + } + + validateDimensionDisplayInds(visibleDims); + + visibleDims.forEach(function(dim, dimInd) { + validateCategoryProperties(dim, uniqueInfoDims[dimInd]); + }); + + // Handle path colors + // ------------------ + var line = trace.line; + var markerColorscale; + + // Process colorscale + if(line) { + if(hasColorscale(trace, 'line')) { + colorscaleCalc(trace, trace.line.color, 'line', 'c'); + } + markerColorscale = Drawing.tryColorscale(line); + } else { + markerColorscale = Lib.identity; + } + + // Build color generation function + function getMarkerColorInfo(index) { + var value; + if(Lib.isArrayOrTypedArray(line.color)) { + value = line.color[index % line.color.length]; + } else { + value = line.color; + } + + return {color: markerColorscale(value), rawColor: value}; + } + + // Number of values and counts + // --------------------------- + var numValues = visibleDims[0].values.length; + + // Build path info + // --------------- + // Mapping from category inds to PathModel objects + var pathModels = {}; + + // Category inds array for each dimension + var categoryIndsDims = uniqueInfoDims.map(function(di) {return di.inds;}); + + // Initialize total count + totalCount = 0; + var valueInd; + var d; + + for(valueInd = 0; valueInd < numValues; valueInd++) { + + // Category inds for this input value across dimensions + var categoryIndsPath = []; + for(d = 0; d < categoryIndsDims.length; d++) { + categoryIndsPath.push(categoryIndsDims[d][valueInd]); + } + + // Count + count = counts[valueInd % counts.length]; + + // Update total count + totalCount += count; + + // Path color + var pathColorInfo = getMarkerColorInfo(valueInd); + + // path key + var pathKey = categoryIndsPath + '-' + pathColorInfo.rawColor; + + // Create / Update PathModel + if(pathModels[pathKey] === undefined) { + pathModels[pathKey] = createPathModel(categoryIndsPath, + pathColorInfo.color, + pathColorInfo.rawColor); + } + updatePathModel(pathModels[pathKey], valueInd, count); + } + + var dimensionModels = visibleDims.map(function(di, i) { + return createDimensionModel(i, di._index, di._displayindex, di.label, totalCount); + }); + + + for(valueInd = 0; valueInd < numValues; valueInd++) { + + count = counts[valueInd % counts.length]; + + for(d = 0; d < dimensionModels.length; d++) { + var containerInd = dimensionModels[d].containerInd; + var catInd = uniqueInfoDims[d].inds[valueInd]; + var cats = dimensionModels[d].categories; + + if(cats[catInd] === undefined) { + var catValue = trace.dimensions[containerInd]._categoryarray[catInd]; + var catLabel = trace.dimensions[containerInd]._ticktext[catInd]; + cats[catInd] = createCategoryModel(d, catInd, catValue, catLabel); + } + + updateCategoryModel(cats[catInd], valueInd, count); + } + } + + // Compute unique + return wrap(createParcatsModel(dimensionModels, pathModels, totalCount)); +}; + +// Models +// ====== + +// Parcats Model +// ------------- +/** + * @typedef {Object} ParcatsModel + * Object containing calculated information about a parcats trace + * + * @property {Array.} dimensions + * Array of dimension models + * @property {Object.} paths + * Dictionary from category inds string (e.g. "1,2,1,1") to path model + * @property {Number} maxCats + * The maximum number of categories of any dimension in the diagram + * @property {Number} count + * Total number of input values + * @property {Object} trace + */ + +/** + * Create and new ParcatsModel object + * @param {Array.} dimensions + * @param {Object.} paths + * @param {Number} count + * @return {ParcatsModel} + */ +function createParcatsModel(dimensions, paths, count) { + var maxCats = dimensions + .map(function(d) {return d.categories.length;}) + .reduce(function(v1, v2) {return Math.max(v1, v2);}); + return {dimensions: dimensions, paths: paths, trace: undefined, maxCats: maxCats, count: count}; +} + +// Dimension Model +// --------------- +/** + * @typedef {Object} DimensionModel + * Object containing calculated information about a single dimension + * + * @property {Number} dimensionInd + * The index of this dimension among the *visible* dimensions + * @property {Number} containerInd + * The index of this dimension in the original dimensions container, + * irrespective of dimension visibility + * @property {Number} displayInd + * The display index of this dimension (where 0 is the left most dimension) + * @property {String} dimensionLabel + * The label of this dimension + * @property {Number} count + * Total number of input values + * @property {Array.} categories + * @property {Number|null} dragX + * The x position of dimension that is currently being dragged. null if not being dragged + */ + +/** + * Create and new DimensionModel object with an empty categories array + * @param {Number} dimensionInd + * @param {Number} containerInd + * @param {Number} displayInd + * @param {String} dimensionLabel + * @param {Number} count + * Total number of input values + * @return {DimensionModel} + */ +function createDimensionModel(dimensionInd, containerInd, displayInd, dimensionLabel, count) { + return { + dimensionInd: dimensionInd, + containerInd: containerInd, + displayInd: displayInd, + dimensionLabel: dimensionLabel, + count: count, + categories: [], + dragX: null + }; +} + +// Category Model +// -------------- +/** + * @typedef {Object} CategoryModel + * Object containing calculated information about a single category. + * + * @property {Number} dimensionInd + * The index of this categories dimension + * @property {Number} categoryInd + * The index of this category + * @property {Number} displayInd + * The display index of this category (where 0 is the topmost category) + * @property {String} categoryLabel + * The name of this category + * @property categoryValue: Raw value of the category + * @property {Array} valueInds + * Array of indices (into the original value array) of all samples in this category + * @property {Number} count + * The number of elements from the original array in this path + * @property {Number|null} dragY + * The y position of category that is currently being dragged. null if not being dragged + */ + +/** + * Create and return a new CategoryModel object + * @param {Number} dimensionInd + * @param {Number} categoryInd + * The display index of this category (where 0 is the topmost category) + * @param {String} categoryValue + * @param {String} categoryLabel + * @return {CategoryModel} + */ +function createCategoryModel(dimensionInd, categoryInd, categoryValue, categoryLabel) { + return { + dimensionInd: dimensionInd, + categoryInd: categoryInd, + categoryValue: categoryValue, + displayInd: categoryInd, + categoryLabel: categoryLabel, + valueInds: [], + count: 0, + dragY: null + }; +} + +/** + * Update a CategoryModel object with a new value index + * Note: The calling parameter is modified in place. + * + * @param {CategoryModel} categoryModel + * @param {Number} valueInd + * @param {Number} count + */ +function updateCategoryModel(categoryModel, valueInd, count) { + categoryModel.valueInds.push(valueInd); + categoryModel.count += count; +} + + +// Path Model +// ---------- +/** + * @typedef {Object} PathModel + * Object containing calculated information about the samples in a path. + * + * @property {Array} categoryInds + * Array of category indices for each dimension (length `numDimensions`) + * @param {String} pathColor + * Color of this path. (Note: Any colorscaling has already taken place) + * @property {Array} valueInds + * Array of indices (into the original value array) of all samples in this path + * @property {Number} count + * The number of elements from the original array in this path + * @property {String} color + * The path's color (ass CSS color string) + * @property rawColor + * The raw color value specified by the user. May be a CSS color string or a Number + */ + +/** + * Create and return a new PathModel object + * @param {Array} categoryInds + * @param color + * @param rawColor + * @return {PathModel} + */ +function createPathModel(categoryInds, color, rawColor) { + return { + categoryInds: categoryInds, + color: color, + rawColor: rawColor, + valueInds: [], + count: 0 + }; +} + +/** + * Update a PathModel object with a new value index + * Note: The calling parameter is modified in place. + * + * @param {PathModel} pathModel + * @param {Number} valueInd + * @param {Number} count + */ +function updatePathModel(pathModel, valueInd, count) { + pathModel.valueInds.push(valueInd); + pathModel.count += count; +} + +// Unique calculations +// =================== +/** + * @typedef {Object} UniqueInfo + * Object containing information about the unique values of an input array + * + * @property {Array} uniqueValues + * The unique values in the input array + * @property {Array} uniqueCounts + * The number of times each entry in uniqueValues occurs in input array. + * This has the same length as `uniqueValues` + * @property {Array} inds + * Indices into uniqueValues that would reproduce original input array + */ + +/** + * Compute unique value information for an array + * + * IMPORTANT: Note that values are considered unique + * if their string representations are unique. + * + * @param {Array} values + * @param {Array|undefined} uniqueValues + * Array of expected unique values. The uniqueValues property of the resulting UniqueInfo object will begin with + * these entries. Entries are included even if there are zero occurrences in the values array. Entries found in + * the values array that are not present in uniqueValues will be included at the end of the array in the + * UniqueInfo object. + * @return {UniqueInfo} + */ +function getUniqueInfo(values, uniqueValues) { + + // Initialize uniqueValues if not specified + if(uniqueValues === undefined || uniqueValues === null) { + uniqueValues = []; + } else { + // Shallow copy so append below doesn't alter input array + uniqueValues = uniqueValues.map(function(e) {return e;}); + } + + // Initialize Variables + var uniqueValueCounts = {}, + uniqueValueInds = {}, + inds = []; + + // Initialize uniqueValueCounts and + uniqueValues.forEach(function(uniqueVal, valInd) { + uniqueValueCounts[uniqueVal] = 0; + uniqueValueInds[uniqueVal] = valInd; + }); + + // Compute the necessary unique info in a single pass + for(var i = 0; i < values.length; i++) { + var item = values[i]; + var itemInd; + + if(uniqueValueCounts[item] === undefined) { + // This item has a previously unseen value + uniqueValueCounts[item] = 1; + itemInd = uniqueValues.push(item) - 1; + uniqueValueInds[item] = itemInd; + } else { + // Increment count for this item + uniqueValueCounts[item]++; + itemInd = uniqueValueInds[item]; + } + inds.push(itemInd); + } + + // Build UniqueInfo + var uniqueCounts = uniqueValues.map(function(v) { return uniqueValueCounts[v]; }); + + return { + uniqueValues: uniqueValues, + uniqueCounts: uniqueCounts, + inds: inds + }; +} + + +/** + * Validate the requested display order for the dimensions. + * If the display order is a permutation of 0 through dimensions.length - 1, link to _displayindex + * Otherwise, replace the display order with the dimension order + * @param {Object} trace + */ +function validateDimensionDisplayInds(visibleDims) { + var displayInds = visibleDims.map(function(d) { return d.displayindex; }); + var i; + + if(isRangePermutation(displayInds)) { + for(i = 0; i < visibleDims.length; i++) { + visibleDims[i]._displayindex = visibleDims[i].displayindex; + } + } else { + for(i = 0; i < visibleDims.length; i++) { + visibleDims[i]._displayindex = i; + } + } +} + + +/** + * Update category properties based on the unique values found for this dimension + * @param {Object} dim + * @param {UniqueInfo} uniqueInfoDim + */ +function validateCategoryProperties(dim, uniqueInfoDim) { + + // Update categoryarray + dim._categoryarray = uniqueInfoDim.uniqueValues; + + // Handle ticktext + if(dim.ticktext === null || dim.ticktext === undefined) { + dim._ticktext = []; + } else { + // Shallow copy to avoid modifying input array + dim._ticktext = dim.ticktext.slice(); + } + + // Extend ticktext with elements from uniqueInfoDim.uniqueValues + for(var i = dim._ticktext.length; i < uniqueInfoDim.uniqueValues.length; i++) { + dim._ticktext.push(uniqueInfoDim.uniqueValues[i]); + } +} + +/** + * Determine whether an array contains a permutation of the integers from 0 to the array's length - 1 + * @param {Array} inds + * @return {boolean} + */ +function isRangePermutation(inds) { + var indsSpecified = new Array(inds.length); + + for(var i = 0; i < inds.length; i++) { + // Check for out of bounds + if(inds[i] < 0 || inds[i] >= inds.length) { + return false; + } + + // Check for collisions with already specified index + if(indsSpecified[inds[i]] !== undefined) { + return false; + } + + indsSpecified[inds[i]] = true; + } + + // Nothing out of bounds and no collisions. We have a permutation + return true; +} + +},{"../../components/colorscale/calc":578,"../../components/colorscale/has_colorscale":584,"../../components/drawing":595,"../../lib":696,"../../lib/filter_unique.js":686,"../../lib/gup":693}],1003:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var handleDomainDefaults = _dereq_('../../plots/domain').defaults; +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var mergeLength = _dereq_('../parcoords/merge_length'); + +function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { + + coerce('line.shape'); + var lineColor = coerce('line.color', layout.colorway[0]); + if(hasColorscale(traceIn, 'line') && Lib.isArrayOrTypedArray(lineColor)) { + if(lineColor.length) { + coerce('line.colorscale'); + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); + return lineColor.length; + } + else { + traceOut.line.color = defaultColor; + } + } + return Infinity; +} + +function dimensionDefaults(dimensionIn, dimensionOut) { + function coerce(attr, dflt) { + return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); + } + + var values = coerce('values'); + var visible = coerce('visible'); + if(!(values && values.length)) { + visible = dimensionOut.visible = false; + } + + if(visible) { + // Dimension level + coerce('label'); + coerce('displayindex', dimensionOut._index); + + // Category level + var arrayIn = dimensionIn.categoryarray; + var isValidArray = (Array.isArray(arrayIn) && arrayIn.length > 0); + + var orderDefault; + if(isValidArray) orderDefault = 'array'; + var order = coerce('categoryorder', orderDefault); + + // coerce 'categoryarray' only in array order case + if(order === 'array') { + coerce('categoryarray'); + coerce('ticktext'); + } else { + delete dimensionIn.categoryarray; + delete dimensionIn.ticktext; + } + + // cannot set 'categoryorder' to 'array' with an invalid 'categoryarray' + if(!isValidArray && order === 'array') { + dimensionOut.categoryorder = 'trace'; + } + } +} + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { + name: 'dimensions', + handleItemDefaults: dimensionDefaults + }); + + var len = handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + + handleDomainDefaults(traceOut, layout, coerce); + + if(!Array.isArray(dimensions) || !dimensions.length) { + traceOut.visible = false; + } + + mergeLength(traceOut, dimensions, 'values', len); + + coerce('hoveron'); + coerce('arrangement'); + coerce('bundlecolors'); + coerce('sortpaths'); + coerce('counts'); + + var labelfontDflt = { + family: layout.font.family, + size: Math.round(layout.font.size), + color: layout.font.color + }; + + Lib.coerceFont(coerce, 'labelfont', labelfontDflt); + + var categoryfontDefault = { + family: layout.font.family, + size: Math.round(layout.font.size / 1.2), + color: layout.font.color + }; + + Lib.coerceFont(coerce, 'tickfont', categoryfontDefault); +}; + +},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/domain":770,"../parcoords/merge_length":1015,"./attributes":1000}],1004:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Parcats = {}; + +Parcats.attributes = _dereq_('./attributes'); +Parcats.supplyDefaults = _dereq_('./defaults'); +Parcats.calc = _dereq_('./calc'); +Parcats.plot = _dereq_('./plot'); +Parcats.colorbar = { + container: 'line', + min: 'cmin', + max: 'cmax' +}; + +Parcats.moduleType = 'trace'; +Parcats.name = 'parcats'; +Parcats.basePlotModule = _dereq_('./base_plot'); +Parcats.categories = ['noOpacity']; +Parcats.meta = { + +}; + +module.exports = Parcats; + +},{"./attributes":1000,"./base_plot":1001,"./calc":1002,"./defaults":1003,"./plot":1006}],1005:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Plotly = _dereq_('../../plot_api/plot_api'); +var Fx = _dereq_('../../components/fx'); +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); +var tinycolor = _dereq_('tinycolor2'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); + +function performPlot(parcatsModels, graphDiv, layout, svg) { + + var viewModels = parcatsModels.map(createParcatsViewModel.bind(0, graphDiv, layout)); + + // Get (potentially empty) parcatslayer selection with bound data to single element array + var layerSelection = svg.selectAll('g.parcatslayer').data([null]); + + // Initialize single parcatslayer group if it doesn't exist + layerSelection.enter() + .append('g') + .attr('class', 'parcatslayer') + .style('pointer-events', 'all'); + + // Bind data to children of layerSelection and get reference to traceSelection + var traceSelection = layerSelection + .selectAll('g.trace.parcats') + .data(viewModels, key); + + // Initialize group for each trace/dimensions + var traceEnter = traceSelection.enter() + .append('g') + .attr('class', 'trace parcats'); + + // Update properties for each trace + traceSelection + .attr('transform', function(d) { + return 'translate(' + d.x + ', ' + d.y + ')'; + }); + + // Initialize paths group + traceEnter + .append('g') + .attr('class', 'paths'); + + // Update paths transform + var pathsSelection = traceSelection + .select('g.paths'); + + // Get paths selection + var pathSelection = pathsSelection + .selectAll('path.path') + .data(function(d) { + return d.paths; + }, key); + + // Update existing path colors + pathSelection + .attr('fill', function(d) { + return d.model.color; + }); + + // Create paths + var pathSelectionEnter = pathSelection + .enter() + .append('path') + .attr('class', 'path') + .attr('stroke-opacity', 0) + .attr('fill', function(d) { + return d.model.color; + }) + .attr('fill-opacity', 0); + + stylePathsNoHover(pathSelectionEnter); + + // Set path geometry + pathSelection + .attr('d', function(d) { + return d.svgD; + }); + + // sort paths + if(!pathSelectionEnter.empty()) { + // Only sort paths if there has been a change. + // Otherwise paths are already sorted or a hover operation may be in progress + pathSelection.sort(compareRawColor); + } + + // Remove any old paths + pathSelection.exit().remove(); + + // Path hover + pathSelection + .on('mouseover', mouseoverPath) + .on('mouseout', mouseoutPath) + .on('click', clickPath); + + // Initialize dimensions group + traceEnter.append('g').attr('class', 'dimensions'); + + // Update dimensions transform + var dimensionsSelection = traceSelection + .select('g.dimensions'); + + // Get dimension selection + var dimensionSelection = dimensionsSelection + .selectAll('g.dimension') + .data(function(d) { + return d.dimensions; + }, key); + + // Create dimension groups + dimensionSelection.enter() + .append('g') + .attr('class', 'dimension'); + + // Update dimension group transforms + dimensionSelection.attr('transform', function(d) { + return 'translate(' + d.x + ', 0)'; + }); + + // Remove any old dimensions + dimensionSelection.exit().remove(); + + // Get category selection + var categorySelection = dimensionSelection + .selectAll('g.category') + .data(function(d) { + return d.categories; + }, key); + + // Initialize category groups + var categoryGroupEnterSelection = categorySelection + .enter() + .append('g') + .attr('class', 'category'); + + // Update category transforms + categorySelection + .attr('transform', function(d) { + return 'translate(0, ' + d.y + ')'; + }); + + + // Initialize rectangle + categoryGroupEnterSelection + .append('rect') + .attr('class', 'catrect') + .attr('pointer-events', 'none'); + + + // Update rectangle + categorySelection.select('rect.catrect') + .attr('fill', 'none') + .attr('width', function(d) { + return d.width; + }) + .attr('height', function(d) { + return d.height; + }); + + styleCategoriesNoHover(categoryGroupEnterSelection); + + // Initialize color band rects + var bandSelection = categorySelection + .selectAll('rect.bandrect') + .data( + /** @param {CategoryViewModel} catViewModel*/ + function(catViewModel) { + return catViewModel.bands; + }, key); + + // Raise all update bands to the top so that fading enter/exit bands will be behind + bandSelection.each(function() {Lib.raiseToTop(this);}); + + // Update band color + bandSelection + .attr('fill', function(d) { + return d.color; + }); + + var bandsSelectionEnter = bandSelection.enter() + .append('rect') + .attr('class', 'bandrect') + .attr('stroke-opacity', 0) + .attr('fill', function(d) { + return d.color; + }) + .attr('fill-opacity', 0); + + bandSelection + .attr('fill', function(d) { + return d.color; + }) + .attr('width', function(d) { + return d.width; + }) + .attr('height', function(d) { + return d.height; + }) + .attr('y', function(d) { + return d.y; + }) + .attr('cursor', + /** @param {CategoryBandViewModel} bandModel*/ + function(bandModel) { + if(bandModel.parcatsViewModel.arrangement === 'fixed') { + return 'default'; + } else if(bandModel.parcatsViewModel.arrangement === 'perpendicular') { + return 'ns-resize'; + } else { + return 'move'; + } + }); + + styleBandsNoHover(bandsSelectionEnter); + + bandSelection.exit().remove(); + + // Initialize category label + categoryGroupEnterSelection + .append('text') + .attr('class', 'catlabel') + .attr('pointer-events', 'none'); + + var paperColor = graphDiv._fullLayout.paper_bgcolor; + + // Update category label + categorySelection.select('text.catlabel') + .attr('text-anchor', + function(d) { + if(catInRightDim(d)) { + // Place label to the right of category + return 'start'; + } else { + // Place label to the left of category + return 'end'; + } + }) + .attr('alignment-baseline', 'middle') + + .style('text-shadow', + paperColor + ' -1px 1px 2px, ' + + paperColor + ' 1px 1px 2px, ' + + paperColor + ' 1px -1px 2px, ' + + paperColor + ' -1px -1px 2px') + .style('fill', 'rgb(0, 0, 0)') + .attr('x', + function(d) { + if(catInRightDim(d)) { + // Place label to the right of category + return d.width + 5; + } else { + // Place label to the left of category + return -5; + } + }) + .attr('y', function(d) { + return d.height / 2; + }) + .text(function(d) { + return d.model.categoryLabel; + }) + .each( + /** @param {CategoryViewModel} catModel*/ + function(catModel) { + Drawing.font(d3.select(this), catModel.parcatsViewModel.categorylabelfont); + svgTextUtils.convertToTspans(d3.select(this), graphDiv); + }); + + // Initialize dimension label + categoryGroupEnterSelection + .append('text') + .attr('class', 'dimlabel'); + + // Update dimension label + categorySelection.select('text.dimlabel') + .attr('text-anchor', 'middle') + .attr('alignment-baseline', 'baseline') + .attr('cursor', + /** @param {CategoryViewModel} catModel*/ + function(catModel) { + if(catModel.parcatsViewModel.arrangement === 'fixed') { + return 'default'; + } else { + return 'ew-resize'; + } + }) + .attr('x', function(d) { + return d.width / 2; + }) + .attr('y', -5) + .text(function(d, i) { + if(i === 0) { + // Add dimension label above topmost category + return d.parcatsViewModel.model.dimensions[d.model.dimensionInd].dimensionLabel; + } else { + return null; + } + }) + .each( + /** @param {CategoryViewModel} catModel*/ + function(catModel) { + Drawing.font(d3.select(this), catModel.parcatsViewModel.labelfont); + }); + + // Category hover + // categorySelection.select('rect.catrect') + categorySelection.selectAll('rect.bandrect') + .on('mouseover', mouseoverCategoryBand) + .on('mouseout', mouseoutCategory); + + // Remove unused categories + categorySelection.exit().remove(); + + // Setup drag + dimensionSelection.call(d3.behavior.drag() + .origin(function(d) { + return {x: d.x, y: 0}; + }) + .on('dragstart', dragDimensionStart) + .on('drag', dragDimension) + .on('dragend', dragDimensionEnd)); + + + // Save off selections to view models + traceSelection.each(function(d) { + d.traceSelection = d3.select(this); + d.pathSelection = d3.select(this).selectAll('g.paths').selectAll('path.path'); + d.dimensionSelection = d3.select(this).selectAll('g.dimensions').selectAll('g.dimension'); + }); + + // Remove any orphan traces + traceSelection.exit().remove(); +} + +/** + * Create / update parcat traces + * + * @param {Object} graphDiv + * @param {Object} svg + * @param {Array.} parcatsModels + * @param {Layout} layout + */ +module.exports = function(graphDiv, svg, parcatsModels, layout) { + performPlot(parcatsModels, graphDiv, layout, svg); +}; + +/** + * Function the returns the key property of an object for use with as D3 join function + * @param d + */ +function key(d) { + return d.key; +} + + /** True if a category view model is in the right-most display dimension + * @param {CategoryViewModel} d */ +function catInRightDim(d) { + var numDims = d.parcatsViewModel.dimensions.length, + leftDimInd = d.parcatsViewModel.dimensions[numDims - 1].model.dimensionInd; + return d.model.dimensionInd === leftDimInd; +} + +/** + * @param {PathViewModel} a + * @param {PathViewModel} b + */ +function compareRawColor(a, b) { + if(a.model.rawColor > b.model.rawColor) { + return 1; + } else if(a.model.rawColor < b.model.rawColor) { + return -1; + } else { + return 0; + } +} + +/** + * Handle path mouseover + * @param {PathViewModel} d + */ +function mouseoverPath(d) { + + if(!d.parcatsViewModel.dragDimension) { + // We're not currently dragging + + if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + // hoverinfo is not skip, so we at least style the paths and emit interaction events + + // Raise path to top + Lib.raiseToTop(this); + + stylePathsHover(d3.select(this)); + + // Emit hover event + var points = buildPointsArrayForPath(d); + d.parcatsViewModel.graphDiv.emit('plotly_hover', {points: points, event: d3.event}); + + // Handle hover label + if(d.parcatsViewModel.hoverinfoItems.indexOf('none') === -1) { + // hoverinfo is a combination of 'count' and 'probability' + + // Mouse + var hoverX = d3.mouse(this)[0]; + + // Label + var gd = d.parcatsViewModel.graphDiv; + var fullLayout = gd._fullLayout; + var rootBBox = fullLayout._paperdiv.node().getBoundingClientRect(); + var graphDivBBox = d.parcatsViewModel.graphDiv.getBoundingClientRect(); + + // Find path center in path coordinates + var pathCenterX, + pathCenterY, + dimInd; + + for(dimInd = 0; dimInd < (d.leftXs.length - 1); dimInd++) { + if(d.leftXs[dimInd] + d.dimWidths[dimInd] - 2 <= hoverX && hoverX <= d.leftXs[dimInd + 1] + 2) { + var leftDim = d.parcatsViewModel.dimensions[dimInd]; + var rightDim = d.parcatsViewModel.dimensions[dimInd + 1]; + pathCenterX = (leftDim.x + leftDim.width + rightDim.x) / 2; + pathCenterY = (d.topYs[dimInd] + d.topYs[dimInd + 1] + d.height) / 2; + break; + } + } + + // Find path center in root coordinates + var hoverCenterX = d.parcatsViewModel.x + pathCenterX; + var hoverCenterY = d.parcatsViewModel.y + pathCenterY; + + var textColor = tinycolor.mostReadable(d.model.color, ['black', 'white']); + + // Build hover text + var hovertextParts = []; + if(d.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { + hovertextParts.push(['Count:', d.model.count].join(' ')); + } + if(d.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { + hovertextParts.push(['P:', (d.model.count / d.parcatsViewModel.model.count).toFixed(3)].join(' ')); + } + + var hovertext = hovertextParts.join('
'); + var mouseX = d3.mouse(gd)[0]; + + Fx.loneHover({ + x: hoverCenterX - rootBBox.left + graphDivBBox.left, + y: hoverCenterY - rootBBox.top + graphDivBBox.top, + text: hovertext, + color: d.model.color, + borderColor: 'black', + fontFamily: 'Monaco, "Courier New", monospace', + fontSize: 10, + fontColor: textColor, + idealAlign: mouseX < hoverCenterX ? 'right' : 'left' + }, { + container: fullLayout._hoverlayer.node(), + outerContainer: fullLayout._paper.node(), + gd: gd + }); + } + } + } +} + +/** + * Handle path mouseout + * @param {PathViewModel} d + */ +function mouseoutPath(d) { + if(!d.parcatsViewModel.dragDimension) { + // We're not currently dragging + stylePathsNoHover(d3.select(this)); + + // Remove and hover label + Fx.loneUnhover(d.parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); + + // Restore path order + d.parcatsViewModel.pathSelection.sort(compareRawColor); + + // Emit unhover event + if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + var points = buildPointsArrayForPath(d); + d.parcatsViewModel.graphDiv.emit('plotly_unhover', {points: points, event: d3.event}); + } + } +} + +/** + * Build array of point objects for a path + * + * For use in click/hover events + * @param {PathViewModel} d + */ +function buildPointsArrayForPath(d) { + var points = []; + var curveNumber = getTraceIndex(d.parcatsViewModel); + + for(var i = 0; i < d.model.valueInds.length; i++) { + var pointNumber = d.model.valueInds[i]; + points.push({ + curveNumber: curveNumber, + pointNumber: pointNumber + }); + } + return points; +} + +/** + * Handle path click + * @param {PathViewModel} d + */ +function clickPath(d) { + if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + // hoverinfo it's skip, so interaction events aren't disabled + var points = buildPointsArrayForPath(d); + d.parcatsViewModel.graphDiv.emit('plotly_click', {points: points, event: d3.event}); + } +} + +function stylePathsNoHover(pathSelection) { + pathSelection + .attr('fill', function(d) { + return d.model.color; + }) + .attr('fill-opacity', 0.6) + .attr('stroke', 'lightgray') + .attr('stroke-width', 0.2) + .attr('stroke-opacity', 1.0); +} + +function stylePathsHover(pathSelection) { + pathSelection + .attr('fill-opacity', 0.8) + .attr('stroke', function(d) { + return tinycolor.mostReadable(d.model.color, ['black', 'white']); + }) + .attr('stroke-width', 0.3); +} + +function styleCategoryHover(categorySelection) { + categorySelection + .select('rect.catrect') + .attr('stroke', 'black') + .attr('stroke-width', 2.5); +} + +function styleCategoriesNoHover(categorySelection) { + categorySelection + .select('rect.catrect') + .attr('stroke', 'black') + .attr('stroke-width', 1) + .attr('stroke-opacity', 1); +} + +function styleBandsHover(bandsSelection) { + bandsSelection + .attr('stroke', 'black') + .attr('stroke-width', 1.5); +} + +function styleBandsNoHover(bandsSelection) { + bandsSelection + .attr('stroke', 'black') + .attr('stroke-width', 0.2) + .attr('stroke-opacity', 1.0) + .attr('fill-opacity', 1.0); +} + +/** + * Return selection of all paths that pass through the specified category + * @param {CategoryBandViewModel} catBandViewModel + */ +function selectPathsThroughCategoryBandColor(catBandViewModel) { + + var allPaths = catBandViewModel.parcatsViewModel.pathSelection; + var dimInd = catBandViewModel.categoryViewModel.model.dimensionInd; + var catInd = catBandViewModel.categoryViewModel.model.categoryInd; + + return allPaths + .filter( + /** @param {PathViewModel} pathViewModel */ + function(pathViewModel) { + return pathViewModel.model.categoryInds[dimInd] === catInd && + pathViewModel.model.color === catBandViewModel.color; + }); +} + + +/** + * Perform hover styling for all paths that pass though the specified band element's category + * + * @param {HTMLElement} bandElement + * HTML element for band + * + */ +function styleForCategoryHovermode(bandElement) { + + // Get all bands in the current category + var bandSel = d3.select(bandElement.parentNode).selectAll('rect.bandrect'); + + // Raise and style paths + bandSel.each(function(bvm) { + var paths = selectPathsThroughCategoryBandColor(bvm); + stylePathsHover(paths); + paths.each(function() { + // Raise path to top + Lib.raiseToTop(this); + }); + }); + + // Style category + styleCategoryHover(d3.select(bandElement.parentNode)); +} + +/** + * Perform hover styling for all paths that pass though the category of the specified band element and share the + * same color + * + * @param {HTMLElement} bandElement + * HTML element for band + * + */ +function styleForColorHovermode(bandElement) { + var bandViewModel = d3.select(bandElement).datum(); + var catPaths = selectPathsThroughCategoryBandColor(bandViewModel); + stylePathsHover(catPaths); + catPaths.each(function() { + // Raise path to top + Lib.raiseToTop(this); + }); + + // Style category for drag + d3.select(bandElement.parentNode) + .selectAll('rect.bandrect') + .filter(function(b) {return b.color === bandViewModel.color;}) + .each(function() { + Lib.raiseToTop(this); + styleBandsHover(d3.select(this)); + }); +} + + +/** + * @param {HTMLElement} bandElement + * HTML element for band + * @param eventName + * Event name (plotly_hover or plotly_click) + * @param event + * Mouse Event + */ +function emitPointsEventCategoryHovermode(bandElement, eventName, event) { + // Get all bands in the current category + var bandViewModel = d3.select(bandElement).datum(); + var gd = bandViewModel.parcatsViewModel.graphDiv; + var bandSel = d3.select(bandElement.parentNode).selectAll('rect.bandrect'); + + var points = []; + bandSel.each(function(bvm) { + var paths = selectPathsThroughCategoryBandColor(bvm); + paths.each(function(pathViewModel) { + // Extend points array + Array.prototype.push.apply(points, buildPointsArrayForPath(pathViewModel)); + }); + }); + + gd.emit(eventName, {points: points, event: event}); +} + +/** + * @param {HTMLElement} bandElement + * HTML element for band + * @param eventName + * Event name (plotly_hover or plotly_click) + * @param event + * Mouse Event + */ +function emitPointsEventColorHovermode(bandElement, eventName, event) { + var bandViewModel = d3.select(bandElement).datum(); + var gd = bandViewModel.parcatsViewModel.graphDiv; + var paths = selectPathsThroughCategoryBandColor(bandViewModel); + + var points = []; + paths.each(function(pathViewModel) { + // Extend points array + Array.prototype.push.apply(points, buildPointsArrayForPath(pathViewModel)); + }); + + gd.emit(eventName, {points: points, event: event}); +} + +/** + * Create hover label for a band element's category (for use when hoveron === 'category') + * + * @param {ClientRect} rootBBox + * Client bounding box for root of figure + * @param {HTMLElement} bandElement + * HTML element for band + * + */ +function createHoverLabelForCategoryHovermode(rootBBox, bandElement) { + // Selections + var rectSelection = d3.select(bandElement.parentNode).select('rect.catrect'); + var rectBoundingBox = rectSelection.node().getBoundingClientRect(); + + // Models + /** @type {CategoryViewModel} */ + var catViewModel = rectSelection.datum(); + var parcatsViewModel = catViewModel.parcatsViewModel; + var dimensionModel = parcatsViewModel.model.dimensions[catViewModel.model.dimensionInd]; + + // Positions + var hoverCenterY = rectBoundingBox.top + rectBoundingBox.height / 2; + var hoverCenterX, + hoverLabelIdealAlign; + + if(parcatsViewModel.dimensions.length > 1 && + dimensionModel.displayInd === parcatsViewModel.dimensions.length - 1) { + + // right most dimension + hoverCenterX = rectBoundingBox.left; + hoverLabelIdealAlign = 'left'; + } else { + hoverCenterX = rectBoundingBox.left + rectBoundingBox.width; + hoverLabelIdealAlign = 'right'; + } + + // Hover label text + var hoverinfoParts = []; + if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { + hoverinfoParts.push(['Count:', catViewModel.model.count].join(' ')); + } + if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { + hoverinfoParts.push([ + 'P(' + catViewModel.model.categoryLabel + '):', + (catViewModel.model.count / catViewModel.parcatsViewModel.model.count).toFixed(3)].join(' ')); + } + + var hovertext = hoverinfoParts.join('
'); + return { + x: hoverCenterX - rootBBox.left, + y: hoverCenterY - rootBBox.top, + text: hovertext, + color: 'lightgray', + borderColor: 'black', + fontFamily: 'Monaco, "Courier New", monospace', + fontSize: 12, + fontColor: 'black', + idealAlign: hoverLabelIdealAlign + }; +} + +/** + * Create hover label for a band element's category (for use when hoveron === 'category') + * + * @param {ClientRect} rootBBox + * Client bounding box for root of figure + * @param {HTMLElement} bandElement + * HTML element for band + * + */ +function createHoverLabelForDimensionHovermode(rootBBox, bandElement) { + + var allHoverlabels = []; + + d3.select(bandElement.parentNode.parentNode) + .selectAll('g.category') + .select('rect.catrect') + .each(function() { + var bandNode = this; + allHoverlabels.push(createHoverLabelForCategoryHovermode(rootBBox, bandNode)); + }); + + return allHoverlabels; +} + +/** + * Create hover labels for a band element's category (for use when hoveron === 'dimension') + * + * @param {ClientRect} rootBBox + * Client bounding box for root of figure + * @param {HTMLElement} bandElement + * HTML element for band + * + */ +function createHoverLabelForColorHovermode(rootBBox, bandElement) { + + var bandBoundingBox = bandElement.getBoundingClientRect(); + + // Models + /** @type {CategoryBandViewModel} */ + var bandViewModel = d3.select(bandElement).datum(); + var catViewModel = bandViewModel.categoryViewModel; + var parcatsViewModel = catViewModel.parcatsViewModel; + var dimensionModel = parcatsViewModel.model.dimensions[catViewModel.model.dimensionInd]; + + // positions + var hoverCenterY = bandBoundingBox.y + bandBoundingBox.height / 2; + + var hoverCenterX, + hoverLabelIdealAlign; + if(parcatsViewModel.dimensions.length > 1 && + dimensionModel.displayInd === parcatsViewModel.dimensions.length - 1) { + // right most dimension + hoverCenterX = bandBoundingBox.left; + hoverLabelIdealAlign = 'left'; + } else { + hoverCenterX = bandBoundingBox.left + bandBoundingBox.width; + hoverLabelIdealAlign = 'right'; + } + + // Labels + var catLabel = catViewModel.model.categoryLabel; + + // Counts + var totalCount = bandViewModel.parcatsViewModel.model.count; + + var bandColorCount = 0; + bandViewModel.categoryViewModel.bands.forEach(function(b) { + if(b.color === bandViewModel.color) { + bandColorCount += b.count; + } + }); + + var catCount = catViewModel.model.count; + + var colorCount = 0; + parcatsViewModel.pathSelection.each( + /** @param {PathViewModel} pathViewModel */ + function(pathViewModel) { + if(pathViewModel.model.color === bandViewModel.color) { + colorCount += pathViewModel.model.count; + } + }); + + // Hover label text + var hoverinfoParts = []; + if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { + hoverinfoParts.push(['Count:', bandColorCount].join(' ')); + } + if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { + var pColorAndCatLable = 'P(color ∩ ' + catLabel + '): '; + var pColorAndCatValue = (bandColorCount / totalCount).toFixed(3); + var pColorAndCatRow = pColorAndCatLable + pColorAndCatValue; + hoverinfoParts.push(pColorAndCatRow); + + var pCatGivenColorLabel = 'P(' + catLabel + ' | color): '; + var pCatGivenColorValue = (bandColorCount / colorCount).toFixed(3); + var pCatGivenColorRow = pCatGivenColorLabel + pCatGivenColorValue; + hoverinfoParts.push(pCatGivenColorRow); + + var pColorGivenCatLabel = 'P(color | ' + catLabel + '): '; + var pColorGivenCatValue = (bandColorCount / catCount).toFixed(3); + var pColorGivenCatRow = pColorGivenCatLabel + pColorGivenCatValue; + hoverinfoParts.push(pColorGivenCatRow); + } + + var hovertext = hoverinfoParts.join('
'); + + // Compute text color + var textColor = tinycolor.mostReadable(bandViewModel.color, ['black', 'white']); + + return { + x: hoverCenterX - rootBBox.left, + y: hoverCenterY - rootBBox.top, + // name: 'NAME', + text: hovertext, + color: bandViewModel.color, + borderColor: 'black', + fontFamily: 'Monaco, "Courier New", monospace', + fontColor: textColor, + fontSize: 10, + idealAlign: hoverLabelIdealAlign + }; +} + +/** + * Handle dimension mouseover + * @param {CategoryBandViewModel} bandViewModel + */ +function mouseoverCategoryBand(bandViewModel) { + if(!bandViewModel.parcatsViewModel.dragDimension) { + // We're not currently dragging + + if(bandViewModel.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + // hoverinfo is not skip, so we at least style the bands and emit interaction events + + // Mouse + var mouseY = d3.mouse(this)[1]; + if(mouseY < -1) { + // Hover is above above the category rectangle (probably the dimension title text) + return; + } + + var gd = bandViewModel.parcatsViewModel.graphDiv; + var fullLayout = gd._fullLayout; + var rootBBox = fullLayout._paperdiv.node().getBoundingClientRect(); + var hoveron = bandViewModel.parcatsViewModel.hoveron; + + /** @type {HTMLElement} */ + var bandElement = this; + + // Handle style and events + if(hoveron === 'color') { + styleForColorHovermode(bandElement); + emitPointsEventColorHovermode(bandElement, 'plotly_hover', d3.event); + } else { + styleForCategoryHovermode(bandElement); + emitPointsEventCategoryHovermode(bandElement, 'plotly_hover', d3.event); + } + + // Handle hover label + if(bandViewModel.parcatsViewModel.hoverinfoItems.indexOf('none') === -1) { + var hoverItems; + if(hoveron === 'category') { + hoverItems = createHoverLabelForCategoryHovermode(rootBBox, bandElement); + } else if(hoveron === 'color') { + hoverItems = createHoverLabelForColorHovermode(rootBBox, bandElement); + } else if(hoveron === 'dimension') { + hoverItems = createHoverLabelForDimensionHovermode(rootBBox, bandElement); + } + + if(hoverItems) { + Fx.multiHovers(hoverItems, { + container: fullLayout._hoverlayer.node(), + outerContainer: fullLayout._paper.node(), + gd: gd + }); + } + } + } + } +} + + +/** + * Handle dimension mouseover + * @param {CategoryBandViewModel} bandViewModel + */ +function mouseoutCategory(bandViewModel) { + + var parcatsViewModel = bandViewModel.parcatsViewModel; + + if(!parcatsViewModel.dragDimension) { + // We're not dragging anything + + // Reset unhovered styles + stylePathsNoHover(parcatsViewModel.pathSelection); + styleCategoriesNoHover(parcatsViewModel.dimensionSelection.selectAll('g.category')); + styleBandsNoHover(parcatsViewModel.dimensionSelection.selectAll('g.category').selectAll('rect.bandrect')); + + // Remove hover label + Fx.loneUnhover(parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); + + // Restore path order + parcatsViewModel.pathSelection.sort(compareRawColor); + + // Emit unhover event + if(parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + + var hoveron = bandViewModel.parcatsViewModel.hoveron; + var bandElement = this; + + // Handle style and events + if(hoveron === 'color') { + emitPointsEventColorHovermode(bandElement, 'plotly_unhover', d3.event); + } else { + emitPointsEventCategoryHovermode(bandElement, 'plotly_unhover', d3.event); + } + } + } +} + + +/** + * Handle dimension drag start + * @param {DimensionViewModel} d + */ +function dragDimensionStart(d) { + + // Check if dragging is supported + if(d.parcatsViewModel.arrangement === 'fixed') { + return; + } + + // Save off initial drag indexes for dimension + d.dragDimensionDisplayInd = d.model.displayInd; + d.initialDragDimensionDisplayInds = d.parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); + d.dragHasMoved = false; + + // Check for category hit + d.dragCategoryDisplayInd = null; + d3.select(this) + .selectAll('g.category') + .select('rect.catrect') + .each( + /** @param {CategoryViewModel} catViewModel */ + function(catViewModel) { + var catMouseX = d3.mouse(this)[0]; + var catMouseY = d3.mouse(this)[1]; + + + if(-2 <= catMouseX && catMouseX <= catViewModel.width + 2 && + -2 <= catMouseY && catMouseY <= catViewModel.height + 2) { + + // Save off initial drag indexes for categories + d.dragCategoryDisplayInd = catViewModel.model.displayInd; + d.initialDragCategoryDisplayInds = d.model.categories.map(function(c) { + return c.displayInd; + }); + + // Initialize categories dragY to be the current y position + catViewModel.model.dragY = catViewModel.y; + + // Raise category + Lib.raiseToTop(this.parentNode); + + // Get band element + d3.select(this.parentNode) + .selectAll('rect.bandrect') + /** @param {CategoryBandViewModel} bandViewModel */ + .each(function(bandViewModel) { + if(bandViewModel.y < catMouseY && catMouseY <= bandViewModel.y + bandViewModel.height) { + d.potentialClickBand = this; + } + }); + } + }); + + // Update toplevel drag dimension + d.parcatsViewModel.dragDimension = d; + + // Remove hover label if any + Fx.loneUnhover(d.parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); +} + +/** + * Handle dimension drag + * @param {DimensionViewModel} d + */ +function dragDimension(d) { + + // Check if dragging is supported + if(d.parcatsViewModel.arrangement === 'fixed') { + return; + } + + d.dragHasMoved = true; + + if(d.dragDimensionDisplayInd === null) { + return; + } + + var dragDimInd = d.dragDimensionDisplayInd, + prevDimInd = dragDimInd - 1, + nextDimInd = dragDimInd + 1; + + var dragDimension = d.parcatsViewModel + .dimensions[dragDimInd]; + + // Update category + if(d.dragCategoryDisplayInd !== null) { + + var dragCategory = dragDimension.categories[d.dragCategoryDisplayInd]; + + // Update dragY by dy + dragCategory.model.dragY += d3.event.dy; + var categoryY = dragCategory.model.dragY; + + // Check for category drag swaps + var catDisplayInd = dragCategory.model.displayInd; + var dimCategoryViews = dragDimension.categories; + + var catAbove = dimCategoryViews[catDisplayInd - 1]; + var catBelow = dimCategoryViews[catDisplayInd + 1]; + + // Check for overlap above + if(catAbove !== undefined) { + + if(categoryY < (catAbove.y + catAbove.height / 2.0)) { + + // Swap display inds + dragCategory.model.displayInd = catAbove.model.displayInd; + catAbove.model.displayInd = catDisplayInd; + } + } + + if(catBelow !== undefined) { + + if((categoryY + dragCategory.height) > (catBelow.y + catBelow.height / 2.0)) { + + // Swap display inds + dragCategory.model.displayInd = catBelow.model.displayInd; + catBelow.model.displayInd = catDisplayInd; + } + } + + // Update category drag display index + d.dragCategoryDisplayInd = dragCategory.model.displayInd; + } + + // Update dimension position + if(d.dragCategoryDisplayInd === null || d.parcatsViewModel.arrangement === 'freeform') { + dragDimension.model.dragX = d3.event.x; + + // Check for dimension swaps + var prevDimension = d.parcatsViewModel.dimensions[prevDimInd]; + var nextDimension = d.parcatsViewModel.dimensions[nextDimInd]; + + if(prevDimension !== undefined) { + if(dragDimension.model.dragX < (prevDimension.x + prevDimension.width)) { + + // Swap display inds + dragDimension.model.displayInd = prevDimension.model.displayInd; + prevDimension.model.displayInd = dragDimInd; + } + } + + if(nextDimension !== undefined) { + if((dragDimension.model.dragX + dragDimension.width) > nextDimension.x) { + + // Swap display inds + dragDimension.model.displayInd = nextDimension.model.displayInd; + nextDimension.model.displayInd = d.dragDimensionDisplayInd; + } + } + + // Update drag display index + d.dragDimensionDisplayInd = dragDimension.model.displayInd; + } + + // Update view models + updateDimensionViewModels(d.parcatsViewModel); + updatePathViewModels(d.parcatsViewModel); + + // Update svg geometry + updateSvgCategories(d.parcatsViewModel); + updateSvgPaths(d.parcatsViewModel); +} + + +/** + * Handle dimension drag end + * @param {DimensionViewModel} d + */ +function dragDimensionEnd(d) { + + // Check if dragging is supported + if(d.parcatsViewModel.arrangement === 'fixed') { + return; + } + + if(d.dragDimensionDisplayInd === null) { + return; + } + + d3.select(this).selectAll('text').attr('font-weight', 'normal'); + + // Compute restyle command + // ----------------------- + var restyleData = {}; + var traceInd = getTraceIndex(d.parcatsViewModel); + + // ### Handle dimension reordering ### + var finalDragDimensionDisplayInds = d.parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); + var anyDimsReordered = d.initialDragDimensionDisplayInds.some(function(initDimDisplay, dimInd) { + return initDimDisplay !== finalDragDimensionDisplayInds[dimInd]; + }); + + if(anyDimsReordered) { + finalDragDimensionDisplayInds.forEach(function(finalDimDisplay, dimInd) { + var containerInd = d.parcatsViewModel.model.dimensions[dimInd].containerInd; + restyleData['dimensions[' + containerInd + '].displayindex'] = finalDimDisplay; + }); + } + + // ### Handle category reordering ### + var anyCatsReordered = false; + if(d.dragCategoryDisplayInd !== null) { + var finalDragCategoryDisplayInds = d.model.categories.map(function(c) { + return c.displayInd; + }); + + anyCatsReordered = d.initialDragCategoryDisplayInds.some(function(initCatDisplay, catInd) { + return initCatDisplay !== finalDragCategoryDisplayInds[catInd]; + }); + + if(anyCatsReordered) { + + // Sort a shallow copy of the category models by display index + var sortedCategoryModels = d.model.categories.slice().sort( + function(a, b) { return a.displayInd - b.displayInd; }); + + // Get new categoryarray and ticktext values + var newCategoryArray = sortedCategoryModels.map(function(v) { return v.categoryValue; }); + var newCategoryLabels = sortedCategoryModels.map(function(v) { return v.categoryLabel; }); + + restyleData['dimensions[' + d.model.containerInd + '].categoryarray'] = [newCategoryArray]; + restyleData['dimensions[' + d.model.containerInd + '].ticktext'] = [newCategoryLabels]; + restyleData['dimensions[' + d.model.containerInd + '].categoryorder'] = 'array'; + } + } + + // Handle potential click event + // ---------------------------- + if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { + if(!d.dragHasMoved && d.potentialClickBand) { + if(d.parcatsViewModel.hoveron === 'color') { + emitPointsEventColorHovermode(d.potentialClickBand, 'plotly_click', d3.event.sourceEvent); + } else { + emitPointsEventCategoryHovermode(d.potentialClickBand, 'plotly_click', d3.event.sourceEvent); + } + } + } + + // Nullify drag states + // ------------------- + d.model.dragX = null; + if(d.dragCategoryDisplayInd !== null) { + var dragCategory = d.parcatsViewModel + .dimensions[d.dragDimensionDisplayInd] + .categories[d.dragCategoryDisplayInd]; + + dragCategory.model.dragY = null; + d.dragCategoryDisplayInd = null; + } + + d.dragDimensionDisplayInd = null; + d.parcatsViewModel.dragDimension = null; + d.dragHasMoved = null; + d.potentialClickBand = null; + + // Update view models + // ------------------ + updateDimensionViewModels(d.parcatsViewModel); + updatePathViewModels(d.parcatsViewModel); + + // Perform transition + // ------------------ + var transition = d3.transition() + .duration(300) + .ease('cubic-in-out'); + + transition + .each(function() { + updateSvgCategories(d.parcatsViewModel, true); + updateSvgPaths(d.parcatsViewModel, true); + }) + .each('end', function() { + if(anyDimsReordered || anyCatsReordered) { + // Perform restyle if the order of categories or dimensions changed + Plotly.restyle(d.parcatsViewModel.graphDiv, restyleData, [traceInd]); + } + }); +} + +/** + * + * @param {ParcatsViewModel} parcatsViewModel + */ +function getTraceIndex(parcatsViewModel) { + var traceInd; + var allTraces = parcatsViewModel.graphDiv._fullData; + for(var i = 0; i < allTraces.length; i++) { + if(parcatsViewModel.key === allTraces[i].uid) { + traceInd = i; + break; + } + } + return traceInd; +} + +/** Update the svg paths for view model + * @param {ParcatsViewModel} parcatsViewModel + * @param {boolean} hasTransition Whether to update element with transition + */ +function updateSvgPaths(parcatsViewModel, hasTransition) { + + if(hasTransition === undefined) { + hasTransition = false; + } + + function transition(selection) { + return hasTransition ? selection.transition() : selection; + } + + // Update binding + parcatsViewModel.pathSelection.data(function(d) { + return d.paths; + }, key); + + // Update paths + transition(parcatsViewModel.pathSelection).attr('d', function(d) { + return d.svgD; + }); +} + +/** Update the svg paths for view model + * @param {ParcatsViewModel} parcatsViewModel + * @param {boolean} hasTransition Whether to update element with transition + */ +function updateSvgCategories(parcatsViewModel, hasTransition) { + + if(hasTransition === undefined) { + hasTransition = false; + } + + function transition(selection) { + return hasTransition ? selection.transition() : selection; + } + + // Update binding + parcatsViewModel.dimensionSelection + .data(function(d) { + return d.dimensions;}, key); + + var categorySelection = parcatsViewModel.dimensionSelection + .selectAll('g.category') + .data(function(d) {return d.categories;}, key); + + // Update dimension position + transition(parcatsViewModel.dimensionSelection) + .attr('transform', function(d) { + return 'translate(' + d.x + ', 0)'; + }); + + // Update category position + transition(categorySelection) + .attr('transform', function(d) { + return 'translate(0, ' + d.y + ')'; + }); + + var dimLabelSelection = categorySelection.select('.dimlabel'); + + // ### Update dimension label + // Only the top-most display category should have the dimension label + dimLabelSelection + .text(function(d, i) { + if(i === 0) { + // Add dimension label above topmost category + return d.parcatsViewModel.model.dimensions[d.model.dimensionInd].dimensionLabel; + } else { + return null; + } + }); + + // Update category label + // Categories in the right-most display dimension have their labels on + // the right, all others on the left + var catLabelSelection = categorySelection.select('.catlabel'); + catLabelSelection + .attr('text-anchor', + function(d) { + if(catInRightDim(d)) { + // Place label to the right of category + return 'start'; + } else { + // Place label to the left of category + return 'end'; + } + }) + .attr('x', + function(d) { + if(catInRightDim(d)) { + // Place label to the right of category + return d.width + 5; + } else { + // Place label to the left of category + return -5; + } + }) + .each(function(d) { + // Update attriubutes of elements + var newX; + var newAnchor; + if(catInRightDim(d)) { + // Place label to the right of category + newX = d.width + 5; + newAnchor = 'start'; + } else { + // Place label to the left of category + newX = -5; + newAnchor = 'end'; + } + d3.select(this) + .selectAll('tspan') + .attr('x', newX) + .attr('text-anchor', newAnchor); + }); + + // Update bands + // Initialize color band rects + var bandSelection = categorySelection + .selectAll('rect.bandrect') + .data( + /** @param {CategoryViewModel} catViewModel*/ + function(catViewModel) { + return catViewModel.bands; + }, key); + + var bandsSelectionEnter = bandSelection.enter() + .append('rect') + .attr('class', 'bandrect') + .attr('cursor', 'move') + .attr('stroke-opacity', 0) + .attr('fill', function(d) { + return d.color; + }) + .attr('fill-opacity', 0); + + bandSelection + .attr('fill', function(d) { + return d.color; + }) + .attr('width', function(d) { + return d.width; + }) + .attr('height', function(d) { + return d.height; + }) + .attr('y', function(d) { + return d.y; + }); + + styleBandsNoHover(bandsSelectionEnter); + + // Raise bands to the top + bandSelection.each(function() {Lib.raiseToTop(this);}); + + // Remove unused bands + bandSelection.exit().remove(); +} + +/** + * Create a ParcatsViewModel traces + * @param {Object} graphDiv + * Top-level graph div element + * @param {Layout} layout + * SVG layout object + * @param {Array.} wrappedParcatsModel + * Wrapped ParcatsModel for this trace + * @return {ParcatsViewModel} + */ +function createParcatsViewModel(graphDiv, layout, wrappedParcatsModel) { + // Unwrap model + var parcatsModel = wrappedParcatsModel[0]; + + // Compute margin + var margin = layout.margin || {l: 80, r: 80, t: 100, b: 80}; + + // Compute pixel position/extents + var trace = parcatsModel.trace, + domain = trace.domain, + figureWidth = layout.width, + figureHeight = layout.height, + traceWidth = Math.floor(figureWidth * (domain.x[1] - domain.x[0])), + traceHeight = Math.floor(figureHeight * (domain.y[1] - domain.y[0])), + traceX = domain.x[0] * figureWidth + margin.l, + traceY = layout.height - domain.y[1] * layout.height + margin.t; + + // Handle path shape + // ----------------- + var pathShape = trace.line.shape; + + // Handle hover info + // ----------------- + var hoverinfoItems; + if(trace.hoverinfo === 'all') { + hoverinfoItems = ['count', 'probability']; + } else { + hoverinfoItems = trace.hoverinfo.split('+'); + } + + // Construct parcatsViewModel + // -------------------------- + var parcatsViewModel = { + key: trace.uid, + model: parcatsModel, + x: traceX, + y: traceY, + width: traceWidth, + height: traceHeight, + hoveron: trace.hoveron, + hoverinfoItems: hoverinfoItems, + arrangement: trace.arrangement, + bundlecolors: trace.bundlecolors, + sortpaths: trace.sortpaths, + labelfont: trace.labelfont, + categorylabelfont: trace.tickfont, + pathShape: pathShape, + dragDimension: null, + margin: margin, + paths: [], + dimensions: [], + graphDiv: graphDiv, + traceSelection: null, + pathSelection: null, + dimensionSelection: null + }; + + // Update dimension view models if we have at least 1 dimension + if(parcatsModel.dimensions) { + updateDimensionViewModels(parcatsViewModel); + + // Update path view models if we have at least 2 dimensions + updatePathViewModels(parcatsViewModel); + } + // Inside a categories view model + return parcatsViewModel; +} + +/** + * Build the SVG string to represents a parallel categories path + * @param {Array.} leftXPositions + * Array of the x positions of the left edge of each dimension (in display order) + * @param {Array.} pathYs + * Array of the y positions of the top of the path at each dimension (in display order) + * @param {Array.} dimWidths + * Array of the widths of each dimension in display order + * @param {Number} pathHeight + * The height of the path in pixels + * @param {Number} curvature + * The curvature factor for the path. 0 results in a straight line and values greater than zero result in curved paths + * @return {string} + */ +function buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, curvature) { + + // Compute the x midpoint of each path segment + var xRefPoints1 = [], + xRefPoints2 = [], + refInterpolator, + d; + + for(d = 0; d < dimWidths.length - 1; d++) { + refInterpolator = d3.interpolateNumber(dimWidths[d] + leftXPositions[d], leftXPositions[d + 1]); + xRefPoints1.push(refInterpolator(curvature)); + xRefPoints2.push(refInterpolator(1 - curvature)); + } + + // Move to top of path on left edge of left-most category + var svgD = 'M ' + leftXPositions[0] + ',' + pathYs[0]; + + // Horizontal line to right edge + svgD += 'l' + dimWidths[0] + ',0 '; + + // Horizontal line to right edge + for(d = 1; d < dimWidths.length; d++) { + + // Curve to left edge of category + svgD += 'C' + xRefPoints1[d - 1] + ',' + pathYs[d - 1] + + ' ' + xRefPoints2[d - 1] + ',' + pathYs[d] + + ' ' + leftXPositions[d] + ',' + pathYs[d]; + + // svgD += 'L' + leftXPositions[d] + ',' + pathYs[d]; + + // Horizontal line to right edge + svgD += 'l' + dimWidths[d] + ',0 '; + } + + // Line down + svgD += 'l' + '0,' + pathHeight + ' '; + + // Line to left edge of right-most category + svgD += 'l -' + dimWidths[dimWidths.length - 1] + ',0 '; + + for(d = dimWidths.length - 2; d >= 0; d--) { + + // Curve to right edge of category + svgD += 'C' + xRefPoints2[d] + ',' + (pathYs[d + 1] + pathHeight) + + ' ' + xRefPoints1[d] + ',' + (pathYs[d] + pathHeight) + + ' ' + (leftXPositions[d] + dimWidths[d]) + ',' + (pathYs[d] + pathHeight); + + // svgD += 'L' + (leftXPositions[d] + dimWidths[d]) + ',' + (pathYs[d] + pathHeight); + + // Horizontal line to right edge + svgD += 'l-' + dimWidths[d] + ',0 '; + } + + // Close path + svgD += 'Z'; + return svgD; +} + +/** + * Update the path view models based on the dimension view models in a ParcatsViewModel + * + * @param {ParcatsViewModel} parcatsViewModel + * View model for trace + */ +function updatePathViewModels(parcatsViewModel) { + + // Initialize an array of the y position of the top of the next path to be added to each category. + // + // nextYPositions[d][c] is the y position of the next path through category with index c of dimension with index d + var dimensionViewModels = parcatsViewModel.dimensions; + var parcatsModel = parcatsViewModel.model; + var nextYPositions = dimensionViewModels.map( + function(d) { + return d.categories.map( + function(c) { + return c.y; + }); + }); + + // Array from category index to category display index for each true dimension index + var catToDisplayIndPerDim = parcatsViewModel.model.dimensions.map( + function(d) { + return d.categories.map(function(c) {return c.displayInd;}); + }); + + // Array from true dimension index to dimension display index + var dimToDisplayInd = parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); + var displayToDimInd = parcatsViewModel.dimensions.map(function(d) {return d.model.dimensionInd;}); + + // Array of the x position of the left edge of the rectangles for each dimension + var leftXPositions = dimensionViewModels.map( + function(d) { + return d.x; + }); + + // Compute dimension widths + var dimWidths = dimensionViewModels.map(function(d) {return d.width;}); + + // Build sorted Array of PathModel objects + var pathModels = []; + for(var p in parcatsModel.paths) { + if(parcatsModel.paths.hasOwnProperty(p)) { + pathModels.push(parcatsModel.paths[p]); + } + } + + // Compute category display inds to use for sorting paths + function pathDisplayCategoryInds(pathModel) { + var dimensionInds = pathModel.categoryInds.map(function(catInd, dimInd) {return catToDisplayIndPerDim[dimInd][catInd];}); + var displayInds = displayToDimInd.map(function(dimInd) { + return dimensionInds[dimInd]; + }); + return displayInds; + } + + // Sort in ascending order by display index array + pathModels.sort(function(v1, v2) { + + // Build display inds for each path + var sortArray1 = pathDisplayCategoryInds(v1); + var sortArray2 = pathDisplayCategoryInds(v2); + + // Handle path sort order + if(parcatsViewModel.sortpaths === 'backward') { + sortArray1.reverse(); + sortArray2.reverse(); + } + + // Append the first value index of the path to break ties + sortArray1.push(v1.valueInds[0]); + sortArray2.push(v2.valueInds[0]); + + // Handle color bundling + if(parcatsViewModel.bundlecolors) { + // Prepend sort array with the raw color value + sortArray1.unshift(v1.rawColor); + sortArray2.unshift(v2.rawColor); + } + + // colors equal, sort by display categories + if(sortArray1 < sortArray2) { + return -1; + } + if(sortArray1 > sortArray2) { + return 1; + } + + return 0; + }); + + // Create path models + var pathViewModels = new Array(pathModels.length), + totalCount = dimensionViewModels[0].model.count, + totalHeight = dimensionViewModels[0].categories + .map(function(c) { + return c.height;}).reduce( + function(v1, v2) {return v1 + v2;}); + + + for(var pathNumber = 0; pathNumber < pathModels.length; pathNumber++) { + var pathModel = pathModels[pathNumber]; + + var pathHeight; + if(totalCount > 0) { + pathHeight = totalHeight * (pathModel.count / totalCount); + } else { + pathHeight = 0; + } + + // Build path y coords + var pathYs = new Array(nextYPositions.length); + for(var d = 0; d < pathModel.categoryInds.length; d++) { + var catInd = pathModel.categoryInds[d]; + var catDisplayInd = catToDisplayIndPerDim[d][catInd]; + var dimDisplayInd = dimToDisplayInd[d]; + + // Update next y position + pathYs[dimDisplayInd] = nextYPositions[dimDisplayInd][catDisplayInd]; + nextYPositions[dimDisplayInd][catDisplayInd] += pathHeight; + + // Update category color information + var catViewModle = parcatsViewModel.dimensions[dimDisplayInd].categories[catDisplayInd]; + var numBands = catViewModle.bands.length; + var lastCatBand = catViewModle.bands[numBands - 1]; + + if(lastCatBand === undefined || pathModel.rawColor !== lastCatBand.rawColor) { + // Create a new band + var bandY = lastCatBand === undefined ? 0 : lastCatBand.y + lastCatBand.height; + catViewModle.bands.push({ + key: bandY, + color: pathModel.color, + rawColor: pathModel.rawColor, + height: pathHeight, + width: catViewModle.width, + count: pathModel.count, + y: bandY, + categoryViewModel: catViewModle, + parcatsViewModel: parcatsViewModel + }); + } else { + // Extend current band + var currentBand = catViewModle.bands[numBands - 1]; + currentBand.height += pathHeight; + currentBand.count += pathModel.count; + } + } + + // build svg path + var svgD; + if(parcatsViewModel.pathShape === 'hspline') { + svgD = buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, 0.5); + } else { + svgD = buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, 0); + } + + pathViewModels[pathNumber] = { + key: pathModel.valueInds[0], + model: pathModel, + height: pathHeight, + leftXs: leftXPositions, + topYs: pathYs, + dimWidths: dimWidths, + svgD: svgD, + parcatsViewModel: parcatsViewModel + }; + } + + parcatsViewModel.paths = pathViewModels; + + // * @property key + // * Unique key for this model + // * @property {PathModel} model + // * Source path model + // * @property {Number} height + // * Height of this path (pixels) + // * @property {String} svgD + // * SVG path "d" attribute string +} + +/** + * Update the dimension view models based on the dimension models in a ParcatsViewModel + * + * @param {ParcatsViewModel} parcatsViewModel + * View model for trace + */ +function updateDimensionViewModels(parcatsViewModel) { + + // Compute dimension ordering + var dimensionsIndInfo = parcatsViewModel.model.dimensions.map(function(d) { + return {displayInd: d.displayInd, dimensionInd: d.dimensionInd}; + }); + + dimensionsIndInfo.sort(function(a, b) { + return a.displayInd - b.displayInd; + }); + + var dimensions = []; + for(var displayInd in dimensionsIndInfo) { + var dimensionInd = dimensionsIndInfo[displayInd].dimensionInd; + var dimModel = parcatsViewModel.model.dimensions[dimensionInd]; + dimensions.push(createDimensionViewModel(parcatsViewModel, dimModel)); + } + + parcatsViewModel.dimensions = dimensions; +} + +/** + * Create a parcats DimensionViewModel + * + * @param {ParcatsViewModel} parcatsViewModel + * View model for trace + * @param {DimensionModel} dimensionModel + * @return {DimensionViewModel} + */ +function createDimensionViewModel(parcatsViewModel, dimensionModel) { + + // Compute dimension x position + var categoryLabelPad = 40, + dimWidth = 16, + numDimensions = parcatsViewModel.model.dimensions.length, + displayInd = dimensionModel.displayInd; + + // Compute x coordinate values + var dimDx, + dimX0, + dimX; + + if(numDimensions > 1) { + dimDx = (parcatsViewModel.width - 2 * categoryLabelPad - dimWidth) / (numDimensions - 1); + } else { + dimDx = 0; + } + dimX0 = categoryLabelPad; + dimX = dimX0 + dimDx * displayInd; + + // Compute categories + var categories = [], + maxCats = parcatsViewModel.model.maxCats, + numCats = dimensionModel.categories.length, + catSpacing = 8, + totalCount = dimensionModel.count, + totalHeight = parcatsViewModel.height - catSpacing * (maxCats - 1), + nextCatHeight, + nextCatModel, + nextCat, + catInd, + catDisplayInd; + + // Compute starting Y offset + var nextCatY = (maxCats - numCats) * catSpacing / 2.0; + + // Compute category ordering + var categoryIndInfo = dimensionModel.categories.map(function(c) { + return {displayInd: c.displayInd, categoryInd: c.categoryInd}; + }); + + categoryIndInfo.sort(function(a, b) { + return a.displayInd - b.displayInd; + }); + + for(catDisplayInd = 0; catDisplayInd < numCats; catDisplayInd++) { + catInd = categoryIndInfo[catDisplayInd].categoryInd; + nextCatModel = dimensionModel.categories[catInd]; + + if(totalCount > 0) { + nextCatHeight = (nextCatModel.count / totalCount) * totalHeight; + } else { + nextCatHeight = 0; + } + + nextCat = { + key: nextCatModel.valueInds[0], + model: nextCatModel, + width: dimWidth, + height: nextCatHeight, + y: nextCatModel.dragY !== null ? nextCatModel.dragY : nextCatY, + bands: [], + parcatsViewModel: parcatsViewModel + }; + + nextCatY = nextCatY + nextCatHeight + catSpacing; + categories.push(nextCat); + } + + return { + key: dimensionModel.dimensionInd, + x: dimensionModel.dragX !== null ? dimensionModel.dragX : dimX, + y: 0, + width: dimWidth, + model: dimensionModel, + categories: categories, + parcatsViewModel: parcatsViewModel, + dragCategoryDisplayInd: null, + dragDimensionDisplayInd: null, + initialDragDimensionDisplayInds: null, + initialDragCategoryDisplayInds: null, + dragHasMoved: null, + potentialClickBand: null + }; +} + +// JSDoc typedefs +// ============== +/** + * @typedef {Object} Layout + * Object containing svg layout information + * + * @property {Number} width (pixels) + * Usable width for Figure (after margins are removed) + * @property {Number} height (pixels) + * Usable height for Figure (after margins are removed) + * @property {Margin} margin + * Margin around the Figure (pixels) + */ + +/** + * @typedef {Object} Margin + * Object containing padding information in pixels + * + * @property {Number} t + * Top margin + * @property {Number} r + * Right margin + * @property {Number} b + * Bottom margin + * @property {Number} l + * Left margin + */ + +/** + * @typedef {Object} Font + * Object containing font information + * + * @property {Number} size: Font size + * @property {String} color: Font color + * @property {String} family: Font family + */ + +/** + * @typedef {Object} ParcatsViewModel + * Object containing calculated parcats view information + * + * These are quantities that require Layout information to calculate + * @property key + * Unique key for this model + * @property {ParcatsModel} model + * Source parcats model + * @property {Array.} dimensions + * Array of dimension view models + * @property {Number} width + * Width for this trace (pixels) + * @property {Number} height + * Height for this trace (pixels) + * @property {Number} x + * X position of this trace with respect to the Figure (pixels) + * @property {Number} y + * Y position of this trace with respect to the Figure (pixels) + * @property {String} hoveron + * Hover interaction mode. One of: 'category', 'color', or 'dimension' + * @property {Array.} hoverinfoItems + * Info to display on hover. Array with a combination of 'counts' and/or 'probabilities', or 'none', or 'skip' + * @property {String} arrangement + * Category arrangement. One of: 'perpendicular', 'freeform', or 'fixed' + * @property {Boolean} bundlecolors + * Whether paths should be sorted so that like colors are bundled together as they pass through categories + * @property {String} sortpaths + * If 'forward' then sort paths based on dimensions from left to right. If 'backward' sort based on dimensions + * from right to left + * @property {Font} labelfont + * Font for the dimension labels + * @property {Font} categorylabelfont + * Font for the category labels + * @property {String} pathShape + * The shape of the paths. Either 'linear' or 'hspline'. + * @property {DimensionViewModel|null} dragDimension + * Dimension currently being dragged. Null if no drag in progress + * @property {Margin} margin + * Margin around the Figure + * @property {Object} graphDiv + * Top-level graph div element + * @property {Object} traceSelection + * D3 selection of this view models trace group element + * @property {Object} pathSelection + * D3 selection of this view models path elements + * @property {Object} dimensionSelection + * D3 selection of this view models dimension group element + */ + +/** + * @typedef {Object} DimensionViewModel + * Object containing calculated parcats dimension view information + * + * These are quantities that require Layout information to calculate + * @property key + * Unique key for this model + * @property {DimensionModel} model + * Source dimension model + * @property {Number} x + * X position of the center of this dimension with respect to the Figure (pixels) + * @property {Number} y + * Y position of the top of this dimension with respect to the Figure (pixels) + * @property {Number} width + * Width of categories in this dimension (pixels) + * @property {ParcatsViewModel} parcatsViewModel + * The parent trace's view model + * @property {Array.} categories + * Dimensions category view models + * @property {Number|null} dragCategoryDisplayInd + * Display index of category currently being dragged. null if no category is being dragged + * @property {Number|null} dragDimensionDisplayInd + * Display index of the dimension being dragged. null if no dimension is being dragged + * @property {Array.|null} initialDragDimensionDisplayInds + * Dimensions display indexes at the beginning of the current drag. null if no dimension is being dragged + * @property {Array.|null} initialDragCategoryDisplayInds + * Category display indexes for the at the beginning of the current drag. null if no category is being dragged + * @property {HTMLElement} potentialClickBand + * Band under mouse when current drag began. If no drag movement takes place then a click will be emitted for this + * band. Null if not drag in progress. + * @property {Boolean} dragHasMoved + * True if there is an active drag and the drag has moved. If drag doesn't move before being ended then + * this may be interpreted as a click. Null if no drag in progress + */ + +/** + * @typedef {Object} CategoryViewModel + * Object containing calculated parcats category view information + * + * These are quantities that require Layout information to calculate + * @property key + * Unique key for this model + * @property {CategoryModel} model + * Source category model + * @property {Number} width + * Width for this category (pixels) + * @property {Number} height + * Height for this category (pixels) + * @property {Number} y + * Y position of this cateogry with respect to the Figure (pixels) + * @property {Array.} bands + * Array of color bands inside the category + * @property {ParcatsViewModel} parcatsViewModel + * The parent trace's view model + */ + +/** + * @typedef {Object} CategoryBandViewModel + * Object containing calculated category band information. A category band is a region inside a category covering + * paths of a single color + * + * @property key + * Unique key for this model + * @property color + * Band color + * @property rawColor + * Raw color value for band + * @property {Number} width + * Band width + * @property {Number} height + * Band height + * @property {Number} y + * Y position of top of the band with respect to the category + * @property {Number} count + * The number of samples represented by the band + * @property {CategoryViewModel} categoryViewModel + * The parent categorie's view model + * @property {ParcatsViewModel} parcatsViewModel + * The parent trace's view model + */ + +/** + * @typedef {Object} PathViewModel + * Object containing calculated parcats path view information + * + * These are quantities that require Layout information to calculate + * @property key + * Unique key for this model + * @property {PathModel} model + * Source path model + * @property {Number} height + * Height of this path (pixels) + * @property {Array.} leftXs + * The x position of the left edge of each display dimension + * @property {Array.} topYs + * The y position of the top of the path for each display dimension + * @property {Array.} dimWidths + * The width of each display dimension + * @property {String} svgD + * SVG path "d" attribute string + * @property {ParcatsViewModel} parcatsViewModel + * The parent trace's view model + */ + +},{"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/svg_text_utils":720,"../../plot_api/plot_api":731,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"tinycolor2":514}],1006:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +var parcats = _dereq_('./parcats'); + +/** + * Create / update parcat traces + * + * @param {Object} graphDiv + * @param {Array.} parcatsModels + */ +module.exports = function plot(graphDiv, parcatsModels, transitionOpts, makeOnCompleteCallback) { + var fullLayout = graphDiv._fullLayout, + svg = fullLayout._paper, + size = fullLayout._size; + + parcats( + graphDiv, + svg, + parcatsModels, + { + width: size.w, + height: size.h, + margin: { + t: size.t, + r: size.r, + b: size.b, + l: size.l + } + }, + transitionOpts, + makeOnCompleteCallback + ); +}; + +},{"./parcats":1005}],1007:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var domainAttrs = _dereq_('../../plots/domain').attributes; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; + +module.exports = { + domain: domainAttrs({name: 'parcoords', trace: true, editType: 'calc'}), + + hoverlabel: undefined, + + labelfont: fontAttrs({ + editType: 'calc', + + }), + tickfont: fontAttrs({ + editType: 'calc', + + }), + rangefont: fontAttrs({ + editType: 'calc', + + }), + + dimensions: templatedArray('dimension', { + label: { + valType: 'string', + + editType: 'calc', + + }, + // TODO: better way to determine ordinal vs continuous axes, + // so users can use tickvals/ticktext with a continuous axis. + tickvals: extendFlat({}, axesAttrs.tickvals, {editType: 'calc'}), + ticktext: extendFlat({}, axesAttrs.ticktext, {editType: 'calc'}), + tickformat: { + valType: 'string', + dflt: '3s', + + editType: 'calc', + + }, + visible: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'number', editType: 'calc'}, + {valType: 'number', editType: 'calc'} + ], + editType: 'calc', + + }, + constraintrange: { + valType: 'info_array', + + freeLength: true, + dimensions: '1-2', + items: [ + {valType: 'number', editType: 'calc'}, + {valType: 'number', editType: 'calc'} + ], + editType: 'calc', + + }, + multiselect: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + values: { + valType: 'data_array', + + editType: 'calc', + + }, + editType: 'calc', + + }), + + line: extendFlat( + colorAttributes('line', { + // the default autocolorscale isn't quite usable for parcoords due to context ambiguity around 0 (grey, off-white) + // autocolorscale therefore defaults to false too, to avoid being overridden by the blue-white-red autocolor palette + colorscaleDflt: 'Viridis', + autoColorDflt: false, + editTypeOverride: 'calc' + }), { + colorbar: colorbarAttrs, + editType: 'calc' + }) +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/plot_template":734,"../../plots/cartesian/layout_attributes":757,"../../plots/domain":770,"../../plots/font_attributes":771}],1008:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var c = _dereq_('./constants'); +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var keyFun = _dereq_('../../lib/gup').keyFun; +var repeat = _dereq_('../../lib/gup').repeat; +var sortAsc = _dereq_('../../lib').sorterAsc; + +var snapRatio = c.bar.snapRatio; +function snapOvershoot(v, vAdjacent) { return v * (1 - snapRatio) + vAdjacent * snapRatio; } + +var snapClose = c.bar.snapClose; +function closeToCovering(v, vAdjacent) { return v * (1 - snapClose) + vAdjacent * snapClose; } + +// snap for the low end of a range on an ordinal scale +// on an ordinal scale, always show some overshoot from the exact value, +// so it's clear we're covering it +// find the interval we're in, and snap to 1/4 the distance to the next +// these two could be unified at a slight loss of readability / perf +function ordinalScaleSnapLo(a, v, existingRanges) { + if(overlappingExisting(v, existingRanges)) return v; + + var aPrev = a[0]; + var aPrevPrev = aPrev; + for(var i = 1; i < a.length; i++) { + var aNext = a[i]; + + // very close to the previous - snap down to it + if(v < closeToCovering(aPrev, aNext)) return snapOvershoot(aPrev, aPrevPrev); + if(v < aNext || i === a.length - 1) return snapOvershoot(aNext, aPrev); + + aPrevPrev = aPrev; + aPrev = aNext; + } +} + +function ordinalScaleSnapHi(a, v, existingRanges) { + if(overlappingExisting(v, existingRanges)) return v; + + var aPrev = a[a.length - 1]; + var aPrevPrev = aPrev; + for(var i = a.length - 2; i >= 0; i--) { + var aNext = a[i]; + + // very close to the previous - snap down to it + if(v > closeToCovering(aPrev, aNext)) return snapOvershoot(aPrev, aPrevPrev); + if(v > aNext || i === a.length - 1) return snapOvershoot(aNext, aPrev); + + aPrevPrev = aPrev; + aPrev = aNext; + } +} + +function overlappingExisting(v, existingRanges) { + for(var i = 0; i < existingRanges.length; i++) { + if(v >= existingRanges[i][0] && v <= existingRanges[i][1]) return true; + } + return false; +} + +function barHorizontalSetup(selection) { + selection + .attr('x', -c.bar.captureWidth / 2) + .attr('width', c.bar.captureWidth); +} + +function backgroundBarHorizontalSetup(selection) { + selection + .attr('visibility', 'visible') + .style('visibility', 'visible') + .attr('fill', 'yellow') + .attr('opacity', 0); +} + +function setHighlight(d) { + if(!d.brush.filterSpecified) { + return '0,' + d.height; + } + var pixelRanges = unitToPx(d.brush.filter.getConsolidated(), d.height); + var dashArray = [0]; // we start with a 0 length selection as filter ranges are inclusive, not exclusive + var p, sectionHeight, iNext; + var currentGap = pixelRanges.length ? pixelRanges[0][0] : null; + for(var i = 0; i < pixelRanges.length; i++) { + p = pixelRanges[i]; + sectionHeight = p[1] - p[0]; + dashArray.push(currentGap); + dashArray.push(sectionHeight); + iNext = i + 1; + if(iNext < pixelRanges.length) { + currentGap = pixelRanges[iNext][0] - p[1]; + } + } + dashArray.push(d.height); + // d.height is added at the end to ensure that (1) we have an even number of dasharray points, MDN page says + // "If an odd number of values is provided, then the list of values is repeated to yield an even number of values." + // and (2) it's _at least_ as long as the full height (even if range is minuscule and at the bottom) though this + // may not be necessary, maybe duplicating the last point would do too. But no harm in a longer dasharray than line. + return dashArray; +} + +function unitToPx(unitRanges, height) { + return unitRanges.map(function(pr) { + return pr.map(function(v) { return v * height; }).sort(sortAsc); + }); +} + +// is the cursor over the north, middle, or south of a bar? +// the end handles extend over the last 10% of the bar +function getRegion(fPix, y) { + var pad = c.bar.handleHeight; + if(y > fPix[1] + pad || y < fPix[0] - pad) return; + if(y >= 0.9 * fPix[1] + 0.1 * fPix[0]) return 'n'; + if(y <= 0.9 * fPix[0] + 0.1 * fPix[1]) return 's'; + return 'ns'; +} + +function clearCursor() { + d3.select(document.body) + .style('cursor', null); +} + +function styleHighlight(selection) { + // stroke-dasharray is used to minimize the number of created DOM nodes, because the requirement calls for up to + // 1000 individual selections on an axis, and there can be 60 axes per parcoords, and multiple parcoords per + // dashboard. The technique is similar to https://codepen.io/monfera/pen/rLYqWR and using a `polyline` with + // multiple sections, or a `path` element via its `d` attribute would also be DOM-sparing alternatives. + selection.attr('stroke-dasharray', setHighlight); +} + +function renderHighlight(root, tweenCallback) { + var bar = d3.select(root).selectAll('.highlight, .highlight-shadow'); + var barToStyle = tweenCallback ? bar.transition().duration(c.bar.snapDuration).each('end', tweenCallback) : bar; + styleHighlight(barToStyle); +} + +function getInterval(d, y) { + var b = d.brush; + var active = b.filterSpecified; + var closestInterval = NaN; + var out = {}; + var i; + + if(active) { + var height = d.height; + var intervals = b.filter.getConsolidated(); + var pixIntervals = unitToPx(intervals, height); + var hoveredInterval = NaN; + var previousInterval = NaN; + var nextInterval = NaN; + for(i = 0; i <= pixIntervals.length; i++) { + var p = pixIntervals[i]; + if(p && p[0] <= y && y <= p[1]) { + // over a bar + hoveredInterval = i; + break; + } else { + // between bars, or before/after the first/last bar + previousInterval = i ? i - 1 : NaN; + if(p && p[0] > y) { + nextInterval = i; + break; // no point continuing as intervals are non-overlapping and sorted; could use log search + } + } + } + + closestInterval = hoveredInterval; + if(isNaN(closestInterval)) { + if(isNaN(previousInterval) || isNaN(nextInterval)) { + closestInterval = isNaN(previousInterval) ? nextInterval : previousInterval; + } + else { + closestInterval = (y - pixIntervals[previousInterval][1] < pixIntervals[nextInterval][0] - y) ? + previousInterval : nextInterval; + } + } + + if(!isNaN(closestInterval)) { + var fPix = pixIntervals[closestInterval]; + var region = getRegion(fPix, y); + + if(region) { + out.interval = intervals[closestInterval]; + out.intervalPix = fPix; + out.region = region; + } + } + } + + if(d.ordinal && !out.region) { + var a = d.unitTickvals; + var unitLocation = d.unitToPaddedPx.invert(y); + for(i = 0; i < a.length; i++) { + var rangei = [ + a[Math.max(i - 1, 0)] * 0.25 + a[i] * 0.75, + a[Math.min(i + 1, a.length - 1)] * 0.25 + a[i] * 0.75 + ]; + if(unitLocation >= rangei[0] && unitLocation <= rangei[1]) { + out.clickableOrdinalRange = rangei; + break; + } + } + } + + return out; +} + +function attachDragBehavior(selection) { + // There's some fiddling with pointer cursor styling so that the cursor preserves its shape while dragging a brush + // even if the cursor strays from the interacting bar, which is bound to happen as bars are thin and the user + // will inevitably leave the hotspot strip. In this regard, it does something similar to what the D3 brush would do. + selection + .on('mousemove', function(d) { + d3.event.preventDefault(); + if(!d.parent.inBrushDrag) { + var y = d.height - d3.mouse(this)[1] - 2 * c.verticalPadding; + var interval = getInterval(d, y); + + var cursor = 'crosshair'; + if(interval.clickableOrdinalRange) cursor = 'pointer'; + else if(interval.region) cursor = interval.region + '-resize'; + d3.select(document.body) + .style('cursor', cursor); + } + }) + .on('mouseleave', function(d) { + if(!d.parent.inBrushDrag) clearCursor(); + }) + .call(d3.behavior.drag() + .on('dragstart', function(d) { + d3.event.sourceEvent.stopPropagation(); + var y = d.height - d3.mouse(this)[1] - 2 * c.verticalPadding; + var unitLocation = d.unitToPaddedPx.invert(y); + var b = d.brush; + var interval = getInterval(d, y); + var unitRange = interval.interval; + var s = b.svgBrush; + s.wasDragged = false; // we start assuming there won't be a drag - useful for reset + s.grabbingBar = interval.region === 'ns'; + if(s.grabbingBar) { + var pixelRange = unitRange.map(d.unitToPaddedPx); + s.grabPoint = y - pixelRange[0] - c.verticalPadding; + s.barLength = pixelRange[1] - pixelRange[0]; + } + s.clickableOrdinalRange = interval.clickableOrdinalRange; + s.stayingIntervals = (d.multiselect && b.filterSpecified) ? b.filter.getConsolidated() : []; + if(unitRange) { + s.stayingIntervals = s.stayingIntervals.filter(function(int2) { + return int2[0] !== unitRange[0] && int2[1] !== unitRange[1]; + }); + } + s.startExtent = interval.region ? unitRange[interval.region === 's' ? 1 : 0] : unitLocation; + d.parent.inBrushDrag = true; + s.brushStartCallback(); + }) + .on('drag', function(d) { + d3.event.sourceEvent.stopPropagation(); + var y = d.height - d3.mouse(this)[1] - 2 * c.verticalPadding; + var s = d.brush.svgBrush; + s.wasDragged = true; + + if(s.grabbingBar) { // moving the bar + s.newExtent = [y - s.grabPoint, y + s.barLength - s.grabPoint].map(d.unitToPaddedPx.invert); + } else { // south/north drag or new bar creation + s.newExtent = [s.startExtent, d.unitToPaddedPx.invert(y)].sort(sortAsc); + } + + // take care of the parcoords axis height constraint: bar can't breach it + var bottomViolation = Math.max(0, -s.newExtent[0]); + var topViolation = Math.max(0, s.newExtent[1] - 1); + s.newExtent[0] += bottomViolation; + s.newExtent[1] -= topViolation; + if(s.grabbingBar) { + // in case of bar dragging (non-resizing interaction, unlike north/south resize or new bar creation) + // the constraint adjustment must apply to the other end of the bar as well, otherwise it'd + // shorten or lengthen + s.newExtent[1] += bottomViolation; + s.newExtent[0] -= topViolation; + } + + d.brush.filterSpecified = true; + s.extent = s.stayingIntervals.concat([s.newExtent]); + s.brushCallback(d); + renderHighlight(this.parentNode); + }) + .on('dragend', function(d) { + var e = d3.event; + e.sourceEvent.stopPropagation(); + var brush = d.brush; + var filter = brush.filter; + var s = brush.svgBrush; + var grabbingBar = s.grabbingBar; + s.grabbingBar = false; + s.grabLocation = undefined; + d.parent.inBrushDrag = false; + clearCursor(); // instead of clearing, a nicer thing would be to set it according to current location + if(!s.wasDragged) { // a click+release on the same spot (ie. w/o dragging) means a bar or full reset + s.wasDragged = undefined; // logic-wise unneeded, just shows `wasDragged` has no longer a meaning + if(s.clickableOrdinalRange) { + if(brush.filterSpecified && d.multiselect) { + s.extent.push(s.clickableOrdinalRange); + } + else { + s.extent = [s.clickableOrdinalRange]; + brush.filterSpecified = true; + } + } + else if(grabbingBar) { + s.extent = s.stayingIntervals; + if(s.extent.length === 0) { + brushClear(brush); + } + } else { + brushClear(brush); + } + s.brushCallback(d); + renderHighlight(this.parentNode); + s.brushEndCallback(brush.filterSpecified ? filter.getConsolidated() : []); + return; // no need to fuse intervals or snap to ordinals, so we can bail early + } + + var mergeIntervals = function() { + // Key piece of logic: once the button is released, possibly overlapping intervals will be fused: + // Here it's done immediately on click release while on ordinal snap transition it's done at the end + filter.set(filter.getConsolidated()); + }; + + if(d.ordinal) { + var a = d.unitTickvals; + if(a[a.length - 1] < a[0]) a.reverse(); + s.newExtent = [ + ordinalScaleSnapLo(a, s.newExtent[0], s.stayingIntervals), + ordinalScaleSnapHi(a, s.newExtent[1], s.stayingIntervals) + ]; + var hasNewExtent = s.newExtent[1] > s.newExtent[0]; + s.extent = s.stayingIntervals.concat(hasNewExtent ? [s.newExtent] : []); + if(!s.extent.length) { + brushClear(brush); + } + s.brushCallback(d); + if(hasNewExtent) { + // merging intervals post the snap tween + renderHighlight(this.parentNode, mergeIntervals); + } + else { + // if no new interval, don't animate, just redraw the highlight immediately + mergeIntervals(); + renderHighlight(this.parentNode); + } + } else { + mergeIntervals(); // merging intervals immediately + } + s.brushEndCallback(brush.filterSpecified ? filter.getConsolidated() : []); + }) + ); +} + +function startAsc(a, b) { return a[0] - b[0]; } + +function renderAxisBrush(axisBrush) { + + var background = axisBrush.selectAll('.background').data(repeat); + + background.enter() + .append('rect') + .classed('background', true) + .call(barHorizontalSetup) + .call(backgroundBarHorizontalSetup) + .style('pointer-events', 'auto') // parent pointer events are disabled; we must have it to register events + .attr('transform', 'translate(0 ' + c.verticalPadding + ')'); + + background + .call(attachDragBehavior) + .attr('height', function(d) { + return d.height - c.verticalPadding; + }); + + var highlightShadow = axisBrush.selectAll('.highlight-shadow').data(repeat); // we have a set here, can't call it `extent` + + highlightShadow.enter() + .append('line') + .classed('highlight-shadow', true) + .attr('x', -c.bar.width / 2) + .attr('stroke-width', c.bar.width + c.bar.strokeWidth) + .attr('stroke', c.bar.strokeColor) + .attr('opacity', c.bar.strokeOpacity) + .attr('stroke-linecap', 'butt'); + + highlightShadow + .attr('y1', function(d) { return d.height; }) + .call(styleHighlight); + + var highlight = axisBrush.selectAll('.highlight').data(repeat); // we have a set here, can't call it `extent` + + highlight.enter() + .append('line') + .classed('highlight', true) + .attr('x', -c.bar.width / 2) + .attr('stroke-width', c.bar.width - c.bar.strokeWidth) + .attr('stroke', c.bar.fillColor) + .attr('opacity', c.bar.fillOpacity) + .attr('stroke-linecap', 'butt'); + + highlight + .attr('y1', function(d) { return d.height; }) + .call(styleHighlight); +} + +function ensureAxisBrush(axisOverlays) { + var axisBrush = axisOverlays.selectAll('.' + c.cn.axisBrush) + .data(repeat, keyFun); + + axisBrush.enter() + .append('g') + .classed(c.cn.axisBrush, true); + + renderAxisBrush(axisBrush); +} + +function getBrushExtent(brush) { + return brush.svgBrush.extent.map(function(e) {return e.slice();}); +} + +function brushClear(brush) { + brush.filterSpecified = false; + brush.svgBrush.extent = [[0, 1]]; +} + +function axisBrushMoved(callback) { + return function axisBrushMoved(dimension) { + var brush = dimension.brush; + var extent = getBrushExtent(brush); + var newExtent = extent.slice(); + brush.filter.set(newExtent); + callback(); + }; +} + +function dedupeRealRanges(intervals) { + // Fuses elements of intervals if they overlap, yielding discontiguous intervals, results.length <= intervals.length + // Currently uses closed intervals, ie. dedupeRealRanges([[400, 800], [300, 400]]) -> [300, 800] + var queue = intervals.slice(); + var result = []; + var currentInterval; + var current = queue.shift(); + while(current) { // [].shift === undefined, so we don't descend into an empty array + currentInterval = current.slice(); + while((current = queue.shift()) && current[0] <= /* right-open interval would need `<` */ currentInterval[1]) { + currentInterval[1] = Math.max(currentInterval[1], current[1]); + } + result.push(currentInterval); + } + return result; +} + +function makeFilter() { + var filter = []; + var consolidated; + var bounds; + return { + set: function(a) { + filter = a + .map(function(d) { return d.slice().sort(sortAsc); }) + .sort(startAsc); + consolidated = dedupeRealRanges(filter); + bounds = filter.reduce(function(p, n) { + return [Math.min(p[0], n[0]), Math.max(p[1], n[1])]; + }, [Infinity, -Infinity]); + }, + get: function() { return filter.slice(); }, + getConsolidated: function() { return consolidated; }, + getBounds: function() { return bounds; } + }; +} + +function makeBrush(state, rangeSpecified, initialRange, brushStartCallback, brushCallback, brushEndCallback) { + var filter = makeFilter(); + filter.set(initialRange); + return { + filter: filter, + filterSpecified: rangeSpecified, // there's a difference between not filtering and filtering a non-proper subset + svgBrush: { + extent: [], // this is where the svgBrush writes contents into + brushStartCallback: brushStartCallback, + brushCallback: axisBrushMoved(brushCallback), + brushEndCallback: brushEndCallback + } + }; +} + +// for use by supplyDefaults, but it needed tons of pieces from here so +// seemed to make more sense just to put the whole routine here +function cleanRanges(ranges, dimension) { + if(Array.isArray(ranges[0])) { + ranges = ranges.map(function(ri) { return ri.sort(sortAsc); }); + + if(!dimension.multiselect) ranges = [ranges[0]]; + else ranges = dedupeRealRanges(ranges.sort(startAsc)); + } + else ranges = [ranges.sort(sortAsc)]; + + // ordinal snapping + if(dimension.tickvals) { + var sortedTickVals = dimension.tickvals.slice().sort(sortAsc); + ranges = ranges.map(function(ri) { + var rSnapped = [ + ordinalScaleSnapLo(sortedTickVals, ri[0], []), + ordinalScaleSnapHi(sortedTickVals, ri[1], []) + ]; + if(rSnapped[1] > rSnapped[0]) return rSnapped; + }) + .filter(function(ri) { return ri; }); + + if(!ranges.length) return; + } + return ranges.length > 1 ? ranges : ranges[0]; +} + +module.exports = { + makeBrush: makeBrush, + ensureAxisBrush: ensureAxisBrush, + cleanRanges: cleanRanges +}; + +},{"../../lib":696,"../../lib/gup":693,"./constants":1011,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1009:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; +var parcoordsPlot = _dereq_('./plot'); +var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); + +var PARCOORDS = 'parcoords'; + +exports.name = PARCOORDS; + +exports.plot = function(gd) { + var calcData = getModuleCalcData(gd.calcdata, PARCOORDS)[0]; + if(calcData.length) parcoordsPlot(gd, calcData); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadParcoords = (oldFullLayout._has && oldFullLayout._has(PARCOORDS)); + var hasParcoords = (newFullLayout._has && newFullLayout._has(PARCOORDS)); + + if(hadParcoords && !hasParcoords) { + oldFullLayout._paperdiv.selectAll('.parcoords').remove(); + oldFullLayout._glimages.selectAll('*').remove(); + } +}; + +exports.toSVG = function(gd) { + var imageRoot = gd._fullLayout._glimages; + var root = d3.select(gd).selectAll('.svg-container'); + var canvases = root.filter(function(d, i) {return i === root.size() - 1;}) + .selectAll('.gl-canvas-context, .gl-canvas-focus'); + + function canvasToImage() { + var canvas = this; + var imageData = canvas.toDataURL('image/png'); + var image = imageRoot.append('svg:image'); + + image.attr({ + xmlns: xmlnsNamespaces.svg, + 'xlink:href': imageData, + preserveAspectRatio: 'none', + x: 0, + y: 0, + width: canvas.width, + height: canvas.height + }); + } + + canvases.each(canvasToImage); + + // Chrome / Safari bug workaround - browser apparently loses connection to the defined pattern + // Without the workaround, these browsers 'lose' the filter brush styling (color etc.) after a snapshot + // on a subsequent interaction. + // Firefox works fine without this workaround + window.setTimeout(function() { + d3.selectAll('#filterBarPattern') + .attr('id', 'filterBarPattern'); + }, 60); +}; + +},{"../../constants/xmlns_namespaces":674,"../../plots/get_data":781,"./plot":1017,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1010:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var calcColorscale = _dereq_('../../components/colorscale/calc'); +var Lib = _dereq_('../../lib'); +var wrap = _dereq_('../../lib/gup').wrap; + +module.exports = function calc(gd, trace) { + var cs = !!trace.line.colorscale && Lib.isArrayOrTypedArray(trace.line.color); + var color = cs ? trace.line.color : constHalf(trace._length); + var cscale = cs ? trace.line.colorscale : [[0, trace.line.color], [1, trace.line.color]]; + + if(hasColorscale(trace, 'line')) { + calcColorscale(trace, color, 'line', 'c'); + } + + return wrap({ + lineColor: color, + cscale: cscale + }); +}; + +function constHalf(len) { + var out = new Array(len); + for(var i = 0; i < len; i++) { + out[i] = 0.5; + } + return out; +} + +},{"../../components/colorscale/calc":578,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../lib/gup":693}],1011:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + maxDimensionCount: 60, // this cannot be increased without WebGL code refactoring + overdrag: 45, + verticalPadding: 2, // otherwise, horizontal lines on top or bottom are of lower width + tickDistance: 50, + canvasPixelRatio: 1, + blockLineCount: 5000, + layers: ['contextLineLayer', 'focusLineLayer', 'pickLineLayer'], + axisTitleOffset: 28, + axisExtentOffset: 10, + bar: { + width: 4, // Visible width of the filter bar + captureWidth: 10, // Mouse-sensitive width for interaction (Fitts law) + fillColor: 'magenta', // Color of the filter bar fill + fillOpacity: 1, // Filter bar fill opacity + snapDuration: 150, // tween duration in ms for brush snap for ordinal axes + snapRatio: 0.25, // ratio of bar extension relative to the distance between two adjacent ordinal values + snapClose: 0.01, // fraction of inter-value distance to snap to the closer one, even if you're not over it + strokeColor: 'white', // Color of the filter bar side lines + strokeOpacity: 1, // Filter bar side stroke opacity + strokeWidth: 1, // Filter bar side stroke width in pixels + handleHeight: 8, // Height of the filter bar vertical resize areas on top and bottom + handleOpacity: 1, // Opacity of the filter bar vertical resize areas on top and bottom + handleOverlap: 0 // A larger than 0 value causes overlaps with the filter bar, represented as pixels + }, + cn: { + axisExtentText: 'axis-extent-text', + parcoordsLineLayers: 'parcoords-line-layers', + parcoordsLineLayer: 'parcoords-lines', + parcoords: 'parcoords', + parcoordsControlView: 'parcoords-control-view', + yAxis: 'y-axis', + axisOverlays: 'axis-overlays', + axis: 'axis', + axisHeading: 'axis-heading', + axisTitle: 'axis-title', + axisExtent: 'axis-extent', + axisExtentTop: 'axis-extent-top', + axisExtentTopText: 'axis-extent-top-text', + axisExtentBottom: 'axis-extent-bottom', + axisExtentBottomText: 'axis-extent-bottom-text', + axisBrush: 'axis-brush' + }, + id: { + filterBarPattern: 'filter-bar-pattern' + + } +}; + +},{}],1012:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var handleDomainDefaults = _dereq_('../../plots/domain').defaults; +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var axisBrush = _dereq_('./axisbrush'); +var maxDimensionCount = _dereq_('./constants').maxDimensionCount; +var mergeLength = _dereq_('./merge_length'); + +function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { + var lineColor = coerce('line.color', defaultColor); + + if(hasColorscale(traceIn, 'line') && Lib.isArrayOrTypedArray(lineColor)) { + if(lineColor.length) { + coerce('line.colorscale'); + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); + // TODO: I think it would be better to keep showing lines beyond the last line color + // but I'm not sure what color to give these lines - probably black or white + // depending on the background color? + return lineColor.length; + } + else { + traceOut.line.color = defaultColor; + } + } + return Infinity; +} + +function dimensionDefaults(dimensionIn, dimensionOut) { + function coerce(attr, dflt) { + return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); + } + + var values = coerce('values'); + var visible = coerce('visible'); + if(!(values && values.length)) { + visible = dimensionOut.visible = false; + } + + if(visible) { + coerce('label'); + coerce('tickvals'); + coerce('ticktext'); + coerce('tickformat'); + coerce('range'); + + coerce('multiselect'); + var constraintRange = coerce('constraintrange'); + if(constraintRange) { + dimensionOut.constraintrange = axisBrush.cleanRanges(constraintRange, dimensionOut); + } + } +} + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var dimensionsIn = traceIn.dimensions; + if(Array.isArray(dimensionsIn) && dimensionsIn.length > maxDimensionCount) { + Lib.log('parcoords traces support up to ' + maxDimensionCount + ' dimensions at the moment'); + dimensionsIn.splice(maxDimensionCount); + } + + var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { + name: 'dimensions', + handleItemDefaults: dimensionDefaults + }); + + var len = handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + + handleDomainDefaults(traceOut, layout, coerce); + + if(!Array.isArray(dimensions) || !dimensions.length) { + traceOut.visible = false; + } + + mergeLength(traceOut, dimensions, 'values', len); + + // make default font size 10px (default is 12), + // scale linearly with global font size + var fontDflt = { + family: layout.font.family, + size: Math.round(layout.font.size / 1.2), + color: layout.font.color + }; + + Lib.coerceFont(coerce, 'labelfont', fontDflt); + Lib.coerceFont(coerce, 'tickfont', fontDflt); + Lib.coerceFont(coerce, 'rangefont', fontDflt); +}; + +},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/domain":770,"./attributes":1007,"./axisbrush":1008,"./constants":1011,"./merge_length":1015}],1013:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Parcoords = {}; + +Parcoords.attributes = _dereq_('./attributes'); +Parcoords.supplyDefaults = _dereq_('./defaults'); +Parcoords.calc = _dereq_('./calc'); +Parcoords.plot = _dereq_('./plot'); +Parcoords.colorbar = { + container: 'line', + min: 'cmin', + max: 'cmax' +}; + +Parcoords.moduleType = 'trace'; +Parcoords.name = 'parcoords'; +Parcoords.basePlotModule = _dereq_('./base_plot'); +Parcoords.categories = ['gl', 'regl', 'noOpacity']; +Parcoords.meta = { + +}; + +module.exports = Parcoords; + +},{"./attributes":1007,"./base_plot":1009,"./calc":1010,"./defaults":1012,"./plot":1017}],1014:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var glslify = _dereq_('glslify'); +var vertexShaderSource = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D palette;\nuniform sampler2D mask;\nuniform float maskHeight;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec4 unit_1 = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit_1, unit_1);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nconst int bitsPerByte = 8;\n\nint mod2(int a) {\n return a - 2 * (a / 2);\n}\n\nint mod8(int a) {\n return a - 8 * (a / 8);\n}\n\nvec4 zero = vec4(0, 0, 0, 0);\nvec4 unit_0 = vec4(1, 1, 1, 1);\nvec2 xyProjection = vec2(1, 1);\n\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\n return mat4(clamp(m[0], lo[0], hi[0]),\n clamp(m[1], lo[1], hi[1]),\n clamp(m[2], lo[2], hi[2]),\n clamp(m[3], lo[3], hi[3]));\n}\n\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\n return mclamp(p, lo, hi) == p;\n}\n\nbool withinBoundingBox(\n mat4 d[4],\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD\n ) {\n\n return mshow(d[0], loA, hiA) &&\n mshow(d[1], loB, hiB) &&\n mshow(d[2], loC, hiC) &&\n mshow(d[3], loD, hiD);\n}\n\nbool withinRasterMask(mat4 d[4], sampler2D mask, float height) {\n bool result = true;\n int bitInByteStepper;\n float valY, valueY, scaleX;\n int hit, bitmask, valX;\n for(int i = 0; i < 4; i++) {\n for(int j = 0; j < 4; j++) {\n for(int k = 0; k < 4; k++) {\n bitInByteStepper = mod8(j * 4 + k);\n valX = i * 2 + j / 2;\n valY = d[i][j][k];\n valueY = valY * (height - 1.0) + 0.5;\n scaleX = (float(valX) + 0.5) / 8.0;\n hit = int(texture2D(mask, vec2(scaleX, (valueY + 0.5) / height))[3] * 255.0) / int(pow(2.0, float(bitInByteStepper)));\n result = result && mod2(hit) == 1;\n }\n }\n }\n return result;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D,\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD,\n sampler2D mask, float maskHeight\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n float show = float(\n withinBoundingBox(dims, loA, hiA, loB, hiB, loC, hiC, loD, hiD)\n && withinRasterMask(dims, mask, maskHeight)\n );\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n float depthOrHide = depth + 2.0 * (1.0 - show);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depthOrHide,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD,\n mask, maskHeight\n );\n\n float clampedColorIndex = clamp((prominence - colorClamp[0]) / (colorClamp[1] - colorClamp[0]), 0.0, 1.0);\n fragColor = texture2D(palette, vec2((clampedColorIndex * 255.0 + 0.5) / 256.0, 0.5));\n}\n"]); +var contextShaderSource = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D palette;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec2 xyProjection = vec2(1, 1);\n\nvec4 unit = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit, unit);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depth,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D\n );\n\n float clampedColorIndex = clamp((prominence - colorClamp[0]) / (colorClamp[1] - colorClamp[0]), 0.0, 1.0);\n fragColor = texture2D(palette, vec2((clampedColorIndex * 255.0 + 0.5) / 256.0, 0.5));\n}\n"]); +var pickVertexShaderSource = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D mask;\nuniform float maskHeight;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec4 unit_1 = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit_1, unit_1);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nconst int bitsPerByte = 8;\n\nint mod2(int a) {\n return a - 2 * (a / 2);\n}\n\nint mod8(int a) {\n return a - 8 * (a / 8);\n}\n\nvec4 zero = vec4(0, 0, 0, 0);\nvec4 unit_0 = vec4(1, 1, 1, 1);\nvec2 xyProjection = vec2(1, 1);\n\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\n return mat4(clamp(m[0], lo[0], hi[0]),\n clamp(m[1], lo[1], hi[1]),\n clamp(m[2], lo[2], hi[2]),\n clamp(m[3], lo[3], hi[3]));\n}\n\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\n return mclamp(p, lo, hi) == p;\n}\n\nbool withinBoundingBox(\n mat4 d[4],\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD\n ) {\n\n return mshow(d[0], loA, hiA) &&\n mshow(d[1], loB, hiB) &&\n mshow(d[2], loC, hiC) &&\n mshow(d[3], loD, hiD);\n}\n\nbool withinRasterMask(mat4 d[4], sampler2D mask, float height) {\n bool result = true;\n int bitInByteStepper;\n float valY, valueY, scaleX;\n int hit, bitmask, valX;\n for(int i = 0; i < 4; i++) {\n for(int j = 0; j < 4; j++) {\n for(int k = 0; k < 4; k++) {\n bitInByteStepper = mod8(j * 4 + k);\n valX = i * 2 + j / 2;\n valY = d[i][j][k];\n valueY = valY * (height - 1.0) + 0.5;\n scaleX = (float(valX) + 0.5) / 8.0;\n hit = int(texture2D(mask, vec2(scaleX, (valueY + 0.5) / height))[3] * 255.0) / int(pow(2.0, float(bitInByteStepper)));\n result = result && mod2(hit) == 1;\n }\n }\n }\n return result;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D,\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD,\n sampler2D mask, float maskHeight\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n float show = float(\n withinBoundingBox(dims, loA, hiA, loB, hiB, loC, hiC, loD, hiD)\n && withinRasterMask(dims, mask, maskHeight)\n );\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n float depthOrHide = depth + 2.0 * (1.0 - show);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depthOrHide,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD,\n mask, maskHeight\n );\n\n fragColor = vec4(pf.rgb, 1.0);\n}\n"]); +var fragmentShaderSource = glslify(["precision lowp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n gl_FragColor = fragColor;\n}\n"]); + +var Lib = _dereq_('../../lib'); + +// don't change; otherwise near/far plane lines are lost +var depthLimitEpsilon = 1e-6; +// just enough buffer for an extra bit at single-precision floating point +// which on [0, 1] is 6e-8 (1/2^24) +var filterEpsilon = 1e-7; + +// precision of multiselect is the full range divided into this many parts +var maskHeight = 2048; + +var gpuDimensionCount = 64; +var sectionVertexCount = 2; +var vec4NumberCount = 4; +var bitsPerByte = 8; +var channelCount = gpuDimensionCount / bitsPerByte; // == 8 bytes needed to have 64 bits + +var contextColor = [119, 119, 119]; // middle gray to not drawn the focus; looks good on a black or white background + +var dummyPixel = new Uint8Array(4); +var pickPixel = new Uint8Array(4); + +var paletteTextureConfig = { + shape: [256, 1], + format: 'rgba', + type: 'uint8', + mag: 'nearest', + min: 'nearest' +}; + +function ensureDraw(regl) { + regl.read({ + x: 0, + y: 0, + width: 1, + height: 1, + data: dummyPixel + }); +} + +function clear(regl, x, y, width, height) { + var gl = regl._gl; + gl.enable(gl.SCISSOR_TEST); + gl.scissor(x, y, width, height); + regl.clear({color: [0, 0, 0, 0], depth: 1}); // clearing is done in scissored panel only +} + +function renderBlock(regl, glAes, renderState, blockLineCount, sampleCount, item) { + + var rafKey = item.key; + + function render(blockNumber) { + + var count; + + count = Math.min(blockLineCount, sampleCount - blockNumber * blockLineCount); + + item.offset = sectionVertexCount * blockNumber * blockLineCount; + item.count = sectionVertexCount * count; + if(blockNumber === 0) { + // stop drawing possibly stale glyphs before clearing + window.cancelAnimationFrame(renderState.currentRafs[rafKey]); + delete renderState.currentRafs[rafKey]; + clear(regl, item.scissorX, item.scissorY, item.scissorWidth, item.viewBoxSize[1]); + } + + if(renderState.clearOnly) { + return; + } + + glAes(item); + + if(blockNumber * blockLineCount + count < sampleCount) { + renderState.currentRafs[rafKey] = window.requestAnimationFrame(function() { + render(blockNumber + 1); + }); + } + + renderState.drawCompleted = false; + } + + if(!renderState.drawCompleted) { + ensureDraw(regl); + renderState.drawCompleted = true; + } + + // start with rendering item 0; recursion handles the rest + render(0); +} + +function adjustDepth(d) { + // WebGL matrix operations use floats with limited precision, potentially causing a number near a border of [0, 1] + // to end up slightly outside the border. With an epsilon, we reduce the chance that a line gets clipped by the + // near or the far plane. + return Math.max(depthLimitEpsilon, Math.min(1 - depthLimitEpsilon, d)); +} + +function palette(unitToColor, context, opacity) { + var result = []; + for(var j = 0; j < 256; j++) { + var c = unitToColor(j / 255); + result.push((context ? contextColor : c).concat(opacity)); + } + + return result; +} + +// Maps the sample index [0...sampleCount - 1] to a range of [0, 1] as the shader expects colors in the [0, 1] range. +// but first it shifts the sample index by 0, 8 or 16 bits depending on rgbIndex [0..2] +// with the end result that each line will be of a unique color, making it possible for the pick handler +// to uniquely identify which line is hovered over (bijective mapping). +// The inverse, i.e. readPixel is invoked from 'parcoords.js' +function calcPickColor(j, rgbIndex) { + return (j >>> 8 * rgbIndex) % 256 / 255; +} + +function makePoints(sampleCount, dimensions, color) { + var dimensionCount = dimensions.length; + + var points = []; + for(var j = 0; j < sampleCount; j++) { + for(var i = 0; i < gpuDimensionCount; i++) { + points.push(i < dimensionCount ? + dimensions[i].paddedUnitValues[j] : + i === (gpuDimensionCount - 1) ? + adjustDepth(color[j]) : + i >= gpuDimensionCount - 4 ? + calcPickColor(j, gpuDimensionCount - 2 - i) : + 0.5); + } + } + + return points; +} + +function makeVecAttr(sampleCount, points, vecIndex) { + var i, j, k; + var pointPairs = []; + + for(j = 0; j < sampleCount; j++) { + for(k = 0; k < sectionVertexCount; k++) { + for(i = 0; i < vec4NumberCount; i++) { + pointPairs.push(points[j * gpuDimensionCount + vecIndex * vec4NumberCount + i]); + if(vecIndex * vec4NumberCount + i === gpuDimensionCount - 1 && k % 2 === 0) { + pointPairs[pointPairs.length - 1] *= -1; + } + } + } + } + + return pointPairs; +} + +function setAttributes(attributes, sampleCount, points) { + for(var i = 0; i < 16; i++) { + attributes['p' + i.toString(16)](makeVecAttr(sampleCount, points, i)); + } +} + +function emptyAttributes(regl) { + var attributes = {}; + for(var i = 0; i < 16; i++) { + attributes['p' + i.toString(16)] = regl.buffer({usage: 'dynamic', type: 'float', data: new Uint8Array(0)}); + } + return attributes; +} + +module.exports = function(canvasGL, d) { + // context & pick describe which canvas we're talking about - won't change with new data + var context = d.context; + var pick = d.pick; + + var regl = d.regl; + + var renderState = { + currentRafs: {}, + drawCompleted: true, + clearOnly: false + }; + + // state to be set by update and used later + var model; + var vm; + var initialDims; + var sampleCount; + var attributes = emptyAttributes(regl); + var maskTexture; + var paletteTexture = regl.texture(paletteTextureConfig); + + update(d); + + var glAes = regl({ + + profile: false, + + blend: { + enable: context, + func: { + srcRGB: 'src alpha', + dstRGB: 'one minus src alpha', + srcAlpha: 1, + dstAlpha: 1 // 'one minus src alpha' + }, + equation: { + rgb: 'add', + alpha: 'add' + }, + color: [0, 0, 0, 0] + }, + + depth: { + enable: !context, + mask: true, + func: 'less', + range: [0, 1] + }, + + // for polygons + cull: { + enable: true, + face: 'back' + }, + + scissor: { + enable: true, + box: { + x: regl.prop('scissorX'), + y: regl.prop('scissorY'), + width: regl.prop('scissorWidth'), + height: regl.prop('scissorHeight') + } + }, + + viewport: { + x: regl.prop('viewportX'), + y: regl.prop('viewportY'), + width: regl.prop('viewportWidth'), + height: regl.prop('viewportHeight') + }, + + dither: false, + + vert: pick ? pickVertexShaderSource : context ? contextShaderSource : vertexShaderSource, + + frag: fragmentShaderSource, + + primitive: 'lines', + lineWidth: 1, + attributes: attributes, + uniforms: { + resolution: regl.prop('resolution'), + viewBoxPosition: regl.prop('viewBoxPosition'), + viewBoxSize: regl.prop('viewBoxSize'), + dim1A: regl.prop('dim1A'), + dim2A: regl.prop('dim2A'), + dim1B: regl.prop('dim1B'), + dim2B: regl.prop('dim2B'), + dim1C: regl.prop('dim1C'), + dim2C: regl.prop('dim2C'), + dim1D: regl.prop('dim1D'), + dim2D: regl.prop('dim2D'), + loA: regl.prop('loA'), + hiA: regl.prop('hiA'), + loB: regl.prop('loB'), + hiB: regl.prop('hiB'), + loC: regl.prop('loC'), + hiC: regl.prop('hiC'), + loD: regl.prop('loD'), + hiD: regl.prop('hiD'), + palette: paletteTexture, + mask: regl.prop('maskTexture'), + maskHeight: regl.prop('maskHeight'), + colorClamp: regl.prop('colorClamp') + }, + offset: regl.prop('offset'), + count: regl.prop('count') + }); + + function update(dNew) { + model = dNew.model; + vm = dNew.viewModel; + initialDims = vm.dimensions.slice(); + sampleCount = initialDims[0] ? initialDims[0].values.length : 0; + + var lines = model.lines; + var color = pick ? lines.color.map(function(_, i) {return i / lines.color.length;}) : lines.color; + var contextOpacity = Math.max(1 / 255, Math.pow(1 / color.length, 1 / 3)); + + var points = makePoints(sampleCount, initialDims, color); + setAttributes(attributes, sampleCount, points); + + paletteTexture = regl.texture(Lib.extendFlat({ + data: palette(model.unitToColor, context, Math.round((context ? contextOpacity : 1) * 255)) + }, paletteTextureConfig)); + } + + var colorClamp = [0, 1]; + + function setColorDomain(unitDomain) { + colorClamp[0] = unitDomain[0]; + colorClamp[1] = unitDomain[1]; + } + + var previousAxisOrder = []; + + function makeItem(i, ii, x, y, panelSizeX, canvasPanelSizeY, crossfilterDimensionIndex, I, leftmost, rightmost, constraints) { + var loHi, abcd, d, index; + var leftRight = [i, ii]; + + var dims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});}); + + for(loHi = 0; loHi < 2; loHi++) { + index = leftRight[loHi]; + for(abcd = 0; abcd < 4; abcd++) { + for(d = 0; d < 16; d++) { + dims[loHi][abcd][d] = d + 16 * abcd === index ? 1 : 0; + } + } + } + + var overdrag = model.lines.canvasOverdrag; + var domain = model.domain; + var canvasWidth = model.canvasWidth; + var canvasHeight = model.canvasHeight; + + var itemModel = Lib.extendFlat({ + key: crossfilterDimensionIndex, + resolution: [canvasWidth, canvasHeight], + viewBoxPosition: [x + overdrag, y], + viewBoxSize: [panelSizeX, canvasPanelSizeY], + i: i, + ii: ii, + + dim1A: dims[0][0], + dim1B: dims[0][1], + dim1C: dims[0][2], + dim1D: dims[0][3], + dim2A: dims[1][0], + dim2B: dims[1][1], + dim2C: dims[1][2], + dim2D: dims[1][3], + + colorClamp: colorClamp, + + scissorX: (I === leftmost ? 0 : x + overdrag) + (model.pad.l - overdrag) + model.layoutWidth * domain.x[0], + scissorWidth: (I === rightmost ? canvasWidth - x + overdrag : panelSizeX + 0.5) + (I === leftmost ? x + overdrag : 0), + scissorY: y + model.pad.b + model.layoutHeight * domain.y[0], + scissorHeight: canvasPanelSizeY, + + viewportX: model.pad.l - overdrag + model.layoutWidth * domain.x[0], + viewportY: model.pad.b + model.layoutHeight * domain.y[0], + viewportWidth: canvasWidth, + viewportHeight: canvasHeight + }, constraints); + + return itemModel; + } + + function makeConstraints() { + var loHi, abcd, d; + + var lims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});}); + + for(loHi = 0; loHi < 2; loHi++) { + for(abcd = 0; abcd < 4; abcd++) { + for(d = 0; d < 16; d++) { + var dimP = d + 16 * abcd; + var lim; + if(dimP < initialDims.length) { + lim = initialDims[dimP].brush.filter.getBounds()[loHi]; + } + else lim = loHi; + lims[loHi][abcd][d] = lim + (2 * loHi - 1) * filterEpsilon; + } + } + } + + function expandedPixelRange(dim, bounds) { + var maskHMinus = maskHeight - 1; + return [ + Math.max(0, Math.floor(bounds[0] * maskHMinus)), + Math.min(maskHMinus, Math.ceil(bounds[1] * maskHMinus)) + ]; + } + + var mask = Array.apply(null, new Array(maskHeight * channelCount)).map(function() { + return 255; + }); + for(var dimIndex = 0; dimIndex < initialDims.length; dimIndex++) { + var bitIndex = dimIndex % bitsPerByte; + var byteIndex = (dimIndex - bitIndex) / bitsPerByte; + var bitMask = Math.pow(2, bitIndex); + var dim = initialDims[dimIndex]; + var ranges = dim.brush.filter.get(); + if(ranges.length < 2) continue; // bail if the bounding box based filter is sufficient + + var prevEnd = expandedPixelRange(dim, ranges[0])[1]; + for(var ri = 1; ri < ranges.length; ri++) { + var nextRange = expandedPixelRange(dim, ranges[ri]); + for(var pi = prevEnd + 1; pi < nextRange[0]; pi++) { + mask[pi * channelCount + byteIndex] &= ~bitMask; + } + prevEnd = Math.max(prevEnd, nextRange[1]); + } + } + + var textureData = { + // 8 units x 8 bits = 64 bits, just sufficient for the almost 64 dimensions we support + shape: [channelCount, maskHeight], + format: 'alpha', + type: 'uint8', + mag: 'nearest', + min: 'nearest', + data: mask + }; + if(maskTexture) maskTexture(textureData); + else maskTexture = regl.texture(textureData); + + return { + maskTexture: maskTexture, + maskHeight: maskHeight, + loA: lims[0][0], + loB: lims[0][1], + loC: lims[0][2], + loD: lims[0][3], + hiA: lims[1][0], + hiB: lims[1][1], + hiC: lims[1][2], + hiD: lims[1][3] + }; + } + + function renderGLParcoords(panels, setChanged, clearOnly) { + var panelCount = panels.length; + var I; + + var leftmost, rightmost, lowestX = Infinity, highestX = -Infinity; + + for(I = 0; I < panelCount; I++) { + if(panels[I].dim2.canvasX > highestX) { + highestX = panels[I].dim2.canvasX; + rightmost = I; + } + if(panels[I].dim1.canvasX < lowestX) { + lowestX = panels[I].dim1.canvasX; + leftmost = I; + } + } + + if(panelCount === 0) { + // clear canvas here, as the panel iteration below will not enter the loop body + clear(regl, 0, 0, model.canvasWidth, model.canvasHeight); + } + var constraints = context ? {} : makeConstraints(); + + for(I = 0; I < panelCount; I++) { + var panel = panels[I]; + var dim1 = panel.dim1; + var i = dim1.crossfilterDimensionIndex; + var x = panel.canvasX; + var y = panel.canvasY; + var dim2 = panel.dim2; + var ii = dim2.crossfilterDimensionIndex; + var panelSizeX = panel.panelSizeX; + var panelSizeY = panel.panelSizeY; + var xTo = x + panelSizeX; + if(setChanged || !previousAxisOrder[i] || previousAxisOrder[i][0] !== x || previousAxisOrder[i][1] !== xTo) { + previousAxisOrder[i] = [x, xTo]; + var item = makeItem(i, ii, x, y, panelSizeX, panelSizeY, dim1.crossfilterDimensionIndex, I, leftmost, rightmost, constraints); + renderState.clearOnly = clearOnly; + renderBlock(regl, glAes, renderState, setChanged ? model.lines.blockLineCount : sampleCount, sampleCount, item); + } + } + } + + function readPixel(canvasX, canvasY) { + regl.read({ + x: canvasX, + y: canvasY, + width: 1, + height: 1, + data: pickPixel + }); + return pickPixel; + } + + function readPixels(canvasX, canvasY, width, height) { + var pixelArray = new Uint8Array(4 * width * height); + regl.read({ + x: canvasX, + y: canvasY, + width: width, + height: height, + data: pixelArray + }); + return pixelArray; + } + + function destroy() { + canvasGL.style['pointer-events'] = 'none'; + paletteTexture.destroy(); + if(maskTexture) maskTexture.destroy(); + for(var k in attributes) attributes[k].destroy(); + } + + return { + setColorDomain: setColorDomain, + render: renderGLParcoords, + readPixel: readPixel, + readPixels: readPixels, + destroy: destroy, + update: update + }; +}; + +},{"../../lib":696,"glslify":392}],1015:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * mergeLength: set trace length as the minimum of all dimension data lengths + * and propagates this length into each dimension + * + * @param {object} traceOut: the fullData trace + * @param {Array(object)} dimensions: array of dimension objects + * @param {string} dataAttr: the attribute of each dimension containing the data + * @param {integer} len: an already-existing length from other attributes + */ +module.exports = function(traceOut, dimensions, dataAttr, len) { + if(!len) len = Infinity; + var i, dimi; + for(i = 0; i < dimensions.length; i++) { + dimi = dimensions[i]; + if(dimi.visible) len = Math.min(len, dimi[dataAttr].length); + } + if(len === Infinity) len = 0; + + traceOut._length = len; + for(i = 0; i < dimensions.length; i++) { + dimi = dimensions[i]; + if(dimi.visible) dimi._length = len; + } + + return len; +}; + +},{}],1016:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var lineLayerMaker = _dereq_('./lines'); +var c = _dereq_('./constants'); +var Lib = _dereq_('../../lib'); +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../../components/drawing'); +var gup = _dereq_('../../lib/gup'); +var keyFun = gup.keyFun; +var repeat = gup.repeat; +var unwrap = gup.unwrap; +var brush = _dereq_('./axisbrush'); + +function visible(dimension) { return !('visible' in dimension) || dimension.visible; } + +function dimensionExtent(dimension) { + + var lo = dimension.range ? dimension.range[0] : Lib.aggNums(Math.min, null, dimension.values, dimension._length); + var hi = dimension.range ? dimension.range[1] : Lib.aggNums(Math.max, null, dimension.values, dimension._length); + + if(isNaN(lo) || !isFinite(lo)) { + lo = 0; + } + + if(isNaN(hi) || !isFinite(hi)) { + hi = 0; + } + + // avoid a degenerate (zero-width) domain + if(lo === hi) { + if(lo === 0) { + // no use to multiplying zero, so add/subtract in this case + lo -= 1; + hi += 1; + } else { + // this keeps the range in the order of magnitude of the data + lo *= 0.9; + hi *= 1.1; + } + } + + return [lo, hi]; +} + +function toText(formatter, texts) { + if(texts) { + return function(v, i) { + var text = texts[i]; + if(text === null || text === undefined) return formatter(v); + return text; + }; + } + return formatter; +} + +function domainScale(height, padding, dimension, tickvals, ticktext) { + var extent = dimensionExtent(dimension); + if(tickvals) { + return d3.scale.ordinal() + .domain(tickvals.map(toText(d3.format(dimension.tickformat), ticktext))) + .range(tickvals + .map(function(d) { + var unitVal = (d - extent[0]) / (extent[1] - extent[0]); + return (height - padding + unitVal * (2 * padding - height)); + }) + ); + } + return d3.scale.linear() + .domain(extent) + .range([height - padding, padding]); +} + +function unitToPaddedPx(height, padding) { return d3.scale.linear().range([padding, height - padding]); } + +function domainToPaddedUnitScale(dimension, padFraction) { + return d3.scale.linear() + .domain(dimensionExtent(dimension)) + .range([padFraction, 1 - padFraction]); +} + +function ordinalScale(dimension) { + if(!dimension.tickvals) return; + + var extent = dimensionExtent(dimension); + return d3.scale.ordinal() + .domain(dimension.tickvals) + .range(dimension.tickvals.map(function(d) { + return (d - extent[0]) / (extent[1] - extent[0]); + })); +} + +function unitToColorScale(cscale) { + + var colorStops = cscale.map(function(d) { return d[0]; }); + var colorTuples = cscale.map(function(d) { return d3.rgb(d[1]); }); + var prop = function(n) { return function(o) { return o[n]; }; }; + + // We can't use d3 color interpolation as we may have non-uniform color palette raster + // (various color stop distances). + var polylinearUnitScales = 'rgb'.split('').map(function(key) { + return d3.scale.linear() + .clamp(true) + .domain(colorStops) + .range(colorTuples.map(prop(key))); + }); + + return function(d) { + return polylinearUnitScales.map(function(s) { + return s(d); + }); + }; +} + +function someFiltersActive(view) { + return view.dimensions.some(function(p) { + return p.brush.filterSpecified; + }); +} + +function model(layout, d, i) { + var cd0 = unwrap(d), + trace = cd0.trace, + lineColor = cd0.lineColor, + cscale = cd0.cscale, + line = trace.line, + domain = trace.domain, + dimensions = trace.dimensions, + width = layout.width, + labelFont = trace.labelfont, + tickFont = trace.tickfont, + rangeFont = trace.rangefont; + + var lines = Lib.extendDeepNoArrays({}, line, { + color: lineColor.map(d3.scale.linear().domain(dimensionExtent({ + values: lineColor, + range: [line.cmin, line.cmax], + _length: trace._length + }))), + blockLineCount: c.blockLineCount, + canvasOverdrag: c.overdrag * c.canvasPixelRatio + }); + + var groupWidth = Math.floor(width * (domain.x[1] - domain.x[0])); + var groupHeight = Math.floor(layout.height * (domain.y[1] - domain.y[0])); + + var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; + var rowContentWidth = groupWidth; + var rowHeight = groupHeight; + + return { + key: i, + colCount: dimensions.filter(visible).length, + dimensions: dimensions, + tickDistance: c.tickDistance, + unitToColor: unitToColorScale(cscale), + lines: lines, + labelFont: labelFont, + tickFont: tickFont, + rangeFont: rangeFont, + layoutWidth: width, + layoutHeight: layout.height, + domain: domain, + translateX: domain.x[0] * width, + translateY: layout.height - domain.y[1] * layout.height, + pad: pad, + canvasWidth: rowContentWidth * c.canvasPixelRatio + 2 * lines.canvasOverdrag, + canvasHeight: rowHeight * c.canvasPixelRatio, + width: rowContentWidth, + height: rowHeight, + canvasPixelRatio: c.canvasPixelRatio + }; +} + +function viewModel(state, callbacks, model) { + + var width = model.width; + var height = model.height; + var dimensions = model.dimensions; + var canvasPixelRatio = model.canvasPixelRatio; + + var xScale = function(d) {return width * d / Math.max(1, model.colCount - 1);}; + + var unitPad = c.verticalPadding / height; + var _unitToPaddedPx = unitToPaddedPx(height, c.verticalPadding); + + var viewModel = { + key: model.key, + xScale: xScale, + model: model, + inBrushDrag: false // consider factoring it out and putting it in a centralized global-ish gesture state object + }; + + var uniqueKeys = {}; + + viewModel.dimensions = dimensions.filter(visible).map(function(dimension, i) { + var domainToPaddedUnit = domainToPaddedUnitScale(dimension, unitPad); + var foundKey = uniqueKeys[dimension.label]; + uniqueKeys[dimension.label] = (foundKey || 0) + 1; + var key = dimension.label + (foundKey ? '__' + foundKey : ''); + var specifiedConstraint = dimension.constraintrange; + var filterRangeSpecified = specifiedConstraint && specifiedConstraint.length; + if(filterRangeSpecified && !Array.isArray(specifiedConstraint[0])) { + specifiedConstraint = [specifiedConstraint]; + } + var filterRange = filterRangeSpecified ? + specifiedConstraint.map(function(d) { return d.map(domainToPaddedUnit); }) : + [[0, 1]]; + var brushMove = function() { + var p = viewModel; + p.focusLayer && p.focusLayer.render(p.panels, true); + var filtersActive = someFiltersActive(p); + if(!state.contextShown() && filtersActive) { + p.contextLayer && p.contextLayer.render(p.panels, true); + state.contextShown(true); + } else if(state.contextShown() && !filtersActive) { + p.contextLayer && p.contextLayer.render(p.panels, true, true); + state.contextShown(false); + } + }; + + var truncatedValues = dimension.values; + if(truncatedValues.length > dimension._length) { + truncatedValues = truncatedValues.slice(0, dimension._length); + } + + var tickvals = dimension.tickvals; + var ticktext; + function makeTickItem(v, i) { return {val: v, text: ticktext[i]}; } + function sortTickItem(a, b) { return a.val - b.val; } + if(Array.isArray(tickvals) && tickvals.length) { + ticktext = dimension.ticktext; + + // ensure ticktext and tickvals have same length + if(!Array.isArray(ticktext) || !ticktext.length) { + ticktext = tickvals.map(d3.format(dimension.tickformat)); + } + else if(ticktext.length > tickvals.length) { + ticktext = ticktext.slice(0, tickvals.length); + } + else if(tickvals.length > ticktext.length) { + tickvals = tickvals.slice(0, ticktext.length); + } + + // check if we need to sort tickvals/ticktext + for(var j = 1; j < tickvals.length; j++) { + if(tickvals[j] < tickvals[j - 1]) { + var tickItems = tickvals.map(makeTickItem).sort(sortTickItem); + for(var k = 0; k < tickvals.length; k++) { + tickvals[k] = tickItems[k].val; + ticktext[k] = tickItems[k].text; + } + break; + } + } + } + else tickvals = undefined; + + return { + key: key, + label: dimension.label, + tickFormat: dimension.tickformat, + tickvals: tickvals, + ticktext: ticktext, + ordinal: !!tickvals, + multiselect: dimension.multiselect, + xIndex: i, + crossfilterDimensionIndex: i, + visibleIndex: dimension._index, + height: height, + values: truncatedValues, + paddedUnitValues: truncatedValues.map(domainToPaddedUnit), + unitTickvals: tickvals && tickvals.map(domainToPaddedUnit), + xScale: xScale, + x: xScale(i), + canvasX: xScale(i) * canvasPixelRatio, + unitToPaddedPx: _unitToPaddedPx, + domainScale: domainScale(height, c.verticalPadding, dimension, tickvals, ticktext), + ordinalScale: ordinalScale(dimension), + parent: viewModel, + model: model, + brush: brush.makeBrush( + state, + filterRangeSpecified, + filterRange, + function() { + state.linePickActive(false); + }, + brushMove, + function(f) { + var p = viewModel; + p.focusLayer.render(p.panels, true); + p.pickLayer && p.pickLayer.render(p.panels, true); + state.linePickActive(true); + if(callbacks && callbacks.filterChanged) { + var invScale = domainToPaddedUnit.invert; + + // update gd.data as if a Plotly.restyle were fired + var newRanges = f.map(function(r) { + return r.map(invScale).sort(Lib.sorterAsc); + }).sort(function(a, b) { return a[0] - b[0]; }); + callbacks.filterChanged(p.key, dimension._index, newRanges); + } + } + ) + }; + }); + + return viewModel; +} + +function styleExtentTexts(selection) { + selection + .classed(c.cn.axisExtentText, true) + .attr('text-anchor', 'middle') + .style('cursor', 'default') + .style('user-select', 'none'); +} + +function parcoordsInteractionState() { + var linePickActive = true; + var contextShown = false; + return { + linePickActive: function(val) {return arguments.length ? linePickActive = !!val : linePickActive;}, + contextShown: function(val) {return arguments.length ? contextShown = !!val : contextShown;} + }; +} + +module.exports = function(root, svg, parcoordsLineLayers, styledData, layout, callbacks) { + + var state = parcoordsInteractionState(); + + var vm = styledData + .filter(function(d) { return unwrap(d).trace.visible; }) + .map(model.bind(0, layout)) + .map(viewModel.bind(0, state, callbacks)); + + parcoordsLineLayers.each(function(d, i) { + return Lib.extendFlat(d, vm[i]); + }); + + var parcoordsLineLayer = parcoordsLineLayers.selectAll('.gl-canvas') + .each(function(d) { + // FIXME: figure out how to handle multiple instances + d.viewModel = vm[0]; + d.model = d.viewModel ? d.viewModel.model : null; + }); + + var lastHovered = null; + + var pickLayer = parcoordsLineLayer.filter(function(d) {return d.pick;}); + + // emit hover / unhover event + pickLayer + .style('pointer-events', 'auto') + .on('mousemove', function(d) { + if(state.linePickActive() && d.lineLayer && callbacks && callbacks.hover) { + var event = d3.event; + var cw = this.width; + var ch = this.height; + var pointer = d3.mouse(this); + var x = pointer[0]; + var y = pointer[1]; + + if(x < 0 || y < 0 || x >= cw || y >= ch) { + return; + } + var pixel = d.lineLayer.readPixel(x, ch - 1 - y); + var found = pixel[3] !== 0; + // inverse of the calcPickColor in `lines.js`; detailed comment there + var curveNumber = found ? pixel[2] + 256 * (pixel[1] + 256 * pixel[0]) : null; + var eventData = { + x: x, + y: y, + clientX: event.clientX, + clientY: event.clientY, + dataIndex: d.model.key, + curveNumber: curveNumber + }; + if(curveNumber !== lastHovered) { // don't unnecessarily repeat the same hit (or miss) + if(found) { + callbacks.hover(eventData); + } else if(callbacks.unhover) { + callbacks.unhover(eventData); + } + lastHovered = curveNumber; + } + } + }); + + parcoordsLineLayer + .style('opacity', function(d) {return d.pick ? 0.01 : 1;}); + + svg.style('background', 'rgba(255, 255, 255, 0)'); + var parcoordsControlOverlay = svg.selectAll('.' + c.cn.parcoords) + .data(vm, keyFun); + + parcoordsControlOverlay.exit().remove(); + + parcoordsControlOverlay.enter() + .append('g') + .classed(c.cn.parcoords, true) + .style('shape-rendering', 'crispEdges') + .style('pointer-events', 'none'); + + parcoordsControlOverlay.attr('transform', function(d) { + return 'translate(' + d.model.translateX + ',' + d.model.translateY + ')'; + }); + + var parcoordsControlView = parcoordsControlOverlay.selectAll('.' + c.cn.parcoordsControlView) + .data(repeat, keyFun); + + parcoordsControlView.enter() + .append('g') + .classed(c.cn.parcoordsControlView, true); + + parcoordsControlView.attr('transform', function(d) { + return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')'; + }); + + var yAxis = parcoordsControlView.selectAll('.' + c.cn.yAxis) + .data(function(vm) { return vm.dimensions; }, keyFun); + + function updatePanelLayout(yAxis, vm) { + var panels = vm.panels || (vm.panels = []); + var dimData = yAxis.data(); + var panelCount = dimData.length - 1; + for(var p = 0; p < panelCount; p++) { + var panel = panels[p] || (panels[p] = {}); + var dim1 = dimData[p]; + var dim2 = dimData[p + 1]; + panel.dim1 = dim1; + panel.dim2 = dim2; + panel.canvasX = dim1.canvasX; + panel.panelSizeX = dim2.canvasX - dim1.canvasX; + panel.panelSizeY = vm.model.canvasHeight; + panel.y = 0; + panel.canvasY = 0; + } + } + + yAxis.enter() + .append('g') + .classed(c.cn.yAxis, true); + + parcoordsControlView.each(function(vm) { + updatePanelLayout(yAxis, vm); + }); + + parcoordsLineLayer + .each(function(d) { + if(d.viewModel) { + if(!d.lineLayer || callbacks) { // recreate in case of having callbacks e.g. restyle. Should we test for callback to be a restyle? + d.lineLayer = lineLayerMaker(this, d); + } else d.lineLayer.update(d); + + if(d.key || d.key === 0) d.viewModel[d.key] = d.lineLayer; + + var setChanged = (!d.context || // don't update background + callbacks); // unless there is a callback on the context layer. Should we test the callback? + + d.lineLayer.render(d.viewModel.panels, setChanged); + } + }); + + yAxis.attr('transform', function(d) { + return 'translate(' + d.xScale(d.xIndex) + ', 0)'; + }); + + // drag column for reordering columns + yAxis.call(d3.behavior.drag() + .origin(function(d) { return d; }) + .on('drag', function(d) { + var p = d.parent; + state.linePickActive(false); + d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag, d3.event.x)); + d.canvasX = d.x * d.model.canvasPixelRatio; + yAxis + .sort(function(a, b) { return a.x - b.x; }) + .each(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd.xIndex); + dd.canvasX = dd.x * dd.model.canvasPixelRatio; + }); + + updatePanelLayout(yAxis, p); + + yAxis.filter(function(dd) { return Math.abs(d.xIndex - dd.xIndex) !== 0; }) + .attr('transform', function(d) { return 'translate(' + d.xScale(d.xIndex) + ', 0)'; }); + d3.select(this).attr('transform', 'translate(' + d.x + ', 0)'); + yAxis.each(function(dd, i, ii) { if(ii === d.parent.key) p.dimensions[i] = dd; }); + p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); + p.focusLayer.render && p.focusLayer.render(p.panels); + }) + .on('dragend', function(d) { + var p = d.parent; + d.x = d.xScale(d.xIndex); + d.canvasX = d.x * d.model.canvasPixelRatio; + updatePanelLayout(yAxis, p); + d3.select(this) + .attr('transform', function(d) { return 'translate(' + d.x + ', 0)'; }); + p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); + p.focusLayer && p.focusLayer.render(p.panels); + p.pickLayer && p.pickLayer.render(p.panels, true); + state.linePickActive(true); + + if(callbacks && callbacks.axesMoved) { + callbacks.axesMoved(p.key, p.dimensions.map(function(dd) {return dd.crossfilterDimensionIndex;})); + } + }) + ); + + yAxis.exit() + .remove(); + + var axisOverlays = yAxis.selectAll('.' + c.cn.axisOverlays) + .data(repeat, keyFun); + + axisOverlays.enter() + .append('g') + .classed(c.cn.axisOverlays, true); + + axisOverlays.selectAll('.' + c.cn.axis).remove(); + + var axis = axisOverlays.selectAll('.' + c.cn.axis) + .data(repeat, keyFun); + + axis.enter() + .append('g') + .classed(c.cn.axis, true); + + axis + .each(function(d) { + var wantedTickCount = d.model.height / d.model.tickDistance; + var scale = d.domainScale; + var sdom = scale.domain(); + d3.select(this) + .call(d3.svg.axis() + .orient('left') + .tickSize(4) + .outerTickSize(2) + .ticks(wantedTickCount, d.tickFormat) // works for continuous scales only... + .tickValues(d.ordinal ? // and this works for ordinal scales + sdom : + null) + .tickFormat(d.ordinal ? function(d) { return d; } : null) + .scale(scale)); + Drawing.font(axis.selectAll('text'), d.model.tickFont); + }); + + axis.selectAll('.domain, .tick>line') + .attr('fill', 'none') + .attr('stroke', 'black') + .attr('stroke-opacity', 0.25) + .attr('stroke-width', '1px'); + + axis.selectAll('text') + .style('text-shadow', '1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff') + .style('cursor', 'default') + .style('user-select', 'none'); + + var axisHeading = axisOverlays.selectAll('.' + c.cn.axisHeading) + .data(repeat, keyFun); + + axisHeading.enter() + .append('g') + .classed(c.cn.axisHeading, true); + + var axisTitle = axisHeading.selectAll('.' + c.cn.axisTitle) + .data(repeat, keyFun); + + axisTitle.enter() + .append('text') + .classed(c.cn.axisTitle, true) + .attr('text-anchor', 'middle') + .style('cursor', 'ew-resize') + .style('user-select', 'none') + .style('pointer-events', 'auto'); + + axisTitle + .attr('transform', 'translate(0,' + -c.axisTitleOffset + ')') + .text(function(d) { return d.label; }) + .each(function(d) { Drawing.font(d3.select(this), d.model.labelFont); }); + + var axisExtent = axisOverlays.selectAll('.' + c.cn.axisExtent) + .data(repeat, keyFun); + + axisExtent.enter() + .append('g') + .classed(c.cn.axisExtent, true); + + var axisExtentTop = axisExtent.selectAll('.' + c.cn.axisExtentTop) + .data(repeat, keyFun); + + axisExtentTop.enter() + .append('g') + .classed(c.cn.axisExtentTop, true); + + axisExtentTop + .attr('transform', 'translate(' + 0 + ',' + -c.axisExtentOffset + ')'); + + var axisExtentTopText = axisExtentTop.selectAll('.' + c.cn.axisExtentTopText) + .data(repeat, keyFun); + + function extremeText(d, isTop) { + if(d.ordinal) return ''; + var domain = d.domainScale.domain(); + return d3.format(d.tickFormat)(domain[isTop ? domain.length - 1 : 0]); + } + + axisExtentTopText.enter() + .append('text') + .classed(c.cn.axisExtentTopText, true) + .call(styleExtentTexts); + + axisExtentTopText + .text(function(d) { return extremeText(d, true); }) + .each(function(d) { Drawing.font(d3.select(this), d.model.rangeFont); }); + + var axisExtentBottom = axisExtent.selectAll('.' + c.cn.axisExtentBottom) + .data(repeat, keyFun); + + axisExtentBottom.enter() + .append('g') + .classed(c.cn.axisExtentBottom, true); + + axisExtentBottom + .attr('transform', function(d) { + return 'translate(' + 0 + ',' + (d.model.height + c.axisExtentOffset) + ')'; + }); + + var axisExtentBottomText = axisExtentBottom.selectAll('.' + c.cn.axisExtentBottomText) + .data(repeat, keyFun); + + axisExtentBottomText.enter() + .append('text') + .classed(c.cn.axisExtentBottomText, true) + .attr('dy', '0.75em') + .call(styleExtentTexts); + + axisExtentBottomText + .text(function(d) { return extremeText(d); }) + .each(function(d) { Drawing.font(d3.select(this), d.model.rangeFont); }); + + brush.ensureAxisBrush(axisOverlays); +}; + +},{"../../components/drawing":595,"../../lib":696,"../../lib/gup":693,"./axisbrush":1008,"./constants":1011,"./lines":1014,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1017:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var parcoords = _dereq_('./parcoords'); +var prepareRegl = _dereq_('../../lib/prepare_regl'); + +module.exports = function plot(gd, cdparcoords) { + var fullLayout = gd._fullLayout; + var svg = fullLayout._toppaper; + var root = fullLayout._paperdiv; + var container = fullLayout._glcontainer; + + var success = prepareRegl(gd); + if(!success) return; + + var gdDimensions = {}; + var gdDimensionsOriginalOrder = {}; + + var size = fullLayout._size; + + cdparcoords.forEach(function(d, i) { + gdDimensions[i] = gd.data[i].dimensions; + gdDimensionsOriginalOrder[i] = gd.data[i].dimensions.slice(); + }); + + var filterChanged = function(i, originalDimensionIndex, newRanges) { + + // Have updated `constraintrange` data on `gd.data` and raise `Plotly.restyle` event + // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call + + var gdDimension = gdDimensionsOriginalOrder[i][originalDimensionIndex]; + var newConstraints = newRanges.map(function(r) { return r.slice(); }); + if(!newConstraints.length) { + delete gdDimension.constraintrange; + newConstraints = null; + } + else { + if(newConstraints.length === 1) newConstraints = newConstraints[0]; + gdDimension.constraintrange = newConstraints; + // wrap in another array for restyle event data + newConstraints = [newConstraints]; + } + + var restyleData = {}; + var aStr = 'dimensions[' + originalDimensionIndex + '].constraintrange'; + restyleData[aStr] = newConstraints; + gd.emit('plotly_restyle', [restyleData, [i]]); + }; + + var hover = function(eventData) { + gd.emit('plotly_hover', eventData); + }; + + var unhover = function(eventData) { + gd.emit('plotly_unhover', eventData); + }; + + var axesMoved = function(i, visibleIndices) { + + // Have updated order data on `gd.data` and raise `Plotly.restyle` event + // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call + + function visible(dimension) {return !('visible' in dimension) || dimension.visible;} + + function newIdx(visibleIndices, orig, dim) { + var origIndex = orig.indexOf(dim); + var currentIndex = visibleIndices.indexOf(origIndex); + if(currentIndex === -1) { + // invisible dimensions initially go to the end + currentIndex += orig.length; + } + return currentIndex; + } + + function sorter(orig) { + return function sorter(d1, d2) { + var i1 = newIdx(visibleIndices, orig, d1); + var i2 = newIdx(visibleIndices, orig, d2); + return i1 - i2; + }; + } + + // drag&drop sorting of the visible dimensions + var orig = sorter(gdDimensionsOriginalOrder[i].filter(visible)); + gdDimensions[i].sort(orig); + + // invisible dimensions are not interpreted in the context of drag&drop sorting as an invisible dimension + // cannot be dragged; they're interspersed into their original positions by this subsequent merging step + gdDimensionsOriginalOrder[i].filter(function(d) {return !visible(d);}) + .sort(function(d) { + // subsequent splicing to be done left to right, otherwise indices may be incorrect + return gdDimensionsOriginalOrder[i].indexOf(d); + }) + .forEach(function(d) { + gdDimensions[i].splice(gdDimensions[i].indexOf(d), 1); // remove from the end + gdDimensions[i].splice(gdDimensionsOriginalOrder[i].indexOf(d), 0, d); // insert at original index + }); + + gd.emit('plotly_restyle'); + }; + + parcoords( + root, + svg, + container, + cdparcoords, + { + width: size.w, + height: size.h, + margin: { + t: size.t, + r: size.r, + b: size.b, + l: size.l + } + }, + { + filterChanged: filterChanged, + hover: hover, + unhover: unhover, + axesMoved: axesMoved + }); +}; + +},{"../../lib/prepare_regl":709,"./parcoords":1016}],1018:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = _dereq_('../../components/color/attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var domainAttrs = _dereq_('../../plots/domain').attributes; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var textFontAttrs = fontAttrs({ + editType: 'calc', + arrayOk: true, + colorEditType: 'plot', + +}); + +module.exports = { + labels: { + valType: 'data_array', + editType: 'calc', + + }, + // equivalent of x0 and dx, if label is missing + label0: { + valType: 'number', + + dflt: 0, + editType: 'calc', + + }, + dlabel: { + valType: 'number', + + dflt: 1, + editType: 'calc', + + }, + + values: { + valType: 'data_array', + editType: 'calc', + + }, + + marker: { + colors: { + valType: 'data_array', // TODO 'color_array' ? + editType: 'calc', + + }, + + line: { + color: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + arrayOk: true, + editType: 'style', + + }, + width: { + valType: 'number', + + min: 0, + dflt: 0, + arrayOk: true, + editType: 'style', + + }, + editType: 'calc' + }, + editType: 'calc' + }, + + text: { + valType: 'data_array', + editType: 'calc', + + }, + hovertext: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'style', + + }, + +// 'see eg:' +// 'https://www.e-education.psu.edu/natureofgeoinfo/sites/www.e-education.psu.edu.natureofgeoinfo/files/image/hisp_pies.gif', +// '(this example involves a map too - may someday be a whole trace type', +// 'of its own. but the point is the size of the whole pie is important.)' + scalegroup: { + valType: 'string', + + dflt: '', + editType: 'calc', + + }, + + // labels (legend is handled by plots.attributes.showlegend and layout.hiddenlabels) + textinfo: { + valType: 'flaglist', + + flags: ['label', 'text', 'value', 'percent'], + extras: ['none'], + editType: 'calc', + + }, + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['label', 'text', 'value', 'percent', 'name'] + }), + textposition: { + valType: 'enumerated', + + values: ['inside', 'outside', 'auto', 'none'], + dflt: 'auto', + arrayOk: true, + editType: 'calc', + + }, + textfont: extendFlat({}, textFontAttrs, { + + }), + insidetextfont: extendFlat({}, textFontAttrs, { + + }), + outsidetextfont: extendFlat({}, textFontAttrs, { + + }), + + title: { + valType: 'string', + dflt: '', + + editType: 'calc', + + }, + titleposition: { + valType: 'enumerated', + values: [ + 'top left', 'top center', 'top right', + 'middle center', + 'bottom left', 'bottom center', 'bottom right' + ], + + editType: 'calc', + + }, + titlefont: extendFlat({}, textFontAttrs, { + + }), + + // position and shape + domain: domainAttrs({name: 'pie', trace: true, editType: 'calc'}), + + hole: { + valType: 'number', + + min: 0, + max: 1, + dflt: 0, + editType: 'calc', + + }, + + // ordering and direction + sort: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + direction: { + /** + * there are two common conventions, both of which place the first + * (largest, if sorted) slice with its left edge at 12 o'clock but + * succeeding slices follow either cw or ccw from there. + * + * see http://visage.co/data-visualization-101-pie-charts/ + */ + valType: 'enumerated', + values: ['clockwise', 'counterclockwise'], + + dflt: 'counterclockwise', + editType: 'calc', + + }, + rotation: { + valType: 'number', + + min: -360, + max: 360, + dflt: 0, + editType: 'calc', + + }, + + pull: { + valType: 'number', + + min: 0, + max: 1, + dflt: 0, + arrayOk: true, + editType: 'calc', + + } +}; + +},{"../../components/color/attributes":569,"../../lib/extend":685,"../../plots/attributes":741,"../../plots/domain":770,"../../plots/font_attributes":771}],1019:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; + +exports.name = 'pie'; + +exports.plot = function(gd) { + var Pie = Registry.getModule('pie'); + var cdPie = getModuleCalcData(gd.calcdata, Pie)[0]; + + if(cdPie.length) Pie.plot(gd, cdPie); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadPie = (oldFullLayout._has && oldFullLayout._has('pie')); + var hasPie = (newFullLayout._has && newFullLayout._has('pie')); + + if(hadPie && !hasPie) { + oldFullLayout._pielayer.selectAll('g.trace').remove(); + } +}; + +},{"../../plots/get_data":781,"../../registry":827}],1020:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; +var tinycolor = _dereq_('tinycolor2'); + +var Color = _dereq_('../../components/color'); +var helpers = _dereq_('./helpers'); + +exports.calc = function calc(gd, trace) { + var vals = trace.values; + var hasVals = isArrayOrTypedArray(vals) && vals.length; + var labels = trace.labels; + var colors = trace.marker.colors || []; + var cd = []; + var fullLayout = gd._fullLayout; + var colorMap = fullLayout._piecolormap; + var allThisTraceLabels = {}; + var vTotal = 0; + var hiddenLabels = fullLayout.hiddenlabels || []; + + var i, v, label, hidden, pt; + + if(trace.dlabel) { + labels = new Array(vals.length); + for(i = 0; i < vals.length; i++) { + labels[i] = String(trace.label0 + i * trace.dlabel); + } + } + + function pullColor(color, label) { + if(!color) return false; + + color = tinycolor(color); + if(!color.isValid()) return false; + + color = Color.addOpacity(color, color.getAlpha()); + if(!colorMap[label]) colorMap[label] = color; + + return color; + } + + var seriesLen = (hasVals ? vals : labels).length; + + for(i = 0; i < seriesLen; i++) { + if(hasVals) { + v = vals[i]; + if(!isNumeric(v)) continue; + v = +v; + if(v < 0) continue; + } + else v = 1; + + label = labels[i]; + if(label === undefined || label === '') label = i; + label = String(label); + + var thisLabelIndex = allThisTraceLabels[label]; + if(thisLabelIndex === undefined) { + allThisTraceLabels[label] = cd.length; + + hidden = hiddenLabels.indexOf(label) !== -1; + + if(!hidden) vTotal += v; + + cd.push({ + v: v, + label: label, + color: pullColor(colors[i], label), + i: i, + pts: [i], + hidden: hidden + }); + } + else { + pt = cd[thisLabelIndex]; + pt.v += v; + pt.pts.push(i); + if(!pt.hidden) vTotal += v; + + if(pt.color === false && colors[i]) { + pt.color = pullColor(colors[i], label); + } + } + } + + if(trace.sort) cd.sort(function(a, b) { return b.v - a.v; }); + + // include the sum of all values in the first point + if(cd[0]) cd[0].vTotal = vTotal; + + // now insert text + if(trace.textinfo && trace.textinfo !== 'none') { + var hasLabel = trace.textinfo.indexOf('label') !== -1; + var hasText = trace.textinfo.indexOf('text') !== -1; + var hasValue = trace.textinfo.indexOf('value') !== -1; + var hasPercent = trace.textinfo.indexOf('percent') !== -1; + var separators = fullLayout.separators; + + var thisText; + + for(i = 0; i < cd.length; i++) { + pt = cd[i]; + thisText = hasLabel ? [pt.label] : []; + if(hasText) { + var texti = helpers.getFirstFilled(trace.text, pt.pts); + if(texti) thisText.push(texti); + } + if(hasValue) thisText.push(helpers.formatPieValue(pt.v, separators)); + if(hasPercent) thisText.push(helpers.formatPiePercent(pt.v / vTotal, separators)); + pt.text = thisText.join('
'); + } + } + + return cd; +}; + +/* + * `calc` filled in (and collated) explicit colors. + * Now we need to propagate these explicit colors to other traces, + * and fill in default colors. + * This is done after sorting, so we pick defaults + * in the order slices will be displayed + */ +exports.crossTraceCalc = function(gd) { + var fullLayout = gd._fullLayout; + var calcdata = gd.calcdata; + var pieColorWay = fullLayout.piecolorway; + var colorMap = fullLayout._piecolormap; + + if(fullLayout.extendpiecolors) { + pieColorWay = generateExtendedColors(pieColorWay); + } + var dfltColorCount = 0; + + var i, j, cd, pt; + for(i = 0; i < calcdata.length; i++) { + cd = calcdata[i]; + if(cd[0].trace.type !== 'pie') continue; + + for(j = 0; j < cd.length; j++) { + pt = cd[j]; + if(pt.color === false) { + // have we seen this label and assigned a color to it in a previous trace? + if(colorMap[pt.label]) { + pt.color = colorMap[pt.label]; + } + else { + colorMap[pt.label] = pt.color = pieColorWay[dfltColorCount % pieColorWay.length]; + dfltColorCount++; + } + } + } + } +}; + +/** + * pick a default color from the main default set, augmented by + * itself lighter then darker before repeating + */ +var extendedColorWays = {}; + +function generateExtendedColors(colorList) { + var i; + var colorString = JSON.stringify(colorList); + var pieColors = extendedColorWays[colorString]; + if(!pieColors) { + pieColors = colorList.slice(); + + for(i = 0; i < colorList.length; i++) { + pieColors.push(tinycolor(colorList[i]).lighten(20).toHexString()); + } + + for(i = 0; i < colorList.length; i++) { + pieColors.push(tinycolor(colorList[i]).darken(20).toHexString()); + } + extendedColorWays[colorString] = pieColors; + } + + return pieColors; +} + +},{"../../components/color":570,"../../lib":696,"./helpers":1023,"fast-isnumeric":214,"tinycolor2":514}],1021:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attributes = _dereq_('./attributes'); +var handleDomainDefaults = _dereq_('../../plots/domain').defaults; + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var coerceFont = Lib.coerceFont; + var len; + + var vals = coerce('values'); + var hasVals = Lib.isArrayOrTypedArray(vals); + var labels = coerce('labels'); + if(Array.isArray(labels)) { + len = labels.length; + if(hasVals) len = Math.min(len, vals.length); + } + else if(hasVals) { + len = vals.length; + + coerce('label0'); + coerce('dlabel'); + } + + if(!len) { + traceOut.visible = false; + return; + } + traceOut._length = len; + + var lineWidth = coerce('marker.line.width'); + if(lineWidth) coerce('marker.line.color'); + + coerce('marker.colors'); + + coerce('scalegroup'); + // TODO: hole needs to be coerced to the same value within a scaleegroup + + var textData = coerce('text'); + var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); + coerce('hovertext'); + + if(textInfo && textInfo !== 'none') { + var textPosition = coerce('textposition'), + hasBoth = Array.isArray(textPosition) || textPosition === 'auto', + hasInside = hasBoth || textPosition === 'inside', + hasOutside = hasBoth || textPosition === 'outside'; + + if(hasInside || hasOutside) { + var dfltFont = coerceFont(coerce, 'textfont', layout.font); + if(hasInside) { + var insideTextFontDefault = Lib.extendFlat({}, dfltFont); + var isTraceTextfontColorSet = traceIn.textfont && traceIn.textfont.color; + var isColorInheritedFromLayoutFont = !isTraceTextfontColorSet; + if(isColorInheritedFromLayoutFont) { + delete insideTextFontDefault.color; + } + coerceFont(coerce, 'insidetextfont', insideTextFontDefault); + } + if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont); + } + } + + handleDomainDefaults(traceOut, layout, coerce); + + var hole = coerce('hole'); + var title = coerce('title'); + if(title) { + var titlePosition = coerce('titleposition', hole ? 'middle center' : 'top center'); + if(!hole && titlePosition === 'middle center') traceOut.titleposition = 'top center'; + coerceFont(coerce, 'titlefont', layout.font); + } + + coerce('sort'); + coerce('direction'); + coerce('rotation'); + + coerce('pull'); +}; + +},{"../../lib":696,"../../plots/domain":770,"./attributes":1018}],1022:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var appendArrayMultiPointValues = _dereq_('../../components/fx/helpers').appendArrayMultiPointValues; + + +// Note: like other eventData routines, this creates the data for hover/unhover/click events +// but it has a different API and goes through a totally different pathway. +// So to ensure it doesn't get misused, it's not attached to the Pie module. +module.exports = function eventData(pt, trace) { + var out = { + curveNumber: trace.index, + pointNumbers: pt.pts, + data: trace._input, + fullData: trace, + label: pt.label, + color: pt.color, + value: pt.v, + + // pt.v (and pt.i below) for backward compatibility + v: pt.v + }; + + // Only include pointNumber if it's unambiguous + if(pt.pts.length === 1) out.pointNumber = out.i = pt.pts[0]; + + // Add extra data arrays to the output + // notice that this is the multi-point version ('s' on the end!) + // so added data will be arrays matching the pointNumbers array. + appendArrayMultiPointValues(out, trace, pt.pts); + + return out; +}; + +},{"../../components/fx/helpers":609}],1023:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +exports.formatPiePercent = function formatPiePercent(v, separators) { + var vRounded = (v * 100).toPrecision(3); + if(vRounded.lastIndexOf('.') !== -1) { + vRounded = vRounded.replace(/[.]?0+$/, ''); + } + return Lib.numSeparate(vRounded, separators) + '%'; +}; + +exports.formatPieValue = function formatPieValue(v, separators) { + var vRounded = v.toPrecision(10); + if(vRounded.lastIndexOf('.') !== -1) { + vRounded = vRounded.replace(/[.]?0+$/, ''); + } + return Lib.numSeparate(vRounded, separators); +}; + +exports.getFirstFilled = function getFirstFilled(array, indices) { + if(!Array.isArray(array)) return; + for(var i = 0; i < indices.length; i++) { + var v = array[indices[i]]; + if(v || v === 0) return v; + } +}; + +exports.castOption = function castOption(item, indices) { + if(Array.isArray(item)) return exports.getFirstFilled(item, indices); + else if(item) return item; +}; + +},{"../../lib":696}],1024:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Pie = {}; + +Pie.attributes = _dereq_('./attributes'); +Pie.supplyDefaults = _dereq_('./defaults'); +Pie.supplyLayoutDefaults = _dereq_('./layout_defaults'); +Pie.layoutAttributes = _dereq_('./layout_attributes'); + +var calcModule = _dereq_('./calc'); +Pie.calc = calcModule.calc; +Pie.crossTraceCalc = calcModule.crossTraceCalc; + +Pie.plot = _dereq_('./plot'); +Pie.style = _dereq_('./style'); +Pie.styleOne = _dereq_('./style_one'); + +Pie.moduleType = 'trace'; +Pie.name = 'pie'; +Pie.basePlotModule = _dereq_('./base_plot'); +Pie.categories = ['pie', 'showLegend']; +Pie.meta = { + +}; + +module.exports = Pie; + +},{"./attributes":1018,"./base_plot":1019,"./calc":1020,"./defaults":1021,"./layout_attributes":1025,"./layout_defaults":1026,"./plot":1027,"./style":1028,"./style_one":1029}],1025:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + /** + * hiddenlabels is the pie chart analog of visible:'legendonly' + * but it can contain many labels, and can hide slices + * from several pies simultaneously + */ + hiddenlabels: { + valType: 'data_array', + editType: 'calc' + }, + piecolorway: { + valType: 'colorlist', + + editType: 'calc', + + }, + extendpiecolors: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + } +}; + +},{}],1026:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var layoutAttributes = _dereq_('./layout_attributes'); + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + coerce('hiddenlabels'); + coerce('piecolorway', layoutOut.colorway); + coerce('extendpiecolors'); +}; + +},{"../../lib":696,"./layout_attributes":1025}],1027:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Fx = _dereq_('../../components/fx'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var Lib = _dereq_('../../lib'); +var svgTextUtils = _dereq_('../../lib/svg_text_utils'); + +var helpers = _dereq_('./helpers'); +var eventData = _dereq_('./event_data'); + +module.exports = function plot(gd, cdpie) { + var fullLayout = gd._fullLayout; + + prerenderTitles(cdpie, gd); + scalePies(cdpie, fullLayout._size); + + var pieGroups = Lib.makeTraceGroups(fullLayout._pielayer, cdpie, 'trace').each(function(cd) { + var pieGroup = d3.select(this); + var cd0 = cd[0]; + var trace = cd0.trace; + + setCoords(cd); + + // TODO: miter might look better but can sometimes cause problems + // maybe miter with a small-ish stroke-miterlimit? + pieGroup.attr('stroke-linejoin', 'round'); + + pieGroup.each(function() { + var slices = d3.select(this).selectAll('g.slice').data(cd); + + slices.enter().append('g') + .classed('slice', true); + slices.exit().remove(); + + var quadrants = [ + [[], []], // y<0: x<0, x>=0 + [[], []] // y>=0: x<0, x>=0 + ]; + var hasOutsideText = false; + + slices.each(function(pt) { + if(pt.hidden) { + d3.select(this).selectAll('path,g').remove(); + return; + } + + // to have consistent event data compared to other traces + pt.pointNumber = pt.i; + pt.curveNumber = trace.index; + + quadrants[pt.pxmid[1] < 0 ? 0 : 1][pt.pxmid[0] < 0 ? 0 : 1].push(pt); + + var cx = cd0.cx; + var cy = cd0.cy; + var sliceTop = d3.select(this); + var slicePath = sliceTop.selectAll('path.surface').data([pt]); + + // hover state vars + // have we drawn a hover label, so it should be cleared later + var hasHoverLabel = false; + // have we emitted a hover event, so later an unhover event should be emitted + // note that click events do not depend on this - you can still get them + // with hovermode: false or if you were earlier dragging, then clicked + // in the same slice that you moused up in + var hasHoverEvent = false; + + function handleMouseOver() { + // in case fullLayout or fullData has changed without a replot + var fullLayout2 = gd._fullLayout; + var trace2 = gd._fullData[trace.index]; + + if(gd._dragging || fullLayout2.hovermode === false) return; + + var hoverinfo = trace2.hoverinfo; + if(Array.isArray(hoverinfo)) { + // super hacky: we need to pull out the *first* hoverinfo from + // pt.pts, then put it back into an array in a dummy trace + // and call castHoverinfo on that. + // TODO: do we want to have Fx.castHoverinfo somehow handle this? + // it already takes an array for index, for 2D, so this seems tricky. + hoverinfo = Fx.castHoverinfo({ + hoverinfo: [helpers.castOption(hoverinfo, pt.pts)], + _module: trace._module + }, fullLayout2, 0); + } + + if(hoverinfo === 'all') hoverinfo = 'label+text+value+percent+name'; + + // in case we dragged over the pie from another subplot, + // or if hover is turned off + if(hoverinfo !== 'none' && hoverinfo !== 'skip' && hoverinfo) { + var rInscribed = getInscribedRadiusFraction(pt, cd0); + var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed); + var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed); + var separators = fullLayout.separators; + var thisText = []; + + if(hoverinfo.indexOf('label') !== -1) thisText.push(pt.label); + if(hoverinfo.indexOf('text') !== -1) { + var texti = helpers.castOption(trace2.hovertext || trace2.text, pt.pts); + if(texti) thisText.push(texti); + } + if(hoverinfo.indexOf('value') !== -1) thisText.push(helpers.formatPieValue(pt.v, separators)); + if(hoverinfo.indexOf('percent') !== -1) thisText.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators)); + + var hoverLabel = trace.hoverlabel; + var hoverFont = hoverLabel.font; + + Fx.loneHover({ + x0: hoverCenterX - rInscribed * cd0.r, + x1: hoverCenterX + rInscribed * cd0.r, + y: hoverCenterY, + text: thisText.join('
'), + name: hoverinfo.indexOf('name') !== -1 ? trace2.name : undefined, + idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', + color: helpers.castOption(hoverLabel.bgcolor, pt.pts) || pt.color, + borderColor: helpers.castOption(hoverLabel.bordercolor, pt.pts), + fontFamily: helpers.castOption(hoverFont.family, pt.pts), + fontSize: helpers.castOption(hoverFont.size, pt.pts), + fontColor: helpers.castOption(hoverFont.color, pt.pts) + }, { + container: fullLayout2._hoverlayer.node(), + outerContainer: fullLayout2._paper.node(), + gd: gd + }); + + hasHoverLabel = true; + } + + gd.emit('plotly_hover', { + points: [eventData(pt, trace2)], + event: d3.event + }); + hasHoverEvent = true; + } + + function handleMouseOut(evt) { + var fullLayout2 = gd._fullLayout; + var trace2 = gd._fullData[trace.index]; + + if(hasHoverEvent) { + evt.originalEvent = d3.event; + gd.emit('plotly_unhover', { + points: [eventData(pt, trace2)], + event: d3.event + }); + hasHoverEvent = false; + } + + if(hasHoverLabel) { + Fx.loneUnhover(fullLayout2._hoverlayer.node()); + hasHoverLabel = false; + } + } + + function handleClick() { + // TODO: this does not support right-click. If we want to support it, we + // would likely need to change pie to use dragElement instead of straight + // mapbox event binding. Or perhaps better, make a simple wrapper with the + // right mousedown, mousemove, and mouseup handlers just for a left/right click + // mapbox would use this too. + var fullLayout2 = gd._fullLayout; + var trace2 = gd._fullData[trace.index]; + + if(gd._dragging || fullLayout2.hovermode === false) return; + + gd._hoverdata = [eventData(pt, trace2)]; + Fx.click(gd, d3.event); + } + + slicePath.enter().append('path') + .classed('surface', true) + .style({'pointer-events': 'all'}); + + sliceTop.select('path.textline').remove(); + + sliceTop + .on('mouseover', handleMouseOver) + .on('mouseout', handleMouseOut) + .on('click', handleClick); + + if(trace.pull) { + var pull = +helpers.castOption(trace.pull, pt.pts) || 0; + if(pull > 0) { + cx += pull * pt.pxmid[0]; + cy += pull * pt.pxmid[1]; + } + } + + pt.cxFinal = cx; + pt.cyFinal = cy; + + function arc(start, finish, cw, scale) { + return 'a' + (scale * cd0.r) + ',' + (scale * cd0.r) + ' 0 ' + + pt.largeArc + (cw ? ' 1 ' : ' 0 ') + + (scale * (finish[0] - start[0])) + ',' + (scale * (finish[1] - start[1])); + } + + var hole = trace.hole; + if(pt.v === cd0.vTotal) { // 100% fails bcs arc start and end are identical + var outerCircle = 'M' + (cx + pt.px0[0]) + ',' + (cy + pt.px0[1]) + + arc(pt.px0, pt.pxmid, true, 1) + + arc(pt.pxmid, pt.px0, true, 1) + 'Z'; + if(hole) { + slicePath.attr('d', + 'M' + (cx + hole * pt.px0[0]) + ',' + (cy + hole * pt.px0[1]) + + arc(pt.px0, pt.pxmid, false, hole) + + arc(pt.pxmid, pt.px0, false, hole) + + 'Z' + outerCircle); + } + else slicePath.attr('d', outerCircle); + } else { + + var outerArc = arc(pt.px0, pt.px1, true, 1); + + if(hole) { + var rim = 1 - hole; + slicePath.attr('d', + 'M' + (cx + hole * pt.px1[0]) + ',' + (cy + hole * pt.px1[1]) + + arc(pt.px1, pt.px0, false, hole) + + 'l' + (rim * pt.px0[0]) + ',' + (rim * pt.px0[1]) + + outerArc + + 'Z'); + } else { + slicePath.attr('d', + 'M' + cx + ',' + cy + + 'l' + pt.px0[0] + ',' + pt.px0[1] + + outerArc + + 'Z'); + } + } + + // add text + var textPosition = helpers.castOption(trace.textposition, pt.pts); + var sliceTextGroup = sliceTop.selectAll('g.slicetext') + .data(pt.text && (textPosition !== 'none') ? [0] : []); + + sliceTextGroup.enter().append('g') + .classed('slicetext', true); + sliceTextGroup.exit().remove(); + + sliceTextGroup.each(function() { + var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { + // prohibit tex interpretation until we can handle + // tex and regular text together + s.attr('data-notex', 1); + }); + + sliceText.text(pt.text) + .attr({ + 'class': 'slicetext', + transform: '', + 'text-anchor': 'middle' + }) + .call(Drawing.font, textPosition === 'outside' ? + determineOutsideTextFont(trace, pt, gd._fullLayout.font) : + determineInsideTextFont(trace, pt, gd._fullLayout.font)) + .call(svgTextUtils.convertToTspans, gd); + + // position the text relative to the slice + var textBB = Drawing.bBox(sliceText.node()); + var transform; + + if(textPosition === 'outside') { + transform = transformOutsideText(textBB, pt); + } else { + transform = transformInsideText(textBB, pt, cd0); + if(textPosition === 'auto' && transform.scale < 1) { + sliceText.call(Drawing.font, trace.outsidetextfont); + if(trace.outsidetextfont.family !== trace.insidetextfont.family || + trace.outsidetextfont.size !== trace.insidetextfont.size) { + textBB = Drawing.bBox(sliceText.node()); + } + transform = transformOutsideText(textBB, pt); + } + } + + var translateX = cx + pt.pxmid[0] * transform.rCenter + (transform.x || 0); + var translateY = cy + pt.pxmid[1] * transform.rCenter + (transform.y || 0); + + // save some stuff to use later ensure no labels overlap + if(transform.outside) { + pt.yLabelMin = translateY - textBB.height / 2; + pt.yLabelMid = translateY; + pt.yLabelMax = translateY + textBB.height / 2; + pt.labelExtraX = 0; + pt.labelExtraY = 0; + hasOutsideText = true; + } + + sliceText.attr('transform', + 'translate(' + translateX + ',' + translateY + ')' + + (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + + (transform.rotate ? ('rotate(' + transform.rotate + ')') : '') + + 'translate(' + + (-(textBB.left + textBB.right) / 2) + ',' + + (-(textBB.top + textBB.bottom) / 2) + + ')'); + }); + }); + + // add the title + var titleTextGroup = d3.select(this).selectAll('g.titletext') + .data(trace.title ? [0] : []); + + titleTextGroup.enter().append('g') + .classed('titletext', true); + titleTextGroup.exit().remove(); + + titleTextGroup.each(function() { + var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { + // prohibit tex interpretation as above + s.attr('data-notex', 1); + }); + + titleText.text(trace.title) + .attr({ + 'class': 'titletext', + transform: '', + 'text-anchor': 'middle', + }) + .call(Drawing.font, trace.titlefont) + .call(svgTextUtils.convertToTspans, gd); + + var transform; + + if(trace.titleposition === 'middle center') { + transform = positionTitleInside(cd0); + } else { + transform = positionTitleOutside(cd0, fullLayout._size); + } + + titleText.attr('transform', + 'translate(' + transform.x + ',' + transform.y + ')' + + (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + + 'translate(' + transform.tx + ',' + transform.ty + ')'); + }); + + // now make sure no labels overlap (at least within one pie) + if(hasOutsideText) scootLabels(quadrants, trace); + slices.each(function(pt) { + if(pt.labelExtraX || pt.labelExtraY) { + // first move the text to its new location + var sliceTop = d3.select(this); + var sliceText = sliceTop.select('g.slicetext text'); + + sliceText.attr('transform', 'translate(' + pt.labelExtraX + ',' + pt.labelExtraY + ')' + + sliceText.attr('transform')); + + // then add a line to the new location + var lineStartX = pt.cxFinal + pt.pxmid[0]; + var lineStartY = pt.cyFinal + pt.pxmid[1]; + var textLinePath = 'M' + lineStartX + ',' + lineStartY; + var finalX = (pt.yLabelMax - pt.yLabelMin) * (pt.pxmid[0] < 0 ? -1 : 1) / 4; + + if(pt.labelExtraX) { + var yFromX = pt.labelExtraX * pt.pxmid[1] / pt.pxmid[0]; + var yNet = pt.yLabelMid + pt.labelExtraY - (pt.cyFinal + pt.pxmid[1]); + + if(Math.abs(yFromX) > Math.abs(yNet)) { + textLinePath += + 'l' + (yNet * pt.pxmid[0] / pt.pxmid[1]) + ',' + yNet + + 'H' + (lineStartX + pt.labelExtraX + finalX); + } else { + textLinePath += 'l' + pt.labelExtraX + ',' + yFromX + + 'v' + (yNet - yFromX) + + 'h' + finalX; + } + } else { + textLinePath += + 'V' + (pt.yLabelMid + pt.labelExtraY) + + 'h' + finalX; + } + + sliceTop.append('path') + .classed('textline', true) + .call(Color.stroke, trace.outsidetextfont.color) + .attr({ + 'stroke-width': Math.min(2, trace.outsidetextfont.size / 8), + d: textLinePath, + fill: 'none' + }); + } + }); + }); + }); + + // This is for a bug in Chrome (as of 2015-07-22, and does not affect FF) + // if insidetextfont and outsidetextfont are different sizes, sometimes the size + // of an "em" gets taken from the wrong element at first so lines are + // spaced wrong. You just have to tell it to try again later and it gets fixed. + // I have no idea why we haven't seen this in other contexts. Also, sometimes + // it gets the initial draw correct but on redraw it gets confused. + setTimeout(function() { + pieGroups.selectAll('tspan').each(function() { + var s = d3.select(this); + if(s.attr('dy')) s.attr('dy', s.attr('dy')); + }); + }, 0); +}; + +function determineOutsideTextFont(trace, pt, layoutFont) { + var color = helpers.castOption(trace.outsidetextfont.color, pt.pts) || + helpers.castOption(trace.textfont.color, pt.pts) || + layoutFont.color; + + var family = helpers.castOption(trace.outsidetextfont.family, pt.pts) || + helpers.castOption(trace.textfont.family, pt.pts) || + layoutFont.family; + + var size = helpers.castOption(trace.outsidetextfont.size, pt.pts) || + helpers.castOption(trace.textfont.size, pt.pts) || + layoutFont.size; + + return { + color: color, + family: family, + size: size + }; +} + +function determineInsideTextFont(trace, pt, layoutFont) { + var customColor = helpers.castOption(trace.insidetextfont.color, pt.pts); + if(!customColor && trace._input.textfont) { + + // Why not simply using trace.textfont? Because if not set, it + // defaults to layout.font which has a default color. But if + // textfont.color and insidetextfont.color don't supply a value, + // a contrasting color shall be used. + customColor = helpers.castOption(trace._input.textfont.color, pt.pts); + } + + var family = helpers.castOption(trace.insidetextfont.family, pt.pts) || + helpers.castOption(trace.textfont.family, pt.pts) || + layoutFont.family; + + var size = helpers.castOption(trace.insidetextfont.size, pt.pts) || + helpers.castOption(trace.textfont.size, pt.pts) || + layoutFont.size; + + return { + color: customColor || Color.contrast(pt.color), + family: family, + size: size + }; +} + +function prerenderTitles(cdpie, gd) { + var cd0, trace; + // Determine the width and height of the title for each pie. + for(var i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + trace = cd0.trace; + + if(trace.title) { + var dummyTitle = Drawing.tester.append('text') + .attr('data-notex', 1) + .text(trace.title) + .call(Drawing.font, trace.titlefont) + .call(svgTextUtils.convertToTspans, gd); + var bBox = Drawing.bBox(dummyTitle.node(), true); + cd0.titleBox = { + width: bBox.width, + height: bBox.height, + }; + dummyTitle.remove(); + } + } +} + +function transformInsideText(textBB, pt, cd0) { + var textDiameter = Math.sqrt(textBB.width * textBB.width + textBB.height * textBB.height); + var textAspect = textBB.width / textBB.height; + var halfAngle = Math.PI * Math.min(pt.v / cd0.vTotal, 0.5); + var ring = 1 - cd0.trace.hole; + var rInscribed = getInscribedRadiusFraction(pt, cd0), + + // max size text can be inserted inside without rotating it + // this inscribes the text rectangle in a circle, which is then inscribed + // in the slice, so it will be an underestimate, which some day we may want + // to improve so this case can get more use + transform = { + scale: rInscribed * cd0.r * 2 / textDiameter, + + // and the center position and rotation in this case + rCenter: 1 - rInscribed, + rotate: 0 + }; + + if(transform.scale >= 1) return transform; + + // max size if text is rotated radially + var Qr = textAspect + 1 / (2 * Math.tan(halfAngle)); + var maxHalfHeightRotRadial = cd0.r * Math.min( + 1 / (Math.sqrt(Qr * Qr + 0.5) + Qr), + ring / (Math.sqrt(textAspect * textAspect + ring / 2) + textAspect) + ); + var radialTransform = { + scale: maxHalfHeightRotRadial * 2 / textBB.height, + rCenter: Math.cos(maxHalfHeightRotRadial / cd0.r) - + maxHalfHeightRotRadial * textAspect / cd0.r, + rotate: (180 / Math.PI * pt.midangle + 720) % 180 - 90 + }; + + // max size if text is rotated tangentially + var aspectInv = 1 / textAspect; + var Qt = aspectInv + 1 / (2 * Math.tan(halfAngle)); + var maxHalfWidthTangential = cd0.r * Math.min( + 1 / (Math.sqrt(Qt * Qt + 0.5) + Qt), + ring / (Math.sqrt(aspectInv * aspectInv + ring / 2) + aspectInv) + ); + var tangentialTransform = { + scale: maxHalfWidthTangential * 2 / textBB.width, + rCenter: Math.cos(maxHalfWidthTangential / cd0.r) - + maxHalfWidthTangential / textAspect / cd0.r, + rotate: (180 / Math.PI * pt.midangle + 810) % 180 - 90 + }; + // if we need a rotated transform, pick the biggest one + // even if both are bigger than 1 + var rotatedTransform = tangentialTransform.scale > radialTransform.scale ? + tangentialTransform : radialTransform; + + if(transform.scale < 1 && rotatedTransform.scale > transform.scale) return rotatedTransform; + return transform; +} + +function getInscribedRadiusFraction(pt, cd0) { + if(pt.v === cd0.vTotal && !cd0.trace.hole) return 1;// special case of 100% with no hole + + var halfAngle = Math.PI * Math.min(pt.v / cd0.vTotal, 0.5); + return Math.min(1 / (1 + 1 / Math.sin(halfAngle)), (1 - cd0.trace.hole) / 2); +} + +function transformOutsideText(textBB, pt) { + var x = pt.pxmid[0]; + var y = pt.pxmid[1]; + var dx = textBB.width / 2; + var dy = textBB.height / 2; + + if(x < 0) dx *= -1; + if(y < 0) dy *= -1; + + return { + scale: 1, + rCenter: 1, + rotate: 0, + x: dx + Math.abs(dy) * (dx > 0 ? 1 : -1) / 2, + y: dy / (1 + x * x / (y * y)), + outside: true + }; +} + +function positionTitleInside(cd0) { + var textDiameter = + Math.sqrt(cd0.titleBox.width * cd0.titleBox.width + cd0.titleBox.height * cd0.titleBox.height); + return { + x: cd0.cx, + y: cd0.cy, + scale: cd0.trace.hole * cd0.r * 2 / textDiameter, + tx: 0, + ty: - cd0.titleBox.height / 2 + cd0.trace.titlefont.size + }; +} + +function positionTitleOutside(cd0, plotSize) { + var scaleX = 1, scaleY = 1, maxWidth, maxPull; + var trace = cd0.trace; + // position of the baseline point of the text box in the plot, before scaling. + // we anchored the text in the middle, so the baseline is on the bottom middle + // of the first line of text. + var topMiddle = { + x: cd0.cx, + y: cd0.cy + }; + // relative translation of the text box after scaling + var translate = { + tx: 0, + ty: 0 + }; + + // we reason below as if the baseline is the top middle point of the text box. + // so we must add the font size to approximate the y-coord. of the top. + // note that this correction must happen after scaling. + translate.ty += trace.titlefont.size; + maxPull = getMaxPull(trace); + + if(trace.titleposition.indexOf('top') !== -1) { + topMiddle.y -= (1 + maxPull) * cd0.r; + translate.ty -= cd0.titleBox.height; + } + else if(trace.titleposition.indexOf('bottom') !== -1) { + topMiddle.y += (1 + maxPull) * cd0.r; + } + + if(trace.titleposition.indexOf('left') !== -1) { + // we start the text at the left edge of the pie + maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2 + cd0.r; + topMiddle.x -= (1 + maxPull) * cd0.r; + translate.tx += cd0.titleBox.width / 2; + } else if(trace.titleposition.indexOf('center') !== -1) { + maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]); + } else if(trace.titleposition.indexOf('right') !== -1) { + maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2 + cd0.r; + topMiddle.x += (1 + maxPull) * cd0.r; + translate.tx -= cd0.titleBox.width / 2; + } + scaleX = maxWidth / cd0.titleBox.width; + scaleY = getTitleSpace(cd0, plotSize) / cd0.titleBox.height; + return { + x: topMiddle.x, + y: topMiddle.y, + scale: Math.min(scaleX, scaleY), + tx: translate.tx, + ty: translate.ty + }; +} + +function getTitleSpace(cd0, plotSize) { + var trace = cd0.trace; + var pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]); + // use at most half of the plot for the title + return Math.min(cd0.titleBox.height, pieBoxHeight / 2); +} + +function getMaxPull(trace) { + var maxPull = trace.pull, j; + if(Array.isArray(maxPull)) { + maxPull = 0; + for(j = 0; j < trace.pull.length; j++) { + if(trace.pull[j] > maxPull) maxPull = trace.pull[j]; + } + } + return maxPull; +} + +function scootLabels(quadrants, trace) { + var xHalf, yHalf, equatorFirst, farthestX, farthestY, + xDiffSign, yDiffSign, thisQuad, oppositeQuad, + wholeSide, i, thisQuadOutside, firstOppositeOutsidePt; + + function topFirst(a, b) { return a.pxmid[1] - b.pxmid[1]; } + function bottomFirst(a, b) { return b.pxmid[1] - a.pxmid[1]; } + + function scootOneLabel(thisPt, prevPt) { + if(!prevPt) prevPt = {}; + + var prevOuterY = prevPt.labelExtraY + (yHalf ? prevPt.yLabelMax : prevPt.yLabelMin); + var thisInnerY = yHalf ? thisPt.yLabelMin : thisPt.yLabelMax; + var thisOuterY = yHalf ? thisPt.yLabelMax : thisPt.yLabelMin; + var thisSliceOuterY = thisPt.cyFinal + farthestY(thisPt.px0[1], thisPt.px1[1]); + var newExtraY = prevOuterY - thisInnerY; + + var xBuffer, i, otherPt, otherOuterY, otherOuterX, newExtraX; + + // make sure this label doesn't overlap other labels + // this *only* has us move these labels vertically + if(newExtraY * yDiffSign > 0) thisPt.labelExtraY = newExtraY; + + // make sure this label doesn't overlap any slices + if(!Array.isArray(trace.pull)) return; // this can only happen with array pulls + + for(i = 0; i < wholeSide.length; i++) { + otherPt = wholeSide[i]; + + // overlap can only happen if the other point is pulled more than this one + if(otherPt === thisPt || ( + (helpers.castOption(trace.pull, thisPt.pts) || 0) >= + (helpers.castOption(trace.pull, otherPt.pts) || 0)) + ) { + continue; + } + + if((thisPt.pxmid[1] - otherPt.pxmid[1]) * yDiffSign > 0) { + // closer to the equator - by construction all of these happen first + // move the text vertically to get away from these slices + otherOuterY = otherPt.cyFinal + farthestY(otherPt.px0[1], otherPt.px1[1]); + newExtraY = otherOuterY - thisInnerY - thisPt.labelExtraY; + + if(newExtraY * yDiffSign > 0) thisPt.labelExtraY += newExtraY; + + } else if((thisOuterY + thisPt.labelExtraY - thisSliceOuterY) * yDiffSign > 0) { + // farther from the equator - happens after we've done all the + // vertical moving we're going to do + // move horizontally to get away from these more polar slices + + // if we're moving horz. based on a slice that's several slices away from this one + // then we need some extra space for the lines to labels between them + xBuffer = 3 * xDiffSign * Math.abs(i - wholeSide.indexOf(thisPt)); + + otherOuterX = otherPt.cxFinal + farthestX(otherPt.px0[0], otherPt.px1[0]); + newExtraX = otherOuterX + xBuffer - (thisPt.cxFinal + thisPt.pxmid[0]) - thisPt.labelExtraX; + + if(newExtraX * xDiffSign > 0) thisPt.labelExtraX += newExtraX; + } + } + } + + for(yHalf = 0; yHalf < 2; yHalf++) { + equatorFirst = yHalf ? topFirst : bottomFirst; + farthestY = yHalf ? Math.max : Math.min; + yDiffSign = yHalf ? 1 : -1; + + for(xHalf = 0; xHalf < 2; xHalf++) { + farthestX = xHalf ? Math.max : Math.min; + xDiffSign = xHalf ? 1 : -1; + + // first sort the array + // note this is a copy of cd, so cd itself doesn't get sorted + // but we can still modify points in place. + thisQuad = quadrants[yHalf][xHalf]; + thisQuad.sort(equatorFirst); + + oppositeQuad = quadrants[1 - yHalf][xHalf]; + wholeSide = oppositeQuad.concat(thisQuad); + + thisQuadOutside = []; + for(i = 0; i < thisQuad.length; i++) { + if(thisQuad[i].yLabelMid !== undefined) thisQuadOutside.push(thisQuad[i]); + } + + firstOppositeOutsidePt = false; + for(i = 0; yHalf && i < oppositeQuad.length; i++) { + if(oppositeQuad[i].yLabelMid !== undefined) { + firstOppositeOutsidePt = oppositeQuad[i]; + break; + } + } + + // each needs to avoid the previous + for(i = 0; i < thisQuadOutside.length; i++) { + var prevPt = i && thisQuadOutside[i - 1]; + // bottom half needs to avoid the first label of the top half + // top half we still need to call scootOneLabel on the first slice + // so we can avoid other slices, but we don't pass a prevPt + if(firstOppositeOutsidePt && !i) prevPt = firstOppositeOutsidePt; + scootOneLabel(thisQuadOutside[i], prevPt); + } + } + } +} + +function scalePies(cdpie, plotSize) { + var scaleGroups = []; + + var pieBoxWidth, pieBoxHeight, i, j, cd0, trace, + maxPull, scaleGroup, minPxPerValUnit; + + // first figure out the center and maximum radius for each pie + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + trace = cd0.trace; + + pieBoxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]); + pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]); + // leave some space for the title, if it will be displayed outside + if(trace.title && trace.titleposition !== 'middle center') { + pieBoxHeight -= getTitleSpace(cd0, plotSize); + } + + maxPull = getMaxPull(trace); + + cd0.r = Math.min(pieBoxWidth, pieBoxHeight) / (2 + 2 * maxPull); + + cd0.cx = plotSize.l + plotSize.w * (trace.domain.x[1] + trace.domain.x[0]) / 2; + cd0.cy = plotSize.t + plotSize.h * (1 - trace.domain.y[0]) - pieBoxHeight / 2; + if(trace.title && trace.titleposition.indexOf('bottom') !== -1) { + cd0.cy -= getTitleSpace(cd0, plotSize); + } + + if(trace.scalegroup && scaleGroups.indexOf(trace.scalegroup) === -1) { + scaleGroups.push(trace.scalegroup); + } + } + + // Then scale any pies that are grouped + for(j = 0; j < scaleGroups.length; j++) { + minPxPerValUnit = Infinity; + scaleGroup = scaleGroups[j]; + + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + if(cd0.trace.scalegroup === scaleGroup) { + minPxPerValUnit = Math.min(minPxPerValUnit, + cd0.r * cd0.r / cd0.vTotal); + } + } + + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + if(cd0.trace.scalegroup === scaleGroup) { + cd0.r = Math.sqrt(minPxPerValUnit * cd0.vTotal); + } + } + } + +} + +function setCoords(cd) { + var cd0 = cd[0]; + var trace = cd0.trace; + var currentAngle = trace.rotation * Math.PI / 180; + var angleFactor = 2 * Math.PI / cd0.vTotal; + var firstPt = 'px0'; + var lastPt = 'px1'; + + var i, cdi, currentCoords; + + if(trace.direction === 'counterclockwise') { + for(i = 0; i < cd.length; i++) { + if(!cd[i].hidden) break; // find the first non-hidden slice + } + if(i === cd.length) return; // all slices hidden + + currentAngle += angleFactor * cd[i].v; + angleFactor *= -1; + firstPt = 'px1'; + lastPt = 'px0'; + } + + function getCoords(angle) { + return [cd0.r * Math.sin(angle), -cd0.r * Math.cos(angle)]; + } + + currentCoords = getCoords(currentAngle); + + for(i = 0; i < cd.length; i++) { + cdi = cd[i]; + if(cdi.hidden) continue; + + cdi[firstPt] = currentCoords; + + currentAngle += angleFactor * cdi.v / 2; + cdi.pxmid = getCoords(currentAngle); + cdi.midangle = currentAngle; + + currentAngle += angleFactor * cdi.v / 2; + currentCoords = getCoords(currentAngle); + + cdi[lastPt] = currentCoords; + + cdi.largeArc = (cdi.v > cd0.vTotal / 2) ? 1 : 0; + } +} + +},{"../../components/color":570,"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/svg_text_utils":720,"./event_data":1022,"./helpers":1023,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1028:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var styleOne = _dereq_('./style_one'); + +module.exports = function style(gd) { + gd._fullLayout._pielayer.selectAll('.trace').each(function(cd) { + var cd0 = cd[0]; + var trace = cd0.trace; + var traceSelection = d3.select(this); + + traceSelection.style({opacity: trace.opacity}); + + traceSelection.selectAll('path.surface').each(function(pt) { + d3.select(this).call(styleOne, pt, trace); + }); + }); +}; + +},{"./style_one":1029,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1029:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Color = _dereq_('../../components/color'); +var castOption = _dereq_('./helpers').castOption; + +module.exports = function styleOne(s, pt, trace) { + var line = trace.marker.line; + var lineColor = castOption(line.color, pt.pts) || Color.defaultLine; + var lineWidth = castOption(line.width, pt.pts) || 0; + + s.style({'stroke-width': lineWidth}) + .call(Color.fill, pt.color) + .call(Color.stroke, lineColor); +}; + +},{"../../components/color":570,"./helpers":1023}],1030:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterglAttrs = _dereq_('../scatter/attributes'); + +module.exports = { + x: scatterglAttrs.x, + y: scatterglAttrs.y, + xy: { + valType: 'data_array', + editType: 'calc', + + }, + indices: { + valType: 'data_array', + editType: 'calc', + + }, + xbounds: { + valType: 'data_array', + editType: 'calc', + + }, + ybounds: { + valType: 'data_array', + editType: 'calc', + + }, + text: scatterglAttrs.text, + marker: { + color: { + valType: 'color', + arrayOk: false, + + editType: 'calc', + + }, + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + arrayOk: false, + + editType: 'calc', + + }, + blend: { + valType: 'boolean', + dflt: null, + + editType: 'calc', + + }, + sizemin: { + valType: 'number', + min: 0.1, + max: 2, + dflt: 0.5, + + editType: 'calc', + + }, + sizemax: { + valType: 'number', + min: 0.1, + dflt: 20, + + editType: 'calc', + + }, + border: { + color: { + valType: 'color', + arrayOk: false, + + editType: 'calc', + + }, + arearatio: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + + editType: 'calc', + + }, + editType: 'calc' + }, + editType: 'calc' + }, + transforms: undefined +}; + +},{"../scatter/attributes":1043}],1031:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var createPointCloudRenderer = _dereq_('gl-pointcloud2d'); + +var str2RGBArray = _dereq_('../../lib/str2rgbarray'); +var findExtremes = _dereq_('../../plots/cartesian/autorange').findExtremes; +var getTraceColor = _dereq_('../scatter/get_trace_color'); + +function Pointcloud(scene, uid) { + this.scene = scene; + this.uid = uid; + this.type = 'pointcloud'; + + this.pickXData = []; + this.pickYData = []; + this.xData = []; + this.yData = []; + this.textLabels = []; + this.color = 'rgb(0, 0, 0)'; + this.name = ''; + this.hoverinfo = 'all'; + + this.idToIndex = new Int32Array(0); + this.bounds = [0, 0, 0, 0]; + + this.pointcloudOptions = { + positions: new Float32Array(0), + idToIndex: this.idToIndex, + sizemin: 0.5, + sizemax: 12, + color: [0, 0, 0, 1], + areaRatio: 1, + borderColor: [0, 0, 0, 1] + }; + this.pointcloud = createPointCloudRenderer(scene.glplot, this.pointcloudOptions); + this.pointcloud._trace = this; // scene2d requires this prop +} + +var proto = Pointcloud.prototype; + +proto.handlePick = function(pickResult) { + var index = this.idToIndex[pickResult.pointId]; + + // prefer the readout from XY, if present + return { + trace: this, + dataCoord: pickResult.dataCoord, + traceCoord: this.pickXYData ? + [this.pickXYData[index * 2], this.pickXYData[index * 2 + 1]] : + [this.pickXData[index], this.pickYData[index]], + textLabel: Array.isArray(this.textLabels) ? + this.textLabels[index] : + this.textLabels, + color: this.color, + name: this.name, + pointIndex: index, + hoverinfo: this.hoverinfo + }; +}; + +proto.update = function(options) { + this.index = options.index; + this.textLabels = options.text; + this.name = options.name; + this.hoverinfo = options.hoverinfo; + this.bounds = [Infinity, Infinity, -Infinity, -Infinity]; + + this.updateFast(options); + + this.color = getTraceColor(options, {}); +}; + +proto.updateFast = function(options) { + var x = this.xData = this.pickXData = options.x; + var y = this.yData = this.pickYData = options.y; + var xy = this.pickXYData = options.xy; + + var userBounds = options.xbounds && options.ybounds; + var index = options.indices; + + var len, + idToIndex, + positions, + bounds = this.bounds; + + var xx, yy, i; + + if(xy) { + + positions = xy; + + // dividing xy.length by 2 and truncating to integer if xy.length was not even + len = xy.length >>> 1; + + if(userBounds) { + + bounds[0] = options.xbounds[0]; + bounds[2] = options.xbounds[1]; + bounds[1] = options.ybounds[0]; + bounds[3] = options.ybounds[1]; + + } else { + + for(i = 0; i < len; i++) { + + xx = positions[i * 2]; + yy = positions[i * 2 + 1]; + + if(xx < bounds[0]) bounds[0] = xx; + if(xx > bounds[2]) bounds[2] = xx; + if(yy < bounds[1]) bounds[1] = yy; + if(yy > bounds[3]) bounds[3] = yy; + } + + } + + if(index) { + + idToIndex = index; + + } else { + + idToIndex = new Int32Array(len); + + for(i = 0; i < len; i++) { + + idToIndex[i] = i; + + } + + } + + } else { + + len = x.length; + + positions = new Float32Array(2 * len); + idToIndex = new Int32Array(len); + + for(i = 0; i < len; i++) { + xx = x[i]; + yy = y[i]; + + idToIndex[i] = i; + + positions[i * 2] = xx; + positions[i * 2 + 1] = yy; + + if(xx < bounds[0]) bounds[0] = xx; + if(xx > bounds[2]) bounds[2] = xx; + if(yy < bounds[1]) bounds[1] = yy; + if(yy > bounds[3]) bounds[3] = yy; + } + + } + + this.idToIndex = idToIndex; + this.pointcloudOptions.idToIndex = idToIndex; + + this.pointcloudOptions.positions = positions; + + var markerColor = str2RGBArray(options.marker.color), + borderColor = str2RGBArray(options.marker.border.color), + opacity = options.opacity * options.marker.opacity; + + markerColor[3] *= opacity; + this.pointcloudOptions.color = markerColor; + + // detect blending from the number of points, if undefined + // because large data with blending hits performance + var blend = options.marker.blend; + if(blend === null) { + var maxPoints = 100; + blend = x.length < maxPoints || y.length < maxPoints; + } + this.pointcloudOptions.blend = blend; + + borderColor[3] *= opacity; + this.pointcloudOptions.borderColor = borderColor; + + var markerSizeMin = options.marker.sizemin; + var markerSizeMax = Math.max(options.marker.sizemax, options.marker.sizemin); + this.pointcloudOptions.sizeMin = markerSizeMin; + this.pointcloudOptions.sizeMax = markerSizeMax; + this.pointcloudOptions.areaRatio = options.marker.border.arearatio; + + this.pointcloud.update(this.pointcloudOptions); + + // add item for autorange routine + var xa = this.scene.xaxis; + var ya = this.scene.yaxis; + var pad = markerSizeMax / 2 || 0.5; + options._extremes[xa._id] = findExtremes(xa, [bounds[0], bounds[2]], {ppad: pad}); + options._extremes[ya._id] = findExtremes(ya, [bounds[1], bounds[3]], {ppad: pad}); +}; + +proto.dispose = function() { + this.pointcloud.dispose(); +}; + +function createPointcloud(scene, data) { + var plot = new Pointcloud(scene, data.uid); + plot.update(data); + return plot; +} + +module.exports = createPointcloud; + +},{"../../lib/str2rgbarray":719,"../../plots/cartesian/autorange":743,"../scatter/get_trace_color":1053,"gl-pointcloud2d":279}],1032:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + coerce('x'); + coerce('y'); + + coerce('xbounds'); + coerce('ybounds'); + + if(traceIn.xy && traceIn.xy instanceof Float32Array) { + traceOut.xy = traceIn.xy; + } + + if(traceIn.indices && traceIn.indices instanceof Int32Array) { + traceOut.indices = traceIn.indices; + } + + coerce('text'); + coerce('marker.color', defaultColor); + coerce('marker.opacity'); + coerce('marker.blend'); + coerce('marker.sizemin'); + coerce('marker.sizemax'); + coerce('marker.border.color', defaultColor); + coerce('marker.border.arearatio'); + + // disable 1D transforms - that would defeat the purpose of this trace type, performance! + traceOut._length = null; +}; + +},{"../../lib":696,"./attributes":1030}],1033:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var pointcloud = {}; + +pointcloud.attributes = _dereq_('./attributes'); +pointcloud.supplyDefaults = _dereq_('./defaults'); + +// reuse the Scatter3D 'dummy' calc step so that legends know what to do +pointcloud.calc = _dereq_('../scatter3d/calc'); +pointcloud.plot = _dereq_('./convert'); + +pointcloud.moduleType = 'trace'; +pointcloud.name = 'pointcloud'; +pointcloud.basePlotModule = _dereq_('../../plots/gl2d'); +pointcloud.categories = ['gl', 'gl2d', 'showLegend']; +pointcloud.meta = { + +}; + +module.exports = pointcloud; + +},{"../../plots/gl2d":784,"../scatter3d/calc":1071,"./attributes":1030,"./convert":1031,"./defaults":1032}],1034:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = _dereq_('../../plots/font_attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var colorAttrs = _dereq_('../../components/color/attributes'); +var fxAttrs = _dereq_('../../components/fx/attributes'); +var domainAttrs = _dereq_('../../plots/domain').attributes; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var attrs = module.exports = overrideAll({ + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: [], + arrayOk: false, + + }), + hoverlabel: fxAttrs.hoverlabel, + domain: domainAttrs({name: 'sankey', trace: true}), + + orientation: { + valType: 'enumerated', + values: ['v', 'h'], + dflt: 'h', + + + }, + + valueformat: { + valType: 'string', + dflt: '.3s', + + + }, + + valuesuffix: { + valType: 'string', + dflt: '', + + + }, + + arrangement: { + valType: 'enumerated', + values: ['snap', 'perpendicular', 'freeform', 'fixed'], + dflt: 'snap', + + + }, + + textfont: fontAttrs({ + + }), + + node: { + label: { + valType: 'data_array', + dflt: [], + + + }, + color: { + valType: 'color', + + arrayOk: true, + + }, + line: { + color: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + arrayOk: true, + + }, + width: { + valType: 'number', + + min: 0, + dflt: 0.5, + arrayOk: true, + + } + }, + pad: { + valType: 'number', + arrayOk: false, + min: 0, + dflt: 20, + + + }, + thickness: { + valType: 'number', + arrayOk: false, + min: 1, + dflt: 20, + + + }, + hoverinfo: { + valType: 'enumerated', + values: ['all', 'none', 'skip'], + dflt: 'all', + + + }, + hoverlabel: fxAttrs.hoverlabel, // needs editType override, + + }, + + link: { + label: { + valType: 'data_array', + dflt: [], + + + }, + color: { + valType: 'color', + + arrayOk: true, + + }, + line: { + color: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + arrayOk: true, + + }, + width: { + valType: 'number', + + min: 0, + dflt: 0, + arrayOk: true, + + } + }, + source: { + valType: 'data_array', + + dflt: [], + + }, + target: { + valType: 'data_array', + + dflt: [], + + }, + value: { + valType: 'data_array', + dflt: [], + + + }, + hoverinfo: { + valType: 'enumerated', + values: ['all', 'none', 'skip'], + dflt: 'all', + + + }, + hoverlabel: fxAttrs.hoverlabel, // needs editType override, + + } +}, 'calc', 'nested'); +attrs.transforms = undefined; + +},{"../../components/color/attributes":569,"../../components/fx/attributes":604,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../../plots/domain":770,"../../plots/font_attributes":771}],1035:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; +var plot = _dereq_('./plot'); +var fxAttrs = _dereq_('../../components/fx/layout_attributes'); + +var SANKEY = 'sankey'; + +exports.name = SANKEY; + +exports.baseLayoutAttrOverrides = overrideAll({ + hoverlabel: fxAttrs.hoverlabel +}, 'plot', 'nested'); + +exports.plot = function(gd) { + var calcData = getModuleCalcData(gd.calcdata, SANKEY)[0]; + plot(gd, calcData); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadPlot = (oldFullLayout._has && oldFullLayout._has(SANKEY)); + var hasPlot = (newFullLayout._has && newFullLayout._has(SANKEY)); + + if(hadPlot && !hasPlot) { + oldFullLayout._paperdiv.selectAll('.sankey').remove(); + } +}; + +},{"../../components/fx/layout_attributes":613,"../../plot_api/edit_types":727,"../../plots/get_data":781,"./plot":1040}],1036:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var tarjan = _dereq_('strongly-connected-components'); +var Lib = _dereq_('../../lib'); +var wrap = _dereq_('../../lib/gup').wrap; + +function circularityPresent(nodeList, sources, targets) { + + var nodeLen = nodeList.length; + var nodes = Lib.init2dArray(nodeLen, 0); + + for(var i = 0; i < Math.min(sources.length, targets.length); i++) { + if(Lib.isIndex(sources[i], nodeLen) && Lib.isIndex(targets[i], nodeLen)) { + if(sources[i] === targets[i]) { + return true; // self-link which is also a scc of one + } + nodes[sources[i]].push(targets[i]); + } + } + + var scc = tarjan(nodes); + + // Tarján's strongly connected components algorithm coded by Mikola Lysenko + // returns at least one non-singular component if there's circularity in the graph + return scc.components.some(function(c) { + return c.length > 1; + }); +} + +module.exports = function calc(gd, trace) { + + if(circularityPresent(trace.node.label, trace.link.source, trace.link.target)) { + Lib.error('Circularity is present in the Sankey data. Removing all nodes and links.'); + trace.link.label = []; + trace.link.source = []; + trace.link.target = []; + trace.link.value = []; + trace.link.color = []; + trace.node.label = []; + trace.node.color = []; + } + + return wrap({ + link: trace.link, + node: trace.node + }); +}; + +},{"../../lib":696,"../../lib/gup":693,"strongly-connected-components":506}],1037:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + nodeTextOffsetHorizontal: 4, + nodeTextOffsetVertical: 3, + nodePadAcross: 10, + sankeyIterations: 50, + forceIterations: 5, + forceTicksPerFrame: 10, + duration: 500, + ease: 'cubic-in-out', + cn: { + sankey: 'sankey', + sankeyLinks: 'sankey-links', + sankeyLink: 'sankey-link', + sankeyNodeSet: 'sankey-node-set', + sankeyNode: 'sankey-node', + nodeRect: 'node-rect', + nodeCapture: 'node-capture', + nodeCentered: 'node-entered', + nodeLabelGuide: 'node-label-guide', + nodeLabel: 'node-label', + nodeLabelTextPath: 'node-label-text-path' + } +}; + +},{}],1038:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attributes = _dereq_('./attributes'); +var Color = _dereq_('../../components/color'); +var tinycolor = _dereq_('tinycolor2'); +var handleDomainDefaults = _dereq_('../../plots/domain').defaults; +var handleHoverLabelDefaults = _dereq_('../../components/fx/hoverlabel_defaults'); +var Template = _dereq_('../../plot_api/plot_template'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var hoverlabelDefault = Lib.extendDeep(layout.hoverlabel, traceIn.hoverlabel); + + // node attributes + var nodeIn = traceIn.node, nodeOut = Template.newContainer(traceOut, 'node'); + function coerceNode(attr, dflt) { + return Lib.coerce(nodeIn, nodeOut, attributes.node, attr, dflt); + } + coerceNode('label'); + coerceNode('pad'); + coerceNode('thickness'); + coerceNode('line.color'); + coerceNode('line.width'); + coerceNode('hoverinfo', traceIn.hoverinfo); + handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault); + + var colors = layout.colorway; + + var defaultNodePalette = function(i) {return colors[i % colors.length];}; + + coerceNode('color', nodeOut.label.map(function(d, i) { + return Color.addOpacity(defaultNodePalette(i), 0.8); + })); + + // link attributes + var linkIn = traceIn.link, linkOut = Template.newContainer(traceOut, 'link'); + function coerceLink(attr, dflt) { + return Lib.coerce(linkIn, linkOut, attributes.link, attr, dflt); + } + coerceLink('label'); + coerceLink('source'); + coerceLink('target'); + coerceLink('value'); + coerceLink('line.color'); + coerceLink('line.width'); + coerceLink('hoverinfo', traceIn.hoverinfo); + handleHoverLabelDefaults(linkIn, linkOut, coerceLink, hoverlabelDefault); + + var defaultLinkColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ? + 'rgba(255, 255, 255, 0.6)' : + 'rgba(0, 0, 0, 0.2)'; + + coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length)); + + handleDomainDefaults(traceOut, layout, coerce); + + coerce('orientation'); + coerce('valueformat'); + coerce('valuesuffix'); + coerce('arrangement'); + + Lib.coerceFont(coerce, 'textfont', Lib.extendFlat({}, layout.font)); + + // disable 1D transforms - arrays here are 1D but their lengths/meanings + // don't match, between nodes and links + traceOut._length = null; +}; + +},{"../../components/color":570,"../../components/fx/hoverlabel_defaults":611,"../../lib":696,"../../plot_api/plot_template":734,"../../plots/domain":770,"./attributes":1034,"tinycolor2":514}],1039:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Plot = {}; + +Plot.attributes = _dereq_('./attributes'); +Plot.supplyDefaults = _dereq_('./defaults'); +Plot.calc = _dereq_('./calc'); +Plot.plot = _dereq_('./plot'); + +Plot.moduleType = 'trace'; +Plot.name = 'sankey'; +Plot.basePlotModule = _dereq_('./base_plot'); +Plot.categories = ['noOpacity']; +Plot.meta = { + +}; + +module.exports = Plot; + +},{"./attributes":1034,"./base_plot":1035,"./calc":1036,"./defaults":1038,"./plot":1040}],1040:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var render = _dereq_('./render'); +var Fx = _dereq_('../../components/fx'); +var Color = _dereq_('../../components/color'); +var Lib = _dereq_('../../lib'); +var cn = _dereq_('./constants').cn; + +var _ = Lib._; + +function renderableValuePresent(d) {return d !== '';} + +function ownTrace(selection, d) { + return selection.filter(function(s) {return s.key === d.traceId;}); +} + +function makeTranslucent(element, alpha) { + d3.select(element) + .select('path') + .style('fill-opacity', alpha); + d3.select(element) + .select('rect') + .style('fill-opacity', alpha); +} + +function makeTextContrasty(element) { + d3.select(element) + .select('text.name') + .style('fill', 'black'); +} + +function relatedLinks(d) { + return function(l) { + return d.node.sourceLinks.indexOf(l.link) !== -1 || d.node.targetLinks.indexOf(l.link) !== -1; + }; +} + +function relatedNodes(l) { + return function(d) { + return d.node.sourceLinks.indexOf(l.link) !== -1 || d.node.targetLinks.indexOf(l.link) !== -1; + }; +} + +function nodeHoveredStyle(sankeyNode, d, sankey) { + if(d && sankey) { + ownTrace(sankey, d) + .selectAll('.' + cn.sankeyLink) + .filter(relatedLinks(d)) + .call(linkHoveredStyle.bind(0, d, sankey, false)); + } +} + +function nodeNonHoveredStyle(sankeyNode, d, sankey) { + if(d && sankey) { + ownTrace(sankey, d) + .selectAll('.' + cn.sankeyLink) + .filter(relatedLinks(d)) + .call(linkNonHoveredStyle.bind(0, d, sankey, false)); + } +} + +function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) { + + var label = sankeyLink.datum().link.label; + + sankeyLink.style('fill-opacity', 0.4); + + if(label) { + ownTrace(sankey, d) + .selectAll('.' + cn.sankeyLink) + .filter(function(l) {return l.link.label === label;}) + .style('fill-opacity', 0.4); + } + + if(visitNodes) { + ownTrace(sankey, d) + .selectAll('.' + cn.sankeyNode) + .filter(relatedNodes(d)) + .call(nodeHoveredStyle); + } +} + +function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) { + + var label = sankeyLink.datum().link.label; + + sankeyLink.style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + + if(label) { + ownTrace(sankey, d) + .selectAll('.' + cn.sankeyLink) + .filter(function(l) {return l.link.label === label;}) + .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + } + + if(visitNodes) { + ownTrace(sankey, d) + .selectAll(cn.sankeyNode) + .filter(relatedNodes(d)) + .call(nodeNonHoveredStyle); + } +} + +// does not support array values for now +function castHoverOption(trace, attr) { + var labelOpts = trace.hoverlabel || {}; + var val = Lib.nestedProperty(labelOpts, attr).get(); + return Array.isArray(val) ? false : val; +} + +module.exports = function plot(gd, calcData) { + var fullLayout = gd._fullLayout; + var svg = fullLayout._paper; + var size = fullLayout._size; + + var linkSelect = function(element, d) { + var evt = d.link; + evt.originalEvent = d3.event; + gd._hoverdata = [evt]; + Fx.click(gd, { target: true }); + }; + + var linkHover = function(element, d, sankey) { + if(gd._fullLayout.hovermode === false) return; + d3.select(element).call(linkHoveredStyle.bind(0, d, sankey, true)); + if(d.link.trace.link.hoverinfo !== 'skip') { + gd.emit('plotly_hover', { + event: d3.event, + points: [d.link] + }); + } + + }; + + var sourceLabel = _(gd, 'source:') + ' '; + var targetLabel = _(gd, 'target:') + ' '; + var incomingLabel = _(gd, 'incoming flow count:') + ' '; + var outgoingLabel = _(gd, 'outgoing flow count:') + ' '; + + var linkHoverFollow = function(element, d) { + if(gd._fullLayout.hovermode === false) return; + var obj = d.link.trace.link; + if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return; + var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect(); + var boundingBox = element.getBoundingClientRect(); + var hoverCenterX = boundingBox.left + boundingBox.width / 2; + var hoverCenterY = boundingBox.top + boundingBox.height / 2; + + var tooltip = Fx.loneHover({ + x: hoverCenterX - rootBBox.left, + y: hoverCenterY - rootBBox.top, + name: d3.format(d.valueFormat)(d.link.value) + d.valueSuffix, + text: [ + d.link.label || '', + sourceLabel + d.link.source.label, + targetLabel + d.link.target.label + ].filter(renderableValuePresent).join('
'), + color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1), + borderColor: castHoverOption(obj, 'bordercolor'), + fontFamily: castHoverOption(obj, 'font.family'), + fontSize: castHoverOption(obj, 'font.size'), + fontColor: castHoverOption(obj, 'font.color'), + idealAlign: d3.event.x < hoverCenterX ? 'right' : 'left' + }, { + container: fullLayout._hoverlayer.node(), + outerContainer: fullLayout._paper.node(), + gd: gd + }); + + makeTranslucent(tooltip, 0.65); + makeTextContrasty(tooltip); + }; + + var linkUnhover = function(element, d, sankey) { + if(gd._fullLayout.hovermode === false) return; + d3.select(element).call(linkNonHoveredStyle.bind(0, d, sankey, true)); + if(d.link.trace.link.hoverinfo !== 'skip') { + gd.emit('plotly_unhover', { + event: d3.event, + points: [d.link] + }); + } + + Fx.loneUnhover(fullLayout._hoverlayer.node()); + }; + + var nodeSelect = function(element, d, sankey) { + var evt = d.node; + evt.originalEvent = d3.event; + gd._hoverdata = [evt]; + d3.select(element).call(nodeNonHoveredStyle, d, sankey); + Fx.click(gd, { target: true }); + }; + + var nodeHover = function(element, d, sankey) { + if(gd._fullLayout.hovermode === false) return; + d3.select(element).call(nodeHoveredStyle, d, sankey); + if(d.node.trace.node.hoverinfo !== 'skip') { + gd.emit('plotly_hover', { + event: d3.event, + points: [d.node] + }); + } + }; + + var nodeHoverFollow = function(element, d) { + if(gd._fullLayout.hovermode === false) return; + + var obj = d.node.trace.node; + if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return; + var nodeRect = d3.select(element).select('.' + cn.nodeRect); + var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect(); + var boundingBox = nodeRect.node().getBoundingClientRect(); + var hoverCenterX0 = boundingBox.left - 2 - rootBBox.left; + var hoverCenterX1 = boundingBox.right + 2 - rootBBox.left; + var hoverCenterY = boundingBox.top + boundingBox.height / 4 - rootBBox.top; + + var tooltip = Fx.loneHover({ + x0: hoverCenterX0, + x1: hoverCenterX1, + y: hoverCenterY, + name: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix, + text: [ + d.node.label, + incomingLabel + d.node.targetLinks.length, + outgoingLabel + d.node.sourceLinks.length + ].filter(renderableValuePresent).join('
'), + color: castHoverOption(obj, 'bgcolor') || d.tinyColorHue, + borderColor: castHoverOption(obj, 'bordercolor'), + fontFamily: castHoverOption(obj, 'font.family'), + fontSize: castHoverOption(obj, 'font.size'), + fontColor: castHoverOption(obj, 'font.color'), + idealAlign: 'left' + }, { + container: fullLayout._hoverlayer.node(), + outerContainer: fullLayout._paper.node(), + gd: gd + }); + + makeTranslucent(tooltip, 0.85); + makeTextContrasty(tooltip); + }; + + var nodeUnhover = function(element, d, sankey) { + if(gd._fullLayout.hovermode === false) return; + d3.select(element).call(nodeNonHoveredStyle, d, sankey); + if(d.node.trace.node.hoverinfo !== 'skip') { + gd.emit('plotly_unhover', { + event: d3.event, + points: [d.node] + }); + } + + Fx.loneUnhover(fullLayout._hoverlayer.node()); + }; + + render( + svg, + calcData, + { + width: size.w, + height: size.h, + margin: { + t: size.t, + r: size.r, + b: size.b, + l: size.l + } + }, + { + linkEvents: { + hover: linkHover, + follow: linkHoverFollow, + unhover: linkUnhover, + select: linkSelect + }, + nodeEvents: { + hover: nodeHover, + follow: nodeHoverFollow, + unhover: nodeUnhover, + select: nodeSelect + } + } + ); +}; + +},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"./constants":1037,"./render":1041,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1041:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var c = _dereq_('./constants'); +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var tinycolor = _dereq_('tinycolor2'); +var Color = _dereq_('../../components/color'); +var Drawing = _dereq_('../../components/drawing'); +var d3sankey = _dereq_('@plotly/d3-sankey').sankey; +var d3Force = _dereq_('d3-force'); +var Lib = _dereq_('../../lib'); +var isArrayOrTypedArray = Lib.isArrayOrTypedArray; +var isIndex = Lib.isIndex; +var gup = _dereq_('../../lib/gup'); +var keyFun = gup.keyFun; +var repeat = gup.repeat; +var unwrap = gup.unwrap; + +// basic data utilities + +function persistOriginalPlace(nodes) { + var i, distinctLayerPositions = []; + for(i = 0; i < nodes.length; i++) { + nodes[i].originalX = nodes[i].x; + nodes[i].originalY = nodes[i].y; + if(distinctLayerPositions.indexOf(nodes[i].x) === -1) { + distinctLayerPositions.push(nodes[i].x); + } + } + distinctLayerPositions.sort(function(a, b) {return a - b;}); + for(i = 0; i < nodes.length; i++) { + nodes[i].originalLayerIndex = distinctLayerPositions.indexOf(nodes[i].originalX); + nodes[i].originalLayer = nodes[i].originalLayerIndex / (distinctLayerPositions.length - 1); + } +} + +function saveCurrentDragPosition(d) { + d.lastDraggedX = d.x; + d.lastDraggedY = d.y; +} + +function sameLayer(d) { + return function(n) {return n.node.originalX === d.node.originalX;}; +} + +function switchToForceFormat(nodes) { + // force uses x, y as centers + for(var i = 0; i < nodes.length; i++) { + nodes[i].y = nodes[i].y + nodes[i].dy / 2; + } +} + +function switchToSankeyFormat(nodes) { + // sankey uses x, y as top left + for(var i = 0; i < nodes.length; i++) { + nodes[i].y = nodes[i].y - nodes[i].dy / 2; + } +} + +// view models + +function sankeyModel(layout, d, traceIndex) { + var trace = unwrap(d).trace; + var domain = trace.domain; + var nodeSpec = trace.node; + var linkSpec = trace.link; + var arrangement = trace.arrangement; + var horizontal = trace.orientation === 'h'; + var nodePad = trace.node.pad; + var nodeThickness = trace.node.thickness; + var nodeLineColor = trace.node.line.color; + var nodeLineWidth = trace.node.line.width; + var linkLineColor = trace.link.line.color; + var linkLineWidth = trace.link.line.width; + var valueFormat = trace.valueformat; + var valueSuffix = trace.valuesuffix; + var textFont = trace.textfont; + + var width = layout.width * (domain.x[1] - domain.x[0]); + var height = layout.height * (domain.y[1] - domain.y[0]); + + var links = []; + var hasLinkColorArray = isArrayOrTypedArray(linkSpec.color); + var linkedNodes = {}; + + var nodeCount = nodeSpec.label.length; + var i; + for(i = 0; i < linkSpec.value.length; i++) { + var val = linkSpec.value[i]; + // remove negative values, but keep zeros with special treatment + var source = linkSpec.source[i]; + var target = linkSpec.target[i]; + if(!(val > 0 && isIndex(source, nodeCount) && isIndex(target, nodeCount))) { + continue; + } + + source = +source; + target = +target; + linkedNodes[source] = linkedNodes[target] = true; + + links.push({ + pointNumber: i, + label: linkSpec.label[i], + color: hasLinkColorArray ? linkSpec.color[i] : linkSpec.color, + source: source, + target: target, + value: +val + }); + } + + var hasNodeColorArray = isArrayOrTypedArray(nodeSpec.color); + var nodes = []; + var removedNodes = false; + var nodeIndices = {}; + for(i = 0; i < nodeCount; i++) { + if(linkedNodes[i]) { + var l = nodeSpec.label[i]; + nodeIndices[i] = nodes.length; + nodes.push({ + pointNumber: i, + label: l, + color: hasNodeColorArray ? nodeSpec.color[i] : nodeSpec.color + }); + } + else removedNodes = true; + } + + // need to re-index links now, since we didn't put all the nodes in + if(removedNodes) { + for(i = 0; i < links.length; i++) { + links[i].source = nodeIndices[links[i].source]; + links[i].target = nodeIndices[links[i].target]; + } + } + + var sankey = d3sankey() + .size(horizontal ? [width, height] : [height, width]) + .nodeWidth(nodeThickness) + .nodePadding(nodePad) + .nodes(nodes) + .links(links) + .layout(c.sankeyIterations); + + if(sankey.nodePadding() < nodePad) { + Lib.warn('node.pad was reduced to ', sankey.nodePadding(), ' to fit within the figure.'); + } + + var node, sankeyNodes = sankey.nodes(); + for(var n = 0; n < sankeyNodes.length; n++) { + node = sankeyNodes[n]; + node.width = width; + node.height = height; + } + + switchToForceFormat(nodes); + + return { + key: traceIndex, + trace: trace, + guid: Math.floor(1e12 * (1 + Math.random())), + horizontal: horizontal, + width: width, + height: height, + nodePad: nodePad, + nodeLineColor: nodeLineColor, + nodeLineWidth: nodeLineWidth, + linkLineColor: linkLineColor, + linkLineWidth: linkLineWidth, + valueFormat: valueFormat, + valueSuffix: valueSuffix, + textFont: textFont, + translateX: domain.x[0] * layout.width + layout.margin.l, + translateY: layout.height - domain.y[1] * layout.height + layout.margin.t, + dragParallel: horizontal ? height : width, + dragPerpendicular: horizontal ? width : height, + nodes: nodes, + links: links, + arrangement: arrangement, + sankey: sankey, + forceLayouts: {}, + interactionState: { + dragInProgress: false, + hovered: false + } + }; +} + +function linkModel(uniqueKeys, d, l) { + var tc = tinycolor(l.color); + var basicKey = l.source.label + '|' + l.target.label; + var foundKey = uniqueKeys[basicKey]; + uniqueKeys[basicKey] = (foundKey || 0) + 1; + var key = basicKey + '__' + uniqueKeys[basicKey]; + + // for event data + l.trace = d.trace; + l.curveNumber = d.trace.index; + + return { + key: key, + traceId: d.key, + link: l, + tinyColorHue: Color.tinyRGB(tc), + tinyColorAlpha: tc.getAlpha(), + linkLineColor: d.linkLineColor, + linkLineWidth: d.linkLineWidth, + valueFormat: d.valueFormat, + valueSuffix: d.valueSuffix, + sankey: d.sankey, + interactionState: d.interactionState + }; +} + +function nodeModel(uniqueKeys, d, n) { + var tc = tinycolor(n.color), + zoneThicknessPad = c.nodePadAcross, + zoneLengthPad = d.nodePad / 2, + visibleThickness = n.dx, + visibleLength = Math.max(0.5, n.dy); + + var basicKey = n.label; + var foundKey = uniqueKeys[basicKey]; + uniqueKeys[basicKey] = (foundKey || 0) + 1; + var key = basicKey + '__' + uniqueKeys[basicKey]; + + // for event data + n.trace = d.trace; + n.curveNumber = d.trace.index; + + return { + key: key, + traceId: d.key, + node: n, + nodePad: d.nodePad, + nodeLineColor: d.nodeLineColor, + nodeLineWidth: d.nodeLineWidth, + textFont: d.textFont, + size: d.horizontal ? d.height : d.width, + visibleWidth: Math.ceil(visibleThickness), + visibleHeight: visibleLength, + zoneX: -zoneThicknessPad, + zoneY: -zoneLengthPad, + zoneWidth: visibleThickness + 2 * zoneThicknessPad, + zoneHeight: visibleLength + 2 * zoneLengthPad, + labelY: d.horizontal ? n.dy / 2 + 1 : n.dx / 2 + 1, + left: n.originalLayer === 1, + sizeAcross: d.width, + forceLayouts: d.forceLayouts, + horizontal: d.horizontal, + darkBackground: tc.getBrightness() <= 128, + tinyColorHue: Color.tinyRGB(tc), + tinyColorAlpha: tc.getAlpha(), + valueFormat: d.valueFormat, + valueSuffix: d.valueSuffix, + sankey: d.sankey, + arrangement: d.arrangement, + uniqueNodeLabelPathId: [d.guid, d.key, key].join(' '), + interactionState: d.interactionState + }; +} + +// rendering snippets + +function updateNodePositions(sankeyNode) { + sankeyNode + .attr('transform', function(d) { + return 'translate(' + d.node.x.toFixed(3) + ', ' + (d.node.y - d.node.dy / 2).toFixed(3) + ')'; + }); +} + +function linkPath(d) { + var nodes = d.sankey.nodes(); + switchToSankeyFormat(nodes); + var result = d.sankey.link()(d.link); + switchToForceFormat(nodes); + return result; +} + +function updateNodeShapes(sankeyNode) { + sankeyNode.call(updateNodePositions); +} + +function updateShapes(sankeyNode, sankeyLink) { + sankeyNode.call(updateNodeShapes); + sankeyLink.attr('d', linkPath); +} + +function sizeNode(rect) { + rect.attr('width', function(d) {return d.visibleWidth;}) + .attr('height', function(d) {return d.visibleHeight;}); +} + +function salientEnough(d) {return d.link.dy > 1 || d.linkLineWidth > 0;} + +function sankeyTransform(d) { + var offset = 'translate(' + d.translateX + ',' + d.translateY + ')'; + return offset + (d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)'); +} + +function nodeCentering(d) { + return 'translate(' + (d.horizontal ? 0 : d.labelY) + ' ' + (d.horizontal ? d.labelY : 0) + ')'; +} + +function textGuidePath(d) { + return d3.svg.line()([ + [d.horizontal ? (d.left ? -d.sizeAcross : d.visibleWidth + c.nodeTextOffsetHorizontal) : c.nodeTextOffsetHorizontal, 0], + [d.horizontal ? (d.left ? - c.nodeTextOffsetHorizontal : d.sizeAcross) : d.visibleHeight - c.nodeTextOffsetHorizontal, 0] + ]);} + +function sankeyInverseTransform(d) {return d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)';} +function textFlip(d) {return d.horizontal ? 'scale(1 1)' : 'scale(-1 1)';} +function nodeTextColor(d) {return d.darkBackground && !d.horizontal ? 'rgb(255,255,255)' : 'rgb(0,0,0)';} +function nodeTextOffset(d) {return d.horizontal && d.left ? '100%' : '0%';} + +// event handling + +function attachPointerEvents(selection, sankey, eventSet) { + selection + .on('.basic', null) // remove any preexisting handlers + .on('mouseover.basic', function(d) { + if(!d.interactionState.dragInProgress) { + eventSet.hover(this, d, sankey); + d.interactionState.hovered = [this, d]; + } + }) + .on('mousemove.basic', function(d) { + if(!d.interactionState.dragInProgress) { + eventSet.follow(this, d); + d.interactionState.hovered = [this, d]; + } + }) + .on('mouseout.basic', function(d) { + if(!d.interactionState.dragInProgress) { + eventSet.unhover(this, d, sankey); + d.interactionState.hovered = false; + } + }) + .on('click.basic', function(d) { + if(d.interactionState.hovered) { + eventSet.unhover(this, d, sankey); + d.interactionState.hovered = false; + } + if(!d.interactionState.dragInProgress) { + eventSet.select(this, d, sankey); + } + }); +} + +function attachDragHandler(sankeyNode, sankeyLink, callbacks) { + + var dragBehavior = d3.behavior.drag() + + .origin(function(d) {return d.node;}) + + .on('dragstart', function(d) { + if(d.arrangement === 'fixed') return; + Lib.raiseToTop(this); + d.interactionState.dragInProgress = d.node; + saveCurrentDragPosition(d.node); + if(d.interactionState.hovered) { + callbacks.nodeEvents.unhover.apply(0, d.interactionState.hovered); + d.interactionState.hovered = false; + } + if(d.arrangement === 'snap') { + var forceKey = d.traceId + '|' + Math.floor(d.node.originalX); + if(d.forceLayouts[forceKey]) { + d.forceLayouts[forceKey].alpha(1); + } else { // make a forceLayout iff needed + attachForce(sankeyNode, forceKey, d); + } + startForce(sankeyNode, sankeyLink, d, forceKey); + } + }) + + .on('drag', function(d) { + if(d.arrangement === 'fixed') return; + var x = d3.event.x; + var y = d3.event.y; + if(d.arrangement === 'snap') { + d.node.x = x; + d.node.y = y; + } else { + if(d.arrangement === 'freeform') { + d.node.x = x; + } + d.node.y = Math.max(d.node.dy / 2, Math.min(d.size - d.node.dy / 2, y)); + } + saveCurrentDragPosition(d.node); + if(d.arrangement !== 'snap') { + d.sankey.relayout(); + updateShapes(sankeyNode.filter(sameLayer(d)), sankeyLink); + } + }) + + .on('dragend', function(d) { + d.interactionState.dragInProgress = false; + }); + + sankeyNode + .on('.drag', null) // remove possible previous handlers + .call(dragBehavior); +} + +function attachForce(sankeyNode, forceKey, d) { + var nodes = d.sankey.nodes().filter(function(n) {return n.originalX === d.node.originalX;}); + d.forceLayouts[forceKey] = d3Force.forceSimulation(nodes) + .alphaDecay(0) + .force('collide', d3Force.forceCollide() + .radius(function(n) {return n.dy / 2 + d.nodePad / 2;}) + .strength(1) + .iterations(c.forceIterations)) + .force('constrain', snappingForce(sankeyNode, forceKey, nodes, d)) + .stop(); +} + +function startForce(sankeyNode, sankeyLink, d, forceKey) { + window.requestAnimationFrame(function faster() { + for(var i = 0; i < c.forceTicksPerFrame; i++) { + d.forceLayouts[forceKey].tick(); + } + d.sankey.relayout(); + updateShapes(sankeyNode.filter(sameLayer(d)), sankeyLink); + if(d.forceLayouts[forceKey].alpha() > 0) { + window.requestAnimationFrame(faster); + } + }); +} + +function snappingForce(sankeyNode, forceKey, nodes, d) { + return function _snappingForce() { + var maxVelocity = 0; + for(var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + if(n === d.interactionState.dragInProgress) { // constrain node position to the dragging pointer + n.x = n.lastDraggedX; + n.y = n.lastDraggedY; + } else { + n.vx = (n.originalX - n.x) / c.forceTicksPerFrame; // snap to layer + n.y = Math.min(d.size - n.dy / 2, Math.max(n.dy / 2, n.y)); // constrain to extent + } + maxVelocity = Math.max(maxVelocity, Math.abs(n.vx), Math.abs(n.vy)); + } + if(!d.interactionState.dragInProgress && maxVelocity < 0.1 && d.forceLayouts[forceKey].alpha() > 0) { + d.forceLayouts[forceKey].alpha(0); + } + }; +} + +// scene graph +module.exports = function(svg, styledData, layout, callbacks) { + var sankey = svg.selectAll('.' + c.cn.sankey) + .data(styledData + .filter(function(d) {return unwrap(d).trace.visible;}) + .map(sankeyModel.bind(null, layout)), + keyFun); + + sankey.exit() + .remove(); + + sankey.enter() + .append('g') + .classed(c.cn.sankey, true) + .style('box-sizing', 'content-box') + .style('position', 'absolute') + .style('left', 0) + .style('shape-rendering', 'geometricPrecision') + .style('pointer-events', 'auto') + .attr('transform', sankeyTransform); + + sankey.transition() + .ease(c.ease).duration(c.duration) + .attr('transform', sankeyTransform); + + var sankeyLinks = sankey.selectAll('.' + c.cn.sankeyLinks) + .data(repeat, keyFun); + + sankeyLinks.enter() + .append('g') + .classed(c.cn.sankeyLinks, true) + .style('fill', 'none'); + + var sankeyLink = sankeyLinks.selectAll('.' + c.cn.sankeyLink) + .data(function(d) { + var uniqueKeys = {}; + return d.sankey.links() + .filter(function(l) {return l.value;}) + .map(linkModel.bind(null, uniqueKeys, d)); + }, keyFun); + + sankeyLink.enter() + .append('path') + .classed(c.cn.sankeyLink, true) + .attr('d', linkPath) + .call(attachPointerEvents, sankey, callbacks.linkEvents); + + sankeyLink + .style('stroke', function(d) { + return salientEnough(d) ? Color.tinyRGB(tinycolor(d.linkLineColor)) : d.tinyColorHue; + }) + .style('stroke-opacity', function(d) { + return salientEnough(d) ? Color.opacity(d.linkLineColor) : d.tinyColorAlpha; + }) + .style('stroke-width', function(d) {return salientEnough(d) ? d.linkLineWidth : 1;}) + .style('fill', function(d) {return d.tinyColorHue;}) + .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + + sankeyLink.transition() + .ease(c.ease).duration(c.duration) + .attr('d', linkPath); + + sankeyLink.exit().transition() + .ease(c.ease).duration(c.duration) + .style('opacity', 0) + .remove(); + + var sankeyNodeSet = sankey.selectAll('.' + c.cn.sankeyNodeSet) + .data(repeat, keyFun); + + sankeyNodeSet.enter() + .append('g') + .classed(c.cn.sankeyNodeSet, true); + + sankeyNodeSet + .style('cursor', function(d) { + switch(d.arrangement) { + case 'fixed': return 'default'; + case 'perpendicular': return 'ns-resize'; + default: return 'move'; + } + }); + + var sankeyNode = sankeyNodeSet.selectAll('.' + c.cn.sankeyNode) + .data(function(d) { + var nodes = d.sankey.nodes(); + var uniqueKeys = {}; + persistOriginalPlace(nodes); + return nodes + .filter(function(n) {return n.value;}) + .map(nodeModel.bind(null, uniqueKeys, d)); + }, keyFun); + + sankeyNode.enter() + .append('g') + .classed(c.cn.sankeyNode, true) + .call(updateNodePositions) + .call(attachPointerEvents, sankey, callbacks.nodeEvents); + + sankeyNode + .call(attachDragHandler, sankeyLink, callbacks); // has to be here as it binds sankeyLink + + sankeyNode.transition() + .ease(c.ease).duration(c.duration) + .call(updateNodePositions); + + sankeyNode.exit().transition() + .ease(c.ease).duration(c.duration) + .style('opacity', 0) + .remove(); + + var nodeRect = sankeyNode.selectAll('.' + c.cn.nodeRect) + .data(repeat); + + nodeRect.enter() + .append('rect') + .classed(c.cn.nodeRect, true) + .call(sizeNode); + + nodeRect + .style('stroke-width', function(d) {return d.nodeLineWidth;}) + .style('stroke', function(d) {return Color.tinyRGB(tinycolor(d.nodeLineColor));}) + .style('stroke-opacity', function(d) {return Color.opacity(d.nodeLineColor);}) + .style('fill', function(d) {return d.tinyColorHue;}) + .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + + nodeRect.transition() + .ease(c.ease).duration(c.duration) + .call(sizeNode); + + var nodeCapture = sankeyNode.selectAll('.' + c.cn.nodeCapture) + .data(repeat); + + nodeCapture.enter() + .append('rect') + .classed(c.cn.nodeCapture, true) + .style('fill-opacity', 0); + + nodeCapture + .attr('x', function(d) {return d.zoneX;}) + .attr('y', function(d) {return d.zoneY;}) + .attr('width', function(d) {return d.zoneWidth;}) + .attr('height', function(d) {return d.zoneHeight;}); + + var nodeCentered = sankeyNode.selectAll('.' + c.cn.nodeCentered) + .data(repeat); + + nodeCentered.enter() + .append('g') + .classed(c.cn.nodeCentered, true) + .attr('transform', nodeCentering); + + nodeCentered + .transition() + .ease(c.ease).duration(c.duration) + .attr('transform', nodeCentering); + + var nodeLabelGuide = nodeCentered.selectAll('.' + c.cn.nodeLabelGuide) + .data(repeat); + + nodeLabelGuide.enter() + .append('path') + .classed(c.cn.nodeLabelGuide, true) + .attr('id', function(d) {return d.uniqueNodeLabelPathId;}) + .attr('d', textGuidePath) + .attr('transform', sankeyInverseTransform); + + nodeLabelGuide + .transition() + .ease(c.ease).duration(c.duration) + .attr('d', textGuidePath) + .attr('transform', sankeyInverseTransform); + + var nodeLabel = nodeCentered.selectAll('.' + c.cn.nodeLabel) + .data(repeat); + + nodeLabel.enter() + .append('text') + .classed(c.cn.nodeLabel, true) + .attr('transform', textFlip) + .style('user-select', 'none') + .style('cursor', 'default') + .style('fill', 'black'); + + nodeLabel + .style('text-shadow', function(d) { + return d.horizontal ? '-1px 1px 1px #fff, 1px 1px 1px #fff, 1px -1px 1px #fff, -1px -1px 1px #fff' : 'none'; + }) + .each(function(d) {Drawing.font(nodeLabel, d.textFont);}); + + nodeLabel + .transition() + .ease(c.ease).duration(c.duration) + .attr('transform', textFlip); + + var nodeLabelTextPath = nodeLabel.selectAll('.' + c.cn.nodeLabelTextPath) + .data(repeat); + + nodeLabelTextPath.enter() + .append('textPath') + .classed(c.cn.nodeLabelTextPath, true) + .attr('alignment-baseline', 'middle') + .attr('xlink:href', function(d) {return '#' + d.uniqueNodeLabelPathId;}) + .attr('startOffset', nodeTextOffset) + .style('fill', nodeTextColor); + + nodeLabelTextPath + .text(function(d) {return d.horizontal || d.node.dy > 5 ? d.node.label : '';}) + .attr('text-anchor', function(d) {return d.horizontal && d.left ? 'end' : 'start';}); + + nodeLabelTextPath + .transition() + .ease(c.ease).duration(c.duration) + .attr('startOffset', nodeTextOffset) + .style('fill', nodeTextColor); +}; + +},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../lib/gup":693,"./constants":1037,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"@plotly/d3-sankey":46,"d3-force":144,"tinycolor2":514}],1042:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + + +// arrayOk attributes, merge them into calcdata array +module.exports = function arraysToCalcdata(cd, trace) { + + // so each point knows which index it originally came from + for(var i = 0; i < cd.length; i++) cd[i].i = i; + + Lib.mergeArray(trace.text, cd, 'tx'); + Lib.mergeArray(trace.hovertext, cd, 'htx'); + Lib.mergeArray(trace.customdata, cd, 'data'); + Lib.mergeArray(trace.textposition, cd, 'tp'); + if(trace.textfont) { + Lib.mergeArray(trace.textfont.size, cd, 'ts'); + Lib.mergeArray(trace.textfont.color, cd, 'tc'); + Lib.mergeArray(trace.textfont.family, cd, 'tf'); + } + + var marker = trace.marker; + if(marker) { + Lib.mergeArray(marker.size, cd, 'ms'); + Lib.mergeArray(marker.opacity, cd, 'mo'); + Lib.mergeArray(marker.symbol, cd, 'mx'); + Lib.mergeArray(marker.color, cd, 'mc'); + + var markerLine = marker.line; + if(marker.line) { + Lib.mergeArray(markerLine.color, cd, 'mlc'); + Lib.mergeArray(markerLine.width, cd, 'mlw'); + } + + var markerGradient = marker.gradient; + if(markerGradient && markerGradient.type !== 'none') { + Lib.mergeArray(markerGradient.type, cd, 'mgt'); + Lib.mergeArray(markerGradient.color, cd, 'mgc'); + } + } +}; + +},{"../../lib":696}],1043:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var fontAttrs = _dereq_('../../plots/font_attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; + +var Drawing = _dereq_('../../components/drawing'); +var constants = _dereq_('./constants'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = { + x: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + anim: true, + + }, + x0: { + valType: 'any', + dflt: 0, + + editType: 'calc+clearAxisTypes', + anim: true, + + }, + dx: { + valType: 'number', + dflt: 1, + + editType: 'calc', + anim: true, + + }, + y: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + anim: true, + + }, + y0: { + valType: 'any', + dflt: 0, + + editType: 'calc+clearAxisTypes', + anim: true, + + }, + dy: { + valType: 'number', + dflt: 1, + + editType: 'calc', + anim: true, + + }, + + stackgroup: { + valType: 'string', + + dflt: '', + editType: 'calc', + + }, + orientation: { + valType: 'enumerated', + + values: ['v', 'h'], + editType: 'calc', + + }, + groupnorm: { + valType: 'enumerated', + values: ['', 'fraction', 'percent'], + dflt: '', + + editType: 'calc', + + }, + stackgaps: { + valType: 'enumerated', + values: ['infer zero', 'interpolate'], + dflt: 'infer zero', + + editType: 'calc', + + }, + + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'calc', + + }, + hovertext: { + valType: 'string', + + dflt: '', + arrayOk: true, + editType: 'style', + + }, + mode: { + valType: 'flaglist', + flags: ['lines', 'markers', 'text'], + extras: ['none'], + + editType: 'calc', + + }, + hoveron: { + valType: 'flaglist', + flags: ['points', 'fills'], + + editType: 'style', + + }, + line: { + color: { + valType: 'color', + + editType: 'style', + anim: true, + + }, + width: { + valType: 'number', + min: 0, + dflt: 2, + + editType: 'style', + anim: true, + + }, + shape: { + valType: 'enumerated', + values: ['linear', 'spline', 'hv', 'vh', 'hvh', 'vhv'], + dflt: 'linear', + + editType: 'plot', + + }, + smoothing: { + valType: 'number', + min: 0, + max: 1.3, + dflt: 1, + + editType: 'plot', + + }, + dash: extendFlat({}, dash, {editType: 'style'}), + simplify: { + valType: 'boolean', + dflt: true, + + editType: 'plot', + + }, + editType: 'plot' + }, + + connectgaps: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + cliponaxis: { + valType: 'boolean', + dflt: true, + + editType: 'plot', + + }, + + fill: { + valType: 'enumerated', + values: ['none', 'tozeroy', 'tozerox', 'tonexty', 'tonextx', 'toself', 'tonext'], + + editType: 'calc', + + }, + fillcolor: { + valType: 'color', + + editType: 'style', + anim: true, + + }, + marker: extendFlat({ + symbol: { + valType: 'enumerated', + values: Drawing.symbolList, + dflt: 'circle', + arrayOk: true, + + editType: 'style', + + }, + opacity: { + valType: 'number', + min: 0, + max: 1, + arrayOk: true, + + editType: 'style', + anim: true, + + }, + size: { + valType: 'number', + min: 0, + dflt: 6, + arrayOk: true, + + editType: 'calc', + anim: true, + + }, + maxdisplayed: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'plot', + + }, + sizeref: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + sizemin: { + valType: 'number', + min: 0, + dflt: 0, + + editType: 'calc', + + }, + sizemode: { + valType: 'enumerated', + values: ['diameter', 'area'], + dflt: 'diameter', + + editType: 'calc', + + }, + + colorbar: colorbarAttrs, + + line: extendFlat({ + width: { + valType: 'number', + min: 0, + arrayOk: true, + + editType: 'style', + anim: true, + + }, + editType: 'calc' + }, + colorAttributes('marker.line', {anim: true}) + ), + gradient: { + type: { + valType: 'enumerated', + values: ['radial', 'horizontal', 'vertical', 'none'], + arrayOk: true, + dflt: 'none', + + editType: 'calc', + + }, + color: { + valType: 'color', + arrayOk: true, + + editType: 'calc', + + }, + editType: 'calc' + }, + editType: 'calc' + }, + colorAttributes('marker', {anim: true}) + ), + selected: { + marker: { + opacity: { + valType: 'number', + min: 0, + max: 1, + + editType: 'style', + + }, + color: { + valType: 'color', + + editType: 'style', + + }, + size: { + valType: 'number', + min: 0, + + editType: 'style', + + }, + editType: 'style' + }, + textfont: { + color: { + valType: 'color', + + editType: 'style', + + }, + editType: 'style' + }, + editType: 'style' + }, + unselected: { + marker: { + opacity: { + valType: 'number', + min: 0, + max: 1, + + editType: 'style', + + }, + color: { + valType: 'color', + + editType: 'style', + + }, + size: { + valType: 'number', + min: 0, + + editType: 'style', + + }, + editType: 'style' + }, + textfont: { + color: { + valType: 'color', + + editType: 'style', + + }, + editType: 'style' + }, + editType: 'style' + }, + + textposition: { + valType: 'enumerated', + values: [ + 'top left', 'top center', 'top right', + 'middle left', 'middle center', 'middle right', + 'bottom left', 'bottom center', 'bottom right' + ], + dflt: 'middle center', + arrayOk: true, + + editType: 'calc', + + }, + textfont: fontAttrs({ + editType: 'calc', + colorEditType: 'style', + arrayOk: true, + + }), + + r: { + valType: 'data_array', + editType: 'calc', + + }, + t: { + valType: 'data_array', + editType: 'calc', + + } +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../components/drawing":595,"../../components/drawing/attributes":594,"../../lib/extend":685,"../../plots/font_attributes":771,"./constants":1047}],1044:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var Lib = _dereq_('../../lib'); + +var Axes = _dereq_('../../plots/cartesian/axes'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var subTypes = _dereq_('./subtypes'); +var calcColorscale = _dereq_('./colorscale_calc'); +var arraysToCalcdata = _dereq_('./arrays_to_calcdata'); +var calcSelection = _dereq_('./calc_selection'); + +function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var xa = Axes.getFromId(gd, trace.xaxis || 'x'); + var ya = Axes.getFromId(gd, trace.yaxis || 'y'); + var x = xa.makeCalcdata(trace, 'x'); + var y = ya.makeCalcdata(trace, 'y'); + var serieslen = trace._length; + var cd = new Array(serieslen); + var ids = trace.ids; + var stackGroupOpts = getStackOpts(trace, fullLayout, xa, ya); + var interpolateGaps = false; + var isV, i, j, k, interpolate, vali; + + setFirstScatter(fullLayout, trace); + + var xAttr = 'x'; + var yAttr = 'y'; + var posAttr; + if(stackGroupOpts) { + stackGroupOpts.traceIndices.push(trace.index); + isV = stackGroupOpts.orientation === 'v'; + // size, like we use for bar + if(isV) { + yAttr = 's'; + posAttr = 'x'; + } + else { + xAttr = 's'; + posAttr = 'y'; + } + interpolate = stackGroupOpts.stackgaps === 'interpolate'; + } + else { + var ppad = calcMarkerSize(trace, serieslen); + calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); + } + + for(i = 0; i < serieslen; i++) { + var cdi = cd[i] = {}; + var xValid = isNumeric(x[i]); + var yValid = isNumeric(y[i]); + if(xValid && yValid) { + cdi[xAttr] = x[i]; + cdi[yAttr] = y[i]; + } + // if we're stacking we need to hold on to all valid positions + // even with invalid sizes + else if(stackGroupOpts && (isV ? xValid : yValid)) { + cdi[posAttr] = isV ? x[i] : y[i]; + cdi.gap = true; + if(interpolate) { + cdi.s = BADNUM; + interpolateGaps = true; + } + else { + cdi.s = 0; + } + } + else { + cdi[xAttr] = cdi[yAttr] = BADNUM; + } + + if(ids) { + cdi.id = String(ids[i]); + } + } + + arraysToCalcdata(cd, trace); + calcColorscale(trace); + calcSelection(cd, trace); + + if(stackGroupOpts) { + // remove bad positions and sort + // note that original indices get added to cd in arraysToCalcdata + i = 0; + while(i < cd.length) { + if(cd[i][posAttr] === BADNUM) { + cd.splice(i, 1); + } + else i++; + } + + Lib.sort(cd, function(a, b) { + return (a[posAttr] - b[posAttr]) || (a.i - b.i); + }); + + if(interpolateGaps) { + // first fill the beginning with constant from the first point + i = 0; + while(i < cd.length - 1 && cd[i].gap) { + i++; + } + vali = cd[i].s; + if(!vali) vali = cd[i].s = 0; // in case of no data AT ALL in this trace - use 0 + for(j = 0; j < i; j++) { + cd[j].s = vali; + } + // then fill the end with constant from the last point + k = cd.length - 1; + while(k > i && cd[k].gap) { + k--; + } + vali = cd[k].s; + for(j = cd.length - 1; j > k; j--) { + cd[j].s = vali; + } + // now interpolate internal gaps linearly + while(i < k) { + i++; + if(cd[i].gap) { + j = i + 1; + while(cd[j].gap) { + j++; + } + var pos0 = cd[i - 1][posAttr]; + var size0 = cd[i - 1].s; + var m = (cd[j].s - size0) / (cd[j][posAttr] - pos0); + while(i < j) { + cd[i].s = size0 + (cd[i][posAttr] - pos0) * m; + i++; + } + } + } + } + } + + return cd; +} + +function calcAxisExpansion(gd, trace, xa, ya, x, y, ppad) { + var serieslen = trace._length; + var fullLayout = gd._fullLayout; + var xId = xa._id; + var yId = ya._id; + var firstScatter = fullLayout._firstScatter[firstScatterGroup(trace)] === trace.uid; + var stackOrientation = (getStackOpts(trace, fullLayout, xa, ya) || {}).orientation; + var fill = trace.fill; + + // cancel minimum tick spacings (only applies to bars and boxes) + xa._minDtick = 0; + ya._minDtick = 0; + + // check whether bounds should be tight, padded, extended to zero... + // most cases both should be padded on both ends, so start with that. + var xOptions = {padded: true}; + var yOptions = {padded: true}; + + if(ppad) { + xOptions.ppad = yOptions.ppad = ppad; + } + + // TODO: text size + + var openEnded = serieslen < 2 || (x[0] !== x[serieslen - 1]) || (y[0] !== y[serieslen - 1]); + + // include zero (tight) and extremes (padded) if fill to zero + // (unless the shape is closed, then it's just filling the shape regardless) + if(openEnded && ( + (fill === 'tozerox') || + ((fill === 'tonextx') && (firstScatter || stackOrientation === 'h')) + )) { + xOptions.tozero = true; + } + + // if no error bars, markers or text, or fill to y=0 remove x padding + else if(!(trace.error_y || {}).visible && ( + (fill === 'tonexty' || fill === 'tozeroy') || + (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace)) + )) { + xOptions.padded = false; + xOptions.ppad = 0; + } + + // now check for y - rather different logic, though still mostly padded both ends + // include zero (tight) and extremes (padded) if fill to zero + // (unless the shape is closed, then it's just filling the shape regardless) + if(openEnded && ( + (fill === 'tozeroy') || + ((fill === 'tonexty') && (firstScatter || stackOrientation === 'v')) + )) { + yOptions.tozero = true; + } + + // tight y: any x fill + else if(fill === 'tonextx' || fill === 'tozerox') { + yOptions.padded = false; + } + + // N.B. asymmetric splom traces call this with blank {} xa or ya + if(xId) trace._extremes[xId] = Axes.findExtremes(xa, x, xOptions); + if(yId) trace._extremes[yId] = Axes.findExtremes(ya, y, yOptions); +} + +function calcMarkerSize(trace, serieslen) { + if(!subTypes.hasMarkers(trace)) return; + + // Treat size like x or y arrays --- Run d2c + // this needs to go before ppad computation + var marker = trace.marker; + var sizeref = 1.6 * (trace.marker.sizeref || 1); + var markerTrans; + + if(trace.marker.sizemode === 'area') { + markerTrans = function(v) { + return Math.max(Math.sqrt((v || 0) / sizeref), 3); + }; + } else { + markerTrans = function(v) { + return Math.max((v || 0) / sizeref, 3); + }; + } + + if(Lib.isArrayOrTypedArray(marker.size)) { + // I tried auto-type but category and dates dont make much sense. + var ax = {type: 'linear'}; + Axes.setConvert(ax); + + var s = ax.makeCalcdata(trace.marker, 'size'); + + var sizeOut = new Array(serieslen); + for(var i = 0; i < serieslen; i++) { + sizeOut[i] = markerTrans(s[i]); + } + return sizeOut; + + } else { + return markerTrans(marker.size); + } +} + +/** + * mark the first scatter trace for each subplot + * note that scatter and scattergl each get their own first trace + * note also that I'm doing this during calc rather than supplyDefaults + * so I don't need to worry about transforms, but if we ever do + * per-trace calc this will get confused. + */ +function setFirstScatter(fullLayout, trace) { + var group = firstScatterGroup(trace); + var firstScatter = fullLayout._firstScatter; + if(!firstScatter[group]) firstScatter[group] = trace.uid; +} + +function firstScatterGroup(trace) { + var stackGroup = trace.stackgroup; + return trace.xaxis + trace.yaxis + trace.type + + (stackGroup ? '-' + stackGroup : ''); +} + +function getStackOpts(trace, fullLayout, xa, ya) { + var stackGroup = trace.stackgroup; + if(!stackGroup) return; + var stackOpts = fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup]; + var stackAx = stackOpts.orientation === 'v' ? ya : xa; + // Allow stacking only on numeric axes + // calc is a little late to be figuring this out, but during supplyDefaults + // we don't know the axis type yet + if(stackAx.type === 'linear' || stackAx.type === 'log') return stackOpts; +} + +module.exports = { + calc: calc, + calcMarkerSize: calcMarkerSize, + calcAxisExpansion: calcAxisExpansion, + setFirstScatter: setFirstScatter, + getStackOpts: getStackOpts +}; + +},{"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axes":744,"./arrays_to_calcdata":1042,"./calc_selection":1045,"./colorscale_calc":1046,"./subtypes":1067,"fast-isnumeric":214}],1045:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +module.exports = function calcSelection(cd, trace) { + if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { + Lib.tagSelected(cd, trace); + } +}; + +},{"../../lib":696}],1046:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var calcColorscale = _dereq_('../../components/colorscale/calc'); + +var subTypes = _dereq_('./subtypes'); + + +module.exports = function calcMarkerColorscale(trace) { + if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) { + calcColorscale(trace, trace.line.color, 'line', 'c'); + } + + if(subTypes.hasMarkers(trace)) { + if(hasColorscale(trace, 'marker')) { + calcColorscale(trace, trace.marker.color, 'marker', 'c'); + } + if(hasColorscale(trace, 'marker.line')) { + calcColorscale(trace, trace.marker.line.color, 'marker.line', 'c'); + } + } +}; + +},{"../../components/colorscale/calc":578,"../../components/colorscale/has_colorscale":584,"./subtypes":1067}],1047:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + PTS_LINESONLY: 20, + + // fixed parameters of clustering and clipping algorithms + + // fraction of clustering tolerance "so close we don't even consider it a new point" + minTolerance: 0.2, + // how fast does clustering tolerance increase as you get away from the visible region + toleranceGrowth: 10, + + // number of viewport sizes away from the visible region + // at which we clip all lines to the perimeter + maxScreensAway: 20 +}; + +},{}],1048:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var calc = _dereq_('./calc'); + +/* + * Scatter stacking & normalization calculations + * runs per subplot, and can handle multiple stacking groups + */ + +module.exports = function crossTraceCalc(gd, plotinfo) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + var subplot = xa._id + ya._id; + + var subplotStackOpts = gd._fullLayout._scatterStackOpts[subplot]; + if(!subplotStackOpts) return; + + var calcTraces = gd.calcdata; + + var i, j, k, i2, cd, cd0, posj, sumj, norm; + var groupOpts, interpolate, groupnorm, posAttr, valAttr; + var hasAnyBlanks; + + for(var stackGroup in subplotStackOpts) { + groupOpts = subplotStackOpts[stackGroup]; + var indices = groupOpts.traceIndices; + + // can get here with no indices if the stack axis is non-numeric + if(!indices.length) continue; + + interpolate = groupOpts.stackgaps === 'interpolate'; + groupnorm = groupOpts.groupnorm; + if(groupOpts.orientation === 'v') { + posAttr = 'x'; + valAttr = 'y'; + } + else { + posAttr = 'y'; + valAttr = 'x'; + } + hasAnyBlanks = new Array(indices.length); + for(i = 0; i < hasAnyBlanks.length; i++) { + hasAnyBlanks[i] = false; + } + + // Collect the complete set of all positions across ALL traces. + // Start with the first trace, then interleave items from later traces + // as needed. + // Fill in mising items as we go. + cd0 = calcTraces[indices[0]]; + var allPositions = new Array(cd0.length); + for(i = 0; i < cd0.length; i++) { + allPositions[i] = cd0[i][posAttr]; + } + + for(i = 1; i < indices.length; i++) { + cd = calcTraces[indices[i]]; + + for(j = k = 0; j < cd.length; j++) { + posj = cd[j][posAttr]; + for(; posj > allPositions[k] && k < allPositions.length; k++) { + // the current trace is missing a position from some previous trace(s) + insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr); + j++; + } + if(posj !== allPositions[k]) { + // previous trace(s) are missing a position from the current trace + for(i2 = 0; i2 < i; i2++) { + insertBlank(calcTraces[indices[i2]], k, posj, i2, hasAnyBlanks, interpolate, posAttr); + } + allPositions.splice(k, 0, posj); + } + k++; + } + for(; k < allPositions.length; k++) { + insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr); + j++; + } + } + + var serieslen = allPositions.length; + + // stack (and normalize)! + for(j = 0; j < cd0.length; j++) { + sumj = cd0[j][valAttr] = cd0[j].s; + for(i = 1; i < indices.length; i++) { + cd = calcTraces[indices[i]]; + cd[0].trace._rawLength = cd[0].trace._length; + cd[0].trace._length = serieslen; + sumj += cd[j].s; + cd[j][valAttr] = sumj; + } + + if(groupnorm) { + norm = ((groupnorm === 'fraction') ? sumj : (sumj / 100)) || 1; + for(i = 0; i < indices.length; i++) { + var cdj = calcTraces[indices[i]][j]; + cdj[valAttr] /= norm; + cdj.sNorm = cdj.s / norm; + } + } + } + + // autorange + for(i = 0; i < indices.length; i++) { + cd = calcTraces[indices[i]]; + var trace = cd[0].trace; + var ppad = calc.calcMarkerSize(trace, trace._rawLength); + var arrayPad = Array.isArray(ppad); + if((ppad && hasAnyBlanks[i]) || arrayPad) { + var ppadRaw = ppad; + ppad = new Array(serieslen); + for(j = 0; j < serieslen; j++) { + ppad[j] = cd[j].gap ? 0 : (arrayPad ? ppadRaw[cd[j].i] : ppadRaw); + } + } + var x = new Array(serieslen); + var y = new Array(serieslen); + for(j = 0; j < serieslen; j++) { + x[j] = cd[j].x; + y[j] = cd[j].y; + } + calc.calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); + + // while we're here (in a loop over all traces in the stack) + // record the orientation, so hover can find it easily + cd[0].t.orientation = groupOpts.orientation; + } + } +}; + +function insertBlank(calcTrace, index, position, traceIndex, hasAnyBlanks, interpolate, posAttr) { + hasAnyBlanks[traceIndex] = true; + var newEntry = { + i: null, + gap: true, + s: 0 + }; + newEntry[posAttr] = position; + calcTrace.splice(index, 0, newEntry); + // Even if we're not interpolating, if one trace has multiple + // values at the same position and this trace only has one value there, + // we just duplicate that one value rather than insert a zero. + // We also make it look like a real point - because it's ambiguous which + // one really is the real one! + if(index && position === calcTrace[index - 1][posAttr]) { + var prevEntry = calcTrace[index - 1]; + newEntry.s = prevEntry.s; + // TODO is it going to cause any problems to have multiple + // calcdata points with the same index? + newEntry.i = prevEntry.i; + newEntry.gap = prevEntry.gap; + } + else if(interpolate) { + newEntry.s = getInterp(calcTrace, index, position, posAttr); + } + if(!index) { + // t and trace need to stay on the first cd entry + calcTrace[0].t = calcTrace[1].t; + calcTrace[0].trace = calcTrace[1].trace; + delete calcTrace[1].t; + delete calcTrace[1].trace; + } +} + +function getInterp(calcTrace, index, position, posAttr) { + var pt0 = calcTrace[index - 1]; + var pt1 = calcTrace[index + 1]; + if(!pt1) return pt0.s; + if(!pt0) return pt1.s; + return pt0.s + (pt1.s - pt0.s) * (position - pt0[posAttr]) / (pt1[posAttr] - pt0[posAttr]); +} + +},{"./calc":1044}],1049:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// remove opacity for any trace that has a fill or is filled to +module.exports = function crossTraceDefaults(fullData) { + for(var i = 0; i < fullData.length; i++) { + var tracei = fullData[i]; + if(tracei.type !== 'scatter') continue; + + var filli = tracei.fill; + if(filli === 'none' || filli === 'toself') continue; + + tracei.opacity = undefined; + + if(filli === 'tonexty' || filli === 'tonextx') { + for(var j = i - 1; j >= 0; j--) { + var tracej = fullData[j]; + + if((tracej.type === 'scatter') && + (tracej.xaxis === tracei.xaxis) && + (tracej.yaxis === tracei.yaxis)) { + tracej.opacity = undefined; + break; + } + } + } + } +}; + +},{}],1050:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); + +var attributes = _dereq_('./attributes'); +var constants = _dereq_('./constants'); +var subTypes = _dereq_('./subtypes'); +var handleXYDefaults = _dereq_('./xy_defaults'); +var handleStackDefaults = _dereq_('./stack_defaults'); +var handleMarkerDefaults = _dereq_('./marker_defaults'); +var handleLineDefaults = _dereq_('./line_defaults'); +var handleLineShapeDefaults = _dereq_('./line_shape_defaults'); +var handleTextDefaults = _dereq_('./text_defaults'); +var handleFillColorDefaults = _dereq_('./fillcolor_defaults'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleXYDefaults(traceIn, traceOut, layout, coerce); + if(!len) traceOut.visible = false; + + if(!traceOut.visible) return; + + var stackGroupOpts = handleStackDefaults(traceIn, traceOut, layout, coerce); + + var defaultMode = !stackGroupOpts && (len < constants.PTS_LINESONLY) ? + 'lines+markers' : 'lines'; + coerce('text'); + coerce('hovertext'); + coerce('mode', defaultMode); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + handleLineShapeDefaults(traceIn, traceOut, coerce); + coerce('connectgaps'); + coerce('line.simplify'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + var dfltHoverOn = []; + + if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { + coerce('cliponaxis'); + coerce('marker.maxdisplayed'); + dfltHoverOn.push('points'); + } + + // It's possible for this default to be changed by a later trace. + // We handle that case in some hacky code inside handleStackDefaults. + coerce('fill', stackGroupOpts ? stackGroupOpts.fillDflt : 'none'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + } + + if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { + dfltHoverOn.push('fills'); + } + coerce('hoveron', dfltHoverOn.join('+') || 'points'); + + var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'x', inherit: 'y'}); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../../registry":827,"./attributes":1043,"./constants":1047,"./fillcolor_defaults":1052,"./line_defaults":1056,"./line_shape_defaults":1058,"./marker_defaults":1062,"./stack_defaults":1065,"./subtypes":1067,"./text_defaults":1068,"./xy_defaults":1069}],1051:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +/** Fill hover 'pointData' container with 'correct' hover text value + * + * - If trace hoverinfo contains a 'text' flag and hovertext is not set, + * the text elements will be seen in the hover labels. + * + * - If trace hoverinfo contains a 'text' flag and hovertext is set, + * hovertext takes precedence over text + * i.e. the hoverinfo elements will be seen in the hover labels + * + * @param {object} calcPt + * @param {object} trace + * @param {object || array} contOut (mutated here) + */ +module.exports = function fillHoverText(calcPt, trace, contOut) { + var fill = Array.isArray(contOut) ? + function(v) { contOut.push(v); } : + function(v) { contOut.text = v; }; + + var htx = Lib.extractOption(calcPt, trace, 'htx', 'hovertext'); + if(isValid(htx)) return fill(htx); + + var tx = Lib.extractOption(calcPt, trace, 'tx', 'text'); + if(isValid(tx)) return fill(tx); +}; + +// accept all truthy values and 0 (which gets cast to '0' in the hover labels) +function isValid(v) { + return v || v === 0; +} + +},{"../../lib":696}],1052:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../../components/color'); +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; + +module.exports = function fillColorDefaults(traceIn, traceOut, defaultColor, coerce) { + var inheritColorFromMarker = false; + + if(traceOut.marker) { + // don't try to inherit a color array + var markerColor = traceOut.marker.color, + markerLineColor = (traceOut.marker.line || {}).color; + + if(markerColor && !isArrayOrTypedArray(markerColor)) { + inheritColorFromMarker = markerColor; + } + else if(markerLineColor && !isArrayOrTypedArray(markerLineColor)) { + inheritColorFromMarker = markerLineColor; + } + } + + coerce('fillcolor', Color.addOpacity( + (traceOut.line || {}).color || + inheritColorFromMarker || + defaultColor, 0.5 + )); +}; + +},{"../../components/color":570,"../../lib":696}],1053:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../../components/color'); +var subtypes = _dereq_('./subtypes'); + + +module.exports = function getTraceColor(trace, di) { + var lc, tc; + + // TODO: text modes + + if(trace.mode === 'lines') { + lc = trace.line.color; + return (lc && Color.opacity(lc)) ? + lc : trace.fillcolor; + } + else if(trace.mode === 'none') { + return trace.fill ? trace.fillcolor : ''; + } + else { + var mc = di.mcc || (trace.marker || {}).color, + mlc = di.mlcc || ((trace.marker || {}).line || {}).color; + + tc = (mc && Color.opacity(mc)) ? mc : + (mlc && Color.opacity(mlc) && + (di.mlw || ((trace.marker || {}).line || {}).width)) ? mlc : ''; + + if(tc) { + // make sure the points aren't TOO transparent + if(Color.opacity(tc) < 0.3) { + return Color.addOpacity(tc, 0.3); + } + else return tc; + } + else { + lc = (trace.line || {}).color; + return (lc && Color.opacity(lc) && + subtypes.hasLines(trace) && trace.line.width) ? + lc : trace.fillcolor; + } + } +}; + +},{"../../components/color":570,"./subtypes":1067}],1054:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Fx = _dereq_('../../components/fx'); +var Registry = _dereq_('../../registry'); +var getTraceColor = _dereq_('./get_trace_color'); +var Color = _dereq_('../../components/color'); +var fillHoverText = _dereq_('./fill_hover_text'); + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var trace = cd[0].trace; + var xa = pointData.xa; + var ya = pointData.ya; + var xpx = xa.c2p(xval); + var ypx = ya.c2p(yval); + var pt = [xpx, ypx]; + var hoveron = trace.hoveron || ''; + var minRad = (trace.mode.indexOf('markers') !== -1) ? 3 : 0.5; + + // look for points to hover on first, then take fills only if we + // didn't find a point + if(hoveron.indexOf('points') !== -1) { + var dx = function(di) { + // dx and dy are used in compare modes - here we want to always + // prioritize the closest data point, at least as long as markers are + // the same size or nonexistent, but still try to prioritize small markers too. + var rad = Math.max(3, di.mrc || 0); + var kink = 1 - 1 / rad; + var dxRaw = Math.abs(xa.c2p(di.x) - xpx); + var d = (dxRaw < rad) ? (kink * dxRaw / rad) : (dxRaw - rad + kink); + return d; + }; + var dy = function(di) { + var rad = Math.max(3, di.mrc || 0); + var kink = 1 - 1 / rad; + var dyRaw = Math.abs(ya.c2p(di.y) - ypx); + return (dyRaw < rad) ? (kink * dyRaw / rad) : (dyRaw - rad + kink); + }; + var dxy = function(di) { + // scatter points: d.mrc is the calculated marker radius + // adjust the distance so if you're inside the marker it + // always will show up regardless of point size, but + // prioritize smaller points + var rad = Math.max(minRad, di.mrc || 0); + var dx = xa.c2p(di.x) - xpx; + var dy = ya.c2p(di.y) - ypx; + return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - minRad / rad); + }; + var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); + + Fx.getClosest(cd, distfn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index !== false) { + + // the closest data point + var di = cd[pointData.index]; + var xc = xa.c2p(di.x, true); + var yc = ya.c2p(di.y, true); + var rad = di.mrc || 1; + + // now we're done using the whole `calcdata` array, replace the + // index with the original index (in case of inserted point from + // stacked area) + pointData.index = di.i; + + var orientation = cd[0].t.orientation; + // TODO: for scatter and bar, option to show (sub)totals and + // raw data? Currently stacked and/or normalized bars just show + // the normalized individual sizes, so that's what I'm doing here + // for now. + var sizeVal = orientation && (di.sNorm || di.s); + var xLabelVal = (orientation === 'h') ? sizeVal : di.x; + var yLabelVal = (orientation === 'v') ? sizeVal : di.y; + + Lib.extendFlat(pointData, { + color: getTraceColor(trace, di), + + x0: xc - rad, + x1: xc + rad, + xLabelVal: xLabelVal, + + y0: yc - rad, + y1: yc + rad, + yLabelVal: yLabelVal, + + spikeDistance: dxy(di) + }); + + fillHoverText(di, trace, pointData); + Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData); + + return [pointData]; + } + } + + // even if hoveron is 'fills', only use it if we have polygons too + if(hoveron.indexOf('fills') !== -1 && trace._polygons) { + var polygons = trace._polygons; + var polygonsIn = []; + var inside = false; + var xmin = Infinity; + var xmax = -Infinity; + var ymin = Infinity; + var ymax = -Infinity; + + var i, j, polygon, pts, xCross, x0, x1, y0, y1; + + for(i = 0; i < polygons.length; i++) { + polygon = polygons[i]; + // TODO: this is not going to work right for curved edges, it will + // act as though they're straight. That's probably going to need + // the elements themselves to capture the events. Worth it? + if(polygon.contains(pt)) { + inside = !inside; + // TODO: need better than just the overall bounding box + polygonsIn.push(polygon); + ymin = Math.min(ymin, polygon.ymin); + ymax = Math.max(ymax, polygon.ymax); + } + } + + if(inside) { + // constrain ymin/max to the visible plot, so the label goes + // at the middle of the piece you can see + ymin = Math.max(ymin, 0); + ymax = Math.min(ymax, ya._length); + + // find the overall left-most and right-most points of the + // polygon(s) we're inside at their combined vertical midpoint. + // This is where we will draw the hover label. + // Note that this might not be the vertical midpoint of the + // whole trace, if it's disjoint. + var yAvg = (ymin + ymax) / 2; + for(i = 0; i < polygonsIn.length; i++) { + pts = polygonsIn[i].pts; + for(j = 1; j < pts.length; j++) { + y0 = pts[j - 1][1]; + y1 = pts[j][1]; + if((y0 > yAvg) !== (y1 >= yAvg)) { + x0 = pts[j - 1][0]; + x1 = pts[j][0]; + if(y1 - y0) { + xCross = x0 + (x1 - x0) * (yAvg - y0) / (y1 - y0); + xmin = Math.min(xmin, xCross); + xmax = Math.max(xmax, xCross); + } + } + } + } + + // constrain xmin/max to the visible plot now too + xmin = Math.max(xmin, 0); + xmax = Math.min(xmax, xa._length); + + // get only fill or line color for the hover color + var color = Color.defaultLine; + if(Color.opacity(trace.fillcolor)) color = trace.fillcolor; + else if(Color.opacity((trace.line || {}).color)) { + color = trace.line.color; + } + + Lib.extendFlat(pointData, { + // never let a 2D override 1D type as closest point + // also: no spikeDistance, it's not allowed for fills + distance: pointData.maxHoverDistance, + x0: xmin, + x1: xmax, + y0: yAvg, + y1: yAvg, + color: color + }); + + delete pointData.index; + + if(trace.text && !Array.isArray(trace.text)) { + pointData.text = String(trace.text); + } + else pointData.text = trace.name; + + return [pointData]; + } + } +}; + +},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"../../registry":827,"./fill_hover_text":1051,"./get_trace_color":1053}],1055:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Scatter = {}; + +var subtypes = _dereq_('./subtypes'); +Scatter.hasLines = subtypes.hasLines; +Scatter.hasMarkers = subtypes.hasMarkers; +Scatter.hasText = subtypes.hasText; +Scatter.isBubble = subtypes.isBubble; + +Scatter.attributes = _dereq_('./attributes'); +Scatter.supplyDefaults = _dereq_('./defaults'); +Scatter.crossTraceDefaults = _dereq_('./cross_trace_defaults'); +Scatter.calc = _dereq_('./calc').calc; +Scatter.crossTraceCalc = _dereq_('./cross_trace_calc'); +Scatter.arraysToCalcdata = _dereq_('./arrays_to_calcdata'); +Scatter.plot = _dereq_('./plot'); +Scatter.colorbar = _dereq_('./marker_colorbar'); +Scatter.style = _dereq_('./style').style; +Scatter.styleOnSelect = _dereq_('./style').styleOnSelect; +Scatter.hoverPoints = _dereq_('./hover'); +Scatter.selectPoints = _dereq_('./select'); +Scatter.animatable = true; + +Scatter.moduleType = 'trace'; +Scatter.name = 'scatter'; +Scatter.basePlotModule = _dereq_('../../plots/cartesian'); +Scatter.categories = [ + 'cartesian', 'svg', 'symbols', 'errorBarsOK', 'showLegend', 'scatter-like', + 'zoomScale' +]; +Scatter.meta = { + +}; + +module.exports = Scatter; + +},{"../../plots/cartesian":756,"./arrays_to_calcdata":1042,"./attributes":1043,"./calc":1044,"./cross_trace_calc":1048,"./cross_trace_defaults":1049,"./defaults":1050,"./hover":1054,"./marker_colorbar":1061,"./plot":1063,"./select":1064,"./style":1066,"./subtypes":1067}],1056:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); + +module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) { + var markerColor = (traceIn.marker || {}).color; + + coerce('line.color', defaultColor); + + if(hasColorscale(traceIn, 'line')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c', noScale: true}); + } else { + var lineColorDflt = (isArrayOrTypedArray(markerColor) ? false : markerColor) || defaultColor; + coerce('line.color', lineColorDflt); + } + + coerce('line.width'); + if(!(opts || {}).noDash) coerce('line.dash'); +}; + +},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696}],1057:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var numConstants = _dereq_('../../constants/numerical'); +var BADNUM = numConstants.BADNUM; +var LOG_CLIP = numConstants.LOG_CLIP; +var LOG_CLIP_PLUS = LOG_CLIP + 0.5; +var LOG_CLIP_MINUS = LOG_CLIP - 0.5; +var Lib = _dereq_('../../lib'); +var segmentsIntersect = Lib.segmentsIntersect; +var constrain = Lib.constrain; +var constants = _dereq_('./constants'); + + +module.exports = function linePoints(d, opts) { + var xa = opts.xaxis; + var ya = opts.yaxis; + var xLog = xa.type === 'log'; + var yLog = ya.type === 'log'; + var xLen = xa._length; + var yLen = ya._length; + var connectGaps = opts.connectGaps; + var baseTolerance = opts.baseTolerance; + var shape = opts.shape; + var linear = shape === 'linear'; + var segments = []; + var minTolerance = constants.minTolerance; + var pts = new Array(d.length); + var pti = 0; + + var i; + + // pt variables are pixel coordinates [x,y] of one point + // these four are the outputs of clustering on a line + var clusterStartPt, clusterEndPt, clusterHighPt, clusterLowPt; + + // "this" is the next point we're considering adding to the cluster + var thisPt; + + // did we encounter the high point first, then a low point, or vice versa? + var clusterHighFirst; + + // the first two points in the cluster determine its unit vector + // so the second is always in the "High" direction + var clusterUnitVector; + + // the pixel delta from clusterStartPt + var thisVector; + + // val variables are (signed) pixel distances along the cluster vector + var clusterRefDist, clusterHighVal, clusterLowVal, thisVal; + + // deviation variables are (signed) pixel distances normal to the cluster vector + var clusterMinDeviation, clusterMaxDeviation, thisDeviation; + + // turn one calcdata point into pixel coordinates + function getPt(index) { + var di = d[index]; + if(!di) return false; + var x = xa.c2p(di.x); + var y = ya.c2p(di.y); + + // if non-positive log values, set them VERY far off-screen + // so the line looks essentially straight from the previous point. + if(x === BADNUM) { + if(xLog) x = xa.c2p(di.x, true); + if(x === BADNUM) return false; + // If BOTH were bad log values, make the line follow a constant + // exponent rather than a constant slope + if(yLog && y === BADNUM) { + x *= Math.abs(xa._m * yLen * (xa._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS) / + (ya._m * xLen * (ya._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS))); + } + x *= 1000; + } + if(y === BADNUM) { + if(yLog) y = ya.c2p(di.y, true); + if(y === BADNUM) return false; + y *= 1000; + } + return [x, y]; + } + + function crossesViewport(xFrac0, yFrac0, xFrac1, yFrac1) { + var dx = xFrac1 - xFrac0; + var dy = yFrac1 - yFrac0; + var dx0 = 0.5 - xFrac0; + var dy0 = 0.5 - yFrac0; + var norm2 = dx * dx + dy * dy; + var dot = dx * dx0 + dy * dy0; + if(dot > 0 && dot < norm2) { + var cross = dx0 * dy - dy0 * dx; + if(cross * cross < norm2) return true; + } + } + + var latestXFrac, latestYFrac; + // if we're off-screen, increase tolerance over baseTolerance + function getTolerance(pt, nextPt) { + var xFrac = pt[0] / xLen; + var yFrac = pt[1] / yLen; + var offScreenFraction = Math.max(0, -xFrac, xFrac - 1, -yFrac, yFrac - 1); + if(offScreenFraction && (latestXFrac !== undefined) && + crossesViewport(xFrac, yFrac, latestXFrac, latestYFrac) + ) { + offScreenFraction = 0; + } + if(offScreenFraction && nextPt && + crossesViewport(xFrac, yFrac, nextPt[0] / xLen, nextPt[1] / yLen) + ) { + offScreenFraction = 0; + } + + return (1 + constants.toleranceGrowth * offScreenFraction) * baseTolerance; + } + + function ptDist(pt1, pt2) { + var dx = pt1[0] - pt2[0]; + var dy = pt1[1] - pt2[1]; + return Math.sqrt(dx * dx + dy * dy); + } + + // last bit of filtering: clip paths that are VERY far off-screen + // so we don't get near the browser's hard limit (+/- 2^29 px in Chrome and FF) + + var maxScreensAway = constants.maxScreensAway; + + // find the intersections between the segment from pt1 to pt2 + // and the large rectangle maxScreensAway around the viewport + // if one of pt1 and pt2 is inside and the other outside, there + // will be only one intersection. + // if both are outside there will be 0 or 2 intersections + // (or 1 if it's right at a corner - we'll treat that like 0) + // returns an array of intersection pts + var xEdge0 = -xLen * maxScreensAway; + var xEdge1 = xLen * (1 + maxScreensAway); + var yEdge0 = -yLen * maxScreensAway; + var yEdge1 = yLen * (1 + maxScreensAway); + var edges = [ + [xEdge0, yEdge0, xEdge1, yEdge0], + [xEdge1, yEdge0, xEdge1, yEdge1], + [xEdge1, yEdge1, xEdge0, yEdge1], + [xEdge0, yEdge1, xEdge0, yEdge0] + ]; + var xEdge, yEdge, lastXEdge, lastYEdge, lastFarPt, edgePt; + + // for linear line shape, edge intersections should be linearly interpolated + // spline uses this too, which isn't precisely correct but is actually pretty + // good, because Catmull-Rom weights far-away points less in creating the curvature + function getLinearEdgeIntersections(pt1, pt2) { + var out = []; + var ptCount = 0; + for(var i = 0; i < 4; i++) { + var edge = edges[i]; + var ptInt = segmentsIntersect(pt1[0], pt1[1], pt2[0], pt2[1], + edge[0], edge[1], edge[2], edge[3]); + if(ptInt && (!ptCount || + Math.abs(ptInt.x - out[0][0]) > 1 || + Math.abs(ptInt.y - out[0][1]) > 1 + )) { + ptInt = [ptInt.x, ptInt.y]; + // if we have 2 intersections, make sure the closest one to pt1 comes first + if(ptCount && ptDist(ptInt, pt1) < ptDist(out[0], pt1)) out.unshift(ptInt); + else out.push(ptInt); + ptCount++; + } + } + return out; + } + + function onlyConstrainedPoint(pt) { + if(pt[0] < xEdge0 || pt[0] > xEdge1 || pt[1] < yEdge0 || pt[1] > yEdge1) { + return [constrain(pt[0], xEdge0, xEdge1), constrain(pt[1], yEdge0, yEdge1)]; + } + } + + function sameEdge(pt1, pt2) { + if(pt1[0] === pt2[0] && (pt1[0] === xEdge0 || pt1[0] === xEdge1)) return true; + if(pt1[1] === pt2[1] && (pt1[1] === yEdge0 || pt1[1] === yEdge1)) return true; + } + + // for line shapes hv and vh, movement in the two dimensions is decoupled, + // so all we need to do is constrain each dimension independently + function getHVEdgeIntersections(pt1, pt2) { + var out = []; + var ptInt1 = onlyConstrainedPoint(pt1); + var ptInt2 = onlyConstrainedPoint(pt2); + if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out; + + if(ptInt1) out.push(ptInt1); + if(ptInt2) out.push(ptInt2); + return out; + } + + // hvh and vhv we sometimes have to move one of the intersection points + // out BEYOND the clipping rect, by a maximum of a factor of 2, so that + // the midpoint line is drawn in the right place + function getABAEdgeIntersections(dim, limit0, limit1) { + return function(pt1, pt2) { + var ptInt1 = onlyConstrainedPoint(pt1); + var ptInt2 = onlyConstrainedPoint(pt2); + + var out = []; + if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out; + + if(ptInt1) out.push(ptInt1); + if(ptInt2) out.push(ptInt2); + + var midShift = 2 * Lib.constrain((pt1[dim] + pt2[dim]) / 2, limit0, limit1) - + ((ptInt1 || pt1)[dim] + (ptInt2 || pt2)[dim]); + if(midShift) { + var ptToAlter; + if(ptInt1 && ptInt2) { + ptToAlter = (midShift > 0 === ptInt1[dim] > ptInt2[dim]) ? ptInt1 : ptInt2; + } + else ptToAlter = ptInt1 || ptInt2; + + ptToAlter[dim] += midShift; + } + + return out; + }; + } + + var getEdgeIntersections; + if(shape === 'linear' || shape === 'spline') { + getEdgeIntersections = getLinearEdgeIntersections; + } + else if(shape === 'hv' || shape === 'vh') { + getEdgeIntersections = getHVEdgeIntersections; + } + else if(shape === 'hvh') getEdgeIntersections = getABAEdgeIntersections(0, xEdge0, xEdge1); + else if(shape === 'vhv') getEdgeIntersections = getABAEdgeIntersections(1, yEdge0, yEdge1); + + // a segment pt1->pt2 entirely outside the nearby region: + // find the corner it gets closest to touching + function getClosestCorner(pt1, pt2) { + var dx = pt2[0] - pt1[0]; + var m = (pt2[1] - pt1[1]) / dx; + var b = (pt1[1] * pt2[0] - pt2[1] * pt1[0]) / dx; + + if(b > 0) return [m > 0 ? xEdge0 : xEdge1, yEdge1]; + else return [m > 0 ? xEdge1 : xEdge0, yEdge0]; + } + + function updateEdge(pt) { + var x = pt[0]; + var y = pt[1]; + var xSame = x === pts[pti - 1][0]; + var ySame = y === pts[pti - 1][1]; + // duplicate point? + if(xSame && ySame) return; + if(pti > 1) { + // backtracking along an edge? + var xSame2 = x === pts[pti - 2][0]; + var ySame2 = y === pts[pti - 2][1]; + if(xSame && (x === xEdge0 || x === xEdge1) && xSame2) { + if(ySame2) pti--; // backtracking exactly - drop prev pt and don't add + else pts[pti - 1] = pt; // not exact: replace the prev pt + } + else if(ySame && (y === yEdge0 || y === yEdge1) && ySame2) { + if(xSame2) pti--; + else pts[pti - 1] = pt; + } + else pts[pti++] = pt; + } + else pts[pti++] = pt; + } + + function updateEdgesForReentry(pt) { + // if we're outside the nearby region and going back in, + // we may need to loop around a corner point + if(pts[pti - 1][0] !== pt[0] && pts[pti - 1][1] !== pt[1]) { + updateEdge([lastXEdge, lastYEdge]); + } + updateEdge(pt); + lastFarPt = null; + lastXEdge = lastYEdge = 0; + } + + function addPt(pt) { + latestXFrac = pt[0] / xLen; + latestYFrac = pt[1] / yLen; + // Are we more than maxScreensAway off-screen any direction? + // if so, clip to this box, but in such a way that on-screen + // drawing is unchanged + xEdge = (pt[0] < xEdge0) ? xEdge0 : (pt[0] > xEdge1) ? xEdge1 : 0; + yEdge = (pt[1] < yEdge0) ? yEdge0 : (pt[1] > yEdge1) ? yEdge1 : 0; + if(xEdge || yEdge) { + // to get fills right - if first point is far, push it toward the + // screen in whichever direction(s) are far + if(!pti) { + pts[pti++] = [xEdge || pt[0], yEdge || pt[1]]; + } + else if(lastFarPt) { + // both this point and the last are outside the nearby region + // check if we're crossing the nearby region + var intersections = getEdgeIntersections(lastFarPt, pt); + if(intersections.length > 1) { + updateEdgesForReentry(intersections[0]); + pts[pti++] = intersections[1]; + } + } + // we're leaving the nearby region - add the point where we left it + else { + edgePt = getEdgeIntersections(pts[pti - 1], pt)[0]; + pts[pti++] = edgePt; + } + + var lastPt = pts[pti - 1]; + if(xEdge && yEdge && (lastPt[0] !== xEdge || lastPt[1] !== yEdge)) { + // we've gone out beyond a new corner: add the corner too + // so that the next point will take the right winding + if(lastFarPt) { + if(lastXEdge !== xEdge && lastYEdge !== yEdge) { + if(lastXEdge && lastYEdge) { + // we've gone around to an opposite corner - we + // need to add the correct extra corner + // in order to get the right winding + updateEdge(getClosestCorner(lastFarPt, pt)); + } + else { + // we're coming from a far edge - the extra corner + // we need is determined uniquely by the sectors + updateEdge([lastXEdge || xEdge, lastYEdge || yEdge]); + } + } + else if(lastXEdge && lastYEdge) { + updateEdge([lastXEdge, lastYEdge]); + } + } + updateEdge([xEdge, yEdge]); + } + else if((lastXEdge - xEdge) && (lastYEdge - yEdge)) { + // we're coming from an edge or far corner to an edge - again the + // extra corner we need is uniquely determined by the sectors + updateEdge([xEdge || lastXEdge, yEdge || lastYEdge]); + } + lastFarPt = pt; + lastXEdge = xEdge; + lastYEdge = yEdge; + } + else { + if(lastFarPt) { + // this point is in range but the previous wasn't: add its entry pt first + updateEdgesForReentry(getEdgeIntersections(lastFarPt, pt)[0]); + } + + pts[pti++] = pt; + } + } + + // loop over ALL points in this trace + for(i = 0; i < d.length; i++) { + clusterStartPt = getPt(i); + if(!clusterStartPt) continue; + + pti = 0; + lastFarPt = null; + addPt(clusterStartPt); + + // loop over one segment of the trace + for(i++; i < d.length; i++) { + clusterHighPt = getPt(i); + if(!clusterHighPt) { + if(connectGaps) continue; + else break; + } + + // can't decimate if nonlinear line shape + // TODO: we *could* decimate [hv]{2,3} shapes if we restricted clusters to horz or vert again + // but spline would be verrry awkward to decimate + if(!linear || !opts.simplify) { + addPt(clusterHighPt); + continue; + } + + var nextPt = getPt(i + 1); + + clusterRefDist = ptDist(clusterHighPt, clusterStartPt); + + if(clusterRefDist < getTolerance(clusterHighPt, nextPt) * minTolerance) continue; + + clusterUnitVector = [ + (clusterHighPt[0] - clusterStartPt[0]) / clusterRefDist, + (clusterHighPt[1] - clusterStartPt[1]) / clusterRefDist + ]; + + clusterLowPt = clusterStartPt; + clusterHighVal = clusterRefDist; + clusterLowVal = clusterMinDeviation = clusterMaxDeviation = 0; + clusterHighFirst = false; + clusterEndPt = clusterHighPt; + + // loop over one cluster of points that collapse onto one line + for(i++; i < d.length; i++) { + thisPt = nextPt; + nextPt = getPt(i + 1); + if(!thisPt) { + if(connectGaps) continue; + else break; + } + thisVector = [ + thisPt[0] - clusterStartPt[0], + thisPt[1] - clusterStartPt[1] + ]; + // cross product (or dot with normal to the cluster vector) + thisDeviation = thisVector[0] * clusterUnitVector[1] - thisVector[1] * clusterUnitVector[0]; + clusterMinDeviation = Math.min(clusterMinDeviation, thisDeviation); + clusterMaxDeviation = Math.max(clusterMaxDeviation, thisDeviation); + + if(clusterMaxDeviation - clusterMinDeviation > getTolerance(thisPt, nextPt)) break; + + clusterEndPt = thisPt; + thisVal = thisVector[0] * clusterUnitVector[0] + thisVector[1] * clusterUnitVector[1]; + + if(thisVal > clusterHighVal) { + clusterHighVal = thisVal; + clusterHighPt = thisPt; + clusterHighFirst = false; + } else if(thisVal < clusterLowVal) { + clusterLowVal = thisVal; + clusterLowPt = thisPt; + clusterHighFirst = true; + } + } + + // insert this cluster into pts + // we've already inserted the start pt, now check if we have high and low pts + if(clusterHighFirst) { + addPt(clusterHighPt); + if(clusterEndPt !== clusterLowPt) addPt(clusterLowPt); + } else { + if(clusterLowPt !== clusterStartPt) addPt(clusterLowPt); + if(clusterEndPt !== clusterHighPt) addPt(clusterHighPt); + } + // and finally insert the end pt + addPt(clusterEndPt); + + // have we reached the end of this segment? + if(i >= d.length || !thisPt) break; + + // otherwise we have an out-of-cluster point to insert as next clusterStartPt + addPt(thisPt); + clusterStartPt = thisPt; + } + + // to get fills right - repeat what we did at the start + if(lastFarPt) updateEdge([lastXEdge || lastFarPt[0], lastYEdge || lastFarPt[1]]); + + segments.push(pts.slice(0, pti)); + } + + return segments; +}; + +},{"../../constants/numerical":673,"../../lib":696,"./constants":1047}],1058:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// common to 'scatter' and 'scatterternary' +module.exports = function handleLineShapeDefaults(traceIn, traceOut, coerce) { + var shape = coerce('line.shape'); + if(shape === 'spline') coerce('line.smoothing'); +}; + +},{}],1059:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var LINKEDFILLS = {tonextx: 1, tonexty: 1, tonext: 1}; + +module.exports = function linkTraces(gd, plotinfo, cdscatter) { + var trace, i, group, prevtrace, groupIndex; + + // first sort traces to keep stacks & filled-together groups together + var groupIndices = {}; + var needsSort = false; + var prevGroupIndex = -1; + var nextGroupIndex = 0; + var prevUnstackedGroupIndex = -1; + for(i = 0; i < cdscatter.length; i++) { + trace = cdscatter[i][0].trace; + group = trace.stackgroup || ''; + if(group) { + if(group in groupIndices) { + groupIndex = groupIndices[group]; + } + else { + groupIndex = groupIndices[group] = nextGroupIndex; + nextGroupIndex++; + } + } + else if(trace.fill in LINKEDFILLS && prevUnstackedGroupIndex >= 0) { + groupIndex = prevUnstackedGroupIndex; + } + else { + groupIndex = prevUnstackedGroupIndex = nextGroupIndex; + nextGroupIndex++; + } + + if(groupIndex < prevGroupIndex) needsSort = true; + trace._groupIndex = prevGroupIndex = groupIndex; + } + + var cdscatterSorted = cdscatter.slice(); + if(needsSort) { + cdscatterSorted.sort(function(a, b) { + var traceA = a[0].trace; + var traceB = b[0].trace; + return (traceA._groupIndex - traceB._groupIndex) || + (traceA.index - traceB.index); + }); + } + + // now link traces to each other + var prevtraces = {}; + for(i = 0; i < cdscatterSorted.length; i++) { + trace = cdscatterSorted[i][0].trace; + group = trace.stackgroup || ''; + + // Note: The check which ensures all cdscatter here are for the same axis and + // are either cartesian or scatterternary has been removed. This code assumes + // the passed scattertraces have been filtered to the proper plot types and + // the proper subplots. + if(trace.visible === true) { + trace._nexttrace = null; + + if(trace.fill in LINKEDFILLS) { + prevtrace = prevtraces[group]; + trace._prevtrace = prevtrace || null; + + if(prevtrace) { + prevtrace._nexttrace = trace; + } + } + + trace._ownfill = (trace.fill && ( + trace.fill.substr(0, 6) === 'tozero' || + trace.fill === 'toself' || + (trace.fill.substr(0, 2) === 'to' && !trace._prevtrace) + )); + + prevtraces[group] = trace; + } else { + trace._prevtrace = trace._nexttrace = trace._ownfill = null; + } + } + + return cdscatterSorted; +}; + +},{}],1060:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + + +// used in the drawing step for 'scatter' and 'scattegeo' and +// in the convert step for 'scatter3d' +module.exports = function makeBubbleSizeFn(trace) { + var marker = trace.marker, + sizeRef = marker.sizeref || 1, + sizeMin = marker.sizemin || 0; + + // for bubble charts, allow scaling the provided value linearly + // and by area or diameter. + // Note this only applies to the array-value sizes + + var baseFn = (marker.sizemode === 'area') ? + function(v) { return Math.sqrt(v / sizeRef); } : + function(v) { return v / sizeRef; }; + + // TODO add support for position/negative bubbles? + // TODO add 'sizeoffset' attribute? + return function(v) { + var baseSize = baseFn(v / 2); + + // don't show non-numeric and negative sizes + return (isNumeric(baseSize) && (baseSize > 0)) ? + Math.max(baseSize, sizeMin) : + 0; + }; +}; + +},{"fast-isnumeric":214}],1061:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + container: 'marker', + min: 'cmin', + max: 'cmax' +}; + +},{}],1062:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = _dereq_('../../components/color'); +var hasColorscale = _dereq_('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); + +var subTypes = _dereq_('./subtypes'); + +/* + * opts: object of flags to control features not all marker users support + * noLine: caller does not support marker lines + * gradient: caller supports gradients + * noSelect: caller does not support selected/unselected attribute containers + */ +module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) { + var isBubble = subTypes.isBubble(traceIn), + lineColor = (traceIn.line || {}).color, + defaultMLC; + + opts = opts || {}; + + // marker.color inherit from line.color (even if line.color is an array) + if(lineColor) defaultColor = lineColor; + + coerce('marker.symbol'); + coerce('marker.opacity', isBubble ? 0.7 : 1); + coerce('marker.size'); + + coerce('marker.color', defaultColor); + if(hasColorscale(traceIn, 'marker')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'}); + } + + if(!opts.noSelect) { + coerce('selected.marker.color'); + coerce('unselected.marker.color'); + coerce('selected.marker.size'); + coerce('unselected.marker.size'); + } + + if(!opts.noLine) { + // if there's a line with a different color than the marker, use + // that line color as the default marker line color + // (except when it's an array) + // mostly this is for transparent markers to behave nicely + if(lineColor && !Array.isArray(lineColor) && (traceOut.marker.color !== lineColor)) { + defaultMLC = lineColor; + } + else if(isBubble) defaultMLC = Color.background; + else defaultMLC = Color.defaultLine; + + coerce('marker.line.color', defaultMLC); + if(hasColorscale(traceIn, 'marker.line')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'}); + } + + coerce('marker.line.width', isBubble ? 1 : 0); + } + + if(isBubble) { + coerce('marker.sizeref'); + coerce('marker.sizemin'); + coerce('marker.sizemode'); + } + + if(opts.gradient) { + var gradientType = coerce('marker.gradient.type'); + if(gradientType !== 'none') { + coerce('marker.gradient.color'); + } + } +}; + +},{"../../components/color":570,"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"./subtypes":1067}],1063:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var ensureSingle = Lib.ensureSingle; +var identity = Lib.identity; +var Drawing = _dereq_('../../components/drawing'); + +var subTypes = _dereq_('./subtypes'); +var linePoints = _dereq_('./line_points'); +var linkTraces = _dereq_('./link_traces'); +var polygonTester = _dereq_('../../lib/polygon').tester; + +module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transitionOpts, makeOnCompleteCallback) { + var join, onComplete; + + // If transition config is provided, then it is only a partial replot and traces not + // updated are removed. + var isFullReplot = !transitionOpts; + var hasTransition = !!transitionOpts && transitionOpts.duration > 0; + + // Link traces so the z-order of fill layers is correct + var cdscatterSorted = linkTraces(gd, plotinfo, cdscatter); + + join = scatterLayer.selectAll('g.trace') + .data(cdscatterSorted, function(d) { return d[0].trace.uid; }); + + // Append new traces: + join.enter().append('g') + .attr('class', function(d) { + return 'trace scatter trace' + d[0].trace.uid; + }) + .style('stroke-miterlimit', 2); + join.order(); + + createFills(gd, join, plotinfo); + + if(hasTransition) { + if(makeOnCompleteCallback) { + // If it was passed a callback to register completion, make a callback. If + // this is created, then it must be executed on completion, otherwise the + // pos-transition redraw will not execute: + onComplete = makeOnCompleteCallback(); + } + + var transition = d3.transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing) + .each('end', function() { + onComplete && onComplete(); + }) + .each('interrupt', function() { + onComplete && onComplete(); + }); + + transition.each(function() { + // Must run the selection again since otherwise enters/updates get grouped together + // and these get executed out of order. Except we need them in order! + scatterLayer.selectAll('g.trace').each(function(d, i) { + plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts); + }); + }); + } else { + join.each(function(d, i) { + plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts); + }); + } + + if(isFullReplot) { + join.exit().remove(); + } + + // remove paths that didn't get used + scatterLayer.selectAll('path:not([d])').remove(); +}; + +function createFills(gd, traceJoin, plotinfo) { + traceJoin.each(function(d) { + var fills = ensureSingle(d3.select(this), 'g', 'fills'); + Drawing.setClipUrl(fills, plotinfo.layerClipId); + + var trace = d[0].trace; + + var fillData = []; + if(trace._ownfill) fillData.push('_ownFill'); + if(trace._nexttrace) fillData.push('_nextFill'); + + var fillJoin = fills.selectAll('g').data(fillData, identity); + + fillJoin.enter().append('g'); + + fillJoin.exit() + .each(function(d) { trace[d] = null; }) + .remove(); + + fillJoin.order().each(function(d) { + // make a path element inside the fill group, just so + // we can give it its own data later on and the group can + // keep its simple '_*Fill' data + trace[d] = ensureSingle(d3.select(this), 'path', 'js-fill'); + }); + }); +} + +function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transitionOpts) { + var i; + + // Since this has been reorganized and we're executing this on individual traces, + // we need to pass it the full list of cdscatter as well as this trace's index (idx) + // since it does an internal n^2 loop over comparisons with other traces: + selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll); + + var hasTransition = !!transitionOpts && transitionOpts.duration > 0; + + function transition(selection) { + return hasTransition ? selection.transition() : selection; + } + + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + var trace = cdscatter[0].trace; + var line = trace.line; + var tr = d3.select(element); + + var errorBarGroup = ensureSingle(tr, 'g', 'errorbars'); + var lines = ensureSingle(tr, 'g', 'lines'); + var points = ensureSingle(tr, 'g', 'points'); + var text = ensureSingle(tr, 'g', 'text'); + + // error bars are at the bottom + Registry.getComponentMethod('errorbars', 'plot')(errorBarGroup, plotinfo, transitionOpts); + + if(trace.visible !== true) return; + + transition(tr).style('opacity', trace.opacity); + + // BUILD LINES AND FILLS + var ownFillEl3, tonext; + var ownFillDir = trace.fill.charAt(trace.fill.length - 1); + if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = ''; + + // store node for tweaking by selectPoints + if(!plotinfo.isRangePlot) cdscatter[0].node3 = tr; + + var prevRevpath = ''; + var prevPolygons = []; + var prevtrace = trace._prevtrace; + + if(prevtrace) { + prevRevpath = prevtrace._prevRevpath || ''; + tonext = prevtrace._nextFill; + prevPolygons = prevtrace._polygons; + } + + var thispath, + thisrevpath, + // fullpath is all paths for this curve, joined together straight + // across gaps, for filling + fullpath = '', + // revpath is fullpath reversed, for fill-to-next + revpath = '', + // functions for converting a point array to a path + pathfn, revpathbase, revpathfn, + // variables used before and after the data join + pt0, lastSegment, pt1, thisPolygons; + + // initialize line join data / method + var segments = [], + makeUpdate = Lib.noop; + + ownFillEl3 = trace._ownFill; + + if(subTypes.hasLines(trace) || trace.fill !== 'none') { + + if(tonext) { + // This tells .style which trace to use for fill information: + tonext.datum(cdscatter); + } + + if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) { + pathfn = Drawing.steps(line.shape); + revpathbase = Drawing.steps( + line.shape.split('').reverse().join('') + ); + } + else if(line.shape === 'spline') { + pathfn = revpathbase = function(pts) { + var pLast = pts[pts.length - 1]; + if(pts.length > 1 && pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) { + // identical start and end points: treat it as a + // closed curve so we don't get a kink + return Drawing.smoothclosed(pts.slice(1), line.smoothing); + } + else { + return Drawing.smoothopen(pts, line.smoothing); + } + }; + } + else { + pathfn = revpathbase = function(pts) { + return 'M' + pts.join('L'); + }; + } + + revpathfn = function(pts) { + // note: this is destructive (reverses pts in place) so can't use pts after this + return revpathbase(pts.reverse()); + }; + + segments = linePoints(cdscatter, { + xaxis: xa, + yaxis: ya, + connectGaps: trace.connectgaps, + baseTolerance: Math.max(line.width || 1, 3) / 4, + shape: line.shape, + simplify: line.simplify + }); + + // since we already have the pixel segments here, use them to make + // polygons for hover on fill + // TODO: can we skip this if hoveron!=fills? That would mean we + // need to redraw when you change hoveron... + thisPolygons = trace._polygons = new Array(segments.length); + for(i = 0; i < segments.length; i++) { + trace._polygons[i] = polygonTester(segments[i]); + } + + if(segments.length) { + pt0 = segments[0][0]; + lastSegment = segments[segments.length - 1]; + pt1 = lastSegment[lastSegment.length - 1]; + } + + makeUpdate = function(isEnter) { + return function(pts) { + thispath = pathfn(pts); + thisrevpath = revpathfn(pts); + if(!fullpath) { + fullpath = thispath; + revpath = thisrevpath; + } + else if(ownFillDir) { + fullpath += 'L' + thispath.substr(1); + revpath = thisrevpath + ('L' + revpath.substr(1)); + } + else { + fullpath += 'Z' + thispath; + revpath = thisrevpath + 'Z' + revpath; + } + + if(subTypes.hasLines(trace) && pts.length > 1) { + var el = d3.select(this); + + // This makes the coloring work correctly: + el.datum(cdscatter); + + if(isEnter) { + transition(el.style('opacity', 0) + .attr('d', thispath) + .call(Drawing.lineGroupStyle)) + .style('opacity', 1); + } else { + var sel = transition(el); + sel.attr('d', thispath); + Drawing.singleLineStyle(cdscatter, sel); + } + } + }; + }; + } + + var lineJoin = lines.selectAll('.js-line').data(segments); + + transition(lineJoin.exit()) + .style('opacity', 0) + .remove(); + + lineJoin.each(makeUpdate(false)); + + lineJoin.enter().append('path') + .classed('js-line', true) + .style('vector-effect', 'non-scaling-stroke') + .call(Drawing.lineGroupStyle) + .each(makeUpdate(true)); + + Drawing.setClipUrl(lineJoin, plotinfo.layerClipId); + + function clearFill(selection) { + transition(selection).attr('d', 'M0,0Z'); + } + + if(segments.length) { + if(ownFillEl3) { + ownFillEl3.datum(cdscatter); + if(pt0 && pt1) { + if(ownFillDir) { + if(ownFillDir === 'y') { + pt0[1] = pt1[1] = ya.c2p(0, true); + } + else if(ownFillDir === 'x') { + pt0[0] = pt1[0] = xa.c2p(0, true); + } + + // fill to zero: full trace path, plus extension of + // the endpoints to the appropriate axis + // For the sake of animations, wrap the points around so that + // the points on the axes are the first two points. Otherwise + // animations get a little crazy if the number of points changes. + transition(ownFillEl3).attr('d', 'M' + pt1 + 'L' + pt0 + 'L' + fullpath.substr(1)) + .call(Drawing.singleFillStyle); + } else { + // fill to self: just join the path to itself + transition(ownFillEl3).attr('d', fullpath + 'Z') + .call(Drawing.singleFillStyle); + } + } + } + else if(tonext) { + if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevRevpath) { + // fill to next: full trace path, plus the previous path reversed + if(trace.fill === 'tonext') { + // tonext: for use by concentric shapes, like manually constructed + // contours, we just add the two paths closed on themselves. + // This makes strange results if one path is *not* entirely + // inside the other, but then that is a strange usage. + transition(tonext).attr('d', fullpath + 'Z' + prevRevpath + 'Z') + .call(Drawing.singleFillStyle); + } + else { + // tonextx/y: for now just connect endpoints with lines. This is + // the correct behavior if the endpoints are at the same value of + // y/x, but if they *aren't*, we should ideally do more complicated + // things depending on whether the new endpoint projects onto the + // existing curve or off the end of it + transition(tonext).attr('d', fullpath + 'L' + prevRevpath.substr(1) + 'Z') + .call(Drawing.singleFillStyle); + } + trace._polygons = trace._polygons.concat(prevPolygons); + } + else { + clearFill(tonext); + trace._polygons = null; + } + } + trace._prevRevpath = revpath; + trace._prevPolygons = thisPolygons; + } + else { + if(ownFillEl3) clearFill(ownFillEl3); + else if(tonext) clearFill(tonext); + trace._polygons = trace._prevRevpath = trace._prevPolygons = null; + } + + + function visFilter(d) { + return d.filter(function(v) { return !v.gap && v.vis; }); + } + + function visFilterWithGaps(d) { + return d.filter(function(v) { return v.vis; }); + } + + function gapFilter(d) { + return d.filter(function(v) { return !v.gap; }); + } + + function keyFunc(d) { + return d.id; + } + + // Returns a function if the trace is keyed, otherwise returns undefined + function getKeyFunc(trace) { + if(trace.ids) { + return keyFunc; + } + } + + function hideFilter() { + return false; + } + + function makePoints(points, text, cdscatter) { + var join, selection, hasNode; + + var trace = cdscatter[0].trace; + var showMarkers = subTypes.hasMarkers(trace); + var showText = subTypes.hasText(trace); + + var keyFunc = getKeyFunc(trace); + var markerFilter = hideFilter; + var textFilter = hideFilter; + + if(showMarkers || showText) { + var showFilter = identity; + // if we're stacking, "infer zero" gap mode gets markers in the + // gap points - because we've inferred a zero there - but other + // modes (currently "interpolate", later "interrupt" hopefully) + // we don't draw generated markers + var stackGroup = trace.stackgroup; + var isInferZero = stackGroup && ( + gd._fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup].stackgaps === 'infer zero'); + if(trace.marker.maxdisplayed || trace._needsCull) { + showFilter = isInferZero ? visFilterWithGaps : visFilter; + } + else if(stackGroup && !isInferZero) { + showFilter = gapFilter; + } + + if(showMarkers) markerFilter = showFilter; + if(showText) textFilter = showFilter; + } + + // marker points + + selection = points.selectAll('path.point'); + + join = selection.data(markerFilter, keyFunc); + + var enter = join.enter().append('path') + .classed('point', true); + + if(hasTransition) { + enter + .call(Drawing.pointStyle, trace, gd) + .call(Drawing.translatePoints, xa, ya) + .style('opacity', 0) + .transition() + .style('opacity', 1); + } + + join.order(); + + var styleFns; + if(showMarkers) { + styleFns = Drawing.makePointStyleFns(trace); + } + + join.each(function(d) { + var el = d3.select(this); + var sel = transition(el); + hasNode = Drawing.translatePoint(d, sel, xa, ya); + + if(hasNode) { + Drawing.singlePointStyle(d, sel, trace, styleFns, gd); + + if(plotinfo.layerClipId) { + Drawing.hideOutsideRangePoint(d, sel, xa, ya, trace.xcalendar, trace.ycalendar); + } + + if(trace.customdata) { + el.classed('plotly-customdata', d.data !== null && d.data !== undefined); + } + } else { + sel.remove(); + } + }); + + if(hasTransition) { + join.exit().transition() + .style('opacity', 0) + .remove(); + } else { + join.exit().remove(); + } + + // text points + selection = text.selectAll('g'); + join = selection.data(textFilter, keyFunc); + + // each text needs to go in its own 'g' in case + // it gets converted to mathjax + join.enter().append('g').classed('textpoint', true).append('text'); + + join.order(); + + join.each(function(d) { + var g = d3.select(this); + var sel = transition(g.select('text')); + hasNode = Drawing.translatePoint(d, sel, xa, ya); + + if(hasNode) { + if(plotinfo.layerClipId) { + Drawing.hideOutsideRangePoint(d, g, xa, ya, trace.xcalendar, trace.ycalendar); + } + } else { + g.remove(); + } + }); + + join.selectAll('text') + .call(Drawing.textPointStyle, trace, gd) + .each(function(d) { + // This just *has* to be totally custom becuase of SVG text positioning :( + // It's obviously copied from translatePoint; we just can't use that + var x = xa.c2p(d.x); + var y = ya.c2p(d.y); + + d3.select(this).selectAll('tspan.line').each(function() { + transition(d3.select(this)).attr({x: x, y: y}); + }); + }); + + join.exit().remove(); + } + + points.datum(cdscatter); + text.datum(cdscatter); + makePoints(points, text, cdscatter); + + // lastly, clip points groups of `cliponaxis !== false` traces + // on `plotinfo._hasClipOnAxisFalse === true` subplots + var hasClipOnAxisFalse = trace.cliponaxis === false; + var clipUrl = hasClipOnAxisFalse ? null : plotinfo.layerClipId; + Drawing.setClipUrl(points, clipUrl); + Drawing.setClipUrl(text, clipUrl); +} + +function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) { + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis, + xr = d3.extent(Lib.simpleMap(xa.range, xa.r2c)), + yr = d3.extent(Lib.simpleMap(ya.range, ya.r2c)); + + var trace = cdscatter[0].trace; + if(!subTypes.hasMarkers(trace)) return; + // if marker.maxdisplayed is used, select a maximum of + // mnum markers to show, from the set that are in the viewport + var mnum = trace.marker.maxdisplayed; + + // TODO: remove some as we get away from the viewport? + if(mnum === 0) return; + + var cd = cdscatter.filter(function(v) { + return v.x >= xr[0] && v.x <= xr[1] && v.y >= yr[0] && v.y <= yr[1]; + }), + inc = Math.ceil(cd.length / mnum), + tnum = 0; + cdscatterAll.forEach(function(cdj, j) { + var tracei = cdj[0].trace; + if(subTypes.hasMarkers(tracei) && + tracei.marker.maxdisplayed > 0 && j < idx) { + tnum++; + } + }); + + // if multiple traces use maxdisplayed, stagger which markers we + // display this formula offsets successive traces by 1/3 of the + // increment, adding an extra small amount after each triplet so + // it's not quite periodic + var i0 = Math.round(tnum * inc / 3 + Math.floor(tnum / 3) * inc / 7.1); + + // for error bars: save in cd which markers to show + // so we don't have to repeat this + cdscatter.forEach(function(v) { delete v.vis; }); + cd.forEach(function(v, i) { + if(Math.round((i + i0) % inc) === 0) v.vis = true; + }); +} + +},{"../../components/drawing":595,"../../lib":696,"../../lib/polygon":708,"../../registry":827,"./line_points":1057,"./link_traces":1059,"./subtypes":1067,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1064:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var subtypes = _dereq_('./subtypes'); + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd, + xa = searchInfo.xaxis, + ya = searchInfo.yaxis, + selection = [], + trace = cd[0].trace, + i, + di, + x, + y; + + var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); + if(hasOnlyLines) return []; + + if(selectionTester === false) { // clear selection + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } + else { + for(i = 0; i < cd.length; i++) { + di = cd[i]; + x = xa.c2p(di.x); + y = ya.c2p(di.y); + + if((di.i !== null) && selectionTester.contains([x, y], false, i, searchInfo)) { + selection.push({ + pointNumber: di.i, + x: xa.c2d(di.x), + y: ya.c2d(di.y) + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + + return selection; +}; + +},{"./subtypes":1067}],1065:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var perStackAttrs = ['orientation', 'groupnorm', 'stackgaps']; + +module.exports = function handleStackDefaults(traceIn, traceOut, layout, coerce) { + var stackOpts = layout._scatterStackOpts; + + var stackGroup = coerce('stackgroup'); + if(stackGroup) { + // use independent stacking options per subplot + var subplot = traceOut.xaxis + traceOut.yaxis; + var subplotStackOpts = stackOpts[subplot]; + if(!subplotStackOpts) subplotStackOpts = stackOpts[subplot] = {}; + + var groupOpts = subplotStackOpts[stackGroup]; + var firstTrace = false; + if(groupOpts) { + groupOpts.traces.push(traceOut); + } + else { + groupOpts = subplotStackOpts[stackGroup] = { + // keep track of trace indices for use during stacking calculations + // this will be filled in during `calc` and used during `crossTraceCalc` + // so it's OK if we don't recreate it during a non-calc edit + traceIndices: [], + // Hold on to the whole set of prior traces + // First one is most important, so we can clear defaults + // there if we find explicit values only in later traces. + // We're only going to *use* the values stored in groupOpts, + // but for the editor and validate we want things self-consistent + // The full set of traces is used only to fix `fill` default if + // we find `orientation: 'h'` beyond the first trace + traces: [traceOut] + }; + firstTrace = true; + } + // TODO: how is this going to work with groupby transforms? + // in principle it should be OK I guess, as long as explicit group styles + // don't override explicit base-trace styles? + + var dflts = { + orientation: (traceOut.x && !traceOut.y) ? 'h' : 'v' + }; + + for(var i = 0; i < perStackAttrs.length; i++) { + var attr = perStackAttrs[i]; + var attrFound = attr + 'Found'; + if(!groupOpts[attrFound]) { + var traceHasAttr = traceIn[attr] !== undefined; + var isOrientation = attr === 'orientation'; + if(traceHasAttr || firstTrace) { + groupOpts[attr] = coerce(attr, dflts[attr]); + + if(isOrientation) { + groupOpts.fillDflt = groupOpts[attr] === 'h' ? + 'tonextx' : 'tonexty'; + } + + if(traceHasAttr) { + // Note: this will show a value here even if it's invalid + // in which case it will revert to default. + groupOpts[attrFound] = true; + + // Note: only one trace in the stack will get a _fullData + // entry for a given stack-wide attribute. If no traces + // (or the first trace) specify that attribute, the + // first trace will get it. If the first trace does NOT + // specify it but some later trace does, then it gets + // removed from the first trace and only included in the + // one that specified it. This is mostly important for + // editors (that want to see the full values to know + // what settings are available) and Plotly.react diffing. + // Editors may want to use fullLayout._scatterStackOpts + // directly and make these settings available from all + // traces in the stack... then set the new value into + // the first trace, and clear all later traces. + if(!firstTrace) { + delete groupOpts.traces[0][attr]; + + // orientation can affect default fill of previous traces + if(isOrientation) { + for(var j = 0; j < groupOpts.traces.length - 1; j++) { + var trace2 = groupOpts.traces[j]; + if(trace2._input.fill !== trace2.fill) { + trace2.fill = groupOpts.fillDflt; + } + } + } + } + } + } + } + } + return groupOpts; + } +}; + +},{}],1066:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../../components/drawing'); +var Registry = _dereq_('../../registry'); + +function style(gd, cd) { + var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.scatter'); + + s.style('opacity', function(d) { + return d[0].trace.opacity; + }); + + s.selectAll('g.points').each(function(d) { + var sel = d3.select(this); + var trace = d.trace || d[0].trace; + stylePoints(sel, trace, gd); + }); + + s.selectAll('g.text').each(function(d) { + var sel = d3.select(this); + var trace = d.trace || d[0].trace; + styleText(sel, trace, gd); + }); + + s.selectAll('g.trace path.js-line') + .call(Drawing.lineGroupStyle); + + s.selectAll('g.trace path.js-fill') + .call(Drawing.fillGroupStyle); + + Registry.getComponentMethod('errorbars', 'style')(s); +} + +function stylePoints(sel, trace, gd) { + Drawing.pointStyle(sel.selectAll('path.point'), trace, gd); +} + +function styleText(sel, trace, gd) { + Drawing.textPointStyle(sel.selectAll('text'), trace, gd); +} + +function styleOnSelect(gd, cd) { + var s = cd[0].node3; + var trace = cd[0].trace; + + if(trace.selectedpoints) { + Drawing.selectedPointStyle(s.selectAll('path.point'), trace); + Drawing.selectedTextStyle(s.selectAll('text'), trace); + } else { + stylePoints(s, trace, gd); + styleText(s, trace, gd); + } +} + +module.exports = { + style: style, + stylePoints: stylePoints, + styleText: styleText, + styleOnSelect: styleOnSelect +}; + +},{"../../components/drawing":595,"../../registry":827,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1067:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +module.exports = { + hasLines: function(trace) { + return trace.visible && trace.mode && + trace.mode.indexOf('lines') !== -1; + }, + + hasMarkers: function(trace) { + return trace.visible && ( + (trace.mode && trace.mode.indexOf('markers') !== -1) || + // until splom implements 'mode' + trace.type === 'splom' + ); + }, + + hasText: function(trace) { + return trace.visible && trace.mode && + trace.mode.indexOf('text') !== -1; + }, + + isBubble: function(trace) { + return Lib.isPlainObject(trace.marker) && + Lib.isArrayOrTypedArray(trace.marker.size); + } +}; + +},{"../../lib":696}],1068:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +/* + * opts: object of flags to control features not all text users support + * noSelect: caller does not support selected/unselected attribute containers + */ +module.exports = function(traceIn, traceOut, layout, coerce, opts) { + opts = opts || {}; + + coerce('textposition'); + Lib.coerceFont(coerce, 'textfont', layout.font); + + if(!opts.noSelect) { + coerce('selected.textfont.color'); + coerce('unselected.textfont.color'); + } +}; + +},{"../../lib":696}],1069:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); + + +module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) { + var len, + x = coerce('x'), + y = coerce('y'); + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); + + if(x) { + if(y) { + len = Math.min(x.length, y.length); + } + else { + len = x.length; + coerce('y0'); + coerce('dy'); + } + } + else { + if(!y) return 0; + + len = traceOut.y.length; + coerce('x0'); + coerce('dx'); + } + + traceOut._length = len; + + return len; +}; + +},{"../../registry":827}],1070:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var baseAttrs = _dereq_('../../plots/attributes'); +var DASHES = _dereq_('../../constants/gl3d_dashes'); + +var MARKER_SYMBOLS = _dereq_('../../constants/gl3d_markers'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var scatterLineAttrs = scatterAttrs.line; +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +var lineAttrs = extendFlat({ + width: scatterLineAttrs.width, + dash: { + valType: 'enumerated', + values: Object.keys(DASHES), + dflt: 'solid', + + + } +}, colorAttributes('line')); +// not yet implemented +delete lineAttrs.showscale; +delete lineAttrs.colorbar; + +function makeProjectionAttr(axLetter) { + return { + show: { + valType: 'boolean', + + dflt: false, + + }, + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + + }, + scale: { + valType: 'number', + + min: 0, + max: 10, + dflt: 2 / 3, + + } + }; +} + +var attrs = module.exports = overrideAll({ + x: scatterAttrs.x, + y: scatterAttrs.y, + z: { + valType: 'data_array', + + }, + + text: extendFlat({}, scatterAttrs.text, { + + }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + + }), + + mode: extendFlat({}, scatterAttrs.mode, // shouldn't this be on-par with 2D? + {dflt: 'lines+markers'}), + surfaceaxis: { + valType: 'enumerated', + + values: [-1, 0, 1, 2], + dflt: -1, + + }, + surfacecolor: { + valType: 'color', + + + }, + projection: { + x: makeProjectionAttr('x'), + y: makeProjectionAttr('y'), + z: makeProjectionAttr('z') + }, + + connectgaps: scatterAttrs.connectgaps, + line: lineAttrs, + + marker: extendFlat({ // Parity with scatter.js? + symbol: { + valType: 'enumerated', + values: Object.keys(MARKER_SYMBOLS), + + dflt: 'circle', + arrayOk: true, + + }, + size: extendFlat({}, scatterMarkerAttrs.size, {dflt: 8}), + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + opacity: extendFlat({}, scatterMarkerAttrs.opacity, { + arrayOk: false, + + }), + colorbar: scatterMarkerAttrs.colorbar, + + line: extendFlat({ + width: extendFlat({}, scatterMarkerLineAttrs.width, {arrayOk: false}) + }, + colorAttributes('marker.line') + ) + }, + colorAttributes('marker') + ), + + textposition: extendFlat({}, scatterAttrs.textposition, {dflt: 'top center', arrayOk: false}), + textfont: { + color: scatterAttrs.textfont.color, + size: scatterAttrs.textfont.size, + family: extendFlat({}, scatterAttrs.textfont.family, {arrayOk: false}) + }, + + hoverinfo: extendFlat({}, baseAttrs.hoverinfo) +}, 'calc', 'nested'); + +attrs.x.editType = attrs.y.editType = attrs.z.editType = 'calc+clearAxisTypes'; + +},{"../../components/colorscale/attributes":577,"../../constants/gl3d_dashes":670,"../../constants/gl3d_markers":671,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../scatter/attributes":1043}],1071:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcColorscales = _dereq_('../scatter/colorscale_calc'); + + +/** + * This is a kludge to put the array attributes into + * calcdata the way Scatter.plot does, so that legends and + * popovers know what to do with them. + */ +module.exports = function calc(gd, trace) { + var cd = [{x: false, y: false, trace: trace, t: {}}]; + + arraysToCalcdata(cd, trace); + calcColorscales(trace); + + return cd; +}; + +},{"../scatter/arrays_to_calcdata":1042,"../scatter/colorscale_calc":1046}],1072:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = _dereq_('../../registry'); + +function calculateAxisErrors(data, params, scaleFactor, axis) { + if(!params || !params.visible) return null; + + var computeError = Registry.getComponentMethod('errorbars', 'makeComputeError')(params); + var result = new Array(data.length); + + for(var i = 0; i < data.length; i++) { + var errors = computeError(+data[i], i); + + if(axis.type === 'log') { + var point = axis.c2l(data[i]); + var min = data[i] - errors[0], + max = data[i] + errors[1]; + + result[i] = [ + (axis.c2l(min, true) - point) * scaleFactor, + (axis.c2l(max, true) - point) * scaleFactor + ]; + + // Keep track of the lower error bound which isn't negative! + if(min > 0) { + var lower = axis.c2l(min); + if(!axis._lowerLogErrorBound) axis._lowerLogErrorBound = lower; + axis._lowerErrorBound = Math.min(axis._lowerLogErrorBound, lower); + } + } else { + result[i] = [ + -errors[0] * scaleFactor, + errors[1] * scaleFactor + ]; + } + } + + return result; +} + +function dataLength(array) { + for(var i = 0; i < array.length; i++) { + if(array[i]) return array[i].length; + } + return 0; +} + +function calculateErrors(data, scaleFactor, sceneLayout) { + var errors = [ + calculateAxisErrors(data.x, data.error_x, scaleFactor[0], sceneLayout.xaxis), + calculateAxisErrors(data.y, data.error_y, scaleFactor[1], sceneLayout.yaxis), + calculateAxisErrors(data.z, data.error_z, scaleFactor[2], sceneLayout.zaxis) + ]; + + var n = dataLength(errors); + if(n === 0) return null; + + var errorBounds = new Array(n); + + for(var i = 0; i < n; i++) { + var bound = [[0, 0, 0], [0, 0, 0]]; + + for(var j = 0; j < 3; j++) { + if(errors[j]) { + for(var k = 0; k < 2; k++) { + bound[k][j] = errors[j][i][k]; + } + } + } + + errorBounds[i] = bound; + } + + return errorBounds; +} + +module.exports = calculateErrors; + +},{"../../registry":827}],1073:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createLinePlot = _dereq_('gl-line3d'); +var createScatterPlot = _dereq_('gl-scatter3d'); +var createErrorBars = _dereq_('gl-error3d'); +var createMesh = _dereq_('gl-mesh3d'); +var triangulate = _dereq_('delaunay-triangulate'); + +var Lib = _dereq_('../../lib'); +var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); +var formatColor = _dereq_('../../lib/gl_format_color').formatColor; +var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); +var DASH_PATTERNS = _dereq_('../../constants/gl3d_dashes'); +var MARKER_SYMBOLS = _dereq_('../../constants/gl3d_markers'); + +var calculateError = _dereq_('./calc_errors'); + +function LineWithMarkers(scene, uid) { + this.scene = scene; + this.uid = uid; + this.linePlot = null; + this.scatterPlot = null; + this.errorBars = null; + this.textMarkers = null; + this.delaunayMesh = null; + this.color = null; + this.mode = ''; + this.dataPoints = []; + this.axesBounds = [ + [-Infinity, -Infinity, -Infinity], + [Infinity, Infinity, Infinity] + ]; + this.textLabels = null; + this.data = null; +} + +var proto = LineWithMarkers.prototype; + +proto.handlePick = function(selection) { + if(selection.object && + (selection.object === this.linePlot || + selection.object === this.delaunayMesh || + selection.object === this.textMarkers || + selection.object === this.scatterPlot) + ) { + var ind = selection.index = selection.data.index; + + if(selection.object.highlight) { + selection.object.highlight(null); + } + if(this.scatterPlot) { + selection.object = this.scatterPlot; + this.scatterPlot.highlight(selection.data); + } + + selection.textLabel = ''; + if(this.textLabels) { + if(Array.isArray(this.textLabels)) { + if(this.textLabels[ind] || this.textLabels[ind] === 0) { + selection.textLabel = this.textLabels[ind]; + } + } else { + selection.textLabel = this.textLabels; + } + } + + selection.traceCoordinate = [ + this.data.x[ind], + this.data.y[ind], + this.data.z[ind] + ]; + + return true; + } +}; + +function constructDelaunay(points, color, axis) { + var u = (axis + 1) % 3; + var v = (axis + 2) % 3; + var filteredPoints = []; + var filteredIds = []; + var i; + + for(i = 0; i < points.length; ++i) { + var p = points[i]; + if(isNaN(p[u]) || !isFinite(p[u]) || + isNaN(p[v]) || !isFinite(p[v])) { + continue; + } + filteredPoints.push([p[u], p[v]]); + filteredIds.push(i); + } + var cells = triangulate(filteredPoints); + for(i = 0; i < cells.length; ++i) { + var c = cells[i]; + for(var j = 0; j < c.length; ++j) { + c[j] = filteredIds[c[j]]; + } + } + return { + positions: points, + cells: cells, + meshColor: color + }; +} + +function calculateErrorParams(errors) { + var capSize = [0.0, 0.0, 0.0], + color = [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + lineWidth = [1.0, 1.0, 1.0]; + + for(var i = 0; i < 3; i++) { + var e = errors[i]; + + if(e && e.copy_zstyle !== false && errors[2].visible !== false) e = errors[2]; + if(!e || !e.visible) continue; + + capSize[i] = e.width / 2; // ballpark rescaling + color[i] = str2RgbaArray(e.color); + lineWidth[i] = e.thickness; + + } + + return {capSize: capSize, color: color, lineWidth: lineWidth}; +} + +function calculateTextOffset(tp) { + // Read out text properties + var textOffset = [0, 0]; + if(Array.isArray(tp)) return [0, -1]; + if(tp.indexOf('bottom') >= 0) textOffset[1] += 1; + if(tp.indexOf('top') >= 0) textOffset[1] -= 1; + if(tp.indexOf('left') >= 0) textOffset[0] -= 1; + if(tp.indexOf('right') >= 0) textOffset[0] += 1; + return textOffset; +} + + +function calculateSize(sizeIn, sizeFn) { + // rough parity with Plotly 2D markers + return sizeFn(sizeIn * 4); +} + +function calculateSymbol(symbolIn) { + return MARKER_SYMBOLS[symbolIn]; +} + +function formatParam(paramIn, len, calculate, dflt, extraFn) { + var paramOut = null; + + if(Lib.isArrayOrTypedArray(paramIn)) { + paramOut = []; + + for(var i = 0; i < len; i++) { + if(paramIn[i] === undefined) paramOut[i] = dflt; + else paramOut[i] = calculate(paramIn[i], extraFn); + } + + } + else paramOut = calculate(paramIn, Lib.identity); + + return paramOut; +} + + +function convertPlotlyOptions(scene, data) { + var params, i, + points = [], + sceneLayout = scene.fullSceneLayout, + scaleFactor = scene.dataScale, + xaxis = sceneLayout.xaxis, + yaxis = sceneLayout.yaxis, + zaxis = sceneLayout.zaxis, + marker = data.marker, + line = data.line, + xc, x = data.x || [], + yc, y = data.y || [], + zc, z = data.z || [], + len = x.length, + xcalendar = data.xcalendar, + ycalendar = data.ycalendar, + zcalendar = data.zcalendar, + text; + + // Convert points + for(i = 0; i < len; i++) { + // sanitize numbers and apply transforms based on axes.type + xc = xaxis.d2l(x[i], 0, xcalendar) * scaleFactor[0]; + yc = yaxis.d2l(y[i], 0, ycalendar) * scaleFactor[1]; + zc = zaxis.d2l(z[i], 0, zcalendar) * scaleFactor[2]; + + points[i] = [xc, yc, zc]; + } + + // convert text + if(Array.isArray(data.text)) text = data.text; + else if(data.text !== undefined) { + text = new Array(len); + for(i = 0; i < len; i++) text[i] = data.text; + } + + // Build object parameters + params = { + position: points, + mode: data.mode, + text: text + }; + + if('line' in data) { + params.lineColor = formatColor(line, 1, len); + params.lineWidth = line.width; + params.lineDashes = line.dash; + } + + if('marker' in data) { + var sizeFn = makeBubbleSizeFn(data); + + params.scatterColor = formatColor(marker, 1, len); + params.scatterSize = formatParam(marker.size, len, calculateSize, 20, sizeFn); + params.scatterMarker = formatParam(marker.symbol, len, calculateSymbol, '●'); + params.scatterLineWidth = marker.line.width; // arrayOk === false + params.scatterLineColor = formatColor(marker.line, 1, len); + params.scatterAngle = 0; + } + + if('textposition' in data) { + params.textOffset = calculateTextOffset(data.textposition); // arrayOk === false + params.textColor = formatColor(data.textfont, 1, len); + params.textSize = formatParam(data.textfont.size, len, Lib.identity, 12); + params.textFont = data.textfont.family; // arrayOk === false + params.textAngle = 0; + } + + var dims = ['x', 'y', 'z']; + params.project = [false, false, false]; + params.projectScale = [1, 1, 1]; + params.projectOpacity = [1, 1, 1]; + for(i = 0; i < 3; ++i) { + var projection = data.projection[dims[i]]; + if((params.project[i] = projection.show)) { + params.projectOpacity[i] = projection.opacity; + params.projectScale[i] = projection.scale; + } + } + + params.errorBounds = calculateError(data, scaleFactor, sceneLayout); + + var errorParams = calculateErrorParams([data.error_x, data.error_y, data.error_z]); + params.errorColor = errorParams.color; + params.errorLineWidth = errorParams.lineWidth; + params.errorCapSize = errorParams.capSize; + + params.delaunayAxis = data.surfaceaxis; + params.delaunayColor = str2RgbaArray(data.surfacecolor); + + return params; +} + +function arrayToColor(color) { + if(Array.isArray(color)) { + var c = color[0]; + + if(Array.isArray(c)) color = c; + + return 'rgb(' + color.slice(0, 3).map(function(x) { + return Math.round(x * 255); + }) + ')'; + } + + return null; +} + +proto.update = function(data) { + var gl = this.scene.glplot.gl, + lineOptions, + scatterOptions, + errorOptions, + textOptions, + dashPattern = DASH_PATTERNS.solid; + + // Save data + this.data = data; + + // Run data conversion + var options = convertPlotlyOptions(this.scene, data); + + if('mode' in options) { + this.mode = options.mode; + } + if('lineDashes' in options) { + if(options.lineDashes in DASH_PATTERNS) { + dashPattern = DASH_PATTERNS[options.lineDashes]; + } + } + + this.color = arrayToColor(options.scatterColor) || + arrayToColor(options.lineColor); + + // Save data points + this.dataPoints = options.position; + + lineOptions = { + gl: gl, + position: options.position, + color: options.lineColor, + lineWidth: options.lineWidth || 1, + dashes: dashPattern[0], + dashScale: dashPattern[1], + opacity: data.opacity, + connectGaps: data.connectgaps + }; + + if(this.mode.indexOf('lines') !== -1) { + if(this.linePlot) this.linePlot.update(lineOptions); + else { + this.linePlot = createLinePlot(lineOptions); + this.linePlot._trace = this; + this.scene.glplot.add(this.linePlot); + } + } else if(this.linePlot) { + this.scene.glplot.remove(this.linePlot); + this.linePlot.dispose(); + this.linePlot = null; + } + + // N.B. marker.opacity must be a scalar for performance + var scatterOpacity = data.opacity; + if(data.marker && data.marker.opacity) scatterOpacity *= data.marker.opacity; + + scatterOptions = { + gl: gl, + position: options.position, + color: options.scatterColor, + size: options.scatterSize, + glyph: options.scatterMarker, + opacity: scatterOpacity, + orthographic: true, + lineWidth: options.scatterLineWidth, + lineColor: options.scatterLineColor, + project: options.project, + projectScale: options.projectScale, + projectOpacity: options.projectOpacity + }; + + if(this.mode.indexOf('markers') !== -1) { + if(this.scatterPlot) this.scatterPlot.update(scatterOptions); + else { + this.scatterPlot = createScatterPlot(scatterOptions); + this.scatterPlot._trace = this; + this.scatterPlot.highlightScale = 1; + this.scene.glplot.add(this.scatterPlot); + } + } else if(this.scatterPlot) { + this.scene.glplot.remove(this.scatterPlot); + this.scatterPlot.dispose(); + this.scatterPlot = null; + } + + textOptions = { + gl: gl, + position: options.position, + glyph: options.text, + color: options.textColor, + size: options.textSize, + angle: options.textAngle, + alignment: options.textOffset, + font: options.textFont, + orthographic: true, + lineWidth: 0, + project: false, + opacity: data.opacity + }; + + this.textLabels = data.hovertext || data.text; + + if(this.mode.indexOf('text') !== -1) { + if(this.textMarkers) this.textMarkers.update(textOptions); + else { + this.textMarkers = createScatterPlot(textOptions); + this.textMarkers._trace = this; + this.textMarkers.highlightScale = 1; + this.scene.glplot.add(this.textMarkers); + } + } else if(this.textMarkers) { + this.scene.glplot.remove(this.textMarkers); + this.textMarkers.dispose(); + this.textMarkers = null; + } + + errorOptions = { + gl: gl, + position: options.position, + color: options.errorColor, + error: options.errorBounds, + lineWidth: options.errorLineWidth, + capSize: options.errorCapSize, + opacity: data.opacity + }; + if(this.errorBars) { + if(options.errorBounds) { + this.errorBars.update(errorOptions); + } else { + this.scene.glplot.remove(this.errorBars); + this.errorBars.dispose(); + this.errorBars = null; + } + } else if(options.errorBounds) { + this.errorBars = createErrorBars(errorOptions); + this.errorBars._trace = this; + this.scene.glplot.add(this.errorBars); + } + + if(options.delaunayAxis >= 0) { + var delaunayOptions = constructDelaunay( + options.position, + options.delaunayColor, + options.delaunayAxis + ); + delaunayOptions.opacity = data.opacity; + + if(this.delaunayMesh) { + this.delaunayMesh.update(delaunayOptions); + } else { + delaunayOptions.gl = gl; + this.delaunayMesh = createMesh(delaunayOptions); + this.delaunayMesh._trace = this; + this.scene.glplot.add(this.delaunayMesh); + } + } else if(this.delaunayMesh) { + this.scene.glplot.remove(this.delaunayMesh); + this.delaunayMesh.dispose(); + this.delaunayMesh = null; + } +}; + +proto.dispose = function() { + if(this.linePlot) { + this.scene.glplot.remove(this.linePlot); + this.linePlot.dispose(); + } + if(this.scatterPlot) { + this.scene.glplot.remove(this.scatterPlot); + this.scatterPlot.dispose(); + } + if(this.errorBars) { + this.scene.glplot.remove(this.errorBars); + this.errorBars.dispose(); + } + if(this.textMarkers) { + this.scene.glplot.remove(this.textMarkers); + this.textMarkers.dispose(); + } + if(this.delaunayMesh) { + this.scene.glplot.remove(this.delaunayMesh); + this.delaunayMesh.dispose(); + } +}; + +function createLineWithMarkers(scene, data) { + var plot = new LineWithMarkers(scene, data.uid); + plot.update(data); + return plot; +} + +module.exports = createLineWithMarkers; + +},{"../../constants/gl3d_dashes":670,"../../constants/gl3d_markers":671,"../../lib":696,"../../lib/gl_format_color":692,"../../lib/str2rgbarray":719,"../scatter/make_bubble_size_func":1060,"./calc_errors":1072,"delaunay-triangulate":150,"gl-error3d":237,"gl-line3d":245,"gl-mesh3d":268,"gl-scatter3d":284}],1074:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); + +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleXYZDefaults(traceIn, traceOut, coerce, layout); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + coerce('hovertext'); + coerce('mode'); + + if(subTypes.hasLines(traceOut)) { + coerce('connectgaps'); + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noSelect: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce, {noSelect: true}); + } + + var lineColor = (traceOut.line || {}).color, + markerColor = (traceOut.marker || {}).color; + if(coerce('surfaceaxis') >= 0) coerce('surfacecolor', lineColor || markerColor); + + var dims = ['x', 'y', 'z']; + for(var i = 0; i < 3; ++i) { + var projection = 'projection.' + dims[i]; + if(coerce(projection + '.show')) { + coerce(projection + '.opacity'); + coerce(projection + '.scale'); + } + } + + var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'z'}); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'y', inherit: 'z'}); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'x', inherit: 'z'}); +}; + +function handleXYZDefaults(traceIn, traceOut, coerce, layout) { + var len = 0, + x = coerce('x'), + y = coerce('y'), + z = coerce('z'); + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); + + if(x && y && z) { + // TODO: what happens if one is missing? + len = Math.min(x.length, y.length, z.length); + traceOut._length = traceOut._xlength = traceOut._ylength = traceOut._zlength = len; + } + + return len; +} + +},{"../../lib":696,"../../registry":827,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1070}],1075:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Scatter3D = {}; + +Scatter3D.plot = _dereq_('./convert'); +Scatter3D.attributes = _dereq_('./attributes'); +Scatter3D.markerSymbols = _dereq_('../../constants/gl3d_markers'); +Scatter3D.supplyDefaults = _dereq_('./defaults'); +Scatter3D.colorbar = _dereq_('../scatter/marker_colorbar'); +Scatter3D.calc = _dereq_('./calc'); + +Scatter3D.moduleType = 'trace'; +Scatter3D.name = 'scatter3d'; +Scatter3D.basePlotModule = _dereq_('../../plots/gl3d'); +Scatter3D.categories = ['gl3d', 'symbols', 'showLegend']; +Scatter3D.meta = { + + +}; + +module.exports = Scatter3D; + +},{"../../constants/gl3d_markers":671,"../../plots/gl3d":787,"../scatter/marker_colorbar":1061,"./attributes":1070,"./calc":1071,"./convert":1073,"./defaults":1074}],1076:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker, + scatterLineAttrs = scatterAttrs.line, + scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +module.exports = { + carpet: { + valType: 'string', + + editType: 'calc', + + }, + a: { + valType: 'data_array', + editType: 'calc', + + }, + b: { + valType: 'data_array', + editType: 'calc', + + }, + mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), + text: extendFlat({}, scatterAttrs.text, { + + }), + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + dash: scatterLineAttrs.dash, + shape: extendFlat({}, scatterLineAttrs.shape, + {values: ['linear', 'spline']}), + smoothing: scatterLineAttrs.smoothing, + editType: 'calc' + }, + connectgaps: scatterAttrs.connectgaps, + fill: extendFlat({}, scatterAttrs.fill, { + values: ['none', 'toself', 'tonext'], + dflt: 'none', + + }), + fillcolor: scatterAttrs.fillcolor, + marker: extendFlat({ + symbol: scatterMarkerAttrs.symbol, + opacity: scatterMarkerAttrs.opacity, + maxdisplayed: scatterMarkerAttrs.maxdisplayed, + size: scatterMarkerAttrs.size, + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + line: extendFlat({ + width: scatterMarkerLineAttrs.width, + editType: 'calc' + }, + colorAttributes('marker.line') + ), + gradient: scatterMarkerAttrs.gradient, + editType: 'calc' + }, colorAttributes('marker'), { + colorbar: colorbarAttrs + }), + + textfont: scatterAttrs.textfont, + textposition: scatterAttrs.textposition, + + selected: scatterAttrs.selected, + unselected: scatterAttrs.unselected, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['a', 'b', 'text', 'name'] + }), + hoveron: scatterAttrs.hoveron, +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../scatter/attributes":1043}],1077:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var calcColorscale = _dereq_('../scatter/colorscale_calc'); +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); +var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; +var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); + +module.exports = function calc(gd, trace) { + var carpet = trace._carpetTrace = lookupCarpet(gd, trace); + if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; + var i; + + // Transfer this over from carpet before plotting since this is a necessary + // condition in order for cartesian to actually plot this trace: + trace.xaxis = carpet.xaxis; + trace.yaxis = carpet.yaxis; + + // make the calcdata array + var serieslen = trace._length; + var cd = new Array(serieslen); + var a, b; + var needsCull = false; + for(i = 0; i < serieslen; i++) { + a = trace.a[i]; + b = trace.b[i]; + if(isNumeric(a) && isNumeric(b)) { + var xy = carpet.ab2xy(+a, +b, true); + var visible = carpet.isVisible(+a, +b); + if(!visible) needsCull = true; + cd[i] = {x: xy[0], y: xy[1], a: a, b: b, vis: visible}; + } + else cd[i] = {x: false, y: false}; + } + + trace._needsCull = needsCull; + + cd[0].carpet = carpet; + cd[0].trace = trace; + + calcMarkerSize(trace, serieslen); + calcColorscale(trace); + arraysToCalcdata(cd, trace); + calcSelection(cd, trace); + + return cd; +}; + +},{"../carpet/lookup_carpetid":894,"../scatter/arrays_to_calcdata":1042,"../scatter/calc":1044,"../scatter/calc_selection":1045,"../scatter/colorscale_calc":1046,"fast-isnumeric":214}],1078:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var constants = _dereq_('../scatter/constants'); +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); + +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + coerce('carpet'); + + // XXX: Don't hard code this + traceOut.xaxis = 'x'; + traceOut.yaxis = 'y'; + + var a = coerce('a'); + var b = coerce('b'); + var len = Math.min(a.length, b.length); + + if(!len) { + traceOut.visible = false; + return; + } + + traceOut._length = len; + + coerce('text'); + + var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; + coerce('mode', defaultMode); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + handleLineShapeDefaults(traceIn, traceOut, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + var dfltHoverOn = []; + + if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { + coerce('marker.maxdisplayed'); + dfltHoverOn.push('points'); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + } + + if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { + dfltHoverOn.push('fills'); + } + coerce('hoveron', dfltHoverOn.join('+') || 'points'); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../scatter/constants":1047,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/line_shape_defaults":1058,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1076}],1079:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function eventData(out, pt, trace, cd, pointNumber) { + var cdi = cd[pointNumber]; + + out.a = cdi.a; + out.b = cdi.b; + + return out; +}; + +},{}],1080:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scatterHover = _dereq_('../scatter/hover'); + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var scatterPointData = scatterHover(pointData, xval, yval, hovermode); + if(!scatterPointData || scatterPointData[0].index === false) return; + + var newPointData = scatterPointData[0]; + + // if hovering on a fill, we don't show any point data so the label is + // unchanged from what scatter gives us - except that it needs to + // be constrained to the trianglular plot area, not just the rectangular + // area defined by the synthetic x and y axes + // TODO: in some cases the vertical middle of the shape is not within + // the triangular viewport at all, so the label can become disconnected + // from the shape entirely. But calculating what portion of the shape + // is actually visible, as constrained by the diagonal axis lines, is not + // so easy and anyway we lost the information we would have needed to do + // this inside scatterHover. + if(newPointData.index === undefined) { + var yFracUp = 1 - (newPointData.y0 / pointData.ya._length), + xLen = pointData.xa._length, + xMin = xLen * yFracUp / 2, + xMax = xLen - xMin; + newPointData.x0 = Math.max(Math.min(newPointData.x0, xMax), xMin); + newPointData.x1 = Math.max(Math.min(newPointData.x1, xMax), xMin); + return scatterPointData; + } + + var cdi = newPointData.cd[newPointData.index]; + + newPointData.a = cdi.a; + newPointData.b = cdi.b; + + newPointData.xLabelVal = undefined; + newPointData.yLabelVal = undefined; + // TODO: nice formatting, and label by axis title, for a, b, and c? + + var trace = newPointData.trace; + var carpet = trace._carpet; + var hoverinfo = cdi.hi || trace.hoverinfo; + var parts = hoverinfo.split('+'); + var text = []; + + function textPart(ax, val) { + var prefix; + + if(ax.labelprefix && ax.labelprefix.length > 0) { + prefix = ax.labelprefix.replace(/ = $/, ''); + } else { + prefix = ax._hovertitle; + } + + text.push(prefix + ': ' + val.toFixed(3) + ax.labelsuffix); + } + + if(parts.indexOf('all') !== -1) parts = ['a', 'b']; + if(parts.indexOf('a') !== -1) textPart(carpet.aaxis, cdi.a); + if(parts.indexOf('b') !== -1) textPart(carpet.baxis, cdi.b); + + var ij = carpet.ab2ij([cdi.a, cdi.b]); + var i0 = Math.floor(ij[0]); + var ti = ij[0] - i0; + + var j0 = Math.floor(ij[1]); + var tj = ij[1] - j0; + + var xy = carpet.evalxy([], i0, j0, ti, tj); + text.push('y: ' + xy[1].toFixed(3)); + + newPointData.extraText = text.join('
'); + + return scatterPointData; +}; + +},{"../scatter/hover":1054}],1081:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ScatterCarpet = {}; + +ScatterCarpet.attributes = _dereq_('./attributes'); +ScatterCarpet.supplyDefaults = _dereq_('./defaults'); +ScatterCarpet.colorbar = _dereq_('../scatter/marker_colorbar'); +ScatterCarpet.calc = _dereq_('./calc'); +ScatterCarpet.plot = _dereq_('./plot'); +ScatterCarpet.style = _dereq_('../scatter/style').style; +ScatterCarpet.styleOnSelect = _dereq_('../scatter/style').styleOnSelect; +ScatterCarpet.hoverPoints = _dereq_('./hover'); +ScatterCarpet.selectPoints = _dereq_('../scatter/select'); +ScatterCarpet.eventData = _dereq_('./event_data'); + +ScatterCarpet.moduleType = 'trace'; +ScatterCarpet.name = 'scattercarpet'; +ScatterCarpet.basePlotModule = _dereq_('../../plots/cartesian'); +ScatterCarpet.categories = ['svg', 'carpet', 'symbols', 'showLegend', 'carpetDependent', 'zoomScale']; +ScatterCarpet.meta = { + + +}; + +module.exports = ScatterCarpet; + +},{"../../plots/cartesian":756,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1076,"./calc":1077,"./defaults":1078,"./event_data":1079,"./hover":1080,"./plot":1082}],1082:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scatterPlot = _dereq_('../scatter/plot'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Drawing = _dereq_('../../components/drawing'); + +module.exports = function plot(gd, plotinfoproxy, data, layer) { + var i, trace, node; + + var carpet = data[0][0].carpet; + // mimic cartesian plotinfo + var plotinfo = { + xaxis: Axes.getFromId(gd, carpet.xaxis || 'x'), + yaxis: Axes.getFromId(gd, carpet.yaxis || 'y'), + plot: plotinfoproxy.plot, + }; + + scatterPlot(gd, plotinfo, data, layer); + + for(i = 0; i < data.length; i++) { + trace = data[i][0].trace; + + // Note: .select is adequate but seems to mutate the node data, + // which is at least a bit suprising and causes problems elsewhere + node = layer.selectAll('g.trace' + trace.uid + ' .js-line'); + + // Note: it would be more efficient if this didn't need to be applied + // separately to all scattercarpet traces, but that would require + // lots of reorganization of scatter traces that is otherwise not + // necessary. That makes this a potential optimization. + Drawing.setClipUrl(node, carpet._clipPathId); + } +}; + +},{"../../components/drawing":595,"../../plots/cartesian/axes":744,"../scatter/plot":1063}],1083:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var scatterMarkerAttrs = scatterAttrs.marker, + scatterLineAttrs = scatterAttrs.line, + scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +module.exports = overrideAll({ + lon: { + valType: 'data_array', + + }, + lat: { + valType: 'data_array', + + }, + + locations: { + valType: 'data_array', + + }, + locationmode: { + valType: 'enumerated', + values: ['ISO-3', 'USA-states', 'country names'], + + dflt: 'ISO-3', + + }, + + mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), + + text: extendFlat({}, scatterAttrs.text, { + + }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + + }), + + textfont: scatterAttrs.textfont, + textposition: scatterAttrs.textposition, + + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + dash: dash + }, + connectgaps: scatterAttrs.connectgaps, + + marker: extendFlat({ + symbol: scatterMarkerAttrs.symbol, + opacity: scatterMarkerAttrs.opacity, + size: scatterMarkerAttrs.size, + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + colorbar: scatterMarkerAttrs.colorbar, + line: extendFlat({ + width: scatterMarkerLineAttrs.width + }, + colorAttributes('marker.line') + ), + gradient: scatterMarkerAttrs.gradient + }, + colorAttributes('marker') + ), + + fill: { + valType: 'enumerated', + values: ['none', 'toself'], + dflt: 'none', + + + }, + fillcolor: scatterAttrs.fillcolor, + + selected: scatterAttrs.selected, + unselected: scatterAttrs.unselected, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['lon', 'lat', 'location', 'text', 'name'] + }) +}, 'calc', 'nested'); + +},{"../../components/colorscale/attributes":577,"../../components/drawing/attributes":594,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../scatter/attributes":1043}],1084:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var calcMarkerColorscale = _dereq_('../scatter/colorscale_calc'); +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); + +var _ = _dereq_('../../lib')._; + +module.exports = function calc(gd, trace) { + var hasLocationData = Array.isArray(trace.locations); + var len = hasLocationData ? trace.locations.length : trace._length; + var calcTrace = new Array(len); + + for(var i = 0; i < len; i++) { + var calcPt = calcTrace[i] = {}; + + if(hasLocationData) { + var loc = trace.locations[i]; + calcPt.loc = typeof loc === 'string' ? loc : null; + } else { + var lon = trace.lon[i]; + var lat = trace.lat[i]; + + if(isNumeric(lon) && isNumeric(lat)) calcPt.lonlat = [+lon, +lat]; + else calcPt.lonlat = [BADNUM, BADNUM]; + } + } + + arraysToCalcdata(calcTrace, trace); + calcMarkerColorscale(trace); + calcSelection(calcTrace, trace); + + if(len) { + calcTrace[0].t = { + labels: { + lat: _(gd, 'lat:') + ' ', + lon: _(gd, 'lon:') + ' ' + } + }; + } + + return calcTrace; +}; + +},{"../../constants/numerical":673,"../../lib":696,"../scatter/arrays_to_calcdata":1042,"../scatter/calc_selection":1045,"../scatter/colorscale_calc":1046,"fast-isnumeric":214}],1085:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); + +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleLonLatLocDefaults(traceIn, traceOut, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + coerce('hovertext'); + coerce('mode'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + } + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +function handleLonLatLocDefaults(traceIn, traceOut, coerce) { + var len = 0, + locations = coerce('locations'); + + var lon, lat; + + if(locations) { + coerce('locationmode'); + len = locations.length; + return len; + } + + lon = coerce('lon') || []; + lat = coerce('lat') || []; + len = Math.min(lon.length, lat.length); + traceOut._length = len; + + return len; +} + +},{"../../lib":696,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1083}],1086:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = function eventData(out, pt) { + out.lon = pt.lon; + out.lat = pt.lat; + out.location = pt.loc ? pt.loc : null; + + return out; +}; + +},{}],1087:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = _dereq_('../../components/fx'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var getTraceColor = _dereq_('../scatter/get_trace_color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); +var attributes = _dereq_('./attributes'); + +module.exports = function hoverPoints(pointData, xval, yval) { + var cd = pointData.cd; + var trace = cd[0].trace; + var xa = pointData.xa; + var ya = pointData.ya; + var geo = pointData.subplot; + + var isLonLatOverEdges = geo.projection.isLonLatOverEdges; + var project = geo.project; + + function distFn(d) { + var lonlat = d.lonlat; + + if(lonlat[0] === BADNUM) return Infinity; + if(isLonLatOverEdges(lonlat)) return Infinity; + + var pt = project(lonlat); + var px = project([xval, yval]); + var dx = Math.abs(pt[0] - px[0]); + var dy = Math.abs(pt[1] - px[1]); + var rad = Math.max(3, d.mrc || 0); + + // N.B. d.mrc is the calculated marker radius + // which is only set for trace with 'markers' mode. + + return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); + } + + Fx.getClosest(cd, distFn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index === false) return; + + var di = cd[pointData.index]; + var lonlat = di.lonlat; + var pos = [xa.c2p(lonlat), ya.c2p(lonlat)]; + var rad = di.mrc || 1; + + pointData.x0 = pos[0] - rad; + pointData.x1 = pos[0] + rad; + pointData.y0 = pos[1] - rad; + pointData.y1 = pos[1] + rad; + + pointData.loc = di.loc; + pointData.lon = lonlat[0]; + pointData.lat = lonlat[1]; + + pointData.color = getTraceColor(trace, di); + pointData.extraText = getExtraText(trace, di, geo.mockAxis, cd[0].t.labels); + + return [pointData]; +}; + +function getExtraText(trace, pt, axis, labels) { + var hoverinfo = pt.hi || trace.hoverinfo; + + var parts = hoverinfo === 'all' ? + attributes.hoverinfo.flags : + hoverinfo.split('+'); + + var hasLocation = parts.indexOf('location') !== -1 && Array.isArray(trace.locations); + var hasLon = (parts.indexOf('lon') !== -1); + var hasLat = (parts.indexOf('lat') !== -1); + var hasText = (parts.indexOf('text') !== -1); + var text = []; + + function format(val) { + return Axes.tickText(axis, axis.c2l(val), 'hover').text + '\u00B0'; + } + + if(hasLocation) { + text.push(pt.loc); + } else if(hasLon && hasLat) { + text.push('(' + format(pt.lonlat[0]) + ', ' + format(pt.lonlat[1]) + ')'); + } else if(hasLon) { + text.push(labels.lon + format(pt.lonlat[0])); + } else if(hasLat) { + text.push(labels.lat + format(pt.lonlat[1])); + } + + if(hasText) { + fillHoverText(pt, trace, text); + } + + return text.join('
'); +} + +},{"../../components/fx":612,"../../constants/numerical":673,"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051,"../scatter/get_trace_color":1053,"./attributes":1083}],1088:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var ScatterGeo = {}; + +ScatterGeo.attributes = _dereq_('./attributes'); +ScatterGeo.supplyDefaults = _dereq_('./defaults'); +ScatterGeo.colorbar = _dereq_('../scatter/marker_colorbar'); +ScatterGeo.calc = _dereq_('./calc'); +ScatterGeo.plot = _dereq_('./plot'); +ScatterGeo.style = _dereq_('./style'); +ScatterGeo.styleOnSelect = _dereq_('../scatter/style').styleOnSelect; +ScatterGeo.hoverPoints = _dereq_('./hover'); +ScatterGeo.eventData = _dereq_('./event_data'); +ScatterGeo.selectPoints = _dereq_('./select'); + +ScatterGeo.moduleType = 'trace'; +ScatterGeo.name = 'scattergeo'; +ScatterGeo.basePlotModule = _dereq_('../../plots/geo'); +ScatterGeo.categories = ['geo', 'symbols', 'showLegend', 'scatter-like']; +ScatterGeo.meta = { + + +}; + +module.exports = ScatterGeo; + +},{"../../plots/geo":775,"../scatter/marker_colorbar":1061,"../scatter/style":1066,"./attributes":1083,"./calc":1084,"./defaults":1085,"./event_data":1086,"./hover":1087,"./plot":1089,"./select":1090,"./style":1091}],1089:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); + +var Lib = _dereq_('../../lib'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; +var getTopojsonFeatures = _dereq_('../../lib/topojson_utils').getTopojsonFeatures; +var locationToFeature = _dereq_('../../lib/geo_location_utils').locationToFeature; +var geoJsonUtils = _dereq_('../../lib/geojson_utils'); +var subTypes = _dereq_('../scatter/subtypes'); +var style = _dereq_('./style'); + +module.exports = function plot(gd, geo, calcData) { + for(var i = 0; i < calcData.length; i++) { + calcGeoJSON(calcData[i], geo.topojson); + } + + function removeBADNUM(d, node) { + if(d.lonlat[0] === BADNUM) { + d3.select(node).remove(); + } + } + + var scatterLayer = geo.layers.frontplot.select('.scatterlayer'); + var gTraces = Lib.makeTraceGroups(scatterLayer, calcData, 'trace scattergeo'); + + // TODO find a way to order the inner nodes on update + gTraces.selectAll('*').remove(); + + gTraces.each(function(calcTrace) { + var s = calcTrace[0].node3 = d3.select(this); + var trace = calcTrace[0].trace; + + if(subTypes.hasLines(trace) || trace.fill !== 'none') { + var lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace); + + var lineData = (trace.fill !== 'none') ? + geoJsonUtils.makePolygon(lineCoords) : + geoJsonUtils.makeLine(lineCoords); + + s.selectAll('path.js-line') + .data([{geojson: lineData, trace: trace}]) + .enter().append('path') + .classed('js-line', true) + .style('stroke-miterlimit', 2); + } + + if(subTypes.hasMarkers(trace)) { + s.selectAll('path.point') + .data(Lib.identity) + .enter().append('path') + .classed('point', true) + .each(function(calcPt) { removeBADNUM(calcPt, this); }); + } + + if(subTypes.hasText(trace)) { + s.selectAll('g') + .data(Lib.identity) + .enter().append('g') + .append('text') + .each(function(calcPt) { removeBADNUM(calcPt, this); }); + } + + // call style here within topojson request callback + style(gd, calcTrace); + }); +}; + +function calcGeoJSON(calcTrace, topojson) { + var trace = calcTrace[0].trace; + + if(!Array.isArray(trace.locations)) return; + + var features = getTopojsonFeatures(trace, topojson); + var locationmode = trace.locationmode; + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + var feature = locationToFeature(locationmode, calcPt.loc, features); + + calcPt.lonlat = feature ? feature.properties.ct : [BADNUM, BADNUM]; + } +} + +},{"../../constants/numerical":673,"../../lib":696,"../../lib/geo_location_utils":688,"../../lib/geojson_utils":689,"../../lib/topojson_utils":723,"../scatter/subtypes":1067,"./style":1091,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1090:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var subtypes = _dereq_('../scatter/subtypes'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var trace = cd[0].trace; + + var di, lonlat, x, y, i; + + var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); + if(hasOnlyLines) return []; + + if(selectionTester === false) { + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + di = cd[i]; + lonlat = di.lonlat; + + // some projection types can't handle BADNUMs + if(lonlat[0] === BADNUM) continue; + + x = xa.c2p(lonlat); + y = ya.c2p(lonlat); + + if(selectionTester.contains([x, y], null, i, searchInfo)) { + selection.push({ + pointNumber: i, + lon: lonlat[0], + lat: lonlat[1] + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + + return selection; +}; + +},{"../../constants/numerical":673,"../scatter/subtypes":1067}],1091:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Drawing = _dereq_('../../components/drawing'); +var Color = _dereq_('../../components/color'); + +var scatterStyle = _dereq_('../scatter/style'); +var stylePoints = scatterStyle.stylePoints; +var styleText = scatterStyle.styleText; + +module.exports = function style(gd, calcTrace) { + if(calcTrace) styleTrace(gd, calcTrace); +}; + +function styleTrace(gd, calcTrace) { + var trace = calcTrace[0].trace; + var s = calcTrace[0].node3; + + s.style('opacity', calcTrace[0].trace.opacity); + + stylePoints(s, trace, gd); + styleText(s, trace, gd); + + // this part is incompatible with Drawing.lineGroupStyle + s.selectAll('path.js-line') + .style('fill', 'none') + .each(function(d) { + var path = d3.select(this); + var trace = d.trace; + var line = trace.line || {}; + + path.call(Color.stroke, line.color) + .call(Drawing.dashLine, line.dash || '', line.width || 0); + + if(trace.fill !== 'none') { + path.call(Color.fill, trace.fillcolor); + } + }); +} + +},{"../../components/color":570,"../../components/drawing":595,"../scatter/style":1066,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1092:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var plotAttrs = _dereq_('../../plots/attributes'); +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorAttrs = _dereq_('../../components/colorscale/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var DASHES = _dereq_('./constants').DASHES; + +var scatterLineAttrs = scatterAttrs.line; +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +var attrs = module.exports = overrideAll({ + x: scatterAttrs.x, + x0: scatterAttrs.x0, + dx: scatterAttrs.dx, + y: scatterAttrs.y, + y0: scatterAttrs.y0, + dy: scatterAttrs.dy, + + text: scatterAttrs.text, + hovertext: scatterAttrs.hovertext, + + textposition: scatterAttrs.textposition, + textfont: scatterAttrs.textfont, + + mode: { + valType: 'flaglist', + flags: ['lines', 'markers', 'text'], + extras: ['none'], + + + }, + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + shape: { + valType: 'enumerated', + values: ['linear', 'hv', 'vh', 'hvh', 'vhv'], + dflt: 'linear', + + editType: 'plot', + + }, + dash: { + valType: 'enumerated', + values: Object.keys(DASHES), + dflt: 'solid', + + + } + }, + marker: extendFlat({}, colorAttrs('marker'), { + symbol: scatterMarkerAttrs.symbol, + size: scatterMarkerAttrs.size, + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + opacity: scatterMarkerAttrs.opacity, + colorbar: scatterMarkerAttrs.colorbar, + line: extendFlat({}, colorAttrs('marker.line'), { + width: scatterMarkerLineAttrs.width + }) + }), + connectgaps: scatterAttrs.connectgaps, + fill: extendFlat({}, scatterAttrs.fill, {dflt: 'none'}), + fillcolor: scatterAttrs.fillcolor, + + // no hoveron + + selected: { + marker: scatterAttrs.selected.marker, + textfont: scatterAttrs.selected.textfont + }, + unselected: { + marker: scatterAttrs.unselected.marker, + textfont: scatterAttrs.unselected.textfont + }, + + opacity: plotAttrs.opacity + +}, 'calc', 'nested'); + +attrs.x.editType = attrs.y.editType = attrs.x0.editType = attrs.y0.editType = 'calc+clearAxisTypes'; + +},{"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../scatter/attributes":1043,"./constants":1093}],1093:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var SYMBOL_SIZE = 20; + +module.exports = { + TOO_MANY_POINTS: 1e5, + + SYMBOL_SDF_SIZE: 200, + SYMBOL_SIZE: SYMBOL_SIZE, + SYMBOL_STROKE: SYMBOL_SIZE / 20, + + DOT_RE: /-dot/, + OPEN_RE: /-open/, + + DASHES: { + solid: [1], + dot: [1, 1], + dash: [4, 1], + longdash: [8, 1], + dashdot: [4, 1, 1, 1], + longdashdot: [8, 1, 1, 1] + } +}; + +},{}],1094:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var svgSdf = _dereq_('svg-path-sdf'); +var rgba = _dereq_('color-normalize'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); +var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); + +var formatColor = _dereq_('../../lib/gl_format_color').formatColor; +var subTypes = _dereq_('../scatter/subtypes'); +var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); + +var constants = _dereq_('./constants'); +var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; + +var TEXTOFFSETSIGN = { + start: 1, left: 1, end: -1, right: -1, middle: 0, center: 0, bottom: 1, top: -1 +}; + +function convertStyle(gd, trace) { + var i; + + var opts = { + marker: undefined, + markerSel: undefined, + markerUnsel: undefined, + line: undefined, + fill: undefined, + errorX: undefined, + errorY: undefined, + text: undefined, + textSel: undefined, + textUnsel: undefined + }; + + if(trace.visible !== true) return opts; + + if(subTypes.hasText(trace)) { + opts.text = convertTextStyle(trace); + opts.textSel = convertTextSelection(trace, trace.selected); + opts.textUnsel = convertTextSelection(trace, trace.unselected); + } + + if(subTypes.hasMarkers(trace)) { + opts.marker = convertMarkerStyle(trace); + opts.markerSel = convertMarkerSelection(trace, trace.selected); + opts.markerUnsel = convertMarkerSelection(trace, trace.unselected); + + if(!trace.unselected && Array.isArray(trace.marker.opacity)) { + var mo = trace.marker.opacity; + opts.markerUnsel.opacity = new Array(mo.length); + for(i = 0; i < mo.length; i++) { + opts.markerUnsel.opacity[i] = DESELECTDIM * mo[i]; + } + } + } + + if(subTypes.hasLines(trace)) { + opts.line = { + overlay: true, + thickness: trace.line.width, + color: trace.line.color, + opacity: trace.opacity + }; + + var dashes = (constants.DASHES[trace.line.dash] || [1]).slice(); + for(i = 0; i < dashes.length; ++i) { + dashes[i] *= trace.line.width; + } + opts.line.dashes = dashes; + } + + if(trace.error_x && trace.error_x.visible) { + opts.errorX = convertErrorBarStyle(trace, trace.error_x); + } + + if(trace.error_y && trace.error_y.visible) { + opts.errorY = convertErrorBarStyle(trace, trace.error_y); + } + + if(!!trace.fill && trace.fill !== 'none') { + opts.fill = { + closed: true, + fill: trace.fillcolor, + thickness: 0 + }; + } + + return opts; +} + +function convertTextStyle(trace) { + var count = trace._length; + var textfontIn = trace.textfont; + var textpositionIn = trace.textposition; + var textPos = Array.isArray(textpositionIn) ? textpositionIn : [textpositionIn]; + var tfc = textfontIn.color; + var tfs = textfontIn.size; + var tff = textfontIn.family; + var optsOut = {}; + var i; + + optsOut.text = trace.text; + optsOut.opacity = trace.opacity; + optsOut.font = {}; + optsOut.align = []; + optsOut.baseline = []; + + for(i = 0; i < textPos.length; i++) { + var tp = textPos[i].split(/\s+/); + + switch(tp[1]) { + case 'left': + optsOut.align.push('right'); + break; + case 'right': + optsOut.align.push('left'); + break; + default: + optsOut.align.push(tp[1]); + } + switch(tp[0]) { + case 'top': + optsOut.baseline.push('bottom'); + break; + case 'bottom': + optsOut.baseline.push('top'); + break; + default: + optsOut.baseline.push(tp[0]); + } + } + + if(Array.isArray(tfc)) { + optsOut.color = new Array(count); + for(i = 0; i < count; i++) { + optsOut.color[i] = tfc[i]; + } + } else { + optsOut.color = tfc; + } + + if(Array.isArray(tfs) || Array.isArray(tff)) { + // if any textfont param is array - make render a batch + optsOut.font = new Array(count); + for(i = 0; i < count; i++) { + var fonti = optsOut.font[i] = {}; + + fonti.size = Array.isArray(tfs) ? + (isNumeric(tfs[i]) ? tfs[i] : 0) : + tfs; + + fonti.family = Array.isArray(tff) ? tff[i] : tff; + } + } else { + // if both are single values, make render fast single-value + optsOut.font = {size: tfs, family: tff}; + } + + return optsOut; +} + + +function convertMarkerStyle(trace) { + var count = trace._length; + var optsIn = trace.marker; + var optsOut = {}; + var i; + + var multiSymbol = Array.isArray(optsIn.symbol); + var multiColor = Lib.isArrayOrTypedArray(optsIn.color); + var multiLineColor = Lib.isArrayOrTypedArray(optsIn.line.color); + var multiOpacity = Lib.isArrayOrTypedArray(optsIn.opacity); + var multiSize = Lib.isArrayOrTypedArray(optsIn.size); + var multiLineWidth = Lib.isArrayOrTypedArray(optsIn.line.width); + + var isOpen; + if(!multiSymbol) isOpen = constants.OPEN_RE.test(optsIn.symbol); + + // prepare colors + if(multiSymbol || multiColor || multiLineColor || multiOpacity) { + optsOut.colors = new Array(count); + optsOut.borderColors = new Array(count); + + var colors = formatColor(optsIn, optsIn.opacity, count); + var borderColors = formatColor(optsIn.line, optsIn.opacity, count); + + if(!Array.isArray(borderColors[0])) { + var borderColor = borderColors; + borderColors = Array(count); + for(i = 0; i < count; i++) { + borderColors[i] = borderColor; + } + } + if(!Array.isArray(colors[0])) { + var color = colors; + colors = Array(count); + for(i = 0; i < count; i++) { + colors[i] = color; + } + } + + optsOut.colors = colors; + optsOut.borderColors = borderColors; + + for(i = 0; i < count; i++) { + if(multiSymbol) { + var symbol = optsIn.symbol[i]; + isOpen = constants.OPEN_RE.test(symbol); + } + if(isOpen) { + borderColors[i] = colors[i].slice(); + colors[i] = colors[i].slice(); + colors[i][3] = 0; + } + } + + optsOut.opacity = trace.opacity; + } else { + if(isOpen) { + optsOut.color = rgba(optsIn.color, 'uint8'); + optsOut.color[3] = 0; + optsOut.borderColor = rgba(optsIn.color, 'uint8'); + } else { + optsOut.color = rgba(optsIn.color, 'uint8'); + optsOut.borderColor = rgba(optsIn.line.color, 'uint8'); + } + + optsOut.opacity = trace.opacity * optsIn.opacity; + } + + // prepare symbols + if(multiSymbol) { + optsOut.markers = new Array(count); + for(i = 0; i < count; i++) { + optsOut.markers[i] = getSymbolSdf(optsIn.symbol[i]); + } + } else { + optsOut.marker = getSymbolSdf(optsIn.symbol); + } + + // prepare sizes + var markerSizeFunc = makeBubbleSizeFn(trace); + var s; + + if(multiSize || multiLineWidth) { + var sizes = optsOut.sizes = new Array(count); + var borderSizes = optsOut.borderSizes = new Array(count); + var sizeTotal = 0; + var sizeAvg; + + if(multiSize) { + for(i = 0; i < count; i++) { + sizes[i] = markerSizeFunc(optsIn.size[i]); + sizeTotal += sizes[i]; + } + sizeAvg = sizeTotal / count; + } else { + s = markerSizeFunc(optsIn.size); + for(i = 0; i < count; i++) { + sizes[i] = s; + } + } + + // See https://github.com/plotly/plotly.js/pull/1781#discussion_r121820798 + if(multiLineWidth) { + for(i = 0; i < count; i++) { + borderSizes[i] = optsIn.line.width[i] / 2; + } + } else { + s = optsIn.line.width / 2; + for(i = 0; i < count; i++) { + borderSizes[i] = s; + } + } + + optsOut.sizeAvg = sizeAvg; + } else { + optsOut.size = markerSizeFunc(optsIn && optsIn.size || 10); + optsOut.borderSizes = markerSizeFunc(optsIn.line.width); + } + + return optsOut; +} + +function convertMarkerSelection(trace, target) { + var optsIn = trace.marker; + var optsOut = {}; + + if(!target) return optsOut; + + if(target.marker && target.marker.symbol) { + optsOut = convertMarkerStyle(Lib.extendFlat({}, optsIn, target.marker)); + } else if(target.marker) { + if(target.marker.size) optsOut.size = target.marker.size / 2; + if(target.marker.color) optsOut.colors = target.marker.color; + if(target.marker.opacity !== undefined) optsOut.opacity = target.marker.opacity; + } + + return optsOut; +} + +function convertTextSelection(trace, target) { + var optsOut = {}; + + if(!target) return optsOut; + + if(target.textfont) { + var optsIn = { + opacity: 1, + text: trace.text, + textposition: trace.textposition, + textfont: Lib.extendFlat({}, trace.textfont) + }; + if(target.textfont) { + Lib.extendFlat(optsIn.textfont, target.textfont); + } + optsOut = convertTextStyle(optsIn); + } + + return optsOut; +} + +function convertErrorBarStyle(trace, target) { + var optsOut = { + capSize: target.width * 2, + lineWidth: target.thickness, + color: target.color + }; + + if(target.copy_ystyle) { + optsOut = trace.error_y; + } + + return optsOut; +} + +var SYMBOL_SDF_SIZE = constants.SYMBOL_SDF_SIZE; +var SYMBOL_SIZE = constants.SYMBOL_SIZE; +var SYMBOL_STROKE = constants.SYMBOL_STROKE; +var SYMBOL_SDF = {}; +var SYMBOL_SVG_CIRCLE = Drawing.symbolFuncs[0](SYMBOL_SIZE * 0.05); + +function getSymbolSdf(symbol) { + if(symbol === 'circle') return null; + + var symbolPath, symbolSdf; + var symbolNumber = Drawing.symbolNumber(symbol); + var symbolFunc = Drawing.symbolFuncs[symbolNumber % 100]; + var symbolNoDot = !!Drawing.symbolNoDot[symbolNumber % 100]; + var symbolNoFill = !!Drawing.symbolNoFill[symbolNumber % 100]; + + var isDot = constants.DOT_RE.test(symbol); + + // get symbol sdf from cache or generate it + if(SYMBOL_SDF[symbol]) return SYMBOL_SDF[symbol]; + + if(isDot && !symbolNoDot) { + symbolPath = symbolFunc(SYMBOL_SIZE * 1.1) + SYMBOL_SVG_CIRCLE; + } + else { + symbolPath = symbolFunc(SYMBOL_SIZE); + } + + symbolSdf = svgSdf(symbolPath, { + w: SYMBOL_SDF_SIZE, + h: SYMBOL_SDF_SIZE, + viewBox: [-SYMBOL_SIZE, -SYMBOL_SIZE, SYMBOL_SIZE, SYMBOL_SIZE], + stroke: symbolNoFill ? SYMBOL_STROKE : -SYMBOL_STROKE + }); + SYMBOL_SDF[symbol] = symbolSdf; + + return symbolSdf || null; +} + +function convertLinePositions(gd, trace, positions) { + var len = positions.length; + var count = len / 2; + var linePositions; + var i; + + if(subTypes.hasLines(trace) && count) { + if(trace.line.shape === 'hv') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) { + linePositions.push(NaN, NaN, NaN, NaN); + } else { + linePositions.push(positions[i * 2], positions[i * 2 + 1]); + if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) { + linePositions.push(positions[i * 2 + 2], positions[i * 2 + 1]); + } else { + linePositions.push(NaN, NaN); + } + } + } + linePositions.push(positions[len - 2], positions[len - 1]); + } else if(trace.line.shape === 'hvh') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { + if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { + linePositions.push(positions[i * 2], positions[i * 2 + 1]); + } else { + linePositions.push(NaN, NaN); + } + linePositions.push(NaN, NaN); + } + else { + var midPtX = (positions[i * 2] + positions[i * 2 + 2]) / 2; + linePositions.push( + positions[i * 2], + positions[i * 2 + 1], + midPtX, + positions[i * 2 + 1], + midPtX, + positions[i * 2 + 3] + ); + } + } + linePositions.push(positions[len - 2], positions[len - 1]); + } else if(trace.line.shape === 'vhv') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { + if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { + linePositions.push(positions[i * 2], positions[i * 2 + 1]); + } else { + linePositions.push(NaN, NaN); + } + linePositions.push(NaN, NaN); + } + else { + var midPtY = (positions[i * 2 + 1] + positions[i * 2 + 3]) / 2; + linePositions.push( + positions[i * 2], + positions[i * 2 + 1], + positions[i * 2], + midPtY, + positions[i * 2 + 2], + midPtY + ); + } + } + linePositions.push(positions[len - 2], positions[len - 1]); + } else if(trace.line.shape === 'vh') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) { + linePositions.push(NaN, NaN, NaN, NaN); + } + else { + linePositions.push(positions[i * 2], positions[i * 2 + 1]); + if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) { + linePositions.push(positions[i * 2], positions[i * 2 + 3]); + } else { + linePositions.push(NaN, NaN); + } + } + } + linePositions.push(positions[len - 2], positions[len - 1]); + } else { + linePositions = positions; + } + } + + // If we have data with gaps, we ought to use rect joins + // FIXME: get rid of this + var hasNaN = false; + for(i = 0; i < linePositions.length; i++) { + if(isNaN(linePositions[i])) { + hasNaN = true; + break; + } + } + + var join = (hasNaN || linePositions.length > constants.TOO_MANY_POINTS) ? 'rect' : + subTypes.hasMarkers(trace) ? 'rect' : 'round'; + + // fill gaps + if(hasNaN && trace.connectgaps) { + var lastX = linePositions[0]; + var lastY = linePositions[1]; + + for(i = 0; i < linePositions.length; i += 2) { + if(isNaN(linePositions[i]) || isNaN(linePositions[i + 1])) { + linePositions[i] = lastX; + linePositions[i + 1] = lastY; + } + else { + lastX = linePositions[i]; + lastY = linePositions[i + 1]; + } + } + } + + return { + join: join, + positions: linePositions + }; +} + +function convertErrorBarPositions(gd, trace, positions, x, y) { + var makeComputeError = Registry.getComponentMethod('errorbars', 'makeComputeError'); + var xa = AxisIDs.getFromId(gd, trace.xaxis); + var ya = AxisIDs.getFromId(gd, trace.yaxis); + var count = positions.length / 2; + var out = {}; + + function convertOneAxis(coords, ax) { + var axLetter = ax._id.charAt(0); + var opts = trace['error_' + axLetter]; + + if(opts && opts.visible && (ax.type === 'linear' || ax.type === 'log')) { + var computeError = makeComputeError(opts); + var pOffset = {x: 0, y: 1}[axLetter]; + var eOffset = {x: [0, 1, 2, 3], y: [2, 3, 0, 1]}[axLetter]; + var errors = new Float64Array(4 * count); + var minShoe = Infinity; + var maxHat = -Infinity; + + for(var i = 0, j = 0; i < count; i++, j += 4) { + var dc = coords[i]; + + if(isNumeric(dc)) { + var dl = positions[i * 2 + pOffset]; + var vals = computeError(dc, i); + var lv = vals[0]; + var hv = vals[1]; + + if(isNumeric(lv) && isNumeric(hv)) { + var shoe = dc - lv; + var hat = dc + hv; + + errors[j + eOffset[0]] = dl - ax.c2l(shoe); + errors[j + eOffset[1]] = ax.c2l(hat) - dl; + errors[j + eOffset[2]] = 0; + errors[j + eOffset[3]] = 0; + + minShoe = Math.min(minShoe, dc - lv); + maxHat = Math.max(maxHat, dc + hv); + } + } + } + + out[axLetter] = { + positions: positions, + errors: errors, + _bnds: [minShoe, maxHat] + }; + } + } + + convertOneAxis(x, xa); + convertOneAxis(y, ya); + return out; +} + +function convertTextPosition(gd, trace, textOpts, markerOpts) { + var count = trace._length; + var out = {}; + var i; + + // corresponds to textPointPosition from component.drawing + if(subTypes.hasMarkers(trace)) { + var fontOpts = textOpts.font; + var align = textOpts.align; + var baseline = textOpts.baseline; + out.offset = new Array(count); + + for(i = 0; i < count; i++) { + var ms = markerOpts.sizes ? markerOpts.sizes[i] : markerOpts.size; + var fs = Array.isArray(fontOpts) ? fontOpts[i].size : fontOpts.size; + + var a = Array.isArray(align) ? + (align.length > 1 ? align[i] : align[0]) : + align; + var b = Array.isArray(baseline) ? + (baseline.length > 1 ? baseline[i] : baseline[0]) : + baseline; + + var hSign = TEXTOFFSETSIGN[a]; + var vSign = TEXTOFFSETSIGN[b]; + var xPad = ms ? ms / 0.8 + 1 : 0; + var yPad = -vSign * xPad - vSign * 0.5; + out.offset[i] = [hSign * xPad / fs, yPad / fs]; + } + } + + return out; +} + +module.exports = { + style: convertStyle, + + markerStyle: convertMarkerStyle, + markerSelection: convertMarkerSelection, + + linePositions: convertLinePositions, + errorBarPositions: convertErrorBarPositions, + textPosition: convertTextPosition +}; + +},{"../../components/drawing":595,"../../constants/interactions":672,"../../lib":696,"../../lib/gl_format_color":692,"../../plots/cartesian/axis_ids":747,"../../registry":827,"../scatter/make_bubble_size_func":1060,"../scatter/subtypes":1067,"./constants":1093,"color-normalize":108,"fast-isnumeric":214,"svg-path-sdf":512}],1095:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Registry = _dereq_('../../registry'); + +var attributes = _dereq_('./attributes'); +var constants = _dereq_('../scatter/constants'); +var subTypes = _dereq_('../scatter/subtypes'); +var handleXYDefaults = _dereq_('../scatter/xy_defaults'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var isOpen = traceIn.marker ? /-open/.test(traceIn.marker.symbol) : false; + var isBubble = subTypes.isBubble(traceIn); + + var len = handleXYDefaults(traceIn, traceOut, layout, coerce); + if(!len) { + traceOut.visible = false; + return; + } + var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; + + coerce('text'); + coerce('hovertext'); + coerce('mode', defaultMode); + + if(subTypes.hasLines(traceOut)) { + coerce('connectgaps'); + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('line.shape'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('marker.line.width', isOpen || isBubble ? 1 : 0); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + } + + var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'x', inherit: 'y'}); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../../registry":827,"../scatter/constants":1047,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"../scatter/xy_defaults":1069,"./attributes":1092}],1096:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var createScatter = _dereq_('regl-scatter2d'); +var createLine = _dereq_('regl-line2d'); +var createError = _dereq_('regl-error2d'); +var cluster = _dereq_('point-cluster'); +var arrayRange = _dereq_('array-range'); +var Text = _dereq_('gl-text'); + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); +var prepareRegl = _dereq_('../../lib/prepare_regl'); +var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); +var findExtremes = _dereq_('../../plots/cartesian/autorange').findExtremes; +var Color = _dereq_('../../components/color'); + +var subTypes = _dereq_('../scatter/subtypes'); +var scatterCalc = _dereq_('../scatter/calc'); +var calcMarkerSize = scatterCalc.calcMarkerSize; +var calcAxisExpansion = scatterCalc.calcAxisExpansion; +var setFirstScatter = scatterCalc.setFirstScatter; +var calcColorscales = _dereq_('../scatter/colorscale_calc'); +var linkTraces = _dereq_('../scatter/link_traces'); +var getTraceColor = _dereq_('../scatter/get_trace_color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); +var convert = _dereq_('./convert'); + +var BADNUM = _dereq_('../../constants/numerical').BADNUM; +var TOO_MANY_POINTS = _dereq_('./constants').TOO_MANY_POINTS; +var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; + +function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var xa = AxisIDs.getFromId(gd, trace.xaxis); + var ya = AxisIDs.getFromId(gd, trace.yaxis); + var subplot = fullLayout._plots[trace.xaxis + trace.yaxis]; + var len = trace._length; + var len2 = len * 2; + var stash = {}; + var i, xx, yy; + + var x = xa.makeCalcdata(trace, 'x'); + var y = ya.makeCalcdata(trace, 'y'); + + // we need hi-precision for scatter2d, + // regl-scatter2d uses NaNs for bad/missing values + var positions = new Array(len2); + for(i = 0; i < len; i++) { + xx = x[i]; + yy = y[i]; + positions[i * 2] = xx === BADNUM ? NaN : xx; + positions[i * 2 + 1] = yy === BADNUM ? NaN : yy; + } + + if(xa.type === 'log') { + for(i = 0; i < len2; i += 2) { + positions[i] = xa.c2l(positions[i]); + } + } + if(ya.type === 'log') { + for(i = 1; i < len2; i += 2) { + positions[i] = ya.c2l(positions[i]); + } + } + + // we don't build a tree for log axes since it takes long to convert log2px + // and it is also + if(xa.type !== 'log' && ya.type !== 'log') { + // FIXME: delegate this to webworker + stash.tree = cluster(positions); + } else { + var ids = stash.ids = new Array(len); + for(i = 0; i < len; i++) { + ids[i] = i; + } + } + + // create scene options and scene + calcColorscales(trace); + var opts = sceneOptions(gd, subplot, trace, positions, x, y); + var scene = sceneUpdate(gd, subplot); + + // Reuse SVG scatter axis expansion routine. + // For graphs with very large number of points and array marker.size, + // use average marker size instead to speed things up. + setFirstScatter(fullLayout, trace); + var ppad = len < TOO_MANY_POINTS ? + calcMarkerSize(trace, len) : + 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3)); + calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); + if(opts.errorX) expandForErrorBars(trace, xa, opts.errorX); + if(opts.errorY) expandForErrorBars(trace, ya, opts.errorY); + + // set flags to create scene renderers + if(opts.fill && !scene.fill2d) scene.fill2d = true; + if(opts.marker && !scene.scatter2d) scene.scatter2d = true; + if(opts.line && !scene.line2d) scene.line2d = true; + if((opts.errorX || opts.errorY) && !scene.error2d) scene.error2d = true; + if(opts.text && !scene.glText) scene.glText = true; + + // FIXME: organize it in a more appropriate manner, probably in sceneOptions + // put point-cluster instance for optimized regl calc + if(opts.marker && len >= TOO_MANY_POINTS) { + opts.marker.cluster = stash.tree; + } + + // save scene opts batch + scene.lineOptions.push(opts.line); + scene.errorXOptions.push(opts.errorX); + scene.errorYOptions.push(opts.errorY); + scene.fillOptions.push(opts.fill); + scene.markerOptions.push(opts.marker); + scene.markerSelectedOptions.push(opts.markerSel); + scene.markerUnselectedOptions.push(opts.markerUnsel); + scene.textOptions.push(opts.text); + scene.textSelectedOptions.push(opts.textSel); + scene.textUnselectedOptions.push(opts.textUnsel); + + // stash scene ref + stash._scene = scene; + stash.index = scene.count; + stash.x = x; + stash.y = y; + stash.positions = positions; + scene.count++; + + return [{x: false, y: false, t: stash, trace: trace}]; +} + +function expandForErrorBars(trace, ax, opts) { + var extremes = trace._extremes[ax._id]; + var errExt = findExtremes(ax, opts._bnds, {padded: true}); + extremes.min = extremes.min.concat(errExt.min); + extremes.max = extremes.max.concat(errExt.max); +} + +// create scene options +function sceneOptions(gd, subplot, trace, positions, x, y) { + var opts = convert.style(gd, trace); + + if(opts.marker) { + opts.marker.positions = positions; + } + + if(opts.line && positions.length > 1) { + Lib.extendFlat( + opts.line, + convert.linePositions(gd, trace, positions) + ); + } + + if(opts.errorX || opts.errorY) { + var errors = convert.errorBarPositions(gd, trace, positions, x, y); + + if(opts.errorX) { + Lib.extendFlat(opts.errorX, errors.x); + } + if(opts.errorY) { + Lib.extendFlat(opts.errorY, errors.y); + } + } + + if(opts.text) { + Lib.extendFlat( + opts.text, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.marker) + ); + Lib.extendFlat( + opts.textSel, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.markerSel) + ); + Lib.extendFlat( + opts.textUnsel, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.markerUnsel) + ); + } + + return opts; +} + + +// make sure scene exists on subplot, return it +function sceneUpdate(gd, subplot) { + var scene = subplot._scene; + + var resetOpts = { + // number of traces in subplot, since scene:subplot → 1:1 + count: 0, + // whether scene requires init hook in plot call (dirty plot call) + dirty: true, + // last used options + lineOptions: [], + fillOptions: [], + markerOptions: [], + markerSelectedOptions: [], + markerUnselectedOptions: [], + errorXOptions: [], + errorYOptions: [], + textOptions: [], + textSelectedOptions: [], + textUnselectedOptions: [] + }; + + var initOpts = { + selectBatch: null, + unselectBatch: null, + // regl- component stubs, initialized in dirty plot call + fill2d: false, + scatter2d: false, + error2d: false, + line2d: false, + glText: false, + select2d: null + }; + + if(!subplot._scene) { + scene = subplot._scene = {}; + + scene.init = function init() { + Lib.extendFlat(scene, initOpts, resetOpts); + }; + + scene.init(); + + // apply new option to all regl components (used on drag) + scene.update = function update(opt) { + var opts = Lib.repeat(opt, scene.count); + + if(scene.fill2d) scene.fill2d.update(opts); + if(scene.scatter2d) scene.scatter2d.update(opts); + if(scene.line2d) scene.line2d.update(opts); + if(scene.error2d) scene.error2d.update(opts.concat(opts)); + if(scene.select2d) scene.select2d.update(opts); + if(scene.glText) { + for(var i = 0; i < scene.count; i++) { + scene.glText[i].update(opt); + } + } + }; + + // draw traces in proper order + scene.draw = function draw() { + var count = scene.count; + var fill2d = scene.fill2d; + var error2d = scene.error2d; + var line2d = scene.line2d; + var scatter2d = scene.scatter2d; + var glText = scene.glText; + var select2d = scene.select2d; + var selectBatch = scene.selectBatch; + var unselectBatch = scene.unselectBatch; + + for(var i = 0; i < count; i++) { + if(fill2d && scene.fillOrder[i]) { + fill2d.draw(scene.fillOrder[i]); + } + if(line2d && scene.lineOptions[i]) { + line2d.draw(i); + } + if(error2d) { + if(scene.errorXOptions[i]) error2d.draw(i); + if(scene.errorYOptions[i]) error2d.draw(i + count); + } + if(scatter2d && scene.markerOptions[i] && (!selectBatch || !selectBatch[i])) { + scatter2d.draw(i); + } + if(glText[i] && scene.textOptions[i]) { + glText[i].render(); + } + } + + if(scatter2d && select2d && selectBatch) { + select2d.draw(selectBatch); + scatter2d.draw(unselectBatch); + } + + scene.dirty = false; + }; + + // remove scene resources + scene.destroy = function destroy() { + if(scene.fill2d && scene.fill2d.destroy) scene.fill2d.destroy(); + if(scene.scatter2d && scene.scatter2d.destroy) scene.scatter2d.destroy(); + if(scene.error2d && scene.error2d.destroy) scene.error2d.destroy(); + if(scene.line2d && scene.line2d.destroy) scene.line2d.destroy(); + if(scene.select2d && scene.select2d.destroy) scene.select2d.destroy(); + if(scene.glText) { + scene.glText.forEach(function(text) { + if(text.destroy) text.destroy(); + }); + } + + scene.lineOptions = null; + scene.fillOptions = null; + scene.markerOptions = null; + scene.markerSelectedOptions = null; + scene.markerUnselectedOptions = null; + scene.errorXOptions = null; + scene.errorYOptions = null; + scene.textOptions = null; + scene.textSelectedOptions = null; + scene.textUnselectedOptions = null; + + scene.selectBatch = null; + scene.unselectBatch = null; + + // we can't just delete _scene, because `destroy` is called in the + // middle of supplyDefaults, before relinkPrivateKeys which will put it back. + subplot._scene = null; + }; + } + + // In case if we have scene from the last calc - reset data + if(!scene.dirty) { + Lib.extendFlat(scene, resetOpts); + } + + return scene; +} + +function getViewport(fullLayout, xaxis, yaxis) { + var gs = fullLayout._size; + var width = fullLayout.width; + var height = fullLayout.height; + return [ + gs.l + xaxis.domain[0] * gs.w, + gs.b + yaxis.domain[0] * gs.h, + (width - gs.r) - (1 - xaxis.domain[1]) * gs.w, + (height - gs.t) - (1 - yaxis.domain[1]) * gs.h + ]; +} + +function plot(gd, subplot, cdata) { + if(!cdata.length) return; + + var fullLayout = gd._fullLayout; + var scene = subplot._scene; + var xaxis = subplot.xaxis; + var yaxis = subplot.yaxis; + var i, j; + + // we may have more subplots than initialized data due to Axes.getSubplots method + if(!scene) return; + + var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']); + if(!success) { + scene.init(); + return; + } + + var regl = fullLayout._glcanvas.data()[0].regl; + + // that is needed for fills + linkTraces(gd, subplot, cdata); + + if(scene.dirty) { + // make sure scenes are created + if(scene.error2d === true) { + scene.error2d = createError(regl); + } + if(scene.line2d === true) { + scene.line2d = createLine(regl); + } + if(scene.scatter2d === true) { + scene.scatter2d = createScatter(regl); + } + if(scene.fill2d === true) { + scene.fill2d = createLine(regl); + } + if(scene.glText === true) { + scene.glText = new Array(scene.count); + for(i = 0; i < scene.count; i++) { + scene.glText[i] = new Text(regl); + } + } + + // update main marker options + if(scene.glText) { + for(i = 0; i < scene.count; i++) { + scene.glText[i].update(scene.textOptions[i]); + } + } + if(scene.line2d) { + scene.line2d.update(scene.lineOptions); + scene.lineOptions = scene.lineOptions.map(function(lineOptions) { + if(lineOptions && lineOptions.positions) { + var srcPos = lineOptions.positions; + + var firstptdef = 0; + while(firstptdef < srcPos.length && (isNaN(srcPos[firstptdef]) || isNaN(srcPos[firstptdef + 1]))) { + firstptdef += 2; + } + var lastptdef = srcPos.length - 2; + while(lastptdef > firstptdef && (isNaN(srcPos[lastptdef]) || isNaN(srcPos[lastptdef + 1]))) { + lastptdef -= 2; + } + lineOptions.positions = srcPos.slice(firstptdef, lastptdef + 2); + } + return lineOptions; + }); + scene.line2d.update(scene.lineOptions); + } + if(scene.error2d) { + var errorBatch = (scene.errorXOptions || []).concat(scene.errorYOptions || []); + scene.error2d.update(errorBatch); + } + if(scene.scatter2d) { + scene.scatter2d.update(scene.markerOptions); + } + + // fill requires linked traces, so we generate it's positions here + scene.fillOrder = Lib.repeat(null, scene.count); + if(scene.fill2d) { + scene.fillOptions = scene.fillOptions.map(function(fillOptions, i) { + var cdscatter = cdata[i]; + if(!fillOptions || !cdscatter || !cdscatter[0] || !cdscatter[0].trace) return; + var cd = cdscatter[0]; + var trace = cd.trace; + var stash = cd.t; + var lineOptions = scene.lineOptions[i]; + var last, j; + + var fillData = []; + if(trace._ownfill) fillData.push(i); + if(trace._nexttrace) fillData.push(i + 1); + if(fillData.length) scene.fillOrder[i] = fillData; + + var pos = []; + var srcPos = (lineOptions && lineOptions.positions) || stash.positions; + var firstptdef, lastptdef; + + if(trace.fill === 'tozeroy') { + firstptdef = 0; + while(firstptdef < srcPos.length && isNaN(srcPos[firstptdef + 1])) { + firstptdef += 2; + } + lastptdef = srcPos.length - 2; + while(lastptdef > firstptdef && isNaN(srcPos[lastptdef + 1])) { + lastptdef -= 2; + } + if(srcPos[firstptdef + 1] !== 0) { + pos = [srcPos[firstptdef], 0]; + } + pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); + if(srcPos[lastptdef + 1] !== 0) { + pos = pos.concat([srcPos[lastptdef], 0]); + } + } + else if(trace.fill === 'tozerox') { + firstptdef = 0; + while(firstptdef < srcPos.length && isNaN(srcPos[firstptdef])) { + firstptdef += 2; + } + lastptdef = srcPos.length - 2; + while(lastptdef > firstptdef && isNaN(srcPos[lastptdef])) { + lastptdef -= 2; + } + if(srcPos[firstptdef] !== 0) { + pos = [0, srcPos[firstptdef + 1]]; + } + pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); + if(srcPos[lastptdef] !== 0) { + pos = pos.concat([ 0, srcPos[lastptdef + 1]]); + } + } + else if(trace.fill === 'toself' || trace.fill === 'tonext') { + pos = []; + last = 0; + for(j = 0; j < srcPos.length; j += 2) { + if(isNaN(srcPos[j]) || isNaN(srcPos[j + 1])) { + pos = pos.concat(srcPos.slice(last, j)); + pos.push(srcPos[last], srcPos[last + 1]); + last = j + 2; + } + } + pos = pos.concat(srcPos.slice(last)); + if(last) { + pos.push(srcPos[last], srcPos[last + 1]); + } + } + else { + var nextTrace = trace._nexttrace; + + if(nextTrace) { + var nextOptions = scene.lineOptions[i + 1]; + + if(nextOptions) { + var nextPos = nextOptions.positions; + if(trace.fill === 'tonexty') { + pos = srcPos.slice(); + + for(i = Math.floor(nextPos.length / 2); i--;) { + var xx = nextPos[i * 2], yy = nextPos[i * 2 + 1]; + if(isNaN(xx) || isNaN(yy)) continue; + pos.push(xx, yy); + } + fillOptions.fill = nextTrace.fillcolor; + } + } + } + } + + // detect prev trace positions to exclude from current fill + if(trace._prevtrace && trace._prevtrace.fill === 'tonext') { + var prevLinePos = scene.lineOptions[i - 1].positions; + + // FIXME: likely this logic should be tested better + var offset = pos.length / 2; + last = offset; + var hole = [last]; + for(j = 0; j < prevLinePos.length; j += 2) { + if(isNaN(prevLinePos[j]) || isNaN(prevLinePos[j + 1])) { + hole.push(j / 2 + offset + 1); + last = j + 2; + } + } + + pos = pos.concat(prevLinePos); + fillOptions.hole = hole; + } + fillOptions.fillmode = trace.fill; + fillOptions.opacity = trace.opacity; + fillOptions.positions = pos; + + return fillOptions; + }); + + scene.fill2d.update(scene.fillOptions); + } + } + + // form batch arrays, and check for selected points + scene.selectBatch = null; + scene.unselectBatch = null; + var dragmode = fullLayout.dragmode; + var selectMode = dragmode === 'lasso' || dragmode === 'select'; + var clickSelectEnabled = fullLayout.clickmode.indexOf('select') > -1; + + for(i = 0; i < cdata.length; i++) { + var cd0 = cdata[i][0]; + var trace = cd0.trace; + var stash = cd0.t; + var index = stash.index; + var len = trace._length; + var x = stash.x; + var y = stash.y; + + if(trace.selectedpoints || selectMode || clickSelectEnabled) { + if(!selectMode) selectMode = true; + + if(!scene.selectBatch) { + scene.selectBatch = []; + scene.unselectBatch = []; + } + + // regenerate scene batch, if traces number changed during selection + if(trace.selectedpoints) { + var selPts = scene.selectBatch[index] = Lib.selIndices2selPoints(trace); + + var selDict = {}; + for(j = 0; j < selPts.length; j++) { + selDict[selPts[j]] = 1; + } + var unselPts = []; + for(j = 0; j < len; j++) { + if(!selDict[j]) unselPts.push(j); + } + scene.unselectBatch[index] = unselPts; + } + + // precalculate px coords since we are not going to pan during select + // TODO, could do better here e.g. + // - spin that in a webworker + // - compute selection from polygons in data coordinates + // (maybe just for linear axes) + var xpx = stash.xpx = new Array(len); + var ypx = stash.ypx = new Array(len); + for(j = 0; j < len; j++) { + xpx[j] = xaxis.c2p(x[j]); + ypx[j] = yaxis.c2p(y[j]); + } + } else { + stash.xpx = stash.ypx = null; + } + } + + + if(selectMode) { + // create select2d + if(!scene.select2d) { + // create scatter instance by cloning scatter2d + scene.select2d = createScatter(fullLayout._glcanvas.data()[1].regl); + } + + if(scene.scatter2d && scene.selectBatch && scene.selectBatch.length) { + // update only traces with selection + scene.scatter2d.update(scene.markerUnselectedOptions.map(function(opts, i) { + return scene.selectBatch[i] ? opts : null; + })); + } + + if(scene.select2d) { + scene.select2d.update(scene.markerOptions); + scene.select2d.update(scene.markerSelectedOptions); + } + + if(scene.glText) { + cdata.forEach(function(cdscatter) { + if(cdscatter && cdscatter[0] && cdscatter[0].trace) { + styleTextSelection(cdscatter); + } + }); + } + } else { + if(scene.scatter2d) { + // reset scatter2d opts to base opts, + // thus unsetting markerUnselectedOptions from selection + scene.scatter2d.update(scene.markerOptions); + } + } + + // provide viewport and range + var vpRange0 = { + viewport: getViewport(fullLayout, xaxis, yaxis), + // TODO do we need those fallbacks? + range: [ + (xaxis._rl || xaxis.range)[0], + (yaxis._rl || yaxis.range)[0], + (xaxis._rl || xaxis.range)[1], + (yaxis._rl || yaxis.range)[1] + ] + }; + var vpRange = Lib.repeat(vpRange0, scene.count); + + // upload viewport/range data to GPU + if(scene.fill2d) { + scene.fill2d.update(vpRange); + } + if(scene.line2d) { + scene.line2d.update(vpRange); + } + if(scene.error2d) { + scene.error2d.update(vpRange.concat(vpRange)); + } + if(scene.scatter2d) { + scene.scatter2d.update(vpRange); + } + if(scene.select2d) { + scene.select2d.update(vpRange); + } + if(scene.glText) { + scene.glText.forEach(function(text) { text.update(vpRange0); }); + } +} + + +function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var stash = cd[0].t; + var trace = cd[0].trace; + var xa = pointData.xa; + var ya = pointData.ya; + var x = stash.x; + var y = stash.y; + var xpx = xa.c2p(xval); + var ypx = ya.c2p(yval); + var maxDistance = pointData.distance; + var ids; + + // FIXME: make sure this is a proper way to calc search radius + if(stash.tree) { + var xl = xa.p2c(xpx - maxDistance); + var xr = xa.p2c(xpx + maxDistance); + var yl = ya.p2c(ypx - maxDistance); + var yr = ya.p2c(ypx + maxDistance); + + if(hovermode === 'x') { + ids = stash.tree.range( + Math.min(xl, xr), Math.min(ya._rl[0], ya._rl[1]), + Math.max(xl, xr), Math.max(ya._rl[0], ya._rl[1]) + ); + } + else { + ids = stash.tree.range( + Math.min(xl, xr), Math.min(yl, yr), + Math.max(xl, xr), Math.max(yl, yr) + ); + } + } + else if(stash.ids) { + ids = stash.ids; + } + else return [pointData]; + + // pick the id closest to the point + // note that point possibly may not be found + var id, ptx, pty, i, dx, dy, dist, dxy; + + var minDist = maxDistance; + if(hovermode === 'x') { + for(i = 0; i < ids.length; i++) { + ptx = x[ids[i]]; + dx = Math.abs(xa.c2p(ptx) - xpx); + if(dx < minDist) { + minDist = dx; + dy = ya.c2p(y[ids[i]]) - ypx; + dxy = Math.sqrt(dx * dx + dy * dy); + id = ids[i]; + } + } + } + else { + for(i = 0; i < ids.length; i++) { + ptx = x[ids[i]]; + pty = y[ids[i]]; + dx = xa.c2p(ptx) - xpx; + dy = ya.c2p(pty) - ypx; + + dist = Math.sqrt(dx * dx + dy * dy); + if(dist < minDist) { + minDist = dxy = dist; + id = ids[i]; + } + } + } + + pointData.index = id; + pointData.distance = minDist; + pointData.dxy = dxy; + + if(id === undefined) return [pointData]; + + calcHover(pointData, x, y, trace); + + return [pointData]; +} + + +function calcHover(pointData, x, y, trace) { + var xa = pointData.xa; + var ya = pointData.ya; + var minDist = pointData.distance; + var dxy = pointData.dxy; + var id = pointData.index; + + // the closest data point + var di = { + pointNumber: id, + x: x[id], + y: y[id] + }; + + // that is single-item arrays_to_calcdata excerpt, since we are doing it for a single point and we don't have to do it beforehead for 1e6 points + di.tx = Array.isArray(trace.text) ? trace.text[id] : trace.text; + di.htx = Array.isArray(trace.hovertext) ? trace.hovertext[id] : trace.hovertext; + di.data = Array.isArray(trace.customdata) ? trace.customdata[id] : trace.customdata; + di.tp = Array.isArray(trace.textposition) ? trace.textposition[id] : trace.textposition; + + var font = trace.textfont; + if(font) { + di.ts = Array.isArray(font.size) ? font.size[id] : font.size; + di.tc = Array.isArray(font.color) ? font.color[id] : font.color; + di.tf = Array.isArray(font.family) ? font.family[id] : font.family; + } + + var marker = trace.marker; + if(marker) { + di.ms = Lib.isArrayOrTypedArray(marker.size) ? marker.size[id] : marker.size; + di.mo = Lib.isArrayOrTypedArray(marker.opacity) ? marker.opacity[id] : marker.opacity; + di.mx = Array.isArray(marker.symbol) ? marker.symbol[id] : marker.symbol; + di.mc = Lib.isArrayOrTypedArray(marker.color) ? marker.color[id] : marker.color; + } + + var line = marker && marker.line; + if(line) { + di.mlc = Array.isArray(line.color) ? line.color[id] : line.color; + di.mlw = Lib.isArrayOrTypedArray(line.width) ? line.width[id] : line.width; + } + + var grad = marker && marker.gradient; + if(grad && grad.type !== 'none') { + di.mgt = Array.isArray(grad.type) ? grad.type[id] : grad.type; + di.mgc = Array.isArray(grad.color) ? grad.color[id] : grad.color; + } + + var xp = xa.c2p(di.x, true); + var yp = ya.c2p(di.y, true); + var rad = di.mrc || 1; + + var hoverlabel = trace.hoverlabel; + + if(hoverlabel) { + di.hbg = Array.isArray(hoverlabel.bgcolor) ? hoverlabel.bgcolor[id] : hoverlabel.bgcolor; + di.hbc = Array.isArray(hoverlabel.bordercolor) ? hoverlabel.bordercolor[id] : hoverlabel.bordercolor; + di.hts = Array.isArray(hoverlabel.font.size) ? hoverlabel.font.size[id] : hoverlabel.font.size; + di.htc = Array.isArray(hoverlabel.font.color) ? hoverlabel.font.color[id] : hoverlabel.font.color; + di.htf = Array.isArray(hoverlabel.font.family) ? hoverlabel.font.family[id] : hoverlabel.font.family; + di.hnl = Array.isArray(hoverlabel.namelength) ? hoverlabel.namelength[id] : hoverlabel.namelength; + } + var hoverinfo = trace.hoverinfo; + if(hoverinfo) { + di.hi = Array.isArray(hoverinfo) ? hoverinfo[id] : hoverinfo; + } + + var fakeCd = {}; + fakeCd[pointData.index] = di; + + Lib.extendFlat(pointData, { + color: getTraceColor(trace, di), + + x0: xp - rad, + x1: xp + rad, + xLabelVal: di.x, + + y0: yp - rad, + y1: yp + rad, + yLabelVal: di.y, + + cd: fakeCd, + distance: minDist, + spikeDistance: dxy + }); + + if(di.htx) pointData.text = di.htx; + else if(di.tx) pointData.text = di.tx; + else if(trace.text) pointData.text = trace.text; + + fillHoverText(di, trace, pointData); + Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData); + + return pointData; +} + + +function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var selection = []; + var trace = cd[0].trace; + var stash = cd[0].t; + var len = trace._length; + var x = stash.x; + var y = stash.y; + var scene = stash._scene; + + if(!scene) return selection; + + var hasText = subTypes.hasText(trace); + var hasMarkers = subTypes.hasMarkers(trace); + var hasOnlyLines = !hasMarkers && !hasText; + if(trace.visible !== true || hasOnlyLines) return selection; + + // degenerate polygon does not enable selection + // filter out points by visible scatter ones + var els = null; + var unels = null; + // FIXME: clearing selection does not work here + var i; + if(selectionTester !== false && !selectionTester.degenerate) { + els = [], unels = []; + for(i = 0; i < len; i++) { + if(selectionTester.contains([stash.xpx[i], stash.ypx[i]], false, i, searchInfo)) { + els.push(i); + selection.push({ + pointNumber: i, + x: x[i], + y: y[i] + }); + } + else { + unels.push(i); + } + } + } else { + unels = arrayRange(len); + } + + // make sure selectBatch is created + if(!scene.selectBatch) { + scene.selectBatch = []; + scene.unselectBatch = []; + } + + if(!scene.selectBatch[stash.index]) { + // enter every trace select mode + for(i = 0; i < scene.count; i++) { + scene.selectBatch[i] = []; + scene.unselectBatch[i] = []; + } + // we should turn scatter2d into unselected once we have any points selected + if(hasMarkers) { + scene.scatter2d.update(scene.markerUnselectedOptions); + } + } + + scene.selectBatch[stash.index] = els; + scene.unselectBatch[stash.index] = unels; + + // update text options + if(hasText) { + styleTextSelection(cd); + } + + return selection; +} + +function styleTextSelection(cd) { + var cd0 = cd[0]; + var trace = cd0.trace; + var stash = cd0.t; + var scene = stash._scene; + var index = stash.index; + var els = scene.selectBatch[index]; + var unels = scene.unselectBatch[index]; + var baseOpts = scene.textOptions[index]; + var selOpts = scene.textSelectedOptions[index] || {}; + var unselOpts = scene.textUnselectedOptions[index] || {}; + var opts = Lib.extendFlat({}, baseOpts); + var i, j; + + if(els && unels) { + var stc = selOpts.color; + var utc = unselOpts.color; + var base = baseOpts.color; + var hasArrayBase = Array.isArray(base); + opts.color = new Array(trace._length); + + for(i = 0; i < els.length; i++) { + j = els[i]; + opts.color[j] = stc || (hasArrayBase ? base[j] : base); + } + for(i = 0; i < unels.length; i++) { + j = unels[i]; + var basej = hasArrayBase ? base[j] : base; + opts.color[j] = utc ? utc : + stc ? basej : Color.addOpacity(basej, DESELECTDIM); + } + } + + scene.glText[index].update(opts); +} + +module.exports = { + moduleType: 'trace', + name: 'scattergl', + basePlotModule: _dereq_('../../plots/cartesian'), + categories: ['gl', 'regl', 'cartesian', 'symbols', 'errorBarsOK', 'showLegend', 'scatter-like'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + crossTraceDefaults: _dereq_('../scatter/cross_trace_defaults'), + colorbar: _dereq_('../scatter/marker_colorbar'), + calc: calc, + plot: plot, + hoverPoints: hoverPoints, + selectPoints: selectPoints, + + sceneUpdate: sceneUpdate, + calcHover: calcHover, + + meta: { + + + } +}; + +},{"../../components/color":570,"../../constants/interactions":672,"../../constants/numerical":673,"../../lib":696,"../../lib/prepare_regl":709,"../../plots/cartesian":756,"../../plots/cartesian/autorange":743,"../../plots/cartesian/axis_ids":747,"../../registry":827,"../scatter/calc":1044,"../scatter/colorscale_calc":1046,"../scatter/cross_trace_defaults":1049,"../scatter/fill_hover_text":1051,"../scatter/get_trace_color":1053,"../scatter/link_traces":1059,"../scatter/marker_colorbar":1061,"../scatter/subtypes":1067,"./attributes":1092,"./constants":1093,"./convert":1094,"./defaults":1095,"array-range":55,"gl-text":304,"point-cluster":452,"regl-error2d":473,"regl-line2d":474,"regl-scatter2d":475}],1097:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterGeoAttrs = _dereq_('../scattergeo/attributes'); +var scatterAttrs = _dereq_('../scatter/attributes'); +var mapboxAttrs = _dereq_('../../plots/mapbox/layout_attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +var lineAttrs = scatterGeoAttrs.line; +var markerAttrs = scatterGeoAttrs.marker; + +module.exports = overrideAll({ + lon: scatterGeoAttrs.lon, + lat: scatterGeoAttrs.lat, + + // locations + // locationmode + + mode: extendFlat({}, scatterAttrs.mode, { + dflt: 'markers', + + }), + + text: extendFlat({}, scatterAttrs.text, { + + }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + + }), + + line: { + color: lineAttrs.color, + width: lineAttrs.width + + // TODO + // dash: dash + }, + + connectgaps: scatterAttrs.connectgaps, + + marker: { + symbol: { + valType: 'string', + dflt: 'circle', + + arrayOk: true, + + }, + opacity: markerAttrs.opacity, + size: markerAttrs.size, + sizeref: markerAttrs.sizeref, + sizemin: markerAttrs.sizemin, + sizemode: markerAttrs.sizemode, + color: markerAttrs.color, + colorscale: markerAttrs.colorscale, + cauto: markerAttrs.cauto, + cmax: markerAttrs.cmax, + cmin: markerAttrs.cmin, + autocolorscale: markerAttrs.autocolorscale, + reversescale: markerAttrs.reversescale, + showscale: markerAttrs.showscale, + colorbar: colorbarAttrs, + + // line + }, + + fill: scatterGeoAttrs.fill, + fillcolor: scatterAttrs.fillcolor, + + textfont: mapboxAttrs.layers.symbol.textfont, + textposition: mapboxAttrs.layers.symbol.textposition, + + selected: { + marker: scatterAttrs.selected.marker + }, + unselected: { + marker: scatterAttrs.unselected.marker + }, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['lon', 'lat', 'text', 'name'] + }) +}, 'calc', 'nested'); + +},{"../../components/colorbar/attributes":571,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../../plots/mapbox/layout_attributes":804,"../scatter/attributes":1043,"../scattergeo/attributes":1083}],1098:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var Lib = _dereq_('../../lib'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; +var geoJsonUtils = _dereq_('../../lib/geojson_utils'); + +var Colorscale = _dereq_('../../components/colorscale'); +var Drawing = _dereq_('../../components/drawing'); +var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); +var subTypes = _dereq_('../scatter/subtypes'); +var convertTextOpts = _dereq_('../../plots/mapbox/convert_text_opts'); + +module.exports = function convert(calcTrace) { + var trace = calcTrace[0].trace; + + var isVisible = (trace.visible === true); + var hasFill = (trace.fill !== 'none'); + var hasLines = subTypes.hasLines(trace); + var hasMarkers = subTypes.hasMarkers(trace); + var hasText = subTypes.hasText(trace); + var hasCircles = (hasMarkers && trace.marker.symbol === 'circle'); + var hasSymbols = (hasMarkers && trace.marker.symbol !== 'circle'); + + var fill = initContainer(); + var line = initContainer(); + var circle = initContainer(); + var symbol = initContainer(); + + var opts = { + fill: fill, + line: line, + circle: circle, + symbol: symbol + }; + + // early return if not visible or placeholder + if(!isVisible) return opts; + + // fill layer and line layer use the same coords + var lineCoords; + if(hasFill || hasLines) { + lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace); + } + + if(hasFill) { + fill.geojson = geoJsonUtils.makePolygon(lineCoords); + fill.layout.visibility = 'visible'; + + Lib.extendFlat(fill.paint, { + 'fill-color': trace.fillcolor + }); + } + + if(hasLines) { + line.geojson = geoJsonUtils.makeLine(lineCoords); + line.layout.visibility = 'visible'; + + Lib.extendFlat(line.paint, { + 'line-width': trace.line.width, + 'line-color': trace.line.color, + 'line-opacity': trace.opacity + }); + + // TODO convert line.dash into line-dasharray + } + + if(hasCircles) { + var circleOpts = makeCircleOpts(calcTrace); + circle.geojson = circleOpts.geojson; + circle.layout.visibility = 'visible'; + + Lib.extendFlat(circle.paint, { + 'circle-color': circleOpts.mcc, + 'circle-radius': circleOpts.mrc, + 'circle-opacity': circleOpts.mo + }); + } + + if(hasSymbols || hasText) { + symbol.geojson = makeSymbolGeoJSON(calcTrace); + + Lib.extendFlat(symbol.layout, { + visibility: 'visible', + 'icon-image': '{symbol}-15', + 'text-field': '{text}' + }); + + if(hasSymbols) { + Lib.extendFlat(symbol.layout, { + 'icon-size': trace.marker.size / 10 + }); + + Lib.extendFlat(symbol.paint, { + 'icon-opacity': trace.opacity * trace.marker.opacity, + + // TODO does not work ?? + 'icon-color': trace.marker.color + }); + } + + if(hasText) { + var iconSize = (trace.marker || {}).size, + textOpts = convertTextOpts(trace.textposition, iconSize); + + // all data-driven below !! + + Lib.extendFlat(symbol.layout, { + 'text-size': trace.textfont.size, + 'text-anchor': textOpts.anchor, + 'text-offset': textOpts.offset + + // TODO font family + // 'text-font': symbol.textfont.family.split(', '), + }); + + Lib.extendFlat(symbol.paint, { + 'text-color': trace.textfont.color, + 'text-opacity': trace.opacity + }); + } + } + + return opts; +}; + +function initContainer() { + return { + geojson: geoJsonUtils.makeBlank(), + layout: { visibility: 'none' }, + paint: {} + }; +} + +function makeCircleOpts(calcTrace) { + var trace = calcTrace[0].trace; + var marker = trace.marker; + var selectedpoints = trace.selectedpoints; + var arrayColor = Lib.isArrayOrTypedArray(marker.color); + var arraySize = Lib.isArrayOrTypedArray(marker.size); + var arrayOpacity = Lib.isArrayOrTypedArray(marker.opacity); + var i; + + function addTraceOpacity(o) { return trace.opacity * o; } + + function size2radius(s) { return s / 2; } + + var colorFn; + if(arrayColor) { + if(Colorscale.hasColorscale(trace, 'marker')) { + colorFn = Colorscale.makeColorScaleFunc( + Colorscale.extractScale(marker.colorscale, marker.cmin, marker.cmax) + ); + } else { + colorFn = Lib.identity; + } + } + + var sizeFn; + if(arraySize) { + sizeFn = makeBubbleSizeFn(trace); + } + + var opacityFn; + if(arrayOpacity) { + opacityFn = function(mo) { + var mo2 = isNumeric(mo) ? +Lib.constrain(mo, 0, 1) : 0; + return addTraceOpacity(mo2); + }; + } + + var features = []; + for(i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + var lonlat = calcPt.lonlat; + + if(isBADNUM(lonlat)) continue; + + var props = {}; + if(colorFn) props.mcc = calcPt.mcc = colorFn(calcPt.mc); + if(sizeFn) props.mrc = calcPt.mrc = sizeFn(calcPt.ms); + if(opacityFn) props.mo = opacityFn(calcPt.mo); + if(selectedpoints) props.selected = calcPt.selected || 0; + + features.push({ + type: 'Feature', + geometry: {type: 'Point', coordinates: lonlat}, + properties: props + }); + } + + var fns; + if(selectedpoints) { + fns = Drawing.makeSelectedPointStyleFns(trace); + + for(i = 0; i < features.length; i++) { + var d = features[i].properties; + + if(fns.selectedOpacityFn) { + d.mo = addTraceOpacity(fns.selectedOpacityFn(d)); + } + if(fns.selectedColorFn) { + d.mcc = fns.selectedColorFn(d); + } + if(fns.selectedSizeFn) { + d.mrc = fns.selectedSizeFn(d); + } + } + } + + return { + geojson: {type: 'FeatureCollection', features: features}, + mcc: arrayColor || (fns && fns.selectedColorFn) ? + {type: 'identity', property: 'mcc'} : + marker.color, + mrc: arraySize || (fns && fns.selectedSizeFn) ? + {type: 'identity', property: 'mrc'} : + size2radius(marker.size), + mo: arrayOpacity || (fns && fns.selectedOpacityFn) ? + {type: 'identity', property: 'mo'} : + addTraceOpacity(marker.opacity) + }; +} + +function makeSymbolGeoJSON(calcTrace) { + var trace = calcTrace[0].trace; + + var marker = trace.marker || {}, + symbol = marker.symbol, + text = trace.text; + + var fillSymbol = (symbol !== 'circle') ? + getFillFunc(symbol) : + blankFillFunc; + + var fillText = subTypes.hasText(trace) ? + getFillFunc(text) : + blankFillFunc; + + var features = []; + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + + if(isBADNUM(calcPt.lonlat)) continue; + + features.push({ + type: 'Feature', + geometry: { + type: 'Point', + coordinates: calcPt.lonlat + }, + properties: { + symbol: fillSymbol(calcPt.mx), + text: fillText(calcPt.tx) + } + }); + } + + return { + type: 'FeatureCollection', + features: features + }; +} + +function getFillFunc(attr) { + if(Lib.isArrayOrTypedArray(attr)) { + return function(v) { return v; }; + } + else if(attr) { + return function() { return attr; }; + } + else { + return blankFillFunc; + } +} + +function blankFillFunc() { return ''; } + +// only need to check lon (OR lat) +function isBADNUM(lonlat) { + return lonlat[0] === BADNUM; +} + +},{"../../components/colorscale":585,"../../components/drawing":595,"../../constants/numerical":673,"../../lib":696,"../../lib/geojson_utils":689,"../../plots/mapbox/convert_text_opts":801,"../scatter/make_bubble_size_func":1060,"../scatter/subtypes":1067,"fast-isnumeric":214}],1099:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleLonLatDefaults(traceIn, traceOut, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + coerce('hovertext'); + coerce('mode'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noDash: true}); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noLine: true}); + + // array marker.size and marker.color are only supported with circles + var marker = traceOut.marker; + if(marker.symbol !== 'circle') { + if(Lib.isArrayOrTypedArray(marker.size)) marker.size = marker.size[0]; + if(Lib.isArrayOrTypedArray(marker.color)) marker.color = marker.color[0]; + } + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce, {noSelect: true}); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + } + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +function handleLonLatDefaults(traceIn, traceOut, coerce) { + var lon = coerce('lon') || []; + var lat = coerce('lat') || []; + var len = Math.min(lon.length, lat.length); + traceOut._length = len; + + return len; +} + +},{"../../lib":696,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1097}],1100:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = function eventData(out, pt) { + out.lon = pt.lon; + out.lat = pt.lat; + + return out; +}; + +},{}],1101:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = _dereq_('../../components/fx'); +var Lib = _dereq_('../../lib'); +var getTraceColor = _dereq_('../scatter/get_trace_color'); +var fillHoverText = _dereq_('../scatter/fill_hover_text'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function hoverPoints(pointData, xval, yval) { + var cd = pointData.cd; + var trace = cd[0].trace; + var xa = pointData.xa; + var ya = pointData.ya; + var subplot = pointData.subplot; + + // compute winding number about [-180, 180] globe + var winding = (xval >= 0) ? + Math.floor((xval + 180) / 360) : + Math.ceil((xval - 180) / 360); + + // shift longitude to [-180, 180] to determine closest point + var lonShift = winding * 360; + var xval2 = xval - lonShift; + + function distFn(d) { + var lonlat = d.lonlat; + if(lonlat[0] === BADNUM) return Infinity; + + var lon = Lib.modHalf(lonlat[0], 360); + var lat = lonlat[1]; + var pt = subplot.project([lon, lat]); + var dx = pt.x - xa.c2p([xval2, lat]); + var dy = pt.y - ya.c2p([lon, yval]); + var rad = Math.max(3, d.mrc || 0); + + return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); + } + + Fx.getClosest(cd, distFn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index === false) return; + + var di = cd[pointData.index]; + var lonlat = di.lonlat; + var lonlatShifted = [Lib.modHalf(lonlat[0], 360) + lonShift, lonlat[1]]; + + // shift labels back to original winded globe + var xc = xa.c2p(lonlatShifted); + var yc = ya.c2p(lonlatShifted); + var rad = di.mrc || 1; + + pointData.x0 = xc - rad; + pointData.x1 = xc + rad; + pointData.y0 = yc - rad; + pointData.y1 = yc + rad; + + pointData.color = getTraceColor(trace, di); + pointData.extraText = getExtraText(trace, di, cd[0].t.labels); + + return [pointData]; +}; + +function getExtraText(trace, di, labels) { + var hoverinfo = di.hi || trace.hoverinfo; + var parts = hoverinfo.split('+'); + var isAll = parts.indexOf('all') !== -1; + var hasLon = parts.indexOf('lon') !== -1; + var hasLat = parts.indexOf('lat') !== -1; + var lonlat = di.lonlat; + var text = []; + + // TODO should we use a mock axis to format hover? + // If so, we'll need to make precision be zoom-level dependent + function format(v) { + return v + '\u00B0'; + } + + if(isAll || (hasLon && hasLat)) { + text.push('(' + format(lonlat[0]) + ', ' + format(lonlat[1]) + ')'); + } else if(hasLon) { + text.push(labels.lon + format(lonlat[0])); + } else if(hasLat) { + text.push(labels.lat + format(lonlat[1])); + } + + if(isAll || parts.indexOf('text') !== -1) { + fillHoverText(di, trace, text); + } + + return text.join('
'); +} + +},{"../../components/fx":612,"../../constants/numerical":673,"../../lib":696,"../scatter/fill_hover_text":1051,"../scatter/get_trace_color":1053}],1102:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +var ScatterMapbox = {}; + +ScatterMapbox.attributes = _dereq_('./attributes'); +ScatterMapbox.supplyDefaults = _dereq_('./defaults'); +ScatterMapbox.colorbar = _dereq_('../scatter/marker_colorbar'); +ScatterMapbox.calc = _dereq_('../scattergeo/calc'); +ScatterMapbox.plot = _dereq_('./plot'); +ScatterMapbox.hoverPoints = _dereq_('./hover'); +ScatterMapbox.eventData = _dereq_('./event_data'); +ScatterMapbox.selectPoints = _dereq_('./select'); + +ScatterMapbox.style = function(_, cd) { + if(cd) { + var trace = cd[0].trace; + trace._glTrace.update(cd); + } +}; + +ScatterMapbox.moduleType = 'trace'; +ScatterMapbox.name = 'scattermapbox'; +ScatterMapbox.basePlotModule = _dereq_('../../plots/mapbox'); +ScatterMapbox.categories = ['mapbox', 'gl', 'symbols', 'showLegend', 'scatterlike']; +ScatterMapbox.meta = { + + +}; + +module.exports = ScatterMapbox; + +},{"../../plots/mapbox":802,"../scatter/marker_colorbar":1061,"../scattergeo/calc":1084,"./attributes":1097,"./defaults":1099,"./event_data":1100,"./hover":1101,"./plot":1103,"./select":1104}],1103:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var convert = _dereq_('./convert'); + +function ScatterMapbox(subplot, uid) { + this.subplot = subplot; + this.uid = uid; + + this.sourceIds = { + fill: uid + '-source-fill', + line: uid + '-source-line', + circle: uid + '-source-circle', + symbol: uid + '-source-symbol' + }; + + this.layerIds = { + fill: uid + '-layer-fill', + line: uid + '-layer-line', + circle: uid + '-layer-circle', + symbol: uid + '-layer-symbol' + }; + + this.order = ['fill', 'line', 'circle', 'symbol']; + + // We could merge the 'fill' source with the 'line' source and + // the 'circle' source with the 'symbol' source if ever having + // for up-to 4 sources per 'scattermapbox' traces becomes a problem. +} + +var proto = ScatterMapbox.prototype; + +proto.addSource = function(k, opts) { + this.subplot.map.addSource(this.sourceIds[k], { + type: 'geojson', + data: opts.geojson + }); +}; + +proto.setSourceData = function(k, opts) { + this.subplot.map + .getSource(this.sourceIds[k]) + .setData(opts.geojson); +}; + +proto.addLayer = function(k, opts) { + this.subplot.map.addLayer({ + type: k, + id: this.layerIds[k], + source: this.sourceIds[k], + layout: opts.layout, + paint: opts.paint + }); +}; + +proto.update = function update(calcTrace) { + var subplot = this.subplot; + var optsAll = convert(calcTrace); + + for(var i = 0; i < this.order.length; i++) { + var k = this.order[i]; + var opts = optsAll[k]; + + subplot.setOptions(this.layerIds[k], 'setLayoutProperty', opts.layout); + + if(opts.layout.visibility === 'visible') { + this.setSourceData(k, opts); + subplot.setOptions(this.layerIds[k], 'setPaintProperty', opts.paint); + } + } + + // link ref for quick update during selections + calcTrace[0].trace._glTrace = this; +}; + +proto.dispose = function dispose() { + var map = this.subplot.map; + + for(var i = 0; i < this.order.length; i++) { + var k = this.order[i]; + map.removeLayer(this.layerIds[k]); + map.removeSource(this.sourceIds[k]); + } +}; + +module.exports = function createScatterMapbox(subplot, calcTrace) { + var trace = calcTrace[0].trace; + var scatterMapbox = new ScatterMapbox(subplot, trace.uid); + var optsAll = convert(calcTrace); + + for(var i = 0; i < scatterMapbox.order.length; i++) { + var k = scatterMapbox.order[i]; + var opts = optsAll[k]; + + scatterMapbox.addSource(k, opts); + scatterMapbox.addLayer(k, opts); + } + + // link ref for quick update during selections + calcTrace[0].trace._glTrace = scatterMapbox; + + return scatterMapbox; +}; + +},{"./convert":1098}],1104:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var subtypes = _dereq_('../scatter/subtypes'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var trace = cd[0].trace; + var i; + + if(!subtypes.hasMarkers(trace)) return []; + + if(selectionTester === false) { + for(i = 0; i < cd.length; i++) { + cd[i].selected = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + var di = cd[i]; + var lonlat = di.lonlat; + + if(lonlat[0] !== BADNUM) { + var lonlat2 = [Lib.modHalf(lonlat[0], 360), lonlat[1]]; + var xy = [xa.c2p(lonlat2), ya.c2p(lonlat2)]; + + if(selectionTester.contains(xy, null, i, searchInfo)) { + selection.push({ + pointNumber: i, + lon: lonlat[0], + lat: lonlat[1] + }); + di.selected = 1; + } else { + di.selected = 0; + } + } + } + } + + return selection; +}; + +},{"../../constants/numerical":673,"../../lib":696,"../scatter/subtypes":1067}],1105:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var scatterAttrs = _dereq_('../scatter/attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var lineAttrs = scatterAttrs.line; + +module.exports = { + mode: scatterAttrs.mode, + + r: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + + theta: { + valType: 'data_array', + editType: 'calc+clearAxisTypes', + + }, + + r0: { + valType: 'any', + dflt: 0, + + editType: 'calc+clearAxisTypes', + + }, + dr: { + valType: 'number', + dflt: 1, + + editType: 'calc', + + }, + + theta0: { + valType: 'any', + dflt: 0, + + editType: 'calc+clearAxisTypes', + + }, + dtheta: { + valType: 'number', + + editType: 'calc', + + }, + + thetaunit: { + valType: 'enumerated', + values: ['radians', 'degrees', 'gradians'], + dflt: 'degrees', + + editType: 'calc+clearAxisTypes', + + }, + + text: scatterAttrs.text, + hovertext: scatterAttrs.hovertext, + + line: { + color: lineAttrs.color, + width: lineAttrs.width, + dash: lineAttrs.dash, + shape: extendFlat({}, lineAttrs.shape, { + values: ['linear', 'spline'] + }), + smoothing: lineAttrs.smoothing, + editType: 'calc' + }, + connectgaps: scatterAttrs.connectgaps, + + marker: scatterAttrs.marker, + cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, {dflt: false}), + + textposition: scatterAttrs.textposition, + textfont: scatterAttrs.textfont, + + fill: extendFlat({}, scatterAttrs.fill, { + values: ['none', 'toself', 'tonext'], + dflt: 'none', + + }), + fillcolor: scatterAttrs.fillcolor, + + // TODO error bars + // https://stackoverflow.com/a/26597487/4068492 + // error_x (error_r, error_theta) + // error_y + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['r', 'theta', 'text', 'name'] + }), + hoveron: scatterAttrs.hoveron, + + selected: scatterAttrs.selected, + unselected: scatterAttrs.unselected +}; + +},{"../../lib/extend":685,"../../plots/attributes":741,"../scatter/attributes":1043}],1106:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +var Axes = _dereq_('../../plots/cartesian/axes'); + +var calcColorscale = _dereq_('../scatter/colorscale_calc'); +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); +var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; + +module.exports = function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var subplotId = trace.subplot; + var radialAxis = fullLayout[subplotId].radialaxis; + var angularAxis = fullLayout[subplotId].angularaxis; + var rArray = radialAxis.makeCalcdata(trace, 'r'); + var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); + var len = trace._length; + var cd = new Array(len); + + for(var i = 0; i < len; i++) { + var r = rArray[i]; + var theta = thetaArray[i]; + var cdi = cd[i] = {}; + + if(isNumeric(r) && isNumeric(theta)) { + cdi.r = r; + cdi.theta = theta; + } else { + cdi.r = BADNUM; + } + } + + var ppad = calcMarkerSize(trace, len); + trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad}); + + calcColorscale(trace); + arraysToCalcdata(cd, trace); + calcSelection(cd, trace); + + return cd; +}; + +},{"../../constants/numerical":673,"../../plots/cartesian/axes":744,"../scatter/arrays_to_calcdata":1042,"../scatter/calc":1044,"../scatter/calc_selection":1045,"../scatter/colorscale_calc":1046,"fast-isnumeric":214}],1107:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); +var PTS_LINESONLY = _dereq_('../scatter/constants').PTS_LINESONLY; + +var attributes = _dereq_('./attributes'); + +function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('thetaunit'); + coerce('mode', len < PTS_LINESONLY ? 'lines+markers' : 'lines'); + coerce('text'); + coerce('hovertext'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + handleLineShapeDefaults(traceIn, traceOut, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + var dfltHoverOn = []; + + if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { + coerce('cliponaxis'); + coerce('marker.maxdisplayed'); + dfltHoverOn.push('points'); + } + + coerce('fill'); + + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + } + + if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { + dfltHoverOn.push('fills'); + } + coerce('hoveron', dfltHoverOn.join('+') || 'points'); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +} + +function handleRThetaDefaults(traceIn, traceOut, layout, coerce) { + var r = coerce('r'); + var theta = coerce('theta'); + var len; + + if(r) { + if(theta) { + len = Math.min(r.length, theta.length); + } else { + len = r.length; + coerce('theta0'); + coerce('dtheta'); + } + } else { + if(!theta) return 0; + len = traceOut.theta.length; + coerce('r0'); + coerce('dr'); + } + + traceOut._length = len; + return len; +} + +module.exports = { + handleRThetaDefaults: handleRThetaDefaults, + supplyDefaults: supplyDefaults +}; + +},{"../../lib":696,"../scatter/constants":1047,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/line_shape_defaults":1058,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1105}],1108:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterHover = _dereq_('../scatter/hover'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var Lib = _dereq_('../../lib'); + +function hoverPoints(pointData, xval, yval, hovermode) { + var scatterPointData = scatterHover(pointData, xval, yval, hovermode); + if(!scatterPointData || scatterPointData[0].index === false) return; + + var newPointData = scatterPointData[0]; + + // hovering on fill case + if(newPointData.index === undefined) { + return scatterPointData; + } + + var subplot = pointData.subplot; + var cdi = newPointData.cd[newPointData.index]; + var trace = newPointData.trace; + + if(!subplot.isPtInside(cdi)) return; + + newPointData.xLabelVal = undefined; + newPointData.yLabelVal = undefined; + makeHoverPointText(cdi, trace, subplot, newPointData); + + return scatterPointData; +} + +function makeHoverPointText(cdi, trace, subplot, pointData) { + var radialAxis = subplot.radialAxis; + var angularAxis = subplot.angularAxis; + var hoverinfo = cdi.hi || trace.hoverinfo; + var parts = hoverinfo.split('+'); + var text = []; + + radialAxis._hovertitle = 'r'; + angularAxis._hovertitle = 'θ'; + + function textPart(ax, val) { + text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text); + } + + if(parts.indexOf('all') !== -1) parts = ['r', 'theta', 'text']; + if(parts.indexOf('r') !== -1) { + textPart(radialAxis, radialAxis.c2l(cdi.r)); + } + if(parts.indexOf('theta') !== -1) { + var theta = cdi.theta; + textPart( + angularAxis, + angularAxis.thetaunit === 'degrees' ? Lib.rad2deg(theta) : theta + ); + } + if(parts.indexOf('text') !== -1 && pointData.text) { + text.push(pointData.text); + delete pointData.text; + } + + pointData.extraText = text.join('
'); +} + +module.exports = { + hoverPoints: hoverPoints, + makeHoverPointText: makeHoverPointText +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../scatter/hover":1054}],1109:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'scatterpolar', + basePlotModule: _dereq_('../../plots/polar'), + categories: ['polar', 'symbols', 'showLegend', 'scatter-like'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults').supplyDefaults, + colorbar: _dereq_('../scatter/marker_colorbar'), + calc: _dereq_('./calc'), + plot: _dereq_('./plot'), + style: _dereq_('../scatter/style').style, + hoverPoints: _dereq_('./hover').hoverPoints, + selectPoints: _dereq_('../scatter/select'), + + meta: { + + + } +}; + +},{"../../plots/polar":811,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1105,"./calc":1106,"./defaults":1107,"./hover":1108,"./plot":1110}],1110:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterPlot = _dereq_('../scatter/plot'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function plot(gd, subplot, moduleCalcData) { + var mlayer = subplot.layers.frontplot.select('g.scatterlayer'); + + var plotinfo = { + xaxis: subplot.xaxis, + yaxis: subplot.yaxis, + plot: subplot.framework, + layerClipId: subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null + }; + + var radialAxis = subplot.radialAxis; + var angularAxis = subplot.angularAxis; + + // convert: + // 'c' (r,theta) -> 'geometric' (r,theta) -> (x,y) + for(var i = 0; i < moduleCalcData.length; i++) { + var cdi = moduleCalcData[i]; + + for(var j = 0; j < cdi.length; j++) { + var cd = cdi[j]; + var r = cd.r; + + if(r === BADNUM) { + cd.x = cd.y = BADNUM; + } else { + var rg = radialAxis.c2g(r); + var thetag = angularAxis.c2g(cd.theta); + cd.x = rg * Math.cos(thetag); + cd.y = rg * Math.sin(thetag); + } + } + } + + scatterPlot(gd, plotinfo, moduleCalcData, mlayer); +}; + +},{"../../constants/numerical":673,"../scatter/plot":1063}],1111:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterPolarAttrs = _dereq_('../scatterpolar/attributes'); +var scatterGlAttrs = _dereq_('../scattergl/attributes'); + +module.exports = { + mode: scatterPolarAttrs.mode, + r: scatterPolarAttrs.r, + theta: scatterPolarAttrs.theta, + r0: scatterPolarAttrs.r0, + dr: scatterPolarAttrs.dr, + theta0: scatterPolarAttrs.theta0, + dtheta: scatterPolarAttrs.dtheta, + thetaunit: scatterPolarAttrs.thetaunit, + + text: scatterPolarAttrs.text, + hovertext: scatterPolarAttrs.hovertext, + + line: scatterGlAttrs.line, + connectgaps: scatterGlAttrs.connectgaps, + + marker: scatterGlAttrs.marker, + // no cliponaxis + + fill: scatterGlAttrs.fill, + fillcolor: scatterGlAttrs.fillcolor, + + textposition: scatterGlAttrs.textposition, + textfont: scatterGlAttrs.textfont, + + hoverinfo: scatterPolarAttrs.hoverinfo, + // no hoveron + + selected: scatterPolarAttrs.selected, + unselected: scatterPolarAttrs.unselected +}; + +},{"../scattergl/attributes":1092,"../scatterpolar/attributes":1105}],1112:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var subTypes = _dereq_('../scatter/subtypes'); +var handleRThetaDefaults = _dereq_('../scatterpolar/defaults').handleRThetaDefaults; +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); +var PTS_LINESONLY = _dereq_('../scatter/constants').PTS_LINESONLY; + +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('thetaunit'); + coerce('mode', len < PTS_LINESONLY ? 'lines+markers' : 'lines'); + coerce('text'); + coerce('hovertext'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + } + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../scatter/constants":1047,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"../scatterpolar/defaults":1107,"./attributes":1111}],1113:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var cluster = _dereq_('point-cluster'); +var isNumeric = _dereq_('fast-isnumeric'); + +var ScatterGl = _dereq_('../scattergl'); +var calcColorscales = _dereq_('../scatter/colorscale_calc'); +var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; +var convert = _dereq_('../scattergl/convert'); + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var makeHoverPointText = _dereq_('../scatterpolar/hover').makeHoverPointText; + +var TOO_MANY_POINTS = _dereq_('../scattergl/constants').TOO_MANY_POINTS; + +function calc(gd, trace) { + var fullLayout = gd._fullLayout; + var subplotId = trace.subplot; + var radialAxis = fullLayout[subplotId].radialaxis; + var angularAxis = fullLayout[subplotId].angularaxis; + var rArray = radialAxis.makeCalcdata(trace, 'r'); + var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); + var len = trace._length; + var stash = {}; + + if(len < rArray.length) rArray = rArray.slice(0, len); + if(len < thetaArray.length) thetaArray = thetaArray.slice(0, len); + + stash.r = rArray; + stash.theta = thetaArray; + + calcColorscales(trace); + + // only compute 'style' options in calc, as position options + // depend on the radial range and must be set in plot + var opts = stash.opts = convert.style(gd, trace); + + // For graphs with very large number of points and array marker.size, + // use average marker size instead to speed things up. + var ppad = len < TOO_MANY_POINTS ? + calcMarkerSize(trace, len) : + 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3)); + trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad}); + + return [{x: false, y: false, t: stash, trace: trace}]; +} + +function plot(gd, subplot, cdata) { + if(!cdata.length) return; + + var radialAxis = subplot.radialAxis; + var angularAxis = subplot.angularAxis; + var scene = ScatterGl.sceneUpdate(gd, subplot); + + cdata.forEach(function(cdscatter) { + if(!cdscatter || !cdscatter[0] || !cdscatter[0].trace) return; + var cd = cdscatter[0]; + var trace = cd.trace; + var stash = cd.t; + var len = trace._length; + var rArray = stash.r; + var thetaArray = stash.theta; + var opts = stash.opts; + var i; + + var subRArray = rArray.slice(); + var subThetaArray = thetaArray.slice(); + + // filter out by range + for(i = 0; i < rArray.length; i++) { + if(!subplot.isPtInside({r: rArray[i], theta: thetaArray[i]})) { + subRArray[i] = NaN; + subThetaArray[i] = NaN; + } + } + + var positions = new Array(len * 2); + var x = Array(len); + var y = Array(len); + + for(i = 0; i < len; i++) { + var r = subRArray[i]; + var xx, yy; + + if(isNumeric(r)) { + var rg = radialAxis.c2g(r); + var thetag = angularAxis.c2g(subThetaArray[i], trace.thetaunit); + xx = rg * Math.cos(thetag); + yy = rg * Math.sin(thetag); + } else { + xx = yy = NaN; + } + x[i] = positions[i * 2] = xx; + y[i] = positions[i * 2 + 1] = yy; + } + + stash.tree = cluster(positions); + + // FIXME: see scattergl.js#109 + if(opts.marker && len >= TOO_MANY_POINTS) { + opts.marker.cluster = stash.tree; + } + + if(opts.marker) { + opts.markerSel.positions = opts.markerUnsel.positions = opts.marker.positions = positions; + } + + if(opts.line && positions.length > 1) { + Lib.extendFlat( + opts.line, + convert.linePositions(gd, trace, positions) + ); + } + + if(opts.text) { + Lib.extendFlat( + opts.text, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.marker) + ); + Lib.extendFlat( + opts.textSel, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.markerSel) + ); + Lib.extendFlat( + opts.textUnsel, + {positions: positions}, + convert.textPosition(gd, trace, opts.text, opts.markerUnsel) + ); + } + + if(opts.fill && !scene.fill2d) scene.fill2d = true; + if(opts.marker && !scene.scatter2d) scene.scatter2d = true; + if(opts.line && !scene.line2d) scene.line2d = true; + if(opts.text && !scene.glText) scene.glText = true; + + scene.lineOptions.push(opts.line); + scene.fillOptions.push(opts.fill); + scene.markerOptions.push(opts.marker); + scene.markerSelectedOptions.push(opts.markerSel); + scene.markerUnselectedOptions.push(opts.markerUnsel); + scene.textOptions.push(opts.text); + scene.textSelectedOptions.push(opts.textSel); + scene.textUnselectedOptions.push(opts.textUnsel); + + stash.x = x; + stash.y = y; + stash.rawx = x; + stash.rawy = y; + stash.r = rArray; + stash.theta = thetaArray; + stash.positions = positions; + stash._scene = scene; + stash.index = scene.count; + scene.count++; + }); + + return ScatterGl.plot(gd, subplot, cdata); +} + +function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd; + var stash = cd[0].t; + var rArray = stash.r; + var thetaArray = stash.theta; + + var scatterPointData = ScatterGl.hoverPoints(pointData, xval, yval, hovermode); + if(!scatterPointData || scatterPointData[0].index === false) return; + + var newPointData = scatterPointData[0]; + + if(newPointData.index === undefined) { + return scatterPointData; + } + + var subplot = pointData.subplot; + var cdi = newPointData.cd[newPointData.index]; + var trace = newPointData.trace; + + // augment pointData with r/theta param + cdi.r = rArray[newPointData.index]; + cdi.theta = thetaArray[newPointData.index]; + + if(!subplot.isPtInside(cdi)) return; + + newPointData.xLabelVal = undefined; + newPointData.yLabelVal = undefined; + makeHoverPointText(cdi, trace, subplot, newPointData); + + return scatterPointData; +} + +module.exports = { + moduleType: 'trace', + name: 'scatterpolargl', + basePlotModule: _dereq_('../../plots/polar'), + categories: ['gl', 'regl', 'polar', 'symbols', 'showLegend', 'scatter-like'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + colorbar: _dereq_('../scatter/marker_colorbar'), + + calc: calc, + plot: plot, + hoverPoints: hoverPoints, + selectPoints: ScatterGl.selectPoints, + + meta: { + + + } +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../../plots/polar":811,"../scatter/calc":1044,"../scatter/colorscale_calc":1046,"../scatter/marker_colorbar":1061,"../scattergl":1096,"../scattergl/constants":1093,"../scattergl/convert":1094,"../scatterpolar/hover":1108,"./attributes":1111,"./defaults":1112,"fast-isnumeric":214,"point-cluster":452}],1114:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var plotAttrs = _dereq_('../../plots/attributes'); +var colorAttributes = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var dash = _dereq_('../../components/drawing/attributes').dash; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker, + scatterLineAttrs = scatterAttrs.line, + scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +module.exports = { + a: { + valType: 'data_array', + editType: 'calc', + + }, + b: { + valType: 'data_array', + editType: 'calc', + + }, + c: { + valType: 'data_array', + editType: 'calc', + + }, + sum: { + valType: 'number', + + dflt: 0, + min: 0, + editType: 'calc', + + }, + mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), + text: extendFlat({}, scatterAttrs.text, { + + }), + hovertext: extendFlat({}, scatterAttrs.hovertext, { + + }), + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + dash: dash, + shape: extendFlat({}, scatterLineAttrs.shape, + {values: ['linear', 'spline']}), + smoothing: scatterLineAttrs.smoothing, + editType: 'calc' + }, + connectgaps: scatterAttrs.connectgaps, + cliponaxis: scatterAttrs.cliponaxis, + fill: extendFlat({}, scatterAttrs.fill, { + values: ['none', 'toself', 'tonext'], + dflt: 'none', + + }), + fillcolor: scatterAttrs.fillcolor, + marker: extendFlat({ + symbol: scatterMarkerAttrs.symbol, + opacity: scatterMarkerAttrs.opacity, + maxdisplayed: scatterMarkerAttrs.maxdisplayed, + size: scatterMarkerAttrs.size, + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + line: extendFlat({ + width: scatterMarkerLineAttrs.width, + editType: 'calc' + }, + colorAttributes('marker.line') + ), + gradient: scatterMarkerAttrs.gradient, + editType: 'calc' + }, colorAttributes('marker'), { + colorbar: colorbarAttrs + }), + + textfont: scatterAttrs.textfont, + textposition: scatterAttrs.textposition, + + selected: scatterAttrs.selected, + unselected: scatterAttrs.unselected, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['a', 'b', 'c', 'text', 'name'] + }), + hoveron: scatterAttrs.hoveron, +}; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../components/drawing/attributes":594,"../../lib/extend":685,"../../plots/attributes":741,"../scatter/attributes":1043}],1115:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = _dereq_('fast-isnumeric'); + +var calcColorscale = _dereq_('../scatter/colorscale_calc'); +var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); +var calcSelection = _dereq_('../scatter/calc_selection'); +var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; + +var dataArrays = ['a', 'b', 'c']; +var arraysToFill = {a: ['b', 'c'], b: ['a', 'c'], c: ['a', 'b']}; + +module.exports = function calc(gd, trace) { + var ternary = gd._fullLayout[trace.subplot]; + var displaySum = ternary.sum; + var normSum = trace.sum || displaySum; + var arrays = {a: trace.a, b: trace.b, c: trace.c}; + + var i, j, dataArray, newArray, fillArray1, fillArray2; + + // fill in one missing component + for(i = 0; i < dataArrays.length; i++) { + dataArray = dataArrays[i]; + if(arrays[dataArray]) continue; + + fillArray1 = arrays[arraysToFill[dataArray][0]]; + fillArray2 = arrays[arraysToFill[dataArray][1]]; + newArray = new Array(fillArray1.length); + for(j = 0; j < fillArray1.length; j++) { + newArray[j] = normSum - fillArray1[j] - fillArray2[j]; + } + arrays[dataArray] = newArray; + } + + // make the calcdata array + var serieslen = trace._length; + var cd = new Array(serieslen); + var a, b, c, norm, x, y; + for(i = 0; i < serieslen; i++) { + a = arrays.a[i]; + b = arrays.b[i]; + c = arrays.c[i]; + if(isNumeric(a) && isNumeric(b) && isNumeric(c)) { + a = +a; + b = +b; + c = +c; + norm = displaySum / (a + b + c); + if(norm !== 1) { + a *= norm; + b *= norm; + c *= norm; + } + // map a, b, c onto x and y where the full scale of y + // is [0, sum], and x is [-sum, sum] + // TODO: this makes `a` always the top, `b` the bottom left, + // and `c` the bottom right. Do we want options to rearrange + // these? + y = a; + x = c - b; + cd[i] = {x: x, y: y, a: a, b: b, c: c}; + } + else cd[i] = {x: false, y: false}; + } + + calcMarkerSize(trace, serieslen); + calcColorscale(trace); + arraysToCalcdata(cd, trace); + calcSelection(cd, trace); + + return cd; +}; + +},{"../scatter/arrays_to_calcdata":1042,"../scatter/calc":1044,"../scatter/calc_selection":1045,"../scatter/colorscale_calc":1046,"fast-isnumeric":214}],1116:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var constants = _dereq_('../scatter/constants'); +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var handleLineDefaults = _dereq_('../scatter/line_defaults'); +var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); +var handleTextDefaults = _dereq_('../scatter/text_defaults'); +var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); + +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var a = coerce('a'), + b = coerce('b'), + c = coerce('c'), + len; + + // allow any one array to be missing, len is the minimum length of those + // present. Note that after coerce data_array's are either Arrays (which + // are truthy even if empty) or undefined. As in scatter, an empty array + // is different from undefined, because it can signify that this data is + // not known yet but expected in the future + if(a) { + len = a.length; + if(b) { + len = Math.min(len, b.length); + if(c) len = Math.min(len, c.length); + } + else if(c) len = Math.min(len, c.length); + else len = 0; + } + else if(b && c) { + len = Math.min(b.length, c.length); + } + + if(!len) { + traceOut.visible = false; + return; + } + + traceOut._length = len; + + coerce('sum'); + + coerce('text'); + coerce('hovertext'); + + var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; + coerce('mode', defaultMode); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + handleLineShapeDefaults(traceIn, traceOut, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + var dfltHoverOn = []; + + if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { + coerce('cliponaxis'); + coerce('marker.maxdisplayed'); + dfltHoverOn.push('points'); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + } + + if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { + dfltHoverOn.push('fills'); + } + coerce('hoveron', dfltHoverOn.join('+') || 'points'); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +},{"../../lib":696,"../scatter/constants":1047,"../scatter/fillcolor_defaults":1052,"../scatter/line_defaults":1056,"../scatter/line_shape_defaults":1058,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1114}],1117:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function eventData(out, pt, trace, cd, pointNumber) { + if(pt.xa) out.xaxis = pt.xa; + if(pt.ya) out.yaxis = pt.ya; + + if(cd[pointNumber]) { + var cdi = cd[pointNumber]; + + // N.B. These are the normalized coordinates. + out.a = cdi.a; + out.b = cdi.b; + out.c = cdi.c; + } else { + // for fill-hover only + out.a = pt.a; + out.b = pt.b; + out.c = pt.c; + } + + return out; +}; + +},{}],1118:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scatterHover = _dereq_('../scatter/hover'); +var Axes = _dereq_('../../plots/cartesian/axes'); + + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var scatterPointData = scatterHover(pointData, xval, yval, hovermode); + if(!scatterPointData || scatterPointData[0].index === false) return; + + var newPointData = scatterPointData[0]; + + // if hovering on a fill, we don't show any point data so the label is + // unchanged from what scatter gives us - except that it needs to + // be constrained to the trianglular plot area, not just the rectangular + // area defined by the synthetic x and y axes + // TODO: in some cases the vertical middle of the shape is not within + // the triangular viewport at all, so the label can become disconnected + // from the shape entirely. But calculating what portion of the shape + // is actually visible, as constrained by the diagonal axis lines, is not + // so easy and anyway we lost the information we would have needed to do + // this inside scatterHover. + if(newPointData.index === undefined) { + var yFracUp = 1 - (newPointData.y0 / pointData.ya._length), + xLen = pointData.xa._length, + xMin = xLen * yFracUp / 2, + xMax = xLen - xMin; + newPointData.x0 = Math.max(Math.min(newPointData.x0, xMax), xMin); + newPointData.x1 = Math.max(Math.min(newPointData.x1, xMax), xMin); + return scatterPointData; + } + + var cdi = newPointData.cd[newPointData.index]; + + newPointData.a = cdi.a; + newPointData.b = cdi.b; + newPointData.c = cdi.c; + + newPointData.xLabelVal = undefined; + newPointData.yLabelVal = undefined; + // TODO: nice formatting, and label by axis title, for a, b, and c? + + var trace = newPointData.trace; + var ternary = newPointData.subplot; + var hoverinfo = cdi.hi || trace.hoverinfo; + var parts = hoverinfo.split('+'); + var text = []; + + function textPart(ax, val) { + text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text); + } + + if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'c']; + if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, cdi.a); + if(parts.indexOf('b') !== -1) textPart(ternary.baxis, cdi.b); + if(parts.indexOf('c') !== -1) textPart(ternary.caxis, cdi.c); + + newPointData.extraText = text.join('
'); + + return scatterPointData; +}; + +},{"../../plots/cartesian/axes":744,"../scatter/hover":1054}],1119:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ScatterTernary = {}; + +ScatterTernary.attributes = _dereq_('./attributes'); +ScatterTernary.supplyDefaults = _dereq_('./defaults'); +ScatterTernary.colorbar = _dereq_('../scatter/marker_colorbar'); +ScatterTernary.calc = _dereq_('./calc'); +ScatterTernary.plot = _dereq_('./plot'); +ScatterTernary.style = _dereq_('../scatter/style').style; +ScatterTernary.styleOnSelect = _dereq_('../scatter/style').styleOnSelect; +ScatterTernary.hoverPoints = _dereq_('./hover'); +ScatterTernary.selectPoints = _dereq_('../scatter/select'); +ScatterTernary.eventData = _dereq_('./event_data'); + +ScatterTernary.moduleType = 'trace'; +ScatterTernary.name = 'scatterternary'; +ScatterTernary.basePlotModule = _dereq_('../../plots/ternary'); +ScatterTernary.categories = ['ternary', 'symbols', 'showLegend', 'scatter-like']; +ScatterTernary.meta = { + + +}; + +module.exports = ScatterTernary; + +},{"../../plots/ternary":823,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1114,"./calc":1115,"./defaults":1116,"./event_data":1117,"./hover":1118,"./plot":1120}],1120:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scatterPlot = _dereq_('../scatter/plot'); + +module.exports = function plot(gd, ternary, moduleCalcData) { + var plotContainer = ternary.plotContainer; + + // remove all nodes inside the scatter layer + plotContainer.select('.scatterlayer').selectAll('*').remove(); + + // mimic cartesian plotinfo + var plotinfo = { + xaxis: ternary.xaxis, + yaxis: ternary.yaxis, + plot: plotContainer, + layerClipId: ternary._hasClipOnAxisFalse ? ternary.clipIdRelative : null + }; + + var scatterLayer = ternary.layers.frontplot.select('g.scatterlayer'); + + scatterPlot(gd, plotinfo, moduleCalcData, scatterLayer); +}; + +},{"../scatter/plot":1063}],1121:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = _dereq_('../scatter/attributes'); +var colorAttrs = _dereq_('../../components/colorscale/attributes'); +var scatterGlAttrs = _dereq_('../scattergl/attributes'); +var cartesianIdRegex = _dereq_('../../plots/cartesian/constants').idRegex; +var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +var markerLineAttrs = extendFlat(colorAttrs('marker.line', {editTypeOverride: 'calc'}), { + width: extendFlat({}, scatterMarkerLineAttrs.width, {editType: 'calc'}), + editType: 'calc' +}); + +var markerAttrs = extendFlat(colorAttrs('marker'), { + symbol: scatterMarkerAttrs.symbol, + size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}), + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + opacity: scatterMarkerAttrs.opacity, + colorbar: scatterMarkerAttrs.colorbar, + line: markerLineAttrs, + editType: 'calc' +}); + +markerAttrs.color.editType = markerAttrs.cmin.editType = markerAttrs.cmax.editType = 'style'; + +function makeAxesValObject(axLetter) { + return { + valType: 'info_array', + freeLength: true, + + editType: 'calc', + items: { + valType: 'subplotid', + regex: cartesianIdRegex[axLetter], + editType: 'plot' + }, + + }; +} + +module.exports = { + dimensions: templatedArray('dimension', { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + label: { + valType: 'string', + + editType: 'calc', + + }, + values: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + + axis: { + type: { + valType: 'enumerated', + values: ['linear', 'log', 'date', 'category'], + + editType: 'calc+clearAxisTypes', + + }, + + editType: 'calc+clearAxisTypes' + }, + + // TODO should add an attribute to pin down x only vars and y only vars + // like https://seaborn.pydata.org/generated/seaborn.pairplot.html + // x_vars and y_vars + + // maybe more axis defaulting option e.g. `showgrid: false` + + editType: 'calc+clearAxisTypes' + }), + + // mode: {}, (only 'markers' for now) + + text: extendFlat({}, scatterGlAttrs.text, { + + }), + + marker: markerAttrs, + + xaxes: makeAxesValObject('x'), + yaxes: makeAxesValObject('y'), + + diagonal: { + visible: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + + // type: 'scattergl' | 'histogram' | 'box' | 'violin' + // ... + // more options + + editType: 'calc' + }, + + showupperhalf: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + showlowerhalf: { + valType: 'boolean', + + dflt: true, + editType: 'calc', + + }, + + selected: { + marker: scatterGlAttrs.selected.marker, + editType: 'calc' + }, + unselected: { + marker: scatterGlAttrs.unselected.marker, + editType: 'calc' + }, + + opacity: scatterGlAttrs.opacity +}; + +},{"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750,"../scatter/attributes":1043,"../scattergl/attributes":1092}],1122:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var createLine = _dereq_('regl-line2d'); + +var Registry = _dereq_('../../registry'); +var prepareRegl = _dereq_('../../lib/prepare_regl'); +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; +var Cartesian = _dereq_('../../plots/cartesian'); +var getFromId = _dereq_('../../plots/cartesian/axis_ids').getFromId; +var shouldShowZeroLine = _dereq_('../../plots/cartesian/axes').shouldShowZeroLine; + +var SPLOM = 'splom'; + +function plot(gd) { + var fullLayout = gd._fullLayout; + var _module = Registry.getModule(SPLOM); + var splomCalcData = getModuleCalcData(gd.calcdata, _module)[0]; + + var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']); + if(!success) return; + + if(fullLayout._hasOnlyLargeSploms) { + updateGrid(gd); + } + + _module.plot(gd, {}, splomCalcData); +} + +function drag(gd) { + var cd = gd.calcdata; + var fullLayout = gd._fullLayout; + + if(fullLayout._hasOnlyLargeSploms) { + updateGrid(gd); + } + + for(var i = 0; i < cd.length; i++) { + var cd0 = cd[i][0]; + var trace = cd0.trace; + var scene = fullLayout._splomScenes[trace.uid]; + + if(trace.type === 'splom' && scene && scene.matrix) { + dragOne(gd, trace, scene); + } + } +} + +function dragOne(gd, trace, scene) { + var visibleLength = scene.matrixOptions.data.length; + var visibleDims = trace._visibleDims; + var ranges = scene.viewOpts.ranges = new Array(visibleLength); + + for(var k = 0; k < visibleDims.length; k++) { + var i = visibleDims[k]; + var rng = ranges[k] = new Array(4); + + var xa = getFromId(gd, trace._diag[i][0]); + if(xa) { + rng[0] = xa.r2l(xa.range[0]); + rng[2] = xa.r2l(xa.range[1]); + } + + var ya = getFromId(gd, trace._diag[i][1]); + if(ya) { + rng[1] = ya.r2l(ya.range[0]); + rng[3] = ya.r2l(ya.range[1]); + } + } + + if(scene.selectBatch) { + scene.matrix.update({ranges: ranges}, {ranges: ranges}); + } else { + scene.matrix.update({ranges: ranges}); + } +} + +function updateGrid(gd) { + var fullLayout = gd._fullLayout; + var regl = fullLayout._glcanvas.data()[0].regl; + var splomGrid = fullLayout._splomGrid; + + if(!splomGrid) { + splomGrid = fullLayout._splomGrid = createLine(regl); + } + splomGrid.update(makeGridData(gd)); +} + +function makeGridData(gd) { + var fullLayout = gd._fullLayout; + var gs = fullLayout._size; + var fullView = [0, 0, fullLayout.width, fullLayout.height]; + var lookup = {}; + var k; + + function push(prefix, ax, x0, x1, y0, y1) { + var lcolor = ax[prefix + 'color']; + var lwidth = ax[prefix + 'width']; + var key = String(lcolor + lwidth); + + if(key in lookup) { + lookup[key].data.push(NaN, NaN, x0, x1, y0, y1); + } else { + lookup[key] = { + data: [x0, x1, y0, y1], + join: 'rect', + thickness: lwidth, + color: lcolor, + viewport: fullView, + range: fullView, + overlay: false + }; + } + } + + for(k in fullLayout._splomSubplots) { + var sp = fullLayout._plots[k]; + var xa = sp.xaxis; + var ya = sp.yaxis; + var xVals = xa._vals; + var yVals = ya._vals; + // ya.l2p assumes top-to-bottom coordinate system (a la SVG), + // we need to compute bottom-to-top offsets and slopes: + var yOffset = gs.b + ya.domain[0] * gs.h; + var ym = -ya._m; + var yb = -ym * ya.r2l(ya.range[0], ya.calendar); + var x, y; + + if(xa.showgrid) { + for(k = 0; k < xVals.length; k++) { + x = xa._offset + xa.l2p(xVals[k].x); + push('grid', xa, x, yOffset, x, yOffset + ya._length); + } + } + if(ya.showgrid) { + for(k = 0; k < yVals.length; k++) { + y = yOffset + yb + ym * yVals[k].x; + push('grid', ya, xa._offset, y, xa._offset + xa._length, y); + } + } + if(shouldShowZeroLine(gd, xa, ya)) { + x = xa._offset + xa.l2p(0); + push('zeroline', xa, x, yOffset, x, yOffset + ya._length); + } + if(shouldShowZeroLine(gd, ya, xa)) { + y = yOffset + yb + 0; + push('zeroline', ya, xa._offset, y, xa._offset + xa._length, y); + } + } + + var gridBatches = []; + for(k in lookup) { + gridBatches.push(lookup[k]); + } + + return gridBatches; +} + +function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var lookup = {}; + var i; + + if(oldFullLayout._splomScenes) { + for(i = 0; i < newFullData.length; i++) { + var newTrace = newFullData[i]; + if(newTrace.type === 'splom') { + lookup[newTrace.uid] = 1; + } + } + for(i = 0; i < oldFullData.length; i++) { + var oldTrace = oldFullData[i]; + if(!lookup[oldTrace.uid]) { + var scene = oldFullLayout._splomScenes[oldTrace.uid]; + if(scene && scene.destroy) scene.destroy(); + // must first set scene to null in order to get garbage collected + oldFullLayout._splomScenes[oldTrace.uid] = null; + delete oldFullLayout._splomScenes[oldTrace.uid]; + } + } + } + + if(Object.keys(oldFullLayout._splomScenes || {}).length === 0) { + delete oldFullLayout._splomScenes; + } + + if(oldFullLayout._splomGrid && + (!newFullLayout._hasOnlyLargeSploms && oldFullLayout._hasOnlyLargeSploms)) { + // must first set scene to null in order to get garbage collected + oldFullLayout._splomGrid.destroy(); + oldFullLayout._splomGrid = null; + delete oldFullLayout._splomGrid; + } + + Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); +} + +function updateFx(gd) { + Cartesian.updateFx(gd); + + var fullLayout = gd._fullLayout; + var dragmode = fullLayout.dragmode; + + // unset selection styles when coming out of a selection mode + if(dragmode === 'zoom' || dragmode === 'pan') { + var cd = gd.calcdata; + + for(var i = 0; i < cd.length; i++) { + var cd0 = cd[i][0]; + var trace = cd0.trace; + + if(trace.type === 'splom') { + var scene = fullLayout._splomScenes[trace.uid]; + if(scene.selectBatch === null) { + scene.matrix.update(scene.matrixOptions, null); + } + } + } + } +} + +module.exports = { + name: SPLOM, + attr: Cartesian.attr, + attrRegex: Cartesian.attrRegex, + layoutAttributes: Cartesian.layoutAttributes, + supplyLayoutDefaults: Cartesian.supplyLayoutDefaults, + drawFramework: Cartesian.drawFramework, + plot: plot, + drag: drag, + updateGrid: updateGrid, + clean: clean, + updateFx: updateFx, + toSVG: Cartesian.toSVG +}; + +},{"../../lib/prepare_regl":709,"../../plots/cartesian":756,"../../plots/cartesian/axes":744,"../../plots/cartesian/axis_ids":747,"../../plots/get_data":781,"../../registry":827,"regl-line2d":474}],1123:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); + +var attributes = _dereq_('./attributes'); +var subTypes = _dereq_('../scatter/subtypes'); +var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); +var mergeLength = _dereq_('../parcoords/merge_length'); +var OPEN_RE = /-open/; + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { + name: 'dimensions', + handleItemDefaults: dimensionDefaults + }); + + var showDiag = coerce('diagonal.visible'); + var showUpper = coerce('showupperhalf'); + var showLower = coerce('showlowerhalf'); + + var dimLength = mergeLength(traceOut, dimensions, 'values'); + + if(!dimLength || (!showDiag && !showUpper && !showLower)) { + traceOut.visible = false; + return; + } + + coerce('text'); + + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); + + var isOpen = OPEN_RE.test(traceOut.marker.symbol); + var isBubble = subTypes.isBubble(traceOut); + coerce('marker.line.width', isOpen || isBubble ? 1 : 0); + + handleAxisDefaults(traceIn, traceOut, layout, coerce); + + Lib.coerceSelectionMarkerOpacity(traceOut, coerce); +}; + +function dimensionDefaults(dimIn, dimOut) { + function coerce(attr, dflt) { + return Lib.coerce(dimIn, dimOut, attributes.dimensions, attr, dflt); + } + + coerce('label'); + var values = coerce('values'); + + if(!(values && values.length)) dimOut.visible = false; + else coerce('visible'); + + coerce('axis.type'); +} + +function handleAxisDefaults(traceIn, traceOut, layout, coerce) { + var dimensions = traceOut.dimensions; + var dimLength = dimensions.length; + var showUpper = traceOut.showupperhalf; + var showLower = traceOut.showlowerhalf; + var showDiag = traceOut.diagonal.visible; + var i, j; + + var xAxesDflt = new Array(dimLength); + var yAxesDflt = new Array(dimLength); + + for(i = 0; i < dimLength; i++) { + var suffix = i ? i + 1 : ''; + xAxesDflt[i] = 'x' + suffix; + yAxesDflt[i] = 'y' + suffix; + } + + var xaxes = coerce('xaxes', xAxesDflt); + var yaxes = coerce('yaxes', yAxesDflt); + + // build list of [x,y] axis corresponding to each dimensions[i], + // very useful for passing options to regl-splom + var diag = traceOut._diag = new Array(dimLength); + + // lookup for 'drawn' x|y axes, to avoid costly indexOf downstream + traceOut._xaxes = {}; + traceOut._yaxes = {}; + + // list of 'drawn' x|y axes, use to generate list of subplots + var xList = []; + var yList = []; + + function fillAxisStashes(axId, dim, list) { + if(!axId) return; + + var axLetter = axId.charAt(0); + var stash = layout._splomAxes[axLetter]; + + traceOut['_' + axLetter + 'axes'][axId] = 1; + list.push(axId); + + if(!(axId in stash)) { + var s = stash[axId] = {}; + if(dim) { + s.label = dim.label || ''; + if(dim.visible && dim.axis) { + s.type = dim.axis.type; + } + } + } + } + + // cases where showDiag and showLower or showUpper are false + // no special treatment as the 'drawn' x-axes and y-axes no longer match + // the dimensions items and xaxes|yaxes 1-to-1 + var mustShiftX = !showDiag && !showLower; + var mustShiftY = !showDiag && !showUpper; + + for(i = 0; i < dimLength; i++) { + var dim = dimensions[i]; + var i0 = i === 0; + var iN = i === dimLength - 1; + + var xaId = (i0 && mustShiftX) || (iN && mustShiftY) ? + undefined : + xaxes[i]; + + var yaId = (i0 && mustShiftY) || (iN && mustShiftX) ? + undefined : + yaxes[i]; + + fillAxisStashes(xaId, dim, xList); + fillAxisStashes(yaId, dim, yList); + diag[i] = [xaId, yaId]; + } + + // fill in splom subplot keys + for(i = 0; i < xList.length; i++) { + for(j = 0; j < yList.length; j++) { + var id = xList[i] + yList[j]; + + if(i > j && showUpper) { + layout._splomSubplots[id] = 1; + } else if(i < j && showLower) { + layout._splomSubplots[id] = 1; + } else if(i === j && (showDiag || !showLower || !showUpper)) { + // need to include diagonal subplots when + // hiding one half and the diagonal + layout._splomSubplots[id] = 1; + } + } + } + + // when lower half is omitted, or when just the diagonal is gone, + // override grid default to make sure axes remain on + // the left/bottom of the plot area + if(!showLower || (!showDiag && showUpper && showLower)) { + layout._splomGridDflt.xside = 'bottom'; + layout._splomGridDflt.yside = 'left'; + } +} + +},{"../../lib":696,"../../plots/array_container_defaults":740,"../parcoords/merge_length":1015,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"./attributes":1121}],1124:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var createMatrix = _dereq_('regl-splom'); +var arrayRange = _dereq_('array-range'); + +var Registry = _dereq_('../../registry'); +var Grid = _dereq_('../../components/grid'); +var Lib = _dereq_('../../lib'); +var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); + +var subTypes = _dereq_('../scatter/subtypes'); +var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; +var calcAxisExpansion = _dereq_('../scatter/calc').calcAxisExpansion; +var calcColorscales = _dereq_('../scatter/colorscale_calc'); +var convertMarkerSelection = _dereq_('../scattergl/convert').markerSelection; +var convertMarkerStyle = _dereq_('../scattergl/convert').markerStyle; +var calcHover = _dereq_('../scattergl').calcHover; + +var BADNUM = _dereq_('../../constants/numerical').BADNUM; +var TOO_MANY_POINTS = _dereq_('../scattergl/constants').TOO_MANY_POINTS; + +function calc(gd, trace) { + var dimensions = trace.dimensions; + var commonLength = trace._length; + var opts = {}; + // 'c' for calculated, 'l' for linear, + // only differ here for log axes, pass ldata to createMatrix as 'data' + var cdata = opts.cdata = []; + var ldata = opts.data = []; + // keep track of visible dimensions + var visibleDims = trace._visibleDims = []; + var i, k, dim, xa, ya; + + function makeCalcdata(ax, dim) { + // call makeCalcdata with fake input + var ccol = ax.makeCalcdata({ + v: dim.values, + vcalendar: trace.calendar + }, 'v'); + + for(var j = 0; j < ccol.length; j++) { + ccol[j] = ccol[j] === BADNUM ? NaN : ccol[j]; + } + cdata.push(ccol); + ldata.push(ax.type === 'log' ? Lib.simpleMap(ccol, ax.c2l) : ccol); + } + + for(i = 0; i < dimensions.length; i++) { + dim = dimensions[i]; + + if(dim.visible) { + xa = AxisIDs.getFromId(gd, trace._diag[i][0]); + ya = AxisIDs.getFromId(gd, trace._diag[i][1]); + + // if corresponding x & y axes don't have matching types, skip dim + if(xa && ya && xa.type !== ya.type) { + Lib.log('Skipping splom dimension ' + i + ' with conflicting axis types'); + continue; + } + + if(xa) { + makeCalcdata(xa, dim); + if(ya && ya.type === 'category') { + ya._categories = xa._categories.slice(); + } + } else { + // should not make it here, if both xa and ya undefined + makeCalcdata(ya, dim); + } + + visibleDims.push(i); + } + } + + calcColorscales(trace); + Lib.extendFlat(opts, convertMarkerStyle(trace)); + + var visibleLength = cdata.length; + var hasTooManyPoints = (visibleLength * commonLength) > TOO_MANY_POINTS; + + // Reuse SVG scatter axis expansion routine. + // For graphs with very large number of points and array marker.size, + // use average marker size instead to speed things up. + var ppad; + if(hasTooManyPoints) { + ppad = 2 * (opts.sizeAvg || Math.max(opts.size, 3)); + } else { + ppad = calcMarkerSize(trace, commonLength); + } + + for(k = 0; k < visibleDims.length; k++) { + i = visibleDims[k]; + dim = dimensions[i]; + xa = AxisIDs.getFromId(gd, trace._diag[i][0]) || {}; + ya = AxisIDs.getFromId(gd, trace._diag[i][1]) || {}; + calcAxisExpansion(gd, trace, xa, ya, cdata[k], cdata[k], ppad); + } + + var scene = sceneUpdate(gd, trace); + if(!scene.matrix) scene.matrix = true; + scene.matrixOptions = opts; + + scene.selectedOptions = convertMarkerSelection(trace, trace.selected); + scene.unselectedOptions = convertMarkerSelection(trace, trace.unselected); + + return [{x: false, y: false, t: {}, trace: trace}]; +} + +function sceneUpdate(gd, trace) { + var fullLayout = gd._fullLayout; + var uid = trace.uid; + + // must place ref to 'scene' in fullLayout, so that: + // - it can be relinked properly on updates + // - it can be destroyed properly when needed + var splomScenes = fullLayout._splomScenes; + if(!splomScenes) splomScenes = fullLayout._splomScenes = {}; + + var reset = {dirty: true}; + + var first = { + selectBatch: null, + unselectBatch: null, + matrix: false, + select: null + }; + + var scene = splomScenes[trace.uid]; + + if(!scene) { + scene = splomScenes[uid] = Lib.extendFlat({}, reset, first); + + scene.draw = function draw() { + if(scene.matrix && scene.matrix.draw) { + if(scene.selectBatch) { + scene.matrix.draw(scene.unselectBatch, scene.selectBatch); + } else { + scene.matrix.draw(); + } + } + + scene.dirty = false; + }; + + // remove scene resources + scene.destroy = function destroy() { + if(scene.matrix && scene.matrix.destroy) { + scene.matrix.destroy(); + } + scene.matrixOptions = null; + scene.selectBatch = null; + scene.unselectBatch = null; + scene = null; + }; + } + + // In case if we have scene from the last calc - reset data + if(!scene.dirty) { + Lib.extendFlat(scene, reset); + } + + return scene; +} + +function plot(gd, _, splomCalcData) { + if(!splomCalcData.length) return; + + for(var i = 0; i < splomCalcData.length; i++) { + plotOne(gd, splomCalcData[i][0]); + } +} + +function plotOne(gd, cd0) { + var fullLayout = gd._fullLayout; + var gs = fullLayout._size; + var trace = cd0.trace; + var stash = cd0.t; + var scene = fullLayout._splomScenes[trace.uid]; + var matrixOpts = scene.matrixOptions; + var cdata = matrixOpts.cdata; + var regl = fullLayout._glcanvas.data()[0].regl; + var dragmode = fullLayout.dragmode; + var xa, ya; + var i, j, k; + + if(cdata.length === 0) return; + + // augment options with proper upper/lower halves + // regl-splom's default grid starts from bottom-left + matrixOpts.lower = trace.showupperhalf; + matrixOpts.upper = trace.showlowerhalf; + matrixOpts.diagonal = trace.diagonal.visible; + + var visibleDims = trace._visibleDims; + var visibleLength = cdata.length; + var viewOpts = scene.viewOpts = {}; + viewOpts.ranges = new Array(visibleLength); + viewOpts.domains = new Array(visibleLength); + + for(k = 0; k < visibleDims.length; k++) { + i = visibleDims[k]; + + var rng = viewOpts.ranges[k] = new Array(4); + var dmn = viewOpts.domains[k] = new Array(4); + + xa = AxisIDs.getFromId(gd, trace._diag[i][0]); + if(xa) { + rng[0] = xa._rl[0]; + rng[2] = xa._rl[1]; + dmn[0] = xa.domain[0]; + dmn[2] = xa.domain[1]; + } + + ya = AxisIDs.getFromId(gd, trace._diag[i][1]); + if(ya) { + rng[1] = ya._rl[0]; + rng[3] = ya._rl[1]; + dmn[1] = ya.domain[0]; + dmn[3] = ya.domain[1]; + } + } + + viewOpts.viewport = [gs.l, gs.b, gs.w + gs.l, gs.h + gs.b]; + + if(scene.matrix === true) { + scene.matrix = createMatrix(regl); + } + + var clickSelectEnabled = fullLayout.clickmode.indexOf('select') > -1; + var selectMode = dragmode === 'lasso' || dragmode === 'select' || + !!trace.selectedpoints || clickSelectEnabled; + scene.selectBatch = null; + scene.unselectBatch = null; + + if(selectMode) { + var commonLength = trace._length; + + if(!scene.selectBatch) { + scene.selectBatch = []; + scene.unselectBatch = []; + } + + // regenerate scene batch, if traces number changed during selection + if(trace.selectedpoints) { + scene.selectBatch = trace.selectedpoints; + + var selPts = trace.selectedpoints; + var selDict = {}; + for(i = 0; i < selPts.length; i++) { + selDict[selPts[i]] = true; + } + var unselPts = []; + for(i = 0; i < commonLength; i++) { + if(!selDict[i]) unselPts.push(i); + } + scene.unselectBatch = unselPts; + } + + // precalculate px coords since we are not going to pan during select + var xpx = stash.xpx = new Array(visibleLength); + var ypx = stash.ypx = new Array(visibleLength); + + for(k = 0; k < visibleDims.length; k++) { + i = visibleDims[k]; + + xa = AxisIDs.getFromId(gd, trace._diag[i][0]); + if(xa) { + xpx[k] = new Array(commonLength); + for(j = 0; j < commonLength; j++) { + xpx[k][j] = xa.c2p(cdata[k][j]); + } + } + + ya = AxisIDs.getFromId(gd, trace._diag[i][1]); + if(ya) { + ypx[k] = new Array(commonLength); + for(j = 0; j < commonLength; j++) { + ypx[k][j] = ya.c2p(cdata[k][j]); + } + } + } + + if(scene.selectBatch) { + scene.matrix.update(matrixOpts, matrixOpts); + scene.matrix.update(scene.unselectedOptions, scene.selectedOptions); + scene.matrix.update(viewOpts, viewOpts); + } + else { + // delete selection pass + scene.matrix.update(viewOpts, null); + } + } + else { + var opts = Lib.extendFlat({}, matrixOpts, viewOpts); + scene.matrix.update(opts, null); + stash.xpx = stash.ypx = null; + } +} + +function editStyle(gd, cd0) { + var trace = cd0.trace; + var scene = gd._fullLayout._splomScenes[trace.uid]; + + if(scene) { + calcColorscales(trace); + + Lib.extendFlat(scene.matrixOptions, convertMarkerStyle(trace)); + // TODO [un]selected styles? + + var opts = Lib.extendFlat({}, scene.matrixOptions, scene.viewOpts); + + // TODO this is too long for arrayOk attributes! + scene.matrix.update(opts, null); + } +} + +function hoverPoints(pointData, xval, yval) { + var cd = pointData.cd; + var trace = cd[0].trace; + var scene = pointData.scene; + var cdata = scene.matrixOptions.cdata; + var xa = pointData.xa; + var ya = pointData.ya; + var xpx = xa.c2p(xval); + var ypx = ya.c2p(yval); + var maxDistance = pointData.distance; + + var xi = getDimIndex(trace, xa); + var yi = getDimIndex(trace, ya); + if(xi === false || yi === false) return [pointData]; + + var x = cdata[xi]; + var y = cdata[yi]; + + var id, dxy; + var minDist = maxDistance; + + for(var i = 0; i < x.length; i++) { + var ptx = x[i]; + var pty = y[i]; + var dx = xa.c2p(ptx) - xpx; + var dy = ya.c2p(pty) - ypx; + var dist = Math.sqrt(dx * dx + dy * dy); + + if(dist < minDist) { + minDist = dxy = dist; + id = i; + } + } + + pointData.index = id; + pointData.distance = minDist; + pointData.dxy = dxy; + + if(id === undefined) return [pointData]; + + calcHover(pointData, x, y, trace); + + return [pointData]; +} + +function selectPoints(searchInfo, selectionTester) { + var cd = searchInfo.cd; + var trace = cd[0].trace; + var stash = cd[0].t; + var scene = searchInfo.scene; + var cdata = scene.matrixOptions.cdata; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var i; + + if(!scene) return selection; + + var hasOnlyLines = (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace)); + if(trace.visible !== true || hasOnlyLines) return selection; + + var xi = getDimIndex(trace, xa); + var yi = getDimIndex(trace, ya); + if(xi === false || yi === false) return selection; + + var xpx = stash.xpx[xi]; + var ypx = stash.ypx[yi]; + var x = cdata[xi]; + var y = cdata[yi]; + + // degenerate polygon does not enable selection + // filter out points by visible scatter ones + var els = null; + var unels = null; + if(selectionTester !== false && !selectionTester.degenerate) { + els = [], unels = []; + for(i = 0; i < x.length; i++) { + if(selectionTester.contains([xpx[i], ypx[i]], null, i, searchInfo)) { + els.push(i); + selection.push({ + pointNumber: i, + x: x[i], + y: y[i] + }); + } + else { + unels.push(i); + } + } + } else { + unels = arrayRange(stash.count); + } + + // make sure selectBatch is created + if(!scene.selectBatch) { + scene.selectBatch = []; + scene.unselectBatch = []; + } + + if(!scene.selectBatch) { + // enter every trace select mode + for(i = 0; i < scene.count; i++) { + scene.selectBatch = []; + scene.unselectBatch = []; + } + // we should turn scatter2d into unselected once we have any points selected + scene.matrix.update(scene.unselectedOptions, scene.selectedOptions); + } + + scene.selectBatch = els; + scene.unselectBatch = unels; + + + return selection; +} + +function getDimIndex(trace, ax) { + var axId = ax._id; + var axLetter = axId.charAt(0); + var ind = {x: 0, y: 1}[axLetter]; + var visibleDims = trace._visibleDims; + + for(var k = 0; k < visibleDims.length; k++) { + var i = visibleDims[k]; + if(trace._diag[i][ind] === axId) return k; + } + return false; +} + +module.exports = { + moduleType: 'trace', + name: 'splom', + + basePlotModule: _dereq_('./base_plot'), + categories: ['gl', 'regl', 'cartesian', 'symbols', 'showLegend', 'scatter-like'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + colorbar: _dereq_('../scatter/marker_colorbar'), + + calc: calc, + plot: plot, + hoverPoints: hoverPoints, + selectPoints: selectPoints, + editStyle: editStyle, + + meta: { + + } +}; + +// splom traces use the 'grid' component to generate their axes, +// register it here +Registry.register(Grid); + +},{"../../components/grid":616,"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axis_ids":747,"../../registry":827,"../scatter/calc":1044,"../scatter/colorscale_calc":1046,"../scatter/marker_colorbar":1061,"../scatter/subtypes":1067,"../scattergl":1096,"../scattergl/constants":1093,"../scattergl/convert":1094,"./attributes":1121,"./base_plot":1122,"./defaults":1123,"array-range":55,"regl-splom":477}],1125:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var mesh3dAttrs = _dereq_('../mesh3d/attributes'); +var baseAttrs = _dereq_('../../plots/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +var attrs = { + x: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + y: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + z: { + valType: 'data_array', + + editType: 'calc+clearAxisTypes', + + }, + + u: { + valType: 'data_array', + editType: 'calc', + + }, + v: { + valType: 'data_array', + editType: 'calc', + + }, + w: { + valType: 'data_array', + editType: 'calc', + + }, + + starts: { + x: { + valType: 'data_array', + editType: 'calc', + + }, + y: { + valType: 'data_array', + editType: 'calc', + + }, + z: { + valType: 'data_array', + editType: 'calc', + + }, + editType: 'calc' + }, + + maxdisplayed: { + valType: 'integer', + min: 0, + dflt: 1000, + + editType: 'calc', + + }, + + // TODO + // + // Should add 'absolute' (like cone traces have), but currently gl-streamtube3d's + // `absoluteTubeSize` doesn't behave well enough for our needs. + // + // 'fixed' would be a nice addition to plot stream 'lines', see + // https://github.com/plotly/plotly.js/commit/812be20750e21e0a1831975001c248d365850f73#r29129877 + // + // sizemode: { + // valType: 'enumerated', + // values: ['scaled', 'absolute', 'fixed'], + // dflt: 'scaled', + // + // editType: 'calc', + // + // }, + + sizeref: { + valType: 'number', + + editType: 'calc', + min: 0, + dflt: 1, + + }, + + text: { + valType: 'string', + + dflt: '', + editType: 'calc', + + } +}; + +extendFlat(attrs, colorscaleAttrs('', { + colorAttr: 'u/v/w norm', + showScaleDflt: true, + editTypeOverride: 'calc' +}), { + colorbar: colorbarAttrs +}); + +var fromMesh3d = ['opacity', 'lightposition', 'lighting']; +fromMesh3d.forEach(function(k) { + attrs[k] = mesh3dAttrs[k]; +}); + +attrs.hoverinfo = extendFlat({}, baseAttrs.hoverinfo, { + editType: 'calc', + flags: ['x', 'y', 'z', 'u', 'v', 'w', 'norm', 'divergence', 'text', 'name'], + dflt: 'x+y+z+norm+text+name' +}); + +attrs.transforms = undefined; + +module.exports = attrs; + +},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../mesh3d/attributes":986}],1126:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); + +module.exports = function calc(gd, trace) { + var i; + + var u = trace.u; + var v = trace.v; + var w = trace.w; + var x = trace.x; + var y = trace.y; + var z = trace.z; + var len = Math.min(x.length, y.length, z.length, u.length, v.length, w.length); + + var slen = 0; + var startx, starty, startz; + if(trace.starts) { + startx = trace.starts.x || []; + starty = trace.starts.y || []; + startz = trace.starts.z || []; + slen = Math.min(startx.length, starty.length, startz.length); + } + + var normMax = 0; + var normMin = Infinity; + + for(i = 0; i < len; i++) { + var uu = u[i]; + var vv = v[i]; + var ww = w[i]; + var norm = Math.sqrt(uu * uu + vv * vv + ww * ww); + + normMax = Math.max(normMax, norm); + normMin = Math.min(normMin, norm); + } + + colorscaleCalc(trace, [normMin, normMax], '', 'c'); + + var xMax = -Infinity; + var xMin = Infinity; + var yMax = -Infinity; + var yMin = Infinity; + var zMax = -Infinity; + var zMin = Infinity; + + for(i = 0; i < len; i++) { + var xx = x[i]; + xMax = Math.max(xMax, xx); + xMin = Math.min(xMin, xx); + + var yy = y[i]; + yMax = Math.max(yMax, yy); + yMin = Math.min(yMin, yy); + + var zz = z[i]; + zMax = Math.max(zMax, zz); + zMin = Math.min(zMin, zz); + } + for(i = 0; i < slen; i++) { + var sx = startx[i]; + xMax = Math.max(xMax, sx); + xMin = Math.min(xMin, sx); + + var sy = starty[i]; + yMax = Math.max(yMax, sy); + yMin = Math.min(yMin, sy); + + var sz = startz[i]; + zMax = Math.max(zMax, sz); + zMin = Math.min(zMin, sz); + } + + trace._len = len; + trace._slen = slen; + trace._normMax = normMax; + trace._xbnds = [xMin, xMax]; + trace._ybnds = [yMin, yMax]; + trace._zbnds = [zMin, zMax]; +}; + +},{"../../components/colorscale/calc":578}],1127:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var tube2mesh = _dereq_('gl-streamtube3d'); +var createTubeMesh = tube2mesh.createTubeMesh; + +var Lib = _dereq_('../../lib'); +var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; +var zip3 = _dereq_('../../plots/gl3d/zip3'); + +var axisName2scaleIndex = {xaxis: 0, yaxis: 1, zaxis: 2}; + +function Streamtube(scene, uid) { + this.scene = scene; + this.uid = uid; + this.mesh = null; + this.data = null; +} + +var proto = Streamtube.prototype; + +proto.handlePick = function(selection) { + var sceneLayout = this.scene.fullSceneLayout; + var dataScale = this.scene.dataScale; + + function fromDataScale(v, axisName) { + var ax = sceneLayout[axisName]; + var scale = dataScale[axisName2scaleIndex[axisName]]; + return ax.l2c(v) / scale; + } + + if(selection.object === this.mesh) { + var pos = selection.data.position; + var uvx = selection.data.velocity; + + selection.traceCoordinate = [ + fromDataScale(pos[0], 'xaxis'), + fromDataScale(pos[1], 'yaxis'), + fromDataScale(pos[2], 'zaxis'), + + fromDataScale(uvx[0], 'xaxis'), + fromDataScale(uvx[1], 'yaxis'), + fromDataScale(uvx[2], 'zaxis'), + + // u/v/w norm + selection.data.intensity * this.data._normMax, + // divergence + selection.data.divergence + ]; + + selection.textLabel = this.data.text; + + return true; + } +}; + +function distinctVals(col) { + return Lib.distinctVals(col).vals; +} + +function getDfltStartingPositions(vec) { + var len = vec.length; + var s; + + if(len > 2) { + s = vec.slice(1, len - 1); + } else if(len === 2) { + s = [(vec[0] + vec[1]) / 2]; + } else { + s = vec; + } + return s; +} + +function getBoundPads(vec) { + var len = vec.length; + if(len === 1) { + return [0.5, 0.5]; + } else { + return [vec[1] - vec[0], vec[len - 1] - vec[len - 2]]; + } +} + +function convert(scene, trace) { + var sceneLayout = scene.fullSceneLayout; + var dataScale = scene.dataScale; + var len = trace._len; + var tubeOpts = {}; + + function toDataCoords(arr, axisName) { + var ax = sceneLayout[axisName]; + var scale = dataScale[axisName2scaleIndex[axisName]]; + return Lib.simpleMap(arr, function(v) { return ax.d2l(v) * scale; }); + } + + tubeOpts.vectors = zip3( + toDataCoords(trace.u, 'xaxis'), + toDataCoords(trace.v, 'yaxis'), + toDataCoords(trace.w, 'zaxis'), + len + ); + + var valsx = distinctVals(trace.x.slice(0, len)); + var valsy = distinctVals(trace.y.slice(0, len)); + var valsz = distinctVals(trace.z.slice(0, len)); + + // Over-specified mesh case, this would error in tube2mesh + if(valsx.length * valsy.length * valsz.length > len) { + return {positions: [], cells: []}; + } + + var meshx = toDataCoords(valsx, 'xaxis'); + var meshy = toDataCoords(valsy, 'yaxis'); + var meshz = toDataCoords(valsz, 'zaxis'); + + tubeOpts.meshgrid = [meshx, meshy, meshz]; + + if(trace.starts) { + var slen = trace._slen; + tubeOpts.startingPositions = zip3( + toDataCoords(trace.starts.x.slice(0, slen), 'xaxis'), + toDataCoords(trace.starts.y.slice(0, slen), 'yaxis'), + toDataCoords(trace.starts.z.slice(0, slen), 'zaxis') + ); + } else { + // Default starting positions: + // + // if len>2, cut xz plane at min-y, + // takes all x/y/z pts on that plane except those on the edges + // to generate "well-defined" tubes, + // + // if len=2, take position halfway between two the pts, + // + // if len=1, take that pt + var sy0 = meshy[0]; + var sx = getDfltStartingPositions(meshx); + var sz = getDfltStartingPositions(meshz); + var startingPositions = new Array(sx.length * sz.length); + var m = 0; + + for(var i = 0; i < sx.length; i++) { + for(var k = 0; k < sz.length; k++) { + startingPositions[m++] = [sx[i], sy0, sz[k]]; + } + } + tubeOpts.startingPositions = startingPositions; + } + + tubeOpts.colormap = parseColorScale(trace.colorscale); + tubeOpts.tubeSize = trace.sizeref; + tubeOpts.maxLength = trace.maxdisplayed; + + // add some padding around the bounds + // to e.g. allow tubes starting from a slice of the x/y/z mesh + // to go beyond bounds a little bit w/o getting clipped + var xbnds = toDataCoords(trace._xbnds, 'xaxis'); + var ybnds = toDataCoords(trace._ybnds, 'yaxis'); + var zbnds = toDataCoords(trace._zbnds, 'zaxis'); + var xpads = getBoundPads(meshx); + var ypads = getBoundPads(meshy); + var zpads = getBoundPads(meshz); + + var bounds = [ + [xbnds[0] - xpads[0], ybnds[0] - ypads[0], zbnds[0] - zpads[0]], + [xbnds[1] + xpads[1], ybnds[1] + ypads[1], zbnds[1] + zpads[1]] + ]; + + var meshData = tube2mesh(tubeOpts, bounds); + + // N.B. cmin/cmax correspond to the min/max vector norm + // in the u/v/w arrays, which in general is NOT equal to max + // intensity that colors the tubes. + meshData.vertexIntensityBounds = [trace.cmin / trace._normMax, trace.cmax / trace._normMax]; + + // pass gl-mesh3d lighting attributes + var lp = trace.lightposition; + meshData.lightPosition = [lp.x, lp.y, lp.z]; + meshData.ambient = trace.lighting.ambient; + meshData.diffuse = trace.lighting.diffuse; + meshData.specular = trace.lighting.specular; + meshData.roughness = trace.lighting.roughness; + meshData.fresnel = trace.lighting.fresnel; + meshData.opacity = trace.opacity; + + // stash autorange pad value + trace._pad = meshData.tubeScale * trace.sizeref * 2; + + return meshData; +} + +proto.update = function(data) { + this.data = data; + + var meshData = convert(this.scene, data); + this.mesh.update(meshData); +}; + +proto.dispose = function() { + this.scene.glplot.remove(this.mesh); + this.mesh.dispose(); +}; + +function createStreamtubeTrace(scene, data) { + var gl = scene.glplot.gl; + + var meshData = convert(scene, data); + var mesh = createTubeMesh(gl, meshData); + + var streamtube = new Streamtube(scene, data.uid); + streamtube.mesh = mesh; + streamtube.data = data; + mesh._trace = streamtube; + + scene.glplot.add(mesh); + + return streamtube; +} + +module.exports = createStreamtubeTrace; + +},{"../../lib":696,"../../lib/gl_format_color":692,"../../plots/gl3d/zip3":798,"gl-streamtube3d":301}],1128:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var u = coerce('u'); + var v = coerce('v'); + var w = coerce('w'); + + var x = coerce('x'); + var y = coerce('y'); + var z = coerce('z'); + + if( + !u || !u.length || !v || !v.length || !w || !w.length || + !x || !x.length || !y || !y.length || !z || !z.length + ) { + traceOut.visible = false; + return; + } + + coerce('starts.x'); + coerce('starts.y'); + coerce('starts.z'); + + coerce('maxdisplayed'); + coerce('sizeref'); + + coerce('lighting.ambient'); + coerce('lighting.diffuse'); + coerce('lighting.specular'); + coerce('lighting.roughness'); + coerce('lighting.fresnel'); + coerce('lightposition.x'); + coerce('lightposition.y'); + coerce('lightposition.z'); + + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); + + coerce('text'); + + // disable 1D transforms (for now) + // x/y/z and u/v/w have matching lengths, + // but they don't have to match with starts.(x|y|z) + traceOut._length = null; +}; + +},{"../../components/colorscale/defaults":580,"../../lib":696,"./attributes":1125}],1129:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'trace', + name: 'streamtube', + basePlotModule: _dereq_('../../plots/gl3d'), + categories: ['gl3d'], + + attributes: _dereq_('./attributes'), + supplyDefaults: _dereq_('./defaults'), + colorbar: { + min: 'cmin', + max: 'cmax' + }, + calc: _dereq_('./calc'), + plot: _dereq_('./convert'), + eventData: function(out, pt) { + out.tubex = out.x; + out.tubey = out.y; + out.tubez = out.z; + + out.tubeu = pt.traceCoordinate[3]; + out.tubev = pt.traceCoordinate[4]; + out.tubew = pt.traceCoordinate[5]; + + out.norm = pt.traceCoordinate[6]; + out.divergence = pt.traceCoordinate[7]; + + // Does not correspond to input x/y/z, so delete them + delete out.x; + delete out.y; + delete out.z; + + return out; + }, + + meta: { + + } +}; + +},{"../../plots/gl3d":787,"./attributes":1125,"./calc":1126,"./convert":1127,"./defaults":1128}],1130:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Color = _dereq_('../../components/color'); +var colorscaleAttrs = _dereq_('../../components/colorscale/attributes'); +var colorbarAttrs = _dereq_('../../components/colorbar/attributes'); +var baseAttrs = _dereq_('../../plots/attributes'); + +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; + +function makeContourProjAttr(axLetter) { + return { + valType: 'boolean', + + dflt: false, + + }; +} + +function makeContourAttr(axLetter) { + return { + show: { + valType: 'boolean', + + dflt: false, + + }, + project: { + x: makeContourProjAttr('x'), + y: makeContourProjAttr('y'), + z: makeContourProjAttr('z') + }, + color: { + valType: 'color', + + dflt: Color.defaultLine, + + }, + usecolormap: { + valType: 'boolean', + + dflt: false, + + }, + width: { + valType: 'number', + + min: 1, + max: 16, + dflt: 2, + + }, + highlight: { + valType: 'boolean', + + dflt: true, + + }, + highlightcolor: { + valType: 'color', + + dflt: Color.defaultLine, + + }, + highlightwidth: { + valType: 'number', + + min: 1, + max: 16, + dflt: 2, + + } + }; +} + +var attrs = module.exports = overrideAll(extendFlat({ + z: { + valType: 'data_array', + + }, + x: { + valType: 'data_array', + + }, + y: { + valType: 'data_array', + + }, + + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + + }, + + surfacecolor: { + valType: 'data_array', + + }, +}, + +colorscaleAttrs('', { + colorAttr: 'z or surfacecolor', + showScaleDflt: true, + autoColorDflt: false, + editTypeOverride: 'calc' +}), { + colorbar: colorbarAttrs, + + contours: { + x: makeContourAttr('x'), + y: makeContourAttr('y'), + z: makeContourAttr('z') + }, + hidesurface: { + valType: 'boolean', + + dflt: false, + + }, + + lightposition: { + x: { + valType: 'number', + + min: -1e5, + max: 1e5, + dflt: 10, + + }, + y: { + valType: 'number', + + min: -1e5, + max: 1e5, + dflt: 1e4, + + }, + z: { + valType: 'number', + + min: -1e5, + max: 1e5, + dflt: 0, + + } + }, + + lighting: { + ambient: { + valType: 'number', + + min: 0.00, + max: 1.0, + dflt: 0.8, + + }, + diffuse: { + valType: 'number', + + min: 0.00, + max: 1.00, + dflt: 0.8, + + }, + specular: { + valType: 'number', + + min: 0.00, + max: 2.00, + dflt: 0.05, + + }, + roughness: { + valType: 'number', + + min: 0.00, + max: 1.00, + dflt: 0.5, + + }, + fresnel: { + valType: 'number', + + min: 0.00, + max: 5.00, + dflt: 0.2, + + } + }, + + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + + }, + + _deprecated: { + zauto: extendFlat({}, colorscaleAttrs.zauto, { + + }), + zmin: extendFlat({}, colorscaleAttrs.zmin, { + + }), + zmax: extendFlat({}, colorscaleAttrs.zmax, { + + }) + }, + + hoverinfo: extendFlat({}, baseAttrs.hoverinfo) +}), 'calc', 'nested'); + +attrs.x.editType = attrs.y.editType = attrs.z.editType = 'calc+clearAxisTypes'; +attrs.transforms = undefined; + +},{"../../components/color":570,"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741}],1131:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var colorscaleCalc = _dereq_('../../components/colorscale/calc'); + + +// Compute auto-z and autocolorscale if applicable +module.exports = function calc(gd, trace) { + if(trace.surfacecolor) { + colorscaleCalc(trace, trace.surfacecolor, '', 'c'); + } else { + colorscaleCalc(trace, trace.z, '', 'c'); + } +}; + +},{"../../components/colorscale/calc":578}],1132:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var createSurface = _dereq_('gl-surface3d'); +var ndarray = _dereq_('ndarray'); +var homography = _dereq_('ndarray-homography'); +var fill = _dereq_('ndarray-fill'); +var ops = _dereq_('ndarray-ops'); + +var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; +var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; +var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); + +var MIN_RESOLUTION = 128; + +function SurfaceTrace(scene, surface, uid) { + this.scene = scene; + this.uid = uid; + this.surface = surface; + this.data = null; + this.showContour = [false, false, false]; + this.dataScale = 1.0; +} + +var proto = SurfaceTrace.prototype; + +proto.handlePick = function(selection) { + if(selection.object === this.surface) { + var selectIndex = selection.index = [ + Math.min( + Math.round(selection.data.index[0] / this.dataScale - 1)|0, + this.data.z[0].length - 1 + ), + Math.min( + Math.round(selection.data.index[1] / this.dataScale - 1)|0, + this.data.z.length - 1 + ) + ]; + var traceCoordinate = [0, 0, 0]; + + if(!isArrayOrTypedArray(this.data.x)) { + traceCoordinate[0] = selectIndex[0]; + } else if(isArrayOrTypedArray(this.data.x[0])) { + traceCoordinate[0] = this.data.x[selectIndex[1]][selectIndex[0]]; + } else { + traceCoordinate[0] = this.data.x[selectIndex[0]]; + } + + if(!isArrayOrTypedArray(this.data.y)) { + traceCoordinate[1] = selectIndex[1]; + } else if(isArrayOrTypedArray(this.data.y[0])) { + traceCoordinate[1] = this.data.y[selectIndex[1]][selectIndex[0]]; + } else { + traceCoordinate[1] = this.data.y[selectIndex[1]]; + } + + traceCoordinate[2] = this.data.z[selectIndex[1]][selectIndex[0]]; + selection.traceCoordinate = traceCoordinate; + + var sceneLayout = this.scene.fullSceneLayout; + selection.dataCoordinate = [ + sceneLayout.xaxis.d2l(traceCoordinate[0], 0, this.data.xcalendar) * this.scene.dataScale[0], + sceneLayout.yaxis.d2l(traceCoordinate[1], 0, this.data.ycalendar) * this.scene.dataScale[1], + sceneLayout.zaxis.d2l(traceCoordinate[2], 0, this.data.zcalendar) * this.scene.dataScale[2] + ]; + + var text = this.data.text; + if(Array.isArray(text) && text[selectIndex[1]] && text[selectIndex[1]][selectIndex[0]] !== undefined) { + selection.textLabel = text[selectIndex[1]][selectIndex[0]]; + } else if(text) { + selection.textLabel = text; + } else { + selection.textLabel = ''; + } + + selection.data.dataCoordinate = selection.dataCoordinate.slice(); + + this.surface.highlight(selection.data); + + // Snap spikes to data coordinate + this.scene.glplot.spikes.position = selection.dataCoordinate; + + return true; + } +}; + +function isColormapCircular(colormap) { + var first = colormap[0].rgb, + last = colormap[colormap.length - 1].rgb; + + return ( + first[0] === last[0] && + first[1] === last[1] && + first[2] === last[2] && + first[3] === last[3] + ); +} + +// Pad coords by +1 +function padField(field) { + var shape = field.shape; + var nshape = [shape[0] + 2, shape[1] + 2]; + var nfield = ndarray(new Float32Array(nshape[0] * nshape[1]), nshape); + + // Center + ops.assign(nfield.lo(1, 1).hi(shape[0], shape[1]), field); + + // Edges + ops.assign(nfield.lo(1).hi(shape[0], 1), + field.hi(shape[0], 1)); + ops.assign(nfield.lo(1, nshape[1] - 1).hi(shape[0], 1), + field.lo(0, shape[1] - 1).hi(shape[0], 1)); + ops.assign(nfield.lo(0, 1).hi(1, shape[1]), + field.hi(1)); + ops.assign(nfield.lo(nshape[0] - 1, 1).hi(1, shape[1]), + field.lo(shape[0] - 1)); + + // Corners + nfield.set(0, 0, field.get(0, 0)); + nfield.set(0, nshape[1] - 1, field.get(0, shape[1] - 1)); + nfield.set(nshape[0] - 1, 0, field.get(shape[0] - 1, 0)); + nfield.set(nshape[0] - 1, nshape[1] - 1, field.get(shape[0] - 1, shape[1] - 1)); + + return nfield; +} + +function refine(coords) { + var minScale = Math.max(coords[0].shape[0], coords[0].shape[1]); + + if(minScale < MIN_RESOLUTION) { + var scaleF = MIN_RESOLUTION / minScale; + var nshape = [ + Math.floor((coords[0].shape[0]) * scaleF + 1)|0, + Math.floor((coords[0].shape[1]) * scaleF + 1)|0 ]; + var nsize = nshape[0] * nshape[1]; + + for(var i = 0; i < coords.length; ++i) { + var padImg = padField(coords[i]); + var scaledImg = ndarray(new Float32Array(nsize), nshape); + homography(scaledImg, padImg, [scaleF, 0, 0, + 0, scaleF, 0, + 0, 0, 1]); + coords[i] = scaledImg; + } + + return scaleF; + } + + return 1.0; +} + +proto.setContourLevels = function() { + var nlevels = [[], [], []]; + var needsUpdate = false; + + for(var i = 0; i < 3; ++i) { + if(this.showContour[i]) { + needsUpdate = true; + nlevels[i] = this.scene.contourLevels[i]; + } + } + + if(needsUpdate) { + this.surface.update({ levels: nlevels }); + } +}; + +proto.update = function(data) { + var i, + scene = this.scene, + sceneLayout = scene.fullSceneLayout, + surface = this.surface, + alpha = data.opacity, + colormap = parseColorScale(data.colorscale, alpha), + z = data.z, + x = data.x, + y = data.y, + xaxis = sceneLayout.xaxis, + yaxis = sceneLayout.yaxis, + zaxis = sceneLayout.zaxis, + scaleFactor = scene.dataScale, + xlen = z[0].length, + ylen = data._ylength, + coords = [ + ndarray(new Float32Array(xlen * ylen), [xlen, ylen]), + ndarray(new Float32Array(xlen * ylen), [xlen, ylen]), + ndarray(new Float32Array(xlen * ylen), [xlen, ylen]) + ], + xc = coords[0], + yc = coords[1], + contourLevels = scene.contourLevels; + + // Save data + this.data = data; + + /* + * Fill and transpose zdata. + * Consistent with 'heatmap' and 'contour', plotly 'surface' + * 'z' are such that sub-arrays correspond to y-coords + * and that the sub-array entries correspond to a x-coords, + * which is the transpose of 'gl-surface-plot'. + */ + + var xcalendar = data.xcalendar, + ycalendar = data.ycalendar, + zcalendar = data.zcalendar; + + fill(coords[2], function(row, col) { + return zaxis.d2l(z[col][row], 0, zcalendar) * scaleFactor[2]; + }); + + // coords x + if(!isArrayOrTypedArray(x)) { + fill(xc, function(row) { + return xaxis.d2l(row, 0, xcalendar) * scaleFactor[0]; + }); + } else if(isArrayOrTypedArray(x[0])) { + fill(xc, function(row, col) { + return xaxis.d2l(x[col][row], 0, xcalendar) * scaleFactor[0]; + }); + } else { + // ticks x + fill(xc, function(row) { + return xaxis.d2l(x[row], 0, xcalendar) * scaleFactor[0]; + }); + } + + // coords y + if(!isArrayOrTypedArray(x)) { + fill(yc, function(row, col) { + return yaxis.d2l(col, 0, xcalendar) * scaleFactor[1]; + }); + } else if(isArrayOrTypedArray(y[0])) { + fill(yc, function(row, col) { + return yaxis.d2l(y[col][row], 0, ycalendar) * scaleFactor[1]; + }); + } else { + // ticks y + fill(yc, function(row, col) { + return yaxis.d2l(y[col], 0, ycalendar) * scaleFactor[1]; + }); + } + + var params = { + colormap: colormap, + levels: [[], [], []], + showContour: [true, true, true], + showSurface: !data.hidesurface, + contourProject: [ + [false, false, false], + [false, false, false], + [false, false, false] + ], + contourWidth: [1, 1, 1], + contourColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], + contourTint: [1, 1, 1], + dynamicColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], + dynamicWidth: [1, 1, 1], + dynamicTint: [1, 1, 1], + opacity: data.opacity + }; + + params.intensityBounds = [data.cmin, data.cmax]; + + // Refine if necessary + if(data.surfacecolor) { + var intensity = ndarray(new Float32Array(xlen * ylen), [xlen, ylen]); + + fill(intensity, function(row, col) { + return data.surfacecolor[col][row]; + }); + + coords.push(intensity); + } + else { + // when 'z' is used as 'intensity', + // we must scale its value + params.intensityBounds[0] *= scaleFactor[2]; + params.intensityBounds[1] *= scaleFactor[2]; + } + + this.dataScale = refine(coords); + + if(data.surfacecolor) { + params.intensity = coords.pop(); + } + + var highlightEnable = [true, true, true]; + var axis = ['x', 'y', 'z']; + + for(i = 0; i < 3; ++i) { + var contourParams = data.contours[axis[i]]; + highlightEnable[i] = contourParams.highlight; + + params.showContour[i] = contourParams.show || contourParams.highlight; + if(!params.showContour[i]) continue; + + params.contourProject[i] = [ + contourParams.project.x, + contourParams.project.y, + contourParams.project.z + ]; + + if(contourParams.show) { + this.showContour[i] = true; + params.levels[i] = contourLevels[i]; + surface.highlightColor[i] = params.contourColor[i] = str2RgbaArray(contourParams.color); + + if(contourParams.usecolormap) { + surface.highlightTint[i] = params.contourTint[i] = 0; + } + else { + surface.highlightTint[i] = params.contourTint[i] = 1; + } + params.contourWidth[i] = contourParams.width; + } else { + this.showContour[i] = false; + } + + if(contourParams.highlight) { + params.dynamicColor[i] = str2RgbaArray(contourParams.highlightcolor); + params.dynamicWidth[i] = contourParams.highlightwidth; + } + } + + // see https://github.com/plotly/plotly.js/issues/940 + if(isColormapCircular(colormap)) { + params.vertexColor = true; + } + + params.coords = coords; + + surface.update(params); + + surface.visible = data.visible; + surface.enableDynamic = highlightEnable; + surface.enableHighlight = highlightEnable; + + surface.snapToData = true; + + if('lighting' in data) { + surface.ambientLight = data.lighting.ambient; + surface.diffuseLight = data.lighting.diffuse; + surface.specularLight = data.lighting.specular; + surface.roughness = data.lighting.roughness; + surface.fresnel = data.lighting.fresnel; + } + + if('lightposition' in data) { + surface.lightPosition = [data.lightposition.x, data.lightposition.y, data.lightposition.z]; + } + + if(alpha && alpha < 1) { + surface.supportsTransparency = true; + } +}; + +proto.dispose = function() { + this.scene.glplot.remove(this.surface); + this.surface.dispose(); +}; + +function createSurfaceTrace(scene, data) { + var gl = scene.glplot.gl; + var surface = createSurface({ gl: gl }); + var result = new SurfaceTrace(scene, surface, data.uid); + surface._trace = result; + result.update(data); + scene.glplot.add(surface); + return result; +} + +module.exports = createSurfaceTrace; + +},{"../../lib":696,"../../lib/gl_format_color":692,"../../lib/str2rgbarray":719,"gl-surface3d":303,"ndarray":433,"ndarray-fill":423,"ndarray-homography":425,"ndarray-ops":427}],1133:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = _dereq_('../../registry'); +var Lib = _dereq_('../../lib'); + +var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); +var attributes = _dereq_('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + var i, j; + + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var z = coerce('z'); + if(!z) { + traceOut.visible = false; + return; + } + + var x = coerce('x'); + coerce('y'); + + traceOut._xlength = (Array.isArray(x) && Lib.isArrayOrTypedArray(x[0])) ? z.length : z[0].length; + traceOut._ylength = z.length; + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); + handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); + + coerce('text'); + + // Coerce remaining properties + [ + 'lighting.ambient', + 'lighting.diffuse', + 'lighting.specular', + 'lighting.roughness', + 'lighting.fresnel', + 'lightposition.x', + 'lightposition.y', + 'lightposition.z', + 'hidesurface', + 'opacity' + ].forEach(function(x) { coerce(x); }); + + var surfaceColor = coerce('surfacecolor'); + + coerce('colorscale'); + + var dims = ['x', 'y', 'z']; + for(i = 0; i < 3; ++i) { + + var contourDim = 'contours.' + dims[i]; + var show = coerce(contourDim + '.show'); + var highlight = coerce(contourDim + '.highlight'); + + if(show || highlight) { + for(j = 0; j < 3; ++j) { + coerce(contourDim + '.project.' + dims[j]); + } + } + + if(show) { + coerce(contourDim + '.color'); + coerce(contourDim + '.width'); + coerce(contourDim + '.usecolormap'); + } + + if(highlight) { + coerce(contourDim + '.highlightcolor'); + coerce(contourDim + '.highlightwidth'); + } + } + + // backward compatibility block + if(!surfaceColor) { + mapLegacy(traceIn, 'zmin', 'cmin'); + mapLegacy(traceIn, 'zmax', 'cmax'); + mapLegacy(traceIn, 'zauto', 'cauto'); + } + + // TODO if contours.?.usecolormap are false and hidesurface is true + // the colorbar shouldn't be shown by default + + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'} + ); + + // disable 1D transforms - currently surface does NOT support column data like heatmap does + // you can use mesh3d for this use case, but not surface + traceOut._length = null; +}; + +function mapLegacy(traceIn, oldAttr, newAttr) { + if(oldAttr in traceIn && !(newAttr in traceIn)) { + traceIn[newAttr] = traceIn[oldAttr]; + } +} + +},{"../../components/colorscale/defaults":580,"../../lib":696,"../../registry":827,"./attributes":1130}],1134:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Surface = {}; + +Surface.attributes = _dereq_('./attributes'); +Surface.supplyDefaults = _dereq_('./defaults'); +Surface.colorbar = { + min: 'cmin', + max: 'cmax' +}; +Surface.calc = _dereq_('./calc'); +Surface.plot = _dereq_('./convert'); + +Surface.moduleType = 'trace'; +Surface.name = 'surface'; +Surface.basePlotModule = _dereq_('../../plots/gl3d'); +Surface.categories = ['gl3d', '2dMap', 'noOpacity']; +Surface.meta = { + +}; + +module.exports = Surface; + +},{"../../plots/gl3d":787,"./attributes":1130,"./calc":1131,"./convert":1132,"./defaults":1133}],1135:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var annAttrs = _dereq_('../../components/annotations/attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; +var fontAttrs = _dereq_('../../plots/font_attributes'); +var domainAttrs = _dereq_('../../plots/domain').attributes; + +var attrs = module.exports = overrideAll({ + domain: domainAttrs({name: 'table', trace: true}), + + columnwidth: { + valType: 'number', + arrayOk: true, + dflt: null, + + + }, + + columnorder: { + valType: 'data_array', + + + }, + + header: { + + values: { + valType: 'data_array', + + dflt: [], + + }, + + format: { + valType: 'data_array', + + dflt: [], + + }, + + prefix: { + valType: 'string', + arrayOk: true, + dflt: null, + + + }, + + suffix: { + valType: 'string', + arrayOk: true, + dflt: null, + + + }, + + height: { + valType: 'number', + dflt: 28, + + + }, + + align: extendFlat({}, annAttrs.align, {arrayOk: true}), + + line: { + width: { + valType: 'number', + arrayOk: true, + dflt: 1, + + }, + color: { + valType: 'color', + arrayOk: true, + dflt: 'grey', + + } + }, + + fill: { + color: { + valType: 'color', + arrayOk: true, + dflt: 'white', + + + } + }, + + font: extendFlat({}, fontAttrs({arrayOk: true})) + }, + + cells: { + + values: { + valType: 'data_array', + + dflt: [], + + }, + + format: { + valType: 'data_array', + + dflt: [], + + }, + + prefix: { + valType: 'string', + arrayOk: true, + dflt: null, + + + }, + + suffix: { + valType: 'string', + arrayOk: true, + dflt: null, + + + }, + + height: { + valType: 'number', + dflt: 20, + + + }, + + align: extendFlat({}, annAttrs.align, {arrayOk: true}), + + line: { + width: { + valType: 'number', + arrayOk: true, + dflt: 1, + + }, + color: { + valType: 'color', + arrayOk: true, + dflt: 'grey', + + } + }, + + fill: { + color: { + valType: 'color', + arrayOk: true, + + dflt: 'white', + + } + }, + + font: extendFlat({}, fontAttrs({arrayOk: true})) + } +}, 'calc', 'from-root'); +attrs.transforms = undefined; + +},{"../../components/annotations/attributes":553,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/domain":770,"../../plots/font_attributes":771}],1136:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; +var tablePlot = _dereq_('./plot'); + +var TABLE = 'table'; + +exports.name = TABLE; + +exports.plot = function(gd) { + var calcData = getModuleCalcData(gd.calcdata, TABLE)[0]; + if(calcData.length) tablePlot(gd, calcData); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadTable = (oldFullLayout._has && oldFullLayout._has(TABLE)); + var hasTable = (newFullLayout._has && newFullLayout._has(TABLE)); + + if(hadTable && !hasTable) { + oldFullLayout._paperdiv.selectAll('.table').remove(); + } +}; + +},{"../../plots/get_data":781,"./plot":1143}],1137:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var wrap = _dereq_('../../lib/gup').wrap; + +module.exports = function calc() { + // we don't actually need to include the trace here, since that will be added + // by Plots.doCalcdata, and that's all we actually need later. + return wrap({}); +}; + +},{"../../lib/gup":693}],1138:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + cellPad: 8, + columnExtentOffset: 10, + columnTitleOffset: 28, + emptyHeaderHeight: 16, + latexCheck: /^\$.*\$$/, + goldenRatio: 1.618, + lineBreaker: '
', + maxDimensionCount: 60, + overdrag: 45, + releaseTransitionDuration: 120, + releaseTransitionEase: 'cubic-out', + scrollbarCaptureWidth: 18, + scrollbarHideDelay: 1000, + scrollbarHideDuration: 1000, + scrollbarOffset: 5, + scrollbarWidth: 8, + transitionDuration: 100, + transitionEase: 'cubic-out', + uplift: 5, + wrapSpacer: ' ', + wrapSplitCharacter: ' ', + cn: { + // general class names + table: 'table', + tableControlView: 'table-control-view', + scrollBackground: 'scroll-background', + yColumn: 'y-column', + columnBlock: 'column-block', + scrollAreaClip: 'scroll-area-clip', + scrollAreaClipRect: 'scroll-area-clip-rect', + columnBoundary: 'column-boundary', + columnBoundaryClippath: 'column-boundary-clippath', + columnBoundaryRect: 'column-boundary-rect', + columnCells: 'column-cells', + columnCell: 'column-cell', + cellRect: 'cell-rect', + cellText: 'cell-text', + cellTextHolder: 'cell-text-holder', + + // scroll related class names + scrollbarKit: 'scrollbar-kit', + scrollbar: 'scrollbar', + scrollbarSlider: 'scrollbar-slider', + scrollbarGlyph: 'scrollbar-glyph', + scrollbarCaptureZone: 'scrollbar-capture-zone' + } +}; + +},{}],1139:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var c = _dereq_('./constants'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; +var isNumeric = _dereq_('fast-isnumeric'); + +// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying +module.exports = function calc(gd, trace) { + var cellsValues = squareStringMatrix(trace.cells.values); + var slicer = function(a) { + return a.slice(trace.header.values.length, a.length); + }; + var headerValuesIn = squareStringMatrix(trace.header.values); + if(headerValuesIn.length && !headerValuesIn[0].length) { + headerValuesIn[0] = ['']; + headerValuesIn = squareStringMatrix(headerValuesIn); + } + var headerValues = headerValuesIn + .concat(slicer(cellsValues).map(function() { + return emptyStrings((headerValuesIn[0] || ['']).length); + })); + + var domain = trace.domain; + var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); + var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); + var headerRowHeights = trace.header.values.length ? + headerValues[0].map(function() { return trace.header.height; }) : + [c.emptyHeaderHeight]; + var rowHeights = cellsValues.length ? cellsValues[0].map(function() { return trace.cells.height; }) : []; + var headerHeight = headerRowHeights.reduce(sum, 0); + var scrollHeight = groupHeight - headerHeight; + var minimumFillHeight = scrollHeight + c.uplift; + var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); + var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); + var headerRowBlocks = makeRowBlock(anchorToHeaderRowBlock, []); + var rowBlocks = makeRowBlock(anchorToRowBlock, headerRowBlocks); + var uniqueKeys = {}; + var columnOrder = trace._fullInput.columnorder.concat(slicer(cellsValues.map(function(d, i) {return i;}))); + var columnWidths = headerValues.map(function(d, i) { + var value = Array.isArray(trace.columnwidth) ? + trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : + trace.columnwidth; + return isNumeric(value) ? Number(value) : 1; + }); + var totalColumnWidths = columnWidths.reduce(sum, 0); + + // fit columns in the available vertical space as there's no vertical scrolling now + columnWidths = columnWidths.map(function(d) { return d / totalColumnWidths * groupWidth; }); + + var maxLineWidth = Math.max(arrayMax(trace.header.line.width), arrayMax(trace.cells.line.width)); + + var calcdata = { + key: trace.index, + translateX: domain.x[0] * gd._fullLayout._size.w, + translateY: gd._fullLayout._size.h * (1 - domain.y[1]), + size: gd._fullLayout._size, + width: groupWidth, + maxLineWidth: maxLineWidth, + height: groupHeight, + columnOrder: columnOrder, // will be mutated on column move, todo use in callback + groupHeight: groupHeight, + rowBlocks: rowBlocks, + headerRowBlocks: headerRowBlocks, + scrollY: 0, // will be mutated on scroll + cells: extendFlat({}, trace.cells, {values: cellsValues}), + headerCells: extendFlat({}, trace.header, {values: headerValues}), + gdColumns: headerValues.map(function(d) {return d[0];}), + gdColumnsOriginalOrder: headerValues.map(function(d) {return d[0];}), + prevPages: [0, 0], + scrollbarState: {scrollbarScrollInProgress: false}, + columns: headerValues.map(function(label, i) { + var foundKey = uniqueKeys[label]; + uniqueKeys[label] = (foundKey || 0) + 1; + var key = label + '__' + uniqueKeys[label]; + return { + key: key, + label: label, + specIndex: i, + xIndex: columnOrder[i], + xScale: xScale, + x: undefined, // initialized below + calcdata: undefined, // initialized below + columnWidth: columnWidths[i] + }; + }) + }; + + calcdata.columns.forEach(function(col) { + col.calcdata = calcdata; + col.x = xScale(col); + }); + + return calcdata; +}; + +function arrayMax(maybeArray) { + if(Array.isArray(maybeArray)) { + var max = 0; + for(var i = 0; i < maybeArray.length; i++) { + max = Math.max(max, arrayMax(maybeArray[i])); + } + return max; + } + return maybeArray; +} + +function sum(a, b) { return a + b; } + +// fill matrix in place to equal lengths +// and ensure it's uniformly 2D +function squareStringMatrix(matrixIn) { + var matrix = matrixIn.slice(); + var minLen = Infinity; + var maxLen = 0; + var i; + for(i = 0; i < matrix.length; i++) { + if(!Array.isArray(matrix[i])) matrix[i] = [matrix[i]]; + minLen = Math.min(minLen, matrix[i].length); + maxLen = Math.max(maxLen, matrix[i].length); + } + + if(minLen !== maxLen) { + for(i = 0; i < matrix.length; i++) { + var padLen = maxLen - matrix[i].length; + if(padLen) matrix[i] = matrix[i].concat(emptyStrings(padLen)); + } + } + return matrix; +} + +function emptyStrings(len) { + var padArray = new Array(len); + for(var j = 0; j < len; j++) padArray[j] = ''; + return padArray; +} + +function xScale(d) { + return d.calcdata.columns.reduce(function(prev, next) { + return next.xIndex < d.xIndex ? prev + next.columnWidth : prev; + }, 0); +} + +function makeRowBlock(anchorToRowBlock, auxiliary) { + var blockAnchorKeys = Object.keys(anchorToRowBlock); + return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}); +} + +function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { + + var anchorToRowBlock = {}; + var currentRowHeight; + var currentAnchor = 0; + var currentBlockHeight = 0; + var currentBlock = makeIdentity(); + var currentFirstRowIndex = 0; + var blockCounter = 0; + for(var i = 0; i < rowHeights.length; i++) { + currentRowHeight = rowHeights[i]; + currentBlock.rows.push({ + rowIndex: i, + rowHeight: currentRowHeight + }); + currentBlockHeight += currentRowHeight; + if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { + anchorToRowBlock[currentAnchor] = currentBlock; + currentBlock.key = blockCounter++; + currentBlock.firstRowIndex = currentFirstRowIndex; + currentBlock.lastRowIndex = i; + currentBlock = makeIdentity(); + currentAnchor += currentBlockHeight; + currentFirstRowIndex = i + 1; + currentBlockHeight = 0; + } + } + + return anchorToRowBlock; +} + +function makeIdentity() { + return { + firstRowIndex: null, + lastRowIndex: null, + rows: [] + }; +} + +},{"../../lib/extend":685,"./constants":1138,"fast-isnumeric":214}],1140:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying + +exports.splitToPanels = function(d) { + var prevPages = [0, 0]; + var headerPanel = extendFlat({}, d, { + key: 'header', + type: 'header', + page: 0, + prevPages: prevPages, + currentRepaint: [null, null], + dragHandle: true, + values: d.calcdata.headerCells.values[d.specIndex], + rowBlocks: d.calcdata.headerRowBlocks, + calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) + }); + var revolverPanel1 = extendFlat({}, d, { + key: 'cells1', + type: 'cells', + page: 0, + prevPages: prevPages, + currentRepaint: [null, null], + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowBlocks: d.calcdata.rowBlocks + }); + var revolverPanel2 = extendFlat({}, d, { + key: 'cells2', + type: 'cells', + page: 1, + prevPages: prevPages, + currentRepaint: [null, null], + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowBlocks: d.calcdata.rowBlocks + }); + // order due to SVG using painter's algo: + return [revolverPanel1, revolverPanel2, headerPanel]; +}; + +exports.splitToCells = function(d) { + var fromTo = rowFromTo(d); + return (d.values || []).slice(fromTo[0], fromTo[1]).map(function(v, i) { + // By keeping identical key, a DOM node removal, creation and addition is spared, important when visible + // grid has a lot of elements (quadratic with xcol/ycol count). + // But it has to be busted when `svgUtil.convertToTspans` is used as it reshapes cell subtrees asynchronously, + // and by that time the user may have scrolled away, resulting in stale overwrites. The real solution will be + // to turn `svgUtil.convertToTspans` into a cancelable request, in which case no key busting is needed. + var buster = (typeof v === 'string') && v.match(/[<$&> ]/) ? '_keybuster_' + Math.random() : ''; + return { + // keyWithinBlock: /*fromTo[0] + */i, // optimized future version - no busting + // keyWithinBlock: fromTo[0] + i, // initial always-unoptimized version - janky scrolling with 5+ columns + keyWithinBlock: i + buster, // current compromise: regular content is very fast; async content is possible + key: fromTo[0] + i, + column: d, + calcdata: d.calcdata, + page: d.page, + rowBlocks: d.rowBlocks, + value: v + }; + }); +}; + +function rowFromTo(d) { + var rowBlock = d.rowBlocks[d.page]; + // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 + var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; + return [rowFrom, rowTo]; +} + +},{"../../lib/extend":685}],1141:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var attributes = _dereq_('./attributes'); +var handleDomainDefaults = _dereq_('../../plots/domain').defaults; + +function defaultColumnOrder(traceOut, coerce) { + var specifiedColumnOrder = traceOut.columnorder || []; + var commonLength = traceOut.header.values.length; + var truncated = specifiedColumnOrder.slice(0, commonLength); + var sorted = truncated.slice().sort(function(a, b) {return a - b;}); + var oneStepped = truncated.map(function(d) {return sorted.indexOf(d);}); + for(var i = oneStepped.length; i < commonLength; i++) { + oneStepped.push(i); + } + coerce('columnorder', oneStepped); +} + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + handleDomainDefaults(traceOut, layout, coerce); + + coerce('columnwidth'); + + coerce('header.values'); + coerce('header.format'); + coerce('header.align'); + + coerce('header.prefix'); + coerce('header.suffix'); + coerce('header.height'); + coerce('header.line.width'); + coerce('header.line.color'); + coerce('header.fill.color'); + Lib.coerceFont(coerce, 'header.font', Lib.extendFlat({}, layout.font)); + + defaultColumnOrder(traceOut, coerce); + + coerce('cells.values'); + coerce('cells.format'); + coerce('cells.align'); + coerce('cells.prefix'); + coerce('cells.suffix'); + coerce('cells.height'); + coerce('cells.line.width'); + coerce('cells.line.color'); + coerce('cells.fill.color'); + Lib.coerceFont(coerce, 'cells.font', Lib.extendFlat({}, layout.font)); + + // disable 1D transforms + traceOut._length = null; +}; + +},{"../../lib":696,"../../plots/domain":770,"./attributes":1135}],1142:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Table = {}; + +Table.attributes = _dereq_('./attributes'); +Table.supplyDefaults = _dereq_('./defaults'); +Table.calc = _dereq_('./calc'); +Table.plot = _dereq_('./plot'); + +Table.moduleType = 'trace'; +Table.name = 'table'; +Table.basePlotModule = _dereq_('./base_plot'); +Table.categories = ['noOpacity']; +Table.meta = { + +}; + +module.exports = Table; + +},{"./attributes":1135,"./base_plot":1136,"./calc":1137,"./defaults":1141,"./plot":1143}],1143:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var c = _dereq_('./constants'); +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var gup = _dereq_('../../lib/gup'); +var Drawing = _dereq_('../../components/drawing'); +var svgUtil = _dereq_('../../lib/svg_text_utils'); +var raiseToTop = _dereq_('../../lib').raiseToTop; +var cancelEeaseColumn = _dereq_('../../lib').cancelTransition; +var prepareData = _dereq_('./data_preparation_helper'); +var splitData = _dereq_('./data_split_helpers'); +var Color = _dereq_('../../components/color'); + +module.exports = function plot(gd, wrappedTraceHolders) { + + var table = gd._fullLayout._paper.selectAll('.' + c.cn.table) + .data(wrappedTraceHolders.map(function(wrappedTraceHolder) { + var traceHolder = gup.unwrap(wrappedTraceHolder); + var trace = traceHolder.trace; + return prepareData(gd, trace); + }), gup.keyFun); + + table.exit().remove(); + + table.enter() + .append('g') + .classed(c.cn.table, true) + .attr('overflow', 'visible') + .style('box-sizing', 'content-box') + .style('position', 'absolute') + .style('left', 0) + .style('overflow', 'visible') + .style('shape-rendering', 'crispEdges') + .style('pointer-events', 'all'); + + table + .attr('width', function(d) {return d.width + d.size.l + d.size.r;}) + .attr('height', function(d) {return d.height + d.size.t + d.size.b;}) + .attr('transform', function(d) { + return 'translate(' + d.translateX + ',' + d.translateY + ')'; + }); + + var tableControlView = table.selectAll('.' + c.cn.tableControlView) + .data(gup.repeat, gup.keyFun); + + tableControlView.enter() + .append('g') + .classed(c.cn.tableControlView, true) + .style('box-sizing', 'content-box') + .on('mousemove', function(d) {tableControlView.filter(function(dd) {return d === dd;}).call(renderScrollbarKit, gd);}) + .on('mousewheel', function(d) { + if(d.scrollbarState.wheeling) return; + d.scrollbarState.wheeling = true; + d3.event.stopPropagation(); + d3.event.preventDefault(); + makeDragRow(gd, tableControlView, null, d.scrollY + d3.event.deltaY)(d); + d.scrollbarState.wheeling = false; + }) + .call(renderScrollbarKit, gd, true); + + tableControlView + .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}); + + // scrollBackground merely ensures that mouse events are captured even on crazy fast scrollwheeling + // otherwise rendering glitches may occur + var scrollBackground = tableControlView.selectAll('.' + c.cn.scrollBackground) + .data(gup.repeat, gup.keyFun); + + scrollBackground.enter() + .append('rect') + .classed(c.cn.scrollBackground, true) + .attr('fill', 'none'); + + scrollBackground + .attr('width', function(d) {return d.width;}) + .attr('height', function(d) {return d.height;}); + + tableControlView + .each(function(d) {Drawing.setClipUrl(d3.select(this), scrollAreaBottomClipKey(gd, d));}); + + var yColumn = tableControlView.selectAll('.' + c.cn.yColumn) + .data(function(vm) {return vm.columns;}, gup.keyFun); + + yColumn.enter() + .append('g') + .classed(c.cn.yColumn, true); + + yColumn.exit().remove(); + + yColumn + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}) + .call(d3.behavior.drag() + .origin(function(d) { + var movedColumn = d3.select(this); + easeColumn(movedColumn, d, -c.uplift); + raiseToTop(this); + d.calcdata.columnDragInProgress = true; + renderScrollbarKit(tableControlView.filter(function(dd) {return d.calcdata.key === dd.key;}), gd); + return d; + }) + .on('drag', function(d) { + var movedColumn = d3.select(this); + var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;}; + d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); + + var sortableColumns = flatData(yColumn).filter(function(dd) {return dd.calcdata.key === d.calcdata.key;}); + var newOrder = sortableColumns.sort(function(a, b) {return getter(a) - getter(b);}); + newOrder.forEach(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd); + }); + + yColumn.filter(function(dd) {return d !== dd;}) + .transition() + .ease(c.transitionEase) + .duration(c.transitionDuration) + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); + movedColumn + .call(cancelEeaseColumn) + .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); + }) + .on('dragend', function(d) { + var movedColumn = d3.select(this); + var p = d.calcdata; + d.x = d.xScale(d); + d.calcdata.columnDragInProgress = false; + easeColumn(movedColumn, d, 0); + columnMoved(gd, p, p.columns.map(function(dd) {return dd.xIndex;})); + }) + ); + + yColumn.each(function(d) {Drawing.setClipUrl(d3.select(this), columnBoundaryClipKey(gd, d));}); + + var columnBlock = yColumn.selectAll('.' + c.cn.columnBlock) + .data(splitData.splitToPanels, gup.keyFun); + + columnBlock.enter() + .append('g') + .classed(c.cn.columnBlock, true) + .attr('id', function(d) {return d.key;}); + + columnBlock + .style('cursor', function(d) { + return d.dragHandle ? 'ew-resize' : d.calcdata.scrollbarState.barWiggleRoom ? 'ns-resize' : 'default'; + }); + + var headerColumnBlock = columnBlock.filter(headerBlock); + var cellsColumnBlock = columnBlock.filter(cellsBlock); + + cellsColumnBlock + .call(d3.behavior.drag() + .origin(function(d) { + d3.event.stopPropagation(); + return d; + }) + .on('drag', makeDragRow(gd, tableControlView, -1)) + .on('dragend', function() { + // fixme emit plotly notification + }) + ); + + // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) + // but blocks are _entered_ the way they are due to painter's algo (header on top) + renderColumnCellTree(gd, tableControlView, headerColumnBlock, columnBlock); + renderColumnCellTree(gd, tableControlView, cellsColumnBlock, columnBlock); + + var scrollAreaClip = tableControlView.selectAll('.' + c.cn.scrollAreaClip) + .data(gup.repeat, gup.keyFun); + + scrollAreaClip.enter() + .append('clipPath') + .classed(c.cn.scrollAreaClip, true) + .attr('id', function(d) {return scrollAreaBottomClipKey(gd, d);}); + + var scrollAreaClipRect = scrollAreaClip.selectAll('.' + c.cn.scrollAreaClipRect) + .data(gup.repeat, gup.keyFun); + + scrollAreaClipRect.enter() + .append('rect') + .classed(c.cn.scrollAreaClipRect, true) + .attr('x', -c.overdrag) + .attr('y', -c.uplift) + .attr('fill', 'none'); + + scrollAreaClipRect + .attr('width', function(d) {return d.width + 2 * c.overdrag;}) + .attr('height', function(d) {return d.height + c.uplift;}); + + var columnBoundary = yColumn.selectAll('.' + c.cn.columnBoundary) + .data(gup.repeat, gup.keyFun); + + columnBoundary.enter() + .append('g') + .classed(c.cn.columnBoundary, true); + + var columnBoundaryClippath = yColumn.selectAll('.' + c.cn.columnBoundaryClippath) + .data(gup.repeat, gup.keyFun); + + // SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference + columnBoundaryClippath.enter() + .append('clipPath') + .classed(c.cn.columnBoundaryClippath, true); + + columnBoundaryClippath + .attr('id', function(d) {return columnBoundaryClipKey(gd, d);}); + + var columnBoundaryRect = columnBoundaryClippath.selectAll('.' + c.cn.columnBoundaryRect) + .data(gup.repeat, gup.keyFun); + + columnBoundaryRect.enter() + .append('rect') + .classed(c.cn.columnBoundaryRect, true) + .attr('fill', 'none'); + + columnBoundaryRect + .attr('width', function(d) { return d.columnWidth + 2 * roundHalfWidth(d); }) + .attr('height', function(d) {return d.calcdata.height + 2 * roundHalfWidth(d) + c.uplift;}) + .attr('x', function(d) { return -roundHalfWidth(d); }) + .attr('y', function(d) { return -roundHalfWidth(d); }); + + updateBlockYPosition(null, cellsColumnBlock, tableControlView); +}; + +function roundHalfWidth(d) { + return Math.ceil(d.calcdata.maxLineWidth / 2); +} + +function scrollAreaBottomClipKey(gd, d) { + return 'clip' + gd._fullLayout._uid + '_scrollAreaBottomClip_' + d.key; +} + +function columnBoundaryClipKey(gd, d) { + return 'clip' + gd._fullLayout._uid + '_columnBoundaryClippath_' + d.calcdata.key + '_' + d.specIndex; +} + +function flatData(selection) { + return [].concat.apply([], selection.map(function(g) {return g;})) + .map(function(g) {return g.__data__;}); +} + +function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) { + + function calcTotalHeight(d) { + var blocks = d.rowBlocks; + return firstRowAnchor(blocks, blocks.length - 1) + (blocks.length ? rowsHeight(blocks[blocks.length - 1], Infinity) : 1); + } + + var scrollbarKit = tableControlView.selectAll('.' + c.cn.scrollbarKit) + .data(gup.repeat, gup.keyFun); + + scrollbarKit.enter() + .append('g') + .classed(c.cn.scrollbarKit, true) + .style('shape-rendering', 'geometricPrecision'); + + scrollbarKit + .each(function(d) { + var s = d.scrollbarState; + s.totalHeight = calcTotalHeight(d); + s.scrollableAreaHeight = d.groupHeight - headerHeight(d); + s.currentlyVisibleHeight = Math.min(s.totalHeight, s.scrollableAreaHeight); + s.ratio = s.currentlyVisibleHeight / s.totalHeight; + s.barLength = Math.max(s.ratio * s.currentlyVisibleHeight, c.goldenRatio * c.scrollbarWidth); + s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; + s.wiggleRoom = Math.max(0, s.totalHeight - s.scrollableAreaHeight); + s.topY = s.barWiggleRoom === 0 ? 0 : (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; + s.bottomY = s.topY + s.barLength; + s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; + }) + .attr('transform', function(d) { + var xPosition = d.width + c.scrollbarWidth / 2 + c.scrollbarOffset; + return 'translate(' + xPosition + ' ' + headerHeight(d) + ')'; + }); + + var scrollbar = scrollbarKit.selectAll('.' + c.cn.scrollbar) + .data(gup.repeat, gup.keyFun); + + scrollbar.enter() + .append('g') + .classed(c.cn.scrollbar, true); + + var scrollbarSlider = scrollbar.selectAll('.' + c.cn.scrollbarSlider) + .data(gup.repeat, gup.keyFun); + + scrollbarSlider.enter() + .append('g') + .classed(c.cn.scrollbarSlider, true); + + scrollbarSlider + .attr('transform', function(d) { + return 'translate(0 ' + (d.scrollbarState.topY || 0) + ')'; + }); + + var scrollbarGlyph = scrollbarSlider.selectAll('.' + c.cn.scrollbarGlyph) + .data(gup.repeat, gup.keyFun); + + scrollbarGlyph.enter() + .append('line') + .classed(c.cn.scrollbarGlyph, true) + .attr('stroke', 'black') + .attr('stroke-width', c.scrollbarWidth) + .attr('stroke-linecap', 'round') + .attr('y1', c.scrollbarWidth / 2); + + scrollbarGlyph + .attr('y2', function(d) { + return d.scrollbarState.barLength - c.scrollbarWidth / 2; + }) + .attr('stroke-opacity', function(d) { + return d.columnDragInProgress || !d.scrollbarState.barWiggleRoom || bypassVisibleBar ? 0 : 0.4; + }); + + // cancel transition: possible pending (also, delayed) transition + scrollbarGlyph + .transition().delay(0).duration(0); + + scrollbarGlyph + .transition().delay(c.scrollbarHideDelay).duration(c.scrollbarHideDuration) + .attr('stroke-opacity', 0); + + var scrollbarCaptureZone = scrollbar.selectAll('.' + c.cn.scrollbarCaptureZone) + .data(gup.repeat, gup.keyFun); + + scrollbarCaptureZone.enter() + .append('line') + .classed(c.cn.scrollbarCaptureZone, true) + .attr('stroke', 'white') + .attr('stroke-opacity', 0.01) // some browser might get rid of a 0 opacity element + .attr('stroke-width', c.scrollbarCaptureWidth) + .attr('stroke-linecap', 'butt') + .attr('y1', 0) + .on('mousedown', function(d) { + var y = d3.event.y; + var bbox = this.getBoundingClientRect(); + var s = d.scrollbarState; + var pixelVal = y - bbox.top; + var inverseScale = d3.scale.linear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true); + if(!(s.topY <= pixelVal && pixelVal <= s.bottomY)) { + makeDragRow(gd, tableControlView, null, inverseScale(pixelVal - s.barLength / 2))(d); + } + }) + .call(d3.behavior.drag() + .origin(function(d) { + d3.event.stopPropagation(); + d.scrollbarState.scrollbarScrollInProgress = true; + return d; + }) + .on('drag', makeDragRow(gd, tableControlView)) + .on('dragend', function() { + // fixme emit Plotly event + }) + ); + + scrollbarCaptureZone + .attr('y2', function(d) { + return d.scrollbarState.scrollableAreaHeight; + }); +} + +function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) { + // fixme this perf hotspot + // this is performance critical code as scrolling calls it on every revolver switch + // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization + + var columnCells = renderColumnCells(columnBlock); + + var columnCell = renderColumnCell(columnCells); + + supplyStylingValues(columnCell); + + var cellRect = renderCellRect(columnCell); + + sizeAndStyleRect(cellRect); + + var cellTextHolder = renderCellTextHolder(columnCell); + + var cellText = renderCellText(cellTextHolder); + + setFont(cellText); + populateCellText(cellText, tableControlView, allColumnBlock, gd); + + // doing this at the end when text, and text stlying are set + setCellHeightAndPositionY(columnCell); +} + +function renderColumnCells(columnBlock) { + + var columnCells = columnBlock.selectAll('.' + c.cn.columnCells) + .data(gup.repeat, gup.keyFun); + + columnCells.enter() + .append('g') + .classed(c.cn.columnCells, true); + + columnCells.exit() + .remove(); + + return columnCells; +} + +function renderColumnCell(columnCells) { + + var columnCell = columnCells.selectAll('.' + c.cn.columnCell) + .data(splitData.splitToCells, function(d) {return d.keyWithinBlock;}); + + columnCell.enter() + .append('g') + .classed(c.cn.columnCell, true); + + columnCell.exit() + .remove(); + + return columnCell; +} + +function renderCellRect(columnCell) { + + var cellRect = columnCell.selectAll('.' + c.cn.cellRect) + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); + + cellRect.enter() + .append('rect') + .classed(c.cn.cellRect, true); + + return cellRect; +} + +function renderCellText(cellTextHolder) { + + var cellText = cellTextHolder.selectAll('.' + c.cn.cellText) + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); + + cellText.enter() + .append('text') + .classed(c.cn.cellText, true) + .style('cursor', function() {return 'auto';}) + .on('mousedown', function() {d3.event.stopPropagation();}); + + return cellText; +} + +function renderCellTextHolder(columnCell) { + + var cellTextHolder = columnCell.selectAll('.' + c.cn.cellTextHolder) + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); + + cellTextHolder.enter() + .append('g') + .classed(c.cn.cellTextHolder, true) + .style('shape-rendering', 'geometricPrecision'); + + return cellTextHolder; +} + +function supplyStylingValues(columnCell) { + columnCell + .each(function(d, i) { + var spec = d.calcdata.cells.font; + var col = d.column.specIndex; + var font = { + size: gridPick(spec.size, col, i), + color: gridPick(spec.color, col, i), + family: gridPick(spec.family, col, i) + }; + d.rowNumber = d.key; + d.align = gridPick(d.calcdata.cells.align, col, i); + d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i); + d.font = font; + }); +} + +function setFont(cellText) { + cellText + .each(function(d) { + Drawing.font(d3.select(this), d.font); + }); +} + +function sizeAndStyleRect(cellRect) { + cellRect + .attr('width', function(d) {return d.column.columnWidth;}) + .attr('stroke-width', function(d) {return d.cellBorderWidth;}) + .each(function(d) { + var atomicSelection = d3.select(this); + Color.stroke(atomicSelection, gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber)); + Color.fill(atomicSelection, gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber)); + }); +} + +function populateCellText(cellText, tableControlView, allColumnBlock, gd) { + cellText + .text(function(d) { + + var col = d.column.specIndex; + var row = d.rowNumber; + + var userSuppliedContent = d.value; + var stringSupplied = (typeof userSuppliedContent === 'string'); + var hasBreaks = stringSupplied && userSuppliedContent.match(/
/i); + var userBrokenText = !stringSupplied || hasBreaks; + d.mayHaveMarkup = stringSupplied && userSuppliedContent.match(/[<&>]/); + + var latex = isLatex(userSuppliedContent); + d.latex = latex; + + var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; + var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; + var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; + + var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; + + var hasWrapSplitCharacter; + d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hasWrapCharacter(prefixSuffixedText)); + d.cellHeightMayIncrease = hasBreaks || latex || d.mayHaveMarkup || (hasWrapSplitCharacter === void(0) ? hasWrapCharacter(prefixSuffixedText) : hasWrapSplitCharacter); + d.needsConvertToTspans = d.mayHaveMarkup || d.wrappingNeeded || d.latex; + + var textToRender; + if(d.wrappingNeeded) { + var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/ pTop) { + pages.push(blockIndex); + } + pTop += rowsHeight; + + // consider this nice final optimization; put it in `for` condition - caveat, currently the + // block.allRowsHeight relies on being invalidated, so enabling this opt may not be safe + // if(pages.length > 1) break; + } + + return pages; +} + +function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { + var d = flatData(cellsColumnBlock)[0]; + if(d === undefined) return; + var blocks = d.rowBlocks; + var calcdata = d.calcdata; + + var bottom = firstRowAnchor(blocks, blocks.length); + var scrollHeight = d.calcdata.groupHeight - headerHeight(d); + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); + + var pages = findPagesAndCacheHeights(blocks, scrollY, scrollHeight); + if(pages.length === 1) { + if(pages[0] === blocks.length - 1) { + pages.unshift(pages[0] - 1); + } else { + pages.push(pages[0] + 1); + } + } + + // make phased out page jump by 2 while leaving stationary page intact + if(pages[0] % 2) { + pages.reverse(); + } + + cellsColumnBlock + .each(function(d, i) { + // these values will also be needed when a block is translated again due to growing cell height + d.page = pages[i]; + d.scrollY = scrollY; + }); + + cellsColumnBlock + .attr('transform', function(d) { + var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; + return 'translate(0 ' + yTranslate + ')'; + }); + + // conditionally rerendering panel 0 and 1 + if(gd) { + conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 0); + conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 1); + renderScrollbarKit(tableControlView, gd); + } +} + +function makeDragRow(gd, allTableControlView, optionalMultiplier, optionalPosition) { + return function dragRow(eventD) { + // may come from whicever DOM event target: drag, wheel, bar... eventD corresponds to event target + var d = eventD.calcdata ? eventD.calcdata : eventD; + var tableControlView = allTableControlView.filter(function(dd) {return d.key === dd.key;}); + var multiplier = optionalMultiplier || d.scrollbarState.dragMultiplier; + d.scrollY = optionalPosition === void(0) ? d.scrollY + multiplier * d3.event.dy : optionalPosition; + var cellsColumnBlock = tableControlView.selectAll('.' + c.cn.yColumn).selectAll('.' + c.cn.columnBlock).filter(cellsBlock); + updateBlockYPosition(gd, cellsColumnBlock, tableControlView); + }; +} + +function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, prevPages, d, revolverIndex) { + var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; + if(shouldComponentUpdate) { + clearTimeout(d.currentRepaint[revolverIndex]); + d.currentRepaint[revolverIndex] = setTimeout(function() { + // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes + // some repaints invisible ie. wasteful (DOM work blocks the main thread) + var toRerender = cellsColumnBlock.filter(function(d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); + renderColumnCellTree(gd, tableControlView, toRerender, cellsColumnBlock); + prevPages[revolverIndex] = pages[revolverIndex]; + }); + } +} + +function wrapTextMaker(columnBlock, element, tableControlView) { + return function wrapText() { + var cellTextHolder = d3.select(element.parentNode); + cellTextHolder + .each(function(d) { + var fragments = d.fragments; + cellTextHolder.selectAll('tspan.line').each(function(dd, i) { + fragments[i].width = this.getComputedTextLength(); + }); + // last element is only for measuring the separator character, so it's ignored: + var separatorLength = fragments[fragments.length - 1].width; + var rest = fragments.slice(0, -1); + var currentRow = []; + var currentAddition, currentAdditionLength; + var currentRowLength = 0; + var rowLengthLimit = d.column.columnWidth - 2 * c.cellPad; + d.value = ''; + while(rest.length) { + currentAddition = rest.shift(); + currentAdditionLength = currentAddition.width + separatorLength; + if(currentRowLength + currentAdditionLength > rowLengthLimit) { + d.value += currentRow.join(c.wrapSpacer) + c.lineBreaker; + currentRow = []; + currentRowLength = 0; + } + currentRow.push(currentAddition.text); + currentRowLength += currentAdditionLength; + } + if(currentRowLength) { + d.value += currentRow.join(c.wrapSpacer); + } + d.wrapped = true; + }); + + // the pre-wrapped text was rendered only for the text measurements + cellTextHolder.selectAll('tspan.line').remove(); + + // resupply text, now wrapped + populateCellText(cellTextHolder.select('.' + c.cn.cellText), tableControlView, columnBlock); + d3.select(element.parentNode.parentNode).call(setCellHeightAndPositionY); + }; +} + +function updateYPositionMaker(columnBlock, element, tableControlView, gd, d) { + return function updateYPosition() { + if(d.settledY) return; + var cellTextHolder = d3.select(element.parentNode); + var l = getBlock(d); + var rowIndex = d.key - l.firstRowIndex; + + var declaredRowHeight = l.rows[rowIndex].rowHeight; + + var requiredHeight = d.cellHeightMayIncrease ? element.parentNode.getBoundingClientRect().height + 2 * c.cellPad : declaredRowHeight; + + var finalHeight = Math.max(requiredHeight, declaredRowHeight); + var increase = finalHeight - l.rows[rowIndex].rowHeight; + + if(increase) { + + // current row height increased + l.rows[rowIndex].rowHeight = finalHeight; + + columnBlock + .selectAll('.' + c.cn.columnCell) + .call(setCellHeightAndPositionY); + + updateBlockYPosition(null, columnBlock.filter(cellsBlock), 0); + + // if d.column.type === 'header', then the scrollbar has to be pushed downward to the scrollable area + // if d.column.type === 'cells', it can still be relevant if total scrolling content height is less than the + // scrollable window, as increases to row heights may need scrollbar updates + renderScrollbarKit(tableControlView, gd, true); + } + + cellTextHolder + .attr('transform', function() { + // this code block is only invoked for items where d.cellHeightMayIncrease is truthy + var element = this; + var columnCellElement = element.parentNode; + var box = columnCellElement.getBoundingClientRect(); + var rectBox = d3.select(element.parentNode).select('.' + c.cn.cellRect).node().getBoundingClientRect(); + var currentTransform = element.transform.baseVal.consolidate(); + var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); + return 'translate(' + xPosition(d, d3.select(element.parentNode).select('.' + c.cn.cellTextHolder).node().getBoundingClientRect().width) + ' ' + yPosition + ')'; + }); + + d.settledY = true; + }; +} + +function xPosition(d, optionalWidth) { + switch(d.align) { + case 'left': return c.cellPad; + case 'right': return d.column.columnWidth - (optionalWidth || 0) - c.cellPad; + case 'center': return (d.column.columnWidth - (optionalWidth || 0)) / 2; + default: return c.cellPad; + } +} + +function setCellHeightAndPositionY(columnCell) { + columnCell + .attr('transform', function(d) { + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity);}, 0); + var l = getBlock(d); + var rowAnchor = rowsHeight(l, d.key); + var yOffset = rowAnchor + headerHeight; + return 'translate(0 ' + yOffset + ')'; + }) + .selectAll('.' + c.cn.cellRect) + .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); +} + +function firstRowAnchor(blocks, page) { + var total = 0; + for(var i = page - 1; i >= 0; i--) { + total += allRowsHeight(blocks[i]); + } + return total; +} + +function rowsHeight(rowBlock, key) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { + total += rowBlock.rows[i].rowHeight; + } + return total; +} + +function allRowsHeight(rowBlock) { + var cached = rowBlock.allRowsHeight; + + if(cached !== void(0)) { + return cached; + } + + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + total += rowBlock.rows[i].rowHeight; + } + rowBlock.allRowsHeight = total; + + return total; +} + +function getBlock(d) {return d.rowBlocks[d.page];} +function getRow(l, i) {return l.rows[i - l.firstRowIndex];} + +},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../lib/gup":693,"../../lib/svg_text_utils":720,"./constants":1138,"./data_preparation_helper":1139,"./data_split_helpers":1140,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1144:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var boxAttrs = _dereq_('../box/attributes'); +var extendFlat = _dereq_('../../lib/extend').extendFlat; + +module.exports = { + y: boxAttrs.y, + x: boxAttrs.x, + x0: boxAttrs.x0, + y0: boxAttrs.y0, + name: boxAttrs.name, + orientation: extendFlat({}, boxAttrs.orientation, { + + }), + + bandwidth: { + valType: 'number', + min: 0, + + editType: 'calc', + + }, + + scalegroup: { + valType: 'string', + + dflt: '', + editType: 'calc', + + }, + scalemode: { + valType: 'enumerated', + values: ['width', 'count'], + dflt: 'width', + + editType: 'calc', + + }, + + spanmode: { + valType: 'enumerated', + values: ['soft', 'hard', 'manual'], + dflt: 'soft', + + editType: 'calc', + + }, + span: { + valType: 'info_array', + items: [ + {valType: 'any', editType: 'calc'}, + {valType: 'any', editType: 'calc'} + ], + + editType: 'calc', + + }, + + line: { + color: { + valType: 'color', + + editType: 'style', + + }, + width: { + valType: 'number', + + min: 0, + dflt: 2, + editType: 'style', + + }, + editType: 'plot' + }, + fillcolor: boxAttrs.fillcolor, + + points: extendFlat({}, boxAttrs.boxpoints, { + + }), + jitter: extendFlat({}, boxAttrs.jitter, { + + }), + pointpos: extendFlat({}, boxAttrs.pointpos, { + + }), + marker: boxAttrs.marker, + text: boxAttrs.text, + + box: { + visible: { + valType: 'boolean', + dflt: false, + + editType: 'plot', + + }, + width: { + valType: 'number', + min: 0, + max: 1, + dflt: 0.25, + + editType: 'plot', + + }, + fillcolor: { + valType: 'color', + + editType: 'style', + + }, + line: { + color: { + valType: 'color', + + editType: 'style', + + }, + width: { + valType: 'number', + min: 0, + + editType: 'style', + + }, + editType: 'style' + }, + editType: 'plot' + }, + + meanline: { + visible: { + valType: 'boolean', + dflt: false, + + editType: 'plot', + + }, + color: { + valType: 'color', + + editType: 'style', + + }, + width: { + valType: 'number', + min: 0, + + editType: 'style', + + }, + editType: 'plot' + }, + + side: { + valType: 'enumerated', + values: ['both', 'positive', 'negative'], + dflt: 'both', + + editType: 'plot', + + }, + + selected: boxAttrs.selected, + unselected: boxAttrs.unselected, + + hoveron: { + valType: 'flaglist', + flags: ['violins', 'points', 'kde'], + dflt: 'violins+points+kde', + extras: ['all'], + + editType: 'style', + + } +}; + +},{"../../lib/extend":685,"../box/attributes":859}],1145:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var boxCalc = _dereq_('../box/calc'); +var helpers = _dereq_('./helpers'); +var BADNUM = _dereq_('../../constants/numerical').BADNUM; + +module.exports = function calc(gd, trace) { + var cd = boxCalc(gd, trace); + + if(cd[0].t.empty) return cd; + + var fullLayout = gd._fullLayout; + var valAxis = Axes.getFromId( + gd, + trace[trace.orientation === 'h' ? 'xaxis' : 'yaxis'] + ); + + var violinScaleGroupStats = fullLayout._violinScaleGroupStats; + var scaleGroup = trace.scalegroup; + var groupStats = violinScaleGroupStats[scaleGroup]; + if(!groupStats) { + groupStats = violinScaleGroupStats[scaleGroup] = { + maxWidth: 0, + maxCount: 0 + }; + } + + var spanMin = Infinity; + var spanMax = -Infinity; + + for(var i = 0; i < cd.length; i++) { + var cdi = cd[i]; + var vals = cdi.pts.map(helpers.extractVal); + + var bandwidth = cdi.bandwidth = calcBandwidth(trace, cdi, vals); + var span = cdi.span = calcSpan(trace, cdi, valAxis, bandwidth); + + // step that well covers the bandwidth and is multiple of span distance + var dist = span[1] - span[0]; + var n = Math.ceil(dist / (bandwidth / 3)); + var step = dist / n; + + if(!isFinite(step) || !isFinite(n)) { + Lib.error('Something went wrong with computing the violin span'); + cd[0].t.empty = true; + return cd; + } + + var kde = helpers.makeKDE(cdi, trace, vals); + cdi.density = new Array(n); + + for(var k = 0, t = span[0]; t < (span[1] + step / 2); k++, t += step) { + var v = kde(t); + groupStats.maxWidth = Math.max(groupStats.maxWidth, v); + cdi.density[k] = {v: v, t: t}; + } + + groupStats.maxCount = Math.max(groupStats.maxCount, vals.length); + + spanMin = Math.min(spanMin, span[0]); + spanMax = Math.max(spanMax, span[1]); + } + + var extremes = Axes.findExtremes(valAxis, [spanMin, spanMax], {padded: true}); + trace._extremes[valAxis._id] = extremes; + + cd[0].t.labels.kde = Lib._(gd, 'kde:'); + + return cd; +}; + +// Default to Silveman's rule of thumb +// - https://stats.stackexchange.com/a/6671 +// - https://en.wikipedia.org/wiki/Kernel_density_estimation#A_rule-of-thumb_bandwidth_estimator +// - https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/bandwidths.py +function silvermanRule(len, ssd, iqr) { + var a = Math.min(ssd, iqr / 1.349); + return 1.059 * a * Math.pow(len, -0.2); +} + +function calcBandwidth(trace, cdi, vals) { + var span = cdi.max - cdi.min; + + // plot single-value violin with bandwidth of 1 + if(!span) return 1; + + // Limit how small the bandwidth can be. + // + // Silverman's rule of thumb can be "very" small + // when IQR does a poor job at describing the spread + // of the distribution. + // We also want to limit custom bandwidths + // to not blow up kde computations. + + if(trace.bandwidth) { + return Math.max(trace.bandwidth, span / 1e4); + } else { + var len = vals.length; + var ssd = Lib.stdev(vals, len - 1, cdi.mean); + return Math.max( + silvermanRule(len, ssd, cdi.q3 - cdi.q1), + span / 100 + ); + } +} + +function calcSpan(trace, cdi, valAxis, bandwidth) { + var spanmode = trace.spanmode; + var spanIn = trace.span || []; + var spanTight = [cdi.min, cdi.max]; + var spanLoose = [cdi.min - 2 * bandwidth, cdi.max + 2 * bandwidth]; + var spanOut; + + function calcSpanItem(index) { + var s = spanIn[index]; + var sc = valAxis.d2c(s, 0, trace[cdi.valLetter + 'calendar']); + return sc === BADNUM ? spanLoose[index] : sc; + } + + if(spanmode === 'soft') { + spanOut = spanLoose; + } else if(spanmode === 'hard') { + spanOut = spanTight; + } else { + spanOut = [calcSpanItem(0), calcSpanItem(1)]; + } + + // to reuse the equal-range-item block + var dummyAx = { + type: 'linear', + range: spanOut + }; + Axes.setConvert(dummyAx); + dummyAx.cleanRange(); + + return spanOut; +} + +},{"../../constants/numerical":673,"../../lib":696,"../../plots/cartesian/axes":744,"../box/calc":860,"./helpers":1148}],1146:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var setPositionOffset = _dereq_('../box/cross_trace_calc').setPositionOffset; +var orientations = ['v', 'h']; + +module.exports = function crossTraceCalc(gd, plotinfo) { + var calcdata = gd.calcdata; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + for(var i = 0; i < orientations.length; i++) { + var orientation = orientations[i]; + var posAxis = orientation === 'h' ? ya : xa; + var violinList = []; + var minPad = 0; + var maxPad = 0; + + for(var j = 0; j < calcdata.length; j++) { + var cd = calcdata[j]; + var t = cd[0].t; + var trace = cd[0].trace; + + if(trace.visible === true && trace.type === 'violin' && + !t.empty && + trace.orientation === orientation && + trace.xaxis === xa._id && + trace.yaxis === ya._id + ) { + violinList.push(j); + + if(trace.points !== false) { + minPad = Math.max(minPad, trace.jitter - trace.pointpos - 1); + maxPad = Math.max(maxPad, trace.jitter + trace.pointpos - 1); + } + } + } + + setPositionOffset('violin', gd, violinList, posAxis, [minPad, maxPad]); + } +}; + +},{"../box/cross_trace_calc":861}],1147:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Color = _dereq_('../../components/color'); + +var boxDefaults = _dereq_('../box/defaults'); +var attributes = _dereq_('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + function coerce2(attr, dflt) { + return Lib.coerce2(traceIn, traceOut, attributes, attr, dflt); + } + + boxDefaults.handleSampleDefaults(traceIn, traceOut, coerce, layout); + if(traceOut.visible === false) return; + + coerce('bandwidth'); + coerce('scalegroup', traceOut.name); + coerce('scalemode'); + coerce('side'); + + var span = coerce('span'); + var spanmodeDflt; + if(Array.isArray(span)) spanmodeDflt = 'manual'; + coerce('spanmode', spanmodeDflt); + + var lineColor = coerce('line.color', (traceIn.marker || {}).color || defaultColor); + var lineWidth = coerce('line.width'); + var fillColor = coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5)); + + boxDefaults.handlePointsDefaults(traceIn, traceOut, coerce, {prefix: ''}); + + var boxWidth = coerce2('box.width'); + var boxFillColor = coerce2('box.fillcolor', fillColor); + var boxLineColor = coerce2('box.line.color', lineColor); + var boxLineWidth = coerce2('box.line.width', lineWidth); + var boxVisible = coerce('box.visible', Boolean(boxWidth || boxFillColor || boxLineColor || boxLineWidth)); + if(!boxVisible) traceOut.box = {visible: false}; + + var meanLineColor = coerce2('meanline.color', lineColor); + var meanLineWidth = coerce2('meanline.width', lineWidth); + var meanLineVisible = coerce('meanline.visible', Boolean(meanLineColor || meanLineWidth)); + if(!meanLineVisible) traceOut.meanline = {visible: false}; +}; + +},{"../../components/color":570,"../../lib":696,"../box/defaults":862,"./attributes":1144}],1148:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); + +// Maybe add kernels more down the road, +// but note that the default `spanmode: 'soft'` bounds might have +// to become kernel-dependent +var kernels = { + gaussian: function(v) { + return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * v * v); + } +}; + +exports.makeKDE = function(calcItem, trace, vals) { + var len = vals.length; + var kernel = kernels.gaussian; + var bandwidth = calcItem.bandwidth; + var factor = 1 / (len * bandwidth); + + // don't use Lib.aggNums to skip isNumeric checks + return function(x) { + var sum = 0; + for(var i = 0; i < len; i++) { + sum += kernel((x - vals[i]) / bandwidth); + } + return factor * sum; + }; +}; + +exports.getPositionOnKdePath = function(calcItem, trace, valuePx) { + var posLetter, valLetter; + + if(trace.orientation === 'h') { + posLetter = 'y'; + valLetter = 'x'; + } else { + posLetter = 'x'; + valLetter = 'y'; + } + + var pointOnPath = Lib.findPointOnPath( + calcItem.path, + valuePx, + valLetter, + {pathLength: calcItem.pathLength} + ); + + var posCenterPx = calcItem.posCenterPx; + var posOnPath0 = pointOnPath[posLetter]; + var posOnPath1 = trace.side === 'both' ? + 2 * posCenterPx - posOnPath0 : + posCenterPx; + + return [posOnPath0, posOnPath1]; +}; + +exports.getKdeValue = function(calcItem, trace, valueDist) { + var vals = calcItem.pts.map(exports.extractVal); + var kde = exports.makeKDE(calcItem, trace, vals); + return kde(valueDist) / calcItem.posDensityScale; +}; + +exports.extractVal = function(o) { return o.v; }; + +},{"../../lib":696}],1149:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var Axes = _dereq_('../../plots/cartesian/axes'); +var boxHoverPoints = _dereq_('../box/hover'); +var helpers = _dereq_('./helpers'); + +module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) { + var cd = pointData.cd; + var trace = cd[0].trace; + var hoveron = trace.hoveron; + var hasHoveronViolins = hoveron.indexOf('violins') !== -1; + var hasHoveronKDE = hoveron.indexOf('kde') !== -1; + var closeData = []; + var closePtData; + var violinLineAttrs; + + if(hasHoveronViolins || hasHoveronKDE) { + var closeBoxData = boxHoverPoints.hoverOnBoxes(pointData, xval, yval, hovermode); + + if(hasHoveronViolins) { + closeData = closeData.concat(closeBoxData); + } + + if(hasHoveronKDE && closeBoxData.length > 0) { + var xa = pointData.xa; + var ya = pointData.ya; + var pLetter, vLetter, pAxis, vAxis, vVal; + + if(trace.orientation === 'h') { + vVal = xval; + pLetter = 'y'; + pAxis = ya; + vLetter = 'x'; + vAxis = xa; + } else { + vVal = yval; + pLetter = 'x'; + pAxis = xa; + vLetter = 'y'; + vAxis = ya; + } + + var di = cd[pointData.index]; + + if(vVal >= di.span[0] && vVal <= di.span[1]) { + var kdePointData = Lib.extendFlat({}, pointData); + var vValPx = vAxis.c2p(vVal, true); + var kdeVal = helpers.getKdeValue(di, trace, vVal); + var pOnPath = helpers.getPositionOnKdePath(di, trace, vValPx); + var paOffset = pAxis._offset; + var paLength = pAxis._length; + + kdePointData[pLetter + '0'] = pOnPath[0]; + kdePointData[pLetter + '1'] = pOnPath[1]; + kdePointData[vLetter + '0'] = kdePointData[vLetter + '1'] = vValPx; + kdePointData[vLetter + 'Label'] = vLetter + ': ' + Axes.hoverLabelText(vAxis, vVal) + ', ' + cd[0].t.labels.kde + ' ' + kdeVal.toFixed(3); + + // move the spike to the KDE point + kdePointData.spikeDistance = closeBoxData[0].spikeDistance; + var spikePosAttr = pLetter + 'Spike'; + kdePointData[spikePosAttr] = closeBoxData[0][spikePosAttr]; + closeBoxData[0].spikeDistance = undefined; + closeBoxData[0][spikePosAttr] = undefined; + + closeData.push(kdePointData); + + violinLineAttrs = {stroke: pointData.color}; + violinLineAttrs[pLetter + '1'] = Lib.constrain(paOffset + pOnPath[0], paOffset, paOffset + paLength); + violinLineAttrs[pLetter + '2'] = Lib.constrain(paOffset + pOnPath[1], paOffset, paOffset + paLength); + violinLineAttrs[vLetter + '1'] = violinLineAttrs[vLetter + '2'] = vAxis._offset + vValPx; + } + } + } + + if(hoveron.indexOf('points') !== -1) { + closePtData = boxHoverPoints.hoverOnPoints(pointData, xval, yval); + } + + // update violin line (if any) + var violinLine = hoverLayer.selectAll('.violinline-' + trace.uid) + .data(violinLineAttrs ? [0] : []); + violinLine.enter().append('line') + .classed('violinline-' + trace.uid, true) + .attr('stroke-width', 1.5); + violinLine.exit().remove(); + violinLine.attr(violinLineAttrs); + + // same combine logic as box hoverPoints + if(hovermode === 'closest') { + if(closePtData) return [closePtData]; + return closeData; + } + if(closePtData) { + closeData.push(closePtData); + return closeData; + } + return closeData; +}; + +},{"../../lib":696,"../../plots/cartesian/axes":744,"../box/hover":864,"./helpers":1148}],1150:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + attributes: _dereq_('./attributes'), + layoutAttributes: _dereq_('./layout_attributes'), + supplyDefaults: _dereq_('./defaults'), + supplyLayoutDefaults: _dereq_('./layout_defaults'), + calc: _dereq_('./calc'), + crossTraceCalc: _dereq_('./cross_trace_calc'), + plot: _dereq_('./plot'), + style: _dereq_('./style'), + styleOnSelect: _dereq_('../scatter/style').styleOnSelect, + hoverPoints: _dereq_('./hover'), + selectPoints: _dereq_('../box/select'), + + moduleType: 'trace', + name: 'violin', + basePlotModule: _dereq_('../../plots/cartesian'), + categories: ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'violinLayout', 'zoomScale'], + meta: { + + } +}; + +},{"../../plots/cartesian":756,"../box/select":869,"../scatter/style":1066,"./attributes":1144,"./calc":1145,"./cross_trace_calc":1146,"./defaults":1147,"./hover":1149,"./layout_attributes":1151,"./layout_defaults":1152,"./plot":1153,"./style":1154}],1151:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var boxLayoutAttrs = _dereq_('../box/layout_attributes'); +var extendFlat = _dereq_('../../lib').extendFlat; + +module.exports = { + violinmode: extendFlat({}, boxLayoutAttrs.boxmode, { + + }), + violingap: extendFlat({}, boxLayoutAttrs.boxgap, { + + }), + violingroupgap: extendFlat({}, boxLayoutAttrs.boxgroupgap, { + + }) +}; + +},{"../../lib":696,"../box/layout_attributes":866}],1152:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../../lib'); +var layoutAttributes = _dereq_('./layout_attributes'); +var boxLayoutDefaults = _dereq_('../box/layout_defaults'); + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + boxLayoutDefaults._supply(layoutIn, layoutOut, fullData, coerce, 'violin'); +}; + +},{"../../lib":696,"../box/layout_defaults":867,"./layout_attributes":1151}],1153:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Lib = _dereq_('../../lib'); +var Drawing = _dereq_('../../components/drawing'); + +var boxPlot = _dereq_('../box/plot'); +var linePoints = _dereq_('../scatter/line_points'); +var helpers = _dereq_('./helpers'); + +module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) { + var fullLayout = gd._fullLayout; + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + function makePath(pts) { + var segments = linePoints(pts, { + xaxis: xa, + yaxis: ya, + connectGaps: true, + baseTolerance: 0.75, + shape: 'spline', + simplify: true + }); + return Drawing.smoothopen(segments[0], 1); + } + + Lib.makeTraceGroups(violinLayer, cdViolins, 'trace violins').each(function(cd) { + var plotGroup = d3.select(this); + var cd0 = cd[0]; + var t = cd0.t; + var trace = cd0.trace; + if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; + var numViolins = fullLayout._numViolins; + var group = (fullLayout.violinmode === 'group' && numViolins > 1); + var groupFraction = 1 - fullLayout.violingap; + // violin max half width + var bdPos = t.bdPos = t.dPos * groupFraction * (1 - fullLayout.violingroupgap) / (group ? numViolins : 1); + // violin center offset + var bPos = t.bPos = group ? 2 * t.dPos * (-0.5 + (t.num + 0.5) / numViolins) * groupFraction : 0; + // half-width within which to accept hover for this violin + // always split the distance to the closest violin + t.wHover = t.dPos * (group ? groupFraction / numViolins : 1); + + if(trace.visible !== true || t.empty) { + plotGroup.remove(); + return; + } + + var valAxis = plotinfo[t.valLetter + 'axis']; + var posAxis = plotinfo[t.posLetter + 'axis']; + var hasBothSides = trace.side === 'both'; + var hasPositiveSide = hasBothSides || trace.side === 'positive'; + var hasNegativeSide = hasBothSides || trace.side === 'negative'; + var groupStats = fullLayout._violinScaleGroupStats[trace.scalegroup]; + + var violins = plotGroup.selectAll('path.violin').data(Lib.identity); + + violins.enter().append('path') + .style('vector-effect', 'non-scaling-stroke') + .attr('class', 'violin'); + + violins.exit().remove(); + + violins.each(function(d) { + var pathSel = d3.select(this); + var density = d.density; + var len = density.length; + var posCenter = d.pos + bPos; + var posCenterPx = posAxis.c2p(posCenter); + var scale; + + switch(trace.scalemode) { + case 'width': + scale = groupStats.maxWidth / bdPos; + break; + case 'count': + scale = (groupStats.maxWidth / bdPos) * (groupStats.maxCount / d.pts.length); + break; + } + + var pathPos, pathNeg, path; + var i, k, pts, pt; + + if(hasPositiveSide) { + pts = new Array(len); + for(i = 0; i < len; i++) { + pt = pts[i] = {}; + pt[t.posLetter] = posCenter + (density[i].v / scale); + pt[t.valLetter] = density[i].t; + } + pathPos = makePath(pts); + } + + if(hasNegativeSide) { + pts = new Array(len); + for(k = 0, i = len - 1; k < len; k++, i--) { + pt = pts[k] = {}; + pt[t.posLetter] = posCenter - (density[i].v / scale); + pt[t.valLetter] = density[i].t; + } + pathNeg = makePath(pts); + } + + if(hasBothSides) { + path = pathPos + 'L' + pathNeg.substr(1) + 'Z'; + } + else { + var startPt = [posCenterPx, valAxis.c2p(density[0].t)]; + var endPt = [posCenterPx, valAxis.c2p(density[len - 1].t)]; + + if(trace.orientation === 'h') { + startPt.reverse(); + endPt.reverse(); + } + + if(hasPositiveSide) { + path = 'M' + startPt + 'L' + pathPos.substr(1) + 'L' + endPt; + } else { + path = 'M' + endPt + 'L' + pathNeg.substr(1) + 'L' + startPt; + } + } + pathSel.attr('d', path); + + // save a few things used in getPositionOnKdePath, getKdeValue + // on hover and for meanline draw block below + d.posCenterPx = posCenterPx; + d.posDensityScale = scale * bdPos; + d.path = pathSel.node(); + d.pathLength = d.path.getTotalLength() / (hasBothSides ? 2 : 1); + }); + + var boxAttrs = trace.box; + var boxWidth = boxAttrs.width; + var boxLineWidth = (boxAttrs.line || {}).width; + var bdPosScaled; + var bPosPxOffset; + + if(hasBothSides) { + bdPosScaled = bdPos * boxWidth; + bPosPxOffset = 0; + } else if(hasPositiveSide) { + bdPosScaled = [0, bdPos * boxWidth / 2]; + bPosPxOffset = -boxLineWidth; + } else { + bdPosScaled = [bdPos * boxWidth / 2, 0]; + bPosPxOffset = boxLineWidth; + } + + // inner box + boxPlot.plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, { + bPos: bPos, + bdPos: bdPosScaled, + bPosPxOffset: bPosPxOffset + }); + + // meanline insider box + boxPlot.plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, { + bPos: bPos, + bdPos: bdPosScaled, + bPosPxOffset: bPosPxOffset + }); + + var fn; + if(!trace.box.visible && trace.meanline.visible) { + fn = Lib.identity; + } + + // N.B. use different class name than boxPlot.plotBoxMean, + // to avoid selectAll conflict + var meanPaths = plotGroup.selectAll('path.meanline').data(fn || []); + meanPaths.enter().append('path') + .attr('class', 'meanline') + .style('fill', 'none') + .style('vector-effect', 'non-scaling-stroke'); + meanPaths.exit().remove(); + meanPaths.each(function(d) { + var v = valAxis.c2p(d.mean, true); + var p = helpers.getPositionOnKdePath(d, trace, v); + + d3.select(this).attr('d', + trace.orientation === 'h' ? + 'M' + v + ',' + p[0] + 'V' + p[1] : + 'M' + p[0] + ',' + v + 'H' + p[1] + ); + }); + + boxPlot.plotPoints(plotGroup, {x: xa, y: ya}, trace, t); + }); +}; + +},{"../../components/drawing":595,"../../lib":696,"../box/plot":868,"../scatter/line_points":1057,"./helpers":1148,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1154:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = _dereq_("/home/circleci/plotly.js/test/image/strict-d3.js"); +var Color = _dereq_('../../components/color'); +var stylePoints = _dereq_('../scatter/style').stylePoints; + +module.exports = function style(gd, cd) { + var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.violins'); + + s.style('opacity', function(d) { return d[0].trace.opacity; }); + + s.each(function(d) { + var trace = d[0].trace; + var sel = d3.select(this); + var box = trace.box || {}; + var boxLine = box.line || {}; + var meanline = trace.meanline || {}; + var meanLineWidth = meanline.width; + + sel.selectAll('path.violin') + .style('stroke-width', trace.line.width + 'px') + .call(Color.stroke, trace.line.color) + .call(Color.fill, trace.fillcolor); + + sel.selectAll('path.box') + .style('stroke-width', boxLine.width + 'px') + .call(Color.stroke, boxLine.color) + .call(Color.fill, box.fillcolor); + + var meanLineStyle = { + 'stroke-width': meanLineWidth + 'px', + 'stroke-dasharray': (2 * meanLineWidth) + 'px,' + meanLineWidth + 'px' + }; + + sel.selectAll('path.mean') + .style(meanLineStyle) + .call(Color.stroke, meanline.color); + + sel.selectAll('path.meanline') + .style(meanLineStyle) + .call(Color.stroke, meanline.color); + + stylePoints(sel, trace, gd); + }); +}; + +},{"../../components/color":570,"../scatter/style":1066,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1155:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Axes = _dereq_('../plots/cartesian/axes'); +var Lib = _dereq_('../lib'); +var PlotSchema = _dereq_('../plot_api/plot_schema'); +var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; +var BADNUM = _dereq_('../constants/numerical').BADNUM; + +exports.moduleType = 'transform'; + +exports.name = 'aggregate'; + +var attrs = exports.attributes = { + enabled: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + groups: { + // TODO: groupby should support string or array grouping this way too + // currently groupby only allows a grouping array + valType: 'string', + strict: true, + noBlank: true, + arrayOk: true, + dflt: 'x', + + editType: 'calc', + + }, + aggregations: { + _isLinkedToArray: 'aggregation', + target: { + valType: 'string', + + editType: 'calc', + + }, + func: { + valType: 'enumerated', + values: ['count', 'sum', 'avg', 'median', 'mode', 'rms', 'stddev', 'min', 'max', 'first', 'last', 'change', 'range'], + dflt: 'first', + + editType: 'calc', + + }, + funcmode: { + valType: 'enumerated', + values: ['sample', 'population'], + dflt: 'sample', + + editType: 'calc', + + }, + enabled: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + editType: 'calc' + }, + editType: 'calc' +}; + +var aggAttrs = attrs.aggregations; + +/** + * Supply transform attributes defaults + * + * @param {object} transformIn + * object linked to trace.transforms[i] with 'func' set to exports.name + * @param {object} traceOut + * the _fullData trace this transform applies to + * @param {object} layout + * the plot's (not-so-full) layout + * @param {object} traceIn + * the input data trace this transform applies to + * + * @return {object} transformOut + * copy of transformIn that contains attribute defaults + */ +exports.supplyDefaults = function(transformIn, traceOut) { + var transformOut = {}; + var i; + + function coerce(attr, dflt) { + return Lib.coerce(transformIn, transformOut, attrs, attr, dflt); + } + + var enabled = coerce('enabled'); + + if(!enabled) return transformOut; + + /* + * Normally _arrayAttrs is calculated during doCalc, but that comes later. + * Anyway this can change due to *count* aggregations (see below) so it's not + * necessarily the same set. + * + * For performance we turn it into an object of truthy values + * we'll use 1 for arrays we haven't aggregated yet, 0 for finished arrays, + * as distinct from undefined which means this array isn't present in the input + * missing arrays can still be aggregate outputs for *count* aggregations. + */ + var arrayAttrArray = PlotSchema.findArrayAttributes(traceOut); + var arrayAttrs = {}; + for(i = 0; i < arrayAttrArray.length; i++) arrayAttrs[arrayAttrArray[i]] = 1; + + var groups = coerce('groups'); + + if(!Array.isArray(groups)) { + if(!arrayAttrs[groups]) { + transformOut.enabled = false; + return transformOut; + } + arrayAttrs[groups] = 0; + } + + var aggregationsIn = transformIn.aggregations || []; + var aggregationsOut = transformOut.aggregations = new Array(aggregationsIn.length); + var aggregationOut; + + function coercei(attr, dflt) { + return Lib.coerce(aggregationsIn[i], aggregationOut, aggAttrs, attr, dflt); + } + + for(i = 0; i < aggregationsIn.length; i++) { + aggregationOut = {_index: i}; + var target = coercei('target'); + var func = coercei('func'); + var enabledi = coercei('enabled'); + + // add this aggregation to the output only if it's the first instance + // of a valid target attribute - or an unused target attribute with "count" + if(enabledi && target && (arrayAttrs[target] || (func === 'count' && arrayAttrs[target] === undefined))) { + if(func === 'stddev') coercei('funcmode'); + + arrayAttrs[target] = 0; + aggregationsOut[i] = aggregationOut; + } + else aggregationsOut[i] = {enabled: false, _index: i}; + } + + // any array attributes we haven't yet covered, fill them with the default aggregation + for(i = 0; i < arrayAttrArray.length; i++) { + if(arrayAttrs[arrayAttrArray[i]]) { + aggregationsOut.push({ + target: arrayAttrArray[i], + func: aggAttrs.func.dflt, + enabled: true, + _index: -1 + }); + } + } + + return transformOut; +}; + + +exports.calcTransform = function(gd, trace, opts) { + if(!opts.enabled) return; + + var groups = opts.groups; + + var groupArray = Lib.getTargetArray(trace, {target: groups}); + if(!groupArray) return; + + var i, vi, groupIndex, newGrouping; + + var groupIndices = {}; + var indexToPoints = {}; + var groupings = []; + + var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); + + var len = groupArray.length; + if(trace._length) len = Math.min(len, trace._length); + + for(i = 0; i < len; i++) { + vi = groupArray[i]; + groupIndex = groupIndices[vi]; + if(groupIndex === undefined) { + groupIndices[vi] = groupings.length; + newGrouping = [i]; + groupings.push(newGrouping); + indexToPoints[groupIndices[vi]] = originalPointsAccessor(i); + } + else { + groupings[groupIndex].push(i); + indexToPoints[groupIndices[vi]] = (indexToPoints[groupIndices[vi]] || []).concat(originalPointsAccessor(i)); + } + } + + opts._indexToPoints = indexToPoints; + + var aggregations = opts.aggregations; + + for(i = 0; i < aggregations.length; i++) { + aggregateOneArray(gd, trace, groupings, aggregations[i]); + } + + if(typeof groups === 'string') { + aggregateOneArray(gd, trace, groupings, { + target: groups, + func: 'first', + enabled: true + }); + } + + trace._length = groupings.length; +}; + +function aggregateOneArray(gd, trace, groupings, aggregation) { + if(!aggregation.enabled) return; + + var attr = aggregation.target; + var targetNP = Lib.nestedProperty(trace, attr); + var arrayIn = targetNP.get(); + var conversions = Axes.getDataConversions(gd, trace, attr, arrayIn); + var func = getAggregateFunction(aggregation, conversions); + + var arrayOut = new Array(groupings.length); + for(var i = 0; i < groupings.length; i++) { + arrayOut[i] = func(arrayIn, groupings[i]); + } + targetNP.set(arrayOut); + + if(aggregation.func === 'count') { + // count does not depend on an input array, so it's likely not part of _arrayAttrs yet + // but after this transform it most definitely *is* an array attribute. + Lib.pushUnique(trace._arrayAttrs, attr); + } +} + +function getAggregateFunction(opts, conversions) { + var func = opts.func; + var d2c = conversions.d2c; + var c2d = conversions.c2d; + + switch(func) { + // count, first, and last don't depend on anything about the data + // point back to pure functions for performance + case 'count': + return count; + case 'first': + return first; + case 'last': + return last; + + case 'sum': + // This will produce output in all cases even though it's nonsensical + // for date or category data. + return function(array, indices) { + var total = 0; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) total += vi; + } + return c2d(total); + }; + + case 'avg': + // Generally meaningless for category data but it still does something. + return function(array, indices) { + var total = 0; + var cnt = 0; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) { + total += vi; + cnt++; + } + } + return cnt ? c2d(total / cnt) : BADNUM; + }; + + case 'min': + return function(array, indices) { + var out = Infinity; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) out = Math.min(out, vi); + } + return (out === Infinity) ? BADNUM : c2d(out); + }; + + case 'max': + return function(array, indices) { + var out = -Infinity; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) out = Math.max(out, vi); + } + return (out === -Infinity) ? BADNUM : c2d(out); + }; + + case 'range': + return function(array, indices) { + var min = Infinity; + var max = -Infinity; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) { + min = Math.min(min, vi); + max = Math.max(max, vi); + } + } + return (max === -Infinity || min === Infinity) ? BADNUM : c2d(max - min); + }; + + case 'change': + return function(array, indices) { + var first = d2c(array[indices[0]]); + var last = d2c(array[indices[indices.length - 1]]); + return (first === BADNUM || last === BADNUM) ? BADNUM : c2d(last - first); + }; + + case 'median': + return function(array, indices) { + var sortCalc = []; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) sortCalc.push(vi); + } + if(!sortCalc.length) return BADNUM; + sortCalc.sort(); + var mid = (sortCalc.length - 1) / 2; + return c2d((sortCalc[Math.floor(mid)] + sortCalc[Math.ceil(mid)]) / 2); + }; + + case 'mode': + return function(array, indices) { + var counts = {}; + var maxCnt = 0; + var out = BADNUM; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) { + var counti = counts[vi] = (counts[vi] || 0) + 1; + if(counti > maxCnt) { + maxCnt = counti; + out = vi; + } + } + } + return maxCnt ? c2d(out) : BADNUM; + }; + + case 'rms': + return function(array, indices) { + var total = 0; + var cnt = 0; + for(var i = 0; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) { + total += vi * vi; + cnt++; + } + } + return cnt ? c2d(Math.sqrt(total / cnt)) : BADNUM; + }; + + case 'stddev': + return function(array, indices) { + // balance numerical stability with performance: + // so that we call d2c once per element but don't need to + // store them, reference all to the first element + var total = 0; + var total2 = 0; + var cnt = 1; + var v0 = BADNUM; + var i; + for(i = 0; i < indices.length && v0 === BADNUM; i++) { + v0 = d2c(array[indices[i]]); + } + if(v0 === BADNUM) return BADNUM; + + for(; i < indices.length; i++) { + var vi = d2c(array[indices[i]]); + if(vi !== BADNUM) { + var dv = vi - v0; + total += dv; + total2 += dv * dv; + cnt++; + } + } + + // This is population std dev, if we want sample std dev + // we would need (...) / (cnt - 1) + // Also note there's no c2d here - that means for dates the result + // is a number of milliseconds, and for categories it's a number + // of category differences, which is not generically meaningful but + // as in other cases we don't forbid it. + var norm = (opts.funcmode === 'sample') ? (cnt - 1) : cnt; + // this is debatable: should a count of 1 return sample stddev of + // 0 or undefined? + if(!norm) return 0; + return Math.sqrt((total2 - (total * total / cnt)) / norm); + }; + } +} + +function count(array, indices) { + return indices.length; +} + +function first(array, indices) { + return array[indices[0]]; +} + +function last(array, indices) { + return array[indices[indices.length - 1]]; +} + +},{"../constants/numerical":673,"../lib":696,"../plot_api/plot_schema":733,"../plots/cartesian/axes":744,"./helpers":1158}],1156:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var Registry = _dereq_('../registry'); +var Axes = _dereq_('../plots/cartesian/axes'); +var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; + +var filterOps = _dereq_('../constants/filter_ops'); +var COMPARISON_OPS = filterOps.COMPARISON_OPS; +var INTERVAL_OPS = filterOps.INTERVAL_OPS; +var SET_OPS = filterOps.SET_OPS; + +exports.moduleType = 'transform'; + +exports.name = 'filter'; + +exports.attributes = { + enabled: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + target: { + valType: 'string', + strict: true, + noBlank: true, + arrayOk: true, + dflt: 'x', + + editType: 'calc', + + }, + operation: { + valType: 'enumerated', + values: [] + .concat(COMPARISON_OPS) + .concat(INTERVAL_OPS) + .concat(SET_OPS), + dflt: '=', + + editType: 'calc', + + }, + value: { + valType: 'any', + dflt: 0, + + editType: 'calc', + + }, + preservegaps: { + valType: 'boolean', + dflt: false, + + editType: 'calc', + + }, + editType: 'calc' +}; + +exports.supplyDefaults = function(transformIn) { + var transformOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); + } + + var enabled = coerce('enabled'); + + if(enabled) { + coerce('preservegaps'); + coerce('operation'); + coerce('value'); + coerce('target'); + + var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); + handleCalendarDefaults(transformIn, transformOut, 'valuecalendar', null); + handleCalendarDefaults(transformIn, transformOut, 'targetcalendar', null); + } + + return transformOut; +}; + +exports.calcTransform = function(gd, trace, opts) { + if(!opts.enabled) return; + + var targetArray = Lib.getTargetArray(trace, opts); + if(!targetArray) return; + + var target = opts.target; + + var len = targetArray.length; + if(trace._length) len = Math.min(len, trace._length); + + var targetCalendar = opts.targetcalendar; + var arrayAttrs = trace._arrayAttrs; + var preservegaps = opts.preservegaps; + + // even if you provide targetcalendar, if target is a string and there + // is a calendar attribute matching target it will get used instead. + if(typeof target === 'string') { + var attrTargetCalendar = Lib.nestedProperty(trace, target + 'calendar').get(); + if(attrTargetCalendar) targetCalendar = attrTargetCalendar; + } + + var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray); + var filterFunc = getFilterFunc(opts, d2c, targetCalendar); + var originalArrays = {}; + var indexToPoints = {}; + var index = 0; + + function forAllAttrs(fn, index) { + for(var j = 0; j < arrayAttrs.length; j++) { + var np = Lib.nestedProperty(trace, arrayAttrs[j]); + fn(np, index); + } + } + + var initFn; + var fillFn; + if(preservegaps) { + initFn = function(np) { + originalArrays[np.astr] = Lib.extendDeep([], np.get()); + np.set(new Array(len)); + }; + fillFn = function(np, index) { + var val = originalArrays[np.astr][index]; + np.get()[index] = val; + }; + } else { + initFn = function(np) { + originalArrays[np.astr] = Lib.extendDeep([], np.get()); + np.set([]); + }; + fillFn = function(np, index) { + var val = originalArrays[np.astr][index]; + np.get().push(val); + }; + } + + // copy all original array attribute values, and clear arrays in trace + forAllAttrs(initFn); + + var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); + + // loop through filter array, fill trace arrays if passed + for(var i = 0; i < len; i++) { + var passed = filterFunc(targetArray[i]); + if(passed) { + forAllAttrs(fillFn, i); + indexToPoints[index++] = originalPointsAccessor(i); + } + else if(preservegaps) index++; + } + + opts._indexToPoints = indexToPoints; + trace._length = index; +}; + +function getFilterFunc(opts, d2c, targetCalendar) { + var operation = opts.operation, + value = opts.value, + hasArrayValue = Array.isArray(value); + + function isOperationIn(array) { + return array.indexOf(operation) !== -1; + } + + var d2cValue = function(v) { return d2c(v, 0, opts.valuecalendar); }, + d2cTarget = function(v) { return d2c(v, 0, targetCalendar); }; + + var coercedValue; + + if(isOperationIn(COMPARISON_OPS)) { + coercedValue = hasArrayValue ? d2cValue(value[0]) : d2cValue(value); + } + else if(isOperationIn(INTERVAL_OPS)) { + coercedValue = hasArrayValue ? + [d2cValue(value[0]), d2cValue(value[1])] : + [d2cValue(value), d2cValue(value)]; + } + else if(isOperationIn(SET_OPS)) { + coercedValue = hasArrayValue ? value.map(d2cValue) : [d2cValue(value)]; + } + + switch(operation) { + + case '=': + return function(v) { return d2cTarget(v) === coercedValue; }; + + case '!=': + return function(v) { return d2cTarget(v) !== coercedValue; }; + + case '<': + return function(v) { return d2cTarget(v) < coercedValue; }; + + case '<=': + return function(v) { return d2cTarget(v) <= coercedValue; }; + + case '>': + return function(v) { return d2cTarget(v) > coercedValue; }; + + case '>=': + return function(v) { return d2cTarget(v) >= coercedValue; }; + + case '[]': + return function(v) { + var cv = d2cTarget(v); + return cv >= coercedValue[0] && cv <= coercedValue[1]; + }; + + case '()': + return function(v) { + var cv = d2cTarget(v); + return cv > coercedValue[0] && cv < coercedValue[1]; + }; + + case '[)': + return function(v) { + var cv = d2cTarget(v); + return cv >= coercedValue[0] && cv < coercedValue[1]; + }; + + case '(]': + return function(v) { + var cv = d2cTarget(v); + return cv > coercedValue[0] && cv <= coercedValue[1]; + }; + + case '][': + return function(v) { + var cv = d2cTarget(v); + return cv <= coercedValue[0] || cv >= coercedValue[1]; + }; + + case ')(': + return function(v) { + var cv = d2cTarget(v); + return cv < coercedValue[0] || cv > coercedValue[1]; + }; + + case '](': + return function(v) { + var cv = d2cTarget(v); + return cv <= coercedValue[0] || cv > coercedValue[1]; + }; + + case ')[': + return function(v) { + var cv = d2cTarget(v); + return cv < coercedValue[0] || cv >= coercedValue[1]; + }; + + case '{}': + return function(v) { + return coercedValue.indexOf(d2cTarget(v)) !== -1; + }; + + case '}{': + return function(v) { + return coercedValue.indexOf(d2cTarget(v)) === -1; + }; + } +} + +},{"../constants/filter_ops":669,"../lib":696,"../plots/cartesian/axes":744,"../registry":827,"./helpers":1158}],1157:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var PlotSchema = _dereq_('../plot_api/plot_schema'); +var Plots = _dereq_('../plots/plots'); +var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; + +exports.moduleType = 'transform'; + +exports.name = 'groupby'; + +exports.attributes = { + enabled: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + groups: { + valType: 'data_array', + dflt: [], + + editType: 'calc', + + }, + nameformat: { + valType: 'string', + + editType: 'calc', + + }, + styles: { + _isLinkedToArray: 'style', + target: { + valType: 'string', + + editType: 'calc', + + }, + value: { + valType: 'any', + + dflt: {}, + editType: 'calc', + + _compareAsJSON: true + }, + editType: 'calc' + }, + editType: 'calc' +}; + +/** + * Supply transform attributes defaults + * + * @param {object} transformIn + * object linked to trace.transforms[i] with 'type' set to exports.name + * @param {object} traceOut + * the _fullData trace this transform applies to + * @param {object} layout + * the plot's (not-so-full) layout + * @param {object} traceIn + * the input data trace this transform applies to + * + * @return {object} transformOut + * copy of transformIn that contains attribute defaults + */ +exports.supplyDefaults = function(transformIn, traceOut, layout) { + var i; + var transformOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); + } + + var enabled = coerce('enabled'); + + if(!enabled) return transformOut; + + coerce('groups'); + coerce('nameformat', layout._dataLength > 1 ? '%{group} (%{trace})' : '%{group}'); + + var styleIn = transformIn.styles; + var styleOut = transformOut.styles = []; + + if(styleIn) { + for(i = 0; i < styleIn.length; i++) { + var thisStyle = styleOut[i] = {}; + Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'target'); + var value = Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'value'); + + // so that you can edit value in place and have Plotly.react notice it, or + // rebuild it every time and have Plotly.react NOT think it changed: + // use _compareAsJSON to say we should diff the _JSON_value + if(Lib.isPlainObject(value)) thisStyle.value = Lib.extendDeep({}, value); + else if(value) delete thisStyle.value; + } + } + + return transformOut; +}; + + +/** + * Apply transform !!! + * + * @param {array} data + * array of transformed traces (is [fullTrace] upon first transform) + * + * @param {object} state + * state object which includes: + * - transform {object} full transform attributes + * - fullTrace {object} full trace object which is being transformed + * - fullData {array} full pre-transform(s) data array + * - layout {object} the plot's (not-so-full) layout + * + * @return {object} newData + * array of transformed traces + */ +exports.transform = function(data, state) { + var newTraces, i, j; + var newData = []; + + for(i = 0; i < data.length; i++) { + newTraces = transformOne(data[i], state); + + for(j = 0; j < newTraces.length; j++) { + newData.push(newTraces[j]); + } + } + + return newData; +}; + +function transformOne(trace, state) { + var i, j, k, attr, srcArray, groupName, newTrace, transforms, arrayLookup; + var groupNameObj; + + var opts = state.transform; + var transformIndex = state.transformIndex; + var groups = trace.transforms[transformIndex].groups; + var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); + + if(!(Array.isArray(groups)) || groups.length === 0) { + return [trace]; + } + + var groupNames = Lib.filterUnique(groups), + newData = new Array(groupNames.length), + len = groups.length; + + var arrayAttrs = PlotSchema.findArrayAttributes(trace); + + var styles = opts.styles || []; + var styleLookup = {}; + for(i = 0; i < styles.length; i++) { + styleLookup[styles[i].target] = styles[i].value; + } + + if(opts.styles) { + groupNameObj = Lib.keyedContainer(opts, 'styles', 'target', 'value.name'); + } + + // An index to map group name --> expanded trace index + var indexLookup = {}; + var indexCnts = {}; + + for(i = 0; i < groupNames.length; i++) { + groupName = groupNames[i]; + indexLookup[groupName] = i; + indexCnts[groupName] = 0; + + // Start with a deep extend that just copies array references. + newTrace = newData[i] = Lib.extendDeepNoArrays({}, trace); + newTrace._group = groupName; + // helper function for when we need to push updates back to the input, + // outside of the normal restyle/relayout pathway, like filling in auto values + newTrace.updateStyle = styleUpdater(groupName, transformIndex); + newTrace.transforms[transformIndex]._indexToPoints = {}; + + var suppliedName = null; + if(groupNameObj) { + suppliedName = groupNameObj.get(groupName); + } + + if(suppliedName || suppliedName === '') { + newTrace.name = suppliedName; + } else { + newTrace.name = Lib.templateString(opts.nameformat, { + trace: trace.name, + group: groupName + }); + } + + // In order for groups to apply correctly to other transform data (e.g. + // a filter transform), we have to break the connection and clone the + // transforms so that each group writes grouped values into a different + // destination. This function does not break the array reference + // connection between the split transforms it creates. That's handled in + // initialize, which creates a new empty array for each arrayAttr. + transforms = newTrace.transforms; + newTrace.transforms = []; + for(j = 0; j < transforms.length; j++) { + newTrace.transforms[j] = Lib.extendDeepNoArrays({}, transforms[j]); + } + + // Initialize empty arrays for the arrayAttrs, to be split in the next step + for(j = 0; j < arrayAttrs.length; j++) { + Lib.nestedProperty(newTrace, arrayAttrs[j]).set([]); + } + } + + // For each array attribute including those nested inside this and other + // transforms (small note that we technically only need to do this for + // transforms that have not yet been applied): + for(k = 0; k < arrayAttrs.length; k++) { + attr = arrayAttrs[k]; + + // Cache all the arrays to which we'll push: + for(j = 0, arrayLookup = []; j < groupNames.length; j++) { + arrayLookup[j] = Lib.nestedProperty(newData[j], attr).get(); + } + + // Get the input data: + srcArray = Lib.nestedProperty(trace, attr).get(); + + // Send each data point to the appropriate expanded trace: + for(j = 0; j < len; j++) { + // Map group data --> trace index --> array and push data onto it + arrayLookup[indexLookup[groups[j]]].push(srcArray[j]); + } + } + + for(j = 0; j < len; j++) { + newTrace = newData[indexLookup[groups[j]]]; + + var indexToPoints = newTrace.transforms[transformIndex]._indexToPoints; + indexToPoints[indexCnts[groups[j]]] = originalPointsAccessor(j); + indexCnts[groups[j]]++; + } + + for(i = 0; i < groupNames.length; i++) { + groupName = groupNames[i]; + newTrace = newData[i]; + + Plots.clearExpandedTraceDefaultColors(newTrace); + + // there's no need to coerce styleLookup[groupName] here + // as another round of supplyDefaults is done on the transformed traces + newTrace = Lib.extendDeepNoArrays(newTrace, styleLookup[groupName] || {}); + } + + return newData; +} + +function styleUpdater(groupName, transformIndex) { + return function(trace, attr, value) { + Lib.keyedContainer( + trace, + 'transforms[' + transformIndex + '].styles', + 'target', + 'value.' + attr + ).set(String(groupName), value); + }; +} + +},{"../lib":696,"../plot_api/plot_schema":733,"../plots/plots":808,"./helpers":1158}],1158:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +exports.pointsAccessorFunction = function(transforms, opts) { + var tr; + var prevIndexToPoints; + for(var i = 0; i < transforms.length; i++) { + tr = transforms[i]; + if(tr === opts) break; + if(!tr._indexToPoints || tr.enabled === false) continue; + prevIndexToPoints = tr._indexToPoints; + } + var originalPointsAccessor = prevIndexToPoints ? + function(i) {return prevIndexToPoints[i];} : + function(i) {return [i];}; + return originalPointsAccessor; +}; + +},{}],1159:[function(_dereq_,module,exports){ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = _dereq_('../lib'); +var Axes = _dereq_('../plots/cartesian/axes'); +var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; + +exports.moduleType = 'transform'; + +exports.name = 'sort'; + +exports.attributes = { + enabled: { + valType: 'boolean', + dflt: true, + + editType: 'calc', + + }, + target: { + valType: 'string', + strict: true, + noBlank: true, + arrayOk: true, + dflt: 'x', + + editType: 'calc', + + }, + order: { + valType: 'enumerated', + values: ['ascending', 'descending'], + dflt: 'ascending', + + editType: 'calc', + + }, + editType: 'calc' +}; + +exports.supplyDefaults = function(transformIn) { + var transformOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); + } + + var enabled = coerce('enabled'); + + if(enabled) { + coerce('target'); + coerce('order'); + } + + return transformOut; +}; + +exports.calcTransform = function(gd, trace, opts) { + if(!opts.enabled) return; + + var targetArray = Lib.getTargetArray(trace, opts); + if(!targetArray) return; + + var target = opts.target; + + var len = targetArray.length; + if(trace._length) len = Math.min(len, trace._length); + + var arrayAttrs = trace._arrayAttrs; + var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray); + var indices = getIndices(opts, targetArray, d2c, len); + var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); + var indexToPoints = {}; + var i, j; + + for(i = 0; i < arrayAttrs.length; i++) { + var np = Lib.nestedProperty(trace, arrayAttrs[i]); + var arrayOld = np.get(); + var arrayNew = new Array(len); + + for(j = 0; j < len; j++) { + arrayNew[j] = arrayOld[indices[j]]; + } + + np.set(arrayNew); + } + + for(j = 0; j < len; j++) { + indexToPoints[j] = originalPointsAccessor(indices[j]); + } + + opts._indexToPoints = indexToPoints; + trace._length = len; +}; + +function getIndices(opts, targetArray, d2c, len) { + var sortedArray = new Array(len); + var indices = new Array(len); + var i; + + for(i = 0; i < len; i++) { + sortedArray[i] = {v: targetArray[i], i: i}; + } + + sortedArray.sort(getSortFunc(opts, d2c)); + + for(i = 0; i < len; i++) { + indices[i] = sortedArray[i].i; + } + + return indices; +} + +function getSortFunc(opts, d2c) { + switch(opts.order) { + case 'ascending': + return function(a, b) { return d2c(a.v) - d2c(b.v); }; + case 'descending': + return function(a, b) { return d2c(b.v) - d2c(a.v); }; + } +} + +},{"../lib":696,"../plots/cartesian/axes":744,"./helpers":1158}],1160:[function(_dereq_,module,exports){ +/* + * strict-d3: wrap selection.style to prohibit specific incorrect style values + * that are known to cause problems in IE (at least IE9) + */ +'use strict'; + +var d3 = _dereq_('d3'); +var isNumeric = _dereq_('fast-isnumeric'); + +var selProto = d3.selection.prototype; +var originalSelAttr = selProto.attr; +var originalSelStyle = selProto.style; + +selProto.attr = function() { + var sel = this; + var obj = arguments[0]; + + if(sel.size()) { + if(typeof obj === 'string') { + checkAttrVal(sel, obj, arguments[1]); + } else { + Object.keys(obj).forEach(function(key) { checkAttrVal(sel, key, obj[key]); }); + } + } + + return originalSelAttr.apply(sel, arguments); +}; + +selProto.style = function() { + var sel = this; + var obj = arguments[0]; + + if(sel.size()) { + if(typeof obj === 'string') { + if(arguments.length === 1 && !d3.event) { + throw new Error('d3 selection.style called as getter: ' + + 'disallowed outside event handlers as it can fail for ' + + 'unattached elements. Use node.style.attribute instead.'); + } + checkStyleVal(sel, obj, arguments[1]); + } else { + Object.keys(obj).forEach(function(key) { checkStyleVal(sel, key, obj[key]); }); + } + } + + return originalSelStyle.apply(sel, arguments); +}; + +function checkAttrVal(sel, key, val) { + // setting the transform attribute on a does not + // work in Chrome, IE and Edge + if(sel.node().nodeName === 'clipPath' && key === 'transform') { + throw new Error('d3 selection.attr called with key \'transform\' on a clipPath node'); + } + + // make sure no double-negative string get into the DOM, + // their handling differs from browsers to browsers + if(/--/.test(val) && isNumeric(val.split('--')[1].charAt(0))) { + throw new Error('d3 selection.attr called with value ' + val + ' which includes a double negative'); + } +} + +function checkStyleVal(sel, key, val) { + if(typeof val === 'string') { + // in case of multipart styles (stroke-dasharray, margins, etc) + // test each part separately + val.split(/[, ]/g).forEach(function(valPart) { + var pxSplit = valPart.length - 2; + if(valPart.substr(pxSplit) === 'px' && !isNumeric(valPart.substr(0, pxSplit))) { + throw new Error('d3 selection.style called with value: ' + val); + } + }); + } + + // Microsoft browsers incl. "Edge" don't support CSS transform on SVG elements + if(key === 'transform' && sel.node() instanceof SVGElement) { + throw new Error('d3 selection.style called on an SVG element with key: ' + key); + } +} + +module.exports = d3; + +},{"d3":148,"fast-isnumeric":214}]},{},[22])(22) +}); + +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJidWlsZC9wbG90Y3NzLmpzIiwiYnVpbGQvcGxvdGljb24uanMiLCJsaWIvYWdncmVnYXRlLmpzIiwibGliL2Jhci5qcyIsImxpYi9iYXJwb2xhci5qcyIsImxpYi9ib3guanMiLCJsaWIvY2FsZW5kYXJzLmpzIiwibGliL2NhbmRsZXN0aWNrLmpzIiwibGliL2NhcnBldC5qcyIsImxpYi9jaG9yb3BsZXRoLmpzIiwibGliL2NvbmUuanMiLCJsaWIvY29udG91ci5qcyIsImxpYi9jb250b3VyY2FycGV0LmpzIiwibGliL2NvcmUuanMiLCJsaWIvZmlsdGVyLmpzIiwibGliL2dyb3VwYnkuanMiLCJsaWIvaGVhdG1hcC5qcyIsImxpYi9oZWF0bWFwZ2wuanMiLCJsaWIvaGlzdG9ncmFtLmpzIiwibGliL2hpc3RvZ3JhbTJkLmpzIiwibGliL2hpc3RvZ3JhbTJkY29udG91ci5qcyIsImxpYi9pbmRleC5qcyIsImxpYi9tZXNoM2QuanMiLCJsaWIvb2hsYy5qcyIsImxpYi9wYXJjYXRzLmpzIiwibGliL3BhcmNvb3Jkcy5qcyIsImxpYi9waWUuanMiLCJsaWIvcG9pbnRjbG91ZC5qcyIsImxpYi9zYW5rZXkuanMiLCJsaWIvc2NhdHRlcjNkLmpzIiwibGliL3NjYXR0ZXJjYXJwZXQuanMiLCJsaWIvc2NhdHRlcmdlby5qcyIsImxpYi9zY2F0dGVyZ2wuanMiLCJsaWIvc2NhdHRlcm1hcGJveC5qcyIsImxpYi9zY2F0dGVycG9sYXIuanMiLCJsaWIvc2NhdHRlcnBvbGFyZ2wuanMiLCJsaWIvc2NhdHRlcnRlcm5hcnkuanMiLCJsaWIvc29ydC5qcyIsImxpYi9zcGxvbS5qcyIsImxpYi9zdHJlYW10dWJlLmpzIiwibGliL3N1cmZhY2UuanMiLCJsaWIvdGFibGUuanMiLCJsaWIvdmlvbGluLmpzIiwibm9kZV9tb2R1bGVzLzNkLXZpZXctY29udHJvbHMvY2FtZXJhLmpzIiwibm9kZV9tb2R1bGVzLzNkLXZpZXcvdmlldy5qcyIsIm5vZGVfbW9kdWxlcy9AcGxvdGx5L2QzLXNhbmtleS9idWlsZC9kMy1zYW5rZXkuanMiLCJub2RlX21vZHVsZXMvYS1iaWctdHJpYW5nbGUvdHJpYW5nbGUuanMiLCJub2RlX21vZHVsZXMvYWJzLXN2Zy1wYXRoL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2FkZC1saW5lLW51bWJlcnMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYWZmaW5lLWh1bGwvYWZmLmpzIiwibm9kZV9tb2R1bGVzL2FscGhhLWNvbXBsZXgvYWxwaGEuanMiLCJub2RlX21vZHVsZXMvYWxwaGEtc2hhcGUvYWxwaGEuanMiLCJub2RlX21vZHVsZXMvYXJyYXktYm91bmRzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2FycmF5LW5vcm1hbGl6ZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9hcnJheS1yYW5nZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9hc3NlcnQvYXNzZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2Fzc2VydC9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9hc3NlcnQvbm9kZV9tb2R1bGVzL3V0aWwvc3VwcG9ydC9pc0J1ZmZlckJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvYXNzZXJ0L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvYXRvYi1saXRlL2F0b2ItYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9iYXJ5Y2VudHJpYy9iYXJ5Y2VudHJpYy5qcyIsIm5vZGVfbW9kdWxlcy9iYXNlNjQtanMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9hZGQuanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9jbXAuanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9kaXYuanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9iaWctcmF0L2lzLXJhdC5qcyIsIm5vZGVfbW9kdWxlcy9iaWctcmF0L2xpYi9ibi1zaWduLmpzIiwibm9kZV9tb2R1bGVzL2JpZy1yYXQvbGliL2JuLXRvLW51bS5qcyIsIm5vZGVfbW9kdWxlcy9iaWctcmF0L2xpYi9jdHouanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9saWIvaXMtYm4uanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9saWIvbnVtLXRvLWJuLmpzIiwibm9kZV9tb2R1bGVzL2JpZy1yYXQvbGliL3JhdGlvbmFsaXplLmpzIiwibm9kZV9tb2R1bGVzL2JpZy1yYXQvbGliL3N0ci10by1ibi5qcyIsIm5vZGVfbW9kdWxlcy9iaWctcmF0L211bC5qcyIsIm5vZGVfbW9kdWxlcy9iaWctcmF0L3NpZ24uanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC9zdWIuanMiLCJub2RlX21vZHVsZXMvYmlnLXJhdC90by1mbG9hdC5qcyIsIm5vZGVfbW9kdWxlcy9iaW5hcnktc2VhcmNoLWJvdW5kcy9zZWFyY2gtYm91bmRzLmpzIiwibm9kZV9tb2R1bGVzL2JpdC10d2lkZGxlL3R3aWRkbGUuanMiLCJub2RlX21vZHVsZXMvYml0bWFwLXNkZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9ibi5qcy9saWIvYm4uanMiLCJub2RlX21vZHVsZXMvYm91bmRhcnktY2VsbHMvYm91bmRhcnkuanMiLCJub2RlX21vZHVsZXMvYm94LWludGVyc2VjdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9ib3gtaW50ZXJzZWN0L2xpYi9icnV0ZS5qcyIsIm5vZGVfbW9kdWxlcy9ib3gtaW50ZXJzZWN0L2xpYi9pbnRlcnNlY3QuanMiLCJub2RlX21vZHVsZXMvYm94LWludGVyc2VjdC9saWIvbWVkaWFuLmpzIiwibm9kZV9tb2R1bGVzL2JveC1pbnRlcnNlY3QvbGliL3BhcnRpdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9ib3gtaW50ZXJzZWN0L2xpYi9zb3J0LmpzIiwibm9kZV9tb2R1bGVzL2JveC1pbnRlcnNlY3QvbGliL3N3ZWVwLmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXItcmVzb2x2ZS9lbXB0eS5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9ldmVudHMvZXZlbnRzLmpzIiwibm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jZHQyZC9jZHQyZC5qcyIsIm5vZGVfbW9kdWxlcy9jZHQyZC9saWIvZGVsYXVuYXkuanMiLCJub2RlX21vZHVsZXMvY2R0MmQvbGliL2ZpbHRlci5qcyIsIm5vZGVfbW9kdWxlcy9jZHQyZC9saWIvbW9ub3RvbmUuanMiLCJub2RlX21vZHVsZXMvY2R0MmQvbGliL3RyaWFuZ3VsYXRpb24uanMiLCJub2RlX21vZHVsZXMvY2R0MmQvbm9kZV9tb2R1bGVzL2JpbmFyeS1zZWFyY2gtYm91bmRzL3NlYXJjaC1ib3VuZHMuanMiLCJub2RlX21vZHVsZXMvY2VsbC1vcmllbnRhdGlvbi9vcmllbnRhdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9jaXJjdW1jZW50ZXIvY2lyY3VtY2VudGVyLmpzIiwibm9kZV9tb2R1bGVzL2NpcmN1bXJhZGl1cy9jcmFkLmpzIiwibm9kZV9tb2R1bGVzL2NsYW1wL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2NsZWFuLXBzbGcvY2xlYW4tcHNsZy5qcyIsIm5vZGVfbW9kdWxlcy9jbGVhbi1wc2xnL2xpYi9yYXQtc2VnLWludGVyc2VjdC5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvci1pZC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvci1uYW1lL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2NvbG9yLW5vcm1hbGl6ZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvci1wYXJzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvci1yZ2JhL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2NvbG9yLXNwYWNlL2hzbC5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvci1zcGFjZS9yZ2IuanMiLCJub2RlX21vZHVsZXMvY29sb3JtYXAvY29sb3JTY2FsZS5qcyIsIm5vZGVfbW9kdWxlcy9jb2xvcm1hcC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jb21wYXJlLWFuZ2xlL2NtcGFuZ2xlLmpzIiwibm9kZV9tb2R1bGVzL2NvbXBhcmUtY2VsbC9jb21wYXJlLmpzIiwibm9kZV9tb2R1bGVzL2NvbXBhcmUtb3JpZW50ZWQtY2VsbC9jb21wYXJlLmpzIiwibm9kZV9tb2R1bGVzL2NvbnZleC1odWxsL2NoLmpzIiwibm9kZV9tb2R1bGVzL2NvbnZleC1odWxsL2xpYi9jaDFkLmpzIiwibm9kZV9tb2R1bGVzL2NvbnZleC1odWxsL2xpYi9jaDJkLmpzIiwibm9kZV9tb2R1bGVzL2NvbnZleC1odWxsL2xpYi9jaG5kLmpzIiwibm9kZV9tb2R1bGVzL2NvdW50cnktcmVnZXgvaW5kZXguanMiLCJub2RlX21vZHVsZXMvY3NzLWZvbnQtc2l6ZS1rZXl3b3Jkcy9pbmRleC5qc29uIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250LXN0cmV0Y2gta2V5d29yZHMvaW5kZXguanNvbiIsIm5vZGVfbW9kdWxlcy9jc3MtZm9udC1zdHlsZS1rZXl3b3Jkcy9pbmRleC5qc29uIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250LXdlaWdodC1rZXl3b3Jkcy9pbmRleC5qc29uIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250L2xpYi91dGlsLmpzIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250L3BhcnNlLmpzIiwibm9kZV9tb2R1bGVzL2Nzcy1mb250L3N0cmluZ2lmeS5qcyIsIm5vZGVfbW9kdWxlcy9jc3MtZ2xvYmFsLWtleXdvcmRzL2luZGV4Lmpzb24iLCJub2RlX21vZHVsZXMvY3NzLXN5c3RlbS1mb250LWtleXdvcmRzL2luZGV4Lmpzb24iLCJub2RlX21vZHVsZXMvY3ViaWMtaGVybWl0ZS9oZXJtaXRlLmpzIiwibm9kZV9tb2R1bGVzL2N3aXNlLWNvbXBpbGVyL2NvbXBpbGVyLmpzIiwibm9kZV9tb2R1bGVzL2N3aXNlLWNvbXBpbGVyL2xpYi9jb21waWxlLmpzIiwibm9kZV9tb2R1bGVzL2N3aXNlLWNvbXBpbGVyL2xpYi90aHVuay5qcyIsIm5vZGVfbW9kdWxlcy9jd2lzZS9saWIvd3JhcHBlci5qcyIsIm5vZGVfbW9kdWxlcy9kL2F1dG8tYmluZC5qcyIsIm5vZGVfbW9kdWxlcy9kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2QzLWFycmF5L2Rpc3QvZDMtYXJyYXkuanMiLCJub2RlX21vZHVsZXMvZDMtY29sbGVjdGlvbi9idWlsZC9kMy1jb2xsZWN0aW9uLmpzIiwibm9kZV9tb2R1bGVzL2QzLWNvbG9yL2Rpc3QvZDMtY29sb3IuanMiLCJub2RlX21vZHVsZXMvZDMtZGlzcGF0Y2gvYnVpbGQvZDMtZGlzcGF0Y2guanMiLCJub2RlX21vZHVsZXMvZDMtZm9yY2UvYnVpbGQvZDMtZm9yY2UuanMiLCJub2RlX21vZHVsZXMvZDMtaW50ZXJwb2xhdGUvZGlzdC9kMy1pbnRlcnBvbGF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9kMy1xdWFkdHJlZS9idWlsZC9kMy1xdWFkdHJlZS5qcyIsIm5vZGVfbW9kdWxlcy9kMy10aW1lci9idWlsZC9kMy10aW1lci5qcyIsIm5vZGVfbW9kdWxlcy9kMy9kMy5qcyIsIm5vZGVfbW9kdWxlcy9kZWZpbmVkL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2RlbGF1bmF5LXRyaWFuZ3VsYXRlL3RyaWFuZ3VsYXRlLmpzIiwibm9kZV9tb2R1bGVzL2RldGVjdC1rZXJuaW5nL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2RvdWJsZS1iaXRzL2RvdWJsZS5qcyIsIm5vZGVfbW9kdWxlcy9kcmF3LXN2Zy1wYXRoL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2R0eXBlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2R1cC9kdXAuanMiLCJub2RlX21vZHVsZXMvZWFyY3V0L3NyYy9lYXJjdXQuanMiLCJub2RlX21vZHVsZXMvZWRnZXMtdG8tYWRqYWNlbmN5LWxpc3QvZTJhLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvYXJyYXkvIy9jbGVhci5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L2FycmF5L2Zyb20vaW5kZXguanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9hcnJheS9mcm9tL2lzLWltcGxlbWVudGVkLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvYXJyYXkvZnJvbS9zaGltLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvZnVuY3Rpb24vaXMtYXJndW1lbnRzLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvZnVuY3Rpb24vaXMtZnVuY3Rpb24uanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9mdW5jdGlvbi9ub29wLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvbWF0aC9zaWduL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvbWF0aC9zaWduL2lzLWltcGxlbWVudGVkLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvbWF0aC9zaWduL3NoaW0uanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9udW1iZXIvdG8taW50ZWdlci5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L251bWJlci90by1wb3MtaW50ZWdlci5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9faXRlcmF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9hc3NpZ24vaW5kZXguanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9vYmplY3QvYXNzaWduL2lzLWltcGxlbWVudGVkLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2Fzc2lnbi9zaGltLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2NvcHkuanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9vYmplY3QvY3JlYXRlLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2Zvci1lYWNoLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2lzLWNhbGxhYmxlLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2lzLW9iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9pcy12YWx1ZS5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9rZXlzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L2tleXMvaXMtaW1wbGVtZW50ZWQuanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9vYmplY3Qva2V5cy9zaGltLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L21hcC5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9ub3JtYWxpemUtb3B0aW9ucy5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC9zZXQtcHJvdG90eXBlLW9mL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L3NldC1wcm90b3R5cGUtb2YvaXMtaW1wbGVtZW50ZWQuanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZi9zaGltLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L3ZhbGlkLWNhbGxhYmxlLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvb2JqZWN0L3ZhbGlkLW9iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L29iamVjdC92YWxpZC12YWx1ZS5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L3N0cmluZy8jL2NvbnRhaW5zL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvc3RyaW5nLyMvY29udGFpbnMvaXMtaW1wbGVtZW50ZWQuanMiLCJub2RlX21vZHVsZXMvZXM1LWV4dC9zdHJpbmcvIy9jb250YWlucy9zaGltLmpzIiwibm9kZV9tb2R1bGVzL2VzNS1leHQvc3RyaW5nL2lzLXN0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9lczUtZXh0L3N0cmluZy9yYW5kb20tdW5pcS5qcyIsIm5vZGVfbW9kdWxlcy9lczYtaXRlcmF0b3IvYXJyYXkuanMiLCJub2RlX21vZHVsZXMvZXM2LWl0ZXJhdG9yL2Zvci1vZi5qcyIsIm5vZGVfbW9kdWxlcy9lczYtaXRlcmF0b3IvZ2V0LmpzIiwibm9kZV9tb2R1bGVzL2VzNi1pdGVyYXRvci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9lczYtaXRlcmF0b3IvaXMtaXRlcmFibGUuanMiLCJub2RlX21vZHVsZXMvZXM2LWl0ZXJhdG9yL3N0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9lczYtaXRlcmF0b3IvdmFsaWQtaXRlcmFibGUuanMiLCJub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9lczYtcHJvbWlzZS5qcyIsIm5vZGVfbW9kdWxlcy9lczYtc3ltYm9sL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VzNi1zeW1ib2wvaXMtaW1wbGVtZW50ZWQuanMiLCJub2RlX21vZHVsZXMvZXM2LXN5bWJvbC9pcy1zeW1ib2wuanMiLCJub2RlX21vZHVsZXMvZXM2LXN5bWJvbC9wb2x5ZmlsbC5qcyIsIm5vZGVfbW9kdWxlcy9lczYtc3ltYm9sL3ZhbGlkYXRlLXN5bWJvbC5qcyIsIm5vZGVfbW9kdWxlcy9lczYtd2Vhay1tYXAvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZXM2LXdlYWstbWFwL2lzLWltcGxlbWVudGVkLmpzIiwibm9kZV9tb2R1bGVzL2VzNi13ZWFrLW1hcC9pcy1uYXRpdmUtaW1wbGVtZW50ZWQuanMiLCJub2RlX21vZHVsZXMvZXM2LXdlYWstbWFwL3BvbHlmaWxsLmpzIiwibm9kZV9tb2R1bGVzL2V4dHJhY3QtZnJ1c3R1bS1wbGFuZXMvZXh0cmFjdC1wbGFuZXMuanMiLCJub2RlX21vZHVsZXMvZmFzdC1pc251bWVyaWMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZmlsdGVyZWQtdmVjdG9yL2Z2ZWMuanMiLCJub2RlX21vZHVsZXMvZmxhdHRlbi12ZXJ0ZXgtZGF0YS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9mb250LWF0bGFzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2ZvbnQtbWVhc3VyZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9mdW5jdGlvbmFsLXJlZC1ibGFjay10cmVlL3JidHJlZS5qcyIsIm5vZGVfbW9kdWxlcy9nYW1tYS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9nZXQtY2FudmFzLWNvbnRleHQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2wtYXhlczNkL2F4ZXMuanMiLCJub2RlX21vZHVsZXMvZ2wtYXhlczNkL2xpYi9iYWNrZ3JvdW5kLmpzIiwibm9kZV9tb2R1bGVzL2dsLWF4ZXMzZC9saWIvY3ViZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC1heGVzM2QvbGliL2xpbmVzLmpzIiwibm9kZV9tb2R1bGVzL2dsLWF4ZXMzZC9saWIvc2hhZGVycy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1heGVzM2QvbGliL3RleHQuanMiLCJub2RlX21vZHVsZXMvZ2wtYXhlczNkL2xpYi90aWNrcy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1heGVzM2QvcHJvcGVydGllcy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1idWZmZXIvYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL2dsLWNvbmUzZC9jb25lLmpzIiwibm9kZV9tb2R1bGVzL2dsLWNvbmUzZC9saWIvY2xvc2VzdC1wb2ludC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1jb25lM2QvbGliL2NvbmVtZXNoLmpzIiwibm9kZV9tb2R1bGVzL2dsLWNvbmUzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1jb25zdGFudHMvMS4wL251bWJlcnMuanMiLCJub2RlX21vZHVsZXMvZ2wtY29uc3RhbnRzL2xvb2t1cC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1lcnJvcjNkL2Vycm9yYmFycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1lcnJvcjNkL3NoYWRlcnMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2wtZmJvL2Ziby5qcyIsIm5vZGVfbW9kdWxlcy9nbC1mb3JtYXQtY29tcGlsZXItZXJyb3IvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2wtaGVhdG1hcDJkL2hlYXRtYXAuanMiLCJub2RlX21vZHVsZXMvZ2wtaGVhdG1hcDJkL2xpYi9zaGFkZXJzLmpzIiwibm9kZV9tb2R1bGVzL2dsLWxpbmUzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1saW5lM2QvbGluZXMuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0Mi9pbnZlcnQuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0My9pbnZlcnQuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0NC9jbG9uZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L2NyZWF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L2RldGVybWluYW50LmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvZnJvbVF1YXQuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0NC9mcm9tUm90YXRpb25UcmFuc2xhdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L2lkZW50aXR5LmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvaW52ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvbG9va0F0LmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvbXVsdGlwbHkuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0NC9wZXJzcGVjdGl2ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L3JvdGF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L3JvdGF0ZVguanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0NC9yb3RhdGVZLmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvcm90YXRlWi5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tYXQ0L3NjYWxlLmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvdHJhbnNsYXRlLmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdDQvdHJhbnNwb3NlLmpzIiwibm9kZV9tb2R1bGVzL2dsLW1hdHJpeC1pbnZlcnQvaW52ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dsLW1lc2gzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1tZXNoM2QvbWVzaC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1wbG90MmQvbGliL2JveC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1wbG90MmQvbGliL2dyaWQuanMiLCJub2RlX21vZHVsZXMvZ2wtcGxvdDJkL2xpYi9saW5lLmpzIiwibm9kZV9tb2R1bGVzL2dsLXBsb3QyZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1wbG90MmQvbGliL3RleHQuanMiLCJub2RlX21vZHVsZXMvZ2wtcGxvdDJkL3Bsb3QuanMiLCJub2RlX21vZHVsZXMvZ2wtcGxvdDNkL2xpYi9zaGFkZXIuanMiLCJub2RlX21vZHVsZXMvZ2wtcGxvdDNkL3NjZW5lLmpzIiwibm9kZV9tb2R1bGVzL2dsLXBvaW50Y2xvdWQyZC9saWIvc2hhZGVyLmpzIiwibm9kZV9tb2R1bGVzL2dsLXBvaW50Y2xvdWQyZC9wb2ludGNsb3VkMmQuanMiLCJub2RlX21vZHVsZXMvZ2wtcXVhdC9zbGVycC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zY2F0dGVyM2QvbGliL2dldC1zaW1wbGUtc3RyaW5nLmpzIiwibm9kZV9tb2R1bGVzL2dsLXNjYXR0ZXIzZC9saWIvZ2x5cGhzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXNjYXR0ZXIzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zY2F0dGVyM2QvcG9pbnRjbG91ZC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zZWxlY3QtYm94L2xpYi9zaGFkZXJzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXNlbGVjdC1ib3gvc2VsZWN0Ym94LmpzIiwibm9kZV9tb2R1bGVzL2dsLXNlbGVjdC1zdGF0aWMvc2VsZWN0LmpzIiwibm9kZV9tb2R1bGVzL2dsLXNoYWRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zaGFkZXIvbGliL0dMRXJyb3IuanMiLCJub2RlX21vZHVsZXMvZ2wtc2hhZGVyL2xpYi9jcmVhdGUtYXR0cmlidXRlcy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zaGFkZXIvbGliL2NyZWF0ZS11bmlmb3Jtcy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zaGFkZXIvbGliL3JlZmxlY3QuanMiLCJub2RlX21vZHVsZXMvZ2wtc2hhZGVyL2xpYi9ydW50aW1lLXJlZmxlY3QuanMiLCJub2RlX21vZHVsZXMvZ2wtc2hhZGVyL2xpYi9zaGFkZXItY2FjaGUuanMiLCJub2RlX21vZHVsZXMvZ2wtc3Bpa2VzMmQvc3Bpa2VzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXNwaWtlczNkL3NoYWRlcnMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2wtc3Bpa2VzM2Qvc3Bpa2VzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXN0cmVhbXR1YmUzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zdHJlYW10dWJlM2QvbGliL3R1YmVtZXNoLmpzIiwibm9kZV9tb2R1bGVzL2dsLXN0cmVhbXR1YmUzZC9zdHJlYW10dWJlLmpzIiwibm9kZV9tb2R1bGVzL2dsLXN1cmZhY2UzZC9saWIvc2hhZGVycy5qcyIsIm5vZGVfbW9kdWxlcy9nbC1zdXJmYWNlM2Qvc3VyZmFjZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC10ZXh0L2Rpc3QuanMiLCJub2RlX21vZHVsZXMvZ2wtdGV4dHVyZTJkL3RleHR1cmUuanMiLCJub2RlX21vZHVsZXMvZ2wtdXRpbC9jb250ZXh0LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZhby9saWIvZG8tYmluZC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12YW8vbGliL3Zhby1lbXVsYXRlZC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12YW8vbGliL3Zhby1uYXRpdmUuanMiLCJub2RlX21vZHVsZXMvZ2wtdmFvL3Zhby5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2FkZC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2FuZ2xlLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvY2VpbC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2Nsb25lLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvY29weS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2NyZWF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2Nyb3NzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZGlzdC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2Rpc3RhbmNlLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZGl2LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZGl2aWRlLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZG90LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZXBzaWxvbi5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2VxdWFscy5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2V4YWN0RXF1YWxzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZmxvb3IuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9mb3JFYWNoLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvZnJvbVZhbHVlcy5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvaW52ZXJzZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2xlbi5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2xlbmd0aC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL2xlcnAuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9tYXguanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9taW4uanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9tdWwuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9tdWx0aXBseS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL25lZ2F0ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL25vcm1hbGl6ZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3JhbmRvbS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3JvdGF0ZVguanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9yb3RhdGVZLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvcm90YXRlWi5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3JvdW5kLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvc2NhbGUuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9zY2FsZUFuZEFkZC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3NldC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3NxckRpc3QuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9zcXJMZW4uanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9zcXVhcmVkRGlzdGFuY2UuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy9zcXVhcmVkTGVuZ3RoLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvc3ViLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvc3VidHJhY3QuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjMy90cmFuc2Zvcm1NYXQzLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzMvdHJhbnNmb3JtTWF0NC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWMzL3RyYW5zZm9ybVF1YXQuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9hZGQuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9jbG9uZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L2NvcHkuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9jcmVhdGUuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9kaXN0YW5jZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L2RpdmlkZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L2RvdC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L2Zyb21WYWx1ZXMuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L2ludmVyc2UuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9sZW5ndGguanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9sZXJwLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvbWF4LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvbWluLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvbXVsdGlwbHkuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9uZWdhdGUuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9ub3JtYWxpemUuanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9yYW5kb20uanMiLCJub2RlX21vZHVsZXMvZ2wtdmVjNC9zY2FsZS5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L3NjYWxlQW5kQWRkLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvc2V0LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvc3F1YXJlZERpc3RhbmNlLmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvc3F1YXJlZExlbmd0aC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L3N1YnRyYWN0LmpzIiwibm9kZV9tb2R1bGVzL2dsLXZlYzQvdHJhbnNmb3JtTWF0NC5qcyIsIm5vZGVfbW9kdWxlcy9nbC12ZWM0L3RyYW5zZm9ybVF1YXQuanMiLCJub2RlX21vZHVsZXMvZ2xzbC1yZWFkLWZsb2F0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dsc2wtc2hhZGVyLW5hbWUvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2xzbC10b2tlbml6ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2xzbC10b2tlbml6ZXIvbGliL2J1aWx0aW5zLTMwMGVzLmpzIiwibm9kZV9tb2R1bGVzL2dsc2wtdG9rZW5pemVyL2xpYi9idWlsdGlucy5qcyIsIm5vZGVfbW9kdWxlcy9nbHNsLXRva2VuaXplci9saWIvbGl0ZXJhbHMtMzAwZXMuanMiLCJub2RlX21vZHVsZXMvZ2xzbC10b2tlbml6ZXIvbGliL2xpdGVyYWxzLmpzIiwibm9kZV9tb2R1bGVzL2dsc2wtdG9rZW5pemVyL2xpYi9vcGVyYXRvcnMuanMiLCJub2RlX21vZHVsZXMvZ2xzbC10b2tlbml6ZXIvc3RyaW5nLmpzIiwibm9kZV9tb2R1bGVzL2dsc2xpZnkvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9oYXMtaG92ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaGFzLXBhc3NpdmUtZXZlbnRzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaW5jcmVtZW50YWwtY29udmV4LWh1bGwvaWNoLmpzIiwibm9kZV9tb2R1bGVzL2ludGVydmFsLXRyZWUtMWQvaW50ZXJ2YWwtdHJlZS5qcyIsIm5vZGVfbW9kdWxlcy9pbnZlcnQtcGVybXV0YXRpb24vaW5kZXguanMiLCJub2RlX21vZHVsZXMvaW90YS1hcnJheS9pb3RhLmpzIiwibm9kZV9tb2R1bGVzL2lzLWJyb3dzZXIvY2xpZW50LmpzIiwibm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pcy1pZXhwbG9yZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaXMtbW9iaWxlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2lzLW9iai9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pcy1wbGFpbi1vYmovaW5kZXguanMiLCJub2RlX21vZHVsZXMvaXMtc3RyaW5nLWJsYW5rL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2lzLXN2Zy1wYXRoL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2xlcnAvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbWFwYm94LWdsL2Rpc3QvbWFwYm94LWdsLmpzIiwibm9kZV9tb2R1bGVzL21hcmNoaW5nLXNpbXBsZXgtdGFibGUvbXN0YWIuanMiLCJub2RlX21vZHVsZXMvbWF0NC1kZWNvbXBvc2UvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbWF0NC1kZWNvbXBvc2Uvbm9ybWFsaXplLmpzIiwibm9kZV9tb2R1bGVzL21hdDQtaW50ZXJwb2xhdGUvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbWF0NC1yZWNvbXBvc2UvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbWF0aC1sb2cyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL21hdHJpeC1jYW1lcmEtY29udHJvbGxlci9tYXRyaXguanMiLCJub2RlX21vZHVsZXMvbW9ub3RvbmUtY29udmV4LWh1bGwtMmQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbW91c2UtY2hhbmdlL21vdXNlLWxpc3Rlbi5qcyIsIm5vZGVfbW9kdWxlcy9tb3VzZS1ldmVudC1vZmZzZXQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbW91c2UtZXZlbnQvbW91c2UuanMiLCJub2RlX21vZHVsZXMvbW91c2Utd2hlZWwvd2hlZWwuanMiLCJub2RlX21vZHVsZXMvbmRhcnJheS1leHRyYWN0LWNvbnRvdXIvY29udG91ci5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5LWZpbGwvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbmRhcnJheS1ncmFkaWVudC9mZGcuanMiLCJub2RlX21vZHVsZXMvbmRhcnJheS1ob21vZ3JhcGh5L3hmb3JtLmpzIiwibm9kZV9tb2R1bGVzL25kYXJyYXktbGluZWFyLWludGVycG9sYXRlL2ludGVycC5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5LW9wcy9uZGFycmF5LW9wcy5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5LXBhY2svY29udmVydC5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5LXBhY2svZG9Db252ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL25kYXJyYXktc29ydC9saWIvY29tcGlsZV9zb3J0LmpzIiwibm9kZV9tb2R1bGVzL25kYXJyYXktc29ydC9zb3J0LmpzIiwibm9kZV9tb2R1bGVzL25kYXJyYXktd2FycC93YXJwLmpzIiwibm9kZV9tb2R1bGVzL25kYXJyYXkvbmRhcnJheS5qcyIsIm5vZGVfbW9kdWxlcy9uZXh0YWZ0ZXIvbmV4dGFmdGVyLmpzIiwibm9kZV9tb2R1bGVzL25vcm1hbGl6ZS1zdmctcGF0aC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9ub3JtYWxzL25vcm1hbHMuanMiLCJub2RlX21vZHVsZXMvb2JqZWN0LWFzc2lnbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9vcmJpdC1jYW1lcmEtY29udHJvbGxlci9saWIvcXVhdEZyb21GcmFtZS5qcyIsIm5vZGVfbW9kdWxlcy9vcmJpdC1jYW1lcmEtY29udHJvbGxlci9vcmJpdC5qcyIsIm5vZGVfbW9kdWxlcy9wYWQtbGVmdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYXJlbnRoZXNpcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYXJzZS1yZWN0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3BhcnNlLXN2Zy1wYXRoL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3BhcnNlLXVuaXQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcGVyZm9ybWFuY2Utbm93L2xpYi9wZXJmb3JtYW5jZS1ub3cuanMiLCJub2RlX21vZHVsZXMvcGVybXV0YXRpb24tcGFyaXR5L3Blcm11dGF0aW9uLXNpZ24uanMiLCJub2RlX21vZHVsZXMvcGVybXV0YXRpb24tcmFuay9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9waWNrLWJ5LWFsaWFzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3BsYW5hci1kdWFsL2xvb3BzLmpzIiwibm9kZV9tb2R1bGVzL3BsYW5hci1ncmFwaC10by1wb2x5bGluZS9saWIvdHJpbS1sZWF2ZXMuanMiLCJub2RlX21vZHVsZXMvcGxhbmFyLWdyYXBoLXRvLXBvbHlsaW5lL3BnMnBsLmpzIiwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL25vZGVfbW9kdWxlcy9wb2ludC1jbHVzdGVyL2luZGV4LmpzIiwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL25vZGVfbW9kdWxlcy9wb2ludC1jbHVzdGVyL3F1YWQuanMiLCJub2RlX21vZHVsZXMvcG9pbnQtaW4tYmlnLXBvbHlnb24vcG5wLWJpZy5qcyIsIm5vZGVfbW9kdWxlcy9wb2x5Ym9vbGpzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3BvbHlib29sanMvbGliL2J1aWxkLWxvZy5qcyIsIm5vZGVfbW9kdWxlcy9wb2x5Ym9vbGpzL2xpYi9lcHNpbG9uLmpzIiwibm9kZV9tb2R1bGVzL3BvbHlib29sanMvbGliL2dlb2pzb24uanMiLCJub2RlX21vZHVsZXMvcG9seWJvb2xqcy9saWIvaW50ZXJzZWN0ZXIuanMiLCJub2RlX21vZHVsZXMvcG9seWJvb2xqcy9saWIvbGlua2VkLWxpc3QuanMiLCJub2RlX21vZHVsZXMvcG9seWJvb2xqcy9saWIvc2VnbWVudC1jaGFpbmVyLmpzIiwibm9kZV9tb2R1bGVzL3BvbHlib29sanMvbGliL3NlZ21lbnQtc2VsZWN0b3IuanMiLCJub2RlX21vZHVsZXMvcG9seXRvcGUtY2xvc2VzdC1wb2ludC9saWIvY2xvc2VzdF9wb2ludF8yZC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcXVhdC1zbGVycC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yYWYvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmF0LXZlYy9hZGQuanMiLCJub2RlX21vZHVsZXMvcmF0LXZlYy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yYXQtdmVjL211bHMuanMiLCJub2RlX21vZHVsZXMvcmF0LXZlYy9zdWIuanMiLCJub2RlX21vZHVsZXMvcmVkdWNlLXNpbXBsaWNpYWwtY29tcGxleC9yZWR1Y2UuanMiLCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvbm9kZV9tb2R1bGVzL3JlZ2wtZXJyb3IyZC9pbmRleC5qcyIsIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy9ub2RlX21vZHVsZXMvcmVnbC1saW5lMmQvaW5kZXguanMiLCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvbm9kZV9tb2R1bGVzL3JlZ2wtc2NhdHRlcjJkL2luZGV4LmpzIiwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL25vZGVfbW9kdWxlcy9yZWdsLXNjYXR0ZXIyZC9zY2F0dGVyLmpzIiwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL25vZGVfbW9kdWxlcy9yZWdsLXNwbG9tL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlZ2wvZGlzdC9yZWdsLmpzIiwibm9kZV9tb2R1bGVzL3JlcGVhdC1zdHJpbmcvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmlnaHQtbm93L2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcm9idXN0LWNvbXByZXNzL2NvbXByZXNzLmpzIiwibm9kZV9tb2R1bGVzL3JvYnVzdC1kZXRlcm1pbmFudC9yb2J1c3QtZGV0ZXJtaW5hbnQuanMiLCJub2RlX21vZHVsZXMvcm9idXN0LWRvdC1wcm9kdWN0L2RvdC1wcm9kLmpzIiwibm9kZV9tb2R1bGVzL3JvYnVzdC1pbi1zcGhlcmUvaW4tc3BoZXJlLmpzIiwibm9kZV9tb2R1bGVzL3JvYnVzdC1saW5lYXItc29sdmUvbGluc29sdmUuanMiLCJub2RlX21vZHVsZXMvcm9idXN0LW9yaWVudGF0aW9uL29yaWVudGF0aW9uLmpzIiwibm9kZV9tb2R1bGVzL3JvYnVzdC1wcm9kdWN0L3Byb2R1Y3QuanMiLCJub2RlX21vZHVsZXMvcm9idXN0LXNjYWxlL3JvYnVzdC1zY2FsZS5qcyIsIm5vZGVfbW9kdWxlcy9yb2J1c3Qtc2VnbWVudC1pbnRlcnNlY3Qvc2Vnc2VnLmpzIiwibm9kZV9tb2R1bGVzL3JvYnVzdC1zdWJ0cmFjdC9yb2J1c3QtZGlmZi5qcyIsIm5vZGVfbW9kdWxlcy9yb2J1c3Qtc3VtL3JvYnVzdC1zdW0uanMiLCJub2RlX21vZHVsZXMvc2lnbnVtL3Nnbi5qcyIsIm5vZGVfbW9kdWxlcy9zaW1wbGljaWFsLWNvbXBsZXgtYm91bmRhcnkvYm91bmRhcnkuanMiLCJub2RlX21vZHVsZXMvc2ltcGxpY2lhbC1jb21wbGV4LWNvbnRvdXIvY29udG91ci5qcyIsIm5vZGVfbW9kdWxlcy9zaW1wbGljaWFsLWNvbXBsZXgtY29udG91ci9saWIvY29kZWdlbi5qcyIsIm5vZGVfbW9kdWxlcy9zaW1wbGljaWFsLWNvbXBsZXgvdG9wb2xvZ3kuanMiLCJub2RlX21vZHVsZXMvc2ltcGxpZnktcGxhbmFyLWdyYXBoL25vZGVfbW9kdWxlcy91bmlvbi1maW5kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NpbXBsaWZ5LXBsYW5hci1ncmFwaC9zaW1wbGlmeS5qcyIsIm5vZGVfbW9kdWxlcy9zbGFiLWRlY29tcG9zaXRpb24vbGliL29yZGVyLXNlZ21lbnRzLmpzIiwibm9kZV9tb2R1bGVzL3NsYWItZGVjb21wb3NpdGlvbi9zbGFicy5qcyIsIm5vZGVfbW9kdWxlcy9zcGxpdC1wb2x5Z29uL2NsaXAtcG9seS5qcyIsIm5vZGVfbW9kdWxlcy9zcHJpbnRmLWpzL3NyYy9zcHJpbnRmLmpzIiwibm9kZV9tb2R1bGVzL3N0cmluZy1zcGxpdC1ieS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zdHJvbmdseS1jb25uZWN0ZWQtY29tcG9uZW50cy9zY2MuanMiLCJub2RlX21vZHVsZXMvc3VwZXJzY3JpcHQtdGV4dC9zdXBlcnNjcmlwdC5qcyIsIm5vZGVfbW9kdWxlcy9zdXJmYWNlLW5ldHMvc3VyZmFjZW5ldHMuanMiLCJub2RlX21vZHVsZXMvc3ZnLWFyYy10by1jdWJpYy1iZXppZXIvY2pzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3N2Zy1wYXRoLWJvdW5kcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zdmctcGF0aC1ib3VuZHMvbm9kZV9tb2R1bGVzL25vcm1hbGl6ZS1zdmctcGF0aC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zdmctcGF0aC1zZGYvaW5kZXguanMiLCJub2RlX21vZHVsZXMvdGV4dC1jYWNoZS90ZXh0Y2FjaGUuanMiLCJub2RlX21vZHVsZXMvdGlueWNvbG9yMi90aW55Y29sb3IuanMiLCJub2RlX21vZHVsZXMvdG8tZmxvYXQzMi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy90by1weC90b3B4LmpzIiwibm9kZV9tb2R1bGVzL3RvcG9qc29uLWNsaWVudC9kaXN0L3RvcG9qc29uLWNsaWVudC5qcyIsIm5vZGVfbW9kdWxlcy90cmlhbmd1bGF0ZS1oeXBlcmN1YmUvdHJpYW5ndWxhdGUtY3ViZS5qcyIsIm5vZGVfbW9kdWxlcy90dXJudGFibGUtY2FtZXJhLWNvbnRyb2xsZXIvdHVybnRhYmxlLmpzIiwibm9kZV9tb2R1bGVzL3R3by1wcm9kdWN0L3R3by1wcm9kdWN0LmpzIiwibm9kZV9tb2R1bGVzL3R3by1zdW0vdHdvLXN1bS5qcyIsIm5vZGVfbW9kdWxlcy90eXBlZGFycmF5LXBvb2wvcG9vbC5qcyIsIm5vZGVfbW9kdWxlcy91bmlvbi1maW5kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3VuaXEvdW5pcS5qcyIsIm5vZGVfbW9kdWxlcy91bnF1b3RlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3VwZGF0ZS1kaWZmL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3ZlY3Rvcml6ZS10ZXh0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3ZlY3Rvcml6ZS10ZXh0L2xpYi92dGV4dC5qcyIsIm5vZGVfbW9kdWxlcy93ZWFrLW1hcC93ZWFrLW1hcC5qcyIsIm5vZGVfbW9kdWxlcy93ZWFrbWFwLXNoaW0vY3JlYXRlLXN0b3JlLmpzIiwibm9kZV9tb2R1bGVzL3dlYWttYXAtc2hpbS9oaWRkZW4tc3RvcmUuanMiLCJub2RlX21vZHVsZXMvd2Vha21hcC1zaGltL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3dlYmdsLWNvbnRleHQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2NoaW5lc2UuanMiLCJub2RlX21vZHVsZXMvd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2NvcHRpYy5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvZGlzY3dvcmxkLmpzIiwibm9kZV9tb2R1bGVzL3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9ldGhpb3BpYW4uanMiLCJub2RlX21vZHVsZXMvd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2hlYnJldy5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvaXNsYW1pYy5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvanVsaWFuLmpzIiwibm9kZV9tb2R1bGVzL3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9tYXlhbi5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbmFuYWtzaGFoaS5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbmVwYWxpLmpzIiwibm9kZV9tb2R1bGVzL3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9wZXJzaWFuLmpzIiwibm9kZV9tb2R1bGVzL3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy90YWl3YW4uanMiLCJub2RlX21vZHVsZXMvd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3RoYWkuanMiLCJub2RlX21vZHVsZXMvd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3VtbWFscXVyYS5qcyIsIm5vZGVfbW9kdWxlcy93b3JsZC1jYWxlbmRhcnMvZGlzdC9tYWluLmpzIiwibm9kZV9tb2R1bGVzL3dvcmxkLWNhbGVuZGFycy9kaXN0L3BsdXMuanMiLCJub2RlX21vZHVsZXMvemVyby1jcm9zc2luZ3MvbGliL3pjLWNvcmUuanMiLCJub2RlX21vZHVsZXMvemVyby1jcm9zc2luZ3MvemMuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9ucy9hcnJvd19wYXRocy5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9ucy9jYWxjX2F1dG9yYW5nZS5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zL2NsaWNrLmpzIiwic3JjL2NvbXBvbmVudHMvYW5ub3RhdGlvbnMvY29tbW9uX2RlZmF1bHRzLmpzIiwic3JjL2NvbXBvbmVudHMvYW5ub3RhdGlvbnMvY29udmVydF9jb29yZHMuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9ucy9kZWZhdWx0cy5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zL2RyYXcuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9ucy9kcmF3X2Fycm93X2hlYWQuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9ucy9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zM2QvYXR0cmlidXRlcy5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zM2QvY29udmVydC5qcyIsInNyYy9jb21wb25lbnRzL2Fubm90YXRpb25zM2QvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9uczNkL2RyYXcuanMiLCJzcmMvY29tcG9uZW50cy9hbm5vdGF0aW9uczNkL2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvY2FsZW5kYXJzL2NhbGVuZGFycy5qcyIsInNyYy9jb21wb25lbnRzL2NhbGVuZGFycy9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9jb2xvci9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9jb2xvcmJhci9jb25uZWN0LmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JiYXIvY29uc3RhbnRzLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JiYXIvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9jb2xvcmJhci9kcmF3LmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JiYXIvaGFzX2NvbG9yYmFyLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0X3NjYWxlLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cy5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yc2NhbGUvZXh0cmFjdF9zY2FsZS5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yc2NhbGUvZmxpcF9zY2FsZS5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yc2NhbGUvZ2V0X3NjYWxlLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oYXNfY29sb3JzY2FsZS5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yc2NhbGUvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy9jb2xvcnNjYWxlL2lzX3ZhbGlkX3NjYWxlLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9pc192YWxpZF9zY2FsZV9hcnJheS5qcyIsInNyYy9jb21wb25lbnRzL2NvbG9yc2NhbGUvbWFrZV9jb2xvcl9zY2FsZV9mdW5jLmpzIiwic3JjL2NvbXBvbmVudHMvY29sb3JzY2FsZS9zY2FsZXMuanMiLCJzcmMvY29tcG9uZW50cy9kcmFnZWxlbWVudC9hbGlnbi5qcyIsInNyYy9jb21wb25lbnRzL2RyYWdlbGVtZW50L2N1cnNvci5qcyIsInNyYy9jb21wb25lbnRzL2RyYWdlbGVtZW50L2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnQvdW5ob3Zlci5qcyIsInNyYy9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcy5qcyIsInNyYy9jb21wb25lbnRzL2RyYXdpbmcvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy9kcmF3aW5nL3N5bWJvbF9kZWZzLmpzIiwic3JjL2NvbXBvbmVudHMvZXJyb3JiYXJzL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9lcnJvcmJhcnMvY2FsYy5qcyIsInNyYy9jb21wb25lbnRzL2Vycm9yYmFycy9jb21wdXRlX2Vycm9yLmpzIiwic3JjL2NvbXBvbmVudHMvZXJyb3JiYXJzL2RlZmF1bHRzLmpzIiwic3JjL2NvbXBvbmVudHMvZXJyb3JiYXJzL2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvZXJyb3JiYXJzL3Bsb3QuanMiLCJzcmMvY29tcG9uZW50cy9lcnJvcmJhcnMvc3R5bGUuanMiLCJzcmMvY29tcG9uZW50cy9meC9hdHRyaWJ1dGVzLmpzIiwic3JjL2NvbXBvbmVudHMvZngvY2FsYy5qcyIsInNyYy9jb21wb25lbnRzL2Z4L2NsaWNrLmpzIiwic3JjL2NvbXBvbmVudHMvZngvY29uc3RhbnRzLmpzIiwic3JjL2NvbXBvbmVudHMvZngvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9meC9oZWxwZXJzLmpzIiwic3JjL2NvbXBvbmVudHMvZngvaG92ZXIuanMiLCJzcmMvY29tcG9uZW50cy9meC9ob3ZlcmxhYmVsX2RlZmF1bHRzLmpzIiwic3JjL2NvbXBvbmVudHMvZngvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy9meC9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy9jb21wb25lbnRzL2Z4L2xheW91dF9kZWZhdWx0cy5qcyIsInNyYy9jb21wb25lbnRzL2Z4L2xheW91dF9nbG9iYWxfZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9ncmlkL2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvaW1hZ2VzL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9pbWFnZXMvY29udmVydF9jb29yZHMuanMiLCJzcmMvY29tcG9uZW50cy9pbWFnZXMvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9pbWFnZXMvZHJhdy5qcyIsInNyYy9jb21wb25lbnRzL2ltYWdlcy9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL2xlZ2VuZC9hbmNob3JfdXRpbHMuanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvYXR0cmlidXRlcy5qcyIsInNyYy9jb21wb25lbnRzL2xlZ2VuZC9jb25zdGFudHMuanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvZHJhdy5qcyIsInNyYy9jb21wb25lbnRzL2xlZ2VuZC9nZXRfbGVnZW5kX2RhdGEuanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvaGFuZGxlX2NsaWNrLmpzIiwic3JjL2NvbXBvbmVudHMvbGVnZW5kL2hlbHBlcnMuanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy9sZWdlbmQvc3R5bGUuanMiLCJzcmMvY29tcG9uZW50cy9tb2RlYmFyL2J1dHRvbnMuanMiLCJzcmMvY29tcG9uZW50cy9tb2RlYmFyL2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvbW9kZWJhci9tYW5hZ2UuanMiLCJzcmMvY29tcG9uZW50cy9tb2RlYmFyL21vZGViYXIuanMiLCJzcmMvY29tcG9uZW50cy9yYW5nZXNlbGVjdG9yL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9yYW5nZXNlbGVjdG9yL2NvbnN0YW50cy5qcyIsInNyYy9jb21wb25lbnRzL3Jhbmdlc2VsZWN0b3IvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy9yYW5nZXNlbGVjdG9yL2RyYXcuanMiLCJzcmMvY29tcG9uZW50cy9yYW5nZXNlbGVjdG9yL2dldF91cGRhdGVfb2JqZWN0LmpzIiwic3JjL2NvbXBvbmVudHMvcmFuZ2VzZWxlY3Rvci9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL3Jhbmdlc2xpZGVyL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9yYW5nZXNsaWRlci9jYWxjX2F1dG9yYW5nZS5qcyIsInNyYy9jb21wb25lbnRzL3Jhbmdlc2xpZGVyL2NvbnN0YW50cy5qcyIsInNyYy9jb21wb25lbnRzL3Jhbmdlc2xpZGVyL2RlZmF1bHRzLmpzIiwic3JjL2NvbXBvbmVudHMvcmFuZ2VzbGlkZXIvZHJhdy5qcyIsInNyYy9jb21wb25lbnRzL3Jhbmdlc2xpZGVyL2luZGV4LmpzIiwic3JjL2NvbXBvbmVudHMvcmFuZ2VzbGlkZXIvb3BwYXhpc19hdHRyaWJ1dGVzLmpzIiwic3JjL2NvbXBvbmVudHMvc2hhcGVzL2F0dHJpYnV0ZXMuanMiLCJzcmMvY29tcG9uZW50cy9zaGFwZXMvY2FsY19hdXRvcmFuZ2UuanMiLCJzcmMvY29tcG9uZW50cy9zaGFwZXMvY29uc3RhbnRzLmpzIiwic3JjL2NvbXBvbmVudHMvc2hhcGVzL2RlZmF1bHRzLmpzIiwic3JjL2NvbXBvbmVudHMvc2hhcGVzL2RyYXcuanMiLCJzcmMvY29tcG9uZW50cy9zaGFwZXMvaGVscGVycy5qcyIsInNyYy9jb21wb25lbnRzL3NoYXBlcy9pbmRleC5qcyIsInNyYy9jb21wb25lbnRzL3NsaWRlcnMvYXR0cmlidXRlcy5qcyIsInNyYy9jb21wb25lbnRzL3NsaWRlcnMvY29uc3RhbnRzLmpzIiwic3JjL2NvbXBvbmVudHMvc2xpZGVycy9kZWZhdWx0cy5qcyIsInNyYy9jb21wb25lbnRzL3NsaWRlcnMvZHJhdy5qcyIsInNyYy9jb21wb25lbnRzL3NsaWRlcnMvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy90aXRsZXMvaW5kZXguanMiLCJzcmMvY29tcG9uZW50cy91cGRhdGVtZW51cy9hdHRyaWJ1dGVzLmpzIiwic3JjL2NvbXBvbmVudHMvdXBkYXRlbWVudXMvY29uc3RhbnRzLmpzIiwic3JjL2NvbXBvbmVudHMvdXBkYXRlbWVudXMvZGVmYXVsdHMuanMiLCJzcmMvY29tcG9uZW50cy91cGRhdGVtZW51cy9kcmF3LmpzIiwic3JjL2NvbXBvbmVudHMvdXBkYXRlbWVudXMvc2Nyb2xsYm94LmpzIiwic3JjL2NvbnN0YW50cy9hbGlnbm1lbnQuanMiLCJzcmMvY29uc3RhbnRzL2ZpbHRlcl9vcHMuanMiLCJzcmMvY29uc3RhbnRzL2dsM2RfZGFzaGVzLmpzIiwic3JjL2NvbnN0YW50cy9nbDNkX21hcmtlcnMuanMiLCJzcmMvY29uc3RhbnRzL2ludGVyYWN0aW9ucy5qcyIsInNyYy9jb25zdGFudHMvbnVtZXJpY2FsLmpzIiwic3JjL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzLmpzIiwic3JjL2NvcmUuanMiLCJzcmMvZm9udHMvbWF0aGpheF9jb25maWcuanMiLCJzcmMvbGliL2FuZ2xlcy5qcyIsInNyYy9saWIvYXJyYXkuanMiLCJzcmMvbGliL2NsZWFuX251bWJlci5qcyIsInNyYy9saWIvY2xlYXJfZ2xfY2FudmFzZXMuanMiLCJzcmMvbGliL2NsZWFyX3Jlc3BvbnNpdmUuanMiLCJzcmMvbGliL2NvZXJjZS5qcyIsInNyYy9saWIvZGF0ZXMuanMiLCJzcmMvbGliL2V2ZW50cy5qcyIsInNyYy9saWIvZXh0ZW5kLmpzIiwic3JjL2xpYi9maWx0ZXJfdW5pcXVlLmpzIiwic3JjL2xpYi9maWx0ZXJfdmlzaWJsZS5qcyIsInNyYy9saWIvZ2VvX2xvY2F0aW9uX3V0aWxzLmpzIiwic3JjL2xpYi9nZW9qc29uX3V0aWxzLmpzIiwic3JjL2xpYi9nZW9tZXRyeTJkLmpzIiwic3JjL2xpYi9nZXRfZ3JhcGhfZGl2LmpzIiwic3JjL2xpYi9nbF9mb3JtYXRfY29sb3IuanMiLCJzcmMvbGliL2d1cC5qcyIsInNyYy9saWIvaHRtbDJ1bmljb2RlLmpzIiwic3JjL2xpYi9pZGVudGl0eS5qcyIsInNyYy9saWIvaW5kZXguanMiLCJzcmMvbGliL2lzX3BsYWluX29iamVjdC5qcyIsInNyYy9saWIva2V5ZWRfY29udGFpbmVyLmpzIiwic3JjL2xpYi9sb2NhbGl6ZS5qcyIsInNyYy9saWIvbG9nZ2Vycy5qcyIsInNyYy9saWIvbWFrZV90cmFjZV9ncm91cHMuanMiLCJzcmMvbGliL21hdHJpeC5qcyIsInNyYy9saWIvbW9kLmpzIiwic3JjL2xpYi9uZXN0ZWRfcHJvcGVydHkuanMiLCJzcmMvbGliL25vb3AuanMiLCJzcmMvbGliL25vdGlmaWVyLmpzIiwic3JjL2xpYi9vdmVycmlkZV9jdXJzb3IuanMiLCJzcmMvbGliL3BvbHlnb24uanMiLCJzcmMvbGliL3ByZXBhcmVfcmVnbC5qcyIsInNyYy9saWIvcHVzaF91bmlxdWUuanMiLCJzcmMvbGliL3F1ZXVlLmpzIiwic3JjL2xpYi9yZWdleC5qcyIsInNyYy9saWIvcmVsYXRpdmVfYXR0ci5qcyIsInNyYy9saWIvcmVsaW5rX3ByaXZhdGUuanMiLCJzcmMvbGliL3NlYXJjaC5qcyIsInNyYy9saWIvc2V0Y3Vyc29yLmpzIiwic3JjL2xpYi9zaG93X25vX3dlYmdsX21zZy5qcyIsInNyYy9saWIvc3RhdHMuanMiLCJzcmMvbGliL3N0cjJyZ2JhcnJheS5qcyIsInNyYy9saWIvc3ZnX3RleHRfdXRpbHMuanMiLCJzcmMvbGliL3Rocm90dGxlLmpzIiwic3JjL2xpYi90b19sb2dfcmFuZ2UuanMiLCJzcmMvbGliL3RvcG9qc29uX3V0aWxzLmpzIiwic3JjL2xvY2FsZS1lbi11cy5qcyIsInNyYy9sb2NhbGUtZW4uanMiLCJzcmMvcGxvdF9hcGkvY29udGFpbmVyX2FycmF5X21hdGNoLmpzIiwic3JjL3Bsb3RfYXBpL2VkaXRfdHlwZXMuanMiLCJzcmMvcGxvdF9hcGkvaGVscGVycy5qcyIsInNyYy9wbG90X2FwaS9pbmRleC5qcyIsInNyYy9wbG90X2FwaS9tYW5hZ2VfYXJyYXlzLmpzIiwic3JjL3Bsb3RfYXBpL3Bsb3RfYXBpLmpzIiwic3JjL3Bsb3RfYXBpL3Bsb3RfY29uZmlnLmpzIiwic3JjL3Bsb3RfYXBpL3Bsb3Rfc2NoZW1hLmpzIiwic3JjL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUuanMiLCJzcmMvcGxvdF9hcGkvc3Vicm91dGluZXMuanMiLCJzcmMvcGxvdF9hcGkvdGVtcGxhdGVfYXBpLmpzIiwic3JjL3Bsb3RfYXBpL3RvX2ltYWdlLmpzIiwic3JjL3Bsb3RfYXBpL3ZhbGlkYXRlLmpzIiwic3JjL3Bsb3RzL2FuaW1hdGlvbl9hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy9hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2UuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2F4ZXMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2F4aXNfYXV0b3R5cGUuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2F4aXNfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9jYXRlZ29yeV9vcmRlcl9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy9jYXJ0ZXNpYW4vY2xlYW5fdGlja3MuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cy5qcyIsInNyYy9wbG90cy9jYXJ0ZXNpYW4vY29uc3RyYWludF9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy9jYXJ0ZXNpYW4vY29uc3RyYWludHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2RyYWdib3guanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2dyYXBoX2ludGVyYWN0LmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL2luZGV4LmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2RlZmF1bHRzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9saW5lX2dyaWRfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL3Bvc2l0aW9uX2RlZmF1bHRzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9zY2FsZV96b29tLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi9zZWxlY3QuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL3NldF9jb252ZXJ0LmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzLmpzIiwic3JjL3Bsb3RzL2NhcnRlc2lhbi90aWNrX21hcmtfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvY2FydGVzaWFuL3RyYW5zaXRpb25fYXhlcy5qcyIsInNyYy9wbG90cy9jYXJ0ZXNpYW4vdHlwZV9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy9jb21tYW5kLmpzIiwic3JjL3Bsb3RzL2RvbWFpbi5qcyIsInNyYy9wbG90cy9mb250X2F0dHJpYnV0ZXMuanMiLCJzcmMvcGxvdHMvZnJhbWVfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9nZW8vY29uc3RhbnRzLmpzIiwic3JjL3Bsb3RzL2dlby9nZW8uanMiLCJzcmMvcGxvdHMvZ2VvL2luZGV4LmpzIiwic3JjL3Bsb3RzL2dlby9sYXlvdXQvYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9nZW8vbGF5b3V0L2RlZmF1bHRzLmpzIiwic3JjL3Bsb3RzL2dlby9sYXlvdXQvbGF5b3V0X2F0dHJpYnV0ZXMuanMiLCJzcmMvcGxvdHMvZ2VvL3Byb2plY3Rpb25zLmpzIiwic3JjL3Bsb3RzL2dlby96b29tLmpzIiwic3JjL3Bsb3RzL2dldF9kYXRhLmpzIiwic3JjL3Bsb3RzL2dsMmQvY2FtZXJhLmpzIiwic3JjL3Bsb3RzL2dsMmQvY29udmVydC5qcyIsInNyYy9wbG90cy9nbDJkL2luZGV4LmpzIiwic3JjL3Bsb3RzL2dsMmQvc2NlbmUyZC5qcyIsInNyYy9wbG90cy9nbDNkL2NhbWVyYS5qcyIsInNyYy9wbG90cy9nbDNkL2luZGV4LmpzIiwic3JjL3Bsb3RzL2dsM2QvbGF5b3V0L2F0dHJpYnV0ZXMuanMiLCJzcmMvcGxvdHMvZ2wzZC9sYXlvdXQvYXhpc19hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL2dsM2QvbGF5b3V0L2F4aXNfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvZ2wzZC9sYXlvdXQvY29udmVydC5qcyIsInNyYy9wbG90cy9nbDNkL2xheW91dC9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy9nbDNkL2xheW91dC9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9nbDNkL2xheW91dC9zcGlrZXMuanMiLCJzcmMvcGxvdHMvZ2wzZC9sYXlvdXQvdGlja19tYXJrcy5qcyIsInNyYy9wbG90cy9nbDNkL3Byb2plY3QuanMiLCJzcmMvcGxvdHMvZ2wzZC9zY2VuZS5qcyIsInNyYy9wbG90cy9nbDNkL3ppcDMuanMiLCJzcmMvcGxvdHMvbGF5b3V0X2F0dHJpYnV0ZXMuanMiLCJzcmMvcGxvdHMvbWFwYm94L2NvbnN0YW50cy5qcyIsInNyYy9wbG90cy9tYXBib3gvY29udmVydF90ZXh0X29wdHMuanMiLCJzcmMvcGxvdHMvbWFwYm94L2luZGV4LmpzIiwic3JjL3Bsb3RzL21hcGJveC9sYXllcnMuanMiLCJzcmMvcGxvdHMvbWFwYm94L2xheW91dF9hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL21hcGJveC9sYXlvdXRfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvbWFwYm94L21hcGJveC5qcyIsInNyYy9wbG90cy9wYWRfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9wbG90cy5qcyIsInNyYy9wbG90cy9wb2xhci9jb25zdGFudHMuanMiLCJzcmMvcGxvdHMvcG9sYXIvaGVscGVycy5qcyIsInNyYy9wbG90cy9wb2xhci9pbmRleC5qcyIsInNyYy9wbG90cy9wb2xhci9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9wb2xhci9sYXlvdXRfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvcG9sYXIvbGVnYWN5L2FyZWFfYXR0cmlidXRlcy5qcyIsInNyYy9wbG90cy9wb2xhci9sZWdhY3kvYXhpc19hdHRyaWJ1dGVzLmpzIiwic3JjL3Bsb3RzL3BvbGFyL2xlZ2FjeS9pbmRleC5qcyIsInNyYy9wbG90cy9wb2xhci9sZWdhY3kvbWljcm9wb2xhci5qcyIsInNyYy9wbG90cy9wb2xhci9sZWdhY3kvbWljcm9wb2xhcl9tYW5hZ2VyLmpzIiwic3JjL3Bsb3RzL3BvbGFyL2xlZ2FjeS91bmRvX21hbmFnZXIuanMiLCJzcmMvcGxvdHMvcG9sYXIvcG9sYXIuanMiLCJzcmMvcGxvdHMvcG9sYXIvc2V0X2NvbnZlcnQuanMiLCJzcmMvcGxvdHMvc3VicGxvdF9kZWZhdWx0cy5qcyIsInNyYy9wbG90cy90ZXJuYXJ5L2luZGV4LmpzIiwic3JjL3Bsb3RzL3Rlcm5hcnkvbGF5b3V0X2F0dHJpYnV0ZXMuanMiLCJzcmMvcGxvdHMvdGVybmFyeS9sYXlvdXRfZGVmYXVsdHMuanMiLCJzcmMvcGxvdHMvdGVybmFyeS90ZXJuYXJ5LmpzIiwic3JjL3JlZ2lzdHJ5LmpzIiwic3JjL3NuYXBzaG90L2Nsb25lcGxvdC5qcyIsInNyYy9zbmFwc2hvdC9kb3dubG9hZC5qcyIsInNyYy9zbmFwc2hvdC9maWxlc2F2ZXIuanMiLCJzcmMvc25hcHNob3QvaGVscGVycy5qcyIsInNyYy9zbmFwc2hvdC9pbmRleC5qcyIsInNyYy9zbmFwc2hvdC9zdmd0b2ltZy5qcyIsInNyYy9zbmFwc2hvdC90b2ltYWdlLmpzIiwic3JjL3NuYXBzaG90L3Rvc3ZnLmpzIiwic3JjL3RyYWNlcy9iYXIvYXJyYXlzX3RvX2NhbGNkYXRhLmpzIiwic3JjL3RyYWNlcy9iYXIvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvYmFyL2NhbGMuanMiLCJzcmMvdHJhY2VzL2Jhci9jcm9zc190cmFjZV9jYWxjLmpzIiwic3JjL3RyYWNlcy9iYXIvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2Jhci9oZWxwZXJzLmpzIiwic3JjL3RyYWNlcy9iYXIvaG92ZXIuanMiLCJzcmMvdHJhY2VzL2Jhci9pbmRleC5qcyIsInNyYy90cmFjZXMvYmFyL2xheW91dF9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9iYXIvbGF5b3V0X2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9iYXIvcGxvdC5qcyIsInNyYy90cmFjZXMvYmFyL3NlbGVjdC5qcyIsInNyYy90cmFjZXMvYmFyL3NpZXZlLmpzIiwic3JjL3RyYWNlcy9iYXIvc3R5bGUuanMiLCJzcmMvdHJhY2VzL2Jhci9zdHlsZV9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvYmFycG9sYXIvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvYmFycG9sYXIvY2FsYy5qcyIsInNyYy90cmFjZXMvYmFycG9sYXIvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2JhcnBvbGFyL2hvdmVyLmpzIiwic3JjL3RyYWNlcy9iYXJwb2xhci9pbmRleC5qcyIsInNyYy90cmFjZXMvYmFycG9sYXIvbGF5b3V0X2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL2JhcnBvbGFyL2xheW91dF9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvYmFycG9sYXIvcGxvdC5qcyIsInNyYy90cmFjZXMvYm94L2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL2JveC9jYWxjLmpzIiwic3JjL3RyYWNlcy9ib3gvY3Jvc3NfdHJhY2VfY2FsYy5qcyIsInNyYy90cmFjZXMvYm94L2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9ib3gvZXZlbnRfZGF0YS5qcyIsInNyYy90cmFjZXMvYm94L2hvdmVyLmpzIiwic3JjL3RyYWNlcy9ib3gvaW5kZXguanMiLCJzcmMvdHJhY2VzL2JveC9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvYm94L2xheW91dF9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvYm94L3Bsb3QuanMiLCJzcmMvdHJhY2VzL2JveC9zZWxlY3QuanMiLCJzcmMvdHJhY2VzL2JveC9zdHlsZS5qcyIsInNyYy90cmFjZXMvY2FuZGxlc3RpY2svYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvY2FuZGxlc3RpY2svY2FsYy5qcyIsInNyYy90cmFjZXMvY2FuZGxlc3RpY2svZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2NhbmRsZXN0aWNrL2luZGV4LmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvYWJfZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2NhcnBldC9hcnJheV9taW5tYXguanMiLCJzcmMvdHJhY2VzL2NhcnBldC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvYXhpc19hbGlnbmVkX2xpbmUuanMiLCJzcmMvdHJhY2VzL2NhcnBldC9heGlzX2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL2NhcnBldC9heGlzX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvY2FsYy5qcyIsInNyYy90cmFjZXMvY2FycGV0L2NhbGNfY2xpcHBhdGguanMiLCJzcmMvdHJhY2VzL2NhcnBldC9jYWxjX2dyaWRsaW5lcy5qcyIsInNyYy90cmFjZXMvY2FycGV0L2NhbGNfbGFiZWxzLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvY2F0bXVsbF9yb20uanMiLCJzcmMvdHJhY2VzL2NhcnBldC9jaGVhdGVyX2Jhc2lzLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvY29tcHV0ZV9jb250cm9sX3BvaW50cy5qcyIsInNyYy90cmFjZXMvY2FycGV0L2NvbnN0YW50cy5qcyIsInNyYy90cmFjZXMvY2FycGV0L2NyZWF0ZV9pX2Rlcml2YXRpdmVfZXZhbHVhdG9yLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvY3JlYXRlX2pfZGVyaXZhdGl2ZV9ldmFsdWF0b3IuanMiLCJzcmMvdHJhY2VzL2NhcnBldC9jcmVhdGVfc3BsaW5lX2V2YWx1YXRvci5qcyIsInNyYy90cmFjZXMvY2FycGV0L2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvaW5kZXguanMiLCJzcmMvdHJhY2VzL2NhcnBldC9sb29rdXBfY2FycGV0aWQuanMiLCJzcmMvdHJhY2VzL2NhcnBldC9tYWtlcGF0aC5qcyIsInNyYy90cmFjZXMvY2FycGV0L21hcF8xZF9hcnJheS5qcyIsInNyYy90cmFjZXMvY2FycGV0L29yaWVudF90ZXh0LmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvcGxvdC5qcyIsInNyYy90cmFjZXMvY2FycGV0L3NldF9jb252ZXJ0LmpzIiwic3JjL3RyYWNlcy9jYXJwZXQvc21vb3RoX2ZpbGxfMmRfYXJyYXkuanMiLCJzcmMvdHJhY2VzL2NhcnBldC94eV9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY2hvcm9wbGV0aC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9jaG9yb3BsZXRoL2NhbGMuanMiLCJzcmMvdHJhY2VzL2Nob3JvcGxldGgvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2Nob3JvcGxldGgvZXZlbnRfZGF0YS5qcyIsInNyYy90cmFjZXMvY2hvcm9wbGV0aC9ob3Zlci5qcyIsInNyYy90cmFjZXMvY2hvcm9wbGV0aC9pbmRleC5qcyIsInNyYy90cmFjZXMvY2hvcm9wbGV0aC9wbG90LmpzIiwic3JjL3RyYWNlcy9jaG9yb3BsZXRoL3NlbGVjdC5qcyIsInNyYy90cmFjZXMvY2hvcm9wbGV0aC9zdHlsZS5qcyIsInNyYy90cmFjZXMvY29uZS9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9jb25lL2NhbGMuanMiLCJzcmMvdHJhY2VzL2NvbmUvY29udmVydC5qcyIsInNyYy90cmFjZXMvY29uZS9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY29uZS9pbmRleC5qcyIsInNyYy90cmFjZXMvY29udG91ci9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9jb250b3VyL2NhbGMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXIvY2xvc2VfYm91bmRhcmllcy5qcyIsInNyYy90cmFjZXMvY29udG91ci9jb2xvcmJhci5qcyIsInNyYy90cmFjZXMvY29udG91ci9jb25zdGFudHMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXIvY29uc3RyYWludF9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY29udG91ci9jb25zdHJhaW50X21hcHBpbmcuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXIvY29udG91cnNfZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXIvY29udmVydF90b19jb25zdHJhaW50cy5qcyIsInNyYy90cmFjZXMvY29udG91ci9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY29udG91ci9lbXB0eV9wYXRoaW5mby5qcyIsInNyYy90cmFjZXMvY29udG91ci9lbmRfcGx1cy5qcyIsInNyYy90cmFjZXMvY29udG91ci9maW5kX2FsbF9wYXRocy5qcyIsInNyYy90cmFjZXMvY29udG91ci9ob3Zlci5qcyIsInNyYy90cmFjZXMvY29udG91ci9pbmRleC5qcyIsInNyYy90cmFjZXMvY29udG91ci9sYWJlbF9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY29udG91ci9tYWtlX2NvbG9yX21hcC5qcyIsInNyYy90cmFjZXMvY29udG91ci9tYWtlX2Nyb3NzaW5ncy5qcyIsInNyYy90cmFjZXMvY29udG91ci9wbG90LmpzIiwic3JjL3RyYWNlcy9jb250b3VyL3NldF9jb250b3Vycy5qcyIsInNyYy90cmFjZXMvY29udG91ci9zdHlsZS5qcyIsInNyYy90cmFjZXMvY29udG91ci9zdHlsZV9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvY29udG91cmNhcnBldC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9jb250b3VyY2FycGV0L2NhbGMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXJjYXJwZXQvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXJjYXJwZXQvaW5kZXguanMiLCJzcmMvdHJhY2VzL2NvbnRvdXJjYXJwZXQvam9pbl9hbGxfcGF0aHMuanMiLCJzcmMvdHJhY2VzL2NvbnRvdXJjYXJwZXQvbWFwX3BhdGhpbmZvLmpzIiwic3JjL3RyYWNlcy9jb250b3VyY2FycGV0L3Bsb3QuanMiLCJzcmMvdHJhY2VzL2hlYXRtYXAvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvaGVhdG1hcC9jYWxjLmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL2NsZWFuXzJkX2FycmF5LmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL2NvbG9yYmFyLmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL2NvbnZlcnRfY29sdW1uX3h5ei5qcyIsInNyYy90cmFjZXMvaGVhdG1hcC9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvaGVhdG1hcC9maW5kX2VtcHRpZXMuanMiLCJzcmMvdHJhY2VzL2hlYXRtYXAvaG92ZXIuanMiLCJzcmMvdHJhY2VzL2hlYXRtYXAvaW5kZXguanMiLCJzcmMvdHJhY2VzL2hlYXRtYXAvaW50ZXJwMmQuanMiLCJzcmMvdHJhY2VzL2hlYXRtYXAvbWFrZV9ib3VuZF9hcnJheS5qcyIsInNyYy90cmFjZXMvaGVhdG1hcC9tYXhfcm93X2xlbmd0aC5qcyIsInNyYy90cmFjZXMvaGVhdG1hcC9wbG90LmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL3N0eWxlLmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL3N0eWxlX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwL3h5el9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvaGVhdG1hcGdsL2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL2hlYXRtYXBnbC9jb252ZXJ0LmpzIiwic3JjL3RyYWNlcy9oZWF0bWFwZ2wvaW5kZXguanMiLCJzcmMvdHJhY2VzL2hpc3RvZ3JhbS9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0vYXZlcmFnZS5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtL2Jpbl9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0vYmluX2Z1bmN0aW9ucy5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtL2Jpbl9sYWJlbF92YWxzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0vY2FsYy5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtL2Nyb3NzX3RyYWNlX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0vZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2hpc3RvZ3JhbS9ldmVudF9kYXRhLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0vaG92ZXIuanMiLCJzcmMvdHJhY2VzL2hpc3RvZ3JhbS9pbmRleC5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtL25vcm1fZnVuY3Rpb25zLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZC9jYWxjLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZC9jcm9zc190cmFjZV9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtMmQvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL2hpc3RvZ3JhbTJkL2hvdmVyLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZC9pbmRleC5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtMmQvc2FtcGxlX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZGNvbnRvdXIvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvaGlzdG9ncmFtMmRjb250b3VyL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9oaXN0b2dyYW0yZGNvbnRvdXIvaW5kZXguanMiLCJzcmMvdHJhY2VzL21lc2gzZC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9tZXNoM2QvY2FsYy5qcyIsInNyYy90cmFjZXMvbWVzaDNkL2NvbnZlcnQuanMiLCJzcmMvdHJhY2VzL21lc2gzZC9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvbWVzaDNkL2luZGV4LmpzIiwic3JjL3RyYWNlcy9vaGxjL2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL29obGMvY2FsYy5qcyIsInNyYy90cmFjZXMvb2hsYy9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvb2hsYy9ob3Zlci5qcyIsInNyYy90cmFjZXMvb2hsYy9pbmRleC5qcyIsInNyYy90cmFjZXMvb2hsYy9vaGxjX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9vaGxjL3Bsb3QuanMiLCJzcmMvdHJhY2VzL29obGMvc2VsZWN0LmpzIiwic3JjL3RyYWNlcy9vaGxjL3N0eWxlLmpzIiwic3JjL3RyYWNlcy9wYXJjYXRzL2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL3BhcmNhdHMvYmFzZV9wbG90LmpzIiwic3JjL3RyYWNlcy9wYXJjYXRzL2NhbGMuanMiLCJzcmMvdHJhY2VzL3BhcmNhdHMvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3BhcmNhdHMvaW5kZXguanMiLCJzcmMvdHJhY2VzL3BhcmNhdHMvcGFyY2F0cy5qcyIsInNyYy90cmFjZXMvcGFyY2F0cy9wbG90LmpzIiwic3JjL3RyYWNlcy9wYXJjb29yZHMvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvcGFyY29vcmRzL2F4aXNicnVzaC5qcyIsInNyYy90cmFjZXMvcGFyY29vcmRzL2Jhc2VfcGxvdC5qcyIsInNyYy90cmFjZXMvcGFyY29vcmRzL2NhbGMuanMiLCJzcmMvdHJhY2VzL3BhcmNvb3Jkcy9jb25zdGFudHMuanMiLCJzcmMvdHJhY2VzL3BhcmNvb3Jkcy9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvcGFyY29vcmRzL2luZGV4LmpzIiwic3JjL3RyYWNlcy9wYXJjb29yZHMvbGluZXMuanMiLCJzcmMvdHJhY2VzL3BhcmNvb3Jkcy9tZXJnZV9sZW5ndGguanMiLCJzcmMvdHJhY2VzL3BhcmNvb3Jkcy9wYXJjb29yZHMuanMiLCJzcmMvdHJhY2VzL3BhcmNvb3Jkcy9wbG90LmpzIiwic3JjL3RyYWNlcy9waWUvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvcGllL2Jhc2VfcGxvdC5qcyIsInNyYy90cmFjZXMvcGllL2NhbGMuanMiLCJzcmMvdHJhY2VzL3BpZS9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvcGllL2V2ZW50X2RhdGEuanMiLCJzcmMvdHJhY2VzL3BpZS9oZWxwZXJzLmpzIiwic3JjL3RyYWNlcy9waWUvaW5kZXguanMiLCJzcmMvdHJhY2VzL3BpZS9sYXlvdXRfYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvcGllL2xheW91dF9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvcGllL3Bsb3QuanMiLCJzcmMvdHJhY2VzL3BpZS9zdHlsZS5qcyIsInNyYy90cmFjZXMvcGllL3N0eWxlX29uZS5qcyIsInNyYy90cmFjZXMvcG9pbnRjbG91ZC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9wb2ludGNsb3VkL2NvbnZlcnQuanMiLCJzcmMvdHJhY2VzL3BvaW50Y2xvdWQvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3BvaW50Y2xvdWQvaW5kZXguanMiLCJzcmMvdHJhY2VzL3NhbmtleS9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9zYW5rZXkvYmFzZV9wbG90LmpzIiwic3JjL3RyYWNlcy9zYW5rZXkvY2FsYy5qcyIsInNyYy90cmFjZXMvc2Fua2V5L2NvbnN0YW50cy5qcyIsInNyYy90cmFjZXMvc2Fua2V5L2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zYW5rZXkvaW5kZXguanMiLCJzcmMvdHJhY2VzL3NhbmtleS9wbG90LmpzIiwic3JjL3RyYWNlcy9zYW5rZXkvcmVuZGVyLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YS5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2NhbGMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24uanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2NvbnN0YW50cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9jcm9zc190cmFjZV9jYWxjLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2Nyb3NzX3RyYWNlX2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dC5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2hvdmVyLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2luZGV4LmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL2xpbmVfZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvbGluZV9wb2ludHMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvbGluZV9zaGFwZV9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9saW5rX3RyYWNlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9wbG90LmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL3NlbGVjdC5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9zdGFja19kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9zdHlsZS5qcyIsInNyYy90cmFjZXMvc2NhdHRlci9zdWJ0eXBlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlci90ZXh0X2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyL3h5X2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyM2QvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcjNkL2NhbGMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIzZC9jYWxjX2Vycm9ycy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcjNkL2NvbnZlcnQuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXIzZC9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcjNkL2luZGV4LmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyY2FycGV0L2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJjYXJwZXQvY2FsYy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcmNhcnBldC9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcmNhcnBldC9ldmVudF9kYXRhLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyY2FycGV0L2hvdmVyLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyY2FycGV0L2luZGV4LmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyY2FycGV0L3Bsb3QuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnZW8vYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcmdlby9jYWxjLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyZ2VvL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyZ2VvL2V2ZW50X2RhdGEuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnZW8vaG92ZXIuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnZW8vaW5kZXguanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnZW8vcGxvdC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcmdlby9zZWxlY3QuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnZW8vc3R5bGUuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJnbC9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyZ2wvY29uc3RhbnRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyZ2wvY29udmVydC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcmdsL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVyZ2wvaW5kZXguanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJtYXBib3gvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcm1hcGJveC9jb252ZXJ0LmpzIiwic3JjL3RyYWNlcy9zY2F0dGVybWFwYm94L2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVybWFwYm94L2V2ZW50X2RhdGEuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJtYXBib3gvaG92ZXIuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJtYXBib3gvaW5kZXguanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJtYXBib3gvcGxvdC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcm1hcGJveC9zZWxlY3QuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJwb2xhci9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVycG9sYXIvY2FsYy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnBvbGFyL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVycG9sYXIvaG92ZXIuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJwb2xhci9pbmRleC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnBvbGFyL3Bsb3QuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJwb2xhcmdsL2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJwb2xhcmdsL2RlZmF1bHRzLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVycG9sYXJnbC9pbmRleC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnkvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnkvY2FsYy5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnkvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJ0ZXJuYXJ5L2V2ZW50X2RhdGEuanMiLCJzcmMvdHJhY2VzL3NjYXR0ZXJ0ZXJuYXJ5L2hvdmVyLmpzIiwic3JjL3RyYWNlcy9zY2F0dGVydGVybmFyeS9pbmRleC5qcyIsInNyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnkvcGxvdC5qcyIsInNyYy90cmFjZXMvc3Bsb20vYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc3Bsb20vYmFzZV9wbG90LmpzIiwic3JjL3RyYWNlcy9zcGxvbS9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvc3Bsb20vaW5kZXguanMiLCJzcmMvdHJhY2VzL3N0cmVhbXR1YmUvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc3RyZWFtdHViZS9jYWxjLmpzIiwic3JjL3RyYWNlcy9zdHJlYW10dWJlL2NvbnZlcnQuanMiLCJzcmMvdHJhY2VzL3N0cmVhbXR1YmUvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3N0cmVhbXR1YmUvaW5kZXguanMiLCJzcmMvdHJhY2VzL3N1cmZhY2UvYXR0cmlidXRlcy5qcyIsInNyYy90cmFjZXMvc3VyZmFjZS9jYWxjLmpzIiwic3JjL3RyYWNlcy9zdXJmYWNlL2NvbnZlcnQuanMiLCJzcmMvdHJhY2VzL3N1cmZhY2UvZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3N1cmZhY2UvaW5kZXguanMiLCJzcmMvdHJhY2VzL3RhYmxlL2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL3RhYmxlL2Jhc2VfcGxvdC5qcyIsInNyYy90cmFjZXMvdGFibGUvY2FsYy5qcyIsInNyYy90cmFjZXMvdGFibGUvY29uc3RhbnRzLmpzIiwic3JjL3RyYWNlcy90YWJsZS9kYXRhX3ByZXBhcmF0aW9uX2hlbHBlci5qcyIsInNyYy90cmFjZXMvdGFibGUvZGF0YV9zcGxpdF9oZWxwZXJzLmpzIiwic3JjL3RyYWNlcy90YWJsZS9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvdGFibGUvaW5kZXguanMiLCJzcmMvdHJhY2VzL3RhYmxlL3Bsb3QuanMiLCJzcmMvdHJhY2VzL3Zpb2xpbi9hdHRyaWJ1dGVzLmpzIiwic3JjL3RyYWNlcy92aW9saW4vY2FsYy5qcyIsInNyYy90cmFjZXMvdmlvbGluL2Nyb3NzX3RyYWNlX2NhbGMuanMiLCJzcmMvdHJhY2VzL3Zpb2xpbi9kZWZhdWx0cy5qcyIsInNyYy90cmFjZXMvdmlvbGluL2hlbHBlcnMuanMiLCJzcmMvdHJhY2VzL3Zpb2xpbi9ob3Zlci5qcyIsInNyYy90cmFjZXMvdmlvbGluL2luZGV4LmpzIiwic3JjL3RyYWNlcy92aW9saW4vbGF5b3V0X2F0dHJpYnV0ZXMuanMiLCJzcmMvdHJhY2VzL3Zpb2xpbi9sYXlvdXRfZGVmYXVsdHMuanMiLCJzcmMvdHJhY2VzL3Zpb2xpbi9wbG90LmpzIiwic3JjL3RyYWNlcy92aW9saW4vc3R5bGUuanMiLCJzcmMvdHJhbnNmb3Jtcy9hZ2dyZWdhdGUuanMiLCJzcmMvdHJhbnNmb3Jtcy9maWx0ZXIuanMiLCJzcmMvdHJhbnNmb3Jtcy9ncm91cGJ5LmpzIiwic3JjL3RyYW5zZm9ybXMvaGVscGVycy5qcyIsInNyYy90cmFuc2Zvcm1zL3NvcnQuanMiLCJ0ZXN0L2ltYWdlL3N0cmljdC1kMy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDMWVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDMWtCQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ24yR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN2VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2piQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDdkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDOUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdFdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqMVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNwR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaERBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDam9DQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbitCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL09BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMxTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Z0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuZ0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNya0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzd2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM3lCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsZ0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1eUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3R0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDampCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25IQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBOztBQ0RBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3V0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBOzs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5WkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeFNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Y0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2dEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNNQSxZQUFZOztBQUVaLE1BQU0sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQzs7OztBQ0ZsQzs7Ozs7O0FBTUEsWUFBWTs7QUFFWixHQUFLLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQztBQUM5QyxHQUFLLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7QUFDOUIsR0FBSyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQ2xDLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6QyxHQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7QUFDckMsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO0FBQ2xDLEdBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDO0FBQzlDLEdBQUssQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztBQUMvQixHQUFLLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7QUFDOUIsR0FBSyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDOzs7QUFHakMsTUFBTSxDQUFDLE9BQU8sR0FBRyxTQUFTLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFO0NBQ3RELElBQUksQ0FBQyxPQUFPLElBQUUsT0FBTyxHQUFHLElBQUU7O0NBRTFCLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQzs7Q0FFekMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUU7RUFDdkIsTUFBTSxFQUFFLDhCQUE4QjtFQUN0QyxRQUFRLEVBQUUsd0RBQXdEO0VBQ2xFLEtBQUssRUFBRSw4Q0FBOEM7Ozs7RUFJckQsQ0FBQzs7O0NBR0YsR0FBRyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUM7Q0FDN0MsR0FBRyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0NBQzdELElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUU7Q0FDeEMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBRTs7Q0FFeEMsR0FBRyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQzs7O0NBR3pDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDO0NBQzlCLEdBQUcsQ0FBQyxHQUFHO0NBQ1AsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUUsT0FBTyxDQUFDLEtBQUssR0FBRyxTQUFPOztDQUUzQyxJQUFJLE9BQU8sT0FBTyxDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUU7RUFDdEMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQ25DO01BQ0ksSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFO0VBQ3ZCLEdBQUcsR0FBRyxPQUFPLENBQUMsS0FBSztFQUNuQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUUsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFDO0VBQ3RDO0NBQ0QsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFO0VBQzNCLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0VBQ1Y7OztDQUdELEdBQUcsQ0FBQyxNQUFNLEdBQUcsRUFBRTs7O0NBR2YsR0FBRyxDQUFDLFNBQVMsR0FBRyxFQUFFOzs7Q0FHbEIsR0FBRyxDQUFDLE1BQU0sR0FBRyxFQUFFOzs7Q0FHZixHQUFHLENBQUMsT0FBTyxHQUFHLEVBQUU7Ozs7Q0FJaEIsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDOzs7OztDQUt4QixHQUFHLENBQUMsTUFBTSxHQUFHLENBQUM7Q0FDZCxLQUFLLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFO0VBQ25ELEdBQUcsQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztFQUM5QixJQUFJLEdBQUcsQ0FBQyxHQUFHLElBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxHQUFDO09BQ25DO0dBQ0osS0FBSyxHQUFHLENBQUMsR0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsRUFBRSxFQUFFO0lBQ2xELEdBQUcsQ0FBQyxHQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLEdBQUMsQ0FBQztJQUMvQjtHQUNEO0VBQ0QsR0FBRyxDQUFDLFVBQVUsR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU07RUFDOUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQztFQUNyQyxNQUFNLEdBQUcsVUFBVTtFQUNuQjs7Q0FFRCxHQUFHLENBQUMsS0FBSyxHQUFHLEtBQUs7O0NBRWpCLE9BQU8sR0FBRzs7Ozs7Q0FLVixTQUFTLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRTtFQUM3QyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sSUFBRSxPQUFPLE1BQUk7OztFQUc1QixHQUFHLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7RUFDdEQsR0FBRyxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO0VBQ3ZELEdBQUcsQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztFQUMxRCxHQUFHLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNOztFQUU5QixLQUFLLEVBQUU7OztFQUdQLElBQUksS0FBSyxHQUFHLFFBQVEsRUFBRTtHQUNyQixLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3BDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3ZCLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ3JDOztHQUVELE9BQU8sTUFBTTtHQUNiOztFQUVELFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQ3ZCLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDOztFQUV2QixJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFO0dBQ3BCLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDO0dBQ3JDLE9BQU8sTUFBTTtHQUNiOzs7RUFHRCxHQUFHLENBQUMsRUFBRSxHQUFHLElBQUksR0FBRyxFQUFFO0VBQ2xCLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUU7OztFQUc1QixHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUU7O0VBRTlDLEtBQUssR0FBRyxDQUFDLEdBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEVBQUUsRUFBRTtHQUMzQyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFDLENBQUM7SUFDZixHQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDbkIsR0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztHQUN4QixHQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0dBQ2hHOztFQUVELEtBQUssS0FBSyxDQUFDO0VBQ1gsUUFBUSxDQUFDLElBQUk7R0FDWixJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUM7R0FDbEMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQztHQUN2QyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0dBQ3ZDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUM7R0FDeEM7O0VBRUQsT0FBTyxNQUFNO0VBQ2I7OztDQUdELFNBQVMsS0FBSyxFQUFFLEFBQVMsRUFBRTs7O0FBQUM7RUFDM0IsR0FBRyxDQUFDLE9BQU87O0VBRVgsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtHQUNqQyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUU7OztHQUdwQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLEdBQUcsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUU7SUFDekUsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDO0lBQ1osT0FBTyxHQUFHLEVBQUU7SUFDWjs7R0FFRCxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRTtJQUNuQixLQUFLLEVBQUUsZ0JBQWdCO0lBQ3ZCLENBQUMsRUFBRSxzRUFBc0U7SUFDekUsR0FBRyxFQUFFLDRCQUE0QjtJQUNqQyxDQUFDO0dBQ0Y7T0FDSTtHQUNKLE9BQU8sR0FBRyxFQUFFO0dBQ1o7O0VBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUUsSUFBSSxHQUFHLFFBQU07O0VBRS9CLEdBQUcsQ0FBQyxHQUFHLEdBQUcsVUFBSSxFQUFFLFFBQUcsSUFBSSxFQUFFOztFQUV6QixPQUE0QixHQUFHO0dBQzlCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7R0FDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztHQUNuQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO0dBQ2xDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUM7O0VBSi9CO0VBQU07RUFBTTtFQUFNLGtCQUt0Qjs7RUFFRCxTQUFnQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLE1BQU07RUFBeEU7RUFBTztFQUFPO0VBQU8scUJBQXFEOztFQUUvRSxHQUFHLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUM7OztFQUdwRCxJQUFJLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFO0dBQ3RCLEdBQUcsQ0FBQyxDQUFDO0dBQ0wsSUFBSSxPQUFPLE9BQU8sQ0FBQyxDQUFDLEtBQUssUUFBUSxJQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsR0FBQztRQUN4RCxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsR0FBQzs7R0FFeEMsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHO0lBQ2xCLElBQUksQ0FBQyxHQUFHO0tBQ1AsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDMUQsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDMUQ7SUFDRCxRQUFRO0lBQ1I7R0FDRDtFQUNELFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDOzs7RUFHNUMsSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO0dBQ2hCLE9BQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUM7R0FDaEQ7Ozs7O0VBS0QsR0FBRyxDQUFDLFNBQVMsR0FBRyxFQUFFOzs7RUFHbEIsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDOztFQUV6QixTQUFTLE1BQU0sR0FBRyxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsR0FBRztHQUNoRCxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxLQUFLLElBQUksSUFBRSxRQUFNOztHQUV4QyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDO0dBQ2pCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUM7OztHQUdqQixLQUFLLEtBQUssR0FBRyxHQUFHLElBQUksS0FBSyxHQUFHLEdBQUcsSUFBSSxLQUFLLEdBQUcsR0FBRyxJQUFJLEtBQUssR0FBRyxHQUFHLEtBQUcsUUFBTTtHQUN0RSxLQUFLLEtBQUssSUFBSSxRQUFRLEtBQUcsUUFBTTtHQUMvQixLQUFLLElBQUksS0FBSyxFQUFFLEtBQUcsUUFBTTs7O0dBR3pCLEdBQUcsQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQzs7R0FFOUIsSUFBSSxFQUFFLEtBQUssU0FBUyxJQUFFLEVBQUUsR0FBRyxVQUFVLENBQUMsUUFBTTs7R0FFNUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQy9CLEdBQUcsQ0FBQyxFQUFFLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQzs7SUFFdEIsR0FBRyxDQUFDLEVBQUUsR0FBRyxTQUFTLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFBRTtJQUM1QixHQUFHLENBQUMsRUFBRSxHQUFHLFNBQVMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTs7SUFFaEMsS0FBSyxFQUFFLElBQUksSUFBSSxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLElBQUksSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7S0FDOUU7SUFDRDs7O0dBR0QsR0FBRyxDQUFDLE9BQU8sR0FBRyxTQUFTLEVBQUUsS0FBSyxFQUFFO0dBQ2hDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0dBQ2xDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0dBQ2xDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0dBQ2xDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0dBQ2xDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDOztHQUV2QyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxFQUFFO0dBQ2YsR0FBRyxDQUFDLFNBQVMsR0FBRyxLQUFLLEdBQUcsQ0FBQztHQUN6QixNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLElBQUksSUFBSSxJQUFJLElBQUksSUFBSSxHQUFHLENBQUM7R0FDbkUsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksSUFBSSxJQUFJLElBQUksR0FBRyxDQUFDO0dBQ2hFLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDO0dBQ3hELE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDO0dBQ3JEOztFQUVELFNBQVMsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUU7R0FDbEMsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQyxHQUFHLENBQUM7R0FDeEIsTUFBTSxNQUFNLEtBQUssSUFBSSxFQUFFO0lBQ3RCLE1BQU0sR0FBRyxPQUFPLEVBQUUsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7SUFDaEMsQ0FBQyxFQUFFO0lBQ0gsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBRSxPQUFPLE1BQUk7SUFDbkM7R0FDRCxPQUFPLE1BQU07R0FDYjs7RUFFRCxPQUFPLFNBQVM7RUFDaEI7Ozs7Q0FJRCxTQUFTLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFO0VBQzNDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsRUFBRTs7RUFFZixLQUFLLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxRQUFRLEVBQUUsS0FBSyxFQUFFLEVBQUU7R0FDOUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDO0dBQy9CLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQzs7R0FFNUIsR0FBRyxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUM7R0FDNUMsR0FBRyxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUM7OztHQUcxQyxHQUFHLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLGVBQWUsQ0FBQztHQUN6RCxHQUFHLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7O0dBRTFGLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxJQUFJLEVBQUUsU0FBUyxHQUFHLElBQUksQ0FBQztHQUN0RDs7RUFFRCxPQUFPLE1BQU07RUFDYjs7O0NBR0QsU0FBUyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUU7RUFDNUIsR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDOztFQUViLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFO0VBQ3BCLEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBRTs7RUFFYixLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7R0FDL0IsS0FBSyxLQUFLLENBQUM7O0dBRVgsS0FBSyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQzs7R0FFckQsSUFBSSxJQUFJLEVBQUU7O0dBRVYsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSTtHQUMzQixFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJO0dBQzNCOztFQUVELE9BQU8sS0FBSztFQUNaO0NBQ0Q7Ozs7QUFJRCxTQUFTLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFO0NBQ2hDLEFBQUs7Q0FBSztDQUFLO0NBQUssb0JBQWE7Q0FDakMsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0NBQzlCLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztDQUM5QixHQUFHLENBQUMsTUFBTSxHQUFHLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7O0NBRWxDLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7RUFDL0MsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0VBQ3BELE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0VBQ3hEOztDQUVELE9BQU8sTUFBTTtDQUNiOztBQzdVRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDemZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TEE7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQSxZQUFZOztBQUVaLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6QyxHQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztBQUN2QyxHQUFLLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDekMsR0FBSyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDO0FBQ3JDLEdBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQztBQUN2QyxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztBQUM5QyxPQUF3QixHQUFHLE9BQU8sQ0FBQyxZQUFZO0FBQXhDO0FBQVMsMEJBQWdDOztBQUVoRCxNQUFNLENBQUMsT0FBTyxHQUFHLE9BQU87O0FBRXhCLEdBQUssQ0FBQyxPQUFPLEdBQUc7Ozs7Q0FJZixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ2xCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNuQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQzs7Q0FFcEIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDcEIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ25CLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7OztDQUdsQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDbkIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Q0FDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDOztDQUVuQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Q0FDbkIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNsQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7OztDQUduQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNwQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0NBQ3JCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDOztDQUVwQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztDQUNwQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDbkIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7OztDQUdwQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ2xCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNuQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQzs7Q0FFcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNsQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7OztDQUduQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDbkIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDOztDQUVuQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ2xCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNuQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7OztDQUduQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztDQUNwQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ3JCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDOztDQUVwQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDbkIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7Q0FDcEI7OztBQUdELFNBQVMsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7Q0FDaEMsSUFBSSxPQUFPLElBQUksS0FBSyxVQUFVLEVBQUU7RUFDL0IsSUFBSSxDQUFDLE9BQU8sSUFBRSxPQUFPLEdBQUcsSUFBRTtFQUMxQixPQUFPLENBQUMsSUFBSSxHQUFHLElBQUk7RUFDbkI7TUFDSTtFQUNKLE9BQU8sR0FBRyxJQUFJO0VBQ2Q7Q0FDRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUUsT0FBTyxDQUFDLFNBQVMsR0FBRyxTQUFPO0NBQy9DLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSTs7Q0FFbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsd0JBQXdCLENBQUMsRUFBRTtFQUNqRCxNQUFNLEtBQUssQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO0VBQ2xGOzs7Q0FHRCxHQUFHLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFVBQVU7R0FDdEcsUUFBUSxHQUFHO0lBQ1YsS0FBSyxFQUFFLE9BQU87SUFDZCxPQUFPLEVBQUUsQ0FBQztJQUNWLFNBQVMsRUFBRSxDQUFDO0lBQ1osT0FBTyxFQUFFLENBQUM7SUFDVixRQUFRLEVBQUUsSUFBSTtJQUNkLEtBQUssRUFBRSxJQUFJO0lBQ1gsTUFBTSxFQUFFLENBQUM7SUFDVCxLQUFLLEVBQUUsQ0FBQztJQUNSLE1BQU0sRUFBRSxJQUFJO0lBQ1osU0FBUyxFQUFFLEVBQUU7SUFDYixNQUFNLEVBQUUsRUFBRTtJQUNWLEVBQUUsTUFBTSxHQUFHLEVBQUU7OztDQUdoQixXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztFQUN6QixLQUFLLEVBQUUsU0FBUztFQUNoQixJQUFJLEVBQUUsT0FBTztFQUNiLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7RUFDdkIsQ0FBQzs7Q0FFRixjQUFjLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztFQUM1QixLQUFLLEVBQUUsU0FBUztFQUNoQixJQUFJLEVBQUUsT0FBTztFQUNiLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7RUFDdkIsQ0FBQzs7Q0FFRixtQkFBbUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0VBQ2pDLEtBQUssRUFBRSxTQUFTO0VBQ2hCLElBQUksRUFBRSxPQUFPO0VBQ2IsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztFQUN2QixDQUFDOztDQUVGLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0VBQ3pCLEtBQUssRUFBRSxTQUFTO0VBQ2hCLElBQUksRUFBRSxPQUFPO0VBQ2IsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztFQUN2QixDQUFDOztDQUVGLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0VBQ3hCLEtBQUssRUFBRSxRQUFRO0VBQ2YsSUFBSSxFQUFFLE9BQU87RUFDYixJQUFJLEVBQUUsT0FBTztFQUNiLENBQUM7O0NBRUYsTUFBTSxDQUFDLE9BQU8sQ0FBQzs7O0NBR2YsVUFBVSxHQUFHLElBQUksQ0FBQztFQUNqQixJQUFJLEVBQUUsbTdCQWlDTDs7RUFFRCxJQUFJLEVBQUUsa01BV0w7O0VBRUQsUUFBUSxFQUFFO0dBQ1QsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0dBQ3pCLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztHQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7R0FDN0IsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0dBQzdCLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztHQUN6QixTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7R0FDakMsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0dBQ25DLGNBQWMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO0dBQzNDLFFBQVEsV0FBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLGNBQWMsSUFBQztHQUNsRzs7RUFFRCxVQUFVLEVBQUU7O0dBRVgsS0FBSyxFQUFFO0lBQ04sTUFBTSxFQUFFLFdBQVc7SUFDbkIsTUFBTSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBQztJQUN0QyxPQUFPLEVBQUUsQ0FBQztJQUNWO0dBQ0QsUUFBUSxFQUFFO0lBQ1QsTUFBTSxFQUFFLGNBQWM7SUFDdEIsTUFBTSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBQztJQUN0QyxPQUFPLEVBQUUsQ0FBQztJQUNWO0dBQ0QsYUFBYSxFQUFFO0lBQ2QsTUFBTSxFQUFFLG1CQUFtQjtJQUMzQixNQUFNLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFDO0lBQ3RDLE9BQU8sRUFBRSxDQUFDO0lBQ1Y7R0FDRCxLQUFLLEVBQUU7SUFDTixNQUFNLEVBQUUsV0FBVztJQUNuQixNQUFNLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFFO0lBQ3ZDLE9BQU8sRUFBRSxDQUFDO0lBQ1Y7OztHQUdELFNBQVMsRUFBRTtJQUNWLE1BQU0sRUFBRSxVQUFVO0lBQ2xCLE1BQU0sRUFBRSxFQUFFO0lBQ1YsTUFBTSxFQUFFLENBQUM7SUFDVDtHQUNELFVBQVUsRUFBRTtJQUNYLE1BQU0sRUFBRSxVQUFVO0lBQ2xCLE1BQU0sRUFBRSxFQUFFO0lBQ1YsTUFBTSxFQUFFLENBQUM7SUFDVDtHQUNELFNBQVMsRUFBRTtJQUNWLE1BQU0sRUFBRSxVQUFVO0lBQ2xCLE1BQU0sRUFBRSxFQUFFO0lBQ1YsTUFBTSxFQUFFLEVBQUU7SUFDVjtHQUNEOztFQUVELFNBQVMsRUFBRSxXQUFXOztFQUV0QixLQUFLLEVBQUU7R0FDTixNQUFNLEVBQUUsSUFBSTtHQUNaLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztHQUNoQixRQUFRLEVBQUU7SUFDVCxHQUFHLEVBQUUsS0FBSztJQUNWLEtBQUssRUFBRSxLQUFLO0lBQ1o7R0FDRCxJQUFJLEVBQUU7SUFDTCxNQUFNLEVBQUUsV0FBVztJQUNuQixNQUFNLEVBQUUscUJBQXFCO0lBQzdCLFFBQVEsRUFBRSxxQkFBcUI7SUFDL0IsUUFBUSxFQUFFLEtBQUs7SUFDZjtHQUNEOztFQUVELEtBQUssRUFBRTtHQUNOLE1BQU0sRUFBRSxLQUFLO0dBQ2I7O0VBRUQsT0FBTyxFQUFFO0dBQ1IsTUFBTSxFQUFFLElBQUk7R0FDWixHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7R0FDMUI7RUFDRCxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7RUFDL0IsT0FBTyxFQUFFLEtBQUs7O0VBRWQsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0VBQzdCLEtBQUssRUFBRSxPQUFPLENBQUMsTUFBTTtFQUNyQixDQUFDOzs7Q0FHRixNQUFNLENBQUMsT0FBTyxFQUFFO0VBQ2YsTUFBTSxFQUFFLE1BQU07RUFDZCxJQUFJLEVBQUUsSUFBSTtFQUNWLE9BQU8sRUFBRSxPQUFPO0VBQ2hCLElBQUksRUFBRSxJQUFJO0VBQ1YsRUFBRSxFQUFFLEVBQUU7RUFDTixNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU07RUFDakIsTUFBTSxFQUFFLE1BQU07RUFDZCxDQUFDOztDQUVGLE9BQU8sT0FBTzs7Q0FFZCxTQUFTLE9BQU8sRUFBRSxJQUFJLEVBQUU7O0VBRXZCLElBQUksSUFBSSxFQUFFO0dBQ1QsTUFBTSxDQUFDLElBQUksQ0FBQztHQUNaOzs7T0FHSSxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUU7R0FDdkIsT0FBTyxFQUFFO0dBQ1Q7O0VBRUQsSUFBSSxFQUFFO0VBQ047Ozs7Q0FJRCxTQUFTLElBQUksRUFBRSxPQUFPLEVBQUU7RUFDdkIsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUUsT0FBTyxTQUFTLENBQUMsT0FBTyxHQUFDOzs7RUFHMUQsSUFBSSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFFLE9BQU8sR0FBRyxDQUFDLE9BQU8sR0FBQzs7O0VBRzNELElBQUksQ0FBQyxRQUFRLEVBQUU7OztFQUdmLE1BQU0sQ0FBQyxPQUFPLFVBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEFBQUc7R0FDeEIsSUFBSSxDQUFDLENBQUMsSUFBRSxRQUFNOztHQUVkLElBQUksT0FBTyxFQUFFO0lBQ1osSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLE9BQUs7V0FDMUIsQ0FBQyxDQUFDLElBQUksR0FBRyxNQUFJO0lBQ2xCOzs7R0FHRCxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtJQUNaLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ2QsTUFBTTtJQUNOOztHQUVELFNBQVMsQ0FBQyxDQUFDLENBQUM7R0FDWixDQUFDO0VBQ0Y7OztDQUdELFNBQVMsU0FBUyxFQUFFLENBQUMsRUFBRTtFQUN0QixJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBQztFQUN4QyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUUsUUFBTTs7RUFFckIsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLElBQUUsUUFBTTs7RUFFNUYsQ0FBQyxDQUFDLFVBQVUsR0FBRztHQUNkLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLO0dBQzdCLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0dBQzlCOztFQUVELFVBQVUsQ0FBQyxDQUFDLENBQUM7O0VBRWIsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFDO0VBQ3ZCOztDQUVELFNBQVMsTUFBTSxFQUFFLE9BQU8sRUFBRTtFQUN6QixJQUFJLENBQUMsT0FBTyxJQUFFLFFBQU07OztFQUdwQixJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFO0dBQzNCLElBQUksT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxJQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxHQUFDO0dBQ3BFOzs7T0FHSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBRSxPQUFPLEdBQUcsQ0FBQyxPQUFPLEdBQUM7OztFQUdyRCxHQUFHLENBQUMsVUFBVSxHQUFHLENBQUMsRUFBRSxVQUFVLEdBQUcsQ0FBQzs7RUFFbEMsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsVUFBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQUFBRztHQUNyRCxHQUFHLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUM7O0dBRXJCLElBQUksQ0FBQyxPQUFPLElBQUUsT0FBTyxPQUFLO1FBQ3JCLElBQUksT0FBTyxPQUFPLEtBQUssVUFBVSxJQUFFLE9BQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLEdBQUM7UUFDN0QsSUFBSSxPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUUsT0FBTyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sR0FBQzs7O0dBR3ZFLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFO0lBQ3ZCLEtBQUssRUFBRSxtQkFBbUI7SUFDMUIsT0FBTyxFQUFFLDhCQUE4QjtJQUN2QyxTQUFTLEVBQUUsMkNBQTJDO0lBQ3RELE9BQU8sRUFBRSxlQUFlO0lBQ3hCLEtBQUssRUFBRSxlQUFlO0lBQ3RCLFFBQVEsRUFBRSxrQkFBa0I7SUFDNUIsTUFBTSxFQUFFLGNBQWM7SUFDdEIsU0FBUyxFQUFFLGdDQUFnQztJQUMzQyxDQUFDOztHQUVGLElBQUksQ0FBQyxLQUFLLEVBQUU7SUFDWCxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHO0tBQ25CLEVBQUUsRUFBRSxDQUFDO0tBQ0wsS0FBSyxFQUFFLElBQUk7S0FDWCxTQUFTLEVBQUUsSUFBSTtLQUNmLFVBQVUsRUFBRSxJQUFJO0tBQ2hCLGNBQWMsRUFBRSxJQUFJO0tBQ3BCLElBQUksRUFBRSxJQUFJO0tBQ1Y7SUFDRCxPQUFPLEdBQUcsTUFBTSxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDO0lBQ3ZDOztHQUVELFVBQVUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDM0IsU0FBUyxZQUFFLEVBQUMsQ0FBQyxTQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUU7SUFDdkIsT0FBTyxZQUFFLEVBQUMsQ0FBQyxTQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUU7SUFDckIsT0FBTyxFQUFFLFVBQVU7SUFDbkIsTUFBTSxZQUFFLE9BQU0sQ0FBQyxBQUFHO0tBQ2pCLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDOztLQUV4QixVQUFVLElBQUksTUFBTSxDQUFDLE1BQU07S0FDM0IsT0FBTyxNQUFNO0tBQ2I7SUFDRCxTQUFTLFdBQUUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLEFBQUc7S0FDaEMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDO0tBQ3pDLEtBQUssQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztLQUM5QyxLQUFLLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO0tBQ3RDLEtBQUssQ0FBQyxNQUFNLEdBQUcsVUFBVTs7S0FFekIsVUFBVSxJQUFJLEtBQUssQ0FBQyxLQUFLOztLQUV6QixPQUFPLFNBQVM7S0FDaEI7SUFDRCxFQUFFO0lBQ0YsS0FBSyxXQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxBQUFHO0tBQ3pCLEdBQUcsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUs7O0tBRXZCLElBQUksQ0FBQyxNQUFNLElBQUUsTUFBTSxHQUFHLGVBQWE7OztLQUduQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7TUFDNUQsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFNO01BQ2xCLE1BQU0sR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO01BQ3JCLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtPQUMvQixNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSztPQUNqQjtNQUNEOztLQUVELElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxLQUFLLElBQUUsTUFBTSxLQUFLLENBQUMsbUJBQW1CLEdBQUM7O0tBRTNELEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxVQUFVLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQzs7O0tBR3pDLEtBQUssR0FBRyxDQUFDLEdBQUMsR0FBRyxDQUFDLEVBQUUsR0FBQyxHQUFHLEtBQUssRUFBRSxHQUFDLEVBQUUsRUFBRTtNQUMvQixHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDO01BQ2hDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUMsR0FBRyxDQUFDLENBQUM7TUFDdkI7O0tBRUQsT0FBTyxTQUFTO0tBQ2hCOztJQUVELEtBQUssV0FBRSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEFBQUc7S0FDakMsR0FBRyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTTtLQUN6QixJQUFJLENBQUMsS0FBSyxJQUFFLEtBQUssR0FBRyxRQUFNOztLQUUxQixLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNwRSxLQUFLLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7O0tBRXhDLEtBQUssQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7S0FDdkMsS0FBSyxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQzs7S0FFL0MsT0FBTyxLQUFLO0tBQ1o7O0lBRUQsUUFBUSxZQUFFLEdBQUUsQ0FBQyxBQUFHO0tBQ2YsR0FBRyxDQUFDLFFBQVE7O0tBRVosSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFO01BQ3RCLFFBQVEsR0FBRztPQUNWLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO09BQ1IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7T0FDUixLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7T0FDcEIsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO09BQ3JCO01BQ0Q7VUFDSSxJQUFJLEVBQUUsRUFBRTtNQUNaLFFBQVEsR0FBRztPQUNWLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQztPQUN2QixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUM7T0FDdEI7O01BRUQsSUFBSSxFQUFFLENBQUMsS0FBSyxJQUFFLFFBQVEsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUMsR0FBQzthQUMvQyxRQUFRLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssSUFBSSxHQUFDOztNQUUzQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLElBQUUsUUFBUSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxHQUFDO2FBQ2xELFFBQVEsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxJQUFJLEdBQUM7TUFDN0M7VUFDSTtNQUNKLFFBQVEsR0FBRztPQUNWLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7T0FDVixLQUFLLEVBQUUsRUFBRSxDQUFDLGtCQUFrQjtPQUM1QixNQUFNLEVBQUUsRUFBRSxDQUFDLG1CQUFtQjtPQUM5QjtNQUNEOztLQUVELE9BQU8sUUFBUTtLQUNmO0lBQ0QsQ0FBQyxDQUFDOztHQUVILE9BQU8sS0FBSztHQUNaLENBQUM7O0VBRUYsSUFBSSxVQUFVLElBQUksVUFBVSxFQUFFO0dBQzdCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLE1BQU0sVUFBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEFBQUc7SUFDMUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDdEMsRUFBRSxDQUFDLENBQUM7O0dBRUwsR0FBRyxDQUFDLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0dBQzVDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztHQUN2QyxHQUFHLENBQUMsU0FBUyxHQUFHLElBQUksWUFBWSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7O0dBRXpDLE1BQU0sQ0FBQyxPQUFPLFVBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEFBQUc7SUFDNUIsSUFBSSxDQUFDLEtBQUssSUFBRSxRQUFNO0lBQ2xCLEFBQUs7SUFBVztJQUFPO0lBQVE7SUFBTywwQkFBZTtJQUNyRCxJQUFJLENBQUMsS0FBSyxJQUFFLFFBQU07O0lBRWxCLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDaEMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNqQyxZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7O0dBRUYsY0FBYyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztHQUNyQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7R0FDMUMsV0FBVyxDQUFDLFNBQVMsQ0FBQztHQUN0QixXQUFXLENBQUMsU0FBUyxDQUFDO0dBQ3RCOztFQUVEOztDQUVELFNBQVMsT0FBTyxJQUFJO0VBQ25CLGNBQWMsQ0FBQyxPQUFPLEVBQUU7RUFDeEIsbUJBQW1CLENBQUMsT0FBTyxFQUFFO0VBQzdCLFdBQVcsQ0FBQyxPQUFPLEVBQUU7RUFDckIsV0FBVyxDQUFDLE9BQU8sRUFBRTtFQUNyQixVQUFVLENBQUMsT0FBTyxFQUFFO0VBQ3BCO0NBQ0Q7O0FDMWdCRCxZQUFZOzs7QUFHWixHQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztBQUN2QyxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7QUFDekMsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDO0FBQ3ZDLEdBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztBQUNsQyxHQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7QUFDckMsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUM7QUFDOUMsR0FBSyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO0FBQ3JDLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDO0FBQzVDLE9BQTBCLEdBQUcsT0FBTyxDQUFDLFlBQVk7QUFBekM7QUFBUywwQkFBaUM7QUFDbEQsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQ3ZDLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQzs7O0FBR3ZDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTTs7OztBQUl2QixTQUFTLE1BQU0sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0NBQy9CLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxNQUFNLENBQUMsSUFBRSxPQUFPLElBQUksTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLEdBQUM7O0NBRS9ELElBQUksT0FBTyxJQUFJLEtBQUssVUFBVSxFQUFFO0VBQy9CLElBQUksQ0FBQyxPQUFPLElBQUUsT0FBTyxHQUFHLElBQUU7RUFDMUIsT0FBTyxDQUFDLElBQUksR0FBRyxJQUFJO0VBQ25CO01BQ0k7RUFDSixPQUFPLEdBQUcsSUFBSTtFQUNkO0NBQ0QsSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFFLE9BQU8sQ0FBQyxTQUFTLEdBQUcsU0FBTztDQUMvQyxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUk7O0NBRW5CLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLHdCQUF3QixDQUFDLEVBQUU7RUFDakQsTUFBTSxLQUFLLENBQUMsb0VBQW9FLENBQUMsQ0FBQztFQUNsRjs7O0NBR0QsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRztDQUNsQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUk7OztDQUdoQixJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUU7OztDQUdoQixJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQzs7OztDQUluSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztDQUNwQjs7O0FBR0QsTUFBTSxDQUFDLFFBQVEsR0FBRyxDQUFDO0FBQ25CLE1BQU0sQ0FBQyxnQkFBZ0IsR0FBRyxHQUFHO0FBQzdCLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxHQUFHO0FBQy9CLE1BQU0sQ0FBQyxTQUFTLEdBQUcsR0FBRztBQUN0QixNQUFNLENBQUMsUUFBUSxHQUFHLElBQUk7Ozs7QUFJdEIsTUFBTSxDQUFDLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRTs7OztBQUk5QixNQUFNLENBQUMsYUFBYSxHQUFHLFVBQVUsSUFBSSxFQUFFO0NBQ3RDLEdBQUcsQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztFQUM5QixLQUFLLEVBQUUsUUFBUTtFQUNmLElBQUksRUFBRSxPQUFPO0VBQ2IsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztFQUMxQixDQUFDOztDQUVGLEdBQUcsQ0FBQyxhQUFhLEdBQUc7RUFDbkIsU0FBUyxFQUFFLGdCQUFnQjtFQUMzQixTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7RUFDN0IsS0FBSyxFQUFFLENBQUM7RUFDUixNQUFNLEVBQUUsQ0FBQzs7RUFFVCxRQUFRLEVBQUU7R0FDVCxTQUFTLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLElBQUksS0FBSyxPQUFPLEdBQUcsQ0FBQyxHQUFHLElBQUM7R0FDdkQsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0dBQ25DLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztHQUN6QixVQUFVLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7R0FDbkMsY0FBYyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7R0FDM0MsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO0dBQ2pDLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztHQUNqQyxXQUFXLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7R0FDckMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0dBQzdCLFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztHQUN0QyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7R0FDbkIsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0dBQ2pDLFFBQVEsV0FBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBRyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLGNBQWMsSUFBQztHQUNuRixLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7R0FDekI7O0VBRUQsS0FBSyxFQUFFO0dBQ04sTUFBTSxFQUFFLElBQUk7R0FDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7R0FDaEIsUUFBUSxFQUFFO0lBQ1QsR0FBRyxFQUFFLEtBQUs7SUFDVixLQUFLLEVBQUUsS0FBSztJQUNaO0dBQ0QsSUFBSSxFQUFFO0lBQ0wsTUFBTSxFQUFFLFdBQVc7SUFDbkIsTUFBTSxFQUFFLHFCQUFxQjtJQUM3QixRQUFRLEVBQUUscUJBQXFCO0lBQy9CLFFBQVEsRUFBRSxLQUFLO0lBQ2Y7R0FDRDtFQUNELEtBQUssRUFBRTtHQUNOLE1BQU0sV0FBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQUFBRztJQUNqQixPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU87SUFDakI7R0FDRDtFQUNELE9BQU8sRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUM7RUFDeEIsT0FBTyxFQUFFO0dBQ1IsTUFBTSxFQUFFLElBQUk7R0FDWixHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7R0FDMUI7RUFDRCxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7RUFDL0I7Ozs7Q0FJRCxHQUFHLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7RUFDOUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLGd2Q0FBZ3ZDLENBQUMsQ0FBQztFQUNqd0MsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLHViQUF1YixDQUFDLENBQUM7O0VBRXhjLFVBQVUsRUFBRTs7R0FFWCxPQUFPLEVBQUU7SUFDUixNQUFNLEVBQUUsWUFBWTtJQUNwQixPQUFPLEVBQUUsQ0FBQztJQUNWLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVDs7R0FFRCxPQUFPLEVBQUU7SUFDUixNQUFNLEVBQUUsWUFBWTtJQUNwQixPQUFPLEVBQUUsQ0FBQztJQUNWLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVDs7R0FFRCxNQUFNLEVBQUU7SUFDUCxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUNuQyxNQUFNLEVBQUUsQ0FBQztJQUNULE1BQU0sRUFBRSxDQUFDO0lBQ1QsT0FBTyxFQUFFLENBQUM7SUFDVjs7R0FFRCxNQUFNLEVBQUU7SUFDUCxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUNuQyxNQUFNLEVBQUUsQ0FBQztJQUNULE1BQU0sRUFBRSxFQUFFO0lBQ1YsT0FBTyxFQUFFLENBQUM7SUFDVjtHQUNELFdBQVcsRUFBRTtJQUNaLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDO0lBQ3hDLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVCxPQUFPLEVBQUUsQ0FBQztJQUNWO0dBQ0QsV0FBVyxFQUFFO0lBQ1osTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUM7SUFDeEMsTUFBTSxFQUFFLENBQUM7SUFDVCxNQUFNLEVBQUUsRUFBRTtJQUNWLE9BQU8sRUFBRSxDQUFDO0lBQ1Y7R0FDRCxLQUFLLEVBQUU7SUFDTixNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDaEMsTUFBTSxFQUFFLENBQUM7SUFDVCxNQUFNLEVBQUUsQ0FBQztJQUNULE9BQU8sRUFBRSxDQUFDO0lBQ1Y7R0FDRDtFQUNELEVBQUUsYUFBYSxDQUFDLENBQUM7OztDQUdsQixHQUFHLENBQUMsYUFBYTs7Q0FFakIsSUFBSTtFQUNILGFBQWEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDOztHQUUzQixJQUFJLEVBQUU7SUFDTCxNQUFNLEVBQUUsSUFBSTtJQUNaLElBQUksRUFBRSxNQUFNO0lBQ1o7O0dBRUQsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLDJ2UUFBMnZRLENBQUMsQ0FBQztHQUM1d1EsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLCtrRUFBK2tFLENBQUMsQ0FBQzs7R0FFaG1FLFVBQVUsRUFBRTs7SUFFWCxPQUFPLEVBQUU7S0FDUixNQUFNLEVBQUUsWUFBWTtLQUNwQixPQUFPLEVBQUUsQ0FBQztLQUNWLE1BQU0sRUFBRSxDQUFDO0tBQ1QsTUFBTSxFQUFFLENBQUM7S0FDVDs7SUFFRCxPQUFPLEVBQUU7S0FDUixNQUFNLEVBQUUsWUFBWTtLQUNwQixPQUFPLEVBQUUsQ0FBQztLQUNWLE1BQU0sRUFBRSxDQUFDO0tBQ1QsTUFBTSxFQUFFLENBQUM7S0FDVDs7SUFFRCxNQUFNLEVBQUU7S0FDUCxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7S0FDaEMsTUFBTSxFQUFFLENBQUM7S0FDVCxNQUFNLEVBQUUsQ0FBQztLQUNULE9BQU8sRUFBRSxDQUFDO0tBQ1Y7O0lBRUQsTUFBTSxFQUFFO0tBQ1AsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDO0tBQ2hDLE1BQU0sRUFBRSxDQUFDO0tBQ1QsTUFBTSxFQUFFLENBQUM7S0FDVCxPQUFPLEVBQUUsQ0FBQztLQUNWO0lBQ0QsU0FBUyxFQUFFO0tBQ1YsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7S0FDbkMsTUFBTSxFQUFFLENBQUM7S0FDVCxNQUFNLEVBQUUsQ0FBQztLQUNULE9BQU8sRUFBRSxDQUFDO0tBQ1Y7SUFDRCxNQUFNLEVBQUU7S0FDUCxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztLQUNuQyxNQUFNLEVBQUUsQ0FBQztLQUNULE1BQU0sRUFBRSxDQUFDO0tBQ1QsT0FBTyxFQUFFLENBQUM7S0FDVjtJQUNELE1BQU0sRUFBRTtLQUNQLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO0tBQ25DLE1BQU0sRUFBRSxDQUFDO0tBQ1QsTUFBTSxFQUFFLEVBQUU7S0FDVixPQUFPLEVBQUUsQ0FBQztLQUNWO0lBQ0QsU0FBUyxFQUFFO0tBQ1YsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7S0FDbkMsTUFBTSxFQUFFLENBQUM7S0FDVCxNQUFNLEVBQUUsRUFBRTtLQUNWLE9BQU8sRUFBRSxDQUFDO0tBQ1Y7SUFDRDtHQUNELEVBQUUsYUFBYSxDQUFDLENBQUM7RUFDbEIsQ0FBQyxPQUFPLENBQUMsRUFBRTs7RUFFWCxhQUFhLEdBQUcsWUFBWTtFQUM1Qjs7O0NBR0QsR0FBRyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7RUFDbkIsU0FBUyxFQUFFLFVBQVU7RUFDckIsUUFBUSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxZQUFTO0VBQ3ZDLE1BQU0sRUFBRSxDQUFDOztFQUVULElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyw0cEJBQTRwQixDQUFDLENBQUM7RUFDN3FCLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyx5SEFBeUgsQ0FBQyxDQUFDOztFQUUxSSxRQUFRLEVBQUU7R0FDVCxLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7R0FDekIsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQ3hCLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztHQUNuQyxjQUFjLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztHQUMzQyxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7R0FDakMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0dBQzdCLFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztHQUN0QyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7R0FDbkIsUUFBUSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsY0FBYyxJQUFDO0dBQ2xHOztFQUVELFVBQVUsRUFBRTtHQUNYLFFBQVEsRUFBRTtJQUNULE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ25DLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVDtHQUNELGFBQWEsRUFBRTtJQUNkLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDO0lBQ3hDLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVDtHQUNEOztFQUVELEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSzs7RUFFMUIsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtFQUN4QixPQUFPLEVBQUUsYUFBYSxDQUFDLE9BQU87RUFDOUIsT0FBTyxFQUFFLGFBQWEsQ0FBQyxPQUFPO0VBQzlCLFFBQVEsRUFBRSxhQUFhLENBQUMsUUFBUTtFQUNoQyxDQUFDOztDQUVGLE9BQU87RUFDTixJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLGFBQWE7RUFDeEQ7Q0FDRDs7OztBQUlELE1BQU0sQ0FBQyxRQUFRLEdBQUc7Q0FDakIsTUFBTSxFQUFFLElBQUk7Q0FDWixJQUFJLEVBQUUsT0FBTztDQUNiLFVBQVUsRUFBRSxDQUFDO0NBQ2IsU0FBUyxFQUFFLEVBQUU7Q0FDYixHQUFHLEVBQUUsUUFBUTtDQUNiLEtBQUssRUFBRSxPQUFPO0NBQ2QsT0FBTyxFQUFFLENBQUM7Q0FDVixPQUFPLEVBQUUsS0FBSztDQUNkLFFBQVEsRUFBRSxJQUFJO0NBQ2QsS0FBSyxFQUFFLElBQUk7Q0FDWCxLQUFLLEVBQUUsS0FBSztDQUNaLElBQUksRUFBRSxJQUFJO0NBQ1Y7OztBQUdELE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsQUFBTyxFQUFFOzs7O2dEQUFDO0NBQzdDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtTQUNoQixLQUFJLENBQUMsWUFBTSxDQUFDLEtBQUcsSUFBSSxDQUFDO0VBQ3BCOztDQUVELElBQUksQ0FBQyxJQUFJLEVBQUU7Q0FDWDs7O0FBR0QsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsVUFBVSxBQUFPLEVBQUU7Ozs7QUFBQzs7Q0FFM0MsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxVQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxBQUFHOztBQUFDOztFQUVyRCxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFFLGNBQU8sT0FBSSxDQUFDLFVBQUksQ0FBQyxLQUFHLENBQUMsR0FBQzs7RUFFakQsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUUsQ0FBQyxHQUFHLE1BQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFDOztFQUU3QyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFFLFFBQU07O0VBRTVDLE1BQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFOztFQUVwQixJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7R0FDcEQsTUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0dBQ3BCOztFQUVELElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxJQUFFLFFBQU07OztFQUd4QixJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixFQUFFO0dBQzVILE1BQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztHQUNwQjs7O09BR0ksSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUU7R0FDN0YsTUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0dBQ3BCO09BQ0k7R0FDSixNQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7R0FDckI7RUFDRCxDQUFDOztDQUVGLE9BQU8sSUFBSTtDQUNYOztBQUVELE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsT0FBTyxFQUFFOztBQUFDO0NBQzdDLElBQUksQ0FBQyxPQUFPLElBQUUsUUFBTTs7Q0FFcEIsSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFJLElBQUksRUFBRTtFQUMzQixJQUFJLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsSUFBRSxPQUFPLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBQztFQUNwRTs7O01BR0ksSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUUsT0FBTyxHQUFHLENBQUMsT0FBTyxHQUFDOztDQUVyRCxPQUFnQixHQUFHO0NBQWI7Q0FBTSxnQkFBVzs7O0NBR3ZCLE9BQU8sQ0FBQyxPQUFPLFVBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEFBQUc7RUFDekIsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQzs7RUFFMUIsSUFBSSxDQUFDLEtBQUssU0FBUyxJQUFFLFFBQU07OztFQUczQixJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUU7R0FDZixNQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUk7R0FDckIsTUFBTTtHQUNOOztFQUVELElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxJQUFFLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDLEdBQUM7OztFQUdoRCxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsRUFBRTtHQUNYLFNBQVMsRUFBRSw4QkFBOEI7R0FDekMsU0FBUyxFQUFFLGdHQUFnRztHQUMzRyxJQUFJLEVBQUUsa0NBQWtDO0dBQ3hDLFVBQVUsRUFBRSx1QkFBdUI7R0FDbkMsTUFBTSxFQUFFLDRDQUE0QztHQUNwRCxLQUFLLEVBQUUsNkRBQTZEO0dBQ3BFLElBQUksRUFBRSwyQkFBMkI7R0FDakMsT0FBTyxFQUFFLGVBQWU7R0FDeEIsT0FBTyxFQUFFLGtDQUFrQztHQUMzQyxLQUFLLEVBQUUsb0NBQW9DO0dBQzNDLEtBQUssRUFBRSxlQUFlO0dBQ3RCLFFBQVEsRUFBRSxrQkFBa0I7R0FDNUIsSUFBSSxFQUFFLG1CQUFtQjtHQUN6QixDQUFDOzs7RUFHRixJQUFJLENBQUMsS0FBSyxFQUFFO0dBQ1gsTUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUc7SUFDeEIsRUFBRSxFQUFFLENBQUM7SUFDTCxLQUFLLEVBQUUsSUFBSTtJQUNYLFVBQVUsRUFBRSxJQUFJO0lBQ2hCLFNBQVMsRUFBRSxJQUFJO0lBQ2YsY0FBYyxFQUFFLElBQUk7SUFDcEIsS0FBSyxFQUFFLENBQUM7SUFDUixJQUFJLEVBQUUsRUFBRTtJQUNSLEtBQUssRUFBRSxDQUFDOztJQUVSLFVBQVUsRUFBRSxDQUFDO0lBQ2IsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUM7S0FDekIsUUFBUSxFQUFFLENBQUM7S0FDWCxJQUFJLEVBQUUsSUFBSSxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUMzQixLQUFLLEVBQUUsQ0FBQztLQUNSLE1BQU0sRUFBRSxDQUFDO0tBQ1QsR0FBRyxFQUFFLFFBQVE7S0FDYixHQUFHLEVBQUUsUUFBUTtLQUNiLENBQUM7O0lBRUYsV0FBVyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDeEIsS0FBSyxFQUFFLFNBQVM7S0FDaEIsSUFBSSxFQUFFLE9BQU87S0FDYixJQUFJLEVBQUUsSUFBSSxVQUFVLEVBQUU7S0FDdEIsQ0FBQztJQUNGLGNBQWMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO0tBQzNCLEtBQUssRUFBRSxTQUFTO0tBQ2hCLElBQUksRUFBRSxPQUFPO0tBQ2IsSUFBSSxFQUFFLElBQUksVUFBVSxFQUFFO0tBQ3RCLENBQUM7SUFDRixtQkFBbUIsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO0tBQ2hDLEtBQUssRUFBRSxTQUFTO0tBQ2hCLElBQUksRUFBRSxPQUFPO0tBQ2IsSUFBSSxFQUFFLElBQUksVUFBVSxFQUFFO0tBQ3RCLENBQUM7SUFDRjs7R0FFRCxDQUFDLEdBQUcsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztHQUNsQztFQUNELElBQUksQ0FBQyxDQUFDLFNBQVMsSUFBSSxJQUFJLElBQUUsS0FBSyxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBQztFQUNsRSxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksSUFBSSxJQUFFLEtBQUssQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUM7RUFDNUQsSUFBSSxDQUFDLENBQUMsVUFBVSxJQUFJLElBQUksSUFBRSxLQUFLLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsVUFBVSxHQUFDO0VBQ3JFLElBQUksQ0FBQyxDQUFDLE9BQU8sSUFBSSxJQUFJLEVBQUU7R0FDdEIsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU87R0FDM0IsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRTtJQUN4QixLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBTSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDckY7R0FDRDtFQUNELElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLElBQUUsS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsTUFBSTtFQUN2QyxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxJQUFFLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQUk7RUFDdkMsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksSUFBRSxLQUFLLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFDO0VBQ3ZFLElBQUksQ0FBQyxDQUFDLFFBQVEsSUFBSSxJQUFJLElBQUUsS0FBSyxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBQzs7RUFFOUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUU7R0FDcEIsS0FBSyxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUM7SUFDMUIsRUFBRSxDQUFDLGtCQUFrQjtJQUNyQixFQUFFLENBQUMsbUJBQW1CO0lBQ3RCLENBQUM7R0FDRjs7RUFFRCxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSSxJQUFFLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLE9BQUs7OztFQUcxQyxJQUFJLENBQUMsQ0FBQyxTQUFTLEtBQUssSUFBSSxJQUFFLENBQUMsQ0FBQyxTQUFTLEdBQUcsSUFBRTtFQUMxQyxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUU7R0FDaEIsR0FBRyxDQUFDLFNBQVMsRUFBRSxLQUFLOzs7R0FHcEIsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRTtJQUNuQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN4QixHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN4QixLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRztLQUM3QixJQUFJLENBQUMsTUFBTTtLQUNYLElBQUksQ0FBQyxNQUFNO0tBQ1g7SUFDRCxTQUFTLEdBQUcsSUFBSSxZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUN2QyxLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxLQUFLLEVBQUUsR0FBQyxFQUFFLEVBQUU7S0FDL0IsU0FBUyxDQUFDLEdBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBQyxDQUFDO0tBQzFCLFNBQVMsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFDLENBQUM7S0FDOUI7SUFDRDtRQUNJO0lBQ0osU0FBUyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUMzQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3REOztHQUVELEdBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQzs7OztHQUluRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUU7SUFDZixHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUU7OztJQUdaLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRTtJQUNaLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQzs7SUFFZCxLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEVBQUUsRUFBRTtLQUNyRCxHQUFHLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxHQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ3RCLEdBQUcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLEdBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQzFCLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUU7TUFDbkQsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO01BQ3ZCLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7TUFDM0IsR0FBRyxDQUFDLEdBQUMsQ0FBQyxHQUFHLE1BQU07TUFDZjtVQUNJO01BQ0osTUFBTSxHQUFHLEdBQUM7TUFDVjtLQUNELEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUM7S0FDZCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDO0tBQ2Q7O0lBRUQsR0FBRyxDQUFDLFNBQVMsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDOztJQUVsRCxLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLEdBQUMsR0FBRyxHQUFDLEVBQUUsR0FBQyxFQUFFLEVBQUU7S0FDakQsSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFFLFNBQVMsQ0FBQyxHQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUMsQ0FBQyxHQUFDO0tBQy9EOztJQUVELEtBQUssQ0FBQyxTQUFTLEdBQUcsU0FBUztJQUMzQjs7O0dBR0QsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUM7R0FDdEMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDOztHQUUxQixHQUFHLENBQUMsWUFBWSxHQUFHLElBQUksWUFBWSxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDOzs7R0FHbEQsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFO0lBQ2hCLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUMxQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7S0FDekMsWUFBWSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNuQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ25DO1NBQ0k7S0FDSixZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ25DLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDbkM7SUFDRDtRQUNJO0lBQ0osWUFBWSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDekIsWUFBWSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDekI7O0dBRUQsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDOzs7R0FHekIsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFOztJQUVoQixJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDMUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO0tBQ3pDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDbkMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUNuQyxLQUFLLENBQUMsS0FBSyxJQUFJLENBQUM7S0FDaEI7U0FDSTtLQUNKLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDbkMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUNuQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0tBQ25DLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDbkM7SUFDRDs7UUFFSTtJQUNKLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0MsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3Qzs7R0FFRCxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztHQUMzQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0dBQ2hEOztFQUVELElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRTtHQUNaLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUs7R0FDckIsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRTtHQUN4QixLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNO0dBQzFCOztFQUVELElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFO0dBQzVDLEdBQUcsQ0FBQyxRQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU07O0dBRXpCLEdBQUcsQ0FBQyxPQUFPLEdBQUcsUUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQU0sQ0FBQyxDQUFDLENBQUM7SUFDbEMsT0FBTyxHQUFHLFFBQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFNLENBQUMsQ0FBQyxDQUFDOztHQUVoQyxHQUFHLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDM0MsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7O0dBRXpDLEtBQUssQ0FBQyxLQUFLLEdBQUc7SUFDYixPQUFPLEdBQUcsTUFBTTtJQUNoQixPQUFPLEdBQUcsTUFBTTtJQUNoQjtHQUNELEtBQUssQ0FBQyxTQUFTLEdBQUc7SUFDakIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sR0FBRyxRQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUM7SUFDbEQsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sR0FBRyxRQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUM7SUFDbEQ7O0dBRUQsS0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztHQUN2QyxLQUFLLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO0dBQy9DOztFQUVELElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRTtHQUNiLEdBQUcsQ0FBQyxVQUFVLEdBQUcsRUFBRSxFQUFFLFFBQVE7O0dBRTdCLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtJQUNyQyxVQUFVLEdBQUcsRUFBRTtJQUNmLFFBQVEsR0FBRyxJQUFJLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNuRTs7UUFFSTtJQUNKLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFDaEIsSUFBSSxHQUFHLENBQUMsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsRUFBRSxHQUFDLEVBQUU7S0FDeEMsVUFBVSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBQyxDQUFDO0tBQ3pCO0lBQ0QsUUFBUSxHQUFHLElBQUksVUFBVSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO0lBQ3ZELEdBQUcsQ0FBQyxLQUFHLEdBQUcsQ0FBQztJQUNYLEdBQUcsQ0FBQyxTQUFTLEdBQUcsR0FBRzs7O0lBR25CLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtLQUMzQixJQUFJLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLEdBQUMsRUFBRTtNQUN4QyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7T0FDbEUsUUFBUSxDQUFDLEtBQUcsRUFBRSxDQUFDLEdBQUcsU0FBUztPQUMzQjtNQUNELFNBQVMsSUFBSSxHQUFHO01BQ2hCO0tBQ0Q7SUFDRDs7R0FFRCxLQUFLLENBQUMsVUFBVSxHQUFHLFVBQVU7R0FDN0IsS0FBSyxDQUFDLFdBQVcsQ0FBQztJQUNqQixRQUFRLEVBQUUsQ0FBQztJQUNYLElBQUksRUFBRSxRQUFRO0lBQ2QsS0FBSyxFQUFFLFFBQVEsQ0FBQyxNQUFNO0lBQ3RCLE1BQU0sRUFBRSxDQUFDO0lBQ1QsR0FBRyxFQUFFLFFBQVE7SUFDYixHQUFHLEVBQUUsUUFBUTtJQUNiLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztHQUNSOztFQUVELElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRTtHQUNaLEdBQUcsQ0FBQyxPQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUs7R0FDdkIsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSzs7R0FFcEIsSUFBSSxDQUFDLE1BQU0sSUFBRSxNQUFNLEdBQUcsZUFBYTs7R0FFbkMsR0FBRyxDQUFDLFNBQVMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQzs7O0dBRzdDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsRUFBRTtJQUM1RCxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDOztJQUU3QixLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxPQUFLLEdBQUcsQ0FBQyxFQUFFLEdBQUMsRUFBRSxFQUFFO0tBQ25DLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUMsR0FBRyxDQUFDLENBQUM7S0FDdkI7SUFDRCxNQUFNO0lBQ04sS0FBSyxHQUFHLENBQUMsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEdBQUcsT0FBSyxFQUFFLEdBQUMsRUFBRSxFQUFFO0tBQy9CLEdBQUcsQ0FBQyxHQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFDLENBQUMsRUFBRSxPQUFPLENBQUM7S0FDaEMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFDLEVBQUUsR0FBQyxHQUFHLENBQUMsQ0FBQztLQUN2QjtJQUNELFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxPQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ2xEOztHQUVELEtBQUssQ0FBQyxXQUFXLENBQUM7SUFDakIsS0FBSyxFQUFFLFNBQVM7SUFDaEIsSUFBSSxFQUFFLE9BQU87SUFDYixJQUFJLEVBQUUsU0FBUztJQUNmLENBQUM7R0FDRjtFQUNELENBQUM7OztDQUdGLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtFQUN4QyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7R0FDekQsR0FBRyxDQUFDLElBQUksR0FBRyxNQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztHQUN6QixJQUFJLENBQUMsSUFBSSxJQUFFLFVBQVE7R0FDbkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7R0FDMUIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUU7R0FDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7R0FDMUI7RUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTTtFQUNuQzs7O0NBR0QsR0FBRyxDQUFDLE1BQU0sR0FBRyxFQUFFO0NBQ2YsS0FBSyxHQUFHLENBQUMsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBQyxFQUFFLEVBQUU7RUFDNUMsSUFBSSxNQUFJLENBQUMsTUFBTSxDQUFDLEdBQUMsQ0FBQyxLQUFLLElBQUksSUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQUksQ0FBQyxNQUFNLENBQUMsR0FBQyxDQUFDLEdBQUM7RUFDeEQ7Q0FDRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU07O0NBRXBCLE9BQU8sSUFBSTtDQUNYOztBQUVELE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLFlBQVk7Q0FDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLFdBQUMsS0FBSSxDQUFDLEFBQUc7RUFDM0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7RUFDMUIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUU7RUFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7RUFDMUIsQ0FBQzs7Q0FFRixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDOztDQUV0QixPQUFPLElBQUk7Q0FDWDs7O0FDdHNCRCxZQUFZOztBQUVaLEdBQUcsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQztBQUNsQyxHQUFHLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7O0FBRXJDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxJQUFJLEVBQUUsT0FBTyxFQUFFO0NBQ3pDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQzs7Q0FFeEMsR0FBRyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7OztDQUd6QyxNQUFNLENBQUMsTUFBTSxFQUFFO0VBQ2QsTUFBTSxFQUFFLE1BQU07RUFDZCxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0VBQ3BDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7RUFDaEMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztFQUN0QyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7RUFDbEIsRUFBRSxFQUFFLE9BQU8sQ0FBQyxFQUFFO0VBQ2QsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTTtFQUN6QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07RUFDdEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxXQUFXO0VBQzVCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztFQUN4QixDQUFDOztDQUVGLE9BQU8sTUFBTTtDQUNiOztBQ3pCRCxZQUFZOztBQUVaLEdBQUssQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDO0FBQ3ZDLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6QyxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFDbkMsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDO0FBQ3hDLEdBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQztBQUN2QyxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7QUFDbEMsR0FBSyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDO0FBQ3JDLEdBQUssQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQztBQUN6QyxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztBQUM5QyxHQUFLLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7QUFDbEMsR0FBSyxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQ2pDLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQzs7O0FBR3ZDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsT0FBTzs7O0FBR3hCLFNBQVMsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7O0FBQUM7Q0FDakMsSUFBSSxDQUFDLENBQUMsSUFBSSxZQUFZLE9BQU8sQ0FBQyxJQUFFLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBQzs7Q0FFakUsSUFBSSxPQUFPLElBQUksS0FBSyxVQUFVLEVBQUU7RUFDL0IsSUFBSSxDQUFDLE9BQU8sSUFBRSxPQUFPLEdBQUcsSUFBRTtFQUMxQixPQUFPLENBQUMsSUFBSSxHQUFHLElBQUk7RUFDbkI7TUFDSTtFQUNKLE9BQU8sR0FBRyxJQUFJO0VBQ2QsSUFBSSxHQUFHLElBQUk7RUFDWDs7Q0FFRCxJQUFJLE9BQU8sSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFFLE9BQU8sQ0FBQyxTQUFTLEdBQUcsU0FBTzs7Q0FFMUQsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJOzs7Q0FHbkIsR0FBRyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLGNBQWMsRUFBRSxPQUFPLEdBQUcsRUFBRSxFQUFFLFVBQVUsR0FBRyxFQUFFOzs7RUFHL0QsTUFBTSxHQUFHLEVBQUU7OztFQUdYLGNBQWMsR0FBRyxDQUFDLElBQUksQ0FBQztFQUN2QixXQUFXLEdBQUcsQ0FBQyxJQUFJLENBQUM7O0NBRXJCLEdBQUssQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFLE9BQU8sR0FBRyxHQUFHOzs7O0NBSXBDLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRTs7O0NBR3ZCLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO0VBQzdCLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO0VBQ25DLEtBQUssRUFBRSxTQUFTO0VBQ2hCLE1BQU0sRUFBRSxDQUFDO0VBQ1QsSUFBSSxFQUFFLE9BQU87RUFDYixNQUFNLEVBQUUsTUFBTTtFQUNkLEtBQUssRUFBRSxPQUFPO0VBQ2QsS0FBSyxFQUFFLE9BQU87RUFDZCxHQUFHLEVBQUUsU0FBUztFQUNkLEdBQUcsRUFBRSxTQUFTO0VBQ2QsQ0FBQzs7Q0FFRixNQUFNLENBQUMsSUFBSSxFQUFFO1FBQ1osSUFBSTtNQUNKLEVBQUU7VUFDRixNQUFNO2VBQ04sV0FBVztrQkFDWCxjQUFjO1dBQ2QsT0FBTztjQUNQLFVBQVU7a0JBQ1YsY0FBYzthQUNkLFNBQVM7V0FDVCxPQUFPO0VBQ1AsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNO0VBQ2pCLENBQUM7O0NBRUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUM7OztDQUdwQixHQUFHLENBQUMsYUFBYSxHQUFHO0VBQ25CLFFBQVEsRUFBRTtHQUNULFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztHQUN0QyxPQUFPLEVBQUUsY0FBYztHQUN2QixXQUFXLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsQ0FBQyxNQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsR0FBRyxTQUFTLEVBQUUsY0FBYyxDQUFDLE1BQU0sSUFBQztHQUN2RixLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7R0FDekIsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0dBQ25DLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztHQUNqQyxjQUFjLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztHQUMzQyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7R0FDN0IsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO0dBQ2xDOztFQUVELFVBQVUsRUFBRTs7R0FFWCxDQUFDLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLEtBQUssSUFBSTtJQUMvQixNQUFNLEVBQUUsSUFBSSxDQUFDLGNBQWM7SUFDM0IsTUFBTSxFQUFFLENBQUM7SUFDVCxNQUFNLEVBQUUsQ0FBQztPQUNUO0dBQ0QsQ0FBQyxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxLQUFLLElBQUk7SUFDL0IsTUFBTSxFQUFFLElBQUksQ0FBQyxjQUFjO0lBQzNCLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7T0FDVDtHQUNELE1BQU0sV0FBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUc7SUFDMUQsTUFBTSxFQUFFLElBQUksQ0FBQyxtQkFBbUI7SUFDaEMsTUFBTSxFQUFFLENBQUM7SUFDVCxNQUFNLEVBQUUsQ0FBQztPQUNUO0dBQ0QsTUFBTSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRztJQUMxRCxNQUFNLEVBQUUsSUFBSSxDQUFDLG1CQUFtQjtJQUNoQyxNQUFNLEVBQUUsQ0FBQztJQUNULE1BQU0sRUFBRSxDQUFDO09BQ1Q7R0FDRCxJQUFJLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUc7SUFDdkMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO0lBQ3ZCLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVCxHQUFHO0lBQ0gsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7T0FDeEQ7R0FDRCxVQUFVLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUc7SUFDbkQsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO0lBQ3ZCLE1BQU0sRUFBRSxDQUFDO0lBQ1QsTUFBTSxFQUFFLENBQUM7SUFDVCxHQUFHO0lBQ0gsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLEdBQUcsR0FBRyxNQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7T0FDOUQ7R0FDRCxPQUFPLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUc7SUFDM0MsTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXO0lBQ3hCLE1BQU0sRUFBRSxNQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsR0FBRyxDQUFDO0lBQ2xDLE1BQU0sRUFBRSxDQUFDO0lBQ1QsR0FBRztJQUNILFFBQVEsRUFBRSxNQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFO09BQ2pHO0dBQ0QsYUFBYSxXQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHO0lBQ3ZELE1BQU0sRUFBRSxJQUFJLENBQUMsV0FBVztJQUN4QixNQUFNLEVBQUUsTUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLEdBQUcsQ0FBQztJQUNsQyxNQUFNLEVBQUUsTUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLEdBQUcsQ0FBQztJQUNsQyxHQUFHO0lBQ0gsUUFBUSxFQUFFLE1BQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUU7T0FDbkg7R0FDRCxRQUFRLFdBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQUcsSUFBSSxDQUFDLFVBQVUsS0FBSyxJQUFJLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFFO0dBQzdIOztFQUVELEtBQUssRUFBRTtHQUNOLE1BQU0sRUFBRSxJQUFJO0dBQ1osS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOzs7R0FHaEIsSUFBSSxFQUFFO0lBQ0wsTUFBTSxFQUFFLFdBQVc7SUFDbkIsTUFBTSxFQUFFLHFCQUFxQjtJQUM3QixRQUFRLEVBQUUscUJBQXFCO0lBQy9CLFFBQVEsRUFBRSxLQUFLO0lBQ2Y7R0FDRDs7RUFFRCxPQUFPLEVBQUU7R0FDUixNQUFNLEVBQUUsSUFBSTtHQUNaLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztHQUMxQjtFQUNELFFBQVEsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQzs7RUFFL0IsT0FBTyxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQztFQUN4QixLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDOztFQUV0QixRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7RUFDL0IsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0VBQ3pCLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQzs7RUFFM0IsU0FBUyxFQUFFLFFBQVE7RUFDbkI7OztDQUdELEdBQUcsQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLEVBQUUsRUFBRSxhQUFhLENBQUM7Q0FDN0MsYUFBYSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyx1akNBQXVqQyxDQUFDLENBQUM7Q0FDdmxDLGFBQWEsQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsdTJEQUF1MkQsQ0FBQyxDQUFDOztDQUV2NEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDOzs7Q0FHckMsR0FBRyxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsRUFBRSxFQUFFLGFBQWEsQ0FBQztDQUM3QyxhQUFhLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLHV4QkFBdXhCLENBQUMsQ0FBQztDQUN2ekIsYUFBYSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyw0dURBQTR1RCxDQUFDLENBQUM7OztDQUc1d0QsSUFBSSxFQUFFLEVBQUU7RUFDUCxhQUFhLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUM7RUFDM0UsYUFBYSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDO0VBQzNFOztDQUVELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztDQUNyQzs7O0FBR0QsT0FBTyxDQUFDLFFBQVEsR0FBRztDQUNsQixLQUFLLEVBQUUsT0FBTztDQUNkLFdBQVcsRUFBRSxhQUFhO0NBQzFCLFVBQVUsRUFBRSxDQUFDO0NBQ2IsSUFBSSxFQUFFLEVBQUU7Q0FDUixPQUFPLEVBQUUsQ0FBQztDQUNWLE1BQU0sRUFBRSxTQUFTO0NBQ2pCLFFBQVEsRUFBRSxJQUFJO0NBQ2QsS0FBSyxFQUFFLElBQUk7Q0FDWCxTQUFTLEVBQUUsSUFBSTtDQUNmLEtBQUssRUFBRSxDQUFDO0NBQ1IsTUFBTSxFQUFFLENBQUM7Q0FDVCxNQUFNLEVBQUUsSUFBSTtDQUNaLFNBQVMsRUFBRSxFQUFFO0NBQ2IsSUFBSSxFQUFFLEdBQUc7Q0FDVDs7OztBQUlELE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsQUFBTyxFQUFFOzs7O2dEQUFDO0NBQzlDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtTQUNoQixLQUFJLENBQUMsWUFBTSxDQUFDLEtBQUcsSUFBSSxDQUFDO0VBQ3BCOztDQUVELElBQUksQ0FBQyxJQUFJLEVBQUU7O0NBRVgsT0FBTyxJQUFJO0NBQ1g7Ozs7QUFJRCxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxVQUFVLEFBQU8sRUFBRTs7OztBQUFDO0NBQzVDLE9BQWMsR0FBRztDQUFYLHdCQUFlOzs7Q0FHckIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7RUFDdkcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7RUFDZDs7O0NBR0QsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7O0NBRXBCLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtFQUNoQixLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0dBQ3JDLE1BQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztHQUN6QjtFQUNEOztNQUVJO0VBQ0osTUFBTSxDQUFDLE9BQU8sVUFBQyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQUFBRztHQUM1QixNQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztHQUNoQixDQUFDO0VBQ0Y7O0NBRUQsT0FBTyxJQUFJO0NBQ1g7OztBQUdELE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxHQUFHLFVBQVUsRUFBRSxFQUFFLEdBQUcsRUFBRTs7QUFBQztDQUNoRCxPQUFjLEdBQUc7Q0FBWCx3QkFBZTtDQUNyQixHQUFHLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUM7Ozs7Ozs7OztDQVN0QixJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRTtFQUM1QixFQUFFLEdBQUcsR0FBRztFQUNSLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO0VBQ25CLEdBQUcsR0FBRyxJQUFJO0VBQ1Y7O0NBRUQsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFFLFFBQU07OztDQUdwRCxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUU7O0VBRXhCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7RUFDekQ7OztDQUdELEdBQUcsQ0FBQyxLQUFLLEdBQUcsRUFBRTs7Q0FFZCxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtFQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUUsVUFBUTs7RUFFeEcsS0FBSyxDQUFDLFVBQUksQ0FBQyxPQUFHLE1BQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0VBQ3ZEOztDQUVELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRTtFQUNqQixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztFQUN0QjtDQUNEOzs7QUFHRCxPQUFPLENBQUMsU0FBUyxDQUFDLG9CQUFvQixHQUFHLFNBQVMsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7O0FBQUM7Q0FDN0UsQUFBTTtDQUFPO0NBQU07Q0FBVTtDQUFZO0NBQWlCLHdCQUFlO0NBQ3pFLE9BQVksR0FBRztDQUFULG9CQUFhOzs7Q0FHbkIsSUFBSSxDQUFDLElBQUksRUFBRTs7RUFFVixJQUFJLFFBQVEsRUFBRTtHQUNiLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRTtJQUN6QixhQUFhLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7SUFDNUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUM7SUFDaEMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxNQUFNO2NBQ3RCLFFBQVE7SUFDUixNQUFNLEVBQUUsQ0FBQztJQUNULENBQUMsQ0FBQztHQUNIOztFQUVELE9BQU8sRUFBRSxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRTtHQUMxQixhQUFhLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7R0FDNUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUM7R0FDaEMsTUFBTSxFQUFFLENBQUM7R0FDVCxDQUFDLEVBQUU7RUFDSjs7O0NBR0QsR0FBRyxDQUFDLEtBQUssR0FBRyxFQUFFOztDQUVkLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRTtFQUM1QyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSztFQUN0QyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTTtFQUN2QyxDQUFDLENBQUM7OztDQUdILElBQUksUUFBUSxFQUFFO0VBQ2IsR0FBRyxDQUFDLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUM7RUFDM0MsR0FBRyxDQUFDLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJO0VBQ2hDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDO0VBQ2hDLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7R0FDekMsR0FBRyxDQUFDLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0dBQ3BCLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7R0FDOUI7RUFDRCxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztFQUM3Qjs7Q0FFRCxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRztFQUM5QixTQUFjLEdBQUcsR0FBRyxDQUFDLENBQUM7RUFBakI7RUFBTSxrQkFBWTs7RUFFdkIsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRTtHQUM1QixhQUFhLEVBQUUsTUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7R0FDNUMsVUFBVSxFQUFFLFFBQVEsR0FBRyxlQUFlLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQztHQUM3RCxNQUFNLEVBQUUsSUFBSTtHQUNaLEtBQUssRUFBRSxFQUFFLEdBQUcsSUFBSTtHQUNoQixDQUFDLENBQUM7RUFDSDs7Q0FFRCxPQUFPLEtBQUs7Q0FDWjs7O0FBR0QsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsVUFBVSxBQUFPLEVBQUU7Ozs7QUFBQztDQUM5QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBRSxRQUFNOzs7Q0FHeEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFFLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFDOztDQUUvRCxPQUFxRCxHQUFHO0NBQWxEO0NBQVE7Q0FBSTtDQUFNO0NBQVM7Q0FBVywwQkFBZ0I7O0NBRTVELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLFVBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEFBQUc7RUFDL0MsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDOztFQUVyQixJQUFJLE9BQU8sS0FBSyxTQUFTLElBQUUsT0FBTyxPQUFLOztFQUV2QyxJQUFJLE9BQU8sS0FBSyxJQUFJLElBQUUsT0FBTyxHQUFHLEVBQUUsU0FBUyxFQUFFLElBQUksSUFBRTtPQUM5QyxJQUFJLE9BQU8sT0FBTyxLQUFLLFVBQVUsSUFBRSxPQUFPLEdBQUcsRUFBRSxNQUFNLEVBQUUsT0FBTyxJQUFFO09BQ2hFLElBQUksT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxJQUFFLE9BQU8sR0FBRyxFQUFFLFNBQVMsRUFBRSxPQUFPLElBQUU7OztFQUd6RSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRTtHQUN2QixTQUFTLEVBQUUsdUJBQXVCO0dBQ2xDLElBQUksRUFBRSx1QkFBdUI7R0FDN0IsSUFBSSxFQUFFLG1CQUFtQjtHQUN6QixVQUFVLEVBQUUsOElBQThJO0dBQzFKLEtBQUssRUFBRSx3Q0FBd0M7R0FDL0MsV0FBVyxFQUFFLDBEQUEwRDtHQUN2RSxNQUFNLEVBQUUsc0JBQXNCO0dBQzlCLEtBQUssRUFBRSx1QkFBdUI7R0FDOUIsUUFBUSxFQUFFLG1DQUFtQztHQUM3QyxPQUFPLEVBQUUsNEJBQTRCO0dBQ3JDLE1BQU0sRUFBRSxnQ0FBZ0M7R0FDeEMsQ0FBQzs7RUFFRixJQUFJLE9BQU8sQ0FBQyxTQUFTLEtBQUssSUFBSSxJQUFFLE9BQU8sQ0FBQyxTQUFTLEdBQUcsSUFBRTs7RUFFdEQsSUFBSSxDQUFDLEtBQUssRUFBRTtHQUNYLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUc7SUFDbkIsRUFBRSxFQUFFLENBQUM7SUFDTCxLQUFLLEVBQUUsSUFBSTtJQUNYLFNBQVMsRUFBRSxJQUFJO0lBQ2YsVUFBVSxFQUFFLElBQUk7SUFDaEIsY0FBYyxFQUFFLElBQUk7OztJQUdwQixVQUFVLEVBQUUsRUFBRTs7O0lBR2QsZUFBZSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDNUIsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztLQUN2QixLQUFLLEVBQUUsUUFBUTtLQUNmLElBQUksRUFBRSxPQUFPO0tBQ2IsQ0FBQzs7OztJQUlGLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO0tBQ3ZCLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7S0FDdkIsS0FBSyxFQUFFLFNBQVM7S0FDaEIsSUFBSSxFQUFFLE9BQU87S0FDYixDQUFDO0lBQ0YsV0FBVyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDeEIsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztLQUN2QixLQUFLLEVBQUUsU0FBUztLQUNoQixJQUFJLEVBQUUsT0FBTztLQUNiLENBQUM7SUFDRixjQUFjLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQztLQUMzQixJQUFJLEVBQUUsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDO0tBQ3ZCLEtBQUssRUFBRSxTQUFTO0tBQ2hCLElBQUksRUFBRSxPQUFPO0tBQ2IsQ0FBQztJQUNGLG1CQUFtQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDaEMsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztLQUN2QixLQUFLLEVBQUUsU0FBUztLQUNoQixJQUFJLEVBQUUsT0FBTztLQUNiLENBQUM7SUFDRjtHQUNELE9BQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDO0dBQy9DOzs7RUFHRCxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsRUFBRTtHQUNoRCxPQUFPLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNO0dBQzdCLE9BQU8sS0FBSyxDQUFDLE1BQU07R0FDbkI7OztFQUdELElBQUksT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxFQUFFO0dBQ2hELE9BQU8sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVM7R0FDbkMsT0FBTyxLQUFLLENBQUMsU0FBUztHQUN0Qjs7O0VBR0QsR0FBRyxDQUFDLE9BQU8sR0FBRyxDQUFDLEVBQUUsUUFBUSxHQUFHLENBQUM7O0VBRTdCLFVBQVUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7R0FDM0IsSUFBSSxFQUFFLElBQUk7R0FDVixJQUFJLFdBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEFBQUc7SUFDbkIsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQUk7SUFDeEMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDO0lBQ2hDLE9BQU8sQ0FBQztJQUNSO0dBQ0QsVUFBVSxXQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxBQUFHO0lBQ3pCLElBQUksQ0FBQyxJQUFJLElBQUksSUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFVO0lBQzlDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQztJQUNoQyxPQUFPLENBQUM7SUFDUjtHQUNELE9BQU8sRUFBRSxVQUFVOzs7R0FHbkIsS0FBSyxXQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxBQUFHO0lBQ3BCLElBQUksQ0FBQyxJQUFJLElBQUksSUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFLO0lBQ3pDLENBQUMsR0FBRyxNQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN2QixRQUFRLEVBQUU7SUFDVixPQUFPLENBQUM7SUFDUjtHQUNELFdBQVcsV0FBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQUFBRztJQUMxQixJQUFJLENBQUMsSUFBSSxJQUFJLElBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBVztJQUMvQyxDQUFDLEdBQUcsTUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDdkIsUUFBUSxFQUFFO0lBQ1YsT0FBTyxDQUFDO0lBQ1I7O0dBRUQsTUFBTSxXQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQUFBRztJQUNuQyxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLElBQUUsT0FBTyxDQUFDLEtBQUssR0FBRyxNQUFJO0lBQy9DLE9BQU8sTUFBTTtJQUNiOztHQUVELFNBQVMsV0FBRSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEFBQUc7SUFDekMsQUFBTSxzQkFBYztJQUNwQixBQUFNO0lBQWdCO0lBQXFCLDRDQUF5Qjs7O0lBR3BFLElBQUksU0FBUyxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxFQUFFO0tBQy9CLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUU7TUFDdkIsS0FBSyxDQUFDLEtBQUssR0FBRztPQUNiLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7T0FDaEMsTUFBTSxFQUFFLENBQUM7T0FDVCxNQUFNLEVBQUUsQ0FBQztPQUNULEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU07T0FDekI7TUFDRDtVQUNJO01BQ0osS0FBSyxDQUFDLEtBQUssR0FBRztPQUNiLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU07T0FDMUIsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDO09BQ25DLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUM7T0FDckMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSztPQUN4QjtNQUNEO0tBQ0QsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtNQUN2QixLQUFLLENBQUMsS0FBSyxHQUFHO09BQ2IsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztPQUNoQyxNQUFNLEVBQUUsQ0FBQztPQUNULE1BQU0sRUFBRSxDQUFDO09BQ1QsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTTtPQUN6QjtNQUNEO1VBQ0k7TUFDSixLQUFLLENBQUMsS0FBSyxHQUFHO09BQ2IsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTTtPQUMxQixNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUM7T0FDbkMsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQztPQUNyQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLO09BQ3hCO01BQ0Q7S0FDRCxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7O0tBRTVELE9BQU8sU0FBUztLQUNoQjs7SUFFRCxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUM7O0lBRXpDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzFELEdBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLEdBQUcsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJOzs7SUFHbEUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFO0tBQ25DLE9BQU8sS0FBSyxDQUFDLEtBQUs7S0FDbEIsT0FBTyxDQUFDLEtBQUssR0FBRyxNQUFNO0tBQ3RCOzs7SUFHRCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7S0FDckMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDO0tBQ3BCLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO0tBQ3RCOzs7SUFHRCxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxFQUFFO0tBQzVDLEtBQUssQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsRUFBRSxVQUFFLE1BQU0sRUFBRSxDQUFDO0tBQzNDOztTQUVJLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7S0FDN0IsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJO0tBQ2pCOztJQUVELElBQUksS0FBSyxDQUFDLElBQUksRUFBRTtLQUNmLEdBQUcsQ0FBQyxJQUFJLEdBQUc7TUFDVixTQUFTLEVBQUUsUUFBUTtNQUNuQixLQUFLLEVBQUUsUUFBUTtNQUNmLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtNQUNoQixJQUFJLEVBQUUsUUFBUTtNQUNkO0tBQ0QsSUFBSSxLQUFLLENBQUMsUUFBUSxJQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFDO1lBQ25DLEtBQUssQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUM7S0FDekM7OztJQUdELGNBQWMsQ0FBQztLQUNkLElBQUksRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztLQUMxQixLQUFLLEVBQUUsU0FBUztLQUNoQixDQUFDO0lBQ0YsbUJBQW1CLENBQUM7S0FDbkIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO0tBQzFCLEtBQUssRUFBRSxTQUFTO0tBQ2hCLENBQUM7OztJQUdGLGVBQWUsQ0FBQztLQUNmLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQUM7S0FDM0IsSUFBSSxFQUFFLE9BQU87S0FDYixLQUFLLEVBQUUsUUFBUTtLQUNmLENBQUM7O0lBRUYsT0FBTyxTQUFTO0lBQ2hCO0dBQ0QsRUFBRTs7R0FFRixNQUFNLFdBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxBQUFHO0lBQ3BDLEFBQU0sa0NBQW9COzs7SUFHMUIsVUFBVSxDQUFDLE9BQU8sV0FBQyxPQUFNLENBQUMsU0FBRyxNQUFNLElBQUksTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFFLENBQUM7SUFDMUUsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDOzs7SUFHckIsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7S0FDL0MsR0FBRyxDQUFDLEVBQUUsR0FBRyxNQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQztLQUNoQyxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSTtLQUNyQjs7O1NBR0k7S0FDSixHQUFHLENBQUMsV0FBVyxHQUFHLEVBQUU7O0tBRXBCLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtNQUN0RSxHQUFHLENBQUMsSUFBRSxHQUFHLE1BQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDOztNQUVuQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUUsQ0FBQyxJQUFFLFdBQVcsQ0FBQyxJQUFFLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFDOzs7TUFHbkUsV0FBVyxDQUFDLElBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7TUFDdEI7O0tBRUQsS0FBSyxHQUFHLENBQUMsSUFBRSxHQUFHLENBQUMsRUFBRSxJQUFFLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFFLEVBQUUsRUFBRTtNQUMvQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUUsQ0FBQyxJQUFFLFVBQVE7O01BRTlCLEdBQUcsQ0FBQyxJQUFJLEdBQUc7T0FDVixJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUUsQ0FBQztPQUNyQixJQUFJLEVBQUUsT0FBTztPQUNiLEtBQUssRUFBRSxRQUFRO09BQ2Y7TUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUUsQ0FBQyxFQUFFO09BQ3BCLFVBQVUsQ0FBQyxJQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztPQUNsQztXQUNJO09BQ0osVUFBVSxDQUFDLElBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztPQUNwQjs7TUFFRCxVQUFVLENBQUMsSUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFFLENBQUM7TUFDckM7S0FDRDs7SUFFRCxPQUFPLE9BQU87SUFDZDs7R0FFRCxLQUFLLFdBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxBQUFHO0lBQ2pDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU07OztJQUd6QixJQUFJLENBQUMsTUFBTSxJQUFFLFFBQU07SUFDbkIsSUFBSSxDQUFDLEtBQUssSUFBRSxLQUFLLEdBQUcsUUFBTTs7SUFFMUIsS0FBSyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEUsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDOztJQUV4QyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztJQUN6QyxLQUFLLENBQUMsY0FBYyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQzs7SUFFakQsT0FBTyxLQUFLO0lBQ1o7O0dBRUQsUUFBUSxZQUFFLEdBQUUsQ0FBQyxBQUFHO0lBQ2YsR0FBRyxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsRUFBRSxJQUFJO0tBQzFCLEVBQUUsQ0FBQyxrQkFBa0I7S0FDckIsRUFBRSxDQUFDLG1CQUFtQjtLQUN0QixDQUFDOzs7OztJQUtGLE9BQU8sSUFBSTtJQUNYO0dBQ0QsQ0FBQyxDQUFDOzs7RUFHSCxJQUFJLE9BQU8sRUFBRTtHQUNaLEFBQU07R0FBTztHQUFNO0dBQVksa0NBQW9COztHQUVuRCxHQUFHLENBQUMsS0FBSyxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7R0FDbkMsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUU7SUFDckMsS0FBSyxHQUFHLENBQUMsR0FBQyxHQUFHLENBQUMsRUFBRSxHQUFDLEdBQUcsS0FBSyxFQUFFLEdBQUMsRUFBRSxFQUFFOztLQUUvQixLQUFLLENBQUMsR0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBQyxDQUFDLElBQUksSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsT0FBTyxDQUFDO0tBQzNFLEtBQUssQ0FBQyxHQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBQyxDQUFDLElBQUksSUFBSSxHQUFHLFVBQVUsR0FBRyxVQUFVLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsT0FBTyxDQUFDO0tBQ2pHO0lBQ0Q7R0FDRCxVQUFVLENBQUM7SUFDVixJQUFJLEVBQUUsS0FBSztJQUNYLEtBQUssRUFBRSxTQUFTO0lBQ2hCLENBQUM7R0FDRjs7O0VBR0QsSUFBSSxRQUFRLEVBQUU7R0FDYixBQUFLO0dBQU87R0FBTztHQUFhLG9DQUFxQjtHQUNyRCxHQUFHLENBQUMsTUFBTTs7O0dBR1YsSUFBSSxNQUFJLENBQUMsYUFBYSxFQUFFO0lBQ3ZCLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxXQUFXLENBQUMsTUFBTSxFQUFFO0tBQ3ZDLE1BQU0sR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFLLEdBQUcsQ0FBQyxDQUFDO0tBQ2xDLEtBQUssR0FBRyxDQUFDLEdBQUMsR0FBRyxDQUFDLEVBQUUsR0FBQyxHQUFHLE9BQUssRUFBRSxHQUFDLEVBQUUsRUFBRTtNQUMvQixHQUFHLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxHQUFDLENBQUM7TUFDdEIsTUFBTSxDQUFDLEdBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztNQUNoQyxNQUFNLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7TUFDeEMsTUFBTSxDQUFDLEdBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO01BQ3hDLE1BQU0sQ0FBQyxHQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQzs7TUFFeEMsR0FBRyxDQUFDLGFBQWEsR0FBRyxXQUFXLENBQUMsR0FBQyxDQUFDO01BQ2xDLE1BQU0sQ0FBQyxHQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO01BQzFDLE1BQU0sQ0FBQyxHQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztNQUM5QyxNQUFNLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7TUFDOUMsTUFBTSxDQUFDLEdBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO01BQzlDO0tBQ0Q7SUFDRDs7OztRQUlJO0lBQ0osSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUU7O0tBRXZDLE1BQU0sR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUN0QyxLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxPQUFLLEVBQUUsR0FBQyxFQUFFLEVBQUU7O01BRS9CLElBQUksS0FBSyxDQUFDLEdBQUMsQ0FBQyxJQUFJLElBQUksRUFBRTtPQUNyQixNQUFNLENBQUMsR0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFDLENBQUMsR0FBRyxTQUFTO09BQ2xDLE1BQU0sQ0FBQyxHQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQztPQUNsRDtNQUNELElBQUksV0FBVyxDQUFDLEdBQUMsQ0FBQyxJQUFJLElBQUksRUFBRTtPQUMzQixNQUFNLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxXQUFXLENBQUMsR0FBQyxDQUFDLEdBQUcsU0FBUztPQUM1QyxNQUFNLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFDLENBQUMsR0FBRyxTQUFTLENBQUM7T0FDeEQ7TUFDRDtLQUNEO0lBQ0Q7O0dBRUQsV0FBVyxDQUFDO0lBQ1gsSUFBSSxFQUFFLE1BQU0sSUFBSSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDakMsSUFBSSxFQUFFLE9BQU87SUFDYixLQUFLLEVBQUUsU0FBUztJQUNoQixDQUFDO0dBQ0Y7O0VBRUQsT0FBTyxLQUFLO0VBQ1osQ0FBQztDQUNGOzs7O0FBSUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEdBQUcsVUFBVSxHQUFHLEVBQUU7Q0FDNUMsT0FBeUMsR0FBRztDQUF0QztDQUFnQjtDQUFNLGtDQUFvQjs7Q0FFaEQsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLElBQUksSUFBSSxHQUFHLENBQUMsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7Q0FFcEQsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFFLE9BQU8sS0FBRzs7O0NBR3hCLEdBQUcsQ0FBQyxPQUFPO0NBQ1gsSUFBSSxHQUFHLFlBQVksVUFBVSxJQUFJLEdBQUcsWUFBWSxpQkFBaUIsRUFBRTtFQUNsRSxPQUFPLEdBQUcsR0FBRztFQUNiO01BQ0k7RUFDSixPQUFPLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztFQUNwQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7R0FDM0MsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHO0dBQ3pCO0VBQ0Q7O0NBRUQsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDOztDQUVsRCxHQUFHLEdBQUcsY0FBYyxDQUFDLE1BQU07O0NBRTNCLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0NBQ3JCLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztFQUNoQyxRQUFRLEVBQUUsQ0FBQztFQUNYLElBQUksRUFBRSxPQUFPO0VBQ2IsTUFBTSxFQUFFLE1BQU07RUFDZCxHQUFHLEVBQUUsUUFBUTtFQUNiLEdBQUcsRUFBRSxRQUFRO0VBQ2IsQ0FBQyxDQUFDOztDQUVILE9BQU8sR0FBRztDQUNWOzs7QUFHRCxPQUFPLENBQUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxVQUFVLE1BQU0sRUFBRTtDQUNqRCxPQUFzQyxHQUFHO0NBQW5DO0NBQVk7Q0FBUyw4QkFBa0I7O0NBRTdDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO0VBQzNCLE1BQU0sR0FBRyxDQUFDLE1BQU0sQ0FBQztFQUNqQjs7Q0FFRCxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUU7OztDQUdaLElBQUksT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxFQUFFO0VBQ2xDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsRUFBRTs7RUFFaEIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO0dBQzFCLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUN4QyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQztHQUNEO09BQ0k7R0FDSixLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUMsRUFBRSxDQUFDLEVBQUU7SUFDeEMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUMsRUFBRSxHQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckM7R0FDRDs7RUFFRCxNQUFNLEdBQUcsT0FBTztFQUNoQjs7Q0FFRCxLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUMsRUFBRSxFQUFFO0VBQ3ZDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLEdBQUMsQ0FBQzs7RUFFckIsS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDOztFQUU1QixHQUFHLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDOzs7RUFHOUIsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxFQUFFO0dBQzNCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU07R0FDeEIsVUFBVSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztHQUNwQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztHQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7R0FDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0dBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztHQUN6Qjs7RUFFRCxHQUFHLENBQUMsR0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztFQUN2Qjs7O0NBR0QsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLEdBQUcsU0FBUyxHQUFHLENBQUMsSUFBRSxJQUFJLENBQUMsYUFBYSxHQUFHLE1BQUk7OztDQUdoRyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQzs7O0NBRzNCLE9BQU8sR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUc7Q0FDdEM7O0FBRUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEdBQUcsVUFBVSxPQUFPLEVBQUU7Q0FDcEQsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFFLFFBQU07O0NBRTlCLE9BQWlDLEdBQUc7Q0FBOUI7Q0FBVyx3Q0FBdUI7O0NBRXhDLEdBQUcsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLEdBQUcsR0FBRyxTQUFTLENBQUM7OztDQUdoRSxJQUFJLGNBQWMsR0FBRyxDQUFDLEVBQUU7RUFDdkIsT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLEVBQUU7RUFDekIsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxHQUFHLGNBQWMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUU7R0FDckYsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7R0FDeEI7RUFDRDs7O0NBR0QsSUFBSSxjQUFjLENBQUMsTUFBTSxHQUFHLGNBQWMsRUFBRTtFQUMzQyxjQUFjLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUM7RUFDaEQ7OztDQUdELGNBQWMsQ0FBQyxRQUFRLENBQUM7RUFDdkIsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQUUsU0FBUyxDQUFDO0VBQ2hELE1BQU0sRUFBRSxjQUFjO0VBQ3RCLElBQUksRUFBRSxPQUFPO0VBQ2IsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0NBQ1I7OztBQUdELE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLFlBQVk7Q0FDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLFdBQUMsTUFBSyxDQUFDLEFBQUc7RUFDNUIsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUU7RUFDMUIsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUU7RUFDOUIsS0FBSyxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRTtFQUNuQyxLQUFLLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRTtFQUMzQixLQUFLLENBQUMsVUFBVSxDQUFDLE9BQU8sV0FBQyxFQUFDLENBQUMsU0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUMsT0FBTyxLQUFFLENBQUM7RUFDNUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUU7O0VBRS9CLElBQUksS0FBSyxDQUFDLFFBQVEsSUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sSUFBRTtFQUM1QyxDQUFDO0NBQ0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQzs7Q0FFdEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUU7O0NBRTdCLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxXQUFDLElBQUcsQ0FBQyxTQUFHLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEtBQUUsQ0FBQzs7Q0FFdkUsT0FBTyxJQUFJO0NBQ1g7O0FDMzJCRCxZQUFZOzs7QUFHWixHQUFLLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQztBQUN2RCxHQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7QUFDckMsR0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQ3pDLEdBQUssQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztBQUMxQixHQUFLLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDdkMsR0FBSyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQ2xDLEdBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDOzs7QUFHOUMsTUFBTSxDQUFDLE9BQU8sR0FBRyxLQUFLOzs7O0FBSXRCLFNBQVMsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7Q0FDOUIsSUFBSSxDQUFDLENBQUMsSUFBSSxZQUFZLEtBQUssQ0FBQyxJQUFFLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBQzs7O0NBRzdELElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRTs7O0NBR2hCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRTs7Q0FFaEIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJOzs7Q0FHaEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDOztDQUVsQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTTtDQUNqQzs7OztBQUlELEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsQUFBTyxFQUFFOzs7OztnREFBQztDQUM1QyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7U0FDaEIsS0FBSSxDQUFDLFlBQU0sQ0FBQyxLQUFHLElBQUksQ0FBQztFQUNwQjs7Q0FFRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLHFCQUFxQixJQUFFLE9BQU8sSUFBSSxDQUFDLElBQUksSUFBRTs7O0NBR2xFLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtFQUNmLElBQUksSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLEVBQUU7R0FDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLFVBQUMsR0FBRyxBQUFHO0lBQ3hCLE1BQUksQ0FBQyxJQUFJLEVBQUU7SUFDWCxNQUFJLENBQUMsS0FBSyxHQUFHLElBQUk7SUFDakIsTUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJO0lBQ25CLENBQUM7R0FDRjtFQUNEO01BQ0k7RUFDSixJQUFJLENBQUMsSUFBSSxFQUFFO0VBQ1gsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJO0VBQ2pCLEdBQUcsVUFBQyxHQUFHLEFBQUc7R0FDVCxNQUFJLENBQUMsS0FBSyxHQUFHLEtBQUs7R0FDbEIsQ0FBQztFQUNGOztDQUVELE9BQU8sSUFBSTtDQUNYOzs7O0FBSUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsVUFBVSxBQUFPLEVBQUU7Ozs7O2dEQUFDO0NBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFFLFFBQU07O0NBRXhCLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7RUFDckMsTUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQzNCOzs7Q0FHRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQzs7O0NBR3pDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsRUFBRTtDQUNmLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQztDQUNkLEtBQUssR0FBRyxDQUFDLEdBQUMsR0FBRyxDQUFDLEVBQUUsR0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUMsRUFBRSxFQUFFO0VBQzVDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsTUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFDLENBQUM7RUFDMUIsR0FBRyxDQUFDLFdBQVcsR0FBRyxNQUFJLENBQUMsTUFBTSxDQUFDLEdBQUMsQ0FBQyxDQUFDLE1BQU07RUFDdkMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtHQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7R0FDeEM7O0VBRUQsS0FBSyxDQUFDLFVBQVUsR0FBRyxNQUFNO0VBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU07RUFDN0I7O1FBRUQsSUFBSSxDQUFDLFFBQU8sQ0FBQyxZQUFNLENBQUMsS0FBRyxNQUFNLENBQUM7O0NBRTlCLE9BQU8sSUFBSTtDQUNYOzs7O0FBSUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLEVBQUUsT0FBTyxFQUFFOztBQUFDO0NBQ25ELE9BQVksR0FBRztDQUFULG9CQUFhOzs7Q0FHbkIsSUFBSSxPQUFPLEtBQUssSUFBSSxFQUFFO0VBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSTtFQUNyQixPQUFPLElBQUk7RUFDWDs7Q0FFRCxJQUFJLENBQUMsT0FBTyxJQUFFLE9BQU8sTUFBSTs7Q0FFekIsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFO0VBQ3JCLElBQUksRUFBRSxxREFBcUQ7RUFDM0QsSUFBSSxFQUFFLGNBQWM7RUFDcEIsSUFBSSxFQUFFLG1CQUFtQjtFQUN6QixLQUFLLEVBQUUsd0NBQXdDO0VBQy9DLE9BQU8sRUFBRSxtQ0FBbUM7RUFDNUMsVUFBVSxFQUFFLDhJQUE4STtFQUMxSixXQUFXLEVBQUUsc0VBQXNFO0VBQ25GLE1BQU0sRUFBRSxzQkFBc0I7RUFDOUIsS0FBSyxFQUFFLDhCQUE4QjtFQUNyQyxRQUFRLEVBQUUsMEJBQTBCO0VBQ3BDLE1BQU0sRUFBRSwyQkFBMkI7RUFDbkMsT0FBTyxFQUFFLDBDQUEwQztFQUNuRCxTQUFTLEVBQUUsc0JBQXNCO0VBQ2pDLFFBQVEsRUFBRSw0QkFBNEI7RUFDdEMsS0FBSyxFQUFFLHdFQUF3RTtFQUMvRSxLQUFLLEVBQUUsNEVBQTRFO0VBQ25GLENBQUM7OztDQUdGLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRztFQUNoRCxFQUFFLEVBQUUsQ0FBQztFQUNMLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQ25CLEtBQUssRUFBRSxTQUFTO0dBQ2hCLElBQUksRUFBRSxPQUFPO0dBQ2IsSUFBSSxFQUFFLElBQUksVUFBVSxFQUFFO0dBQ3RCLENBQUM7RUFDRixLQUFLLEVBQUUsT0FBTztFQUNkLE1BQU0sRUFBRSxJQUFJO0VBQ1osSUFBSSxFQUFFLEVBQUU7RUFDUixXQUFXLEVBQUUsYUFBYTtFQUMxQixVQUFVLEVBQUUsQ0FBQztFQUNiLFFBQVEsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsQ0FBQztFQUM1RSxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7RUFDckIsT0FBTyxFQUFFLENBQUM7RUFDVixRQUFRLEVBQUUsSUFBSTtFQUNkLEtBQUssRUFBRSxJQUFJO0VBQ1gsS0FBSyxFQUFFLElBQUk7RUFDWCxDQUFDLENBQUM7Ozs7Q0FJSCxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFO0VBQ3BCLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUs7RUFDckI7Q0FDRCxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxFQUFFO0VBQ25CLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUk7RUFDbkI7Q0FDRCxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFO0VBQ3JCLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU07RUFDdkI7Q0FDRCxJQUFJLENBQUMsQ0FBQyxXQUFXLElBQUksSUFBSSxFQUFFO0VBQzFCLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLFdBQVc7RUFDakM7Q0FDRCxJQUFJLENBQUMsQ0FBQyxVQUFVLElBQUksSUFBSSxFQUFFO0VBQ3pCLEtBQUssQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLFVBQVU7RUFDL0I7Q0FDRCxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksSUFBSSxFQUFFO0VBQ3RCLEtBQUssQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLE9BQU87RUFDekI7Q0FDRCxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUU7RUFDZixLQUFLLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0VBQ2pDO0NBQ0QsSUFBSSxDQUFDLENBQUMsUUFBUSxJQUFJLElBQUksSUFBRSxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxVQUFRO0NBQ25ELElBQUksQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLElBQUUsS0FBSyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsT0FBSztDQUMxQyxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSSxJQUFFLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLE9BQUs7OztDQUcxQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUU7RUFDWCxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7RUFDN0IsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU07RUFDN0IsS0FBSyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07OztFQUc5QixLQUFLLENBQUMsTUFBTSxHQUFHLEVBQUU7O0VBRWpCLEtBQUssR0FBRyxDQUFDLEdBQUMsR0FBRyxDQUFDLEVBQUUsR0FBQyxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBQyxFQUFFLEVBQUU7R0FDdkMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7R0FDekM7RUFDRDs7O0NBR0QsR0FBRyxDQUFDLFVBQVU7Q0FDZCxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7RUFDWixLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxLQUFLO0VBQ3JCLFVBQVUsR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRO0VBQzlEOztDQUVELElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRTtFQUNiLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU07RUFDdkI7Q0FDRCxHQUFHLENBQUMsWUFBWSxHQUFHLEtBQUs7Q0FDeEIsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLElBQUksRUFBRTs7RUFFdEIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sS0FBSyxLQUFLLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7R0FDMUgsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7R0FDckMsWUFBWSxHQUFHLElBQUk7R0FDbkI7O09BRUk7R0FDSixLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0dBQ2pDO0VBQ0Q7OztDQUdELEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLE9BQU87Q0FDckIsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSzs7Q0FFbkIsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUs7Q0FDNUIsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU07Q0FDN0IsR0FBRyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Q0FDM0IsR0FBRyxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Q0FDMUIsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQztDQUNkLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUM7O0NBRWQsS0FBSyxDQUFDLE1BQU0sR0FBRyxFQUFFOztDQUVqQixLQUFLLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUMsR0FBRyxDQUFDLEVBQUUsR0FBQyxFQUFFLEVBQUU7RUFDM0IsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0dBQzNCLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxJQUFJLENBQUMsS0FBSyxHQUFDLElBQUUsVUFBUTtHQUN4QyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxHQUFDLEdBQUcsQ0FBQyxJQUFFLFVBQVE7R0FDbkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksR0FBQyxHQUFHLENBQUMsSUFBRSxVQUFROztHQUVuQyxHQUFHLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEdBQUMsRUFBRSxDQUFDLENBQUM7O0dBRWhDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsTUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDOztHQUV0RCxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUU7SUFDWCxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUU7S0FDaEIsSUFBSSxDQUFDLFNBQVMsR0FBRztNQUNoQixDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztNQUN6RCxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztNQUN6RDtLQUNEO1NBQ0k7S0FDSixJQUFJLENBQUMsU0FBUyxHQUFHO01BQ2hCLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7TUFDbEQsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztNQUNsRDtLQUNEOztJQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsR0FBQyxFQUFFLENBQUMsQ0FBQztJQUN4Qzs7R0FFRCxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO0lBQ3JDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsWUFBWSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsT0FBTztJQUNwRSxJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUU7S0FDakIsU0FBd0IsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFDLEVBQUUsQ0FBQztLQUEvQztLQUFLO0tBQUs7S0FBSyxtQkFBaUM7O0tBRXJELElBQUksQ0FBQyxRQUFRLEdBQUc7TUFDZixJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO01BQ3ZCLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7TUFDdEIsSUFBSSxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztNQUN2QixHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO01BQ3RCO0tBQ0Q7O1NBRUk7S0FDSixJQUFJLENBQUMsUUFBUSxHQUFHO01BQ2YsSUFBSSxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7TUFDM0IsR0FBRyxHQUFHLEdBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7TUFDMUIsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztNQUNqQyxHQUFHLEdBQUcsQ0FBQyxHQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO01BQ2hDO0tBQ0Q7SUFDRDs7R0FFRCxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBSztHQUNyQyxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUUsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsTUFBSTtHQUNsQyxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsUUFBTTtHQUN4QyxJQUFJLENBQUMsQ0FBQyxVQUFVLElBQUUsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsWUFBVTtHQUNwRCxJQUFJLENBQUMsQ0FBQyxXQUFXLElBQUUsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsYUFBVztHQUN2RCxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUUsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsU0FBTzs7R0FFM0MsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO0lBQ1osSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU07SUFDaEY7O0dBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0dBQ3RCO0VBQ0Q7O0NBRUQsT0FBTyxJQUFJO0NBQ1g7Ozs7QUFJRCxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxVQUFVLEFBQU8sRUFBRTs7Ozs7Z0RBQUM7Q0FDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7RUFDakIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7RUFDbkI7TUFDSTtFQUNKLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRTtFQUNaLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7O0dBRXJDLElBQUksT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxHQUFHO0lBQ2pDLE9BQTBCLEdBQUcsTUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQTFDO0lBQVEsZ0NBQW1DO0lBQ2pELEdBQUcsQ0FBQyxVQUFJLENBQUMsS0FBRyxRQUFRLENBQUMsVUFBVSxFQUFFLFVBQVUsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0Q7O1FBRUksSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFO0lBQ3hCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqQixTQUEwQixHQUFHLE1BQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUFwQztJQUFRLG9DQUE2QjtJQUMzQyxRQUFNLEdBQUcsUUFBTSxDQUFDLEdBQUcsVUFBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQUFBRztLQUNsQyxHQUFHLENBQUMsWUFBVSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUc7S0FDekIsQ0FBQztJQUNGO0dBQ0Q7V0FDRCxJQUFJLENBQUMsUUFBTyxDQUFDLFVBQUksQ0FBQyxPQUFHLEdBQUcsQ0FBQztFQUN6Qjs7Q0FFRCxPQUFPLElBQUk7Q0FDWDs7OztBQUlELEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLFlBQVk7Q0FDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLFdBQUMsTUFBSyxDQUFDLEFBQUc7RUFDNUIsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFFO0VBQ2hFLENBQUM7Q0FDRixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUk7Q0FDbEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJOztDQUVsQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRTs7Q0FFdEIsT0FBTyxJQUFJO0NBQ1g7Ozs7QUFJRCxTQUFTLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtDQUM3QixHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUM7Q0FDOUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDO0NBQ1QsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDO0NBQ1QsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSTs7Q0FFL0MsT0FBTyxHQUFHO0NBQ1Y7Ozs7QUFJRCxTQUFTLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtDQUM3QixHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUk7Q0FDbEQsR0FBRyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7O0NBRXRDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7RUFDckIsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7RUFDZixJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztFQUNmLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0VBQ2YsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7RUFDZjtNQUNJLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRTtFQUN0QixJQUFJLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7RUFDdEIsSUFBSSxHQUFHLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0VBQ3RCO01BQ0k7RUFDSixJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUM7RUFDZCxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUM7RUFDZCxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSztFQUM1QixJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTTtFQUM3Qjs7Q0FFRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0VBQ3JCLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0VBQ2YsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7RUFDZixJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztFQUNmLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0VBQ2Y7TUFDSSxJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUU7RUFDdEIsSUFBSSxHQUFHLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0VBQ3RCLElBQUksR0FBRyxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztFQUN0QjtNQUNJO0VBQ0osSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDO0VBQ2QsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDO0VBQ2QsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUs7RUFDNUIsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU07RUFDN0I7O0NBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRTtDQUNqQzs7O0FBR0QsU0FBUyxNQUFNLEVBQUUsR0FBRyxFQUFFO0NBQ3JCLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUM7TUFDbkQsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFDO01BQzdEO0VBQ0osR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0VBQ25CLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztFQUM1RDtDQUNEOzs7QUM3WUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaDdTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUN0VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDck9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQy9GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzcUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNyTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3cUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2NEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzcUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25MQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdlNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0b0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3dUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0bEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcG5CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25IQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcm5CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDeG9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdGRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDemxCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDM1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcndCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNW1CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2MkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNXFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeGRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDanFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzltQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcHdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOWVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1YkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2h0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzMwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxNENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbDNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2x2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9zQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdGJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6UkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdlFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25pRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN29CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdDFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdFpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMWpCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JtQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDLzhCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbE9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwMkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4YUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9zcmMvbGliJyk7XG52YXIgcnVsZXMgPSB7XG4gICAgXCJYLFggZGl2XCI6IFwiZGlyZWN0aW9uOmx0cjtmb250LWZhbWlseTonT3BlbiBTYW5zJywgdmVyZGFuYSwgYXJpYWwsIHNhbnMtc2VyaWY7bWFyZ2luOjA7cGFkZGluZzowO1wiLFxuICAgIFwiWCBpbnB1dCxYIGJ1dHRvblwiOiBcImZvbnQtZmFtaWx5OidPcGVuIFNhbnMnLCB2ZXJkYW5hLCBhcmlhbCwgc2Fucy1zZXJpZjtcIixcbiAgICBcIlggaW5wdXQ6Zm9jdXMsWCBidXR0b246Zm9jdXNcIjogXCJvdXRsaW5lOm5vbmU7XCIsXG4gICAgXCJYIGFcIjogXCJ0ZXh0LWRlY29yYXRpb246bm9uZTtcIixcbiAgICBcIlggYTpob3ZlclwiOiBcInRleHQtZGVjb3JhdGlvbjpub25lO1wiLFxuICAgIFwiWCAuY3Jpc3BcIjogXCJzaGFwZS1yZW5kZXJpbmc6Y3Jpc3BFZGdlcztcIixcbiAgICBcIlggLnVzZXItc2VsZWN0LW5vbmVcIjogXCItd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7LW1vei11c2VyLXNlbGVjdDpub25lOy1tcy11c2VyLXNlbGVjdDpub25lOy1vLXVzZXItc2VsZWN0Om5vbmU7dXNlci1zZWxlY3Q6bm9uZTtcIixcbiAgICBcIlggc3ZnXCI6IFwib3ZlcmZsb3c6aGlkZGVuO1wiLFxuICAgIFwiWCBzdmcgYVwiOiBcImZpbGw6IzQ0N2FkYjtcIixcbiAgICBcIlggc3ZnIGE6aG92ZXJcIjogXCJmaWxsOiMzYzZkYzU7XCIsXG4gICAgXCJYIC5tYWluLXN2Z1wiOiBcInBvc2l0aW9uOmFic29sdXRlO3RvcDowO2xlZnQ6MDtwb2ludGVyLWV2ZW50czpub25lO1wiLFxuICAgIFwiWCAubWFpbi1zdmcgLmRyYWdsYXllclwiOiBcInBvaW50ZXItZXZlbnRzOmFsbDtcIixcbiAgICBcIlggLmN1cnNvci1kZWZhdWx0XCI6IFwiY3Vyc29yOmRlZmF1bHQ7XCIsXG4gICAgXCJYIC5jdXJzb3ItcG9pbnRlclwiOiBcImN1cnNvcjpwb2ludGVyO1wiLFxuICAgIFwiWCAuY3Vyc29yLWNyb3NzaGFpclwiOiBcImN1cnNvcjpjcm9zc2hhaXI7XCIsXG4gICAgXCJYIC5jdXJzb3ItbW92ZVwiOiBcImN1cnNvcjptb3ZlO1wiLFxuICAgIFwiWCAuY3Vyc29yLWNvbC1yZXNpemVcIjogXCJjdXJzb3I6Y29sLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1yb3ctcmVzaXplXCI6IFwiY3Vyc29yOnJvdy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3ItbnMtcmVzaXplXCI6IFwiY3Vyc29yOm5zLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1ldy1yZXNpemVcIjogXCJjdXJzb3I6ZXctcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLXN3LXJlc2l6ZVwiOiBcImN1cnNvcjpzdy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3Itcy1yZXNpemVcIjogXCJjdXJzb3I6cy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3Itc2UtcmVzaXplXCI6IFwiY3Vyc29yOnNlLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci13LXJlc2l6ZVwiOiBcImN1cnNvcjp3LXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1lLXJlc2l6ZVwiOiBcImN1cnNvcjplLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1udy1yZXNpemVcIjogXCJjdXJzb3I6bnctcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLW4tcmVzaXplXCI6IFwiY3Vyc29yOm4tcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLW5lLXJlc2l6ZVwiOiBcImN1cnNvcjpuZS1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3ItZ3JhYlwiOiBcImN1cnNvcjotd2Via2l0LWdyYWI7Y3Vyc29yOmdyYWI7XCIsXG4gICAgXCJYIC5tb2RlYmFyXCI6IFwicG9zaXRpb246YWJzb2x1dGU7dG9wOjJweDtyaWdodDoycHg7ei1pbmRleDoxMDAxO1wiLFxuICAgIFwiWCAubW9kZWJhci0taG92ZXJcIjogXCJvcGFjaXR5OjA7LXdlYmtpdC10cmFuc2l0aW9uOm9wYWNpdHkgMC4zcyBlYXNlIDBzOy1tb3otdHJhbnNpdGlvbjpvcGFjaXR5IDAuM3MgZWFzZSAwczstbXMtdHJhbnNpdGlvbjpvcGFjaXR5IDAuM3MgZWFzZSAwczstby10cmFuc2l0aW9uOm9wYWNpdHkgMC4zcyBlYXNlIDBzO3RyYW5zaXRpb246b3BhY2l0eSAwLjNzIGVhc2UgMHM7XCIsXG4gICAgXCJYOmhvdmVyIC5tb2RlYmFyLS1ob3ZlclwiOiBcIm9wYWNpdHk6MTtcIixcbiAgICBcIlggLm1vZGViYXItZ3JvdXBcIjogXCJmbG9hdDpsZWZ0O2Rpc3BsYXk6aW5saW5lLWJsb2NrO2JveC1zaXppbmc6Ym9yZGVyLWJveDttYXJnaW4tbGVmdDo4cHg7cG9zaXRpb246cmVsYXRpdmU7dmVydGljYWwtYWxpZ246bWlkZGxlO3doaXRlLXNwYWNlOm5vd3JhcDtcIixcbiAgICBcIlggLm1vZGViYXItYnRuXCI6IFwicG9zaXRpb246cmVsYXRpdmU7Zm9udC1zaXplOjE2cHg7cGFkZGluZzozcHggNHB4O2hlaWdodDoyMnB4O2N1cnNvcjpwb2ludGVyO2xpbmUtaGVpZ2h0Om5vcm1hbDtib3gtc2l6aW5nOmJvcmRlci1ib3g7XCIsXG4gICAgXCJYIC5tb2RlYmFyLWJ0biBzdmdcIjogXCJwb3NpdGlvbjpyZWxhdGl2ZTt0b3A6MnB4O1wiLFxuICAgIFwiWCAubW9kZWJhci52ZXJ0aWNhbFwiOiBcImRpc3BsYXk6ZmxleDtmbGV4LWRpcmVjdGlvbjpjb2x1bW47ZmxleC13cmFwOndyYXA7YWxpZ24tY29udGVudDpmbGV4LWVuZDttYXgtaGVpZ2h0OjEwMCU7XCIsXG4gICAgXCJYIC5tb2RlYmFyLnZlcnRpY2FsIHN2Z1wiOiBcInRvcDotMXB4O1wiLFxuICAgIFwiWCAubW9kZWJhci52ZXJ0aWNhbCAubW9kZWJhci1ncm91cFwiOiBcImRpc3BsYXk6YmxvY2s7ZmxvYXQ6bm9uZTttYXJnaW4tbGVmdDowcHg7bWFyZ2luLWJvdHRvbTo4cHg7XCIsXG4gICAgXCJYIC5tb2RlYmFyLnZlcnRpY2FsIC5tb2RlYmFyLWdyb3VwIC5tb2RlYmFyLWJ0blwiOiBcImRpc3BsYXk6YmxvY2s7dGV4dC1hbGlnbjpjZW50ZXI7XCIsXG4gICAgXCJYIFtkYXRhLXRpdGxlXTpiZWZvcmUsWCBbZGF0YS10aXRsZV06YWZ0ZXJcIjogXCJwb3NpdGlvbjphYnNvbHV0ZTstd2Via2l0LXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLCAwLCAwKTstbW96LXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLCAwLCAwKTstbXMtdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKDAsIDAsIDApOy1vLXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLCAwLCAwKTt0cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwgMCwgMCk7ZGlzcGxheTpub25lO29wYWNpdHk6MDt6LWluZGV4OjEwMDE7cG9pbnRlci1ldmVudHM6bm9uZTt0b3A6MTEwJTtyaWdodDo1MCU7XCIsXG4gICAgXCJYIFtkYXRhLXRpdGxlXTpob3ZlcjpiZWZvcmUsWCBbZGF0YS10aXRsZV06aG92ZXI6YWZ0ZXJcIjogXCJkaXNwbGF5OmJsb2NrO29wYWNpdHk6MTtcIixcbiAgICBcIlggW2RhdGEtdGl0bGVdOmJlZm9yZVwiOiBcImNvbnRlbnQ6Jyc7cG9zaXRpb246YWJzb2x1dGU7YmFja2dyb3VuZDp0cmFuc3BhcmVudDtib3JkZXI6NnB4IHNvbGlkIHRyYW5zcGFyZW50O3otaW5kZXg6MTAwMjttYXJnaW4tdG9wOi0xMnB4O2JvcmRlci1ib3R0b20tY29sb3I6IzY5NzM4YTttYXJnaW4tcmlnaHQ6LTZweDtcIixcbiAgICBcIlggW2RhdGEtdGl0bGVdOmFmdGVyXCI6IFwiY29udGVudDphdHRyKGRhdGEtdGl0bGUpO2JhY2tncm91bmQ6IzY5NzM4YTtjb2xvcjp3aGl0ZTtwYWRkaW5nOjhweCAxMHB4O2ZvbnQtc2l6ZToxMnB4O2xpbmUtaGVpZ2h0OjEycHg7d2hpdGUtc3BhY2U6bm93cmFwO21hcmdpbi1yaWdodDotMThweDtib3JkZXItcmFkaXVzOjJweDtcIixcbiAgICBcIlggLnZlcnRpY2FsIFtkYXRhLXRpdGxlXTpiZWZvcmUsWCAudmVydGljYWwgW2RhdGEtdGl0bGVdOmFmdGVyXCI6IFwidG9wOjAlO3JpZ2h0OjIwMCU7XCIsXG4gICAgXCJYIC52ZXJ0aWNhbCBbZGF0YS10aXRsZV06YmVmb3JlXCI6IFwiYm9yZGVyOjZweCBzb2xpZCB0cmFuc3BhcmVudDtib3JkZXItbGVmdC1jb2xvcjojNjk3MzhhO21hcmdpbi10b3A6OHB4O21hcmdpbi1yaWdodDotMzBweDtcIixcbiAgICBcIlggLnNlbGVjdC1vdXRsaW5lXCI6IFwiZmlsbDpub25lO3N0cm9rZS13aWR0aDoxO3NoYXBlLXJlbmRlcmluZzpjcmlzcEVkZ2VzO1wiLFxuICAgIFwiWCAuc2VsZWN0LW91dGxpbmUtMVwiOiBcInN0cm9rZTp3aGl0ZTtcIixcbiAgICBcIlggLnNlbGVjdC1vdXRsaW5lLTJcIjogXCJzdHJva2U6YmxhY2s7c3Ryb2tlLWRhc2hhcnJheToycHggMnB4O1wiLFxuICAgIFk6IFwiZm9udC1mYW1pbHk6J09wZW4gU2Fucyc7cG9zaXRpb246Zml4ZWQ7dG9wOjUwcHg7cmlnaHQ6MjBweDt6LWluZGV4OjEwMDAwO2ZvbnQtc2l6ZToxMHB0O21heC13aWR0aDoxODBweDtcIixcbiAgICBcIlkgcFwiOiBcIm1hcmdpbjowO1wiLFxuICAgIFwiWSAubm90aWZpZXItbm90ZVwiOiBcIm1pbi13aWR0aDoxODBweDttYXgtd2lkdGg6MjUwcHg7Ym9yZGVyOjFweCBzb2xpZCAjZmZmO3otaW5kZXg6MzAwMDttYXJnaW46MDtiYWNrZ3JvdW5kLWNvbG9yOiM4Yzk3YWY7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDE0MCwxNTEsMTc1LDAuOSk7Y29sb3I6I2ZmZjtwYWRkaW5nOjEwcHg7b3ZlcmZsb3ctd3JhcDpicmVhay13b3JkO3dvcmQtd3JhcDpicmVhay13b3JkOy1tcy1oeXBoZW5zOmF1dG87LXdlYmtpdC1oeXBoZW5zOmF1dG87aHlwaGVuczphdXRvO1wiLFxuICAgIFwiWSAubm90aWZpZXItY2xvc2VcIjogXCJjb2xvcjojZmZmO29wYWNpdHk6MC44O2Zsb2F0OnJpZ2h0O3BhZGRpbmc6MCA1cHg7YmFja2dyb3VuZDpub25lO2JvcmRlcjpub25lO2ZvbnQtc2l6ZToyMHB4O2ZvbnQtd2VpZ2h0OmJvbGQ7bGluZS1oZWlnaHQ6MjBweDtcIixcbiAgICBcIlkgLm5vdGlmaWVyLWNsb3NlOmhvdmVyXCI6IFwiY29sb3I6IzQ0NDt0ZXh0LWRlY29yYXRpb246bm9uZTtjdXJzb3I6cG9pbnRlcjtcIlxufTtcblxuZm9yKHZhciBzZWxlY3RvciBpbiBydWxlcykge1xuICAgIHZhciBmdWxsU2VsZWN0b3IgPSBzZWxlY3Rvci5yZXBsYWNlKC9eLC8sJyAsJylcbiAgICAgICAgLnJlcGxhY2UoL1gvZywgJy5qcy1wbG90bHktcGxvdCAucGxvdGx5JylcbiAgICAgICAgLnJlcGxhY2UoL1kvZywgJy5wbG90bHktbm90aWZpZXInKTtcbiAgICBMaWIuYWRkU3R5bGVSdWxlKGZ1bGxTZWxlY3RvciwgcnVsZXNbc2VsZWN0b3JdKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgJ3VuZG8nOiB7XG4gICAgICAgICd3aWR0aCc6IDg1Ny4xLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTg1NyAzNTBxMC04Ny0zNC0xNjZ0LTkxLTEzNy0xMzctOTItMTY2LTM0cS05NiAwLTE4MyA0MXQtMTQ3IDExNHEtNCA2LTQgMTN0NSAxMWw3NiA3N3E2IDUgMTQgNSA5LTEgMTMtNyA0MS01MyAxMDAtODJ0MTI2LTI5cTU4IDAgMTEwIDIzdDkyIDYxIDYxIDkxIDIyIDExMS0yMiAxMTEtNjEgOTEtOTIgNjEtMTEwIDIzcS01NSAwLTEwNS0yMHQtOTAtNTdsNzctNzdxMTctMTYgOC0zOC0xMC0yMy0zMy0yM2gtMjUwcS0xNSAwLTI1IDExdC0xMSAyNXYyNTBxMCAyNCAyMiAzMyAyMiAxMCAzOS04bDcyLTcycTYwIDU3IDEzNyA4OHQxNTkgMzFxODcgMCAxNjYtMzR0MTM3LTkyIDkxLTEzNyAzNC0xNjZ6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ2hvbWUnOiB7XG4gICAgICAgICd3aWR0aCc6IDkyOC42LFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTc4NiAyOTZ2LTI2N3EwLTE1LTExLTI2dC0yNS0xMGgtMjE0djIxNGgtMTQzdi0yMTRoLTIxNHEtMTUgMC0yNSAxMHQtMTEgMjZ2MjY3cTAgMSAwIDJ0MCAybDMyMSAyNjQgMzIxLTI2NHExLTEgMS00eiBtMTI0IDM5bC0zNC00MXEtNS01LTEyLTZoLTJxLTcgMC0xMiAzbC0zODYgMzIyLTM4Ni0zMjJxLTctNC0xMy00LTcgMi0xMiA3bC0zNSA0MXEtNCA1LTMgMTN0NiAxMmw0MDEgMzM0cTE4IDE1IDQyIDE1dDQzLTE1bDEzNi0xMTR2MTA5cTAgOCA1IDEzdDEzIDVoMTA3cTggMCAxMy01dDUtMTN2LTIyN2wxMjItMTAycTUtNSA2LTEydC00LTEzeicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdjYW1lcmEtcmV0cm8nOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtNTE4IDM4NnEwIDgtNSAxM3QtMTMgNXEtMzcgMC02My0yN3QtMjYtNjNxMC04IDUtMTN0MTMtNSAxMiA1IDUgMTNxMCAyMyAxNiAzOHQzOCAxNnE4IDAgMTMgNXQ1IDEzeiBtMTI1LTczcTAtNTktNDItMTAxdC0xMDEtNDItMTAxIDQyLTQyIDEwMSA0MiAxMDEgMTAxIDQyIDEwMS00MiA0Mi0xMDF6IG0tNTcyLTMyMGg4NTh2NzFoLTg1OHYtNzF6IG02NDMgMzIwcTAgODktNjIgMTUydC0xNTIgNjItMTUxLTYyLTYzLTE1MiA2My0xNTEgMTUxLTYzIDE1MiA2MyA2MiAxNTF6IG0tNTcxIDM1OGgyMTR2NzJoLTIxNHYtNzJ6IG0tNzItMTA3aDg1OHYxNDNoLTQ2MmwtMzYtNzFoLTM2MHYtNzJ6IG05MjkgMTQzdi03MTRxMC0zMC0yMS01MXQtNTAtMjFoLTg1OHEtMjkgMC01MCAyMXQtMjEgNTF2NzE0cTAgMzAgMjEgNTF0NTAgMjFoODU4cTI5IDAgNTAtMjF0MjEtNTF6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3pvb21ib3gnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMTAwMC0yNWwtMjUwIDI1MWM0MCA2MyA2MyAxMzggNjMgMjE4IDAgMjI0LTE4MiA0MDYtNDA3IDQwNi0yMjQgMC00MDYtMTgyLTQwNi00MDZzMTgzLTQwNiA0MDctNDA2YzgwIDAgMTU1IDIyIDIxOCA2MmwyNTAtMjUwIDEyNSAxMjV6IG0tODEyIDI1MGwwIDQzOCA0MzcgMCAwLTQzOC00MzcgMHogbTYyIDM3NWwzMTMgMCAwLTMxMi0zMTMgMCAwIDMxMnonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAncGFuJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTEwMDAgMzUwbC0xODcgMTg4IDAtMTI1LTI1MCAwIDAgMjUwIDEyNSAwLTE4OCAxODctMTg3LTE4NyAxMjUgMCAwLTI1MC0yNTAgMCAwIDEyNS0xODgtMTg4IDE4Ni0xODcgMCAxMjUgMjUyIDAgMC0yNTAtMTI1IDAgMTg3LTE4OCAxODggMTg4LTEyNSAwIDAgMjUwIDI1MCAwIDAtMTI2IDE4NyAxODh6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3pvb21fcGx1cyc6IHtcbiAgICAgICAgJ3dpZHRoJzogODc1LFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTEgNzg3bDAtODc1IDg3NSAwIDAgODc1LTg3NSAweiBtNjg3LTUwMGwtMTg3IDAgMC0xODctMTI1IDAgMCAxODctMTg4IDAgMCAxMjUgMTg4IDAgMCAxODcgMTI1IDAgMC0xODcgMTg3IDAgMC0xMjV6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3pvb21fbWludXMnOiB7XG4gICAgICAgICd3aWR0aCc6IDg3NSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20wIDc4OGwwLTg3NiA4NzUgMCAwIDg3Ni04NzUgMHogbTY4OC01MDBsLTUwMCAwIDAgMTI1IDUwMCAwIDAtMTI1eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdhdXRvc2NhbGUnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMjUwIDg1MGwtMTg3IDAtNjMgMCAwLTYyIDAtMTg4IDYzIDAgMCAxODggMTg3IDAgMCA2MnogbTY4OCAwbC0xODggMCAwLTYyIDE4OCAwIDAtMTg4IDYyIDAgMCAxODggMCA2Mi02MiAweiBtLTg3NS05MzhsMCAxODgtNjMgMCAwLTE4OCAwLTYyIDYzIDAgMTg3IDAgMCA2Mi0xODcgMHogbTg3NSAxODhsMC0xODgtMTg4IDAgMC02MiAxODggMCA2MiAwIDAgNjIgMCAxODgtNjIgMHogbS0xMjUgMTg4bC0xIDAtOTMtOTQtMTU2IDE1NiAxNTYgMTU2IDkyLTkzIDIgMCAwIDI1MC0yNTAgMCAwLTIgOTMtOTItMTU2LTE1Ni0xNTYgMTU2IDk0IDkyIDAgMi0yNTAgMCAwLTI1MCAwIDAgOTMgOTMgMTU3LTE1Ni0xNTctMTU2LTkzIDk0IDAgMCAwLTI1MCAyNTAgMCAwIDAtOTQgOTMgMTU2IDE1NyAxNTYtMTU3LTkzLTkzIDAgMCAyNTAgMCAwIDI1MHonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAndG9vbHRpcF9iYXNpYyc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTUwMCxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20zNzUgNzI1bDAgMC0zNzUtMzc1IDM3NS0zNzQgMC0xIDExMjUgMCAwIDc1MC0xMTI1IDB6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3Rvb2x0aXBfY29tcGFyZSc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTEyNSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20xODcgNzg2bDAgMi0xODctMTg4IDE4OC0xODcgMCAwIDkzNyAwIDAgMzczLTkzOCAweiBtMC00OTlsMCAxLTE4Ny0xODggMTg4LTE4OCAwIDAgOTM3IDAgMCAzNzYtOTM4LTF6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3Bsb3RseWxvZ28nOiB7XG4gICAgICAgICd3aWR0aCc6IDE1NDIsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMC0xMGgxODJ2LTE0MGgtMTgydjE0MHogbTIyOCAxNDZoMTgzdi0yODZoLTE4M3YyODZ6IG0yMjUgNzE0aDE4MnYtMTAwMGgtMTgydjEwMDB6IG0yMjUtMjg1aDE4MnYtNzE1aC0xODJ2NzE1eiBtMjI1IDE0MmgxODN2LTg1N2gtMTgzdjg1N3ogbTIzMS00MjhoMTgydi00MjloLTE4MnY0Mjl6IG0yMjUtMjkxaDE4M3YtMTM4aC0xODN2MTM4eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICd6LWF4aXMnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtODMzIDVsLTE3IDEwOHY0MWwtMTMwLTY1IDEzMC02NmMwIDAgMCAzOCAwIDM5IDAtMSAzNi0xNCAzOS0yNSA0LTE1LTYtMjItMTYtMzAtMTUtMTItMzktMTYtNTYtMjAtOTAtMjItMTg3LTIzLTI3OS0yMy0yNjEgMC0zNDEgMzQtMzUzIDU5IDMgNjAgMjI4IDExMCAyMjggMTEwLTE0MC04LTM1MS0zNS0zNTEtMTE2IDAtMTIwIDI5My0xNDIgNDc0LTE0MiAxNTUgMCA0NzcgMjIgNDc3IDE0MiAwIDUwLTc0IDc5LTE2MyA5NnogbS0zNzQgOTRjLTU4LTUtOTktMjEtOTktNDAgMC0yNCA2NS00MyAxNDQtNDMgNzkgMCAxNDMgMTkgMTQzIDQzIDAgMTktNDIgMzQtOTggNDB2MjE2aDg3bC0xMzIgMTM1LTEzMy0xMzVoODh2LTIxNnogbTE2NyA1MTVoLTEzNnYxYzE2IDE2IDMxIDM0IDQ2IDUybDg0IDEwOXY1NGgtMjMwdi03MWgxMjR2LTFjLTE2LTE3LTI4LTMyLTQ0LTUxbC04OS0xMTR2LTUxaDI0NXY3MnonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnM2Rfcm90YXRlJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTkyMiA2NjBjLTUgNC05IDctMTQgMTEtMzU5IDI2My01ODAtMzEtNTgwLTMxbC0xMDIgMjggNTgtNDAwYzAgMSAxIDEgMiAyIDExOCAxMDggMzUxIDI0OSAzNTEgMjQ5cy02MiAyNy0xMDAgNDJjODggODMgMjIyIDE4MyAzNDcgMTIyIDE2LTggMzAtMTcgNDQtMjctMiAxLTQgMi02IDR6IG0zNi0zMjljMCAwIDY0IDIyOS04OCAyOTYtNjIgMjctMTI0IDE0LTE3NS0xMSAxNTctNzggMjI1LTIwOCAyNDktMjY2IDgtMTkgMTEtMzEgMTEtMzEgMiA1IDYgMTUgMTEgMzItNS0xMy04LTIwLTgtMjB6IG0tNzc1LTIzOWM3MC0zMSAxMTctNTAgMTk4LTMyLTEyMSA4MC0xOTkgMzQ2LTE5OSAzNDZsLTk2LTE1LTU4LTEyYzAgMCA1NS0yMjYgMTU1LTI4N3ogbTYwMyAxMzNsLTMxNy0xMzljMCAwIDQtNCAxOS0xNCA3LTUgMjQtMTUgMjQtMTVzLTE3Ny0xNDctMzg5IDRjMjM1LTI4NyA1MzYtMTEyIDUzNi0xMTJsMzEtMjIgMTAwIDI5OS00LTF6IG0tMjk4LTE1M2M2LTQgMTQtOSAyNC0xNSAwIDAtMTcgMTAtMjQgMTV6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ2NhbWVyYSc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTAwMCxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ201MDAgNDUwYy04MyAwLTE1MC02Ny0xNTAtMTUwIDAtODMgNjctMTUwIDE1MC0xNTAgODMgMCAxNTAgNjcgMTUwIDE1MCAwIDgzLTY3IDE1MC0xNTAgMTUweiBtNDAwIDE1MGgtMTIwYy0xNiAwLTM0IDEzLTM5IDI5bC0zMSA5M2MtNiAxNS0yMyAyOC00MCAyOGgtMzQwYy0xNiAwLTM0LTEzLTM5LTI4bC0zMS05NGMtNi0xNS0yMy0yOC00MC0yOGgtMTIwYy01NSAwLTEwMC00NS0xMDAtMTAwdi00NTBjMC01NSA0NS0xMDAgMTAwLTEwMGg4MDBjNTUgMCAxMDAgNDUgMTAwIDEwMHY0NTBjMCA1NS00NSAxMDAtMTAwIDEwMHogbS00MDAtNTUwYy0xMzggMC0yNTAgMTEyLTI1MCAyNTAgMCAxMzggMTEyIDI1MCAyNTAgMjUwIDEzOCAwIDI1MC0xMTIgMjUwLTI1MCAwLTEzOC0xMTItMjUwLTI1MC0yNTB6IG0zNjUgMzgwYy0xOSAwLTM1IDE2LTM1IDM1IDAgMTkgMTYgMzUgMzUgMzUgMTkgMCAzNS0xNiAzNS0zNSAwLTE5LTE2LTM1LTM1LTM1eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdtb3ZpZSc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTAwMCxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ205MzggNDEzbC0xODgtMTI1YzAgMzctMTcgNzEtNDQgOTQgNjQgMzggMTA3IDEwNyAxMDcgMTg3IDAgMTIxLTk4IDIxOS0yMTkgMjE5LTEyMSAwLTIxOS05OC0yMTktMjE5IDAtNjEgMjUtMTE3IDY2LTE1NmgtMTE1YzMwIDMzIDQ5IDc2IDQ5IDEyNSAwIDEwMy04NCAxODctMTg3IDE4N3MtMTg4LTg0LTE4OC0xODdjMC01NyAyNi0xMDcgNjUtMTQxLTM4LTIyLTY1LTYyLTY1LTEwOXYtMjUwYzAtNzAgNTYtMTI2IDEyNS0xMjZoNTAwYzY5IDAgMTI1IDU2IDEyNSAxMjZsMTg4LTEyNmMzNCAwIDYyIDI4IDYyIDYzdjM3NWMwIDM1LTI4IDYzLTYyIDYzeiBtLTc1MCAwYy02OSAwLTEyNSA1Ni0xMjUgMTI1czU2IDEyNSAxMjUgMTI1IDEyNS01NiAxMjUtMTI1LTU2LTEyNS0xMjUtMTI1eiBtNDA2LTFjLTg3IDAtMTU3IDcwLTE1NyAxNTcgMCA4NiA3MCAxNTYgMTU3IDE1NnMxNTYtNzAgMTU2LTE1Ni03MC0xNTctMTU2LTE1N3onLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAncXVlc3Rpb24nOiB7XG4gICAgICAgICd3aWR0aCc6IDg1Ny4xLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTUwMCA4MnYxMDdxMCA4LTUgMTN0LTEzIDVoLTEwN3EtOCAwLTEzLTV0LTUtMTN2LTEwN3EwLTggNS0xM3QxMy01aDEwN3E4IDAgMTMgNXQ1IDEzeiBtMTQzIDM3NXEwIDQ5LTMxIDkxdC03NyA2NS05NSAyM3EtMTM2IDAtMjA3LTExOS05LTE0IDQtMjRsNzQtNTVxNC00IDEwLTQgOSAwIDE0IDcgMzAgMzggNDggNTEgMTkgMTQgNDggMTQgMjcgMCA0OC0xNXQyMS0zM3EwLTIxLTExLTM0dC0zOC0yNXEtMzUtMTYtNjUtNDh0LTI5LTcwdi0yMHEwLTggNS0xM3QxMy01aDEwN3E4IDAgMTMgNXQ1IDEzcTAgMTAgMTIgMjd0MzAgMjhxMTggMTAgMjggMTZ0MjUgMTkgMjUgMjcgMTYgMzQgNyA0NXogbTIxNC0xMDdxMC0xMTctNTctMjE1dC0xNTYtMTU2LTIxNS01OC0yMTYgNTgtMTU1IDE1Ni01OCAyMTUgNTggMjE1IDE1NSAxNTYgMjE2IDU4IDIxNS01OCAxNTYtMTU2IDU3LTIxNXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnZGlzayc6IHtcbiAgICAgICAgJ3dpZHRoJzogODU3LjEsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMjE0LTdoNDI5djIxNGgtNDI5di0yMTR6IG01MDAgMGg3MnY1MDBxMCA4LTYgMjF0LTExIDIwbC0xNTcgMTU2cS01IDYtMTkgMTJ0LTIyIDV2LTIzMnEwLTIyLTE1LTM4dC0zOC0xNmgtMzIycS0yMiAwLTM3IDE2dC0xNiAzOHYyMzJoLTcydi03MTRoNzJ2MjMycTAgMjIgMTYgMzh0MzcgMTZoNDY1cTIyIDAgMzgtMTZ0MTUtMzh2LTIzMnogbS0yMTQgNTE4djE3OHEwIDgtNSAxM3QtMTMgNWgtMTA3cS03IDAtMTMtNXQtNS0xM3YtMTc4cTAtOCA1LTEzdDEzLTVoMTA3cTcgMCAxMyA1dDUgMTN6IG0zNTctMTh2LTUxOHEwLTIyLTE1LTM4dC0zOC0xNmgtNzUwcS0yMyAwLTM4IDE2dC0xNiAzOHY3NTBxMCAyMiAxNiAzOHQzOCAxNmg1MTdxMjMgMCA1MC0xMnQ0Mi0yNmwxNTYtMTU3cTE2LTE1IDI3LTQydDExLTQ5eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdsYXNzbyc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTAzMSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20xMDE4IDUzOGMtMzYgMjA3LTI5MCAzMzYtNTY4IDI4Ni0yNzctNDgtNDczLTI1Ni00MzYtNDYzIDEwLTU3IDM2LTEwOCA3Ni0xNTEtMTMtNjYgMTEtMTM3IDY4LTE4MyAzNC0yOCA3NS00MSAxMTQtNDJsLTU1LTcwIDAgMGMtMi0xLTMtMi00LTMtMTAtMTQtOC0zNCA1LTQ1IDE0LTExIDM0LTggNDUgNCAxIDEgMiAzIDIgNWwwIDAgMTEzIDE0MGMxNiAxMSAzMSAyNCA0NSA0MCA0IDMgNiA3IDggMTEgNDgtMyAxMDAgMCAxNTEgOSAyNzggNDggNDczIDI1NSA0MzYgNDYyeiBtLTYyNC0zNzljLTgwIDE0LTE0OSA0OC0xOTcgOTYgNDIgNDIgMTA5IDQ3IDE1NiA5IDMzLTI2IDQ3LTY2IDQxLTEwNXogbS0xODctNzRjLTE5IDE2LTMzIDM3LTM5IDYwIDUwLTMyIDEwOS01NSAxNzQtNjgtNDItMjUtOTUtMjQtMTM1IDh6IG0zNjAgNzVjLTM0LTctNjktOS0xMDItOCA4IDYyLTE2IDEyOC02OCAxNzAtNzMgNTktMTc1IDU0LTI0NC01LTkgMjAtMTYgNDAtMjAgNjEtMjggMTU5IDEyMSAzMTcgMzMzIDM1NHM0MDctNjAgNDM0LTIxN2MyOC0xNTktMTIxLTMxOC0zMzMtMzU1eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdzZWxlY3Rib3gnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMCA4NTBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0yODYgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbTI4NSAwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtMjg2IDBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0tODU3LTI4NmwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbTg1NyAwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtLTg1Ny0yODVsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG04NTcgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbS04NTctMjg2bDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtMjg2IDBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0yODUgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbTI4NiAwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdzcGlrZWxpbmUnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdNNTEyIDQwOWMwLTU3LTQ2LTEwNC0xMDMtMTA0LTU3IDAtMTA0IDQ3LTEwNCAxMDQgMCA1NyA0NyAxMDMgMTA0IDEwMyA1NyAwIDEwMy00NiAxMDMtMTAzeiBtLTMyNy0zOWw5MiAwIDAgOTItOTIgMHogbS0xODUgMGw5MiAwIDAgOTItOTIgMHogbTM3MC0xODZsOTIgMCAwIDkzLTkyIDB6IG0wLTE4NGw5MiAwIDAgOTItOTIgMHonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxLjUgMCAwIC0xLjUgMCA4NTApJ1xuICAgIH0sXG4gICAgJ25ld3Bsb3RseWxvZ28nOiB7XG4gICAgICAgICduYW1lJzogJ25ld3Bsb3RseWxvZ28nLFxuICAgICAgICAnc3ZnJzogJzxzdmcgeG1sbnM9XFwnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcXCcgdmlld0JveD1cXCcwIDAgMTMyIDEzMlxcJz48ZGVmcz48c3R5bGU+LmNscy0xIHtmaWxsOiAjMTE5ZGZmO30gLmNscy0yIHtmaWxsOiAjMjVmZWZkO30gLmNscy0zIHtmaWxsOiAjZmZmO308L3N0eWxlPjwvZGVmcz48dGl0bGU+cGxvdGx5LWxvZ29tYXJrPC90aXRsZT48ZyBpZD1cXCdzeW1ib2xcXCc+PHJlY3QgY2xhc3M9XFwnY2xzLTFcXCcgd2lkdGg9XFwnMTMyXFwnIGhlaWdodD1cXCcxMzJcXCcgcng9XFwnNlxcJyByeT1cXCc2XFwnLz48Y2lyY2xlIGNsYXNzPVxcJ2Nscy0yXFwnIGN4PVxcJzc4XFwnIGN5PVxcJzU0XFwnIHI9XFwnNlxcJy8+PGNpcmNsZSBjbGFzcz1cXCdjbHMtMlxcJyBjeD1cXCcxMDJcXCcgY3k9XFwnMzBcXCcgcj1cXCc2XFwnLz48Y2lyY2xlIGNsYXNzPVxcJ2Nscy0yXFwnIGN4PVxcJzc4XFwnIGN5PVxcJzMwXFwnIHI9XFwnNlxcJy8+PGNpcmNsZSBjbGFzcz1cXCdjbHMtMlxcJyBjeD1cXCc1NFxcJyBjeT1cXCczMFxcJyByPVxcJzZcXCcvPjxjaXJjbGUgY2xhc3M9XFwnY2xzLTJcXCcgY3g9XFwnMzBcXCcgY3k9XFwnMzBcXCcgcj1cXCc2XFwnLz48Y2lyY2xlIGNsYXNzPVxcJ2Nscy0yXFwnIGN4PVxcJzMwXFwnIGN5PVxcJzU0XFwnIHI9XFwnNlxcJy8+PHBhdGggY2xhc3M9XFwnY2xzLTNcXCcgZD1cXCdNMzAsNzJhNiw2LDAsMCwwLTYsNnYyNGE2LDYsMCwwLDAsMTIsMFY3OEE2LDYsMCwwLDAsMzAsNzJaXFwnLz48cGF0aCBjbGFzcz1cXCdjbHMtM1xcJyBkPVxcJ003OCw3MmE2LDYsMCwwLDAtNiw2djI0YTYsNiwwLDAsMCwxMiwwVjc4QTYsNiwwLDAsMCw3OCw3MlpcXCcvPjxwYXRoIGNsYXNzPVxcJ2Nscy0zXFwnIGQ9XFwnTTU0LDQ4YTYsNiwwLDAsMC02LDZ2NDhhNiw2LDAsMCwwLDEyLDBWNTRBNiw2LDAsMCwwLDU0LDQ4WlxcJy8+PHBhdGggY2xhc3M9XFwnY2xzLTNcXCcgZD1cXCdNMTAyLDQ4YTYsNiwwLDAsMC02LDZ2NDhhNiw2LDAsMCwwLDEyLDBWNTRBNiw2LDAsMCwwLDEwMiw0OFpcXCcvPjwvZz48L3N2Zz4nXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhbnNmb3Jtcy9hZ2dyZWdhdGUnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL2JhcicpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvYmFycG9sYXInKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL2JveCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy9jb21wb25lbnRzL2NhbGVuZGFycycpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvY2FuZGxlc3RpY2snKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL2NhcnBldCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvY2hvcm9wbGV0aCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvY29uZScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvY29udG91cicpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvY29udG91cmNhcnBldCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy9jb3JlJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYW5zZm9ybXMvZmlsdGVyJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYW5zZm9ybXMvZ3JvdXBieScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvaGVhdG1hcCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvaGVhdG1hcGdsJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9oaXN0b2dyYW0nKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL2hpc3RvZ3JhbTJkJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9oaXN0b2dyYW0yZGNvbnRvdXInKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFBsb3RseSA9IHJlcXVpcmUoJy4vY29yZScpO1xuXG4vLyB0cmFjZXNcblBsb3RseS5yZWdpc3RlcihbXG4gICAgcmVxdWlyZSgnLi9iYXInKSxcbiAgICByZXF1aXJlKCcuL2JveCcpLFxuICAgIHJlcXVpcmUoJy4vaGVhdG1hcCcpLFxuICAgIHJlcXVpcmUoJy4vaGlzdG9ncmFtJyksXG4gICAgcmVxdWlyZSgnLi9oaXN0b2dyYW0yZCcpLFxuICAgIHJlcXVpcmUoJy4vaGlzdG9ncmFtMmRjb250b3VyJyksXG4gICAgcmVxdWlyZSgnLi9waWUnKSxcbiAgICByZXF1aXJlKCcuL2NvbnRvdXInKSxcbiAgICByZXF1aXJlKCcuL3NjYXR0ZXJ0ZXJuYXJ5JyksXG4gICAgcmVxdWlyZSgnLi92aW9saW4nKSxcblxuICAgIHJlcXVpcmUoJy4vc2NhdHRlcjNkJyksXG4gICAgcmVxdWlyZSgnLi9zdXJmYWNlJyksXG4gICAgcmVxdWlyZSgnLi9tZXNoM2QnKSxcbiAgICByZXF1aXJlKCcuL2NvbmUnKSxcbiAgICByZXF1aXJlKCcuL3N0cmVhbXR1YmUnKSxcblxuICAgIHJlcXVpcmUoJy4vc2NhdHRlcmdlbycpLFxuICAgIHJlcXVpcmUoJy4vY2hvcm9wbGV0aCcpLFxuXG4gICAgcmVxdWlyZSgnLi9zY2F0dGVyZ2wnKSxcbiAgICByZXF1aXJlKCcuL3NwbG9tJyksXG5cbiAgICByZXF1aXJlKCcuL3BvaW50Y2xvdWQnKSxcbiAgICByZXF1aXJlKCcuL2hlYXRtYXBnbCcpLFxuICAgIHJlcXVpcmUoJy4vcGFyY29vcmRzJyksXG4gICAgcmVxdWlyZSgnLi9wYXJjYXRzJyksXG4gICAgcmVxdWlyZSgnLi9zY2F0dGVybWFwYm94JyksXG5cbiAgICByZXF1aXJlKCcuL3NhbmtleScpLFxuXG4gICAgcmVxdWlyZSgnLi90YWJsZScpLFxuXG4gICAgcmVxdWlyZSgnLi9jYXJwZXQnKSxcbiAgICByZXF1aXJlKCcuL3NjYXR0ZXJjYXJwZXQnKSxcbiAgICByZXF1aXJlKCcuL2NvbnRvdXJjYXJwZXQnKSxcblxuICAgIHJlcXVpcmUoJy4vb2hsYycpLFxuICAgIHJlcXVpcmUoJy4vY2FuZGxlc3RpY2snKSxcblxuICAgIHJlcXVpcmUoJy4vc2NhdHRlcnBvbGFyJyksXG4gICAgcmVxdWlyZSgnLi9zY2F0dGVycG9sYXJnbCcpLFxuICAgIHJlcXVpcmUoJy4vYmFycG9sYXInKVxuXSk7XG5cbi8vIHRyYW5zZm9ybXNcbi8vXG4vLyBQbGVhc2Ugbm90ZSB0aGF0IGFsbCAqdHJhbnNmb3JtKiBtZXRob2RzIGFyZSBleGVjdXRlZCBiZWZvcmVcbi8vIGFsbCAqY2FsY1RyYW5zZm9ybSogbWV0aG9kcyAtIHdoaWNoIGNvdWxkIHBvc3NpYmx5IGxlYWQgdG9cbi8vIHVuZXhwZWN0ZWQgcmVzdWx0cyB3aGVuIGFwcGx5aW5nIG11bHRpcGxlIHRyYW5zZm9ybXMgb2YgZGlmZmVyZW50IHR5cGVzXG4vLyB0byBhIGdpdmVuIHRyYWNlLlxuLy9cbi8vIEZvciBtb3JlIGluZm8sIHNlZTpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvOTc4I3B1bGxyZXF1ZXN0cmV2aWV3LTI0MDMzNTNcbi8vXG5QbG90bHkucmVnaXN0ZXIoW1xuICAgIHJlcXVpcmUoJy4vYWdncmVnYXRlJyksXG4gICAgcmVxdWlyZSgnLi9maWx0ZXInKSxcbiAgICByZXF1aXJlKCcuL2dyb3VwYnknKSxcbiAgICByZXF1aXJlKCcuL3NvcnQnKVxuXSk7XG5cbi8vIGNvbXBvbmVudHNcblBsb3RseS5yZWdpc3RlcihbXG4gICAgcmVxdWlyZSgnLi9jYWxlbmRhcnMnKVxuXSk7XG5cbm1vZHVsZS5leHBvcnRzID0gUGxvdGx5O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvbWVzaDNkJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9vaGxjJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9wYXJjYXRzJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9wYXJjb29yZHMnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL3BpZScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvcG9pbnRjbG91ZCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc2Fua2V5Jyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9zY2F0dGVyM2QnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJjYXJwZXQnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJnZW8nKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJnbCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc2NhdHRlcm1hcGJveCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc2NhdHRlcnBvbGFyJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9zY2F0dGVycG9sYXJnbCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnknKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhbnNmb3Jtcy9zb3J0Jyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vc3JjL3RyYWNlcy9zcGxvbScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc3RyZWFtdHViZScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvc3VyZmFjZScpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL3NyYy90cmFjZXMvdGFibGUnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9zcmMvdHJhY2VzL3Zpb2xpbicpO1xuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUNhbWVyYVxyXG5cclxudmFyIG5vdyAgICAgICAgID0gcmVxdWlyZSgncmlnaHQtbm93JylcclxudmFyIGNyZWF0ZVZpZXcgID0gcmVxdWlyZSgnM2QtdmlldycpXHJcbnZhciBtb3VzZUNoYW5nZSA9IHJlcXVpcmUoJ21vdXNlLWNoYW5nZScpXHJcbnZhciBtb3VzZVdoZWVsICA9IHJlcXVpcmUoJ21vdXNlLXdoZWVsJylcclxudmFyIG1vdXNlT2Zmc2V0ID0gcmVxdWlyZSgnbW91c2UtZXZlbnQtb2Zmc2V0JylcclxudmFyIGhhc1Bhc3NpdmUgID0gcmVxdWlyZSgnaGFzLXBhc3NpdmUtZXZlbnRzJylcclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUNhbWVyYShlbGVtZW50LCBvcHRpb25zKSB7XHJcbiAgZWxlbWVudCA9IGVsZW1lbnQgfHwgZG9jdW1lbnQuYm9keVxyXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XHJcblxyXG4gIHZhciBsaW1pdHMgID0gWyAwLjAxLCBJbmZpbml0eSBdXHJcbiAgaWYoJ2Rpc3RhbmNlTGltaXRzJyBpbiBvcHRpb25zKSB7XHJcbiAgICBsaW1pdHNbMF0gPSBvcHRpb25zLmRpc3RhbmNlTGltaXRzWzBdXHJcbiAgICBsaW1pdHNbMV0gPSBvcHRpb25zLmRpc3RhbmNlTGltaXRzWzFdXHJcbiAgfVxyXG4gIGlmKCd6b29tTWluJyBpbiBvcHRpb25zKSB7XHJcbiAgICBsaW1pdHNbMF0gPSBvcHRpb25zLnpvb21NaW5cclxuICB9XHJcbiAgaWYoJ3pvb21NYXgnIGluIG9wdGlvbnMpIHtcclxuICAgIGxpbWl0c1sxXSA9IG9wdGlvbnMuem9vbU1heFxyXG4gIH1cclxuXHJcbiAgdmFyIHZpZXcgPSBjcmVhdGVWaWV3KHtcclxuICAgIGNlbnRlcjogb3B0aW9ucy5jZW50ZXIgfHwgWzAsMCwwXSxcclxuICAgIHVwOiAgICAgb3B0aW9ucy51cCAgICAgfHwgWzAsMSwwXSxcclxuICAgIGV5ZTogICAgb3B0aW9ucy5leWUgICAgfHwgWzAsMCwxMF0sXHJcbiAgICBtb2RlOiAgIG9wdGlvbnMubW9kZSAgIHx8ICdvcmJpdCcsXHJcbiAgICBkaXN0YW5jZUxpbWl0czogbGltaXRzXHJcbiAgfSlcclxuXHJcbiAgdmFyIHBtYXRyaXggPSBbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1cclxuICB2YXIgZGlzdGFuY2UgPSAwLjBcclxuICB2YXIgd2lkdGggICA9IGVsZW1lbnQuY2xpZW50V2lkdGhcclxuICB2YXIgaGVpZ2h0ICA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0XHJcblxyXG4gIHZhciBjYW1lcmEgPSB7XHJcbiAgICB2aWV3OiAgICAgICAgICAgICAgIHZpZXcsXHJcbiAgICBlbGVtZW50OiAgICAgICAgICAgIGVsZW1lbnQsXHJcbiAgICBkZWxheTogICAgICAgICAgICAgIG9wdGlvbnMuZGVsYXkgICAgICAgICAgfHwgMTYsXHJcbiAgICByb3RhdGVTcGVlZDogICAgICAgIG9wdGlvbnMucm90YXRlU3BlZWQgICAgfHwgMSxcclxuICAgIHpvb21TcGVlZDogICAgICAgICAgb3B0aW9ucy56b29tU3BlZWQgICAgICB8fCAxLFxyXG4gICAgdHJhbnNsYXRlU3BlZWQ6ICAgICBvcHRpb25zLnRyYW5zbGF0ZVNwZWVkIHx8IDEsXHJcbiAgICBmbGlwWDogICAgICAgICAgICAgICEhb3B0aW9ucy5mbGlwWCxcclxuICAgIGZsaXBZOiAgICAgICAgICAgICAgISFvcHRpb25zLmZsaXBZLFxyXG4gICAgbW9kZXM6ICAgICAgICAgICAgICB2aWV3Lm1vZGVzLFxyXG4gICAgdGljazogZnVuY3Rpb24oKSB7XHJcbiAgICAgIHZhciB0ID0gbm93KClcclxuICAgICAgdmFyIGRlbGF5ID0gdGhpcy5kZWxheVxyXG4gICAgICB2aWV3LmlkbGUodC1kZWxheSlcclxuICAgICAgdmlldy5mbHVzaCh0LSgxMDArZGVsYXkqMikpXHJcbiAgICAgIHZhciBjdGltZSA9IHQgLSAyICogZGVsYXlcclxuICAgICAgdmlldy5yZWNhbGNNYXRyaXgoY3RpbWUpXHJcbiAgICAgIHZhciBhbGxFcXVhbCA9IHRydWVcclxuICAgICAgdmFyIG1hdHJpeCA9IHZpZXcuY29tcHV0ZWRNYXRyaXhcclxuICAgICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xyXG4gICAgICAgIGFsbEVxdWFsID0gYWxsRXF1YWwgJiYgKHBtYXRyaXhbaV0gPT09IG1hdHJpeFtpXSlcclxuICAgICAgICBwbWF0cml4W2ldID0gbWF0cml4W2ldXHJcbiAgICAgIH1cclxuICAgICAgdmFyIHNpemVDaGFuZ2VkID1cclxuICAgICAgICAgIGVsZW1lbnQuY2xpZW50V2lkdGggPT09IHdpZHRoICYmXHJcbiAgICAgICAgICBlbGVtZW50LmNsaWVudEhlaWdodCA9PT0gaGVpZ2h0XHJcbiAgICAgIHdpZHRoICA9IGVsZW1lbnQuY2xpZW50V2lkdGhcclxuICAgICAgaGVpZ2h0ID0gZWxlbWVudC5jbGllbnRIZWlnaHRcclxuICAgICAgaWYoYWxsRXF1YWwpIHtcclxuICAgICAgICByZXR1cm4gIXNpemVDaGFuZ2VkXHJcbiAgICAgIH1cclxuICAgICAgZGlzdGFuY2UgPSBNYXRoLmV4cCh2aWV3LmNvbXB1dGVkUmFkaXVzWzBdKVxyXG4gICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgfSxcclxuICAgIGxvb2tBdDogZnVuY3Rpb24oY2VudGVyLCBleWUsIHVwKSB7XHJcbiAgICAgIHZpZXcubG9va0F0KHZpZXcubGFzdFQoKSwgY2VudGVyLCBleWUsIHVwKVxyXG4gICAgfSxcclxuICAgIHJvdGF0ZTogZnVuY3Rpb24ocGl0Y2gsIHlhdywgcm9sbCkge1xyXG4gICAgICB2aWV3LnJvdGF0ZSh2aWV3Lmxhc3RUKCksIHBpdGNoLCB5YXcsIHJvbGwpXHJcbiAgICB9LFxyXG4gICAgcGFuOiBmdW5jdGlvbihkeCwgZHksIGR6KSB7XHJcbiAgICAgIHZpZXcucGFuKHZpZXcubGFzdFQoKSwgZHgsIGR5LCBkeilcclxuICAgIH0sXHJcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uKGR4LCBkeSwgZHopIHtcclxuICAgICAgdmlldy50cmFuc2xhdGUodmlldy5sYXN0VCgpLCBkeCwgZHksIGR6KVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoY2FtZXJhLCB7XHJcbiAgICBtYXRyaXg6IHtcclxuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcclxuICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZE1hdHJpeFxyXG4gICAgICB9LFxyXG4gICAgICBzZXQ6IGZ1bmN0aW9uKG1hdCkge1xyXG4gICAgICAgIHZpZXcuc2V0TWF0cml4KHZpZXcubGFzdFQoKSwgbWF0KVxyXG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkTWF0cml4XHJcbiAgICAgIH0sXHJcbiAgICAgIGVudW1lcmFibGU6IHRydWVcclxuICAgIH0sXHJcbiAgICBtb2RlOiB7XHJcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIHZpZXcuZ2V0TW9kZSgpXHJcbiAgICAgIH0sXHJcbiAgICAgIHNldDogZnVuY3Rpb24obW9kZSkge1xyXG4gICAgICAgIHZpZXcuc2V0TW9kZShtb2RlKVxyXG4gICAgICAgIHJldHVybiB2aWV3LmdldE1vZGUoKVxyXG4gICAgICB9LFxyXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXHJcbiAgICB9LFxyXG4gICAgY2VudGVyOiB7XHJcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRDZW50ZXJcclxuICAgICAgfSxcclxuICAgICAgc2V0OiBmdW5jdGlvbihuY2VudGVyKSB7XHJcbiAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBuY2VudGVyKVxyXG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkQ2VudGVyXHJcbiAgICAgIH0sXHJcbiAgICAgIGVudW1lcmFibGU6IHRydWVcclxuICAgIH0sXHJcbiAgICBleWU6IHtcclxuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcclxuICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZEV5ZVxyXG4gICAgICB9LFxyXG4gICAgICBzZXQ6IGZ1bmN0aW9uKG5leWUpIHtcclxuICAgICAgICB2aWV3Lmxvb2tBdCh2aWV3Lmxhc3RUKCksIG51bGwsIG5leWUpXHJcbiAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRFeWVcclxuICAgICAgfSxcclxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxyXG4gICAgfSxcclxuICAgIHVwOiB7XHJcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRVcFxyXG4gICAgICB9LFxyXG4gICAgICBzZXQ6IGZ1bmN0aW9uKG51cCkge1xyXG4gICAgICAgIHZpZXcubG9va0F0KHZpZXcubGFzdFQoKSwgbnVsbCwgbnVsbCwgbnVwKVxyXG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkVXBcclxuICAgICAgfSxcclxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxyXG4gICAgfSxcclxuICAgIGRpc3RhbmNlOiB7XHJcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIGRpc3RhbmNlXHJcbiAgICAgIH0sXHJcbiAgICAgIHNldDogZnVuY3Rpb24oZCkge1xyXG4gICAgICAgIHZpZXcuc2V0RGlzdGFuY2Uodmlldy5sYXN0VCgpLCBkKVxyXG4gICAgICAgIHJldHVybiBkXHJcbiAgICAgIH0sXHJcbiAgICAgIGVudW1lcmFibGU6IHRydWVcclxuICAgIH0sXHJcbiAgICBkaXN0YW5jZUxpbWl0czoge1xyXG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHJldHVybiB2aWV3LmdldERpc3RhbmNlTGltaXRzKGxpbWl0cylcclxuICAgICAgfSxcclxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XHJcbiAgICAgICAgdmlldy5zZXREaXN0YW5jZUxpbWl0cyh2KVxyXG4gICAgICAgIHJldHVybiB2XHJcbiAgICAgIH0sXHJcbiAgICAgIGVudW1lcmFibGU6IHRydWVcclxuICAgIH1cclxuICB9KVxyXG5cclxuICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZnVuY3Rpb24oZXYpIHtcclxuICAgIGV2LnByZXZlbnREZWZhdWx0KClcclxuICAgIHJldHVybiBmYWxzZVxyXG4gIH0pXHJcblxyXG4gIHZhciBsYXN0WCA9IDAsIGxhc3RZID0gMCwgbGFzdE1vZHMgPSB7c2hpZnQ6IGZhbHNlLCBjb250cm9sOiBmYWxzZSwgYWx0OiBmYWxzZSwgbWV0YTogZmFsc2V9XHJcbiAgbW91c2VDaGFuZ2UoZWxlbWVudCwgaGFuZGxlSW50ZXJhY3Rpb24pXHJcblxyXG4gIC8vZW5hYmxlIHNpbXBsZSB0b3VjaCBpbnRlcmFjdGlvbnNcclxuICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBmdW5jdGlvbiAoZXYpIHtcclxuICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KVxyXG4gICAgaGFuZGxlSW50ZXJhY3Rpb24oMCwgeHlbMF0sIHh5WzFdLCBsYXN0TW9kcylcclxuICAgIGhhbmRsZUludGVyYWN0aW9uKDEsIHh5WzBdLCB4eVsxXSwgbGFzdE1vZHMpXHJcblxyXG4gICAgZXYucHJldmVudERlZmF1bHQoKVxyXG4gIH0sIGhhc1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpXHJcblxyXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgZnVuY3Rpb24gKGV2KSB7XHJcbiAgICB2YXIgeHkgPSBtb3VzZU9mZnNldChldi5jaGFuZ2VkVG91Y2hlc1swXSwgZWxlbWVudClcclxuICAgIGhhbmRsZUludGVyYWN0aW9uKDEsIHh5WzBdLCB4eVsxXSwgbGFzdE1vZHMpXHJcblxyXG4gICAgZXYucHJldmVudERlZmF1bHQoKVxyXG4gIH0sIGhhc1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpXHJcblxyXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBmdW5jdGlvbiAoZXYpIHtcclxuICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KVxyXG4gICAgaGFuZGxlSW50ZXJhY3Rpb24oMCwgbGFzdFgsIGxhc3RZLCBsYXN0TW9kcylcclxuXHJcbiAgICBldi5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgfSwgaGFzUGFzc2l2ZSA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSlcclxuXHJcbiAgZnVuY3Rpb24gaGFuZGxlSW50ZXJhY3Rpb24gKGJ1dHRvbnMsIHgsIHksIG1vZHMpIHtcclxuICAgIHZhciBzY2FsZSA9IDEuMCAvIGVsZW1lbnQuY2xpZW50SGVpZ2h0XHJcbiAgICB2YXIgZHggICAgPSBzY2FsZSAqICh4IC0gbGFzdFgpXHJcbiAgICB2YXIgZHkgICAgPSBzY2FsZSAqICh5IC0gbGFzdFkpXHJcblxyXG4gICAgdmFyIGZsaXBYID0gY2FtZXJhLmZsaXBYID8gMSA6IC0xXHJcbiAgICB2YXIgZmxpcFkgPSBjYW1lcmEuZmxpcFkgPyAxIDogLTFcclxuXHJcbiAgICB2YXIgZHJvdCAgPSBNYXRoLlBJICogY2FtZXJhLnJvdGF0ZVNwZWVkXHJcblxyXG4gICAgdmFyIHQgPSBub3coKVxyXG5cclxuICAgIGlmKGJ1dHRvbnMgJiAxKSB7XHJcbiAgICAgIGlmKG1vZHMuc2hpZnQpIHtcclxuICAgICAgICB2aWV3LnJvdGF0ZSh0LCAwLCAwLCAtZHggKiBkcm90KVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHZpZXcucm90YXRlKHQsIGZsaXBYICogZHJvdCAqIGR4LCAtZmxpcFkgKiBkcm90ICogZHksIDApXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZihidXR0b25zICYgMikge1xyXG4gICAgICB2aWV3LnBhbih0LCAtY2FtZXJhLnRyYW5zbGF0ZVNwZWVkICogZHggKiBkaXN0YW5jZSwgY2FtZXJhLnRyYW5zbGF0ZVNwZWVkICogZHkgKiBkaXN0YW5jZSwgMClcclxuICAgIH0gZWxzZSBpZihidXR0b25zICYgNCkge1xyXG4gICAgICB2YXIga3pvb20gPSBjYW1lcmEuem9vbVNwZWVkICogZHkgLyB3aW5kb3cuaW5uZXJIZWlnaHQgKiAodCAtIHZpZXcubGFzdFQoKSkgKiA1MC4wXHJcbiAgICAgIHZpZXcucGFuKHQsIDAsIDAsIGRpc3RhbmNlICogKE1hdGguZXhwKGt6b29tKSAtIDEpKVxyXG4gICAgfVxyXG5cclxuICAgIGxhc3RYID0geFxyXG4gICAgbGFzdFkgPSB5XHJcbiAgICBsYXN0TW9kcyA9IG1vZHNcclxuICB9XHJcblxyXG4gIG1vdXNlV2hlZWwoZWxlbWVudCwgZnVuY3Rpb24oZHgsIGR5LCBkeikge1xyXG4gICAgdmFyIGZsaXBYID0gY2FtZXJhLmZsaXBYID8gMSA6IC0xXHJcbiAgICB2YXIgZmxpcFkgPSBjYW1lcmEuZmxpcFkgPyAxIDogLTFcclxuICAgIHZhciB0ID0gbm93KClcclxuICAgIGlmKE1hdGguYWJzKGR4KSA+IE1hdGguYWJzKGR5KSkge1xyXG4gICAgICB2aWV3LnJvdGF0ZSh0LCAwLCAwLCAtZHggKiBmbGlwWCAqIE1hdGguUEkgKiBjYW1lcmEucm90YXRlU3BlZWQgLyB3aW5kb3cuaW5uZXJXaWR0aClcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHZhciBrem9vbSA9IGNhbWVyYS56b29tU3BlZWQgKiBmbGlwWSAqIGR5IC8gd2luZG93LmlubmVySGVpZ2h0ICogKHQgLSB2aWV3Lmxhc3RUKCkpIC8gMTAwLjBcclxuICAgICAgdmlldy5wYW4odCwgMCwgMCwgZGlzdGFuY2UgKiAoTWF0aC5leHAoa3pvb20pIC0gMSkpXHJcbiAgICB9XHJcbiAgfSwgdHJ1ZSlcclxuXHJcbiAgcmV0dXJuIGNhbWVyYVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVZpZXdDb250cm9sbGVyXG5cbnZhciBjcmVhdGVUdXJudGFibGUgPSByZXF1aXJlKCd0dXJudGFibGUtY2FtZXJhLWNvbnRyb2xsZXInKVxudmFyIGNyZWF0ZU9yYml0ICAgICA9IHJlcXVpcmUoJ29yYml0LWNhbWVyYS1jb250cm9sbGVyJylcbnZhciBjcmVhdGVNYXRyaXggICAgPSByZXF1aXJlKCdtYXRyaXgtY2FtZXJhLWNvbnRyb2xsZXInKVxuXG5mdW5jdGlvbiBWaWV3Q29udHJvbGxlcihjb250cm9sbGVycywgbW9kZSkge1xuICB0aGlzLl9jb250cm9sbGVyTmFtZXMgPSBPYmplY3Qua2V5cyhjb250cm9sbGVycylcbiAgdGhpcy5fY29udHJvbGxlckxpc3QgPSB0aGlzLl9jb250cm9sbGVyTmFtZXMubWFwKGZ1bmN0aW9uKG4pIHtcbiAgICByZXR1cm4gY29udHJvbGxlcnNbbl1cbiAgfSlcbiAgdGhpcy5fbW9kZSAgID0gbW9kZVxuICB0aGlzLl9hY3RpdmUgPSBjb250cm9sbGVyc1ttb2RlXVxuICBpZighdGhpcy5fYWN0aXZlKSB7XG4gICAgdGhpcy5fbW9kZSAgID0gJ3R1cm50YWJsZSdcbiAgICB0aGlzLl9hY3RpdmUgPSBjb250cm9sbGVycy50dXJudGFibGVcbiAgfVxuICB0aGlzLm1vZGVzID0gdGhpcy5fY29udHJvbGxlck5hbWVzXG4gIHRoaXMuY29tcHV0ZWRNYXRyaXggPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRNYXRyaXhcbiAgdGhpcy5jb21wdXRlZEV5ZSAgICA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZEV5ZVxuICB0aGlzLmNvbXB1dGVkVXAgICAgID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkVXBcbiAgdGhpcy5jb21wdXRlZENlbnRlciA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZENlbnRlclxuICB0aGlzLmNvbXB1dGVkUmFkaXVzID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkUmFkaXVzXG59XG5cbnZhciBwcm90byA9IFZpZXdDb250cm9sbGVyLnByb3RvdHlwZVxuXG52YXIgQ09NTU9OX01FVEhPRFMgPSBbXG4gIFsnZmx1c2gnLCAxXSxcbiAgWydpZGxlJywgMV0sXG4gIFsnbG9va0F0JywgNF0sXG4gIFsncm90YXRlJywgNF0sXG4gIFsncGFuJywgNF0sXG4gIFsndHJhbnNsYXRlJywgNF0sXG4gIFsnc2V0TWF0cml4JywgMl0sXG4gIFsnc2V0RGlzdGFuY2VMaW1pdHMnLCAyXSxcbiAgWydzZXREaXN0YW5jZScsIDJdXG5dXG5cbkNPTU1PTl9NRVRIT0RTLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gIHZhciBuYW1lID0gbWV0aG9kWzBdXG4gIHZhciBhcmdOYW1lcyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG1ldGhvZFsxXTsgKytpKSB7XG4gICAgYXJnTmFtZXMucHVzaCgnYScraSlcbiAgfVxuICB2YXIgY29kZSA9ICd2YXIgY2M9dGhpcy5fY29udHJvbGxlckxpc3Q7Zm9yKHZhciBpPTA7aTxjYy5sZW5ndGg7KytpKXtjY1tpXS4nK21ldGhvZFswXSsnKCcrYXJnTmFtZXMuam9pbigpKycpfSdcbiAgcHJvdG9bbmFtZV0gPSBGdW5jdGlvbi5hcHBseShudWxsLCBhcmdOYW1lcy5jb25jYXQoY29kZSkpXG59KVxuXG5wcm90by5yZWNhbGNNYXRyaXggPSBmdW5jdGlvbih0KSB7XG4gIHRoaXMuX2FjdGl2ZS5yZWNhbGNNYXRyaXgodClcbn1cblxucHJvdG8uZ2V0RGlzdGFuY2UgPSBmdW5jdGlvbih0KSB7XG4gIHJldHVybiB0aGlzLl9hY3RpdmUuZ2V0RGlzdGFuY2UodClcbn1cbnByb3RvLmdldERpc3RhbmNlTGltaXRzID0gZnVuY3Rpb24ob3V0KSB7XG4gIHJldHVybiB0aGlzLl9hY3RpdmUuZ2V0RGlzdGFuY2VMaW1pdHMob3V0KVxufVxuXG5wcm90by5sYXN0VCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5fYWN0aXZlLmxhc3RUKClcbn1cblxucHJvdG8uc2V0TW9kZSA9IGZ1bmN0aW9uKG1vZGUpIHtcbiAgaWYobW9kZSA9PT0gdGhpcy5fbW9kZSkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBpZHggPSB0aGlzLl9jb250cm9sbGVyTmFtZXMuaW5kZXhPZihtb2RlKVxuICBpZihpZHggPCAwKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIHByZXYgID0gdGhpcy5fYWN0aXZlXG4gIHZhciBuZXh0ICA9IHRoaXMuX2NvbnRyb2xsZXJMaXN0W2lkeF1cbiAgdmFyIGxhc3RUID0gTWF0aC5tYXgocHJldi5sYXN0VCgpLCBuZXh0Lmxhc3RUKCkpXG5cbiAgcHJldi5yZWNhbGNNYXRyaXgobGFzdFQpXG4gIG5leHQuc2V0TWF0cml4KGxhc3RULCBwcmV2LmNvbXB1dGVkTWF0cml4KVxuICBcbiAgdGhpcy5fYWN0aXZlID0gbmV4dFxuICB0aGlzLl9tb2RlICAgPSBtb2RlXG5cbiAgLy9VcGRhdGUgbWF0cml4IHByb3BlcnRpZXNcbiAgdGhpcy5jb21wdXRlZE1hdHJpeCA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZE1hdHJpeFxuICB0aGlzLmNvbXB1dGVkRXllICAgID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkRXllXG4gIHRoaXMuY29tcHV0ZWRVcCAgICAgPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRVcFxuICB0aGlzLmNvbXB1dGVkQ2VudGVyID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkQ2VudGVyXG4gIHRoaXMuY29tcHV0ZWRSYWRpdXMgPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRSYWRpdXNcbn1cblxucHJvdG8uZ2V0TW9kZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5fbW9kZVxufVxuXG5mdW5jdGlvbiBjcmVhdGVWaWV3Q29udHJvbGxlcihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgdmFyIGV5ZSAgICAgICA9IG9wdGlvbnMuZXllICAgIHx8IFswLDAsMV1cbiAgdmFyIGNlbnRlciAgICA9IG9wdGlvbnMuY2VudGVyIHx8IFswLDAsMF1cbiAgdmFyIHVwICAgICAgICA9IG9wdGlvbnMudXAgICAgIHx8IFswLDEsMF1cbiAgdmFyIGxpbWl0cyAgICA9IG9wdGlvbnMuZGlzdGFuY2VMaW1pdHMgfHwgWzAsIEluZmluaXR5XVxuICB2YXIgbW9kZSAgICAgID0gb3B0aW9ucy5tb2RlICAgfHwgJ3R1cm50YWJsZSdcblxuICB2YXIgdHVybnRhYmxlID0gY3JlYXRlVHVybnRhYmxlKClcbiAgdmFyIG9yYml0ICAgICA9IGNyZWF0ZU9yYml0KClcbiAgdmFyIG1hdHJpeCAgICA9IGNyZWF0ZU1hdHJpeCgpXG5cbiAgdHVybnRhYmxlLnNldERpc3RhbmNlTGltaXRzKGxpbWl0c1swXSwgbGltaXRzWzFdKVxuICB0dXJudGFibGUubG9va0F0KDAsIGV5ZSwgY2VudGVyLCB1cClcbiAgb3JiaXQuc2V0RGlzdGFuY2VMaW1pdHMobGltaXRzWzBdLCBsaW1pdHNbMV0pXG4gIG9yYml0Lmxvb2tBdCgwLCBleWUsIGNlbnRlciwgdXApXG4gIG1hdHJpeC5zZXREaXN0YW5jZUxpbWl0cyhsaW1pdHNbMF0sIGxpbWl0c1sxXSlcbiAgbWF0cml4Lmxvb2tBdCgwLCBleWUsIGNlbnRlciwgdXApXG5cbiAgcmV0dXJuIG5ldyBWaWV3Q29udHJvbGxlcih7XG4gICAgdHVybnRhYmxlOiB0dXJudGFibGUsXG4gICAgb3JiaXQ6IG9yYml0LFxuICAgIG1hdHJpeDogbWF0cml4XG4gIH0sIG1vZGUpXG59IiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL2QzL2QzLXNhbmtleSBWZXJzaW9uIDAuNS4xLiBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLWFycmF5JyksIHJlcXVpcmUoJ2QzLWNvbGxlY3Rpb24nKSwgcmVxdWlyZSgnZDMtaW50ZXJwb2xhdGUnKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLWFycmF5JywgJ2QzLWNvbGxlY3Rpb24nLCAnZDMtaW50ZXJwb2xhdGUnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMykpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMsZDNBcnJheSxkM0NvbGxlY3Rpb24sZDNJbnRlcnBvbGF0ZSkgeyAndXNlIHN0cmljdCc7XG5cbnZhciBzYW5rZXkgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHNhbmtleSA9IHt9LFxuICAgICAgbm9kZVdpZHRoID0gMjQsXG4gICAgICBub2RlUGFkZGluZyA9IDgsXG4gICAgICBzaXplID0gWzEsIDFdLFxuICAgICAgbm9kZXMgPSBbXSxcbiAgICAgIGxpbmtzID0gW10sXG4gICAgICBtYXhQYWRkZWRTcGFjZSA9IDIgLyAzOyAvLyBEZWZpbmVkIGFzIGEgZnJhY3Rpb24gb2YgdGhlIHRvdGFsIGF2YWlsYWJsZSBzcGFjZVxuXG4gIHNhbmtleS5ub2RlV2lkdGggPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZVdpZHRoO1xuICAgIG5vZGVXaWR0aCA9ICtfO1xuICAgIHJldHVybiBzYW5rZXk7XG4gIH07XG5cbiAgc2Fua2V5Lm5vZGVQYWRkaW5nID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVQYWRkaW5nO1xuICAgIG5vZGVQYWRkaW5nID0gK187XG4gICAgcmV0dXJuIHNhbmtleTtcbiAgfTtcblxuICBzYW5rZXkubm9kZXMgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZXM7XG4gICAgbm9kZXMgPSBfO1xuICAgIHJldHVybiBzYW5rZXk7XG4gIH07XG5cbiAgc2Fua2V5LmxpbmtzID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGxpbmtzO1xuICAgIGxpbmtzID0gXztcbiAgICByZXR1cm4gc2Fua2V5O1xuICB9O1xuXG4gIHNhbmtleS5zaXplID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNpemU7XG4gICAgc2l6ZSA9IF87XG4gICAgcmV0dXJuIHNhbmtleTtcbiAgfTtcblxuICBzYW5rZXkubGF5b3V0ID0gZnVuY3Rpb24oaXRlcmF0aW9ucykge1xuICAgIGNvbXB1dGVOb2RlTGlua3MoKTtcbiAgICBjb21wdXRlTm9kZVZhbHVlcygpO1xuICAgIGNvbXB1dGVOb2RlQnJlYWR0aHMoKTtcbiAgICBjb21wdXRlTm9kZURlcHRocyhpdGVyYXRpb25zKTtcbiAgICBjb21wdXRlTGlua0RlcHRocygpO1xuICAgIHJldHVybiBzYW5rZXk7XG4gIH07XG5cbiAgc2Fua2V5LnJlbGF5b3V0ID0gZnVuY3Rpb24oKSB7XG4gICAgY29tcHV0ZUxpbmtEZXB0aHMoKTtcbiAgICByZXR1cm4gc2Fua2V5O1xuICB9O1xuXG4gIHNhbmtleS5saW5rID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGN1cnZhdHVyZSA9IC41O1xuXG4gICAgZnVuY3Rpb24gbGluayhkKSB7XG4gICAgICB2YXIgeDAgPSBkLnNvdXJjZS54ICsgZC5zb3VyY2UuZHgsXG4gICAgICAgICAgeDEgPSBkLnRhcmdldC54LFxuICAgICAgICAgIHhpID0gZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZU51bWJlcih4MCwgeDEpLFxuICAgICAgICAgIHgyID0geGkoY3VydmF0dXJlKSxcbiAgICAgICAgICB4MyA9IHhpKDEgLSBjdXJ2YXR1cmUpLFxuICAgICAgICAgIHkwYSA9IGQuc291cmNlLnkgKyBkLnN5LFxuICAgICAgICAgIHkwYiA9IHkwYSArIGQuZHksXG4gICAgICAgICAgeTFhID0gZC50YXJnZXQueSArIGQudHksXG4gICAgICAgICAgeTFiID0geTFhICsgZC5keTtcbiAgICAgIHJldHVybiBcIk1cIiArIHgwICsgXCIsXCIgKyB5MGFcbiAgICAgICAgICAgKyBcIkNcIiArIHgyICsgXCIsXCIgKyB5MGFcbiAgICAgICAgICAgKyBcIiBcIiArIHgzICsgXCIsXCIgKyB5MWFcbiAgICAgICAgICAgKyBcIiBcIiArIHgxICsgXCIsXCIgKyB5MWFcbiAgICAgICAgICAgKyBcIkxcIiArIHgxICsgXCIsXCIgKyB5MWJcbiAgICAgICAgICAgKyBcIkNcIiArIHgzICsgXCIsXCIgKyB5MWJcbiAgICAgICAgICAgKyBcIiBcIiArIHgyICsgXCIsXCIgKyB5MGJcbiAgICAgICAgICAgKyBcIiBcIiArIHgwICsgXCIsXCIgKyB5MGJcbiAgICAgICAgICAgKyBcIlpcIjtcbiAgICB9XG5cbiAgICBsaW5rLmN1cnZhdHVyZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGN1cnZhdHVyZTtcbiAgICAgIGN1cnZhdHVyZSA9ICtfO1xuICAgICAgcmV0dXJuIGxpbms7XG4gICAgfTtcblxuICAgIHJldHVybiBsaW5rO1xuICB9O1xuXG4gIC8vIFBvcHVsYXRlIHRoZSBzb3VyY2VMaW5rcyBhbmQgdGFyZ2V0TGlua3MgZm9yIGVhY2ggbm9kZS5cbiAgLy8gQWxzbywgaWYgdGhlIHNvdXJjZSBhbmQgdGFyZ2V0IGFyZSBub3Qgb2JqZWN0cywgYXNzdW1lIHRoZXkgYXJlIGluZGljZXMuXG4gIGZ1bmN0aW9uIGNvbXB1dGVOb2RlTGlua3MoKSB7XG4gICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnNvdXJjZUxpbmtzID0gW107XG4gICAgICBub2RlLnRhcmdldExpbmtzID0gW107XG4gICAgfSk7XG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbihsaW5rLCBpKSB7XG4gICAgICB2YXIgc291cmNlID0gbGluay5zb3VyY2UsXG4gICAgICAgICAgdGFyZ2V0ID0gbGluay50YXJnZXQ7XG4gICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJudW1iZXJcIikgc291cmNlID0gbGluay5zb3VyY2UgPSBub2Rlc1tsaW5rLnNvdXJjZV07XG4gICAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gXCJudW1iZXJcIikgdGFyZ2V0ID0gbGluay50YXJnZXQgPSBub2Rlc1tsaW5rLnRhcmdldF07XG4gICAgICBsaW5rLm9yaWdpbmFsSW5kZXggPSBpO1xuICAgICAgc291cmNlLnNvdXJjZUxpbmtzLnB1c2gobGluayk7XG4gICAgICB0YXJnZXQudGFyZ2V0TGlua3MucHVzaChsaW5rKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIENvbXB1dGUgdGhlIHZhbHVlIChzaXplKSBvZiBlYWNoIG5vZGUgYnkgc3VtbWluZyB0aGUgYXNzb2NpYXRlZCBsaW5rcy5cbiAgZnVuY3Rpb24gY29tcHV0ZU5vZGVWYWx1ZXMoKSB7XG4gICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgIGQzQXJyYXkuc3VtKG5vZGUuc291cmNlTGlua3MsIHZhbHVlKSxcbiAgICAgICAgZDNBcnJheS5zdW0obm9kZS50YXJnZXRMaW5rcywgdmFsdWUpXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gSXRlcmF0aXZlbHkgYXNzaWduIHRoZSBicmVhZHRoICh4LXBvc2l0aW9uKSBmb3IgZWFjaCBub2RlLlxuICAvLyBOb2RlcyBhcmUgYXNzaWduZWQgdGhlIG1heGltdW0gYnJlYWR0aCBvZiBpbmNvbWluZyBuZWlnaGJvcnMgcGx1cyBvbmU7XG4gIC8vIG5vZGVzIHdpdGggbm8gaW5jb21pbmcgbGlua3MgYXJlIGFzc2lnbmVkIGJyZWFkdGggemVybywgd2hpbGVcbiAgLy8gbm9kZXMgd2l0aCBubyBvdXRnb2luZyBsaW5rcyBhcmUgYXNzaWduZWQgdGhlIG1heGltdW0gYnJlYWR0aC5cbiAgZnVuY3Rpb24gY29tcHV0ZU5vZGVCcmVhZHRocygpIHtcbiAgICB2YXIgcmVtYWluaW5nTm9kZXMgPSBub2RlcyxcbiAgICAgICAgbmV4dE5vZGVzLFxuICAgICAgICB4ID0gMDtcblxuICAgIHdoaWxlIChyZW1haW5pbmdOb2Rlcy5sZW5ndGgpIHtcbiAgICAgIG5leHROb2RlcyA9IFtdO1xuICAgICAgcmVtYWluaW5nTm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIG5vZGUueCA9IHg7XG4gICAgICAgIG5vZGUuZHggPSBub2RlV2lkdGg7XG4gICAgICAgIG5vZGUuc291cmNlTGlua3MuZm9yRWFjaChmdW5jdGlvbihsaW5rKSB7XG4gICAgICAgICAgaWYgKG5leHROb2Rlcy5pbmRleE9mKGxpbmsudGFyZ2V0KSA8IDApIHtcbiAgICAgICAgICAgIG5leHROb2Rlcy5wdXNoKGxpbmsudGFyZ2V0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICByZW1haW5pbmdOb2RlcyA9IG5leHROb2RlcztcbiAgICAgICsreDtcbiAgICB9XG5cbiAgICAvL1xuICAgIG1vdmVTaW5rc1JpZ2h0KHgpO1xuICAgIHNjYWxlTm9kZUJyZWFkdGhzKChzaXplWzBdIC0gbm9kZVdpZHRoKSAvICh4IC0gMSkpO1xuICB9XG5cbiAgLy8gZnVuY3Rpb24gbW92ZVNvdXJjZXNSaWdodCgpIHtcbiAgLy8gICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgLy8gICAgIGlmICghbm9kZS50YXJnZXRMaW5rcy5sZW5ndGgpIHtcbiAgLy8gICAgICAgbm9kZS54ID0gbWluKG5vZGUuc291cmNlTGlua3MsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQudGFyZ2V0Lng7IH0pIC0gMTtcbiAgLy8gICAgIH1cbiAgLy8gICB9KTtcbiAgLy8gfVxuXG4gIGZ1bmN0aW9uIG1vdmVTaW5rc1JpZ2h0KHgpIHtcbiAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGlmICghbm9kZS5zb3VyY2VMaW5rcy5sZW5ndGgpIHtcbiAgICAgICAgbm9kZS54ID0geCAtIDE7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBzY2FsZU5vZGVCcmVhZHRocyhreCkge1xuICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZS54ICo9IGt4O1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcHV0ZU5vZGVEZXB0aHMoaXRlcmF0aW9ucykge1xuICAgIHZhciBub2Rlc0J5QnJlYWR0aCA9IGQzQ29sbGVjdGlvbi5uZXN0KClcbiAgICAgICAgLmtleShmdW5jdGlvbihkKSB7IHJldHVybiBkLng7IH0pXG4gICAgICAgIC5zb3J0S2V5cyhkM0FycmF5LmFzY2VuZGluZylcbiAgICAgICAgLmVudHJpZXMobm9kZXMpXG4gICAgICAgIC5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC52YWx1ZXM7IH0pO1xuXG4gICAgLy9cbiAgICBpbml0aWFsaXplTm9kZURlcHRoKCk7XG4gICAgcmVzb2x2ZUNvbGxpc2lvbnMoKTtcbiAgICBmb3IgKHZhciBhbHBoYSA9IDE7IGl0ZXJhdGlvbnMgPiAwOyAtLWl0ZXJhdGlvbnMpIHtcbiAgICAgIHJlbGF4UmlnaHRUb0xlZnQoYWxwaGEgKj0gLjk5KTtcbiAgICAgIHJlc29sdmVDb2xsaXNpb25zKCk7XG4gICAgICByZWxheExlZnRUb1JpZ2h0KGFscGhhKTtcbiAgICAgIHJlc29sdmVDb2xsaXNpb25zKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5pdGlhbGl6ZU5vZGVEZXB0aCgpIHtcbiAgICAgIHZhciBMID0gZDNBcnJheS5tYXgobm9kZXNCeUJyZWFkdGgsIGZ1bmN0aW9uKG5vZGVzKSB7XG4gICAgICAgIHJldHVybiBub2Rlcy5sZW5ndGg7XG4gICAgICB9KTtcbiAgICAgIHZhciBtYXhOb2RlUGFkZGluZyA9IG1heFBhZGRlZFNwYWNlICogc2l6ZVsxXSAvIChMIC0gMSk7XG4gICAgICBpZihub2RlUGFkZGluZyA+IG1heE5vZGVQYWRkaW5nKSBub2RlUGFkZGluZyA9IG1heE5vZGVQYWRkaW5nO1xuICAgICAgdmFyIGt5ID0gZDNBcnJheS5taW4obm9kZXNCeUJyZWFkdGgsIGZ1bmN0aW9uKG5vZGVzKSB7XG4gICAgICAgIHJldHVybiAoc2l6ZVsxXSAtIChub2Rlcy5sZW5ndGggLSAxKSAqIG5vZGVQYWRkaW5nKSAvIGQzQXJyYXkuc3VtKG5vZGVzLCB2YWx1ZSk7XG4gICAgICB9KTtcblxuICAgICAgbm9kZXNCeUJyZWFkdGguZm9yRWFjaChmdW5jdGlvbihub2Rlcykge1xuICAgICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUsIGkpIHtcbiAgICAgICAgICBub2RlLnkgPSBpO1xuICAgICAgICAgIG5vZGUuZHkgPSBub2RlLnZhbHVlICoga3k7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGxpbmtzLmZvckVhY2goZnVuY3Rpb24obGluaykge1xuICAgICAgICBsaW5rLmR5ID0gbGluay52YWx1ZSAqIGt5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVsYXhMZWZ0VG9SaWdodChhbHBoYSkge1xuICAgICAgbm9kZXNCeUJyZWFkdGguZm9yRWFjaChmdW5jdGlvbihub2Rlcykge1xuICAgICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICBpZiAobm9kZS50YXJnZXRMaW5rcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciB5ID0gZDNBcnJheS5zdW0obm9kZS50YXJnZXRMaW5rcywgd2VpZ2h0ZWRTb3VyY2UpIC8gZDNBcnJheS5zdW0obm9kZS50YXJnZXRMaW5rcywgdmFsdWUpO1xuICAgICAgICAgICAgbm9kZS55ICs9ICh5IC0gY2VudGVyKG5vZGUpKSAqIGFscGhhO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZnVuY3Rpb24gd2VpZ2h0ZWRTb3VyY2UobGluaykge1xuICAgICAgICByZXR1cm4gY2VudGVyKGxpbmsuc291cmNlKSAqIGxpbmsudmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVsYXhSaWdodFRvTGVmdChhbHBoYSkge1xuICAgICAgbm9kZXNCeUJyZWFkdGguc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaChmdW5jdGlvbihub2Rlcykge1xuICAgICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICBpZiAobm9kZS5zb3VyY2VMaW5rcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciB5ID0gZDNBcnJheS5zdW0obm9kZS5zb3VyY2VMaW5rcywgd2VpZ2h0ZWRUYXJnZXQpIC8gZDNBcnJheS5zdW0obm9kZS5zb3VyY2VMaW5rcywgdmFsdWUpO1xuICAgICAgICAgICAgbm9kZS55ICs9ICh5IC0gY2VudGVyKG5vZGUpKSAqIGFscGhhO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZnVuY3Rpb24gd2VpZ2h0ZWRUYXJnZXQobGluaykge1xuICAgICAgICByZXR1cm4gY2VudGVyKGxpbmsudGFyZ2V0KSAqIGxpbmsudmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUNvbGxpc2lvbnMoKSB7XG4gICAgICBub2Rlc0J5QnJlYWR0aC5mb3JFYWNoKGZ1bmN0aW9uKG5vZGVzKSB7XG4gICAgICAgIHZhciBub2RlLFxuICAgICAgICAgICAgZHksXG4gICAgICAgICAgICB5MCA9IDAsXG4gICAgICAgICAgICBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgICAgICAgaTtcblxuICAgICAgICAvLyBQdXNoIGFueSBvdmVybGFwcGluZyBub2RlcyBkb3duLlxuICAgICAgICBub2Rlcy5zb3J0KGFzY2VuZGluZ0RlcHRoKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgICBkeSA9IHkwIC0gbm9kZS55O1xuICAgICAgICAgIGlmIChkeSA+IDApIG5vZGUueSArPSBkeTtcbiAgICAgICAgICB5MCA9IG5vZGUueSArIG5vZGUuZHkgKyBub2RlUGFkZGluZztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSBib3R0b21tb3N0IG5vZGUgZ29lcyBvdXRzaWRlIHRoZSBib3VuZHMsIHB1c2ggaXQgYmFjayB1cC5cbiAgICAgICAgZHkgPSB5MCAtIG5vZGVQYWRkaW5nIC0gc2l6ZVsxXTtcbiAgICAgICAgaWYgKGR5ID4gMCkge1xuICAgICAgICAgIHkwID0gbm9kZS55IC09IGR5O1xuXG4gICAgICAgICAgLy8gUHVzaCBhbnkgb3ZlcmxhcHBpbmcgbm9kZXMgYmFjayB1cC5cbiAgICAgICAgICBmb3IgKGkgPSBuIC0gMjsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgICAgIGR5ID0gbm9kZS55ICsgbm9kZS5keSArIG5vZGVQYWRkaW5nIC0geTA7XG4gICAgICAgICAgICBpZiAoZHkgPiAwKSBub2RlLnkgLT0gZHk7XG4gICAgICAgICAgICB5MCA9IG5vZGUueTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFzY2VuZGluZ0RlcHRoKGEsIGIpIHtcbiAgICAgIHJldHVybiBhLnkgLSBiLnk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29tcHV0ZUxpbmtEZXB0aHMoKSB7XG4gICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnNvdXJjZUxpbmtzLnNvcnQoYXNjZW5kaW5nVGFyZ2V0RGVwdGgpO1xuICAgICAgbm9kZS50YXJnZXRMaW5rcy5zb3J0KGFzY2VuZGluZ1NvdXJjZURlcHRoKTtcbiAgICB9KTtcbiAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciBzeSA9IDAsIHR5ID0gMDtcbiAgICAgIG5vZGUuc291cmNlTGlua3MuZm9yRWFjaChmdW5jdGlvbihsaW5rKSB7XG4gICAgICAgIGxpbmsuc3kgPSBzeTtcbiAgICAgICAgc3kgKz0gbGluay5keTtcbiAgICAgIH0pO1xuICAgICAgbm9kZS50YXJnZXRMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uKGxpbmspIHtcbiAgICAgICAgbGluay50eSA9IHR5O1xuICAgICAgICB0eSArPSBsaW5rLmR5O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBhc2NlbmRpbmdTb3VyY2VEZXB0aChhLCBiKSB7XG4gICAgICByZXR1cm4gKGEuc291cmNlLnkgLSBiLnNvdXJjZS55KSB8fCAoYS5vcmlnaW5hbEluZGV4IC0gYi5vcmlnaW5hbEluZGV4KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhc2NlbmRpbmdUYXJnZXREZXB0aChhLCBiKSB7XG4gICAgICByZXR1cm4gKGEudGFyZ2V0LnkgLSBiLnRhcmdldC55KSB8fCAoYS5vcmlnaW5hbEluZGV4IC0gYi5vcmlnaW5hbEluZGV4KTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjZW50ZXIobm9kZSkge1xuICAgIHJldHVybiBub2RlLnkgKyBub2RlLmR5IC8gMjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZhbHVlKGxpbmspIHtcbiAgICByZXR1cm4gbGluay52YWx1ZTtcbiAgfVxuXG4gIHJldHVybiBzYW5rZXk7XG59O1xuXG5leHBvcnRzLnNhbmtleSA9IHNhbmtleTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgd2Vha01hcCAgICAgID0gdHlwZW9mIFdlYWtNYXAgPT09ICd1bmRlZmluZWQnID8gcmVxdWlyZSgnd2Vhay1tYXAnKSA6IFdlYWtNYXBcbnZhciBjcmVhdGVCdWZmZXIgPSByZXF1aXJlKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyAgICA9IHJlcXVpcmUoJ2dsLXZhbycpXG5cbnZhciBUcmlhbmdsZUNhY2hlID0gbmV3IHdlYWtNYXAoKVxuXG5mdW5jdGlvbiBjcmVhdGVBQmlnVHJpYW5nbGUoZ2wpIHtcblxuICB2YXIgdHJpYW5nbGVWQU8gPSBUcmlhbmdsZUNhY2hlLmdldChnbClcbiAgdmFyIGhhbmRsZSA9IHRyaWFuZ2xlVkFPICYmICh0cmlhbmdsZVZBTy5fdHJpYW5nbGVCdWZmZXIuaGFuZGxlIHx8IHRyaWFuZ2xlVkFPLl90cmlhbmdsZUJ1ZmZlci5idWZmZXIpXG4gIGlmKCFoYW5kbGUgfHwgIWdsLmlzQnVmZmVyKGhhbmRsZSkpIHtcbiAgICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGdsLCBuZXcgRmxvYXQzMkFycmF5KFstMSwgLTEsIC0xLCA0LCA0LCAtMV0pKVxuICAgIHRyaWFuZ2xlVkFPID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgICB7IGJ1ZmZlcjogYnVmLFxuICAgICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgICAgc2l6ZTogMlxuICAgICAgfVxuICAgIF0pXG4gICAgdHJpYW5nbGVWQU8uX3RyaWFuZ2xlQnVmZmVyID0gYnVmXG4gICAgVHJpYW5nbGVDYWNoZS5zZXQoZ2wsIHRyaWFuZ2xlVkFPKVxuICB9XG4gIHRyaWFuZ2xlVkFPLmJpbmQoKVxuICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgMylcbiAgdHJpYW5nbGVWQU8udW5iaW5kKClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBQmlnVHJpYW5nbGVcbiIsIlxubW9kdWxlLmV4cG9ydHMgPSBhYnNvbHV0aXplXG5cbi8qKlxuICogcmVkZWZpbmUgYHBhdGhgIHdpdGggYWJzb2x1dGUgY29vcmRpbmF0ZXNcbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBwYXRoXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuXG5mdW5jdGlvbiBhYnNvbHV0aXplKHBhdGgpe1xuXHR2YXIgc3RhcnRYID0gMFxuXHR2YXIgc3RhcnRZID0gMFxuXHR2YXIgeCA9IDBcblx0dmFyIHkgPSAwXG5cblx0cmV0dXJuIHBhdGgubWFwKGZ1bmN0aW9uKHNlZyl7XG5cdFx0c2VnID0gc2VnLnNsaWNlKClcblx0XHR2YXIgdHlwZSA9IHNlZ1swXVxuXHRcdHZhciBjb21tYW5kID0gdHlwZS50b1VwcGVyQ2FzZSgpXG5cblx0XHQvLyBpcyByZWxhdGl2ZVxuXHRcdGlmICh0eXBlICE9IGNvbW1hbmQpIHtcblx0XHRcdHNlZ1swXSA9IGNvbW1hbmRcblx0XHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0XHRjYXNlICdhJzpcblx0XHRcdFx0XHRzZWdbNl0gKz0geFxuXHRcdFx0XHRcdHNlZ1s3XSArPSB5XG5cdFx0XHRcdFx0YnJlYWtcblx0XHRcdFx0Y2FzZSAndic6XG5cdFx0XHRcdFx0c2VnWzFdICs9IHlcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlICdoJzpcblx0XHRcdFx0XHRzZWdbMV0gKz0geFxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDE7IGkgPCBzZWcubGVuZ3RoOykge1xuXHRcdFx0XHRcdFx0c2VnW2krK10gKz0geFxuXHRcdFx0XHRcdFx0c2VnW2krK10gKz0geVxuXHRcdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyB1cGRhdGUgY3Vyc29yIHN0YXRlXG5cdFx0c3dpdGNoIChjb21tYW5kKSB7XG5cdFx0XHRjYXNlICdaJzpcblx0XHRcdFx0eCA9IHN0YXJ0WFxuXHRcdFx0XHR5ID0gc3RhcnRZXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdIJzpcblx0XHRcdFx0eCA9IHNlZ1sxXVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnVic6XG5cdFx0XHRcdHkgPSBzZWdbMV1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ00nOlxuXHRcdFx0XHR4ID0gc3RhcnRYID0gc2VnWzFdXG5cdFx0XHRcdHkgPSBzdGFydFkgPSBzZWdbMl1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHggPSBzZWdbc2VnLmxlbmd0aCAtIDJdXG5cdFx0XHRcdHkgPSBzZWdbc2VnLmxlbmd0aCAtIDFdXG5cdFx0fVxuXG5cdFx0cmV0dXJuIHNlZ1xuXHR9KVxufVxuIiwidmFyIHBhZExlZnQgPSByZXF1aXJlKCdwYWQtbGVmdCcpXG5cbm1vZHVsZS5leHBvcnRzID0gYWRkTGluZU51bWJlcnNcbmZ1bmN0aW9uIGFkZExpbmVOdW1iZXJzIChzdHJpbmcsIHN0YXJ0LCBkZWxpbSkge1xuICBzdGFydCA9IHR5cGVvZiBzdGFydCA9PT0gJ251bWJlcicgPyBzdGFydCA6IDFcbiAgZGVsaW0gPSBkZWxpbSB8fCAnOiAnXG5cbiAgdmFyIGxpbmVzID0gc3RyaW5nLnNwbGl0KC9cXHI/XFxuLylcbiAgdmFyIHRvdGFsRGlnaXRzID0gU3RyaW5nKGxpbmVzLmxlbmd0aCArIHN0YXJ0IC0gMSkubGVuZ3RoXG4gIHJldHVybiBsaW5lcy5tYXAoZnVuY3Rpb24gKGxpbmUsIGkpIHtcbiAgICB2YXIgYyA9IGkgKyBzdGFydFxuICAgIHZhciBkaWdpdHMgPSBTdHJpbmcoYykubGVuZ3RoXG4gICAgdmFyIHByZWZpeCA9IHBhZExlZnQoYywgdG90YWxEaWdpdHMgLSBkaWdpdHMpXG4gICAgcmV0dXJuIHByZWZpeCArIGRlbGltICsgbGluZVxuICB9KS5qb2luKCdcXG4nKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gYWZmaW5lSHVsbFxuXG52YXIgb3JpZW50ID0gcmVxdWlyZSgncm9idXN0LW9yaWVudGF0aW9uJylcblxuZnVuY3Rpb24gbGluZWFybHlJbmRlcGVuZGVudChwb2ludHMsIGQpIHtcbiAgdmFyIG5odWxsID0gbmV3IEFycmF5KGQrMSlcbiAgZm9yKHZhciBpPTA7IGk8cG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgbmh1bGxbaV0gPSBwb2ludHNbaV1cbiAgfVxuICBmb3IodmFyIGk9MDsgaTw9cG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgZm9yKHZhciBqPXBvaW50cy5sZW5ndGg7IGo8PWQ7ICsraikge1xuICAgICAgdmFyIHggPSBuZXcgQXJyYXkoZClcbiAgICAgIGZvcih2YXIgaz0wOyBrPGQ7ICsraykge1xuICAgICAgICB4W2tdID0gTWF0aC5wb3coaisxLWksIGspXG4gICAgICB9XG4gICAgICBuaHVsbFtqXSA9IHhcbiAgICB9XG4gICAgdmFyIG8gPSBvcmllbnQuYXBwbHkodm9pZCAwLCBuaHVsbClcbiAgICBpZihvKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gYWZmaW5lSHVsbChwb2ludHMpIHtcbiAgdmFyIG4gPSBwb2ludHMubGVuZ3RoXG4gIGlmKG4gPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICBpZihuID09PSAxKSB7XG4gICAgcmV0dXJuIFswXVxuICB9XG4gIHZhciBkID0gcG9pbnRzWzBdLmxlbmd0aFxuICB2YXIgZnJhbWUgPSBbIHBvaW50c1swXSBdXG4gIHZhciBpbmRleCA9IFsgMCBdXG4gIGZvcih2YXIgaT0xOyBpPG47ICsraSkge1xuICAgIGZyYW1lLnB1c2gocG9pbnRzW2ldKVxuICAgIGlmKCFsaW5lYXJseUluZGVwZW5kZW50KGZyYW1lLCBkKSkge1xuICAgICAgZnJhbWUucG9wKClcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGluZGV4LnB1c2goaSlcbiAgICBpZihpbmRleC5sZW5ndGggPT09IGQrMSkge1xuICAgICAgcmV0dXJuIGluZGV4XG4gICAgfVxuICB9XG4gIHJldHVybiBpbmRleFxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGFscGhhQ29tcGxleFxuXG52YXIgZGVsYXVuYXkgPSByZXF1aXJlKCdkZWxhdW5heS10cmlhbmd1bGF0ZScpXG52YXIgY2lyY3VtcmFkaXVzID0gcmVxdWlyZSgnY2lyY3VtcmFkaXVzJylcblxuZnVuY3Rpb24gYWxwaGFDb21wbGV4KGFscGhhLCBwb2ludHMpIHtcbiAgcmV0dXJuIGRlbGF1bmF5KHBvaW50cykuZmlsdGVyKGZ1bmN0aW9uKGNlbGwpIHtcbiAgICB2YXIgc2ltcGxleCA9IG5ldyBBcnJheShjZWxsLmxlbmd0aClcbiAgICBmb3IodmFyIGk9MDsgaTxjZWxsLmxlbmd0aDsgKytpKSB7XG4gICAgICBzaW1wbGV4W2ldID0gcG9pbnRzW2NlbGxbaV1dXG4gICAgfVxuICAgIHJldHVybiBjaXJjdW1yYWRpdXMoc2ltcGxleCkgKiBhbHBoYSA8IDFcbiAgfSlcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGFscGhhU2hhcGVcblxudmFyIGFjID0gcmVxdWlyZSgnYWxwaGEtY29tcGxleCcpXG52YXIgYm5kID0gcmVxdWlyZSgnc2ltcGxpY2lhbC1jb21wbGV4LWJvdW5kYXJ5JylcblxuZnVuY3Rpb24gYWxwaGFTaGFwZShhbHBoYSwgcG9pbnRzKSB7XG4gIHJldHVybiBibmQoYWMoYWxwaGEsIHBvaW50cykpXG59IiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IG5vcm1hbGl6ZTtcclxuXHJcbmZ1bmN0aW9uIG5vcm1hbGl6ZSAoYXJyLCBkaW0pIHtcclxuXHRpZiAoIWFyciB8fCBhcnIubGVuZ3RoID09IG51bGwpIHRocm93IEVycm9yKCdBcmd1bWVudCBzaG91bGQgYmUgYW4gYXJyYXknKVxyXG5cclxuXHRpZiAoZGltID09IG51bGwpIGRpbSA9IDFcclxuXHRlbHNlIGRpbSA9IE1hdGguZmxvb3IoZGltKVxyXG5cclxuXHR2YXIgYm91bmRzID0gQXJyYXkoZGltICogMilcclxuXHJcblx0Zm9yICh2YXIgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgZGltOyBvZmZzZXQrKykge1xyXG5cdFx0dmFyIG1heCA9IC1JbmZpbml0eSwgbWluID0gSW5maW5pdHksIGkgPSBvZmZzZXQsIGwgPSBhcnIubGVuZ3RoO1xyXG5cclxuXHRcdGZvciAoOyBpIDwgbDsgaSs9ZGltKSB7XHJcblx0XHRcdGlmIChhcnJbaV0gPiBtYXgpIG1heCA9IGFycltpXTtcclxuXHRcdFx0aWYgKGFycltpXSA8IG1pbikgbWluID0gYXJyW2ldO1xyXG5cdFx0fVxyXG5cclxuXHRcdGJvdW5kc1tvZmZzZXRdID0gbWluXHJcblx0XHRib3VuZHNbZGltICsgb2Zmc2V0XSA9IG1heFxyXG5cdH1cclxuXHJcblx0cmV0dXJuIGJvdW5kcztcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBnZXRCb3VuZHMgPSByZXF1aXJlKCdhcnJheS1ib3VuZHMnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBub3JtYWxpemU7XHJcblxyXG5mdW5jdGlvbiBub3JtYWxpemUgKGFyciwgZGltLCBib3VuZHMpIHtcclxuXHRpZiAoIWFyciB8fCBhcnIubGVuZ3RoID09IG51bGwpIHRocm93IEVycm9yKCdBcmd1bWVudCBzaG91bGQgYmUgYW4gYXJyYXknKVxyXG5cclxuXHRpZiAoZGltID09IG51bGwpIGRpbSA9IDFcclxuXHRpZiAoYm91bmRzID09IG51bGwpIGJvdW5kcyA9IGdldEJvdW5kcyhhcnIsIGRpbSlcclxuXHJcblx0Zm9yICh2YXIgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgZGltOyBvZmZzZXQrKykge1xyXG5cdFx0dmFyIG1heCA9IGJvdW5kc1tkaW0gKyBvZmZzZXRdLCBtaW4gPSBib3VuZHNbb2Zmc2V0XSwgaSA9IG9mZnNldCwgbCA9IGFyci5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKG1heCA9PT0gSW5maW5pdHkgJiYgbWluID09PSAtSW5maW5pdHkpIHtcclxuXHRcdFx0Zm9yIChpID0gb2Zmc2V0OyBpIDwgbDsgaSs9ZGltKSB7XHJcblx0XHRcdFx0YXJyW2ldID0gYXJyW2ldID09PSBtYXggPyAxIDogYXJyW2ldID09PSBtaW4gPyAwIDogLjVcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSBpZiAobWF4ID09PSBJbmZpbml0eSkge1xyXG5cdFx0XHRmb3IgKGkgPSBvZmZzZXQ7IGkgPCBsOyBpKz1kaW0pIHtcclxuXHRcdFx0XHRhcnJbaV0gPSBhcnJbaV0gPT09IG1heCA/IDEgOiAwXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGVsc2UgaWYgKG1pbiA9PT0gLUluZmluaXR5KSB7XHJcblx0XHRcdGZvciAoaSA9IG9mZnNldDsgaSA8IGw7IGkrPWRpbSkge1xyXG5cdFx0XHRcdGFycltpXSA9IGFycltpXSA9PT0gbWluID8gMCA6IDFcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHZhciByYW5nZSA9IG1heCAtIG1pblxyXG5cdFx0XHRmb3IgKGkgPSBvZmZzZXQ7IGkgPCBsOyBpKz1kaW0pIHtcclxuXHRcdFx0XHRhcnJbaV0gPSByYW5nZSA9PT0gMCA/IC41IDogKGFycltpXSAtIG1pbikgLyByYW5nZVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gYXJyO1xyXG59XHJcbiIsIlxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBuZXdBcnJheShzdGFydCwgZW5kKSB7XG4gICAgdmFyIG4wID0gdHlwZW9mIHN0YXJ0ID09PSAnbnVtYmVyJyxcbiAgICAgICAgbjEgPSB0eXBlb2YgZW5kID09PSAnbnVtYmVyJ1xuXG4gICAgaWYgKG4wICYmICFuMSkge1xuICAgICAgICBlbmQgPSBzdGFydFxuICAgICAgICBzdGFydCA9IDBcbiAgICB9IGVsc2UgaWYgKCFuMCAmJiAhbjEpIHtcbiAgICAgICAgc3RhcnQgPSAwXG4gICAgICAgIGVuZCA9IDBcbiAgICB9XG5cbiAgICBzdGFydCA9IHN0YXJ0fDBcbiAgICBlbmQgPSBlbmR8MFxuICAgIHZhciBsZW4gPSBlbmQtc3RhcnRcbiAgICBpZiAobGVuPDApXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYXJyYXkgbGVuZ3RoIG11c3QgYmUgcG9zaXRpdmUnKVxuICAgIFxuICAgIHZhciBhID0gbmV3IEFycmF5KGxlbilcbiAgICBmb3IgKHZhciBpPTAsIGM9c3RhcnQ7IGk8bGVuOyBpKyssIGMrKylcbiAgICAgICAgYVtpXSA9IGNcbiAgICByZXR1cm4gYVxufSIsIid1c2Ugc3RyaWN0JztcblxuLy8gY29tcGFyZSBhbmQgaXNCdWZmZXIgdGFrZW4gZnJvbSBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9ibG9iLzY4MGU5ZTVlNDg4ZjIyYWFjMjc1OTlhNTdkYzg0NGE2MzE1OTI4ZGQvaW5kZXguanNcbi8vIG9yaWdpbmFsIG5vdGljZTpcblxuLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuZnVuY3Rpb24gY29tcGFyZShhLCBiKSB7XG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICB2YXIgeCA9IGEubGVuZ3RoO1xuICB2YXIgeSA9IGIubGVuZ3RoO1xuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBNYXRoLm1pbih4LCB5KTsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHtcbiAgICAgIHggPSBhW2ldO1xuICAgICAgeSA9IGJbaV07XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHtcbiAgICByZXR1cm4gLTE7XG4gIH1cbiAgaWYgKHkgPCB4KSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cbiAgcmV0dXJuIDA7XG59XG5mdW5jdGlvbiBpc0J1ZmZlcihiKSB7XG4gIGlmIChnbG9iYWwuQnVmZmVyICYmIHR5cGVvZiBnbG9iYWwuQnVmZmVyLmlzQnVmZmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGdsb2JhbC5CdWZmZXIuaXNCdWZmZXIoYik7XG4gIH1cbiAgcmV0dXJuICEhKGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlcik7XG59XG5cbi8vIGJhc2VkIG9uIG5vZGUgYXNzZXJ0LCBvcmlnaW5hbCBub3RpY2U6XG5cbi8vIGh0dHA6Ly93aWtpLmNvbW1vbmpzLm9yZy93aWtpL1VuaXRfVGVzdGluZy8xLjBcbi8vXG4vLyBUSElTIElTIE5PVCBURVNURUQgTk9SIExJS0VMWSBUTyBXT1JLIE9VVFNJREUgVjghXG4vL1xuLy8gT3JpZ2luYWxseSBmcm9tIG5hcndoYWwuanMgKGh0dHA6Ly9uYXJ3aGFsanMub3JnKVxuLy8gQ29weXJpZ2h0IChjKSAyMDA5IFRob21hcyBSb2JpbnNvbiA8Mjgwbm9ydGguY29tPlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICdTb2Z0d2FyZScpLCB0b1xuLy8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAnQVMgSVMnLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU5cbi8vIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT05cbi8vIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJ3V0aWwvJyk7XG52YXIgaGFzT3duID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbnZhciBwU2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG52YXIgZnVuY3Rpb25zSGF2ZU5hbWVzID0gKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGZvbygpIHt9Lm5hbWUgPT09ICdmb28nO1xufSgpKTtcbmZ1bmN0aW9uIHBUb1N0cmluZyAob2JqKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcbn1cbmZ1bmN0aW9uIGlzVmlldyhhcnJidWYpIHtcbiAgaWYgKGlzQnVmZmVyKGFycmJ1ZikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHR5cGVvZiBnbG9iYWwuQXJyYXlCdWZmZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlci5pc1ZpZXcgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gQXJyYXlCdWZmZXIuaXNWaWV3KGFycmJ1Zik7XG4gIH1cbiAgaWYgKCFhcnJidWYpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGFycmJ1ZiBpbnN0YW5jZW9mIERhdGFWaWV3KSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKGFycmJ1Zi5idWZmZXIgJiYgYXJyYnVmLmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuLy8gMS4gVGhlIGFzc2VydCBtb2R1bGUgcHJvdmlkZXMgZnVuY3Rpb25zIHRoYXQgdGhyb3dcbi8vIEFzc2VydGlvbkVycm9yJ3Mgd2hlbiBwYXJ0aWN1bGFyIGNvbmRpdGlvbnMgYXJlIG5vdCBtZXQuIFRoZVxuLy8gYXNzZXJ0IG1vZHVsZSBtdXN0IGNvbmZvcm0gdG8gdGhlIGZvbGxvd2luZyBpbnRlcmZhY2UuXG5cbnZhciBhc3NlcnQgPSBtb2R1bGUuZXhwb3J0cyA9IG9rO1xuXG4vLyAyLiBUaGUgQXNzZXJ0aW9uRXJyb3IgaXMgZGVmaW5lZCBpbiBhc3NlcnQuXG4vLyBuZXcgYXNzZXJ0LkFzc2VydGlvbkVycm9yKHsgbWVzc2FnZTogbWVzc2FnZSxcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3R1YWw6IGFjdHVhbCxcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBlY3RlZDogZXhwZWN0ZWQgfSlcblxudmFyIHJlZ2V4ID0gL1xccypmdW5jdGlvblxccysoW15cXChcXHNdKilcXHMqLztcbi8vIGJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS9samhhcmIvZnVuY3Rpb24ucHJvdG90eXBlLm5hbWUvYmxvYi9hZGVlZWVjOGJmY2M2MDY4YjE4N2Q3ZDlmYjNkNWJiMWQzYTMwODk5L2ltcGxlbWVudGF0aW9uLmpzXG5mdW5jdGlvbiBnZXROYW1lKGZ1bmMpIHtcbiAgaWYgKCF1dGlsLmlzRnVuY3Rpb24oZnVuYykpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGZ1bmN0aW9uc0hhdmVOYW1lcykge1xuICAgIHJldHVybiBmdW5jLm5hbWU7XG4gIH1cbiAgdmFyIHN0ciA9IGZ1bmMudG9TdHJpbmcoKTtcbiAgdmFyIG1hdGNoID0gc3RyLm1hdGNoKHJlZ2V4KTtcbiAgcmV0dXJuIG1hdGNoICYmIG1hdGNoWzFdO1xufVxuYXNzZXJ0LkFzc2VydGlvbkVycm9yID0gZnVuY3Rpb24gQXNzZXJ0aW9uRXJyb3Iob3B0aW9ucykge1xuICB0aGlzLm5hbWUgPSAnQXNzZXJ0aW9uRXJyb3InO1xuICB0aGlzLmFjdHVhbCA9IG9wdGlvbnMuYWN0dWFsO1xuICB0aGlzLmV4cGVjdGVkID0gb3B0aW9ucy5leHBlY3RlZDtcbiAgdGhpcy5vcGVyYXRvciA9IG9wdGlvbnMub3BlcmF0b3I7XG4gIGlmIChvcHRpb25zLm1lc3NhZ2UpIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSBvcHRpb25zLm1lc3NhZ2U7XG4gICAgdGhpcy5nZW5lcmF0ZWRNZXNzYWdlID0gZmFsc2U7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5tZXNzYWdlID0gZ2V0TWVzc2FnZSh0aGlzKTtcbiAgICB0aGlzLmdlbmVyYXRlZE1lc3NhZ2UgPSB0cnVlO1xuICB9XG4gIHZhciBzdGFja1N0YXJ0RnVuY3Rpb24gPSBvcHRpb25zLnN0YWNrU3RhcnRGdW5jdGlvbiB8fCBmYWlsO1xuICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBzdGFja1N0YXJ0RnVuY3Rpb24pO1xuICB9IGVsc2Uge1xuICAgIC8vIG5vbiB2OCBicm93c2VycyBzbyB3ZSBjYW4gaGF2ZSBhIHN0YWNrdHJhY2VcbiAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG4gICAgaWYgKGVyci5zdGFjaykge1xuICAgICAgdmFyIG91dCA9IGVyci5zdGFjaztcblxuICAgICAgLy8gdHJ5IHRvIHN0cmlwIHVzZWxlc3MgZnJhbWVzXG4gICAgICB2YXIgZm5fbmFtZSA9IGdldE5hbWUoc3RhY2tTdGFydEZ1bmN0aW9uKTtcbiAgICAgIHZhciBpZHggPSBvdXQuaW5kZXhPZignXFxuJyArIGZuX25hbWUpO1xuICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgIC8vIG9uY2Ugd2UgaGF2ZSBsb2NhdGVkIHRoZSBmdW5jdGlvbiBmcmFtZVxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHN0cmlwIG91dCBldmVyeXRoaW5nIGJlZm9yZSBpdCAoYW5kIGl0cyBsaW5lKVxuICAgICAgICB2YXIgbmV4dF9saW5lID0gb3V0LmluZGV4T2YoJ1xcbicsIGlkeCArIDEpO1xuICAgICAgICBvdXQgPSBvdXQuc3Vic3RyaW5nKG5leHRfbGluZSArIDEpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnN0YWNrID0gb3V0O1xuICAgIH1cbiAgfVxufTtcblxuLy8gYXNzZXJ0LkFzc2VydGlvbkVycm9yIGluc3RhbmNlb2YgRXJyb3JcbnV0aWwuaW5oZXJpdHMoYXNzZXJ0LkFzc2VydGlvbkVycm9yLCBFcnJvcik7XG5cbmZ1bmN0aW9uIHRydW5jYXRlKHMsIG4pIHtcbiAgaWYgKHR5cGVvZiBzID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBzLmxlbmd0aCA8IG4gPyBzIDogcy5zbGljZSgwLCBuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcztcbiAgfVxufVxuZnVuY3Rpb24gaW5zcGVjdChzb21ldGhpbmcpIHtcbiAgaWYgKGZ1bmN0aW9uc0hhdmVOYW1lcyB8fCAhdXRpbC5pc0Z1bmN0aW9uKHNvbWV0aGluZykpIHtcbiAgICByZXR1cm4gdXRpbC5pbnNwZWN0KHNvbWV0aGluZyk7XG4gIH1cbiAgdmFyIHJhd25hbWUgPSBnZXROYW1lKHNvbWV0aGluZyk7XG4gIHZhciBuYW1lID0gcmF3bmFtZSA/ICc6ICcgKyByYXduYW1lIDogJyc7XG4gIHJldHVybiAnW0Z1bmN0aW9uJyArICBuYW1lICsgJ10nO1xufVxuZnVuY3Rpb24gZ2V0TWVzc2FnZShzZWxmKSB7XG4gIHJldHVybiB0cnVuY2F0ZShpbnNwZWN0KHNlbGYuYWN0dWFsKSwgMTI4KSArICcgJyArXG4gICAgICAgICBzZWxmLm9wZXJhdG9yICsgJyAnICtcbiAgICAgICAgIHRydW5jYXRlKGluc3BlY3Qoc2VsZi5leHBlY3RlZCksIDEyOCk7XG59XG5cbi8vIEF0IHByZXNlbnQgb25seSB0aGUgdGhyZWUga2V5cyBtZW50aW9uZWQgYWJvdmUgYXJlIHVzZWQgYW5kXG4vLyB1bmRlcnN0b29kIGJ5IHRoZSBzcGVjLiBJbXBsZW1lbnRhdGlvbnMgb3Igc3ViIG1vZHVsZXMgY2FuIHBhc3Ncbi8vIG90aGVyIGtleXMgdG8gdGhlIEFzc2VydGlvbkVycm9yJ3MgY29uc3RydWN0b3IgLSB0aGV5IHdpbGwgYmVcbi8vIGlnbm9yZWQuXG5cbi8vIDMuIEFsbCBvZiB0aGUgZm9sbG93aW5nIGZ1bmN0aW9ucyBtdXN0IHRocm93IGFuIEFzc2VydGlvbkVycm9yXG4vLyB3aGVuIGEgY29ycmVzcG9uZGluZyBjb25kaXRpb24gaXMgbm90IG1ldCwgd2l0aCBhIG1lc3NhZ2UgdGhhdFxuLy8gbWF5IGJlIHVuZGVmaW5lZCBpZiBub3QgcHJvdmlkZWQuICBBbGwgYXNzZXJ0aW9uIG1ldGhvZHMgcHJvdmlkZVxuLy8gYm90aCB0aGUgYWN0dWFsIGFuZCBleHBlY3RlZCB2YWx1ZXMgdG8gdGhlIGFzc2VydGlvbiBlcnJvciBmb3Jcbi8vIGRpc3BsYXkgcHVycG9zZXMuXG5cbmZ1bmN0aW9uIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgb3BlcmF0b3IsIHN0YWNrU3RhcnRGdW5jdGlvbikge1xuICB0aHJvdyBuZXcgYXNzZXJ0LkFzc2VydGlvbkVycm9yKHtcbiAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgIGFjdHVhbDogYWN0dWFsLFxuICAgIGV4cGVjdGVkOiBleHBlY3RlZCxcbiAgICBvcGVyYXRvcjogb3BlcmF0b3IsXG4gICAgc3RhY2tTdGFydEZ1bmN0aW9uOiBzdGFja1N0YXJ0RnVuY3Rpb25cbiAgfSk7XG59XG5cbi8vIEVYVEVOU0lPTiEgYWxsb3dzIGZvciB3ZWxsIGJlaGF2ZWQgZXJyb3JzIGRlZmluZWQgZWxzZXdoZXJlLlxuYXNzZXJ0LmZhaWwgPSBmYWlsO1xuXG4vLyA0LiBQdXJlIGFzc2VydGlvbiB0ZXN0cyB3aGV0aGVyIGEgdmFsdWUgaXMgdHJ1dGh5LCBhcyBkZXRlcm1pbmVkXG4vLyBieSAhIWd1YXJkLlxuLy8gYXNzZXJ0Lm9rKGd1YXJkLCBtZXNzYWdlX29wdCk7XG4vLyBUaGlzIHN0YXRlbWVudCBpcyBlcXVpdmFsZW50IHRvIGFzc2VydC5lcXVhbCh0cnVlLCAhIWd1YXJkLFxuLy8gbWVzc2FnZV9vcHQpOy4gVG8gdGVzdCBzdHJpY3RseSBmb3IgdGhlIHZhbHVlIHRydWUsIHVzZVxuLy8gYXNzZXJ0LnN0cmljdEVxdWFsKHRydWUsIGd1YXJkLCBtZXNzYWdlX29wdCk7LlxuXG5mdW5jdGlvbiBvayh2YWx1ZSwgbWVzc2FnZSkge1xuICBpZiAoIXZhbHVlKSBmYWlsKHZhbHVlLCB0cnVlLCBtZXNzYWdlLCAnPT0nLCBhc3NlcnQub2spO1xufVxuYXNzZXJ0Lm9rID0gb2s7XG5cbi8vIDUuIFRoZSBlcXVhbGl0eSBhc3NlcnRpb24gdGVzdHMgc2hhbGxvdywgY29lcmNpdmUgZXF1YWxpdHkgd2l0aFxuLy8gPT0uXG4vLyBhc3NlcnQuZXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQuZXF1YWwgPSBmdW5jdGlvbiBlcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChhY3R1YWwgIT0gZXhwZWN0ZWQpIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJz09JywgYXNzZXJ0LmVxdWFsKTtcbn07XG5cbi8vIDYuIFRoZSBub24tZXF1YWxpdHkgYXNzZXJ0aW9uIHRlc3RzIGZvciB3aGV0aGVyIHR3byBvYmplY3RzIGFyZSBub3QgZXF1YWxcbi8vIHdpdGggIT0gYXNzZXJ0Lm5vdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0Lm5vdEVxdWFsID0gZnVuY3Rpb24gbm90RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoYWN0dWFsID09IGV4cGVjdGVkKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnIT0nLCBhc3NlcnQubm90RXF1YWwpO1xuICB9XG59O1xuXG4vLyA3LiBUaGUgZXF1aXZhbGVuY2UgYXNzZXJ0aW9uIHRlc3RzIGEgZGVlcCBlcXVhbGl0eSByZWxhdGlvbi5cbi8vIGFzc2VydC5kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQuZGVlcEVxdWFsID0gZnVuY3Rpb24gZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKCFfZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIGZhbHNlKSkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJ2RlZXBFcXVhbCcsIGFzc2VydC5kZWVwRXF1YWwpO1xuICB9XG59O1xuXG5hc3NlcnQuZGVlcFN0cmljdEVxdWFsID0gZnVuY3Rpb24gZGVlcFN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKCFfZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIHRydWUpKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnZGVlcFN0cmljdEVxdWFsJywgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIF9kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgc3RyaWN0LCBtZW1vcykge1xuICAvLyA3LjEuIEFsbCBpZGVudGljYWwgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBhcyBkZXRlcm1pbmVkIGJ5ID09PS5cbiAgaWYgKGFjdHVhbCA9PT0gZXhwZWN0ZWQpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChpc0J1ZmZlcihhY3R1YWwpICYmIGlzQnVmZmVyKGV4cGVjdGVkKSkge1xuICAgIHJldHVybiBjb21wYXJlKGFjdHVhbCwgZXhwZWN0ZWQpID09PSAwO1xuXG4gIC8vIDcuMi4gSWYgdGhlIGV4cGVjdGVkIHZhbHVlIGlzIGEgRGF0ZSBvYmplY3QsIHRoZSBhY3R1YWwgdmFsdWUgaXNcbiAgLy8gZXF1aXZhbGVudCBpZiBpdCBpcyBhbHNvIGEgRGF0ZSBvYmplY3QgdGhhdCByZWZlcnMgdG8gdGhlIHNhbWUgdGltZS5cbiAgfSBlbHNlIGlmICh1dGlsLmlzRGF0ZShhY3R1YWwpICYmIHV0aWwuaXNEYXRlKGV4cGVjdGVkKSkge1xuICAgIHJldHVybiBhY3R1YWwuZ2V0VGltZSgpID09PSBleHBlY3RlZC5nZXRUaW1lKCk7XG5cbiAgLy8gNy4zIElmIHRoZSBleHBlY3RlZCB2YWx1ZSBpcyBhIFJlZ0V4cCBvYmplY3QsIHRoZSBhY3R1YWwgdmFsdWUgaXNcbiAgLy8gZXF1aXZhbGVudCBpZiBpdCBpcyBhbHNvIGEgUmVnRXhwIG9iamVjdCB3aXRoIHRoZSBzYW1lIHNvdXJjZSBhbmRcbiAgLy8gcHJvcGVydGllcyAoYGdsb2JhbGAsIGBtdWx0aWxpbmVgLCBgbGFzdEluZGV4YCwgYGlnbm9yZUNhc2VgKS5cbiAgfSBlbHNlIGlmICh1dGlsLmlzUmVnRXhwKGFjdHVhbCkgJiYgdXRpbC5pc1JlZ0V4cChleHBlY3RlZCkpIHtcbiAgICByZXR1cm4gYWN0dWFsLnNvdXJjZSA9PT0gZXhwZWN0ZWQuc291cmNlICYmXG4gICAgICAgICAgIGFjdHVhbC5nbG9iYWwgPT09IGV4cGVjdGVkLmdsb2JhbCAmJlxuICAgICAgICAgICBhY3R1YWwubXVsdGlsaW5lID09PSBleHBlY3RlZC5tdWx0aWxpbmUgJiZcbiAgICAgICAgICAgYWN0dWFsLmxhc3RJbmRleCA9PT0gZXhwZWN0ZWQubGFzdEluZGV4ICYmXG4gICAgICAgICAgIGFjdHVhbC5pZ25vcmVDYXNlID09PSBleHBlY3RlZC5pZ25vcmVDYXNlO1xuXG4gIC8vIDcuNC4gT3RoZXIgcGFpcnMgdGhhdCBkbyBub3QgYm90aCBwYXNzIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyxcbiAgLy8gZXF1aXZhbGVuY2UgaXMgZGV0ZXJtaW5lZCBieSA9PS5cbiAgfSBlbHNlIGlmICgoYWN0dWFsID09PSBudWxsIHx8IHR5cGVvZiBhY3R1YWwgIT09ICdvYmplY3QnKSAmJlxuICAgICAgICAgICAgIChleHBlY3RlZCA9PT0gbnVsbCB8fCB0eXBlb2YgZXhwZWN0ZWQgIT09ICdvYmplY3QnKSkge1xuICAgIHJldHVybiBzdHJpY3QgPyBhY3R1YWwgPT09IGV4cGVjdGVkIDogYWN0dWFsID09IGV4cGVjdGVkO1xuXG4gIC8vIElmIGJvdGggdmFsdWVzIGFyZSBpbnN0YW5jZXMgb2YgdHlwZWQgYXJyYXlzLCB3cmFwIHRoZWlyIHVuZGVybHlpbmdcbiAgLy8gQXJyYXlCdWZmZXJzIGluIGEgQnVmZmVyIGVhY2ggdG8gaW5jcmVhc2UgcGVyZm9ybWFuY2VcbiAgLy8gVGhpcyBvcHRpbWl6YXRpb24gcmVxdWlyZXMgdGhlIGFycmF5cyB0byBoYXZlIHRoZSBzYW1lIHR5cGUgYXMgY2hlY2tlZCBieVxuICAvLyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIChha2EgcFRvU3RyaW5nKS4gTmV2ZXIgcGVyZm9ybSBiaW5hcnlcbiAgLy8gY29tcGFyaXNvbnMgZm9yIEZsb2F0KkFycmF5cywgdGhvdWdoLCBzaW5jZSBlLmcuICswID09PSAtMCBidXQgdGhlaXJcbiAgLy8gYml0IHBhdHRlcm5zIGFyZSBub3QgaWRlbnRpY2FsLlxuICB9IGVsc2UgaWYgKGlzVmlldyhhY3R1YWwpICYmIGlzVmlldyhleHBlY3RlZCkgJiZcbiAgICAgICAgICAgICBwVG9TdHJpbmcoYWN0dWFsKSA9PT0gcFRvU3RyaW5nKGV4cGVjdGVkKSAmJlxuICAgICAgICAgICAgICEoYWN0dWFsIGluc3RhbmNlb2YgRmxvYXQzMkFycmF5IHx8XG4gICAgICAgICAgICAgICBhY3R1YWwgaW5zdGFuY2VvZiBGbG9hdDY0QXJyYXkpKSB7XG4gICAgcmV0dXJuIGNvbXBhcmUobmV3IFVpbnQ4QXJyYXkoYWN0dWFsLmJ1ZmZlciksXG4gICAgICAgICAgICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoZXhwZWN0ZWQuYnVmZmVyKSkgPT09IDA7XG5cbiAgLy8gNy41IEZvciBhbGwgb3RoZXIgT2JqZWN0IHBhaXJzLCBpbmNsdWRpbmcgQXJyYXkgb2JqZWN0cywgZXF1aXZhbGVuY2UgaXNcbiAgLy8gZGV0ZXJtaW5lZCBieSBoYXZpbmcgdGhlIHNhbWUgbnVtYmVyIG9mIG93bmVkIHByb3BlcnRpZXMgKGFzIHZlcmlmaWVkXG4gIC8vIHdpdGggT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKSwgdGhlIHNhbWUgc2V0IG9mIGtleXNcbiAgLy8gKGFsdGhvdWdoIG5vdCBuZWNlc3NhcmlseSB0aGUgc2FtZSBvcmRlciksIGVxdWl2YWxlbnQgdmFsdWVzIGZvciBldmVyeVxuICAvLyBjb3JyZXNwb25kaW5nIGtleSwgYW5kIGFuIGlkZW50aWNhbCAncHJvdG90eXBlJyBwcm9wZXJ0eS4gTm90ZTogdGhpc1xuICAvLyBhY2NvdW50cyBmb3IgYm90aCBuYW1lZCBhbmQgaW5kZXhlZCBwcm9wZXJ0aWVzIG9uIEFycmF5cy5cbiAgfSBlbHNlIGlmIChpc0J1ZmZlcihhY3R1YWwpICE9PSBpc0J1ZmZlcihleHBlY3RlZCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0gZWxzZSB7XG4gICAgbWVtb3MgPSBtZW1vcyB8fCB7YWN0dWFsOiBbXSwgZXhwZWN0ZWQ6IFtdfTtcblxuICAgIHZhciBhY3R1YWxJbmRleCA9IG1lbW9zLmFjdHVhbC5pbmRleE9mKGFjdHVhbCk7XG4gICAgaWYgKGFjdHVhbEluZGV4ICE9PSAtMSkge1xuICAgICAgaWYgKGFjdHVhbEluZGV4ID09PSBtZW1vcy5leHBlY3RlZC5pbmRleE9mKGV4cGVjdGVkKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBtZW1vcy5hY3R1YWwucHVzaChhY3R1YWwpO1xuICAgIG1lbW9zLmV4cGVjdGVkLnB1c2goZXhwZWN0ZWQpO1xuXG4gICAgcmV0dXJuIG9iakVxdWl2KGFjdHVhbCwgZXhwZWN0ZWQsIHN0cmljdCwgbWVtb3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzQXJndW1lbnRzKG9iamVjdCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT0gJ1tvYmplY3QgQXJndW1lbnRzXSc7XG59XG5cbmZ1bmN0aW9uIG9iakVxdWl2KGEsIGIsIHN0cmljdCwgYWN0dWFsVmlzaXRlZE9iamVjdHMpIHtcbiAgaWYgKGEgPT09IG51bGwgfHwgYSA9PT0gdW5kZWZpbmVkIHx8IGIgPT09IG51bGwgfHwgYiA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBmYWxzZTtcbiAgLy8gaWYgb25lIGlzIGEgcHJpbWl0aXZlLCB0aGUgb3RoZXIgbXVzdCBiZSBzYW1lXG4gIGlmICh1dGlsLmlzUHJpbWl0aXZlKGEpIHx8IHV0aWwuaXNQcmltaXRpdmUoYikpXG4gICAgcmV0dXJuIGEgPT09IGI7XG4gIGlmIChzdHJpY3QgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpICE9PSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoYikpXG4gICAgcmV0dXJuIGZhbHNlO1xuICB2YXIgYUlzQXJncyA9IGlzQXJndW1lbnRzKGEpO1xuICB2YXIgYklzQXJncyA9IGlzQXJndW1lbnRzKGIpO1xuICBpZiAoKGFJc0FyZ3MgJiYgIWJJc0FyZ3MpIHx8ICghYUlzQXJncyAmJiBiSXNBcmdzKSlcbiAgICByZXR1cm4gZmFsc2U7XG4gIGlmIChhSXNBcmdzKSB7XG4gICAgYSA9IHBTbGljZS5jYWxsKGEpO1xuICAgIGIgPSBwU2xpY2UuY2FsbChiKTtcbiAgICByZXR1cm4gX2RlZXBFcXVhbChhLCBiLCBzdHJpY3QpO1xuICB9XG4gIHZhciBrYSA9IG9iamVjdEtleXMoYSk7XG4gIHZhciBrYiA9IG9iamVjdEtleXMoYik7XG4gIHZhciBrZXksIGk7XG4gIC8vIGhhdmluZyB0aGUgc2FtZSBudW1iZXIgb2Ygb3duZWQgcHJvcGVydGllcyAoa2V5cyBpbmNvcnBvcmF0ZXNcbiAgLy8gaGFzT3duUHJvcGVydHkpXG4gIGlmIChrYS5sZW5ndGggIT09IGtiLmxlbmd0aClcbiAgICByZXR1cm4gZmFsc2U7XG4gIC8vdGhlIHNhbWUgc2V0IG9mIGtleXMgKGFsdGhvdWdoIG5vdCBuZWNlc3NhcmlseSB0aGUgc2FtZSBvcmRlciksXG4gIGthLnNvcnQoKTtcbiAga2Iuc29ydCgpO1xuICAvL35+fmNoZWFwIGtleSB0ZXN0XG4gIGZvciAoaSA9IGthLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKGthW2ldICE9PSBrYltpXSlcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvL2VxdWl2YWxlbnQgdmFsdWVzIGZvciBldmVyeSBjb3JyZXNwb25kaW5nIGtleSwgYW5kXG4gIC8vfn5+cG9zc2libHkgZXhwZW5zaXZlIGRlZXAgdGVzdFxuICBmb3IgKGkgPSBrYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGtleSA9IGthW2ldO1xuICAgIGlmICghX2RlZXBFcXVhbChhW2tleV0sIGJba2V5XSwgc3RyaWN0LCBhY3R1YWxWaXNpdGVkT2JqZWN0cykpXG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8vIDguIFRoZSBub24tZXF1aXZhbGVuY2UgYXNzZXJ0aW9uIHRlc3RzIGZvciBhbnkgZGVlcCBpbmVxdWFsaXR5LlxuLy8gYXNzZXJ0Lm5vdERlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5ub3REZWVwRXF1YWwgPSBmdW5jdGlvbiBub3REZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoX2RlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBmYWxzZSkpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICdub3REZWVwRXF1YWwnLCBhc3NlcnQubm90RGVlcEVxdWFsKTtcbiAgfVxufTtcblxuYXNzZXJ0Lm5vdERlZXBTdHJpY3RFcXVhbCA9IG5vdERlZXBTdHJpY3RFcXVhbDtcbmZ1bmN0aW9uIG5vdERlZXBTdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChfZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIHRydWUpKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnbm90RGVlcFN0cmljdEVxdWFsJywgbm90RGVlcFN0cmljdEVxdWFsKTtcbiAgfVxufVxuXG5cbi8vIDkuIFRoZSBzdHJpY3QgZXF1YWxpdHkgYXNzZXJ0aW9uIHRlc3RzIHN0cmljdCBlcXVhbGl0eSwgYXMgZGV0ZXJtaW5lZCBieSA9PT0uXG4vLyBhc3NlcnQuc3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQuc3RyaWN0RXF1YWwgPSBmdW5jdGlvbiBzdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChhY3R1YWwgIT09IGV4cGVjdGVkKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnPT09JywgYXNzZXJ0LnN0cmljdEVxdWFsKTtcbiAgfVxufTtcblxuLy8gMTAuIFRoZSBzdHJpY3Qgbm9uLWVxdWFsaXR5IGFzc2VydGlvbiB0ZXN0cyBmb3Igc3RyaWN0IGluZXF1YWxpdHksIGFzXG4vLyBkZXRlcm1pbmVkIGJ5ICE9PS4gIGFzc2VydC5ub3RTdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5ub3RTdHJpY3RFcXVhbCA9IGZ1bmN0aW9uIG5vdFN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKGFjdHVhbCA9PT0gZXhwZWN0ZWQpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICchPT0nLCBhc3NlcnQubm90U3RyaWN0RXF1YWwpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBleHBlY3RlZEV4Y2VwdGlvbihhY3R1YWwsIGV4cGVjdGVkKSB7XG4gIGlmICghYWN0dWFsIHx8ICFleHBlY3RlZCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZXhwZWN0ZWQpID09ICdbb2JqZWN0IFJlZ0V4cF0nKSB7XG4gICAgcmV0dXJuIGV4cGVjdGVkLnRlc3QoYWN0dWFsKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgaWYgKGFjdHVhbCBpbnN0YW5jZW9mIGV4cGVjdGVkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBJZ25vcmUuICBUaGUgaW5zdGFuY2VvZiBjaGVjayBkb2Vzbid0IHdvcmsgZm9yIGFycm93IGZ1bmN0aW9ucy5cbiAgfVxuXG4gIGlmIChFcnJvci5pc1Byb3RvdHlwZU9mKGV4cGVjdGVkKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBleHBlY3RlZC5jYWxsKHt9LCBhY3R1YWwpID09PSB0cnVlO1xufVxuXG5mdW5jdGlvbiBfdHJ5QmxvY2soYmxvY2spIHtcbiAgdmFyIGVycm9yO1xuICB0cnkge1xuICAgIGJsb2NrKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBlcnJvciA9IGU7XG4gIH1cbiAgcmV0dXJuIGVycm9yO1xufVxuXG5mdW5jdGlvbiBfdGhyb3dzKHNob3VsZFRocm93LCBibG9jaywgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgdmFyIGFjdHVhbDtcblxuICBpZiAodHlwZW9mIGJsb2NrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJibG9ja1wiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBleHBlY3RlZCA9PT0gJ3N0cmluZycpIHtcbiAgICBtZXNzYWdlID0gZXhwZWN0ZWQ7XG4gICAgZXhwZWN0ZWQgPSBudWxsO1xuICB9XG5cbiAgYWN0dWFsID0gX3RyeUJsb2NrKGJsb2NrKTtcblxuICBtZXNzYWdlID0gKGV4cGVjdGVkICYmIGV4cGVjdGVkLm5hbWUgPyAnICgnICsgZXhwZWN0ZWQubmFtZSArICcpLicgOiAnLicpICtcbiAgICAgICAgICAgIChtZXNzYWdlID8gJyAnICsgbWVzc2FnZSA6ICcuJyk7XG5cbiAgaWYgKHNob3VsZFRocm93ICYmICFhY3R1YWwpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsICdNaXNzaW5nIGV4cGVjdGVkIGV4Y2VwdGlvbicgKyBtZXNzYWdlKTtcbiAgfVxuXG4gIHZhciB1c2VyUHJvdmlkZWRNZXNzYWdlID0gdHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnO1xuICB2YXIgaXNVbndhbnRlZEV4Y2VwdGlvbiA9ICFzaG91bGRUaHJvdyAmJiB1dGlsLmlzRXJyb3IoYWN0dWFsKTtcbiAgdmFyIGlzVW5leHBlY3RlZEV4Y2VwdGlvbiA9ICFzaG91bGRUaHJvdyAmJiBhY3R1YWwgJiYgIWV4cGVjdGVkO1xuXG4gIGlmICgoaXNVbndhbnRlZEV4Y2VwdGlvbiAmJlxuICAgICAgdXNlclByb3ZpZGVkTWVzc2FnZSAmJlxuICAgICAgZXhwZWN0ZWRFeGNlcHRpb24oYWN0dWFsLCBleHBlY3RlZCkpIHx8XG4gICAgICBpc1VuZXhwZWN0ZWRFeGNlcHRpb24pIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsICdHb3QgdW53YW50ZWQgZXhjZXB0aW9uJyArIG1lc3NhZ2UpO1xuICB9XG5cbiAgaWYgKChzaG91bGRUaHJvdyAmJiBhY3R1YWwgJiYgZXhwZWN0ZWQgJiZcbiAgICAgICFleHBlY3RlZEV4Y2VwdGlvbihhY3R1YWwsIGV4cGVjdGVkKSkgfHwgKCFzaG91bGRUaHJvdyAmJiBhY3R1YWwpKSB7XG4gICAgdGhyb3cgYWN0dWFsO1xuICB9XG59XG5cbi8vIDExLiBFeHBlY3RlZCB0byB0aHJvdyBhbiBlcnJvcjpcbi8vIGFzc2VydC50aHJvd3MoYmxvY2ssIEVycm9yX29wdCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQudGhyb3dzID0gZnVuY3Rpb24oYmxvY2ssIC8qb3B0aW9uYWwqL2Vycm9yLCAvKm9wdGlvbmFsKi9tZXNzYWdlKSB7XG4gIF90aHJvd3ModHJ1ZSwgYmxvY2ssIGVycm9yLCBtZXNzYWdlKTtcbn07XG5cbi8vIEVYVEVOU0lPTiEgVGhpcyBpcyBhbm5veWluZyB0byB3cml0ZSBvdXRzaWRlIHRoaXMgbW9kdWxlLlxuYXNzZXJ0LmRvZXNOb3RUaHJvdyA9IGZ1bmN0aW9uKGJsb2NrLCAvKm9wdGlvbmFsKi9lcnJvciwgLypvcHRpb25hbCovbWVzc2FnZSkge1xuICBfdGhyb3dzKGZhbHNlLCBibG9jaywgZXJyb3IsIG1lc3NhZ2UpO1xufTtcblxuYXNzZXJ0LmlmRXJyb3IgPSBmdW5jdGlvbihlcnIpIHsgaWYgKGVycikgdGhyb3cgZXJyOyB9O1xuXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIGtleXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgIGlmIChoYXNPd24uY2FsbChvYmosIGtleSkpIGtleXMucHVzaChrZXkpO1xuICB9XG4gIHJldHVybiBrZXlzO1xufTtcbiIsImlmICh0eXBlb2YgT2JqZWN0LmNyZWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAvLyBpbXBsZW1lbnRhdGlvbiBmcm9tIHN0YW5kYXJkIG5vZGUuanMgJ3V0aWwnIG1vZHVsZVxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgY3Rvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ3Rvci5wcm90b3R5cGUsIHtcbiAgICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICAgIHZhbHVlOiBjdG9yLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xufSBlbHNlIHtcbiAgLy8gb2xkIHNjaG9vbCBzaGltIGZvciBvbGQgYnJvd3NlcnNcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIHZhciBUZW1wQ3RvciA9IGZ1bmN0aW9uICgpIHt9XG4gICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZVxuICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKClcbiAgICBjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IGN0b3JcbiAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gX2F0b2Ioc3RyKSB7XG4gIHJldHVybiBhdG9iKHN0cilcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJhcnljZW50cmljXG5cbnZhciBzb2x2ZSA9IHJlcXVpcmUoJ3JvYnVzdC1saW5lYXItc29sdmUnKVxuXG5mdW5jdGlvbiByZWR1Y2UoeCkge1xuICB2YXIgciA9IDBcbiAgZm9yKHZhciBpPTA7IGk8eC5sZW5ndGg7ICsraSkge1xuICAgIHIgKz0geFtpXVxuICB9XG4gIHJldHVybiByXG59XG5cbmZ1bmN0aW9uIGJhcnljZW50cmljKHNpbXBsZXgsIHBvaW50KSB7XG4gIHZhciBkID0gcG9pbnQubGVuZ3RoXG4gIHZhciBBID0gbmV3IEFycmF5KGQrMSlcbiAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgdmFyIHJvdyA9IG5ldyBBcnJheShkKzEpXG4gICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgcm93W2pdID0gc2ltcGxleFtqXVtpXVxuICAgIH1cbiAgICBBW2ldID0gcm93XG4gIH1cbiAgQVtkXSA9IG5ldyBBcnJheShkKzEpXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICBBW2RdW2ldID0gMVxuICB9XG5cbiAgdmFyIGIgPSBuZXcgQXJyYXkoZCsxKVxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICBiW2ldID0gcG9pbnRbaV1cbiAgfVxuICBiW2RdID0gMS4wXG5cbiAgdmFyIHggPSBzb2x2ZShBLCBiKVxuICB2YXIgdyA9IHJlZHVjZSh4W2QrMV0pXG4gIFxuICBpZih3ID09PSAwKSB7XG4gICAgdyA9IDEuMFxuICB9XG4gIHZhciB5ID0gbmV3IEFycmF5KGQrMSlcbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIHlbaV0gPSByZWR1Y2UoeFtpXSkgLyB3XG4gIH1cbiAgcmV0dXJuIHlcbn0iLCIndXNlIHN0cmljdCdcblxuZXhwb3J0cy5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuZXhwb3J0cy50b0J5dGVBcnJheSA9IHRvQnl0ZUFycmF5XG5leHBvcnRzLmZyb21CeXRlQXJyYXkgPSBmcm9tQnl0ZUFycmF5XG5cbnZhciBsb29rdXAgPSBbXVxudmFyIHJldkxvb2t1cCA9IFtdXG52YXIgQXJyID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnID8gVWludDhBcnJheSA6IEFycmF5XG5cbnZhciBjb2RlID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nXG5mb3IgKHZhciBpID0gMCwgbGVuID0gY29kZS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICBsb29rdXBbaV0gPSBjb2RlW2ldXG4gIHJldkxvb2t1cFtjb2RlLmNoYXJDb2RlQXQoaSldID0gaVxufVxuXG4vLyBTdXBwb3J0IGRlY29kaW5nIFVSTC1zYWZlIGJhc2U2NCBzdHJpbmdzLCBhcyBOb2RlLmpzIGRvZXMuXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXG5yZXZMb29rdXBbJy0nLmNoYXJDb2RlQXQoMCldID0gNjJcbnJldkxvb2t1cFsnXycuY2hhckNvZGVBdCgwKV0gPSA2M1xuXG5mdW5jdGlvbiBnZXRMZW5zIChiNjQpIHtcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcblxuICBpZiAobGVuICUgNCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuICB9XG5cbiAgLy8gVHJpbSBvZmYgZXh0cmEgYnl0ZXMgYWZ0ZXIgcGxhY2Vob2xkZXIgYnl0ZXMgYXJlIGZvdW5kXG4gIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzL2lzc3Vlcy80MlxuICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZignPScpXG4gIGlmICh2YWxpZExlbiA9PT0gLTEpIHZhbGlkTGVuID0gbGVuXG5cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cbiAgICA/IDBcbiAgICA6IDQgLSAodmFsaWRMZW4gJSA0KVxuXG4gIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl1cbn1cblxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChiNjQpIHtcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gX2J5dGVMZW5ndGggKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikge1xuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gdG9CeXRlQXJyYXkgKGI2NCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW5zID0gZ2V0TGVucyhiNjQpXG4gIHZhciB2YWxpZExlbiA9IGxlbnNbMF1cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV1cblxuICB2YXIgYXJyID0gbmV3IEFycihfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pKVxuXG4gIHZhciBjdXJCeXRlID0gMFxuXG4gIC8vIGlmIHRoZXJlIGFyZSBwbGFjZWhvbGRlcnMsIG9ubHkgZ2V0IHVwIHRvIHRoZSBsYXN0IGNvbXBsZXRlIDQgY2hhcnNcbiAgdmFyIGxlbiA9IHBsYWNlSG9sZGVyc0xlbiA+IDBcbiAgICA/IHZhbGlkTGVuIC0gNFxuICAgIDogdmFsaWRMZW5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA0KSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDE4KSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgMTIpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA8PCA2KSB8XG4gICAgICByZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDMpXVxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiAxNikgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgaWYgKHBsYWNlSG9sZGVyc0xlbiA9PT0gMikge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAyKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPj4gNClcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDEpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTApIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCA0KSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPj4gMilcbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICByZXR1cm4gYXJyXG59XG5cbmZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG4gIHJldHVybiBsb29rdXBbbnVtID4+IDE4ICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gPj4gMTIgJiAweDNGXSArXG4gICAgbG9va3VwW251bSA+PiA2ICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gJiAweDNGXVxufVxuXG5mdW5jdGlvbiBlbmNvZGVDaHVuayAodWludDgsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHRtcFxuICB2YXIgb3V0cHV0ID0gW11cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpICs9IDMpIHtcbiAgICB0bXAgPVxuICAgICAgKCh1aW50OFtpXSA8PCAxNikgJiAweEZGMDAwMCkgK1xuICAgICAgKCh1aW50OFtpICsgMV0gPDwgOCkgJiAweEZGMDApICtcbiAgICAgICh1aW50OFtpICsgMl0gJiAweEZGKVxuICAgIG91dHB1dC5wdXNoKHRyaXBsZXRUb0Jhc2U2NCh0bXApKVxuICB9XG4gIHJldHVybiBvdXRwdXQuam9pbignJylcbn1cblxuZnVuY3Rpb24gZnJvbUJ5dGVBcnJheSAodWludDgpIHtcbiAgdmFyIHRtcFxuICB2YXIgbGVuID0gdWludDgubGVuZ3RoXG4gIHZhciBleHRyYUJ5dGVzID0gbGVuICUgMyAvLyBpZiB3ZSBoYXZlIDEgYnl0ZSBsZWZ0LCBwYWQgMiBieXRlc1xuICB2YXIgcGFydHMgPSBbXVxuICB2YXIgbWF4Q2h1bmtMZW5ndGggPSAxNjM4MyAvLyBtdXN0IGJlIG11bHRpcGxlIG9mIDNcblxuICAvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG4gIGZvciAodmFyIGkgPSAwLCBsZW4yID0gbGVuIC0gZXh0cmFCeXRlczsgaSA8IGxlbjI7IGkgKz0gbWF4Q2h1bmtMZW5ndGgpIHtcbiAgICBwYXJ0cy5wdXNoKGVuY29kZUNodW5rKFxuICAgICAgdWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKVxuICAgICkpXG4gIH1cblxuICAvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG4gIGlmIChleHRyYUJ5dGVzID09PSAxKSB7XG4gICAgdG1wID0gdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAyXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcbiAgICAgICc9PSdcbiAgICApXG4gIH0gZWxzZSBpZiAoZXh0cmFCeXRlcyA9PT0gMikge1xuICAgIHRtcCA9ICh1aW50OFtsZW4gLSAyXSA8PCA4KSArIHVpbnQ4W2xlbiAtIDFdXG4gICAgcGFydHMucHVzaChcbiAgICAgIGxvb2t1cFt0bXAgPj4gMTBdICtcbiAgICAgIGxvb2t1cFsodG1wID4+IDQpICYgMHgzRl0gK1xuICAgICAgbG9va3VwWyh0bXAgPDwgMikgJiAweDNGXSArXG4gICAgICAnPSdcbiAgICApXG4gIH1cblxuICByZXR1cm4gcGFydHMuam9pbignJylcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgcmF0aW9uYWxpemUgPSByZXF1aXJlKCcuL2xpYi9yYXRpb25hbGl6ZScpXG5cbm1vZHVsZS5leHBvcnRzID0gYWRkXG5cbmZ1bmN0aW9uIGFkZChhLCBiKSB7XG4gIHJldHVybiByYXRpb25hbGl6ZShcbiAgICBhWzBdLm11bChiWzFdKS5hZGQoYlswXS5tdWwoYVsxXSkpLFxuICAgIGFbMV0ubXVsKGJbMV0pKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY21wXG5cbmZ1bmN0aW9uIGNtcChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0ubXVsKGJbMV0pLmNtcChiWzBdLm11bChhWzFdKSlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgcmF0aW9uYWxpemUgPSByZXF1aXJlKCcuL2xpYi9yYXRpb25hbGl6ZScpXG5cbm1vZHVsZS5leHBvcnRzID0gZGl2XG5cbmZ1bmN0aW9uIGRpdihhLCBiKSB7XG4gIHJldHVybiByYXRpb25hbGl6ZShhWzBdLm11bChiWzFdKSwgYVsxXS5tdWwoYlswXSkpXG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIGlzUmF0ID0gcmVxdWlyZSgnLi9pcy1yYXQnKVxudmFyIGlzQk4gPSByZXF1aXJlKCcuL2xpYi9pcy1ibicpXG52YXIgbnVtMmJuID0gcmVxdWlyZSgnLi9saWIvbnVtLXRvLWJuJylcbnZhciBzdHIyYm4gPSByZXF1aXJlKCcuL2xpYi9zdHItdG8tYm4nKVxudmFyIHJhdGlvbmFsaXplID0gcmVxdWlyZSgnLi9saWIvcmF0aW9uYWxpemUnKVxudmFyIGRpdiA9IHJlcXVpcmUoJy4vZGl2JylcblxubW9kdWxlLmV4cG9ydHMgPSBtYWtlUmF0aW9uYWxcblxuZnVuY3Rpb24gbWFrZVJhdGlvbmFsKG51bWVyLCBkZW5vbSkge1xuICBpZihpc1JhdChudW1lcikpIHtcbiAgICBpZihkZW5vbSkge1xuICAgICAgcmV0dXJuIGRpdihudW1lciwgbWFrZVJhdGlvbmFsKGRlbm9tKSlcbiAgICB9XG4gICAgcmV0dXJuIFtudW1lclswXS5jbG9uZSgpLCBudW1lclsxXS5jbG9uZSgpXVxuICB9XG4gIHZhciBzaGlmdCA9IDBcbiAgdmFyIGEsIGJcbiAgaWYoaXNCTihudW1lcikpIHtcbiAgICBhID0gbnVtZXIuY2xvbmUoKVxuICB9IGVsc2UgaWYodHlwZW9mIG51bWVyID09PSAnc3RyaW5nJykge1xuICAgIGEgPSBzdHIyYm4obnVtZXIpXG4gIH0gZWxzZSBpZihudW1lciA9PT0gMCkge1xuICAgIHJldHVybiBbbnVtMmJuKDApLCBudW0yYm4oMSldXG4gIH0gZWxzZSBpZihudW1lciA9PT0gTWF0aC5mbG9vcihudW1lcikpIHtcbiAgICBhID0gbnVtMmJuKG51bWVyKVxuICB9IGVsc2Uge1xuICAgIHdoaWxlKG51bWVyICE9PSBNYXRoLmZsb29yKG51bWVyKSkge1xuICAgICAgbnVtZXIgPSBudW1lciAqIE1hdGgucG93KDIsIDI1NilcbiAgICAgIHNoaWZ0IC09IDI1NlxuICAgIH1cbiAgICBhID0gbnVtMmJuKG51bWVyKVxuICB9XG4gIGlmKGlzUmF0KGRlbm9tKSkge1xuICAgIGEubXVsKGRlbm9tWzFdKVxuICAgIGIgPSBkZW5vbVswXS5jbG9uZSgpXG4gIH0gZWxzZSBpZihpc0JOKGRlbm9tKSkge1xuICAgIGIgPSBkZW5vbS5jbG9uZSgpXG4gIH0gZWxzZSBpZih0eXBlb2YgZGVub20gPT09ICdzdHJpbmcnKSB7XG4gICAgYiA9IHN0cjJibihkZW5vbSlcbiAgfSBlbHNlIGlmKCFkZW5vbSkge1xuICAgIGIgPSBudW0yYm4oMSlcbiAgfSBlbHNlIGlmKGRlbm9tID09PSBNYXRoLmZsb29yKGRlbm9tKSkge1xuICAgIGIgPSBudW0yYm4oZGVub20pXG4gIH0gZWxzZSB7XG4gICAgd2hpbGUoZGVub20gIT09IE1hdGguZmxvb3IoZGVub20pKSB7XG4gICAgICBkZW5vbSA9IGRlbm9tICogTWF0aC5wb3coMiwgMjU2KVxuICAgICAgc2hpZnQgKz0gMjU2XG4gICAgfVxuICAgIGIgPSBudW0yYm4oZGVub20pXG4gIH1cbiAgaWYoc2hpZnQgPiAwKSB7XG4gICAgYSA9IGEudXNobG4oc2hpZnQpXG4gIH0gZWxzZSBpZihzaGlmdCA8IDApIHtcbiAgICBiID0gYi51c2hsbigtc2hpZnQpXG4gIH1cbiAgcmV0dXJuIHJhdGlvbmFsaXplKGEsIGIpXG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIGlzQk4gPSByZXF1aXJlKCcuL2xpYi9pcy1ibicpXG5cbm1vZHVsZS5leHBvcnRzID0gaXNSYXRcblxuZnVuY3Rpb24gaXNSYXQoeCkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh4KSAmJiB4Lmxlbmd0aCA9PT0gMiAmJiBpc0JOKHhbMF0pICYmIGlzQk4oeFsxXSlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgQk4gPSByZXF1aXJlKCdibi5qcycpXG5cbm1vZHVsZS5leHBvcnRzID0gc2lnblxuXG5mdW5jdGlvbiBzaWduICh4KSB7XG4gIHJldHVybiB4LmNtcChuZXcgQk4oMCkpXG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIHNpZ24gPSByZXF1aXJlKCcuL2JuLXNpZ24nKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJuMm51bVxuXG4vL1RPRE86IE1ha2UgdGhpcyBiZXR0ZXJcbmZ1bmN0aW9uIGJuMm51bShiKSB7XG4gIHZhciBsID0gYi5sZW5ndGhcbiAgdmFyIHdvcmRzID0gYi53b3Jkc1xuICB2YXIgb3V0ID0gMFxuICBpZiAobCA9PT0gMSkge1xuICAgIG91dCA9IHdvcmRzWzBdXG4gIH0gZWxzZSBpZiAobCA9PT0gMikge1xuICAgIG91dCA9IHdvcmRzWzBdICsgKHdvcmRzWzFdICogMHg0MDAwMDAwKVxuICB9IGVsc2Uge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICB2YXIgdyA9IHdvcmRzW2ldXG4gICAgICBvdXQgKz0gdyAqIE1hdGgucG93KDB4NDAwMDAwMCwgaSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHNpZ24oYikgKiBvdXRcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgZGIgPSByZXF1aXJlKCdkb3VibGUtYml0cycpXG52YXIgY3R6ID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKS5jb3VudFRyYWlsaW5nWmVyb3NcblxubW9kdWxlLmV4cG9ydHMgPSBjdHpOdW1iZXJcblxuLy9Db3VudHMgdGhlIG51bWJlciBvZiB0cmFpbGluZyB6ZXJvc1xuZnVuY3Rpb24gY3R6TnVtYmVyKHgpIHtcbiAgdmFyIGwgPSBjdHooZGIubG8oeCkpXG4gIGlmKGwgPCAzMikge1xuICAgIHJldHVybiBsXG4gIH1cbiAgdmFyIGggPSBjdHooZGIuaGkoeCkpXG4gIGlmKGggPiAyMCkge1xuICAgIHJldHVybiA1MlxuICB9XG4gIHJldHVybiBoICsgMzJcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgQk4gPSByZXF1aXJlKCdibi5qcycpXG5cbm1vZHVsZS5leHBvcnRzID0gaXNCTlxuXG4vL1Rlc3QgaWYgeCBpcyBhIGJpZ251bWJlclxuLy9GSVhNRTogb2J2aW91c2x5IHRoaXMgaXMgdGhlIHdyb25nIHdheSB0byBkbyBpdFxuZnVuY3Rpb24gaXNCTih4KSB7XG4gIHJldHVybiB4ICYmIHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiBCb29sZWFuKHgud29yZHMpXG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIEJOID0gcmVxdWlyZSgnYm4uanMnKVxudmFyIGRiID0gcmVxdWlyZSgnZG91YmxlLWJpdHMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG51bTJiblxuXG5mdW5jdGlvbiBudW0yYm4oeCkge1xuICB2YXIgZSA9IGRiLmV4cG9uZW50KHgpXG4gIGlmKGUgPCA1Mikge1xuICAgIHJldHVybiBuZXcgQk4oeClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gKG5ldyBCTih4ICogTWF0aC5wb3coMiwgNTItZSkpKS51c2hsbihlLTUyKVxuICB9XG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIG51bTJibiA9IHJlcXVpcmUoJy4vbnVtLXRvLWJuJylcbnZhciBzaWduID0gcmVxdWlyZSgnLi9ibi1zaWduJylcblxubW9kdWxlLmV4cG9ydHMgPSByYXRpb25hbGl6ZVxuXG5mdW5jdGlvbiByYXRpb25hbGl6ZShudW1lciwgZGVub20pIHtcbiAgdmFyIHNudW1lciA9IHNpZ24obnVtZXIpXG4gIHZhciBzZGVub20gPSBzaWduKGRlbm9tKVxuICBpZihzbnVtZXIgPT09IDApIHtcbiAgICByZXR1cm4gW251bTJibigwKSwgbnVtMmJuKDEpXVxuICB9XG4gIGlmKHNkZW5vbSA9PT0gMCkge1xuICAgIHJldHVybiBbbnVtMmJuKDApLCBudW0yYm4oMCldXG4gIH1cbiAgaWYoc2Rlbm9tIDwgMCkge1xuICAgIG51bWVyID0gbnVtZXIubmVnKClcbiAgICBkZW5vbSA9IGRlbm9tLm5lZygpXG4gIH1cbiAgdmFyIGQgPSBudW1lci5nY2QoZGVub20pXG4gIGlmKGQuY21wbigxKSkge1xuICAgIHJldHVybiBbIG51bWVyLmRpdihkKSwgZGVub20uZGl2KGQpIF1cbiAgfVxuICByZXR1cm4gWyBudW1lciwgZGVub20gXVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBCTiA9IHJlcXVpcmUoJ2JuLmpzJylcblxubW9kdWxlLmV4cG9ydHMgPSBzdHIyQk5cblxuZnVuY3Rpb24gc3RyMkJOKHgpIHtcbiAgcmV0dXJuIG5ldyBCTih4KVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciByYXRpb25hbGl6ZSA9IHJlcXVpcmUoJy4vbGliL3JhdGlvbmFsaXplJylcblxubW9kdWxlLmV4cG9ydHMgPSBtdWxcblxuZnVuY3Rpb24gbXVsKGEsIGIpIHtcbiAgcmV0dXJuIHJhdGlvbmFsaXplKGFbMF0ubXVsKGJbMF0pLCBhWzFdLm11bChiWzFdKSlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgYm5zaWduID0gcmVxdWlyZSgnLi9saWIvYm4tc2lnbicpXG5cbm1vZHVsZS5leHBvcnRzID0gc2lnblxuXG5mdW5jdGlvbiBzaWduKHgpIHtcbiAgcmV0dXJuIGJuc2lnbih4WzBdKSAqIGJuc2lnbih4WzFdKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciByYXRpb25hbGl6ZSA9IHJlcXVpcmUoJy4vbGliL3JhdGlvbmFsaXplJylcblxubW9kdWxlLmV4cG9ydHMgPSBzdWJcblxuZnVuY3Rpb24gc3ViKGEsIGIpIHtcbiAgcmV0dXJuIHJhdGlvbmFsaXplKGFbMF0ubXVsKGJbMV0pLnN1YihhWzFdLm11bChiWzBdKSksIGFbMV0ubXVsKGJbMV0pKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBibjJudW0gPSByZXF1aXJlKCcuL2xpYi9ibi10by1udW0nKVxudmFyIGN0eiA9IHJlcXVpcmUoJy4vbGliL2N0eicpXG5cbm1vZHVsZS5leHBvcnRzID0gcm91bmRSYXRcblxuLy8gUm91bmQgYSByYXRpb25hbCB0byB0aGUgY2xvc2VzdCBmbG9hdFxuZnVuY3Rpb24gcm91bmRSYXQgKGYpIHtcbiAgdmFyIGEgPSBmWzBdXG4gIHZhciBiID0gZlsxXVxuICBpZiAoYS5jbXBuKDApID09PSAwKSB7XG4gICAgcmV0dXJuIDBcbiAgfVxuICB2YXIgaCA9IGEuYWJzKCkuZGl2bW9kKGIuYWJzKCkpXG4gIHZhciBpdiA9IGguZGl2XG4gIHZhciB4ID0gYm4ybnVtKGl2KVxuICB2YXIgaXIgPSBoLm1vZFxuICB2YXIgc2duID0gKGEubmVnYXRpdmUgIT09IGIubmVnYXRpdmUpID8gLTEgOiAxXG4gIGlmIChpci5jbXBuKDApID09PSAwKSB7XG4gICAgcmV0dXJuIHNnbiAqIHhcbiAgfVxuICBpZiAoeCkge1xuICAgIHZhciBzID0gY3R6KHgpICsgNFxuICAgIHZhciB5ID0gYm4ybnVtKGlyLnVzaGxuKHMpLmRpdlJvdW5kKGIpKVxuICAgIHJldHVybiBzZ24gKiAoeCArIHkgKiBNYXRoLnBvdygyLCAtcykpXG4gIH0gZWxzZSB7XG4gICAgdmFyIHliaXRzID0gYi5iaXRMZW5ndGgoKSAtIGlyLmJpdExlbmd0aCgpICsgNTNcbiAgICB2YXIgeSA9IGJuMm51bShpci51c2hsbih5Yml0cykuZGl2Um91bmQoYikpXG4gICAgaWYgKHliaXRzIDwgMTAyMykge1xuICAgICAgcmV0dXJuIHNnbiAqIHkgKiBNYXRoLnBvdygyLCAteWJpdHMpXG4gICAgfVxuICAgIHkgKj0gTWF0aC5wb3coMiwgLTEwMjMpXG4gICAgcmV0dXJuIHNnbiAqIHkgKiBNYXRoLnBvdygyLCAxMDIzIC0geWJpdHMpXG4gIH1cbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGNvbXBpbGVTZWFyY2goZnVuY05hbWUsIHByZWRpY2F0ZSwgcmV2ZXJzZWQsIGV4dHJhQXJncywgdXNlTmRhcnJheSwgZWFybHlPdXQpIHtcbiAgdmFyIGNvZGUgPSBbXG4gICAgXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKGEsbCxoLFwiLCBleHRyYUFyZ3Muam9pbihcIixcIiksICBcIil7XCIsXG5lYXJseU91dCA/IFwiXCIgOiBcInZhciBpPVwiLCAocmV2ZXJzZWQgPyBcImwtMVwiIDogXCJoKzFcIiksXG5cIjt3aGlsZShsPD1oKXtcXFxudmFyIG09KGwraCk+Pj4xLHg9YVwiLCB1c2VOZGFycmF5ID8gXCIuZ2V0KG0pXCIgOiBcIlttXVwiXVxuICBpZihlYXJseU91dCkge1xuICAgIGlmKHByZWRpY2F0ZS5pbmRleE9mKFwiY1wiKSA8IDApIHtcbiAgICAgIGNvZGUucHVzaChcIjtpZih4PT09eSl7cmV0dXJuIG19ZWxzZSBpZih4PD15KXtcIilcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKFwiO3ZhciBwPWMoeCx5KTtpZihwPT09MCl7cmV0dXJuIG19ZWxzZSBpZihwPD0wKXtcIilcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwiO2lmKFwiLCBwcmVkaWNhdGUsIFwiKXtpPW07XCIpXG4gIH1cbiAgaWYocmV2ZXJzZWQpIHtcbiAgICBjb2RlLnB1c2goXCJsPW0rMX1lbHNle2g9bS0xfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcImg9bS0xfWVsc2V7bD1tKzF9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifVwiKVxuICBpZihlYXJseU91dCkge1xuICAgIGNvZGUucHVzaChcInJldHVybiAtMX07XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIGl9O1wiKVxuICB9XG4gIHJldHVybiBjb2RlLmpvaW4oXCJcIilcbn1cblxuZnVuY3Rpb24gY29tcGlsZUJvdW5kc1NlYXJjaChwcmVkaWNhdGUsIHJldmVyc2VkLCBzdWZmaXgsIGVhcmx5T3V0KSB7XG4gIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oW1xuICBjb21waWxlU2VhcmNoKFwiQVwiLCBcInhcIiArIHByZWRpY2F0ZSArIFwieVwiLCByZXZlcnNlZCwgW1wieVwiXSwgZmFsc2UsIGVhcmx5T3V0KSxcbiAgY29tcGlsZVNlYXJjaChcIkJcIiwgXCJ4XCIgKyBwcmVkaWNhdGUgKyBcInlcIiwgcmV2ZXJzZWQsIFtcInlcIl0sIHRydWUsIGVhcmx5T3V0KSxcbiAgY29tcGlsZVNlYXJjaChcIlBcIiwgXCJjKHgseSlcIiArIHByZWRpY2F0ZSArIFwiMFwiLCByZXZlcnNlZCwgW1wieVwiLCBcImNcIl0sIGZhbHNlLCBlYXJseU91dCksXG4gIGNvbXBpbGVTZWFyY2goXCJRXCIsIFwiYyh4LHkpXCIgKyBwcmVkaWNhdGUgKyBcIjBcIiwgcmV2ZXJzZWQsIFtcInlcIiwgXCJjXCJdLCB0cnVlLCBlYXJseU91dCksXG5cImZ1bmN0aW9uIGRpc3BhdGNoQnNlYXJjaFwiLCBzdWZmaXgsIFwiKGEseSxjLGwsaCl7XFxcbmlmKGEuc2hhcGUpe1xcXG5pZih0eXBlb2YoYyk9PT0nZnVuY3Rpb24nKXtcXFxucmV0dXJuIFEoYSwobD09PXVuZGVmaW5lZCk/MDpsfDAsKGg9PT11bmRlZmluZWQpP2Euc2hhcGVbMF0tMTpofDAseSxjKVxcXG59ZWxzZXtcXFxucmV0dXJuIEIoYSwoYz09PXVuZGVmaW5lZCk/MDpjfDAsKGw9PT11bmRlZmluZWQpP2Euc2hhcGVbMF0tMTpsfDAseSlcXFxufX1lbHNle1xcXG5pZih0eXBlb2YoYyk9PT0nZnVuY3Rpb24nKXtcXFxucmV0dXJuIFAoYSwobD09PXVuZGVmaW5lZCk/MDpsfDAsKGg9PT11bmRlZmluZWQpP2EubGVuZ3RoLTE6aHwwLHksYylcXFxufWVsc2V7XFxcbnJldHVybiBBKGEsKGM9PT11bmRlZmluZWQpPzA6Y3wwLChsPT09dW5kZWZpbmVkKT9hLmxlbmd0aC0xOmx8MCx5KVxcXG59fX1cXFxucmV0dXJuIGRpc3BhdGNoQnNlYXJjaFwiLCBzdWZmaXhdLmpvaW4oXCJcIikpXG4gIHJldHVybiByZXN1bHQoKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2U6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+PVwiLCBmYWxzZSwgXCJHRVwiKSxcbiAgZ3Q6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+XCIsIGZhbHNlLCBcIkdUXCIpLFxuICBsdDogY29tcGlsZUJvdW5kc1NlYXJjaChcIjxcIiwgdHJ1ZSwgXCJMVFwiKSxcbiAgbGU6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI8PVwiLCB0cnVlLCBcIkxFXCIpLFxuICBlcTogY29tcGlsZUJvdW5kc1NlYXJjaChcIi1cIiwgdHJ1ZSwgXCJFUVwiLCB0cnVlKVxufVxuIiwiLyoqXG4gKiBCaXQgdHdpZGRsaW5nIGhhY2tzIGZvciBKYXZhU2NyaXB0LlxuICpcbiAqIEF1dGhvcjogTWlrb2xhIEx5c2Vua29cbiAqXG4gKiBQb3J0ZWQgZnJvbSBTdGFuZm9yZCBiaXQgdHdpZGRsaW5nIGhhY2sgbGlicmFyeTpcbiAqICAgIGh0dHA6Ly9ncmFwaGljcy5zdGFuZm9yZC5lZHUvfnNlYW5kZXIvYml0aGFja3MuaHRtbFxuICovXG5cblwidXNlIHN0cmljdFwiOyBcInVzZSByZXN0cmljdFwiO1xuXG4vL051bWJlciBvZiBiaXRzIGluIGFuIGludGVnZXJcbnZhciBJTlRfQklUUyA9IDMyO1xuXG4vL0NvbnN0YW50c1xuZXhwb3J0cy5JTlRfQklUUyAgPSBJTlRfQklUUztcbmV4cG9ydHMuSU5UX01BWCAgID0gIDB4N2ZmZmZmZmY7XG5leHBvcnRzLklOVF9NSU4gICA9IC0xPDwoSU5UX0JJVFMtMSk7XG5cbi8vUmV0dXJucyAtMSwgMCwgKzEgZGVwZW5kaW5nIG9uIHNpZ24gb2YgeFxuZXhwb3J0cy5zaWduID0gZnVuY3Rpb24odikge1xuICByZXR1cm4gKHYgPiAwKSAtICh2IDwgMCk7XG59XG5cbi8vQ29tcHV0ZXMgYWJzb2x1dGUgdmFsdWUgb2YgaW50ZWdlclxuZXhwb3J0cy5hYnMgPSBmdW5jdGlvbih2KSB7XG4gIHZhciBtYXNrID0gdiA+PiAoSU5UX0JJVFMtMSk7XG4gIHJldHVybiAodiBeIG1hc2spIC0gbWFzaztcbn1cblxuLy9Db21wdXRlcyBtaW5pbXVtIG9mIGludGVnZXJzIHggYW5kIHlcbmV4cG9ydHMubWluID0gZnVuY3Rpb24oeCwgeSkge1xuICByZXR1cm4geSBeICgoeCBeIHkpICYgLSh4IDwgeSkpO1xufVxuXG4vL0NvbXB1dGVzIG1heGltdW0gb2YgaW50ZWdlcnMgeCBhbmQgeVxuZXhwb3J0cy5tYXggPSBmdW5jdGlvbih4LCB5KSB7XG4gIHJldHVybiB4IF4gKCh4IF4geSkgJiAtKHggPCB5KSk7XG59XG5cbi8vQ2hlY2tzIGlmIGEgbnVtYmVyIGlzIGEgcG93ZXIgb2YgdHdvXG5leHBvcnRzLmlzUG93MiA9IGZ1bmN0aW9uKHYpIHtcbiAgcmV0dXJuICEodiAmICh2LTEpKSAmJiAoISF2KTtcbn1cblxuLy9Db21wdXRlcyBsb2cgYmFzZSAyIG9mIHZcbmV4cG9ydHMubG9nMiA9IGZ1bmN0aW9uKHYpIHtcbiAgdmFyIHIsIHNoaWZ0O1xuICByID0gICAgICh2ID4gMHhGRkZGKSA8PCA0OyB2ID4+Pj0gcjtcbiAgc2hpZnQgPSAodiA+IDB4RkYgICkgPDwgMzsgdiA+Pj49IHNoaWZ0OyByIHw9IHNoaWZ0O1xuICBzaGlmdCA9ICh2ID4gMHhGICAgKSA8PCAyOyB2ID4+Pj0gc2hpZnQ7IHIgfD0gc2hpZnQ7XG4gIHNoaWZ0ID0gKHYgPiAweDMgICApIDw8IDE7IHYgPj4+PSBzaGlmdDsgciB8PSBzaGlmdDtcbiAgcmV0dXJuIHIgfCAodiA+PiAxKTtcbn1cblxuLy9Db21wdXRlcyBsb2cgYmFzZSAxMCBvZiB2XG5leHBvcnRzLmxvZzEwID0gZnVuY3Rpb24odikge1xuICByZXR1cm4gICh2ID49IDEwMDAwMDAwMDApID8gOSA6ICh2ID49IDEwMDAwMDAwMCkgPyA4IDogKHYgPj0gMTAwMDAwMDApID8gNyA6XG4gICAgICAgICAgKHYgPj0gMTAwMDAwMCkgPyA2IDogKHYgPj0gMTAwMDAwKSA/IDUgOiAodiA+PSAxMDAwMCkgPyA0IDpcbiAgICAgICAgICAodiA+PSAxMDAwKSA/IDMgOiAodiA+PSAxMDApID8gMiA6ICh2ID49IDEwKSA/IDEgOiAwO1xufVxuXG4vL0NvdW50cyBudW1iZXIgb2YgYml0c1xuZXhwb3J0cy5wb3BDb3VudCA9IGZ1bmN0aW9uKHYpIHtcbiAgdiA9IHYgLSAoKHYgPj4+IDEpICYgMHg1NTU1NTU1NSk7XG4gIHYgPSAodiAmIDB4MzMzMzMzMzMpICsgKCh2ID4+PiAyKSAmIDB4MzMzMzMzMzMpO1xuICByZXR1cm4gKCh2ICsgKHYgPj4+IDQpICYgMHhGMEYwRjBGKSAqIDB4MTAxMDEwMSkgPj4+IDI0O1xufVxuXG4vL0NvdW50cyBudW1iZXIgb2YgdHJhaWxpbmcgemVyb3NcbmZ1bmN0aW9uIGNvdW50VHJhaWxpbmdaZXJvcyh2KSB7XG4gIHZhciBjID0gMzI7XG4gIHYgJj0gLXY7XG4gIGlmICh2KSBjLS07XG4gIGlmICh2ICYgMHgwMDAwRkZGRikgYyAtPSAxNjtcbiAgaWYgKHYgJiAweDAwRkYwMEZGKSBjIC09IDg7XG4gIGlmICh2ICYgMHgwRjBGMEYwRikgYyAtPSA0O1xuICBpZiAodiAmIDB4MzMzMzMzMzMpIGMgLT0gMjtcbiAgaWYgKHYgJiAweDU1NTU1NTU1KSBjIC09IDE7XG4gIHJldHVybiBjO1xufVxuZXhwb3J0cy5jb3VudFRyYWlsaW5nWmVyb3MgPSBjb3VudFRyYWlsaW5nWmVyb3M7XG5cbi8vUm91bmRzIHRvIG5leHQgcG93ZXIgb2YgMlxuZXhwb3J0cy5uZXh0UG93MiA9IGZ1bmN0aW9uKHYpIHtcbiAgdiArPSB2ID09PSAwO1xuICAtLXY7XG4gIHYgfD0gdiA+Pj4gMTtcbiAgdiB8PSB2ID4+PiAyO1xuICB2IHw9IHYgPj4+IDQ7XG4gIHYgfD0gdiA+Pj4gODtcbiAgdiB8PSB2ID4+PiAxNjtcbiAgcmV0dXJuIHYgKyAxO1xufVxuXG4vL1JvdW5kcyBkb3duIHRvIHByZXZpb3VzIHBvd2VyIG9mIDJcbmV4cG9ydHMucHJldlBvdzIgPSBmdW5jdGlvbih2KSB7XG4gIHYgfD0gdiA+Pj4gMTtcbiAgdiB8PSB2ID4+PiAyO1xuICB2IHw9IHYgPj4+IDQ7XG4gIHYgfD0gdiA+Pj4gODtcbiAgdiB8PSB2ID4+PiAxNjtcbiAgcmV0dXJuIHYgLSAodj4+PjEpO1xufVxuXG4vL0NvbXB1dGVzIHBhcml0eSBvZiB3b3JkXG5leHBvcnRzLnBhcml0eSA9IGZ1bmN0aW9uKHYpIHtcbiAgdiBePSB2ID4+PiAxNjtcbiAgdiBePSB2ID4+PiA4O1xuICB2IF49IHYgPj4+IDQ7XG4gIHYgJj0gMHhmO1xuICByZXR1cm4gKDB4Njk5NiA+Pj4gdikgJiAxO1xufVxuXG52YXIgUkVWRVJTRV9UQUJMRSA9IG5ldyBBcnJheSgyNTYpO1xuXG4oZnVuY3Rpb24odGFiKSB7XG4gIGZvcih2YXIgaT0wOyBpPDI1NjsgKytpKSB7XG4gICAgdmFyIHYgPSBpLCByID0gaSwgcyA9IDc7XG4gICAgZm9yICh2ID4+Pj0gMTsgdjsgdiA+Pj49IDEpIHtcbiAgICAgIHIgPDw9IDE7XG4gICAgICByIHw9IHYgJiAxO1xuICAgICAgLS1zO1xuICAgIH1cbiAgICB0YWJbaV0gPSAociA8PCBzKSAmIDB4ZmY7XG4gIH1cbn0pKFJFVkVSU0VfVEFCTEUpO1xuXG4vL1JldmVyc2UgYml0cyBpbiBhIDMyIGJpdCB3b3JkXG5leHBvcnRzLnJldmVyc2UgPSBmdW5jdGlvbih2KSB7XG4gIHJldHVybiAgKFJFVkVSU0VfVEFCTEVbIHYgICAgICAgICAmIDB4ZmZdIDw8IDI0KSB8XG4gICAgICAgICAgKFJFVkVSU0VfVEFCTEVbKHYgPj4+IDgpICAmIDB4ZmZdIDw8IDE2KSB8XG4gICAgICAgICAgKFJFVkVSU0VfVEFCTEVbKHYgPj4+IDE2KSAmIDB4ZmZdIDw8IDgpICB8XG4gICAgICAgICAgIFJFVkVSU0VfVEFCTEVbKHYgPj4+IDI0KSAmIDB4ZmZdO1xufVxuXG4vL0ludGVybGVhdmUgYml0cyBvZiAyIGNvb3JkaW5hdGVzIHdpdGggMTYgYml0cy4gIFVzZWZ1bCBmb3IgZmFzdCBxdWFkdHJlZSBjb2Rlc1xuZXhwb3J0cy5pbnRlcmxlYXZlMiA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgeCAmPSAweEZGRkY7XG4gIHggPSAoeCB8ICh4IDw8IDgpKSAmIDB4MDBGRjAwRkY7XG4gIHggPSAoeCB8ICh4IDw8IDQpKSAmIDB4MEYwRjBGMEY7XG4gIHggPSAoeCB8ICh4IDw8IDIpKSAmIDB4MzMzMzMzMzM7XG4gIHggPSAoeCB8ICh4IDw8IDEpKSAmIDB4NTU1NTU1NTU7XG5cbiAgeSAmPSAweEZGRkY7XG4gIHkgPSAoeSB8ICh5IDw8IDgpKSAmIDB4MDBGRjAwRkY7XG4gIHkgPSAoeSB8ICh5IDw8IDQpKSAmIDB4MEYwRjBGMEY7XG4gIHkgPSAoeSB8ICh5IDw8IDIpKSAmIDB4MzMzMzMzMzM7XG4gIHkgPSAoeSB8ICh5IDw8IDEpKSAmIDB4NTU1NTU1NTU7XG5cbiAgcmV0dXJuIHggfCAoeSA8PCAxKTtcbn1cblxuLy9FeHRyYWN0cyB0aGUgbnRoIGludGVybGVhdmVkIGNvbXBvbmVudFxuZXhwb3J0cy5kZWludGVybGVhdmUyID0gZnVuY3Rpb24odiwgbikge1xuICB2ID0gKHYgPj4+IG4pICYgMHg1NTU1NTU1NTtcbiAgdiA9ICh2IHwgKHYgPj4+IDEpKSAgJiAweDMzMzMzMzMzO1xuICB2ID0gKHYgfCAodiA+Pj4gMikpICAmIDB4MEYwRjBGMEY7XG4gIHYgPSAodiB8ICh2ID4+PiA0KSkgICYgMHgwMEZGMDBGRjtcbiAgdiA9ICh2IHwgKHYgPj4+IDE2KSkgJiAweDAwMEZGRkY7XG4gIHJldHVybiAodiA8PCAxNikgPj4gMTY7XG59XG5cblxuLy9JbnRlcmxlYXZlIGJpdHMgb2YgMyBjb29yZGluYXRlcywgZWFjaCB3aXRoIDEwIGJpdHMuICBVc2VmdWwgZm9yIGZhc3Qgb2N0cmVlIGNvZGVzXG5leHBvcnRzLmludGVybGVhdmUzID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICB4ICY9IDB4M0ZGO1xuICB4ICA9ICh4IHwgKHg8PDE2KSkgJiA0Mjc4MTkwMzM1O1xuICB4ICA9ICh4IHwgKHg8PDgpKSAgJiAyNTE3MTk2OTU7XG4gIHggID0gKHggfCAoeDw8NCkpICAmIDMyNzIzNTYwMzU7XG4gIHggID0gKHggfCAoeDw8MikpICAmIDEyMjcxMzM1MTM7XG5cbiAgeSAmPSAweDNGRjtcbiAgeSAgPSAoeSB8ICh5PDwxNikpICYgNDI3ODE5MDMzNTtcbiAgeSAgPSAoeSB8ICh5PDw4KSkgICYgMjUxNzE5Njk1O1xuICB5ICA9ICh5IHwgKHk8PDQpKSAgJiAzMjcyMzU2MDM1O1xuICB5ICA9ICh5IHwgKHk8PDIpKSAgJiAxMjI3MTMzNTEzO1xuICB4IHw9ICh5IDw8IDEpO1xuICBcbiAgeiAmPSAweDNGRjtcbiAgeiAgPSAoeiB8ICh6PDwxNikpICYgNDI3ODE5MDMzNTtcbiAgeiAgPSAoeiB8ICh6PDw4KSkgICYgMjUxNzE5Njk1O1xuICB6ICA9ICh6IHwgKHo8PDQpKSAgJiAzMjcyMzU2MDM1O1xuICB6ICA9ICh6IHwgKHo8PDIpKSAgJiAxMjI3MTMzNTEzO1xuICBcbiAgcmV0dXJuIHggfCAoeiA8PCAyKTtcbn1cblxuLy9FeHRyYWN0cyBudGggaW50ZXJsZWF2ZWQgY29tcG9uZW50IG9mIGEgMy10dXBsZVxuZXhwb3J0cy5kZWludGVybGVhdmUzID0gZnVuY3Rpb24odiwgbikge1xuICB2ID0gKHYgPj4+IG4pICAgICAgICYgMTIyNzEzMzUxMztcbiAgdiA9ICh2IHwgKHY+Pj4yKSkgICAmIDMyNzIzNTYwMzU7XG4gIHYgPSAodiB8ICh2Pj4+NCkpICAgJiAyNTE3MTk2OTU7XG4gIHYgPSAodiB8ICh2Pj4+OCkpICAgJiA0Mjc4MTkwMzM1O1xuICB2ID0gKHYgfCAodj4+PjE2KSkgICYgMHgzRkY7XG4gIHJldHVybiAodjw8MjIpPj4yMjtcbn1cblxuLy9Db21wdXRlcyBuZXh0IGNvbWJpbmF0aW9uIGluIGNvbGV4aWNvZ3JhcGhpYyBvcmRlciAodGhpcyBpcyBtaXN0YWtlbmx5IGNhbGxlZCBuZXh0UGVybXV0YXRpb24gb24gdGhlIGJpdCB0d2lkZGxpbmcgaGFja3MgcGFnZSlcbmV4cG9ydHMubmV4dENvbWJpbmF0aW9uID0gZnVuY3Rpb24odikge1xuICB2YXIgdCA9IHYgfCAodiAtIDEpO1xuICByZXR1cm4gKHQgKyAxKSB8ICgoKH50ICYgLX50KSAtIDEpID4+PiAoY291bnRUcmFpbGluZ1plcm9zKHYpICsgMSkpO1xufVxuXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBjbGFtcCA9IHJlcXVpcmUoJ2NsYW1wJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY2FsY1NERlxyXG5cclxudmFyIElORiA9IDFlMjA7XHJcblxyXG5mdW5jdGlvbiBjYWxjU0RGKHNyYywgb3B0aW9ucykge1xyXG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge31cclxuXHJcbiAgICB2YXIgY3V0b2ZmID0gb3B0aW9ucy5jdXRvZmYgPT0gbnVsbCA/IDAuMjUgOiBvcHRpb25zLmN1dG9mZlxyXG4gICAgdmFyIHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzID09IG51bGwgPyA4IDogb3B0aW9ucy5yYWRpdXNcclxuICAgIHZhciBjaGFubmVsID0gb3B0aW9ucy5jaGFubmVsIHx8IDBcclxuICAgIHZhciB3LCBoLCBzaXplLCBkYXRhLCBpbnREYXRhLCBzdHJpZGUsIGN0eCwgY2FudmFzLCBpbWdEYXRhLCBpLCBsXHJcblxyXG4gICAgLy8gaGFuZGxlIGltYWdlIGNvbnRhaW5lclxyXG4gICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhzcmMpIHx8IEFycmF5LmlzQXJyYXkoc3JjKSkge1xyXG4gICAgICAgIGlmICghb3B0aW9ucy53aWR0aCB8fCAhb3B0aW9ucy5oZWlnaHQpIHRocm93IEVycm9yKCdGb3IgcmF3IGRhdGEgd2lkdGggYW5kIGhlaWdodCBzaG91bGQgYmUgcHJvdmlkZWQgYnkgb3B0aW9ucycpXHJcbiAgICAgICAgdyA9IG9wdGlvbnMud2lkdGgsIGggPSBvcHRpb25zLmhlaWdodFxyXG4gICAgICAgIGRhdGEgPSBzcmNcclxuXHJcbiAgICAgICAgaWYgKCFvcHRpb25zLnN0cmlkZSkgc3RyaWRlID0gTWF0aC5mbG9vcihzcmMubGVuZ3RoIC8gdyAvIGgpXHJcbiAgICAgICAgZWxzZSBzdHJpZGUgPSBvcHRpb25zLnN0cmlkZVxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgICAgaWYgKHdpbmRvdy5IVE1MQ2FudmFzRWxlbWVudCAmJiBzcmMgaW5zdGFuY2VvZiB3aW5kb3cuSFRNTENhbnZhc0VsZW1lbnQpIHtcclxuICAgICAgICAgICAgY2FudmFzID0gc3JjXHJcbiAgICAgICAgICAgIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpXHJcbiAgICAgICAgICAgIHcgPSBjYW52YXMud2lkdGgsIGggPSBjYW52YXMuaGVpZ2h0XHJcbiAgICAgICAgICAgIGltZ0RhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpXHJcbiAgICAgICAgICAgIGRhdGEgPSBpbWdEYXRhLmRhdGFcclxuICAgICAgICAgICAgc3RyaWRlID0gNFxyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh3aW5kb3cuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEICYmIHNyYyBpbnN0YW5jZW9mIHdpbmRvdy5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpIHtcclxuICAgICAgICAgICAgY2FudmFzID0gc3JjLmNhbnZhc1xyXG4gICAgICAgICAgICBjdHggPSBzcmNcclxuICAgICAgICAgICAgdyA9IGNhbnZhcy53aWR0aCwgaCA9IGNhbnZhcy5oZWlnaHRcclxuICAgICAgICAgICAgaW1nRGF0YSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgdywgaClcclxuICAgICAgICAgICAgZGF0YSA9IGltZ0RhdGEuZGF0YVxyXG4gICAgICAgICAgICBzdHJpZGUgPSA0XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHdpbmRvdy5JbWFnZURhdGEgJiYgc3JjIGluc3RhbmNlb2Ygd2luZG93LkltYWdlRGF0YSkge1xyXG4gICAgICAgICAgICBpbWdEYXRhID0gc3JjXHJcbiAgICAgICAgICAgIHcgPSBzcmMud2lkdGgsIGggPSBzcmMuaGVpZ2h0XHJcbiAgICAgICAgICAgIGRhdGEgPSBpbWdEYXRhLmRhdGFcclxuICAgICAgICAgICAgc3RyaWRlID0gNFxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBzaXplID0gTWF0aC5tYXgodywgaClcclxuXHJcbiAgICAvL2NvbnZlcnQgaW50IGRhdGEgdG8gZmxvYXRzXHJcbiAgICBpZiAoKHdpbmRvdy5VaW50OENsYW1wZWRBcnJheSAmJiBkYXRhIGluc3RhbmNlb2Ygd2luZG93LlVpbnQ4Q2xhbXBlZEFycmF5KSB8fCAod2luZG93LlVpbnQ4QXJyYXkgJiYgZGF0YSBpbnN0YW5jZW9mIHdpbmRvdy5VaW50OEFycmF5KSkge1xyXG4gICAgICAgIGludERhdGEgPSBkYXRhXHJcbiAgICAgICAgZGF0YSA9IEFycmF5KHcqaClcclxuXHJcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGludERhdGEubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGRhdGFbaV0gPSBpbnREYXRhW2kqc3RyaWRlICsgY2hhbm5lbF0gLyAyNTVcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBlbHNlIHtcclxuICAgICAgICBpZiAoc3RyaWRlICE9PSAxKSB0aHJvdyBFcnJvcignUmF3IGRhdGEgY2FuIGhhdmUgb25seSAxIHZhbHVlIHBlciBwaXhlbCcpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gdGVtcG9yYXJ5IGFycmF5cyBmb3IgdGhlIGRpc3RhbmNlIHRyYW5zZm9ybVxyXG4gICAgdmFyIGdyaWRPdXRlciA9IEFycmF5KHcgKiBoKVxyXG4gICAgdmFyIGdyaWRJbm5lciA9IEFycmF5KHcgKiBoKVxyXG4gICAgdmFyIGYgPSBBcnJheShzaXplKVxyXG4gICAgdmFyIGQgPSBBcnJheShzaXplKVxyXG4gICAgdmFyIHogPSBBcnJheShzaXplICsgMSlcclxuICAgIHZhciB2ID0gQXJyYXkoc2l6ZSlcclxuXHJcbiAgICBmb3IgKGkgPSAwLCBsID0gdyAqIGg7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICB2YXIgYSA9IGRhdGFbaV1cclxuICAgICAgICBncmlkT3V0ZXJbaV0gPSBhID09PSAxID8gMCA6IGEgPT09IDAgPyBJTkYgOiBNYXRoLnBvdyhNYXRoLm1heCgwLCAwLjUgLSBhKSwgMilcclxuICAgICAgICBncmlkSW5uZXJbaV0gPSBhID09PSAxID8gSU5GIDogYSA9PT0gMCA/IDAgOiBNYXRoLnBvdyhNYXRoLm1heCgwLCBhIC0gMC41KSwgMilcclxuICAgIH1cclxuXHJcbiAgICBlZHQoZ3JpZE91dGVyLCB3LCBoLCBmLCBkLCB2LCB6KVxyXG4gICAgZWR0KGdyaWRJbm5lciwgdywgaCwgZiwgZCwgdiwgeilcclxuXHJcbiAgICB2YXIgZGlzdCA9IHdpbmRvdy5GbG9hdDMyQXJyYXkgPyBuZXcgRmxvYXQzMkFycmF5KHcgKiBoKSA6IG5ldyBBcnJheSh3ICogaClcclxuXHJcbiAgICBmb3IgKGkgPSAwLCBsID0gdypoOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgICAgZGlzdFtpXSA9IGNsYW1wKDEgLSAoIChncmlkT3V0ZXJbaV0gLSBncmlkSW5uZXJbaV0pIC8gcmFkaXVzICsgY3V0b2ZmKSwgMCwgMSlcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZGlzdFxyXG59XHJcblxyXG4vLyAyRCBFdWNsaWRlYW4gZGlzdGFuY2UgdHJhbnNmb3JtIGJ5IEZlbHplbnN6d2FsYiAmIEh1dHRlbmxvY2hlciBodHRwczovL2NzLmJyb3duLmVkdS9+cGZmL2R0L1xyXG5mdW5jdGlvbiBlZHQoZGF0YSwgd2lkdGgsIGhlaWdodCwgZiwgZCwgdiwgeikge1xyXG4gICAgZm9yICh2YXIgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XHJcbiAgICAgICAgZm9yICh2YXIgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xyXG4gICAgICAgICAgICBmW3ldID0gZGF0YVt5ICogd2lkdGggKyB4XVxyXG4gICAgICAgIH1cclxuICAgICAgICBlZHQxZChmLCBkLCB2LCB6LCBoZWlnaHQpXHJcbiAgICAgICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XHJcbiAgICAgICAgICAgIGRhdGFbeSAqIHdpZHRoICsgeF0gPSBkW3ldXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XHJcbiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcclxuICAgICAgICAgICAgZlt4XSA9IGRhdGFbeSAqIHdpZHRoICsgeF1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWR0MWQoZiwgZCwgdiwgeiwgd2lkdGgpXHJcbiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcclxuICAgICAgICAgICAgZGF0YVt5ICogd2lkdGggKyB4XSA9IE1hdGguc3FydChkW3hdKVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLy8gMUQgc3F1YXJlZCBkaXN0YW5jZSB0cmFuc2Zvcm1cclxuZnVuY3Rpb24gZWR0MWQoZiwgZCwgdiwgeiwgbikge1xyXG4gICAgdlswXSA9IDA7XHJcbiAgICB6WzBdID0gLUlORlxyXG4gICAgelsxXSA9ICtJTkZcclxuXHJcbiAgICBmb3IgKHZhciBxID0gMSwgayA9IDA7IHEgPCBuOyBxKyspIHtcclxuICAgICAgICB2YXIgcyA9ICgoZltxXSArIHEgKiBxKSAtIChmW3Zba11dICsgdltrXSAqIHZba10pKSAvICgyICogcSAtIDIgKiB2W2tdKVxyXG4gICAgICAgIHdoaWxlIChzIDw9IHpba10pIHtcclxuICAgICAgICAgICAgay0tXHJcbiAgICAgICAgICAgIHMgPSAoKGZbcV0gKyBxICogcSkgLSAoZlt2W2tdXSArIHZba10gKiB2W2tdKSkgLyAoMiAqIHEgLSAyICogdltrXSlcclxuICAgICAgICB9XHJcbiAgICAgICAgaysrXHJcbiAgICAgICAgdltrXSA9IHFcclxuICAgICAgICB6W2tdID0gc1xyXG4gICAgICAgIHpbayArIDFdID0gK0lORlxyXG4gICAgfVxyXG5cclxuICAgIGZvciAocSA9IDAsIGsgPSAwOyBxIDwgbjsgcSsrKSB7XHJcbiAgICAgICAgd2hpbGUgKHpbayArIDFdIDwgcSkgaysrXHJcbiAgICAgICAgZFtxXSA9IChxIC0gdltrXSkgKiAocSAtIHZba10pICsgZlt2W2tdXVxyXG4gICAgfVxyXG59XHJcbiIsIihmdW5jdGlvbiAobW9kdWxlLCBleHBvcnRzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBVdGlsc1xuICBmdW5jdGlvbiBhc3NlcnQgKHZhbCwgbXNnKSB7XG4gICAgaWYgKCF2YWwpIHRocm93IG5ldyBFcnJvcihtc2cgfHwgJ0Fzc2VydGlvbiBmYWlsZWQnKTtcbiAgfVxuXG4gIC8vIENvdWxkIHVzZSBgaW5oZXJpdHNgIG1vZHVsZSwgYnV0IGRvbid0IHdhbnQgdG8gbW92ZSBmcm9tIHNpbmdsZSBmaWxlXG4gIC8vIGFyY2hpdGVjdHVyZSB5ZXQuXG4gIGZ1bmN0aW9uIGluaGVyaXRzIChjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvcjtcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlO1xuICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKCk7XG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yO1xuICB9XG5cbiAgLy8gQk5cblxuICBmdW5jdGlvbiBCTiAobnVtYmVyLCBiYXNlLCBlbmRpYW4pIHtcbiAgICBpZiAoQk4uaXNCTihudW1iZXIpKSB7XG4gICAgICByZXR1cm4gbnVtYmVyO1xuICAgIH1cblxuICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgIHRoaXMud29yZHMgPSBudWxsO1xuICAgIHRoaXMubGVuZ3RoID0gMDtcblxuICAgIC8vIFJlZHVjdGlvbiBjb250ZXh0XG4gICAgdGhpcy5yZWQgPSBudWxsO1xuXG4gICAgaWYgKG51bWJlciAhPT0gbnVsbCkge1xuICAgICAgaWYgKGJhc2UgPT09ICdsZScgfHwgYmFzZSA9PT0gJ2JlJykge1xuICAgICAgICBlbmRpYW4gPSBiYXNlO1xuICAgICAgICBiYXNlID0gMTA7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2luaXQobnVtYmVyIHx8IDAsIGJhc2UgfHwgMTAsIGVuZGlhbiB8fCAnYmUnKTtcbiAgICB9XG4gIH1cbiAgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBCTjtcbiAgfSBlbHNlIHtcbiAgICBleHBvcnRzLkJOID0gQk47XG4gIH1cblxuICBCTi5CTiA9IEJOO1xuICBCTi53b3JkU2l6ZSA9IDI2O1xuXG4gIHZhciBCdWZmZXI7XG4gIHRyeSB7XG4gICAgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyO1xuICB9IGNhdGNoIChlKSB7XG4gIH1cblxuICBCTi5pc0JOID0gZnVuY3Rpb24gaXNCTiAobnVtKSB7XG4gICAgaWYgKG51bSBpbnN0YW5jZW9mIEJOKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVtICE9PSBudWxsICYmIHR5cGVvZiBudW0gPT09ICdvYmplY3QnICYmXG4gICAgICBudW0uY29uc3RydWN0b3Iud29yZFNpemUgPT09IEJOLndvcmRTaXplICYmIEFycmF5LmlzQXJyYXkobnVtLndvcmRzKTtcbiAgfTtcblxuICBCTi5tYXggPSBmdW5jdGlvbiBtYXggKGxlZnQsIHJpZ2h0KSB7XG4gICAgaWYgKGxlZnQuY21wKHJpZ2h0KSA+IDApIHJldHVybiBsZWZ0O1xuICAgIHJldHVybiByaWdodDtcbiAgfTtcblxuICBCTi5taW4gPSBmdW5jdGlvbiBtaW4gKGxlZnQsIHJpZ2h0KSB7XG4gICAgaWYgKGxlZnQuY21wKHJpZ2h0KSA8IDApIHJldHVybiBsZWZ0O1xuICAgIHJldHVybiByaWdodDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2luaXQgPSBmdW5jdGlvbiBpbml0IChudW1iZXIsIGJhc2UsIGVuZGlhbikge1xuICAgIGlmICh0eXBlb2YgbnVtYmVyID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIHRoaXMuX2luaXROdW1iZXIobnVtYmVyLCBiYXNlLCBlbmRpYW4pO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgbnVtYmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIHRoaXMuX2luaXRBcnJheShudW1iZXIsIGJhc2UsIGVuZGlhbik7XG4gICAgfVxuXG4gICAgaWYgKGJhc2UgPT09ICdoZXgnKSB7XG4gICAgICBiYXNlID0gMTY7XG4gICAgfVxuICAgIGFzc2VydChiYXNlID09PSAoYmFzZSB8IDApICYmIGJhc2UgPj0gMiAmJiBiYXNlIDw9IDM2KTtcblxuICAgIG51bWJlciA9IG51bWJlci50b1N0cmluZygpLnJlcGxhY2UoL1xccysvZywgJycpO1xuICAgIHZhciBzdGFydCA9IDA7XG4gICAgaWYgKG51bWJlclswXSA9PT0gJy0nKSB7XG4gICAgICBzdGFydCsrO1xuICAgIH1cblxuICAgIGlmIChiYXNlID09PSAxNikge1xuICAgICAgdGhpcy5fcGFyc2VIZXgobnVtYmVyLCBzdGFydCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3BhcnNlQmFzZShudW1iZXIsIGJhc2UsIHN0YXJ0KTtcbiAgICB9XG5cbiAgICBpZiAobnVtYmVyWzBdID09PSAnLScpIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgIH1cblxuICAgIHRoaXMuc3RyaXAoKTtcblxuICAgIGlmIChlbmRpYW4gIT09ICdsZScpIHJldHVybjtcblxuICAgIHRoaXMuX2luaXRBcnJheSh0aGlzLnRvQXJyYXkoKSwgYmFzZSwgZW5kaWFuKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2luaXROdW1iZXIgPSBmdW5jdGlvbiBfaW5pdE51bWJlciAobnVtYmVyLCBiYXNlLCBlbmRpYW4pIHtcbiAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgICBudW1iZXIgPSAtbnVtYmVyO1xuICAgIH1cbiAgICBpZiAobnVtYmVyIDwgMHg0MDAwMDAwKSB7XG4gICAgICB0aGlzLndvcmRzID0gWyBudW1iZXIgJiAweDNmZmZmZmYgXTtcbiAgICAgIHRoaXMubGVuZ3RoID0gMTtcbiAgICB9IGVsc2UgaWYgKG51bWJlciA8IDB4MTAwMDAwMDAwMDAwMDApIHtcbiAgICAgIHRoaXMud29yZHMgPSBbXG4gICAgICAgIG51bWJlciAmIDB4M2ZmZmZmZixcbiAgICAgICAgKG51bWJlciAvIDB4NDAwMDAwMCkgJiAweDNmZmZmZmZcbiAgICAgIF07XG4gICAgICB0aGlzLmxlbmd0aCA9IDI7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2VydChudW1iZXIgPCAweDIwMDAwMDAwMDAwMDAwKTsgLy8gMiBeIDUzICh1bnNhZmUpXG4gICAgICB0aGlzLndvcmRzID0gW1xuICAgICAgICBudW1iZXIgJiAweDNmZmZmZmYsXG4gICAgICAgIChudW1iZXIgLyAweDQwMDAwMDApICYgMHgzZmZmZmZmLFxuICAgICAgICAxXG4gICAgICBdO1xuICAgICAgdGhpcy5sZW5ndGggPSAzO1xuICAgIH1cblxuICAgIGlmIChlbmRpYW4gIT09ICdsZScpIHJldHVybjtcblxuICAgIC8vIFJldmVyc2UgdGhlIGJ5dGVzXG4gICAgdGhpcy5faW5pdEFycmF5KHRoaXMudG9BcnJheSgpLCBiYXNlLCBlbmRpYW4pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5faW5pdEFycmF5ID0gZnVuY3Rpb24gX2luaXRBcnJheSAobnVtYmVyLCBiYXNlLCBlbmRpYW4pIHtcbiAgICAvLyBQZXJoYXBzIGEgVWludDhBcnJheVxuICAgIGFzc2VydCh0eXBlb2YgbnVtYmVyLmxlbmd0aCA9PT0gJ251bWJlcicpO1xuICAgIGlmIChudW1iZXIubGVuZ3RoIDw9IDApIHtcbiAgICAgIHRoaXMud29yZHMgPSBbIDAgXTtcbiAgICAgIHRoaXMubGVuZ3RoID0gMTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHRoaXMubGVuZ3RoID0gTWF0aC5jZWlsKG51bWJlci5sZW5ndGggLyAzKTtcbiAgICB0aGlzLndvcmRzID0gbmV3IEFycmF5KHRoaXMubGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSAwO1xuICAgIH1cblxuICAgIHZhciBqLCB3O1xuICAgIHZhciBvZmYgPSAwO1xuICAgIGlmIChlbmRpYW4gPT09ICdiZScpIHtcbiAgICAgIGZvciAoaSA9IG51bWJlci5sZW5ndGggLSAxLCBqID0gMDsgaSA+PSAwOyBpIC09IDMpIHtcbiAgICAgICAgdyA9IG51bWJlcltpXSB8IChudW1iZXJbaSAtIDFdIDw8IDgpIHwgKG51bWJlcltpIC0gMl0gPDwgMTYpO1xuICAgICAgICB0aGlzLndvcmRzW2pdIHw9ICh3IDw8IG9mZikgJiAweDNmZmZmZmY7XG4gICAgICAgIHRoaXMud29yZHNbaiArIDFdID0gKHcgPj4+ICgyNiAtIG9mZikpICYgMHgzZmZmZmZmO1xuICAgICAgICBvZmYgKz0gMjQ7XG4gICAgICAgIGlmIChvZmYgPj0gMjYpIHtcbiAgICAgICAgICBvZmYgLT0gMjY7XG4gICAgICAgICAgaisrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlbmRpYW4gPT09ICdsZScpIHtcbiAgICAgIGZvciAoaSA9IDAsIGogPSAwOyBpIDwgbnVtYmVyLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgICAgIHcgPSBudW1iZXJbaV0gfCAobnVtYmVyW2kgKyAxXSA8PCA4KSB8IChudW1iZXJbaSArIDJdIDw8IDE2KTtcbiAgICAgICAgdGhpcy53b3Jkc1tqXSB8PSAodyA8PCBvZmYpICYgMHgzZmZmZmZmO1xuICAgICAgICB0aGlzLndvcmRzW2ogKyAxXSA9ICh3ID4+PiAoMjYgLSBvZmYpKSAmIDB4M2ZmZmZmZjtcbiAgICAgICAgb2ZmICs9IDI0O1xuICAgICAgICBpZiAob2ZmID49IDI2KSB7XG4gICAgICAgICAgb2ZmIC09IDI2O1xuICAgICAgICAgIGorKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHBhcnNlSGV4IChzdHIsIHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgciA9IDA7XG4gICAgdmFyIGxlbiA9IE1hdGgubWluKHN0ci5sZW5ndGgsIGVuZCk7XG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHZhciBjID0gc3RyLmNoYXJDb2RlQXQoaSkgLSA0ODtcblxuICAgICAgciA8PD0gNDtcblxuICAgICAgLy8gJ2EnIC0gJ2YnXG4gICAgICBpZiAoYyA+PSA0OSAmJiBjIDw9IDU0KSB7XG4gICAgICAgIHIgfD0gYyAtIDQ5ICsgMHhhO1xuXG4gICAgICAvLyAnQScgLSAnRidcbiAgICAgIH0gZWxzZSBpZiAoYyA+PSAxNyAmJiBjIDw9IDIyKSB7XG4gICAgICAgIHIgfD0gYyAtIDE3ICsgMHhhO1xuXG4gICAgICAvLyAnMCcgLSAnOSdcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHIgfD0gYyAmIDB4ZjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH1cblxuICBCTi5wcm90b3R5cGUuX3BhcnNlSGV4ID0gZnVuY3Rpb24gX3BhcnNlSGV4IChudW1iZXIsIHN0YXJ0KSB7XG4gICAgLy8gQ3JlYXRlIHBvc3NpYmx5IGJpZ2dlciBhcnJheSB0byBlbnN1cmUgdGhhdCBpdCBmaXRzIHRoZSBudW1iZXJcbiAgICB0aGlzLmxlbmd0aCA9IE1hdGguY2VpbCgobnVtYmVyLmxlbmd0aCAtIHN0YXJ0KSAvIDYpO1xuICAgIHRoaXMud29yZHMgPSBuZXcgQXJyYXkodGhpcy5sZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGosIHc7XG4gICAgLy8gU2NhbiAyNC1iaXQgY2h1bmtzIGFuZCBhZGQgdGhlbSB0byB0aGUgbnVtYmVyXG4gICAgdmFyIG9mZiA9IDA7XG4gICAgZm9yIChpID0gbnVtYmVyLmxlbmd0aCAtIDYsIGogPSAwOyBpID49IHN0YXJ0OyBpIC09IDYpIHtcbiAgICAgIHcgPSBwYXJzZUhleChudW1iZXIsIGksIGkgKyA2KTtcbiAgICAgIHRoaXMud29yZHNbal0gfD0gKHcgPDwgb2ZmKSAmIDB4M2ZmZmZmZjtcbiAgICAgIC8vIE5PVEU6IGAweDNmZmZmZmAgaXMgaW50ZW50aW9uYWwgaGVyZSwgMjZiaXRzIG1heCBzaGlmdCArIDI0Yml0IGhleCBsaW1iXG4gICAgICB0aGlzLndvcmRzW2ogKyAxXSB8PSB3ID4+PiAoMjYgLSBvZmYpICYgMHgzZmZmZmY7XG4gICAgICBvZmYgKz0gMjQ7XG4gICAgICBpZiAob2ZmID49IDI2KSB7XG4gICAgICAgIG9mZiAtPSAyNjtcbiAgICAgICAgaisrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaSArIDYgIT09IHN0YXJ0KSB7XG4gICAgICB3ID0gcGFyc2VIZXgobnVtYmVyLCBzdGFydCwgaSArIDYpO1xuICAgICAgdGhpcy53b3Jkc1tqXSB8PSAodyA8PCBvZmYpICYgMHgzZmZmZmZmO1xuICAgICAgdGhpcy53b3Jkc1tqICsgMV0gfD0gdyA+Pj4gKDI2IC0gb2ZmKSAmIDB4M2ZmZmZmO1xuICAgIH1cbiAgICB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgZnVuY3Rpb24gcGFyc2VCYXNlIChzdHIsIHN0YXJ0LCBlbmQsIG11bCkge1xuICAgIHZhciByID0gMDtcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oc3RyLmxlbmd0aCwgZW5kKTtcbiAgICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBsZW47IGkrKykge1xuICAgICAgdmFyIGMgPSBzdHIuY2hhckNvZGVBdChpKSAtIDQ4O1xuXG4gICAgICByICo9IG11bDtcblxuICAgICAgLy8gJ2EnXG4gICAgICBpZiAoYyA+PSA0OSkge1xuICAgICAgICByICs9IGMgLSA0OSArIDB4YTtcblxuICAgICAgLy8gJ0EnXG4gICAgICB9IGVsc2UgaWYgKGMgPj0gMTcpIHtcbiAgICAgICAgciArPSBjIC0gMTcgKyAweGE7XG5cbiAgICAgIC8vICcwJyAtICc5J1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgciArPSBjO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfVxuXG4gIEJOLnByb3RvdHlwZS5fcGFyc2VCYXNlID0gZnVuY3Rpb24gX3BhcnNlQmFzZSAobnVtYmVyLCBiYXNlLCBzdGFydCkge1xuICAgIC8vIEluaXRpYWxpemUgYXMgemVyb1xuICAgIHRoaXMud29yZHMgPSBbIDAgXTtcbiAgICB0aGlzLmxlbmd0aCA9IDE7XG5cbiAgICAvLyBGaW5kIGxlbmd0aCBvZiBsaW1iIGluIGJhc2VcbiAgICBmb3IgKHZhciBsaW1iTGVuID0gMCwgbGltYlBvdyA9IDE7IGxpbWJQb3cgPD0gMHgzZmZmZmZmOyBsaW1iUG93ICo9IGJhc2UpIHtcbiAgICAgIGxpbWJMZW4rKztcbiAgICB9XG4gICAgbGltYkxlbi0tO1xuICAgIGxpbWJQb3cgPSAobGltYlBvdyAvIGJhc2UpIHwgMDtcblxuICAgIHZhciB0b3RhbCA9IG51bWJlci5sZW5ndGggLSBzdGFydDtcbiAgICB2YXIgbW9kID0gdG90YWwgJSBsaW1iTGVuO1xuICAgIHZhciBlbmQgPSBNYXRoLm1pbih0b3RhbCwgdG90YWwgLSBtb2QpICsgc3RhcnQ7XG5cbiAgICB2YXIgd29yZCA9IDA7XG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpICs9IGxpbWJMZW4pIHtcbiAgICAgIHdvcmQgPSBwYXJzZUJhc2UobnVtYmVyLCBpLCBpICsgbGltYkxlbiwgYmFzZSk7XG5cbiAgICAgIHRoaXMuaW11bG4obGltYlBvdyk7XG4gICAgICBpZiAodGhpcy53b3Jkc1swXSArIHdvcmQgPCAweDQwMDAwMDApIHtcbiAgICAgICAgdGhpcy53b3Jkc1swXSArPSB3b3JkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5faWFkZG4od29yZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1vZCAhPT0gMCkge1xuICAgICAgdmFyIHBvdyA9IDE7XG4gICAgICB3b3JkID0gcGFyc2VCYXNlKG51bWJlciwgaSwgbnVtYmVyLmxlbmd0aCwgYmFzZSk7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBtb2Q7IGkrKykge1xuICAgICAgICBwb3cgKj0gYmFzZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5pbXVsbihwb3cpO1xuICAgICAgaWYgKHRoaXMud29yZHNbMF0gKyB3b3JkIDwgMHg0MDAwMDAwKSB7XG4gICAgICAgIHRoaXMud29yZHNbMF0gKz0gd29yZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2lhZGRuKHdvcmQpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBCTi5wcm90b3R5cGUuY29weSA9IGZ1bmN0aW9uIGNvcHkgKGRlc3QpIHtcbiAgICBkZXN0LndvcmRzID0gbmV3IEFycmF5KHRoaXMubGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGRlc3Qud29yZHNbaV0gPSB0aGlzLndvcmRzW2ldO1xuICAgIH1cbiAgICBkZXN0Lmxlbmd0aCA9IHRoaXMubGVuZ3RoO1xuICAgIGRlc3QubmVnYXRpdmUgPSB0aGlzLm5lZ2F0aXZlO1xuICAgIGRlc3QucmVkID0gdGhpcy5yZWQ7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gY2xvbmUgKCkge1xuICAgIHZhciByID0gbmV3IEJOKG51bGwpO1xuICAgIHRoaXMuY29weShyKTtcbiAgICByZXR1cm4gcjtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2V4cGFuZCA9IGZ1bmN0aW9uIF9leHBhbmQgKHNpemUpIHtcbiAgICB3aGlsZSAodGhpcy5sZW5ndGggPCBzaXplKSB7XG4gICAgICB0aGlzLndvcmRzW3RoaXMubGVuZ3RoKytdID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gUmVtb3ZlIGxlYWRpbmcgYDBgIGZyb20gYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5zdHJpcCA9IGZ1bmN0aW9uIHN0cmlwICgpIHtcbiAgICB3aGlsZSAodGhpcy5sZW5ndGggPiAxICYmIHRoaXMud29yZHNbdGhpcy5sZW5ndGggLSAxXSA9PT0gMCkge1xuICAgICAgdGhpcy5sZW5ndGgtLTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX25vcm1TaWduKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl9ub3JtU2lnbiA9IGZ1bmN0aW9uIF9ub3JtU2lnbiAoKSB7XG4gICAgLy8gLTAgPSAwXG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAxICYmIHRoaXMud29yZHNbMF0gPT09IDApIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICAgIHJldHVybiAodGhpcy5yZWQgPyAnPEJOLVI6ICcgOiAnPEJOOiAnKSArIHRoaXMudG9TdHJpbmcoMTYpICsgJz4nO1xuICB9O1xuXG4gIC8qXG5cbiAgdmFyIHplcm9zID0gW107XG4gIHZhciBncm91cFNpemVzID0gW107XG4gIHZhciBncm91cEJhc2VzID0gW107XG5cbiAgdmFyIHMgPSAnJztcbiAgdmFyIGkgPSAtMTtcbiAgd2hpbGUgKCsraSA8IEJOLndvcmRTaXplKSB7XG4gICAgemVyb3NbaV0gPSBzO1xuICAgIHMgKz0gJzAnO1xuICB9XG4gIGdyb3VwU2l6ZXNbMF0gPSAwO1xuICBncm91cFNpemVzWzFdID0gMDtcbiAgZ3JvdXBCYXNlc1swXSA9IDA7XG4gIGdyb3VwQmFzZXNbMV0gPSAwO1xuICB2YXIgYmFzZSA9IDIgLSAxO1xuICB3aGlsZSAoKytiYXNlIDwgMzYgKyAxKSB7XG4gICAgdmFyIGdyb3VwU2l6ZSA9IDA7XG4gICAgdmFyIGdyb3VwQmFzZSA9IDE7XG4gICAgd2hpbGUgKGdyb3VwQmFzZSA8ICgxIDw8IEJOLndvcmRTaXplKSAvIGJhc2UpIHtcbiAgICAgIGdyb3VwQmFzZSAqPSBiYXNlO1xuICAgICAgZ3JvdXBTaXplICs9IDE7XG4gICAgfVxuICAgIGdyb3VwU2l6ZXNbYmFzZV0gPSBncm91cFNpemU7XG4gICAgZ3JvdXBCYXNlc1tiYXNlXSA9IGdyb3VwQmFzZTtcbiAgfVxuXG4gICovXG5cbiAgdmFyIHplcm9zID0gW1xuICAgICcnLFxuICAgICcwJyxcbiAgICAnMDAnLFxuICAgICcwMDAnLFxuICAgICcwMDAwJyxcbiAgICAnMDAwMDAnLFxuICAgICcwMDAwMDAnLFxuICAgICcwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJ1xuICBdO1xuXG4gIHZhciBncm91cFNpemVzID0gW1xuICAgIDAsIDAsXG4gICAgMjUsIDE2LCAxMiwgMTEsIDEwLCA5LCA4LFxuICAgIDgsIDcsIDcsIDcsIDcsIDYsIDYsXG4gICAgNiwgNiwgNiwgNiwgNiwgNSwgNSxcbiAgICA1LCA1LCA1LCA1LCA1LCA1LCA1LFxuICAgIDUsIDUsIDUsIDUsIDUsIDUsIDVcbiAgXTtcblxuICB2YXIgZ3JvdXBCYXNlcyA9IFtcbiAgICAwLCAwLFxuICAgIDMzNTU0NDMyLCA0MzA0NjcyMSwgMTY3NzcyMTYsIDQ4ODI4MTI1LCA2MDQ2NjE3NiwgNDAzNTM2MDcsIDE2Nzc3MjE2LFxuICAgIDQzMDQ2NzIxLCAxMDAwMDAwMCwgMTk0ODcxNzEsIDM1ODMxODA4LCA2Mjc0ODUxNywgNzUyOTUzNiwgMTEzOTA2MjUsXG4gICAgMTY3NzcyMTYsIDI0MTM3NTY5LCAzNDAxMjIyNCwgNDcwNDU4ODEsIDY0MDAwMDAwLCA0MDg0MTAxLCA1MTUzNjMyLFxuICAgIDY0MzYzNDMsIDc5NjI2MjQsIDk3NjU2MjUsIDExODgxMzc2LCAxNDM0ODkwNywgMTcyMTAzNjgsIDIwNTExMTQ5LFxuICAgIDI0MzAwMDAwLCAyODYyOTE1MSwgMzM1NTQ0MzIsIDM5MTM1MzkzLCA0NTQzNTQyNCwgNTI1MjE4NzUsIDYwNDY2MTc2XG4gIF07XG5cbiAgQk4ucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKGJhc2UsIHBhZGRpbmcpIHtcbiAgICBiYXNlID0gYmFzZSB8fCAxMDtcbiAgICBwYWRkaW5nID0gcGFkZGluZyB8IDAgfHwgMTtcblxuICAgIHZhciBvdXQ7XG4gICAgaWYgKGJhc2UgPT09IDE2IHx8IGJhc2UgPT09ICdoZXgnKSB7XG4gICAgICBvdXQgPSAnJztcbiAgICAgIHZhciBvZmYgPSAwO1xuICAgICAgdmFyIGNhcnJ5ID0gMDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdyA9IHRoaXMud29yZHNbaV07XG4gICAgICAgIHZhciB3b3JkID0gKCgodyA8PCBvZmYpIHwgY2FycnkpICYgMHhmZmZmZmYpLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgY2FycnkgPSAodyA+Pj4gKDI0IC0gb2ZmKSkgJiAweGZmZmZmZjtcbiAgICAgICAgaWYgKGNhcnJ5ICE9PSAwIHx8IGkgIT09IHRoaXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgIG91dCA9IHplcm9zWzYgLSB3b3JkLmxlbmd0aF0gKyB3b3JkICsgb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dCA9IHdvcmQgKyBvdXQ7XG4gICAgICAgIH1cbiAgICAgICAgb2ZmICs9IDI7XG4gICAgICAgIGlmIChvZmYgPj0gMjYpIHtcbiAgICAgICAgICBvZmYgLT0gMjY7XG4gICAgICAgICAgaS0tO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgICAgb3V0ID0gY2FycnkudG9TdHJpbmcoMTYpICsgb3V0O1xuICAgICAgfVxuICAgICAgd2hpbGUgKG91dC5sZW5ndGggJSBwYWRkaW5nICE9PSAwKSB7XG4gICAgICAgIG91dCA9ICcwJyArIG91dDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICAgIG91dCA9ICctJyArIG91dDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgaWYgKGJhc2UgPT09IChiYXNlIHwgMCkgJiYgYmFzZSA+PSAyICYmIGJhc2UgPD0gMzYpIHtcbiAgICAgIC8vIHZhciBncm91cFNpemUgPSBNYXRoLmZsb29yKEJOLndvcmRTaXplICogTWF0aC5MTjIgLyBNYXRoLmxvZyhiYXNlKSk7XG4gICAgICB2YXIgZ3JvdXBTaXplID0gZ3JvdXBTaXplc1tiYXNlXTtcbiAgICAgIC8vIHZhciBncm91cEJhc2UgPSBNYXRoLnBvdyhiYXNlLCBncm91cFNpemUpO1xuICAgICAgdmFyIGdyb3VwQmFzZSA9IGdyb3VwQmFzZXNbYmFzZV07XG4gICAgICBvdXQgPSAnJztcbiAgICAgIHZhciBjID0gdGhpcy5jbG9uZSgpO1xuICAgICAgYy5uZWdhdGl2ZSA9IDA7XG4gICAgICB3aGlsZSAoIWMuaXNaZXJvKCkpIHtcbiAgICAgICAgdmFyIHIgPSBjLm1vZG4oZ3JvdXBCYXNlKS50b1N0cmluZyhiYXNlKTtcbiAgICAgICAgYyA9IGMuaWRpdm4oZ3JvdXBCYXNlKTtcblxuICAgICAgICBpZiAoIWMuaXNaZXJvKCkpIHtcbiAgICAgICAgICBvdXQgPSB6ZXJvc1tncm91cFNpemUgLSByLmxlbmd0aF0gKyByICsgb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dCA9IHIgKyBvdXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmlzWmVybygpKSB7XG4gICAgICAgIG91dCA9ICcwJyArIG91dDtcbiAgICAgIH1cbiAgICAgIHdoaWxlIChvdXQubGVuZ3RoICUgcGFkZGluZyAhPT0gMCkge1xuICAgICAgICBvdXQgPSAnMCcgKyBvdXQ7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgICBvdXQgPSAnLScgKyBvdXQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIGFzc2VydChmYWxzZSwgJ0Jhc2Ugc2hvdWxkIGJlIGJldHdlZW4gMiBhbmQgMzYnKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudG9OdW1iZXIgPSBmdW5jdGlvbiB0b051bWJlciAoKSB7XG4gICAgdmFyIHJldCA9IHRoaXMud29yZHNbMF07XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAyKSB7XG4gICAgICByZXQgKz0gdGhpcy53b3Jkc1sxXSAqIDB4NDAwMDAwMDtcbiAgICB9IGVsc2UgaWYgKHRoaXMubGVuZ3RoID09PSAzICYmIHRoaXMud29yZHNbMl0gPT09IDB4MDEpIHtcbiAgICAgIC8vIE5PVEU6IGF0IHRoaXMgc3RhZ2UgaXQgaXMga25vd24gdGhhdCB0aGUgdG9wIGJpdCBpcyBzZXRcbiAgICAgIHJldCArPSAweDEwMDAwMDAwMDAwMDAwICsgKHRoaXMud29yZHNbMV0gKiAweDQwMDAwMDApO1xuICAgIH0gZWxzZSBpZiAodGhpcy5sZW5ndGggPiAyKSB7XG4gICAgICBhc3NlcnQoZmFsc2UsICdOdW1iZXIgY2FuIG9ubHkgc2FmZWx5IHN0b3JlIHVwIHRvIDUzIGJpdHMnKTtcbiAgICB9XG4gICAgcmV0dXJuICh0aGlzLm5lZ2F0aXZlICE9PSAwKSA/IC1yZXQgOiByZXQ7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoMTYpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS50b0J1ZmZlciA9IGZ1bmN0aW9uIHRvQnVmZmVyIChlbmRpYW4sIGxlbmd0aCkge1xuICAgIGFzc2VydCh0eXBlb2YgQnVmZmVyICE9PSAndW5kZWZpbmVkJyk7XG4gICAgcmV0dXJuIHRoaXMudG9BcnJheUxpa2UoQnVmZmVyLCBlbmRpYW4sIGxlbmd0aCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbiB0b0FycmF5IChlbmRpYW4sIGxlbmd0aCkge1xuICAgIHJldHVybiB0aGlzLnRvQXJyYXlMaWtlKEFycmF5LCBlbmRpYW4sIGxlbmd0aCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvQXJyYXlMaWtlID0gZnVuY3Rpb24gdG9BcnJheUxpa2UgKEFycmF5VHlwZSwgZW5kaWFuLCBsZW5ndGgpIHtcbiAgICB2YXIgYnl0ZUxlbmd0aCA9IHRoaXMuYnl0ZUxlbmd0aCgpO1xuICAgIHZhciByZXFMZW5ndGggPSBsZW5ndGggfHwgTWF0aC5tYXgoMSwgYnl0ZUxlbmd0aCk7XG4gICAgYXNzZXJ0KGJ5dGVMZW5ndGggPD0gcmVxTGVuZ3RoLCAnYnl0ZSBhcnJheSBsb25nZXIgdGhhbiBkZXNpcmVkIGxlbmd0aCcpO1xuICAgIGFzc2VydChyZXFMZW5ndGggPiAwLCAnUmVxdWVzdGVkIGFycmF5IGxlbmd0aCA8PSAwJyk7XG5cbiAgICB0aGlzLnN0cmlwKCk7XG4gICAgdmFyIGxpdHRsZUVuZGlhbiA9IGVuZGlhbiA9PT0gJ2xlJztcbiAgICB2YXIgcmVzID0gbmV3IEFycmF5VHlwZShyZXFMZW5ndGgpO1xuXG4gICAgdmFyIGIsIGk7XG4gICAgdmFyIHEgPSB0aGlzLmNsb25lKCk7XG4gICAgaWYgKCFsaXR0bGVFbmRpYW4pIHtcbiAgICAgIC8vIEFzc3VtZSBiaWctZW5kaWFuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgcmVxTGVuZ3RoIC0gYnl0ZUxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc1tpXSA9IDA7XG4gICAgICB9XG5cbiAgICAgIGZvciAoaSA9IDA7ICFxLmlzWmVybygpOyBpKyspIHtcbiAgICAgICAgYiA9IHEuYW5kbG4oMHhmZik7XG4gICAgICAgIHEuaXVzaHJuKDgpO1xuXG4gICAgICAgIHJlc1tyZXFMZW5ndGggLSBpIC0gMV0gPSBiO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyAhcS5pc1plcm8oKTsgaSsrKSB7XG4gICAgICAgIGIgPSBxLmFuZGxuKDB4ZmYpO1xuICAgICAgICBxLml1c2hybig4KTtcblxuICAgICAgICByZXNbaV0gPSBiO1xuICAgICAgfVxuXG4gICAgICBmb3IgKDsgaSA8IHJlcUxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc1tpXSA9IDA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBpZiAoTWF0aC5jbHozMikge1xuICAgIEJOLnByb3RvdHlwZS5fY291bnRCaXRzID0gZnVuY3Rpb24gX2NvdW50Qml0cyAodykge1xuICAgICAgcmV0dXJuIDMyIC0gTWF0aC5jbHozMih3KTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIEJOLnByb3RvdHlwZS5fY291bnRCaXRzID0gZnVuY3Rpb24gX2NvdW50Qml0cyAodykge1xuICAgICAgdmFyIHQgPSB3O1xuICAgICAgdmFyIHIgPSAwO1xuICAgICAgaWYgKHQgPj0gMHgxMDAwKSB7XG4gICAgICAgIHIgKz0gMTM7XG4gICAgICAgIHQgPj4+PSAxMztcbiAgICAgIH1cbiAgICAgIGlmICh0ID49IDB4NDApIHtcbiAgICAgICAgciArPSA3O1xuICAgICAgICB0ID4+Pj0gNztcbiAgICAgIH1cbiAgICAgIGlmICh0ID49IDB4OCkge1xuICAgICAgICByICs9IDQ7XG4gICAgICAgIHQgPj4+PSA0O1xuICAgICAgfVxuICAgICAgaWYgKHQgPj0gMHgwMikge1xuICAgICAgICByICs9IDI7XG4gICAgICAgIHQgPj4+PSAyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHIgKyB0O1xuICAgIH07XG4gIH1cblxuICBCTi5wcm90b3R5cGUuX3plcm9CaXRzID0gZnVuY3Rpb24gX3plcm9CaXRzICh3KSB7XG4gICAgLy8gU2hvcnQtY3V0XG4gICAgaWYgKHcgPT09IDApIHJldHVybiAyNjtcblxuICAgIHZhciB0ID0gdztcbiAgICB2YXIgciA9IDA7XG4gICAgaWYgKCh0ICYgMHgxZmZmKSA9PT0gMCkge1xuICAgICAgciArPSAxMztcbiAgICAgIHQgPj4+PSAxMztcbiAgICB9XG4gICAgaWYgKCh0ICYgMHg3ZikgPT09IDApIHtcbiAgICAgIHIgKz0gNztcbiAgICAgIHQgPj4+PSA3O1xuICAgIH1cbiAgICBpZiAoKHQgJiAweGYpID09PSAwKSB7XG4gICAgICByICs9IDQ7XG4gICAgICB0ID4+Pj0gNDtcbiAgICB9XG4gICAgaWYgKCh0ICYgMHgzKSA9PT0gMCkge1xuICAgICAgciArPSAyO1xuICAgICAgdCA+Pj49IDI7XG4gICAgfVxuICAgIGlmICgodCAmIDB4MSkgPT09IDApIHtcbiAgICAgIHIrKztcbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgLy8gUmV0dXJuIG51bWJlciBvZiB1c2VkIGJpdHMgaW4gYSBCTlxuICBCTi5wcm90b3R5cGUuYml0TGVuZ3RoID0gZnVuY3Rpb24gYml0TGVuZ3RoICgpIHtcbiAgICB2YXIgdyA9IHRoaXMud29yZHNbdGhpcy5sZW5ndGggLSAxXTtcbiAgICB2YXIgaGkgPSB0aGlzLl9jb3VudEJpdHModyk7XG4gICAgcmV0dXJuICh0aGlzLmxlbmd0aCAtIDEpICogMjYgKyBoaTtcbiAgfTtcblxuICBmdW5jdGlvbiB0b0JpdEFycmF5IChudW0pIHtcbiAgICB2YXIgdyA9IG5ldyBBcnJheShudW0uYml0TGVuZ3RoKCkpO1xuXG4gICAgZm9yICh2YXIgYml0ID0gMDsgYml0IDwgdy5sZW5ndGg7IGJpdCsrKSB7XG4gICAgICB2YXIgb2ZmID0gKGJpdCAvIDI2KSB8IDA7XG4gICAgICB2YXIgd2JpdCA9IGJpdCAlIDI2O1xuXG4gICAgICB3W2JpdF0gPSAobnVtLndvcmRzW29mZl0gJiAoMSA8PCB3Yml0KSkgPj4+IHdiaXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHc7XG4gIH1cblxuICAvLyBOdW1iZXIgb2YgdHJhaWxpbmcgemVybyBiaXRzXG4gIEJOLnByb3RvdHlwZS56ZXJvQml0cyA9IGZ1bmN0aW9uIHplcm9CaXRzICgpIHtcbiAgICBpZiAodGhpcy5pc1plcm8oKSkgcmV0dXJuIDA7XG5cbiAgICB2YXIgciA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgYiA9IHRoaXMuX3plcm9CaXRzKHRoaXMud29yZHNbaV0pO1xuICAgICAgciArPSBiO1xuICAgICAgaWYgKGIgIT09IDI2KSBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmJ5dGVMZW5ndGggPSBmdW5jdGlvbiBieXRlTGVuZ3RoICgpIHtcbiAgICByZXR1cm4gTWF0aC5jZWlsKHRoaXMuYml0TGVuZ3RoKCkgLyA4KTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudG9Ud29zID0gZnVuY3Rpb24gdG9Ud29zICh3aWR0aCkge1xuICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5hYnMoKS5pbm90bih3aWR0aCkuaWFkZG4oMSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNsb25lKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmZyb21Ud29zID0gZnVuY3Rpb24gZnJvbVR3b3MgKHdpZHRoKSB7XG4gICAgaWYgKHRoaXMudGVzdG4od2lkdGggLSAxKSkge1xuICAgICAgcmV0dXJuIHRoaXMubm90bih3aWR0aCkuaWFkZG4oMSkuaW5lZygpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc05lZyA9IGZ1bmN0aW9uIGlzTmVnICgpIHtcbiAgICByZXR1cm4gdGhpcy5uZWdhdGl2ZSAhPT0gMDtcbiAgfTtcblxuICAvLyBSZXR1cm4gbmVnYXRpdmUgY2xvbmUgb2YgYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5uZWcgPSBmdW5jdGlvbiBuZWcgKCkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaW5lZygpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pbmVnID0gZnVuY3Rpb24gaW5lZyAoKSB7XG4gICAgaWYgKCF0aGlzLmlzWmVybygpKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlIF49IDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gT3IgYG51bWAgd2l0aCBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLml1b3IgPSBmdW5jdGlvbiBpdW9yIChudW0pIHtcbiAgICB3aGlsZSAodGhpcy5sZW5ndGggPCBudW0ubGVuZ3RoKSB7XG4gICAgICB0aGlzLndvcmRzW3RoaXMubGVuZ3RoKytdID0gMDtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bS5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHRoaXMud29yZHNbaV0gfCBudW0ud29yZHNbaV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaW9yID0gZnVuY3Rpb24gaW9yIChudW0pIHtcbiAgICBhc3NlcnQoKHRoaXMubmVnYXRpdmUgfCBudW0ubmVnYXRpdmUpID09PSAwKTtcbiAgICByZXR1cm4gdGhpcy5pdW9yKG51bSk7XG4gIH07XG5cbiAgLy8gT3IgYG51bWAgd2l0aCBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLm9yID0gZnVuY3Rpb24gb3IgKG51bSkge1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHJldHVybiB0aGlzLmNsb25lKCkuaW9yKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLmlvcih0aGlzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudW9yID0gZnVuY3Rpb24gdW9yIChudW0pIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLml1b3IobnVtKTtcbiAgICByZXR1cm4gbnVtLmNsb25lKCkuaXVvcih0aGlzKTtcbiAgfTtcblxuICAvLyBBbmQgYG51bWAgd2l0aCBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLml1YW5kID0gZnVuY3Rpb24gaXVhbmQgKG51bSkge1xuICAgIC8vIGIgPSBtaW4tbGVuZ3RoKG51bSwgdGhpcylcbiAgICB2YXIgYjtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSB7XG4gICAgICBiID0gbnVtO1xuICAgIH0gZWxzZSB7XG4gICAgICBiID0gdGhpcztcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB0aGlzLndvcmRzW2ldICYgbnVtLndvcmRzW2ldO1xuICAgIH1cblxuICAgIHRoaXMubGVuZ3RoID0gYi5sZW5ndGg7XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pYW5kID0gZnVuY3Rpb24gaWFuZCAobnVtKSB7XG4gICAgYXNzZXJ0KCh0aGlzLm5lZ2F0aXZlIHwgbnVtLm5lZ2F0aXZlKSA9PT0gMCk7XG4gICAgcmV0dXJuIHRoaXMuaXVhbmQobnVtKTtcbiAgfTtcblxuICAvLyBBbmQgYG51bWAgd2l0aCBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLmFuZCA9IGZ1bmN0aW9uIGFuZCAobnVtKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkgcmV0dXJuIHRoaXMuY2xvbmUoKS5pYW5kKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLmlhbmQodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnVhbmQgPSBmdW5jdGlvbiB1YW5kIChudW0pIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLml1YW5kKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLml1YW5kKHRoaXMpO1xuICB9O1xuXG4gIC8vIFhvciBgbnVtYCB3aXRoIGB0aGlzYCBpbi1wbGFjZVxuICBCTi5wcm90b3R5cGUuaXV4b3IgPSBmdW5jdGlvbiBpdXhvciAobnVtKSB7XG4gICAgLy8gYS5sZW5ndGggPiBiLmxlbmd0aFxuICAgIHZhciBhO1xuICAgIHZhciBiO1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHtcbiAgICAgIGEgPSB0aGlzO1xuICAgICAgYiA9IG51bTtcbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IG51bTtcbiAgICAgIGIgPSB0aGlzO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYi5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IGEud29yZHNbaV0gXiBiLndvcmRzW2ldO1xuICAgIH1cblxuICAgIGlmICh0aGlzICE9PSBhKSB7XG4gICAgICBmb3IgKDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IGEud29yZHNbaV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sZW5ndGggPSBhLmxlbmd0aDtcblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLml4b3IgPSBmdW5jdGlvbiBpeG9yIChudW0pIHtcbiAgICBhc3NlcnQoKHRoaXMubmVnYXRpdmUgfCBudW0ubmVnYXRpdmUpID09PSAwKTtcbiAgICByZXR1cm4gdGhpcy5pdXhvcihudW0pO1xuICB9O1xuXG4gIC8vIFhvciBgbnVtYCB3aXRoIGB0aGlzYFxuICBCTi5wcm90b3R5cGUueG9yID0gZnVuY3Rpb24geG9yIChudW0pIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLml4b3IobnVtKTtcbiAgICByZXR1cm4gbnVtLmNsb25lKCkuaXhvcih0aGlzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudXhvciA9IGZ1bmN0aW9uIHV4b3IgKG51bSkge1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHJldHVybiB0aGlzLmNsb25lKCkuaXV4b3IobnVtKTtcbiAgICByZXR1cm4gbnVtLmNsb25lKCkuaXV4b3IodGhpcyk7XG4gIH07XG5cbiAgLy8gTm90IGBgdGhpc2BgIHdpdGggYGB3aWR0aGBgIGJpdHdpZHRoXG4gIEJOLnByb3RvdHlwZS5pbm90biA9IGZ1bmN0aW9uIGlub3RuICh3aWR0aCkge1xuICAgIGFzc2VydCh0eXBlb2Ygd2lkdGggPT09ICdudW1iZXInICYmIHdpZHRoID49IDApO1xuXG4gICAgdmFyIGJ5dGVzTmVlZGVkID0gTWF0aC5jZWlsKHdpZHRoIC8gMjYpIHwgMDtcbiAgICB2YXIgYml0c0xlZnQgPSB3aWR0aCAlIDI2O1xuXG4gICAgLy8gRXh0ZW5kIHRoZSBidWZmZXIgd2l0aCBsZWFkaW5nIHplcm9lc1xuICAgIHRoaXMuX2V4cGFuZChieXRlc05lZWRlZCk7XG5cbiAgICBpZiAoYml0c0xlZnQgPiAwKSB7XG4gICAgICBieXRlc05lZWRlZC0tO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSBjb21wbGV0ZSB3b3Jkc1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXNOZWVkZWQ7IGkrKykge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IH50aGlzLndvcmRzW2ldICYgMHgzZmZmZmZmO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSB0aGUgcmVzaWR1ZVxuICAgIGlmIChiaXRzTGVmdCA+IDApIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB+dGhpcy53b3Jkc1tpXSAmICgweDNmZmZmZmYgPj4gKDI2IC0gYml0c0xlZnQpKTtcbiAgICB9XG5cbiAgICAvLyBBbmQgcmVtb3ZlIGxlYWRpbmcgemVyb2VzXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubm90biA9IGZ1bmN0aW9uIG5vdG4gKHdpZHRoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pbm90bih3aWR0aCk7XG4gIH07XG5cbiAgLy8gU2V0IGBiaXRgIG9mIGB0aGlzYFxuICBCTi5wcm90b3R5cGUuc2V0biA9IGZ1bmN0aW9uIHNldG4gKGJpdCwgdmFsKSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBiaXQgPT09ICdudW1iZXInICYmIGJpdCA+PSAwKTtcblxuICAgIHZhciBvZmYgPSAoYml0IC8gMjYpIHwgMDtcbiAgICB2YXIgd2JpdCA9IGJpdCAlIDI2O1xuXG4gICAgdGhpcy5fZXhwYW5kKG9mZiArIDEpO1xuXG4gICAgaWYgKHZhbCkge1xuICAgICAgdGhpcy53b3Jkc1tvZmZdID0gdGhpcy53b3Jkc1tvZmZdIHwgKDEgPDwgd2JpdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMud29yZHNbb2ZmXSA9IHRoaXMud29yZHNbb2ZmXSAmIH4oMSA8PCB3Yml0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIC8vIEFkZCBgbnVtYCB0byBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLmlhZGQgPSBmdW5jdGlvbiBpYWRkIChudW0pIHtcbiAgICB2YXIgcjtcblxuICAgIC8vIG5lZ2F0aXZlICsgcG9zaXRpdmVcbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCAmJiBudW0ubmVnYXRpdmUgPT09IDApIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgICAgciA9IHRoaXMuaXN1YihudW0pO1xuICAgICAgdGhpcy5uZWdhdGl2ZSBePSAxO1xuICAgICAgcmV0dXJuIHRoaXMuX25vcm1TaWduKCk7XG5cbiAgICAvLyBwb3NpdGl2ZSArIG5lZ2F0aXZlXG4gICAgfSBlbHNlIGlmICh0aGlzLm5lZ2F0aXZlID09PSAwICYmIG51bS5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgbnVtLm5lZ2F0aXZlID0gMDtcbiAgICAgIHIgPSB0aGlzLmlzdWIobnVtKTtcbiAgICAgIG51bS5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gci5fbm9ybVNpZ24oKTtcbiAgICB9XG5cbiAgICAvLyBhLmxlbmd0aCA+IGIubGVuZ3RoXG4gICAgdmFyIGEsIGI7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkge1xuICAgICAgYSA9IHRoaXM7XG4gICAgICBiID0gbnVtO1xuICAgIH0gZWxzZSB7XG4gICAgICBhID0gbnVtO1xuICAgICAgYiA9IHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHIgPSAoYS53b3Jkc1tpXSB8IDApICsgKGIud29yZHNbaV0gfCAwKSArIGNhcnJ5O1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHIgJiAweDNmZmZmZmY7XG4gICAgICBjYXJyeSA9IHIgPj4+IDI2O1xuICAgIH1cbiAgICBmb3IgKDsgY2FycnkgIT09IDAgJiYgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIHIgPSAoYS53b3Jkc1tpXSB8IDApICsgY2Fycnk7XG4gICAgICB0aGlzLndvcmRzW2ldID0gciAmIDB4M2ZmZmZmZjtcbiAgICAgIGNhcnJ5ID0gciA+Pj4gMjY7XG4gICAgfVxuXG4gICAgdGhpcy5sZW5ndGggPSBhLmxlbmd0aDtcbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIHRoaXMud29yZHNbdGhpcy5sZW5ndGhdID0gY2Fycnk7XG4gICAgICB0aGlzLmxlbmd0aCsrO1xuICAgIC8vIENvcHkgdGhlIHJlc3Qgb2YgdGhlIHdvcmRzXG4gICAgfSBlbHNlIGlmIChhICE9PSB0aGlzKSB7XG4gICAgICBmb3IgKDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IGEud29yZHNbaV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gQWRkIGBudW1gIHRvIGB0aGlzYFxuICBCTi5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gYWRkIChudW0pIHtcbiAgICB2YXIgcmVzO1xuICAgIGlmIChudW0ubmVnYXRpdmUgIT09IDAgJiYgdGhpcy5uZWdhdGl2ZSA9PT0gMCkge1xuICAgICAgbnVtLm5lZ2F0aXZlID0gMDtcbiAgICAgIHJlcyA9IHRoaXMuc3ViKG51bSk7XG4gICAgICBudW0ubmVnYXRpdmUgXj0gMTtcbiAgICAgIHJldHVybiByZXM7XG4gICAgfSBlbHNlIGlmIChudW0ubmVnYXRpdmUgPT09IDAgJiYgdGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDA7XG4gICAgICByZXMgPSBudW0uc3ViKHRoaXMpO1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHJldHVybiB0aGlzLmNsb25lKCkuaWFkZChudW0pO1xuXG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLmlhZGQodGhpcyk7XG4gIH07XG5cbiAgLy8gU3VidHJhY3QgYG51bWAgZnJvbSBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLmlzdWIgPSBmdW5jdGlvbiBpc3ViIChudW0pIHtcbiAgICAvLyB0aGlzIC0gKC1udW0pID0gdGhpcyArIG51bVxuICAgIGlmIChudW0ubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIG51bS5uZWdhdGl2ZSA9IDA7XG4gICAgICB2YXIgciA9IHRoaXMuaWFkZChudW0pO1xuICAgICAgbnVtLm5lZ2F0aXZlID0gMTtcbiAgICAgIHJldHVybiByLl9ub3JtU2lnbigpO1xuXG4gICAgLy8gLXRoaXMgLSBudW0gPSAtKHRoaXMgKyBudW0pXG4gICAgfSBlbHNlIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICAgIHRoaXMuaWFkZChudW0pO1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gdGhpcy5fbm9ybVNpZ24oKTtcbiAgICB9XG5cbiAgICAvLyBBdCB0aGlzIHBvaW50IGJvdGggbnVtYmVycyBhcmUgcG9zaXRpdmVcbiAgICB2YXIgY21wID0gdGhpcy5jbXAobnVtKTtcblxuICAgIC8vIE9wdGltaXphdGlvbiAtIHplcm9pZnlcbiAgICBpZiAoY21wID09PSAwKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICAgIHRoaXMubGVuZ3RoID0gMTtcbiAgICAgIHRoaXMud29yZHNbMF0gPSAwO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gYSA+IGJcbiAgICB2YXIgYSwgYjtcbiAgICBpZiAoY21wID4gMCkge1xuICAgICAgYSA9IHRoaXM7XG4gICAgICBiID0gbnVtO1xuICAgIH0gZWxzZSB7XG4gICAgICBhID0gbnVtO1xuICAgICAgYiA9IHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHIgPSAoYS53b3Jkc1tpXSB8IDApIC0gKGIud29yZHNbaV0gfCAwKSArIGNhcnJ5O1xuICAgICAgY2FycnkgPSByID4+IDI2O1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHIgJiAweDNmZmZmZmY7XG4gICAgfVxuICAgIGZvciAoOyBjYXJyeSAhPT0gMCAmJiBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgciA9IChhLndvcmRzW2ldIHwgMCkgKyBjYXJyeTtcbiAgICAgIGNhcnJ5ID0gciA+PiAyNjtcbiAgICAgIHRoaXMud29yZHNbaV0gPSByICYgMHgzZmZmZmZmO1xuICAgIH1cblxuICAgIC8vIENvcHkgcmVzdCBvZiB0aGUgd29yZHNcbiAgICBpZiAoY2FycnkgPT09IDAgJiYgaSA8IGEubGVuZ3RoICYmIGEgIT09IHRoaXMpIHtcbiAgICAgIGZvciAoOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLndvcmRzW2ldID0gYS53b3Jkc1tpXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmxlbmd0aCA9IE1hdGgubWF4KHRoaXMubGVuZ3RoLCBpKTtcblxuICAgIGlmIChhICE9PSB0aGlzKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIC8vIFN1YnRyYWN0IGBudW1gIGZyb20gYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5zdWIgPSBmdW5jdGlvbiBzdWIgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaXN1YihudW0pO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHNtYWxsTXVsVG8gKHNlbGYsIG51bSwgb3V0KSB7XG4gICAgb3V0Lm5lZ2F0aXZlID0gbnVtLm5lZ2F0aXZlIF4gc2VsZi5uZWdhdGl2ZTtcbiAgICB2YXIgbGVuID0gKHNlbGYubGVuZ3RoICsgbnVtLmxlbmd0aCkgfCAwO1xuICAgIG91dC5sZW5ndGggPSBsZW47XG4gICAgbGVuID0gKGxlbiAtIDEpIHwgMDtcblxuICAgIC8vIFBlZWwgb25lIGl0ZXJhdGlvbiAoY29tcGlsZXIgY2FuJ3QgZG8gaXQsIGJlY2F1c2Ugb2YgY29kZSBjb21wbGV4aXR5KVxuICAgIHZhciBhID0gc2VsZi53b3Jkc1swXSB8IDA7XG4gICAgdmFyIGIgPSBudW0ud29yZHNbMF0gfCAwO1xuICAgIHZhciByID0gYSAqIGI7XG5cbiAgICB2YXIgbG8gPSByICYgMHgzZmZmZmZmO1xuICAgIHZhciBjYXJyeSA9IChyIC8gMHg0MDAwMDAwKSB8IDA7XG4gICAgb3V0LndvcmRzWzBdID0gbG87XG5cbiAgICBmb3IgKHZhciBrID0gMTsgayA8IGxlbjsgaysrKSB7XG4gICAgICAvLyBTdW0gYWxsIHdvcmRzIHdpdGggdGhlIHNhbWUgYGkgKyBqID0ga2AgYW5kIGFjY3VtdWxhdGUgYG5jYXJyeWAsXG4gICAgICAvLyBub3RlIHRoYXQgbmNhcnJ5IGNvdWxkIGJlID49IDB4M2ZmZmZmZlxuICAgICAgdmFyIG5jYXJyeSA9IGNhcnJ5ID4+PiAyNjtcbiAgICAgIHZhciByd29yZCA9IGNhcnJ5ICYgMHgzZmZmZmZmO1xuICAgICAgdmFyIG1heEogPSBNYXRoLm1pbihrLCBudW0ubGVuZ3RoIC0gMSk7XG4gICAgICBmb3IgKHZhciBqID0gTWF0aC5tYXgoMCwgayAtIHNlbGYubGVuZ3RoICsgMSk7IGogPD0gbWF4SjsgaisrKSB7XG4gICAgICAgIHZhciBpID0gKGsgLSBqKSB8IDA7XG4gICAgICAgIGEgPSBzZWxmLndvcmRzW2ldIHwgMDtcbiAgICAgICAgYiA9IG51bS53b3Jkc1tqXSB8IDA7XG4gICAgICAgIHIgPSBhICogYiArIHJ3b3JkO1xuICAgICAgICBuY2FycnkgKz0gKHIgLyAweDQwMDAwMDApIHwgMDtcbiAgICAgICAgcndvcmQgPSByICYgMHgzZmZmZmZmO1xuICAgICAgfVxuICAgICAgb3V0LndvcmRzW2tdID0gcndvcmQgfCAwO1xuICAgICAgY2FycnkgPSBuY2FycnkgfCAwO1xuICAgIH1cbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIG91dC53b3Jkc1trXSA9IGNhcnJ5IHwgMDtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0Lmxlbmd0aC0tO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQuc3RyaXAoKTtcbiAgfVxuXG4gIC8vIFRPRE8oaW5kdXRueSk6IGl0IG1heSBiZSByZWFzb25hYmxlIHRvIG9taXQgaXQgZm9yIHVzZXJzIHdobyBkb24ndCBuZWVkXG4gIC8vIHRvIHdvcmsgd2l0aCAyNTYtYml0IG51bWJlcnMsIG90aGVyd2lzZSBpdCBnaXZlcyAyMCUgaW1wcm92ZW1lbnQgZm9yIDI1Ni1iaXRcbiAgLy8gbXVsdGlwbGljYXRpb24gKGxpa2UgZWxsaXB0aWMgc2VjcDI1NmsxKS5cbiAgdmFyIGNvbWIxME11bFRvID0gZnVuY3Rpb24gY29tYjEwTXVsVG8gKHNlbGYsIG51bSwgb3V0KSB7XG4gICAgdmFyIGEgPSBzZWxmLndvcmRzO1xuICAgIHZhciBiID0gbnVtLndvcmRzO1xuICAgIHZhciBvID0gb3V0LndvcmRzO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgbG87XG4gICAgdmFyIG1pZDtcbiAgICB2YXIgaGk7XG4gICAgdmFyIGEwID0gYVswXSB8IDA7XG4gICAgdmFyIGFsMCA9IGEwICYgMHgxZmZmO1xuICAgIHZhciBhaDAgPSBhMCA+Pj4gMTM7XG4gICAgdmFyIGExID0gYVsxXSB8IDA7XG4gICAgdmFyIGFsMSA9IGExICYgMHgxZmZmO1xuICAgIHZhciBhaDEgPSBhMSA+Pj4gMTM7XG4gICAgdmFyIGEyID0gYVsyXSB8IDA7XG4gICAgdmFyIGFsMiA9IGEyICYgMHgxZmZmO1xuICAgIHZhciBhaDIgPSBhMiA+Pj4gMTM7XG4gICAgdmFyIGEzID0gYVszXSB8IDA7XG4gICAgdmFyIGFsMyA9IGEzICYgMHgxZmZmO1xuICAgIHZhciBhaDMgPSBhMyA+Pj4gMTM7XG4gICAgdmFyIGE0ID0gYVs0XSB8IDA7XG4gICAgdmFyIGFsNCA9IGE0ICYgMHgxZmZmO1xuICAgIHZhciBhaDQgPSBhNCA+Pj4gMTM7XG4gICAgdmFyIGE1ID0gYVs1XSB8IDA7XG4gICAgdmFyIGFsNSA9IGE1ICYgMHgxZmZmO1xuICAgIHZhciBhaDUgPSBhNSA+Pj4gMTM7XG4gICAgdmFyIGE2ID0gYVs2XSB8IDA7XG4gICAgdmFyIGFsNiA9IGE2ICYgMHgxZmZmO1xuICAgIHZhciBhaDYgPSBhNiA+Pj4gMTM7XG4gICAgdmFyIGE3ID0gYVs3XSB8IDA7XG4gICAgdmFyIGFsNyA9IGE3ICYgMHgxZmZmO1xuICAgIHZhciBhaDcgPSBhNyA+Pj4gMTM7XG4gICAgdmFyIGE4ID0gYVs4XSB8IDA7XG4gICAgdmFyIGFsOCA9IGE4ICYgMHgxZmZmO1xuICAgIHZhciBhaDggPSBhOCA+Pj4gMTM7XG4gICAgdmFyIGE5ID0gYVs5XSB8IDA7XG4gICAgdmFyIGFsOSA9IGE5ICYgMHgxZmZmO1xuICAgIHZhciBhaDkgPSBhOSA+Pj4gMTM7XG4gICAgdmFyIGIwID0gYlswXSB8IDA7XG4gICAgdmFyIGJsMCA9IGIwICYgMHgxZmZmO1xuICAgIHZhciBiaDAgPSBiMCA+Pj4gMTM7XG4gICAgdmFyIGIxID0gYlsxXSB8IDA7XG4gICAgdmFyIGJsMSA9IGIxICYgMHgxZmZmO1xuICAgIHZhciBiaDEgPSBiMSA+Pj4gMTM7XG4gICAgdmFyIGIyID0gYlsyXSB8IDA7XG4gICAgdmFyIGJsMiA9IGIyICYgMHgxZmZmO1xuICAgIHZhciBiaDIgPSBiMiA+Pj4gMTM7XG4gICAgdmFyIGIzID0gYlszXSB8IDA7XG4gICAgdmFyIGJsMyA9IGIzICYgMHgxZmZmO1xuICAgIHZhciBiaDMgPSBiMyA+Pj4gMTM7XG4gICAgdmFyIGI0ID0gYls0XSB8IDA7XG4gICAgdmFyIGJsNCA9IGI0ICYgMHgxZmZmO1xuICAgIHZhciBiaDQgPSBiNCA+Pj4gMTM7XG4gICAgdmFyIGI1ID0gYls1XSB8IDA7XG4gICAgdmFyIGJsNSA9IGI1ICYgMHgxZmZmO1xuICAgIHZhciBiaDUgPSBiNSA+Pj4gMTM7XG4gICAgdmFyIGI2ID0gYls2XSB8IDA7XG4gICAgdmFyIGJsNiA9IGI2ICYgMHgxZmZmO1xuICAgIHZhciBiaDYgPSBiNiA+Pj4gMTM7XG4gICAgdmFyIGI3ID0gYls3XSB8IDA7XG4gICAgdmFyIGJsNyA9IGI3ICYgMHgxZmZmO1xuICAgIHZhciBiaDcgPSBiNyA+Pj4gMTM7XG4gICAgdmFyIGI4ID0gYls4XSB8IDA7XG4gICAgdmFyIGJsOCA9IGI4ICYgMHgxZmZmO1xuICAgIHZhciBiaDggPSBiOCA+Pj4gMTM7XG4gICAgdmFyIGI5ID0gYls5XSB8IDA7XG4gICAgdmFyIGJsOSA9IGI5ICYgMHgxZmZmO1xuICAgIHZhciBiaDkgPSBiOSA+Pj4gMTM7XG5cbiAgICBvdXQubmVnYXRpdmUgPSBzZWxmLm5lZ2F0aXZlIF4gbnVtLm5lZ2F0aXZlO1xuICAgIG91dC5sZW5ndGggPSAxOTtcbiAgICAvKiBrID0gMCAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsMCwgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWwwLCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgwLCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWgwLCBiaDApO1xuICAgIHZhciB3MCA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzAgPj4+IDI2KSkgfCAwO1xuICAgIHcwICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMSAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsMSwgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWwxLCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWgxLCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoMSkpIHwgMDtcbiAgICB2YXIgdzEgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxID4+PiAyNikpIHwgMDtcbiAgICB3MSAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDIgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDIsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsMiwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMiwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoMiwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmgyKSkgfCAwO1xuICAgIHZhciB3MiA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzIgPj4+IDI2KSkgfCAwO1xuICAgIHcyICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMyAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsMywgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWwzLCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgzLCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWgzLCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMiwgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwyLCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDIsIGJoMSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmgzKSkgfCAwO1xuICAgIHZhciB3MyA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzMgPj4+IDI2KSkgfCAwO1xuICAgIHczICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gNCAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsNCwgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw0LCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg0LCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoMSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoNCkpIHwgMDtcbiAgICB2YXIgdzQgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc0ID4+PiAyNikpIHwgMDtcbiAgICB3NCAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDUgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDUsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsNSwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoNSwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDQsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNCwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg0LCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwzLCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDMsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMywgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMiwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwyLCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDIsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmg1KSkgfCAwO1xuICAgIHZhciB3NSA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzUgPj4+IDI2KSkgfCAwO1xuICAgIHc1ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gNiAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsNiwgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw2LCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg2LCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNSwgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw1LCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDUsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDUsIGJoMSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDQsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNCwgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg0LCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwzLCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDMsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMywgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMiwgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwyLCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDIsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmg2KSkgfCAwO1xuICAgIHZhciB3NiA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzYgPj4+IDI2KSkgfCAwO1xuICAgIHc2ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gNyAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsNywgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw3LCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg3LCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg3LCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoMSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoNykpIHwgMDtcbiAgICB2YXIgdzcgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc3ID4+PiAyNikpIHwgMDtcbiAgICB3NyAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDggKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDgsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOCwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOCwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDcsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNywgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg3LCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg3LCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw2LCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDYsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNiwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNiwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNSwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw1LCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDUsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDUsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDQsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNCwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg0LCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwzLCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDMsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMywgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMiwgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwyLCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDIsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmg4KSkgfCAwO1xuICAgIHZhciB3OCA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzggPj4+IDI2KSkgfCAwO1xuICAgIHc4ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gOSAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsOSwgYmwwKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw5LCBiaDApO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg5LCBibDApKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg5LCBiaDApO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsOCwgYmwxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw4LCBiaDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDgsIGJsMSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDgsIGJoMSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDcsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNywgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg3LCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg3LCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw2LCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDYsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNiwgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNiwgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNSwgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw1LCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDUsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDUsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDQsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNCwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg0LCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwzLCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDMsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMywgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMiwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwyLCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDIsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDEsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMSwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgxLCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgxLCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwwLCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDAsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMCwgYmg5KSkgfCAwO1xuICAgIHZhciB3OSA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzkgPj4+IDI2KSkgfCAwO1xuICAgIHc5ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTAgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsMSk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmgxKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmwxKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmgxKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmgyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDIpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDIpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTAgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxMCA+Pj4gMjYpKSB8IDA7XG4gICAgdzEwICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTEgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsMik7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmgyKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmwyKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmgyKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmgzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDMpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDMpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw0KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg0KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsNSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoNSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDYpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDYpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw3KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg3KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsOCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoOCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDkpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDkpKSB8IDA7XG4gICAgdmFyIHcxMSA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzExID4+PiAyNikpIHwgMDtcbiAgICB3MTEgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSAxMiAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsOSwgYmwzKTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw5LCBiaDMpO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg5LCBibDMpKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg5LCBiaDMpO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsOCwgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw4LCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDgsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDgsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDcsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNywgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg3LCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg3LCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw2LCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDYsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNiwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNiwgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNSwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw1LCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDUsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDUsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDQsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNCwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg0LCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg0LCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwzLCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDMsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMywgYmg5KSkgfCAwO1xuICAgIHZhciB3MTIgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxMiA+Pj4gMjYpKSB8IDA7XG4gICAgdzEyICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTMgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsNCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg0KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw0KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg0KTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTMgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxMyA+Pj4gMjYpKSB8IDA7XG4gICAgdzEzICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTQgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsNSk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg1KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw1KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg1KTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDYpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDYpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw3KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg3KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsOCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoOCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDkpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDkpKSB8IDA7XG4gICAgdmFyIHcxNCA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzE0ID4+PiAyNikpIHwgMDtcbiAgICB3MTQgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSAxNSAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsOSwgYmw2KTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw5LCBiaDYpO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg5LCBibDYpKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg5LCBiaDYpO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsOCwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw4LCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDgsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDgsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDcsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNywgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg3LCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg3LCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw2LCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDYsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNiwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNiwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTUgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxNSA+Pj4gMjYpKSB8IDA7XG4gICAgdzE1ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTYgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsNyk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg3KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw3KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg3KTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg5KSkgfCAwO1xuICAgIHZhciB3MTYgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxNiA+Pj4gMjYpKSB8IDA7XG4gICAgdzE2ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTcgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsOCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg4KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw4KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg4KTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDkpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDkpKSB8IDA7XG4gICAgdmFyIHcxNyA9ICgoKGMgKyBsbykgfCAwKSArICgobWlkICYgMHgxZmZmKSA8PCAxMykpIHwgMDtcbiAgICBjID0gKCgoaGkgKyAobWlkID4+PiAxMykpIHwgMCkgKyAodzE3ID4+PiAyNikpIHwgMDtcbiAgICB3MTcgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSAxOCAqL1xuICAgIGxvID0gTWF0aC5pbXVsKGFsOSwgYmw5KTtcbiAgICBtaWQgPSBNYXRoLmltdWwoYWw5LCBiaDkpO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg5LCBibDkpKSB8IDA7XG4gICAgaGkgPSBNYXRoLmltdWwoYWg5LCBiaDkpO1xuICAgIHZhciB3MTggPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxOCA+Pj4gMjYpKSB8IDA7XG4gICAgdzE4ICY9IDB4M2ZmZmZmZjtcbiAgICBvWzBdID0gdzA7XG4gICAgb1sxXSA9IHcxO1xuICAgIG9bMl0gPSB3MjtcbiAgICBvWzNdID0gdzM7XG4gICAgb1s0XSA9IHc0O1xuICAgIG9bNV0gPSB3NTtcbiAgICBvWzZdID0gdzY7XG4gICAgb1s3XSA9IHc3O1xuICAgIG9bOF0gPSB3ODtcbiAgICBvWzldID0gdzk7XG4gICAgb1sxMF0gPSB3MTA7XG4gICAgb1sxMV0gPSB3MTE7XG4gICAgb1sxMl0gPSB3MTI7XG4gICAgb1sxM10gPSB3MTM7XG4gICAgb1sxNF0gPSB3MTQ7XG4gICAgb1sxNV0gPSB3MTU7XG4gICAgb1sxNl0gPSB3MTY7XG4gICAgb1sxN10gPSB3MTc7XG4gICAgb1sxOF0gPSB3MTg7XG4gICAgaWYgKGMgIT09IDApIHtcbiAgICAgIG9bMTldID0gYztcbiAgICAgIG91dC5sZW5ndGgrKztcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfTtcblxuICAvLyBQb2x5ZmlsbCBjb21iXG4gIGlmICghTWF0aC5pbXVsKSB7XG4gICAgY29tYjEwTXVsVG8gPSBzbWFsbE11bFRvO1xuICB9XG5cbiAgZnVuY3Rpb24gYmlnTXVsVG8gKHNlbGYsIG51bSwgb3V0KSB7XG4gICAgb3V0Lm5lZ2F0aXZlID0gbnVtLm5lZ2F0aXZlIF4gc2VsZi5uZWdhdGl2ZTtcbiAgICBvdXQubGVuZ3RoID0gc2VsZi5sZW5ndGggKyBudW0ubGVuZ3RoO1xuXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICB2YXIgaG5jYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBvdXQubGVuZ3RoIC0gMTsgaysrKSB7XG4gICAgICAvLyBTdW0gYWxsIHdvcmRzIHdpdGggdGhlIHNhbWUgYGkgKyBqID0ga2AgYW5kIGFjY3VtdWxhdGUgYG5jYXJyeWAsXG4gICAgICAvLyBub3RlIHRoYXQgbmNhcnJ5IGNvdWxkIGJlID49IDB4M2ZmZmZmZlxuICAgICAgdmFyIG5jYXJyeSA9IGhuY2Fycnk7XG4gICAgICBobmNhcnJ5ID0gMDtcbiAgICAgIHZhciByd29yZCA9IGNhcnJ5ICYgMHgzZmZmZmZmO1xuICAgICAgdmFyIG1heEogPSBNYXRoLm1pbihrLCBudW0ubGVuZ3RoIC0gMSk7XG4gICAgICBmb3IgKHZhciBqID0gTWF0aC5tYXgoMCwgayAtIHNlbGYubGVuZ3RoICsgMSk7IGogPD0gbWF4SjsgaisrKSB7XG4gICAgICAgIHZhciBpID0gayAtIGo7XG4gICAgICAgIHZhciBhID0gc2VsZi53b3Jkc1tpXSB8IDA7XG4gICAgICAgIHZhciBiID0gbnVtLndvcmRzW2pdIHwgMDtcbiAgICAgICAgdmFyIHIgPSBhICogYjtcblxuICAgICAgICB2YXIgbG8gPSByICYgMHgzZmZmZmZmO1xuICAgICAgICBuY2FycnkgPSAobmNhcnJ5ICsgKChyIC8gMHg0MDAwMDAwKSB8IDApKSB8IDA7XG4gICAgICAgIGxvID0gKGxvICsgcndvcmQpIHwgMDtcbiAgICAgICAgcndvcmQgPSBsbyAmIDB4M2ZmZmZmZjtcbiAgICAgICAgbmNhcnJ5ID0gKG5jYXJyeSArIChsbyA+Pj4gMjYpKSB8IDA7XG5cbiAgICAgICAgaG5jYXJyeSArPSBuY2FycnkgPj4+IDI2O1xuICAgICAgICBuY2FycnkgJj0gMHgzZmZmZmZmO1xuICAgICAgfVxuICAgICAgb3V0LndvcmRzW2tdID0gcndvcmQ7XG4gICAgICBjYXJyeSA9IG5jYXJyeTtcbiAgICAgIG5jYXJyeSA9IGhuY2Fycnk7XG4gICAgfVxuICAgIGlmIChjYXJyeSAhPT0gMCkge1xuICAgICAgb3V0LndvcmRzW2tdID0gY2Fycnk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dC5sZW5ndGgtLTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0LnN0cmlwKCk7XG4gIH1cblxuICBmdW5jdGlvbiBqdW1ib011bFRvIChzZWxmLCBudW0sIG91dCkge1xuICAgIHZhciBmZnRtID0gbmV3IEZGVE0oKTtcbiAgICByZXR1cm4gZmZ0bS5tdWxwKHNlbGYsIG51bSwgb3V0KTtcbiAgfVxuXG4gIEJOLnByb3RvdHlwZS5tdWxUbyA9IGZ1bmN0aW9uIG11bFRvIChudW0sIG91dCkge1xuICAgIHZhciByZXM7XG4gICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoICsgbnVtLmxlbmd0aDtcbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDEwICYmIG51bS5sZW5ndGggPT09IDEwKSB7XG4gICAgICByZXMgPSBjb21iMTBNdWxUbyh0aGlzLCBudW0sIG91dCk7XG4gICAgfSBlbHNlIGlmIChsZW4gPCA2Mykge1xuICAgICAgcmVzID0gc21hbGxNdWxUbyh0aGlzLCBudW0sIG91dCk7XG4gICAgfSBlbHNlIGlmIChsZW4gPCAxMDI0KSB7XG4gICAgICByZXMgPSBiaWdNdWxUbyh0aGlzLCBudW0sIG91dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlcyA9IGp1bWJvTXVsVG8odGhpcywgbnVtLCBvdXQpO1xuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgLy8gQ29vbGV5LVR1a2V5IGFsZ29yaXRobSBmb3IgRkZUXG4gIC8vIHNsaWdodGx5IHJldmlzaXRlZCB0byByZWx5IG9uIGxvb3BpbmcgaW5zdGVhZCBvZiByZWN1cnNpb25cblxuICBmdW5jdGlvbiBGRlRNICh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICB9XG5cbiAgRkZUTS5wcm90b3R5cGUubWFrZVJCVCA9IGZ1bmN0aW9uIG1ha2VSQlQgKE4pIHtcbiAgICB2YXIgdCA9IG5ldyBBcnJheShOKTtcbiAgICB2YXIgbCA9IEJOLnByb3RvdHlwZS5fY291bnRCaXRzKE4pIC0gMTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IE47IGkrKykge1xuICAgICAgdFtpXSA9IHRoaXMucmV2QmluKGksIGwsIE4pO1xuICAgIH1cblxuICAgIHJldHVybiB0O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYmluYXJ5LXJldmVyc2VkIHJlcHJlc2VudGF0aW9uIG9mIGB4YFxuICBGRlRNLnByb3RvdHlwZS5yZXZCaW4gPSBmdW5jdGlvbiByZXZCaW4gKHgsIGwsIE4pIHtcbiAgICBpZiAoeCA9PT0gMCB8fCB4ID09PSBOIC0gMSkgcmV0dXJuIHg7XG5cbiAgICB2YXIgcmIgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICByYiB8PSAoeCAmIDEpIDw8IChsIC0gaSAtIDEpO1xuICAgICAgeCA+Pj0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmI7XG4gIH07XG5cbiAgLy8gUGVyZm9ybXMgXCJ0d2VlZGxpbmdcIiBwaGFzZSwgdGhlcmVmb3JlICdlbXVsYXRpbmcnXG4gIC8vIGJlaGF2aW91ciBvZiB0aGUgcmVjdXJzaXZlIGFsZ29yaXRobVxuICBGRlRNLnByb3RvdHlwZS5wZXJtdXRlID0gZnVuY3Rpb24gcGVybXV0ZSAocmJ0LCByd3MsIGl3cywgcnR3cywgaXR3cywgTikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICBydHdzW2ldID0gcndzW3JidFtpXV07XG4gICAgICBpdHdzW2ldID0gaXdzW3JidFtpXV07XG4gICAgfVxuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLnRyYW5zZm9ybSA9IGZ1bmN0aW9uIHRyYW5zZm9ybSAocndzLCBpd3MsIHJ0d3MsIGl0d3MsIE4sIHJidCkge1xuICAgIHRoaXMucGVybXV0ZShyYnQsIHJ3cywgaXdzLCBydHdzLCBpdHdzLCBOKTtcblxuICAgIGZvciAodmFyIHMgPSAxOyBzIDwgTjsgcyA8PD0gMSkge1xuICAgICAgdmFyIGwgPSBzIDw8IDE7XG5cbiAgICAgIHZhciBydHdkZiA9IE1hdGguY29zKDIgKiBNYXRoLlBJIC8gbCk7XG4gICAgICB2YXIgaXR3ZGYgPSBNYXRoLnNpbigyICogTWF0aC5QSSAvIGwpO1xuXG4gICAgICBmb3IgKHZhciBwID0gMDsgcCA8IE47IHAgKz0gbCkge1xuICAgICAgICB2YXIgcnR3ZGZfID0gcnR3ZGY7XG4gICAgICAgIHZhciBpdHdkZl8gPSBpdHdkZjtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHM7IGorKykge1xuICAgICAgICAgIHZhciByZSA9IHJ0d3NbcCArIGpdO1xuICAgICAgICAgIHZhciBpZSA9IGl0d3NbcCArIGpdO1xuXG4gICAgICAgICAgdmFyIHJvID0gcnR3c1twICsgaiArIHNdO1xuICAgICAgICAgIHZhciBpbyA9IGl0d3NbcCArIGogKyBzXTtcblxuICAgICAgICAgIHZhciByeCA9IHJ0d2RmXyAqIHJvIC0gaXR3ZGZfICogaW87XG5cbiAgICAgICAgICBpbyA9IHJ0d2RmXyAqIGlvICsgaXR3ZGZfICogcm87XG4gICAgICAgICAgcm8gPSByeDtcblxuICAgICAgICAgIHJ0d3NbcCArIGpdID0gcmUgKyBybztcbiAgICAgICAgICBpdHdzW3AgKyBqXSA9IGllICsgaW87XG5cbiAgICAgICAgICBydHdzW3AgKyBqICsgc10gPSByZSAtIHJvO1xuICAgICAgICAgIGl0d3NbcCArIGogKyBzXSA9IGllIC0gaW87XG5cbiAgICAgICAgICAvKiBqc2hpbnQgbWF4ZGVwdGggOiBmYWxzZSAqL1xuICAgICAgICAgIGlmIChqICE9PSBsKSB7XG4gICAgICAgICAgICByeCA9IHJ0d2RmICogcnR3ZGZfIC0gaXR3ZGYgKiBpdHdkZl87XG5cbiAgICAgICAgICAgIGl0d2RmXyA9IHJ0d2RmICogaXR3ZGZfICsgaXR3ZGYgKiBydHdkZl87XG4gICAgICAgICAgICBydHdkZl8gPSByeDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgRkZUTS5wcm90b3R5cGUuZ3Vlc3NMZW4xM2IgPSBmdW5jdGlvbiBndWVzc0xlbjEzYiAobiwgbSkge1xuICAgIHZhciBOID0gTWF0aC5tYXgobSwgbikgfCAxO1xuICAgIHZhciBvZGQgPSBOICYgMTtcbiAgICB2YXIgaSA9IDA7XG4gICAgZm9yIChOID0gTiAvIDIgfCAwOyBOOyBOID0gTiA+Pj4gMSkge1xuICAgICAgaSsrO1xuICAgIH1cblxuICAgIHJldHVybiAxIDw8IGkgKyAxICsgb2RkO1xuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLmNvbmp1Z2F0ZSA9IGZ1bmN0aW9uIGNvbmp1Z2F0ZSAocndzLCBpd3MsIE4pIHtcbiAgICBpZiAoTiA8PSAxKSByZXR1cm47XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IE4gLyAyOyBpKyspIHtcbiAgICAgIHZhciB0ID0gcndzW2ldO1xuXG4gICAgICByd3NbaV0gPSByd3NbTiAtIGkgLSAxXTtcbiAgICAgIHJ3c1tOIC0gaSAtIDFdID0gdDtcblxuICAgICAgdCA9IGl3c1tpXTtcblxuICAgICAgaXdzW2ldID0gLWl3c1tOIC0gaSAtIDFdO1xuICAgICAgaXdzW04gLSBpIC0gMV0gPSAtdDtcbiAgICB9XG4gIH07XG5cbiAgRkZUTS5wcm90b3R5cGUubm9ybWFsaXplMTNiID0gZnVuY3Rpb24gbm9ybWFsaXplMTNiICh3cywgTikge1xuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBOIC8gMjsgaSsrKSB7XG4gICAgICB2YXIgdyA9IE1hdGgucm91bmQod3NbMiAqIGkgKyAxXSAvIE4pICogMHgyMDAwICtcbiAgICAgICAgTWF0aC5yb3VuZCh3c1syICogaV0gLyBOKSArXG4gICAgICAgIGNhcnJ5O1xuXG4gICAgICB3c1tpXSA9IHcgJiAweDNmZmZmZmY7XG5cbiAgICAgIGlmICh3IDwgMHg0MDAwMDAwKSB7XG4gICAgICAgIGNhcnJ5ID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhcnJ5ID0gdyAvIDB4NDAwMDAwMCB8IDA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHdzO1xuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLmNvbnZlcnQxM2IgPSBmdW5jdGlvbiBjb252ZXJ0MTNiICh3cywgbGVuLCByd3MsIE4pIHtcbiAgICB2YXIgY2FycnkgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNhcnJ5ID0gY2FycnkgKyAod3NbaV0gfCAwKTtcblxuICAgICAgcndzWzIgKiBpXSA9IGNhcnJ5ICYgMHgxZmZmOyBjYXJyeSA9IGNhcnJ5ID4+PiAxMztcbiAgICAgIHJ3c1syICogaSArIDFdID0gY2FycnkgJiAweDFmZmY7IGNhcnJ5ID0gY2FycnkgPj4+IDEzO1xuICAgIH1cblxuICAgIC8vIFBhZCB3aXRoIHplcm9lc1xuICAgIGZvciAoaSA9IDIgKiBsZW47IGkgPCBOOyArK2kpIHtcbiAgICAgIHJ3c1tpXSA9IDA7XG4gICAgfVxuXG4gICAgYXNzZXJ0KGNhcnJ5ID09PSAwKTtcbiAgICBhc3NlcnQoKGNhcnJ5ICYgfjB4MWZmZikgPT09IDApO1xuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLnN0dWIgPSBmdW5jdGlvbiBzdHViIChOKSB7XG4gICAgdmFyIHBoID0gbmV3IEFycmF5KE4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICBwaFtpXSA9IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBoO1xuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLm11bHAgPSBmdW5jdGlvbiBtdWxwICh4LCB5LCBvdXQpIHtcbiAgICB2YXIgTiA9IDIgKiB0aGlzLmd1ZXNzTGVuMTNiKHgubGVuZ3RoLCB5Lmxlbmd0aCk7XG5cbiAgICB2YXIgcmJ0ID0gdGhpcy5tYWtlUkJUKE4pO1xuXG4gICAgdmFyIF8gPSB0aGlzLnN0dWIoTik7XG5cbiAgICB2YXIgcndzID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciByd3N0ID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciBpd3N0ID0gbmV3IEFycmF5KE4pO1xuXG4gICAgdmFyIG5yd3MgPSBuZXcgQXJyYXkoTik7XG4gICAgdmFyIG5yd3N0ID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciBuaXdzdCA9IG5ldyBBcnJheShOKTtcblxuICAgIHZhciBybXdzID0gb3V0LndvcmRzO1xuICAgIHJtd3MubGVuZ3RoID0gTjtcblxuICAgIHRoaXMuY29udmVydDEzYih4LndvcmRzLCB4Lmxlbmd0aCwgcndzLCBOKTtcbiAgICB0aGlzLmNvbnZlcnQxM2IoeS53b3JkcywgeS5sZW5ndGgsIG5yd3MsIE4pO1xuXG4gICAgdGhpcy50cmFuc2Zvcm0ocndzLCBfLCByd3N0LCBpd3N0LCBOLCByYnQpO1xuICAgIHRoaXMudHJhbnNmb3JtKG5yd3MsIF8sIG5yd3N0LCBuaXdzdCwgTiwgcmJ0KTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICB2YXIgcnggPSByd3N0W2ldICogbnJ3c3RbaV0gLSBpd3N0W2ldICogbml3c3RbaV07XG4gICAgICBpd3N0W2ldID0gcndzdFtpXSAqIG5pd3N0W2ldICsgaXdzdFtpXSAqIG5yd3N0W2ldO1xuICAgICAgcndzdFtpXSA9IHJ4O1xuICAgIH1cblxuICAgIHRoaXMuY29uanVnYXRlKHJ3c3QsIGl3c3QsIE4pO1xuICAgIHRoaXMudHJhbnNmb3JtKHJ3c3QsIGl3c3QsIHJtd3MsIF8sIE4sIHJidCk7XG4gICAgdGhpcy5jb25qdWdhdGUocm13cywgXywgTik7XG4gICAgdGhpcy5ub3JtYWxpemUxM2Iocm13cywgTik7XG5cbiAgICBvdXQubmVnYXRpdmUgPSB4Lm5lZ2F0aXZlIF4geS5uZWdhdGl2ZTtcbiAgICBvdXQubGVuZ3RoID0geC5sZW5ndGggKyB5Lmxlbmd0aDtcbiAgICByZXR1cm4gb3V0LnN0cmlwKCk7XG4gIH07XG5cbiAgLy8gTXVsdGlwbHkgYHRoaXNgIGJ5IGBudW1gXG4gIEJOLnByb3RvdHlwZS5tdWwgPSBmdW5jdGlvbiBtdWwgKG51bSkge1xuICAgIHZhciBvdXQgPSBuZXcgQk4obnVsbCk7XG4gICAgb3V0LndvcmRzID0gbmV3IEFycmF5KHRoaXMubGVuZ3RoICsgbnVtLmxlbmd0aCk7XG4gICAgcmV0dXJuIHRoaXMubXVsVG8obnVtLCBvdXQpO1xuICB9O1xuXG4gIC8vIE11bHRpcGx5IGVtcGxveWluZyBGRlRcbiAgQk4ucHJvdG90eXBlLm11bGYgPSBmdW5jdGlvbiBtdWxmIChudW0pIHtcbiAgICB2YXIgb3V0ID0gbmV3IEJOKG51bGwpO1xuICAgIG91dC53b3JkcyA9IG5ldyBBcnJheSh0aGlzLmxlbmd0aCArIG51bS5sZW5ndGgpO1xuICAgIHJldHVybiBqdW1ib011bFRvKHRoaXMsIG51bSwgb3V0KTtcbiAgfTtcblxuICAvLyBJbi1wbGFjZSBNdWx0aXBsaWNhdGlvblxuICBCTi5wcm90b3R5cGUuaW11bCA9IGZ1bmN0aW9uIGltdWwgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkubXVsVG8obnVtLCB0aGlzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaW11bG4gPSBmdW5jdGlvbiBpbXVsbiAobnVtKSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBudW0gPT09ICdudW1iZXInKTtcbiAgICBhc3NlcnQobnVtIDwgMHg0MDAwMDAwKTtcblxuICAgIC8vIENhcnJ5XG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciB3ID0gKHRoaXMud29yZHNbaV0gfCAwKSAqIG51bTtcbiAgICAgIHZhciBsbyA9ICh3ICYgMHgzZmZmZmZmKSArIChjYXJyeSAmIDB4M2ZmZmZmZik7XG4gICAgICBjYXJyeSA+Pj0gMjY7XG4gICAgICBjYXJyeSArPSAodyAvIDB4NDAwMDAwMCkgfCAwO1xuICAgICAgLy8gTk9URTogbG8gaXMgMjdiaXQgbWF4aW11bVxuICAgICAgY2FycnkgKz0gbG8gPj4+IDI2O1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IGxvICYgMHgzZmZmZmZmO1xuICAgIH1cblxuICAgIGlmIChjYXJyeSAhPT0gMCkge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IGNhcnJ5O1xuICAgICAgdGhpcy5sZW5ndGgrKztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubXVsbiA9IGZ1bmN0aW9uIG11bG4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaW11bG4obnVtKTtcbiAgfTtcblxuICAvLyBgdGhpc2AgKiBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLnNxciA9IGZ1bmN0aW9uIHNxciAoKSB7XG4gICAgcmV0dXJuIHRoaXMubXVsKHRoaXMpO1xuICB9O1xuXG4gIC8vIGB0aGlzYCAqIGB0aGlzYCBpbi1wbGFjZVxuICBCTi5wcm90b3R5cGUuaXNxciA9IGZ1bmN0aW9uIGlzcXIgKCkge1xuICAgIHJldHVybiB0aGlzLmltdWwodGhpcy5jbG9uZSgpKTtcbiAgfTtcblxuICAvLyBNYXRoLnBvdyhgdGhpc2AsIGBudW1gKVxuICBCTi5wcm90b3R5cGUucG93ID0gZnVuY3Rpb24gcG93IChudW0pIHtcbiAgICB2YXIgdyA9IHRvQml0QXJyYXkobnVtKTtcbiAgICBpZiAody5sZW5ndGggPT09IDApIHJldHVybiBuZXcgQk4oMSk7XG5cbiAgICAvLyBTa2lwIGxlYWRpbmcgemVyb2VzXG4gICAgdmFyIHJlcyA9IHRoaXM7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB3Lmxlbmd0aDsgaSsrLCByZXMgPSByZXMuc3FyKCkpIHtcbiAgICAgIGlmICh3W2ldICE9PSAwKSBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoKytpIDwgdy5sZW5ndGgpIHtcbiAgICAgIGZvciAodmFyIHEgPSByZXMuc3FyKCk7IGkgPCB3Lmxlbmd0aDsgaSsrLCBxID0gcS5zcXIoKSkge1xuICAgICAgICBpZiAod1tpXSA9PT0gMCkgY29udGludWU7XG5cbiAgICAgICAgcmVzID0gcmVzLm11bChxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIC8vIFNoaWZ0LWxlZnQgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLml1c2hsbiA9IGZ1bmN0aW9uIGl1c2hsbiAoYml0cykge1xuICAgIGFzc2VydCh0eXBlb2YgYml0cyA9PT0gJ251bWJlcicgJiYgYml0cyA+PSAwKTtcbiAgICB2YXIgciA9IGJpdHMgJSAyNjtcbiAgICB2YXIgcyA9IChiaXRzIC0gcikgLyAyNjtcbiAgICB2YXIgY2FycnlNYXNrID0gKDB4M2ZmZmZmZiA+Pj4gKDI2IC0gcikpIDw8ICgyNiAtIHIpO1xuICAgIHZhciBpO1xuXG4gICAgaWYgKHIgIT09IDApIHtcbiAgICAgIHZhciBjYXJyeSA9IDA7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBuZXdDYXJyeSA9IHRoaXMud29yZHNbaV0gJiBjYXJyeU1hc2s7XG4gICAgICAgIHZhciBjID0gKCh0aGlzLndvcmRzW2ldIHwgMCkgLSBuZXdDYXJyeSkgPDwgcjtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IGMgfCBjYXJyeTtcbiAgICAgICAgY2FycnkgPSBuZXdDYXJyeSA+Pj4gKDI2IC0gcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXJyeSkge1xuICAgICAgICB0aGlzLndvcmRzW2ldID0gY2Fycnk7XG4gICAgICAgIHRoaXMubGVuZ3RoKys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHMgIT09IDApIHtcbiAgICAgIGZvciAoaSA9IHRoaXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpICsgc10gPSB0aGlzLndvcmRzW2ldO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgczsgaSsrKSB7XG4gICAgICAgIHRoaXMud29yZHNbaV0gPSAwO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxlbmd0aCArPSBzO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlzaGxuID0gZnVuY3Rpb24gaXNobG4gKGJpdHMpIHtcbiAgICAvLyBUT0RPKGluZHV0bnkpOiBpbXBsZW1lbnQgbWVcbiAgICBhc3NlcnQodGhpcy5uZWdhdGl2ZSA9PT0gMCk7XG4gICAgcmV0dXJuIHRoaXMuaXVzaGxuKGJpdHMpO1xuICB9O1xuXG4gIC8vIFNoaWZ0LXJpZ2h0IGluLXBsYWNlXG4gIC8vIE5PVEU6IGBoaW50YCBpcyBhIGxvd2VzdCBiaXQgYmVmb3JlIHRyYWlsaW5nIHplcm9lc1xuICAvLyBOT1RFOiBpZiBgZXh0ZW5kZWRgIGlzIHByZXNlbnQgLSBpdCB3aWxsIGJlIGZpbGxlZCB3aXRoIGRlc3Ryb3llZCBiaXRzXG4gIEJOLnByb3RvdHlwZS5pdXNocm4gPSBmdW5jdGlvbiBpdXNocm4gKGJpdHMsIGhpbnQsIGV4dGVuZGVkKSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBiaXRzID09PSAnbnVtYmVyJyAmJiBiaXRzID49IDApO1xuICAgIHZhciBoO1xuICAgIGlmIChoaW50KSB7XG4gICAgICBoID0gKGhpbnQgLSAoaGludCAlIDI2KSkgLyAyNjtcbiAgICB9IGVsc2Uge1xuICAgICAgaCA9IDA7XG4gICAgfVxuXG4gICAgdmFyIHIgPSBiaXRzICUgMjY7XG4gICAgdmFyIHMgPSBNYXRoLm1pbigoYml0cyAtIHIpIC8gMjYsIHRoaXMubGVuZ3RoKTtcbiAgICB2YXIgbWFzayA9IDB4M2ZmZmZmZiBeICgoMHgzZmZmZmZmID4+PiByKSA8PCByKTtcbiAgICB2YXIgbWFza2VkV29yZHMgPSBleHRlbmRlZDtcblxuICAgIGggLT0gcztcbiAgICBoID0gTWF0aC5tYXgoMCwgaCk7XG5cbiAgICAvLyBFeHRlbmRlZCBtb2RlLCBjb3B5IG1hc2tlZCBwYXJ0XG4gICAgaWYgKG1hc2tlZFdvcmRzKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHM7IGkrKykge1xuICAgICAgICBtYXNrZWRXb3Jkcy53b3Jkc1tpXSA9IHRoaXMud29yZHNbaV07XG4gICAgICB9XG4gICAgICBtYXNrZWRXb3Jkcy5sZW5ndGggPSBzO1xuICAgIH1cblxuICAgIGlmIChzID09PSAwKSB7XG4gICAgICAvLyBOby1vcCwgd2Ugc2hvdWxkIG5vdCBtb3ZlIGFueXRoaW5nIGF0IGFsbFxuICAgIH0gZWxzZSBpZiAodGhpcy5sZW5ndGggPiBzKSB7XG4gICAgICB0aGlzLmxlbmd0aCAtPSBzO1xuICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IHRoaXMud29yZHNbaSArIHNdO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLndvcmRzWzBdID0gMDtcbiAgICAgIHRoaXMubGVuZ3RoID0gMTtcbiAgICB9XG5cbiAgICB2YXIgY2FycnkgPSAwO1xuICAgIGZvciAoaSA9IHRoaXMubGVuZ3RoIC0gMTsgaSA+PSAwICYmIChjYXJyeSAhPT0gMCB8fCBpID49IGgpOyBpLS0pIHtcbiAgICAgIHZhciB3b3JkID0gdGhpcy53b3Jkc1tpXSB8IDA7XG4gICAgICB0aGlzLndvcmRzW2ldID0gKGNhcnJ5IDw8ICgyNiAtIHIpKSB8ICh3b3JkID4+PiByKTtcbiAgICAgIGNhcnJ5ID0gd29yZCAmIG1hc2s7XG4gICAgfVxuXG4gICAgLy8gUHVzaCBjYXJyaWVkIGJpdHMgYXMgYSBtYXNrXG4gICAgaWYgKG1hc2tlZFdvcmRzICYmIGNhcnJ5ICE9PSAwKSB7XG4gICAgICBtYXNrZWRXb3Jkcy53b3Jkc1ttYXNrZWRXb3Jkcy5sZW5ndGgrK10gPSBjYXJyeTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMud29yZHNbMF0gPSAwO1xuICAgICAgdGhpcy5sZW5ndGggPSAxO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlzaHJuID0gZnVuY3Rpb24gaXNocm4gKGJpdHMsIGhpbnQsIGV4dGVuZGVkKSB7XG4gICAgLy8gVE9ETyhpbmR1dG55KTogaW1wbGVtZW50IG1lXG4gICAgYXNzZXJ0KHRoaXMubmVnYXRpdmUgPT09IDApO1xuICAgIHJldHVybiB0aGlzLml1c2hybihiaXRzLCBoaW50LCBleHRlbmRlZCk7XG4gIH07XG5cbiAgLy8gU2hpZnQtbGVmdFxuICBCTi5wcm90b3R5cGUuc2hsbiA9IGZ1bmN0aW9uIHNobG4gKGJpdHMpIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmlzaGxuKGJpdHMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS51c2hsbiA9IGZ1bmN0aW9uIHVzaGxuIChiaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pdXNobG4oYml0cyk7XG4gIH07XG5cbiAgLy8gU2hpZnQtcmlnaHRcbiAgQk4ucHJvdG90eXBlLnNocm4gPSBmdW5jdGlvbiBzaHJuIChiaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pc2hybihiaXRzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudXNocm4gPSBmdW5jdGlvbiB1c2hybiAoYml0cykge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaXVzaHJuKGJpdHMpO1xuICB9O1xuXG4gIC8vIFRlc3QgaWYgbiBiaXQgaXMgc2V0XG4gIEJOLnByb3RvdHlwZS50ZXN0biA9IGZ1bmN0aW9uIHRlc3RuIChiaXQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGJpdCA9PT0gJ251bWJlcicgJiYgYml0ID49IDApO1xuICAgIHZhciByID0gYml0ICUgMjY7XG4gICAgdmFyIHMgPSAoYml0IC0gcikgLyAyNjtcbiAgICB2YXIgcSA9IDEgPDwgcjtcblxuICAgIC8vIEZhc3QgY2FzZTogYml0IGlzIG11Y2ggaGlnaGVyIHRoYW4gYWxsIGV4aXN0aW5nIHdvcmRzXG4gICAgaWYgKHRoaXMubGVuZ3RoIDw9IHMpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIENoZWNrIGJpdCBhbmQgcmV0dXJuXG4gICAgdmFyIHcgPSB0aGlzLndvcmRzW3NdO1xuXG4gICAgcmV0dXJuICEhKHcgJiBxKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gb25seSBsb3dlcnMgYml0cyBvZiBudW1iZXIgKGluLXBsYWNlKVxuICBCTi5wcm90b3R5cGUuaW1hc2tuID0gZnVuY3Rpb24gaW1hc2tuIChiaXRzKSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBiaXRzID09PSAnbnVtYmVyJyAmJiBiaXRzID49IDApO1xuICAgIHZhciByID0gYml0cyAlIDI2O1xuICAgIHZhciBzID0gKGJpdHMgLSByKSAvIDI2O1xuXG4gICAgYXNzZXJ0KHRoaXMubmVnYXRpdmUgPT09IDAsICdpbWFza24gd29ya3Mgb25seSB3aXRoIHBvc2l0aXZlIG51bWJlcnMnKTtcblxuICAgIGlmICh0aGlzLmxlbmd0aCA8PSBzKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBpZiAociAhPT0gMCkge1xuICAgICAgcysrO1xuICAgIH1cbiAgICB0aGlzLmxlbmd0aCA9IE1hdGgubWluKHMsIHRoaXMubGVuZ3RoKTtcblxuICAgIGlmIChyICE9PSAwKSB7XG4gICAgICB2YXIgbWFzayA9IDB4M2ZmZmZmZiBeICgoMHgzZmZmZmZmID4+PiByKSA8PCByKTtcbiAgICAgIHRoaXMud29yZHNbdGhpcy5sZW5ndGggLSAxXSAmPSBtYXNrO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgLy8gUmV0dXJuIG9ubHkgbG93ZXJzIGJpdHMgb2YgbnVtYmVyXG4gIEJOLnByb3RvdHlwZS5tYXNrbiA9IGZ1bmN0aW9uIG1hc2tuIChiaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pbWFza24oYml0cyk7XG4gIH07XG5cbiAgLy8gQWRkIHBsYWluIG51bWJlciBgbnVtYCB0byBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLmlhZGRuID0gZnVuY3Rpb24gaWFkZG4gKG51bSkge1xuICAgIGFzc2VydCh0eXBlb2YgbnVtID09PSAnbnVtYmVyJyk7XG4gICAgYXNzZXJ0KG51bSA8IDB4NDAwMDAwMCk7XG4gICAgaWYgKG51bSA8IDApIHJldHVybiB0aGlzLmlzdWJuKC1udW0pO1xuXG4gICAgLy8gUG9zc2libGUgc2lnbiBjaGFuZ2VcbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAxICYmICh0aGlzLndvcmRzWzBdIHwgMCkgPCBudW0pIHtcbiAgICAgICAgdGhpcy53b3Jkc1swXSA9IG51bSAtICh0aGlzLndvcmRzWzBdIHwgMCk7XG4gICAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDA7XG4gICAgICB0aGlzLmlzdWJuKG51bSk7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8vIEFkZCB3aXRob3V0IGNoZWNrc1xuICAgIHJldHVybiB0aGlzLl9pYWRkbihudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5faWFkZG4gPSBmdW5jdGlvbiBfaWFkZG4gKG51bSkge1xuICAgIHRoaXMud29yZHNbMF0gKz0gbnVtO1xuXG4gICAgLy8gQ2FycnlcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoICYmIHRoaXMud29yZHNbaV0gPj0gMHg0MDAwMDAwOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gLT0gMHg0MDAwMDAwO1xuICAgICAgaWYgKGkgPT09IHRoaXMubGVuZ3RoIC0gMSkge1xuICAgICAgICB0aGlzLndvcmRzW2kgKyAxXSA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLndvcmRzW2kgKyAxXSsrO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmxlbmd0aCA9IE1hdGgubWF4KHRoaXMubGVuZ3RoLCBpICsgMSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvLyBTdWJ0cmFjdCBwbGFpbiBudW1iZXIgYG51bWAgZnJvbSBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLmlzdWJuID0gZnVuY3Rpb24gaXN1Ym4gKG51bSkge1xuICAgIGFzc2VydCh0eXBlb2YgbnVtID09PSAnbnVtYmVyJyk7XG4gICAgYXNzZXJ0KG51bSA8IDB4NDAwMDAwMCk7XG4gICAgaWYgKG51bSA8IDApIHJldHVybiB0aGlzLmlhZGRuKC1udW0pO1xuXG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgICAgdGhpcy5pYWRkbihudW0pO1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB0aGlzLndvcmRzWzBdIC09IG51bTtcblxuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSAmJiB0aGlzLndvcmRzWzBdIDwgMCkge1xuICAgICAgdGhpcy53b3Jkc1swXSA9IC10aGlzLndvcmRzWzBdO1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENhcnJ5XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoICYmIHRoaXMud29yZHNbaV0gPCAwOyBpKyspIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSArPSAweDQwMDAwMDA7XG4gICAgICAgIHRoaXMud29yZHNbaSArIDFdIC09IDE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuYWRkbiA9IGZ1bmN0aW9uIGFkZG4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaWFkZG4obnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuc3VibiA9IGZ1bmN0aW9uIHN1Ym4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaXN1Ym4obnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaWFicyA9IGZ1bmN0aW9uIGlhYnMgKCkge1xuICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmFicyA9IGZ1bmN0aW9uIGFicyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pYWJzKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl9pc2hsbnN1Ym11bCA9IGZ1bmN0aW9uIF9pc2hsbnN1Ym11bCAobnVtLCBtdWwsIHNoaWZ0KSB7XG4gICAgdmFyIGxlbiA9IG51bS5sZW5ndGggKyBzaGlmdDtcbiAgICB2YXIgaTtcblxuICAgIHRoaXMuX2V4cGFuZChsZW4pO1xuXG4gICAgdmFyIHc7XG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtLmxlbmd0aDsgaSsrKSB7XG4gICAgICB3ID0gKHRoaXMud29yZHNbaSArIHNoaWZ0XSB8IDApICsgY2Fycnk7XG4gICAgICB2YXIgcmlnaHQgPSAobnVtLndvcmRzW2ldIHwgMCkgKiBtdWw7XG4gICAgICB3IC09IHJpZ2h0ICYgMHgzZmZmZmZmO1xuICAgICAgY2FycnkgPSAodyA+PiAyNikgLSAoKHJpZ2h0IC8gMHg0MDAwMDAwKSB8IDApO1xuICAgICAgdGhpcy53b3Jkc1tpICsgc2hpZnRdID0gdyAmIDB4M2ZmZmZmZjtcbiAgICB9XG4gICAgZm9yICg7IGkgPCB0aGlzLmxlbmd0aCAtIHNoaWZ0OyBpKyspIHtcbiAgICAgIHcgPSAodGhpcy53b3Jkc1tpICsgc2hpZnRdIHwgMCkgKyBjYXJyeTtcbiAgICAgIGNhcnJ5ID0gdyA+PiAyNjtcbiAgICAgIHRoaXMud29yZHNbaSArIHNoaWZ0XSA9IHcgJiAweDNmZmZmZmY7XG4gICAgfVxuXG4gICAgaWYgKGNhcnJ5ID09PSAwKSByZXR1cm4gdGhpcy5zdHJpcCgpO1xuXG4gICAgLy8gU3VidHJhY3Rpb24gb3ZlcmZsb3dcbiAgICBhc3NlcnQoY2FycnkgPT09IC0xKTtcbiAgICBjYXJyeSA9IDA7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHcgPSAtKHRoaXMud29yZHNbaV0gfCAwKSArIGNhcnJ5O1xuICAgICAgY2FycnkgPSB3ID4+IDI2O1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHcgJiAweDNmZmZmZmY7XG4gICAgfVxuICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX3dvcmREaXYgPSBmdW5jdGlvbiBfd29yZERpdiAobnVtLCBtb2RlKSB7XG4gICAgdmFyIHNoaWZ0ID0gdGhpcy5sZW5ndGggLSBudW0ubGVuZ3RoO1xuXG4gICAgdmFyIGEgPSB0aGlzLmNsb25lKCk7XG4gICAgdmFyIGIgPSBudW07XG5cbiAgICAvLyBOb3JtYWxpemVcbiAgICB2YXIgYmhpID0gYi53b3Jkc1tiLmxlbmd0aCAtIDFdIHwgMDtcbiAgICB2YXIgYmhpQml0cyA9IHRoaXMuX2NvdW50Qml0cyhiaGkpO1xuICAgIHNoaWZ0ID0gMjYgLSBiaGlCaXRzO1xuICAgIGlmIChzaGlmdCAhPT0gMCkge1xuICAgICAgYiA9IGIudXNobG4oc2hpZnQpO1xuICAgICAgYS5pdXNobG4oc2hpZnQpO1xuICAgICAgYmhpID0gYi53b3Jkc1tiLmxlbmd0aCAtIDFdIHwgMDtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplIHF1b3RpZW50XG4gICAgdmFyIG0gPSBhLmxlbmd0aCAtIGIubGVuZ3RoO1xuICAgIHZhciBxO1xuXG4gICAgaWYgKG1vZGUgIT09ICdtb2QnKSB7XG4gICAgICBxID0gbmV3IEJOKG51bGwpO1xuICAgICAgcS5sZW5ndGggPSBtICsgMTtcbiAgICAgIHEud29yZHMgPSBuZXcgQXJyYXkocS5sZW5ndGgpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBxLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHEud29yZHNbaV0gPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBkaWZmID0gYS5jbG9uZSgpLl9pc2hsbnN1Ym11bChiLCAxLCBtKTtcbiAgICBpZiAoZGlmZi5uZWdhdGl2ZSA9PT0gMCkge1xuICAgICAgYSA9IGRpZmY7XG4gICAgICBpZiAocSkge1xuICAgICAgICBxLndvcmRzW21dID0gMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gbSAtIDE7IGogPj0gMDsgai0tKSB7XG4gICAgICB2YXIgcWogPSAoYS53b3Jkc1tiLmxlbmd0aCArIGpdIHwgMCkgKiAweDQwMDAwMDAgK1xuICAgICAgICAoYS53b3Jkc1tiLmxlbmd0aCArIGogLSAxXSB8IDApO1xuXG4gICAgICAvLyBOT1RFOiAocWogLyBiaGkpIGlzICgweDNmZmZmZmYgKiAweDQwMDAwMDAgKyAweDNmZmZmZmYpIC8gMHgyMDAwMDAwIG1heFxuICAgICAgLy8gKDB4N2ZmZmZmZilcbiAgICAgIHFqID0gTWF0aC5taW4oKHFqIC8gYmhpKSB8IDAsIDB4M2ZmZmZmZik7XG5cbiAgICAgIGEuX2lzaGxuc3VibXVsKGIsIHFqLCBqKTtcbiAgICAgIHdoaWxlIChhLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICAgIHFqLS07XG4gICAgICAgIGEubmVnYXRpdmUgPSAwO1xuICAgICAgICBhLl9pc2hsbnN1Ym11bChiLCAxLCBqKTtcbiAgICAgICAgaWYgKCFhLmlzWmVybygpKSB7XG4gICAgICAgICAgYS5uZWdhdGl2ZSBePSAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocSkge1xuICAgICAgICBxLndvcmRzW2pdID0gcWo7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChxKSB7XG4gICAgICBxLnN0cmlwKCk7XG4gICAgfVxuICAgIGEuc3RyaXAoKTtcblxuICAgIC8vIERlbm9ybWFsaXplXG4gICAgaWYgKG1vZGUgIT09ICdkaXYnICYmIHNoaWZ0ICE9PSAwKSB7XG4gICAgICBhLml1c2hybihzaGlmdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRpdjogcSB8fCBudWxsLFxuICAgICAgbW9kOiBhXG4gICAgfTtcbiAgfTtcblxuICAvLyBOT1RFOiAxKSBgbW9kZWAgY2FuIGJlIHNldCB0byBgbW9kYCB0byByZXF1ZXN0IG1vZCBvbmx5LFxuICAvLyAgICAgICB0byBgZGl2YCB0byByZXF1ZXN0IGRpdiBvbmx5LCBvciBiZSBhYnNlbnQgdG9cbiAgLy8gICAgICAgcmVxdWVzdCBib3RoIGRpdiAmIG1vZFxuICAvLyAgICAgICAyKSBgcG9zaXRpdmVgIGlzIHRydWUgaWYgdW5zaWduZWQgbW9kIGlzIHJlcXVlc3RlZFxuICBCTi5wcm90b3R5cGUuZGl2bW9kID0gZnVuY3Rpb24gZGl2bW9kIChudW0sIG1vZGUsIHBvc2l0aXZlKSB7XG4gICAgYXNzZXJ0KCFudW0uaXNaZXJvKCkpO1xuXG4gICAgaWYgKHRoaXMuaXNaZXJvKCkpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRpdjogbmV3IEJOKDApLFxuICAgICAgICBtb2Q6IG5ldyBCTigwKVxuICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgZGl2LCBtb2QsIHJlcztcbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCAmJiBudW0ubmVnYXRpdmUgPT09IDApIHtcbiAgICAgIHJlcyA9IHRoaXMubmVnKCkuZGl2bW9kKG51bSwgbW9kZSk7XG5cbiAgICAgIGlmIChtb2RlICE9PSAnbW9kJykge1xuICAgICAgICBkaXYgPSByZXMuZGl2Lm5lZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAobW9kZSAhPT0gJ2RpdicpIHtcbiAgICAgICAgbW9kID0gcmVzLm1vZC5uZWcoKTtcbiAgICAgICAgaWYgKHBvc2l0aXZlICYmIG1vZC5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgICAgIG1vZC5pYWRkKG51bSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGl2OiBkaXYsXG4gICAgICAgIG1vZDogbW9kXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmICh0aGlzLm5lZ2F0aXZlID09PSAwICYmIG51bS5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgcmVzID0gdGhpcy5kaXZtb2QobnVtLm5lZygpLCBtb2RlKTtcblxuICAgICAgaWYgKG1vZGUgIT09ICdtb2QnKSB7XG4gICAgICAgIGRpdiA9IHJlcy5kaXYubmVnKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRpdjogZGl2LFxuICAgICAgICBtb2Q6IHJlcy5tb2RcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKCh0aGlzLm5lZ2F0aXZlICYgbnVtLm5lZ2F0aXZlKSAhPT0gMCkge1xuICAgICAgcmVzID0gdGhpcy5uZWcoKS5kaXZtb2QobnVtLm5lZygpLCBtb2RlKTtcblxuICAgICAgaWYgKG1vZGUgIT09ICdkaXYnKSB7XG4gICAgICAgIG1vZCA9IHJlcy5tb2QubmVnKCk7XG4gICAgICAgIGlmIChwb3NpdGl2ZSAmJiBtb2QubmVnYXRpdmUgIT09IDApIHtcbiAgICAgICAgICBtb2QuaXN1YihudW0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRpdjogcmVzLmRpdixcbiAgICAgICAgbW9kOiBtb2RcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQm90aCBudW1iZXJzIGFyZSBwb3NpdGl2ZSBhdCB0aGlzIHBvaW50XG5cbiAgICAvLyBTdHJpcCBib3RoIG51bWJlcnMgdG8gYXBwcm94aW1hdGUgc2hpZnQgdmFsdWVcbiAgICBpZiAobnVtLmxlbmd0aCA+IHRoaXMubGVuZ3RoIHx8IHRoaXMuY21wKG51bSkgPCAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXY6IG5ldyBCTigwKSxcbiAgICAgICAgbW9kOiB0aGlzXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIFZlcnkgc2hvcnQgcmVkdWN0aW9uXG4gICAgaWYgKG51bS5sZW5ndGggPT09IDEpIHtcbiAgICAgIGlmIChtb2RlID09PSAnZGl2Jykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGRpdjogdGhpcy5kaXZuKG51bS53b3Jkc1swXSksXG4gICAgICAgICAgbW9kOiBudWxsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGlmIChtb2RlID09PSAnbW9kJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGRpdjogbnVsbCxcbiAgICAgICAgICBtb2Q6IG5ldyBCTih0aGlzLm1vZG4obnVtLndvcmRzWzBdKSlcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGl2OiB0aGlzLmRpdm4obnVtLndvcmRzWzBdKSxcbiAgICAgICAgbW9kOiBuZXcgQk4odGhpcy5tb2RuKG51bS53b3Jkc1swXSkpXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl93b3JkRGl2KG51bSwgbW9kZSk7XG4gIH07XG5cbiAgLy8gRmluZCBgdGhpc2AgLyBgbnVtYFxuICBCTi5wcm90b3R5cGUuZGl2ID0gZnVuY3Rpb24gZGl2IChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5kaXZtb2QobnVtLCAnZGl2JywgZmFsc2UpLmRpdjtcbiAgfTtcblxuICAvLyBGaW5kIGB0aGlzYCAlIGBudW1gXG4gIEJOLnByb3RvdHlwZS5tb2QgPSBmdW5jdGlvbiBtb2QgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmRpdm1vZChudW0sICdtb2QnLCBmYWxzZSkubW9kO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS51bW9kID0gZnVuY3Rpb24gdW1vZCAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuZGl2bW9kKG51bSwgJ21vZCcsIHRydWUpLm1vZDtcbiAgfTtcblxuICAvLyBGaW5kIFJvdW5kKGB0aGlzYCAvIGBudW1gKVxuICBCTi5wcm90b3R5cGUuZGl2Um91bmQgPSBmdW5jdGlvbiBkaXZSb3VuZCAobnVtKSB7XG4gICAgdmFyIGRtID0gdGhpcy5kaXZtb2QobnVtKTtcblxuICAgIC8vIEZhc3QgY2FzZSAtIGV4YWN0IGRpdmlzaW9uXG4gICAgaWYgKGRtLm1vZC5pc1plcm8oKSkgcmV0dXJuIGRtLmRpdjtcblxuICAgIHZhciBtb2QgPSBkbS5kaXYubmVnYXRpdmUgIT09IDAgPyBkbS5tb2QuaXN1YihudW0pIDogZG0ubW9kO1xuXG4gICAgdmFyIGhhbGYgPSBudW0udXNocm4oMSk7XG4gICAgdmFyIHIyID0gbnVtLmFuZGxuKDEpO1xuICAgIHZhciBjbXAgPSBtb2QuY21wKGhhbGYpO1xuXG4gICAgLy8gUm91bmQgZG93blxuICAgIGlmIChjbXAgPCAwIHx8IHIyID09PSAxICYmIGNtcCA9PT0gMCkgcmV0dXJuIGRtLmRpdjtcblxuICAgIC8vIFJvdW5kIHVwXG4gICAgcmV0dXJuIGRtLmRpdi5uZWdhdGl2ZSAhPT0gMCA/IGRtLmRpdi5pc3VibigxKSA6IGRtLmRpdi5pYWRkbigxKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubW9kbiA9IGZ1bmN0aW9uIG1vZG4gKG51bSkge1xuICAgIGFzc2VydChudW0gPD0gMHgzZmZmZmZmKTtcbiAgICB2YXIgcCA9ICgxIDw8IDI2KSAlIG51bTtcblxuICAgIHZhciBhY2MgPSAwO1xuICAgIGZvciAodmFyIGkgPSB0aGlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhY2MgPSAocCAqIGFjYyArICh0aGlzLndvcmRzW2ldIHwgMCkpICUgbnVtO1xuICAgIH1cblxuICAgIHJldHVybiBhY2M7XG4gIH07XG5cbiAgLy8gSW4tcGxhY2UgZGl2aXNpb24gYnkgbnVtYmVyXG4gIEJOLnByb3RvdHlwZS5pZGl2biA9IGZ1bmN0aW9uIGlkaXZuIChudW0pIHtcbiAgICBhc3NlcnQobnVtIDw9IDB4M2ZmZmZmZik7XG5cbiAgICB2YXIgY2FycnkgPSAwO1xuICAgIGZvciAodmFyIGkgPSB0aGlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2YXIgdyA9ICh0aGlzLndvcmRzW2ldIHwgMCkgKyBjYXJyeSAqIDB4NDAwMDAwMDtcbiAgICAgIHRoaXMud29yZHNbaV0gPSAodyAvIG51bSkgfCAwO1xuICAgICAgY2FycnkgPSB3ICUgbnVtO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmRpdm4gPSBmdW5jdGlvbiBkaXZuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmlkaXZuKG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmVnY2QgPSBmdW5jdGlvbiBlZ2NkIChwKSB7XG4gICAgYXNzZXJ0KHAubmVnYXRpdmUgPT09IDApO1xuICAgIGFzc2VydCghcC5pc1plcm8oKSk7XG5cbiAgICB2YXIgeCA9IHRoaXM7XG4gICAgdmFyIHkgPSBwLmNsb25lKCk7XG5cbiAgICBpZiAoeC5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgeCA9IHgudW1vZChwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgeCA9IHguY2xvbmUoKTtcbiAgICB9XG5cbiAgICAvLyBBICogeCArIEIgKiB5ID0geFxuICAgIHZhciBBID0gbmV3IEJOKDEpO1xuICAgIHZhciBCID0gbmV3IEJOKDApO1xuXG4gICAgLy8gQyAqIHggKyBEICogeSA9IHlcbiAgICB2YXIgQyA9IG5ldyBCTigwKTtcbiAgICB2YXIgRCA9IG5ldyBCTigxKTtcblxuICAgIHZhciBnID0gMDtcblxuICAgIHdoaWxlICh4LmlzRXZlbigpICYmIHkuaXNFdmVuKCkpIHtcbiAgICAgIHguaXVzaHJuKDEpO1xuICAgICAgeS5pdXNocm4oMSk7XG4gICAgICArK2c7XG4gICAgfVxuXG4gICAgdmFyIHlwID0geS5jbG9uZSgpO1xuICAgIHZhciB4cCA9IHguY2xvbmUoKTtcblxuICAgIHdoaWxlICgheC5pc1plcm8oKSkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGltID0gMTsgKHgud29yZHNbMF0gJiBpbSkgPT09IDAgJiYgaSA8IDI2OyArK2ksIGltIDw8PSAxKTtcbiAgICAgIGlmIChpID4gMCkge1xuICAgICAgICB4Lml1c2hybihpKTtcbiAgICAgICAgd2hpbGUgKGktLSA+IDApIHtcbiAgICAgICAgICBpZiAoQS5pc09kZCgpIHx8IEIuaXNPZGQoKSkge1xuICAgICAgICAgICAgQS5pYWRkKHlwKTtcbiAgICAgICAgICAgIEIuaXN1Yih4cCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgQS5pdXNocm4oMSk7XG4gICAgICAgICAgQi5pdXNocm4oMSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgaiA9IDAsIGptID0gMTsgKHkud29yZHNbMF0gJiBqbSkgPT09IDAgJiYgaiA8IDI2OyArK2osIGptIDw8PSAxKTtcbiAgICAgIGlmIChqID4gMCkge1xuICAgICAgICB5Lml1c2hybihqKTtcbiAgICAgICAgd2hpbGUgKGotLSA+IDApIHtcbiAgICAgICAgICBpZiAoQy5pc09kZCgpIHx8IEQuaXNPZGQoKSkge1xuICAgICAgICAgICAgQy5pYWRkKHlwKTtcbiAgICAgICAgICAgIEQuaXN1Yih4cCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgQy5pdXNocm4oMSk7XG4gICAgICAgICAgRC5pdXNocm4oMSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHguY21wKHkpID49IDApIHtcbiAgICAgICAgeC5pc3ViKHkpO1xuICAgICAgICBBLmlzdWIoQyk7XG4gICAgICAgIEIuaXN1YihEKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHkuaXN1Yih4KTtcbiAgICAgICAgQy5pc3ViKEEpO1xuICAgICAgICBELmlzdWIoQik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGE6IEMsXG4gICAgICBiOiBELFxuICAgICAgZ2NkOiB5Lml1c2hsbihnKVxuICAgIH07XG4gIH07XG5cbiAgLy8gVGhpcyBpcyByZWR1Y2VkIGluY2FybmF0aW9uIG9mIHRoZSBiaW5hcnkgRUVBXG4gIC8vIGFib3ZlLCBkZXNpZ25hdGVkIHRvIGludmVydCBtZW1iZXJzIG9mIHRoZVxuICAvLyBfcHJpbWVfIGZpZWxkcyBGKHApIGF0IGEgbWF4aW1hbCBzcGVlZFxuICBCTi5wcm90b3R5cGUuX2ludm1wID0gZnVuY3Rpb24gX2ludm1wIChwKSB7XG4gICAgYXNzZXJ0KHAubmVnYXRpdmUgPT09IDApO1xuICAgIGFzc2VydCghcC5pc1plcm8oKSk7XG5cbiAgICB2YXIgYSA9IHRoaXM7XG4gICAgdmFyIGIgPSBwLmNsb25lKCk7XG5cbiAgICBpZiAoYS5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgYSA9IGEudW1vZChwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IGEuY2xvbmUoKTtcbiAgICB9XG5cbiAgICB2YXIgeDEgPSBuZXcgQk4oMSk7XG4gICAgdmFyIHgyID0gbmV3IEJOKDApO1xuXG4gICAgdmFyIGRlbHRhID0gYi5jbG9uZSgpO1xuXG4gICAgd2hpbGUgKGEuY21wbigxKSA+IDAgJiYgYi5jbXBuKDEpID4gMCkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGltID0gMTsgKGEud29yZHNbMF0gJiBpbSkgPT09IDAgJiYgaSA8IDI2OyArK2ksIGltIDw8PSAxKTtcbiAgICAgIGlmIChpID4gMCkge1xuICAgICAgICBhLml1c2hybihpKTtcbiAgICAgICAgd2hpbGUgKGktLSA+IDApIHtcbiAgICAgICAgICBpZiAoeDEuaXNPZGQoKSkge1xuICAgICAgICAgICAgeDEuaWFkZChkZWx0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgeDEuaXVzaHJuKDEpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGogPSAwLCBqbSA9IDE7IChiLndvcmRzWzBdICYgam0pID09PSAwICYmIGogPCAyNjsgKytqLCBqbSA8PD0gMSk7XG4gICAgICBpZiAoaiA+IDApIHtcbiAgICAgICAgYi5pdXNocm4oaik7XG4gICAgICAgIHdoaWxlIChqLS0gPiAwKSB7XG4gICAgICAgICAgaWYgKHgyLmlzT2RkKCkpIHtcbiAgICAgICAgICAgIHgyLmlhZGQoZGVsdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHgyLml1c2hybigxKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYS5jbXAoYikgPj0gMCkge1xuICAgICAgICBhLmlzdWIoYik7XG4gICAgICAgIHgxLmlzdWIoeDIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYi5pc3ViKGEpO1xuICAgICAgICB4Mi5pc3ViKHgxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcmVzO1xuICAgIGlmIChhLmNtcG4oMSkgPT09IDApIHtcbiAgICAgIHJlcyA9IHgxO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXMgPSB4MjtcbiAgICB9XG5cbiAgICBpZiAocmVzLmNtcG4oMCkgPCAwKSB7XG4gICAgICByZXMuaWFkZChwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5nY2QgPSBmdW5jdGlvbiBnY2QgKG51bSkge1xuICAgIGlmICh0aGlzLmlzWmVybygpKSByZXR1cm4gbnVtLmFicygpO1xuICAgIGlmIChudW0uaXNaZXJvKCkpIHJldHVybiB0aGlzLmFicygpO1xuXG4gICAgdmFyIGEgPSB0aGlzLmNsb25lKCk7XG4gICAgdmFyIGIgPSBudW0uY2xvbmUoKTtcbiAgICBhLm5lZ2F0aXZlID0gMDtcbiAgICBiLm5lZ2F0aXZlID0gMDtcblxuICAgIC8vIFJlbW92ZSBjb21tb24gZmFjdG9yIG9mIHR3b1xuICAgIGZvciAodmFyIHNoaWZ0ID0gMDsgYS5pc0V2ZW4oKSAmJiBiLmlzRXZlbigpOyBzaGlmdCsrKSB7XG4gICAgICBhLml1c2hybigxKTtcbiAgICAgIGIuaXVzaHJuKDEpO1xuICAgIH1cblxuICAgIGRvIHtcbiAgICAgIHdoaWxlIChhLmlzRXZlbigpKSB7XG4gICAgICAgIGEuaXVzaHJuKDEpO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGIuaXNFdmVuKCkpIHtcbiAgICAgICAgYi5pdXNocm4oMSk7XG4gICAgICB9XG5cbiAgICAgIHZhciByID0gYS5jbXAoYik7XG4gICAgICBpZiAociA8IDApIHtcbiAgICAgICAgLy8gU3dhcCBgYWAgYW5kIGBiYCB0byBtYWtlIGBhYCBhbHdheXMgYmlnZ2VyIHRoYW4gYGJgXG4gICAgICAgIHZhciB0ID0gYTtcbiAgICAgICAgYSA9IGI7XG4gICAgICAgIGIgPSB0O1xuICAgICAgfSBlbHNlIGlmIChyID09PSAwIHx8IGIuY21wbigxKSA9PT0gMCkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgYS5pc3ViKGIpO1xuICAgIH0gd2hpbGUgKHRydWUpO1xuXG4gICAgcmV0dXJuIGIuaXVzaGxuKHNoaWZ0KTtcbiAgfTtcblxuICAvLyBJbnZlcnQgbnVtYmVyIGluIHRoZSBmaWVsZCBGKG51bSlcbiAgQk4ucHJvdG90eXBlLmludm0gPSBmdW5jdGlvbiBpbnZtIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5lZ2NkKG51bSkuYS51bW9kKG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlzRXZlbiA9IGZ1bmN0aW9uIGlzRXZlbiAoKSB7XG4gICAgcmV0dXJuICh0aGlzLndvcmRzWzBdICYgMSkgPT09IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlzT2RkID0gZnVuY3Rpb24gaXNPZGQgKCkge1xuICAgIHJldHVybiAodGhpcy53b3Jkc1swXSAmIDEpID09PSAxO1xuICB9O1xuXG4gIC8vIEFuZCBmaXJzdCB3b3JkIGFuZCBudW1cbiAgQk4ucHJvdG90eXBlLmFuZGxuID0gZnVuY3Rpb24gYW5kbG4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLndvcmRzWzBdICYgbnVtO1xuICB9O1xuXG4gIC8vIEluY3JlbWVudCBhdCB0aGUgYml0IHBvc2l0aW9uIGluLWxpbmVcbiAgQk4ucHJvdG90eXBlLmJpbmNuID0gZnVuY3Rpb24gYmluY24gKGJpdCkge1xuICAgIGFzc2VydCh0eXBlb2YgYml0ID09PSAnbnVtYmVyJyk7XG4gICAgdmFyIHIgPSBiaXQgJSAyNjtcbiAgICB2YXIgcyA9IChiaXQgLSByKSAvIDI2O1xuICAgIHZhciBxID0gMSA8PCByO1xuXG4gICAgLy8gRmFzdCBjYXNlOiBiaXQgaXMgbXVjaCBoaWdoZXIgdGhhbiBhbGwgZXhpc3Rpbmcgd29yZHNcbiAgICBpZiAodGhpcy5sZW5ndGggPD0gcykge1xuICAgICAgdGhpcy5fZXhwYW5kKHMgKyAxKTtcbiAgICAgIHRoaXMud29yZHNbc10gfD0gcTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8vIEFkZCBiaXQgYW5kIHByb3BhZ2F0ZSwgaWYgbmVlZGVkXG4gICAgdmFyIGNhcnJ5ID0gcTtcbiAgICBmb3IgKHZhciBpID0gczsgY2FycnkgIT09IDAgJiYgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciB3ID0gdGhpcy53b3Jkc1tpXSB8IDA7XG4gICAgICB3ICs9IGNhcnJ5O1xuICAgICAgY2FycnkgPSB3ID4+PiAyNjtcbiAgICAgIHcgJj0gMHgzZmZmZmZmO1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHc7XG4gICAgfVxuICAgIGlmIChjYXJyeSAhPT0gMCkge1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IGNhcnJ5O1xuICAgICAgdGhpcy5sZW5ndGgrKztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlzWmVybyA9IGZ1bmN0aW9uIGlzWmVybyAoKSB7XG4gICAgcmV0dXJuIHRoaXMubGVuZ3RoID09PSAxICYmIHRoaXMud29yZHNbMF0gPT09IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmNtcG4gPSBmdW5jdGlvbiBjbXBuIChudW0pIHtcbiAgICB2YXIgbmVnYXRpdmUgPSBudW0gPCAwO1xuXG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDAgJiYgIW5lZ2F0aXZlKSByZXR1cm4gLTE7XG4gICAgaWYgKHRoaXMubmVnYXRpdmUgPT09IDAgJiYgbmVnYXRpdmUpIHJldHVybiAxO1xuXG4gICAgdGhpcy5zdHJpcCgpO1xuXG4gICAgdmFyIHJlcztcbiAgICBpZiAodGhpcy5sZW5ndGggPiAxKSB7XG4gICAgICByZXMgPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAobmVnYXRpdmUpIHtcbiAgICAgICAgbnVtID0gLW51bTtcbiAgICAgIH1cblxuICAgICAgYXNzZXJ0KG51bSA8PSAweDNmZmZmZmYsICdOdW1iZXIgaXMgdG9vIGJpZycpO1xuXG4gICAgICB2YXIgdyA9IHRoaXMud29yZHNbMF0gfCAwO1xuICAgICAgcmVzID0gdyA9PT0gbnVtID8gMCA6IHcgPCBudW0gPyAtMSA6IDE7XG4gICAgfVxuICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwKSByZXR1cm4gLXJlcyB8IDA7XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICAvLyBDb21wYXJlIHR3byBudW1iZXJzIGFuZCByZXR1cm46XG4gIC8vIDEgLSBpZiBgdGhpc2AgPiBgbnVtYFxuICAvLyAwIC0gaWYgYHRoaXNgID09IGBudW1gXG4gIC8vIC0xIC0gaWYgYHRoaXNgIDwgYG51bWBcbiAgQk4ucHJvdG90eXBlLmNtcCA9IGZ1bmN0aW9uIGNtcCAobnVtKSB7XG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDAgJiYgbnVtLm5lZ2F0aXZlID09PSAwKSByZXR1cm4gLTE7XG4gICAgaWYgKHRoaXMubmVnYXRpdmUgPT09IDAgJiYgbnVtLm5lZ2F0aXZlICE9PSAwKSByZXR1cm4gMTtcblxuICAgIHZhciByZXMgPSB0aGlzLnVjbXAobnVtKTtcbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkgcmV0dXJuIC1yZXMgfCAwO1xuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgLy8gVW5zaWduZWQgY29tcGFyaXNvblxuICBCTi5wcm90b3R5cGUudWNtcCA9IGZ1bmN0aW9uIHVjbXAgKG51bSkge1xuICAgIC8vIEF0IHRoaXMgcG9pbnQgYm90aCBudW1iZXJzIGhhdmUgdGhlIHNhbWUgc2lnblxuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHJldHVybiAxO1xuICAgIGlmICh0aGlzLmxlbmd0aCA8IG51bS5sZW5ndGgpIHJldHVybiAtMTtcblxuICAgIHZhciByZXMgPSAwO1xuICAgIGZvciAodmFyIGkgPSB0aGlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2YXIgYSA9IHRoaXMud29yZHNbaV0gfCAwO1xuICAgICAgdmFyIGIgPSBudW0ud29yZHNbaV0gfCAwO1xuXG4gICAgICBpZiAoYSA9PT0gYikgY29udGludWU7XG4gICAgICBpZiAoYSA8IGIpIHtcbiAgICAgICAgcmVzID0gLTE7XG4gICAgICB9IGVsc2UgaWYgKGEgPiBiKSB7XG4gICAgICAgIHJlcyA9IDE7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZ3RuID0gZnVuY3Rpb24gZ3RuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXBuKG51bSkgPT09IDE7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmd0ID0gZnVuY3Rpb24gZ3QgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNtcChudW0pID09PSAxO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5ndGVuID0gZnVuY3Rpb24gZ3RlbiAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wbihudW0pID49IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmd0ZSA9IGZ1bmN0aW9uIGd0ZSAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wKG51bSkgPj0gMDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubHRuID0gZnVuY3Rpb24gbHRuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXBuKG51bSkgPT09IC0xO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5sdCA9IGZ1bmN0aW9uIGx0IChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXAobnVtKSA9PT0gLTE7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmx0ZW4gPSBmdW5jdGlvbiBsdGVuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXBuKG51bSkgPD0gMDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubHRlID0gZnVuY3Rpb24gbHRlIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXAobnVtKSA8PSAwO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5lcW4gPSBmdW5jdGlvbiBlcW4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNtcG4obnVtKSA9PT0gMDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZXEgPSBmdW5jdGlvbiBlcSAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wKG51bSkgPT09IDA7XG4gIH07XG5cbiAgLy9cbiAgLy8gQSByZWR1Y2UgY29udGV4dCwgY291bGQgYmUgdXNpbmcgbW9udGdvbWVyeSBvciBzb21ldGhpbmcgYmV0dGVyLCBkZXBlbmRpbmdcbiAgLy8gb24gdGhlIGBtYCBpdHNlbGYuXG4gIC8vXG4gIEJOLnJlZCA9IGZ1bmN0aW9uIHJlZCAobnVtKSB7XG4gICAgcmV0dXJuIG5ldyBSZWQobnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudG9SZWQgPSBmdW5jdGlvbiB0b1JlZCAoY3R4KSB7XG4gICAgYXNzZXJ0KCF0aGlzLnJlZCwgJ0FscmVhZHkgYSBudW1iZXIgaW4gcmVkdWN0aW9uIGNvbnRleHQnKTtcbiAgICBhc3NlcnQodGhpcy5uZWdhdGl2ZSA9PT0gMCwgJ3JlZCB3b3JrcyBvbmx5IHdpdGggcG9zaXRpdmVzJyk7XG4gICAgcmV0dXJuIGN0eC5jb252ZXJ0VG8odGhpcykuX2ZvcmNlUmVkKGN0eCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmZyb21SZWQgPSBmdW5jdGlvbiBmcm9tUmVkICgpIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdmcm9tUmVkIHdvcmtzIG9ubHkgd2l0aCBudW1iZXJzIGluIHJlZHVjdGlvbiBjb250ZXh0Jyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLmNvbnZlcnRGcm9tKHRoaXMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5fZm9yY2VSZWQgPSBmdW5jdGlvbiBfZm9yY2VSZWQgKGN0eCkge1xuICAgIHRoaXMucmVkID0gY3R4O1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5mb3JjZVJlZCA9IGZ1bmN0aW9uIGZvcmNlUmVkIChjdHgpIHtcbiAgICBhc3NlcnQoIXRoaXMucmVkLCAnQWxyZWFkeSBhIG51bWJlciBpbiByZWR1Y3Rpb24gY29udGV4dCcpO1xuICAgIHJldHVybiB0aGlzLl9mb3JjZVJlZChjdHgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRBZGQgPSBmdW5jdGlvbiByZWRBZGQgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZEFkZCB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuYWRkKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZElBZGQgPSBmdW5jdGlvbiByZWRJQWRkIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRJQWRkIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHJldHVybiB0aGlzLnJlZC5pYWRkKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZFN1YiA9IGZ1bmN0aW9uIHJlZFN1YiAobnVtKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkU3ViIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHJldHVybiB0aGlzLnJlZC5zdWIodGhpcywgbnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUucmVkSVN1YiA9IGZ1bmN0aW9uIHJlZElTdWIgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZElTdWIgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLmlzdWIodGhpcywgbnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUucmVkU2hsID0gZnVuY3Rpb24gcmVkU2hsIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRTaGwgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLnNobCh0aGlzLCBudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRNdWwgPSBmdW5jdGlvbiByZWRNdWwgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZE11bCB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5Mih0aGlzLCBudW0pO1xuICAgIHJldHVybiB0aGlzLnJlZC5tdWwodGhpcywgbnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUucmVkSU11bCA9IGZ1bmN0aW9uIHJlZElNdWwgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZE11bCB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5Mih0aGlzLCBudW0pO1xuICAgIHJldHVybiB0aGlzLnJlZC5pbXVsKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZFNxciA9IGZ1bmN0aW9uIHJlZFNxciAoKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkU3FyIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHRoaXMucmVkLl92ZXJpZnkxKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnJlZC5zcXIodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZElTcXIgPSBmdW5jdGlvbiByZWRJU3FyICgpIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRJU3FyIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHRoaXMucmVkLl92ZXJpZnkxKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnJlZC5pc3FyKHRoaXMpO1xuICB9O1xuXG4gIC8vIFNxdWFyZSByb290IG92ZXIgcFxuICBCTi5wcm90b3R5cGUucmVkU3FydCA9IGZ1bmN0aW9uIHJlZFNxcnQgKCkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZFNxcnQgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgdGhpcy5yZWQuX3ZlcmlmeTEodGhpcyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLnNxcnQodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZEludm0gPSBmdW5jdGlvbiByZWRJbnZtICgpIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRJbnZtIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHRoaXMucmVkLl92ZXJpZnkxKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnJlZC5pbnZtKHRoaXMpO1xuICB9O1xuXG4gIC8vIFJldHVybiBuZWdhdGl2ZSBjbG9uZSBvZiBgdGhpc2AgJSBgcmVkIG1vZHVsb2BcbiAgQk4ucHJvdG90eXBlLnJlZE5lZyA9IGZ1bmN0aW9uIHJlZE5lZyAoKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkTmVnIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHRoaXMucmVkLl92ZXJpZnkxKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnJlZC5uZWcodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZFBvdyA9IGZ1bmN0aW9uIHJlZFBvdyAobnVtKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkICYmICFudW0ucmVkLCAncmVkUG93KG5vcm1hbE51bSknKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5MSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5yZWQucG93KHRoaXMsIG51bSk7XG4gIH07XG5cbiAgLy8gUHJpbWUgbnVtYmVycyB3aXRoIGVmZmljaWVudCByZWR1Y3Rpb25cbiAgdmFyIHByaW1lcyA9IHtcbiAgICBrMjU2OiBudWxsLFxuICAgIHAyMjQ6IG51bGwsXG4gICAgcDE5MjogbnVsbCxcbiAgICBwMjU1MTk6IG51bGxcbiAgfTtcblxuICAvLyBQc2V1ZG8tTWVyc2VubmUgcHJpbWVcbiAgZnVuY3Rpb24gTVByaW1lIChuYW1lLCBwKSB7XG4gICAgLy8gUCA9IDIgXiBOIC0gS1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgdGhpcy5wID0gbmV3IEJOKHAsIDE2KTtcbiAgICB0aGlzLm4gPSB0aGlzLnAuYml0TGVuZ3RoKCk7XG4gICAgdGhpcy5rID0gbmV3IEJOKDEpLml1c2hsbih0aGlzLm4pLmlzdWIodGhpcy5wKTtcblxuICAgIHRoaXMudG1wID0gdGhpcy5fdG1wKCk7XG4gIH1cblxuICBNUHJpbWUucHJvdG90eXBlLl90bXAgPSBmdW5jdGlvbiBfdG1wICgpIHtcbiAgICB2YXIgdG1wID0gbmV3IEJOKG51bGwpO1xuICAgIHRtcC53b3JkcyA9IG5ldyBBcnJheShNYXRoLmNlaWwodGhpcy5uIC8gMTMpKTtcbiAgICByZXR1cm4gdG1wO1xuICB9O1xuXG4gIE1QcmltZS5wcm90b3R5cGUuaXJlZHVjZSA9IGZ1bmN0aW9uIGlyZWR1Y2UgKG51bSkge1xuICAgIC8vIEFzc3VtZXMgdGhhdCBgbnVtYCBpcyBsZXNzIHRoYW4gYFBeMmBcbiAgICAvLyBudW0gPSBISSAqICgyIF4gTiAtIEspICsgSEkgKiBLICsgTE8gPSBISSAqIEsgKyBMTyAobW9kIFApXG4gICAgdmFyIHIgPSBudW07XG4gICAgdmFyIHJsZW47XG5cbiAgICBkbyB7XG4gICAgICB0aGlzLnNwbGl0KHIsIHRoaXMudG1wKTtcbiAgICAgIHIgPSB0aGlzLmltdWxLKHIpO1xuICAgICAgciA9IHIuaWFkZCh0aGlzLnRtcCk7XG4gICAgICBybGVuID0gci5iaXRMZW5ndGgoKTtcbiAgICB9IHdoaWxlIChybGVuID4gdGhpcy5uKTtcblxuICAgIHZhciBjbXAgPSBybGVuIDwgdGhpcy5uID8gLTEgOiByLnVjbXAodGhpcy5wKTtcbiAgICBpZiAoY21wID09PSAwKSB7XG4gICAgICByLndvcmRzWzBdID0gMDtcbiAgICAgIHIubGVuZ3RoID0gMTtcbiAgICB9IGVsc2UgaWYgKGNtcCA+IDApIHtcbiAgICAgIHIuaXN1Yih0aGlzLnApO1xuICAgIH0gZWxzZSB7XG4gICAgICByLnN0cmlwKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgTVByaW1lLnByb3RvdHlwZS5zcGxpdCA9IGZ1bmN0aW9uIHNwbGl0IChpbnB1dCwgb3V0KSB7XG4gICAgaW5wdXQuaXVzaHJuKHRoaXMubiwgMCwgb3V0KTtcbiAgfTtcblxuICBNUHJpbWUucHJvdG90eXBlLmltdWxLID0gZnVuY3Rpb24gaW11bEsgKG51bSkge1xuICAgIHJldHVybiBudW0uaW11bCh0aGlzLmspO1xuICB9O1xuXG4gIGZ1bmN0aW9uIEsyNTYgKCkge1xuICAgIE1QcmltZS5jYWxsKFxuICAgICAgdGhpcyxcbiAgICAgICdrMjU2JyxcbiAgICAgICdmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZSBmZmZmZmMyZicpO1xuICB9XG4gIGluaGVyaXRzKEsyNTYsIE1QcmltZSk7XG5cbiAgSzI1Ni5wcm90b3R5cGUuc3BsaXQgPSBmdW5jdGlvbiBzcGxpdCAoaW5wdXQsIG91dHB1dCkge1xuICAgIC8vIDI1NiA9IDkgKiAyNiArIDIyXG4gICAgdmFyIG1hc2sgPSAweDNmZmZmZjtcblxuICAgIHZhciBvdXRMZW4gPSBNYXRoLm1pbihpbnB1dC5sZW5ndGgsIDkpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3V0TGVuOyBpKyspIHtcbiAgICAgIG91dHB1dC53b3Jkc1tpXSA9IGlucHV0LndvcmRzW2ldO1xuICAgIH1cbiAgICBvdXRwdXQubGVuZ3RoID0gb3V0TGVuO1xuXG4gICAgaWYgKGlucHV0Lmxlbmd0aCA8PSA5KSB7XG4gICAgICBpbnB1dC53b3Jkc1swXSA9IDA7XG4gICAgICBpbnB1dC5sZW5ndGggPSAxO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFNoaWZ0IGJ5IDkgbGltYnNcbiAgICB2YXIgcHJldiA9IGlucHV0LndvcmRzWzldO1xuICAgIG91dHB1dC53b3Jkc1tvdXRwdXQubGVuZ3RoKytdID0gcHJldiAmIG1hc2s7XG5cbiAgICBmb3IgKGkgPSAxMDsgaSA8IGlucHV0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbmV4dCA9IGlucHV0LndvcmRzW2ldIHwgMDtcbiAgICAgIGlucHV0LndvcmRzW2kgLSAxMF0gPSAoKG5leHQgJiBtYXNrKSA8PCA0KSB8IChwcmV2ID4+PiAyMik7XG4gICAgICBwcmV2ID0gbmV4dDtcbiAgICB9XG4gICAgcHJldiA+Pj49IDIyO1xuICAgIGlucHV0LndvcmRzW2kgLSAxMF0gPSBwcmV2O1xuICAgIGlmIChwcmV2ID09PSAwICYmIGlucHV0Lmxlbmd0aCA+IDEwKSB7XG4gICAgICBpbnB1dC5sZW5ndGggLT0gMTA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlucHV0Lmxlbmd0aCAtPSA5O1xuICAgIH1cbiAgfTtcblxuICBLMjU2LnByb3RvdHlwZS5pbXVsSyA9IGZ1bmN0aW9uIGltdWxLIChudW0pIHtcbiAgICAvLyBLID0gMHgxMDAwMDAzZDEgPSBbIDB4NDAsIDB4M2QxIF1cbiAgICBudW0ud29yZHNbbnVtLmxlbmd0aF0gPSAwO1xuICAgIG51bS53b3Jkc1tudW0ubGVuZ3RoICsgMV0gPSAwO1xuICAgIG51bS5sZW5ndGggKz0gMjtcblxuICAgIC8vIGJvdW5kZWQgYXQ6IDB4NDAgKiAweDNmZmZmZmYgKyAweDNkMCA9IDB4MTAwMDAwMzkwXG4gICAgdmFyIGxvID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHcgPSBudW0ud29yZHNbaV0gfCAwO1xuICAgICAgbG8gKz0gdyAqIDB4M2QxO1xuICAgICAgbnVtLndvcmRzW2ldID0gbG8gJiAweDNmZmZmZmY7XG4gICAgICBsbyA9IHcgKiAweDQwICsgKChsbyAvIDB4NDAwMDAwMCkgfCAwKTtcbiAgICB9XG5cbiAgICAvLyBGYXN0IGxlbmd0aCByZWR1Y3Rpb25cbiAgICBpZiAobnVtLndvcmRzW251bS5sZW5ndGggLSAxXSA9PT0gMCkge1xuICAgICAgbnVtLmxlbmd0aC0tO1xuICAgICAgaWYgKG51bS53b3Jkc1tudW0ubGVuZ3RoIC0gMV0gPT09IDApIHtcbiAgICAgICAgbnVtLmxlbmd0aC0tO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVtO1xuICB9O1xuXG4gIGZ1bmN0aW9uIFAyMjQgKCkge1xuICAgIE1QcmltZS5jYWxsKFxuICAgICAgdGhpcyxcbiAgICAgICdwMjI0JyxcbiAgICAgICdmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiAwMDAwMDAwMCAwMDAwMDAwMCAwMDAwMDAwMScpO1xuICB9XG4gIGluaGVyaXRzKFAyMjQsIE1QcmltZSk7XG5cbiAgZnVuY3Rpb24gUDE5MiAoKSB7XG4gICAgTVByaW1lLmNhbGwoXG4gICAgICB0aGlzLFxuICAgICAgJ3AxOTInLFxuICAgICAgJ2ZmZmZmZmZmIGZmZmZmZmZmIGZmZmZmZmZmIGZmZmZmZmZlIGZmZmZmZmZmIGZmZmZmZmZmJyk7XG4gIH1cbiAgaW5oZXJpdHMoUDE5MiwgTVByaW1lKTtcblxuICBmdW5jdGlvbiBQMjU1MTkgKCkge1xuICAgIC8vIDIgXiAyNTUgLSAxOVxuICAgIE1QcmltZS5jYWxsKFxuICAgICAgdGhpcyxcbiAgICAgICcyNTUxOScsXG4gICAgICAnN2ZmZmZmZmZmZmZmZmZmZiBmZmZmZmZmZmZmZmZmZmZmIGZmZmZmZmZmZmZmZmZmZmYgZmZmZmZmZmZmZmZmZmZlZCcpO1xuICB9XG4gIGluaGVyaXRzKFAyNTUxOSwgTVByaW1lKTtcblxuICBQMjU1MTkucHJvdG90eXBlLmltdWxLID0gZnVuY3Rpb24gaW11bEsgKG51bSkge1xuICAgIC8vIEsgPSAweDEzXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGhpID0gKG51bS53b3Jkc1tpXSB8IDApICogMHgxMyArIGNhcnJ5O1xuICAgICAgdmFyIGxvID0gaGkgJiAweDNmZmZmZmY7XG4gICAgICBoaSA+Pj49IDI2O1xuXG4gICAgICBudW0ud29yZHNbaV0gPSBsbztcbiAgICAgIGNhcnJ5ID0gaGk7XG4gICAgfVxuICAgIGlmIChjYXJyeSAhPT0gMCkge1xuICAgICAgbnVtLndvcmRzW251bS5sZW5ndGgrK10gPSBjYXJyeTtcbiAgICB9XG4gICAgcmV0dXJuIG51bTtcbiAgfTtcblxuICAvLyBFeHBvcnRlZCBtb3N0bHkgZm9yIHRlc3RpbmcgcHVycG9zZXMsIHVzZSBwbGFpbiBuYW1lIGluc3RlYWRcbiAgQk4uX3ByaW1lID0gZnVuY3Rpb24gcHJpbWUgKG5hbWUpIHtcbiAgICAvLyBDYWNoZWQgdmVyc2lvbiBvZiBwcmltZVxuICAgIGlmIChwcmltZXNbbmFtZV0pIHJldHVybiBwcmltZXNbbmFtZV07XG5cbiAgICB2YXIgcHJpbWU7XG4gICAgaWYgKG5hbWUgPT09ICdrMjU2Jykge1xuICAgICAgcHJpbWUgPSBuZXcgSzI1NigpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3AyMjQnKSB7XG4gICAgICBwcmltZSA9IG5ldyBQMjI0KCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAncDE5MicpIHtcbiAgICAgIHByaW1lID0gbmV3IFAxOTIoKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICdwMjU1MTknKSB7XG4gICAgICBwcmltZSA9IG5ldyBQMjU1MTkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHByaW1lICcgKyBuYW1lKTtcbiAgICB9XG4gICAgcHJpbWVzW25hbWVdID0gcHJpbWU7XG5cbiAgICByZXR1cm4gcHJpbWU7XG4gIH07XG5cbiAgLy9cbiAgLy8gQmFzZSByZWR1Y3Rpb24gZW5naW5lXG4gIC8vXG4gIGZ1bmN0aW9uIFJlZCAobSkge1xuICAgIGlmICh0eXBlb2YgbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHZhciBwcmltZSA9IEJOLl9wcmltZShtKTtcbiAgICAgIHRoaXMubSA9IHByaW1lLnA7XG4gICAgICB0aGlzLnByaW1lID0gcHJpbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2VydChtLmd0bigxKSwgJ21vZHVsdXMgbXVzdCBiZSBncmVhdGVyIHRoYW4gMScpO1xuICAgICAgdGhpcy5tID0gbTtcbiAgICAgIHRoaXMucHJpbWUgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIFJlZC5wcm90b3R5cGUuX3ZlcmlmeTEgPSBmdW5jdGlvbiBfdmVyaWZ5MSAoYSkge1xuICAgIGFzc2VydChhLm5lZ2F0aXZlID09PSAwLCAncmVkIHdvcmtzIG9ubHkgd2l0aCBwb3NpdGl2ZXMnKTtcbiAgICBhc3NlcnQoYS5yZWQsICdyZWQgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5fdmVyaWZ5MiA9IGZ1bmN0aW9uIF92ZXJpZnkyIChhLCBiKSB7XG4gICAgYXNzZXJ0KChhLm5lZ2F0aXZlIHwgYi5uZWdhdGl2ZSkgPT09IDAsICdyZWQgd29ya3Mgb25seSB3aXRoIHBvc2l0aXZlcycpO1xuICAgIGFzc2VydChhLnJlZCAmJiBhLnJlZCA9PT0gYi5yZWQsXG4gICAgICAncmVkIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuaW1vZCA9IGZ1bmN0aW9uIGltb2QgKGEpIHtcbiAgICBpZiAodGhpcy5wcmltZSkgcmV0dXJuIHRoaXMucHJpbWUuaXJlZHVjZShhKS5fZm9yY2VSZWQodGhpcyk7XG4gICAgcmV0dXJuIGEudW1vZCh0aGlzLm0pLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLm5lZyA9IGZ1bmN0aW9uIG5lZyAoYSkge1xuICAgIGlmIChhLmlzWmVybygpKSB7XG4gICAgICByZXR1cm4gYS5jbG9uZSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm0uc3ViKGEpLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZCAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG5cbiAgICB2YXIgcmVzID0gYS5hZGQoYik7XG4gICAgaWYgKHJlcy5jbXAodGhpcy5tKSA+PSAwKSB7XG4gICAgICByZXMuaXN1Yih0aGlzLm0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmlhZGQgPSBmdW5jdGlvbiBpYWRkIChhLCBiKSB7XG4gICAgdGhpcy5fdmVyaWZ5MihhLCBiKTtcblxuICAgIHZhciByZXMgPSBhLmlhZGQoYik7XG4gICAgaWYgKHJlcy5jbXAodGhpcy5tKSA+PSAwKSB7XG4gICAgICByZXMuaXN1Yih0aGlzLm0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuc3ViID0gZnVuY3Rpb24gc3ViIChhLCBiKSB7XG4gICAgdGhpcy5fdmVyaWZ5MihhLCBiKTtcblxuICAgIHZhciByZXMgPSBhLnN1YihiKTtcbiAgICBpZiAocmVzLmNtcG4oMCkgPCAwKSB7XG4gICAgICByZXMuaWFkZCh0aGlzLm0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmlzdWIgPSBmdW5jdGlvbiBpc3ViIChhLCBiKSB7XG4gICAgdGhpcy5fdmVyaWZ5MihhLCBiKTtcblxuICAgIHZhciByZXMgPSBhLmlzdWIoYik7XG4gICAgaWYgKHJlcy5jbXBuKDApIDwgMCkge1xuICAgICAgcmVzLmlhZGQodGhpcy5tKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLnNobCA9IGZ1bmN0aW9uIHNobCAoYSwgbnVtKSB7XG4gICAgdGhpcy5fdmVyaWZ5MShhKTtcbiAgICByZXR1cm4gdGhpcy5pbW9kKGEudXNobG4obnVtKSk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5pbXVsID0gZnVuY3Rpb24gaW11bCAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG4gICAgcmV0dXJuIHRoaXMuaW1vZChhLmltdWwoYikpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUubXVsID0gZnVuY3Rpb24gbXVsIChhLCBiKSB7XG4gICAgdGhpcy5fdmVyaWZ5MihhLCBiKTtcbiAgICByZXR1cm4gdGhpcy5pbW9kKGEubXVsKGIpKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmlzcXIgPSBmdW5jdGlvbiBpc3FyIChhKSB7XG4gICAgcmV0dXJuIHRoaXMuaW11bChhLCBhLmNsb25lKCkpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuc3FyID0gZnVuY3Rpb24gc3FyIChhKSB7XG4gICAgcmV0dXJuIHRoaXMubXVsKGEsIGEpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuc3FydCA9IGZ1bmN0aW9uIHNxcnQgKGEpIHtcbiAgICBpZiAoYS5pc1plcm8oKSkgcmV0dXJuIGEuY2xvbmUoKTtcblxuICAgIHZhciBtb2QzID0gdGhpcy5tLmFuZGxuKDMpO1xuICAgIGFzc2VydChtb2QzICUgMiA9PT0gMSk7XG5cbiAgICAvLyBGYXN0IGNhc2VcbiAgICBpZiAobW9kMyA9PT0gMykge1xuICAgICAgdmFyIHBvdyA9IHRoaXMubS5hZGQobmV3IEJOKDEpKS5pdXNocm4oMik7XG4gICAgICByZXR1cm4gdGhpcy5wb3coYSwgcG93KTtcbiAgICB9XG5cbiAgICAvLyBUb25lbGxpLVNoYW5rcyBhbGdvcml0aG0gKFRvdGFsbHkgdW5vcHRpbWl6ZWQgYW5kIHNsb3cpXG4gICAgLy9cbiAgICAvLyBGaW5kIFEgYW5kIFMsIHRoYXQgUSAqIDIgXiBTID0gKFAgLSAxKVxuICAgIHZhciBxID0gdGhpcy5tLnN1Ym4oMSk7XG4gICAgdmFyIHMgPSAwO1xuICAgIHdoaWxlICghcS5pc1plcm8oKSAmJiBxLmFuZGxuKDEpID09PSAwKSB7XG4gICAgICBzKys7XG4gICAgICBxLml1c2hybigxKTtcbiAgICB9XG4gICAgYXNzZXJ0KCFxLmlzWmVybygpKTtcblxuICAgIHZhciBvbmUgPSBuZXcgQk4oMSkudG9SZWQodGhpcyk7XG4gICAgdmFyIG5PbmUgPSBvbmUucmVkTmVnKCk7XG5cbiAgICAvLyBGaW5kIHF1YWRyYXRpYyBub24tcmVzaWR1ZVxuICAgIC8vIE5PVEU6IE1heCBpcyBzdWNoIGJlY2F1c2Ugb2YgZ2VuZXJhbGl6ZWQgUmllbWFubiBoeXBvdGhlc2lzLlxuICAgIHZhciBscG93ID0gdGhpcy5tLnN1Ym4oMSkuaXVzaHJuKDEpO1xuICAgIHZhciB6ID0gdGhpcy5tLmJpdExlbmd0aCgpO1xuICAgIHogPSBuZXcgQk4oMiAqIHogKiB6KS50b1JlZCh0aGlzKTtcblxuICAgIHdoaWxlICh0aGlzLnBvdyh6LCBscG93KS5jbXAobk9uZSkgIT09IDApIHtcbiAgICAgIHoucmVkSUFkZChuT25lKTtcbiAgICB9XG5cbiAgICB2YXIgYyA9IHRoaXMucG93KHosIHEpO1xuICAgIHZhciByID0gdGhpcy5wb3coYSwgcS5hZGRuKDEpLml1c2hybigxKSk7XG4gICAgdmFyIHQgPSB0aGlzLnBvdyhhLCBxKTtcbiAgICB2YXIgbSA9IHM7XG4gICAgd2hpbGUgKHQuY21wKG9uZSkgIT09IDApIHtcbiAgICAgIHZhciB0bXAgPSB0O1xuICAgICAgZm9yICh2YXIgaSA9IDA7IHRtcC5jbXAob25lKSAhPT0gMDsgaSsrKSB7XG4gICAgICAgIHRtcCA9IHRtcC5yZWRTcXIoKTtcbiAgICAgIH1cbiAgICAgIGFzc2VydChpIDwgbSk7XG4gICAgICB2YXIgYiA9IHRoaXMucG93KGMsIG5ldyBCTigxKS5pdXNobG4obSAtIGkgLSAxKSk7XG5cbiAgICAgIHIgPSByLnJlZE11bChiKTtcbiAgICAgIGMgPSBiLnJlZFNxcigpO1xuICAgICAgdCA9IHQucmVkTXVsKGMpO1xuICAgICAgbSA9IGk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5pbnZtID0gZnVuY3Rpb24gaW52bSAoYSkge1xuICAgIHZhciBpbnYgPSBhLl9pbnZtcCh0aGlzLm0pO1xuICAgIGlmIChpbnYubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIGludi5uZWdhdGl2ZSA9IDA7XG4gICAgICByZXR1cm4gdGhpcy5pbW9kKGludikucmVkTmVnKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmltb2QoaW52KTtcbiAgICB9XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5wb3cgPSBmdW5jdGlvbiBwb3cgKGEsIG51bSkge1xuICAgIGlmIChudW0uaXNaZXJvKCkpIHJldHVybiBuZXcgQk4oMSkudG9SZWQodGhpcyk7XG4gICAgaWYgKG51bS5jbXBuKDEpID09PSAwKSByZXR1cm4gYS5jbG9uZSgpO1xuXG4gICAgdmFyIHdpbmRvd1NpemUgPSA0O1xuICAgIHZhciB3bmQgPSBuZXcgQXJyYXkoMSA8PCB3aW5kb3dTaXplKTtcbiAgICB3bmRbMF0gPSBuZXcgQk4oMSkudG9SZWQodGhpcyk7XG4gICAgd25kWzFdID0gYTtcbiAgICBmb3IgKHZhciBpID0gMjsgaSA8IHduZC5sZW5ndGg7IGkrKykge1xuICAgICAgd25kW2ldID0gdGhpcy5tdWwod25kW2kgLSAxXSwgYSk7XG4gICAgfVxuXG4gICAgdmFyIHJlcyA9IHduZFswXTtcbiAgICB2YXIgY3VycmVudCA9IDA7XG4gICAgdmFyIGN1cnJlbnRMZW4gPSAwO1xuICAgIHZhciBzdGFydCA9IG51bS5iaXRMZW5ndGgoKSAlIDI2O1xuICAgIGlmIChzdGFydCA9PT0gMCkge1xuICAgICAgc3RhcnQgPSAyNjtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSBudW0ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciB3b3JkID0gbnVtLndvcmRzW2ldO1xuICAgICAgZm9yICh2YXIgaiA9IHN0YXJ0IC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgdmFyIGJpdCA9ICh3b3JkID4+IGopICYgMTtcbiAgICAgICAgaWYgKHJlcyAhPT0gd25kWzBdKSB7XG4gICAgICAgICAgcmVzID0gdGhpcy5zcXIocmVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiaXQgPT09IDAgJiYgY3VycmVudCA9PT0gMCkge1xuICAgICAgICAgIGN1cnJlbnRMZW4gPSAwO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY3VycmVudCA8PD0gMTtcbiAgICAgICAgY3VycmVudCB8PSBiaXQ7XG4gICAgICAgIGN1cnJlbnRMZW4rKztcbiAgICAgICAgaWYgKGN1cnJlbnRMZW4gIT09IHdpbmRvd1NpemUgJiYgKGkgIT09IDAgfHwgaiAhPT0gMCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIHJlcyA9IHRoaXMubXVsKHJlcywgd25kW2N1cnJlbnRdKTtcbiAgICAgICAgY3VycmVudExlbiA9IDA7XG4gICAgICAgIGN1cnJlbnQgPSAwO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSAyNjtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuY29udmVydFRvID0gZnVuY3Rpb24gY29udmVydFRvIChudW0pIHtcbiAgICB2YXIgciA9IG51bS51bW9kKHRoaXMubSk7XG5cbiAgICByZXR1cm4gciA9PT0gbnVtID8gci5jbG9uZSgpIDogcjtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmNvbnZlcnRGcm9tID0gZnVuY3Rpb24gY29udmVydEZyb20gKG51bSkge1xuICAgIHZhciByZXMgPSBudW0uY2xvbmUoKTtcbiAgICByZXMucmVkID0gbnVsbDtcbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIC8vXG4gIC8vIE1vbnRnb21lcnkgbWV0aG9kIGVuZ2luZVxuICAvL1xuXG4gIEJOLm1vbnQgPSBmdW5jdGlvbiBtb250IChudW0pIHtcbiAgICByZXR1cm4gbmV3IE1vbnQobnVtKTtcbiAgfTtcblxuICBmdW5jdGlvbiBNb250IChtKSB7XG4gICAgUmVkLmNhbGwodGhpcywgbSk7XG5cbiAgICB0aGlzLnNoaWZ0ID0gdGhpcy5tLmJpdExlbmd0aCgpO1xuICAgIGlmICh0aGlzLnNoaWZ0ICUgMjYgIT09IDApIHtcbiAgICAgIHRoaXMuc2hpZnQgKz0gMjYgLSAodGhpcy5zaGlmdCAlIDI2KTtcbiAgICB9XG5cbiAgICB0aGlzLnIgPSBuZXcgQk4oMSkuaXVzaGxuKHRoaXMuc2hpZnQpO1xuICAgIHRoaXMucjIgPSB0aGlzLmltb2QodGhpcy5yLnNxcigpKTtcbiAgICB0aGlzLnJpbnYgPSB0aGlzLnIuX2ludm1wKHRoaXMubSk7XG5cbiAgICB0aGlzLm1pbnYgPSB0aGlzLnJpbnYubXVsKHRoaXMucikuaXN1Ym4oMSkuZGl2KHRoaXMubSk7XG4gICAgdGhpcy5taW52ID0gdGhpcy5taW52LnVtb2QodGhpcy5yKTtcbiAgICB0aGlzLm1pbnYgPSB0aGlzLnIuc3ViKHRoaXMubWludik7XG4gIH1cbiAgaW5oZXJpdHMoTW9udCwgUmVkKTtcblxuICBNb250LnByb3RvdHlwZS5jb252ZXJ0VG8gPSBmdW5jdGlvbiBjb252ZXJ0VG8gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmltb2QobnVtLnVzaGxuKHRoaXMuc2hpZnQpKTtcbiAgfTtcblxuICBNb250LnByb3RvdHlwZS5jb252ZXJ0RnJvbSA9IGZ1bmN0aW9uIGNvbnZlcnRGcm9tIChudW0pIHtcbiAgICB2YXIgciA9IHRoaXMuaW1vZChudW0ubXVsKHRoaXMucmludikpO1xuICAgIHIucmVkID0gbnVsbDtcbiAgICByZXR1cm4gcjtcbiAgfTtcblxuICBNb250LnByb3RvdHlwZS5pbXVsID0gZnVuY3Rpb24gaW11bCAoYSwgYikge1xuICAgIGlmIChhLmlzWmVybygpIHx8IGIuaXNaZXJvKCkpIHtcbiAgICAgIGEud29yZHNbMF0gPSAwO1xuICAgICAgYS5sZW5ndGggPSAxO1xuICAgICAgcmV0dXJuIGE7XG4gICAgfVxuXG4gICAgdmFyIHQgPSBhLmltdWwoYik7XG4gICAgdmFyIGMgPSB0Lm1hc2tuKHRoaXMuc2hpZnQpLm11bCh0aGlzLm1pbnYpLmltYXNrbih0aGlzLnNoaWZ0KS5tdWwodGhpcy5tKTtcbiAgICB2YXIgdSA9IHQuaXN1YihjKS5pdXNocm4odGhpcy5zaGlmdCk7XG4gICAgdmFyIHJlcyA9IHU7XG5cbiAgICBpZiAodS5jbXAodGhpcy5tKSA+PSAwKSB7XG4gICAgICByZXMgPSB1LmlzdWIodGhpcy5tKTtcbiAgICB9IGVsc2UgaWYgKHUuY21wbigwKSA8IDApIHtcbiAgICAgIHJlcyA9IHUuaWFkZCh0aGlzLm0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXMuX2ZvcmNlUmVkKHRoaXMpO1xuICB9O1xuXG4gIE1vbnQucHJvdG90eXBlLm11bCA9IGZ1bmN0aW9uIG11bCAoYSwgYikge1xuICAgIGlmIChhLmlzWmVybygpIHx8IGIuaXNaZXJvKCkpIHJldHVybiBuZXcgQk4oMCkuX2ZvcmNlUmVkKHRoaXMpO1xuXG4gICAgdmFyIHQgPSBhLm11bChiKTtcbiAgICB2YXIgYyA9IHQubWFza24odGhpcy5zaGlmdCkubXVsKHRoaXMubWludikuaW1hc2tuKHRoaXMuc2hpZnQpLm11bCh0aGlzLm0pO1xuICAgIHZhciB1ID0gdC5pc3ViKGMpLml1c2hybih0aGlzLnNoaWZ0KTtcbiAgICB2YXIgcmVzID0gdTtcbiAgICBpZiAodS5jbXAodGhpcy5tKSA+PSAwKSB7XG4gICAgICByZXMgPSB1LmlzdWIodGhpcy5tKTtcbiAgICB9IGVsc2UgaWYgKHUuY21wbigwKSA8IDApIHtcbiAgICAgIHJlcyA9IHUuaWFkZCh0aGlzLm0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXMuX2ZvcmNlUmVkKHRoaXMpO1xuICB9O1xuXG4gIE1vbnQucHJvdG90eXBlLmludm0gPSBmdW5jdGlvbiBpbnZtIChhKSB7XG4gICAgLy8gKEFSKV4tMSAqIFJeMiA9IChBXi0xICogUl4tMSkgKiBSXjIgPSBBXi0xICogUlxuICAgIHZhciByZXMgPSB0aGlzLmltb2QoYS5faW52bXAodGhpcy5tKS5tdWwodGhpcy5yMikpO1xuICAgIHJldHVybiByZXMuX2ZvcmNlUmVkKHRoaXMpO1xuICB9O1xufSkodHlwZW9mIG1vZHVsZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbW9kdWxlLCB0aGlzKTtcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJvdW5kYXJ5XG5cbmZ1bmN0aW9uIGJvdW5kYXJ5IChjZWxscykge1xuICB2YXIgaSwgaiwga1xuICB2YXIgbiA9IGNlbGxzLmxlbmd0aFxuICB2YXIgc3ogPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBzeiArPSBjZWxsc1tpXS5sZW5ndGhcbiAgfVxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KHN6KVxuICB2YXIgcHRyID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIHZhciBkID0gYy5sZW5ndGhcbiAgICBmb3IgKGogPSAwOyBqIDwgZDsgKytqKSB7XG4gICAgICB2YXIgYiA9IHJlc3VsdFtwdHIrK10gPSBuZXcgQXJyYXkoZCAtIDEpXG4gICAgICB2YXIgcCA9IDBcbiAgICAgIGZvciAoayA9IDA7IGsgPCBkOyArK2spIHtcbiAgICAgICAgaWYgKGsgPT09IGopIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGJbcCsrXSA9IGNba11cbiAgICAgIH1cbiAgICAgIGlmIChqICYgMSkge1xuICAgICAgICB2YXIgdG1wID0gYlsxXVxuICAgICAgICBiWzFdID0gYlswXVxuICAgICAgICBiWzBdID0gdG1wXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJveEludGVyc2VjdFdyYXBwZXJcblxudmFyIHBvb2wgPSByZXF1aXJlKCd0eXBlZGFycmF5LXBvb2wnKVxudmFyIHN3ZWVwID0gcmVxdWlyZSgnLi9saWIvc3dlZXAnKVxudmFyIGJveEludGVyc2VjdEl0ZXIgPSByZXF1aXJlKCcuL2xpYi9pbnRlcnNlY3QnKVxuXG5mdW5jdGlvbiBib3hFbXB0eShkLCBib3gpIHtcbiAgZm9yKHZhciBqPTA7IGo8ZDsgKytqKSB7XG4gICAgaWYoIShib3hbal0gPD0gYm94W2orZF0pKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxuLy9VbnBhY2sgYm94ZXMgaW50byBhIGZsYXQgdHlwZWQgYXJyYXksIHJlbW92ZSBlbXB0eSBib3hlc1xuZnVuY3Rpb24gY29udmVydEJveGVzKGJveGVzLCBkLCBkYXRhLCBpZHMpIHtcbiAgdmFyIHB0ciA9IDBcbiAgdmFyIGNvdW50ID0gMFxuICBmb3IodmFyIGk9MCwgbj1ib3hlcy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgdmFyIGIgPSBib3hlc1tpXVxuICAgIGlmKGJveEVtcHR5KGQsIGIpKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBmb3IodmFyIGo9MDsgajwyKmQ7ICsraikge1xuICAgICAgZGF0YVtwdHIrK10gPSBiW2pdXG4gICAgfVxuICAgIGlkc1tjb3VudCsrXSA9IGlcbiAgfVxuICByZXR1cm4gY291bnRcbn1cblxuLy9QZXJmb3JtIHR5cGUgY29udmVyc2lvbnMsIGNoZWNrIGJvdW5kc1xuZnVuY3Rpb24gYm94SW50ZXJzZWN0KHJlZCwgYmx1ZSwgdmlzaXQsIGZ1bGwpIHtcbiAgdmFyIG4gPSByZWQubGVuZ3RoXG4gIHZhciBtID0gYmx1ZS5sZW5ndGhcblxuICAvL0lmIGVpdGhlciBhcnJheSBpcyBlbXB0eSwgdGhlbiB3ZSBjYW4gc2tpcCB0aGlzIHdob2xlIHRoaW5nXG4gIGlmKG4gPD0gMCB8fCBtIDw9IDApIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vQ29tcHV0ZSBkaW1lbnNpb24sIGlmIGl0IGlzIDAgdGhlbiB3ZSBza2lwXG4gIHZhciBkID0gKHJlZFswXS5sZW5ndGgpPj4+MVxuICBpZihkIDw9IDApIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciByZXR2YWxcblxuICAvL0NvbnZlcnQgcmVkIGJveGVzXG4gIHZhciByZWRMaXN0ICA9IHBvb2wubWFsbG9jRG91YmxlKDIqZCpuKVxuICB2YXIgcmVkSWRzICAgPSBwb29sLm1hbGxvY0ludDMyKG4pXG4gIG4gPSBjb252ZXJ0Qm94ZXMocmVkLCBkLCByZWRMaXN0LCByZWRJZHMpXG5cbiAgaWYobiA+IDApIHtcbiAgICBpZihkID09PSAxICYmIGZ1bGwpIHtcbiAgICAgIC8vU3BlY2lhbCBjYXNlOiAxZCBjb21wbGV0ZVxuICAgICAgc3dlZXAuaW5pdChuKVxuICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBDb21wbGV0ZShcbiAgICAgICAgZCwgdmlzaXQsIFxuICAgICAgICAwLCBuLCByZWRMaXN0LCByZWRJZHMsXG4gICAgICAgIDAsIG4sIHJlZExpc3QsIHJlZElkcylcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvL0NvbnZlcnQgYmx1ZSBib3hlc1xuICAgICAgdmFyIGJsdWVMaXN0ID0gcG9vbC5tYWxsb2NEb3VibGUoMipkKm0pXG4gICAgICB2YXIgYmx1ZUlkcyAgPSBwb29sLm1hbGxvY0ludDMyKG0pXG4gICAgICBtID0gY29udmVydEJveGVzKGJsdWUsIGQsIGJsdWVMaXN0LCBibHVlSWRzKVxuXG4gICAgICBpZihtID4gMCkge1xuICAgICAgICBzd2VlcC5pbml0KG4rbSlcblxuICAgICAgICBpZihkID09PSAxKSB7XG4gICAgICAgICAgLy9TcGVjaWFsIGNhc2U6IDFkIGJpcGFydGl0ZVxuICAgICAgICAgIHJldHZhbCA9IHN3ZWVwLnN3ZWVwQmlwYXJ0aXRlKFxuICAgICAgICAgICAgZCwgdmlzaXQsIFxuICAgICAgICAgICAgMCwgbiwgcmVkTGlzdCwgIHJlZElkcyxcbiAgICAgICAgICAgIDAsIG0sIGJsdWVMaXN0LCBibHVlSWRzKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vR2VuZXJhbCBjYXNlOiAgZD4xXG4gICAgICAgICAgcmV0dmFsID0gYm94SW50ZXJzZWN0SXRlcihcbiAgICAgICAgICAgIGQsIHZpc2l0LCAgICBmdWxsLFxuICAgICAgICAgICAgbiwgcmVkTGlzdCwgIHJlZElkcyxcbiAgICAgICAgICAgIG0sIGJsdWVMaXN0LCBibHVlSWRzKVxuICAgICAgICB9XG5cbiAgICAgICAgcG9vbC5mcmVlKGJsdWVMaXN0KVxuICAgICAgICBwb29sLmZyZWUoYmx1ZUlkcylcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwb29sLmZyZWUocmVkTGlzdClcbiAgICBwb29sLmZyZWUocmVkSWRzKVxuICB9XG5cbiAgcmV0dXJuIHJldHZhbFxufVxuXG5cbnZhciBSRVNVTFRcblxuZnVuY3Rpb24gYXBwZW5kSXRlbShpLGopIHtcbiAgUkVTVUxULnB1c2goW2ksal0pXG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdEZ1bGxBcnJheSh4KSB7XG4gIFJFU1VMVCA9IFtdXG4gIGJveEludGVyc2VjdCh4LCB4LCBhcHBlbmRJdGVtLCB0cnVlKVxuICByZXR1cm4gUkVTVUxUXG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdEJpcGFydGl0ZUFycmF5KHgsIHkpIHtcbiAgUkVTVUxUID0gW11cbiAgYm94SW50ZXJzZWN0KHgsIHksIGFwcGVuZEl0ZW0sIGZhbHNlKVxuICByZXR1cm4gUkVTVUxUXG59XG5cbi8vVXNlci1mcmllbmRseSB3cmFwcGVyLCBoYW5kbGUgZnVsbCBpbnB1dCBhbmQgbm8tdmlzaXRvciBjYXNlc1xuZnVuY3Rpb24gYm94SW50ZXJzZWN0V3JhcHBlcihhcmcwLCBhcmcxLCBhcmcyKSB7XG4gIHZhciByZXN1bHRcbiAgc3dpdGNoKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gaW50ZXJzZWN0RnVsbEFycmF5KGFyZzApXG4gICAgY2FzZSAyOlxuICAgICAgaWYodHlwZW9mIGFyZzEgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGJveEludGVyc2VjdChhcmcwLCBhcmcwLCBhcmcxLCB0cnVlKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGludGVyc2VjdEJpcGFydGl0ZUFycmF5KGFyZzAsIGFyZzEpXG4gICAgICB9XG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuIGJveEludGVyc2VjdChhcmcwLCBhcmcxLCBhcmcyLCBmYWxzZSlcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdib3gtaW50ZXJzZWN0OiBJbnZhbGlkIGFyZ3VtZW50cycpXG4gIH1cbn0iLCIndXNlIHN0cmljdCdcblxudmFyIERJTUVOU0lPTiAgID0gJ2QnXG52YXIgQVhJUyAgICAgICAgPSAnYXgnXG52YXIgVklTSVQgICAgICAgPSAndnYnXG52YXIgRkxJUCAgICAgICAgPSAnZnAnXG5cbnZhciBFTEVNX1NJWkUgICA9ICdlcydcblxudmFyIFJFRF9TVEFSVCAgID0gJ3JzJ1xudmFyIFJFRF9FTkQgICAgID0gJ3JlJ1xudmFyIFJFRF9CT1hFUyAgID0gJ3JiJ1xudmFyIFJFRF9JTkRFWCAgID0gJ3JpJ1xudmFyIFJFRF9QVFIgICAgID0gJ3JwJ1xuXG52YXIgQkxVRV9TVEFSVCAgPSAnYnMnXG52YXIgQkxVRV9FTkQgICAgPSAnYmUnXG52YXIgQkxVRV9CT1hFUyAgPSAnYmInXG52YXIgQkxVRV9JTkRFWCAgPSAnYmknXG52YXIgQkxVRV9QVFIgICAgPSAnYnAnXG5cbnZhciBSRVRWQUwgICAgICA9ICdydidcblxudmFyIElOTkVSX0xBQkVMID0gJ1EnXG5cbnZhciBBUkdTID0gW1xuICBESU1FTlNJT04sXG4gIEFYSVMsXG4gIFZJU0lULFxuICBSRURfU1RBUlQsXG4gIFJFRF9FTkQsXG4gIFJFRF9CT1hFUyxcbiAgUkVEX0lOREVYLFxuICBCTFVFX1NUQVJULFxuICBCTFVFX0VORCxcbiAgQkxVRV9CT1hFUyxcbiAgQkxVRV9JTkRFWFxuXVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUJydXRlRm9yY2UocmVkTWFqb3IsIGZsaXAsIGZ1bGwpIHtcbiAgdmFyIGZ1bmNOYW1lID0gJ2JydXRlRm9yY2UnICsgXG4gICAgKHJlZE1ham9yID8gJ1JlZCcgOiAnQmx1ZScpICsgXG4gICAgKGZsaXAgPyAnRmxpcCcgOiAnJykgK1xuICAgIChmdWxsID8gJ0Z1bGwnIDogJycpXG5cbiAgdmFyIGNvZGUgPSBbJ2Z1bmN0aW9uICcsIGZ1bmNOYW1lLCAnKCcsIEFSR1Muam9pbigpLCAnKXsnLFxuICAgICd2YXIgJywgRUxFTV9TSVpFLCAnPTIqJywgRElNRU5TSU9OLCAnOyddXG5cbiAgdmFyIHJlZExvb3AgPSBcbiAgICAnZm9yKHZhciBpPScgKyBSRURfU1RBUlQgKyAnLCcgKyBSRURfUFRSICsgJz0nICsgRUxFTV9TSVpFICsgJyonICsgUkVEX1NUQVJUICsgJzsnICtcbiAgICAgICAgJ2k8JyArIFJFRF9FTkQgKyc7JyArXG4gICAgICAgICcrK2ksJyArIFJFRF9QVFIgKyAnKz0nICsgRUxFTV9TSVpFICsgJyl7JyArXG4gICAgICAgICd2YXIgeDA9JyArIFJFRF9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBSRURfUFRSICsgJ10sJyArXG4gICAgICAgICAgICAneDE9JyArIFJFRF9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBSRURfUFRSICsgJysnICsgRElNRU5TSU9OICsgJ10sJyArXG4gICAgICAgICAgICAneGk9JyArIFJFRF9JTkRFWCArICdbaV07J1xuXG4gIHZhciBibHVlTG9vcCA9IFxuICAgICdmb3IodmFyIGo9JyArIEJMVUVfU1RBUlQgKyAnLCcgKyBCTFVFX1BUUiArICc9JyArIEVMRU1fU0laRSArICcqJyArIEJMVUVfU1RBUlQgKyAnOycgK1xuICAgICAgICAnajwnICsgQkxVRV9FTkQgKyAnOycgK1xuICAgICAgICAnKytqLCcgKyBCTFVFX1BUUiArICcrPScgKyBFTEVNX1NJWkUgKyAnKXsnICtcbiAgICAgICAgJ3ZhciB5MD0nICsgQkxVRV9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBCTFVFX1BUUiArICddLCcgK1xuICAgICAgICAgICAgKGZ1bGwgPyAneTE9JyArIEJMVUVfQk9YRVMgKyAnWycgKyBBWElTICsgJysnICsgQkxVRV9QVFIgKyAnKycgKyBESU1FTlNJT04gKyAnXSwnIDogJycpICtcbiAgICAgICAgICAgICd5aT0nICsgQkxVRV9JTkRFWCArICdbal07J1xuXG4gIGlmKHJlZE1ham9yKSB7XG4gICAgY29kZS5wdXNoKHJlZExvb3AsIElOTkVSX0xBQkVMLCAnOicsIGJsdWVMb29wKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChibHVlTG9vcCwgSU5ORVJfTEFCRUwsICc6JywgcmVkTG9vcClcbiAgfVxuXG4gIGlmKGZ1bGwpIHtcbiAgICBjb2RlLnB1c2goJ2lmKHkxPHgwfHx4MTx5MCljb250aW51ZTsnKVxuICB9IGVsc2UgaWYoZmxpcCkge1xuICAgIGNvZGUucHVzaCgnaWYoeTA8PXgwfHx4MTx5MCljb250aW51ZTsnKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaCgnaWYoeTA8eDB8fHgxPHkwKWNvbnRpbnVlOycpXG4gIH1cblxuICBjb2RlLnB1c2goJ2Zvcih2YXIgaz0nK0FYSVMrJysxO2s8JytESU1FTlNJT04rJzsrK2speycrXG4gICAgJ3ZhciByMD0nK1JFRF9CT1hFUysnW2srJytSRURfUFRSKyddLCcrXG4gICAgICAgICdyMT0nK1JFRF9CT1hFUysnW2srJytESU1FTlNJT04rJysnK1JFRF9QVFIrJ10sJytcbiAgICAgICAgJ2IwPScrQkxVRV9CT1hFUysnW2srJytCTFVFX1BUUisnXSwnK1xuICAgICAgICAnYjE9JytCTFVFX0JPWEVTKydbaysnK0RJTUVOU0lPTisnKycrQkxVRV9QVFIrJ107JytcbiAgICAgICdpZihyMTxiMHx8YjE8cjApY29udGludWUgJyArIElOTkVSX0xBQkVMICsgJzt9JyArXG4gICAgICAndmFyICcgKyBSRVRWQUwgKyAnPScgKyBWSVNJVCArICcoJylcblxuICBpZihmbGlwKSB7XG4gICAgY29kZS5wdXNoKCd5aSx4aScpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKCd4aSx5aScpXG4gIH1cblxuICBjb2RlLnB1c2goJyk7aWYoJyArIFJFVFZBTCArICchPT12b2lkIDApcmV0dXJuICcgKyBSRVRWQUwgKyAnO319fScpXG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBmdW5jTmFtZSwgXG4gICAgY29kZTogY29kZS5qb2luKCcnKVxuICB9XG59XG5cbmZ1bmN0aW9uIGJydXRlRm9yY2VQbGFubmVyKGZ1bGwpIHtcbiAgdmFyIGZ1bmNOYW1lID0gJ2JydXRlRm9yY2UnICsgKGZ1bGwgPyAnRnVsbCcgOiAnUGFydGlhbCcpXG4gIHZhciBwcmVmaXggPSBbXVxuICB2YXIgZmFyZ3MgPSBBUkdTLnNsaWNlKClcbiAgaWYoIWZ1bGwpIHtcbiAgICBmYXJncy5zcGxpY2UoMywgMCwgRkxJUClcbiAgfVxuXG4gIHZhciBjb2RlID0gWydmdW5jdGlvbiAnICsgZnVuY05hbWUgKyAnKCcgKyBmYXJncy5qb2luKCkgKyAnKXsnXVxuXG4gIGZ1bmN0aW9uIGludm9rZShyZWRNYWpvciwgZmxpcCkge1xuICAgIHZhciByZXMgPSBnZW5lcmF0ZUJydXRlRm9yY2UocmVkTWFqb3IsIGZsaXAsIGZ1bGwpXG4gICAgcHJlZml4LnB1c2gocmVzLmNvZGUpXG4gICAgY29kZS5wdXNoKCdyZXR1cm4gJyArIHJlcy5uYW1lICsgJygnICsgQVJHUy5qb2luKCkgKyAnKTsnKVxuICB9XG5cbiAgY29kZS5wdXNoKCdpZignICsgUkVEX0VORCArICctJyArIFJFRF9TVEFSVCArICc+JyArXG4gICAgICAgICAgICAgICAgICAgIEJMVUVfRU5EICsgJy0nICsgQkxVRV9TVEFSVCArICcpeycpXG5cbiAgaWYoZnVsbCkge1xuICAgIGludm9rZSh0cnVlLCBmYWxzZSlcbiAgICBjb2RlLnB1c2goJ31lbHNleycpXG4gICAgaW52b2tlKGZhbHNlLCBmYWxzZSlcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goJ2lmKCcgKyBGTElQICsgJyl7JylcbiAgICBpbnZva2UodHJ1ZSwgdHJ1ZSlcbiAgICBjb2RlLnB1c2goJ31lbHNleycpXG4gICAgaW52b2tlKHRydWUsIGZhbHNlKVxuICAgIGNvZGUucHVzaCgnfX1lbHNle2lmKCcgKyBGTElQICsgJyl7JylcbiAgICBpbnZva2UoZmFsc2UsIHRydWUpXG4gICAgY29kZS5wdXNoKCd9ZWxzZXsnKVxuICAgIGludm9rZShmYWxzZSwgZmFsc2UpXG4gICAgY29kZS5wdXNoKCd9JylcbiAgfVxuICBjb2RlLnB1c2goJ319cmV0dXJuICcgKyBmdW5jTmFtZSlcblxuICB2YXIgY29kZVN0ciA9IHByZWZpeC5qb2luKCcnKSArIGNvZGUuam9pbignJylcbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oY29kZVN0cilcbiAgcmV0dXJuIHByb2MoKVxufVxuXG5cbmV4cG9ydHMucGFydGlhbCA9IGJydXRlRm9yY2VQbGFubmVyKGZhbHNlKVxuZXhwb3J0cy5mdWxsICAgID0gYnJ1dGVGb3JjZVBsYW5uZXIodHJ1ZSkiLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBib3hJbnRlcnNlY3RJdGVyXG5cbnZhciBwb29sID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcbnZhciBiaXRzID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKVxudmFyIGJydXRlRm9yY2UgPSByZXF1aXJlKCcuL2JydXRlJylcbnZhciBicnV0ZUZvcmNlUGFydGlhbCA9IGJydXRlRm9yY2UucGFydGlhbFxudmFyIGJydXRlRm9yY2VGdWxsID0gYnJ1dGVGb3JjZS5mdWxsXG52YXIgc3dlZXAgPSByZXF1aXJlKCcuL3N3ZWVwJylcbnZhciBmaW5kTWVkaWFuID0gcmVxdWlyZSgnLi9tZWRpYW4nKVxudmFyIGdlblBhcnRpdGlvbiA9IHJlcXVpcmUoJy4vcGFydGl0aW9uJylcblxuLy9Ud2lkZGxlIHBhcmFtZXRlcnNcbnZhciBCUlVURV9GT1JDRV9DVVRPRkYgICAgPSAxMjggICAgICAgLy9DdXQgb2ZmIGZvciBicnV0ZSBmb3JjZSBzZWFyY2hcbnZhciBTQ0FOX0NVVE9GRiAgICAgICAgICAgPSAoMTw8MjIpICAgLy9DdXQgb2ZmIGZvciB0d28gd2F5IHNjYW5cbnZhciBTQ0FOX0NPTVBMRVRFX0NVVE9GRiAgPSAoMTw8MjIpICBcblxuLy9QYXJ0aXRpb24gZnVuY3Rpb25zXG52YXIgcGFydGl0aW9uSW50ZXJpb3JDb250YWluc0ludGVydmFsID0gZ2VuUGFydGl0aW9uKFxuICAnIShsbz49cDApJiYhKHAxPj1oaSknLCBcbiAgWydwMCcsICdwMSddKVxuXG52YXIgcGFydGl0aW9uU3RhcnRFcXVhbCA9IGdlblBhcnRpdGlvbihcbiAgJ2xvPT09cDAnLFxuICBbJ3AwJ10pXG5cbnZhciBwYXJ0aXRpb25TdGFydExlc3NUaGFuID0gZ2VuUGFydGl0aW9uKFxuICAnbG88cDAnLFxuICBbJ3AwJ10pXG5cbnZhciBwYXJ0aXRpb25FbmRMZXNzVGhhbkVxdWFsID0gZ2VuUGFydGl0aW9uKFxuICAnaGk8PXAwJyxcbiAgWydwMCddKVxuXG52YXIgcGFydGl0aW9uQ29udGFpbnNQb2ludCA9IGdlblBhcnRpdGlvbihcbiAgJ2xvPD1wMCYmcDA8PWhpJyxcbiAgWydwMCddKVxuXG52YXIgcGFydGl0aW9uQ29udGFpbnNQb2ludFByb3BlciA9IGdlblBhcnRpdGlvbihcbiAgJ2xvPHAwJiZwMDw9aGknLFxuICBbJ3AwJ10pXG5cbi8vRnJhbWUgc2l6ZSBmb3IgaXRlcmF0aXZlIGxvb3BcbnZhciBJRlJBTUVfU0laRSA9IDZcbnZhciBERlJBTUVfU0laRSA9IDJcblxuLy9EYXRhIGZvciBib3ggc3RhdGNrXG52YXIgSU5JVF9DQVBBQ0lUWSA9IDEwMjRcbnZhciBCT1hfSVNUQUNLICA9IHBvb2wubWFsbG9jSW50MzIoSU5JVF9DQVBBQ0lUWSlcbnZhciBCT1hfRFNUQUNLICA9IHBvb2wubWFsbG9jRG91YmxlKElOSVRfQ0FQQUNJVFkpXG5cbi8vSW5pdGlhbGl6ZSBpdGVyYXRpdmUgbG9vcCBxdWV1ZVxuZnVuY3Rpb24gaXRlckluaXQoZCwgY291bnQpIHtcbiAgdmFyIGxldmVscyA9ICg4ICogYml0cy5sb2cyKGNvdW50KzEpICogKGQrMSkpfDBcbiAgdmFyIG1heEludHMgPSBiaXRzLm5leHRQb3cyKElGUkFNRV9TSVpFKmxldmVscylcbiAgaWYoQk9YX0lTVEFDSy5sZW5ndGggPCBtYXhJbnRzKSB7XG4gICAgcG9vbC5mcmVlKEJPWF9JU1RBQ0spXG4gICAgQk9YX0lTVEFDSyA9IHBvb2wubWFsbG9jSW50MzIobWF4SW50cylcbiAgfVxuICB2YXIgbWF4RG91YmxlcyA9IGJpdHMubmV4dFBvdzIoREZSQU1FX1NJWkUqbGV2ZWxzKVxuICBpZihCT1hfRFNUQUNLIDwgbWF4RG91Ymxlcykge1xuICAgIHBvb2wuZnJlZShCT1hfRFNUQUNLKVxuICAgIEJPWF9EU1RBQ0sgPSBwb29sLm1hbGxvY0RvdWJsZShtYXhEb3VibGVzKVxuICB9XG59XG5cbi8vQXBwZW5kIGl0ZW0gdG8gcXVldWVcbmZ1bmN0aW9uIGl0ZXJQdXNoKHB0cixcbiAgYXhpcywgXG4gIHJlZFN0YXJ0LCByZWRFbmQsIFxuICBibHVlU3RhcnQsIGJsdWVFbmQsIFxuICBzdGF0ZSwgXG4gIGxvLCBoaSkge1xuXG4gIHZhciBpcHRyID0gSUZSQU1FX1NJWkUgKiBwdHJcbiAgQk9YX0lTVEFDS1tpcHRyXSAgID0gYXhpc1xuICBCT1hfSVNUQUNLW2lwdHIrMV0gPSByZWRTdGFydFxuICBCT1hfSVNUQUNLW2lwdHIrMl0gPSByZWRFbmRcbiAgQk9YX0lTVEFDS1tpcHRyKzNdID0gYmx1ZVN0YXJ0XG4gIEJPWF9JU1RBQ0tbaXB0cis0XSA9IGJsdWVFbmRcbiAgQk9YX0lTVEFDS1tpcHRyKzVdID0gc3RhdGVcblxuICB2YXIgZHB0ciA9IERGUkFNRV9TSVpFICogcHRyXG4gIEJPWF9EU1RBQ0tbZHB0cl0gICA9IGxvXG4gIEJPWF9EU1RBQ0tbZHB0cisxXSA9IGhpXG59XG5cbi8vU3BlY2lhbCBjYXNlOiAgSW50ZXJzZWN0IHNpbmdsZSBwb2ludCB3aXRoIGxpc3Qgb2YgaW50ZXJ2YWxzXG5mdW5jdGlvbiBvbmVQb2ludFBhcnRpYWwoXG4gIGQsIGF4aXMsIHZpc2l0LCBmbGlwLFxuICByZWRTdGFydCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICBibHVlT2Zmc2V0LCBibHVlLCBibHVlSWQpIHtcblxuICB2YXIgZWxlbVNpemUgPSAyICogZFxuICB2YXIgYmx1ZVB0ciAgPSBibHVlT2Zmc2V0ICogZWxlbVNpemVcbiAgdmFyIGJsdWVYICAgID0gYmx1ZVtibHVlUHRyICsgYXhpc11cblxucmVkX2xvb3A6XG4gIGZvcih2YXIgaT1yZWRTdGFydCwgcmVkUHRyPXJlZFN0YXJ0KmVsZW1TaXplOyBpPHJlZEVuZDsgKytpLCByZWRQdHIrPWVsZW1TaXplKSB7XG4gICAgdmFyIHIwID0gcmVkW3JlZFB0citheGlzXVxuICAgIHZhciByMSA9IHJlZFtyZWRQdHIrYXhpcytkXVxuICAgIGlmKGJsdWVYIDwgcjAgfHwgcjEgPCBibHVlWCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYoZmxpcCAmJiBibHVlWCA9PT0gcjApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIHZhciByZWRJZCA9IHJlZEluZGV4W2ldXG4gICAgZm9yKHZhciBqPWF4aXMrMTsgajxkOyArK2opIHtcbiAgICAgIHZhciByMCA9IHJlZFtyZWRQdHIral1cbiAgICAgIHZhciByMSA9IHJlZFtyZWRQdHIraitkXVxuICAgICAgdmFyIGIwID0gYmx1ZVtibHVlUHRyK2pdXG4gICAgICB2YXIgYjEgPSBibHVlW2JsdWVQdHIraitkXVxuICAgICAgaWYocjEgPCBiMCB8fCBiMSA8IHIwKSB7XG4gICAgICAgIGNvbnRpbnVlIHJlZF9sb29wXG4gICAgICB9XG4gICAgfVxuICAgIHZhciByZXR2YWxcbiAgICBpZihmbGlwKSB7XG4gICAgICByZXR2YWwgPSB2aXNpdChibHVlSWQsIHJlZElkKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR2YWwgPSB2aXNpdChyZWRJZCwgYmx1ZUlkKVxuICAgIH1cbiAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgcmV0dXJuIHJldHZhbFxuICAgIH1cbiAgfVxufVxuXG4vL1NwZWNpYWwgY2FzZTogIEludGVyc2VjdCBvbmUgcG9pbnQgd2l0aCBsaXN0IG9mIGludGVydmFsc1xuZnVuY3Rpb24gb25lUG9pbnRGdWxsKFxuICBkLCBheGlzLCB2aXNpdCxcbiAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgYmx1ZU9mZnNldCwgYmx1ZSwgYmx1ZUlkKSB7XG5cbiAgdmFyIGVsZW1TaXplID0gMiAqIGRcbiAgdmFyIGJsdWVQdHIgID0gYmx1ZU9mZnNldCAqIGVsZW1TaXplXG4gIHZhciBibHVlWCAgICA9IGJsdWVbYmx1ZVB0ciArIGF4aXNdXG5cbnJlZF9sb29wOlxuICBmb3IodmFyIGk9cmVkU3RhcnQsIHJlZFB0cj1yZWRTdGFydCplbGVtU2l6ZTsgaTxyZWRFbmQ7ICsraSwgcmVkUHRyKz1lbGVtU2l6ZSkge1xuICAgIHZhciByZWRJZCA9IHJlZEluZGV4W2ldXG4gICAgaWYocmVkSWQgPT09IGJsdWVJZCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIHIwID0gcmVkW3JlZFB0citheGlzXVxuICAgIHZhciByMSA9IHJlZFtyZWRQdHIrYXhpcytkXVxuICAgIGlmKGJsdWVYIDwgcjAgfHwgcjEgPCBibHVlWCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgZm9yKHZhciBqPWF4aXMrMTsgajxkOyArK2opIHtcbiAgICAgIHZhciByMCA9IHJlZFtyZWRQdHIral1cbiAgICAgIHZhciByMSA9IHJlZFtyZWRQdHIraitkXVxuICAgICAgdmFyIGIwID0gYmx1ZVtibHVlUHRyK2pdXG4gICAgICB2YXIgYjEgPSBibHVlW2JsdWVQdHIraitkXVxuICAgICAgaWYocjEgPCBiMCB8fCBiMSA8IHIwKSB7XG4gICAgICAgIGNvbnRpbnVlIHJlZF9sb29wXG4gICAgICB9XG4gICAgfVxuICAgIHZhciByZXR2YWwgPSB2aXNpdChyZWRJZCwgYmx1ZUlkKVxuICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICByZXR1cm4gcmV0dmFsXG4gICAgfVxuICB9XG59XG5cbi8vVGhlIG1haW4gYm94IGludGVyc2VjdGlvbiByb3V0aW5lXG5mdW5jdGlvbiBib3hJbnRlcnNlY3RJdGVyKFxuICBkLCB2aXNpdCwgaW5pdEZ1bGwsXG4gIHhTaXplLCB4Qm94ZXMsIHhJbmRleCxcbiAgeVNpemUsIHlCb3hlcywgeUluZGV4KSB7XG5cbiAgLy9SZXNlcnZlIG1lbW9yeSBmb3Igc3RhY2tcbiAgaXRlckluaXQoZCwgeFNpemUgKyB5U2l6ZSlcblxuICB2YXIgdG9wICA9IDBcbiAgdmFyIGVsZW1TaXplID0gMiAqIGRcbiAgdmFyIHJldHZhbFxuXG4gIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgMCxcbiAgICAgIDAsIHhTaXplLFxuICAgICAgMCwgeVNpemUsXG4gICAgICBpbml0RnVsbCA/IDE2IDogMCwgXG4gICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICBpZighaW5pdEZ1bGwpIHtcbiAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgIDAsXG4gICAgICAwLCB5U2l6ZSxcbiAgICAgIDAsIHhTaXplLFxuICAgICAgMSwgXG4gICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICB9XG5cbiAgd2hpbGUodG9wID4gMCkge1xuICAgIHRvcCAgLT0gMVxuXG4gICAgdmFyIGlwdHIgPSB0b3AgKiBJRlJBTUVfU0laRVxuICAgIHZhciBheGlzICAgICAgPSBCT1hfSVNUQUNLW2lwdHJdXG4gICAgdmFyIHJlZFN0YXJ0ICA9IEJPWF9JU1RBQ0tbaXB0cisxXVxuICAgIHZhciByZWRFbmQgICAgPSBCT1hfSVNUQUNLW2lwdHIrMl1cbiAgICB2YXIgYmx1ZVN0YXJ0ID0gQk9YX0lTVEFDS1tpcHRyKzNdXG4gICAgdmFyIGJsdWVFbmQgICA9IEJPWF9JU1RBQ0tbaXB0cis0XVxuICAgIHZhciBzdGF0ZSAgICAgPSBCT1hfSVNUQUNLW2lwdHIrNV1cblxuICAgIHZhciBkcHRyID0gdG9wICogREZSQU1FX1NJWkVcbiAgICB2YXIgbG8gICAgICAgID0gQk9YX0RTVEFDS1tkcHRyXVxuICAgIHZhciBoaSAgICAgICAgPSBCT1hfRFNUQUNLW2RwdHIrMV1cblxuICAgIC8vVW5wYWNrIHN0YXRlIGluZm9cbiAgICB2YXIgZmxpcCAgICAgID0gKHN0YXRlICYgMSlcbiAgICB2YXIgZnVsbCAgICAgID0gISEoc3RhdGUgJiAxNilcblxuICAgIC8vVW5wYWNrIGluZGljZXNcbiAgICB2YXIgcmVkICAgICAgID0geEJveGVzXG4gICAgdmFyIHJlZEluZGV4ICA9IHhJbmRleFxuICAgIHZhciBibHVlICAgICAgPSB5Qm94ZXNcbiAgICB2YXIgYmx1ZUluZGV4ID0geUluZGV4XG4gICAgaWYoZmxpcCkge1xuICAgICAgcmVkICAgICAgICAgPSB5Qm94ZXNcbiAgICAgIHJlZEluZGV4ICAgID0geUluZGV4XG4gICAgICBibHVlICAgICAgICA9IHhCb3hlc1xuICAgICAgYmx1ZUluZGV4ICAgPSB4SW5kZXhcbiAgICB9XG5cbiAgICBpZihzdGF0ZSAmIDIpIHtcbiAgICAgIHJlZEVuZCA9IHBhcnRpdGlvblN0YXJ0TGVzc1RoYW4oXG4gICAgICAgIGQsIGF4aXMsXG4gICAgICAgIHJlZFN0YXJ0LCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgIGhpKVxuICAgICAgaWYocmVkU3RhcnQgPj0gcmVkRW5kKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfVxuICAgIGlmKHN0YXRlICYgNCkge1xuICAgICAgcmVkU3RhcnQgPSBwYXJ0aXRpb25FbmRMZXNzVGhhbkVxdWFsKFxuICAgICAgICBkLCBheGlzLFxuICAgICAgICByZWRTdGFydCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICBsbylcbiAgICAgIGlmKHJlZFN0YXJ0ID49IHJlZEVuZCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICB2YXIgcmVkQ291bnQgID0gcmVkRW5kICAtIHJlZFN0YXJ0XG4gICAgdmFyIGJsdWVDb3VudCA9IGJsdWVFbmQgLSBibHVlU3RhcnRcblxuICAgIGlmKGZ1bGwpIHtcbiAgICAgIGlmKGQgKiByZWRDb3VudCAqIChyZWRDb3VudCArIGJsdWVDb3VudCkgPCBTQ0FOX0NPTVBMRVRFX0NVVE9GRikge1xuICAgICAgICByZXR2YWwgPSBzd2VlcC5zY2FuQ29tcGxldGUoXG4gICAgICAgICAgZCwgYXhpcywgdmlzaXQsIFxuICAgICAgICAgIHJlZFN0YXJ0LCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmKGQgKiBNYXRoLm1pbihyZWRDb3VudCwgYmx1ZUNvdW50KSA8IEJSVVRFX0ZPUkNFX0NVVE9GRikge1xuICAgICAgICAvL0lmIGlucHV0IHNtYWxsLCB0aGVuIHVzZSBicnV0ZSBmb3JjZVxuICAgICAgICByZXR2YWwgPSBicnV0ZUZvcmNlUGFydGlhbChcbiAgICAgICAgICAgIGQsIGF4aXMsIHZpc2l0LCBmbGlwLFxuICAgICAgICAgICAgcmVkU3RhcnQsICByZWRFbmQsICByZWQsICByZWRJbmRleCxcbiAgICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KVxuICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZVxuICAgICAgfSBlbHNlIGlmKGQgKiByZWRDb3VudCAqIGJsdWVDb3VudCA8IFNDQU5fQ1VUT0ZGKSB7XG4gICAgICAgIC8vSWYgaW5wdXQgbWVkaXVtIHNpemVkLCB0aGVuIHVzZSBzd2VlcCBhbmQgcHJ1bmVcbiAgICAgICAgcmV0dmFsID0gc3dlZXAuc2NhbkJpcGFydGl0ZShcbiAgICAgICAgICBkLCBheGlzLCB2aXNpdCwgZmxpcCwgXG4gICAgICAgICAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy9GaXJzdCwgZmluZCBhbGwgcmVkIGludGVydmFscyB3aG9zZSBpbnRlcmlvciBjb250YWlucyAobG8saGkpXG4gICAgdmFyIHJlZDAgPSBwYXJ0aXRpb25JbnRlcmlvckNvbnRhaW5zSW50ZXJ2YWwoXG4gICAgICBkLCBheGlzLCBcbiAgICAgIHJlZFN0YXJ0LCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICBsbywgaGkpXG5cbiAgICAvL0xvd2VyIGRpbWVuc2lvbmFsIGNhc2VcbiAgICBpZihyZWRTdGFydCA8IHJlZDApIHtcblxuICAgICAgaWYoZCAqIChyZWQwIC0gcmVkU3RhcnQpIDwgQlJVVEVfRk9SQ0VfQ1VUT0ZGKSB7XG4gICAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciBzbWFsbCBpbnB1dHM6IHVzZSBicnV0ZSBmb3JjZVxuICAgICAgICByZXR2YWwgPSBicnV0ZUZvcmNlRnVsbChcbiAgICAgICAgICBkLCBheGlzKzEsIHZpc2l0LFxuICAgICAgICAgIHJlZFN0YXJ0LCByZWQwLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KVxuICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmKGF4aXMgPT09IGQtMikge1xuICAgICAgICBpZihmbGlwKSB7XG4gICAgICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBCaXBhcnRpdGUoXG4gICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4LFxuICAgICAgICAgICAgcmVkU3RhcnQsIHJlZDAsIHJlZCwgcmVkSW5kZXgpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBCaXBhcnRpdGUoXG4gICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgIHJlZFN0YXJ0LCByZWQwLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgIH1cbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgICAgIGF4aXMrMSxcbiAgICAgICAgICByZWRTdGFydCwgcmVkMCxcbiAgICAgICAgICBibHVlU3RhcnQsIGJsdWVFbmQsXG4gICAgICAgICAgZmxpcCxcbiAgICAgICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLFxuICAgICAgICAgIHJlZFN0YXJ0LCByZWQwLFxuICAgICAgICAgIGZsaXBeMSxcbiAgICAgICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vRGl2aWRlIGFuZCBjb25xdWVyIHBoYXNlXG4gICAgaWYocmVkMCA8IHJlZEVuZCkge1xuXG4gICAgICAvL0N1dCBibHVlIGludG8gMyBwYXJ0czpcbiAgICAgIC8vXG4gICAgICAvLyAgUG9pbnRzIDwgbWlkIHBvaW50XG4gICAgICAvLyAgUG9pbnRzID0gbWlkIHBvaW50XG4gICAgICAvLyAgUG9pbnRzID4gbWlkIHBvaW50XG4gICAgICAvL1xuICAgICAgdmFyIGJsdWUwID0gZmluZE1lZGlhbihcbiAgICAgICAgZCwgYXhpcywgXG4gICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KVxuICAgICAgdmFyIG1pZCA9IGJsdWVbZWxlbVNpemUgKiBibHVlMCArIGF4aXNdXG4gICAgICB2YXIgYmx1ZTEgPSBwYXJ0aXRpb25TdGFydEVxdWFsKFxuICAgICAgICBkLCBheGlzLFxuICAgICAgICBibHVlMCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4LFxuICAgICAgICBtaWQpXG5cbiAgICAgIC8vUmlnaHQgY2FzZVxuICAgICAgaWYoYmx1ZTEgPCBibHVlRW5kKSB7XG4gICAgICAgIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgICAgIGF4aXMsXG4gICAgICAgICAgcmVkMCwgcmVkRW5kLFxuICAgICAgICAgIGJsdWUxLCBibHVlRW5kLFxuICAgICAgICAgIChmbGlwfDQpICsgKGZ1bGwgPyAxNiA6IDApLFxuICAgICAgICAgIG1pZCwgaGkpXG4gICAgICB9XG5cbiAgICAgIC8vTGVmdCBjYXNlXG4gICAgICBpZihibHVlU3RhcnQgPCBibHVlMCkge1xuICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICBheGlzLFxuICAgICAgICAgIHJlZDAsIHJlZEVuZCxcbiAgICAgICAgICBibHVlU3RhcnQsIGJsdWUwLFxuICAgICAgICAgIChmbGlwfDIpICsgKGZ1bGwgPyAxNiA6IDApLFxuICAgICAgICAgIGxvLCBtaWQpXG4gICAgICB9XG5cbiAgICAgIC8vQ2VudGVyIGNhc2UgKHRoZSBoYXJkIHBhcnQpXG4gICAgICBpZihibHVlMCArIDEgPT09IGJsdWUxKSB7XG4gICAgICAgIC8vT3B0aW1pemF0aW9uOiBSYW5nZSB3aXRoIGV4YWN0bHkgMSBwb2ludCwgdXNlIGEgYnJ1dGUgZm9yY2Ugc2NhblxuICAgICAgICBpZihmdWxsKSB7XG4gICAgICAgICAgcmV0dmFsID0gb25lUG9pbnRGdWxsKFxuICAgICAgICAgICAgZCwgYXhpcywgdmlzaXQsXG4gICAgICAgICAgICByZWQwLCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICBibHVlMCwgYmx1ZSwgYmx1ZUluZGV4W2JsdWUwXSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR2YWwgPSBvbmVQb2ludFBhcnRpYWwoXG4gICAgICAgICAgICBkLCBheGlzLCB2aXNpdCwgZmxpcCxcbiAgICAgICAgICAgIHJlZDAsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICAgIGJsdWUwLCBibHVlLCBibHVlSW5kZXhbYmx1ZTBdKVxuICAgICAgICB9XG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoYmx1ZTAgPCBibHVlMSkge1xuICAgICAgICB2YXIgcmVkMVxuICAgICAgICBpZihmdWxsKSB7XG4gICAgICAgICAgLy9JZiBmdWxsIGludGVyc2VjdGlvbiwgbmVlZCB0byBoYW5kbGUgc3BlY2lhbCBjYXNlXG4gICAgICAgICAgcmVkMSA9IHBhcnRpdGlvbkNvbnRhaW5zUG9pbnQoXG4gICAgICAgICAgICBkLCBheGlzLFxuICAgICAgICAgICAgcmVkMCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgbWlkKVxuICAgICAgICAgIGlmKHJlZDAgPCByZWQxKSB7XG4gICAgICAgICAgICB2YXIgcmVkWCA9IHBhcnRpdGlvblN0YXJ0RXF1YWwoXG4gICAgICAgICAgICAgIGQsIGF4aXMsXG4gICAgICAgICAgICAgIHJlZDAsIHJlZDEsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICAgIG1pZClcbiAgICAgICAgICAgIGlmKGF4aXMgPT09IGQtMikge1xuICAgICAgICAgICAgICAvL0RlZ2VuZXJhdGUgc3dlZXAgaW50ZXJzZWN0aW9uOlxuICAgICAgICAgICAgICAvLyAgW3JlZDAsIHJlZFhdIHdpdGggW2JsdWUwLCBibHVlMV1cbiAgICAgICAgICAgICAgaWYocmVkMCA8IHJlZFgpIHtcbiAgICAgICAgICAgICAgICByZXR2YWwgPSBzd2VlcC5zd2VlcENvbXBsZXRlKFxuICAgICAgICAgICAgICAgICAgZCwgdmlzaXQsXG4gICAgICAgICAgICAgICAgICByZWQwLCByZWRYLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgICAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAvL05vcm1hbCBzd2VlcCBpbnRlcnNlY3Rpb246XG4gICAgICAgICAgICAgIC8vICBbcmVkWCwgcmVkMV0gd2l0aCBbYmx1ZTAsIGJsdWUxXVxuICAgICAgICAgICAgICBpZihyZWRYIDwgcmVkMSkge1xuICAgICAgICAgICAgICAgIHJldHZhbCA9IHN3ZWVwLnN3ZWVwQmlwYXJ0aXRlKFxuICAgICAgICAgICAgICAgICAgZCwgdmlzaXQsXG4gICAgICAgICAgICAgICAgICByZWRYLCByZWQxLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgICAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmKHJlZDAgPCByZWRYKSB7XG4gICAgICAgICAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgICAgICAgICByZWQwLCByZWRYLFxuICAgICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLFxuICAgICAgICAgICAgICAgICAgMTYsXG4gICAgICAgICAgICAgICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmKHJlZFggPCByZWQxKSB7XG4gICAgICAgICAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgICAgICAgICByZWRYLCByZWQxLFxuICAgICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLFxuICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICAgICAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsXG4gICAgICAgICAgICAgICAgICByZWRYLCByZWQxLFxuICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYoZmxpcCkge1xuICAgICAgICAgICAgcmVkMSA9IHBhcnRpdGlvbkNvbnRhaW5zUG9pbnRQcm9wZXIoXG4gICAgICAgICAgICAgIGQsIGF4aXMsXG4gICAgICAgICAgICAgIHJlZDAsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICAgICAgbWlkKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWQxID0gcGFydGl0aW9uQ29udGFpbnNQb2ludChcbiAgICAgICAgICAgICAgZCwgYXhpcyxcbiAgICAgICAgICAgICAgcmVkMCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgICBtaWQpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHJlZDAgPCByZWQxKSB7XG4gICAgICAgICAgICBpZihheGlzID09PSBkLTIpIHtcbiAgICAgICAgICAgICAgaWYoZmxpcCkge1xuICAgICAgICAgICAgICAgIHJldHZhbCA9IHN3ZWVwLnN3ZWVwQmlwYXJ0aXRlKFxuICAgICAgICAgICAgICAgICAgZCwgdmlzaXQsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsIGJsdWUsIGJsdWVJbmRleCxcbiAgICAgICAgICAgICAgICAgIHJlZDAsIHJlZDEsIHJlZCwgcmVkSW5kZXgpXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBCaXBhcnRpdGUoXG4gICAgICAgICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgICAgICAgIHJlZDAsIHJlZDEsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgICAgICAgYXhpcysxLFxuICAgICAgICAgICAgICAgIHJlZDAsIHJlZDEsXG4gICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLFxuICAgICAgICAgICAgICAgIGZsaXAsXG4gICAgICAgICAgICAgICAgLUluZmluaXR5LCBJbmZpbml0eSlcbiAgICAgICAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgICAgICAgYXhpcysxLFxuICAgICAgICAgICAgICAgIGJsdWUwLCBibHVlMSxcbiAgICAgICAgICAgICAgICByZWQwLCByZWQxLFxuICAgICAgICAgICAgICAgIGZsaXBeMSxcbiAgICAgICAgICAgICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZpbmRNZWRpYW5cblxudmFyIGdlblBhcnRpdGlvbiA9IHJlcXVpcmUoJy4vcGFydGl0aW9uJylcblxudmFyIHBhcnRpdGlvblN0YXJ0TGVzc1RoYW4gPSBnZW5QYXJ0aXRpb24oJ2xvPHAwJywgWydwMCddKVxuXG52YXIgUEFSVElUSU9OX1RIUkVTSE9MRCA9IDggICAvL0N1dCBvZmYgZm9yIHVzaW5nIGluc2VydGlvbiBzb3J0IGluIGZpbmRNZWRpYW5cblxuLy9CYXNlIGNhc2UgZm9yIG1lZGlhbiBmaW5kaW5nOiAgVXNlIGluc2VydGlvbiBzb3J0XG5mdW5jdGlvbiBpbnNlcnRpb25Tb3J0KGQsIGF4aXMsIHN0YXJ0LCBlbmQsIGJveGVzLCBpZHMpIHtcbiAgdmFyIGVsZW1TaXplID0gMiAqIGRcbiAgdmFyIGJveFB0ciA9IGVsZW1TaXplICogKHN0YXJ0KzEpICsgYXhpc1xuICBmb3IodmFyIGk9c3RhcnQrMTsgaTxlbmQ7ICsraSwgYm94UHRyKz1lbGVtU2l6ZSkge1xuICAgIHZhciB4ID0gYm94ZXNbYm94UHRyXVxuICAgIGZvcih2YXIgaj1pLCBwdHI9ZWxlbVNpemUqKGktMSk7IFxuICAgICAgICBqPnN0YXJ0ICYmIGJveGVzW3B0citheGlzXSA+IHg7IFxuICAgICAgICAtLWosIHB0ci09ZWxlbVNpemUpIHtcbiAgICAgIC8vU3dhcFxuICAgICAgdmFyIGFQdHIgPSBwdHJcbiAgICAgIHZhciBiUHRyID0gcHRyK2VsZW1TaXplXG4gICAgICBmb3IodmFyIGs9MDsgazxlbGVtU2l6ZTsgKytrLCArK2FQdHIsICsrYlB0cikge1xuICAgICAgICB2YXIgeSA9IGJveGVzW2FQdHJdXG4gICAgICAgIGJveGVzW2FQdHJdID0gYm94ZXNbYlB0cl1cbiAgICAgICAgYm94ZXNbYlB0cl0gPSB5XG4gICAgICB9XG4gICAgICB2YXIgdG1wID0gaWRzW2pdXG4gICAgICBpZHNbal0gPSBpZHNbai0xXVxuICAgICAgaWRzW2otMV0gPSB0bXBcbiAgICB9XG4gIH1cbn1cblxuLy9GaW5kIG1lZGlhbiB1c2luZyBxdWljayBzZWxlY3QgYWxnb3JpdGhtXG4vLyAgdGFrZXMgTyhuKSB0aW1lIHdpdGggaGlnaCBwcm9iYWJpbGl0eVxuZnVuY3Rpb24gZmluZE1lZGlhbihkLCBheGlzLCBzdGFydCwgZW5kLCBib3hlcywgaWRzKSB7XG4gIGlmKGVuZCA8PSBzdGFydCsxKSB7XG4gICAgcmV0dXJuIHN0YXJ0XG4gIH1cblxuICB2YXIgbG8gICAgICAgPSBzdGFydFxuICB2YXIgaGkgICAgICAgPSBlbmRcbiAgdmFyIG1pZCAgICAgID0gKChlbmQgKyBzdGFydCkgPj4+IDEpXG4gIHZhciBlbGVtU2l6ZSA9IDIqZFxuICB2YXIgcGl2b3QgICAgPSBtaWRcbiAgdmFyIHZhbHVlICAgID0gYm94ZXNbZWxlbVNpemUqbWlkK2F4aXNdXG4gIFxuICB3aGlsZShsbyA8IGhpKSB7XG4gICAgaWYoaGkgLSBsbyA8IFBBUlRJVElPTl9USFJFU0hPTEQpIHtcbiAgICAgIGluc2VydGlvblNvcnQoZCwgYXhpcywgbG8sIGhpLCBib3hlcywgaWRzKVxuICAgICAgdmFsdWUgPSBib3hlc1tlbGVtU2l6ZSptaWQrYXhpc11cbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIFxuICAgIC8vU2VsZWN0IHBpdm90IHVzaW5nIG1lZGlhbi1vZi0zXG4gICAgdmFyIGNvdW50ICA9IGhpIC0gbG9cbiAgICB2YXIgcGl2b3QwID0gKE1hdGgucmFuZG9tKCkqY291bnQrbG8pfDBcbiAgICB2YXIgdmFsdWUwID0gYm94ZXNbZWxlbVNpemUqcGl2b3QwICsgYXhpc11cbiAgICB2YXIgcGl2b3QxID0gKE1hdGgucmFuZG9tKCkqY291bnQrbG8pfDBcbiAgICB2YXIgdmFsdWUxID0gYm94ZXNbZWxlbVNpemUqcGl2b3QxICsgYXhpc11cbiAgICB2YXIgcGl2b3QyID0gKE1hdGgucmFuZG9tKCkqY291bnQrbG8pfDBcbiAgICB2YXIgdmFsdWUyID0gYm94ZXNbZWxlbVNpemUqcGl2b3QyICsgYXhpc11cbiAgICBpZih2YWx1ZTAgPD0gdmFsdWUxKSB7XG4gICAgICBpZih2YWx1ZTIgPj0gdmFsdWUxKSB7XG4gICAgICAgIHBpdm90ID0gcGl2b3QxXG4gICAgICAgIHZhbHVlID0gdmFsdWUxXG4gICAgICB9IGVsc2UgaWYodmFsdWUwID49IHZhbHVlMikge1xuICAgICAgICBwaXZvdCA9IHBpdm90MFxuICAgICAgICB2YWx1ZSA9IHZhbHVlMFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGl2b3QgPSBwaXZvdDJcbiAgICAgICAgdmFsdWUgPSB2YWx1ZTJcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYodmFsdWUxID49IHZhbHVlMikge1xuICAgICAgICBwaXZvdCA9IHBpdm90MVxuICAgICAgICB2YWx1ZSA9IHZhbHVlMVxuICAgICAgfSBlbHNlIGlmKHZhbHVlMiA+PSB2YWx1ZTApIHtcbiAgICAgICAgcGl2b3QgPSBwaXZvdDBcbiAgICAgICAgdmFsdWUgPSB2YWx1ZTBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBpdm90ID0gcGl2b3QyXG4gICAgICAgIHZhbHVlID0gdmFsdWUyXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9Td2FwIHBpdm90IHRvIGVuZCBvZiBhcnJheVxuICAgIHZhciBhUHRyID0gZWxlbVNpemUgKiAoaGktMSlcbiAgICB2YXIgYlB0ciA9IGVsZW1TaXplICogcGl2b3RcbiAgICBmb3IodmFyIGk9MDsgaTxlbGVtU2l6ZTsgKytpLCArK2FQdHIsICsrYlB0cikge1xuICAgICAgdmFyIHggPSBib3hlc1thUHRyXVxuICAgICAgYm94ZXNbYVB0cl0gPSBib3hlc1tiUHRyXVxuICAgICAgYm94ZXNbYlB0cl0gPSB4XG4gICAgfVxuICAgIHZhciB5ID0gaWRzW2hpLTFdXG4gICAgaWRzW2hpLTFdID0gaWRzW3Bpdm90XVxuICAgIGlkc1twaXZvdF0gPSB5XG5cbiAgICAvL1BhcnRpdGlvbiB1c2luZyBwaXZvdFxuICAgIHBpdm90ID0gcGFydGl0aW9uU3RhcnRMZXNzVGhhbihcbiAgICAgIGQsIGF4aXMsIFxuICAgICAgbG8sIGhpLTEsIGJveGVzLCBpZHMsXG4gICAgICB2YWx1ZSlcblxuICAgIC8vU3dhcCBwaXZvdCBiYWNrXG4gICAgdmFyIGFQdHIgPSBlbGVtU2l6ZSAqIChoaS0xKVxuICAgIHZhciBiUHRyID0gZWxlbVNpemUgKiBwaXZvdFxuICAgIGZvcih2YXIgaT0wOyBpPGVsZW1TaXplOyArK2ksICsrYVB0ciwgKytiUHRyKSB7XG4gICAgICB2YXIgeCA9IGJveGVzW2FQdHJdXG4gICAgICBib3hlc1thUHRyXSA9IGJveGVzW2JQdHJdXG4gICAgICBib3hlc1tiUHRyXSA9IHhcbiAgICB9XG4gICAgdmFyIHkgPSBpZHNbaGktMV1cbiAgICBpZHNbaGktMV0gPSBpZHNbcGl2b3RdXG4gICAgaWRzW3Bpdm90XSA9IHlcblxuICAgIC8vU3dhcCBwaXZvdCB0byBsYXN0IHBpdm90XG4gICAgaWYobWlkIDwgcGl2b3QpIHtcbiAgICAgIGhpID0gcGl2b3QtMVxuICAgICAgd2hpbGUobG8gPCBoaSAmJiBcbiAgICAgICAgYm94ZXNbZWxlbVNpemUqKGhpLTEpK2F4aXNdID09PSB2YWx1ZSkge1xuICAgICAgICBoaSAtPSAxXG4gICAgICB9XG4gICAgICBoaSArPSAxXG4gICAgfSBlbHNlIGlmKHBpdm90IDwgbWlkKSB7XG4gICAgICBsbyA9IHBpdm90ICsgMVxuICAgICAgd2hpbGUobG8gPCBoaSAmJlxuICAgICAgICBib3hlc1tlbGVtU2l6ZSpsbytheGlzXSA9PT0gdmFsdWUpIHtcbiAgICAgICAgbG8gKz0gMVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIC8vTWFrZSBzdXJlIHBpdm90IGlzIGF0IHN0YXJ0XG4gIHJldHVybiBwYXJ0aXRpb25TdGFydExlc3NUaGFuKFxuICAgIGQsIGF4aXMsIFxuICAgIHN0YXJ0LCBtaWQsIGJveGVzLCBpZHMsXG4gICAgYm94ZXNbZWxlbVNpemUqbWlkK2F4aXNdKVxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdlblBhcnRpdGlvblxuXG52YXIgY29kZSA9ICdmb3IodmFyIGo9MiphLGs9aipjLGw9ayxtPWMsbj1iLG89YStiLHA9YztkPnA7KytwLGsrPWope3ZhciBfO2lmKCQpaWYobT09PXApbSs9MSxsKz1qO2Vsc2V7Zm9yKHZhciBzPTA7aj5zOysrcyl7dmFyIHQ9ZVtrK3NdO2VbaytzXT1lW2xdLGVbbCsrXT10fXZhciB1PWZbcF07ZltwXT1mW21dLGZbbSsrXT11fX1yZXR1cm4gbSdcblxuZnVuY3Rpb24gZ2VuUGFydGl0aW9uKHByZWRpY2F0ZSwgYXJncykge1xuICB2YXIgZmFyZ3MgPSdhYmNkZWYnLnNwbGl0KCcnKS5jb25jYXQoYXJncylcbiAgdmFyIHJlYWRzID0gW11cbiAgaWYocHJlZGljYXRlLmluZGV4T2YoJ2xvJykgPj0gMCkge1xuICAgIHJlYWRzLnB1c2goJ2xvPWVbaytuXScpXG4gIH1cbiAgaWYocHJlZGljYXRlLmluZGV4T2YoJ2hpJykgPj0gMCkge1xuICAgIHJlYWRzLnB1c2goJ2hpPWVbaytvXScpXG4gIH1cbiAgZmFyZ3MucHVzaChcbiAgICBjb2RlLnJlcGxhY2UoJ18nLCByZWFkcy5qb2luKCkpXG4gICAgICAgIC5yZXBsYWNlKCckJywgcHJlZGljYXRlKSlcbiAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KHZvaWQgMCwgZmFyZ3MpXG59IiwiJ3VzZSBzdHJpY3QnO1xuXG4vL1RoaXMgY29kZSBpcyBleHRyYWN0ZWQgZnJvbSBuZGFycmF5LXNvcnRcbi8vSXQgaXMgaW5saW5lZCBoZXJlIGFzIGEgdGVtcG9yYXJ5IHdvcmthcm91bmRcblxubW9kdWxlLmV4cG9ydHMgPSB3cmFwcGVyO1xuXG52YXIgSU5TRVJUX1NPUlRfQ1VUT0ZGID0gMzJcblxuZnVuY3Rpb24gd3JhcHBlcihkYXRhLCBuMCkge1xuICBpZiAobjAgPD0gNCpJTlNFUlRfU09SVF9DVVRPRkYpIHtcbiAgICBpbnNlcnRpb25Tb3J0KDAsIG4wIC0gMSwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KDAsIG4wIC0gMSwgZGF0YSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5zZXJ0aW9uU29ydChsZWZ0LCByaWdodCwgZGF0YSkge1xuICB2YXIgcHRyID0gMioobGVmdCsxKVxuICBmb3IodmFyIGk9bGVmdCsxOyBpPD1yaWdodDsgKytpKSB7XG4gICAgdmFyIGEgPSBkYXRhW3B0cisrXVxuICAgIHZhciBiID0gZGF0YVtwdHIrK11cbiAgICB2YXIgaiA9IGlcbiAgICB2YXIganB0ciA9IHB0ci0yXG4gICAgd2hpbGUoai0tID4gbGVmdCkge1xuICAgICAgdmFyIHggPSBkYXRhW2pwdHItMl1cbiAgICAgIHZhciB5ID0gZGF0YVtqcHRyLTFdXG4gICAgICBpZih4IDwgYSkge1xuICAgICAgICBicmVha1xuICAgICAgfSBlbHNlIGlmKHggPT09IGEgJiYgeSA8IGIpIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGRhdGFbanB0cl0gICA9IHhcbiAgICAgIGRhdGFbanB0cisxXSA9IHlcbiAgICAgIGpwdHIgLT0gMlxuICAgIH1cbiAgICBkYXRhW2pwdHJdICAgPSBhXG4gICAgZGF0YVtqcHRyKzFdID0gYlxuICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoaSwgaiwgZGF0YSkge1xuICBpICo9IDJcbiAgaiAqPSAyXG4gIHZhciB4ID0gZGF0YVtpXVxuICB2YXIgeSA9IGRhdGFbaSsxXVxuICBkYXRhW2ldID0gZGF0YVtqXVxuICBkYXRhW2krMV0gPSBkYXRhW2orMV1cbiAgZGF0YVtqXSA9IHhcbiAgZGF0YVtqKzFdID0geVxufVxuXG5mdW5jdGlvbiBtb3ZlKGksIGosIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICBkYXRhW2ldID0gZGF0YVtqXVxuICBkYXRhW2krMV0gPSBkYXRhW2orMV1cbn1cblxuZnVuY3Rpb24gcm90YXRlKGksIGosIGssIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICBrICo9IDJcbiAgdmFyIHggPSBkYXRhW2ldXG4gIHZhciB5ID0gZGF0YVtpKzFdXG4gIGRhdGFbaV0gPSBkYXRhW2pdXG4gIGRhdGFbaSsxXSA9IGRhdGFbaisxXVxuICBkYXRhW2pdID0gZGF0YVtrXVxuICBkYXRhW2orMV0gPSBkYXRhW2srMV1cbiAgZGF0YVtrXSA9IHhcbiAgZGF0YVtrKzFdID0geVxufVxuXG5mdW5jdGlvbiBzaHVmZmxlUGl2b3QoaSwgaiwgcHgsIHB5LCBkYXRhKSB7XG4gIGkgKj0gMlxuICBqICo9IDJcbiAgZGF0YVtpXSA9IGRhdGFbal1cbiAgZGF0YVtqXSA9IHB4XG4gIGRhdGFbaSsxXSA9IGRhdGFbaisxXVxuICBkYXRhW2orMV0gPSBweVxufVxuXG5mdW5jdGlvbiBjb21wYXJlKGksIGosIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICB2YXIgeCA9IGRhdGFbaV0sXG4gICAgICB5ID0gZGF0YVtqXVxuICBpZih4IDwgeSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9IGVsc2UgaWYoeCA9PT0geSkge1xuICAgIHJldHVybiBkYXRhW2krMV0gPiBkYXRhW2orMV1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBjb21wYXJlUGl2b3QoaSwgeSwgYiwgZGF0YSkge1xuICBpICo9IDJcbiAgdmFyIHggPSBkYXRhW2ldXG4gIGlmKHggPCB5KSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfSBlbHNlIGlmKHggPT09IHkpIHtcbiAgICByZXR1cm4gZGF0YVtpKzFdIDwgYlxuICB9XG4gIHJldHVybiBmYWxzZVxufVxuXG5mdW5jdGlvbiBxdWlja1NvcnQobGVmdCwgcmlnaHQsIGRhdGEpIHtcbiAgdmFyIHNpeHRoID0gKHJpZ2h0IC0gbGVmdCArIDEpIC8gNiB8IDAsIFxuICAgICAgaW5kZXgxID0gbGVmdCArIHNpeHRoLCBcbiAgICAgIGluZGV4NSA9IHJpZ2h0IC0gc2l4dGgsIFxuICAgICAgaW5kZXgzID0gbGVmdCArIHJpZ2h0ID4+IDEsIFxuICAgICAgaW5kZXgyID0gaW5kZXgzIC0gc2l4dGgsIFxuICAgICAgaW5kZXg0ID0gaW5kZXgzICsgc2l4dGgsIFxuICAgICAgZWwxID0gaW5kZXgxLCBcbiAgICAgIGVsMiA9IGluZGV4MiwgXG4gICAgICBlbDMgPSBpbmRleDMsIFxuICAgICAgZWw0ID0gaW5kZXg0LCBcbiAgICAgIGVsNSA9IGluZGV4NSwgXG4gICAgICBsZXNzID0gbGVmdCArIDEsIFxuICAgICAgZ3JlYXQgPSByaWdodCAtIDEsIFxuICAgICAgdG1wID0gMFxuICBpZihjb21wYXJlKGVsMSwgZWwyLCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMVxuICAgIGVsMSA9IGVsMlxuICAgIGVsMiA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWw0LCBlbDUsIGRhdGEpKSB7XG4gICAgdG1wID0gZWw0XG4gICAgZWw0ID0gZWw1XG4gICAgZWw1ID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDEsIGVsMywgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDFcbiAgICBlbDEgPSBlbDNcbiAgICBlbDMgPSB0bXBcbiAgfVxuICBpZihjb21wYXJlKGVsMiwgZWwzLCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMlxuICAgIGVsMiA9IGVsM1xuICAgIGVsMyA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWwxLCBlbDQsIGRhdGEpKSB7XG4gICAgdG1wID0gZWwxXG4gICAgZWwxID0gZWw0XG4gICAgZWw0ID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDMsIGVsNCwgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDNcbiAgICBlbDMgPSBlbDRcbiAgICBlbDQgPSB0bXBcbiAgfVxuICBpZihjb21wYXJlKGVsMiwgZWw1LCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMlxuICAgIGVsMiA9IGVsNVxuICAgIGVsNSA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWwyLCBlbDMsIGRhdGEpKSB7XG4gICAgdG1wID0gZWwyXG4gICAgZWwyID0gZWwzXG4gICAgZWwzID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDQsIGVsNSwgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDRcbiAgICBlbDQgPSBlbDVcbiAgICBlbDUgPSB0bXBcbiAgfVxuXG4gIHZhciBwaXZvdDFYID0gZGF0YVsyKmVsMl1cbiAgdmFyIHBpdm90MVkgPSBkYXRhWzIqZWwyKzFdXG4gIHZhciBwaXZvdDJYID0gZGF0YVsyKmVsNF1cbiAgdmFyIHBpdm90MlkgPSBkYXRhWzIqZWw0KzFdXG5cbiAgdmFyIHB0cjAgPSAyICogZWwxO1xuICB2YXIgcHRyMiA9IDIgKiBlbDM7XG4gIHZhciBwdHI0ID0gMiAqIGVsNTtcbiAgdmFyIHB0cjUgPSAyICogaW5kZXgxO1xuICB2YXIgcHRyNiA9IDIgKiBpbmRleDM7XG4gIHZhciBwdHI3ID0gMiAqIGluZGV4NTtcbiAgZm9yICh2YXIgaTEgPSAwOyBpMSA8IDI7ICsraTEpIHtcbiAgICB2YXIgeCA9IGRhdGFbcHRyMCtpMV07XG4gICAgdmFyIHkgPSBkYXRhW3B0cjIraTFdO1xuICAgIHZhciB6ID0gZGF0YVtwdHI0K2kxXTtcbiAgICBkYXRhW3B0cjUraTFdID0geDtcbiAgICBkYXRhW3B0cjYraTFdID0geTtcbiAgICBkYXRhW3B0cjcraTFdID0gejtcbiAgfVxuXG4gIG1vdmUoaW5kZXgyLCBsZWZ0LCBkYXRhKVxuICBtb3ZlKGluZGV4NCwgcmlnaHQsIGRhdGEpXG4gIGZvciAodmFyIGsgPSBsZXNzOyBrIDw9IGdyZWF0OyArK2spIHtcbiAgICBpZiAoY29tcGFyZVBpdm90KGssIHBpdm90MVgsIHBpdm90MVksIGRhdGEpKSB7XG4gICAgICBpZiAoayAhPT0gbGVzcykge1xuICAgICAgICBzd2FwKGssIGxlc3MsIGRhdGEpXG4gICAgICB9XG4gICAgICArK2xlc3M7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghY29tcGFyZVBpdm90KGssIHBpdm90MlgsIHBpdm90MlksIGRhdGEpKSB7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgaWYgKCFjb21wYXJlUGl2b3QoZ3JlYXQsIHBpdm90MlgsIHBpdm90MlksIGRhdGEpKSB7XG4gICAgICAgICAgICBpZiAoLS1ncmVhdCA8IGspIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNvbXBhcmVQaXZvdChncmVhdCwgcGl2b3QxWCwgcGl2b3QxWSwgZGF0YSkpIHtcbiAgICAgICAgICAgICAgcm90YXRlKGssIGxlc3MsIGdyZWF0LCBkYXRhKVxuICAgICAgICAgICAgICArK2xlc3M7XG4gICAgICAgICAgICAgIC0tZ3JlYXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzd2FwKGssIGdyZWF0LCBkYXRhKVxuICAgICAgICAgICAgICAtLWdyZWF0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHNodWZmbGVQaXZvdChsZWZ0LCBsZXNzLTEsIHBpdm90MVgsIHBpdm90MVksIGRhdGEpXG4gIHNodWZmbGVQaXZvdChyaWdodCwgZ3JlYXQrMSwgcGl2b3QyWCwgcGl2b3QyWSwgZGF0YSlcbiAgaWYgKGxlc3MgLSAyIC0gbGVmdCA8PSBJTlNFUlRfU09SVF9DVVRPRkYpIHtcbiAgICBpbnNlcnRpb25Tb3J0KGxlZnQsIGxlc3MgLSAyLCBkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICBxdWlja1NvcnQobGVmdCwgbGVzcyAtIDIsIGRhdGEpO1xuICB9XG4gIGlmIChyaWdodCAtIChncmVhdCArIDIpIDw9IElOU0VSVF9TT1JUX0NVVE9GRikge1xuICAgIGluc2VydGlvblNvcnQoZ3JlYXQgKyAyLCByaWdodCwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KGdyZWF0ICsgMiwgcmlnaHQsIGRhdGEpO1xuICB9XG4gIGlmIChncmVhdCAtIGxlc3MgPD0gSU5TRVJUX1NPUlRfQ1VUT0ZGKSB7XG4gICAgaW5zZXJ0aW9uU29ydChsZXNzLCBncmVhdCwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KGxlc3MsIGdyZWF0LCBkYXRhKTtcbiAgfVxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaW5pdDogICAgICAgICAgIHNxSW5pdCxcbiAgc3dlZXBCaXBhcnRpdGU6IHN3ZWVwQmlwYXJ0aXRlLFxuICBzd2VlcENvbXBsZXRlOiAgc3dlZXBDb21wbGV0ZSxcbiAgc2NhbkJpcGFydGl0ZTogIHNjYW5CaXBhcnRpdGUsXG4gIHNjYW5Db21wbGV0ZTogICBzY2FuQ29tcGxldGVcbn1cblxudmFyIHBvb2wgID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcbnZhciBiaXRzICA9IHJlcXVpcmUoJ2JpdC10d2lkZGxlJylcbnZhciBpc29ydCA9IHJlcXVpcmUoJy4vc29ydCcpXG5cbi8vRmxhZyBmb3IgYmx1ZVxudmFyIEJMVUVfRkxBRyA9ICgxPDwyOClcblxuLy8xRCBzd2VlcCBldmVudCBxdWV1ZSBzdHVmZiAodXNlIHBvb2wgdG8gc2F2ZSBzcGFjZSlcbnZhciBJTklUX0NBUEFDSVRZICAgICAgPSAxMDI0XG52YXIgUkVEX1NXRUVQX1FVRVVFICAgID0gcG9vbC5tYWxsb2NJbnQzMihJTklUX0NBUEFDSVRZKVxudmFyIFJFRF9TV0VFUF9JTkRFWCAgICA9IHBvb2wubWFsbG9jSW50MzIoSU5JVF9DQVBBQ0lUWSlcbnZhciBCTFVFX1NXRUVQX1FVRVVFICAgPSBwb29sLm1hbGxvY0ludDMyKElOSVRfQ0FQQUNJVFkpXG52YXIgQkxVRV9TV0VFUF9JTkRFWCAgID0gcG9vbC5tYWxsb2NJbnQzMihJTklUX0NBUEFDSVRZKVxudmFyIENPTU1PTl9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIoSU5JVF9DQVBBQ0lUWSlcbnZhciBDT01NT05fU1dFRVBfSU5ERVggPSBwb29sLm1hbGxvY0ludDMyKElOSVRfQ0FQQUNJVFkpXG52YXIgU1dFRVBfRVZFTlRTICAgICAgID0gcG9vbC5tYWxsb2NEb3VibGUoSU5JVF9DQVBBQ0lUWSAqIDgpXG5cbi8vUmVzZXJ2ZXMgbWVtb3J5IGZvciB0aGUgMUQgc3dlZXAgZGF0YSBzdHJ1Y3R1cmVzXG5mdW5jdGlvbiBzcUluaXQoY291bnQpIHtcbiAgdmFyIHJjb3VudCA9IGJpdHMubmV4dFBvdzIoY291bnQpXG4gIGlmKFJFRF9TV0VFUF9RVUVVRS5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoUkVEX1NXRUVQX1FVRVVFKVxuICAgIFJFRF9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKFJFRF9TV0VFUF9JTkRFWC5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoUkVEX1NXRUVQX0lOREVYKVxuICAgIFJFRF9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKEJMVUVfU1dFRVBfUVVFVUUubGVuZ3RoIDwgcmNvdW50KSB7XG4gICAgcG9vbC5mcmVlKEJMVUVfU1dFRVBfUVVFVUUpXG4gICAgQkxVRV9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKEJMVUVfU1dFRVBfSU5ERVgubGVuZ3RoIDwgcmNvdW50KSB7XG4gICAgcG9vbC5mcmVlKEJMVUVfU1dFRVBfSU5ERVgpXG4gICAgQkxVRV9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKENPTU1PTl9TV0VFUF9RVUVVRS5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoQ09NTU9OX1NXRUVQX1FVRVVFKVxuICAgIENPTU1PTl9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKENPTU1PTl9TV0VFUF9JTkRFWC5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoQ09NTU9OX1NXRUVQX0lOREVYKVxuICAgIENPTU1PTl9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIHZhciBldmVudExlbmd0aCA9IDggKiByY291bnRcbiAgaWYoU1dFRVBfRVZFTlRTLmxlbmd0aCA8IGV2ZW50TGVuZ3RoKSB7XG4gICAgcG9vbC5mcmVlKFNXRUVQX0VWRU5UUylcbiAgICBTV0VFUF9FVkVOVFMgPSBwb29sLm1hbGxvY0RvdWJsZShldmVudExlbmd0aClcbiAgfVxufVxuXG4vL1JlbW92ZSBhbiBpdGVtIGZyb20gdGhlIGFjdGl2ZSBxdWV1ZSBpbiBPKDEpXG5mdW5jdGlvbiBzcVBvcChxdWV1ZSwgaW5kZXgsIGNvdW50LCBpdGVtKSB7XG4gIHZhciBpZHggPSBpbmRleFtpdGVtXVxuICB2YXIgdG9wID0gcXVldWVbY291bnQtMV1cbiAgcXVldWVbaWR4XSA9IHRvcFxuICBpbmRleFt0b3BdID0gaWR4XG59XG5cbi8vSW5zZXJ0IGFuIGl0ZW0gaW50byB0aGUgYWN0aXZlIHF1ZXVlIGluIE8oMSlcbmZ1bmN0aW9uIHNxUHVzaChxdWV1ZSwgaW5kZXgsIGNvdW50LCBpdGVtKSB7XG4gIHF1ZXVlW2NvdW50XSA9IGl0ZW1cbiAgaW5kZXhbaXRlbV0gID0gY291bnRcbn1cblxuLy9SZWN1cnNpb24gYmFzZSBjYXNlOiB1c2UgMUQgc3dlZXAgYWxnb3JpdGhtXG5mdW5jdGlvbiBzd2VlcEJpcGFydGl0ZShcbiAgICBkLCB2aXNpdCxcbiAgICByZWRTdGFydCwgIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleCkge1xuXG4gIC8vc3RvcmUgZXZlbnRzIGFzIHBhaXJzIFtjb29yZGluYXRlLCBpZHhdXG4gIC8vXG4gIC8vICByZWQgY3JlYXRlOiAgLShpZHgrMSlcbiAgLy8gIHJlZCBkZXN0cm95OiBpZHhcbiAgLy8gIGJsdWUgY3JlYXRlOiAtKGlkeCtCTFVFX0ZMQUcpXG4gIC8vICBibHVlIGRlc3Ryb3k6IGlkeCtCTFVFX0ZMQUdcbiAgLy9cbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gZC0xXG4gIHZhciBpZW5kICAgICA9IGVsZW1TaXplLTFcblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gcmVkSW5kZXhbaV1cbiAgICB2YXIgcmVkT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLShpZHgrMSlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpZW5kXVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBpZHhcbiAgfVxuXG4gIGZvcih2YXIgaT1ibHVlU3RhcnQ7IGk8Ymx1ZUVuZDsgKytpKSB7XG4gICAgdmFyIGlkeCA9IGJsdWVJbmRleFtpXStCTFVFX0ZMQUdcbiAgICB2YXIgYmx1ZU9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gYmx1ZVtibHVlT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4XG4gIH1cblxuICAvL3Byb2Nlc3MgZXZlbnRzIGZyb20gbGVmdC0+cmlnaHRcbiAgdmFyIG4gPSBwdHIgPj4+IDFcbiAgaXNvcnQoU1dFRVBfRVZFTlRTLCBuKVxuICBcbiAgdmFyIHJlZEFjdGl2ZSAgPSAwXG4gIHZhciBibHVlQWN0aXZlID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSA9IFNXRUVQX0VWRU5UU1syKmkrMV18MFxuICAgIGlmKGUgPj0gQkxVRV9GTEFHKSB7XG4gICAgICAvL2JsdWUgZGVzdHJveSBldmVudFxuICAgICAgZSA9IChlLUJMVUVfRkxBRyl8MFxuICAgICAgc3FQb3AoQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZS0tLCBlKVxuICAgIH0gZWxzZSBpZihlID49IDApIHtcbiAgICAgIC8vcmVkIGRlc3Ryb3kgZXZlbnRcbiAgICAgIHNxUG9wKFJFRF9TV0VFUF9RVUVVRSwgUkVEX1NXRUVQX0lOREVYLCByZWRBY3RpdmUtLSwgZSlcbiAgICB9IGVsc2UgaWYoZSA8PSAtQkxVRV9GTEFHKSB7XG4gICAgICAvL2JsdWUgY3JlYXRlIGV2ZW50XG4gICAgICBlID0gKC1lLUJMVUVfRkxBRyl8MFxuICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KFJFRF9TV0VFUF9RVUVVRVtqXSwgZSlcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNxUHVzaChCTFVFX1NXRUVQX1FVRVVFLCBCTFVFX1NXRUVQX0lOREVYLCBibHVlQWN0aXZlKyssIGUpXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vcmVkIGNyZWF0ZSBldmVudFxuICAgICAgZSA9ICgtZS0xKXwwXG4gICAgICBmb3IodmFyIGo9MDsgajxibHVlQWN0aXZlOyArK2opIHtcbiAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KGUsIEJMVUVfU1dFRVBfUVVFVUVbal0pXG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzcVB1c2goUkVEX1NXRUVQX1FVRVVFLCBSRURfU1dFRVBfSU5ERVgsIHJlZEFjdGl2ZSsrLCBlKVxuICAgIH1cbiAgfVxufVxuXG4vL0NvbXBsZXRlIHN3ZWVwXG5mdW5jdGlvbiBzd2VlcENvbXBsZXRlKGQsIHZpc2l0LCBcbiAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpIHtcblxuICB2YXIgcHRyICAgICAgPSAwXG4gIHZhciBlbGVtU2l6ZSA9IDIqZFxuICB2YXIgaXN0YXJ0ICAgPSBkLTFcbiAgdmFyIGllbmQgICAgID0gZWxlbVNpemUtMVxuXG4gIGZvcih2YXIgaT1yZWRTdGFydDsgaTxyZWRFbmQ7ICsraSkge1xuICAgIHZhciBpZHggPSAocmVkSW5kZXhbaV0rMSk8PDFcbiAgICB2YXIgcmVkT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2llbmRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IGlkeFxuICB9XG5cbiAgZm9yKHZhciBpPWJsdWVTdGFydDsgaTxibHVlRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gKGJsdWVJbmRleFtpXSsxKTw8MVxuICAgIHZhciBibHVlT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraXN0YXJ0XVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSAoLWlkeCl8MVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4fDFcbiAgfVxuXG4gIC8vcHJvY2VzcyBldmVudHMgZnJvbSBsZWZ0LT5yaWdodFxuICB2YXIgbiA9IHB0ciA+Pj4gMVxuICBpc29ydChTV0VFUF9FVkVOVFMsIG4pXG4gIFxuICB2YXIgcmVkQWN0aXZlICAgID0gMFxuICB2YXIgYmx1ZUFjdGl2ZSAgID0gMFxuICB2YXIgY29tbW9uQWN0aXZlID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSAgICAgPSBTV0VFUF9FVkVOVFNbMippKzFdfDBcbiAgICB2YXIgY29sb3IgPSBlJjFcbiAgICBpZihpIDwgbi0xICYmIChlPj4xKSA9PT0gKFNXRUVQX0VWRU5UU1syKmkrM10+PjEpKSB7XG4gICAgICBjb2xvciA9IDJcbiAgICAgIGkgKz0gMVxuICAgIH1cbiAgICBcbiAgICBpZihlIDwgMCkge1xuICAgICAgLy9DcmVhdGUgZXZlbnRcbiAgICAgIHZhciBpZCA9IC0oZT4+MSkgLSAxXG5cbiAgICAgIC8vSW50ZXJzZWN0IHdpdGggY29tbW9uXG4gICAgICBmb3IodmFyIGo9MDsgajxjb21tb25BY3RpdmU7ICsraikge1xuICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQoQ09NTU9OX1NXRUVQX1FVRVVFW2pdLCBpZClcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoY29sb3IgIT09IDApIHtcbiAgICAgICAgLy9JbnRlcnNlY3Qgd2l0aCByZWRcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQoUkVEX1NXRUVQX1FVRVVFW2pdLCBpZClcbiAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihjb2xvciAhPT0gMSkge1xuICAgICAgICAvL0ludGVyc2VjdCB3aXRoIGJsdWVcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8Ymx1ZUFjdGl2ZTsgKytqKSB7XG4gICAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KEJMVUVfU1dFRVBfUVVFVUVbal0sIGlkKVxuICAgICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmKGNvbG9yID09PSAwKSB7XG4gICAgICAgIC8vUmVkXG4gICAgICAgIHNxUHVzaChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlKyssIGlkKVxuICAgICAgfSBlbHNlIGlmKGNvbG9yID09PSAxKSB7XG4gICAgICAgIC8vQmx1ZVxuICAgICAgICBzcVB1c2goQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZSsrLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMikge1xuICAgICAgICAvL0JvdGhcbiAgICAgICAgc3FQdXNoKENPTU1PTl9TV0VFUF9RVUVVRSwgQ09NTU9OX1NXRUVQX0lOREVYLCBjb21tb25BY3RpdmUrKywgaWQpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vRGVzdHJveSBldmVudFxuICAgICAgdmFyIGlkID0gKGU+PjEpIC0gMVxuICAgICAgaWYoY29sb3IgPT09IDApIHtcbiAgICAgICAgLy9SZWRcbiAgICAgICAgc3FQb3AoUkVEX1NXRUVQX1FVRVVFLCBSRURfU1dFRVBfSU5ERVgsIHJlZEFjdGl2ZS0tLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMSkge1xuICAgICAgICAvL0JsdWVcbiAgICAgICAgc3FQb3AoQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZS0tLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMikge1xuICAgICAgICAvL0JvdGhcbiAgICAgICAgc3FQb3AoQ09NTU9OX1NXRUVQX1FVRVVFLCBDT01NT05fU1dFRVBfSU5ERVgsIGNvbW1vbkFjdGl2ZS0tLCBpZClcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLy9Td2VlcCBhbmQgcHJ1bmUvc2NhbmxpbmUgYWxnb3JpdGhtOlxuLy8gIFNjYW4gYWxvbmcgYXhpcywgZGV0ZWN0IGludGVyc2VjdGlvbnNcbi8vICBCcnV0ZSBmb3JjZSBhbGwgYm94ZXMgYWxvbmcgYXhpc1xuZnVuY3Rpb24gc2NhbkJpcGFydGl0ZShcbiAgZCwgYXhpcywgdmlzaXQsIGZsaXAsXG4gIHJlZFN0YXJ0LCAgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleCkge1xuICBcbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gYXhpc1xuICB2YXIgaWVuZCAgICAgPSBheGlzK2RcblxuICB2YXIgcmVkU2hpZnQgID0gMVxuICB2YXIgYmx1ZVNoaWZ0ID0gMVxuICBpZihmbGlwKSB7XG4gICAgYmx1ZVNoaWZ0ID0gQkxVRV9GTEFHXG4gIH0gZWxzZSB7XG4gICAgcmVkU2hpZnQgID0gQkxVRV9GTEFHXG4gIH1cblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIHJlZFNoaWZ0XG4gICAgdmFyIHJlZE9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpc3RhcnRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IC1pZHhcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpZW5kXVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBpZHhcbiAgfVxuICBmb3IodmFyIGk9Ymx1ZVN0YXJ0OyBpPGJsdWVFbmQ7ICsraSkge1xuICAgIHZhciBpZHggPSBpICsgYmx1ZVNoaWZ0XG4gICAgdmFyIGJsdWVPZmZzZXQgPSBlbGVtU2l6ZSppXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IGJsdWVbYmx1ZU9mZnNldCtpc3RhcnRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IC1pZHhcbiAgfVxuXG4gIC8vcHJvY2VzcyBldmVudHMgZnJvbSBsZWZ0LT5yaWdodFxuICB2YXIgbiA9IHB0ciA+Pj4gMVxuICBpc29ydChTV0VFUF9FVkVOVFMsIG4pXG4gIFxuICB2YXIgcmVkQWN0aXZlICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSA9IFNXRUVQX0VWRU5UU1syKmkrMV18MFxuICAgIGlmKGUgPCAwKSB7XG4gICAgICB2YXIgaWR4ICAgPSAtZVxuICAgICAgdmFyIGlzUmVkID0gZmFsc2VcbiAgICAgIGlmKGlkeCA+PSBCTFVFX0ZMQUcpIHtcbiAgICAgICAgaXNSZWQgPSAhZmxpcFxuICAgICAgICBpZHggLT0gQkxVRV9GTEFHIFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaXNSZWQgPSAhIWZsaXBcbiAgICAgICAgaWR4IC09IDFcbiAgICAgIH1cbiAgICAgIGlmKGlzUmVkKSB7XG4gICAgICAgIHNxUHVzaChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlKyssIGlkeClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBibHVlSWQgID0gYmx1ZUluZGV4W2lkeF1cbiAgICAgICAgdmFyIGJsdWVQdHIgPSBlbGVtU2l6ZSAqIGlkeFxuICAgICAgICBcbiAgICAgICAgdmFyIGIwID0gYmx1ZVtibHVlUHRyK2F4aXMrMV1cbiAgICAgICAgdmFyIGIxID0gYmx1ZVtibHVlUHRyK2F4aXMrMStkXVxuXG5yZWRfbG9vcDpcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgICB2YXIgb2lkeCAgID0gUkVEX1NXRUVQX1FVRVVFW2pdXG4gICAgICAgICAgdmFyIHJlZFB0ciA9IGVsZW1TaXplICogb2lkeFxuXG4gICAgICAgICAgaWYoYjEgPCByZWRbcmVkUHRyK2F4aXMrMV0gfHwgXG4gICAgICAgICAgICAgcmVkW3JlZFB0citheGlzKzErZF0gPCBiMCkge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IodmFyIGs9YXhpcysyOyBrPGQ7ICsraykge1xuICAgICAgICAgICAgaWYoYmx1ZVtibHVlUHRyICsgayArIGRdIDwgcmVkW3JlZFB0ciArIGtdIHx8IFxuICAgICAgICAgICAgICAgcmVkW3JlZFB0ciArIGsgKyBkXSA8IGJsdWVbYmx1ZVB0ciArIGtdKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIHJlZF9sb29wXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHJlZElkICA9IHJlZEluZGV4W29pZHhdXG4gICAgICAgICAgdmFyIHJldHZhbFxuICAgICAgICAgIGlmKGZsaXApIHtcbiAgICAgICAgICAgIHJldHZhbCA9IHZpc2l0KGJsdWVJZCwgcmVkSWQpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHZhbCA9IHZpc2l0KHJlZElkLCBibHVlSWQpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gcmV0dmFsIFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzcVBvcChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlLS0sIGUgLSByZWRTaGlmdClcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc2NhbkNvbXBsZXRlKFxuICBkLCBheGlzLCB2aXNpdCxcbiAgcmVkU3RhcnQsICByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KSB7XG5cbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gYXhpc1xuICB2YXIgaWVuZCAgICAgPSBheGlzK2RcblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIEJMVUVfRkxBR1xuICAgIHZhciByZWRPZmZzZXQgPSBlbGVtU2l6ZSppXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IHJlZFtyZWRPZmZzZXQraXN0YXJ0XVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSAtaWR4XG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IHJlZFtyZWRPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4XG4gIH1cbiAgZm9yKHZhciBpPWJsdWVTdGFydDsgaTxibHVlRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIDFcbiAgICB2YXIgYmx1ZU9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gYmx1ZVtibHVlT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICB9XG5cbiAgLy9wcm9jZXNzIGV2ZW50cyBmcm9tIGxlZnQtPnJpZ2h0XG4gIHZhciBuID0gcHRyID4+PiAxXG4gIGlzb3J0KFNXRUVQX0VWRU5UUywgbilcbiAgXG4gIHZhciByZWRBY3RpdmUgICAgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBlID0gU1dFRVBfRVZFTlRTWzIqaSsxXXwwXG4gICAgaWYoZSA8IDApIHtcbiAgICAgIHZhciBpZHggICA9IC1lXG4gICAgICBpZihpZHggPj0gQkxVRV9GTEFHKSB7XG4gICAgICAgIFJFRF9TV0VFUF9RVUVVRVtyZWRBY3RpdmUrK10gPSBpZHggLSBCTFVFX0ZMQUdcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlkeCAtPSAxXG4gICAgICAgIHZhciBibHVlSWQgID0gYmx1ZUluZGV4W2lkeF1cbiAgICAgICAgdmFyIGJsdWVQdHIgPSBlbGVtU2l6ZSAqIGlkeFxuXG4gICAgICAgIHZhciBiMCA9IGJsdWVbYmx1ZVB0citheGlzKzFdXG4gICAgICAgIHZhciBiMSA9IGJsdWVbYmx1ZVB0citheGlzKzErZF1cblxucmVkX2xvb3A6XG4gICAgICAgIGZvcih2YXIgaj0wOyBqPHJlZEFjdGl2ZTsgKytqKSB7XG4gICAgICAgICAgdmFyIG9pZHggICA9IFJFRF9TV0VFUF9RVUVVRVtqXVxuICAgICAgICAgIHZhciByZWRJZCAgPSByZWRJbmRleFtvaWR4XVxuXG4gICAgICAgICAgaWYocmVkSWQgPT09IGJsdWVJZCkge1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmVkUHRyID0gZWxlbVNpemUgKiBvaWR4XG4gICAgICAgICAgaWYoYjEgPCByZWRbcmVkUHRyK2F4aXMrMV0gfHwgXG4gICAgICAgICAgICByZWRbcmVkUHRyK2F4aXMrMStkXSA8IGIwKSB7XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IodmFyIGs9YXhpcysyOyBrPGQ7ICsraykge1xuICAgICAgICAgICAgaWYoYmx1ZVtibHVlUHRyICsgayArIGRdIDwgcmVkW3JlZFB0ciArIGtdIHx8IFxuICAgICAgICAgICAgICAgcmVkW3JlZFB0ciArIGsgKyBkXSAgIDwgYmx1ZVtibHVlUHRyICsga10pIHtcbiAgICAgICAgICAgICAgY29udGludWUgcmVkX2xvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQocmVkSWQsIGJsdWVJZClcbiAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJldHZhbCBcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGlkeCA9IGUgLSBCTFVFX0ZMQUdcbiAgICAgIGZvcih2YXIgaj1yZWRBY3RpdmUtMTsgaj49MDsgLS1qKSB7XG4gICAgICAgIGlmKFJFRF9TV0VFUF9RVUVVRVtqXSA9PT0gaWR4KSB7XG4gICAgICAgICAgZm9yKHZhciBrPWorMTsgazxyZWRBY3RpdmU7ICsraykge1xuICAgICAgICAgICAgUkVEX1NXRUVQX1FVRVVFW2stMV0gPSBSRURfU1dFRVBfUVVFVUVba11cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLS1yZWRBY3RpdmVcbiAgICB9XG4gIH1cbn0iLCIiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG5cbmV4cG9ydHMuQnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLlNsb3dCdWZmZXIgPSBTbG93QnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcblxudmFyIEtfTUFYX0xFTkdUSCA9IDB4N2ZmZmZmZmZcbmV4cG9ydHMua01heExlbmd0aCA9IEtfTUFYX0xFTkdUSFxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBQcmludCB3YXJuaW5nIGFuZCByZWNvbW1lbmQgdXNpbmcgYGJ1ZmZlcmAgdjQueCB3aGljaCBoYXMgYW4gT2JqZWN0XG4gKiAgICAgICAgICAgICAgIGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBXZSByZXBvcnQgdGhhdCB0aGUgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBpZiB0aGUgYXJlIG5vdCBzdWJjbGFzc2FibGVcbiAqIHVzaW5nIF9fcHJvdG9fXy4gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWBcbiAqIChTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOCkuIElFIDEwIGxhY2tzIHN1cHBvcnRcbiAqIGZvciBfX3Byb3RvX18gYW5kIGhhcyBhIGJ1Z2d5IHR5cGVkIGFycmF5IGltcGxlbWVudGF0aW9uLlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IHR5cGVkQXJyYXlTdXBwb3J0KClcblxuaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgY29uc29sZS5lcnJvciA9PT0gJ2Z1bmN0aW9uJykge1xuICBjb25zb2xlLmVycm9yKFxuICAgICdUaGlzIGJyb3dzZXIgbGFja3MgdHlwZWQgYXJyYXkgKFVpbnQ4QXJyYXkpIHN1cHBvcnQgd2hpY2ggaXMgcmVxdWlyZWQgYnkgJyArXG4gICAgJ2BidWZmZXJgIHY1LnguIFVzZSBgYnVmZmVyYCB2NC54IGlmIHlvdSByZXF1aXJlIG9sZCBicm93c2VyIHN1cHBvcnQuJ1xuICApXG59XG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgLy8gQ2FuIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkP1xuICB0cnkge1xuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGFyci5fX3Byb3RvX18gPSB7X19wcm90b19fOiBVaW50OEFycmF5LnByb3RvdHlwZSwgZm9vOiBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9fVxuICAgIHJldHVybiBhcnIuZm9vKCkgPT09IDQyXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLnByb3RvdHlwZSwgJ3BhcmVudCcsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGhpcykpIHJldHVybiB1bmRlZmluZWRcbiAgICByZXR1cm4gdGhpcy5idWZmZXJcbiAgfVxufSlcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEJ1ZmZlci5wcm90b3R5cGUsICdvZmZzZXQnLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKHRoaXMpKSByZXR1cm4gdW5kZWZpbmVkXG4gICAgcmV0dXJuIHRoaXMuYnl0ZU9mZnNldFxuICB9XG59KVxuXG5mdW5jdGlvbiBjcmVhdGVCdWZmZXIgKGxlbmd0aCkge1xuICBpZiAobGVuZ3RoID4gS19NQVhfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBcIicgKyBsZW5ndGggKyAnXCIgaXMgaW52YWxpZCBmb3Igb3B0aW9uIFwic2l6ZVwiJylcbiAgfVxuICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZVxuICB2YXIgYnVmID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKVxuICBidWYuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICByZXR1cm4gYnVmXG59XG5cbi8qKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBoYXZlIHRoZWlyXG4gKiBwcm90b3R5cGUgY2hhbmdlZCB0byBgQnVmZmVyLnByb3RvdHlwZWAuIEZ1cnRoZXJtb3JlLCBgQnVmZmVyYCBpcyBhIHN1YmNsYXNzIG9mXG4gKiBgVWludDhBcnJheWAsIHNvIHRoZSByZXR1cm5lZCBpbnN0YW5jZXMgd2lsbCBoYXZlIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBtZXRob2RzXG4gKiBhbmQgdGhlIGBVaW50OEFycmF5YCBtZXRob2RzLiBTcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdFxuICogcmV0dXJucyBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBUaGUgYFVpbnQ4QXJyYXlgIHByb3RvdHlwZSByZW1haW5zIHVubW9kaWZpZWQuXG4gKi9cblxuZnVuY3Rpb24gQnVmZmVyIChhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICAvLyBDb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZ09yT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgJ1RoZSBcInN0cmluZ1wiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBzdHJpbmcuIFJlY2VpdmVkIHR5cGUgbnVtYmVyJ1xuICAgICAgKVxuICAgIH1cbiAgICByZXR1cm4gYWxsb2NVbnNhZmUoYXJnKVxuICB9XG4gIHJldHVybiBmcm9tKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxufVxuXG4vLyBGaXggc3ViYXJyYXkoKSBpbiBFUzIwMTYuIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvcHVsbC85N1xuaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC5zcGVjaWVzICE9IG51bGwgJiZcbiAgICBCdWZmZXJbU3ltYm9sLnNwZWNpZXNdID09PSBCdWZmZXIpIHtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEJ1ZmZlciwgU3ltYm9sLnNwZWNpZXMsIHtcbiAgICB2YWx1ZTogbnVsbCxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgd3JpdGFibGU6IGZhbHNlXG4gIH0pXG59XG5cbkJ1ZmZlci5wb29sU2l6ZSA9IDgxOTIgLy8gbm90IHVzZWQgYnkgdGhpcyBpbXBsZW1lbnRhdGlvblxuXG5mdW5jdGlvbiBmcm9tICh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZyb21TdHJpbmcodmFsdWUsIGVuY29kaW5nT3JPZmZzZXQpXG4gIH1cblxuICBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KHZhbHVlKSkge1xuICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKHZhbHVlKVxuICB9XG5cbiAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICB0aHJvdyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgJyArXG4gICAgICAnb3IgQXJyYXktbGlrZSBPYmplY3QuIFJlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdmFsdWUpXG4gICAgKVxuICB9XG5cbiAgaWYgKGlzSW5zdGFuY2UodmFsdWUsIEFycmF5QnVmZmVyKSB8fFxuICAgICAgKHZhbHVlICYmIGlzSW5zdGFuY2UodmFsdWUuYnVmZmVyLCBBcnJheUJ1ZmZlcikpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgb2YgdHlwZSBudW1iZXIuIFJlY2VpdmVkIHR5cGUgbnVtYmVyJ1xuICAgIClcbiAgfVxuXG4gIHZhciB2YWx1ZU9mID0gdmFsdWUudmFsdWVPZiAmJiB2YWx1ZS52YWx1ZU9mKClcbiAgaWYgKHZhbHVlT2YgIT0gbnVsbCAmJiB2YWx1ZU9mICE9PSB2YWx1ZSkge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbSh2YWx1ZU9mLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICB2YXIgYiA9IGZyb21PYmplY3QodmFsdWUpXG4gIGlmIChiKSByZXR1cm4gYlxuXG4gIGlmICh0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9QcmltaXRpdmUgIT0gbnVsbCAmJlxuICAgICAgdHlwZW9mIHZhbHVlW1N5bWJvbC50b1ByaW1pdGl2ZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oXG4gICAgICB2YWx1ZVtTeW1ib2wudG9QcmltaXRpdmVdKCdzdHJpbmcnKSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoXG4gICAgKVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAnVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgJyArXG4gICAgJ29yIEFycmF5LWxpa2UgT2JqZWN0LiBSZWNlaXZlZCB0eXBlICcgKyAodHlwZW9mIHZhbHVlKVxuICApXG59XG5cbi8qKlxuICogRnVuY3Rpb25hbGx5IGVxdWl2YWxlbnQgdG8gQnVmZmVyKGFyZywgZW5jb2RpbmcpIGJ1dCB0aHJvd3MgYSBUeXBlRXJyb3JcbiAqIGlmIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQnVmZmVyLmZyb20oc3RyWywgZW5jb2RpbmddKVxuICogQnVmZmVyLmZyb20oYXJyYXkpXG4gKiBCdWZmZXIuZnJvbShidWZmZXIpXG4gKiBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlclssIGJ5dGVPZmZzZXRbLCBsZW5ndGhdXSlcbiAqKi9cbkJ1ZmZlci5mcm9tID0gZnVuY3Rpb24gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGZyb20odmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuLy8gTm90ZTogQ2hhbmdlIHByb3RvdHlwZSAqYWZ0ZXIqIEJ1ZmZlci5mcm9tIGlzIGRlZmluZWQgdG8gd29ya2Fyb3VuZCBDaHJvbWUgYnVnOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvcHVsbC8xNDhcbkJ1ZmZlci5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGVcbkJ1ZmZlci5fX3Byb3RvX18gPSBVaW50OEFycmF5XG5cbmZ1bmN0aW9uIGFzc2VydFNpemUgKHNpemUpIHtcbiAgaWYgKHR5cGVvZiBzaXplICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wic2l6ZVwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBudW1iZXInKVxuICB9IGVsc2UgaWYgKHNpemUgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBcIicgKyBzaXplICsgJ1wiIGlzIGludmFsaWQgZm9yIG9wdGlvbiBcInNpemVcIicpXG4gIH1cbn1cblxuZnVuY3Rpb24gYWxsb2MgKHNpemUsIGZpbGwsIGVuY29kaW5nKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgaWYgKHNpemUgPD0gMCkge1xuICAgIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbiAgfVxuICBpZiAoZmlsbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gT25seSBwYXkgYXR0ZW50aW9uIHRvIGVuY29kaW5nIGlmIGl0J3MgYSBzdHJpbmcuIFRoaXNcbiAgICAvLyBwcmV2ZW50cyBhY2NpZGVudGFsbHkgc2VuZGluZyBpbiBhIG51bWJlciB0aGF0IHdvdWxkXG4gICAgLy8gYmUgaW50ZXJwcmV0dGVkIGFzIGEgc3RhcnQgb2Zmc2V0LlxuICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICA/IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgICAgOiBjcmVhdGVCdWZmZXIoc2l6ZSkuZmlsbChmaWxsKVxuICB9XG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKiBhbGxvYyhzaXplWywgZmlsbFssIGVuY29kaW5nXV0pXG4gKiovXG5CdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGFsbG9jKHNpemUsIGZpbGwsIGVuY29kaW5nKVxufVxuXG5mdW5jdGlvbiBhbGxvY1Vuc2FmZSAoc2l6ZSkge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG59XG5cbi8qKlxuICogRXF1aXZhbGVudCB0byBCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqICovXG5CdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cbi8qKlxuICogRXF1aXZhbGVudCB0byBTbG93QnVmZmVyKG51bSksIGJ5IGRlZmF1bHQgY3JlYXRlcyBhIG5vbi16ZXJvLWZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICB9XG5cbiAgaWYgKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gIH1cblxuICB2YXIgbGVuZ3RoID0gYnl0ZUxlbmd0aChzdHJpbmcsIGVuY29kaW5nKSB8IDBcbiAgdmFyIGJ1ZiA9IGNyZWF0ZUJ1ZmZlcihsZW5ndGgpXG5cbiAgdmFyIGFjdHVhbCA9IGJ1Zi53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuXG4gIGlmIChhY3R1YWwgIT09IGxlbmd0aCkge1xuICAgIC8vIFdyaXRpbmcgYSBoZXggc3RyaW5nLCBmb3IgZXhhbXBsZSwgdGhhdCBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnMgd2lsbFxuICAgIC8vIGNhdXNlIGV2ZXJ5dGhpbmcgYWZ0ZXIgdGhlIGZpcnN0IGludmFsaWQgY2hhcmFjdGVyIHRvIGJlIGlnbm9yZWQuIChlLmcuXG4gICAgLy8gJ2FieHhjZCcgd2lsbCBiZSB0cmVhdGVkIGFzICdhYicpXG4gICAgYnVmID0gYnVmLnNsaWNlKDAsIGFjdHVhbClcbiAgfVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5TGlrZSAoYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIGJ1ZltpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIgKGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwIHx8IGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0KSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1wib2Zmc2V0XCIgaXMgb3V0c2lkZSBvZiBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGlmIChhcnJheS5ieXRlTGVuZ3RoIDwgYnl0ZU9mZnNldCArIChsZW5ndGggfHwgMCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJsZW5ndGhcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgdmFyIGJ1ZlxuICBpZiAoYnl0ZU9mZnNldCA9PT0gdW5kZWZpbmVkICYmIGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYnVmID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXkpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSwgYnl0ZU9mZnNldClcbiAgfSBlbHNlIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSwgYnl0ZU9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2VcbiAgYnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0IChvYmopIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmopKSB7XG4gICAgdmFyIGxlbiA9IGNoZWNrZWQob2JqLmxlbmd0aCkgfCAwXG4gICAgdmFyIGJ1ZiA9IGNyZWF0ZUJ1ZmZlcihsZW4pXG5cbiAgICBpZiAoYnVmLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJ1ZlxuICAgIH1cblxuICAgIG9iai5jb3B5KGJ1ZiwgMCwgMCwgbGVuKVxuICAgIHJldHVybiBidWZcbiAgfVxuXG4gIGlmIChvYmoubGVuZ3RoICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIG9iai5sZW5ndGggIT09ICdudW1iZXInIHx8IG51bWJlcklzTmFOKG9iai5sZW5ndGgpKSB7XG4gICAgICByZXR1cm4gY3JlYXRlQnVmZmVyKDApXG4gICAgfVxuICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKG9iailcbiAgfVxuXG4gIGlmIChvYmoudHlwZSA9PT0gJ0J1ZmZlcicgJiYgQXJyYXkuaXNBcnJheShvYmouZGF0YSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5TGlrZShvYmouZGF0YSlcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwgS19NQVhfTEVOR1RIYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IEtfTUFYX0xFTkdUSCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBLX01BWF9MRU5HVEgudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlciAobGVuZ3RoKSB7XG4gIGlmICgrbGVuZ3RoICE9IGxlbmd0aCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGVxZXFlcVxuICAgIGxlbmd0aCA9IDBcbiAgfVxuICByZXR1cm4gQnVmZmVyLmFsbG9jKCtsZW5ndGgpXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiBiICE9IG51bGwgJiYgYi5faXNCdWZmZXIgPT09IHRydWUgJiZcbiAgICBiICE9PSBCdWZmZXIucHJvdG90eXBlIC8vIHNvIEJ1ZmZlci5pc0J1ZmZlcihCdWZmZXIucHJvdG90eXBlKSB3aWxsIGJlIGZhbHNlXG59XG5cbkJ1ZmZlci5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAoYSwgYikge1xuICBpZiAoaXNJbnN0YW5jZShhLCBVaW50OEFycmF5KSkgYSA9IEJ1ZmZlci5mcm9tKGEsIGEub2Zmc2V0LCBhLmJ5dGVMZW5ndGgpXG4gIGlmIChpc0luc3RhbmNlKGIsIFVpbnQ4QXJyYXkpKSBiID0gQnVmZmVyLmZyb20oYiwgYi5vZmZzZXQsIGIuYnl0ZUxlbmd0aClcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYSkgfHwgIUJ1ZmZlci5pc0J1ZmZlcihiKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwiYnVmMVwiLCBcImJ1ZjJcIiBhcmd1bWVudHMgbXVzdCBiZSBvbmUgb2YgdHlwZSBCdWZmZXIgb3IgVWludDhBcnJheSdcbiAgICApXG4gIH1cblxuICBpZiAoYSA9PT0gYikgcmV0dXJuIDBcblxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gTWF0aC5taW4oeCwgeSk7IGkgPCBsZW47ICsraSkge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSB7XG4gICAgICB4ID0gYVtpXVxuICAgICAgeSA9IGJbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG5CdWZmZXIuaXNFbmNvZGluZyA9IGZ1bmN0aW9uIGlzRW5jb2RpbmcgKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gY29uY2F0IChsaXN0LCBsZW5ndGgpIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGxpc3QpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgfVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBCdWZmZXIuYWxsb2MoMClcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGxlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgICAgbGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShsZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGJ1ZiA9IGxpc3RbaV1cbiAgICBpZiAoaXNJbnN0YW5jZShidWYsIFVpbnQ4QXJyYXkpKSB7XG4gICAgICBidWYgPSBCdWZmZXIuZnJvbShidWYpXG4gICAgfVxuICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gICAgfVxuICAgIGJ1Zi5jb3B5KGJ1ZmZlciwgcG9zKVxuICAgIHBvcyArPSBidWYubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZmZlclxufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIoc3RyaW5nKSkge1xuICAgIHJldHVybiBzdHJpbmcubGVuZ3RoXG4gIH1cbiAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhzdHJpbmcpIHx8IGlzSW5zdGFuY2Uoc3RyaW5nLCBBcnJheUJ1ZmZlcikpIHtcbiAgICByZXR1cm4gc3RyaW5nLmJ5dGVMZW5ndGhcbiAgfVxuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInN0cmluZ1wiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIG9yIEFycmF5QnVmZmVyLiAnICtcbiAgICAgICdSZWNlaXZlZCB0eXBlICcgKyB0eXBlb2Ygc3RyaW5nXG4gICAgKVxuICB9XG5cbiAgdmFyIGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgdmFyIG11c3RNYXRjaCA9IChhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gPT09IHRydWUpXG4gIGlmICghbXVzdE1hdGNoICYmIGxlbiA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBVc2UgYSBmb3IgbG9vcCB0byBhdm9pZCByZWN1cnNpb25cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGVuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gbGVuICogMlxuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGxlbiA+Pj4gMVxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkge1xuICAgICAgICAgIHJldHVybiBtdXN0TWF0Y2ggPyAtMSA6IHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoIC8vIGFzc3VtZSB1dGY4XG4gICAgICAgIH1cbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuXG5mdW5jdGlvbiBzbG93VG9TdHJpbmcgKGVuY29kaW5nLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG5cbiAgLy8gTm8gbmVlZCB0byB2ZXJpZnkgdGhhdCBcInRoaXMubGVuZ3RoIDw9IE1BWF9VSU5UMzJcIiBzaW5jZSBpdCdzIGEgcmVhZC1vbmx5XG4gIC8vIHByb3BlcnR5IG9mIGEgdHlwZWQgYXJyYXkuXG5cbiAgLy8gVGhpcyBiZWhhdmVzIG5laXRoZXIgbGlrZSBTdHJpbmcgbm9yIFVpbnQ4QXJyYXkgaW4gdGhhdCB3ZSBzZXQgc3RhcnQvZW5kXG4gIC8vIHRvIHRoZWlyIHVwcGVyL2xvd2VyIGJvdW5kcyBpZiB0aGUgdmFsdWUgcGFzc2VkIGlzIG91dCBvZiByYW5nZS5cbiAgLy8gdW5kZWZpbmVkIGlzIGhhbmRsZWQgc3BlY2lhbGx5IGFzIHBlciBFQ01BLTI2MiA2dGggRWRpdGlvbixcbiAgLy8gU2VjdGlvbiAxMy4zLjMuNyBSdW50aW1lIFNlbWFudGljczogS2V5ZWRCaW5kaW5nSW5pdGlhbGl6YXRpb24uXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkIHx8IHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ID0gMFxuICB9XG4gIC8vIFJldHVybiBlYXJseSBpZiBzdGFydCA+IHRoaXMubGVuZ3RoLiBEb25lIGhlcmUgdG8gcHJldmVudCBwb3RlbnRpYWwgdWludDMyXG4gIC8vIGNvZXJjaW9uIGZhaWwgYmVsb3cuXG4gIGlmIChzdGFydCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICBpZiAoZW5kID09PSB1bmRlZmluZWQgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHtcbiAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKGVuZCA8PSAwKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICAvLyBGb3JjZSBjb2Vyc2lvbiB0byB1aW50MzIuIFRoaXMgd2lsbCBhbHNvIGNvZXJjZSBmYWxzZXkvTmFOIHZhbHVlcyB0byAwLlxuICBlbmQgPj4+PSAwXG4gIHN0YXJ0ID4+Pj0gMFxuXG4gIGlmIChlbmQgPD0gc3RhcnQpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxhdGluMVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdXRmMTZsZVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9IChlbmNvZGluZyArICcnKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG4vLyBUaGlzIHByb3BlcnR5IGlzIHVzZWQgYnkgYEJ1ZmZlci5pc0J1ZmZlcmAgKGFuZCB0aGUgYGlzLWJ1ZmZlcmAgbnBtIHBhY2thZ2UpXG4vLyB0byBkZXRlY3QgYSBCdWZmZXIgaW5zdGFuY2UuIEl0J3Mgbm90IHBvc3NpYmxlIHRvIHVzZSBgaW5zdGFuY2VvZiBCdWZmZXJgXG4vLyByZWxpYWJseSBpbiBhIGJyb3dzZXJpZnkgY29udGV4dCBiZWNhdXNlIHRoZXJlIGNvdWxkIGJlIG11bHRpcGxlIGRpZmZlcmVudFxuLy8gY29waWVzIG9mIHRoZSAnYnVmZmVyJyBwYWNrYWdlIGluIHVzZS4gVGhpcyBtZXRob2Qgd29ya3MgZXZlbiBmb3IgQnVmZmVyXG4vLyBpbnN0YW5jZXMgdGhhdCB3ZXJlIGNyZWF0ZWQgZnJvbSBhbm90aGVyIGNvcHkgb2YgdGhlIGBidWZmZXJgIHBhY2thZ2UuXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8xNTRcbkJ1ZmZlci5wcm90b3R5cGUuX2lzQnVmZmVyID0gdHJ1ZVxuXG5mdW5jdGlvbiBzd2FwIChiLCBuLCBtKSB7XG4gIHZhciBpID0gYltuXVxuICBiW25dID0gYlttXVxuICBiW21dID0gaVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXAxNiA9IGZ1bmN0aW9uIHN3YXAxNiAoKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgMiAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYtYml0cycpXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDEpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMzIgPSBmdW5jdGlvbiBzd2FwMzIgKCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbiAlIDQgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDMyLWJpdHMnKVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcbiAgICBzd2FwKHRoaXMsIGksIGkgKyAzKVxuICAgIHN3YXAodGhpcywgaSArIDEsIGkgKyAyKVxuICB9XG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc3dhcDY0ID0gZnVuY3Rpb24gc3dhcDY0ICgpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA4ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA2NC1iaXRzJylcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA4KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgNylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgNilcbiAgICBzd2FwKHRoaXMsIGkgKyAyLCBpICsgNSlcbiAgICBzd2FwKHRoaXMsIGkgKyAzLCBpICsgNClcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9Mb2NhbGVTdHJpbmcgPSBCdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nXG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgdmFyIHN0ciA9ICcnXG4gIHZhciBtYXggPSBleHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTXG4gIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkucmVwbGFjZSgvKC57Mn0pL2csICckMSAnKS50cmltKClcbiAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KSBzdHIgKz0gJyAuLi4gJ1xuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlICh0YXJnZXQsIHN0YXJ0LCBlbmQsIHRoaXNTdGFydCwgdGhpc0VuZCkge1xuICBpZiAoaXNJbnN0YW5jZSh0YXJnZXQsIFVpbnQ4QXJyYXkpKSB7XG4gICAgdGFyZ2V0ID0gQnVmZmVyLmZyb20odGFyZ2V0LCB0YXJnZXQub2Zmc2V0LCB0YXJnZXQuYnl0ZUxlbmd0aClcbiAgfVxuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0YXJnZXQpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJ0YXJnZXRcIiBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIEJ1ZmZlciBvciBVaW50OEFycmF5LiAnICtcbiAgICAgICdSZWNlaXZlZCB0eXBlICcgKyAodHlwZW9mIHRhcmdldClcbiAgICApXG4gIH1cblxuICBpZiAoc3RhcnQgPT09IHVuZGVmaW5lZCkge1xuICAgIHN0YXJ0ID0gMFxuICB9XG4gIGlmIChlbmQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuZCA9IHRhcmdldCA/IHRhcmdldC5sZW5ndGggOiAwXG4gIH1cbiAgaWYgKHRoaXNTdGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpc1N0YXJ0ID0gMFxuICB9XG4gIGlmICh0aGlzRW5kID09PSB1bmRlZmluZWQpIHtcbiAgICB0aGlzRW5kID0gdGhpcy5sZW5ndGhcbiAgfVxuXG4gIGlmIChzdGFydCA8IDAgfHwgZW5kID4gdGFyZ2V0Lmxlbmd0aCB8fCB0aGlzU3RhcnQgPCAwIHx8IHRoaXNFbmQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdvdXQgb2YgcmFuZ2UgaW5kZXgnKVxuICB9XG5cbiAgaWYgKHRoaXNTdGFydCA+PSB0aGlzRW5kICYmIHN0YXJ0ID49IGVuZCkge1xuICAgIHJldHVybiAwXG4gIH1cbiAgaWYgKHRoaXNTdGFydCA+PSB0aGlzRW5kKSB7XG4gICAgcmV0dXJuIC0xXG4gIH1cbiAgaWYgKHN0YXJ0ID49IGVuZCkge1xuICAgIHJldHVybiAxXG4gIH1cblxuICBzdGFydCA+Pj49IDBcbiAgZW5kID4+Pj0gMFxuICB0aGlzU3RhcnQgPj4+PSAwXG4gIHRoaXNFbmQgPj4+PSAwXG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCkgcmV0dXJuIDBcblxuICB2YXIgeCA9IHRoaXNFbmQgLSB0aGlzU3RhcnRcbiAgdmFyIHkgPSBlbmQgLSBzdGFydFxuICB2YXIgbGVuID0gTWF0aC5taW4oeCwgeSlcblxuICB2YXIgdGhpc0NvcHkgPSB0aGlzLnNsaWNlKHRoaXNTdGFydCwgdGhpc0VuZClcbiAgdmFyIHRhcmdldENvcHkgPSB0YXJnZXQuc2xpY2Uoc3RhcnQsIGVuZClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKHRoaXNDb3B5W2ldICE9PSB0YXJnZXRDb3B5W2ldKSB7XG4gICAgICB4ID0gdGhpc0NvcHlbaV1cbiAgICAgIHkgPSB0YXJnZXRDb3B5W2ldXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuLy8gRmluZHMgZWl0aGVyIHRoZSBmaXJzdCBpbmRleCBvZiBgdmFsYCBpbiBgYnVmZmVyYCBhdCBvZmZzZXQgPj0gYGJ5dGVPZmZzZXRgLFxuLy8gT1IgdGhlIGxhc3QgaW5kZXggb2YgYHZhbGAgaW4gYGJ1ZmZlcmAgYXQgb2Zmc2V0IDw9IGBieXRlT2Zmc2V0YC5cbi8vXG4vLyBBcmd1bWVudHM6XG4vLyAtIGJ1ZmZlciAtIGEgQnVmZmVyIHRvIHNlYXJjaFxuLy8gLSB2YWwgLSBhIHN0cmluZywgQnVmZmVyLCBvciBudW1iZXJcbi8vIC0gYnl0ZU9mZnNldCAtIGFuIGluZGV4IGludG8gYGJ1ZmZlcmA7IHdpbGwgYmUgY2xhbXBlZCB0byBhbiBpbnQzMlxuLy8gLSBlbmNvZGluZyAtIGFuIG9wdGlvbmFsIGVuY29kaW5nLCByZWxldmFudCBpcyB2YWwgaXMgYSBzdHJpbmdcbi8vIC0gZGlyIC0gdHJ1ZSBmb3IgaW5kZXhPZiwgZmFsc2UgZm9yIGxhc3RJbmRleE9mXG5mdW5jdGlvbiBiaWRpcmVjdGlvbmFsSW5kZXhPZiAoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpIHtcbiAgLy8gRW1wdHkgYnVmZmVyIG1lYW5zIG5vIG1hdGNoXG4gIGlmIChidWZmZXIubGVuZ3RoID09PSAwKSByZXR1cm4gLTFcblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldFxuICBpZiAodHlwZW9mIGJ5dGVPZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBieXRlT2Zmc2V0XG4gICAgYnl0ZU9mZnNldCA9IDBcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0ID4gMHg3ZmZmZmZmZikge1xuICAgIGJ5dGVPZmZzZXQgPSAweDdmZmZmZmZmXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA8IC0weDgwMDAwMDAwKSB7XG4gICAgYnl0ZU9mZnNldCA9IC0weDgwMDAwMDAwXG4gIH1cbiAgYnl0ZU9mZnNldCA9ICtieXRlT2Zmc2V0IC8vIENvZXJjZSB0byBOdW1iZXIuXG4gIGlmIChudW1iZXJJc05hTihieXRlT2Zmc2V0KSkge1xuICAgIC8vIGJ5dGVPZmZzZXQ6IGl0IGl0J3MgdW5kZWZpbmVkLCBudWxsLCBOYU4sIFwiZm9vXCIsIGV0Yywgc2VhcmNoIHdob2xlIGJ1ZmZlclxuICAgIGJ5dGVPZmZzZXQgPSBkaXIgPyAwIDogKGJ1ZmZlci5sZW5ndGggLSAxKVxuICB9XG5cbiAgLy8gTm9ybWFsaXplIGJ5dGVPZmZzZXQ6IG5lZ2F0aXZlIG9mZnNldHMgc3RhcnQgZnJvbSB0aGUgZW5kIG9mIHRoZSBidWZmZXJcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwKSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCArIGJ5dGVPZmZzZXRcbiAgaWYgKGJ5dGVPZmZzZXQgPj0gYnVmZmVyLmxlbmd0aCkge1xuICAgIGlmIChkaXIpIHJldHVybiAtMVxuICAgIGVsc2UgYnl0ZU9mZnNldCA9IGJ1ZmZlci5sZW5ndGggLSAxXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA8IDApIHtcbiAgICBpZiAoZGlyKSBieXRlT2Zmc2V0ID0gMFxuICAgIGVsc2UgcmV0dXJuIC0xXG4gIH1cblxuICAvLyBOb3JtYWxpemUgdmFsXG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIHZhbCA9IEJ1ZmZlci5mcm9tKHZhbCwgZW5jb2RpbmcpXG4gIH1cblxuICAvLyBGaW5hbGx5LCBzZWFyY2ggZWl0aGVyIGluZGV4T2YgKGlmIGRpciBpcyB0cnVlKSBvciBsYXN0SW5kZXhPZlxuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbCkpIHtcbiAgICAvLyBTcGVjaWFsIGNhc2U6IGxvb2tpbmcgZm9yIGVtcHR5IHN0cmluZy9idWZmZXIgYWx3YXlzIGZhaWxzXG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAtMVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMHhGRiAvLyBTZWFyY2ggZm9yIGEgYnl0ZSB2YWx1ZSBbMC0yNTVdXG4gICAgaWYgKHR5cGVvZiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBpZiAoZGlyKSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUubGFzdEluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZihidWZmZXIsIFsgdmFsIF0sIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG5mdW5jdGlvbiBhcnJheUluZGV4T2YgKGFyciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIHZhciBpbmRleFNpemUgPSAxXG4gIHZhciBhcnJMZW5ndGggPSBhcnIubGVuZ3RoXG4gIHZhciB2YWxMZW5ndGggPSB2YWwubGVuZ3RoXG5cbiAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgIGlmIChlbmNvZGluZyA9PT0gJ3VjczInIHx8IGVuY29kaW5nID09PSAndWNzLTInIHx8XG4gICAgICAgIGVuY29kaW5nID09PSAndXRmMTZsZScgfHwgZW5jb2RpbmcgPT09ICd1dGYtMTZsZScpIHtcbiAgICAgIGlmIChhcnIubGVuZ3RoIDwgMiB8fCB2YWwubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH1cbiAgICAgIGluZGV4U2l6ZSA9IDJcbiAgICAgIGFyckxlbmd0aCAvPSAyXG4gICAgICB2YWxMZW5ndGggLz0gMlxuICAgICAgYnl0ZU9mZnNldCAvPSAyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZCAoYnVmLCBpKSB7XG4gICAgaWYgKGluZGV4U2l6ZSA9PT0gMSkge1xuICAgICAgcmV0dXJuIGJ1ZltpXVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYnVmLnJlYWRVSW50MTZCRShpICogaW5kZXhTaXplKVxuICAgIH1cbiAgfVxuXG4gIHZhciBpXG4gIGlmIChkaXIpIHtcbiAgICB2YXIgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA8IGFyckxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocmVhZChhcnIsIGkpID09PSByZWFkKHZhbCwgZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXgpKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsTGVuZ3RoKSByZXR1cm4gZm91bmRJbmRleCAqIGluZGV4U2l6ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggIT09IC0xKSBpIC09IGkgLSBmb3VuZEluZGV4XG4gICAgICAgIGZvdW5kSW5kZXggPSAtMVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoYnl0ZU9mZnNldCArIHZhbExlbmd0aCA+IGFyckxlbmd0aCkgYnl0ZU9mZnNldCA9IGFyckxlbmd0aCAtIHZhbExlbmd0aFxuICAgIGZvciAoaSA9IGJ5dGVPZmZzZXQ7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2YXIgZm91bmQgPSB0cnVlXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHZhbExlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChyZWFkKGFyciwgaSArIGopICE9PSByZWFkKHZhbCwgaikpIHtcbiAgICAgICAgICBmb3VuZCA9IGZhbHNlXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kKSByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluY2x1ZGVzID0gZnVuY3Rpb24gaW5jbHVkZXMgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIHRoaXMuaW5kZXhPZih2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSAhPT0gLTFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZiAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gYmlkaXJlY3Rpb25hbEluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgdHJ1ZSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5sYXN0SW5kZXhPZiA9IGZ1bmN0aW9uIGxhc3RJbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBmYWxzZSlcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGlmIChudW1iZXJJc05hTihwYXJzZWQpKSByZXR1cm4gaVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gbGF0aW4xV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCA+Pj4gMFxuICAgICAgaWYgKGVuY29kaW5nID09PSB1bmRlZmluZWQpIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0J1ZmZlci53cml0ZShzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXRbLCBsZW5ndGhdKSBpcyBubyBsb25nZXIgc3VwcG9ydGVkJ1xuICAgIClcbiAgfVxuXG4gIHZhciByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxhdGluMVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgdmFyIHJlcyA9IFtdXG5cbiAgdmFyIGkgPSBzdGFydFxuICB3aGlsZSAoaSA8IGVuZCkge1xuICAgIHZhciBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICB2YXIgY29kZVBvaW50ID0gbnVsbFxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpID8gNFxuICAgICAgOiAoZmlyc3RCeXRlID4gMHhERikgPyAzXG4gICAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpID8gMlxuICAgICAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgdmFyIHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxudmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICB2YXIgbGVuID0gY29kZVBvaW50cy5sZW5ndGhcbiAgaWYgKGxlbiA8PSBNQVhfQVJHVU1FTlRTX0xFTkdUSCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY29kZVBvaW50cykgLy8gYXZvaWQgZXh0cmEgc2xpY2UoKVxuICB9XG5cbiAgLy8gRGVjb2RlIGluIGNodW5rcyB0byBhdm9pZCBcImNhbGwgc3RhY2sgc2l6ZSBleGNlZWRlZFwiLlxuICB2YXIgcmVzID0gJydcbiAgdmFyIGkgPSAwXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXG4gICAgICBTdHJpbmcsXG4gICAgICBjb2RlUG9pbnRzLnNsaWNlKGksIGkgKz0gTUFYX0FSR1VNRU5UU19MRU5HVEgpXG4gICAgKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0gJiAweDdGKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gbGF0aW4xU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIChieXRlc1tpICsgMV0gKiAyNTYpKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWYgPSB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpXG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIG5ld0J1Zi5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIHJldHVybiBuZXdCdWZcbn1cblxuLypcbiAqIE5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgYnVmZmVyIGlzbid0IHRyeWluZyB0byB3cml0ZSBvdXQgb2YgYm91bmRzLlxuICovXG5mdW5jdGlvbiBjaGVja09mZnNldCAob2Zmc2V0LCBleHQsIGxlbmd0aCkge1xuICBpZiAoKG9mZnNldCAlIDEpICE9PSAwIHx8IG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdvZmZzZXQgaXMgbm90IHVpbnQnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gbGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgdmFyIG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIHJlYWRJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkUgPSBmdW5jdGlvbiByZWFkSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoXG4gIHZhciBtdWwgPSAxXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0taV1cbiAgd2hpbGUgKGkgPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1pXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiByZWFkSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgaWYgKCEodGhpc1tvZmZzZXRdICYgMHg4MCkpIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdExFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiByZWFkRmxvYXRCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiByZWFkRG91YmxlTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiByZWFkRG91YmxlQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgNTIsIDgpXG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJidWZmZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFID0gZnVuY3Rpb24gd3JpdGVVSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIG1heEJ5dGVzID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpIC0gMVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG1heEJ5dGVzLCAwKVxuICB9XG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVVSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4ZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgKDggKiBieXRlTGVuZ3RoKSAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICBpZiAodmFsdWUgPCAwICYmIHN1YiA9PT0gMCAmJiB0aGlzW29mZnNldCArIGkgLSAxXSAhPT0gMCkge1xuICAgICAgc3ViID0gMVxuICAgIH1cbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiB3cml0ZUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBsaW1pdCA9IE1hdGgucG93KDIsICg4ICogYnl0ZUxlbmd0aCkgLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpICsgMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweDdmLCAtMHg4MClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuZnVuY3Rpb24gd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDgsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG4gIHJldHVybiBvZmZzZXQgKyA4XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUJFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gY29weSAodGFyZ2V0LCB0YXJnZXRTdGFydCwgc3RhcnQsIGVuZCkge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0YXJnZXQpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdhcmd1bWVudCBzaG91bGQgYmUgYSBCdWZmZXInKVxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0U3RhcnQgPj0gdGFyZ2V0Lmxlbmd0aCkgdGFyZ2V0U3RhcnQgPSB0YXJnZXQubGVuZ3RoXG4gIGlmICghdGFyZ2V0U3RhcnQpIHRhcmdldFN0YXJ0ID0gMFxuICBpZiAoZW5kID4gMCAmJiBlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVybiAwXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldFN0YXJ0IDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgfVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0IDwgZW5kIC0gc3RhcnQpIHtcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgKyBzdGFydFxuICB9XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiB0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIFVzZSBidWlsdC1pbiB3aGVuIGF2YWlsYWJsZSwgbWlzc2luZyBmcm9tIElFMTFcbiAgICB0aGlzLmNvcHlXaXRoaW4odGFyZ2V0U3RhcnQsIHN0YXJ0LCBlbmQpXG4gIH0gZWxzZSBpZiAodGhpcyA9PT0gdGFyZ2V0ICYmIHN0YXJ0IDwgdGFyZ2V0U3RhcnQgJiYgdGFyZ2V0U3RhcnQgPCBlbmQpIHtcbiAgICAvLyBkZXNjZW5kaW5nIGNvcHkgZnJvbSBlbmRcbiAgICBmb3IgKHZhciBpID0gbGVuIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgdGFyZ2V0LFxuICAgICAgdGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSxcbiAgICAgIHRhcmdldFN0YXJ0XG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBVc2FnZTpcbi8vICAgIGJ1ZmZlci5maWxsKG51bWJlclssIG9mZnNldFssIGVuZF1dKVxuLy8gICAgYnVmZmVyLmZpbGwoYnVmZmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChzdHJpbmdbLCBvZmZzZXRbLCBlbmRdXVssIGVuY29kaW5nXSlcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbCwgc3RhcnQsIGVuZCwgZW5jb2RpbmcpIHtcbiAgLy8gSGFuZGxlIHN0cmluZyBjYXNlczpcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHR5cGVvZiBzdGFydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gc3RhcnRcbiAgICAgIHN0YXJ0ID0gMFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbmQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IGVuZFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9XG4gICAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5jb2RpbmcgbXVzdCBiZSBhIHN0cmluZycpXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnICYmICFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICB9XG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDEpIHtcbiAgICAgIHZhciBjb2RlID0gdmFsLmNoYXJDb2RlQXQoMClcbiAgICAgIGlmICgoZW5jb2RpbmcgPT09ICd1dGY4JyAmJiBjb2RlIDwgMTI4KSB8fFxuICAgICAgICAgIGVuY29kaW5nID09PSAnbGF0aW4xJykge1xuICAgICAgICAvLyBGYXN0IHBhdGg6IElmIGB2YWxgIGZpdHMgaW50byBhIHNpbmdsZSBieXRlLCB1c2UgdGhhdCBudW1lcmljIHZhbHVlLlxuICAgICAgICB2YWwgPSBjb2RlXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMjU1XG4gIH1cblxuICAvLyBJbnZhbGlkIHJhbmdlcyBhcmUgbm90IHNldCB0byBhIGRlZmF1bHQsIHNvIGNhbiByYW5nZSBjaGVjayBlYXJseS5cbiAgaWYgKHN0YXJ0IDwgMCB8fCB0aGlzLmxlbmd0aCA8IHN0YXJ0IHx8IHRoaXMubGVuZ3RoIDwgZW5kKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghdmFsKSB2YWwgPSAwXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgdGhpc1tpXSA9IHZhbFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgaWYgKGxlbiA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIHZhbHVlIFwiJyArIHZhbCArXG4gICAgICAgICdcIiBpcyBpbnZhbGlkIGZvciBhcmd1bWVudCBcInZhbHVlXCInKVxuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgZW5kIC0gc3RhcnQ7ICsraSkge1xuICAgICAgdGhpc1tpICsgc3RhcnRdID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbnZhciBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXisvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHRha2VzIGVxdWFsIHNpZ25zIGFzIGVuZCBvZiB0aGUgQmFzZTY0IGVuY29kaW5nXG4gIHN0ciA9IHN0ci5zcGxpdCgnPScpWzBdXG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHIudHJpbSgpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBjb2RlUG9pbnQgPSBzdHJpbmcuY2hhckNvZGVBdChpKVxuXG4gICAgLy8gaXMgc3Vycm9nYXRlIGNvbXBvbmVudFxuICAgIGlmIChjb2RlUG9pbnQgPiAweEQ3RkYgJiYgY29kZVBvaW50IDwgMHhFMDAwKSB7XG4gICAgICAvLyBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCFsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIG5vIGxlYWQgeWV0XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBsZWFkXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyAyIGxlYWRzIGluIGEgcm93XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBjb2RlUG9pbnQgPSAobGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCkgKyAweDEwMDAwXG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICB9XG5cbiAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpIGJyZWFrXG4gICAgZHN0W2kgKyBvZmZzZXRdID0gc3JjW2ldXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuLy8gQXJyYXlCdWZmZXIgb3IgVWludDhBcnJheSBvYmplY3RzIGZyb20gb3RoZXIgY29udGV4dHMgKGkuZS4gaWZyYW1lcykgZG8gbm90IHBhc3Ncbi8vIHRoZSBgaW5zdGFuY2VvZmAgY2hlY2sgYnV0IHRoZXkgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgb2YgdGhhdCB0eXBlLlxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9pc3N1ZXMvMTY2XG5mdW5jdGlvbiBpc0luc3RhbmNlIChvYmosIHR5cGUpIHtcbiAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIHR5cGUgfHxcbiAgICAob2JqICE9IG51bGwgJiYgb2JqLmNvbnN0cnVjdG9yICE9IG51bGwgJiYgb2JqLmNvbnN0cnVjdG9yLm5hbWUgIT0gbnVsbCAmJlxuICAgICAgb2JqLmNvbnN0cnVjdG9yLm5hbWUgPT09IHR5cGUubmFtZSlcbn1cbmZ1bmN0aW9uIG51bWJlcklzTmFOIChvYmopIHtcbiAgLy8gRm9yIElFMTEgc3VwcG9ydFxuICByZXR1cm4gb2JqICE9PSBvYmogLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zZWxmLWNvbXBhcmVcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgbW9ub3RvbmVUcmlhbmd1bGF0ZSA9IHJlcXVpcmUoJy4vbGliL21vbm90b25lJylcbnZhciBtYWtlSW5kZXggPSByZXF1aXJlKCcuL2xpYi90cmlhbmd1bGF0aW9uJylcbnZhciBkZWxhdW5heUZsaXAgPSByZXF1aXJlKCcuL2xpYi9kZWxhdW5heScpXG52YXIgZmlsdGVyVHJpYW5ndWxhdGlvbiA9IHJlcXVpcmUoJy4vbGliL2ZpbHRlcicpXG5cbm1vZHVsZS5leHBvcnRzID0gY2R0MmRcblxuZnVuY3Rpb24gY2Fub25pY2FsaXplRWRnZShlKSB7XG4gIHJldHVybiBbTWF0aC5taW4oZVswXSwgZVsxXSksIE1hdGgubWF4KGVbMF0sIGVbMV0pXVxufVxuXG5mdW5jdGlvbiBjb21wYXJlRWRnZShhLCBiKSB7XG4gIHJldHVybiBhWzBdLWJbMF0gfHwgYVsxXS1iWzFdXG59XG5cbmZ1bmN0aW9uIGNhbm9uaWNhbGl6ZUVkZ2VzKGVkZ2VzKSB7XG4gIHJldHVybiBlZGdlcy5tYXAoY2Fub25pY2FsaXplRWRnZSkuc29ydChjb21wYXJlRWRnZSlcbn1cblxuZnVuY3Rpb24gZ2V0RGVmYXVsdChvcHRpb25zLCBwcm9wZXJ0eSwgZGZsdCkge1xuICBpZihwcm9wZXJ0eSBpbiBvcHRpb25zKSB7XG4gICAgcmV0dXJuIG9wdGlvbnNbcHJvcGVydHldXG4gIH1cbiAgcmV0dXJuIGRmbHRcbn1cblxuZnVuY3Rpb24gY2R0MmQocG9pbnRzLCBlZGdlcywgb3B0aW9ucykge1xuXG4gIGlmKCFBcnJheS5pc0FycmF5KGVkZ2VzKSkge1xuICAgIG9wdGlvbnMgPSBlZGdlcyB8fCB7fVxuICAgIGVkZ2VzID0gW11cbiAgfSBlbHNlIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgIGVkZ2VzID0gZWRnZXMgfHwgW11cbiAgfVxuXG4gIC8vUGFyc2Ugb3V0IG9wdGlvbnNcbiAgdmFyIGRlbGF1bmF5ID0gISFnZXREZWZhdWx0KG9wdGlvbnMsICdkZWxhdW5heScsIHRydWUpXG4gIHZhciBpbnRlcmlvciA9ICEhZ2V0RGVmYXVsdChvcHRpb25zLCAnaW50ZXJpb3InLCB0cnVlKVxuICB2YXIgZXh0ZXJpb3IgPSAhIWdldERlZmF1bHQob3B0aW9ucywgJ2V4dGVyaW9yJywgdHJ1ZSlcbiAgdmFyIGluZmluaXR5ID0gISFnZXREZWZhdWx0KG9wdGlvbnMsICdpbmZpbml0eScsIGZhbHNlKVxuXG4gIC8vSGFuZGxlIHRyaXZpYWwgY2FzZVxuICBpZigoIWludGVyaW9yICYmICFleHRlcmlvcikgfHwgcG9pbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG5cbiAgLy9Db25zdHJ1Y3QgaW5pdGlhbCB0cmlhbmd1bGF0aW9uXG4gIHZhciBjZWxscyA9IG1vbm90b25lVHJpYW5ndWxhdGUocG9pbnRzLCBlZGdlcylcblxuICAvL0lmIGRlbGF1bmF5IHJlZmluZW1lbnQgbmVlZGVkLCB0aGVuIGltcHJvdmUgcXVhbGl0eSBieSBlZGdlIGZsaXBwaW5nXG4gIGlmKGRlbGF1bmF5IHx8IGludGVyaW9yICE9PSBleHRlcmlvciB8fCBpbmZpbml0eSkge1xuXG4gICAgLy9JbmRleCBhbGwgb2YgdGhlIGNlbGxzIHRvIHN1cHBvcnQgZmFzdCBuZWlnaGJvcmhvb2QgcXVlcmllc1xuICAgIHZhciB0cmlhbmd1bGF0aW9uID0gbWFrZUluZGV4KHBvaW50cy5sZW5ndGgsIGNhbm9uaWNhbGl6ZUVkZ2VzKGVkZ2VzKSlcbiAgICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGYgPSBjZWxsc1tpXVxuICAgICAgdHJpYW5ndWxhdGlvbi5hZGRUcmlhbmdsZShmWzBdLCBmWzFdLCBmWzJdKVxuICAgIH1cblxuICAgIC8vUnVuIGVkZ2UgZmxpcHBpbmdcbiAgICBpZihkZWxhdW5heSkge1xuICAgICAgZGVsYXVuYXlGbGlwKHBvaW50cywgdHJpYW5ndWxhdGlvbilcbiAgICB9XG5cbiAgICAvL0ZpbHRlciBwb2ludHNcbiAgICBpZighZXh0ZXJpb3IpIHtcbiAgICAgIHJldHVybiBmaWx0ZXJUcmlhbmd1bGF0aW9uKHRyaWFuZ3VsYXRpb24sIC0xKVxuICAgIH0gZWxzZSBpZighaW50ZXJpb3IpIHtcbiAgICAgIHJldHVybiBmaWx0ZXJUcmlhbmd1bGF0aW9uKHRyaWFuZ3VsYXRpb24sICAxLCBpbmZpbml0eSlcbiAgICB9IGVsc2UgaWYoaW5maW5pdHkpIHtcbiAgICAgIHJldHVybiBmaWx0ZXJUcmlhbmd1bGF0aW9uKHRyaWFuZ3VsYXRpb24sIDAsIGluZmluaXR5KVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHJpYW5ndWxhdGlvbi5jZWxscygpXG4gICAgfVxuICAgIFxuICB9IGVsc2Uge1xuICAgIHJldHVybiBjZWxsc1xuICB9XG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIGluQ2lyY2xlID0gcmVxdWlyZSgncm9idXN0LWluLXNwaGVyZScpWzRdXG52YXIgYnNlYXJjaCA9IHJlcXVpcmUoJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcblxubW9kdWxlLmV4cG9ydHMgPSBkZWxhdW5heVJlZmluZVxuXG5mdW5jdGlvbiB0ZXN0RmxpcChwb2ludHMsIHRyaWFuZ3VsYXRpb24sIHN0YWNrLCBhLCBiLCB4KSB7XG4gIHZhciB5ID0gdHJpYW5ndWxhdGlvbi5vcHBvc2l0ZShhLCBiKVxuXG4gIC8vVGVzdCBib3VuZGFyeSBlZGdlXG4gIGlmKHkgPCAwKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvL1N3YXAgZWRnZSBpZiBvcmRlciBmbGlwcGVkXG4gIGlmKGIgPCBhKSB7XG4gICAgdmFyIHRtcCA9IGFcbiAgICBhID0gYlxuICAgIGIgPSB0bXBcbiAgICB0bXAgPSB4XG4gICAgeCA9IHlcbiAgICB5ID0gdG1wXG4gIH1cblxuICAvL1Rlc3QgaWYgZWRnZSBpcyBjb25zdHJhaW5lZFxuICBpZih0cmlhbmd1bGF0aW9uLmlzQ29uc3RyYWludChhLCBiKSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgLy9UZXN0IGlmIGVkZ2UgaXMgZGVsYXVuYXlcbiAgaWYoaW5DaXJjbGUocG9pbnRzW2FdLCBwb2ludHNbYl0sIHBvaW50c1t4XSwgcG9pbnRzW3ldKSA8IDApIHtcbiAgICBzdGFjay5wdXNoKGEsIGIpXG4gIH1cbn1cblxuLy9Bc3N1bWUgZWRnZXMgYXJlIHNvcnRlZCBsZXhpY29ncmFwaGljYWxseVxuZnVuY3Rpb24gZGVsYXVuYXlSZWZpbmUocG9pbnRzLCB0cmlhbmd1bGF0aW9uKSB7XG4gIHZhciBzdGFjayA9IFtdXG5cbiAgdmFyIG51bVBvaW50cyA9IHBvaW50cy5sZW5ndGhcbiAgdmFyIHN0YXJzID0gdHJpYW5ndWxhdGlvbi5zdGFyc1xuICBmb3IodmFyIGE9MDsgYTxudW1Qb2ludHM7ICsrYSkge1xuICAgIHZhciBzdGFyID0gc3RhcnNbYV1cbiAgICBmb3IodmFyIGo9MTsgajxzdGFyLmxlbmd0aDsgais9Mikge1xuICAgICAgdmFyIGIgPSBzdGFyW2pdXG5cbiAgICAgIC8vSWYgb3JkZXIgaXMgbm90IGNvbnNpc3RlbnQsIHRoZW4gc2tpcCBlZGdlXG4gICAgICBpZihiIDwgYSkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvL0NoZWNrIGlmIGVkZ2UgaXMgY29uc3RyYWluZWRcbiAgICAgIGlmKHRyaWFuZ3VsYXRpb24uaXNDb25zdHJhaW50KGEsIGIpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vRmluZCBvcHBvc2l0ZSBlZGdlXG4gICAgICB2YXIgeCA9IHN0YXJbai0xXSwgeSA9IC0xXG4gICAgICBmb3IodmFyIGs9MTsgazxzdGFyLmxlbmd0aDsgays9Mikge1xuICAgICAgICBpZihzdGFyW2stMV0gPT09IGIpIHtcbiAgICAgICAgICB5ID0gc3RhcltrXVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy9JZiB0aGlzIGlzIGEgYm91bmRhcnkgZWRnZSwgZG9uJ3QgZmxpcCBpdFxuICAgICAgaWYoeSA8IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy9JZiBlZGdlIGlzIGluIGNpcmNsZSwgZmxpcCBpdFxuICAgICAgaWYoaW5DaXJjbGUocG9pbnRzW2FdLCBwb2ludHNbYl0sIHBvaW50c1t4XSwgcG9pbnRzW3ldKSA8IDApIHtcbiAgICAgICAgc3RhY2sucHVzaChhLCBiKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHdoaWxlKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICB2YXIgYiA9IHN0YWNrLnBvcCgpXG4gICAgdmFyIGEgPSBzdGFjay5wb3AoKVxuXG4gICAgLy9GaW5kIG9wcG9zaXRlIHBhaXJzXG4gICAgdmFyIHggPSAtMSwgeSA9IC0xXG4gICAgdmFyIHN0YXIgPSBzdGFyc1thXVxuICAgIGZvcih2YXIgaT0xOyBpPHN0YXIubGVuZ3RoOyBpKz0yKSB7XG4gICAgICB2YXIgcyA9IHN0YXJbaS0xXVxuICAgICAgdmFyIHQgPSBzdGFyW2ldXG4gICAgICBpZihzID09PSBiKSB7XG4gICAgICAgIHkgPSB0XG4gICAgICB9IGVsc2UgaWYodCA9PT0gYikge1xuICAgICAgICB4ID0gc1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vSWYgeC95IGFyZSBib3RoIHZhbGlkIHRoZW4gc2tpcCBlZGdlXG4gICAgaWYoeCA8IDAgfHwgeSA8IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy9JZiBlZGdlIGlzIG5vdyBkZWxhdW5heSwgdGhlbiBkb24ndCBmbGlwIGl0XG4gICAgaWYoaW5DaXJjbGUocG9pbnRzW2FdLCBwb2ludHNbYl0sIHBvaW50c1t4XSwgcG9pbnRzW3ldKSA+PSAwKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIC8vRmxpcCB0aGUgZWRnZVxuICAgIHRyaWFuZ3VsYXRpb24uZmxpcChhLCBiKVxuXG4gICAgLy9UZXN0IGZsaXBwaW5nIG5laWdoYm9yaW5nIGVkZ2VzXG4gICAgdGVzdEZsaXAocG9pbnRzLCB0cmlhbmd1bGF0aW9uLCBzdGFjaywgeCwgYSwgeSlcbiAgICB0ZXN0RmxpcChwb2ludHMsIHRyaWFuZ3VsYXRpb24sIHN0YWNrLCBhLCB5LCB4KVxuICAgIHRlc3RGbGlwKHBvaW50cywgdHJpYW5ndWxhdGlvbiwgc3RhY2ssIHksIGIsIHgpXG4gICAgdGVzdEZsaXAocG9pbnRzLCB0cmlhbmd1bGF0aW9uLCBzdGFjaywgYiwgeCwgeSlcbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBic2VhcmNoID0gcmVxdWlyZSgnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzaWZ5RmFjZXNcblxuZnVuY3Rpb24gRmFjZUluZGV4KGNlbGxzLCBuZWlnaGJvciwgY29uc3RyYWludCwgZmxhZ3MsIGFjdGl2ZSwgbmV4dCwgYm91bmRhcnkpIHtcbiAgdGhpcy5jZWxscyAgICAgICA9IGNlbGxzXG4gIHRoaXMubmVpZ2hib3IgICAgPSBuZWlnaGJvclxuICB0aGlzLmZsYWdzICAgICAgID0gZmxhZ3NcbiAgdGhpcy5jb25zdHJhaW50ICA9IGNvbnN0cmFpbnRcbiAgdGhpcy5hY3RpdmUgICAgICA9IGFjdGl2ZVxuICB0aGlzLm5leHQgICAgICAgID0gbmV4dFxuICB0aGlzLmJvdW5kYXJ5ICAgID0gYm91bmRhcnlcbn1cblxudmFyIHByb3RvID0gRmFjZUluZGV4LnByb3RvdHlwZVxuXG5mdW5jdGlvbiBjb21wYXJlQ2VsbChhLCBiKSB7XG4gIHJldHVybiBhWzBdIC0gYlswXSB8fFxuICAgICAgICAgYVsxXSAtIGJbMV0gfHxcbiAgICAgICAgIGFbMl0gLSBiWzJdXG59XG5cbnByb3RvLmxvY2F0ZSA9IChmdW5jdGlvbigpIHtcbiAgdmFyIGtleSA9IFswLDAsMF1cbiAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICB2YXIgeCA9IGEsIHkgPSBiLCB6ID0gY1xuICAgIGlmKGIgPCBjKSB7XG4gICAgICBpZihiIDwgYSkge1xuICAgICAgICB4ID0gYlxuICAgICAgICB5ID0gY1xuICAgICAgICB6ID0gYVxuICAgICAgfVxuICAgIH0gZWxzZSBpZihjIDwgYSkge1xuICAgICAgeCA9IGNcbiAgICAgIHkgPSBhXG4gICAgICB6ID0gYlxuICAgIH1cbiAgICBpZih4IDwgMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIGtleVswXSA9IHhcbiAgICBrZXlbMV0gPSB5XG4gICAga2V5WzJdID0gelxuICAgIHJldHVybiBic2VhcmNoLmVxKHRoaXMuY2VsbHMsIGtleSwgY29tcGFyZUNlbGwpXG4gIH1cbn0pKClcblxuZnVuY3Rpb24gaW5kZXhDZWxscyh0cmlhbmd1bGF0aW9uLCBpbmZpbml0eSkge1xuICAvL0ZpcnN0IGdldCBjZWxscyBhbmQgY2Fub25pY2FsaXplXG4gIHZhciBjZWxscyA9IHRyaWFuZ3VsYXRpb24uY2VsbHMoKVxuICB2YXIgbmMgPSBjZWxscy5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bmM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICB2YXIgeCA9IGNbMF0sIHkgPSBjWzFdLCB6ID0gY1syXVxuICAgIGlmKHkgPCB6KSB7XG4gICAgICBpZih5IDwgeCkge1xuICAgICAgICBjWzBdID0geVxuICAgICAgICBjWzFdID0gelxuICAgICAgICBjWzJdID0geFxuICAgICAgfVxuICAgIH0gZWxzZSBpZih6IDwgeCkge1xuICAgICAgY1swXSA9IHpcbiAgICAgIGNbMV0gPSB4XG4gICAgICBjWzJdID0geVxuICAgIH1cbiAgfVxuICBjZWxscy5zb3J0KGNvbXBhcmVDZWxsKVxuXG4gIC8vSW5pdGlhbGl6ZSBmbGFnIGFycmF5XG4gIHZhciBmbGFncyA9IG5ldyBBcnJheShuYylcbiAgZm9yKHZhciBpPTA7IGk8ZmxhZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBmbGFnc1tpXSA9IDBcbiAgfVxuXG4gIC8vQnVpbGQgbmVpZ2hib3IgaW5kZXgsIGluaXRpYWxpemUgcXVldWVzXG4gIHZhciBhY3RpdmUgPSBbXVxuICB2YXIgbmV4dCAgID0gW11cbiAgdmFyIG5laWdoYm9yID0gbmV3IEFycmF5KDMqbmMpXG4gIHZhciBjb25zdHJhaW50ID0gbmV3IEFycmF5KDMqbmMpXG4gIHZhciBib3VuZGFyeSA9IG51bGxcbiAgaWYoaW5maW5pdHkpIHtcbiAgICBib3VuZGFyeSA9IFtdXG4gIH1cbiAgdmFyIGluZGV4ID0gbmV3IEZhY2VJbmRleChcbiAgICBjZWxscyxcbiAgICBuZWlnaGJvcixcbiAgICBjb25zdHJhaW50LFxuICAgIGZsYWdzLFxuICAgIGFjdGl2ZSxcbiAgICBuZXh0LFxuICAgIGJvdW5kYXJ5KVxuICBmb3IodmFyIGk9MDsgaTxuYzsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgdmFyIHggPSBjW2pdLCB5ID0gY1soaisxKSUzXVxuICAgICAgdmFyIGEgPSBuZWlnaGJvclszKmkral0gPSBpbmRleC5sb2NhdGUoeSwgeCwgdHJpYW5ndWxhdGlvbi5vcHBvc2l0ZSh5LCB4KSlcbiAgICAgIHZhciBiID0gY29uc3RyYWludFszKmkral0gPSB0cmlhbmd1bGF0aW9uLmlzQ29uc3RyYWludCh4LCB5KVxuICAgICAgaWYoYSA8IDApIHtcbiAgICAgICAgaWYoYikge1xuICAgICAgICAgIG5leHQucHVzaChpKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFjdGl2ZS5wdXNoKGkpXG4gICAgICAgICAgZmxhZ3NbaV0gPSAxXG4gICAgICAgIH1cbiAgICAgICAgaWYoaW5maW5pdHkpIHtcbiAgICAgICAgICBib3VuZGFyeS5wdXNoKFt5LCB4LCAtMV0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGluZGV4XG59XG5cbmZ1bmN0aW9uIGZpbHRlckNlbGxzKGNlbGxzLCBmbGFncywgdGFyZ2V0KSB7XG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgaWYoZmxhZ3NbaV0gPT09IHRhcmdldCkge1xuICAgICAgY2VsbHNbcHRyKytdID0gY2VsbHNbaV1cbiAgICB9XG4gIH1cbiAgY2VsbHMubGVuZ3RoID0gcHRyXG4gIHJldHVybiBjZWxsc1xufVxuXG5mdW5jdGlvbiBjbGFzc2lmeUZhY2VzKHRyaWFuZ3VsYXRpb24sIHRhcmdldCwgaW5maW5pdHkpIHtcbiAgdmFyIGluZGV4ID0gaW5kZXhDZWxscyh0cmlhbmd1bGF0aW9uLCBpbmZpbml0eSlcblxuICBpZih0YXJnZXQgPT09IDApIHtcbiAgICBpZihpbmZpbml0eSkge1xuICAgICAgcmV0dXJuIGluZGV4LmNlbGxzLmNvbmNhdChpbmRleC5ib3VuZGFyeSlcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGluZGV4LmNlbGxzXG4gICAgfVxuICB9XG5cbiAgdmFyIHNpZGUgPSAxXG4gIHZhciBhY3RpdmUgPSBpbmRleC5hY3RpdmVcbiAgdmFyIG5leHQgPSBpbmRleC5uZXh0XG4gIHZhciBmbGFncyA9IGluZGV4LmZsYWdzXG4gIHZhciBjZWxscyA9IGluZGV4LmNlbGxzXG4gIHZhciBjb25zdHJhaW50ID0gaW5kZXguY29uc3RyYWludFxuICB2YXIgbmVpZ2hib3IgPSBpbmRleC5uZWlnaGJvclxuXG4gIHdoaWxlKGFjdGl2ZS5sZW5ndGggPiAwIHx8IG5leHQubGVuZ3RoID4gMCkge1xuICAgIHdoaWxlKGFjdGl2ZS5sZW5ndGggPiAwKSB7XG4gICAgICB2YXIgdCA9IGFjdGl2ZS5wb3AoKVxuICAgICAgaWYoZmxhZ3NbdF0gPT09IC1zaWRlKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBmbGFnc1t0XSA9IHNpZGVcbiAgICAgIHZhciBjID0gY2VsbHNbdF1cbiAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICB2YXIgZiA9IG5laWdoYm9yWzMqdCtqXVxuICAgICAgICBpZihmID49IDAgJiYgZmxhZ3NbZl0gPT09IDApIHtcbiAgICAgICAgICBpZihjb25zdHJhaW50WzMqdCtqXSkge1xuICAgICAgICAgICAgbmV4dC5wdXNoKGYpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFjdGl2ZS5wdXNoKGYpXG4gICAgICAgICAgICBmbGFnc1tmXSA9IHNpZGVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL1N3YXAgYXJyYXlzIGFuZCBsb29wXG4gICAgdmFyIHRtcCA9IG5leHRcbiAgICBuZXh0ID0gYWN0aXZlXG4gICAgYWN0aXZlID0gdG1wXG4gICAgbmV4dC5sZW5ndGggPSAwXG4gICAgc2lkZSA9IC1zaWRlXG4gIH1cblxuICB2YXIgcmVzdWx0ID0gZmlsdGVyQ2VsbHMoY2VsbHMsIGZsYWdzLCB0YXJnZXQpXG4gIGlmKGluZmluaXR5KSB7XG4gICAgcmV0dXJuIHJlc3VsdC5jb25jYXQoaW5kZXguYm91bmRhcnkpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBic2VhcmNoID0gcmVxdWlyZSgnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxudmFyIG9yaWVudCA9IHJlcXVpcmUoJ3JvYnVzdC1vcmllbnRhdGlvbicpWzNdXG5cbnZhciBFVkVOVF9QT0lOVCA9IDBcbnZhciBFVkVOVF9FTkQgICA9IDFcbnZhciBFVkVOVF9TVEFSVCA9IDJcblxubW9kdWxlLmV4cG9ydHMgPSBtb25vdG9uZVRyaWFuZ3VsYXRlXG5cbi8vQSBwYXJ0aWFsIGNvbnZleCBodWxsIGZyYWdtZW50LCBtYWRlIG9mIHR3byB1bmltb25vdG9uZSBwb2x5Z29uc1xuZnVuY3Rpb24gUGFydGlhbEh1bGwoYSwgYiwgaWR4LCBsb3dlcklkcywgdXBwZXJJZHMpIHtcbiAgdGhpcy5hID0gYVxuICB0aGlzLmIgPSBiXG4gIHRoaXMuaWR4ID0gaWR4XG4gIHRoaXMubG93ZXJJZHMgPSBsb3dlcklkc1xuICB0aGlzLnVwcGVySWRzID0gdXBwZXJJZHNcbn1cblxuLy9BbiBldmVudCBpbiB0aGUgc3dlZXAgbGluZSBwcm9jZWR1cmVcbmZ1bmN0aW9uIEV2ZW50KGEsIGIsIHR5cGUsIGlkeCkge1xuICB0aGlzLmEgICAgPSBhXG4gIHRoaXMuYiAgICA9IGJcbiAgdGhpcy50eXBlID0gdHlwZVxuICB0aGlzLmlkeCAgPSBpZHhcbn1cblxuLy9UaGlzIGlzIHVzZWQgdG8gY29tcGFyZSBldmVudHMgZm9yIHRoZSBzd2VlcCBsaW5lIHByb2NlZHVyZVxuLy8gUG9pbnRzIGFyZTpcbi8vICAxLiBzb3J0ZWQgbGV4aWNvZ3JhcGhpY2FsbHlcbi8vICAyLiBzb3J0ZWQgYnkgdHlwZSAgKHBvaW50IDwgZW5kIDwgc3RhcnQpXG4vLyAgMy4gc2VnbWVudHMgc29ydGVkIGJ5IHdpbmRpbmcgb3JkZXJcbi8vICA0LiBzb3J0ZWQgYnkgaW5kZXhcbmZ1bmN0aW9uIGNvbXBhcmVFdmVudChhLCBiKSB7XG4gIHZhciBkID1cbiAgICAoYS5hWzBdIC0gYi5hWzBdKSB8fFxuICAgIChhLmFbMV0gLSBiLmFbMV0pIHx8XG4gICAgKGEudHlwZSAtIGIudHlwZSlcbiAgaWYoZCkgeyByZXR1cm4gZCB9XG4gIGlmKGEudHlwZSAhPT0gRVZFTlRfUE9JTlQpIHtcbiAgICBkID0gb3JpZW50KGEuYSwgYS5iLCBiLmIpXG4gICAgaWYoZCkgeyByZXR1cm4gZCB9XG4gIH1cbiAgcmV0dXJuIGEuaWR4IC0gYi5pZHhcbn1cblxuZnVuY3Rpb24gdGVzdFBvaW50KGh1bGwsIHApIHtcbiAgcmV0dXJuIG9yaWVudChodWxsLmEsIGh1bGwuYiwgcClcbn1cblxuZnVuY3Rpb24gYWRkUG9pbnQoY2VsbHMsIGh1bGxzLCBwb2ludHMsIHAsIGlkeCkge1xuICB2YXIgbG8gPSBic2VhcmNoLmx0KGh1bGxzLCBwLCB0ZXN0UG9pbnQpXG4gIHZhciBoaSA9IGJzZWFyY2guZ3QoaHVsbHMsIHAsIHRlc3RQb2ludClcbiAgZm9yKHZhciBpPWxvOyBpPGhpOyArK2kpIHtcbiAgICB2YXIgaHVsbCA9IGh1bGxzW2ldXG5cbiAgICAvL0luc2VydCBwIGludG8gbG93ZXIgaHVsbFxuICAgIHZhciBsb3dlcklkcyA9IGh1bGwubG93ZXJJZHNcbiAgICB2YXIgbSA9IGxvd2VySWRzLmxlbmd0aFxuICAgIHdoaWxlKG0gPiAxICYmIG9yaWVudChcbiAgICAgICAgcG9pbnRzW2xvd2VySWRzW20tMl1dLFxuICAgICAgICBwb2ludHNbbG93ZXJJZHNbbS0xXV0sXG4gICAgICAgIHApID4gMCkge1xuICAgICAgY2VsbHMucHVzaChcbiAgICAgICAgW2xvd2VySWRzW20tMV0sXG4gICAgICAgICBsb3dlcklkc1ttLTJdLFxuICAgICAgICAgaWR4XSlcbiAgICAgIG0gLT0gMVxuICAgIH1cbiAgICBsb3dlcklkcy5sZW5ndGggPSBtXG4gICAgbG93ZXJJZHMucHVzaChpZHgpXG5cbiAgICAvL0luc2VydCBwIGludG8gdXBwZXIgaHVsbFxuICAgIHZhciB1cHBlcklkcyA9IGh1bGwudXBwZXJJZHNcbiAgICB2YXIgbSA9IHVwcGVySWRzLmxlbmd0aFxuICAgIHdoaWxlKG0gPiAxICYmIG9yaWVudChcbiAgICAgICAgcG9pbnRzW3VwcGVySWRzW20tMl1dLFxuICAgICAgICBwb2ludHNbdXBwZXJJZHNbbS0xXV0sXG4gICAgICAgIHApIDwgMCkge1xuICAgICAgY2VsbHMucHVzaChcbiAgICAgICAgW3VwcGVySWRzW20tMl0sXG4gICAgICAgICB1cHBlcklkc1ttLTFdLFxuICAgICAgICAgaWR4XSlcbiAgICAgIG0gLT0gMVxuICAgIH1cbiAgICB1cHBlcklkcy5sZW5ndGggPSBtXG4gICAgdXBwZXJJZHMucHVzaChpZHgpXG4gIH1cbn1cblxuZnVuY3Rpb24gZmluZFNwbGl0KGh1bGwsIGVkZ2UpIHtcbiAgdmFyIGRcbiAgaWYoaHVsbC5hWzBdIDwgZWRnZS5hWzBdKSB7XG4gICAgZCA9IG9yaWVudChodWxsLmEsIGh1bGwuYiwgZWRnZS5hKVxuICB9IGVsc2Uge1xuICAgIGQgPSBvcmllbnQoZWRnZS5iLCBlZGdlLmEsIGh1bGwuYSlcbiAgfVxuICBpZihkKSB7IHJldHVybiBkIH1cbiAgaWYoZWRnZS5iWzBdIDwgaHVsbC5iWzBdKSB7XG4gICAgZCA9IG9yaWVudChodWxsLmEsIGh1bGwuYiwgZWRnZS5iKVxuICB9IGVsc2Uge1xuICAgIGQgPSBvcmllbnQoZWRnZS5iLCBlZGdlLmEsIGh1bGwuYilcbiAgfVxuICByZXR1cm4gZCB8fCBodWxsLmlkeCAtIGVkZ2UuaWR4XG59XG5cbmZ1bmN0aW9uIHNwbGl0SHVsbHMoaHVsbHMsIHBvaW50cywgZXZlbnQpIHtcbiAgdmFyIHNwbGl0SWR4ID0gYnNlYXJjaC5sZShodWxscywgZXZlbnQsIGZpbmRTcGxpdClcbiAgdmFyIGh1bGwgPSBodWxsc1tzcGxpdElkeF1cbiAgdmFyIHVwcGVySWRzID0gaHVsbC51cHBlcklkc1xuICB2YXIgeCA9IHVwcGVySWRzW3VwcGVySWRzLmxlbmd0aC0xXVxuICBodWxsLnVwcGVySWRzID0gW3hdXG4gIGh1bGxzLnNwbGljZShzcGxpdElkeCsxLCAwLFxuICAgIG5ldyBQYXJ0aWFsSHVsbChldmVudC5hLCBldmVudC5iLCBldmVudC5pZHgsIFt4XSwgdXBwZXJJZHMpKVxufVxuXG5cbmZ1bmN0aW9uIG1lcmdlSHVsbHMoaHVsbHMsIHBvaW50cywgZXZlbnQpIHtcbiAgLy9Td2FwIHBvaW50ZXJzIGZvciBtZXJnZSBzZWFyY2hcbiAgdmFyIHRtcCA9IGV2ZW50LmFcbiAgZXZlbnQuYSA9IGV2ZW50LmJcbiAgZXZlbnQuYiA9IHRtcFxuICB2YXIgbWVyZ2VJZHggPSBic2VhcmNoLmVxKGh1bGxzLCBldmVudCwgZmluZFNwbGl0KVxuICB2YXIgdXBwZXIgPSBodWxsc1ttZXJnZUlkeF1cbiAgdmFyIGxvd2VyID0gaHVsbHNbbWVyZ2VJZHgtMV1cbiAgbG93ZXIudXBwZXJJZHMgPSB1cHBlci51cHBlcklkc1xuICBodWxscy5zcGxpY2UobWVyZ2VJZHgsIDEpXG59XG5cblxuZnVuY3Rpb24gbW9ub3RvbmVUcmlhbmd1bGF0ZShwb2ludHMsIGVkZ2VzKSB7XG5cbiAgdmFyIG51bVBvaW50cyA9IHBvaW50cy5sZW5ndGhcbiAgdmFyIG51bUVkZ2VzID0gZWRnZXMubGVuZ3RoXG5cbiAgdmFyIGV2ZW50cyA9IFtdXG5cbiAgLy9DcmVhdGUgcG9pbnQgZXZlbnRzXG4gIGZvcih2YXIgaT0wOyBpPG51bVBvaW50czsgKytpKSB7XG4gICAgZXZlbnRzLnB1c2gobmV3IEV2ZW50KFxuICAgICAgcG9pbnRzW2ldLFxuICAgICAgbnVsbCxcbiAgICAgIEVWRU5UX1BPSU5ULFxuICAgICAgaSkpXG4gIH1cblxuICAvL0NyZWF0ZSBlZGdlIGV2ZW50c1xuICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgIHZhciBhID0gcG9pbnRzW2VbMF1dXG4gICAgdmFyIGIgPSBwb2ludHNbZVsxXV1cbiAgICBpZihhWzBdIDwgYlswXSkge1xuICAgICAgZXZlbnRzLnB1c2goXG4gICAgICAgIG5ldyBFdmVudChhLCBiLCBFVkVOVF9TVEFSVCwgaSksXG4gICAgICAgIG5ldyBFdmVudChiLCBhLCBFVkVOVF9FTkQsIGkpKVxuICAgIH0gZWxzZSBpZihhWzBdID4gYlswXSkge1xuICAgICAgZXZlbnRzLnB1c2goXG4gICAgICAgIG5ldyBFdmVudChiLCBhLCBFVkVOVF9TVEFSVCwgaSksXG4gICAgICAgIG5ldyBFdmVudChhLCBiLCBFVkVOVF9FTkQsIGkpKVxuICAgIH1cbiAgfVxuXG4gIC8vU29ydCBldmVudHNcbiAgZXZlbnRzLnNvcnQoY29tcGFyZUV2ZW50KVxuXG4gIC8vSW5pdGlhbGl6ZSBodWxsXG4gIHZhciBtaW5YID0gZXZlbnRzWzBdLmFbMF0gLSAoMSArIE1hdGguYWJzKGV2ZW50c1swXS5hWzBdKSkgKiBNYXRoLnBvdygyLCAtNTIpXG4gIHZhciBodWxsID0gWyBuZXcgUGFydGlhbEh1bGwoW21pblgsIDFdLCBbbWluWCwgMF0sIC0xLCBbXSwgW10sIFtdLCBbXSkgXVxuXG4gIC8vUHJvY2VzcyBldmVudHMgaW4gb3JkZXJcbiAgdmFyIGNlbGxzID0gW11cbiAgZm9yKHZhciBpPTAsIG51bUV2ZW50cz1ldmVudHMubGVuZ3RoOyBpPG51bUV2ZW50czsgKytpKSB7XG4gICAgdmFyIGV2ZW50ID0gZXZlbnRzW2ldXG4gICAgdmFyIHR5cGUgPSBldmVudC50eXBlXG4gICAgaWYodHlwZSA9PT0gRVZFTlRfUE9JTlQpIHtcbiAgICAgIGFkZFBvaW50KGNlbGxzLCBodWxsLCBwb2ludHMsIGV2ZW50LmEsIGV2ZW50LmlkeClcbiAgICB9IGVsc2UgaWYodHlwZSA9PT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgIHNwbGl0SHVsbHMoaHVsbCwgcG9pbnRzLCBldmVudClcbiAgICB9IGVsc2Uge1xuICAgICAgbWVyZ2VIdWxscyhodWxsLCBwb2ludHMsIGV2ZW50KVxuICAgIH1cbiAgfVxuXG4gIC8vUmV0dXJuIHRyaWFuZ3VsYXRpb25cbiAgcmV0dXJuIGNlbGxzXG59XG4iLCIndXNlIHN0cmljdCdcblxudmFyIGJzZWFyY2ggPSByZXF1aXJlKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVHJpYW5ndWxhdGlvblxuXG5mdW5jdGlvbiBUcmlhbmd1bGF0aW9uKHN0YXJzLCBlZGdlcykge1xuICB0aGlzLnN0YXJzID0gc3RhcnNcbiAgdGhpcy5lZGdlcyA9IGVkZ2VzXG59XG5cbnZhciBwcm90byA9IFRyaWFuZ3VsYXRpb24ucHJvdG90eXBlXG5cbmZ1bmN0aW9uIHJlbW92ZVBhaXIobGlzdCwgaiwgaykge1xuICBmb3IodmFyIGk9MSwgbj1saXN0Lmxlbmd0aDsgaTxuOyBpKz0yKSB7XG4gICAgaWYobGlzdFtpLTFdID09PSBqICYmIGxpc3RbaV0gPT09IGspIHtcbiAgICAgIGxpc3RbaS0xXSA9IGxpc3Rbbi0yXVxuICAgICAgbGlzdFtpXSA9IGxpc3Rbbi0xXVxuICAgICAgbGlzdC5sZW5ndGggPSBuIC0gMlxuICAgICAgcmV0dXJuXG4gICAgfVxuICB9XG59XG5cbnByb3RvLmlzQ29uc3RyYWludCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIGUgPSBbMCwwXVxuICBmdW5jdGlvbiBjb21wYXJlTGV4KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAtIGJbMF0gfHwgYVsxXSAtIGJbMV1cbiAgfVxuICByZXR1cm4gZnVuY3Rpb24oaSwgaikge1xuICAgIGVbMF0gPSBNYXRoLm1pbihpLGopXG4gICAgZVsxXSA9IE1hdGgubWF4KGksailcbiAgICByZXR1cm4gYnNlYXJjaC5lcSh0aGlzLmVkZ2VzLCBlLCBjb21wYXJlTGV4KSA+PSAwXG4gIH1cbn0pKClcblxucHJvdG8ucmVtb3ZlVHJpYW5nbGUgPSBmdW5jdGlvbihpLCBqLCBrKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgcmVtb3ZlUGFpcihzdGFyc1tpXSwgaiwgaylcbiAgcmVtb3ZlUGFpcihzdGFyc1tqXSwgaywgaSlcbiAgcmVtb3ZlUGFpcihzdGFyc1trXSwgaSwgailcbn1cblxucHJvdG8uYWRkVHJpYW5nbGUgPSBmdW5jdGlvbihpLCBqLCBrKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgc3RhcnNbaV0ucHVzaChqLCBrKVxuICBzdGFyc1tqXS5wdXNoKGssIGkpXG4gIHN0YXJzW2tdLnB1c2goaSwgailcbn1cblxucHJvdG8ub3Bwb3NpdGUgPSBmdW5jdGlvbihqLCBpKSB7XG4gIHZhciBsaXN0ID0gdGhpcy5zdGFyc1tpXVxuICBmb3IodmFyIGs9MSwgbj1saXN0Lmxlbmd0aDsgazxuOyBrKz0yKSB7XG4gICAgaWYobGlzdFtrXSA9PT0gaikge1xuICAgICAgcmV0dXJuIGxpc3Rbay0xXVxuICAgIH1cbiAgfVxuICByZXR1cm4gLTFcbn1cblxucHJvdG8uZmxpcCA9IGZ1bmN0aW9uKGksIGopIHtcbiAgdmFyIGEgPSB0aGlzLm9wcG9zaXRlKGksIGopXG4gIHZhciBiID0gdGhpcy5vcHBvc2l0ZShqLCBpKVxuICB0aGlzLnJlbW92ZVRyaWFuZ2xlKGksIGosIGEpXG4gIHRoaXMucmVtb3ZlVHJpYW5nbGUoaiwgaSwgYilcbiAgdGhpcy5hZGRUcmlhbmdsZShpLCBiLCBhKVxuICB0aGlzLmFkZFRyaWFuZ2xlKGosIGEsIGIpXG59XG5cbnByb3RvLmVkZ2VzID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGZvcih2YXIgaT0wLCBuPXN0YXJzLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICB2YXIgbGlzdCA9IHN0YXJzW2ldXG4gICAgZm9yKHZhciBqPTAsIG09bGlzdC5sZW5ndGg7IGo8bTsgais9Mikge1xuICAgICAgcmVzdWx0LnB1c2goW2xpc3Rbal0sIGxpc3RbaisxXV0pXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxucHJvdG8uY2VsbHMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHN0YXJzID0gdGhpcy5zdGFyc1xuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTAsIG49c3RhcnMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHZhciBsaXN0ID0gc3RhcnNbaV1cbiAgICBmb3IodmFyIGo9MCwgbT1saXN0Lmxlbmd0aDsgajxtOyBqKz0yKSB7XG4gICAgICB2YXIgcyA9IGxpc3Rbal1cbiAgICAgIHZhciB0ID0gbGlzdFtqKzFdXG4gICAgICBpZihpIDwgTWF0aC5taW4ocywgdCkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goW2ksIHMsIHRdKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRyaWFuZ3VsYXRpb24obnVtVmVydHMsIGVkZ2VzKSB7XG4gIHZhciBzdGFycyA9IG5ldyBBcnJheShudW1WZXJ0cylcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydHM7ICsraSkge1xuICAgIHN0YXJzW2ldID0gW11cbiAgfVxuICByZXR1cm4gbmV3IFRyaWFuZ3VsYXRpb24oc3RhcnMsIGVkZ2VzKVxufVxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gY29tcGlsZVNlYXJjaChmdW5jTmFtZSwgcHJlZGljYXRlLCByZXZlcnNlZCwgZXh0cmFBcmdzLCBlYXJseU91dCkge1xuICB2YXIgY29kZSA9IFtcbiAgICBcImZ1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoYSxsLGgsXCIsIGV4dHJhQXJncy5qb2luKFwiLFwiKSwgIFwiKXtcIixcbiAgICBlYXJseU91dCA/IFwiXCIgOiBcInZhciBpPVwiLCAocmV2ZXJzZWQgPyBcImwtMVwiIDogXCJoKzFcIiksXG4gICAgXCI7d2hpbGUobDw9aCl7dmFyIG09KGwraCk+Pj4xLHg9YVttXVwiXVxuICBpZihlYXJseU91dCkge1xuICAgIGlmKHByZWRpY2F0ZS5pbmRleE9mKFwiY1wiKSA8IDApIHtcbiAgICAgIGNvZGUucHVzaChcIjtpZih4PT09eSl7cmV0dXJuIG19ZWxzZSBpZih4PD15KXtcIilcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKFwiO3ZhciBwPWMoeCx5KTtpZihwPT09MCl7cmV0dXJuIG19ZWxzZSBpZihwPD0wKXtcIilcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwiO2lmKFwiLCBwcmVkaWNhdGUsIFwiKXtpPW07XCIpXG4gIH1cbiAgaWYocmV2ZXJzZWQpIHtcbiAgICBjb2RlLnB1c2goXCJsPW0rMX1lbHNle2g9bS0xfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcImg9bS0xfWVsc2V7bD1tKzF9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifVwiKVxuICBpZihlYXJseU91dCkge1xuICAgIGNvZGUucHVzaChcInJldHVybiAtMX07XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIGl9O1wiKVxuICB9XG4gIHJldHVybiBjb2RlLmpvaW4oXCJcIilcbn1cblxuZnVuY3Rpb24gY29tcGlsZUJvdW5kc1NlYXJjaChwcmVkaWNhdGUsIHJldmVyc2VkLCBzdWZmaXgsIGVhcmx5T3V0KSB7XG4gIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oW1xuICBjb21waWxlU2VhcmNoKFwiQVwiLCBcInhcIiArIHByZWRpY2F0ZSArIFwieVwiLCByZXZlcnNlZCwgW1wieVwiXSwgZWFybHlPdXQpLFxuICBjb21waWxlU2VhcmNoKFwiUFwiLCBcImMoeCx5KVwiICsgcHJlZGljYXRlICsgXCIwXCIsIHJldmVyc2VkLCBbXCJ5XCIsIFwiY1wiXSwgZWFybHlPdXQpLFxuXCJmdW5jdGlvbiBkaXNwYXRjaEJzZWFyY2hcIiwgc3VmZml4LCBcIihhLHksYyxsLGgpe1xcXG5pZih0eXBlb2YoYyk9PT0nZnVuY3Rpb24nKXtcXFxucmV0dXJuIFAoYSwobD09PXZvaWQgMCk/MDpsfDAsKGg9PT12b2lkIDApP2EubGVuZ3RoLTE6aHwwLHksYylcXFxufWVsc2V7XFxcbnJldHVybiBBKGEsKGM9PT12b2lkIDApPzA6Y3wwLChsPT09dm9pZCAwKT9hLmxlbmd0aC0xOmx8MCx5KVxcXG59fVxcXG5yZXR1cm4gZGlzcGF0Y2hCc2VhcmNoXCIsIHN1ZmZpeF0uam9pbihcIlwiKSlcbiAgcmV0dXJuIHJlc3VsdCgpXG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBnZTogY29tcGlsZUJvdW5kc1NlYXJjaChcIj49XCIsIGZhbHNlLCAgXCJHRVwiKSxcbiAgZ3Q6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+XCIsICBmYWxzZSwgIFwiR1RcIiksXG4gIGx0OiBjb21waWxlQm91bmRzU2VhcmNoKFwiPFwiLCAgdHJ1ZSwgICBcIkxUXCIpLFxuICBsZTogY29tcGlsZUJvdW5kc1NlYXJjaChcIjw9XCIsIHRydWUsICAgXCJMRVwiKSxcbiAgZXE6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCItXCIsICB0cnVlLCAgIFwiRVFcIiwgdHJ1ZSlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IG9yaWVudGF0aW9uXG5cbmZ1bmN0aW9uIG9yaWVudGF0aW9uKHMpIHtcbiAgdmFyIHAgPSAxXG4gIGZvcih2YXIgaT0xOyBpPHMubGVuZ3RoOyArK2kpIHtcbiAgICBmb3IodmFyIGo9MDsgajxpOyArK2opIHtcbiAgICAgIGlmKHNbaV0gPCBzW2pdKSB7XG4gICAgICAgIHAgPSAtcFxuICAgICAgfSBlbHNlIGlmKHNbal0gPT09IHNbaV0pIHtcbiAgICAgICAgcmV0dXJuIDBcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHBcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBkdXAgPSByZXF1aXJlKFwiZHVwXCIpXG52YXIgc29sdmUgPSByZXF1aXJlKFwicm9idXN0LWxpbmVhci1zb2x2ZVwiKVxuXG5mdW5jdGlvbiBkb3QoYSwgYikge1xuICB2YXIgcyA9IDAuMFxuICB2YXIgZCA9IGEubGVuZ3RoXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHMgKz0gYVtpXSAqIGJbaV1cbiAgfVxuICByZXR1cm4gc1xufVxuXG5mdW5jdGlvbiBiYXJ5Y2VudHJpY0NpcmN1bWNlbnRlcihwb2ludHMpIHtcbiAgdmFyIE4gPSBwb2ludHMubGVuZ3RoXG4gIGlmKE4gPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICBcbiAgdmFyIEQgPSBwb2ludHNbMF0ubGVuZ3RoXG4gIHZhciBBID0gZHVwKFtwb2ludHMubGVuZ3RoKzEsIHBvaW50cy5sZW5ndGgrMV0sIDEuMClcbiAgdmFyIGIgPSBkdXAoW3BvaW50cy5sZW5ndGgrMV0sIDEuMClcbiAgQVtOXVtOXSA9IDAuMFxuICBmb3IodmFyIGk9MDsgaTxOOyArK2kpIHtcbiAgICBmb3IodmFyIGo9MDsgajw9aTsgKytqKSB7XG4gICAgICBBW2pdW2ldID0gQVtpXVtqXSA9IDIuMCAqIGRvdChwb2ludHNbaV0sIHBvaW50c1tqXSlcbiAgICB9XG4gICAgYltpXSA9IGRvdChwb2ludHNbaV0sIHBvaW50c1tpXSlcbiAgfVxuICB2YXIgeCA9IHNvbHZlKEEsIGIpXG5cbiAgdmFyIGRlbm9tID0gMC4wXG4gIHZhciBoID0geFtOKzFdXG4gIGZvcih2YXIgaT0wOyBpPGgubGVuZ3RoOyArK2kpIHtcbiAgICBkZW5vbSArPSBoW2ldXG4gIH1cblxuICB2YXIgeSA9IG5ldyBBcnJheShOKVxuICBmb3IodmFyIGk9MDsgaTxOOyArK2kpIHtcbiAgICB2YXIgaCA9IHhbaV1cbiAgICB2YXIgbnVtZXIgPSAwLjBcbiAgICBmb3IodmFyIGo9MDsgajxoLmxlbmd0aDsgKytqKSB7XG4gICAgICBudW1lciArPSBoW2pdXG4gICAgfVxuICAgIHlbaV0gPSAgbnVtZXIgLyBkZW5vbVxuICB9XG5cbiAgcmV0dXJuIHlcbn1cblxuZnVuY3Rpb24gY2lyY3VtY2VudGVyKHBvaW50cykge1xuICBpZihwb2ludHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIEQgPSBwb2ludHNbMF0ubGVuZ3RoXG4gIHZhciByZXN1bHQgPSBkdXAoW0RdKVxuICB2YXIgd2VpZ2h0cyA9IGJhcnljZW50cmljQ2lyY3VtY2VudGVyKHBvaW50cylcbiAgZm9yKHZhciBpPTA7IGk8cG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8RDsgKytqKSB7XG4gICAgICByZXN1bHRbal0gKz0gcG9pbnRzW2ldW2pdICogd2VpZ2h0c1tpXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmNpcmN1bWNlbnRlci5iYXJ5Y2VuZXRyaWMgPSBiYXJ5Y2VudHJpY0NpcmN1bWNlbnRlclxubW9kdWxlLmV4cG9ydHMgPSBjaXJjdW1jZW50ZXIiLCJtb2R1bGUuZXhwb3J0cyA9IGNpcmN1bXJhZGl1c1xuXG52YXIgY2lyY3VtY2VudGVyID0gcmVxdWlyZSgnY2lyY3VtY2VudGVyJylcblxuZnVuY3Rpb24gY2lyY3VtcmFkaXVzKHBvaW50cykge1xuICB2YXIgY2VudGVyID0gY2lyY3VtY2VudGVyKHBvaW50cylcbiAgdmFyIGF2Z0Rpc3QgPSAwLjBcbiAgZm9yKHZhciBpPTA7IGk8cG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHAgPSBwb2ludHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajxjZW50ZXIubGVuZ3RoOyArK2opIHtcbiAgICAgIGF2Z0Rpc3QgKz0gTWF0aC5wb3cocFtqXSAtIGNlbnRlcltqXSwgMilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIE1hdGguc3FydChhdmdEaXN0IC8gcG9pbnRzLmxlbmd0aClcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGNsYW1wXG5cbmZ1bmN0aW9uIGNsYW1wKHZhbHVlLCBtaW4sIG1heCkge1xuICByZXR1cm4gbWluIDwgbWF4XG4gICAgPyAodmFsdWUgPCBtaW4gPyBtaW4gOiB2YWx1ZSA+IG1heCA/IG1heCA6IHZhbHVlKVxuICAgIDogKHZhbHVlIDwgbWF4ID8gbWF4IDogdmFsdWUgPiBtaW4gPyBtaW4gOiB2YWx1ZSlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsZWFuUFNMR1xuXG52YXIgVW5pb25GaW5kID0gcmVxdWlyZSgndW5pb24tZmluZCcpXG52YXIgYm94SW50ZXJzZWN0ID0gcmVxdWlyZSgnYm94LWludGVyc2VjdCcpXG52YXIgc2Vnc2VnID0gcmVxdWlyZSgncm9idXN0LXNlZ21lbnQtaW50ZXJzZWN0JylcbnZhciByYXQgPSByZXF1aXJlKCdiaWctcmF0JylcbnZhciByYXRDbXAgPSByZXF1aXJlKCdiaWctcmF0L2NtcCcpXG52YXIgcmF0VG9GbG9hdCA9IHJlcXVpcmUoJ2JpZy1yYXQvdG8tZmxvYXQnKVxudmFyIHJhdFZlYyA9IHJlcXVpcmUoJ3JhdC12ZWMnKVxudmFyIG5leHRhZnRlciA9IHJlcXVpcmUoJ25leHRhZnRlcicpXG5cbnZhciBzb2x2ZUludGVyc2VjdGlvbiA9IHJlcXVpcmUoJy4vbGliL3JhdC1zZWctaW50ZXJzZWN0JylcblxuLy8gQm91bmRzIG9uIGEgcmF0aW9uYWwgbnVtYmVyIHdoZW4gcm91bmRlZCB0byBhIGZsb2F0XG5mdW5jdGlvbiBib3VuZFJhdCAocikge1xuICB2YXIgZiA9IHJhdFRvRmxvYXQocilcbiAgcmV0dXJuIFtcbiAgICBuZXh0YWZ0ZXIoZiwgLUluZmluaXR5KSxcbiAgICBuZXh0YWZ0ZXIoZiwgSW5maW5pdHkpXG4gIF1cbn1cblxuLy8gQ29udmVydCBhIGxpc3Qgb2YgZWRnZXMgaW4gYSBwc2xnIHRvIGJvdW5kaW5nIGJveGVzXG5mdW5jdGlvbiBib3VuZEVkZ2VzIChwb2ludHMsIGVkZ2VzKSB7XG4gIHZhciBib3VuZHMgPSBuZXcgQXJyYXkoZWRnZXMubGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgIHZhciBhID0gcG9pbnRzW2VbMF1dXG4gICAgdmFyIGIgPSBwb2ludHNbZVsxXV1cbiAgICBib3VuZHNbaV0gPSBbXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5taW4oYVswXSwgYlswXSksIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5taW4oYVsxXSwgYlsxXSksIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5tYXgoYVswXSwgYlswXSksIEluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcihNYXRoLm1heChhWzFdLCBiWzFdKSwgSW5maW5pdHkpXG4gICAgXVxuICB9XG4gIHJldHVybiBib3VuZHNcbn1cblxuLy8gQ29udmVydCBhIGxpc3Qgb2YgcG9pbnRzIGludG8gYm91bmRpbmcgYm94ZXMgYnkgZHVwbGljYXRpbmcgY29vcmRzXG5mdW5jdGlvbiBib3VuZFBvaW50cyAocG9pbnRzKSB7XG4gIHZhciBib3VuZHMgPSBuZXcgQXJyYXkocG9pbnRzLmxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcCA9IHBvaW50c1tpXVxuICAgIGJvdW5kc1tpXSA9IFtcbiAgICAgIG5leHRhZnRlcihwWzBdLCAtSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHBbMV0sIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIocFswXSwgSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHBbMV0sIEluZmluaXR5KVxuICAgIF1cbiAgfVxuICByZXR1cm4gYm91bmRzXG59XG5cbi8vIEZpbmQgYWxsIHBhaXJzIG9mIGNyb3NzaW5nIGVkZ2VzIGluIGEgcHNsZyAoZ2l2ZW4gZWRnZSBib3VuZHMpXG5mdW5jdGlvbiBnZXRDcm9zc2luZ3MgKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMpIHtcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGJveEludGVyc2VjdChlZGdlQm91bmRzLCBmdW5jdGlvbiAoaSwgaikge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICB2YXIgZiA9IGVkZ2VzW2pdXG4gICAgaWYgKGVbMF0gPT09IGZbMF0gfHwgZVswXSA9PT0gZlsxXSB8fFxuICAgICAgZVsxXSA9PT0gZlswXSB8fCBlWzFdID09PSBmWzFdKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdmFyIGEgPSBwb2ludHNbZVswXV1cbiAgICB2YXIgYiA9IHBvaW50c1tlWzFdXVxuICAgIHZhciBjID0gcG9pbnRzW2ZbMF1dXG4gICAgdmFyIGQgPSBwb2ludHNbZlsxXV1cbiAgICBpZiAoc2Vnc2VnKGEsIGIsIGMsIGQpKSB7XG4gICAgICByZXN1bHQucHVzaChbaSwgal0pXG4gICAgfVxuICB9KVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8vIEZpbmQgYWxsIHBhaXJzIG9mIGNyb3NzaW5nIHZlcnRpY2VzIGluIGEgcHNsZyAoZ2l2ZW4gZWRnZS92ZXJ0IGJvdW5kcylcbmZ1bmN0aW9uIGdldFRKdW5jdGlvbnMgKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMsIHZlcnRCb3VuZHMpIHtcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGJveEludGVyc2VjdChlZGdlQm91bmRzLCB2ZXJ0Qm91bmRzLCBmdW5jdGlvbiAoaSwgdikge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICBpZiAoZVswXSA9PT0gdiB8fCBlWzFdID09PSB2KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdmFyIHAgPSBwb2ludHNbdl1cbiAgICB2YXIgYSA9IHBvaW50c1tlWzBdXVxuICAgIHZhciBiID0gcG9pbnRzW2VbMV1dXG4gICAgaWYgKHNlZ3NlZyhhLCBiLCBwLCBwKSkge1xuICAgICAgcmVzdWx0LnB1c2goW2ksIHZdKVxuICAgIH1cbiAgfSlcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vLyBDdXQgZWRnZXMgYWxvbmcgY3Jvc3NpbmdzL3RqdW5jdGlvbnNcbmZ1bmN0aW9uIGN1dEVkZ2VzIChmbG9hdFBvaW50cywgZWRnZXMsIGNyb3NzaW5ncywganVuY3Rpb25zLCB1c2VDb2xvcikge1xuICB2YXIgaSwgZVxuXG4gIC8vIENvbnZlcnQgY3Jvc3NpbmdzIGludG8gdGp1bmN0aW9ucyBieSBjb25zdHJ1Y3RpbmcgcmF0aW9uYWwgcG9pbnRzXG4gIHZhciByYXRQb2ludHMgPSBmbG9hdFBvaW50cy5tYXAoZnVuY3Rpb24ocCkge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgICByYXQocFswXSksXG4gICAgICAgICAgcmF0KHBbMV0pXG4gICAgICBdXG4gIH0pXG4gIGZvciAoaSA9IDA7IGkgPCBjcm9zc2luZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgY3Jvc3NpbmcgPSBjcm9zc2luZ3NbaV1cbiAgICBlID0gY3Jvc3NpbmdbMF1cbiAgICB2YXIgZiA9IGNyb3NzaW5nWzFdXG4gICAgdmFyIGVlID0gZWRnZXNbZV1cbiAgICB2YXIgZWYgPSBlZGdlc1tmXVxuICAgIHZhciB4ID0gc29sdmVJbnRlcnNlY3Rpb24oXG4gICAgICByYXRWZWMoZmxvYXRQb2ludHNbZWVbMF1dKSxcbiAgICAgIHJhdFZlYyhmbG9hdFBvaW50c1tlZVsxXV0pLFxuICAgICAgcmF0VmVjKGZsb2F0UG9pbnRzW2VmWzBdXSksXG4gICAgICByYXRWZWMoZmxvYXRQb2ludHNbZWZbMV1dKSlcbiAgICBpZiAoIXgpIHtcbiAgICAgIC8vIFNlZ21lbnRzIGFyZSBwYXJhbGxlbCwgc2hvdWxkIGFscmVhZHkgYmUgaGFuZGxlZCBieSB0LWp1bmN0aW9uc1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIGlkeCA9IGZsb2F0UG9pbnRzLmxlbmd0aFxuICAgIGZsb2F0UG9pbnRzLnB1c2goW3JhdFRvRmxvYXQoeFswXSksIHJhdFRvRmxvYXQoeFsxXSldKVxuICAgIHJhdFBvaW50cy5wdXNoKHgpXG4gICAganVuY3Rpb25zLnB1c2goW2UsIGlkeF0sIFtmLCBpZHhdKVxuICB9XG5cbiAgLy8gU29ydCB0anVuY3Rpb25zXG4gIGp1bmN0aW9ucy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKGFbMF0gIT09IGJbMF0pIHtcbiAgICAgIHJldHVybiBhWzBdIC0gYlswXVxuICAgIH1cbiAgICB2YXIgdSA9IHJhdFBvaW50c1thWzFdXVxuICAgIHZhciB2ID0gcmF0UG9pbnRzW2JbMV1dXG4gICAgcmV0dXJuIHJhdENtcCh1WzBdLCB2WzBdKSB8fCByYXRDbXAodVsxXSwgdlsxXSlcbiAgfSlcblxuICAvLyBTcGxpdCBlZGdlcyBhbG9uZyBqdW5jdGlvbnNcbiAgZm9yIChpID0ganVuY3Rpb25zLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgdmFyIGp1bmN0aW9uID0ganVuY3Rpb25zW2ldXG4gICAgZSA9IGp1bmN0aW9uWzBdXG5cbiAgICB2YXIgZWRnZSA9IGVkZ2VzW2VdXG4gICAgdmFyIHMgPSBlZGdlWzBdXG4gICAgdmFyIHQgPSBlZGdlWzFdXG5cbiAgICAvLyBDaGVjayBpZiBlZGdlIGlzIG5vdCBsZXhpY29ncmFwaGljYWxseSBzb3J0ZWRcbiAgICB2YXIgYSA9IGZsb2F0UG9pbnRzW3NdXG4gICAgdmFyIGIgPSBmbG9hdFBvaW50c1t0XVxuICAgIGlmICgoKGFbMF0gLSBiWzBdKSB8fCAoYVsxXSAtIGJbMV0pKSA8IDApIHtcbiAgICAgIHZhciB0bXAgPSBzXG4gICAgICBzID0gdFxuICAgICAgdCA9IHRtcFxuICAgIH1cblxuICAgIC8vIFNwbGl0IGxlYWRpbmcgZWRnZVxuICAgIGVkZ2VbMF0gPSBzXG4gICAgdmFyIGxhc3QgPSBlZGdlWzFdID0ganVuY3Rpb25bMV1cblxuICAgIC8vIElmIHdlIGFyZSBncm91cGluZyBlZGdlcyBieSBjb2xvciwgcmVtZW1iZXIgdG8gdHJhY2sgZGF0YVxuICAgIHZhciBjb2xvclxuICAgIGlmICh1c2VDb2xvcikge1xuICAgICAgY29sb3IgPSBlZGdlWzJdXG4gICAgfVxuXG4gICAgLy8gU3BsaXQgb3RoZXIgZWRnZXNcbiAgICB3aGlsZSAoaSA+IDAgJiYganVuY3Rpb25zW2kgLSAxXVswXSA9PT0gZSkge1xuICAgICAgdmFyIGp1bmN0aW9uID0ganVuY3Rpb25zWy0taV1cbiAgICAgIHZhciBuZXh0ID0ganVuY3Rpb25bMV1cbiAgICAgIGlmICh1c2VDb2xvcikge1xuICAgICAgICBlZGdlcy5wdXNoKFtsYXN0LCBuZXh0LCBjb2xvcl0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlZGdlcy5wdXNoKFtsYXN0LCBuZXh0XSlcbiAgICAgIH1cbiAgICAgIGxhc3QgPSBuZXh0XG4gICAgfVxuXG4gICAgLy8gQWRkIGZpbmFsIGVkZ2VcbiAgICBpZiAodXNlQ29sb3IpIHtcbiAgICAgIGVkZ2VzLnB1c2goW2xhc3QsIHQsIGNvbG9yXSlcbiAgICB9IGVsc2Uge1xuICAgICAgZWRnZXMucHVzaChbbGFzdCwgdF0pXG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIGNvbnN0cnVjdGVkIHJhdGlvbmFsIHBvaW50c1xuICByZXR1cm4gcmF0UG9pbnRzXG59XG5cbi8vIE1lcmdlIG92ZXJsYXBwaW5nIHBvaW50c1xuZnVuY3Rpb24gZGVkdXBQb2ludHMgKGZsb2F0UG9pbnRzLCByYXRQb2ludHMsIGZsb2F0Qm91bmRzKSB7XG4gIHZhciBudW1Qb2ludHMgPSByYXRQb2ludHMubGVuZ3RoXG4gIHZhciB1ZiA9IG5ldyBVbmlvbkZpbmQobnVtUG9pbnRzKVxuXG4gIC8vIENvbXB1dGUgcmF0aW9uYWwgYm91bmRzXG4gIHZhciBib3VuZHMgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHJhdFBvaW50cy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBwID0gcmF0UG9pbnRzW2ldXG4gICAgdmFyIHhiID0gYm91bmRSYXQocFswXSlcbiAgICB2YXIgeWIgPSBib3VuZFJhdChwWzFdKVxuICAgIGJvdW5kcy5wdXNoKFtcbiAgICAgIG5leHRhZnRlcih4YlswXSwgLUluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcih5YlswXSwgLUluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcih4YlsxXSwgSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHliWzFdLCBJbmZpbml0eSlcbiAgICBdKVxuICB9XG5cbiAgLy8gTGluayBhbGwgcG9pbnRzIHdpdGggb3ZlciBsYXBwaW5nIGJveGVzXG4gIGJveEludGVyc2VjdChib3VuZHMsIGZ1bmN0aW9uIChpLCBqKSB7XG4gICAgdWYubGluayhpLCBqKVxuICB9KVxuXG4gIC8vIERvIDEgcGFzcyBvdmVyIHBvaW50cyB0byBjb21iaW5lIHBvaW50cyBpbiBsYWJlbCBzZXRzXG4gIHZhciBub0R1cGVzID0gdHJ1ZVxuICB2YXIgbGFiZWxzID0gbmV3IEFycmF5KG51bVBvaW50cylcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1Qb2ludHM7ICsraSkge1xuICAgIHZhciBqID0gdWYuZmluZChpKVxuICAgIGlmIChqICE9PSBpKSB7XG4gICAgICAvLyBDbGVhciBuby1kdXBlcyBmbGFnLCB6ZXJvIG91dCBsYWJlbFxuICAgICAgbm9EdXBlcyA9IGZhbHNlXG4gICAgICAvLyBNYWtlIGVhY2ggcG9pbnQgdGhlIHRvcC1sZWZ0IHBvaW50IGZyb20gaXRzIGNlbGxcbiAgICAgIGZsb2F0UG9pbnRzW2pdID0gW1xuICAgICAgICBNYXRoLm1pbihmbG9hdFBvaW50c1tpXVswXSwgZmxvYXRQb2ludHNbal1bMF0pLFxuICAgICAgICBNYXRoLm1pbihmbG9hdFBvaW50c1tpXVsxXSwgZmxvYXRQb2ludHNbal1bMV0pXG4gICAgICBdXG4gICAgfVxuICB9XG5cbiAgLy8gSWYgbm8gZHVwbGljYXRlcywgcmV0dXJuIG51bGwgdG8gc2lnbmFsIHRlcm1pbmF0aW9uXG4gIGlmIChub0R1cGVzKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBwdHIgPSAwXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtUG9pbnRzOyArK2kpIHtcbiAgICB2YXIgaiA9IHVmLmZpbmQoaSlcbiAgICBpZiAoaiA9PT0gaSkge1xuICAgICAgbGFiZWxzW2ldID0gcHRyXG4gICAgICBmbG9hdFBvaW50c1twdHIrK10gPSBmbG9hdFBvaW50c1tpXVxuICAgIH0gZWxzZSB7XG4gICAgICBsYWJlbHNbaV0gPSAtMVxuICAgIH1cbiAgfVxuXG4gIGZsb2F0UG9pbnRzLmxlbmd0aCA9IHB0clxuXG4gIC8vIERvIGEgc2Vjb25kIHBhc3MgdG8gZml4IHVwIG1pc3NpbmcgbGFiZWxzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtUG9pbnRzOyArK2kpIHtcbiAgICBpZiAobGFiZWxzW2ldIDwgMCkge1xuICAgICAgbGFiZWxzW2ldID0gbGFiZWxzW3VmLmZpbmQoaSldXG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIHJlc3VsdGluZyB1bmlvbi1maW5kIGRhdGEgc3RydWN0dXJlXG4gIHJldHVybiBsYWJlbHNcbn1cblxuZnVuY3Rpb24gY29tcGFyZUxleDIgKGEsIGIpIHsgcmV0dXJuIChhWzBdIC0gYlswXSkgfHwgKGFbMV0gLSBiWzFdKSB9XG5mdW5jdGlvbiBjb21wYXJlTGV4MyAoYSwgYikge1xuICB2YXIgZCA9IChhWzBdIC0gYlswXSkgfHwgKGFbMV0gLSBiWzFdKVxuICBpZiAoZCkge1xuICAgIHJldHVybiBkXG4gIH1cbiAgaWYgKGFbMl0gPCBiWzJdKSB7XG4gICAgcmV0dXJuIC0xXG4gIH0gZWxzZSBpZiAoYVsyXSA+IGJbMl0pIHtcbiAgICByZXR1cm4gMVxuICB9XG4gIHJldHVybiAwXG59XG5cbi8vIFJlbW92ZSBkdXBsaWNhdGUgZWRnZSBsYWJlbHNcbmZ1bmN0aW9uIGRlZHVwRWRnZXMgKGVkZ2VzLCBsYWJlbHMsIHVzZUNvbG9yKSB7XG4gIGlmIChlZGdlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm5cbiAgfVxuICBpZiAobGFiZWxzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlZGdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgICAgdmFyIGEgPSBsYWJlbHNbZVswXV1cbiAgICAgIHZhciBiID0gbGFiZWxzW2VbMV1dXG4gICAgICBlWzBdID0gTWF0aC5taW4oYSwgYilcbiAgICAgIGVbMV0gPSBNYXRoLm1heChhLCBiKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICB2YXIgYSA9IGVbMF1cbiAgICAgIHZhciBiID0gZVsxXVxuICAgICAgZVswXSA9IE1hdGgubWluKGEsIGIpXG4gICAgICBlWzFdID0gTWF0aC5tYXgoYSwgYilcbiAgICB9XG4gIH1cbiAgaWYgKHVzZUNvbG9yKSB7XG4gICAgZWRnZXMuc29ydChjb21wYXJlTGV4MylcbiAgfSBlbHNlIHtcbiAgICBlZGdlcy5zb3J0KGNvbXBhcmVMZXgyKVxuICB9XG4gIHZhciBwdHIgPSAxXG4gIGZvciAodmFyIGkgPSAxOyBpIDwgZWRnZXMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcHJldiA9IGVkZ2VzW2kgLSAxXVxuICAgIHZhciBuZXh0ID0gZWRnZXNbaV1cbiAgICBpZiAobmV4dFswXSA9PT0gcHJldlswXSAmJiBuZXh0WzFdID09PSBwcmV2WzFdICYmXG4gICAgICAoIXVzZUNvbG9yIHx8IG5leHRbMl0gPT09IHByZXZbMl0pKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBlZGdlc1twdHIrK10gPSBuZXh0XG4gIH1cbiAgZWRnZXMubGVuZ3RoID0gcHRyXG59XG5cbmZ1bmN0aW9uIHByZVJvdW5kIChwb2ludHMsIGVkZ2VzLCB1c2VDb2xvcikge1xuICB2YXIgbGFiZWxzID0gZGVkdXBQb2ludHMocG9pbnRzLCBbXSwgYm91bmRQb2ludHMocG9pbnRzKSlcbiAgZGVkdXBFZGdlcyhlZGdlcywgbGFiZWxzLCB1c2VDb2xvcilcbiAgcmV0dXJuICEhbGFiZWxzXG59XG5cbi8vIFJlcGVhdCB1bnRpbCBjb252ZXJnZW5jZVxuZnVuY3Rpb24gc25hcFJvdW5kIChwb2ludHMsIGVkZ2VzLCB1c2VDb2xvcikge1xuICAvLyAxLiBmaW5kIGVkZ2UgY3Jvc3NpbmdzXG4gIHZhciBlZGdlQm91bmRzID0gYm91bmRFZGdlcyhwb2ludHMsIGVkZ2VzKVxuICB2YXIgY3Jvc3NpbmdzID0gZ2V0Q3Jvc3NpbmdzKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMpXG5cbiAgLy8gMi4gZmluZCB0LWp1bmN0aW9uc1xuICB2YXIgdmVydEJvdW5kcyA9IGJvdW5kUG9pbnRzKHBvaW50cylcbiAgdmFyIHRqdW5jdGlvbnMgPSBnZXRUSnVuY3Rpb25zKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMsIHZlcnRCb3VuZHMpXG5cbiAgLy8gMy4gY3V0IGVkZ2VzLCBjb25zdHJ1Y3QgcmF0aW9uYWwgcG9pbnRzXG4gIHZhciByYXRQb2ludHMgPSBjdXRFZGdlcyhwb2ludHMsIGVkZ2VzLCBjcm9zc2luZ3MsIHRqdW5jdGlvbnMsIHVzZUNvbG9yKVxuXG4gIC8vIDQuIGRlZHVwZSB2ZXJ0c1xuICB2YXIgbGFiZWxzID0gZGVkdXBQb2ludHMocG9pbnRzLCByYXRQb2ludHMsIHZlcnRCb3VuZHMpXG5cbiAgLy8gNS4gZGVkdXBlIGVkZ2VzXG4gIGRlZHVwRWRnZXMoZWRnZXMsIGxhYmVscywgdXNlQ29sb3IpXG5cbiAgLy8gNi4gY2hlY2sgdGVybWluYXRpb25cbiAgaWYgKCFsYWJlbHMpIHtcbiAgICByZXR1cm4gKGNyb3NzaW5ncy5sZW5ndGggPiAwIHx8IHRqdW5jdGlvbnMubGVuZ3RoID4gMClcbiAgfVxuXG4gIC8vIE1vcmUgaXRlcmF0aW9ucyBuZWNlc3NhcnlcbiAgcmV0dXJuIHRydWVcbn1cblxuLy8gTWFpbiBsb29wLCBydW5zIFBTTEcgY2xlYW4gdXAgdW50aWwgY29tcGxldGlvblxuZnVuY3Rpb24gY2xlYW5QU0xHIChwb2ludHMsIGVkZ2VzLCBjb2xvcnMpIHtcbiAgLy8gSWYgdXNpbmcgY29sb3JzLCBhdWdtZW50IGVkZ2VzIHdpdGggY29sb3IgZGF0YVxuICB2YXIgcHJldkVkZ2VzXG4gIGlmIChjb2xvcnMpIHtcbiAgICBwcmV2RWRnZXMgPSBlZGdlc1xuICAgIHZhciBhdWdFZGdlcyA9IG5ldyBBcnJheShlZGdlcy5sZW5ndGgpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlZGdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgICAgYXVnRWRnZXNbaV0gPSBbZVswXSwgZVsxXSwgY29sb3JzW2ldXVxuICAgIH1cbiAgICBlZGdlcyA9IGF1Z0VkZ2VzXG4gIH1cblxuICAvLyBGaXJzdCByb3VuZDogcmVtb3ZlIGR1cGxpY2F0ZSBlZGdlcyBhbmQgcG9pbnRzXG4gIHZhciBtb2RpZmllZCA9IHByZVJvdW5kKHBvaW50cywgZWRnZXMsICEhY29sb3JzKVxuXG4gIC8vIFJ1biBzbmFwIHJvdW5kaW5nIHVudGlsIGNvbnZlcmdlbmNlXG4gIHdoaWxlIChzbmFwUm91bmQocG9pbnRzLCBlZGdlcywgISFjb2xvcnMpKSB7XG4gICAgbW9kaWZpZWQgPSB0cnVlXG4gIH1cblxuICAvLyBTdHJpcCBjb2xvciB0YWdzXG4gIGlmICghIWNvbG9ycyAmJiBtb2RpZmllZCkge1xuICAgIHByZXZFZGdlcy5sZW5ndGggPSAwXG4gICAgY29sb3JzLmxlbmd0aCA9IDBcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICBwcmV2RWRnZXMucHVzaChbZVswXSwgZVsxXV0pXG4gICAgICBjb2xvcnMucHVzaChlWzJdKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtb2RpZmllZFxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gc29sdmVJbnRlcnNlY3Rpb25cblxudmFyIHJhdE11bCA9IHJlcXVpcmUoJ2JpZy1yYXQvbXVsJylcbnZhciByYXREaXYgPSByZXF1aXJlKCdiaWctcmF0L2RpdicpXG52YXIgcmF0U3ViID0gcmVxdWlyZSgnYmlnLXJhdC9zdWInKVxudmFyIHJhdFNpZ24gPSByZXF1aXJlKCdiaWctcmF0L3NpZ24nKVxudmFyIHJ2U3ViID0gcmVxdWlyZSgncmF0LXZlYy9zdWInKVxudmFyIHJ2QWRkID0gcmVxdWlyZSgncmF0LXZlYy9hZGQnKVxudmFyIHJ2TXVscyA9IHJlcXVpcmUoJ3JhdC12ZWMvbXVscycpXG5cbmZ1bmN0aW9uIHJhdFBlcnAgKGEsIGIpIHtcbiAgcmV0dXJuIHJhdFN1YihyYXRNdWwoYVswXSwgYlsxXSksIHJhdE11bChhWzFdLCBiWzBdKSlcbn1cblxuLy8gU29sdmUgZm9yIGludGVyc2VjdGlvblxuLy8gIHggPSBhICsgdCAoYi1hKVxuLy8gICh4IC0gYykgXiAoZC1jKSA9IDBcbi8vICAodCAqIChiLWEpICsgKGEtYykgKSBeIChkLWMpID0gMFxuLy8gIHQgKiAoYi1hKV4oZC1jKSA9IChkLWMpXihhLWMpXG4vLyAgdCA9IChkLWMpXihhLWMpIC8gKGItYSleKGQtYylcblxuZnVuY3Rpb24gc29sdmVJbnRlcnNlY3Rpb24gKGEsIGIsIGMsIGQpIHtcbiAgdmFyIGJhID0gcnZTdWIoYiwgYSlcbiAgdmFyIGRjID0gcnZTdWIoZCwgYylcblxuICB2YXIgYmFYZGMgPSByYXRQZXJwKGJhLCBkYylcblxuICBpZiAocmF0U2lnbihiYVhkYykgPT09IDApIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIGFjID0gcnZTdWIoYSwgYylcbiAgdmFyIGRjWGFjID0gcmF0UGVycChkYywgYWMpXG5cbiAgdmFyIHQgPSByYXREaXYoZGNYYWMsIGJhWGRjKVxuICB2YXIgcyA9IHJ2TXVscyhiYSwgdClcbiAgdmFyIHIgPSBydkFkZChhLCBzKVxuXG4gIHJldHVybiByXG59XG4iLCIvKiogQG1vZHVsZSAgY29sb3ItaWQgKi9cclxuXHJcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGNsYW1wID0gcmVxdWlyZSgnY2xhbXAnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB0b051bWJlclxyXG5tb2R1bGUuZXhwb3J0cy50byA9IHRvTnVtYmVyXHJcbm1vZHVsZS5leHBvcnRzLmZyb20gPSBmcm9tTnVtYmVyXHJcblxyXG5mdW5jdGlvbiB0b051bWJlciAocmdiYSwgbm9ybWFsaXplZCkge1xyXG5cdGlmKG5vcm1hbGl6ZWQgPT0gbnVsbCkgbm9ybWFsaXplZCA9IHRydWVcclxuXHJcblx0dmFyIHIgPSByZ2JhWzBdLCBnID0gcmdiYVsxXSwgYiA9IHJnYmFbMl0sIGEgPSByZ2JhWzNdXHJcblxyXG5cdGlmIChhID09IG51bGwpIGEgPSBub3JtYWxpemVkID8gMSA6IDI1NVxyXG5cclxuXHRpZiAobm9ybWFsaXplZCkge1xyXG5cdFx0ciAqPSAyNTVcclxuXHRcdGcgKj0gMjU1XHJcblx0XHRiICo9IDI1NVxyXG5cdFx0YSAqPSAyNTVcclxuXHR9XHJcblxyXG5cdHIgPSBjbGFtcChyLCAwLCAyNTUpICYgMHhGRlxyXG5cdGcgPSBjbGFtcChnLCAwLCAyNTUpICYgMHhGRlxyXG5cdGIgPSBjbGFtcChiLCAwLCAyNTUpICYgMHhGRlxyXG5cdGEgPSBjbGFtcChhLCAwLCAyNTUpICYgMHhGRlxyXG5cclxuXHQvL2hpLW9yZGVyIHNoaWZ0IGNvbnZlcnRzIHRvIC0xLCBzbyB3ZSBjYW4ndCB1c2UgPDwyNFxyXG5cdHZhciBuID0gKHIgKiAweDAxMDAwMDAwKSArIChnIDw8IDE2KSArIChiIDw8IDgpICsgKGEpXHJcblxyXG5cdHJldHVybiBuXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZyb21OdW1iZXIgKG4sIG5vcm1hbGl6ZWQpIHtcclxuXHRuID0gK25cclxuXHJcblx0dmFyIHIgPSBuID4+PiAyNFxyXG5cdHZhciBnID0gKG4gJiAweDAwZmYwMDAwKSA+Pj4gMTZcclxuXHR2YXIgYiA9IChuICYgMHgwMDAwZmYwMCkgPj4+IDhcclxuXHR2YXIgYSA9IG4gJiAweDAwMDAwMGZmXHJcblxyXG5cdGlmIChub3JtYWxpemVkID09PSBmYWxzZSkgcmV0dXJuIFtyLCBnLCBiLCBhXVxyXG5cclxuXHRyZXR1cm4gW3IvMjU1LCBnLzI1NSwgYi8yNTUsIGEvMjU1XVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcblx0XCJhbGljZWJsdWVcIjogWzI0MCwgMjQ4LCAyNTVdLFxyXG5cdFwiYW50aXF1ZXdoaXRlXCI6IFsyNTAsIDIzNSwgMjE1XSxcclxuXHRcImFxdWFcIjogWzAsIDI1NSwgMjU1XSxcclxuXHRcImFxdWFtYXJpbmVcIjogWzEyNywgMjU1LCAyMTJdLFxyXG5cdFwiYXp1cmVcIjogWzI0MCwgMjU1LCAyNTVdLFxyXG5cdFwiYmVpZ2VcIjogWzI0NSwgMjQ1LCAyMjBdLFxyXG5cdFwiYmlzcXVlXCI6IFsyNTUsIDIyOCwgMTk2XSxcclxuXHRcImJsYWNrXCI6IFswLCAwLCAwXSxcclxuXHRcImJsYW5jaGVkYWxtb25kXCI6IFsyNTUsIDIzNSwgMjA1XSxcclxuXHRcImJsdWVcIjogWzAsIDAsIDI1NV0sXHJcblx0XCJibHVldmlvbGV0XCI6IFsxMzgsIDQzLCAyMjZdLFxyXG5cdFwiYnJvd25cIjogWzE2NSwgNDIsIDQyXSxcclxuXHRcImJ1cmx5d29vZFwiOiBbMjIyLCAxODQsIDEzNV0sXHJcblx0XCJjYWRldGJsdWVcIjogWzk1LCAxNTgsIDE2MF0sXHJcblx0XCJjaGFydHJldXNlXCI6IFsxMjcsIDI1NSwgMF0sXHJcblx0XCJjaG9jb2xhdGVcIjogWzIxMCwgMTA1LCAzMF0sXHJcblx0XCJjb3JhbFwiOiBbMjU1LCAxMjcsIDgwXSxcclxuXHRcImNvcm5mbG93ZXJibHVlXCI6IFsxMDAsIDE0OSwgMjM3XSxcclxuXHRcImNvcm5zaWxrXCI6IFsyNTUsIDI0OCwgMjIwXSxcclxuXHRcImNyaW1zb25cIjogWzIyMCwgMjAsIDYwXSxcclxuXHRcImN5YW5cIjogWzAsIDI1NSwgMjU1XSxcclxuXHRcImRhcmtibHVlXCI6IFswLCAwLCAxMzldLFxyXG5cdFwiZGFya2N5YW5cIjogWzAsIDEzOSwgMTM5XSxcclxuXHRcImRhcmtnb2xkZW5yb2RcIjogWzE4NCwgMTM0LCAxMV0sXHJcblx0XCJkYXJrZ3JheVwiOiBbMTY5LCAxNjksIDE2OV0sXHJcblx0XCJkYXJrZ3JlZW5cIjogWzAsIDEwMCwgMF0sXHJcblx0XCJkYXJrZ3JleVwiOiBbMTY5LCAxNjksIDE2OV0sXHJcblx0XCJkYXJra2hha2lcIjogWzE4OSwgMTgzLCAxMDddLFxyXG5cdFwiZGFya21hZ2VudGFcIjogWzEzOSwgMCwgMTM5XSxcclxuXHRcImRhcmtvbGl2ZWdyZWVuXCI6IFs4NSwgMTA3LCA0N10sXHJcblx0XCJkYXJrb3JhbmdlXCI6IFsyNTUsIDE0MCwgMF0sXHJcblx0XCJkYXJrb3JjaGlkXCI6IFsxNTMsIDUwLCAyMDRdLFxyXG5cdFwiZGFya3JlZFwiOiBbMTM5LCAwLCAwXSxcclxuXHRcImRhcmtzYWxtb25cIjogWzIzMywgMTUwLCAxMjJdLFxyXG5cdFwiZGFya3NlYWdyZWVuXCI6IFsxNDMsIDE4OCwgMTQzXSxcclxuXHRcImRhcmtzbGF0ZWJsdWVcIjogWzcyLCA2MSwgMTM5XSxcclxuXHRcImRhcmtzbGF0ZWdyYXlcIjogWzQ3LCA3OSwgNzldLFxyXG5cdFwiZGFya3NsYXRlZ3JleVwiOiBbNDcsIDc5LCA3OV0sXHJcblx0XCJkYXJrdHVycXVvaXNlXCI6IFswLCAyMDYsIDIwOV0sXHJcblx0XCJkYXJrdmlvbGV0XCI6IFsxNDgsIDAsIDIxMV0sXHJcblx0XCJkZWVwcGlua1wiOiBbMjU1LCAyMCwgMTQ3XSxcclxuXHRcImRlZXBza3libHVlXCI6IFswLCAxOTEsIDI1NV0sXHJcblx0XCJkaW1ncmF5XCI6IFsxMDUsIDEwNSwgMTA1XSxcclxuXHRcImRpbWdyZXlcIjogWzEwNSwgMTA1LCAxMDVdLFxyXG5cdFwiZG9kZ2VyYmx1ZVwiOiBbMzAsIDE0NCwgMjU1XSxcclxuXHRcImZpcmVicmlja1wiOiBbMTc4LCAzNCwgMzRdLFxyXG5cdFwiZmxvcmFsd2hpdGVcIjogWzI1NSwgMjUwLCAyNDBdLFxyXG5cdFwiZm9yZXN0Z3JlZW5cIjogWzM0LCAxMzksIDM0XSxcclxuXHRcImZ1Y2hzaWFcIjogWzI1NSwgMCwgMjU1XSxcclxuXHRcImdhaW5zYm9yb1wiOiBbMjIwLCAyMjAsIDIyMF0sXHJcblx0XCJnaG9zdHdoaXRlXCI6IFsyNDgsIDI0OCwgMjU1XSxcclxuXHRcImdvbGRcIjogWzI1NSwgMjE1LCAwXSxcclxuXHRcImdvbGRlbnJvZFwiOiBbMjE4LCAxNjUsIDMyXSxcclxuXHRcImdyYXlcIjogWzEyOCwgMTI4LCAxMjhdLFxyXG5cdFwiZ3JlZW5cIjogWzAsIDEyOCwgMF0sXHJcblx0XCJncmVlbnllbGxvd1wiOiBbMTczLCAyNTUsIDQ3XSxcclxuXHRcImdyZXlcIjogWzEyOCwgMTI4LCAxMjhdLFxyXG5cdFwiaG9uZXlkZXdcIjogWzI0MCwgMjU1LCAyNDBdLFxyXG5cdFwiaG90cGlua1wiOiBbMjU1LCAxMDUsIDE4MF0sXHJcblx0XCJpbmRpYW5yZWRcIjogWzIwNSwgOTIsIDkyXSxcclxuXHRcImluZGlnb1wiOiBbNzUsIDAsIDEzMF0sXHJcblx0XCJpdm9yeVwiOiBbMjU1LCAyNTUsIDI0MF0sXHJcblx0XCJraGFraVwiOiBbMjQwLCAyMzAsIDE0MF0sXHJcblx0XCJsYXZlbmRlclwiOiBbMjMwLCAyMzAsIDI1MF0sXHJcblx0XCJsYXZlbmRlcmJsdXNoXCI6IFsyNTUsIDI0MCwgMjQ1XSxcclxuXHRcImxhd25ncmVlblwiOiBbMTI0LCAyNTIsIDBdLFxyXG5cdFwibGVtb25jaGlmZm9uXCI6IFsyNTUsIDI1MCwgMjA1XSxcclxuXHRcImxpZ2h0Ymx1ZVwiOiBbMTczLCAyMTYsIDIzMF0sXHJcblx0XCJsaWdodGNvcmFsXCI6IFsyNDAsIDEyOCwgMTI4XSxcclxuXHRcImxpZ2h0Y3lhblwiOiBbMjI0LCAyNTUsIDI1NV0sXHJcblx0XCJsaWdodGdvbGRlbnJvZHllbGxvd1wiOiBbMjUwLCAyNTAsIDIxMF0sXHJcblx0XCJsaWdodGdyYXlcIjogWzIxMSwgMjExLCAyMTFdLFxyXG5cdFwibGlnaHRncmVlblwiOiBbMTQ0LCAyMzgsIDE0NF0sXHJcblx0XCJsaWdodGdyZXlcIjogWzIxMSwgMjExLCAyMTFdLFxyXG5cdFwibGlnaHRwaW5rXCI6IFsyNTUsIDE4MiwgMTkzXSxcclxuXHRcImxpZ2h0c2FsbW9uXCI6IFsyNTUsIDE2MCwgMTIyXSxcclxuXHRcImxpZ2h0c2VhZ3JlZW5cIjogWzMyLCAxNzgsIDE3MF0sXHJcblx0XCJsaWdodHNreWJsdWVcIjogWzEzNSwgMjA2LCAyNTBdLFxyXG5cdFwibGlnaHRzbGF0ZWdyYXlcIjogWzExOSwgMTM2LCAxNTNdLFxyXG5cdFwibGlnaHRzbGF0ZWdyZXlcIjogWzExOSwgMTM2LCAxNTNdLFxyXG5cdFwibGlnaHRzdGVlbGJsdWVcIjogWzE3NiwgMTk2LCAyMjJdLFxyXG5cdFwibGlnaHR5ZWxsb3dcIjogWzI1NSwgMjU1LCAyMjRdLFxyXG5cdFwibGltZVwiOiBbMCwgMjU1LCAwXSxcclxuXHRcImxpbWVncmVlblwiOiBbNTAsIDIwNSwgNTBdLFxyXG5cdFwibGluZW5cIjogWzI1MCwgMjQwLCAyMzBdLFxyXG5cdFwibWFnZW50YVwiOiBbMjU1LCAwLCAyNTVdLFxyXG5cdFwibWFyb29uXCI6IFsxMjgsIDAsIDBdLFxyXG5cdFwibWVkaXVtYXF1YW1hcmluZVwiOiBbMTAyLCAyMDUsIDE3MF0sXHJcblx0XCJtZWRpdW1ibHVlXCI6IFswLCAwLCAyMDVdLFxyXG5cdFwibWVkaXVtb3JjaGlkXCI6IFsxODYsIDg1LCAyMTFdLFxyXG5cdFwibWVkaXVtcHVycGxlXCI6IFsxNDcsIDExMiwgMjE5XSxcclxuXHRcIm1lZGl1bXNlYWdyZWVuXCI6IFs2MCwgMTc5LCAxMTNdLFxyXG5cdFwibWVkaXVtc2xhdGVibHVlXCI6IFsxMjMsIDEwNCwgMjM4XSxcclxuXHRcIm1lZGl1bXNwcmluZ2dyZWVuXCI6IFswLCAyNTAsIDE1NF0sXHJcblx0XCJtZWRpdW10dXJxdW9pc2VcIjogWzcyLCAyMDksIDIwNF0sXHJcblx0XCJtZWRpdW12aW9sZXRyZWRcIjogWzE5OSwgMjEsIDEzM10sXHJcblx0XCJtaWRuaWdodGJsdWVcIjogWzI1LCAyNSwgMTEyXSxcclxuXHRcIm1pbnRjcmVhbVwiOiBbMjQ1LCAyNTUsIDI1MF0sXHJcblx0XCJtaXN0eXJvc2VcIjogWzI1NSwgMjI4LCAyMjVdLFxyXG5cdFwibW9jY2FzaW5cIjogWzI1NSwgMjI4LCAxODFdLFxyXG5cdFwibmF2YWpvd2hpdGVcIjogWzI1NSwgMjIyLCAxNzNdLFxyXG5cdFwibmF2eVwiOiBbMCwgMCwgMTI4XSxcclxuXHRcIm9sZGxhY2VcIjogWzI1MywgMjQ1LCAyMzBdLFxyXG5cdFwib2xpdmVcIjogWzEyOCwgMTI4LCAwXSxcclxuXHRcIm9saXZlZHJhYlwiOiBbMTA3LCAxNDIsIDM1XSxcclxuXHRcIm9yYW5nZVwiOiBbMjU1LCAxNjUsIDBdLFxyXG5cdFwib3JhbmdlcmVkXCI6IFsyNTUsIDY5LCAwXSxcclxuXHRcIm9yY2hpZFwiOiBbMjE4LCAxMTIsIDIxNF0sXHJcblx0XCJwYWxlZ29sZGVucm9kXCI6IFsyMzgsIDIzMiwgMTcwXSxcclxuXHRcInBhbGVncmVlblwiOiBbMTUyLCAyNTEsIDE1Ml0sXHJcblx0XCJwYWxldHVycXVvaXNlXCI6IFsxNzUsIDIzOCwgMjM4XSxcclxuXHRcInBhbGV2aW9sZXRyZWRcIjogWzIxOSwgMTEyLCAxNDddLFxyXG5cdFwicGFwYXlhd2hpcFwiOiBbMjU1LCAyMzksIDIxM10sXHJcblx0XCJwZWFjaHB1ZmZcIjogWzI1NSwgMjE4LCAxODVdLFxyXG5cdFwicGVydVwiOiBbMjA1LCAxMzMsIDYzXSxcclxuXHRcInBpbmtcIjogWzI1NSwgMTkyLCAyMDNdLFxyXG5cdFwicGx1bVwiOiBbMjIxLCAxNjAsIDIyMV0sXHJcblx0XCJwb3dkZXJibHVlXCI6IFsxNzYsIDIyNCwgMjMwXSxcclxuXHRcInB1cnBsZVwiOiBbMTI4LCAwLCAxMjhdLFxyXG5cdFwicmViZWNjYXB1cnBsZVwiOiBbMTAyLCA1MSwgMTUzXSxcclxuXHRcInJlZFwiOiBbMjU1LCAwLCAwXSxcclxuXHRcInJvc3licm93blwiOiBbMTg4LCAxNDMsIDE0M10sXHJcblx0XCJyb3lhbGJsdWVcIjogWzY1LCAxMDUsIDIyNV0sXHJcblx0XCJzYWRkbGVicm93blwiOiBbMTM5LCA2OSwgMTldLFxyXG5cdFwic2FsbW9uXCI6IFsyNTAsIDEyOCwgMTE0XSxcclxuXHRcInNhbmR5YnJvd25cIjogWzI0NCwgMTY0LCA5Nl0sXHJcblx0XCJzZWFncmVlblwiOiBbNDYsIDEzOSwgODddLFxyXG5cdFwic2Vhc2hlbGxcIjogWzI1NSwgMjQ1LCAyMzhdLFxyXG5cdFwic2llbm5hXCI6IFsxNjAsIDgyLCA0NV0sXHJcblx0XCJzaWx2ZXJcIjogWzE5MiwgMTkyLCAxOTJdLFxyXG5cdFwic2t5Ymx1ZVwiOiBbMTM1LCAyMDYsIDIzNV0sXHJcblx0XCJzbGF0ZWJsdWVcIjogWzEwNiwgOTAsIDIwNV0sXHJcblx0XCJzbGF0ZWdyYXlcIjogWzExMiwgMTI4LCAxNDRdLFxyXG5cdFwic2xhdGVncmV5XCI6IFsxMTIsIDEyOCwgMTQ0XSxcclxuXHRcInNub3dcIjogWzI1NSwgMjUwLCAyNTBdLFxyXG5cdFwic3ByaW5nZ3JlZW5cIjogWzAsIDI1NSwgMTI3XSxcclxuXHRcInN0ZWVsYmx1ZVwiOiBbNzAsIDEzMCwgMTgwXSxcclxuXHRcInRhblwiOiBbMjEwLCAxODAsIDE0MF0sXHJcblx0XCJ0ZWFsXCI6IFswLCAxMjgsIDEyOF0sXHJcblx0XCJ0aGlzdGxlXCI6IFsyMTYsIDE5MSwgMjE2XSxcclxuXHRcInRvbWF0b1wiOiBbMjU1LCA5OSwgNzFdLFxyXG5cdFwidHVycXVvaXNlXCI6IFs2NCwgMjI0LCAyMDhdLFxyXG5cdFwidmlvbGV0XCI6IFsyMzgsIDEzMCwgMjM4XSxcclxuXHRcIndoZWF0XCI6IFsyNDUsIDIyMiwgMTc5XSxcclxuXHRcIndoaXRlXCI6IFsyNTUsIDI1NSwgMjU1XSxcclxuXHRcIndoaXRlc21va2VcIjogWzI0NSwgMjQ1LCAyNDVdLFxyXG5cdFwieWVsbG93XCI6IFsyNTUsIDI1NSwgMF0sXHJcblx0XCJ5ZWxsb3dncmVlblwiOiBbMTU0LCAyMDUsIDUwXVxyXG59O1xyXG4iLCIvKiogQG1vZHVsZSAgY29sb3Itbm9ybWFsaXplICovXHJcblxyXG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciByZ2JhID0gcmVxdWlyZSgnY29sb3ItcmdiYScpXHJcbnZhciBjbGFtcCA9IHJlcXVpcmUoJ2NsYW1wJylcclxudmFyIGR0eXBlID0gcmVxdWlyZSgnZHR5cGUnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBub3JtYWxpemUgKGNvbG9yLCB0eXBlKSB7XHJcblx0aWYgKHR5cGUgPT09ICdmbG9hdCcgfHwgIXR5cGUpIHR5cGUgPSAnYXJyYXknXHJcblx0aWYgKHR5cGUgPT09ICd1aW50JykgdHlwZSA9ICd1aW50OCdcclxuXHRpZiAodHlwZSA9PT0gJ3VpbnRfY2xhbXBlZCcpIHR5cGUgPSAndWludDhfY2xhbXBlZCdcclxuXHR2YXIgQ3RvciA9IGR0eXBlKHR5cGUpXHJcblx0dmFyIG91dHB1dCA9IG5ldyBDdG9yKDQpXHJcblxyXG5cdHZhciBub3JtYWxpemUgPSB0eXBlICE9PSAndWludDgnICYmIHR5cGUgIT09ICd1aW50OF9jbGFtcGVkJ1xyXG5cclxuXHQvLyBhdHRlbXB0IHRvIHBhcnNlIG5vbi1hcnJheSBhcmd1bWVudHNcclxuXHRpZiAoIWNvbG9yLmxlbmd0aCB8fCB0eXBlb2YgY29sb3IgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRjb2xvciA9IHJnYmEoY29sb3IpXHJcblx0XHRjb2xvclswXSAvPSAyNTVcclxuXHRcdGNvbG9yWzFdIC89IDI1NVxyXG5cdFx0Y29sb3JbMl0gLz0gMjU1XHJcblx0fVxyXG5cclxuXHQvLyAwLCAxIGFyZSBwb3NzaWJsZSBjb250cmFkaWN0b3J5IHZhbHVlcyBmb3IgQXJyYXlzOlxyXG5cdC8vIFsxLDEsMV0gaW5wdXQgZ2l2ZXMgWzEsMSwxXSBvdXRwdXQgaW5zdGVhZCBvZiBbMS8yNTUsMS8yNTUsMS8yNTVdLCB3aGljaCBtYXkgYmUgY29sbGlzaW9uIGlmIGlucHV0IGlzIG1lYW50IHRvIGJlIHVpbnQuXHJcblx0Ly8gY29udmVydGluZyBbMSwxLDFdIHRvIFsxLzI1NSwxLzI1NSwxLzI1NV0gaW4gY2FzZSBvZiBmbG9hdCBpbnB1dCBnaXZlcyBsYXJnZXIgbWlzdGFrZSBzaW5jZSBbMSwxLDFdIGZsb2F0IGlzIGZyZXF1ZW50IGVkZ2UgdmFsdWUsIHdoZXJlYXMgWzAsMSwxXSwgWzEsMSwxXSBldGMuIHVpbnQgaW5wdXRzIGFyZSByZWxhdGl2ZWx5IHJhcmVcclxuXHRpZiAoaXNJbnQoY29sb3IpKSB7XHJcblx0XHRvdXRwdXRbMF0gPSBjb2xvclswXVxyXG5cdFx0b3V0cHV0WzFdID0gY29sb3JbMV1cclxuXHRcdG91dHB1dFsyXSA9IGNvbG9yWzJdXHJcblx0XHRvdXRwdXRbM10gPSBjb2xvclszXSAhPSBudWxsID8gY29sb3JbM10gOiAyNTVcclxuXHJcblx0XHRpZiAobm9ybWFsaXplKSB7XHJcblx0XHRcdG91dHB1dFswXSAvPSAyNTVcclxuXHRcdFx0b3V0cHV0WzFdIC89IDI1NVxyXG5cdFx0XHRvdXRwdXRbMl0gLz0gMjU1XHJcblx0XHRcdG91dHB1dFszXSAvPSAyNTVcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gb3V0cHV0XHJcblx0fVxyXG5cclxuXHRpZiAoIW5vcm1hbGl6ZSkge1xyXG5cdFx0b3V0cHV0WzBdID0gY2xhbXAoTWF0aC5mbG9vcihjb2xvclswXSAqIDI1NSksIDAsIDI1NSlcclxuXHRcdG91dHB1dFsxXSA9IGNsYW1wKE1hdGguZmxvb3IoY29sb3JbMV0gKiAyNTUpLCAwLCAyNTUpXHJcblx0XHRvdXRwdXRbMl0gPSBjbGFtcChNYXRoLmZsb29yKGNvbG9yWzJdICogMjU1KSwgMCwgMjU1KVxyXG5cdFx0b3V0cHV0WzNdID0gY29sb3JbM10gPT0gbnVsbCA/IDI1NSA6IGNsYW1wKE1hdGguZmxvb3IoY29sb3JbM10gKiAyNTUpLCAwLCAyNTUpXHJcblx0fSBlbHNlIHtcclxuXHRcdG91dHB1dFswXSA9IGNvbG9yWzBdXHJcblx0XHRvdXRwdXRbMV0gPSBjb2xvclsxXVxyXG5cdFx0b3V0cHV0WzJdID0gY29sb3JbMl1cclxuXHRcdG91dHB1dFszXSA9IGNvbG9yWzNdICE9IG51bGwgPyBjb2xvclszXSA6IDFcclxuXHR9XHJcblxyXG5cdHJldHVybiBvdXRwdXRcclxufVxyXG5cclxuZnVuY3Rpb24gaXNJbnQoY29sb3IpIHtcclxuXHRpZiAoY29sb3IgaW5zdGFuY2VvZiBVaW50OEFycmF5IHx8IGNvbG9yIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpIHJldHVybiB0cnVlXHJcblxyXG5cdGlmIChBcnJheS5pc0FycmF5KGNvbG9yKSAmJlxyXG5cdFx0KGNvbG9yWzBdID4gMSB8fCBjb2xvclswXSA9PT0gMCkgJiZcclxuXHRcdChjb2xvclsxXSA+IDEgfHwgY29sb3JbMV0gPT09IDApICYmXHJcblx0XHQoY29sb3JbMl0gPiAxIHx8IGNvbG9yWzJdID09PSAwKSAmJlxyXG5cdFx0KCFjb2xvclszXSB8fCBjb2xvclszXSA+IDEpXHJcblx0KSByZXR1cm4gdHJ1ZVxyXG5cclxuXHRyZXR1cm4gZmFsc2VcclxufVxyXG4iLCIvKipcclxuICogQG1vZHVsZSBjb2xvci1wYXJzZVxyXG4gKi9cclxuXHJcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIG5hbWVzID0gcmVxdWlyZSgnY29sb3ItbmFtZScpXHJcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJ2lzLXBsYWluLW9iaicpXHJcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnZGVmaW5lZCcpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHBhcnNlXHJcblxyXG4vKipcclxuICogQmFzZSBodWVzXHJcbiAqIGh0dHA6Ly9kZXYudzMub3JnL2Nzc3dnL2Nzcy1jb2xvci8jdHlwZWRlZi1uYW1lZC1odWVcclxuICovXHJcbi8vRklYTUU6IHVzZSBleHRlcm5hbCBodWUgZGV0ZWN0b3JcclxudmFyIGJhc2VIdWVzID0ge1xyXG5cdHJlZDogMCxcclxuXHRvcmFuZ2U6IDYwLFxyXG5cdHllbGxvdzogMTIwLFxyXG5cdGdyZWVuOiAxODAsXHJcblx0Ymx1ZTogMjQwLFxyXG5cdHB1cnBsZTogMzAwXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBQYXJzZSBjb2xvciBmcm9tIHRoZSBzdHJpbmcgcGFzc2VkXHJcbiAqXHJcbiAqIEByZXR1cm4ge09iamVjdH0gQSBzcGFjZSBpbmRpY2F0b3IgYHNwYWNlYCwgYW4gYXJyYXkgYHZhbHVlc2AgYW5kIGBhbHBoYWBcclxuICovXHJcbmZ1bmN0aW9uIHBhcnNlIChjc3RyKSB7XHJcblx0dmFyIG0sIHBhcnRzID0gW10sIGFscGhhID0gMSwgc3BhY2VcclxuXHJcblx0aWYgKHR5cGVvZiBjc3RyID09PSAnc3RyaW5nJykge1xyXG5cdFx0Ly9rZXl3b3JkXHJcblx0XHRpZiAobmFtZXNbY3N0cl0pIHtcclxuXHRcdFx0cGFydHMgPSBuYW1lc1tjc3RyXS5zbGljZSgpXHJcblx0XHRcdHNwYWNlID0gJ3JnYidcclxuXHRcdH1cclxuXHJcblx0XHQvL3Jlc2VydmVkIHdvcmRzXHJcblx0XHRlbHNlIGlmIChjc3RyID09PSAndHJhbnNwYXJlbnQnKSB7XHJcblx0XHRcdGFscGhhID0gMFxyXG5cdFx0XHRzcGFjZSA9ICdyZ2InXHJcblx0XHRcdHBhcnRzID0gWzAsMCwwXVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vaGV4XHJcblx0XHRlbHNlIGlmICgvXiNbQS1GYS1mMC05XSskLy50ZXN0KGNzdHIpKSB7XHJcblx0XHRcdHZhciBiYXNlID0gY3N0ci5zbGljZSgxKVxyXG5cdFx0XHR2YXIgc2l6ZSA9IGJhc2UubGVuZ3RoXHJcblx0XHRcdHZhciBpc1Nob3J0ID0gc2l6ZSA8PSA0XHJcblx0XHRcdGFscGhhID0gMVxyXG5cclxuXHRcdFx0aWYgKGlzU2hvcnQpIHtcclxuXHRcdFx0XHRwYXJ0cyA9IFtcclxuXHRcdFx0XHRcdHBhcnNlSW50KGJhc2VbMF0gKyBiYXNlWzBdLCAxNiksXHJcblx0XHRcdFx0XHRwYXJzZUludChiYXNlWzFdICsgYmFzZVsxXSwgMTYpLFxyXG5cdFx0XHRcdFx0cGFyc2VJbnQoYmFzZVsyXSArIGJhc2VbMl0sIDE2KVxyXG5cdFx0XHRcdF1cclxuXHRcdFx0XHRpZiAoc2l6ZSA9PT0gNCkge1xyXG5cdFx0XHRcdFx0YWxwaGEgPSBwYXJzZUludChiYXNlWzNdICsgYmFzZVszXSwgMTYpIC8gMjU1XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdHBhcnRzID0gW1xyXG5cdFx0XHRcdFx0cGFyc2VJbnQoYmFzZVswXSArIGJhc2VbMV0sIDE2KSxcclxuXHRcdFx0XHRcdHBhcnNlSW50KGJhc2VbMl0gKyBiYXNlWzNdLCAxNiksXHJcblx0XHRcdFx0XHRwYXJzZUludChiYXNlWzRdICsgYmFzZVs1XSwgMTYpXHJcblx0XHRcdFx0XVxyXG5cdFx0XHRcdGlmIChzaXplID09PSA4KSB7XHJcblx0XHRcdFx0XHRhbHBoYSA9IHBhcnNlSW50KGJhc2VbNl0gKyBiYXNlWzddLCAxNikgLyAyNTVcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmICghcGFydHNbMF0pIHBhcnRzWzBdID0gMFxyXG5cdFx0XHRpZiAoIXBhcnRzWzFdKSBwYXJ0c1sxXSA9IDBcclxuXHRcdFx0aWYgKCFwYXJ0c1syXSkgcGFydHNbMl0gPSAwXHJcblxyXG5cdFx0XHRzcGFjZSA9ICdyZ2InXHJcblx0XHR9XHJcblxyXG5cdFx0Ly9jb2xvciBzcGFjZVxyXG5cdFx0ZWxzZSBpZiAobSA9IC9eKCg/OnJnYnxoc1tsdmJdfGh3YnxjbXlrP3x4eVt6eV18Z3JheXxsYWJ8bGNodT92P3xbbHlddXZ8bG1zKWE/KVxccypcXCgoW15cXCldKilcXCkvLmV4ZWMoY3N0cikpIHtcclxuXHRcdFx0dmFyIG5hbWUgPSBtWzFdXHJcblx0XHRcdHZhciBiYXNlID0gbmFtZS5yZXBsYWNlKC9hJC8sICcnKVxyXG5cdFx0XHRzcGFjZSA9IGJhc2VcclxuXHRcdFx0dmFyIHNpemUgPSBiYXNlID09PSAnY215aycgPyA0IDogYmFzZSA9PT0gJ2dyYXknID8gMSA6IDNcclxuXHRcdFx0cGFydHMgPSBtWzJdLnRyaW0oKVxyXG5cdFx0XHRcdC5zcGxpdCgvXFxzKixcXHMqLylcclxuXHRcdFx0XHQubWFwKGZ1bmN0aW9uICh4LCBpKSB7XHJcblx0XHRcdFx0XHQvLzxwZXJjZW50YWdlPlxyXG5cdFx0XHRcdFx0aWYgKC8lJC8udGVzdCh4KSkge1xyXG5cdFx0XHRcdFx0XHQvL2FscGhhXHJcblx0XHRcdFx0XHRcdGlmIChpID09PSBzaXplKVx0cmV0dXJuIHBhcnNlRmxvYXQoeCkgLyAxMDBcclxuXHRcdFx0XHRcdFx0Ly9yZ2JcclxuXHRcdFx0XHRcdFx0aWYgKGJhc2UgPT09ICdyZ2InKSByZXR1cm4gcGFyc2VGbG9hdCh4KSAqIDI1NSAvIDEwMFxyXG5cdFx0XHRcdFx0XHRyZXR1cm4gcGFyc2VGbG9hdCh4KVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Ly9odWVcclxuXHRcdFx0XHRcdGVsc2UgaWYgKGJhc2VbaV0gPT09ICdoJykge1xyXG5cdFx0XHRcdFx0XHQvLzxkZWc+XHJcblx0XHRcdFx0XHRcdGlmICgvZGVnJC8udGVzdCh4KSkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBwYXJzZUZsb2F0KHgpXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0Ly88YmFzZS1odWU+XHJcblx0XHRcdFx0XHRcdGVsc2UgaWYgKGJhc2VIdWVzW3hdICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gYmFzZUh1ZXNbeF1cclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQoeClcclxuXHRcdFx0XHR9KVxyXG5cclxuXHRcdFx0aWYgKG5hbWUgPT09IGJhc2UpIHBhcnRzLnB1c2goMSlcclxuXHRcdFx0YWxwaGEgPSBwYXJ0c1tzaXplXSA9PT0gdW5kZWZpbmVkID8gMSA6IHBhcnRzW3NpemVdXHJcblx0XHRcdHBhcnRzID0gcGFydHMuc2xpY2UoMCwgc2l6ZSlcclxuXHRcdH1cclxuXHJcblx0XHQvL25hbWVkIGNoYW5uZWxzIGNhc2VcclxuXHRcdGVsc2UgaWYgKGNzdHIubGVuZ3RoID4gMTAgJiYgL1swLTldKD86XFxzfFxcLykvLnRlc3QoY3N0cikpIHtcclxuXHRcdFx0cGFydHMgPSBjc3RyLm1hdGNoKC8oWzAtOV0rKS9nKS5tYXAoZnVuY3Rpb24gKHZhbHVlKSB7XHJcblx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQodmFsdWUpXHJcblx0XHRcdH0pXHJcblxyXG5cdFx0XHRzcGFjZSA9IGNzdHIubWF0Y2goLyhbYS16XSkvaWcpLmpvaW4oJycpLnRvTG93ZXJDYXNlKClcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8vbnVtZXJpYyBjYXNlXHJcblx0ZWxzZSBpZiAoIWlzTmFOKGNzdHIpKSB7XHJcblx0XHRzcGFjZSA9ICdyZ2InXHJcblx0XHRwYXJ0cyA9IFtjc3RyID4+PiAxNiwgKGNzdHIgJiAweDAwZmYwMCkgPj4+IDgsIGNzdHIgJiAweDAwMDBmZl1cclxuXHR9XHJcblxyXG5cdC8vb2JqZWN0IGNhc2UgLSBkZXRlY3RzIGNzcyBjYXNlcyBvZiByZ2IgYW5kIGhzbFxyXG5cdGVsc2UgaWYgKGlzT2JqZWN0KGNzdHIpKSB7XHJcblx0XHR2YXIgciA9IGRlZmluZWQoY3N0ci5yLCBjc3RyLnJlZCwgY3N0ci5SLCBudWxsKVxyXG5cclxuXHRcdGlmIChyICE9PSBudWxsKSB7XHJcblx0XHRcdHNwYWNlID0gJ3JnYidcclxuXHRcdFx0cGFydHMgPSBbXHJcblx0XHRcdFx0cixcclxuXHRcdFx0XHRkZWZpbmVkKGNzdHIuZywgY3N0ci5ncmVlbiwgY3N0ci5HKSxcclxuXHRcdFx0XHRkZWZpbmVkKGNzdHIuYiwgY3N0ci5ibHVlLCBjc3RyLkIpXHJcblx0XHRcdF1cclxuXHRcdH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRzcGFjZSA9ICdoc2wnXHJcblx0XHRcdHBhcnRzID0gW1xyXG5cdFx0XHRcdGRlZmluZWQoY3N0ci5oLCBjc3RyLmh1ZSwgY3N0ci5IKSxcclxuXHRcdFx0XHRkZWZpbmVkKGNzdHIucywgY3N0ci5zYXR1cmF0aW9uLCBjc3RyLlMpLFxyXG5cdFx0XHRcdGRlZmluZWQoY3N0ci5sLCBjc3RyLmxpZ2h0bmVzcywgY3N0ci5MLCBjc3RyLmIsIGNzdHIuYnJpZ2h0bmVzcylcclxuXHRcdFx0XVxyXG5cdFx0fVxyXG5cclxuXHRcdGFscGhhID0gZGVmaW5lZChjc3RyLmEsIGNzdHIuYWxwaGEsIGNzdHIub3BhY2l0eSwgMSlcclxuXHJcblx0XHRpZiAoY3N0ci5vcGFjaXR5ICE9IG51bGwpIGFscGhhIC89IDEwMFxyXG5cdH1cclxuXHJcblx0Ly9hcnJheVxyXG5cdGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY3N0cikgfHwgZ2xvYmFsLkFycmF5QnVmZmVyICYmIEFycmF5QnVmZmVyLmlzVmlldyAmJiBBcnJheUJ1ZmZlci5pc1ZpZXcoY3N0cikpIHtcclxuXHRcdHBhcnRzID0gW2NzdHJbMF0sIGNzdHJbMV0sIGNzdHJbMl1dXHJcblx0XHRzcGFjZSA9ICdyZ2InXHJcblx0XHRhbHBoYSA9IGNzdHIubGVuZ3RoID09PSA0ID8gY3N0clszXSA6IDFcclxuXHR9XHJcblxyXG5cdHJldHVybiB7XHJcblx0XHRzcGFjZTogc3BhY2UsXHJcblx0XHR2YWx1ZXM6IHBhcnRzLFxyXG5cdFx0YWxwaGE6IGFscGhhXHJcblx0fVxyXG59XHJcbiIsIi8qKiBAbW9kdWxlICBjb2xvci1yZ2JhICovXHJcblxyXG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBwYXJzZSA9IHJlcXVpcmUoJ2NvbG9yLXBhcnNlJylcclxudmFyIGhzbCA9IHJlcXVpcmUoJ2NvbG9yLXNwYWNlL2hzbCcpXHJcbnZhciBjbGFtcCA9IHJlcXVpcmUoJ2NsYW1wJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcmdiYSAoY29sb3IpIHtcclxuXHR2YXIgdmFsdWVzLCBpLCBsXHJcblxyXG5cdC8vYXR0ZW1wdCB0byBwYXJzZSBub24tYXJyYXkgYXJndW1lbnRzXHJcblx0dmFyIHBhcnNlZCA9IHBhcnNlKGNvbG9yKVxyXG5cclxuXHRpZiAoIXBhcnNlZC5zcGFjZSkgcmV0dXJuIFtdXHJcblxyXG5cdHZhbHVlcyA9IEFycmF5KDMpXHJcblx0dmFsdWVzWzBdID0gY2xhbXAocGFyc2VkLnZhbHVlc1swXSwgMCwgMjU1KVxyXG5cdHZhbHVlc1sxXSA9IGNsYW1wKHBhcnNlZC52YWx1ZXNbMV0sIDAsIDI1NSlcclxuXHR2YWx1ZXNbMl0gPSBjbGFtcChwYXJzZWQudmFsdWVzWzJdLCAwLCAyNTUpXHJcblxyXG5cdGlmIChwYXJzZWQuc3BhY2VbMF0gPT09ICdoJykge1xyXG5cdFx0dmFsdWVzID0gaHNsLnJnYih2YWx1ZXMpXHJcblx0fVxyXG5cclxuXHR2YWx1ZXMucHVzaChjbGFtcChwYXJzZWQuYWxwaGEsIDAsIDEpKVxyXG5cclxuXHRyZXR1cm4gdmFsdWVzXHJcbn1cclxuIiwiLyoqXG4gKiBAbW9kdWxlIGNvbG9yLXNwYWNlL2hzbFxuICovXG4ndXNlIHN0cmljdCdcblxudmFyIHJnYiA9IHJlcXVpcmUoJy4vcmdiJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRuYW1lOiAnaHNsJyxcblx0bWluOiBbMCwwLDBdLFxuXHRtYXg6IFszNjAsMTAwLDEwMF0sXG5cdGNoYW5uZWw6IFsnaHVlJywgJ3NhdHVyYXRpb24nLCAnbGlnaHRuZXNzJ10sXG5cdGFsaWFzOiBbJ0hTTCddLFxuXG5cdHJnYjogZnVuY3Rpb24oaHNsKSB7XG5cdFx0dmFyIGggPSBoc2xbMF0gLyAzNjAsXG5cdFx0XHRcdHMgPSBoc2xbMV0gLyAxMDAsXG5cdFx0XHRcdGwgPSBoc2xbMl0gLyAxMDAsXG5cdFx0XHRcdHQxLCB0MiwgdDMsIHJnYiwgdmFsO1xuXG5cdFx0aWYgKHMgPT09IDApIHtcblx0XHRcdHZhbCA9IGwgKiAyNTU7XG5cdFx0XHRyZXR1cm4gW3ZhbCwgdmFsLCB2YWxdO1xuXHRcdH1cblxuXHRcdGlmIChsIDwgMC41KSB7XG5cdFx0XHR0MiA9IGwgKiAoMSArIHMpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHQyID0gbCArIHMgLSBsICogcztcblx0XHR9XG5cdFx0dDEgPSAyICogbCAtIHQyO1xuXG5cdFx0cmdiID0gWzAsIDAsIDBdO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG5cdFx0XHR0MyA9IGggKyAxIC8gMyAqIC0gKGkgLSAxKTtcblx0XHRcdGlmICh0MyA8IDApIHtcblx0XHRcdFx0dDMrKztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKHQzID4gMSkge1xuXHRcdFx0XHR0My0tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoNiAqIHQzIDwgMSkge1xuXHRcdFx0XHR2YWwgPSB0MSArICh0MiAtIHQxKSAqIDYgKiB0Mztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKDIgKiB0MyA8IDEpIHtcblx0XHRcdFx0dmFsID0gdDI7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICgzICogdDMgPCAyKSB7XG5cdFx0XHRcdHZhbCA9IHQxICsgKHQyIC0gdDEpICogKDIgLyAzIC0gdDMpICogNjtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB0MTtcblx0XHRcdH1cblxuXHRcdFx0cmdiW2ldID0gdmFsICogMjU1O1xuXHRcdH1cblxuXHRcdHJldHVybiByZ2I7XG5cdH1cbn07XG5cblxuLy9leHRlbmQgcmdiXG5yZ2IuaHNsID0gZnVuY3Rpb24ocmdiKSB7XG5cdHZhciByID0gcmdiWzBdLzI1NSxcblx0XHRcdGcgPSByZ2JbMV0vMjU1LFxuXHRcdFx0YiA9IHJnYlsyXS8yNTUsXG5cdFx0XHRtaW4gPSBNYXRoLm1pbihyLCBnLCBiKSxcblx0XHRcdG1heCA9IE1hdGgubWF4KHIsIGcsIGIpLFxuXHRcdFx0ZGVsdGEgPSBtYXggLSBtaW4sXG5cdFx0XHRoLCBzLCBsO1xuXG5cdGlmIChtYXggPT09IG1pbikge1xuXHRcdGggPSAwO1xuXHR9XG5cdGVsc2UgaWYgKHIgPT09IG1heCkge1xuXHRcdGggPSAoZyAtIGIpIC8gZGVsdGE7XG5cdH1cblx0ZWxzZSBpZiAoZyA9PT0gbWF4KSB7XG5cdFx0aCA9IDIgKyAoYiAtIHIpIC8gZGVsdGE7XG5cdH1cblx0ZWxzZSBpZiAoYiA9PT0gbWF4KSB7XG5cdFx0aCA9IDQgKyAociAtIGcpLyBkZWx0YTtcblx0fVxuXG5cdGggPSBNYXRoLm1pbihoICogNjAsIDM2MCk7XG5cblx0aWYgKGggPCAwKSB7XG5cdFx0aCArPSAzNjA7XG5cdH1cblxuXHRsID0gKG1pbiArIG1heCkgLyAyO1xuXG5cdGlmIChtYXggPT09IG1pbikge1xuXHRcdHMgPSAwO1xuXHR9XG5cdGVsc2UgaWYgKGwgPD0gMC41KSB7XG5cdFx0cyA9IGRlbHRhIC8gKG1heCArIG1pbik7XG5cdH1cblx0ZWxzZSB7XG5cdFx0cyA9IGRlbHRhIC8gKDIgLSBtYXggLSBtaW4pO1xuXHR9XG5cblx0cmV0dXJuIFtoLCBzICogMTAwLCBsICogMTAwXTtcbn07XG4iLCIvKipcbiAqIFJHQiBzcGFjZS5cbiAqXG4gKiBAbW9kdWxlICBjb2xvci1zcGFjZS9yZ2JcbiAqL1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRuYW1lOiAncmdiJyxcblx0bWluOiBbMCwwLDBdLFxuXHRtYXg6IFsyNTUsMjU1LDI1NV0sXG5cdGNoYW5uZWw6IFsncmVkJywgJ2dyZWVuJywgJ2JsdWUnXSxcblx0YWxpYXM6IFsnUkdCJ11cbn07XG4iLCJtb2R1bGUuZXhwb3J0cz17XG5cdFwiamV0XCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMTMxXX0se1wiaW5kZXhcIjowLjEyNSxcInJnYlwiOlswLDYwLDE3MF19LHtcImluZGV4XCI6MC4zNzUsXCJyZ2JcIjpbNSwyNTUsMjU1XX0se1wiaW5kZXhcIjowLjYyNSxcInJnYlwiOlsyNTUsMjU1LDBdfSx7XCJpbmRleFwiOjAuODc1LFwicmdiXCI6WzI1MCwwLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMTI4LDAsMF19XSxcblxuXHRcImhzdlwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMjU1LDAsMF19LHtcImluZGV4XCI6MC4xNjksXCJyZ2JcIjpbMjUzLDI1NSwyXX0se1wiaW5kZXhcIjowLjE3MyxcInJnYlwiOlsyNDcsMjU1LDJdfSx7XCJpbmRleFwiOjAuMzM3LFwicmdiXCI6WzAsMjUyLDRdfSx7XCJpbmRleFwiOjAuMzQxLFwicmdiXCI6WzAsMjUyLDEwXX0se1wiaW5kZXhcIjowLjUwNixcInJnYlwiOlsxLDI0OSwyNTVdfSx7XCJpbmRleFwiOjAuNjcxLFwicmdiXCI6WzIsMCwyNTNdfSx7XCJpbmRleFwiOjAuNjc1LFwicmdiXCI6WzgsMCwyNTNdfSx7XCJpbmRleFwiOjAuODM5LFwicmdiXCI6WzI1NSwwLDI1MV19LHtcImluZGV4XCI6MC44NDMsXCJyZ2JcIjpbMjU1LDAsMjQ1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwwLDZdfV0sXG5cblx0XCJob3RcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjMsXCJyZ2JcIjpbMjMwLDAsMF19LHtcImluZGV4XCI6MC42LFwicmdiXCI6WzI1NSwyMTAsMF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDI1NV19XSxcblxuXHRcImNvb2xcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMjU1LDI1NV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMCwyNTVdfV0sXG5cblx0XCJzcHJpbmdcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzI1NSwwLDI1NV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDBdfV0sXG5cblx0XCJzdW1tZXJcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMTI4LDEwMl19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDEwMl19XSxcblxuXHRcImF1dHVtblwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMjU1LDAsMF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDBdfV0sXG5cblx0XCJ3aW50ZXJcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwyNTVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMCwyNTUsMTI4XX1dLFxuXG5cdFwiYm9uZVwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDBdfSx7XCJpbmRleFwiOjAuMzc2LFwicmdiXCI6Wzg0LDg0LDExNl19LHtcImluZGV4XCI6MC43NTMsXCJyZ2JcIjpbMTY5LDIwMCwyMDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwyNTVdfV0sXG5cblx0XCJjb3BwZXJcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjgwNCxcInJnYlwiOlsyNTUsMTYwLDEwMl19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMTk5LDEyN119XSxcblxuXHRcImdyZXlzXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDI1NV19XSxcblxuXHRcInlpZ25idVwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbOCwyOSw4OF19LHtcImluZGV4XCI6MC4xMjUsXCJyZ2JcIjpbMzcsNTIsMTQ4XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzM0LDk0LDE2OF19LHtcImluZGV4XCI6MC4zNzUsXCJyZ2JcIjpbMjksMTQ1LDE5Ml19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzY1LDE4MiwxOTZdfSx7XCJpbmRleFwiOjAuNjI1LFwicmdiXCI6WzEyNywyMDUsMTg3XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzE5OSwyMzMsMTgwXX0se1wiaW5kZXhcIjowLjg3NSxcInJnYlwiOlsyMzcsMjQ4LDIxN119LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDIxN119XSxcblxuXHRcImdyZWVuc1wiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCw2OCwyN119LHtcImluZGV4XCI6MC4xMjUsXCJyZ2JcIjpbMCwxMDksNDRdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMzUsMTM5LDY5XX0se1wiaW5kZXhcIjowLjM3NSxcInJnYlwiOls2NSwxNzEsOTNdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxMTYsMTk2LDExOF19LHtcImluZGV4XCI6MC42MjUsXCJyZ2JcIjpbMTYxLDIxNywxNTVdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTk5LDIzMywxOTJdfSx7XCJpbmRleFwiOjAuODc1LFwicmdiXCI6WzIyOSwyNDUsMjI0XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI0NywyNTIsMjQ1XX1dLFxuXG5cdFwieWlvcnJkXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlsxMjgsMCwzOF19LHtcImluZGV4XCI6MC4xMjUsXCJyZ2JcIjpbMTg5LDAsMzhdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMjI3LDI2LDI4XX0se1wiaW5kZXhcIjowLjM3NSxcInJnYlwiOlsyNTIsNzgsNDJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsyNTMsMTQxLDYwXX0se1wiaW5kZXhcIjowLjYyNSxcInJnYlwiOlsyNTQsMTc4LDc2XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI1NCwyMTcsMTE4XX0se1wiaW5kZXhcIjowLjg3NSxcInJnYlwiOlsyNTUsMjM3LDE2MF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDIwNF19XSxcblxuXHRcImJsdWVyZWRcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwyNTVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDAsMF19XSxcblxuXHRcInJkYnVcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzUsMTAsMTcyXX0se1wiaW5kZXhcIjowLjM1LFwicmdiXCI6WzEwNiwxMzcsMjQ3XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTkwLDE5MCwxOTBdfSx7XCJpbmRleFwiOjAuNixcInJnYlwiOlsyMjAsMTcwLDEzMl19LHtcImluZGV4XCI6MC43LFwicmdiXCI6WzIzMCwxNDUsOTBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMTc4LDEwLDI4XX1dLFxuXG5cdFwicGljbmljXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMjU1XX0se1wiaW5kZXhcIjowLjEsXCJyZ2JcIjpbNTEsMTUzLDI1NV19LHtcImluZGV4XCI6MC4yLFwicmdiXCI6WzEwMiwyMDQsMjU1XX0se1wiaW5kZXhcIjowLjMsXCJyZ2JcIjpbMTUzLDIwNCwyNTVdfSx7XCJpbmRleFwiOjAuNCxcInJnYlwiOlsyMDQsMjA0LDI1NV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzI1NSwyNTUsMjU1XX0se1wiaW5kZXhcIjowLjYsXCJyZ2JcIjpbMjU1LDIwNCwyNTVdfSx7XCJpbmRleFwiOjAuNyxcInJnYlwiOlsyNTUsMTUzLDI1NV19LHtcImluZGV4XCI6MC44LFwicmdiXCI6WzI1NSwxMDIsMjA0XX0se1wiaW5kZXhcIjowLjksXCJyZ2JcIjpbMjU1LDEwMiwxMDJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDAsMF19XSxcblxuXHRcInJhaW5ib3dcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzE1MCwwLDkwXX0se1wiaW5kZXhcIjowLjEyNSxcInJnYlwiOlswLDAsMjAwXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzAsMjUsMjU1XX0se1wiaW5kZXhcIjowLjM3NSxcInJnYlwiOlswLDE1MiwyNTVdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls0NCwyNTUsMTUwXX0se1wiaW5kZXhcIjowLjYyNSxcInJnYlwiOlsxNTEsMjU1LDBdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjU1LDIzNCwwXX0se1wiaW5kZXhcIjowLjg3NSxcInJnYlwiOlsyNTUsMTExLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDAsMF19XSxcblxuXHRcInBvcnRsYW5kXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlsxMiw1MSwxMzFdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTAsMTM2LDE4Nl19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzI0MiwyMTEsNTZdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjQyLDE0Myw1Nl19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyMTcsMzAsMzBdfV0sXG5cblx0XCJibGFja2JvZHlcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjIsXCJyZ2JcIjpbMjMwLDAsMF19LHtcImluZGV4XCI6MC40LFwicmdiXCI6WzIzMCwyMTAsMF19LHtcImluZGV4XCI6MC43LFwicmdiXCI6WzI1NSwyNTUsMjU1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzE2MCwyMDAsMjU1XX1dLFxuXG5cdFwiZWFydGhcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwxMzBdfSx7XCJpbmRleFwiOjAuMSxcInJnYlwiOlswLDE4MCwxODBdfSx7XCJpbmRleFwiOjAuMixcInJnYlwiOls0MCwyMTAsNDBdfSx7XCJpbmRleFwiOjAuNCxcInJnYlwiOlsyMzAsMjMwLDUwXX0se1wiaW5kZXhcIjowLjYsXCJyZ2JcIjpbMTIwLDcwLDIwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwyNTUsMjU1XX1dLFxuXG5cdFwiZWxlY3RyaWNcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjE1LFwicmdiXCI6WzMwLDAsMTAwXX0se1wiaW5kZXhcIjowLjQsXCJyZ2JcIjpbMTIwLDAsMTAwXX0se1wiaW5kZXhcIjowLjYsXCJyZ2JcIjpbMTYwLDkwLDBdfSx7XCJpbmRleFwiOjAuOCxcInJnYlwiOlsyMzAsMjAwLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1MCwyMjBdfV0sXG5cblx0XCJhbHBoYVwiOiBbe1wiaW5kZXhcIjowLCBcInJnYlwiOiBbMjU1LDI1NSwyNTUsMF19LHtcImluZGV4XCI6MSwgXCJyZ2JcIjogWzI1NSwyNTUsMjU1LDFdfV0sXG5cblx0XCJ2aXJpZGlzXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbNjgsMSw4NF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOls3MSw0NCwxMjJdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbNTksODEsMTM5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzQ0LDExMywxNDJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlszMywxNDQsMTQxXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzM5LDE3MywxMjldfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbOTIsMjAwLDk5XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzE3MCwyMjAsNTBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjUzLDIzMSwzN119XSxcblxuXHRcImluZmVybm9cIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsNF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlszMSwxMiw3Ml19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls4NSwxNSwxMDldfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTM2LDM0LDEwNl19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE4Niw1NCw4NV19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMjcsODksNTFdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjQ5LDE0MCwxMF19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyNDksMjAxLDUwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1MiwyNTUsMTY0XX1dLFxuXG5cdFwibWFnbWFcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsNF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsyOCwxNiw2OF19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls3OSwxOCwxMjNdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTI5LDM3LDEyOV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE4MSw1NCwxMjJdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMjI5LDgwLDEwMF19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyNTEsMTM1LDk3XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzI1NCwxOTQsMTM1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1MiwyNTMsMTkxXX1dLFxuXG5cdFwicGxhc21hXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTMsOCwxMzVdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbNzUsMywxNjFdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTI1LDMsMTY4XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzE2OCwzNCwxNTBdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsyMDMsNzAsMTIxXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzIyOSwxMDcsOTNdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjQ4LDE0OCw2NV19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyNTMsMTk1LDQwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI0MCwyNDksMzNdfV0sXG5cblx0XCJ3YXJtXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTI1LDAsMTc5XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzE3MiwwLDE4N119LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsyMTksMCwxNzBdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMjU1LDAsMTMwXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMjU1LDYzLDc0XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzI1NSwxMjMsMF19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyMzQsMTc2LDBdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMTkwLDIyOCwwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzE0NywyNTUsMF19XSxcblxuXHRcImNvb2xcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlsxMjUsMCwxNzldfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMTE2LDAsMjE4XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6Wzk4LDc0LDIzN119LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOls2OCwxNDYsMjMxXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMCwyMDQsMTk3XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzAsMjQ3LDE0Nl19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlswLDI1NSw4OF19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOls0MCwyNTUsOF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsxNDcsMjU1LDBdfV0sXG5cblx0XCJyYWluYm93LXNvZnRcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlsxMjUsMCwxNzldfSx7XCJpbmRleFwiOjAuMSxcInJnYlwiOlsxOTksMCwxODBdfSx7XCJpbmRleFwiOjAuMixcInJnYlwiOlsyNTUsMCwxMjFdfSx7XCJpbmRleFwiOjAuMyxcInJnYlwiOlsyNTUsMTA4LDBdfSx7XCJpbmRleFwiOjAuNCxcInJnYlwiOlsyMjIsMTk0LDBdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxNTAsMjU1LDBdfSx7XCJpbmRleFwiOjAuNixcInJnYlwiOlswLDI1NSw1NV19LHtcImluZGV4XCI6MC43LFwicmdiXCI6WzAsMjQ2LDE1MF19LHtcImluZGV4XCI6MC44LFwicmdiXCI6WzUwLDE2NywyMjJdfSx7XCJpbmRleFwiOjAuOSxcInJnYlwiOlsxMDMsNTEsMjM1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzEyNCwwLDE4Nl19XSxcblxuXHRcImJhdGh5bWV0cnlcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls0MCwyNiw0NF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOls1OSw0OSw5MF19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls2NCw3NiwxMzldfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbNjMsMTEwLDE1MV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzcyLDE0MiwxNThdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbODUsMTc0LDE2M119LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsxMjAsMjA2LDE2M119LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsxODcsMjMwLDE3Ml19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTMsMjU0LDIwNF19XSxcblxuXHRcImNkb21cIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls0NywxNSw2Ml19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOls4NywyMyw4Nl19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsxMzAsMjgsOTldfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTcxLDQxLDk2XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMjA2LDY3LDg2XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzIzMCwxMDYsODRdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjQyLDE0OSwxMDNdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjQ5LDE5MywxMzVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU0LDIzNywxNzZdfV0sXG5cblx0XCJjaGxvcm9waHlsbFwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzE4LDM2LDIwXX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzI1LDYzLDQxXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzI0LDkxLDU5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzEzLDExOSw3Ml19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE4LDE0OCw4MF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOls4MCwxNzMsODldfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTMyLDE5NiwxMjJdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMTc1LDIyMSwxNjJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjE1LDI0OSwyMDhdfV0sXG5cblx0XCJkZW5zaXR5XCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbNTQsMTQsMzZdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbODksMjMsODBdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTEwLDQ1LDEzMl19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxMjAsNzcsMTc4XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTIwLDExMywyMTNdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMTE1LDE1MSwyMjhdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTM0LDE4NSwyMjddfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMTc3LDIxNCwyMjddfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjMwLDI0MSwyNDFdfV0sXG5cblx0XCJmcmVlc3VyZmFjZS1ibHVlXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMzAsNCwxMTBdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbNDcsMTQsMTc2XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzQxLDQ1LDIzNl19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsyNSw5OSwyMTJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls2OCwxMzEsMjAwXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzExNCwxNTYsMTk3XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzE1NywxODEsMjAzXX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzIwMCwyMDgsMjE2XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI0MSwyMzcsMjM2XX1dLFxuXG5cdFwiZnJlZXN1cmZhY2UtcmVkXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbNjAsOSwxOF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsxMDAsMTcsMjddfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTQyLDIwLDI5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzE3Nyw0MywyN119LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE5Miw4Nyw2M119LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMDUsMTI1LDEwNV19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyMTYsMTYyLDE0OF19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMjcsMTk5LDE5M119LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNDEsMjM3LDIzNl19XSxcblxuXHRcIm94eWdlblwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzY0LDUsNV19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsxMDYsNiwxNV19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsxNDQsMjYsN119LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxNjgsNjQsM119LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE4OCwxMDAsNF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMDYsMTM2LDExXX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzIyMCwxNzQsMjVdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjMxLDIxNSw0NF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNDgsMjU0LDEwNV19XSxcblxuXHRcInBhclwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzUxLDIwLDI0XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzkwLDMyLDM1XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzEyOSw0NCwzNF19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxNTksNjgsMjVdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxODIsOTksMTldfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMTk5LDEzNCwyMl19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyMTIsMTcxLDM1XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzIyMSwyMTAsNTRdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjI1LDI1Myw3NV19XSxcblxuXHRcInBoYXNlXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTQ1LDEwNSwxOF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsxODQsNzEsMzhdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTg2LDU4LDExNV19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxNjAsNzEsMTg1XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTEwLDk3LDIxOF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOls1MCwxMjMsMTY0XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzMxLDEzMSwxMTBdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbNzcsMTI5LDM0XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzE0NSwxMDUsMThdfV0sXG5cblx0XCJzYWxpbml0eVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzQyLDI0LDEwOF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlszMyw1MCwxNjJdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTUsOTAsMTQ1XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzQwLDExOCwxMzddfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls1OSwxNDYsMTM1XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6Wzc5LDE3NSwxMjZdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTIwLDIwMywxMDRdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMTkzLDIyMSwxMDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjUzLDIzOSwxNTRdfV0sXG5cblx0XCJ0ZW1wZXJhdHVyZVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzQsMzUsNTFdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMjMsNTEsMTIyXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6Wzg1LDU5LDE1N119LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxMjksNzksMTQzXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTc1LDk1LDEzMF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMjIsMTEyLDEwMV19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyNDksMTQ2LDY2XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzI0OSwxOTYsNjVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjMyLDI1MCw5MV19XSxcblxuXHRcInR1cmJpZGl0eVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzM0LDMxLDI3XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzY1LDUwLDQxXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6Wzk4LDY5LDUyXX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzEzMSw4OSw1N119LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE2MSwxMTIsNTldfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMTg1LDE0MCw2Nl19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyMDIsMTc0LDg4XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzIxNiwyMDksMTI2XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIzMywyNDYsMTcxXX1dLFxuXG5cdFwidmVsb2NpdHktYmx1ZVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzE3LDMyLDY0XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzM1LDUyLDExNl19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsyOSw4MSwxNTZdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMzEsMTEzLDE2Ml19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzUwLDE0NCwxNjldfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbODcsMTczLDE3Nl19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsxNDksMTk2LDE4OV19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMDMsMjIxLDIxMV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTQsMjUxLDIzMF19XSxcblxuXHRcInZlbG9jaXR5LWdyZWVuXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMjMsMzUsMTldfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMjQsNjQsMzhdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTEsOTUsNDVdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMzksMTIzLDM1XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbOTUsMTQ2LDEyXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzE1MiwxNjUsMThdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjAxLDE4Niw2OV19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMzMsMjE2LDEzN119LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjUzLDIwNV19XSxcblxuXHRcImN1YmVoZWxpeFwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjA3LFwicmdiXCI6WzIyLDUsNTldfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbNjAsNCwxMDVdfSx7XCJpbmRleFwiOjAuMixcInJnYlwiOlsxMDksMSwxMzVdfSx7XCJpbmRleFwiOjAuMjcsXCJyZ2JcIjpbMTYxLDAsMTQ3XX0se1wiaW5kZXhcIjowLjMzLFwicmdiXCI6WzIxMCwyLDE0Ml19LHtcImluZGV4XCI6MC40LFwicmdiXCI6WzI1MSwxMSwxMjNdfSx7XCJpbmRleFwiOjAuNDcsXCJyZ2JcIjpbMjU1LDI5LDk3XX0se1wiaW5kZXhcIjowLjUzLFwicmdiXCI6WzI1NSw1NCw2OV19LHtcImluZGV4XCI6MC42LFwicmdiXCI6WzI1NSw4NSw0Nl19LHtcImluZGV4XCI6MC42NyxcInJnYlwiOlsyNTUsMTIwLDM0XX0se1wiaW5kZXhcIjowLjczLFwicmdiXCI6WzI1NSwxNTcsMzddfSx7XCJpbmRleFwiOjAuOCxcInJnYlwiOlsyNDEsMTkxLDU3XX0se1wiaW5kZXhcIjowLjg3LFwicmdiXCI6WzIyNCwyMjAsOTNdfSx7XCJpbmRleFwiOjAuOTMsXCJyZ2JcIjpbMjE4LDI0MSwxNDJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjI3LDI1MywxOThdfV1cbn07XG4iLCIvKlxuICogQmVuIFBvc3RsZXRod2FpdGVcbiAqIEphbnVhcnkgMjAxM1xuICogTGljZW5zZSBNSVRcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JTY2FsZSA9IHJlcXVpcmUoJy4vY29sb3JTY2FsZScpO1xudmFyIGxlcnAgPSByZXF1aXJlKCdsZXJwJylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVDb2xvcm1hcDtcblxuZnVuY3Rpb24gY3JlYXRlQ29sb3JtYXAgKHNwZWMpIHtcbiAgICAvKlxuICAgICAqIERlZmF1bHQgT3B0aW9uc1xuICAgICAqL1xuICAgIHZhciBpbmRpY2llcywgcmdiYSwgZnJvbXJnYmEsIHRvcmdiYSxcbiAgICAgICAgbnN0ZXBzLCBjbWFwLCBjb2xvcm1hcCwgZm9ybWF0LFxuICAgICAgICBuc2hhZGVzLCBjb2xvcnMsIGFscGhhLCBpbmRleCwgaSxcbiAgICAgICAgciA9IFtdLFxuICAgICAgICBnID0gW10sXG4gICAgICAgIGIgPSBbXSxcbiAgICAgICAgYSA9IFtdO1xuXG4gICAgaWYgKCAhc3BlYyApIHNwZWMgPSB7fTtcblxuICAgIG5zaGFkZXMgPSAoc3BlYy5uc2hhZGVzIHx8IDcyKSAtIDE7XG4gICAgZm9ybWF0ID0gc3BlYy5mb3JtYXQgfHwgJ2hleCc7XG5cbiAgICBjb2xvcm1hcCA9IHNwZWMuY29sb3JtYXA7XG4gICAgaWYgKCFjb2xvcm1hcCkgY29sb3JtYXAgPSAnamV0JztcblxuICAgIGlmICh0eXBlb2YgY29sb3JtYXAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbG9ybWFwID0gY29sb3JtYXAudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBpZiAoIWNvbG9yU2NhbGVbY29sb3JtYXBdKSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcihjb2xvcm1hcCArICcgbm90IGEgc3VwcG9ydGVkIGNvbG9yc2NhbGUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNtYXAgPSBjb2xvclNjYWxlW2NvbG9ybWFwXTtcblxuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjb2xvcm1hcCkpIHtcbiAgICAgICAgY21hcCA9IGNvbG9ybWFwLnNsaWNlKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcigndW5zdXBwb3J0ZWQgY29sb3JtYXAgb3B0aW9uJywgY29sb3JtYXApO1xuICAgIH1cblxuICAgIGlmIChjbWFwLmxlbmd0aCA+IG5zaGFkZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgY29sb3JtYXArJyBtYXAgcmVxdWlyZXMgbnNoYWRlcyB0byBiZSBhdCBsZWFzdCBzaXplICcrY21hcC5sZW5ndGhcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoc3BlYy5hbHBoYSkpIHtcblxuICAgICAgICBpZiAodHlwZW9mIHNwZWMuYWxwaGEgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBhbHBoYSA9IFtzcGVjLmFscGhhLCBzcGVjLmFscGhhXTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWxwaGEgPSBbMSwgMV07XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoc3BlYy5hbHBoYS5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgYWxwaGEgPSBbMSwgMV07XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBhbHBoYSA9IHNwZWMuYWxwaGEuc2xpY2UoKTtcbiAgICB9XG5cbiAgICAvLyBtYXAgaW5kZXggcG9pbnRzIGZyb20gMC4uMSB0byAwLi5uLTFcbiAgICBpbmRpY2llcyA9IGNtYXAubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoYy5pbmRleCAqIG5zaGFkZXMpO1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIGFscGhhIGNoYW5uZWwgdG8gdGhlIG1hcFxuICAgIGFscGhhWzBdID0gTWF0aC5taW4oTWF0aC5tYXgoYWxwaGFbMF0sIDApLCAxKTtcbiAgICBhbHBoYVsxXSA9IE1hdGgubWluKE1hdGgubWF4KGFscGhhWzFdLCAwKSwgMSk7XG5cbiAgICB2YXIgc3RlcHMgPSBjbWFwLm1hcChmdW5jdGlvbihjLCBpKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGNtYXBbaV0uaW5kZXhcblxuICAgICAgICB2YXIgcmdiYSA9IGNtYXBbaV0ucmdiLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gaWYgdXNlciBzdXBwbGllcyB0aGVpciBvd24gbWFwIHVzZSBpdFxuICAgICAgICBpZiAocmdiYS5sZW5ndGggPT09IDQgJiYgcmdiYVszXSA+PSAwICYmIHJnYmFbM10gPD0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIHJnYmFcbiAgICAgICAgfVxuICAgICAgICByZ2JhWzNdID0gYWxwaGFbMF0gKyAoYWxwaGFbMV0gLSBhbHBoYVswXSkqaW5kZXg7XG5cbiAgICAgICAgcmV0dXJuIHJnYmFcbiAgICB9KVxuXG5cbiAgICAvKlxuICAgICAqIG1hcCBpbmNyZWFzaW5nIGxpbmVhciB2YWx1ZXMgYmV0d2VlbiBpbmRpY2llcyB0b1xuICAgICAqIGxpbmVhciBzdGVwcyBpbiBjb2xvcnZhbHVlc1xuICAgICAqL1xuICAgIHZhciBjb2xvcnMgPSBbXVxuICAgIGZvciAoaSA9IDA7IGkgPCBpbmRpY2llcy5sZW5ndGgtMTsgKytpKSB7XG4gICAgICAgIG5zdGVwcyA9IGluZGljaWVzW2krMV0gLSBpbmRpY2llc1tpXTtcbiAgICAgICAgZnJvbXJnYmEgPSBzdGVwc1tpXTtcbiAgICAgICAgdG9yZ2JhID0gc3RlcHNbaSsxXTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG5zdGVwczsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYW10ID0gaiAvIG5zdGVwc1xuICAgICAgICAgICAgY29sb3JzLnB1c2goW1xuICAgICAgICAgICAgICAgIE1hdGgucm91bmQobGVycChmcm9tcmdiYVswXSwgdG9yZ2JhWzBdLCBhbXQpKSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKGxlcnAoZnJvbXJnYmFbMV0sIHRvcmdiYVsxXSwgYW10KSksXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZChsZXJwKGZyb21yZ2JhWzJdLCB0b3JnYmFbMl0sIGFtdCkpLFxuICAgICAgICAgICAgICAgIGxlcnAoZnJvbXJnYmFbM10sIHRvcmdiYVszXSwgYW10KVxuICAgICAgICAgICAgXSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vYWRkIDEgc3RlcCBhcyBsYXN0IHZhbHVlXG4gICAgY29sb3JzLnB1c2goY21hcFtjbWFwLmxlbmd0aCAtIDFdLnJnYi5jb25jYXQoYWxwaGFbMV0pKVxuXG4gICAgaWYgKGZvcm1hdCA9PT0gJ2hleCcpIGNvbG9ycyA9IGNvbG9ycy5tYXAoIHJnYjJoZXggKTtcbiAgICBlbHNlIGlmIChmb3JtYXQgPT09ICdyZ2JhU3RyaW5nJykgY29sb3JzID0gY29sb3JzLm1hcCggcmdiYVN0ciApO1xuICAgIGVsc2UgaWYgKGZvcm1hdCA9PT0gJ2Zsb2F0JykgY29sb3JzID0gY29sb3JzLm1hcCggcmdiMmZsb2F0ICk7XG5cbiAgICByZXR1cm4gY29sb3JzO1xufTtcblxuZnVuY3Rpb24gcmdiMmZsb2F0IChyZ2JhKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgcmdiYVswXSAvIDI1NSxcbiAgICAgICAgcmdiYVsxXSAvIDI1NSxcbiAgICAgICAgcmdiYVsyXSAvIDI1NSxcbiAgICAgICAgcmdiYVszXVxuICAgIF1cbn1cblxuZnVuY3Rpb24gcmdiMmhleCAocmdiYSkge1xuICAgIHZhciBkaWcsIGhleCA9ICcjJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICBkaWcgPSByZ2JhW2ldO1xuICAgICAgICBkaWcgPSBkaWcudG9TdHJpbmcoMTYpO1xuICAgICAgICBoZXggKz0gKCcwMCcgKyBkaWcpLnN1YnN0ciggZGlnLmxlbmd0aCApO1xuICAgIH1cbiAgICByZXR1cm4gaGV4O1xufVxuXG5mdW5jdGlvbiByZ2JhU3RyIChyZ2JhKSB7XG4gICAgcmV0dXJuICdyZ2JhKCcgKyByZ2JhLmpvaW4oJywnKSArICcpJztcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gY29tcGFyZUFuZ2xlXG5cbnZhciBvcmllbnQgPSByZXF1aXJlKFwicm9idXN0LW9yaWVudGF0aW9uXCIpXG52YXIgc2duID0gcmVxdWlyZShcInNpZ251bVwiKVxudmFyIHR3b1N1bSA9IHJlcXVpcmUoXCJ0d28tc3VtXCIpXG52YXIgcm9idXN0UHJvZHVjdCA9IHJlcXVpcmUoXCJyb2J1c3QtcHJvZHVjdFwiKVxudmFyIHJvYnVzdFN1bSA9IHJlcXVpcmUoXCJyb2J1c3Qtc3VtXCIpXG5cbmZ1bmN0aW9uIHRlc3RJbnRlcmlvcihhLCBiLCBjKSB7XG4gIHZhciB4MCA9IHR3b1N1bShhWzBdLCAtYlswXSlcbiAgdmFyIHkwID0gdHdvU3VtKGFbMV0sIC1iWzFdKVxuICB2YXIgeDEgPSB0d29TdW0oY1swXSwgLWJbMF0pXG4gIHZhciB5MSA9IHR3b1N1bShjWzFdLCAtYlsxXSlcblxuICB2YXIgZCA9IHJvYnVzdFN1bShcbiAgICByb2J1c3RQcm9kdWN0KHgwLCB4MSksXG4gICAgcm9idXN0UHJvZHVjdCh5MCwgeTEpKVxuXG4gIHJldHVybiBkW2QubGVuZ3RoLTFdID49IDBcbn1cblxuZnVuY3Rpb24gY29tcGFyZUFuZ2xlKGEsIGIsIGMsIGQpIHtcbiAgdmFyIGJjZCA9IG9yaWVudChiLCBjLCBkKVxuICBpZihiY2QgPT09IDApIHtcbiAgICAvL0hhbmRsZSBkZWdlbmVyYXRlIGNhc2VzXG4gICAgdmFyIHNhYmMgPSBzZ24ob3JpZW50KGEsIGIsIGMpKVxuICAgIHZhciBzYWJkID0gc2duKG9yaWVudChhLCBiLCBkKSlcbiAgICBpZihzYWJjID09PSBzYWJkKSB7XG4gICAgICBpZihzYWJjID09PSAwKSB7XG4gICAgICAgIHZhciBpYyA9IHRlc3RJbnRlcmlvcihhLCBiLCBjKVxuICAgICAgICB2YXIgaWQgPSB0ZXN0SW50ZXJpb3IoYSwgYiwgZClcbiAgICAgICAgaWYoaWMgPT09IGlkKSB7XG4gICAgICAgICAgcmV0dXJuIDBcbiAgICAgICAgfSBlbHNlIGlmKGljKSB7XG4gICAgICAgICAgcmV0dXJuIDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gLTFcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIDBcbiAgICB9IGVsc2UgaWYoc2FiZCA9PT0gMCkge1xuICAgICAgaWYoc2FiYyA+IDApIHtcbiAgICAgICAgcmV0dXJuIC0xXG4gICAgICB9IGVsc2UgaWYodGVzdEludGVyaW9yKGEsIGIsIGQpKSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDFcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoc2FiYyA9PT0gMCkge1xuICAgICAgaWYoc2FiZCA+IDApIHtcbiAgICAgICAgcmV0dXJuIDFcbiAgICAgIH0gZWxzZSBpZih0ZXN0SW50ZXJpb3IoYSwgYiwgYykpIHtcbiAgICAgICAgcmV0dXJuIDFcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2duKHNhYmQgLSBzYWJjKVxuICB9XG4gIHZhciBhYmMgPSBvcmllbnQoYSwgYiwgYylcbiAgaWYoYWJjID4gMCkge1xuICAgIGlmKGJjZCA+IDAgJiYgb3JpZW50KGEsIGIsIGQpID4gMCkge1xuICAgICAgcmV0dXJuIDFcbiAgICB9XG4gICAgcmV0dXJuIC0xXG4gIH0gZWxzZSBpZihhYmMgPCAwKSB7XG4gICAgaWYoYmNkID4gMCB8fCBvcmllbnQoYSwgYiwgZCkgPiAwKSB7XG4gICAgICByZXR1cm4gMVxuICAgIH1cbiAgICByZXR1cm4gLTFcbiAgfSBlbHNlIHtcbiAgICB2YXIgYWJkID0gb3JpZW50KGEsIGIsIGQpXG4gICAgaWYoYWJkID4gMCkge1xuICAgICAgcmV0dXJuIDFcbiAgICB9IGVsc2Uge1xuICAgICAgaWYodGVzdEludGVyaW9yKGEsIGIsIGMpKSB7XG4gICAgICAgIHJldHVybiAxXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH1cbiAgICB9XG4gIH1cbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGNvbXBhcmVDZWxsc1xuXG52YXIgbWluID0gTWF0aC5taW5cblxuZnVuY3Rpb24gY29tcGFyZUludChhLCBiKSB7XG4gIHJldHVybiBhIC0gYlxufVxuXG5mdW5jdGlvbiBjb21wYXJlQ2VsbHMoYSwgYikge1xuICB2YXIgbiA9IGEubGVuZ3RoXG4gICAgLCB0ID0gYS5sZW5ndGggLSBiLmxlbmd0aFxuICBpZih0KSB7XG4gICAgcmV0dXJuIHRcbiAgfVxuICBzd2l0Y2gobikge1xuICAgIGNhc2UgMDpcbiAgICAgIHJldHVybiAwXG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIGFbMF0gLSBiWzBdXG4gICAgY2FzZSAyOlxuICAgICAgcmV0dXJuIChhWzBdK2FbMV0tYlswXS1iWzFdKSB8fFxuICAgICAgICAgICAgIG1pbihhWzBdLGFbMV0pIC0gbWluKGJbMF0sYlsxXSlcbiAgICBjYXNlIDM6XG4gICAgICB2YXIgbDEgPSBhWzBdK2FbMV1cbiAgICAgICAgLCBtMSA9IGJbMF0rYlsxXVxuICAgICAgdCA9IGwxK2FbMl0gLSAobTErYlsyXSlcbiAgICAgIGlmKHQpIHtcbiAgICAgICAgcmV0dXJuIHRcbiAgICAgIH1cbiAgICAgIHZhciBsMCA9IG1pbihhWzBdLCBhWzFdKVxuICAgICAgICAsIG0wID0gbWluKGJbMF0sIGJbMV0pXG4gICAgICByZXR1cm4gbWluKGwwLCBhWzJdKSAtIG1pbihtMCwgYlsyXSkgfHxcbiAgICAgICAgICAgICBtaW4obDArYVsyXSwgbDEpIC0gbWluKG0wK2JbMl0sIG0xKVxuICAgIGNhc2UgNDpcbiAgICAgIHZhciBhdz1hWzBdLCBheD1hWzFdLCBheT1hWzJdLCBhej1hWzNdXG4gICAgICAgICwgYnc9YlswXSwgYng9YlsxXSwgYnk9YlsyXSwgYno9YlszXVxuICAgICAgcmV0dXJuIChhdytheCtheStheiktKGJ3K2J4K2J5K2J6KSB8fFxuICAgICAgICAgICAgIG1pbihhdyxheCxheSxheiktbWluKGJ3LGJ4LGJ5LGJ6LGJ3KSB8fFxuICAgICAgICAgICAgIG1pbihhdytheCxhdytheSxhdytheixheCtheSxheCtheixheStheikgLVxuICAgICAgICAgICAgICAgbWluKGJ3K2J4LGJ3K2J5LGJ3K2J6LGJ4K2J5LGJ4K2J6LGJ5K2J6KSB8fFxuICAgICAgICAgICAgIG1pbihhdytheCtheSxhdytheCtheixhdytheStheixheCtheStheikgLVxuICAgICAgICAgICAgICAgbWluKGJ3K2J4K2J5LGJ3K2J4K2J6LGJ3K2J5K2J6LGJ4K2J5K2J6KVxuICAgIGRlZmF1bHQ6XG4gICAgICB2YXIgYXMgPSBhLnNsaWNlKCkuc29ydChjb21wYXJlSW50KVxuICAgICAgdmFyIGJzID0gYi5zbGljZSgpLnNvcnQoY29tcGFyZUludClcbiAgICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgICB0ID0gYXNbaV0gLSBic1tpXVxuICAgICAgICBpZih0KSB7XG4gICAgICAgICAgcmV0dXJuIHRcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIDBcbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBjb21wYXJlQ2VsbHMgPSByZXF1aXJlKCdjb21wYXJlLWNlbGwnKVxudmFyIHBhcml0eSA9IHJlcXVpcmUoJ2NlbGwtb3JpZW50YXRpb24nKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbXBhcmVPcmllbnRlZENlbGxzXG5cbmZ1bmN0aW9uIGNvbXBhcmVPcmllbnRlZENlbGxzKGEsIGIpIHtcbiAgcmV0dXJuIGNvbXBhcmVDZWxscyhhLCBiKSB8fCBwYXJpdHkoYSkgLSBwYXJpdHkoYilcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBjb252ZXhIdWxsMWQgPSByZXF1aXJlKCcuL2xpYi9jaDFkJylcbnZhciBjb252ZXhIdWxsMmQgPSByZXF1aXJlKCcuL2xpYi9jaDJkJylcbnZhciBjb252ZXhIdWxsbmQgPSByZXF1aXJlKCcuL2xpYi9jaG5kJylcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXhIdWxsXG5cbmZ1bmN0aW9uIGNvbnZleEh1bGwocG9pbnRzKSB7XG4gIHZhciBuID0gcG9pbnRzLmxlbmd0aFxuICBpZihuID09PSAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH0gZWxzZSBpZihuID09PSAxKSB7XG4gICAgcmV0dXJuIFtbMF1dXG4gIH1cbiAgdmFyIGQgPSBwb2ludHNbMF0ubGVuZ3RoXG4gIGlmKGQgPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfSBlbHNlIGlmKGQgPT09IDEpIHtcbiAgICByZXR1cm4gY29udmV4SHVsbDFkKHBvaW50cylcbiAgfSBlbHNlIGlmKGQgPT09IDIpIHtcbiAgICByZXR1cm4gY29udmV4SHVsbDJkKHBvaW50cylcbiAgfVxuICByZXR1cm4gY29udmV4SHVsbG5kKHBvaW50cywgZClcbn0iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbnZleEh1bGwxZFxuXG5mdW5jdGlvbiBjb252ZXhIdWxsMWQocG9pbnRzKSB7XG4gIHZhciBsbyA9IDBcbiAgdmFyIGhpID0gMFxuICBmb3IodmFyIGk9MTsgaTxwb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICBpZihwb2ludHNbaV1bMF0gPCBwb2ludHNbbG9dWzBdKSB7XG4gICAgICBsbyA9IGlcbiAgICB9XG4gICAgaWYocG9pbnRzW2ldWzBdID4gcG9pbnRzW2hpXVswXSkge1xuICAgICAgaGkgPSBpXG4gICAgfVxuICB9XG4gIGlmKGxvIDwgaGkpIHtcbiAgICByZXR1cm4gW1tsb10sIFtoaV1dXG4gIH0gZWxzZSBpZihsbyA+IGhpKSB7XG4gICAgcmV0dXJuIFtbaGldLCBbbG9dXVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBbW2xvXV1cbiAgfVxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbnZleEh1bGwyRFxuXG52YXIgbW9ub3RvbmVIdWxsID0gcmVxdWlyZSgnbW9ub3RvbmUtY29udmV4LWh1bGwtMmQnKVxuXG5mdW5jdGlvbiBjb252ZXhIdWxsMkQocG9pbnRzKSB7XG4gIHZhciBodWxsID0gbW9ub3RvbmVIdWxsKHBvaW50cylcbiAgdmFyIGggPSBodWxsLmxlbmd0aFxuICBpZihoIDw9IDIpIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICB2YXIgZWRnZXMgPSBuZXcgQXJyYXkoaClcbiAgdmFyIGEgPSBodWxsW2gtMV1cbiAgZm9yKHZhciBpPTA7IGk8aDsgKytpKSB7XG4gICAgdmFyIGIgPSBodWxsW2ldXG4gICAgZWRnZXNbaV0gPSBbYSxiXVxuICAgIGEgPSBiXG4gIH1cbiAgcmV0dXJuIGVkZ2VzXG59XG4iLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXhIdWxsbkRcblxudmFyIGljaCA9IHJlcXVpcmUoJ2luY3JlbWVudGFsLWNvbnZleC1odWxsJylcbnZhciBhZmYgPSByZXF1aXJlKCdhZmZpbmUtaHVsbCcpXG5cbmZ1bmN0aW9uIHBlcm11dGUocG9pbnRzLCBmcm9udCkge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcbiAgdmFyIG5wb2ludHMgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8ZnJvbnQubGVuZ3RoOyArK2kpIHtcbiAgICBucG9pbnRzW2ldID0gcG9pbnRzW2Zyb250W2ldXVxuICB9XG4gIHZhciBwdHIgPSBmcm9udC5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgaWYoZnJvbnQuaW5kZXhPZihpKSA8IDApIHtcbiAgICAgIG5wb2ludHNbcHRyKytdID0gcG9pbnRzW2ldXG4gICAgfVxuICB9XG4gIHJldHVybiBucG9pbnRzXG59XG5cbmZ1bmN0aW9uIGludlBlcm11dGUoY2VsbHMsIGZyb250KSB7XG4gIHZhciBuYyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgbmYgPSBmcm9udC5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bmM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XG4gICAgICB2YXIgeCA9IGNbal1cbiAgICAgIGlmKHggPCBuZikge1xuICAgICAgICBjW2pdID0gZnJvbnRbeF1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHggPSB4IC0gbmZcbiAgICAgICAgZm9yKHZhciBrPTA7IGs8bmY7ICsraykge1xuICAgICAgICAgIGlmKHggPj0gZnJvbnRba10pIHtcbiAgICAgICAgICAgIHggKz0gMVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjW2pdID0geFxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gY2VsbHNcbn1cblxuZnVuY3Rpb24gY29udmV4SHVsbG5EKHBvaW50cywgZCkge1xuICB0cnkge1xuICAgIHJldHVybiBpY2gocG9pbnRzLCB0cnVlKVxuICB9IGNhdGNoKGUpIHtcbiAgICAvL0lmIHBvaW50IHNldCBpcyBkZWdlbmVyYXRlLCB0cnkgdG8gZmluZCBhIGJhc2lzIGFuZCByZXJ1biBpdFxuICAgIHZhciBhaCA9IGFmZihwb2ludHMpXG4gICAgaWYoYWgubGVuZ3RoIDw9IGQpIHtcbiAgICAgIC8vTm8gYmFzaXMsIG5vIHRyeVxuICAgICAgcmV0dXJuIFtdXG4gICAgfVxuICAgIHZhciBucG9pbnRzID0gcGVybXV0ZShwb2ludHMsIGFoKVxuICAgIHZhciBuaHVsbCAgID0gaWNoKG5wb2ludHMsIHRydWUpXG4gICAgcmV0dXJuIGludlBlcm11dGUobmh1bGwsIGFoKVxuICB9XG59IiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIEFGRzogJ2FmZ2hhbicsXG4gIEFMQTogJ1xcXFxiXFxcXHdsYW5kJyxcbiAgQUxCOiAnYWxiYW5pYScsXG4gIERaQTogJ2FsZ2VyaWEnLFxuICBBU006ICdeKD89LiphbWVyaWMpLipzYW1vYScsXG4gIEFORDogJ2FuZG9ycmEnLFxuICBBR086ICdhbmdvbGEnLFxuICBBSUE6ICdhbmd1aWxsP2EnLFxuICBBVEE6ICdhbnRhcmN0aWNhJyxcbiAgQVRHOiAnYW50aWd1YScsXG4gIEFSRzogJ2FyZ2VudGluJyxcbiAgQVJNOiAnYXJtZW5pYScsXG4gIEFCVzogJ14oPyEuKmJvbmFpcmUpLipcXFxcYmFydWJhJyxcbiAgQVVTOiAnYXVzdHJhbGlhJyxcbiAgQVVUOiAnXig/IS4qaHVuZ2FyeSkuKmF1c3RyaWF8XFxcXGJhdXN0cmkuKlxcXFxiZW1wJyxcbiAgQVpFOiAnYXplcmJhaWphbicsXG4gIEJIUzogJ2JhaGFtYXMnLFxuICBCSFI6ICdiYWhyYWluJyxcbiAgQkdEOiAnYmFuZ2xhZGVzaHxeKD89LiplYXN0KS4qcGFraT9zdGFuJyxcbiAgQlJCOiAnYmFyYmFkb3MnLFxuICBCTFI6ICdiZWxhcnVzfGJ5ZWxvJyxcbiAgQkVMOiAnXig/IS4qbHV4ZW0pLipiZWxnaXVtJyxcbiAgQkxaOiAnYmVsaXplfF4oPz0uKmJyaXRpc2gpLipob25kdXJhcycsXG4gIEJFTjogJ2JlbmlufGRhaG9tZScsXG4gIEJNVTogJ2Jlcm11ZGEnLFxuICBCVE46ICdiaHV0YW4nLFxuICBCT0w6ICdib2xpdmlhJyxcbiAgQkVTOiAnXig/PS4qYm9uYWlyZSkuKmV1c3RhdGl1c3xeKD89LipjYXJpYikuKm5ldGhlcmxhbmRzfFxcXFxiYmVzLj9pc2xhbmRzJyxcbiAgQklIOiAnaGVyemVnb3ZpbmF8Ym9zbmlhJyxcbiAgQldBOiAnYm90c3dhbmF8YmVjaHVhbmEnLFxuICBCVlQ6ICdib3V2ZXQnLFxuICBCUkE6ICdicmF6aWwnLFxuICBJT1Q6ICdicml0aXNoLj9pbmRpYW4uP29jZWFuJyxcbiAgQlJOOiAnYnJ1bmVpJyxcbiAgQkdSOiAnYnVsZ2FyaWEnLFxuICBCRkE6ICdidXJraW5hfFxcXFxiZmFzb3x1cHBlci4/dm9sdGEnLFxuICBCREk6ICdidXJ1bmRpJyxcbiAgQ1BWOiAndmVyZGUnLFxuICBLSE06ICdjYW1ib2RpYXxrYW1wdWNoZWF8a2htZXInLFxuICBDTVI6ICdjYW1lcm9vbicsXG4gIENBTjogJ2NhbmFkYScsXG4gIENZTTogJ2NheW1hbicsXG4gIENBRjogJ1xcXFxiY2VudHJhbC5hZnJpY2FuLnJlcHVibGljJyxcbiAgVENEOiAnXFxcXGJjaGFkJyxcbiAgQ0hMOiAnXFxcXGJjaGlsZScsXG4gIENITjogJ14oPyEuKlxcXFxibWFjKSg/IS4qXFxcXGJob25nKSg/IS4qXFxcXGJ0YWkpKD8hLipcXFxcYnJlcCkuKmNoaW5hfF4oPz0uKnBlbykoPz0uKnJlcCkuKmNoaW5hJyxcbiAgQ1hSOiAnY2hyaXN0bWFzJyxcbiAgQ0NLOiAnXFxcXGJjb2Nvc3xrZWVsaW5nJyxcbiAgQ09MOiAnY29sb21iaWEnLFxuICBDT006ICdjb21vcm8nLFxuICBDT0c6ICdeKD8hLipcXFxcYmRlbSkoPyEuKlxcXFxiZFtcXFxcLl0/cikoPyEuKmtpbnNoYXNhKSg/IS4qemFpcmUpKD8hLipiZWxnKSg/IS4qbC5vcG9sZHZpbGxlKSg/IS4qZnJlZSkuKlxcXFxiY29uZ28nLFxuICBDT0s6ICdcXFxcYmNvb2snLFxuICBDUkk6ICdjb3N0YS4/cmljYScsXG4gIENJVjogJ2l2b2lyZXxpdm9yeScsXG4gIEhSVjogJ2Nyb2F0aWEnLFxuICBDVUI6ICdcXFxcYmN1YmEnLFxuICBDVVc6ICdeKD8hLipib25haXJlKS4qXFxcXGJjdXJhKGN8w6cpYW8nLFxuICBDWVA6ICdjeXBydXMnLFxuICBDU0s6ICdjemVjaG9zbG92YWtpYScsXG4gIENaRTogJ14oPz0uKnJlcCkuKmN6ZWNofGN6ZWNoaWF8Ym9oZW1pYScsXG4gIENPRDogJ1xcXFxiZGVtLipjb25nb3xjb25nby4qXFxcXGJkZW18Y29uZ28uKlxcXFxiZFtcXFxcLl0/cnxcXFxcYmRbXFxcXC5dP3IuKmNvbmdvfGJlbGdpYW4uP2NvbmdvfGNvbmdvLj9mcmVlLj9zdGF0ZXxraW5zaGFzYXx6YWlyZXxsLm9wb2xkdmlsbGV8ZHJjfGRyb2N8cmRjJyxcbiAgRE5LOiAnZGVubWFyaycsXG4gIERKSTogJ2RqaWJvdXRpJyxcbiAgRE1BOiAnZG9taW5pY2EoPyFuKScsXG4gIERPTTogJ2RvbWluaWNhbi5yZXAnLFxuICBFQ1U6ICdlY3VhZG9yJyxcbiAgRUdZOiAnZWd5cHQnLFxuICBTTFY6ICdlbC4/c2FsdmFkb3InLFxuICBHTlE6ICdndWluZS4qZXF8ZXEuKmd1aW5lfF4oPz0uKnNwYW4pLipndWluZWEnLFxuICBFUkk6ICdlcml0cmVhJyxcbiAgRVNUOiAnZXN0b25pYScsXG4gIEVUSDogJ2V0aGlvcGlhfGFieXNzaW5pYScsXG4gIEZMSzogJ2ZhbGtsYW5kfG1hbHZpbmFzJyxcbiAgRlJPOiAnZmFyb2V8ZmFlcm9lJyxcbiAgRkpJOiAnZmlqaScsXG4gIEZJTjogJ2ZpbmxhbmQnLFxuICBGUkE6ICdeKD8hLipcXFxcYmRlcCkoPyEuKm1hcnRpbmlxdWUpLipmcmFuY2V8ZnJlbmNoLj9yZXB1YmxpY3xcXFxcYmdhdWwnLFxuICBHVUY6ICdeKD89LipmcmVuY2gpLipndWlhbmEnLFxuICBQWUY6ICdmcmVuY2guP3BvbHluZXNpYXx0YWhpdGknLFxuICBBVEY6ICdmcmVuY2guP3NvdXRoZXJuJyxcbiAgR0FCOiAnZ2Fib24nLFxuICBHTUI6ICdnYW1iaWEnLFxuICBHRU86ICdeKD8hLipzb3V0aCkuKmdlb3JnaWEnLFxuICBERFI6ICdnZXJtYW4uP2RlbW9jcmF0aWMuP3JlcHVibGljfGRlbW9jcmF0aWMuP3JlcHVibGljLipnZXJtYW55fGVhc3QuZ2VybWFueScsXG4gIERFVTogJ14oPyEuKmVhc3QpLipnZXJtYW55fF4oPz0uKlxcXFxiZmVkLipcXFxcYnJlcCkuKmdlcm1hbicsXG4gIEdIQTogJ2doYW5hfGdvbGQuP2NvYXN0JyxcbiAgR0lCOiAnZ2licmFsdGFyJyxcbiAgR1JDOiAnZ3JlZWNlfGhlbGxlbmljfGhlbGxhcycsXG4gIEdSTDogJ2dyZWVubGFuZCcsXG4gIEdSRDogJ2dyZW5hZGEnLFxuICBHTFA6ICdndWFkZWxvdXBlJyxcbiAgR1VNOiAnXFxcXGJndWFtJyxcbiAgR1RNOiAnZ3VhdGVtYWxhJyxcbiAgR0dZOiAnZ3Vlcm5zZXknLFxuICBHSU46ICdeKD8hLiplcSkoPyEuKnNwYW4pKD8hLipiaXNzYXUpKD8hLipwb3J0dSkoPyEuKm5ldykuKmd1aW5lYScsXG4gIEdOQjogJ2Jpc3NhdXxeKD89Lipwb3J0dSkuKmd1aW5lYScsXG4gIEdVWTogJ2d1eWFuYXxicml0aXNoLj9ndWlhbmEnLFxuICBIVEk6ICdoYWl0aScsXG4gIEhNRDogJ2hlYXJkLiptY2RvbmFsZCcsXG4gIFZBVDogJ2hvbHkuP3NlZXx2YXRpY2FufHBhcGFsLj9zdCcsXG4gIEhORDogJ14oPyEuKmJyaXQpLipob25kdXJhcycsXG4gIEhLRzogJ2hvbmcuP2tvbmcnLFxuICBIVU46ICdeKD8hLiphdXN0cikuKmh1bmdhcnknLFxuICBJU0w6ICdpY2VsYW5kJyxcbiAgSU5EOiAnaW5kaWEoPyEuKm9jZWEpJyxcbiAgSUROOiAnaW5kb25lc2lhJyxcbiAgSVJOOiAnXFxcXGJpcmFufHBlcnNpYScsXG4gIElSUTogJ1xcXFxiaXJhcXxtZXNvcG90YW1pYScsXG4gIElSTDogJyheaXJlbGFuZCl8KF5yZXB1YmxpYy4qaXJlbGFuZCknLFxuICBJTU46ICdeKD89Lippc2xlKS4qXFxcXGJtYW4nLFxuICBJU1I6ICdpc3JhZWwnLFxuICBJVEE6ICdpdGFseScsXG4gIEpBTTogJ2phbWFpY2EnLFxuICBKUE46ICdqYXBhbicsXG4gIEpFWTogJ2plcnNleScsXG4gIEpPUjogJ2pvcmRhbicsXG4gIEtBWjogJ2themFrJyxcbiAgS0VOOiAna2VueWF8YnJpdGlzaC4/ZWFzdC4/YWZyaWNhfGVhc3QuP2FmcmljYS4/cHJvdCcsXG4gIEtJUjogJ2tpcmliYXRpJyxcbiAgUFJLOiAnXig/PS4qZGVtb2NyYXR8cGVvcGxlfG5vcnRofGQuKnAuKi5yKS4qXFxcXGJrb3JlYXxkcHJrfGtvcmVhLiooZC4qcC4qciknLFxuICBLV1Q6ICdrdXdhaXQnLFxuICBLR1o6ICdreXJneXp8a2lyZ2hpeicsXG4gIExBTzogJ1xcXFxibGFvcz9cXFxcYicsXG4gIExWQTogJ2xhdHZpYScsXG4gIExCTjogJ2xlYmFub24nLFxuICBMU086ICdsZXNvdGhvfGJhc3V0bycsXG4gIExCUjogJ2xpYmVyaWEnLFxuICBMQlk6ICdsaWJ5YScsXG4gIExJRTogJ2xpZWNodGVuc3RlaW4nLFxuICBMVFU6ICdsaXRodWFuaWEnLFxuICBMVVg6ICdeKD8hLipiZWxnKS4qbHV4ZW0nLFxuICBNQUM6ICdtYWNhKG98dSknLFxuICBNREc6ICdtYWRhZ2FzY2FyfG1hbGFnYXN5JyxcbiAgTVdJOiAnbWFsYXdpfG55YXNhJyxcbiAgTVlTOiAnbWFsYXlzaWEnLFxuICBNRFY6ICdtYWxkaXZlJyxcbiAgTUxJOiAnXFxcXGJtYWxpXFxcXGInLFxuICBNTFQ6ICdcXFxcYm1hbHRhJyxcbiAgTUhMOiAnbWFyc2hhbGwnLFxuICBNVFE6ICdtYXJ0aW5pcXVlJyxcbiAgTVJUOiAnbWF1cml0YW5pYScsXG4gIE1VUzogJ21hdXJpdGl1cycsXG4gIE1ZVDogJ1xcXFxibWF5b3R0ZScsXG4gIE1FWDogJ1xcXFxibWV4aWMnLFxuICBGU006ICdmZWQuKm1pY3JvbmVzaWF8bWljcm9uZXNpYS4qZmVkJyxcbiAgTUNPOiAnbW9uYWNvJyxcbiAgTU5HOiAnbW9uZ29saWEnLFxuICBNTkU6ICdeKD8hLipzZXJiaWEpLiptb250ZW5lZ3JvJyxcbiAgTVNSOiAnbW9udHNlcnJhdCcsXG4gIE1BUjogJ21vcm9jY298XFxcXGJtYXJvYycsXG4gIE1PWjogJ21vemFtYmlxdWUnLFxuICBNTVI6ICdteWFubWFyfGJ1cm1hJyxcbiAgTkFNOiAnbmFtaWJpYScsXG4gIE5SVTogJ25hdXJ1JyxcbiAgTlBMOiAnbmVwYWwnLFxuICBOTEQ6ICdeKD8hLipcXFxcYmFudCkoPyEuKlxcXFxiY2FyaWIpLipuZXRoZXJsYW5kcycsXG4gIEFOVDogJ14oPz0uKlxcXFxiYW50KS4qKG5ldGhlcnxkdXRjaCknLFxuICBOQ0w6ICduZXcuP2NhbGVkb25pYScsXG4gIE5aTDogJ25ldy4/emVhbGFuZCcsXG4gIE5JQzogJ25pY2FyYWd1YScsXG4gIE5FUjogJ1xcXFxibmlnZXIoPyFpYSknLFxuICBOR0E6ICduaWdlcmlhJyxcbiAgTklVOiAnbml1ZScsXG4gIE5GSzogJ25vcmZvbGsnLFxuICBNTlA6ICdtYXJpYW5hJyxcbiAgTk9SOiAnbm9yd2F5JyxcbiAgT01OOiAnXFxcXGJvbWFufHRydWNpYWwnLFxuICBQQUs6ICdeKD8hLiplYXN0KS4qcGFraT9zdGFuJyxcbiAgUExXOiAncGFsYXUnLFxuICBQU0U6ICdwYWxlc3RpbnxcXFxcYmdhemF8d2VzdC4/YmFuaycsXG4gIFBBTjogJ3BhbmFtYScsXG4gIFBORzogJ3BhcHVhfG5ldy4/Z3VpbmVhJyxcbiAgUFJZOiAncGFyYWd1YXknLFxuICBQRVI6ICdwZXJ1JyxcbiAgUEhMOiAncGhpbGlwcGluZXMnLFxuICBQQ046ICdwaXRjYWlybicsXG4gIFBPTDogJ3BvbGFuZCcsXG4gIFBSVDogJ3BvcnR1Z2FsJyxcbiAgUFJJOiAncHVlcnRvLj9yaWNvJyxcbiAgUUFUOiAncWF0YXInLFxuICBLT1I6ICdeKD8hLipkLipwLipyKSg/IS4qZGVtb2NyYXQpKD8hLipwZW9wbGUpKD8hLipub3J0aCkuKlxcXFxia29yZWEoPyEuKmQuKnAuKnIpJyxcbiAgTURBOiAnbW9sZG92fGIoYXxlKXNzYXJhYmlhJyxcbiAgUkVVOiAncihlfMOpKXVuaW9uJyxcbiAgUk9VOiAncihvfHV8b3UpbWFuaWEnLFxuICBSVVM6ICdcXFxcYnJ1c3NpYXxzb3ZpZXQuP3VuaW9ufHVcXFxcLj9zXFxcXC4/c1xcXFwuP3J8c29jaWFsaXN0Lj9yZXB1YmxpY3MnLFxuICBSV0E6ICdyd2FuZGEnLFxuICBCTE06ICdiYXJ0aChlfMOpKWxlbXknLFxuICBTSE46ICdoZWxlbmEnLFxuICBLTkE6ICdraXR0c3xcXFxcYm5ldmlzJyxcbiAgTENBOiAnXFxcXGJsdWNpYScsXG4gIE1BRjogJ14oPz0uKmNvbGxlY3Rpdml0eSkuKm1hcnRpbnxeKD89LipmcmFuY2UpLiptYXJ0aW4oPyFpcXVlKXxeKD89LipmcmVuY2gpLiptYXJ0aW4oPyFpcXVlKScsXG4gIFNQTTogJ21pcXVlbG9uJyxcbiAgVkNUOiAndmluY2VudCcsXG4gIFdTTTogJ14oPyEuKmFtZXIpLipzYW1vYScsXG4gIFNNUjogJ3Nhbi4/bWFyaW5vJyxcbiAgU1RQOiAnXFxcXGJzKGF8w6Mpby4/dG9tKGV8w6kpJyxcbiAgU0FVOiAnXFxcXGJzYVxcXFx3Ki4/YXJhYmlhJyxcbiAgU0VOOiAnc2VuZWdhbCcsXG4gIFNSQjogJ14oPyEuKm1vbnRlKS4qc2VyYmlhJyxcbiAgU1lDOiAnc2V5Y2hlbGwnLFxuICBTTEU6ICdzaWVycmEnLFxuICBTR1A6ICdzaW5nYXBvcmUnLFxuICBTWE06ICdeKD8hLiptYXJ0aW4pKD8hLipzYWJhKS4qbWFhcnRlbicsXG4gIFNWSzogJ14oPyEuKmN6ZSkuKnNsb3ZhaycsXG4gIFNWTjogJ3Nsb3ZlbmlhJyxcbiAgU0xCOiAnc29sb21vbicsXG4gIFNPTTogJ3NvbWFsaScsXG4gIFpBRjogJ3NvdXRoLmFmcmljYXxzXFxcXFxcXFwuLj9hZnJpY2EnLFxuICBTR1M6ICdzb3V0aC4/Z2VvcmdpYXxzYW5kd2ljaCcsXG4gIFNTRDogJ1xcXFxic1xcXFx3Ki4/c3VkYW4nLFxuICBFU1A6ICdzcGFpbicsXG4gIExLQTogJ3NyaS4/bGFua2F8Y2V5bG9uJyxcbiAgU0ROOiAnXig/IS4qXFxcXGJzKD8hdSkpLipzdWRhbicsXG4gIFNVUjogJ3N1cmluYW18ZHV0Y2guP2d1aWFuYScsXG4gIFNKTTogJ3N2YWxiYXJkJyxcbiAgU1daOiAnc3dhemlsYW5kJyxcbiAgU1dFOiAnc3dlZGVuJyxcbiAgQ0hFOiAnc3dpdHp8c3dpc3MnLFxuICBTWVI6ICdzeXJpYScsXG4gIFRXTjogJ3RhaXdhbnx0YWlwZWl8Zm9ybW9zYXxeKD8hLipwZW8pKD89LipyZXApLipjaGluYScsXG4gIFRKSzogJ3RhamlrJyxcbiAgVEhBOiAndGhhaWxhbmR8XFxcXGJzaWFtJyxcbiAgTUtEOiAnbWFjZWRvbmlhfGZ5cm9tJyxcbiAgVExTOiAnXig/PS4qbGVzdGUpLip0aW1vcnxeKD89LiplYXN0KS4qdGltb3InLFxuICBUR086ICd0b2dvJyxcbiAgVEtMOiAndG9rZWxhdScsXG4gIFRPTjogJ3RvbmdhJyxcbiAgVFRPOiAndHJpbmlkYWR8dG9iYWdvJyxcbiAgVFVOOiAndHVuaXNpYScsXG4gIFRVUjogJ3R1cmtleScsXG4gIFRLTTogJ3R1cmttZW4nLFxuICBUQ0E6ICd0dXJrcycsXG4gIFRVVjogJ3R1dmFsdScsXG4gIFVHQTogJ3VnYW5kYScsXG4gIFVLUjogJ3VrcmFpbicsXG4gIEFSRTogJ2VtaXJhdGVzfF51XFxcXC4/YVxcXFwuP2VcXFxcLj8kfHVuaXRlZC4/YXJhYi4/ZW0nLFxuICBHQlI6ICd1bml0ZWQuP2tpbmdkb218YnJpdGFpbnxedVxcXFwuP2tcXFxcLj8kJyxcbiAgVFpBOiAndGFuemFuaWEnLFxuICBVU0E6ICd1bml0ZWQuP3N0YXRlc1xcXFxiKD8hLippc2xhbmRzKXxcXFxcYnVcXFxcLj9zXFxcXC4/YVxcXFwuP1xcXFxifF5cXFxccyp1XFxcXC4/c1xcXFwuP1xcXFxiKD8hLippc2xhbmRzKScsXG4gIFVNSTogJ21pbm9yLj9vdXRseWluZy4/aXMnLFxuICBVUlk6ICd1cnVndWF5JyxcbiAgVVpCOiAndXpiZWsnLFxuICBWVVQ6ICd2YW51YXR1fG5ldy4/aGVicmlkZXMnLFxuICBWRU46ICd2ZW5lenVlbGEnLFxuICBWTk06ICdeKD8hLipyZXB1YmxpYykuKnZpZXQuP25hbXxeKD89Lipzb2NpYWxpc3QpLip2aWV0Lj9uYW0nLFxuICBWR0I6ICdeKD89LipcXFxcYnVcXFxcLj9cXFxccz9rKS4qdmlyZ2lufF4oPz0uKmJyaXQpLip2aXJnaW58Xig/PS4qa2luZ2RvbSkuKnZpcmdpbicsXG4gIFZJUjogJ14oPz0uKlxcXFxidVxcXFwuP1xcXFxzP3MpLip2aXJnaW58Xig/PS4qc3RhdGVzKS4qdmlyZ2luJyxcbiAgV0xGOiAnZnV0dW5hfHdhbGxpcycsXG4gIEVTSDogJ3dlc3Rlcm4uc2FoYXJhJyxcbiAgWUVNOiAnXig/IS4qYXJhYikoPyEuKm5vcnRoKSg/IS4qc2FuYSkoPyEuKnBlbykoPyEuKmRlbSkoPyEuKnNvdXRoKSg/IS4qYWRlbikoPyEuKlxcXFxicFxcXFwuP2RcXFxcLj9yKS4qeWVtZW4nLFxuICBZTUQ6ICdeKD89LipwZW8pLip5ZW1lbnxeKD8hLipyZXApKD89LipkZW0pLip5ZW1lbnxeKD89Lipzb3V0aCkuKnllbWVufF4oPz0uKmFkZW4pLip5ZW1lbnxeKD89LipcXFxcYnBcXFxcLj9kXFxcXC4/cikuKnllbWVuJyxcbiAgWVVHOiAneXVnb3NsYXZpYScsXG4gIFpNQjogJ3phbWJpYXxub3J0aGVybi4/cmhvZGVzaWEnLFxuICBFQVo6ICd6YW56aWJhcicsXG4gIFpXRTogJ3ppbWJhYndlfF4oPyEuKm5vcnRoZXJuKS4qcmhvZGVzaWEnXG59XG4iLCJtb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJ4eC1zbWFsbFwiLFxyXG5cdFwieC1zbWFsbFwiLFxyXG5cdFwic21hbGxcIixcclxuXHRcIm1lZGl1bVwiLFxyXG5cdFwibGFyZ2VcIixcclxuXHRcIngtbGFyZ2VcIixcclxuXHRcInh4LWxhcmdlXCIsXHJcblx0XCJsYXJnZXJcIixcclxuXHRcInNtYWxsZXJcIlxyXG5dXHJcbiIsIm1vZHVsZS5leHBvcnRzPVtcclxuXHRcIm5vcm1hbFwiLFxyXG5cdFwiY29uZGVuc2VkXCIsXHJcblx0XCJzZW1pLWNvbmRlbnNlZFwiLFxyXG5cdFwiZXh0cmEtY29uZGVuc2VkXCIsXHJcblx0XCJ1bHRyYS1jb25kZW5zZWRcIixcclxuXHRcImV4cGFuZGVkXCIsXHJcblx0XCJzZW1pLWV4cGFuZGVkXCIsXHJcblx0XCJleHRyYS1leHBhbmRlZFwiLFxyXG5cdFwidWx0cmEtZXhwYW5kZWRcIlxyXG5dXHJcbiIsIm1vZHVsZS5leHBvcnRzPVtcclxuXHRcIm5vcm1hbFwiLFxyXG5cdFwiaXRhbGljXCIsXHJcblx0XCJvYmxpcXVlXCJcclxuXVxyXG4iLCJtb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJub3JtYWxcIixcclxuXHRcImJvbGRcIixcclxuXHRcImJvbGRlclwiLFxyXG5cdFwibGlnaHRlclwiLFxyXG5cdFwiMTAwXCIsXHJcblx0XCIyMDBcIixcclxuXHRcIjMwMFwiLFxyXG5cdFwiNDAwXCIsXHJcblx0XCI1MDBcIixcclxuXHRcIjYwMFwiLFxyXG5cdFwiNzAwXCIsXHJcblx0XCI4MDBcIixcclxuXHRcIjkwMFwiXHJcbl1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuXHRwYXJzZTogcmVxdWlyZSgnLi9wYXJzZScpLFxyXG5cdHN0cmluZ2lmeTogcmVxdWlyZSgnLi9zdHJpbmdpZnknKVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHNpemVzID0gcmVxdWlyZSgnY3NzLWZvbnQtc2l6ZS1rZXl3b3JkcycpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuXHRpc1NpemU6IGZ1bmN0aW9uIGlzU2l6ZSh2YWx1ZSkge1xyXG5cdFx0cmV0dXJuIC9eW1xcZFxcLl0vLnRlc3QodmFsdWUpXHJcblx0XHRcdHx8IHZhbHVlLmluZGV4T2YoJy8nKSAhPT0gLTFcclxuXHRcdFx0fHwgc2l6ZXMuaW5kZXhPZih2YWx1ZSkgIT09IC0xXHJcblx0fVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHVucXVvdGUgPSByZXF1aXJlKCd1bnF1b3RlJylcclxudmFyIGdsb2JhbEtleXdvcmRzID0gcmVxdWlyZSgnY3NzLWdsb2JhbC1rZXl3b3JkcycpXHJcbnZhciBzeXN0ZW1Gb250S2V5d29yZHMgPSByZXF1aXJlKCdjc3Mtc3lzdGVtLWZvbnQta2V5d29yZHMnKVxyXG52YXIgZm9udFdlaWdodEtleXdvcmRzID0gcmVxdWlyZSgnY3NzLWZvbnQtd2VpZ2h0LWtleXdvcmRzJylcclxudmFyIGZvbnRTdHlsZUtleXdvcmRzID0gcmVxdWlyZSgnY3NzLWZvbnQtc3R5bGUta2V5d29yZHMnKVxyXG52YXIgZm9udFN0cmV0Y2hLZXl3b3JkcyA9IHJlcXVpcmUoJ2Nzcy1mb250LXN0cmV0Y2gta2V5d29yZHMnKVxyXG52YXIgc3BsaXRCeSA9IHJlcXVpcmUoJ3N0cmluZy1zcGxpdC1ieScpXHJcbnZhciBpc1NpemUgPSByZXF1aXJlKCcuL2xpYi91dGlsJykuaXNTaXplXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBwYXJzZUZvbnRcclxuXHJcblxyXG52YXIgY2FjaGUgPSBwYXJzZUZvbnQuY2FjaGUgPSB7fVxyXG5cclxuXHJcbmZ1bmN0aW9uIHBhcnNlRm9udCAodmFsdWUpIHtcclxuXHRpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykgdGhyb3cgbmV3IEVycm9yKCdGb250IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcuJylcclxuXHJcblx0aWYgKGNhY2hlW3ZhbHVlXSkgcmV0dXJuIGNhY2hlW3ZhbHVlXVxyXG5cclxuXHRpZiAodmFsdWUgPT09ICcnKSB7XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBwYXJzZSBhbiBlbXB0eSBzdHJpbmcuJylcclxuXHR9XHJcblxyXG5cdGlmIChzeXN0ZW1Gb250S2V5d29yZHMuaW5kZXhPZih2YWx1ZSkgIT09IC0xKSB7XHJcblx0XHRyZXR1cm4gY2FjaGVbdmFsdWVdID0ge3N5c3RlbTogdmFsdWV9XHJcblx0fVxyXG5cclxuXHR2YXIgZm9udCA9IHtcclxuXHRcdHN0eWxlOiAnbm9ybWFsJyxcclxuXHRcdHZhcmlhbnQ6ICdub3JtYWwnLFxyXG5cdFx0d2VpZ2h0OiAnbm9ybWFsJyxcclxuXHRcdHN0cmV0Y2g6ICdub3JtYWwnLFxyXG5cdFx0bGluZUhlaWdodDogJ25vcm1hbCcsXHJcblx0XHRzaXplOiAnMXJlbScsXHJcblx0XHRmYW1pbHk6IFsnc2VyaWYnXVxyXG5cdH1cclxuXHJcblx0dmFyIHRva2VucyA9IHNwbGl0QnkodmFsdWUsIC9cXHMrLylcclxuXHR2YXIgdG9rZW5cclxuXHJcblx0d2hpbGUgKHRva2VuID0gdG9rZW5zLnNoaWZ0KCkpIHtcclxuXHRcdGlmIChnbG9iYWxLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0WydzdHlsZScsICd2YXJpYW50JywgJ3dlaWdodCcsICdzdHJldGNoJ10uZm9yRWFjaChmdW5jdGlvbihwcm9wKSB7XHJcblx0XHRcdFx0Zm9udFtwcm9wXSA9IHRva2VuXHJcblx0XHRcdH0pXHJcblxyXG5cdFx0XHRyZXR1cm4gY2FjaGVbdmFsdWVdID0gZm9udFxyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChmb250U3R5bGVLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0Zm9udC5zdHlsZSA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRva2VuID09PSAnbm9ybWFsJyB8fCB0b2tlbiA9PT0gJ3NtYWxsLWNhcHMnKSB7XHJcblx0XHRcdGZvbnQudmFyaWFudCA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGZvbnRTdHJldGNoS2V5d29yZHMuaW5kZXhPZih0b2tlbikgIT09IC0xKSB7XHJcblx0XHRcdGZvbnQuc3RyZXRjaCA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGZvbnRXZWlnaHRLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0Zm9udC53ZWlnaHQgPSB0b2tlblxyXG5cdFx0XHRjb250aW51ZVxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHRpZiAoaXNTaXplKHRva2VuKSkge1xyXG5cdFx0XHR2YXIgcGFydHMgPSBzcGxpdEJ5KHRva2VuLCAnLycpXHJcblx0XHRcdGZvbnQuc2l6ZSA9IHBhcnRzWzBdXHJcblx0XHRcdGlmIChwYXJ0c1sxXSAhPSBudWxsKSB7XHJcblx0XHRcdFx0Zm9udC5saW5lSGVpZ2h0ID0gcGFyc2VMaW5lSGVpZ2h0KHBhcnRzWzFdKVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKHRva2Vuc1swXSA9PT0gJy8nKSB7XHJcblx0XHRcdFx0dG9rZW5zLnNoaWZ0KClcclxuXHRcdFx0XHRmb250LmxpbmVIZWlnaHQgPSBwYXJzZUxpbmVIZWlnaHQodG9rZW5zLnNoaWZ0KCkpXHJcbiBcdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAoIXRva2Vucy5sZW5ndGgpIHtcclxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZm9udC1mYW1pbHkuJylcclxuXHRcdFx0fVxyXG5cdFx0XHRmb250LmZhbWlseSA9IHNwbGl0QnkodG9rZW5zLmpvaW4oJyAnKSwgL1xccyosXFxzKi8pLm1hcCh1bnF1b3RlKVxyXG5cclxuXHRcdFx0cmV0dXJuIGNhY2hlW3ZhbHVlXSA9IGZvbnRcclxuXHRcdH1cclxuXHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gb3IgdW5zdXBwb3J0ZWQgZm9udCB0b2tlbjogJyArIHRva2VuKVxyXG5cdH1cclxuXHJcblx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGZvbnQtc2l6ZS4nKVxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcGFyc2VMaW5lSGVpZ2h0KHZhbHVlKSB7XHJcblx0dmFyIHBhcnNlZCA9IHBhcnNlRmxvYXQodmFsdWUpXHJcblx0aWYgKHBhcnNlZC50b1N0cmluZygpID09PSB2YWx1ZSkge1xyXG5cdFx0cmV0dXJuIHBhcnNlZFxyXG5cdH1cclxuXHRyZXR1cm4gdmFsdWVcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBwaWNrID0gcmVxdWlyZSgncGljay1ieS1hbGlhcycpXHJcbnZhciBpc1NpemUgPSByZXF1aXJlKCcuL2xpYi91dGlsJykuaXNTaXplXHJcblxyXG52YXIgZ2xvYmFscyA9IGEybyhyZXF1aXJlKCdjc3MtZ2xvYmFsLWtleXdvcmRzJykpXHJcbnZhciBzeXN0ZW1zID0gYTJvKHJlcXVpcmUoJ2Nzcy1zeXN0ZW0tZm9udC1rZXl3b3JkcycpKVxyXG52YXIgd2VpZ2h0cyA9IGEybyhyZXF1aXJlKCdjc3MtZm9udC13ZWlnaHQta2V5d29yZHMnKSlcclxudmFyIHN0eWxlcyA9IGEybyhyZXF1aXJlKCdjc3MtZm9udC1zdHlsZS1rZXl3b3JkcycpKVxyXG52YXIgc3RyZXRjaGVzID0gYTJvKHJlcXVpcmUoJ2Nzcy1mb250LXN0cmV0Y2gta2V5d29yZHMnKSlcclxuXHJcbnZhciB2YXJpYW50cyA9IHsnbm9ybWFsJzogMSwgJ3NtYWxsLWNhcHMnOiAxfVxyXG52YXIgZmFtcyA9IHtcclxuXHQnc2VyaWYnOiAxLFxyXG5cdCdzYW5zLXNlcmlmJzogMSxcclxuXHQnbW9ub3NwYWNlJzogMSxcclxuXHQnY3Vyc2l2ZSc6IDEsXHJcblx0J2ZhbnRhc3knOiAxLFxyXG5cdCdzeXN0ZW0tdWknOiAxXHJcbn1cclxuXHJcbnZhciBkZWZhdWx0cyA9IHtcclxuXHRzdHlsZTogJ25vcm1hbCcsXHJcblx0dmFyaWFudDogJ25vcm1hbCcsXHJcblx0d2VpZ2h0OiAnbm9ybWFsJyxcclxuXHRzdHJldGNoOiAnbm9ybWFsJyxcclxuXHRzaXplOiAnMXJlbScsXHJcblx0bGluZUhlaWdodDogJ25vcm1hbCcsXHJcblx0ZmFtaWx5OiAnc2VyaWYnXHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3RyaW5naWZ5Rm9udCAobykge1xyXG5cdG8gPSBwaWNrKG8sIHtcclxuXHRcdHN0eWxlOiAnc3R5bGUgZm9udHN0eWxlIGZvbnRTdHlsZSBmb250LXN0eWxlIHNsb3BlIGRpc3RpbmN0aW9uJyxcclxuXHRcdHZhcmlhbnQ6ICd2YXJpYW50IGZvbnQtdmFyaWFudCBmb250VmFyaWFudCBmb250dmFyaWFudCB2YXIgY2FwaXRhbGl6YXRpb24nLFxyXG5cdFx0d2VpZ2h0OiAnd2VpZ2h0IHcgZm9udC13ZWlnaHQgZm9udFdlaWdodCBmb250d2VpZ2h0JyxcclxuXHRcdHN0cmV0Y2g6ICdzdHJldGNoIGZvbnQtc3RyZXRjaCBmb250U3RyZXRjaCBmb250c3RyZXRjaCB3aWR0aCcsXHJcblx0XHRzaXplOiAnc2l6ZSBzIGZvbnQtc2l6ZSBmb250U2l6ZSBmb250c2l6ZSBoZWlnaHQgZW0gZW1TaXplJyxcclxuXHRcdGxpbmVIZWlnaHQ6ICdsaCBsaW5lLWhlaWdodCBsaW5lSGVpZ2h0IGxpbmVoZWlnaHQgbGVhZGluZycsXHJcblx0XHRmYW1pbHk6ICdmb250IGZhbWlseSBmb250RmFtaWx5IGZvbnQtZmFtaWx5IGZvbnRmYW1pbHkgdHlwZSB0eXBlZmFjZSBmYWNlJyxcclxuXHRcdHN5c3RlbTogJ3N5c3RlbSByZXNlcnZlZCBkZWZhdWx0IGdsb2JhbCcsXHJcblx0fSlcclxuXHJcblx0aWYgKG8uc3lzdGVtKSB7XHJcblx0XHRpZiAoby5zeXN0ZW0pIHZlcmlmeShvLnN5c3RlbSwgc3lzdGVtcylcclxuXHRcdHJldHVybiBvLnN5c3RlbVxyXG5cdH1cclxuXHJcblx0dmVyaWZ5KG8uc3R5bGUsIHN0eWxlcylcclxuXHR2ZXJpZnkoby52YXJpYW50LCB2YXJpYW50cylcclxuXHR2ZXJpZnkoby53ZWlnaHQsIHdlaWdodHMpXHJcblx0dmVyaWZ5KG8uc3RyZXRjaCwgc3RyZXRjaGVzKVxyXG5cclxuXHQvLyBkZWZhdWx0IHJvb3QgdmFsdWUgaXMgbWVkaXVtLCBidXQgYnkgZGVmYXVsdCBpdCdzIGluaGVyaXRlZFxyXG5cdGlmIChvLnNpemUgPT0gbnVsbCkgby5zaXplID0gZGVmYXVsdHMuc2l6ZVxyXG5cdGlmICh0eXBlb2Ygby5zaXplID09PSAnbnVtYmVyJykgby5zaXplICs9ICdweCdcclxuXHJcblx0aWYgKCFpc1NpemUpIHRocm93IEVycm9yKCdCYWQgc2l6ZSB2YWx1ZSBgJyArIG8uc2l6ZSArICdgJylcclxuXHJcblx0Ly8gbWFueSB1c2VyLWFnZW50cyB1c2Ugc2VyaWYsIHdlIGRvbid0IGRldGVjdCB0aGF0IGZvciBjb25zaXN0ZW5jeVxyXG5cdGlmICghby5mYW1pbHkpIG8uZmFtaWx5ID0gZGVmYXVsdHMuZmFtaWx5XHJcblx0aWYgKEFycmF5LmlzQXJyYXkoby5mYW1pbHkpKSB7XHJcblx0XHRpZiAoIW8uZmFtaWx5Lmxlbmd0aCkgby5mYW1pbHkgPSBbZGVmYXVsdHMuZmFtaWx5XVxyXG5cdFx0by5mYW1pbHkgPSBvLmZhbWlseS5tYXAoZnVuY3Rpb24gKGYpIHtcclxuXHRcdFx0cmV0dXJuIGZhbXNbZl0gPyBmIDogJ1wiJyArIGYgKyAnXCInXHJcblx0XHR9KS5qb2luKCcsICcpXHJcblx0fVxyXG5cclxuXHQvLyBbIFsgPCdmb250LXN0eWxlJz4gfHwgPGZvbnQtdmFyaWFudC1jc3MyMT4gfHwgPCdmb250LXdlaWdodCc+IHx8IDwnZm9udC1zdHJldGNoJz4gXT8gPCdmb250LXNpemUnPiBbIC8gPCdsaW5lLWhlaWdodCc+IF0/IDwnZm9udC1mYW1pbHknPiBdXHJcblx0dmFyIHJlc3VsdCA9IFtdXHJcblxyXG5cdHJlc3VsdC5wdXNoKG8uc3R5bGUpXHJcblx0aWYgKG8udmFyaWFudCAhPT0gby5zdHlsZSkgcmVzdWx0LnB1c2goby52YXJpYW50KVxyXG5cclxuXHRpZiAoby53ZWlnaHQgIT09IG8udmFyaWFudCAmJlxyXG5cdFx0by53ZWlnaHQgIT09IG8uc3R5bGUpIHJlc3VsdC5wdXNoKG8ud2VpZ2h0KVxyXG5cclxuXHRpZiAoby5zdHJldGNoICE9PSBvLndlaWdodCAmJlxyXG5cdFx0by5zdHJldGNoICE9PSBvLnZhcmlhbnQgJiZcclxuXHRcdG8uc3RyZXRjaCAhPT0gby5zdHlsZSkgcmVzdWx0LnB1c2goby5zdHJldGNoKVxyXG5cclxuXHRyZXN1bHQucHVzaChvLnNpemUgKyAoby5saW5lSGVpZ2h0ID09IG51bGwgfHwgby5saW5lSGVpZ2h0ID09PSAnbm9ybWFsJyB8fCAoby5saW5lSGVpZ2h0ICsgJycgPT09ICcxJykgID8gJycgOiAoJy8nICsgby5saW5lSGVpZ2h0KSkpXHJcblx0cmVzdWx0LnB1c2goby5mYW1pbHkpXHJcblxyXG5cdHJldHVybiByZXN1bHQuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJyAnKVxyXG59XHJcblxyXG5mdW5jdGlvbiB2ZXJpZnkgKHZhbHVlLCB2YWx1ZXMpIHtcclxuXHRpZiAodmFsdWUgJiYgIXZhbHVlc1t2YWx1ZV0gJiYgIWdsb2JhbHNbdmFsdWVdKSB0aHJvdyBFcnJvcignVW5rbm93biBrZXl3b3JkIGAnICsgdmFsdWUgKydgJylcclxuXHJcblx0cmV0dXJuIHZhbHVlXHJcbn1cclxuXHJcblxyXG4vLyBbJ2EnLCAnYiddIC0+IHthOiB0cnVlLCBiOiB0cnVlfVxyXG5mdW5jdGlvbiBhMm8gKGEpIHtcclxuXHR2YXIgbyA9IHt9XHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRvW2FbaV1dID0gMVxyXG5cdH1cclxuXHRyZXR1cm4gb1xyXG59XHJcbiIsIm1vZHVsZS5leHBvcnRzPVtcclxuXHRcImluaGVyaXRcIixcclxuXHRcImluaXRpYWxcIixcclxuXHRcInVuc2V0XCJcclxuXVxyXG4iLCJtb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJjYXB0aW9uXCIsXHJcblx0XCJpY29uXCIsXHJcblx0XCJtZW51XCIsXHJcblx0XCJtZXNzYWdlLWJveFwiLFxyXG5cdFwic21hbGwtY2FwdGlvblwiLFxyXG5cdFwic3RhdHVzLWJhclwiXHJcbl1cclxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gZGN1YmljSGVybWl0ZShwMCwgdjAsIHAxLCB2MSwgdCwgZikge1xuICB2YXIgZGgwMCA9IDYqdCp0LTYqdCxcbiAgICAgIGRoMTAgPSAzKnQqdC00KnQgKyAxLFxuICAgICAgZGgwMSA9IC02KnQqdCs2KnQsXG4gICAgICBkaDExID0gMyp0KnQtMip0XG4gIGlmKHAwLmxlbmd0aCkge1xuICAgIGlmKCFmKSB7XG4gICAgICBmID0gbmV3IEFycmF5KHAwLmxlbmd0aClcbiAgICB9XG4gICAgZm9yKHZhciBpPXAwLmxlbmd0aC0xOyBpPj0wOyAtLWkpIHtcbiAgICAgIGZbaV0gPSBkaDAwKnAwW2ldICsgZGgxMCp2MFtpXSArIGRoMDEqcDFbaV0gKyBkaDExKnYxW2ldXG4gICAgfVxuICAgIHJldHVybiBmXG4gIH1cbiAgcmV0dXJuIGRoMDAqcDAgKyBkaDEwKnYwICsgZGgwMSpwMVtpXSArIGRoMTEqdjFcbn1cblxuZnVuY3Rpb24gY3ViaWNIZXJtaXRlKHAwLCB2MCwgcDEsIHYxLCB0LCBmKSB7XG4gIHZhciB0aSAgPSAodC0xKSwgdDIgPSB0KnQsIHRpMiA9IHRpKnRpLFxuICAgICAgaDAwID0gKDErMip0KSp0aTIsXG4gICAgICBoMTAgPSB0KnRpMixcbiAgICAgIGgwMSA9IHQyKigzLTIqdCksXG4gICAgICBoMTEgPSB0Mip0aVxuICBpZihwMC5sZW5ndGgpIHtcbiAgICBpZighZikge1xuICAgICAgZiA9IG5ldyBBcnJheShwMC5sZW5ndGgpXG4gICAgfVxuICAgIGZvcih2YXIgaT1wMC5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICBmW2ldID0gaDAwKnAwW2ldICsgaDEwKnYwW2ldICsgaDAxKnAxW2ldICsgaDExKnYxW2ldXG4gICAgfVxuICAgIHJldHVybiBmXG4gIH1cbiAgcmV0dXJuIGgwMCpwMCArIGgxMCp2MCArIGgwMSpwMSArIGgxMSp2MVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGN1YmljSGVybWl0ZVxubW9kdWxlLmV4cG9ydHMuZGVyaXZhdGl2ZSA9IGRjdWJpY0hlcm1pdGUiLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgY3JlYXRlVGh1bmsgPSByZXF1aXJlKFwiLi9saWIvdGh1bmsuanNcIilcblxuZnVuY3Rpb24gUHJvY2VkdXJlKCkge1xuICB0aGlzLmFyZ1R5cGVzID0gW11cbiAgdGhpcy5zaGltQXJncyA9IFtdXG4gIHRoaXMuYXJyYXlBcmdzID0gW11cbiAgdGhpcy5hcnJheUJsb2NrSW5kaWNlcyA9IFtdXG4gIHRoaXMuc2NhbGFyQXJncyA9IFtdXG4gIHRoaXMub2Zmc2V0QXJncyA9IFtdXG4gIHRoaXMub2Zmc2V0QXJnSW5kZXggPSBbXVxuICB0aGlzLmluZGV4QXJncyA9IFtdXG4gIHRoaXMuc2hhcGVBcmdzID0gW11cbiAgdGhpcy5mdW5jTmFtZSA9IFwiXCJcbiAgdGhpcy5wcmUgPSBudWxsXG4gIHRoaXMuYm9keSA9IG51bGxcbiAgdGhpcy5wb3N0ID0gbnVsbFxuICB0aGlzLmRlYnVnID0gZmFsc2Vcbn1cblxuZnVuY3Rpb24gY29tcGlsZUN3aXNlKHVzZXJfYXJncykge1xuICAvL0NyZWF0ZSBwcm9jZWR1cmVcbiAgdmFyIHByb2MgPSBuZXcgUHJvY2VkdXJlKClcbiAgXG4gIC8vUGFyc2UgYmxvY2tzXG4gIHByb2MucHJlICAgID0gdXNlcl9hcmdzLnByZVxuICBwcm9jLmJvZHkgICA9IHVzZXJfYXJncy5ib2R5XG4gIHByb2MucG9zdCAgID0gdXNlcl9hcmdzLnBvc3RcblxuICAvL1BhcnNlIGFyZ3VtZW50c1xuICB2YXIgcHJvY19hcmdzID0gdXNlcl9hcmdzLmFyZ3Muc2xpY2UoMClcbiAgcHJvYy5hcmdUeXBlcyA9IHByb2NfYXJnc1xuICBmb3IodmFyIGk9MDsgaTxwcm9jX2FyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYXJnX3R5cGUgPSBwcm9jX2FyZ3NbaV1cbiAgICBpZihhcmdfdHlwZSA9PT0gXCJhcnJheVwiIHx8ICh0eXBlb2YgYXJnX3R5cGUgPT09IFwib2JqZWN0XCIgJiYgYXJnX3R5cGUuYmxvY2tJbmRpY2VzKSkge1xuICAgICAgcHJvYy5hcmdUeXBlc1tpXSA9IFwiYXJyYXlcIlxuICAgICAgcHJvYy5hcnJheUFyZ3MucHVzaChpKVxuICAgICAgcHJvYy5hcnJheUJsb2NrSW5kaWNlcy5wdXNoKGFyZ190eXBlLmJsb2NrSW5kaWNlcyA/IGFyZ190eXBlLmJsb2NrSW5kaWNlcyA6IDApXG4gICAgICBwcm9jLnNoaW1BcmdzLnB1c2goXCJhcnJheVwiICsgaSlcbiAgICAgIGlmKGkgPCBwcm9jLnByZS5hcmdzLmxlbmd0aCAmJiBwcm9jLnByZS5hcmdzW2ldLmNvdW50PjApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHByZSgpIGJsb2NrIG1heSBub3QgcmVmZXJlbmNlIGFycmF5IGFyZ3NcIilcbiAgICAgIH1cbiAgICAgIGlmKGkgPCBwcm9jLnBvc3QuYXJncy5sZW5ndGggJiYgcHJvYy5wb3N0LmFyZ3NbaV0uY291bnQ+MCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogcG9zdCgpIGJsb2NrIG1heSBub3QgcmVmZXJlbmNlIGFycmF5IGFyZ3NcIilcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoYXJnX3R5cGUgPT09IFwic2NhbGFyXCIpIHtcbiAgICAgIHByb2Muc2NhbGFyQXJncy5wdXNoKGkpXG4gICAgICBwcm9jLnNoaW1BcmdzLnB1c2goXCJzY2FsYXJcIiArIGkpXG4gICAgfSBlbHNlIGlmKGFyZ190eXBlID09PSBcImluZGV4XCIpIHtcbiAgICAgIHByb2MuaW5kZXhBcmdzLnB1c2goaSlcbiAgICAgIGlmKGkgPCBwcm9jLnByZS5hcmdzLmxlbmd0aCAmJiBwcm9jLnByZS5hcmdzW2ldLmNvdW50ID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogcHJlKCkgYmxvY2sgbWF5IG5vdCByZWZlcmVuY2UgYXJyYXkgaW5kZXhcIilcbiAgICAgIH1cbiAgICAgIGlmKGkgPCBwcm9jLmJvZHkuYXJncy5sZW5ndGggJiYgcHJvYy5ib2R5LmFyZ3NbaV0ubHZhbHVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBib2R5KCkgYmxvY2sgbWF5IG5vdCB3cml0ZSB0byBhcnJheSBpbmRleFwiKVxuICAgICAgfVxuICAgICAgaWYoaSA8IHByb2MucG9zdC5hcmdzLmxlbmd0aCAmJiBwcm9jLnBvc3QuYXJnc1tpXS5jb3VudCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHBvc3QoKSBibG9jayBtYXkgbm90IHJlZmVyZW5jZSBhcnJheSBpbmRleFwiKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZihhcmdfdHlwZSA9PT0gXCJzaGFwZVwiKSB7XG4gICAgICBwcm9jLnNoYXBlQXJncy5wdXNoKGkpXG4gICAgICBpZihpIDwgcHJvYy5wcmUuYXJncy5sZW5ndGggJiYgcHJvYy5wcmUuYXJnc1tpXS5sdmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHByZSgpIGJsb2NrIG1heSBub3Qgd3JpdGUgdG8gYXJyYXkgc2hhcGVcIilcbiAgICAgIH1cbiAgICAgIGlmKGkgPCBwcm9jLmJvZHkuYXJncy5sZW5ndGggJiYgcHJvYy5ib2R5LmFyZ3NbaV0ubHZhbHVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBib2R5KCkgYmxvY2sgbWF5IG5vdCB3cml0ZSB0byBhcnJheSBzaGFwZVwiKVxuICAgICAgfVxuICAgICAgaWYoaSA8IHByb2MucG9zdC5hcmdzLmxlbmd0aCAmJiBwcm9jLnBvc3QuYXJnc1tpXS5sdmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHBvc3QoKSBibG9jayBtYXkgbm90IHdyaXRlIHRvIGFycmF5IHNoYXBlXCIpXG4gICAgICB9XG4gICAgfSBlbHNlIGlmKHR5cGVvZiBhcmdfdHlwZSA9PT0gXCJvYmplY3RcIiAmJiBhcmdfdHlwZS5vZmZzZXQpIHtcbiAgICAgIHByb2MuYXJnVHlwZXNbaV0gPSBcIm9mZnNldFwiXG4gICAgICBwcm9jLm9mZnNldEFyZ3MucHVzaCh7IGFycmF5OiBhcmdfdHlwZS5hcnJheSwgb2Zmc2V0OmFyZ190eXBlLm9mZnNldCB9KVxuICAgICAgcHJvYy5vZmZzZXRBcmdJbmRleC5wdXNoKGkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBVbmtub3duIGFyZ3VtZW50IHR5cGUgXCIgKyBwcm9jX2FyZ3NbaV0pXG4gICAgfVxuICB9XG4gIFxuICAvL01ha2Ugc3VyZSBhdCBsZWFzdCBvbmUgYXJyYXkgYXJndW1lbnQgd2FzIHNwZWNpZmllZFxuICBpZihwcm9jLmFycmF5QXJncy5sZW5ndGggPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBObyBhcnJheSBhcmd1bWVudHMgc3BlY2lmaWVkXCIpXG4gIH1cbiAgXG4gIC8vTWFrZSBzdXJlIGFyZ3VtZW50cyBhcmUgY29ycmVjdFxuICBpZihwcm9jLnByZS5hcmdzLmxlbmd0aCA+IHByb2NfYXJncy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogVG9vIG1hbnkgYXJndW1lbnRzIGluIHByZSgpIGJsb2NrXCIpXG4gIH1cbiAgaWYocHJvYy5ib2R5LmFyZ3MubGVuZ3RoID4gcHJvY19hcmdzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBUb28gbWFueSBhcmd1bWVudHMgaW4gYm9keSgpIGJsb2NrXCIpXG4gIH1cbiAgaWYocHJvYy5wb3N0LmFyZ3MubGVuZ3RoID4gcHJvY19hcmdzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBUb28gbWFueSBhcmd1bWVudHMgaW4gcG9zdCgpIGJsb2NrXCIpXG4gIH1cblxuICAvL0NoZWNrIGRlYnVnIGZsYWdcbiAgcHJvYy5kZWJ1ZyA9ICEhdXNlcl9hcmdzLnByaW50Q29kZSB8fCAhIXVzZXJfYXJncy5kZWJ1Z1xuICBcbiAgLy9SZXRyaWV2ZSBuYW1lXG4gIHByb2MuZnVuY05hbWUgPSB1c2VyX2FyZ3MuZnVuY05hbWUgfHwgXCJjd2lzZVwiXG4gIFxuICAvL1JlYWQgaW4gYmxvY2sgc2l6ZVxuICBwcm9jLmJsb2NrU2l6ZSA9IHVzZXJfYXJncy5ibG9ja1NpemUgfHwgNjRcblxuICByZXR1cm4gY3JlYXRlVGh1bmsocHJvYylcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb21waWxlQ3dpc2VcbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciB1bmlxID0gcmVxdWlyZShcInVuaXFcIilcblxuLy8gVGhpcyBmdW5jdGlvbiBnZW5lcmF0ZXMgdmVyeSBzaW1wbGUgbG9vcHMgYW5hbG9nb3VzIHRvIGhvdyB5b3UgdHlwaWNhbGx5IHRyYXZlcnNlIGFycmF5cyAodGhlIG91dGVybW9zdCBsb29wIGNvcnJlc3BvbmRzIHRvIHRoZSBzbG93ZXN0IGNoYW5naW5nIGluZGV4LCB0aGUgaW5uZXJtb3N0IGxvb3AgdG8gdGhlIGZhc3Rlc3QgY2hhbmdpbmcgaW5kZXgpXG4vLyBUT0RPOiBJZiB0d28gYXJyYXlzIGhhdmUgdGhlIHNhbWUgc3RyaWRlcyAoYW5kIG9mZnNldHMpIHRoZXJlIGlzIHBvdGVudGlhbCBmb3IgZGVjcmVhc2luZyB0aGUgbnVtYmVyIG9mIFwicG9pbnRlcnNcIiBhbmQgcmVsYXRlZCB2YXJpYWJsZXMuIFRoZSBkcmF3YmFjayBpcyB0aGF0IHRoZSB0eXBlIHNpZ25hdHVyZSB3b3VsZCBiZWNvbWUgbW9yZSBzcGVjaWZpYyBhbmQgdGhhdCB0aGVyZSB3b3VsZCB0aHVzIGJlIGxlc3MgcG90ZW50aWFsIGZvciBjYWNoaW5nLCBidXQgaXQgbWlnaHQgc3RpbGwgYmUgd29ydGggaXQsIGVzcGVjaWFsbHkgd2hlbiBkZWFsaW5nIHdpdGggbGFyZ2UgbnVtYmVycyBvZiBhcmd1bWVudHMuXG5mdW5jdGlvbiBpbm5lckZpbGwob3JkZXIsIHByb2MsIGJvZHkpIHtcbiAgdmFyIGRpbWVuc2lvbiA9IG9yZGVyLmxlbmd0aFxuICAgICwgbmFyZ3MgPSBwcm9jLmFycmF5QXJncy5sZW5ndGhcbiAgICAsIGhhc19pbmRleCA9IHByb2MuaW5kZXhBcmdzLmxlbmd0aD4wXG4gICAgLCBjb2RlID0gW11cbiAgICAsIHZhcnMgPSBbXVxuICAgICwgaWR4PTAsIHBpZHg9MCwgaSwgalxuICBmb3IoaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7IC8vIEl0ZXJhdGlvbiB2YXJpYWJsZXNcbiAgICB2YXJzLnB1c2goW1wiaVwiLGksXCI9MFwiXS5qb2luKFwiXCIpKVxuICB9XG4gIC8vQ29tcHV0ZSBzY2FuIGRlbHRhc1xuICBmb3Ioaj0wOyBqPG5hcmdzOyArK2opIHtcbiAgICBmb3IoaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICBwaWR4ID0gaWR4XG4gICAgICBpZHggPSBvcmRlcltpXVxuICAgICAgaWYoaSA9PT0gMCkgeyAvLyBUaGUgaW5uZXJtb3N0L2Zhc3Rlc3QgZGltZW5zaW9uJ3MgZGVsdGEgaXMgc2ltcGx5IGl0cyBzdHJpZGVcbiAgICAgICAgdmFycy5wdXNoKFtcImRcIixqLFwic1wiLGksXCI9dFwiLGosXCJwXCIsaWR4XS5qb2luKFwiXCIpKVxuICAgICAgfSBlbHNlIHsgLy8gRm9yIG90aGVyIGRpbWVuc2lvbnMgdGhlIGRlbHRhIGlzIGJhc2ljYWxseSB0aGUgc3RyaWRlIG1pbnVzIHNvbWV0aGluZyB3aGljaCBlc3NlbnRpYWxseSBcInJld2luZHNcIiB0aGUgcHJldmlvdXMgKG1vcmUgaW5uZXIpIGRpbWVuc2lvblxuICAgICAgICB2YXJzLnB1c2goW1wiZFwiLGosXCJzXCIsaSxcIj0odFwiLGosXCJwXCIsaWR4LFwiLXNcIixwaWR4LFwiKnRcIixqLFwicFwiLHBpZHgsXCIpXCJdLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmICh2YXJzLmxlbmd0aCA+IDApIHtcbiAgICBjb2RlLnB1c2goXCJ2YXIgXCIgKyB2YXJzLmpvaW4oXCIsXCIpKVxuICB9ICBcbiAgLy9TY2FuIGxvb3BcbiAgZm9yKGk9ZGltZW5zaW9uLTE7IGk+PTA7IC0taSkgeyAvLyBTdGFydCBhdCBsYXJnZXN0IHN0cmlkZSBhbmQgd29yayB5b3VyIHdheSBpbndhcmRzXG4gICAgaWR4ID0gb3JkZXJbaV1cbiAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixpLFwiPTA7aVwiLGksXCI8c1wiLGlkeCxcIjsrK2lcIixpLFwiKXtcIl0uam9pbihcIlwiKSlcbiAgfVxuICAvL1B1c2ggYm9keSBvZiBpbm5lciBsb29wXG4gIGNvZGUucHVzaChib2R5KVxuICAvL0FkdmFuY2Ugc2NhbiBwb2ludGVyc1xuICBmb3IoaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgcGlkeCA9IGlkeFxuICAgIGlkeCA9IG9yZGVyW2ldXG4gICAgZm9yKGo9MDsgajxuYXJnczsgKytqKSB7XG4gICAgICBjb2RlLnB1c2goW1wicFwiLGosXCIrPWRcIixqLFwic1wiLGldLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGlmKGhhc19pbmRleCkge1xuICAgICAgaWYoaSA+IDApIHtcbiAgICAgICAgY29kZS5wdXNoKFtcImluZGV4W1wiLHBpZHgsXCJdLT1zXCIscGlkeF0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChbXCIrK2luZGV4W1wiLGlkeCxcIl1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgY29kZS5wdXNoKFwifVwiKVxuICB9XG4gIHJldHVybiBjb2RlLmpvaW4oXCJcXG5cIilcbn1cblxuLy8gR2VuZXJhdGUgXCJvdXRlclwiIGxvb3BzIHRoYXQgbG9vcCBvdmVyIGJsb2NrcyBvZiBkYXRhLCBhcHBseWluZyBcImlubmVyXCIgbG9vcHMgdG8gdGhlIGJsb2NrcyBieSBtYW5pcHVsYXRpbmcgdGhlIGxvY2FsIHZhcmlhYmxlcyBpbiBzdWNoIGEgd2F5IHRoYXQgdGhlIGlubmVyIGxvb3Agb25seSBcInNlZXNcIiB0aGUgY3VycmVudCBibG9jay5cbi8vIFRPRE86IElmIHRoaXMgaXMgdXNlZCwgdGhlbiB0aGUgcHJldmlvdXMgZGVjbGFyYXRpb24gKGRvbmUgYnkgZ2VuZXJhdGVDd2lzZU9wKSBvZiBzKiBpcyBlc3NlbnRpYWxseSB1bm5lY2Vzc2FyeS5cbi8vICAgICAgIEkgYmVsaWV2ZSB0aGUgcyogYXJlIG5vdCB1c2VkIGVsc2V3aGVyZSAoaW4gcGFydGljdWxhciwgSSBkb24ndCB0aGluayB0aGV5J3JlIHVzZWQgaW4gdGhlIHByZS9wb3N0IHBhcnRzIGFuZCBcInNoYXBlXCIgaXMgZGVmaW5lZCBpbmRlcGVuZGVudGx5KSwgc28gaXQgd291bGQgYmUgcG9zc2libGUgdG8gbWFrZSBkZWZpbmluZyB0aGUgcyogZGVwZW5kZW50IG9uIHdoYXQgbG9vcCBtZXRob2QgaXMgYmVpbmcgdXNlZC5cbmZ1bmN0aW9uIG91dGVyRmlsbChtYXRjaGVkLCBvcmRlciwgcHJvYywgYm9keSkge1xuICB2YXIgZGltZW5zaW9uID0gb3JkZXIubGVuZ3RoXG4gICAgLCBuYXJncyA9IHByb2MuYXJyYXlBcmdzLmxlbmd0aFxuICAgICwgYmxvY2tTaXplID0gcHJvYy5ibG9ja1NpemVcbiAgICAsIGhhc19pbmRleCA9IHByb2MuaW5kZXhBcmdzLmxlbmd0aCA+IDBcbiAgICAsIGNvZGUgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxuYXJnczsgKytpKSB7XG4gICAgY29kZS5wdXNoKFtcInZhciBvZmZzZXRcIixpLFwiPXBcIixpXS5qb2luKFwiXCIpKVxuICB9XG4gIC8vR2VuZXJhdGUgbG9vcHMgZm9yIHVubWF0Y2hlZCBkaW1lbnNpb25zXG4gIC8vIFRoZSBvcmRlciBpbiB3aGljaCB0aGVzZSBkaW1lbnNpb25zIGFyZSB0cmF2ZXJzZWQgaXMgZmFpcmx5IGFyYml0cmFyeSAoZnJvbSBzbWFsbCBzdHJpZGUgdG8gbGFyZ2Ugc3RyaWRlLCBmb3IgdGhlIGZpcnN0IGFyZ3VtZW50KVxuICAvLyBUT0RPOiBJdCB3b3VsZCBiZSBuaWNlIGlmIHRoZSBvcmRlciBpbiB3aGljaCB0aGVzZSBsb29wcyBhcmUgcGxhY2VkIHdvdWxkIGFsc28gYmUgc29tZWhvdyBcIm9wdGltYWxcIiAoYXQgdGhlIHZlcnkgbGVhc3Qgd2Ugc2hvdWxkIGNoZWNrIHRoYXQgaXQgcmVhbGx5IGRvZXNuJ3QgaHVydCB1cyBpZiB0aGV5J3JlIG5vdCkuXG4gIGZvcih2YXIgaT1tYXRjaGVkOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgY29kZS5wdXNoKFtcImZvcih2YXIgalwiK2krXCI9U1NbXCIsIG9yZGVyW2ldLCBcIl18MDtqXCIsIGksIFwiPjA7KXtcIl0uam9pbihcIlwiKSkgLy8gSXRlcmF0ZSBiYWNrIHRvIGZyb250XG4gICAgY29kZS5wdXNoKFtcImlmKGpcIixpLFwiPFwiLGJsb2NrU2l6ZSxcIil7XCJdLmpvaW4oXCJcIikpIC8vIEVpdGhlciBkZWNyZWFzZSBqIGJ5IGJsb2NrU2l6ZSAocyA9IGJsb2NrU2l6ZSksIG9yIHNldCBpdCB0byB6ZXJvIChhZnRlciBzZXR0aW5nIHMgPSBqKS5cbiAgICBjb2RlLnB1c2goW1wic1wiLG9yZGVyW2ldLFwiPWpcIixpXS5qb2luKFwiXCIpKVxuICAgIGNvZGUucHVzaChbXCJqXCIsaSxcIj0wXCJdLmpvaW4oXCJcIikpXG4gICAgY29kZS5wdXNoKFtcIn1lbHNle3NcIixvcmRlcltpXSxcIj1cIixibG9ja1NpemVdLmpvaW4oXCJcIikpXG4gICAgY29kZS5wdXNoKFtcImpcIixpLFwiLT1cIixibG9ja1NpemUsXCJ9XCJdLmpvaW4oXCJcIikpXG4gICAgaWYoaGFzX2luZGV4KSB7XG4gICAgICBjb2RlLnB1c2goW1wiaW5kZXhbXCIsb3JkZXJbaV0sXCJdPWpcIixpXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgfVxuICBmb3IodmFyIGk9MDsgaTxuYXJnczsgKytpKSB7XG4gICAgdmFyIGluZGV4U3RyID0gW1wib2Zmc2V0XCIraV1cbiAgICBmb3IodmFyIGo9bWF0Y2hlZDsgajxkaW1lbnNpb247ICsraikge1xuICAgICAgaW5kZXhTdHIucHVzaChbXCJqXCIsaixcIip0XCIsaSxcInBcIixvcmRlcltqXV0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgY29kZS5wdXNoKFtcInBcIixpLFwiPShcIixpbmRleFN0ci5qb2luKFwiK1wiKSxcIilcIl0uam9pbihcIlwiKSlcbiAgfVxuICBjb2RlLnB1c2goaW5uZXJGaWxsKG9yZGVyLCBwcm9jLCBib2R5KSlcbiAgZm9yKHZhciBpPW1hdGNoZWQ7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXCJ9XCIpXG4gIH1cbiAgcmV0dXJuIGNvZGUuam9pbihcIlxcblwiKVxufVxuXG4vL0NvdW50IHRoZSBudW1iZXIgb2YgY29tcGF0aWJsZSBpbm5lciBvcmRlcnNcbi8vIFRoaXMgaXMgdGhlIGxlbmd0aCBvZiB0aGUgbG9uZ2VzdCBjb21tb24gcHJlZml4IG9mIHRoZSBhcnJheXMgaW4gb3JkZXJzLlxuLy8gRWFjaCBhcnJheSBpbiBvcmRlcnMgbGlzdHMgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIGNvcnJlc3BvbmQgbmRhcnJheSBpbiBvcmRlciBvZiBpbmNyZWFzaW5nIHN0cmlkZS5cbi8vIFRoaXMgaXMgdGh1cyB0aGUgbWF4aW11bSBudW1iZXIgb2YgZGltZW5zaW9ucyB0aGF0IGNhbiBiZSBlZmZpY2llbnRseSB0cmF2ZXJzZWQgYnkgc2ltcGxlIG5lc3RlZCBsb29wcyBmb3IgYWxsIGFycmF5cy5cbmZ1bmN0aW9uIGNvdW50TWF0Y2hlcyhvcmRlcnMpIHtcbiAgdmFyIG1hdGNoZWQgPSAwLCBkaW1lbnNpb24gPSBvcmRlcnNbMF0ubGVuZ3RoXG4gIHdoaWxlKG1hdGNoZWQgPCBkaW1lbnNpb24pIHtcbiAgICBmb3IodmFyIGo9MTsgajxvcmRlcnMubGVuZ3RoOyArK2opIHtcbiAgICAgIGlmKG9yZGVyc1tqXVttYXRjaGVkXSAhPT0gb3JkZXJzWzBdW21hdGNoZWRdKSB7XG4gICAgICAgIHJldHVybiBtYXRjaGVkXG4gICAgICB9XG4gICAgfVxuICAgICsrbWF0Y2hlZFxuICB9XG4gIHJldHVybiBtYXRjaGVkXG59XG5cbi8vUHJvY2Vzc2VzIGEgYmxvY2sgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBkYXRhIHR5cGVzXG4vLyBSZXBsYWNlcyB2YXJpYWJsZSBuYW1lcyBieSBkaWZmZXJlbnQgb25lcywgZWl0aGVyIFwibG9jYWxcIiBvbmVzICh0aGF0IGFyZSB0aGVuIGZlcnJpZWQgaW4gYW5kIG91dCBvZiB0aGUgZ2l2ZW4gYXJyYXkpIG9yIG9uZXMgbWF0Y2hpbmcgdGhlIGFyZ3VtZW50cyB0aGF0IHRoZSBmdW5jdGlvbiBwZXJmb3JtaW5nIHRoZSB1bHRpbWF0ZSBsb29wIHdpbGwgYWNjZXB0LlxuZnVuY3Rpb24gcHJvY2Vzc0Jsb2NrKGJsb2NrLCBwcm9jLCBkdHlwZXMpIHtcbiAgdmFyIGNvZGUgPSBibG9jay5ib2R5XG4gIHZhciBwcmUgPSBbXVxuICB2YXIgcG9zdCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGJsb2NrLmFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgY2FyZyA9IGJsb2NrLmFyZ3NbaV1cbiAgICBpZihjYXJnLmNvdW50IDw9IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIHZhciByZSA9IG5ldyBSZWdFeHAoY2FyZy5uYW1lLCBcImdcIilcbiAgICB2YXIgcHRyU3RyID0gXCJcIlxuICAgIHZhciBhcnJOdW0gPSBwcm9jLmFycmF5QXJncy5pbmRleE9mKGkpXG4gICAgc3dpdGNoKHByb2MuYXJnVHlwZXNbaV0pIHtcbiAgICAgIGNhc2UgXCJvZmZzZXRcIjpcbiAgICAgICAgdmFyIG9mZkFyZ0luZGV4ID0gcHJvYy5vZmZzZXRBcmdJbmRleC5pbmRleE9mKGkpXG4gICAgICAgIHZhciBvZmZBcmcgPSBwcm9jLm9mZnNldEFyZ3Nbb2ZmQXJnSW5kZXhdXG4gICAgICAgIGFyck51bSA9IG9mZkFyZy5hcnJheVxuICAgICAgICBwdHJTdHIgPSBcIitxXCIgKyBvZmZBcmdJbmRleCAvLyBBZGRzIG9mZnNldCB0byB0aGUgXCJwb2ludGVyXCIgaW4gdGhlIGFycmF5XG4gICAgICBjYXNlIFwiYXJyYXlcIjpcbiAgICAgICAgcHRyU3RyID0gXCJwXCIgKyBhcnJOdW0gKyBwdHJTdHJcbiAgICAgICAgdmFyIGxvY2FsU3RyID0gXCJsXCIgKyBpXG4gICAgICAgIHZhciBhcnJTdHIgPSBcImFcIiArIGFyck51bVxuICAgICAgICBpZiAocHJvYy5hcnJheUJsb2NrSW5kaWNlc1thcnJOdW1dID09PSAwKSB7IC8vIEFyZ3VtZW50IHRvIGJvZHkgaXMganVzdCBhIHNpbmdsZSB2YWx1ZSBmcm9tIHRoaXMgYXJyYXlcbiAgICAgICAgICBpZihjYXJnLmNvdW50ID09PSAxKSB7IC8vIEFyZ3VtZW50L2FycmF5IHVzZWQgb25seSBvbmNlKD8pXG4gICAgICAgICAgICBpZihkdHlwZXNbYXJyTnVtXSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgICAgICAgICAgaWYoY2FyZy5sdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBwcmUucHVzaChbXCJ2YXIgXCIsIGxvY2FsU3RyLCBcIj1cIiwgYXJyU3RyLCBcIi5nZXQoXCIsIHB0clN0ciwgXCIpXCJdLmpvaW4oXCJcIikpIC8vIElzIHRoaXMgbmVjZXNzYXJ5IGlmIHRoZSBhcmd1bWVudCBpcyBPTkxZIHVzZWQgYXMgYW4gbHZhbHVlPyAoa2VlcCBpbiBtaW5kIHRoYXQgd2UgY2FuIGhhdmUgYSArPSBzb21ldGhpbmcsIHNvIHdlIHdvdWxkIGFjdHVhbGx5IG5lZWQgdG8gY2hlY2sgY2FyZy5ydmFsdWUpXG4gICAgICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgbG9jYWxTdHIpXG4gICAgICAgICAgICAgICAgcG9zdC5wdXNoKFthcnJTdHIsIFwiLnNldChcIiwgcHRyU3RyLCBcIixcIiwgbG9jYWxTdHIsXCIpXCJdLmpvaW4oXCJcIikpXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgW2FyclN0ciwgXCIuZ2V0KFwiLCBwdHJTdHIsIFwiKVwiXS5qb2luKFwiXCIpKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBbYXJyU3RyLCBcIltcIiwgcHRyU3RyLCBcIl1cIl0uam9pbihcIlwiKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYoZHR5cGVzW2Fyck51bV0gPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICAgICAgICBwcmUucHVzaChbXCJ2YXIgXCIsIGxvY2FsU3RyLCBcIj1cIiwgYXJyU3RyLCBcIi5nZXQoXCIsIHB0clN0ciwgXCIpXCJdLmpvaW4oXCJcIikpIC8vIFRPRE86IENvdWxkIHdlIG9wdGltaXplIGJ5IGNoZWNraW5nIGZvciBjYXJnLnJ2YWx1ZT9cbiAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIGxvY2FsU3RyKVxuICAgICAgICAgICAgaWYoY2FyZy5sdmFsdWUpIHtcbiAgICAgICAgICAgICAgcG9zdC5wdXNoKFthcnJTdHIsIFwiLnNldChcIiwgcHRyU3RyLCBcIixcIiwgbG9jYWxTdHIsXCIpXCJdLmpvaW4oXCJcIikpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZS5wdXNoKFtcInZhciBcIiwgbG9jYWxTdHIsIFwiPVwiLCBhcnJTdHIsIFwiW1wiLCBwdHJTdHIsIFwiXVwiXS5qb2luKFwiXCIpKSAvLyBUT0RPOiBDb3VsZCB3ZSBvcHRpbWl6ZSBieSBjaGVja2luZyBmb3IgY2FyZy5ydmFsdWU/XG4gICAgICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBsb2NhbFN0cilcbiAgICAgICAgICAgIGlmKGNhcmcubHZhbHVlKSB7XG4gICAgICAgICAgICAgIHBvc3QucHVzaChbYXJyU3RyLCBcIltcIiwgcHRyU3RyLCBcIl09XCIsIGxvY2FsU3RyXS5qb2luKFwiXCIpKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHsgLy8gQXJndW1lbnQgdG8gYm9keSBpcyBhIFwiYmxvY2tcIlxuICAgICAgICAgIHZhciByZVN0ckFyciA9IFtjYXJnLm5hbWVdLCBwdHJTdHJBcnIgPSBbcHRyU3RyXVxuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPE1hdGguYWJzKHByb2MuYXJyYXlCbG9ja0luZGljZXNbYXJyTnVtXSk7IGorKykge1xuICAgICAgICAgICAgcmVTdHJBcnIucHVzaChcIlxcXFxzKlxcXFxbKFteXFxcXF1dKylcXFxcXVwiKVxuICAgICAgICAgICAgcHRyU3RyQXJyLnB1c2goXCIkXCIgKyAoaisxKSArIFwiKnRcIiArIGFyck51bSArIFwiYlwiICsgaikgLy8gTWF0Y2hlZCBpbmRleCB0aW1lcyBzdHJpZGVcbiAgICAgICAgICB9XG4gICAgICAgICAgcmUgPSBuZXcgUmVnRXhwKHJlU3RyQXJyLmpvaW4oXCJcIiksIFwiZ1wiKVxuICAgICAgICAgIHB0clN0ciA9IHB0clN0ckFyci5qb2luKFwiK1wiKVxuICAgICAgICAgIGlmKGR0eXBlc1thcnJOdW1dID09PSBcImdlbmVyaWNcIikge1xuICAgICAgICAgICAgLyppZihjYXJnLmx2YWx1ZSkge1xuICAgICAgICAgICAgICBwcmUucHVzaChbXCJ2YXIgXCIsIGxvY2FsU3RyLCBcIj1cIiwgYXJyU3RyLCBcIi5nZXQoXCIsIHB0clN0ciwgXCIpXCJdLmpvaW4oXCJcIikpIC8vIElzIHRoaXMgbmVjZXNzYXJ5IGlmIHRoZSBhcmd1bWVudCBpcyBPTkxZIHVzZWQgYXMgYW4gbHZhbHVlPyAoa2VlcCBpbiBtaW5kIHRoYXQgd2UgY2FuIGhhdmUgYSArPSBzb21ldGhpbmcsIHNvIHdlIHdvdWxkIGFjdHVhbGx5IG5lZWQgdG8gY2hlY2sgY2FyZy5ydmFsdWUpXG4gICAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIGxvY2FsU3RyKVxuICAgICAgICAgICAgICBwb3N0LnB1c2goW2FyclN0ciwgXCIuc2V0KFwiLCBwdHJTdHIsIFwiLFwiLCBsb2NhbFN0cixcIilcIl0uam9pbihcIlwiKSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIFthcnJTdHIsIFwiLmdldChcIiwgcHRyU3RyLCBcIilcIl0uam9pbihcIlwiKSlcbiAgICAgICAgICAgIH0qL1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IEdlbmVyaWMgYXJyYXlzIG5vdCBzdXBwb3J0ZWQgaW4gY29tYmluYXRpb24gd2l0aCBibG9ja3MhXCIpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgZG9lcyBub3QgcHJvZHVjZSBhbnkgbG9jYWwgdmFyaWFibGVzLCBldmVuIGlmIHZhcmlhYmxlcyBhcmUgdXNlZCBtdWx0aXBsZSB0aW1lcy4gSXQgd291bGQgYmUgcG9zc2libGUgdG8gZG8gc28sIGJ1dCBpdCB3b3VsZCBjb21wbGljYXRlIHRoaW5ncyBxdWl0ZSBhIGJpdC5cbiAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIFthcnJTdHIsIFwiW1wiLCBwdHJTdHIsIFwiXVwiXS5qb2luKFwiXCIpKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgYnJlYWtcbiAgICAgIGNhc2UgXCJzY2FsYXJcIjpcbiAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgXCJZXCIgKyBwcm9jLnNjYWxhckFyZ3MuaW5kZXhPZihpKSlcbiAgICAgIGJyZWFrXG4gICAgICBjYXNlIFwiaW5kZXhcIjpcbiAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgXCJpbmRleFwiKVxuICAgICAgYnJlYWtcbiAgICAgIGNhc2UgXCJzaGFwZVwiOlxuICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBcInNoYXBlXCIpXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuICByZXR1cm4gW3ByZS5qb2luKFwiXFxuXCIpLCBjb2RlLCBwb3N0LmpvaW4oXCJcXG5cIildLmpvaW4oXCJcXG5cIikudHJpbSgpXG59XG5cbmZ1bmN0aW9uIHR5cGVTdW1tYXJ5KGR0eXBlcykge1xuICB2YXIgc3VtbWFyeSA9IG5ldyBBcnJheShkdHlwZXMubGVuZ3RoKVxuICB2YXIgYWxsRXF1YWwgPSB0cnVlXG4gIGZvcih2YXIgaT0wOyBpPGR0eXBlcy5sZW5ndGg7ICsraSkge1xuICAgIHZhciB0ID0gZHR5cGVzW2ldXG4gICAgdmFyIGRpZ2l0cyA9IHQubWF0Y2goL1xcZCsvKVxuICAgIGlmKCFkaWdpdHMpIHtcbiAgICAgIGRpZ2l0cyA9IFwiXCJcbiAgICB9IGVsc2Uge1xuICAgICAgZGlnaXRzID0gZGlnaXRzWzBdXG4gICAgfVxuICAgIGlmKHQuY2hhckF0KDApID09PSAwKSB7XG4gICAgICBzdW1tYXJ5W2ldID0gXCJ1XCIgKyB0LmNoYXJBdCgxKSArIGRpZ2l0c1xuICAgIH0gZWxzZSB7XG4gICAgICBzdW1tYXJ5W2ldID0gdC5jaGFyQXQoMCkgKyBkaWdpdHNcbiAgICB9XG4gICAgaWYoaSA+IDApIHtcbiAgICAgIGFsbEVxdWFsID0gYWxsRXF1YWwgJiYgc3VtbWFyeVtpXSA9PT0gc3VtbWFyeVtpLTFdXG4gICAgfVxuICB9XG4gIGlmKGFsbEVxdWFsKSB7XG4gICAgcmV0dXJuIHN1bW1hcnlbMF1cbiAgfVxuICByZXR1cm4gc3VtbWFyeS5qb2luKFwiXCIpXG59XG5cbi8vR2VuZXJhdGVzIGEgY3dpc2Ugb3BlcmF0b3JcbmZ1bmN0aW9uIGdlbmVyYXRlQ1dpc2VPcChwcm9jLCB0eXBlc2lnKSB7XG5cbiAgLy9Db21wdXRlIGRpbWVuc2lvblxuICAvLyBBcnJheXMgZ2V0IHB1dCBmaXJzdCBpbiB0eXBlc2lnLCBhbmQgdGhlcmUgYXJlIHR3byBlbnRyaWVzIHBlciBhcnJheSAoZHR5cGUgYW5kIG9yZGVyKSwgc28gdGhpcyBnZXRzIHRoZSBudW1iZXIgb2YgZGltZW5zaW9ucyBpbiB0aGUgZmlyc3QgYXJyYXkgYXJnLlxuICB2YXIgZGltZW5zaW9uID0gKHR5cGVzaWdbMV0ubGVuZ3RoIC0gTWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1swXSkpfDBcbiAgdmFyIG9yZGVycyA9IG5ldyBBcnJheShwcm9jLmFycmF5QXJncy5sZW5ndGgpXG4gIHZhciBkdHlwZXMgPSBuZXcgQXJyYXkocHJvYy5hcnJheUFyZ3MubGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxwcm9jLmFycmF5QXJncy5sZW5ndGg7ICsraSkge1xuICAgIGR0eXBlc1tpXSA9IHR5cGVzaWdbMippXVxuICAgIG9yZGVyc1tpXSA9IHR5cGVzaWdbMippKzFdXG4gIH1cbiAgXG4gIC8vRGV0ZXJtaW5lIHdoZXJlIGJsb2NrIGFuZCBsb29wIGluZGljZXMgc3RhcnQgYW5kIGVuZFxuICB2YXIgYmxvY2tCZWdpbiA9IFtdLCBibG9ja0VuZCA9IFtdIC8vIFRoZXNlIGluZGljZXMgYXJlIGV4cG9zZWQgYXMgYmxvY2tzXG4gIHZhciBsb29wQmVnaW4gPSBbXSwgbG9vcEVuZCA9IFtdIC8vIFRoZXNlIGluZGljZXMgYXJlIGl0ZXJhdGVkIG92ZXJcbiAgdmFyIGxvb3BPcmRlcnMgPSBbXSAvLyBvcmRlcnMgcmVzdHJpY3RlZCB0byB0aGUgbG9vcCBpbmRpY2VzXG4gIGZvcih2YXIgaT0wOyBpPHByb2MuYXJyYXlBcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKHByb2MuYXJyYXlCbG9ja0luZGljZXNbaV08MCkge1xuICAgICAgbG9vcEJlZ2luLnB1c2goMClcbiAgICAgIGxvb3BFbmQucHVzaChkaW1lbnNpb24pXG4gICAgICBibG9ja0JlZ2luLnB1c2goZGltZW5zaW9uKVxuICAgICAgYmxvY2tFbmQucHVzaChkaW1lbnNpb24rcHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9vcEJlZ2luLnB1c2gocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSkgLy8gTm9uLW5lZ2F0aXZlXG4gICAgICBsb29wRW5kLnB1c2gocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXStkaW1lbnNpb24pXG4gICAgICBibG9ja0JlZ2luLnB1c2goMClcbiAgICAgIGJsb2NrRW5kLnB1c2gocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSlcbiAgICB9XG4gICAgdmFyIG5ld09yZGVyID0gW11cbiAgICBmb3IodmFyIGo9MDsgajxvcmRlcnNbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgIGlmIChsb29wQmVnaW5baV08PW9yZGVyc1tpXVtqXSAmJiBvcmRlcnNbaV1bal08bG9vcEVuZFtpXSkge1xuICAgICAgICBuZXdPcmRlci5wdXNoKG9yZGVyc1tpXVtqXS1sb29wQmVnaW5baV0pIC8vIElmIHRoaXMgaXMgYSBsb29wIGluZGV4LCBwdXQgaXQgaW4gbmV3T3JkZXIsIHN1YnRyYWN0aW5nIGxvb3BCZWdpbiwgdG8gbWFrZSBzdXJlIHRoYXQgYWxsIGxvb3BPcmRlcnMgYXJlIHVzaW5nIGEgY29tbW9uIHNldCBvZiBpbmRpY2VzLlxuICAgICAgfVxuICAgIH1cbiAgICBsb29wT3JkZXJzLnB1c2gobmV3T3JkZXIpXG4gIH1cblxuICAvL0ZpcnN0IGNyZWF0ZSBhcmd1bWVudHMgZm9yIHByb2NlZHVyZVxuICB2YXIgYXJnbGlzdCA9IFtcIlNTXCJdIC8vIFNTIGlzIHRoZSBvdmVyYWxsIHNoYXBlIG92ZXIgd2hpY2ggd2UgaXRlcmF0ZVxuICB2YXIgY29kZSA9IFtcIid1c2Ugc3RyaWN0J1wiXVxuICB2YXIgdmFycyA9IFtdXG4gIFxuICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikge1xuICAgIHZhcnMucHVzaChbXCJzXCIsIGosIFwiPVNTW1wiLCBqLCBcIl1cIl0uam9pbihcIlwiKSkgLy8gVGhlIGxpbWl0cyBmb3IgZWFjaCBkaW1lbnNpb24uXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8cHJvYy5hcnJheUFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBhcmdsaXN0LnB1c2goXCJhXCIraSkgLy8gQWN0dWFsIGRhdGEgYXJyYXlcbiAgICBhcmdsaXN0LnB1c2goXCJ0XCIraSkgLy8gU3RyaWRlc1xuICAgIGFyZ2xpc3QucHVzaChcInBcIitpKSAvLyBPZmZzZXQgaW4gdGhlIGFycmF5IGF0IHdoaWNoIHRoZSBkYXRhIHN0YXJ0cyAoYWxzbyB1c2VkIGZvciBpdGVyYXRpbmcgb3ZlciB0aGUgZGF0YSlcbiAgICBcbiAgICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikgeyAvLyBVbnBhY2sgdGhlIHN0cmlkZXMgaW50byB2YXJzIGZvciBsb29waW5nXG4gICAgICB2YXJzLnB1c2goW1widFwiLGksXCJwXCIsaixcIj10XCIsaSxcIltcIixsb29wQmVnaW5baV0raixcIl1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgXG4gICAgZm9yKHZhciBqPTA7IGo8TWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSk7ICsraikgeyAvLyBVbnBhY2sgdGhlIHN0cmlkZXMgaW50byB2YXJzIGZvciBibG9jayBpdGVyYXRpb25cbiAgICAgIHZhcnMucHVzaChbXCJ0XCIsaSxcImJcIixqLFwiPXRcIixpLFwiW1wiLGJsb2NrQmVnaW5baV0raixcIl1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8cHJvYy5zY2FsYXJBcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgYXJnbGlzdC5wdXNoKFwiWVwiICsgaSlcbiAgfVxuICBpZihwcm9jLnNoYXBlQXJncy5sZW5ndGggPiAwKSB7XG4gICAgdmFycy5wdXNoKFwic2hhcGU9U1Muc2xpY2UoMClcIikgLy8gTWFrZXMgdGhlIHNoYXBlIG92ZXIgd2hpY2ggd2UgaXRlcmF0ZSBhdmFpbGFibGUgdG8gdGhlIHVzZXIgZGVmaW5lZCBmdW5jdGlvbnMgKHNvIHlvdSBjYW4gdXNlIHdpZHRoL2hlaWdodCBmb3IgZXhhbXBsZSlcbiAgfVxuICBpZihwcm9jLmluZGV4QXJncy5sZW5ndGggPiAwKSB7XG4gICAgLy8gUHJlcGFyZSBhbiBhcnJheSB0byBrZWVwIHRyYWNrIG9mIHRoZSAobG9naWNhbCkgaW5kaWNlcywgaW5pdGlhbGl6ZWQgdG8gZGltZW5zaW9uIHplcm9lcy5cbiAgICB2YXIgemVyb3MgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICB6ZXJvc1tpXSA9IFwiMFwiXG4gICAgfVxuICAgIHZhcnMucHVzaChbXCJpbmRleD1bXCIsIHplcm9zLmpvaW4oXCIsXCIpLCBcIl1cIl0uam9pbihcIlwiKSlcbiAgfVxuICBmb3IodmFyIGk9MDsgaTxwcm9jLm9mZnNldEFyZ3MubGVuZ3RoOyArK2kpIHsgLy8gT2Zmc2V0IGFyZ3VtZW50cyB1c2VkIGZvciBzdGVuY2lsIG9wZXJhdGlvbnNcbiAgICB2YXIgb2ZmX2FyZyA9IHByb2Mub2Zmc2V0QXJnc1tpXVxuICAgIHZhciBpbml0X3N0cmluZyA9IFtdXG4gICAgZm9yKHZhciBqPTA7IGo8b2ZmX2FyZy5vZmZzZXQubGVuZ3RoOyArK2opIHtcbiAgICAgIGlmKG9mZl9hcmcub2Zmc2V0W2pdID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9IGVsc2UgaWYob2ZmX2FyZy5vZmZzZXRbal0gPT09IDEpIHtcbiAgICAgICAgaW5pdF9zdHJpbmcucHVzaChbXCJ0XCIsIG9mZl9hcmcuYXJyYXksIFwicFwiLCBqXS5qb2luKFwiXCIpKSAgICAgIFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdF9zdHJpbmcucHVzaChbb2ZmX2FyZy5vZmZzZXRbal0sIFwiKnRcIiwgb2ZmX2FyZy5hcnJheSwgXCJwXCIsIGpdLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICAgIGlmKGluaXRfc3RyaW5nLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdmFycy5wdXNoKFwicVwiICsgaSArIFwiPTBcIilcbiAgICB9IGVsc2Uge1xuICAgICAgdmFycy5wdXNoKFtcInFcIiwgaSwgXCI9XCIsIGluaXRfc3RyaW5nLmpvaW4oXCIrXCIpXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgfVxuXG4gIC8vUHJlcGFyZSB0aGlzIHZhcmlhYmxlc1xuICB2YXIgdGhpc1ZhcnMgPSB1bmlxKFtdLmNvbmNhdChwcm9jLnByZS50aGlzVmFycylcbiAgICAgICAgICAgICAgICAgICAgICAuY29uY2F0KHByb2MuYm9keS50aGlzVmFycylcbiAgICAgICAgICAgICAgICAgICAgICAuY29uY2F0KHByb2MucG9zdC50aGlzVmFycykpXG4gIHZhcnMgPSB2YXJzLmNvbmNhdCh0aGlzVmFycylcbiAgaWYgKHZhcnMubGVuZ3RoID4gMCkge1xuICAgIGNvZGUucHVzaChcInZhciBcIiArIHZhcnMuam9pbihcIixcIikpXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8cHJvYy5hcnJheUFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXCJwXCIraStcInw9MFwiKVxuICB9XG4gIFxuICAvL0lubGluZSBwcmVsdWRlXG4gIGlmKHByb2MucHJlLmJvZHkubGVuZ3RoID4gMykge1xuICAgIGNvZGUucHVzaChwcm9jZXNzQmxvY2socHJvYy5wcmUsIHByb2MsIGR0eXBlcykpXG4gIH1cblxuICAvL1Byb2Nlc3MgYm9keVxuICB2YXIgYm9keSA9IHByb2Nlc3NCbG9jayhwcm9jLmJvZHksIHByb2MsIGR0eXBlcylcbiAgdmFyIG1hdGNoZWQgPSBjb3VudE1hdGNoZXMobG9vcE9yZGVycylcbiAgaWYobWF0Y2hlZCA8IGRpbWVuc2lvbikge1xuICAgIGNvZGUucHVzaChvdXRlckZpbGwobWF0Y2hlZCwgbG9vcE9yZGVyc1swXSwgcHJvYywgYm9keSkpIC8vIFRPRE86IFJhdGhlciB0aGFuIHBhc3NpbmcgbG9vcE9yZGVyc1swXSwgaXQgbWlnaHQgYmUgaW50ZXJlc3RpbmcgdG8gbG9vayBhdCBwYXNzaW5nIGFuIG9yZGVyIHRoYXQgcmVwcmVzZW50cyB0aGUgbWFqb3JpdHkgb2YgdGhlIGFyZ3VtZW50cyBmb3IgZXhhbXBsZS5cbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goaW5uZXJGaWxsKGxvb3BPcmRlcnNbMF0sIHByb2MsIGJvZHkpKVxuICB9XG5cbiAgLy9JbmxpbmUgZXBpbG9nXG4gIGlmKHByb2MucG9zdC5ib2R5Lmxlbmd0aCA+IDMpIHtcbiAgICBjb2RlLnB1c2gocHJvY2Vzc0Jsb2NrKHByb2MucG9zdCwgcHJvYywgZHR5cGVzKSlcbiAgfVxuICBcbiAgaWYocHJvYy5kZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKFwiLS0tLS1HZW5lcmF0ZWQgY3dpc2Ugcm91dGluZSBmb3IgXCIsIHR5cGVzaWcsIFwiOlxcblwiICsgY29kZS5qb2luKFwiXFxuXCIpICsgXCJcXG4tLS0tLS0tLS0tXCIpXG4gIH1cbiAgXG4gIHZhciBsb29wTmFtZSA9IFsocHJvYy5mdW5jTmFtZXx8XCJ1bm5hbWVkXCIpLCBcIl9jd2lzZV9sb29wX1wiLCBvcmRlcnNbMF0uam9pbihcInNcIiksXCJtXCIsbWF0Y2hlZCx0eXBlU3VtbWFyeShkdHlwZXMpXS5qb2luKFwiXCIpXG4gIHZhciBmID0gbmV3IEZ1bmN0aW9uKFtcImZ1bmN0aW9uIFwiLGxvb3BOYW1lLFwiKFwiLCBhcmdsaXN0LmpvaW4oXCIsXCIpLFwiKXtcIiwgY29kZS5qb2luKFwiXFxuXCIpLFwifSByZXR1cm4gXCIsIGxvb3BOYW1lXS5qb2luKFwiXCIpKVxuICByZXR1cm4gZigpXG59XG5tb2R1bGUuZXhwb3J0cyA9IGdlbmVyYXRlQ1dpc2VPcFxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxuLy8gVGhlIGZ1bmN0aW9uIGJlbG93IGlzIGNhbGxlZCB3aGVuIGNvbnN0cnVjdGluZyBhIGN3aXNlIGZ1bmN0aW9uIG9iamVjdCwgYW5kIGRvZXMgdGhlIGZvbGxvd2luZzpcbi8vIEEgZnVuY3Rpb24gb2JqZWN0IGlzIGNvbnN0cnVjdGVkIHdoaWNoIGFjY2VwdHMgYXMgYXJndW1lbnQgYSBjb21waWxhdGlvbiBmdW5jdGlvbiBhbmQgcmV0dXJucyBhbm90aGVyIGZ1bmN0aW9uLlxuLy8gSXQgaXMgdGhpcyBvdGhlciBmdW5jdGlvbiB0aGF0IGlzIGV2ZW50dWFsbHkgcmV0dXJuZWQgYnkgY3JlYXRlVGh1bmssIGFuZCB0aGlzIGZ1bmN0aW9uIGlzIHRoZSBvbmUgdGhhdCBhY3R1YWxseVxuLy8gY2hlY2tzIHdoZXRoZXIgYSBjZXJ0YWluIHBhdHRlcm4gb2YgYXJndW1lbnRzIGhhcyBhbHJlYWR5IGJlZW4gdXNlZCBiZWZvcmUgYW5kIGNvbXBpbGVzIG5ldyBsb29wcyBhcyBuZWVkZWQuXG4vLyBUaGUgY29tcGlsYXRpb24gcGFzc2VkIHRvIHRoZSBmaXJzdCBmdW5jdGlvbiBvYmplY3QgaXMgdXNlZCBmb3IgY29tcGlsaW5nIG5ldyBmdW5jdGlvbnMuXG4vLyBPbmNlIHRoaXMgZnVuY3Rpb24gb2JqZWN0IGlzIGNyZWF0ZWQsIGl0IGlzIGNhbGxlZCB3aXRoIGNvbXBpbGUgYXMgYXJndW1lbnQsIHdoZXJlIHRoZSBmaXJzdCBhcmd1bWVudCBvZiBjb21waWxlXG4vLyBpcyBib3VuZCB0byBcInByb2NcIiAoZXNzZW50aWFsbHkgY29udGFpbmluZyBhIHByZXByb2Nlc3NlZCB2ZXJzaW9uIG9mIHRoZSB1c2VyIGFyZ3VtZW50cyB0byBjd2lzZSkuXG4vLyBTbyBjcmVhdGVUaHVuayByb3VnaGx5IHdvcmtzIGxpa2UgdGhpczpcbi8vIGZ1bmN0aW9uIGNyZWF0ZVRodW5rKHByb2MpIHtcbi8vICAgdmFyIHRodW5rID0gZnVuY3Rpb24oY29tcGlsZUJvdW5kKSB7XG4vLyAgICAgdmFyIENBQ0hFRCA9IHt9XG4vLyAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5cyBhbmQgc2NhbGFycykge1xuLy8gICAgICAgaWYgKGR0eXBlIGFuZCBvcmRlciBvZiBhcnJheXMgaW4gQ0FDSEVEKSB7XG4vLyAgICAgICAgIHZhciBmdW5jID0gQ0FDSEVEW2R0eXBlIGFuZCBvcmRlciBvZiBhcnJheXNdXG4vLyAgICAgICB9IGVsc2Uge1xuLy8gICAgICAgICB2YXIgZnVuYyA9IENBQ0hFRFtkdHlwZSBhbmQgb3JkZXIgb2YgYXJyYXlzXSA9IGNvbXBpbGVCb3VuZChkdHlwZSBhbmQgb3JkZXIgb2YgYXJyYXlzKVxuLy8gICAgICAgfVxuLy8gICAgICAgcmV0dXJuIGZ1bmMoYXJyYXlzIGFuZCBzY2FsYXJzKVxuLy8gICAgIH1cbi8vICAgfVxuLy8gICByZXR1cm4gdGh1bmsoY29tcGlsZS5iaW5kMShwcm9jKSlcbi8vIH1cblxudmFyIGNvbXBpbGUgPSByZXF1aXJlKFwiLi9jb21waWxlLmpzXCIpXG5cbmZ1bmN0aW9uIGNyZWF0ZVRodW5rKHByb2MpIHtcbiAgdmFyIGNvZGUgPSBbXCIndXNlIHN0cmljdCdcIiwgXCJ2YXIgQ0FDSEVEPXt9XCJdXG4gIHZhciB2YXJzID0gW11cbiAgdmFyIHRodW5rTmFtZSA9IHByb2MuZnVuY05hbWUgKyBcIl9jd2lzZV90aHVua1wiXG4gIFxuICAvL0J1aWxkIHRodW5rXG4gIGNvZGUucHVzaChbXCJyZXR1cm4gZnVuY3Rpb24gXCIsIHRodW5rTmFtZSwgXCIoXCIsIHByb2Muc2hpbUFyZ3Muam9pbihcIixcIiksIFwiKXtcIl0uam9pbihcIlwiKSlcbiAgdmFyIHR5cGVzaWcgPSBbXVxuICB2YXIgc3RyaW5nX3R5cGVzaWcgPSBbXVxuICB2YXIgcHJvY19hcmdzID0gW1tcImFycmF5XCIscHJvYy5hcnJheUFyZ3NbMF0sXCIuc2hhcGUuc2xpY2UoXCIsIC8vIFNsaWNlIHNoYXBlIHNvIHRoYXQgd2Ugb25seSByZXRhaW4gdGhlIHNoYXBlIG92ZXIgd2hpY2ggd2UgaXRlcmF0ZSAod2hpY2ggZ2V0cyBwYXNzZWQgdG8gdGhlIGN3aXNlIG9wZXJhdG9yIGFzIFNTKS5cbiAgICAgICAgICAgICAgICAgICAgTWF0aC5tYXgoMCxwcm9jLmFycmF5QmxvY2tJbmRpY2VzWzBdKSxwcm9jLmFycmF5QmxvY2tJbmRpY2VzWzBdPDA/KFwiLFwiK3Byb2MuYXJyYXlCbG9ja0luZGljZXNbMF0rXCIpXCIpOlwiKVwiXS5qb2luKFwiXCIpXVxuICB2YXIgc2hhcGVMZW5ndGhDb25kaXRpb25zID0gW10sIHNoYXBlQ29uZGl0aW9ucyA9IFtdXG4gIC8vIFByb2Nlc3MgYXJyYXkgYXJndW1lbnRzXG4gIGZvcih2YXIgaT0wOyBpPHByb2MuYXJyYXlBcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGogPSBwcm9jLmFycmF5QXJnc1tpXVxuICAgIHZhcnMucHVzaChbXCJ0XCIsIGosIFwiPWFycmF5XCIsIGosIFwiLmR0eXBlLFwiLFxuICAgICAgICAgICAgICAgXCJyXCIsIGosIFwiPWFycmF5XCIsIGosIFwiLm9yZGVyXCJdLmpvaW4oXCJcIikpXG4gICAgdHlwZXNpZy5wdXNoKFwidFwiICsgailcbiAgICB0eXBlc2lnLnB1c2goXCJyXCIgKyBqKVxuICAgIHN0cmluZ190eXBlc2lnLnB1c2goXCJ0XCIrailcbiAgICBzdHJpbmdfdHlwZXNpZy5wdXNoKFwiclwiK2orXCIuam9pbigpXCIpXG4gICAgcHJvY19hcmdzLnB1c2goXCJhcnJheVwiICsgaiArIFwiLmRhdGFcIilcbiAgICBwcm9jX2FyZ3MucHVzaChcImFycmF5XCIgKyBqICsgXCIuc3RyaWRlXCIpXG4gICAgcHJvY19hcmdzLnB1c2goXCJhcnJheVwiICsgaiArIFwiLm9mZnNldHwwXCIpXG4gICAgaWYgKGk+MCkgeyAvLyBHYXRoZXIgY29uZGl0aW9ucyB0byBjaGVjayBmb3Igc2hhcGUgZXF1YWxpdHkgKGlnbm9yaW5nIGJsb2NrIGluZGljZXMpXG4gICAgICBzaGFwZUxlbmd0aENvbmRpdGlvbnMucHVzaChcImFycmF5XCIgKyBwcm9jLmFycmF5QXJnc1swXSArIFwiLnNoYXBlLmxlbmd0aD09PWFycmF5XCIgKyBqICsgXCIuc2hhcGUubGVuZ3RoK1wiICsgKE1hdGguYWJzKHByb2MuYXJyYXlCbG9ja0luZGljZXNbMF0pLU1hdGguYWJzKHByb2MuYXJyYXlCbG9ja0luZGljZXNbaV0pKSlcbiAgICAgIHNoYXBlQ29uZGl0aW9ucy5wdXNoKFwiYXJyYXlcIiArIHByb2MuYXJyYXlBcmdzWzBdICsgXCIuc2hhcGVbc2hhcGVJbmRleCtcIiArIE1hdGgubWF4KDAscHJvYy5hcnJheUJsb2NrSW5kaWNlc1swXSkgKyBcIl09PT1hcnJheVwiICsgaiArIFwiLnNoYXBlW3NoYXBlSW5kZXgrXCIgKyBNYXRoLm1heCgwLHByb2MuYXJyYXlCbG9ja0luZGljZXNbaV0pICsgXCJdXCIpXG4gICAgfVxuICB9XG4gIC8vIENoZWNrIGZvciBzaGFwZSBlcXVhbGl0eVxuICBpZiAocHJvYy5hcnJheUFyZ3MubGVuZ3RoID4gMSkge1xuICAgIGNvZGUucHVzaChcImlmICghKFwiICsgc2hhcGVMZW5ndGhDb25kaXRpb25zLmpvaW4oXCIgJiYgXCIpICsgXCIpKSB0aHJvdyBuZXcgRXJyb3IoJ2N3aXNlOiBBcnJheXMgZG8gbm90IGFsbCBoYXZlIHRoZSBzYW1lIGRpbWVuc2lvbmFsaXR5IScpXCIpXG4gICAgY29kZS5wdXNoKFwiZm9yKHZhciBzaGFwZUluZGV4PWFycmF5XCIgKyBwcm9jLmFycmF5QXJnc1swXSArIFwiLnNoYXBlLmxlbmd0aC1cIiArIE1hdGguYWJzKHByb2MuYXJyYXlCbG9ja0luZGljZXNbMF0pICsgXCI7IHNoYXBlSW5kZXgtLT4wOykge1wiKVxuICAgIGNvZGUucHVzaChcImlmICghKFwiICsgc2hhcGVDb25kaXRpb25zLmpvaW4oXCIgJiYgXCIpICsgXCIpKSB0aHJvdyBuZXcgRXJyb3IoJ2N3aXNlOiBBcnJheXMgZG8gbm90IGFsbCBoYXZlIHRoZSBzYW1lIHNoYXBlIScpXCIpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICB9XG4gIC8vIFByb2Nlc3Mgc2NhbGFyIGFyZ3VtZW50c1xuICBmb3IodmFyIGk9MDsgaTxwcm9jLnNjYWxhckFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBwcm9jX2FyZ3MucHVzaChcInNjYWxhclwiICsgcHJvYy5zY2FsYXJBcmdzW2ldKVxuICB9XG4gIC8vIENoZWNrIGZvciBjYWNoZWQgZnVuY3Rpb24gKGFuZCBpZiBub3QgcHJlc2VudCwgZ2VuZXJhdGUgaXQpXG4gIHZhcnMucHVzaChbXCJ0eXBlPVtcIiwgc3RyaW5nX3R5cGVzaWcuam9pbihcIixcIiksIFwiXS5qb2luKClcIl0uam9pbihcIlwiKSlcbiAgdmFycy5wdXNoKFwicHJvYz1DQUNIRURbdHlwZV1cIilcbiAgY29kZS5wdXNoKFwidmFyIFwiICsgdmFycy5qb2luKFwiLFwiKSlcbiAgXG4gIGNvZGUucHVzaChbXCJpZighcHJvYyl7XCIsXG4gICAgICAgICAgICAgXCJDQUNIRURbdHlwZV09cHJvYz1jb21waWxlKFtcIiwgdHlwZXNpZy5qb2luKFwiLFwiKSwgXCJdKX1cIixcbiAgICAgICAgICAgICBcInJldHVybiBwcm9jKFwiLCBwcm9jX2FyZ3Muam9pbihcIixcIiksIFwiKX1cIl0uam9pbihcIlwiKSlcblxuICBpZihwcm9jLmRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXCItLS0tLUdlbmVyYXRlZCB0aHVuazpcXG5cIiArIGNvZGUuam9pbihcIlxcblwiKSArIFwiXFxuLS0tLS0tLS0tLVwiKVxuICB9XG4gIFxuICAvL0NvbXBpbGUgdGh1bmtcbiAgdmFyIHRodW5rID0gbmV3IEZ1bmN0aW9uKFwiY29tcGlsZVwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gIHJldHVybiB0aHVuayhjb21waWxlLmJpbmQodW5kZWZpbmVkLCBwcm9jKSlcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUaHVua1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiY3dpc2UtY29tcGlsZXJcIikiLCIndXNlIHN0cmljdCc7XG5cbnZhciBjb3B5ICAgICAgICAgICAgID0gcmVxdWlyZSgnZXM1LWV4dC9vYmplY3QvY29weScpXG4gICwgbm9ybWFsaXplT3B0aW9ucyA9IHJlcXVpcmUoJ2VzNS1leHQvb2JqZWN0L25vcm1hbGl6ZS1vcHRpb25zJylcbiAgLCBlbnN1cmVDYWxsYWJsZSAgID0gcmVxdWlyZSgnZXM1LWV4dC9vYmplY3QvdmFsaWQtY2FsbGFibGUnKVxuICAsIG1hcCAgICAgICAgICAgICAgPSByZXF1aXJlKCdlczUtZXh0L29iamVjdC9tYXAnKVxuICAsIGNhbGxhYmxlICAgICAgICAgPSByZXF1aXJlKCdlczUtZXh0L29iamVjdC92YWxpZC1jYWxsYWJsZScpXG4gICwgdmFsaWRWYWx1ZSAgICAgICA9IHJlcXVpcmUoJ2VzNS1leHQvb2JqZWN0L3ZhbGlkLXZhbHVlJylcblxuICAsIGJpbmQgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCwgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHlcbiAgLCBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHlcbiAgLCBkZWZpbmU7XG5cbmRlZmluZSA9IGZ1bmN0aW9uIChuYW1lLCBkZXNjLCBvcHRpb25zKSB7XG5cdHZhciB2YWx1ZSA9IHZhbGlkVmFsdWUoZGVzYykgJiYgY2FsbGFibGUoZGVzYy52YWx1ZSksIGRncztcblx0ZGdzID0gY29weShkZXNjKTtcblx0ZGVsZXRlIGRncy53cml0YWJsZTtcblx0ZGVsZXRlIGRncy52YWx1ZTtcblx0ZGdzLmdldCA9IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIW9wdGlvbnMub3ZlcndyaXRlRGVmaW5pdGlvbiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMsIG5hbWUpKSByZXR1cm4gdmFsdWU7XG5cdFx0ZGVzYy52YWx1ZSA9IGJpbmQuY2FsbCh2YWx1ZSwgb3B0aW9ucy5yZXNvbHZlQ29udGV4dCA/IG9wdGlvbnMucmVzb2x2ZUNvbnRleHQodGhpcykgOiB0aGlzKTtcblx0XHRkZWZpbmVQcm9wZXJ0eSh0aGlzLCBuYW1lLCBkZXNjKTtcblx0XHRyZXR1cm4gdGhpc1tuYW1lXTtcblx0fTtcblx0cmV0dXJuIGRncztcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHByb3BzLyosIG9wdGlvbnMqLykge1xuXHR2YXIgb3B0aW9ucyA9IG5vcm1hbGl6ZU9wdGlvbnMoYXJndW1lbnRzWzFdKTtcblx0aWYgKG9wdGlvbnMucmVzb2x2ZUNvbnRleHQgIT0gbnVsbCkgZW5zdXJlQ2FsbGFibGUob3B0aW9ucy5yZXNvbHZlQ29udGV4dCk7XG5cdHJldHVybiBtYXAocHJvcHMsIGZ1bmN0aW9uIChkZXNjLCBuYW1lKSB7IHJldHVybiBkZWZpbmUobmFtZSwgZGVzYywgb3B0aW9ucyk7IH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFzc2lnbiAgICAgICAgPSByZXF1aXJlKCdlczUtZXh0L29iamVjdC9hc3NpZ24nKVxuICAsIG5vcm1hbGl6ZU9wdHMgPSByZXF1aXJlKCdlczUtZXh0L29iamVjdC9ub3JtYWxpemUtb3B0aW9ucycpXG4gICwgaXNDYWxsYWJsZSAgICA9IHJlcXVpcmUoJ2VzNS1leHQvb2JqZWN0L2lzLWNhbGxhYmxlJylcbiAgLCBjb250YWlucyAgICAgID0gcmVxdWlyZSgnZXM1LWV4dC9zdHJpbmcvIy9jb250YWlucycpXG5cbiAgLCBkO1xuXG5kID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZHNjciwgdmFsdWUvKiwgb3B0aW9ucyovKSB7XG5cdHZhciBjLCBlLCB3LCBvcHRpb25zLCBkZXNjO1xuXHRpZiAoKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB8fCAodHlwZW9mIGRzY3IgIT09ICdzdHJpbmcnKSkge1xuXHRcdG9wdGlvbnMgPSB2YWx1ZTtcblx0XHR2YWx1ZSA9IGRzY3I7XG5cdFx0ZHNjciA9IG51bGw7XG5cdH0gZWxzZSB7XG5cdFx0b3B0aW9ucyA9IGFyZ3VtZW50c1syXTtcblx0fVxuXHRpZiAoZHNjciA9PSBudWxsKSB7XG5cdFx0YyA9IHcgPSB0cnVlO1xuXHRcdGUgPSBmYWxzZTtcblx0fSBlbHNlIHtcblx0XHRjID0gY29udGFpbnMuY2FsbChkc2NyLCAnYycpO1xuXHRcdGUgPSBjb250YWlucy5jYWxsKGRzY3IsICdlJyk7XG5cdFx0dyA9IGNvbnRhaW5zLmNhbGwoZHNjciwgJ3cnKTtcblx0fVxuXG5cdGRlc2MgPSB7IHZhbHVlOiB2YWx1ZSwgY29uZmlndXJhYmxlOiBjLCBlbnVtZXJhYmxlOiBlLCB3cml0YWJsZTogdyB9O1xuXHRyZXR1cm4gIW9wdGlvbnMgPyBkZXNjIDogYXNzaWduKG5vcm1hbGl6ZU9wdHMob3B0aW9ucyksIGRlc2MpO1xufTtcblxuZC5ncyA9IGZ1bmN0aW9uIChkc2NyLCBnZXQsIHNldC8qLCBvcHRpb25zKi8pIHtcblx0dmFyIGMsIGUsIG9wdGlvbnMsIGRlc2M7XG5cdGlmICh0eXBlb2YgZHNjciAhPT0gJ3N0cmluZycpIHtcblx0XHRvcHRpb25zID0gc2V0O1xuXHRcdHNldCA9IGdldDtcblx0XHRnZXQgPSBkc2NyO1xuXHRcdGRzY3IgPSBudWxsO1xuXHR9IGVsc2Uge1xuXHRcdG9wdGlvbnMgPSBhcmd1bWVudHNbM107XG5cdH1cblx0aWYgKGdldCA9PSBudWxsKSB7XG5cdFx0Z2V0ID0gdW5kZWZpbmVkO1xuXHR9IGVsc2UgaWYgKCFpc0NhbGxhYmxlKGdldCkpIHtcblx0XHRvcHRpb25zID0gZ2V0O1xuXHRcdGdldCA9IHNldCA9IHVuZGVmaW5lZDtcblx0fSBlbHNlIGlmIChzZXQgPT0gbnVsbCkge1xuXHRcdHNldCA9IHVuZGVmaW5lZDtcblx0fSBlbHNlIGlmICghaXNDYWxsYWJsZShzZXQpKSB7XG5cdFx0b3B0aW9ucyA9IHNldDtcblx0XHRzZXQgPSB1bmRlZmluZWQ7XG5cdH1cblx0aWYgKGRzY3IgPT0gbnVsbCkge1xuXHRcdGMgPSB0cnVlO1xuXHRcdGUgPSBmYWxzZTtcblx0fSBlbHNlIHtcblx0XHRjID0gY29udGFpbnMuY2FsbChkc2NyLCAnYycpO1xuXHRcdGUgPSBjb250YWlucy5jYWxsKGRzY3IsICdlJyk7XG5cdH1cblxuXHRkZXNjID0geyBnZXQ6IGdldCwgc2V0OiBzZXQsIGNvbmZpZ3VyYWJsZTogYywgZW51bWVyYWJsZTogZSB9O1xuXHRyZXR1cm4gIW9wdGlvbnMgPyBkZXNjIDogYXNzaWduKG5vcm1hbGl6ZU9wdHMob3B0aW9ucyksIGRlc2MpO1xufTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtYXJyYXkvIHYxLjIuNCBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2tcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG50eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuKGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiBhID49IGIgPyAwIDogTmFOO1xufVxuXG5mdW5jdGlvbiBiaXNlY3Rvcihjb21wYXJlKSB7XG4gIGlmIChjb21wYXJlLmxlbmd0aCA9PT0gMSkgY29tcGFyZSA9IGFzY2VuZGluZ0NvbXBhcmF0b3IoY29tcGFyZSk7XG4gIHJldHVybiB7XG4gICAgbGVmdDogZnVuY3Rpb24oYSwgeCwgbG8sIGhpKSB7XG4gICAgICBpZiAobG8gPT0gbnVsbCkgbG8gPSAwO1xuICAgICAgaWYgKGhpID09IG51bGwpIGhpID0gYS5sZW5ndGg7XG4gICAgICB3aGlsZSAobG8gPCBoaSkge1xuICAgICAgICB2YXIgbWlkID0gbG8gKyBoaSA+Pj4gMTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYVttaWRdLCB4KSA8IDApIGxvID0gbWlkICsgMTtcbiAgICAgICAgZWxzZSBoaSA9IG1pZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsbztcbiAgICB9LFxuICAgIHJpZ2h0OiBmdW5jdGlvbihhLCB4LCBsbywgaGkpIHtcbiAgICAgIGlmIChsbyA9PSBudWxsKSBsbyA9IDA7XG4gICAgICBpZiAoaGkgPT0gbnVsbCkgaGkgPSBhLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICAgIHZhciBtaWQgPSBsbyArIGhpID4+PiAxO1xuICAgICAgICBpZiAoY29tcGFyZShhW21pZF0sIHgpID4gMCkgaGkgPSBtaWQ7XG4gICAgICAgIGVsc2UgbG8gPSBtaWQgKyAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gYXNjZW5kaW5nQ29tcGFyYXRvcihmKSB7XG4gIHJldHVybiBmdW5jdGlvbihkLCB4KSB7XG4gICAgcmV0dXJuIGFzY2VuZGluZyhmKGQpLCB4KTtcbiAgfTtcbn1cblxudmFyIGFzY2VuZGluZ0Jpc2VjdCA9IGJpc2VjdG9yKGFzY2VuZGluZyk7XG52YXIgYmlzZWN0UmlnaHQgPSBhc2NlbmRpbmdCaXNlY3QucmlnaHQ7XG52YXIgYmlzZWN0TGVmdCA9IGFzY2VuZGluZ0Jpc2VjdC5sZWZ0O1xuXG5mdW5jdGlvbiBwYWlycyhhcnJheSwgZikge1xuICBpZiAoZiA9PSBudWxsKSBmID0gcGFpcjtcbiAgdmFyIGkgPSAwLCBuID0gYXJyYXkubGVuZ3RoIC0gMSwgcCA9IGFycmF5WzBdLCBwYWlycyA9IG5ldyBBcnJheShuIDwgMCA/IDAgOiBuKTtcbiAgd2hpbGUgKGkgPCBuKSBwYWlyc1tpXSA9IGYocCwgcCA9IGFycmF5WysraV0pO1xuICByZXR1cm4gcGFpcnM7XG59XG5cbmZ1bmN0aW9uIHBhaXIoYSwgYikge1xuICByZXR1cm4gW2EsIGJdO1xufVxuXG5mdW5jdGlvbiBjcm9zcyh2YWx1ZXMwLCB2YWx1ZXMxLCByZWR1Y2UpIHtcbiAgdmFyIG4wID0gdmFsdWVzMC5sZW5ndGgsXG4gICAgICBuMSA9IHZhbHVlczEubGVuZ3RoLFxuICAgICAgdmFsdWVzID0gbmV3IEFycmF5KG4wICogbjEpLFxuICAgICAgaTAsXG4gICAgICBpMSxcbiAgICAgIGksXG4gICAgICB2YWx1ZTA7XG5cbiAgaWYgKHJlZHVjZSA9PSBudWxsKSByZWR1Y2UgPSBwYWlyO1xuXG4gIGZvciAoaTAgPSBpID0gMDsgaTAgPCBuMDsgKytpMCkge1xuICAgIGZvciAodmFsdWUwID0gdmFsdWVzMFtpMF0sIGkxID0gMDsgaTEgPCBuMTsgKytpMSwgKytpKSB7XG4gICAgICB2YWx1ZXNbaV0gPSByZWR1Y2UodmFsdWUwLCB2YWx1ZXMxW2kxXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHZhbHVlcztcbn1cblxuZnVuY3Rpb24gZGVzY2VuZGluZyhhLCBiKSB7XG4gIHJldHVybiBiIDwgYSA/IC0xIDogYiA+IGEgPyAxIDogYiA+PSBhID8gMCA6IE5hTjtcbn1cblxuZnVuY3Rpb24gbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGwgPyBOYU4gOiAreDtcbn1cblxuZnVuY3Rpb24gdmFyaWFuY2UodmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIG0gPSAwLFxuICAgICAgaSA9IC0xLFxuICAgICAgbWVhbiA9IDAsXG4gICAgICB2YWx1ZSxcbiAgICAgIGRlbHRhLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHtcbiAgICAgICAgZGVsdGEgPSB2YWx1ZSAtIG1lYW47XG4gICAgICAgIG1lYW4gKz0gZGVsdGEgLyArK207XG4gICAgICAgIHN1bSArPSBkZWx0YSAqICh2YWx1ZSAtIG1lYW4pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSkpIHtcbiAgICAgICAgZGVsdGEgPSB2YWx1ZSAtIG1lYW47XG4gICAgICAgIG1lYW4gKz0gZGVsdGEgLyArK207XG4gICAgICAgIHN1bSArPSBkZWx0YSAqICh2YWx1ZSAtIG1lYW4pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChtID4gMSkgcmV0dXJuIHN1bSAvIChtIC0gMSk7XG59XG5cbmZ1bmN0aW9uIGRldmlhdGlvbihhcnJheSwgZikge1xuICB2YXIgdiA9IHZhcmlhbmNlKGFycmF5LCBmKTtcbiAgcmV0dXJuIHYgPyBNYXRoLnNxcnQodikgOiB2O1xufVxuXG5mdW5jdGlvbiBleHRlbnQodmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgbWluLFxuICAgICAgbWF4O1xuXG4gIGlmICh2YWx1ZW9mID09IG51bGwpIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlc1tpXSkgIT0gbnVsbCAmJiB2YWx1ZSA+PSB2YWx1ZSkge1xuICAgICAgICBtaW4gPSBtYXggPSB2YWx1ZTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gQ29tcGFyZSB0aGUgcmVtYWluaW5nIHZhbHVlcy5cbiAgICAgICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAobWluID4gdmFsdWUpIG1pbiA9IHZhbHVlO1xuICAgICAgICAgICAgaWYgKG1heCA8IHZhbHVlKSBtYXggPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IG1heCA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKG1pbiA+IHZhbHVlKSBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICAgIGlmIChtYXggPCB2YWx1ZSkgbWF4ID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFttaW4sIG1heF07XG59XG5cbnZhciBhcnJheSA9IEFycmF5LnByb3RvdHlwZTtcblxudmFyIHNsaWNlID0gYXJyYXkuc2xpY2U7XG52YXIgbWFwID0gYXJyYXkubWFwO1xuXG5mdW5jdGlvbiBjb25zdGFudCh4KSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4geDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaWRlbnRpdHkoeCkge1xuICByZXR1cm4geDtcbn1cblxuZnVuY3Rpb24gcmFuZ2Uoc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgc3RhcnQgPSArc3RhcnQsIHN0b3AgPSArc3RvcCwgc3RlcCA9IChuID0gYXJndW1lbnRzLmxlbmd0aCkgPCAyID8gKHN0b3AgPSBzdGFydCwgc3RhcnQgPSAwLCAxKSA6IG4gPCAzID8gMSA6ICtzdGVwO1xuXG4gIHZhciBpID0gLTEsXG4gICAgICBuID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKChzdG9wIC0gc3RhcnQpIC8gc3RlcCkpIHwgMCxcbiAgICAgIHJhbmdlID0gbmV3IEFycmF5KG4pO1xuXG4gIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgcmFuZ2VbaV0gPSBzdGFydCArIGkgKiBzdGVwO1xuICB9XG5cbiAgcmV0dXJuIHJhbmdlO1xufVxuXG52YXIgZTEwID0gTWF0aC5zcXJ0KDUwKSxcbiAgICBlNSA9IE1hdGguc3FydCgxMCksXG4gICAgZTIgPSBNYXRoLnNxcnQoMik7XG5cbmZ1bmN0aW9uIHRpY2tzKHN0YXJ0LCBzdG9wLCBjb3VudCkge1xuICB2YXIgcmV2ZXJzZSxcbiAgICAgIGkgPSAtMSxcbiAgICAgIG4sXG4gICAgICB0aWNrcyxcbiAgICAgIHN0ZXA7XG5cbiAgc3RvcCA9ICtzdG9wLCBzdGFydCA9ICtzdGFydCwgY291bnQgPSArY291bnQ7XG4gIGlmIChzdGFydCA9PT0gc3RvcCAmJiBjb3VudCA+IDApIHJldHVybiBbc3RhcnRdO1xuICBpZiAocmV2ZXJzZSA9IHN0b3AgPCBzdGFydCkgbiA9IHN0YXJ0LCBzdGFydCA9IHN0b3AsIHN0b3AgPSBuO1xuICBpZiAoKHN0ZXAgPSB0aWNrSW5jcmVtZW50KHN0YXJ0LCBzdG9wLCBjb3VudCkpID09PSAwIHx8ICFpc0Zpbml0ZShzdGVwKSkgcmV0dXJuIFtdO1xuXG4gIGlmIChzdGVwID4gMCkge1xuICAgIHN0YXJ0ID0gTWF0aC5jZWlsKHN0YXJ0IC8gc3RlcCk7XG4gICAgc3RvcCA9IE1hdGguZmxvb3Ioc3RvcCAvIHN0ZXApO1xuICAgIHRpY2tzID0gbmV3IEFycmF5KG4gPSBNYXRoLmNlaWwoc3RvcCAtIHN0YXJ0ICsgMSkpO1xuICAgIHdoaWxlICgrK2kgPCBuKSB0aWNrc1tpXSA9IChzdGFydCArIGkpICogc3RlcDtcbiAgfSBlbHNlIHtcbiAgICBzdGFydCA9IE1hdGguZmxvb3Ioc3RhcnQgKiBzdGVwKTtcbiAgICBzdG9wID0gTWF0aC5jZWlsKHN0b3AgKiBzdGVwKTtcbiAgICB0aWNrcyA9IG5ldyBBcnJheShuID0gTWF0aC5jZWlsKHN0YXJ0IC0gc3RvcCArIDEpKTtcbiAgICB3aGlsZSAoKytpIDwgbikgdGlja3NbaV0gPSAoc3RhcnQgLSBpKSAvIHN0ZXA7XG4gIH1cblxuICBpZiAocmV2ZXJzZSkgdGlja3MucmV2ZXJzZSgpO1xuXG4gIHJldHVybiB0aWNrcztcbn1cblxuZnVuY3Rpb24gdGlja0luY3JlbWVudChzdGFydCwgc3RvcCwgY291bnQpIHtcbiAgdmFyIHN0ZXAgPSAoc3RvcCAtIHN0YXJ0KSAvIE1hdGgubWF4KDAsIGNvdW50KSxcbiAgICAgIHBvd2VyID0gTWF0aC5mbG9vcihNYXRoLmxvZyhzdGVwKSAvIE1hdGguTE4xMCksXG4gICAgICBlcnJvciA9IHN0ZXAgLyBNYXRoLnBvdygxMCwgcG93ZXIpO1xuICByZXR1cm4gcG93ZXIgPj0gMFxuICAgICAgPyAoZXJyb3IgPj0gZTEwID8gMTAgOiBlcnJvciA+PSBlNSA/IDUgOiBlcnJvciA+PSBlMiA/IDIgOiAxKSAqIE1hdGgucG93KDEwLCBwb3dlcilcbiAgICAgIDogLU1hdGgucG93KDEwLCAtcG93ZXIpIC8gKGVycm9yID49IGUxMCA/IDEwIDogZXJyb3IgPj0gZTUgPyA1IDogZXJyb3IgPj0gZTIgPyAyIDogMSk7XG59XG5cbmZ1bmN0aW9uIHRpY2tTdGVwKHN0YXJ0LCBzdG9wLCBjb3VudCkge1xuICB2YXIgc3RlcDAgPSBNYXRoLmFicyhzdG9wIC0gc3RhcnQpIC8gTWF0aC5tYXgoMCwgY291bnQpLFxuICAgICAgc3RlcDEgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihNYXRoLmxvZyhzdGVwMCkgLyBNYXRoLkxOMTApKSxcbiAgICAgIGVycm9yID0gc3RlcDAgLyBzdGVwMTtcbiAgaWYgKGVycm9yID49IGUxMCkgc3RlcDEgKj0gMTA7XG4gIGVsc2UgaWYgKGVycm9yID49IGU1KSBzdGVwMSAqPSA1O1xuICBlbHNlIGlmIChlcnJvciA+PSBlMikgc3RlcDEgKj0gMjtcbiAgcmV0dXJuIHN0b3AgPCBzdGFydCA/IC1zdGVwMSA6IHN0ZXAxO1xufVxuXG5mdW5jdGlvbiBzdHVyZ2VzKHZhbHVlcykge1xuICByZXR1cm4gTWF0aC5jZWlsKE1hdGgubG9nKHZhbHVlcy5sZW5ndGgpIC8gTWF0aC5MTjIpICsgMTtcbn1cblxuZnVuY3Rpb24gaGlzdG9ncmFtKCkge1xuICB2YXIgdmFsdWUgPSBpZGVudGl0eSxcbiAgICAgIGRvbWFpbiA9IGV4dGVudCxcbiAgICAgIHRocmVzaG9sZCA9IHN0dXJnZXM7XG5cbiAgZnVuY3Rpb24gaGlzdG9ncmFtKGRhdGEpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgICB4LFxuICAgICAgICB2YWx1ZXMgPSBuZXcgQXJyYXkobik7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YWx1ZXNbaV0gPSB2YWx1ZShkYXRhW2ldLCBpLCBkYXRhKTtcbiAgICB9XG5cbiAgICB2YXIgeHogPSBkb21haW4odmFsdWVzKSxcbiAgICAgICAgeDAgPSB4elswXSxcbiAgICAgICAgeDEgPSB4elsxXSxcbiAgICAgICAgdHogPSB0aHJlc2hvbGQodmFsdWVzLCB4MCwgeDEpO1xuXG4gICAgLy8gQ29udmVydCBudW1iZXIgb2YgdGhyZXNob2xkcyBpbnRvIHVuaWZvcm0gdGhyZXNob2xkcy5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodHopKSB7XG4gICAgICB0eiA9IHRpY2tTdGVwKHgwLCB4MSwgdHopO1xuICAgICAgdHogPSByYW5nZShNYXRoLmNlaWwoeDAgLyB0eikgKiB0eiwgeDEsIHR6KTsgLy8gZXhjbHVzaXZlXG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGFueSB0aHJlc2hvbGRzIG91dHNpZGUgdGhlIGRvbWFpbi5cbiAgICB2YXIgbSA9IHR6Lmxlbmd0aDtcbiAgICB3aGlsZSAodHpbMF0gPD0geDApIHR6LnNoaWZ0KCksIC0tbTtcbiAgICB3aGlsZSAodHpbbSAtIDFdID4geDEpIHR6LnBvcCgpLCAtLW07XG5cbiAgICB2YXIgYmlucyA9IG5ldyBBcnJheShtICsgMSksXG4gICAgICAgIGJpbjtcblxuICAgIC8vIEluaXRpYWxpemUgYmlucy5cbiAgICBmb3IgKGkgPSAwOyBpIDw9IG07ICsraSkge1xuICAgICAgYmluID0gYmluc1tpXSA9IFtdO1xuICAgICAgYmluLngwID0gaSA+IDAgPyB0eltpIC0gMV0gOiB4MDtcbiAgICAgIGJpbi54MSA9IGkgPCBtID8gdHpbaV0gOiB4MTtcbiAgICB9XG5cbiAgICAvLyBBc3NpZ24gZGF0YSB0byBiaW5zIGJ5IHZhbHVlLCBpZ25vcmluZyBhbnkgb3V0c2lkZSB0aGUgZG9tYWluLlxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHggPSB2YWx1ZXNbaV07XG4gICAgICBpZiAoeDAgPD0geCAmJiB4IDw9IHgxKSB7XG4gICAgICAgIGJpbnNbYmlzZWN0UmlnaHQodHosIHgsIDAsIG0pXS5wdXNoKGRhdGFbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBiaW5zO1xuICB9XG5cbiAgaGlzdG9ncmFtLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgaGlzdG9ncmFtKSA6IHZhbHVlO1xuICB9O1xuXG4gIGhpc3RvZ3JhbS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChbX1swXSwgX1sxXV0pLCBoaXN0b2dyYW0pIDogZG9tYWluO1xuICB9O1xuXG4gIGhpc3RvZ3JhbS50aHJlc2hvbGRzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRocmVzaG9sZCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogQXJyYXkuaXNBcnJheShfKSA/IGNvbnN0YW50KHNsaWNlLmNhbGwoXykpIDogY29uc3RhbnQoXyksIGhpc3RvZ3JhbSkgOiB0aHJlc2hvbGQ7XG4gIH07XG5cbiAgcmV0dXJuIGhpc3RvZ3JhbTtcbn1cblxuZnVuY3Rpb24gcXVhbnRpbGUodmFsdWVzLCBwLCB2YWx1ZW9mKSB7XG4gIGlmICh2YWx1ZW9mID09IG51bGwpIHZhbHVlb2YgPSBudW1iZXI7XG4gIGlmICghKG4gPSB2YWx1ZXMubGVuZ3RoKSkgcmV0dXJuO1xuICBpZiAoKHAgPSArcCkgPD0gMCB8fCBuIDwgMikgcmV0dXJuICt2YWx1ZW9mKHZhbHVlc1swXSwgMCwgdmFsdWVzKTtcbiAgaWYgKHAgPj0gMSkgcmV0dXJuICt2YWx1ZW9mKHZhbHVlc1tuIC0gMV0sIG4gLSAxLCB2YWx1ZXMpO1xuICB2YXIgbixcbiAgICAgIGkgPSAobiAtIDEpICogcCxcbiAgICAgIGkwID0gTWF0aC5mbG9vcihpKSxcbiAgICAgIHZhbHVlMCA9ICt2YWx1ZW9mKHZhbHVlc1tpMF0sIGkwLCB2YWx1ZXMpLFxuICAgICAgdmFsdWUxID0gK3ZhbHVlb2YodmFsdWVzW2kwICsgMV0sIGkwICsgMSwgdmFsdWVzKTtcbiAgcmV0dXJuIHZhbHVlMCArICh2YWx1ZTEgLSB2YWx1ZTApICogKGkgLSBpMCk7XG59XG5cbmZ1bmN0aW9uIGZyZWVkbWFuRGlhY29uaXModmFsdWVzLCBtaW4sIG1heCkge1xuICB2YWx1ZXMgPSBtYXAuY2FsbCh2YWx1ZXMsIG51bWJlcikuc29ydChhc2NlbmRpbmcpO1xuICByZXR1cm4gTWF0aC5jZWlsKChtYXggLSBtaW4pIC8gKDIgKiAocXVhbnRpbGUodmFsdWVzLCAwLjc1KSAtIHF1YW50aWxlKHZhbHVlcywgMC4yNSkpICogTWF0aC5wb3codmFsdWVzLmxlbmd0aCwgLTEgLyAzKSkpO1xufVxuXG5mdW5jdGlvbiBzY290dCh2YWx1ZXMsIG1pbiwgbWF4KSB7XG4gIHJldHVybiBNYXRoLmNlaWwoKG1heCAtIG1pbikgLyAoMy41ICogZGV2aWF0aW9uKHZhbHVlcykgKiBNYXRoLnBvdyh2YWx1ZXMubGVuZ3RoLCAtMSAvIDMpKSk7XG59XG5cbmZ1bmN0aW9uIG1heCh2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBtYXg7XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1heCA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgdmFsdWUgPiBtYXgpIHtcbiAgICAgICAgICAgIG1heCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWF4ID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIHZhbHVlID4gbWF4KSB7XG4gICAgICAgICAgICBtYXggPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWF4O1xufVxuXG5mdW5jdGlvbiBtZWFuKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBtID0gbixcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGlmIChtKSByZXR1cm4gc3VtIC8gbTtcbn1cblxuZnVuY3Rpb24gbWVkaWFuKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBpID0gLTEsXG4gICAgICB2YWx1ZSxcbiAgICAgIG51bWJlcnMgPSBbXTtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHtcbiAgICAgICAgbnVtYmVycy5wdXNoKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgaWYgKCFpc05hTih2YWx1ZSA9IG51bWJlcih2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkpKSB7XG4gICAgICAgIG51bWJlcnMucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHF1YW50aWxlKG51bWJlcnMuc29ydChhc2NlbmRpbmcpLCAwLjUpO1xufVxuXG5mdW5jdGlvbiBtZXJnZShhcnJheXMpIHtcbiAgdmFyIG4gPSBhcnJheXMubGVuZ3RoLFxuICAgICAgbSxcbiAgICAgIGkgPSAtMSxcbiAgICAgIGogPSAwLFxuICAgICAgbWVyZ2VkLFxuICAgICAgYXJyYXk7XG5cbiAgd2hpbGUgKCsraSA8IG4pIGogKz0gYXJyYXlzW2ldLmxlbmd0aDtcbiAgbWVyZ2VkID0gbmV3IEFycmF5KGopO1xuXG4gIHdoaWxlICgtLW4gPj0gMCkge1xuICAgIGFycmF5ID0gYXJyYXlzW25dO1xuICAgIG0gPSBhcnJheS5sZW5ndGg7XG4gICAgd2hpbGUgKC0tbSA+PSAwKSB7XG4gICAgICBtZXJnZWRbLS1qXSA9IGFycmF5W21dO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtZXJnZWQ7XG59XG5cbmZ1bmN0aW9uIG1pbih2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBtaW47XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgbWluID4gdmFsdWUpIHtcbiAgICAgICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWluID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIG1pbiA+IHZhbHVlKSB7XG4gICAgICAgICAgICBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWluO1xufVxuXG5mdW5jdGlvbiBwZXJtdXRlKGFycmF5LCBpbmRleGVzKSB7XG4gIHZhciBpID0gaW5kZXhlcy5sZW5ndGgsIHBlcm11dGVzID0gbmV3IEFycmF5KGkpO1xuICB3aGlsZSAoaS0tKSBwZXJtdXRlc1tpXSA9IGFycmF5W2luZGV4ZXNbaV1dO1xuICByZXR1cm4gcGVybXV0ZXM7XG59XG5cbmZ1bmN0aW9uIHNjYW4odmFsdWVzLCBjb21wYXJlKSB7XG4gIGlmICghKG4gPSB2YWx1ZXMubGVuZ3RoKSkgcmV0dXJuO1xuICB2YXIgbixcbiAgICAgIGkgPSAwLFxuICAgICAgaiA9IDAsXG4gICAgICB4aSxcbiAgICAgIHhqID0gdmFsdWVzW2pdO1xuXG4gIGlmIChjb21wYXJlID09IG51bGwpIGNvbXBhcmUgPSBhc2NlbmRpbmc7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBpZiAoY29tcGFyZSh4aSA9IHZhbHVlc1tpXSwgeGopIDwgMCB8fCBjb21wYXJlKHhqLCB4aikgIT09IDApIHtcbiAgICAgIHhqID0geGksIGogPSBpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb21wYXJlKHhqLCB4aikgPT09IDApIHJldHVybiBqO1xufVxuXG5mdW5jdGlvbiBzaHVmZmxlKGFycmF5LCBpMCwgaTEpIHtcbiAgdmFyIG0gPSAoaTEgPT0gbnVsbCA/IGFycmF5Lmxlbmd0aCA6IGkxKSAtIChpMCA9IGkwID09IG51bGwgPyAwIDogK2kwKSxcbiAgICAgIHQsXG4gICAgICBpO1xuXG4gIHdoaWxlIChtKSB7XG4gICAgaSA9IE1hdGgucmFuZG9tKCkgKiBtLS0gfCAwO1xuICAgIHQgPSBhcnJheVttICsgaTBdO1xuICAgIGFycmF5W20gKyBpMF0gPSBhcnJheVtpICsgaTBdO1xuICAgIGFycmF5W2kgKyBpMF0gPSB0O1xuICB9XG5cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5mdW5jdGlvbiBzdW0odmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh2YWx1ZSA9ICt2YWx1ZXNbaV0pIHN1bSArPSB2YWx1ZTsgLy8gTm90ZTogemVybyBhbmQgbnVsbCBhcmUgZXF1aXZhbGVudC5cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgaWYgKHZhbHVlID0gK3ZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSBzdW0gKz0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN1bTtcbn1cblxuZnVuY3Rpb24gdHJhbnNwb3NlKG1hdHJpeCkge1xuICBpZiAoIShuID0gbWF0cml4Lmxlbmd0aCkpIHJldHVybiBbXTtcbiAgZm9yICh2YXIgaSA9IC0xLCBtID0gbWluKG1hdHJpeCwgbGVuZ3RoKSwgdHJhbnNwb3NlID0gbmV3IEFycmF5KG0pOyArK2kgPCBtOykge1xuICAgIGZvciAodmFyIGogPSAtMSwgbiwgcm93ID0gdHJhbnNwb3NlW2ldID0gbmV3IEFycmF5KG4pOyArK2ogPCBuOykge1xuICAgICAgcm93W2pdID0gbWF0cml4W2pdW2ldO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJhbnNwb3NlO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgoZCkge1xuICByZXR1cm4gZC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHppcCgpIHtcbiAgcmV0dXJuIHRyYW5zcG9zZShhcmd1bWVudHMpO1xufVxuXG5leHBvcnRzLmJpc2VjdCA9IGJpc2VjdFJpZ2h0O1xuZXhwb3J0cy5iaXNlY3RSaWdodCA9IGJpc2VjdFJpZ2h0O1xuZXhwb3J0cy5iaXNlY3RMZWZ0ID0gYmlzZWN0TGVmdDtcbmV4cG9ydHMuYXNjZW5kaW5nID0gYXNjZW5kaW5nO1xuZXhwb3J0cy5iaXNlY3RvciA9IGJpc2VjdG9yO1xuZXhwb3J0cy5jcm9zcyA9IGNyb3NzO1xuZXhwb3J0cy5kZXNjZW5kaW5nID0gZGVzY2VuZGluZztcbmV4cG9ydHMuZGV2aWF0aW9uID0gZGV2aWF0aW9uO1xuZXhwb3J0cy5leHRlbnQgPSBleHRlbnQ7XG5leHBvcnRzLmhpc3RvZ3JhbSA9IGhpc3RvZ3JhbTtcbmV4cG9ydHMudGhyZXNob2xkRnJlZWRtYW5EaWFjb25pcyA9IGZyZWVkbWFuRGlhY29uaXM7XG5leHBvcnRzLnRocmVzaG9sZFNjb3R0ID0gc2NvdHQ7XG5leHBvcnRzLnRocmVzaG9sZFN0dXJnZXMgPSBzdHVyZ2VzO1xuZXhwb3J0cy5tYXggPSBtYXg7XG5leHBvcnRzLm1lYW4gPSBtZWFuO1xuZXhwb3J0cy5tZWRpYW4gPSBtZWRpYW47XG5leHBvcnRzLm1lcmdlID0gbWVyZ2U7XG5leHBvcnRzLm1pbiA9IG1pbjtcbmV4cG9ydHMucGFpcnMgPSBwYWlycztcbmV4cG9ydHMucGVybXV0ZSA9IHBlcm11dGU7XG5leHBvcnRzLnF1YW50aWxlID0gcXVhbnRpbGU7XG5leHBvcnRzLnJhbmdlID0gcmFuZ2U7XG5leHBvcnRzLnNjYW4gPSBzY2FuO1xuZXhwb3J0cy5zaHVmZmxlID0gc2h1ZmZsZTtcbmV4cG9ydHMuc3VtID0gc3VtO1xuZXhwb3J0cy50aWNrcyA9IHRpY2tzO1xuZXhwb3J0cy50aWNrSW5jcmVtZW50ID0gdGlja0luY3JlbWVudDtcbmV4cG9ydHMudGlja1N0ZXAgPSB0aWNrU3RlcDtcbmV4cG9ydHMudHJhbnNwb3NlID0gdHJhbnNwb3NlO1xuZXhwb3J0cy52YXJpYW5jZSA9IHZhcmlhbmNlO1xuZXhwb3J0cy56aXAgPSB6aXA7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWNvbGxlY3Rpb24vIFZlcnNpb24gMS4wLjQuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHByZWZpeCA9IFwiJFwiO1xuXG5mdW5jdGlvbiBNYXAoKSB7fVxuXG5NYXAucHJvdG90eXBlID0gbWFwLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IE1hcCxcbiAgaGFzOiBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gKHByZWZpeCArIGtleSkgaW4gdGhpcztcbiAgfSxcbiAgZ2V0OiBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gdGhpc1twcmVmaXggKyBrZXldO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICB0aGlzW3ByZWZpeCArIGtleV0gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmVtb3ZlOiBmdW5jdGlvbihrZXkpIHtcbiAgICB2YXIgcHJvcGVydHkgPSBwcmVmaXggKyBrZXk7XG4gICAgcmV0dXJuIHByb3BlcnR5IGluIHRoaXMgJiYgZGVsZXRlIHRoaXNbcHJvcGVydHldO1xuICB9LFxuICBjbGVhcjogZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIGRlbGV0ZSB0aGlzW3Byb3BlcnR5XTtcbiAgfSxcbiAga2V5czogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkga2V5cy5wdXNoKHByb3BlcnR5LnNsaWNlKDEpKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfSxcbiAgdmFsdWVzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWVzID0gW107XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIHZhbHVlcy5wdXNoKHRoaXNbcHJvcGVydHldKTtcbiAgICByZXR1cm4gdmFsdWVzO1xuICB9LFxuICBlbnRyaWVzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgZW50cmllcyA9IFtdO1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSBlbnRyaWVzLnB1c2goe2tleTogcHJvcGVydHkuc2xpY2UoMSksIHZhbHVlOiB0aGlzW3Byb3BlcnR5XX0pO1xuICAgIHJldHVybiBlbnRyaWVzO1xuICB9LFxuICBzaXplOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2l6ZSA9IDA7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpICsrc2l6ZTtcbiAgICByZXR1cm4gc2l6ZTtcbiAgfSxcbiAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGVhY2g6IGZ1bmN0aW9uKGYpIHtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkgZih0aGlzW3Byb3BlcnR5XSwgcHJvcGVydHkuc2xpY2UoMSksIHRoaXMpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBtYXAob2JqZWN0LCBmKSB7XG4gIHZhciBtYXAgPSBuZXcgTWFwO1xuXG4gIC8vIENvcHkgY29uc3RydWN0b3IuXG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBNYXApIG9iamVjdC5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsgbWFwLnNldChrZXksIHZhbHVlKTsgfSk7XG5cbiAgLy8gSW5kZXggYXJyYXkgYnkgbnVtZXJpYyBpbmRleCBvciBzcGVjaWZpZWQga2V5IGZ1bmN0aW9uLlxuICBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICB2YXIgaSA9IC0xLFxuICAgICAgICBuID0gb2JqZWN0Lmxlbmd0aCxcbiAgICAgICAgbztcblxuICAgIGlmIChmID09IG51bGwpIHdoaWxlICgrK2kgPCBuKSBtYXAuc2V0KGksIG9iamVjdFtpXSk7XG4gICAgZWxzZSB3aGlsZSAoKytpIDwgbikgbWFwLnNldChmKG8gPSBvYmplY3RbaV0sIGksIG9iamVjdCksIG8pO1xuICB9XG5cbiAgLy8gQ29udmVydCBvYmplY3QgdG8gbWFwLlxuICBlbHNlIGlmIChvYmplY3QpIGZvciAodmFyIGtleSBpbiBvYmplY3QpIG1hcC5zZXQoa2V5LCBvYmplY3Rba2V5XSk7XG5cbiAgcmV0dXJuIG1hcDtcbn1cblxudmFyIG5lc3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGtleXMgPSBbXSxcbiAgICAgIHNvcnRLZXlzID0gW10sXG4gICAgICBzb3J0VmFsdWVzLFxuICAgICAgcm9sbHVwLFxuICAgICAgbmVzdDtcblxuICBmdW5jdGlvbiBhcHBseShhcnJheSwgZGVwdGgsIGNyZWF0ZVJlc3VsdCwgc2V0UmVzdWx0KSB7XG4gICAgaWYgKGRlcHRoID49IGtleXMubGVuZ3RoKSB7XG4gICAgICBpZiAoc29ydFZhbHVlcyAhPSBudWxsKSBhcnJheS5zb3J0KHNvcnRWYWx1ZXMpO1xuICAgICAgcmV0dXJuIHJvbGx1cCAhPSBudWxsID8gcm9sbHVwKGFycmF5KSA6IGFycmF5O1xuICAgIH1cblxuICAgIHZhciBpID0gLTEsXG4gICAgICAgIG4gPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIGtleSA9IGtleXNbZGVwdGgrK10sXG4gICAgICAgIGtleVZhbHVlLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgdmFsdWVzQnlLZXkgPSBtYXAoKSxcbiAgICAgICAgdmFsdWVzLFxuICAgICAgICByZXN1bHQgPSBjcmVhdGVSZXN1bHQoKTtcblxuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAodmFsdWVzID0gdmFsdWVzQnlLZXkuZ2V0KGtleVZhbHVlID0ga2V5KHZhbHVlID0gYXJyYXlbaV0pICsgXCJcIikpIHtcbiAgICAgICAgdmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVzQnlLZXkuc2V0KGtleVZhbHVlLCBbdmFsdWVdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YWx1ZXNCeUtleS5lYWNoKGZ1bmN0aW9uKHZhbHVlcywga2V5KSB7XG4gICAgICBzZXRSZXN1bHQocmVzdWx0LCBrZXksIGFwcGx5KHZhbHVlcywgZGVwdGgsIGNyZWF0ZVJlc3VsdCwgc2V0UmVzdWx0KSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gZW50cmllcyhtYXAkJDEsIGRlcHRoKSB7XG4gICAgaWYgKCsrZGVwdGggPiBrZXlzLmxlbmd0aCkgcmV0dXJuIG1hcCQkMTtcbiAgICB2YXIgYXJyYXksIHNvcnRLZXkgPSBzb3J0S2V5c1tkZXB0aCAtIDFdO1xuICAgIGlmIChyb2xsdXAgIT0gbnVsbCAmJiBkZXB0aCA+PSBrZXlzLmxlbmd0aCkgYXJyYXkgPSBtYXAkJDEuZW50cmllcygpO1xuICAgIGVsc2UgYXJyYXkgPSBbXSwgbWFwJCQxLmVhY2goZnVuY3Rpb24odiwgaykgeyBhcnJheS5wdXNoKHtrZXk6IGssIHZhbHVlczogZW50cmllcyh2LCBkZXB0aCl9KTsgfSk7XG4gICAgcmV0dXJuIHNvcnRLZXkgIT0gbnVsbCA/IGFycmF5LnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gc29ydEtleShhLmtleSwgYi5rZXkpOyB9KSA6IGFycmF5O1xuICB9XG5cbiAgcmV0dXJuIG5lc3QgPSB7XG4gICAgb2JqZWN0OiBmdW5jdGlvbihhcnJheSkgeyByZXR1cm4gYXBwbHkoYXJyYXksIDAsIGNyZWF0ZU9iamVjdCwgc2V0T2JqZWN0KTsgfSxcbiAgICBtYXA6IGZ1bmN0aW9uKGFycmF5KSB7IHJldHVybiBhcHBseShhcnJheSwgMCwgY3JlYXRlTWFwLCBzZXRNYXApOyB9LFxuICAgIGVudHJpZXM6IGZ1bmN0aW9uKGFycmF5KSB7IHJldHVybiBlbnRyaWVzKGFwcGx5KGFycmF5LCAwLCBjcmVhdGVNYXAsIHNldE1hcCksIDApOyB9LFxuICAgIGtleTogZnVuY3Rpb24oZCkgeyBrZXlzLnB1c2goZCk7IHJldHVybiBuZXN0OyB9LFxuICAgIHNvcnRLZXlzOiBmdW5jdGlvbihvcmRlcikgeyBzb3J0S2V5c1trZXlzLmxlbmd0aCAtIDFdID0gb3JkZXI7IHJldHVybiBuZXN0OyB9LFxuICAgIHNvcnRWYWx1ZXM6IGZ1bmN0aW9uKG9yZGVyKSB7IHNvcnRWYWx1ZXMgPSBvcmRlcjsgcmV0dXJuIG5lc3Q7IH0sXG4gICAgcm9sbHVwOiBmdW5jdGlvbihmKSB7IHJvbGx1cCA9IGY7IHJldHVybiBuZXN0OyB9XG4gIH07XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVPYmplY3QoKSB7XG4gIHJldHVybiB7fTtcbn1cblxuZnVuY3Rpb24gc2V0T2JqZWN0KG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVNYXAoKSB7XG4gIHJldHVybiBtYXAoKTtcbn1cblxuZnVuY3Rpb24gc2V0TWFwKG1hcCQkMSwga2V5LCB2YWx1ZSkge1xuICBtYXAkJDEuc2V0KGtleSwgdmFsdWUpO1xufVxuXG5mdW5jdGlvbiBTZXQoKSB7fVxuXG52YXIgcHJvdG8gPSBtYXAucHJvdG90eXBlO1xuXG5TZXQucHJvdG90eXBlID0gc2V0LnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFNldCxcbiAgaGFzOiBwcm90by5oYXMsXG4gIGFkZDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YWx1ZSArPSBcIlwiO1xuICAgIHRoaXNbcHJlZml4ICsgdmFsdWVdID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHJlbW92ZTogcHJvdG8ucmVtb3ZlLFxuICBjbGVhcjogcHJvdG8uY2xlYXIsXG4gIHZhbHVlczogcHJvdG8ua2V5cyxcbiAgc2l6ZTogcHJvdG8uc2l6ZSxcbiAgZW1wdHk6IHByb3RvLmVtcHR5LFxuICBlYWNoOiBwcm90by5lYWNoXG59O1xuXG5mdW5jdGlvbiBzZXQob2JqZWN0LCBmKSB7XG4gIHZhciBzZXQgPSBuZXcgU2V0O1xuXG4gIC8vIENvcHkgY29uc3RydWN0b3IuXG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBTZXQpIG9iamVjdC5lYWNoKGZ1bmN0aW9uKHZhbHVlKSB7IHNldC5hZGQodmFsdWUpOyB9KTtcblxuICAvLyBPdGhlcndpc2UsIGFzc3VtZSBpdOKAmXMgYW4gYXJyYXkuXG4gIGVsc2UgaWYgKG9iamVjdCkge1xuICAgIHZhciBpID0gLTEsIG4gPSBvYmplY3QubGVuZ3RoO1xuICAgIGlmIChmID09IG51bGwpIHdoaWxlICgrK2kgPCBuKSBzZXQuYWRkKG9iamVjdFtpXSk7XG4gICAgZWxzZSB3aGlsZSAoKytpIDwgbikgc2V0LmFkZChmKG9iamVjdFtpXSwgaSwgb2JqZWN0KSk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG52YXIga2V5cyA9IGZ1bmN0aW9uKG1hcCkge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gbWFwKSBrZXlzLnB1c2goa2V5KTtcbiAgcmV0dXJuIGtleXM7XG59O1xuXG52YXIgdmFsdWVzID0gZnVuY3Rpb24obWFwKSB7XG4gIHZhciB2YWx1ZXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG1hcCkgdmFsdWVzLnB1c2gobWFwW2tleV0pO1xuICByZXR1cm4gdmFsdWVzO1xufTtcblxudmFyIGVudHJpZXMgPSBmdW5jdGlvbihtYXApIHtcbiAgdmFyIGVudHJpZXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG1hcCkgZW50cmllcy5wdXNoKHtrZXk6IGtleSwgdmFsdWU6IG1hcFtrZXldfSk7XG4gIHJldHVybiBlbnRyaWVzO1xufTtcblxuZXhwb3J0cy5uZXN0ID0gbmVzdDtcbmV4cG9ydHMuc2V0ID0gc2V0O1xuZXhwb3J0cy5tYXAgPSBtYXA7XG5leHBvcnRzLmtleXMgPSBrZXlzO1xuZXhwb3J0cy52YWx1ZXMgPSB2YWx1ZXM7XG5leHBvcnRzLmVudHJpZXMgPSBlbnRyaWVzO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1jb2xvci8gdjEuMi4zIENvcHlyaWdodCAyMDE4IE1pa2UgQm9zdG9ja1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbnR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxudHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG4oZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBkZWZpbmUoY29uc3RydWN0b3IsIGZhY3RvcnksIHByb3RvdHlwZSkge1xuICBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBmYWN0b3J5LnByb3RvdHlwZSA9IHByb3RvdHlwZTtcbiAgcHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY29uc3RydWN0b3I7XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChwYXJlbnQsIGRlZmluaXRpb24pIHtcbiAgdmFyIHByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUocGFyZW50LnByb3RvdHlwZSk7XG4gIGZvciAodmFyIGtleSBpbiBkZWZpbml0aW9uKSBwcm90b3R5cGVba2V5XSA9IGRlZmluaXRpb25ba2V5XTtcbiAgcmV0dXJuIHByb3RvdHlwZTtcbn1cblxuZnVuY3Rpb24gQ29sb3IoKSB7fVxuXG52YXIgZGFya2VyID0gMC43O1xudmFyIGJyaWdodGVyID0gMSAvIGRhcmtlcjtcblxudmFyIHJlSSA9IFwiXFxcXHMqKFsrLV0/XFxcXGQrKVxcXFxzKlwiLFxuICAgIHJlTiA9IFwiXFxcXHMqKFsrLV0/XFxcXGQqXFxcXC4/XFxcXGQrKD86W2VFXVsrLV0/XFxcXGQrKT8pXFxcXHMqXCIsXG4gICAgcmVQID0gXCJcXFxccyooWystXT9cXFxcZCpcXFxcLj9cXFxcZCsoPzpbZUVdWystXT9cXFxcZCspPyklXFxcXHMqXCIsXG4gICAgcmVIZXgzID0gL14jKFswLTlhLWZdezN9KSQvLFxuICAgIHJlSGV4NiA9IC9eIyhbMC05YS1mXXs2fSkkLyxcbiAgICByZVJnYkludGVnZXIgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVJLCByZUksIHJlSV0gKyBcIlxcXFwpJFwiKSxcbiAgICByZVJnYlBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUF0gKyBcIlxcXFwpJFwiKSxcbiAgICByZVJnYmFJbnRlZ2VyID0gbmV3IFJlZ0V4cChcIl5yZ2JhXFxcXChcIiArIFtyZUksIHJlSSwgcmVJLCByZU5dICsgXCJcXFxcKSRcIiksXG4gICAgcmVSZ2JhUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJecmdiYVxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUCwgcmVOXSArIFwiXFxcXCkkXCIpLFxuICAgIHJlSHNsUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJeaHNsXFxcXChcIiArIFtyZU4sIHJlUCwgcmVQXSArIFwiXFxcXCkkXCIpLFxuICAgIHJlSHNsYVBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXmhzbGFcXFxcKFwiICsgW3JlTiwgcmVQLCByZVAsIHJlTl0gKyBcIlxcXFwpJFwiKTtcblxudmFyIG5hbWVkID0ge1xuICBhbGljZWJsdWU6IDB4ZjBmOGZmLFxuICBhbnRpcXVld2hpdGU6IDB4ZmFlYmQ3LFxuICBhcXVhOiAweDAwZmZmZixcbiAgYXF1YW1hcmluZTogMHg3ZmZmZDQsXG4gIGF6dXJlOiAweGYwZmZmZixcbiAgYmVpZ2U6IDB4ZjVmNWRjLFxuICBiaXNxdWU6IDB4ZmZlNGM0LFxuICBibGFjazogMHgwMDAwMDAsXG4gIGJsYW5jaGVkYWxtb25kOiAweGZmZWJjZCxcbiAgYmx1ZTogMHgwMDAwZmYsXG4gIGJsdWV2aW9sZXQ6IDB4OGEyYmUyLFxuICBicm93bjogMHhhNTJhMmEsXG4gIGJ1cmx5d29vZDogMHhkZWI4ODcsXG4gIGNhZGV0Ymx1ZTogMHg1ZjllYTAsXG4gIGNoYXJ0cmV1c2U6IDB4N2ZmZjAwLFxuICBjaG9jb2xhdGU6IDB4ZDI2OTFlLFxuICBjb3JhbDogMHhmZjdmNTAsXG4gIGNvcm5mbG93ZXJibHVlOiAweDY0OTVlZCxcbiAgY29ybnNpbGs6IDB4ZmZmOGRjLFxuICBjcmltc29uOiAweGRjMTQzYyxcbiAgY3lhbjogMHgwMGZmZmYsXG4gIGRhcmtibHVlOiAweDAwMDA4YixcbiAgZGFya2N5YW46IDB4MDA4YjhiLFxuICBkYXJrZ29sZGVucm9kOiAweGI4ODYwYixcbiAgZGFya2dyYXk6IDB4YTlhOWE5LFxuICBkYXJrZ3JlZW46IDB4MDA2NDAwLFxuICBkYXJrZ3JleTogMHhhOWE5YTksXG4gIGRhcmtraGFraTogMHhiZGI3NmIsXG4gIGRhcmttYWdlbnRhOiAweDhiMDA4YixcbiAgZGFya29saXZlZ3JlZW46IDB4NTU2YjJmLFxuICBkYXJrb3JhbmdlOiAweGZmOGMwMCxcbiAgZGFya29yY2hpZDogMHg5OTMyY2MsXG4gIGRhcmtyZWQ6IDB4OGIwMDAwLFxuICBkYXJrc2FsbW9uOiAweGU5OTY3YSxcbiAgZGFya3NlYWdyZWVuOiAweDhmYmM4ZixcbiAgZGFya3NsYXRlYmx1ZTogMHg0ODNkOGIsXG4gIGRhcmtzbGF0ZWdyYXk6IDB4MmY0ZjRmLFxuICBkYXJrc2xhdGVncmV5OiAweDJmNGY0ZixcbiAgZGFya3R1cnF1b2lzZTogMHgwMGNlZDEsXG4gIGRhcmt2aW9sZXQ6IDB4OTQwMGQzLFxuICBkZWVwcGluazogMHhmZjE0OTMsXG4gIGRlZXBza3libHVlOiAweDAwYmZmZixcbiAgZGltZ3JheTogMHg2OTY5NjksXG4gIGRpbWdyZXk6IDB4Njk2OTY5LFxuICBkb2RnZXJibHVlOiAweDFlOTBmZixcbiAgZmlyZWJyaWNrOiAweGIyMjIyMixcbiAgZmxvcmFsd2hpdGU6IDB4ZmZmYWYwLFxuICBmb3Jlc3RncmVlbjogMHgyMjhiMjIsXG4gIGZ1Y2hzaWE6IDB4ZmYwMGZmLFxuICBnYWluc2Jvcm86IDB4ZGNkY2RjLFxuICBnaG9zdHdoaXRlOiAweGY4ZjhmZixcbiAgZ29sZDogMHhmZmQ3MDAsXG4gIGdvbGRlbnJvZDogMHhkYWE1MjAsXG4gIGdyYXk6IDB4ODA4MDgwLFxuICBncmVlbjogMHgwMDgwMDAsXG4gIGdyZWVueWVsbG93OiAweGFkZmYyZixcbiAgZ3JleTogMHg4MDgwODAsXG4gIGhvbmV5ZGV3OiAweGYwZmZmMCxcbiAgaG90cGluazogMHhmZjY5YjQsXG4gIGluZGlhbnJlZDogMHhjZDVjNWMsXG4gIGluZGlnbzogMHg0YjAwODIsXG4gIGl2b3J5OiAweGZmZmZmMCxcbiAga2hha2k6IDB4ZjBlNjhjLFxuICBsYXZlbmRlcjogMHhlNmU2ZmEsXG4gIGxhdmVuZGVyYmx1c2g6IDB4ZmZmMGY1LFxuICBsYXduZ3JlZW46IDB4N2NmYzAwLFxuICBsZW1vbmNoaWZmb246IDB4ZmZmYWNkLFxuICBsaWdodGJsdWU6IDB4YWRkOGU2LFxuICBsaWdodGNvcmFsOiAweGYwODA4MCxcbiAgbGlnaHRjeWFuOiAweGUwZmZmZixcbiAgbGlnaHRnb2xkZW5yb2R5ZWxsb3c6IDB4ZmFmYWQyLFxuICBsaWdodGdyYXk6IDB4ZDNkM2QzLFxuICBsaWdodGdyZWVuOiAweDkwZWU5MCxcbiAgbGlnaHRncmV5OiAweGQzZDNkMyxcbiAgbGlnaHRwaW5rOiAweGZmYjZjMSxcbiAgbGlnaHRzYWxtb246IDB4ZmZhMDdhLFxuICBsaWdodHNlYWdyZWVuOiAweDIwYjJhYSxcbiAgbGlnaHRza3libHVlOiAweDg3Y2VmYSxcbiAgbGlnaHRzbGF0ZWdyYXk6IDB4Nzc4ODk5LFxuICBsaWdodHNsYXRlZ3JleTogMHg3Nzg4OTksXG4gIGxpZ2h0c3RlZWxibHVlOiAweGIwYzRkZSxcbiAgbGlnaHR5ZWxsb3c6IDB4ZmZmZmUwLFxuICBsaW1lOiAweDAwZmYwMCxcbiAgbGltZWdyZWVuOiAweDMyY2QzMixcbiAgbGluZW46IDB4ZmFmMGU2LFxuICBtYWdlbnRhOiAweGZmMDBmZixcbiAgbWFyb29uOiAweDgwMDAwMCxcbiAgbWVkaXVtYXF1YW1hcmluZTogMHg2NmNkYWEsXG4gIG1lZGl1bWJsdWU6IDB4MDAwMGNkLFxuICBtZWRpdW1vcmNoaWQ6IDB4YmE1NWQzLFxuICBtZWRpdW1wdXJwbGU6IDB4OTM3MGRiLFxuICBtZWRpdW1zZWFncmVlbjogMHgzY2IzNzEsXG4gIG1lZGl1bXNsYXRlYmx1ZTogMHg3YjY4ZWUsXG4gIG1lZGl1bXNwcmluZ2dyZWVuOiAweDAwZmE5YSxcbiAgbWVkaXVtdHVycXVvaXNlOiAweDQ4ZDFjYyxcbiAgbWVkaXVtdmlvbGV0cmVkOiAweGM3MTU4NSxcbiAgbWlkbmlnaHRibHVlOiAweDE5MTk3MCxcbiAgbWludGNyZWFtOiAweGY1ZmZmYSxcbiAgbWlzdHlyb3NlOiAweGZmZTRlMSxcbiAgbW9jY2FzaW46IDB4ZmZlNGI1LFxuICBuYXZham93aGl0ZTogMHhmZmRlYWQsXG4gIG5hdnk6IDB4MDAwMDgwLFxuICBvbGRsYWNlOiAweGZkZjVlNixcbiAgb2xpdmU6IDB4ODA4MDAwLFxuICBvbGl2ZWRyYWI6IDB4NmI4ZTIzLFxuICBvcmFuZ2U6IDB4ZmZhNTAwLFxuICBvcmFuZ2VyZWQ6IDB4ZmY0NTAwLFxuICBvcmNoaWQ6IDB4ZGE3MGQ2LFxuICBwYWxlZ29sZGVucm9kOiAweGVlZThhYSxcbiAgcGFsZWdyZWVuOiAweDk4ZmI5OCxcbiAgcGFsZXR1cnF1b2lzZTogMHhhZmVlZWUsXG4gIHBhbGV2aW9sZXRyZWQ6IDB4ZGI3MDkzLFxuICBwYXBheWF3aGlwOiAweGZmZWZkNSxcbiAgcGVhY2hwdWZmOiAweGZmZGFiOSxcbiAgcGVydTogMHhjZDg1M2YsXG4gIHBpbms6IDB4ZmZjMGNiLFxuICBwbHVtOiAweGRkYTBkZCxcbiAgcG93ZGVyYmx1ZTogMHhiMGUwZTYsXG4gIHB1cnBsZTogMHg4MDAwODAsXG4gIHJlYmVjY2FwdXJwbGU6IDB4NjYzMzk5LFxuICByZWQ6IDB4ZmYwMDAwLFxuICByb3N5YnJvd246IDB4YmM4ZjhmLFxuICByb3lhbGJsdWU6IDB4NDE2OWUxLFxuICBzYWRkbGVicm93bjogMHg4YjQ1MTMsXG4gIHNhbG1vbjogMHhmYTgwNzIsXG4gIHNhbmR5YnJvd246IDB4ZjRhNDYwLFxuICBzZWFncmVlbjogMHgyZThiNTcsXG4gIHNlYXNoZWxsOiAweGZmZjVlZSxcbiAgc2llbm5hOiAweGEwNTIyZCxcbiAgc2lsdmVyOiAweGMwYzBjMCxcbiAgc2t5Ymx1ZTogMHg4N2NlZWIsXG4gIHNsYXRlYmx1ZTogMHg2YTVhY2QsXG4gIHNsYXRlZ3JheTogMHg3MDgwOTAsXG4gIHNsYXRlZ3JleTogMHg3MDgwOTAsXG4gIHNub3c6IDB4ZmZmYWZhLFxuICBzcHJpbmdncmVlbjogMHgwMGZmN2YsXG4gIHN0ZWVsYmx1ZTogMHg0NjgyYjQsXG4gIHRhbjogMHhkMmI0OGMsXG4gIHRlYWw6IDB4MDA4MDgwLFxuICB0aGlzdGxlOiAweGQ4YmZkOCxcbiAgdG9tYXRvOiAweGZmNjM0NyxcbiAgdHVycXVvaXNlOiAweDQwZTBkMCxcbiAgdmlvbGV0OiAweGVlODJlZSxcbiAgd2hlYXQ6IDB4ZjVkZWIzLFxuICB3aGl0ZTogMHhmZmZmZmYsXG4gIHdoaXRlc21va2U6IDB4ZjVmNWY1LFxuICB5ZWxsb3c6IDB4ZmZmZjAwLFxuICB5ZWxsb3dncmVlbjogMHg5YWNkMzJcbn07XG5cbmRlZmluZShDb2xvciwgY29sb3IsIHtcbiAgZGlzcGxheWFibGU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJnYigpLmRpc3BsYXlhYmxlKCk7XG4gIH0sXG4gIGhleDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucmdiKCkuaGV4KCk7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5yZ2IoKSArIFwiXCI7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBjb2xvcihmb3JtYXQpIHtcbiAgdmFyIG07XG4gIGZvcm1hdCA9IChmb3JtYXQgKyBcIlwiKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChtID0gcmVIZXgzLmV4ZWMoZm9ybWF0KSkgPyAobSA9IHBhcnNlSW50KG1bMV0sIDE2KSwgbmV3IFJnYigobSA+PiA4ICYgMHhmKSB8IChtID4+IDQgJiAweDBmMCksIChtID4+IDQgJiAweGYpIHwgKG0gJiAweGYwKSwgKChtICYgMHhmKSA8PCA0KSB8IChtICYgMHhmKSwgMSkpIC8vICNmMDBcbiAgICAgIDogKG0gPSByZUhleDYuZXhlYyhmb3JtYXQpKSA/IHJnYm4ocGFyc2VJbnQobVsxXSwgMTYpKSAvLyAjZmYwMDAwXG4gICAgICA6IChtID0gcmVSZ2JJbnRlZ2VyLmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0sIG1bMl0sIG1bM10sIDEpIC8vIHJnYigyNTUsIDAsIDApXG4gICAgICA6IChtID0gcmVSZ2JQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIDEpIC8vIHJnYigxMDAlLCAwJSwgMCUpXG4gICAgICA6IChtID0gcmVSZ2JhSW50ZWdlci5leGVjKGZvcm1hdCkpID8gcmdiYShtWzFdLCBtWzJdLCBtWzNdLCBtWzRdKSAvLyByZ2JhKDI1NSwgMCwgMCwgMSlcbiAgICAgIDogKG0gPSByZVJnYmFQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyByZ2JhKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIG1bNF0pIC8vIHJnYigxMDAlLCAwJSwgMCUsIDEpXG4gICAgICA6IChtID0gcmVIc2xQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBoc2xhKG1bMV0sIG1bMl0gLyAxMDAsIG1bM10gLyAxMDAsIDEpIC8vIGhzbCgxMjAsIDUwJSwgNTAlKVxuICAgICAgOiAobSA9IHJlSHNsYVBlcmNlbnQuZXhlYyhmb3JtYXQpKSA/IGhzbGEobVsxXSwgbVsyXSAvIDEwMCwgbVszXSAvIDEwMCwgbVs0XSkgLy8gaHNsYSgxMjAsIDUwJSwgNTAlLCAxKVxuICAgICAgOiBuYW1lZC5oYXNPd25Qcm9wZXJ0eShmb3JtYXQpID8gcmdibihuYW1lZFtmb3JtYXRdKVxuICAgICAgOiBmb3JtYXQgPT09IFwidHJhbnNwYXJlbnRcIiA/IG5ldyBSZ2IoTmFOLCBOYU4sIE5hTiwgMClcbiAgICAgIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcmdibihuKSB7XG4gIHJldHVybiBuZXcgUmdiKG4gPj4gMTYgJiAweGZmLCBuID4+IDggJiAweGZmLCBuICYgMHhmZiwgMSk7XG59XG5cbmZ1bmN0aW9uIHJnYmEociwgZywgYiwgYSkge1xuICBpZiAoYSA8PSAwKSByID0gZyA9IGIgPSBOYU47XG4gIHJldHVybiBuZXcgUmdiKHIsIGcsIGIsIGEpO1xufVxuXG5mdW5jdGlvbiByZ2JDb252ZXJ0KG8pIHtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIENvbG9yKSkgbyA9IGNvbG9yKG8pO1xuICBpZiAoIW8pIHJldHVybiBuZXcgUmdiO1xuICBvID0gby5yZ2IoKTtcbiAgcmV0dXJuIG5ldyBSZ2Ioby5yLCBvLmcsIG8uYiwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gcmdiKHIsIGcsIGIsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyByZ2JDb252ZXJ0KHIpIDogbmV3IFJnYihyLCBnLCBiLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIFJnYihyLCBnLCBiLCBvcGFjaXR5KSB7XG4gIHRoaXMuciA9ICtyO1xuICB0aGlzLmcgPSArZztcbiAgdGhpcy5iID0gK2I7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoUmdiLCByZ2IsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gayA9PSBudWxsID8gZGFya2VyIDogTWF0aC5wb3coZGFya2VyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBkaXNwbGF5YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgwIDw9IHRoaXMuciAmJiB0aGlzLnIgPD0gMjU1KVxuICAgICAgICAmJiAoMCA8PSB0aGlzLmcgJiYgdGhpcy5nIDw9IDI1NSlcbiAgICAgICAgJiYgKDAgPD0gdGhpcy5iICYmIHRoaXMuYiA8PSAyNTUpXG4gICAgICAgICYmICgwIDw9IHRoaXMub3BhY2l0eSAmJiB0aGlzLm9wYWNpdHkgPD0gMSk7XG4gIH0sXG4gIGhleDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFwiI1wiICsgaGV4KHRoaXMucikgKyBoZXgodGhpcy5nKSArIGhleCh0aGlzLmIpO1xuICB9LFxuICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGEgPSB0aGlzLm9wYWNpdHk7IGEgPSBpc05hTihhKSA/IDEgOiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBhKSk7XG4gICAgcmV0dXJuIChhID09PSAxID8gXCJyZ2IoXCIgOiBcInJnYmEoXCIpXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMucikgfHwgMCkpICsgXCIsIFwiXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMuZykgfHwgMCkpICsgXCIsIFwiXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMuYikgfHwgMCkpXG4gICAgICAgICsgKGEgPT09IDEgPyBcIilcIiA6IFwiLCBcIiArIGEgKyBcIilcIik7XG4gIH1cbn0pKTtcblxuZnVuY3Rpb24gaGV4KHZhbHVlKSB7XG4gIHZhbHVlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHZhbHVlKSB8fCAwKSk7XG4gIHJldHVybiAodmFsdWUgPCAxNiA/IFwiMFwiIDogXCJcIikgKyB2YWx1ZS50b1N0cmluZygxNik7XG59XG5cbmZ1bmN0aW9uIGhzbGEoaCwgcywgbCwgYSkge1xuICBpZiAoYSA8PSAwKSBoID0gcyA9IGwgPSBOYU47XG4gIGVsc2UgaWYgKGwgPD0gMCB8fCBsID49IDEpIGggPSBzID0gTmFOO1xuICBlbHNlIGlmIChzIDw9IDApIGggPSBOYU47XG4gIHJldHVybiBuZXcgSHNsKGgsIHMsIGwsIGEpO1xufVxuXG5mdW5jdGlvbiBoc2xDb252ZXJ0KG8pIHtcbiAgaWYgKG8gaW5zdGFuY2VvZiBIc2wpIHJldHVybiBuZXcgSHNsKG8uaCwgby5zLCBvLmwsIG8ub3BhY2l0eSk7XG4gIGlmICghKG8gaW5zdGFuY2VvZiBDb2xvcikpIG8gPSBjb2xvcihvKTtcbiAgaWYgKCFvKSByZXR1cm4gbmV3IEhzbDtcbiAgaWYgKG8gaW5zdGFuY2VvZiBIc2wpIHJldHVybiBvO1xuICBvID0gby5yZ2IoKTtcbiAgdmFyIHIgPSBvLnIgLyAyNTUsXG4gICAgICBnID0gby5nIC8gMjU1LFxuICAgICAgYiA9IG8uYiAvIDI1NSxcbiAgICAgIG1pbiA9IE1hdGgubWluKHIsIGcsIGIpLFxuICAgICAgbWF4ID0gTWF0aC5tYXgociwgZywgYiksXG4gICAgICBoID0gTmFOLFxuICAgICAgcyA9IG1heCAtIG1pbixcbiAgICAgIGwgPSAobWF4ICsgbWluKSAvIDI7XG4gIGlmIChzKSB7XG4gICAgaWYgKHIgPT09IG1heCkgaCA9IChnIC0gYikgLyBzICsgKGcgPCBiKSAqIDY7XG4gICAgZWxzZSBpZiAoZyA9PT0gbWF4KSBoID0gKGIgLSByKSAvIHMgKyAyO1xuICAgIGVsc2UgaCA9IChyIC0gZykgLyBzICsgNDtcbiAgICBzIC89IGwgPCAwLjUgPyBtYXggKyBtaW4gOiAyIC0gbWF4IC0gbWluO1xuICAgIGggKj0gNjA7XG4gIH0gZWxzZSB7XG4gICAgcyA9IGwgPiAwICYmIGwgPCAxID8gMCA6IGg7XG4gIH1cbiAgcmV0dXJuIG5ldyBIc2woaCwgcywgbCwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gaHNsKGgsIHMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBoc2xDb252ZXJ0KGgpIDogbmV3IEhzbChoLCBzLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEhzbChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLnMgPSArcztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoSHNsLCBoc2wsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IEhzbCh0aGlzLmgsIHRoaXMucywgdGhpcy5sICogaywgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgayA9IGsgPT0gbnVsbCA/IGRhcmtlciA6IE1hdGgucG93KGRhcmtlciwgayk7XG4gICAgcmV0dXJuIG5ldyBIc2wodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGggPSB0aGlzLmggJSAzNjAgKyAodGhpcy5oIDwgMCkgKiAzNjAsXG4gICAgICAgIHMgPSBpc05hTihoKSB8fCBpc05hTih0aGlzLnMpID8gMCA6IHRoaXMucyxcbiAgICAgICAgbCA9IHRoaXMubCxcbiAgICAgICAgbTIgPSBsICsgKGwgPCAwLjUgPyBsIDogMSAtIGwpICogcyxcbiAgICAgICAgbTEgPSAyICogbCAtIG0yO1xuICAgIHJldHVybiBuZXcgUmdiKFxuICAgICAgaHNsMnJnYihoID49IDI0MCA/IGggLSAyNDAgOiBoICsgMTIwLCBtMSwgbTIpLFxuICAgICAgaHNsMnJnYihoLCBtMSwgbTIpLFxuICAgICAgaHNsMnJnYihoIDwgMTIwID8gaCArIDI0MCA6IGggLSAxMjAsIG0xLCBtMiksXG4gICAgICB0aGlzLm9wYWNpdHlcbiAgICApO1xuICB9LFxuICBkaXNwbGF5YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgwIDw9IHRoaXMucyAmJiB0aGlzLnMgPD0gMSB8fCBpc05hTih0aGlzLnMpKVxuICAgICAgICAmJiAoMCA8PSB0aGlzLmwgJiYgdGhpcy5sIDw9IDEpXG4gICAgICAgICYmICgwIDw9IHRoaXMub3BhY2l0eSAmJiB0aGlzLm9wYWNpdHkgPD0gMSk7XG4gIH1cbn0pKTtcblxuLyogRnJvbSBGdkQgMTMuMzcsIENTUyBDb2xvciBNb2R1bGUgTGV2ZWwgMyAqL1xuZnVuY3Rpb24gaHNsMnJnYihoLCBtMSwgbTIpIHtcbiAgcmV0dXJuIChoIDwgNjAgPyBtMSArIChtMiAtIG0xKSAqIGggLyA2MFxuICAgICAgOiBoIDwgMTgwID8gbTJcbiAgICAgIDogaCA8IDI0MCA/IG0xICsgKG0yIC0gbTEpICogKDI0MCAtIGgpIC8gNjBcbiAgICAgIDogbTEpICogMjU1O1xufVxuXG52YXIgZGVnMnJhZCA9IE1hdGguUEkgLyAxODA7XG52YXIgcmFkMmRlZyA9IDE4MCAvIE1hdGguUEk7XG5cbi8vIGh0dHBzOi8vYmV0YS5vYnNlcnZhYmxlaHEuY29tL0BtYm9zdG9jay9sYWItYW5kLXJnYlxudmFyIEsgPSAxOCxcbiAgICBYbiA9IDAuOTY0MjIsXG4gICAgWW4gPSAxLFxuICAgIFpuID0gMC44MjUyMSxcbiAgICB0MCA9IDQgLyAyOSxcbiAgICB0MSA9IDYgLyAyOSxcbiAgICB0MiA9IDMgKiB0MSAqIHQxLFxuICAgIHQzID0gdDEgKiB0MSAqIHQxO1xuXG5mdW5jdGlvbiBsYWJDb252ZXJ0KG8pIHtcbiAgaWYgKG8gaW5zdGFuY2VvZiBMYWIpIHJldHVybiBuZXcgTGFiKG8ubCwgby5hLCBvLmIsIG8ub3BhY2l0eSk7XG4gIGlmIChvIGluc3RhbmNlb2YgSGNsKSB7XG4gICAgaWYgKGlzTmFOKG8uaCkpIHJldHVybiBuZXcgTGFiKG8ubCwgMCwgMCwgby5vcGFjaXR5KTtcbiAgICB2YXIgaCA9IG8uaCAqIGRlZzJyYWQ7XG4gICAgcmV0dXJuIG5ldyBMYWIoby5sLCBNYXRoLmNvcyhoKSAqIG8uYywgTWF0aC5zaW4oaCkgKiBvLmMsIG8ub3BhY2l0eSk7XG4gIH1cbiAgaWYgKCEobyBpbnN0YW5jZW9mIFJnYikpIG8gPSByZ2JDb252ZXJ0KG8pO1xuICB2YXIgciA9IHJnYjJscmdiKG8uciksXG4gICAgICBnID0gcmdiMmxyZ2Ioby5nKSxcbiAgICAgIGIgPSByZ2IybHJnYihvLmIpLFxuICAgICAgeSA9IHh5ejJsYWIoKDAuMjIyNTA0NSAqIHIgKyAwLjcxNjg3ODYgKiBnICsgMC4wNjA2MTY5ICogYikgLyBZbiksIHgsIHo7XG4gIGlmIChyID09PSBnICYmIGcgPT09IGIpIHggPSB6ID0geTsgZWxzZSB7XG4gICAgeCA9IHh5ejJsYWIoKDAuNDM2MDc0NyAqIHIgKyAwLjM4NTA2NDkgKiBnICsgMC4xNDMwODA0ICogYikgLyBYbik7XG4gICAgeiA9IHh5ejJsYWIoKDAuMDEzOTMyMiAqIHIgKyAwLjA5NzEwNDUgKiBnICsgMC43MTQxNzMzICogYikgLyBabik7XG4gIH1cbiAgcmV0dXJuIG5ldyBMYWIoMTE2ICogeSAtIDE2LCA1MDAgKiAoeCAtIHkpLCAyMDAgKiAoeSAtIHopLCBvLm9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBncmF5KGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIG5ldyBMYWIobCwgMCwgMCwgb3BhY2l0eSA9PSBudWxsID8gMSA6IG9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBsYWIobCwgYSwgYiwgb3BhY2l0eSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGxhYkNvbnZlcnQobCkgOiBuZXcgTGFiKGwsIGEsIGIsIG9wYWNpdHkgPT0gbnVsbCA/IDEgOiBvcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gTGFiKGwsIGEsIGIsIG9wYWNpdHkpIHtcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMuYSA9ICthO1xuICB0aGlzLmIgPSArYjtcbiAgdGhpcy5vcGFjaXR5ID0gK29wYWNpdHk7XG59XG5cbmRlZmluZShMYWIsIGxhYiwgZXh0ZW5kKENvbG9yLCB7XG4gIGJyaWdodGVyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBMYWIodGhpcy5sICsgSyAqIChrID09IG51bGwgPyAxIDogayksIHRoaXMuYSwgdGhpcy5iLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IExhYih0aGlzLmwgLSBLICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5hLCB0aGlzLmIsIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHkgPSAodGhpcy5sICsgMTYpIC8gMTE2LFxuICAgICAgICB4ID0gaXNOYU4odGhpcy5hKSA/IHkgOiB5ICsgdGhpcy5hIC8gNTAwLFxuICAgICAgICB6ID0gaXNOYU4odGhpcy5iKSA/IHkgOiB5IC0gdGhpcy5iIC8gMjAwO1xuICAgIHggPSBYbiAqIGxhYjJ4eXooeCk7XG4gICAgeSA9IFluICogbGFiMnh5eih5KTtcbiAgICB6ID0gWm4gKiBsYWIyeHl6KHopO1xuICAgIHJldHVybiBuZXcgUmdiKFxuICAgICAgbHJnYjJyZ2IoIDMuMTMzODU2MSAqIHggLSAxLjYxNjg2NjcgKiB5IC0gMC40OTA2MTQ2ICogeiksXG4gICAgICBscmdiMnJnYigtMC45Nzg3Njg0ICogeCArIDEuOTE2MTQxNSAqIHkgKyAwLjAzMzQ1NDAgKiB6KSxcbiAgICAgIGxyZ2IycmdiKCAwLjA3MTk0NTMgKiB4IC0gMC4yMjg5OTE0ICogeSArIDEuNDA1MjQyNyAqIHopLFxuICAgICAgdGhpcy5vcGFjaXR5XG4gICAgKTtcbiAgfVxufSkpO1xuXG5mdW5jdGlvbiB4eXoybGFiKHQpIHtcbiAgcmV0dXJuIHQgPiB0MyA/IE1hdGgucG93KHQsIDEgLyAzKSA6IHQgLyB0MiArIHQwO1xufVxuXG5mdW5jdGlvbiBsYWIyeHl6KHQpIHtcbiAgcmV0dXJuIHQgPiB0MSA/IHQgKiB0ICogdCA6IHQyICogKHQgLSB0MCk7XG59XG5cbmZ1bmN0aW9uIGxyZ2IycmdiKHgpIHtcbiAgcmV0dXJuIDI1NSAqICh4IDw9IDAuMDAzMTMwOCA/IDEyLjkyICogeCA6IDEuMDU1ICogTWF0aC5wb3coeCwgMSAvIDIuNCkgLSAwLjA1NSk7XG59XG5cbmZ1bmN0aW9uIHJnYjJscmdiKHgpIHtcbiAgcmV0dXJuICh4IC89IDI1NSkgPD0gMC4wNDA0NSA/IHggLyAxMi45MiA6IE1hdGgucG93KCh4ICsgMC4wNTUpIC8gMS4wNTUsIDIuNCk7XG59XG5cbmZ1bmN0aW9uIGhjbENvbnZlcnQobykge1xuICBpZiAobyBpbnN0YW5jZW9mIEhjbCkgcmV0dXJuIG5ldyBIY2woby5oLCBvLmMsIG8ubCwgby5vcGFjaXR5KTtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIExhYikpIG8gPSBsYWJDb252ZXJ0KG8pO1xuICBpZiAoby5hID09PSAwICYmIG8uYiA9PT0gMCkgcmV0dXJuIG5ldyBIY2woTmFOLCAwLCBvLmwsIG8ub3BhY2l0eSk7XG4gIHZhciBoID0gTWF0aC5hdGFuMihvLmIsIG8uYSkgKiByYWQyZGVnO1xuICByZXR1cm4gbmV3IEhjbChoIDwgMCA/IGggKyAzNjAgOiBoLCBNYXRoLnNxcnQoby5hICogby5hICsgby5iICogby5iKSwgby5sLCBvLm9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBsY2gobCwgYywgaCwgb3BhY2l0eSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGhjbENvbnZlcnQobCkgOiBuZXcgSGNsKGgsIGMsIGwsIG9wYWNpdHkgPT0gbnVsbCA/IDEgOiBvcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gaGNsKGgsIGMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBoY2xDb252ZXJ0KGgpIDogbmV3IEhjbChoLCBjLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEhjbChoLCBjLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLmMgPSArYztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoSGNsLCBoY2wsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIHJldHVybiBuZXcgSGNsKHRoaXMuaCwgdGhpcy5jLCB0aGlzLmwgKyBLICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBIY2wodGhpcy5oLCB0aGlzLmMsIHRoaXMubCAtIEsgKiAoayA9PSBudWxsID8gMSA6IGspLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBsYWJDb252ZXJ0KHRoaXMpLnJnYigpO1xuICB9XG59KSk7XG5cbnZhciBBID0gLTAuMTQ4NjEsXG4gICAgQiA9ICsxLjc4Mjc3LFxuICAgIEMgPSAtMC4yOTIyNyxcbiAgICBEID0gLTAuOTA2NDksXG4gICAgRSA9ICsxLjk3Mjk0LFxuICAgIEVEID0gRSAqIEQsXG4gICAgRUIgPSBFICogQixcbiAgICBCQ19EQSA9IEIgKiBDIC0gRCAqIEE7XG5cbmZ1bmN0aW9uIGN1YmVoZWxpeENvbnZlcnQobykge1xuICBpZiAobyBpbnN0YW5jZW9mIEN1YmVoZWxpeCkgcmV0dXJuIG5ldyBDdWJlaGVsaXgoby5oLCBvLnMsIG8ubCwgby5vcGFjaXR5KTtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIFJnYikpIG8gPSByZ2JDb252ZXJ0KG8pO1xuICB2YXIgciA9IG8uciAvIDI1NSxcbiAgICAgIGcgPSBvLmcgLyAyNTUsXG4gICAgICBiID0gby5iIC8gMjU1LFxuICAgICAgbCA9IChCQ19EQSAqIGIgKyBFRCAqIHIgLSBFQiAqIGcpIC8gKEJDX0RBICsgRUQgLSBFQiksXG4gICAgICBibCA9IGIgLSBsLFxuICAgICAgayA9IChFICogKGcgLSBsKSAtIEMgKiBibCkgLyBELFxuICAgICAgcyA9IE1hdGguc3FydChrICogayArIGJsICogYmwpIC8gKEUgKiBsICogKDEgLSBsKSksIC8vIE5hTiBpZiBsPTAgb3IgbD0xXG4gICAgICBoID0gcyA/IE1hdGguYXRhbjIoaywgYmwpICogcmFkMmRlZyAtIDEyMCA6IE5hTjtcbiAgcmV0dXJuIG5ldyBDdWJlaGVsaXgoaCA8IDAgPyBoICsgMzYwIDogaCwgcywgbCwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gY3ViZWhlbGl4KGgsIHMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBjdWJlaGVsaXhDb252ZXJ0KGgpIDogbmV3IEN1YmVoZWxpeChoLCBzLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEN1YmVoZWxpeChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLnMgPSArcztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoQ3ViZWhlbGl4LCBjdWJlaGVsaXgsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IEN1YmVoZWxpeCh0aGlzLmgsIHRoaXMucywgdGhpcy5sICogaywgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgayA9IGsgPT0gbnVsbCA/IGRhcmtlciA6IE1hdGgucG93KGRhcmtlciwgayk7XG4gICAgcmV0dXJuIG5ldyBDdWJlaGVsaXgodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGggPSBpc05hTih0aGlzLmgpID8gMCA6ICh0aGlzLmggKyAxMjApICogZGVnMnJhZCxcbiAgICAgICAgbCA9ICt0aGlzLmwsXG4gICAgICAgIGEgPSBpc05hTih0aGlzLnMpID8gMCA6IHRoaXMucyAqIGwgKiAoMSAtIGwpLFxuICAgICAgICBjb3NoID0gTWF0aC5jb3MoaCksXG4gICAgICAgIHNpbmggPSBNYXRoLnNpbihoKTtcbiAgICByZXR1cm4gbmV3IFJnYihcbiAgICAgIDI1NSAqIChsICsgYSAqIChBICogY29zaCArIEIgKiBzaW5oKSksXG4gICAgICAyNTUgKiAobCArIGEgKiAoQyAqIGNvc2ggKyBEICogc2luaCkpLFxuICAgICAgMjU1ICogKGwgKyBhICogKEUgKiBjb3NoKSksXG4gICAgICB0aGlzLm9wYWNpdHlcbiAgICApO1xuICB9XG59KSk7XG5cbmV4cG9ydHMuY29sb3IgPSBjb2xvcjtcbmV4cG9ydHMucmdiID0gcmdiO1xuZXhwb3J0cy5oc2wgPSBoc2w7XG5leHBvcnRzLmxhYiA9IGxhYjtcbmV4cG9ydHMuaGNsID0gaGNsO1xuZXhwb3J0cy5sY2ggPSBsY2g7XG5leHBvcnRzLmdyYXkgPSBncmF5O1xuZXhwb3J0cy5jdWJlaGVsaXggPSBjdWJlaGVsaXg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWRpc3BhdGNoLyBWZXJzaW9uIDEuMC4zLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBub29wID0ge3ZhbHVlOiBmdW5jdGlvbigpIHt9fTtcblxuZnVuY3Rpb24gZGlzcGF0Y2goKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gYXJndW1lbnRzLmxlbmd0aCwgXyA9IHt9LCB0OyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKCEodCA9IGFyZ3VtZW50c1tpXSArIFwiXCIpIHx8ICh0IGluIF8pKSB0aHJvdyBuZXcgRXJyb3IoXCJpbGxlZ2FsIHR5cGU6IFwiICsgdCk7XG4gICAgX1t0XSA9IFtdO1xuICB9XG4gIHJldHVybiBuZXcgRGlzcGF0Y2goXyk7XG59XG5cbmZ1bmN0aW9uIERpc3BhdGNoKF8pIHtcbiAgdGhpcy5fID0gXztcbn1cblxuZnVuY3Rpb24gcGFyc2VUeXBlbmFtZXModHlwZW5hbWVzLCB0eXBlcykge1xuICByZXR1cm4gdHlwZW5hbWVzLnRyaW0oKS5zcGxpdCgvXnxcXHMrLykubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICB2YXIgbmFtZSA9IFwiXCIsIGkgPSB0LmluZGV4T2YoXCIuXCIpO1xuICAgIGlmIChpID49IDApIG5hbWUgPSB0LnNsaWNlKGkgKyAxKSwgdCA9IHQuc2xpY2UoMCwgaSk7XG4gICAgaWYgKHQgJiYgIXR5cGVzLmhhc093blByb3BlcnR5KHQpKSB0aHJvdyBuZXcgRXJyb3IoXCJ1bmtub3duIHR5cGU6IFwiICsgdCk7XG4gICAgcmV0dXJuIHt0eXBlOiB0LCBuYW1lOiBuYW1lfTtcbiAgfSk7XG59XG5cbkRpc3BhdGNoLnByb3RvdHlwZSA9IGRpc3BhdGNoLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IERpc3BhdGNoLFxuICBvbjogZnVuY3Rpb24odHlwZW5hbWUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIF8gPSB0aGlzLl8sXG4gICAgICAgIFQgPSBwYXJzZVR5cGVuYW1lcyh0eXBlbmFtZSArIFwiXCIsIF8pLFxuICAgICAgICB0LFxuICAgICAgICBpID0gLTEsXG4gICAgICAgIG4gPSBULmxlbmd0aDtcblxuICAgIC8vIElmIG5vIGNhbGxiYWNrIHdhcyBzcGVjaWZpZWQsIHJldHVybiB0aGUgY2FsbGJhY2sgb2YgdGhlIGdpdmVuIHR5cGUgYW5kIG5hbWUuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCh0ID0gKHR5cGVuYW1lID0gVFtpXSkudHlwZSkgJiYgKHQgPSBnZXQoX1t0XSwgdHlwZW5hbWUubmFtZSkpKSByZXR1cm4gdDtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJZiBhIHR5cGUgd2FzIHNwZWNpZmllZCwgc2V0IHRoZSBjYWxsYmFjayBmb3IgdGhlIGdpdmVuIHR5cGUgYW5kIG5hbWUuXG4gICAgLy8gT3RoZXJ3aXNlLCBpZiBhIG51bGwgY2FsbGJhY2sgd2FzIHNwZWNpZmllZCwgcmVtb3ZlIGNhbGxiYWNrcyBvZiB0aGUgZ2l2ZW4gbmFtZS5cbiAgICBpZiAoY2FsbGJhY2sgIT0gbnVsbCAmJiB0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBjYWxsYmFjazogXCIgKyBjYWxsYmFjayk7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh0ID0gKHR5cGVuYW1lID0gVFtpXSkudHlwZSkgX1t0XSA9IHNldChfW3RdLCB0eXBlbmFtZS5uYW1lLCBjYWxsYmFjayk7XG4gICAgICBlbHNlIGlmIChjYWxsYmFjayA9PSBudWxsKSBmb3IgKHQgaW4gXykgX1t0XSA9IHNldChfW3RdLCB0eXBlbmFtZS5uYW1lLCBudWxsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgY29weTogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvcHkgPSB7fSwgXyA9IHRoaXMuXztcbiAgICBmb3IgKHZhciB0IGluIF8pIGNvcHlbdF0gPSBfW3RdLnNsaWNlKCk7XG4gICAgcmV0dXJuIG5ldyBEaXNwYXRjaChjb3B5KTtcbiAgfSxcbiAgY2FsbDogZnVuY3Rpb24odHlwZSwgdGhhdCkge1xuICAgIGlmICgobiA9IGFyZ3VtZW50cy5sZW5ndGggLSAyKSA+IDApIGZvciAodmFyIGFyZ3MgPSBuZXcgQXJyYXkobiksIGkgPSAwLCBuLCB0OyBpIDwgbjsgKytpKSBhcmdzW2ldID0gYXJndW1lbnRzW2kgKyAyXTtcbiAgICBpZiAoIXRoaXMuXy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biB0eXBlOiBcIiArIHR5cGUpO1xuICAgIGZvciAodCA9IHRoaXMuX1t0eXBlXSwgaSA9IDAsIG4gPSB0Lmxlbmd0aDsgaSA8IG47ICsraSkgdFtpXS52YWx1ZS5hcHBseSh0aGF0LCBhcmdzKTtcbiAgfSxcbiAgYXBwbHk6IGZ1bmN0aW9uKHR5cGUsIHRoYXQsIGFyZ3MpIHtcbiAgICBpZiAoIXRoaXMuXy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biB0eXBlOiBcIiArIHR5cGUpO1xuICAgIGZvciAodmFyIHQgPSB0aGlzLl9bdHlwZV0sIGkgPSAwLCBuID0gdC5sZW5ndGg7IGkgPCBuOyArK2kpIHRbaV0udmFsdWUuYXBwbHkodGhhdCwgYXJncyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGdldCh0eXBlLCBuYW1lKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gdHlwZS5sZW5ndGgsIGM7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAoKGMgPSB0eXBlW2ldKS5uYW1lID09PSBuYW1lKSB7XG4gICAgICByZXR1cm4gYy52YWx1ZTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc2V0KHR5cGUsIG5hbWUsIGNhbGxiYWNrKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gdHlwZS5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAodHlwZVtpXS5uYW1lID09PSBuYW1lKSB7XG4gICAgICB0eXBlW2ldID0gbm9vcCwgdHlwZSA9IHR5cGUuc2xpY2UoMCwgaSkuY29uY2F0KHR5cGUuc2xpY2UoaSArIDEpKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAoY2FsbGJhY2sgIT0gbnVsbCkgdHlwZS5wdXNoKHtuYW1lOiBuYW1lLCB2YWx1ZTogY2FsbGJhY2t9KTtcbiAgcmV0dXJuIHR5cGU7XG59XG5cbmV4cG9ydHMuZGlzcGF0Y2ggPSBkaXNwYXRjaDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtZm9yY2UvIFZlcnNpb24gMS4xLjAuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtcXVhZHRyZWUnKSwgcmVxdWlyZSgnZDMtY29sbGVjdGlvbicpLCByZXF1aXJlKCdkMy1kaXNwYXRjaCcpLCByZXF1aXJlKCdkMy10aW1lcicpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtcXVhZHRyZWUnLCAnZDMtY29sbGVjdGlvbicsICdkMy1kaXNwYXRjaCcsICdkMy10aW1lciddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMykpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMsZDNRdWFkdHJlZSxkM0NvbGxlY3Rpb24sZDNEaXNwYXRjaCxkM1RpbWVyKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGNlbnRlciA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgdmFyIG5vZGVzO1xuXG4gIGlmICh4ID09IG51bGwpIHggPSAwO1xuICBpZiAoeSA9PSBudWxsKSB5ID0gMDtcblxuICBmdW5jdGlvbiBmb3JjZSgpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgbm9kZSxcbiAgICAgICAgc3ggPSAwLFxuICAgICAgICBzeSA9IDA7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIHN4ICs9IG5vZGUueCwgc3kgKz0gbm9kZS55O1xuICAgIH1cblxuICAgIGZvciAoc3ggPSBzeCAvIG4gLSB4LCBzeSA9IHN5IC8gbiAtIHksIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUueCAtPSBzeCwgbm9kZS55IC09IHN5O1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9ICtfLCBmb3JjZSkgOiB4O1xuICB9O1xuXG4gIGZvcmNlLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9ICtfLCBmb3JjZSkgOiB5O1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxudmFyIGppZ2dsZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gKE1hdGgucmFuZG9tKCkgLSAwLjUpICogMWUtNjtcbn07XG5cbmZ1bmN0aW9uIHgoZCkge1xuICByZXR1cm4gZC54ICsgZC52eDtcbn1cblxuZnVuY3Rpb24geShkKSB7XG4gIHJldHVybiBkLnkgKyBkLnZ5O1xufVxuXG52YXIgY29sbGlkZSA9IGZ1bmN0aW9uKHJhZGl1cykge1xuICB2YXIgbm9kZXMsXG4gICAgICByYWRpaSxcbiAgICAgIHN0cmVuZ3RoID0gMSxcbiAgICAgIGl0ZXJhdGlvbnMgPSAxO1xuXG4gIGlmICh0eXBlb2YgcmFkaXVzICE9PSBcImZ1bmN0aW9uXCIpIHJhZGl1cyA9IGNvbnN0YW50KHJhZGl1cyA9PSBudWxsID8gMSA6ICtyYWRpdXMpO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKCkge1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgICB0cmVlLFxuICAgICAgICBub2RlLFxuICAgICAgICB4aSxcbiAgICAgICAgeWksXG4gICAgICAgIHJpLFxuICAgICAgICByaTI7XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGl0ZXJhdGlvbnM7ICsraykge1xuICAgICAgdHJlZSA9IGQzUXVhZHRyZWUucXVhZHRyZWUobm9kZXMsIHgsIHkpLnZpc2l0QWZ0ZXIocHJlcGFyZSk7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgcmkgPSByYWRpaVtub2RlLmluZGV4XSwgcmkyID0gcmkgKiByaTtcbiAgICAgICAgeGkgPSBub2RlLnggKyBub2RlLnZ4O1xuICAgICAgICB5aSA9IG5vZGUueSArIG5vZGUudnk7XG4gICAgICAgIHRyZWUudmlzaXQoYXBwbHkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGx5KHF1YWQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgICB2YXIgZGF0YSA9IHF1YWQuZGF0YSwgcmogPSBxdWFkLnIsIHIgPSByaSArIHJqO1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgaWYgKGRhdGEuaW5kZXggPiBub2RlLmluZGV4KSB7XG4gICAgICAgICAgdmFyIHggPSB4aSAtIGRhdGEueCAtIGRhdGEudngsXG4gICAgICAgICAgICAgIHkgPSB5aSAtIGRhdGEueSAtIGRhdGEudnksXG4gICAgICAgICAgICAgIGwgPSB4ICogeCArIHkgKiB5O1xuICAgICAgICAgIGlmIChsIDwgciAqIHIpIHtcbiAgICAgICAgICAgIGlmICh4ID09PSAwKSB4ID0gamlnZ2xlKCksIGwgKz0geCAqIHg7XG4gICAgICAgICAgICBpZiAoeSA9PT0gMCkgeSA9IGppZ2dsZSgpLCBsICs9IHkgKiB5O1xuICAgICAgICAgICAgbCA9IChyIC0gKGwgPSBNYXRoLnNxcnQobCkpKSAvIGwgKiBzdHJlbmd0aDtcbiAgICAgICAgICAgIG5vZGUudnggKz0gKHggKj0gbCkgKiAociA9IChyaiAqPSByaikgLyAocmkyICsgcmopKTtcbiAgICAgICAgICAgIG5vZGUudnkgKz0gKHkgKj0gbCkgKiByO1xuICAgICAgICAgICAgZGF0YS52eCAtPSB4ICogKHIgPSAxIC0gcik7XG4gICAgICAgICAgICBkYXRhLnZ5IC09IHkgKiByO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXR1cm4geDAgPiB4aSArIHIgfHwgeDEgPCB4aSAtIHIgfHwgeTAgPiB5aSArIHIgfHwgeTEgPCB5aSAtIHI7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcHJlcGFyZShxdWFkKSB7XG4gICAgaWYgKHF1YWQuZGF0YSkgcmV0dXJuIHF1YWQuciA9IHJhZGlpW3F1YWQuZGF0YS5pbmRleF07XG4gICAgZm9yICh2YXIgaSA9IHF1YWQuciA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgIGlmIChxdWFkW2ldICYmIHF1YWRbaV0uciA+IHF1YWQucikge1xuICAgICAgICBxdWFkLnIgPSBxdWFkW2ldLnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7XG4gICAgcmFkaWkgPSBuZXcgQXJyYXkobik7XG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkgbm9kZSA9IG5vZGVzW2ldLCByYWRpaVtub2RlLmluZGV4XSA9ICtyYWRpdXMobm9kZSwgaSwgbm9kZXMpO1xuICB9XG5cbiAgZm9yY2UuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBub2RlcyA9IF87XG4gICAgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLml0ZXJhdGlvbnMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaXRlcmF0aW9ucyA9ICtfLCBmb3JjZSkgOiBpdGVyYXRpb25zO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gK18sIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiByYWRpdXM7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxuZnVuY3Rpb24gaW5kZXgoZCkge1xuICByZXR1cm4gZC5pbmRleDtcbn1cblxuZnVuY3Rpb24gZmluZChub2RlQnlJZCwgbm9kZUlkKSB7XG4gIHZhciBub2RlID0gbm9kZUJ5SWQuZ2V0KG5vZGVJZCk7XG4gIGlmICghbm9kZSkgdGhyb3cgbmV3IEVycm9yKFwibWlzc2luZzogXCIgKyBub2RlSWQpO1xuICByZXR1cm4gbm9kZTtcbn1cblxudmFyIGxpbmsgPSBmdW5jdGlvbihsaW5rcykge1xuICB2YXIgaWQgPSBpbmRleCxcbiAgICAgIHN0cmVuZ3RoID0gZGVmYXVsdFN0cmVuZ3RoLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgZGlzdGFuY2UgPSBjb25zdGFudCgzMCksXG4gICAgICBkaXN0YW5jZXMsXG4gICAgICBub2RlcyxcbiAgICAgIGNvdW50LFxuICAgICAgYmlhcyxcbiAgICAgIGl0ZXJhdGlvbnMgPSAxO1xuXG4gIGlmIChsaW5rcyA9PSBudWxsKSBsaW5rcyA9IFtdO1xuXG4gIGZ1bmN0aW9uIGRlZmF1bHRTdHJlbmd0aChsaW5rKSB7XG4gICAgcmV0dXJuIDEgLyBNYXRoLm1pbihjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0sIGNvdW50W2xpbmsudGFyZ2V0LmluZGV4XSk7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGsgPSAwLCBuID0gbGlua3MubGVuZ3RoOyBrIDwgaXRlcmF0aW9uczsgKytrKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGluaywgc291cmNlLCB0YXJnZXQsIHgsIHksIGwsIGI7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgbGluayA9IGxpbmtzW2ldLCBzb3VyY2UgPSBsaW5rLnNvdXJjZSwgdGFyZ2V0ID0gbGluay50YXJnZXQ7XG4gICAgICAgIHggPSB0YXJnZXQueCArIHRhcmdldC52eCAtIHNvdXJjZS54IC0gc291cmNlLnZ4IHx8IGppZ2dsZSgpO1xuICAgICAgICB5ID0gdGFyZ2V0LnkgKyB0YXJnZXQudnkgLSBzb3VyY2UueSAtIHNvdXJjZS52eSB8fCBqaWdnbGUoKTtcbiAgICAgICAgbCA9IE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcbiAgICAgICAgbCA9IChsIC0gZGlzdGFuY2VzW2ldKSAvIGwgKiBhbHBoYSAqIHN0cmVuZ3Roc1tpXTtcbiAgICAgICAgeCAqPSBsLCB5ICo9IGw7XG4gICAgICAgIHRhcmdldC52eCAtPSB4ICogKGIgPSBiaWFzW2ldKTtcbiAgICAgICAgdGFyZ2V0LnZ5IC09IHkgKiBiO1xuICAgICAgICBzb3VyY2UudnggKz0geCAqIChiID0gMSAtIGIpO1xuICAgICAgICBzb3VyY2UudnkgKz0geSAqIGI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG5cbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgbSA9IGxpbmtzLmxlbmd0aCxcbiAgICAgICAgbm9kZUJ5SWQgPSBkM0NvbGxlY3Rpb24ubWFwKG5vZGVzLCBpZCksXG4gICAgICAgIGxpbms7XG5cbiAgICBmb3IgKGkgPSAwLCBjb3VudCA9IG5ldyBBcnJheShuKTsgaSA8IG07ICsraSkge1xuICAgICAgbGluayA9IGxpbmtzW2ldLCBsaW5rLmluZGV4ID0gaTtcbiAgICAgIGlmICh0eXBlb2YgbGluay5zb3VyY2UgIT09IFwib2JqZWN0XCIpIGxpbmsuc291cmNlID0gZmluZChub2RlQnlJZCwgbGluay5zb3VyY2UpO1xuICAgICAgaWYgKHR5cGVvZiBsaW5rLnRhcmdldCAhPT0gXCJvYmplY3RcIikgbGluay50YXJnZXQgPSBmaW5kKG5vZGVCeUlkLCBsaW5rLnRhcmdldCk7XG4gICAgICBjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0gPSAoY291bnRbbGluay5zb3VyY2UuaW5kZXhdIHx8IDApICsgMTtcbiAgICAgIGNvdW50W2xpbmsudGFyZ2V0LmluZGV4XSA9IChjb3VudFtsaW5rLnRhcmdldC5pbmRleF0gfHwgMCkgKyAxO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDAsIGJpYXMgPSBuZXcgQXJyYXkobSk7IGkgPCBtOyArK2kpIHtcbiAgICAgIGxpbmsgPSBsaW5rc1tpXSwgYmlhc1tpXSA9IGNvdW50W2xpbmsuc291cmNlLmluZGV4XSAvIChjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0gKyBjb3VudFtsaW5rLnRhcmdldC5pbmRleF0pO1xuICAgIH1cblxuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShtKSwgaW5pdGlhbGl6ZVN0cmVuZ3RoKCk7XG4gICAgZGlzdGFuY2VzID0gbmV3IEFycmF5KG0pLCBpbml0aWFsaXplRGlzdGFuY2UoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemVTdHJlbmd0aCgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IGxpbmtzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgc3RyZW5ndGhzW2ldID0gK3N0cmVuZ3RoKGxpbmtzW2ldLCBpLCBsaW5rcyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZURpc3RhbmNlKCkge1xuICAgIGlmICghbm9kZXMpIHJldHVybjtcblxuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbGlua3MubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICBkaXN0YW5jZXNbaV0gPSArZGlzdGFuY2UobGlua3NbaV0sIGksIGxpbmtzKTtcbiAgICB9XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXztcbiAgICBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2UubGlua3MgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGlua3MgPSBfLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IGxpbmtzO1xuICB9O1xuXG4gIGZvcmNlLmlkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGlkID0gXywgZm9yY2UpIDogaWQ7XG4gIH07XG5cbiAgZm9yY2UuaXRlcmF0aW9ucyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpdGVyYXRpb25zID0gK18sIGZvcmNlKSA6IGl0ZXJhdGlvbnM7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZVN0cmVuZ3RoKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLmRpc3RhbmNlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRpc3RhbmNlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemVEaXN0YW5jZSgpLCBmb3JjZSkgOiBkaXN0YW5jZTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG5mdW5jdGlvbiB4JDEoZCkge1xuICByZXR1cm4gZC54O1xufVxuXG5mdW5jdGlvbiB5JDEoZCkge1xuICByZXR1cm4gZC55O1xufVxuXG52YXIgaW5pdGlhbFJhZGl1cyA9IDEwO1xudmFyIGluaXRpYWxBbmdsZSA9IE1hdGguUEkgKiAoMyAtIE1hdGguc3FydCg1KSk7XG5cbnZhciBzaW11bGF0aW9uID0gZnVuY3Rpb24obm9kZXMpIHtcbiAgdmFyIHNpbXVsYXRpb24sXG4gICAgICBhbHBoYSA9IDEsXG4gICAgICBhbHBoYU1pbiA9IDAuMDAxLFxuICAgICAgYWxwaGFEZWNheSA9IDEgLSBNYXRoLnBvdyhhbHBoYU1pbiwgMSAvIDMwMCksXG4gICAgICBhbHBoYVRhcmdldCA9IDAsXG4gICAgICB2ZWxvY2l0eURlY2F5ID0gMC42LFxuICAgICAgZm9yY2VzID0gZDNDb2xsZWN0aW9uLm1hcCgpLFxuICAgICAgc3RlcHBlciA9IGQzVGltZXIudGltZXIoc3RlcCksXG4gICAgICBldmVudCA9IGQzRGlzcGF0Y2guZGlzcGF0Y2goXCJ0aWNrXCIsIFwiZW5kXCIpO1xuXG4gIGlmIChub2RlcyA9PSBudWxsKSBub2RlcyA9IFtdO1xuXG4gIGZ1bmN0aW9uIHN0ZXAoKSB7XG4gICAgdGljaygpO1xuICAgIGV2ZW50LmNhbGwoXCJ0aWNrXCIsIHNpbXVsYXRpb24pO1xuICAgIGlmIChhbHBoYSA8IGFscGhhTWluKSB7XG4gICAgICBzdGVwcGVyLnN0b3AoKTtcbiAgICAgIGV2ZW50LmNhbGwoXCJlbmRcIiwgc2ltdWxhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdGljaygpIHtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCwgbm9kZTtcblxuICAgIGFscGhhICs9IChhbHBoYVRhcmdldCAtIGFscGhhKSAqIGFscGhhRGVjYXk7XG5cbiAgICBmb3JjZXMuZWFjaChmdW5jdGlvbihmb3JjZSkge1xuICAgICAgZm9yY2UoYWxwaGEpO1xuICAgIH0pO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgaWYgKG5vZGUuZnggPT0gbnVsbCkgbm9kZS54ICs9IG5vZGUudnggKj0gdmVsb2NpdHlEZWNheTtcbiAgICAgIGVsc2Ugbm9kZS54ID0gbm9kZS5meCwgbm9kZS52eCA9IDA7XG4gICAgICBpZiAobm9kZS5meSA9PSBudWxsKSBub2RlLnkgKz0gbm9kZS52eSAqPSB2ZWxvY2l0eURlY2F5O1xuICAgICAgZWxzZSBub2RlLnkgPSBub2RlLmZ5LCBub2RlLnZ5ID0gMDtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplTm9kZXMoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXSwgbm9kZS5pbmRleCA9IGk7XG4gICAgICBpZiAoaXNOYU4obm9kZS54KSB8fCBpc05hTihub2RlLnkpKSB7XG4gICAgICAgIHZhciByYWRpdXMgPSBpbml0aWFsUmFkaXVzICogTWF0aC5zcXJ0KGkpLCBhbmdsZSA9IGkgKiBpbml0aWFsQW5nbGU7XG4gICAgICAgIG5vZGUueCA9IHJhZGl1cyAqIE1hdGguY29zKGFuZ2xlKTtcbiAgICAgICAgbm9kZS55ID0gcmFkaXVzICogTWF0aC5zaW4oYW5nbGUpO1xuICAgICAgfVxuICAgICAgaWYgKGlzTmFOKG5vZGUudngpIHx8IGlzTmFOKG5vZGUudnkpKSB7XG4gICAgICAgIG5vZGUudnggPSBub2RlLnZ5ID0gMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplRm9yY2UoZm9yY2UpIHtcbiAgICBpZiAoZm9yY2UuaW5pdGlhbGl6ZSkgZm9yY2UuaW5pdGlhbGl6ZShub2Rlcyk7XG4gICAgcmV0dXJuIGZvcmNlO1xuICB9XG5cbiAgaW5pdGlhbGl6ZU5vZGVzKCk7XG5cbiAgcmV0dXJuIHNpbXVsYXRpb24gPSB7XG4gICAgdGljazogdGljayxcblxuICAgIHJlc3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHN0ZXBwZXIucmVzdGFydChzdGVwKSwgc2ltdWxhdGlvbjtcbiAgICB9LFxuXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gc3RlcHBlci5zdG9wKCksIHNpbXVsYXRpb247XG4gICAgfSxcblxuICAgIG5vZGVzOiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChub2RlcyA9IF8sIGluaXRpYWxpemVOb2RlcygpLCBmb3JjZXMuZWFjaChpbml0aWFsaXplRm9yY2UpLCBzaW11bGF0aW9uKSA6IG5vZGVzO1xuICAgIH0sXG5cbiAgICBhbHBoYTogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYWxwaGEgPSArXywgc2ltdWxhdGlvbikgOiBhbHBoYTtcbiAgICB9LFxuXG4gICAgYWxwaGFNaW46IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhTWluID0gK18sIHNpbXVsYXRpb24pIDogYWxwaGFNaW47XG4gICAgfSxcblxuICAgIGFscGhhRGVjYXk6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhRGVjYXkgPSArXywgc2ltdWxhdGlvbikgOiArYWxwaGFEZWNheTtcbiAgICB9LFxuXG4gICAgYWxwaGFUYXJnZXQ6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhVGFyZ2V0ID0gK18sIHNpbXVsYXRpb24pIDogYWxwaGFUYXJnZXQ7XG4gICAgfSxcblxuICAgIHZlbG9jaXR5RGVjYXk6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZlbG9jaXR5RGVjYXkgPSAxIC0gXywgc2ltdWxhdGlvbikgOiAxIC0gdmVsb2NpdHlEZWNheTtcbiAgICB9LFxuXG4gICAgZm9yY2U6IGZ1bmN0aW9uKG5hbWUsIF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID4gMSA/ICgoXyA9PSBudWxsID8gZm9yY2VzLnJlbW92ZShuYW1lKSA6IGZvcmNlcy5zZXQobmFtZSwgaW5pdGlhbGl6ZUZvcmNlKF8pKSksIHNpbXVsYXRpb24pIDogZm9yY2VzLmdldChuYW1lKTtcbiAgICB9LFxuXG4gICAgZmluZDogZnVuY3Rpb24oeCwgeSwgcmFkaXVzKSB7XG4gICAgICB2YXIgaSA9IDAsXG4gICAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgICBkeCxcbiAgICAgICAgICBkeSxcbiAgICAgICAgICBkMixcbiAgICAgICAgICBub2RlLFxuICAgICAgICAgIGNsb3Nlc3Q7XG5cbiAgICAgIGlmIChyYWRpdXMgPT0gbnVsbCkgcmFkaXVzID0gSW5maW5pdHk7XG4gICAgICBlbHNlIHJhZGl1cyAqPSByYWRpdXM7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBkeCA9IHggLSBub2RlLng7XG4gICAgICAgIGR5ID0geSAtIG5vZGUueTtcbiAgICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgICAgICAgaWYgKGQyIDwgcmFkaXVzKSBjbG9zZXN0ID0gbm9kZSwgcmFkaXVzID0gZDI7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjbG9zZXN0O1xuICAgIH0sXG5cbiAgICBvbjogZnVuY3Rpb24obmFtZSwgXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gKGV2ZW50Lm9uKG5hbWUsIF8pLCBzaW11bGF0aW9uKSA6IGV2ZW50Lm9uKG5hbWUpO1xuICAgIH1cbiAgfTtcbn07XG5cbnZhciBtYW55Qm9keSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbm9kZXMsXG4gICAgICBub2RlLFxuICAgICAgYWxwaGEsXG4gICAgICBzdHJlbmd0aCA9IGNvbnN0YW50KC0zMCksXG4gICAgICBzdHJlbmd0aHMsXG4gICAgICBkaXN0YW5jZU1pbjIgPSAxLFxuICAgICAgZGlzdGFuY2VNYXgyID0gSW5maW5pdHksXG4gICAgICB0aGV0YTIgPSAwLjgxO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKF8pIHtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCwgdHJlZSA9IGQzUXVhZHRyZWUucXVhZHRyZWUobm9kZXMsIHgkMSwgeSQxKS52aXNpdEFmdGVyKGFjY3VtdWxhdGUpO1xuICAgIGZvciAoYWxwaGEgPSBfLCBpID0gMDsgaSA8IG47ICsraSkgbm9kZSA9IG5vZGVzW2ldLCB0cmVlLnZpc2l0KGFwcGx5KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBub2RlID0gbm9kZXNbaV0sIHN0cmVuZ3Roc1tub2RlLmluZGV4XSA9ICtzdHJlbmd0aChub2RlLCBpLCBub2Rlcyk7XG4gIH1cblxuICBmdW5jdGlvbiBhY2N1bXVsYXRlKHF1YWQpIHtcbiAgICB2YXIgc3RyZW5ndGggPSAwLCBxLCBjLCB3ZWlnaHQgPSAwLCB4LCB5LCBpO1xuXG4gICAgLy8gRm9yIGludGVybmFsIG5vZGVzLCBhY2N1bXVsYXRlIGZvcmNlcyBmcm9tIGNoaWxkIHF1YWRyYW50cy5cbiAgICBpZiAocXVhZC5sZW5ndGgpIHtcbiAgICAgIGZvciAoeCA9IHkgPSBpID0gMDsgaSA8IDQ7ICsraSkge1xuICAgICAgICBpZiAoKHEgPSBxdWFkW2ldKSAmJiAoYyA9IE1hdGguYWJzKHEudmFsdWUpKSkge1xuICAgICAgICAgIHN0cmVuZ3RoICs9IHEudmFsdWUsIHdlaWdodCArPSBjLCB4ICs9IGMgKiBxLngsIHkgKz0gYyAqIHEueTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcXVhZC54ID0geCAvIHdlaWdodDtcbiAgICAgIHF1YWQueSA9IHkgLyB3ZWlnaHQ7XG4gICAgfVxuXG4gICAgLy8gRm9yIGxlYWYgbm9kZXMsIGFjY3VtdWxhdGUgZm9yY2VzIGZyb20gY29pbmNpZGVudCBxdWFkcmFudHMuXG4gICAgZWxzZSB7XG4gICAgICBxID0gcXVhZDtcbiAgICAgIHEueCA9IHEuZGF0YS54O1xuICAgICAgcS55ID0gcS5kYXRhLnk7XG4gICAgICBkbyBzdHJlbmd0aCArPSBzdHJlbmd0aHNbcS5kYXRhLmluZGV4XTtcbiAgICAgIHdoaWxlIChxID0gcS5uZXh0KTtcbiAgICB9XG5cbiAgICBxdWFkLnZhbHVlID0gc3RyZW5ndGg7XG4gIH1cblxuICBmdW5jdGlvbiBhcHBseShxdWFkLCB4MSwgXywgeDIpIHtcbiAgICBpZiAoIXF1YWQudmFsdWUpIHJldHVybiB0cnVlO1xuXG4gICAgdmFyIHggPSBxdWFkLnggLSBub2RlLngsXG4gICAgICAgIHkgPSBxdWFkLnkgLSBub2RlLnksXG4gICAgICAgIHcgPSB4MiAtIHgxLFxuICAgICAgICBsID0geCAqIHggKyB5ICogeTtcblxuICAgIC8vIEFwcGx5IHRoZSBCYXJuZXMtSHV0IGFwcHJveGltYXRpb24gaWYgcG9zc2libGUuXG4gICAgLy8gTGltaXQgZm9yY2VzIGZvciB2ZXJ5IGNsb3NlIG5vZGVzOyByYW5kb21pemUgZGlyZWN0aW9uIGlmIGNvaW5jaWRlbnQuXG4gICAgaWYgKHcgKiB3IC8gdGhldGEyIDwgbCkge1xuICAgICAgaWYgKGwgPCBkaXN0YW5jZU1heDIpIHtcbiAgICAgICAgaWYgKHggPT09IDApIHggPSBqaWdnbGUoKSwgbCArPSB4ICogeDtcbiAgICAgICAgaWYgKHkgPT09IDApIHkgPSBqaWdnbGUoKSwgbCArPSB5ICogeTtcbiAgICAgICAgaWYgKGwgPCBkaXN0YW5jZU1pbjIpIGwgPSBNYXRoLnNxcnQoZGlzdGFuY2VNaW4yICogbCk7XG4gICAgICAgIG5vZGUudnggKz0geCAqIHF1YWQudmFsdWUgKiBhbHBoYSAvIGw7XG4gICAgICAgIG5vZGUudnkgKz0geSAqIHF1YWQudmFsdWUgKiBhbHBoYSAvIGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIHByb2Nlc3MgcG9pbnRzIGRpcmVjdGx5LlxuICAgIGVsc2UgaWYgKHF1YWQubGVuZ3RoIHx8IGwgPj0gZGlzdGFuY2VNYXgyKSByZXR1cm47XG5cbiAgICAvLyBMaW1pdCBmb3JjZXMgZm9yIHZlcnkgY2xvc2Ugbm9kZXM7IHJhbmRvbWl6ZSBkaXJlY3Rpb24gaWYgY29pbmNpZGVudC5cbiAgICBpZiAocXVhZC5kYXRhICE9PSBub2RlIHx8IHF1YWQubmV4dCkge1xuICAgICAgaWYgKHggPT09IDApIHggPSBqaWdnbGUoKSwgbCArPSB4ICogeDtcbiAgICAgIGlmICh5ID09PSAwKSB5ID0gamlnZ2xlKCksIGwgKz0geSAqIHk7XG4gICAgICBpZiAobCA8IGRpc3RhbmNlTWluMikgbCA9IE1hdGguc3FydChkaXN0YW5jZU1pbjIgKiBsKTtcbiAgICB9XG5cbiAgICBkbyBpZiAocXVhZC5kYXRhICE9PSBub2RlKSB7XG4gICAgICB3ID0gc3RyZW5ndGhzW3F1YWQuZGF0YS5pbmRleF0gKiBhbHBoYSAvIGw7XG4gICAgICBub2RlLnZ4ICs9IHggKiB3O1xuICAgICAgbm9kZS52eSArPSB5ICogdztcbiAgICB9IHdoaWxlIChxdWFkID0gcXVhZC5uZXh0KTtcbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLmRpc3RhbmNlTWluID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRpc3RhbmNlTWluMiA9IF8gKiBfLCBmb3JjZSkgOiBNYXRoLnNxcnQoZGlzdGFuY2VNaW4yKTtcbiAgfTtcblxuICBmb3JjZS5kaXN0YW5jZU1heCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkaXN0YW5jZU1heDIgPSBfICogXywgZm9yY2UpIDogTWF0aC5zcXJ0KGRpc3RhbmNlTWF4Mik7XG4gIH07XG5cbiAgZm9yY2UudGhldGEgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGhldGEyID0gXyAqIF8sIGZvcmNlKSA6IE1hdGguc3FydCh0aGV0YTIpO1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciByYWRpYWwgPSBmdW5jdGlvbihyYWRpdXMsIHgsIHkpIHtcbiAgdmFyIG5vZGVzLFxuICAgICAgc3RyZW5ndGggPSBjb25zdGFudCgwLjEpLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgcmFkaXVzZXM7XG5cbiAgaWYgKHR5cGVvZiByYWRpdXMgIT09IFwiZnVuY3Rpb25cIikgcmFkaXVzID0gY29uc3RhbnQoK3JhZGl1cyk7XG4gIGlmICh4ID09IG51bGwpIHggPSAwO1xuICBpZiAoeSA9PSBudWxsKSB5ID0gMDtcblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldLFxuICAgICAgICAgIGR4ID0gbm9kZS54IC0geCB8fCAxZS02LFxuICAgICAgICAgIGR5ID0gbm9kZS55IC0geSB8fCAxZS02LFxuICAgICAgICAgIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpLFxuICAgICAgICAgIGsgPSAocmFkaXVzZXNbaV0gLSByKSAqIHN0cmVuZ3Roc1tpXSAqIGFscGhhIC8gcjtcbiAgICAgIG5vZGUudnggKz0gZHggKiBrO1xuICAgICAgbm9kZS52eSArPSBkeSAqIGs7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGg7XG4gICAgc3RyZW5ndGhzID0gbmV3IEFycmF5KG4pO1xuICAgIHJhZGl1c2VzID0gbmV3IEFycmF5KG4pO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHJhZGl1c2VzW2ldID0gK3JhZGl1cyhub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgICAgc3RyZW5ndGhzW2ldID0gaXNOYU4ocmFkaXVzZXNbaV0pID8gMCA6ICtzdHJlbmd0aChub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfLCBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS5yYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogcmFkaXVzO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9ICtfLCBmb3JjZSkgOiB4O1xuICB9O1xuXG4gIGZvcmNlLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9ICtfLCBmb3JjZSkgOiB5O1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciB4JDIgPSBmdW5jdGlvbih4KSB7XG4gIHZhciBzdHJlbmd0aCA9IGNvbnN0YW50KDAuMSksXG4gICAgICBub2RlcyxcbiAgICAgIHN0cmVuZ3RocyxcbiAgICAgIHh6O1xuXG4gIGlmICh0eXBlb2YgeCAhPT0gXCJmdW5jdGlvblwiKSB4ID0gY29uc3RhbnQoeCA9PSBudWxsID8gMCA6ICt4KTtcblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUudnggKz0gKHh6W2ldIC0gbm9kZS54KSAqIHN0cmVuZ3Roc1tpXSAqIGFscGhhO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICB4eiA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBzdHJlbmd0aHNbaV0gPSBpc05hTih4eltpXSA9ICt4KG5vZGVzW2ldLCBpLCBub2RlcykpID8gMCA6ICtzdHJlbmd0aChub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHg7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxudmFyIHkkMiA9IGZ1bmN0aW9uKHkpIHtcbiAgdmFyIHN0cmVuZ3RoID0gY29uc3RhbnQoMC4xKSxcbiAgICAgIG5vZGVzLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgeXo7XG5cbiAgaWYgKHR5cGVvZiB5ICE9PSBcImZ1bmN0aW9uXCIpIHkgPSBjb25zdGFudCh5ID09IG51bGwgPyAwIDogK3kpO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKGFscGhhKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXSwgbm9kZS52eSArPSAoeXpbaV0gLSBub2RlLnkpICogc3RyZW5ndGhzW2ldICogYWxwaGE7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGg7XG4gICAgc3RyZW5ndGhzID0gbmV3IEFycmF5KG4pO1xuICAgIHl6ID0gbmV3IEFycmF5KG4pO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHN0cmVuZ3Roc1tpXSA9IGlzTmFOKHl6W2ldID0gK3kobm9kZXNbaV0sIGksIG5vZGVzKSkgPyAwIDogK3N0cmVuZ3RoKG5vZGVzW2ldLCBpLCBub2Rlcyk7XG4gICAgfVxuICB9XG5cbiAgZm9yY2UuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBub2RlcyA9IF87XG4gICAgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogc3RyZW5ndGg7XG4gIH07XG5cbiAgZm9yY2UueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5ID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogeTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG5leHBvcnRzLmZvcmNlQ2VudGVyID0gY2VudGVyO1xuZXhwb3J0cy5mb3JjZUNvbGxpZGUgPSBjb2xsaWRlO1xuZXhwb3J0cy5mb3JjZUxpbmsgPSBsaW5rO1xuZXhwb3J0cy5mb3JjZU1hbnlCb2R5ID0gbWFueUJvZHk7XG5leHBvcnRzLmZvcmNlUmFkaWFsID0gcmFkaWFsO1xuZXhwb3J0cy5mb3JjZVNpbXVsYXRpb24gPSBzaW11bGF0aW9uO1xuZXhwb3J0cy5mb3JjZVggPSB4JDI7XG5leHBvcnRzLmZvcmNlWSA9IHkkMjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtaW50ZXJwb2xhdGUvIHYxLjMuMiBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2tcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG50eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLWNvbG9yJykpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtY29sb3InXSwgZmFjdG9yeSkgOlxuKGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSksZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0NvbG9yKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gYmFzaXModDEsIHYwLCB2MSwgdjIsIHYzKSB7XG4gIHZhciB0MiA9IHQxICogdDEsIHQzID0gdDIgKiB0MTtcbiAgcmV0dXJuICgoMSAtIDMgKiB0MSArIDMgKiB0MiAtIHQzKSAqIHYwXG4gICAgICArICg0IC0gNiAqIHQyICsgMyAqIHQzKSAqIHYxXG4gICAgICArICgxICsgMyAqIHQxICsgMyAqIHQyIC0gMyAqIHQzKSAqIHYyXG4gICAgICArIHQzICogdjMpIC8gNjtcbn1cblxuZnVuY3Rpb24gYmFzaXMkMSh2YWx1ZXMpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoIC0gMTtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICB2YXIgaSA9IHQgPD0gMCA/ICh0ID0gMCkgOiB0ID49IDEgPyAodCA9IDEsIG4gLSAxKSA6IE1hdGguZmxvb3IodCAqIG4pLFxuICAgICAgICB2MSA9IHZhbHVlc1tpXSxcbiAgICAgICAgdjIgPSB2YWx1ZXNbaSArIDFdLFxuICAgICAgICB2MCA9IGkgPiAwID8gdmFsdWVzW2kgLSAxXSA6IDIgKiB2MSAtIHYyLFxuICAgICAgICB2MyA9IGkgPCBuIC0gMSA/IHZhbHVlc1tpICsgMl0gOiAyICogdjIgLSB2MTtcbiAgICByZXR1cm4gYmFzaXMoKHQgLSBpIC8gbikgKiBuLCB2MCwgdjEsIHYyLCB2Myk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGJhc2lzQ2xvc2VkKHZhbHVlcykge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgdmFyIGkgPSBNYXRoLmZsb29yKCgodCAlPSAxKSA8IDAgPyArK3QgOiB0KSAqIG4pLFxuICAgICAgICB2MCA9IHZhbHVlc1soaSArIG4gLSAxKSAlIG5dLFxuICAgICAgICB2MSA9IHZhbHVlc1tpICUgbl0sXG4gICAgICAgIHYyID0gdmFsdWVzWyhpICsgMSkgJSBuXSxcbiAgICAgICAgdjMgPSB2YWx1ZXNbKGkgKyAyKSAlIG5dO1xuICAgIHJldHVybiBiYXNpcygodCAtIGkgLyBuKSAqIG4sIHYwLCB2MSwgdjIsIHYzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY29uc3RhbnQoeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGxpbmVhcihhLCBkKSB7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuIGEgKyB0ICogZDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gZXhwb25lbnRpYWwoYSwgYiwgeSkge1xuICByZXR1cm4gYSA9IE1hdGgucG93KGEsIHkpLCBiID0gTWF0aC5wb3coYiwgeSkgLSBhLCB5ID0gMSAvIHksIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coYSArIHQgKiBiLCB5KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaHVlKGEsIGIpIHtcbiAgdmFyIGQgPSBiIC0gYTtcbiAgcmV0dXJuIGQgPyBsaW5lYXIoYSwgZCA+IDE4MCB8fCBkIDwgLTE4MCA/IGQgLSAzNjAgKiBNYXRoLnJvdW5kKGQgLyAzNjApIDogZCkgOiBjb25zdGFudChpc05hTihhKSA/IGIgOiBhKTtcbn1cblxuZnVuY3Rpb24gZ2FtbWEoeSkge1xuICByZXR1cm4gKHkgPSAreSkgPT09IDEgPyBub2dhbW1hIDogZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBiIC0gYSA/IGV4cG9uZW50aWFsKGEsIGIsIHkpIDogY29uc3RhbnQoaXNOYU4oYSkgPyBiIDogYSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG5vZ2FtbWEoYSwgYikge1xuICB2YXIgZCA9IGIgLSBhO1xuICByZXR1cm4gZCA/IGxpbmVhcihhLCBkKSA6IGNvbnN0YW50KGlzTmFOKGEpID8gYiA6IGEpO1xufVxuXG52YXIgcmdiID0gKGZ1bmN0aW9uIHJnYkdhbW1hKHkpIHtcbiAgdmFyIGNvbG9yID0gZ2FtbWEoeSk7XG5cbiAgZnVuY3Rpb24gcmdiKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgciA9IGNvbG9yKChzdGFydCA9IGQzQ29sb3IucmdiKHN0YXJ0KSkuciwgKGVuZCA9IGQzQ29sb3IucmdiKGVuZCkpLnIpLFxuICAgICAgICBnID0gY29sb3Ioc3RhcnQuZywgZW5kLmcpLFxuICAgICAgICBiID0gY29sb3Ioc3RhcnQuYiwgZW5kLmIpLFxuICAgICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHN0YXJ0LnIgPSByKHQpO1xuICAgICAgc3RhcnQuZyA9IGcodCk7XG4gICAgICBzdGFydC5iID0gYih0KTtcbiAgICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgICAgcmV0dXJuIHN0YXJ0ICsgXCJcIjtcbiAgICB9O1xuICB9XG5cbiAgcmdiLmdhbW1hID0gcmdiR2FtbWE7XG5cbiAgcmV0dXJuIHJnYjtcbn0pKDEpO1xuXG5mdW5jdGlvbiByZ2JTcGxpbmUoc3BsaW5lKSB7XG4gIHJldHVybiBmdW5jdGlvbihjb2xvcnMpIHtcbiAgICB2YXIgbiA9IGNvbG9ycy5sZW5ndGgsXG4gICAgICAgIHIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGcgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGksIGNvbG9yO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGNvbG9yID0gZDNDb2xvci5yZ2IoY29sb3JzW2ldKTtcbiAgICAgIHJbaV0gPSBjb2xvci5yIHx8IDA7XG4gICAgICBnW2ldID0gY29sb3IuZyB8fCAwO1xuICAgICAgYltpXSA9IGNvbG9yLmIgfHwgMDtcbiAgICB9XG4gICAgciA9IHNwbGluZShyKTtcbiAgICBnID0gc3BsaW5lKGcpO1xuICAgIGIgPSBzcGxpbmUoYik7XG4gICAgY29sb3Iub3BhY2l0eSA9IDE7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIGNvbG9yLnIgPSByKHQpO1xuICAgICAgY29sb3IuZyA9IGcodCk7XG4gICAgICBjb2xvci5iID0gYih0KTtcbiAgICAgIHJldHVybiBjb2xvciArIFwiXCI7XG4gICAgfTtcbiAgfTtcbn1cblxudmFyIHJnYkJhc2lzID0gcmdiU3BsaW5lKGJhc2lzJDEpO1xudmFyIHJnYkJhc2lzQ2xvc2VkID0gcmdiU3BsaW5lKGJhc2lzQ2xvc2VkKTtcblxuZnVuY3Rpb24gYXJyYXkoYSwgYikge1xuICB2YXIgbmIgPSBiID8gYi5sZW5ndGggOiAwLFxuICAgICAgbmEgPSBhID8gTWF0aC5taW4obmIsIGEubGVuZ3RoKSA6IDAsXG4gICAgICB4ID0gbmV3IEFycmF5KG5hKSxcbiAgICAgIGMgPSBuZXcgQXJyYXkobmIpLFxuICAgICAgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgbmE7ICsraSkgeFtpXSA9IHZhbHVlKGFbaV0sIGJbaV0pO1xuICBmb3IgKDsgaSA8IG5iOyArK2kpIGNbaV0gPSBiW2ldO1xuXG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgZm9yIChpID0gMDsgaSA8IG5hOyArK2kpIGNbaV0gPSB4W2ldKHQpO1xuICAgIHJldHVybiBjO1xuICB9O1xufVxuXG5mdW5jdGlvbiBkYXRlKGEsIGIpIHtcbiAgdmFyIGQgPSBuZXcgRGF0ZTtcbiAgcmV0dXJuIGEgPSArYSwgYiAtPSBhLCBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuIGQuc2V0VGltZShhICsgYiAqIHQpLCBkO1xuICB9O1xufVxuXG5mdW5jdGlvbiBudW1iZXIoYSwgYikge1xuICByZXR1cm4gYSA9ICthLCBiIC09IGEsIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gYSArIGIgKiB0O1xuICB9O1xufVxuXG5mdW5jdGlvbiBvYmplY3QoYSwgYikge1xuICB2YXIgaSA9IHt9LFxuICAgICAgYyA9IHt9LFxuICAgICAgaztcblxuICBpZiAoYSA9PT0gbnVsbCB8fCB0eXBlb2YgYSAhPT0gXCJvYmplY3RcIikgYSA9IHt9O1xuICBpZiAoYiA9PT0gbnVsbCB8fCB0eXBlb2YgYiAhPT0gXCJvYmplY3RcIikgYiA9IHt9O1xuXG4gIGZvciAoayBpbiBiKSB7XG4gICAgaWYgKGsgaW4gYSkge1xuICAgICAgaVtrXSA9IHZhbHVlKGFba10sIGJba10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjW2tdID0gYltrXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIGZvciAoayBpbiBpKSBjW2tdID0gaVtrXSh0KTtcbiAgICByZXR1cm4gYztcbiAgfTtcbn1cblxudmFyIHJlQSA9IC9bLStdPyg/OlxcZCtcXC4/XFxkKnxcXC4/XFxkKykoPzpbZUVdWy0rXT9cXGQrKT8vZyxcbiAgICByZUIgPSBuZXcgUmVnRXhwKHJlQS5zb3VyY2UsIFwiZ1wiKTtcblxuZnVuY3Rpb24gemVybyhiKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gb25lKGIpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gYih0KSArIFwiXCI7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHN0cmluZyhhLCBiKSB7XG4gIHZhciBiaSA9IHJlQS5sYXN0SW5kZXggPSByZUIubGFzdEluZGV4ID0gMCwgLy8gc2NhbiBpbmRleCBmb3IgbmV4dCBudW1iZXIgaW4gYlxuICAgICAgYW0sIC8vIGN1cnJlbnQgbWF0Y2ggaW4gYVxuICAgICAgYm0sIC8vIGN1cnJlbnQgbWF0Y2ggaW4gYlxuICAgICAgYnMsIC8vIHN0cmluZyBwcmVjZWRpbmcgY3VycmVudCBudW1iZXIgaW4gYiwgaWYgYW55XG4gICAgICBpID0gLTEsIC8vIGluZGV4IGluIHNcbiAgICAgIHMgPSBbXSwgLy8gc3RyaW5nIGNvbnN0YW50cyBhbmQgcGxhY2Vob2xkZXJzXG4gICAgICBxID0gW107IC8vIG51bWJlciBpbnRlcnBvbGF0b3JzXG5cbiAgLy8gQ29lcmNlIGlucHV0cyB0byBzdHJpbmdzLlxuICBhID0gYSArIFwiXCIsIGIgPSBiICsgXCJcIjtcblxuICAvLyBJbnRlcnBvbGF0ZSBwYWlycyBvZiBudW1iZXJzIGluIGEgJiBiLlxuICB3aGlsZSAoKGFtID0gcmVBLmV4ZWMoYSkpXG4gICAgICAmJiAoYm0gPSByZUIuZXhlYyhiKSkpIHtcbiAgICBpZiAoKGJzID0gYm0uaW5kZXgpID4gYmkpIHsgLy8gYSBzdHJpbmcgcHJlY2VkZXMgdGhlIG5leHQgbnVtYmVyIGluIGJcbiAgICAgIGJzID0gYi5zbGljZShiaSwgYnMpO1xuICAgICAgaWYgKHNbaV0pIHNbaV0gKz0gYnM7IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgICBlbHNlIHNbKytpXSA9IGJzO1xuICAgIH1cbiAgICBpZiAoKGFtID0gYW1bMF0pID09PSAoYm0gPSBibVswXSkpIHsgLy8gbnVtYmVycyBpbiBhICYgYiBtYXRjaFxuICAgICAgaWYgKHNbaV0pIHNbaV0gKz0gYm07IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgICBlbHNlIHNbKytpXSA9IGJtO1xuICAgIH0gZWxzZSB7IC8vIGludGVycG9sYXRlIG5vbi1tYXRjaGluZyBudW1iZXJzXG4gICAgICBzWysraV0gPSBudWxsO1xuICAgICAgcS5wdXNoKHtpOiBpLCB4OiBudW1iZXIoYW0sIGJtKX0pO1xuICAgIH1cbiAgICBiaSA9IHJlQi5sYXN0SW5kZXg7XG4gIH1cblxuICAvLyBBZGQgcmVtYWlucyBvZiBiLlxuICBpZiAoYmkgPCBiLmxlbmd0aCkge1xuICAgIGJzID0gYi5zbGljZShiaSk7XG4gICAgaWYgKHNbaV0pIHNbaV0gKz0gYnM7IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgZWxzZSBzWysraV0gPSBicztcbiAgfVxuXG4gIC8vIFNwZWNpYWwgb3B0aW1pemF0aW9uIGZvciBvbmx5IGEgc2luZ2xlIG1hdGNoLlxuICAvLyBPdGhlcndpc2UsIGludGVycG9sYXRlIGVhY2ggb2YgdGhlIG51bWJlcnMgYW5kIHJlam9pbiB0aGUgc3RyaW5nLlxuICByZXR1cm4gcy5sZW5ndGggPCAyID8gKHFbMF1cbiAgICAgID8gb25lKHFbMF0ueClcbiAgICAgIDogemVybyhiKSlcbiAgICAgIDogKGIgPSBxLmxlbmd0aCwgZnVuY3Rpb24odCkge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBvOyBpIDwgYjsgKytpKSBzWyhvID0gcVtpXSkuaV0gPSBvLngodCk7XG4gICAgICAgICAgcmV0dXJuIHMuam9pbihcIlwiKTtcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlKGEsIGIpIHtcbiAgdmFyIHQgPSB0eXBlb2YgYiwgYztcbiAgcmV0dXJuIGIgPT0gbnVsbCB8fCB0ID09PSBcImJvb2xlYW5cIiA/IGNvbnN0YW50KGIpXG4gICAgICA6ICh0ID09PSBcIm51bWJlclwiID8gbnVtYmVyXG4gICAgICA6IHQgPT09IFwic3RyaW5nXCIgPyAoKGMgPSBkM0NvbG9yLmNvbG9yKGIpKSA/IChiID0gYywgcmdiKSA6IHN0cmluZylcbiAgICAgIDogYiBpbnN0YW5jZW9mIGQzQ29sb3IuY29sb3IgPyByZ2JcbiAgICAgIDogYiBpbnN0YW5jZW9mIERhdGUgPyBkYXRlXG4gICAgICA6IEFycmF5LmlzQXJyYXkoYikgPyBhcnJheVxuICAgICAgOiB0eXBlb2YgYi52YWx1ZU9mICE9PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGIudG9TdHJpbmcgIT09IFwiZnVuY3Rpb25cIiB8fCBpc05hTihiKSA/IG9iamVjdFxuICAgICAgOiBudW1iZXIpKGEsIGIpO1xufVxuXG5mdW5jdGlvbiBkaXNjcmV0ZShyYW5nZSkge1xuICB2YXIgbiA9IHJhbmdlLmxlbmd0aDtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gcmFuZ2VbTWF0aC5tYXgoMCwgTWF0aC5taW4obiAtIDEsIE1hdGguZmxvb3IodCAqIG4pKSldO1xuICB9O1xufVxuXG5mdW5jdGlvbiBodWUkMShhLCBiKSB7XG4gIHZhciBpID0gaHVlKCthLCArYik7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgdmFyIHggPSBpKHQpO1xuICAgIHJldHVybiB4IC0gMzYwICogTWF0aC5mbG9vcih4IC8gMzYwKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcm91bmQoYSwgYikge1xuICByZXR1cm4gYSA9ICthLCBiIC09IGEsIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChhICsgYiAqIHQpO1xuICB9O1xufVxuXG52YXIgZGVncmVlcyA9IDE4MCAvIE1hdGguUEk7XG5cbnZhciBpZGVudGl0eSA9IHtcbiAgdHJhbnNsYXRlWDogMCxcbiAgdHJhbnNsYXRlWTogMCxcbiAgcm90YXRlOiAwLFxuICBza2V3WDogMCxcbiAgc2NhbGVYOiAxLFxuICBzY2FsZVk6IDFcbn07XG5cbmZ1bmN0aW9uIGRlY29tcG9zZShhLCBiLCBjLCBkLCBlLCBmKSB7XG4gIHZhciBzY2FsZVgsIHNjYWxlWSwgc2tld1g7XG4gIGlmIChzY2FsZVggPSBNYXRoLnNxcnQoYSAqIGEgKyBiICogYikpIGEgLz0gc2NhbGVYLCBiIC89IHNjYWxlWDtcbiAgaWYgKHNrZXdYID0gYSAqIGMgKyBiICogZCkgYyAtPSBhICogc2tld1gsIGQgLT0gYiAqIHNrZXdYO1xuICBpZiAoc2NhbGVZID0gTWF0aC5zcXJ0KGMgKiBjICsgZCAqIGQpKSBjIC89IHNjYWxlWSwgZCAvPSBzY2FsZVksIHNrZXdYIC89IHNjYWxlWTtcbiAgaWYgKGEgKiBkIDwgYiAqIGMpIGEgPSAtYSwgYiA9IC1iLCBza2V3WCA9IC1za2V3WCwgc2NhbGVYID0gLXNjYWxlWDtcbiAgcmV0dXJuIHtcbiAgICB0cmFuc2xhdGVYOiBlLFxuICAgIHRyYW5zbGF0ZVk6IGYsXG4gICAgcm90YXRlOiBNYXRoLmF0YW4yKGIsIGEpICogZGVncmVlcyxcbiAgICBza2V3WDogTWF0aC5hdGFuKHNrZXdYKSAqIGRlZ3JlZXMsXG4gICAgc2NhbGVYOiBzY2FsZVgsXG4gICAgc2NhbGVZOiBzY2FsZVlcbiAgfTtcbn1cblxudmFyIGNzc05vZGUsXG4gICAgY3NzUm9vdCxcbiAgICBjc3NWaWV3LFxuICAgIHN2Z05vZGU7XG5cbmZ1bmN0aW9uIHBhcnNlQ3NzKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PT0gXCJub25lXCIpIHJldHVybiBpZGVudGl0eTtcbiAgaWYgKCFjc3NOb2RlKSBjc3NOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIkRJVlwiKSwgY3NzUm9vdCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgY3NzVmlldyA9IGRvY3VtZW50LmRlZmF1bHRWaWV3O1xuICBjc3NOb2RlLnN0eWxlLnRyYW5zZm9ybSA9IHZhbHVlO1xuICB2YWx1ZSA9IGNzc1ZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShjc3NSb290LmFwcGVuZENoaWxkKGNzc05vZGUpLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKFwidHJhbnNmb3JtXCIpO1xuICBjc3NSb290LnJlbW92ZUNoaWxkKGNzc05vZGUpO1xuICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDcsIC0xKS5zcGxpdChcIixcIik7XG4gIHJldHVybiBkZWNvbXBvc2UoK3ZhbHVlWzBdLCArdmFsdWVbMV0sICt2YWx1ZVsyXSwgK3ZhbHVlWzNdLCArdmFsdWVbNF0sICt2YWx1ZVs1XSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlU3ZnKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gaWRlbnRpdHk7XG4gIGlmICghc3ZnTm9kZSkgc3ZnTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIFwiZ1wiKTtcbiAgc3ZnTm9kZS5zZXRBdHRyaWJ1dGUoXCJ0cmFuc2Zvcm1cIiwgdmFsdWUpO1xuICBpZiAoISh2YWx1ZSA9IHN2Z05vZGUudHJhbnNmb3JtLmJhc2VWYWwuY29uc29saWRhdGUoKSkpIHJldHVybiBpZGVudGl0eTtcbiAgdmFsdWUgPSB2YWx1ZS5tYXRyaXg7XG4gIHJldHVybiBkZWNvbXBvc2UodmFsdWUuYSwgdmFsdWUuYiwgdmFsdWUuYywgdmFsdWUuZCwgdmFsdWUuZSwgdmFsdWUuZik7XG59XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlVHJhbnNmb3JtKHBhcnNlLCBweENvbW1hLCBweFBhcmVuLCBkZWdQYXJlbikge1xuXG4gIGZ1bmN0aW9uIHBvcChzKSB7XG4gICAgcmV0dXJuIHMubGVuZ3RoID8gcy5wb3AoKSArIFwiIFwiIDogXCJcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYW5zbGF0ZSh4YSwgeWEsIHhiLCB5YiwgcywgcSkge1xuICAgIGlmICh4YSAhPT0geGIgfHwgeWEgIT09IHliKSB7XG4gICAgICB2YXIgaSA9IHMucHVzaChcInRyYW5zbGF0ZShcIiwgbnVsbCwgcHhDb21tYSwgbnVsbCwgcHhQYXJlbik7XG4gICAgICBxLnB1c2goe2k6IGkgLSA0LCB4OiBudW1iZXIoeGEsIHhiKX0sIHtpOiBpIC0gMiwgeDogbnVtYmVyKHlhLCB5Yil9KTtcbiAgICB9IGVsc2UgaWYgKHhiIHx8IHliKSB7XG4gICAgICBzLnB1c2goXCJ0cmFuc2xhdGUoXCIgKyB4YiArIHB4Q29tbWEgKyB5YiArIHB4UGFyZW4pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJvdGF0ZShhLCBiLCBzLCBxKSB7XG4gICAgaWYgKGEgIT09IGIpIHtcbiAgICAgIGlmIChhIC0gYiA+IDE4MCkgYiArPSAzNjA7IGVsc2UgaWYgKGIgLSBhID4gMTgwKSBhICs9IDM2MDsgLy8gc2hvcnRlc3QgcGF0aFxuICAgICAgcS5wdXNoKHtpOiBzLnB1c2gocG9wKHMpICsgXCJyb3RhdGUoXCIsIG51bGwsIGRlZ1BhcmVuKSAtIDIsIHg6IG51bWJlcihhLCBiKX0pO1xuICAgIH0gZWxzZSBpZiAoYikge1xuICAgICAgcy5wdXNoKHBvcChzKSArIFwicm90YXRlKFwiICsgYiArIGRlZ1BhcmVuKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBza2V3WChhLCBiLCBzLCBxKSB7XG4gICAgaWYgKGEgIT09IGIpIHtcbiAgICAgIHEucHVzaCh7aTogcy5wdXNoKHBvcChzKSArIFwic2tld1goXCIsIG51bGwsIGRlZ1BhcmVuKSAtIDIsIHg6IG51bWJlcihhLCBiKX0pO1xuICAgIH0gZWxzZSBpZiAoYikge1xuICAgICAgcy5wdXNoKHBvcChzKSArIFwic2tld1goXCIgKyBiICsgZGVnUGFyZW4pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNjYWxlKHhhLCB5YSwgeGIsIHliLCBzLCBxKSB7XG4gICAgaWYgKHhhICE9PSB4YiB8fCB5YSAhPT0geWIpIHtcbiAgICAgIHZhciBpID0gcy5wdXNoKHBvcChzKSArIFwic2NhbGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe2k6IGkgLSA0LCB4OiBudW1iZXIoeGEsIHhiKX0sIHtpOiBpIC0gMiwgeDogbnVtYmVyKHlhLCB5Yil9KTtcbiAgICB9IGVsc2UgaWYgKHhiICE9PSAxIHx8IHliICE9PSAxKSB7XG4gICAgICBzLnB1c2gocG9wKHMpICsgXCJzY2FsZShcIiArIHhiICsgXCIsXCIgKyB5YiArIFwiKVwiKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBzID0gW10sIC8vIHN0cmluZyBjb25zdGFudHMgYW5kIHBsYWNlaG9sZGVyc1xuICAgICAgICBxID0gW107IC8vIG51bWJlciBpbnRlcnBvbGF0b3JzXG4gICAgYSA9IHBhcnNlKGEpLCBiID0gcGFyc2UoYik7XG4gICAgdHJhbnNsYXRlKGEudHJhbnNsYXRlWCwgYS50cmFuc2xhdGVZLCBiLnRyYW5zbGF0ZVgsIGIudHJhbnNsYXRlWSwgcywgcSk7XG4gICAgcm90YXRlKGEucm90YXRlLCBiLnJvdGF0ZSwgcywgcSk7XG4gICAgc2tld1goYS5za2V3WCwgYi5za2V3WCwgcywgcSk7XG4gICAgc2NhbGUoYS5zY2FsZVgsIGEuc2NhbGVZLCBiLnNjYWxlWCwgYi5zY2FsZVksIHMsIHEpO1xuICAgIGEgPSBiID0gbnVsbDsgLy8gZ2NcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IHEubGVuZ3RoLCBvO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHNbKG8gPSBxW2ldKS5pXSA9IG8ueCh0KTtcbiAgICAgIHJldHVybiBzLmpvaW4oXCJcIik7XG4gICAgfTtcbiAgfTtcbn1cblxudmFyIGludGVycG9sYXRlVHJhbnNmb3JtQ3NzID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm0ocGFyc2VDc3MsIFwicHgsIFwiLCBcInB4KVwiLCBcImRlZylcIik7XG52YXIgaW50ZXJwb2xhdGVUcmFuc2Zvcm1TdmcgPSBpbnRlcnBvbGF0ZVRyYW5zZm9ybShwYXJzZVN2ZywgXCIsIFwiLCBcIilcIiwgXCIpXCIpO1xuXG52YXIgcmhvID0gTWF0aC5TUVJUMixcbiAgICByaG8yID0gMixcbiAgICByaG80ID0gNCxcbiAgICBlcHNpbG9uMiA9IDFlLTEyO1xuXG5mdW5jdGlvbiBjb3NoKHgpIHtcbiAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSArIDEgLyB4KSAvIDI7XG59XG5cbmZ1bmN0aW9uIHNpbmgoeCkge1xuICByZXR1cm4gKCh4ID0gTWF0aC5leHAoeCkpIC0gMSAvIHgpIC8gMjtcbn1cblxuZnVuY3Rpb24gdGFuaCh4KSB7XG4gIHJldHVybiAoKHggPSBNYXRoLmV4cCgyICogeCkpIC0gMSkgLyAoeCArIDEpO1xufVxuXG4vLyBwMCA9IFt1eDAsIHV5MCwgdzBdXG4vLyBwMSA9IFt1eDEsIHV5MSwgdzFdXG5mdW5jdGlvbiB6b29tKHAwLCBwMSkge1xuICB2YXIgdXgwID0gcDBbMF0sIHV5MCA9IHAwWzFdLCB3MCA9IHAwWzJdLFxuICAgICAgdXgxID0gcDFbMF0sIHV5MSA9IHAxWzFdLCB3MSA9IHAxWzJdLFxuICAgICAgZHggPSB1eDEgLSB1eDAsXG4gICAgICBkeSA9IHV5MSAtIHV5MCxcbiAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHksXG4gICAgICBpLFxuICAgICAgUztcblxuICAvLyBTcGVjaWFsIGNhc2UgZm9yIHUwIOKJhSB1MS5cbiAgaWYgKGQyIDwgZXBzaWxvbjIpIHtcbiAgICBTID0gTWF0aC5sb2codzEgLyB3MCkgLyByaG87XG4gICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHV4MCArIHQgKiBkeCxcbiAgICAgICAgdXkwICsgdCAqIGR5LFxuICAgICAgICB3MCAqIE1hdGguZXhwKHJobyAqIHQgKiBTKVxuICAgICAgXTtcbiAgICB9O1xuICB9XG5cbiAgLy8gR2VuZXJhbCBjYXNlLlxuICBlbHNlIHtcbiAgICB2YXIgZDEgPSBNYXRoLnNxcnQoZDIpLFxuICAgICAgICBiMCA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIHJobzQgKiBkMikgLyAoMiAqIHcwICogcmhvMiAqIGQxKSxcbiAgICAgICAgYjEgPSAodzEgKiB3MSAtIHcwICogdzAgLSByaG80ICogZDIpIC8gKDIgKiB3MSAqIHJobzIgKiBkMSksXG4gICAgICAgIHIwID0gTWF0aC5sb2coTWF0aC5zcXJ0KGIwICogYjAgKyAxKSAtIGIwKSxcbiAgICAgICAgcjEgPSBNYXRoLmxvZyhNYXRoLnNxcnQoYjEgKiBiMSArIDEpIC0gYjEpO1xuICAgIFMgPSAocjEgLSByMCkgLyByaG87XG4gICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBzID0gdCAqIFMsXG4gICAgICAgICAgY29zaHIwID0gY29zaChyMCksXG4gICAgICAgICAgdSA9IHcwIC8gKHJobzIgKiBkMSkgKiAoY29zaHIwICogdGFuaChyaG8gKiBzICsgcjApIC0gc2luaChyMCkpO1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgdXgwICsgdSAqIGR4LFxuICAgICAgICB1eTAgKyB1ICogZHksXG4gICAgICAgIHcwICogY29zaHIwIC8gY29zaChyaG8gKiBzICsgcjApXG4gICAgICBdO1xuICAgIH07XG4gIH1cblxuICBpLmR1cmF0aW9uID0gUyAqIDEwMDA7XG5cbiAgcmV0dXJuIGk7XG59XG5cbmZ1bmN0aW9uIGhzbChodWUkJDEpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgaCA9IGh1ZSQkMSgoc3RhcnQgPSBkM0NvbG9yLmhzbChzdGFydCkpLmgsIChlbmQgPSBkM0NvbG9yLmhzbChlbmQpKS5oKSxcbiAgICAgICAgcyA9IG5vZ2FtbWEoc3RhcnQucywgZW5kLnMpLFxuICAgICAgICBsID0gbm9nYW1tYShzdGFydC5sLCBlbmQubCksXG4gICAgICAgIG9wYWNpdHkgPSBub2dhbW1hKHN0YXJ0Lm9wYWNpdHksIGVuZC5vcGFjaXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgc3RhcnQuaCA9IGgodCk7XG4gICAgICBzdGFydC5zID0gcyh0KTtcbiAgICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgIH07XG4gIH1cbn1cblxudmFyIGhzbCQxID0gaHNsKGh1ZSk7XG52YXIgaHNsTG9uZyA9IGhzbChub2dhbW1hKTtcblxuZnVuY3Rpb24gbGFiKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGwgPSBub2dhbW1hKChzdGFydCA9IGQzQ29sb3IubGFiKHN0YXJ0KSkubCwgKGVuZCA9IGQzQ29sb3IubGFiKGVuZCkpLmwpLFxuICAgICAgYSA9IG5vZ2FtbWEoc3RhcnQuYSwgZW5kLmEpLFxuICAgICAgYiA9IG5vZ2FtbWEoc3RhcnQuYiwgZW5kLmIpLFxuICAgICAgb3BhY2l0eSA9IG5vZ2FtbWEoc3RhcnQub3BhY2l0eSwgZW5kLm9wYWNpdHkpO1xuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgIHN0YXJ0LmEgPSBhKHQpO1xuICAgIHN0YXJ0LmIgPSBiKHQpO1xuICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgIHJldHVybiBzdGFydCArIFwiXCI7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGhjbChodWUkJDEpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgaCA9IGh1ZSQkMSgoc3RhcnQgPSBkM0NvbG9yLmhjbChzdGFydCkpLmgsIChlbmQgPSBkM0NvbG9yLmhjbChlbmQpKS5oKSxcbiAgICAgICAgYyA9IG5vZ2FtbWEoc3RhcnQuYywgZW5kLmMpLFxuICAgICAgICBsID0gbm9nYW1tYShzdGFydC5sLCBlbmQubCksXG4gICAgICAgIG9wYWNpdHkgPSBub2dhbW1hKHN0YXJ0Lm9wYWNpdHksIGVuZC5vcGFjaXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgc3RhcnQuaCA9IGgodCk7XG4gICAgICBzdGFydC5jID0gYyh0KTtcbiAgICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgIH07XG4gIH1cbn1cblxudmFyIGhjbCQxID0gaGNsKGh1ZSk7XG52YXIgaGNsTG9uZyA9IGhjbChub2dhbW1hKTtcblxuZnVuY3Rpb24gY3ViZWhlbGl4KGh1ZSQkMSkge1xuICByZXR1cm4gKGZ1bmN0aW9uIGN1YmVoZWxpeEdhbW1hKHkpIHtcbiAgICB5ID0gK3k7XG5cbiAgICBmdW5jdGlvbiBjdWJlaGVsaXgoc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGggPSBodWUkJDEoKHN0YXJ0ID0gZDNDb2xvci5jdWJlaGVsaXgoc3RhcnQpKS5oLCAoZW5kID0gZDNDb2xvci5jdWJlaGVsaXgoZW5kKSkuaCksXG4gICAgICAgICAgcyA9IG5vZ2FtbWEoc3RhcnQucywgZW5kLnMpLFxuICAgICAgICAgIGwgPSBub2dhbW1hKHN0YXJ0LmwsIGVuZC5sKSxcbiAgICAgICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgICBzdGFydC5oID0gaCh0KTtcbiAgICAgICAgc3RhcnQucyA9IHModCk7XG4gICAgICAgIHN0YXJ0LmwgPSBsKE1hdGgucG93KHQsIHkpKTtcbiAgICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICAgIHJldHVybiBzdGFydCArIFwiXCI7XG4gICAgICB9O1xuICAgIH1cblxuICAgIGN1YmVoZWxpeC5nYW1tYSA9IGN1YmVoZWxpeEdhbW1hO1xuXG4gICAgcmV0dXJuIGN1YmVoZWxpeDtcbiAgfSkoMSk7XG59XG5cbnZhciBjdWJlaGVsaXgkMSA9IGN1YmVoZWxpeChodWUpO1xudmFyIGN1YmVoZWxpeExvbmcgPSBjdWJlaGVsaXgobm9nYW1tYSk7XG5cbmZ1bmN0aW9uIHBpZWNld2lzZShpbnRlcnBvbGF0ZSwgdmFsdWVzKSB7XG4gIHZhciBpID0gMCwgbiA9IHZhbHVlcy5sZW5ndGggLSAxLCB2ID0gdmFsdWVzWzBdLCBJID0gbmV3IEFycmF5KG4gPCAwID8gMCA6IG4pO1xuICB3aGlsZSAoaSA8IG4pIElbaV0gPSBpbnRlcnBvbGF0ZSh2LCB2ID0gdmFsdWVzWysraV0pO1xuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIHZhciBpID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obiAtIDEsIE1hdGguZmxvb3IodCAqPSBuKSkpO1xuICAgIHJldHVybiBJW2ldKHQgLSBpKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcXVhbnRpemUoaW50ZXJwb2xhdG9yLCBuKSB7XG4gIHZhciBzYW1wbGVzID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgc2FtcGxlc1tpXSA9IGludGVycG9sYXRvcihpIC8gKG4gLSAxKSk7XG4gIHJldHVybiBzYW1wbGVzO1xufVxuXG5leHBvcnRzLmludGVycG9sYXRlID0gdmFsdWU7XG5leHBvcnRzLmludGVycG9sYXRlQXJyYXkgPSBhcnJheTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVCYXNpcyA9IGJhc2lzJDE7XG5leHBvcnRzLmludGVycG9sYXRlQmFzaXNDbG9zZWQgPSBiYXNpc0Nsb3NlZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVEYXRlID0gZGF0ZTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVEaXNjcmV0ZSA9IGRpc2NyZXRlO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZUh1ZSA9IGh1ZSQxO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZU51bWJlciA9IG51bWJlcjtcbmV4cG9ydHMuaW50ZXJwb2xhdGVPYmplY3QgPSBvYmplY3Q7XG5leHBvcnRzLmludGVycG9sYXRlUm91bmQgPSByb3VuZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVTdHJpbmcgPSBzdHJpbmc7XG5leHBvcnRzLmludGVycG9sYXRlVHJhbnNmb3JtQ3NzID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm1Dc3M7XG5leHBvcnRzLmludGVycG9sYXRlVHJhbnNmb3JtU3ZnID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm1Tdmc7XG5leHBvcnRzLmludGVycG9sYXRlWm9vbSA9IHpvb207XG5leHBvcnRzLmludGVycG9sYXRlUmdiID0gcmdiO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZVJnYkJhc2lzID0gcmdiQmFzaXM7XG5leHBvcnRzLmludGVycG9sYXRlUmdiQmFzaXNDbG9zZWQgPSByZ2JCYXNpc0Nsb3NlZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVIc2wgPSBoc2wkMTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVIc2xMb25nID0gaHNsTG9uZztcbmV4cG9ydHMuaW50ZXJwb2xhdGVMYWIgPSBsYWI7XG5leHBvcnRzLmludGVycG9sYXRlSGNsID0gaGNsJDE7XG5leHBvcnRzLmludGVycG9sYXRlSGNsTG9uZyA9IGhjbExvbmc7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4ID0gY3ViZWhlbGl4JDE7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4TG9uZyA9IGN1YmVoZWxpeExvbmc7XG5leHBvcnRzLnBpZWNld2lzZSA9IHBpZWNld2lzZTtcbmV4cG9ydHMucXVhbnRpemUgPSBxdWFudGl6ZTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtcXVhZHRyZWUvIFZlcnNpb24gMS4wLjMuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHRyZWVfYWRkID0gZnVuY3Rpb24oZCkge1xuICB2YXIgeCA9ICt0aGlzLl94LmNhbGwobnVsbCwgZCksXG4gICAgICB5ID0gK3RoaXMuX3kuY2FsbChudWxsLCBkKTtcbiAgcmV0dXJuIGFkZCh0aGlzLmNvdmVyKHgsIHkpLCB4LCB5LCBkKTtcbn07XG5cbmZ1bmN0aW9uIGFkZCh0cmVlLCB4LCB5LCBkKSB7XG4gIGlmIChpc05hTih4KSB8fCBpc05hTih5KSkgcmV0dXJuIHRyZWU7IC8vIGlnbm9yZSBpbnZhbGlkIHBvaW50c1xuXG4gIHZhciBwYXJlbnQsXG4gICAgICBub2RlID0gdHJlZS5fcm9vdCxcbiAgICAgIGxlYWYgPSB7ZGF0YTogZH0sXG4gICAgICB4MCA9IHRyZWUuX3gwLFxuICAgICAgeTAgPSB0cmVlLl95MCxcbiAgICAgIHgxID0gdHJlZS5feDEsXG4gICAgICB5MSA9IHRyZWUuX3kxLFxuICAgICAgeG0sXG4gICAgICB5bSxcbiAgICAgIHhwLFxuICAgICAgeXAsXG4gICAgICByaWdodCxcbiAgICAgIGJvdHRvbSxcbiAgICAgIGksXG4gICAgICBqO1xuXG4gIC8vIElmIHRoZSB0cmVlIGlzIGVtcHR5LCBpbml0aWFsaXplIHRoZSByb290IGFzIGEgbGVhZi5cbiAgaWYgKCFub2RlKSByZXR1cm4gdHJlZS5fcm9vdCA9IGxlYWYsIHRyZWU7XG5cbiAgLy8gRmluZCB0aGUgZXhpc3RpbmcgbGVhZiBmb3IgdGhlIG5ldyBwb2ludCwgb3IgYWRkIGl0LlxuICB3aGlsZSAobm9kZS5sZW5ndGgpIHtcbiAgICBpZiAocmlnaHQgPSB4ID49ICh4bSA9ICh4MCArIHgxKSAvIDIpKSB4MCA9IHhtOyBlbHNlIHgxID0geG07XG4gICAgaWYgKGJvdHRvbSA9IHkgPj0gKHltID0gKHkwICsgeTEpIC8gMikpIHkwID0geW07IGVsc2UgeTEgPSB5bTtcbiAgICBpZiAocGFyZW50ID0gbm9kZSwgIShub2RlID0gbm9kZVtpID0gYm90dG9tIDw8IDEgfCByaWdodF0pKSByZXR1cm4gcGFyZW50W2ldID0gbGVhZiwgdHJlZTtcbiAgfVxuXG4gIC8vIElzIHRoZSBuZXcgcG9pbnQgaXMgZXhhY3RseSBjb2luY2lkZW50IHdpdGggdGhlIGV4aXN0aW5nIHBvaW50P1xuICB4cCA9ICt0cmVlLl94LmNhbGwobnVsbCwgbm9kZS5kYXRhKTtcbiAgeXAgPSArdHJlZS5feS5jYWxsKG51bGwsIG5vZGUuZGF0YSk7XG4gIGlmICh4ID09PSB4cCAmJiB5ID09PSB5cCkgcmV0dXJuIGxlYWYubmV4dCA9IG5vZGUsIHBhcmVudCA/IHBhcmVudFtpXSA9IGxlYWYgOiB0cmVlLl9yb290ID0gbGVhZiwgdHJlZTtcblxuICAvLyBPdGhlcndpc2UsIHNwbGl0IHRoZSBsZWFmIG5vZGUgdW50aWwgdGhlIG9sZCBhbmQgbmV3IHBvaW50IGFyZSBzZXBhcmF0ZWQuXG4gIGRvIHtcbiAgICBwYXJlbnQgPSBwYXJlbnQgPyBwYXJlbnRbaV0gPSBuZXcgQXJyYXkoNCkgOiB0cmVlLl9yb290ID0gbmV3IEFycmF5KDQpO1xuICAgIGlmIChyaWdodCA9IHggPj0gKHhtID0gKHgwICsgeDEpIC8gMikpIHgwID0geG07IGVsc2UgeDEgPSB4bTtcbiAgICBpZiAoYm90dG9tID0geSA+PSAoeW0gPSAoeTAgKyB5MSkgLyAyKSkgeTAgPSB5bTsgZWxzZSB5MSA9IHltO1xuICB9IHdoaWxlICgoaSA9IGJvdHRvbSA8PCAxIHwgcmlnaHQpID09PSAoaiA9ICh5cCA+PSB5bSkgPDwgMSB8ICh4cCA+PSB4bSkpKTtcbiAgcmV0dXJuIHBhcmVudFtqXSA9IG5vZGUsIHBhcmVudFtpXSA9IGxlYWYsIHRyZWU7XG59XG5cbmZ1bmN0aW9uIGFkZEFsbChkYXRhKSB7XG4gIHZhciBkLCBpLCBuID0gZGF0YS5sZW5ndGgsXG4gICAgICB4LFxuICAgICAgeSxcbiAgICAgIHh6ID0gbmV3IEFycmF5KG4pLFxuICAgICAgeXogPSBuZXcgQXJyYXkobiksXG4gICAgICB4MCA9IEluZmluaXR5LFxuICAgICAgeTAgPSBJbmZpbml0eSxcbiAgICAgIHgxID0gLUluZmluaXR5LFxuICAgICAgeTEgPSAtSW5maW5pdHk7XG5cbiAgLy8gQ29tcHV0ZSB0aGUgcG9pbnRzIGFuZCB0aGVpciBleHRlbnQuXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAoaXNOYU4oeCA9ICt0aGlzLl94LmNhbGwobnVsbCwgZCA9IGRhdGFbaV0pKSB8fCBpc05hTih5ID0gK3RoaXMuX3kuY2FsbChudWxsLCBkKSkpIGNvbnRpbnVlO1xuICAgIHh6W2ldID0geDtcbiAgICB5eltpXSA9IHk7XG4gICAgaWYgKHggPCB4MCkgeDAgPSB4O1xuICAgIGlmICh4ID4geDEpIHgxID0geDtcbiAgICBpZiAoeSA8IHkwKSB5MCA9IHk7XG4gICAgaWYgKHkgPiB5MSkgeTEgPSB5O1xuICB9XG5cbiAgLy8gSWYgdGhlcmUgd2VyZSBubyAodmFsaWQpIHBvaW50cywgaW5oZXJpdCB0aGUgZXhpc3RpbmcgZXh0ZW50LlxuICBpZiAoeDEgPCB4MCkgeDAgPSB0aGlzLl94MCwgeDEgPSB0aGlzLl94MTtcbiAgaWYgKHkxIDwgeTApIHkwID0gdGhpcy5feTAsIHkxID0gdGhpcy5feTE7XG5cbiAgLy8gRXhwYW5kIHRoZSB0cmVlIHRvIGNvdmVyIHRoZSBuZXcgcG9pbnRzLlxuICB0aGlzLmNvdmVyKHgwLCB5MCkuY292ZXIoeDEsIHkxKTtcblxuICAvLyBBZGQgdGhlIG5ldyBwb2ludHMuXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBhZGQodGhpcywgeHpbaV0sIHl6W2ldLCBkYXRhW2ldKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufVxuXG52YXIgdHJlZV9jb3ZlciA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgaWYgKGlzTmFOKHggPSAreCkgfHwgaXNOYU4oeSA9ICt5KSkgcmV0dXJuIHRoaXM7IC8vIGlnbm9yZSBpbnZhbGlkIHBvaW50c1xuXG4gIHZhciB4MCA9IHRoaXMuX3gwLFxuICAgICAgeTAgPSB0aGlzLl95MCxcbiAgICAgIHgxID0gdGhpcy5feDEsXG4gICAgICB5MSA9IHRoaXMuX3kxO1xuXG4gIC8vIElmIHRoZSBxdWFkdHJlZSBoYXMgbm8gZXh0ZW50LCBpbml0aWFsaXplIHRoZW0uXG4gIC8vIEludGVnZXIgZXh0ZW50IGFyZSBuZWNlc3Nhcnkgc28gdGhhdCBpZiB3ZSBsYXRlciBkb3VibGUgdGhlIGV4dGVudCxcbiAgLy8gdGhlIGV4aXN0aW5nIHF1YWRyYW50IGJvdW5kYXJpZXMgZG9u4oCZdCBjaGFuZ2UgZHVlIHRvIGZsb2F0aW5nIHBvaW50IGVycm9yIVxuICBpZiAoaXNOYU4oeDApKSB7XG4gICAgeDEgPSAoeDAgPSBNYXRoLmZsb29yKHgpKSArIDE7XG4gICAgeTEgPSAoeTAgPSBNYXRoLmZsb29yKHkpKSArIDE7XG4gIH1cblxuICAvLyBPdGhlcndpc2UsIGRvdWJsZSByZXBlYXRlZGx5IHRvIGNvdmVyLlxuICBlbHNlIGlmICh4MCA+IHggfHwgeCA+IHgxIHx8IHkwID4geSB8fCB5ID4geTEpIHtcbiAgICB2YXIgeiA9IHgxIC0geDAsXG4gICAgICAgIG5vZGUgPSB0aGlzLl9yb290LFxuICAgICAgICBwYXJlbnQsXG4gICAgICAgIGk7XG5cbiAgICBzd2l0Y2ggKGkgPSAoeSA8ICh5MCArIHkxKSAvIDIpIDw8IDEgfCAoeCA8ICh4MCArIHgxKSAvIDIpKSB7XG4gICAgICBjYXNlIDA6IHtcbiAgICAgICAgZG8gcGFyZW50ID0gbmV3IEFycmF5KDQpLCBwYXJlbnRbaV0gPSBub2RlLCBub2RlID0gcGFyZW50O1xuICAgICAgICB3aGlsZSAoeiAqPSAyLCB4MSA9IHgwICsgeiwgeTEgPSB5MCArIHosIHggPiB4MSB8fCB5ID4geTEpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMToge1xuICAgICAgICBkbyBwYXJlbnQgPSBuZXcgQXJyYXkoNCksIHBhcmVudFtpXSA9IG5vZGUsIG5vZGUgPSBwYXJlbnQ7XG4gICAgICAgIHdoaWxlICh6ICo9IDIsIHgwID0geDEgLSB6LCB5MSA9IHkwICsgeiwgeDAgPiB4IHx8IHkgPiB5MSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAyOiB7XG4gICAgICAgIGRvIHBhcmVudCA9IG5ldyBBcnJheSg0KSwgcGFyZW50W2ldID0gbm9kZSwgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgd2hpbGUgKHogKj0gMiwgeDEgPSB4MCArIHosIHkwID0geTEgLSB6LCB4ID4geDEgfHwgeTAgPiB5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDM6IHtcbiAgICAgICAgZG8gcGFyZW50ID0gbmV3IEFycmF5KDQpLCBwYXJlbnRbaV0gPSBub2RlLCBub2RlID0gcGFyZW50O1xuICAgICAgICB3aGlsZSAoeiAqPSAyLCB4MCA9IHgxIC0geiwgeTAgPSB5MSAtIHosIHgwID4geCB8fCB5MCA+IHkpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcm9vdCAmJiB0aGlzLl9yb290Lmxlbmd0aCkgdGhpcy5fcm9vdCA9IG5vZGU7XG4gIH1cblxuICAvLyBJZiB0aGUgcXVhZHRyZWUgY292ZXJzIHRoZSBwb2ludCBhbHJlYWR5LCBqdXN0IHJldHVybi5cbiAgZWxzZSByZXR1cm4gdGhpcztcblxuICB0aGlzLl94MCA9IHgwO1xuICB0aGlzLl95MCA9IHkwO1xuICB0aGlzLl94MSA9IHgxO1xuICB0aGlzLl95MSA9IHkxO1xuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciB0cmVlX2RhdGEgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGRhdGEgPSBbXTtcbiAgdGhpcy52aXNpdChmdW5jdGlvbihub2RlKSB7XG4gICAgaWYgKCFub2RlLmxlbmd0aCkgZG8gZGF0YS5wdXNoKG5vZGUuZGF0YSk7IHdoaWxlIChub2RlID0gbm9kZS5uZXh0KVxuICB9KTtcbiAgcmV0dXJuIGRhdGE7XG59O1xuXG52YXIgdHJlZV9leHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgICA/IHRoaXMuY292ZXIoK19bMF1bMF0sICtfWzBdWzFdKS5jb3ZlcigrX1sxXVswXSwgK19bMV1bMV0pXG4gICAgICA6IGlzTmFOKHRoaXMuX3gwKSA/IHVuZGVmaW5lZCA6IFtbdGhpcy5feDAsIHRoaXMuX3kwXSwgW3RoaXMuX3gxLCB0aGlzLl95MV1dO1xufTtcblxudmFyIFF1YWQgPSBmdW5jdGlvbihub2RlLCB4MCwgeTAsIHgxLCB5MSkge1xuICB0aGlzLm5vZGUgPSBub2RlO1xuICB0aGlzLngwID0geDA7XG4gIHRoaXMueTAgPSB5MDtcbiAgdGhpcy54MSA9IHgxO1xuICB0aGlzLnkxID0geTE7XG59O1xuXG52YXIgdHJlZV9maW5kID0gZnVuY3Rpb24oeCwgeSwgcmFkaXVzKSB7XG4gIHZhciBkYXRhLFxuICAgICAgeDAgPSB0aGlzLl94MCxcbiAgICAgIHkwID0gdGhpcy5feTAsXG4gICAgICB4MSxcbiAgICAgIHkxLFxuICAgICAgeDIsXG4gICAgICB5MixcbiAgICAgIHgzID0gdGhpcy5feDEsXG4gICAgICB5MyA9IHRoaXMuX3kxLFxuICAgICAgcXVhZHMgPSBbXSxcbiAgICAgIG5vZGUgPSB0aGlzLl9yb290LFxuICAgICAgcSxcbiAgICAgIGk7XG5cbiAgaWYgKG5vZGUpIHF1YWRzLnB1c2gobmV3IFF1YWQobm9kZSwgeDAsIHkwLCB4MywgeTMpKTtcbiAgaWYgKHJhZGl1cyA9PSBudWxsKSByYWRpdXMgPSBJbmZpbml0eTtcbiAgZWxzZSB7XG4gICAgeDAgPSB4IC0gcmFkaXVzLCB5MCA9IHkgLSByYWRpdXM7XG4gICAgeDMgPSB4ICsgcmFkaXVzLCB5MyA9IHkgKyByYWRpdXM7XG4gICAgcmFkaXVzICo9IHJhZGl1cztcbiAgfVxuXG4gIHdoaWxlIChxID0gcXVhZHMucG9wKCkpIHtcblxuICAgIC8vIFN0b3Agc2VhcmNoaW5nIGlmIHRoaXMgcXVhZHJhbnQgY2Fu4oCZdCBjb250YWluIGEgY2xvc2VyIG5vZGUuXG4gICAgaWYgKCEobm9kZSA9IHEubm9kZSlcbiAgICAgICAgfHwgKHgxID0gcS54MCkgPiB4M1xuICAgICAgICB8fCAoeTEgPSBxLnkwKSA+IHkzXG4gICAgICAgIHx8ICh4MiA9IHEueDEpIDwgeDBcbiAgICAgICAgfHwgKHkyID0gcS55MSkgPCB5MCkgY29udGludWU7XG5cbiAgICAvLyBCaXNlY3QgdGhlIGN1cnJlbnQgcXVhZHJhbnQuXG4gICAgaWYgKG5vZGUubGVuZ3RoKSB7XG4gICAgICB2YXIgeG0gPSAoeDEgKyB4MikgLyAyLFxuICAgICAgICAgIHltID0gKHkxICsgeTIpIC8gMjtcblxuICAgICAgcXVhZHMucHVzaChcbiAgICAgICAgbmV3IFF1YWQobm9kZVszXSwgeG0sIHltLCB4MiwgeTIpLFxuICAgICAgICBuZXcgUXVhZChub2RlWzJdLCB4MSwgeW0sIHhtLCB5MiksXG4gICAgICAgIG5ldyBRdWFkKG5vZGVbMV0sIHhtLCB5MSwgeDIsIHltKSxcbiAgICAgICAgbmV3IFF1YWQobm9kZVswXSwgeDEsIHkxLCB4bSwgeW0pXG4gICAgICApO1xuXG4gICAgICAvLyBWaXNpdCB0aGUgY2xvc2VzdCBxdWFkcmFudCBmaXJzdC5cbiAgICAgIGlmIChpID0gKHkgPj0geW0pIDw8IDEgfCAoeCA+PSB4bSkpIHtcbiAgICAgICAgcSA9IHF1YWRzW3F1YWRzLmxlbmd0aCAtIDFdO1xuICAgICAgICBxdWFkc1txdWFkcy5sZW5ndGggLSAxXSA9IHF1YWRzW3F1YWRzLmxlbmd0aCAtIDEgLSBpXTtcbiAgICAgICAgcXVhZHNbcXVhZHMubGVuZ3RoIC0gMSAtIGldID0gcTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWaXNpdCB0aGlzIHBvaW50LiAoVmlzaXRpbmcgY29pbmNpZGVudCBwb2ludHMgaXNu4oCZdCBuZWNlc3NhcnkhKVxuICAgIGVsc2Uge1xuICAgICAgdmFyIGR4ID0geCAtICt0aGlzLl94LmNhbGwobnVsbCwgbm9kZS5kYXRhKSxcbiAgICAgICAgICBkeSA9IHkgLSArdGhpcy5feS5jYWxsKG51bGwsIG5vZGUuZGF0YSksXG4gICAgICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgICAgIGlmIChkMiA8IHJhZGl1cykge1xuICAgICAgICB2YXIgZCA9IE1hdGguc3FydChyYWRpdXMgPSBkMik7XG4gICAgICAgIHgwID0geCAtIGQsIHkwID0geSAtIGQ7XG4gICAgICAgIHgzID0geCArIGQsIHkzID0geSArIGQ7XG4gICAgICAgIGRhdGEgPSBub2RlLmRhdGE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59O1xuXG52YXIgdHJlZV9yZW1vdmUgPSBmdW5jdGlvbihkKSB7XG4gIGlmIChpc05hTih4ID0gK3RoaXMuX3guY2FsbChudWxsLCBkKSkgfHwgaXNOYU4oeSA9ICt0aGlzLl95LmNhbGwobnVsbCwgZCkpKSByZXR1cm4gdGhpczsgLy8gaWdub3JlIGludmFsaWQgcG9pbnRzXG5cbiAgdmFyIHBhcmVudCxcbiAgICAgIG5vZGUgPSB0aGlzLl9yb290LFxuICAgICAgcmV0YWluZXIsXG4gICAgICBwcmV2aW91cyxcbiAgICAgIG5leHQsXG4gICAgICB4MCA9IHRoaXMuX3gwLFxuICAgICAgeTAgPSB0aGlzLl95MCxcbiAgICAgIHgxID0gdGhpcy5feDEsXG4gICAgICB5MSA9IHRoaXMuX3kxLFxuICAgICAgeCxcbiAgICAgIHksXG4gICAgICB4bSxcbiAgICAgIHltLFxuICAgICAgcmlnaHQsXG4gICAgICBib3R0b20sXG4gICAgICBpLFxuICAgICAgajtcblxuICAvLyBJZiB0aGUgdHJlZSBpcyBlbXB0eSwgaW5pdGlhbGl6ZSB0aGUgcm9vdCBhcyBhIGxlYWYuXG4gIGlmICghbm9kZSkgcmV0dXJuIHRoaXM7XG5cbiAgLy8gRmluZCB0aGUgbGVhZiBub2RlIGZvciB0aGUgcG9pbnQuXG4gIC8vIFdoaWxlIGRlc2NlbmRpbmcsIGFsc28gcmV0YWluIHRoZSBkZWVwZXN0IHBhcmVudCB3aXRoIGEgbm9uLXJlbW92ZWQgc2libGluZy5cbiAgaWYgKG5vZGUubGVuZ3RoKSB3aGlsZSAodHJ1ZSkge1xuICAgIGlmIChyaWdodCA9IHggPj0gKHhtID0gKHgwICsgeDEpIC8gMikpIHgwID0geG07IGVsc2UgeDEgPSB4bTtcbiAgICBpZiAoYm90dG9tID0geSA+PSAoeW0gPSAoeTAgKyB5MSkgLyAyKSkgeTAgPSB5bTsgZWxzZSB5MSA9IHltO1xuICAgIGlmICghKHBhcmVudCA9IG5vZGUsIG5vZGUgPSBub2RlW2kgPSBib3R0b20gPDwgMSB8IHJpZ2h0XSkpIHJldHVybiB0aGlzO1xuICAgIGlmICghbm9kZS5sZW5ndGgpIGJyZWFrO1xuICAgIGlmIChwYXJlbnRbKGkgKyAxKSAmIDNdIHx8IHBhcmVudFsoaSArIDIpICYgM10gfHwgcGFyZW50WyhpICsgMykgJiAzXSkgcmV0YWluZXIgPSBwYXJlbnQsIGogPSBpO1xuICB9XG5cbiAgLy8gRmluZCB0aGUgcG9pbnQgdG8gcmVtb3ZlLlxuICB3aGlsZSAobm9kZS5kYXRhICE9PSBkKSBpZiAoIShwcmV2aW91cyA9IG5vZGUsIG5vZGUgPSBub2RlLm5leHQpKSByZXR1cm4gdGhpcztcbiAgaWYgKG5leHQgPSBub2RlLm5leHQpIGRlbGV0ZSBub2RlLm5leHQ7XG5cbiAgLy8gSWYgdGhlcmUgYXJlIG11bHRpcGxlIGNvaW5jaWRlbnQgcG9pbnRzLCByZW1vdmUganVzdCB0aGUgcG9pbnQuXG4gIGlmIChwcmV2aW91cykgcmV0dXJuIChuZXh0ID8gcHJldmlvdXMubmV4dCA9IG5leHQgOiBkZWxldGUgcHJldmlvdXMubmV4dCksIHRoaXM7XG5cbiAgLy8gSWYgdGhpcyBpcyB0aGUgcm9vdCBwb2ludCwgcmVtb3ZlIGl0LlxuICBpZiAoIXBhcmVudCkgcmV0dXJuIHRoaXMuX3Jvb3QgPSBuZXh0LCB0aGlzO1xuXG4gIC8vIFJlbW92ZSB0aGlzIGxlYWYuXG4gIG5leHQgPyBwYXJlbnRbaV0gPSBuZXh0IDogZGVsZXRlIHBhcmVudFtpXTtcblxuICAvLyBJZiB0aGUgcGFyZW50IG5vdyBjb250YWlucyBleGFjdGx5IG9uZSBsZWFmLCBjb2xsYXBzZSBzdXBlcmZsdW91cyBwYXJlbnRzLlxuICBpZiAoKG5vZGUgPSBwYXJlbnRbMF0gfHwgcGFyZW50WzFdIHx8IHBhcmVudFsyXSB8fCBwYXJlbnRbM10pXG4gICAgICAmJiBub2RlID09PSAocGFyZW50WzNdIHx8IHBhcmVudFsyXSB8fCBwYXJlbnRbMV0gfHwgcGFyZW50WzBdKVxuICAgICAgJiYgIW5vZGUubGVuZ3RoKSB7XG4gICAgaWYgKHJldGFpbmVyKSByZXRhaW5lcltqXSA9IG5vZGU7XG4gICAgZWxzZSB0aGlzLl9yb290ID0gbm9kZTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gcmVtb3ZlQWxsKGRhdGEpIHtcbiAgZm9yICh2YXIgaSA9IDAsIG4gPSBkYXRhLmxlbmd0aDsgaSA8IG47ICsraSkgdGhpcy5yZW1vdmUoZGF0YVtpXSk7XG4gIHJldHVybiB0aGlzO1xufVxuXG52YXIgdHJlZV9yb290ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLl9yb290O1xufTtcblxudmFyIHRyZWVfc2l6ZSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc2l6ZSA9IDA7XG4gIHRoaXMudmlzaXQoZnVuY3Rpb24obm9kZSkge1xuICAgIGlmICghbm9kZS5sZW5ndGgpIGRvICsrc2l6ZTsgd2hpbGUgKG5vZGUgPSBub2RlLm5leHQpXG4gIH0pO1xuICByZXR1cm4gc2l6ZTtcbn07XG5cbnZhciB0cmVlX3Zpc2l0ID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdmFyIHF1YWRzID0gW10sIHEsIG5vZGUgPSB0aGlzLl9yb290LCBjaGlsZCwgeDAsIHkwLCB4MSwgeTE7XG4gIGlmIChub2RlKSBxdWFkcy5wdXNoKG5ldyBRdWFkKG5vZGUsIHRoaXMuX3gwLCB0aGlzLl95MCwgdGhpcy5feDEsIHRoaXMuX3kxKSk7XG4gIHdoaWxlIChxID0gcXVhZHMucG9wKCkpIHtcbiAgICBpZiAoIWNhbGxiYWNrKG5vZGUgPSBxLm5vZGUsIHgwID0gcS54MCwgeTAgPSBxLnkwLCB4MSA9IHEueDEsIHkxID0gcS55MSkgJiYgbm9kZS5sZW5ndGgpIHtcbiAgICAgIHZhciB4bSA9ICh4MCArIHgxKSAvIDIsIHltID0gKHkwICsgeTEpIC8gMjtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbM10pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHhtLCB5bSwgeDEsIHkxKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzJdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4MCwgeW0sIHhtLCB5MSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVsxXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeG0sIHkwLCB4MSwgeW0pKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMF0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHgwLCB5MCwgeG0sIHltKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxudmFyIHRyZWVfdmlzaXRBZnRlciA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gIHZhciBxdWFkcyA9IFtdLCBuZXh0ID0gW10sIHE7XG4gIGlmICh0aGlzLl9yb290KSBxdWFkcy5wdXNoKG5ldyBRdWFkKHRoaXMuX3Jvb3QsIHRoaXMuX3gwLCB0aGlzLl95MCwgdGhpcy5feDEsIHRoaXMuX3kxKSk7XG4gIHdoaWxlIChxID0gcXVhZHMucG9wKCkpIHtcbiAgICB2YXIgbm9kZSA9IHEubm9kZTtcbiAgICBpZiAobm9kZS5sZW5ndGgpIHtcbiAgICAgIHZhciBjaGlsZCwgeDAgPSBxLngwLCB5MCA9IHEueTAsIHgxID0gcS54MSwgeTEgPSBxLnkxLCB4bSA9ICh4MCArIHgxKSAvIDIsIHltID0gKHkwICsgeTEpIC8gMjtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMF0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHgwLCB5MCwgeG0sIHltKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzFdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4bSwgeTAsIHgxLCB5bSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVsyXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeDAsIHltLCB4bSwgeTEpKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbM10pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHhtLCB5bSwgeDEsIHkxKSk7XG4gICAgfVxuICAgIG5leHQucHVzaChxKTtcbiAgfVxuICB3aGlsZSAocSA9IG5leHQucG9wKCkpIHtcbiAgICBjYWxsYmFjayhxLm5vZGUsIHEueDAsIHEueTAsIHEueDEsIHEueTEpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gZGVmYXVsdFgoZCkge1xuICByZXR1cm4gZFswXTtcbn1cblxudmFyIHRyZWVfeCA9IGZ1bmN0aW9uKF8pIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGhpcy5feCA9IF8sIHRoaXMpIDogdGhpcy5feDtcbn07XG5cbmZ1bmN0aW9uIGRlZmF1bHRZKGQpIHtcbiAgcmV0dXJuIGRbMV07XG59XG5cbnZhciB0cmVlX3kgPSBmdW5jdGlvbihfKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRoaXMuX3kgPSBfLCB0aGlzKSA6IHRoaXMuX3k7XG59O1xuXG5mdW5jdGlvbiBxdWFkdHJlZShub2RlcywgeCwgeSkge1xuICB2YXIgdHJlZSA9IG5ldyBRdWFkdHJlZSh4ID09IG51bGwgPyBkZWZhdWx0WCA6IHgsIHkgPT0gbnVsbCA/IGRlZmF1bHRZIDogeSwgTmFOLCBOYU4sIE5hTiwgTmFOKTtcbiAgcmV0dXJuIG5vZGVzID09IG51bGwgPyB0cmVlIDogdHJlZS5hZGRBbGwobm9kZXMpO1xufVxuXG5mdW5jdGlvbiBRdWFkdHJlZSh4LCB5LCB4MCwgeTAsIHgxLCB5MSkge1xuICB0aGlzLl94ID0geDtcbiAgdGhpcy5feSA9IHk7XG4gIHRoaXMuX3gwID0geDA7XG4gIHRoaXMuX3kwID0geTA7XG4gIHRoaXMuX3gxID0geDE7XG4gIHRoaXMuX3kxID0geTE7XG4gIHRoaXMuX3Jvb3QgPSB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGxlYWZfY29weShsZWFmKSB7XG4gIHZhciBjb3B5ID0ge2RhdGE6IGxlYWYuZGF0YX0sIG5leHQgPSBjb3B5O1xuICB3aGlsZSAobGVhZiA9IGxlYWYubmV4dCkgbmV4dCA9IG5leHQubmV4dCA9IHtkYXRhOiBsZWFmLmRhdGF9O1xuICByZXR1cm4gY29weTtcbn1cblxudmFyIHRyZWVQcm90byA9IHF1YWR0cmVlLnByb3RvdHlwZSA9IFF1YWR0cmVlLnByb3RvdHlwZTtcblxudHJlZVByb3RvLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGNvcHkgPSBuZXcgUXVhZHRyZWUodGhpcy5feCwgdGhpcy5feSwgdGhpcy5feDAsIHRoaXMuX3kwLCB0aGlzLl94MSwgdGhpcy5feTEpLFxuICAgICAgbm9kZSA9IHRoaXMuX3Jvb3QsXG4gICAgICBub2RlcyxcbiAgICAgIGNoaWxkO1xuXG4gIGlmICghbm9kZSkgcmV0dXJuIGNvcHk7XG5cbiAgaWYgKCFub2RlLmxlbmd0aCkgcmV0dXJuIGNvcHkuX3Jvb3QgPSBsZWFmX2NvcHkobm9kZSksIGNvcHk7XG5cbiAgbm9kZXMgPSBbe3NvdXJjZTogbm9kZSwgdGFyZ2V0OiBjb3B5Ll9yb290ID0gbmV3IEFycmF5KDQpfV07XG4gIHdoaWxlIChub2RlID0gbm9kZXMucG9wKCkpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDQ7ICsraSkge1xuICAgICAgaWYgKGNoaWxkID0gbm9kZS5zb3VyY2VbaV0pIHtcbiAgICAgICAgaWYgKGNoaWxkLmxlbmd0aCkgbm9kZXMucHVzaCh7c291cmNlOiBjaGlsZCwgdGFyZ2V0OiBub2RlLnRhcmdldFtpXSA9IG5ldyBBcnJheSg0KX0pO1xuICAgICAgICBlbHNlIG5vZGUudGFyZ2V0W2ldID0gbGVhZl9jb3B5KGNoaWxkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29weTtcbn07XG5cbnRyZWVQcm90by5hZGQgPSB0cmVlX2FkZDtcbnRyZWVQcm90by5hZGRBbGwgPSBhZGRBbGw7XG50cmVlUHJvdG8uY292ZXIgPSB0cmVlX2NvdmVyO1xudHJlZVByb3RvLmRhdGEgPSB0cmVlX2RhdGE7XG50cmVlUHJvdG8uZXh0ZW50ID0gdHJlZV9leHRlbnQ7XG50cmVlUHJvdG8uZmluZCA9IHRyZWVfZmluZDtcbnRyZWVQcm90by5yZW1vdmUgPSB0cmVlX3JlbW92ZTtcbnRyZWVQcm90by5yZW1vdmVBbGwgPSByZW1vdmVBbGw7XG50cmVlUHJvdG8ucm9vdCA9IHRyZWVfcm9vdDtcbnRyZWVQcm90by5zaXplID0gdHJlZV9zaXplO1xudHJlZVByb3RvLnZpc2l0ID0gdHJlZV92aXNpdDtcbnRyZWVQcm90by52aXNpdEFmdGVyID0gdHJlZV92aXNpdEFmdGVyO1xudHJlZVByb3RvLnggPSB0cmVlX3g7XG50cmVlUHJvdG8ueSA9IHRyZWVfeTtcblxuZXhwb3J0cy5xdWFkdHJlZSA9IHF1YWR0cmVlO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy10aW1lci8gVmVyc2lvbiAxLjAuNy4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgZnJhbWUgPSAwO1xudmFyIHRpbWVvdXQgPSAwO1xudmFyIGludGVydmFsID0gMDtcbnZhciBwb2tlRGVsYXkgPSAxMDAwO1xudmFyIHRhc2tIZWFkO1xudmFyIHRhc2tUYWlsO1xudmFyIGNsb2NrTGFzdCA9IDA7XG52YXIgY2xvY2tOb3cgPSAwO1xudmFyIGNsb2NrU2tldyA9IDA7XG52YXIgY2xvY2sgPSB0eXBlb2YgcGVyZm9ybWFuY2UgPT09IFwib2JqZWN0XCIgJiYgcGVyZm9ybWFuY2Uubm93ID8gcGVyZm9ybWFuY2UgOiBEYXRlO1xudmFyIHNldEZyYW1lID0gdHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIiAmJiB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lID8gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZS5iaW5kKHdpbmRvdykgOiBmdW5jdGlvbihmKSB7IHNldFRpbWVvdXQoZiwgMTcpOyB9O1xuXG5mdW5jdGlvbiBub3coKSB7XG4gIHJldHVybiBjbG9ja05vdyB8fCAoc2V0RnJhbWUoY2xlYXJOb3cpLCBjbG9ja05vdyA9IGNsb2NrLm5vdygpICsgY2xvY2tTa2V3KTtcbn1cblxuZnVuY3Rpb24gY2xlYXJOb3coKSB7XG4gIGNsb2NrTm93ID0gMDtcbn1cblxuZnVuY3Rpb24gVGltZXIoKSB7XG4gIHRoaXMuX2NhbGwgPVxuICB0aGlzLl90aW1lID1cbiAgdGhpcy5fbmV4dCA9IG51bGw7XG59XG5cblRpbWVyLnByb3RvdHlwZSA9IHRpbWVyLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFRpbWVyLFxuICByZXN0YXJ0OiBmdW5jdGlvbihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvblwiKTtcbiAgICB0aW1lID0gKHRpbWUgPT0gbnVsbCA/IG5vdygpIDogK3RpbWUpICsgKGRlbGF5ID09IG51bGwgPyAwIDogK2RlbGF5KTtcbiAgICBpZiAoIXRoaXMuX25leHQgJiYgdGFza1RhaWwgIT09IHRoaXMpIHtcbiAgICAgIGlmICh0YXNrVGFpbCkgdGFza1RhaWwuX25leHQgPSB0aGlzO1xuICAgICAgZWxzZSB0YXNrSGVhZCA9IHRoaXM7XG4gICAgICB0YXNrVGFpbCA9IHRoaXM7XG4gICAgfVxuICAgIHRoaXMuX2NhbGwgPSBjYWxsYmFjaztcbiAgICB0aGlzLl90aW1lID0gdGltZTtcbiAgICBzbGVlcCgpO1xuICB9LFxuICBzdG9wOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fY2FsbCkge1xuICAgICAgdGhpcy5fY2FsbCA9IG51bGw7XG4gICAgICB0aGlzLl90aW1lID0gSW5maW5pdHk7XG4gICAgICBzbGVlcCgpO1xuICAgIH1cbiAgfVxufTtcblxuZnVuY3Rpb24gdGltZXIoY2FsbGJhY2ssIGRlbGF5LCB0aW1lKSB7XG4gIHZhciB0ID0gbmV3IFRpbWVyO1xuICB0LnJlc3RhcnQoY2FsbGJhY2ssIGRlbGF5LCB0aW1lKTtcbiAgcmV0dXJuIHQ7XG59XG5cbmZ1bmN0aW9uIHRpbWVyRmx1c2goKSB7XG4gIG5vdygpOyAvLyBHZXQgdGhlIGN1cnJlbnQgdGltZSwgaWYgbm90IGFscmVhZHkgc2V0LlxuICArK2ZyYW1lOyAvLyBQcmV0ZW5kIHdl4oCZdmUgc2V0IGFuIGFsYXJtLCBpZiB3ZSBoYXZlbuKAmXQgYWxyZWFkeS5cbiAgdmFyIHQgPSB0YXNrSGVhZCwgZTtcbiAgd2hpbGUgKHQpIHtcbiAgICBpZiAoKGUgPSBjbG9ja05vdyAtIHQuX3RpbWUpID49IDApIHQuX2NhbGwuY2FsbChudWxsLCBlKTtcbiAgICB0ID0gdC5fbmV4dDtcbiAgfVxuICAtLWZyYW1lO1xufVxuXG5mdW5jdGlvbiB3YWtlKCkge1xuICBjbG9ja05vdyA9IChjbG9ja0xhc3QgPSBjbG9jay5ub3coKSkgKyBjbG9ja1NrZXc7XG4gIGZyYW1lID0gdGltZW91dCA9IDA7XG4gIHRyeSB7XG4gICAgdGltZXJGbHVzaCgpO1xuICB9IGZpbmFsbHkge1xuICAgIGZyYW1lID0gMDtcbiAgICBuYXAoKTtcbiAgICBjbG9ja05vdyA9IDA7XG4gIH1cbn1cblxuZnVuY3Rpb24gcG9rZSgpIHtcbiAgdmFyIG5vdyA9IGNsb2NrLm5vdygpLCBkZWxheSA9IG5vdyAtIGNsb2NrTGFzdDtcbiAgaWYgKGRlbGF5ID4gcG9rZURlbGF5KSBjbG9ja1NrZXcgLT0gZGVsYXksIGNsb2NrTGFzdCA9IG5vdztcbn1cblxuZnVuY3Rpb24gbmFwKCkge1xuICB2YXIgdDAsIHQxID0gdGFza0hlYWQsIHQyLCB0aW1lID0gSW5maW5pdHk7XG4gIHdoaWxlICh0MSkge1xuICAgIGlmICh0MS5fY2FsbCkge1xuICAgICAgaWYgKHRpbWUgPiB0MS5fdGltZSkgdGltZSA9IHQxLl90aW1lO1xuICAgICAgdDAgPSB0MSwgdDEgPSB0MS5fbmV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdDIgPSB0MS5fbmV4dCwgdDEuX25leHQgPSBudWxsO1xuICAgICAgdDEgPSB0MCA/IHQwLl9uZXh0ID0gdDIgOiB0YXNrSGVhZCA9IHQyO1xuICAgIH1cbiAgfVxuICB0YXNrVGFpbCA9IHQwO1xuICBzbGVlcCh0aW1lKTtcbn1cblxuZnVuY3Rpb24gc2xlZXAodGltZSkge1xuICBpZiAoZnJhbWUpIHJldHVybjsgLy8gU29vbmVzdCBhbGFybSBhbHJlYWR5IHNldCwgb3Igd2lsbCBiZS5cbiAgaWYgKHRpbWVvdXQpIHRpbWVvdXQgPSBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gIHZhciBkZWxheSA9IHRpbWUgLSBjbG9ja05vdzsgLy8gU3RyaWN0bHkgbGVzcyB0aGFuIGlmIHdlIHJlY29tcHV0ZWQgY2xvY2tOb3cuXG4gIGlmIChkZWxheSA+IDI0KSB7XG4gICAgaWYgKHRpbWUgPCBJbmZpbml0eSkgdGltZW91dCA9IHNldFRpbWVvdXQod2FrZSwgdGltZSAtIGNsb2NrLm5vdygpIC0gY2xvY2tTa2V3KTtcbiAgICBpZiAoaW50ZXJ2YWwpIGludGVydmFsID0gY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFpbnRlcnZhbCkgY2xvY2tMYXN0ID0gY2xvY2subm93KCksIGludGVydmFsID0gc2V0SW50ZXJ2YWwocG9rZSwgcG9rZURlbGF5KTtcbiAgICBmcmFtZSA9IDEsIHNldEZyYW1lKHdha2UpO1xuICB9XG59XG5cbnZhciB0aW1lb3V0JDEgPSBmdW5jdGlvbihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgdmFyIHQgPSBuZXcgVGltZXI7XG4gIGRlbGF5ID0gZGVsYXkgPT0gbnVsbCA/IDAgOiArZGVsYXk7XG4gIHQucmVzdGFydChmdW5jdGlvbihlbGFwc2VkKSB7XG4gICAgdC5zdG9wKCk7XG4gICAgY2FsbGJhY2soZWxhcHNlZCArIGRlbGF5KTtcbiAgfSwgZGVsYXksIHRpbWUpO1xuICByZXR1cm4gdDtcbn07XG5cbnZhciBpbnRlcnZhbCQxID0gZnVuY3Rpb24oY2FsbGJhY2ssIGRlbGF5LCB0aW1lKSB7XG4gIHZhciB0ID0gbmV3IFRpbWVyLCB0b3RhbCA9IGRlbGF5O1xuICBpZiAoZGVsYXkgPT0gbnVsbCkgcmV0dXJuIHQucmVzdGFydChjYWxsYmFjaywgZGVsYXksIHRpbWUpLCB0O1xuICBkZWxheSA9ICtkZWxheSwgdGltZSA9IHRpbWUgPT0gbnVsbCA/IG5vdygpIDogK3RpbWU7XG4gIHQucmVzdGFydChmdW5jdGlvbiB0aWNrKGVsYXBzZWQpIHtcbiAgICBlbGFwc2VkICs9IHRvdGFsO1xuICAgIHQucmVzdGFydCh0aWNrLCB0b3RhbCArPSBkZWxheSwgdGltZSk7XG4gICAgY2FsbGJhY2soZWxhcHNlZCk7XG4gIH0sIGRlbGF5LCB0aW1lKTtcbiAgcmV0dXJuIHQ7XG59O1xuXG5leHBvcnRzLm5vdyA9IG5vdztcbmV4cG9ydHMudGltZXIgPSB0aW1lcjtcbmV4cG9ydHMudGltZXJGbHVzaCA9IHRpbWVyRmx1c2g7XG5leHBvcnRzLnRpbWVvdXQgPSB0aW1lb3V0JDE7XG5leHBvcnRzLmludGVydmFsID0gaW50ZXJ2YWwkMTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIiFmdW5jdGlvbigpIHtcbiAgdmFyIGQzID0ge1xuICAgIHZlcnNpb246IFwiMy41LjE3XCJcbiAgfTtcbiAgdmFyIGQzX2FycmF5U2xpY2UgPSBbXS5zbGljZSwgZDNfYXJyYXkgPSBmdW5jdGlvbihsaXN0KSB7XG4gICAgcmV0dXJuIGQzX2FycmF5U2xpY2UuY2FsbChsaXN0KTtcbiAgfTtcbiAgdmFyIGQzX2RvY3VtZW50ID0gdGhpcy5kb2N1bWVudDtcbiAgZnVuY3Rpb24gZDNfZG9jdW1lbnRFbGVtZW50KG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZSAmJiAobm9kZS5vd25lckRvY3VtZW50IHx8IG5vZGUuZG9jdW1lbnQgfHwgbm9kZSkuZG9jdW1lbnRFbGVtZW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3dpbmRvdyhub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUgJiYgKG5vZGUub3duZXJEb2N1bWVudCAmJiBub2RlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgfHwgbm9kZS5kb2N1bWVudCAmJiBub2RlIHx8IG5vZGUuZGVmYXVsdFZpZXcpO1xuICB9XG4gIGlmIChkM19kb2N1bWVudCkge1xuICAgIHRyeSB7XG4gICAgICBkM19hcnJheShkM19kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2hpbGROb2RlcylbMF0ubm9kZVR5cGU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZDNfYXJyYXkgPSBmdW5jdGlvbihsaXN0KSB7XG4gICAgICAgIHZhciBpID0gbGlzdC5sZW5ndGgsIGFycmF5ID0gbmV3IEFycmF5KGkpO1xuICAgICAgICB3aGlsZSAoaS0tKSBhcnJheVtpXSA9IGxpc3RbaV07XG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICAgIH07XG4gICAgfVxuICB9XG4gIGlmICghRGF0ZS5ub3cpIERhdGUubm93ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZSgpO1xuICB9O1xuICBpZiAoZDNfZG9jdW1lbnQpIHtcbiAgICB0cnkge1xuICAgICAgZDNfZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIkRJVlwiKS5zdHlsZS5zZXRQcm9wZXJ0eShcIm9wYWNpdHlcIiwgMCwgXCJcIik7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHZhciBkM19lbGVtZW50X3Byb3RvdHlwZSA9IHRoaXMuRWxlbWVudC5wcm90b3R5cGUsIGQzX2VsZW1lbnRfc2V0QXR0cmlidXRlID0gZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlLCBkM19lbGVtZW50X3NldEF0dHJpYnV0ZU5TID0gZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlTlMsIGQzX3N0eWxlX3Byb3RvdHlwZSA9IHRoaXMuQ1NTU3R5bGVEZWNsYXJhdGlvbi5wcm90b3R5cGUsIGQzX3N0eWxlX3NldFByb3BlcnR5ID0gZDNfc3R5bGVfcHJvdG90eXBlLnNldFByb3BlcnR5O1xuICAgICAgZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICAgICAgZDNfZWxlbWVudF9zZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lLCB2YWx1ZSArIFwiXCIpO1xuICAgICAgfTtcbiAgICAgIGQzX2VsZW1lbnRfcHJvdG90eXBlLnNldEF0dHJpYnV0ZU5TID0gZnVuY3Rpb24oc3BhY2UsIGxvY2FsLCB2YWx1ZSkge1xuICAgICAgICBkM19lbGVtZW50X3NldEF0dHJpYnV0ZU5TLmNhbGwodGhpcywgc3BhY2UsIGxvY2FsLCB2YWx1ZSArIFwiXCIpO1xuICAgICAgfTtcbiAgICAgIGQzX3N0eWxlX3Byb3RvdHlwZS5zZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBwcmlvcml0eSkge1xuICAgICAgICBkM19zdHlsZV9zZXRQcm9wZXJ0eS5jYWxsKHRoaXMsIG5hbWUsIHZhbHVlICsgXCJcIiwgcHJpb3JpdHkpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgZDMuYXNjZW5kaW5nID0gZDNfYXNjZW5kaW5nO1xuICBmdW5jdGlvbiBkM19hc2NlbmRpbmcoYSwgYikge1xuICAgIHJldHVybiBhIDwgYiA/IC0xIDogYSA+IGIgPyAxIDogYSA+PSBiID8gMCA6IE5hTjtcbiAgfVxuICBkMy5kZXNjZW5kaW5nID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBiIDwgYSA/IC0xIDogYiA+IGEgPyAxIDogYiA+PSBhID8gMCA6IE5hTjtcbiAgfTtcbiAgZDMubWluID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgaSA9IC0xLCBuID0gYXJyYXkubGVuZ3RoLCBhLCBiO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gYXJyYXlbaV0pICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCAmJiBhID4gYikgYSA9IGI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBmLmNhbGwoYXJyYXksIGFycmF5W2ldLCBpKSkgIT0gbnVsbCAmJiBiID49IGIpIHtcbiAgICAgICAgYSA9IGI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICgoYiA9IGYuY2FsbChhcnJheSwgYXJyYXlbaV0sIGkpKSAhPSBudWxsICYmIGEgPiBiKSBhID0gYjtcbiAgICB9XG4gICAgcmV0dXJuIGE7XG4gIH07XG4gIGQzLm1heCA9IGZ1bmN0aW9uKGFycmF5LCBmKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGFycmF5Lmxlbmd0aCwgYSwgYjtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICgoYiA9IGFycmF5W2ldKSAhPSBudWxsICYmIGIgPj0gYikge1xuICAgICAgICBhID0gYjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gYXJyYXlbaV0pICE9IG51bGwgJiYgYiA+IGEpIGEgPSBiO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBmLmNhbGwoYXJyYXksIGFycmF5W2ldLCBpKSkgIT0gbnVsbCAmJiBiID4gYSkgYSA9IGI7XG4gICAgfVxuICAgIHJldHVybiBhO1xuICB9O1xuICBkMy5leHRlbnQgPSBmdW5jdGlvbihhcnJheSwgZikge1xuICAgIHZhciBpID0gLTEsIG4gPSBhcnJheS5sZW5ndGgsIGEsIGIsIGM7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCAmJiBiID49IGIpIHtcbiAgICAgICAgYSA9IGMgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCkge1xuICAgICAgICBpZiAoYSA+IGIpIGEgPSBiO1xuICAgICAgICBpZiAoYyA8IGIpIGMgPSBiO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBjID0gYjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwpIHtcbiAgICAgICAgaWYgKGEgPiBiKSBhID0gYjtcbiAgICAgICAgaWYgKGMgPCBiKSBjID0gYjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFsgYSwgYyBdO1xuICB9O1xuICBmdW5jdGlvbiBkM19udW1iZXIoeCkge1xuICAgIHJldHVybiB4ID09PSBudWxsID8gTmFOIDogK3g7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbnVtZXJpYyh4KSB7XG4gICAgcmV0dXJuICFpc05hTih4KTtcbiAgfVxuICBkMy5zdW0gPSBmdW5jdGlvbihhcnJheSwgZikge1xuICAgIHZhciBzID0gMCwgbiA9IGFycmF5Lmxlbmd0aCwgYSwgaSA9IC0xO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKGQzX251bWVyaWMoYSA9ICthcnJheVtpXSkpIHMgKz0gYTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmIChkM19udW1lcmljKGEgPSArZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSBzICs9IGE7XG4gICAgfVxuICAgIHJldHVybiBzO1xuICB9O1xuICBkMy5tZWFuID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgcyA9IDAsIG4gPSBhcnJheS5sZW5ndGgsIGEsIGkgPSAtMSwgaiA9IG47XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGFycmF5W2ldKSkpIHMgKz0gYTsgZWxzZSAtLWo7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGYuY2FsbChhcnJheSwgYXJyYXlbaV0sIGkpKSkpIHMgKz0gYTsgZWxzZSAtLWo7XG4gICAgfVxuICAgIGlmIChqKSByZXR1cm4gcyAvIGo7XG4gIH07XG4gIGQzLnF1YW50aWxlID0gZnVuY3Rpb24odmFsdWVzLCBwKSB7XG4gICAgdmFyIEggPSAodmFsdWVzLmxlbmd0aCAtIDEpICogcCArIDEsIGggPSBNYXRoLmZsb29yKEgpLCB2ID0gK3ZhbHVlc1toIC0gMV0sIGUgPSBIIC0gaDtcbiAgICByZXR1cm4gZSA/IHYgKyBlICogKHZhbHVlc1toXSAtIHYpIDogdjtcbiAgfTtcbiAgZDMubWVkaWFuID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgbnVtYmVycyA9IFtdLCBuID0gYXJyYXkubGVuZ3RoLCBhLCBpID0gLTE7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGFycmF5W2ldKSkpIG51bWJlcnMucHVzaChhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmIChkM19udW1lcmljKGEgPSBkM19udW1iZXIoZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSkgbnVtYmVycy5wdXNoKGEpO1xuICAgIH1cbiAgICBpZiAobnVtYmVycy5sZW5ndGgpIHJldHVybiBkMy5xdWFudGlsZShudW1iZXJzLnNvcnQoZDNfYXNjZW5kaW5nKSwgLjUpO1xuICB9O1xuICBkMy52YXJpYW5jZSA9IGZ1bmN0aW9uKGFycmF5LCBmKSB7XG4gICAgdmFyIG4gPSBhcnJheS5sZW5ndGgsIG0gPSAwLCBhLCBkLCBzID0gMCwgaSA9IC0xLCBqID0gMDtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgaWYgKGQzX251bWVyaWMoYSA9IGQzX251bWJlcihhcnJheVtpXSkpKSB7XG4gICAgICAgICAgZCA9IGEgLSBtO1xuICAgICAgICAgIG0gKz0gZCAvICsrajtcbiAgICAgICAgICBzICs9IGQgKiAoYSAtIG0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkM19udW1lcmljKGEgPSBkM19udW1iZXIoZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSkge1xuICAgICAgICAgIGQgPSBhIC0gbTtcbiAgICAgICAgICBtICs9IGQgLyArK2o7XG4gICAgICAgICAgcyArPSBkICogKGEgLSBtKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaiA+IDEpIHJldHVybiBzIC8gKGogLSAxKTtcbiAgfTtcbiAgZDMuZGV2aWF0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHYgPSBkMy52YXJpYW5jZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiB2ID8gTWF0aC5zcXJ0KHYpIDogdjtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfYmlzZWN0b3IoY29tcGFyZSkge1xuICAgIHJldHVybiB7XG4gICAgICBsZWZ0OiBmdW5jdGlvbihhLCB4LCBsbywgaGkpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBsbyA9IDA7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgNCkgaGkgPSBhLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGxvIDwgaGkpIHtcbiAgICAgICAgICB2YXIgbWlkID0gbG8gKyBoaSA+Pj4gMTtcbiAgICAgICAgICBpZiAoY29tcGFyZShhW21pZF0sIHgpIDwgMCkgbG8gPSBtaWQgKyAxOyBlbHNlIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsbztcbiAgICAgIH0sXG4gICAgICByaWdodDogZnVuY3Rpb24oYSwgeCwgbG8sIGhpKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgbG8gPSAwO1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDQpIGhpID0gYS5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICAgICAgdmFyIG1pZCA9IGxvICsgaGkgPj4+IDE7XG4gICAgICAgICAgaWYgKGNvbXBhcmUoYVttaWRdLCB4KSA+IDApIGhpID0gbWlkOyBlbHNlIGxvID0gbWlkICsgMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG87XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICB2YXIgZDNfYmlzZWN0ID0gZDNfYmlzZWN0b3IoZDNfYXNjZW5kaW5nKTtcbiAgZDMuYmlzZWN0TGVmdCA9IGQzX2Jpc2VjdC5sZWZ0O1xuICBkMy5iaXNlY3QgPSBkMy5iaXNlY3RSaWdodCA9IGQzX2Jpc2VjdC5yaWdodDtcbiAgZDMuYmlzZWN0b3IgPSBmdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIGQzX2Jpc2VjdG9yKGYubGVuZ3RoID09PSAxID8gZnVuY3Rpb24oZCwgeCkge1xuICAgICAgcmV0dXJuIGQzX2FzY2VuZGluZyhmKGQpLCB4KTtcbiAgICB9IDogZik7XG4gIH07XG4gIGQzLnNodWZmbGUgPSBmdW5jdGlvbihhcnJheSwgaTAsIGkxKSB7XG4gICAgaWYgKChtID0gYXJndW1lbnRzLmxlbmd0aCkgPCAzKSB7XG4gICAgICBpMSA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmIChtIDwgMikgaTAgPSAwO1xuICAgIH1cbiAgICB2YXIgbSA9IGkxIC0gaTAsIHQsIGk7XG4gICAgd2hpbGUgKG0pIHtcbiAgICAgIGkgPSBNYXRoLnJhbmRvbSgpICogbS0tIHwgMDtcbiAgICAgIHQgPSBhcnJheVttICsgaTBdLCBhcnJheVttICsgaTBdID0gYXJyYXlbaSArIGkwXSwgYXJyYXlbaSArIGkwXSA9IHQ7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfTtcbiAgZDMucGVybXV0ZSA9IGZ1bmN0aW9uKGFycmF5LCBpbmRleGVzKSB7XG4gICAgdmFyIGkgPSBpbmRleGVzLmxlbmd0aCwgcGVybXV0ZXMgPSBuZXcgQXJyYXkoaSk7XG4gICAgd2hpbGUgKGktLSkgcGVybXV0ZXNbaV0gPSBhcnJheVtpbmRleGVzW2ldXTtcbiAgICByZXR1cm4gcGVybXV0ZXM7XG4gIH07XG4gIGQzLnBhaXJzID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgaSA9IDAsIG4gPSBhcnJheS5sZW5ndGggLSAxLCBwMCwgcDEgPSBhcnJheVswXSwgcGFpcnMgPSBuZXcgQXJyYXkobiA8IDAgPyAwIDogbik7XG4gICAgd2hpbGUgKGkgPCBuKSBwYWlyc1tpXSA9IFsgcDAgPSBwMSwgcDEgPSBhcnJheVsrK2ldIF07XG4gICAgcmV0dXJuIHBhaXJzO1xuICB9O1xuICBkMy50cmFuc3Bvc2UgPSBmdW5jdGlvbihtYXRyaXgpIHtcbiAgICBpZiAoIShuID0gbWF0cml4Lmxlbmd0aCkpIHJldHVybiBbXTtcbiAgICBmb3IgKHZhciBpID0gLTEsIG0gPSBkMy5taW4obWF0cml4LCBkM190cmFuc3Bvc2VMZW5ndGgpLCB0cmFuc3Bvc2UgPSBuZXcgQXJyYXkobSk7ICsraSA8IG07ICkge1xuICAgICAgZm9yICh2YXIgaiA9IC0xLCBuLCByb3cgPSB0cmFuc3Bvc2VbaV0gPSBuZXcgQXJyYXkobik7ICsraiA8IG47ICkge1xuICAgICAgICByb3dbal0gPSBtYXRyaXhbal1baV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cmFuc3Bvc2U7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zcG9zZUxlbmd0aChkKSB7XG4gICAgcmV0dXJuIGQubGVuZ3RoO1xuICB9XG4gIGQzLnppcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkMy50cmFuc3Bvc2UoYXJndW1lbnRzKTtcbiAgfTtcbiAgZDMua2V5cyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG1hcCkga2V5cy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG4gIGQzLnZhbHVlcyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gbWFwKSB2YWx1ZXMucHVzaChtYXBba2V5XSk7XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfTtcbiAgZDMuZW50cmllcyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciBlbnRyaWVzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG1hcCkgZW50cmllcy5wdXNoKHtcbiAgICAgIGtleToga2V5LFxuICAgICAgdmFsdWU6IG1hcFtrZXldXG4gICAgfSk7XG4gICAgcmV0dXJuIGVudHJpZXM7XG4gIH07XG4gIGQzLm1lcmdlID0gZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgdmFyIG4gPSBhcnJheXMubGVuZ3RoLCBtLCBpID0gLTEsIGogPSAwLCBtZXJnZWQsIGFycmF5O1xuICAgIHdoaWxlICgrK2kgPCBuKSBqICs9IGFycmF5c1tpXS5sZW5ndGg7XG4gICAgbWVyZ2VkID0gbmV3IEFycmF5KGopO1xuICAgIHdoaWxlICgtLW4gPj0gMCkge1xuICAgICAgYXJyYXkgPSBhcnJheXNbbl07XG4gICAgICBtID0gYXJyYXkubGVuZ3RoO1xuICAgICAgd2hpbGUgKC0tbSA+PSAwKSB7XG4gICAgICAgIG1lcmdlZFstLWpdID0gYXJyYXlbbV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtZXJnZWQ7XG4gIH07XG4gIHZhciBhYnMgPSBNYXRoLmFicztcbiAgZDMucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykge1xuICAgICAgc3RlcCA9IDE7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgc3RvcCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXAgPT09IEluZmluaXR5KSB0aHJvdyBuZXcgRXJyb3IoXCJpbmZpbml0ZSByYW5nZVwiKTtcbiAgICB2YXIgcmFuZ2UgPSBbXSwgayA9IGQzX3JhbmdlX2ludGVnZXJTY2FsZShhYnMoc3RlcCkpLCBpID0gLTEsIGo7XG4gICAgc3RhcnQgKj0gaywgc3RvcCAqPSBrLCBzdGVwICo9IGs7XG4gICAgaWYgKHN0ZXAgPCAwKSB3aGlsZSAoKGogPSBzdGFydCArIHN0ZXAgKiArK2kpID4gc3RvcCkgcmFuZ2UucHVzaChqIC8gayk7IGVsc2Ugd2hpbGUgKChqID0gc3RhcnQgKyBzdGVwICogKytpKSA8IHN0b3ApIHJhbmdlLnB1c2goaiAvIGspO1xuICAgIHJldHVybiByYW5nZTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfcmFuZ2VfaW50ZWdlclNjYWxlKHgpIHtcbiAgICB2YXIgayA9IDE7XG4gICAgd2hpbGUgKHggKiBrICUgMSkgayAqPSAxMDtcbiAgICByZXR1cm4gaztcbiAgfVxuICBmdW5jdGlvbiBkM19jbGFzcyhjdG9yLCBwcm9wZXJ0aWVzKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHByb3BlcnRpZXMpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdG9yLnByb3RvdHlwZSwga2V5LCB7XG4gICAgICAgIHZhbHVlOiBwcm9wZXJ0aWVzW2tleV0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgZDMubWFwID0gZnVuY3Rpb24ob2JqZWN0LCBmKSB7XG4gICAgdmFyIG1hcCA9IG5ldyBkM19NYXAoKTtcbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgZDNfTWFwKSB7XG4gICAgICBvYmplY3QuZm9yRWFjaChmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgICAgIG1hcC5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IG9iamVjdC5sZW5ndGgsIG87XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgd2hpbGUgKCsraSA8IG4pIG1hcC5zZXQoaSwgb2JqZWN0W2ldKTsgZWxzZSB3aGlsZSAoKytpIDwgbikgbWFwLnNldChmLmNhbGwob2JqZWN0LCBvID0gb2JqZWN0W2ldLCBpKSwgbyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIG1hcC5zZXQoa2V5LCBvYmplY3Rba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiBtYXA7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX01hcCgpIHtcbiAgICB0aGlzLl8gPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG4gIHZhciBkM19tYXBfcHJvdG8gPSBcIl9fcHJvdG9fX1wiLCBkM19tYXBfemVybyA9IFwiXFx4MDBcIjtcbiAgZDNfY2xhc3MoZDNfTWFwLCB7XG4gICAgaGFzOiBkM19tYXBfaGFzLFxuICAgIGdldDogZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gdGhpcy5fW2QzX21hcF9lc2NhcGUoa2V5KV07XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9bZDNfbWFwX2VzY2FwZShrZXkpXSA9IHZhbHVlO1xuICAgIH0sXG4gICAgcmVtb3ZlOiBkM19tYXBfcmVtb3ZlLFxuICAgIGtleXM6IGQzX21hcF9rZXlzLFxuICAgIHZhbHVlczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdmFsdWVzID0gW107XG4gICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSB2YWx1ZXMucHVzaCh0aGlzLl9ba2V5XSk7XG4gICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH0sXG4gICAgZW50cmllczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZW50cmllcyA9IFtdO1xuICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykgZW50cmllcy5wdXNoKHtcbiAgICAgICAga2V5OiBkM19tYXBfdW5lc2NhcGUoa2V5KSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX1trZXldXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBlbnRyaWVzO1xuICAgIH0sXG4gICAgc2l6ZTogZDNfbWFwX3NpemUsXG4gICAgZW1wdHk6IGQzX21hcF9lbXB0eSxcbiAgICBmb3JFYWNoOiBmdW5jdGlvbihmKSB7XG4gICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSBmLmNhbGwodGhpcywgZDNfbWFwX3VuZXNjYXBlKGtleSksIHRoaXMuX1trZXldKTtcbiAgICB9XG4gIH0pO1xuICBmdW5jdGlvbiBkM19tYXBfZXNjYXBlKGtleSkge1xuICAgIHJldHVybiAoa2V5ICs9IFwiXCIpID09PSBkM19tYXBfcHJvdG8gfHwga2V5WzBdID09PSBkM19tYXBfemVybyA/IGQzX21hcF96ZXJvICsga2V5IDoga2V5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF91bmVzY2FwZShrZXkpIHtcbiAgICByZXR1cm4gKGtleSArPSBcIlwiKVswXSA9PT0gZDNfbWFwX3plcm8gPyBrZXkuc2xpY2UoMSkgOiBrZXk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbWFwX2hhcyhrZXkpIHtcbiAgICByZXR1cm4gZDNfbWFwX2VzY2FwZShrZXkpIGluIHRoaXMuXztcbiAgfVxuICBmdW5jdGlvbiBkM19tYXBfcmVtb3ZlKGtleSkge1xuICAgIHJldHVybiAoa2V5ID0gZDNfbWFwX2VzY2FwZShrZXkpKSBpbiB0aGlzLl8gJiYgZGVsZXRlIHRoaXMuX1trZXldO1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF9rZXlzKCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykga2V5cy5wdXNoKGQzX21hcF91bmVzY2FwZShrZXkpKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfVxuICBmdW5jdGlvbiBkM19tYXBfc2l6ZSgpIHtcbiAgICB2YXIgc2l6ZSA9IDA7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykgKytzaXplO1xuICAgIHJldHVybiBzaXplO1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF9lbXB0eSgpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZDMubmVzdCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBuZXN0ID0ge30sIGtleXMgPSBbXSwgc29ydEtleXMgPSBbXSwgc29ydFZhbHVlcywgcm9sbHVwO1xuICAgIGZ1bmN0aW9uIG1hcChtYXBUeXBlLCBhcnJheSwgZGVwdGgpIHtcbiAgICAgIGlmIChkZXB0aCA+PSBrZXlzLmxlbmd0aCkgcmV0dXJuIHJvbGx1cCA/IHJvbGx1cC5jYWxsKG5lc3QsIGFycmF5KSA6IHNvcnRWYWx1ZXMgPyBhcnJheS5zb3J0KHNvcnRWYWx1ZXMpIDogYXJyYXk7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gYXJyYXkubGVuZ3RoLCBrZXkgPSBrZXlzW2RlcHRoKytdLCBrZXlWYWx1ZSwgb2JqZWN0LCBzZXR0ZXIsIHZhbHVlc0J5S2V5ID0gbmV3IGQzX01hcCgpLCB2YWx1ZXM7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBpZiAodmFsdWVzID0gdmFsdWVzQnlLZXkuZ2V0KGtleVZhbHVlID0ga2V5KG9iamVjdCA9IGFycmF5W2ldKSkpIHtcbiAgICAgICAgICB2YWx1ZXMucHVzaChvYmplY3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlc0J5S2V5LnNldChrZXlWYWx1ZSwgWyBvYmplY3QgXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChtYXBUeXBlKSB7XG4gICAgICAgIG9iamVjdCA9IG1hcFR5cGUoKTtcbiAgICAgICAgc2V0dGVyID0gZnVuY3Rpb24oa2V5VmFsdWUsIHZhbHVlcykge1xuICAgICAgICAgIG9iamVjdC5zZXQoa2V5VmFsdWUsIG1hcChtYXBUeXBlLCB2YWx1ZXMsIGRlcHRoKSk7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmplY3QgPSB7fTtcbiAgICAgICAgc2V0dGVyID0gZnVuY3Rpb24oa2V5VmFsdWUsIHZhbHVlcykge1xuICAgICAgICAgIG9iamVjdFtrZXlWYWx1ZV0gPSBtYXAobWFwVHlwZSwgdmFsdWVzLCBkZXB0aCk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICB2YWx1ZXNCeUtleS5mb3JFYWNoKHNldHRlcik7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbnRyaWVzKG1hcCwgZGVwdGgpIHtcbiAgICAgIGlmIChkZXB0aCA+PSBrZXlzLmxlbmd0aCkgcmV0dXJuIG1hcDtcbiAgICAgIHZhciBhcnJheSA9IFtdLCBzb3J0S2V5ID0gc29ydEtleXNbZGVwdGgrK107XG4gICAgICBtYXAuZm9yRWFjaChmdW5jdGlvbihrZXksIGtleU1hcCkge1xuICAgICAgICBhcnJheS5wdXNoKHtcbiAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICB2YWx1ZXM6IGVudHJpZXMoa2V5TWFwLCBkZXB0aClcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBzb3J0S2V5ID8gYXJyYXkuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBzb3J0S2V5KGEua2V5LCBiLmtleSk7XG4gICAgICB9KSA6IGFycmF5O1xuICAgIH1cbiAgICBuZXN0Lm1hcCA9IGZ1bmN0aW9uKGFycmF5LCBtYXBUeXBlKSB7XG4gICAgICByZXR1cm4gbWFwKG1hcFR5cGUsIGFycmF5LCAwKTtcbiAgICB9O1xuICAgIG5lc3QuZW50cmllcyA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICByZXR1cm4gZW50cmllcyhtYXAoZDMubWFwLCBhcnJheSwgMCksIDApO1xuICAgIH07XG4gICAgbmVzdC5rZXkgPSBmdW5jdGlvbihkKSB7XG4gICAgICBrZXlzLnB1c2goZCk7XG4gICAgICByZXR1cm4gbmVzdDtcbiAgICB9O1xuICAgIG5lc3Quc29ydEtleXMgPSBmdW5jdGlvbihvcmRlcikge1xuICAgICAgc29ydEtleXNba2V5cy5sZW5ndGggLSAxXSA9IG9yZGVyO1xuICAgICAgcmV0dXJuIG5lc3Q7XG4gICAgfTtcbiAgICBuZXN0LnNvcnRWYWx1ZXMgPSBmdW5jdGlvbihvcmRlcikge1xuICAgICAgc29ydFZhbHVlcyA9IG9yZGVyO1xuICAgICAgcmV0dXJuIG5lc3Q7XG4gICAgfTtcbiAgICBuZXN0LnJvbGx1cCA9IGZ1bmN0aW9uKGYpIHtcbiAgICAgIHJvbGx1cCA9IGY7XG4gICAgICByZXR1cm4gbmVzdDtcbiAgICB9O1xuICAgIHJldHVybiBuZXN0O1xuICB9O1xuICBkMy5zZXQgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciBzZXQgPSBuZXcgZDNfU2V0KCk7XG4gICAgaWYgKGFycmF5KSBmb3IgKHZhciBpID0gMCwgbiA9IGFycmF5Lmxlbmd0aDsgaSA8IG47ICsraSkgc2V0LmFkZChhcnJheVtpXSk7XG4gICAgcmV0dXJuIHNldDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfU2V0KCkge1xuICAgIHRoaXMuXyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cbiAgZDNfY2xhc3MoZDNfU2V0LCB7XG4gICAgaGFzOiBkM19tYXBfaGFzLFxuICAgIGFkZDogZnVuY3Rpb24oa2V5KSB7XG4gICAgICB0aGlzLl9bZDNfbWFwX2VzY2FwZShrZXkgKz0gXCJcIildID0gdHJ1ZTtcbiAgICAgIHJldHVybiBrZXk7XG4gICAgfSxcbiAgICByZW1vdmU6IGQzX21hcF9yZW1vdmUsXG4gICAgdmFsdWVzOiBkM19tYXBfa2V5cyxcbiAgICBzaXplOiBkM19tYXBfc2l6ZSxcbiAgICBlbXB0eTogZDNfbWFwX2VtcHR5LFxuICAgIGZvckVhY2g6IGZ1bmN0aW9uKGYpIHtcbiAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLl8pIGYuY2FsbCh0aGlzLCBkM19tYXBfdW5lc2NhcGUoa2V5KSk7XG4gICAgfVxuICB9KTtcbiAgZDMuYmVoYXZpb3IgPSB7fTtcbiAgZnVuY3Rpb24gZDNfaWRlbnRpdHkoZCkge1xuICAgIHJldHVybiBkO1xuICB9XG4gIGQzLnJlYmluZCA9IGZ1bmN0aW9uKHRhcmdldCwgc291cmNlKSB7XG4gICAgdmFyIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aCwgbWV0aG9kO1xuICAgIHdoaWxlICgrK2kgPCBuKSB0YXJnZXRbbWV0aG9kID0gYXJndW1lbnRzW2ldXSA9IGQzX3JlYmluZCh0YXJnZXQsIHNvdXJjZSwgc291cmNlW21ldGhvZF0pO1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3JlYmluZCh0YXJnZXQsIHNvdXJjZSwgbWV0aG9kKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHZhbHVlID0gbWV0aG9kLmFwcGx5KHNvdXJjZSwgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gc291cmNlID8gdGFyZ2V0IDogdmFsdWU7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM192ZW5kb3JTeW1ib2wob2JqZWN0LCBuYW1lKSB7XG4gICAgaWYgKG5hbWUgaW4gb2JqZWN0KSByZXR1cm4gbmFtZTtcbiAgICBuYW1lID0gbmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG5hbWUuc2xpY2UoMSk7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBkM192ZW5kb3JQcmVmaXhlcy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciBwcmVmaXhOYW1lID0gZDNfdmVuZG9yUHJlZml4ZXNbaV0gKyBuYW1lO1xuICAgICAgaWYgKHByZWZpeE5hbWUgaW4gb2JqZWN0KSByZXR1cm4gcHJlZml4TmFtZTtcbiAgICB9XG4gIH1cbiAgdmFyIGQzX3ZlbmRvclByZWZpeGVzID0gWyBcIndlYmtpdFwiLCBcIm1zXCIsIFwibW96XCIsIFwiTW96XCIsIFwib1wiLCBcIk9cIiBdO1xuICBmdW5jdGlvbiBkM19ub29wKCkge31cbiAgZDMuZGlzcGF0Y2ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZGlzcGF0Y2ggPSBuZXcgZDNfZGlzcGF0Y2goKSwgaSA9IC0xLCBuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgZGlzcGF0Y2hbYXJndW1lbnRzW2ldXSA9IGQzX2Rpc3BhdGNoX2V2ZW50KGRpc3BhdGNoKTtcbiAgICByZXR1cm4gZGlzcGF0Y2g7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2Rpc3BhdGNoKCkge31cbiAgZDNfZGlzcGF0Y2gucHJvdG90eXBlLm9uID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgICB2YXIgaSA9IHR5cGUuaW5kZXhPZihcIi5cIiksIG5hbWUgPSBcIlwiO1xuICAgIGlmIChpID49IDApIHtcbiAgICAgIG5hbWUgPSB0eXBlLnNsaWNlKGkgKyAxKTtcbiAgICAgIHR5cGUgPSB0eXBlLnNsaWNlKDAsIGkpO1xuICAgIH1cbiAgICBpZiAodHlwZSkgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAyID8gdGhpc1t0eXBlXS5vbihuYW1lKSA6IHRoaXNbdHlwZV0ub24obmFtZSwgbGlzdGVuZXIpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7XG4gICAgICBpZiAobGlzdGVuZXIgPT0gbnVsbCkgZm9yICh0eXBlIGluIHRoaXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkodHlwZSkpIHRoaXNbdHlwZV0ub24obmFtZSwgbnVsbCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2Rpc3BhdGNoX2V2ZW50KGRpc3BhdGNoKSB7XG4gICAgdmFyIGxpc3RlbmVycyA9IFtdLCBsaXN0ZW5lckJ5TmFtZSA9IG5ldyBkM19NYXAoKTtcbiAgICBmdW5jdGlvbiBldmVudCgpIHtcbiAgICAgIHZhciB6ID0gbGlzdGVuZXJzLCBpID0gLTEsIG4gPSB6Lmxlbmd0aCwgbDtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAobCA9IHpbaV0ub24pIGwuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBkaXNwYXRjaDtcbiAgICB9XG4gICAgZXZlbnQub24gPSBmdW5jdGlvbihuYW1lLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGwgPSBsaXN0ZW5lckJ5TmFtZS5nZXQobmFtZSksIGk7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHJldHVybiBsICYmIGwub247XG4gICAgICBpZiAobCkge1xuICAgICAgICBsLm9uID0gbnVsbDtcbiAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzLnNsaWNlKDAsIGkgPSBsaXN0ZW5lcnMuaW5kZXhPZihsKSkuY29uY2F0KGxpc3RlbmVycy5zbGljZShpICsgMSkpO1xuICAgICAgICBsaXN0ZW5lckJ5TmFtZS5yZW1vdmUobmFtZSk7XG4gICAgICB9XG4gICAgICBpZiAobGlzdGVuZXIpIGxpc3RlbmVycy5wdXNoKGxpc3RlbmVyQnlOYW1lLnNldChuYW1lLCB7XG4gICAgICAgIG9uOiBsaXN0ZW5lclxuICAgICAgfSkpO1xuICAgICAgcmV0dXJuIGRpc3BhdGNoO1xuICAgIH07XG4gICAgcmV0dXJuIGV2ZW50O1xuICB9XG4gIGQzLmV2ZW50ID0gbnVsbDtcbiAgZnVuY3Rpb24gZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCgpIHtcbiAgICBkMy5ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2V2ZW50U291cmNlKCkge1xuICAgIHZhciBlID0gZDMuZXZlbnQsIHM7XG4gICAgd2hpbGUgKHMgPSBlLnNvdXJjZUV2ZW50KSBlID0gcztcbiAgICByZXR1cm4gZTtcbiAgfVxuICBmdW5jdGlvbiBkM19ldmVudERpc3BhdGNoKHRhcmdldCkge1xuICAgIHZhciBkaXNwYXRjaCA9IG5ldyBkM19kaXNwYXRjaCgpLCBpID0gMCwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IG4pIGRpc3BhdGNoW2FyZ3VtZW50c1tpXV0gPSBkM19kaXNwYXRjaF9ldmVudChkaXNwYXRjaCk7XG4gICAgZGlzcGF0Y2gub2YgPSBmdW5jdGlvbih0aGl6LCBhcmd1bWVudHopIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihlMSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHZhciBlMCA9IGUxLnNvdXJjZUV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgZTEudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICAgIGQzLmV2ZW50ID0gZTE7XG4gICAgICAgICAgZGlzcGF0Y2hbZTEudHlwZV0uYXBwbHkodGhpeiwgYXJndW1lbnR6KTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBkMy5ldmVudCA9IGUwO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIGRpc3BhdGNoO1xuICB9XG4gIGQzLnJlcXVvdGUgPSBmdW5jdGlvbihzKSB7XG4gICAgcmV0dXJuIHMucmVwbGFjZShkM19yZXF1b3RlX3JlLCBcIlxcXFwkJlwiKTtcbiAgfTtcbiAgdmFyIGQzX3JlcXVvdGVfcmUgPSAvW1xcXFxcXF5cXCRcXCpcXCtcXD9cXHxcXFtcXF1cXChcXClcXC5cXHtcXH1dL2c7XG4gIHZhciBkM19zdWJjbGFzcyA9IHt9Ll9fcHJvdG9fXyA/IGZ1bmN0aW9uKG9iamVjdCwgcHJvdG90eXBlKSB7XG4gICAgb2JqZWN0Ll9fcHJvdG9fXyA9IHByb3RvdHlwZTtcbiAgfSA6IGZ1bmN0aW9uKG9iamVjdCwgcHJvdG90eXBlKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gcHJvdG90eXBlKSBvYmplY3RbcHJvcGVydHldID0gcHJvdG90eXBlW3Byb3BlcnR5XTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uKGdyb3Vwcykge1xuICAgIGQzX3N1YmNsYXNzKGdyb3VwcywgZDNfc2VsZWN0aW9uUHJvdG90eXBlKTtcbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIHZhciBkM19zZWxlY3QgPSBmdW5jdGlvbihzLCBuKSB7XG4gICAgcmV0dXJuIG4ucXVlcnlTZWxlY3RvcihzKTtcbiAgfSwgZDNfc2VsZWN0QWxsID0gZnVuY3Rpb24ocywgbikge1xuICAgIHJldHVybiBuLnF1ZXJ5U2VsZWN0b3JBbGwocyk7XG4gIH0sIGQzX3NlbGVjdE1hdGNoZXMgPSBmdW5jdGlvbihuLCBzKSB7XG4gICAgdmFyIGQzX3NlbGVjdE1hdGNoZXIgPSBuLm1hdGNoZXMgfHwgbltkM192ZW5kb3JTeW1ib2wobiwgXCJtYXRjaGVzU2VsZWN0b3JcIildO1xuICAgIGQzX3NlbGVjdE1hdGNoZXMgPSBmdW5jdGlvbihuLCBzKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0TWF0Y2hlci5jYWxsKG4sIHMpO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NlbGVjdE1hdGNoZXMobiwgcyk7XG4gIH07XG4gIGlmICh0eXBlb2YgU2l6emxlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBkM19zZWxlY3QgPSBmdW5jdGlvbihzLCBuKSB7XG4gICAgICByZXR1cm4gU2l6emxlKHMsIG4pWzBdIHx8IG51bGw7XG4gICAgfTtcbiAgICBkM19zZWxlY3RBbGwgPSBTaXp6bGU7XG4gICAgZDNfc2VsZWN0TWF0Y2hlcyA9IFNpenpsZS5tYXRjaGVzU2VsZWN0b3I7XG4gIH1cbiAgZDMuc2VsZWN0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzLnNlbGVjdChkM19kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuICB9O1xuICB2YXIgZDNfc2VsZWN0aW9uUHJvdG90eXBlID0gZDMuc2VsZWN0aW9uLnByb3RvdHlwZSA9IFtdO1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuc2VsZWN0ID0gZnVuY3Rpb24oc2VsZWN0b3IpIHtcbiAgICB2YXIgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2RlLCBncm91cCwgbm9kZTtcbiAgICBzZWxlY3RvciA9IGQzX3NlbGVjdGlvbl9zZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBzdWJncm91cC5wYXJlbnROb2RlID0gKGdyb3VwID0gdGhpc1tqXSkucGFyZW50Tm9kZTtcbiAgICAgIGZvciAodmFyIGkgPSAtMSwgbiA9IGdyb3VwLmxlbmd0aDsgKytpIDwgbjsgKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUgPSBzZWxlY3Rvci5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopKTtcbiAgICAgICAgICBpZiAoc3Vibm9kZSAmJiBcIl9fZGF0YV9fXCIgaW4gbm9kZSkgc3Vibm9kZS5fX2RhdGFfXyA9IG5vZGUuX19kYXRhX187XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaChudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKHN1Ymdyb3Vwcyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9zZWxlY3RvcihzZWxlY3Rvcikge1xuICAgIHJldHVybiB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiA/IHNlbGVjdG9yIDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0KHNlbGVjdG9yLCB0aGlzKTtcbiAgICB9O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5zZWxlY3RBbGwgPSBmdW5jdGlvbihzZWxlY3Rvcikge1xuICAgIHZhciBzdWJncm91cHMgPSBbXSwgc3ViZ3JvdXAsIG5vZGU7XG4gICAgc2VsZWN0b3IgPSBkM19zZWxlY3Rpb25fc2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICAgIGZvciAodmFyIGogPSAtMSwgbSA9IHRoaXMubGVuZ3RoOyArK2ogPCBtOyApIHtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IC0xLCBuID0gZ3JvdXAubGVuZ3RoOyArK2kgPCBuOyApIHtcbiAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gZDNfYXJyYXkoc2VsZWN0b3IuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpO1xuICAgICAgICAgIHN1Ymdyb3VwLnBhcmVudE5vZGUgPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM19zZWxlY3Rpb24oc3ViZ3JvdXBzKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX3NlbGVjdG9yQWxsKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiID8gc2VsZWN0b3IgOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19zZWxlY3RBbGwoc2VsZWN0b3IsIHRoaXMpO1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX25zWGh0bWwgPSBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjtcbiAgdmFyIGQzX25zUHJlZml4ID0ge1xuICAgIHN2ZzogXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFxuICAgIHhodG1sOiBkM19uc1hodG1sLFxuICAgIHhsaW5rOiBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIixcbiAgICB4bWw6IFwiaHR0cDovL3d3dy53My5vcmcvWE1MLzE5OTgvbmFtZXNwYWNlXCIsXG4gICAgeG1sbnM6IFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC94bWxucy9cIlxuICB9O1xuICBkMy5ucyA9IHtcbiAgICBwcmVmaXg6IGQzX25zUHJlZml4LFxuICAgIHF1YWxpZnk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBpID0gbmFtZS5pbmRleE9mKFwiOlwiKSwgcHJlZml4ID0gbmFtZTtcbiAgICAgIGlmIChpID49IDAgJiYgKHByZWZpeCA9IG5hbWUuc2xpY2UoMCwgaSkpICE9PSBcInhtbG5zXCIpIG5hbWUgPSBuYW1lLnNsaWNlKGkgKyAxKTtcbiAgICAgIHJldHVybiBkM19uc1ByZWZpeC5oYXNPd25Qcm9wZXJ0eShwcmVmaXgpID8ge1xuICAgICAgICBzcGFjZTogZDNfbnNQcmVmaXhbcHJlZml4XSxcbiAgICAgICAgbG9jYWw6IG5hbWVcbiAgICAgIH0gOiBuYW1lO1xuICAgIH1cbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmF0dHIgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5ub2RlKCk7XG4gICAgICAgIG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWUpO1xuICAgICAgICByZXR1cm4gbmFtZS5sb2NhbCA/IG5vZGUuZ2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCkgOiBub2RlLmdldEF0dHJpYnV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFsdWUgaW4gbmFtZSkgdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9hdHRyKHZhbHVlLCBuYW1lW3ZhbHVlXSkpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVhY2goZDNfc2VsZWN0aW9uX2F0dHIobmFtZSwgdmFsdWUpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX2F0dHIobmFtZSwgdmFsdWUpIHtcbiAgICBuYW1lID0gZDMubnMucXVhbGlmeShuYW1lKTtcbiAgICBmdW5jdGlvbiBhdHRyTnVsbCgpIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyTnVsbE5TKCkge1xuICAgICAgdGhpcy5yZW1vdmVBdHRyaWJ1dGVOUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ckNvbnN0YW50KCkge1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyQ29uc3RhbnROUygpIHtcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgdmFsdWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyRnVuY3Rpb24oKSB7XG4gICAgICB2YXIgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoeCA9PSBudWxsKSB0aGlzLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTsgZWxzZSB0aGlzLnNldEF0dHJpYnV0ZShuYW1lLCB4KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ckZ1bmN0aW9uTlMoKSB7XG4gICAgICB2YXIgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoeCA9PSBudWxsKSB0aGlzLnJlbW92ZUF0dHJpYnV0ZU5TKG5hbWUuc3BhY2UsIG5hbWUubG9jYWwpOyBlbHNlIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgeCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsID8gbmFtZS5sb2NhbCA/IGF0dHJOdWxsTlMgOiBhdHRyTnVsbCA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gbmFtZS5sb2NhbCA/IGF0dHJGdW5jdGlvbk5TIDogYXR0ckZ1bmN0aW9uIDogbmFtZS5sb2NhbCA/IGF0dHJDb25zdGFudE5TIDogYXR0ckNvbnN0YW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2NvbGxhcHNlKHMpIHtcbiAgICByZXR1cm4gcy50cmltKCkucmVwbGFjZSgvXFxzKy9nLCBcIiBcIik7XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmNsYXNzZWQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5ub2RlKCksIG4gPSAobmFtZSA9IGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpKS5sZW5ndGgsIGkgPSAtMTtcbiAgICAgICAgaWYgKHZhbHVlID0gbm9kZS5jbGFzc0xpc3QpIHtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCF2YWx1ZS5jb250YWlucyhuYW1lW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlID0gbm9kZS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKTtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCFkM19zZWxlY3Rpb25fY2xhc3NlZFJlKG5hbWVbaV0pLnRlc3QodmFsdWUpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBmb3IgKHZhbHVlIGluIG5hbWUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fY2xhc3NlZCh2YWx1ZSwgbmFtZVt2YWx1ZV0pKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9jbGFzc2VkKG5hbWUsIHZhbHVlKSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkUmUobmFtZSkge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKD86XnxcXFxccyspXCIgKyBkMy5yZXF1b3RlKG5hbWUpICsgXCIoPzpcXFxccyt8JClcIiwgXCJnXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpIHtcbiAgICByZXR1cm4gKG5hbWUgKyBcIlwiKS50cmltKCkuc3BsaXQoL158XFxzKy8pO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkKG5hbWUsIHZhbHVlKSB7XG4gICAgbmFtZSA9IGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpLm1hcChkM19zZWxlY3Rpb25fY2xhc3NlZE5hbWUpO1xuICAgIHZhciBuID0gbmFtZS5sZW5ndGg7XG4gICAgZnVuY3Rpb24gY2xhc3NlZENvbnN0YW50KCkge1xuICAgICAgdmFyIGkgPSAtMTtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBuYW1lW2ldKHRoaXMsIHZhbHVlKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY2xhc3NlZEZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGkgPSAtMSwgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB3aGlsZSAoKytpIDwgbikgbmFtZVtpXSh0aGlzLCB4KTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gY2xhc3NlZEZ1bmN0aW9uIDogY2xhc3NlZENvbnN0YW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkTmFtZShuYW1lKSB7XG4gICAgdmFyIHJlID0gZDNfc2VsZWN0aW9uX2NsYXNzZWRSZShuYW1lKTtcbiAgICByZXR1cm4gZnVuY3Rpb24obm9kZSwgdmFsdWUpIHtcbiAgICAgIGlmIChjID0gbm9kZS5jbGFzc0xpc3QpIHJldHVybiB2YWx1ZSA/IGMuYWRkKG5hbWUpIDogYy5yZW1vdmUobmFtZSk7XG4gICAgICB2YXIgYyA9IG5vZGUuZ2V0QXR0cmlidXRlKFwiY2xhc3NcIikgfHwgXCJcIjtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICByZS5sYXN0SW5kZXggPSAwO1xuICAgICAgICBpZiAoIXJlLnRlc3QoYykpIG5vZGUuc2V0QXR0cmlidXRlKFwiY2xhc3NcIiwgZDNfY29sbGFwc2UoYyArIFwiIFwiICsgbmFtZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoXCJjbGFzc1wiLCBkM19jb2xsYXBzZShjLnJlcGxhY2UocmUsIFwiIFwiKSkpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnN0eWxlID0gZnVuY3Rpb24obmFtZSwgdmFsdWUsIHByaW9yaXR5KSB7XG4gICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGlmIChuIDwgMykge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGlmIChuIDwgMikgdmFsdWUgPSBcIlwiO1xuICAgICAgICBmb3IgKHByaW9yaXR5IGluIG5hbWUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fc3R5bGUocHJpb3JpdHksIG5hbWVbcHJpb3JpdHldLCB2YWx1ZSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICAgIGlmIChuIDwgMikge1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMubm9kZSgpO1xuICAgICAgICByZXR1cm4gZDNfd2luZG93KG5vZGUpLmdldENvbXB1dGVkU3R5bGUobm9kZSwgbnVsbCkuZ2V0UHJvcGVydHlWYWx1ZShuYW1lKTtcbiAgICAgIH1cbiAgICAgIHByaW9yaXR5ID0gXCJcIjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fc3R5bGUobmFtZSwgdmFsdWUsIHByaW9yaXR5KSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9zdHlsZShuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgICBmdW5jdGlvbiBzdHlsZU51bGwoKSB7XG4gICAgICB0aGlzLnN0eWxlLnJlbW92ZVByb3BlcnR5KG5hbWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdHlsZUNvbnN0YW50KCkge1xuICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdHlsZUZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHggPSB2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgaWYgKHggPT0gbnVsbCkgdGhpcy5zdHlsZS5yZW1vdmVQcm9wZXJ0eShuYW1lKTsgZWxzZSB0aGlzLnN0eWxlLnNldFByb3BlcnR5KG5hbWUsIHgsIHByaW9yaXR5KTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGwgPyBzdHlsZU51bGwgOiB0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiA/IHN0eWxlRnVuY3Rpb24gOiBzdHlsZUNvbnN0YW50O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5wcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3RyaW5nXCIpIHJldHVybiB0aGlzLm5vZGUoKVtuYW1lXTtcbiAgICAgIGZvciAodmFsdWUgaW4gbmFtZSkgdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9wcm9wZXJ0eSh2YWx1ZSwgbmFtZVt2YWx1ZV0pKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9wcm9wZXJ0eShuYW1lLCB2YWx1ZSkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fcHJvcGVydHkobmFtZSwgdmFsdWUpIHtcbiAgICBmdW5jdGlvbiBwcm9wZXJ0eU51bGwoKSB7XG4gICAgICBkZWxldGUgdGhpc1tuYW1lXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvcGVydHlDb25zdGFudCgpIHtcbiAgICAgIHRoaXNbbmFtZV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvcGVydHlGdW5jdGlvbigpIHtcbiAgICAgIHZhciB4ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmICh4ID09IG51bGwpIGRlbGV0ZSB0aGlzW25hbWVdOyBlbHNlIHRoaXNbbmFtZV0gPSB4O1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbCA/IHByb3BlcnR5TnVsbCA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gcHJvcGVydHlGdW5jdGlvbiA6IHByb3BlcnR5Q29uc3RhbnQ7XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnRleHQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5lYWNoKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdiA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB0aGlzLnRleHRDb250ZW50ID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gICAgfSA6IHZhbHVlID09IG51bGwgPyBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSBcIlwiO1xuICAgIH0gOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTtcbiAgICB9KSA6IHRoaXMubm9kZSgpLnRleHRDb250ZW50O1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuaHRtbCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyB0aGlzLmVhY2godHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIgPyBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHRoaXMuaW5uZXJIVE1MID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gICAgfSA6IHZhbHVlID09IG51bGwgPyBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9IDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmlubmVySFRNTCA9IHZhbHVlO1xuICAgIH0pIDogdGhpcy5ub2RlKCkuaW5uZXJIVE1MO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24obmFtZSkge1xuICAgIG5hbWUgPSBkM19zZWxlY3Rpb25fY3JlYXRvcihuYW1lKTtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3QoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5hcHBlbmRDaGlsZChuYW1lLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICAgIH0pO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fY3JlYXRvcihuYW1lKSB7XG4gICAgZnVuY3Rpb24gY3JlYXRlKCkge1xuICAgICAgdmFyIGRvY3VtZW50ID0gdGhpcy5vd25lckRvY3VtZW50LCBuYW1lc3BhY2UgPSB0aGlzLm5hbWVzcGFjZVVSSTtcbiAgICAgIHJldHVybiBuYW1lc3BhY2UgPT09IGQzX25zWGh0bWwgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Lm5hbWVzcGFjZVVSSSA9PT0gZDNfbnNYaHRtbCA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQobmFtZSkgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlLCBuYW1lKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlTlMoKSB7XG4gICAgICByZXR1cm4gdGhpcy5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiBuYW1lID09PSBcImZ1bmN0aW9uXCIgPyBuYW1lIDogKG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWUpKS5sb2NhbCA/IGNyZWF0ZU5TIDogY3JlYXRlO1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbihuYW1lLCBiZWZvcmUpIHtcbiAgICBuYW1lID0gZDNfc2VsZWN0aW9uX2NyZWF0b3IobmFtZSk7XG4gICAgYmVmb3JlID0gZDNfc2VsZWN0aW9uX3NlbGVjdG9yKGJlZm9yZSk7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0KGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW5zZXJ0QmVmb3JlKG5hbWUuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgYmVmb3JlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgbnVsbCk7XG4gICAgfSk7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvblJlbW92ZSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvblJlbW92ZSgpIHtcbiAgICB2YXIgcGFyZW50ID0gdGhpcy5wYXJlbnROb2RlO1xuICAgIGlmIChwYXJlbnQpIHBhcmVudC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZGF0YSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICB2YXIgaSA9IC0xLCBuID0gdGhpcy5sZW5ndGgsIGdyb3VwLCBub2RlO1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgdmFsdWUgPSBuZXcgQXJyYXkobiA9IChncm91cCA9IHRoaXNbMF0pLmxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgdmFsdWVbaV0gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGJpbmQoZ3JvdXAsIGdyb3VwRGF0YSkge1xuICAgICAgdmFyIGksIG4gPSBncm91cC5sZW5ndGgsIG0gPSBncm91cERhdGEubGVuZ3RoLCBuMCA9IE1hdGgubWluKG4sIG0pLCB1cGRhdGVOb2RlcyA9IG5ldyBBcnJheShtKSwgZW50ZXJOb2RlcyA9IG5ldyBBcnJheShtKSwgZXhpdE5vZGVzID0gbmV3IEFycmF5KG4pLCBub2RlLCBub2RlRGF0YTtcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgdmFyIG5vZGVCeUtleVZhbHVlID0gbmV3IGQzX01hcCgpLCBrZXlWYWx1ZXMgPSBuZXcgQXJyYXkobiksIGtleVZhbHVlO1xuICAgICAgICBmb3IgKGkgPSAtMTsgKytpIDwgbjsgKSB7XG4gICAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgICAgaWYgKG5vZGVCeUtleVZhbHVlLmhhcyhrZXlWYWx1ZSA9IGtleS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpKSkge1xuICAgICAgICAgICAgICBleGl0Tm9kZXNbaV0gPSBub2RlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbm9kZUJ5S2V5VmFsdWUuc2V0KGtleVZhbHVlLCBub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGtleVZhbHVlc1tpXSA9IGtleVZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAtMTsgKytpIDwgbTsgKSB7XG4gICAgICAgICAgaWYgKCEobm9kZSA9IG5vZGVCeUtleVZhbHVlLmdldChrZXlWYWx1ZSA9IGtleS5jYWxsKGdyb3VwRGF0YSwgbm9kZURhdGEgPSBncm91cERhdGFbaV0sIGkpKSkpIHtcbiAgICAgICAgICAgIGVudGVyTm9kZXNbaV0gPSBkM19zZWxlY3Rpb25fZGF0YU5vZGUobm9kZURhdGEpO1xuICAgICAgICAgIH0gZWxzZSBpZiAobm9kZSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdXBkYXRlTm9kZXNbaV0gPSBub2RlO1xuICAgICAgICAgICAgbm9kZS5fX2RhdGFfXyA9IG5vZGVEYXRhO1xuICAgICAgICAgIH1cbiAgICAgICAgICBub2RlQnlLZXlWYWx1ZS5zZXQoa2V5VmFsdWUsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IC0xOyArK2kgPCBuOyApIHtcbiAgICAgICAgICBpZiAoaSBpbiBrZXlWYWx1ZXMgJiYgbm9kZUJ5S2V5VmFsdWUuZ2V0KGtleVZhbHVlc1tpXSkgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGV4aXROb2Rlc1tpXSA9IGdyb3VwW2ldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChpID0gLTE7ICsraSA8IG4wOyApIHtcbiAgICAgICAgICBub2RlID0gZ3JvdXBbaV07XG4gICAgICAgICAgbm9kZURhdGEgPSBncm91cERhdGFbaV07XG4gICAgICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUuX19kYXRhX18gPSBub2RlRGF0YTtcbiAgICAgICAgICAgIHVwZGF0ZU5vZGVzW2ldID0gbm9kZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZW50ZXJOb2Rlc1tpXSA9IGQzX3NlbGVjdGlvbl9kYXRhTm9kZShub2RlRGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoO2kgPCBtOyArK2kpIHtcbiAgICAgICAgICBlbnRlck5vZGVzW2ldID0gZDNfc2VsZWN0aW9uX2RhdGFOb2RlKGdyb3VwRGF0YVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICg7aSA8IG47ICsraSkge1xuICAgICAgICAgIGV4aXROb2Rlc1tpXSA9IGdyb3VwW2ldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbnRlck5vZGVzLnVwZGF0ZSA9IHVwZGF0ZU5vZGVzO1xuICAgICAgZW50ZXJOb2Rlcy5wYXJlbnROb2RlID0gdXBkYXRlTm9kZXMucGFyZW50Tm9kZSA9IGV4aXROb2Rlcy5wYXJlbnROb2RlID0gZ3JvdXAucGFyZW50Tm9kZTtcbiAgICAgIGVudGVyLnB1c2goZW50ZXJOb2Rlcyk7XG4gICAgICB1cGRhdGUucHVzaCh1cGRhdGVOb2Rlcyk7XG4gICAgICBleGl0LnB1c2goZXhpdE5vZGVzKTtcbiAgICB9XG4gICAgdmFyIGVudGVyID0gZDNfc2VsZWN0aW9uX2VudGVyKFtdKSwgdXBkYXRlID0gZDNfc2VsZWN0aW9uKFtdKSwgZXhpdCA9IGQzX3NlbGVjdGlvbihbXSk7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBiaW5kKGdyb3VwID0gdGhpc1tpXSwgdmFsdWUuY2FsbChncm91cCwgZ3JvdXAucGFyZW50Tm9kZS5fX2RhdGFfXywgaSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBiaW5kKGdyb3VwID0gdGhpc1tpXSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGUuZW50ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBlbnRlcjtcbiAgICB9O1xuICAgIHVwZGF0ZS5leGl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZXhpdDtcbiAgICB9O1xuICAgIHJldHVybiB1cGRhdGU7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9kYXRhTm9kZShkYXRhKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fZGF0YV9fOiBkYXRhXG4gICAgfTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZGF0dW0gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5wcm9wZXJ0eShcIl9fZGF0YV9fXCIsIHZhbHVlKSA6IHRoaXMucHJvcGVydHkoXCJfX2RhdGFfX1wiKTtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmZpbHRlciA9IGZ1bmN0aW9uKGZpbHRlcikge1xuICAgIHZhciBzdWJncm91cHMgPSBbXSwgc3ViZ3JvdXAsIGdyb3VwLCBub2RlO1xuICAgIGlmICh0eXBlb2YgZmlsdGVyICE9PSBcImZ1bmN0aW9uXCIpIGZpbHRlciA9IGQzX3NlbGVjdGlvbl9maWx0ZXIoZmlsdGVyKTtcbiAgICBmb3IgKHZhciBqID0gMCwgbSA9IHRoaXMubGVuZ3RoOyBqIDwgbTsgaisrKSB7XG4gICAgICBzdWJncm91cHMucHVzaChzdWJncm91cCA9IFtdKTtcbiAgICAgIHN1Ymdyb3VwLnBhcmVudE5vZGUgPSAoZ3JvdXAgPSB0aGlzW2pdKS5wYXJlbnROb2RlO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG4gPSBncm91cC5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIGZpbHRlci5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopKSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaChub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKHN1Ymdyb3Vwcyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9maWx0ZXIoc2VsZWN0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0TWF0Y2hlcyh0aGlzLCBzZWxlY3Rvcik7XG4gICAgfTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUub3JkZXIgPSBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSBncm91cC5sZW5ndGggLSAxLCBuZXh0ID0gZ3JvdXBbaV0sIG5vZGU7IC0taSA+PSAwOyApIHtcbiAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgIGlmIChuZXh0ICYmIG5leHQgIT09IG5vZGUubmV4dFNpYmxpbmcpIG5leHQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgbmV4dCk7XG4gICAgICAgICAgbmV4dCA9IG5vZGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5zb3J0ID0gZnVuY3Rpb24oY29tcGFyYXRvcikge1xuICAgIGNvbXBhcmF0b3IgPSBkM19zZWxlY3Rpb25fc29ydENvbXBhcmF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB0aGlzW2pdLnNvcnQoY29tcGFyYXRvcik7XG4gICAgcmV0dXJuIHRoaXMub3JkZXIoKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX3NvcnRDb21wYXJhdG9yKGNvbXBhcmF0b3IpIHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIGNvbXBhcmF0b3IgPSBkM19hc2NlbmRpbmc7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgIHJldHVybiBhICYmIGIgPyBjb21wYXJhdG9yKGEuX19kYXRhX18sIGIuX19kYXRhX18pIDogIWEgLSAhYjtcbiAgICB9O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgY2FsbGJhY2suY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKTtcbiAgICB9KTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX2VhY2goZ3JvdXBzLCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gZ3JvdXBzLmxlbmd0aDsgaiA8IG07IGorKykge1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIGkgPSAwLCBuID0gZ3JvdXAubGVuZ3RoLCBub2RlOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIGNhbGxiYWNrKG5vZGUsIGksIGopO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5jYWxsID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICB2YXIgYXJncyA9IGQzX2FycmF5KGFyZ3VtZW50cyk7XG4gICAgY2FsbGJhY2suYXBwbHkoYXJnc1swXSA9IHRoaXMsIGFyZ3MpO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZW1wdHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMubm9kZSgpO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUubm9kZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gdGhpcy5sZW5ndGg7IGogPCBtOyBqKyspIHtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IDAsIG4gPSBncm91cC5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgdmFyIG5vZGUgPSBncm91cFtpXTtcbiAgICAgICAgaWYgKG5vZGUpIHJldHVybiBub2RlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbiA9IDA7XG4gICAgZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24oKSB7XG4gICAgICArK247XG4gICAgfSk7XG4gICAgcmV0dXJuIG47XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9lbnRlcihzZWxlY3Rpb24pIHtcbiAgICBkM19zdWJjbGFzcyhzZWxlY3Rpb24sIGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZSk7XG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbiAgfVxuICB2YXIgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlID0gW107XG4gIGQzLnNlbGVjdGlvbi5lbnRlciA9IGQzX3NlbGVjdGlvbl9lbnRlcjtcbiAgZDMuc2VsZWN0aW9uLmVudGVyLnByb3RvdHlwZSA9IGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLmFwcGVuZCA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5hcHBlbmQ7XG4gIGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZS5lbXB0eSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5lbXB0eTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLm5vZGUgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUubm9kZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLmNhbGwgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuY2FsbDtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLnNpemUgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuc2l6ZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgc3Vibm9kZSwgdXBncm91cCwgZ3JvdXAsIG5vZGU7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgdXBncm91cCA9IChncm91cCA9IHRoaXNbal0pLnVwZGF0ZTtcbiAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gW10pO1xuICAgICAgc3ViZ3JvdXAucGFyZW50Tm9kZSA9IGdyb3VwLnBhcmVudE5vZGU7XG4gICAgICBmb3IgKHZhciBpID0gLTEsIG4gPSBncm91cC5sZW5ndGg7ICsraSA8IG47ICkge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaCh1cGdyb3VwW2ldID0gc3Vibm9kZSA9IHNlbGVjdG9yLmNhbGwoZ3JvdXAucGFyZW50Tm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaikpO1xuICAgICAgICAgIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1Ymdyb3VwLnB1c2gobnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbihzdWJncm91cHMpO1xuICB9O1xuICBkM19zZWxlY3Rpb25fZW50ZXJQcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24obmFtZSwgYmVmb3JlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBiZWZvcmUgPSBkM19zZWxlY3Rpb25fZW50ZXJJbnNlcnRCZWZvcmUodGhpcyk7XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvblByb3RvdHlwZS5pbnNlcnQuY2FsbCh0aGlzLCBuYW1lLCBiZWZvcmUpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fZW50ZXJJbnNlcnRCZWZvcmUoZW50ZXIpIHtcbiAgICB2YXIgaTAsIGowO1xuICAgIHJldHVybiBmdW5jdGlvbihkLCBpLCBqKSB7XG4gICAgICB2YXIgZ3JvdXAgPSBlbnRlcltqXS51cGRhdGUsIG4gPSBncm91cC5sZW5ndGgsIG5vZGU7XG4gICAgICBpZiAoaiAhPSBqMCkgajAgPSBqLCBpMCA9IDA7XG4gICAgICBpZiAoaSA+PSBpMCkgaTAgPSBpICsgMTtcbiAgICAgIHdoaWxlICghKG5vZGUgPSBncm91cFtpMF0pICYmICsraTAgPCBuKSA7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9O1xuICB9XG4gIGQzLnNlbGVjdCA9IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICB2YXIgZ3JvdXA7XG4gICAgaWYgKHR5cGVvZiBub2RlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBncm91cCA9IFsgZDNfc2VsZWN0KG5vZGUsIGQzX2RvY3VtZW50KSBdO1xuICAgICAgZ3JvdXAucGFyZW50Tm9kZSA9IGQzX2RvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgZ3JvdXAgPSBbIG5vZGUgXTtcbiAgICAgIGdyb3VwLnBhcmVudE5vZGUgPSBkM19kb2N1bWVudEVsZW1lbnQobm9kZSk7XG4gICAgfVxuICAgIHJldHVybiBkM19zZWxlY3Rpb24oWyBncm91cCBdKTtcbiAgfTtcbiAgZDMuc2VsZWN0QWxsID0gZnVuY3Rpb24obm9kZXMpIHtcbiAgICB2YXIgZ3JvdXA7XG4gICAgaWYgKHR5cGVvZiBub2RlcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgZ3JvdXAgPSBkM19hcnJheShkM19zZWxlY3RBbGwobm9kZXMsIGQzX2RvY3VtZW50KSk7XG4gICAgICBncm91cC5wYXJlbnROb2RlID0gZDNfZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICBncm91cCA9IGQzX2FycmF5KG5vZGVzKTtcbiAgICAgIGdyb3VwLnBhcmVudE5vZGUgPSBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKFsgZ3JvdXAgXSk7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG4gICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGlmIChuIDwgMykge1xuICAgICAgaWYgKHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGlmIChuIDwgMikgbGlzdGVuZXIgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjYXB0dXJlIGluIHR5cGUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fb24oY2FwdHVyZSwgdHlwZVtjYXB0dXJlXSwgbGlzdGVuZXIpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDIpIHJldHVybiAobiA9IHRoaXMubm9kZSgpW1wiX19vblwiICsgdHlwZV0pICYmIG4uXztcbiAgICAgIGNhcHR1cmUgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fb24odHlwZSwgbGlzdGVuZXIsIGNhcHR1cmUpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX29uKHR5cGUsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG4gICAgdmFyIG5hbWUgPSBcIl9fb25cIiArIHR5cGUsIGkgPSB0eXBlLmluZGV4T2YoXCIuXCIpLCB3cmFwID0gZDNfc2VsZWN0aW9uX29uTGlzdGVuZXI7XG4gICAgaWYgKGkgPiAwKSB0eXBlID0gdHlwZS5zbGljZSgwLCBpKTtcbiAgICB2YXIgZmlsdGVyID0gZDNfc2VsZWN0aW9uX29uRmlsdGVycy5nZXQodHlwZSk7XG4gICAgaWYgKGZpbHRlcikgdHlwZSA9IGZpbHRlciwgd3JhcCA9IGQzX3NlbGVjdGlvbl9vbkZpbHRlcjtcbiAgICBmdW5jdGlvbiBvblJlbW92ZSgpIHtcbiAgICAgIHZhciBsID0gdGhpc1tuYW1lXTtcbiAgICAgIGlmIChsKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBsLCBsLiQpO1xuICAgICAgICBkZWxldGUgdGhpc1tuYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gb25BZGQoKSB7XG4gICAgICB2YXIgbCA9IHdyYXAobGlzdGVuZXIsIGQzX2FycmF5KGFyZ3VtZW50cykpO1xuICAgICAgb25SZW1vdmUuY2FsbCh0aGlzKTtcbiAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCB0aGlzW25hbWVdID0gbCwgbC4kID0gY2FwdHVyZSk7XG4gICAgICBsLl8gPSBsaXN0ZW5lcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVtb3ZlQWxsKCkge1xuICAgICAgdmFyIHJlID0gbmV3IFJlZ0V4cChcIl5fX29uKFteLl0rKVwiICsgZDMucmVxdW90ZSh0eXBlKSArIFwiJFwiKSwgbWF0Y2g7XG4gICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMpIHtcbiAgICAgICAgaWYgKG1hdGNoID0gbmFtZS5tYXRjaChyZSkpIHtcbiAgICAgICAgICB2YXIgbCA9IHRoaXNbbmFtZV07XG4gICAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKG1hdGNoWzFdLCBsLCBsLiQpO1xuICAgICAgICAgIGRlbGV0ZSB0aGlzW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpID8gbGlzdGVuZXIgPyBvbkFkZCA6IG9uUmVtb3ZlIDogbGlzdGVuZXIgPyBkM19ub29wIDogcmVtb3ZlQWxsO1xuICB9XG4gIHZhciBkM19zZWxlY3Rpb25fb25GaWx0ZXJzID0gZDMubWFwKHtcbiAgICBtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuICAgIG1vdXNlbGVhdmU6IFwibW91c2VvdXRcIlxuICB9KTtcbiAgaWYgKGQzX2RvY3VtZW50KSB7XG4gICAgZDNfc2VsZWN0aW9uX29uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICAgIGlmIChcIm9uXCIgKyBrIGluIGQzX2RvY3VtZW50KSBkM19zZWxlY3Rpb25fb25GaWx0ZXJzLnJlbW92ZShrKTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fb25MaXN0ZW5lcihsaXN0ZW5lciwgYXJndW1lbnR6KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciBvID0gZDMuZXZlbnQ7XG4gICAgICBkMy5ldmVudCA9IGU7XG4gICAgICBhcmd1bWVudHpbMF0gPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnR6KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGQzLmV2ZW50ID0gbztcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9vbkZpbHRlcihsaXN0ZW5lciwgYXJndW1lbnR6KSB7XG4gICAgdmFyIGwgPSBkM19zZWxlY3Rpb25fb25MaXN0ZW5lcihsaXN0ZW5lciwgYXJndW1lbnR6KTtcbiAgICByZXR1cm4gZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIHRhcmdldCA9IHRoaXMsIHJlbGF0ZWQgPSBlLnJlbGF0ZWRUYXJnZXQ7XG4gICAgICBpZiAoIXJlbGF0ZWQgfHwgcmVsYXRlZCAhPT0gdGFyZ2V0ICYmICEocmVsYXRlZC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbih0YXJnZXQpICYgOCkpIHtcbiAgICAgICAgbC5jYWxsKHRhcmdldCwgZSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICB2YXIgZDNfZXZlbnRfZHJhZ1NlbGVjdCwgZDNfZXZlbnRfZHJhZ0lkID0gMDtcbiAgZnVuY3Rpb24gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKG5vZGUpIHtcbiAgICB2YXIgbmFtZSA9IFwiLmRyYWdzdXBwcmVzcy1cIiArICsrZDNfZXZlbnRfZHJhZ0lkLCBjbGljayA9IFwiY2xpY2tcIiArIG5hbWUsIHcgPSBkMy5zZWxlY3QoZDNfd2luZG93KG5vZGUpKS5vbihcInRvdWNobW92ZVwiICsgbmFtZSwgZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCkub24oXCJkcmFnc3RhcnRcIiArIG5hbWUsIGQzX2V2ZW50UHJldmVudERlZmF1bHQpLm9uKFwic2VsZWN0c3RhcnRcIiArIG5hbWUsIGQzX2V2ZW50UHJldmVudERlZmF1bHQpO1xuICAgIGlmIChkM19ldmVudF9kcmFnU2VsZWN0ID09IG51bGwpIHtcbiAgICAgIGQzX2V2ZW50X2RyYWdTZWxlY3QgPSBcIm9uc2VsZWN0c3RhcnRcIiBpbiBub2RlID8gZmFsc2UgOiBkM192ZW5kb3JTeW1ib2wobm9kZS5zdHlsZSwgXCJ1c2VyU2VsZWN0XCIpO1xuICAgIH1cbiAgICBpZiAoZDNfZXZlbnRfZHJhZ1NlbGVjdCkge1xuICAgICAgdmFyIHN0eWxlID0gZDNfZG9jdW1lbnRFbGVtZW50KG5vZGUpLnN0eWxlLCBzZWxlY3QgPSBzdHlsZVtkM19ldmVudF9kcmFnU2VsZWN0XTtcbiAgICAgIHN0eWxlW2QzX2V2ZW50X2RyYWdTZWxlY3RdID0gXCJub25lXCI7XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbihzdXBwcmVzc0NsaWNrKSB7XG4gICAgICB3Lm9uKG5hbWUsIG51bGwpO1xuICAgICAgaWYgKGQzX2V2ZW50X2RyYWdTZWxlY3QpIHN0eWxlW2QzX2V2ZW50X2RyYWdTZWxlY3RdID0gc2VsZWN0O1xuICAgICAgaWYgKHN1cHByZXNzQ2xpY2spIHtcbiAgICAgICAgdmFyIG9mZiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHcub24oY2xpY2ssIG51bGwpO1xuICAgICAgICB9O1xuICAgICAgICB3Lm9uKGNsaWNrLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgb2ZmKCk7XG4gICAgICAgIH0sIHRydWUpO1xuICAgICAgICBzZXRUaW1lb3V0KG9mZiwgMCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkMy5tb3VzZSA9IGZ1bmN0aW9uKGNvbnRhaW5lcikge1xuICAgIHJldHVybiBkM19tb3VzZVBvaW50KGNvbnRhaW5lciwgZDNfZXZlbnRTb3VyY2UoKSk7XG4gIH07XG4gIHZhciBkM19tb3VzZV9idWc0NDA4MyA9IHRoaXMubmF2aWdhdG9yICYmIC9XZWJLaXQvLnRlc3QodGhpcy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IC0xIDogMDtcbiAgZnVuY3Rpb24gZDNfbW91c2VQb2ludChjb250YWluZXIsIGUpIHtcbiAgICBpZiAoZS5jaGFuZ2VkVG91Y2hlcykgZSA9IGUuY2hhbmdlZFRvdWNoZXNbMF07XG4gICAgdmFyIHN2ZyA9IGNvbnRhaW5lci5vd25lclNWR0VsZW1lbnQgfHwgY29udGFpbmVyO1xuICAgIGlmIChzdmcuY3JlYXRlU1ZHUG9pbnQpIHtcbiAgICAgIHZhciBwb2ludCA9IHN2Zy5jcmVhdGVTVkdQb2ludCgpO1xuICAgICAgaWYgKGQzX21vdXNlX2J1ZzQ0MDgzIDwgMCkge1xuICAgICAgICB2YXIgd2luZG93ID0gZDNfd2luZG93KGNvbnRhaW5lcik7XG4gICAgICAgIGlmICh3aW5kb3cuc2Nyb2xsWCB8fCB3aW5kb3cuc2Nyb2xsWSkge1xuICAgICAgICAgIHN2ZyA9IGQzLnNlbGVjdChcImJvZHlcIikuYXBwZW5kKFwic3ZnXCIpLnN0eWxlKHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiBcImFic29sdXRlXCIsXG4gICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgbWFyZ2luOiAwLFxuICAgICAgICAgICAgcGFkZGluZzogMCxcbiAgICAgICAgICAgIGJvcmRlcjogXCJub25lXCJcbiAgICAgICAgICB9LCBcImltcG9ydGFudFwiKTtcbiAgICAgICAgICB2YXIgY3RtID0gc3ZnWzBdWzBdLmdldFNjcmVlbkNUTSgpO1xuICAgICAgICAgIGQzX21vdXNlX2J1ZzQ0MDgzID0gIShjdG0uZiB8fCBjdG0uZSk7XG4gICAgICAgICAgc3ZnLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZDNfbW91c2VfYnVnNDQwODMpIHBvaW50LnggPSBlLnBhZ2VYLCBwb2ludC55ID0gZS5wYWdlWTsgZWxzZSBwb2ludC54ID0gZS5jbGllbnRYLCBcbiAgICAgIHBvaW50LnkgPSBlLmNsaWVudFk7XG4gICAgICBwb2ludCA9IHBvaW50Lm1hdHJpeFRyYW5zZm9ybShjb250YWluZXIuZ2V0U2NyZWVuQ1RNKCkuaW52ZXJzZSgpKTtcbiAgICAgIHJldHVybiBbIHBvaW50LngsIHBvaW50LnkgXTtcbiAgICB9XG4gICAgdmFyIHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIFsgZS5jbGllbnRYIC0gcmVjdC5sZWZ0IC0gY29udGFpbmVyLmNsaWVudExlZnQsIGUuY2xpZW50WSAtIHJlY3QudG9wIC0gY29udGFpbmVyLmNsaWVudFRvcCBdO1xuICB9XG4gIGQzLnRvdWNoID0gZnVuY3Rpb24oY29udGFpbmVyLCB0b3VjaGVzLCBpZGVudGlmaWVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBpZGVudGlmaWVyID0gdG91Y2hlcywgdG91Y2hlcyA9IGQzX2V2ZW50U291cmNlKCkuY2hhbmdlZFRvdWNoZXM7XG4gICAgaWYgKHRvdWNoZXMpIGZvciAodmFyIGkgPSAwLCBuID0gdG91Y2hlcy5sZW5ndGgsIHRvdWNoOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKHRvdWNoID0gdG91Y2hlc1tpXSkuaWRlbnRpZmllciA9PT0gaWRlbnRpZmllcikge1xuICAgICAgICByZXR1cm4gZDNfbW91c2VQb2ludChjb250YWluZXIsIHRvdWNoKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIGQzLmJlaGF2aW9yLmRyYWcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKGRyYWcsIFwiZHJhZ1wiLCBcImRyYWdzdGFydFwiLCBcImRyYWdlbmRcIiksIG9yaWdpbiA9IG51bGwsIG1vdXNlZG93biA9IGRyYWdzdGFydChkM19ub29wLCBkMy5tb3VzZSwgZDNfd2luZG93LCBcIm1vdXNlbW92ZVwiLCBcIm1vdXNldXBcIiksIHRvdWNoc3RhcnQgPSBkcmFnc3RhcnQoZDNfYmVoYXZpb3JfZHJhZ1RvdWNoSWQsIGQzLnRvdWNoLCBkM19pZGVudGl0eSwgXCJ0b3VjaG1vdmVcIiwgXCJ0b3VjaGVuZFwiKTtcbiAgICBmdW5jdGlvbiBkcmFnKCkge1xuICAgICAgdGhpcy5vbihcIm1vdXNlZG93bi5kcmFnXCIsIG1vdXNlZG93bikub24oXCJ0b3VjaHN0YXJ0LmRyYWdcIiwgdG91Y2hzdGFydCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRyYWdzdGFydChpZCwgcG9zaXRpb24sIHN1YmplY3QsIG1vdmUsIGVuZCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXMsIHRhcmdldCA9IGQzLmV2ZW50LnRhcmdldC5jb3JyZXNwb25kaW5nRWxlbWVudCB8fCBkMy5ldmVudC50YXJnZXQsIHBhcmVudCA9IHRoYXQucGFyZW50Tm9kZSwgZGlzcGF0Y2ggPSBldmVudC5vZih0aGF0LCBhcmd1bWVudHMpLCBkcmFnZ2VkID0gMCwgZHJhZ0lkID0gaWQoKSwgZHJhZ05hbWUgPSBcIi5kcmFnXCIgKyAoZHJhZ0lkID09IG51bGwgPyBcIlwiIDogXCItXCIgKyBkcmFnSWQpLCBkcmFnT2Zmc2V0LCBkcmFnU3ViamVjdCA9IGQzLnNlbGVjdChzdWJqZWN0KHRhcmdldCkpLm9uKG1vdmUgKyBkcmFnTmFtZSwgbW92ZWQpLm9uKGVuZCArIGRyYWdOYW1lLCBlbmRlZCksIGRyYWdSZXN0b3JlID0gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKHRhcmdldCksIHBvc2l0aW9uMCA9IHBvc2l0aW9uKHBhcmVudCwgZHJhZ0lkKTtcbiAgICAgICAgaWYgKG9yaWdpbikge1xuICAgICAgICAgIGRyYWdPZmZzZXQgPSBvcmlnaW4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICAgICAgICBkcmFnT2Zmc2V0ID0gWyBkcmFnT2Zmc2V0LnggLSBwb3NpdGlvbjBbMF0sIGRyYWdPZmZzZXQueSAtIHBvc2l0aW9uMFsxXSBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRyYWdPZmZzZXQgPSBbIDAsIDAgXTtcbiAgICAgICAgfVxuICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgdHlwZTogXCJkcmFnc3RhcnRcIlxuICAgICAgICB9KTtcbiAgICAgICAgZnVuY3Rpb24gbW92ZWQoKSB7XG4gICAgICAgICAgdmFyIHBvc2l0aW9uMSA9IHBvc2l0aW9uKHBhcmVudCwgZHJhZ0lkKSwgZHgsIGR5O1xuICAgICAgICAgIGlmICghcG9zaXRpb24xKSByZXR1cm47XG4gICAgICAgICAgZHggPSBwb3NpdGlvbjFbMF0gLSBwb3NpdGlvbjBbMF07XG4gICAgICAgICAgZHkgPSBwb3NpdGlvbjFbMV0gLSBwb3NpdGlvbjBbMV07XG4gICAgICAgICAgZHJhZ2dlZCB8PSBkeCB8IGR5O1xuICAgICAgICAgIHBvc2l0aW9uMCA9IHBvc2l0aW9uMTtcbiAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiBcImRyYWdcIixcbiAgICAgICAgICAgIHg6IHBvc2l0aW9uMVswXSArIGRyYWdPZmZzZXRbMF0sXG4gICAgICAgICAgICB5OiBwb3NpdGlvbjFbMV0gKyBkcmFnT2Zmc2V0WzFdLFxuICAgICAgICAgICAgZHg6IGR4LFxuICAgICAgICAgICAgZHk6IGR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZW5kZWQoKSB7XG4gICAgICAgICAgaWYgKCFwb3NpdGlvbihwYXJlbnQsIGRyYWdJZCkpIHJldHVybjtcbiAgICAgICAgICBkcmFnU3ViamVjdC5vbihtb3ZlICsgZHJhZ05hbWUsIG51bGwpLm9uKGVuZCArIGRyYWdOYW1lLCBudWxsKTtcbiAgICAgICAgICBkcmFnUmVzdG9yZShkcmFnZ2VkKTtcbiAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiBcImRyYWdlbmRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICBkcmFnLm9yaWdpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG9yaWdpbjtcbiAgICAgIG9yaWdpbiA9IHg7XG4gICAgICByZXR1cm4gZHJhZztcbiAgICB9O1xuICAgIHJldHVybiBkMy5yZWJpbmQoZHJhZywgZXZlbnQsIFwib25cIik7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2JlaGF2aW9yX2RyYWdUb3VjaElkKCkge1xuICAgIHJldHVybiBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5pZGVudGlmaWVyO1xuICB9XG4gIGQzLnRvdWNoZXMgPSBmdW5jdGlvbihjb250YWluZXIsIHRvdWNoZXMpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHRvdWNoZXMgPSBkM19ldmVudFNvdXJjZSgpLnRvdWNoZXM7XG4gICAgcmV0dXJuIHRvdWNoZXMgPyBkM19hcnJheSh0b3VjaGVzKS5tYXAoZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgIHZhciBwb2ludCA9IGQzX21vdXNlUG9pbnQoY29udGFpbmVyLCB0b3VjaCk7XG4gICAgICBwb2ludC5pZGVudGlmaWVyID0gdG91Y2guaWRlbnRpZmllcjtcbiAgICAgIHJldHVybiBwb2ludDtcbiAgICB9KSA6IFtdO1xuICB9O1xuICB2YXIgzrUgPSAxZS02LCDOtTIgPSDOtSAqIM61LCDPgCA9IE1hdGguUEksIM+EID0gMiAqIM+ALCDPhM61ID0gz4QgLSDOtSwgaGFsZs+AID0gz4AgLyAyLCBkM19yYWRpYW5zID0gz4AgLyAxODAsIGQzX2RlZ3JlZXMgPSAxODAgLyDPgDtcbiAgZnVuY3Rpb24gZDNfc2duKHgpIHtcbiAgICByZXR1cm4geCA+IDAgPyAxIDogeCA8IDAgPyAtMSA6IDA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfY3Jvc3MyZChhLCBiLCBjKSB7XG4gICAgcmV0dXJuIChiWzBdIC0gYVswXSkgKiAoY1sxXSAtIGFbMV0pIC0gKGJbMV0gLSBhWzFdKSAqIChjWzBdIC0gYVswXSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfYWNvcyh4KSB7XG4gICAgcmV0dXJuIHggPiAxID8gMCA6IHggPCAtMSA/IM+AIDogTWF0aC5hY29zKHgpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2FzaW4oeCkge1xuICAgIHJldHVybiB4ID4gMSA/IGhhbGbPgCA6IHggPCAtMSA/IC1oYWxmz4AgOiBNYXRoLmFzaW4oeCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2luaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSAtIDEgLyB4KSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfY29zaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSArIDEgLyB4KSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGFuaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKDIgKiB4KSkgLSAxKSAvICh4ICsgMSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfaGF2ZXJzaW4oeCkge1xuICAgIHJldHVybiAoeCA9IE1hdGguc2luKHggLyAyKSkgKiB4O1xuICB9XG4gIHZhciDPgSA9IE1hdGguU1FSVDIsIM+BMiA9IDIsIM+BNCA9IDQ7XG4gIGQzLmludGVycG9sYXRlWm9vbSA9IGZ1bmN0aW9uKHAwLCBwMSkge1xuICAgIHZhciB1eDAgPSBwMFswXSwgdXkwID0gcDBbMV0sIHcwID0gcDBbMl0sIHV4MSA9IHAxWzBdLCB1eTEgPSBwMVsxXSwgdzEgPSBwMVsyXSwgZHggPSB1eDEgLSB1eDAsIGR5ID0gdXkxIC0gdXkwLCBkMiA9IGR4ICogZHggKyBkeSAqIGR5LCBpLCBTO1xuICAgIGlmIChkMiA8IM61Mikge1xuICAgICAgUyA9IE1hdGgubG9nKHcxIC8gdzApIC8gz4E7XG4gICAgICBpID0gZnVuY3Rpb24odCkge1xuICAgICAgICByZXR1cm4gWyB1eDAgKyB0ICogZHgsIHV5MCArIHQgKiBkeSwgdzAgKiBNYXRoLmV4cCjPgSAqIHQgKiBTKSBdO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGQxID0gTWF0aC5zcXJ0KGQyKSwgYjAgPSAodzEgKiB3MSAtIHcwICogdzAgKyDPgTQgKiBkMikgLyAoMiAqIHcwICogz4EyICogZDEpLCBiMSA9ICh3MSAqIHcxIC0gdzAgKiB3MCAtIM+BNCAqIGQyKSAvICgyICogdzEgKiDPgTIgKiBkMSksIHIwID0gTWF0aC5sb2coTWF0aC5zcXJ0KGIwICogYjAgKyAxKSAtIGIwKSwgcjEgPSBNYXRoLmxvZyhNYXRoLnNxcnQoYjEgKiBiMSArIDEpIC0gYjEpO1xuICAgICAgUyA9IChyMSAtIHIwKSAvIM+BO1xuICAgICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdmFyIHMgPSB0ICogUywgY29zaHIwID0gZDNfY29zaChyMCksIHUgPSB3MCAvICjPgTIgKiBkMSkgKiAoY29zaHIwICogZDNfdGFuaCjPgSAqIHMgKyByMCkgLSBkM19zaW5oKHIwKSk7XG4gICAgICAgIHJldHVybiBbIHV4MCArIHUgKiBkeCwgdXkwICsgdSAqIGR5LCB3MCAqIGNvc2hyMCAvIGQzX2Nvc2goz4EgKiBzICsgcjApIF07XG4gICAgICB9O1xuICAgIH1cbiAgICBpLmR1cmF0aW9uID0gUyAqIDFlMztcbiAgICByZXR1cm4gaTtcbiAgfTtcbiAgZDMuYmVoYXZpb3Iuem9vbSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2aWV3ID0ge1xuICAgICAgeDogMCxcbiAgICAgIHk6IDAsXG4gICAgICBrOiAxXG4gICAgfSwgdHJhbnNsYXRlMCwgY2VudGVyMCwgY2VudGVyLCBzaXplID0gWyA5NjAsIDUwMCBdLCBzY2FsZUV4dGVudCA9IGQzX2JlaGF2aW9yX3pvb21JbmZpbml0eSwgZHVyYXRpb24gPSAyNTAsIHpvb21pbmcgPSAwLCBtb3VzZWRvd24gPSBcIm1vdXNlZG93bi56b29tXCIsIG1vdXNlbW92ZSA9IFwibW91c2Vtb3ZlLnpvb21cIiwgbW91c2V1cCA9IFwibW91c2V1cC56b29tXCIsIG1vdXNld2hlZWxUaW1lciwgdG91Y2hzdGFydCA9IFwidG91Y2hzdGFydC56b29tXCIsIHRvdWNodGltZSwgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKHpvb20sIFwiem9vbXN0YXJ0XCIsIFwiem9vbVwiLCBcInpvb21lbmRcIiksIHgwLCB4MSwgeTAsIHkxO1xuICAgIGlmICghZDNfYmVoYXZpb3Jfem9vbVdoZWVsKSB7XG4gICAgICBkM19iZWhhdmlvcl96b29tV2hlZWwgPSBcIm9ud2hlZWxcIiBpbiBkM19kb2N1bWVudCA/IChkM19iZWhhdmlvcl96b29tRGVsdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIC1kMy5ldmVudC5kZWx0YVkgKiAoZDMuZXZlbnQuZGVsdGFNb2RlID8gMTIwIDogMSk7XG4gICAgICB9LCBcIndoZWVsXCIpIDogXCJvbm1vdXNld2hlZWxcIiBpbiBkM19kb2N1bWVudCA/IChkM19iZWhhdmlvcl96b29tRGVsdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGQzLmV2ZW50LndoZWVsRGVsdGE7XG4gICAgICB9LCBcIm1vdXNld2hlZWxcIikgOiAoZDNfYmVoYXZpb3Jfem9vbURlbHRhID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAtZDMuZXZlbnQuZGV0YWlsO1xuICAgICAgfSwgXCJNb3pNb3VzZVBpeGVsU2Nyb2xsXCIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB6b29tKGcpIHtcbiAgICAgIGcub24obW91c2Vkb3duLCBtb3VzZWRvd25lZCkub24oZDNfYmVoYXZpb3Jfem9vbVdoZWVsICsgXCIuem9vbVwiLCBtb3VzZXdoZWVsZWQpLm9uKFwiZGJsY2xpY2suem9vbVwiLCBkYmxjbGlja2VkKS5vbih0b3VjaHN0YXJ0LCB0b3VjaHN0YXJ0ZWQpO1xuICAgIH1cbiAgICB6b29tLmV2ZW50ID0gZnVuY3Rpb24oZykge1xuICAgICAgZy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZGlzcGF0Y2ggPSBldmVudC5vZih0aGlzLCBhcmd1bWVudHMpLCB2aWV3MSA9IHZpZXc7XG4gICAgICAgIGlmIChkM190cmFuc2l0aW9uSW5oZXJpdElkKSB7XG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5lYWNoKFwic3RhcnQuem9vbVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZpZXcgPSB0aGlzLl9fY2hhcnRfXyB8fCB7XG4gICAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgIGs6IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB6b29tc3RhcnRlZChkaXNwYXRjaCk7XG4gICAgICAgICAgfSkudHdlZW4oXCJ6b29tOnpvb21cIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZHggPSBzaXplWzBdLCBkeSA9IHNpemVbMV0sIGN4ID0gY2VudGVyMCA/IGNlbnRlcjBbMF0gOiBkeCAvIDIsIGN5ID0gY2VudGVyMCA/IGNlbnRlcjBbMV0gOiBkeSAvIDIsIGkgPSBkMy5pbnRlcnBvbGF0ZVpvb20oWyAoY3ggLSB2aWV3LngpIC8gdmlldy5rLCAoY3kgLSB2aWV3LnkpIC8gdmlldy5rLCBkeCAvIHZpZXcuayBdLCBbIChjeCAtIHZpZXcxLngpIC8gdmlldzEuaywgKGN5IC0gdmlldzEueSkgLyB2aWV3MS5rLCBkeCAvIHZpZXcxLmsgXSk7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICB2YXIgbCA9IGkodCksIGsgPSBkeCAvIGxbMl07XG4gICAgICAgICAgICAgIHRoaXMuX19jaGFydF9fID0gdmlldyA9IHtcbiAgICAgICAgICAgICAgICB4OiBjeCAtIGxbMF0gKiBrLFxuICAgICAgICAgICAgICAgIHk6IGN5IC0gbFsxXSAqIGssXG4gICAgICAgICAgICAgICAgazoga1xuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KS5lYWNoKFwiaW50ZXJydXB0Lnpvb21cIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB6b29tZW5kZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgIH0pLmVhY2goXCJlbmQuem9vbVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fX2NoYXJ0X18gPSB2aWV3O1xuICAgICAgICAgIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgem9vbS50cmFuc2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHZpZXcueCwgdmlldy55IF07XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiArX1swXSxcbiAgICAgICAgeTogK19bMV0sXG4gICAgICAgIGs6IHZpZXcua1xuICAgICAgfTtcbiAgICAgIHJlc2NhbGUoKTtcbiAgICAgIHJldHVybiB6b29tO1xuICAgIH07XG4gICAgem9vbS5zY2FsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZpZXcuaztcbiAgICAgIHZpZXcgPSB7XG4gICAgICAgIHg6IHZpZXcueCxcbiAgICAgICAgeTogdmlldy55LFxuICAgICAgICBrOiBudWxsXG4gICAgICB9O1xuICAgICAgc2NhbGVUbygrXyk7XG4gICAgICByZXNjYWxlKCk7XG4gICAgICByZXR1cm4gem9vbTtcbiAgICB9O1xuICAgIHpvb20uc2NhbGVFeHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzY2FsZUV4dGVudDtcbiAgICAgIHNjYWxlRXh0ZW50ID0gXyA9PSBudWxsID8gZDNfYmVoYXZpb3Jfem9vbUluZmluaXR5IDogWyArX1swXSwgK19bMV0gXTtcbiAgICAgIHJldHVybiB6b29tO1xuICAgIH07XG4gICAgem9vbS5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjZW50ZXI7XG4gICAgICBjZW50ZXIgPSBfICYmIFsgK19bMF0sICtfWzFdIF07XG4gICAgICByZXR1cm4gem9vbTtcbiAgICB9O1xuICAgIHpvb20uc2l6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNpemU7XG4gICAgICBzaXplID0gXyAmJiBbICtfWzBdLCArX1sxXSBdO1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLmR1cmF0aW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZHVyYXRpb247XG4gICAgICBkdXJhdGlvbiA9ICtfO1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLnggPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB4MTtcbiAgICAgIHgxID0gejtcbiAgICAgIHgwID0gei5jb3B5KCk7XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICBrOiAxXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLnkgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5MTtcbiAgICAgIHkxID0gejtcbiAgICAgIHkwID0gei5jb3B5KCk7XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICBrOiAxXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICBmdW5jdGlvbiBsb2NhdGlvbihwKSB7XG4gICAgICByZXR1cm4gWyAocFswXSAtIHZpZXcueCkgLyB2aWV3LmssIChwWzFdIC0gdmlldy55KSAvIHZpZXcuayBdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludChsKSB7XG4gICAgICByZXR1cm4gWyBsWzBdICogdmlldy5rICsgdmlldy54LCBsWzFdICogdmlldy5rICsgdmlldy55IF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlVG8ocykge1xuICAgICAgdmlldy5rID0gTWF0aC5tYXgoc2NhbGVFeHRlbnRbMF0sIE1hdGgubWluKHNjYWxlRXh0ZW50WzFdLCBzKSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZVRvKHAsIGwpIHtcbiAgICAgIGwgPSBwb2ludChsKTtcbiAgICAgIHZpZXcueCArPSBwWzBdIC0gbFswXTtcbiAgICAgIHZpZXcueSArPSBwWzFdIC0gbFsxXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbVRvKHRoYXQsIHAsIGwsIGspIHtcbiAgICAgIHRoYXQuX19jaGFydF9fID0ge1xuICAgICAgICB4OiB2aWV3LngsXG4gICAgICAgIHk6IHZpZXcueSxcbiAgICAgICAgazogdmlldy5rXG4gICAgICB9O1xuICAgICAgc2NhbGVUbyhNYXRoLnBvdygyLCBrKSk7XG4gICAgICB0cmFuc2xhdGVUbyhjZW50ZXIwID0gcCwgbCk7XG4gICAgICB0aGF0ID0gZDMuc2VsZWN0KHRoYXQpO1xuICAgICAgaWYgKGR1cmF0aW9uID4gMCkgdGhhdCA9IHRoYXQudHJhbnNpdGlvbigpLmR1cmF0aW9uKGR1cmF0aW9uKTtcbiAgICAgIHRoYXQuY2FsbCh6b29tLmV2ZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICAgIGlmICh4MSkgeDEuZG9tYWluKHgwLnJhbmdlKCkubWFwKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgcmV0dXJuICh4IC0gdmlldy54KSAvIHZpZXcuaztcbiAgICAgIH0pLm1hcCh4MC5pbnZlcnQpKTtcbiAgICAgIGlmICh5MSkgeTEuZG9tYWluKHkwLnJhbmdlKCkubWFwKGZ1bmN0aW9uKHkpIHtcbiAgICAgICAgcmV0dXJuICh5IC0gdmlldy55KSAvIHZpZXcuaztcbiAgICAgIH0pLm1hcCh5MC5pbnZlcnQpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbXN0YXJ0ZWQoZGlzcGF0Y2gpIHtcbiAgICAgIGlmICghem9vbWluZysrKSBkaXNwYXRjaCh7XG4gICAgICAgIHR5cGU6IFwiem9vbXN0YXJ0XCJcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiB6b29tZWQoZGlzcGF0Y2gpIHtcbiAgICAgIHJlc2NhbGUoKTtcbiAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgdHlwZTogXCJ6b29tXCIsXG4gICAgICAgIHNjYWxlOiB2aWV3LmssXG4gICAgICAgIHRyYW5zbGF0ZTogWyB2aWV3LngsIHZpZXcueSBdXG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbWVuZGVkKGRpc3BhdGNoKSB7XG4gICAgICBpZiAoIS0tem9vbWluZykgZGlzcGF0Y2goe1xuICAgICAgICB0eXBlOiBcInpvb21lbmRcIlxuICAgICAgfSksIGNlbnRlcjAgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiBtb3VzZWRvd25lZCgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcywgZGlzcGF0Y2ggPSBldmVudC5vZih0aGF0LCBhcmd1bWVudHMpLCBkcmFnZ2VkID0gMCwgc3ViamVjdCA9IGQzLnNlbGVjdChkM193aW5kb3codGhhdCkpLm9uKG1vdXNlbW92ZSwgbW92ZWQpLm9uKG1vdXNldXAsIGVuZGVkKSwgbG9jYXRpb24wID0gbG9jYXRpb24oZDMubW91c2UodGhhdCkpLCBkcmFnUmVzdG9yZSA9IGQzX2V2ZW50X2RyYWdTdXBwcmVzcyh0aGF0KTtcbiAgICAgIGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQuY2FsbCh0aGF0KTtcbiAgICAgIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgIGZ1bmN0aW9uIG1vdmVkKCkge1xuICAgICAgICBkcmFnZ2VkID0gMTtcbiAgICAgICAgdHJhbnNsYXRlVG8oZDMubW91c2UodGhhdCksIGxvY2F0aW9uMCk7XG4gICAgICAgIHpvb21lZChkaXNwYXRjaCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBlbmRlZCgpIHtcbiAgICAgICAgc3ViamVjdC5vbihtb3VzZW1vdmUsIG51bGwpLm9uKG1vdXNldXAsIG51bGwpO1xuICAgICAgICBkcmFnUmVzdG9yZShkcmFnZ2VkKTtcbiAgICAgICAgem9vbWVuZGVkKGRpc3BhdGNoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gdG91Y2hzdGFydGVkKCkge1xuICAgICAgdmFyIHRoYXQgPSB0aGlzLCBkaXNwYXRjaCA9IGV2ZW50Lm9mKHRoYXQsIGFyZ3VtZW50cyksIGxvY2F0aW9uczAgPSB7fSwgZGlzdGFuY2UwID0gMCwgc2NhbGUwLCB6b29tTmFtZSA9IFwiLnpvb20tXCIgKyBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5pZGVudGlmaWVyLCB0b3VjaG1vdmUgPSBcInRvdWNobW92ZVwiICsgem9vbU5hbWUsIHRvdWNoZW5kID0gXCJ0b3VjaGVuZFwiICsgem9vbU5hbWUsIHRhcmdldHMgPSBbXSwgc3ViamVjdCA9IGQzLnNlbGVjdCh0aGF0KSwgZHJhZ1Jlc3RvcmUgPSBkM19ldmVudF9kcmFnU3VwcHJlc3ModGhhdCk7XG4gICAgICBzdGFydGVkKCk7XG4gICAgICB6b29tc3RhcnRlZChkaXNwYXRjaCk7XG4gICAgICBzdWJqZWN0Lm9uKG1vdXNlZG93biwgbnVsbCkub24odG91Y2hzdGFydCwgc3RhcnRlZCk7XG4gICAgICBmdW5jdGlvbiByZWxvY2F0ZSgpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBkMy50b3VjaGVzKHRoYXQpO1xuICAgICAgICBzY2FsZTAgPSB2aWV3Lms7XG4gICAgICAgIHRvdWNoZXMuZm9yRWFjaChmdW5jdGlvbih0KSB7XG4gICAgICAgICAgaWYgKHQuaWRlbnRpZmllciBpbiBsb2NhdGlvbnMwKSBsb2NhdGlvbnMwW3QuaWRlbnRpZmllcl0gPSBsb2NhdGlvbih0KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0b3VjaGVzO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc3RhcnRlZCgpIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGQzLmV2ZW50LnRhcmdldDtcbiAgICAgICAgZDMuc2VsZWN0KHRhcmdldCkub24odG91Y2htb3ZlLCBtb3ZlZCkub24odG91Y2hlbmQsIGVuZGVkKTtcbiAgICAgICAgdGFyZ2V0cy5wdXNoKHRhcmdldCk7XG4gICAgICAgIHZhciBjaGFuZ2VkID0gZDMuZXZlbnQuY2hhbmdlZFRvdWNoZXM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gY2hhbmdlZC5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBsb2NhdGlvbnMwW2NoYW5nZWRbaV0uaWRlbnRpZmllcl0gPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0b3VjaGVzID0gcmVsb2NhdGUoKSwgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKHRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgaWYgKG5vdyAtIHRvdWNodGltZSA8IDUwMCkge1xuICAgICAgICAgICAgdmFyIHAgPSB0b3VjaGVzWzBdO1xuICAgICAgICAgICAgem9vbVRvKHRoYXQsIHAsIGxvY2F0aW9uczBbcC5pZGVudGlmaWVyXSwgTWF0aC5mbG9vcihNYXRoLmxvZyh2aWV3LmspIC8gTWF0aC5MTjIpICsgMSk7XG4gICAgICAgICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRvdWNodGltZSA9IG5vdztcbiAgICAgICAgfSBlbHNlIGlmICh0b3VjaGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB2YXIgcCA9IHRvdWNoZXNbMF0sIHEgPSB0b3VjaGVzWzFdLCBkeCA9IHBbMF0gLSBxWzBdLCBkeSA9IHBbMV0gLSBxWzFdO1xuICAgICAgICAgIGRpc3RhbmNlMCA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBtb3ZlZCgpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBkMy50b3VjaGVzKHRoYXQpLCBwMCwgbDAsIHAxLCBsMTtcbiAgICAgICAgZDNfc2VsZWN0aW9uX2ludGVycnVwdC5jYWxsKHRoYXQpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IHRvdWNoZXMubGVuZ3RoOyBpIDwgbjsgKytpLCBsMSA9IG51bGwpIHtcbiAgICAgICAgICBwMSA9IHRvdWNoZXNbaV07XG4gICAgICAgICAgaWYgKGwxID0gbG9jYXRpb25zMFtwMS5pZGVudGlmaWVyXSkge1xuICAgICAgICAgICAgaWYgKGwwKSBicmVhaztcbiAgICAgICAgICAgIHAwID0gcDEsIGwwID0gbDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChsMSkge1xuICAgICAgICAgIHZhciBkaXN0YW5jZTEgPSAoZGlzdGFuY2UxID0gcDFbMF0gLSBwMFswXSkgKiBkaXN0YW5jZTEgKyAoZGlzdGFuY2UxID0gcDFbMV0gLSBwMFsxXSkgKiBkaXN0YW5jZTEsIHNjYWxlMSA9IGRpc3RhbmNlMCAmJiBNYXRoLnNxcnQoZGlzdGFuY2UxIC8gZGlzdGFuY2UwKTtcbiAgICAgICAgICBwMCA9IFsgKHAwWzBdICsgcDFbMF0pIC8gMiwgKHAwWzFdICsgcDFbMV0pIC8gMiBdO1xuICAgICAgICAgIGwwID0gWyAobDBbMF0gKyBsMVswXSkgLyAyLCAobDBbMV0gKyBsMVsxXSkgLyAyIF07XG4gICAgICAgICAgc2NhbGVUbyhzY2FsZTEgKiBzY2FsZTApO1xuICAgICAgICB9XG4gICAgICAgIHRvdWNodGltZSA9IG51bGw7XG4gICAgICAgIHRyYW5zbGF0ZVRvKHAwLCBsMCk7XG4gICAgICAgIHpvb21lZChkaXNwYXRjaCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBlbmRlZCgpIHtcbiAgICAgICAgaWYgKGQzLmV2ZW50LnRvdWNoZXMubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGNoYW5nZWQgPSBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlcztcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGNoYW5nZWQubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICBkZWxldGUgbG9jYXRpb25zMFtjaGFuZ2VkW2ldLmlkZW50aWZpZXJdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IgKHZhciBpZGVudGlmaWVyIGluIGxvY2F0aW9uczApIHtcbiAgICAgICAgICAgIHJldHVybiB2b2lkIHJlbG9jYXRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGQzLnNlbGVjdEFsbCh0YXJnZXRzKS5vbih6b29tTmFtZSwgbnVsbCk7XG4gICAgICAgIHN1YmplY3Qub24obW91c2Vkb3duLCBtb3VzZWRvd25lZCkub24odG91Y2hzdGFydCwgdG91Y2hzdGFydGVkKTtcbiAgICAgICAgZHJhZ1Jlc3RvcmUoKTtcbiAgICAgICAgem9vbWVuZGVkKGRpc3BhdGNoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gbW91c2V3aGVlbGVkKCkge1xuICAgICAgdmFyIGRpc3BhdGNoID0gZXZlbnQub2YodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmIChtb3VzZXdoZWVsVGltZXIpIGNsZWFyVGltZW91dChtb3VzZXdoZWVsVGltZXIpOyBlbHNlIGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQuY2FsbCh0aGlzKSwgXG4gICAgICB0cmFuc2xhdGUwID0gbG9jYXRpb24oY2VudGVyMCA9IGNlbnRlciB8fCBkMy5tb3VzZSh0aGlzKSksIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgIG1vdXNld2hlZWxUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIG1vdXNld2hlZWxUaW1lciA9IG51bGw7XG4gICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICB9LCA1MCk7XG4gICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICBzY2FsZVRvKE1hdGgucG93KDIsIGQzX2JlaGF2aW9yX3pvb21EZWx0YSgpICogLjAwMikgKiB2aWV3LmspO1xuICAgICAgdHJhbnNsYXRlVG8oY2VudGVyMCwgdHJhbnNsYXRlMCk7XG4gICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkYmxjbGlja2VkKCkge1xuICAgICAgdmFyIHAgPSBkMy5tb3VzZSh0aGlzKSwgayA9IE1hdGgubG9nKHZpZXcuaykgLyBNYXRoLkxOMjtcbiAgICAgIHpvb21Ubyh0aGlzLCBwLCBsb2NhdGlvbihwKSwgZDMuZXZlbnQuc2hpZnRLZXkgPyBNYXRoLmNlaWwoaykgLSAxIDogTWF0aC5mbG9vcihrKSArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gZDMucmViaW5kKHpvb20sIGV2ZW50LCBcIm9uXCIpO1xuICB9O1xuICB2YXIgZDNfYmVoYXZpb3Jfem9vbUluZmluaXR5ID0gWyAwLCBJbmZpbml0eSBdLCBkM19iZWhhdmlvcl96b29tRGVsdGEsIGQzX2JlaGF2aW9yX3pvb21XaGVlbDtcbiAgZDMuY29sb3IgPSBkM19jb2xvcjtcbiAgZnVuY3Rpb24gZDNfY29sb3IoKSB7fVxuICBkM19jb2xvci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5yZ2IoKSArIFwiXCI7XG4gIH07XG4gIGQzLmhzbCA9IGQzX2hzbDtcbiAgZnVuY3Rpb24gZDNfaHNsKGgsIHMsIGwpIHtcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIGQzX2hzbCA/IHZvaWQgKHRoaXMuaCA9ICtoLCB0aGlzLnMgPSArcywgdGhpcy5sID0gK2wpIDogYXJndW1lbnRzLmxlbmd0aCA8IDIgPyBoIGluc3RhbmNlb2YgZDNfaHNsID8gbmV3IGQzX2hzbChoLmgsIGgucywgaC5sKSA6IGQzX3JnYl9wYXJzZShcIlwiICsgaCwgZDNfcmdiX2hzbCwgZDNfaHNsKSA6IG5ldyBkM19oc2woaCwgcywgbCk7XG4gIH1cbiAgdmFyIGQzX2hzbFByb3RvdHlwZSA9IGQzX2hzbC5wcm90b3R5cGUgPSBuZXcgZDNfY29sb3IoKTtcbiAgZDNfaHNsUHJvdG90eXBlLmJyaWdodGVyID0gZnVuY3Rpb24oaykge1xuICAgIGsgPSBNYXRoLnBvdyguNywgYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKTtcbiAgICByZXR1cm4gbmV3IGQzX2hzbCh0aGlzLmgsIHRoaXMucywgdGhpcy5sIC8gayk7XG4gIH07XG4gIGQzX2hzbFByb3RvdHlwZS5kYXJrZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgayA9IE1hdGgucG93KC43LCBhcmd1bWVudHMubGVuZ3RoID8gayA6IDEpO1xuICAgIHJldHVybiBuZXcgZDNfaHNsKHRoaXMuaCwgdGhpcy5zLCBrICogdGhpcy5sKTtcbiAgfTtcbiAgZDNfaHNsUHJvdG90eXBlLnJnYiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19oc2xfcmdiKHRoaXMuaCwgdGhpcy5zLCB0aGlzLmwpO1xuICB9O1xuICBmdW5jdGlvbiBkM19oc2xfcmdiKGgsIHMsIGwpIHtcbiAgICB2YXIgbTEsIG0yO1xuICAgIGggPSBpc05hTihoKSA/IDAgOiAoaCAlPSAzNjApIDwgMCA/IGggKyAzNjAgOiBoO1xuICAgIHMgPSBpc05hTihzKSA/IDAgOiBzIDwgMCA/IDAgOiBzID4gMSA/IDEgOiBzO1xuICAgIGwgPSBsIDwgMCA/IDAgOiBsID4gMSA/IDEgOiBsO1xuICAgIG0yID0gbCA8PSAuNSA/IGwgKiAoMSArIHMpIDogbCArIHMgLSBsICogcztcbiAgICBtMSA9IDIgKiBsIC0gbTI7XG4gICAgZnVuY3Rpb24gdihoKSB7XG4gICAgICBpZiAoaCA+IDM2MCkgaCAtPSAzNjA7IGVsc2UgaWYgKGggPCAwKSBoICs9IDM2MDtcbiAgICAgIGlmIChoIDwgNjApIHJldHVybiBtMSArIChtMiAtIG0xKSAqIGggLyA2MDtcbiAgICAgIGlmIChoIDwgMTgwKSByZXR1cm4gbTI7XG4gICAgICBpZiAoaCA8IDI0MCkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDI0MCAtIGgpIC8gNjA7XG4gICAgICByZXR1cm4gbTE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHZ2KGgpIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHYoaCkgKiAyNTUpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IGQzX3JnYih2dihoICsgMTIwKSwgdnYoaCksIHZ2KGggLSAxMjApKTtcbiAgfVxuICBkMy5oY2wgPSBkM19oY2w7XG4gIGZ1bmN0aW9uIGQzX2hjbChoLCBjLCBsKSB7XG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBkM19oY2wgPyB2b2lkICh0aGlzLmggPSAraCwgdGhpcy5jID0gK2MsIHRoaXMubCA9ICtsKSA6IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gaCBpbnN0YW5jZW9mIGQzX2hjbCA/IG5ldyBkM19oY2woaC5oLCBoLmMsIGgubCkgOiBoIGluc3RhbmNlb2YgZDNfbGFiID8gZDNfbGFiX2hjbChoLmwsIGguYSwgaC5iKSA6IGQzX2xhYl9oY2woKGggPSBkM19yZ2JfbGFiKChoID0gZDMucmdiKGgpKS5yLCBoLmcsIGguYikpLmwsIGguYSwgaC5iKSA6IG5ldyBkM19oY2woaCwgYywgbCk7XG4gIH1cbiAgdmFyIGQzX2hjbFByb3RvdHlwZSA9IGQzX2hjbC5wcm90b3R5cGUgPSBuZXcgZDNfY29sb3IoKTtcbiAgZDNfaGNsUHJvdG90eXBlLmJyaWdodGVyID0gZnVuY3Rpb24oaykge1xuICAgIHJldHVybiBuZXcgZDNfaGNsKHRoaXMuaCwgdGhpcy5jLCBNYXRoLm1pbigxMDAsIHRoaXMubCArIGQzX2xhYl9LICogKGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSkpKTtcbiAgfTtcbiAgZDNfaGNsUHJvdG90eXBlLmRhcmtlciA9IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IGQzX2hjbCh0aGlzLmgsIHRoaXMuYywgTWF0aC5tYXgoMCwgdGhpcy5sIC0gZDNfbGFiX0sgKiAoYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKSkpO1xuICB9O1xuICBkM19oY2xQcm90b3R5cGUucmdiID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2hjbF9sYWIodGhpcy5oLCB0aGlzLmMsIHRoaXMubCkucmdiKCk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2hjbF9sYWIoaCwgYywgbCkge1xuICAgIGlmIChpc05hTihoKSkgaCA9IDA7XG4gICAgaWYgKGlzTmFOKGMpKSBjID0gMDtcbiAgICByZXR1cm4gbmV3IGQzX2xhYihsLCBNYXRoLmNvcyhoICo9IGQzX3JhZGlhbnMpICogYywgTWF0aC5zaW4oaCkgKiBjKTtcbiAgfVxuICBkMy5sYWIgPSBkM19sYWI7XG4gIGZ1bmN0aW9uIGQzX2xhYihsLCBhLCBiKSB7XG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBkM19sYWIgPyB2b2lkICh0aGlzLmwgPSArbCwgdGhpcy5hID0gK2EsIHRoaXMuYiA9ICtiKSA6IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gbCBpbnN0YW5jZW9mIGQzX2xhYiA/IG5ldyBkM19sYWIobC5sLCBsLmEsIGwuYikgOiBsIGluc3RhbmNlb2YgZDNfaGNsID8gZDNfaGNsX2xhYihsLmgsIGwuYywgbC5sKSA6IGQzX3JnYl9sYWIoKGwgPSBkM19yZ2IobCkpLnIsIGwuZywgbC5iKSA6IG5ldyBkM19sYWIobCwgYSwgYik7XG4gIH1cbiAgdmFyIGQzX2xhYl9LID0gMTg7XG4gIHZhciBkM19sYWJfWCA9IC45NTA0NywgZDNfbGFiX1kgPSAxLCBkM19sYWJfWiA9IDEuMDg4ODM7XG4gIHZhciBkM19sYWJQcm90b3R5cGUgPSBkM19sYWIucHJvdG90eXBlID0gbmV3IGQzX2NvbG9yKCk7XG4gIGQzX2xhYlByb3RvdHlwZS5icmlnaHRlciA9IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IGQzX2xhYihNYXRoLm1pbigxMDAsIHRoaXMubCArIGQzX2xhYl9LICogKGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSkpLCB0aGlzLmEsIHRoaXMuYik7XG4gIH07XG4gIGQzX2xhYlByb3RvdHlwZS5kYXJrZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBkM19sYWIoTWF0aC5tYXgoMCwgdGhpcy5sIC0gZDNfbGFiX0sgKiAoYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKSksIHRoaXMuYSwgdGhpcy5iKTtcbiAgfTtcbiAgZDNfbGFiUHJvdG90eXBlLnJnYiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19sYWJfcmdiKHRoaXMubCwgdGhpcy5hLCB0aGlzLmIpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYWJfcmdiKGwsIGEsIGIpIHtcbiAgICB2YXIgeSA9IChsICsgMTYpIC8gMTE2LCB4ID0geSArIGEgLyA1MDAsIHogPSB5IC0gYiAvIDIwMDtcbiAgICB4ID0gZDNfbGFiX3h5eih4KSAqIGQzX2xhYl9YO1xuICAgIHkgPSBkM19sYWJfeHl6KHkpICogZDNfbGFiX1k7XG4gICAgeiA9IGQzX2xhYl94eXooeikgKiBkM19sYWJfWjtcbiAgICByZXR1cm4gbmV3IGQzX3JnYihkM194eXpfcmdiKDMuMjQwNDU0MiAqIHggLSAxLjUzNzEzODUgKiB5IC0gLjQ5ODUzMTQgKiB6KSwgZDNfeHl6X3JnYigtLjk2OTI2NiAqIHggKyAxLjg3NjAxMDggKiB5ICsgLjA0MTU1NiAqIHopLCBkM194eXpfcmdiKC4wNTU2NDM0ICogeCAtIC4yMDQwMjU5ICogeSArIDEuMDU3MjI1MiAqIHopKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYWJfaGNsKGwsIGEsIGIpIHtcbiAgICByZXR1cm4gbCA+IDAgPyBuZXcgZDNfaGNsKE1hdGguYXRhbjIoYiwgYSkgKiBkM19kZWdyZWVzLCBNYXRoLnNxcnQoYSAqIGEgKyBiICogYiksIGwpIDogbmV3IGQzX2hjbChOYU4sIE5hTiwgbCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGFiX3h5eih4KSB7XG4gICAgcmV0dXJuIHggPiAuMjA2ODkzMDM0ID8geCAqIHggKiB4IDogKHggLSA0IC8gMjkpIC8gNy43ODcwMzc7XG4gIH1cbiAgZnVuY3Rpb24gZDNfeHl6X2xhYih4KSB7XG4gICAgcmV0dXJuIHggPiAuMDA4ODU2ID8gTWF0aC5wb3coeCwgMSAvIDMpIDogNy43ODcwMzcgKiB4ICsgNCAvIDI5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3h5el9yZ2Iocikge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKDI1NSAqIChyIDw9IC4wMDMwNCA/IDEyLjkyICogciA6IDEuMDU1ICogTWF0aC5wb3cociwgMSAvIDIuNCkgLSAuMDU1KSk7XG4gIH1cbiAgZDMucmdiID0gZDNfcmdiO1xuICBmdW5jdGlvbiBkM19yZ2IociwgZywgYikge1xuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgZDNfcmdiID8gdm9pZCAodGhpcy5yID0gfn5yLCB0aGlzLmcgPSB+fmcsIHRoaXMuYiA9IH5+YikgOiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IHIgaW5zdGFuY2VvZiBkM19yZ2IgPyBuZXcgZDNfcmdiKHIuciwgci5nLCByLmIpIDogZDNfcmdiX3BhcnNlKFwiXCIgKyByLCBkM19yZ2IsIGQzX2hzbF9yZ2IpIDogbmV3IGQzX3JnYihyLCBnLCBiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JOdW1iZXIodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IGQzX3JnYih2YWx1ZSA+PiAxNiwgdmFsdWUgPj4gOCAmIDI1NSwgdmFsdWUgJiAyNTUpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3JnYlN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBkM19yZ2JOdW1iZXIodmFsdWUpICsgXCJcIjtcbiAgfVxuICB2YXIgZDNfcmdiUHJvdG90eXBlID0gZDNfcmdiLnByb3RvdHlwZSA9IG5ldyBkM19jb2xvcigpO1xuICBkM19yZ2JQcm90b3R5cGUuYnJpZ2h0ZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgayA9IE1hdGgucG93KC43LCBhcmd1bWVudHMubGVuZ3RoID8gayA6IDEpO1xuICAgIHZhciByID0gdGhpcy5yLCBnID0gdGhpcy5nLCBiID0gdGhpcy5iLCBpID0gMzA7XG4gICAgaWYgKCFyICYmICFnICYmICFiKSByZXR1cm4gbmV3IGQzX3JnYihpLCBpLCBpKTtcbiAgICBpZiAociAmJiByIDwgaSkgciA9IGk7XG4gICAgaWYgKGcgJiYgZyA8IGkpIGcgPSBpO1xuICAgIGlmIChiICYmIGIgPCBpKSBiID0gaTtcbiAgICByZXR1cm4gbmV3IGQzX3JnYihNYXRoLm1pbigyNTUsIHIgLyBrKSwgTWF0aC5taW4oMjU1LCBnIC8gayksIE1hdGgubWluKDI1NSwgYiAvIGspKTtcbiAgfTtcbiAgZDNfcmdiUHJvdG90eXBlLmRhcmtlciA9IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gTWF0aC5wb3coLjcsIGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSk7XG4gICAgcmV0dXJuIG5ldyBkM19yZ2IoayAqIHRoaXMuciwgayAqIHRoaXMuZywgayAqIHRoaXMuYik7XG4gIH07XG4gIGQzX3JnYlByb3RvdHlwZS5oc2wgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfcmdiX2hzbCh0aGlzLnIsIHRoaXMuZywgdGhpcy5iKTtcbiAgfTtcbiAgZDNfcmdiUHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFwiI1wiICsgZDNfcmdiX2hleCh0aGlzLnIpICsgZDNfcmdiX2hleCh0aGlzLmcpICsgZDNfcmdiX2hleCh0aGlzLmIpO1xuICB9O1xuICBmdW5jdGlvbiBkM19yZ2JfaGV4KHYpIHtcbiAgICByZXR1cm4gdiA8IDE2ID8gXCIwXCIgKyBNYXRoLm1heCgwLCB2KS50b1N0cmluZygxNikgOiBNYXRoLm1pbigyNTUsIHYpLnRvU3RyaW5nKDE2KTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JfcGFyc2UoZm9ybWF0LCByZ2IsIGhzbCkge1xuICAgIHZhciByID0gMCwgZyA9IDAsIGIgPSAwLCBtMSwgbTIsIGNvbG9yO1xuICAgIG0xID0gLyhbYS16XSspXFwoKC4qKVxcKS8uZXhlYyhmb3JtYXQgPSBmb3JtYXQudG9Mb3dlckNhc2UoKSk7XG4gICAgaWYgKG0xKSB7XG4gICAgICBtMiA9IG0xWzJdLnNwbGl0KFwiLFwiKTtcbiAgICAgIHN3aXRjaCAobTFbMV0pIHtcbiAgICAgICBjYXNlIFwiaHNsXCI6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gaHNsKHBhcnNlRmxvYXQobTJbMF0pLCBwYXJzZUZsb2F0KG0yWzFdKSAvIDEwMCwgcGFyc2VGbG9hdChtMlsyXSkgLyAxMDApO1xuICAgICAgICB9XG5cbiAgICAgICBjYXNlIFwicmdiXCI6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gcmdiKGQzX3JnYl9wYXJzZU51bWJlcihtMlswXSksIGQzX3JnYl9wYXJzZU51bWJlcihtMlsxXSksIGQzX3JnYl9wYXJzZU51bWJlcihtMlsyXSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjb2xvciA9IGQzX3JnYl9uYW1lcy5nZXQoZm9ybWF0KSkge1xuICAgICAgcmV0dXJuIHJnYihjb2xvci5yLCBjb2xvci5nLCBjb2xvci5iKTtcbiAgICB9XG4gICAgaWYgKGZvcm1hdCAhPSBudWxsICYmIGZvcm1hdC5jaGFyQXQoMCkgPT09IFwiI1wiICYmICFpc05hTihjb2xvciA9IHBhcnNlSW50KGZvcm1hdC5zbGljZSgxKSwgMTYpKSkge1xuICAgICAgaWYgKGZvcm1hdC5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgciA9IChjb2xvciAmIDM4NDApID4+IDQ7XG4gICAgICAgIHIgPSByID4+IDQgfCByO1xuICAgICAgICBnID0gY29sb3IgJiAyNDA7XG4gICAgICAgIGcgPSBnID4+IDQgfCBnO1xuICAgICAgICBiID0gY29sb3IgJiAxNTtcbiAgICAgICAgYiA9IGIgPDwgNCB8IGI7XG4gICAgICB9IGVsc2UgaWYgKGZvcm1hdC5sZW5ndGggPT09IDcpIHtcbiAgICAgICAgciA9IChjb2xvciAmIDE2NzExNjgwKSA+PiAxNjtcbiAgICAgICAgZyA9IChjb2xvciAmIDY1MjgwKSA+PiA4O1xuICAgICAgICBiID0gY29sb3IgJiAyNTU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZ2IociwgZywgYik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX2hzbChyLCBnLCBiKSB7XG4gICAgdmFyIG1pbiA9IE1hdGgubWluKHIgLz0gMjU1LCBnIC89IDI1NSwgYiAvPSAyNTUpLCBtYXggPSBNYXRoLm1heChyLCBnLCBiKSwgZCA9IG1heCAtIG1pbiwgaCwgcywgbCA9IChtYXggKyBtaW4pIC8gMjtcbiAgICBpZiAoZCkge1xuICAgICAgcyA9IGwgPCAuNSA/IGQgLyAobWF4ICsgbWluKSA6IGQgLyAoMiAtIG1heCAtIG1pbik7XG4gICAgICBpZiAociA9PSBtYXgpIGggPSAoZyAtIGIpIC8gZCArIChnIDwgYiA/IDYgOiAwKTsgZWxzZSBpZiAoZyA9PSBtYXgpIGggPSAoYiAtIHIpIC8gZCArIDI7IGVsc2UgaCA9IChyIC0gZykgLyBkICsgNDtcbiAgICAgIGggKj0gNjA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGggPSBOYU47XG4gICAgICBzID0gbCA+IDAgJiYgbCA8IDEgPyAwIDogaDtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBkM19oc2woaCwgcywgbCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX2xhYihyLCBnLCBiKSB7XG4gICAgciA9IGQzX3JnYl94eXoocik7XG4gICAgZyA9IGQzX3JnYl94eXooZyk7XG4gICAgYiA9IGQzX3JnYl94eXooYik7XG4gICAgdmFyIHggPSBkM194eXpfbGFiKCguNDEyNDU2NCAqIHIgKyAuMzU3NTc2MSAqIGcgKyAuMTgwNDM3NSAqIGIpIC8gZDNfbGFiX1gpLCB5ID0gZDNfeHl6X2xhYigoLjIxMjY3MjkgKiByICsgLjcxNTE1MjIgKiBnICsgLjA3MjE3NSAqIGIpIC8gZDNfbGFiX1kpLCB6ID0gZDNfeHl6X2xhYigoLjAxOTMzMzkgKiByICsgLjExOTE5MiAqIGcgKyAuOTUwMzA0MSAqIGIpIC8gZDNfbGFiX1opO1xuICAgIHJldHVybiBkM19sYWIoMTE2ICogeSAtIDE2LCA1MDAgKiAoeCAtIHkpLCAyMDAgKiAoeSAtIHopKTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JfeHl6KHIpIHtcbiAgICByZXR1cm4gKHIgLz0gMjU1KSA8PSAuMDQwNDUgPyByIC8gMTIuOTIgOiBNYXRoLnBvdygociArIC4wNTUpIC8gMS4wNTUsIDIuNCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX3BhcnNlTnVtYmVyKGMpIHtcbiAgICB2YXIgZiA9IHBhcnNlRmxvYXQoYyk7XG4gICAgcmV0dXJuIGMuY2hhckF0KGMubGVuZ3RoIC0gMSkgPT09IFwiJVwiID8gTWF0aC5yb3VuZChmICogMi41NSkgOiBmO1xuICB9XG4gIHZhciBkM19yZ2JfbmFtZXMgPSBkMy5tYXAoe1xuICAgIGFsaWNlYmx1ZTogMTU3OTIzODMsXG4gICAgYW50aXF1ZXdoaXRlOiAxNjQ0NDM3NSxcbiAgICBhcXVhOiA2NTUzNSxcbiAgICBhcXVhbWFyaW5lOiA4Mzg4NTY0LFxuICAgIGF6dXJlOiAxNTc5NDE3NSxcbiAgICBiZWlnZTogMTYxMTkyNjAsXG4gICAgYmlzcXVlOiAxNjc3MDI0NCxcbiAgICBibGFjazogMCxcbiAgICBibGFuY2hlZGFsbW9uZDogMTY3NzIwNDUsXG4gICAgYmx1ZTogMjU1LFxuICAgIGJsdWV2aW9sZXQ6IDkwNTUyMDIsXG4gICAgYnJvd246IDEwODI0MjM0LFxuICAgIGJ1cmx5d29vZDogMTQ1OTYyMzEsXG4gICAgY2FkZXRibHVlOiA2MjY2NTI4LFxuICAgIGNoYXJ0cmV1c2U6IDgzODgzNTIsXG4gICAgY2hvY29sYXRlOiAxMzc4OTQ3MCxcbiAgICBjb3JhbDogMTY3NDQyNzIsXG4gICAgY29ybmZsb3dlcmJsdWU6IDY1OTE5ODEsXG4gICAgY29ybnNpbGs6IDE2Nzc1Mzg4LFxuICAgIGNyaW1zb246IDE0NDIzMTAwLFxuICAgIGN5YW46IDY1NTM1LFxuICAgIGRhcmtibHVlOiAxMzksXG4gICAgZGFya2N5YW46IDM1NzIzLFxuICAgIGRhcmtnb2xkZW5yb2Q6IDEyMDkyOTM5LFxuICAgIGRhcmtncmF5OiAxMTExOTAxNyxcbiAgICBkYXJrZ3JlZW46IDI1NjAwLFxuICAgIGRhcmtncmV5OiAxMTExOTAxNyxcbiAgICBkYXJra2hha2k6IDEyNDMzMjU5LFxuICAgIGRhcmttYWdlbnRhOiA5MTA5NjQzLFxuICAgIGRhcmtvbGl2ZWdyZWVuOiA1NTk3OTk5LFxuICAgIGRhcmtvcmFuZ2U6IDE2NzQ3NTIwLFxuICAgIGRhcmtvcmNoaWQ6IDEwMDQwMDEyLFxuICAgIGRhcmtyZWQ6IDkxMDk1MDQsXG4gICAgZGFya3NhbG1vbjogMTUzMDg0MTAsXG4gICAgZGFya3NlYWdyZWVuOiA5NDE5OTE5LFxuICAgIGRhcmtzbGF0ZWJsdWU6IDQ3MzQzNDcsXG4gICAgZGFya3NsYXRlZ3JheTogMzEwMDQ5NSxcbiAgICBkYXJrc2xhdGVncmV5OiAzMTAwNDk1LFxuICAgIGRhcmt0dXJxdW9pc2U6IDUyOTQ1LFxuICAgIGRhcmt2aW9sZXQ6IDk2OTk1MzksXG4gICAgZGVlcHBpbms6IDE2NzE2OTQ3LFxuICAgIGRlZXBza3libHVlOiA0OTE1MSxcbiAgICBkaW1ncmF5OiA2OTA4MjY1LFxuICAgIGRpbWdyZXk6IDY5MDgyNjUsXG4gICAgZG9kZ2VyYmx1ZTogMjAwMzE5OSxcbiAgICBmaXJlYnJpY2s6IDExNjc0MTQ2LFxuICAgIGZsb3JhbHdoaXRlOiAxNjc3NTkyMCxcbiAgICBmb3Jlc3RncmVlbjogMjI2Mzg0MixcbiAgICBmdWNoc2lhOiAxNjcxMTkzNSxcbiAgICBnYWluc2Jvcm86IDE0NDc0NDYwLFxuICAgIGdob3N0d2hpdGU6IDE2MzE2NjcxLFxuICAgIGdvbGQ6IDE2NzY2NzIwLFxuICAgIGdvbGRlbnJvZDogMTQzMjkxMjAsXG4gICAgZ3JheTogODQyMTUwNCxcbiAgICBncmVlbjogMzI3NjgsXG4gICAgZ3JlZW55ZWxsb3c6IDExNDAzMDU1LFxuICAgIGdyZXk6IDg0MjE1MDQsXG4gICAgaG9uZXlkZXc6IDE1Nzk0MTYwLFxuICAgIGhvdHBpbms6IDE2NzM4NzQwLFxuICAgIGluZGlhbnJlZDogMTM0NTg1MjQsXG4gICAgaW5kaWdvOiA0OTE1MzMwLFxuICAgIGl2b3J5OiAxNjc3NzIwMCxcbiAgICBraGFraTogMTU3ODc2NjAsXG4gICAgbGF2ZW5kZXI6IDE1MTMyNDEwLFxuICAgIGxhdmVuZGVyYmx1c2g6IDE2NzczMzY1LFxuICAgIGxhd25ncmVlbjogODE5MDk3NixcbiAgICBsZW1vbmNoaWZmb246IDE2Nzc1ODg1LFxuICAgIGxpZ2h0Ymx1ZTogMTEzOTMyNTQsXG4gICAgbGlnaHRjb3JhbDogMTU3NjE1MzYsXG4gICAgbGlnaHRjeWFuOiAxNDc0NTU5OSxcbiAgICBsaWdodGdvbGRlbnJvZHllbGxvdzogMTY0NDgyMTAsXG4gICAgbGlnaHRncmF5OiAxMzg4MjMyMyxcbiAgICBsaWdodGdyZWVuOiA5NDk4MjU2LFxuICAgIGxpZ2h0Z3JleTogMTM4ODIzMjMsXG4gICAgbGlnaHRwaW5rOiAxNjc1ODQ2NSxcbiAgICBsaWdodHNhbG1vbjogMTY3NTI3NjIsXG4gICAgbGlnaHRzZWFncmVlbjogMjE0Mjg5MCxcbiAgICBsaWdodHNreWJsdWU6IDg5MDAzNDYsXG4gICAgbGlnaHRzbGF0ZWdyYXk6IDc4MzM3NTMsXG4gICAgbGlnaHRzbGF0ZWdyZXk6IDc4MzM3NTMsXG4gICAgbGlnaHRzdGVlbGJsdWU6IDExNTg0NzM0LFxuICAgIGxpZ2h0eWVsbG93OiAxNjc3NzE4NCxcbiAgICBsaW1lOiA2NTI4MCxcbiAgICBsaW1lZ3JlZW46IDMzMjkzMzAsXG4gICAgbGluZW46IDE2NDQ1NjcwLFxuICAgIG1hZ2VudGE6IDE2NzExOTM1LFxuICAgIG1hcm9vbjogODM4ODYwOCxcbiAgICBtZWRpdW1hcXVhbWFyaW5lOiA2NzM3MzIyLFxuICAgIG1lZGl1bWJsdWU6IDIwNSxcbiAgICBtZWRpdW1vcmNoaWQ6IDEyMjExNjY3LFxuICAgIG1lZGl1bXB1cnBsZTogOTY2MjY4MyxcbiAgICBtZWRpdW1zZWFncmVlbjogMzk3ODA5NyxcbiAgICBtZWRpdW1zbGF0ZWJsdWU6IDgwODc3OTAsXG4gICAgbWVkaXVtc3ByaW5nZ3JlZW46IDY0MTU0LFxuICAgIG1lZGl1bXR1cnF1b2lzZTogNDc3MjMwMCxcbiAgICBtZWRpdW12aW9sZXRyZWQ6IDEzMDQ3MTczLFxuICAgIG1pZG5pZ2h0Ymx1ZTogMTY0NDkxMixcbiAgICBtaW50Y3JlYW06IDE2MTIxODUwLFxuICAgIG1pc3R5cm9zZTogMTY3NzAyNzMsXG4gICAgbW9jY2FzaW46IDE2NzcwMjI5LFxuICAgIG5hdmFqb3doaXRlOiAxNjc2ODY4NSxcbiAgICBuYXZ5OiAxMjgsXG4gICAgb2xkbGFjZTogMTY2NDM1NTgsXG4gICAgb2xpdmU6IDg0MjEzNzYsXG4gICAgb2xpdmVkcmFiOiA3MDQ4NzM5LFxuICAgIG9yYW5nZTogMTY3NTM5MjAsXG4gICAgb3JhbmdlcmVkOiAxNjcyOTM0NCxcbiAgICBvcmNoaWQ6IDE0MzE1NzM0LFxuICAgIHBhbGVnb2xkZW5yb2Q6IDE1NjU3MTMwLFxuICAgIHBhbGVncmVlbjogMTAwMjU4ODAsXG4gICAgcGFsZXR1cnF1b2lzZTogMTE1Mjk5NjYsXG4gICAgcGFsZXZpb2xldHJlZDogMTQzODEyMDMsXG4gICAgcGFwYXlhd2hpcDogMTY3NzMwNzcsXG4gICAgcGVhY2hwdWZmOiAxNjc2NzY3MyxcbiAgICBwZXJ1OiAxMzQ2ODk5MSxcbiAgICBwaW5rOiAxNjc2MTAzNSxcbiAgICBwbHVtOiAxNDUyNDYzNyxcbiAgICBwb3dkZXJibHVlOiAxMTU5MTkxMCxcbiAgICBwdXJwbGU6IDgzODg3MzYsXG4gICAgcmViZWNjYXB1cnBsZTogNjY5Nzg4MSxcbiAgICByZWQ6IDE2NzExNjgwLFxuICAgIHJvc3licm93bjogMTIzNTc1MTksXG4gICAgcm95YWxibHVlOiA0Mjg2OTQ1LFxuICAgIHNhZGRsZWJyb3duOiA5MTI3MTg3LFxuICAgIHNhbG1vbjogMTY0MTY4ODIsXG4gICAgc2FuZHlicm93bjogMTYwMzI4NjQsXG4gICAgc2VhZ3JlZW46IDMwNTAzMjcsXG4gICAgc2Vhc2hlbGw6IDE2Nzc0NjM4LFxuICAgIHNpZW5uYTogMTA1MDY3OTcsXG4gICAgc2lsdmVyOiAxMjYzMjI1NixcbiAgICBza3libHVlOiA4OTAwMzMxLFxuICAgIHNsYXRlYmx1ZTogNjk3MDA2MSxcbiAgICBzbGF0ZWdyYXk6IDczNzI5NDQsXG4gICAgc2xhdGVncmV5OiA3MzcyOTQ0LFxuICAgIHNub3c6IDE2Nzc1OTMwLFxuICAgIHNwcmluZ2dyZWVuOiA2NTQwNyxcbiAgICBzdGVlbGJsdWU6IDQ2MjA5ODAsXG4gICAgdGFuOiAxMzgwODc4MCxcbiAgICB0ZWFsOiAzMjg5NixcbiAgICB0aGlzdGxlOiAxNDIwNDg4OCxcbiAgICB0b21hdG86IDE2NzM3MDk1LFxuICAgIHR1cnF1b2lzZTogNDI1MTg1NixcbiAgICB2aW9sZXQ6IDE1NjMxMDg2LFxuICAgIHdoZWF0OiAxNjExMzMzMSxcbiAgICB3aGl0ZTogMTY3NzcyMTUsXG4gICAgd2hpdGVzbW9rZTogMTYxMTkyODUsXG4gICAgeWVsbG93OiAxNjc3Njk2MCxcbiAgICB5ZWxsb3dncmVlbjogMTAxNDUwNzRcbiAgfSk7XG4gIGQzX3JnYl9uYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBkM19yZ2JfbmFtZXMuc2V0KGtleSwgZDNfcmdiTnVtYmVyKHZhbHVlKSk7XG4gIH0pO1xuICBmdW5jdGlvbiBkM19mdW5jdG9yKHYpIHtcbiAgICByZXR1cm4gdHlwZW9mIHYgPT09IFwiZnVuY3Rpb25cIiA/IHYgOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB2O1xuICAgIH07XG4gIH1cbiAgZDMuZnVuY3RvciA9IGQzX2Z1bmN0b3I7XG4gIGQzLnhociA9IGQzX3hoclR5cGUoZDNfaWRlbnRpdHkpO1xuICBmdW5jdGlvbiBkM194aHJUeXBlKHJlc3BvbnNlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHVybCwgbWltZVR5cGUsIGNhbGxiYWNrKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMiAmJiB0eXBlb2YgbWltZVR5cGUgPT09IFwiZnVuY3Rpb25cIikgY2FsbGJhY2sgPSBtaW1lVHlwZSwgXG4gICAgICBtaW1lVHlwZSA9IG51bGw7XG4gICAgICByZXR1cm4gZDNfeGhyKHVybCwgbWltZVR5cGUsIHJlc3BvbnNlLCBjYWxsYmFjayk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM194aHIodXJsLCBtaW1lVHlwZSwgcmVzcG9uc2UsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IHt9LCBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKFwiYmVmb3Jlc2VuZFwiLCBcInByb2dyZXNzXCIsIFwibG9hZFwiLCBcImVycm9yXCIpLCBoZWFkZXJzID0ge30sIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKSwgcmVzcG9uc2VUeXBlID0gbnVsbDtcbiAgICBpZiAodGhpcy5YRG9tYWluUmVxdWVzdCAmJiAhKFwid2l0aENyZWRlbnRpYWxzXCIgaW4gcmVxdWVzdCkgJiYgL14oaHR0cChzKT86KT9cXC9cXC8vLnRlc3QodXJsKSkgcmVxdWVzdCA9IG5ldyBYRG9tYWluUmVxdWVzdCgpO1xuICAgIFwib25sb2FkXCIgaW4gcmVxdWVzdCA/IHJlcXVlc3Qub25sb2FkID0gcmVxdWVzdC5vbmVycm9yID0gcmVzcG9uZCA6IHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXF1ZXN0LnJlYWR5U3RhdGUgPiAzICYmIHJlc3BvbmQoKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJlc3BvbmQoKSB7XG4gICAgICB2YXIgc3RhdHVzID0gcmVxdWVzdC5zdGF0dXMsIHJlc3VsdDtcbiAgICAgIGlmICghc3RhdHVzICYmIGQzX3hockhhc1Jlc3BvbnNlKHJlcXVlc3QpIHx8IHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwIHx8IHN0YXR1cyA9PT0gMzA0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzdWx0ID0gcmVzcG9uc2UuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgZGlzcGF0Y2guZXJyb3IuY2FsbCh4aHIsIGUpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkaXNwYXRjaC5sb2FkLmNhbGwoeGhyLCByZXN1bHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlzcGF0Y2guZXJyb3IuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXF1ZXN0Lm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgdmFyIG8gPSBkMy5ldmVudDtcbiAgICAgIGQzLmV2ZW50ID0gZXZlbnQ7XG4gICAgICB0cnkge1xuICAgICAgICBkaXNwYXRjaC5wcm9ncmVzcy5jYWxsKHhociwgcmVxdWVzdCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkMy5ldmVudCA9IG87XG4gICAgICB9XG4gICAgfTtcbiAgICB4aHIuaGVhZGVyID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICAgIG5hbWUgPSAobmFtZSArIFwiXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHJldHVybiBoZWFkZXJzW25hbWVdO1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIGRlbGV0ZSBoZWFkZXJzW25hbWVdOyBlbHNlIGhlYWRlcnNbbmFtZV0gPSB2YWx1ZSArIFwiXCI7XG4gICAgICByZXR1cm4geGhyO1xuICAgIH07XG4gICAgeGhyLm1pbWVUeXBlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1pbWVUeXBlO1xuICAgICAgbWltZVR5cGUgPSB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlICsgXCJcIjtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICB4aHIucmVzcG9uc2VUeXBlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJlc3BvbnNlVHlwZTtcbiAgICAgIHJlc3BvbnNlVHlwZSA9IHZhbHVlO1xuICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuICAgIHhoci5yZXNwb25zZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXNwb25zZSA9IHZhbHVlO1xuICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuICAgIFsgXCJnZXRcIiwgXCJwb3N0XCIgXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgeGhyW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHhoci5zZW5kLmFwcGx5KHhociwgWyBtZXRob2QgXS5jb25jYXQoZDNfYXJyYXkoYXJndW1lbnRzKSkpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgICB4aHIuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBkYXRhID09PSBcImZ1bmN0aW9uXCIpIGNhbGxiYWNrID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gICAgICByZXF1ZXN0Lm9wZW4obWV0aG9kLCB1cmwsIHRydWUpO1xuICAgICAgaWYgKG1pbWVUeXBlICE9IG51bGwgJiYgIShcImFjY2VwdFwiIGluIGhlYWRlcnMpKSBoZWFkZXJzW1wiYWNjZXB0XCJdID0gbWltZVR5cGUgKyBcIiwqLypcIjtcbiAgICAgIGlmIChyZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIpIGZvciAodmFyIG5hbWUgaW4gaGVhZGVycykgcmVxdWVzdC5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIGhlYWRlcnNbbmFtZV0pO1xuICAgICAgaWYgKG1pbWVUeXBlICE9IG51bGwgJiYgcmVxdWVzdC5vdmVycmlkZU1pbWVUeXBlKSByZXF1ZXN0Lm92ZXJyaWRlTWltZVR5cGUobWltZVR5cGUpO1xuICAgICAgaWYgKHJlc3BvbnNlVHlwZSAhPSBudWxsKSByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9IHJlc3BvbnNlVHlwZTtcbiAgICAgIGlmIChjYWxsYmFjayAhPSBudWxsKSB4aHIub24oXCJlcnJvclwiLCBjYWxsYmFjaykub24oXCJsb2FkXCIsIGZ1bmN0aW9uKHJlcXVlc3QpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVxdWVzdCk7XG4gICAgICB9KTtcbiAgICAgIGRpc3BhdGNoLmJlZm9yZXNlbmQuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgcmVxdWVzdC5zZW5kKGRhdGEgPT0gbnVsbCA/IG51bGwgOiBkYXRhKTtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICB4aHIuYWJvcnQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJlcXVlc3QuYWJvcnQoKTtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICBkMy5yZWJpbmQoeGhyLCBkaXNwYXRjaCwgXCJvblwiKTtcbiAgICByZXR1cm4gY2FsbGJhY2sgPT0gbnVsbCA/IHhociA6IHhoci5nZXQoZDNfeGhyX2ZpeENhbGxiYWNrKGNhbGxiYWNrKSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfeGhyX2ZpeENhbGxiYWNrKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrLmxlbmd0aCA9PT0gMSA/IGZ1bmN0aW9uKGVycm9yLCByZXF1ZXN0KSB7XG4gICAgICBjYWxsYmFjayhlcnJvciA9PSBudWxsID8gcmVxdWVzdCA6IG51bGwpO1xuICAgIH0gOiBjYWxsYmFjaztcbiAgfVxuICBmdW5jdGlvbiBkM194aHJIYXNSZXNwb25zZShyZXF1ZXN0KSB7XG4gICAgdmFyIHR5cGUgPSByZXF1ZXN0LnJlc3BvbnNlVHlwZTtcbiAgICByZXR1cm4gdHlwZSAmJiB0eXBlICE9PSBcInRleHRcIiA/IHJlcXVlc3QucmVzcG9uc2UgOiByZXF1ZXN0LnJlc3BvbnNlVGV4dDtcbiAgfVxuICBkMy5kc3YgPSBmdW5jdGlvbihkZWxpbWl0ZXIsIG1pbWVUeXBlKSB7XG4gICAgdmFyIHJlRm9ybWF0ID0gbmV3IFJlZ0V4cCgnW1wiJyArIGRlbGltaXRlciArIFwiXFxuXVwiKSwgZGVsaW1pdGVyQ29kZSA9IGRlbGltaXRlci5jaGFyQ29kZUF0KDApO1xuICAgIGZ1bmN0aW9uIGRzdih1cmwsIHJvdywgY2FsbGJhY2spIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgY2FsbGJhY2sgPSByb3csIHJvdyA9IG51bGw7XG4gICAgICB2YXIgeGhyID0gZDNfeGhyKHVybCwgbWltZVR5cGUsIHJvdyA9PSBudWxsID8gcmVzcG9uc2UgOiB0eXBlZFJlc3BvbnNlKHJvdyksIGNhbGxiYWNrKTtcbiAgICAgIHhoci5yb3cgPSBmdW5jdGlvbihfKSB7XG4gICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8geGhyLnJlc3BvbnNlKChyb3cgPSBfKSA9PSBudWxsID8gcmVzcG9uc2UgOiB0eXBlZFJlc3BvbnNlKF8pKSA6IHJvdztcbiAgICAgIH07XG4gICAgICByZXR1cm4geGhyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNwb25zZShyZXF1ZXN0KSB7XG4gICAgICByZXR1cm4gZHN2LnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHlwZWRSZXNwb25zZShmKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocmVxdWVzdCkge1xuICAgICAgICByZXR1cm4gZHN2LnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0LCBmKTtcbiAgICAgIH07XG4gICAgfVxuICAgIGRzdi5wYXJzZSA9IGZ1bmN0aW9uKHRleHQsIGYpIHtcbiAgICAgIHZhciBvO1xuICAgICAgcmV0dXJuIGRzdi5wYXJzZVJvd3ModGV4dCwgZnVuY3Rpb24ocm93LCBpKSB7XG4gICAgICAgIGlmIChvKSByZXR1cm4gbyhyb3csIGkgLSAxKTtcbiAgICAgICAgdmFyIGEgPSBuZXcgRnVuY3Rpb24oXCJkXCIsIFwicmV0dXJuIHtcIiArIHJvdy5tYXAoZnVuY3Rpb24obmFtZSwgaSkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShuYW1lKSArIFwiOiBkW1wiICsgaSArIFwiXVwiO1xuICAgICAgICB9KS5qb2luKFwiLFwiKSArIFwifVwiKTtcbiAgICAgICAgbyA9IGYgPyBmdW5jdGlvbihyb3csIGkpIHtcbiAgICAgICAgICByZXR1cm4gZihhKHJvdyksIGkpO1xuICAgICAgICB9IDogYTtcbiAgICAgIH0pO1xuICAgIH07XG4gICAgZHN2LnBhcnNlUm93cyA9IGZ1bmN0aW9uKHRleHQsIGYpIHtcbiAgICAgIHZhciBFT0wgPSB7fSwgRU9GID0ge30sIHJvd3MgPSBbXSwgTiA9IHRleHQubGVuZ3RoLCBJID0gMCwgbiA9IDAsIHQsIGVvbDtcbiAgICAgIGZ1bmN0aW9uIHRva2VuKCkge1xuICAgICAgICBpZiAoSSA+PSBOKSByZXR1cm4gRU9GO1xuICAgICAgICBpZiAoZW9sKSByZXR1cm4gZW9sID0gZmFsc2UsIEVPTDtcbiAgICAgICAgdmFyIGogPSBJO1xuICAgICAgICBpZiAodGV4dC5jaGFyQ29kZUF0KGopID09PSAzNCkge1xuICAgICAgICAgIHZhciBpID0gajtcbiAgICAgICAgICB3aGlsZSAoaSsrIDwgTikge1xuICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpKSA9PT0gMzQpIHtcbiAgICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpICsgMSkgIT09IDM0KSBicmVhaztcbiAgICAgICAgICAgICAgKytpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBJID0gaSArIDI7XG4gICAgICAgICAgdmFyIGMgPSB0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgICAgIGlmIChjID09PSAxMykge1xuICAgICAgICAgICAgZW9sID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0ZXh0LmNoYXJDb2RlQXQoaSArIDIpID09PSAxMCkgKytJO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gMTApIHtcbiAgICAgICAgICAgIGVvbCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0ZXh0LnNsaWNlKGogKyAxLCBpKS5yZXBsYWNlKC9cIlwiL2csICdcIicpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChJIDwgTikge1xuICAgICAgICAgIHZhciBjID0gdGV4dC5jaGFyQ29kZUF0KEkrKyksIGsgPSAxO1xuICAgICAgICAgIGlmIChjID09PSAxMCkgZW9sID0gdHJ1ZTsgZWxzZSBpZiAoYyA9PT0gMTMpIHtcbiAgICAgICAgICAgIGVvbCA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGV4dC5jaGFyQ29kZUF0KEkpID09PSAxMCkgKytJLCArK2s7XG4gICAgICAgICAgfSBlbHNlIGlmIChjICE9PSBkZWxpbWl0ZXJDb2RlKSBjb250aW51ZTtcbiAgICAgICAgICByZXR1cm4gdGV4dC5zbGljZShqLCBJIC0gayk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHQuc2xpY2Uoaik7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKHQgPSB0b2tlbigpKSAhPT0gRU9GKSB7XG4gICAgICAgIHZhciBhID0gW107XG4gICAgICAgIHdoaWxlICh0ICE9PSBFT0wgJiYgdCAhPT0gRU9GKSB7XG4gICAgICAgICAgYS5wdXNoKHQpO1xuICAgICAgICAgIHQgPSB0b2tlbigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmICYmIChhID0gZihhLCBuKyspKSA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgcm93cy5wdXNoKGEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfTtcbiAgICBkc3YuZm9ybWF0ID0gZnVuY3Rpb24ocm93cykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93c1swXSkpIHJldHVybiBkc3YuZm9ybWF0Um93cyhyb3dzKTtcbiAgICAgIHZhciBmaWVsZFNldCA9IG5ldyBkM19TZXQoKSwgZmllbGRzID0gW107XG4gICAgICByb3dzLmZvckVhY2goZnVuY3Rpb24ocm93KSB7XG4gICAgICAgIGZvciAodmFyIGZpZWxkIGluIHJvdykge1xuICAgICAgICAgIGlmICghZmllbGRTZXQuaGFzKGZpZWxkKSkge1xuICAgICAgICAgICAgZmllbGRzLnB1c2goZmllbGRTZXQuYWRkKGZpZWxkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBbIGZpZWxkcy5tYXAoZm9ybWF0VmFsdWUpLmpvaW4oZGVsaW1pdGVyKSBdLmNvbmNhdChyb3dzLm1hcChmdW5jdGlvbihyb3cpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkcy5tYXAoZnVuY3Rpb24oZmllbGQpIHtcbiAgICAgICAgICByZXR1cm4gZm9ybWF0VmFsdWUocm93W2ZpZWxkXSk7XG4gICAgICAgIH0pLmpvaW4oZGVsaW1pdGVyKTtcbiAgICAgIH0pKS5qb2luKFwiXFxuXCIpO1xuICAgIH07XG4gICAgZHN2LmZvcm1hdFJvd3MgPSBmdW5jdGlvbihyb3dzKSB7XG4gICAgICByZXR1cm4gcm93cy5tYXAoZm9ybWF0Um93KS5qb2luKFwiXFxuXCIpO1xuICAgIH07XG4gICAgZnVuY3Rpb24gZm9ybWF0Um93KHJvdykge1xuICAgICAgcmV0dXJuIHJvdy5tYXAoZm9ybWF0VmFsdWUpLmpvaW4oZGVsaW1pdGVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZm9ybWF0VmFsdWUodGV4dCkge1xuICAgICAgcmV0dXJuIHJlRm9ybWF0LnRlc3QodGV4dCkgPyAnXCInICsgdGV4dC5yZXBsYWNlKC9cXFwiL2csICdcIlwiJykgKyAnXCInIDogdGV4dDtcbiAgICB9XG4gICAgcmV0dXJuIGRzdjtcbiAgfTtcbiAgZDMuY3N2ID0gZDMuZHN2KFwiLFwiLCBcInRleHQvY3N2XCIpO1xuICBkMy50c3YgPSBkMy5kc3YoXCJcdFwiLCBcInRleHQvdGFiLXNlcGFyYXRlZC12YWx1ZXNcIik7XG4gIHZhciBkM190aW1lcl9xdWV1ZUhlYWQsIGQzX3RpbWVyX3F1ZXVlVGFpbCwgZDNfdGltZXJfaW50ZXJ2YWwsIGQzX3RpbWVyX3RpbWVvdXQsIGQzX3RpbWVyX2ZyYW1lID0gdGhpc1tkM192ZW5kb3JTeW1ib2wodGhpcywgXCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWVcIildIHx8IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgc2V0VGltZW91dChjYWxsYmFjaywgMTcpO1xuICB9O1xuICBkMy50aW1lciA9IGZ1bmN0aW9uKCkge1xuICAgIGQzX3RpbWVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RpbWVyKGNhbGxiYWNrLCBkZWxheSwgdGhlbikge1xuICAgIHZhciBuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICBpZiAobiA8IDIpIGRlbGF5ID0gMDtcbiAgICBpZiAobiA8IDMpIHRoZW4gPSBEYXRlLm5vdygpO1xuICAgIHZhciB0aW1lID0gdGhlbiArIGRlbGF5LCB0aW1lciA9IHtcbiAgICAgIGM6IGNhbGxiYWNrLFxuICAgICAgdDogdGltZSxcbiAgICAgIG46IG51bGxcbiAgICB9O1xuICAgIGlmIChkM190aW1lcl9xdWV1ZVRhaWwpIGQzX3RpbWVyX3F1ZXVlVGFpbC5uID0gdGltZXI7IGVsc2UgZDNfdGltZXJfcXVldWVIZWFkID0gdGltZXI7XG4gICAgZDNfdGltZXJfcXVldWVUYWlsID0gdGltZXI7XG4gICAgaWYgKCFkM190aW1lcl9pbnRlcnZhbCkge1xuICAgICAgZDNfdGltZXJfdGltZW91dCA9IGNsZWFyVGltZW91dChkM190aW1lcl90aW1lb3V0KTtcbiAgICAgIGQzX3RpbWVyX2ludGVydmFsID0gMTtcbiAgICAgIGQzX3RpbWVyX2ZyYW1lKGQzX3RpbWVyX3N0ZXApO1xuICAgIH1cbiAgICByZXR1cm4gdGltZXI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZXJfc3RlcCgpIHtcbiAgICB2YXIgbm93ID0gZDNfdGltZXJfbWFyaygpLCBkZWxheSA9IGQzX3RpbWVyX3N3ZWVwKCkgLSBub3c7XG4gICAgaWYgKGRlbGF5ID4gMjQpIHtcbiAgICAgIGlmIChpc0Zpbml0ZShkZWxheSkpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KGQzX3RpbWVyX3RpbWVvdXQpO1xuICAgICAgICBkM190aW1lcl90aW1lb3V0ID0gc2V0VGltZW91dChkM190aW1lcl9zdGVwLCBkZWxheSk7XG4gICAgICB9XG4gICAgICBkM190aW1lcl9pbnRlcnZhbCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGQzX3RpbWVyX2ludGVydmFsID0gMTtcbiAgICAgIGQzX3RpbWVyX2ZyYW1lKGQzX3RpbWVyX3N0ZXApO1xuICAgIH1cbiAgfVxuICBkMy50aW1lci5mbHVzaCA9IGZ1bmN0aW9uKCkge1xuICAgIGQzX3RpbWVyX21hcmsoKTtcbiAgICBkM190aW1lcl9zd2VlcCgpO1xuICB9O1xuICBmdW5jdGlvbiBkM190aW1lcl9tYXJrKCkge1xuICAgIHZhciBub3cgPSBEYXRlLm5vdygpLCB0aW1lciA9IGQzX3RpbWVyX3F1ZXVlSGVhZDtcbiAgICB3aGlsZSAodGltZXIpIHtcbiAgICAgIGlmIChub3cgPj0gdGltZXIudCAmJiB0aW1lci5jKG5vdyAtIHRpbWVyLnQpKSB0aW1lci5jID0gbnVsbDtcbiAgICAgIHRpbWVyID0gdGltZXIubjtcbiAgICB9XG4gICAgcmV0dXJuIG5vdztcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lcl9zd2VlcCgpIHtcbiAgICB2YXIgdDAsIHQxID0gZDNfdGltZXJfcXVldWVIZWFkLCB0aW1lID0gSW5maW5pdHk7XG4gICAgd2hpbGUgKHQxKSB7XG4gICAgICBpZiAodDEuYykge1xuICAgICAgICBpZiAodDEudCA8IHRpbWUpIHRpbWUgPSB0MS50O1xuICAgICAgICB0MSA9ICh0MCA9IHQxKS5uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdDEgPSB0MCA/IHQwLm4gPSB0MS5uIDogZDNfdGltZXJfcXVldWVIZWFkID0gdDEubjtcbiAgICAgIH1cbiAgICB9XG4gICAgZDNfdGltZXJfcXVldWVUYWlsID0gdDA7XG4gICAgcmV0dXJuIHRpbWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZm9ybWF0X3ByZWNpc2lvbih4LCBwKSB7XG4gICAgcmV0dXJuIHAgLSAoeCA/IE1hdGguY2VpbChNYXRoLmxvZyh4KSAvIE1hdGguTE4xMCkgOiAxKTtcbiAgfVxuICBkMy5yb3VuZCA9IGZ1bmN0aW9uKHgsIG4pIHtcbiAgICByZXR1cm4gbiA/IE1hdGgucm91bmQoeCAqIChuID0gTWF0aC5wb3coMTAsIG4pKSkgLyBuIDogTWF0aC5yb3VuZCh4KTtcbiAgfTtcbiAgdmFyIGQzX2Zvcm1hdFByZWZpeGVzID0gWyBcInlcIiwgXCJ6XCIsIFwiYVwiLCBcImZcIiwgXCJwXCIsIFwiblwiLCBcIsK1XCIsIFwibVwiLCBcIlwiLCBcImtcIiwgXCJNXCIsIFwiR1wiLCBcIlRcIiwgXCJQXCIsIFwiRVwiLCBcIlpcIiwgXCJZXCIgXS5tYXAoZDNfZm9ybWF0UHJlZml4KTtcbiAgZDMuZm9ybWF0UHJlZml4ID0gZnVuY3Rpb24odmFsdWUsIHByZWNpc2lvbikge1xuICAgIHZhciBpID0gMDtcbiAgICBpZiAodmFsdWUgPSArdmFsdWUpIHtcbiAgICAgIGlmICh2YWx1ZSA8IDApIHZhbHVlICo9IC0xO1xuICAgICAgaWYgKHByZWNpc2lvbikgdmFsdWUgPSBkMy5yb3VuZCh2YWx1ZSwgZDNfZm9ybWF0X3ByZWNpc2lvbih2YWx1ZSwgcHJlY2lzaW9uKSk7XG4gICAgICBpID0gMSArIE1hdGguZmxvb3IoMWUtMTIgKyBNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMTApO1xuICAgICAgaSA9IE1hdGgubWF4KC0yNCwgTWF0aC5taW4oMjQsIE1hdGguZmxvb3IoKGkgLSAxKSAvIDMpICogMykpO1xuICAgIH1cbiAgICByZXR1cm4gZDNfZm9ybWF0UHJlZml4ZXNbOCArIGkgLyAzXTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZm9ybWF0UHJlZml4KGQsIGkpIHtcbiAgICB2YXIgayA9IE1hdGgucG93KDEwLCBhYnMoOCAtIGkpICogMyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjYWxlOiBpID4gOCA/IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQgLyBrO1xuICAgICAgfSA6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQgKiBrO1xuICAgICAgfSxcbiAgICAgIHN5bWJvbDogZFxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfbG9jYWxlX251bWJlckZvcm1hdChsb2NhbGUpIHtcbiAgICB2YXIgbG9jYWxlX2RlY2ltYWwgPSBsb2NhbGUuZGVjaW1hbCwgbG9jYWxlX3Rob3VzYW5kcyA9IGxvY2FsZS50aG91c2FuZHMsIGxvY2FsZV9ncm91cGluZyA9IGxvY2FsZS5ncm91cGluZywgbG9jYWxlX2N1cnJlbmN5ID0gbG9jYWxlLmN1cnJlbmN5LCBmb3JtYXRHcm91cCA9IGxvY2FsZV9ncm91cGluZyAmJiBsb2NhbGVfdGhvdXNhbmRzID8gZnVuY3Rpb24odmFsdWUsIHdpZHRoKSB7XG4gICAgICB2YXIgaSA9IHZhbHVlLmxlbmd0aCwgdCA9IFtdLCBqID0gMCwgZyA9IGxvY2FsZV9ncm91cGluZ1swXSwgbGVuZ3RoID0gMDtcbiAgICAgIHdoaWxlIChpID4gMCAmJiBnID4gMCkge1xuICAgICAgICBpZiAobGVuZ3RoICsgZyArIDEgPiB3aWR0aCkgZyA9IE1hdGgubWF4KDEsIHdpZHRoIC0gbGVuZ3RoKTtcbiAgICAgICAgdC5wdXNoKHZhbHVlLnN1YnN0cmluZyhpIC09IGcsIGkgKyBnKSk7XG4gICAgICAgIGlmICgobGVuZ3RoICs9IGcgKyAxKSA+IHdpZHRoKSBicmVhaztcbiAgICAgICAgZyA9IGxvY2FsZV9ncm91cGluZ1tqID0gKGogKyAxKSAlIGxvY2FsZV9ncm91cGluZy5sZW5ndGhdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHQucmV2ZXJzZSgpLmpvaW4obG9jYWxlX3Rob3VzYW5kcyk7XG4gICAgfSA6IGQzX2lkZW50aXR5O1xuICAgIHJldHVybiBmdW5jdGlvbihzcGVjaWZpZXIpIHtcbiAgICAgIHZhciBtYXRjaCA9IGQzX2Zvcm1hdF9yZS5leGVjKHNwZWNpZmllciksIGZpbGwgPSBtYXRjaFsxXSB8fCBcIiBcIiwgYWxpZ24gPSBtYXRjaFsyXSB8fCBcIj5cIiwgc2lnbiA9IG1hdGNoWzNdIHx8IFwiLVwiLCBzeW1ib2wgPSBtYXRjaFs0XSB8fCBcIlwiLCB6ZmlsbCA9IG1hdGNoWzVdLCB3aWR0aCA9ICttYXRjaFs2XSwgY29tbWEgPSBtYXRjaFs3XSwgcHJlY2lzaW9uID0gbWF0Y2hbOF0sIHR5cGUgPSBtYXRjaFs5XSwgc2NhbGUgPSAxLCBwcmVmaXggPSBcIlwiLCBzdWZmaXggPSBcIlwiLCBpbnRlZ2VyID0gZmFsc2UsIGV4cG9uZW50ID0gdHJ1ZTtcbiAgICAgIGlmIChwcmVjaXNpb24pIHByZWNpc2lvbiA9ICtwcmVjaXNpb24uc3Vic3RyaW5nKDEpO1xuICAgICAgaWYgKHpmaWxsIHx8IGZpbGwgPT09IFwiMFwiICYmIGFsaWduID09PSBcIj1cIikge1xuICAgICAgICB6ZmlsbCA9IGZpbGwgPSBcIjBcIjtcbiAgICAgICAgYWxpZ24gPSBcIj1cIjtcbiAgICAgIH1cbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgIGNhc2UgXCJuXCI6XG4gICAgICAgIGNvbW1hID0gdHJ1ZTtcbiAgICAgICAgdHlwZSA9IFwiZ1wiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCIlXCI6XG4gICAgICAgIHNjYWxlID0gMTAwO1xuICAgICAgICBzdWZmaXggPSBcIiVcIjtcbiAgICAgICAgdHlwZSA9IFwiZlwiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJwXCI6XG4gICAgICAgIHNjYWxlID0gMTAwO1xuICAgICAgICBzdWZmaXggPSBcIiVcIjtcbiAgICAgICAgdHlwZSA9IFwiclwiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJiXCI6XG4gICAgICAgY2FzZSBcIm9cIjpcbiAgICAgICBjYXNlIFwieFwiOlxuICAgICAgIGNhc2UgXCJYXCI6XG4gICAgICAgIGlmIChzeW1ib2wgPT09IFwiI1wiKSBwcmVmaXggPSBcIjBcIiArIHR5cGUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgIGNhc2UgXCJjXCI6XG4gICAgICAgIGV4cG9uZW50ID0gZmFsc2U7XG5cbiAgICAgICBjYXNlIFwiZFwiOlxuICAgICAgICBpbnRlZ2VyID0gdHJ1ZTtcbiAgICAgICAgcHJlY2lzaW9uID0gMDtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgICBjYXNlIFwic1wiOlxuICAgICAgICBzY2FsZSA9IC0xO1xuICAgICAgICB0eXBlID0gXCJyXCI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHN5bWJvbCA9PT0gXCIkXCIpIHByZWZpeCA9IGxvY2FsZV9jdXJyZW5jeVswXSwgc3VmZml4ID0gbG9jYWxlX2N1cnJlbmN5WzFdO1xuICAgICAgaWYgKHR5cGUgPT0gXCJyXCIgJiYgIXByZWNpc2lvbikgdHlwZSA9IFwiZ1wiO1xuICAgICAgaWYgKHByZWNpc2lvbiAhPSBudWxsKSB7XG4gICAgICAgIGlmICh0eXBlID09IFwiZ1wiKSBwcmVjaXNpb24gPSBNYXRoLm1heCgxLCBNYXRoLm1pbigyMSwgcHJlY2lzaW9uKSk7IGVsc2UgaWYgKHR5cGUgPT0gXCJlXCIgfHwgdHlwZSA9PSBcImZcIikgcHJlY2lzaW9uID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjAsIHByZWNpc2lvbikpO1xuICAgICAgfVxuICAgICAgdHlwZSA9IGQzX2Zvcm1hdF90eXBlcy5nZXQodHlwZSkgfHwgZDNfZm9ybWF0X3R5cGVEZWZhdWx0O1xuICAgICAgdmFyIHpjb21tYSA9IHpmaWxsICYmIGNvbW1hO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciBmdWxsU3VmZml4ID0gc3VmZml4O1xuICAgICAgICBpZiAoaW50ZWdlciAmJiB2YWx1ZSAlIDEpIHJldHVybiBcIlwiO1xuICAgICAgICB2YXIgbmVnYXRpdmUgPSB2YWx1ZSA8IDAgfHwgdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCA/ICh2YWx1ZSA9IC12YWx1ZSwgXCItXCIpIDogc2lnbiA9PT0gXCItXCIgPyBcIlwiIDogc2lnbjtcbiAgICAgICAgaWYgKHNjYWxlIDwgMCkge1xuICAgICAgICAgIHZhciB1bml0ID0gZDMuZm9ybWF0UHJlZml4KHZhbHVlLCBwcmVjaXNpb24pO1xuICAgICAgICAgIHZhbHVlID0gdW5pdC5zY2FsZSh2YWx1ZSk7XG4gICAgICAgICAgZnVsbFN1ZmZpeCA9IHVuaXQuc3ltYm9sICsgc3VmZml4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlICo9IHNjYWxlO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlID0gdHlwZSh2YWx1ZSwgcHJlY2lzaW9uKTtcbiAgICAgICAgdmFyIGkgPSB2YWx1ZS5sYXN0SW5kZXhPZihcIi5cIiksIGJlZm9yZSwgYWZ0ZXI7XG4gICAgICAgIGlmIChpIDwgMCkge1xuICAgICAgICAgIHZhciBqID0gZXhwb25lbnQgPyB2YWx1ZS5sYXN0SW5kZXhPZihcImVcIikgOiAtMTtcbiAgICAgICAgICBpZiAoaiA8IDApIGJlZm9yZSA9IHZhbHVlLCBhZnRlciA9IFwiXCI7IGVsc2UgYmVmb3JlID0gdmFsdWUuc3Vic3RyaW5nKDAsIGopLCBhZnRlciA9IHZhbHVlLnN1YnN0cmluZyhqKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBiZWZvcmUgPSB2YWx1ZS5zdWJzdHJpbmcoMCwgaSk7XG4gICAgICAgICAgYWZ0ZXIgPSBsb2NhbGVfZGVjaW1hbCArIHZhbHVlLnN1YnN0cmluZyhpICsgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF6ZmlsbCAmJiBjb21tYSkgYmVmb3JlID0gZm9ybWF0R3JvdXAoYmVmb3JlLCBJbmZpbml0eSk7XG4gICAgICAgIHZhciBsZW5ndGggPSBwcmVmaXgubGVuZ3RoICsgYmVmb3JlLmxlbmd0aCArIGFmdGVyLmxlbmd0aCArICh6Y29tbWEgPyAwIDogbmVnYXRpdmUubGVuZ3RoKSwgcGFkZGluZyA9IGxlbmd0aCA8IHdpZHRoID8gbmV3IEFycmF5KGxlbmd0aCA9IHdpZHRoIC0gbGVuZ3RoICsgMSkuam9pbihmaWxsKSA6IFwiXCI7XG4gICAgICAgIGlmICh6Y29tbWEpIGJlZm9yZSA9IGZvcm1hdEdyb3VwKHBhZGRpbmcgKyBiZWZvcmUsIHBhZGRpbmcubGVuZ3RoID8gd2lkdGggLSBhZnRlci5sZW5ndGggOiBJbmZpbml0eSk7XG4gICAgICAgIG5lZ2F0aXZlICs9IHByZWZpeDtcbiAgICAgICAgdmFsdWUgPSBiZWZvcmUgKyBhZnRlcjtcbiAgICAgICAgcmV0dXJuIChhbGlnbiA9PT0gXCI8XCIgPyBuZWdhdGl2ZSArIHZhbHVlICsgcGFkZGluZyA6IGFsaWduID09PSBcIj5cIiA/IHBhZGRpbmcgKyBuZWdhdGl2ZSArIHZhbHVlIDogYWxpZ24gPT09IFwiXlwiID8gcGFkZGluZy5zdWJzdHJpbmcoMCwgbGVuZ3RoID4+PSAxKSArIG5lZ2F0aXZlICsgdmFsdWUgKyBwYWRkaW5nLnN1YnN0cmluZyhsZW5ndGgpIDogbmVnYXRpdmUgKyAoemNvbW1hID8gdmFsdWUgOiBwYWRkaW5nICsgdmFsdWUpKSArIGZ1bGxTdWZmaXg7XG4gICAgICB9O1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX2Zvcm1hdF9yZSA9IC8oPzooW157XSk/KFs8Pj1eXSkpPyhbK1xcLSBdKT8oWyQjXSk/KDApPyhcXGQrKT8oLCk/KFxcLi0/XFxkKyk/KFthLXolXSk/L2k7XG4gIHZhciBkM19mb3JtYXRfdHlwZXMgPSBkMy5tYXAoe1xuICAgIGI6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDIpO1xuICAgIH0sXG4gICAgYzogZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoeCk7XG4gICAgfSxcbiAgICBvOiBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4geC50b1N0cmluZyg4KTtcbiAgICB9LFxuICAgIHg6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDE2KTtcbiAgICB9LFxuICAgIFg6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xuICAgIH0sXG4gICAgZzogZnVuY3Rpb24oeCwgcCkge1xuICAgICAgcmV0dXJuIHgudG9QcmVjaXNpb24ocCk7XG4gICAgfSxcbiAgICBlOiBmdW5jdGlvbih4LCBwKSB7XG4gICAgICByZXR1cm4geC50b0V4cG9uZW50aWFsKHApO1xuICAgIH0sXG4gICAgZjogZnVuY3Rpb24oeCwgcCkge1xuICAgICAgcmV0dXJuIHgudG9GaXhlZChwKTtcbiAgICB9LFxuICAgIHI6IGZ1bmN0aW9uKHgsIHApIHtcbiAgICAgIHJldHVybiAoeCA9IGQzLnJvdW5kKHgsIGQzX2Zvcm1hdF9wcmVjaXNpb24oeCwgcCkpKS50b0ZpeGVkKE1hdGgubWF4KDAsIE1hdGgubWluKDIwLCBkM19mb3JtYXRfcHJlY2lzaW9uKHggKiAoMSArIDFlLTE1KSwgcCkpKSk7XG4gICAgfVxuICB9KTtcbiAgZnVuY3Rpb24gZDNfZm9ybWF0X3R5cGVEZWZhdWx0KHgpIHtcbiAgICByZXR1cm4geCArIFwiXCI7XG4gIH1cbiAgdmFyIGQzX3RpbWUgPSBkMy50aW1lID0ge30sIGQzX2RhdGUgPSBEYXRlO1xuICBmdW5jdGlvbiBkM19kYXRlX3V0YygpIHtcbiAgICB0aGlzLl8gPSBuZXcgRGF0ZShhcmd1bWVudHMubGVuZ3RoID4gMSA/IERhdGUuVVRDLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBhcmd1bWVudHNbMF0pO1xuICB9XG4gIGQzX2RhdGVfdXRjLnByb3RvdHlwZSA9IHtcbiAgICBnZXREYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDRGF0ZSgpO1xuICAgIH0sXG4gICAgZ2V0RGF5OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDRGF5KCk7XG4gICAgfSxcbiAgICBnZXRGdWxsWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ0Z1bGxZZWFyKCk7XG4gICAgfSxcbiAgICBnZXRIb3VyczogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ0hvdXJzKCk7XG4gICAgfSxcbiAgICBnZXRNaWxsaXNlY29uZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuXy5nZXRVVENNaWxsaXNlY29uZHMoKTtcbiAgICB9LFxuICAgIGdldE1pbnV0ZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuXy5nZXRVVENNaW51dGVzKCk7XG4gICAgfSxcbiAgICBnZXRNb250aDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ01vbnRoKCk7XG4gICAgfSxcbiAgICBnZXRTZWNvbmRzOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDU2Vjb25kcygpO1xuICAgIH0sXG4gICAgZ2V0VGltZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFRpbWUoKTtcbiAgICB9LFxuICAgIGdldFRpbWV6b25lT2Zmc2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0sXG4gICAgdmFsdWVPZjogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLnZhbHVlT2YoKTtcbiAgICB9LFxuICAgIHNldERhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDRGF0ZS5hcHBseSh0aGlzLl8sIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBzZXREYXk6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDRGF5LmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldEZ1bGxZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ0Z1bGxZZWFyLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldEhvdXJzOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ0hvdXJzLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldE1pbGxpc2Vjb25kczogZnVuY3Rpb24oKSB7XG4gICAgICBkM190aW1lX3Byb3RvdHlwZS5zZXRVVENNaWxsaXNlY29uZHMuYXBwbHkodGhpcy5fLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgc2V0TWludXRlczogZnVuY3Rpb24oKSB7XG4gICAgICBkM190aW1lX3Byb3RvdHlwZS5zZXRVVENNaW51dGVzLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldE1vbnRoOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ01vbnRoLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldFNlY29uZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDU2Vjb25kcy5hcHBseSh0aGlzLl8sIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBzZXRUaW1lOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFRpbWUuYXBwbHkodGhpcy5fLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfTtcbiAgdmFyIGQzX3RpbWVfcHJvdG90eXBlID0gRGF0ZS5wcm90b3R5cGU7XG4gIGZ1bmN0aW9uIGQzX3RpbWVfaW50ZXJ2YWwobG9jYWwsIHN0ZXAsIG51bWJlcikge1xuICAgIGZ1bmN0aW9uIHJvdW5kKGRhdGUpIHtcbiAgICAgIHZhciBkMCA9IGxvY2FsKGRhdGUpLCBkMSA9IG9mZnNldChkMCwgMSk7XG4gICAgICByZXR1cm4gZGF0ZSAtIGQwIDwgZDEgLSBkYXRlID8gZDAgOiBkMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY2VpbChkYXRlKSB7XG4gICAgICBzdGVwKGRhdGUgPSBsb2NhbChuZXcgZDNfZGF0ZShkYXRlIC0gMSkpLCAxKTtcbiAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cbiAgICBmdW5jdGlvbiBvZmZzZXQoZGF0ZSwgaykge1xuICAgICAgc3RlcChkYXRlID0gbmV3IGQzX2RhdGUoK2RhdGUpLCBrKTtcbiAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cbiAgICBmdW5jdGlvbiByYW5nZSh0MCwgdDEsIGR0KSB7XG4gICAgICB2YXIgdGltZSA9IGNlaWwodDApLCB0aW1lcyA9IFtdO1xuICAgICAgaWYgKGR0ID4gMSkge1xuICAgICAgICB3aGlsZSAodGltZSA8IHQxKSB7XG4gICAgICAgICAgaWYgKCEobnVtYmVyKHRpbWUpICUgZHQpKSB0aW1lcy5wdXNoKG5ldyBEYXRlKCt0aW1lKSk7XG4gICAgICAgICAgc3RlcCh0aW1lLCAxKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2hpbGUgKHRpbWUgPCB0MSkgdGltZXMucHVzaChuZXcgRGF0ZSgrdGltZSkpLCBzdGVwKHRpbWUsIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRpbWVzO1xuICAgIH1cbiAgICBmdW5jdGlvbiByYW5nZV91dGModDAsIHQxLCBkdCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZDNfZGF0ZSA9IGQzX2RhdGVfdXRjO1xuICAgICAgICB2YXIgdXRjID0gbmV3IGQzX2RhdGVfdXRjKCk7XG4gICAgICAgIHV0Yy5fID0gdDA7XG4gICAgICAgIHJldHVybiByYW5nZSh1dGMsIHQxLCBkdCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkM19kYXRlID0gRGF0ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgbG9jYWwuZmxvb3IgPSBsb2NhbDtcbiAgICBsb2NhbC5yb3VuZCA9IHJvdW5kO1xuICAgIGxvY2FsLmNlaWwgPSBjZWlsO1xuICAgIGxvY2FsLm9mZnNldCA9IG9mZnNldDtcbiAgICBsb2NhbC5yYW5nZSA9IHJhbmdlO1xuICAgIHZhciB1dGMgPSBsb2NhbC51dGMgPSBkM190aW1lX2ludGVydmFsX3V0Yyhsb2NhbCk7XG4gICAgdXRjLmZsb29yID0gdXRjO1xuICAgIHV0Yy5yb3VuZCA9IGQzX3RpbWVfaW50ZXJ2YWxfdXRjKHJvdW5kKTtcbiAgICB1dGMuY2VpbCA9IGQzX3RpbWVfaW50ZXJ2YWxfdXRjKGNlaWwpO1xuICAgIHV0Yy5vZmZzZXQgPSBkM190aW1lX2ludGVydmFsX3V0YyhvZmZzZXQpO1xuICAgIHV0Yy5yYW5nZSA9IHJhbmdlX3V0YztcbiAgICByZXR1cm4gbG9jYWw7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9pbnRlcnZhbF91dGMobWV0aG9kKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGRhdGUsIGspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgdmFyIHV0YyA9IG5ldyBkM19kYXRlX3V0YygpO1xuICAgICAgICB1dGMuXyA9IGRhdGU7XG4gICAgICAgIHJldHVybiBtZXRob2QodXRjLCBrKS5fO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgZDNfZGF0ZSA9IERhdGU7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkM190aW1lLnllYXIgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlID0gZDNfdGltZS5kYXkoZGF0ZSk7XG4gICAgZGF0ZS5zZXRNb250aCgwLCAxKTtcbiAgICByZXR1cm4gZGF0ZTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRGdWxsWWVhcihkYXRlLmdldEZ1bGxZZWFyKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0RnVsbFllYXIoKTtcbiAgfSk7XG4gIGQzX3RpbWUueWVhcnMgPSBkM190aW1lLnllYXIucmFuZ2U7XG4gIGQzX3RpbWUueWVhcnMudXRjID0gZDNfdGltZS55ZWFyLnV0Yy5yYW5nZTtcbiAgZDNfdGltZS5kYXkgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgZGF5ID0gbmV3IGQzX2RhdGUoMmUzLCAwKTtcbiAgICBkYXkuc2V0RnVsbFllYXIoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpKTtcbiAgICByZXR1cm4gZGF5O1xuICB9LCBmdW5jdGlvbihkYXRlLCBvZmZzZXQpIHtcbiAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0RGF0ZSgpIC0gMTtcbiAgfSk7XG4gIGQzX3RpbWUuZGF5cyA9IGQzX3RpbWUuZGF5LnJhbmdlO1xuICBkM190aW1lLmRheXMudXRjID0gZDNfdGltZS5kYXkudXRjLnJhbmdlO1xuICBkM190aW1lLmRheU9mWWVhciA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgeWVhciA9IGQzX3RpbWUueWVhcihkYXRlKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcigoZGF0ZSAtIHllYXIgLSAoZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpIC0geWVhci5nZXRUaW1lem9uZU9mZnNldCgpKSAqIDZlNCkgLyA4NjRlNSk7XG4gIH07XG4gIFsgXCJzdW5kYXlcIiwgXCJtb25kYXlcIiwgXCJ0dWVzZGF5XCIsIFwid2VkbmVzZGF5XCIsIFwidGh1cnNkYXlcIiwgXCJmcmlkYXlcIiwgXCJzYXR1cmRheVwiIF0uZm9yRWFjaChmdW5jdGlvbihkYXksIGkpIHtcbiAgICBpID0gNyAtIGk7XG4gICAgdmFyIGludGVydmFsID0gZDNfdGltZVtkYXldID0gZDNfdGltZV9pbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgICAoZGF0ZSA9IGQzX3RpbWUuZGF5KGRhdGUpKS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpIC0gKGRhdGUuZ2V0RGF5KCkgKyBpKSAlIDcpO1xuICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBNYXRoLmZsb29yKG9mZnNldCkgKiA3KTtcbiAgICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgICB2YXIgZGF5ID0gZDNfdGltZS55ZWFyKGRhdGUpLmdldERheSgpO1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGQzX3RpbWUuZGF5T2ZZZWFyKGRhdGUpICsgKGRheSArIGkpICUgNykgLyA3KSAtIChkYXkgIT09IGkpO1xuICAgIH0pO1xuICAgIGQzX3RpbWVbZGF5ICsgXCJzXCJdID0gaW50ZXJ2YWwucmFuZ2U7XG4gICAgZDNfdGltZVtkYXkgKyBcInNcIl0udXRjID0gaW50ZXJ2YWwudXRjLnJhbmdlO1xuICAgIGQzX3RpbWVbZGF5ICsgXCJPZlllYXJcIl0gPSBmdW5jdGlvbihkYXRlKSB7XG4gICAgICB2YXIgZGF5ID0gZDNfdGltZS55ZWFyKGRhdGUpLmdldERheSgpO1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGQzX3RpbWUuZGF5T2ZZZWFyKGRhdGUpICsgKGRheSArIGkpICUgNykgLyA3KTtcbiAgICB9O1xuICB9KTtcbiAgZDNfdGltZS53ZWVrID0gZDNfdGltZS5zdW5kYXk7XG4gIGQzX3RpbWUud2Vla3MgPSBkM190aW1lLnN1bmRheS5yYW5nZTtcbiAgZDNfdGltZS53ZWVrcy51dGMgPSBkM190aW1lLnN1bmRheS51dGMucmFuZ2U7XG4gIGQzX3RpbWUud2Vla09mWWVhciA9IGQzX3RpbWUuc3VuZGF5T2ZZZWFyO1xuICBmdW5jdGlvbiBkM19sb2NhbGVfdGltZUZvcm1hdChsb2NhbGUpIHtcbiAgICB2YXIgbG9jYWxlX2RhdGVUaW1lID0gbG9jYWxlLmRhdGVUaW1lLCBsb2NhbGVfZGF0ZSA9IGxvY2FsZS5kYXRlLCBsb2NhbGVfdGltZSA9IGxvY2FsZS50aW1lLCBsb2NhbGVfcGVyaW9kcyA9IGxvY2FsZS5wZXJpb2RzLCBsb2NhbGVfZGF5cyA9IGxvY2FsZS5kYXlzLCBsb2NhbGVfc2hvcnREYXlzID0gbG9jYWxlLnNob3J0RGF5cywgbG9jYWxlX21vbnRocyA9IGxvY2FsZS5tb250aHMsIGxvY2FsZV9zaG9ydE1vbnRocyA9IGxvY2FsZS5zaG9ydE1vbnRocztcbiAgICBmdW5jdGlvbiBkM190aW1lX2Zvcm1hdCh0ZW1wbGF0ZSkge1xuICAgICAgdmFyIG4gPSB0ZW1wbGF0ZS5sZW5ndGg7XG4gICAgICBmdW5jdGlvbiBmb3JtYXQoZGF0ZSkge1xuICAgICAgICB2YXIgc3RyaW5nID0gW10sIGkgPSAtMSwgaiA9IDAsIGMsIHAsIGY7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgaWYgKHRlbXBsYXRlLmNoYXJDb2RlQXQoaSkgPT09IDM3KSB7XG4gICAgICAgICAgICBzdHJpbmcucHVzaCh0ZW1wbGF0ZS5zbGljZShqLCBpKSk7XG4gICAgICAgICAgICBpZiAoKHAgPSBkM190aW1lX2Zvcm1hdFBhZHNbYyA9IHRlbXBsYXRlLmNoYXJBdCgrK2kpXSkgIT0gbnVsbCkgYyA9IHRlbXBsYXRlLmNoYXJBdCgrK2kpO1xuICAgICAgICAgICAgaWYgKGYgPSBkM190aW1lX2Zvcm1hdHNbY10pIGMgPSBmKGRhdGUsIHAgPT0gbnVsbCA/IGMgPT09IFwiZVwiID8gXCIgXCIgOiBcIjBcIiA6IHApO1xuICAgICAgICAgICAgc3RyaW5nLnB1c2goYyk7XG4gICAgICAgICAgICBqID0gaSArIDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0cmluZy5wdXNoKHRlbXBsYXRlLnNsaWNlKGosIGkpKTtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5qb2luKFwiXCIpO1xuICAgICAgfVxuICAgICAgZm9ybWF0LnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICAgIHZhciBkID0ge1xuICAgICAgICAgIHk6IDE5MDAsXG4gICAgICAgICAgbTogMCxcbiAgICAgICAgICBkOiAxLFxuICAgICAgICAgIEg6IDAsXG4gICAgICAgICAgTTogMCxcbiAgICAgICAgICBTOiAwLFxuICAgICAgICAgIEw6IDAsXG4gICAgICAgICAgWjogbnVsbFxuICAgICAgICB9LCBpID0gZDNfdGltZV9wYXJzZShkLCB0ZW1wbGF0ZSwgc3RyaW5nLCAwKTtcbiAgICAgICAgaWYgKGkgIT0gc3RyaW5nLmxlbmd0aCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGlmIChcInBcIiBpbiBkKSBkLkggPSBkLkggJSAxMiArIGQucCAqIDEyO1xuICAgICAgICB2YXIgbG9jYWxaID0gZC5aICE9IG51bGwgJiYgZDNfZGF0ZSAhPT0gZDNfZGF0ZV91dGMsIGRhdGUgPSBuZXcgKGxvY2FsWiA/IGQzX2RhdGVfdXRjIDogZDNfZGF0ZSkoKTtcbiAgICAgICAgaWYgKFwialwiIGluIGQpIGRhdGUuc2V0RnVsbFllYXIoZC55LCAwLCBkLmopOyBlbHNlIGlmIChcIldcIiBpbiBkIHx8IFwiVVwiIGluIGQpIHtcbiAgICAgICAgICBpZiAoIShcIndcIiBpbiBkKSkgZC53ID0gXCJXXCIgaW4gZCA/IDEgOiAwO1xuICAgICAgICAgIGRhdGUuc2V0RnVsbFllYXIoZC55LCAwLCAxKTtcbiAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKGQueSwgMCwgXCJXXCIgaW4gZCA/IChkLncgKyA2KSAlIDcgKyBkLlcgKiA3IC0gKGRhdGUuZ2V0RGF5KCkgKyA1KSAlIDcgOiBkLncgKyBkLlUgKiA3IC0gKGRhdGUuZ2V0RGF5KCkgKyA2KSAlIDcpO1xuICAgICAgICB9IGVsc2UgZGF0ZS5zZXRGdWxsWWVhcihkLnksIGQubSwgZC5kKTtcbiAgICAgICAgZGF0ZS5zZXRIb3VycyhkLkggKyAoZC5aIC8gMTAwIHwgMCksIGQuTSArIGQuWiAlIDEwMCwgZC5TLCBkLkwpO1xuICAgICAgICByZXR1cm4gbG9jYWxaID8gZGF0ZS5fIDogZGF0ZTtcbiAgICAgIH07XG4gICAgICBmb3JtYXQudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgfTtcbiAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2UoZGF0ZSwgdGVtcGxhdGUsIHN0cmluZywgaikge1xuICAgICAgdmFyIGMsIHAsIHQsIGkgPSAwLCBuID0gdGVtcGxhdGUubGVuZ3RoLCBtID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIHdoaWxlIChpIDwgbikge1xuICAgICAgICBpZiAoaiA+PSBtKSByZXR1cm4gLTE7XG4gICAgICAgIGMgPSB0ZW1wbGF0ZS5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgIGlmIChjID09PSAzNykge1xuICAgICAgICAgIHQgPSB0ZW1wbGF0ZS5jaGFyQXQoaSsrKTtcbiAgICAgICAgICBwID0gZDNfdGltZV9wYXJzZXJzW3QgaW4gZDNfdGltZV9mb3JtYXRQYWRzID8gdGVtcGxhdGUuY2hhckF0KGkrKykgOiB0XTtcbiAgICAgICAgICBpZiAoIXAgfHwgKGogPSBwKGRhdGUsIHN0cmluZywgaikpIDwgMCkgcmV0dXJuIC0xO1xuICAgICAgICB9IGVsc2UgaWYgKGMgIT0gc3RyaW5nLmNoYXJDb2RlQXQoaisrKSkge1xuICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGo7XG4gICAgfVxuICAgIGQzX3RpbWVfZm9ybWF0LnV0YyA9IGZ1bmN0aW9uKHRlbXBsYXRlKSB7XG4gICAgICB2YXIgbG9jYWwgPSBkM190aW1lX2Zvcm1hdCh0ZW1wbGF0ZSk7XG4gICAgICBmdW5jdGlvbiBmb3JtYXQoZGF0ZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgICB2YXIgdXRjID0gbmV3IGQzX2RhdGUoKTtcbiAgICAgICAgICB1dGMuXyA9IGRhdGU7XG4gICAgICAgICAgcmV0dXJuIGxvY2FsKHV0Yyk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgZDNfZGF0ZSA9IERhdGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvcm1hdC5wYXJzZSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgICB2YXIgZGF0ZSA9IGxvY2FsLnBhcnNlKHN0cmluZyk7XG4gICAgICAgICAgcmV0dXJuIGRhdGUgJiYgZGF0ZS5fO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGQzX2RhdGUgPSBEYXRlO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZm9ybWF0LnRvU3RyaW5nID0gbG9jYWwudG9TdHJpbmc7XG4gICAgICByZXR1cm4gZm9ybWF0O1xuICAgIH07XG4gICAgZDNfdGltZV9mb3JtYXQubXVsdGkgPSBkM190aW1lX2Zvcm1hdC51dGMubXVsdGkgPSBkM190aW1lX2Zvcm1hdE11bHRpO1xuICAgIHZhciBkM190aW1lX3BlcmlvZExvb2t1cCA9IGQzLm1hcCgpLCBkM190aW1lX2RheVJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfZGF5cyksIGQzX3RpbWVfZGF5TG9va3VwID0gZDNfdGltZV9mb3JtYXRMb29rdXAobG9jYWxlX2RheXMpLCBkM190aW1lX2RheUFiYnJldlJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfc2hvcnREYXlzKSwgZDNfdGltZV9kYXlBYmJyZXZMb29rdXAgPSBkM190aW1lX2Zvcm1hdExvb2t1cChsb2NhbGVfc2hvcnREYXlzKSwgZDNfdGltZV9tb250aFJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfbW9udGhzKSwgZDNfdGltZV9tb250aExvb2t1cCA9IGQzX3RpbWVfZm9ybWF0TG9va3VwKGxvY2FsZV9tb250aHMpLCBkM190aW1lX21vbnRoQWJicmV2UmUgPSBkM190aW1lX2Zvcm1hdFJlKGxvY2FsZV9zaG9ydE1vbnRocyksIGQzX3RpbWVfbW9udGhBYmJyZXZMb29rdXAgPSBkM190aW1lX2Zvcm1hdExvb2t1cChsb2NhbGVfc2hvcnRNb250aHMpO1xuICAgIGxvY2FsZV9wZXJpb2RzLmZvckVhY2goZnVuY3Rpb24ocCwgaSkge1xuICAgICAgZDNfdGltZV9wZXJpb2RMb29rdXAuc2V0KHAudG9Mb3dlckNhc2UoKSwgaSk7XG4gICAgfSk7XG4gICAgdmFyIGQzX3RpbWVfZm9ybWF0cyA9IHtcbiAgICAgIGE6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZV9zaG9ydERheXNbZC5nZXREYXkoKV07XG4gICAgICB9LFxuICAgICAgQTogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX2RheXNbZC5nZXREYXkoKV07XG4gICAgICB9LFxuICAgICAgYjogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX3Nob3J0TW9udGhzW2QuZ2V0TW9udGgoKV07XG4gICAgICB9LFxuICAgICAgQjogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX21vbnRoc1tkLmdldE1vbnRoKCldO1xuICAgICAgfSxcbiAgICAgIGM6IGQzX3RpbWVfZm9ybWF0KGxvY2FsZV9kYXRlVGltZSksXG4gICAgICBkOiBmdW5jdGlvbihkLCBwKSB7XG4gICAgICAgIHJldHVybiBkM190aW1lX2Zvcm1hdFBhZChkLmdldERhdGUoKSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgZTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXREYXRlKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIEg6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQuZ2V0SG91cnMoKSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgSTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRIb3VycygpICUgMTIgfHwgMTIsIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIGo6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKDEgKyBkM190aW1lLmRheU9mWWVhcihkKSwgcCwgMyk7XG4gICAgICB9LFxuICAgICAgTDogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNaWxsaXNlY29uZHMoKSwgcCwgMyk7XG4gICAgICB9LFxuICAgICAgbTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNb250aCgpICsgMSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgTTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNaW51dGVzKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIHA6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZV9wZXJpb2RzWysoZC5nZXRIb3VycygpID49IDEyKV07XG4gICAgICB9LFxuICAgICAgUzogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRTZWNvbmRzKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIFU6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQzX3RpbWUuc3VuZGF5T2ZZZWFyKGQpLCBwLCAyKTtcbiAgICAgIH0sXG4gICAgICB3OiBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkLmdldERheSgpO1xuICAgICAgfSxcbiAgICAgIFc6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQzX3RpbWUubW9uZGF5T2ZZZWFyKGQpLCBwLCAyKTtcbiAgICAgIH0sXG4gICAgICB4OiBkM190aW1lX2Zvcm1hdChsb2NhbGVfZGF0ZSksXG4gICAgICBYOiBkM190aW1lX2Zvcm1hdChsb2NhbGVfdGltZSksXG4gICAgICB5OiBmdW5jdGlvbihkLCBwKSB7XG4gICAgICAgIHJldHVybiBkM190aW1lX2Zvcm1hdFBhZChkLmdldEZ1bGxZZWFyKCkgJSAxMDAsIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIFk6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQuZ2V0RnVsbFllYXIoKSAlIDFlNCwgcCwgNCk7XG4gICAgICB9LFxuICAgICAgWjogZDNfdGltZV96b25lLFxuICAgICAgXCIlXCI6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gXCIlXCI7XG4gICAgICB9XG4gICAgfTtcbiAgICB2YXIgZDNfdGltZV9wYXJzZXJzID0ge1xuICAgICAgYTogZDNfdGltZV9wYXJzZVdlZWtkYXlBYmJyZXYsXG4gICAgICBBOiBkM190aW1lX3BhcnNlV2Vla2RheSxcbiAgICAgIGI6IGQzX3RpbWVfcGFyc2VNb250aEFiYnJldixcbiAgICAgIEI6IGQzX3RpbWVfcGFyc2VNb250aCxcbiAgICAgIGM6IGQzX3RpbWVfcGFyc2VMb2NhbGVGdWxsLFxuICAgICAgZDogZDNfdGltZV9wYXJzZURheSxcbiAgICAgIGU6IGQzX3RpbWVfcGFyc2VEYXksXG4gICAgICBIOiBkM190aW1lX3BhcnNlSG91cjI0LFxuICAgICAgSTogZDNfdGltZV9wYXJzZUhvdXIyNCxcbiAgICAgIGo6IGQzX3RpbWVfcGFyc2VEYXlPZlllYXIsXG4gICAgICBMOiBkM190aW1lX3BhcnNlTWlsbGlzZWNvbmRzLFxuICAgICAgbTogZDNfdGltZV9wYXJzZU1vbnRoTnVtYmVyLFxuICAgICAgTTogZDNfdGltZV9wYXJzZU1pbnV0ZXMsXG4gICAgICBwOiBkM190aW1lX3BhcnNlQW1QbSxcbiAgICAgIFM6IGQzX3RpbWVfcGFyc2VTZWNvbmRzLFxuICAgICAgVTogZDNfdGltZV9wYXJzZVdlZWtOdW1iZXJTdW5kYXksXG4gICAgICB3OiBkM190aW1lX3BhcnNlV2Vla2RheU51bWJlcixcbiAgICAgIFc6IGQzX3RpbWVfcGFyc2VXZWVrTnVtYmVyTW9uZGF5LFxuICAgICAgeDogZDNfdGltZV9wYXJzZUxvY2FsZURhdGUsXG4gICAgICBYOiBkM190aW1lX3BhcnNlTG9jYWxlVGltZSxcbiAgICAgIHk6IGQzX3RpbWVfcGFyc2VZZWFyLFxuICAgICAgWTogZDNfdGltZV9wYXJzZUZ1bGxZZWFyLFxuICAgICAgWjogZDNfdGltZV9wYXJzZVpvbmUsXG4gICAgICBcIiVcIjogZDNfdGltZV9wYXJzZUxpdGVyYWxQZXJjZW50XG4gICAgfTtcbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheUFiYnJldihkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIGQzX3RpbWVfZGF5QWJicmV2UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9kYXlBYmJyZXZSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLncgPSBkM190aW1lX2RheUFiYnJldkxvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIGQzX3RpbWVfZGF5UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9kYXlSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLncgPSBkM190aW1lX2RheUxvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTW9udGhBYmJyZXYoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgICBkM190aW1lX21vbnRoQWJicmV2UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9tb250aEFiYnJldlJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICAgIHJldHVybiBuID8gKGRhdGUubSA9IGQzX3RpbWVfbW9udGhBYmJyZXZMb29rdXAuZ2V0KG5bMF0udG9Mb3dlckNhc2UoKSksIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1vbnRoKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgZDNfdGltZV9tb250aFJlLmxhc3RJbmRleCA9IDA7XG4gICAgICB2YXIgbiA9IGQzX3RpbWVfbW9udGhSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLm0gPSBkM190aW1lX21vbnRoTG9va3VwLmdldChuWzBdLnRvTG93ZXJDYXNlKCkpLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VMb2NhbGVGdWxsKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgcmV0dXJuIGQzX3RpbWVfcGFyc2UoZGF0ZSwgZDNfdGltZV9mb3JtYXRzLmMudG9TdHJpbmcoKSwgc3RyaW5nLCBpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUxvY2FsZURhdGUoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9wYXJzZShkYXRlLCBkM190aW1lX2Zvcm1hdHMueC50b1N0cmluZygpLCBzdHJpbmcsIGkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTG9jYWxlVGltZShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIHJldHVybiBkM190aW1lX3BhcnNlKGRhdGUsIGQzX3RpbWVfZm9ybWF0cy5YLnRvU3RyaW5nKCksIHN0cmluZywgaSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VBbVBtKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgdmFyIG4gPSBkM190aW1lX3BlcmlvZExvb2t1cC5nZXQoc3RyaW5nLnNsaWNlKGksIGkgKz0gMikudG9Mb3dlckNhc2UoKSk7XG4gICAgICByZXR1cm4gbiA9PSBudWxsID8gLTEgOiAoZGF0ZS5wID0gbiwgaSk7XG4gICAgfVxuICAgIHJldHVybiBkM190aW1lX2Zvcm1hdDtcbiAgfVxuICB2YXIgZDNfdGltZV9mb3JtYXRQYWRzID0ge1xuICAgIFwiLVwiOiBcIlwiLFxuICAgIF86IFwiIFwiLFxuICAgIFwiMFwiOiBcIjBcIlxuICB9LCBkM190aW1lX251bWJlclJlID0gL15cXHMqXFxkKy8sIGQzX3RpbWVfcGVyY2VudFJlID0gL14lLztcbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRQYWQodmFsdWUsIGZpbGwsIHdpZHRoKSB7XG4gICAgdmFyIHNpZ24gPSB2YWx1ZSA8IDAgPyBcIi1cIiA6IFwiXCIsIHN0cmluZyA9IChzaWduID8gLXZhbHVlIDogdmFsdWUpICsgXCJcIiwgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcbiAgICByZXR1cm4gc2lnbiArIChsZW5ndGggPCB3aWR0aCA/IG5ldyBBcnJheSh3aWR0aCAtIGxlbmd0aCArIDEpLmpvaW4oZmlsbCkgKyBzdHJpbmcgOiBzdHJpbmcpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfZm9ybWF0UmUobmFtZXMpIHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChcIl4oPzpcIiArIG5hbWVzLm1hcChkMy5yZXF1b3RlKS5qb2luKFwifFwiKSArIFwiKVwiLCBcImlcIik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRMb29rdXAobmFtZXMpIHtcbiAgICB2YXIgbWFwID0gbmV3IGQzX01hcCgpLCBpID0gLTEsIG4gPSBuYW1lcy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IG4pIG1hcC5zZXQobmFtZXNbaV0udG9Mb3dlckNhc2UoKSwgaSk7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheU51bWJlcihkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAxKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS53ID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla051bWJlclN1bmRheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLlUgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VXZWVrTnVtYmVyTW9uZGF5KGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSkpO1xuICAgIHJldHVybiBuID8gKGRhdGUuVyA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUZ1bGxZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDQpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLnkgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLnkgPSBkM190aW1lX2V4cGFuZFllYXIoK25bMF0pLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZVpvbmUoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgcmV0dXJuIC9eWystXVxcZHs0fSQvLnRlc3Qoc3RyaW5nID0gc3RyaW5nLnNsaWNlKGksIGkgKyA1KSkgPyAoZGF0ZS5aID0gLXN0cmluZywgXG4gICAgaSArIDUpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9leHBhbmRZZWFyKGQpIHtcbiAgICByZXR1cm4gZCArIChkID4gNjggPyAxOTAwIDogMmUzKTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTW9udGhOdW1iZXIoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUubSA9IG5bMF0gLSAxLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZURheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS5kID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlRGF5T2ZZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDMpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLmogPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VIb3VyMjQoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuSCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1pbnV0ZXMoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuTSA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZVNlY29uZHMoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuUyA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1pbGxpc2Vjb25kcyhkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAzKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS5MID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3pvbmUoZCkge1xuICAgIHZhciB6ID0gZC5nZXRUaW1lem9uZU9mZnNldCgpLCB6cyA9IHogPiAwID8gXCItXCIgOiBcIitcIiwgemggPSBhYnMoeikgLyA2MCB8IDAsIHptID0gYWJzKHopICUgNjA7XG4gICAgcmV0dXJuIHpzICsgZDNfdGltZV9mb3JtYXRQYWQoemgsIFwiMFwiLCAyKSArIGQzX3RpbWVfZm9ybWF0UGFkKHptLCBcIjBcIiwgMik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUxpdGVyYWxQZXJjZW50KGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfcGVyY2VudFJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX3BlcmNlbnRSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMSkpO1xuICAgIHJldHVybiBuID8gaSArIG5bMF0ubGVuZ3RoIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRNdWx0aShmb3JtYXRzKSB7XG4gICAgdmFyIG4gPSBmb3JtYXRzLmxlbmd0aCwgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBuKSBmb3JtYXRzW2ldWzBdID0gdGhpcyhmb3JtYXRzW2ldWzBdKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgdmFyIGkgPSAwLCBmID0gZm9ybWF0c1tpXTtcbiAgICAgIHdoaWxlICghZlsxXShkYXRlKSkgZiA9IGZvcm1hdHNbKytpXTtcbiAgICAgIHJldHVybiBmWzBdKGRhdGUpO1xuICAgIH07XG4gIH1cbiAgZDMubG9jYWxlID0gZnVuY3Rpb24obG9jYWxlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG51bWJlckZvcm1hdDogZDNfbG9jYWxlX251bWJlckZvcm1hdChsb2NhbGUpLFxuICAgICAgdGltZUZvcm1hdDogZDNfbG9jYWxlX3RpbWVGb3JtYXQobG9jYWxlKVxuICAgIH07XG4gIH07XG4gIHZhciBkM19sb2NhbGVfZW5VUyA9IGQzLmxvY2FsZSh7XG4gICAgZGVjaW1hbDogXCIuXCIsXG4gICAgdGhvdXNhbmRzOiBcIixcIixcbiAgICBncm91cGluZzogWyAzIF0sXG4gICAgY3VycmVuY3k6IFsgXCIkXCIsIFwiXCIgXSxcbiAgICBkYXRlVGltZTogXCIlYSAlYiAlZSAlWCAlWVwiLFxuICAgIGRhdGU6IFwiJW0vJWQvJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogWyBcIkFNXCIsIFwiUE1cIiBdLFxuICAgIGRheXM6IFsgXCJTdW5kYXlcIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiIF0sXG4gICAgc2hvcnREYXlzOiBbIFwiU3VuXCIsIFwiTW9uXCIsIFwiVHVlXCIsIFwiV2VkXCIsIFwiVGh1XCIsIFwiRnJpXCIsIFwiU2F0XCIgXSxcbiAgICBtb250aHM6IFsgXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLCBcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiIF0sXG4gICAgc2hvcnRNb250aHM6IFsgXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIiBdXG4gIH0pO1xuICBkMy5mb3JtYXQgPSBkM19sb2NhbGVfZW5VUy5udW1iZXJGb3JtYXQ7XG4gIGQzLmdlbyA9IHt9O1xuICBmdW5jdGlvbiBkM19hZGRlcigpIHt9XG4gIGQzX2FkZGVyLnByb3RvdHlwZSA9IHtcbiAgICBzOiAwLFxuICAgIHQ6IDAsXG4gICAgYWRkOiBmdW5jdGlvbih5KSB7XG4gICAgICBkM19hZGRlclN1bSh5LCB0aGlzLnQsIGQzX2FkZGVyVGVtcCk7XG4gICAgICBkM19hZGRlclN1bShkM19hZGRlclRlbXAucywgdGhpcy5zLCB0aGlzKTtcbiAgICAgIGlmICh0aGlzLnMpIHRoaXMudCArPSBkM19hZGRlclRlbXAudDsgZWxzZSB0aGlzLnMgPSBkM19hZGRlclRlbXAudDtcbiAgICB9LFxuICAgIHJlc2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMucyA9IHRoaXMudCA9IDA7XG4gICAgfSxcbiAgICB2YWx1ZU9mOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnM7XG4gICAgfVxuICB9O1xuICB2YXIgZDNfYWRkZXJUZW1wID0gbmV3IGQzX2FkZGVyKCk7XG4gIGZ1bmN0aW9uIGQzX2FkZGVyU3VtKGEsIGIsIG8pIHtcbiAgICB2YXIgeCA9IG8ucyA9IGEgKyBiLCBidiA9IHggLSBhLCBhdiA9IHggLSBidjtcbiAgICBvLnQgPSBhIC0gYXYgKyAoYiAtIGJ2KTtcbiAgfVxuICBkMy5nZW8uc3RyZWFtID0gZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgIGlmIChvYmplY3QgJiYgZDNfZ2VvX3N0cmVhbU9iamVjdFR5cGUuaGFzT3duUHJvcGVydHkob2JqZWN0LnR5cGUpKSB7XG4gICAgICBkM19nZW9fc3RyZWFtT2JqZWN0VHlwZVtvYmplY3QudHlwZV0ob2JqZWN0LCBsaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGQzX2dlb19zdHJlYW1HZW9tZXRyeShvYmplY3QsIGxpc3RlbmVyKTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19zdHJlYW1HZW9tZXRyeShnZW9tZXRyeSwgbGlzdGVuZXIpIHtcbiAgICBpZiAoZ2VvbWV0cnkgJiYgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZS5oYXNPd25Qcm9wZXJ0eShnZW9tZXRyeS50eXBlKSkge1xuICAgICAgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZVtnZW9tZXRyeS50eXBlXShnZW9tZXRyeSwgbGlzdGVuZXIpO1xuICAgIH1cbiAgfVxuICB2YXIgZDNfZ2VvX3N0cmVhbU9iamVjdFR5cGUgPSB7XG4gICAgRmVhdHVyZTogZnVuY3Rpb24oZmVhdHVyZSwgbGlzdGVuZXIpIHtcbiAgICAgIGQzX2dlb19zdHJlYW1HZW9tZXRyeShmZWF0dXJlLmdlb21ldHJ5LCBsaXN0ZW5lcik7XG4gICAgfSxcbiAgICBGZWF0dXJlQ29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGZlYXR1cmVzID0gb2JqZWN0LmZlYXR1cmVzLCBpID0gLTEsIG4gPSBmZWF0dXJlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5KGZlYXR1cmVzW2ldLmdlb21ldHJ5LCBsaXN0ZW5lcik7XG4gICAgfVxuICB9O1xuICB2YXIgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZSA9IHtcbiAgICBTcGhlcmU6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIGxpc3RlbmVyLnNwaGVyZSgpO1xuICAgIH0sXG4gICAgUG9pbnQ6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIG9iamVjdCA9IG9iamVjdC5jb29yZGluYXRlcztcbiAgICAgIGxpc3RlbmVyLnBvaW50KG9iamVjdFswXSwgb2JqZWN0WzFdLCBvYmplY3RbMl0pO1xuICAgIH0sXG4gICAgTXVsdGlQb2ludDogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gb2JqZWN0LmNvb3JkaW5hdGVzLCBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgb2JqZWN0ID0gY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyLnBvaW50KG9iamVjdFswXSwgb2JqZWN0WzFdLCBvYmplY3RbMl0pO1xuICAgIH0sXG4gICAgTGluZVN0cmluZzogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgZDNfZ2VvX3N0cmVhbUxpbmUob2JqZWN0LmNvb3JkaW5hdGVzLCBsaXN0ZW5lciwgMCk7XG4gICAgfSxcbiAgICBNdWx0aUxpbmVTdHJpbmc6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBjb29yZGluYXRlcyA9IG9iamVjdC5jb29yZGluYXRlcywgaSA9IC0xLCBuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGQzX2dlb19zdHJlYW1MaW5lKGNvb3JkaW5hdGVzW2ldLCBsaXN0ZW5lciwgMCk7XG4gICAgfSxcbiAgICBQb2x5Z29uOiBmdW5jdGlvbihvYmplY3QsIGxpc3RlbmVyKSB7XG4gICAgICBkM19nZW9fc3RyZWFtUG9seWdvbihvYmplY3QuY29vcmRpbmF0ZXMsIGxpc3RlbmVyKTtcbiAgICB9LFxuICAgIE11bHRpUG9seWdvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gb2JqZWN0LmNvb3JkaW5hdGVzLCBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyKTtcbiAgICB9LFxuICAgIEdlb21ldHJ5Q29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGdlb21ldHJpZXMgPSBvYmplY3QuZ2VvbWV0cmllcywgaSA9IC0xLCBuID0gZ2VvbWV0cmllcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5KGdlb21ldHJpZXNbaV0sIGxpc3RlbmVyKTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19zdHJlYW1MaW5lKGNvb3JkaW5hdGVzLCBsaXN0ZW5lciwgY2xvc2VkKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aCAtIGNsb3NlZCwgY29vcmRpbmF0ZTtcbiAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICB3aGlsZSAoKytpIDwgbikgY29vcmRpbmF0ZSA9IGNvb3JkaW5hdGVzW2ldLCBsaXN0ZW5lci5wb2ludChjb29yZGluYXRlWzBdLCBjb29yZGluYXRlWzFdLCBjb29yZGluYXRlWzJdKTtcbiAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3N0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXMsIGxpc3RlbmVyKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICBsaXN0ZW5lci5wb2x5Z29uU3RhcnQoKTtcbiAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUxpbmUoY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyLCAxKTtcbiAgICBsaXN0ZW5lci5wb2x5Z29uRW5kKCk7XG4gIH1cbiAgZDMuZ2VvLmFyZWEgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBkM19nZW9fYXJlYVN1bSA9IDA7XG4gICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIGQzX2dlb19hcmVhKTtcbiAgICByZXR1cm4gZDNfZ2VvX2FyZWFTdW07XG4gIH07XG4gIHZhciBkM19nZW9fYXJlYVN1bSwgZDNfZ2VvX2FyZWFSaW5nU3VtID0gbmV3IGQzX2FkZGVyKCk7XG4gIHZhciBkM19nZW9fYXJlYSA9IHtcbiAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX2FyZWFTdW0gKz0gNCAqIM+AO1xuICAgIH0sXG4gICAgcG9pbnQ6IGQzX25vb3AsXG4gICAgbGluZVN0YXJ0OiBkM19ub29wLFxuICAgIGxpbmVFbmQ6IGQzX25vb3AsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19hcmVhUmluZ1N1bS5yZXNldCgpO1xuICAgICAgZDNfZ2VvX2FyZWEubGluZVN0YXJ0ID0gZDNfZ2VvX2FyZWFSaW5nU3RhcnQ7XG4gICAgfSxcbiAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmVhID0gMiAqIGQzX2dlb19hcmVhUmluZ1N1bTtcbiAgICAgIGQzX2dlb19hcmVhU3VtICs9IGFyZWEgPCAwID8gNCAqIM+AICsgYXJlYSA6IGFyZWE7XG4gICAgICBkM19nZW9fYXJlYS5saW5lU3RhcnQgPSBkM19nZW9fYXJlYS5saW5lRW5kID0gZDNfZ2VvX2FyZWEucG9pbnQgPSBkM19ub29wO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2FyZWFSaW5nU3RhcnQoKSB7XG4gICAgdmFyIM67MDAsIM+GMDAsIM67MCwgY29zz4YwLCBzaW7PhjA7XG4gICAgZDNfZ2VvX2FyZWEucG9pbnQgPSBmdW5jdGlvbijOuywgz4YpIHtcbiAgICAgIGQzX2dlb19hcmVhLnBvaW50ID0gbmV4dFBvaW50O1xuICAgICAgzrswID0gKM67MDAgPSDOuykgKiBkM19yYWRpYW5zLCBjb3PPhjAgPSBNYXRoLmNvcyjPhiA9ICjPhjAwID0gz4YpICogZDNfcmFkaWFucyAvIDIgKyDPgCAvIDQpLCBcbiAgICAgIHNpbs+GMCA9IE1hdGguc2luKM+GKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIG5leHRQb2ludCjOuywgz4YpIHtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICDPhiA9IM+GICogZDNfcmFkaWFucyAvIDIgKyDPgCAvIDQ7XG4gICAgICB2YXIgZM67ID0gzrsgLSDOuzAsIHNkzrsgPSBkzrsgPj0gMCA/IDEgOiAtMSwgYWTOuyA9IHNkzrsgKiBkzrssIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBzaW7PhiA9IE1hdGguc2luKM+GKSwgayA9IHNpbs+GMCAqIHNpbs+GLCB1ID0gY29zz4YwICogY29zz4YgKyBrICogTWF0aC5jb3MoYWTOuyksIHYgPSBrICogc2TOuyAqIE1hdGguc2luKGFkzrspO1xuICAgICAgZDNfZ2VvX2FyZWFSaW5nU3VtLmFkZChNYXRoLmF0YW4yKHYsIHUpKTtcbiAgICAgIM67MCA9IM67LCBjb3PPhjAgPSBjb3PPhiwgc2luz4YwID0gc2luz4Y7XG4gICAgfVxuICAgIGQzX2dlb19hcmVhLmxpbmVFbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIG5leHRQb2ludCjOuzAwLCDPhjAwKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW4oc3BoZXJpY2FsKSB7XG4gICAgdmFyIM67ID0gc3BoZXJpY2FsWzBdLCDPhiA9IHNwaGVyaWNhbFsxXSwgY29zz4YgPSBNYXRoLmNvcyjPhik7XG4gICAgcmV0dXJuIFsgY29zz4YgKiBNYXRoLmNvcyjOuyksIGNvc8+GICogTWF0aC5zaW4ozrspLCBNYXRoLnNpbijPhikgXTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2FydGVzaWFuRG90KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhhLCBiKSB7XG4gICAgcmV0dXJuIFsgYVsxXSAqIGJbMl0gLSBhWzJdICogYlsxXSwgYVsyXSAqIGJbMF0gLSBhWzBdICogYlsyXSwgYVswXSAqIGJbMV0gLSBhWzFdICogYlswXSBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5BZGQoYSwgYikge1xuICAgIGFbMF0gKz0gYlswXTtcbiAgICBhWzFdICs9IGJbMV07XG4gICAgYVsyXSArPSBiWzJdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5TY2FsZSh2ZWN0b3IsIGspIHtcbiAgICByZXR1cm4gWyB2ZWN0b3JbMF0gKiBrLCB2ZWN0b3JbMV0gKiBrLCB2ZWN0b3JbMl0gKiBrIF07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NhcnRlc2lhbk5vcm1hbGl6ZShkKSB7XG4gICAgdmFyIGwgPSBNYXRoLnNxcnQoZFswXSAqIGRbMF0gKyBkWzFdICogZFsxXSArIGRbMl0gKiBkWzJdKTtcbiAgICBkWzBdIC89IGw7XG4gICAgZFsxXSAvPSBsO1xuICAgIGRbMl0gLz0gbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fc3BoZXJpY2FsKGNhcnRlc2lhbikge1xuICAgIHJldHVybiBbIE1hdGguYXRhbjIoY2FydGVzaWFuWzFdLCBjYXJ0ZXNpYW5bMF0pLCBkM19hc2luKGNhcnRlc2lhblsyXSkgXTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fc3BoZXJpY2FsRXF1YWwoYSwgYikge1xuICAgIHJldHVybiBhYnMoYVswXSAtIGJbMF0pIDwgzrUgJiYgYWJzKGFbMV0gLSBiWzFdKSA8IM61O1xuICB9XG4gIGQzLmdlby5ib3VuZHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgzrswLCDPhjAsIM67MSwgz4YxLCDOu18sIM67X18sIM+GX18sIHAwLCBkzrtTdW0sIHJhbmdlcywgcmFuZ2U7XG4gICAgdmFyIGJvdW5kID0ge1xuICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgbGluZVN0YXJ0OiBsaW5lU3RhcnQsXG4gICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgYm91bmQucG9pbnQgPSByaW5nUG9pbnQ7XG4gICAgICAgIGJvdW5kLmxpbmVTdGFydCA9IHJpbmdTdGFydDtcbiAgICAgICAgYm91bmQubGluZUVuZCA9IHJpbmdFbmQ7XG4gICAgICAgIGTOu1N1bSA9IDA7XG4gICAgICAgIGQzX2dlb19hcmVhLnBvbHlnb25TdGFydCgpO1xuICAgICAgfSxcbiAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBkM19nZW9fYXJlYS5wb2x5Z29uRW5kKCk7XG4gICAgICAgIGJvdW5kLnBvaW50ID0gcG9pbnQ7XG4gICAgICAgIGJvdW5kLmxpbmVTdGFydCA9IGxpbmVTdGFydDtcbiAgICAgICAgYm91bmQubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgIGlmIChkM19nZW9fYXJlYVJpbmdTdW0gPCAwKSDOuzAgPSAtKM67MSA9IDE4MCksIM+GMCA9IC0oz4YxID0gOTApOyBlbHNlIGlmIChkzrtTdW0gPiDOtSkgz4YxID0gOTA7IGVsc2UgaWYgKGTOu1N1bSA8IC3OtSkgz4YwID0gLTkwO1xuICAgICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICB9XG4gICAgfTtcbiAgICBmdW5jdGlvbiBwb2ludCjOuywgz4YpIHtcbiAgICAgIHJhbmdlcy5wdXNoKHJhbmdlID0gWyDOuzAgPSDOuywgzrsxID0gzrsgXSk7XG4gICAgICBpZiAoz4YgPCDPhjApIM+GMCA9IM+GO1xuICAgICAgaWYgKM+GID4gz4YxKSDPhjEgPSDPhjtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZVBvaW50KM67LCDPhikge1xuICAgICAgdmFyIHAgPSBkM19nZW9fY2FydGVzaWFuKFsgzrsgKiBkM19yYWRpYW5zLCDPhiAqIGQzX3JhZGlhbnMgXSk7XG4gICAgICBpZiAocDApIHtcbiAgICAgICAgdmFyIG5vcm1hbCA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhwMCwgcCksIGVxdWF0b3JpYWwgPSBbIG5vcm1hbFsxXSwgLW5vcm1hbFswXSwgMCBdLCBpbmZsZWN0aW9uID0gZDNfZ2VvX2NhcnRlc2lhbkNyb3NzKGVxdWF0b3JpYWwsIG5vcm1hbCk7XG4gICAgICAgIGQzX2dlb19jYXJ0ZXNpYW5Ob3JtYWxpemUoaW5mbGVjdGlvbik7XG4gICAgICAgIGluZmxlY3Rpb24gPSBkM19nZW9fc3BoZXJpY2FsKGluZmxlY3Rpb24pO1xuICAgICAgICB2YXIgZM67ID0gzrsgLSDOu18sIHMgPSBkzrsgPiAwID8gMSA6IC0xLCDOu2kgPSBpbmZsZWN0aW9uWzBdICogZDNfZGVncmVlcyAqIHMsIGFudGltZXJpZGlhbiA9IGFicyhkzrspID4gMTgwO1xuICAgICAgICBpZiAoYW50aW1lcmlkaWFuIF4gKHMgKiDOu18gPCDOu2kgJiYgzrtpIDwgcyAqIM67KSkge1xuICAgICAgICAgIHZhciDPhmkgPSBpbmZsZWN0aW9uWzFdICogZDNfZGVncmVlcztcbiAgICAgICAgICBpZiAoz4ZpID4gz4YxKSDPhjEgPSDPhmk7XG4gICAgICAgIH0gZWxzZSBpZiAozrtpID0gKM67aSArIDM2MCkgJSAzNjAgLSAxODAsIGFudGltZXJpZGlhbiBeIChzICogzrtfIDwgzrtpICYmIM67aSA8IHMgKiDOuykpIHtcbiAgICAgICAgICB2YXIgz4ZpID0gLWluZmxlY3Rpb25bMV0gKiBkM19kZWdyZWVzO1xuICAgICAgICAgIGlmICjPhmkgPCDPhjApIM+GMCA9IM+GaTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoz4YgPCDPhjApIM+GMCA9IM+GO1xuICAgICAgICAgIGlmICjPhiA+IM+GMSkgz4YxID0gz4Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFudGltZXJpZGlhbikge1xuICAgICAgICAgIGlmICjOuyA8IM67Xykge1xuICAgICAgICAgICAgaWYgKGFuZ2xlKM67MCwgzrspID4gYW5nbGUozrswLCDOuzEpKSDOuzEgPSDOuztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGFuZ2xlKM67LCDOuzEpID4gYW5nbGUozrswLCDOuzEpKSDOuzAgPSDOuztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKM67MSA+PSDOuzApIHtcbiAgICAgICAgICAgIGlmICjOuyA8IM67MCkgzrswID0gzrs7XG4gICAgICAgICAgICBpZiAozrsgPiDOuzEpIM67MSA9IM67O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAozrsgPiDOu18pIHtcbiAgICAgICAgICAgICAgaWYgKGFuZ2xlKM67MCwgzrspID4gYW5nbGUozrswLCDOuzEpKSDOuzEgPSDOuztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChhbmdsZSjOuywgzrsxKSA+IGFuZ2xlKM67MCwgzrsxKSkgzrswID0gzrs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb2ludCjOuywgz4YpO1xuICAgICAgfVxuICAgICAgcDAgPSBwLCDOu18gPSDOuztcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgYm91bmQucG9pbnQgPSBsaW5lUG9pbnQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxpbmVFbmQoKSB7XG4gICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICBib3VuZC5wb2ludCA9IHBvaW50O1xuICAgICAgcDAgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiByaW5nUG9pbnQozrssIM+GKSB7XG4gICAgICBpZiAocDApIHtcbiAgICAgICAgdmFyIGTOuyA9IM67IC0gzrtfO1xuICAgICAgICBkzrtTdW0gKz0gYWJzKGTOuykgPiAxODAgPyBkzrsgKyAoZM67ID4gMCA/IDM2MCA6IC0zNjApIDogZM67O1xuICAgICAgfSBlbHNlIM67X18gPSDOuywgz4ZfXyA9IM+GO1xuICAgICAgZDNfZ2VvX2FyZWEucG9pbnQozrssIM+GKTtcbiAgICAgIGxpbmVQb2ludCjOuywgz4YpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByaW5nU3RhcnQoKSB7XG4gICAgICBkM19nZW9fYXJlYS5saW5lU3RhcnQoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmluZ0VuZCgpIHtcbiAgICAgIHJpbmdQb2ludCjOu19fLCDPhl9fKTtcbiAgICAgIGQzX2dlb19hcmVhLmxpbmVFbmQoKTtcbiAgICAgIGlmIChhYnMoZM67U3VtKSA+IM61KSDOuzAgPSAtKM67MSA9IDE4MCk7XG4gICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICBwMCA9IG51bGw7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFuZ2xlKM67MCwgzrsxKSB7XG4gICAgICByZXR1cm4gKM67MSAtPSDOuzApIDwgMCA/IM67MSArIDM2MCA6IM67MTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29tcGFyZVJhbmdlcyhhLCBiKSB7XG4gICAgICByZXR1cm4gYVswXSAtIGJbMF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHdpdGhpblJhbmdlKHgsIHJhbmdlKSB7XG4gICAgICByZXR1cm4gcmFuZ2VbMF0gPD0gcmFuZ2VbMV0gPyByYW5nZVswXSA8PSB4ICYmIHggPD0gcmFuZ2VbMV0gOiB4IDwgcmFuZ2VbMF0gfHwgcmFuZ2VbMV0gPCB4O1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgz4YxID0gzrsxID0gLSjOuzAgPSDPhjAgPSBJbmZpbml0eSk7XG4gICAgICByYW5nZXMgPSBbXTtcbiAgICAgIGQzLmdlby5zdHJlYW0oZmVhdHVyZSwgYm91bmQpO1xuICAgICAgdmFyIG4gPSByYW5nZXMubGVuZ3RoO1xuICAgICAgaWYgKG4pIHtcbiAgICAgICAgcmFuZ2VzLnNvcnQoY29tcGFyZVJhbmdlcyk7XG4gICAgICAgIGZvciAodmFyIGkgPSAxLCBhID0gcmFuZ2VzWzBdLCBiLCBtZXJnZWQgPSBbIGEgXTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGIgPSByYW5nZXNbaV07XG4gICAgICAgICAgaWYgKHdpdGhpblJhbmdlKGJbMF0sIGEpIHx8IHdpdGhpblJhbmdlKGJbMV0sIGEpKSB7XG4gICAgICAgICAgICBpZiAoYW5nbGUoYVswXSwgYlsxXSkgPiBhbmdsZShhWzBdLCBhWzFdKSkgYVsxXSA9IGJbMV07XG4gICAgICAgICAgICBpZiAoYW5nbGUoYlswXSwgYVsxXSkgPiBhbmdsZShhWzBdLCBhWzFdKSkgYVswXSA9IGJbMF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lcmdlZC5wdXNoKGEgPSBiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJlc3QgPSAtSW5maW5pdHksIGTOuztcbiAgICAgICAgZm9yICh2YXIgbiA9IG1lcmdlZC5sZW5ndGggLSAxLCBpID0gMCwgYSA9IG1lcmdlZFtuXSwgYjsgaSA8PSBuOyBhID0gYiwgKytpKSB7XG4gICAgICAgICAgYiA9IG1lcmdlZFtpXTtcbiAgICAgICAgICBpZiAoKGTOuyA9IGFuZ2xlKGFbMV0sIGJbMF0pKSA+IGJlc3QpIGJlc3QgPSBkzrssIM67MCA9IGJbMF0sIM67MSA9IGFbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJhbmdlcyA9IHJhbmdlID0gbnVsbDtcbiAgICAgIHJldHVybiDOuzAgPT09IEluZmluaXR5IHx8IM+GMCA9PT0gSW5maW5pdHkgPyBbIFsgTmFOLCBOYU4gXSwgWyBOYU4sIE5hTiBdIF0gOiBbIFsgzrswLCDPhjAgXSwgWyDOuzEsIM+GMSBdIF07XG4gICAgfTtcbiAgfSgpO1xuICBkMy5nZW8uY2VudHJvaWQgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBkM19nZW9fY2VudHJvaWRXMCA9IGQzX2dlb19jZW50cm9pZFcxID0gZDNfZ2VvX2NlbnRyb2lkWDAgPSBkM19nZW9fY2VudHJvaWRZMCA9IGQzX2dlb19jZW50cm9pZFowID0gZDNfZ2VvX2NlbnRyb2lkWDEgPSBkM19nZW9fY2VudHJvaWRZMSA9IGQzX2dlb19jZW50cm9pZFoxID0gZDNfZ2VvX2NlbnRyb2lkWDIgPSBkM19nZW9fY2VudHJvaWRZMiA9IGQzX2dlb19jZW50cm9pZFoyID0gMDtcbiAgICBkMy5nZW8uc3RyZWFtKG9iamVjdCwgZDNfZ2VvX2NlbnRyb2lkKTtcbiAgICB2YXIgeCA9IGQzX2dlb19jZW50cm9pZFgyLCB5ID0gZDNfZ2VvX2NlbnRyb2lkWTIsIHogPSBkM19nZW9fY2VudHJvaWRaMiwgbSA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcbiAgICBpZiAobSA8IM61Mikge1xuICAgICAgeCA9IGQzX2dlb19jZW50cm9pZFgxLCB5ID0gZDNfZ2VvX2NlbnRyb2lkWTEsIHogPSBkM19nZW9fY2VudHJvaWRaMTtcbiAgICAgIGlmIChkM19nZW9fY2VudHJvaWRXMSA8IM61KSB4ID0gZDNfZ2VvX2NlbnRyb2lkWDAsIHkgPSBkM19nZW9fY2VudHJvaWRZMCwgeiA9IGQzX2dlb19jZW50cm9pZFowO1xuICAgICAgbSA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcbiAgICAgIGlmIChtIDwgzrUyKSByZXR1cm4gWyBOYU4sIE5hTiBdO1xuICAgIH1cbiAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHksIHgpICogZDNfZGVncmVlcywgZDNfYXNpbih6IC8gTWF0aC5zcXJ0KG0pKSAqIGQzX2RlZ3JlZXMgXTtcbiAgfTtcbiAgdmFyIGQzX2dlb19jZW50cm9pZFcwLCBkM19nZW9fY2VudHJvaWRXMSwgZDNfZ2VvX2NlbnRyb2lkWDAsIGQzX2dlb19jZW50cm9pZFkwLCBkM19nZW9fY2VudHJvaWRaMCwgZDNfZ2VvX2NlbnRyb2lkWDEsIGQzX2dlb19jZW50cm9pZFkxLCBkM19nZW9fY2VudHJvaWRaMSwgZDNfZ2VvX2NlbnRyb2lkWDIsIGQzX2dlb19jZW50cm9pZFkyLCBkM19nZW9fY2VudHJvaWRaMjtcbiAgdmFyIGQzX2dlb19jZW50cm9pZCA9IHtcbiAgICBzcGhlcmU6IGQzX25vb3AsXG4gICAgcG9pbnQ6IGQzX2dlb19jZW50cm9pZFBvaW50LFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX2NlbnRyb2lkTGluZVN0YXJ0LFxuICAgIGxpbmVFbmQ6IGQzX2dlb19jZW50cm9pZExpbmVFbmQsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fY2VudHJvaWRSaW5nU3RhcnQ7XG4gICAgfSxcbiAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fY2VudHJvaWRMaW5lU3RhcnQ7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRQb2ludCjOuywgz4YpIHtcbiAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgIHZhciBjb3PPhiA9IE1hdGguY29zKM+GICo9IGQzX3JhZGlhbnMpO1xuICAgIGQzX2dlb19jZW50cm9pZFBvaW50WFlaKGNvc8+GICogTWF0aC5jb3MozrspLCBjb3PPhiAqIE1hdGguc2luKM67KSwgTWF0aC5zaW4oz4YpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4LCB5LCB6KSB7XG4gICAgKytkM19nZW9fY2VudHJvaWRXMDtcbiAgICBkM19nZW9fY2VudHJvaWRYMCArPSAoeCAtIGQzX2dlb19jZW50cm9pZFgwKSAvIGQzX2dlb19jZW50cm9pZFcwO1xuICAgIGQzX2dlb19jZW50cm9pZFkwICs9ICh5IC0gZDNfZ2VvX2NlbnRyb2lkWTApIC8gZDNfZ2VvX2NlbnRyb2lkVzA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkWjAgKz0gKHogLSBkM19nZW9fY2VudHJvaWRaMCkgLyBkM19nZW9fY2VudHJvaWRXMDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRMaW5lU3RhcnQoKSB7XG4gICAgdmFyIHgwLCB5MCwgejA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YgKj0gZDNfcmFkaWFucyk7XG4gICAgICB4MCA9IGNvc8+GICogTWF0aC5jb3MozrspO1xuICAgICAgeTAgPSBjb3PPhiAqIE1hdGguc2luKM67KTtcbiAgICAgIHowID0gTWF0aC5zaW4oz4YpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gbmV4dFBvaW50O1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkUG9pbnRYWVooeDAsIHkwLCB6MCk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQozrssIM+GKSB7XG4gICAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YgKj0gZDNfcmFkaWFucyksIHggPSBjb3PPhiAqIE1hdGguY29zKM67KSwgeSA9IGNvc8+GICogTWF0aC5zaW4ozrspLCB6ID0gTWF0aC5zaW4oz4YpLCB3ID0gTWF0aC5hdGFuMihNYXRoLnNxcnQoKHcgPSB5MCAqIHogLSB6MCAqIHkpICogdyArICh3ID0gejAgKiB4IC0geDAgKiB6KSAqIHcgKyAodyA9IHgwICogeSAtIHkwICogeCkgKiB3KSwgeDAgKiB4ICsgeTAgKiB5ICsgejAgKiB6KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFcxICs9IHc7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB3ICogKHgwICsgKHgwID0geCkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0gdyAqICh5MCArICh5MCA9IHkpKTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHcgKiAoejAgKyAoejAgPSB6KSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NlbnRyb2lkTGluZUVuZCgpIHtcbiAgICBkM19nZW9fY2VudHJvaWQucG9pbnQgPSBkM19nZW9fY2VudHJvaWRQb2ludDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRSaW5nU3RhcnQoKSB7XG4gICAgdmFyIM67MDAsIM+GMDAsIHgwLCB5MCwgejA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICDOuzAwID0gzrssIM+GMDAgPSDPhjtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICB2YXIgY29zz4YgPSBNYXRoLmNvcyjPhiAqPSBkM19yYWRpYW5zKTtcbiAgICAgIHgwID0gY29zz4YgKiBNYXRoLmNvcyjOuyk7XG4gICAgICB5MCA9IGNvc8+GICogTWF0aC5zaW4ozrspO1xuICAgICAgejAgPSBNYXRoLnNpbijPhik7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9O1xuICAgIGQzX2dlb19jZW50cm9pZC5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQozrswMCwgz4YwMCk7XG4gICAgICBkM19nZW9fY2VudHJvaWQubGluZUVuZCA9IGQzX2dlb19jZW50cm9pZExpbmVFbmQ7XG4gICAgICBkM19nZW9fY2VudHJvaWQucG9pbnQgPSBkM19nZW9fY2VudHJvaWRQb2ludDtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIG5leHRQb2ludCjOuywgz4YpIHtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICB2YXIgY29zz4YgPSBNYXRoLmNvcyjPhiAqPSBkM19yYWRpYW5zKSwgeCA9IGNvc8+GICogTWF0aC5jb3MozrspLCB5ID0gY29zz4YgKiBNYXRoLnNpbijOuyksIHogPSBNYXRoLnNpbijPhiksIGN4ID0geTAgKiB6IC0gejAgKiB5LCBjeSA9IHowICogeCAtIHgwICogeiwgY3ogPSB4MCAqIHkgLSB5MCAqIHgsIG0gPSBNYXRoLnNxcnQoY3ggKiBjeCArIGN5ICogY3kgKyBjeiAqIGN6KSwgdSA9IHgwICogeCArIHkwICogeSArIHowICogeiwgdiA9IG0gJiYgLWQzX2Fjb3ModSkgLyBtLCB3ID0gTWF0aC5hdGFuMihtLCB1KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFgyICs9IHYgKiBjeDtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkyICs9IHYgKiBjeTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoyICs9IHYgKiBjejtcbiAgICAgIGQzX2dlb19jZW50cm9pZFcxICs9IHc7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB3ICogKHgwICsgKHgwID0geCkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0gdyAqICh5MCArICh5MCA9IHkpKTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHcgKiAoejAgKyAoejAgPSB6KSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NvbXBvc2UoYSwgYikge1xuICAgIGZ1bmN0aW9uIGNvbXBvc2UoeCwgeSkge1xuICAgICAgcmV0dXJuIHggPSBhKHgsIHkpLCBiKHhbMF0sIHhbMV0pO1xuICAgIH1cbiAgICBpZiAoYS5pbnZlcnQgJiYgYi5pbnZlcnQpIGNvbXBvc2UuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgICAgcmV0dXJuIHggPSBiLmludmVydCh4LCB5KSwgeCAmJiBhLmludmVydCh4WzBdLCB4WzFdKTtcbiAgICB9O1xuICAgIHJldHVybiBjb21wb3NlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RydWUoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBQb2x5Z29uKHNlZ21lbnRzLCBjb21wYXJlLCBjbGlwU3RhcnRJbnNpZGUsIGludGVycG9sYXRlLCBsaXN0ZW5lcikge1xuICAgIHZhciBzdWJqZWN0ID0gW10sIGNsaXAgPSBbXTtcbiAgICBzZWdtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgIGlmICgobiA9IHNlZ21lbnQubGVuZ3RoIC0gMSkgPD0gMCkgcmV0dXJuO1xuICAgICAgdmFyIG4sIHAwID0gc2VnbWVudFswXSwgcDEgPSBzZWdtZW50W25dO1xuICAgICAgaWYgKGQzX2dlb19zcGhlcmljYWxFcXVhbChwMCwgcDEpKSB7XG4gICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgbGlzdGVuZXIucG9pbnQoKHAwID0gc2VnbWVudFtpXSlbMF0sIHAwWzFdKTtcbiAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgYSA9IG5ldyBkM19nZW9fY2xpcFBvbHlnb25JbnRlcnNlY3Rpb24ocDAsIHNlZ21lbnQsIG51bGwsIHRydWUpLCBiID0gbmV3IGQzX2dlb19jbGlwUG9seWdvbkludGVyc2VjdGlvbihwMCwgbnVsbCwgYSwgZmFsc2UpO1xuICAgICAgYS5vID0gYjtcbiAgICAgIHN1YmplY3QucHVzaChhKTtcbiAgICAgIGNsaXAucHVzaChiKTtcbiAgICAgIGEgPSBuZXcgZDNfZ2VvX2NsaXBQb2x5Z29uSW50ZXJzZWN0aW9uKHAxLCBzZWdtZW50LCBudWxsLCBmYWxzZSk7XG4gICAgICBiID0gbmV3IGQzX2dlb19jbGlwUG9seWdvbkludGVyc2VjdGlvbihwMSwgbnVsbCwgYSwgdHJ1ZSk7XG4gICAgICBhLm8gPSBiO1xuICAgICAgc3ViamVjdC5wdXNoKGEpO1xuICAgICAgY2xpcC5wdXNoKGIpO1xuICAgIH0pO1xuICAgIGNsaXAuc29ydChjb21wYXJlKTtcbiAgICBkM19nZW9fY2xpcFBvbHlnb25MaW5rQ2lyY3VsYXIoc3ViamVjdCk7XG4gICAgZDNfZ2VvX2NsaXBQb2x5Z29uTGlua0NpcmN1bGFyKGNsaXApO1xuICAgIGlmICghc3ViamVjdC5sZW5ndGgpIHJldHVybjtcbiAgICBmb3IgKHZhciBpID0gMCwgZW50cnkgPSBjbGlwU3RhcnRJbnNpZGUsIG4gPSBjbGlwLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgY2xpcFtpXS5lID0gZW50cnkgPSAhZW50cnk7XG4gICAgfVxuICAgIHZhciBzdGFydCA9IHN1YmplY3RbMF0sIHBvaW50cywgcG9pbnQ7XG4gICAgd2hpbGUgKDEpIHtcbiAgICAgIHZhciBjdXJyZW50ID0gc3RhcnQsIGlzU3ViamVjdCA9IHRydWU7XG4gICAgICB3aGlsZSAoY3VycmVudC52KSBpZiAoKGN1cnJlbnQgPSBjdXJyZW50Lm4pID09PSBzdGFydCkgcmV0dXJuO1xuICAgICAgcG9pbnRzID0gY3VycmVudC56O1xuICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICBkbyB7XG4gICAgICAgIGN1cnJlbnQudiA9IGN1cnJlbnQuby52ID0gdHJ1ZTtcbiAgICAgICAgaWYgKGN1cnJlbnQuZSkge1xuICAgICAgICAgIGlmIChpc1N1YmplY3QpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gcG9pbnRzLmxlbmd0aDsgaSA8IG47ICsraSkgbGlzdGVuZXIucG9pbnQoKHBvaW50ID0gcG9pbnRzW2ldKVswXSwgcG9pbnRbMV0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbnRlcnBvbGF0ZShjdXJyZW50LngsIGN1cnJlbnQubi54LCAxLCBsaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50Lm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGlzU3ViamVjdCkge1xuICAgICAgICAgICAgcG9pbnRzID0gY3VycmVudC5wLno7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gcG9pbnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSBsaXN0ZW5lci5wb2ludCgocG9pbnQgPSBwb2ludHNbaV0pWzBdLCBwb2ludFsxXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGludGVycG9sYXRlKGN1cnJlbnQueCwgY3VycmVudC5wLngsIC0xLCBsaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnA7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudCA9IGN1cnJlbnQubztcbiAgICAgICAgcG9pbnRzID0gY3VycmVudC56O1xuICAgICAgICBpc1N1YmplY3QgPSAhaXNTdWJqZWN0O1xuICAgICAgfSB3aGlsZSAoIWN1cnJlbnQudik7XG4gICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwUG9seWdvbkxpbmtDaXJjdWxhcihhcnJheSkge1xuICAgIGlmICghKG4gPSBhcnJheS5sZW5ndGgpKSByZXR1cm47XG4gICAgdmFyIG4sIGkgPSAwLCBhID0gYXJyYXlbMF0sIGI7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGEubiA9IGIgPSBhcnJheVtpXTtcbiAgICAgIGIucCA9IGE7XG4gICAgICBhID0gYjtcbiAgICB9XG4gICAgYS5uID0gYiA9IGFycmF5WzBdO1xuICAgIGIucCA9IGE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBQb2x5Z29uSW50ZXJzZWN0aW9uKHBvaW50LCBwb2ludHMsIG90aGVyLCBlbnRyeSkge1xuICAgIHRoaXMueCA9IHBvaW50O1xuICAgIHRoaXMueiA9IHBvaW50cztcbiAgICB0aGlzLm8gPSBvdGhlcjtcbiAgICB0aGlzLmUgPSBlbnRyeTtcbiAgICB0aGlzLnYgPSBmYWxzZTtcbiAgICB0aGlzLm4gPSB0aGlzLnAgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwKHBvaW50VmlzaWJsZSwgY2xpcExpbmUsIGludGVycG9sYXRlLCBjbGlwU3RhcnQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ocm90YXRlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGxpbmUgPSBjbGlwTGluZShsaXN0ZW5lciksIHJvdGF0ZWRDbGlwU3RhcnQgPSByb3RhdGUuaW52ZXJ0KGNsaXBTdGFydFswXSwgY2xpcFN0YXJ0WzFdKTtcbiAgICAgIHZhciBjbGlwID0ge1xuICAgICAgICBwb2ludDogcG9pbnQsXG4gICAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGNsaXAucG9pbnQgPSBwb2ludFJpbmc7XG4gICAgICAgICAgY2xpcC5saW5lU3RhcnQgPSByaW5nU3RhcnQ7XG4gICAgICAgICAgY2xpcC5saW5lRW5kID0gcmluZ0VuZDtcbiAgICAgICAgICBzZWdtZW50cyA9IFtdO1xuICAgICAgICAgIHBvbHlnb24gPSBbXTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICAgIGNsaXAubGluZVN0YXJ0ID0gbGluZVN0YXJ0O1xuICAgICAgICAgIGNsaXAubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgICAgc2VnbWVudHMgPSBkMy5tZXJnZShzZWdtZW50cyk7XG4gICAgICAgICAgdmFyIGNsaXBTdGFydEluc2lkZSA9IGQzX2dlb19wb2ludEluUG9seWdvbihyb3RhdGVkQ2xpcFN0YXJ0LCBwb2x5Z29uKTtcbiAgICAgICAgICBpZiAoc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIXBvbHlnb25TdGFydGVkKSBsaXN0ZW5lci5wb2x5Z29uU3RhcnQoKSwgcG9seWdvblN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgZDNfZ2VvX2NsaXBQb2x5Z29uKHNlZ21lbnRzLCBkM19nZW9fY2xpcFNvcnQsIGNsaXBTdGFydEluc2lkZSwgaW50ZXJwb2xhdGUsIGxpc3RlbmVyKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNsaXBTdGFydEluc2lkZSkge1xuICAgICAgICAgICAgaWYgKCFwb2x5Z29uU3RhcnRlZCkgbGlzdGVuZXIucG9seWdvblN0YXJ0KCksIHBvbHlnb25TdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgaW50ZXJwb2xhdGUobnVsbCwgbnVsbCwgMSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocG9seWdvblN0YXJ0ZWQpIGxpc3RlbmVyLnBvbHlnb25FbmQoKSwgcG9seWdvblN0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgICBzZWdtZW50cyA9IHBvbHlnb24gPSBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxpc3RlbmVyLnBvbHlnb25TdGFydCgpO1xuICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGludGVycG9sYXRlKG51bGwsIG51bGwsIDEsIGxpc3RlbmVyKTtcbiAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9seWdvbkVuZCgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZnVuY3Rpb24gcG9pbnQozrssIM+GKSB7XG4gICAgICAgIHZhciBwb2ludCA9IHJvdGF0ZSjOuywgz4YpO1xuICAgICAgICBpZiAocG9pbnRWaXNpYmxlKM67ID0gcG9pbnRbMF0sIM+GID0gcG9pbnRbMV0pKSBsaXN0ZW5lci5wb2ludCjOuywgz4YpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcG9pbnRMaW5lKM67LCDPhikge1xuICAgICAgICB2YXIgcG9pbnQgPSByb3RhdGUozrssIM+GKTtcbiAgICAgICAgbGluZS5wb2ludChwb2ludFswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgICBjbGlwLnBvaW50ID0gcG9pbnRMaW5lO1xuICAgICAgICBsaW5lLmxpbmVTdGFydCgpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICBsaW5lLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIHZhciBzZWdtZW50cztcbiAgICAgIHZhciBidWZmZXIgPSBkM19nZW9fY2xpcEJ1ZmZlckxpc3RlbmVyKCksIHJpbmdMaXN0ZW5lciA9IGNsaXBMaW5lKGJ1ZmZlciksIHBvbHlnb25TdGFydGVkID0gZmFsc2UsIHBvbHlnb24sIHJpbmc7XG4gICAgICBmdW5jdGlvbiBwb2ludFJpbmcozrssIM+GKSB7XG4gICAgICAgIHJpbmcucHVzaChbIM67LCDPhiBdKTtcbiAgICAgICAgdmFyIHBvaW50ID0gcm90YXRlKM67LCDPhik7XG4gICAgICAgIHJpbmdMaXN0ZW5lci5wb2ludChwb2ludFswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcmluZ1N0YXJ0KCkge1xuICAgICAgICByaW5nTGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgIHJpbmcgPSBbXTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdFbmQoKSB7XG4gICAgICAgIHBvaW50UmluZyhyaW5nWzBdWzBdLCByaW5nWzBdWzFdKTtcbiAgICAgICAgcmluZ0xpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgdmFyIGNsZWFuID0gcmluZ0xpc3RlbmVyLmNsZWFuKCksIHJpbmdTZWdtZW50cyA9IGJ1ZmZlci5idWZmZXIoKSwgc2VnbWVudCwgbiA9IHJpbmdTZWdtZW50cy5sZW5ndGg7XG4gICAgICAgIHJpbmcucG9wKCk7XG4gICAgICAgIHBvbHlnb24ucHVzaChyaW5nKTtcbiAgICAgICAgcmluZyA9IG51bGw7XG4gICAgICAgIGlmICghbikgcmV0dXJuO1xuICAgICAgICBpZiAoY2xlYW4gJiAxKSB7XG4gICAgICAgICAgc2VnbWVudCA9IHJpbmdTZWdtZW50c1swXTtcbiAgICAgICAgICB2YXIgbiA9IHNlZ21lbnQubGVuZ3RoIC0gMSwgaSA9IC0xLCBwb2ludDtcbiAgICAgICAgICBpZiAobiA+IDApIHtcbiAgICAgICAgICAgIGlmICghcG9seWdvblN0YXJ0ZWQpIGxpc3RlbmVyLnBvbHlnb25TdGFydCgpLCBwb2x5Z29uU3RhcnRlZCA9IHRydWU7XG4gICAgICAgICAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICAgIHdoaWxlICgrK2kgPCBuKSBsaXN0ZW5lci5wb2ludCgocG9pbnQgPSBzZWdtZW50W2ldKVswXSwgcG9pbnRbMV0pO1xuICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPiAxICYmIGNsZWFuICYgMikgcmluZ1NlZ21lbnRzLnB1c2gocmluZ1NlZ21lbnRzLnBvcCgpLmNvbmNhdChyaW5nU2VnbWVudHMuc2hpZnQoKSkpO1xuICAgICAgICBzZWdtZW50cy5wdXNoKHJpbmdTZWdtZW50cy5maWx0ZXIoZDNfZ2VvX2NsaXBTZWdtZW50TGVuZ3RoMSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsaXA7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2xpcFNlZ21lbnRMZW5ndGgxKHNlZ21lbnQpIHtcbiAgICByZXR1cm4gc2VnbWVudC5sZW5ndGggPiAxO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwQnVmZmVyTGlzdGVuZXIoKSB7XG4gICAgdmFyIGxpbmVzID0gW10sIGxpbmU7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGxpbmVzLnB1c2gobGluZSA9IFtdKTtcbiAgICAgIH0sXG4gICAgICBwb2ludDogZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICAgIGxpbmUucHVzaChbIM67LCDPhiBdKTtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBkM19ub29wLFxuICAgICAgYnVmZmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGJ1ZmZlciA9IGxpbmVzO1xuICAgICAgICBsaW5lcyA9IFtdO1xuICAgICAgICBsaW5lID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICAgIH0sXG4gICAgICByZWpvaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAobGluZXMubGVuZ3RoID4gMSkgbGluZXMucHVzaChsaW5lcy5wb3AoKS5jb25jYXQobGluZXMuc2hpZnQoKSkpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBTb3J0KGEsIGIpIHtcbiAgICByZXR1cm4gKChhID0gYS54KVswXSA8IDAgPyBhWzFdIC0gaGFsZs+AIC0gzrUgOiBoYWxmz4AgLSBhWzFdKSAtICgoYiA9IGIueClbMF0gPCAwID8gYlsxXSAtIGhhbGbPgCAtIM61IDogaGFsZs+AIC0gYlsxXSk7XG4gIH1cbiAgdmFyIGQzX2dlb19jbGlwQW50aW1lcmlkaWFuID0gZDNfZ2VvX2NsaXAoZDNfdHJ1ZSwgZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5MaW5lLCBkM19nZW9fY2xpcEFudGltZXJpZGlhbkludGVycG9sYXRlLCBbIC3PgCwgLc+AIC8gMiBdKTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5MaW5lKGxpc3RlbmVyKSB7XG4gICAgdmFyIM67MCA9IE5hTiwgz4YwID0gTmFOLCBzzrswID0gTmFOLCBjbGVhbjtcbiAgICByZXR1cm4ge1xuICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgIGNsZWFuID0gMTtcbiAgICAgIH0sXG4gICAgICBwb2ludDogZnVuY3Rpb24ozrsxLCDPhjEpIHtcbiAgICAgICAgdmFyIHPOuzEgPSDOuzEgPiAwID8gz4AgOiAtz4AsIGTOuyA9IGFicyjOuzEgLSDOuzApO1xuICAgICAgICBpZiAoYWJzKGTOuyAtIM+AKSA8IM61KSB7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQozrswLCDPhjAgPSAoz4YwICsgz4YxKSAvIDIgPiAwID8gaGFsZs+AIDogLWhhbGbPgCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQoc867MCwgz4YwKTtcbiAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQoc867MSwgz4YwKTtcbiAgICAgICAgICBsaXN0ZW5lci5wb2ludCjOuzEsIM+GMCk7XG4gICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKHPOuzAgIT09IHPOuzEgJiYgZM67ID49IM+AKSB7XG4gICAgICAgICAgaWYgKGFicyjOuzAgLSBzzrswKSA8IM61KSDOuzAgLT0gc867MCAqIM61O1xuICAgICAgICAgIGlmIChhYnMozrsxIC0gc867MSkgPCDOtSkgzrsxIC09IHPOuzEgKiDOtTtcbiAgICAgICAgICDPhjAgPSBkM19nZW9fY2xpcEFudGltZXJpZGlhbkludGVyc2VjdCjOuzAsIM+GMCwgzrsxLCDPhjEpO1xuICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHPOuzAsIM+GMCk7XG4gICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHPOuzEsIM+GMCk7XG4gICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGxpc3RlbmVyLnBvaW50KM67MCA9IM67MSwgz4YwID0gz4YxKTtcbiAgICAgICAgc867MCA9IHPOuzE7XG4gICAgICB9LFxuICAgICAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgzrswID0gz4YwID0gTmFOO1xuICAgICAgfSxcbiAgICAgIGNsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDIgLSBjbGVhbjtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwQW50aW1lcmlkaWFuSW50ZXJzZWN0KM67MCwgz4YwLCDOuzEsIM+GMSkge1xuICAgIHZhciBjb3PPhjAsIGNvc8+GMSwgc2luzrswX867MSA9IE1hdGguc2luKM67MCAtIM67MSk7XG4gICAgcmV0dXJuIGFicyhzaW7OuzBfzrsxKSA+IM61ID8gTWF0aC5hdGFuKChNYXRoLnNpbijPhjApICogKGNvc8+GMSA9IE1hdGguY29zKM+GMSkpICogTWF0aC5zaW4ozrsxKSAtIE1hdGguc2luKM+GMSkgKiAoY29zz4YwID0gTWF0aC5jb3Moz4YwKSkgKiBNYXRoLnNpbijOuzApKSAvIChjb3PPhjAgKiBjb3PPhjEgKiBzaW7OuzBfzrsxKSkgOiAoz4YwICsgz4YxKSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5JbnRlcnBvbGF0ZShmcm9tLCB0bywgZGlyZWN0aW9uLCBsaXN0ZW5lcikge1xuICAgIHZhciDPhjtcbiAgICBpZiAoZnJvbSA9PSBudWxsKSB7XG4gICAgICDPhiA9IGRpcmVjdGlvbiAqIGhhbGbPgDtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoMCwgz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoz4AsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KM+ALCAwKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KM+ALCAtz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoMCwgLc+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgLc+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgMCk7XG4gICAgICBsaXN0ZW5lci5wb2ludCgtz4AsIM+GKTtcbiAgICB9IGVsc2UgaWYgKGFicyhmcm9tWzBdIC0gdG9bMF0pID4gzrUpIHtcbiAgICAgIHZhciBzID0gZnJvbVswXSA8IHRvWzBdID8gz4AgOiAtz4A7XG4gICAgICDPhiA9IGRpcmVjdGlvbiAqIHMgLyAyO1xuICAgICAgbGlzdGVuZXIucG9pbnQoLXMsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KDAsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KHMsIM+GKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGlzdGVuZXIucG9pbnQodG9bMF0sIHRvWzFdKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3BvaW50SW5Qb2x5Z29uKHBvaW50LCBwb2x5Z29uKSB7XG4gICAgdmFyIG1lcmlkaWFuID0gcG9pbnRbMF0sIHBhcmFsbGVsID0gcG9pbnRbMV0sIG1lcmlkaWFuTm9ybWFsID0gWyBNYXRoLnNpbihtZXJpZGlhbiksIC1NYXRoLmNvcyhtZXJpZGlhbiksIDAgXSwgcG9sYXJBbmdsZSA9IDAsIHdpbmRpbmcgPSAwO1xuICAgIGQzX2dlb19hcmVhUmluZ1N1bS5yZXNldCgpO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gcG9seWdvbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciByaW5nID0gcG9seWdvbltpXSwgbSA9IHJpbmcubGVuZ3RoO1xuICAgICAgaWYgKCFtKSBjb250aW51ZTtcbiAgICAgIHZhciBwb2ludDAgPSByaW5nWzBdLCDOuzAgPSBwb2ludDBbMF0sIM+GMCA9IHBvaW50MFsxXSAvIDIgKyDPgCAvIDQsIHNpbs+GMCA9IE1hdGguc2luKM+GMCksIGNvc8+GMCA9IE1hdGguY29zKM+GMCksIGogPSAxO1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKGogPT09IG0pIGogPSAwO1xuICAgICAgICBwb2ludCA9IHJpbmdbal07XG4gICAgICAgIHZhciDOuyA9IHBvaW50WzBdLCDPhiA9IHBvaW50WzFdIC8gMiArIM+AIC8gNCwgc2luz4YgPSBNYXRoLnNpbijPhiksIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBkzrsgPSDOuyAtIM67MCwgc2TOuyA9IGTOuyA+PSAwID8gMSA6IC0xLCBhZM67ID0gc2TOuyAqIGTOuywgYW50aW1lcmlkaWFuID0gYWTOuyA+IM+ALCBrID0gc2luz4YwICogc2luz4Y7XG4gICAgICAgIGQzX2dlb19hcmVhUmluZ1N1bS5hZGQoTWF0aC5hdGFuMihrICogc2TOuyAqIE1hdGguc2luKGFkzrspLCBjb3PPhjAgKiBjb3PPhiArIGsgKiBNYXRoLmNvcyhhZM67KSkpO1xuICAgICAgICBwb2xhckFuZ2xlICs9IGFudGltZXJpZGlhbiA/IGTOuyArIHNkzrsgKiDPhCA6IGTOuztcbiAgICAgICAgaWYgKGFudGltZXJpZGlhbiBeIM67MCA+PSBtZXJpZGlhbiBeIM67ID49IG1lcmlkaWFuKSB7XG4gICAgICAgICAgdmFyIGFyYyA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhkM19nZW9fY2FydGVzaWFuKHBvaW50MCksIGQzX2dlb19jYXJ0ZXNpYW4ocG9pbnQpKTtcbiAgICAgICAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGFyYyk7XG4gICAgICAgICAgdmFyIGludGVyc2VjdGlvbiA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhtZXJpZGlhbk5vcm1hbCwgYXJjKTtcbiAgICAgICAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGludGVyc2VjdGlvbik7XG4gICAgICAgICAgdmFyIM+GYXJjID0gKGFudGltZXJpZGlhbiBeIGTOuyA+PSAwID8gLTEgOiAxKSAqIGQzX2FzaW4oaW50ZXJzZWN0aW9uWzJdKTtcbiAgICAgICAgICBpZiAocGFyYWxsZWwgPiDPhmFyYyB8fCBwYXJhbGxlbCA9PT0gz4ZhcmMgJiYgKGFyY1swXSB8fCBhcmNbMV0pKSB7XG4gICAgICAgICAgICB3aW5kaW5nICs9IGFudGltZXJpZGlhbiBeIGTOuyA+PSAwID8gMSA6IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWorKykgYnJlYWs7XG4gICAgICAgIM67MCA9IM67LCBzaW7PhjAgPSBzaW7PhiwgY29zz4YwID0gY29zz4YsIHBvaW50MCA9IHBvaW50O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gKHBvbGFyQW5nbGUgPCAtzrUgfHwgcG9sYXJBbmdsZSA8IM61ICYmIGQzX2dlb19hcmVhUmluZ1N1bSA8IC3OtSkgXiB3aW5kaW5nICYgMTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2xpcENpcmNsZShyYWRpdXMpIHtcbiAgICB2YXIgY3IgPSBNYXRoLmNvcyhyYWRpdXMpLCBzbWFsbFJhZGl1cyA9IGNyID4gMCwgbm90SGVtaXNwaGVyZSA9IGFicyhjcikgPiDOtSwgaW50ZXJwb2xhdGUgPSBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUocmFkaXVzLCA2ICogZDNfcmFkaWFucyk7XG4gICAgcmV0dXJuIGQzX2dlb19jbGlwKHZpc2libGUsIGNsaXBMaW5lLCBpbnRlcnBvbGF0ZSwgc21hbGxSYWRpdXMgPyBbIDAsIC1yYWRpdXMgXSA6IFsgLc+ALCByYWRpdXMgLSDPgCBdKTtcbiAgICBmdW5jdGlvbiB2aXNpYmxlKM67LCDPhikge1xuICAgICAgcmV0dXJuIE1hdGguY29zKM67KSAqIE1hdGguY29zKM+GKSA+IGNyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjbGlwTGluZShsaXN0ZW5lcikge1xuICAgICAgdmFyIHBvaW50MCwgYzAsIHYwLCB2MDAsIGNsZWFuO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2MDAgPSB2MCA9IGZhbHNlO1xuICAgICAgICAgIGNsZWFuID0gMTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9pbnQ6IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgICAgIHZhciBwb2ludDEgPSBbIM67LCDPhiBdLCBwb2ludDIsIHYgPSB2aXNpYmxlKM67LCDPhiksIGMgPSBzbWFsbFJhZGl1cyA/IHYgPyAwIDogY29kZSjOuywgz4YpIDogdiA/IGNvZGUozrsgKyAozrsgPCAwID8gz4AgOiAtz4ApLCDPhikgOiAwO1xuICAgICAgICAgIGlmICghcG9pbnQwICYmICh2MDAgPSB2MCA9IHYpKSBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICBpZiAodiAhPT0gdjApIHtcbiAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDAsIHBvaW50MSk7XG4gICAgICAgICAgICBpZiAoZDNfZ2VvX3NwaGVyaWNhbEVxdWFsKHBvaW50MCwgcG9pbnQyKSB8fCBkM19nZW9fc3BoZXJpY2FsRXF1YWwocG9pbnQxLCBwb2ludDIpKSB7XG4gICAgICAgICAgICAgIHBvaW50MVswXSArPSDOtTtcbiAgICAgICAgICAgICAgcG9pbnQxWzFdICs9IM61O1xuICAgICAgICAgICAgICB2ID0gdmlzaWJsZShwb2ludDFbMF0sIHBvaW50MVsxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh2ICE9PSB2MCkge1xuICAgICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICAgICAgaWYgKHYpIHtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDEsIHBvaW50MCk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHBvaW50MlswXSwgcG9pbnQyWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDAsIHBvaW50MSk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHBvaW50MlswXSwgcG9pbnQyWzFdKTtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnQwID0gcG9pbnQyO1xuICAgICAgICAgIH0gZWxzZSBpZiAobm90SGVtaXNwaGVyZSAmJiBwb2ludDAgJiYgc21hbGxSYWRpdXMgXiB2KSB7XG4gICAgICAgICAgICB2YXIgdDtcbiAgICAgICAgICAgIGlmICghKGMgJiBjMCkgJiYgKHQgPSBpbnRlcnNlY3QocG9pbnQxLCBwb2ludDAsIHRydWUpKSkge1xuICAgICAgICAgICAgICBjbGVhbiA9IDA7XG4gICAgICAgICAgICAgIGlmIChzbWFsbFJhZGl1cykge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHRbMF1bMF0sIHRbMF1bMV0pO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHRbMV1bMF0sIHRbMV1bMV0pO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lci5wb2ludCh0WzFdWzBdLCB0WzFdWzFdKTtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIucG9pbnQodFswXVswXSwgdFswXVsxXSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYgJiYgKCFwb2ludDAgfHwgIWQzX2dlb19zcGhlcmljYWxFcXVhbChwb2ludDAsIHBvaW50MSkpKSB7XG4gICAgICAgICAgICBsaXN0ZW5lci5wb2ludChwb2ludDFbMF0sIHBvaW50MVsxXSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBvaW50MCA9IHBvaW50MSwgdjAgPSB2LCBjMCA9IGM7XG4gICAgICAgIH0sXG4gICAgICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh2MCkgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIHBvaW50MCA9IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gY2xlYW4gfCAodjAwICYmIHYwKSA8PCAxO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnRlcnNlY3QoYSwgYiwgdHdvKSB7XG4gICAgICB2YXIgcGEgPSBkM19nZW9fY2FydGVzaWFuKGEpLCBwYiA9IGQzX2dlb19jYXJ0ZXNpYW4oYik7XG4gICAgICB2YXIgbjEgPSBbIDEsIDAsIDAgXSwgbjIgPSBkM19nZW9fY2FydGVzaWFuQ3Jvc3MocGEsIHBiKSwgbjJuMiA9IGQzX2dlb19jYXJ0ZXNpYW5Eb3QobjIsIG4yKSwgbjFuMiA9IG4yWzBdLCBkZXRlcm1pbmFudCA9IG4ybjIgLSBuMW4yICogbjFuMjtcbiAgICAgIGlmICghZGV0ZXJtaW5hbnQpIHJldHVybiAhdHdvICYmIGE7XG4gICAgICB2YXIgYzEgPSBjciAqIG4ybjIgLyBkZXRlcm1pbmFudCwgYzIgPSAtY3IgKiBuMW4yIC8gZGV0ZXJtaW5hbnQsIG4xeG4yID0gZDNfZ2VvX2NhcnRlc2lhbkNyb3NzKG4xLCBuMiksIEEgPSBkM19nZW9fY2FydGVzaWFuU2NhbGUobjEsIGMxKSwgQiA9IGQzX2dlb19jYXJ0ZXNpYW5TY2FsZShuMiwgYzIpO1xuICAgICAgZDNfZ2VvX2NhcnRlc2lhbkFkZChBLCBCKTtcbiAgICAgIHZhciB1ID0gbjF4bjIsIHcgPSBkM19nZW9fY2FydGVzaWFuRG90KEEsIHUpLCB1dSA9IGQzX2dlb19jYXJ0ZXNpYW5Eb3QodSwgdSksIHQyID0gdyAqIHcgLSB1dSAqIChkM19nZW9fY2FydGVzaWFuRG90KEEsIEEpIC0gMSk7XG4gICAgICBpZiAodDIgPCAwKSByZXR1cm47XG4gICAgICB2YXIgdCA9IE1hdGguc3FydCh0MiksIHEgPSBkM19nZW9fY2FydGVzaWFuU2NhbGUodSwgKC13IC0gdCkgLyB1dSk7XG4gICAgICBkM19nZW9fY2FydGVzaWFuQWRkKHEsIEEpO1xuICAgICAgcSA9IGQzX2dlb19zcGhlcmljYWwocSk7XG4gICAgICBpZiAoIXR3bykgcmV0dXJuIHE7XG4gICAgICB2YXIgzrswID0gYVswXSwgzrsxID0gYlswXSwgz4YwID0gYVsxXSwgz4YxID0gYlsxXSwgejtcbiAgICAgIGlmICjOuzEgPCDOuzApIHogPSDOuzAsIM67MCA9IM67MSwgzrsxID0gejtcbiAgICAgIHZhciDOtM67ID0gzrsxIC0gzrswLCBwb2xhciA9IGFicyjOtM67IC0gz4ApIDwgzrUsIG1lcmlkaWFuID0gcG9sYXIgfHwgzrTOuyA8IM61O1xuICAgICAgaWYgKCFwb2xhciAmJiDPhjEgPCDPhjApIHogPSDPhjAsIM+GMCA9IM+GMSwgz4YxID0gejtcbiAgICAgIGlmIChtZXJpZGlhbiA/IHBvbGFyID8gz4YwICsgz4YxID4gMCBeIHFbMV0gPCAoYWJzKHFbMF0gLSDOuzApIDwgzrUgPyDPhjAgOiDPhjEpIDogz4YwIDw9IHFbMV0gJiYgcVsxXSA8PSDPhjEgOiDOtM67ID4gz4AgXiAozrswIDw9IHFbMF0gJiYgcVswXSA8PSDOuzEpKSB7XG4gICAgICAgIHZhciBxMSA9IGQzX2dlb19jYXJ0ZXNpYW5TY2FsZSh1LCAoLXcgKyB0KSAvIHV1KTtcbiAgICAgICAgZDNfZ2VvX2NhcnRlc2lhbkFkZChxMSwgQSk7XG4gICAgICAgIHJldHVybiBbIHEsIGQzX2dlb19zcGhlcmljYWwocTEpIF07XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNvZGUozrssIM+GKSB7XG4gICAgICB2YXIgciA9IHNtYWxsUmFkaXVzID8gcmFkaXVzIDogz4AgLSByYWRpdXMsIGNvZGUgPSAwO1xuICAgICAgaWYgKM67IDwgLXIpIGNvZGUgfD0gMTsgZWxzZSBpZiAozrsgPiByKSBjb2RlIHw9IDI7XG4gICAgICBpZiAoz4YgPCAtcikgY29kZSB8PSA0OyBlbHNlIGlmICjPhiA+IHIpIGNvZGUgfD0gODtcbiAgICAgIHJldHVybiBjb2RlO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX2NsaXBMaW5lKHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHZhciBhID0gbGluZS5hLCBiID0gbGluZS5iLCBheCA9IGEueCwgYXkgPSBhLnksIGJ4ID0gYi54LCBieSA9IGIueSwgdDAgPSAwLCB0MSA9IDEsIGR4ID0gYnggLSBheCwgZHkgPSBieSAtIGF5LCByO1xuICAgICAgciA9IHgwIC0gYXg7XG4gICAgICBpZiAoIWR4ICYmIHIgPiAwKSByZXR1cm47XG4gICAgICByIC89IGR4O1xuICAgICAgaWYgKGR4IDwgMCkge1xuICAgICAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICAgICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICAgICAgfVxuICAgICAgciA9IHgxIC0gYXg7XG4gICAgICBpZiAoIWR4ICYmIHIgPCAwKSByZXR1cm47XG4gICAgICByIC89IGR4O1xuICAgICAgaWYgKGR4IDwgMCkge1xuICAgICAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICAgICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICAgICAgfVxuICAgICAgciA9IHkwIC0gYXk7XG4gICAgICBpZiAoIWR5ICYmIHIgPiAwKSByZXR1cm47XG4gICAgICByIC89IGR5O1xuICAgICAgaWYgKGR5IDwgMCkge1xuICAgICAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHkgPiAwKSB7XG4gICAgICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICAgICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICAgICAgfVxuICAgICAgciA9IHkxIC0gYXk7XG4gICAgICBpZiAoIWR5ICYmIHIgPCAwKSByZXR1cm47XG4gICAgICByIC89IGR5O1xuICAgICAgaWYgKGR5IDwgMCkge1xuICAgICAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHkgPiAwKSB7XG4gICAgICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICAgICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICAgICAgfVxuICAgICAgaWYgKHQwID4gMCkgbGluZS5hID0ge1xuICAgICAgICB4OiBheCArIHQwICogZHgsXG4gICAgICAgIHk6IGF5ICsgdDAgKiBkeVxuICAgICAgfTtcbiAgICAgIGlmICh0MSA8IDEpIGxpbmUuYiA9IHtcbiAgICAgICAgeDogYXggKyB0MSAqIGR4LFxuICAgICAgICB5OiBheSArIHQxICogZHlcbiAgICAgIH07XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICB9XG4gIHZhciBkM19nZW9fY2xpcEV4dGVudE1BWCA9IDFlOTtcbiAgZDMuZ2VvLmNsaXBFeHRlbnQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgeDAsIHkwLCB4MSwgeTEsIHN0cmVhbSwgY2xpcCwgY2xpcEV4dGVudCA9IHtcbiAgICAgIHN0cmVhbTogZnVuY3Rpb24ob3V0cHV0KSB7XG4gICAgICAgIGlmIChzdHJlYW0pIHN0cmVhbS52YWxpZCA9IGZhbHNlO1xuICAgICAgICBzdHJlYW0gPSBjbGlwKG91dHB1dCk7XG4gICAgICAgIHN0cmVhbS52YWxpZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgICB9LFxuICAgICAgZXh0ZW50OiBmdW5jdGlvbihfKSB7XG4gICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIFsgWyB4MCwgeTAgXSwgWyB4MSwgeTEgXSBdO1xuICAgICAgICBjbGlwID0gZDNfZ2VvX2NsaXBFeHRlbnQoeDAgPSArX1swXVswXSwgeTAgPSArX1swXVsxXSwgeDEgPSArX1sxXVswXSwgeTEgPSArX1sxXVsxXSk7XG4gICAgICAgIGlmIChzdHJlYW0pIHN0cmVhbS52YWxpZCA9IGZhbHNlLCBzdHJlYW0gPSBudWxsO1xuICAgICAgICByZXR1cm4gY2xpcEV4dGVudDtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBjbGlwRXh0ZW50LmV4dGVudChbIFsgMCwgMCBdLCBbIDk2MCwgNTAwIF0gXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwRXh0ZW50KHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdGVuZXJfID0gbGlzdGVuZXIsIGJ1ZmZlckxpc3RlbmVyID0gZDNfZ2VvX2NsaXBCdWZmZXJMaXN0ZW5lcigpLCBjbGlwTGluZSA9IGQzX2dlb21fY2xpcExpbmUoeDAsIHkwLCB4MSwgeTEpLCBzZWdtZW50cywgcG9seWdvbiwgcmluZztcbiAgICAgIHZhciBjbGlwID0ge1xuICAgICAgICBwb2ludDogcG9pbnQsXG4gICAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxpc3RlbmVyID0gYnVmZmVyTGlzdGVuZXI7XG4gICAgICAgICAgc2VnbWVudHMgPSBbXTtcbiAgICAgICAgICBwb2x5Z29uID0gW107XG4gICAgICAgICAgY2xlYW4gPSB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyXztcbiAgICAgICAgICBzZWdtZW50cyA9IGQzLm1lcmdlKHNlZ21lbnRzKTtcbiAgICAgICAgICB2YXIgY2xpcFN0YXJ0SW5zaWRlID0gaW5zaWRlUG9seWdvbihbIHgwLCB5MSBdKSwgaW5zaWRlID0gY2xlYW4gJiYgY2xpcFN0YXJ0SW5zaWRlLCB2aXNpYmxlID0gc2VnbWVudHMubGVuZ3RoO1xuICAgICAgICAgIGlmIChpbnNpZGUgfHwgdmlzaWJsZSkge1xuICAgICAgICAgICAgbGlzdGVuZXIucG9seWdvblN0YXJ0KCk7XG4gICAgICAgICAgICBpZiAoaW5zaWRlKSB7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICBpbnRlcnBvbGF0ZShudWxsLCBudWxsLCAxLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2aXNpYmxlKSB7XG4gICAgICAgICAgICAgIGQzX2dlb19jbGlwUG9seWdvbihzZWdtZW50cywgY29tcGFyZSwgY2xpcFN0YXJ0SW5zaWRlLCBpbnRlcnBvbGF0ZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGlzdGVuZXIucG9seWdvbkVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWdtZW50cyA9IHBvbHlnb24gPSByaW5nID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGZ1bmN0aW9uIGluc2lkZVBvbHlnb24ocCkge1xuICAgICAgICB2YXIgd24gPSAwLCBuID0gcG9seWdvbi5sZW5ndGgsIHkgPSBwWzFdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGZvciAodmFyIGogPSAxLCB2ID0gcG9seWdvbltpXSwgbSA9IHYubGVuZ3RoLCBhID0gdlswXSwgYjsgaiA8IG07ICsraikge1xuICAgICAgICAgICAgYiA9IHZbal07XG4gICAgICAgICAgICBpZiAoYVsxXSA8PSB5KSB7XG4gICAgICAgICAgICAgIGlmIChiWzFdID4geSAmJiBkM19jcm9zczJkKGEsIGIsIHApID4gMCkgKyt3bjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChiWzFdIDw9IHkgJiYgZDNfY3Jvc3MyZChhLCBiLCBwKSA8IDApIC0td247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhID0gYjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHduICE9PSAwO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gaW50ZXJwb2xhdGUoZnJvbSwgdG8sIGRpcmVjdGlvbiwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGEgPSAwLCBhMSA9IDA7XG4gICAgICAgIGlmIChmcm9tID09IG51bGwgfHwgKGEgPSBjb3JuZXIoZnJvbSwgZGlyZWN0aW9uKSkgIT09IChhMSA9IGNvcm5lcih0bywgZGlyZWN0aW9uKSkgfHwgY29tcGFyZVBvaW50cyhmcm9tLCB0bykgPCAwIF4gZGlyZWN0aW9uID4gMCkge1xuICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KGEgPT09IDAgfHwgYSA9PT0gMyA/IHgwIDogeDEsIGEgPiAxID8geTEgOiB5MCk7XG4gICAgICAgICAgfSB3aGlsZSAoKGEgPSAoYSArIGRpcmVjdGlvbiArIDQpICUgNCkgIT09IGExKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaXN0ZW5lci5wb2ludCh0b1swXSwgdG9bMV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBwb2ludFZpc2libGUoeCwgeSkge1xuICAgICAgICByZXR1cm4geDAgPD0geCAmJiB4IDw9IHgxICYmIHkwIDw9IHkgJiYgeSA8PSB5MTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgICAgaWYgKHBvaW50VmlzaWJsZSh4LCB5KSkgbGlzdGVuZXIucG9pbnQoeCwgeSk7XG4gICAgICB9XG4gICAgICB2YXIgeF9fLCB5X18sIHZfXywgeF8sIHlfLCB2XywgZmlyc3QsIGNsZWFuO1xuICAgICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgICBjbGlwLnBvaW50ID0gbGluZVBvaW50O1xuICAgICAgICBpZiAocG9seWdvbikgcG9seWdvbi5wdXNoKHJpbmcgPSBbXSk7XG4gICAgICAgIGZpcnN0ID0gdHJ1ZTtcbiAgICAgICAgdl8gPSBmYWxzZTtcbiAgICAgICAgeF8gPSB5XyA9IE5hTjtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVFbmQoKSB7XG4gICAgICAgIGlmIChzZWdtZW50cykge1xuICAgICAgICAgIGxpbmVQb2ludCh4X18sIHlfXyk7XG4gICAgICAgICAgaWYgKHZfXyAmJiB2XykgYnVmZmVyTGlzdGVuZXIucmVqb2luKCk7XG4gICAgICAgICAgc2VnbWVudHMucHVzaChidWZmZXJMaXN0ZW5lci5idWZmZXIoKSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICBpZiAodl8pIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVQb2ludCh4LCB5KSB7XG4gICAgICAgIHggPSBNYXRoLm1heCgtZDNfZ2VvX2NsaXBFeHRlbnRNQVgsIE1hdGgubWluKGQzX2dlb19jbGlwRXh0ZW50TUFYLCB4KSk7XG4gICAgICAgIHkgPSBNYXRoLm1heCgtZDNfZ2VvX2NsaXBFeHRlbnRNQVgsIE1hdGgubWluKGQzX2dlb19jbGlwRXh0ZW50TUFYLCB5KSk7XG4gICAgICAgIHZhciB2ID0gcG9pbnRWaXNpYmxlKHgsIHkpO1xuICAgICAgICBpZiAocG9seWdvbikgcmluZy5wdXNoKFsgeCwgeSBdKTtcbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgeF9fID0geCwgeV9fID0geSwgdl9fID0gdjtcbiAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuICAgICAgICAgIGlmICh2KSB7XG4gICAgICAgICAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHgsIHkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodiAmJiB2XykgbGlzdGVuZXIucG9pbnQoeCwgeSk7IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGwgPSB7XG4gICAgICAgICAgICAgIGE6IHtcbiAgICAgICAgICAgICAgICB4OiB4XyxcbiAgICAgICAgICAgICAgICB5OiB5X1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBiOiB7XG4gICAgICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgICAgICB5OiB5XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoY2xpcExpbmUobCkpIHtcbiAgICAgICAgICAgICAgaWYgKCF2Xykge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KGwuYS54LCBsLmEueSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGlzdGVuZXIucG9pbnQobC5iLngsIGwuYi55KTtcbiAgICAgICAgICAgICAgaWYgKCF2KSBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgICAgIGNsZWFuID0gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHYpIHtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHgsIHkpO1xuICAgICAgICAgICAgICBjbGVhbiA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB4XyA9IHgsIHlfID0geSwgdl8gPSB2O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsaXA7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBjb3JuZXIocCwgZGlyZWN0aW9uKSB7XG4gICAgICByZXR1cm4gYWJzKHBbMF0gLSB4MCkgPCDOtSA/IGRpcmVjdGlvbiA+IDAgPyAwIDogMyA6IGFicyhwWzBdIC0geDEpIDwgzrUgPyBkaXJlY3Rpb24gPiAwID8gMiA6IDEgOiBhYnMocFsxXSAtIHkwKSA8IM61ID8gZGlyZWN0aW9uID4gMCA/IDEgOiAwIDogZGlyZWN0aW9uID4gMCA/IDMgOiAyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb21wYXJlKGEsIGIpIHtcbiAgICAgIHJldHVybiBjb21wYXJlUG9pbnRzKGEueCwgYi54KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29tcGFyZVBvaW50cyhhLCBiKSB7XG4gICAgICB2YXIgY2EgPSBjb3JuZXIoYSwgMSksIGNiID0gY29ybmVyKGIsIDEpO1xuICAgICAgcmV0dXJuIGNhICE9PSBjYiA/IGNhIC0gY2IgOiBjYSA9PT0gMCA/IGJbMV0gLSBhWzFdIDogY2EgPT09IDEgPyBhWzBdIC0gYlswXSA6IGNhID09PSAyID8gYVsxXSAtIGJbMV0gOiBiWzBdIC0gYVswXTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NvbmljKHByb2plY3RBdCkge1xuICAgIHZhciDPhjAgPSAwLCDPhjEgPSDPgCAvIDMsIG0gPSBkM19nZW9fcHJvamVjdGlvbk11dGF0b3IocHJvamVjdEF0KSwgcCA9IG0oz4YwLCDPhjEpO1xuICAgIHAucGFyYWxsZWxzID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyDPhjAgLyDPgCAqIDE4MCwgz4YxIC8gz4AgKiAxODAgXTtcbiAgICAgIHJldHVybiBtKM+GMCA9IF9bMF0gKiDPgCAvIDE4MCwgz4YxID0gX1sxXSAqIM+AIC8gMTgwKTtcbiAgICB9O1xuICAgIHJldHVybiBwO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jb25pY0VxdWFsQXJlYSjPhjAsIM+GMSkge1xuICAgIHZhciBzaW7PhjAgPSBNYXRoLnNpbijPhjApLCBuID0gKHNpbs+GMCArIE1hdGguc2luKM+GMSkpIC8gMiwgQyA9IDEgKyBzaW7PhjAgKiAoMiAqIG4gLSBzaW7PhjApLCDPgTAgPSBNYXRoLnNxcnQoQykgLyBuO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICB2YXIgz4EgPSBNYXRoLnNxcnQoQyAtIDIgKiBuICogTWF0aC5zaW4oz4YpKSAvIG47XG4gICAgICByZXR1cm4gWyDPgSAqIE1hdGguc2luKM67ICo9IG4pLCDPgTAgLSDPgSAqIE1hdGguY29zKM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IM+BMCAtIHk7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHgsIM+BMF95KSAvIG4sIGQzX2FzaW4oKEMgLSAoeCAqIHggKyDPgTBfeSAqIM+BMF95KSAqIG4gKiBuKSAvICgyICogbikpIF07XG4gICAgfTtcbiAgICByZXR1cm4gZm9yd2FyZDtcbiAgfVxuICAoZDMuZ2VvLmNvbmljRXF1YWxBcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19jb25pYyhkM19nZW9fY29uaWNFcXVhbEFyZWEpO1xuICB9KS5yYXcgPSBkM19nZW9fY29uaWNFcXVhbEFyZWE7XG4gIGQzLmdlby5hbGJlcnMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgOTYsIDAgXSkuY2VudGVyKFsgLS42LCAzOC43IF0pLnBhcmFsbGVscyhbIDI5LjUsIDQ1LjUgXSkuc2NhbGUoMTA3MCk7XG4gIH07XG4gIGQzLmdlby5hbGJlcnNVc2EgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbG93ZXI0OCA9IGQzLmdlby5hbGJlcnMoKTtcbiAgICB2YXIgYWxhc2thID0gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgMTU0LCAwIF0pLmNlbnRlcihbIC0yLCA1OC41IF0pLnBhcmFsbGVscyhbIDU1LCA2NSBdKTtcbiAgICB2YXIgaGF3YWlpID0gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgMTU3LCAwIF0pLmNlbnRlcihbIC0zLCAxOS45IF0pLnBhcmFsbGVscyhbIDgsIDE4IF0pO1xuICAgIHZhciBwb2ludCwgcG9pbnRTdHJlYW0gPSB7XG4gICAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgICBwb2ludCA9IFsgeCwgeSBdO1xuICAgICAgfVxuICAgIH0sIGxvd2VyNDhQb2ludCwgYWxhc2thUG9pbnQsIGhhd2FpaVBvaW50O1xuICAgIGZ1bmN0aW9uIGFsYmVyc1VzYShjb29yZGluYXRlcykge1xuICAgICAgdmFyIHggPSBjb29yZGluYXRlc1swXSwgeSA9IGNvb3JkaW5hdGVzWzFdO1xuICAgICAgcG9pbnQgPSBudWxsO1xuICAgICAgKGxvd2VyNDhQb2ludCh4LCB5KSwgcG9pbnQpIHx8IChhbGFza2FQb2ludCh4LCB5KSwgcG9pbnQpIHx8IGhhd2FpaVBvaW50KHgsIHkpO1xuICAgICAgcmV0dXJuIHBvaW50O1xuICAgIH1cbiAgICBhbGJlcnNVc2EuaW52ZXJ0ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgIHZhciBrID0gbG93ZXI0OC5zY2FsZSgpLCB0ID0gbG93ZXI0OC50cmFuc2xhdGUoKSwgeCA9IChjb29yZGluYXRlc1swXSAtIHRbMF0pIC8gaywgeSA9IChjb29yZGluYXRlc1sxXSAtIHRbMV0pIC8gaztcbiAgICAgIHJldHVybiAoeSA+PSAuMTIgJiYgeSA8IC4yMzQgJiYgeCA+PSAtLjQyNSAmJiB4IDwgLS4yMTQgPyBhbGFza2EgOiB5ID49IC4xNjYgJiYgeSA8IC4yMzQgJiYgeCA+PSAtLjIxNCAmJiB4IDwgLS4xMTUgPyBoYXdhaWkgOiBsb3dlcjQ4KS5pbnZlcnQoY29vcmRpbmF0ZXMpO1xuICAgIH07XG4gICAgYWxiZXJzVXNhLnN0cmVhbSA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgdmFyIGxvd2VyNDhTdHJlYW0gPSBsb3dlcjQ4LnN0cmVhbShzdHJlYW0pLCBhbGFza2FTdHJlYW0gPSBhbGFza2Euc3RyZWFtKHN0cmVhbSksIGhhd2FpaVN0cmVhbSA9IGhhd2FpaS5zdHJlYW0oc3RyZWFtKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICAgICAgbG93ZXI0OFN0cmVhbS5wb2ludCh4LCB5KTtcbiAgICAgICAgICBhbGFza2FTdHJlYW0ucG9pbnQoeCwgeSk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLnBvaW50KHgsIHkpO1xuICAgICAgICB9LFxuICAgICAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0uc3BoZXJlKCk7XG4gICAgICAgICAgYWxhc2thU3RyZWFtLnNwaGVyZSgpO1xuICAgICAgICAgIGhhd2FpaVN0cmVhbS5zcGhlcmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsb3dlcjQ4U3RyZWFtLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5saW5lU3RhcnQoKTtcbiAgICAgICAgICBoYXdhaWlTdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5saW5lRW5kKCk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsb3dlcjQ4U3RyZWFtLnBvbHlnb25TdGFydCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5wb2x5Z29uU3RhcnQoKTtcbiAgICAgICAgICBoYXdhaWlTdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5wb2x5Z29uRW5kKCk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLnBvbHlnb25FbmQoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9O1xuICAgIGFsYmVyc1VzYS5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsb3dlcjQ4LnByZWNpc2lvbigpO1xuICAgICAgbG93ZXI0OC5wcmVjaXNpb24oXyk7XG4gICAgICBhbGFza2EucHJlY2lzaW9uKF8pO1xuICAgICAgaGF3YWlpLnByZWNpc2lvbihfKTtcbiAgICAgIHJldHVybiBhbGJlcnNVc2E7XG4gICAgfTtcbiAgICBhbGJlcnNVc2Euc2NhbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsb3dlcjQ4LnNjYWxlKCk7XG4gICAgICBsb3dlcjQ4LnNjYWxlKF8pO1xuICAgICAgYWxhc2thLnNjYWxlKF8gKiAuMzUpO1xuICAgICAgaGF3YWlpLnNjYWxlKF8pO1xuICAgICAgcmV0dXJuIGFsYmVyc1VzYS50cmFuc2xhdGUobG93ZXI0OC50cmFuc2xhdGUoKSk7XG4gICAgfTtcbiAgICBhbGJlcnNVc2EudHJhbnNsYXRlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbG93ZXI0OC50cmFuc2xhdGUoKTtcbiAgICAgIHZhciBrID0gbG93ZXI0OC5zY2FsZSgpLCB4ID0gK19bMF0sIHkgPSArX1sxXTtcbiAgICAgIGxvd2VyNDhQb2ludCA9IGxvd2VyNDgudHJhbnNsYXRlKF8pLmNsaXBFeHRlbnQoWyBbIHggLSAuNDU1ICogaywgeSAtIC4yMzggKiBrIF0sIFsgeCArIC40NTUgKiBrLCB5ICsgLjIzOCAqIGsgXSBdKS5zdHJlYW0ocG9pbnRTdHJlYW0pLnBvaW50O1xuICAgICAgYWxhc2thUG9pbnQgPSBhbGFza2EudHJhbnNsYXRlKFsgeCAtIC4zMDcgKiBrLCB5ICsgLjIwMSAqIGsgXSkuY2xpcEV4dGVudChbIFsgeCAtIC40MjUgKiBrICsgzrUsIHkgKyAuMTIgKiBrICsgzrUgXSwgWyB4IC0gLjIxNCAqIGsgLSDOtSwgeSArIC4yMzQgKiBrIC0gzrUgXSBdKS5zdHJlYW0ocG9pbnRTdHJlYW0pLnBvaW50O1xuICAgICAgaGF3YWlpUG9pbnQgPSBoYXdhaWkudHJhbnNsYXRlKFsgeCAtIC4yMDUgKiBrLCB5ICsgLjIxMiAqIGsgXSkuY2xpcEV4dGVudChbIFsgeCAtIC4yMTQgKiBrICsgzrUsIHkgKyAuMTY2ICogayArIM61IF0sIFsgeCAtIC4xMTUgKiBrIC0gzrUsIHkgKyAuMjM0ICogayAtIM61IF0gXSkuc3RyZWFtKHBvaW50U3RyZWFtKS5wb2ludDtcbiAgICAgIHJldHVybiBhbGJlcnNVc2E7XG4gICAgfTtcbiAgICByZXR1cm4gYWxiZXJzVXNhLnNjYWxlKDEwNzApO1xuICB9O1xuICB2YXIgZDNfZ2VvX3BhdGhBcmVhU3VtLCBkM19nZW9fcGF0aEFyZWFQb2x5Z29uLCBkM19nZW9fcGF0aEFyZWEgPSB7XG4gICAgcG9pbnQ6IGQzX25vb3AsXG4gICAgbGluZVN0YXJ0OiBkM19ub29wLFxuICAgIGxpbmVFbmQ6IGQzX25vb3AsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVBvbHlnb24gPSAwO1xuICAgICAgZDNfZ2VvX3BhdGhBcmVhLmxpbmVTdGFydCA9IGQzX2dlb19wYXRoQXJlYVJpbmdTdGFydDtcbiAgICB9LFxuICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX3BhdGhBcmVhLmxpbmVTdGFydCA9IGQzX2dlb19wYXRoQXJlYS5saW5lRW5kID0gZDNfZ2VvX3BhdGhBcmVhLnBvaW50ID0gZDNfbm9vcDtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVN1bSArPSBhYnMoZDNfZ2VvX3BhdGhBcmVhUG9seWdvbiAvIDIpO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhBcmVhUmluZ1N0YXJ0KCkge1xuICAgIHZhciB4MDAsIHkwMCwgeDAsIHkwO1xuICAgIGQzX2dlb19wYXRoQXJlYS5wb2ludCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYS5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIHgwMCA9IHgwID0geCwgeTAwID0geTAgPSB5O1xuICAgIH07XG4gICAgZnVuY3Rpb24gbmV4dFBvaW50KHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVBvbHlnb24gKz0geTAgKiB4IC0geDAgKiB5O1xuICAgICAgeDAgPSB4LCB5MCA9IHk7XG4gICAgfVxuICAgIGQzX2dlb19wYXRoQXJlYS5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQoeDAwLCB5MDApO1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX2dlb19wYXRoQm91bmRzWDAsIGQzX2dlb19wYXRoQm91bmRzWTAsIGQzX2dlb19wYXRoQm91bmRzWDEsIGQzX2dlb19wYXRoQm91bmRzWTE7XG4gIHZhciBkM19nZW9fcGF0aEJvdW5kcyA9IHtcbiAgICBwb2ludDogZDNfZ2VvX3BhdGhCb3VuZHNQb2ludCxcbiAgICBsaW5lU3RhcnQ6IGQzX25vb3AsXG4gICAgbGluZUVuZDogZDNfbm9vcCxcbiAgICBwb2x5Z29uU3RhcnQ6IGQzX25vb3AsXG4gICAgcG9seWdvbkVuZDogZDNfbm9vcFxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fcGF0aEJvdW5kc1BvaW50KHgsIHkpIHtcbiAgICBpZiAoeCA8IGQzX2dlb19wYXRoQm91bmRzWDApIGQzX2dlb19wYXRoQm91bmRzWDAgPSB4O1xuICAgIGlmICh4ID4gZDNfZ2VvX3BhdGhCb3VuZHNYMSkgZDNfZ2VvX3BhdGhCb3VuZHNYMSA9IHg7XG4gICAgaWYgKHkgPCBkM19nZW9fcGF0aEJvdW5kc1kwKSBkM19nZW9fcGF0aEJvdW5kc1kwID0geTtcbiAgICBpZiAoeSA+IGQzX2dlb19wYXRoQm91bmRzWTEpIGQzX2dlb19wYXRoQm91bmRzWTEgPSB5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQnVmZmVyKCkge1xuICAgIHZhciBwb2ludENpcmNsZSA9IGQzX2dlb19wYXRoQnVmZmVyQ2lyY2xlKDQuNSksIGJ1ZmZlciA9IFtdO1xuICAgIHZhciBzdHJlYW0gPSB7XG4gICAgICBwb2ludDogcG9pbnQsXG4gICAgICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ucG9pbnQgPSBwb2ludExpbmVTdGFydDtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQgPSBsaW5lRW5kUG9seWdvbjtcbiAgICAgIH0sXG4gICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQgPSBsaW5lRW5kO1xuICAgICAgICBzdHJlYW0ucG9pbnQgPSBwb2ludDtcbiAgICAgIH0sXG4gICAgICBwb2ludFJhZGl1czogZnVuY3Rpb24oXykge1xuICAgICAgICBwb2ludENpcmNsZSA9IGQzX2dlb19wYXRoQnVmZmVyQ2lyY2xlKF8pO1xuICAgICAgICByZXR1cm4gc3RyZWFtO1xuICAgICAgfSxcbiAgICAgIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmIChidWZmZXIubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGJ1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgIGJ1ZmZlci5wdXNoKFwiTVwiLCB4LCBcIixcIiwgeSwgcG9pbnRDaXJjbGUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmVTdGFydCh4LCB5KSB7XG4gICAgICBidWZmZXIucHVzaChcIk1cIiwgeCwgXCIsXCIsIHkpO1xuICAgICAgc3RyZWFtLnBvaW50ID0gcG9pbnRMaW5lO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmUoeCwgeSkge1xuICAgICAgYnVmZmVyLnB1c2goXCJMXCIsIHgsIFwiLFwiLCB5KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50O1xuICAgIH1cbiAgICBmdW5jdGlvbiBsaW5lRW5kUG9seWdvbigpIHtcbiAgICAgIGJ1ZmZlci5wdXNoKFwiWlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cmVhbTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcGF0aEJ1ZmZlckNpcmNsZShyYWRpdXMpIHtcbiAgICByZXR1cm4gXCJtMCxcIiArIHJhZGl1cyArIFwiYVwiICsgcmFkaXVzICsgXCIsXCIgKyByYWRpdXMgKyBcIiAwIDEsMSAwLFwiICsgLTIgKiByYWRpdXMgKyBcImFcIiArIHJhZGl1cyArIFwiLFwiICsgcmFkaXVzICsgXCIgMCAxLDEgMCxcIiArIDIgKiByYWRpdXMgKyBcInpcIjtcbiAgfVxuICB2YXIgZDNfZ2VvX3BhdGhDZW50cm9pZCA9IHtcbiAgICBwb2ludDogZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50LFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX3BhdGhDZW50cm9pZExpbmVTdGFydCxcbiAgICBsaW5lRW5kOiBkM19nZW9fcGF0aENlbnRyb2lkTGluZUVuZCxcbiAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fcGF0aENlbnRyb2lkUmluZ1N0YXJ0O1xuICAgIH0sXG4gICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50O1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fcGF0aENlbnRyb2lkTGluZVN0YXJ0O1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lRW5kID0gZDNfZ2VvX3BhdGhDZW50cm9pZExpbmVFbmQ7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeCwgeSkge1xuICAgIGQzX2dlb19jZW50cm9pZFgwICs9IHg7XG4gICAgZDNfZ2VvX2NlbnRyb2lkWTAgKz0geTtcbiAgICArK2QzX2dlb19jZW50cm9pZFowO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQ2VudHJvaWRMaW5lU3RhcnQoKSB7XG4gICAgdmFyIHgwLCB5MDtcbiAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIGQzX2dlb19wYXRoQ2VudHJvaWRQb2ludCh4MCA9IHgsIHkwID0geSk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQoeCwgeSkge1xuICAgICAgdmFyIGR4ID0geCAtIHgwLCBkeSA9IHkgLSB5MCwgeiA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB6ICogKHgwICsgeCkgLyAyO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0geiAqICh5MCArIHkpIC8gMjtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHo7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeDAgPSB4LCB5MCA9IHkpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcGF0aENlbnRyb2lkTGluZUVuZCgpIHtcbiAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQ2VudHJvaWRSaW5nU3RhcnQoKSB7XG4gICAgdmFyIHgwMCwgeTAwLCB4MCwgeTA7XG4gICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5wb2ludCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQ2VudHJvaWQucG9pbnQgPSBuZXh0UG9pbnQ7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeDAwID0geDAgPSB4LCB5MDAgPSB5MCA9IHkpO1xuICAgIH07XG4gICAgZnVuY3Rpb24gbmV4dFBvaW50KHgsIHkpIHtcbiAgICAgIHZhciBkeCA9IHggLSB4MCwgZHkgPSB5IC0geTAsIHogPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWDEgKz0geiAqICh4MCArIHgpIC8gMjtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkxICs9IHogKiAoeTAgKyB5KSAvIDI7XG4gICAgICBkM19nZW9fY2VudHJvaWRaMSArPSB6O1xuICAgICAgeiA9IHkwICogeCAtIHgwICogeTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFgyICs9IHogKiAoeDAgKyB4KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkyICs9IHogKiAoeTAgKyB5KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoyICs9IHogKiAzO1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50KHgwID0geCwgeTAgPSB5KTtcbiAgICB9XG4gICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQoeDAwLCB5MDApO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhDb250ZXh0KGNvbnRleHQpIHtcbiAgICB2YXIgcG9pbnRSYWRpdXMgPSA0LjU7XG4gICAgdmFyIHN0cmVhbSA9IHtcbiAgICAgIHBvaW50OiBwb2ludCxcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50TGluZVN0YXJ0O1xuICAgICAgfSxcbiAgICAgIGxpbmVFbmQ6IGxpbmVFbmQsXG4gICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ubGluZUVuZCA9IGxpbmVFbmRQb2x5Z29uO1xuICAgICAgfSxcbiAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50O1xuICAgICAgfSxcbiAgICAgIHBvaW50UmFkaXVzOiBmdW5jdGlvbihfKSB7XG4gICAgICAgIHBvaW50UmFkaXVzID0gXztcbiAgICAgICAgcmV0dXJuIHN0cmVhbTtcbiAgICAgIH0sXG4gICAgICByZXN1bHQ6IGQzX25vb3BcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgIGNvbnRleHQubW92ZVRvKHggKyBwb2ludFJhZGl1cywgeSk7XG4gICAgICBjb250ZXh0LmFyYyh4LCB5LCBwb2ludFJhZGl1cywgMCwgz4QpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmVTdGFydCh4LCB5KSB7XG4gICAgICBjb250ZXh0Lm1vdmVUbyh4LCB5KTtcbiAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50TGluZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcG9pbnRMaW5lKHgsIHkpIHtcbiAgICAgIGNvbnRleHQubGluZVRvKHgsIHkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBsaW5lRW5kKCkge1xuICAgICAgc3RyZWFtLnBvaW50ID0gcG9pbnQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxpbmVFbmRQb2x5Z29uKCkge1xuICAgICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cmVhbTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcmVzYW1wbGUocHJvamVjdCkge1xuICAgIHZhciDOtDIgPSAuNSwgY29zTWluRGlzdGFuY2UgPSBNYXRoLmNvcygzMCAqIGQzX3JhZGlhbnMpLCBtYXhEZXB0aCA9IDE2O1xuICAgIGZ1bmN0aW9uIHJlc2FtcGxlKHN0cmVhbSkge1xuICAgICAgcmV0dXJuIChtYXhEZXB0aCA/IHJlc2FtcGxlUmVjdXJzaXZlIDogcmVzYW1wbGVOb25lKShzdHJlYW0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNhbXBsZU5vbmUoc3RyZWFtKSB7XG4gICAgICByZXR1cm4gZDNfZ2VvX3RyYW5zZm9ybVBvaW50KHN0cmVhbSwgZnVuY3Rpb24oeCwgeSkge1xuICAgICAgICB4ID0gcHJvamVjdCh4LCB5KTtcbiAgICAgICAgc3RyZWFtLnBvaW50KHhbMF0sIHhbMV0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2FtcGxlUmVjdXJzaXZlKHN0cmVhbSkge1xuICAgICAgdmFyIM67MDAsIM+GMDAsIHgwMCwgeTAwLCBhMDAsIGIwMCwgYzAwLCDOuzAsIHgwLCB5MCwgYTAsIGIwLCBjMDtcbiAgICAgIHZhciByZXNhbXBsZSA9IHtcbiAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICBsaW5lU3RhcnQ6IGxpbmVTdGFydCxcbiAgICAgICAgbGluZUVuZDogbGluZUVuZCxcbiAgICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBzdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICAgICAgcmVzYW1wbGUubGluZVN0YXJ0ID0gcmluZ1N0YXJ0O1xuICAgICAgICB9LFxuICAgICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBzdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgICAgICAgIHJlc2FtcGxlLmxpbmVTdGFydCA9IGxpbmVTdGFydDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgICAgeCA9IHByb2plY3QoeCwgeSk7XG4gICAgICAgIHN0cmVhbS5wb2ludCh4WzBdLCB4WzFdKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVTdGFydCgpIHtcbiAgICAgICAgeDAgPSBOYU47XG4gICAgICAgIHJlc2FtcGxlLnBvaW50ID0gbGluZVBvaW50O1xuICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBsaW5lUG9pbnQozrssIM+GKSB7XG4gICAgICAgIHZhciBjID0gZDNfZ2VvX2NhcnRlc2lhbihbIM67LCDPhiBdKSwgcCA9IHByb2plY3QozrssIM+GKTtcbiAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDAsIHkwLCDOuzAsIGEwLCBiMCwgYzAsIHgwID0gcFswXSwgeTAgPSBwWzFdLCDOuzAgPSDOuywgYTAgPSBjWzBdLCBiMCA9IGNbMV0sIGMwID0gY1syXSwgbWF4RGVwdGgsIHN0cmVhbSk7XG4gICAgICAgIHN0cmVhbS5wb2ludCh4MCwgeTApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgICAgcmVzYW1wbGUucG9pbnQgPSBwb2ludDtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdTdGFydCgpIHtcbiAgICAgICAgbGluZVN0YXJ0KCk7XG4gICAgICAgIHJlc2FtcGxlLnBvaW50ID0gcmluZ1BvaW50O1xuICAgICAgICByZXNhbXBsZS5saW5lRW5kID0gcmluZ0VuZDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdQb2ludCjOuywgz4YpIHtcbiAgICAgICAgbGluZVBvaW50KM67MDAgPSDOuywgz4YwMCA9IM+GKSwgeDAwID0geDAsIHkwMCA9IHkwLCBhMDAgPSBhMCwgYjAwID0gYjAsIGMwMCA9IGMwO1xuICAgICAgICByZXNhbXBsZS5wb2ludCA9IGxpbmVQb2ludDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdFbmQoKSB7XG4gICAgICAgIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgzrswLCBhMCwgYjAsIGMwLCB4MDAsIHkwMCwgzrswMCwgYTAwLCBiMDAsIGMwMCwgbWF4RGVwdGgsIHN0cmVhbSk7XG4gICAgICAgIHJlc2FtcGxlLmxpbmVFbmQgPSBsaW5lRW5kO1xuICAgICAgICBsaW5lRW5kKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzYW1wbGU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgzrswLCBhMCwgYjAsIGMwLCB4MSwgeTEsIM67MSwgYTEsIGIxLCBjMSwgZGVwdGgsIHN0cmVhbSkge1xuICAgICAgdmFyIGR4ID0geDEgLSB4MCwgZHkgPSB5MSAtIHkwLCBkMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgaWYgKGQyID4gNCAqIM60MiAmJiBkZXB0aC0tKSB7XG4gICAgICAgIHZhciBhID0gYTAgKyBhMSwgYiA9IGIwICsgYjEsIGMgPSBjMCArIGMxLCBtID0gTWF0aC5zcXJ0KGEgKiBhICsgYiAqIGIgKyBjICogYyksIM+GMiA9IE1hdGguYXNpbihjIC89IG0pLCDOuzIgPSBhYnMoYWJzKGMpIC0gMSkgPCDOtSB8fCBhYnMozrswIC0gzrsxKSA8IM61ID8gKM67MCArIM67MSkgLyAyIDogTWF0aC5hdGFuMihiLCBhKSwgcCA9IHByb2plY3QozrsyLCDPhjIpLCB4MiA9IHBbMF0sIHkyID0gcFsxXSwgZHgyID0geDIgLSB4MCwgZHkyID0geTIgLSB5MCwgZHogPSBkeSAqIGR4MiAtIGR4ICogZHkyO1xuICAgICAgICBpZiAoZHogKiBkeiAvIGQyID4gzrQyIHx8IGFicygoZHggKiBkeDIgKyBkeSAqIGR5MikgLyBkMiAtIC41KSA+IC4zIHx8IGEwICogYTEgKyBiMCAqIGIxICsgYzAgKiBjMSA8IGNvc01pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDAsIHkwLCDOuzAsIGEwLCBiMCwgYzAsIHgyLCB5MiwgzrsyLCBhIC89IG0sIGIgLz0gbSwgYywgZGVwdGgsIHN0cmVhbSk7XG4gICAgICAgICAgc3RyZWFtLnBvaW50KHgyLCB5Mik7XG4gICAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDIsIHkyLCDOuzIsIGEsIGIsIGMsIHgxLCB5MSwgzrsxLCBhMSwgYjEsIGMxLCBkZXB0aCwgc3RyZWFtKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXNhbXBsZS5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBNYXRoLnNxcnQozrQyKTtcbiAgICAgIG1heERlcHRoID0gKM60MiA9IF8gKiBfKSA+IDAgJiYgMTY7XG4gICAgICByZXR1cm4gcmVzYW1wbGU7XG4gICAgfTtcbiAgICByZXR1cm4gcmVzYW1wbGU7XG4gIH1cbiAgZDMuZ2VvLnBhdGggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcG9pbnRSYWRpdXMgPSA0LjUsIHByb2plY3Rpb24sIGNvbnRleHQsIHByb2plY3RTdHJlYW0sIGNvbnRleHRTdHJlYW0sIGNhY2hlU3RyZWFtO1xuICAgIGZ1bmN0aW9uIHBhdGgob2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcG9pbnRSYWRpdXMgPT09IFwiZnVuY3Rpb25cIikgY29udGV4dFN0cmVhbS5wb2ludFJhZGl1cygrcG9pbnRSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgICAgIGlmICghY2FjaGVTdHJlYW0gfHwgIWNhY2hlU3RyZWFtLnZhbGlkKSBjYWNoZVN0cmVhbSA9IHByb2plY3RTdHJlYW0oY29udGV4dFN0cmVhbSk7XG4gICAgICAgIGQzLmdlby5zdHJlYW0ob2JqZWN0LCBjYWNoZVN0cmVhbSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29udGV4dFN0cmVhbS5yZXN1bHQoKTtcbiAgICB9XG4gICAgcGF0aC5hcmVhID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICBkM19nZW9fcGF0aEFyZWFTdW0gPSAwO1xuICAgICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIHByb2plY3RTdHJlYW0oZDNfZ2VvX3BhdGhBcmVhKSk7XG4gICAgICByZXR1cm4gZDNfZ2VvX3BhdGhBcmVhU3VtO1xuICAgIH07XG4gICAgcGF0aC5jZW50cm9pZCA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWDAgPSBkM19nZW9fY2VudHJvaWRZMCA9IGQzX2dlb19jZW50cm9pZFowID0gZDNfZ2VvX2NlbnRyb2lkWDEgPSBkM19nZW9fY2VudHJvaWRZMSA9IGQzX2dlb19jZW50cm9pZFoxID0gZDNfZ2VvX2NlbnRyb2lkWDIgPSBkM19nZW9fY2VudHJvaWRZMiA9IGQzX2dlb19jZW50cm9pZFoyID0gMDtcbiAgICAgIGQzLmdlby5zdHJlYW0ob2JqZWN0LCBwcm9qZWN0U3RyZWFtKGQzX2dlb19wYXRoQ2VudHJvaWQpKTtcbiAgICAgIHJldHVybiBkM19nZW9fY2VudHJvaWRaMiA/IFsgZDNfZ2VvX2NlbnRyb2lkWDIgLyBkM19nZW9fY2VudHJvaWRaMiwgZDNfZ2VvX2NlbnRyb2lkWTIgLyBkM19nZW9fY2VudHJvaWRaMiBdIDogZDNfZ2VvX2NlbnRyb2lkWjEgPyBbIGQzX2dlb19jZW50cm9pZFgxIC8gZDNfZ2VvX2NlbnRyb2lkWjEsIGQzX2dlb19jZW50cm9pZFkxIC8gZDNfZ2VvX2NlbnRyb2lkWjEgXSA6IGQzX2dlb19jZW50cm9pZFowID8gWyBkM19nZW9fY2VudHJvaWRYMCAvIGQzX2dlb19jZW50cm9pZFowLCBkM19nZW9fY2VudHJvaWRZMCAvIGQzX2dlb19jZW50cm9pZFowIF0gOiBbIE5hTiwgTmFOIF07XG4gICAgfTtcbiAgICBwYXRoLmJvdW5kcyA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgZDNfZ2VvX3BhdGhCb3VuZHNYMSA9IGQzX2dlb19wYXRoQm91bmRzWTEgPSAtKGQzX2dlb19wYXRoQm91bmRzWDAgPSBkM19nZW9fcGF0aEJvdW5kc1kwID0gSW5maW5pdHkpO1xuICAgICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIHByb2plY3RTdHJlYW0oZDNfZ2VvX3BhdGhCb3VuZHMpKTtcbiAgICAgIHJldHVybiBbIFsgZDNfZ2VvX3BhdGhCb3VuZHNYMCwgZDNfZ2VvX3BhdGhCb3VuZHNZMCBdLCBbIGQzX2dlb19wYXRoQm91bmRzWDEsIGQzX2dlb19wYXRoQm91bmRzWTEgXSBdO1xuICAgIH07XG4gICAgcGF0aC5wcm9qZWN0aW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcHJvamVjdGlvbjtcbiAgICAgIHByb2plY3RTdHJlYW0gPSAocHJvamVjdGlvbiA9IF8pID8gXy5zdHJlYW0gfHwgZDNfZ2VvX3BhdGhQcm9qZWN0U3RyZWFtKF8pIDogZDNfaWRlbnRpdHk7XG4gICAgICByZXR1cm4gcmVzZXQoKTtcbiAgICB9O1xuICAgIHBhdGguY29udGV4dCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGNvbnRleHQ7XG4gICAgICBjb250ZXh0U3RyZWFtID0gKGNvbnRleHQgPSBfKSA9PSBudWxsID8gbmV3IGQzX2dlb19wYXRoQnVmZmVyKCkgOiBuZXcgZDNfZ2VvX3BhdGhDb250ZXh0KF8pO1xuICAgICAgaWYgKHR5cGVvZiBwb2ludFJhZGl1cyAhPT0gXCJmdW5jdGlvblwiKSBjb250ZXh0U3RyZWFtLnBvaW50UmFkaXVzKHBvaW50UmFkaXVzKTtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcGF0aC5wb2ludFJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBvaW50UmFkaXVzO1xuICAgICAgcG9pbnRSYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IChjb250ZXh0U3RyZWFtLnBvaW50UmFkaXVzKCtfKSwgK18pO1xuICAgICAgcmV0dXJuIHBhdGg7XG4gICAgfTtcbiAgICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgIGNhY2hlU3RyZWFtID0gbnVsbDtcbiAgICAgIHJldHVybiBwYXRoO1xuICAgIH1cbiAgICByZXR1cm4gcGF0aC5wcm9qZWN0aW9uKGQzLmdlby5hbGJlcnNVc2EoKSkuY29udGV4dChudWxsKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhQcm9qZWN0U3RyZWFtKHByb2plY3QpIHtcbiAgICB2YXIgcmVzYW1wbGUgPSBkM19nZW9fcmVzYW1wbGUoZnVuY3Rpb24oeCwgeSkge1xuICAgICAgcmV0dXJuIHByb2plY3QoWyB4ICogZDNfZGVncmVlcywgeSAqIGQzX2RlZ3JlZXMgXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uUmFkaWFucyhyZXNhbXBsZShzdHJlYW0pKTtcbiAgICB9O1xuICB9XG4gIGQzLmdlby50cmFuc2Zvcm0gPSBmdW5jdGlvbihtZXRob2RzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0cmVhbTogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBuZXcgZDNfZ2VvX3RyYW5zZm9ybShzdHJlYW0pO1xuICAgICAgICBmb3IgKHZhciBrIGluIG1ldGhvZHMpIHRyYW5zZm9ybVtrXSA9IG1ldGhvZHNba107XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm07XG4gICAgICB9XG4gICAgfTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zZm9ybShzdHJlYW0pIHtcbiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgfVxuICBkM19nZW9fdHJhbnNmb3JtLnByb3RvdHlwZSA9IHtcbiAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgdGhpcy5zdHJlYW0ucG9pbnQoeCwgeSk7XG4gICAgfSxcbiAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0uc3BoZXJlKCk7XG4gICAgfSxcbiAgICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgfSxcbiAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuc3RyZWFtLmxpbmVFbmQoKTtcbiAgICB9LFxuICAgIHBvbHlnb25TdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLnN0cmVhbS5wb2x5Z29uU3RhcnQoKTtcbiAgICB9LFxuICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zZm9ybVBvaW50KHN0cmVhbSwgcG9pbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgc3BoZXJlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLnNwaGVyZSgpO1xuICAgICAgfSxcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5saW5lU3RhcnQoKTtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgIH0sXG4gICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICB9LFxuICAgICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5wb2x5Z29uRW5kKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkMy5nZW8ucHJvamVjdGlvbiA9IGQzX2dlb19wcm9qZWN0aW9uO1xuICBkMy5nZW8ucHJvamVjdGlvbk11dGF0b3IgPSBkM19nZW9fcHJvamVjdGlvbk11dGF0b3I7XG4gIGZ1bmN0aW9uIGQzX2dlb19wcm9qZWN0aW9uKHByb2plY3QpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb25NdXRhdG9yKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHByb2plY3Q7XG4gICAgfSkoKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdGlvbk11dGF0b3IocHJvamVjdEF0KSB7XG4gICAgdmFyIHByb2plY3QsIHJvdGF0ZSwgcHJvamVjdFJvdGF0ZSwgcHJvamVjdFJlc2FtcGxlID0gZDNfZ2VvX3Jlc2FtcGxlKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHggPSBwcm9qZWN0KHgsIHkpO1xuICAgICAgcmV0dXJuIFsgeFswXSAqIGsgKyDOtHgsIM60eSAtIHhbMV0gKiBrIF07XG4gICAgfSksIGsgPSAxNTAsIHggPSA0ODAsIHkgPSAyNTAsIM67ID0gMCwgz4YgPSAwLCDOtM67ID0gMCwgzrTPhiA9IDAsIM60zrMgPSAwLCDOtHgsIM60eSwgcHJlY2xpcCA9IGQzX2dlb19jbGlwQW50aW1lcmlkaWFuLCBwb3N0Y2xpcCA9IGQzX2lkZW50aXR5LCBjbGlwQW5nbGUgPSBudWxsLCBjbGlwRXh0ZW50ID0gbnVsbCwgc3RyZWFtO1xuICAgIGZ1bmN0aW9uIHByb2plY3Rpb24ocG9pbnQpIHtcbiAgICAgIHBvaW50ID0gcHJvamVjdFJvdGF0ZShwb2ludFswXSAqIGQzX3JhZGlhbnMsIHBvaW50WzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gWyBwb2ludFswXSAqIGsgKyDOtHgsIM60eSAtIHBvaW50WzFdICogayBdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnZlcnQocG9pbnQpIHtcbiAgICAgIHBvaW50ID0gcHJvamVjdFJvdGF0ZS5pbnZlcnQoKHBvaW50WzBdIC0gzrR4KSAvIGssICjOtHkgLSBwb2ludFsxXSkgLyBrKTtcbiAgICAgIHJldHVybiBwb2ludCAmJiBbIHBvaW50WzBdICogZDNfZGVncmVlcywgcG9pbnRbMV0gKiBkM19kZWdyZWVzIF07XG4gICAgfVxuICAgIHByb2plY3Rpb24uc3RyZWFtID0gZnVuY3Rpb24ob3V0cHV0KSB7XG4gICAgICBpZiAoc3RyZWFtKSBzdHJlYW0udmFsaWQgPSBmYWxzZTtcbiAgICAgIHN0cmVhbSA9IGQzX2dlb19wcm9qZWN0aW9uUmFkaWFucyhwcmVjbGlwKHJvdGF0ZSwgcHJvamVjdFJlc2FtcGxlKHBvc3RjbGlwKG91dHB1dCkpKSk7XG4gICAgICBzdHJlYW0udmFsaWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHN0cmVhbTtcbiAgICB9O1xuICAgIHByb2plY3Rpb24uY2xpcEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEFuZ2xlO1xuICAgICAgcHJlY2xpcCA9IF8gPT0gbnVsbCA/IChjbGlwQW5nbGUgPSBfLCBkM19nZW9fY2xpcEFudGltZXJpZGlhbikgOiBkM19nZW9fY2xpcENpcmNsZSgoY2xpcEFuZ2xlID0gK18pICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gaW52YWxpZGF0ZSgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEV4dGVudDtcbiAgICAgIGNsaXBFeHRlbnQgPSBfO1xuICAgICAgcG9zdGNsaXAgPSBfID8gZDNfZ2VvX2NsaXBFeHRlbnQoX1swXVswXSwgX1swXVsxXSwgX1sxXVswXSwgX1sxXVsxXSkgOiBkM19pZGVudGl0eTtcbiAgICAgIHJldHVybiBpbnZhbGlkYXRlKCk7XG4gICAgfTtcbiAgICBwcm9qZWN0aW9uLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gaztcbiAgICAgIGsgPSArXztcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi50cmFuc2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHgsIHkgXTtcbiAgICAgIHggPSArX1swXTtcbiAgICAgIHkgPSArX1sxXTtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIM67ICogZDNfZGVncmVlcywgz4YgKiBkM19kZWdyZWVzIF07XG4gICAgICDOuyA9IF9bMF0gJSAzNjAgKiBkM19yYWRpYW5zO1xuICAgICAgz4YgPSBfWzFdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5yb3RhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIM60zrsgKiBkM19kZWdyZWVzLCDOtM+GICogZDNfZGVncmVlcywgzrTOsyAqIGQzX2RlZ3JlZXMgXTtcbiAgICAgIM60zrsgPSBfWzBdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIM60z4YgPSBfWzFdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIM60zrMgPSBfLmxlbmd0aCA+IDIgPyBfWzJdICUgMzYwICogZDNfcmFkaWFucyA6IDA7XG4gICAgICByZXR1cm4gcmVzZXQoKTtcbiAgICB9O1xuICAgIGQzLnJlYmluZChwcm9qZWN0aW9uLCBwcm9qZWN0UmVzYW1wbGUsIFwicHJlY2lzaW9uXCIpO1xuICAgIGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgcHJvamVjdFJvdGF0ZSA9IGQzX2dlb19jb21wb3NlKHJvdGF0ZSA9IGQzX2dlb19yb3RhdGlvbijOtM67LCDOtM+GLCDOtM6zKSwgcHJvamVjdCk7XG4gICAgICB2YXIgY2VudGVyID0gcHJvamVjdCjOuywgz4YpO1xuICAgICAgzrR4ID0geCAtIGNlbnRlclswXSAqIGs7XG4gICAgICDOtHkgPSB5ICsgY2VudGVyWzFdICogaztcbiAgICAgIHJldHVybiBpbnZhbGlkYXRlKCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGludmFsaWRhdGUoKSB7XG4gICAgICBpZiAoc3RyZWFtKSBzdHJlYW0udmFsaWQgPSBmYWxzZSwgc3RyZWFtID0gbnVsbDtcbiAgICAgIHJldHVybiBwcm9qZWN0aW9uO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBwcm9qZWN0ID0gcHJvamVjdEF0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBwcm9qZWN0aW9uLmludmVydCA9IHByb2plY3QuaW52ZXJ0ICYmIGludmVydDtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3Rpb25SYWRpYW5zKHN0cmVhbSkge1xuICAgIHJldHVybiBkM19nZW9fdHJhbnNmb3JtUG9pbnQoc3RyZWFtLCBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBzdHJlYW0ucG9pbnQoeCAqIGQzX3JhZGlhbnMsIHkgKiBkM19yYWRpYW5zKTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyKM67LCDPhikge1xuICAgIHJldHVybiBbIM67LCDPhiBdO1xuICB9XG4gIChkMy5nZW8uZXF1aXJlY3Rhbmd1bGFyID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uKGQzX2dlb19lcXVpcmVjdGFuZ3VsYXIpO1xuICB9KS5yYXcgPSBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyLmludmVydCA9IGQzX2dlb19lcXVpcmVjdGFuZ3VsYXI7XG4gIGQzLmdlby5yb3RhdGlvbiA9IGZ1bmN0aW9uKHJvdGF0ZSkge1xuICAgIHJvdGF0ZSA9IGQzX2dlb19yb3RhdGlvbihyb3RhdGVbMF0gJSAzNjAgKiBkM19yYWRpYW5zLCByb3RhdGVbMV0gKiBkM19yYWRpYW5zLCByb3RhdGUubGVuZ3RoID4gMiA/IHJvdGF0ZVsyXSAqIGQzX3JhZGlhbnMgOiAwKTtcbiAgICBmdW5jdGlvbiBmb3J3YXJkKGNvb3JkaW5hdGVzKSB7XG4gICAgICBjb29yZGluYXRlcyA9IHJvdGF0ZShjb29yZGluYXRlc1swXSAqIGQzX3JhZGlhbnMsIGNvb3JkaW5hdGVzWzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXNbMF0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXNbMV0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXM7XG4gICAgfVxuICAgIGZvcndhcmQuaW52ZXJ0ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgIGNvb3JkaW5hdGVzID0gcm90YXRlLmludmVydChjb29yZGluYXRlc1swXSAqIGQzX3JhZGlhbnMsIGNvb3JkaW5hdGVzWzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXNbMF0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXNbMV0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXM7XG4gICAgfTtcbiAgICByZXR1cm4gZm9yd2FyZDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2lkZW50aXR5Um90YXRpb24ozrssIM+GKSB7XG4gICAgcmV0dXJuIFsgzrsgPiDPgCA/IM67IC0gz4QgOiDOuyA8IC3PgCA/IM67ICsgz4QgOiDOuywgz4YgXTtcbiAgfVxuICBkM19nZW9faWRlbnRpdHlSb3RhdGlvbi5pbnZlcnQgPSBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyO1xuICBmdW5jdGlvbiBkM19nZW9fcm90YXRpb24ozrTOuywgzrTPhiwgzrTOsykge1xuICAgIHJldHVybiDOtM67ID8gzrTPhiB8fCDOtM6zID8gZDNfZ2VvX2NvbXBvc2UoZDNfZ2VvX3JvdGF0aW9uzrsozrTOuyksIGQzX2dlb19yb3RhdGlvbs+GzrMozrTPhiwgzrTOsykpIDogZDNfZ2VvX3JvdGF0aW9uzrsozrTOuykgOiDOtM+GIHx8IM60zrMgPyBkM19nZW9fcm90YXRpb27Phs6zKM60z4YsIM60zrMpIDogZDNfZ2VvX2lkZW50aXR5Um90YXRpb247XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2ZvcndhcmRSb3RhdGlvbs67KM60zrspIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICByZXR1cm4gzrsgKz0gzrTOuywgWyDOuyA+IM+AID8gzrsgLSDPhCA6IM67IDwgLc+AID8gzrsgKyDPhCA6IM67LCDPhiBdO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3JvdGF0aW9uzrsozrTOuykge1xuICAgIHZhciByb3RhdGlvbiA9IGQzX2dlb19mb3J3YXJkUm90YXRpb27OuyjOtM67KTtcbiAgICByb3RhdGlvbi5pbnZlcnQgPSBkM19nZW9fZm9yd2FyZFJvdGF0aW9uzrsoLc60zrspO1xuICAgIHJldHVybiByb3RhdGlvbjtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcm90YXRpb27Phs6zKM60z4YsIM60zrMpIHtcbiAgICB2YXIgY29zzrTPhiA9IE1hdGguY29zKM60z4YpLCBzaW7OtM+GID0gTWF0aC5zaW4ozrTPhiksIGNvc860zrMgPSBNYXRoLmNvcyjOtM6zKSwgc2luzrTOsyA9IE1hdGguc2luKM60zrMpO1xuICAgIGZ1bmN0aW9uIHJvdGF0aW9uKM67LCDPhikge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCB4ID0gTWF0aC5jb3MozrspICogY29zz4YsIHkgPSBNYXRoLnNpbijOuykgKiBjb3PPhiwgeiA9IE1hdGguc2luKM+GKSwgayA9IHogKiBjb3POtM+GICsgeCAqIHNpbs60z4Y7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHkgKiBjb3POtM6zIC0gayAqIHNpbs60zrMsIHggKiBjb3POtM+GIC0geiAqIHNpbs60z4YpLCBkM19hc2luKGsgKiBjb3POtM6zICsgeSAqIHNpbs60zrMpIF07XG4gICAgfVxuICAgIHJvdGF0aW9uLmludmVydCA9IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCB4ID0gTWF0aC5jb3MozrspICogY29zz4YsIHkgPSBNYXRoLnNpbijOuykgKiBjb3PPhiwgeiA9IE1hdGguc2luKM+GKSwgayA9IHogKiBjb3POtM6zIC0geSAqIHNpbs60zrM7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHkgKiBjb3POtM6zICsgeiAqIHNpbs60zrMsIHggKiBjb3POtM+GICsgayAqIHNpbs60z4YpLCBkM19hc2luKGsgKiBjb3POtM+GIC0geCAqIHNpbs60z4YpIF07XG4gICAgfTtcbiAgICByZXR1cm4gcm90YXRpb247XG4gIH1cbiAgZDMuZ2VvLmNpcmNsZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvcmlnaW4gPSBbIDAsIDAgXSwgYW5nbGUsIHByZWNpc2lvbiA9IDYsIGludGVycG9sYXRlO1xuICAgIGZ1bmN0aW9uIGNpcmNsZSgpIHtcbiAgICAgIHZhciBjZW50ZXIgPSB0eXBlb2Ygb3JpZ2luID09PSBcImZ1bmN0aW9uXCIgPyBvcmlnaW4uYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IG9yaWdpbiwgcm90YXRlID0gZDNfZ2VvX3JvdGF0aW9uKC1jZW50ZXJbMF0gKiBkM19yYWRpYW5zLCAtY2VudGVyWzFdICogZDNfcmFkaWFucywgMCkuaW52ZXJ0LCByaW5nID0gW107XG4gICAgICBpbnRlcnBvbGF0ZShudWxsLCBudWxsLCAxLCB7XG4gICAgICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICAgICAgcmluZy5wdXNoKHggPSByb3RhdGUoeCwgeSkpO1xuICAgICAgICAgIHhbMF0gKj0gZDNfZGVncmVlcywgeFsxXSAqPSBkM19kZWdyZWVzO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogWyByaW5nIF1cbiAgICAgIH07XG4gICAgfVxuICAgIGNpcmNsZS5vcmlnaW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvcmlnaW47XG4gICAgICBvcmlnaW4gPSB4O1xuICAgICAgcmV0dXJuIGNpcmNsZTtcbiAgICB9O1xuICAgIGNpcmNsZS5hbmdsZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGFuZ2xlO1xuICAgICAgaW50ZXJwb2xhdGUgPSBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUoKGFuZ2xlID0gK3gpICogZDNfcmFkaWFucywgcHJlY2lzaW9uICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY2lyY2xlO1xuICAgIH07XG4gICAgY2lyY2xlLnByZWNpc2lvbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHByZWNpc2lvbjtcbiAgICAgIGludGVycG9sYXRlID0gZDNfZ2VvX2NpcmNsZUludGVycG9sYXRlKGFuZ2xlICogZDNfcmFkaWFucywgKHByZWNpc2lvbiA9ICtfKSAqIGQzX3JhZGlhbnMpO1xuICAgICAgcmV0dXJuIGNpcmNsZTtcbiAgICB9O1xuICAgIHJldHVybiBjaXJjbGUuYW5nbGUoOTApO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUocmFkaXVzLCBwcmVjaXNpb24pIHtcbiAgICB2YXIgY3IgPSBNYXRoLmNvcyhyYWRpdXMpLCBzciA9IE1hdGguc2luKHJhZGl1cyk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGZyb20sIHRvLCBkaXJlY3Rpb24sIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgc3RlcCA9IGRpcmVjdGlvbiAqIHByZWNpc2lvbjtcbiAgICAgIGlmIChmcm9tICE9IG51bGwpIHtcbiAgICAgICAgZnJvbSA9IGQzX2dlb19jaXJjbGVBbmdsZShjciwgZnJvbSk7XG4gICAgICAgIHRvID0gZDNfZ2VvX2NpcmNsZUFuZ2xlKGNyLCB0byk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPiAwID8gZnJvbSA8IHRvIDogZnJvbSA+IHRvKSBmcm9tICs9IGRpcmVjdGlvbiAqIM+EO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnJvbSA9IHJhZGl1cyArIGRpcmVjdGlvbiAqIM+EO1xuICAgICAgICB0byA9IHJhZGl1cyAtIC41ICogc3RlcDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIHBvaW50LCB0ID0gZnJvbTsgZGlyZWN0aW9uID4gMCA/IHQgPiB0byA6IHQgPCB0bzsgdCAtPSBzdGVwKSB7XG4gICAgICAgIGxpc3RlbmVyLnBvaW50KChwb2ludCA9IGQzX2dlb19zcGhlcmljYWwoWyBjciwgLXNyICogTWF0aC5jb3ModCksIC1zciAqIE1hdGguc2luKHQpIF0pKVswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NpcmNsZUFuZ2xlKGNyLCBwb2ludCkge1xuICAgIHZhciBhID0gZDNfZ2VvX2NhcnRlc2lhbihwb2ludCk7XG4gICAgYVswXSAtPSBjcjtcbiAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGEpO1xuICAgIHZhciBhbmdsZSA9IGQzX2Fjb3MoLWFbMV0pO1xuICAgIHJldHVybiAoKC1hWzJdIDwgMCA/IC1hbmdsZSA6IGFuZ2xlKSArIDIgKiBNYXRoLlBJIC0gzrUpICUgKDIgKiBNYXRoLlBJKTtcbiAgfVxuICBkMy5nZW8uZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIM6UzrsgPSAoYlswXSAtIGFbMF0pICogZDNfcmFkaWFucywgz4YwID0gYVsxXSAqIGQzX3JhZGlhbnMsIM+GMSA9IGJbMV0gKiBkM19yYWRpYW5zLCBzaW7OlM67ID0gTWF0aC5zaW4ozpTOuyksIGNvc86UzrsgPSBNYXRoLmNvcyjOlM67KSwgc2luz4YwID0gTWF0aC5zaW4oz4YwKSwgY29zz4YwID0gTWF0aC5jb3Moz4YwKSwgc2luz4YxID0gTWF0aC5zaW4oz4YxKSwgY29zz4YxID0gTWF0aC5jb3Moz4YxKSwgdDtcbiAgICByZXR1cm4gTWF0aC5hdGFuMihNYXRoLnNxcnQoKHQgPSBjb3PPhjEgKiBzaW7OlM67KSAqIHQgKyAodCA9IGNvc8+GMCAqIHNpbs+GMSAtIHNpbs+GMCAqIGNvc8+GMSAqIGNvc86UzrspICogdCksIHNpbs+GMCAqIHNpbs+GMSArIGNvc8+GMCAqIGNvc8+GMSAqIGNvc86UzrspO1xuICB9O1xuICBkMy5nZW8uZ3JhdGljdWxlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHgxLCB4MCwgWDEsIFgwLCB5MSwgeTAsIFkxLCBZMCwgZHggPSAxMCwgZHkgPSBkeCwgRFggPSA5MCwgRFkgPSAzNjAsIHgsIHksIFgsIFksIHByZWNpc2lvbiA9IDIuNTtcbiAgICBmdW5jdGlvbiBncmF0aWN1bGUoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIk11bHRpTGluZVN0cmluZ1wiLFxuICAgICAgICBjb29yZGluYXRlczogbGluZXMoKVxuICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZXMoKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoTWF0aC5jZWlsKFgwIC8gRFgpICogRFgsIFgxLCBEWCkubWFwKFgpLmNvbmNhdChkMy5yYW5nZShNYXRoLmNlaWwoWTAgLyBEWSkgKiBEWSwgWTEsIERZKS5tYXAoWSkpLmNvbmNhdChkMy5yYW5nZShNYXRoLmNlaWwoeDAgLyBkeCkgKiBkeCwgeDEsIGR4KS5maWx0ZXIoZnVuY3Rpb24oeCkge1xuICAgICAgICByZXR1cm4gYWJzKHggJSBEWCkgPiDOtTtcbiAgICAgIH0pLm1hcCh4KSkuY29uY2F0KGQzLnJhbmdlKE1hdGguY2VpbCh5MCAvIGR5KSAqIGR5LCB5MSwgZHkpLmZpbHRlcihmdW5jdGlvbih5KSB7XG4gICAgICAgIHJldHVybiBhYnMoeSAlIERZKSA+IM61O1xuICAgICAgfSkubWFwKHkpKTtcbiAgICB9XG4gICAgZ3JhdGljdWxlLmxpbmVzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gbGluZXMoKS5tYXAoZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXNcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLm91dGxpbmUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogWyBYKFgwKS5jb25jYXQoWShZMSkuc2xpY2UoMSksIFgoWDEpLnJldmVyc2UoKS5zbGljZSgxKSwgWShZMCkucmV2ZXJzZSgpLnNsaWNlKDEpKSBdXG4gICAgICB9O1xuICAgIH07XG4gICAgZ3JhdGljdWxlLmV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGdyYXRpY3VsZS5taW5vckV4dGVudCgpO1xuICAgICAgcmV0dXJuIGdyYXRpY3VsZS5tYWpvckV4dGVudChfKS5taW5vckV4dGVudChfKTtcbiAgICB9O1xuICAgIGdyYXRpY3VsZS5tYWpvckV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIFsgWyBYMCwgWTAgXSwgWyBYMSwgWTEgXSBdO1xuICAgICAgWDAgPSArX1swXVswXSwgWDEgPSArX1sxXVswXTtcbiAgICAgIFkwID0gK19bMF1bMV0sIFkxID0gK19bMV1bMV07XG4gICAgICBpZiAoWDAgPiBYMSkgXyA9IFgwLCBYMCA9IFgxLCBYMSA9IF87XG4gICAgICBpZiAoWTAgPiBZMSkgXyA9IFkwLCBZMCA9IFkxLCBZMSA9IF87XG4gICAgICByZXR1cm4gZ3JhdGljdWxlLnByZWNpc2lvbihwcmVjaXNpb24pO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLm1pbm9yRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyBbIHgwLCB5MCBdLCBbIHgxLCB5MSBdIF07XG4gICAgICB4MCA9ICtfWzBdWzBdLCB4MSA9ICtfWzFdWzBdO1xuICAgICAgeTAgPSArX1swXVsxXSwgeTEgPSArX1sxXVsxXTtcbiAgICAgIGlmICh4MCA+IHgxKSBfID0geDAsIHgwID0geDEsIHgxID0gXztcbiAgICAgIGlmICh5MCA+IHkxKSBfID0geTAsIHkwID0geTEsIHkxID0gXztcbiAgICAgIHJldHVybiBncmF0aWN1bGUucHJlY2lzaW9uKHByZWNpc2lvbik7XG4gICAgfTtcbiAgICBncmF0aWN1bGUuc3RlcCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGdyYXRpY3VsZS5taW5vclN0ZXAoKTtcbiAgICAgIHJldHVybiBncmF0aWN1bGUubWFqb3JTdGVwKF8pLm1pbm9yU3RlcChfKTtcbiAgICB9O1xuICAgIGdyYXRpY3VsZS5tYWpvclN0ZXAgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIERYLCBEWSBdO1xuICAgICAgRFggPSArX1swXSwgRFkgPSArX1sxXTtcbiAgICAgIHJldHVybiBncmF0aWN1bGU7XG4gICAgfTtcbiAgICBncmF0aWN1bGUubWlub3JTdGVwID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyBkeCwgZHkgXTtcbiAgICAgIGR4ID0gK19bMF0sIGR5ID0gK19bMV07XG4gICAgICByZXR1cm4gZ3JhdGljdWxlO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLnByZWNpc2lvbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHByZWNpc2lvbjtcbiAgICAgIHByZWNpc2lvbiA9ICtfO1xuICAgICAgeCA9IGQzX2dlb19ncmF0aWN1bGVYKHkwLCB5MSwgOTApO1xuICAgICAgeSA9IGQzX2dlb19ncmF0aWN1bGVZKHgwLCB4MSwgcHJlY2lzaW9uKTtcbiAgICAgIFggPSBkM19nZW9fZ3JhdGljdWxlWChZMCwgWTEsIDkwKTtcbiAgICAgIFkgPSBkM19nZW9fZ3JhdGljdWxlWShYMCwgWDEsIHByZWNpc2lvbik7XG4gICAgICByZXR1cm4gZ3JhdGljdWxlO1xuICAgIH07XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5tYWpvckV4dGVudChbIFsgLTE4MCwgLTkwICsgzrUgXSwgWyAxODAsIDkwIC0gzrUgXSBdKS5taW5vckV4dGVudChbIFsgLTE4MCwgLTgwIC0gzrUgXSwgWyAxODAsIDgwICsgzrUgXSBdKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2dyYXRpY3VsZVgoeTAsIHkxLCBkeSkge1xuICAgIHZhciB5ID0gZDMucmFuZ2UoeTAsIHkxIC0gzrUsIGR5KS5jb25jYXQoeTEpO1xuICAgIHJldHVybiBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4geS5tYXAoZnVuY3Rpb24oeSkge1xuICAgICAgICByZXR1cm4gWyB4LCB5IF07XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19ncmF0aWN1bGVZKHgwLCB4MSwgZHgpIHtcbiAgICB2YXIgeCA9IGQzLnJhbmdlKHgwLCB4MSAtIM61LCBkeCkuY29uY2F0KHgxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeSkge1xuICAgICAgcmV0dXJuIHgubWFwKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgcmV0dXJuIFsgeCwgeSBdO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19zb3VyY2UoZCkge1xuICAgIHJldHVybiBkLnNvdXJjZTtcbiAgfVxuICBmdW5jdGlvbiBkM190YXJnZXQoZCkge1xuICAgIHJldHVybiBkLnRhcmdldDtcbiAgfVxuICBkMy5nZW8uZ3JlYXRBcmMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc291cmNlID0gZDNfc291cmNlLCBzb3VyY2VfLCB0YXJnZXQgPSBkM190YXJnZXQsIHRhcmdldF87XG4gICAgZnVuY3Rpb24gZ3JlYXRBcmMoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IFsgc291cmNlXyB8fCBzb3VyY2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgdGFyZ2V0XyB8fCB0YXJnZXQuYXBwbHkodGhpcywgYXJndW1lbnRzKSBdXG4gICAgICB9O1xuICAgIH1cbiAgICBncmVhdEFyYy5kaXN0YW5jZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzLmdlby5kaXN0YW5jZShzb3VyY2VfIHx8IHNvdXJjZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCB0YXJnZXRfIHx8IHRhcmdldC5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICAgIGdyZWF0QXJjLnNvdXJjZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvdXJjZTtcbiAgICAgIHNvdXJjZSA9IF8sIHNvdXJjZV8gPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gbnVsbCA6IF87XG4gICAgICByZXR1cm4gZ3JlYXRBcmM7XG4gICAgfTtcbiAgICBncmVhdEFyYy50YXJnZXQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB0YXJnZXQ7XG4gICAgICB0YXJnZXQgPSBfLCB0YXJnZXRfID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IG51bGwgOiBfO1xuICAgICAgcmV0dXJuIGdyZWF0QXJjO1xuICAgIH07XG4gICAgZ3JlYXRBcmMucHJlY2lzaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IGdyZWF0QXJjIDogMDtcbiAgICB9O1xuICAgIHJldHVybiBncmVhdEFyYztcbiAgfTtcbiAgZDMuZ2VvLmludGVycG9sYXRlID0gZnVuY3Rpb24oc291cmNlLCB0YXJnZXQpIHtcbiAgICByZXR1cm4gZDNfZ2VvX2ludGVycG9sYXRlKHNvdXJjZVswXSAqIGQzX3JhZGlhbnMsIHNvdXJjZVsxXSAqIGQzX3JhZGlhbnMsIHRhcmdldFswXSAqIGQzX3JhZGlhbnMsIHRhcmdldFsxXSAqIGQzX3JhZGlhbnMpO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9faW50ZXJwb2xhdGUoeDAsIHkwLCB4MSwgeTEpIHtcbiAgICB2YXIgY3kwID0gTWF0aC5jb3MoeTApLCBzeTAgPSBNYXRoLnNpbih5MCksIGN5MSA9IE1hdGguY29zKHkxKSwgc3kxID0gTWF0aC5zaW4oeTEpLCBreDAgPSBjeTAgKiBNYXRoLmNvcyh4MCksIGt5MCA9IGN5MCAqIE1hdGguc2luKHgwKSwga3gxID0gY3kxICogTWF0aC5jb3MoeDEpLCBreTEgPSBjeTEgKiBNYXRoLnNpbih4MSksIGQgPSAyICogTWF0aC5hc2luKE1hdGguc3FydChkM19oYXZlcnNpbih5MSAtIHkwKSArIGN5MCAqIGN5MSAqIGQzX2hhdmVyc2luKHgxIC0geDApKSksIGsgPSAxIC8gTWF0aC5zaW4oZCk7XG4gICAgdmFyIGludGVycG9sYXRlID0gZCA/IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBCID0gTWF0aC5zaW4odCAqPSBkKSAqIGssIEEgPSBNYXRoLnNpbihkIC0gdCkgKiBrLCB4ID0gQSAqIGt4MCArIEIgKiBreDEsIHkgPSBBICoga3kwICsgQiAqIGt5MSwgeiA9IEEgKiBzeTAgKyBCICogc3kxO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih5LCB4KSAqIGQzX2RlZ3JlZXMsIE1hdGguYXRhbjIoeiwgTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpKSAqIGQzX2RlZ3JlZXMgXTtcbiAgICB9IDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gWyB4MCAqIGQzX2RlZ3JlZXMsIHkwICogZDNfZGVncmVlcyBdO1xuICAgIH07XG4gICAgaW50ZXJwb2xhdGUuZGlzdGFuY2UgPSBkO1xuICAgIHJldHVybiBpbnRlcnBvbGF0ZTtcbiAgfVxuICBkMy5nZW8ubGVuZ3RoID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgZDNfZ2VvX2xlbmd0aFN1bSA9IDA7XG4gICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIGQzX2dlb19sZW5ndGgpO1xuICAgIHJldHVybiBkM19nZW9fbGVuZ3RoU3VtO1xuICB9O1xuICB2YXIgZDNfZ2VvX2xlbmd0aFN1bTtcbiAgdmFyIGQzX2dlb19sZW5ndGggPSB7XG4gICAgc3BoZXJlOiBkM19ub29wLFxuICAgIHBvaW50OiBkM19ub29wLFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX2xlbmd0aExpbmVTdGFydCxcbiAgICBsaW5lRW5kOiBkM19ub29wLFxuICAgIHBvbHlnb25TdGFydDogZDNfbm9vcCxcbiAgICBwb2x5Z29uRW5kOiBkM19ub29wXG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19sZW5ndGhMaW5lU3RhcnQoKSB7XG4gICAgdmFyIM67MCwgc2luz4YwLCBjb3PPhjA7XG4gICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgzrswID0gzrsgKiBkM19yYWRpYW5zLCBzaW7PhjAgPSBNYXRoLnNpbijPhiAqPSBkM19yYWRpYW5zKSwgY29zz4YwID0gTWF0aC5jb3Moz4YpO1xuICAgICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IG5leHRQb2ludDtcbiAgICB9O1xuICAgIGQzX2dlb19sZW5ndGgubGluZUVuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IGQzX2dlb19sZW5ndGgubGluZUVuZCA9IGQzX25vb3A7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQozrssIM+GKSB7XG4gICAgICB2YXIgc2luz4YgPSBNYXRoLnNpbijPhiAqPSBkM19yYWRpYW5zKSwgY29zz4YgPSBNYXRoLmNvcyjPhiksIHQgPSBhYnMoKM67ICo9IGQzX3JhZGlhbnMpIC0gzrswKSwgY29zzpTOuyA9IE1hdGguY29zKHQpO1xuICAgICAgZDNfZ2VvX2xlbmd0aFN1bSArPSBNYXRoLmF0YW4yKE1hdGguc3FydCgodCA9IGNvc8+GICogTWF0aC5zaW4odCkpICogdCArICh0ID0gY29zz4YwICogc2luz4YgLSBzaW7PhjAgKiBjb3PPhiAqIGNvc86UzrspICogdCksIHNpbs+GMCAqIHNpbs+GICsgY29zz4YwICogY29zz4YgKiBjb3POlM67KTtcbiAgICAgIM67MCA9IM67LCBzaW7PhjAgPSBzaW7PhiwgY29zz4YwID0gY29zz4Y7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19hemltdXRoYWwoc2NhbGUsIGFuZ2xlKSB7XG4gICAgZnVuY3Rpb24gYXppbXV0aGFsKM67LCDPhikge1xuICAgICAgdmFyIGNvc867ID0gTWF0aC5jb3MozrspLCBjb3PPhiA9IE1hdGguY29zKM+GKSwgayA9IHNjYWxlKGNvc867ICogY29zz4YpO1xuICAgICAgcmV0dXJuIFsgayAqIGNvc8+GICogTWF0aC5zaW4ozrspLCBrICogTWF0aC5zaW4oz4YpIF07XG4gICAgfVxuICAgIGF6aW11dGhhbC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgz4EgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSksIGMgPSBhbmdsZSjPgSksIHNpbmMgPSBNYXRoLnNpbihjKSwgY29zYyA9IE1hdGguY29zKGMpO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4ICogc2luYywgz4EgKiBjb3NjKSwgTWF0aC5hc2luKM+BICYmIHkgKiBzaW5jIC8gz4EpIF07XG4gICAgfTtcbiAgICByZXR1cm4gYXppbXV0aGFsO1xuICB9XG4gIHZhciBkM19nZW9fYXppbXV0aGFsRXF1YWxBcmVhID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbihjb3POu2Nvc8+GKSB7XG4gICAgcmV0dXJuIE1hdGguc3FydCgyIC8gKDEgKyBjb3POu2Nvc8+GKSk7XG4gIH0sIGZ1bmN0aW9uKM+BKSB7XG4gICAgcmV0dXJuIDIgKiBNYXRoLmFzaW4oz4EgLyAyKTtcbiAgfSk7XG4gIChkMy5nZW8uYXppbXV0aGFsRXF1YWxBcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uKGQzX2dlb19hemltdXRoYWxFcXVhbEFyZWEpO1xuICB9KS5yYXcgPSBkM19nZW9fYXppbXV0aGFsRXF1YWxBcmVhO1xuICB2YXIgZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50ID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbihjb3POu2Nvc8+GKSB7XG4gICAgdmFyIGMgPSBNYXRoLmFjb3MoY29zzrtjb3PPhik7XG4gICAgcmV0dXJuIGMgJiYgYyAvIE1hdGguc2luKGMpO1xuICB9LCBkM19pZGVudGl0eSk7XG4gIChkMy5nZW8uYXppbXV0aGFsRXF1aWRpc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50KTtcbiAgfSkucmF3ID0gZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50O1xuICBmdW5jdGlvbiBkM19nZW9fY29uaWNDb25mb3JtYWwoz4YwLCDPhjEpIHtcbiAgICB2YXIgY29zz4YwID0gTWF0aC5jb3Moz4YwKSwgdCA9IGZ1bmN0aW9uKM+GKSB7XG4gICAgICByZXR1cm4gTWF0aC50YW4oz4AgLyA0ICsgz4YgLyAyKTtcbiAgICB9LCBuID0gz4YwID09PSDPhjEgPyBNYXRoLnNpbijPhjApIDogTWF0aC5sb2coY29zz4YwIC8gTWF0aC5jb3Moz4YxKSkgLyBNYXRoLmxvZyh0KM+GMSkgLyB0KM+GMCkpLCBGID0gY29zz4YwICogTWF0aC5wb3codCjPhjApLCBuKSAvIG47XG4gICAgaWYgKCFuKSByZXR1cm4gZDNfZ2VvX21lcmNhdG9yO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICBpZiAoRiA+IDApIHtcbiAgICAgICAgaWYgKM+GIDwgLWhhbGbPgCArIM61KSDPhiA9IC1oYWxmz4AgKyDOtTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICjPhiA+IGhhbGbPgCAtIM61KSDPhiA9IGhhbGbPgCAtIM61O1xuICAgICAgfVxuICAgICAgdmFyIM+BID0gRiAvIE1hdGgucG93KHQoz4YpLCBuKTtcbiAgICAgIHJldHVybiBbIM+BICogTWF0aC5zaW4obiAqIM67KSwgRiAtIM+BICogTWF0aC5jb3MobiAqIM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IEYgLSB5LCDPgSA9IGQzX3NnbihuKSAqIE1hdGguc3FydCh4ICogeCArIM+BMF95ICogz4EwX3kpO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4LCDPgTBfeSkgLyBuLCAyICogTWF0aC5hdGFuKE1hdGgucG93KEYgLyDPgSwgMSAvIG4pKSAtIGhhbGbPgCBdO1xuICAgIH07XG4gICAgcmV0dXJuIGZvcndhcmQ7XG4gIH1cbiAgKGQzLmdlby5jb25pY0NvbmZvcm1hbCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fY29uaWMoZDNfZ2VvX2NvbmljQ29uZm9ybWFsKTtcbiAgfSkucmF3ID0gZDNfZ2VvX2NvbmljQ29uZm9ybWFsO1xuICBmdW5jdGlvbiBkM19nZW9fY29uaWNFcXVpZGlzdGFudCjPhjAsIM+GMSkge1xuICAgIHZhciBjb3PPhjAgPSBNYXRoLmNvcyjPhjApLCBuID0gz4YwID09PSDPhjEgPyBNYXRoLnNpbijPhjApIDogKGNvc8+GMCAtIE1hdGguY29zKM+GMSkpIC8gKM+GMSAtIM+GMCksIEcgPSBjb3PPhjAgLyBuICsgz4YwO1xuICAgIGlmIChhYnMobikgPCDOtSkgcmV0dXJuIGQzX2dlb19lcXVpcmVjdGFuZ3VsYXI7XG4gICAgZnVuY3Rpb24gZm9yd2FyZCjOuywgz4YpIHtcbiAgICAgIHZhciDPgSA9IEcgLSDPhjtcbiAgICAgIHJldHVybiBbIM+BICogTWF0aC5zaW4obiAqIM67KSwgRyAtIM+BICogTWF0aC5jb3MobiAqIM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IEcgLSB5O1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4LCDPgTBfeSkgLyBuLCBHIC0gZDNfc2duKG4pICogTWF0aC5zcXJ0KHggKiB4ICsgz4EwX3kgKiDPgTBfeSkgXTtcbiAgICB9O1xuICAgIHJldHVybiBmb3J3YXJkO1xuICB9XG4gIChkMy5nZW8uY29uaWNFcXVpZGlzdGFudCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fY29uaWMoZDNfZ2VvX2NvbmljRXF1aWRpc3RhbnQpO1xuICB9KS5yYXcgPSBkM19nZW9fY29uaWNFcXVpZGlzdGFudDtcbiAgdmFyIGQzX2dlb19nbm9tb25pYyA9IGQzX2dlb19hemltdXRoYWwoZnVuY3Rpb24oY29zzrtjb3PPhikge1xuICAgIHJldHVybiAxIC8gY29zzrtjb3PPhjtcbiAgfSwgTWF0aC5hdGFuKTtcbiAgKGQzLmdlby5nbm9tb25pYyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fcHJvamVjdGlvbihkM19nZW9fZ25vbW9uaWMpO1xuICB9KS5yYXcgPSBkM19nZW9fZ25vbW9uaWM7XG4gIGZ1bmN0aW9uIGQzX2dlb19tZXJjYXRvcijOuywgz4YpIHtcbiAgICByZXR1cm4gWyDOuywgTWF0aC5sb2coTWF0aC50YW4oz4AgLyA0ICsgz4YgLyAyKSkgXTtcbiAgfVxuICBkM19nZW9fbWVyY2F0b3IuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiBbIHgsIDIgKiBNYXRoLmF0YW4oTWF0aC5leHAoeSkpIC0gaGFsZs+AIF07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19tZXJjYXRvclByb2plY3Rpb24ocHJvamVjdCkge1xuICAgIHZhciBtID0gZDNfZ2VvX3Byb2plY3Rpb24ocHJvamVjdCksIHNjYWxlID0gbS5zY2FsZSwgdHJhbnNsYXRlID0gbS50cmFuc2xhdGUsIGNsaXBFeHRlbnQgPSBtLmNsaXBFeHRlbnQsIGNsaXBBdXRvO1xuICAgIG0uc2NhbGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2ID0gc2NhbGUuYXBwbHkobSwgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiB2ID09PSBtID8gY2xpcEF1dG8gPyBtLmNsaXBFeHRlbnQobnVsbCkgOiBtIDogdjtcbiAgICB9O1xuICAgIG0udHJhbnNsYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdiA9IHRyYW5zbGF0ZS5hcHBseShtLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIHYgPT09IG0gPyBjbGlwQXV0byA/IG0uY2xpcEV4dGVudChudWxsKSA6IG0gOiB2O1xuICAgIH07XG4gICAgbS5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgdmFyIHYgPSBjbGlwRXh0ZW50LmFwcGx5KG0sIGFyZ3VtZW50cyk7XG4gICAgICBpZiAodiA9PT0gbSkge1xuICAgICAgICBpZiAoY2xpcEF1dG8gPSBfID09IG51bGwpIHtcbiAgICAgICAgICB2YXIgayA9IM+AICogc2NhbGUoKSwgdCA9IHRyYW5zbGF0ZSgpO1xuICAgICAgICAgIGNsaXBFeHRlbnQoWyBbIHRbMF0gLSBrLCB0WzFdIC0gayBdLCBbIHRbMF0gKyBrLCB0WzFdICsgayBdIF0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGNsaXBBdXRvKSB7XG4gICAgICAgIHYgPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHY7XG4gICAgfTtcbiAgICByZXR1cm4gbS5jbGlwRXh0ZW50KG51bGwpO1xuICB9XG4gIChkMy5nZW8ubWVyY2F0b3IgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX21lcmNhdG9yUHJvamVjdGlvbihkM19nZW9fbWVyY2F0b3IpO1xuICB9KS5yYXcgPSBkM19nZW9fbWVyY2F0b3I7XG4gIHZhciBkM19nZW9fb3J0aG9ncmFwaGljID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gMTtcbiAgfSwgTWF0aC5hc2luKTtcbiAgKGQzLmdlby5vcnRob2dyYXBoaWMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX29ydGhvZ3JhcGhpYyk7XG4gIH0pLnJhdyA9IGQzX2dlb19vcnRob2dyYXBoaWM7XG4gIHZhciBkM19nZW9fc3RlcmVvZ3JhcGhpYyA9IGQzX2dlb19hemltdXRoYWwoZnVuY3Rpb24oY29zzrtjb3PPhikge1xuICAgIHJldHVybiAxIC8gKDEgKyBjb3POu2Nvc8+GKTtcbiAgfSwgZnVuY3Rpb24oz4EpIHtcbiAgICByZXR1cm4gMiAqIE1hdGguYXRhbijPgSk7XG4gIH0pO1xuICAoZDMuZ2VvLnN0ZXJlb2dyYXBoaWMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX3N0ZXJlb2dyYXBoaWMpO1xuICB9KS5yYXcgPSBkM19nZW9fc3RlcmVvZ3JhcGhpYztcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zdmVyc2VNZXJjYXRvcijOuywgz4YpIHtcbiAgICByZXR1cm4gWyBNYXRoLmxvZyhNYXRoLnRhbijPgCAvIDQgKyDPhiAvIDIpKSwgLc67IF07XG4gIH1cbiAgZDNfZ2VvX3RyYW5zdmVyc2VNZXJjYXRvci5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFsgLXksIDIgKiBNYXRoLmF0YW4oTWF0aC5leHAoeCkpIC0gaGFsZs+AIF07XG4gIH07XG4gIChkMy5nZW8udHJhbnN2ZXJzZU1lcmNhdG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSBkM19nZW9fbWVyY2F0b3JQcm9qZWN0aW9uKGQzX2dlb190cmFuc3ZlcnNlTWVyY2F0b3IpLCBjZW50ZXIgPSBwcm9qZWN0aW9uLmNlbnRlciwgcm90YXRlID0gcHJvamVjdGlvbi5yb3RhdGU7XG4gICAgcHJvamVjdGlvbi5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gXyA/IGNlbnRlcihbIC1fWzFdLCBfWzBdIF0pIDogKF8gPSBjZW50ZXIoKSwgWyBfWzFdLCAtX1swXSBdKTtcbiAgICB9O1xuICAgIHByb2plY3Rpb24ucm90YXRlID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIF8gPyByb3RhdGUoWyBfWzBdLCBfWzFdLCBfLmxlbmd0aCA+IDIgPyBfWzJdICsgOTAgOiA5MCBdKSA6IChfID0gcm90YXRlKCksIFxuICAgICAgWyBfWzBdLCBfWzFdLCBfWzJdIC0gOTAgXSk7XG4gICAgfTtcbiAgICByZXR1cm4gcm90YXRlKFsgMCwgMCwgOTAgXSk7XG4gIH0pLnJhdyA9IGQzX2dlb190cmFuc3ZlcnNlTWVyY2F0b3I7XG4gIGQzLmdlb20gPSB7fTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2ludFgoZCkge1xuICAgIHJldHVybiBkWzBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fcG9pbnRZKGQpIHtcbiAgICByZXR1cm4gZFsxXTtcbiAgfVxuICBkMy5nZW9tLmh1bGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGh1bGwodmVydGljZXMpO1xuICAgIGZ1bmN0aW9uIGh1bGwoZGF0YSkge1xuICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgMykgcmV0dXJuIFtdO1xuICAgICAgdmFyIGZ4ID0gZDNfZnVuY3Rvcih4KSwgZnkgPSBkM19mdW5jdG9yKHkpLCBpLCBuID0gZGF0YS5sZW5ndGgsIHBvaW50cyA9IFtdLCBmbGlwcGVkUG9pbnRzID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHBvaW50cy5wdXNoKFsgK2Z4LmNhbGwodGhpcywgZGF0YVtpXSwgaSksICtmeS5jYWxsKHRoaXMsIGRhdGFbaV0sIGkpLCBpIF0pO1xuICAgICAgfVxuICAgICAgcG9pbnRzLnNvcnQoZDNfZ2VvbV9odWxsT3JkZXIpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykgZmxpcHBlZFBvaW50cy5wdXNoKFsgcG9pbnRzW2ldWzBdLCAtcG9pbnRzW2ldWzFdIF0pO1xuICAgICAgdmFyIHVwcGVyID0gZDNfZ2VvbV9odWxsVXBwZXIocG9pbnRzKSwgbG93ZXIgPSBkM19nZW9tX2h1bGxVcHBlcihmbGlwcGVkUG9pbnRzKTtcbiAgICAgIHZhciBza2lwTGVmdCA9IGxvd2VyWzBdID09PSB1cHBlclswXSwgc2tpcFJpZ2h0ID0gbG93ZXJbbG93ZXIubGVuZ3RoIC0gMV0gPT09IHVwcGVyW3VwcGVyLmxlbmd0aCAtIDFdLCBwb2x5Z29uID0gW107XG4gICAgICBmb3IgKGkgPSB1cHBlci5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgcG9seWdvbi5wdXNoKGRhdGFbcG9pbnRzW3VwcGVyW2ldXVsyXV0pO1xuICAgICAgZm9yIChpID0gK3NraXBMZWZ0OyBpIDwgbG93ZXIubGVuZ3RoIC0gc2tpcFJpZ2h0OyArK2kpIHBvbHlnb24ucHVzaChkYXRhW3BvaW50c1tsb3dlcltpXV1bMl1dKTtcbiAgICAgIHJldHVybiBwb2x5Z29uO1xuICAgIH1cbiAgICBodWxsLnggPSBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4ID0gXywgaHVsbCkgOiB4O1xuICAgIH07XG4gICAgaHVsbC55ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9IF8sIGh1bGwpIDogeTtcbiAgICB9O1xuICAgIHJldHVybiBodWxsO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX2h1bGxVcHBlcihwb2ludHMpIHtcbiAgICB2YXIgbiA9IHBvaW50cy5sZW5ndGgsIGh1bGwgPSBbIDAsIDEgXSwgaHMgPSAyO1xuICAgIGZvciAodmFyIGkgPSAyOyBpIDwgbjsgaSsrKSB7XG4gICAgICB3aGlsZSAoaHMgPiAxICYmIGQzX2Nyb3NzMmQocG9pbnRzW2h1bGxbaHMgLSAyXV0sIHBvaW50c1todWxsW2hzIC0gMV1dLCBwb2ludHNbaV0pIDw9IDApIC0taHM7XG4gICAgICBodWxsW2hzKytdID0gaTtcbiAgICB9XG4gICAgcmV0dXJuIGh1bGwuc2xpY2UoMCwgaHMpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21faHVsbE9yZGVyKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAtIGJbMF0gfHwgYVsxXSAtIGJbMV07XG4gIH1cbiAgZDMuZ2VvbS5wb2x5Z29uID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICBkM19zdWJjbGFzcyhjb29yZGluYXRlcywgZDNfZ2VvbV9wb2x5Z29uUHJvdG90eXBlKTtcbiAgICByZXR1cm4gY29vcmRpbmF0ZXM7XG4gIH07XG4gIHZhciBkM19nZW9tX3BvbHlnb25Qcm90b3R5cGUgPSBkMy5nZW9tLnBvbHlnb24ucHJvdG90eXBlID0gW107XG4gIGQzX2dlb21fcG9seWdvblByb3RvdHlwZS5hcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IHRoaXMubGVuZ3RoLCBhLCBiID0gdGhpc1tuIC0gMV0sIGFyZWEgPSAwO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBhID0gYjtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYXJlYSArPSBhWzFdICogYlswXSAtIGFbMF0gKiBiWzFdO1xuICAgIH1cbiAgICByZXR1cm4gYXJlYSAqIC41O1xuICB9O1xuICBkM19nZW9tX3BvbHlnb25Qcm90b3R5cGUuY2VudHJvaWQgPSBmdW5jdGlvbihrKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IHRoaXMubGVuZ3RoLCB4ID0gMCwgeSA9IDAsIGEsIGIgPSB0aGlzW24gLSAxXSwgYztcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIGsgPSAtMSAvICg2ICogdGhpcy5hcmVhKCkpO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBhID0gYjtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYyA9IGFbMF0gKiBiWzFdIC0gYlswXSAqIGFbMV07XG4gICAgICB4ICs9IChhWzBdICsgYlswXSkgKiBjO1xuICAgICAgeSArPSAoYVsxXSArIGJbMV0pICogYztcbiAgICB9XG4gICAgcmV0dXJuIFsgeCAqIGssIHkgKiBrIF07XG4gIH07XG4gIGQzX2dlb21fcG9seWdvblByb3RvdHlwZS5jbGlwID0gZnVuY3Rpb24oc3ViamVjdCkge1xuICAgIHZhciBpbnB1dCwgY2xvc2VkID0gZDNfZ2VvbV9wb2x5Z29uQ2xvc2VkKHN1YmplY3QpLCBpID0gLTEsIG4gPSB0aGlzLmxlbmd0aCAtIGQzX2dlb21fcG9seWdvbkNsb3NlZCh0aGlzKSwgaiwgbSwgYSA9IHRoaXNbbiAtIDFdLCBiLCBjLCBkO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpbnB1dCA9IHN1YmplY3Quc2xpY2UoKTtcbiAgICAgIHN1YmplY3QubGVuZ3RoID0gMDtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYyA9IGlucHV0WyhtID0gaW5wdXQubGVuZ3RoIC0gY2xvc2VkKSAtIDFdO1xuICAgICAgaiA9IC0xO1xuICAgICAgd2hpbGUgKCsraiA8IG0pIHtcbiAgICAgICAgZCA9IGlucHV0W2pdO1xuICAgICAgICBpZiAoZDNfZ2VvbV9wb2x5Z29uSW5zaWRlKGQsIGEsIGIpKSB7XG4gICAgICAgICAgaWYgKCFkM19nZW9tX3BvbHlnb25JbnNpZGUoYywgYSwgYikpIHtcbiAgICAgICAgICAgIHN1YmplY3QucHVzaChkM19nZW9tX3BvbHlnb25JbnRlcnNlY3QoYywgZCwgYSwgYikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzdWJqZWN0LnB1c2goZCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZDNfZ2VvbV9wb2x5Z29uSW5zaWRlKGMsIGEsIGIpKSB7XG4gICAgICAgICAgc3ViamVjdC5wdXNoKGQzX2dlb21fcG9seWdvbkludGVyc2VjdChjLCBkLCBhLCBiKSk7XG4gICAgICAgIH1cbiAgICAgICAgYyA9IGQ7XG4gICAgICB9XG4gICAgICBpZiAoY2xvc2VkKSBzdWJqZWN0LnB1c2goc3ViamVjdFswXSk7XG4gICAgICBhID0gYjtcbiAgICB9XG4gICAgcmV0dXJuIHN1YmplY3Q7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb21fcG9seWdvbkluc2lkZShwLCBhLCBiKSB7XG4gICAgcmV0dXJuIChiWzBdIC0gYVswXSkgKiAocFsxXSAtIGFbMV0pIDwgKGJbMV0gLSBhWzFdKSAqIChwWzBdIC0gYVswXSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2x5Z29uSW50ZXJzZWN0KGMsIGQsIGEsIGIpIHtcbiAgICB2YXIgeDEgPSBjWzBdLCB4MyA9IGFbMF0sIHgyMSA9IGRbMF0gLSB4MSwgeDQzID0gYlswXSAtIHgzLCB5MSA9IGNbMV0sIHkzID0gYVsxXSwgeTIxID0gZFsxXSAtIHkxLCB5NDMgPSBiWzFdIC0geTMsIHVhID0gKHg0MyAqICh5MSAtIHkzKSAtIHk0MyAqICh4MSAtIHgzKSkgLyAoeTQzICogeDIxIC0geDQzICogeTIxKTtcbiAgICByZXR1cm4gWyB4MSArIHVhICogeDIxLCB5MSArIHVhICogeTIxIF07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2x5Z29uQ2xvc2VkKGNvb3JkaW5hdGVzKSB7XG4gICAgdmFyIGEgPSBjb29yZGluYXRlc1swXSwgYiA9IGNvb3JkaW5hdGVzW2Nvb3JkaW5hdGVzLmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiAhKGFbMF0gLSBiWzBdIHx8IGFbMV0gLSBiWzFdKTtcbiAgfVxuICB2YXIgZDNfZ2VvbV92b3Jvbm9pRWRnZXMsIGQzX2dlb21fdm9yb25vaUNlbGxzLCBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLCBkM19nZW9tX3Zvcm9ub2lCZWFjaFBvb2wgPSBbXSwgZDNfZ2VvbV92b3Jvbm9pRmlyc3RDaXJjbGUsIGQzX2dlb21fdm9yb25vaUNpcmNsZXMsIGQzX2dlb21fdm9yb25vaUNpcmNsZVBvb2wgPSBbXTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQmVhY2goKSB7XG4gICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tOb2RlKHRoaXMpO1xuICAgIHRoaXMuZWRnZSA9IHRoaXMuc2l0ZSA9IHRoaXMuY2lyY2xlID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lDcmVhdGVCZWFjaChzaXRlKSB7XG4gICAgdmFyIGJlYWNoID0gZDNfZ2VvbV92b3Jvbm9pQmVhY2hQb29sLnBvcCgpIHx8IG5ldyBkM19nZW9tX3Zvcm9ub2lCZWFjaCgpO1xuICAgIGJlYWNoLnNpdGUgPSBzaXRlO1xuICAgIHJldHVybiBiZWFjaDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChiZWFjaCkge1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShiZWFjaCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcy5yZW1vdmUoYmVhY2gpO1xuICAgIGQzX2dlb21fdm9yb25vaUJlYWNoUG9vbC5wdXNoKGJlYWNoKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUoYmVhY2gpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJlbW92ZUJlYWNoKGJlYWNoKSB7XG4gICAgdmFyIGNpcmNsZSA9IGJlYWNoLmNpcmNsZSwgeCA9IGNpcmNsZS54LCB5ID0gY2lyY2xlLmN5LCB2ZXJ0ZXggPSB7XG4gICAgICB4OiB4LFxuICAgICAgeTogeVxuICAgIH0sIHByZXZpb3VzID0gYmVhY2guUCwgbmV4dCA9IGJlYWNoLk4sIGRpc2FwcGVhcmluZyA9IFsgYmVhY2ggXTtcbiAgICBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChiZWFjaCk7XG4gICAgdmFyIGxBcmMgPSBwcmV2aW91cztcbiAgICB3aGlsZSAobEFyYy5jaXJjbGUgJiYgYWJzKHggLSBsQXJjLmNpcmNsZS54KSA8IM61ICYmIGFicyh5IC0gbEFyYy5jaXJjbGUuY3kpIDwgzrUpIHtcbiAgICAgIHByZXZpb3VzID0gbEFyYy5QO1xuICAgICAgZGlzYXBwZWFyaW5nLnVuc2hpZnQobEFyYyk7XG4gICAgICBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChsQXJjKTtcbiAgICAgIGxBcmMgPSBwcmV2aW91cztcbiAgICB9XG4gICAgZGlzYXBwZWFyaW5nLnVuc2hpZnQobEFyYyk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIHZhciByQXJjID0gbmV4dDtcbiAgICB3aGlsZSAockFyYy5jaXJjbGUgJiYgYWJzKHggLSByQXJjLmNpcmNsZS54KSA8IM61ICYmIGFicyh5IC0gckFyYy5jaXJjbGUuY3kpIDwgzrUpIHtcbiAgICAgIG5leHQgPSByQXJjLk47XG4gICAgICBkaXNhcHBlYXJpbmcucHVzaChyQXJjKTtcbiAgICAgIGQzX2dlb21fdm9yb25vaURldGFjaEJlYWNoKHJBcmMpO1xuICAgICAgckFyYyA9IG5leHQ7XG4gICAgfVxuICAgIGRpc2FwcGVhcmluZy5wdXNoKHJBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShyQXJjKTtcbiAgICB2YXIgbkFyY3MgPSBkaXNhcHBlYXJpbmcubGVuZ3RoLCBpQXJjO1xuICAgIGZvciAoaUFyYyA9IDE7IGlBcmMgPCBuQXJjczsgKytpQXJjKSB7XG4gICAgICByQXJjID0gZGlzYXBwZWFyaW5nW2lBcmNdO1xuICAgICAgbEFyYyA9IGRpc2FwcGVhcmluZ1tpQXJjIC0gMV07XG4gICAgICBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKHJBcmMuZWRnZSwgbEFyYy5zaXRlLCByQXJjLnNpdGUsIHZlcnRleCk7XG4gICAgfVxuICAgIGxBcmMgPSBkaXNhcHBlYXJpbmdbMF07XG4gICAgckFyYyA9IGRpc2FwcGVhcmluZ1tuQXJjcyAtIDFdO1xuICAgIHJBcmMuZWRnZSA9IGQzX2dlb21fdm9yb25vaUNyZWF0ZUVkZ2UobEFyYy5zaXRlLCByQXJjLnNpdGUsIG51bGwsIHZlcnRleCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaUF0dGFjaENpcmNsZShyQXJjKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lBZGRCZWFjaChzaXRlKSB7XG4gICAgdmFyIHggPSBzaXRlLngsIGRpcmVjdHJpeCA9IHNpdGUueSwgbEFyYywgckFyYywgZHhsLCBkeHIsIG5vZGUgPSBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLl87XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgIGR4bCA9IGQzX2dlb21fdm9yb25vaUxlZnRCcmVha1BvaW50KG5vZGUsIGRpcmVjdHJpeCkgLSB4O1xuICAgICAgaWYgKGR4bCA+IM61KSBub2RlID0gbm9kZS5MOyBlbHNlIHtcbiAgICAgICAgZHhyID0geCAtIGQzX2dlb21fdm9yb25vaVJpZ2h0QnJlYWtQb2ludChub2RlLCBkaXJlY3RyaXgpO1xuICAgICAgICBpZiAoZHhyID4gzrUpIHtcbiAgICAgICAgICBpZiAoIW5vZGUuUikge1xuICAgICAgICAgICAgbEFyYyA9IG5vZGU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgbm9kZSA9IG5vZGUuUjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoZHhsID4gLc61KSB7XG4gICAgICAgICAgICBsQXJjID0gbm9kZS5QO1xuICAgICAgICAgICAgckFyYyA9IG5vZGU7XG4gICAgICAgICAgfSBlbHNlIGlmIChkeHIgPiAtzrUpIHtcbiAgICAgICAgICAgIGxBcmMgPSBub2RlO1xuICAgICAgICAgICAgckFyYyA9IG5vZGUuTjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbEFyYyA9IHJBcmMgPSBub2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB2YXIgbmV3QXJjID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlQmVhY2goc2l0ZSk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcy5pbnNlcnQobEFyYywgbmV3QXJjKTtcbiAgICBpZiAoIWxBcmMgJiYgIXJBcmMpIHJldHVybjtcbiAgICBpZiAobEFyYyA9PT0gckFyYykge1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgICAgckFyYyA9IGQzX2dlb21fdm9yb25vaUNyZWF0ZUJlYWNoKGxBcmMuc2l0ZSk7XG4gICAgICBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLmluc2VydChuZXdBcmMsIHJBcmMpO1xuICAgICAgbmV3QXJjLmVkZ2UgPSByQXJjLmVkZ2UgPSBkM19nZW9tX3Zvcm9ub2lDcmVhdGVFZGdlKGxBcmMuc2l0ZSwgbmV3QXJjLnNpdGUpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKGxBcmMpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKHJBcmMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXJBcmMpIHtcbiAgICAgIG5ld0FyYy5lZGdlID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlRWRnZShsQXJjLnNpdGUsIG5ld0FyYy5zaXRlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShyQXJjKTtcbiAgICB2YXIgbFNpdGUgPSBsQXJjLnNpdGUsIGF4ID0gbFNpdGUueCwgYXkgPSBsU2l0ZS55LCBieCA9IHNpdGUueCAtIGF4LCBieSA9IHNpdGUueSAtIGF5LCByU2l0ZSA9IHJBcmMuc2l0ZSwgY3ggPSByU2l0ZS54IC0gYXgsIGN5ID0gclNpdGUueSAtIGF5LCBkID0gMiAqIChieCAqIGN5IC0gYnkgKiBjeCksIGhiID0gYnggKiBieCArIGJ5ICogYnksIGhjID0gY3ggKiBjeCArIGN5ICogY3ksIHZlcnRleCA9IHtcbiAgICAgIHg6IChjeSAqIGhiIC0gYnkgKiBoYykgLyBkICsgYXgsXG4gICAgICB5OiAoYnggKiBoYyAtIGN4ICogaGIpIC8gZCArIGF5XG4gICAgfTtcbiAgICBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKHJBcmMuZWRnZSwgbFNpdGUsIHJTaXRlLCB2ZXJ0ZXgpO1xuICAgIG5ld0FyYy5lZGdlID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlRWRnZShsU2l0ZSwgc2l0ZSwgbnVsbCwgdmVydGV4KTtcbiAgICByQXJjLmVkZ2UgPSBkM19nZW9tX3Zvcm9ub2lDcmVhdGVFZGdlKHNpdGUsIHJTaXRlLCBudWxsLCB2ZXJ0ZXgpO1xuICAgIGQzX2dlb21fdm9yb25vaUF0dGFjaENpcmNsZShsQXJjKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lBdHRhY2hDaXJjbGUockFyYyk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pTGVmdEJyZWFrUG9pbnQoYXJjLCBkaXJlY3RyaXgpIHtcbiAgICB2YXIgc2l0ZSA9IGFyYy5zaXRlLCByZm9jeCA9IHNpdGUueCwgcmZvY3kgPSBzaXRlLnksIHBieTIgPSByZm9jeSAtIGRpcmVjdHJpeDtcbiAgICBpZiAoIXBieTIpIHJldHVybiByZm9jeDtcbiAgICB2YXIgbEFyYyA9IGFyYy5QO1xuICAgIGlmICghbEFyYykgcmV0dXJuIC1JbmZpbml0eTtcbiAgICBzaXRlID0gbEFyYy5zaXRlO1xuICAgIHZhciBsZm9jeCA9IHNpdGUueCwgbGZvY3kgPSBzaXRlLnksIHBsYnkyID0gbGZvY3kgLSBkaXJlY3RyaXg7XG4gICAgaWYgKCFwbGJ5MikgcmV0dXJuIGxmb2N4O1xuICAgIHZhciBobCA9IGxmb2N4IC0gcmZvY3gsIGFieTIgPSAxIC8gcGJ5MiAtIDEgLyBwbGJ5MiwgYiA9IGhsIC8gcGxieTI7XG4gICAgaWYgKGFieTIpIHJldHVybiAoLWIgKyBNYXRoLnNxcnQoYiAqIGIgLSAyICogYWJ5MiAqIChobCAqIGhsIC8gKC0yICogcGxieTIpIC0gbGZvY3kgKyBwbGJ5MiAvIDIgKyByZm9jeSAtIHBieTIgLyAyKSkpIC8gYWJ5MiArIHJmb2N4O1xuICAgIHJldHVybiAocmZvY3ggKyBsZm9jeCkgLyAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJpZ2h0QnJlYWtQb2ludChhcmMsIGRpcmVjdHJpeCkge1xuICAgIHZhciByQXJjID0gYXJjLk47XG4gICAgaWYgKHJBcmMpIHJldHVybiBkM19nZW9tX3Zvcm9ub2lMZWZ0QnJlYWtQb2ludChyQXJjLCBkaXJlY3RyaXgpO1xuICAgIHZhciBzaXRlID0gYXJjLnNpdGU7XG4gICAgcmV0dXJuIHNpdGUueSA9PT0gZGlyZWN0cml4ID8gc2l0ZS54IDogSW5maW5pdHk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQ2VsbChzaXRlKSB7XG4gICAgdGhpcy5zaXRlID0gc2l0ZTtcbiAgICB0aGlzLmVkZ2VzID0gW107XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pQ2VsbC5wcm90b3R5cGUucHJlcGFyZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoYWxmRWRnZXMgPSB0aGlzLmVkZ2VzLCBpSGFsZkVkZ2UgPSBoYWxmRWRnZXMubGVuZ3RoLCBlZGdlO1xuICAgIHdoaWxlIChpSGFsZkVkZ2UtLSkge1xuICAgICAgZWRnZSA9IGhhbGZFZGdlc1tpSGFsZkVkZ2VdLmVkZ2U7XG4gICAgICBpZiAoIWVkZ2UuYiB8fCAhZWRnZS5hKSBoYWxmRWRnZXMuc3BsaWNlKGlIYWxmRWRnZSwgMSk7XG4gICAgfVxuICAgIGhhbGZFZGdlcy5zb3J0KGQzX2dlb21fdm9yb25vaUhhbGZFZGdlT3JkZXIpO1xuICAgIHJldHVybiBoYWxmRWRnZXMubGVuZ3RoO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lDbG9zZUNlbGxzKGV4dGVudCkge1xuICAgIHZhciB4MCA9IGV4dGVudFswXVswXSwgeDEgPSBleHRlbnRbMV1bMF0sIHkwID0gZXh0ZW50WzBdWzFdLCB5MSA9IGV4dGVudFsxXVsxXSwgeDIsIHkyLCB4MywgeTMsIGNlbGxzID0gZDNfZ2VvbV92b3Jvbm9pQ2VsbHMsIGlDZWxsID0gY2VsbHMubGVuZ3RoLCBjZWxsLCBpSGFsZkVkZ2UsIGhhbGZFZGdlcywgbkhhbGZFZGdlcywgc3RhcnQsIGVuZDtcbiAgICB3aGlsZSAoaUNlbGwtLSkge1xuICAgICAgY2VsbCA9IGNlbGxzW2lDZWxsXTtcbiAgICAgIGlmICghY2VsbCB8fCAhY2VsbC5wcmVwYXJlKCkpIGNvbnRpbnVlO1xuICAgICAgaGFsZkVkZ2VzID0gY2VsbC5lZGdlcztcbiAgICAgIG5IYWxmRWRnZXMgPSBoYWxmRWRnZXMubGVuZ3RoO1xuICAgICAgaUhhbGZFZGdlID0gMDtcbiAgICAgIHdoaWxlIChpSGFsZkVkZ2UgPCBuSGFsZkVkZ2VzKSB7XG4gICAgICAgIGVuZCA9IGhhbGZFZGdlc1tpSGFsZkVkZ2VdLmVuZCgpLCB4MyA9IGVuZC54LCB5MyA9IGVuZC55O1xuICAgICAgICBzdGFydCA9IGhhbGZFZGdlc1srK2lIYWxmRWRnZSAlIG5IYWxmRWRnZXNdLnN0YXJ0KCksIHgyID0gc3RhcnQueCwgeTIgPSBzdGFydC55O1xuICAgICAgICBpZiAoYWJzKHgzIC0geDIpID4gzrUgfHwgYWJzKHkzIC0geTIpID4gzrUpIHtcbiAgICAgICAgICBoYWxmRWRnZXMuc3BsaWNlKGlIYWxmRWRnZSwgMCwgbmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGQzX2dlb21fdm9yb25vaUNyZWF0ZUJvcmRlckVkZ2UoY2VsbC5zaXRlLCBlbmQsIGFicyh4MyAtIHgwKSA8IM61ICYmIHkxIC0geTMgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IHgwLFxuICAgICAgICAgICAgeTogYWJzKHgyIC0geDApIDwgzrUgPyB5MiA6IHkxXG4gICAgICAgICAgfSA6IGFicyh5MyAtIHkxKSA8IM61ICYmIHgxIC0geDMgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IGFicyh5MiAtIHkxKSA8IM61ID8geDIgOiB4MSxcbiAgICAgICAgICAgIHk6IHkxXG4gICAgICAgICAgfSA6IGFicyh4MyAtIHgxKSA8IM61ICYmIHkzIC0geTAgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogYWJzKHgyIC0geDEpIDwgzrUgPyB5MiA6IHkwXG4gICAgICAgICAgfSA6IGFicyh5MyAtIHkwKSA8IM61ICYmIHgzIC0geDAgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IGFicyh5MiAtIHkwKSA8IM61ID8geDIgOiB4MCxcbiAgICAgICAgICAgIHk6IHkwXG4gICAgICAgICAgfSA6IG51bGwpLCBjZWxsLnNpdGUsIG51bGwpKTtcbiAgICAgICAgICArK25IYWxmRWRnZXM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2VPcmRlcihhLCBiKSB7XG4gICAgcmV0dXJuIGIuYW5nbGUgLSBhLmFuZ2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNpcmNsZSgpIHtcbiAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUodGhpcyk7XG4gICAgdGhpcy54ID0gdGhpcy55ID0gdGhpcy5hcmMgPSB0aGlzLnNpdGUgPSB0aGlzLmN5ID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lBdHRhY2hDaXJjbGUoYXJjKSB7XG4gICAgdmFyIGxBcmMgPSBhcmMuUCwgckFyYyA9IGFyYy5OO1xuICAgIGlmICghbEFyYyB8fCAhckFyYykgcmV0dXJuO1xuICAgIHZhciBsU2l0ZSA9IGxBcmMuc2l0ZSwgY1NpdGUgPSBhcmMuc2l0ZSwgclNpdGUgPSByQXJjLnNpdGU7XG4gICAgaWYgKGxTaXRlID09PSByU2l0ZSkgcmV0dXJuO1xuICAgIHZhciBieCA9IGNTaXRlLngsIGJ5ID0gY1NpdGUueSwgYXggPSBsU2l0ZS54IC0gYngsIGF5ID0gbFNpdGUueSAtIGJ5LCBjeCA9IHJTaXRlLnggLSBieCwgY3kgPSByU2l0ZS55IC0gYnk7XG4gICAgdmFyIGQgPSAyICogKGF4ICogY3kgLSBheSAqIGN4KTtcbiAgICBpZiAoZCA+PSAtzrUyKSByZXR1cm47XG4gICAgdmFyIGhhID0gYXggKiBheCArIGF5ICogYXksIGhjID0gY3ggKiBjeCArIGN5ICogY3ksIHggPSAoY3kgKiBoYSAtIGF5ICogaGMpIC8gZCwgeSA9IChheCAqIGhjIC0gY3ggKiBoYSkgLyBkLCBjeSA9IHkgKyBieTtcbiAgICB2YXIgY2lyY2xlID0gZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlUG9vbC5wb3AoKSB8fCBuZXcgZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlKCk7XG4gICAgY2lyY2xlLmFyYyA9IGFyYztcbiAgICBjaXJjbGUuc2l0ZSA9IGNTaXRlO1xuICAgIGNpcmNsZS54ID0geCArIGJ4O1xuICAgIGNpcmNsZS55ID0gY3kgKyBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgY2lyY2xlLmN5ID0gY3k7XG4gICAgYXJjLmNpcmNsZSA9IGNpcmNsZTtcbiAgICB2YXIgYmVmb3JlID0gbnVsbCwgbm9kZSA9IGQzX2dlb21fdm9yb25vaUNpcmNsZXMuXztcbiAgICB3aGlsZSAobm9kZSkge1xuICAgICAgaWYgKGNpcmNsZS55IDwgbm9kZS55IHx8IGNpcmNsZS55ID09PSBub2RlLnkgJiYgY2lyY2xlLnggPD0gbm9kZS54KSB7XG4gICAgICAgIGlmIChub2RlLkwpIG5vZGUgPSBub2RlLkw7IGVsc2Uge1xuICAgICAgICAgIGJlZm9yZSA9IG5vZGUuUDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKG5vZGUuUikgbm9kZSA9IG5vZGUuUjsgZWxzZSB7XG4gICAgICAgICAgYmVmb3JlID0gbm9kZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzLmluc2VydChiZWZvcmUsIGNpcmNsZSk7XG4gICAgaWYgKCFiZWZvcmUpIGQzX2dlb21fdm9yb25vaUZpcnN0Q2lyY2xlID0gY2lyY2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShhcmMpIHtcbiAgICB2YXIgY2lyY2xlID0gYXJjLmNpcmNsZTtcbiAgICBpZiAoY2lyY2xlKSB7XG4gICAgICBpZiAoIWNpcmNsZS5QKSBkM19nZW9tX3Zvcm9ub2lGaXJzdENpcmNsZSA9IGNpcmNsZS5OO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlcy5yZW1vdmUoY2lyY2xlKTtcbiAgICAgIGQzX2dlb21fdm9yb25vaUNpcmNsZVBvb2wucHVzaChjaXJjbGUpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tOb2RlKGNpcmNsZSk7XG4gICAgICBhcmMuY2lyY2xlID0gbnVsbDtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQ2xpcEVkZ2VzKGV4dGVudCkge1xuICAgIHZhciBlZGdlcyA9IGQzX2dlb21fdm9yb25vaUVkZ2VzLCBjbGlwID0gZDNfZ2VvbV9jbGlwTGluZShleHRlbnRbMF1bMF0sIGV4dGVudFswXVsxXSwgZXh0ZW50WzFdWzBdLCBleHRlbnRbMV1bMV0pLCBpID0gZWRnZXMubGVuZ3RoLCBlO1xuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgIGUgPSBlZGdlc1tpXTtcbiAgICAgIGlmICghZDNfZ2VvbV92b3Jvbm9pQ29ubmVjdEVkZ2UoZSwgZXh0ZW50KSB8fCAhY2xpcChlKSB8fCBhYnMoZS5hLnggLSBlLmIueCkgPCDOtSAmJiBhYnMoZS5hLnkgLSBlLmIueSkgPCDOtSkge1xuICAgICAgICBlLmEgPSBlLmIgPSBudWxsO1xuICAgICAgICBlZGdlcy5zcGxpY2UoaSwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNvbm5lY3RFZGdlKGVkZ2UsIGV4dGVudCkge1xuICAgIHZhciB2YiA9IGVkZ2UuYjtcbiAgICBpZiAodmIpIHJldHVybiB0cnVlO1xuICAgIHZhciB2YSA9IGVkZ2UuYSwgeDAgPSBleHRlbnRbMF1bMF0sIHgxID0gZXh0ZW50WzFdWzBdLCB5MCA9IGV4dGVudFswXVsxXSwgeTEgPSBleHRlbnRbMV1bMV0sIGxTaXRlID0gZWRnZS5sLCByU2l0ZSA9IGVkZ2UuciwgbHggPSBsU2l0ZS54LCBseSA9IGxTaXRlLnksIHJ4ID0gclNpdGUueCwgcnkgPSByU2l0ZS55LCBmeCA9IChseCArIHJ4KSAvIDIsIGZ5ID0gKGx5ICsgcnkpIC8gMiwgZm0sIGZiO1xuICAgIGlmIChyeSA9PT0gbHkpIHtcbiAgICAgIGlmIChmeCA8IHgwIHx8IGZ4ID49IHgxKSByZXR1cm47XG4gICAgICBpZiAobHggPiByeCkge1xuICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICB4OiBmeCxcbiAgICAgICAgICB5OiB5MFxuICAgICAgICB9OyBlbHNlIGlmICh2YS55ID49IHkxKSByZXR1cm47XG4gICAgICAgIHZiID0ge1xuICAgICAgICAgIHg6IGZ4LFxuICAgICAgICAgIHk6IHkxXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICB4OiBmeCxcbiAgICAgICAgICB5OiB5MVxuICAgICAgICB9OyBlbHNlIGlmICh2YS55IDwgeTApIHJldHVybjtcbiAgICAgICAgdmIgPSB7XG4gICAgICAgICAgeDogZngsXG4gICAgICAgICAgeTogeTBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm0gPSAobHggLSByeCkgLyAocnkgLSBseSk7XG4gICAgICBmYiA9IGZ5IC0gZm0gKiBmeDtcbiAgICAgIGlmIChmbSA8IC0xIHx8IGZtID4gMSkge1xuICAgICAgICBpZiAobHggPiByeCkge1xuICAgICAgICAgIGlmICghdmEpIHZhID0ge1xuICAgICAgICAgICAgeDogKHkwIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MFxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnkgPj0geTEpIHJldHVybjtcbiAgICAgICAgICB2YiA9IHtcbiAgICAgICAgICAgIHg6ICh5MSAtIGZiKSAvIGZtLFxuICAgICAgICAgICAgeTogeTFcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghdmEpIHZhID0ge1xuICAgICAgICAgICAgeDogKHkxIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MVxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnkgPCB5MCkgcmV0dXJuO1xuICAgICAgICAgIHZiID0ge1xuICAgICAgICAgICAgeDogKHkwIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChseSA8IHJ5KSB7XG4gICAgICAgICAgaWYgKCF2YSkgdmEgPSB7XG4gICAgICAgICAgICB4OiB4MCxcbiAgICAgICAgICAgIHk6IGZtICogeDAgKyBmYlxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnggPj0geDEpIHJldHVybjtcbiAgICAgICAgICB2YiA9IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogZm0gKiB4MSArIGZiXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogZm0gKiB4MSArIGZiXG4gICAgICAgICAgfTsgZWxzZSBpZiAodmEueCA8IHgwKSByZXR1cm47XG4gICAgICAgICAgdmIgPSB7XG4gICAgICAgICAgICB4OiB4MCxcbiAgICAgICAgICAgIHk6IGZtICogeDAgKyBmYlxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWRnZS5hID0gdmE7XG4gICAgZWRnZS5iID0gdmI7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pRWRnZShsU2l0ZSwgclNpdGUpIHtcbiAgICB0aGlzLmwgPSBsU2l0ZTtcbiAgICB0aGlzLnIgPSByU2l0ZTtcbiAgICB0aGlzLmEgPSB0aGlzLmIgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNyZWF0ZUVkZ2UobFNpdGUsIHJTaXRlLCB2YSwgdmIpIHtcbiAgICB2YXIgZWRnZSA9IG5ldyBkM19nZW9tX3Zvcm9ub2lFZGdlKGxTaXRlLCByU2l0ZSk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pRWRnZXMucHVzaChlZGdlKTtcbiAgICBpZiAodmEpIGQzX2dlb21fdm9yb25vaVNldEVkZ2VFbmQoZWRnZSwgbFNpdGUsIHJTaXRlLCB2YSk7XG4gICAgaWYgKHZiKSBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKGVkZ2UsIHJTaXRlLCBsU2l0ZSwgdmIpO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzW2xTaXRlLmldLmVkZ2VzLnB1c2gobmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGVkZ2UsIGxTaXRlLCByU2l0ZSkpO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzW3JTaXRlLmldLmVkZ2VzLnB1c2gobmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGVkZ2UsIHJTaXRlLCBsU2l0ZSkpO1xuICAgIHJldHVybiBlZGdlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNyZWF0ZUJvcmRlckVkZ2UobFNpdGUsIHZhLCB2Yikge1xuICAgIHZhciBlZGdlID0gbmV3IGQzX2dlb21fdm9yb25vaUVkZ2UobFNpdGUsIG51bGwpO1xuICAgIGVkZ2UuYSA9IHZhO1xuICAgIGVkZ2UuYiA9IHZiO1xuICAgIGQzX2dlb21fdm9yb25vaUVkZ2VzLnB1c2goZWRnZSk7XG4gICAgcmV0dXJuIGVkZ2U7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pU2V0RWRnZUVuZChlZGdlLCBsU2l0ZSwgclNpdGUsIHZlcnRleCkge1xuICAgIGlmICghZWRnZS5hICYmICFlZGdlLmIpIHtcbiAgICAgIGVkZ2UuYSA9IHZlcnRleDtcbiAgICAgIGVkZ2UubCA9IGxTaXRlO1xuICAgICAgZWRnZS5yID0gclNpdGU7XG4gICAgfSBlbHNlIGlmIChlZGdlLmwgPT09IHJTaXRlKSB7XG4gICAgICBlZGdlLmIgPSB2ZXJ0ZXg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVkZ2UuYSA9IHZlcnRleDtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2UoZWRnZSwgbFNpdGUsIHJTaXRlKSB7XG4gICAgdmFyIHZhID0gZWRnZS5hLCB2YiA9IGVkZ2UuYjtcbiAgICB0aGlzLmVkZ2UgPSBlZGdlO1xuICAgIHRoaXMuc2l0ZSA9IGxTaXRlO1xuICAgIHRoaXMuYW5nbGUgPSByU2l0ZSA/IE1hdGguYXRhbjIoclNpdGUueSAtIGxTaXRlLnksIHJTaXRlLnggLSBsU2l0ZS54KSA6IGVkZ2UubCA9PT0gbFNpdGUgPyBNYXRoLmF0YW4yKHZiLnggLSB2YS54LCB2YS55IC0gdmIueSkgOiBNYXRoLmF0YW4yKHZhLnggLSB2Yi54LCB2Yi55IC0gdmEueSk7XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2UucHJvdG90eXBlID0ge1xuICAgIHN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmVkZ2UubCA9PT0gdGhpcy5zaXRlID8gdGhpcy5lZGdlLmEgOiB0aGlzLmVkZ2UuYjtcbiAgICB9LFxuICAgIGVuZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5lZGdlLmwgPT09IHRoaXMuc2l0ZSA/IHRoaXMuZWRnZS5iIDogdGhpcy5lZGdlLmE7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1RyZWUoKSB7XG4gICAgdGhpcy5fID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUobm9kZSkge1xuICAgIG5vZGUuVSA9IG5vZGUuQyA9IG5vZGUuTCA9IG5vZGUuUiA9IG5vZGUuUCA9IG5vZGUuTiA9IG51bGw7XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tUcmVlLnByb3RvdHlwZSA9IHtcbiAgICBpbnNlcnQ6IGZ1bmN0aW9uKGFmdGVyLCBub2RlKSB7XG4gICAgICB2YXIgcGFyZW50LCBncmFuZHBhLCB1bmNsZTtcbiAgICAgIGlmIChhZnRlcikge1xuICAgICAgICBub2RlLlAgPSBhZnRlcjtcbiAgICAgICAgbm9kZS5OID0gYWZ0ZXIuTjtcbiAgICAgICAgaWYgKGFmdGVyLk4pIGFmdGVyLk4uUCA9IG5vZGU7XG4gICAgICAgIGFmdGVyLk4gPSBub2RlO1xuICAgICAgICBpZiAoYWZ0ZXIuUikge1xuICAgICAgICAgIGFmdGVyID0gYWZ0ZXIuUjtcbiAgICAgICAgICB3aGlsZSAoYWZ0ZXIuTCkgYWZ0ZXIgPSBhZnRlci5MO1xuICAgICAgICAgIGFmdGVyLkwgPSBub2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFmdGVyLlIgPSBub2RlO1xuICAgICAgICB9XG4gICAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl8pIHtcbiAgICAgICAgYWZ0ZXIgPSBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja0ZpcnN0KHRoaXMuXyk7XG4gICAgICAgIG5vZGUuUCA9IG51bGw7XG4gICAgICAgIG5vZGUuTiA9IGFmdGVyO1xuICAgICAgICBhZnRlci5QID0gYWZ0ZXIuTCA9IG5vZGU7XG4gICAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5QID0gbm9kZS5OID0gbnVsbDtcbiAgICAgICAgdGhpcy5fID0gbm9kZTtcbiAgICAgICAgcGFyZW50ID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIG5vZGUuTCA9IG5vZGUuUiA9IG51bGw7XG4gICAgICBub2RlLlUgPSBwYXJlbnQ7XG4gICAgICBub2RlLkMgPSB0cnVlO1xuICAgICAgYWZ0ZXIgPSBub2RlO1xuICAgICAgd2hpbGUgKHBhcmVudCAmJiBwYXJlbnQuQykge1xuICAgICAgICBncmFuZHBhID0gcGFyZW50LlU7XG4gICAgICAgIGlmIChwYXJlbnQgPT09IGdyYW5kcGEuTCkge1xuICAgICAgICAgIHVuY2xlID0gZ3JhbmRwYS5SO1xuICAgICAgICAgIGlmICh1bmNsZSAmJiB1bmNsZS5DKSB7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHVuY2xlLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgICBhZnRlciA9IGdyYW5kcGE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChhZnRlciA9PT0gcGFyZW50LlIpIHtcbiAgICAgICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHBhcmVudCk7XG4gICAgICAgICAgICAgIGFmdGVyID0gcGFyZW50O1xuICAgICAgICAgICAgICBwYXJlbnQgPSBhZnRlci5VO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyZW50LkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIGdyYW5kcGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1bmNsZSA9IGdyYW5kcGEuTDtcbiAgICAgICAgICBpZiAodW5jbGUgJiYgdW5jbGUuQykge1xuICAgICAgICAgICAgcGFyZW50LkMgPSB1bmNsZS5DID0gZmFsc2U7XG4gICAgICAgICAgICBncmFuZHBhLkMgPSB0cnVlO1xuICAgICAgICAgICAgYWZ0ZXIgPSBncmFuZHBhO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoYWZ0ZXIgPT09IHBhcmVudC5MKSB7XG4gICAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlUmlnaHQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgICAgYWZ0ZXIgPSBwYXJlbnQ7XG4gICAgICAgICAgICAgIHBhcmVudCA9IGFmdGVyLlU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJlbnQuQyA9IGZhbHNlO1xuICAgICAgICAgICAgZ3JhbmRwYS5DID0gdHJ1ZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0aGlzLCBncmFuZHBhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50ID0gYWZ0ZXIuVTtcbiAgICAgIH1cbiAgICAgIHRoaXMuXy5DID0gZmFsc2U7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGlmIChub2RlLk4pIG5vZGUuTi5QID0gbm9kZS5QO1xuICAgICAgaWYgKG5vZGUuUCkgbm9kZS5QLk4gPSBub2RlLk47XG4gICAgICBub2RlLk4gPSBub2RlLlAgPSBudWxsO1xuICAgICAgdmFyIHBhcmVudCA9IG5vZGUuVSwgc2libGluZywgbGVmdCA9IG5vZGUuTCwgcmlnaHQgPSBub2RlLlIsIG5leHQsIHJlZDtcbiAgICAgIGlmICghbGVmdCkgbmV4dCA9IHJpZ2h0OyBlbHNlIGlmICghcmlnaHQpIG5leHQgPSBsZWZ0OyBlbHNlIG5leHQgPSBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja0ZpcnN0KHJpZ2h0KTtcbiAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgaWYgKHBhcmVudC5MID09PSBub2RlKSBwYXJlbnQuTCA9IG5leHQ7IGVsc2UgcGFyZW50LlIgPSBuZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fID0gbmV4dDtcbiAgICAgIH1cbiAgICAgIGlmIChsZWZ0ICYmIHJpZ2h0KSB7XG4gICAgICAgIHJlZCA9IG5leHQuQztcbiAgICAgICAgbmV4dC5DID0gbm9kZS5DO1xuICAgICAgICBuZXh0LkwgPSBsZWZ0O1xuICAgICAgICBsZWZ0LlUgPSBuZXh0O1xuICAgICAgICBpZiAobmV4dCAhPT0gcmlnaHQpIHtcbiAgICAgICAgICBwYXJlbnQgPSBuZXh0LlU7XG4gICAgICAgICAgbmV4dC5VID0gbm9kZS5VO1xuICAgICAgICAgIG5vZGUgPSBuZXh0LlI7XG4gICAgICAgICAgcGFyZW50LkwgPSBub2RlO1xuICAgICAgICAgIG5leHQuUiA9IHJpZ2h0O1xuICAgICAgICAgIHJpZ2h0LlUgPSBuZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQuVSA9IHBhcmVudDtcbiAgICAgICAgICBwYXJlbnQgPSBuZXh0O1xuICAgICAgICAgIG5vZGUgPSBuZXh0LlI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlZCA9IG5vZGUuQztcbiAgICAgICAgbm9kZSA9IG5leHQ7XG4gICAgICB9XG4gICAgICBpZiAobm9kZSkgbm9kZS5VID0gcGFyZW50O1xuICAgICAgaWYgKHJlZCkgcmV0dXJuO1xuICAgICAgaWYgKG5vZGUgJiYgbm9kZS5DKSB7XG4gICAgICAgIG5vZGUuQyA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkbyB7XG4gICAgICAgIGlmIChub2RlID09PSB0aGlzLl8pIGJyZWFrO1xuICAgICAgICBpZiAobm9kZSA9PT0gcGFyZW50LkwpIHtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50LlI7XG4gICAgICAgICAgaWYgKHNpYmxpbmcuQykge1xuICAgICAgICAgICAgc2libGluZy5DID0gZmFsc2U7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZUxlZnQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgIHNpYmxpbmcgPSBwYXJlbnQuUjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNpYmxpbmcuTCAmJiBzaWJsaW5nLkwuQyB8fCBzaWJsaW5nLlIgJiYgc2libGluZy5SLkMpIHtcbiAgICAgICAgICAgIGlmICghc2libGluZy5SIHx8ICFzaWJsaW5nLlIuQykge1xuICAgICAgICAgICAgICBzaWJsaW5nLkwuQyA9IGZhbHNlO1xuICAgICAgICAgICAgICBzaWJsaW5nLkMgPSB0cnVlO1xuICAgICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50LlI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICAgIHBhcmVudC5DID0gc2libGluZy5SLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0aGlzLCBwYXJlbnQpO1xuICAgICAgICAgICAgbm9kZSA9IHRoaXMuXztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgaWYgKHNpYmxpbmcuQykge1xuICAgICAgICAgICAgc2libGluZy5DID0gZmFsc2U7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIHBhcmVudCk7XG4gICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzaWJsaW5nLkwgJiYgc2libGluZy5MLkMgfHwgc2libGluZy5SICYmIHNpYmxpbmcuUi5DKSB7XG4gICAgICAgICAgICBpZiAoIXNpYmxpbmcuTCB8fCAhc2libGluZy5MLkMpIHtcbiAgICAgICAgICAgICAgc2libGluZy5SLkMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgc2libGluZy5DID0gdHJ1ZTtcbiAgICAgICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICAgIHBhcmVudC5DID0gc2libGluZy5MLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlUmlnaHQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgIG5vZGUgPSB0aGlzLl87XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2libGluZy5DID0gdHJ1ZTtcbiAgICAgICAgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgcGFyZW50ID0gcGFyZW50LlU7XG4gICAgICB9IHdoaWxlICghbm9kZS5DKTtcbiAgICAgIGlmIChub2RlKSBub2RlLkMgPSBmYWxzZTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0cmVlLCBub2RlKSB7XG4gICAgdmFyIHAgPSBub2RlLCBxID0gbm9kZS5SLCBwYXJlbnQgPSBwLlU7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgaWYgKHBhcmVudC5MID09PSBwKSBwYXJlbnQuTCA9IHE7IGVsc2UgcGFyZW50LlIgPSBxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmVlLl8gPSBxO1xuICAgIH1cbiAgICBxLlUgPSBwYXJlbnQ7XG4gICAgcC5VID0gcTtcbiAgICBwLlIgPSBxLkw7XG4gICAgaWYgKHAuUikgcC5SLlUgPSBwO1xuICAgIHEuTCA9IHA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVSaWdodCh0cmVlLCBub2RlKSB7XG4gICAgdmFyIHAgPSBub2RlLCBxID0gbm9kZS5MLCBwYXJlbnQgPSBwLlU7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgaWYgKHBhcmVudC5MID09PSBwKSBwYXJlbnQuTCA9IHE7IGVsc2UgcGFyZW50LlIgPSBxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmVlLl8gPSBxO1xuICAgIH1cbiAgICBxLlUgPSBwYXJlbnQ7XG4gICAgcC5VID0gcTtcbiAgICBwLkwgPSBxLlI7XG4gICAgaWYgKHAuTCkgcC5MLlUgPSBwO1xuICAgIHEuUiA9IHA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tGaXJzdChub2RlKSB7XG4gICAgd2hpbGUgKG5vZGUuTCkgbm9kZSA9IG5vZGUuTDtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2koc2l0ZXMsIGJib3gpIHtcbiAgICB2YXIgc2l0ZSA9IHNpdGVzLnNvcnQoZDNfZ2VvbV92b3Jvbm9pVmVydGV4T3JkZXIpLnBvcCgpLCB4MCwgeTAsIGNpcmNsZTtcbiAgICBkM19nZW9tX3Zvcm9ub2lFZGdlcyA9IFtdO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzID0gbmV3IEFycmF5KHNpdGVzLmxlbmd0aCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcyA9IG5ldyBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1RyZWUoKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzID0gbmV3IGQzX2dlb21fdm9yb25vaVJlZEJsYWNrVHJlZSgpO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjaXJjbGUgPSBkM19nZW9tX3Zvcm9ub2lGaXJzdENpcmNsZTtcbiAgICAgIGlmIChzaXRlICYmICghY2lyY2xlIHx8IHNpdGUueSA8IGNpcmNsZS55IHx8IHNpdGUueSA9PT0gY2lyY2xlLnkgJiYgc2l0ZS54IDwgY2lyY2xlLngpKSB7XG4gICAgICAgIGlmIChzaXRlLnggIT09IHgwIHx8IHNpdGUueSAhPT0geTApIHtcbiAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lDZWxsc1tzaXRlLmldID0gbmV3IGQzX2dlb21fdm9yb25vaUNlbGwoc2l0ZSk7XG4gICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pQWRkQmVhY2goc2l0ZSk7XG4gICAgICAgICAgeDAgPSBzaXRlLngsIHkwID0gc2l0ZS55O1xuICAgICAgICB9XG4gICAgICAgIHNpdGUgPSBzaXRlcy5wb3AoKTtcbiAgICAgIH0gZWxzZSBpZiAoY2lyY2xlKSB7XG4gICAgICAgIGQzX2dlb21fdm9yb25vaVJlbW92ZUJlYWNoKGNpcmNsZS5hcmMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChiYm94KSBkM19nZW9tX3Zvcm9ub2lDbGlwRWRnZXMoYmJveCksIGQzX2dlb21fdm9yb25vaUNsb3NlQ2VsbHMoYmJveCk7XG4gICAgdmFyIGRpYWdyYW0gPSB7XG4gICAgICBjZWxsczogZDNfZ2VvbV92b3Jvbm9pQ2VsbHMsXG4gICAgICBlZGdlczogZDNfZ2VvbV92b3Jvbm9pRWRnZXNcbiAgICB9O1xuICAgIGQzX2dlb21fdm9yb25vaUJlYWNoZXMgPSBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzID0gZDNfZ2VvbV92b3Jvbm9pRWRnZXMgPSBkM19nZW9tX3Zvcm9ub2lDZWxscyA9IG51bGw7XG4gICAgcmV0dXJuIGRpYWdyYW07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pVmVydGV4T3JkZXIoYSwgYikge1xuICAgIHJldHVybiBiLnkgLSBhLnkgfHwgYi54IC0gYS54O1xuICB9XG4gIGQzLmdlb20udm9yb25vaSA9IGZ1bmN0aW9uKHBvaW50cykge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WSwgZnggPSB4LCBmeSA9IHksIGNsaXBFeHRlbnQgPSBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50O1xuICAgIGlmIChwb2ludHMpIHJldHVybiB2b3Jvbm9pKHBvaW50cyk7XG4gICAgZnVuY3Rpb24gdm9yb25vaShkYXRhKSB7XG4gICAgICB2YXIgcG9seWdvbnMgPSBuZXcgQXJyYXkoZGF0YS5sZW5ndGgpLCB4MCA9IGNsaXBFeHRlbnRbMF1bMF0sIHkwID0gY2xpcEV4dGVudFswXVsxXSwgeDEgPSBjbGlwRXh0ZW50WzFdWzBdLCB5MSA9IGNsaXBFeHRlbnRbMV1bMV07XG4gICAgICBkM19nZW9tX3Zvcm9ub2koc2l0ZXMoZGF0YSksIGNsaXBFeHRlbnQpLmNlbGxzLmZvckVhY2goZnVuY3Rpb24oY2VsbCwgaSkge1xuICAgICAgICB2YXIgZWRnZXMgPSBjZWxsLmVkZ2VzLCBzaXRlID0gY2VsbC5zaXRlLCBwb2x5Z29uID0gcG9seWdvbnNbaV0gPSBlZGdlcy5sZW5ndGggPyBlZGdlcy5tYXAoZnVuY3Rpb24oZSkge1xuICAgICAgICAgIHZhciBzID0gZS5zdGFydCgpO1xuICAgICAgICAgIHJldHVybiBbIHMueCwgcy55IF07XG4gICAgICAgIH0pIDogc2l0ZS54ID49IHgwICYmIHNpdGUueCA8PSB4MSAmJiBzaXRlLnkgPj0geTAgJiYgc2l0ZS55IDw9IHkxID8gWyBbIHgwLCB5MSBdLCBbIHgxLCB5MSBdLCBbIHgxLCB5MCBdLCBbIHgwLCB5MCBdIF0gOiBbXTtcbiAgICAgICAgcG9seWdvbi5wb2ludCA9IGRhdGFbaV07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBwb2x5Z29ucztcbiAgICB9XG4gICAgZnVuY3Rpb24gc2l0ZXMoZGF0YSkge1xuICAgICAgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB4OiBNYXRoLnJvdW5kKGZ4KGQsIGkpIC8gzrUpICogzrUsXG4gICAgICAgICAgeTogTWF0aC5yb3VuZChmeShkLCBpKSAvIM61KSAqIM61LFxuICAgICAgICAgIGk6IGlcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB2b3Jvbm9pLmxpbmtzID0gZnVuY3Rpb24oZGF0YSkge1xuICAgICAgcmV0dXJuIGQzX2dlb21fdm9yb25vaShzaXRlcyhkYXRhKSkuZWRnZXMuZmlsdGVyKGZ1bmN0aW9uKGVkZ2UpIHtcbiAgICAgICAgcmV0dXJuIGVkZ2UubCAmJiBlZGdlLnI7XG4gICAgICB9KS5tYXAoZnVuY3Rpb24oZWRnZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHNvdXJjZTogZGF0YVtlZGdlLmwuaV0sXG4gICAgICAgICAgdGFyZ2V0OiBkYXRhW2VkZ2Uuci5pXVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfTtcbiAgICB2b3Jvbm9pLnRyaWFuZ2xlcyA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHZhciB0cmlhbmdsZXMgPSBbXTtcbiAgICAgIGQzX2dlb21fdm9yb25vaShzaXRlcyhkYXRhKSkuY2VsbHMuZm9yRWFjaChmdW5jdGlvbihjZWxsLCBpKSB7XG4gICAgICAgIHZhciBzaXRlID0gY2VsbC5zaXRlLCBlZGdlcyA9IGNlbGwuZWRnZXMuc29ydChkM19nZW9tX3Zvcm9ub2lIYWxmRWRnZU9yZGVyKSwgaiA9IC0xLCBtID0gZWRnZXMubGVuZ3RoLCBlMCwgczAsIGUxID0gZWRnZXNbbSAtIDFdLmVkZ2UsIHMxID0gZTEubCA9PT0gc2l0ZSA/IGUxLnIgOiBlMS5sO1xuICAgICAgICB3aGlsZSAoKytqIDwgbSkge1xuICAgICAgICAgIGUwID0gZTE7XG4gICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICBlMSA9IGVkZ2VzW2pdLmVkZ2U7XG4gICAgICAgICAgczEgPSBlMS5sID09PSBzaXRlID8gZTEuciA6IGUxLmw7XG4gICAgICAgICAgaWYgKGkgPCBzMC5pICYmIGkgPCBzMS5pICYmIGQzX2dlb21fdm9yb25vaVRyaWFuZ2xlQXJlYShzaXRlLCBzMCwgczEpIDwgMCkge1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goWyBkYXRhW2ldLCBkYXRhW3MwLmldLCBkYXRhW3MxLmldIF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdHJpYW5nbGVzO1xuICAgIH07XG4gICAgdm9yb25vaS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZnggPSBkM19mdW5jdG9yKHggPSBfKSwgdm9yb25vaSkgOiB4O1xuICAgIH07XG4gICAgdm9yb25vaS55ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZnkgPSBkM19mdW5jdG9yKHkgPSBfKSwgdm9yb25vaSkgOiB5O1xuICAgIH07XG4gICAgdm9yb25vaS5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEV4dGVudCA9PT0gZDNfZ2VvbV92b3Jvbm9pQ2xpcEV4dGVudCA/IG51bGwgOiBjbGlwRXh0ZW50O1xuICAgICAgY2xpcEV4dGVudCA9IF8gPT0gbnVsbCA/IGQzX2dlb21fdm9yb25vaUNsaXBFeHRlbnQgOiBfO1xuICAgICAgcmV0dXJuIHZvcm9ub2k7XG4gICAgfTtcbiAgICB2b3Jvbm9pLnNpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjbGlwRXh0ZW50ID09PSBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50ID8gbnVsbCA6IGNsaXBFeHRlbnQgJiYgY2xpcEV4dGVudFsxXTtcbiAgICAgIHJldHVybiB2b3Jvbm9pLmNsaXBFeHRlbnQoXyAmJiBbIFsgMCwgMCBdLCBfIF0pO1xuICAgIH07XG4gICAgcmV0dXJuIHZvcm9ub2k7XG4gIH07XG4gIHZhciBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50ID0gWyBbIC0xZTYsIC0xZTYgXSwgWyAxZTYsIDFlNiBdIF07XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVRyaWFuZ2xlQXJlYShhLCBiLCBjKSB7XG4gICAgcmV0dXJuIChhLnggLSBjLngpICogKGIueSAtIGEueSkgLSAoYS54IC0gYi54KSAqIChjLnkgLSBhLnkpO1xuICB9XG4gIGQzLmdlb20uZGVsYXVuYXkgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIHJldHVybiBkMy5nZW9tLnZvcm9ub2koKS50cmlhbmdsZXModmVydGljZXMpO1xuICB9O1xuICBkMy5nZW9tLnF1YWR0cmVlID0gZnVuY3Rpb24ocG9pbnRzLCB4MSwgeTEsIHgyLCB5Mikge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WSwgY29tcGF0O1xuICAgIGlmIChjb21wYXQgPSBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICB4ID0gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFg7XG4gICAgICB5ID0gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFk7XG4gICAgICBpZiAoY29tcGF0ID09PSAzKSB7XG4gICAgICAgIHkyID0geTE7XG4gICAgICAgIHgyID0geDE7XG4gICAgICAgIHkxID0geDEgPSAwO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHF1YWR0cmVlKHBvaW50cyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHF1YWR0cmVlKGRhdGEpIHtcbiAgICAgIHZhciBkLCBmeCA9IGQzX2Z1bmN0b3IoeCksIGZ5ID0gZDNfZnVuY3Rvcih5KSwgeHMsIHlzLCBpLCBuLCB4MV8sIHkxXywgeDJfLCB5Ml87XG4gICAgICBpZiAoeDEgIT0gbnVsbCkge1xuICAgICAgICB4MV8gPSB4MSwgeTFfID0geTEsIHgyXyA9IHgyLCB5Ml8gPSB5MjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHgyXyA9IHkyXyA9IC0oeDFfID0geTFfID0gSW5maW5pdHkpO1xuICAgICAgICB4cyA9IFtdLCB5cyA9IFtdO1xuICAgICAgICBuID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGlmIChjb21wYXQpIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBkID0gZGF0YVtpXTtcbiAgICAgICAgICBpZiAoZC54IDwgeDFfKSB4MV8gPSBkLng7XG4gICAgICAgICAgaWYgKGQueSA8IHkxXykgeTFfID0gZC55O1xuICAgICAgICAgIGlmIChkLnggPiB4Ml8pIHgyXyA9IGQueDtcbiAgICAgICAgICBpZiAoZC55ID4geTJfKSB5Ml8gPSBkLnk7XG4gICAgICAgICAgeHMucHVzaChkLngpO1xuICAgICAgICAgIHlzLnB1c2goZC55KTtcbiAgICAgICAgfSBlbHNlIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICB2YXIgeF8gPSArZngoZCA9IGRhdGFbaV0sIGkpLCB5XyA9ICtmeShkLCBpKTtcbiAgICAgICAgICBpZiAoeF8gPCB4MV8pIHgxXyA9IHhfO1xuICAgICAgICAgIGlmICh5XyA8IHkxXykgeTFfID0geV87XG4gICAgICAgICAgaWYgKHhfID4geDJfKSB4Ml8gPSB4XztcbiAgICAgICAgICBpZiAoeV8gPiB5Ml8pIHkyXyA9IHlfO1xuICAgICAgICAgIHhzLnB1c2goeF8pO1xuICAgICAgICAgIHlzLnB1c2goeV8pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgZHggPSB4Ml8gLSB4MV8sIGR5ID0geTJfIC0geTFfO1xuICAgICAgaWYgKGR4ID4gZHkpIHkyXyA9IHkxXyArIGR4OyBlbHNlIHgyXyA9IHgxXyArIGR5O1xuICAgICAgZnVuY3Rpb24gaW5zZXJ0KG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgIGlmIChpc05hTih4KSB8fCBpc05hTih5KSkgcmV0dXJuO1xuICAgICAgICBpZiAobi5sZWFmKSB7XG4gICAgICAgICAgdmFyIG54ID0gbi54LCBueSA9IG4ueTtcbiAgICAgICAgICBpZiAobnggIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGFicyhueCAtIHgpICsgYWJzKG55IC0geSkgPCAuMDEpIHtcbiAgICAgICAgICAgICAgaW5zZXJ0Q2hpbGQobiwgZCwgeCwgeSwgeDEsIHkxLCB4MiwgeTIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmFyIG5Qb2ludCA9IG4ucG9pbnQ7XG4gICAgICAgICAgICAgIG4ueCA9IG4ueSA9IG4ucG9pbnQgPSBudWxsO1xuICAgICAgICAgICAgICBpbnNlcnRDaGlsZChuLCBuUG9pbnQsIG54LCBueSwgeDEsIHkxLCB4MiwgeTIpO1xuICAgICAgICAgICAgICBpbnNlcnRDaGlsZChuLCBkLCB4LCB5LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG4ueCA9IHgsIG4ueSA9IHksIG4ucG9pbnQgPSBkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnNlcnRDaGlsZChuLCBkLCB4LCB5LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGluc2VydENoaWxkKG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgIHZhciB4bSA9ICh4MSArIHgyKSAqIC41LCB5bSA9ICh5MSArIHkyKSAqIC41LCByaWdodCA9IHggPj0geG0sIGJlbG93ID0geSA+PSB5bSwgaSA9IGJlbG93IDw8IDEgfCByaWdodDtcbiAgICAgICAgbi5sZWFmID0gZmFsc2U7XG4gICAgICAgIG4gPSBuLm5vZGVzW2ldIHx8IChuLm5vZGVzW2ldID0gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKSk7XG4gICAgICAgIGlmIChyaWdodCkgeDEgPSB4bTsgZWxzZSB4MiA9IHhtO1xuICAgICAgICBpZiAoYmVsb3cpIHkxID0geW07IGVsc2UgeTIgPSB5bTtcbiAgICAgICAgaW5zZXJ0KG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKTtcbiAgICAgIH1cbiAgICAgIHZhciByb290ID0gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKTtcbiAgICAgIHJvb3QuYWRkID0gZnVuY3Rpb24oZCkge1xuICAgICAgICBpbnNlcnQocm9vdCwgZCwgK2Z4KGQsICsraSksICtmeShkLCBpKSwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgIH07XG4gICAgICByb290LnZpc2l0ID0gZnVuY3Rpb24oZikge1xuICAgICAgICBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgcm9vdCwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgIH07XG4gICAgICByb290LmZpbmQgPSBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gZDNfZ2VvbV9xdWFkdHJlZUZpbmQocm9vdCwgcG9pbnRbMF0sIHBvaW50WzFdLCB4MV8sIHkxXywgeDJfLCB5Ml8pO1xuICAgICAgfTtcbiAgICAgIGkgPSAtMTtcbiAgICAgIGlmICh4MSA9PSBudWxsKSB7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgaW5zZXJ0KHJvb3QsIGRhdGFbaV0sIHhzW2ldLCB5c1tpXSwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgICAgfVxuICAgICAgICAtLWk7XG4gICAgICB9IGVsc2UgZGF0YS5mb3JFYWNoKHJvb3QuYWRkKTtcbiAgICAgIHhzID0geXMgPSBkYXRhID0gZCA9IG51bGw7XG4gICAgICByZXR1cm4gcm9vdDtcbiAgICB9XG4gICAgcXVhZHRyZWUueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSBfLCBxdWFkdHJlZSkgOiB4O1xuICAgIH07XG4gICAgcXVhZHRyZWUueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkgPSBfLCBxdWFkdHJlZSkgOiB5O1xuICAgIH07XG4gICAgcXVhZHRyZWUuZXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDEgPT0gbnVsbCA/IG51bGwgOiBbIFsgeDEsIHkxIF0sIFsgeDIsIHkyIF0gXTtcbiAgICAgIGlmIChfID09IG51bGwpIHgxID0geTEgPSB4MiA9IHkyID0gbnVsbDsgZWxzZSB4MSA9ICtfWzBdWzBdLCB5MSA9ICtfWzBdWzFdLCB4MiA9ICtfWzFdWzBdLCBcbiAgICAgIHkyID0gK19bMV1bMV07XG4gICAgICByZXR1cm4gcXVhZHRyZWU7XG4gICAgfTtcbiAgICBxdWFkdHJlZS5zaXplID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDEgPT0gbnVsbCA/IG51bGwgOiBbIHgyIC0geDEsIHkyIC0geTEgXTtcbiAgICAgIGlmIChfID09IG51bGwpIHgxID0geTEgPSB4MiA9IHkyID0gbnVsbDsgZWxzZSB4MSA9IHkxID0gMCwgeDIgPSArX1swXSwgeTIgPSArX1sxXTtcbiAgICAgIHJldHVybiBxdWFkdHJlZTtcbiAgICB9O1xuICAgIHJldHVybiBxdWFkdHJlZTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFgoZCkge1xuICAgIHJldHVybiBkLng7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFkoZCkge1xuICAgIHJldHVybiBkLnk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxlYWY6IHRydWUsXG4gICAgICBub2RlczogW10sXG4gICAgICBwb2ludDogbnVsbCxcbiAgICAgIHg6IG51bGwsXG4gICAgICB5OiBudWxsXG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgbm9kZSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICBpZiAoIWYobm9kZSwgeDEsIHkxLCB4MiwgeTIpKSB7XG4gICAgICB2YXIgc3ggPSAoeDEgKyB4MikgKiAuNSwgc3kgPSAoeTEgKyB5MikgKiAuNSwgY2hpbGRyZW4gPSBub2RlLm5vZGVzO1xuICAgICAgaWYgKGNoaWxkcmVuWzBdKSBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgY2hpbGRyZW5bMF0sIHgxLCB5MSwgc3gsIHN5KTtcbiAgICAgIGlmIChjaGlsZHJlblsxXSkgZDNfZ2VvbV9xdWFkdHJlZVZpc2l0KGYsIGNoaWxkcmVuWzFdLCBzeCwgeTEsIHgyLCBzeSk7XG4gICAgICBpZiAoY2hpbGRyZW5bMl0pIGQzX2dlb21fcXVhZHRyZWVWaXNpdChmLCBjaGlsZHJlblsyXSwgeDEsIHN5LCBzeCwgeTIpO1xuICAgICAgaWYgKGNoaWxkcmVuWzNdKSBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgY2hpbGRyZW5bM10sIHN4LCBzeSwgeDIsIHkyKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUZpbmQocm9vdCwgeCwgeSwgeDAsIHkwLCB4MywgeTMpIHtcbiAgICB2YXIgbWluRGlzdGFuY2UyID0gSW5maW5pdHksIGNsb3Nlc3RQb2ludDtcbiAgICAoZnVuY3Rpb24gZmluZChub2RlLCB4MSwgeTEsIHgyLCB5Mikge1xuICAgICAgaWYgKHgxID4geDMgfHwgeTEgPiB5MyB8fCB4MiA8IHgwIHx8IHkyIDwgeTApIHJldHVybjtcbiAgICAgIGlmIChwb2ludCA9IG5vZGUucG9pbnQpIHtcbiAgICAgICAgdmFyIHBvaW50LCBkeCA9IHggLSBub2RlLngsIGR5ID0geSAtIG5vZGUueSwgZGlzdGFuY2UyID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICAgIGlmIChkaXN0YW5jZTIgPCBtaW5EaXN0YW5jZTIpIHtcbiAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBNYXRoLnNxcnQobWluRGlzdGFuY2UyID0gZGlzdGFuY2UyKTtcbiAgICAgICAgICB4MCA9IHggLSBkaXN0YW5jZSwgeTAgPSB5IC0gZGlzdGFuY2U7XG4gICAgICAgICAgeDMgPSB4ICsgZGlzdGFuY2UsIHkzID0geSArIGRpc3RhbmNlO1xuICAgICAgICAgIGNsb3Nlc3RQb2ludCA9IHBvaW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgY2hpbGRyZW4gPSBub2RlLm5vZGVzLCB4bSA9ICh4MSArIHgyKSAqIC41LCB5bSA9ICh5MSArIHkyKSAqIC41LCByaWdodCA9IHggPj0geG0sIGJlbG93ID0geSA+PSB5bTtcbiAgICAgIGZvciAodmFyIGkgPSBiZWxvdyA8PCAxIHwgcmlnaHQsIGogPSBpICsgNDsgaSA8IGo7ICsraSkge1xuICAgICAgICBpZiAobm9kZSA9IGNoaWxkcmVuW2kgJiAzXSkgc3dpdGNoIChpICYgMykge1xuICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGZpbmQobm9kZSwgeDEsIHkxLCB4bSwgeW0pO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgZmluZChub2RlLCB4bSwgeTEsIHgyLCB5bSk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBmaW5kKG5vZGUsIHgxLCB5bSwgeG0sIHkyKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGZpbmQobm9kZSwgeG0sIHltLCB4MiwgeTIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSkocm9vdCwgeDAsIHkwLCB4MywgeTMpO1xuICAgIHJldHVybiBjbG9zZXN0UG9pbnQ7XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVSZ2IgPSBkM19pbnRlcnBvbGF0ZVJnYjtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVSZ2IoYSwgYikge1xuICAgIGEgPSBkMy5yZ2IoYSk7XG4gICAgYiA9IGQzLnJnYihiKTtcbiAgICB2YXIgYXIgPSBhLnIsIGFnID0gYS5nLCBhYiA9IGEuYiwgYnIgPSBiLnIgLSBhciwgYmcgPSBiLmcgLSBhZywgYmIgPSBiLmIgLSBhYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIFwiI1wiICsgZDNfcmdiX2hleChNYXRoLnJvdW5kKGFyICsgYnIgKiB0KSkgKyBkM19yZ2JfaGV4KE1hdGgucm91bmQoYWcgKyBiZyAqIHQpKSArIGQzX3JnYl9oZXgoTWF0aC5yb3VuZChhYiArIGJiICogdCkpO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVPYmplY3QgPSBkM19pbnRlcnBvbGF0ZU9iamVjdDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVPYmplY3QoYSwgYikge1xuICAgIHZhciBpID0ge30sIGMgPSB7fSwgaztcbiAgICBmb3IgKGsgaW4gYSkge1xuICAgICAgaWYgKGsgaW4gYikge1xuICAgICAgICBpW2tdID0gZDNfaW50ZXJwb2xhdGUoYVtrXSwgYltrXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjW2tdID0gYVtrXTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChrIGluIGIpIHtcbiAgICAgIGlmICghKGsgaW4gYSkpIHtcbiAgICAgICAgY1trXSA9IGJba107XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICBmb3IgKGsgaW4gaSkgY1trXSA9IGlba10odCk7XG4gICAgICByZXR1cm4gYztcbiAgICB9O1xuICB9XG4gIGQzLmludGVycG9sYXRlTnVtYmVyID0gZDNfaW50ZXJwb2xhdGVOdW1iZXI7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlTnVtYmVyKGEsIGIpIHtcbiAgICBhID0gK2EsIGIgPSArYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGEgKiAoMSAtIHQpICsgYiAqIHQ7XG4gICAgfTtcbiAgfVxuICBkMy5pbnRlcnBvbGF0ZVN0cmluZyA9IGQzX2ludGVycG9sYXRlU3RyaW5nO1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVN0cmluZyhhLCBiKSB7XG4gICAgdmFyIGJpID0gZDNfaW50ZXJwb2xhdGVfbnVtYmVyQS5sYXN0SW5kZXggPSBkM19pbnRlcnBvbGF0ZV9udW1iZXJCLmxhc3RJbmRleCA9IDAsIGFtLCBibSwgYnMsIGkgPSAtMSwgcyA9IFtdLCBxID0gW107XG4gICAgYSA9IGEgKyBcIlwiLCBiID0gYiArIFwiXCI7XG4gICAgd2hpbGUgKChhbSA9IGQzX2ludGVycG9sYXRlX251bWJlckEuZXhlYyhhKSkgJiYgKGJtID0gZDNfaW50ZXJwb2xhdGVfbnVtYmVyQi5leGVjKGIpKSkge1xuICAgICAgaWYgKChicyA9IGJtLmluZGV4KSA+IGJpKSB7XG4gICAgICAgIGJzID0gYi5zbGljZShiaSwgYnMpO1xuICAgICAgICBpZiAoc1tpXSkgc1tpXSArPSBiczsgZWxzZSBzWysraV0gPSBicztcbiAgICAgIH1cbiAgICAgIGlmICgoYW0gPSBhbVswXSkgPT09IChibSA9IGJtWzBdKSkge1xuICAgICAgICBpZiAoc1tpXSkgc1tpXSArPSBibTsgZWxzZSBzWysraV0gPSBibTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNbKytpXSA9IG51bGw7XG4gICAgICAgIHEucHVzaCh7XG4gICAgICAgICAgaTogaSxcbiAgICAgICAgICB4OiBkM19pbnRlcnBvbGF0ZU51bWJlcihhbSwgYm0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYmkgPSBkM19pbnRlcnBvbGF0ZV9udW1iZXJCLmxhc3RJbmRleDtcbiAgICB9XG4gICAgaWYgKGJpIDwgYi5sZW5ndGgpIHtcbiAgICAgIGJzID0gYi5zbGljZShiaSk7XG4gICAgICBpZiAoc1tpXSkgc1tpXSArPSBiczsgZWxzZSBzWysraV0gPSBicztcbiAgICB9XG4gICAgcmV0dXJuIHMubGVuZ3RoIDwgMiA/IHFbMF0gPyAoYiA9IHFbMF0ueCwgZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGIodCkgKyBcIlwiO1xuICAgIH0pIDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gYjtcbiAgICB9IDogKGIgPSBxLmxlbmd0aCwgZnVuY3Rpb24odCkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG87IGkgPCBiOyArK2kpIHNbKG8gPSBxW2ldKS5pXSA9IG8ueCh0KTtcbiAgICAgIHJldHVybiBzLmpvaW4oXCJcIik7XG4gICAgfSk7XG4gIH1cbiAgdmFyIGQzX2ludGVycG9sYXRlX251bWJlckEgPSAvWy0rXT8oPzpcXGQrXFwuP1xcZCp8XFwuP1xcZCspKD86W2VFXVstK10/XFxkKyk/L2csIGQzX2ludGVycG9sYXRlX251bWJlckIgPSBuZXcgUmVnRXhwKGQzX2ludGVycG9sYXRlX251bWJlckEuc291cmNlLCBcImdcIik7XG4gIGQzLmludGVycG9sYXRlID0gZDNfaW50ZXJwb2xhdGU7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlKGEsIGIpIHtcbiAgICB2YXIgaSA9IGQzLmludGVycG9sYXRvcnMubGVuZ3RoLCBmO1xuICAgIHdoaWxlICgtLWkgPj0gMCAmJiAhKGYgPSBkMy5pbnRlcnBvbGF0b3JzW2ldKGEsIGIpKSkgO1xuICAgIHJldHVybiBmO1xuICB9XG4gIGQzLmludGVycG9sYXRvcnMgPSBbIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgdCA9IHR5cGVvZiBiO1xuICAgIHJldHVybiAodCA9PT0gXCJzdHJpbmdcIiA/IGQzX3JnYl9uYW1lcy5oYXMoYi50b0xvd2VyQ2FzZSgpKSB8fCAvXigjfHJnYlxcKHxoc2xcXCgpL2kudGVzdChiKSA/IGQzX2ludGVycG9sYXRlUmdiIDogZDNfaW50ZXJwb2xhdGVTdHJpbmcgOiBiIGluc3RhbmNlb2YgZDNfY29sb3IgPyBkM19pbnRlcnBvbGF0ZVJnYiA6IEFycmF5LmlzQXJyYXkoYikgPyBkM19pbnRlcnBvbGF0ZUFycmF5IDogdCA9PT0gXCJvYmplY3RcIiAmJiBpc05hTihiKSA/IGQzX2ludGVycG9sYXRlT2JqZWN0IDogZDNfaW50ZXJwb2xhdGVOdW1iZXIpKGEsIGIpO1xuICB9IF07XG4gIGQzLmludGVycG9sYXRlQXJyYXkgPSBkM19pbnRlcnBvbGF0ZUFycmF5O1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZUFycmF5KGEsIGIpIHtcbiAgICB2YXIgeCA9IFtdLCBjID0gW10sIG5hID0gYS5sZW5ndGgsIG5iID0gYi5sZW5ndGgsIG4wID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKSwgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjA7ICsraSkgeC5wdXNoKGQzX2ludGVycG9sYXRlKGFbaV0sIGJbaV0pKTtcbiAgICBmb3IgKDtpIDwgbmE7ICsraSkgY1tpXSA9IGFbaV07XG4gICAgZm9yICg7aSA8IG5iOyArK2kpIGNbaV0gPSBiW2ldO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjA7ICsraSkgY1tpXSA9IHhbaV0odCk7XG4gICAgICByZXR1cm4gYztcbiAgICB9O1xuICB9XG4gIHZhciBkM19lYXNlX2RlZmF1bHQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfaWRlbnRpdHk7XG4gIH07XG4gIHZhciBkM19lYXNlID0gZDMubWFwKHtcbiAgICBsaW5lYXI6IGQzX2Vhc2VfZGVmYXVsdCxcbiAgICBwb2x5OiBkM19lYXNlX3BvbHksXG4gICAgcXVhZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9xdWFkO1xuICAgIH0sXG4gICAgY3ViaWM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX2Vhc2VfY3ViaWM7XG4gICAgfSxcbiAgICBzaW46IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX2Vhc2Vfc2luO1xuICAgIH0sXG4gICAgZXhwOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19lYXNlX2V4cDtcbiAgICB9LFxuICAgIGNpcmNsZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9jaXJjbGU7XG4gICAgfSxcbiAgICBlbGFzdGljOiBkM19lYXNlX2VsYXN0aWMsXG4gICAgYmFjazogZDNfZWFzZV9iYWNrLFxuICAgIGJvdW5jZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9ib3VuY2U7XG4gICAgfVxuICB9KTtcbiAgdmFyIGQzX2Vhc2VfbW9kZSA9IGQzLm1hcCh7XG4gICAgXCJpblwiOiBkM19pZGVudGl0eSxcbiAgICBvdXQ6IGQzX2Vhc2VfcmV2ZXJzZSxcbiAgICBcImluLW91dFwiOiBkM19lYXNlX3JlZmxlY3QsXG4gICAgXCJvdXQtaW5cIjogZnVuY3Rpb24oZikge1xuICAgICAgcmV0dXJuIGQzX2Vhc2VfcmVmbGVjdChkM19lYXNlX3JldmVyc2UoZikpO1xuICAgIH1cbiAgfSk7XG4gIGQzLmVhc2UgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIGkgPSBuYW1lLmluZGV4T2YoXCItXCIpLCB0ID0gaSA+PSAwID8gbmFtZS5zbGljZSgwLCBpKSA6IG5hbWUsIG0gPSBpID49IDAgPyBuYW1lLnNsaWNlKGkgKyAxKSA6IFwiaW5cIjtcbiAgICB0ID0gZDNfZWFzZS5nZXQodCkgfHwgZDNfZWFzZV9kZWZhdWx0O1xuICAgIG0gPSBkM19lYXNlX21vZGUuZ2V0KG0pIHx8IGQzX2lkZW50aXR5O1xuICAgIHJldHVybiBkM19lYXNlX2NsYW1wKG0odC5hcHBseShudWxsLCBkM19hcnJheVNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZWFzZV9jbGFtcChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0IDw9IDAgPyAwIDogdCA+PSAxID8gMSA6IGYodCk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX3JldmVyc2UoZikge1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICByZXR1cm4gMSAtIGYoMSAtIHQpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZWFzZV9yZWZsZWN0KGYpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIC41ICogKHQgPCAuNSA/IGYoMiAqIHQpIDogMiAtIGYoMiAtIDIgKiB0KSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX3F1YWQodCkge1xuICAgIHJldHVybiB0ICogdDtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2N1YmljKHQpIHtcbiAgICByZXR1cm4gdCAqIHQgKiB0O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfY3ViaWNJbk91dCh0KSB7XG4gICAgaWYgKHQgPD0gMCkgcmV0dXJuIDA7XG4gICAgaWYgKHQgPj0gMSkgcmV0dXJuIDE7XG4gICAgdmFyIHQyID0gdCAqIHQsIHQzID0gdDIgKiB0O1xuICAgIHJldHVybiA0ICogKHQgPCAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAuNzUpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfcG9seShlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiBNYXRoLnBvdyh0LCBlKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2Vfc2luKHQpIHtcbiAgICByZXR1cm4gMSAtIE1hdGguY29zKHQgKiBoYWxmz4ApO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfZXhwKHQpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMiwgMTAgKiAodCAtIDEpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2NpcmNsZSh0KSB7XG4gICAgcmV0dXJuIDEgLSBNYXRoLnNxcnQoMSAtIHQgKiB0KTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2VsYXN0aWMoYSwgcCkge1xuICAgIHZhciBzO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcCA9IC40NTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCkgcyA9IHAgLyDPhCAqIE1hdGguYXNpbigxIC8gYSk7IGVsc2UgYSA9IDEsIHMgPSBwIC8gNDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIDEgKyBhICogTWF0aC5wb3coMiwgLTEwICogdCkgKiBNYXRoLnNpbigodCAtIHMpICogz4QgLyBwKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfYmFjayhzKSB7XG4gICAgaWYgKCFzKSBzID0gMS43MDE1ODtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQgKiB0ICogKChzICsgMSkgKiB0IC0gcyk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2JvdW5jZSh0KSB7XG4gICAgcmV0dXJuIHQgPCAxIC8gMi43NSA/IDcuNTYyNSAqIHQgKiB0IDogdCA8IDIgLyAyLjc1ID8gNy41NjI1ICogKHQgLT0gMS41IC8gMi43NSkgKiB0ICsgLjc1IDogdCA8IDIuNSAvIDIuNzUgPyA3LjU2MjUgKiAodCAtPSAyLjI1IC8gMi43NSkgKiB0ICsgLjkzNzUgOiA3LjU2MjUgKiAodCAtPSAyLjYyNSAvIDIuNzUpICogdCArIC45ODQzNzU7XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVIY2wgPSBkM19pbnRlcnBvbGF0ZUhjbDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVIY2woYSwgYikge1xuICAgIGEgPSBkMy5oY2woYSk7XG4gICAgYiA9IGQzLmhjbChiKTtcbiAgICB2YXIgYWggPSBhLmgsIGFjID0gYS5jLCBhbCA9IGEubCwgYmggPSBiLmggLSBhaCwgYmMgPSBiLmMgLSBhYywgYmwgPSBiLmwgLSBhbDtcbiAgICBpZiAoaXNOYU4oYmMpKSBiYyA9IDAsIGFjID0gaXNOYU4oYWMpID8gYi5jIDogYWM7XG4gICAgaWYgKGlzTmFOKGJoKSkgYmggPSAwLCBhaCA9IGlzTmFOKGFoKSA/IGIuaCA6IGFoOyBlbHNlIGlmIChiaCA+IDE4MCkgYmggLT0gMzYwOyBlbHNlIGlmIChiaCA8IC0xODApIGJoICs9IDM2MDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2hjbF9sYWIoYWggKyBiaCAqIHQsIGFjICsgYmMgKiB0LCBhbCArIGJsICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVIc2wgPSBkM19pbnRlcnBvbGF0ZUhzbDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVIc2woYSwgYikge1xuICAgIGEgPSBkMy5oc2woYSk7XG4gICAgYiA9IGQzLmhzbChiKTtcbiAgICB2YXIgYWggPSBhLmgsIGFzID0gYS5zLCBhbCA9IGEubCwgYmggPSBiLmggLSBhaCwgYnMgPSBiLnMgLSBhcywgYmwgPSBiLmwgLSBhbDtcbiAgICBpZiAoaXNOYU4oYnMpKSBicyA9IDAsIGFzID0gaXNOYU4oYXMpID8gYi5zIDogYXM7XG4gICAgaWYgKGlzTmFOKGJoKSkgYmggPSAwLCBhaCA9IGlzTmFOKGFoKSA/IGIuaCA6IGFoOyBlbHNlIGlmIChiaCA+IDE4MCkgYmggLT0gMzYwOyBlbHNlIGlmIChiaCA8IC0xODApIGJoICs9IDM2MDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2hzbF9yZ2IoYWggKyBiaCAqIHQsIGFzICsgYnMgKiB0LCBhbCArIGJsICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVMYWIgPSBkM19pbnRlcnBvbGF0ZUxhYjtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVMYWIoYSwgYikge1xuICAgIGEgPSBkMy5sYWIoYSk7XG4gICAgYiA9IGQzLmxhYihiKTtcbiAgICB2YXIgYWwgPSBhLmwsIGFhID0gYS5hLCBhYiA9IGEuYiwgYmwgPSBiLmwgLSBhbCwgYmEgPSBiLmEgLSBhYSwgYmIgPSBiLmIgLSBhYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2xhYl9yZ2IoYWwgKyBibCAqIHQsIGFhICsgYmEgKiB0LCBhYiArIGJiICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVSb3VuZCA9IGQzX2ludGVycG9sYXRlUm91bmQ7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlUm91bmQoYSwgYikge1xuICAgIGIgLT0gYTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIE1hdGgucm91bmQoYSArIGIgKiB0KTtcbiAgICB9O1xuICB9XG4gIGQzLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHZhciBnID0gZDNfZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKGQzLm5zLnByZWZpeC5zdmcsIFwiZ1wiKTtcbiAgICByZXR1cm4gKGQzLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgaWYgKHN0cmluZyAhPSBudWxsKSB7XG4gICAgICAgIGcuc2V0QXR0cmlidXRlKFwidHJhbnNmb3JtXCIsIHN0cmluZyk7XG4gICAgICAgIHZhciB0ID0gZy50cmFuc2Zvcm0uYmFzZVZhbC5jb25zb2xpZGF0ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBkM190cmFuc2Zvcm0odCA/IHQubWF0cml4IDogZDNfdHJhbnNmb3JtSWRlbnRpdHkpO1xuICAgIH0pKHN0cmluZyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zZm9ybShtKSB7XG4gICAgdmFyIHIwID0gWyBtLmEsIG0uYiBdLCByMSA9IFsgbS5jLCBtLmQgXSwga3ggPSBkM190cmFuc2Zvcm1Ob3JtYWxpemUocjApLCBreiA9IGQzX3RyYW5zZm9ybURvdChyMCwgcjEpLCBreSA9IGQzX3RyYW5zZm9ybU5vcm1hbGl6ZShkM190cmFuc2Zvcm1Db21iaW5lKHIxLCByMCwgLWt6KSkgfHwgMDtcbiAgICBpZiAocjBbMF0gKiByMVsxXSA8IHIxWzBdICogcjBbMV0pIHtcbiAgICAgIHIwWzBdICo9IC0xO1xuICAgICAgcjBbMV0gKj0gLTE7XG4gICAgICBreCAqPSAtMTtcbiAgICAgIGt6ICo9IC0xO1xuICAgIH1cbiAgICB0aGlzLnJvdGF0ZSA9IChreCA/IE1hdGguYXRhbjIocjBbMV0sIHIwWzBdKSA6IE1hdGguYXRhbjIoLXIxWzBdLCByMVsxXSkpICogZDNfZGVncmVlcztcbiAgICB0aGlzLnRyYW5zbGF0ZSA9IFsgbS5lLCBtLmYgXTtcbiAgICB0aGlzLnNjYWxlID0gWyBreCwga3kgXTtcbiAgICB0aGlzLnNrZXcgPSBreSA/IE1hdGguYXRhbjIoa3osIGt5KSAqIGQzX2RlZ3JlZXMgOiAwO1xuICB9XG4gIGQzX3RyYW5zZm9ybS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXCJ0cmFuc2xhdGUoXCIgKyB0aGlzLnRyYW5zbGF0ZSArIFwiKXJvdGF0ZShcIiArIHRoaXMucm90YXRlICsgXCIpc2tld1goXCIgKyB0aGlzLnNrZXcgKyBcIilzY2FsZShcIiArIHRoaXMuc2NhbGUgKyBcIilcIjtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfdHJhbnNmb3JtRG90KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXTtcbiAgfVxuICBmdW5jdGlvbiBkM190cmFuc2Zvcm1Ob3JtYWxpemUoYSkge1xuICAgIHZhciBrID0gTWF0aC5zcXJ0KGQzX3RyYW5zZm9ybURvdChhLCBhKSk7XG4gICAgaWYgKGspIHtcbiAgICAgIGFbMF0gLz0gaztcbiAgICAgIGFbMV0gLz0gaztcbiAgICB9XG4gICAgcmV0dXJuIGs7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdHJhbnNmb3JtQ29tYmluZShhLCBiLCBrKSB7XG4gICAgYVswXSArPSBrICogYlswXTtcbiAgICBhWzFdICs9IGsgKiBiWzFdO1xuICAgIHJldHVybiBhO1xuICB9XG4gIHZhciBkM190cmFuc2Zvcm1JZGVudGl0eSA9IHtcbiAgICBhOiAxLFxuICAgIGI6IDAsXG4gICAgYzogMCxcbiAgICBkOiAxLFxuICAgIGU6IDAsXG4gICAgZjogMFxuICB9O1xuICBkMy5pbnRlcnBvbGF0ZVRyYW5zZm9ybSA9IGQzX2ludGVycG9sYXRlVHJhbnNmb3JtO1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSB7XG4gICAgcmV0dXJuIHMubGVuZ3RoID8gcy5wb3AoKSArIFwiLFwiIDogXCJcIjtcbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zbGF0ZSh0YSwgdGIsIHMsIHEpIHtcbiAgICBpZiAodGFbMF0gIT09IHRiWzBdIHx8IHRhWzFdICE9PSB0YlsxXSkge1xuICAgICAgdmFyIGkgPSBzLnB1c2goXCJ0cmFuc2xhdGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe1xuICAgICAgICBpOiBpIC0gNCxcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIodGFbMF0sIHRiWzBdKVxuICAgICAgfSwge1xuICAgICAgICBpOiBpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIodGFbMV0sIHRiWzFdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh0YlswXSB8fCB0YlsxXSkge1xuICAgICAgcy5wdXNoKFwidHJhbnNsYXRlKFwiICsgdGIgKyBcIilcIik7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlUm90YXRlKHJhLCByYiwgcywgcSkge1xuICAgIGlmIChyYSAhPT0gcmIpIHtcbiAgICAgIGlmIChyYSAtIHJiID4gMTgwKSByYiArPSAzNjA7IGVsc2UgaWYgKHJiIC0gcmEgPiAxODApIHJhICs9IDM2MDtcbiAgICAgIHEucHVzaCh7XG4gICAgICAgIGk6IHMucHVzaChkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSArIFwicm90YXRlKFwiLCBudWxsLCBcIilcIikgLSAyLFxuICAgICAgICB4OiBkM19pbnRlcnBvbGF0ZU51bWJlcihyYSwgcmIpXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHJiKSB7XG4gICAgICBzLnB1c2goZDNfaW50ZXJwb2xhdGVUcmFuc2Zvcm1Qb3AocykgKyBcInJvdGF0ZShcIiArIHJiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVNrZXcod2EsIHdiLCBzLCBxKSB7XG4gICAgaWYgKHdhICE9PSB3Yikge1xuICAgICAgcS5wdXNoKHtcbiAgICAgICAgaTogcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJza2V3WChcIiwgbnVsbCwgXCIpXCIpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIod2EsIHdiKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh3Yikge1xuICAgICAgcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJza2V3WChcIiArIHdiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVNjYWxlKGthLCBrYiwgcywgcSkge1xuICAgIGlmIChrYVswXSAhPT0ga2JbMF0gfHwga2FbMV0gIT09IGtiWzFdKSB7XG4gICAgICB2YXIgaSA9IHMucHVzaChkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSArIFwic2NhbGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe1xuICAgICAgICBpOiBpIC0gNCxcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIoa2FbMF0sIGtiWzBdKVxuICAgICAgfSwge1xuICAgICAgICBpOiBpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIoa2FbMV0sIGtiWzFdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChrYlswXSAhPT0gMSB8fCBrYlsxXSAhPT0gMSkge1xuICAgICAgcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJzY2FsZShcIiArIGtiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybShhLCBiKSB7XG4gICAgdmFyIHMgPSBbXSwgcSA9IFtdO1xuICAgIGEgPSBkMy50cmFuc2Zvcm0oYSksIGIgPSBkMy50cmFuc2Zvcm0oYik7XG4gICAgZDNfaW50ZXJwb2xhdGVUcmFuc2xhdGUoYS50cmFuc2xhdGUsIGIudHJhbnNsYXRlLCBzLCBxKTtcbiAgICBkM19pbnRlcnBvbGF0ZVJvdGF0ZShhLnJvdGF0ZSwgYi5yb3RhdGUsIHMsIHEpO1xuICAgIGQzX2ludGVycG9sYXRlU2tldyhhLnNrZXcsIGIuc2tldywgcywgcSk7XG4gICAgZDNfaW50ZXJwb2xhdGVTY2FsZShhLnNjYWxlLCBiLnNjYWxlLCBzLCBxKTtcbiAgICBhID0gYiA9IG51bGw7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBpID0gLTEsIG4gPSBxLmxlbmd0aCwgbztcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBzWyhvID0gcVtpXSkuaV0gPSBvLngodCk7XG4gICAgICByZXR1cm4gcy5qb2luKFwiXCIpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfdW5pbnRlcnBvbGF0ZU51bWJlcihhLCBiKSB7XG4gICAgYiA9IChiIC09IGEgPSArYSkgfHwgMSAvIGI7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAoeCAtIGEpIC8gYjtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3VuaW50ZXJwb2xhdGVDbGFtcChhLCBiKSB7XG4gICAgYiA9IChiIC09IGEgPSArYSkgfHwgMSAvIGI7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCAoeCAtIGEpIC8gYikpO1xuICAgIH07XG4gIH1cbiAgZDMubGF5b3V0ID0ge307XG4gIGQzLmxheW91dC5idW5kbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24obGlua3MpIHtcbiAgICAgIHZhciBwYXRocyA9IFtdLCBpID0gLTEsIG4gPSBsaW5rcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgcGF0aHMucHVzaChkM19sYXlvdXRfYnVuZGxlUGF0aChsaW5rc1tpXSkpO1xuICAgICAgcmV0dXJuIHBhdGhzO1xuICAgIH07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVQYXRoKGxpbmspIHtcbiAgICB2YXIgc3RhcnQgPSBsaW5rLnNvdXJjZSwgZW5kID0gbGluay50YXJnZXQsIGxjYSA9IGQzX2xheW91dF9idW5kbGVMZWFzdENvbW1vbkFuY2VzdG9yKHN0YXJ0LCBlbmQpLCBwb2ludHMgPSBbIHN0YXJ0IF07XG4gICAgd2hpbGUgKHN0YXJ0ICE9PSBsY2EpIHtcbiAgICAgIHN0YXJ0ID0gc3RhcnQucGFyZW50O1xuICAgICAgcG9pbnRzLnB1c2goc3RhcnQpO1xuICAgIH1cbiAgICB2YXIgayA9IHBvaW50cy5sZW5ndGg7XG4gICAgd2hpbGUgKGVuZCAhPT0gbGNhKSB7XG4gICAgICBwb2ludHMuc3BsaWNlKGssIDAsIGVuZCk7XG4gICAgICBlbmQgPSBlbmQucGFyZW50O1xuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMobm9kZSkge1xuICAgIHZhciBhbmNlc3RvcnMgPSBbXSwgcGFyZW50ID0gbm9kZS5wYXJlbnQ7XG4gICAgd2hpbGUgKHBhcmVudCAhPSBudWxsKSB7XG4gICAgICBhbmNlc3RvcnMucHVzaChub2RlKTtcbiAgICAgIG5vZGUgPSBwYXJlbnQ7XG4gICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50O1xuICAgIH1cbiAgICBhbmNlc3RvcnMucHVzaChub2RlKTtcbiAgICByZXR1cm4gYW5jZXN0b3JzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVMZWFzdENvbW1vbkFuY2VzdG9yKGEsIGIpIHtcbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIGE7XG4gICAgdmFyIGFOb2RlcyA9IGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMoYSksIGJOb2RlcyA9IGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMoYiksIGFOb2RlID0gYU5vZGVzLnBvcCgpLCBiTm9kZSA9IGJOb2Rlcy5wb3AoKSwgc2hhcmVkTm9kZSA9IG51bGw7XG4gICAgd2hpbGUgKGFOb2RlID09PSBiTm9kZSkge1xuICAgICAgc2hhcmVkTm9kZSA9IGFOb2RlO1xuICAgICAgYU5vZGUgPSBhTm9kZXMucG9wKCk7XG4gICAgICBiTm9kZSA9IGJOb2Rlcy5wb3AoKTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYXJlZE5vZGU7XG4gIH1cbiAgZDMubGF5b3V0LmNob3JkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNob3JkID0ge30sIGNob3JkcywgZ3JvdXBzLCBtYXRyaXgsIG4sIHBhZGRpbmcgPSAwLCBzb3J0R3JvdXBzLCBzb3J0U3ViZ3JvdXBzLCBzb3J0Q2hvcmRzO1xuICAgIGZ1bmN0aW9uIHJlbGF5b3V0KCkge1xuICAgICAgdmFyIHN1Ymdyb3VwcyA9IHt9LCBncm91cFN1bXMgPSBbXSwgZ3JvdXBJbmRleCA9IGQzLnJhbmdlKG4pLCBzdWJncm91cEluZGV4ID0gW10sIGssIHgsIHgwLCBpLCBqO1xuICAgICAgY2hvcmRzID0gW107XG4gICAgICBncm91cHMgPSBbXTtcbiAgICAgIGsgPSAwLCBpID0gLTE7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICB4ID0gMCwgaiA9IC0xO1xuICAgICAgICB3aGlsZSAoKytqIDwgbikge1xuICAgICAgICAgIHggKz0gbWF0cml4W2ldW2pdO1xuICAgICAgICB9XG4gICAgICAgIGdyb3VwU3Vtcy5wdXNoKHgpO1xuICAgICAgICBzdWJncm91cEluZGV4LnB1c2goZDMucmFuZ2UobikpO1xuICAgICAgICBrICs9IHg7XG4gICAgICB9XG4gICAgICBpZiAoc29ydEdyb3Vwcykge1xuICAgICAgICBncm91cEluZGV4LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgIHJldHVybiBzb3J0R3JvdXBzKGdyb3VwU3Vtc1thXSwgZ3JvdXBTdW1zW2JdKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBpZiAoc29ydFN1Ymdyb3Vwcykge1xuICAgICAgICBzdWJncm91cEluZGV4LmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgIGQuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gc29ydFN1Ymdyb3VwcyhtYXRyaXhbaV1bYV0sIG1hdHJpeFtpXVtiXSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgayA9ICjPhCAtIHBhZGRpbmcgKiBuKSAvIGs7XG4gICAgICB4ID0gMCwgaSA9IC0xO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgeDAgPSB4LCBqID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2ogPCBuKSB7XG4gICAgICAgICAgdmFyIGRpID0gZ3JvdXBJbmRleFtpXSwgZGogPSBzdWJncm91cEluZGV4W2RpXVtqXSwgdiA9IG1hdHJpeFtkaV1bZGpdLCBhMCA9IHgsIGExID0geCArPSB2ICogaztcbiAgICAgICAgICBzdWJncm91cHNbZGkgKyBcIi1cIiArIGRqXSA9IHtcbiAgICAgICAgICAgIGluZGV4OiBkaSxcbiAgICAgICAgICAgIHN1YmluZGV4OiBkaixcbiAgICAgICAgICAgIHN0YXJ0QW5nbGU6IGEwLFxuICAgICAgICAgICAgZW5kQW5nbGU6IGExLFxuICAgICAgICAgICAgdmFsdWU6IHZcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGdyb3Vwc1tkaV0gPSB7XG4gICAgICAgICAgaW5kZXg6IGRpLFxuICAgICAgICAgIHN0YXJ0QW5nbGU6IHgwLFxuICAgICAgICAgIGVuZEFuZ2xlOiB4LFxuICAgICAgICAgIHZhbHVlOiBncm91cFN1bXNbZGldXG4gICAgICAgIH07XG4gICAgICAgIHggKz0gcGFkZGluZztcbiAgICAgIH1cbiAgICAgIGkgPSAtMTtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGogPSBpIC0gMTtcbiAgICAgICAgd2hpbGUgKCsraiA8IG4pIHtcbiAgICAgICAgICB2YXIgc291cmNlID0gc3ViZ3JvdXBzW2kgKyBcIi1cIiArIGpdLCB0YXJnZXQgPSBzdWJncm91cHNbaiArIFwiLVwiICsgaV07XG4gICAgICAgICAgaWYgKHNvdXJjZS52YWx1ZSB8fCB0YXJnZXQudmFsdWUpIHtcbiAgICAgICAgICAgIGNob3Jkcy5wdXNoKHNvdXJjZS52YWx1ZSA8IHRhcmdldC52YWx1ZSA/IHtcbiAgICAgICAgICAgICAgc291cmNlOiB0YXJnZXQsXG4gICAgICAgICAgICAgIHRhcmdldDogc291cmNlXG4gICAgICAgICAgICB9IDoge1xuICAgICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHNvcnRDaG9yZHMpIHJlc29ydCgpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNvcnQoKSB7XG4gICAgICBjaG9yZHMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBzb3J0Q2hvcmRzKChhLnNvdXJjZS52YWx1ZSArIGEudGFyZ2V0LnZhbHVlKSAvIDIsIChiLnNvdXJjZS52YWx1ZSArIGIudGFyZ2V0LnZhbHVlKSAvIDIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGNob3JkLm1hdHJpeCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1hdHJpeDtcbiAgICAgIG4gPSAobWF0cml4ID0geCkgJiYgbWF0cml4Lmxlbmd0aDtcbiAgICAgIGNob3JkcyA9IGdyb3VwcyA9IG51bGw7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5wYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkZGluZztcbiAgICAgIHBhZGRpbmcgPSB4O1xuICAgICAgY2hvcmRzID0gZ3JvdXBzID0gbnVsbDtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIGNob3JkLnNvcnRHcm91cHMgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3J0R3JvdXBzO1xuICAgICAgc29ydEdyb3VwcyA9IHg7XG4gICAgICBjaG9yZHMgPSBncm91cHMgPSBudWxsO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuc29ydFN1Ymdyb3VwcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvcnRTdWJncm91cHM7XG4gICAgICBzb3J0U3ViZ3JvdXBzID0geDtcbiAgICAgIGNob3JkcyA9IG51bGw7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5zb3J0Q2hvcmRzID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc29ydENob3JkcztcbiAgICAgIHNvcnRDaG9yZHMgPSB4O1xuICAgICAgaWYgKGNob3JkcykgcmVzb3J0KCk7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5jaG9yZHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghY2hvcmRzKSByZWxheW91dCgpO1xuICAgICAgcmV0dXJuIGNob3JkcztcbiAgICB9O1xuICAgIGNob3JkLmdyb3VwcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFncm91cHMpIHJlbGF5b3V0KCk7XG4gICAgICByZXR1cm4gZ3JvdXBzO1xuICAgIH07XG4gICAgcmV0dXJuIGNob3JkO1xuICB9O1xuICBkMy5sYXlvdXQuZm9yY2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZm9yY2UgPSB7fSwgZXZlbnQgPSBkMy5kaXNwYXRjaChcInN0YXJ0XCIsIFwidGlja1wiLCBcImVuZFwiKSwgdGltZXIsIHNpemUgPSBbIDEsIDEgXSwgZHJhZywgYWxwaGEsIGZyaWN0aW9uID0gLjksIGxpbmtEaXN0YW5jZSA9IGQzX2xheW91dF9mb3JjZUxpbmtEaXN0YW5jZSwgbGlua1N0cmVuZ3RoID0gZDNfbGF5b3V0X2ZvcmNlTGlua1N0cmVuZ3RoLCBjaGFyZ2UgPSAtMzAsIGNoYXJnZURpc3RhbmNlMiA9IGQzX2xheW91dF9mb3JjZUNoYXJnZURpc3RhbmNlMiwgZ3Jhdml0eSA9IC4xLCB0aGV0YTIgPSAuNjQsIG5vZGVzID0gW10sIGxpbmtzID0gW10sIGRpc3RhbmNlcywgc3RyZW5ndGhzLCBjaGFyZ2VzO1xuICAgIGZ1bmN0aW9uIHJlcHVsc2Uobm9kZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHF1YWQsIHgxLCBfLCB4Mikge1xuICAgICAgICBpZiAocXVhZC5wb2ludCAhPT0gbm9kZSkge1xuICAgICAgICAgIHZhciBkeCA9IHF1YWQuY3ggLSBub2RlLngsIGR5ID0gcXVhZC5jeSAtIG5vZGUueSwgZHcgPSB4MiAtIHgxLCBkbiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICAgIGlmIChkdyAqIGR3IC8gdGhldGEyIDwgZG4pIHtcbiAgICAgICAgICAgIGlmIChkbiA8IGNoYXJnZURpc3RhbmNlMikge1xuICAgICAgICAgICAgICB2YXIgayA9IHF1YWQuY2hhcmdlIC8gZG47XG4gICAgICAgICAgICAgIG5vZGUucHggLT0gZHggKiBrO1xuICAgICAgICAgICAgICBub2RlLnB5IC09IGR5ICogaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocXVhZC5wb2ludCAmJiBkbiAmJiBkbiA8IGNoYXJnZURpc3RhbmNlMikge1xuICAgICAgICAgICAgdmFyIGsgPSBxdWFkLnBvaW50Q2hhcmdlIC8gZG47XG4gICAgICAgICAgICBub2RlLnB4IC09IGR4ICogaztcbiAgICAgICAgICAgIG5vZGUucHkgLT0gZHkgKiBrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIXF1YWQuY2hhcmdlO1xuICAgICAgfTtcbiAgICB9XG4gICAgZm9yY2UudGljayA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKChhbHBoYSAqPSAuOTkpIDwgLjAwNSkge1xuICAgICAgICB0aW1lciA9IG51bGw7XG4gICAgICAgIGV2ZW50LmVuZCh7XG4gICAgICAgICAgdHlwZTogXCJlbmRcIixcbiAgICAgICAgICBhbHBoYTogYWxwaGEgPSAwXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBuID0gbm9kZXMubGVuZ3RoLCBtID0gbGlua3MubGVuZ3RoLCBxLCBpLCBvLCBzLCB0LCBsLCBrLCB4LCB5O1xuICAgICAgZm9yIChpID0gMDsgaSA8IG07ICsraSkge1xuICAgICAgICBvID0gbGlua3NbaV07XG4gICAgICAgIHMgPSBvLnNvdXJjZTtcbiAgICAgICAgdCA9IG8udGFyZ2V0O1xuICAgICAgICB4ID0gdC54IC0gcy54O1xuICAgICAgICB5ID0gdC55IC0gcy55O1xuICAgICAgICBpZiAobCA9IHggKiB4ICsgeSAqIHkpIHtcbiAgICAgICAgICBsID0gYWxwaGEgKiBzdHJlbmd0aHNbaV0gKiAoKGwgPSBNYXRoLnNxcnQobCkpIC0gZGlzdGFuY2VzW2ldKSAvIGw7XG4gICAgICAgICAgeCAqPSBsO1xuICAgICAgICAgIHkgKj0gbDtcbiAgICAgICAgICB0LnggLT0geCAqIChrID0gcy53ZWlnaHQgKyB0LndlaWdodCA/IHMud2VpZ2h0IC8gKHMud2VpZ2h0ICsgdC53ZWlnaHQpIDogLjUpO1xuICAgICAgICAgIHQueSAtPSB5ICogaztcbiAgICAgICAgICBzLnggKz0geCAqIChrID0gMSAtIGspO1xuICAgICAgICAgIHMueSArPSB5ICogaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGsgPSBhbHBoYSAqIGdyYXZpdHkpIHtcbiAgICAgICAgeCA9IHNpemVbMF0gLyAyO1xuICAgICAgICB5ID0gc2l6ZVsxXSAvIDI7XG4gICAgICAgIGkgPSAtMTtcbiAgICAgICAgaWYgKGspIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgbyA9IG5vZGVzW2ldO1xuICAgICAgICAgIG8ueCArPSAoeCAtIG8ueCkgKiBrO1xuICAgICAgICAgIG8ueSArPSAoeSAtIG8ueSkgKiBrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY2hhcmdlKSB7XG4gICAgICAgIGQzX2xheW91dF9mb3JjZUFjY3VtdWxhdGUocSA9IGQzLmdlb20ucXVhZHRyZWUobm9kZXMpLCBhbHBoYSwgY2hhcmdlcyk7XG4gICAgICAgIGkgPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgICBpZiAoIShvID0gbm9kZXNbaV0pLmZpeGVkKSB7XG4gICAgICAgICAgICBxLnZpc2l0KHJlcHVsc2UobykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaSA9IC0xO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgbyA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAoby5maXhlZCkge1xuICAgICAgICAgIG8ueCA9IG8ucHg7XG4gICAgICAgICAgby55ID0gby5weTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvLnggLT0gKG8ucHggLSAoby5weCA9IG8ueCkpICogZnJpY3Rpb247XG4gICAgICAgICAgby55IC09IChvLnB5IC0gKG8ucHkgPSBvLnkpKSAqIGZyaWN0aW9uO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBldmVudC50aWNrKHtcbiAgICAgICAgdHlwZTogXCJ0aWNrXCIsXG4gICAgICAgIGFscGhhOiBhbHBoYVxuICAgICAgfSk7XG4gICAgfTtcbiAgICBmb3JjZS5ub2RlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVzO1xuICAgICAgbm9kZXMgPSB4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UubGlua3MgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5rcztcbiAgICAgIGxpbmtzID0geDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzaXplO1xuICAgICAgc2l6ZSA9IHg7XG4gICAgICByZXR1cm4gZm9yY2U7XG4gICAgfTtcbiAgICBmb3JjZS5saW5rRGlzdGFuY2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5rRGlzdGFuY2U7XG4gICAgICBsaW5rRGlzdGFuY2UgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuZGlzdGFuY2UgPSBmb3JjZS5saW5rRGlzdGFuY2U7XG4gICAgZm9yY2UubGlua1N0cmVuZ3RoID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbGlua1N0cmVuZ3RoO1xuICAgICAgbGlua1N0cmVuZ3RoID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiAreDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmZyaWN0aW9uID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZnJpY3Rpb247XG4gICAgICBmcmljdGlvbiA9ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuY2hhcmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2hhcmdlO1xuICAgICAgY2hhcmdlID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiAreDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmNoYXJnZURpc3RhbmNlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gTWF0aC5zcXJ0KGNoYXJnZURpc3RhbmNlMik7XG4gICAgICBjaGFyZ2VEaXN0YW5jZTIgPSB4ICogeDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmdyYXZpdHkgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBncmF2aXR5O1xuICAgICAgZ3Jhdml0eSA9ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UudGhldGEgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBNYXRoLnNxcnQodGhldGEyKTtcbiAgICAgIHRoZXRhMiA9IHggKiB4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuYWxwaGEgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBhbHBoYTtcbiAgICAgIHggPSAreDtcbiAgICAgIGlmIChhbHBoYSkge1xuICAgICAgICBpZiAoeCA+IDApIHtcbiAgICAgICAgICBhbHBoYSA9IHg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGltZXIuYyA9IG51bGwsIHRpbWVyLnQgPSBOYU4sIHRpbWVyID0gbnVsbDtcbiAgICAgICAgICBldmVudC5lbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJlbmRcIixcbiAgICAgICAgICAgIGFscGhhOiBhbHBoYSA9IDBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh4ID4gMCkge1xuICAgICAgICBldmVudC5zdGFydCh7XG4gICAgICAgICAgdHlwZTogXCJzdGFydFwiLFxuICAgICAgICAgIGFscGhhOiBhbHBoYSA9IHhcbiAgICAgICAgfSk7XG4gICAgICAgIHRpbWVyID0gZDNfdGltZXIoZm9yY2UudGljayk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZm9yY2U7XG4gICAgfTtcbiAgICBmb3JjZS5zdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIG0gPSBsaW5rcy5sZW5ndGgsIHcgPSBzaXplWzBdLCBoID0gc2l6ZVsxXSwgbmVpZ2hib3JzLCBvO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAobyA9IG5vZGVzW2ldKS5pbmRleCA9IGk7XG4gICAgICAgIG8ud2VpZ2h0ID0gMDtcbiAgICAgIH1cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHtcbiAgICAgICAgbyA9IGxpbmtzW2ldO1xuICAgICAgICBpZiAodHlwZW9mIG8uc291cmNlID09IFwibnVtYmVyXCIpIG8uc291cmNlID0gbm9kZXNbby5zb3VyY2VdO1xuICAgICAgICBpZiAodHlwZW9mIG8udGFyZ2V0ID09IFwibnVtYmVyXCIpIG8udGFyZ2V0ID0gbm9kZXNbby50YXJnZXRdO1xuICAgICAgICArK28uc291cmNlLndlaWdodDtcbiAgICAgICAgKytvLnRhcmdldC53ZWlnaHQ7XG4gICAgICB9XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG8gPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKGlzTmFOKG8ueCkpIG8ueCA9IHBvc2l0aW9uKFwieFwiLCB3KTtcbiAgICAgICAgaWYgKGlzTmFOKG8ueSkpIG8ueSA9IHBvc2l0aW9uKFwieVwiLCBoKTtcbiAgICAgICAgaWYgKGlzTmFOKG8ucHgpKSBvLnB4ID0gby54O1xuICAgICAgICBpZiAoaXNOYU4oby5weSkpIG8ucHkgPSBvLnk7XG4gICAgICB9XG4gICAgICBkaXN0YW5jZXMgPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgbGlua0Rpc3RhbmNlID09PSBcImZ1bmN0aW9uXCIpIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIGRpc3RhbmNlc1tpXSA9ICtsaW5rRGlzdGFuY2UuY2FsbCh0aGlzLCBsaW5rc1tpXSwgaSk7IGVsc2UgZm9yIChpID0gMDsgaSA8IG07ICsraSkgZGlzdGFuY2VzW2ldID0gbGlua0Rpc3RhbmNlO1xuICAgICAgc3RyZW5ndGhzID0gW107XG4gICAgICBpZiAodHlwZW9mIGxpbmtTdHJlbmd0aCA9PT0gXCJmdW5jdGlvblwiKSBmb3IgKGkgPSAwOyBpIDwgbTsgKytpKSBzdHJlbmd0aHNbaV0gPSArbGlua1N0cmVuZ3RoLmNhbGwodGhpcywgbGlua3NbaV0sIGkpOyBlbHNlIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHN0cmVuZ3Roc1tpXSA9IGxpbmtTdHJlbmd0aDtcbiAgICAgIGNoYXJnZXMgPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgY2hhcmdlID09PSBcImZ1bmN0aW9uXCIpIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGNoYXJnZXNbaV0gPSArY2hhcmdlLmNhbGwodGhpcywgbm9kZXNbaV0sIGkpOyBlbHNlIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGNoYXJnZXNbaV0gPSBjaGFyZ2U7XG4gICAgICBmdW5jdGlvbiBwb3NpdGlvbihkaW1lbnNpb24sIHNpemUpIHtcbiAgICAgICAgaWYgKCFuZWlnaGJvcnMpIHtcbiAgICAgICAgICBuZWlnaGJvcnMgPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgZm9yIChqID0gMDsgaiA8IG47ICsraikge1xuICAgICAgICAgICAgbmVpZ2hib3JzW2pdID0gW107XG4gICAgICAgICAgfVxuICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgICAgIHZhciBvID0gbGlua3Nbal07XG4gICAgICAgICAgICBuZWlnaGJvcnNbby5zb3VyY2UuaW5kZXhdLnB1c2goby50YXJnZXQpO1xuICAgICAgICAgICAgbmVpZ2hib3JzW28udGFyZ2V0LmluZGV4XS5wdXNoKG8uc291cmNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNhbmRpZGF0ZXMgPSBuZWlnaGJvcnNbaV0sIGogPSAtMSwgbCA9IGNhbmRpZGF0ZXMubGVuZ3RoLCB4O1xuICAgICAgICB3aGlsZSAoKytqIDwgbCkgaWYgKCFpc05hTih4ID0gY2FuZGlkYXRlc1tqXVtkaW1lbnNpb25dKSkgcmV0dXJuIHg7XG4gICAgICAgIHJldHVybiBNYXRoLnJhbmRvbSgpICogc2l6ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmb3JjZS5yZXN1bWUoKTtcbiAgICB9O1xuICAgIGZvcmNlLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGZvcmNlLmFscGhhKC4xKTtcbiAgICB9O1xuICAgIGZvcmNlLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBmb3JjZS5hbHBoYSgwKTtcbiAgICB9O1xuICAgIGZvcmNlLmRyYWcgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghZHJhZykgZHJhZyA9IGQzLmJlaGF2aW9yLmRyYWcoKS5vcmlnaW4oZDNfaWRlbnRpdHkpLm9uKFwiZHJhZ3N0YXJ0LmZvcmNlXCIsIGQzX2xheW91dF9mb3JjZURyYWdzdGFydCkub24oXCJkcmFnLmZvcmNlXCIsIGRyYWdtb3ZlKS5vbihcImRyYWdlbmQuZm9yY2VcIiwgZDNfbGF5b3V0X2ZvcmNlRHJhZ2VuZCk7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkcmFnO1xuICAgICAgdGhpcy5vbihcIm1vdXNlb3Zlci5mb3JjZVwiLCBkM19sYXlvdXRfZm9yY2VNb3VzZW92ZXIpLm9uKFwibW91c2VvdXQuZm9yY2VcIiwgZDNfbGF5b3V0X2ZvcmNlTW91c2VvdXQpLmNhbGwoZHJhZyk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBkcmFnbW92ZShkKSB7XG4gICAgICBkLnB4ID0gZDMuZXZlbnQueCwgZC5weSA9IGQzLmV2ZW50Lnk7XG4gICAgICBmb3JjZS5yZXN1bWUoKTtcbiAgICB9XG4gICAgcmV0dXJuIGQzLnJlYmluZChmb3JjZSwgZXZlbnQsIFwib25cIik7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9mb3JjZURyYWdzdGFydChkKSB7XG4gICAgZC5maXhlZCB8PSAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9mb3JjZURyYWdlbmQoZCkge1xuICAgIGQuZml4ZWQgJj0gfjY7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2ZvcmNlTW91c2VvdmVyKGQpIHtcbiAgICBkLmZpeGVkIHw9IDQ7XG4gICAgZC5weCA9IGQueCwgZC5weSA9IGQueTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfZm9yY2VNb3VzZW91dChkKSB7XG4gICAgZC5maXhlZCAmPSB+NDtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfZm9yY2VBY2N1bXVsYXRlKHF1YWQsIGFscGhhLCBjaGFyZ2VzKSB7XG4gICAgdmFyIGN4ID0gMCwgY3kgPSAwO1xuICAgIHF1YWQuY2hhcmdlID0gMDtcbiAgICBpZiAoIXF1YWQubGVhZikge1xuICAgICAgdmFyIG5vZGVzID0gcXVhZC5ub2RlcywgbiA9IG5vZGVzLmxlbmd0aCwgaSA9IC0xLCBjO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgYyA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAoYyA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgZDNfbGF5b3V0X2ZvcmNlQWNjdW11bGF0ZShjLCBhbHBoYSwgY2hhcmdlcyk7XG4gICAgICAgIHF1YWQuY2hhcmdlICs9IGMuY2hhcmdlO1xuICAgICAgICBjeCArPSBjLmNoYXJnZSAqIGMuY3g7XG4gICAgICAgIGN5ICs9IGMuY2hhcmdlICogYy5jeTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHF1YWQucG9pbnQpIHtcbiAgICAgIGlmICghcXVhZC5sZWFmKSB7XG4gICAgICAgIHF1YWQucG9pbnQueCArPSBNYXRoLnJhbmRvbSgpIC0gLjU7XG4gICAgICAgIHF1YWQucG9pbnQueSArPSBNYXRoLnJhbmRvbSgpIC0gLjU7XG4gICAgICB9XG4gICAgICB2YXIgayA9IGFscGhhICogY2hhcmdlc1txdWFkLnBvaW50LmluZGV4XTtcbiAgICAgIHF1YWQuY2hhcmdlICs9IHF1YWQucG9pbnRDaGFyZ2UgPSBrO1xuICAgICAgY3ggKz0gayAqIHF1YWQucG9pbnQueDtcbiAgICAgIGN5ICs9IGsgKiBxdWFkLnBvaW50Lnk7XG4gICAgfVxuICAgIHF1YWQuY3ggPSBjeCAvIHF1YWQuY2hhcmdlO1xuICAgIHF1YWQuY3kgPSBjeSAvIHF1YWQuY2hhcmdlO1xuICB9XG4gIHZhciBkM19sYXlvdXRfZm9yY2VMaW5rRGlzdGFuY2UgPSAyMCwgZDNfbGF5b3V0X2ZvcmNlTGlua1N0cmVuZ3RoID0gMSwgZDNfbGF5b3V0X2ZvcmNlQ2hhcmdlRGlzdGFuY2UyID0gSW5maW5pdHk7XG4gIGQzLmxheW91dC5oaWVyYXJjaHkgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc29ydCA9IGQzX2xheW91dF9oaWVyYXJjaHlTb3J0LCBjaGlsZHJlbiA9IGQzX2xheW91dF9oaWVyYXJjaHlDaGlsZHJlbiwgdmFsdWUgPSBkM19sYXlvdXRfaGllcmFyY2h5VmFsdWU7XG4gICAgZnVuY3Rpb24gaGllcmFyY2h5KHJvb3QpIHtcbiAgICAgIHZhciBzdGFjayA9IFsgcm9vdCBdLCBub2RlcyA9IFtdLCBub2RlO1xuICAgICAgcm9vdC5kZXB0aCA9IDA7XG4gICAgICB3aGlsZSAoKG5vZGUgPSBzdGFjay5wb3AoKSkgIT0gbnVsbCkge1xuICAgICAgICBub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICBpZiAoKGNoaWxkcyA9IGNoaWxkcmVuLmNhbGwoaGllcmFyY2h5LCBub2RlLCBub2RlLmRlcHRoKSkgJiYgKG4gPSBjaGlsZHMubGVuZ3RoKSkge1xuICAgICAgICAgIHZhciBuLCBjaGlsZHMsIGNoaWxkO1xuICAgICAgICAgIHdoaWxlICgtLW4gPj0gMCkge1xuICAgICAgICAgICAgc3RhY2sucHVzaChjaGlsZCA9IGNoaWxkc1tuXSk7XG4gICAgICAgICAgICBjaGlsZC5wYXJlbnQgPSBub2RlO1xuICAgICAgICAgICAgY2hpbGQuZGVwdGggPSBub2RlLmRlcHRoICsgMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHZhbHVlKSBub2RlLnZhbHVlID0gMDtcbiAgICAgICAgICBub2RlLmNoaWxkcmVuID0gY2hpbGRzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh2YWx1ZSkgbm9kZS52YWx1ZSA9ICt2YWx1ZS5jYWxsKGhpZXJhcmNoeSwgbm9kZSwgbm9kZS5kZXB0aCkgfHwgMDtcbiAgICAgICAgICBkZWxldGUgbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdCwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICB2YXIgY2hpbGRzLCBwYXJlbnQ7XG4gICAgICAgIGlmIChzb3J0ICYmIChjaGlsZHMgPSBub2RlLmNoaWxkcmVuKSkgY2hpbGRzLnNvcnQoc29ydCk7XG4gICAgICAgIGlmICh2YWx1ZSAmJiAocGFyZW50ID0gbm9kZS5wYXJlbnQpKSBwYXJlbnQudmFsdWUgKz0gbm9kZS52YWx1ZTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICBoaWVyYXJjaHkuc29ydCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvcnQ7XG4gICAgICBzb3J0ID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkuY2hpbGRyZW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjaGlsZHJlbjtcbiAgICAgIGNoaWxkcmVuID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkudmFsdWUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB2YWx1ZTtcbiAgICAgIHZhbHVlID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkucmV2YWx1ZSA9IGZ1bmN0aW9uKHJvb3QpIHtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdCwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICAgIGlmIChub2RlLmNoaWxkcmVuKSBub2RlLnZhbHVlID0gMDtcbiAgICAgICAgfSk7XG4gICAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICB2YXIgcGFyZW50O1xuICAgICAgICAgIGlmICghbm9kZS5jaGlsZHJlbikgbm9kZS52YWx1ZSA9ICt2YWx1ZS5jYWxsKGhpZXJhcmNoeSwgbm9kZSwgbm9kZS5kZXB0aCkgfHwgMDtcbiAgICAgICAgICBpZiAocGFyZW50ID0gbm9kZS5wYXJlbnQpIHBhcmVudC52YWx1ZSArPSBub2RlLnZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByb290O1xuICAgIH07XG4gICAgcmV0dXJuIGhpZXJhcmNoeTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZChvYmplY3QsIGhpZXJhcmNoeSkge1xuICAgIGQzLnJlYmluZChvYmplY3QsIGhpZXJhcmNoeSwgXCJzb3J0XCIsIFwiY2hpbGRyZW5cIiwgXCJ2YWx1ZVwiKTtcbiAgICBvYmplY3Qubm9kZXMgPSBvYmplY3Q7XG4gICAgb2JqZWN0LmxpbmtzID0gZDNfbGF5b3V0X2hpZXJhcmNoeUxpbmtzO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QmVmb3JlKG5vZGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG5vZGVzID0gWyBub2RlIF07XG4gICAgd2hpbGUgKChub2RlID0gbm9kZXMucG9wKCkpICE9IG51bGwpIHtcbiAgICAgIGNhbGxiYWNrKG5vZGUpO1xuICAgICAgaWYgKChjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4pICYmIChuID0gY2hpbGRyZW4ubGVuZ3RoKSkge1xuICAgICAgICB2YXIgbiwgY2hpbGRyZW47XG4gICAgICAgIHdoaWxlICgtLW4gPj0gMCkgbm9kZXMucHVzaChjaGlsZHJlbltuXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKG5vZGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG5vZGVzID0gWyBub2RlIF0sIG5vZGVzMiA9IFtdO1xuICAgIHdoaWxlICgobm9kZSA9IG5vZGVzLnBvcCgpKSAhPSBudWxsKSB7XG4gICAgICBub2RlczIucHVzaChub2RlKTtcbiAgICAgIGlmICgoY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuKSAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkpIHtcbiAgICAgICAgdmFyIGkgPSAtMSwgbiwgY2hpbGRyZW47XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSBub2Rlcy5wdXNoKGNoaWxkcmVuW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gICAgd2hpbGUgKChub2RlID0gbm9kZXMyLnBvcCgpKSAhPSBudWxsKSB7XG4gICAgICBjYWxsYmFjayhub2RlKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeUNoaWxkcmVuKGQpIHtcbiAgICByZXR1cm4gZC5jaGlsZHJlbjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfaGllcmFyY2h5VmFsdWUoZCkge1xuICAgIHJldHVybiBkLnZhbHVlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaWVyYXJjaHlTb3J0KGEsIGIpIHtcbiAgICByZXR1cm4gYi52YWx1ZSAtIGEudmFsdWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeUxpbmtzKG5vZGVzKSB7XG4gICAgcmV0dXJuIGQzLm1lcmdlKG5vZGVzLm1hcChmdW5jdGlvbihwYXJlbnQpIHtcbiAgICAgIHJldHVybiAocGFyZW50LmNoaWxkcmVuIHx8IFtdKS5tYXAoZnVuY3Rpb24oY2hpbGQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzb3VyY2U6IHBhcmVudCxcbiAgICAgICAgICB0YXJnZXQ6IGNoaWxkXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9KSk7XG4gIH1cbiAgZDMubGF5b3V0LnBhcnRpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCksIHNpemUgPSBbIDEsIDEgXTtcbiAgICBmdW5jdGlvbiBwb3NpdGlvbihub2RlLCB4LCBkeCwgZHkpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG4gICAgICBub2RlLnggPSB4O1xuICAgICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIGR5O1xuICAgICAgbm9kZS5keCA9IGR4O1xuICAgICAgbm9kZS5keSA9IGR5O1xuICAgICAgaWYgKGNoaWxkcmVuICYmIChuID0gY2hpbGRyZW4ubGVuZ3RoKSkge1xuICAgICAgICB2YXIgaSA9IC0xLCBuLCBjLCBkO1xuICAgICAgICBkeCA9IG5vZGUudmFsdWUgPyBkeCAvIG5vZGUudmFsdWUgOiAwO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICAgIHBvc2l0aW9uKGMgPSBjaGlsZHJlbltpXSwgeCwgZCA9IGMudmFsdWUgKiBkeCwgZHkpO1xuICAgICAgICAgIHggKz0gZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBkZXB0aChub2RlKSB7XG4gICAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuLCBkID0gMDtcbiAgICAgIGlmIChjaGlsZHJlbiAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkpIHtcbiAgICAgICAgdmFyIGkgPSAtMSwgbjtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIGQgPSBNYXRoLm1heChkLCBkZXB0aChjaGlsZHJlbltpXSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIDEgKyBkO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJ0aXRpb24oZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSk7XG4gICAgICBwb3NpdGlvbihub2Rlc1swXSwgMCwgc2l6ZVswXSwgc2l6ZVsxXSAvIGRlcHRoKG5vZGVzWzBdKSk7XG4gICAgICByZXR1cm4gbm9kZXM7XG4gICAgfVxuICAgIHBhcnRpdGlvbi5zaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2l6ZTtcbiAgICAgIHNpemUgPSB4O1xuICAgICAgcmV0dXJuIHBhcnRpdGlvbjtcbiAgICB9O1xuICAgIHJldHVybiBkM19sYXlvdXRfaGllcmFyY2h5UmViaW5kKHBhcnRpdGlvbiwgaGllcmFyY2h5KTtcbiAgfTtcbiAgZDMubGF5b3V0LnBpZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZSA9IE51bWJlciwgc29ydCA9IGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSwgc3RhcnRBbmdsZSA9IDAsIGVuZEFuZ2xlID0gz4QsIHBhZEFuZ2xlID0gMDtcbiAgICBmdW5jdGlvbiBwaWUoZGF0YSkge1xuICAgICAgdmFyIG4gPSBkYXRhLmxlbmd0aCwgdmFsdWVzID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gK3ZhbHVlLmNhbGwocGllLCBkLCBpKTtcbiAgICAgIH0pLCBhID0gKyh0eXBlb2Ygc3RhcnRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gc3RhcnRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogc3RhcnRBbmdsZSksIGRhID0gKHR5cGVvZiBlbmRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gZW5kQW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IGVuZEFuZ2xlKSAtIGEsIHAgPSBNYXRoLm1pbihNYXRoLmFicyhkYSkgLyBuLCArKHR5cGVvZiBwYWRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gcGFkQW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IHBhZEFuZ2xlKSksIHBhID0gcCAqIChkYSA8IDAgPyAtMSA6IDEpLCBzdW0gPSBkMy5zdW0odmFsdWVzKSwgayA9IHN1bSA/IChkYSAtIG4gKiBwYSkgLyBzdW0gOiAwLCBpbmRleCA9IGQzLnJhbmdlKG4pLCBhcmNzID0gW10sIHY7XG4gICAgICBpZiAoc29ydCAhPSBudWxsKSBpbmRleC5zb3J0KHNvcnQgPT09IGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSA/IGZ1bmN0aW9uKGksIGopIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlc1tqXSAtIHZhbHVlc1tpXTtcbiAgICAgIH0gOiBmdW5jdGlvbihpLCBqKSB7XG4gICAgICAgIHJldHVybiBzb3J0KGRhdGFbaV0sIGRhdGFbal0pO1xuICAgICAgfSk7XG4gICAgICBpbmRleC5mb3JFYWNoKGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgYXJjc1tpXSA9IHtcbiAgICAgICAgICBkYXRhOiBkYXRhW2ldLFxuICAgICAgICAgIHZhbHVlOiB2ID0gdmFsdWVzW2ldLFxuICAgICAgICAgIHN0YXJ0QW5nbGU6IGEsXG4gICAgICAgICAgZW5kQW5nbGU6IGEgKz0gdiAqIGsgKyBwYSxcbiAgICAgICAgICBwYWRBbmdsZTogcFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYXJjcztcbiAgICB9XG4gICAgcGllLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdmFsdWU7XG4gICAgICB2YWx1ZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnNvcnQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3J0O1xuICAgICAgc29ydCA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGFydEFuZ2xlO1xuICAgICAgc3RhcnRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLmVuZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZW5kQW5nbGU7XG4gICAgICBlbmRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnBhZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkQW5nbGU7XG4gICAgICBwYWRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcmV0dXJuIHBpZTtcbiAgfTtcbiAgdmFyIGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSA9IHt9O1xuICBkMy5sYXlvdXQuc3RhY2sgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWVzID0gZDNfaWRlbnRpdHksIG9yZGVyID0gZDNfbGF5b3V0X3N0YWNrT3JkZXJEZWZhdWx0LCBvZmZzZXQgPSBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvLCBvdXQgPSBkM19sYXlvdXRfc3RhY2tPdXQsIHggPSBkM19sYXlvdXRfc3RhY2tYLCB5ID0gZDNfbGF5b3V0X3N0YWNrWTtcbiAgICBmdW5jdGlvbiBzdGFjayhkYXRhLCBpbmRleCkge1xuICAgICAgaWYgKCEobiA9IGRhdGEubGVuZ3RoKSkgcmV0dXJuIGRhdGE7XG4gICAgICB2YXIgc2VyaWVzID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gdmFsdWVzLmNhbGwoc3RhY2ssIGQsIGkpO1xuICAgICAgfSk7XG4gICAgICB2YXIgcG9pbnRzID0gc2VyaWVzLm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkLm1hcChmdW5jdGlvbih2LCBpKSB7XG4gICAgICAgICAgcmV0dXJuIFsgeC5jYWxsKHN0YWNrLCB2LCBpKSwgeS5jYWxsKHN0YWNrLCB2LCBpKSBdO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgdmFyIG9yZGVycyA9IG9yZGVyLmNhbGwoc3RhY2ssIHBvaW50cywgaW5kZXgpO1xuICAgICAgc2VyaWVzID0gZDMucGVybXV0ZShzZXJpZXMsIG9yZGVycyk7XG4gICAgICBwb2ludHMgPSBkMy5wZXJtdXRlKHBvaW50cywgb3JkZXJzKTtcbiAgICAgIHZhciBvZmZzZXRzID0gb2Zmc2V0LmNhbGwoc3RhY2ssIHBvaW50cywgaW5kZXgpO1xuICAgICAgdmFyIG0gPSBzZXJpZXNbMF0ubGVuZ3RoLCBuLCBpLCBqLCBvO1xuICAgICAgZm9yIChqID0gMDsgaiA8IG07ICsraikge1xuICAgICAgICBvdXQuY2FsbChzdGFjaywgc2VyaWVzWzBdW2pdLCBvID0gb2Zmc2V0c1tqXSwgcG9pbnRzWzBdW2pdWzFdKTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIG91dC5jYWxsKHN0YWNrLCBzZXJpZXNbaV1bal0sIG8gKz0gcG9pbnRzW2kgLSAxXVtqXVsxXSwgcG9pbnRzW2ldW2pdWzFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIHN0YWNrLnZhbHVlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZhbHVlcztcbiAgICAgIHZhbHVlcyA9IHg7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfTtcbiAgICBzdGFjay5vcmRlciA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG9yZGVyO1xuICAgICAgb3JkZXIgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6IGQzX2xheW91dF9zdGFja09yZGVycy5nZXQoeCkgfHwgZDNfbGF5b3V0X3N0YWNrT3JkZXJEZWZhdWx0O1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgc3RhY2sub2Zmc2V0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb2Zmc2V0O1xuICAgICAgb2Zmc2V0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBkM19sYXlvdXRfc3RhY2tPZmZzZXRzLmdldCh4KSB8fCBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvO1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgc3RhY2sueCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHg7XG4gICAgICB4ID0gejtcbiAgICAgIHJldHVybiBzdGFjaztcbiAgICB9O1xuICAgIHN0YWNrLnkgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5O1xuICAgICAgeSA9IHo7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfTtcbiAgICBzdGFjay5vdXQgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvdXQ7XG4gICAgICBvdXQgPSB6O1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgcmV0dXJuIHN0YWNrO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfc3RhY2tYKGQpIHtcbiAgICByZXR1cm4gZC54O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja1koZCkge1xuICAgIHJldHVybiBkLnk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrT3V0KGQsIHkwLCB5KSB7XG4gICAgZC55MCA9IHkwO1xuICAgIGQueSA9IHk7XG4gIH1cbiAgdmFyIGQzX2xheW91dF9zdGFja09yZGVycyA9IGQzLm1hcCh7XG4gICAgXCJpbnNpZGUtb3V0XCI6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHZhciBuID0gZGF0YS5sZW5ndGgsIGksIGosIG1heCA9IGRhdGEubWFwKGQzX2xheW91dF9zdGFja01heEluZGV4KSwgc3VtcyA9IGRhdGEubWFwKGQzX2xheW91dF9zdGFja1JlZHVjZVN1bSksIGluZGV4ID0gZDMucmFuZ2Uobikuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBtYXhbYV0gLSBtYXhbYl07XG4gICAgICB9KSwgdG9wID0gMCwgYm90dG9tID0gMCwgdG9wcyA9IFtdLCBib3R0b21zID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGogPSBpbmRleFtpXTtcbiAgICAgICAgaWYgKHRvcCA8IGJvdHRvbSkge1xuICAgICAgICAgIHRvcCArPSBzdW1zW2pdO1xuICAgICAgICAgIHRvcHMucHVzaChqKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBib3R0b20gKz0gc3Vtc1tqXTtcbiAgICAgICAgICBib3R0b21zLnB1c2goaik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBib3R0b21zLnJldmVyc2UoKS5jb25jYXQodG9wcyk7XG4gICAgfSxcbiAgICByZXZlcnNlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoZGF0YS5sZW5ndGgpLnJldmVyc2UoKTtcbiAgICB9LFxuICAgIFwiZGVmYXVsdFwiOiBkM19sYXlvdXRfc3RhY2tPcmRlckRlZmF1bHRcbiAgfSk7XG4gIHZhciBkM19sYXlvdXRfc3RhY2tPZmZzZXRzID0gZDMubWFwKHtcbiAgICBzaWxob3VldHRlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCBtID0gZGF0YVswXS5sZW5ndGgsIHN1bXMgPSBbXSwgbWF4ID0gMCwgaSwgaiwgbywgeTAgPSBbXTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgZm9yIChpID0gMCwgbyA9IDA7IGkgPCBuOyBpKyspIG8gKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgaWYgKG8gPiBtYXgpIG1heCA9IG87XG4gICAgICAgIHN1bXMucHVzaChvKTtcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgeTBbal0gPSAobWF4IC0gc3Vtc1tqXSkgLyAyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHkwO1xuICAgIH0sXG4gICAgd2lnZ2xlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCB4ID0gZGF0YVswXSwgbSA9IHgubGVuZ3RoLCBpLCBqLCBrLCBzMSwgczIsIHMzLCBkeCwgbywgbzAsIHkwID0gW107XG4gICAgICB5MFswXSA9IG8gPSBvMCA9IDA7XG4gICAgICBmb3IgKGogPSAxOyBqIDwgbTsgKytqKSB7XG4gICAgICAgIGZvciAoaSA9IDAsIHMxID0gMDsgaSA8IG47ICsraSkgczEgKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgZm9yIChpID0gMCwgczIgPSAwLCBkeCA9IHhbal1bMF0gLSB4W2ogLSAxXVswXTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGZvciAoayA9IDAsIHMzID0gKGRhdGFbaV1bal1bMV0gLSBkYXRhW2ldW2ogLSAxXVsxXSkgLyAoMiAqIGR4KTsgayA8IGk7ICsraykge1xuICAgICAgICAgICAgczMgKz0gKGRhdGFba11bal1bMV0gLSBkYXRhW2tdW2ogLSAxXVsxXSkgLyBkeDtcbiAgICAgICAgICB9XG4gICAgICAgICAgczIgKz0gczMgKiBkYXRhW2ldW2pdWzFdO1xuICAgICAgICB9XG4gICAgICAgIHkwW2pdID0gbyAtPSBzMSA/IHMyIC8gczEgKiBkeCA6IDA7XG4gICAgICAgIGlmIChvIDwgbzApIG8wID0gbztcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHkwW2pdIC09IG8wO1xuICAgICAgcmV0dXJuIHkwO1xuICAgIH0sXG4gICAgZXhwYW5kOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCBtID0gZGF0YVswXS5sZW5ndGgsIGsgPSAxIC8gbiwgaSwgaiwgbywgeTAgPSBbXTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgZm9yIChpID0gMCwgbyA9IDA7IGkgPCBuOyBpKyspIG8gKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgaWYgKG8pIGZvciAoaSA9IDA7IGkgPCBuOyBpKyspIGRhdGFbaV1bal1bMV0gLz0gbzsgZWxzZSBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSBkYXRhW2ldW2pdWzFdID0gaztcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHkwW2pdID0gMDtcbiAgICAgIHJldHVybiB5MDtcbiAgICB9LFxuICAgIHplcm86IGQzX2xheW91dF9zdGFja09mZnNldFplcm9cbiAgfSk7XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja09yZGVyRGVmYXVsdChkYXRhKSB7XG4gICAgcmV0dXJuIGQzLnJhbmdlKGRhdGEubGVuZ3RoKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvKGRhdGEpIHtcbiAgICB2YXIgaiA9IC0xLCBtID0gZGF0YVswXS5sZW5ndGgsIHkwID0gW107XG4gICAgd2hpbGUgKCsraiA8IG0pIHkwW2pdID0gMDtcbiAgICByZXR1cm4geTA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrTWF4SW5kZXgoYXJyYXkpIHtcbiAgICB2YXIgaSA9IDEsIGogPSAwLCB2ID0gYXJyYXlbMF1bMV0sIGssIG4gPSBhcnJheS5sZW5ndGg7XG4gICAgZm9yICg7aSA8IG47ICsraSkge1xuICAgICAgaWYgKChrID0gYXJyYXlbaV1bMV0pID4gdikge1xuICAgICAgICBqID0gaTtcbiAgICAgICAgdiA9IGs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBqO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja1JlZHVjZVN1bShkKSB7XG4gICAgcmV0dXJuIGQucmVkdWNlKGQzX2xheW91dF9zdGFja1N1bSwgMCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrU3VtKHAsIGQpIHtcbiAgICByZXR1cm4gcCArIGRbMV07XG4gIH1cbiAgZDMubGF5b3V0Lmhpc3RvZ3JhbSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmcmVxdWVuY3kgPSB0cnVlLCB2YWx1ZXIgPSBOdW1iZXIsIHJhbmdlciA9IGQzX2xheW91dF9oaXN0b2dyYW1SYW5nZSwgYmlubmVyID0gZDNfbGF5b3V0X2hpc3RvZ3JhbUJpblN0dXJnZXM7XG4gICAgZnVuY3Rpb24gaGlzdG9ncmFtKGRhdGEsIGkpIHtcbiAgICAgIHZhciBiaW5zID0gW10sIHZhbHVlcyA9IGRhdGEubWFwKHZhbHVlciwgdGhpcyksIHJhbmdlID0gcmFuZ2VyLmNhbGwodGhpcywgdmFsdWVzLCBpKSwgdGhyZXNob2xkcyA9IGJpbm5lci5jYWxsKHRoaXMsIHJhbmdlLCB2YWx1ZXMsIGkpLCBiaW4sIGkgPSAtMSwgbiA9IHZhbHVlcy5sZW5ndGgsIG0gPSB0aHJlc2hvbGRzLmxlbmd0aCAtIDEsIGsgPSBmcmVxdWVuY3kgPyAxIDogMSAvIG4sIHg7XG4gICAgICB3aGlsZSAoKytpIDwgbSkge1xuICAgICAgICBiaW4gPSBiaW5zW2ldID0gW107XG4gICAgICAgIGJpbi5keCA9IHRocmVzaG9sZHNbaSArIDFdIC0gKGJpbi54ID0gdGhyZXNob2xkc1tpXSk7XG4gICAgICAgIGJpbi55ID0gMDtcbiAgICAgIH1cbiAgICAgIGlmIChtID4gMCkge1xuICAgICAgICBpID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgeCA9IHZhbHVlc1tpXTtcbiAgICAgICAgICBpZiAoeCA+PSByYW5nZVswXSAmJiB4IDw9IHJhbmdlWzFdKSB7XG4gICAgICAgICAgICBiaW4gPSBiaW5zW2QzLmJpc2VjdCh0aHJlc2hvbGRzLCB4LCAxLCBtKSAtIDFdO1xuICAgICAgICAgICAgYmluLnkgKz0gaztcbiAgICAgICAgICAgIGJpbi5wdXNoKGRhdGFbaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJpbnM7XG4gICAgfVxuICAgIGhpc3RvZ3JhbS52YWx1ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZhbHVlcjtcbiAgICAgIHZhbHVlciA9IHg7XG4gICAgICByZXR1cm4gaGlzdG9ncmFtO1xuICAgIH07XG4gICAgaGlzdG9ncmFtLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2VyO1xuICAgICAgcmFuZ2VyID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBoaXN0b2dyYW07XG4gICAgfTtcbiAgICBoaXN0b2dyYW0uYmlucyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGJpbm5lcjtcbiAgICAgIGJpbm5lciA9IHR5cGVvZiB4ID09PSBcIm51bWJlclwiID8gZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIGQzX2xheW91dF9oaXN0b2dyYW1CaW5GaXhlZChyYW5nZSwgeCk7XG4gICAgICB9IDogZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBoaXN0b2dyYW07XG4gICAgfTtcbiAgICBoaXN0b2dyYW0uZnJlcXVlbmN5ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZnJlcXVlbmN5O1xuICAgICAgZnJlcXVlbmN5ID0gISF4O1xuICAgICAgcmV0dXJuIGhpc3RvZ3JhbTtcbiAgICB9O1xuICAgIHJldHVybiBoaXN0b2dyYW07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaXN0b2dyYW1CaW5TdHVyZ2VzKHJhbmdlLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpc3RvZ3JhbUJpbkZpeGVkKHJhbmdlLCBNYXRoLmNlaWwoTWF0aC5sb2codmFsdWVzLmxlbmd0aCkgLyBNYXRoLkxOMiArIDEpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfaGlzdG9ncmFtQmluRml4ZWQocmFuZ2UsIG4pIHtcbiAgICB2YXIgeCA9IC0xLCBiID0gK3JhbmdlWzBdLCBtID0gKHJhbmdlWzFdIC0gYikgLyBuLCBmID0gW107XG4gICAgd2hpbGUgKCsreCA8PSBuKSBmW3hdID0gbSAqIHggKyBiO1xuICAgIHJldHVybiBmO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaXN0b2dyYW1SYW5nZSh2YWx1ZXMpIHtcbiAgICByZXR1cm4gWyBkMy5taW4odmFsdWVzKSwgZDMubWF4KHZhbHVlcykgXTtcbiAgfVxuICBkMy5sYXlvdXQucGFjayA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCkuc29ydChkM19sYXlvdXRfcGFja1NvcnQpLCBwYWRkaW5nID0gMCwgc2l6ZSA9IFsgMSwgMSBdLCByYWRpdXM7XG4gICAgZnVuY3Rpb24gcGFjayhkLCBpKSB7XG4gICAgICB2YXIgbm9kZXMgPSBoaWVyYXJjaHkuY2FsbCh0aGlzLCBkLCBpKSwgcm9vdCA9IG5vZGVzWzBdLCB3ID0gc2l6ZVswXSwgaCA9IHNpemVbMV0sIHIgPSByYWRpdXMgPT0gbnVsbCA/IE1hdGguc3FydCA6IHR5cGVvZiByYWRpdXMgPT09IFwiZnVuY3Rpb25cIiA/IHJhZGl1cyA6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcmFkaXVzO1xuICAgICAgfTtcbiAgICAgIHJvb3QueCA9IHJvb3QueSA9IDA7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBmdW5jdGlvbihkKSB7XG4gICAgICAgIGQuciA9ICtyKGQudmFsdWUpO1xuICAgICAgfSk7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBkM19sYXlvdXRfcGFja1NpYmxpbmdzKTtcbiAgICAgIGlmIChwYWRkaW5nKSB7XG4gICAgICAgIHZhciBkciA9IHBhZGRpbmcgKiAocmFkaXVzID8gMSA6IE1hdGgubWF4KDIgKiByb290LnIgLyB3LCAyICogcm9vdC5yIC8gaCkpIC8gMjtcbiAgICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdCwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIGQuciArPSBkcjtcbiAgICAgICAgfSk7XG4gICAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGQzX2xheW91dF9wYWNrU2libGluZ3MpO1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgZC5yIC09IGRyO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGQzX2xheW91dF9wYWNrVHJhbnNmb3JtKHJvb3QsIHcgLyAyLCBoIC8gMiwgcmFkaXVzID8gMSA6IDEgLyBNYXRoLm1heCgyICogcm9vdC5yIC8gdywgMiAqIHJvb3QuciAvIGgpKTtcbiAgICAgIHJldHVybiBub2RlcztcbiAgICB9XG4gICAgcGFjay5zaXplID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2l6ZTtcbiAgICAgIHNpemUgPSBfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICBwYWNrLnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJhZGl1cztcbiAgICAgIHJhZGl1cyA9IF8gPT0gbnVsbCB8fCB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6ICtfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICBwYWNrLnBhZGRpbmcgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBwYWRkaW5nO1xuICAgICAgcGFkZGluZyA9ICtfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZChwYWNrLCBoaWVyYXJjaHkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1NvcnQoYSwgYikge1xuICAgIHJldHVybiBhLnZhbHVlIC0gYi52YWx1ZTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja0luc2VydChhLCBiKSB7XG4gICAgdmFyIGMgPSBhLl9wYWNrX25leHQ7XG4gICAgYS5fcGFja19uZXh0ID0gYjtcbiAgICBiLl9wYWNrX3ByZXYgPSBhO1xuICAgIGIuX3BhY2tfbmV4dCA9IGM7XG4gICAgYy5fcGFja19wcmV2ID0gYjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1NwbGljZShhLCBiKSB7XG4gICAgYS5fcGFja19uZXh0ID0gYjtcbiAgICBiLl9wYWNrX3ByZXYgPSBhO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhhLCBiKSB7XG4gICAgdmFyIGR4ID0gYi54IC0gYS54LCBkeSA9IGIueSAtIGEueSwgZHIgPSBhLnIgKyBiLnI7XG4gICAgcmV0dXJuIC45OTkgKiBkciAqIGRyID4gZHggKiBkeCArIGR5ICogZHk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3BhY2tTaWJsaW5ncyhub2RlKSB7XG4gICAgaWYgKCEobm9kZXMgPSBub2RlLmNoaWxkcmVuKSB8fCAhKG4gPSBub2Rlcy5sZW5ndGgpKSByZXR1cm47XG4gICAgdmFyIG5vZGVzLCB4TWluID0gSW5maW5pdHksIHhNYXggPSAtSW5maW5pdHksIHlNaW4gPSBJbmZpbml0eSwgeU1heCA9IC1JbmZpbml0eSwgYSwgYiwgYywgaSwgaiwgaywgbjtcbiAgICBmdW5jdGlvbiBib3VuZChub2RlKSB7XG4gICAgICB4TWluID0gTWF0aC5taW4obm9kZS54IC0gbm9kZS5yLCB4TWluKTtcbiAgICAgIHhNYXggPSBNYXRoLm1heChub2RlLnggKyBub2RlLnIsIHhNYXgpO1xuICAgICAgeU1pbiA9IE1hdGgubWluKG5vZGUueSAtIG5vZGUuciwgeU1pbik7XG4gICAgICB5TWF4ID0gTWF0aC5tYXgobm9kZS55ICsgbm9kZS5yLCB5TWF4KTtcbiAgICB9XG4gICAgbm9kZXMuZm9yRWFjaChkM19sYXlvdXRfcGFja0xpbmspO1xuICAgIGEgPSBub2Rlc1swXTtcbiAgICBhLnggPSAtYS5yO1xuICAgIGEueSA9IDA7XG4gICAgYm91bmQoYSk7XG4gICAgaWYgKG4gPiAxKSB7XG4gICAgICBiID0gbm9kZXNbMV07XG4gICAgICBiLnggPSBiLnI7XG4gICAgICBiLnkgPSAwO1xuICAgICAgYm91bmQoYik7XG4gICAgICBpZiAobiA+IDIpIHtcbiAgICAgICAgYyA9IG5vZGVzWzJdO1xuICAgICAgICBkM19sYXlvdXRfcGFja1BsYWNlKGEsIGIsIGMpO1xuICAgICAgICBib3VuZChjKTtcbiAgICAgICAgZDNfbGF5b3V0X3BhY2tJbnNlcnQoYSwgYyk7XG4gICAgICAgIGEuX3BhY2tfcHJldiA9IGM7XG4gICAgICAgIGQzX2xheW91dF9wYWNrSW5zZXJ0KGMsIGIpO1xuICAgICAgICBiID0gYS5fcGFja19uZXh0O1xuICAgICAgICBmb3IgKGkgPSAzOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgZDNfbGF5b3V0X3BhY2tQbGFjZShhLCBiLCBjID0gbm9kZXNbaV0pO1xuICAgICAgICAgIHZhciBpc2VjdCA9IDAsIHMxID0gMSwgczIgPSAxO1xuICAgICAgICAgIGZvciAoaiA9IGIuX3BhY2tfbmV4dDsgaiAhPT0gYjsgaiA9IGouX3BhY2tfbmV4dCwgczErKykge1xuICAgICAgICAgICAgaWYgKGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhqLCBjKSkge1xuICAgICAgICAgICAgICBpc2VjdCA9IDE7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaXNlY3QgPT0gMSkge1xuICAgICAgICAgICAgZm9yIChrID0gYS5fcGFja19wcmV2OyBrICE9PSBqLl9wYWNrX3ByZXY7IGsgPSBrLl9wYWNrX3ByZXYsIHMyKyspIHtcbiAgICAgICAgICAgICAgaWYgKGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhrLCBjKSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpc2VjdCkge1xuICAgICAgICAgICAgaWYgKHMxIDwgczIgfHwgczEgPT0gczIgJiYgYi5yIDwgYS5yKSBkM19sYXlvdXRfcGFja1NwbGljZShhLCBiID0gaik7IGVsc2UgZDNfbGF5b3V0X3BhY2tTcGxpY2UoYSA9IGssIGIpO1xuICAgICAgICAgICAgaS0tO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkM19sYXlvdXRfcGFja0luc2VydChhLCBjKTtcbiAgICAgICAgICAgIGIgPSBjO1xuICAgICAgICAgICAgYm91bmQoYyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBjeCA9ICh4TWluICsgeE1heCkgLyAyLCBjeSA9ICh5TWluICsgeU1heCkgLyAyLCBjciA9IDA7XG4gICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgYyA9IG5vZGVzW2ldO1xuICAgICAgYy54IC09IGN4O1xuICAgICAgYy55IC09IGN5O1xuICAgICAgY3IgPSBNYXRoLm1heChjciwgYy5yICsgTWF0aC5zcXJ0KGMueCAqIGMueCArIGMueSAqIGMueSkpO1xuICAgIH1cbiAgICBub2RlLnIgPSBjcjtcbiAgICBub2Rlcy5mb3JFYWNoKGQzX2xheW91dF9wYWNrVW5saW5rKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja0xpbmsobm9kZSkge1xuICAgIG5vZGUuX3BhY2tfbmV4dCA9IG5vZGUuX3BhY2tfcHJldiA9IG5vZGU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3BhY2tVbmxpbmsobm9kZSkge1xuICAgIGRlbGV0ZSBub2RlLl9wYWNrX25leHQ7XG4gICAgZGVsZXRlIG5vZGUuX3BhY2tfcHJldjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1RyYW5zZm9ybShub2RlLCB4LCB5LCBrKSB7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICBub2RlLnggPSB4ICs9IGsgKiBub2RlLng7XG4gICAgbm9kZS55ID0geSArPSBrICogbm9kZS55O1xuICAgIG5vZGUuciAqPSBrO1xuICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBkM19sYXlvdXRfcGFja1RyYW5zZm9ybShjaGlsZHJlbltpXSwgeCwgeSwgayk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9wYWNrUGxhY2UoYSwgYiwgYykge1xuICAgIHZhciBkYiA9IGEuciArIGMuciwgZHggPSBiLnggLSBhLngsIGR5ID0gYi55IC0gYS55O1xuICAgIGlmIChkYiAmJiAoZHggfHwgZHkpKSB7XG4gICAgICB2YXIgZGEgPSBiLnIgKyBjLnIsIGRjID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICBkYSAqPSBkYTtcbiAgICAgIGRiICo9IGRiO1xuICAgICAgdmFyIHggPSAuNSArIChkYiAtIGRhKSAvICgyICogZGMpLCB5ID0gTWF0aC5zcXJ0KE1hdGgubWF4KDAsIDIgKiBkYSAqIChkYiArIGRjKSAtIChkYiAtPSBkYykgKiBkYiAtIGRhICogZGEpKSAvICgyICogZGMpO1xuICAgICAgYy54ID0gYS54ICsgeCAqIGR4ICsgeSAqIGR5O1xuICAgICAgYy55ID0gYS55ICsgeCAqIGR5IC0geSAqIGR4O1xuICAgIH0gZWxzZSB7XG4gICAgICBjLnggPSBhLnggKyBkYjtcbiAgICAgIGMueSA9IGEueTtcbiAgICB9XG4gIH1cbiAgZDMubGF5b3V0LnRyZWUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaGllcmFyY2h5ID0gZDMubGF5b3V0LmhpZXJhcmNoeSgpLnNvcnQobnVsbCkudmFsdWUobnVsbCksIHNlcGFyYXRpb24gPSBkM19sYXlvdXRfdHJlZVNlcGFyYXRpb24sIHNpemUgPSBbIDEsIDEgXSwgbm9kZVNpemUgPSBudWxsO1xuICAgIGZ1bmN0aW9uIHRyZWUoZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSksIHJvb3QwID0gbm9kZXNbMF0sIHJvb3QxID0gd3JhcFRyZWUocm9vdDApO1xuICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdDEsIGZpcnN0V2FsayksIHJvb3QxLnBhcmVudC5tID0gLXJvb3QxLno7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDEsIHNlY29uZFdhbGspO1xuICAgICAgaWYgKG5vZGVTaXplKSBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDAsIHNpemVOb2RlKTsgZWxzZSB7XG4gICAgICAgIHZhciBsZWZ0ID0gcm9vdDAsIHJpZ2h0ID0gcm9vdDAsIGJvdHRvbSA9IHJvb3QwO1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDAsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICBpZiAobm9kZS54IDwgbGVmdC54KSBsZWZ0ID0gbm9kZTtcbiAgICAgICAgICBpZiAobm9kZS54ID4gcmlnaHQueCkgcmlnaHQgPSBub2RlO1xuICAgICAgICAgIGlmIChub2RlLmRlcHRoID4gYm90dG9tLmRlcHRoKSBib3R0b20gPSBub2RlO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHR4ID0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyIC0gbGVmdC54LCBreCA9IHNpemVbMF0gLyAocmlnaHQueCArIHNlcGFyYXRpb24ocmlnaHQsIGxlZnQpIC8gMiArIHR4KSwga3kgPSBzaXplWzFdIC8gKGJvdHRvbS5kZXB0aCB8fCAxKTtcbiAgICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QmVmb3JlKHJvb3QwLCBmdW5jdGlvbihub2RlKSB7XG4gICAgICAgICAgbm9kZS54ID0gKG5vZGUueCArIHR4KSAqIGt4O1xuICAgICAgICAgIG5vZGUueSA9IG5vZGUuZGVwdGggKiBreTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbm9kZXM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHdyYXBUcmVlKHJvb3QwKSB7XG4gICAgICB2YXIgcm9vdDEgPSB7XG4gICAgICAgIEE6IG51bGwsXG4gICAgICAgIGNoaWxkcmVuOiBbIHJvb3QwIF1cbiAgICAgIH0sIHF1ZXVlID0gWyByb290MSBdLCBub2RlMTtcbiAgICAgIHdoaWxlICgobm9kZTEgPSBxdWV1ZS5wb3AoKSkgIT0gbnVsbCkge1xuICAgICAgICBmb3IgKHZhciBjaGlsZHJlbiA9IG5vZGUxLmNoaWxkcmVuLCBjaGlsZCwgaSA9IDAsIG4gPSBjaGlsZHJlbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBxdWV1ZS5wdXNoKChjaGlsZHJlbltpXSA9IGNoaWxkID0ge1xuICAgICAgICAgICAgXzogY2hpbGRyZW5baV0sXG4gICAgICAgICAgICBwYXJlbnQ6IG5vZGUxLFxuICAgICAgICAgICAgY2hpbGRyZW46IChjaGlsZCA9IGNoaWxkcmVuW2ldLmNoaWxkcmVuKSAmJiBjaGlsZC5zbGljZSgpIHx8IFtdLFxuICAgICAgICAgICAgQTogbnVsbCxcbiAgICAgICAgICAgIGE6IG51bGwsXG4gICAgICAgICAgICB6OiAwLFxuICAgICAgICAgICAgbTogMCxcbiAgICAgICAgICAgIGM6IDAsXG4gICAgICAgICAgICBzOiAwLFxuICAgICAgICAgICAgdDogbnVsbCxcbiAgICAgICAgICAgIGk6IGlcbiAgICAgICAgICB9KS5hID0gY2hpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcm9vdDEuY2hpbGRyZW5bMF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGZpcnN0V2Fsayh2KSB7XG4gICAgICB2YXIgY2hpbGRyZW4gPSB2LmNoaWxkcmVuLCBzaWJsaW5ncyA9IHYucGFyZW50LmNoaWxkcmVuLCB3ID0gdi5pID8gc2libGluZ3Nbdi5pIC0gMV0gOiBudWxsO1xuICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICBkM19sYXlvdXRfdHJlZVNoaWZ0KHYpO1xuICAgICAgICB2YXIgbWlkcG9pbnQgPSAoY2hpbGRyZW5bMF0ueiArIGNoaWxkcmVuW2NoaWxkcmVuLmxlbmd0aCAtIDFdLnopIC8gMjtcbiAgICAgICAgaWYgKHcpIHtcbiAgICAgICAgICB2LnogPSB3LnogKyBzZXBhcmF0aW9uKHYuXywgdy5fKTtcbiAgICAgICAgICB2Lm0gPSB2LnogLSBtaWRwb2ludDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2LnogPSBtaWRwb2ludDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh3KSB7XG4gICAgICAgIHYueiA9IHcueiArIHNlcGFyYXRpb24odi5fLCB3Ll8pO1xuICAgICAgfVxuICAgICAgdi5wYXJlbnQuQSA9IGFwcG9ydGlvbih2LCB3LCB2LnBhcmVudC5BIHx8IHNpYmxpbmdzWzBdKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2Vjb25kV2Fsayh2KSB7XG4gICAgICB2Ll8ueCA9IHYueiArIHYucGFyZW50Lm07XG4gICAgICB2Lm0gKz0gdi5wYXJlbnQubTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXBwb3J0aW9uKHYsIHcsIGFuY2VzdG9yKSB7XG4gICAgICBpZiAodykge1xuICAgICAgICB2YXIgdmlwID0gdiwgdm9wID0gdiwgdmltID0gdywgdm9tID0gdmlwLnBhcmVudC5jaGlsZHJlblswXSwgc2lwID0gdmlwLm0sIHNvcCA9IHZvcC5tLCBzaW0gPSB2aW0ubSwgc29tID0gdm9tLm0sIHNoaWZ0O1xuICAgICAgICB3aGlsZSAodmltID0gZDNfbGF5b3V0X3RyZWVSaWdodCh2aW0pLCB2aXAgPSBkM19sYXlvdXRfdHJlZUxlZnQodmlwKSwgdmltICYmIHZpcCkge1xuICAgICAgICAgIHZvbSA9IGQzX2xheW91dF90cmVlTGVmdCh2b20pO1xuICAgICAgICAgIHZvcCA9IGQzX2xheW91dF90cmVlUmlnaHQodm9wKTtcbiAgICAgICAgICB2b3AuYSA9IHY7XG4gICAgICAgICAgc2hpZnQgPSB2aW0ueiArIHNpbSAtIHZpcC56IC0gc2lwICsgc2VwYXJhdGlvbih2aW0uXywgdmlwLl8pO1xuICAgICAgICAgIGlmIChzaGlmdCA+IDApIHtcbiAgICAgICAgICAgIGQzX2xheW91dF90cmVlTW92ZShkM19sYXlvdXRfdHJlZUFuY2VzdG9yKHZpbSwgdiwgYW5jZXN0b3IpLCB2LCBzaGlmdCk7XG4gICAgICAgICAgICBzaXAgKz0gc2hpZnQ7XG4gICAgICAgICAgICBzb3AgKz0gc2hpZnQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNpbSArPSB2aW0ubTtcbiAgICAgICAgICBzaXAgKz0gdmlwLm07XG4gICAgICAgICAgc29tICs9IHZvbS5tO1xuICAgICAgICAgIHNvcCArPSB2b3AubTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmltICYmICFkM19sYXlvdXRfdHJlZVJpZ2h0KHZvcCkpIHtcbiAgICAgICAgICB2b3AudCA9IHZpbTtcbiAgICAgICAgICB2b3AubSArPSBzaW0gLSBzb3A7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZpcCAmJiAhZDNfbGF5b3V0X3RyZWVMZWZ0KHZvbSkpIHtcbiAgICAgICAgICB2b20udCA9IHZpcDtcbiAgICAgICAgICB2b20ubSArPSBzaXAgLSBzb207XG4gICAgICAgICAgYW5jZXN0b3IgPSB2O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYW5jZXN0b3I7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNpemVOb2RlKG5vZGUpIHtcbiAgICAgIG5vZGUueCAqPSBzaXplWzBdO1xuICAgICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIHNpemVbMV07XG4gICAgfVxuICAgIHRyZWUuc2VwYXJhdGlvbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNlcGFyYXRpb247XG4gICAgICBzZXBhcmF0aW9uID0geDtcbiAgICAgIHJldHVybiB0cmVlO1xuICAgIH07XG4gICAgdHJlZS5zaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZVNpemUgPyBudWxsIDogc2l6ZTtcbiAgICAgIG5vZGVTaXplID0gKHNpemUgPSB4KSA9PSBudWxsID8gc2l6ZU5vZGUgOiBudWxsO1xuICAgICAgcmV0dXJuIHRyZWU7XG4gICAgfTtcbiAgICB0cmVlLm5vZGVTaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZVNpemUgPyBzaXplIDogbnVsbDtcbiAgICAgIG5vZGVTaXplID0gKHNpemUgPSB4KSA9PSBudWxsID8gbnVsbCA6IHNpemVOb2RlO1xuICAgICAgcmV0dXJuIHRyZWU7XG4gICAgfTtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZCh0cmVlLCBoaWVyYXJjaHkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfdHJlZVNlcGFyYXRpb24oYSwgYikge1xuICAgIHJldHVybiBhLnBhcmVudCA9PSBiLnBhcmVudCA/IDEgOiAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlTGVmdCh2KSB7XG4gICAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbjtcbiAgICByZXR1cm4gY2hpbGRyZW4ubGVuZ3RoID8gY2hpbGRyZW5bMF0gOiB2LnQ7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3RyZWVSaWdodCh2KSB7XG4gICAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbiwgbjtcbiAgICByZXR1cm4gKG4gPSBjaGlsZHJlbi5sZW5ndGgpID8gY2hpbGRyZW5bbiAtIDFdIDogdi50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlTW92ZSh3bSwgd3AsIHNoaWZ0KSB7XG4gICAgdmFyIGNoYW5nZSA9IHNoaWZ0IC8gKHdwLmkgLSB3bS5pKTtcbiAgICB3cC5jIC09IGNoYW5nZTtcbiAgICB3cC5zICs9IHNoaWZ0O1xuICAgIHdtLmMgKz0gY2hhbmdlO1xuICAgIHdwLnogKz0gc2hpZnQ7XG4gICAgd3AubSArPSBzaGlmdDtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfdHJlZVNoaWZ0KHYpIHtcbiAgICB2YXIgc2hpZnQgPSAwLCBjaGFuZ2UgPSAwLCBjaGlsZHJlbiA9IHYuY2hpbGRyZW4sIGkgPSBjaGlsZHJlbi5sZW5ndGgsIHc7XG4gICAgd2hpbGUgKC0taSA+PSAwKSB7XG4gICAgICB3ID0gY2hpbGRyZW5baV07XG4gICAgICB3LnogKz0gc2hpZnQ7XG4gICAgICB3Lm0gKz0gc2hpZnQ7XG4gICAgICBzaGlmdCArPSB3LnMgKyAoY2hhbmdlICs9IHcuYyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlQW5jZXN0b3IodmltLCB2LCBhbmNlc3Rvcikge1xuICAgIHJldHVybiB2aW0uYS5wYXJlbnQgPT09IHYucGFyZW50ID8gdmltLmEgOiBhbmNlc3RvcjtcbiAgfVxuICBkMy5sYXlvdXQuY2x1c3RlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCkuc29ydChudWxsKS52YWx1ZShudWxsKSwgc2VwYXJhdGlvbiA9IGQzX2xheW91dF90cmVlU2VwYXJhdGlvbiwgc2l6ZSA9IFsgMSwgMSBdLCBub2RlU2l6ZSA9IGZhbHNlO1xuICAgIGZ1bmN0aW9uIGNsdXN0ZXIoZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSksIHJvb3QgPSBub2Rlc1swXSwgcHJldmlvdXNOb2RlLCB4ID0gMDtcbiAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgaWYgKGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgIG5vZGUueCA9IGQzX2xheW91dF9jbHVzdGVyWChjaGlsZHJlbik7XG4gICAgICAgICAgbm9kZS55ID0gZDNfbGF5b3V0X2NsdXN0ZXJZKGNoaWxkcmVuKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBub2RlLnggPSBwcmV2aW91c05vZGUgPyB4ICs9IHNlcGFyYXRpb24obm9kZSwgcHJldmlvdXNOb2RlKSA6IDA7XG4gICAgICAgICAgbm9kZS55ID0gMDtcbiAgICAgICAgICBwcmV2aW91c05vZGUgPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHZhciBsZWZ0ID0gZDNfbGF5b3V0X2NsdXN0ZXJMZWZ0KHJvb3QpLCByaWdodCA9IGQzX2xheW91dF9jbHVzdGVyUmlnaHQocm9vdCksIHgwID0gbGVmdC54IC0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyLCB4MSA9IHJpZ2h0LnggKyBzZXBhcmF0aW9uKHJpZ2h0LCBsZWZ0KSAvIDI7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBub2RlU2l6ZSA/IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgbm9kZS54ID0gKG5vZGUueCAtIHJvb3QueCkgKiBzaXplWzBdO1xuICAgICAgICBub2RlLnkgPSAocm9vdC55IC0gbm9kZS55KSAqIHNpemVbMV07XG4gICAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgICBub2RlLnggPSAobm9kZS54IC0geDApIC8gKHgxIC0geDApICogc2l6ZVswXTtcbiAgICAgICAgbm9kZS55ID0gKDEgLSAocm9vdC55ID8gbm9kZS55IC8gcm9vdC55IDogMSkpICogc2l6ZVsxXTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICBjbHVzdGVyLnNlcGFyYXRpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzZXBhcmF0aW9uO1xuICAgICAgc2VwYXJhdGlvbiA9IHg7XG4gICAgICByZXR1cm4gY2x1c3RlcjtcbiAgICB9O1xuICAgIGNsdXN0ZXIuc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVTaXplID8gbnVsbCA6IHNpemU7XG4gICAgICBub2RlU2l6ZSA9IChzaXplID0geCkgPT0gbnVsbDtcbiAgICAgIHJldHVybiBjbHVzdGVyO1xuICAgIH07XG4gICAgY2x1c3Rlci5ub2RlU2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVTaXplID8gc2l6ZSA6IG51bGw7XG4gICAgICBub2RlU2l6ZSA9IChzaXplID0geCkgIT0gbnVsbDtcbiAgICAgIHJldHVybiBjbHVzdGVyO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX2xheW91dF9oaWVyYXJjaHlSZWJpbmQoY2x1c3RlciwgaGllcmFyY2h5KTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2NsdXN0ZXJZKGNoaWxkcmVuKSB7XG4gICAgcmV0dXJuIDEgKyBkMy5tYXgoY2hpbGRyZW4sIGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgICByZXR1cm4gY2hpbGQueTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfY2x1c3RlclgoY2hpbGRyZW4pIHtcbiAgICByZXR1cm4gY2hpbGRyZW4ucmVkdWNlKGZ1bmN0aW9uKHgsIGNoaWxkKSB7XG4gICAgICByZXR1cm4geCArIGNoaWxkLng7XG4gICAgfSwgMCkgLyBjaGlsZHJlbi5sZW5ndGg7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2NsdXN0ZXJMZWZ0KG5vZGUpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgIHJldHVybiBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggPyBkM19sYXlvdXRfY2x1c3RlckxlZnQoY2hpbGRyZW5bMF0pIDogbm9kZTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfY2x1c3RlclJpZ2h0KG5vZGUpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuLCBuO1xuICAgIHJldHVybiBjaGlsZHJlbiAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkgPyBkM19sYXlvdXRfY2x1c3RlclJpZ2h0KGNoaWxkcmVuW24gLSAxXSkgOiBub2RlO1xuICB9XG4gIGQzLmxheW91dC50cmVlbWFwID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGhpZXJhcmNoeSA9IGQzLmxheW91dC5oaWVyYXJjaHkoKSwgcm91bmQgPSBNYXRoLnJvdW5kLCBzaXplID0gWyAxLCAxIF0sIHBhZGRpbmcgPSBudWxsLCBwYWQgPSBkM19sYXlvdXRfdHJlZW1hcFBhZE51bGwsIHN0aWNreSA9IGZhbHNlLCBzdGlja2llcywgbW9kZSA9IFwic3F1YXJpZnlcIiwgcmF0aW8gPSAuNSAqICgxICsgTWF0aC5zcXJ0KDUpKTtcbiAgICBmdW5jdGlvbiBzY2FsZShjaGlsZHJlbiwgaykge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGNoaWxkcmVuLmxlbmd0aCwgY2hpbGQsIGFyZWE7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBhcmVhID0gKGNoaWxkID0gY2hpbGRyZW5baV0pLnZhbHVlICogKGsgPCAwID8gMCA6IGspO1xuICAgICAgICBjaGlsZC5hcmVhID0gaXNOYU4oYXJlYSkgfHwgYXJlYSA8PSAwID8gMCA6IGFyZWE7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNxdWFyaWZ5KG5vZGUpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG4gICAgICBpZiAoY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgIHZhciByZWN0ID0gcGFkKG5vZGUpLCByb3cgPSBbXSwgcmVtYWluaW5nID0gY2hpbGRyZW4uc2xpY2UoKSwgY2hpbGQsIGJlc3QgPSBJbmZpbml0eSwgc2NvcmUsIHUgPSBtb2RlID09PSBcInNsaWNlXCIgPyByZWN0LmR4IDogbW9kZSA9PT0gXCJkaWNlXCIgPyByZWN0LmR5IDogbW9kZSA9PT0gXCJzbGljZS1kaWNlXCIgPyBub2RlLmRlcHRoICYgMSA/IHJlY3QuZHkgOiByZWN0LmR4IDogTWF0aC5taW4ocmVjdC5keCwgcmVjdC5keSksIG47XG4gICAgICAgIHNjYWxlKHJlbWFpbmluZywgcmVjdC5keCAqIHJlY3QuZHkgLyBub2RlLnZhbHVlKTtcbiAgICAgICAgcm93LmFyZWEgPSAwO1xuICAgICAgICB3aGlsZSAoKG4gPSByZW1haW5pbmcubGVuZ3RoKSA+IDApIHtcbiAgICAgICAgICByb3cucHVzaChjaGlsZCA9IHJlbWFpbmluZ1tuIC0gMV0pO1xuICAgICAgICAgIHJvdy5hcmVhICs9IGNoaWxkLmFyZWE7XG4gICAgICAgICAgaWYgKG1vZGUgIT09IFwic3F1YXJpZnlcIiB8fCAoc2NvcmUgPSB3b3JzdChyb3csIHUpKSA8PSBiZXN0KSB7XG4gICAgICAgICAgICByZW1haW5pbmcucG9wKCk7XG4gICAgICAgICAgICBiZXN0ID0gc2NvcmU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvdy5hcmVhIC09IHJvdy5wb3AoKS5hcmVhO1xuICAgICAgICAgICAgcG9zaXRpb24ocm93LCB1LCByZWN0LCBmYWxzZSk7XG4gICAgICAgICAgICB1ID0gTWF0aC5taW4ocmVjdC5keCwgcmVjdC5keSk7XG4gICAgICAgICAgICByb3cubGVuZ3RoID0gcm93LmFyZWEgPSAwO1xuICAgICAgICAgICAgYmVzdCA9IEluZmluaXR5O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocm93Lmxlbmd0aCkge1xuICAgICAgICAgIHBvc2l0aW9uKHJvdywgdSwgcmVjdCwgdHJ1ZSk7XG4gICAgICAgICAgcm93Lmxlbmd0aCA9IHJvdy5hcmVhID0gMDtcbiAgICAgICAgfVxuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKHNxdWFyaWZ5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gc3RpY2tpZnkobm9kZSkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgIGlmIChjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBwYWQobm9kZSksIHJlbWFpbmluZyA9IGNoaWxkcmVuLnNsaWNlKCksIGNoaWxkLCByb3cgPSBbXTtcbiAgICAgICAgc2NhbGUocmVtYWluaW5nLCByZWN0LmR4ICogcmVjdC5keSAvIG5vZGUudmFsdWUpO1xuICAgICAgICByb3cuYXJlYSA9IDA7XG4gICAgICAgIHdoaWxlIChjaGlsZCA9IHJlbWFpbmluZy5wb3AoKSkge1xuICAgICAgICAgIHJvdy5wdXNoKGNoaWxkKTtcbiAgICAgICAgICByb3cuYXJlYSArPSBjaGlsZC5hcmVhO1xuICAgICAgICAgIGlmIChjaGlsZC56ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uKHJvdywgY2hpbGQueiA/IHJlY3QuZHggOiByZWN0LmR5LCByZWN0LCAhcmVtYWluaW5nLmxlbmd0aCk7XG4gICAgICAgICAgICByb3cubGVuZ3RoID0gcm93LmFyZWEgPSAwO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKHN0aWNraWZ5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gd29yc3Qocm93LCB1KSB7XG4gICAgICB2YXIgcyA9IHJvdy5hcmVhLCByLCBybWF4ID0gMCwgcm1pbiA9IEluZmluaXR5LCBpID0gLTEsIG4gPSByb3cubGVuZ3RoO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgaWYgKCEociA9IHJvd1tpXS5hcmVhKSkgY29udGludWU7XG4gICAgICAgIGlmIChyIDwgcm1pbikgcm1pbiA9IHI7XG4gICAgICAgIGlmIChyID4gcm1heCkgcm1heCA9IHI7XG4gICAgICB9XG4gICAgICBzICo9IHM7XG4gICAgICB1ICo9IHU7XG4gICAgICByZXR1cm4gcyA/IE1hdGgubWF4KHUgKiBybWF4ICogcmF0aW8gLyBzLCBzIC8gKHUgKiBybWluICogcmF0aW8pKSA6IEluZmluaXR5O1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb3NpdGlvbihyb3csIHUsIHJlY3QsIGZsdXNoKSB7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gcm93Lmxlbmd0aCwgeCA9IHJlY3QueCwgeSA9IHJlY3QueSwgdiA9IHUgPyByb3VuZChyb3cuYXJlYSAvIHUpIDogMCwgbztcbiAgICAgIGlmICh1ID09IHJlY3QuZHgpIHtcbiAgICAgICAgaWYgKGZsdXNoIHx8IHYgPiByZWN0LmR5KSB2ID0gcmVjdC5keTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgICBvID0gcm93W2ldO1xuICAgICAgICAgIG8ueCA9IHg7XG4gICAgICAgICAgby55ID0geTtcbiAgICAgICAgICBvLmR5ID0gdjtcbiAgICAgICAgICB4ICs9IG8uZHggPSBNYXRoLm1pbihyZWN0LnggKyByZWN0LmR4IC0geCwgdiA/IHJvdW5kKG8uYXJlYSAvIHYpIDogMCk7XG4gICAgICAgIH1cbiAgICAgICAgby56ID0gdHJ1ZTtcbiAgICAgICAgby5keCArPSByZWN0LnggKyByZWN0LmR4IC0geDtcbiAgICAgICAgcmVjdC55ICs9IHY7XG4gICAgICAgIHJlY3QuZHkgLT0gdjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmbHVzaCB8fCB2ID4gcmVjdC5keCkgdiA9IHJlY3QuZHg7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgbyA9IHJvd1tpXTtcbiAgICAgICAgICBvLnggPSB4O1xuICAgICAgICAgIG8ueSA9IHk7XG4gICAgICAgICAgby5keCA9IHY7XG4gICAgICAgICAgeSArPSBvLmR5ID0gTWF0aC5taW4ocmVjdC55ICsgcmVjdC5keSAtIHksIHYgPyByb3VuZChvLmFyZWEgLyB2KSA6IDApO1xuICAgICAgICB9XG4gICAgICAgIG8ueiA9IGZhbHNlO1xuICAgICAgICBvLmR5ICs9IHJlY3QueSArIHJlY3QuZHkgLSB5O1xuICAgICAgICByZWN0LnggKz0gdjtcbiAgICAgICAgcmVjdC5keCAtPSB2O1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiB0cmVlbWFwKGQpIHtcbiAgICAgIHZhciBub2RlcyA9IHN0aWNraWVzIHx8IGhpZXJhcmNoeShkKSwgcm9vdCA9IG5vZGVzWzBdO1xuICAgICAgcm9vdC54ID0gcm9vdC55ID0gMDtcbiAgICAgIGlmIChyb290LnZhbHVlKSByb290LmR4ID0gc2l6ZVswXSwgcm9vdC5keSA9IHNpemVbMV07IGVsc2Ugcm9vdC5keCA9IHJvb3QuZHkgPSAwO1xuICAgICAgaWYgKHN0aWNraWVzKSBoaWVyYXJjaHkucmV2YWx1ZShyb290KTtcbiAgICAgIHNjYWxlKFsgcm9vdCBdLCByb290LmR4ICogcm9vdC5keSAvIHJvb3QudmFsdWUpO1xuICAgICAgKHN0aWNraWVzID8gc3RpY2tpZnkgOiBzcXVhcmlmeSkocm9vdCk7XG4gICAgICBpZiAoc3RpY2t5KSBzdGlja2llcyA9IG5vZGVzO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICB0cmVlbWFwLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzaXplO1xuICAgICAgc2l6ZSA9IHg7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHRyZWVtYXAucGFkZGluZyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBhZGRpbmc7XG4gICAgICBmdW5jdGlvbiBwYWRGdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHZhciBwID0geC5jYWxsKHRyZWVtYXAsIG5vZGUsIG5vZGUuZGVwdGgpO1xuICAgICAgICByZXR1cm4gcCA9PSBudWxsID8gZDNfbGF5b3V0X3RyZWVtYXBQYWROdWxsKG5vZGUpIDogZDNfbGF5b3V0X3RyZWVtYXBQYWQobm9kZSwgdHlwZW9mIHAgPT09IFwibnVtYmVyXCIgPyBbIHAsIHAsIHAsIHAgXSA6IHApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcGFkQ29uc3RhbnQobm9kZSkge1xuICAgICAgICByZXR1cm4gZDNfbGF5b3V0X3RyZWVtYXBQYWQobm9kZSwgeCk7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZTtcbiAgICAgIHBhZCA9IChwYWRkaW5nID0geCkgPT0gbnVsbCA/IGQzX2xheW91dF90cmVlbWFwUGFkTnVsbCA6ICh0eXBlID0gdHlwZW9mIHgpID09PSBcImZ1bmN0aW9uXCIgPyBwYWRGdW5jdGlvbiA6IHR5cGUgPT09IFwibnVtYmVyXCIgPyAoeCA9IFsgeCwgeCwgeCwgeCBdLCBcbiAgICAgIHBhZENvbnN0YW50KSA6IHBhZENvbnN0YW50O1xuICAgICAgcmV0dXJuIHRyZWVtYXA7XG4gICAgfTtcbiAgICB0cmVlbWFwLnJvdW5kID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcm91bmQgIT0gTnVtYmVyO1xuICAgICAgcm91bmQgPSB4ID8gTWF0aC5yb3VuZCA6IE51bWJlcjtcbiAgICAgIHJldHVybiB0cmVlbWFwO1xuICAgIH07XG4gICAgdHJlZW1hcC5zdGlja3kgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGlja3k7XG4gICAgICBzdGlja3kgPSB4O1xuICAgICAgc3RpY2tpZXMgPSBudWxsO1xuICAgICAgcmV0dXJuIHRyZWVtYXA7XG4gICAgfTtcbiAgICB0cmVlbWFwLnJhdGlvID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmF0aW87XG4gICAgICByYXRpbyA9IHg7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHRyZWVtYXAubW9kZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1vZGU7XG4gICAgICBtb2RlID0geCArIFwiXCI7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHJldHVybiBkM19sYXlvdXRfaGllcmFyY2h5UmViaW5kKHRyZWVtYXAsIGhpZXJhcmNoeSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlbWFwUGFkTnVsbChub2RlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IG5vZGUueCxcbiAgICAgIHk6IG5vZGUueSxcbiAgICAgIGR4OiBub2RlLmR4LFxuICAgICAgZHk6IG5vZGUuZHlcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlbWFwUGFkKG5vZGUsIHBhZGRpbmcpIHtcbiAgICB2YXIgeCA9IG5vZGUueCArIHBhZGRpbmdbM10sIHkgPSBub2RlLnkgKyBwYWRkaW5nWzBdLCBkeCA9IG5vZGUuZHggLSBwYWRkaW5nWzFdIC0gcGFkZGluZ1szXSwgZHkgPSBub2RlLmR5IC0gcGFkZGluZ1swXSAtIHBhZGRpbmdbMl07XG4gICAgaWYgKGR4IDwgMCkge1xuICAgICAgeCArPSBkeCAvIDI7XG4gICAgICBkeCA9IDA7XG4gICAgfVxuICAgIGlmIChkeSA8IDApIHtcbiAgICAgIHkgKz0gZHkgLyAyO1xuICAgICAgZHkgPSAwO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgeDogeCxcbiAgICAgIHk6IHksXG4gICAgICBkeDogZHgsXG4gICAgICBkeTogZHlcbiAgICB9O1xuICB9XG4gIGQzLnJhbmRvbSA9IHtcbiAgICBub3JtYWw6IGZ1bmN0aW9uKMK1LCDPgykge1xuICAgICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgaWYgKG4gPCAyKSDPgyA9IDE7XG4gICAgICBpZiAobiA8IDEpIMK1ID0gMDtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHgsIHksIHI7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICB4ID0gTWF0aC5yYW5kb20oKSAqIDIgLSAxO1xuICAgICAgICAgIHkgPSBNYXRoLnJhbmRvbSgpICogMiAtIDE7XG4gICAgICAgICAgciA9IHggKiB4ICsgeSAqIHk7XG4gICAgICAgIH0gd2hpbGUgKCFyIHx8IHIgPiAxKTtcbiAgICAgICAgcmV0dXJuIMK1ICsgz4MgKiB4ICogTWF0aC5zcXJ0KC0yICogTWF0aC5sb2cocikgLyByKTtcbiAgICAgIH07XG4gICAgfSxcbiAgICBsb2dOb3JtYWw6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJhbmRvbSA9IGQzLnJhbmRvbS5ub3JtYWwuYXBwbHkoZDMsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmV4cChyYW5kb20oKSk7XG4gICAgICB9O1xuICAgIH0sXG4gICAgYmF0ZXM6IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHZhciByYW5kb20gPSBkMy5yYW5kb20uaXJ3aW5IYWxsKG0pO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcmFuZG9tKCkgLyBtO1xuICAgICAgfTtcbiAgICB9LFxuICAgIGlyd2luSGFsbDogZnVuY3Rpb24obSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBzID0gMCwgaiA9IDA7IGogPCBtOyBqKyspIHMgKz0gTWF0aC5yYW5kb20oKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgICB9O1xuICAgIH1cbiAgfTtcbiAgZDMuc2NhbGUgPSB7fTtcbiAgZnVuY3Rpb24gZDNfc2NhbGVFeHRlbnQoZG9tYWluKSB7XG4gICAgdmFyIHN0YXJ0ID0gZG9tYWluWzBdLCBzdG9wID0gZG9tYWluW2RvbWFpbi5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gc3RhcnQgPCBzdG9wID8gWyBzdGFydCwgc3RvcCBdIDogWyBzdG9wLCBzdGFydCBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlUmFuZ2Uoc2NhbGUpIHtcbiAgICByZXR1cm4gc2NhbGUucmFuZ2VFeHRlbnQgPyBzY2FsZS5yYW5nZUV4dGVudCgpIDogZDNfc2NhbGVFeHRlbnQoc2NhbGUucmFuZ2UoKSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfYmlsaW5lYXIoZG9tYWluLCByYW5nZSwgdW5pbnRlcnBvbGF0ZSwgaW50ZXJwb2xhdGUpIHtcbiAgICB2YXIgdSA9IHVuaW50ZXJwb2xhdGUoZG9tYWluWzBdLCBkb21haW5bMV0pLCBpID0gaW50ZXJwb2xhdGUocmFuZ2VbMF0sIHJhbmdlWzFdKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIGkodSh4KSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9uaWNlKGRvbWFpbiwgbmljZSkge1xuICAgIHZhciBpMCA9IDAsIGkxID0gZG9tYWluLmxlbmd0aCAtIDEsIHgwID0gZG9tYWluW2kwXSwgeDEgPSBkb21haW5baTFdLCBkeDtcbiAgICBpZiAoeDEgPCB4MCkge1xuICAgICAgZHggPSBpMCwgaTAgPSBpMSwgaTEgPSBkeDtcbiAgICAgIGR4ID0geDAsIHgwID0geDEsIHgxID0gZHg7XG4gICAgfVxuICAgIGRvbWFpbltpMF0gPSBuaWNlLmZsb29yKHgwKTtcbiAgICBkb21haW5baTFdID0gbmljZS5jZWlsKHgxKTtcbiAgICByZXR1cm4gZG9tYWluO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX25pY2VTdGVwKHN0ZXApIHtcbiAgICByZXR1cm4gc3RlcCA/IHtcbiAgICAgIGZsb29yOiBmdW5jdGlvbih4KSB7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKHggLyBzdGVwKSAqIHN0ZXA7XG4gICAgICB9LFxuICAgICAgY2VpbDogZnVuY3Rpb24oeCkge1xuICAgICAgICByZXR1cm4gTWF0aC5jZWlsKHggLyBzdGVwKSAqIHN0ZXA7XG4gICAgICB9XG4gICAgfSA6IGQzX3NjYWxlX25pY2VJZGVudGl0eTtcbiAgfVxuICB2YXIgZDNfc2NhbGVfbmljZUlkZW50aXR5ID0ge1xuICAgIGZsb29yOiBkM19pZGVudGl0eSxcbiAgICBjZWlsOiBkM19pZGVudGl0eVxuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9wb2x5bGluZWFyKGRvbWFpbiwgcmFuZ2UsIHVuaW50ZXJwb2xhdGUsIGludGVycG9sYXRlKSB7XG4gICAgdmFyIHUgPSBbXSwgaSA9IFtdLCBqID0gMCwgayA9IE1hdGgubWluKGRvbWFpbi5sZW5ndGgsIHJhbmdlLmxlbmd0aCkgLSAxO1xuICAgIGlmIChkb21haW5ba10gPCBkb21haW5bMF0pIHtcbiAgICAgIGRvbWFpbiA9IGRvbWFpbi5zbGljZSgpLnJldmVyc2UoKTtcbiAgICAgIHJhbmdlID0gcmFuZ2Uuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICAgIHdoaWxlICgrK2ogPD0gaykge1xuICAgICAgdS5wdXNoKHVuaW50ZXJwb2xhdGUoZG9tYWluW2ogLSAxXSwgZG9tYWluW2pdKSk7XG4gICAgICBpLnB1c2goaW50ZXJwb2xhdGUocmFuZ2VbaiAtIDFdLCByYW5nZVtqXSkpO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgdmFyIGogPSBkMy5iaXNlY3QoZG9tYWluLCB4LCAxLCBrKSAtIDE7XG4gICAgICByZXR1cm4gaVtqXSh1W2pdKHgpKTtcbiAgICB9O1xuICB9XG4gIGQzLnNjYWxlLmxpbmVhciA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9saW5lYXIoWyAwLCAxIF0sIFsgMCwgMSBdLCBkM19pbnRlcnBvbGF0ZSwgZmFsc2UpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXIoZG9tYWluLCByYW5nZSwgaW50ZXJwb2xhdGUsIGNsYW1wKSB7XG4gICAgdmFyIG91dHB1dCwgaW5wdXQ7XG4gICAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICAgIHZhciBsaW5lYXIgPSBNYXRoLm1pbihkb21haW4ubGVuZ3RoLCByYW5nZS5sZW5ndGgpID4gMiA/IGQzX3NjYWxlX3BvbHlsaW5lYXIgOiBkM19zY2FsZV9iaWxpbmVhciwgdW5pbnRlcnBvbGF0ZSA9IGNsYW1wID8gZDNfdW5pbnRlcnBvbGF0ZUNsYW1wIDogZDNfdW5pbnRlcnBvbGF0ZU51bWJlcjtcbiAgICAgIG91dHB1dCA9IGxpbmVhcihkb21haW4sIHJhbmdlLCB1bmludGVycG9sYXRlLCBpbnRlcnBvbGF0ZSk7XG4gICAgICBpbnB1dCA9IGxpbmVhcihyYW5nZSwgZG9tYWluLCB1bmludGVycG9sYXRlLCBkM19pbnRlcnBvbGF0ZSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlKHgpIHtcbiAgICAgIHJldHVybiBvdXRwdXQoeCk7XG4gICAgfVxuICAgIHNjYWxlLmludmVydCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHJldHVybiBpbnB1dCh5KTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGRvbWFpbiA9IHgubWFwKE51bWJlcik7XG4gICAgICByZXR1cm4gcmVzY2FsZSgpO1xuICAgIH07XG4gICAgc2NhbGUucmFuZ2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiByYW5nZTtcbiAgICAgIHJhbmdlID0geDtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5yYW5nZVJvdW5kID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHNjYWxlLnJhbmdlKHgpLmludGVycG9sYXRlKGQzX2ludGVycG9sYXRlUm91bmQpO1xuICAgIH07XG4gICAgc2NhbGUuY2xhbXAgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjbGFtcDtcbiAgICAgIGNsYW1wID0geDtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5pbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGludGVycG9sYXRlO1xuICAgICAgaW50ZXJwb2xhdGUgPSB4O1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLnRpY2tzID0gZnVuY3Rpb24obSkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tzKGRvbWFpbiwgbSk7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrRm9ybWF0ID0gZnVuY3Rpb24obSwgZm9ybWF0KSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfbGluZWFyVGlja0Zvcm1hdChkb21haW4sIG0sIGZvcm1hdCk7XG4gICAgfTtcbiAgICBzY2FsZS5uaWNlID0gZnVuY3Rpb24obSkge1xuICAgICAgZDNfc2NhbGVfbGluZWFyTmljZShkb21haW4sIG0pO1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXIoZG9tYWluLCByYW5nZSwgaW50ZXJwb2xhdGUsIGNsYW1wKTtcbiAgICB9O1xuICAgIHJldHVybiByZXNjYWxlKCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfbGluZWFyUmViaW5kKHNjYWxlLCBsaW5lYXIpIHtcbiAgICByZXR1cm4gZDMucmViaW5kKHNjYWxlLCBsaW5lYXIsIFwicmFuZ2VcIiwgXCJyYW5nZVJvdW5kXCIsIFwiaW50ZXJwb2xhdGVcIiwgXCJjbGFtcFwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJOaWNlKGRvbWFpbiwgbSkge1xuICAgIGQzX3NjYWxlX25pY2UoZG9tYWluLCBkM19zY2FsZV9uaWNlU3RlcChkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKVsyXSkpO1xuICAgIGQzX3NjYWxlX25pY2UoZG9tYWluLCBkM19zY2FsZV9uaWNlU3RlcChkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKVsyXSkpO1xuICAgIHJldHVybiBkb21haW47XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfbGluZWFyVGlja1JhbmdlKGRvbWFpbiwgbSkge1xuICAgIGlmIChtID09IG51bGwpIG0gPSAxMDtcbiAgICB2YXIgZXh0ZW50ID0gZDNfc2NhbGVFeHRlbnQoZG9tYWluKSwgc3BhbiA9IGV4dGVudFsxXSAtIGV4dGVudFswXSwgc3RlcCA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubG9nKHNwYW4gLyBtKSAvIE1hdGguTE4xMCkpLCBlcnIgPSBtIC8gc3BhbiAqIHN0ZXA7XG4gICAgaWYgKGVyciA8PSAuMTUpIHN0ZXAgKj0gMTA7IGVsc2UgaWYgKGVyciA8PSAuMzUpIHN0ZXAgKj0gNTsgZWxzZSBpZiAoZXJyIDw9IC43NSkgc3RlcCAqPSAyO1xuICAgIGV4dGVudFswXSA9IE1hdGguY2VpbChleHRlbnRbMF0gLyBzdGVwKSAqIHN0ZXA7XG4gICAgZXh0ZW50WzFdID0gTWF0aC5mbG9vcihleHRlbnRbMV0gLyBzdGVwKSAqIHN0ZXAgKyBzdGVwICogLjU7XG4gICAgZXh0ZW50WzJdID0gc3RlcDtcbiAgICByZXR1cm4gZXh0ZW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2xpbmVhclRpY2tzKGRvbWFpbiwgbSkge1xuICAgIHJldHVybiBkMy5yYW5nZS5hcHBseShkMywgZDNfc2NhbGVfbGluZWFyVGlja1JhbmdlKGRvbWFpbiwgbSkpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpIHtcbiAgICB2YXIgcmFuZ2UgPSBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKTtcbiAgICBpZiAoZm9ybWF0KSB7XG4gICAgICB2YXIgbWF0Y2ggPSBkM19mb3JtYXRfcmUuZXhlYyhmb3JtYXQpO1xuICAgICAgbWF0Y2guc2hpZnQoKTtcbiAgICAgIGlmIChtYXRjaFs4XSA9PT0gXCJzXCIpIHtcbiAgICAgICAgdmFyIHByZWZpeCA9IGQzLmZvcm1hdFByZWZpeChNYXRoLm1heChhYnMocmFuZ2VbMF0pLCBhYnMocmFuZ2VbMV0pKSk7XG4gICAgICAgIGlmICghbWF0Y2hbN10pIG1hdGNoWzddID0gXCIuXCIgKyBkM19zY2FsZV9saW5lYXJQcmVjaXNpb24ocHJlZml4LnNjYWxlKHJhbmdlWzJdKSk7XG4gICAgICAgIG1hdGNoWzhdID0gXCJmXCI7XG4gICAgICAgIGZvcm1hdCA9IGQzLmZvcm1hdChtYXRjaC5qb2luKFwiXCIpKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICByZXR1cm4gZm9ybWF0KHByZWZpeC5zY2FsZShkKSkgKyBwcmVmaXguc3ltYm9sO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKCFtYXRjaFs3XSkgbWF0Y2hbN10gPSBcIi5cIiArIGQzX3NjYWxlX2xpbmVhckZvcm1hdFByZWNpc2lvbihtYXRjaFs4XSwgcmFuZ2UpO1xuICAgICAgZm9ybWF0ID0gbWF0Y2guam9pbihcIlwiKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9ybWF0ID0gXCIsLlwiICsgZDNfc2NhbGVfbGluZWFyUHJlY2lzaW9uKHJhbmdlWzJdKSArIFwiZlwiO1xuICAgIH1cbiAgICByZXR1cm4gZDMuZm9ybWF0KGZvcm1hdCk7XG4gIH1cbiAgdmFyIGQzX3NjYWxlX2xpbmVhckZvcm1hdFNpZ25pZmljYW50ID0ge1xuICAgIHM6IDEsXG4gICAgZzogMSxcbiAgICBwOiAxLFxuICAgIHI6IDEsXG4gICAgZTogMVxuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJQcmVjaXNpb24odmFsdWUpIHtcbiAgICByZXR1cm4gLU1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjEwICsgLjAxKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJGb3JtYXRQcmVjaXNpb24odHlwZSwgcmFuZ2UpIHtcbiAgICB2YXIgcCA9IGQzX3NjYWxlX2xpbmVhclByZWNpc2lvbihyYW5nZVsyXSk7XG4gICAgcmV0dXJuIHR5cGUgaW4gZDNfc2NhbGVfbGluZWFyRm9ybWF0U2lnbmlmaWNhbnQgPyBNYXRoLmFicyhwIC0gZDNfc2NhbGVfbGluZWFyUHJlY2lzaW9uKE1hdGgubWF4KGFicyhyYW5nZVswXSksIGFicyhyYW5nZVsxXSkpKSkgKyArKHR5cGUgIT09IFwiZVwiKSA6IHAgLSAodHlwZSA9PT0gXCIlXCIpICogMjtcbiAgfVxuICBkMy5zY2FsZS5sb2cgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfbG9nKGQzLnNjYWxlLmxpbmVhcigpLmRvbWFpbihbIDAsIDEgXSksIDEwLCB0cnVlLCBbIDEsIDEwIF0pO1xuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9sb2cobGluZWFyLCBiYXNlLCBwb3NpdGl2ZSwgZG9tYWluKSB7XG4gICAgZnVuY3Rpb24gbG9nKHgpIHtcbiAgICAgIHJldHVybiAocG9zaXRpdmUgPyBNYXRoLmxvZyh4IDwgMCA/IDAgOiB4KSA6IC1NYXRoLmxvZyh4ID4gMCA/IDAgOiAteCkpIC8gTWF0aC5sb2coYmFzZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBvdyh4KSB7XG4gICAgICByZXR1cm4gcG9zaXRpdmUgPyBNYXRoLnBvdyhiYXNlLCB4KSA6IC1NYXRoLnBvdyhiYXNlLCAteCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlKHgpIHtcbiAgICAgIHJldHVybiBsaW5lYXIobG9nKHgpKTtcbiAgICB9XG4gICAgc2NhbGUuaW52ZXJ0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHBvdyhsaW5lYXIuaW52ZXJ0KHgpKTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIHBvc2l0aXZlID0geFswXSA+PSAwO1xuICAgICAgbGluZWFyLmRvbWFpbigoZG9tYWluID0geC5tYXAoTnVtYmVyKSkubWFwKGxvZykpO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUuYmFzZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGJhc2U7XG4gICAgICBiYXNlID0gK187XG4gICAgICBsaW5lYXIuZG9tYWluKGRvbWFpbi5tYXAobG9nKSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS5uaWNlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbmljZWQgPSBkM19zY2FsZV9uaWNlKGRvbWFpbi5tYXAobG9nKSwgcG9zaXRpdmUgPyBNYXRoIDogZDNfc2NhbGVfbG9nTmljZU5lZ2F0aXZlKTtcbiAgICAgIGxpbmVhci5kb21haW4obmljZWQpO1xuICAgICAgZG9tYWluID0gbmljZWQubWFwKHBvdyk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGV4dGVudCA9IGQzX3NjYWxlRXh0ZW50KGRvbWFpbiksIHRpY2tzID0gW10sIHUgPSBleHRlbnRbMF0sIHYgPSBleHRlbnRbMV0sIGkgPSBNYXRoLmZsb29yKGxvZyh1KSksIGogPSBNYXRoLmNlaWwobG9nKHYpKSwgbiA9IGJhc2UgJSAxID8gMiA6IGJhc2U7XG4gICAgICBpZiAoaXNGaW5pdGUoaiAtIGkpKSB7XG4gICAgICAgIGlmIChwb3NpdGl2ZSkge1xuICAgICAgICAgIGZvciAoO2kgPCBqOyBpKyspIGZvciAodmFyIGsgPSAxOyBrIDwgbjsgaysrKSB0aWNrcy5wdXNoKHBvdyhpKSAqIGspO1xuICAgICAgICAgIHRpY2tzLnB1c2gocG93KGkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aWNrcy5wdXNoKHBvdyhpKSk7XG4gICAgICAgICAgZm9yICg7aSsrIDwgajsgKSBmb3IgKHZhciBrID0gbiAtIDE7IGsgPiAwOyBrLS0pIHRpY2tzLnB1c2gocG93KGkpICogayk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgdGlja3NbaV0gPCB1OyBpKyspIHt9XG4gICAgICAgIGZvciAoaiA9IHRpY2tzLmxlbmd0aDsgdGlja3NbaiAtIDFdID4gdjsgai0tKSB7fVxuICAgICAgICB0aWNrcyA9IHRpY2tzLnNsaWNlKGksIGopO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRpY2tzO1xuICAgIH07XG4gICAgc2NhbGUudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG4sIGZvcm1hdCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZDNfc2NhbGVfbG9nRm9ybWF0O1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBmb3JtYXQgPSBkM19zY2FsZV9sb2dGb3JtYXQ7IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgIT09IFwiZnVuY3Rpb25cIikgZm9ybWF0ID0gZDMuZm9ybWF0KGZvcm1hdCk7XG4gICAgICB2YXIgayA9IE1hdGgubWF4KDEsIGJhc2UgKiBuIC8gc2NhbGUudGlja3MoKS5sZW5ndGgpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGkgPSBkIC8gcG93KE1hdGgucm91bmQobG9nKGQpKSk7XG4gICAgICAgIGlmIChpICogYmFzZSA8IGJhc2UgLSAuNSkgaSAqPSBiYXNlO1xuICAgICAgICByZXR1cm4gaSA8PSBrID8gZm9ybWF0KGQpIDogXCJcIjtcbiAgICAgIH07XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfbG9nKGxpbmVhci5jb3B5KCksIGJhc2UsIHBvc2l0aXZlLCBkb21haW4pO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclJlYmluZChzY2FsZSwgbGluZWFyKTtcbiAgfVxuICB2YXIgZDNfc2NhbGVfbG9nRm9ybWF0ID0gZDMuZm9ybWF0KFwiLjBlXCIpLCBkM19zY2FsZV9sb2dOaWNlTmVnYXRpdmUgPSB7XG4gICAgZmxvb3I6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAtTWF0aC5jZWlsKC14KTtcbiAgICB9LFxuICAgIGNlaWw6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAtTWF0aC5mbG9vcigteCk7XG4gICAgfVxuICB9O1xuICBkMy5zY2FsZS5wb3cgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfcG93KGQzLnNjYWxlLmxpbmVhcigpLCAxLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3BvdyhsaW5lYXIsIGV4cG9uZW50LCBkb21haW4pIHtcbiAgICB2YXIgcG93cCA9IGQzX3NjYWxlX3Bvd1BvdyhleHBvbmVudCksIHBvd2IgPSBkM19zY2FsZV9wb3dQb3coMSAvIGV4cG9uZW50KTtcbiAgICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgICByZXR1cm4gbGluZWFyKHBvd3AoeCkpO1xuICAgIH1cbiAgICBzY2FsZS5pbnZlcnQgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gcG93YihsaW5lYXIuaW52ZXJ0KHgpKTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGxpbmVhci5kb21haW4oKGRvbWFpbiA9IHgubWFwKE51bWJlcikpLm1hcChwb3dwKSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrcyA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJUaWNrcyhkb21haW4sIG0pO1xuICAgIH07XG4gICAgc2NhbGUudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG0sIGZvcm1hdCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpO1xuICAgIH07XG4gICAgc2NhbGUubmljZSA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBzY2FsZS5kb21haW4oZDNfc2NhbGVfbGluZWFyTmljZShkb21haW4sIG0pKTtcbiAgICB9O1xuICAgIHNjYWxlLmV4cG9uZW50ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZXhwb25lbnQ7XG4gICAgICBwb3dwID0gZDNfc2NhbGVfcG93UG93KGV4cG9uZW50ID0geCk7XG4gICAgICBwb3diID0gZDNfc2NhbGVfcG93UG93KDEgLyBleHBvbmVudCk7XG4gICAgICBsaW5lYXIuZG9tYWluKGRvbWFpbi5tYXAocG93cCkpO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3BvdyhsaW5lYXIuY29weSgpLCBleHBvbmVudCwgZG9tYWluKTtcbiAgICB9O1xuICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJSZWJpbmQoc2NhbGUsIGxpbmVhcik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfcG93UG93KGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHggPCAwID8gLU1hdGgucG93KC14LCBlKSA6IE1hdGgucG93KHgsIGUpO1xuICAgIH07XG4gIH1cbiAgZDMuc2NhbGUuc3FydCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkMy5zY2FsZS5wb3coKS5leHBvbmVudCguNSk7XG4gIH07XG4gIGQzLnNjYWxlLm9yZGluYWwgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfb3JkaW5hbChbXSwge1xuICAgICAgdDogXCJyYW5nZVwiLFxuICAgICAgYTogWyBbXSBdXG4gICAgfSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX29yZGluYWwoZG9tYWluLCByYW5nZXIpIHtcbiAgICB2YXIgaW5kZXgsIHJhbmdlLCByYW5nZUJhbmQ7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgcmV0dXJuIHJhbmdlWygoaW5kZXguZ2V0KHgpIHx8IChyYW5nZXIudCA9PT0gXCJyYW5nZVwiID8gaW5kZXguc2V0KHgsIGRvbWFpbi5wdXNoKHgpKSA6IE5hTikpIC0gMSkgJSByYW5nZS5sZW5ndGhdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdGVwcyhzdGFydCwgc3RlcCkge1xuICAgICAgcmV0dXJuIGQzLnJhbmdlKGRvbWFpbi5sZW5ndGgpLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICAgIHJldHVybiBzdGFydCArIHN0ZXAgKiBpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGRvbWFpbiA9IFtdO1xuICAgICAgaW5kZXggPSBuZXcgZDNfTWFwKCk7XG4gICAgICB2YXIgaSA9IC0xLCBuID0geC5sZW5ndGgsIHhpO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICghaW5kZXguaGFzKHhpID0geFtpXSkpIGluZGV4LnNldCh4aSwgZG9tYWluLnB1c2goeGkpKTtcbiAgICAgIHJldHVybiBzY2FsZVtyYW5nZXIudF0uYXBwbHkoc2NhbGUsIHJhbmdlci5hKTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IHg7XG4gICAgICByYW5nZUJhbmQgPSAwO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlUG9pbnRzID0gZnVuY3Rpb24oeCwgcGFkZGluZykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBwYWRkaW5nID0gMDtcbiAgICAgIHZhciBzdGFydCA9IHhbMF0sIHN0b3AgPSB4WzFdLCBzdGVwID0gZG9tYWluLmxlbmd0aCA8IDIgPyAoc3RhcnQgPSAoc3RhcnQgKyBzdG9wKSAvIDIsIFxuICAgICAgMCkgOiAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gMSArIHBhZGRpbmcpO1xuICAgICAgcmFuZ2UgPSBzdGVwcyhzdGFydCArIHN0ZXAgKiBwYWRkaW5nIC8gMiwgc3RlcCk7XG4gICAgICByYW5nZUJhbmQgPSAwO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlUG9pbnRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlUm91bmRQb2ludHMgPSBmdW5jdGlvbih4LCBwYWRkaW5nKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHBhZGRpbmcgPSAwO1xuICAgICAgdmFyIHN0YXJ0ID0geFswXSwgc3RvcCA9IHhbMV0sIHN0ZXAgPSBkb21haW4ubGVuZ3RoIDwgMiA/IChzdGFydCA9IHN0b3AgPSBNYXRoLnJvdW5kKChzdGFydCArIHN0b3ApIC8gMiksIFxuICAgICAgMCkgOiAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gMSArIHBhZGRpbmcpIHwgMDtcbiAgICAgIHJhbmdlID0gc3RlcHMoc3RhcnQgKyBNYXRoLnJvdW5kKHN0ZXAgKiBwYWRkaW5nIC8gMiArIChzdG9wIC0gc3RhcnQgLSAoZG9tYWluLmxlbmd0aCAtIDEgKyBwYWRkaW5nKSAqIHN0ZXApIC8gMiksIHN0ZXApO1xuICAgICAgcmFuZ2VCYW5kID0gMDtcbiAgICAgIHJhbmdlciA9IHtcbiAgICAgICAgdDogXCJyYW5nZVJvdW5kUG9pbnRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlQmFuZHMgPSBmdW5jdGlvbih4LCBwYWRkaW5nLCBvdXRlclBhZGRpbmcpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcGFkZGluZyA9IDA7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIG91dGVyUGFkZGluZyA9IHBhZGRpbmc7XG4gICAgICB2YXIgcmV2ZXJzZSA9IHhbMV0gPCB4WzBdLCBzdGFydCA9IHhbcmV2ZXJzZSAtIDBdLCBzdG9wID0geFsxIC0gcmV2ZXJzZV0sIHN0ZXAgPSAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gcGFkZGluZyArIDIgKiBvdXRlclBhZGRpbmcpO1xuICAgICAgcmFuZ2UgPSBzdGVwcyhzdGFydCArIHN0ZXAgKiBvdXRlclBhZGRpbmcsIHN0ZXApO1xuICAgICAgaWYgKHJldmVyc2UpIHJhbmdlLnJldmVyc2UoKTtcbiAgICAgIHJhbmdlQmFuZCA9IHN0ZXAgKiAoMSAtIHBhZGRpbmcpO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlQmFuZHNcIixcbiAgICAgICAgYTogYXJndW1lbnRzXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUucmFuZ2VSb3VuZEJhbmRzID0gZnVuY3Rpb24oeCwgcGFkZGluZywgb3V0ZXJQYWRkaW5nKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHBhZGRpbmcgPSAwO1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBvdXRlclBhZGRpbmcgPSBwYWRkaW5nO1xuICAgICAgdmFyIHJldmVyc2UgPSB4WzFdIDwgeFswXSwgc3RhcnQgPSB4W3JldmVyc2UgLSAwXSwgc3RvcCA9IHhbMSAtIHJldmVyc2VdLCBzdGVwID0gTWF0aC5mbG9vcigoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gcGFkZGluZyArIDIgKiBvdXRlclBhZGRpbmcpKTtcbiAgICAgIHJhbmdlID0gc3RlcHMoc3RhcnQgKyBNYXRoLnJvdW5kKChzdG9wIC0gc3RhcnQgLSAoZG9tYWluLmxlbmd0aCAtIHBhZGRpbmcpICogc3RlcCkgLyAyKSwgc3RlcCk7XG4gICAgICBpZiAocmV2ZXJzZSkgcmFuZ2UucmV2ZXJzZSgpO1xuICAgICAgcmFuZ2VCYW5kID0gTWF0aC5yb3VuZChzdGVwICogKDEgLSBwYWRkaW5nKSk7XG4gICAgICByYW5nZXIgPSB7XG4gICAgICAgIHQ6IFwicmFuZ2VSb3VuZEJhbmRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlQmFuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJhbmdlQmFuZDtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlRXh0ZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVFeHRlbnQocmFuZ2VyLmFbMF0pO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX29yZGluYWwoZG9tYWluLCByYW5nZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIHNjYWxlLmRvbWFpbihkb21haW4pO1xuICB9XG4gIGQzLnNjYWxlLmNhdGVnb3J5MTAgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MTApO1xuICB9O1xuICBkMy5zY2FsZS5jYXRlZ29yeTIwID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzLnNjYWxlLm9yZGluYWwoKS5yYW5nZShkM19jYXRlZ29yeTIwKTtcbiAgfTtcbiAgZDMuc2NhbGUuY2F0ZWdvcnkyMGIgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MjBiKTtcbiAgfTtcbiAgZDMuc2NhbGUuY2F0ZWdvcnkyMGMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MjBjKTtcbiAgfTtcbiAgdmFyIGQzX2NhdGVnb3J5MTAgPSBbIDIwNjIyNjAsIDE2NzQ0MjA2LCAyOTI0NTg4LCAxNDAzNDcyOCwgOTcyNTg4NSwgOTE5NzEzMSwgMTQ5MDczMzAsIDgzNTU3MTEsIDEyMzY5MTg2LCAxNTU2MTc1IF0ubWFwKGQzX3JnYlN0cmluZyk7XG4gIHZhciBkM19jYXRlZ29yeTIwID0gWyAyMDYyMjYwLCAxMTQ1NDQ0MCwgMTY3NDQyMDYsIDE2NzU5NjcyLCAyOTI0NTg4LCAxMDAxODY5OCwgMTQwMzQ3MjgsIDE2NzUwNzQyLCA5NzI1ODg1LCAxMjk1NTg2MSwgOTE5NzEzMSwgMTI4ODUxNDAsIDE0OTA3MzMwLCAxNjIzNDE5NCwgODM1NTcxMSwgMTMwOTI4MDcsIDEyMzY5MTg2LCAxNDQwODU4OSwgMTU1NjE3NSwgMTA0MTA3MjUgXS5tYXAoZDNfcmdiU3RyaW5nKTtcbiAgdmFyIGQzX2NhdGVnb3J5MjBiID0gWyAzNzUwNzc3LCA1Mzk1NjE5LCA3MDQwNzE5LCAxMDI2NDI4NiwgNjUxOTA5NywgOTIxNjU5NCwgMTE5MTUxMTUsIDEzNTU2NjM2LCA5MjAyOTkzLCAxMjQyNjgwOSwgMTUxODY1MTQsIDE1MTkwOTMyLCA4NjY2MTY5LCAxMTM1NjQ5MCwgMTQwNDk2NDMsIDE1MTc3MzcyLCA4MDc3NjgzLCAxMDgzNDMyNCwgMTM1Mjg1MDksIDE0NTg5NjU0IF0ubWFwKGQzX3JnYlN0cmluZyk7XG4gIHZhciBkM19jYXRlZ29yeTIwYyA9IFsgMzI0NDczMywgNzA1NzExMCwgMTA0MDY2MjUsIDEzMDMyNDMxLCAxNTA5NTA1MywgMTY2MTY3NjQsIDE2NjI1MjU5LCAxNjYzNDAxOCwgMzI1MzA3NiwgNzY1MjQ3MCwgMTA2MDcwMDMsIDEzMTAxNTA0LCA3Njk1MjgxLCAxMDM5NDMxMiwgMTIzNjkzNzIsIDE0MzQyODkxLCA2NTEzNTA3LCA5ODY4OTUwLCAxMjQzNDg3NywgMTQyNzcwODEgXS5tYXAoZDNfcmdiU3RyaW5nKTtcbiAgZDMuc2NhbGUucXVhbnRpbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfcXVhbnRpbGUoW10sIFtdKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2NhbGVfcXVhbnRpbGUoZG9tYWluLCByYW5nZSkge1xuICAgIHZhciB0aHJlc2hvbGRzO1xuICAgIGZ1bmN0aW9uIHJlc2NhbGUoKSB7XG4gICAgICB2YXIgayA9IDAsIHEgPSByYW5nZS5sZW5ndGg7XG4gICAgICB0aHJlc2hvbGRzID0gW107XG4gICAgICB3aGlsZSAoKytrIDwgcSkgdGhyZXNob2xkc1trIC0gMV0gPSBkMy5xdWFudGlsZShkb21haW4sIGsgLyBxKTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgaWYgKCFpc05hTih4ID0gK3gpKSByZXR1cm4gcmFuZ2VbZDMuYmlzZWN0KHRocmVzaG9sZHMsIHgpXTtcbiAgICB9XG4gICAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZG9tYWluO1xuICAgICAgZG9tYWluID0geC5tYXAoZDNfbnVtYmVyKS5maWx0ZXIoZDNfbnVtZXJpYykuc29ydChkM19hc2NlbmRpbmcpO1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IHg7XG4gICAgICByZXR1cm4gcmVzY2FsZSgpO1xuICAgIH07XG4gICAgc2NhbGUucXVhbnRpbGVzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhyZXNob2xkcztcbiAgICB9O1xuICAgIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHkgPSByYW5nZS5pbmRleE9mKHkpO1xuICAgICAgcmV0dXJuIHkgPCAwID8gWyBOYU4sIE5hTiBdIDogWyB5ID4gMCA/IHRocmVzaG9sZHNbeSAtIDFdIDogZG9tYWluWzBdLCB5IDwgdGhyZXNob2xkcy5sZW5ndGggPyB0aHJlc2hvbGRzW3ldIDogZG9tYWluW2RvbWFpbi5sZW5ndGggLSAxXSBdO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3F1YW50aWxlKGRvbWFpbiwgcmFuZ2UpO1xuICAgIH07XG4gICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgfVxuICBkMy5zY2FsZS5xdWFudGl6ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9xdWFudGl6ZSgwLCAxLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3F1YW50aXplKHgwLCB4MSwgcmFuZ2UpIHtcbiAgICB2YXIga3gsIGk7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgcmV0dXJuIHJhbmdlW01hdGgubWF4KDAsIE1hdGgubWluKGksIE1hdGguZmxvb3Ioa3ggKiAoeCAtIHgwKSkpKV07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2NhbGUoKSB7XG4gICAgICBreCA9IHJhbmdlLmxlbmd0aCAvICh4MSAtIHgwKTtcbiAgICAgIGkgPSByYW5nZS5sZW5ndGggLSAxO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH1cbiAgICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHgwLCB4MSBdO1xuICAgICAgeDAgPSAreFswXTtcbiAgICAgIHgxID0gK3hbeC5sZW5ndGggLSAxXTtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5yYW5nZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJhbmdlO1xuICAgICAgcmFuZ2UgPSB4O1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHkgPSByYW5nZS5pbmRleE9mKHkpO1xuICAgICAgeSA9IHkgPCAwID8gTmFOIDogeSAvIGt4ICsgeDA7XG4gICAgICByZXR1cm4gWyB5LCB5ICsgMSAvIGt4IF07XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfcXVhbnRpemUoeDAsIHgxLCByYW5nZSk7XG4gICAgfTtcbiAgICByZXR1cm4gcmVzY2FsZSgpO1xuICB9XG4gIGQzLnNjYWxlLnRocmVzaG9sZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV90aHJlc2hvbGQoWyAuNSBdLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3RocmVzaG9sZChkb21haW4sIHJhbmdlKSB7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgaWYgKHggPD0geCkgcmV0dXJuIHJhbmdlW2QzLmJpc2VjdChkb21haW4sIHgpXTtcbiAgICB9XG4gICAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZG9tYWluO1xuICAgICAgZG9tYWluID0gXztcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IF87XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS5pbnZlcnRFeHRlbnQgPSBmdW5jdGlvbih5KSB7XG4gICAgICB5ID0gcmFuZ2UuaW5kZXhPZih5KTtcbiAgICAgIHJldHVybiBbIGRvbWFpblt5IC0gMV0sIGRvbWFpblt5XSBdO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3RocmVzaG9sZChkb21haW4sIHJhbmdlKTtcbiAgICB9O1xuICAgIHJldHVybiBzY2FsZTtcbiAgfVxuICBkMy5zY2FsZS5pZGVudGl0eSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9pZGVudGl0eShbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2lkZW50aXR5KGRvbWFpbikge1xuICAgIGZ1bmN0aW9uIGlkZW50aXR5KHgpIHtcbiAgICAgIHJldHVybiAreDtcbiAgICB9XG4gICAgaWRlbnRpdHkuaW52ZXJ0ID0gaWRlbnRpdHk7XG4gICAgaWRlbnRpdHkuZG9tYWluID0gaWRlbnRpdHkucmFuZ2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkb21haW47XG4gICAgICBkb21haW4gPSB4Lm1hcChpZGVudGl0eSk7XG4gICAgICByZXR1cm4gaWRlbnRpdHk7XG4gICAgfTtcbiAgICBpZGVudGl0eS50aWNrcyA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJUaWNrcyhkb21haW4sIG0pO1xuICAgIH07XG4gICAgaWRlbnRpdHkudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG0sIGZvcm1hdCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpO1xuICAgIH07XG4gICAgaWRlbnRpdHkuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2lkZW50aXR5KGRvbWFpbik7XG4gICAgfTtcbiAgICByZXR1cm4gaWRlbnRpdHk7XG4gIH1cbiAgZDMuc3ZnID0ge307XG4gIGZ1bmN0aW9uIGQzX3plcm8oKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgZDMuc3ZnLmFyYyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpbm5lclJhZGl1cyA9IGQzX3N2Z19hcmNJbm5lclJhZGl1cywgb3V0ZXJSYWRpdXMgPSBkM19zdmdfYXJjT3V0ZXJSYWRpdXMsIGNvcm5lclJhZGl1cyA9IGQzX3plcm8sIHBhZFJhZGl1cyA9IGQzX3N2Z19hcmNBdXRvLCBzdGFydEFuZ2xlID0gZDNfc3ZnX2FyY1N0YXJ0QW5nbGUsIGVuZEFuZ2xlID0gZDNfc3ZnX2FyY0VuZEFuZ2xlLCBwYWRBbmdsZSA9IGQzX3N2Z19hcmNQYWRBbmdsZTtcbiAgICBmdW5jdGlvbiBhcmMoKSB7XG4gICAgICB2YXIgcjAgPSBNYXRoLm1heCgwLCAraW5uZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSksIHIxID0gTWF0aC5tYXgoMCwgK291dGVyUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpLCBhMCA9IHN0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSAtIGhhbGbPgCwgYTEgPSBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC0gaGFsZs+ALCBkYSA9IE1hdGguYWJzKGExIC0gYTApLCBjdyA9IGEwID4gYTEgPyAwIDogMTtcbiAgICAgIGlmIChyMSA8IHIwKSByYyA9IHIxLCByMSA9IHIwLCByMCA9IHJjO1xuICAgICAgaWYgKGRhID49IM+EzrUpIHJldHVybiBjaXJjbGVTZWdtZW50KHIxLCBjdykgKyAocjAgPyBjaXJjbGVTZWdtZW50KHIwLCAxIC0gY3cpIDogXCJcIikgKyBcIlpcIjtcbiAgICAgIHZhciByYywgY3IsIHJwLCBhcCwgcDAgPSAwLCBwMSA9IDAsIHgwLCB5MCwgeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgcGF0aCA9IFtdO1xuICAgICAgaWYgKGFwID0gKCtwYWRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IDApIC8gMikge1xuICAgICAgICBycCA9IHBhZFJhZGl1cyA9PT0gZDNfc3ZnX2FyY0F1dG8gPyBNYXRoLnNxcnQocjAgKiByMCArIHIxICogcjEpIDogK3BhZFJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICBpZiAoIWN3KSBwMSAqPSAtMTtcbiAgICAgICAgaWYgKHIxKSBwMSA9IGQzX2FzaW4ocnAgLyByMSAqIE1hdGguc2luKGFwKSk7XG4gICAgICAgIGlmIChyMCkgcDAgPSBkM19hc2luKHJwIC8gcjAgKiBNYXRoLnNpbihhcCkpO1xuICAgICAgfVxuICAgICAgaWYgKHIxKSB7XG4gICAgICAgIHgwID0gcjEgKiBNYXRoLmNvcyhhMCArIHAxKTtcbiAgICAgICAgeTAgPSByMSAqIE1hdGguc2luKGEwICsgcDEpO1xuICAgICAgICB4MSA9IHIxICogTWF0aC5jb3MoYTEgLSBwMSk7XG4gICAgICAgIHkxID0gcjEgKiBNYXRoLnNpbihhMSAtIHAxKTtcbiAgICAgICAgdmFyIGwxID0gTWF0aC5hYnMoYTEgLSBhMCAtIDIgKiBwMSkgPD0gz4AgPyAwIDogMTtcbiAgICAgICAgaWYgKHAxICYmIGQzX3N2Z19hcmNTd2VlcCh4MCwgeTAsIHgxLCB5MSkgPT09IGN3IF4gbDEpIHtcbiAgICAgICAgICB2YXIgaDEgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgICAgIHgwID0gcjEgKiBNYXRoLmNvcyhoMSk7XG4gICAgICAgICAgeTAgPSByMSAqIE1hdGguc2luKGgxKTtcbiAgICAgICAgICB4MSA9IHkxID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDAgPSB5MCA9IDA7XG4gICAgICB9XG4gICAgICBpZiAocjApIHtcbiAgICAgICAgeDIgPSByMCAqIE1hdGguY29zKGExIC0gcDApO1xuICAgICAgICB5MiA9IHIwICogTWF0aC5zaW4oYTEgLSBwMCk7XG4gICAgICAgIHgzID0gcjAgKiBNYXRoLmNvcyhhMCArIHAwKTtcbiAgICAgICAgeTMgPSByMCAqIE1hdGguc2luKGEwICsgcDApO1xuICAgICAgICB2YXIgbDAgPSBNYXRoLmFicyhhMCAtIGExICsgMiAqIHAwKSA8PSDPgCA/IDAgOiAxO1xuICAgICAgICBpZiAocDAgJiYgZDNfc3ZnX2FyY1N3ZWVwKHgyLCB5MiwgeDMsIHkzKSA9PT0gMSAtIGN3IF4gbDApIHtcbiAgICAgICAgICB2YXIgaDAgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgICAgIHgyID0gcjAgKiBNYXRoLmNvcyhoMCk7XG4gICAgICAgICAgeTIgPSByMCAqIE1hdGguc2luKGgwKTtcbiAgICAgICAgICB4MyA9IHkzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDIgPSB5MiA9IDA7XG4gICAgICB9XG4gICAgICBpZiAoZGEgPiDOtSAmJiAocmMgPSBNYXRoLm1pbihNYXRoLmFicyhyMSAtIHIwKSAvIDIsICtjb3JuZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSkpID4gLjAwMSkge1xuICAgICAgICBjciA9IHIwIDwgcjEgXiBjdyA/IDAgOiAxO1xuICAgICAgICB2YXIgcmMxID0gcmMsIHJjMCA9IHJjO1xuICAgICAgICBpZiAoZGEgPCDPgCkge1xuICAgICAgICAgIHZhciBvYyA9IHgzID09IG51bGwgPyBbIHgyLCB5MiBdIDogeDEgPT0gbnVsbCA/IFsgeDAsIHkwIF0gOiBkM19nZW9tX3BvbHlnb25JbnRlcnNlY3QoWyB4MCwgeTAgXSwgWyB4MywgeTMgXSwgWyB4MSwgeTEgXSwgWyB4MiwgeTIgXSksIGF4ID0geDAgLSBvY1swXSwgYXkgPSB5MCAtIG9jWzFdLCBieCA9IHgxIC0gb2NbMF0sIGJ5ID0geTEgLSBvY1sxXSwga2MgPSAxIC8gTWF0aC5zaW4oTWF0aC5hY29zKChheCAqIGJ4ICsgYXkgKiBieSkgLyAoTWF0aC5zcXJ0KGF4ICogYXggKyBheSAqIGF5KSAqIE1hdGguc3FydChieCAqIGJ4ICsgYnkgKiBieSkpKSAvIDIpLCBsYyA9IE1hdGguc3FydChvY1swXSAqIG9jWzBdICsgb2NbMV0gKiBvY1sxXSk7XG4gICAgICAgICAgcmMwID0gTWF0aC5taW4ocmMsIChyMCAtIGxjKSAvIChrYyAtIDEpKTtcbiAgICAgICAgICByYzEgPSBNYXRoLm1pbihyYywgKHIxIC0gbGMpIC8gKGtjICsgMSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4MSAhPSBudWxsKSB7XG4gICAgICAgICAgdmFyIHQzMCA9IGQzX3N2Z19hcmNDb3JuZXJUYW5nZW50cyh4MyA9PSBudWxsID8gWyB4MiwgeTIgXSA6IFsgeDMsIHkzIF0sIFsgeDAsIHkwIF0sIHIxLCByYzEsIGN3KSwgdDEyID0gZDNfc3ZnX2FyY0Nvcm5lclRhbmdlbnRzKFsgeDEsIHkxIF0sIFsgeDIsIHkyIF0sIHIxLCByYzEsIGN3KTtcbiAgICAgICAgICBpZiAocmMgPT09IHJjMSkge1xuICAgICAgICAgICAgcGF0aC5wdXNoKFwiTVwiLCB0MzBbMF0sIFwiQVwiLCByYzEsIFwiLFwiLCByYzEsIFwiIDAgMCxcIiwgY3IsIFwiIFwiLCB0MzBbMV0sIFwiQVwiLCByMSwgXCIsXCIsIHIxLCBcIiAwIFwiLCAxIC0gY3cgXiBkM19zdmdfYXJjU3dlZXAodDMwWzFdWzBdLCB0MzBbMV1bMV0sIHQxMlsxXVswXSwgdDEyWzFdWzFdKSwgXCIsXCIsIGN3LCBcIiBcIiwgdDEyWzFdLCBcIkFcIiwgcmMxLCBcIixcIiwgcmMxLCBcIiAwIDAsXCIsIGNyLCBcIiBcIiwgdDEyWzBdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGF0aC5wdXNoKFwiTVwiLCB0MzBbMF0sIFwiQVwiLCByYzEsIFwiLFwiLCByYzEsIFwiIDAgMSxcIiwgY3IsIFwiIFwiLCB0MTJbMF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXRoLnB1c2goXCJNXCIsIHgwLCBcIixcIiwgeTApO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4MyAhPSBudWxsKSB7XG4gICAgICAgICAgdmFyIHQwMyA9IGQzX3N2Z19hcmNDb3JuZXJUYW5nZW50cyhbIHgwLCB5MCBdLCBbIHgzLCB5MyBdLCByMCwgLXJjMCwgY3cpLCB0MjEgPSBkM19zdmdfYXJjQ29ybmVyVGFuZ2VudHMoWyB4MiwgeTIgXSwgeDEgPT0gbnVsbCA/IFsgeDAsIHkwIF0gOiBbIHgxLCB5MSBdLCByMCwgLXJjMCwgY3cpO1xuICAgICAgICAgIGlmIChyYyA9PT0gcmMwKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goXCJMXCIsIHQyMVswXSwgXCJBXCIsIHJjMCwgXCIsXCIsIHJjMCwgXCIgMCAwLFwiLCBjciwgXCIgXCIsIHQyMVsxXSwgXCJBXCIsIHIwLCBcIixcIiwgcjAsIFwiIDAgXCIsIGN3IF4gZDNfc3ZnX2FyY1N3ZWVwKHQyMVsxXVswXSwgdDIxWzFdWzFdLCB0MDNbMV1bMF0sIHQwM1sxXVsxXSksIFwiLFwiLCAxIC0gY3csIFwiIFwiLCB0MDNbMV0sIFwiQVwiLCByYzAsIFwiLFwiLCByYzAsIFwiIDAgMCxcIiwgY3IsIFwiIFwiLCB0MDNbMF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goXCJMXCIsIHQyMVswXSwgXCJBXCIsIHJjMCwgXCIsXCIsIHJjMCwgXCIgMCAwLFwiLCBjciwgXCIgXCIsIHQwM1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhdGgucHVzaChcIkxcIiwgeDIsIFwiLFwiLCB5Mik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdGgucHVzaChcIk1cIiwgeDAsIFwiLFwiLCB5MCk7XG4gICAgICAgIGlmICh4MSAhPSBudWxsKSBwYXRoLnB1c2goXCJBXCIsIHIxLCBcIixcIiwgcjEsIFwiIDAgXCIsIGwxLCBcIixcIiwgY3csIFwiIFwiLCB4MSwgXCIsXCIsIHkxKTtcbiAgICAgICAgcGF0aC5wdXNoKFwiTFwiLCB4MiwgXCIsXCIsIHkyKTtcbiAgICAgICAgaWYgKHgzICE9IG51bGwpIHBhdGgucHVzaChcIkFcIiwgcjAsIFwiLFwiLCByMCwgXCIgMCBcIiwgbDAsIFwiLFwiLCAxIC0gY3csIFwiIFwiLCB4MywgXCIsXCIsIHkzKTtcbiAgICAgIH1cbiAgICAgIHBhdGgucHVzaChcIlpcIik7XG4gICAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjaXJjbGVTZWdtZW50KHIxLCBjdykge1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyByMSArIFwiQVwiICsgcjEgKyBcIixcIiArIHIxICsgXCIgMCAxLFwiICsgY3cgKyBcIiAwLFwiICsgLXIxICsgXCJBXCIgKyByMSArIFwiLFwiICsgcjEgKyBcIiAwIDEsXCIgKyBjdyArIFwiIDAsXCIgKyByMTtcbiAgICB9XG4gICAgYXJjLmlubmVyUmFkaXVzID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gaW5uZXJSYWRpdXM7XG4gICAgICBpbm5lclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLm91dGVyUmFkaXVzID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb3V0ZXJSYWRpdXM7XG4gICAgICBvdXRlclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmNvcm5lclJhZGl1cyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGNvcm5lclJhZGl1cztcbiAgICAgIGNvcm5lclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnBhZFJhZGl1cyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBhZFJhZGl1cztcbiAgICAgIHBhZFJhZGl1cyA9IHYgPT0gZDNfc3ZnX2FyY0F1dG8gPyBkM19zdmdfYXJjQXV0byA6IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGFydEFuZ2xlO1xuICAgICAgc3RhcnRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmVuZEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZW5kQW5nbGU7XG4gICAgICBlbmRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnBhZEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkQW5nbGU7XG4gICAgICBwYWRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmNlbnRyb2lkID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgciA9ICgraW5uZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtvdXRlclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIsIGEgPSAoK3N0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIgLSBoYWxmz4A7XG4gICAgICByZXR1cm4gWyBNYXRoLmNvcyhhKSAqIHIsIE1hdGguc2luKGEpICogciBdO1xuICAgIH07XG4gICAgcmV0dXJuIGFyYztcbiAgfTtcbiAgdmFyIGQzX3N2Z19hcmNBdXRvID0gXCJhdXRvXCI7XG4gIGZ1bmN0aW9uIGQzX3N2Z19hcmNJbm5lclJhZGl1cyhkKSB7XG4gICAgcmV0dXJuIGQuaW5uZXJSYWRpdXM7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2FyY091dGVyUmFkaXVzKGQpIHtcbiAgICByZXR1cm4gZC5vdXRlclJhZGl1cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjU3RhcnRBbmdsZShkKSB7XG4gICAgcmV0dXJuIGQuc3RhcnRBbmdsZTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjRW5kQW5nbGUoZCkge1xuICAgIHJldHVybiBkLmVuZEFuZ2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19hcmNQYWRBbmdsZShkKSB7XG4gICAgcmV0dXJuIGQgJiYgZC5wYWRBbmdsZTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjU3dlZXAoeDAsIHkwLCB4MSwgeTEpIHtcbiAgICByZXR1cm4gKHgwIC0geDEpICogeTAgLSAoeTAgLSB5MSkgKiB4MCA+IDAgPyAwIDogMTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjQ29ybmVyVGFuZ2VudHMocDAsIHAxLCByMSwgcmMsIGN3KSB7XG4gICAgdmFyIHgwMSA9IHAwWzBdIC0gcDFbMF0sIHkwMSA9IHAwWzFdIC0gcDFbMV0sIGxvID0gKGN3ID8gcmMgOiAtcmMpIC8gTWF0aC5zcXJ0KHgwMSAqIHgwMSArIHkwMSAqIHkwMSksIG94ID0gbG8gKiB5MDEsIG95ID0gLWxvICogeDAxLCB4MSA9IHAwWzBdICsgb3gsIHkxID0gcDBbMV0gKyBveSwgeDIgPSBwMVswXSArIG94LCB5MiA9IHAxWzFdICsgb3ksIHgzID0gKHgxICsgeDIpIC8gMiwgeTMgPSAoeTEgKyB5MikgLyAyLCBkeCA9IHgyIC0geDEsIGR5ID0geTIgLSB5MSwgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeSwgciA9IHIxIC0gcmMsIEQgPSB4MSAqIHkyIC0geDIgKiB5MSwgZCA9IChkeSA8IDAgPyAtMSA6IDEpICogTWF0aC5zcXJ0KE1hdGgubWF4KDAsIHIgKiByICogZDIgLSBEICogRCkpLCBjeDAgPSAoRCAqIGR5IC0gZHggKiBkKSAvIGQyLCBjeTAgPSAoLUQgKiBkeCAtIGR5ICogZCkgLyBkMiwgY3gxID0gKEQgKiBkeSArIGR4ICogZCkgLyBkMiwgY3kxID0gKC1EICogZHggKyBkeSAqIGQpIC8gZDIsIGR4MCA9IGN4MCAtIHgzLCBkeTAgPSBjeTAgLSB5MywgZHgxID0gY3gxIC0geDMsIGR5MSA9IGN5MSAtIHkzO1xuICAgIGlmIChkeDAgKiBkeDAgKyBkeTAgKiBkeTAgPiBkeDEgKiBkeDEgKyBkeTEgKiBkeTEpIGN4MCA9IGN4MSwgY3kwID0gY3kxO1xuICAgIHJldHVybiBbIFsgY3gwIC0gb3gsIGN5MCAtIG95IF0sIFsgY3gwICogcjEgLyByLCBjeTAgKiByMSAvIHIgXSBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lKHByb2plY3Rpb24pIHtcbiAgICB2YXIgeCA9IGQzX2dlb21fcG9pbnRYLCB5ID0gZDNfZ2VvbV9wb2ludFksIGRlZmluZWQgPSBkM190cnVlLCBpbnRlcnBvbGF0ZSA9IGQzX3N2Z19saW5lTGluZWFyLCBpbnRlcnBvbGF0ZUtleSA9IGludGVycG9sYXRlLmtleSwgdGVuc2lvbiA9IC43O1xuICAgIGZ1bmN0aW9uIGxpbmUoZGF0YSkge1xuICAgICAgdmFyIHNlZ21lbnRzID0gW10sIHBvaW50cyA9IFtdLCBpID0gLTEsIG4gPSBkYXRhLmxlbmd0aCwgZCwgZnggPSBkM19mdW5jdG9yKHgpLCBmeSA9IGQzX2Z1bmN0b3IoeSk7XG4gICAgICBmdW5jdGlvbiBzZWdtZW50KCkge1xuICAgICAgICBzZWdtZW50cy5wdXNoKFwiTVwiLCBpbnRlcnBvbGF0ZShwcm9qZWN0aW9uKHBvaW50cyksIHRlbnNpb24pKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkZWZpbmVkLmNhbGwodGhpcywgZCA9IGRhdGFbaV0sIGkpKSB7XG4gICAgICAgICAgcG9pbnRzLnB1c2goWyArZnguY2FsbCh0aGlzLCBkLCBpKSwgK2Z5LmNhbGwodGhpcywgZCwgaSkgXSk7XG4gICAgICAgIH0gZWxzZSBpZiAocG9pbnRzLmxlbmd0aCkge1xuICAgICAgICAgIHNlZ21lbnQoKTtcbiAgICAgICAgICBwb2ludHMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHBvaW50cy5sZW5ndGgpIHNlZ21lbnQoKTtcbiAgICAgIHJldHVybiBzZWdtZW50cy5sZW5ndGggPyBzZWdtZW50cy5qb2luKFwiXCIpIDogbnVsbDtcbiAgICB9XG4gICAgbGluZS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDtcbiAgICAgIHggPSBfO1xuICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfTtcbiAgICBsaW5lLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5O1xuICAgICAgeSA9IF87XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICAgIGxpbmUuZGVmaW5lZCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRlZmluZWQ7XG4gICAgICBkZWZpbmVkID0gXztcbiAgICAgIHJldHVybiBsaW5lO1xuICAgIH07XG4gICAgbGluZS5pbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGludGVycG9sYXRlS2V5O1xuICAgICAgaWYgKHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIpIGludGVycG9sYXRlS2V5ID0gaW50ZXJwb2xhdGUgPSBfOyBlbHNlIGludGVycG9sYXRlS2V5ID0gKGludGVycG9sYXRlID0gZDNfc3ZnX2xpbmVJbnRlcnBvbGF0b3JzLmdldChfKSB8fCBkM19zdmdfbGluZUxpbmVhcikua2V5O1xuICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfTtcbiAgICBsaW5lLnRlbnNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB0ZW5zaW9uO1xuICAgICAgdGVuc2lvbiA9IF87XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICAgIHJldHVybiBsaW5lO1xuICB9XG4gIGQzLnN2Zy5saW5lID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX3N2Z19saW5lKGQzX2lkZW50aXR5KTtcbiAgfTtcbiAgdmFyIGQzX3N2Z19saW5lSW50ZXJwb2xhdG9ycyA9IGQzLm1hcCh7XG4gICAgbGluZWFyOiBkM19zdmdfbGluZUxpbmVhcixcbiAgICBcImxpbmVhci1jbG9zZWRcIjogZDNfc3ZnX2xpbmVMaW5lYXJDbG9zZWQsXG4gICAgc3RlcDogZDNfc3ZnX2xpbmVTdGVwLFxuICAgIFwic3RlcC1iZWZvcmVcIjogZDNfc3ZnX2xpbmVTdGVwQmVmb3JlLFxuICAgIFwic3RlcC1hZnRlclwiOiBkM19zdmdfbGluZVN0ZXBBZnRlcixcbiAgICBiYXNpczogZDNfc3ZnX2xpbmVCYXNpcyxcbiAgICBcImJhc2lzLW9wZW5cIjogZDNfc3ZnX2xpbmVCYXNpc09wZW4sXG4gICAgXCJiYXNpcy1jbG9zZWRcIjogZDNfc3ZnX2xpbmVCYXNpc0Nsb3NlZCxcbiAgICBidW5kbGU6IGQzX3N2Z19saW5lQnVuZGxlLFxuICAgIGNhcmRpbmFsOiBkM19zdmdfbGluZUNhcmRpbmFsLFxuICAgIFwiY2FyZGluYWwtb3BlblwiOiBkM19zdmdfbGluZUNhcmRpbmFsT3BlbixcbiAgICBcImNhcmRpbmFsLWNsb3NlZFwiOiBkM19zdmdfbGluZUNhcmRpbmFsQ2xvc2VkLFxuICAgIG1vbm90b25lOiBkM19zdmdfbGluZU1vbm90b25lXG4gIH0pO1xuICBkM19zdmdfbGluZUludGVycG9sYXRvcnMuZm9yRWFjaChmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgdmFsdWUua2V5ID0ga2V5O1xuICAgIHZhbHVlLmNsb3NlZCA9IC8tY2xvc2VkJC8udGVzdChrZXkpO1xuICB9KTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPiAxID8gcG9pbnRzLmpvaW4oXCJMXCIpIDogcG9pbnRzICsgXCJaXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVMaW5lYXJDbG9zZWQocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5qb2luKFwiTFwiKSArIFwiWlwiO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU3RlcChwb2ludHMpIHtcbiAgICB2YXIgaSA9IDAsIG4gPSBwb2ludHMubGVuZ3RoLCBwID0gcG9pbnRzWzBdLCBwYXRoID0gWyBwWzBdLCBcIixcIiwgcFsxXSBdO1xuICAgIHdoaWxlICgrK2kgPCBuKSBwYXRoLnB1c2goXCJIXCIsIChwWzBdICsgKHAgPSBwb2ludHNbaV0pWzBdKSAvIDIsIFwiVlwiLCBwWzFdKTtcbiAgICBpZiAobiA+IDEpIHBhdGgucHVzaChcIkhcIiwgcFswXSk7XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZVN0ZXBCZWZvcmUocG9pbnRzKSB7XG4gICAgdmFyIGkgPSAwLCBuID0gcG9pbnRzLmxlbmd0aCwgcCA9IHBvaW50c1swXSwgcGF0aCA9IFsgcFswXSwgXCIsXCIsIHBbMV0gXTtcbiAgICB3aGlsZSAoKytpIDwgbikgcGF0aC5wdXNoKFwiVlwiLCAocCA9IHBvaW50c1tpXSlbMV0sIFwiSFwiLCBwWzBdKTtcbiAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU3RlcEFmdGVyKHBvaW50cykge1xuICAgIHZhciBpID0gMCwgbiA9IHBvaW50cy5sZW5ndGgsIHAgPSBwb2ludHNbMF0sIHBhdGggPSBbIHBbMF0sIFwiLFwiLCBwWzFdIF07XG4gICAgd2hpbGUgKCsraSA8IG4pIHBhdGgucHVzaChcIkhcIiwgKHAgPSBwb2ludHNbaV0pWzBdLCBcIlZcIiwgcFsxXSk7XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsT3Blbihwb2ludHMsIHRlbnNpb24pIHtcbiAgICByZXR1cm4gcG9pbnRzLmxlbmd0aCA8IDQgPyBkM19zdmdfbGluZUxpbmVhcihwb2ludHMpIDogcG9pbnRzWzFdICsgZDNfc3ZnX2xpbmVIZXJtaXRlKHBvaW50cy5zbGljZSgxLCAtMSksIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhwb2ludHMsIHRlbnNpb24pKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsQ2xvc2VkKHBvaW50cywgdGVuc2lvbikge1xuICAgIHJldHVybiBwb2ludHMubGVuZ3RoIDwgMyA/IGQzX3N2Z19saW5lTGluZWFyQ2xvc2VkKHBvaW50cykgOiBwb2ludHNbMF0gKyBkM19zdmdfbGluZUhlcm1pdGUoKHBvaW50cy5wdXNoKHBvaW50c1swXSksIFxuICAgIHBvaW50cyksIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhbIHBvaW50c1twb2ludHMubGVuZ3RoIC0gMl0gXS5jb25jYXQocG9pbnRzLCBbIHBvaW50c1sxXSBdKSwgdGVuc2lvbikpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lQ2FyZGluYWwocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPCAzID8gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSA6IHBvaW50c1swXSArIGQzX3N2Z19saW5lSGVybWl0ZShwb2ludHMsIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhwb2ludHMsIHRlbnNpb24pKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUhlcm1pdGUocG9pbnRzLCB0YW5nZW50cykge1xuICAgIGlmICh0YW5nZW50cy5sZW5ndGggPCAxIHx8IHBvaW50cy5sZW5ndGggIT0gdGFuZ2VudHMubGVuZ3RoICYmIHBvaW50cy5sZW5ndGggIT0gdGFuZ2VudHMubGVuZ3RoICsgMikge1xuICAgICAgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgfVxuICAgIHZhciBxdWFkID0gcG9pbnRzLmxlbmd0aCAhPSB0YW5nZW50cy5sZW5ndGgsIHBhdGggPSBcIlwiLCBwMCA9IHBvaW50c1swXSwgcCA9IHBvaW50c1sxXSwgdDAgPSB0YW5nZW50c1swXSwgdCA9IHQwLCBwaSA9IDE7XG4gICAgaWYgKHF1YWQpIHtcbiAgICAgIHBhdGggKz0gXCJRXCIgKyAocFswXSAtIHQwWzBdICogMiAvIDMpICsgXCIsXCIgKyAocFsxXSAtIHQwWzFdICogMiAvIDMpICsgXCIsXCIgKyBwWzBdICsgXCIsXCIgKyBwWzFdO1xuICAgICAgcDAgPSBwb2ludHNbMV07XG4gICAgICBwaSA9IDI7XG4gICAgfVxuICAgIGlmICh0YW5nZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0ID0gdGFuZ2VudHNbMV07XG4gICAgICBwID0gcG9pbnRzW3BpXTtcbiAgICAgIHBpKys7XG4gICAgICBwYXRoICs9IFwiQ1wiICsgKHAwWzBdICsgdDBbMF0pICsgXCIsXCIgKyAocDBbMV0gKyB0MFsxXSkgKyBcIixcIiArIChwWzBdIC0gdFswXSkgKyBcIixcIiArIChwWzFdIC0gdFsxXSkgKyBcIixcIiArIHBbMF0gKyBcIixcIiArIHBbMV07XG4gICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHRhbmdlbnRzLmxlbmd0aDsgaSsrLCBwaSsrKSB7XG4gICAgICAgIHAgPSBwb2ludHNbcGldO1xuICAgICAgICB0ID0gdGFuZ2VudHNbaV07XG4gICAgICAgIHBhdGggKz0gXCJTXCIgKyAocFswXSAtIHRbMF0pICsgXCIsXCIgKyAocFsxXSAtIHRbMV0pICsgXCIsXCIgKyBwWzBdICsgXCIsXCIgKyBwWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocXVhZCkge1xuICAgICAgdmFyIGxwID0gcG9pbnRzW3BpXTtcbiAgICAgIHBhdGggKz0gXCJRXCIgKyAocFswXSArIHRbMF0gKiAyIC8gMykgKyBcIixcIiArIChwWzFdICsgdFsxXSAqIDIgLyAzKSArIFwiLFwiICsgbHBbMF0gKyBcIixcIiArIGxwWzFdO1xuICAgIH1cbiAgICByZXR1cm4gcGF0aDtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsVGFuZ2VudHMocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgdmFyIHRhbmdlbnRzID0gW10sIGEgPSAoMSAtIHRlbnNpb24pIC8gMiwgcDAsIHAxID0gcG9pbnRzWzBdLCBwMiA9IHBvaW50c1sxXSwgaSA9IDEsIG4gPSBwb2ludHMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBwMCA9IHAxO1xuICAgICAgcDEgPSBwMjtcbiAgICAgIHAyID0gcG9pbnRzW2ldO1xuICAgICAgdGFuZ2VudHMucHVzaChbIGEgKiAocDJbMF0gLSBwMFswXSksIGEgKiAocDJbMV0gLSBwMFsxXSkgXSk7XG4gICAgfVxuICAgIHJldHVybiB0YW5nZW50cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUJhc2lzKHBvaW50cykge1xuICAgIGlmIChwb2ludHMubGVuZ3RoIDwgMykgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgdmFyIGkgPSAxLCBuID0gcG9pbnRzLmxlbmd0aCwgcGkgPSBwb2ludHNbMF0sIHgwID0gcGlbMF0sIHkwID0gcGlbMV0sIHB4ID0gWyB4MCwgeDAsIHgwLCAocGkgPSBwb2ludHNbMV0pWzBdIF0sIHB5ID0gWyB5MCwgeTAsIHkwLCBwaVsxXSBdLCBwYXRoID0gWyB4MCwgXCIsXCIsIHkwLCBcIkxcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIzLCBweCksIFwiLFwiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB5KSBdO1xuICAgIHBvaW50cy5wdXNoKHBvaW50c1tuIC0gMV0pO1xuICAgIHdoaWxlICgrK2kgPD0gbikge1xuICAgICAgcGkgPSBwb2ludHNbaV07XG4gICAgICBweC5zaGlmdCgpO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5zaGlmdCgpO1xuICAgICAgcHkucHVzaChwaVsxXSk7XG4gICAgICBkM19zdmdfbGluZUJhc2lzQmV6aWVyKHBhdGgsIHB4LCBweSk7XG4gICAgfVxuICAgIHBvaW50cy5wb3AoKTtcbiAgICBwYXRoLnB1c2goXCJMXCIsIHBpKTtcbiAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lQmFzaXNPcGVuKHBvaW50cykge1xuICAgIGlmIChwb2ludHMubGVuZ3RoIDwgNCkgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgdmFyIHBhdGggPSBbXSwgaSA9IC0xLCBuID0gcG9pbnRzLmxlbmd0aCwgcGksIHB4ID0gWyAwIF0sIHB5ID0gWyAwIF07XG4gICAgd2hpbGUgKCsraSA8IDMpIHtcbiAgICAgIHBpID0gcG9pbnRzW2ldO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5wdXNoKHBpWzFdKTtcbiAgICB9XG4gICAgcGF0aC5wdXNoKGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgcHgpICsgXCIsXCIgKyBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB5KSk7XG4gICAgLS1pO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBwaSA9IHBvaW50c1tpXTtcbiAgICAgIHB4LnNoaWZ0KCk7XG4gICAgICBweC5wdXNoKHBpWzBdKTtcbiAgICAgIHB5LnNoaWZ0KCk7XG4gICAgICBweS5wdXNoKHBpWzFdKTtcbiAgICAgIGQzX3N2Z19saW5lQmFzaXNCZXppZXIocGF0aCwgcHgsIHB5KTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUJhc2lzQ2xvc2VkKHBvaW50cykge1xuICAgIHZhciBwYXRoLCBpID0gLTEsIG4gPSBwb2ludHMubGVuZ3RoLCBtID0gbiArIDQsIHBpLCBweCA9IFtdLCBweSA9IFtdO1xuICAgIHdoaWxlICgrK2kgPCA0KSB7XG4gICAgICBwaSA9IHBvaW50c1tpICUgbl07XG4gICAgICBweC5wdXNoKHBpWzBdKTtcbiAgICAgIHB5LnB1c2gocGlbMV0pO1xuICAgIH1cbiAgICBwYXRoID0gWyBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB4KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgcHkpIF07XG4gICAgLS1pO1xuICAgIHdoaWxlICgrK2kgPCBtKSB7XG4gICAgICBwaSA9IHBvaW50c1tpICUgbl07XG4gICAgICBweC5zaGlmdCgpO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5zaGlmdCgpO1xuICAgICAgcHkucHVzaChwaVsxXSk7XG4gICAgICBkM19zdmdfbGluZUJhc2lzQmV6aWVyKHBhdGgsIHB4LCBweSk7XG4gICAgfVxuICAgIHJldHVybiBwYXRoLmpvaW4oXCJcIik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVCdW5kbGUocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgdmFyIG4gPSBwb2ludHMubGVuZ3RoIC0gMTtcbiAgICBpZiAobikge1xuICAgICAgdmFyIHgwID0gcG9pbnRzWzBdWzBdLCB5MCA9IHBvaW50c1swXVsxXSwgZHggPSBwb2ludHNbbl1bMF0gLSB4MCwgZHkgPSBwb2ludHNbbl1bMV0gLSB5MCwgaSA9IC0xLCBwLCB0O1xuICAgICAgd2hpbGUgKCsraSA8PSBuKSB7XG4gICAgICAgIHAgPSBwb2ludHNbaV07XG4gICAgICAgIHQgPSBpIC8gbjtcbiAgICAgICAgcFswXSA9IHRlbnNpb24gKiBwWzBdICsgKDEgLSB0ZW5zaW9uKSAqICh4MCArIHQgKiBkeCk7XG4gICAgICAgIHBbMV0gPSB0ZW5zaW9uICogcFsxXSArICgxIC0gdGVuc2lvbikgKiAoeTAgKyB0ICogZHkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc3ZnX2xpbmVCYXNpcyhwb2ludHMpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lRG90NChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXSArIGFbM10gKiBiWzNdO1xuICB9XG4gIHZhciBkM19zdmdfbGluZUJhc2lzQmV6aWVyMSA9IFsgMCwgMiAvIDMsIDEgLyAzLCAwIF0sIGQzX3N2Z19saW5lQmFzaXNCZXppZXIyID0gWyAwLCAxIC8gMywgMiAvIDMsIDAgXSwgZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMgPSBbIDAsIDEgLyA2LCAyIC8gMywgMSAvIDYgXTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVCYXNpc0JlemllcihwYXRoLCB4LCB5KSB7XG4gICAgcGF0aC5wdXNoKFwiQ1wiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjEsIHgpLCBcIixcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIxLCB5KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMiwgeCksIFwiLFwiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjIsIHkpLCBcIixcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIzLCB4KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgeSkpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU2xvcGUocDAsIHAxKSB7XG4gICAgcmV0dXJuIChwMVsxXSAtIHAwWzFdKSAvIChwMVswXSAtIHAwWzBdKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUZpbml0ZURpZmZlcmVuY2VzKHBvaW50cykge1xuICAgIHZhciBpID0gMCwgaiA9IHBvaW50cy5sZW5ndGggLSAxLCBtID0gW10sIHAwID0gcG9pbnRzWzBdLCBwMSA9IHBvaW50c1sxXSwgZCA9IG1bMF0gPSBkM19zdmdfbGluZVNsb3BlKHAwLCBwMSk7XG4gICAgd2hpbGUgKCsraSA8IGopIHtcbiAgICAgIG1baV0gPSAoZCArIChkID0gZDNfc3ZnX2xpbmVTbG9wZShwMCA9IHAxLCBwMSA9IHBvaW50c1tpICsgMV0pKSkgLyAyO1xuICAgIH1cbiAgICBtW2ldID0gZDtcbiAgICByZXR1cm4gbTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZU1vbm90b25lVGFuZ2VudHMocG9pbnRzKSB7XG4gICAgdmFyIHRhbmdlbnRzID0gW10sIGQsIGEsIGIsIHMsIG0gPSBkM19zdmdfbGluZUZpbml0ZURpZmZlcmVuY2VzKHBvaW50cyksIGkgPSAtMSwgaiA9IHBvaW50cy5sZW5ndGggLSAxO1xuICAgIHdoaWxlICgrK2kgPCBqKSB7XG4gICAgICBkID0gZDNfc3ZnX2xpbmVTbG9wZShwb2ludHNbaV0sIHBvaW50c1tpICsgMV0pO1xuICAgICAgaWYgKGFicyhkKSA8IM61KSB7XG4gICAgICAgIG1baV0gPSBtW2kgKyAxXSA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhID0gbVtpXSAvIGQ7XG4gICAgICAgIGIgPSBtW2kgKyAxXSAvIGQ7XG4gICAgICAgIHMgPSBhICogYSArIGIgKiBiO1xuICAgICAgICBpZiAocyA+IDkpIHtcbiAgICAgICAgICBzID0gZCAqIDMgLyBNYXRoLnNxcnQocyk7XG4gICAgICAgICAgbVtpXSA9IHMgKiBhO1xuICAgICAgICAgIG1baSArIDFdID0gcyAqIGI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPD0gaikge1xuICAgICAgcyA9IChwb2ludHNbTWF0aC5taW4oaiwgaSArIDEpXVswXSAtIHBvaW50c1tNYXRoLm1heCgwLCBpIC0gMSldWzBdKSAvICg2ICogKDEgKyBtW2ldICogbVtpXSkpO1xuICAgICAgdGFuZ2VudHMucHVzaChbIHMgfHwgMCwgbVtpXSAqIHMgfHwgMCBdKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhbmdlbnRzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lTW9ub3RvbmUocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPCAzID8gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSA6IHBvaW50c1swXSArIGQzX3N2Z19saW5lSGVybWl0ZShwb2ludHMsIGQzX3N2Z19saW5lTW9ub3RvbmVUYW5nZW50cyhwb2ludHMpKTtcbiAgfVxuICBkMy5zdmcubGluZS5yYWRpYWwgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbGluZSA9IGQzX3N2Z19saW5lKGQzX3N2Z19saW5lUmFkaWFsKTtcbiAgICBsaW5lLnJhZGl1cyA9IGxpbmUueCwgZGVsZXRlIGxpbmUueDtcbiAgICBsaW5lLmFuZ2xlID0gbGluZS55LCBkZWxldGUgbGluZS55O1xuICAgIHJldHVybiBsaW5lO1xuICB9O1xuICBmdW5jdGlvbiBkM19zdmdfbGluZVJhZGlhbChwb2ludHMpIHtcbiAgICB2YXIgcG9pbnQsIGkgPSAtMSwgbiA9IHBvaW50cy5sZW5ndGgsIHIsIGE7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgciA9IHBvaW50WzBdO1xuICAgICAgYSA9IHBvaW50WzFdIC0gaGFsZs+AO1xuICAgICAgcG9pbnRbMF0gPSByICogTWF0aC5jb3MoYSk7XG4gICAgICBwb2ludFsxXSA9IHIgKiBNYXRoLnNpbihhKTtcbiAgICB9XG4gICAgcmV0dXJuIHBvaW50cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJlYShwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHgwID0gZDNfZ2VvbV9wb2ludFgsIHgxID0gZDNfZ2VvbV9wb2ludFgsIHkwID0gMCwgeTEgPSBkM19nZW9tX3BvaW50WSwgZGVmaW5lZCA9IGQzX3RydWUsIGludGVycG9sYXRlID0gZDNfc3ZnX2xpbmVMaW5lYXIsIGludGVycG9sYXRlS2V5ID0gaW50ZXJwb2xhdGUua2V5LCBpbnRlcnBvbGF0ZVJldmVyc2UgPSBpbnRlcnBvbGF0ZSwgTCA9IFwiTFwiLCB0ZW5zaW9uID0gLjc7XG4gICAgZnVuY3Rpb24gYXJlYShkYXRhKSB7XG4gICAgICB2YXIgc2VnbWVudHMgPSBbXSwgcG9pbnRzMCA9IFtdLCBwb2ludHMxID0gW10sIGkgPSAtMSwgbiA9IGRhdGEubGVuZ3RoLCBkLCBmeDAgPSBkM19mdW5jdG9yKHgwKSwgZnkwID0gZDNfZnVuY3Rvcih5MCksIGZ4MSA9IHgwID09PSB4MSA/IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4geDtcbiAgICAgIH0gOiBkM19mdW5jdG9yKHgxKSwgZnkxID0geTAgPT09IHkxID8gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB5O1xuICAgICAgfSA6IGQzX2Z1bmN0b3IoeTEpLCB4LCB5O1xuICAgICAgZnVuY3Rpb24gc2VnbWVudCgpIHtcbiAgICAgICAgc2VnbWVudHMucHVzaChcIk1cIiwgaW50ZXJwb2xhdGUocHJvamVjdGlvbihwb2ludHMxKSwgdGVuc2lvbiksIEwsIGludGVycG9sYXRlUmV2ZXJzZShwcm9qZWN0aW9uKHBvaW50czAucmV2ZXJzZSgpKSwgdGVuc2lvbiksIFwiWlwiKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkZWZpbmVkLmNhbGwodGhpcywgZCA9IGRhdGFbaV0sIGkpKSB7XG4gICAgICAgICAgcG9pbnRzMC5wdXNoKFsgeCA9ICtmeDAuY2FsbCh0aGlzLCBkLCBpKSwgeSA9ICtmeTAuY2FsbCh0aGlzLCBkLCBpKSBdKTtcbiAgICAgICAgICBwb2ludHMxLnB1c2goWyArZngxLmNhbGwodGhpcywgZCwgaSksICtmeTEuY2FsbCh0aGlzLCBkLCBpKSBdKTtcbiAgICAgICAgfSBlbHNlIGlmIChwb2ludHMwLmxlbmd0aCkge1xuICAgICAgICAgIHNlZ21lbnQoKTtcbiAgICAgICAgICBwb2ludHMwID0gW107XG4gICAgICAgICAgcG9pbnRzMSA9IFtdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocG9pbnRzMC5sZW5ndGgpIHNlZ21lbnQoKTtcbiAgICAgIHJldHVybiBzZWdtZW50cy5sZW5ndGggPyBzZWdtZW50cy5qb2luKFwiXCIpIDogbnVsbDtcbiAgICB9XG4gICAgYXJlYS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDE7XG4gICAgICB4MCA9IHgxID0gXztcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS54MCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHgwO1xuICAgICAgeDAgPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICBhcmVhLngxID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDE7XG4gICAgICB4MSA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHkxO1xuICAgICAgeTAgPSB5MSA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEueTAgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5MDtcbiAgICAgIHkwID0gXztcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS55MSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHkxO1xuICAgICAgeTEgPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICBhcmVhLmRlZmluZWQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkZWZpbmVkO1xuICAgICAgZGVmaW5lZCA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEuaW50ZXJwb2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBpbnRlcnBvbGF0ZUtleTtcbiAgICAgIGlmICh0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiKSBpbnRlcnBvbGF0ZUtleSA9IGludGVycG9sYXRlID0gXzsgZWxzZSBpbnRlcnBvbGF0ZUtleSA9IChpbnRlcnBvbGF0ZSA9IGQzX3N2Z19saW5lSW50ZXJwb2xhdG9ycy5nZXQoXykgfHwgZDNfc3ZnX2xpbmVMaW5lYXIpLmtleTtcbiAgICAgIGludGVycG9sYXRlUmV2ZXJzZSA9IGludGVycG9sYXRlLnJldmVyc2UgfHwgaW50ZXJwb2xhdGU7XG4gICAgICBMID0gaW50ZXJwb2xhdGUuY2xvc2VkID8gXCJNXCIgOiBcIkxcIjtcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS50ZW5zaW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGVuc2lvbjtcbiAgICAgIHRlbnNpb24gPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICByZXR1cm4gYXJlYTtcbiAgfVxuICBkM19zdmdfbGluZVN0ZXBCZWZvcmUucmV2ZXJzZSA9IGQzX3N2Z19saW5lU3RlcEFmdGVyO1xuICBkM19zdmdfbGluZVN0ZXBBZnRlci5yZXZlcnNlID0gZDNfc3ZnX2xpbmVTdGVwQmVmb3JlO1xuICBkMy5zdmcuYXJlYSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zdmdfYXJlYShkM19pZGVudGl0eSk7XG4gIH07XG4gIGQzLnN2Zy5hcmVhLnJhZGlhbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmVhID0gZDNfc3ZnX2FyZWEoZDNfc3ZnX2xpbmVSYWRpYWwpO1xuICAgIGFyZWEucmFkaXVzID0gYXJlYS54LCBkZWxldGUgYXJlYS54O1xuICAgIGFyZWEuaW5uZXJSYWRpdXMgPSBhcmVhLngwLCBkZWxldGUgYXJlYS54MDtcbiAgICBhcmVhLm91dGVyUmFkaXVzID0gYXJlYS54MSwgZGVsZXRlIGFyZWEueDE7XG4gICAgYXJlYS5hbmdsZSA9IGFyZWEueSwgZGVsZXRlIGFyZWEueTtcbiAgICBhcmVhLnN0YXJ0QW5nbGUgPSBhcmVhLnkwLCBkZWxldGUgYXJlYS55MDtcbiAgICBhcmVhLmVuZEFuZ2xlID0gYXJlYS55MSwgZGVsZXRlIGFyZWEueTE7XG4gICAgcmV0dXJuIGFyZWE7XG4gIH07XG4gIGQzLnN2Zy5jaG9yZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzb3VyY2UgPSBkM19zb3VyY2UsIHRhcmdldCA9IGQzX3RhcmdldCwgcmFkaXVzID0gZDNfc3ZnX2Nob3JkUmFkaXVzLCBzdGFydEFuZ2xlID0gZDNfc3ZnX2FyY1N0YXJ0QW5nbGUsIGVuZEFuZ2xlID0gZDNfc3ZnX2FyY0VuZEFuZ2xlO1xuICAgIGZ1bmN0aW9uIGNob3JkKGQsIGkpIHtcbiAgICAgIHZhciBzID0gc3ViZ3JvdXAodGhpcywgc291cmNlLCBkLCBpKSwgdCA9IHN1Ymdyb3VwKHRoaXMsIHRhcmdldCwgZCwgaSk7XG4gICAgICByZXR1cm4gXCJNXCIgKyBzLnAwICsgYXJjKHMuciwgcy5wMSwgcy5hMSAtIHMuYTApICsgKGVxdWFscyhzLCB0KSA/IGN1cnZlKHMuciwgcy5wMSwgcy5yLCBzLnAwKSA6IGN1cnZlKHMuciwgcy5wMSwgdC5yLCB0LnAwKSArIGFyYyh0LnIsIHQucDEsIHQuYTEgLSB0LmEwKSArIGN1cnZlKHQuciwgdC5wMSwgcy5yLCBzLnAwKSkgKyBcIlpcIjtcbiAgICB9XG4gICAgZnVuY3Rpb24gc3ViZ3JvdXAoc2VsZiwgZiwgZCwgaSkge1xuICAgICAgdmFyIHN1Ymdyb3VwID0gZi5jYWxsKHNlbGYsIGQsIGkpLCByID0gcmFkaXVzLmNhbGwoc2VsZiwgc3ViZ3JvdXAsIGkpLCBhMCA9IHN0YXJ0QW5nbGUuY2FsbChzZWxmLCBzdWJncm91cCwgaSkgLSBoYWxmz4AsIGExID0gZW5kQW5nbGUuY2FsbChzZWxmLCBzdWJncm91cCwgaSkgLSBoYWxmz4A7XG4gICAgICByZXR1cm4ge1xuICAgICAgICByOiByLFxuICAgICAgICBhMDogYTAsXG4gICAgICAgIGExOiBhMSxcbiAgICAgICAgcDA6IFsgciAqIE1hdGguY29zKGEwKSwgciAqIE1hdGguc2luKGEwKSBdLFxuICAgICAgICBwMTogWyByICogTWF0aC5jb3MoYTEpLCByICogTWF0aC5zaW4oYTEpIF1cbiAgICAgIH07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVxdWFscyhhLCBiKSB7XG4gICAgICByZXR1cm4gYS5hMCA9PSBiLmEwICYmIGEuYTEgPT0gYi5hMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXJjKHIsIHAsIGEpIHtcbiAgICAgIHJldHVybiBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIFwiICsgKyhhID4gz4ApICsgXCIsMSBcIiArIHA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGN1cnZlKHIwLCBwMCwgcjEsIHAxKSB7XG4gICAgICByZXR1cm4gXCJRIDAsMCBcIiArIHAxO1xuICAgIH1cbiAgICBjaG9yZC5yYWRpdXMgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiByYWRpdXM7XG4gICAgICByYWRpdXMgPSBkM19mdW5jdG9yKHYpO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuc291cmNlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc291cmNlO1xuICAgICAgc291cmNlID0gZDNfZnVuY3Rvcih2KTtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIGNob3JkLnRhcmdldCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRhcmdldDtcbiAgICAgIHRhcmdldCA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5zdGFydEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc3RhcnRBbmdsZTtcbiAgICAgIHN0YXJ0QW5nbGUgPSBkM19mdW5jdG9yKHYpO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuZW5kQW5nbGUgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBlbmRBbmdsZTtcbiAgICAgIGVuZEFuZ2xlID0gZDNfZnVuY3Rvcih2KTtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIHJldHVybiBjaG9yZDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2Nob3JkUmFkaXVzKGQpIHtcbiAgICByZXR1cm4gZC5yYWRpdXM7XG4gIH1cbiAgZDMuc3ZnLmRpYWdvbmFsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHNvdXJjZSA9IGQzX3NvdXJjZSwgdGFyZ2V0ID0gZDNfdGFyZ2V0LCBwcm9qZWN0aW9uID0gZDNfc3ZnX2RpYWdvbmFsUHJvamVjdGlvbjtcbiAgICBmdW5jdGlvbiBkaWFnb25hbChkLCBpKSB7XG4gICAgICB2YXIgcDAgPSBzb3VyY2UuY2FsbCh0aGlzLCBkLCBpKSwgcDMgPSB0YXJnZXQuY2FsbCh0aGlzLCBkLCBpKSwgbSA9IChwMC55ICsgcDMueSkgLyAyLCBwID0gWyBwMCwge1xuICAgICAgICB4OiBwMC54LFxuICAgICAgICB5OiBtXG4gICAgICB9LCB7XG4gICAgICAgIHg6IHAzLngsXG4gICAgICAgIHk6IG1cbiAgICAgIH0sIHAzIF07XG4gICAgICBwID0gcC5tYXAocHJvamVjdGlvbik7XG4gICAgICByZXR1cm4gXCJNXCIgKyBwWzBdICsgXCJDXCIgKyBwWzFdICsgXCIgXCIgKyBwWzJdICsgXCIgXCIgKyBwWzNdO1xuICAgIH1cbiAgICBkaWFnb25hbC5zb3VyY2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3VyY2U7XG4gICAgICBzb3VyY2UgPSBkM19mdW5jdG9yKHgpO1xuICAgICAgcmV0dXJuIGRpYWdvbmFsO1xuICAgIH07XG4gICAgZGlhZ29uYWwudGFyZ2V0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGFyZ2V0O1xuICAgICAgdGFyZ2V0ID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBkaWFnb25hbDtcbiAgICB9O1xuICAgIGRpYWdvbmFsLnByb2plY3Rpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBwcm9qZWN0aW9uO1xuICAgICAgcHJvamVjdGlvbiA9IHg7XG4gICAgICByZXR1cm4gZGlhZ29uYWw7XG4gICAgfTtcbiAgICByZXR1cm4gZGlhZ29uYWw7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3N2Z19kaWFnb25hbFByb2plY3Rpb24oZCkge1xuICAgIHJldHVybiBbIGQueCwgZC55IF07XG4gIH1cbiAgZDMuc3ZnLmRpYWdvbmFsLnJhZGlhbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBkaWFnb25hbCA9IGQzLnN2Zy5kaWFnb25hbCgpLCBwcm9qZWN0aW9uID0gZDNfc3ZnX2RpYWdvbmFsUHJvamVjdGlvbiwgcHJvamVjdGlvbl8gPSBkaWFnb25hbC5wcm9qZWN0aW9uO1xuICAgIGRpYWdvbmFsLnByb2plY3Rpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IHByb2plY3Rpb25fKGQzX3N2Z19kaWFnb25hbFJhZGlhbFByb2plY3Rpb24ocHJvamVjdGlvbiA9IHgpKSA6IHByb2plY3Rpb247XG4gICAgfTtcbiAgICByZXR1cm4gZGlhZ29uYWw7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3N2Z19kaWFnb25hbFJhZGlhbFByb2plY3Rpb24ocHJvamVjdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBkID0gcHJvamVjdGlvbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCByID0gZFswXSwgYSA9IGRbMV0gLSBoYWxmz4A7XG4gICAgICByZXR1cm4gWyByICogTWF0aC5jb3MoYSksIHIgKiBNYXRoLnNpbihhKSBdO1xuICAgIH07XG4gIH1cbiAgZDMuc3ZnLnN5bWJvbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0eXBlID0gZDNfc3ZnX3N5bWJvbFR5cGUsIHNpemUgPSBkM19zdmdfc3ltYm9sU2l6ZTtcbiAgICBmdW5jdGlvbiBzeW1ib2woZCwgaSkge1xuICAgICAgcmV0dXJuIChkM19zdmdfc3ltYm9scy5nZXQodHlwZS5jYWxsKHRoaXMsIGQsIGkpKSB8fCBkM19zdmdfc3ltYm9sQ2lyY2xlKShzaXplLmNhbGwodGhpcywgZCwgaSkpO1xuICAgIH1cbiAgICBzeW1ib2wudHlwZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHR5cGU7XG4gICAgICB0eXBlID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBzeW1ib2w7XG4gICAgfTtcbiAgICBzeW1ib2wuc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNpemU7XG4gICAgICBzaXplID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBzeW1ib2w7XG4gICAgfTtcbiAgICByZXR1cm4gc3ltYm9sO1xuICB9O1xuICBmdW5jdGlvbiBkM19zdmdfc3ltYm9sU2l6ZSgpIHtcbiAgICByZXR1cm4gNjQ7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX3N5bWJvbFR5cGUoKSB7XG4gICAgcmV0dXJuIFwiY2lyY2xlXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX3N5bWJvbENpcmNsZShzaXplKSB7XG4gICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSAvIM+AKTtcbiAgICByZXR1cm4gXCJNMCxcIiArIHIgKyBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIDEsMSAwLFwiICsgLXIgKyBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIDEsMSAwLFwiICsgciArIFwiWlwiO1xuICB9XG4gIHZhciBkM19zdmdfc3ltYm9scyA9IGQzLm1hcCh7XG4gICAgY2lyY2xlOiBkM19zdmdfc3ltYm9sQ2lyY2xlLFxuICAgIGNyb3NzOiBmdW5jdGlvbihzaXplKSB7XG4gICAgICB2YXIgciA9IE1hdGguc3FydChzaXplIC8gNSkgLyAyO1xuICAgICAgcmV0dXJuIFwiTVwiICsgLTMgKiByICsgXCIsXCIgKyAtciArIFwiSFwiICsgLXIgKyBcIlZcIiArIC0zICogciArIFwiSFwiICsgciArIFwiVlwiICsgLXIgKyBcIkhcIiArIDMgKiByICsgXCJWXCIgKyByICsgXCJIXCIgKyByICsgXCJWXCIgKyAzICogciArIFwiSFwiICsgLXIgKyBcIlZcIiArIHIgKyBcIkhcIiArIC0zICogciArIFwiWlwiO1xuICAgIH0sXG4gICAgZGlhbW9uZDogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHJ5ID0gTWF0aC5zcXJ0KHNpemUgLyAoMiAqIGQzX3N2Z19zeW1ib2xUYW4zMCkpLCByeCA9IHJ5ICogZDNfc3ZnX3N5bWJvbFRhbjMwO1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyAtcnkgKyBcIkxcIiArIHJ4ICsgXCIsMFwiICsgXCIgMCxcIiArIHJ5ICsgXCIgXCIgKyAtcnggKyBcIiwwXCIgKyBcIlpcIjtcbiAgICB9LFxuICAgIHNxdWFyZTogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSkgLyAyO1xuICAgICAgcmV0dXJuIFwiTVwiICsgLXIgKyBcIixcIiArIC1yICsgXCJMXCIgKyByICsgXCIsXCIgKyAtciArIFwiIFwiICsgciArIFwiLFwiICsgciArIFwiIFwiICsgLXIgKyBcIixcIiArIHIgKyBcIlpcIjtcbiAgICB9LFxuICAgIFwidHJpYW5nbGUtZG93blwiOiBmdW5jdGlvbihzaXplKSB7XG4gICAgICB2YXIgcnggPSBNYXRoLnNxcnQoc2l6ZSAvIGQzX3N2Z19zeW1ib2xTcXJ0MyksIHJ5ID0gcnggKiBkM19zdmdfc3ltYm9sU3FydDMgLyAyO1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyByeSArIFwiTFwiICsgcnggKyBcIixcIiArIC1yeSArIFwiIFwiICsgLXJ4ICsgXCIsXCIgKyAtcnkgKyBcIlpcIjtcbiAgICB9LFxuICAgIFwidHJpYW5nbGUtdXBcIjogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHJ4ID0gTWF0aC5zcXJ0KHNpemUgLyBkM19zdmdfc3ltYm9sU3FydDMpLCByeSA9IHJ4ICogZDNfc3ZnX3N5bWJvbFNxcnQzIC8gMjtcbiAgICAgIHJldHVybiBcIk0wLFwiICsgLXJ5ICsgXCJMXCIgKyByeCArIFwiLFwiICsgcnkgKyBcIiBcIiArIC1yeCArIFwiLFwiICsgcnkgKyBcIlpcIjtcbiAgICB9XG4gIH0pO1xuICBkMy5zdmcuc3ltYm9sVHlwZXMgPSBkM19zdmdfc3ltYm9scy5rZXlzKCk7XG4gIHZhciBkM19zdmdfc3ltYm9sU3FydDMgPSBNYXRoLnNxcnQoMyksIGQzX3N2Z19zeW1ib2xUYW4zMCA9IE1hdGgudGFuKDMwICogZDNfcmFkaWFucyk7XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpZCA9IGQzX3RyYW5zaXRpb25Jbmhlcml0SWQgfHwgKytkM190cmFuc2l0aW9uSWQsIG5zID0gZDNfdHJhbnNpdGlvbk5hbWVzcGFjZShuYW1lKSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBub2RlLCB0cmFuc2l0aW9uID0gZDNfdHJhbnNpdGlvbkluaGVyaXQgfHwge1xuICAgICAgdGltZTogRGF0ZS5ub3coKSxcbiAgICAgIGVhc2U6IGQzX2Vhc2VfY3ViaWNJbk91dCxcbiAgICAgIGRlbGF5OiAwLFxuICAgICAgZHVyYXRpb246IDI1MFxuICAgIH07XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSAtMSwgbiA9IGdyb3VwLmxlbmd0aDsgKytpIDwgbjsgKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIGQzX3RyYW5zaXRpb25Ob2RlKG5vZGUsIGksIG5zLCBpZCwgdHJhbnNpdGlvbik7XG4gICAgICAgIHN1Ymdyb3VwLnB1c2gobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgbnMsIGlkKTtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmludGVycnVwdCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKG5hbWUgPT0gbnVsbCA/IGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQgOiBkM19zZWxlY3Rpb25faW50ZXJydXB0TlMoZDNfdHJhbnNpdGlvbk5hbWVzcGFjZShuYW1lKSkpO1xuICB9O1xuICB2YXIgZDNfc2VsZWN0aW9uX2ludGVycnVwdCA9IGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHROUyhkM190cmFuc2l0aW9uTmFtZXNwYWNlKCkpO1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25faW50ZXJydXB0TlMobnMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbG9jaywgYWN0aXZlSWQsIGFjdGl2ZTtcbiAgICAgIGlmICgobG9jayA9IHRoaXNbbnNdKSAmJiAoYWN0aXZlID0gbG9ja1thY3RpdmVJZCA9IGxvY2suYWN0aXZlXSkpIHtcbiAgICAgICAgYWN0aXZlLnRpbWVyLmMgPSBudWxsO1xuICAgICAgICBhY3RpdmUudGltZXIudCA9IE5hTjtcbiAgICAgICAgaWYgKC0tbG9jay5jb3VudCkgZGVsZXRlIGxvY2tbYWN0aXZlSWRdOyBlbHNlIGRlbGV0ZSB0aGlzW25zXTtcbiAgICAgICAgbG9jay5hY3RpdmUgKz0gLjU7XG4gICAgICAgIGFjdGl2ZS5ldmVudCAmJiBhY3RpdmUuZXZlbnQuaW50ZXJydXB0LmNhbGwodGhpcywgdGhpcy5fX2RhdGFfXywgYWN0aXZlLmluZGV4KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb24oZ3JvdXBzLCBucywgaWQpIHtcbiAgICBkM19zdWJjbGFzcyhncm91cHMsIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUpO1xuICAgIGdyb3Vwcy5uYW1lc3BhY2UgPSBucztcbiAgICBncm91cHMuaWQgPSBpZDtcbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIHZhciBkM190cmFuc2l0aW9uUHJvdG90eXBlID0gW10sIGQzX3RyYW5zaXRpb25JZCA9IDAsIGQzX3RyYW5zaXRpb25Jbmhlcml0SWQsIGQzX3RyYW5zaXRpb25Jbmhlcml0O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmNhbGwgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuY2FsbDtcbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5lbXB0eSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5lbXB0eTtcbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5ub2RlID0gZDNfc2VsZWN0aW9uUHJvdG90eXBlLm5vZGU7XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuc2l6ZSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5zaXplO1xuICBkMy50cmFuc2l0aW9uID0gZnVuY3Rpb24oc2VsZWN0aW9uLCBuYW1lKSB7XG4gICAgcmV0dXJuIHNlbGVjdGlvbiAmJiBzZWxlY3Rpb24udHJhbnNpdGlvbiA/IGQzX3RyYW5zaXRpb25Jbmhlcml0SWQgPyBzZWxlY3Rpb24udHJhbnNpdGlvbihuYW1lKSA6IHNlbGVjdGlvbiA6IGQzLnNlbGVjdGlvbigpLnRyYW5zaXRpb24oc2VsZWN0aW9uKTtcbiAgfTtcbiAgZDMudHJhbnNpdGlvbi5wcm90b3R5cGUgPSBkM190cmFuc2l0aW9uUHJvdG90eXBlO1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIGlkID0gdGhpcy5pZCwgbnMgPSB0aGlzLm5hbWVzcGFjZSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2RlLCBub2RlO1xuICAgIHNlbGVjdG9yID0gZDNfc2VsZWN0aW9uX3NlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB7XG4gICAgICBzdWJncm91cHMucHVzaChzdWJncm91cCA9IFtdKTtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IC0xLCBuID0gZ3JvdXAubGVuZ3RoOyArK2kgPCBuOyApIHtcbiAgICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIChzdWJub2RlID0gc2VsZWN0b3IuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpIHtcbiAgICAgICAgICBpZiAoXCJfX2RhdGFfX1wiIGluIG5vZGUpIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICAgIGQzX3RyYW5zaXRpb25Ob2RlKHN1Ym5vZGUsIGksIG5zLCBpZCwgbm9kZVtuc11baWRdKTtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1Ymdyb3VwLnB1c2gobnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGQzX3RyYW5zaXRpb24oc3ViZ3JvdXBzLCBucywgaWQpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnNlbGVjdEFsbCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIGlkID0gdGhpcy5pZCwgbnMgPSB0aGlzLm5hbWVzcGFjZSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2Rlcywgbm9kZSwgc3Vibm9kZSwgdHJhbnNpdGlvbjtcbiAgICBzZWxlY3RvciA9IGQzX3NlbGVjdGlvbl9zZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSB0aGlzW2pdLCBpID0gLTEsIG4gPSBncm91cC5sZW5ndGg7ICsraSA8IG47ICkge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgdHJhbnNpdGlvbiA9IG5vZGVbbnNdW2lkXTtcbiAgICAgICAgICBzdWJub2RlcyA9IHNlbGVjdG9yLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaik7XG4gICAgICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICAgICAgZm9yICh2YXIgayA9IC0xLCBvID0gc3Vibm9kZXMubGVuZ3RoOyArK2sgPCBvOyApIHtcbiAgICAgICAgICAgIGlmIChzdWJub2RlID0gc3Vibm9kZXNba10pIGQzX3RyYW5zaXRpb25Ob2RlKHN1Ym5vZGUsIGssIG5zLCBpZCwgdHJhbnNpdGlvbik7XG4gICAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfdHJhbnNpdGlvbihzdWJncm91cHMsIG5zLCBpZCk7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuZmlsdGVyID0gZnVuY3Rpb24oZmlsdGVyKSB7XG4gICAgdmFyIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgZ3JvdXAsIG5vZGU7XG4gICAgaWYgKHR5cGVvZiBmaWx0ZXIgIT09IFwiZnVuY3Rpb25cIikgZmlsdGVyID0gZDNfc2VsZWN0aW9uX2ZpbHRlcihmaWx0ZXIpO1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gdGhpcy5sZW5ndGg7IGogPCBtOyBqKyspIHtcbiAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gW10pO1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSB0aGlzW2pdLCBpID0gMCwgbiA9IGdyb3VwLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICBpZiAoKG5vZGUgPSBncm91cFtpXSkgJiYgZmlsdGVyLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaikpIHtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgdGhpcy5uYW1lc3BhY2UsIHRoaXMuaWQpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnR3ZWVuID0gZnVuY3Rpb24obmFtZSwgdHdlZW4pIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0udHdlZW4uZ2V0KG5hbWUpO1xuICAgIHJldHVybiBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCB0d2VlbiA9PSBudWxsID8gZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLnR3ZWVuLnJlbW92ZShuYW1lKTtcbiAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLnR3ZWVuLnNldChuYW1lLCB0d2Vlbik7XG4gICAgfSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb25fdHdlZW4oZ3JvdXBzLCBuYW1lLCB2YWx1ZSwgdHdlZW4pIHtcbiAgICB2YXIgaWQgPSBncm91cHMuaWQsIG5zID0gZ3JvdXBzLm5hbWVzcGFjZTtcbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uX2VhY2goZ3JvdXBzLCB0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiA/IGZ1bmN0aW9uKG5vZGUsIGksIGopIHtcbiAgICAgIG5vZGVbbnNdW2lkXS50d2Vlbi5zZXQobmFtZSwgdHdlZW4odmFsdWUuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpO1xuICAgIH0gOiAodmFsdWUgPSB0d2Vlbih2YWx1ZSksIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIG5vZGVbbnNdW2lkXS50d2Vlbi5zZXQobmFtZSwgdmFsdWUpO1xuICAgIH0pKTtcbiAgfVxuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmF0dHIgPSBmdW5jdGlvbihuYW1lTlMsIHZhbHVlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICBmb3IgKHZhbHVlIGluIG5hbWVOUykgdGhpcy5hdHRyKHZhbHVlLCBuYW1lTlNbdmFsdWVdKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICB2YXIgaW50ZXJwb2xhdGUgPSBuYW1lTlMgPT0gXCJ0cmFuc2Zvcm1cIiA/IGQzX2ludGVycG9sYXRlVHJhbnNmb3JtIDogZDNfaW50ZXJwb2xhdGUsIG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWVOUyk7XG4gICAgZnVuY3Rpb24gYXR0ck51bGwoKSB7XG4gICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ck51bGxOUygpIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGF0dHJUd2VlbihiKSB7XG4gICAgICByZXR1cm4gYiA9PSBudWxsID8gYXR0ck51bGwgOiAoYiArPSBcIlwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmdldEF0dHJpYnV0ZShuYW1lKSwgaTtcbiAgICAgICAgcmV0dXJuIGEgIT09IGIgJiYgKGkgPSBpbnRlcnBvbGF0ZShhLCBiKSwgZnVuY3Rpb24odCkge1xuICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKG5hbWUsIGkodCkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyVHdlZW5OUyhiKSB7XG4gICAgICByZXR1cm4gYiA9PSBudWxsID8gYXR0ck51bGxOUyA6IChiICs9IFwiXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYSA9IHRoaXMuZ2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCksIGk7XG4gICAgICAgIHJldHVybiBhICE9PSBiICYmIChpID0gaW50ZXJwb2xhdGUoYSwgYiksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZU5TKG5hbWUuc3BhY2UsIG5hbWUubG9jYWwsIGkodCkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gZDNfdHJhbnNpdGlvbl90d2Vlbih0aGlzLCBcImF0dHIuXCIgKyBuYW1lTlMsIHZhbHVlLCBuYW1lLmxvY2FsID8gYXR0clR3ZWVuTlMgOiBhdHRyVHdlZW4pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmF0dHJUd2VlbiA9IGZ1bmN0aW9uKG5hbWVOUywgdHdlZW4pIHtcbiAgICB2YXIgbmFtZSA9IGQzLm5zLnF1YWxpZnkobmFtZU5TKTtcbiAgICBmdW5jdGlvbiBhdHRyVHdlZW4oZCwgaSkge1xuICAgICAgdmFyIGYgPSB0d2Vlbi5jYWxsKHRoaXMsIGQsIGksIHRoaXMuZ2V0QXR0cmlidXRlKG5hbWUpKTtcbiAgICAgIHJldHVybiBmICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUobmFtZSwgZih0KSk7XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyVHdlZW5OUyhkLCBpKSB7XG4gICAgICB2YXIgZiA9IHR3ZWVuLmNhbGwodGhpcywgZCwgaSwgdGhpcy5nZXRBdHRyaWJ1dGVOUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKSk7XG4gICAgICByZXR1cm4gZiAmJiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgZih0KSk7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50d2VlbihcImF0dHIuXCIgKyBuYW1lTlMsIG5hbWUubG9jYWwgPyBhdHRyVHdlZW5OUyA6IGF0dHJUd2Vlbik7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuc3R5bGUgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgICB2YXIgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgaWYgKG4gPCAzKSB7XG4gICAgICBpZiAodHlwZW9mIG5hbWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgaWYgKG4gPCAyKSB2YWx1ZSA9IFwiXCI7XG4gICAgICAgIGZvciAocHJpb3JpdHkgaW4gbmFtZSkgdGhpcy5zdHlsZShwcmlvcml0eSwgbmFtZVtwcmlvcml0eV0sIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgICBwcmlvcml0eSA9IFwiXCI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0eWxlTnVsbCgpIHtcbiAgICAgIHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkobmFtZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0eWxlU3RyaW5nKGIpIHtcbiAgICAgIHJldHVybiBiID09IG51bGwgPyBzdHlsZU51bGwgOiAoYiArPSBcIlwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGEgPSBkM193aW5kb3codGhpcykuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKG5hbWUpLCBpO1xuICAgICAgICByZXR1cm4gYSAhPT0gYiAmJiAoaSA9IGQzX2ludGVycG9sYXRlKGEsIGIpLCBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCBpKHQpLCBwcmlvcml0eSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uX3R3ZWVuKHRoaXMsIFwic3R5bGUuXCIgKyBuYW1lLCB2YWx1ZSwgc3R5bGVTdHJpbmcpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnN0eWxlVHdlZW4gPSBmdW5jdGlvbihuYW1lLCB0d2VlbiwgcHJpb3JpdHkpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIHByaW9yaXR5ID0gXCJcIjtcbiAgICBmdW5jdGlvbiBzdHlsZVR3ZWVuKGQsIGkpIHtcbiAgICAgIHZhciBmID0gdHdlZW4uY2FsbCh0aGlzLCBkLCBpLCBkM193aW5kb3codGhpcykuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKG5hbWUpKTtcbiAgICAgIHJldHVybiBmICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCBmKHQpLCBwcmlvcml0eSk7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50d2VlbihcInN0eWxlLlwiICsgbmFtZSwgc3R5bGVUd2Vlbik7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUudGV4dCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGQzX3RyYW5zaXRpb25fdHdlZW4odGhpcywgXCJ0ZXh0XCIsIHZhbHVlLCBkM190cmFuc2l0aW9uX3RleHQpO1xuICB9O1xuICBmdW5jdGlvbiBkM190cmFuc2l0aW9uX3RleHQoYikge1xuICAgIGlmIChiID09IG51bGwpIGIgPSBcIlwiO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSBiO1xuICAgIH07XG4gIH1cbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbnMgPSB0aGlzLm5hbWVzcGFjZTtcbiAgICByZXR1cm4gdGhpcy5lYWNoKFwiZW5kLnRyYW5zaXRpb25cIiwgZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcDtcbiAgICAgIGlmICh0aGlzW25zXS5jb3VudCA8IDIgJiYgKHAgPSB0aGlzLnBhcmVudE5vZGUpKSBwLnJlbW92ZUNoaWxkKHRoaXMpO1xuICAgIH0pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmVhc2UgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHZhciBpZCA9IHRoaXMuaWQsIG5zID0gdGhpcy5uYW1lc3BhY2U7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAxKSByZXR1cm4gdGhpcy5ub2RlKClbbnNdW2lkXS5lYXNlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwiZnVuY3Rpb25cIikgdmFsdWUgPSBkMy5lYXNlLmFwcGx5KGQzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCBmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlW25zXVtpZF0uZWFzZSA9IHZhbHVlO1xuICAgIH0pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmRlbGF5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMSkgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0uZGVsYXk7XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbl9lYWNoKHRoaXMsIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgbm9kZVtuc11baWRdLmRlbGF5ID0gK3ZhbHVlLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaik7XG4gICAgfSA6ICh2YWx1ZSA9ICt2YWx1ZSwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLmRlbGF5ID0gdmFsdWU7XG4gICAgfSkpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmR1cmF0aW9uID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMSkgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0uZHVyYXRpb247XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbl9lYWNoKHRoaXMsIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgbm9kZVtuc11baWRdLmR1cmF0aW9uID0gTWF0aC5tYXgoMSwgdmFsdWUuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSk7XG4gICAgfSA6ICh2YWx1ZSA9IE1hdGgubWF4KDEsIHZhbHVlKSwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLmR1cmF0aW9uID0gdmFsdWU7XG4gICAgfSkpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmVhY2ggPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICAgIHZhciBpZCA9IHRoaXMuaWQsIG5zID0gdGhpcy5uYW1lc3BhY2U7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICB2YXIgaW5oZXJpdCA9IGQzX3RyYW5zaXRpb25Jbmhlcml0LCBpbmhlcml0SWQgPSBkM190cmFuc2l0aW9uSW5oZXJpdElkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXRJZCA9IGlkO1xuICAgICAgICBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCBmdW5jdGlvbihub2RlLCBpLCBqKSB7XG4gICAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXQgPSBub2RlW25zXVtpZF07XG4gICAgICAgICAgdHlwZS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopO1xuICAgICAgICB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGQzX3RyYW5zaXRpb25Jbmhlcml0ID0gaW5oZXJpdDtcbiAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXRJZCA9IGluaGVyaXRJZDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IG5vZGVbbnNdW2lkXTtcbiAgICAgICAgKHRyYW5zaXRpb24uZXZlbnQgfHwgKHRyYW5zaXRpb24uZXZlbnQgPSBkMy5kaXNwYXRjaChcInN0YXJ0XCIsIFwiZW5kXCIsIFwiaW50ZXJydXB0XCIpKSkub24odHlwZSwgbGlzdGVuZXIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnRyYW5zaXRpb24gPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaWQwID0gdGhpcy5pZCwgaWQxID0gKytkM190cmFuc2l0aW9uSWQsIG5zID0gdGhpcy5uYW1lc3BhY2UsIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgZ3JvdXAsIG5vZGUsIHRyYW5zaXRpb247XG4gICAgZm9yICh2YXIgaiA9IDAsIG0gPSB0aGlzLmxlbmd0aDsgaiA8IG07IGorKykge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSAwLCBuID0gZ3JvdXAubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgICB0cmFuc2l0aW9uID0gbm9kZVtuc11baWQwXTtcbiAgICAgICAgICBkM190cmFuc2l0aW9uTm9kZShub2RlLCBpLCBucywgaWQxLCB7XG4gICAgICAgICAgICB0aW1lOiB0cmFuc2l0aW9uLnRpbWUsXG4gICAgICAgICAgICBlYXNlOiB0cmFuc2l0aW9uLmVhc2UsXG4gICAgICAgICAgICBkZWxheTogdHJhbnNpdGlvbi5kZWxheSArIHRyYW5zaXRpb24uZHVyYXRpb24sXG4gICAgICAgICAgICBkdXJhdGlvbjogdHJhbnNpdGlvbi5kdXJhdGlvblxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHN1Ymdyb3VwLnB1c2gobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgbnMsIGlkMSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb25OYW1lc3BhY2UobmFtZSkge1xuICAgIHJldHVybiBuYW1lID09IG51bGwgPyBcIl9fdHJhbnNpdGlvbl9fXCIgOiBcIl9fdHJhbnNpdGlvbl9cIiArIG5hbWUgKyBcIl9fXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdHJhbnNpdGlvbk5vZGUobm9kZSwgaSwgbnMsIGlkLCBpbmhlcml0KSB7XG4gICAgdmFyIGxvY2sgPSBub2RlW25zXSB8fCAobm9kZVtuc10gPSB7XG4gICAgICBhY3RpdmU6IDAsXG4gICAgICBjb3VudDogMFxuICAgIH0pLCB0cmFuc2l0aW9uID0gbG9ja1tpZF0sIHRpbWUsIHRpbWVyLCBkdXJhdGlvbiwgZWFzZSwgdHdlZW5zO1xuICAgIGZ1bmN0aW9uIHNjaGVkdWxlKGVsYXBzZWQpIHtcbiAgICAgIHZhciBkZWxheSA9IHRyYW5zaXRpb24uZGVsYXk7XG4gICAgICB0aW1lci50ID0gZGVsYXkgKyB0aW1lO1xuICAgICAgaWYgKGRlbGF5IDw9IGVsYXBzZWQpIHJldHVybiBzdGFydChlbGFwc2VkIC0gZGVsYXkpO1xuICAgICAgdGltZXIuYyA9IHN0YXJ0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdGFydChlbGFwc2VkKSB7XG4gICAgICB2YXIgYWN0aXZlSWQgPSBsb2NrLmFjdGl2ZSwgYWN0aXZlID0gbG9ja1thY3RpdmVJZF07XG4gICAgICBpZiAoYWN0aXZlKSB7XG4gICAgICAgIGFjdGl2ZS50aW1lci5jID0gbnVsbDtcbiAgICAgICAgYWN0aXZlLnRpbWVyLnQgPSBOYU47XG4gICAgICAgIC0tbG9jay5jb3VudDtcbiAgICAgICAgZGVsZXRlIGxvY2tbYWN0aXZlSWRdO1xuICAgICAgICBhY3RpdmUuZXZlbnQgJiYgYWN0aXZlLmV2ZW50LmludGVycnVwdC5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGFjdGl2ZS5pbmRleCk7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBjYW5jZWxJZCBpbiBsb2NrKSB7XG4gICAgICAgIGlmICgrY2FuY2VsSWQgPCBpZCkge1xuICAgICAgICAgIHZhciBjYW5jZWwgPSBsb2NrW2NhbmNlbElkXTtcbiAgICAgICAgICBjYW5jZWwudGltZXIuYyA9IG51bGw7XG4gICAgICAgICAgY2FuY2VsLnRpbWVyLnQgPSBOYU47XG4gICAgICAgICAgLS1sb2NrLmNvdW50O1xuICAgICAgICAgIGRlbGV0ZSBsb2NrW2NhbmNlbElkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGltZXIuYyA9IHRpY2s7XG4gICAgICBkM190aW1lcihmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRpbWVyLmMgJiYgdGljayhlbGFwc2VkIHx8IDEpKSB7XG4gICAgICAgICAgdGltZXIuYyA9IG51bGw7XG4gICAgICAgICAgdGltZXIudCA9IE5hTjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0sIDAsIHRpbWUpO1xuICAgICAgbG9jay5hY3RpdmUgPSBpZDtcbiAgICAgIHRyYW5zaXRpb24uZXZlbnQgJiYgdHJhbnNpdGlvbi5ldmVudC5zdGFydC5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpO1xuICAgICAgdHdlZW5zID0gW107XG4gICAgICB0cmFuc2l0aW9uLnR3ZWVuLmZvckVhY2goZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgPSB2YWx1ZS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpKSB7XG4gICAgICAgICAgdHdlZW5zLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGVhc2UgPSB0cmFuc2l0aW9uLmVhc2U7XG4gICAgICBkdXJhdGlvbiA9IHRyYW5zaXRpb24uZHVyYXRpb247XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRpY2soZWxhcHNlZCkge1xuICAgICAgdmFyIHQgPSBlbGFwc2VkIC8gZHVyYXRpb24sIGUgPSBlYXNlKHQpLCBuID0gdHdlZW5zLmxlbmd0aDtcbiAgICAgIHdoaWxlIChuID4gMCkge1xuICAgICAgICB0d2VlbnNbLS1uXS5jYWxsKG5vZGUsIGUpO1xuICAgICAgfVxuICAgICAgaWYgKHQgPj0gMSkge1xuICAgICAgICB0cmFuc2l0aW9uLmV2ZW50ICYmIHRyYW5zaXRpb24uZXZlbnQuZW5kLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSk7XG4gICAgICAgIGlmICgtLWxvY2suY291bnQpIGRlbGV0ZSBsb2NrW2lkXTsgZWxzZSBkZWxldGUgbm9kZVtuc107XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXRyYW5zaXRpb24pIHtcbiAgICAgIHRpbWUgPSBpbmhlcml0LnRpbWU7XG4gICAgICB0aW1lciA9IGQzX3RpbWVyKHNjaGVkdWxlLCAwLCB0aW1lKTtcbiAgICAgIHRyYW5zaXRpb24gPSBsb2NrW2lkXSA9IHtcbiAgICAgICAgdHdlZW46IG5ldyBkM19NYXAoKSxcbiAgICAgICAgdGltZTogdGltZSxcbiAgICAgICAgdGltZXI6IHRpbWVyLFxuICAgICAgICBkZWxheTogaW5oZXJpdC5kZWxheSxcbiAgICAgICAgZHVyYXRpb246IGluaGVyaXQuZHVyYXRpb24sXG4gICAgICAgIGVhc2U6IGluaGVyaXQuZWFzZSxcbiAgICAgICAgaW5kZXg6IGlcbiAgICAgIH07XG4gICAgICBpbmhlcml0ID0gbnVsbDtcbiAgICAgICsrbG9jay5jb3VudDtcbiAgICB9XG4gIH1cbiAgZDMuc3ZnLmF4aXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2NhbGUgPSBkMy5zY2FsZS5saW5lYXIoKSwgb3JpZW50ID0gZDNfc3ZnX2F4aXNEZWZhdWx0T3JpZW50LCBpbm5lclRpY2tTaXplID0gNiwgb3V0ZXJUaWNrU2l6ZSA9IDYsIHRpY2tQYWRkaW5nID0gMywgdGlja0FyZ3VtZW50c18gPSBbIDEwIF0sIHRpY2tWYWx1ZXMgPSBudWxsLCB0aWNrRm9ybWF0XztcbiAgICBmdW5jdGlvbiBheGlzKGcpIHtcbiAgICAgIGcuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGcgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBzY2FsZTAgPSB0aGlzLl9fY2hhcnRfXyB8fCBzY2FsZSwgc2NhbGUxID0gdGhpcy5fX2NoYXJ0X18gPSBzY2FsZS5jb3B5KCk7XG4gICAgICAgIHZhciB0aWNrcyA9IHRpY2tWYWx1ZXMgPT0gbnVsbCA/IHNjYWxlMS50aWNrcyA/IHNjYWxlMS50aWNrcy5hcHBseShzY2FsZTEsIHRpY2tBcmd1bWVudHNfKSA6IHNjYWxlMS5kb21haW4oKSA6IHRpY2tWYWx1ZXMsIHRpY2tGb3JtYXQgPSB0aWNrRm9ybWF0XyA9PSBudWxsID8gc2NhbGUxLnRpY2tGb3JtYXQgPyBzY2FsZTEudGlja0Zvcm1hdC5hcHBseShzY2FsZTEsIHRpY2tBcmd1bWVudHNfKSA6IGQzX2lkZW50aXR5IDogdGlja0Zvcm1hdF8sIHRpY2sgPSBnLnNlbGVjdEFsbChcIi50aWNrXCIpLmRhdGEodGlja3MsIHNjYWxlMSksIHRpY2tFbnRlciA9IHRpY2suZW50ZXIoKS5pbnNlcnQoXCJnXCIsIFwiLmRvbWFpblwiKS5hdHRyKFwiY2xhc3NcIiwgXCJ0aWNrXCIpLnN0eWxlKFwib3BhY2l0eVwiLCDOtSksIHRpY2tFeGl0ID0gZDMudHJhbnNpdGlvbih0aWNrLmV4aXQoKSkuc3R5bGUoXCJvcGFjaXR5XCIsIM61KS5yZW1vdmUoKSwgdGlja1VwZGF0ZSA9IGQzLnRyYW5zaXRpb24odGljay5vcmRlcigpKS5zdHlsZShcIm9wYWNpdHlcIiwgMSksIHRpY2tTcGFjaW5nID0gTWF0aC5tYXgoaW5uZXJUaWNrU2l6ZSwgMCkgKyB0aWNrUGFkZGluZywgdGlja1RyYW5zZm9ybTtcbiAgICAgICAgdmFyIHJhbmdlID0gZDNfc2NhbGVSYW5nZShzY2FsZTEpLCBwYXRoID0gZy5zZWxlY3RBbGwoXCIuZG9tYWluXCIpLmRhdGEoWyAwIF0pLCBwYXRoVXBkYXRlID0gKHBhdGguZW50ZXIoKS5hcHBlbmQoXCJwYXRoXCIpLmF0dHIoXCJjbGFzc1wiLCBcImRvbWFpblwiKSwgXG4gICAgICAgIGQzLnRyYW5zaXRpb24ocGF0aCkpO1xuICAgICAgICB0aWNrRW50ZXIuYXBwZW5kKFwibGluZVwiKTtcbiAgICAgICAgdGlja0VudGVyLmFwcGVuZChcInRleHRcIik7XG4gICAgICAgIHZhciBsaW5lRW50ZXIgPSB0aWNrRW50ZXIuc2VsZWN0KFwibGluZVwiKSwgbGluZVVwZGF0ZSA9IHRpY2tVcGRhdGUuc2VsZWN0KFwibGluZVwiKSwgdGV4dCA9IHRpY2suc2VsZWN0KFwidGV4dFwiKS50ZXh0KHRpY2tGb3JtYXQpLCB0ZXh0RW50ZXIgPSB0aWNrRW50ZXIuc2VsZWN0KFwidGV4dFwiKSwgdGV4dFVwZGF0ZSA9IHRpY2tVcGRhdGUuc2VsZWN0KFwidGV4dFwiKSwgc2lnbiA9IG9yaWVudCA9PT0gXCJ0b3BcIiB8fCBvcmllbnQgPT09IFwibGVmdFwiID8gLTEgOiAxLCB4MSwgeDIsIHkxLCB5MjtcbiAgICAgICAgaWYgKG9yaWVudCA9PT0gXCJib3R0b21cIiB8fCBvcmllbnQgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICB0aWNrVHJhbnNmb3JtID0gZDNfc3ZnX2F4aXNYLCB4MSA9IFwieFwiLCB5MSA9IFwieVwiLCB4MiA9IFwieDJcIiwgeTIgPSBcInkyXCI7XG4gICAgICAgICAgdGV4dC5hdHRyKFwiZHlcIiwgc2lnbiA8IDAgPyBcIjBlbVwiIDogXCIuNzFlbVwiKS5zdHlsZShcInRleHQtYW5jaG9yXCIsIFwibWlkZGxlXCIpO1xuICAgICAgICAgIHBhdGhVcGRhdGUuYXR0cihcImRcIiwgXCJNXCIgKyByYW5nZVswXSArIFwiLFwiICsgc2lnbiAqIG91dGVyVGlja1NpemUgKyBcIlYwSFwiICsgcmFuZ2VbMV0gKyBcIlZcIiArIHNpZ24gKiBvdXRlclRpY2tTaXplKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aWNrVHJhbnNmb3JtID0gZDNfc3ZnX2F4aXNZLCB4MSA9IFwieVwiLCB5MSA9IFwieFwiLCB4MiA9IFwieTJcIiwgeTIgPSBcIngyXCI7XG4gICAgICAgICAgdGV4dC5hdHRyKFwiZHlcIiwgXCIuMzJlbVwiKS5zdHlsZShcInRleHQtYW5jaG9yXCIsIHNpZ24gPCAwID8gXCJlbmRcIiA6IFwic3RhcnRcIik7XG4gICAgICAgICAgcGF0aFVwZGF0ZS5hdHRyKFwiZFwiLCBcIk1cIiArIHNpZ24gKiBvdXRlclRpY2tTaXplICsgXCIsXCIgKyByYW5nZVswXSArIFwiSDBWXCIgKyByYW5nZVsxXSArIFwiSFwiICsgc2lnbiAqIG91dGVyVGlja1NpemUpO1xuICAgICAgICB9XG4gICAgICAgIGxpbmVFbnRlci5hdHRyKHkyLCBzaWduICogaW5uZXJUaWNrU2l6ZSk7XG4gICAgICAgIHRleHRFbnRlci5hdHRyKHkxLCBzaWduICogdGlja1NwYWNpbmcpO1xuICAgICAgICBsaW5lVXBkYXRlLmF0dHIoeDIsIDApLmF0dHIoeTIsIHNpZ24gKiBpbm5lclRpY2tTaXplKTtcbiAgICAgICAgdGV4dFVwZGF0ZS5hdHRyKHgxLCAwKS5hdHRyKHkxLCBzaWduICogdGlja1NwYWNpbmcpO1xuICAgICAgICBpZiAoc2NhbGUxLnJhbmdlQmFuZCkge1xuICAgICAgICAgIHZhciB4ID0gc2NhbGUxLCBkeCA9IHgucmFuZ2VCYW5kKCkgLyAyO1xuICAgICAgICAgIHNjYWxlMCA9IHNjYWxlMSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiB4KGQpICsgZHg7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChzY2FsZTAucmFuZ2VCYW5kKSB7XG4gICAgICAgICAgc2NhbGUwID0gc2NhbGUxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRpY2tFeGl0LmNhbGwodGlja1RyYW5zZm9ybSwgc2NhbGUxLCBzY2FsZTApO1xuICAgICAgICB9XG4gICAgICAgIHRpY2tFbnRlci5jYWxsKHRpY2tUcmFuc2Zvcm0sIHNjYWxlMCwgc2NhbGUxKTtcbiAgICAgICAgdGlja1VwZGF0ZS5jYWxsKHRpY2tUcmFuc2Zvcm0sIHNjYWxlMSwgc2NhbGUxKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBheGlzLnNjYWxlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2NhbGU7XG4gICAgICBzY2FsZSA9IHg7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMub3JpZW50ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb3JpZW50O1xuICAgICAgb3JpZW50ID0geCBpbiBkM19zdmdfYXhpc09yaWVudHMgPyB4ICsgXCJcIiA6IGQzX3N2Z19heGlzRGVmYXVsdE9yaWVudDtcbiAgICAgIHJldHVybiBheGlzO1xuICAgIH07XG4gICAgYXhpcy50aWNrcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja0FyZ3VtZW50c187XG4gICAgICB0aWNrQXJndW1lbnRzXyA9IGQzX2FycmF5KGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMudGlja1ZhbHVlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRpY2tWYWx1ZXM7XG4gICAgICB0aWNrVmFsdWVzID0geDtcbiAgICAgIHJldHVybiBheGlzO1xuICAgIH07XG4gICAgYXhpcy50aWNrRm9ybWF0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja0Zvcm1hdF87XG4gICAgICB0aWNrRm9ybWF0XyA9IHg7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMudGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICBpZiAoIW4pIHJldHVybiBpbm5lclRpY2tTaXplO1xuICAgICAgaW5uZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgb3V0ZXJUaWNrU2l6ZSA9ICthcmd1bWVudHNbbiAtIDFdO1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLmlubmVyVGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBpbm5lclRpY2tTaXplO1xuICAgICAgaW5uZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLm91dGVyVGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvdXRlclRpY2tTaXplO1xuICAgICAgb3V0ZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLnRpY2tQYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja1BhZGRpbmc7XG4gICAgICB0aWNrUGFkZGluZyA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLnRpY2tTdWJkaXZpZGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoICYmIGF4aXM7XG4gICAgfTtcbiAgICByZXR1cm4gYXhpcztcbiAgfTtcbiAgdmFyIGQzX3N2Z19heGlzRGVmYXVsdE9yaWVudCA9IFwiYm90dG9tXCIsIGQzX3N2Z19heGlzT3JpZW50cyA9IHtcbiAgICB0b3A6IDEsXG4gICAgcmlnaHQ6IDEsXG4gICAgYm90dG9tOiAxLFxuICAgIGxlZnQ6IDFcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2F4aXNYKHNlbGVjdGlvbiwgeDAsIHgxKSB7XG4gICAgc2VsZWN0aW9uLmF0dHIoXCJ0cmFuc2Zvcm1cIiwgZnVuY3Rpb24oZCkge1xuICAgICAgdmFyIHYwID0geDAoZCk7XG4gICAgICByZXR1cm4gXCJ0cmFuc2xhdGUoXCIgKyAoaXNGaW5pdGUodjApID8gdjAgOiB4MShkKSkgKyBcIiwwKVwiO1xuICAgIH0pO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19heGlzWShzZWxlY3Rpb24sIHkwLCB5MSkge1xuICAgIHNlbGVjdGlvbi5hdHRyKFwidHJhbnNmb3JtXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICAgIHZhciB2MCA9IHkwKGQpO1xuICAgICAgcmV0dXJuIFwidHJhbnNsYXRlKDAsXCIgKyAoaXNGaW5pdGUodjApID8gdjAgOiB5MShkKSkgKyBcIilcIjtcbiAgICB9KTtcbiAgfVxuICBkMy5zdmcuYnJ1c2ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKGJydXNoLCBcImJydXNoc3RhcnRcIiwgXCJicnVzaFwiLCBcImJydXNoZW5kXCIpLCB4ID0gbnVsbCwgeSA9IG51bGwsIHhFeHRlbnQgPSBbIDAsIDAgXSwgeUV4dGVudCA9IFsgMCwgMCBdLCB4RXh0ZW50RG9tYWluLCB5RXh0ZW50RG9tYWluLCB4Q2xhbXAgPSB0cnVlLCB5Q2xhbXAgPSB0cnVlLCByZXNpemVzID0gZDNfc3ZnX2JydXNoUmVzaXplc1swXTtcbiAgICBmdW5jdGlvbiBicnVzaChnKSB7XG4gICAgICBnLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnID0gZDMuc2VsZWN0KHRoaXMpLnN0eWxlKFwicG9pbnRlci1ldmVudHNcIiwgXCJhbGxcIikuc3R5bGUoXCItd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3JcIiwgXCJyZ2JhKDAsMCwwLDApXCIpLm9uKFwibW91c2Vkb3duLmJydXNoXCIsIGJydXNoc3RhcnQpLm9uKFwidG91Y2hzdGFydC5icnVzaFwiLCBicnVzaHN0YXJ0KTtcbiAgICAgICAgdmFyIGJhY2tncm91bmQgPSBnLnNlbGVjdEFsbChcIi5iYWNrZ3JvdW5kXCIpLmRhdGEoWyAwIF0pO1xuICAgICAgICBiYWNrZ3JvdW5kLmVudGVyKCkuYXBwZW5kKFwicmVjdFwiKS5hdHRyKFwiY2xhc3NcIiwgXCJiYWNrZ3JvdW5kXCIpLnN0eWxlKFwidmlzaWJpbGl0eVwiLCBcImhpZGRlblwiKS5zdHlsZShcImN1cnNvclwiLCBcImNyb3NzaGFpclwiKTtcbiAgICAgICAgZy5zZWxlY3RBbGwoXCIuZXh0ZW50XCIpLmRhdGEoWyAwIF0pLmVudGVyKCkuYXBwZW5kKFwicmVjdFwiKS5hdHRyKFwiY2xhc3NcIiwgXCJleHRlbnRcIikuc3R5bGUoXCJjdXJzb3JcIiwgXCJtb3ZlXCIpO1xuICAgICAgICB2YXIgcmVzaXplID0gZy5zZWxlY3RBbGwoXCIucmVzaXplXCIpLmRhdGEocmVzaXplcywgZDNfaWRlbnRpdHkpO1xuICAgICAgICByZXNpemUuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICByZXNpemUuZW50ZXIoKS5hcHBlbmQoXCJnXCIpLmF0dHIoXCJjbGFzc1wiLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgcmV0dXJuIFwicmVzaXplIFwiICsgZDtcbiAgICAgICAgfSkuc3R5bGUoXCJjdXJzb3JcIiwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIHJldHVybiBkM19zdmdfYnJ1c2hDdXJzb3JbZF07XG4gICAgICAgIH0pLmFwcGVuZChcInJlY3RcIikuYXR0cihcInhcIiwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIHJldHVybiAvW2V3XSQvLnRlc3QoZCkgPyAtMyA6IG51bGw7XG4gICAgICAgIH0pLmF0dHIoXCJ5XCIsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICByZXR1cm4gL15bbnNdLy50ZXN0KGQpID8gLTMgOiBudWxsO1xuICAgICAgICB9KS5hdHRyKFwid2lkdGhcIiwgNikuYXR0cihcImhlaWdodFwiLCA2KS5zdHlsZShcInZpc2liaWxpdHlcIiwgXCJoaWRkZW5cIik7XG4gICAgICAgIHJlc2l6ZS5zdHlsZShcImRpc3BsYXlcIiwgYnJ1c2guZW1wdHkoKSA/IFwibm9uZVwiIDogbnVsbCk7XG4gICAgICAgIHZhciBnVXBkYXRlID0gZDMudHJhbnNpdGlvbihnKSwgYmFja2dyb3VuZFVwZGF0ZSA9IGQzLnRyYW5zaXRpb24oYmFja2dyb3VuZCksIHJhbmdlO1xuICAgICAgICBpZiAoeCkge1xuICAgICAgICAgIHJhbmdlID0gZDNfc2NhbGVSYW5nZSh4KTtcbiAgICAgICAgICBiYWNrZ3JvdW5kVXBkYXRlLmF0dHIoXCJ4XCIsIHJhbmdlWzBdKS5hdHRyKFwid2lkdGhcIiwgcmFuZ2VbMV0gLSByYW5nZVswXSk7XG4gICAgICAgICAgcmVkcmF3WChnVXBkYXRlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeSkge1xuICAgICAgICAgIHJhbmdlID0gZDNfc2NhbGVSYW5nZSh5KTtcbiAgICAgICAgICBiYWNrZ3JvdW5kVXBkYXRlLmF0dHIoXCJ5XCIsIHJhbmdlWzBdKS5hdHRyKFwiaGVpZ2h0XCIsIHJhbmdlWzFdIC0gcmFuZ2VbMF0pO1xuICAgICAgICAgIHJlZHJhd1koZ1VwZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVkcmF3KGdVcGRhdGUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGJydXNoLmV2ZW50ID0gZnVuY3Rpb24oZykge1xuICAgICAgZy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZXZlbnRfID0gZXZlbnQub2YodGhpcywgYXJndW1lbnRzKSwgZXh0ZW50MSA9IHtcbiAgICAgICAgICB4OiB4RXh0ZW50LFxuICAgICAgICAgIHk6IHlFeHRlbnQsXG4gICAgICAgICAgaTogeEV4dGVudERvbWFpbixcbiAgICAgICAgICBqOiB5RXh0ZW50RG9tYWluXG4gICAgICAgIH0sIGV4dGVudDAgPSB0aGlzLl9fY2hhcnRfXyB8fCBleHRlbnQxO1xuICAgICAgICB0aGlzLl9fY2hhcnRfXyA9IGV4dGVudDE7XG4gICAgICAgIGlmIChkM190cmFuc2l0aW9uSW5oZXJpdElkKSB7XG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5lYWNoKFwic3RhcnQuYnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB4RXh0ZW50RG9tYWluID0gZXh0ZW50MC5pO1xuICAgICAgICAgICAgeUV4dGVudERvbWFpbiA9IGV4dGVudDAuajtcbiAgICAgICAgICAgIHhFeHRlbnQgPSBleHRlbnQwLng7XG4gICAgICAgICAgICB5RXh0ZW50ID0gZXh0ZW50MC55O1xuICAgICAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJicnVzaHN0YXJ0XCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pLnR3ZWVuKFwiYnJ1c2g6YnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgeGkgPSBkM19pbnRlcnBvbGF0ZUFycmF5KHhFeHRlbnQsIGV4dGVudDEueCksIHlpID0gZDNfaW50ZXJwb2xhdGVBcnJheSh5RXh0ZW50LCBleHRlbnQxLnkpO1xuICAgICAgICAgICAgeEV4dGVudERvbWFpbiA9IHlFeHRlbnREb21haW4gPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgeEV4dGVudCA9IGV4dGVudDEueCA9IHhpKHQpO1xuICAgICAgICAgICAgICB5RXh0ZW50ID0gZXh0ZW50MS55ID0geWkodCk7XG4gICAgICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJicnVzaFwiLFxuICAgICAgICAgICAgICAgIG1vZGU6IFwicmVzaXplXCJcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pLmVhY2goXCJlbmQuYnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB4RXh0ZW50RG9tYWluID0gZXh0ZW50MS5pO1xuICAgICAgICAgICAgeUV4dGVudERvbWFpbiA9IGV4dGVudDEuajtcbiAgICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICAgIHR5cGU6IFwiYnJ1c2hcIixcbiAgICAgICAgICAgICAgbW9kZTogXCJyZXNpemVcIlxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBldmVudF8oe1xuICAgICAgICAgICAgICB0eXBlOiBcImJydXNoZW5kXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICB0eXBlOiBcImJydXNoc3RhcnRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICB0eXBlOiBcImJydXNoXCIsXG4gICAgICAgICAgICBtb2RlOiBcInJlc2l6ZVwiXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICAgIHR5cGU6IFwiYnJ1c2hlbmRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJlZHJhdyhnKSB7XG4gICAgICBnLnNlbGVjdEFsbChcIi5yZXNpemVcIikuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBcInRyYW5zbGF0ZShcIiArIHhFeHRlbnRbKy9lJC8udGVzdChkKV0gKyBcIixcIiArIHlFeHRlbnRbKy9ecy8udGVzdChkKV0gKyBcIilcIjtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZWRyYXdYKGcpIHtcbiAgICAgIGcuc2VsZWN0KFwiLmV4dGVudFwiKS5hdHRyKFwieFwiLCB4RXh0ZW50WzBdKTtcbiAgICAgIGcuc2VsZWN0QWxsKFwiLmV4dGVudCwubj5yZWN0LC5zPnJlY3RcIikuYXR0cihcIndpZHRoXCIsIHhFeHRlbnRbMV0gLSB4RXh0ZW50WzBdKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVkcmF3WShnKSB7XG4gICAgICBnLnNlbGVjdChcIi5leHRlbnRcIikuYXR0cihcInlcIiwgeUV4dGVudFswXSk7XG4gICAgICBnLnNlbGVjdEFsbChcIi5leHRlbnQsLmU+cmVjdCwudz5yZWN0XCIpLmF0dHIoXCJoZWlnaHRcIiwgeUV4dGVudFsxXSAtIHlFeHRlbnRbMF0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBicnVzaHN0YXJ0KCkge1xuICAgICAgdmFyIHRhcmdldCA9IHRoaXMsIGV2ZW50VGFyZ2V0ID0gZDMuc2VsZWN0KGQzLmV2ZW50LnRhcmdldCksIGV2ZW50XyA9IGV2ZW50Lm9mKHRhcmdldCwgYXJndW1lbnRzKSwgZyA9IGQzLnNlbGVjdCh0YXJnZXQpLCByZXNpemluZyA9IGV2ZW50VGFyZ2V0LmRhdHVtKCksIHJlc2l6aW5nWCA9ICEvXihufHMpJC8udGVzdChyZXNpemluZykgJiYgeCwgcmVzaXppbmdZID0gIS9eKGV8dykkLy50ZXN0KHJlc2l6aW5nKSAmJiB5LCBkcmFnZ2luZyA9IGV2ZW50VGFyZ2V0LmNsYXNzZWQoXCJleHRlbnRcIiksIGRyYWdSZXN0b3JlID0gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKHRhcmdldCksIGNlbnRlciwgb3JpZ2luID0gZDMubW91c2UodGFyZ2V0KSwgb2Zmc2V0O1xuICAgICAgdmFyIHcgPSBkMy5zZWxlY3QoZDNfd2luZG93KHRhcmdldCkpLm9uKFwia2V5ZG93bi5icnVzaFwiLCBrZXlkb3duKS5vbihcImtleXVwLmJydXNoXCIsIGtleXVwKTtcbiAgICAgIGlmIChkMy5ldmVudC5jaGFuZ2VkVG91Y2hlcykge1xuICAgICAgICB3Lm9uKFwidG91Y2htb3ZlLmJydXNoXCIsIGJydXNobW92ZSkub24oXCJ0b3VjaGVuZC5icnVzaFwiLCBicnVzaGVuZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3Lm9uKFwibW91c2Vtb3ZlLmJydXNoXCIsIGJydXNobW92ZSkub24oXCJtb3VzZXVwLmJydXNoXCIsIGJydXNoZW5kKTtcbiAgICAgIH1cbiAgICAgIGcuaW50ZXJydXB0KCkuc2VsZWN0QWxsKFwiKlwiKS5pbnRlcnJ1cHQoKTtcbiAgICAgIGlmIChkcmFnZ2luZykge1xuICAgICAgICBvcmlnaW5bMF0gPSB4RXh0ZW50WzBdIC0gb3JpZ2luWzBdO1xuICAgICAgICBvcmlnaW5bMV0gPSB5RXh0ZW50WzBdIC0gb3JpZ2luWzFdO1xuICAgICAgfSBlbHNlIGlmIChyZXNpemluZykge1xuICAgICAgICB2YXIgZXggPSArL3ckLy50ZXN0KHJlc2l6aW5nKSwgZXkgPSArL15uLy50ZXN0KHJlc2l6aW5nKTtcbiAgICAgICAgb2Zmc2V0ID0gWyB4RXh0ZW50WzEgLSBleF0gLSBvcmlnaW5bMF0sIHlFeHRlbnRbMSAtIGV5XSAtIG9yaWdpblsxXSBdO1xuICAgICAgICBvcmlnaW5bMF0gPSB4RXh0ZW50W2V4XTtcbiAgICAgICAgb3JpZ2luWzFdID0geUV4dGVudFtleV07XG4gICAgICB9IGVsc2UgaWYgKGQzLmV2ZW50LmFsdEtleSkgY2VudGVyID0gb3JpZ2luLnNsaWNlKCk7XG4gICAgICBnLnN0eWxlKFwicG9pbnRlci1ldmVudHNcIiwgXCJub25lXCIpLnNlbGVjdEFsbChcIi5yZXNpemVcIikuc3R5bGUoXCJkaXNwbGF5XCIsIG51bGwpO1xuICAgICAgZDMuc2VsZWN0KFwiYm9keVwiKS5zdHlsZShcImN1cnNvclwiLCBldmVudFRhcmdldC5zdHlsZShcImN1cnNvclwiKSk7XG4gICAgICBldmVudF8oe1xuICAgICAgICB0eXBlOiBcImJydXNoc3RhcnRcIlxuICAgICAgfSk7XG4gICAgICBicnVzaG1vdmUoKTtcbiAgICAgIGZ1bmN0aW9uIGtleWRvd24oKSB7XG4gICAgICAgIGlmIChkMy5ldmVudC5rZXlDb2RlID09IDMyKSB7XG4gICAgICAgICAgaWYgKCFkcmFnZ2luZykge1xuICAgICAgICAgICAgY2VudGVyID0gbnVsbDtcbiAgICAgICAgICAgIG9yaWdpblswXSAtPSB4RXh0ZW50WzFdO1xuICAgICAgICAgICAgb3JpZ2luWzFdIC09IHlFeHRlbnRbMV07XG4gICAgICAgICAgICBkcmFnZ2luZyA9IDI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGQzX2V2ZW50UHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZnVuY3Rpb24ga2V5dXAoKSB7XG4gICAgICAgIGlmIChkMy5ldmVudC5rZXlDb2RlID09IDMyICYmIGRyYWdnaW5nID09IDIpIHtcbiAgICAgICAgICBvcmlnaW5bMF0gKz0geEV4dGVudFsxXTtcbiAgICAgICAgICBvcmlnaW5bMV0gKz0geUV4dGVudFsxXTtcbiAgICAgICAgICBkcmFnZ2luZyA9IDA7XG4gICAgICAgICAgZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBicnVzaG1vdmUoKSB7XG4gICAgICAgIHZhciBwb2ludCA9IGQzLm1vdXNlKHRhcmdldCksIG1vdmVkID0gZmFsc2U7XG4gICAgICAgIGlmIChvZmZzZXQpIHtcbiAgICAgICAgICBwb2ludFswXSArPSBvZmZzZXRbMF07XG4gICAgICAgICAgcG9pbnRbMV0gKz0gb2Zmc2V0WzFdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZHJhZ2dpbmcpIHtcbiAgICAgICAgICBpZiAoZDMuZXZlbnQuYWx0S2V5KSB7XG4gICAgICAgICAgICBpZiAoIWNlbnRlcikgY2VudGVyID0gWyAoeEV4dGVudFswXSArIHhFeHRlbnRbMV0pIC8gMiwgKHlFeHRlbnRbMF0gKyB5RXh0ZW50WzFdKSAvIDIgXTtcbiAgICAgICAgICAgIG9yaWdpblswXSA9IHhFeHRlbnRbKyhwb2ludFswXSA8IGNlbnRlclswXSldO1xuICAgICAgICAgICAgb3JpZ2luWzFdID0geUV4dGVudFsrKHBvaW50WzFdIDwgY2VudGVyWzFdKV07XG4gICAgICAgICAgfSBlbHNlIGNlbnRlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc2l6aW5nWCAmJiBtb3ZlMShwb2ludCwgeCwgMCkpIHtcbiAgICAgICAgICByZWRyYXdYKGcpO1xuICAgICAgICAgIG1vdmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzaXppbmdZICYmIG1vdmUxKHBvaW50LCB5LCAxKSkge1xuICAgICAgICAgIHJlZHJhd1koZyk7XG4gICAgICAgICAgbW92ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb3ZlZCkge1xuICAgICAgICAgIHJlZHJhdyhnKTtcbiAgICAgICAgICBldmVudF8oe1xuICAgICAgICAgICAgdHlwZTogXCJicnVzaFwiLFxuICAgICAgICAgICAgbW9kZTogZHJhZ2dpbmcgPyBcIm1vdmVcIiA6IFwicmVzaXplXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbW92ZTEocG9pbnQsIHNjYWxlLCBpKSB7XG4gICAgICAgIHZhciByYW5nZSA9IGQzX3NjYWxlUmFuZ2Uoc2NhbGUpLCByMCA9IHJhbmdlWzBdLCByMSA9IHJhbmdlWzFdLCBwb3NpdGlvbiA9IG9yaWdpbltpXSwgZXh0ZW50ID0gaSA/IHlFeHRlbnQgOiB4RXh0ZW50LCBzaXplID0gZXh0ZW50WzFdIC0gZXh0ZW50WzBdLCBtaW4sIG1heDtcbiAgICAgICAgaWYgKGRyYWdnaW5nKSB7XG4gICAgICAgICAgcjAgLT0gcG9zaXRpb247XG4gICAgICAgICAgcjEgLT0gc2l6ZSArIHBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIG1pbiA9IChpID8geUNsYW1wIDogeENsYW1wKSA/IE1hdGgubWF4KHIwLCBNYXRoLm1pbihyMSwgcG9pbnRbaV0pKSA6IHBvaW50W2ldO1xuICAgICAgICBpZiAoZHJhZ2dpbmcpIHtcbiAgICAgICAgICBtYXggPSAobWluICs9IHBvc2l0aW9uKSArIHNpemU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGNlbnRlcikgcG9zaXRpb24gPSBNYXRoLm1heChyMCwgTWF0aC5taW4ocjEsIDIgKiBjZW50ZXJbaV0gLSBtaW4pKTtcbiAgICAgICAgICBpZiAocG9zaXRpb24gPCBtaW4pIHtcbiAgICAgICAgICAgIG1heCA9IG1pbjtcbiAgICAgICAgICAgIG1pbiA9IHBvc2l0aW9uO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXggPSBwb3NpdGlvbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4dGVudFswXSAhPSBtaW4gfHwgZXh0ZW50WzFdICE9IG1heCkge1xuICAgICAgICAgIGlmIChpKSB5RXh0ZW50RG9tYWluID0gbnVsbDsgZWxzZSB4RXh0ZW50RG9tYWluID0gbnVsbDtcbiAgICAgICAgICBleHRlbnRbMF0gPSBtaW47XG4gICAgICAgICAgZXh0ZW50WzFdID0gbWF4O1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBicnVzaGVuZCgpIHtcbiAgICAgICAgYnJ1c2htb3ZlKCk7XG4gICAgICAgIGcuc3R5bGUoXCJwb2ludGVyLWV2ZW50c1wiLCBcImFsbFwiKS5zZWxlY3RBbGwoXCIucmVzaXplXCIpLnN0eWxlKFwiZGlzcGxheVwiLCBicnVzaC5lbXB0eSgpID8gXCJub25lXCIgOiBudWxsKTtcbiAgICAgICAgZDMuc2VsZWN0KFwiYm9keVwiKS5zdHlsZShcImN1cnNvclwiLCBudWxsKTtcbiAgICAgICAgdy5vbihcIm1vdXNlbW92ZS5icnVzaFwiLCBudWxsKS5vbihcIm1vdXNldXAuYnJ1c2hcIiwgbnVsbCkub24oXCJ0b3VjaG1vdmUuYnJ1c2hcIiwgbnVsbCkub24oXCJ0b3VjaGVuZC5icnVzaFwiLCBudWxsKS5vbihcImtleWRvd24uYnJ1c2hcIiwgbnVsbCkub24oXCJrZXl1cC5icnVzaFwiLCBudWxsKTtcbiAgICAgICAgZHJhZ1Jlc3RvcmUoKTtcbiAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICB0eXBlOiBcImJydXNoZW5kXCJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGJydXNoLnggPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB4O1xuICAgICAgeCA9IHo7XG4gICAgICByZXNpemVzID0gZDNfc3ZnX2JydXNoUmVzaXplc1sheCA8PCAxIHwgIXldO1xuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2gueSA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHk7XG4gICAgICB5ID0gejtcbiAgICAgIHJlc2l6ZXMgPSBkM19zdmdfYnJ1c2hSZXNpemVzWyF4IDw8IDEgfCAheV07XG4gICAgICByZXR1cm4gYnJ1c2g7XG4gICAgfTtcbiAgICBicnVzaC5jbGFtcCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHggJiYgeSA/IFsgeENsYW1wLCB5Q2xhbXAgXSA6IHggPyB4Q2xhbXAgOiB5ID8geUNsYW1wIDogbnVsbDtcbiAgICAgIGlmICh4ICYmIHkpIHhDbGFtcCA9ICEhelswXSwgeUNsYW1wID0gISF6WzFdOyBlbHNlIGlmICh4KSB4Q2xhbXAgPSAhIXo7IGVsc2UgaWYgKHkpIHlDbGFtcCA9ICEhejtcbiAgICAgIHJldHVybiBicnVzaDtcbiAgICB9O1xuICAgIGJydXNoLmV4dGVudCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIHZhciB4MCwgeDEsIHkwLCB5MSwgdDtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBpZiAoeCkge1xuICAgICAgICAgIGlmICh4RXh0ZW50RG9tYWluKSB7XG4gICAgICAgICAgICB4MCA9IHhFeHRlbnREb21haW5bMF0sIHgxID0geEV4dGVudERvbWFpblsxXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeDAgPSB4RXh0ZW50WzBdLCB4MSA9IHhFeHRlbnRbMV07XG4gICAgICAgICAgICBpZiAoeC5pbnZlcnQpIHgwID0geC5pbnZlcnQoeDApLCB4MSA9IHguaW52ZXJ0KHgxKTtcbiAgICAgICAgICAgIGlmICh4MSA8IHgwKSB0ID0geDAsIHgwID0geDEsIHgxID0gdDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHkpIHtcbiAgICAgICAgICBpZiAoeUV4dGVudERvbWFpbikge1xuICAgICAgICAgICAgeTAgPSB5RXh0ZW50RG9tYWluWzBdLCB5MSA9IHlFeHRlbnREb21haW5bMV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHkwID0geUV4dGVudFswXSwgeTEgPSB5RXh0ZW50WzFdO1xuICAgICAgICAgICAgaWYgKHkuaW52ZXJ0KSB5MCA9IHkuaW52ZXJ0KHkwKSwgeTEgPSB5LmludmVydCh5MSk7XG4gICAgICAgICAgICBpZiAoeTEgPCB5MCkgdCA9IHkwLCB5MCA9IHkxLCB5MSA9IHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB4ICYmIHkgPyBbIFsgeDAsIHkwIF0sIFsgeDEsIHkxIF0gXSA6IHggPyBbIHgwLCB4MSBdIDogeSAmJiBbIHkwLCB5MSBdO1xuICAgICAgfVxuICAgICAgaWYgKHgpIHtcbiAgICAgICAgeDAgPSB6WzBdLCB4MSA9IHpbMV07XG4gICAgICAgIGlmICh5KSB4MCA9IHgwWzBdLCB4MSA9IHgxWzBdO1xuICAgICAgICB4RXh0ZW50RG9tYWluID0gWyB4MCwgeDEgXTtcbiAgICAgICAgaWYgKHguaW52ZXJ0KSB4MCA9IHgoeDApLCB4MSA9IHgoeDEpO1xuICAgICAgICBpZiAoeDEgPCB4MCkgdCA9IHgwLCB4MCA9IHgxLCB4MSA9IHQ7XG4gICAgICAgIGlmICh4MCAhPSB4RXh0ZW50WzBdIHx8IHgxICE9IHhFeHRlbnRbMV0pIHhFeHRlbnQgPSBbIHgwLCB4MSBdO1xuICAgICAgfVxuICAgICAgaWYgKHkpIHtcbiAgICAgICAgeTAgPSB6WzBdLCB5MSA9IHpbMV07XG4gICAgICAgIGlmICh4KSB5MCA9IHkwWzFdLCB5MSA9IHkxWzFdO1xuICAgICAgICB5RXh0ZW50RG9tYWluID0gWyB5MCwgeTEgXTtcbiAgICAgICAgaWYgKHkuaW52ZXJ0KSB5MCA9IHkoeTApLCB5MSA9IHkoeTEpO1xuICAgICAgICBpZiAoeTEgPCB5MCkgdCA9IHkwLCB5MCA9IHkxLCB5MSA9IHQ7XG4gICAgICAgIGlmICh5MCAhPSB5RXh0ZW50WzBdIHx8IHkxICE9IHlFeHRlbnRbMV0pIHlFeHRlbnQgPSBbIHkwLCB5MSBdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2guY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghYnJ1c2guZW1wdHkoKSkge1xuICAgICAgICB4RXh0ZW50ID0gWyAwLCAwIF0sIHlFeHRlbnQgPSBbIDAsIDAgXTtcbiAgICAgICAgeEV4dGVudERvbWFpbiA9IHlFeHRlbnREb21haW4gPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2guZW1wdHkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhIXggJiYgeEV4dGVudFswXSA9PSB4RXh0ZW50WzFdIHx8ICEheSAmJiB5RXh0ZW50WzBdID09IHlFeHRlbnRbMV07XG4gICAgfTtcbiAgICByZXR1cm4gZDMucmViaW5kKGJydXNoLCBldmVudCwgXCJvblwiKTtcbiAgfTtcbiAgdmFyIGQzX3N2Z19icnVzaEN1cnNvciA9IHtcbiAgICBuOiBcIm5zLXJlc2l6ZVwiLFxuICAgIGU6IFwiZXctcmVzaXplXCIsXG4gICAgczogXCJucy1yZXNpemVcIixcbiAgICB3OiBcImV3LXJlc2l6ZVwiLFxuICAgIG53OiBcIm53c2UtcmVzaXplXCIsXG4gICAgbmU6IFwibmVzdy1yZXNpemVcIixcbiAgICBzZTogXCJud3NlLXJlc2l6ZVwiLFxuICAgIHN3OiBcIm5lc3ctcmVzaXplXCJcbiAgfTtcbiAgdmFyIGQzX3N2Z19icnVzaFJlc2l6ZXMgPSBbIFsgXCJuXCIsIFwiZVwiLCBcInNcIiwgXCJ3XCIsIFwibndcIiwgXCJuZVwiLCBcInNlXCIsIFwic3dcIiBdLCBbIFwiZVwiLCBcIndcIiBdLCBbIFwiblwiLCBcInNcIiBdLCBbXSBdO1xuICB2YXIgZDNfdGltZV9mb3JtYXQgPSBkM190aW1lLmZvcm1hdCA9IGQzX2xvY2FsZV9lblVTLnRpbWVGb3JtYXQ7XG4gIHZhciBkM190aW1lX2Zvcm1hdFV0YyA9IGQzX3RpbWVfZm9ybWF0LnV0YztcbiAgdmFyIGQzX3RpbWVfZm9ybWF0SXNvID0gZDNfdGltZV9mb3JtYXRVdGMoXCIlWS0lbS0lZFQlSDolTTolUy4lTFpcIik7XG4gIGQzX3RpbWVfZm9ybWF0LmlzbyA9IERhdGUucHJvdG90eXBlLnRvSVNPU3RyaW5nICYmICtuZXcgRGF0ZShcIjIwMDAtMDEtMDFUMDA6MDA6MDAuMDAwWlwiKSA/IGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlIDogZDNfdGltZV9mb3JtYXRJc287XG4gIGZ1bmN0aW9uIGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlKGRhdGUpIHtcbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG4gIGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlLnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShzdHJpbmcpO1xuICAgIHJldHVybiBpc05hTihkYXRlKSA/IG51bGwgOiBkYXRlO1xuICB9O1xuICBkM190aW1lX2Zvcm1hdElzb05hdGl2ZS50b1N0cmluZyA9IGQzX3RpbWVfZm9ybWF0SXNvLnRvU3RyaW5nO1xuICBkM190aW1lLnNlY29uZCA9IGQzX3RpbWVfaW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBuZXcgZDNfZGF0ZShNYXRoLmZsb29yKGRhdGUgLyAxZTMpICogMWUzKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogMWUzKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBkYXRlLmdldFNlY29uZHMoKTtcbiAgfSk7XG4gIGQzX3RpbWUuc2Vjb25kcyA9IGQzX3RpbWUuc2Vjb25kLnJhbmdlO1xuICBkM190aW1lLnNlY29uZHMudXRjID0gZDNfdGltZS5zZWNvbmQudXRjLnJhbmdlO1xuICBkM190aW1lLm1pbnV0ZSA9IGQzX3RpbWVfaW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBuZXcgZDNfZGF0ZShNYXRoLmZsb29yKGRhdGUgLyA2ZTQpICogNmU0KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogNmU0KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBkYXRlLmdldE1pbnV0ZXMoKTtcbiAgfSk7XG4gIGQzX3RpbWUubWludXRlcyA9IGQzX3RpbWUubWludXRlLnJhbmdlO1xuICBkM190aW1lLm1pbnV0ZXMudXRjID0gZDNfdGltZS5taW51dGUudXRjLnJhbmdlO1xuICBkM190aW1lLmhvdXIgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgdGltZXpvbmUgPSBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkgLyA2MDtcbiAgICByZXR1cm4gbmV3IGQzX2RhdGUoKE1hdGguZmxvb3IoZGF0ZSAvIDM2ZTUgLSB0aW1lem9uZSkgKyB0aW1lem9uZSkgKiAzNmU1KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogMzZlNSk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgICByZXR1cm4gZGF0ZS5nZXRIb3VycygpO1xuICB9KTtcbiAgZDNfdGltZS5ob3VycyA9IGQzX3RpbWUuaG91ci5yYW5nZTtcbiAgZDNfdGltZS5ob3Vycy51dGMgPSBkM190aW1lLmhvdXIudXRjLnJhbmdlO1xuICBkM190aW1lLm1vbnRoID0gZDNfdGltZV9pbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZSA9IGQzX3RpbWUuZGF5KGRhdGUpO1xuICAgIGRhdGUuc2V0RGF0ZSgxKTtcbiAgICByZXR1cm4gZGF0ZTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRNb250aChkYXRlLmdldE1vbnRoKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0TW9udGgoKTtcbiAgfSk7XG4gIGQzX3RpbWUubW9udGhzID0gZDNfdGltZS5tb250aC5yYW5nZTtcbiAgZDNfdGltZS5tb250aHMudXRjID0gZDNfdGltZS5tb250aC51dGMucmFuZ2U7XG4gIGZ1bmN0aW9uIGQzX3RpbWVfc2NhbGUobGluZWFyLCBtZXRob2RzLCBmb3JtYXQpIHtcbiAgICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgICByZXR1cm4gbGluZWFyKHgpO1xuICAgIH1cbiAgICBzY2FsZS5pbnZlcnQgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9zY2FsZURhdGUobGluZWFyLmludmVydCh4KSk7XG4gICAgfTtcbiAgICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5lYXIuZG9tYWluKCkubWFwKGQzX3RpbWVfc2NhbGVEYXRlKTtcbiAgICAgIGxpbmVhci5kb21haW4oeCk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBmdW5jdGlvbiB0aWNrTWV0aG9kKGV4dGVudCwgY291bnQpIHtcbiAgICAgIHZhciBzcGFuID0gZXh0ZW50WzFdIC0gZXh0ZW50WzBdLCB0YXJnZXQgPSBzcGFuIC8gY291bnQsIGkgPSBkMy5iaXNlY3QoZDNfdGltZV9zY2FsZVN0ZXBzLCB0YXJnZXQpO1xuICAgICAgcmV0dXJuIGkgPT0gZDNfdGltZV9zY2FsZVN0ZXBzLmxlbmd0aCA/IFsgbWV0aG9kcy55ZWFyLCBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZXh0ZW50Lm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkIC8gMzE1MzZlNjtcbiAgICAgIH0pLCBjb3VudClbMl0gXSA6ICFpID8gWyBkM190aW1lX3NjYWxlTWlsbGlzZWNvbmRzLCBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZXh0ZW50LCBjb3VudClbMl0gXSA6IG1ldGhvZHNbdGFyZ2V0IC8gZDNfdGltZV9zY2FsZVN0ZXBzW2kgLSAxXSA8IGQzX3RpbWVfc2NhbGVTdGVwc1tpXSAvIHRhcmdldCA/IGkgLSAxIDogaV07XG4gICAgfVxuICAgIHNjYWxlLm5pY2UgPSBmdW5jdGlvbihpbnRlcnZhbCwgc2tpcCkge1xuICAgICAgdmFyIGRvbWFpbiA9IHNjYWxlLmRvbWFpbigpLCBleHRlbnQgPSBkM19zY2FsZUV4dGVudChkb21haW4pLCBtZXRob2QgPSBpbnRlcnZhbCA9PSBudWxsID8gdGlja01ldGhvZChleHRlbnQsIDEwKSA6IHR5cGVvZiBpbnRlcnZhbCA9PT0gXCJudW1iZXJcIiAmJiB0aWNrTWV0aG9kKGV4dGVudCwgaW50ZXJ2YWwpO1xuICAgICAgaWYgKG1ldGhvZCkgaW50ZXJ2YWwgPSBtZXRob2RbMF0sIHNraXAgPSBtZXRob2RbMV07XG4gICAgICBmdW5jdGlvbiBza2lwcGVkKGRhdGUpIHtcbiAgICAgICAgcmV0dXJuICFpc05hTihkYXRlKSAmJiAhaW50ZXJ2YWwucmFuZ2UoZGF0ZSwgZDNfdGltZV9zY2FsZURhdGUoK2RhdGUgKyAxKSwgc2tpcCkubGVuZ3RoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjYWxlLmRvbWFpbihkM19zY2FsZV9uaWNlKGRvbWFpbiwgc2tpcCA+IDEgPyB7XG4gICAgICAgIGZsb29yOiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgd2hpbGUgKHNraXBwZWQoZGF0ZSA9IGludGVydmFsLmZsb29yKGRhdGUpKSkgZGF0ZSA9IGQzX3RpbWVfc2NhbGVEYXRlKGRhdGUgLSAxKTtcbiAgICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICAgICAgfSxcbiAgICAgICAgY2VpbDogZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgICAgIHdoaWxlIChza2lwcGVkKGRhdGUgPSBpbnRlcnZhbC5jZWlsKGRhdGUpKSkgZGF0ZSA9IGQzX3RpbWVfc2NhbGVEYXRlKCtkYXRlICsgMSk7XG4gICAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgICAgIH1cbiAgICAgIH0gOiBpbnRlcnZhbCkpO1xuICAgIH07XG4gICAgc2NhbGUudGlja3MgPSBmdW5jdGlvbihpbnRlcnZhbCwgc2tpcCkge1xuICAgICAgdmFyIGV4dGVudCA9IGQzX3NjYWxlRXh0ZW50KHNjYWxlLmRvbWFpbigpKSwgbWV0aG9kID0gaW50ZXJ2YWwgPT0gbnVsbCA/IHRpY2tNZXRob2QoZXh0ZW50LCAxMCkgOiB0eXBlb2YgaW50ZXJ2YWwgPT09IFwibnVtYmVyXCIgPyB0aWNrTWV0aG9kKGV4dGVudCwgaW50ZXJ2YWwpIDogIWludGVydmFsLnJhbmdlICYmIFsge1xuICAgICAgICByYW5nZTogaW50ZXJ2YWxcbiAgICAgIH0sIHNraXAgXTtcbiAgICAgIGlmIChtZXRob2QpIGludGVydmFsID0gbWV0aG9kWzBdLCBza2lwID0gbWV0aG9kWzFdO1xuICAgICAgcmV0dXJuIGludGVydmFsLnJhbmdlKGV4dGVudFswXSwgZDNfdGltZV9zY2FsZURhdGUoK2V4dGVudFsxXSArIDEpLCBza2lwIDwgMSA/IDEgOiBza2lwKTtcbiAgICB9O1xuICAgIHNjYWxlLnRpY2tGb3JtYXQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9zY2FsZShsaW5lYXIuY29weSgpLCBtZXRob2RzLCBmb3JtYXQpO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclJlYmluZChzY2FsZSwgbGluZWFyKTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3NjYWxlRGF0ZSh0KSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHQpO1xuICB9XG4gIHZhciBkM190aW1lX3NjYWxlU3RlcHMgPSBbIDFlMywgNWUzLCAxNWUzLCAzZTQsIDZlNCwgM2U1LCA5ZTUsIDE4ZTUsIDM2ZTUsIDEwOGU1LCAyMTZlNSwgNDMyZTUsIDg2NGU1LCAxNzI4ZTUsIDYwNDhlNSwgMjU5MmU2LCA3Nzc2ZTYsIDMxNTM2ZTYgXTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVMb2NhbE1ldGhvZHMgPSBbIFsgZDNfdGltZS5zZWNvbmQsIDEgXSwgWyBkM190aW1lLnNlY29uZCwgNSBdLCBbIGQzX3RpbWUuc2Vjb25kLCAxNSBdLCBbIGQzX3RpbWUuc2Vjb25kLCAzMCBdLCBbIGQzX3RpbWUubWludXRlLCAxIF0sIFsgZDNfdGltZS5taW51dGUsIDUgXSwgWyBkM190aW1lLm1pbnV0ZSwgMTUgXSwgWyBkM190aW1lLm1pbnV0ZSwgMzAgXSwgWyBkM190aW1lLmhvdXIsIDEgXSwgWyBkM190aW1lLmhvdXIsIDMgXSwgWyBkM190aW1lLmhvdXIsIDYgXSwgWyBkM190aW1lLmhvdXIsIDEyIF0sIFsgZDNfdGltZS5kYXksIDEgXSwgWyBkM190aW1lLmRheSwgMiBdLCBbIGQzX3RpbWUud2VlaywgMSBdLCBbIGQzX3RpbWUubW9udGgsIDEgXSwgWyBkM190aW1lLm1vbnRoLCAzIF0sIFsgZDNfdGltZS55ZWFyLCAxIF0gXTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVMb2NhbEZvcm1hdCA9IGQzX3RpbWVfZm9ybWF0Lm11bHRpKFsgWyBcIi4lTFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0TWlsbGlzZWNvbmRzKCk7XG4gIH0gXSwgWyBcIjolU1wiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0U2Vjb25kcygpO1xuICB9IF0sIFsgXCIlSTolTVwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0TWludXRlcygpO1xuICB9IF0sIFsgXCIlSSAlcFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0SG91cnMoKTtcbiAgfSBdLCBbIFwiJWEgJWRcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldERheSgpICYmIGQuZ2V0RGF0ZSgpICE9IDE7XG4gIH0gXSwgWyBcIiViICVkXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICByZXR1cm4gZC5nZXREYXRlKCkgIT0gMTtcbiAgfSBdLCBbIFwiJUJcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldE1vbnRoKCk7XG4gIH0gXSwgWyBcIiVZXCIsIGQzX3RydWUgXSBdKTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVNaWxsaXNlY29uZHMgPSB7XG4gICAgcmFuZ2U6IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoTWF0aC5jZWlsKHN0YXJ0IC8gc3RlcCkgKiBzdGVwLCArc3RvcCwgc3RlcCkubWFwKGQzX3RpbWVfc2NhbGVEYXRlKTtcbiAgICB9LFxuICAgIGZsb29yOiBkM19pZGVudGl0eSxcbiAgICBjZWlsOiBkM19pZGVudGl0eVxuICB9O1xuICBkM190aW1lX3NjYWxlTG9jYWxNZXRob2RzLnllYXIgPSBkM190aW1lLnllYXI7XG4gIGQzX3RpbWUuc2NhbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfdGltZV9zY2FsZShkMy5zY2FsZS5saW5lYXIoKSwgZDNfdGltZV9zY2FsZUxvY2FsTWV0aG9kcywgZDNfdGltZV9zY2FsZUxvY2FsRm9ybWF0KTtcbiAgfTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVVdGNNZXRob2RzID0gZDNfdGltZV9zY2FsZUxvY2FsTWV0aG9kcy5tYXAoZnVuY3Rpb24obSkge1xuICAgIHJldHVybiBbIG1bMF0udXRjLCBtWzFdIF07XG4gIH0pO1xuICB2YXIgZDNfdGltZV9zY2FsZVV0Y0Zvcm1hdCA9IGQzX3RpbWVfZm9ybWF0VXRjLm11bHRpKFsgWyBcIi4lTFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDTWlsbGlzZWNvbmRzKCk7XG4gIH0gXSwgWyBcIjolU1wiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDU2Vjb25kcygpO1xuICB9IF0sIFsgXCIlSTolTVwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDTWludXRlcygpO1xuICB9IF0sIFsgXCIlSSAlcFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDSG91cnMoKTtcbiAgfSBdLCBbIFwiJWEgJWRcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldFVUQ0RheSgpICYmIGQuZ2V0VVRDRGF0ZSgpICE9IDE7XG4gIH0gXSwgWyBcIiViICVkXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICByZXR1cm4gZC5nZXRVVENEYXRlKCkgIT0gMTtcbiAgfSBdLCBbIFwiJUJcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldFVUQ01vbnRoKCk7XG4gIH0gXSwgWyBcIiVZXCIsIGQzX3RydWUgXSBdKTtcbiAgZDNfdGltZV9zY2FsZVV0Y01ldGhvZHMueWVhciA9IGQzX3RpbWUueWVhci51dGM7XG4gIGQzX3RpbWUuc2NhbGUudXRjID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX3RpbWVfc2NhbGUoZDMuc2NhbGUubGluZWFyKCksIGQzX3RpbWVfc2NhbGVVdGNNZXRob2RzLCBkM190aW1lX3NjYWxlVXRjRm9ybWF0KTtcbiAgfTtcbiAgZDMudGV4dCA9IGQzX3hoclR5cGUoZnVuY3Rpb24ocmVxdWVzdCkge1xuICAgIHJldHVybiByZXF1ZXN0LnJlc3BvbnNlVGV4dDtcbiAgfSk7XG4gIGQzLmpzb24gPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGQzX3hocih1cmwsIFwiYXBwbGljYXRpb24vanNvblwiLCBkM19qc29uLCBjYWxsYmFjayk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2pzb24ocmVxdWVzdCkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgfVxuICBkMy5odG1sID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHJldHVybiBkM194aHIodXJsLCBcInRleHQvaHRtbFwiLCBkM19odG1sLCBjYWxsYmFjayk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2h0bWwocmVxdWVzdCkge1xuICAgIHZhciByYW5nZSA9IGQzX2RvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgcmFuZ2Uuc2VsZWN0Tm9kZShkM19kb2N1bWVudC5ib2R5KTtcbiAgICByZXR1cm4gcmFuZ2UuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgfVxuICBkMy54bWwgPSBkM194aHJUeXBlKGZ1bmN0aW9uKHJlcXVlc3QpIHtcbiAgICByZXR1cm4gcmVxdWVzdC5yZXNwb25zZVhNTDtcbiAgfSk7XG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgdGhpcy5kMyA9IGQzLCBkZWZpbmUoZDMpOyBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIG1vZHVsZS5leHBvcnRzKSBtb2R1bGUuZXhwb3J0cyA9IGQzOyBlbHNlIHRoaXMuZDMgPSBkMztcbn0oKTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYXJndW1lbnRzW2ldICE9PSB1bmRlZmluZWQpIHJldHVybiBhcmd1bWVudHNbaV07XG4gICAgfVxufTtcbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBjaCA9IHJlcXVpcmUoXCJpbmNyZW1lbnRhbC1jb252ZXgtaHVsbFwiKVxudmFyIHVuaXEgPSByZXF1aXJlKFwidW5pcVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRyaWFuZ3VsYXRlXG5cbmZ1bmN0aW9uIExpZnRlZFBvaW50KHAsIGkpIHtcbiAgdGhpcy5wb2ludCA9IHBcbiAgdGhpcy5pbmRleCA9IGlcbn1cblxuZnVuY3Rpb24gY29tcGFyZUxpZnRlZChhLCBiKSB7XG4gIHZhciBhcCA9IGEucG9pbnRcbiAgdmFyIGJwID0gYi5wb2ludFxuICB2YXIgZCA9IGFwLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICB2YXIgcyA9IGJwW2ldIC0gYXBbaV1cbiAgICBpZihzKSB7XG4gICAgICByZXR1cm4gc1xuICAgIH1cbiAgfVxuICByZXR1cm4gMFxufVxuXG5mdW5jdGlvbiB0cmlhbmd1bGF0ZTFEKG4sIHBvaW50cywgaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICBpZihuID09PSAxKSB7XG4gICAgaWYoaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICAgICAgcmV0dXJuIFsgWy0xLCAwXSBdXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBbXVxuICAgIH1cbiAgfVxuICB2YXIgbGlmdGVkID0gcG9pbnRzLm1hcChmdW5jdGlvbihwLCBpKSB7XG4gICAgcmV0dXJuIFsgcFswXSwgaSBdXG4gIH0pXG4gIGxpZnRlZC5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgIHJldHVybiBhWzBdIC0gYlswXVxuICB9KVxuICB2YXIgY2VsbHMgPSBuZXcgQXJyYXkobiAtIDEpXG4gIGZvcih2YXIgaT0xOyBpPG47ICsraSkge1xuICAgIHZhciBhID0gbGlmdGVkW2ktMV1cbiAgICB2YXIgYiA9IGxpZnRlZFtpXVxuICAgIGNlbGxzW2ktMV0gPSBbIGFbMV0sIGJbMV0gXVxuICB9XG4gIGlmKGluY2x1ZGVQb2ludEF0SW5maW5pdHkpIHtcbiAgICBjZWxscy5wdXNoKFxuICAgICAgWyAtMSwgY2VsbHNbMF1bMV0sIF0sXG4gICAgICBbIGNlbGxzW24tMV1bMV0sIC0xIF0pXG4gIH1cbiAgcmV0dXJuIGNlbGxzXG59XG5cbmZ1bmN0aW9uIHRyaWFuZ3VsYXRlKHBvaW50cywgaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcbiAgaWYobiA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIFxuICB2YXIgZCA9IHBvaW50c1swXS5sZW5ndGhcbiAgaWYoZCA8IDEpIHtcbiAgICByZXR1cm4gW11cbiAgfVxuXG4gIC8vU3BlY2lhbCBjYXNlOiAgRm9yIDFEIHdlIGNhbiBqdXN0IHNvcnQgdGhlIHBvaW50c1xuICBpZihkID09PSAxKSB7XG4gICAgcmV0dXJuIHRyaWFuZ3VsYXRlMUQobiwgcG9pbnRzLCBpbmNsdWRlUG9pbnRBdEluZmluaXR5KVxuICB9XG4gIFxuICAvL0xpZnQgcG9pbnRzLCBzb3J0XG4gIHZhciBsaWZ0ZWQgPSBuZXcgQXJyYXkobilcbiAgdmFyIHVwcGVyID0gMS4wXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBwID0gcG9pbnRzW2ldXG4gICAgdmFyIHggPSBuZXcgQXJyYXkoZCsxKVxuICAgIHZhciBsID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8ZDsgKytqKSB7XG4gICAgICB2YXIgdiA9IHBbal1cbiAgICAgIHhbal0gPSB2XG4gICAgICBsICs9IHYgKiB2XG4gICAgfVxuICAgIHhbZF0gPSBsXG4gICAgbGlmdGVkW2ldID0gbmV3IExpZnRlZFBvaW50KHgsIGkpXG4gICAgdXBwZXIgPSBNYXRoLm1heChsLCB1cHBlcilcbiAgfVxuICB1bmlxKGxpZnRlZCwgY29tcGFyZUxpZnRlZClcbiAgXG4gIC8vRG91YmxlIHBvaW50c1xuICBuID0gbGlmdGVkLmxlbmd0aFxuXG4gIC8vQ3JlYXRlIG5ldyBsaXN0IG9mIHBvaW50c1xuICB2YXIgZHBvaW50cyA9IG5ldyBBcnJheShuICsgZCArIDEpXG4gIHZhciBkaW5kZXggPSBuZXcgQXJyYXkobiArIGQgKyAxKVxuXG4gIC8vQWRkIHN0ZWluZXIgcG9pbnRzIGF0IHRvcFxuICB2YXIgdSA9IChkKzEpICogKGQrMSkgKiB1cHBlclxuICB2YXIgeSA9IG5ldyBBcnJheShkKzEpXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICB5W2ldID0gMC4wXG4gIH1cbiAgeVtkXSA9IHVcblxuICBkcG9pbnRzWzBdID0geS5zbGljZSgpXG4gIGRpbmRleFswXSA9IC0xXG5cbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIHZhciB4ID0geS5zbGljZSgpXG4gICAgeFtpXSA9IDFcbiAgICBkcG9pbnRzW2krMV0gPSB4XG4gICAgZGluZGV4W2krMV0gPSAtMVxuICB9XG5cbiAgLy9Db3B5IHJlc3Qgb2YgdGhlIHBvaW50cyBvdmVyXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBoID0gbGlmdGVkW2ldXG4gICAgZHBvaW50c1tpICsgZCArIDFdID0gaC5wb2ludFxuICAgIGRpbmRleFtpICsgZCArIDFdID0gIGguaW5kZXhcbiAgfVxuXG4gIC8vQ29uc3RydWN0IGNvbnZleCBodWxsXG4gIHZhciBodWxsID0gY2goZHBvaW50cywgZmFsc2UpXG4gIGlmKGluY2x1ZGVQb2ludEF0SW5maW5pdHkpIHtcbiAgICBodWxsID0gaHVsbC5maWx0ZXIoZnVuY3Rpb24oY2VsbCkge1xuICAgICAgdmFyIGNvdW50ID0gMFxuICAgICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgICB2YXIgdiA9IGRpbmRleFtjZWxsW2pdXVxuICAgICAgICBpZih2IDwgMCkge1xuICAgICAgICAgIGlmKCsrY291bnQgPj0gMikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNlbGxbal0gPSB2XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0pXG4gIH0gZWxzZSB7XG4gICAgaHVsbCA9IGh1bGwuZmlsdGVyKGZ1bmN0aW9uKGNlbGwpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICAgICAgdmFyIHYgPSBkaW5kZXhbY2VsbFtpXV1cbiAgICAgICAgaWYodiA8IDApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgICAgICBjZWxsW2ldID0gdlxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KVxuICB9XG5cbiAgaWYoZCAmIDEpIHtcbiAgICBmb3IodmFyIGk9MDsgaTxodWxsLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaCA9IGh1bGxbaV1cbiAgICAgIHZhciB4ID0gaFswXVxuICAgICAgaFswXSA9IGhbMV1cbiAgICAgIGhbMV0gPSB4XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGh1bGxcbn0iLCIndXNlIHN0cmljdCdcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGtlcm5pbmdcclxuXHJcblxyXG52YXIgY2FudmFzID0ga2VybmluZy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxyXG52YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJylcclxudmFyIGFzY2lpUGFpcnMgPSBjcmVhdGVQYWlycyhbMzIsIDEyNl0pXHJcblxyXG5rZXJuaW5nLmNyZWF0ZVBhaXJzID0gY3JlYXRlUGFpcnNcclxua2VybmluZy5hc2NpaSA9IGFzY2lpUGFpcnNcclxuXHJcblxyXG5mdW5jdGlvbiBrZXJuaW5nIChmYW1pbHksIG8pIHtcclxuXHRpZiAoQXJyYXkuaXNBcnJheShmYW1pbHkpKSBmYW1pbHkgPSBmYW1pbHkuam9pbignLCAnKVxyXG5cclxuXHR2YXIgdGFibGUgPSB7fSwgcGFpcnMsIGZzID0gMTYsIHRocmVzaG9sZCA9IC4wNVxyXG5cclxuXHRpZiAobykge1xyXG5cdFx0aWYgKG8ubGVuZ3RoID09PSAyICYmIHR5cGVvZiBvWzBdID09PSAnbnVtYmVyJykge1xyXG5cdFx0XHRwYWlycyA9IGNyZWF0ZVBhaXJzKG8pXHJcblx0XHR9XHJcblx0XHRlbHNlIGlmIChBcnJheS5pc0FycmF5KG8pKSB7XHJcblx0XHRcdHBhaXJzID0gb1xyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdGlmIChvLm8pIHBhaXJzID0gY3JlYXRlUGFpcnMoby5vKVxyXG5cdFx0XHRlbHNlIGlmIChvLnBhaXJzKSBwYWlycyA9IG8ucGFpcnNcclxuXHJcblx0XHRcdGlmIChvLmZvbnRTaXplKSBmcyA9IG8uZm9udFNpemVcclxuXHRcdFx0aWYgKG8udGhyZXNob2xkICE9IG51bGwpIHRocmVzaG9sZCA9IG8udGhyZXNob2xkXHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRpZiAoIXBhaXJzKSBwYWlycyA9IGFzY2lpUGFpcnNcclxuXHJcblx0Y3R4LmZvbnQgPSBmcyArICdweCAnICsgZmFtaWx5XHJcblxyXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgcGFpcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciBwYWlyID0gcGFpcnNbaV1cclxuXHRcdHZhciB3aWR0aCA9IGN0eC5tZWFzdXJlVGV4dChwYWlyWzBdKS53aWR0aCArIGN0eC5tZWFzdXJlVGV4dChwYWlyWzFdKS53aWR0aFxyXG5cdFx0dmFyIGtlcm5pbmdXaWR0aCA9IGN0eC5tZWFzdXJlVGV4dChwYWlyKS53aWR0aFxyXG5cdFx0aWYgKE1hdGguYWJzKHdpZHRoIC0ga2VybmluZ1dpZHRoKSA+IGZzICogdGhyZXNob2xkKSB7XHJcblx0XHRcdHZhciBlbVdpZHRoID0gKGtlcm5pbmdXaWR0aCAtIHdpZHRoKSAvIGZzXHJcblx0XHRcdHRhYmxlW3BhaXJdID0gZW1XaWR0aCAqIDEwMDBcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiB0YWJsZVxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gY3JlYXRlUGFpcnMgKHJhbmdlKSB7XHJcblx0dmFyIHBhaXJzID0gW11cclxuXHJcbiAgICBmb3IgKHZhciBpID0gcmFuZ2VbMF07IGkgPD0gcmFuZ2VbMV07IGkrKykge1xyXG5cdFx0dmFyIGxlZnRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShpKVxyXG5cdFx0Zm9yICh2YXIgaiA9IHJhbmdlWzBdOyBqIDwgcmFuZ2VbMV07IGorKykge1xyXG5cdFx0XHR2YXIgcmlnaHRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShqKVxyXG5cdFx0XHR2YXIgcGFpciA9IGxlZnRDaGFyICsgcmlnaHRDaGFyXHJcblxyXG5cdFx0XHRwYWlycy5wdXNoKHBhaXIpXHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gcGFpcnNcclxufVxyXG4iLCJ2YXIgaGFzVHlwZWRBcnJheXMgPSBmYWxzZVxuaWYodHlwZW9mIEZsb2F0NjRBcnJheSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICB2YXIgRE9VQkxFX1ZJRVcgPSBuZXcgRmxvYXQ2NEFycmF5KDEpXG4gICAgLCBVSU5UX1ZJRVcgICA9IG5ldyBVaW50MzJBcnJheShET1VCTEVfVklFVy5idWZmZXIpXG4gIERPVUJMRV9WSUVXWzBdID0gMS4wXG4gIGhhc1R5cGVkQXJyYXlzID0gdHJ1ZVxuICBpZihVSU5UX1ZJRVdbMV0gPT09IDB4M2ZmMDAwMDApIHtcbiAgICAvL1VzZSBsaXR0bGUgZW5kaWFuXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkb3VibGVCaXRzTEUobikge1xuICAgICAgRE9VQkxFX1ZJRVdbMF0gPSBuXG4gICAgICByZXR1cm4gWyBVSU5UX1ZJRVdbMF0sIFVJTlRfVklFV1sxXSBdXG4gICAgfVxuICAgIGZ1bmN0aW9uIHRvRG91YmxlTEUobG8sIGhpKSB7XG4gICAgICBVSU5UX1ZJRVdbMF0gPSBsb1xuICAgICAgVUlOVF9WSUVXWzFdID0gaGlcbiAgICAgIHJldHVybiBET1VCTEVfVklFV1swXVxuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0cy5wYWNrID0gdG9Eb3VibGVMRVxuICAgIGZ1bmN0aW9uIGxvd1VpbnRMRShuKSB7XG4gICAgICBET1VCTEVfVklFV1swXSA9IG5cbiAgICAgIHJldHVybiBVSU5UX1ZJRVdbMF1cbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHMubG8gPSBsb3dVaW50TEVcbiAgICBmdW5jdGlvbiBoaWdoVWludExFKG4pIHtcbiAgICAgIERPVUJMRV9WSUVXWzBdID0gblxuICAgICAgcmV0dXJuIFVJTlRfVklFV1sxXVxuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0cy5oaSA9IGhpZ2hVaW50TEVcbiAgfSBlbHNlIGlmKFVJTlRfVklFV1swXSA9PT0gMHgzZmYwMDAwMCkge1xuICAgIC8vVXNlIGJpZyBlbmRpYW5cbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRvdWJsZUJpdHNCRShuKSB7XG4gICAgICBET1VCTEVfVklFV1swXSA9IG5cbiAgICAgIHJldHVybiBbIFVJTlRfVklFV1sxXSwgVUlOVF9WSUVXWzBdIF1cbiAgICB9XG4gICAgZnVuY3Rpb24gdG9Eb3VibGVCRShsbywgaGkpIHtcbiAgICAgIFVJTlRfVklFV1sxXSA9IGxvXG4gICAgICBVSU5UX1ZJRVdbMF0gPSBoaVxuICAgICAgcmV0dXJuIERPVUJMRV9WSUVXWzBdXG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzLnBhY2sgPSB0b0RvdWJsZUJFXG4gICAgZnVuY3Rpb24gbG93VWludEJFKG4pIHtcbiAgICAgIERPVUJMRV9WSUVXWzBdID0gblxuICAgICAgcmV0dXJuIFVJTlRfVklFV1sxXVxuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0cy5sbyA9IGxvd1VpbnRCRVxuICAgIGZ1bmN0aW9uIGhpZ2hVaW50QkUobikge1xuICAgICAgRE9VQkxFX1ZJRVdbMF0gPSBuXG4gICAgICByZXR1cm4gVUlOVF9WSUVXWzBdXG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzLmhpID0gaGlnaFVpbnRCRVxuICB9IGVsc2Uge1xuICAgIGhhc1R5cGVkQXJyYXlzID0gZmFsc2VcbiAgfVxufVxuaWYoIWhhc1R5cGVkQXJyYXlzKSB7XG4gIHZhciBidWZmZXIgPSBuZXcgQnVmZmVyKDgpXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZG91YmxlQml0cyhuKSB7XG4gICAgYnVmZmVyLndyaXRlRG91YmxlTEUobiwgMCwgdHJ1ZSlcbiAgICByZXR1cm4gWyBidWZmZXIucmVhZFVJbnQzMkxFKDAsIHRydWUpLCBidWZmZXIucmVhZFVJbnQzMkxFKDQsIHRydWUpIF1cbiAgfVxuICBmdW5jdGlvbiB0b0RvdWJsZShsbywgaGkpIHtcbiAgICBidWZmZXIud3JpdGVVSW50MzJMRShsbywgMCwgdHJ1ZSlcbiAgICBidWZmZXIud3JpdGVVSW50MzJMRShoaSwgNCwgdHJ1ZSlcbiAgICByZXR1cm4gYnVmZmVyLnJlYWREb3VibGVMRSgwLCB0cnVlKVxuICB9XG4gIG1vZHVsZS5leHBvcnRzLnBhY2sgPSB0b0RvdWJsZSAgXG4gIGZ1bmN0aW9uIGxvd1VpbnQobikge1xuICAgIGJ1ZmZlci53cml0ZURvdWJsZUxFKG4sIDAsIHRydWUpXG4gICAgcmV0dXJuIGJ1ZmZlci5yZWFkVUludDMyTEUoMCwgdHJ1ZSlcbiAgfVxuICBtb2R1bGUuZXhwb3J0cy5sbyA9IGxvd1VpbnRcbiAgZnVuY3Rpb24gaGlnaFVpbnQobikge1xuICAgIGJ1ZmZlci53cml0ZURvdWJsZUxFKG4sIDAsIHRydWUpXG4gICAgcmV0dXJuIGJ1ZmZlci5yZWFkVUludDMyTEUoNCwgdHJ1ZSlcbiAgfVxuICBtb2R1bGUuZXhwb3J0cy5oaSA9IGhpZ2hVaW50XG59XG5cbm1vZHVsZS5leHBvcnRzLnNpZ24gPSBmdW5jdGlvbihuKSB7XG4gIHJldHVybiBtb2R1bGUuZXhwb3J0cy5oaShuKSA+Pj4gMzFcbn1cblxubW9kdWxlLmV4cG9ydHMuZXhwb25lbnQgPSBmdW5jdGlvbihuKSB7XG4gIHZhciBiID0gbW9kdWxlLmV4cG9ydHMuaGkobilcbiAgcmV0dXJuICgoYjw8MSkgPj4+IDIxKSAtIDEwMjNcbn1cblxubW9kdWxlLmV4cG9ydHMuZnJhY3Rpb24gPSBmdW5jdGlvbihuKSB7XG4gIHZhciBsbyA9IG1vZHVsZS5leHBvcnRzLmxvKG4pXG4gIHZhciBoaSA9IG1vZHVsZS5leHBvcnRzLmhpKG4pXG4gIHZhciBiID0gaGkgJiAoKDE8PDIwKSAtIDEpXG4gIGlmKGhpICYgMHg3ZmYwMDAwMCkge1xuICAgIGIgKz0gKDE8PDIwKVxuICB9XG4gIHJldHVybiBbbG8sIGJdXG59XG5cbm1vZHVsZS5leHBvcnRzLmRlbm9ybWFsaXplZCA9IGZ1bmN0aW9uKG4pIHtcbiAgdmFyIGhpID0gbW9kdWxlLmV4cG9ydHMuaGkobilcbiAgcmV0dXJuICEoaGkgJiAweDdmZjAwMDAwKVxufSIsInZhciBhYnMgPSByZXF1aXJlKCdhYnMtc3ZnLXBhdGgnKVxudmFyIG5vcm1hbGl6ZSA9IHJlcXVpcmUoJ25vcm1hbGl6ZS1zdmctcGF0aCcpXG5cbnZhciBtZXRob2RzID0ge1xuICAnTSc6ICdtb3ZlVG8nLFxuICAnQyc6ICdiZXppZXJDdXJ2ZVRvJ1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNvbnRleHQsIHNlZ21lbnRzKSB7XG4gIGNvbnRleHQuYmVnaW5QYXRoKClcblxuICAvLyBNYWtlIHBhdGggZWFzeSB0byByZXByb2R1Y2UuXG4gIG5vcm1hbGl6ZShhYnMoc2VnbWVudHMpKS5mb3JFYWNoKFxuICAgIGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgIHZhciBjb21tYW5kID0gc2VnbWVudFswXVxuICAgICAgdmFyIGFyZ3MgPSBzZWdtZW50LnNsaWNlKDEpXG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIHBhdGggY29tbWFuZCB0byBhIGNvbnRleHQgbWV0aG9kLlxuICAgICAgY29udGV4dFttZXRob2RzW2NvbW1hbmRdXS5hcHBseShjb250ZXh0LCBhcmdzKVxuICAgIH1cbiAgKVxuXG4gIGNvbnRleHQuY2xvc2VQYXRoKClcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZHR5cGUpIHtcbiAgc3dpdGNoIChkdHlwZSkge1xuICAgIGNhc2UgJ2ludDgnOlxuICAgICAgcmV0dXJuIEludDhBcnJheVxuICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgIHJldHVybiBJbnQxNkFycmF5XG4gICAgY2FzZSAnaW50MzInOlxuICAgICAgcmV0dXJuIEludDMyQXJyYXlcbiAgICBjYXNlICd1aW50OCc6XG4gICAgICByZXR1cm4gVWludDhBcnJheVxuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gVWludDE2QXJyYXlcbiAgICBjYXNlICd1aW50MzInOlxuICAgICAgcmV0dXJuIFVpbnQzMkFycmF5XG4gICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICByZXR1cm4gRmxvYXQzMkFycmF5XG4gICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICByZXR1cm4gRmxvYXQ2NEFycmF5XG4gICAgY2FzZSAnYXJyYXknOlxuICAgICAgcmV0dXJuIEFycmF5XG4gICAgY2FzZSAndWludDhfY2xhbXBlZCc6XG4gICAgICByZXR1cm4gVWludDhDbGFtcGVkQXJyYXlcbiAgfVxufVxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gZHVwZV9hcnJheShjb3VudCwgdmFsdWUsIGkpIHtcbiAgdmFyIGMgPSBjb3VudFtpXXwwXG4gIGlmKGMgPD0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoYyksIGpcbiAgaWYoaSA9PT0gY291bnQubGVuZ3RoLTEpIHtcbiAgICBmb3Ioaj0wOyBqPGM7ICsraikge1xuICAgICAgcmVzdWx0W2pdID0gdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZm9yKGo9MDsgajxjOyArK2opIHtcbiAgICAgIHJlc3VsdFtqXSA9IGR1cGVfYXJyYXkoY291bnQsIHZhbHVlLCBpKzEpXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gZHVwZV9udW1iZXIoY291bnQsIHZhbHVlKSB7XG4gIHZhciByZXN1bHQsIGlcbiAgcmVzdWx0ID0gbmV3IEFycmF5KGNvdW50KVxuICBmb3IoaT0wOyBpPGNvdW50OyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSB2YWx1ZVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gZHVwZShjb3VudCwgdmFsdWUpIHtcbiAgaWYodHlwZW9mIHZhbHVlID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgdmFsdWUgPSAwXG4gIH1cbiAgc3dpdGNoKHR5cGVvZiBjb3VudCkge1xuICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgIGlmKGNvdW50ID4gMCkge1xuICAgICAgICByZXR1cm4gZHVwZV9udW1iZXIoY291bnR8MCwgdmFsdWUpXG4gICAgICB9XG4gICAgYnJlYWtcbiAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICBpZih0eXBlb2YgKGNvdW50Lmxlbmd0aCkgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgcmV0dXJuIGR1cGVfYXJyYXkoY291bnQsIHZhbHVlLCAwKVxuICAgICAgfVxuICAgIGJyZWFrXG4gIH1cbiAgcmV0dXJuIFtdXG59XG5cbm1vZHVsZS5leHBvcnRzID0gZHVwZSIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBlYXJjdXQ7XG5tb2R1bGUuZXhwb3J0cy5kZWZhdWx0ID0gZWFyY3V0O1xuXG5mdW5jdGlvbiBlYXJjdXQoZGF0YSwgaG9sZUluZGljZXMsIGRpbSkge1xuXG4gICAgZGltID0gZGltIHx8IDI7XG5cbiAgICB2YXIgaGFzSG9sZXMgPSBob2xlSW5kaWNlcyAmJiBob2xlSW5kaWNlcy5sZW5ndGgsXG4gICAgICAgIG91dGVyTGVuID0gaGFzSG9sZXMgPyBob2xlSW5kaWNlc1swXSAqIGRpbSA6IGRhdGEubGVuZ3RoLFxuICAgICAgICBvdXRlck5vZGUgPSBsaW5rZWRMaXN0KGRhdGEsIDAsIG91dGVyTGVuLCBkaW0sIHRydWUpLFxuICAgICAgICB0cmlhbmdsZXMgPSBbXTtcblxuICAgIGlmICghb3V0ZXJOb2RlKSByZXR1cm4gdHJpYW5nbGVzO1xuXG4gICAgdmFyIG1pblgsIG1pblksIG1heFgsIG1heFksIHgsIHksIGludlNpemU7XG5cbiAgICBpZiAoaGFzSG9sZXMpIG91dGVyTm9kZSA9IGVsaW1pbmF0ZUhvbGVzKGRhdGEsIGhvbGVJbmRpY2VzLCBvdXRlck5vZGUsIGRpbSk7XG5cbiAgICAvLyBpZiB0aGUgc2hhcGUgaXMgbm90IHRvbyBzaW1wbGUsIHdlJ2xsIHVzZSB6LW9yZGVyIGN1cnZlIGhhc2ggbGF0ZXI7IGNhbGN1bGF0ZSBwb2x5Z29uIGJib3hcbiAgICBpZiAoZGF0YS5sZW5ndGggPiA4MCAqIGRpbSkge1xuICAgICAgICBtaW5YID0gbWF4WCA9IGRhdGFbMF07XG4gICAgICAgIG1pblkgPSBtYXhZID0gZGF0YVsxXTtcblxuICAgICAgICBmb3IgKHZhciBpID0gZGltOyBpIDwgb3V0ZXJMZW47IGkgKz0gZGltKSB7XG4gICAgICAgICAgICB4ID0gZGF0YVtpXTtcbiAgICAgICAgICAgIHkgPSBkYXRhW2kgKyAxXTtcbiAgICAgICAgICAgIGlmICh4IDwgbWluWCkgbWluWCA9IHg7XG4gICAgICAgICAgICBpZiAoeSA8IG1pblkpIG1pblkgPSB5O1xuICAgICAgICAgICAgaWYgKHggPiBtYXhYKSBtYXhYID0geDtcbiAgICAgICAgICAgIGlmICh5ID4gbWF4WSkgbWF4WSA9IHk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtaW5YLCBtaW5ZIGFuZCBpbnZTaXplIGFyZSBsYXRlciB1c2VkIHRvIHRyYW5zZm9ybSBjb29yZHMgaW50byBpbnRlZ2VycyBmb3Igei1vcmRlciBjYWxjdWxhdGlvblxuICAgICAgICBpbnZTaXplID0gTWF0aC5tYXgobWF4WCAtIG1pblgsIG1heFkgLSBtaW5ZKTtcbiAgICAgICAgaW52U2l6ZSA9IGludlNpemUgIT09IDAgPyAxIC8gaW52U2l6ZSA6IDA7XG4gICAgfVxuXG4gICAgZWFyY3V0TGlua2VkKG91dGVyTm9kZSwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpO1xuXG4gICAgcmV0dXJuIHRyaWFuZ2xlcztcbn1cblxuLy8gY3JlYXRlIGEgY2lyY3VsYXIgZG91Ymx5IGxpbmtlZCBsaXN0IGZyb20gcG9seWdvbiBwb2ludHMgaW4gdGhlIHNwZWNpZmllZCB3aW5kaW5nIG9yZGVyXG5mdW5jdGlvbiBsaW5rZWRMaXN0KGRhdGEsIHN0YXJ0LCBlbmQsIGRpbSwgY2xvY2t3aXNlKSB7XG4gICAgdmFyIGksIGxhc3Q7XG5cbiAgICBpZiAoY2xvY2t3aXNlID09PSAoc2lnbmVkQXJlYShkYXRhLCBzdGFydCwgZW5kLCBkaW0pID4gMCkpIHtcbiAgICAgICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gZGltKSBsYXN0ID0gaW5zZXJ0Tm9kZShpLCBkYXRhW2ldLCBkYXRhW2kgKyAxXSwgbGFzdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChpID0gZW5kIC0gZGltOyBpID49IHN0YXJ0OyBpIC09IGRpbSkgbGFzdCA9IGluc2VydE5vZGUoaSwgZGF0YVtpXSwgZGF0YVtpICsgMV0sIGxhc3QpO1xuICAgIH1cblxuICAgIGlmIChsYXN0ICYmIGVxdWFscyhsYXN0LCBsYXN0Lm5leHQpKSB7XG4gICAgICAgIHJlbW92ZU5vZGUobGFzdCk7XG4gICAgICAgIGxhc3QgPSBsYXN0Lm5leHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhc3Q7XG59XG5cbi8vIGVsaW1pbmF0ZSBjb2xpbmVhciBvciBkdXBsaWNhdGUgcG9pbnRzXG5mdW5jdGlvbiBmaWx0ZXJQb2ludHMoc3RhcnQsIGVuZCkge1xuICAgIGlmICghc3RhcnQpIHJldHVybiBzdGFydDtcbiAgICBpZiAoIWVuZCkgZW5kID0gc3RhcnQ7XG5cbiAgICB2YXIgcCA9IHN0YXJ0LFxuICAgICAgICBhZ2FpbjtcbiAgICBkbyB7XG4gICAgICAgIGFnYWluID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFwLnN0ZWluZXIgJiYgKGVxdWFscyhwLCBwLm5leHQpIHx8IGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID09PSAwKSkge1xuICAgICAgICAgICAgcmVtb3ZlTm9kZShwKTtcbiAgICAgICAgICAgIHAgPSBlbmQgPSBwLnByZXY7XG4gICAgICAgICAgICBpZiAocCA9PT0gcC5uZXh0KSBicmVhaztcbiAgICAgICAgICAgIGFnYWluID0gdHJ1ZTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcCA9IHAubmV4dDtcbiAgICAgICAgfVxuICAgIH0gd2hpbGUgKGFnYWluIHx8IHAgIT09IGVuZCk7XG5cbiAgICByZXR1cm4gZW5kO1xufVxuXG4vLyBtYWluIGVhciBzbGljaW5nIGxvb3Agd2hpY2ggdHJpYW5ndWxhdGVzIGEgcG9seWdvbiAoZ2l2ZW4gYXMgYSBsaW5rZWQgbGlzdClcbmZ1bmN0aW9uIGVhcmN1dExpbmtlZChlYXIsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCBwYXNzKSB7XG4gICAgaWYgKCFlYXIpIHJldHVybjtcblxuICAgIC8vIGludGVybGluayBwb2x5Z29uIG5vZGVzIGluIHotb3JkZXJcbiAgICBpZiAoIXBhc3MgJiYgaW52U2l6ZSkgaW5kZXhDdXJ2ZShlYXIsIG1pblgsIG1pblksIGludlNpemUpO1xuXG4gICAgdmFyIHN0b3AgPSBlYXIsXG4gICAgICAgIHByZXYsIG5leHQ7XG5cbiAgICAvLyBpdGVyYXRlIHRocm91Z2ggZWFycywgc2xpY2luZyB0aGVtIG9uZSBieSBvbmVcbiAgICB3aGlsZSAoZWFyLnByZXYgIT09IGVhci5uZXh0KSB7XG4gICAgICAgIHByZXYgPSBlYXIucHJldjtcbiAgICAgICAgbmV4dCA9IGVhci5uZXh0O1xuXG4gICAgICAgIGlmIChpbnZTaXplID8gaXNFYXJIYXNoZWQoZWFyLCBtaW5YLCBtaW5ZLCBpbnZTaXplKSA6IGlzRWFyKGVhcikpIHtcbiAgICAgICAgICAgIC8vIGN1dCBvZmYgdGhlIHRyaWFuZ2xlXG4gICAgICAgICAgICB0cmlhbmdsZXMucHVzaChwcmV2LmkgLyBkaW0pO1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goZWFyLmkgLyBkaW0pO1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2gobmV4dC5pIC8gZGltKTtcblxuICAgICAgICAgICAgcmVtb3ZlTm9kZShlYXIpO1xuXG4gICAgICAgICAgICAvLyBza2lwcGluZyB0aGUgbmV4dCB2ZXJ0aWNlIGxlYWRzIHRvIGxlc3Mgc2xpdmVyIHRyaWFuZ2xlc1xuICAgICAgICAgICAgZWFyID0gbmV4dC5uZXh0O1xuICAgICAgICAgICAgc3RvcCA9IG5leHQubmV4dDtcblxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBlYXIgPSBuZXh0O1xuXG4gICAgICAgIC8vIGlmIHdlIGxvb3BlZCB0aHJvdWdoIHRoZSB3aG9sZSByZW1haW5pbmcgcG9seWdvbiBhbmQgY2FuJ3QgZmluZCBhbnkgbW9yZSBlYXJzXG4gICAgICAgIGlmIChlYXIgPT09IHN0b3ApIHtcbiAgICAgICAgICAgIC8vIHRyeSBmaWx0ZXJpbmcgcG9pbnRzIGFuZCBzbGljaW5nIGFnYWluXG4gICAgICAgICAgICBpZiAoIXBhc3MpIHtcbiAgICAgICAgICAgICAgICBlYXJjdXRMaW5rZWQoZmlsdGVyUG9pbnRzKGVhciksIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCAxKTtcblxuICAgICAgICAgICAgLy8gaWYgdGhpcyBkaWRuJ3Qgd29yaywgdHJ5IGN1cmluZyBhbGwgc21hbGwgc2VsZi1pbnRlcnNlY3Rpb25zIGxvY2FsbHlcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFzcyA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGVhciA9IGN1cmVMb2NhbEludGVyc2VjdGlvbnMoZWFyLCB0cmlhbmdsZXMsIGRpbSk7XG4gICAgICAgICAgICAgICAgZWFyY3V0TGlua2VkKGVhciwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUsIDIpO1xuXG4gICAgICAgICAgICAvLyBhcyBhIGxhc3QgcmVzb3J0LCB0cnkgc3BsaXR0aW5nIHRoZSByZW1haW5pbmcgcG9seWdvbiBpbnRvIHR3b1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwYXNzID09PSAyKSB7XG4gICAgICAgICAgICAgICAgc3BsaXRFYXJjdXQoZWFyLCB0cmlhbmdsZXMsIGRpbSwgbWluWCwgbWluWSwgaW52U2l6ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBjaGVjayB3aGV0aGVyIGEgcG9seWdvbiBub2RlIGZvcm1zIGEgdmFsaWQgZWFyIHdpdGggYWRqYWNlbnQgbm9kZXNcbmZ1bmN0aW9uIGlzRWFyKGVhcikge1xuICAgIHZhciBhID0gZWFyLnByZXYsXG4gICAgICAgIGIgPSBlYXIsXG4gICAgICAgIGMgPSBlYXIubmV4dDtcblxuICAgIGlmIChhcmVhKGEsIGIsIGMpID49IDApIHJldHVybiBmYWxzZTsgLy8gcmVmbGV4LCBjYW4ndCBiZSBhbiBlYXJcblxuICAgIC8vIG5vdyBtYWtlIHN1cmUgd2UgZG9uJ3QgaGF2ZSBvdGhlciBwb2ludHMgaW5zaWRlIHRoZSBwb3RlbnRpYWwgZWFyXG4gICAgdmFyIHAgPSBlYXIubmV4dC5uZXh0O1xuXG4gICAgd2hpbGUgKHAgIT09IGVhci5wcmV2KSB7XG4gICAgICAgIGlmIChwb2ludEluVHJpYW5nbGUoYS54LCBhLnksIGIueCwgYi55LCBjLngsIGMueSwgcC54LCBwLnkpICYmXG4gICAgICAgICAgICBhcmVhKHAucHJldiwgcCwgcC5uZXh0KSA+PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzRWFySGFzaGVkKGVhciwgbWluWCwgbWluWSwgaW52U2l6ZSkge1xuICAgIHZhciBhID0gZWFyLnByZXYsXG4gICAgICAgIGIgPSBlYXIsXG4gICAgICAgIGMgPSBlYXIubmV4dDtcblxuICAgIGlmIChhcmVhKGEsIGIsIGMpID49IDApIHJldHVybiBmYWxzZTsgLy8gcmVmbGV4LCBjYW4ndCBiZSBhbiBlYXJcblxuICAgIC8vIHRyaWFuZ2xlIGJib3g7IG1pbiAmIG1heCBhcmUgY2FsY3VsYXRlZCBsaWtlIHRoaXMgZm9yIHNwZWVkXG4gICAgdmFyIG1pblRYID0gYS54IDwgYi54ID8gKGEueCA8IGMueCA/IGEueCA6IGMueCkgOiAoYi54IDwgYy54ID8gYi54IDogYy54KSxcbiAgICAgICAgbWluVFkgPSBhLnkgPCBiLnkgPyAoYS55IDwgYy55ID8gYS55IDogYy55KSA6IChiLnkgPCBjLnkgPyBiLnkgOiBjLnkpLFxuICAgICAgICBtYXhUWCA9IGEueCA+IGIueCA/IChhLnggPiBjLnggPyBhLnggOiBjLngpIDogKGIueCA+IGMueCA/IGIueCA6IGMueCksXG4gICAgICAgIG1heFRZID0gYS55ID4gYi55ID8gKGEueSA+IGMueSA/IGEueSA6IGMueSkgOiAoYi55ID4gYy55ID8gYi55IDogYy55KTtcblxuICAgIC8vIHotb3JkZXIgcmFuZ2UgZm9yIHRoZSBjdXJyZW50IHRyaWFuZ2xlIGJib3g7XG4gICAgdmFyIG1pblogPSB6T3JkZXIobWluVFgsIG1pblRZLCBtaW5YLCBtaW5ZLCBpbnZTaXplKSxcbiAgICAgICAgbWF4WiA9IHpPcmRlcihtYXhUWCwgbWF4VFksIG1pblgsIG1pblksIGludlNpemUpO1xuXG4gICAgdmFyIHAgPSBlYXIucHJldlosXG4gICAgICAgIG4gPSBlYXIubmV4dFo7XG5cbiAgICAvLyBsb29rIGZvciBwb2ludHMgaW5zaWRlIHRoZSB0cmlhbmdsZSBpbiBib3RoIGRpcmVjdGlvbnNcbiAgICB3aGlsZSAocCAmJiBwLnogPj0gbWluWiAmJiBuICYmIG4ueiA8PSBtYXhaKSB7XG4gICAgICAgIGlmIChwICE9PSBlYXIucHJldiAmJiBwICE9PSBlYXIubmV4dCAmJlxuICAgICAgICAgICAgcG9pbnRJblRyaWFuZ2xlKGEueCwgYS55LCBiLngsIGIueSwgYy54LCBjLnksIHAueCwgcC55KSAmJlxuICAgICAgICAgICAgYXJlYShwLnByZXYsIHAsIHAubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBwID0gcC5wcmV2WjtcblxuICAgICAgICBpZiAobiAhPT0gZWFyLnByZXYgJiYgbiAhPT0gZWFyLm5leHQgJiZcbiAgICAgICAgICAgIHBvaW50SW5UcmlhbmdsZShhLngsIGEueSwgYi54LCBiLnksIGMueCwgYy55LCBuLngsIG4ueSkgJiZcbiAgICAgICAgICAgIGFyZWEobi5wcmV2LCBuLCBuLm5leHQpID49IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgbiA9IG4ubmV4dFo7XG4gICAgfVxuXG4gICAgLy8gbG9vayBmb3IgcmVtYWluaW5nIHBvaW50cyBpbiBkZWNyZWFzaW5nIHotb3JkZXJcbiAgICB3aGlsZSAocCAmJiBwLnogPj0gbWluWikge1xuICAgICAgICBpZiAocCAhPT0gZWFyLnByZXYgJiYgcCAhPT0gZWFyLm5leHQgJiZcbiAgICAgICAgICAgIHBvaW50SW5UcmlhbmdsZShhLngsIGEueSwgYi54LCBiLnksIGMueCwgYy55LCBwLngsIHAueSkgJiZcbiAgICAgICAgICAgIGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID49IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgcCA9IHAucHJldlo7XG4gICAgfVxuXG4gICAgLy8gbG9vayBmb3IgcmVtYWluaW5nIHBvaW50cyBpbiBpbmNyZWFzaW5nIHotb3JkZXJcbiAgICB3aGlsZSAobiAmJiBuLnogPD0gbWF4Wikge1xuICAgICAgICBpZiAobiAhPT0gZWFyLnByZXYgJiYgbiAhPT0gZWFyLm5leHQgJiZcbiAgICAgICAgICAgIHBvaW50SW5UcmlhbmdsZShhLngsIGEueSwgYi54LCBiLnksIGMueCwgYy55LCBuLngsIG4ueSkgJiZcbiAgICAgICAgICAgIGFyZWEobi5wcmV2LCBuLCBuLm5leHQpID49IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgbiA9IG4ubmV4dFo7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8vIGdvIHRocm91Z2ggYWxsIHBvbHlnb24gbm9kZXMgYW5kIGN1cmUgc21hbGwgbG9jYWwgc2VsZi1pbnRlcnNlY3Rpb25zXG5mdW5jdGlvbiBjdXJlTG9jYWxJbnRlcnNlY3Rpb25zKHN0YXJ0LCB0cmlhbmdsZXMsIGRpbSkge1xuICAgIHZhciBwID0gc3RhcnQ7XG4gICAgZG8ge1xuICAgICAgICB2YXIgYSA9IHAucHJldixcbiAgICAgICAgICAgIGIgPSBwLm5leHQubmV4dDtcblxuICAgICAgICBpZiAoIWVxdWFscyhhLCBiKSAmJiBpbnRlcnNlY3RzKGEsIHAsIHAubmV4dCwgYikgJiYgbG9jYWxseUluc2lkZShhLCBiKSAmJiBsb2NhbGx5SW5zaWRlKGIsIGEpKSB7XG5cbiAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKGEuaSAvIGRpbSk7XG4gICAgICAgICAgICB0cmlhbmdsZXMucHVzaChwLmkgLyBkaW0pO1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goYi5pIC8gZGltKTtcblxuICAgICAgICAgICAgLy8gcmVtb3ZlIHR3byBub2RlcyBpbnZvbHZlZFxuICAgICAgICAgICAgcmVtb3ZlTm9kZShwKTtcbiAgICAgICAgICAgIHJlbW92ZU5vZGUocC5uZXh0KTtcblxuICAgICAgICAgICAgcCA9IHN0YXJ0ID0gYjtcbiAgICAgICAgfVxuICAgICAgICBwID0gcC5uZXh0O1xuICAgIH0gd2hpbGUgKHAgIT09IHN0YXJ0KTtcblxuICAgIHJldHVybiBwO1xufVxuXG4vLyB0cnkgc3BsaXR0aW5nIHBvbHlnb24gaW50byB0d28gYW5kIHRyaWFuZ3VsYXRlIHRoZW0gaW5kZXBlbmRlbnRseVxuZnVuY3Rpb24gc3BsaXRFYXJjdXQoc3RhcnQsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplKSB7XG4gICAgLy8gbG9vayBmb3IgYSB2YWxpZCBkaWFnb25hbCB0aGF0IGRpdmlkZXMgdGhlIHBvbHlnb24gaW50byB0d29cbiAgICB2YXIgYSA9IHN0YXJ0O1xuICAgIGRvIHtcbiAgICAgICAgdmFyIGIgPSBhLm5leHQubmV4dDtcbiAgICAgICAgd2hpbGUgKGIgIT09IGEucHJldikge1xuICAgICAgICAgICAgaWYgKGEuaSAhPT0gYi5pICYmIGlzVmFsaWREaWFnb25hbChhLCBiKSkge1xuICAgICAgICAgICAgICAgIC8vIHNwbGl0IHRoZSBwb2x5Z29uIGluIHR3byBieSB0aGUgZGlhZ29uYWxcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHNwbGl0UG9seWdvbihhLCBiKTtcblxuICAgICAgICAgICAgICAgIC8vIGZpbHRlciBjb2xpbmVhciBwb2ludHMgYXJvdW5kIHRoZSBjdXRzXG4gICAgICAgICAgICAgICAgYSA9IGZpbHRlclBvaW50cyhhLCBhLm5leHQpO1xuICAgICAgICAgICAgICAgIGMgPSBmaWx0ZXJQb2ludHMoYywgYy5uZXh0KTtcblxuICAgICAgICAgICAgICAgIC8vIHJ1biBlYXJjdXQgb24gZWFjaCBoYWxmXG4gICAgICAgICAgICAgICAgZWFyY3V0TGlua2VkKGEsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplKTtcbiAgICAgICAgICAgICAgICBlYXJjdXRMaW5rZWQoYywgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGIgPSBiLm5leHQ7XG4gICAgICAgIH1cbiAgICAgICAgYSA9IGEubmV4dDtcbiAgICB9IHdoaWxlIChhICE9PSBzdGFydCk7XG59XG5cbi8vIGxpbmsgZXZlcnkgaG9sZSBpbnRvIHRoZSBvdXRlciBsb29wLCBwcm9kdWNpbmcgYSBzaW5nbGUtcmluZyBwb2x5Z29uIHdpdGhvdXQgaG9sZXNcbmZ1bmN0aW9uIGVsaW1pbmF0ZUhvbGVzKGRhdGEsIGhvbGVJbmRpY2VzLCBvdXRlck5vZGUsIGRpbSkge1xuICAgIHZhciBxdWV1ZSA9IFtdLFxuICAgICAgICBpLCBsZW4sIHN0YXJ0LCBlbmQsIGxpc3Q7XG5cbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBob2xlSW5kaWNlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBzdGFydCA9IGhvbGVJbmRpY2VzW2ldICogZGltO1xuICAgICAgICBlbmQgPSBpIDwgbGVuIC0gMSA/IGhvbGVJbmRpY2VzW2kgKyAxXSAqIGRpbSA6IGRhdGEubGVuZ3RoO1xuICAgICAgICBsaXN0ID0gbGlua2VkTGlzdChkYXRhLCBzdGFydCwgZW5kLCBkaW0sIGZhbHNlKTtcbiAgICAgICAgaWYgKGxpc3QgPT09IGxpc3QubmV4dCkgbGlzdC5zdGVpbmVyID0gdHJ1ZTtcbiAgICAgICAgcXVldWUucHVzaChnZXRMZWZ0bW9zdChsaXN0KSk7XG4gICAgfVxuXG4gICAgcXVldWUuc29ydChjb21wYXJlWCk7XG5cbiAgICAvLyBwcm9jZXNzIGhvbGVzIGZyb20gbGVmdCB0byByaWdodFxuICAgIGZvciAoaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICBlbGltaW5hdGVIb2xlKHF1ZXVlW2ldLCBvdXRlck5vZGUpO1xuICAgICAgICBvdXRlck5vZGUgPSBmaWx0ZXJQb2ludHMob3V0ZXJOb2RlLCBvdXRlck5vZGUubmV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dGVyTm9kZTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZVgoYSwgYikge1xuICAgIHJldHVybiBhLnggLSBiLng7XG59XG5cbi8vIGZpbmQgYSBicmlkZ2UgYmV0d2VlbiB2ZXJ0aWNlcyB0aGF0IGNvbm5lY3RzIGhvbGUgd2l0aCBhbiBvdXRlciByaW5nIGFuZCBhbmQgbGluayBpdFxuZnVuY3Rpb24gZWxpbWluYXRlSG9sZShob2xlLCBvdXRlck5vZGUpIHtcbiAgICBvdXRlck5vZGUgPSBmaW5kSG9sZUJyaWRnZShob2xlLCBvdXRlck5vZGUpO1xuICAgIGlmIChvdXRlck5vZGUpIHtcbiAgICAgICAgdmFyIGIgPSBzcGxpdFBvbHlnb24ob3V0ZXJOb2RlLCBob2xlKTtcbiAgICAgICAgZmlsdGVyUG9pbnRzKGIsIGIubmV4dCk7XG4gICAgfVxufVxuXG4vLyBEYXZpZCBFYmVybHkncyBhbGdvcml0aG0gZm9yIGZpbmRpbmcgYSBicmlkZ2UgYmV0d2VlbiBob2xlIGFuZCBvdXRlciBwb2x5Z29uXG5mdW5jdGlvbiBmaW5kSG9sZUJyaWRnZShob2xlLCBvdXRlck5vZGUpIHtcbiAgICB2YXIgcCA9IG91dGVyTm9kZSxcbiAgICAgICAgaHggPSBob2xlLngsXG4gICAgICAgIGh5ID0gaG9sZS55LFxuICAgICAgICBxeCA9IC1JbmZpbml0eSxcbiAgICAgICAgbTtcblxuICAgIC8vIGZpbmQgYSBzZWdtZW50IGludGVyc2VjdGVkIGJ5IGEgcmF5IGZyb20gdGhlIGhvbGUncyBsZWZ0bW9zdCBwb2ludCB0byB0aGUgbGVmdDtcbiAgICAvLyBzZWdtZW50J3MgZW5kcG9pbnQgd2l0aCBsZXNzZXIgeCB3aWxsIGJlIHBvdGVudGlhbCBjb25uZWN0aW9uIHBvaW50XG4gICAgZG8ge1xuICAgICAgICBpZiAoaHkgPD0gcC55ICYmIGh5ID49IHAubmV4dC55ICYmIHAubmV4dC55ICE9PSBwLnkpIHtcbiAgICAgICAgICAgIHZhciB4ID0gcC54ICsgKGh5IC0gcC55KSAqIChwLm5leHQueCAtIHAueCkgLyAocC5uZXh0LnkgLSBwLnkpO1xuICAgICAgICAgICAgaWYgKHggPD0gaHggJiYgeCA+IHF4KSB7XG4gICAgICAgICAgICAgICAgcXggPSB4O1xuICAgICAgICAgICAgICAgIGlmICh4ID09PSBoeCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHkgPT09IHAueSkgcmV0dXJuIHA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoeSA9PT0gcC5uZXh0LnkpIHJldHVybiBwLm5leHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG0gPSBwLnggPCBwLm5leHQueCA/IHAgOiBwLm5leHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcCA9IHAubmV4dDtcbiAgICB9IHdoaWxlIChwICE9PSBvdXRlck5vZGUpO1xuXG4gICAgaWYgKCFtKSByZXR1cm4gbnVsbDtcblxuICAgIGlmIChoeCA9PT0gcXgpIHJldHVybiBtLnByZXY7IC8vIGhvbGUgdG91Y2hlcyBvdXRlciBzZWdtZW50OyBwaWNrIGxvd2VyIGVuZHBvaW50XG5cbiAgICAvLyBsb29rIGZvciBwb2ludHMgaW5zaWRlIHRoZSB0cmlhbmdsZSBvZiBob2xlIHBvaW50LCBzZWdtZW50IGludGVyc2VjdGlvbiBhbmQgZW5kcG9pbnQ7XG4gICAgLy8gaWYgdGhlcmUgYXJlIG5vIHBvaW50cyBmb3VuZCwgd2UgaGF2ZSBhIHZhbGlkIGNvbm5lY3Rpb247XG4gICAgLy8gb3RoZXJ3aXNlIGNob29zZSB0aGUgcG9pbnQgb2YgdGhlIG1pbmltdW0gYW5nbGUgd2l0aCB0aGUgcmF5IGFzIGNvbm5lY3Rpb24gcG9pbnRcblxuICAgIHZhciBzdG9wID0gbSxcbiAgICAgICAgbXggPSBtLngsXG4gICAgICAgIG15ID0gbS55LFxuICAgICAgICB0YW5NaW4gPSBJbmZpbml0eSxcbiAgICAgICAgdGFuO1xuXG4gICAgcCA9IG0ubmV4dDtcblxuICAgIHdoaWxlIChwICE9PSBzdG9wKSB7XG4gICAgICAgIGlmIChoeCA+PSBwLnggJiYgcC54ID49IG14ICYmIGh4ICE9PSBwLnggJiZcbiAgICAgICAgICAgICAgICBwb2ludEluVHJpYW5nbGUoaHkgPCBteSA/IGh4IDogcXgsIGh5LCBteCwgbXksIGh5IDwgbXkgPyBxeCA6IGh4LCBoeSwgcC54LCBwLnkpKSB7XG5cbiAgICAgICAgICAgIHRhbiA9IE1hdGguYWJzKGh5IC0gcC55KSAvIChoeCAtIHAueCk7IC8vIHRhbmdlbnRpYWxcblxuICAgICAgICAgICAgaWYgKCh0YW4gPCB0YW5NaW4gfHwgKHRhbiA9PT0gdGFuTWluICYmIHAueCA+IG0ueCkpICYmIGxvY2FsbHlJbnNpZGUocCwgaG9sZSkpIHtcbiAgICAgICAgICAgICAgICBtID0gcDtcbiAgICAgICAgICAgICAgICB0YW5NaW4gPSB0YW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwID0gcC5uZXh0O1xuICAgIH1cblxuICAgIHJldHVybiBtO1xufVxuXG4vLyBpbnRlcmxpbmsgcG9seWdvbiBub2RlcyBpbiB6LW9yZGVyXG5mdW5jdGlvbiBpbmRleEN1cnZlKHN0YXJ0LCBtaW5YLCBtaW5ZLCBpbnZTaXplKSB7XG4gICAgdmFyIHAgPSBzdGFydDtcbiAgICBkbyB7XG4gICAgICAgIGlmIChwLnogPT09IG51bGwpIHAueiA9IHpPcmRlcihwLngsIHAueSwgbWluWCwgbWluWSwgaW52U2l6ZSk7XG4gICAgICAgIHAucHJldlogPSBwLnByZXY7XG4gICAgICAgIHAubmV4dFogPSBwLm5leHQ7XG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfSB3aGlsZSAocCAhPT0gc3RhcnQpO1xuXG4gICAgcC5wcmV2Wi5uZXh0WiA9IG51bGw7XG4gICAgcC5wcmV2WiA9IG51bGw7XG5cbiAgICBzb3J0TGlua2VkKHApO1xufVxuXG4vLyBTaW1vbiBUYXRoYW0ncyBsaW5rZWQgbGlzdCBtZXJnZSBzb3J0IGFsZ29yaXRobVxuLy8gaHR0cDovL3d3dy5jaGlhcmsuZ3JlZW5lbmQub3JnLnVrL35zZ3RhdGhhbS9hbGdvcml0aG1zL2xpc3Rzb3J0Lmh0bWxcbmZ1bmN0aW9uIHNvcnRMaW5rZWQobGlzdCkge1xuICAgIHZhciBpLCBwLCBxLCBlLCB0YWlsLCBudW1NZXJnZXMsIHBTaXplLCBxU2l6ZSxcbiAgICAgICAgaW5TaXplID0gMTtcblxuICAgIGRvIHtcbiAgICAgICAgcCA9IGxpc3Q7XG4gICAgICAgIGxpc3QgPSBudWxsO1xuICAgICAgICB0YWlsID0gbnVsbDtcbiAgICAgICAgbnVtTWVyZ2VzID0gMDtcblxuICAgICAgICB3aGlsZSAocCkge1xuICAgICAgICAgICAgbnVtTWVyZ2VzKys7XG4gICAgICAgICAgICBxID0gcDtcbiAgICAgICAgICAgIHBTaXplID0gMDtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBpblNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHBTaXplKys7XG4gICAgICAgICAgICAgICAgcSA9IHEubmV4dFo7XG4gICAgICAgICAgICAgICAgaWYgKCFxKSBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHFTaXplID0gaW5TaXplO1xuXG4gICAgICAgICAgICB3aGlsZSAocFNpemUgPiAwIHx8IChxU2l6ZSA+IDAgJiYgcSkpIHtcblxuICAgICAgICAgICAgICAgIGlmIChwU2l6ZSAhPT0gMCAmJiAocVNpemUgPT09IDAgfHwgIXEgfHwgcC56IDw9IHEueikpIHtcbiAgICAgICAgICAgICAgICAgICAgZSA9IHA7XG4gICAgICAgICAgICAgICAgICAgIHAgPSBwLm5leHRaO1xuICAgICAgICAgICAgICAgICAgICBwU2l6ZS0tO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGUgPSBxO1xuICAgICAgICAgICAgICAgICAgICBxID0gcS5uZXh0WjtcbiAgICAgICAgICAgICAgICAgICAgcVNpemUtLTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGFpbCkgdGFpbC5uZXh0WiA9IGU7XG4gICAgICAgICAgICAgICAgZWxzZSBsaXN0ID0gZTtcblxuICAgICAgICAgICAgICAgIGUucHJldlogPSB0YWlsO1xuICAgICAgICAgICAgICAgIHRhaWwgPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwID0gcTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhaWwubmV4dFogPSBudWxsO1xuICAgICAgICBpblNpemUgKj0gMjtcblxuICAgIH0gd2hpbGUgKG51bU1lcmdlcyA+IDEpO1xuXG4gICAgcmV0dXJuIGxpc3Q7XG59XG5cbi8vIHotb3JkZXIgb2YgYSBwb2ludCBnaXZlbiBjb29yZHMgYW5kIGludmVyc2Ugb2YgdGhlIGxvbmdlciBzaWRlIG9mIGRhdGEgYmJveFxuZnVuY3Rpb24gek9yZGVyKHgsIHksIG1pblgsIG1pblksIGludlNpemUpIHtcbiAgICAvLyBjb29yZHMgYXJlIHRyYW5zZm9ybWVkIGludG8gbm9uLW5lZ2F0aXZlIDE1LWJpdCBpbnRlZ2VyIHJhbmdlXG4gICAgeCA9IDMyNzY3ICogKHggLSBtaW5YKSAqIGludlNpemU7XG4gICAgeSA9IDMyNzY3ICogKHkgLSBtaW5ZKSAqIGludlNpemU7XG5cbiAgICB4ID0gKHggfCAoeCA8PCA4KSkgJiAweDAwRkYwMEZGO1xuICAgIHggPSAoeCB8ICh4IDw8IDQpKSAmIDB4MEYwRjBGMEY7XG4gICAgeCA9ICh4IHwgKHggPDwgMikpICYgMHgzMzMzMzMzMztcbiAgICB4ID0gKHggfCAoeCA8PCAxKSkgJiAweDU1NTU1NTU1O1xuXG4gICAgeSA9ICh5IHwgKHkgPDwgOCkpICYgMHgwMEZGMDBGRjtcbiAgICB5ID0gKHkgfCAoeSA8PCA0KSkgJiAweDBGMEYwRjBGO1xuICAgIHkgPSAoeSB8ICh5IDw8IDIpKSAmIDB4MzMzMzMzMzM7XG4gICAgeSA9ICh5IHwgKHkgPDwgMSkpICYgMHg1NTU1NTU1NTtcblxuICAgIHJldHVybiB4IHwgKHkgPDwgMSk7XG59XG5cbi8vIGZpbmQgdGhlIGxlZnRtb3N0IG5vZGUgb2YgYSBwb2x5Z29uIHJpbmdcbmZ1bmN0aW9uIGdldExlZnRtb3N0KHN0YXJ0KSB7XG4gICAgdmFyIHAgPSBzdGFydCxcbiAgICAgICAgbGVmdG1vc3QgPSBzdGFydDtcbiAgICBkbyB7XG4gICAgICAgIGlmIChwLnggPCBsZWZ0bW9zdC54KSBsZWZ0bW9zdCA9IHA7XG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfSB3aGlsZSAocCAhPT0gc3RhcnQpO1xuXG4gICAgcmV0dXJuIGxlZnRtb3N0O1xufVxuXG4vLyBjaGVjayBpZiBhIHBvaW50IGxpZXMgd2l0aGluIGEgY29udmV4IHRyaWFuZ2xlXG5mdW5jdGlvbiBwb2ludEluVHJpYW5nbGUoYXgsIGF5LCBieCwgYnksIGN4LCBjeSwgcHgsIHB5KSB7XG4gICAgcmV0dXJuIChjeCAtIHB4KSAqIChheSAtIHB5KSAtIChheCAtIHB4KSAqIChjeSAtIHB5KSA+PSAwICYmXG4gICAgICAgICAgIChheCAtIHB4KSAqIChieSAtIHB5KSAtIChieCAtIHB4KSAqIChheSAtIHB5KSA+PSAwICYmXG4gICAgICAgICAgIChieCAtIHB4KSAqIChjeSAtIHB5KSAtIChjeCAtIHB4KSAqIChieSAtIHB5KSA+PSAwO1xufVxuXG4vLyBjaGVjayBpZiBhIGRpYWdvbmFsIGJldHdlZW4gdHdvIHBvbHlnb24gbm9kZXMgaXMgdmFsaWQgKGxpZXMgaW4gcG9seWdvbiBpbnRlcmlvcilcbmZ1bmN0aW9uIGlzVmFsaWREaWFnb25hbChhLCBiKSB7XG4gICAgcmV0dXJuIGEubmV4dC5pICE9PSBiLmkgJiYgYS5wcmV2LmkgIT09IGIuaSAmJiAhaW50ZXJzZWN0c1BvbHlnb24oYSwgYikgJiZcbiAgICAgICAgICAgbG9jYWxseUluc2lkZShhLCBiKSAmJiBsb2NhbGx5SW5zaWRlKGIsIGEpICYmIG1pZGRsZUluc2lkZShhLCBiKTtcbn1cblxuLy8gc2lnbmVkIGFyZWEgb2YgYSB0cmlhbmdsZVxuZnVuY3Rpb24gYXJlYShwLCBxLCByKSB7XG4gICAgcmV0dXJuIChxLnkgLSBwLnkpICogKHIueCAtIHEueCkgLSAocS54IC0gcC54KSAqIChyLnkgLSBxLnkpO1xufVxuXG4vLyBjaGVjayBpZiB0d28gcG9pbnRzIGFyZSBlcXVhbFxuZnVuY3Rpb24gZXF1YWxzKHAxLCBwMikge1xuICAgIHJldHVybiBwMS54ID09PSBwMi54ICYmIHAxLnkgPT09IHAyLnk7XG59XG5cbi8vIGNoZWNrIGlmIHR3byBzZWdtZW50cyBpbnRlcnNlY3RcbmZ1bmN0aW9uIGludGVyc2VjdHMocDEsIHExLCBwMiwgcTIpIHtcbiAgICBpZiAoKGVxdWFscyhwMSwgcTEpICYmIGVxdWFscyhwMiwgcTIpKSB8fFxuICAgICAgICAoZXF1YWxzKHAxLCBxMikgJiYgZXF1YWxzKHAyLCBxMSkpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gYXJlYShwMSwgcTEsIHAyKSA+IDAgIT09IGFyZWEocDEsIHExLCBxMikgPiAwICYmXG4gICAgICAgICAgIGFyZWEocDIsIHEyLCBwMSkgPiAwICE9PSBhcmVhKHAyLCBxMiwgcTEpID4gMDtcbn1cblxuLy8gY2hlY2sgaWYgYSBwb2x5Z29uIGRpYWdvbmFsIGludGVyc2VjdHMgYW55IHBvbHlnb24gc2VnbWVudHNcbmZ1bmN0aW9uIGludGVyc2VjdHNQb2x5Z29uKGEsIGIpIHtcbiAgICB2YXIgcCA9IGE7XG4gICAgZG8ge1xuICAgICAgICBpZiAocC5pICE9PSBhLmkgJiYgcC5uZXh0LmkgIT09IGEuaSAmJiBwLmkgIT09IGIuaSAmJiBwLm5leHQuaSAhPT0gYi5pICYmXG4gICAgICAgICAgICAgICAgaW50ZXJzZWN0cyhwLCBwLm5leHQsIGEsIGIpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgcCA9IHAubmV4dDtcbiAgICB9IHdoaWxlIChwICE9PSBhKTtcblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLy8gY2hlY2sgaWYgYSBwb2x5Z29uIGRpYWdvbmFsIGlzIGxvY2FsbHkgaW5zaWRlIHRoZSBwb2x5Z29uXG5mdW5jdGlvbiBsb2NhbGx5SW5zaWRlKGEsIGIpIHtcbiAgICByZXR1cm4gYXJlYShhLnByZXYsIGEsIGEubmV4dCkgPCAwID9cbiAgICAgICAgYXJlYShhLCBiLCBhLm5leHQpID49IDAgJiYgYXJlYShhLCBhLnByZXYsIGIpID49IDAgOlxuICAgICAgICBhcmVhKGEsIGIsIGEucHJldikgPCAwIHx8IGFyZWEoYSwgYS5uZXh0LCBiKSA8IDA7XG59XG5cbi8vIGNoZWNrIGlmIHRoZSBtaWRkbGUgcG9pbnQgb2YgYSBwb2x5Z29uIGRpYWdvbmFsIGlzIGluc2lkZSB0aGUgcG9seWdvblxuZnVuY3Rpb24gbWlkZGxlSW5zaWRlKGEsIGIpIHtcbiAgICB2YXIgcCA9IGEsXG4gICAgICAgIGluc2lkZSA9IGZhbHNlLFxuICAgICAgICBweCA9IChhLnggKyBiLngpIC8gMixcbiAgICAgICAgcHkgPSAoYS55ICsgYi55KSAvIDI7XG4gICAgZG8ge1xuICAgICAgICBpZiAoKChwLnkgPiBweSkgIT09IChwLm5leHQueSA+IHB5KSkgJiYgcC5uZXh0LnkgIT09IHAueSAmJlxuICAgICAgICAgICAgICAgIChweCA8IChwLm5leHQueCAtIHAueCkgKiAocHkgLSBwLnkpIC8gKHAubmV4dC55IC0gcC55KSArIHAueCkpXG4gICAgICAgICAgICBpbnNpZGUgPSAhaW5zaWRlO1xuICAgICAgICBwID0gcC5uZXh0O1xuICAgIH0gd2hpbGUgKHAgIT09IGEpO1xuXG4gICAgcmV0dXJuIGluc2lkZTtcbn1cblxuLy8gbGluayB0d28gcG9seWdvbiB2ZXJ0aWNlcyB3aXRoIGEgYnJpZGdlOyBpZiB0aGUgdmVydGljZXMgYmVsb25nIHRvIHRoZSBzYW1lIHJpbmcsIGl0IHNwbGl0cyBwb2x5Z29uIGludG8gdHdvO1xuLy8gaWYgb25lIGJlbG9uZ3MgdG8gdGhlIG91dGVyIHJpbmcgYW5kIGFub3RoZXIgdG8gYSBob2xlLCBpdCBtZXJnZXMgaXQgaW50byBhIHNpbmdsZSByaW5nXG5mdW5jdGlvbiBzcGxpdFBvbHlnb24oYSwgYikge1xuICAgIHZhciBhMiA9IG5ldyBOb2RlKGEuaSwgYS54LCBhLnkpLFxuICAgICAgICBiMiA9IG5ldyBOb2RlKGIuaSwgYi54LCBiLnkpLFxuICAgICAgICBhbiA9IGEubmV4dCxcbiAgICAgICAgYnAgPSBiLnByZXY7XG5cbiAgICBhLm5leHQgPSBiO1xuICAgIGIucHJldiA9IGE7XG5cbiAgICBhMi5uZXh0ID0gYW47XG4gICAgYW4ucHJldiA9IGEyO1xuXG4gICAgYjIubmV4dCA9IGEyO1xuICAgIGEyLnByZXYgPSBiMjtcblxuICAgIGJwLm5leHQgPSBiMjtcbiAgICBiMi5wcmV2ID0gYnA7XG5cbiAgICByZXR1cm4gYjI7XG59XG5cbi8vIGNyZWF0ZSBhIG5vZGUgYW5kIG9wdGlvbmFsbHkgbGluayBpdCB3aXRoIHByZXZpb3VzIG9uZSAoaW4gYSBjaXJjdWxhciBkb3VibHkgbGlua2VkIGxpc3QpXG5mdW5jdGlvbiBpbnNlcnROb2RlKGksIHgsIHksIGxhc3QpIHtcbiAgICB2YXIgcCA9IG5ldyBOb2RlKGksIHgsIHkpO1xuXG4gICAgaWYgKCFsYXN0KSB7XG4gICAgICAgIHAucHJldiA9IHA7XG4gICAgICAgIHAubmV4dCA9IHA7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBwLm5leHQgPSBsYXN0Lm5leHQ7XG4gICAgICAgIHAucHJldiA9IGxhc3Q7XG4gICAgICAgIGxhc3QubmV4dC5wcmV2ID0gcDtcbiAgICAgICAgbGFzdC5uZXh0ID0gcDtcbiAgICB9XG4gICAgcmV0dXJuIHA7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5vZGUocCkge1xuICAgIHAubmV4dC5wcmV2ID0gcC5wcmV2O1xuICAgIHAucHJldi5uZXh0ID0gcC5uZXh0O1xuXG4gICAgaWYgKHAucHJldlopIHAucHJldloubmV4dFogPSBwLm5leHRaO1xuICAgIGlmIChwLm5leHRaKSBwLm5leHRaLnByZXZaID0gcC5wcmV2Wjtcbn1cblxuZnVuY3Rpb24gTm9kZShpLCB4LCB5KSB7XG4gICAgLy8gdmVydGljZSBpbmRleCBpbiBjb29yZGluYXRlcyBhcnJheVxuICAgIHRoaXMuaSA9IGk7XG5cbiAgICAvLyB2ZXJ0ZXggY29vcmRpbmF0ZXNcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG5cbiAgICAvLyBwcmV2aW91cyBhbmQgbmV4dCB2ZXJ0aWNlIG5vZGVzIGluIGEgcG9seWdvbiByaW5nXG4gICAgdGhpcy5wcmV2ID0gbnVsbDtcbiAgICB0aGlzLm5leHQgPSBudWxsO1xuXG4gICAgLy8gei1vcmRlciBjdXJ2ZSB2YWx1ZVxuICAgIHRoaXMueiA9IG51bGw7XG5cbiAgICAvLyBwcmV2aW91cyBhbmQgbmV4dCBub2RlcyBpbiB6LW9yZGVyXG4gICAgdGhpcy5wcmV2WiA9IG51bGw7XG4gICAgdGhpcy5uZXh0WiA9IG51bGw7XG5cbiAgICAvLyBpbmRpY2F0ZXMgd2hldGhlciB0aGlzIGlzIGEgc3RlaW5lciBwb2ludFxuICAgIHRoaXMuc3RlaW5lciA9IGZhbHNlO1xufVxuXG4vLyByZXR1cm4gYSBwZXJjZW50YWdlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcG9seWdvbiBhcmVhIGFuZCBpdHMgdHJpYW5ndWxhdGlvbiBhcmVhO1xuLy8gdXNlZCB0byB2ZXJpZnkgY29ycmVjdG5lc3Mgb2YgdHJpYW5ndWxhdGlvblxuZWFyY3V0LmRldmlhdGlvbiA9IGZ1bmN0aW9uIChkYXRhLCBob2xlSW5kaWNlcywgZGltLCB0cmlhbmdsZXMpIHtcbiAgICB2YXIgaGFzSG9sZXMgPSBob2xlSW5kaWNlcyAmJiBob2xlSW5kaWNlcy5sZW5ndGg7XG4gICAgdmFyIG91dGVyTGVuID0gaGFzSG9sZXMgPyBob2xlSW5kaWNlc1swXSAqIGRpbSA6IGRhdGEubGVuZ3RoO1xuXG4gICAgdmFyIHBvbHlnb25BcmVhID0gTWF0aC5hYnMoc2lnbmVkQXJlYShkYXRhLCAwLCBvdXRlckxlbiwgZGltKSk7XG4gICAgaWYgKGhhc0hvbGVzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBob2xlSW5kaWNlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0YXJ0ID0gaG9sZUluZGljZXNbaV0gKiBkaW07XG4gICAgICAgICAgICB2YXIgZW5kID0gaSA8IGxlbiAtIDEgPyBob2xlSW5kaWNlc1tpICsgMV0gKiBkaW0gOiBkYXRhLmxlbmd0aDtcbiAgICAgICAgICAgIHBvbHlnb25BcmVhIC09IE1hdGguYWJzKHNpZ25lZEFyZWEoZGF0YSwgc3RhcnQsIGVuZCwgZGltKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdHJpYW5nbGVzQXJlYSA9IDA7XG4gICAgZm9yIChpID0gMDsgaSA8IHRyaWFuZ2xlcy5sZW5ndGg7IGkgKz0gMykge1xuICAgICAgICB2YXIgYSA9IHRyaWFuZ2xlc1tpXSAqIGRpbTtcbiAgICAgICAgdmFyIGIgPSB0cmlhbmdsZXNbaSArIDFdICogZGltO1xuICAgICAgICB2YXIgYyA9IHRyaWFuZ2xlc1tpICsgMl0gKiBkaW07XG4gICAgICAgIHRyaWFuZ2xlc0FyZWEgKz0gTWF0aC5hYnMoXG4gICAgICAgICAgICAoZGF0YVthXSAtIGRhdGFbY10pICogKGRhdGFbYiArIDFdIC0gZGF0YVthICsgMV0pIC1cbiAgICAgICAgICAgIChkYXRhW2FdIC0gZGF0YVtiXSkgKiAoZGF0YVtjICsgMV0gLSBkYXRhW2EgKyAxXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBwb2x5Z29uQXJlYSA9PT0gMCAmJiB0cmlhbmdsZXNBcmVhID09PSAwID8gMCA6XG4gICAgICAgIE1hdGguYWJzKCh0cmlhbmdsZXNBcmVhIC0gcG9seWdvbkFyZWEpIC8gcG9seWdvbkFyZWEpO1xufTtcblxuZnVuY3Rpb24gc2lnbmVkQXJlYShkYXRhLCBzdGFydCwgZW5kLCBkaW0pIHtcbiAgICB2YXIgc3VtID0gMDtcbiAgICBmb3IgKHZhciBpID0gc3RhcnQsIGogPSBlbmQgLSBkaW07IGkgPCBlbmQ7IGkgKz0gZGltKSB7XG4gICAgICAgIHN1bSArPSAoZGF0YVtqXSAtIGRhdGFbaV0pICogKGRhdGFbaSArIDFdICsgZGF0YVtqICsgMV0pO1xuICAgICAgICBqID0gaTtcbiAgICB9XG4gICAgcmV0dXJuIHN1bTtcbn1cblxuLy8gdHVybiBhIHBvbHlnb24gaW4gYSBtdWx0aS1kaW1lbnNpb25hbCBhcnJheSBmb3JtIChlLmcuIGFzIGluIEdlb0pTT04pIGludG8gYSBmb3JtIEVhcmN1dCBhY2NlcHRzXG5lYXJjdXQuZmxhdHRlbiA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyIGRpbSA9IGRhdGFbMF1bMF0ubGVuZ3RoLFxuICAgICAgICByZXN1bHQgPSB7dmVydGljZXM6IFtdLCBob2xlczogW10sIGRpbWVuc2lvbnM6IGRpbX0sXG4gICAgICAgIGhvbGVJbmRleCA9IDA7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBkYXRhW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBkID0gMDsgZCA8IGRpbTsgZCsrKSByZXN1bHQudmVydGljZXMucHVzaChkYXRhW2ldW2pdW2RdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaSA+IDApIHtcbiAgICAgICAgICAgIGhvbGVJbmRleCArPSBkYXRhW2kgLSAxXS5sZW5ndGg7XG4gICAgICAgICAgICByZXN1bHQuaG9sZXMucHVzaChob2xlSW5kZXgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBlZGdlVG9BZGphY2VuY3lcblxudmFyIHVuaXEgPSByZXF1aXJlKFwidW5pcVwiKVxuXG5mdW5jdGlvbiBlZGdlVG9BZGphY2VuY3koZWRnZXMsIG51bVZlcnRpY2VzKSB7XG4gIHZhciBudW1FZGdlcyA9IGVkZ2VzLmxlbmd0aFxuICBpZih0eXBlb2YgbnVtVmVydGljZXMgIT09IFwibnVtYmVyXCIpIHtcbiAgICBudW1WZXJ0aWNlcyA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICBudW1WZXJ0aWNlcyA9IE1hdGgubWF4KG51bVZlcnRpY2VzLCBlWzBdLCBlWzFdKVxuICAgIH1cbiAgICBudW1WZXJ0aWNlcyA9IChudW1WZXJ0aWNlc3wwKSArIDFcbiAgfVxuICBudW1WZXJ0aWNlcyA9IG51bVZlcnRpY2VzfDBcbiAgdmFyIGFkaiA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGFkaltpXSA9IFtdXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8bnVtRWRnZXM7ICsraSkge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICBhZGpbZVswXV0ucHVzaChlWzFdKVxuICAgIGFkaltlWzFdXS5wdXNoKGVbMF0pXG4gIH1cbiAgZm9yKHZhciBqPTA7IGo8bnVtVmVydGljZXM7ICsraikge1xuICAgIHVuaXEoYWRqW2pdLCBmdW5jdGlvbihhLCBiKSB7XG4gICAgICByZXR1cm4gYSAtIGJcbiAgICB9KVxuICB9XG4gIHJldHVybiBhZGpcbn0iLCIvLyBJbnNwaXJlZCBieSBHb29nbGUgQ2xvc3VyZTpcbi8vIGh0dHA6Ly9jbG9zdXJlLWxpYnJhcnkuZ29vZ2xlY29kZS5jb20vc3ZuL2RvY3MvXG4vLyBjbG9zdXJlX2dvb2dfYXJyYXlfYXJyYXkuanMuaHRtbCNnb29nLmFycmF5LmNsZWFyXG5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgdmFsdWUgPSByZXF1aXJlKFwiLi4vLi4vb2JqZWN0L3ZhbGlkLXZhbHVlXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcblx0dmFsdWUodGhpcykubGVuZ3RoID0gMDtcblx0cmV0dXJuIHRoaXM7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IEFycmF5LmZyb21cblx0OiByZXF1aXJlKFwiLi9zaGltXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgZnJvbSA9IEFycmF5LmZyb20sIGFyciwgcmVzdWx0O1xuXHRpZiAodHlwZW9mIGZyb20gIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGZhbHNlO1xuXHRhcnIgPSBbXCJyYXpcIiwgXCJkd2FcIl07XG5cdHJlc3VsdCA9IGZyb20oYXJyKTtcblx0cmV0dXJuIEJvb2xlYW4ocmVzdWx0ICYmIChyZXN1bHQgIT09IGFycikgJiYgKHJlc3VsdFsxXSA9PT0gXCJkd2FcIikpO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgaXRlcmF0b3JTeW1ib2wgPSByZXF1aXJlKFwiZXM2LXN5bWJvbFwiKS5pdGVyYXRvclxuICAsIGlzQXJndW1lbnRzICAgID0gcmVxdWlyZShcIi4uLy4uL2Z1bmN0aW9uL2lzLWFyZ3VtZW50c1wiKVxuICAsIGlzRnVuY3Rpb24gICAgID0gcmVxdWlyZShcIi4uLy4uL2Z1bmN0aW9uL2lzLWZ1bmN0aW9uXCIpXG4gICwgdG9Qb3NJbnQgICAgICAgPSByZXF1aXJlKFwiLi4vLi4vbnVtYmVyL3RvLXBvcy1pbnRlZ2VyXCIpXG4gICwgY2FsbGFibGUgICAgICAgPSByZXF1aXJlKFwiLi4vLi4vb2JqZWN0L3ZhbGlkLWNhbGxhYmxlXCIpXG4gICwgdmFsaWRWYWx1ZSAgICAgPSByZXF1aXJlKFwiLi4vLi4vb2JqZWN0L3ZhbGlkLXZhbHVlXCIpXG4gICwgaXNWYWx1ZSAgICAgICAgPSByZXF1aXJlKFwiLi4vLi4vb2JqZWN0L2lzLXZhbHVlXCIpXG4gICwgaXNTdHJpbmcgICAgICAgPSByZXF1aXJlKFwiLi4vLi4vc3RyaW5nL2lzLXN0cmluZ1wiKVxuICAsIGlzQXJyYXkgICAgICAgID0gQXJyYXkuaXNBcnJheVxuICAsIGNhbGwgICAgICAgICAgID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGxcbiAgLCBkZXNjICAgICAgICAgICA9IHsgY29uZmlndXJhYmxlOiB0cnVlLCBlbnVtZXJhYmxlOiB0cnVlLCB3cml0YWJsZTogdHJ1ZSwgdmFsdWU6IG51bGwgfVxuICAsIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJyYXlMaWtlIC8qLCBtYXBGbiwgdGhpc0FyZyovKSB7XG5cdHZhciBtYXBGbiA9IGFyZ3VtZW50c1sxXVxuXHQgICwgdGhpc0FyZyA9IGFyZ3VtZW50c1syXVxuXHQgICwgQ29udGV4dFxuXHQgICwgaVxuXHQgICwgalxuXHQgICwgYXJyXG5cdCAgLCBsZW5ndGhcblx0ICAsIGNvZGVcblx0ICAsIGl0ZXJhdG9yXG5cdCAgLCByZXN1bHRcblx0ICAsIGdldEl0ZXJhdG9yXG5cdCAgLCB2YWx1ZTtcblxuXHRhcnJheUxpa2UgPSBPYmplY3QodmFsaWRWYWx1ZShhcnJheUxpa2UpKTtcblxuXHRpZiAoaXNWYWx1ZShtYXBGbikpIGNhbGxhYmxlKG1hcEZuKTtcblx0aWYgKCF0aGlzIHx8IHRoaXMgPT09IEFycmF5IHx8ICFpc0Z1bmN0aW9uKHRoaXMpKSB7XG5cdFx0Ly8gUmVzdWx0OiBQbGFpbiBhcnJheVxuXHRcdGlmICghbWFwRm4pIHtcblx0XHRcdGlmIChpc0FyZ3VtZW50cyhhcnJheUxpa2UpKSB7XG5cdFx0XHRcdC8vIFNvdXJjZTogQXJndW1lbnRzXG5cdFx0XHRcdGxlbmd0aCA9IGFycmF5TGlrZS5sZW5ndGg7XG5cdFx0XHRcdGlmIChsZW5ndGggIT09IDEpIHJldHVybiBBcnJheS5hcHBseShudWxsLCBhcnJheUxpa2UpO1xuXHRcdFx0XHRhcnIgPSBuZXcgQXJyYXkoMSk7XG5cdFx0XHRcdGFyclswXSA9IGFycmF5TGlrZVswXTtcblx0XHRcdFx0cmV0dXJuIGFycjtcblx0XHRcdH1cblx0XHRcdGlmIChpc0FycmF5KGFycmF5TGlrZSkpIHtcblx0XHRcdFx0Ly8gU291cmNlOiBBcnJheVxuXHRcdFx0XHRhcnIgPSBuZXcgQXJyYXkobGVuZ3RoID0gYXJyYXlMaWtlLmxlbmd0aCk7XG5cdFx0XHRcdGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgYXJyW2ldID0gYXJyYXlMaWtlW2ldO1xuXHRcdFx0XHRyZXR1cm4gYXJyO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRhcnIgPSBbXTtcblx0fSBlbHNlIHtcblx0XHQvLyBSZXN1bHQ6IE5vbiBwbGFpbiBhcnJheVxuXHRcdENvbnRleHQgPSB0aGlzO1xuXHR9XG5cblx0aWYgKCFpc0FycmF5KGFycmF5TGlrZSkpIHtcblx0XHRpZiAoKGdldEl0ZXJhdG9yID0gYXJyYXlMaWtlW2l0ZXJhdG9yU3ltYm9sXSkgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0Ly8gU291cmNlOiBJdGVyYXRvclxuXHRcdFx0aXRlcmF0b3IgPSBjYWxsYWJsZShnZXRJdGVyYXRvcikuY2FsbChhcnJheUxpa2UpO1xuXHRcdFx0aWYgKENvbnRleHQpIGFyciA9IG5ldyBDb250ZXh0KCk7XG5cdFx0XHRyZXN1bHQgPSBpdGVyYXRvci5uZXh0KCk7XG5cdFx0XHRpID0gMDtcblx0XHRcdHdoaWxlICghcmVzdWx0LmRvbmUpIHtcblx0XHRcdFx0dmFsdWUgPSBtYXBGbiA/IGNhbGwuY2FsbChtYXBGbiwgdGhpc0FyZywgcmVzdWx0LnZhbHVlLCBpKSA6IHJlc3VsdC52YWx1ZTtcblx0XHRcdFx0aWYgKENvbnRleHQpIHtcblx0XHRcdFx0XHRkZXNjLnZhbHVlID0gdmFsdWU7XG5cdFx0XHRcdFx0ZGVmaW5lUHJvcGVydHkoYXJyLCBpLCBkZXNjKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhcnJbaV0gPSB2YWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXN1bHQgPSBpdGVyYXRvci5uZXh0KCk7XG5cdFx0XHRcdCsraTtcblx0XHRcdH1cblx0XHRcdGxlbmd0aCA9IGk7XG5cdFx0fSBlbHNlIGlmIChpc1N0cmluZyhhcnJheUxpa2UpKSB7XG5cdFx0XHQvLyBTb3VyY2U6IFN0cmluZ1xuXHRcdFx0bGVuZ3RoID0gYXJyYXlMaWtlLmxlbmd0aDtcblx0XHRcdGlmIChDb250ZXh0KSBhcnIgPSBuZXcgQ29udGV4dCgpO1xuXHRcdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuXHRcdFx0XHR2YWx1ZSA9IGFycmF5TGlrZVtpXTtcblx0XHRcdFx0aWYgKGkgKyAxIDwgbGVuZ3RoKSB7XG5cdFx0XHRcdFx0Y29kZSA9IHZhbHVlLmNoYXJDb2RlQXQoMCk7XG5cdFx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1kZXB0aFxuXHRcdFx0XHRcdGlmIChjb2RlID49IDB4ZDgwMCAmJiBjb2RlIDw9IDB4ZGJmZikgdmFsdWUgKz0gYXJyYXlMaWtlWysraV07XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFsdWUgPSBtYXBGbiA/IGNhbGwuY2FsbChtYXBGbiwgdGhpc0FyZywgdmFsdWUsIGopIDogdmFsdWU7XG5cdFx0XHRcdGlmIChDb250ZXh0KSB7XG5cdFx0XHRcdFx0ZGVzYy52YWx1ZSA9IHZhbHVlO1xuXHRcdFx0XHRcdGRlZmluZVByb3BlcnR5KGFyciwgaiwgZGVzYyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0YXJyW2pdID0gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0KytqO1xuXHRcdFx0fVxuXHRcdFx0bGVuZ3RoID0gajtcblx0XHR9XG5cdH1cblx0aWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0Ly8gU291cmNlOiBhcnJheSBvciBhcnJheS1saWtlXG5cdFx0bGVuZ3RoID0gdG9Qb3NJbnQoYXJyYXlMaWtlLmxlbmd0aCk7XG5cdFx0aWYgKENvbnRleHQpIGFyciA9IG5ldyBDb250ZXh0KGxlbmd0aCk7XG5cdFx0Zm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG5cdFx0XHR2YWx1ZSA9IG1hcEZuID8gY2FsbC5jYWxsKG1hcEZuLCB0aGlzQXJnLCBhcnJheUxpa2VbaV0sIGkpIDogYXJyYXlMaWtlW2ldO1xuXHRcdFx0aWYgKENvbnRleHQpIHtcblx0XHRcdFx0ZGVzYy52YWx1ZSA9IHZhbHVlO1xuXHRcdFx0XHRkZWZpbmVQcm9wZXJ0eShhcnIsIGksIGRlc2MpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXJyW2ldID0gdmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGlmIChDb250ZXh0KSB7XG5cdFx0ZGVzYy52YWx1ZSA9IG51bGw7XG5cdFx0YXJyLmxlbmd0aCA9IGxlbmd0aDtcblx0fVxuXHRyZXR1cm4gYXJyO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgb2JqVG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nXG4gICwgaWQgPSBvYmpUb1N0cmluZy5jYWxsKFxuXHQoZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBhcmd1bWVudHM7XG5cdH0pKClcbik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdHJldHVybiBvYmpUb1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gaWQ7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBvYmpUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcsIGlkID0gb2JqVG9TdHJpbmcuY2FsbChyZXF1aXJlKFwiLi9ub29wXCIpKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0cmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiICYmIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09PSBpZDtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVtcHR5LWZ1bmN0aW9uXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHt9O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IE1hdGguc2lnblxuXHQ6IHJlcXVpcmUoXCIuL3NoaW1cIik7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzaWduID0gTWF0aC5zaWduO1xuXHRpZiAodHlwZW9mIHNpZ24gIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGZhbHNlO1xuXHRyZXR1cm4gKHNpZ24oMTApID09PSAxKSAmJiAoc2lnbigtMjApID09PSAtMSk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdHZhbHVlID0gTnVtYmVyKHZhbHVlKTtcblx0aWYgKGlzTmFOKHZhbHVlKSB8fCAodmFsdWUgPT09IDApKSByZXR1cm4gdmFsdWU7XG5cdHJldHVybiB2YWx1ZSA+IDAgPyAxIDogLTE7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzaWduID0gcmVxdWlyZShcIi4uL21hdGgvc2lnblwiKVxuXG4gICwgYWJzID0gTWF0aC5hYnMsIGZsb29yID0gTWF0aC5mbG9vcjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKGlzTmFOKHZhbHVlKSkgcmV0dXJuIDA7XG5cdHZhbHVlID0gTnVtYmVyKHZhbHVlKTtcblx0aWYgKCh2YWx1ZSA9PT0gMCkgfHwgIWlzRmluaXRlKHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xuXHRyZXR1cm4gc2lnbih2YWx1ZSkgKiBmbG9vcihhYnModmFsdWUpKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoXCIuL3RvLWludGVnZXJcIilcblxuICAsIG1heCA9IE1hdGgubWF4O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuIHJldHVybiBtYXgoMCwgdG9JbnRlZ2VyKHZhbHVlKSk7XG59O1xuIiwiLy8gSW50ZXJuYWwgbWV0aG9kLCB1c2VkIGJ5IGl0ZXJhdGlvbiBmdW5jdGlvbnMuXG4vLyBDYWxscyBhIGZ1bmN0aW9uIGZvciBlYWNoIGtleS12YWx1ZSBwYWlyIGZvdW5kIGluIG9iamVjdFxuLy8gT3B0aW9uYWxseSB0YWtlcyBjb21wYXJlRm4gdG8gaXRlcmF0ZSBvYmplY3QgaW4gc3BlY2lmaWMgb3JkZXJcblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjYWxsYWJsZSAgICAgICAgICAgICAgICA9IHJlcXVpcmUoXCIuL3ZhbGlkLWNhbGxhYmxlXCIpXG4gICwgdmFsdWUgICAgICAgICAgICAgICAgICAgPSByZXF1aXJlKFwiLi92YWxpZC12YWx1ZVwiKVxuICAsIGJpbmQgICAgICAgICAgICAgICAgICAgID0gRnVuY3Rpb24ucHJvdG90eXBlLmJpbmRcbiAgLCBjYWxsICAgICAgICAgICAgICAgICAgICA9IEZ1bmN0aW9uLnByb3RvdHlwZS5jYWxsXG4gICwga2V5cyAgICAgICAgICAgICAgICAgICAgPSBPYmplY3Qua2V5c1xuICAsIG9ialByb3BlcnR5SXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobWV0aG9kLCBkZWZWYWwpIHtcblx0cmV0dXJuIGZ1bmN0aW9uIChvYmosIGNiIC8qLCB0aGlzQXJnLCBjb21wYXJlRm4qLykge1xuXHRcdHZhciBsaXN0LCB0aGlzQXJnID0gYXJndW1lbnRzWzJdLCBjb21wYXJlRm4gPSBhcmd1bWVudHNbM107XG5cdFx0b2JqID0gT2JqZWN0KHZhbHVlKG9iaikpO1xuXHRcdGNhbGxhYmxlKGNiKTtcblxuXHRcdGxpc3QgPSBrZXlzKG9iaik7XG5cdFx0aWYgKGNvbXBhcmVGbikge1xuXHRcdFx0bGlzdC5zb3J0KHR5cGVvZiBjb21wYXJlRm4gPT09IFwiZnVuY3Rpb25cIiA/IGJpbmQuY2FsbChjb21wYXJlRm4sIG9iaikgOiB1bmRlZmluZWQpO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIG1ldGhvZCAhPT0gXCJmdW5jdGlvblwiKSBtZXRob2QgPSBsaXN0W21ldGhvZF07XG5cdFx0cmV0dXJuIGNhbGwuY2FsbChtZXRob2QsIGxpc3QsIGZ1bmN0aW9uIChrZXksIGluZGV4KSB7XG5cdFx0XHRpZiAoIW9ialByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqLCBrZXkpKSByZXR1cm4gZGVmVmFsO1xuXHRcdFx0cmV0dXJuIGNhbGwuY2FsbChjYiwgdGhpc0FyZywgb2JqW2tleV0sIGtleSwgb2JqLCBpbmRleCk7XG5cdFx0fSk7XG5cdH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IE9iamVjdC5hc3NpZ25cblx0OiByZXF1aXJlKFwiLi9zaGltXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgYXNzaWduID0gT2JqZWN0LmFzc2lnbiwgb2JqO1xuXHRpZiAodHlwZW9mIGFzc2lnbiAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdG9iaiA9IHsgZm9vOiBcInJhelwiIH07XG5cdGFzc2lnbihvYmosIHsgYmFyOiBcImR3YVwiIH0sIHsgdHJ6eTogXCJ0cnp5XCIgfSk7XG5cdHJldHVybiAob2JqLmZvbyArIG9iai5iYXIgKyBvYmoudHJ6eSkgPT09IFwicmF6ZHdhdHJ6eVwiO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIga2V5cyAgPSByZXF1aXJlKFwiLi4va2V5c1wiKVxuICAsIHZhbHVlID0gcmVxdWlyZShcIi4uL3ZhbGlkLXZhbHVlXCIpXG4gICwgbWF4ICAgPSBNYXRoLm1heDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZGVzdCwgc3JjIC8qLCDigKZzcmNuKi8pIHtcblx0dmFyIGVycm9yLCBpLCBsZW5ndGggPSBtYXgoYXJndW1lbnRzLmxlbmd0aCwgMiksIGFzc2lnbjtcblx0ZGVzdCA9IE9iamVjdCh2YWx1ZShkZXN0KSk7XG5cdGFzc2lnbiA9IGZ1bmN0aW9uIChrZXkpIHtcblx0XHR0cnkge1xuXHRcdFx0ZGVzdFtrZXldID0gc3JjW2tleV07XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0aWYgKCFlcnJvcikgZXJyb3IgPSBlO1xuXHRcdH1cblx0fTtcblx0Zm9yIChpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7XG5cdFx0c3JjID0gYXJndW1lbnRzW2ldO1xuXHRcdGtleXMoc3JjKS5mb3JFYWNoKGFzc2lnbik7XG5cdH1cblx0aWYgKGVycm9yICE9PSB1bmRlZmluZWQpIHRocm93IGVycm9yO1xuXHRyZXR1cm4gZGVzdDtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGFGcm9tICA9IHJlcXVpcmUoXCIuLi9hcnJheS9mcm9tXCIpXG4gICwgYXNzaWduID0gcmVxdWlyZShcIi4vYXNzaWduXCIpXG4gICwgdmFsdWUgID0gcmVxdWlyZShcIi4vdmFsaWQtdmFsdWVcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iai8qLCBwcm9wZXJ0eU5hbWVzLCBvcHRpb25zKi8pIHtcblx0dmFyIGNvcHkgPSBPYmplY3QodmFsdWUob2JqKSksIHByb3BlcnR5TmFtZXMgPSBhcmd1bWVudHNbMV0sIG9wdGlvbnMgPSBPYmplY3QoYXJndW1lbnRzWzJdKTtcblx0aWYgKGNvcHkgIT09IG9iaiAmJiAhcHJvcGVydHlOYW1lcykgcmV0dXJuIGNvcHk7XG5cdHZhciByZXN1bHQgPSB7fTtcblx0aWYgKHByb3BlcnR5TmFtZXMpIHtcblx0XHRhRnJvbShwcm9wZXJ0eU5hbWVzLCBmdW5jdGlvbiAocHJvcGVydHlOYW1lKSB7XG5cdFx0XHRpZiAob3B0aW9ucy5lbnN1cmUgfHwgcHJvcGVydHlOYW1lIGluIG9iaikgcmVzdWx0W3Byb3BlcnR5TmFtZV0gPSBvYmpbcHJvcGVydHlOYW1lXTtcblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHRhc3NpZ24ocmVzdWx0LCBvYmopO1xuXHR9XG5cdHJldHVybiByZXN1bHQ7XG59O1xuIiwiLy8gV29ya2Fyb3VuZCBmb3IgaHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjgwNFxuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGUsIHNoaW07XG5cbmlmICghcmVxdWlyZShcIi4vc2V0LXByb3RvdHlwZS1vZi9pcy1pbXBsZW1lbnRlZFwiKSgpKSB7XG5cdHNoaW0gPSByZXF1aXJlKFwiLi9zZXQtcHJvdG90eXBlLW9mL3NoaW1cIik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uICgpIHtcblx0dmFyIG51bGxPYmplY3QsIHBvbHlQcm9wcywgZGVzYztcblx0aWYgKCFzaGltKSByZXR1cm4gY3JlYXRlO1xuXHRpZiAoc2hpbS5sZXZlbCAhPT0gMSkgcmV0dXJuIGNyZWF0ZTtcblxuXHRudWxsT2JqZWN0ID0ge307XG5cdHBvbHlQcm9wcyA9IHt9O1xuXHRkZXNjID0ge1xuXHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG5cdFx0ZW51bWVyYWJsZTogZmFsc2UsXG5cdFx0d3JpdGFibGU6IHRydWUsXG5cdFx0dmFsdWU6IHVuZGVmaW5lZFxuXHR9O1xuXHRPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhPYmplY3QucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0aWYgKG5hbWUgPT09IFwiX19wcm90b19fXCIpIHtcblx0XHRcdHBvbHlQcm9wc1tuYW1lXSA9IHtcblx0XHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRlbnVtZXJhYmxlOiBmYWxzZSxcblx0XHRcdFx0d3JpdGFibGU6IHRydWUsXG5cdFx0XHRcdHZhbHVlOiB1bmRlZmluZWRcblx0XHRcdH07XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHBvbHlQcm9wc1tuYW1lXSA9IGRlc2M7XG5cdH0pO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydGllcyhudWxsT2JqZWN0LCBwb2x5UHJvcHMpO1xuXG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzaGltLCBcIm51bGxQb2x5ZmlsbFwiLCB7XG5cdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcblx0XHRlbnVtZXJhYmxlOiBmYWxzZSxcblx0XHR3cml0YWJsZTogZmFsc2UsXG5cdFx0dmFsdWU6IG51bGxPYmplY3Rcblx0fSk7XG5cblx0cmV0dXJuIGZ1bmN0aW9uIChwcm90b3R5cGUsIHByb3BzKSB7XG5cdFx0cmV0dXJuIGNyZWF0ZShwcm90b3R5cGUgPT09IG51bGwgPyBudWxsT2JqZWN0IDogcHJvdG90eXBlLCBwcm9wcyk7XG5cdH07XG59KCkpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vX2l0ZXJhdGVcIikoXCJmb3JFYWNoXCIpO1xuIiwiLy8gRGVwcmVjYXRlZFxuXG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gcmV0dXJuIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIjtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGlzVmFsdWUgPSByZXF1aXJlKFwiLi9pcy12YWx1ZVwiKTtcblxudmFyIG1hcCA9IHsgZnVuY3Rpb246IHRydWUsIG9iamVjdDogdHJ1ZSB9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRyZXR1cm4gKGlzVmFsdWUodmFsdWUpICYmIG1hcFt0eXBlb2YgdmFsdWVdKSB8fCBmYWxzZTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF91bmRlZmluZWQgPSByZXF1aXJlKFwiLi4vZnVuY3Rpb24vbm9vcFwiKSgpOyAvLyBTdXBwb3J0IEVTMyBlbmdpbmVzXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbCkge1xuIHJldHVybiAodmFsICE9PSBfdW5kZWZpbmVkKSAmJiAodmFsICE9PSBudWxsKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiLi9pcy1pbXBsZW1lbnRlZFwiKSgpID8gT2JqZWN0LmtleXMgOiByZXF1aXJlKFwiLi9zaGltXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR0cnkge1xuXHRcdE9iamVjdC5rZXlzKFwicHJpbWl0aXZlXCIpO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc1ZhbHVlID0gcmVxdWlyZShcIi4uL2lzLXZhbHVlXCIpO1xuXG52YXIga2V5cyA9IE9iamVjdC5rZXlzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QpIHsgcmV0dXJuIGtleXMoaXNWYWx1ZShvYmplY3QpID8gT2JqZWN0KG9iamVjdCkgOiBvYmplY3QpOyB9O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjYWxsYWJsZSA9IHJlcXVpcmUoXCIuL3ZhbGlkLWNhbGxhYmxlXCIpXG4gICwgZm9yRWFjaCAgPSByZXF1aXJlKFwiLi9mb3ItZWFjaFwiKVxuICAsIGNhbGwgICAgID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGw7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaiwgY2IgLyosIHRoaXNBcmcqLykge1xuXHR2YXIgcmVzdWx0ID0ge30sIHRoaXNBcmcgPSBhcmd1bWVudHNbMl07XG5cdGNhbGxhYmxlKGNiKTtcblx0Zm9yRWFjaChvYmosIGZ1bmN0aW9uICh2YWx1ZSwga2V5LCB0YXJnZXRPYmosIGluZGV4KSB7XG5cdFx0cmVzdWx0W2tleV0gPSBjYWxsLmNhbGwoY2IsIHRoaXNBcmcsIHZhbHVlLCBrZXksIHRhcmdldE9iaiwgaW5kZXgpO1xuXHR9KTtcblx0cmV0dXJuIHJlc3VsdDtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGlzVmFsdWUgPSByZXF1aXJlKFwiLi9pcy12YWx1ZVwiKTtcblxudmFyIGZvckVhY2ggPSBBcnJheS5wcm90b3R5cGUuZm9yRWFjaCwgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZTtcblxudmFyIHByb2Nlc3MgPSBmdW5jdGlvbiAoc3JjLCBvYmopIHtcblx0dmFyIGtleTtcblx0Zm9yIChrZXkgaW4gc3JjKSBvYmpba2V5XSA9IHNyY1trZXldO1xufTtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvcHRzMSAvKiwg4oCmb3B0aW9ucyovKSB7XG5cdHZhciByZXN1bHQgPSBjcmVhdGUobnVsbCk7XG5cdGZvckVhY2guY2FsbChhcmd1bWVudHMsIGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdFx0aWYgKCFpc1ZhbHVlKG9wdGlvbnMpKSByZXR1cm47XG5cdFx0cHJvY2VzcyhPYmplY3Qob3B0aW9ucyksIHJlc3VsdCk7XG5cdH0pO1xuXHRyZXR1cm4gcmVzdWx0O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCIuL2lzLWltcGxlbWVudGVkXCIpKClcblx0PyBPYmplY3Quc2V0UHJvdG90eXBlT2Zcblx0OiByZXF1aXJlKFwiLi9zaGltXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjcmVhdGUgPSBPYmplY3QuY3JlYXRlLCBnZXRQcm90b3R5cGVPZiA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiwgcGxhaW5PYmplY3QgPSB7fTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoLyogQ3VzdG9tQ3JlYXRlKi8pIHtcblx0dmFyIHNldFByb3RvdHlwZU9mID0gT2JqZWN0LnNldFByb3RvdHlwZU9mLCBjdXN0b21DcmVhdGUgPSBhcmd1bWVudHNbMF0gfHwgY3JlYXRlO1xuXHRpZiAodHlwZW9mIHNldFByb3RvdHlwZU9mICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBmYWxzZTtcblx0cmV0dXJuIGdldFByb3RvdHlwZU9mKHNldFByb3RvdHlwZU9mKGN1c3RvbUNyZWF0ZShudWxsKSwgcGxhaW5PYmplY3QpKSA9PT0gcGxhaW5PYmplY3Q7XG59O1xuIiwiLyogZXNsaW50IG5vLXByb3RvOiBcIm9mZlwiICovXG5cbi8vIEJpZyB0aGFua3MgdG8gQFdlYlJlZmxlY3Rpb24gZm9yIHNvcnRpbmcgdGhpcyBvdXRcbi8vIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL1dlYlJlZmxlY3Rpb24vNTU5MzU1NFxuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGlzT2JqZWN0ICAgICAgICA9IHJlcXVpcmUoXCIuLi9pcy1vYmplY3RcIilcbiAgLCB2YWx1ZSAgICAgICAgICAgPSByZXF1aXJlKFwiLi4vdmFsaWQtdmFsdWVcIilcbiAgLCBvYmpJc1Byb3RvdHlwZU9mID0gT2JqZWN0LnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mXG4gICwgZGVmaW5lUHJvcGVydHkgID0gT2JqZWN0LmRlZmluZVByb3BlcnR5XG4gICwgbnVsbERlc2MgICAgICAgID0ge1xuXHRjb25maWd1cmFibGU6IHRydWUsXG5cdGVudW1lcmFibGU6IGZhbHNlLFxuXHR3cml0YWJsZTogdHJ1ZSxcblx0dmFsdWU6IHVuZGVmaW5lZFxufVxuICAsIHZhbGlkYXRlO1xuXG52YWxpZGF0ZSA9IGZ1bmN0aW9uIChvYmosIHByb3RvdHlwZSkge1xuXHR2YWx1ZShvYmopO1xuXHRpZiAocHJvdG90eXBlID09PSBudWxsIHx8IGlzT2JqZWN0KHByb3RvdHlwZSkpIHJldHVybiBvYmo7XG5cdHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcm90b3R5cGUgbXVzdCBiZSBudWxsIG9yIGFuIG9iamVjdFwiKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIChzdGF0dXMpIHtcblx0dmFyIGZuLCBzZXQ7XG5cdGlmICghc3RhdHVzKSByZXR1cm4gbnVsbDtcblx0aWYgKHN0YXR1cy5sZXZlbCA9PT0gMikge1xuXHRcdGlmIChzdGF0dXMuc2V0KSB7XG5cdFx0XHRzZXQgPSBzdGF0dXMuc2V0O1xuXHRcdFx0Zm4gPSBmdW5jdGlvbiAob2JqLCBwcm90b3R5cGUpIHtcblx0XHRcdFx0c2V0LmNhbGwodmFsaWRhdGUob2JqLCBwcm90b3R5cGUpLCBwcm90b3R5cGUpO1xuXHRcdFx0XHRyZXR1cm4gb2JqO1xuXHRcdFx0fTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm4gPSBmdW5jdGlvbiAob2JqLCBwcm90b3R5cGUpIHtcblx0XHRcdFx0dmFsaWRhdGUob2JqLCBwcm90b3R5cGUpLl9fcHJvdG9fXyA9IHByb3RvdHlwZTtcblx0XHRcdFx0cmV0dXJuIG9iajtcblx0XHRcdH07XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdGZuID0gZnVuY3Rpb24gc2VsZihvYmosIHByb3RvdHlwZSkge1xuXHRcdFx0dmFyIGlzTnVsbEJhc2U7XG5cdFx0XHR2YWxpZGF0ZShvYmosIHByb3RvdHlwZSk7XG5cdFx0XHRpc051bGxCYXNlID0gb2JqSXNQcm90b3R5cGVPZi5jYWxsKHNlbGYubnVsbFBvbHlmaWxsLCBvYmopO1xuXHRcdFx0aWYgKGlzTnVsbEJhc2UpIGRlbGV0ZSBzZWxmLm51bGxQb2x5ZmlsbC5fX3Byb3RvX187XG5cdFx0XHRpZiAocHJvdG90eXBlID09PSBudWxsKSBwcm90b3R5cGUgPSBzZWxmLm51bGxQb2x5ZmlsbDtcblx0XHRcdG9iai5fX3Byb3RvX18gPSBwcm90b3R5cGU7XG5cdFx0XHRpZiAoaXNOdWxsQmFzZSkgZGVmaW5lUHJvcGVydHkoc2VsZi5udWxsUG9seWZpbGwsIFwiX19wcm90b19fXCIsIG51bGxEZXNjKTtcblx0XHRcdHJldHVybiBvYmo7XG5cdFx0fTtcblx0fVxuXHRyZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGZuLCBcImxldmVsXCIsIHtcblx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuXHRcdGVudW1lcmFibGU6IGZhbHNlLFxuXHRcdHdyaXRhYmxlOiBmYWxzZSxcblx0XHR2YWx1ZTogc3RhdHVzLmxldmVsXG5cdH0pO1xufShcblx0KGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgdG1wT2JqMSA9IE9iamVjdC5jcmVhdGUobnVsbClcblx0XHQgICwgdG1wT2JqMiA9IHt9XG5cdFx0ICAsIHNldFxuXHRcdCAgLCBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPYmplY3QucHJvdG90eXBlLCBcIl9fcHJvdG9fX1wiKTtcblxuXHRcdGlmIChkZXNjKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRzZXQgPSBkZXNjLnNldDsgLy8gT3BlcmEgY3Jhc2hlcyBhdCB0aGlzIHBvaW50XG5cdFx0XHRcdHNldC5jYWxsKHRtcE9iajEsIHRtcE9iajIpO1xuXHRcdFx0fSBjYXRjaCAoaWdub3JlKSB7fVxuXHRcdFx0aWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih0bXBPYmoxKSA9PT0gdG1wT2JqMikgcmV0dXJuIHsgc2V0OiBzZXQsIGxldmVsOiAyIH07XG5cdFx0fVxuXG5cdFx0dG1wT2JqMS5fX3Byb3RvX18gPSB0bXBPYmoyO1xuXHRcdGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YodG1wT2JqMSkgPT09IHRtcE9iajIpIHJldHVybiB7IGxldmVsOiAyIH07XG5cblx0XHR0bXBPYmoxID0ge307XG5cdFx0dG1wT2JqMS5fX3Byb3RvX18gPSB0bXBPYmoyO1xuXHRcdGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YodG1wT2JqMSkgPT09IHRtcE9iajIpIHJldHVybiB7IGxldmVsOiAxIH07XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0pKClcbikpO1xuXG5yZXF1aXJlKFwiLi4vY3JlYXRlXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG5cdGlmICh0eXBlb2YgZm4gIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihmbiArIFwiIGlzIG5vdCBhIGZ1bmN0aW9uXCIpO1xuXHRyZXR1cm4gZm47XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc09iamVjdCA9IHJlcXVpcmUoXCIuL2lzLW9iamVjdFwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKCFpc09iamVjdCh2YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IodmFsdWUgKyBcIiBpcyBub3QgYW4gT2JqZWN0XCIpO1xuXHRyZXR1cm4gdmFsdWU7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc1ZhbHVlID0gcmVxdWlyZShcIi4vaXMtdmFsdWVcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdGlmICghaXNWYWx1ZSh2YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgdXNlIG51bGwgb3IgdW5kZWZpbmVkXCIpO1xuXHRyZXR1cm4gdmFsdWU7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IFN0cmluZy5wcm90b3R5cGUuY29udGFpbnNcblx0OiByZXF1aXJlKFwiLi9zaGltXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzdHIgPSBcInJhemR3YXRyenlcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdGlmICh0eXBlb2Ygc3RyLmNvbnRhaW5zICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBmYWxzZTtcblx0cmV0dXJuIChzdHIuY29udGFpbnMoXCJkd2FcIikgPT09IHRydWUpICYmIChzdHIuY29udGFpbnMoXCJmb29cIikgPT09IGZhbHNlKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGluZGV4T2YgPSBTdHJpbmcucHJvdG90eXBlLmluZGV4T2Y7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHNlYXJjaFN0cmluZy8qLCBwb3NpdGlvbiovKSB7XG5cdHJldHVybiBpbmRleE9mLmNhbGwodGhpcywgc2VhcmNoU3RyaW5nLCBhcmd1bWVudHNbMV0pID4gLTE7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBvYmpUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcsIGlkID0gb2JqVG9TdHJpbmcuY2FsbChcIlwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0cmV0dXJuIChcblx0XHR0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHxcblx0XHQodmFsdWUgJiZcblx0XHRcdHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJlxuXHRcdFx0KHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nIHx8IG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09PSBpZCkpIHx8XG5cdFx0ZmFsc2Vcblx0KTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGdlbmVyYXRlZCA9IE9iamVjdC5jcmVhdGUobnVsbCksIHJhbmRvbSA9IE1hdGgucmFuZG9tO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIHN0cjtcblx0ZG8ge1xuXHRcdHN0ciA9IHJhbmRvbSgpXG5cdFx0XHQudG9TdHJpbmcoMzYpXG5cdFx0XHQuc2xpY2UoMik7XG5cdH0gd2hpbGUgKGdlbmVyYXRlZFtzdHJdKTtcblx0cmV0dXJuIHN0cjtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIHNldFByb3RvdHlwZU9mID0gcmVxdWlyZShcImVzNS1leHQvb2JqZWN0L3NldC1wcm90b3R5cGUtb2ZcIilcbiAgLCBjb250YWlucyAgICAgICA9IHJlcXVpcmUoXCJlczUtZXh0L3N0cmluZy8jL2NvbnRhaW5zXCIpXG4gICwgZCAgICAgICAgICAgICAgPSByZXF1aXJlKFwiZFwiKVxuICAsIFN5bWJvbCAgICAgICAgID0gcmVxdWlyZShcImVzNi1zeW1ib2xcIilcbiAgLCBJdGVyYXRvciAgICAgICA9IHJlcXVpcmUoXCIuL1wiKTtcblxudmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5LCBBcnJheUl0ZXJhdG9yO1xuXG5BcnJheUl0ZXJhdG9yID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJyLCBraW5kKSB7XG5cdGlmICghKHRoaXMgaW5zdGFuY2VvZiBBcnJheUl0ZXJhdG9yKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNvbnN0cnVjdG9yIHJlcXVpcmVzICduZXcnXCIpO1xuXHRJdGVyYXRvci5jYWxsKHRoaXMsIGFycik7XG5cdGlmICgha2luZCkga2luZCA9IFwidmFsdWVcIjtcblx0ZWxzZSBpZiAoY29udGFpbnMuY2FsbChraW5kLCBcImtleSt2YWx1ZVwiKSkga2luZCA9IFwia2V5K3ZhbHVlXCI7XG5cdGVsc2UgaWYgKGNvbnRhaW5zLmNhbGwoa2luZCwgXCJrZXlcIikpIGtpbmQgPSBcImtleVwiO1xuXHRlbHNlIGtpbmQgPSBcInZhbHVlXCI7XG5cdGRlZmluZVByb3BlcnR5KHRoaXMsIFwiX19raW5kX19cIiwgZChcIlwiLCBraW5kKSk7XG59O1xuaWYgKHNldFByb3RvdHlwZU9mKSBzZXRQcm90b3R5cGVPZihBcnJheUl0ZXJhdG9yLCBJdGVyYXRvcik7XG5cbi8vIEludGVybmFsICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJSBkb2Vzbid0IGV4cG9zZSBpdHMgY29uc3RydWN0b3JcbmRlbGV0ZSBBcnJheUl0ZXJhdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvcjtcblxuQXJyYXlJdGVyYXRvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEl0ZXJhdG9yLnByb3RvdHlwZSwge1xuXHRfcmVzb2x2ZTogZChmdW5jdGlvbiAoaSkge1xuXHRcdGlmICh0aGlzLl9fa2luZF9fID09PSBcInZhbHVlXCIpIHJldHVybiB0aGlzLl9fbGlzdF9fW2ldO1xuXHRcdGlmICh0aGlzLl9fa2luZF9fID09PSBcImtleSt2YWx1ZVwiKSByZXR1cm4gW2ksIHRoaXMuX19saXN0X19baV1dO1xuXHRcdHJldHVybiBpO1xuXHR9KVxufSk7XG5kZWZpbmVQcm9wZXJ0eShBcnJheUl0ZXJhdG9yLnByb3RvdHlwZSwgU3ltYm9sLnRvU3RyaW5nVGFnLCBkKFwiY1wiLCBcIkFycmF5IEl0ZXJhdG9yXCIpKTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNBcmd1bWVudHMgPSByZXF1aXJlKFwiZXM1LWV4dC9mdW5jdGlvbi9pcy1hcmd1bWVudHNcIilcbiAgLCBjYWxsYWJsZSAgICA9IHJlcXVpcmUoXCJlczUtZXh0L29iamVjdC92YWxpZC1jYWxsYWJsZVwiKVxuICAsIGlzU3RyaW5nICAgID0gcmVxdWlyZShcImVzNS1leHQvc3RyaW5nL2lzLXN0cmluZ1wiKVxuICAsIGdldCAgICAgICAgID0gcmVxdWlyZShcIi4vZ2V0XCIpO1xuXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXksIGNhbGwgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbCwgc29tZSA9IEFycmF5LnByb3RvdHlwZS5zb21lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYWJsZSwgY2IgLyosIHRoaXNBcmcqLykge1xuXHR2YXIgbW9kZSwgdGhpc0FyZyA9IGFyZ3VtZW50c1syXSwgcmVzdWx0LCBkb0JyZWFrLCBicm9rZW4sIGksIGxlbmd0aCwgY2hhciwgY29kZTtcblx0aWYgKGlzQXJyYXkoaXRlcmFibGUpIHx8IGlzQXJndW1lbnRzKGl0ZXJhYmxlKSkgbW9kZSA9IFwiYXJyYXlcIjtcblx0ZWxzZSBpZiAoaXNTdHJpbmcoaXRlcmFibGUpKSBtb2RlID0gXCJzdHJpbmdcIjtcblx0ZWxzZSBpdGVyYWJsZSA9IGdldChpdGVyYWJsZSk7XG5cblx0Y2FsbGFibGUoY2IpO1xuXHRkb0JyZWFrID0gZnVuY3Rpb24gKCkge1xuXHRcdGJyb2tlbiA9IHRydWU7XG5cdH07XG5cdGlmIChtb2RlID09PSBcImFycmF5XCIpIHtcblx0XHRzb21lLmNhbGwoaXRlcmFibGUsIGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdFx0Y2FsbC5jYWxsKGNiLCB0aGlzQXJnLCB2YWx1ZSwgZG9CcmVhayk7XG5cdFx0XHRyZXR1cm4gYnJva2VuO1xuXHRcdH0pO1xuXHRcdHJldHVybjtcblx0fVxuXHRpZiAobW9kZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdGxlbmd0aCA9IGl0ZXJhYmxlLmxlbmd0aDtcblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcblx0XHRcdGNoYXIgPSBpdGVyYWJsZVtpXTtcblx0XHRcdGlmIChpICsgMSA8IGxlbmd0aCkge1xuXHRcdFx0XHRjb2RlID0gY2hhci5jaGFyQ29kZUF0KDApO1xuXHRcdFx0XHRpZiAoY29kZSA+PSAweGQ4MDAgJiYgY29kZSA8PSAweGRiZmYpIGNoYXIgKz0gaXRlcmFibGVbKytpXTtcblx0XHRcdH1cblx0XHRcdGNhbGwuY2FsbChjYiwgdGhpc0FyZywgY2hhciwgZG9CcmVhayk7XG5cdFx0XHRpZiAoYnJva2VuKSBicmVhaztcblx0XHR9XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHJlc3VsdCA9IGl0ZXJhYmxlLm5leHQoKTtcblxuXHR3aGlsZSAoIXJlc3VsdC5kb25lKSB7XG5cdFx0Y2FsbC5jYWxsKGNiLCB0aGlzQXJnLCByZXN1bHQudmFsdWUsIGRvQnJlYWspO1xuXHRcdGlmIChicm9rZW4pIHJldHVybjtcblx0XHRyZXN1bHQgPSBpdGVyYWJsZS5uZXh0KCk7XG5cdH1cbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGlzQXJndW1lbnRzICAgID0gcmVxdWlyZShcImVzNS1leHQvZnVuY3Rpb24vaXMtYXJndW1lbnRzXCIpXG4gICwgaXNTdHJpbmcgICAgICAgPSByZXF1aXJlKFwiZXM1LWV4dC9zdHJpbmcvaXMtc3RyaW5nXCIpXG4gICwgQXJyYXlJdGVyYXRvciAgPSByZXF1aXJlKFwiLi9hcnJheVwiKVxuICAsIFN0cmluZ0l0ZXJhdG9yID0gcmVxdWlyZShcIi4vc3RyaW5nXCIpXG4gICwgaXRlcmFibGUgICAgICAgPSByZXF1aXJlKFwiLi92YWxpZC1pdGVyYWJsZVwiKVxuICAsIGl0ZXJhdG9yU3ltYm9sID0gcmVxdWlyZShcImVzNi1zeW1ib2xcIikuaXRlcmF0b3I7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaikge1xuXHRpZiAodHlwZW9mIGl0ZXJhYmxlKG9iailbaXRlcmF0b3JTeW1ib2xdID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBvYmpbaXRlcmF0b3JTeW1ib2xdKCk7XG5cdGlmIChpc0FyZ3VtZW50cyhvYmopKSByZXR1cm4gbmV3IEFycmF5SXRlcmF0b3Iob2JqKTtcblx0aWYgKGlzU3RyaW5nKG9iaikpIHJldHVybiBuZXcgU3RyaW5nSXRlcmF0b3Iob2JqKTtcblx0cmV0dXJuIG5ldyBBcnJheUl0ZXJhdG9yKG9iaik7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjbGVhciAgICA9IHJlcXVpcmUoXCJlczUtZXh0L2FycmF5LyMvY2xlYXJcIilcbiAgLCBhc3NpZ24gICA9IHJlcXVpcmUoXCJlczUtZXh0L29iamVjdC9hc3NpZ25cIilcbiAgLCBjYWxsYWJsZSA9IHJlcXVpcmUoXCJlczUtZXh0L29iamVjdC92YWxpZC1jYWxsYWJsZVwiKVxuICAsIHZhbHVlICAgID0gcmVxdWlyZShcImVzNS1leHQvb2JqZWN0L3ZhbGlkLXZhbHVlXCIpXG4gICwgZCAgICAgICAgPSByZXF1aXJlKFwiZFwiKVxuICAsIGF1dG9CaW5kID0gcmVxdWlyZShcImQvYXV0by1iaW5kXCIpXG4gICwgU3ltYm9sICAgPSByZXF1aXJlKFwiZXM2LXN5bWJvbFwiKTtcblxudmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5LCBkZWZpbmVQcm9wZXJ0aWVzID0gT2JqZWN0LmRlZmluZVByb3BlcnRpZXMsIEl0ZXJhdG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEl0ZXJhdG9yID0gZnVuY3Rpb24gKGxpc3QsIGNvbnRleHQpIHtcblx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIEl0ZXJhdG9yKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNvbnN0cnVjdG9yIHJlcXVpcmVzICduZXcnXCIpO1xuXHRkZWZpbmVQcm9wZXJ0aWVzKHRoaXMsIHtcblx0XHRfX2xpc3RfXzogZChcIndcIiwgdmFsdWUobGlzdCkpLFxuXHRcdF9fY29udGV4dF9fOiBkKFwid1wiLCBjb250ZXh0KSxcblx0XHRfX25leHRJbmRleF9fOiBkKFwid1wiLCAwKVxuXHR9KTtcblx0aWYgKCFjb250ZXh0KSByZXR1cm47XG5cdGNhbGxhYmxlKGNvbnRleHQub24pO1xuXHRjb250ZXh0Lm9uKFwiX2FkZFwiLCB0aGlzLl9vbkFkZCk7XG5cdGNvbnRleHQub24oXCJfZGVsZXRlXCIsIHRoaXMuX29uRGVsZXRlKTtcblx0Y29udGV4dC5vbihcIl9jbGVhclwiLCB0aGlzLl9vbkNsZWFyKTtcbn07XG5cbi8vIEludGVybmFsICVJdGVyYXRvclByb3RvdHlwZSUgZG9lc24ndCBleHBvc2UgaXRzIGNvbnN0cnVjdG9yXG5kZWxldGUgSXRlcmF0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yO1xuXG5kZWZpbmVQcm9wZXJ0aWVzKFxuXHRJdGVyYXRvci5wcm90b3R5cGUsXG5cdGFzc2lnbihcblx0XHR7XG5cdFx0XHRfbmV4dDogZChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHZhciBpO1xuXHRcdFx0XHRpZiAoIXRoaXMuX19saXN0X18pIHJldHVybiB1bmRlZmluZWQ7XG5cdFx0XHRcdGlmICh0aGlzLl9fcmVkb19fKSB7XG5cdFx0XHRcdFx0aSA9IHRoaXMuX19yZWRvX18uc2hpZnQoKTtcblx0XHRcdFx0XHRpZiAoaSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gaTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAodGhpcy5fX25leHRJbmRleF9fIDwgdGhpcy5fX2xpc3RfXy5sZW5ndGgpIHJldHVybiB0aGlzLl9fbmV4dEluZGV4X18rKztcblx0XHRcdFx0dGhpcy5fdW5CaW5kKCk7XG5cdFx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0XHR9KSxcblx0XHRcdG5leHQ6IGQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlUmVzdWx0KHRoaXMuX25leHQoKSk7XG5cdFx0XHR9KSxcblx0XHRcdF9jcmVhdGVSZXN1bHQ6IGQoZnVuY3Rpb24gKGkpIHtcblx0XHRcdFx0aWYgKGkgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHsgZG9uZTogdHJ1ZSwgdmFsdWU6IHVuZGVmaW5lZCB9O1xuXHRcdFx0XHRyZXR1cm4geyBkb25lOiBmYWxzZSwgdmFsdWU6IHRoaXMuX3Jlc29sdmUoaSkgfTtcblx0XHRcdH0pLFxuXHRcdFx0X3Jlc29sdmU6IGQoZnVuY3Rpb24gKGkpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX19saXN0X19baV07XG5cdFx0XHR9KSxcblx0XHRcdF91bkJpbmQ6IGQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLl9fbGlzdF9fID0gbnVsbDtcblx0XHRcdFx0ZGVsZXRlIHRoaXMuX19yZWRvX187XG5cdFx0XHRcdGlmICghdGhpcy5fX2NvbnRleHRfXykgcmV0dXJuO1xuXHRcdFx0XHR0aGlzLl9fY29udGV4dF9fLm9mZihcIl9hZGRcIiwgdGhpcy5fb25BZGQpO1xuXHRcdFx0XHR0aGlzLl9fY29udGV4dF9fLm9mZihcIl9kZWxldGVcIiwgdGhpcy5fb25EZWxldGUpO1xuXHRcdFx0XHR0aGlzLl9fY29udGV4dF9fLm9mZihcIl9jbGVhclwiLCB0aGlzLl9vbkNsZWFyKTtcblx0XHRcdFx0dGhpcy5fX2NvbnRleHRfXyA9IG51bGw7XG5cdFx0XHR9KSxcblx0XHRcdHRvU3RyaW5nOiBkKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cmV0dXJuIFwiW29iamVjdCBcIiArICh0aGlzW1N5bWJvbC50b1N0cmluZ1RhZ10gfHwgXCJPYmplY3RcIikgKyBcIl1cIjtcblx0XHRcdH0pXG5cdFx0fSxcblx0XHRhdXRvQmluZCh7XG5cdFx0XHRfb25BZGQ6IGQoZnVuY3Rpb24gKGluZGV4KSB7XG5cdFx0XHRcdGlmIChpbmRleCA+PSB0aGlzLl9fbmV4dEluZGV4X18pIHJldHVybjtcblx0XHRcdFx0Kyt0aGlzLl9fbmV4dEluZGV4X187XG5cdFx0XHRcdGlmICghdGhpcy5fX3JlZG9fXykge1xuXHRcdFx0XHRcdGRlZmluZVByb3BlcnR5KHRoaXMsIFwiX19yZWRvX19cIiwgZChcImNcIiwgW2luZGV4XSkpO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLl9fcmVkb19fLmZvckVhY2goZnVuY3Rpb24gKHJlZG8sIGkpIHtcblx0XHRcdFx0XHRpZiAocmVkbyA+PSBpbmRleCkgdGhpcy5fX3JlZG9fX1tpXSA9ICsrcmVkbztcblx0XHRcdFx0fSwgdGhpcyk7XG5cdFx0XHRcdHRoaXMuX19yZWRvX18ucHVzaChpbmRleCk7XG5cdFx0XHR9KSxcblx0XHRcdF9vbkRlbGV0ZTogZChmdW5jdGlvbiAoaW5kZXgpIHtcblx0XHRcdFx0dmFyIGk7XG5cdFx0XHRcdGlmIChpbmRleCA+PSB0aGlzLl9fbmV4dEluZGV4X18pIHJldHVybjtcblx0XHRcdFx0LS10aGlzLl9fbmV4dEluZGV4X187XG5cdFx0XHRcdGlmICghdGhpcy5fX3JlZG9fXykgcmV0dXJuO1xuXHRcdFx0XHRpID0gdGhpcy5fX3JlZG9fXy5pbmRleE9mKGluZGV4KTtcblx0XHRcdFx0aWYgKGkgIT09IC0xKSB0aGlzLl9fcmVkb19fLnNwbGljZShpLCAxKTtcblx0XHRcdFx0dGhpcy5fX3JlZG9fXy5mb3JFYWNoKGZ1bmN0aW9uIChyZWRvLCBqKSB7XG5cdFx0XHRcdFx0aWYgKHJlZG8gPiBpbmRleCkgdGhpcy5fX3JlZG9fX1tqXSA9IC0tcmVkbztcblx0XHRcdFx0fSwgdGhpcyk7XG5cdFx0XHR9KSxcblx0XHRcdF9vbkNsZWFyOiBkKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0aWYgKHRoaXMuX19yZWRvX18pIGNsZWFyLmNhbGwodGhpcy5fX3JlZG9fXyk7XG5cdFx0XHRcdHRoaXMuX19uZXh0SW5kZXhfXyA9IDA7XG5cdFx0XHR9KVxuXHRcdH0pXG5cdClcbik7XG5cbmRlZmluZVByb3BlcnR5KFxuXHRJdGVyYXRvci5wcm90b3R5cGUsXG5cdFN5bWJvbC5pdGVyYXRvcixcblx0ZChmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0pXG4pO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc0FyZ3VtZW50cyA9IHJlcXVpcmUoXCJlczUtZXh0L2Z1bmN0aW9uL2lzLWFyZ3VtZW50c1wiKVxuICAsIGlzVmFsdWUgICAgID0gcmVxdWlyZShcImVzNS1leHQvb2JqZWN0L2lzLXZhbHVlXCIpXG4gICwgaXNTdHJpbmcgICAgPSByZXF1aXJlKFwiZXM1LWV4dC9zdHJpbmcvaXMtc3RyaW5nXCIpO1xuXG52YXIgaXRlcmF0b3JTeW1ib2wgPSByZXF1aXJlKFwiZXM2LXN5bWJvbFwiKS5pdGVyYXRvclxuICAsIGlzQXJyYXkgICAgICAgID0gQXJyYXkuaXNBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKCFpc1ZhbHVlKHZhbHVlKSkgcmV0dXJuIGZhbHNlO1xuXHRpZiAoaXNBcnJheSh2YWx1ZSkpIHJldHVybiB0cnVlO1xuXHRpZiAoaXNTdHJpbmcodmFsdWUpKSByZXR1cm4gdHJ1ZTtcblx0aWYgKGlzQXJndW1lbnRzKHZhbHVlKSkgcmV0dXJuIHRydWU7XG5cdHJldHVybiB0eXBlb2YgdmFsdWVbaXRlcmF0b3JTeW1ib2xdID09PSBcImZ1bmN0aW9uXCI7XG59O1xuIiwiLy8gVGhhbmtzIEBtYXRoaWFzYnluZW5zXG4vLyBodHRwOi8vbWF0aGlhc2J5bmVucy5iZS9ub3Rlcy9qYXZhc2NyaXB0LXVuaWNvZGUjaXRlcmF0aW5nLW92ZXItc3ltYm9sc1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHNldFByb3RvdHlwZU9mID0gcmVxdWlyZShcImVzNS1leHQvb2JqZWN0L3NldC1wcm90b3R5cGUtb2ZcIilcbiAgLCBkICAgICAgICAgICAgICA9IHJlcXVpcmUoXCJkXCIpXG4gICwgU3ltYm9sICAgICAgICAgPSByZXF1aXJlKFwiZXM2LXN5bWJvbFwiKVxuICAsIEl0ZXJhdG9yICAgICAgID0gcmVxdWlyZShcIi4vXCIpO1xuXG52YXIgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHksIFN0cmluZ0l0ZXJhdG9yO1xuXG5TdHJpbmdJdGVyYXRvciA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0cikge1xuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgU3RyaW5nSXRlcmF0b3IpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ29uc3RydWN0b3IgcmVxdWlyZXMgJ25ldydcIik7XG5cdHN0ciA9IFN0cmluZyhzdHIpO1xuXHRJdGVyYXRvci5jYWxsKHRoaXMsIHN0cik7XG5cdGRlZmluZVByb3BlcnR5KHRoaXMsIFwiX19sZW5ndGhfX1wiLCBkKFwiXCIsIHN0ci5sZW5ndGgpKTtcbn07XG5pZiAoc2V0UHJvdG90eXBlT2YpIHNldFByb3RvdHlwZU9mKFN0cmluZ0l0ZXJhdG9yLCBJdGVyYXRvcik7XG5cbi8vIEludGVybmFsICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJSBkb2Vzbid0IGV4cG9zZSBpdHMgY29uc3RydWN0b3JcbmRlbGV0ZSBTdHJpbmdJdGVyYXRvci5wcm90b3R5cGUuY29uc3RydWN0b3I7XG5cblN0cmluZ0l0ZXJhdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSXRlcmF0b3IucHJvdG90eXBlLCB7XG5cdF9uZXh0OiBkKGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX19saXN0X18pIHJldHVybiB1bmRlZmluZWQ7XG5cdFx0aWYgKHRoaXMuX19uZXh0SW5kZXhfXyA8IHRoaXMuX19sZW5ndGhfXykgcmV0dXJuIHRoaXMuX19uZXh0SW5kZXhfXysrO1xuXHRcdHRoaXMuX3VuQmluZCgpO1xuXHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdH0pLFxuXHRfcmVzb2x2ZTogZChmdW5jdGlvbiAoaSkge1xuXHRcdHZhciBjaGFyID0gdGhpcy5fX2xpc3RfX1tpXSwgY29kZTtcblx0XHRpZiAodGhpcy5fX25leHRJbmRleF9fID09PSB0aGlzLl9fbGVuZ3RoX18pIHJldHVybiBjaGFyO1xuXHRcdGNvZGUgPSBjaGFyLmNoYXJDb2RlQXQoMCk7XG5cdFx0aWYgKGNvZGUgPj0gMHhkODAwICYmIGNvZGUgPD0gMHhkYmZmKSByZXR1cm4gY2hhciArIHRoaXMuX19saXN0X19bdGhpcy5fX25leHRJbmRleF9fKytdO1xuXHRcdHJldHVybiBjaGFyO1xuXHR9KVxufSk7XG5kZWZpbmVQcm9wZXJ0eShTdHJpbmdJdGVyYXRvci5wcm90b3R5cGUsIFN5bWJvbC50b1N0cmluZ1RhZywgZChcImNcIiwgXCJTdHJpbmcgSXRlcmF0b3JcIikpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc0l0ZXJhYmxlID0gcmVxdWlyZShcIi4vaXMtaXRlcmFibGVcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdGlmICghaXNJdGVyYWJsZSh2YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IodmFsdWUgKyBcIiBpcyBub3QgaXRlcmFibGVcIik7XG5cdHJldHVybiB2YWx1ZTtcbn07XG4iLCIvKiFcbiAqIEBvdmVydmlldyBlczYtcHJvbWlzZSAtIGEgdGlueSBpbXBsZW1lbnRhdGlvbiBvZiBQcm9taXNlcy9BKy5cbiAqIEBjb3B5cmlnaHQgQ29weXJpZ2h0IChjKSAyMDE0IFllaHVkYSBLYXR6LCBUb20gRGFsZSwgU3RlZmFuIFBlbm5lciBhbmQgY29udHJpYnV0b3JzIChDb252ZXJzaW9uIHRvIEVTNiBBUEkgYnkgSmFrZSBBcmNoaWJhbGQpXG4gKiBAbGljZW5zZSAgIExpY2Vuc2VkIHVuZGVyIE1JVCBsaWNlbnNlXG4gKiAgICAgICAgICAgIFNlZSBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RlZmFucGVubmVyL2VzNi1wcm9taXNlL21hc3Rlci9MSUNFTlNFXG4gKiBAdmVyc2lvbiAgIDMuMy4xXG4gKi9cblxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgICAoZ2xvYmFsLkVTNlByb21pc2UgPSBmYWN0b3J5KCkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIG9iamVjdE9yRnVuY3Rpb24oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIHggIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbic7XG59XG5cbnZhciBfaXNBcnJheSA9IHVuZGVmaW5lZDtcbmlmICghQXJyYXkuaXNBcnJheSkge1xuICBfaXNBcnJheSA9IGZ1bmN0aW9uICh4KSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgfTtcbn0gZWxzZSB7XG4gIF9pc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbn1cblxudmFyIGlzQXJyYXkgPSBfaXNBcnJheTtcblxudmFyIGxlbiA9IDA7XG52YXIgdmVydHhOZXh0ID0gdW5kZWZpbmVkO1xudmFyIGN1c3RvbVNjaGVkdWxlckZuID0gdW5kZWZpbmVkO1xuXG52YXIgYXNhcCA9IGZ1bmN0aW9uIGFzYXAoY2FsbGJhY2ssIGFyZykge1xuICBxdWV1ZVtsZW5dID0gY2FsbGJhY2s7XG4gIHF1ZXVlW2xlbiArIDFdID0gYXJnO1xuICBsZW4gKz0gMjtcbiAgaWYgKGxlbiA9PT0gMikge1xuICAgIC8vIElmIGxlbiBpcyAyLCB0aGF0IG1lYW5zIHRoYXQgd2UgbmVlZCB0byBzY2hlZHVsZSBhbiBhc3luYyBmbHVzaC5cbiAgICAvLyBJZiBhZGRpdGlvbmFsIGNhbGxiYWNrcyBhcmUgcXVldWVkIGJlZm9yZSB0aGUgcXVldWUgaXMgZmx1c2hlZCwgdGhleVxuICAgIC8vIHdpbGwgYmUgcHJvY2Vzc2VkIGJ5IHRoaXMgZmx1c2ggdGhhdCB3ZSBhcmUgc2NoZWR1bGluZy5cbiAgICBpZiAoY3VzdG9tU2NoZWR1bGVyRm4pIHtcbiAgICAgIGN1c3RvbVNjaGVkdWxlckZuKGZsdXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2NoZWR1bGVGbHVzaCgpO1xuICAgIH1cbiAgfVxufTtcblxuZnVuY3Rpb24gc2V0U2NoZWR1bGVyKHNjaGVkdWxlRm4pIHtcbiAgY3VzdG9tU2NoZWR1bGVyRm4gPSBzY2hlZHVsZUZuO1xufVxuXG5mdW5jdGlvbiBzZXRBc2FwKGFzYXBGbikge1xuICBhc2FwID0gYXNhcEZuO1xufVxuXG52YXIgYnJvd3NlcldpbmRvdyA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdW5kZWZpbmVkO1xudmFyIGJyb3dzZXJHbG9iYWwgPSBicm93c2VyV2luZG93IHx8IHt9O1xudmFyIEJyb3dzZXJNdXRhdGlvbk9ic2VydmVyID0gYnJvd3Nlckdsb2JhbC5NdXRhdGlvbk9ic2VydmVyIHx8IGJyb3dzZXJHbG9iYWwuV2ViS2l0TXV0YXRpb25PYnNlcnZlcjtcbnZhciBpc05vZGUgPSB0eXBlb2Ygc2VsZiA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmICh7fSkudG9TdHJpbmcuY2FsbChwcm9jZXNzKSA9PT0gJ1tvYmplY3QgcHJvY2Vzc10nO1xuXG4vLyB0ZXN0IGZvciB3ZWIgd29ya2VyIGJ1dCBub3QgaW4gSUUxMFxudmFyIGlzV29ya2VyID0gdHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgaW1wb3J0U2NyaXB0cyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJztcblxuLy8gbm9kZVxuZnVuY3Rpb24gdXNlTmV4dFRpY2soKSB7XG4gIC8vIG5vZGUgdmVyc2lvbiAwLjEwLnggZGlzcGxheXMgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdoZW4gbmV4dFRpY2sgaXMgdXNlZCByZWN1cnNpdmVseVxuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2N1am9qcy93aGVuL2lzc3Vlcy80MTAgZm9yIGRldGFpbHNcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljayhmbHVzaCk7XG4gIH07XG59XG5cbi8vIHZlcnR4XG5mdW5jdGlvbiB1c2VWZXJ0eFRpbWVyKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZlcnR4TmV4dChmbHVzaCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHVzZU11dGF0aW9uT2JzZXJ2ZXIoKSB7XG4gIHZhciBpdGVyYXRpb25zID0gMDtcbiAgdmFyIG9ic2VydmVyID0gbmV3IEJyb3dzZXJNdXRhdGlvbk9ic2VydmVyKGZsdXNoKTtcbiAgdmFyIG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gIG9ic2VydmVyLm9ic2VydmUobm9kZSwgeyBjaGFyYWN0ZXJEYXRhOiB0cnVlIH0pO1xuXG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgbm9kZS5kYXRhID0gaXRlcmF0aW9ucyA9ICsraXRlcmF0aW9ucyAlIDI7XG4gIH07XG59XG5cbi8vIHdlYiB3b3JrZXJcbmZ1bmN0aW9uIHVzZU1lc3NhZ2VDaGFubmVsKCkge1xuICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZsdXNoO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBjaGFubmVsLnBvcnQyLnBvc3RNZXNzYWdlKDApO1xuICB9O1xufVxuXG5mdW5jdGlvbiB1c2VTZXRUaW1lb3V0KCkge1xuICAvLyBTdG9yZSBzZXRUaW1lb3V0IHJlZmVyZW5jZSBzbyBlczYtcHJvbWlzZSB3aWxsIGJlIHVuYWZmZWN0ZWQgYnlcbiAgLy8gb3RoZXIgY29kZSBtb2RpZnlpbmcgc2V0VGltZW91dCAobGlrZSBzaW5vbi51c2VGYWtlVGltZXJzKCkpXG4gIHZhciBnbG9iYWxTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZ2xvYmFsU2V0VGltZW91dChmbHVzaCwgMSk7XG4gIH07XG59XG5cbnZhciBxdWV1ZSA9IG5ldyBBcnJheSgxMDAwKTtcbmZ1bmN0aW9uIGZsdXNoKCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSAyKSB7XG4gICAgdmFyIGNhbGxiYWNrID0gcXVldWVbaV07XG4gICAgdmFyIGFyZyA9IHF1ZXVlW2kgKyAxXTtcblxuICAgIGNhbGxiYWNrKGFyZyk7XG5cbiAgICBxdWV1ZVtpXSA9IHVuZGVmaW5lZDtcbiAgICBxdWV1ZVtpICsgMV0gPSB1bmRlZmluZWQ7XG4gIH1cblxuICBsZW4gPSAwO1xufVxuXG5mdW5jdGlvbiBhdHRlbXB0VmVydHgoKSB7XG4gIHRyeSB7XG4gICAgdmFyIHIgPSByZXF1aXJlO1xuICAgIHZhciB2ZXJ0eCA9IHIoJ3ZlcnR4Jyk7XG4gICAgdmVydHhOZXh0ID0gdmVydHgucnVuT25Mb29wIHx8IHZlcnR4LnJ1bk9uQ29udGV4dDtcbiAgICByZXR1cm4gdXNlVmVydHhUaW1lcigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIHVzZVNldFRpbWVvdXQoKTtcbiAgfVxufVxuXG52YXIgc2NoZWR1bGVGbHVzaCA9IHVuZGVmaW5lZDtcbi8vIERlY2lkZSB3aGF0IGFzeW5jIG1ldGhvZCB0byB1c2UgdG8gdHJpZ2dlcmluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlZCBjYWxsYmFja3M6XG5pZiAoaXNOb2RlKSB7XG4gIHNjaGVkdWxlRmx1c2ggPSB1c2VOZXh0VGljaygpO1xufSBlbHNlIGlmIChCcm93c2VyTXV0YXRpb25PYnNlcnZlcikge1xuICBzY2hlZHVsZUZsdXNoID0gdXNlTXV0YXRpb25PYnNlcnZlcigpO1xufSBlbHNlIGlmIChpc1dvcmtlcikge1xuICBzY2hlZHVsZUZsdXNoID0gdXNlTWVzc2FnZUNoYW5uZWwoKTtcbn0gZWxzZSBpZiAoYnJvd3NlcldpbmRvdyA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nKSB7XG4gIHNjaGVkdWxlRmx1c2ggPSBhdHRlbXB0VmVydHgoKTtcbn0gZWxzZSB7XG4gIHNjaGVkdWxlRmx1c2ggPSB1c2VTZXRUaW1lb3V0KCk7XG59XG5cbmZ1bmN0aW9uIHRoZW4ob25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24pIHtcbiAgdmFyIF9hcmd1bWVudHMgPSBhcmd1bWVudHM7XG5cbiAgdmFyIHBhcmVudCA9IHRoaXM7XG5cbiAgdmFyIGNoaWxkID0gbmV3IHRoaXMuY29uc3RydWN0b3Iobm9vcCk7XG5cbiAgaWYgKGNoaWxkW1BST01JU0VfSURdID09PSB1bmRlZmluZWQpIHtcbiAgICBtYWtlUHJvbWlzZShjaGlsZCk7XG4gIH1cblxuICB2YXIgX3N0YXRlID0gcGFyZW50Ll9zdGF0ZTtcblxuICBpZiAoX3N0YXRlKSB7XG4gICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBjYWxsYmFjayA9IF9hcmd1bWVudHNbX3N0YXRlIC0gMV07XG4gICAgICBhc2FwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGludm9rZUNhbGxiYWNrKF9zdGF0ZSwgY2hpbGQsIGNhbGxiYWNrLCBwYXJlbnQuX3Jlc3VsdCk7XG4gICAgICB9KTtcbiAgICB9KSgpO1xuICB9IGVsc2Uge1xuICAgIHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbik7XG4gIH1cblxuICByZXR1cm4gY2hpbGQ7XG59XG5cbi8qKlxuICBgUHJvbWlzZS5yZXNvbHZlYCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIHJlc29sdmVkIHdpdGggdGhlXG4gIHBhc3NlZCBgdmFsdWVgLiBJdCBpcyBzaG9ydGhhbmQgZm9yIHRoZSBmb2xsb3dpbmc6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgcmVzb2x2ZSgxKTtcbiAgfSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyB2YWx1ZSA9PT0gMVxuICB9KTtcbiAgYGBgXG5cbiAgSW5zdGVhZCBvZiB3cml0aW5nIHRoZSBhYm92ZSwgeW91ciBjb2RlIG5vdyBzaW1wbHkgYmVjb21lcyB0aGUgZm9sbG93aW5nOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoMSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyB2YWx1ZSA9PT0gMVxuICB9KTtcbiAgYGBgXG5cbiAgQG1ldGhvZCByZXNvbHZlXG4gIEBzdGF0aWNcbiAgQHBhcmFtIHtBbnl9IHZhbHVlIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgZnVsZmlsbGVkIHdpdGggdGhlIGdpdmVuXG4gIGB2YWx1ZWBcbiovXG5mdW5jdGlvbiByZXNvbHZlKG9iamVjdCkge1xuICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuXG4gIGlmIChvYmplY3QgJiYgdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0LmNvbnN0cnVjdG9yID09PSBDb25zdHJ1Y3Rvcikge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICB2YXIgcHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3Rvcihub29wKTtcbiAgX3Jlc29sdmUocHJvbWlzZSwgb2JqZWN0KTtcbiAgcmV0dXJuIHByb21pc2U7XG59XG5cbnZhciBQUk9NSVNFX0lEID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDE2KTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnZhciBQRU5ESU5HID0gdm9pZCAwO1xudmFyIEZVTEZJTExFRCA9IDE7XG52YXIgUkVKRUNURUQgPSAyO1xuXG52YXIgR0VUX1RIRU5fRVJST1IgPSBuZXcgRXJyb3JPYmplY3QoKTtcblxuZnVuY3Rpb24gc2VsZkZ1bGZpbGxtZW50KCkge1xuICByZXR1cm4gbmV3IFR5cGVFcnJvcihcIllvdSBjYW5ub3QgcmVzb2x2ZSBhIHByb21pc2Ugd2l0aCBpdHNlbGZcIik7XG59XG5cbmZ1bmN0aW9uIGNhbm5vdFJldHVybk93bigpIHtcbiAgcmV0dXJuIG5ldyBUeXBlRXJyb3IoJ0EgcHJvbWlzZXMgY2FsbGJhY2sgY2Fubm90IHJldHVybiB0aGF0IHNhbWUgcHJvbWlzZS4nKTtcbn1cblxuZnVuY3Rpb24gZ2V0VGhlbihwcm9taXNlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHByb21pc2UudGhlbjtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBHRVRfVEhFTl9FUlJPUi5lcnJvciA9IGVycm9yO1xuICAgIHJldHVybiBHRVRfVEhFTl9FUlJPUjtcbiAgfVxufVxuXG5mdW5jdGlvbiB0cnlUaGVuKHRoZW4sIHZhbHVlLCBmdWxmaWxsbWVudEhhbmRsZXIsIHJlamVjdGlvbkhhbmRsZXIpIHtcbiAgdHJ5IHtcbiAgICB0aGVuLmNhbGwodmFsdWUsIGZ1bGZpbGxtZW50SGFuZGxlciwgcmVqZWN0aW9uSGFuZGxlcik7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVGb3JlaWduVGhlbmFibGUocHJvbWlzZSwgdGhlbmFibGUsIHRoZW4pIHtcbiAgYXNhcChmdW5jdGlvbiAocHJvbWlzZSkge1xuICAgIHZhciBzZWFsZWQgPSBmYWxzZTtcbiAgICB2YXIgZXJyb3IgPSB0cnlUaGVuKHRoZW4sIHRoZW5hYmxlLCBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIGlmIChzZWFsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2VhbGVkID0gdHJ1ZTtcbiAgICAgIGlmICh0aGVuYWJsZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgX3Jlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgaWYgKHNlYWxlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzZWFsZWQgPSB0cnVlO1xuXG4gICAgICBfcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gICAgfSwgJ1NldHRsZTogJyArIChwcm9taXNlLl9sYWJlbCB8fCAnIHVua25vd24gcHJvbWlzZScpKTtcblxuICAgIGlmICghc2VhbGVkICYmIGVycm9yKSB7XG4gICAgICBzZWFsZWQgPSB0cnVlO1xuICAgICAgX3JlamVjdChwcm9taXNlLCBlcnJvcik7XG4gICAgfVxuICB9LCBwcm9taXNlKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlT3duVGhlbmFibGUocHJvbWlzZSwgdGhlbmFibGUpIHtcbiAgaWYgKHRoZW5hYmxlLl9zdGF0ZSA9PT0gRlVMRklMTEVEKSB7XG4gICAgZnVsZmlsbChwcm9taXNlLCB0aGVuYWJsZS5fcmVzdWx0KTtcbiAgfSBlbHNlIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IFJFSkVDVEVEKSB7XG4gICAgX3JlamVjdChwcm9taXNlLCB0aGVuYWJsZS5fcmVzdWx0KTtcbiAgfSBlbHNlIHtcbiAgICBzdWJzY3JpYmUodGhlbmFibGUsIHVuZGVmaW5lZCwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICByZXR1cm4gX3Jlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIHJldHVybiBfcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gICAgfSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaGFuZGxlTWF5YmVUaGVuYWJsZShwcm9taXNlLCBtYXliZVRoZW5hYmxlLCB0aGVuJCQpIHtcbiAgaWYgKG1heWJlVGhlbmFibGUuY29uc3RydWN0b3IgPT09IHByb21pc2UuY29uc3RydWN0b3IgJiYgdGhlbiQkID09PSB0aGVuICYmIG1heWJlVGhlbmFibGUuY29uc3RydWN0b3IucmVzb2x2ZSA9PT0gcmVzb2x2ZSkge1xuICAgIGhhbmRsZU93blRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUpO1xuICB9IGVsc2Uge1xuICAgIGlmICh0aGVuJCQgPT09IEdFVF9USEVOX0VSUk9SKSB7XG4gICAgICBfcmVqZWN0KHByb21pc2UsIEdFVF9USEVOX0VSUk9SLmVycm9yKTtcbiAgICB9IGVsc2UgaWYgKHRoZW4kJCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBmdWxmaWxsKHByb21pc2UsIG1heWJlVGhlbmFibGUpO1xuICAgIH0gZWxzZSBpZiAoaXNGdW5jdGlvbih0aGVuJCQpKSB7XG4gICAgICBoYW5kbGVGb3JlaWduVGhlbmFibGUocHJvbWlzZSwgbWF5YmVUaGVuYWJsZSwgdGhlbiQkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gX3Jlc29sdmUocHJvbWlzZSwgdmFsdWUpIHtcbiAgaWYgKHByb21pc2UgPT09IHZhbHVlKSB7XG4gICAgX3JlamVjdChwcm9taXNlLCBzZWxmRnVsZmlsbG1lbnQoKSk7XG4gIH0gZWxzZSBpZiAob2JqZWN0T3JGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICBoYW5kbGVNYXliZVRoZW5hYmxlKHByb21pc2UsIHZhbHVlLCBnZXRUaGVuKHZhbHVlKSk7XG4gIH0gZWxzZSB7XG4gICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcHVibGlzaFJlamVjdGlvbihwcm9taXNlKSB7XG4gIGlmIChwcm9taXNlLl9vbmVycm9yKSB7XG4gICAgcHJvbWlzZS5fb25lcnJvcihwcm9taXNlLl9yZXN1bHQpO1xuICB9XG5cbiAgcHVibGlzaChwcm9taXNlKTtcbn1cblxuZnVuY3Rpb24gZnVsZmlsbChwcm9taXNlLCB2YWx1ZSkge1xuICBpZiAocHJvbWlzZS5fc3RhdGUgIT09IFBFTkRJTkcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm9taXNlLl9yZXN1bHQgPSB2YWx1ZTtcbiAgcHJvbWlzZS5fc3RhdGUgPSBGVUxGSUxMRUQ7XG5cbiAgaWYgKHByb21pc2UuX3N1YnNjcmliZXJzLmxlbmd0aCAhPT0gMCkge1xuICAgIGFzYXAocHVibGlzaCwgcHJvbWlzZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX3JlamVjdChwcm9taXNlLCByZWFzb24pIHtcbiAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBQRU5ESU5HKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHByb21pc2UuX3N0YXRlID0gUkVKRUNURUQ7XG4gIHByb21pc2UuX3Jlc3VsdCA9IHJlYXNvbjtcblxuICBhc2FwKHB1Ymxpc2hSZWplY3Rpb24sIHByb21pc2UpO1xufVxuXG5mdW5jdGlvbiBzdWJzY3JpYmUocGFyZW50LCBjaGlsZCwgb25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24pIHtcbiAgdmFyIF9zdWJzY3JpYmVycyA9IHBhcmVudC5fc3Vic2NyaWJlcnM7XG4gIHZhciBsZW5ndGggPSBfc3Vic2NyaWJlcnMubGVuZ3RoO1xuXG4gIHBhcmVudC5fb25lcnJvciA9IG51bGw7XG5cbiAgX3N1YnNjcmliZXJzW2xlbmd0aF0gPSBjaGlsZDtcbiAgX3N1YnNjcmliZXJzW2xlbmd0aCArIEZVTEZJTExFRF0gPSBvbkZ1bGZpbGxtZW50O1xuICBfc3Vic2NyaWJlcnNbbGVuZ3RoICsgUkVKRUNURURdID0gb25SZWplY3Rpb247XG5cbiAgaWYgKGxlbmd0aCA9PT0gMCAmJiBwYXJlbnQuX3N0YXRlKSB7XG4gICAgYXNhcChwdWJsaXNoLCBwYXJlbnQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHB1Ymxpc2gocHJvbWlzZSkge1xuICB2YXIgc3Vic2NyaWJlcnMgPSBwcm9taXNlLl9zdWJzY3JpYmVycztcbiAgdmFyIHNldHRsZWQgPSBwcm9taXNlLl9zdGF0ZTtcblxuICBpZiAoc3Vic2NyaWJlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGNoaWxkID0gdW5kZWZpbmVkLFxuICAgICAgY2FsbGJhY2sgPSB1bmRlZmluZWQsXG4gICAgICBkZXRhaWwgPSBwcm9taXNlLl9yZXN1bHQ7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdWJzY3JpYmVycy5sZW5ndGg7IGkgKz0gMykge1xuICAgIGNoaWxkID0gc3Vic2NyaWJlcnNbaV07XG4gICAgY2FsbGJhY2sgPSBzdWJzY3JpYmVyc1tpICsgc2V0dGxlZF07XG5cbiAgICBpZiAoY2hpbGQpIHtcbiAgICAgIGludm9rZUNhbGxiYWNrKHNldHRsZWQsIGNoaWxkLCBjYWxsYmFjaywgZGV0YWlsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGJhY2soZGV0YWlsKTtcbiAgICB9XG4gIH1cblxuICBwcm9taXNlLl9zdWJzY3JpYmVycy5sZW5ndGggPSAwO1xufVxuXG5mdW5jdGlvbiBFcnJvck9iamVjdCgpIHtcbiAgdGhpcy5lcnJvciA9IG51bGw7XG59XG5cbnZhciBUUllfQ0FUQ0hfRVJST1IgPSBuZXcgRXJyb3JPYmplY3QoKTtcblxuZnVuY3Rpb24gdHJ5Q2F0Y2goY2FsbGJhY2ssIGRldGFpbCkge1xuICB0cnkge1xuICAgIHJldHVybiBjYWxsYmFjayhkZXRhaWwpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgVFJZX0NBVENIX0VSUk9SLmVycm9yID0gZTtcbiAgICByZXR1cm4gVFJZX0NBVENIX0VSUk9SO1xuICB9XG59XG5cbmZ1bmN0aW9uIGludm9rZUNhbGxiYWNrKHNldHRsZWQsIHByb21pc2UsIGNhbGxiYWNrLCBkZXRhaWwpIHtcbiAgdmFyIGhhc0NhbGxiYWNrID0gaXNGdW5jdGlvbihjYWxsYmFjayksXG4gICAgICB2YWx1ZSA9IHVuZGVmaW5lZCxcbiAgICAgIGVycm9yID0gdW5kZWZpbmVkLFxuICAgICAgc3VjY2VlZGVkID0gdW5kZWZpbmVkLFxuICAgICAgZmFpbGVkID0gdW5kZWZpbmVkO1xuXG4gIGlmIChoYXNDYWxsYmFjaykge1xuICAgIHZhbHVlID0gdHJ5Q2F0Y2goY2FsbGJhY2ssIGRldGFpbCk7XG5cbiAgICBpZiAodmFsdWUgPT09IFRSWV9DQVRDSF9FUlJPUikge1xuICAgICAgZmFpbGVkID0gdHJ1ZTtcbiAgICAgIGVycm9yID0gdmFsdWUuZXJyb3I7XG4gICAgICB2YWx1ZSA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1Y2NlZWRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHByb21pc2UgPT09IHZhbHVlKSB7XG4gICAgICBfcmVqZWN0KHByb21pc2UsIGNhbm5vdFJldHVybk93bigpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFsdWUgPSBkZXRhaWw7XG4gICAgc3VjY2VlZGVkID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykge1xuICAgIC8vIG5vb3BcbiAgfSBlbHNlIGlmIChoYXNDYWxsYmFjayAmJiBzdWNjZWVkZWQpIHtcbiAgICAgIF9yZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKGZhaWxlZCkge1xuICAgICAgX3JlamVjdChwcm9taXNlLCBlcnJvcik7XG4gICAgfSBlbHNlIGlmIChzZXR0bGVkID09PSBGVUxGSUxMRUQpIHtcbiAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoc2V0dGxlZCA9PT0gUkVKRUNURUQpIHtcbiAgICAgIF9yZWplY3QocHJvbWlzZSwgdmFsdWUpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVByb21pc2UocHJvbWlzZSwgcmVzb2x2ZXIpIHtcbiAgdHJ5IHtcbiAgICByZXNvbHZlcihmdW5jdGlvbiByZXNvbHZlUHJvbWlzZSh2YWx1ZSkge1xuICAgICAgX3Jlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICAgIH0sIGZ1bmN0aW9uIHJlamVjdFByb21pc2UocmVhc29uKSB7XG4gICAgICBfcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBfcmVqZWN0KHByb21pc2UsIGUpO1xuICB9XG59XG5cbnZhciBpZCA9IDA7XG5mdW5jdGlvbiBuZXh0SWQoKSB7XG4gIHJldHVybiBpZCsrO1xufVxuXG5mdW5jdGlvbiBtYWtlUHJvbWlzZShwcm9taXNlKSB7XG4gIHByb21pc2VbUFJPTUlTRV9JRF0gPSBpZCsrO1xuICBwcm9taXNlLl9zdGF0ZSA9IHVuZGVmaW5lZDtcbiAgcHJvbWlzZS5fcmVzdWx0ID0gdW5kZWZpbmVkO1xuICBwcm9taXNlLl9zdWJzY3JpYmVycyA9IFtdO1xufVxuXG5mdW5jdGlvbiBFbnVtZXJhdG9yKENvbnN0cnVjdG9yLCBpbnB1dCkge1xuICB0aGlzLl9pbnN0YW5jZUNvbnN0cnVjdG9yID0gQ29uc3RydWN0b3I7XG4gIHRoaXMucHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3Rvcihub29wKTtcblxuICBpZiAoIXRoaXMucHJvbWlzZVtQUk9NSVNFX0lEXSkge1xuICAgIG1ha2VQcm9taXNlKHRoaXMucHJvbWlzZSk7XG4gIH1cblxuICBpZiAoaXNBcnJheShpbnB1dCkpIHtcbiAgICB0aGlzLl9pbnB1dCA9IGlucHV0O1xuICAgIHRoaXMubGVuZ3RoID0gaW5wdXQubGVuZ3RoO1xuICAgIHRoaXMuX3JlbWFpbmluZyA9IGlucHV0Lmxlbmd0aDtcblxuICAgIHRoaXMuX3Jlc3VsdCA9IG5ldyBBcnJheSh0aGlzLmxlbmd0aCk7XG5cbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGZ1bGZpbGwodGhpcy5wcm9taXNlLCB0aGlzLl9yZXN1bHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxlbmd0aCA9IHRoaXMubGVuZ3RoIHx8IDA7XG4gICAgICB0aGlzLl9lbnVtZXJhdGUoKTtcbiAgICAgIGlmICh0aGlzLl9yZW1haW5pbmcgPT09IDApIHtcbiAgICAgICAgZnVsZmlsbCh0aGlzLnByb21pc2UsIHRoaXMuX3Jlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIF9yZWplY3QodGhpcy5wcm9taXNlLCB2YWxpZGF0aW9uRXJyb3IoKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFsaWRhdGlvbkVycm9yKCkge1xuICByZXR1cm4gbmV3IEVycm9yKCdBcnJheSBNZXRob2RzIG11c3QgYmUgcHJvdmlkZWQgYW4gQXJyYXknKTtcbn07XG5cbkVudW1lcmF0b3IucHJvdG90eXBlLl9lbnVtZXJhdGUgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aDtcbiAgdmFyIF9pbnB1dCA9IHRoaXMuX2lucHV0O1xuXG4gIGZvciAodmFyIGkgPSAwOyB0aGlzLl9zdGF0ZSA9PT0gUEVORElORyAmJiBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB0aGlzLl9lYWNoRW50cnkoX2lucHV0W2ldLCBpKTtcbiAgfVxufTtcblxuRW51bWVyYXRvci5wcm90b3R5cGUuX2VhY2hFbnRyeSA9IGZ1bmN0aW9uIChlbnRyeSwgaSkge1xuICB2YXIgYyA9IHRoaXMuX2luc3RhbmNlQ29uc3RydWN0b3I7XG4gIHZhciByZXNvbHZlJCQgPSBjLnJlc29sdmU7XG5cbiAgaWYgKHJlc29sdmUkJCA9PT0gcmVzb2x2ZSkge1xuICAgIHZhciBfdGhlbiA9IGdldFRoZW4oZW50cnkpO1xuXG4gICAgaWYgKF90aGVuID09PSB0aGVuICYmIGVudHJ5Ll9zdGF0ZSAhPT0gUEVORElORykge1xuICAgICAgdGhpcy5fc2V0dGxlZEF0KGVudHJ5Ll9zdGF0ZSwgaSwgZW50cnkuX3Jlc3VsdCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgX3RoZW4gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRoaXMuX3JlbWFpbmluZy0tO1xuICAgICAgdGhpcy5fcmVzdWx0W2ldID0gZW50cnk7XG4gICAgfSBlbHNlIGlmIChjID09PSBQcm9taXNlKSB7XG4gICAgICB2YXIgcHJvbWlzZSA9IG5ldyBjKG5vb3ApO1xuICAgICAgaGFuZGxlTWF5YmVUaGVuYWJsZShwcm9taXNlLCBlbnRyeSwgX3RoZW4pO1xuICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KHByb21pc2UsIGkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl93aWxsU2V0dGxlQXQobmV3IGMoZnVuY3Rpb24gKHJlc29sdmUkJCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSQkKGVudHJ5KTtcbiAgICAgIH0pLCBpKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5fd2lsbFNldHRsZUF0KHJlc29sdmUkJChlbnRyeSksIGkpO1xuICB9XG59O1xuXG5FbnVtZXJhdG9yLnByb3RvdHlwZS5fc2V0dGxlZEF0ID0gZnVuY3Rpb24gKHN0YXRlLCBpLCB2YWx1ZSkge1xuICB2YXIgcHJvbWlzZSA9IHRoaXMucHJvbWlzZTtcblxuICBpZiAocHJvbWlzZS5fc3RhdGUgPT09IFBFTkRJTkcpIHtcbiAgICB0aGlzLl9yZW1haW5pbmctLTtcblxuICAgIGlmIChzdGF0ZSA9PT0gUkVKRUNURUQpIHtcbiAgICAgIF9yZWplY3QocHJvbWlzZSwgdmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9yZXN1bHRbaV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAodGhpcy5fcmVtYWluaW5nID09PSAwKSB7XG4gICAgZnVsZmlsbChwcm9taXNlLCB0aGlzLl9yZXN1bHQpO1xuICB9XG59O1xuXG5FbnVtZXJhdG9yLnByb3RvdHlwZS5fd2lsbFNldHRsZUF0ID0gZnVuY3Rpb24gKHByb21pc2UsIGkpIHtcbiAgdmFyIGVudW1lcmF0b3IgPSB0aGlzO1xuXG4gIHN1YnNjcmliZShwcm9taXNlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBlbnVtZXJhdG9yLl9zZXR0bGVkQXQoRlVMRklMTEVELCBpLCB2YWx1ZSk7XG4gIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICByZXR1cm4gZW51bWVyYXRvci5fc2V0dGxlZEF0KFJFSkVDVEVELCBpLCByZWFzb24pO1xuICB9KTtcbn07XG5cbi8qKlxuICBgUHJvbWlzZS5hbGxgIGFjY2VwdHMgYW4gYXJyYXkgb2YgcHJvbWlzZXMsIGFuZCByZXR1cm5zIGEgbmV3IHByb21pc2Ugd2hpY2hcbiAgaXMgZnVsZmlsbGVkIHdpdGggYW4gYXJyYXkgb2YgZnVsZmlsbG1lbnQgdmFsdWVzIGZvciB0aGUgcGFzc2VkIHByb21pc2VzLCBvclxuICByZWplY3RlZCB3aXRoIHRoZSByZWFzb24gb2YgdGhlIGZpcnN0IHBhc3NlZCBwcm9taXNlIHRvIGJlIHJlamVjdGVkLiBJdCBjYXN0cyBhbGxcbiAgZWxlbWVudHMgb2YgdGhlIHBhc3NlZCBpdGVyYWJsZSB0byBwcm9taXNlcyBhcyBpdCBydW5zIHRoaXMgYWxnb3JpdGhtLlxuXG4gIEV4YW1wbGU6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpO1xuICBsZXQgcHJvbWlzZTIgPSByZXNvbHZlKDIpO1xuICBsZXQgcHJvbWlzZTMgPSByZXNvbHZlKDMpO1xuICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTtcblxuICBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbihmdW5jdGlvbihhcnJheSl7XG4gICAgLy8gVGhlIGFycmF5IGhlcmUgd291bGQgYmUgWyAxLCAyLCAzIF07XG4gIH0pO1xuICBgYGBcblxuICBJZiBhbnkgb2YgdGhlIGBwcm9taXNlc2AgZ2l2ZW4gdG8gYGFsbGAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZVxuICB0aGF0IGlzIHJlamVjdGVkIHdpbGwgYmUgZ2l2ZW4gYXMgYW4gYXJndW1lbnQgdG8gdGhlIHJldHVybmVkIHByb21pc2VzJ3NcbiAgcmVqZWN0aW9uIGhhbmRsZXIuIEZvciBleGFtcGxlOlxuXG4gIEV4YW1wbGU6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpO1xuICBsZXQgcHJvbWlzZTIgPSByZWplY3QobmV3IEVycm9yKFwiMlwiKSk7XG4gIGxldCBwcm9taXNlMyA9IHJlamVjdChuZXcgRXJyb3IoXCIzXCIpKTtcbiAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07XG5cbiAgUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpe1xuICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIVxuICB9LCBmdW5jdGlvbihlcnJvcikge1xuICAgIC8vIGVycm9yLm1lc3NhZ2UgPT09IFwiMlwiXG4gIH0pO1xuICBgYGBcblxuICBAbWV0aG9kIGFsbFxuICBAc3RhdGljXG4gIEBwYXJhbSB7QXJyYXl9IGVudHJpZXMgYXJyYXkgb2YgcHJvbWlzZXNcbiAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCBgcHJvbWlzZXNgIGhhdmUgYmVlblxuICBmdWxmaWxsZWQsIG9yIHJlamVjdGVkIGlmIGFueSBvZiB0aGVtIGJlY29tZSByZWplY3RlZC5cbiAgQHN0YXRpY1xuKi9cbmZ1bmN0aW9uIGFsbChlbnRyaWVzKSB7XG4gIHJldHVybiBuZXcgRW51bWVyYXRvcih0aGlzLCBlbnRyaWVzKS5wcm9taXNlO1xufVxuXG4vKipcbiAgYFByb21pc2UucmFjZWAgcmV0dXJucyBhIG5ldyBwcm9taXNlIHdoaWNoIGlzIHNldHRsZWQgaW4gdGhlIHNhbWUgd2F5IGFzIHRoZVxuICBmaXJzdCBwYXNzZWQgcHJvbWlzZSB0byBzZXR0bGUuXG5cbiAgRXhhbXBsZTpcblxuICBgYGBqYXZhc2NyaXB0XG4gIGxldCBwcm9taXNlMSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgcmVzb2x2ZSgncHJvbWlzZSAxJyk7XG4gICAgfSwgMjAwKTtcbiAgfSk7XG5cbiAgbGV0IHByb21pc2UyID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZXNvbHZlKCdwcm9taXNlIDInKTtcbiAgICB9LCAxMDApO1xuICB9KTtcblxuICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICAvLyByZXN1bHQgPT09ICdwcm9taXNlIDInIGJlY2F1c2UgaXQgd2FzIHJlc29sdmVkIGJlZm9yZSBwcm9taXNlMVxuICAgIC8vIHdhcyByZXNvbHZlZC5cbiAgfSk7XG4gIGBgYFxuXG4gIGBQcm9taXNlLnJhY2VgIGlzIGRldGVybWluaXN0aWMgaW4gdGhhdCBvbmx5IHRoZSBzdGF0ZSBvZiB0aGUgZmlyc3RcbiAgc2V0dGxlZCBwcm9taXNlIG1hdHRlcnMuIEZvciBleGFtcGxlLCBldmVuIGlmIG90aGVyIHByb21pc2VzIGdpdmVuIHRvIHRoZVxuICBgcHJvbWlzZXNgIGFycmF5IGFyZ3VtZW50IGFyZSByZXNvbHZlZCwgYnV0IHRoZSBmaXJzdCBzZXR0bGVkIHByb21pc2UgaGFzXG4gIGJlY29tZSByZWplY3RlZCBiZWZvcmUgdGhlIG90aGVyIHByb21pc2VzIGJlY2FtZSBmdWxmaWxsZWQsIHRoZSByZXR1cm5lZFxuICBwcm9taXNlIHdpbGwgYmVjb21lIHJlamVjdGVkOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UxID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZXNvbHZlKCdwcm9taXNlIDEnKTtcbiAgICB9LCAyMDApO1xuICB9KTtcblxuICBsZXQgcHJvbWlzZTIgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoJ3Byb21pc2UgMicpKTtcbiAgICB9LCAxMDApO1xuICB9KTtcblxuICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICAvLyBDb2RlIGhlcmUgbmV2ZXIgcnVuc1xuICB9LCBmdW5jdGlvbihyZWFzb24pe1xuICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIHByb21pc2UgMiBiZWNhbWUgcmVqZWN0ZWQgYmVmb3JlXG4gICAgLy8gcHJvbWlzZSAxIGJlY2FtZSBmdWxmaWxsZWRcbiAgfSk7XG4gIGBgYFxuXG4gIEFuIGV4YW1wbGUgcmVhbC13b3JsZCB1c2UgY2FzZSBpcyBpbXBsZW1lbnRpbmcgdGltZW91dHM6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBQcm9taXNlLnJhY2UoW2FqYXgoJ2Zvby5qc29uJyksIHRpbWVvdXQoNTAwMCldKVxuICBgYGBcblxuICBAbWV0aG9kIHJhY2VcbiAgQHN0YXRpY1xuICBAcGFyYW0ge0FycmF5fSBwcm9taXNlcyBhcnJheSBvZiBwcm9taXNlcyB0byBvYnNlcnZlXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHdoaWNoIHNldHRsZXMgaW4gdGhlIHNhbWUgd2F5IGFzIHRoZSBmaXJzdCBwYXNzZWRcbiAgcHJvbWlzZSB0byBzZXR0bGUuXG4qL1xuZnVuY3Rpb24gcmFjZShlbnRyaWVzKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7XG5cbiAgaWYgKCFpc0FycmF5KGVudHJpZXMpKSB7XG4gICAgcmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiAoXywgcmVqZWN0KSB7XG4gICAgICByZXR1cm4gcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ1lvdSBtdXN0IHBhc3MgYW4gYXJyYXkgdG8gcmFjZS4nKSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gZW50cmllcy5sZW5ndGg7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIENvbnN0cnVjdG9yLnJlc29sdmUoZW50cmllc1tpXSkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICBgUHJvbWlzZS5yZWplY3RgIHJldHVybnMgYSBwcm9taXNlIHJlamVjdGVkIHdpdGggdGhlIHBhc3NlZCBgcmVhc29uYC5cbiAgSXQgaXMgc2hvcnRoYW5kIGZvciB0aGUgZm9sbG93aW5nOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHJlamVjdChuZXcgRXJyb3IoJ1dIT09QUycpKTtcbiAgfSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCFcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUydcbiAgfSk7XG4gIGBgYFxuXG4gIEluc3RlYWQgb2Ygd3JpdGluZyB0aGUgYWJvdmUsIHlvdXIgY29kZSBub3cgc2ltcGx5IGJlY29tZXMgdGhlIGZvbGxvd2luZzpcblxuICBgYGBqYXZhc2NyaXB0XG4gIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdXSE9PUFMnKSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCFcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUydcbiAgfSk7XG4gIGBgYFxuXG4gIEBtZXRob2QgcmVqZWN0XG4gIEBzdGF0aWNcbiAgQHBhcmFtIHtBbnl9IHJlYXNvbiB2YWx1ZSB0aGF0IHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aC5cbiAgVXNlZnVsIGZvciB0b29saW5nLlxuICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgcmVqZWN0ZWQgd2l0aCB0aGUgZ2l2ZW4gYHJlYXNvbmAuXG4qL1xuZnVuY3Rpb24gcmVqZWN0KHJlYXNvbikge1xuICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuICB2YXIgcHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3Rvcihub29wKTtcbiAgX3JlamVjdChwcm9taXNlLCByZWFzb24pO1xuICByZXR1cm4gcHJvbWlzZTtcbn1cblxuZnVuY3Rpb24gbmVlZHNSZXNvbHZlcigpIHtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcignWW91IG11c3QgcGFzcyBhIHJlc29sdmVyIGZ1bmN0aW9uIGFzIHRoZSBmaXJzdCBhcmd1bWVudCB0byB0aGUgcHJvbWlzZSBjb25zdHJ1Y3RvcicpO1xufVxuXG5mdW5jdGlvbiBuZWVkc05ldygpIHtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkZhaWxlZCB0byBjb25zdHJ1Y3QgJ1Byb21pc2UnOiBQbGVhc2UgdXNlIHRoZSAnbmV3JyBvcGVyYXRvciwgdGhpcyBvYmplY3QgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLlwiKTtcbn1cblxuLyoqXG4gIFByb21pc2Ugb2JqZWN0cyByZXByZXNlbnQgdGhlIGV2ZW50dWFsIHJlc3VsdCBvZiBhbiBhc3luY2hyb25vdXMgb3BlcmF0aW9uLiBUaGVcbiAgcHJpbWFyeSB3YXkgb2YgaW50ZXJhY3Rpbmcgd2l0aCBhIHByb21pc2UgaXMgdGhyb3VnaCBpdHMgYHRoZW5gIG1ldGhvZCwgd2hpY2hcbiAgcmVnaXN0ZXJzIGNhbGxiYWNrcyB0byByZWNlaXZlIGVpdGhlciBhIHByb21pc2UncyBldmVudHVhbCB2YWx1ZSBvciB0aGUgcmVhc29uXG4gIHdoeSB0aGUgcHJvbWlzZSBjYW5ub3QgYmUgZnVsZmlsbGVkLlxuXG4gIFRlcm1pbm9sb2d5XG4gIC0tLS0tLS0tLS0tXG5cbiAgLSBgcHJvbWlzZWAgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHdpdGggYSBgdGhlbmAgbWV0aG9kIHdob3NlIGJlaGF2aW9yIGNvbmZvcm1zIHRvIHRoaXMgc3BlY2lmaWNhdGlvbi5cbiAgLSBgdGhlbmFibGVgIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB0aGF0IGRlZmluZXMgYSBgdGhlbmAgbWV0aG9kLlxuICAtIGB2YWx1ZWAgaXMgYW55IGxlZ2FsIEphdmFTY3JpcHQgdmFsdWUgKGluY2x1ZGluZyB1bmRlZmluZWQsIGEgdGhlbmFibGUsIG9yIGEgcHJvbWlzZSkuXG4gIC0gYGV4Y2VwdGlvbmAgaXMgYSB2YWx1ZSB0aGF0IGlzIHRocm93biB1c2luZyB0aGUgdGhyb3cgc3RhdGVtZW50LlxuICAtIGByZWFzb25gIGlzIGEgdmFsdWUgdGhhdCBpbmRpY2F0ZXMgd2h5IGEgcHJvbWlzZSB3YXMgcmVqZWN0ZWQuXG4gIC0gYHNldHRsZWRgIHRoZSBmaW5hbCByZXN0aW5nIHN0YXRlIG9mIGEgcHJvbWlzZSwgZnVsZmlsbGVkIG9yIHJlamVjdGVkLlxuXG4gIEEgcHJvbWlzZSBjYW4gYmUgaW4gb25lIG9mIHRocmVlIHN0YXRlczogcGVuZGluZywgZnVsZmlsbGVkLCBvciByZWplY3RlZC5cblxuICBQcm9taXNlcyB0aGF0IGFyZSBmdWxmaWxsZWQgaGF2ZSBhIGZ1bGZpbGxtZW50IHZhbHVlIGFuZCBhcmUgaW4gdGhlIGZ1bGZpbGxlZFxuICBzdGF0ZS4gIFByb21pc2VzIHRoYXQgYXJlIHJlamVjdGVkIGhhdmUgYSByZWplY3Rpb24gcmVhc29uIGFuZCBhcmUgaW4gdGhlXG4gIHJlamVjdGVkIHN0YXRlLiAgQSBmdWxmaWxsbWVudCB2YWx1ZSBpcyBuZXZlciBhIHRoZW5hYmxlLlxuXG4gIFByb21pc2VzIGNhbiBhbHNvIGJlIHNhaWQgdG8gKnJlc29sdmUqIGEgdmFsdWUuICBJZiB0aGlzIHZhbHVlIGlzIGFsc28gYVxuICBwcm9taXNlLCB0aGVuIHRoZSBvcmlnaW5hbCBwcm9taXNlJ3Mgc2V0dGxlZCBzdGF0ZSB3aWxsIG1hdGNoIHRoZSB2YWx1ZSdzXG4gIHNldHRsZWQgc3RhdGUuICBTbyBhIHByb21pc2UgdGhhdCAqcmVzb2x2ZXMqIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMgd2lsbFxuICBpdHNlbGYgcmVqZWN0LCBhbmQgYSBwcm9taXNlIHRoYXQgKnJlc29sdmVzKiBhIHByb21pc2UgdGhhdCBmdWxmaWxscyB3aWxsXG4gIGl0c2VsZiBmdWxmaWxsLlxuXG5cbiAgQmFzaWMgVXNhZ2U6XG4gIC0tLS0tLS0tLS0tLVxuXG4gIGBgYGpzXG4gIGxldCBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgLy8gb24gc3VjY2Vzc1xuICAgIHJlc29sdmUodmFsdWUpO1xuXG4gICAgLy8gb24gZmFpbHVyZVxuICAgIHJlamVjdChyZWFzb24pO1xuICB9KTtcblxuICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpIHtcbiAgICAvLyBvbiBmdWxmaWxsbWVudFxuICB9LCBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAvLyBvbiByZWplY3Rpb25cbiAgfSk7XG4gIGBgYFxuXG4gIEFkdmFuY2VkIFVzYWdlOlxuICAtLS0tLS0tLS0tLS0tLS1cblxuICBQcm9taXNlcyBzaGluZSB3aGVuIGFic3RyYWN0aW5nIGF3YXkgYXN5bmNocm9ub3VzIGludGVyYWN0aW9ucyBzdWNoIGFzXG4gIGBYTUxIdHRwUmVxdWVzdGBzLlxuXG4gIGBgYGpzXG4gIGZ1bmN0aW9uIGdldEpTT04odXJsKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgICBsZXQgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG5cbiAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwpO1xuICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGhhbmRsZXI7XG4gICAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2pzb24nO1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgICB4aHIuc2VuZCgpO1xuXG4gICAgICBmdW5jdGlvbiBoYW5kbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5yZWFkeVN0YXRlID09PSB0aGlzLkRPTkUpIHtcbiAgICAgICAgICBpZiAodGhpcy5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLnJlc3BvbnNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignZ2V0SlNPTjogYCcgKyB1cmwgKyAnYCBmYWlsZWQgd2l0aCBzdGF0dXM6IFsnICsgdGhpcy5zdGF0dXMgKyAnXScpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBnZXRKU09OKCcvcG9zdHMuanNvbicpLnRoZW4oZnVuY3Rpb24oanNvbikge1xuICAgIC8vIG9uIGZ1bGZpbGxtZW50XG4gIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgIC8vIG9uIHJlamVjdGlvblxuICB9KTtcbiAgYGBgXG5cbiAgVW5saWtlIGNhbGxiYWNrcywgcHJvbWlzZXMgYXJlIGdyZWF0IGNvbXBvc2FibGUgcHJpbWl0aXZlcy5cblxuICBgYGBqc1xuICBQcm9taXNlLmFsbChbXG4gICAgZ2V0SlNPTignL3Bvc3RzJyksXG4gICAgZ2V0SlNPTignL2NvbW1lbnRzJylcbiAgXSkudGhlbihmdW5jdGlvbih2YWx1ZXMpe1xuICAgIHZhbHVlc1swXSAvLyA9PiBwb3N0c0pTT05cbiAgICB2YWx1ZXNbMV0gLy8gPT4gY29tbWVudHNKU09OXG5cbiAgICByZXR1cm4gdmFsdWVzO1xuICB9KTtcbiAgYGBgXG5cbiAgQGNsYXNzIFByb21pc2VcbiAgQHBhcmFtIHtmdW5jdGlvbn0gcmVzb2x2ZXJcbiAgVXNlZnVsIGZvciB0b29saW5nLlxuICBAY29uc3RydWN0b3JcbiovXG5mdW5jdGlvbiBQcm9taXNlKHJlc29sdmVyKSB7XG4gIHRoaXNbUFJPTUlTRV9JRF0gPSBuZXh0SWQoKTtcbiAgdGhpcy5fcmVzdWx0ID0gdGhpcy5fc3RhdGUgPSB1bmRlZmluZWQ7XG4gIHRoaXMuX3N1YnNjcmliZXJzID0gW107XG5cbiAgaWYgKG5vb3AgIT09IHJlc29sdmVyKSB7XG4gICAgdHlwZW9mIHJlc29sdmVyICE9PSAnZnVuY3Rpb24nICYmIG5lZWRzUmVzb2x2ZXIoKTtcbiAgICB0aGlzIGluc3RhbmNlb2YgUHJvbWlzZSA/IGluaXRpYWxpemVQcm9taXNlKHRoaXMsIHJlc29sdmVyKSA6IG5lZWRzTmV3KCk7XG4gIH1cbn1cblxuUHJvbWlzZS5hbGwgPSBhbGw7XG5Qcm9taXNlLnJhY2UgPSByYWNlO1xuUHJvbWlzZS5yZXNvbHZlID0gcmVzb2x2ZTtcblByb21pc2UucmVqZWN0ID0gcmVqZWN0O1xuUHJvbWlzZS5fc2V0U2NoZWR1bGVyID0gc2V0U2NoZWR1bGVyO1xuUHJvbWlzZS5fc2V0QXNhcCA9IHNldEFzYXA7XG5Qcm9taXNlLl9hc2FwID0gYXNhcDtcblxuUHJvbWlzZS5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBQcm9taXNlLFxuXG4gIC8qKlxuICAgIFRoZSBwcmltYXJ5IHdheSBvZiBpbnRlcmFjdGluZyB3aXRoIGEgcHJvbWlzZSBpcyB0aHJvdWdoIGl0cyBgdGhlbmAgbWV0aG9kLFxuICAgIHdoaWNoIHJlZ2lzdGVycyBjYWxsYmFja3MgdG8gcmVjZWl2ZSBlaXRoZXIgYSBwcm9taXNlJ3MgZXZlbnR1YWwgdmFsdWUgb3IgdGhlXG4gICAgcmVhc29uIHdoeSB0aGUgcHJvbWlzZSBjYW5ub3QgYmUgZnVsZmlsbGVkLlxuICBcbiAgICBgYGBqc1xuICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbih1c2VyKXtcbiAgICAgIC8vIHVzZXIgaXMgYXZhaWxhYmxlXG4gICAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAgIC8vIHVzZXIgaXMgdW5hdmFpbGFibGUsIGFuZCB5b3UgYXJlIGdpdmVuIHRoZSByZWFzb24gd2h5XG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIENoYWluaW5nXG4gICAgLS0tLS0tLS1cbiAgXG4gICAgVGhlIHJldHVybiB2YWx1ZSBvZiBgdGhlbmAgaXMgaXRzZWxmIGEgcHJvbWlzZS4gIFRoaXMgc2Vjb25kLCAnZG93bnN0cmVhbSdcbiAgICBwcm9taXNlIGlzIHJlc29sdmVkIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZmlyc3QgcHJvbWlzZSdzIGZ1bGZpbGxtZW50XG4gICAgb3IgcmVqZWN0aW9uIGhhbmRsZXIsIG9yIHJlamVjdGVkIGlmIHRoZSBoYW5kbGVyIHRocm93cyBhbiBleGNlcHRpb24uXG4gIFxuICAgIGBgYGpzXG4gICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICByZXR1cm4gdXNlci5uYW1lO1xuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIHJldHVybiAnZGVmYXVsdCBuYW1lJztcbiAgICB9KS50aGVuKGZ1bmN0aW9uICh1c2VyTmFtZSkge1xuICAgICAgLy8gSWYgYGZpbmRVc2VyYCBmdWxmaWxsZWQsIGB1c2VyTmFtZWAgd2lsbCBiZSB0aGUgdXNlcidzIG5hbWUsIG90aGVyd2lzZSBpdFxuICAgICAgLy8gd2lsbCBiZSBgJ2RlZmF1bHQgbmFtZSdgXG4gICAgfSk7XG4gIFxuICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScpO1xuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYGZpbmRVc2VyYCByZWplY3RlZCBhbmQgd2UncmUgdW5oYXBweScpO1xuICAgIH0pLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAvLyBuZXZlciByZWFjaGVkXG4gICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgLy8gaWYgYGZpbmRVc2VyYCBmdWxmaWxsZWQsIGByZWFzb25gIHdpbGwgYmUgJ0ZvdW5kIHVzZXIsIGJ1dCBzdGlsbCB1bmhhcHB5Jy5cbiAgICAgIC8vIElmIGBmaW5kVXNlcmAgcmVqZWN0ZWQsIGByZWFzb25gIHdpbGwgYmUgJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlJ3JlIHVuaGFwcHknLlxuICAgIH0pO1xuICAgIGBgYFxuICAgIElmIHRoZSBkb3duc3RyZWFtIHByb21pc2UgZG9lcyBub3Qgc3BlY2lmeSBhIHJlamVjdGlvbiBoYW5kbGVyLCByZWplY3Rpb24gcmVhc29ucyB3aWxsIGJlIHByb3BhZ2F0ZWQgZnVydGhlciBkb3duc3RyZWFtLlxuICBcbiAgICBgYGBqc1xuICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgdGhyb3cgbmV3IFBlZGFnb2dpY2FsRXhjZXB0aW9uKCdVcHN0cmVhbSBlcnJvcicpO1xuICAgIH0pLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAvLyBuZXZlciByZWFjaGVkXG4gICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIC8vIG5ldmVyIHJlYWNoZWRcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAvLyBUaGUgYFBlZGdhZ29jaWFsRXhjZXB0aW9uYCBpcyBwcm9wYWdhdGVkIGFsbCB0aGUgd2F5IGRvd24gdG8gaGVyZVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBBc3NpbWlsYXRpb25cbiAgICAtLS0tLS0tLS0tLS1cbiAgXG4gICAgU29tZXRpbWVzIHRoZSB2YWx1ZSB5b3Ugd2FudCB0byBwcm9wYWdhdGUgdG8gYSBkb3duc3RyZWFtIHByb21pc2UgY2FuIG9ubHkgYmVcbiAgICByZXRyaWV2ZWQgYXN5bmNocm9ub3VzbHkuIFRoaXMgY2FuIGJlIGFjaGlldmVkIGJ5IHJldHVybmluZyBhIHByb21pc2UgaW4gdGhlXG4gICAgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZSBkb3duc3RyZWFtIHByb21pc2Ugd2lsbCB0aGVuIGJlIHBlbmRpbmdcbiAgICB1bnRpbCB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBzZXR0bGVkLiBUaGlzIGlzIGNhbGxlZCAqYXNzaW1pbGF0aW9uKi5cbiAgXG4gICAgYGBganNcbiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHtcbiAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChjb21tZW50cykge1xuICAgICAgLy8gVGhlIHVzZXIncyBjb21tZW50cyBhcmUgbm93IGF2YWlsYWJsZVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBJZiB0aGUgYXNzaW1saWF0ZWQgcHJvbWlzZSByZWplY3RzLCB0aGVuIHRoZSBkb3duc3RyZWFtIHByb21pc2Ugd2lsbCBhbHNvIHJlamVjdC5cbiAgXG4gICAgYGBganNcbiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHtcbiAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChjb21tZW50cykge1xuICAgICAgLy8gSWYgYGZpbmRDb21tZW50c0J5QXV0aG9yYCBmdWxmaWxscywgd2UnbGwgaGF2ZSB0aGUgdmFsdWUgaGVyZVxuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIC8vIElmIGBmaW5kQ29tbWVudHNCeUF1dGhvcmAgcmVqZWN0cywgd2UnbGwgaGF2ZSB0aGUgcmVhc29uIGhlcmVcbiAgICB9KTtcbiAgICBgYGBcbiAgXG4gICAgU2ltcGxlIEV4YW1wbGVcbiAgICAtLS0tLS0tLS0tLS0tLVxuICBcbiAgICBTeW5jaHJvbm91cyBFeGFtcGxlXG4gIFxuICAgIGBgYGphdmFzY3JpcHRcbiAgICBsZXQgcmVzdWx0O1xuICBcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZmluZFJlc3VsdCgpO1xuICAgICAgLy8gc3VjY2Vzc1xuICAgIH0gY2F0Y2gocmVhc29uKSB7XG4gICAgICAvLyBmYWlsdXJlXG4gICAgfVxuICAgIGBgYFxuICBcbiAgICBFcnJiYWNrIEV4YW1wbGVcbiAgXG4gICAgYGBganNcbiAgICBmaW5kUmVzdWx0KGZ1bmN0aW9uKHJlc3VsdCwgZXJyKXtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgLy8gZmFpbHVyZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gc3VjY2Vzc1xuICAgICAgfVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBQcm9taXNlIEV4YW1wbGU7XG4gIFxuICAgIGBgYGphdmFzY3JpcHRcbiAgICBmaW5kUmVzdWx0KCkudGhlbihmdW5jdGlvbihyZXN1bHQpe1xuICAgICAgLy8gc3VjY2Vzc1xuICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgICAvLyBmYWlsdXJlXG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIEFkdmFuY2VkIEV4YW1wbGVcbiAgICAtLS0tLS0tLS0tLS0tLVxuICBcbiAgICBTeW5jaHJvbm91cyBFeGFtcGxlXG4gIFxuICAgIGBgYGphdmFzY3JpcHRcbiAgICBsZXQgYXV0aG9yLCBib29rcztcbiAgXG4gICAgdHJ5IHtcbiAgICAgIGF1dGhvciA9IGZpbmRBdXRob3IoKTtcbiAgICAgIGJvb2tzICA9IGZpbmRCb29rc0J5QXV0aG9yKGF1dGhvcik7XG4gICAgICAvLyBzdWNjZXNzXG4gICAgfSBjYXRjaChyZWFzb24pIHtcbiAgICAgIC8vIGZhaWx1cmVcbiAgICB9XG4gICAgYGBgXG4gIFxuICAgIEVycmJhY2sgRXhhbXBsZVxuICBcbiAgICBgYGBqc1xuICBcbiAgICBmdW5jdGlvbiBmb3VuZEJvb2tzKGJvb2tzKSB7XG4gIFxuICAgIH1cbiAgXG4gICAgZnVuY3Rpb24gZmFpbHVyZShyZWFzb24pIHtcbiAgXG4gICAgfVxuICBcbiAgICBmaW5kQXV0aG9yKGZ1bmN0aW9uKGF1dGhvciwgZXJyKXtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgZmFpbHVyZShlcnIpO1xuICAgICAgICAvLyBmYWlsdXJlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGZpbmRCb29va3NCeUF1dGhvcihhdXRob3IsIGZ1bmN0aW9uKGJvb2tzLCBlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgZmFpbHVyZShlcnIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmb3VuZEJvb2tzKGJvb2tzKTtcbiAgICAgICAgICAgICAgfSBjYXRjaChyZWFzb24pIHtcbiAgICAgICAgICAgICAgICBmYWlsdXJlKHJlYXNvbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgIGZhaWx1cmUoZXJyKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzdWNjZXNzXG4gICAgICB9XG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIFByb21pc2UgRXhhbXBsZTtcbiAgXG4gICAgYGBgamF2YXNjcmlwdFxuICAgIGZpbmRBdXRob3IoKS5cbiAgICAgIHRoZW4oZmluZEJvb2tzQnlBdXRob3IpLlxuICAgICAgdGhlbihmdW5jdGlvbihib29rcyl7XG4gICAgICAgIC8vIGZvdW5kIGJvb2tzXG4gICAgfSkuY2F0Y2goZnVuY3Rpb24ocmVhc29uKXtcbiAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nXG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIEBtZXRob2QgdGhlblxuICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uRnVsZmlsbGVkXG4gICAgQHBhcmFtIHtGdW5jdGlvbn0gb25SZWplY3RlZFxuICAgIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgICBAcmV0dXJuIHtQcm9taXNlfVxuICAqL1xuICB0aGVuOiB0aGVuLFxuXG4gIC8qKlxuICAgIGBjYXRjaGAgaXMgc2ltcGx5IHN1Z2FyIGZvciBgdGhlbih1bmRlZmluZWQsIG9uUmVqZWN0aW9uKWAgd2hpY2ggbWFrZXMgaXQgdGhlIHNhbWVcbiAgICBhcyB0aGUgY2F0Y2ggYmxvY2sgb2YgYSB0cnkvY2F0Y2ggc3RhdGVtZW50LlxuICBcbiAgICBgYGBqc1xuICAgIGZ1bmN0aW9uIGZpbmRBdXRob3IoKXtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGRuJ3QgZmluZCB0aGF0IGF1dGhvcicpO1xuICAgIH1cbiAgXG4gICAgLy8gc3luY2hyb25vdXNcbiAgICB0cnkge1xuICAgICAgZmluZEF1dGhvcigpO1xuICAgIH0gY2F0Y2gocmVhc29uKSB7XG4gICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZ1xuICAgIH1cbiAgXG4gICAgLy8gYXN5bmMgd2l0aCBwcm9taXNlc1xuICAgIGZpbmRBdXRob3IoKS5jYXRjaChmdW5jdGlvbihyZWFzb24pe1xuICAgICAgLy8gc29tZXRoaW5nIHdlbnQgd3JvbmdcbiAgICB9KTtcbiAgICBgYGBcbiAgXG4gICAgQG1ldGhvZCBjYXRjaFxuICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVqZWN0aW9uXG4gICAgVXNlZnVsIGZvciB0b29saW5nLlxuICAgIEByZXR1cm4ge1Byb21pc2V9XG4gICovXG4gICdjYXRjaCc6IGZ1bmN0aW9uIF9jYXRjaChvblJlamVjdGlvbikge1xuICAgIHJldHVybiB0aGlzLnRoZW4obnVsbCwgb25SZWplY3Rpb24pO1xuICB9XG59O1xuXG5mdW5jdGlvbiBwb2x5ZmlsbCgpIHtcbiAgICB2YXIgbG9jYWwgPSB1bmRlZmluZWQ7XG5cbiAgICBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgbG9jYWwgPSBnbG9iYWw7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgbG9jYWwgPSBzZWxmO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2NhbCA9IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncG9seWZpbGwgZmFpbGVkIGJlY2F1c2UgZ2xvYmFsIG9iamVjdCBpcyB1bmF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgUCA9IGxvY2FsLlByb21pc2U7XG5cbiAgICBpZiAoUCkge1xuICAgICAgICB2YXIgcHJvbWlzZVRvU3RyaW5nID0gbnVsbDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHByb21pc2VUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChQLnJlc29sdmUoKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIHNpbGVudGx5IGlnbm9yZWRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcm9taXNlVG9TdHJpbmcgPT09ICdbb2JqZWN0IFByb21pc2VdJyAmJiAhUC5jYXN0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsb2NhbC5Qcm9taXNlID0gUHJvbWlzZTtcbn1cblxucG9seWZpbGwoKTtcbi8vIFN0cmFuZ2UgY29tcGF0Li5cblByb21pc2UucG9seWZpbGwgPSBwb2x5ZmlsbDtcblByb21pc2UuUHJvbWlzZSA9IFByb21pc2U7XG5cbnJldHVybiBQcm9taXNlO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZXM2LXByb21pc2UubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vaXMtaW1wbGVtZW50ZWQnKSgpID8gU3ltYm9sIDogcmVxdWlyZSgnLi9wb2x5ZmlsbCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdmFsaWRUeXBlcyA9IHsgb2JqZWN0OiB0cnVlLCBzeW1ib2w6IHRydWUgfTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzeW1ib2w7XG5cdGlmICh0eXBlb2YgU3ltYm9sICE9PSAnZnVuY3Rpb24nKSByZXR1cm4gZmFsc2U7XG5cdHN5bWJvbCA9IFN5bWJvbCgndGVzdCBzeW1ib2wnKTtcblx0dHJ5IHsgU3RyaW5nKHN5bWJvbCk7IH0gY2F0Y2ggKGUpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0Ly8gUmV0dXJuICd0cnVlJyBhbHNvIGZvciBwb2x5ZmlsbHNcblx0aWYgKCF2YWxpZFR5cGVzW3R5cGVvZiBTeW1ib2wuaXRlcmF0b3JdKSByZXR1cm4gZmFsc2U7XG5cdGlmICghdmFsaWRUeXBlc1t0eXBlb2YgU3ltYm9sLnRvUHJpbWl0aXZlXSkgcmV0dXJuIGZhbHNlO1xuXHRpZiAoIXZhbGlkVHlwZXNbdHlwZW9mIFN5bWJvbC50b1N0cmluZ1RhZ10pIHJldHVybiBmYWxzZTtcblxuXHRyZXR1cm4gdHJ1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHgpIHtcblx0aWYgKCF4KSByZXR1cm4gZmFsc2U7XG5cdGlmICh0eXBlb2YgeCA9PT0gJ3N5bWJvbCcpIHJldHVybiB0cnVlO1xuXHRpZiAoIXguY29uc3RydWN0b3IpIHJldHVybiBmYWxzZTtcblx0aWYgKHguY29uc3RydWN0b3IubmFtZSAhPT0gJ1N5bWJvbCcpIHJldHVybiBmYWxzZTtcblx0cmV0dXJuICh4W3guY29uc3RydWN0b3IudG9TdHJpbmdUYWddID09PSAnU3ltYm9sJyk7XG59O1xuIiwiLy8gRVMyMDE1IFN5bWJvbCBwb2x5ZmlsbCBmb3IgZW52aXJvbm1lbnRzIHRoYXQgZG8gbm90IChvciBwYXJ0aWFsbHkpIHN1cHBvcnQgaXRcblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZCAgICAgICAgICAgICAgPSByZXF1aXJlKCdkJylcbiAgLCB2YWxpZGF0ZVN5bWJvbCA9IHJlcXVpcmUoJy4vdmFsaWRhdGUtc3ltYm9sJylcblxuICAsIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGUsIGRlZmluZVByb3BlcnRpZXMgPSBPYmplY3QuZGVmaW5lUHJvcGVydGllc1xuICAsIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5LCBvYmpQcm90b3R5cGUgPSBPYmplY3QucHJvdG90eXBlXG4gICwgTmF0aXZlU3ltYm9sLCBTeW1ib2xQb2x5ZmlsbCwgSGlkZGVuU3ltYm9sLCBnbG9iYWxTeW1ib2xzID0gY3JlYXRlKG51bGwpXG4gICwgaXNOYXRpdmVTYWZlO1xuXG5pZiAodHlwZW9mIFN5bWJvbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHROYXRpdmVTeW1ib2wgPSBTeW1ib2w7XG5cdHRyeSB7XG5cdFx0U3RyaW5nKE5hdGl2ZVN5bWJvbCgpKTtcblx0XHRpc05hdGl2ZVNhZmUgPSB0cnVlO1xuXHR9IGNhdGNoIChpZ25vcmUpIHt9XG59XG5cbnZhciBnZW5lcmF0ZU5hbWUgPSAoZnVuY3Rpb24gKCkge1xuXHR2YXIgY3JlYXRlZCA9IGNyZWF0ZShudWxsKTtcblx0cmV0dXJuIGZ1bmN0aW9uIChkZXNjKSB7XG5cdFx0dmFyIHBvc3RmaXggPSAwLCBuYW1lLCBpZTExQnVnV29ya2Fyb3VuZDtcblx0XHR3aGlsZSAoY3JlYXRlZFtkZXNjICsgKHBvc3RmaXggfHwgJycpXSkgKytwb3N0Zml4O1xuXHRcdGRlc2MgKz0gKHBvc3RmaXggfHwgJycpO1xuXHRcdGNyZWF0ZWRbZGVzY10gPSB0cnVlO1xuXHRcdG5hbWUgPSAnQEAnICsgZGVzYztcblx0XHRkZWZpbmVQcm9wZXJ0eShvYmpQcm90b3R5cGUsIG5hbWUsIGQuZ3MobnVsbCwgZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0XHQvLyBGb3IgSUUxMSBpc3N1ZSBzZWU6XG5cdFx0XHQvLyBodHRwczovL2Nvbm5lY3QubWljcm9zb2Z0LmNvbS9JRS9mZWVkYmFja2RldGFpbC92aWV3LzE5Mjg1MDgvXG5cdFx0XHQvLyAgICBpZTExLWJyb2tlbi1nZXR0ZXJzLW9uLWRvbS1vYmplY3RzXG5cdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vbWVkaWtvby9lczYtc3ltYm9sL2lzc3Vlcy8xMlxuXHRcdFx0aWYgKGllMTFCdWdXb3JrYXJvdW5kKSByZXR1cm47XG5cdFx0XHRpZTExQnVnV29ya2Fyb3VuZCA9IHRydWU7XG5cdFx0XHRkZWZpbmVQcm9wZXJ0eSh0aGlzLCBuYW1lLCBkKHZhbHVlKSk7XG5cdFx0XHRpZTExQnVnV29ya2Fyb3VuZCA9IGZhbHNlO1xuXHRcdH0pKTtcblx0XHRyZXR1cm4gbmFtZTtcblx0fTtcbn0oKSk7XG5cbi8vIEludGVybmFsIGNvbnN0cnVjdG9yIChub3Qgb25lIGV4cG9zZWQpIGZvciBjcmVhdGluZyBTeW1ib2wgaW5zdGFuY2VzLlxuLy8gVGhpcyBvbmUgaXMgdXNlZCB0byBlbnN1cmUgdGhhdCBgc29tZVN5bWJvbCBpbnN0YW5jZW9mIFN5bWJvbGAgYWx3YXlzIHJldHVybiBmYWxzZVxuSGlkZGVuU3ltYm9sID0gZnVuY3Rpb24gU3ltYm9sKGRlc2NyaXB0aW9uKSB7XG5cdGlmICh0aGlzIGluc3RhbmNlb2YgSGlkZGVuU3ltYm9sKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdTeW1ib2wgaXMgbm90IGEgY29uc3RydWN0b3InKTtcblx0cmV0dXJuIFN5bWJvbFBvbHlmaWxsKGRlc2NyaXB0aW9uKTtcbn07XG5cbi8vIEV4cG9zZWQgYFN5bWJvbGAgY29uc3RydWN0b3Jcbi8vIChyZXR1cm5zIGluc3RhbmNlcyBvZiBIaWRkZW5TeW1ib2wpXG5tb2R1bGUuZXhwb3J0cyA9IFN5bWJvbFBvbHlmaWxsID0gZnVuY3Rpb24gU3ltYm9sKGRlc2NyaXB0aW9uKSB7XG5cdHZhciBzeW1ib2w7XG5cdGlmICh0aGlzIGluc3RhbmNlb2YgU3ltYm9sKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdTeW1ib2wgaXMgbm90IGEgY29uc3RydWN0b3InKTtcblx0aWYgKGlzTmF0aXZlU2FmZSkgcmV0dXJuIE5hdGl2ZVN5bWJvbChkZXNjcmlwdGlvbik7XG5cdHN5bWJvbCA9IGNyZWF0ZShIaWRkZW5TeW1ib2wucHJvdG90eXBlKTtcblx0ZGVzY3JpcHRpb24gPSAoZGVzY3JpcHRpb24gPT09IHVuZGVmaW5lZCA/ICcnIDogU3RyaW5nKGRlc2NyaXB0aW9uKSk7XG5cdHJldHVybiBkZWZpbmVQcm9wZXJ0aWVzKHN5bWJvbCwge1xuXHRcdF9fZGVzY3JpcHRpb25fXzogZCgnJywgZGVzY3JpcHRpb24pLFxuXHRcdF9fbmFtZV9fOiBkKCcnLCBnZW5lcmF0ZU5hbWUoZGVzY3JpcHRpb24pKVxuXHR9KTtcbn07XG5kZWZpbmVQcm9wZXJ0aWVzKFN5bWJvbFBvbHlmaWxsLCB7XG5cdGZvcjogZChmdW5jdGlvbiAoa2V5KSB7XG5cdFx0aWYgKGdsb2JhbFN5bWJvbHNba2V5XSkgcmV0dXJuIGdsb2JhbFN5bWJvbHNba2V5XTtcblx0XHRyZXR1cm4gKGdsb2JhbFN5bWJvbHNba2V5XSA9IFN5bWJvbFBvbHlmaWxsKFN0cmluZyhrZXkpKSk7XG5cdH0pLFxuXHRrZXlGb3I6IGQoZnVuY3Rpb24gKHMpIHtcblx0XHR2YXIga2V5O1xuXHRcdHZhbGlkYXRlU3ltYm9sKHMpO1xuXHRcdGZvciAoa2V5IGluIGdsb2JhbFN5bWJvbHMpIGlmIChnbG9iYWxTeW1ib2xzW2tleV0gPT09IHMpIHJldHVybiBrZXk7XG5cdH0pLFxuXG5cdC8vIFRvIGVuc3VyZSBwcm9wZXIgaW50ZXJvcGVyYWJpbGl0eSB3aXRoIG90aGVyIG5hdGl2ZSBmdW5jdGlvbnMgKGUuZy4gQXJyYXkuZnJvbSlcblx0Ly8gZmFsbGJhY2sgdG8gZXZlbnR1YWwgbmF0aXZlIGltcGxlbWVudGF0aW9uIG9mIGdpdmVuIHN5bWJvbFxuXHRoYXNJbnN0YW5jZTogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wuaGFzSW5zdGFuY2UpIHx8IFN5bWJvbFBvbHlmaWxsKCdoYXNJbnN0YW5jZScpKSxcblx0aXNDb25jYXRTcHJlYWRhYmxlOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5pc0NvbmNhdFNwcmVhZGFibGUpIHx8XG5cdFx0U3ltYm9sUG9seWZpbGwoJ2lzQ29uY2F0U3ByZWFkYWJsZScpKSxcblx0aXRlcmF0b3I6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLml0ZXJhdG9yKSB8fCBTeW1ib2xQb2x5ZmlsbCgnaXRlcmF0b3InKSksXG5cdG1hdGNoOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5tYXRjaCkgfHwgU3ltYm9sUG9seWZpbGwoJ21hdGNoJykpLFxuXHRyZXBsYWNlOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5yZXBsYWNlKSB8fCBTeW1ib2xQb2x5ZmlsbCgncmVwbGFjZScpKSxcblx0c2VhcmNoOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5zZWFyY2gpIHx8IFN5bWJvbFBvbHlmaWxsKCdzZWFyY2gnKSksXG5cdHNwZWNpZXM6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLnNwZWNpZXMpIHx8IFN5bWJvbFBvbHlmaWxsKCdzcGVjaWVzJykpLFxuXHRzcGxpdDogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wuc3BsaXQpIHx8IFN5bWJvbFBvbHlmaWxsKCdzcGxpdCcpKSxcblx0dG9QcmltaXRpdmU6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLnRvUHJpbWl0aXZlKSB8fCBTeW1ib2xQb2x5ZmlsbCgndG9QcmltaXRpdmUnKSksXG5cdHRvU3RyaW5nVGFnOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC50b1N0cmluZ1RhZykgfHwgU3ltYm9sUG9seWZpbGwoJ3RvU3RyaW5nVGFnJykpLFxuXHR1bnNjb3BhYmxlczogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wudW5zY29wYWJsZXMpIHx8IFN5bWJvbFBvbHlmaWxsKCd1bnNjb3BhYmxlcycpKVxufSk7XG5cbi8vIEludGVybmFsIHR3ZWFrcyBmb3IgcmVhbCBzeW1ib2wgcHJvZHVjZXJcbmRlZmluZVByb3BlcnRpZXMoSGlkZGVuU3ltYm9sLnByb3RvdHlwZSwge1xuXHRjb25zdHJ1Y3RvcjogZChTeW1ib2xQb2x5ZmlsbCksXG5cdHRvU3RyaW5nOiBkKCcnLCBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9fbmFtZV9fOyB9KVxufSk7XG5cbi8vIFByb3BlciBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGV4cG9zZWQgb24gU3ltYm9sLnByb3RvdHlwZVxuLy8gVGhleSB3b24ndCBiZSBhY2Nlc3NpYmxlIG9uIHByb2R1Y2VkIHN5bWJvbCBpbnN0YW5jZXMgYXMgdGhleSBkZXJpdmUgZnJvbSBIaWRkZW5TeW1ib2wucHJvdG90eXBlXG5kZWZpbmVQcm9wZXJ0aWVzKFN5bWJvbFBvbHlmaWxsLnByb3RvdHlwZSwge1xuXHR0b1N0cmluZzogZChmdW5jdGlvbiAoKSB7IHJldHVybiAnU3ltYm9sICgnICsgdmFsaWRhdGVTeW1ib2wodGhpcykuX19kZXNjcmlwdGlvbl9fICsgJyknOyB9KSxcblx0dmFsdWVPZjogZChmdW5jdGlvbiAoKSB7IHJldHVybiB2YWxpZGF0ZVN5bWJvbCh0aGlzKTsgfSlcbn0pO1xuZGVmaW5lUHJvcGVydHkoU3ltYm9sUG9seWZpbGwucHJvdG90eXBlLCBTeW1ib2xQb2x5ZmlsbC50b1ByaW1pdGl2ZSwgZCgnJywgZnVuY3Rpb24gKCkge1xuXHR2YXIgc3ltYm9sID0gdmFsaWRhdGVTeW1ib2wodGhpcyk7XG5cdGlmICh0eXBlb2Ygc3ltYm9sID09PSAnc3ltYm9sJykgcmV0dXJuIHN5bWJvbDtcblx0cmV0dXJuIHN5bWJvbC50b1N0cmluZygpO1xufSkpO1xuZGVmaW5lUHJvcGVydHkoU3ltYm9sUG9seWZpbGwucHJvdG90eXBlLCBTeW1ib2xQb2x5ZmlsbC50b1N0cmluZ1RhZywgZCgnYycsICdTeW1ib2wnKSk7XG5cbi8vIFByb3BlciBpbXBsZW1lbnRhdG9uIG9mIHRvUHJpbWl0aXZlIGFuZCB0b1N0cmluZ1RhZyBmb3IgcmV0dXJuZWQgc3ltYm9sIGluc3RhbmNlc1xuZGVmaW5lUHJvcGVydHkoSGlkZGVuU3ltYm9sLnByb3RvdHlwZSwgU3ltYm9sUG9seWZpbGwudG9TdHJpbmdUYWcsXG5cdGQoJ2MnLCBTeW1ib2xQb2x5ZmlsbC5wcm90b3R5cGVbU3ltYm9sUG9seWZpbGwudG9TdHJpbmdUYWddKSk7XG5cbi8vIE5vdGU6IEl0J3MgaW1wb3J0YW50IHRvIGRlZmluZSBgdG9QcmltaXRpdmVgIGFzIGxhc3Qgb25lLCBhcyBzb21lIGltcGxlbWVudGF0aW9uc1xuLy8gaW1wbGVtZW50IGB0b1ByaW1pdGl2ZWAgbmF0aXZlbHkgd2l0aG91dCBpbXBsZW1lbnRpbmcgYHRvU3RyaW5nVGFnYCAob3Igb3RoZXIgc3BlY2lmaWVkIHN5bWJvbHMpXG4vLyBBbmQgdGhhdCBtYXkgaW52b2tlIGVycm9yIGluIGRlZmluaXRpb24gZmxvdzpcbi8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL21lZGlrb28vZXM2LXN5bWJvbC9pc3N1ZXMvMTMjaXNzdWVjb21tZW50LTE2NDE0NjE0OVxuZGVmaW5lUHJvcGVydHkoSGlkZGVuU3ltYm9sLnByb3RvdHlwZSwgU3ltYm9sUG9seWZpbGwudG9QcmltaXRpdmUsXG5cdGQoJ2MnLCBTeW1ib2xQb2x5ZmlsbC5wcm90b3R5cGVbU3ltYm9sUG9seWZpbGwudG9QcmltaXRpdmVdKSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBpc1N5bWJvbCA9IHJlcXVpcmUoJy4vaXMtc3ltYm9sJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdGlmICghaXNTeW1ib2wodmFsdWUpKSB0aHJvdyBuZXcgVHlwZUVycm9yKHZhbHVlICsgXCIgaXMgbm90IGEgc3ltYm9sXCIpO1xuXHRyZXR1cm4gdmFsdWU7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vaXMtaW1wbGVtZW50ZWQnKSgpID8gV2Vha01hcCA6IHJlcXVpcmUoJy4vcG9seWZpbGwnKTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciB3ZWFrTWFwLCB4O1xuXHRpZiAodHlwZW9mIFdlYWtNYXAgIT09ICdmdW5jdGlvbicpIHJldHVybiBmYWxzZTtcblx0dHJ5IHtcblx0XHQvLyBXZWJLaXQgZG9lc24ndCBzdXBwb3J0IGFyZ3VtZW50cyBhbmQgY3Jhc2hlc1xuXHRcdHdlYWtNYXAgPSBuZXcgV2Vha01hcChbW3ggPSB7fSwgJ29uZSddLCBbe30sICd0d28nXSwgW3t9LCAndGhyZWUnXV0pO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cdGlmIChTdHJpbmcod2Vha01hcCkgIT09ICdbb2JqZWN0IFdlYWtNYXBdJykgcmV0dXJuIGZhbHNlO1xuXHRpZiAodHlwZW9mIHdlYWtNYXAuc2V0ICE9PSAnZnVuY3Rpb24nKSByZXR1cm4gZmFsc2U7XG5cdGlmICh3ZWFrTWFwLnNldCh7fSwgMSkgIT09IHdlYWtNYXApIHJldHVybiBmYWxzZTtcblx0aWYgKHR5cGVvZiB3ZWFrTWFwLmRlbGV0ZSAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuXHRpZiAodHlwZW9mIHdlYWtNYXAuaGFzICE9PSAnZnVuY3Rpb24nKSByZXR1cm4gZmFsc2U7XG5cdGlmICh3ZWFrTWFwLmdldCh4KSAhPT0gJ29uZScpIHJldHVybiBmYWxzZTtcblxuXHRyZXR1cm4gdHJ1ZTtcbn07XG4iLCIvLyBFeHBvcnRzIHRydWUgaWYgZW52aXJvbm1lbnQgcHJvdmlkZXMgbmF0aXZlIGBXZWFrTWFwYCBpbXBsZW1lbnRhdGlvbiwgd2hhdGV2ZXIgdGhhdCBpcy5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiAoKSB7XG5cdGlmICh0eXBlb2YgV2Vha01hcCAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuXHRyZXR1cm4gKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChuZXcgV2Vha01hcCgpKSA9PT0gJ1tvYmplY3QgV2Vha01hcF0nKTtcbn0oKSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBzZXRQcm90b3R5cGVPZiAgICA9IHJlcXVpcmUoJ2VzNS1leHQvb2JqZWN0L3NldC1wcm90b3R5cGUtb2YnKVxuICAsIG9iamVjdCAgICAgICAgICAgID0gcmVxdWlyZSgnZXM1LWV4dC9vYmplY3QvdmFsaWQtb2JqZWN0JylcbiAgLCB2YWx1ZSAgICAgICAgICAgICA9IHJlcXVpcmUoJ2VzNS1leHQvb2JqZWN0L3ZhbGlkLXZhbHVlJylcbiAgLCByYW5kb21VbmlxICAgICAgICA9IHJlcXVpcmUoJ2VzNS1leHQvc3RyaW5nL3JhbmRvbS11bmlxJylcbiAgLCBkICAgICAgICAgICAgICAgICA9IHJlcXVpcmUoJ2QnKVxuICAsIGdldEl0ZXJhdG9yICAgICAgID0gcmVxdWlyZSgnZXM2LWl0ZXJhdG9yL2dldCcpXG4gICwgZm9yT2YgICAgICAgICAgICAgPSByZXF1aXJlKCdlczYtaXRlcmF0b3IvZm9yLW9mJylcbiAgLCB0b1N0cmluZ1RhZ1N5bWJvbCA9IHJlcXVpcmUoJ2VzNi1zeW1ib2wnKS50b1N0cmluZ1RhZ1xuICAsIGlzTmF0aXZlICAgICAgICAgID0gcmVxdWlyZSgnLi9pcy1uYXRpdmUtaW1wbGVtZW50ZWQnKVxuXG4gICwgaXNBcnJheSA9IEFycmF5LmlzQXJyYXksIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5XG4gICwgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LCBnZXRQcm90b3R5cGVPZiA9IE9iamVjdC5nZXRQcm90b3R5cGVPZlxuICAsIFdlYWtNYXBQb2x5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdlYWtNYXBQb2x5ID0gZnVuY3Rpb24gKC8qaXRlcmFibGUqLykge1xuXHR2YXIgaXRlcmFibGUgPSBhcmd1bWVudHNbMF0sIHNlbGY7XG5cdGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWFrTWFwUG9seSkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0NvbnN0cnVjdG9yIHJlcXVpcmVzIFxcJ25ld1xcJycpO1xuXHRpZiAoaXNOYXRpdmUgJiYgc2V0UHJvdG90eXBlT2YgJiYgKFdlYWtNYXAgIT09IFdlYWtNYXBQb2x5KSkge1xuXHRcdHNlbGYgPSBzZXRQcm90b3R5cGVPZihuZXcgV2Vha01hcCgpLCBnZXRQcm90b3R5cGVPZih0aGlzKSk7XG5cdH0gZWxzZSB7XG5cdFx0c2VsZiA9IHRoaXM7XG5cdH1cblx0aWYgKGl0ZXJhYmxlICE9IG51bGwpIHtcblx0XHRpZiAoIWlzQXJyYXkoaXRlcmFibGUpKSBpdGVyYWJsZSA9IGdldEl0ZXJhdG9yKGl0ZXJhYmxlKTtcblx0fVxuXHRkZWZpbmVQcm9wZXJ0eShzZWxmLCAnX193ZWFrTWFwRGF0YV9fJywgZCgnYycsICckd2Vha01hcCQnICsgcmFuZG9tVW5pcSgpKSk7XG5cdGlmICghaXRlcmFibGUpIHJldHVybiBzZWxmO1xuXHRmb3JPZihpdGVyYWJsZSwgZnVuY3Rpb24gKHZhbCkge1xuXHRcdHZhbHVlKHZhbCk7XG5cdFx0c2VsZi5zZXQodmFsWzBdLCB2YWxbMV0pO1xuXHR9KTtcblx0cmV0dXJuIHNlbGY7XG59O1xuXG5pZiAoaXNOYXRpdmUpIHtcblx0aWYgKHNldFByb3RvdHlwZU9mKSBzZXRQcm90b3R5cGVPZihXZWFrTWFwUG9seSwgV2Vha01hcCk7XG5cdFdlYWtNYXBQb2x5LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoV2Vha01hcC5wcm90b3R5cGUsIHtcblx0XHRjb25zdHJ1Y3RvcjogZChXZWFrTWFwUG9seSlcblx0fSk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFdlYWtNYXBQb2x5LnByb3RvdHlwZSwge1xuXHRkZWxldGU6IGQoZnVuY3Rpb24gKGtleSkge1xuXHRcdGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdChrZXkpLCB0aGlzLl9fd2Vha01hcERhdGFfXykpIHtcblx0XHRcdGRlbGV0ZSBrZXlbdGhpcy5fX3dlYWtNYXBEYXRhX19dO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fSksXG5cdGdldDogZChmdW5jdGlvbiAoa2V5KSB7XG5cdFx0aWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0KGtleSksIHRoaXMuX193ZWFrTWFwRGF0YV9fKSkge1xuXHRcdFx0cmV0dXJuIGtleVt0aGlzLl9fd2Vha01hcERhdGFfX107XG5cdFx0fVxuXHR9KSxcblx0aGFzOiBkKGZ1bmN0aW9uIChrZXkpIHtcblx0XHRyZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3Qoa2V5KSwgdGhpcy5fX3dlYWtNYXBEYXRhX18pO1xuXHR9KSxcblx0c2V0OiBkKGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG5cdFx0ZGVmaW5lUHJvcGVydHkob2JqZWN0KGtleSksIHRoaXMuX193ZWFrTWFwRGF0YV9fLCBkKCdjJywgdmFsdWUpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSksXG5cdHRvU3RyaW5nOiBkKGZ1bmN0aW9uICgpIHsgcmV0dXJuICdbb2JqZWN0IFdlYWtNYXBdJzsgfSlcbn0pO1xuZGVmaW5lUHJvcGVydHkoV2Vha01hcFBvbHkucHJvdG90eXBlLCB0b1N0cmluZ1RhZ1N5bWJvbCwgZCgnYycsICdXZWFrTWFwJykpO1xuIiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBleHRyYWN0UGxhbmVzXG5cbmZ1bmN0aW9uIGV4dHJhY3RQbGFuZXMoTSwgek5lYXIsIHpGYXIpIHtcbiAgdmFyIHogID0gek5lYXIgfHwgMC4wXG4gIHZhciB6ZiA9IHpGYXIgfHwgMS4wXG4gIHJldHVybiBbXG4gICAgWyBNWzEyXSArIE1bMF0sIE1bMTNdICsgTVsxXSwgTVsxNF0gKyBNWzJdLCBNWzE1XSArIE1bM10gXSxcbiAgICBbIE1bMTJdIC0gTVswXSwgTVsxM10gLSBNWzFdLCBNWzE0XSAtIE1bMl0sIE1bMTVdIC0gTVszXSBdLFxuICAgIFsgTVsxMl0gKyBNWzRdLCBNWzEzXSArIE1bNV0sIE1bMTRdICsgTVs2XSwgTVsxNV0gKyBNWzddIF0sXG4gICAgWyBNWzEyXSAtIE1bNF0sIE1bMTNdIC0gTVs1XSwgTVsxNF0gLSBNWzZdLCBNWzE1XSAtIE1bN10gXSxcbiAgICBbIHoqTVsxMl0gKyBNWzhdLCB6Kk1bMTNdICsgTVs5XSwgeipNWzE0XSArIE1bMTBdLCB6Kk1bMTVdICsgTVsxMV0gXSxcbiAgICBbIHpmKk1bMTJdIC0gTVs4XSwgemYqTVsxM10gLSBNWzldLCB6ZipNWzE0XSAtIE1bMTBdLCB6ZipNWzE1XSAtIE1bMTFdIF1cbiAgXVxufSIsIi8qKlxyXG4gKiBpbnNwaXJlZCBieSBpcy1udW1iZXIgPGh0dHBzOi8vZ2l0aHViLmNvbS9qb25zY2hsaW5rZXJ0L2lzLW51bWJlcj5cclxuICogYnV0IHNpZ25pZmljYW50bHkgc2ltcGxpZmllZCBhbmQgc3BlZCB1cCBieSBpZ25vcmluZyBudW1iZXIgYW5kIHN0cmluZyBjb25zdHJ1Y3RvcnNcclxuICogaWUgdGhlc2UgcmV0dXJuIGZhbHNlOlxyXG4gKiAgIG5ldyBOdW1iZXIoMSlcclxuICogICBuZXcgU3RyaW5nKCcxJylcclxuICovXHJcblxyXG4ndXNlIHN0cmljdCc7XHJcblxyXG52YXIgYWxsQmxhbmtDaGFyQ29kZXMgPSByZXF1aXJlKCdpcy1zdHJpbmctYmxhbmsnKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obikge1xyXG4gICAgdmFyIHR5cGUgPSB0eXBlb2YgbjtcclxuICAgIGlmKHR5cGUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgdmFyIG9yaWdpbmFsID0gbjtcclxuICAgICAgICBuID0gK247XHJcbiAgICAgICAgLy8gd2hpdGVzcGFjZSBzdHJpbmdzIGNhc3QgdG8gemVybyAtIGZpbHRlciB0aGVtIG91dFxyXG4gICAgICAgIGlmKG49PT0wICYmIGFsbEJsYW5rQ2hhckNvZGVzKG9yaWdpbmFsKSkgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZih0eXBlICE9PSAnbnVtYmVyJykgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgIHJldHVybiBuIC0gbiA8IDE7XHJcbn07XHJcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUZpbHRlcmVkVmVjdG9yXG5cbnZhciBjdWJpY0hlcm1pdGUgPSByZXF1aXJlKCdjdWJpYy1oZXJtaXRlJylcbnZhciBic2VhcmNoID0gcmVxdWlyZSgnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxuXG5mdW5jdGlvbiBjbGFtcChsbywgaGksIHgpIHtcbiAgcmV0dXJuIE1hdGgubWluKGhpLCBNYXRoLm1heChsbywgeCkpXG59XG5cbmZ1bmN0aW9uIEZpbHRlcmVkVmVjdG9yKHN0YXRlMCwgdmVsb2NpdHkwLCB0MCkge1xuICB0aGlzLmRpbWVuc2lvbiAgPSBzdGF0ZTAubGVuZ3RoXG4gIHRoaXMuYm91bmRzICAgICA9IFsgbmV3IEFycmF5KHRoaXMuZGltZW5zaW9uKSwgbmV3IEFycmF5KHRoaXMuZGltZW5zaW9uKSBdXG4gIGZvcih2YXIgaT0wOyBpPHRoaXMuZGltZW5zaW9uOyArK2kpIHtcbiAgICB0aGlzLmJvdW5kc1swXVtpXSA9IC1JbmZpbml0eVxuICAgIHRoaXMuYm91bmRzWzFdW2ldID0gSW5maW5pdHlcbiAgfVxuICB0aGlzLl9zdGF0ZSAgICAgPSBzdGF0ZTAuc2xpY2UoKS5yZXZlcnNlKClcbiAgdGhpcy5fdmVsb2NpdHkgID0gdmVsb2NpdHkwLnNsaWNlKCkucmV2ZXJzZSgpXG4gIHRoaXMuX3RpbWUgICAgICA9IFsgdDAgXVxuICB0aGlzLl9zY3JhdGNoICAgPSBbIHN0YXRlMC5zbGljZSgpLCBzdGF0ZTAuc2xpY2UoKSwgc3RhdGUwLnNsaWNlKCksIHN0YXRlMC5zbGljZSgpLCBzdGF0ZTAuc2xpY2UoKSBdXG59XG5cbnZhciBwcm90byA9IEZpbHRlcmVkVmVjdG9yLnByb3RvdHlwZVxuXG5wcm90by5mbHVzaCA9IGZ1bmN0aW9uKHQpIHtcbiAgdmFyIGlkeCA9IGJzZWFyY2guZ3QodGhpcy5fdGltZSwgdCkgLSAxXG4gIGlmKGlkeCA8PSAwKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdGhpcy5fdGltZS5zcGxpY2UoMCwgaWR4KVxuICB0aGlzLl9zdGF0ZS5zcGxpY2UoMCwgaWR4ICogdGhpcy5kaW1lbnNpb24pXG4gIHRoaXMuX3ZlbG9jaXR5LnNwbGljZSgwLCBpZHggKiB0aGlzLmRpbWVuc2lvbilcbn1cblxucHJvdG8uY3VydmUgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0aW1lICAgICAgPSB0aGlzLl90aW1lXG4gIHZhciBuICAgICAgICAgPSB0aW1lLmxlbmd0aFxuICB2YXIgaWR4ICAgICAgID0gYnNlYXJjaC5sZSh0aW1lLCB0KVxuICB2YXIgcmVzdWx0ICAgID0gdGhpcy5fc2NyYXRjaFswXVxuICB2YXIgc3RhdGUgICAgID0gdGhpcy5fc3RhdGVcbiAgdmFyIHZlbG9jaXR5ICA9IHRoaXMuX3ZlbG9jaXR5XG4gIHZhciBkICAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgYm91bmRzICAgID0gdGhpcy5ib3VuZHNcbiAgaWYoaWR4IDwgMCkge1xuICAgIHZhciBwdHIgPSBkLTFcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2ksIC0tcHRyKSB7XG4gICAgICByZXN1bHRbaV0gPSBzdGF0ZVtwdHJdXG4gICAgfVxuICB9IGVsc2UgaWYoaWR4ID49IG4tMSkge1xuICAgIHZhciBwdHIgPSBzdGF0ZS5sZW5ndGgtMVxuICAgIHZhciB0ZiA9IHQgLSB0aW1lW24tMV1cbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2ksIC0tcHRyKSB7XG4gICAgICByZXN1bHRbaV0gPSBzdGF0ZVtwdHJdICsgdGYgKiB2ZWxvY2l0eVtwdHJdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBwdHIgPSBkICogKGlkeCsxKSAtIDFcbiAgICB2YXIgdDAgID0gdGltZVtpZHhdXG4gICAgdmFyIHQxICA9IHRpbWVbaWR4KzFdXG4gICAgdmFyIGR0ICA9ICh0MSAtIHQwKSB8fCAxLjBcbiAgICB2YXIgeDAgID0gdGhpcy5fc2NyYXRjaFsxXVxuICAgIHZhciB4MSAgPSB0aGlzLl9zY3JhdGNoWzJdXG4gICAgdmFyIHYwICA9IHRoaXMuX3NjcmF0Y2hbM11cbiAgICB2YXIgdjEgID0gdGhpcy5fc2NyYXRjaFs0XVxuICAgIHZhciBzdGVhZHkgPSB0cnVlXG4gICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpLCAtLXB0cikge1xuICAgICAgeDBbaV0gPSBzdGF0ZVtwdHJdXG4gICAgICB2MFtpXSA9IHZlbG9jaXR5W3B0cl0gKiBkdFxuICAgICAgeDFbaV0gPSBzdGF0ZVtwdHIrZF1cbiAgICAgIHYxW2ldID0gdmVsb2NpdHlbcHRyK2RdICogZHRcbiAgICAgIHN0ZWFkeSA9IHN0ZWFkeSAmJiAoeDBbaV0gPT09IHgxW2ldICYmIHYwW2ldID09PSB2MVtpXSAmJiB2MFtpXSA9PT0gMC4wKVxuICAgIH1cbiAgICBpZihzdGVhZHkpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgICAgICByZXN1bHRbaV0gPSB4MFtpXVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjdWJpY0hlcm1pdGUoeDAsIHYwLCB4MSwgdjEsICh0LXQwKS9kdCwgcmVzdWx0KVxuICAgIH1cbiAgfVxuICB2YXIgbG8gPSBib3VuZHNbMF1cbiAgdmFyIGhpID0gYm91bmRzWzFdXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IGNsYW1wKGxvW2ldLCBoaVtpXSwgcmVzdWx0W2ldKVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxucHJvdG8uZGN1cnZlID0gZnVuY3Rpb24odCkge1xuICB2YXIgdGltZSAgICAgPSB0aGlzLl90aW1lXG4gIHZhciBuICAgICAgICA9IHRpbWUubGVuZ3RoXG4gIHZhciBpZHggICAgICA9IGJzZWFyY2gubGUodGltZSwgdClcbiAgdmFyIHJlc3VsdCAgID0gdGhpcy5fc2NyYXRjaFswXVxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgZCAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICBpZihpZHggPj0gbi0xKSB7XG4gICAgdmFyIHB0ciA9IHN0YXRlLmxlbmd0aC0xXG4gICAgdmFyIHRmID0gdCAtIHRpbWVbbi0xXVxuICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSwgLS1wdHIpIHtcbiAgICAgIHJlc3VsdFtpXSA9IHZlbG9jaXR5W3B0cl1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIHB0ciA9IGQgKiAoaWR4KzEpIC0gMVxuICAgIHZhciB0MCA9IHRpbWVbaWR4XVxuICAgIHZhciB0MSA9IHRpbWVbaWR4KzFdXG4gICAgdmFyIGR0ID0gKHQxIC0gdDApIHx8IDEuMFxuICAgIHZhciB4MCA9IHRoaXMuX3NjcmF0Y2hbMV1cbiAgICB2YXIgeDEgPSB0aGlzLl9zY3JhdGNoWzJdXG4gICAgdmFyIHYwID0gdGhpcy5fc2NyYXRjaFszXVxuICAgIHZhciB2MSA9IHRoaXMuX3NjcmF0Y2hbNF1cbiAgICB2YXIgc3RlYWR5ID0gdHJ1ZVxuICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSwgLS1wdHIpIHtcbiAgICAgIHgwW2ldID0gc3RhdGVbcHRyXVxuICAgICAgdjBbaV0gPSB2ZWxvY2l0eVtwdHJdICogZHRcbiAgICAgIHgxW2ldID0gc3RhdGVbcHRyK2RdXG4gICAgICB2MVtpXSA9IHZlbG9jaXR5W3B0citkXSAqIGR0XG4gICAgICBzdGVhZHkgPSBzdGVhZHkgJiYgKHgwW2ldID09PSB4MVtpXSAmJiB2MFtpXSA9PT0gdjFbaV0gJiYgdjBbaV0gPT09IDAuMClcbiAgICB9XG4gICAgaWYoc3RlYWR5KSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgICAgcmVzdWx0W2ldID0gMC4wXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGN1YmljSGVybWl0ZS5kZXJpdmF0aXZlKHgwLCB2MCwgeDEsIHYxLCAodC10MCkvZHQsIHJlc3VsdClcbiAgICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgICAgICByZXN1bHRbaV0gLz0gZHRcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5sYXN0VCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdGltZSA9IHRoaXMuX3RpbWVcbiAgcmV0dXJuIHRpbWVbdGltZS5sZW5ndGgtMV1cbn1cblxucHJvdG8uc3RhYmxlID0gZnVuY3Rpb24oKSB7XG4gIHZhciB2ZWxvY2l0eSA9IHRoaXMuX3ZlbG9jaXR5XG4gIHZhciBwdHIgPSB2ZWxvY2l0eS5sZW5ndGhcbiAgZm9yKHZhciBpPXRoaXMuZGltZW5zaW9uLTE7IGk+PTA7IC0taSkge1xuICAgIGlmKHZlbG9jaXR5Wy0tcHRyXSkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlXG59XG5cbnByb3RvLmp1bXAgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0MCA9IHRoaXMubGFzdFQoKVxuICB2YXIgZCAgPSB0aGlzLmRpbWVuc2lvblxuICBpZih0IDwgdDAgfHwgYXJndW1lbnRzLmxlbmd0aCAhPT0gZCsxKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIHN0YXRlICAgICA9IHRoaXMuX3N0YXRlXG4gIHZhciB2ZWxvY2l0eSAgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgcHRyICAgICAgID0gc3RhdGUubGVuZ3RoLXRoaXMuZGltZW5zaW9uXG4gIHZhciBib3VuZHMgICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgID0gYm91bmRzWzBdXG4gIHZhciBoaSAgICAgICAgPSBib3VuZHNbMV1cbiAgdGhpcy5fdGltZS5wdXNoKHQwLCB0KVxuICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgIHN0YXRlLnB1c2goc3RhdGVbcHRyKytdKVxuICAgICAgdmVsb2NpdHkucHVzaCgwKVxuICAgIH1cbiAgfVxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQ7IGk+MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpLTFdLCBoaVtpLTFdLCBhcmd1bWVudHNbaV0pKVxuICAgIHZlbG9jaXR5LnB1c2goMClcbiAgfVxufVxuXG5wcm90by5wdXNoID0gZnVuY3Rpb24odCkge1xuICB2YXIgdDAgPSB0aGlzLmxhc3RUKClcbiAgdmFyIGQgID0gdGhpcy5kaW1lbnNpb25cbiAgaWYodCA8IHQwIHx8IGFyZ3VtZW50cy5sZW5ndGggIT09IGQrMSkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBzdGF0ZSAgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgID0gdGhpcy5fdmVsb2NpdHlcbiAgdmFyIHB0ciAgICAgICA9IHN0YXRlLmxlbmd0aC10aGlzLmRpbWVuc2lvblxuICB2YXIgZHQgICAgICAgID0gdCAtIHQwXG4gIHZhciBib3VuZHMgICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgID0gYm91bmRzWzBdXG4gIHZhciBoaSAgICAgICAgPSBib3VuZHNbMV1cbiAgdmFyIHNmICAgICAgICA9IChkdCA+IDFlLTYpID8gMS9kdCA6IDBcbiAgdGhpcy5fdGltZS5wdXNoKHQpXG4gIGZvcih2YXIgaT1kOyBpPjA7IC0taSkge1xuICAgIHZhciB4YyA9IGNsYW1wKGxvW2ktMV0sIGhpW2ktMV0sIGFyZ3VtZW50c1tpXSlcbiAgICBzdGF0ZS5wdXNoKHhjKVxuICAgIHZlbG9jaXR5LnB1c2goKHhjIC0gc3RhdGVbcHRyKytdKSAqIHNmKVxuICB9XG59XG5cbnByb3RvLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgdmFyIGQgPSB0aGlzLmRpbWVuc2lvblxuICBpZih0IDwgdGhpcy5sYXN0VCgpIHx8IGFyZ3VtZW50cy5sZW5ndGggIT09IGQrMSkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBzdGF0ZSAgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgID0gdGhpcy5fdmVsb2NpdHlcbiAgdmFyIGJvdW5kcyAgICA9IHRoaXMuYm91bmRzXG4gIHZhciBsbyAgICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgICA9IGJvdW5kc1sxXVxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQ7IGk+MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpLTFdLCBoaVtpLTFdLCBhcmd1bWVudHNbaV0pKVxuICAgIHZlbG9jaXR5LnB1c2goMClcbiAgfVxufVxuXG5wcm90by5tb3ZlID0gZnVuY3Rpb24odCkge1xuICB2YXIgdDAgPSB0aGlzLmxhc3RUKClcbiAgdmFyIGQgID0gdGhpcy5kaW1lbnNpb25cbiAgaWYodCA8PSB0MCB8fCBhcmd1bWVudHMubGVuZ3RoICE9PSBkKzEpIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgc3RhdGVQdHIgPSBzdGF0ZS5sZW5ndGggLSB0aGlzLmRpbWVuc2lvblxuICB2YXIgYm91bmRzICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgID0gYm91bmRzWzFdXG4gIHZhciBkdCAgICAgICA9IHQgLSB0MFxuICB2YXIgc2YgICAgICAgPSAoZHQgPiAxZS02KSA/IDEvZHQgOiAwLjBcbiAgdGhpcy5fdGltZS5wdXNoKHQpXG4gIGZvcih2YXIgaT1kOyBpPjA7IC0taSkge1xuICAgIHZhciBkeCA9IGFyZ3VtZW50c1tpXVxuICAgIHN0YXRlLnB1c2goY2xhbXAobG9baS0xXSwgaGlbaS0xXSwgc3RhdGVbc3RhdGVQdHIrK10gKyBkeCkpXG4gICAgdmVsb2NpdHkucHVzaChkeCAqIHNmKVxuICB9XG59XG5cbnByb3RvLmlkbGUgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0MCA9IHRoaXMubGFzdFQoKVxuICBpZih0IDwgdDApIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgZCAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgc3RhdGVQdHIgPSBzdGF0ZS5sZW5ndGgtZFxuICB2YXIgYm91bmRzICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgID0gYm91bmRzWzFdXG4gIHZhciBkdCAgICAgICA9IHQgLSB0MFxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQtMTsgaT49MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpXSwgaGlbaV0sIHN0YXRlW3N0YXRlUHRyXSArIGR0ICogdmVsb2NpdHlbc3RhdGVQdHJdKSlcbiAgICB2ZWxvY2l0eS5wdXNoKDApXG4gICAgc3RhdGVQdHIgKz0gMVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldFplcm8oZCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGQpXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IDAuMFxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gY3JlYXRlRmlsdGVyZWRWZWN0b3IoaW5pdFN0YXRlLCBpbml0VmVsb2NpdHksIGluaXRUaW1lKSB7XG4gIHN3aXRjaChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJlZFZlY3RvcihbMF0sIFswXSwgMClcbiAgICBjYXNlIDE6XG4gICAgICBpZih0eXBlb2YgaW5pdFN0YXRlID09PSAnbnVtYmVyJykge1xuICAgICAgICB2YXIgemVybyA9IGdldFplcm8oaW5pdFN0YXRlKVxuICAgICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKHplcm8sIHplcm8sIDApXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKGluaXRTdGF0ZSwgZ2V0WmVybyhpbml0U3RhdGUubGVuZ3RoKSwgMClcbiAgICAgIH1cbiAgICBjYXNlIDI6XG4gICAgICBpZih0eXBlb2YgaW5pdFZlbG9jaXR5ID09PSAnbnVtYmVyJykge1xuICAgICAgICB2YXIgemVybyA9IGdldFplcm8oaW5pdFN0YXRlLmxlbmd0aClcbiAgICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJlZFZlY3Rvcihpbml0U3RhdGUsIHplcm8sICtpbml0VmVsb2NpdHkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0VGltZSA9IDBcbiAgICAgIH1cbiAgICBjYXNlIDM6XG4gICAgICBpZihpbml0U3RhdGUubGVuZ3RoICE9PSBpbml0VmVsb2NpdHkubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc3RhdGUgYW5kIHZlbG9jaXR5IGxlbmd0aHMgbXVzdCBtYXRjaCcpXG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKGluaXRTdGF0ZSwgaW5pdFZlbG9jaXR5LCBpbml0VGltZSlcbiAgfVxufVxuIiwiLyplc2xpbnQgbmV3LWNhcDowKi9cbnZhciBkdHlwZSA9IHJlcXVpcmUoJ2R0eXBlJylcblxubW9kdWxlLmV4cG9ydHMgPSBmbGF0dGVuVmVydGV4RGF0YVxuXG5mdW5jdGlvbiBmbGF0dGVuVmVydGV4RGF0YSAoZGF0YSwgb3V0cHV0LCBvZmZzZXQpIHtcbiAgaWYgKCFkYXRhKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdXN0IHNwZWNpZnkgZGF0YSBhcyBmaXJzdCBwYXJhbWV0ZXInKVxuICBvZmZzZXQgPSArKG9mZnNldCB8fCAwKSB8IDBcblxuICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSAmJiAoZGF0YVswXSAmJiB0eXBlb2YgZGF0YVswXVswXSA9PT0gJ251bWJlcicpKSB7XG4gICAgdmFyIGRpbSA9IGRhdGFbMF0ubGVuZ3RoXG4gICAgdmFyIGxlbmd0aCA9IGRhdGEubGVuZ3RoICogZGltXG4gICAgdmFyIGksIGosIGssIGxcblxuICAgIC8vIG5vIG91dHB1dCBzcGVjaWZpZWQsIGNyZWF0ZSBhIG5ldyB0eXBlZCBhcnJheVxuICAgIGlmICghb3V0cHV0IHx8IHR5cGVvZiBvdXRwdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvdXRwdXQgPSBuZXcgKGR0eXBlKG91dHB1dCB8fCAnZmxvYXQzMicpKShsZW5ndGggKyBvZmZzZXQpXG4gICAgfVxuXG4gICAgdmFyIGRzdExlbmd0aCA9IG91dHB1dC5sZW5ndGggLSBvZmZzZXRcbiAgICBpZiAobGVuZ3RoICE9PSBkc3RMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGxlbmd0aCAnICsgbGVuZ3RoICsgJyAoJyArIGRpbSArICd4JyArIGRhdGEubGVuZ3RoICsgJyknICtcbiAgICAgICAgJyBkb2VzIG5vdCBtYXRjaCBkZXN0aW5hdGlvbiBsZW5ndGggJyArIGRzdExlbmd0aClcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwLCBrID0gb2Zmc2V0OyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgZm9yIChqID0gMDsgaiA8IGRpbTsgaisrKSB7XG4gICAgICAgIG91dHB1dFtrKytdID0gZGF0YVtpXVtqXSA9PT0gbnVsbCA/IE5hTiA6IGRhdGFbaV1bal1cbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFvdXRwdXQgfHwgdHlwZW9mIG91dHB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIC8vIG5vIG91dHB1dCwgY3JlYXRlIGEgbmV3IG9uZVxuICAgICAgdmFyIEN0b3IgPSBkdHlwZShvdXRwdXQgfHwgJ2Zsb2F0MzInKVxuXG4gICAgICAvLyBoYW5kbGUgYXJyYXlzIHNlcGFyYXRlbHkgZHVlIHRvIHBvc3NpYmxlIG51bGxzXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSB8fCBvdXRwdXQgPT09ICdhcnJheScpIHtcbiAgICAgICAgb3V0cHV0ID0gbmV3IEN0b3IoZGF0YS5sZW5ndGggKyBvZmZzZXQpXG4gICAgICAgIGZvciAoaSA9IDAsIGsgPSBvZmZzZXQsIGwgPSBvdXRwdXQubGVuZ3RoOyBrIDwgbDsgaysrLCBpKyspIHtcbiAgICAgICAgICBvdXRwdXRba10gPSBkYXRhW2ldID09PSBudWxsID8gTmFOIDogZGF0YVtpXVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAob2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgb3V0cHV0ID0gbmV3IEN0b3IoZGF0YSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvdXRwdXQgPSBuZXcgQ3RvcihkYXRhLmxlbmd0aCArIG9mZnNldClcblxuICAgICAgICAgIG91dHB1dC5zZXQoZGF0YSwgb2Zmc2V0KVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHN0b3JlIG91dHB1dCBpbiBleGlzdGluZyBhcnJheVxuICAgICAgb3V0cHV0LnNldChkYXRhLCBvZmZzZXQpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG91dHB1dFxufVxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgc3RyaW5naWZ5Rm9udCA9IHJlcXVpcmUoJ2Nzcy1mb250L3N0cmluZ2lmeScpXHJcbnZhciBkZWZhdWx0Q2hhcnMgPSBbMzIsIDEyNl1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gYXRsYXNcclxuXHJcbmZ1bmN0aW9uIGF0bGFzKG9wdGlvbnMpIHtcclxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxyXG5cclxuICB2YXIgc2hhcGUgID0gb3B0aW9ucy5zaGFwZSA/IG9wdGlvbnMuc2hhcGUgOiBvcHRpb25zLmNhbnZhcyA/IFtvcHRpb25zLmNhbnZhcy53aWR0aCwgb3B0aW9ucy5jYW52YXMuaGVpZ2h0XSA6IFs1MTIsIDUxMl1cclxuICB2YXIgY2FudmFzID0gb3B0aW9ucy5jYW52YXMgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcclxuICB2YXIgZm9udCAgID0gb3B0aW9ucy5mb250XHJcbiAgdmFyIHN0ZXAgICA9IHR5cGVvZiBvcHRpb25zLnN0ZXAgPT09ICdudW1iZXInID8gW29wdGlvbnMuc3RlcCwgb3B0aW9ucy5zdGVwXSA6IG9wdGlvbnMuc3RlcCB8fCBbMzIsIDMyXVxyXG4gIHZhciBjaGFycyAgPSBvcHRpb25zLmNoYXJzIHx8IGRlZmF1bHRDaGFyc1xyXG5cclxuICBpZiAoZm9udCAmJiB0eXBlb2YgZm9udCAhPT0gJ3N0cmluZycpIGZvbnQgPSBzdHJpbmdpZnlGb250KGZvbnQpXHJcblxyXG4gIGlmICghQXJyYXkuaXNBcnJheShjaGFycykpIHtcclxuICAgIGNoYXJzID0gU3RyaW5nKGNoYXJzKS5zcGxpdCgnJylcclxuICB9IGVsc2VcclxuICBpZiAoY2hhcnMubGVuZ3RoID09PSAyXHJcbiAgICAmJiB0eXBlb2YgY2hhcnNbMF0gPT09ICdudW1iZXInXHJcbiAgICAmJiB0eXBlb2YgY2hhcnNbMV0gPT09ICdudW1iZXInXHJcbiAgKSB7XHJcbiAgICB2YXIgbmV3Y2hhcnMgPSBbXVxyXG5cclxuICAgIGZvciAodmFyIGkgPSBjaGFyc1swXSwgaiA9IDA7IGkgPD0gY2hhcnNbMV07IGkrKykge1xyXG4gICAgICBuZXdjaGFyc1tqKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZShpKVxyXG4gICAgfVxyXG5cclxuICAgIGNoYXJzID0gbmV3Y2hhcnNcclxuICB9XHJcblxyXG4gIHNoYXBlID0gc2hhcGUuc2xpY2UoKVxyXG4gIGNhbnZhcy53aWR0aCAgPSBzaGFwZVswXVxyXG4gIGNhbnZhcy5oZWlnaHQgPSBzaGFwZVsxXVxyXG5cclxuICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJylcclxuXHJcbiAgY3R4LmZpbGxTdHlsZSA9ICcjMDAwJ1xyXG4gIGN0eC5maWxsUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpXHJcblxyXG4gIGN0eC5mb250ID0gZm9udFxyXG4gIGN0eC50ZXh0QWxpZ24gPSAnY2VudGVyJ1xyXG4gIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJ1xyXG4gIGN0eC5maWxsU3R5bGUgPSAnI2ZmZidcclxuXHJcbiAgdmFyIHggPSBzdGVwWzBdIC8gMlxyXG4gIHZhciB5ID0gc3RlcFsxXSAvIDJcclxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNoYXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICBjdHguZmlsbFRleHQoY2hhcnNbaV0sIHgsIHkpXHJcbiAgICBpZiAoKHggKz0gc3RlcFswXSkgPiBzaGFwZVswXSAtIHN0ZXBbMF0vMikgKHggPSBzdGVwWzBdLzIpLCAoeSArPSBzdGVwWzFdKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGNhbnZhc1xyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBtZWFzdXJlXHJcblxyXG5tZWFzdXJlLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbm1lYXN1cmUuY2FjaGUgPSB7fVxyXG5cclxuZnVuY3Rpb24gbWVhc3VyZSAoZm9udCwgbykge1xyXG5cdGlmICghbykgbyA9IHt9XHJcblxyXG5cdGlmICh0eXBlb2YgZm9udCA9PT0gJ3N0cmluZycgfHwgQXJyYXkuaXNBcnJheShmb250KSkge1xyXG5cdFx0by5mYW1pbHkgPSBmb250XHJcblx0fVxyXG5cclxuXHR2YXIgZmFtaWx5ID0gQXJyYXkuaXNBcnJheShvLmZhbWlseSkgPyBvLmZhbWlseS5qb2luKCcsICcpIDogby5mYW1pbHlcclxuXHRpZiAoIWZhbWlseSkgdGhyb3cgRXJyb3IoJ2BmYW1pbHlgIG11c3QgYmUgZGVmaW5lZCcpXHJcblxyXG5cdHZhciBmcyA9IG8uc2l6ZSB8fCBvLmZvbnRTaXplIHx8IG8uZW0gfHwgNDhcclxuXHR2YXIgd2VpZ2h0ID0gby53ZWlnaHQgfHwgby5mb250V2VpZ2h0IHx8ICcnXHJcblx0dmFyIHN0eWxlID0gby5zdHlsZSB8fCBvLmZvbnRTdHlsZSB8fCAnJ1xyXG5cdHZhciBmb250ID0gW3N0eWxlLCB3ZWlnaHQsIGZzXS5qb2luKCcgJykgKyAncHggJyArIGZhbWlseVxyXG5cdHZhciBvcmlnaW4gPSBvLm9yaWdpbiB8fCAndG9wJ1xyXG5cclxuXHRpZiAobWVhc3VyZS5jYWNoZVtmYW1pbHldKSB7XHJcblx0XHQvLyByZXR1cm4gbW9yZSBwcmVjaXNlIHZhbHVlcyBpZiBjYWNoZSBoYXMgdGhlbVxyXG5cdFx0aWYgKGZzIDw9IG1lYXN1cmUuY2FjaGVbZmFtaWx5XS5lbSkge1xyXG5cdFx0XHRyZXR1cm4gYXBwbHlPcmlnaW4obWVhc3VyZS5jYWNoZVtmYW1pbHldLCBvcmlnaW4pXHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHR2YXIgY2FudmFzID0gby5jYW52YXMgfHwgbWVhc3VyZS5jYW52YXNcclxuXHR2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJylcclxuXHR2YXIgY2hhcnMgPSB7XHJcblx0XHR1cHBlcjogby51cHBlciAhPT0gdW5kZWZpbmVkID8gby51cHBlciA6ICdIJyxcclxuXHRcdGxvd2VyOiBvLmxvd2VyICE9PSB1bmRlZmluZWQgPyBvLmxvd2VyIDogJ3gnLFxyXG5cdFx0ZGVzY2VudDogby5kZXNjZW50ICE9PSB1bmRlZmluZWQgPyBvLmRlc2NlbnQgOiAncCcsXHJcblx0XHRhc2NlbnQ6IG8uYXNjZW50ICE9PSB1bmRlZmluZWQgPyBvLmFzY2VudCA6ICdoJyxcclxuXHRcdHRpdHRsZTogby50aXR0bGUgIT09IHVuZGVmaW5lZCA/IG8udGl0dGxlIDogJ2knLFxyXG5cdFx0b3ZlcnNob290OiBvLm92ZXJzaG9vdCAhPT0gdW5kZWZpbmVkID8gby5vdmVyc2hvb3QgOiAnTydcclxuXHR9XHJcblx0dmFyIGwgPSBNYXRoLmNlaWwoZnMgKiAxLjUpXHJcblx0Y2FudmFzLmhlaWdodCA9IGxcclxuXHRjYW52YXMud2lkdGggPSBsICogLjVcclxuXHRjdHguZm9udCA9IGZvbnRcclxuXHJcblx0dmFyIGNoYXIgPSAnSCdcclxuXHR2YXIgcmVzdWx0ID0ge1xyXG5cdFx0dG9wOiAwXHJcblx0fVxyXG5cclxuXHQvLyBtZWFzdXJlIGxpbmUtaGVpZ2h0XHJcblx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdGN0eC50ZXh0QmFzZWxpbmUgPSAndG9wJ1xyXG5cdGN0eC5maWxsU3R5bGUgPSAnYmxhY2snXHJcblx0Y3R4LmZpbGxUZXh0KGNoYXIsIDAsIDApXHJcblx0dmFyIHRvcFB4ID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0Y3R4LnRleHRCYXNlbGluZSA9ICdib3R0b20nXHJcblx0Y3R4LmZpbGxUZXh0KGNoYXIsIDAsIGwpXHJcblx0dmFyIGJvdHRvbVB4ID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHRyZXN1bHQubGluZUhlaWdodCA9XHJcblx0cmVzdWx0LmJvdHRvbSA9IGwgLSBib3R0b21QeCArIHRvcFB4XHJcblxyXG5cdC8vIG1lYXN1cmUgYmFzZWxpbmVcclxuXHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0Y3R4LnRleHRCYXNlbGluZSA9ICdhbHBoYWJldGljJ1xyXG5cdGN0eC5maWxsVGV4dChjaGFyLCAwLCBsKVxyXG5cdHZhciBiYXNlbGluZVB4ID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHR2YXIgYmFzZWxpbmUgPSBsIC0gYmFzZWxpbmVQeCAtIDEgKyB0b3BQeFxyXG5cdHJlc3VsdC5iYXNlbGluZSA9XHJcblx0cmVzdWx0LmFscGhhYmV0aWMgPSBiYXNlbGluZVxyXG5cclxuXHQvLyBtZWFzdXJlIG1lZGlhblxyXG5cdGN0eC5jbGVhclJlY3QoMCwgMCwgbCwgbClcclxuXHRjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSdcclxuXHRjdHguZmlsbFRleHQoY2hhciwgMCwgbCAqIC41KVxyXG5cdHZhciBtZWRpYW5QeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0cmVzdWx0Lm1lZGlhbiA9XHJcblx0cmVzdWx0Lm1pZGRsZSA9IGwgLSBtZWRpYW5QeCAtIDEgKyB0b3BQeCAtIGwgKiAuNVxyXG5cclxuXHQvLyBtZWFzdXJlIGhhbmdpbmdcclxuXHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0Y3R4LnRleHRCYXNlbGluZSA9ICdoYW5naW5nJ1xyXG5cdGN0eC5maWxsVGV4dChjaGFyLCAwLCBsICogLjUpXHJcblx0dmFyIGhhbmdpbmdQeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0cmVzdWx0LmhhbmdpbmcgPSBsIC0gaGFuZ2luZ1B4IC0gMSArIHRvcFB4IC0gbCAqIC41XHJcblxyXG5cdC8vIG1lYXN1cmUgaWRlb2dyYXBoaWNcclxuXHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0Y3R4LnRleHRCYXNlbGluZSA9ICdpZGVvZ3JhcGhpYydcclxuXHRjdHguZmlsbFRleHQoY2hhciwgMCwgbClcclxuXHR2YXIgaWRlb2dyYXBoaWNQeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0cmVzdWx0LmlkZW9ncmFwaGljID0gbCAtIGlkZW9ncmFwaGljUHggLSAxICsgdG9wUHhcclxuXHJcblx0Ly8gbWVhc3VyZSBjYXBcclxuXHRpZiAoY2hhcnMudXBwZXIpIHtcclxuXHRcdGN0eC5jbGVhclJlY3QoMCwgMCwgbCwgbClcclxuXHRcdGN0eC50ZXh0QmFzZWxpbmUgPSAndG9wJ1xyXG5cdFx0Y3R4LmZpbGxUZXh0KGNoYXJzLnVwcGVyLCAwLCAwKVxyXG5cdFx0cmVzdWx0LnVwcGVyID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHRcdHJlc3VsdC5jYXBIZWlnaHQgPSAocmVzdWx0LmJhc2VsaW5lIC0gcmVzdWx0LnVwcGVyKVxyXG5cdH1cclxuXHJcblx0Ly8gbWVhc3VyZSB4XHJcblx0aWYgKGNoYXJzLmxvd2VyKSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy5sb3dlciwgMCwgMClcclxuXHRcdHJlc3VsdC5sb3dlciA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0XHRyZXN1bHQueEhlaWdodCA9IChyZXN1bHQuYmFzZWxpbmUgLSByZXN1bHQubG93ZXIpXHJcblx0fVxyXG5cclxuXHQvLyBtZWFzdXJlIHRpdHRsZVxyXG5cdGlmIChjaGFycy50aXR0bGUpIHtcclxuXHRcdGN0eC5jbGVhclJlY3QoMCwgMCwgbCwgbClcclxuXHRcdGN0eC50ZXh0QmFzZWxpbmUgPSAndG9wJ1xyXG5cdFx0Y3R4LmZpbGxUZXh0KGNoYXJzLnRpdHRsZSwgMCwgMClcclxuXHRcdHJlc3VsdC50aXR0bGUgPSBmaXJzdFRvcChjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdH1cclxuXHJcblx0Ly8gbWVhc3VyZSBhc2NlbnRcclxuXHRpZiAoY2hhcnMuYXNjZW50KSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy5hc2NlbnQsIDAsIDApXHJcblx0XHRyZXN1bHQuYXNjZW50ID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHR9XHJcblxyXG5cdC8vIG1lYXN1cmUgZGVzY2VudFxyXG5cdGlmIChjaGFycy5kZXNjZW50KSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy5kZXNjZW50LCAwLCAwKVxyXG5cdFx0cmVzdWx0LmRlc2NlbnQgPSBmaXJzdEJvdHRvbShjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdH1cclxuXHJcblx0Ly8gbWVhc3VyZSBvdmVyc2hvb3RcclxuXHRpZiAoY2hhcnMub3ZlcnNob290KSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy5vdmVyc2hvb3QsIDAsIDApXHJcblx0XHR2YXIgb3ZlcnNob290UHggPSBmaXJzdEJvdHRvbShjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdFx0cmVzdWx0Lm92ZXJzaG9vdCA9IG92ZXJzaG9vdFB4IC0gYmFzZWxpbmVcclxuXHR9XHJcblxyXG5cdC8vIG5vcm1hbGl6ZSByZXN1bHRcclxuXHRmb3IgKHZhciBuYW1lIGluIHJlc3VsdCkge1xyXG5cdFx0cmVzdWx0W25hbWVdIC89IGZzXHJcblx0fVxyXG5cclxuXHRyZXN1bHQuZW0gPSBmc1xyXG5cdG1lYXN1cmUuY2FjaGVbZmFtaWx5XSA9IHJlc3VsdFxyXG5cclxuXHRyZXR1cm4gYXBwbHlPcmlnaW4ocmVzdWx0LCBvcmlnaW4pXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFwcGx5T3JpZ2luKG9iaiwgb3JpZ2luKSB7XHJcblx0dmFyIHJlcyA9IHt9XHJcblx0aWYgKHR5cGVvZiBvcmlnaW4gPT09ICdzdHJpbmcnKSBvcmlnaW4gPSBvYmpbb3JpZ2luXVxyXG5cdGZvciAodmFyIG5hbWUgaW4gb2JqKSB7XHJcblx0XHRpZiAobmFtZSA9PT0gJ2VtJykgY29udGludWVcclxuXHRcdHJlc1tuYW1lXSA9IG9ialtuYW1lXSAtIG9yaWdpblxyXG5cdH1cclxuXHRyZXR1cm4gcmVzXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZpcnN0VG9wKGlEYXRhKSB7XHJcblx0dmFyIGwgPSBpRGF0YS5oZWlnaHRcclxuXHR2YXIgZGF0YSA9IGlEYXRhLmRhdGFcclxuXHRmb3IgKHZhciBpID0gMzsgaSA8IGRhdGEubGVuZ3RoOyBpKz00KSB7XHJcblx0XHRpZiAoZGF0YVtpXSAhPT0gMCkge1xyXG5cdFx0XHRyZXR1cm4gTWF0aC5mbG9vcigoaSAtIDMpICouMjUgLyBsKVxyXG5cdFx0fVxyXG5cdH1cclxufVxyXG5cclxuZnVuY3Rpb24gZmlyc3RCb3R0b20oaURhdGEpIHtcclxuXHR2YXIgbCA9IGlEYXRhLmhlaWdodFxyXG5cdHZhciBkYXRhID0gaURhdGEuZGF0YVxyXG5cdGZvciAodmFyIGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPiAwOyBpIC09IDQpIHtcclxuXHRcdGlmIChkYXRhW2ldICE9PSAwKSB7XHJcblx0XHRcdHJldHVybiBNYXRoLmZsb29yKChpIC0gMykgKi4yNSAvIGwpXHJcblx0XHR9XHJcblx0fVxyXG59XHJcbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlUkJUcmVlXG5cbnZhciBSRUQgICA9IDBcbnZhciBCTEFDSyA9IDFcblxuZnVuY3Rpb24gUkJOb2RlKGNvbG9yLCBrZXksIHZhbHVlLCBsZWZ0LCByaWdodCwgY291bnQpIHtcbiAgdGhpcy5fY29sb3IgPSBjb2xvclxuICB0aGlzLmtleSA9IGtleVxuICB0aGlzLnZhbHVlID0gdmFsdWVcbiAgdGhpcy5sZWZ0ID0gbGVmdFxuICB0aGlzLnJpZ2h0ID0gcmlnaHRcbiAgdGhpcy5fY291bnQgPSBjb3VudFxufVxuXG5mdW5jdGlvbiBjbG9uZU5vZGUobm9kZSkge1xuICByZXR1cm4gbmV3IFJCTm9kZShub2RlLl9jb2xvciwgbm9kZS5rZXksIG5vZGUudmFsdWUsIG5vZGUubGVmdCwgbm9kZS5yaWdodCwgbm9kZS5fY291bnQpXG59XG5cbmZ1bmN0aW9uIHJlcGFpbnQoY29sb3IsIG5vZGUpIHtcbiAgcmV0dXJuIG5ldyBSQk5vZGUoY29sb3IsIG5vZGUua2V5LCBub2RlLnZhbHVlLCBub2RlLmxlZnQsIG5vZGUucmlnaHQsIG5vZGUuX2NvdW50KVxufVxuXG5mdW5jdGlvbiByZWNvdW50KG5vZGUpIHtcbiAgbm9kZS5fY291bnQgPSAxICsgKG5vZGUubGVmdCA/IG5vZGUubGVmdC5fY291bnQgOiAwKSArIChub2RlLnJpZ2h0ID8gbm9kZS5yaWdodC5fY291bnQgOiAwKVxufVxuXG5mdW5jdGlvbiBSZWRCbGFja1RyZWUoY29tcGFyZSwgcm9vdCkge1xuICB0aGlzLl9jb21wYXJlID0gY29tcGFyZVxuICB0aGlzLnJvb3QgPSByb290XG59XG5cbnZhciBwcm90byA9IFJlZEJsYWNrVHJlZS5wcm90b3R5cGVcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBcImtleXNcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZXN1bHQgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbihrLHYpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGspXG4gICAgfSlcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbn0pXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywgXCJ2YWx1ZXNcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZXN1bHQgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbihrLHYpIHtcbiAgICAgIHJlc3VsdC5wdXNoKHYpXG4gICAgfSlcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbn0pXG5cbi8vUmV0dXJucyB0aGUgbnVtYmVyIG9mIG5vZGVzIGluIHRoZSB0cmVlXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sIFwibGVuZ3RoXCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICBpZih0aGlzLnJvb3QpIHtcbiAgICAgIHJldHVybiB0aGlzLnJvb3QuX2NvdW50XG4gICAgfVxuICAgIHJldHVybiAwXG4gIH1cbn0pXG5cbi8vSW5zZXJ0IGEgbmV3IGl0ZW0gaW50byB0aGUgdHJlZVxucHJvdG8uaW5zZXJ0ID0gZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICAvL0ZpbmQgcG9pbnQgdG8gaW5zZXJ0IG5ldyBub2RlIGF0XG4gIHZhciBuID0gdGhpcy5yb290XG4gIHZhciBuX3N0YWNrID0gW11cbiAgdmFyIGRfc3RhY2sgPSBbXVxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBuX3N0YWNrLnB1c2gobilcbiAgICBkX3N0YWNrLnB1c2goZClcbiAgICBpZihkIDw9IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgLy9SZWJ1aWxkIHBhdGggdG8gbGVhZiBub2RlXG4gIG5fc3RhY2sucHVzaChuZXcgUkJOb2RlKFJFRCwga2V5LCB2YWx1ZSwgbnVsbCwgbnVsbCwgMSkpXG4gIGZvcih2YXIgcz1uX3N0YWNrLmxlbmd0aC0yOyBzPj0wOyAtLXMpIHtcbiAgICB2YXIgbiA9IG5fc3RhY2tbc11cbiAgICBpZihkX3N0YWNrW3NdIDw9IDApIHtcbiAgICAgIG5fc3RhY2tbc10gPSBuZXcgUkJOb2RlKG4uX2NvbG9yLCBuLmtleSwgbi52YWx1ZSwgbl9zdGFja1tzKzFdLCBuLnJpZ2h0LCBuLl9jb3VudCsxKVxuICAgIH0gZWxzZSB7XG4gICAgICBuX3N0YWNrW3NdID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG4ubGVmdCwgbl9zdGFja1tzKzFdLCBuLl9jb3VudCsxKVxuICAgIH1cbiAgfVxuICAvL1JlYmFsYW5jZSB0cmVlIHVzaW5nIHJvdGF0aW9uc1xuICAvL2NvbnNvbGUubG9nKFwic3RhcnQgaW5zZXJ0XCIsIGtleSwgZF9zdGFjaylcbiAgZm9yKHZhciBzPW5fc3RhY2subGVuZ3RoLTE7IHM+MTsgLS1zKSB7XG4gICAgdmFyIHAgPSBuX3N0YWNrW3MtMV1cbiAgICB2YXIgbiA9IG5fc3RhY2tbc11cbiAgICBpZihwLl9jb2xvciA9PT0gQkxBQ0sgfHwgbi5fY29sb3IgPT09IEJMQUNLKSB7XG4gICAgICBicmVha1xuICAgIH1cbiAgICB2YXIgcHAgPSBuX3N0YWNrW3MtMl1cbiAgICBpZihwcC5sZWZ0ID09PSBwKSB7XG4gICAgICBpZihwLmxlZnQgPT09IG4pIHtcbiAgICAgICAgdmFyIHkgPSBwcC5yaWdodFxuICAgICAgICBpZih5ICYmIHkuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTExyXCIpXG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHBwLnJpZ2h0ID0gcmVwYWludChCTEFDSywgeSlcbiAgICAgICAgICBwcC5fY29sb3IgPSBSRURcbiAgICAgICAgICBzIC09IDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTExiXCIpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcHAubGVmdCA9IHAucmlnaHRcbiAgICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgcC5yaWdodCA9IHBwXG4gICAgICAgICAgbl9zdGFja1tzLTJdID0gcFxuICAgICAgICAgIG5fc3RhY2tbcy0xXSA9IG5cbiAgICAgICAgICByZWNvdW50KHBwKVxuICAgICAgICAgIHJlY291bnQocClcbiAgICAgICAgICBpZihzID49IDMpIHtcbiAgICAgICAgICAgIHZhciBwcHAgPSBuX3N0YWNrW3MtM11cbiAgICAgICAgICAgIGlmKHBwcC5sZWZ0ID09PSBwcCkge1xuICAgICAgICAgICAgICBwcHAubGVmdCA9IHBcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBwcC5yaWdodCA9IHBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHkgPSBwcC5yaWdodFxuICAgICAgICBpZih5ICYmIHkuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTFJyXCIpXG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHBwLnJpZ2h0ID0gcmVwYWludChCTEFDSywgeSlcbiAgICAgICAgICBwcC5fY29sb3IgPSBSRURcbiAgICAgICAgICBzIC09IDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiTFJiXCIpXG4gICAgICAgICAgcC5yaWdodCA9IG4ubGVmdFxuICAgICAgICAgIHBwLl9jb2xvciA9IFJFRFxuICAgICAgICAgIHBwLmxlZnQgPSBuLnJpZ2h0XG4gICAgICAgICAgbi5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIG4ubGVmdCA9IHBcbiAgICAgICAgICBuLnJpZ2h0ID0gcHBcbiAgICAgICAgICBuX3N0YWNrW3MtMl0gPSBuXG4gICAgICAgICAgbl9zdGFja1tzLTFdID0gcFxuICAgICAgICAgIHJlY291bnQocHApXG4gICAgICAgICAgcmVjb3VudChwKVxuICAgICAgICAgIHJlY291bnQobilcbiAgICAgICAgICBpZihzID49IDMpIHtcbiAgICAgICAgICAgIHZhciBwcHAgPSBuX3N0YWNrW3MtM11cbiAgICAgICAgICAgIGlmKHBwcC5sZWZ0ID09PSBwcCkge1xuICAgICAgICAgICAgICBwcHAubGVmdCA9IG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBwcC5yaWdodCA9IG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZihwLnJpZ2h0ID09PSBuKSB7XG4gICAgICAgIHZhciB5ID0gcHAubGVmdFxuICAgICAgICBpZih5ICYmIHkuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiUlJyXCIsIHkua2V5KVxuICAgICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBwcC5sZWZ0ID0gcmVwYWludChCTEFDSywgeSlcbiAgICAgICAgICBwcC5fY29sb3IgPSBSRURcbiAgICAgICAgICBzIC09IDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiUlJiXCIpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcHAucmlnaHQgPSBwLmxlZnRcbiAgICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgcC5sZWZ0ID0gcHBcbiAgICAgICAgICBuX3N0YWNrW3MtMl0gPSBwXG4gICAgICAgICAgbl9zdGFja1tzLTFdID0gblxuICAgICAgICAgIHJlY291bnQocHApXG4gICAgICAgICAgcmVjb3VudChwKVxuICAgICAgICAgIGlmKHMgPj0gMykge1xuICAgICAgICAgICAgdmFyIHBwcCA9IG5fc3RhY2tbcy0zXVxuICAgICAgICAgICAgaWYocHBwLnJpZ2h0ID09PSBwcCkge1xuICAgICAgICAgICAgICBwcHAucmlnaHQgPSBwXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwcHAubGVmdCA9IHBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHkgPSBwcC5sZWZ0XG4gICAgICAgIGlmKHkgJiYgeS5fY29sb3IgPT09IFJFRCkge1xuICAgICAgICAgIC8vY29uc29sZS5sb2coXCJSTHJcIilcbiAgICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgcHAubGVmdCA9IHJlcGFpbnQoQkxBQ0ssIHkpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcyAtPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIlJMYlwiKVxuICAgICAgICAgIHAubGVmdCA9IG4ucmlnaHRcbiAgICAgICAgICBwcC5fY29sb3IgPSBSRURcbiAgICAgICAgICBwcC5yaWdodCA9IG4ubGVmdFxuICAgICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBuLnJpZ2h0ID0gcFxuICAgICAgICAgIG4ubGVmdCA9IHBwXG4gICAgICAgICAgbl9zdGFja1tzLTJdID0gblxuICAgICAgICAgIG5fc3RhY2tbcy0xXSA9IHBcbiAgICAgICAgICByZWNvdW50KHBwKVxuICAgICAgICAgIHJlY291bnQocClcbiAgICAgICAgICByZWNvdW50KG4pXG4gICAgICAgICAgaWYocyA+PSAzKSB7XG4gICAgICAgICAgICB2YXIgcHBwID0gbl9zdGFja1tzLTNdXG4gICAgICAgICAgICBpZihwcHAucmlnaHQgPT09IHBwKSB7XG4gICAgICAgICAgICAgIHBwcC5yaWdodCA9IG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBwcC5sZWZ0ID0gblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIC8vUmV0dXJuIG5ldyB0cmVlXG4gIG5fc3RhY2tbMF0uX2NvbG9yID0gQkxBQ0tcbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWUoY21wLCBuX3N0YWNrWzBdKVxufVxuXG5cbi8vVmlzaXQgYWxsIG5vZGVzIGlub3JkZXJcbmZ1bmN0aW9uIGRvVmlzaXRGdWxsKHZpc2l0LCBub2RlKSB7XG4gIGlmKG5vZGUubGVmdCkge1xuICAgIHZhciB2ID0gZG9WaXNpdEZ1bGwodmlzaXQsIG5vZGUubGVmdClcbiAgICBpZih2KSB7IHJldHVybiB2IH1cbiAgfVxuICB2YXIgdiA9IHZpc2l0KG5vZGUua2V5LCBub2RlLnZhbHVlKVxuICBpZih2KSB7IHJldHVybiB2IH1cbiAgaWYobm9kZS5yaWdodCkge1xuICAgIHJldHVybiBkb1Zpc2l0RnVsbCh2aXNpdCwgbm9kZS5yaWdodClcbiAgfVxufVxuXG4vL1Zpc2l0IGhhbGYgbm9kZXMgaW4gb3JkZXJcbmZ1bmN0aW9uIGRvVmlzaXRIYWxmKGxvLCBjb21wYXJlLCB2aXNpdCwgbm9kZSkge1xuICB2YXIgbCA9IGNvbXBhcmUobG8sIG5vZGUua2V5KVxuICBpZihsIDw9IDApIHtcbiAgICBpZihub2RlLmxlZnQpIHtcbiAgICAgIHZhciB2ID0gZG9WaXNpdEhhbGYobG8sIGNvbXBhcmUsIHZpc2l0LCBub2RlLmxlZnQpXG4gICAgICBpZih2KSB7IHJldHVybiB2IH1cbiAgICB9XG4gICAgdmFyIHYgPSB2aXNpdChub2RlLmtleSwgbm9kZS52YWx1ZSlcbiAgICBpZih2KSB7IHJldHVybiB2IH1cbiAgfVxuICBpZihub2RlLnJpZ2h0KSB7XG4gICAgcmV0dXJuIGRvVmlzaXRIYWxmKGxvLCBjb21wYXJlLCB2aXNpdCwgbm9kZS5yaWdodClcbiAgfVxufVxuXG4vL1Zpc2l0IGFsbCBub2RlcyB3aXRoaW4gYSByYW5nZVxuZnVuY3Rpb24gZG9WaXNpdChsbywgaGksIGNvbXBhcmUsIHZpc2l0LCBub2RlKSB7XG4gIHZhciBsID0gY29tcGFyZShsbywgbm9kZS5rZXkpXG4gIHZhciBoID0gY29tcGFyZShoaSwgbm9kZS5rZXkpXG4gIHZhciB2XG4gIGlmKGwgPD0gMCkge1xuICAgIGlmKG5vZGUubGVmdCkge1xuICAgICAgdiA9IGRvVmlzaXQobG8sIGhpLCBjb21wYXJlLCB2aXNpdCwgbm9kZS5sZWZ0KVxuICAgICAgaWYodikgeyByZXR1cm4gdiB9XG4gICAgfVxuICAgIGlmKGggPiAwKSB7XG4gICAgICB2ID0gdmlzaXQobm9kZS5rZXksIG5vZGUudmFsdWUpXG4gICAgICBpZih2KSB7IHJldHVybiB2IH1cbiAgICB9XG4gIH1cbiAgaWYoaCA+IDAgJiYgbm9kZS5yaWdodCkge1xuICAgIHJldHVybiBkb1Zpc2l0KGxvLCBoaSwgY29tcGFyZSwgdmlzaXQsIG5vZGUucmlnaHQpXG4gIH1cbn1cblxuXG5wcm90by5mb3JFYWNoID0gZnVuY3Rpb24gcmJUcmVlRm9yRWFjaCh2aXNpdCwgbG8sIGhpKSB7XG4gIGlmKCF0aGlzLnJvb3QpIHtcbiAgICByZXR1cm5cbiAgfVxuICBzd2l0Y2goYXJndW1lbnRzLmxlbmd0aCkge1xuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiBkb1Zpc2l0RnVsbCh2aXNpdCwgdGhpcy5yb290KVxuICAgIGJyZWFrXG5cbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gZG9WaXNpdEhhbGYobG8sIHRoaXMuX2NvbXBhcmUsIHZpc2l0LCB0aGlzLnJvb3QpXG4gICAgYnJlYWtcblxuICAgIGNhc2UgMzpcbiAgICAgIGlmKHRoaXMuX2NvbXBhcmUobG8sIGhpKSA+PSAwKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgcmV0dXJuIGRvVmlzaXQobG8sIGhpLCB0aGlzLl9jb21wYXJlLCB2aXNpdCwgdGhpcy5yb290KVxuICAgIGJyZWFrXG4gIH1cbn1cblxuLy9GaXJzdCBpdGVtIGluIGxpc3Rcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywgXCJiZWdpblwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHN0YWNrID0gW11cbiAgICB2YXIgbiA9IHRoaXMucm9vdFxuICAgIHdoaWxlKG4pIHtcbiAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBzdGFjaylcbiAgfVxufSlcblxuLy9MYXN0IGl0ZW0gaW4gbGlzdFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBcImVuZFwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHN0YWNrID0gW11cbiAgICB2YXIgbiA9IHRoaXMucm9vdFxuICAgIHdoaWxlKG4pIHtcbiAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgc3RhY2spXG4gIH1cbn0pXG5cbi8vRmluZCB0aGUgaXRoIGl0ZW0gaW4gdGhlIHRyZWVcbnByb3RvLmF0ID0gZnVuY3Rpb24oaWR4KSB7XG4gIGlmKGlkeCA8IDApIHtcbiAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIFtdKVxuICB9XG4gIHZhciBuID0gdGhpcy5yb290XG4gIHZhciBzdGFjayA9IFtdXG4gIHdoaWxlKHRydWUpIHtcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYobi5sZWZ0KSB7XG4gICAgICBpZihpZHggPCBuLmxlZnQuX2NvdW50KSB7XG4gICAgICAgIG4gPSBuLmxlZnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGlkeCAtPSBuLmxlZnQuX2NvdW50XG4gICAgfVxuICAgIGlmKCFpZHgpIHtcbiAgICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgc3RhY2spXG4gICAgfVxuICAgIGlkeCAtPSAxXG4gICAgaWYobi5yaWdodCkge1xuICAgICAgaWYoaWR4ID49IG4ucmlnaHQuX2NvdW50KSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBuID0gbi5yaWdodFxuICAgIH0gZWxzZSB7XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIFtdKVxufVxuXG5wcm90by5nZSA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgc3RhY2sgPSBbXVxuICB2YXIgbGFzdF9wdHIgPSAwXG4gIHdoaWxlKG4pIHtcbiAgICB2YXIgZCA9IGNtcChrZXksIG4ua2V5KVxuICAgIHN0YWNrLnB1c2gobilcbiAgICBpZihkIDw9IDApIHtcbiAgICAgIGxhc3RfcHRyID0gc3RhY2subGVuZ3RoXG4gICAgfVxuICAgIGlmKGQgPD0gMCkge1xuICAgICAgbiA9IG4ubGVmdFxuICAgIH0gZWxzZSB7XG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgfVxuICBzdGFjay5sZW5ndGggPSBsYXN0X3B0clxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxufVxuXG5wcm90by5ndCA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgc3RhY2sgPSBbXVxuICB2YXIgbGFzdF9wdHIgPSAwXG4gIHdoaWxlKG4pIHtcbiAgICB2YXIgZCA9IGNtcChrZXksIG4ua2V5KVxuICAgIHN0YWNrLnB1c2gobilcbiAgICBpZihkIDwgMCkge1xuICAgICAgbGFzdF9wdHIgPSBzdGFjay5sZW5ndGhcbiAgICB9XG4gICAgaWYoZCA8IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgc3RhY2subGVuZ3RoID0gbGFzdF9wdHJcbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBzdGFjaylcbn1cblxucHJvdG8ubHQgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgdmFyIHN0YWNrID0gW11cbiAgdmFyIGxhc3RfcHRyID0gMFxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYoZCA+IDApIHtcbiAgICAgIGxhc3RfcHRyID0gc3RhY2subGVuZ3RoXG4gICAgfVxuICAgIGlmKGQgPD0gMCkge1xuICAgICAgbiA9IG4ubGVmdFxuICAgIH0gZWxzZSB7XG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgfVxuICBzdGFjay5sZW5ndGggPSBsYXN0X3B0clxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxufVxuXG5wcm90by5sZSA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgc3RhY2sgPSBbXVxuICB2YXIgbGFzdF9wdHIgPSAwXG4gIHdoaWxlKG4pIHtcbiAgICB2YXIgZCA9IGNtcChrZXksIG4ua2V5KVxuICAgIHN0YWNrLnB1c2gobilcbiAgICBpZihkID49IDApIHtcbiAgICAgIGxhc3RfcHRyID0gc3RhY2subGVuZ3RoXG4gICAgfVxuICAgIGlmKGQgPCAwKSB7XG4gICAgICBuID0gbi5sZWZ0XG4gICAgfSBlbHNlIHtcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9XG4gIHN0YWNrLmxlbmd0aCA9IGxhc3RfcHRyXG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgc3RhY2spXG59XG5cbi8vRmluZHMgdGhlIGl0ZW0gd2l0aCBrZXkgaWYgaXQgZXhpc3RzXG5wcm90by5maW5kID0gZnVuY3Rpb24oa2V5KSB7XG4gIHZhciBjbXAgPSB0aGlzLl9jb21wYXJlXG4gIHZhciBuID0gdGhpcy5yb290XG4gIHZhciBzdGFjayA9IFtdXG4gIHdoaWxlKG4pIHtcbiAgICB2YXIgZCA9IGNtcChrZXksIG4ua2V5KVxuICAgIHN0YWNrLnB1c2gobilcbiAgICBpZihkID09PSAwKSB7XG4gICAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxuICAgIH1cbiAgICBpZihkIDw9IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBbXSlcbn1cblxuLy9SZW1vdmVzIGl0ZW0gd2l0aCBrZXkgZnJvbSB0cmVlXG5wcm90by5yZW1vdmUgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGl0ZXIgPSB0aGlzLmZpbmQoa2V5KVxuICBpZihpdGVyKSB7XG4gICAgcmV0dXJuIGl0ZXIucmVtb3ZlKClcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG4vL1JldHVybnMgdGhlIGl0ZW0gYXQgYGtleWBcbnByb3RvLmdldCA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBpZihkID09PSAwKSB7XG4gICAgICByZXR1cm4gbi52YWx1ZVxuICAgIH1cbiAgICBpZihkIDw9IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgcmV0dXJuXG59XG5cbi8vSXRlcmF0b3IgZm9yIHJlZCBibGFjayB0cmVlXG5mdW5jdGlvbiBSZWRCbGFja1RyZWVJdGVyYXRvcih0cmVlLCBzdGFjaykge1xuICB0aGlzLnRyZWUgPSB0cmVlXG4gIHRoaXMuX3N0YWNrID0gc3RhY2tcbn1cblxudmFyIGlwcm90byA9IFJlZEJsYWNrVHJlZUl0ZXJhdG9yLnByb3RvdHlwZVxuXG4vL1Rlc3QgaWYgaXRlcmF0b3IgaXMgdmFsaWRcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwidmFsaWRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9zdGFjay5sZW5ndGggPiAwXG4gIH1cbn0pXG5cbi8vTm9kZSBvZiB0aGUgaXRlcmF0b3Jcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwibm9kZVwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5fc3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3N0YWNrW3RoaXMuX3N0YWNrLmxlbmd0aC0xXVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9LFxuICBlbnVtZXJhYmxlOiB0cnVlXG59KVxuXG4vL01ha2VzIGEgY29weSBvZiBhbiBpdGVyYXRvclxuaXByb3RvLmNsb25lID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcy50cmVlLCB0aGlzLl9zdGFjay5zbGljZSgpKVxufVxuXG4vL1N3YXBzIHR3byBub2Rlc1xuZnVuY3Rpb24gc3dhcE5vZGUobiwgdikge1xuICBuLmtleSA9IHYua2V5XG4gIG4udmFsdWUgPSB2LnZhbHVlXG4gIG4ubGVmdCA9IHYubGVmdFxuICBuLnJpZ2h0ID0gdi5yaWdodFxuICBuLl9jb2xvciA9IHYuX2NvbG9yXG4gIG4uX2NvdW50ID0gdi5fY291bnRcbn1cblxuLy9GaXggdXAgYSBkb3VibGUgYmxhY2sgbm9kZSBpbiBhIHRyZWVcbmZ1bmN0aW9uIGZpeERvdWJsZUJsYWNrKHN0YWNrKSB7XG4gIHZhciBuLCBwLCBzLCB6XG4gIGZvcih2YXIgaT1zdGFjay5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgbiA9IHN0YWNrW2ldXG4gICAgaWYoaSA9PT0gMCkge1xuICAgICAgbi5fY29sb3IgPSBCTEFDS1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIC8vY29uc29sZS5sb2coXCJ2aXNpdCBub2RlOlwiLCBuLmtleSwgaSwgc3RhY2tbaV0ua2V5LCBzdGFja1tpLTFdLmtleSlcbiAgICBwID0gc3RhY2tbaS0xXVxuICAgIGlmKHAubGVmdCA9PT0gbikge1xuICAgICAgLy9jb25zb2xlLmxvZyhcImxlZnQgY2hpbGRcIilcbiAgICAgIHMgPSBwLnJpZ2h0XG4gICAgICBpZihzLnJpZ2h0ICYmIHMucmlnaHQuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMTogcmlnaHQgc2libGluZyBjaGlsZCByZWRcIilcbiAgICAgICAgcyA9IHAucmlnaHQgPSBjbG9uZU5vZGUocylcbiAgICAgICAgeiA9IHMucmlnaHQgPSBjbG9uZU5vZGUocy5yaWdodClcbiAgICAgICAgcC5yaWdodCA9IHMubGVmdFxuICAgICAgICBzLmxlZnQgPSBwXG4gICAgICAgIHMucmlnaHQgPSB6XG4gICAgICAgIHMuX2NvbG9yID0gcC5fY29sb3JcbiAgICAgICAgbi5fY29sb3IgPSBCTEFDS1xuICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIHouX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcmVjb3VudChwKVxuICAgICAgICByZWNvdW50KHMpXG4gICAgICAgIGlmKGkgPiAxKSB7XG4gICAgICAgICAgdmFyIHBwID0gc3RhY2tbaS0yXVxuICAgICAgICAgIGlmKHBwLmxlZnQgPT09IHApIHtcbiAgICAgICAgICAgIHBwLmxlZnQgPSBzXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBwLnJpZ2h0ID0gc1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja1tpLTFdID0gc1xuICAgICAgICByZXR1cm5cbiAgICAgIH0gZWxzZSBpZihzLmxlZnQgJiYgcy5sZWZ0Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgIC8vY29uc29sZS5sb2coXCJjYXNlIDE6IGxlZnQgc2libGluZyBjaGlsZCByZWRcIilcbiAgICAgICAgcyA9IHAucmlnaHQgPSBjbG9uZU5vZGUocylcbiAgICAgICAgeiA9IHMubGVmdCA9IGNsb25lTm9kZShzLmxlZnQpXG4gICAgICAgIHAucmlnaHQgPSB6LmxlZnRcbiAgICAgICAgcy5sZWZ0ID0gei5yaWdodFxuICAgICAgICB6LmxlZnQgPSBwXG4gICAgICAgIHoucmlnaHQgPSBzXG4gICAgICAgIHouX2NvbG9yID0gcC5fY29sb3JcbiAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICBzLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcmVjb3VudChwKVxuICAgICAgICByZWNvdW50KHMpXG4gICAgICAgIHJlY291bnQoeilcbiAgICAgICAgaWYoaSA+IDEpIHtcbiAgICAgICAgICB2YXIgcHAgPSBzdGFja1tpLTJdXG4gICAgICAgICAgaWYocHAubGVmdCA9PT0gcCkge1xuICAgICAgICAgICAgcHAubGVmdCA9IHpcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHAucmlnaHQgPSB6XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YWNrW2ktMV0gPSB6XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgaWYocy5fY29sb3IgPT09IEJMQUNLKSB7XG4gICAgICAgIGlmKHAuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAyOiBibGFjayBzaWJsaW5nLCByZWQgcGFyZW50XCIsIHAucmlnaHQudmFsdWUpXG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHAucmlnaHQgPSByZXBhaW50KFJFRCwgcylcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAyOiBibGFjayBzaWJsaW5nLCBibGFjayBwYXJlbnRcIiwgcC5yaWdodC52YWx1ZSlcbiAgICAgICAgICBwLnJpZ2h0ID0gcmVwYWludChSRUQsIHMpXG4gICAgICAgICAgY29udGludWUgIFxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAzOiByZWQgc2libGluZ1wiKVxuICAgICAgICBzID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHAucmlnaHQgPSBzLmxlZnRcbiAgICAgICAgcy5sZWZ0ID0gcFxuICAgICAgICBzLl9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIHAuX2NvbG9yID0gUkVEXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICBpZihpID4gMSkge1xuICAgICAgICAgIHZhciBwcCA9IHN0YWNrW2ktMl1cbiAgICAgICAgICBpZihwcC5sZWZ0ID09PSBwKSB7XG4gICAgICAgICAgICBwcC5sZWZ0ID0gc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcC5yaWdodCA9IHNcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2tbaS0xXSA9IHNcbiAgICAgICAgc3RhY2tbaV0gPSBwXG4gICAgICAgIGlmKGkrMSA8IHN0YWNrLmxlbmd0aCkge1xuICAgICAgICAgIHN0YWNrW2krMV0gPSBuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3RhY2sucHVzaChuKVxuICAgICAgICB9XG4gICAgICAgIGkgPSBpKzJcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy9jb25zb2xlLmxvZyhcInJpZ2h0IGNoaWxkXCIpXG4gICAgICBzID0gcC5sZWZ0XG4gICAgICBpZihzLmxlZnQgJiYgcy5sZWZ0Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgIC8vY29uc29sZS5sb2coXCJjYXNlIDE6IGxlZnQgc2libGluZyBjaGlsZCByZWRcIiwgcC52YWx1ZSwgcC5fY29sb3IpXG4gICAgICAgIHMgPSBwLmxlZnQgPSBjbG9uZU5vZGUocylcbiAgICAgICAgeiA9IHMubGVmdCA9IGNsb25lTm9kZShzLmxlZnQpXG4gICAgICAgIHAubGVmdCA9IHMucmlnaHRcbiAgICAgICAgcy5yaWdodCA9IHBcbiAgICAgICAgcy5sZWZ0ID0gelxuICAgICAgICBzLl9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICB6Ll9jb2xvciA9IEJMQUNLXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICBpZihpID4gMSkge1xuICAgICAgICAgIHZhciBwcCA9IHN0YWNrW2ktMl1cbiAgICAgICAgICBpZihwcC5yaWdodCA9PT0gcCkge1xuICAgICAgICAgICAgcHAucmlnaHQgPSBzXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBwLmxlZnQgPSBzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YWNrW2ktMV0gPSBzXG4gICAgICAgIHJldHVyblxuICAgICAgfSBlbHNlIGlmKHMucmlnaHQgJiYgcy5yaWdodC5fY29sb3IgPT09IFJFRCkge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAxOiByaWdodCBzaWJsaW5nIGNoaWxkIHJlZFwiKVxuICAgICAgICBzID0gcC5sZWZ0ID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHogPSBzLnJpZ2h0ID0gY2xvbmVOb2RlKHMucmlnaHQpXG4gICAgICAgIHAubGVmdCA9IHoucmlnaHRcbiAgICAgICAgcy5yaWdodCA9IHoubGVmdFxuICAgICAgICB6LnJpZ2h0ID0gcFxuICAgICAgICB6LmxlZnQgPSBzXG4gICAgICAgIHouX2NvbG9yID0gcC5fY29sb3JcbiAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICBzLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcmVjb3VudChwKVxuICAgICAgICByZWNvdW50KHMpXG4gICAgICAgIHJlY291bnQoeilcbiAgICAgICAgaWYoaSA+IDEpIHtcbiAgICAgICAgICB2YXIgcHAgPSBzdGFja1tpLTJdXG4gICAgICAgICAgaWYocHAucmlnaHQgPT09IHApIHtcbiAgICAgICAgICAgIHBwLnJpZ2h0ID0gelxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcC5sZWZ0ID0gelxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja1tpLTFdID0gelxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmKHMuX2NvbG9yID09PSBCTEFDSykge1xuICAgICAgICBpZihwLl9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMjogYmxhY2sgc2libGluZywgcmVkIHBhcmVudFwiKVxuICAgICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBwLmxlZnQgPSByZXBhaW50KFJFRCwgcylcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAyOiBibGFjayBzaWJsaW5nLCBibGFjayBwYXJlbnRcIilcbiAgICAgICAgICBwLmxlZnQgPSByZXBhaW50KFJFRCwgcylcbiAgICAgICAgICBjb250aW51ZSAgXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vY29uc29sZS5sb2coXCJjYXNlIDM6IHJlZCBzaWJsaW5nXCIpXG4gICAgICAgIHMgPSBjbG9uZU5vZGUocylcbiAgICAgICAgcC5sZWZ0ID0gcy5yaWdodFxuICAgICAgICBzLnJpZ2h0ID0gcFxuICAgICAgICBzLl9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIHAuX2NvbG9yID0gUkVEXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICBpZihpID4gMSkge1xuICAgICAgICAgIHZhciBwcCA9IHN0YWNrW2ktMl1cbiAgICAgICAgICBpZihwcC5yaWdodCA9PT0gcCkge1xuICAgICAgICAgICAgcHAucmlnaHQgPSBzXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBwLmxlZnQgPSBzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YWNrW2ktMV0gPSBzXG4gICAgICAgIHN0YWNrW2ldID0gcFxuICAgICAgICBpZihpKzEgPCBzdGFjay5sZW5ndGgpIHtcbiAgICAgICAgICBzdGFja1tpKzFdID0gblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgICAgfVxuICAgICAgICBpID0gaSsyXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vUmVtb3ZlcyBpdGVtIGF0IGl0ZXJhdG9yIGZyb20gdHJlZVxuaXByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc3RhY2sgPSB0aGlzLl9zdGFja1xuICBpZihzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdGhpcy50cmVlXG4gIH1cbiAgLy9GaXJzdCBjb3B5IHBhdGggdG8gbm9kZVxuICB2YXIgY3N0YWNrID0gbmV3IEFycmF5KHN0YWNrLmxlbmd0aClcbiAgdmFyIG4gPSBzdGFja1tzdGFjay5sZW5ndGgtMV1cbiAgY3N0YWNrW2NzdGFjay5sZW5ndGgtMV0gPSBuZXcgUkJOb2RlKG4uX2NvbG9yLCBuLmtleSwgbi52YWx1ZSwgbi5sZWZ0LCBuLnJpZ2h0LCBuLl9jb3VudClcbiAgZm9yKHZhciBpPXN0YWNrLmxlbmd0aC0yOyBpPj0wOyAtLWkpIHtcbiAgICB2YXIgbiA9IHN0YWNrW2ldXG4gICAgaWYobi5sZWZ0ID09PSBzdGFja1tpKzFdKSB7XG4gICAgICBjc3RhY2tbaV0gPSBuZXcgUkJOb2RlKG4uX2NvbG9yLCBuLmtleSwgbi52YWx1ZSwgY3N0YWNrW2krMV0sIG4ucmlnaHQsIG4uX2NvdW50KVxuICAgIH0gZWxzZSB7XG4gICAgICBjc3RhY2tbaV0gPSBuZXcgUkJOb2RlKG4uX2NvbG9yLCBuLmtleSwgbi52YWx1ZSwgbi5sZWZ0LCBjc3RhY2tbaSsxXSwgbi5fY291bnQpXG4gICAgfVxuICB9XG5cbiAgLy9HZXQgbm9kZVxuICBuID0gY3N0YWNrW2NzdGFjay5sZW5ndGgtMV1cbiAgLy9jb25zb2xlLmxvZyhcInN0YXJ0IHJlbW92ZTogXCIsIG4udmFsdWUpXG5cbiAgLy9JZiBub3QgbGVhZiwgdGhlbiBzd2FwIHdpdGggcHJldmlvdXMgbm9kZVxuICBpZihuLmxlZnQgJiYgbi5yaWdodCkge1xuICAgIC8vY29uc29sZS5sb2coXCJtb3ZpbmcgdG8gbGVhZlwiKVxuXG4gICAgLy9GaXJzdCB3YWxrIHRvIHByZXZpb3VzIGxlYWZcbiAgICB2YXIgc3BsaXQgPSBjc3RhY2subGVuZ3RoXG4gICAgbiA9IG4ubGVmdFxuICAgIHdoaWxlKG4ucmlnaHQpIHtcbiAgICAgIGNzdGFjay5wdXNoKG4pXG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgICAvL0NvcHkgcGF0aCB0byBsZWFmXG4gICAgdmFyIHYgPSBjc3RhY2tbc3BsaXQtMV1cbiAgICBjc3RhY2sucHVzaChuZXcgUkJOb2RlKG4uX2NvbG9yLCB2LmtleSwgdi52YWx1ZSwgbi5sZWZ0LCBuLnJpZ2h0LCBuLl9jb3VudCkpXG4gICAgY3N0YWNrW3NwbGl0LTFdLmtleSA9IG4ua2V5XG4gICAgY3N0YWNrW3NwbGl0LTFdLnZhbHVlID0gbi52YWx1ZVxuXG4gICAgLy9GaXggdXAgc3RhY2tcbiAgICBmb3IodmFyIGk9Y3N0YWNrLmxlbmd0aC0yOyBpPj1zcGxpdDsgLS1pKSB7XG4gICAgICBuID0gY3N0YWNrW2ldXG4gICAgICBjc3RhY2tbaV0gPSBuZXcgUkJOb2RlKG4uX2NvbG9yLCBuLmtleSwgbi52YWx1ZSwgbi5sZWZ0LCBjc3RhY2tbaSsxXSwgbi5fY291bnQpXG4gICAgfVxuICAgIGNzdGFja1tzcGxpdC0xXS5sZWZ0ID0gY3N0YWNrW3NwbGl0XVxuICB9XG4gIC8vY29uc29sZS5sb2coXCJzdGFjaz1cIiwgY3N0YWNrLm1hcChmdW5jdGlvbih2KSB7IHJldHVybiB2LnZhbHVlIH0pKVxuXG4gIC8vUmVtb3ZlIGxlYWYgbm9kZVxuICBuID0gY3N0YWNrW2NzdGFjay5sZW5ndGgtMV1cbiAgaWYobi5fY29sb3IgPT09IFJFRCkge1xuICAgIC8vRWFzeSBjYXNlOiByZW1vdmluZyByZWQgbGVhZlxuICAgIC8vY29uc29sZS5sb2coXCJSRUQgbGVhZlwiKVxuICAgIHZhciBwID0gY3N0YWNrW2NzdGFjay5sZW5ndGgtMl1cbiAgICBpZihwLmxlZnQgPT09IG4pIHtcbiAgICAgIHAubGVmdCA9IG51bGxcbiAgICB9IGVsc2UgaWYocC5yaWdodCA9PT0gbikge1xuICAgICAgcC5yaWdodCA9IG51bGxcbiAgICB9XG4gICAgY3N0YWNrLnBvcCgpXG4gICAgZm9yKHZhciBpPTA7IGk8Y3N0YWNrLmxlbmd0aDsgKytpKSB7XG4gICAgICBjc3RhY2tbaV0uX2NvdW50LS1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWUodGhpcy50cmVlLl9jb21wYXJlLCBjc3RhY2tbMF0pXG4gIH0gZWxzZSB7XG4gICAgaWYobi5sZWZ0IHx8IG4ucmlnaHQpIHtcbiAgICAgIC8vU2Vjb25kIGVhc3kgY2FzZTogIFNpbmdsZSBjaGlsZCBibGFjayBwYXJlbnRcbiAgICAgIC8vY29uc29sZS5sb2coXCJCTEFDSyBzaW5nbGUgY2hpbGRcIilcbiAgICAgIGlmKG4ubGVmdCkge1xuICAgICAgICBzd2FwTm9kZShuLCBuLmxlZnQpXG4gICAgICB9IGVsc2UgaWYobi5yaWdodCkge1xuICAgICAgICBzd2FwTm9kZShuLCBuLnJpZ2h0KVxuICAgICAgfVxuICAgICAgLy9DaGlsZCBtdXN0IGJlIHJlZCwgc28gcmVwYWludCBpdCBibGFjayB0byBiYWxhbmNlIGNvbG9yXG4gICAgICBuLl9jb2xvciA9IEJMQUNLXG4gICAgICBmb3IodmFyIGk9MDsgaTxjc3RhY2subGVuZ3RoLTE7ICsraSkge1xuICAgICAgICBjc3RhY2tbaV0uX2NvdW50LS1cbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlKHRoaXMudHJlZS5fY29tcGFyZSwgY3N0YWNrWzBdKVxuICAgIH0gZWxzZSBpZihjc3RhY2subGVuZ3RoID09PSAxKSB7XG4gICAgICAvL1RoaXJkIGVhc3kgY2FzZTogcm9vdFxuICAgICAgLy9jb25zb2xlLmxvZyhcIlJPT1RcIilcbiAgICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlKHRoaXMudHJlZS5fY29tcGFyZSwgbnVsbClcbiAgICB9IGVsc2Uge1xuICAgICAgLy9IYXJkIGNhc2U6IFJlcGFpbnQgbiwgYW5kIHRoZW4gZG8gc29tZSBuYXN0eSBzdHVmZlxuICAgICAgLy9jb25zb2xlLmxvZyhcIkJMQUNLIGxlYWYgbm8gY2hpbGRyZW5cIilcbiAgICAgIGZvcih2YXIgaT0wOyBpPGNzdGFjay5sZW5ndGg7ICsraSkge1xuICAgICAgICBjc3RhY2tbaV0uX2NvdW50LS1cbiAgICAgIH1cbiAgICAgIHZhciBwYXJlbnQgPSBjc3RhY2tbY3N0YWNrLmxlbmd0aC0yXVxuICAgICAgZml4RG91YmxlQmxhY2soY3N0YWNrKVxuICAgICAgLy9GaXggdXAgbGlua3NcbiAgICAgIGlmKHBhcmVudC5sZWZ0ID09PSBuKSB7XG4gICAgICAgIHBhcmVudC5sZWZ0ID0gbnVsbFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyZW50LnJpZ2h0ID0gbnVsbFxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZSh0aGlzLnRyZWUuX2NvbXBhcmUsIGNzdGFja1swXSlcbn1cblxuLy9SZXR1cm5zIGtleVxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGlwcm90bywgXCJrZXlcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMuX3N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGgtMV0ua2V5XG4gICAgfVxuICAgIHJldHVyblxuICB9LFxuICBlbnVtZXJhYmxlOiB0cnVlXG59KVxuXG4vL1JldHVybnMgdmFsdWVcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwidmFsdWVcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMuX3N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGgtMV0udmFsdWVcbiAgICB9XG4gICAgcmV0dXJuXG4gIH0sXG4gIGVudW1lcmFibGU6IHRydWVcbn0pXG5cblxuLy9SZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGlzIGl0ZXJhdG9yIGluIHRoZSBzb3J0ZWQgbGlzdFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGlwcm90bywgXCJpbmRleFwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGlkeCA9IDBcbiAgICB2YXIgc3RhY2sgPSB0aGlzLl9zdGFja1xuICAgIGlmKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdmFyIHIgPSB0aGlzLnRyZWUucm9vdFxuICAgICAgaWYocikge1xuICAgICAgICByZXR1cm4gci5fY291bnRcbiAgICAgIH1cbiAgICAgIHJldHVybiAwXG4gICAgfSBlbHNlIGlmKHN0YWNrW3N0YWNrLmxlbmd0aC0xXS5sZWZ0KSB7XG4gICAgICBpZHggPSBzdGFja1tzdGFjay5sZW5ndGgtMV0ubGVmdC5fY291bnRcbiAgICB9XG4gICAgZm9yKHZhciBzPXN0YWNrLmxlbmd0aC0yOyBzPj0wOyAtLXMpIHtcbiAgICAgIGlmKHN0YWNrW3MrMV0gPT09IHN0YWNrW3NdLnJpZ2h0KSB7XG4gICAgICAgICsraWR4XG4gICAgICAgIGlmKHN0YWNrW3NdLmxlZnQpIHtcbiAgICAgICAgICBpZHggKz0gc3RhY2tbc10ubGVmdC5fY291bnRcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaWR4XG4gIH0sXG4gIGVudW1lcmFibGU6IHRydWVcbn0pXG5cbi8vQWR2YW5jZXMgaXRlcmF0b3IgdG8gbmV4dCBlbGVtZW50IGluIGxpc3Rcbmlwcm90by5uZXh0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzdGFjayA9IHRoaXMuX3N0YWNrXG4gIGlmKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBuID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdXG4gIGlmKG4ucmlnaHQpIHtcbiAgICBuID0gbi5yaWdodFxuICAgIHdoaWxlKG4pIHtcbiAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgc3RhY2sucG9wKClcbiAgICB3aGlsZShzdGFjay5sZW5ndGggPiAwICYmIHN0YWNrW3N0YWNrLmxlbmd0aC0xXS5yaWdodCA9PT0gbikge1xuICAgICAgbiA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXVxuICAgICAgc3RhY2sucG9wKClcbiAgICB9XG4gIH1cbn1cblxuLy9DaGVja3MgaWYgaXRlcmF0b3IgaXMgYXQgZW5kIG9mIHRyZWVcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwiaGFzTmV4dFwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgICBpZihzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihzdGFja1tzdGFjay5sZW5ndGgtMV0ucmlnaHQpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIGZvcih2YXIgcz1zdGFjay5sZW5ndGgtMTsgcz4wOyAtLXMpIHtcbiAgICAgIGlmKHN0YWNrW3MtMV0ubGVmdCA9PT0gc3RhY2tbc10pIHtcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn0pXG5cbi8vVXBkYXRlIHZhbHVlXG5pcHJvdG8udXBkYXRlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgaWYoc3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgdXBkYXRlIGVtcHR5IG5vZGUhXCIpXG4gIH1cbiAgdmFyIGNzdGFjayA9IG5ldyBBcnJheShzdGFjay5sZW5ndGgpXG4gIHZhciBuID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdXG4gIGNzdGFja1tjc3RhY2subGVuZ3RoLTFdID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIHZhbHVlLCBuLmxlZnQsIG4ucmlnaHQsIG4uX2NvdW50KVxuICBmb3IodmFyIGk9c3RhY2subGVuZ3RoLTI7IGk+PTA7IC0taSkge1xuICAgIG4gPSBzdGFja1tpXVxuICAgIGlmKG4ubGVmdCA9PT0gc3RhY2tbaSsxXSkge1xuICAgICAgY3N0YWNrW2ldID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIGNzdGFja1tpKzFdLCBuLnJpZ2h0LCBuLl9jb3VudClcbiAgICB9IGVsc2Uge1xuICAgICAgY3N0YWNrW2ldID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG4ubGVmdCwgY3N0YWNrW2krMV0sIG4uX2NvdW50KVxuICAgIH1cbiAgfVxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZSh0aGlzLnRyZWUuX2NvbXBhcmUsIGNzdGFja1swXSlcbn1cblxuLy9Nb3ZlcyBpdGVyYXRvciBiYWNrd2FyZCBvbmUgZWxlbWVudFxuaXByb3RvLnByZXYgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgaWYoc3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIG4gPSBzdGFja1tzdGFjay5sZW5ndGgtMV1cbiAgaWYobi5sZWZ0KSB7XG4gICAgbiA9IG4ubGVmdFxuICAgIHdoaWxlKG4pIHtcbiAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHN0YWNrLnBvcCgpXG4gICAgd2hpbGUoc3RhY2subGVuZ3RoID4gMCAmJiBzdGFja1tzdGFjay5sZW5ndGgtMV0ubGVmdCA9PT0gbikge1xuICAgICAgbiA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXVxuICAgICAgc3RhY2sucG9wKClcbiAgICB9XG4gIH1cbn1cblxuLy9DaGVja3MgaWYgaXRlcmF0b3IgaXMgYXQgc3RhcnQgb2YgdHJlZVxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGlwcm90bywgXCJoYXNQcmV2XCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgc3RhY2sgPSB0aGlzLl9zdGFja1xuICAgIGlmKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmKHN0YWNrW3N0YWNrLmxlbmd0aC0xXS5sZWZ0KSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICBmb3IodmFyIHM9c3RhY2subGVuZ3RoLTE7IHM+MDsgLS1zKSB7XG4gICAgICBpZihzdGFja1tzLTFdLnJpZ2h0ID09PSBzdGFja1tzXSkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufSlcblxuLy9EZWZhdWx0IGNvbXBhcmlzb24gZnVuY3Rpb25cbmZ1bmN0aW9uIGRlZmF1bHRDb21wYXJlKGEsIGIpIHtcbiAgaWYoYSA8IGIpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZihhID4gYikge1xuICAgIHJldHVybiAxXG4gIH1cbiAgcmV0dXJuIDBcbn1cblxuLy9CdWlsZCBhIHRyZWVcbmZ1bmN0aW9uIGNyZWF0ZVJCVHJlZShjb21wYXJlKSB7XG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlKGNvbXBhcmUgfHwgZGVmYXVsdENvbXBhcmUsIG51bGwpXG59IiwiLy8gdHJhbnNsaXRlcmF0ZWQgZnJvbSB0aGUgcHl0aG9uIHNuaXBwZXQgaGVyZTpcbi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGFuY3pvc19hcHByb3hpbWF0aW9uXG5cbnZhciBnID0gNztcbnZhciBwID0gW1xuICAgIDAuOTk5OTk5OTk5OTk5ODA5OTMsXG4gICAgNjc2LjUyMDM2ODEyMTg4NTEsXG4gICAgLTEyNTkuMTM5MjE2NzIyNDAyOCxcbiAgICA3NzEuMzIzNDI4Nzc3NjUzMTMsXG4gICAgLTE3Ni42MTUwMjkxNjIxNDA1OSxcbiAgICAxMi41MDczNDMyNzg2ODY5MDUsXG4gICAgLTAuMTM4NTcxMDk1MjY1NzIwMTIsXG4gICAgOS45ODQzNjk1NzgwMTk1NzE2ZS02LFxuICAgIDEuNTA1NjMyNzM1MTQ5MzExNmUtN1xuXTtcblxudmFyIGdfbG4gPSA2MDcvMTI4O1xudmFyIHBfbG4gPSBbXG4gICAgMC45OTk5OTk5OTk5OTk5OTcwOTE4MixcbiAgICA1Ny4xNTYyMzU2NjU4NjI5MjM1MTcsXG4gICAgLTU5LjU5Nzk2MDM1NTQ3NTQ5MTI0OCxcbiAgICAxNC4xMzYwOTc5NzQ3NDE3NDcxNzQsXG4gICAgLTAuNDkxOTEzODE2MDk3NjIwMTk5NzgsXG4gICAgMC4zMzk5NDY0OTk4NDgxMTg4ODY5OWUtNCxcbiAgICAwLjQ2NTIzNjI4OTI3MDQ4NTc1NjY1ZS00LFxuICAgIC0wLjk4Mzc0NDc1MzA0ODc5NTY0Njc3ZS00LFxuICAgIDAuMTU4MDg4NzAzMjI0OTEyNDg4ODRlLTMsXG4gICAgLTAuMjEwMjY0NDQxNzI0MTA0ODgzMTllLTMsXG4gICAgMC4yMTc0Mzk2MTgxMTUyMTI2NDMyMGUtMyxcbiAgICAtMC4xNjQzMTgxMDY1MzY3NjM4OTAyMmUtMyxcbiAgICAwLjg0NDE4MjIzOTgzODUyNzQzMjkzZS00LFxuICAgIC0wLjI2MTkwODM4NDAxNTgxNDA4NjcwZS00LFxuICAgIDAuMzY4OTkxODI2NTk1MzE2MjI3MDRlLTVcbl07XG5cbi8vIFNwb3VnZSBhcHByb3hpbWF0aW9uIChzdWl0YWJsZSBmb3IgbGFyZ2UgYXJndW1lbnRzKVxuZnVuY3Rpb24gbG5nYW1tYSh6KSB7XG5cbiAgICBpZih6IDwgMCkgcmV0dXJuIE51bWJlcignMC8wJyk7XG4gICAgdmFyIHggPSBwX2xuWzBdO1xuICAgIGZvcih2YXIgaSA9IHBfbG4ubGVuZ3RoIC0gMTsgaSA+IDA7IC0taSkgeCArPSBwX2xuW2ldIC8gKHogKyBpKTtcbiAgICB2YXIgdCA9IHogKyBnX2xuICsgMC41O1xuICAgIHJldHVybiAuNSpNYXRoLmxvZygyKk1hdGguUEkpKyh6Ky41KSpNYXRoLmxvZyh0KS10K01hdGgubG9nKHgpLU1hdGgubG9nKHopO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdhbW1hICh6KSB7XG4gICAgaWYgKHogPCAwLjUpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguUEkgLyAoTWF0aC5zaW4oTWF0aC5QSSAqIHopICogZ2FtbWEoMSAtIHopKTtcbiAgICB9XG4gICAgZWxzZSBpZih6ID4gMTAwKSByZXR1cm4gTWF0aC5leHAobG5nYW1tYSh6KSk7XG4gICAgZWxzZSB7XG4gICAgICAgIHogLT0gMTtcbiAgICAgICAgdmFyIHggPSBwWzBdO1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGcgKyAyOyBpKyspIHtcbiAgICAgICAgICAgIHggKz0gcFtpXSAvICh6ICsgaSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHQgPSB6ICsgZyArIDAuNTtcblxuICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KDIgKiBNYXRoLlBJKVxuICAgICAgICAgICAgKiBNYXRoLnBvdyh0LCB6ICsgMC41KVxuICAgICAgICAgICAgKiBNYXRoLmV4cCgtdClcbiAgICAgICAgICAgICogeFxuICAgICAgICA7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMubG9nID0gbG5nYW1tYTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZ2V0Q2FudmFzQ29udGV4dFxuZnVuY3Rpb24gZ2V0Q2FudmFzQ29udGV4dCAodHlwZSwgb3B0cykge1xuICBpZiAodHlwZW9mIHR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVzdCBzcGVjaWZ5IHR5cGUgc3RyaW5nJylcbiAgfVxuXG4gIG9wdHMgPSBvcHRzIHx8IHt9XG5cbiAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgJiYgIW9wdHMuY2FudmFzKSB7XG4gICAgcmV0dXJuIG51bGwgLy8gY2hlY2sgZm9yIE5vZGVcbiAgfVxuXG4gIHZhciBjYW52YXMgPSBvcHRzLmNhbnZhcyB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICBpZiAodHlwZW9mIG9wdHMud2lkdGggPT09ICdudW1iZXInKSB7XG4gICAgY2FudmFzLndpZHRoID0gb3B0cy53aWR0aFxuICB9XG4gIGlmICh0eXBlb2Ygb3B0cy5oZWlnaHQgPT09ICdudW1iZXInKSB7XG4gICAgY2FudmFzLmhlaWdodCA9IG9wdHMuaGVpZ2h0XG4gIH1cblxuICB2YXIgYXR0cmlicyA9IG9wdHNcbiAgdmFyIGdsXG4gIHRyeSB7XG4gICAgdmFyIG5hbWVzID0gWyB0eXBlIF1cbiAgICAvLyBwcmVmaXggR0wgY29udGV4dHNcbiAgICBpZiAodHlwZS5pbmRleE9mKCd3ZWJnbCcpID09PSAwKSB7XG4gICAgICBuYW1lcy5wdXNoKCdleHBlcmltZW50YWwtJyArIHR5cGUpXG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dChuYW1lc1tpXSwgYXR0cmlicylcbiAgICAgIGlmIChnbCkgcmV0dXJuIGdsXG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgZ2wgPSBudWxsXG4gIH1cbiAgcmV0dXJuIChnbCB8fCBudWxsKSAvLyBlbnN1cmUgbnVsbCBvbiBmYWlsXG59XG4iLCIndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQXhlc1xyXG5cclxudmFyIGNyZWF0ZVRleHQgICAgICAgID0gcmVxdWlyZSgnLi9saWIvdGV4dC5qcycpXHJcbnZhciBjcmVhdGVMaW5lcyAgICAgICA9IHJlcXVpcmUoJy4vbGliL2xpbmVzLmpzJylcclxudmFyIGNyZWF0ZUJhY2tncm91bmQgID0gcmVxdWlyZSgnLi9saWIvYmFja2dyb3VuZC5qcycpXHJcbnZhciBnZXRDdWJlUHJvcGVydGllcyA9IHJlcXVpcmUoJy4vbGliL2N1YmUuanMnKVxyXG52YXIgVGlja3MgICAgICAgICAgICAgPSByZXF1aXJlKCcuL2xpYi90aWNrcy5qcycpXHJcblxyXG52YXIgaWRlbnRpdHkgPSBuZXcgRmxvYXQzMkFycmF5KFtcclxuICAxLCAwLCAwLCAwLFxyXG4gIDAsIDEsIDAsIDAsXHJcbiAgMCwgMCwgMSwgMCxcclxuICAwLCAwLCAwLCAxXSlcclxuXHJcbmZ1bmN0aW9uIGNvcHlWZWMzKGEsIGIpIHtcclxuICBhWzBdID0gYlswXVxyXG4gIGFbMV0gPSBiWzFdXHJcbiAgYVsyXSA9IGJbMl1cclxuICByZXR1cm4gYVxyXG59XHJcblxyXG5mdW5jdGlvbiBBeGVzKGdsKSB7XHJcbiAgdGhpcy5nbCAgICAgICAgICAgICA9IGdsXHJcblxyXG4gIHRoaXMucGl4ZWxSYXRpbyAgICAgPSAxXHJcblxyXG4gIHRoaXMuYm91bmRzICAgICAgICAgPSBbIFstMTAsIC0xMCwgLTEwXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBbIDEwLCAgMTAsICAxMF0gXVxyXG4gIHRoaXMudGlja3MgICAgICAgICAgPSBbIFtdLCBbXSwgW10gXVxyXG4gIHRoaXMuYXV0b1RpY2tzICAgICAgPSB0cnVlXHJcbiAgdGhpcy50aWNrU3BhY2luZyAgICA9IFsgMSwgMSwgMSBdXHJcblxyXG4gIHRoaXMudGlja0VuYWJsZSAgICAgPSBbIHRydWUsIHRydWUsIHRydWUgXVxyXG4gIHRoaXMudGlja0ZvbnQgICAgICAgPSBbICdzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnLCAnc2Fucy1zZXJpZicgXVxyXG4gIHRoaXMudGlja1NpemUgICAgICAgPSBbIDEyLCAxMiwgMTIgXVxyXG4gIHRoaXMudGlja0FuZ2xlICAgICAgPSBbIDAsIDAsIDAgXVxyXG4gIHRoaXMuX3RpY2tBbGlnbiAgICAgID0gWyAnYXV0bycsICdhdXRvJywgJ2F1dG8nIF1cclxuICB0aGlzLnRpY2tDb2xvciAgICAgID0gWyBbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdIF1cclxuICB0aGlzLnRpY2tQYWQgICAgICAgID0gWyAxMCwgMTAsIDEwIF1cclxuXHJcbiAgdGhpcy5sYXN0Q3ViZVByb3BzICA9IHtcclxuICAgIGN1YmVFZGdlczogWzAsMCwwXSxcclxuICAgIGF4aXM6ICAgICAgWzAsMCwwXVxyXG4gIH1cclxuXHJcbiAgdGhpcy5sYWJlbHMgICAgICAgICA9IFsgJ3gnLCAneScsICd6JyBdXHJcbiAgdGhpcy5sYWJlbEVuYWJsZSAgICA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdXHJcbiAgdGhpcy5sYWJlbEZvbnQgICAgICA9ICdzYW5zLXNlcmlmJ1xyXG4gIHRoaXMubGFiZWxTaXplICAgICAgPSBbIDIwLCAyMCwgMjAgXVxyXG4gIHRoaXMuX2xhYmVsQW5nbGUgICAgID0gWyAwLCAwLCAwIF1cclxuICB0aGlzLl9sYWJlbEFsaWduICAgICA9IFsgJ2F1dG8nLCAnYXV0bycsICdhdXRvJyBdXHJcbiAgdGhpcy5sYWJlbENvbG9yICAgICA9IFsgWzAsMCwwLDFdLCBbMCwwLDAsMV0sIFswLDAsMCwxXSBdXHJcbiAgdGhpcy5sYWJlbFBhZCAgICAgICA9IFsgMTAsIDEwLCAxMCBdXHJcblxyXG4gIHRoaXMubGluZUVuYWJsZSAgICAgPSBbIHRydWUsIHRydWUsIHRydWUgXVxyXG4gIHRoaXMubGluZU1pcnJvciAgICAgPSBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXVxyXG4gIHRoaXMubGluZVdpZHRoICAgICAgPSBbIDEsIDEsIDEgXVxyXG4gIHRoaXMubGluZUNvbG9yICAgICAgPSBbIFswLDAsMCwxXSwgWzAsMCwwLDFdLCBbMCwwLDAsMV0gXVxyXG5cclxuICB0aGlzLmxpbmVUaWNrRW5hYmxlID0gWyB0cnVlLCB0cnVlLCB0cnVlIF1cclxuICB0aGlzLmxpbmVUaWNrTWlycm9yID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF1cclxuICB0aGlzLmxpbmVUaWNrTGVuZ3RoID0gWyAwLCAwLCAwIF1cclxuICB0aGlzLmxpbmVUaWNrV2lkdGggID0gWyAxLCAxLCAxIF1cclxuICB0aGlzLmxpbmVUaWNrQ29sb3IgID0gWyBbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdIF1cclxuXHJcbiAgdGhpcy5ncmlkRW5hYmxlICAgICA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdXHJcbiAgdGhpcy5ncmlkV2lkdGggICAgICA9IFsgMSwgMSwgMSBdXHJcbiAgdGhpcy5ncmlkQ29sb3IgICAgICA9IFsgWzAsMCwwLDFdLCBbMCwwLDAsMV0sIFswLDAsMCwxXSBdXHJcblxyXG4gIHRoaXMuemVyb0VuYWJsZSAgICAgPSBbIHRydWUsIHRydWUsIHRydWUgXVxyXG4gIHRoaXMuemVyb0xpbmVDb2xvciAgPSBbIFswLDAsMCwxXSwgWzAsMCwwLDFdLCBbMCwwLDAsMV0gXVxyXG4gIHRoaXMuemVyb0xpbmVXaWR0aCAgPSBbIDIsIDIsIDIgXVxyXG5cclxuICB0aGlzLmJhY2tncm91bmRFbmFibGUgPSBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXVxyXG4gIHRoaXMuYmFja2dyb3VuZENvbG9yICA9IFsgWzAuOCwgMC44LCAwLjgsIDAuNV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMC44LCAwLjgsIDAuOCwgMC41XSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLjgsIDAuOCwgMC44LCAwLjVdIF1cclxuXHJcbiAgdGhpcy5fZmlyc3RJbml0ID0gdHJ1ZVxyXG4gIHRoaXMuX3RleHQgID0gbnVsbFxyXG4gIHRoaXMuX2xpbmVzID0gbnVsbFxyXG4gIHRoaXMuX2JhY2tncm91bmQgPSBjcmVhdGVCYWNrZ3JvdW5kKGdsKVxyXG59XHJcblxyXG52YXIgcHJvdG8gPSBBeGVzLnByb3RvdHlwZVxyXG5cclxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xyXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XHJcblxyXG4gIC8vT3B0aW9uIHBhcnNpbmcgaGVscGVyIGZ1bmN0aW9uc1xyXG4gIGZ1bmN0aW9uIHBhcnNlT3B0aW9uKG5lc3QsIGNvbnMsIG5hbWUpIHtcclxuICAgIGlmKG5hbWUgaW4gb3B0aW9ucykge1xyXG4gICAgICB2YXIgb3B0ID0gb3B0aW9uc1tuYW1lXVxyXG4gICAgICB2YXIgcHJldiA9IHRoaXNbbmFtZV1cclxuICAgICAgdmFyIG5leHRcclxuICAgICAgaWYobmVzdCA/IChBcnJheS5pc0FycmF5KG9wdCkgJiYgQXJyYXkuaXNBcnJheShvcHRbMF0pKSA6XHJcbiAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShvcHQpICkge1xyXG4gICAgICAgIHRoaXNbbmFtZV0gPSBuZXh0ID0gWyBjb25zKG9wdFswXSksIGNvbnMob3B0WzFdKSwgY29ucyhvcHRbMl0pIF1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzW25hbWVdID0gbmV4dCA9IFsgY29ucyhvcHQpLCBjb25zKG9wdCksIGNvbnMob3B0KSBdXHJcbiAgICAgIH1cclxuICAgICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICAgICAgaWYobmV4dFtpXSAhPT0gcHJldltpXSkge1xyXG4gICAgICAgICAgcmV0dXJuIHRydWVcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZVxyXG4gIH1cclxuXHJcbiAgdmFyIE5VTUJFUiAgPSBwYXJzZU9wdGlvbi5iaW5kKHRoaXMsIGZhbHNlLCBOdW1iZXIpXHJcbiAgdmFyIEJPT0xFQU4gPSBwYXJzZU9wdGlvbi5iaW5kKHRoaXMsIGZhbHNlLCBCb29sZWFuKVxyXG4gIHZhciBTVFJJTkcgID0gcGFyc2VPcHRpb24uYmluZCh0aGlzLCBmYWxzZSwgU3RyaW5nKVxyXG4gIHZhciBDT0xPUiAgID0gcGFyc2VPcHRpb24uYmluZCh0aGlzLCB0cnVlLCBmdW5jdGlvbih2KSB7XHJcbiAgICBpZihBcnJheS5pc0FycmF5KHYpKSB7XHJcbiAgICAgIGlmKHYubGVuZ3RoID09PSAzKSB7XHJcbiAgICAgICAgcmV0dXJuIFsgK3ZbMF0sICt2WzFdLCArdlsyXSwgMS4wIF1cclxuICAgICAgfSBlbHNlIGlmKHYubGVuZ3RoID09PSA0KSB7XHJcbiAgICAgICAgcmV0dXJuIFsgK3ZbMF0sICt2WzFdLCArdlsyXSwgK3ZbM10gXVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gWyAwLCAwLCAwLCAxIF1cclxuICB9KVxyXG5cclxuICAvL1RpY2sgbWFya3MgYW5kIGJvdW5kc1xyXG4gIHZhciBuZXh0VGlja3NcclxuICB2YXIgdGlja3NVcGRhdGUgICA9IGZhbHNlXHJcbiAgdmFyIGJvdW5kc0NoYW5nZWQgPSBmYWxzZVxyXG4gIGlmKCdib3VuZHMnIGluIG9wdGlvbnMpIHtcclxuICAgIHZhciBib3VuZHMgPSBvcHRpb25zLmJvdW5kc1xyXG5pX2xvb3A6XHJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgaWYoYm91bmRzW2ldW2pdICE9PSB0aGlzLmJvdW5kc1tpXVtqXSkge1xyXG4gICAgICAgICAgYm91bmRzQ2hhbmdlZCA9IHRydWVcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5ib3VuZHNbaV1bal0gPSBib3VuZHNbaV1bal1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICBpZigndGlja3MnIGluIG9wdGlvbnMpIHtcclxuICAgIG5leHRUaWNrcyAgICAgID0gb3B0aW9ucy50aWNrc1xyXG4gICAgdGlja3NVcGRhdGUgICAgPSB0cnVlXHJcbiAgICB0aGlzLmF1dG9UaWNrcyA9IGZhbHNlXHJcbiAgICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgICAgdGhpcy50aWNrU3BhY2luZ1tpXSA9IDAuMFxyXG4gICAgfVxyXG4gIH0gZWxzZSBpZihOVU1CRVIoJ3RpY2tTcGFjaW5nJykpIHtcclxuICAgIHRoaXMuYXV0b1RpY2tzICA9IHRydWVcclxuICAgIGJvdW5kc0NoYW5nZWQgICA9IHRydWVcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuX2ZpcnN0SW5pdCkge1xyXG4gICAgaWYoISgndGlja3MnIGluIG9wdGlvbnMgfHwgJ3RpY2tTcGFjaW5nJyBpbiBvcHRpb25zKSkge1xyXG4gICAgICB0aGlzLmF1dG9UaWNrcyA9IHRydWVcclxuICAgIH1cclxuXHJcbiAgICAvL0ZvcmNlIHRpY2sgcmVjb21wdXRhdGlvbiBvbiBmaXJzdCB1cGRhdGVcclxuICAgIGJvdW5kc0NoYW5nZWQgICA9IHRydWVcclxuICAgIHRpY2tzVXBkYXRlICAgICA9IHRydWVcclxuICAgIHRoaXMuX2ZpcnN0SW5pdCA9IGZhbHNlXHJcbiAgfVxyXG5cclxuICBpZihib3VuZHNDaGFuZ2VkICYmIHRoaXMuYXV0b1RpY2tzKSB7XHJcbiAgICBuZXh0VGlja3MgPSBUaWNrcy5jcmVhdGUodGhpcy5ib3VuZHMsIHRoaXMudGlja1NwYWNpbmcpXHJcbiAgICB0aWNrc1VwZGF0ZSA9IHRydWVcclxuICB9XHJcblxyXG4gIC8vQ29tcGFyZSBuZXh0IHRpY2tzIHRvIHByZXZpb3VzIHRpY2tzLCBvbmx5IHVwZGF0ZSBpZiBuZWVkZWRcclxuICBpZih0aWNrc1VwZGF0ZSkge1xyXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICAgIG5leHRUaWNrc1tpXS5zb3J0KGZ1bmN0aW9uKGEsYikge1xyXG4gICAgICAgIHJldHVybiBhLngtYi54XHJcbiAgICAgIH0pXHJcbiAgICB9XHJcbiAgICBpZihUaWNrcy5lcXVhbChuZXh0VGlja3MsIHRoaXMudGlja3MpKSB7XHJcbiAgICAgIHRpY2tzVXBkYXRlID0gZmFsc2VcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudGlja3MgPSBuZXh0VGlja3NcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vUGFyc2UgdGljayBwcm9wZXJ0aWVzXHJcbiAgQk9PTEVBTigndGlja0VuYWJsZScpXHJcbiAgaWYoU1RSSU5HKCd0aWNrRm9udCcpKSB7XHJcbiAgICB0aWNrc1VwZGF0ZSA9IHRydWUgIC8vSWYgZm9udCBjaGFuZ2VzLCBtdXN0IHJlYnVpbGQgdmJvXHJcbiAgfVxyXG4gIE5VTUJFUigndGlja1NpemUnKVxyXG4gIE5VTUJFUigndGlja0FuZ2xlJylcclxuICBOVU1CRVIoJ3RpY2tQYWQnKVxyXG4gIENPTE9SKCd0aWNrQ29sb3InKVxyXG5cclxuICAvL0F4aXMgbGFiZWxzXHJcbiAgdmFyIGxhYmVsVXBkYXRlID0gU1RSSU5HKCdsYWJlbHMnKVxyXG4gIGlmKFNUUklORygnbGFiZWxGb250JykpIHtcclxuICAgIGxhYmVsVXBkYXRlID0gdHJ1ZVxyXG4gIH1cclxuICBCT09MRUFOKCdsYWJlbEVuYWJsZScpXHJcbiAgTlVNQkVSKCdsYWJlbFNpemUnKVxyXG4gIE5VTUJFUignbGFiZWxQYWQnKVxyXG4gIENPTE9SKCdsYWJlbENvbG9yJylcclxuXHJcbiAgLy9BeGlzIGxpbmVzXHJcbiAgQk9PTEVBTignbGluZUVuYWJsZScpXHJcbiAgQk9PTEVBTignbGluZU1pcnJvcicpXHJcbiAgTlVNQkVSKCdsaW5lV2lkdGgnKVxyXG4gIENPTE9SKCdsaW5lQ29sb3InKVxyXG5cclxuICAvL0F4aXMgbGluZSB0aWNrc1xyXG4gIEJPT0xFQU4oJ2xpbmVUaWNrRW5hYmxlJylcclxuICBCT09MRUFOKCdsaW5lVGlja01pcnJvcicpXHJcbiAgTlVNQkVSKCdsaW5lVGlja0xlbmd0aCcpXHJcbiAgTlVNQkVSKCdsaW5lVGlja1dpZHRoJylcclxuICBDT0xPUignbGluZVRpY2tDb2xvcicpXHJcblxyXG4gIC8vR3JpZCBsaW5lc1xyXG4gIEJPT0xFQU4oJ2dyaWRFbmFibGUnKVxyXG4gIE5VTUJFUignZ3JpZFdpZHRoJylcclxuICBDT0xPUignZ3JpZENvbG9yJylcclxuXHJcbiAgLy9aZXJvIGxpbmVcclxuICBCT09MRUFOKCd6ZXJvRW5hYmxlJylcclxuICBDT0xPUignemVyb0xpbmVDb2xvcicpXHJcbiAgTlVNQkVSKCd6ZXJvTGluZVdpZHRoJylcclxuXHJcbiAgLy9CYWNrZ3JvdW5kXHJcbiAgQk9PTEVBTignYmFja2dyb3VuZEVuYWJsZScpXHJcbiAgQ09MT1IoJ2JhY2tncm91bmRDb2xvcicpXHJcblxyXG4gIC8vVXBkYXRlIHRleHQgaWYgbmVjZXNzYXJ5XHJcbiAgaWYoIXRoaXMuX3RleHQpIHtcclxuICAgIHRoaXMuX3RleHQgPSBjcmVhdGVUZXh0KFxyXG4gICAgICB0aGlzLmdsLFxyXG4gICAgICB0aGlzLmJvdW5kcyxcclxuICAgICAgdGhpcy5sYWJlbHMsXHJcbiAgICAgIHRoaXMubGFiZWxGb250LFxyXG4gICAgICB0aGlzLnRpY2tzLFxyXG4gICAgICB0aGlzLnRpY2tGb250KVxyXG4gIH0gZWxzZSBpZih0aGlzLl90ZXh0ICYmIChsYWJlbFVwZGF0ZSB8fCB0aWNrc1VwZGF0ZSkpIHtcclxuICAgIHRoaXMuX3RleHQudXBkYXRlKFxyXG4gICAgICB0aGlzLmJvdW5kcyxcclxuICAgICAgdGhpcy5sYWJlbHMsXHJcbiAgICAgIHRoaXMubGFiZWxGb250LFxyXG4gICAgICB0aGlzLnRpY2tzLFxyXG4gICAgICB0aGlzLnRpY2tGb250KVxyXG4gIH1cclxuXHJcbiAgLy9VcGRhdGUgbGluZXMgaWYgbmVjZXNzYXJ5XHJcbiAgaWYodGhpcy5fbGluZXMgJiYgdGlja3NVcGRhdGUpIHtcclxuICAgIHRoaXMuX2xpbmVzLmRpc3Bvc2UoKVxyXG4gICAgdGhpcy5fbGluZXMgPSBudWxsXHJcbiAgfVxyXG4gIGlmKCF0aGlzLl9saW5lcykge1xyXG4gICAgdGhpcy5fbGluZXMgPSBjcmVhdGVMaW5lcyh0aGlzLmdsLCB0aGlzLmJvdW5kcywgdGhpcy50aWNrcylcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIE9mZnNldEluZm8oKSB7XHJcbiAgdGhpcy5wcmltYWxPZmZzZXQgPSBbMCwwLDBdXHJcbiAgdGhpcy5wcmltYWxNaW5vciAgPSBbMCwwLDBdXHJcbiAgdGhpcy5taXJyb3JPZmZzZXQgPSBbMCwwLDBdXHJcbiAgdGhpcy5taXJyb3JNaW5vciAgPSBbMCwwLDBdXHJcbn1cclxuXHJcbnZhciBMSU5FX09GRlNFVCA9IFsgbmV3IE9mZnNldEluZm8oKSwgbmV3IE9mZnNldEluZm8oKSwgbmV3IE9mZnNldEluZm8oKSBdXHJcblxyXG5mdW5jdGlvbiBjb21wdXRlTGluZU9mZnNldChyZXN1bHQsIGksIGJvdW5kcywgY3ViZUVkZ2VzLCBjdWJlQXhpcykge1xyXG4gIHZhciBwcmltYWxPZmZzZXQgPSByZXN1bHQucHJpbWFsT2Zmc2V0XHJcbiAgdmFyIHByaW1hbE1pbm9yICA9IHJlc3VsdC5wcmltYWxNaW5vclxyXG4gIHZhciBkdWFsT2Zmc2V0ICAgPSByZXN1bHQubWlycm9yT2Zmc2V0XHJcbiAgdmFyIGR1YWxNaW5vciAgICA9IHJlc3VsdC5taXJyb3JNaW5vclxyXG4gIHZhciBlID0gY3ViZUVkZ2VzW2ldXHJcblxyXG4gIC8vQ2FsY3VsYXRlIG9mZnNldHNcclxuICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgIGlmKGkgPT09IGopIHtcclxuICAgICAgY29udGludWVcclxuICAgIH1cclxuICAgIHZhciBhID0gcHJpbWFsT2Zmc2V0LFxyXG4gICAgICAgIGIgPSBkdWFsT2Zmc2V0LFxyXG4gICAgICAgIGMgPSBwcmltYWxNaW5vcixcclxuICAgICAgICBkID0gZHVhbE1pbm9yXHJcbiAgICBpZihlICYgKDE8PGopKSB7XHJcbiAgICAgIGEgPSBkdWFsT2Zmc2V0XHJcbiAgICAgIGIgPSBwcmltYWxPZmZzZXRcclxuICAgICAgYyA9IGR1YWxNaW5vclxyXG4gICAgICBkID0gcHJpbWFsTWlub3JcclxuICAgIH1cclxuICAgIGFbal0gPSBib3VuZHNbMF1bal1cclxuICAgIGJbal0gPSBib3VuZHNbMV1bal1cclxuICAgIGlmKGN1YmVBeGlzW2pdID4gMCkge1xyXG4gICAgICBjW2pdID0gLTFcclxuICAgICAgZFtqXSA9IDBcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNbal0gPSAwXHJcbiAgICAgIGRbal0gPSArMVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxudmFyIENVQkVfRU5BQkxFID0gWzAsMCwwXVxyXG52YXIgREVGQVVMVF9QQVJBTVMgPSB7XHJcbiAgbW9kZWw6ICAgICAgaWRlbnRpdHksXHJcbiAgdmlldzogICAgICAgaWRlbnRpdHksXHJcbiAgcHJvamVjdGlvbjogaWRlbnRpdHlcclxufVxyXG5cclxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcclxuICByZXR1cm4gdHJ1ZVxyXG59XHJcblxyXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XHJcbiAgcmV0dXJuIGZhbHNlXHJcbn1cclxuXHJcbnByb3RvLmRyYXdUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKHBhcmFtcykge31cclxuXHJcbnZhciBBTElHTl9PUFRJT05fQVVUTyA9IDAgLy8gaS5lLiBhcyBkZWZpbmVkIGluIHRoZSBzaGFkZXIgdGhlIHRleHQgd291bGQgcm90YXRlIHRvIHN0YXkgdXB3YXJkcyByYW5nZTogWy05MCw5MF1cclxuXHJcbnZhciBQUklNQUxfTUlOT1IgID0gWzAsMCwwXVxyXG52YXIgTUlSUk9SX01JTk9SICA9IFswLDAsMF1cclxudmFyIFBSSU1BTF9PRkZTRVQgPSBbMCwwLDBdXHJcblxyXG5wcm90by5kcmF3ID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IERFRkFVTFRfUEFSQU1TXHJcblxyXG4gIHZhciBnbCA9IHRoaXMuZ2xcclxuXHJcbiAgLy9HZW9tZXRyeSBmb3IgY2FtZXJhIGFuZCBheGVzXHJcbiAgdmFyIG1vZGVsICAgICAgID0gcGFyYW1zLm1vZGVsIHx8IGlkZW50aXR5XHJcbiAgdmFyIHZpZXcgICAgICAgID0gcGFyYW1zLnZpZXcgfHwgaWRlbnRpdHlcclxuICB2YXIgcHJvamVjdGlvbiAgPSBwYXJhbXMucHJvamVjdGlvbiB8fCBpZGVudGl0eVxyXG4gIHZhciBib3VuZHMgICAgICA9IHRoaXMuYm91bmRzXHJcblxyXG4gIC8vVW5wYWNrIGF4aXMgaW5mb1xyXG4gIHZhciBjdWJlUGFyYW1zICA9IGdldEN1YmVQcm9wZXJ0aWVzKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBib3VuZHMpXHJcbiAgdmFyIGN1YmVFZGdlcyAgID0gY3ViZVBhcmFtcy5jdWJlRWRnZXNcclxuICB2YXIgY3ViZUF4aXMgICAgPSBjdWJlUGFyYW1zLmF4aXNcclxuXHJcbiAgdmFyIGN4ID0gdmlld1sxMl1cclxuICB2YXIgY3kgPSB2aWV3WzEzXVxyXG4gIHZhciBjeiA9IHZpZXdbMTRdXHJcbiAgdmFyIGN3ID0gdmlld1sxNV1cclxuXHJcbiAgdmFyIHBpeGVsU2NhbGVGID0gdGhpcy5waXhlbFJhdGlvICogKHByb2plY3Rpb25bM10qY3ggKyBwcm9qZWN0aW9uWzddKmN5ICsgcHJvamVjdGlvblsxMV0qY3ogKyBwcm9qZWN0aW9uWzE1XSpjdykgLyBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XHJcblxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgdGhpcy5sYXN0Q3ViZVByb3BzLmN1YmVFZGdlc1tpXSA9IGN1YmVFZGdlc1tpXVxyXG4gICAgdGhpcy5sYXN0Q3ViZVByb3BzLmF4aXNbaV0gPSBjdWJlQXhpc1tpXVxyXG4gIH1cclxuXHJcbiAgLy9Db21wdXRlIGF4aXMgaW5mb1xyXG4gIHZhciBsaW5lT2Zmc2V0ICA9IExJTkVfT0ZGU0VUXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBjb21wdXRlTGluZU9mZnNldChcclxuICAgICAgTElORV9PRkZTRVRbaV0sXHJcbiAgICAgIGksXHJcbiAgICAgIHRoaXMuYm91bmRzLFxyXG4gICAgICBjdWJlRWRnZXMsXHJcbiAgICAgIGN1YmVBeGlzKVxyXG4gIH1cclxuXHJcbiAgLy9TZXQgdXAgc3RhdGUgcGFyYW1ldGVyc1xyXG4gIHZhciBnbCA9IHRoaXMuZ2xcclxuXHJcbiAgLy9EcmF3IGJhY2tncm91bmQgZmlyc3RcclxuICB2YXIgY3ViZUVuYWJsZSA9IENVQkVfRU5BQkxFXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBpZih0aGlzLmJhY2tncm91bmRFbmFibGVbaV0pIHtcclxuICAgICAgY3ViZUVuYWJsZVtpXSA9IGN1YmVBeGlzW2ldXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjdWJlRW5hYmxlW2ldID0gMFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGhpcy5fYmFja2dyb3VuZC5kcmF3KFxyXG4gICAgbW9kZWwsXHJcbiAgICB2aWV3LFxyXG4gICAgcHJvamVjdGlvbixcclxuICAgIGJvdW5kcyxcclxuICAgIGN1YmVFbmFibGUsXHJcbiAgICB0aGlzLmJhY2tncm91bmRDb2xvcilcclxuXHJcbiAgLy9EcmF3IGxpbmVzXHJcbiAgdGhpcy5fbGluZXMuYmluZChcclxuICAgIG1vZGVsLFxyXG4gICAgdmlldyxcclxuICAgIHByb2plY3Rpb24sXHJcbiAgICB0aGlzKVxyXG5cclxuICAvL0ZpcnN0IGRyYXcgZ3JpZCBsaW5lcyBhbmQgemVybyBsaW5lc1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgdmFyIHggPSBbMCwwLDBdXHJcbiAgICBpZihjdWJlQXhpc1tpXSA+IDApIHtcclxuICAgICAgeFtpXSA9IGJvdW5kc1sxXVtpXVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgeFtpXSA9IGJvdW5kc1swXVtpXVxyXG4gICAgfVxyXG5cclxuICAgIC8vRHJhdyBncmlkIGxpbmVzXHJcbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcclxuICAgICAgdmFyIHUgPSAoaSArIDEgKyBqKSAlIDNcclxuICAgICAgdmFyIHYgPSAoaSArIDEgKyAoal4xKSkgJSAzXHJcbiAgICAgIGlmKHRoaXMuZ3JpZEVuYWJsZVt1XSkge1xyXG4gICAgICAgIHRoaXMuX2xpbmVzLmRyYXdHcmlkKHUsIHYsIHRoaXMuYm91bmRzLCB4LCB0aGlzLmdyaWRDb2xvclt1XSwgdGhpcy5ncmlkV2lkdGhbdV0qdGhpcy5waXhlbFJhdGlvKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9EcmF3IHplcm8gbGluZXMgKG5lZWQgdG8gZG8gdGhpcyBBRlRFUiBhbGwgZ3JpZCBsaW5lcyBhcmUgZHJhd24pXHJcbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcclxuICAgICAgdmFyIHUgPSAoaSArIDEgKyBqKSAlIDNcclxuICAgICAgdmFyIHYgPSAoaSArIDEgKyAoal4xKSkgJSAzXHJcbiAgICAgIGlmKHRoaXMuemVyb0VuYWJsZVt2XSkge1xyXG4gICAgICAgIC8vQ2hlY2sgaWYgemVybyBsaW5lIGluIGJvdW5kc1xyXG4gICAgICAgIGlmKE1hdGgubWluKGJvdW5kc1swXVt2XSwgYm91bmRzWzFdW3ZdKSA8PSAwICYmIE1hdGgubWF4KGJvdW5kc1swXVt2XSwgYm91bmRzWzFdW3ZdKSA+PSAwKSB7XHJcbiAgICAgICAgICB0aGlzLl9saW5lcy5kcmF3WmVybyh1LCB2LCB0aGlzLmJvdW5kcywgeCwgdGhpcy56ZXJvTGluZUNvbG9yW3ZdLCB0aGlzLnplcm9MaW5lV2lkdGhbdl0qdGhpcy5waXhlbFJhdGlvKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy9UaGVuIGRyYXcgYXhpcyBsaW5lcyBhbmQgdGljayBtYXJrc1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG5cclxuICAgIC8vRHJhdyBheGlzIGxpbmVzXHJcbiAgICBpZih0aGlzLmxpbmVFbmFibGVbaV0pIHtcclxuICAgICAgdGhpcy5fbGluZXMuZHJhd0F4aXNMaW5lKGksIHRoaXMuYm91bmRzLCBsaW5lT2Zmc2V0W2ldLnByaW1hbE9mZnNldCwgdGhpcy5saW5lQ29sb3JbaV0sIHRoaXMubGluZVdpZHRoW2ldKnRoaXMucGl4ZWxSYXRpbylcclxuICAgIH1cclxuICAgIGlmKHRoaXMubGluZU1pcnJvcltpXSkge1xyXG4gICAgICB0aGlzLl9saW5lcy5kcmF3QXhpc0xpbmUoaSwgdGhpcy5ib3VuZHMsIGxpbmVPZmZzZXRbaV0ubWlycm9yT2Zmc2V0LCB0aGlzLmxpbmVDb2xvcltpXSwgdGhpcy5saW5lV2lkdGhbaV0qdGhpcy5waXhlbFJhdGlvKVxyXG4gICAgfVxyXG5cclxuICAgIC8vQ29tcHV0ZSBtaW5vciBheGVzXHJcbiAgICB2YXIgcHJpbWFsTWlub3IgPSBjb3B5VmVjMyhQUklNQUxfTUlOT1IsIGxpbmVPZmZzZXRbaV0ucHJpbWFsTWlub3IpXHJcbiAgICB2YXIgbWlycm9yTWlub3IgPSBjb3B5VmVjMyhNSVJST1JfTUlOT1IsIGxpbmVPZmZzZXRbaV0ubWlycm9yTWlub3IpXHJcbiAgICB2YXIgdGlja0xlbmd0aCAgPSB0aGlzLmxpbmVUaWNrTGVuZ3RoXHJcbiAgICB2YXIgb3AgPSAwXHJcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgdmFyIHNjYWxlRmFjdG9yID0gcGl4ZWxTY2FsZUYgLyBtb2RlbFs1KmpdXHJcbiAgICAgIHByaW1hbE1pbm9yW2pdICo9IHRpY2tMZW5ndGhbal0gKiBzY2FsZUZhY3RvclxyXG4gICAgICBtaXJyb3JNaW5vcltqXSAqPSB0aWNrTGVuZ3RoW2pdICogc2NhbGVGYWN0b3JcclxuICAgIH1cclxuXHJcbiAgICAvL0RyYXcgYXhpcyBsaW5lIHRpY2tzXHJcbiAgICBpZih0aGlzLmxpbmVUaWNrRW5hYmxlW2ldKSB7XHJcbiAgICAgIHRoaXMuX2xpbmVzLmRyYXdBeGlzVGlja3MoaSwgbGluZU9mZnNldFtpXS5wcmltYWxPZmZzZXQsIHByaW1hbE1pbm9yLCB0aGlzLmxpbmVUaWNrQ29sb3JbaV0sIHRoaXMubGluZVRpY2tXaWR0aFtpXSp0aGlzLnBpeGVsUmF0aW8pXHJcbiAgICB9XHJcbiAgICBpZih0aGlzLmxpbmVUaWNrTWlycm9yW2ldKSB7XHJcbiAgICAgIHRoaXMuX2xpbmVzLmRyYXdBeGlzVGlja3MoaSwgbGluZU9mZnNldFtpXS5taXJyb3JPZmZzZXQsIG1pcnJvck1pbm9yLCB0aGlzLmxpbmVUaWNrQ29sb3JbaV0sIHRoaXMubGluZVRpY2tXaWR0aFtpXSp0aGlzLnBpeGVsUmF0aW8pXHJcbiAgICB9XHJcbiAgfVxyXG4gIHRoaXMuX2xpbmVzLnVuYmluZCgpXHJcblxyXG4gIC8vRHJhdyB0ZXh0IHNwcml0ZXNcclxuICB0aGlzLl90ZXh0LmJpbmQoXHJcbiAgICBtb2RlbCxcclxuICAgIHZpZXcsXHJcbiAgICBwcm9qZWN0aW9uLFxyXG4gICAgdGhpcy5waXhlbFJhdGlvKVxyXG5cclxuICB2YXIgYWxpZ25PcHQgLy8gb3B0aW9ucyBpbiBzaGFkZXIgYXJlIGZyb20gdGhpcyBsaXN0IHstMSwgMCwgMSwgMiwgMywgLi4uLCBufVxyXG4gIC8vIC0xOiBiYWNrd2FyZCBjb21wYXRpYmxlXHJcbiAgLy8gIDA6IHJhdyBkYXRhXHJcbiAgLy8gIDE6IGF1dG8gYWxpZ24sIGZyZWUgYW5nbGVzXHJcbiAgLy8gIDI6IGF1dG8gYWxpZ24sIGhvcml6b250YWwgb3IgdmVydGljYWxcclxuICAvLzMtbjogYXV0byBhbGlnbiwgcm91bmQgdG8gbiBkaXJlY3Rpb25zIGUuZy4gMTIgLT4gcm91bmQgdG8gYW5nbGVzIHdpdGggMzAtZGVncmVlIHN0ZXBzXHJcblxyXG4gIHZhciBodl9yYXRpbyA9IDAuNSAvLyBjYW4gaGF2ZSBhbiBlZmZlY3Qgb24gdGhlIHJhdGlvIGJldHdlZW4gaG9yaXpvbnRhbHMgYW5kIHZlcnRpY2FscyB3aGVuIHVzaW5nIG9wdGlvbiAyXHJcblxyXG4gIHZhciBlbmFibGVBbGlnblxyXG4gIHZhciBhbGlnbkRpclxyXG5cclxuICBmdW5jdGlvbiBhbGlnblRvKGkpIHtcclxuICAgIGFsaWduRGlyID0gWzAsMCwwXVxyXG4gICAgYWxpZ25EaXJbaV0gPSAxXHJcbiAgfVxyXG5cclxuICBmdW5jdGlvbiBzb2x2ZVRpY2tBbGlnbm1lbnRzKGksIG1pbm9yLCBtYWpvcikge1xyXG5cclxuICAgIHZhciBpMSA9IChpICsgMSkgJSAzXHJcbiAgICB2YXIgaTIgPSAoaSArIDIpICUgM1xyXG5cclxuICAgIHZhciBBID0gbWlub3JbaTFdXHJcbiAgICB2YXIgQiA9IG1pbm9yW2kyXVxyXG4gICAgdmFyIEMgPSBtYWpvcltpMV1cclxuICAgIHZhciBEID0gbWFqb3JbaTJdXHJcblxyXG4gICAgICAgICBpZiAoKEEgPiAwKSAmJiAoRCA+IDApKSB7IGFsaWduVG8oaTEpOyByZXR1cm47IH1cclxuICAgIGVsc2UgaWYgKChBID4gMCkgJiYgKEQgPCAwKSkgeyBhbGlnblRvKGkxKTsgcmV0dXJuOyB9XHJcbiAgICBlbHNlIGlmICgoQSA8IDApICYmIChEID4gMCkpIHsgYWxpZ25UbyhpMSk7IHJldHVybjsgfVxyXG4gICAgZWxzZSBpZiAoKEEgPCAwKSAmJiAoRCA8IDApKSB7IGFsaWduVG8oaTEpOyByZXR1cm47IH1cclxuICAgIGVsc2UgaWYgKChCID4gMCkgJiYgKEMgPiAwKSkgeyBhbGlnblRvKGkyKTsgcmV0dXJuOyB9XHJcbiAgICBlbHNlIGlmICgoQiA+IDApICYmIChDIDwgMCkpIHsgYWxpZ25UbyhpMik7IHJldHVybjsgfVxyXG4gICAgZWxzZSBpZiAoKEIgPCAwKSAmJiAoQyA+IDApKSB7IGFsaWduVG8oaTIpOyByZXR1cm47IH1cclxuICAgIGVsc2UgaWYgKChCIDwgMCkgJiYgKEMgPCAwKSkgeyBhbGlnblRvKGkyKTsgcmV0dXJuOyB9XHJcbiAgfVxyXG5cclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuXHJcbiAgICB2YXIgbWlub3IgICAgICA9IGxpbmVPZmZzZXRbaV0ucHJpbWFsTWlub3JcclxuICAgIHZhciBtYWpvciAgICAgID0gbGluZU9mZnNldFtpXS5taXJyb3JNaW5vclxyXG5cclxuICAgIHZhciBvZmZzZXQgICAgID0gY29weVZlYzMoUFJJTUFMX09GRlNFVCwgbGluZU9mZnNldFtpXS5wcmltYWxPZmZzZXQpXHJcblxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIGlmKHRoaXMubGluZVRpY2tFbmFibGVbaV0pIHtcclxuICAgICAgICBvZmZzZXRbal0gKz0gcGl4ZWxTY2FsZUYgKiBtaW5vcltqXSAqIE1hdGgubWF4KHRoaXMubGluZVRpY2tMZW5ndGhbal0sIDApICAvIG1vZGVsWzUqal1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHZhciBheGlzID0gWzAsMCwwXVxyXG4gICAgYXhpc1tpXSA9IDFcclxuXHJcbiAgICAvL0RyYXcgdGljayB0ZXh0XHJcbiAgICBpZih0aGlzLnRpY2tFbmFibGVbaV0pIHtcclxuXHJcbiAgICAgIGlmKHRoaXMudGlja0FuZ2xlW2ldID09PSAtMzYwMCkge1xyXG4gICAgICAgIHRoaXMudGlja0FuZ2xlW2ldID0gMFxyXG4gICAgICAgIHRoaXMuX3RpY2tBbGlnbltpXSA9ICdhdXRvJ1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuX3RpY2tBbGlnbltpXSA9IC0xXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGVuYWJsZUFsaWduID0gMTtcclxuXHJcbiAgICAgIGFsaWduT3B0ID0gW3RoaXMuX3RpY2tBbGlnbltpXSwgaHZfcmF0aW8sIGVuYWJsZUFsaWduXVxyXG4gICAgICBpZihhbGlnbk9wdFswXSA9PT0gJ2F1dG8nKSBhbGlnbk9wdFswXSA9IEFMSUdOX09QVElPTl9BVVRPXHJcbiAgICAgIGVsc2UgYWxpZ25PcHRbMF0gPSBwYXJzZUludCgnJyArIGFsaWduT3B0WzBdKVxyXG5cclxuICAgICAgYWxpZ25EaXIgPSBbMCwwLDBdXHJcbiAgICAgIHNvbHZlVGlja0FsaWdubWVudHMoaSwgbWlub3IsIG1ham9yKVxyXG5cclxuICAgICAgLy9BZGQgdGljayBwYWRkaW5nXHJcbiAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgIG9mZnNldFtqXSArPSBwaXhlbFNjYWxlRiAqIG1pbm9yW2pdICogdGhpcy50aWNrUGFkW2pdIC8gbW9kZWxbNSpqXVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL0RyYXcgYXhpc1xyXG4gICAgICB0aGlzLl90ZXh0LmRyYXdUaWNrcyhcclxuICAgICAgICBpLFxyXG4gICAgICAgIHRoaXMudGlja1NpemVbaV0sXHJcbiAgICAgICAgdGhpcy50aWNrQW5nbGVbaV0sXHJcbiAgICAgICAgb2Zmc2V0LFxyXG4gICAgICAgIHRoaXMudGlja0NvbG9yW2ldLFxyXG4gICAgICAgIGF4aXMsXHJcbiAgICAgICAgYWxpZ25EaXIsXHJcbiAgICAgICAgYWxpZ25PcHQpXHJcbiAgICB9XHJcblxyXG4gICAgLy9EcmF3IGxhYmVsc1xyXG4gICAgaWYodGhpcy5sYWJlbEVuYWJsZVtpXSkge1xyXG5cclxuICAgICAgZW5hYmxlQWxpZ24gPSAwXHJcbiAgICAgIGFsaWduRGlyID0gWzAsMCwwXVxyXG4gICAgICBpZih0aGlzLmxhYmVsc1tpXS5sZW5ndGggPiA0KSB7IC8vIGZvciBsYXJnZSBsYWJlbCBheGlzIGVuYWJsZSBhbGlnbkRpciB0byBheGlzXHJcbiAgICAgICAgYWxpZ25UbyhpKVxyXG4gICAgICAgIGVuYWJsZUFsaWduID0gMVxyXG4gICAgICB9XHJcblxyXG4gICAgICBhbGlnbk9wdCA9IFt0aGlzLl9sYWJlbEFsaWduW2ldLCBodl9yYXRpbywgZW5hYmxlQWxpZ25dXHJcbiAgICAgIGlmKGFsaWduT3B0WzBdID09PSAnYXV0bycpIGFsaWduT3B0WzBdID0gQUxJR05fT1BUSU9OX0FVVE9cclxuICAgICAgZWxzZSBhbGlnbk9wdFswXSA9IHBhcnNlSW50KCcnICsgYWxpZ25PcHRbMF0pXHJcblxyXG4gICAgICAvL0FkZCBsYWJlbCBwYWRkaW5nXHJcbiAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgIG9mZnNldFtqXSArPSBwaXhlbFNjYWxlRiAqIG1pbm9yW2pdICogdGhpcy5sYWJlbFBhZFtqXSAvIG1vZGVsWzUqal1cclxuICAgICAgfVxyXG4gICAgICBvZmZzZXRbaV0gKz0gMC41ICogKGJvdW5kc1swXVtpXSArIGJvdW5kc1sxXVtpXSlcclxuXHJcbiAgICAgIC8vRHJhdyBheGlzXHJcbiAgICAgIHRoaXMuX3RleHQuZHJhd0xhYmVsKFxyXG4gICAgICAgIGksXHJcbiAgICAgICAgdGhpcy5sYWJlbFNpemVbaV0sXHJcbiAgICAgICAgdGhpcy5fbGFiZWxBbmdsZVtpXSxcclxuICAgICAgICBvZmZzZXQsXHJcbiAgICAgICAgdGhpcy5sYWJlbENvbG9yW2ldLFxyXG4gICAgICAgIFswLDAsMF0sXHJcbiAgICAgICAgYWxpZ25EaXIsXHJcbiAgICAgICAgYWxpZ25PcHQpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0aGlzLl90ZXh0LnVuYmluZCgpXHJcbn1cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLl90ZXh0LmRpc3Bvc2UoKVxyXG4gIHRoaXMuX2xpbmVzLmRpc3Bvc2UoKVxyXG4gIHRoaXMuX2JhY2tncm91bmQuZGlzcG9zZSgpXHJcbiAgdGhpcy5fbGluZXMgPSBudWxsXHJcbiAgdGhpcy5fdGV4dCA9IG51bGxcclxuICB0aGlzLl9iYWNrZ3JvdW5kID0gbnVsbFxyXG4gIHRoaXMuZ2wgPSBudWxsXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUF4ZXMoZ2wsIG9wdGlvbnMpIHtcclxuICB2YXIgYXhlcyA9IG5ldyBBeGVzKGdsKVxyXG4gIGF4ZXMudXBkYXRlKG9wdGlvbnMpXHJcbiAgcmV0dXJuIGF4ZXNcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQmFja2dyb3VuZEN1YmVcclxuXHJcbnZhciBjcmVhdGVCdWZmZXIgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG52YXIgY3JlYXRlVkFPICAgID0gcmVxdWlyZSgnZ2wtdmFvJylcclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJy4vc2hhZGVycycpLmJnXHJcblxyXG5mdW5jdGlvbiBCYWNrZ3JvdW5kQ3ViZShnbCwgYnVmZmVyLCB2YW8sIHNoYWRlcikge1xyXG4gIHRoaXMuZ2wgPSBnbFxyXG4gIHRoaXMuYnVmZmVyID0gYnVmZmVyXHJcbiAgdGhpcy52YW8gPSB2YW9cclxuICB0aGlzLnNoYWRlciA9IHNoYWRlclxyXG59XHJcblxyXG52YXIgcHJvdG8gPSBCYWNrZ3JvdW5kQ3ViZS5wcm90b3R5cGVcclxuXHJcbnByb3RvLmRyYXcgPSBmdW5jdGlvbihtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgYm91bmRzLCBlbmFibGUsIGNvbG9ycykge1xyXG4gIHZhciBuZWVkc0JHID0gZmFsc2VcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIG5lZWRzQkcgPSBuZWVkc0JHIHx8IGVuYWJsZVtpXVxyXG4gIH1cclxuICBpZighbmVlZHNCRykge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcblxyXG4gIGdsLmVuYWJsZShnbC5QT0xZR09OX09GRlNFVF9GSUxMKVxyXG4gIGdsLnBvbHlnb25PZmZzZXQoMSwgMilcclxuXHJcbiAgdGhpcy5zaGFkZXIuYmluZCgpXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMgPSB7XHJcbiAgICBtb2RlbDogbW9kZWwsXHJcbiAgICB2aWV3OiB2aWV3LFxyXG4gICAgcHJvamVjdGlvbjogcHJvamVjdGlvbixcclxuICAgIGJvdW5kczogYm91bmRzLFxyXG4gICAgZW5hYmxlOiBlbmFibGUsXHJcbiAgICBjb2xvcnM6IGNvbG9yc1xyXG4gIH1cclxuICB0aGlzLnZhby5iaW5kKClcclxuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCAzNilcclxuICB0aGlzLnZhby51bmJpbmQoKVxyXG5cclxuICBnbC5kaXNhYmxlKGdsLlBPTFlHT05fT0ZGU0VUX0ZJTEwpXHJcbn1cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnZhby5kaXNwb3NlKClcclxuICB0aGlzLmJ1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlQmFja2dyb3VuZEN1YmUoZ2wpIHtcclxuICAvL0NyZWF0ZSBjdWJlIHZlcnRpY2VzXHJcbiAgdmFyIHZlcnRpY2VzID0gW11cclxuICB2YXIgaW5kaWNlcyAgPSBbXVxyXG4gIHZhciBwdHIgPSAwXHJcbiAgZm9yKHZhciBkPTA7IGQ8MzsgKytkKSB7XHJcbiAgICB2YXIgdSA9IChkKzEpICUgM1xyXG4gICAgdmFyIHYgPSAoZCsyKSAlIDNcclxuICAgIHZhciB4ID0gWzAsMCwwXVxyXG4gICAgdmFyIGMgPSBbMCwwLDBdXHJcbiAgICBmb3IodmFyIHM9LTE7IHM8PTE7IHMrPTIpIHtcclxuICAgICAgaW5kaWNlcy5wdXNoKHB0ciwgICBwdHIrMiwgcHRyKzEsXHJcbiAgICAgICAgICAgICAgICAgICBwdHIrMSwgcHRyKzIsIHB0ciszKVxyXG4gICAgICB4W2RdID0gc1xyXG4gICAgICBjW2RdID0gc1xyXG4gICAgICBmb3IodmFyIGk9LTE7IGk8PTE7IGkrPTIpIHtcclxuICAgICAgICB4W3VdID0gaVxyXG4gICAgICAgIGZvcih2YXIgaj0tMTsgajw9MTsgais9Mikge1xyXG4gICAgICAgICAgeFt2XSA9IGpcclxuICAgICAgICAgIHZlcnRpY2VzLnB1c2goeFswXSwgeFsxXSwgeFsyXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSlcclxuICAgICAgICAgIHB0ciArPSAxXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIC8vU3dhcCB1IGFuZCB2XHJcbiAgICAgIHZhciB0dCA9IHVcclxuICAgICAgdSA9IHZcclxuICAgICAgdiA9IHR0XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL0FsbG9jYXRlIGJ1ZmZlciBhbmQgdmVydGV4IGFycmF5XHJcbiAgdmFyIGJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbCwgbmV3IEZsb2F0MzJBcnJheSh2ZXJ0aWNlcykpXHJcbiAgdmFyIGVsZW1lbnRzID0gY3JlYXRlQnVmZmVyKGdsLCBuZXcgVWludDE2QXJyYXkoaW5kaWNlcyksIGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSKVxyXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgICAge1xyXG4gICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICAgIHNpemU6IDMsXHJcbiAgICAgICAgb2Zmc2V0OiAwLFxyXG4gICAgICAgIHN0cmlkZTogMjRcclxuICAgICAgfSxcclxuICAgICAge1xyXG4gICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICAgIHNpemU6IDMsXHJcbiAgICAgICAgb2Zmc2V0OiAxMixcclxuICAgICAgICBzdHJpZGU6IDI0XHJcbiAgICAgIH1cclxuICAgIF0sIGVsZW1lbnRzKVxyXG5cclxuICAvL0NyZWF0ZSBzaGFkZXIgb2JqZWN0XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5ub3JtYWwubG9jYXRpb24gPSAxXHJcblxyXG4gIHJldHVybiBuZXcgQmFja2dyb3VuZEN1YmUoZ2wsIGJ1ZmZlciwgdmFvLCBzaGFkZXIpXHJcbn1cclxuIiwiXCJ1c2Ugc3RyaWN0XCJcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZ2V0Q3ViZUVkZ2VzXHJcblxyXG52YXIgYml0cyAgICAgID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKVxyXG52YXIgbXVsdGlwbHkgID0gcmVxdWlyZSgnZ2wtbWF0NC9tdWx0aXBseScpXHJcbnZhciBpbnZlcnQgICAgPSByZXF1aXJlKCdnbC1tYXQ0L2ludmVydCcpXHJcbnZhciBzcGxpdFBvbHkgPSByZXF1aXJlKCdzcGxpdC1wb2x5Z29uJylcclxudmFyIG9yaWVudCAgICA9IHJlcXVpcmUoJ3JvYnVzdC1vcmllbnRhdGlvbicpXHJcblxyXG52YXIgbXZwICAgICAgICA9IG5ldyBBcnJheSgxNilcclxudmFyIGltdnAgICAgICAgPSBuZXcgQXJyYXkoMTYpXHJcbnZhciBwQ3ViZVZlcnRzID0gbmV3IEFycmF5KDgpXHJcbnZhciBjdWJlVmVydHMgID0gbmV3IEFycmF5KDgpXHJcbnZhciB4ICAgICAgICAgID0gbmV3IEFycmF5KDMpXHJcbnZhciB6ZXJvMyAgICAgID0gWzAsMCwwXVxyXG5cclxuOyhmdW5jdGlvbigpIHtcclxuICBmb3IodmFyIGk9MDsgaTw4OyArK2kpIHtcclxuICAgIHBDdWJlVmVydHNbaV0gPVsxLDEsMSwxXVxyXG4gICAgY3ViZVZlcnRzW2ldID0gWzEsMSwxXVxyXG4gIH1cclxufSkoKVxyXG5cclxuXHJcbmZ1bmN0aW9uIHRyYW5zZm9ybUhnKHJlc3VsdCwgeCwgbWF0KSB7XHJcbiAgZm9yKHZhciBpPTA7IGk8NDsgKytpKSB7XHJcbiAgICByZXN1bHRbaV0gPSBtYXRbMTIraV1cclxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICByZXN1bHRbaV0gKz0geFtqXSptYXRbNCpqK2ldXHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG52YXIgRlJVU1RVTV9QTEFORVMgPSBbXHJcbiAgWyAwLCAwLCAxLCAwLCAwXSxcclxuICBbIDAsIDAsLTEsIDEsIDBdLFxyXG4gIFsgMCwtMSwgMCwgMSwgMF0sXHJcbiAgWyAwLCAxLCAwLCAxLCAwXSxcclxuICBbLTEsIDAsIDAsIDEsIDBdLFxyXG4gIFsgMSwgMCwgMCwgMSwgMF1cclxuXVxyXG5cclxuZnVuY3Rpb24gcG9seWdvbkFyZWEocCkge1xyXG4gIGZvcih2YXIgaT0wOyBpPEZSVVNUVU1fUExBTkVTLmxlbmd0aDsgKytpKSB7XHJcbiAgICBwID0gc3BsaXRQb2x5LnBvc2l0aXZlKHAsIEZSVVNUVU1fUExBTkVTW2ldKVxyXG4gICAgaWYocC5sZW5ndGggPCAzKSB7XHJcbiAgICAgIHJldHVybiAwXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgYmFzZSA9IHBbMF1cclxuICB2YXIgYXggPSBiYXNlWzBdIC8gYmFzZVszXVxyXG4gIHZhciBheSA9IGJhc2VbMV0gLyBiYXNlWzNdXHJcbiAgdmFyIGFyZWEgPSAwLjBcclxuICBmb3IodmFyIGk9MTsgaSsxPHAubGVuZ3RoOyArK2kpIHtcclxuICAgIHZhciBiID0gcFtpXVxyXG4gICAgdmFyIGMgPSBwW2krMV1cclxuXHJcbiAgICB2YXIgYnggPSBiWzBdL2JbM11cclxuICAgIHZhciBieSA9IGJbMV0vYlszXVxyXG4gICAgdmFyIGN4ID0gY1swXS9jWzNdXHJcbiAgICB2YXIgY3kgPSBjWzFdL2NbM11cclxuXHJcbiAgICB2YXIgdXggPSBieCAtIGF4XHJcbiAgICB2YXIgdXkgPSBieSAtIGF5XHJcblxyXG4gICAgdmFyIHZ4ID0gY3ggLSBheFxyXG4gICAgdmFyIHZ5ID0gY3kgLSBheVxyXG5cclxuICAgIGFyZWEgKz0gTWF0aC5hYnModXggKiB2eSAtIHV5ICogdngpXHJcbiAgfVxyXG5cclxuICByZXR1cm4gYXJlYVxyXG59XHJcblxyXG52YXIgQ1VCRV9FREdFUyA9IFsxLDEsMV1cclxudmFyIENVQkVfQVhJUyAgPSBbMCwwLDBdXHJcbnZhciBDVUJFX1JFU1VMVCA9IHtcclxuICBjdWJlRWRnZXM6IENVQkVfRURHRVMsXHJcbiAgYXhpczogQ1VCRV9BWElTXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEN1YmVFZGdlcyhtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgYm91bmRzKSB7XHJcblxyXG4gIC8vQ29uY2F0ZW5hdGUgbWF0cmljZXNcclxuICBtdWx0aXBseShtdnAsIHZpZXcsIG1vZGVsKVxyXG4gIG11bHRpcGx5KG12cCwgcHJvamVjdGlvbiwgbXZwKVxyXG4gIFxyXG4gIC8vRmlyc3QgcHJvamVjdCBjdWJlIHZlcnRpY2VzXHJcbiAgdmFyIHB0ciA9IDBcclxuICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgIHhbMl0gPSBib3VuZHNbaV1bMl1cclxuICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xyXG4gICAgICB4WzFdID0gYm91bmRzW2pdWzFdXHJcbiAgICAgIGZvcih2YXIgaz0wOyBrPDI7ICsraykge1xyXG4gICAgICAgIHhbMF0gPSBib3VuZHNba11bMF1cclxuICAgICAgICB0cmFuc2Zvcm1IZyhwQ3ViZVZlcnRzW3B0cl0sIHgsIG12cClcclxuICAgICAgICBwdHIgKz0gMVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL0NsYXNzaWZ5IGNhbWVyYSBhZ2FpbnN0IGN1YmUgZmFjZXNcclxuICB2YXIgY2xvc2VzdCA9IC0xXHJcblxyXG4gIGZvcih2YXIgaT0wOyBpPDg7ICsraSkge1xyXG4gICAgdmFyIHcgPSBwQ3ViZVZlcnRzW2ldWzNdXHJcbiAgICBmb3IodmFyIGw9MDsgbDwzOyArK2wpIHtcclxuICAgICAgY3ViZVZlcnRzW2ldW2xdID0gcEN1YmVWZXJ0c1tpXVtsXSAvIHdcclxuICAgIH1cclxuICAgIGlmKHcgPCAwKSB7XHJcbiAgICAgIGlmKGNsb3Nlc3QgPCAwKSB7XHJcbiAgICAgICAgY2xvc2VzdCA9IGlcclxuICAgICAgfSBlbHNlIGlmKGN1YmVWZXJ0c1tpXVsyXSA8IGN1YmVWZXJ0c1tjbG9zZXN0XVsyXSkge1xyXG4gICAgICAgIGNsb3Nlc3QgPSBpXHJcbiAgICAgIH1cclxuICAgIH0gICAgXHJcbiAgfVxyXG5cclxuICBpZihjbG9zZXN0IDwgMCkge1xyXG4gICAgY2xvc2VzdCA9IDBcclxuICAgIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xyXG4gICAgICB2YXIgdSA9IChkKzIpICUgM1xyXG4gICAgICB2YXIgdiA9IChkKzEpICUgM1xyXG4gICAgICB2YXIgbzAgPSAtMVxyXG4gICAgICB2YXIgbzEgPSAtMVxyXG4gICAgICBmb3IodmFyIHM9MDsgczwyOyArK3MpIHtcclxuICAgICAgICB2YXIgZjAgPSAoczw8ZClcclxuICAgICAgICB2YXIgZjEgPSBmMCArIChzIDw8IHUpICsgKCgxLXMpIDw8IHYpXHJcbiAgICAgICAgdmFyIGYyID0gZjAgKyAoKDEtcykgPDwgdSkgKyAocyA8PCB2KVxyXG4gICAgICAgIGlmKG9yaWVudChjdWJlVmVydHNbZjBdLCBjdWJlVmVydHNbZjFdLCBjdWJlVmVydHNbZjJdLCB6ZXJvMykgPCAwKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZihzKSB7XHJcbiAgICAgICAgICBvMCA9IDFcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgbzEgPSAxXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGlmKG8wIDwgMCB8fCBvMSA8IDApIHtcclxuICAgICAgICBpZihvMSA+IG8wKSB7XHJcbiAgICAgICAgICBjbG9zZXN0IHw9IDE8PGRcclxuICAgICAgICB9XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfSBcclxuICAgICAgZm9yKHZhciBzPTA7IHM8MjsgKytzKSB7XHJcbiAgICAgICAgdmFyIGYwID0gKHM8PGQpXHJcbiAgICAgICAgdmFyIGYxID0gZjAgKyAocyA8PCB1KSArICgoMS1zKSA8PCB2KVxyXG4gICAgICAgIHZhciBmMiA9IGYwICsgKCgxLXMpIDw8IHUpICsgKHMgPDwgdikgICAgXHJcbiAgICAgICAgdmFyIG8gPSBwb2x5Z29uQXJlYShbXHJcbiAgICAgICAgICAgIHBDdWJlVmVydHNbZjBdLCBcclxuICAgICAgICAgICAgcEN1YmVWZXJ0c1tmMV0sIFxyXG4gICAgICAgICAgICBwQ3ViZVZlcnRzW2YyXSwgXHJcbiAgICAgICAgICAgIHBDdWJlVmVydHNbZjArKDE8PHUpKygxPDx2KV1dKVxyXG4gICAgICAgIGlmKHMpIHtcclxuICAgICAgICAgIG8wID0gb1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBvMSA9IG9cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYobzEgPiBvMCkge1xyXG4gICAgICAgIGNsb3Nlc3QgfD0gMTw8ZFxyXG4gICAgICAgIGNvbnRpbnVlXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHZhciBmYXJ0aGVzdCA9IDdeY2xvc2VzdFxyXG5cclxuICAvL0ZpbmQgbG93ZXN0IHZlcnRleCB3aGljaCBpcyBub3QgY2xvc2VzdCBjbG9zZXN0XHJcbiAgdmFyIGJvdHRvbSA9IC0xXHJcbiAgZm9yKHZhciBpPTA7IGk8ODsgKytpKSB7XHJcbiAgICBpZihpID09PSBjbG9zZXN0IHx8IGkgPT09IGZhcnRoZXN0KSB7XHJcbiAgICAgIGNvbnRpbnVlXHJcbiAgICB9XHJcbiAgICBpZihib3R0b20gPCAwKSB7XHJcbiAgICAgIGJvdHRvbSA9IGlcclxuICAgIH0gZWxzZSBpZihjdWJlVmVydHNbYm90dG9tXVsxXSA+IGN1YmVWZXJ0c1tpXVsxXSkge1xyXG4gICAgICBib3R0b20gPSBpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL0ZpbmQgbGVmdC9yaWdodCBuZWlnaGJvcnMgb2YgYm90dG9tIHZlcnRleFxyXG4gIHZhciBsZWZ0ID0gLTFcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHZhciBpZHggPSBib3R0b20gXiAoMTw8aSlcclxuICAgIGlmKGlkeCA9PT0gY2xvc2VzdCB8fCBpZHggPT09IGZhcnRoZXN0KSB7XHJcbiAgICAgIGNvbnRpbnVlXHJcbiAgICB9XHJcbiAgICBpZihsZWZ0IDwgMCkge1xyXG4gICAgICBsZWZ0ID0gaWR4XHJcbiAgICB9XHJcbiAgICB2YXIgdiA9IGN1YmVWZXJ0c1tpZHhdXHJcbiAgICBpZih2WzBdIDwgY3ViZVZlcnRzW2xlZnRdWzBdKSB7XHJcbiAgICAgIGxlZnQgPSBpZHhcclxuICAgIH1cclxuICB9XHJcbiAgdmFyIHJpZ2h0ID0gLTFcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHZhciBpZHggPSBib3R0b20gXiAoMTw8aSlcclxuICAgIGlmKGlkeCA9PT0gY2xvc2VzdCB8fCBpZHggPT09IGZhcnRoZXN0IHx8IGlkeCA9PT0gbGVmdCkge1xyXG4gICAgICBjb250aW51ZVxyXG4gICAgfVxyXG4gICAgaWYocmlnaHQgPCAwKSB7XHJcbiAgICAgIHJpZ2h0ID0gaWR4XHJcbiAgICB9XHJcbiAgICB2YXIgdiA9IGN1YmVWZXJ0c1tpZHhdXHJcbiAgICBpZih2WzBdID4gY3ViZVZlcnRzW3JpZ2h0XVswXSkge1xyXG4gICAgICByaWdodCA9IGlkeFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy9EZXRlcm1pbmUgZWRnZSBheGlzIGNvb3JkaW5hdGVzXHJcbiAgdmFyIGN1YmVFZGdlcyA9IENVQkVfRURHRVNcclxuICBjdWJlRWRnZXNbMF0gPSBjdWJlRWRnZXNbMV0gPSBjdWJlRWRnZXNbMl0gPSAwXHJcbiAgY3ViZUVkZ2VzW2JpdHMubG9nMihsZWZ0XmJvdHRvbSldID0gYm90dG9tJmxlZnRcclxuICBjdWJlRWRnZXNbYml0cy5sb2cyKGJvdHRvbV5yaWdodCldID0gYm90dG9tJnJpZ2h0XHJcbiAgdmFyIHRvcCA9IHJpZ2h0IF4gN1xyXG4gIGlmKHRvcCA9PT0gY2xvc2VzdCB8fCB0b3AgPT09IGZhcnRoZXN0KSB7XHJcbiAgICB0b3AgPSBsZWZ0IF4gN1xyXG4gICAgY3ViZUVkZ2VzW2JpdHMubG9nMihyaWdodF50b3ApXSA9IHRvcCZyaWdodFxyXG4gIH0gZWxzZSB7XHJcbiAgICBjdWJlRWRnZXNbYml0cy5sb2cyKGxlZnRedG9wKV0gPSB0b3AmbGVmdFxyXG4gIH1cclxuXHJcbiAgLy9EZXRlcm1pbmUgdmlzaWJsZSBmYWNlc1xyXG4gIHZhciBheGlzID0gQ1VCRV9BWElTXHJcbiAgdmFyIGN1dENvcm5lciA9IGNsb3Nlc3RcclxuICBmb3IodmFyIGQ9MDsgZDwzOyArK2QpIHtcclxuICAgIGlmKGN1dENvcm5lciAmICgxPDxkKSkge1xyXG4gICAgICBheGlzW2RdID0gLTFcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGF4aXNbZF0gPSAxXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL1JldHVybiByZXN1bHRcclxuICByZXR1cm4gQ1VCRV9SRVNVTFRcclxufSIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgICAgPSBjcmVhdGVMaW5lc1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciAgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG52YXIgY3JlYXRlVkFPICAgICA9IHJlcXVpcmUoJ2dsLXZhbycpXHJcbnZhciBjcmVhdGVTaGFkZXIgID0gcmVxdWlyZSgnLi9zaGFkZXJzJykubGluZVxyXG5cclxudmFyIE1BSk9SX0FYSVMgPSBbMCwwLDBdXHJcbnZhciBNSU5PUl9BWElTID0gWzAsMCwwXVxyXG52YXIgU0NSRUVOX0FYSVMgPSBbMCwwLDBdXHJcbnZhciBPRkZTRVRfVkVDID0gWzAsMCwwXVxyXG52YXIgU0hBUEUgPSBbMSwxXVxyXG5cclxuZnVuY3Rpb24gemVyb1ZlYyhhKSB7XHJcbiAgYVswXSA9IGFbMV0gPSBhWzJdID0gMFxyXG4gIHJldHVybiBhXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvcHlWZWMoYSxiKSB7XHJcbiAgYVswXSA9IGJbMF1cclxuICBhWzFdID0gYlsxXVxyXG4gIGFbMl0gPSBiWzJdXHJcbiAgcmV0dXJuIGFcclxufVxyXG5cclxuZnVuY3Rpb24gTGluZXMoZ2wsIHZlcnRCdWZmZXIsIHZhbywgc2hhZGVyLCB0aWNrQ291bnQsIHRpY2tPZmZzZXQsIGdyaWRDb3VudCwgZ3JpZE9mZnNldCkge1xyXG4gIHRoaXMuZ2wgICAgICAgICA9IGdsXHJcbiAgdGhpcy52ZXJ0QnVmZmVyID0gdmVydEJ1ZmZlclxyXG4gIHRoaXMudmFvICAgICAgICA9IHZhb1xyXG4gIHRoaXMuc2hhZGVyICAgICA9IHNoYWRlclxyXG4gIHRoaXMudGlja0NvdW50ICA9IHRpY2tDb3VudFxyXG4gIHRoaXMudGlja09mZnNldCA9IHRpY2tPZmZzZXRcclxuICB0aGlzLmdyaWRDb3VudCAgPSBncmlkQ291bnRcclxuICB0aGlzLmdyaWRPZmZzZXQgPSBncmlkT2Zmc2V0XHJcbn1cclxuXHJcbnZhciBwcm90byA9IExpbmVzLnByb3RvdHlwZVxyXG5cclxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uKSB7XHJcbiAgdGhpcy5zaGFkZXIuYmluZCgpXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubW9kZWwgPSBtb2RlbFxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnZpZXcgPSB2aWV3XHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMucHJvamVjdGlvbiA9IHByb2plY3Rpb25cclxuXHJcbiAgU0hBUEVbMF0gPSB0aGlzLmdsLmRyYXdpbmdCdWZmZXJXaWR0aFxyXG4gIFNIQVBFWzFdID0gdGhpcy5nbC5kcmF3aW5nQnVmZmVySGVpZ2h0XHJcblxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjcmVlblNoYXBlID0gU0hBUEVcclxuICB0aGlzLnZhby5iaW5kKClcclxufVxyXG5cclxucHJvdG8udW5iaW5kID0gZnVuY3Rpb24oKSB7XHJcbiAgdGhpcy52YW8udW5iaW5kKClcclxufVxyXG5cclxucHJvdG8uZHJhd0F4aXNMaW5lID0gZnVuY3Rpb24oaiwgYm91bmRzLCBvZmZzZXQsIGNvbG9yLCBsaW5lV2lkdGgpIHtcclxuICB2YXIgbWlub3JBeGlzID0gemVyb1ZlYyhNSU5PUl9BWElTKVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IE1JTk9SX0FYSVNcclxuXHJcbiAgbWlub3JBeGlzW2pdID0gYm91bmRzWzFdW2pdIC0gYm91bmRzWzBdW2pdXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubWlub3JBeGlzID0gbWlub3JBeGlzXHJcblxyXG4gIHZhciBub2Zmc2V0ID0gY29weVZlYyhPRkZTRVRfVkVDLCBvZmZzZXQpXHJcbiAgbm9mZnNldFtqXSArPSBib3VuZHNbMF1bal1cclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5vZmZzZXQgPSBub2Zmc2V0XHJcblxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmxpbmVXaWR0aCA9IGxpbmVXaWR0aFxyXG5cclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5jb2xvciA9IGNvbG9yXHJcblxyXG4gIHZhciBzY3JlZW5BeGlzID0gemVyb1ZlYyhTQ1JFRU5fQVhJUylcclxuICBzY3JlZW5BeGlzWyhqKzIpJTNdID0gMVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkF4aXMgPSBzY3JlZW5BeGlzXHJcbiAgdGhpcy52YW8uZHJhdyh0aGlzLmdsLlRSSUFOR0xFUywgNilcclxuXHJcbiAgdmFyIHNjcmVlbkF4aXMgPSB6ZXJvVmVjKFNDUkVFTl9BWElTKVxyXG4gIHNjcmVlbkF4aXNbKGorMSklM10gPSAxXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NyZWVuQXhpcyA9IHNjcmVlbkF4aXNcclxuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCA2KVxyXG59XHJcblxyXG5wcm90by5kcmF3QXhpc1RpY2tzID0gZnVuY3Rpb24oaiwgb2Zmc2V0LCBtaW5vckF4aXMsIGNvbG9yLCBsaW5lV2lkdGgpIHtcclxuICBpZighdGhpcy50aWNrQ291bnRbal0pIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgdmFyIG1ham9yQXhpcyA9IHplcm9WZWMoTUFKT1JfQVhJUylcclxuICBtYWpvckF4aXNbal0gID0gMVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IG1ham9yQXhpc1xyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm9mZnNldCAgICA9IG9mZnNldFxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1pbm9yQXhpcyA9IG1pbm9yQXhpc1xyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmNvbG9yICAgICA9IGNvbG9yXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubGluZVdpZHRoID0gbGluZVdpZHRoXHJcblxyXG4gIHZhciBzY3JlZW5BeGlzID0gemVyb1ZlYyhTQ1JFRU5fQVhJUylcclxuICBzY3JlZW5BeGlzW2pdID0gMVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkF4aXMgPSBzY3JlZW5BeGlzXHJcbiAgdGhpcy52YW8uZHJhdyh0aGlzLmdsLlRSSUFOR0xFUywgdGhpcy50aWNrQ291bnRbal0sIHRoaXMudGlja09mZnNldFtqXSlcclxufVxyXG5cclxuXHJcbnByb3RvLmRyYXdHcmlkID0gZnVuY3Rpb24oaSwgaiwgYm91bmRzLCBvZmZzZXQsIGNvbG9yLCBsaW5lV2lkdGgpIHtcclxuICBpZighdGhpcy5ncmlkQ291bnRbaV0pIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgdmFyIG1pbm9yQXhpcyA9IHplcm9WZWMoTUlOT1JfQVhJUylcclxuICBtaW5vckF4aXNbal0gID0gYm91bmRzWzFdW2pdIC0gYm91bmRzWzBdW2pdXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubWlub3JBeGlzID0gbWlub3JBeGlzXHJcblxyXG4gIHZhciBub2Zmc2V0ID0gY29weVZlYyhPRkZTRVRfVkVDLCBvZmZzZXQpXHJcbiAgbm9mZnNldFtqXSArPSBib3VuZHNbMF1bal1cclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5vZmZzZXQgPSBub2Zmc2V0XHJcblxyXG4gIHZhciBtYWpvckF4aXMgPSB6ZXJvVmVjKE1BSk9SX0FYSVMpXHJcbiAgbWFqb3JBeGlzW2ldICA9IDFcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5tYWpvckF4aXMgPSBtYWpvckF4aXNcclxuXHJcbiAgdmFyIHNjcmVlbkF4aXMgPSB6ZXJvVmVjKFNDUkVFTl9BWElTKVxyXG4gIHNjcmVlbkF4aXNbaV0gPSAxXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NyZWVuQXhpcyA9IHNjcmVlbkF4aXNcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSBsaW5lV2lkdGhcclxuXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuY29sb3IgPSBjb2xvclxyXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIHRoaXMuZ3JpZENvdW50W2ldLCB0aGlzLmdyaWRPZmZzZXRbaV0pXHJcbn1cclxuXHJcbnByb3RvLmRyYXdaZXJvID0gZnVuY3Rpb24oaiwgaSwgYm91bmRzLCBvZmZzZXQsIGNvbG9yLCBsaW5lV2lkdGgpIHtcclxuICB2YXIgbWlub3JBeGlzID0gemVyb1ZlYyhNSU5PUl9BWElTKVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IG1pbm9yQXhpc1xyXG5cclxuICBtaW5vckF4aXNbal0gPSBib3VuZHNbMV1bal0gLSBib3VuZHNbMF1bal1cclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5taW5vckF4aXMgPSBtaW5vckF4aXNcclxuXHJcbiAgdmFyIG5vZmZzZXQgPSBjb3B5VmVjKE9GRlNFVF9WRUMsIG9mZnNldClcclxuICBub2Zmc2V0W2pdICs9IGJvdW5kc1swXVtqXVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm9mZnNldCA9IG5vZmZzZXRcclxuXHJcbiAgdmFyIHNjcmVlbkF4aXMgPSB6ZXJvVmVjKFNDUkVFTl9BWElTKVxyXG4gIHNjcmVlbkF4aXNbaV0gPSAxXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NyZWVuQXhpcyA9IHNjcmVlbkF4aXNcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSBsaW5lV2lkdGhcclxuXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuY29sb3IgPSBjb2xvclxyXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIDYpXHJcbn1cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnZhby5kaXNwb3NlKClcclxuICB0aGlzLnZlcnRCdWZmZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5zaGFkZXIuZGlzcG9zZSgpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUxpbmVzKGdsLCBib3VuZHMsIHRpY2tzKSB7XHJcbiAgdmFyIHZlcnRpY2VzICAgID0gW11cclxuICB2YXIgdGlja09mZnNldCAgPSBbMCwwLDBdXHJcbiAgdmFyIHRpY2tDb3VudCAgID0gWzAsMCwwXVxyXG5cclxuICAvL0NyZWF0ZSBncmlkIGxpbmVzIGZvciBlYWNoIGF4aXMvZGlyZWN0aW9uXHJcbiAgdmFyIGdyaWRPZmZzZXQgPSBbMCwwLDBdXHJcbiAgdmFyIGdyaWRDb3VudCAgPSBbMCwwLDBdXHJcblxyXG4gIC8vQWRkIHplcm8gbGluZVxyXG4gIHZlcnRpY2VzLnB1c2goXHJcbiAgICAwLDAsMSwgICAwLDEsMSwgICAwLDAsLTEsXHJcbiAgICAwLDAsLTEsICAwLDEsMSwgICAwLDEsLTEpXHJcblxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgLy9BeGlzIHRpY2sgbWFya3NcclxuICAgIHZhciBzdGFydCA9ICgodmVydGljZXMubGVuZ3RoIC8gMyl8MClcclxuICAgIGZvcih2YXIgaj0wOyBqPHRpY2tzW2ldLmxlbmd0aDsgKytqKSB7XHJcbiAgICAgIHZhciB4ID0gK3RpY2tzW2ldW2pdLnhcclxuICAgICAgdmVydGljZXMucHVzaChcclxuICAgICAgICB4LDAsMSwgICB4LDEsMSwgICB4LDAsLTEsXHJcbiAgICAgICAgeCwwLC0xLCAgeCwxLDEsICAgeCwxLC0xKVxyXG4gICAgfVxyXG4gICAgdmFyIGVuZCA9ICgodmVydGljZXMubGVuZ3RoIC8gMyl8MClcclxuICAgIHRpY2tPZmZzZXRbaV0gPSBzdGFydFxyXG4gICAgdGlja0NvdW50W2ldICA9IGVuZCAtIHN0YXJ0XHJcblxyXG4gICAgLy9HcmlkIGxpbmVzXHJcbiAgICB2YXIgc3RhcnQgPSAoKHZlcnRpY2VzLmxlbmd0aCAvIDMpfDApXHJcbiAgICBmb3IodmFyIGs9MDsgazx0aWNrc1tpXS5sZW5ndGg7ICsraykge1xyXG4gICAgICB2YXIgeCA9ICt0aWNrc1tpXVtrXS54XHJcbiAgICAgIHZlcnRpY2VzLnB1c2goXHJcbiAgICAgICAgeCwwLDEsICAgeCwxLDEsICAgeCwwLC0xLFxyXG4gICAgICAgIHgsMCwtMSwgIHgsMSwxLCAgIHgsMSwtMSlcclxuICAgIH1cclxuICAgIHZhciBlbmQgPSAoKHZlcnRpY2VzLmxlbmd0aCAvIDMpfDApXHJcbiAgICBncmlkT2Zmc2V0W2ldID0gc3RhcnRcclxuICAgIGdyaWRDb3VudFtpXSAgPSBlbmQgLSBzdGFydFxyXG4gIH1cclxuXHJcbiAgLy9DcmVhdGUgY3ViZSBWQU9cclxuICB2YXIgdmVydEJ1ZiA9IGNyZWF0ZUJ1ZmZlcihnbCwgbmV3IEZsb2F0MzJBcnJheSh2ZXJ0aWNlcykpXHJcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAgeyBcImJ1ZmZlclwiOiB2ZXJ0QnVmLFxyXG4gICAgICBcInR5cGVcIjogZ2wuRkxPQVQsXHJcbiAgICAgIFwic2l6ZVwiOiAzLFxyXG4gICAgICBcInN0cmlkZVwiOiAwLFxyXG4gICAgICBcIm9mZnNldFwiOiAwXHJcbiAgICB9XHJcbiAgXSlcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHJldHVybiBuZXcgTGluZXMoZ2wsIHZlcnRCdWYsIHZhbywgc2hhZGVyLCB0aWNrQ291bnQsIHRpY2tPZmZzZXQsIGdyaWRDb3VudCwgZ3JpZE9mZnNldClcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBnbHNsaWZ5ID0gcmVxdWlyZSgnZ2xzbGlmeScpXHJcbnZhciBjcmVhdGVTaGFkZXIgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG5cclxudmFyIGxpbmVWZXJ0ID0gZ2xzbGlmeShbXCIjZGVmaW5lIEdMU0xJRlkgMVxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG51bmlmb3JtIHZlYzMgb2Zmc2V0LCBtYWpvckF4aXMsIG1pbm9yQXhpcywgc2NyZWVuQXhpcztcXG51bmlmb3JtIGZsb2F0IGxpbmVXaWR0aDtcXG51bmlmb3JtIHZlYzIgc2NyZWVuU2hhcGU7XFxuXFxudmVjMyBwcm9qZWN0KHZlYzMgcCkge1xcbiAgdmVjNCBwcCA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHAsIDEuMCk7XFxuICByZXR1cm4gcHAueHl6IC8gbWF4KHBwLncsIDAuMDAwMSk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgbWFqb3IgPSBwb3NpdGlvbi54ICogbWFqb3JBeGlzO1xcbiAgdmVjMyBtaW5vciA9IHBvc2l0aW9uLnkgKiBtaW5vckF4aXM7XFxuXFxuICB2ZWMzIHZQb3NpdGlvbiA9IG1ham9yICsgbWlub3IgKyBvZmZzZXQ7XFxuICB2ZWMzIHBQb3NpdGlvbiA9IHByb2plY3QodlBvc2l0aW9uKTtcXG4gIHZlYzMgb2Zmc2V0ID0gcHJvamVjdCh2UG9zaXRpb24gKyBzY3JlZW5BeGlzICogcG9zaXRpb24ueik7XFxuXFxuICB2ZWMyIHNjcmVlbiA9IG5vcm1hbGl6ZSgob2Zmc2V0IC0gcFBvc2l0aW9uKS54eSAqIHNjcmVlblNoYXBlKSAvIHNjcmVlblNoYXBlO1xcblxcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBQb3NpdGlvbiArIHZlYzMoMC41ICogc2NyZWVuICogbGluZVdpZHRoLCAwKSwgMS4wKTtcXG59XFxuXCJdKVxyXG52YXIgbGluZUZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxudW5pZm9ybSB2ZWM0IGNvbG9yO1xcbnZvaWQgbWFpbigpIHtcXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbn1cIl0pXHJcbmV4cG9ydHMubGluZSA9IGZ1bmN0aW9uKGdsKSB7XHJcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgbGluZVZlcnQsIGxpbmVGcmFnLCBudWxsLCBbXHJcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzMnfVxyXG4gIF0pXHJcbn1cclxuXHJcbnZhciB0ZXh0VmVydCA9IGdsc2xpZnkoW1wiI2RlZmluZSBHTFNMSUZZIDFcXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIG9mZnNldCwgYXhpcywgYWxpZ25EaXIsIGFsaWduT3B0O1xcbnVuaWZvcm0gZmxvYXQgc2NhbGUsIGFuZ2xlLCBwaXhlbFNjYWxlO1xcbnVuaWZvcm0gdmVjMiByZXNvbHV0aW9uO1xcblxcbnZlYzMgcHJvamVjdCh2ZWMzIHApIHtcXG4gIHZlYzQgcHAgPSBwcm9qZWN0aW9uICogdmlldyAqIG1vZGVsICogdmVjNChwLCAxLjApO1xcbiAgcmV0dXJuIHBwLnh5eiAvIG1heChwcC53LCAwLjAwMDEpO1xcbn1cXG5cXG5mbG9hdCBjb21wdXRlVmlld0FuZ2xlKHZlYzMgYSwgdmVjMyBiKSB7XFxuICB2ZWMzIEEgPSBwcm9qZWN0KGEpO1xcbiAgdmVjMyBCID0gcHJvamVjdChiKTtcXG5cXG4gIHJldHVybiBhdGFuKFxcbiAgICAoQi55IC0gQS55KSAqIHJlc29sdXRpb24ueSxcXG4gICAgKEIueCAtIEEueCkgKiByZXNvbHV0aW9uLnhcXG4gICk7XFxufVxcblxcbmNvbnN0IGZsb2F0IFBJID0gMy4xNDE1OTI7XFxuY29uc3QgZmxvYXQgVFdPX1BJID0gMi4wICogUEk7XFxuY29uc3QgZmxvYXQgSEFMRl9QSSA9IDAuNSAqIFBJO1xcbmNvbnN0IGZsb2F0IE9ORV9BTkRfSEFMRl9QSSA9IDEuNSAqIFBJO1xcblxcbmludCBvcHRpb24gPSBpbnQoZmxvb3IoYWxpZ25PcHQueCArIDAuMDAxKSk7XFxuZmxvYXQgaHZfcmF0aW8gPSAgICAgICBhbGlnbk9wdC55O1xcbmJvb2wgZW5hYmxlQWxpZ24gPSAgICAoYWxpZ25PcHQueiAhPSAwLjApO1xcblxcbmZsb2F0IG1vZF9hbmdsZShmbG9hdCBhKSB7XFxuICByZXR1cm4gbW9kKGEsIFBJKTtcXG59XFxuXFxuZmxvYXQgcG9zaXRpdmVfYW5nbGUoZmxvYXQgYSkge1xcbiAgcmV0dXJuIG1vZF9hbmdsZSgoYSA8IDAuMCkgP1xcbiAgICBhICsgVFdPX1BJIDpcXG4gICAgYVxcbiAgKTtcXG59XFxuXFxuZmxvYXQgbG9va191cHdhcmRzKGZsb2F0IGEpIHtcXG4gIGZsb2F0IGIgPSBwb3NpdGl2ZV9hbmdsZShhKTtcXG4gIHJldHVybiAoKGIgPiBIQUxGX1BJKSAmJiAoYiA8PSBPTkVfQU5EX0hBTEZfUEkpKSA/XFxuICAgIGIgLSBQSSA6XFxuICAgIGI7XFxufVxcblxcbmZsb2F0IGxvb2tfaG9yaXpvbnRhbF9vcl92ZXJ0aWNhbChmbG9hdCBhLCBmbG9hdCByYXRpbykge1xcbiAgLy8gcmF0aW8gY29udHJvbHMgdGhlIHJhdGlvIGJldHdlZW4gYmVpbmcgaG9yaXpvbnRhbCB0byAodmVydGljYWwgKyBob3Jpem9udGFsKVxcbiAgLy8gaWYgcmF0aW8gaXMgc2V0IHRvIDAuNSB0aGVuIGl0IGlzIDUwJSwgNTAlLlxcbiAgLy8gd2hlbiB1c2luZyBhIGhpZ2hlciByYXRpbyBlLmcuIDAuNzUgdGhlIHJlc3VsdCB3b3VsZFxcbiAgLy8gbGlrZWx5IGJlIG1vcmUgaG9yaXpvbnRhbCB0aGFuIHZlcnRpY2FsLlxcblxcbiAgZmxvYXQgYiA9IHBvc2l0aXZlX2FuZ2xlKGEpO1xcblxcbiAgcmV0dXJuXFxuICAgIChiIDwgKCAgICAgIHJhdGlvKSAqIEhBTEZfUEkpID8gMC4wIDpcXG4gICAgKGIgPCAoMi4wIC0gcmF0aW8pICogSEFMRl9QSSkgPyAtSEFMRl9QSSA6XFxuICAgIChiIDwgKDIuMCArIHJhdGlvKSAqIEhBTEZfUEkpID8gMC4wIDpcXG4gICAgKGIgPCAoNC4wIC0gcmF0aW8pICogSEFMRl9QSSkgPyBIQUxGX1BJIDpcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjA7XFxufVxcblxcbmZsb2F0IHJvdW5kVG8oZmxvYXQgYSwgZmxvYXQgYikge1xcbiAgcmV0dXJuIGZsb2F0KGIgKiBmbG9vcigoYSArIDAuNSAqIGIpIC8gYikpO1xcbn1cXG5cXG5mbG9hdCBsb29rX3JvdW5kX25fZGlyZWN0aW9ucyhmbG9hdCBhLCBpbnQgbikge1xcbiAgZmxvYXQgYiA9IHBvc2l0aXZlX2FuZ2xlKGEpO1xcbiAgZmxvYXQgZGl2ID0gVFdPX1BJIC8gZmxvYXQobik7XFxuICBmbG9hdCBjID0gcm91bmRUbyhiLCBkaXYpO1xcbiAgcmV0dXJuIGxvb2tfdXB3YXJkcyhjKTtcXG59XFxuXFxuZmxvYXQgYXBwbHlBbGlnbk9wdGlvbihmbG9hdCByYXdBbmdsZSwgZmxvYXQgZGVsdGEpIHtcXG4gIHJldHVyblxcbiAgICAob3B0aW9uID4gIDIpID8gbG9va19yb3VuZF9uX2RpcmVjdGlvbnMocmF3QW5nbGUgKyBkZWx0YSwgb3B0aW9uKSA6ICAgICAgIC8vIG9wdGlvbiAzLW46IHJvdW5kIHRvIG4gZGlyZWN0aW9uc1xcbiAgICAob3B0aW9uID09IDIpID8gbG9va19ob3Jpem9udGFsX29yX3ZlcnRpY2FsKHJhd0FuZ2xlICsgZGVsdGEsIGh2X3JhdGlvKSA6IC8vIGhvcml6b250YWwgb3IgdmVydGljYWxcXG4gICAgKG9wdGlvbiA9PSAxKSA/IHJhd0FuZ2xlICsgZGVsdGEgOiAgICAgICAvLyB1c2UgZnJlZSBhbmdsZSwgYW5kIGZsaXAgdG8gYWxpZ24gd2l0aCBvbmUgZGlyZWN0aW9uIG9mIHRoZSBheGlzXFxuICAgIChvcHRpb24gPT0gMCkgPyBsb29rX3Vwd2FyZHMocmF3QW5nbGUpIDogLy8gdXNlIGZyZWUgYW5nbGUsIGFuZCBzdGF5IHVwd2FyZHNcXG4gICAgKG9wdGlvbiA9PS0xKSA/IDAuMCA6ICAgICAgICAgICAgICAgICAgICAvLyB1c2VmdWwgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHksIGFsbCB0ZXh0cyByZW1haW5zIGhvcml6b250YWxcXG4gICAgICAgICAgICAgICAgICAgIHJhd0FuZ2xlOyAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgcmV0dXJuIGJhY2sgcmF3IGlucHV0IGFuZ2xlXFxufVxcblxcbmJvb2wgaXNBeGlzVGl0bGUgPSAoYXhpcy54ID09IDAuMCkgJiZcXG4gICAgICAgICAgICAgICAgICAgKGF4aXMueSA9PSAwLjApICYmXFxuICAgICAgICAgICAgICAgICAgIChheGlzLnogPT0gMC4wKTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAvL0NvbXB1dGUgd29ybGQgb2Zmc2V0XFxuICBmbG9hdCBheGlzRGlzdGFuY2UgPSBwb3NpdGlvbi56O1xcbiAgdmVjMyBkYXRhUG9zaXRpb24gPSBheGlzRGlzdGFuY2UgKiBheGlzICsgb2Zmc2V0O1xcblxcbiAgZmxvYXQgYmV0YSA9IGFuZ2xlOyAvLyBpLmUuIHVzZXIgZGVmaW5lZCBhdHRyaWJ1dGVzIGZvciBlYWNoIHRpY2tcXG5cXG4gIGZsb2F0IGF4aXNBbmdsZTtcXG4gIGZsb2F0IGNsaXBBbmdsZTtcXG4gIGZsb2F0IGZsaXA7XFxuXFxuICBpZiAoZW5hYmxlQWxpZ24pIHtcXG4gICAgYXhpc0FuZ2xlID0gKGlzQXhpc1RpdGxlKSA/IEhBTEZfUEkgOlxcbiAgICAgICAgICAgICAgICAgICAgICBjb21wdXRlVmlld0FuZ2xlKGRhdGFQb3NpdGlvbiwgZGF0YVBvc2l0aW9uICsgYXhpcyk7XFxuICAgIGNsaXBBbmdsZSA9IGNvbXB1dGVWaWV3QW5nbGUoZGF0YVBvc2l0aW9uLCBkYXRhUG9zaXRpb24gKyBhbGlnbkRpcik7XFxuXFxuICAgIGF4aXNBbmdsZSArPSAoc2luKGF4aXNBbmdsZSkgPCAwLjApID8gUEkgOiAwLjA7XFxuICAgIGNsaXBBbmdsZSArPSAoc2luKGNsaXBBbmdsZSkgPCAwLjApID8gUEkgOiAwLjA7XFxuXFxuICAgIGZsaXAgPSAoZG90KHZlYzIoY29zKGF4aXNBbmdsZSksIHNpbihheGlzQW5nbGUpKSxcXG4gICAgICAgICAgICAgICAgdmVjMihzaW4oY2xpcEFuZ2xlKSwtY29zKGNsaXBBbmdsZSkpKSA+IDAuMCkgPyAxLjAgOiAwLjA7XFxuXFxuICAgIGJldGEgKz0gYXBwbHlBbGlnbk9wdGlvbihjbGlwQW5nbGUsIGZsaXAgKiBQSSk7XFxuICB9XFxuXFxuICAvL0NvbXB1dGUgcGxhbmUgb2Zmc2V0XFxuICB2ZWMyIHBsYW5lQ29vcmQgPSBwb3NpdGlvbi54eSAqIHBpeGVsU2NhbGU7XFxuXFxuICBtYXQyIHBsYW5lWGZvcm0gPSBzY2FsZSAqIG1hdDIoXFxuICAgICBjb3MoYmV0YSksIHNpbihiZXRhKSxcXG4gICAgLXNpbihiZXRhKSwgY29zKGJldGEpXFxuICApO1xcblxcbiAgdmVjMiB2aWV3T2Zmc2V0ID0gMi4wICogcGxhbmVYZm9ybSAqIHBsYW5lQ29vcmQgLyByZXNvbHV0aW9uO1xcblxcbiAgLy9Db21wdXRlIGNsaXAgcG9zaXRpb25cXG4gIHZlYzMgY2xpcFBvc2l0aW9uID0gcHJvamVjdChkYXRhUG9zaXRpb24pO1xcblxcbiAgLy9BcHBseSB0ZXh0IG9mZnNldCBpbiBjbGlwIGNvb3JkaW5hdGVzXFxuICBjbGlwUG9zaXRpb24gKz0gdmVjMyh2aWV3T2Zmc2V0LCAwLjApO1xcblxcbiAgLy9Eb25lXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQoY2xpcFBvc2l0aW9uLCAxLjApO1xcbn1cIl0pXHJcbnZhciB0ZXh0RnJhZyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG51bmlmb3JtIHZlYzQgY29sb3I7XFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gY29sb3I7XFxufVwiXSlcclxuZXhwb3J0cy50ZXh0ID0gZnVuY3Rpb24oZ2wpIHtcclxuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCB0ZXh0VmVydCwgdGV4dEZyYWcsIG51bGwsIFtcclxuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9XHJcbiAgXSlcclxufVxyXG5cclxudmFyIGJnVmVydCA9IGdsc2xpZnkoW1wiI2RlZmluZSBHTFNMSUZZIDFcXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjMyBub3JtYWw7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBlbmFibGU7XFxudW5pZm9ybSB2ZWMzIGJvdW5kc1syXTtcXG5cXG52YXJ5aW5nIHZlYzMgY29sb3JDaGFubmVsO1xcblxcbnZvaWQgbWFpbigpIHtcXG5cXG4gIHZlYzMgc2lnbkF4aXMgPSBzaWduKGJvdW5kc1sxXSAtIGJvdW5kc1swXSk7XFxuXFxuICB2ZWMzIHJlYWxOb3JtYWwgPSBzaWduQXhpcyAqIG5vcm1hbDtcXG5cXG4gIGlmKGRvdChyZWFsTm9ybWFsLCBlbmFibGUpID4gMC4wKSB7XFxuICAgIHZlYzMgbWluUmFuZ2UgPSBtaW4oYm91bmRzWzBdLCBib3VuZHNbMV0pO1xcbiAgICB2ZWMzIG1heFJhbmdlID0gbWF4KGJvdW5kc1swXSwgYm91bmRzWzFdKTtcXG4gICAgdmVjMyBuUG9zaXRpb24gPSBtaXgobWluUmFuZ2UsIG1heFJhbmdlLCAwLjUgKiAocG9zaXRpb24gKyAxLjApKTtcXG4gICAgZ2xfUG9zaXRpb24gPSBwcm9qZWN0aW9uICogdmlldyAqIG1vZGVsICogdmVjNChuUG9zaXRpb24sIDEuMCk7XFxuICB9IGVsc2Uge1xcbiAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMCwwLDAsMCk7XFxuICB9XFxuXFxuICBjb2xvckNoYW5uZWwgPSBhYnMocmVhbE5vcm1hbCk7XFxufVwiXSlcclxudmFyIGJnRnJhZyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG51bmlmb3JtIHZlYzQgY29sb3JzWzNdO1xcblxcbnZhcnlpbmcgdmVjMyBjb2xvckNoYW5uZWw7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gY29sb3JDaGFubmVsLnggKiBjb2xvcnNbMF0gK1xcbiAgICAgICAgICAgICAgICAgY29sb3JDaGFubmVsLnkgKiBjb2xvcnNbMV0gK1xcbiAgICAgICAgICAgICAgICAgY29sb3JDaGFubmVsLnogKiBjb2xvcnNbMl07XFxufVwiXSlcclxuZXhwb3J0cy5iZyA9IGZ1bmN0aW9uKGdsKSB7XHJcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgYmdWZXJ0LCBiZ0ZyYWcsIG51bGwsIFtcclxuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxyXG4gICAge25hbWU6ICdub3JtYWwnLCB0eXBlOiAndmVjMyd9XHJcbiAgXSlcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIlxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUZXh0U3ByaXRlc1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciAgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG52YXIgY3JlYXRlVkFPICAgICA9IHJlcXVpcmUoJ2dsLXZhbycpXHJcbnZhciB2ZWN0b3JpemVUZXh0ID0gcmVxdWlyZSgndmVjdG9yaXplLXRleHQnKVxyXG52YXIgY3JlYXRlU2hhZGVyICA9IHJlcXVpcmUoJy4vc2hhZGVycycpLnRleHRcclxuXHJcbnZhciBnbG9iYWxzID0gd2luZG93IHx8IHByb2Nlc3MuZ2xvYmFsIHx8IHt9XHJcbnZhciBfX1RFWFRfQ0FDSEUgID0gZ2xvYmFscy5fX1RFWFRfQ0FDSEUgfHwge31cclxuZ2xvYmFscy5fX1RFWFRfQ0FDSEUgPSB7fVxyXG5cclxuLy9WZXJ0ZXggYnVmZmVyIGZvcm1hdCBmb3IgdGV4dCBpczpcclxuLy9cclxuLy8vIFt4LHksel0gPSBTcGF0aWFsIGNvb3JkaW5hdGVcclxuLy9cclxuXHJcbnZhciBWRVJURVhfU0laRSA9IDNcclxudmFyIFZFUlRFWF9TVFJJREUgPSBWRVJURVhfU0laRSAqIDRcclxuXHJcbmZ1bmN0aW9uIFRleHRTcHJpdGVzKFxyXG4gIGdsLFxyXG4gIHNoYWRlcixcclxuICBidWZmZXIsXHJcbiAgdmFvKSB7XHJcbiAgdGhpcy5nbCAgICAgICAgICAgPSBnbFxyXG4gIHRoaXMuc2hhZGVyICAgICAgID0gc2hhZGVyXHJcbiAgdGhpcy5idWZmZXIgICAgICAgPSBidWZmZXJcclxuICB0aGlzLnZhbyAgICAgICAgICA9IHZhb1xyXG4gIHRoaXMudGlja09mZnNldCAgID1cclxuICB0aGlzLnRpY2tDb3VudCAgICA9XHJcbiAgdGhpcy5sYWJlbE9mZnNldCAgPVxyXG4gIHRoaXMubGFiZWxDb3VudCAgID0gbnVsbFxyXG59XHJcblxyXG52YXIgcHJvdG8gPSBUZXh0U3ByaXRlcy5wcm90b3R5cGVcclxuXHJcbi8vQmluZCB0ZXh0dXJlcyBmb3IgcmVuZGVyaW5nXHJcbnZhciBTSEFQRSA9IFswLDBdXHJcbnByb3RvLmJpbmQgPSBmdW5jdGlvbihtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgcGl4ZWxTY2FsZSkge1xyXG4gIHRoaXMudmFvLmJpbmQoKVxyXG4gIHRoaXMuc2hhZGVyLmJpbmQoKVxyXG4gIHZhciB1bmlmb3JtcyA9IHRoaXMuc2hhZGVyLnVuaWZvcm1zXHJcbiAgdW5pZm9ybXMubW9kZWwgPSBtb2RlbFxyXG4gIHVuaWZvcm1zLnZpZXcgPSB2aWV3XHJcbiAgdW5pZm9ybXMucHJvamVjdGlvbiA9IHByb2plY3Rpb25cclxuICB1bmlmb3Jtcy5waXhlbFNjYWxlID0gcGl4ZWxTY2FsZVxyXG4gIFNIQVBFWzBdID0gdGhpcy5nbC5kcmF3aW5nQnVmZmVyV2lkdGhcclxuICBTSEFQRVsxXSA9IHRoaXMuZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnJlc29sdXRpb24gPSBTSEFQRVxyXG59XHJcblxyXG5wcm90by51bmJpbmQgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnZhby51bmJpbmQoKVxyXG59XHJcblxyXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihib3VuZHMsIGxhYmVscywgbGFiZWxGb250LCB0aWNrcywgdGlja0ZvbnQpIHtcclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcbiAgdmFyIGRhdGEgPSBbXVxyXG5cclxuICBmdW5jdGlvbiBhZGRJdGVtKHQsIHRleHQsIGZvbnQsIHNpemUpIHtcclxuICAgIHZhciBmb250Y2FjaGUgPSBfX1RFWFRfQ0FDSEVbZm9udF1cclxuICAgIGlmKCFmb250Y2FjaGUpIHtcclxuICAgICAgZm9udGNhY2hlID0gX19URVhUX0NBQ0hFW2ZvbnRdID0ge31cclxuICAgIH1cclxuICAgIHZhciBtZXNoID0gZm9udGNhY2hlW3RleHRdXHJcbiAgICBpZighbWVzaCkge1xyXG4gICAgICBtZXNoID0gZm9udGNhY2hlW3RleHRdID0gdHJ5VmVjdG9yaXplVGV4dCh0ZXh0LCB7XHJcbiAgICAgICAgdHJpYW5nbGVzOiB0cnVlLFxyXG4gICAgICAgIGZvbnQ6IGZvbnQsXHJcbiAgICAgICAgdGV4dEFsaWduOiAnY2VudGVyJyxcclxuICAgICAgICB0ZXh0QmFzZWxpbmU6ICdtaWRkbGUnXHJcbiAgICAgIH0pXHJcbiAgICB9XHJcbiAgICB2YXIgc2NhbGUgPSAoc2l6ZSB8fCAxMikgLyAxMlxyXG4gICAgdmFyIHBvc2l0aW9ucyA9IG1lc2gucG9zaXRpb25zXHJcbiAgICB2YXIgY2VsbHMgPSBtZXNoLmNlbGxzXHJcbiAgICB2YXIgbG8gPSBbIEluZmluaXR5LCBJbmZpbml0eV1cclxuICAgIHZhciBoaSA9IFstSW5maW5pdHksLUluZmluaXR5XVxyXG4gICAgZm9yKHZhciBpPTAsIG5jPWNlbGxzLmxlbmd0aDsgaTxuYzsgKytpKSB7XHJcbiAgICAgIHZhciBjID0gY2VsbHNbaV1cclxuICAgICAgZm9yKHZhciBqPTI7IGo+PTA7IC0taikge1xyXG4gICAgICAgIHZhciBwID0gcG9zaXRpb25zW2Nbal1dXHJcbiAgICAgICAgZGF0YS5wdXNoKHNjYWxlKnBbMF0sIC1zY2FsZSpwWzFdLCB0KVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL0dlbmVyYXRlIHNwcml0ZXMgZm9yIGFsbCAzIGF4ZXMsIHN0b3JlIGRhdGEgaW4gdGV4dHVyZSBhdGxhc2VzXHJcbiAgdmFyIHRpY2tPZmZzZXQgID0gWzAsMCwwXVxyXG4gIHZhciB0aWNrQ291bnQgICA9IFswLDAsMF1cclxuICB2YXIgbGFiZWxPZmZzZXQgPSBbMCwwLDBdXHJcbiAgdmFyIGxhYmVsQ291bnQgID0gWzAsMCwwXVxyXG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xyXG5cclxuICAgIC8vR2VuZXJhdGUgbGFiZWxcclxuICAgIGxhYmVsT2Zmc2V0W2RdID0gKGRhdGEubGVuZ3RoL1ZFUlRFWF9TSVpFKXwwXHJcbiAgICBhZGRJdGVtKDAuNSooYm91bmRzWzBdW2RdK2JvdW5kc1sxXVtkXSksIGxhYmVsc1tkXSwgbGFiZWxGb250KVxyXG4gICAgbGFiZWxDb3VudFtkXSA9ICgoZGF0YS5sZW5ndGgvVkVSVEVYX1NJWkUpfDApIC0gbGFiZWxPZmZzZXRbZF1cclxuXHJcbiAgICAvL0dlbmVyYXRlIHNwcml0ZXMgZm9yIHRpY2sgbWFya3NcclxuICAgIHRpY2tPZmZzZXRbZF0gPSAoZGF0YS5sZW5ndGgvVkVSVEVYX1NJWkUpfDBcclxuICAgIGZvcih2YXIgaT0wOyBpPHRpY2tzW2RdLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIGlmKCF0aWNrc1tkXVtpXS50ZXh0KSB7XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG4gICAgICBhZGRJdGVtKFxyXG4gICAgICAgIHRpY2tzW2RdW2ldLngsXHJcbiAgICAgICAgdGlja3NbZF1baV0udGV4dCxcclxuICAgICAgICB0aWNrc1tkXVtpXS5mb250IHx8IHRpY2tGb250LFxyXG4gICAgICAgIHRpY2tzW2RdW2ldLmZvbnRTaXplIHx8IDEyKVxyXG4gICAgfVxyXG4gICAgdGlja0NvdW50W2RdID0gKChkYXRhLmxlbmd0aC9WRVJURVhfU0laRSl8MCkgLSB0aWNrT2Zmc2V0W2RdXHJcbiAgfVxyXG5cclxuICB0aGlzLmJ1ZmZlci51cGRhdGUoZGF0YSlcclxuICB0aGlzLnRpY2tPZmZzZXQgPSB0aWNrT2Zmc2V0XHJcbiAgdGhpcy50aWNrQ291bnQgPSB0aWNrQ291bnRcclxuICB0aGlzLmxhYmVsT2Zmc2V0ID0gbGFiZWxPZmZzZXRcclxuICB0aGlzLmxhYmVsQ291bnQgPSBsYWJlbENvdW50XHJcbn1cclxuXHJcbi8vRHJhd3MgdGhlIHRpY2sgbWFya3MgZm9yIGFuIGF4aXNcclxucHJvdG8uZHJhd1RpY2tzID0gZnVuY3Rpb24oZCwgc2NhbGUsIGFuZ2xlLCBvZmZzZXQsIGNvbG9yLCBheGlzLCBhbGlnbkRpciwgYWxpZ25PcHQpIHtcclxuICBpZighdGhpcy50aWNrQ291bnRbZF0pIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYXhpcyA9IGF4aXNcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5jb2xvciA9IGNvbG9yXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYW5nbGUgPSBhbmdsZVxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjYWxlID0gc2NhbGVcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5vZmZzZXQgPSBvZmZzZXRcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5hbGlnbkRpciA9IGFsaWduRGlyXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYWxpZ25PcHQgPSBhbGlnbk9wdFxyXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIHRoaXMudGlja0NvdW50W2RdLCB0aGlzLnRpY2tPZmZzZXRbZF0pXHJcbn1cclxuXHJcbi8vRHJhd3MgdGhlIHRleHQgbGFiZWwgZm9yIGFuIGF4aXNcclxucHJvdG8uZHJhd0xhYmVsID0gZnVuY3Rpb24oZCwgc2NhbGUsIGFuZ2xlLCBvZmZzZXQsIGNvbG9yLCBheGlzLCBhbGlnbkRpciwgYWxpZ25PcHQpIHtcclxuICBpZighdGhpcy5sYWJlbENvdW50W2RdKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmF4aXMgPSBheGlzXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuY29sb3IgPSBjb2xvclxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmFuZ2xlID0gYW5nbGVcclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5zY2FsZSA9IHNjYWxlXHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMub2Zmc2V0ID0gb2Zmc2V0XHJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYWxpZ25EaXIgPSBhbGlnbkRpclxyXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmFsaWduT3B0ID0gYWxpZ25PcHRcclxuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCB0aGlzLmxhYmVsQ291bnRbZF0sIHRoaXMubGFiZWxPZmZzZXRbZF0pXHJcbn1cclxuXHJcbi8vUmVsZWFzZXMgYWxsIHJlc291cmNlcyBhdHRhY2hlZCB0byB0aGlzIG9iamVjdFxyXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XHJcbiAgdGhpcy5zaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy52YW8uZGlzcG9zZSgpXHJcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHRyeVZlY3Rvcml6ZVRleHQodGV4dCwgb3B0aW9ucykge1xyXG4gIHRyeSB7XHJcbiAgICByZXR1cm4gdmVjdG9yaXplVGV4dCh0ZXh0LCBvcHRpb25zKVxyXG4gIH0gY2F0Y2goZSkge1xyXG4gICAgY29uc29sZS53YXJuKCdlcnJvciB2ZWN0b3JpemluZyB0ZXh0OicsIGUpXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBjZWxsczogW10sXHJcbiAgICAgIHBvc2l0aW9uczogW11cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVRleHRTcHJpdGVzKFxyXG4gICAgZ2wsXHJcbiAgICBib3VuZHMsXHJcbiAgICBsYWJlbHMsXHJcbiAgICBsYWJlbEZvbnQsXHJcbiAgICB0aWNrcyxcclxuICAgIHRpY2tGb250KSB7XHJcblxyXG4gIHZhciBidWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAgeyBcImJ1ZmZlclwiOiBidWZmZXIsXHJcbiAgICAgIFwic2l6ZVwiOiAzXHJcbiAgICB9XHJcbiAgXSlcclxuXHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuXHJcbiAgdmFyIHJlc3VsdCA9IG5ldyBUZXh0U3ByaXRlcyhcclxuICAgIGdsLFxyXG4gICAgc2hhZGVyLFxyXG4gICAgYnVmZmVyLFxyXG4gICAgdmFvKVxyXG5cclxuICByZXN1bHQudXBkYXRlKGJvdW5kcywgbGFiZWxzLCBsYWJlbEZvbnQsIHRpY2tzLCB0aWNrRm9udClcclxuXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxuZXhwb3J0cy5jcmVhdGUgICA9IGRlZmF1bHRUaWNrc1xyXG5leHBvcnRzLmVxdWFsICAgID0gdGlja3NFcXVhbFxyXG5cclxuZnVuY3Rpb24gcHJldHR5UHJpbnQoc3BhY2luZywgaSkge1xyXG4gIHZhciBzdGVwU3RyID0gc3BhY2luZyArIFwiXCJcclxuICB2YXIgdSA9IHN0ZXBTdHIuaW5kZXhPZihcIi5cIilcclxuICB2YXIgc2lnRmlncyA9IDBcclxuICBpZih1ID49IDApIHtcclxuICAgIHNpZ0ZpZ3MgPSBzdGVwU3RyLmxlbmd0aCAtIHUgLSAxXHJcbiAgfVxyXG4gIHZhciBzaGlmdCA9IE1hdGgucG93KDEwLCBzaWdGaWdzKVxyXG4gIHZhciB4ID0gTWF0aC5yb3VuZChzcGFjaW5nICogaSAqIHNoaWZ0KVxyXG4gIHZhciB4c3RyID0geCArIFwiXCJcclxuICBpZih4c3RyLmluZGV4T2YoXCJlXCIpID49IDApIHtcclxuICAgIHJldHVybiB4c3RyXHJcbiAgfVxyXG4gIHZhciB4aSA9IHggLyBzaGlmdCwgeGYgPSB4ICUgc2hpZnRcclxuICBpZih4IDwgMCkge1xyXG4gICAgeGkgPSAtTWF0aC5jZWlsKHhpKXwwXHJcbiAgICB4ZiA9ICgteGYpfDBcclxuICB9IGVsc2Uge1xyXG4gICAgeGkgPSBNYXRoLmZsb29yKHhpKXwwXHJcbiAgICB4ZiA9IHhmfDBcclxuICB9XHJcbiAgdmFyIHhpcyA9IFwiXCIgKyB4aSBcclxuICBpZih4IDwgMCkge1xyXG4gICAgeGlzID0gXCItXCIgKyB4aXNcclxuICB9XHJcbiAgaWYoc2lnRmlncykge1xyXG4gICAgdmFyIHhzID0gXCJcIiArIHhmXHJcbiAgICB3aGlsZSh4cy5sZW5ndGggPCBzaWdGaWdzKSB7XHJcbiAgICAgIHhzID0gXCIwXCIgKyB4c1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHhpcyArIFwiLlwiICsgeHNcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIHhpc1xyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gZGVmYXVsdFRpY2tzKGJvdW5kcywgdGlja1NwYWNpbmcpIHtcclxuICB2YXIgYXJyYXkgPSBbXVxyXG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xyXG4gICAgdmFyIHRpY2tzID0gW11cclxuICAgIHZhciBtID0gMC41Kihib3VuZHNbMF1bZF0rYm91bmRzWzFdW2RdKVxyXG4gICAgZm9yKHZhciB0PTA7IHQqdGlja1NwYWNpbmdbZF08PWJvdW5kc1sxXVtkXTsgKyt0KSB7XHJcbiAgICAgIHRpY2tzLnB1c2goe3g6IHQqdGlja1NwYWNpbmdbZF0sIHRleHQ6IHByZXR0eVByaW50KHRpY2tTcGFjaW5nW2RdLCB0KX0pXHJcbiAgICB9XHJcbiAgICBmb3IodmFyIHQ9LTE7IHQqdGlja1NwYWNpbmdbZF0+PWJvdW5kc1swXVtkXTsgLS10KSB7XHJcbiAgICAgIHRpY2tzLnB1c2goe3g6IHQqdGlja1NwYWNpbmdbZF0sIHRleHQ6IHByZXR0eVByaW50KHRpY2tTcGFjaW5nW2RdLCB0KX0pXHJcbiAgICB9XHJcbiAgICBhcnJheS5wdXNoKHRpY2tzKVxyXG4gIH1cclxuICByZXR1cm4gYXJyYXlcclxufVxyXG5cclxuZnVuY3Rpb24gdGlja3NFcXVhbCh0aWNrc0EsIHRpY2tzQikge1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgaWYodGlja3NBW2ldLmxlbmd0aCAhPT0gdGlja3NCW2ldLmxlbmd0aCkge1xyXG4gICAgICByZXR1cm4gZmFsc2VcclxuICAgIH1cclxuICAgIGZvcih2YXIgaj0wOyBqPHRpY2tzQVtpXS5sZW5ndGg7ICsraikge1xyXG4gICAgICB2YXIgYSA9IHRpY2tzQVtpXVtqXVxyXG4gICAgICB2YXIgYiA9IHRpY2tzQltpXVtqXVxyXG4gICAgICBpZihcclxuICAgICAgICBhLnggIT09IGIueCB8fFxyXG4gICAgICAgIGEudGV4dCAhPT0gYi50ZXh0IHx8XHJcbiAgICAgICAgYS5mb250ICE9PSBiLmZvbnQgfHxcclxuICAgICAgICBhLmZvbnRDb2xvciAhPT0gYi5mb250Q29sb3IgfHxcclxuICAgICAgICBhLmZvbnRTaXplICE9PSBiLmZvbnRTaXplIHx8XHJcbiAgICAgICAgYS5keCAhPT0gYi5keCB8fFxyXG4gICAgICAgIGEuZHkgIT09IGIuZHlcclxuICAgICAgKSB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIHRydWVcclxufSIsIlwidXNlIHN0cmljdFwiXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGF4ZXNQcm9wZXJ0aWVzXHJcblxyXG52YXIgZ2V0UGxhbmVzICAgPSByZXF1aXJlKFwiZXh0cmFjdC1mcnVzdHVtLXBsYW5lc1wiKVxyXG52YXIgc3BsaXRQb2x5ICAgPSByZXF1aXJlKFwic3BsaXQtcG9seWdvblwiKVxyXG52YXIgY3ViZVBhcmFtcyAgPSByZXF1aXJlKFwiLi9saWIvY3ViZS5qc1wiKVxyXG52YXIgbTRtdWwgICAgICAgPSByZXF1aXJlKFwiZ2wtbWF0NC9tdWx0aXBseVwiKVxyXG52YXIgbTR0cmFuc3Bvc2UgPSByZXF1aXJlKFwiZ2wtbWF0NC90cmFuc3Bvc2VcIilcclxudmFyIHY0dHJhbnNmb3JtTWF0NCA9IHJlcXVpcmUoXCJnbC12ZWM0L3RyYW5zZm9ybU1hdDRcIilcclxuXHJcbnZhciBpZGVudGl0eSAgICA9IG5ldyBGbG9hdDMyQXJyYXkoW1xyXG4gICAgMSwgMCwgMCwgMCxcclxuICAgIDAsIDEsIDAsIDAsXHJcbiAgICAwLCAwLCAxLCAwLFxyXG4gICAgMCwgMCwgMCwgMVxyXG4gIF0pXHJcblxyXG52YXIgbXZwICAgICAgICAgPSBuZXcgRmxvYXQzMkFycmF5KDE2KVxyXG5cclxuZnVuY3Rpb24gQXhlc1JhbmdlM0QobG8sIGhpLCBwaXhlbHNQZXJEYXRhVW5pdCkge1xyXG4gIHRoaXMubG8gPSBsb1xyXG4gIHRoaXMuaGkgPSBoaVxyXG4gIHRoaXMucGl4ZWxzUGVyRGF0YVVuaXQgPSBwaXhlbHNQZXJEYXRhVW5pdFxyXG59XHJcblxyXG52YXIgU0NSQVRDSF9QID0gWzAsMCwwLDFdXHJcbnZhciBTQ1JBVENIX1EgPSBbMCwwLDAsMV1cclxuXHJcbmZ1bmN0aW9uIGdyYWRpZW50KHJlc3VsdCwgTSwgdiwgd2lkdGgsIGhlaWdodCkge1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgdmFyIHAgPSBTQ1JBVENIX1BcclxuICAgIHZhciBxID0gU0NSQVRDSF9RXHJcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgcVtqXSA9IHBbal0gPSB2W2pdXHJcbiAgICB9XHJcbiAgICBxWzNdID0gcFszXSA9IDFcclxuXHJcbiAgICBxW2ldICs9IDFcclxuICAgIHY0dHJhbnNmb3JtTWF0NChxLCBxLCBNKVxyXG4gICAgaWYocVszXSA8IDApIHtcclxuICAgICAgcmVzdWx0W2ldID0gSW5maW5pdHlcclxuICAgIH1cclxuXHJcbiAgICBwW2ldIC09IDFcclxuICAgIHY0dHJhbnNmb3JtTWF0NChwLCBwLCBNKVxyXG4gICAgaWYocFszXSA8IDApIHtcclxuICAgICAgcmVzdWx0W2ldID0gSW5maW5pdHlcclxuICAgIH1cclxuXHJcbiAgICB2YXIgZHggPSAocFswXS9wWzNdIC0gcVswXS9xWzNdKSAqIHdpZHRoXHJcbiAgICB2YXIgZHkgPSAocFsxXS9wWzNdIC0gcVsxXS9xWzNdKSAqIGhlaWdodFxyXG5cclxuICAgIHJlc3VsdFtpXSA9IDAuMjUgKiBNYXRoLnNxcnQoZHgqZHggKyBkeSpkeSlcclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG52YXIgUkFOR0VTID0gW1xyXG4gIG5ldyBBeGVzUmFuZ2UzRChJbmZpbml0eSwgLUluZmluaXR5LCBJbmZpbml0eSksXHJcbiAgbmV3IEF4ZXNSYW5nZTNEKEluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5KSxcclxuICBuZXcgQXhlc1JhbmdlM0QoSW5maW5pdHksIC1JbmZpbml0eSwgSW5maW5pdHkpXHJcbl1cclxuXHJcbnZhciBTQ1JBVENIX1ggPSBbMCwwLDBdXHJcblxyXG5mdW5jdGlvbiBheGVzUHJvcGVydGllcyhheGVzLCBjYW1lcmEsIHdpZHRoLCBoZWlnaHQsIHBhcmFtcykge1xyXG4gIHZhciBtb2RlbCAgICAgICA9IGNhbWVyYS5tb2RlbCB8fCBpZGVudGl0eVxyXG4gIHZhciB2aWV3ICAgICAgICA9IGNhbWVyYS52aWV3IHx8IGlkZW50aXR5XHJcbiAgdmFyIHByb2plY3Rpb24gID0gY2FtZXJhLnByb2plY3Rpb24gfHwgaWRlbnRpdHlcclxuICB2YXIgYm91bmRzICAgICAgPSBheGVzLmJvdW5kc1xyXG4gIHZhciBwYXJhbXMgICAgICA9IHBhcmFtcyB8fCBjdWJlUGFyYW1zKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBib3VuZHMpXHJcbiAgdmFyIGF4aXMgICAgICAgID0gcGFyYW1zLmF4aXNcclxuICB2YXIgZWRnZXMgICAgICAgPSBwYXJhbXMuZWRnZXNcclxuXHJcbiAgbTRtdWwobXZwLCB2aWV3LCBtb2RlbClcclxuICBtNG11bChtdnAsIHByb2plY3Rpb24sIG12cClcclxuXHJcbiAgLy9DYWxjdWxhdGUgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIGZvciBlYWNoIGF4aXM6XHJcbiAgLy9cclxuICAvLyAqIGxvIC0gc3RhcnQgb2YgdmlzaWJsZSByYW5nZSBmb3IgZWFjaCBheGlzIGluIHRpY2sgY29vcmRpbmF0ZXNcclxuICAvLyAqIGhpIC0gZW5kIG9mIHZpc2libGUgcmFuZ2UgZm9yIGVhY2ggYXhpcyBpbiB0aWNrIGNvb3JkaW5hdGVzXHJcbiAgLy8gKiB0aWNrc1BlclBpeGVsIC0gcGl4ZWwgZGVuc2l0eSBvZiB0aWNrIG1hcmtzIGZvciB0aGUgYXhpc1xyXG4gIC8vXHJcbiAgdmFyIHJhbmdlcyA9IFJBTkdFU1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgcmFuZ2VzW2ldLmxvID0gSW5maW5pdHlcclxuICAgIHJhbmdlc1tpXS5oaSA9IC1JbmZpbml0eVxyXG4gICAgcmFuZ2VzW2ldLnBpeGVsc1BlckRhdGFVbml0ID0gSW5maW5pdHlcclxuICB9XHJcblxyXG4gIC8vQ29tcHV0ZSBmcnVzdHVtIHBsYW5lcywgaW50ZXJzZWN0IHdpdGggYm94XHJcbiAgdmFyIGZydXN0dW0gPSBnZXRQbGFuZXMobTR0cmFuc3Bvc2UobXZwLCBtdnApKVxyXG4gIG00dHJhbnNwb3NlKG12cCwgbXZwKVxyXG5cclxuICAvL0xvb3Agb3ZlciB2ZXJ0aWNlcyBvZiB2aWV3YWJsZSBib3hcclxuICBmb3IodmFyIGQ9MDsgZDwzOyArK2QpIHtcclxuICAgIHZhciB1ID0gKGQrMSklM1xyXG4gICAgdmFyIHYgPSAoZCsyKSUzXHJcbiAgICB2YXIgeCA9IFNDUkFUQ0hfWFxyXG5pX2xvb3A6XHJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgICAgdmFyIHBvbHkgPSBbXVxyXG5cclxuICAgICAgaWYoKGF4aXNbZF0gPCAwKSA9PT0gISFpKSB7XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG5cclxuICAgICAgeFtkXSA9IGJvdW5kc1tpXVtkXVxyXG4gICAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcclxuICAgICAgICB4W3VdID0gYm91bmRzW2peaV1bdV1cclxuICAgICAgICBmb3IodmFyIGs9MDsgazwyOyArK2spIHtcclxuICAgICAgICAgIHhbdl0gPSBib3VuZHNba15qXmldW3ZdXHJcbiAgICAgICAgICBwb2x5LnB1c2goeC5zbGljZSgpKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBmb3IodmFyIGo9MDsgajxmcnVzdHVtLmxlbmd0aDsgKytqKSB7XHJcbiAgICAgICAgaWYocG9seS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgIGNvbnRpbnVlIGlfbG9vcFxyXG4gICAgICAgIH1cclxuICAgICAgICBwb2x5ID0gc3BsaXRQb2x5LnBvc2l0aXZlKHBvbHksIGZydXN0dW1bal0pXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vTG9vcCBvdmVyIHZlcnRpY2VzIG9mIHBvbHlnb24gdG8gZmluZCBleHRyZW1hbCBwb2ludHNcclxuICAgICAgZm9yKHZhciBqPTA7IGo8cG9seS5sZW5ndGg7ICsraikge1xyXG4gICAgICAgIHZhciB2ID0gcG9seVtqXVxyXG4gICAgICAgIHZhciBncmFkID0gZ3JhZGllbnQoU0NSQVRDSF9YLCBtdnAsIHYsIHdpZHRoLCBoZWlnaHQpXHJcbiAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgICByYW5nZXNba10ubG8gPSBNYXRoLm1pbihyYW5nZXNba10ubG8sIHZba10pXHJcbiAgICAgICAgICByYW5nZXNba10uaGkgPSBNYXRoLm1heChyYW5nZXNba10uaGksIHZba10pXHJcbiAgICAgICAgICBpZihrICE9PSBkKSB7XHJcbiAgICAgICAgICAgIHJhbmdlc1trXS5waXhlbHNQZXJEYXRhVW5pdCA9IE1hdGgubWluKHJhbmdlc1trXS5waXhlbHNQZXJEYXRhVW5pdCwgTWF0aC5hYnMoZ3JhZFtrXSkpXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmFuZ2VzXHJcbn1cclxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHBvb2wgPSByZXF1aXJlKFwidHlwZWRhcnJheS1wb29sXCIpXG52YXIgb3BzID0gcmVxdWlyZShcIm5kYXJyYXktb3BzXCIpXG52YXIgbmRhcnJheSA9IHJlcXVpcmUoXCJuZGFycmF5XCIpXG5cbnZhciBTVVBQT1JURURfVFlQRVMgPSBbXG4gIFwidWludDhcIixcbiAgXCJ1aW50OF9jbGFtcGVkXCIsXG4gIFwidWludDE2XCIsXG4gIFwidWludDMyXCIsXG4gIFwiaW50OFwiLFxuICBcImludDE2XCIsXG4gIFwiaW50MzJcIixcbiAgXCJmbG9hdDMyXCIgXVxuXG5mdW5jdGlvbiBHTEJ1ZmZlcihnbCwgdHlwZSwgaGFuZGxlLCBsZW5ndGgsIHVzYWdlKSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLnR5cGUgPSB0eXBlXG4gIHRoaXMuaGFuZGxlID0gaGFuZGxlXG4gIHRoaXMubGVuZ3RoID0gbGVuZ3RoXG4gIHRoaXMudXNhZ2UgPSB1c2FnZVxufVxuXG52YXIgcHJvdG8gPSBHTEJ1ZmZlci5wcm90b3R5cGVcblxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmdsLmJpbmRCdWZmZXIodGhpcy50eXBlLCB0aGlzLmhhbmRsZSlcbn1cblxucHJvdG8udW5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZ2wuYmluZEJ1ZmZlcih0aGlzLnR5cGUsIG51bGwpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5nbC5kZWxldGVCdWZmZXIodGhpcy5oYW5kbGUpXG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVR5cGVBcnJheShnbCwgdHlwZSwgbGVuLCB1c2FnZSwgZGF0YSwgb2Zmc2V0KSB7XG4gIHZhciBkYXRhTGVuID0gZGF0YS5sZW5ndGggKiBkYXRhLkJZVEVTX1BFUl9FTEVNRU5UXG4gIGlmKG9mZnNldCA8IDApIHtcbiAgICBnbC5idWZmZXJEYXRhKHR5cGUsIGRhdGEsIHVzYWdlKVxuICAgIHJldHVybiBkYXRhTGVuXG4gIH1cbiAgaWYoZGF0YUxlbiArIG9mZnNldCA+IGxlbikge1xuICAgIHRocm93IG5ldyBFcnJvcihcImdsLWJ1ZmZlcjogSWYgcmVzaXppbmcgYnVmZmVyLCBtdXN0IG5vdCBzcGVjaWZ5IG9mZnNldFwiKVxuICB9XG4gIGdsLmJ1ZmZlclN1YkRhdGEodHlwZSwgb2Zmc2V0LCBkYXRhKVxuICByZXR1cm4gbGVuXG59XG5cbmZ1bmN0aW9uIG1ha2VTY3JhdGNoVHlwZUFycmF5KGFycmF5LCBkdHlwZSkge1xuICB2YXIgcmVzID0gcG9vbC5tYWxsb2MoYXJyYXkubGVuZ3RoLCBkdHlwZSlcbiAgdmFyIG4gPSBhcnJheS5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzW2ldID0gYXJyYXlbaV1cbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbmZ1bmN0aW9uIGlzUGFja2VkKHNoYXBlLCBzdHJpZGUpIHtcbiAgdmFyIG4gPSAxXG4gIGZvcih2YXIgaT1zdHJpZGUubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgIGlmKHN0cmlkZVtpXSAhPT0gbikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIG4gKj0gc2hhcGVbaV1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihhcnJheSwgb2Zmc2V0KSB7XG4gIGlmKHR5cGVvZiBvZmZzZXQgIT09IFwibnVtYmVyXCIpIHtcbiAgICBvZmZzZXQgPSAtMVxuICB9XG4gIHRoaXMuYmluZCgpXG4gIGlmKHR5cGVvZiBhcnJheSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgYXJyYXkuc2hhcGUgIT09IFwidW5kZWZpbmVkXCIpIHsgLy9uZGFycmF5XG4gICAgdmFyIGR0eXBlID0gYXJyYXkuZHR5cGVcbiAgICBpZihTVVBQT1JURURfVFlQRVMuaW5kZXhPZihkdHlwZSkgPCAwKSB7XG4gICAgICBkdHlwZSA9IFwiZmxvYXQzMlwiXG4gICAgfVxuICAgIGlmKHRoaXMudHlwZSA9PT0gdGhpcy5nbC5FTEVNRU5UX0FSUkFZX0JVRkZFUikge1xuICAgICAgdmFyIGV4dCA9IGdsLmdldEV4dGVuc2lvbignT0VTX2VsZW1lbnRfaW5kZXhfdWludCcpXG4gICAgICBpZihleHQgJiYgZHR5cGUgIT09IFwidWludDE2XCIpIHtcbiAgICAgICAgZHR5cGUgPSBcInVpbnQzMlwiXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkdHlwZSA9IFwidWludDE2XCJcbiAgICAgIH1cbiAgICB9XG4gICAgaWYoZHR5cGUgPT09IGFycmF5LmR0eXBlICYmIGlzUGFja2VkKGFycmF5LnNoYXBlLCBhcnJheS5zdHJpZGUpKSB7XG4gICAgICBpZihhcnJheS5vZmZzZXQgPT09IDAgJiYgYXJyYXkuZGF0YS5sZW5ndGggPT09IGFycmF5LnNoYXBlWzBdKSB7XG4gICAgICAgIHRoaXMubGVuZ3RoID0gdXBkYXRlVHlwZUFycmF5KHRoaXMuZ2wsIHRoaXMudHlwZSwgdGhpcy5sZW5ndGgsIHRoaXMudXNhZ2UsIGFycmF5LmRhdGEsIG9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubGVuZ3RoID0gdXBkYXRlVHlwZUFycmF5KHRoaXMuZ2wsIHRoaXMudHlwZSwgdGhpcy5sZW5ndGgsIHRoaXMudXNhZ2UsIGFycmF5LmRhdGEuc3ViYXJyYXkoYXJyYXkub2Zmc2V0LCBhcnJheS5zaGFwZVswXSksIG9mZnNldClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHRtcCA9IHBvb2wubWFsbG9jKGFycmF5LnNpemUsIGR0eXBlKVxuICAgICAgdmFyIG5kdCA9IG5kYXJyYXkodG1wLCBhcnJheS5zaGFwZSlcbiAgICAgIG9wcy5hc3NpZ24obmR0LCBhcnJheSlcbiAgICAgIGlmKG9mZnNldCA8IDApIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB1cGRhdGVUeXBlQXJyYXkodGhpcy5nbCwgdGhpcy50eXBlLCB0aGlzLmxlbmd0aCwgdGhpcy51c2FnZSwgdG1wLCBvZmZzZXQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHVwZGF0ZVR5cGVBcnJheSh0aGlzLmdsLCB0aGlzLnR5cGUsIHRoaXMubGVuZ3RoLCB0aGlzLnVzYWdlLCB0bXAuc3ViYXJyYXkoMCwgYXJyYXkuc2l6ZSksIG9mZnNldClcbiAgICAgIH1cbiAgICAgIHBvb2wuZnJlZSh0bXApXG4gICAgfVxuICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShhcnJheSkpIHsgLy9WYW5pbGxhIGFycmF5XG4gICAgdmFyIHRcbiAgICBpZih0aGlzLnR5cGUgPT09IHRoaXMuZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIpIHtcbiAgICAgIHQgPSBtYWtlU2NyYXRjaFR5cGVBcnJheShhcnJheSwgXCJ1aW50MTZcIilcbiAgICB9IGVsc2Uge1xuICAgICAgdCA9IG1ha2VTY3JhdGNoVHlwZUFycmF5KGFycmF5LCBcImZsb2F0MzJcIilcbiAgICB9XG4gICAgaWYob2Zmc2V0IDwgMCkge1xuICAgICAgdGhpcy5sZW5ndGggPSB1cGRhdGVUeXBlQXJyYXkodGhpcy5nbCwgdGhpcy50eXBlLCB0aGlzLmxlbmd0aCwgdGhpcy51c2FnZSwgdCwgb2Zmc2V0KVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxlbmd0aCA9IHVwZGF0ZVR5cGVBcnJheSh0aGlzLmdsLCB0aGlzLnR5cGUsIHRoaXMubGVuZ3RoLCB0aGlzLnVzYWdlLCB0LnN1YmFycmF5KDAsIGFycmF5Lmxlbmd0aCksIG9mZnNldClcbiAgICB9XG4gICAgcG9vbC5mcmVlKHQpXG4gIH0gZWxzZSBpZih0eXBlb2YgYXJyYXkgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIGFycmF5Lmxlbmd0aCA9PT0gXCJudW1iZXJcIikgeyAvL1R5cGVkIGFycmF5XG4gICAgdGhpcy5sZW5ndGggPSB1cGRhdGVUeXBlQXJyYXkodGhpcy5nbCwgdGhpcy50eXBlLCB0aGlzLmxlbmd0aCwgdGhpcy51c2FnZSwgYXJyYXksIG9mZnNldClcbiAgfSBlbHNlIGlmKHR5cGVvZiBhcnJheSA9PT0gXCJudW1iZXJcIiB8fCBhcnJheSA9PT0gdW5kZWZpbmVkKSB7IC8vTnVtYmVyL2RlZmF1bHRcbiAgICBpZihvZmZzZXQgPj0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZ2wtYnVmZmVyOiBDYW5ub3Qgc3BlY2lmeSBvZmZzZXQgd2hlbiByZXNpemluZyBidWZmZXJcIilcbiAgICB9XG4gICAgYXJyYXkgPSBhcnJheSB8IDBcbiAgICBpZihhcnJheSA8PSAwKSB7XG4gICAgICBhcnJheSA9IDFcbiAgICB9XG4gICAgdGhpcy5nbC5idWZmZXJEYXRhKHRoaXMudHlwZSwgYXJyYXl8MCwgdGhpcy51c2FnZSlcbiAgICB0aGlzLmxlbmd0aCA9IGFycmF5XG4gIH0gZWxzZSB7IC8vRXJyb3IsIGNhc2Ugc2hvdWxkIG5vdCBoYXBwZW5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC1idWZmZXI6IEludmFsaWQgZGF0YSB0eXBlXCIpXG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlQnVmZmVyKGdsLCBkYXRhLCB0eXBlLCB1c2FnZSkge1xuICB0eXBlID0gdHlwZSB8fCBnbC5BUlJBWV9CVUZGRVJcbiAgdXNhZ2UgPSB1c2FnZSB8fCBnbC5EWU5BTUlDX0RSQVdcbiAgaWYodHlwZSAhPT0gZ2wuQVJSQVlfQlVGRkVSICYmIHR5cGUgIT09IGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiZ2wtYnVmZmVyOiBJbnZhbGlkIHR5cGUgZm9yIHdlYmdsIGJ1ZmZlciwgbXVzdCBiZSBlaXRoZXIgZ2wuQVJSQVlfQlVGRkVSIG9yIGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSXCIpXG4gIH1cbiAgaWYodXNhZ2UgIT09IGdsLkRZTkFNSUNfRFJBVyAmJiB1c2FnZSAhPT0gZ2wuU1RBVElDX0RSQVcgJiYgdXNhZ2UgIT09IGdsLlNUUkVBTV9EUkFXKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiZ2wtYnVmZmVyOiBJbnZhbGlkIHVzYWdlIGZvciBidWZmZXIsIG11c3QgYmUgZWl0aGVyIGdsLkRZTkFNSUNfRFJBVywgZ2wuU1RBVElDX0RSQVcgb3IgZ2wuU1RSRUFNX0RSQVdcIilcbiAgfVxuICB2YXIgaGFuZGxlID0gZ2wuY3JlYXRlQnVmZmVyKClcbiAgdmFyIHJlc3VsdCA9IG5ldyBHTEJ1ZmZlcihnbCwgdHlwZSwgaGFuZGxlLCAwLCB1c2FnZSlcbiAgcmVzdWx0LnVwZGF0ZShkYXRhKVxuICByZXR1cm4gcmVzdWx0XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQnVmZmVyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxuXHJcbnZhciBWID0gcmVxdWlyZSgnZ2wtdmVjMycpO1xyXG52YXIgVjQgPSByZXF1aXJlKCdnbC12ZWM0Jyk7XHJcblxyXG52YXIgdmVjMyA9IGZ1bmN0aW9uKHgsIHksIHopIHtcclxuXHR2YXIgdiA9IFYuY3JlYXRlKCk7XHJcblx0aWYgKHggIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0Vi5zZXQodiwgeCwgeSwgeik7XHJcblx0fVxyXG5cdHJldHVybiB2O1xyXG59XHJcblxyXG52YXIgY3JlYXRlUG9zaXRpb25zRm9yTWVzaGdyaWQgPSBmdW5jdGlvbihtZXNoZ3JpZCkge1xyXG5cdHZhciB4cyA9IG1lc2hncmlkWzBdLCB5cyA9IG1lc2hncmlkWzFdLCB6cyA9IG1lc2hncmlkWzJdO1xyXG5cdHZhciBwb3NpdGlvbnMgPSBbXTtcclxuXHRmb3IgKHZhciB6PTA7IHo8enMubGVuZ3RoOyB6KyspIHtcclxuXHRcdGZvciAodmFyIHk9MDsgeTx5cy5sZW5ndGg7IHkrKykge1xyXG5cdFx0XHRmb3IgKHZhciB4PTA7IHg8eHMubGVuZ3RoOyB4KyspIHtcclxuXHRcdFx0XHRwb3NpdGlvbnMucHVzaChbenNbel0sIHlzW3ldLCB4c1t4XV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cdHJldHVybiBwb3NpdGlvbnM7XHJcbn07XHJcblxyXG52YXIgZmluZExhc3RTbWFsbGVySW5kZXggPSBmdW5jdGlvbihwb2ludHMsIHYpIHtcclxuXHRmb3IgKHZhciBpPTA7IGk8cG9pbnRzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRpZiAocG9pbnRzW2ldID49IHYpIHtcclxuXHRcdFx0cmV0dXJuIGktMTtcclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIGk7XHJcbn07XHJcblxyXG52YXIgdG1wID0gVi5jcmVhdGUoKTtcclxudmFyIHRtcDIgPSBWLmNyZWF0ZSgpO1xyXG5cclxudmFyIGNsYW1wID0gZnVuY3Rpb24odiwgbWluLCBtYXgpIHtcclxuXHRyZXR1cm4gdiA8IG1pbiA/IG1pbiA6ICh2ID4gbWF4ID8gbWF4IDogdik7XHJcbn07XHJcblxyXG52YXIgc2FtcGxlTWVzaGdyaWQgPSBmdW5jdGlvbihwb2ludCwgYXJyYXksIG1lc2hncmlkLCBjbGFtcE92ZXJmbG93KSB7XHJcblx0dmFyIHggPSBwb2ludFswXTtcclxuXHR2YXIgeSA9IHBvaW50WzFdO1xyXG5cdHZhciB6ID0gcG9pbnRbMl07XHJcblxyXG5cdHZhciB3ID0gbWVzaGdyaWRbMF0ubGVuZ3RoO1xyXG5cdHZhciBoID0gbWVzaGdyaWRbMV0ubGVuZ3RoO1xyXG5cdHZhciBkID0gbWVzaGdyaWRbMl0ubGVuZ3RoO1xyXG5cclxuXHQvLyBGaW5kIHRoZSBpbmRleCBvZiB0aGUgbmVhcmVzdCBzbWFsbGVyIHZhbHVlIGluIHRoZSBtZXNoZ3JpZCBmb3IgZWFjaCBjb29yZGluYXRlIG9mICh4LHkseikuXHJcblx0Ly8gVGhlIG5lYXJlc3Qgc21hbGxlciB2YWx1ZSBpbmRleCBmb3IgeCBpcyB0aGUgaW5kZXggeDAgc3VjaCB0aGF0XHJcblx0Ly8gbWVzaGdyaWRbMF1beDBdIDwgeCBhbmQgZm9yIGFsbCB4MSA+IHgwLCBtZXNoZ3JpZFswXVt4MV0gPj0geC5cclxuXHR2YXIgeDAgPSBmaW5kTGFzdFNtYWxsZXJJbmRleChtZXNoZ3JpZFswXSwgeCk7XHJcblx0dmFyIHkwID0gZmluZExhc3RTbWFsbGVySW5kZXgobWVzaGdyaWRbMV0sIHkpO1xyXG5cdHZhciB6MCA9IGZpbmRMYXN0U21hbGxlckluZGV4KG1lc2hncmlkWzJdLCB6KTtcclxuXHJcblx0Ly8gR2V0IHRoZSBuZWFyZXN0IGxhcmdlciBtZXNoZ3JpZCB2YWx1ZSBpbmRpY2VzLlxyXG5cdC8vIEZyb20gdGhlIGFib3ZlIFwibmVhcmVzdCBzbWFsbGVyIHZhbHVlXCIsIHdlIGtub3cgdGhhdFxyXG5cdC8vICAgbWVzaGdyaWRbMF1beDBdIDwgeFxyXG5cdC8vICAgbWVzaGdyaWRbMF1beDArMV0gPj0geFxyXG5cdHZhciB4MSA9IHgwICsgMTtcclxuXHR2YXIgeTEgPSB5MCArIDE7XHJcblx0dmFyIHoxID0gejAgKyAxO1xyXG5cclxuXHRpZiAoY2xhbXBPdmVyZmxvdykge1xyXG5cdFx0eDAgPSBjbGFtcCh4MCwgMCwgdy0xKTtcclxuXHRcdHgxID0gY2xhbXAoeDEsIDAsIHctMSk7XHJcblx0XHR5MCA9IGNsYW1wKHkwLCAwLCBoLTEpO1xyXG5cdFx0eTEgPSBjbGFtcCh5MSwgMCwgaC0xKTtcclxuXHRcdHowID0gY2xhbXAoejAsIDAsIGQtMSk7XHJcblx0XHR6MSA9IGNsYW1wKHoxLCAwLCBkLTEpO1xyXG5cdH1cclxuXHJcblx0Ly8gUmVqZWN0IHBvaW50cyBvdXRzaWRlIHRoZSBtZXNoZ3JpZCwgcmV0dXJuIGEgemVybyB2ZWN0b3IuXHJcblx0aWYgKHgwIDwgMCB8fCB5MCA8IDAgfHwgejAgPCAwIHx8IHgxID49IHcgfHwgeTEgPj0gaCB8fCB6MSA+PSBkKSB7XHJcblx0XHRyZXR1cm4gVi5jcmVhdGUoKTtcclxuXHR9XHJcblxyXG5cdC8vIE5vcm1hbGl6ZSBwb2ludCBjb29yZGluYXRlcyB0byAwLi4xIHNjYWxpbmcgZmFjdG9yIGJldHdlZW4geDAgYW5kIHgxLlxyXG5cdHZhciB4ZiA9ICh4IC0gbWVzaGdyaWRbMF1beDBdKSAvIChtZXNoZ3JpZFswXVt4MV0gLSBtZXNoZ3JpZFswXVt4MF0pO1xyXG5cdHZhciB5ZiA9ICh5IC0gbWVzaGdyaWRbMV1beTBdKSAvIChtZXNoZ3JpZFsxXVt5MV0gLSBtZXNoZ3JpZFsxXVt5MF0pO1xyXG5cdHZhciB6ZiA9ICh6IC0gbWVzaGdyaWRbMl1bejBdKSAvIChtZXNoZ3JpZFsyXVt6MV0gLSBtZXNoZ3JpZFsyXVt6MF0pO1xyXG5cclxuXHRpZiAoeGYgPCAwIHx8IHhmID4gMSB8fCBpc05hTih4ZikpIHhmID0gMDtcclxuXHRpZiAoeWYgPCAwIHx8IHlmID4gMSB8fCBpc05hTih5ZikpIHlmID0gMDtcclxuXHRpZiAoemYgPCAwIHx8IHpmID4gMSB8fCBpc05hTih6ZikpIHpmID0gMDtcclxuXHJcblx0dmFyIHowb2ZmID0gejAqdypoO1xyXG5cdHZhciB6MW9mZiA9IHoxKncqaDtcclxuXHJcblx0dmFyIHkwb2ZmID0geTAqdztcclxuXHR2YXIgeTFvZmYgPSB5MSp3O1xyXG5cclxuXHR2YXIgeDBvZmYgPSB4MDtcclxuXHR2YXIgeDFvZmYgPSB4MTtcclxuXHJcblx0Ly8gU2FtcGxlIGRhdGEgYXJyYXkgYXJvdW5kIHRoZSAoeCx5LHopIHBvaW50LlxyXG5cdC8vICB2WllYID0gYXJyYXlbelpvZmYgKyB5WW9mZiArIHhYb2ZmXVxyXG5cdHZhciB2MDAwID0gYXJyYXlbeTBvZmYgKyB6MG9mZiArIHgwb2ZmXTtcclxuXHR2YXIgdjAwMSA9IGFycmF5W3kwb2ZmICsgejBvZmYgKyB4MW9mZl07XHJcblx0dmFyIHYwMTAgPSBhcnJheVt5MW9mZiArIHowb2ZmICsgeDBvZmZdO1xyXG5cdHZhciB2MDExID0gYXJyYXlbeTFvZmYgKyB6MG9mZiArIHgxb2ZmXTtcclxuXHR2YXIgdjEwMCA9IGFycmF5W3kwb2ZmICsgejFvZmYgKyB4MG9mZl07XHJcblx0dmFyIHYxMDEgPSBhcnJheVt5MG9mZiArIHoxb2ZmICsgeDFvZmZdO1xyXG5cdHZhciB2MTEwID0gYXJyYXlbeTFvZmYgKyB6MW9mZiArIHgwb2ZmXTtcclxuXHR2YXIgdjExMSA9IGFycmF5W3kxb2ZmICsgejFvZmYgKyB4MW9mZl07XHJcblxyXG5cdHZhciByZXN1bHQgPSBWLmNyZWF0ZSgpO1xyXG5cclxuXHQvLyBBdmVyYWdlIHNhbXBsZXMgYWNjb3JkaW5nIHRvIGRpc3RhbmNlIHRvIHBvaW50LlxyXG5cdFYubGVycChyZXN1bHQsIHYwMDAsIHYwMDEsIHhmKTtcclxuXHRWLmxlcnAodG1wLCB2MDEwLCB2MDExLCB4Zik7XHJcblx0Vi5sZXJwKHJlc3VsdCwgcmVzdWx0LCB0bXAsIHlmKTtcclxuXHRWLmxlcnAodG1wLCB2MTAwLCB2MTAxLCB4Zik7XHJcblx0Vi5sZXJwKHRtcDIsIHYxMTAsIHYxMTEsIHhmKTtcclxuXHRWLmxlcnAodG1wLCB0bXAsIHRtcDIsIHlmKTtcclxuXHRWLmxlcnAocmVzdWx0LCByZXN1bHQsIHRtcCwgemYpO1xyXG5cclxuXHRyZXR1cm4gcmVzdWx0O1xyXG59O1xyXG5cclxudmFyIGdldE9ydGhvZ29uYWxWZWN0b3IgPSBmdW5jdGlvbihkc3QsIHYpIHtcclxuXHQvLyBSZXR1cm4gdXAtdmVjdG9yIGZvciBvbmx5LXogdmVjdG9yLlxyXG5cdGlmICh2WzBdID09PSAwICYmIHZbMV0gPT09IDApIHtcclxuXHRcdFYuc2V0KGRzdCwgMCwgMSwgMCk7XHJcblx0fSBlbHNlIHtcclxuXHRcdC8vIFJldHVybiBheCArIGJ5ICsgY3ogPSAwLCBhIHBvaW50IHRoYXQgbGllcyBvbiB0aGUgcGxhbmUgdGhhdCBoYXMgdiBhcyBhIG5vcm1hbCBhbmQgdGhhdCBpc24ndCAoMCwwLDApLlxyXG5cdFx0Ly8gRnJvbSB0aGUgYWJvdmUgaWYtc3RhdGVtZW50IHdlIGhhdmUgfHxhfHwgPiAwICBVICB8fGJ8fCA+IDAuXHJcblx0XHQvLyBBc3NpZ24geiA9IDAsIHggPSAtYiwgeSA9IGE6XHJcblx0XHQvLyBhKi1iICsgYiphICsgYyowID0gLWJhICsgYmEgKyAwID0gMFxyXG5cdFx0Vi5zZXQoZHN0LCAtdlsxXSwgdlswXSwgMCk7XHJcblx0fVxyXG5cdHJldHVybiBkc3Q7XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHZlY3RvcmZpZWxkLCBib3VuZHMpIHtcclxuXHR2YXIgcG9zaXRpb25zO1xyXG5cdGlmICh2ZWN0b3JmaWVsZC5wb3NpdGlvbnMpIHtcclxuXHRcdHBvc2l0aW9ucyA9IHZlY3RvcmZpZWxkLnBvc2l0aW9ucztcclxuXHR9IGVsc2Uge1xyXG5cdFx0cG9zaXRpb25zID0gY3JlYXRlUG9zaXRpb25zRm9yTWVzaGdyaWQodmVjdG9yZmllbGQubWVzaGdyaWQpO1xyXG5cdH1cclxuXHR2YXIgbWVzaGdyaWQgPSB2ZWN0b3JmaWVsZC5tZXNoZ3JpZDtcclxuXHR2YXIgdmVjdG9ycyA9IHZlY3RvcmZpZWxkLnZlY3RvcnM7XHJcblx0dmFyIGdlbyA9IHtcclxuXHRcdHBvc2l0aW9uczogW10sXHJcblx0XHR2ZXJ0ZXhJbnRlbnNpdHk6IFtdLFxyXG5cdFx0dmVydGV4SW50ZW5zaXR5Qm91bmRzOiB2ZWN0b3JmaWVsZC52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHMsXHJcblx0XHR2ZXJ0ZXhOb3JtYWxzOiBbXSxcclxuXHRcdHZlY3RvcnM6IFtdLFxyXG5cdFx0Y2VsbHM6IFtdLFxyXG5cdFx0Y29uZU9mZnNldDogdmVjdG9yZmllbGQuY29uZU9mZnNldCxcclxuXHRcdGNvbG9ybWFwOiB2ZWN0b3JmaWVsZC5jb2xvcm1hcFxyXG5cdH07XHJcblxyXG5cdGlmICh2ZWN0b3JmaWVsZC5wb3NpdGlvbnMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRpZiAoYm91bmRzKSB7XHJcblx0XHRcdGJvdW5kc1swXSA9IFswLDAsMF07XHJcblx0XHRcdGJvdW5kc1sxXSA9IFswLDAsMF07XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZ2VvO1xyXG5cdH1cclxuXHJcblx0Ly8gQ29tcHV0ZSBib3VuZGluZyBib3ggZm9yIHRoZSBkYXRhc2V0LlxyXG5cdC8vIENvbXB1dGUgbWF4aW11bSB2ZWxvY2l0eSBmb3IgdGhlIGRhdGFzZXQgdG8gdXNlIGZvciBzY2FsaW5nIHRoZSBjb25lcy5cclxuXHR2YXIgbWF4Tm9ybSA9IDA7XHJcblx0dmFyIG1pblggPSAxLzAsIG1heFggPSAtMS8wO1xyXG5cdHZhciBtaW5ZID0gMS8wLCBtYXhZID0gLTEvMDtcclxuXHR2YXIgbWluWiA9IDEvMCwgbWF4WiA9IC0xLzA7XHJcblx0dmFyIHAyID0gbnVsbDtcclxuXHR2YXIgdTIgPSBudWxsO1xyXG5cdHZhciBwb3NpdGlvblZlY3RvcnMgPSBbXTtcclxuXHR2YXIgdmVjdG9yU2NhbGUgPSAxLzA7XHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciBwID0gcG9zaXRpb25zW2ldO1xyXG5cdFx0bWluWCA9IE1hdGgubWluKHBbMF0sIG1pblgpO1xyXG5cdFx0bWF4WCA9IE1hdGgubWF4KHBbMF0sIG1heFgpO1xyXG5cdFx0bWluWSA9IE1hdGgubWluKHBbMV0sIG1pblkpO1xyXG5cdFx0bWF4WSA9IE1hdGgubWF4KHBbMV0sIG1heFkpO1xyXG5cdFx0bWluWiA9IE1hdGgubWluKHBbMl0sIG1pblopO1xyXG5cdFx0bWF4WiA9IE1hdGgubWF4KHBbMl0sIG1heFopO1xyXG5cdFx0dmFyIHU7XHJcblx0XHRpZiAobWVzaGdyaWQpIHtcclxuXHRcdFx0dSA9IHNhbXBsZU1lc2hncmlkKHAsIHZlY3RvcnMsIG1lc2hncmlkLCB0cnVlKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHUgPSB2ZWN0b3JzW2ldO1xyXG5cdFx0fVxyXG5cdFx0aWYgKFYubGVuZ3RoKHUpID4gbWF4Tm9ybSkge1xyXG5cdFx0XHRtYXhOb3JtID0gVi5sZW5ndGgodSk7XHJcblx0XHR9XHJcblx0XHRpZiAoaSkge1xyXG5cdFx0XHQvLyBGaW5kIHZlY3RvciBzY2FsZSBbdy8gdW5pdHMgb2YgdGltZV0gdXNpbmcgXCJzdWNjZXNzaXZlXCIgcG9zaXRpb25zXHJcblx0XHRcdC8vIChub3QgXCJhZGphY2VudFwiIHdpdGggd291bGQgYmUgTyhuXjIpKSxcclxuXHRcdFx0Ly9cclxuXHRcdFx0Ly8gVGhlIHZlY3RvciBzY2FsZSBjb3JyZXNwb25kcyB0byB0aGUgbWluaW11bSBcInRpbWVcIiB0byB0cmF2ZWwgYWNyb3NzIHR3b1xyXG5cdFx0XHQvLyB0d28gYWRqYWNlbnQgcG9zaXRpb25zIGF0IHRoZSBhdmVyYWdlIHZlbG9jaXR5IG9mIHRob3NlIHR3byBhZGphY2VudCBwb3NpdGlvbnNcclxuXHRcdFx0dmVjdG9yU2NhbGUgPSBNYXRoLm1pbih2ZWN0b3JTY2FsZSxcclxuXHRcdFx0XHQyICogVi5kaXN0YW5jZShwMiwgcCkgLyAoVi5sZW5ndGgodTIpICsgVi5sZW5ndGgodSkpXHJcblx0XHRcdCk7XHJcblx0XHR9XHJcblx0XHRwMiA9IHA7XHJcblx0XHR1MiA9IHU7XHJcblx0XHRwb3NpdGlvblZlY3RvcnMucHVzaCh1KTtcclxuXHR9XHJcblx0dmFyIG1pblYgPSBbbWluWCwgbWluWSwgbWluWl07XHJcblx0dmFyIG1heFYgPSBbbWF4WCwgbWF4WSwgbWF4Wl07XHJcblx0aWYgKGJvdW5kcykge1xyXG5cdFx0Ym91bmRzWzBdID0gbWluVjtcclxuXHRcdGJvdW5kc1sxXSA9IG1heFY7XHJcblx0fVxyXG5cdGlmIChtYXhOb3JtID09PSAwKSB7XHJcblx0XHRtYXhOb3JtID0gMTtcclxuXHR9XHJcblxyXG5cdC8vIEludmVydGVkIG1heCBub3JtIHdvdWxkIG1hcCB2ZWN0b3Igd2l0aCBub3JtIG1heE5vcm0gdG8gMSBjb29yZCBzcGFjZSB1bml0cyBpbiBsZW5ndGhcclxuXHR2YXIgaW52ZXJ0ZWRNYXhOb3JtID0gMSAvIG1heE5vcm07XHJcblxyXG5cdGlmICghaXNGaW5pdGUodmVjdG9yU2NhbGUpIHx8IGlzTmFOKHZlY3RvclNjYWxlKSkge1xyXG5cdFx0dmVjdG9yU2NhbGUgPSAxLjA7XHJcblx0fVxyXG5cdGdlby52ZWN0b3JTY2FsZSA9IHZlY3RvclNjYWxlO1xyXG5cclxuXHR2YXIgbm1sID0gdmVjMygwLDEsMCk7XHJcblxyXG5cdHZhciBjb25lU2NhbGUgPSB2ZWN0b3JmaWVsZC5jb25lU2l6ZSB8fCAwLjU7XHJcblxyXG5cdGlmICh2ZWN0b3JmaWVsZC5hYnNvbHV0ZUNvbmVTaXplKSB7XHJcblx0XHRjb25lU2NhbGUgPSB2ZWN0b3JmaWVsZC5hYnNvbHV0ZUNvbmVTaXplICogaW52ZXJ0ZWRNYXhOb3JtO1xyXG5cdH1cclxuXHJcblx0Z2VvLmNvbmVTY2FsZSA9IGNvbmVTY2FsZTtcclxuXHJcblx0Ly8gQnVpbGQgdGhlIGNvbmUgbW9kZWwuXHJcblx0Zm9yICh2YXIgaSA9IDAsIGogPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7XHJcblx0XHR2YXIgcCA9IHBvc2l0aW9uc1tpXTtcclxuXHRcdHZhciB4ID0gcFswXSwgeSA9IHBbMV0sIHogPSBwWzJdO1xyXG5cdFx0dmFyIGQgPSBwb3NpdGlvblZlY3RvcnNbaV07XHJcblx0XHR2YXIgaW50ZW5zaXR5ID0gVi5sZW5ndGgoZCkgKiBpbnZlcnRlZE1heE5vcm07XHJcblx0XHRmb3IgKHZhciBrID0gMCwgbCA9IDg7IGsgPCBsOyBrKyspIHtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcclxuXHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XHJcblxyXG5cdFx0XHRnZW8udmVydGV4SW50ZW5zaXR5LnB1c2goaW50ZW5zaXR5LCBpbnRlbnNpdHksIGludGVuc2l0eSk7XHJcblx0XHRcdGdlby52ZXJ0ZXhJbnRlbnNpdHkucHVzaChpbnRlbnNpdHksIGludGVuc2l0eSwgaW50ZW5zaXR5KTtcclxuXHJcblx0XHRcdGdlby52ZXJ0ZXhOb3JtYWxzLnB1c2gobm1sLCBubWwsIG5tbCk7XHJcblx0XHRcdGdlby52ZXJ0ZXhOb3JtYWxzLnB1c2gobm1sLCBubWwsIG5tbCk7XHJcblxyXG5cdFx0XHR2YXIgbSA9IGdlby5wb3NpdGlvbnMubGVuZ3RoO1xyXG5cdFx0XHRnZW8uY2VsbHMucHVzaChbbS02LCBtLTUsIG0tNF0sIFttLTMsIG0tMiwgbS0xXSk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gZ2VvO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuY3JlYXRlQ29uZU1lc2ggPSByZXF1aXJlKCcuL2xpYi9jb25lbWVzaCcpO1xyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBiYXJ5Y2VudHJpYyAgICAgICAgICAgID0gcmVxdWlyZSgnYmFyeWNlbnRyaWMnKVxyXG52YXIgY2xvc2VzdFBvaW50VG9UcmlhbmdsZSA9IHJlcXVpcmUoJ3BvbHl0b3BlLWNsb3Nlc3QtcG9pbnQvbGliL2Nsb3Nlc3RfcG9pbnRfMmQuanMnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjbG9zZXN0UG9pbnRUb1BpY2tMb2NhdGlvblxyXG5cclxuZnVuY3Rpb24geGZvcm1NYXRyaXgobSwgdikge1xyXG4gIHZhciBvdXQgPSBbMCwwLDAsMF1cclxuICBmb3IodmFyIGk9MDsgaTw0OyArK2kpIHtcclxuICAgIGZvcih2YXIgaj0wOyBqPDQ7ICsraikge1xyXG4gICAgICBvdXRbal0gKz0gbVs0KmkgKyBqXSAqIHZbaV1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIG91dFxyXG59XHJcblxyXG5mdW5jdGlvbiBwcm9qZWN0VmVydGV4KHYsIG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCByZXNvbHV0aW9uKSB7XHJcbiAgdmFyIHAgPSB4Zm9ybU1hdHJpeChwcm9qZWN0aW9uLFxyXG4gICAgICAgICAgICB4Zm9ybU1hdHJpeCh2aWV3LFxyXG4gICAgICAgICAgICAgIHhmb3JtTWF0cml4KG1vZGVsLCBbdlswXSwgdlsxXSwgdlsyXSwgMV0pKSlcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHBbaV0gLz0gcFszXVxyXG4gIH1cclxuICByZXR1cm4gWyAwLjUgKiByZXNvbHV0aW9uWzBdICogKDEuMCtwWzBdKSwgMC41ICogcmVzb2x1dGlvblsxXSAqICgxLjAtcFsxXSkgXVxyXG59XHJcblxyXG5mdW5jdGlvbiBiYXJ5Y2VudHJpY0Nvb3JkKHNpbXBsZXgsIHBvaW50KSB7XHJcbiAgaWYoc2ltcGxleC5sZW5ndGggPT09IDIpIHtcclxuICAgIHZhciBkMCA9IDAuMFxyXG4gICAgdmFyIGQxID0gMC4wXHJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgICAgZDAgKz0gTWF0aC5wb3cocG9pbnRbaV0gLSBzaW1wbGV4WzBdW2ldLCAyKVxyXG4gICAgICBkMSArPSBNYXRoLnBvdyhwb2ludFtpXSAtIHNpbXBsZXhbMV1baV0sIDIpXHJcbiAgICB9XHJcbiAgICBkMCA9IE1hdGguc3FydChkMClcclxuICAgIGQxID0gTWF0aC5zcXJ0KGQxKVxyXG4gICAgaWYoZDArZDEgPCAxZS02KSB7XHJcbiAgICAgIHJldHVybiBbMSwwXVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIFtkMS8oZDArZDEpLGQwLyhkMStkMCldXHJcbiAgfSBlbHNlIGlmKHNpbXBsZXgubGVuZ3RoID09PSAzKSB7XHJcbiAgICB2YXIgY2xvc2VzdFBvaW50ID0gWzAsMF1cclxuICAgIGNsb3Nlc3RQb2ludFRvVHJpYW5nbGUoc2ltcGxleFswXSwgc2ltcGxleFsxXSwgc2ltcGxleFsyXSwgcG9pbnQsIGNsb3Nlc3RQb2ludClcclxuICAgIHJldHVybiBiYXJ5Y2VudHJpYyhzaW1wbGV4LCBjbG9zZXN0UG9pbnQpXHJcbiAgfVxyXG4gIHJldHVybiBbXVxyXG59XHJcblxyXG5mdW5jdGlvbiBpbnRlcnBvbGF0ZShzaW1wbGV4LCB3ZWlnaHRzKSB7XHJcbiAgdmFyIHJlc3VsdCA9IFswLDAsMF1cclxuICBmb3IodmFyIGk9MDsgaTxzaW1wbGV4Lmxlbmd0aDsgKytpKSB7XHJcbiAgICB2YXIgcCA9IHNpbXBsZXhbaV1cclxuICAgIHZhciB3ID0gd2VpZ2h0c1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHJlc3VsdFtqXSArPSB3ICogcFtqXVxyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gcmVzdWx0XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNsb3Nlc3RQb2ludFRvUGlja0xvY2F0aW9uKHNpbXBsZXgsIHBpeGVsQ29vcmQsIG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCByZXNvbHV0aW9uKSB7XHJcbiAgaWYoc2ltcGxleC5sZW5ndGggPT09IDEpIHtcclxuICAgIHJldHVybiBbMCwgc2ltcGxleFswXS5zbGljZSgpXVxyXG4gIH1cclxuICB2YXIgc2ltcGxleDJEID0gbmV3IEFycmF5KHNpbXBsZXgubGVuZ3RoKVxyXG4gIGZvcih2YXIgaT0wOyBpPHNpbXBsZXgubGVuZ3RoOyArK2kpIHtcclxuICAgIHNpbXBsZXgyRFtpXSA9IHByb2plY3RWZXJ0ZXgoc2ltcGxleFtpXSwgbW9kZWwsIHZpZXcsIHByb2plY3Rpb24sIHJlc29sdXRpb24pO1xyXG4gIH1cclxuXHJcbiAgdmFyIGNsb3Nlc3RJbmRleCA9IDBcclxuICB2YXIgY2xvc2VzdERpc3QgID0gSW5maW5pdHlcclxuICBmb3IodmFyIGk9MDsgaTxzaW1wbGV4MkQubGVuZ3RoOyArK2kpIHtcclxuICAgIHZhciBkMiA9IDAuMFxyXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XHJcbiAgICAgIGQyICs9IE1hdGgucG93KHNpbXBsZXgyRFtpXVtqXSAtIHBpeGVsQ29vcmRbal0sIDIpXHJcbiAgICB9XHJcbiAgICBpZihkMiA8IGNsb3Nlc3REaXN0KSB7XHJcbiAgICAgIGNsb3Nlc3REaXN0ICA9IGQyXHJcbiAgICAgIGNsb3Nlc3RJbmRleCA9IGlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHZhciB3ZWlnaHRzID0gYmFyeWNlbnRyaWNDb29yZChzaW1wbGV4MkQsIHBpeGVsQ29vcmQpXHJcbiAgdmFyIHMgPSAwLjBcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIGlmKHdlaWdodHNbaV0gPCAtMC4wMDEgfHxcclxuICAgICAgIHdlaWdodHNbaV0gPiAxLjAwMDEpIHtcclxuICAgICAgcmV0dXJuIG51bGxcclxuICAgIH1cclxuICAgIHMgKz0gd2VpZ2h0c1tpXVxyXG4gIH1cclxuICBpZihNYXRoLmFicyhzIC0gMS4wKSA+IDAuMDAxKSB7XHJcbiAgICByZXR1cm4gbnVsbFxyXG4gIH1cclxuICByZXR1cm4gW2Nsb3Nlc3RJbmRleCwgaW50ZXJwb2xhdGUoc2ltcGxleCwgd2VpZ2h0cyksIHdlaWdodHNdXHJcbn0iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gPSAxZS02OyAvLyBtYXkgYmUgdG9vIGxhcmdlIGlmIHRyaWFuZ2xlcyBhcmUgdmVyeSBzbWFsbFxyXG52YXIgREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA9IDFlLTY7XHJcblxyXG52YXIgY3JlYXRlU2hhZGVyICA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcbnZhciBjcmVhdGVCdWZmZXIgID0gcmVxdWlyZSgnZ2wtYnVmZmVyJylcclxudmFyIGNyZWF0ZVZBTyAgICAgPSByZXF1aXJlKCdnbC12YW8nKVxyXG52YXIgY3JlYXRlVGV4dHVyZSA9IHJlcXVpcmUoJ2dsLXRleHR1cmUyZCcpXHJcbnZhciBub3JtYWxzICAgICAgID0gcmVxdWlyZSgnbm9ybWFscycpXHJcbnZhciBtdWx0aXBseSAgICAgID0gcmVxdWlyZSgnZ2wtbWF0NC9tdWx0aXBseScpXHJcbnZhciBpbnZlcnQgICAgICAgID0gcmVxdWlyZSgnZ2wtbWF0NC9pbnZlcnQnKVxyXG52YXIgbmRhcnJheSAgICAgICA9IHJlcXVpcmUoJ25kYXJyYXknKVxyXG52YXIgY29sb3JtYXAgICAgICA9IHJlcXVpcmUoJ2NvbG9ybWFwJylcclxudmFyIGdldENvbnRvdXIgICAgPSByZXF1aXJlKCdzaW1wbGljaWFsLWNvbXBsZXgtY29udG91cicpXHJcbnZhciBwb29sICAgICAgICAgID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcclxudmFyIHNoYWRlcnMgICAgICAgPSByZXF1aXJlKCcuL3NoYWRlcnMnKVxyXG52YXIgY2xvc2VzdFBvaW50ICA9IHJlcXVpcmUoJy4vY2xvc2VzdC1wb2ludCcpXHJcblxyXG52YXIgbWVzaFNoYWRlciAgICA9IHNoYWRlcnMubWVzaFNoYWRlclxyXG52YXIgcGlja1NoYWRlciAgICA9IHNoYWRlcnMucGlja1NoYWRlclxyXG5cclxudmFyIGlkZW50aXR5TWF0cml4ID0gW1xyXG4gIDEsMCwwLDAsXHJcbiAgMCwxLDAsMCxcclxuICAwLDAsMSwwLFxyXG4gIDAsMCwwLDFdXHJcblxyXG5mdW5jdGlvbiBTaW1wbGljaWFsTWVzaChnbFxyXG4gICwgdGV4dHVyZVxyXG4gICwgdHJpU2hhZGVyXHJcbiAgLCBsaW5lU2hhZGVyXHJcbiAgLCBwb2ludFNoYWRlclxyXG4gICwgcGlja1NoYWRlclxyXG4gICwgcG9pbnRQaWNrU2hhZGVyXHJcbiAgLCBjb250b3VyU2hhZGVyXHJcbiAgLCB0cmlhbmdsZVBvc2l0aW9uc1xyXG4gICwgdHJpYW5nbGVWZWN0b3JzXHJcbiAgLCB0cmlhbmdsZUlkc1xyXG4gICwgdHJpYW5nbGVDb2xvcnNcclxuICAsIHRyaWFuZ2xlVVZzXHJcbiAgLCB0cmlhbmdsZU5vcm1hbHNcclxuICAsIHRyaWFuZ2xlVkFPXHJcbiAgLCBlZGdlUG9zaXRpb25zXHJcbiAgLCBlZGdlSWRzXHJcbiAgLCBlZGdlQ29sb3JzXHJcbiAgLCBlZGdlVVZzXHJcbiAgLCBlZGdlVkFPXHJcbiAgLCBwb2ludFBvc2l0aW9uc1xyXG4gICwgcG9pbnRJZHNcclxuICAsIHBvaW50Q29sb3JzXHJcbiAgLCBwb2ludFVWc1xyXG4gICwgcG9pbnRTaXplc1xyXG4gICwgcG9pbnRWQU9cclxuICAsIGNvbnRvdXJQb3NpdGlvbnNcclxuICAsIGNvbnRvdXJWQU8pIHtcclxuXHJcbiAgdGhpcy5nbCAgICAgICAgICAgICAgICA9IGdsXHJcbiAgdGhpcy5jZWxscyAgICAgICAgICAgICA9IFtdXHJcbiAgdGhpcy5wb3NpdGlvbnMgICAgICAgICA9IFtdXHJcbiAgdGhpcy5pbnRlbnNpdHkgICAgICAgICA9IFtdXHJcbiAgdGhpcy50ZXh0dXJlICAgICAgICAgICA9IHRleHR1cmVcclxuICB0aGlzLmRpcnR5ICAgICAgICAgICAgID0gdHJ1ZVxyXG5cclxuICB0aGlzLnRyaVNoYWRlciAgICAgICAgID0gdHJpU2hhZGVyXHJcbiAgdGhpcy5saW5lU2hhZGVyICAgICAgICA9IGxpbmVTaGFkZXJcclxuICB0aGlzLnBvaW50U2hhZGVyICAgICAgID0gcG9pbnRTaGFkZXJcclxuICB0aGlzLnBpY2tTaGFkZXIgICAgICAgID0gcGlja1NoYWRlclxyXG4gIHRoaXMucG9pbnRQaWNrU2hhZGVyICAgPSBwb2ludFBpY2tTaGFkZXJcclxuICB0aGlzLmNvbnRvdXJTaGFkZXIgICAgID0gY29udG91clNoYWRlclxyXG5cclxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zID0gdHJpYW5nbGVQb3NpdGlvbnNcclxuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycyAgID0gdHJpYW5nbGVWZWN0b3JzXHJcbiAgdGhpcy50cmlhbmdsZUNvbG9ycyAgICA9IHRyaWFuZ2xlQ29sb3JzXHJcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMgICA9IHRyaWFuZ2xlTm9ybWFsc1xyXG4gIHRoaXMudHJpYW5nbGVVVnMgICAgICAgPSB0cmlhbmdsZVVWc1xyXG4gIHRoaXMudHJpYW5nbGVJZHMgICAgICAgPSB0cmlhbmdsZUlkc1xyXG4gIHRoaXMudHJpYW5nbGVWQU8gICAgICAgPSB0cmlhbmdsZVZBT1xyXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgICAgPSAwXHJcblxyXG4gIHRoaXMubGluZVdpZHRoICAgICAgICAgPSAxXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zICAgICA9IGVkZ2VQb3NpdGlvbnNcclxuICB0aGlzLmVkZ2VDb2xvcnMgICAgICAgID0gZWRnZUNvbG9yc1xyXG4gIHRoaXMuZWRnZVVWcyAgICAgICAgICAgPSBlZGdlVVZzXHJcbiAgdGhpcy5lZGdlSWRzICAgICAgICAgICA9IGVkZ2VJZHNcclxuICB0aGlzLmVkZ2VWQU8gICAgICAgICAgID0gZWRnZVZBT1xyXG4gIHRoaXMuZWRnZUNvdW50ICAgICAgICAgPSAwXHJcblxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMgICAgPSBwb2ludFBvc2l0aW9uc1xyXG4gIHRoaXMucG9pbnRDb2xvcnMgICAgICAgPSBwb2ludENvbG9yc1xyXG4gIHRoaXMucG9pbnRVVnMgICAgICAgICAgPSBwb2ludFVWc1xyXG4gIHRoaXMucG9pbnRTaXplcyAgICAgICAgPSBwb2ludFNpemVzXHJcbiAgdGhpcy5wb2ludElkcyAgICAgICAgICA9IHBvaW50SWRzXHJcbiAgdGhpcy5wb2ludFZBTyAgICAgICAgICA9IHBvaW50VkFPXHJcbiAgdGhpcy5wb2ludENvdW50ICAgICAgICA9IDBcclxuXHJcbiAgdGhpcy5jb250b3VyTGluZVdpZHRoICA9IDFcclxuICB0aGlzLmNvbnRvdXJQb3NpdGlvbnMgID0gY29udG91clBvc2l0aW9uc1xyXG4gIHRoaXMuY29udG91clZBTyAgICAgICAgPSBjb250b3VyVkFPXHJcbiAgdGhpcy5jb250b3VyQ291bnQgICAgICA9IDBcclxuICB0aGlzLmNvbnRvdXJDb2xvciAgICAgID0gWzAsMCwwXVxyXG4gIHRoaXMuY29udG91ckVuYWJsZSAgICAgPSB0cnVlXHJcblxyXG4gIHRoaXMucGlja0lkICAgICAgICAgICAgPSAxXHJcbiAgdGhpcy5ib3VuZHMgICAgICAgICAgICA9IFtcclxuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0sXHJcbiAgICBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldIF1cclxuICB0aGlzLmNsaXBCb3VuZHMgICAgICAgID0gW1xyXG4gICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSxcclxuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0gXVxyXG5cclxuICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBbMWU1LCAxZTUsIDBdXHJcbiAgdGhpcy5hbWJpZW50TGlnaHQgID0gMC44XHJcbiAgdGhpcy5kaWZmdXNlTGlnaHQgID0gMC44XHJcbiAgdGhpcy5zcGVjdWxhckxpZ2h0ID0gMi4wXHJcbiAgdGhpcy5yb3VnaG5lc3MgICAgID0gMC41XHJcbiAgdGhpcy5mcmVzbmVsICAgICAgID0gMS41XHJcblxyXG4gIHRoaXMub3BhY2l0eSAgICAgICA9IDEuMFxyXG5cclxuICB0aGlzLmNvbmVTY2FsZSAgICAgPSAyLjBcclxuICB0aGlzLnZlY3RvclNjYWxlICAgPSAxLjBcclxuICB0aGlzLmNvbmVPZmZzZXQgICAgPSAxLjAgLyA0LjA7XHJcblxyXG4gIHRoaXMuX21vZGVsICAgICAgID0gaWRlbnRpdHlNYXRyaXhcclxuICB0aGlzLl92aWV3ICAgICAgICA9IGlkZW50aXR5TWF0cml4XHJcbiAgdGhpcy5fcHJvamVjdGlvbiAgPSBpZGVudGl0eU1hdHJpeFxyXG4gIHRoaXMuX3Jlc29sdXRpb24gID0gWzEsMV1cclxufVxyXG5cclxudmFyIHByb3RvID0gU2ltcGxpY2lhbE1lc2gucHJvdG90eXBlXHJcblxyXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPj0gMVxyXG59XHJcblxyXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XHJcbiAgcmV0dXJuIHRoaXMub3BhY2l0eSA8IDFcclxufVxyXG5cclxucHJvdG8ucGlja1Nsb3RzID0gMVxyXG5cclxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbihpZCkge1xyXG4gIHRoaXMucGlja0lkID0gaWRcclxufVxyXG5cclxuZnVuY3Rpb24gZ2VuQ29sb3JtYXAocGFyYW0pIHtcclxuICB2YXIgY29sb3JzID0gY29sb3JtYXAoe1xyXG4gICAgICBjb2xvcm1hcDogcGFyYW1cclxuICAgICwgbnNoYWRlczogIDI1NlxyXG4gICAgLCBmb3JtYXQ6ICAncmdiYSdcclxuICB9KVxyXG5cclxuICB2YXIgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoMjU2KjQpXHJcbiAgZm9yKHZhciBpPTA7IGk8MjU2OyArK2kpIHtcclxuICAgIHZhciBjID0gY29sb3JzW2ldXHJcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgcmVzdWx0WzQqaStqXSA9IGNbal1cclxuICAgIH1cclxuICAgIHJlc3VsdFs0KmkrM10gPSBjWzNdKjI1NVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5kYXJyYXkocmVzdWx0LCBbMjU2LDI1Niw0XSwgWzQsMCwxXSlcclxufVxyXG5cclxuZnVuY3Rpb24gdW5wYWNrSW50ZW5zaXR5KGNlbGxzLCBudW1WZXJ0cywgY2VsbEludGVuc2l0eSkge1xyXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobnVtVmVydHMpXHJcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydHM7ICsraSkge1xyXG4gICAgcmVzdWx0W2ldID0gMFxyXG4gIH1cclxuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcclxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XHJcbiAgICB2YXIgYyA9IGNlbGxzW2ldXHJcbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XHJcbiAgICAgIHJlc3VsdFtjW2pdXSA9IGNlbGxJbnRlbnNpdHlbaV1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5mdW5jdGlvbiB0YWtlWkNvbXBvbmVudChhcnJheSkge1xyXG4gIHZhciBuID0gYXJyYXkubGVuZ3RoXHJcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKVxyXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xyXG4gICAgcmVzdWx0W2ldID0gYXJyYXlbaV1bMl1cclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5wcm90by5oaWdobGlnaHQgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcclxuICBpZighc2VsZWN0aW9uIHx8ICF0aGlzLmNvbnRvdXJFbmFibGUpIHtcclxuICAgIHRoaXMuY29udG91ckNvdW50ID0gMFxyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG4gIHZhciBsZXZlbCA9IGdldENvbnRvdXIodGhpcy5jZWxscywgdGhpcy5pbnRlbnNpdHksIHNlbGVjdGlvbi5pbnRlbnNpdHkpXHJcbiAgdmFyIGNlbGxzICAgICAgICAgPSBsZXZlbC5jZWxsc1xyXG4gIHZhciB2ZXJ0ZXhJZHMgICAgID0gbGV2ZWwudmVydGV4SWRzXHJcbiAgdmFyIHZlcnRleFdlaWdodHMgPSBsZXZlbC52ZXJ0ZXhXZWlnaHRzXHJcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXHJcbiAgdmFyIHJlc3VsdCA9IHBvb2wubWFsbG9jRmxvYXQzMigyICogMyAqIG51bUNlbGxzKVxyXG4gIHZhciBwdHIgPSAwXHJcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xyXG4gICAgdmFyIGMgPSBjZWxsc1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XHJcbiAgICAgIHZhciB2ID0gY1swXVxyXG4gICAgICBpZihjLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICAgIHYgPSBjW2pdXHJcbiAgICAgIH1cclxuICAgICAgdmFyIGEgPSB2ZXJ0ZXhJZHNbdl1bMF1cclxuICAgICAgdmFyIGIgPSB2ZXJ0ZXhJZHNbdl1bMV1cclxuICAgICAgdmFyIHcgPSB2ZXJ0ZXhXZWlnaHRzW3ZdXHJcbiAgICAgIHZhciB3aSA9IDEuMCAtIHdcclxuICAgICAgdmFyIHBhID0gdGhpcy5wb3NpdGlvbnNbYV1cclxuICAgICAgdmFyIHBiID0gdGhpcy5wb3NpdGlvbnNbYl1cclxuICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgcmVzdWx0W3B0cisrXSA9IHcgKiBwYVtrXSArIHdpICogcGJba11cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICB0aGlzLmNvbnRvdXJDb3VudCA9IChwdHIgLyAzKXwwXHJcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLnVwZGF0ZShyZXN1bHQuc3ViYXJyYXkoMCwgcHRyKSlcclxuICBwb29sLmZyZWUocmVzdWx0KVxyXG59XHJcblxyXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihwYXJhbXMpIHtcclxuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcblxyXG4gIHRoaXMuZGlydHkgPSB0cnVlXHJcblxyXG4gIGlmKCdjb250b3VyRW5hYmxlJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuY29udG91ckVuYWJsZSA9IHBhcmFtcy5jb250b3VyRW5hYmxlXHJcbiAgfVxyXG4gIGlmKCdjb250b3VyQ29sb3InIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5jb250b3VyQ29sb3IgPSBwYXJhbXMuY29udG91ckNvbG9yXHJcbiAgfVxyXG4gIGlmKCdsaW5lV2lkdGgnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5saW5lV2lkdGggPSBwYXJhbXMubGluZVdpZHRoXHJcbiAgfVxyXG4gIGlmKCdsaWdodFBvc2l0aW9uJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMubGlnaHRQb3NpdGlvbiA9IHBhcmFtcy5saWdodFBvc2l0aW9uXHJcbiAgfVxyXG4gIGlmKCdvcGFjaXR5JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMub3BhY2l0eSA9IHBhcmFtcy5vcGFjaXR5XHJcbiAgfVxyXG4gIGlmKCdhbWJpZW50JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuYW1iaWVudExpZ2h0ICA9IHBhcmFtcy5hbWJpZW50XHJcbiAgfVxyXG4gIGlmKCdkaWZmdXNlJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuZGlmZnVzZUxpZ2h0ID0gcGFyYW1zLmRpZmZ1c2VcclxuICB9XHJcbiAgaWYoJ3NwZWN1bGFyJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuc3BlY3VsYXJMaWdodCA9IHBhcmFtcy5zcGVjdWxhclxyXG4gIH1cclxuICBpZigncm91Z2huZXNzJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMucm91Z2huZXNzID0gcGFyYW1zLnJvdWdobmVzc1xyXG4gIH1cclxuICBpZignZnJlc25lbCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmZyZXNuZWwgPSBwYXJhbXMuZnJlc25lbFxyXG4gIH1cclxuXHJcbiAgaWYgKHBhcmFtcy52ZWN0b3JTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLnZlY3RvclNjYWxlID0gcGFyYW1zLnZlY3RvclNjYWxlO1xyXG4gIH1cclxuICBpZiAocGFyYW1zLmNvbmVTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLmNvbmVTY2FsZSA9IHBhcmFtcy5jb25lU2NhbGU7XHJcbiAgfVxyXG4gIGlmIChwYXJhbXMuY29uZU9mZnNldCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLmNvbmVPZmZzZXQgPSBwYXJhbXMuY29uZU9mZnNldDtcclxuICB9XHJcblxyXG4gIGlmKHBhcmFtcy50ZXh0dXJlKSB7XHJcbiAgICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXHJcbiAgICB0aGlzLnRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBwYXJhbXMudGV4dHVyZSlcclxuICB9IGVsc2UgaWYgKHBhcmFtcy5jb2xvcm1hcCkge1xyXG4gICAgdGhpcy50ZXh0dXJlLnNoYXBlID0gWzI1NiwyNTZdXHJcbiAgICB0aGlzLnRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcclxuICAgIHRoaXMudGV4dHVyZS5tYWdGaWx0ZXIgPSBnbC5MSU5FQVJcclxuICAgIHRoaXMudGV4dHVyZS5zZXRQaXhlbHMoZ2VuQ29sb3JtYXAocGFyYW1zLmNvbG9ybWFwKSlcclxuICAgIHRoaXMudGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXHJcbiAgfVxyXG5cclxuICB2YXIgY2VsbHMgPSBwYXJhbXMuY2VsbHNcclxuICB2YXIgcG9zaXRpb25zID0gcGFyYW1zLnBvc2l0aW9uc1xyXG4gIHZhciB2ZWN0b3JzID0gcGFyYW1zLnZlY3RvcnNcclxuXHJcbiAgaWYoIXBvc2l0aW9ucyB8fCAhY2VsbHMgfHwgIXZlY3RvcnMpIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgdmFyIHRQb3MgPSBbXVxyXG4gIHZhciB0VmVjID0gW11cclxuICB2YXIgdENvbCA9IFtdXHJcbiAgdmFyIHROb3IgPSBbXVxyXG4gIHZhciB0VVZzID0gW11cclxuICB2YXIgdElkcyA9IFtdXHJcblxyXG4gIHZhciBlUG9zID0gW11cclxuICB2YXIgZUNvbCA9IFtdXHJcbiAgdmFyIGVVVnMgPSBbXVxyXG4gIHZhciBlSWRzID0gW11cclxuXHJcbiAgdmFyIHBQb3MgPSBbXVxyXG4gIHZhciBwQ29sID0gW11cclxuICB2YXIgcFVWcyA9IFtdXHJcbiAgdmFyIHBTaXogPSBbXVxyXG4gIHZhciBwSWRzID0gW11cclxuXHJcbiAgLy9TYXZlIGdlb21ldHJ5IGRhdGEgZm9yIHBpY2tpbmcgY2FsY3VsYXRpb25zXHJcbiAgdGhpcy5jZWxscyAgICAgPSBjZWxsc1xyXG4gIHRoaXMucG9zaXRpb25zID0gcG9zaXRpb25zXHJcblxyXG4gIC8vQ29tcHV0ZSBub3JtYWxzXHJcbiAgdmFyIHZlcnRleE5vcm1hbHMgPSBwYXJhbXMudmVydGV4Tm9ybWFsc1xyXG4gIHZhciBjZWxsTm9ybWFscyAgID0gcGFyYW1zLmNlbGxOb3JtYWxzXHJcbiAgdmFyIHZlcnRleE5vcm1hbHNFcHNpbG9uID0gcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9WRVJURVhfTk9STUFMU19FUFNJTE9OIDogcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uXHJcbiAgdmFyIGZhY2VOb3JtYWxzRXBzaWxvbiA9IHBhcmFtcy5mYWNlTm9ybWFsc0Vwc2lsb24gPT09IHZvaWQoMCkgPyBERUZBVUxUX0ZBQ0VfTk9STUFMU19FUFNJTE9OIDogcGFyYW1zLmZhY2VOb3JtYWxzRXBzaWxvblxyXG4gIGlmKHBhcmFtcy51c2VGYWNldE5vcm1hbHMgJiYgIWNlbGxOb3JtYWxzKSB7XHJcbiAgICBjZWxsTm9ybWFscyA9IG5vcm1hbHMuZmFjZU5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgZmFjZU5vcm1hbHNFcHNpbG9uKVxyXG4gIH1cclxuICBpZighY2VsbE5vcm1hbHMgJiYgIXZlcnRleE5vcm1hbHMpIHtcclxuICAgIHZlcnRleE5vcm1hbHMgPSBub3JtYWxzLnZlcnRleE5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgdmVydGV4Tm9ybWFsc0Vwc2lsb24pXHJcbiAgfVxyXG5cclxuICAvL0NvbXB1dGUgY29sb3JzXHJcbiAgdmFyIHZlcnRleENvbG9ycyAgICA9IHBhcmFtcy52ZXJ0ZXhDb2xvcnNcclxuICB2YXIgY2VsbENvbG9ycyAgICAgID0gcGFyYW1zLmNlbGxDb2xvcnNcclxuICB2YXIgbWVzaENvbG9yICAgICAgID0gcGFyYW1zLm1lc2hDb2xvciB8fCBbMSwxLDEsMV1cclxuXHJcbiAgLy9VVnNcclxuICB2YXIgdmVydGV4VVZzICAgICAgID0gcGFyYW1zLnZlcnRleFVWc1xyXG4gIHZhciB2ZXJ0ZXhJbnRlbnNpdHkgPSBwYXJhbXMudmVydGV4SW50ZW5zaXR5XHJcbiAgdmFyIGNlbGxVVnMgICAgICAgICA9IHBhcmFtcy5jZWxsVVZzXHJcbiAgdmFyIGNlbGxJbnRlbnNpdHkgICA9IHBhcmFtcy5jZWxsSW50ZW5zaXR5XHJcblxyXG4gIHZhciBpbnRlbnNpdHlMbyAgICAgPSBJbmZpbml0eVxyXG4gIHZhciBpbnRlbnNpdHlIaSAgICAgPSAtSW5maW5pdHlcclxuICBpZighdmVydGV4VVZzICYmICFjZWxsVVZzKSB7XHJcbiAgICBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcclxuICAgICAgaWYocGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kcykge1xyXG4gICAgICAgIGludGVuc2l0eUxvID0gK3BhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHNbMF1cclxuICAgICAgICBpbnRlbnNpdHlIaSA9ICtwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzWzFdXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZm9yKHZhciBpPTA7IGk8dmVydGV4SW50ZW5zaXR5Lmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgICB2YXIgZiA9IHZlcnRleEludGVuc2l0eVtpXVxyXG4gICAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcclxuICAgICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xyXG4gICAgICBmb3IodmFyIGk9MDsgaTxjZWxsSW50ZW5zaXR5Lmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgdmFyIGYgPSBjZWxsSW50ZW5zaXR5W2ldXHJcbiAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcclxuICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBmb3IodmFyIGk9MDsgaTxwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICB2YXIgZiA9IHBvc2l0aW9uc1tpXVsyXVxyXG4gICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXHJcbiAgICAgICAgaW50ZW5zaXR5SGkgPSBNYXRoLm1heChpbnRlbnNpdHlIaSwgZilcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaWYodmVydGV4SW50ZW5zaXR5KSB7XHJcbiAgICB0aGlzLmludGVuc2l0eSA9IHZlcnRleEludGVuc2l0eVxyXG4gIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XHJcbiAgICB0aGlzLmludGVuc2l0eSA9IHVucGFja0ludGVuc2l0eShjZWxscywgcG9zaXRpb25zLmxlbmd0aCwgY2VsbEludGVuc2l0eSlcclxuICB9IGVsc2Uge1xyXG4gICAgdGhpcy5pbnRlbnNpdHkgPSB0YWtlWkNvbXBvbmVudChwb3NpdGlvbnMpXHJcbiAgfVxyXG5cclxuICAvL1BvaW50IHNpemVcclxuICB2YXIgcG9pbnRTaXplcyAgICAgID0gcGFyYW1zLnBvaW50U2l6ZXNcclxuICB2YXIgbWVzaFBvaW50U2l6ZSAgID0gcGFyYW1zLnBvaW50U2l6ZSB8fCAxLjBcclxuXHJcbiAgLy9VcGRhdGUgYm91bmRzXHJcbiAgdGhpcy5ib3VuZHMgICAgICAgPSBbW0luZmluaXR5LEluZmluaXR5LEluZmluaXR5XSwgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XV1cclxuICBmb3IodmFyIGk9MDsgaTxwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcclxuICAgIHZhciBwID0gcG9zaXRpb25zW2ldXHJcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmJvdW5kc1swXVtqXSA9IE1hdGgubWluKHRoaXMuYm91bmRzWzBdW2pdLCBwW2pdKVxyXG4gICAgICB0aGlzLmJvdW5kc1sxXVtqXSA9IE1hdGgubWF4KHRoaXMuYm91bmRzWzFdW2pdLCBwW2pdKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy9QYWNrIGNlbGxzIGludG8gYnVmZmVyc1xyXG4gIHZhciB0cmlhbmdsZUNvdW50ID0gMFxyXG4gIHZhciBlZGdlQ291bnQgPSAwXHJcbiAgdmFyIHBvaW50Q291bnQgPSAwXHJcblxyXG5maWxsX2xvb3A6XHJcbiAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcclxuICAgIHZhciBjZWxsID0gY2VsbHNbaV1cclxuICAgIHN3aXRjaChjZWxsLmxlbmd0aCkge1xyXG4gICAgICBjYXNlIDE6XHJcblxyXG4gICAgICAgIHZhciB2ID0gY2VsbFswXVxyXG4gICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXHJcblxyXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xyXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcFBvcy5wdXNoKHBbMF0sIHBbMV0sIHBbMl0sIHBbM10pXHJcblxyXG4gICAgICAgIHZhciBjXHJcbiAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XHJcbiAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXHJcbiAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcclxuICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGMgPSBtZXNoQ29sb3JcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcclxuICAgICAgICAgIHBDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBwQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciB1dlxyXG4gICAgICAgIGlmKHZlcnRleFVWcykge1xyXG4gICAgICAgICAgdXYgPSB2ZXJ0ZXhVVnNbdl1cclxuICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xyXG4gICAgICAgICAgdXYgPSBjZWxsVVZzW2ldXHJcbiAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcclxuICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAoY2VsbEludGVuc2l0eVtpXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgIH1cclxuICAgICAgICBwVVZzLnB1c2godXZbMF0sIHV2WzFdKVxyXG5cclxuICAgICAgICBpZihwb2ludFNpemVzKSB7XHJcbiAgICAgICAgICBwU2l6LnB1c2gocG9pbnRTaXplc1t2XSlcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcFNpei5wdXNoKG1lc2hQb2ludFNpemUpXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBwSWRzLnB1c2goaSlcclxuXHJcbiAgICAgICAgcG9pbnRDb3VudCArPSAxXHJcbiAgICAgIGJyZWFrXHJcblxyXG4gICAgICBjYXNlIDI6XHJcblxyXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xyXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xyXG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXHJcbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxyXG4gICAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgICAgIGlmKGlzTmFOKHBba10pIHx8ICFpc0Zpbml0ZShwW2tdKSkge1xyXG4gICAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcclxuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxyXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cclxuXHJcbiAgICAgICAgICBlUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSlcclxuXHJcbiAgICAgICAgICB2YXIgY1xyXG4gICAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XHJcbiAgICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XHJcbiAgICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjID0gbWVzaENvbG9yXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xyXG4gICAgICAgICAgICBlQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgMSlcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdKVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHZhciB1dlxyXG4gICAgICAgICAgaWYodmVydGV4VVZzKSB7XHJcbiAgICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXHJcbiAgICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsVVZzKSB7XHJcbiAgICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBlVVZzLnB1c2godXZbMF0sIHV2WzFdKVxyXG5cclxuICAgICAgICAgIGVJZHMucHVzaChpKVxyXG4gICAgICAgIH1cclxuICAgICAgICBlZGdlQ291bnQgKz0gMVxyXG4gICAgICBicmVha1xyXG5cclxuICAgICAgY2FzZSAzOlxyXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xyXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXHJcbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxyXG4gICAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgICAgIGlmKGlzTmFOKHBba10pIHx8ICFpc0Zpbml0ZShwW2tdKSkge1xyXG4gICAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxyXG5cclxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXHJcbiAgICAgICAgICB0UG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSwgcFszXSlcclxuXHJcbiAgICAgICAgICB2YXIgdyA9IHZlY3RvcnNbdl1cclxuICAgICAgICAgIHRWZWMucHVzaCh3WzBdLCB3WzFdLCB3WzJdKTtcclxuXHJcbiAgICAgICAgICB2YXIgY1xyXG4gICAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XHJcbiAgICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XHJcbiAgICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjID0gbWVzaENvbG9yXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xyXG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgMSlcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdKVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHZhciB1dlxyXG4gICAgICAgICAgaWYodmVydGV4VVZzKSB7XHJcbiAgICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXHJcbiAgICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsVVZzKSB7XHJcbiAgICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICB0VVZzLnB1c2godXZbMF0sIHV2WzFdKVxyXG5cclxuICAgICAgICAgIHZhciBxXHJcbiAgICAgICAgICBpZih2ZXJ0ZXhOb3JtYWxzKSB7XHJcbiAgICAgICAgICAgIHEgPSB2ZXJ0ZXhOb3JtYWxzW3ZdXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBxID0gY2VsbE5vcm1hbHNbaV1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHROb3IucHVzaChxWzBdLCBxWzFdLCBxWzJdKVxyXG5cclxuICAgICAgICAgIHRJZHMucHVzaChpKVxyXG4gICAgICAgIH1cclxuICAgICAgICB0cmlhbmdsZUNvdW50ICs9IDFcclxuICAgICAgYnJlYWtcclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgIGJyZWFrXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0aGlzLnBvaW50Q291bnQgICAgID0gcG9pbnRDb3VudFxyXG4gIHRoaXMuZWRnZUNvdW50ICAgICAgPSBlZGdlQ291bnRcclxuICB0aGlzLnRyaWFuZ2xlQ291bnQgID0gdHJpYW5nbGVDb3VudFxyXG5cclxuICB0aGlzLnBvaW50UG9zaXRpb25zLnVwZGF0ZShwUG9zKVxyXG4gIHRoaXMucG9pbnRDb2xvcnMudXBkYXRlKHBDb2wpXHJcbiAgdGhpcy5wb2ludFVWcy51cGRhdGUocFVWcylcclxuICB0aGlzLnBvaW50U2l6ZXMudXBkYXRlKHBTaXopXHJcbiAgdGhpcy5wb2ludElkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KHBJZHMpKVxyXG5cclxuICB0aGlzLmVkZ2VQb3NpdGlvbnMudXBkYXRlKGVQb3MpXHJcbiAgdGhpcy5lZGdlQ29sb3JzLnVwZGF0ZShlQ29sKVxyXG4gIHRoaXMuZWRnZVVWcy51cGRhdGUoZVVWcylcclxuICB0aGlzLmVkZ2VJZHMudXBkYXRlKG5ldyBVaW50MzJBcnJheShlSWRzKSlcclxuXHJcbiAgdGhpcy50cmlhbmdsZVBvc2l0aW9ucy51cGRhdGUodFBvcylcclxuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycy51cGRhdGUodFZlYylcclxuICB0aGlzLnRyaWFuZ2xlQ29sb3JzLnVwZGF0ZSh0Q29sKVxyXG4gIHRoaXMudHJpYW5nbGVVVnMudXBkYXRlKHRVVnMpXHJcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMudXBkYXRlKHROb3IpXHJcbiAgdGhpcy50cmlhbmdsZUlkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KHRJZHMpKVxyXG59XHJcblxyXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XHJcbiAgdmFyIGdsICAgICAgICAgID0gdGhpcy5nbFxyXG4gIHZhciBtb2RlbCAgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IGlkZW50aXR5TWF0cml4XHJcbiAgdmFyIHZpZXcgICAgICAgID0gcGFyYW1zLnZpZXcgICAgICAgfHwgaWRlbnRpdHlNYXRyaXhcclxuICB2YXIgcHJvamVjdGlvbiAgPSBwYXJhbXMucHJvamVjdGlvbiB8fCBpZGVudGl0eU1hdHJpeFxyXG5cclxuICB2YXIgY2xpcEJvdW5kcyA9IFtbLTFlNiwtMWU2LC0xZTZdLFsxZTYsMWU2LDFlNl1dXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBjbGlwQm91bmRzWzBdW2ldID0gTWF0aC5tYXgoY2xpcEJvdW5kc1swXVtpXSwgdGhpcy5jbGlwQm91bmRzWzBdW2ldKVxyXG4gICAgY2xpcEJvdW5kc1sxXVtpXSA9IE1hdGgubWluKGNsaXBCb3VuZHNbMV1baV0sIHRoaXMuY2xpcEJvdW5kc1sxXVtpXSlcclxuICB9XHJcblxyXG4gIHZhciB1bmlmb3JtcyA9IHtcclxuICAgIG1vZGVsOiAgICAgIG1vZGVsLFxyXG4gICAgdmlldzogICAgICAgdmlldyxcclxuICAgIHByb2plY3Rpb246IHByb2plY3Rpb24sXHJcblxyXG4gICAgY2xpcEJvdW5kczogY2xpcEJvdW5kcyxcclxuXHJcbiAgICBrYW1iaWVudDogICB0aGlzLmFtYmllbnRMaWdodCxcclxuICAgIGtkaWZmdXNlOiAgIHRoaXMuZGlmZnVzZUxpZ2h0LFxyXG4gICAga3NwZWN1bGFyOiAgdGhpcy5zcGVjdWxhckxpZ2h0LFxyXG4gICAgcm91Z2huZXNzOiAgdGhpcy5yb3VnaG5lc3MsXHJcbiAgICBmcmVzbmVsOiAgICB0aGlzLmZyZXNuZWwsXHJcblxyXG4gICAgZXllUG9zaXRpb246ICAgWzAsMCwwXSxcclxuICAgIGxpZ2h0UG9zaXRpb246IFswLDAsMF0sXHJcblxyXG4gICAgb3BhY2l0eTogIHRoaXMub3BhY2l0eSxcclxuXHJcbiAgICB2ZWN0b3JTY2FsZTogdGhpcy52ZWN0b3JTY2FsZSxcclxuICAgIGNvbmVTY2FsZTogdGhpcy5jb25lU2NhbGUsXHJcbiAgICBjb25lT2Zmc2V0OiB0aGlzLmNvbmVPZmZzZXQsXHJcblxyXG4gICAgY29udG91ckNvbG9yOiB0aGlzLmNvbnRvdXJDb2xvcixcclxuXHJcbiAgICB0ZXh0dXJlOiAgICAwXHJcbiAgfVxyXG5cclxuICB0aGlzLnRleHR1cmUuYmluZCgwKVxyXG5cclxuICB2YXIgaW52Q2FtZXJhTWF0cml4ID0gbmV3IEFycmF5KDE2KVxyXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMudmlldywgdW5pZm9ybXMubW9kZWwpXHJcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXHJcbiAgaW52ZXJ0KGludkNhbWVyYU1hdHJpeCwgaW52Q2FtZXJhTWF0cml4KVxyXG5cclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHVuaWZvcm1zLmV5ZVBvc2l0aW9uW2ldID0gaW52Q2FtZXJhTWF0cml4WzEyK2ldIC8gaW52Q2FtZXJhTWF0cml4WzE1XVxyXG4gIH1cclxuXHJcbiAgdmFyIHcgPSBpbnZDYW1lcmFNYXRyaXhbMTVdXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB3ICs9IHRoaXMubGlnaHRQb3NpdGlvbltpXSAqIGludkNhbWVyYU1hdHJpeFs0KmkrM11cclxuICB9XHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMitpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHMgKz0gaW52Q2FtZXJhTWF0cml4WzQqaitpXSAqIHRoaXMubGlnaHRQb3NpdGlvbltqXVxyXG4gICAgfVxyXG4gICAgdW5pZm9ybXMubGlnaHRQb3NpdGlvbltpXSA9IHMgLyB3XHJcbiAgfVxyXG5cclxuICBpZih0aGlzLnRyaWFuZ2xlQ291bnQgPiAwKSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy50cmlTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcclxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuZWRnZUNvdW50ID4gMCAmJiB0aGlzLmxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmxpbmVTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxyXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcclxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID4gMCkge1xyXG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5wb2ludFZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXHJcbiAgICB0aGlzLnBvaW50VkFPLnVuYmluZCgpXHJcbiAgfVxyXG5cclxuICBpZih0aGlzLmNvbnRvdXJFbmFibGUgJiYgdGhpcy5jb250b3VyQ291bnQgPiAwICYmIHRoaXMuY29udG91ckxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmNvbnRvdXJTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5jb250b3VyVkFPLmJpbmQoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5jb250b3VyQ291bnQpXHJcbiAgICB0aGlzLmNvbnRvdXJWQU8udW5iaW5kKClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XHJcblxyXG4gIHZhciBnbCAgICAgICAgID0gdGhpcy5nbFxyXG5cclxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IGlkZW50aXR5TWF0cml4XHJcbiAgdmFyIHZpZXcgICAgICAgPSBwYXJhbXMudmlldyAgICAgICB8fCBpZGVudGl0eU1hdHJpeFxyXG4gIHZhciBwcm9qZWN0aW9uID0gcGFyYW1zLnByb2plY3Rpb24gfHwgaWRlbnRpdHlNYXRyaXhcclxuXHJcbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcclxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXHJcbiAgfVxyXG5cclxuICAvL1NhdmUgY2FtZXJhIHBhcmFtZXRlcnNcclxuICB0aGlzLl9tb2RlbCAgICAgID0gW10uc2xpY2UuY2FsbChtb2RlbClcclxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxyXG4gIHRoaXMuX3Byb2plY3Rpb24gPSBbXS5zbGljZS5jYWxsKHByb2plY3Rpb24pXHJcbiAgdGhpcy5fcmVzb2x1dGlvbiA9IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdXHJcblxyXG4gIHZhciB1bmlmb3JtcyA9IHtcclxuICAgIG1vZGVsOiAgICAgIG1vZGVsLFxyXG4gICAgdmlldzogICAgICAgdmlldyxcclxuICAgIHByb2plY3Rpb246IHByb2plY3Rpb24sXHJcbiAgICBjbGlwQm91bmRzOiBjbGlwQm91bmRzLFxyXG5cclxuICAgIHZlY3RvclNjYWxlOiB0aGlzLnZlY3RvclNjYWxlLFxyXG4gICAgY29uZVNjYWxlOiB0aGlzLmNvbmVTY2FsZSxcclxuICAgIGNvbmVPZmZzZXQ6IHRoaXMuY29uZU9mZnNldCxcclxuXHJcbiAgICBwaWNrSWQ6ICAgICB0aGlzLnBpY2tJZCAvIDI1NS4wLFxyXG4gIH1cclxuXHJcbiAgdmFyIHNoYWRlciA9IHRoaXMucGlja1NoYWRlclxyXG4gIHNoYWRlci5iaW5kKClcclxuICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xyXG5cclxuICBpZih0aGlzLnRyaWFuZ2xlQ291bnQgPiAwKSB7XHJcbiAgICB0aGlzLnRyaWFuZ2xlVkFPLmJpbmQoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIHRoaXMudHJpYW5nbGVDb3VudCozKVxyXG4gICAgdGhpcy50cmlhbmdsZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5lZGdlQ291bnQgPiAwKSB7XHJcbiAgICB0aGlzLmVkZ2VWQU8uYmluZCgpXHJcbiAgICBnbC5saW5lV2lkdGgodGhpcy5saW5lV2lkdGgpXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLkxJTkVTLCAwLCB0aGlzLmVkZ2VDb3VudCoyKVxyXG4gICAgdGhpcy5lZGdlVkFPLnVuYmluZCgpXHJcbiAgfVxyXG5cclxuICBpZih0aGlzLnBvaW50Q291bnQgPiAwKSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5wb2ludFBpY2tTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5wb2ludFZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXHJcbiAgICB0aGlzLnBvaW50VkFPLnVuYmluZCgpXHJcbiAgfVxyXG59XHJcblxyXG5cclxucHJvdG8ucGljayA9IGZ1bmN0aW9uKHBpY2tEYXRhKSB7XHJcbiAgaWYoIXBpY2tEYXRhKSB7XHJcbiAgICByZXR1cm4gbnVsbFxyXG4gIH1cclxuICBpZihwaWNrRGF0YS5pZCAhPT0gdGhpcy5waWNrSWQpIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG5cclxuICB2YXIgY2VsbElkICAgID0gcGlja0RhdGEudmFsdWVbMF0gKyAyNTYqcGlja0RhdGEudmFsdWVbMV0gKyA2NTUzNipwaWNrRGF0YS52YWx1ZVsyXVxyXG4gIHZhciBjZWxsICAgICAgPSB0aGlzLmNlbGxzW2NlbGxJZF1cclxuICB2YXIgcG9zID0gICAgIHRoaXMucG9zaXRpb25zW2NlbGxbMV1dLnNsaWNlKDAsIDMpXHJcblxyXG4gIHJldHVybiB7XHJcbiAgICAvLyBjb3JyZXNwb25kaW5nIHRvIGlucHV0IGluZGljZXNcclxuICAgIGluZGV4OiBNYXRoLmZsb29yKGNlbGxbMV0gLyA0OCksXHJcbiAgICBwb3NpdGlvbjogcG9zLFxyXG4gICAgZGF0YUNvb3JkaW5hdGU6IHBvc1xyXG4gIH1cclxufVxyXG5cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXHJcblxyXG4gIHRoaXMudHJpU2hhZGVyLmRpc3Bvc2UoKVxyXG4gIC8vIHRoaXMubGluZVNoYWRlci5kaXNwb3NlKClcclxuICAvLyB0aGlzLnBvaW50U2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcclxuICAvLyB0aGlzLnBvaW50UGlja1NoYWRlci5kaXNwb3NlKClcclxuXHJcbiAgdGhpcy50cmlhbmdsZVZBTy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVWZWN0b3JzLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMuZGlzcG9zZSgpXHJcbiAgdGhpcy50cmlhbmdsZVVWcy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlTm9ybWFscy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlSWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLmVkZ2VWQU8uZGlzcG9zZSgpXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIHRoaXMuZWRnZUNvbG9ycy5kaXNwb3NlKClcclxuICB0aGlzLmVkZ2VVVnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5lZGdlSWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLnBvaW50VkFPLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5wb2ludENvbG9ycy5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50VVZzLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRTaXplcy5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50SWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLmNvbnRvdXJWQU8uZGlzcG9zZSgpXHJcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIC8vIHRoaXMuY29udG91clNoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlTWVzaFNoYWRlcihnbCkge1xyXG4gIC8vIG5lZWQgdG8gcGFzcyBtZXNoU2hhZGVyIGF0dHJpYnV0ZXMgbWFudWFsbHksXHJcbiAgLy8gdG8gbWFrZSB0aGlzIHdvcmsgb24gZXRwaW5hcmQncyBVYnVudHUgVGhpbmtwYWRcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBtZXNoU2hhZGVyLnZlcnRleCwgbWVzaFNoYWRlci5mcmFnbWVudCwgbnVsbCwgbWVzaFNoYWRlci5hdHRyaWJ1dGVzKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uICAgID0gMlxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgID0gM1xyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlV2lyZVNoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHdpcmVTaGFkZXIudmVydGV4LCB3aXJlU2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uICAgID0gMlxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgID0gM1xyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlUG9pbnRTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwb2ludFNoYWRlci52ZXJ0ZXgsIHBvaW50U2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uICA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICAgPSAyXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgID0gM1xyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvaW50U2l6ZS5sb2NhdGlvbiA9IDRcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBpY2tTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwaWNrU2hhZGVyLnZlcnRleCwgcGlja1NoYWRlci5mcmFnbWVudCwgbnVsbCwgcGlja1NoYWRlci5hdHRyaWJ1dGVzKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmlkLmxvY2F0aW9uICAgICAgID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlUG9pbnRQaWNrU2hhZGVyKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcG9pbnRQaWNrU2hhZGVyLnZlcnRleCwgcG9pbnRQaWNrU2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uICA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5pZC5sb2NhdGlvbiAgICAgICAgPSAxXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9pbnRTaXplLmxvY2F0aW9uID0gNFxyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlQ29udG91clNoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIGNvbnRvdXJTaGFkZXIudmVydGV4LCBjb250b3VyU2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlU2ltcGxpY2lhbE1lc2goZ2wsIHBhcmFtcykge1xyXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICBwYXJhbXMgPSBnbDtcclxuICAgIGdsID0gcGFyYW1zLmdsO1xyXG4gIH1cclxuXHJcbiAgdmFyIHRyaVNoYWRlciAgICAgICA9IHBhcmFtcy50cmlTaGFkZXIgfHwgY3JlYXRlTWVzaFNoYWRlcihnbClcclxuICB2YXIgbGluZVNoYWRlciAgICAgID0gbnVsbDsgLy9jcmVhdGVXaXJlU2hhZGVyKGdsKVxyXG4gIHZhciBwb2ludFNoYWRlciAgICAgPSBudWxsOyAvL2NyZWF0ZVBvaW50U2hhZGVyKGdsKVxyXG4gIHZhciBwaWNrU2hhZGVyICAgICAgPSBjcmVhdGVQaWNrU2hhZGVyKGdsKVxyXG4gIHZhciBwb2ludFBpY2tTaGFkZXIgPSBudWxsOyAvL2NyZWF0ZVBvaW50UGlja1NoYWRlcihnbClcclxuICB2YXIgY29udG91clNoYWRlciAgID0gbnVsbDsgLy9jcmVhdGVDb250b3VyU2hhZGVyKGdsKVxyXG5cclxuICB2YXIgbWVzaFRleHR1cmUgICAgICAgPSBjcmVhdGVUZXh0dXJlKGdsLFxyXG4gICAgbmRhcnJheShuZXcgVWludDhBcnJheShbMjU1LDI1NSwyNTUsMjU1XSksIFsxLDEsNF0pKVxyXG4gIG1lc2hUZXh0dXJlLmdlbmVyYXRlTWlwbWFwKClcclxuICBtZXNoVGV4dHVyZS5taW5GaWx0ZXIgPSBnbC5MSU5FQVJfTUlQTUFQX0xJTkVBUlxyXG4gIG1lc2hUZXh0dXJlLm1hZ0ZpbHRlciA9IGdsLkxJTkVBUlxyXG5cclxuICB2YXIgdHJpYW5nbGVQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlVmVjdG9ycyAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB0cmlhbmdsZUNvbG9ycyAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVVVnMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlTm9ybWFscyAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB0cmlhbmdsZUlkcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVWQU8gICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZVBvc2l0aW9ucyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDRcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVJZHMsXHJcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXHJcbiAgICAgIHNpemU6IDQsXHJcbiAgICAgIG5vcm1hbGl6ZWQ6IHRydWVcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVDb2xvcnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiA0XHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlVVZzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogMlxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZU5vcm1hbHMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAzXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlVmVjdG9ycyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDNcclxuICAgIH1cclxuICBdKVxyXG5cclxuICB2YXIgZWRnZVBvc2l0aW9ucyA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgZWRnZUNvbG9ycyAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgZWRnZVVWcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgZWRnZUlkcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgZWRnZVZBTyAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAgeyBidWZmZXI6IGVkZ2VQb3NpdGlvbnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAzXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IGVkZ2VJZHMsXHJcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXHJcbiAgICAgIHNpemU6IDQsXHJcbiAgICAgIG5vcm1hbGl6ZWQ6IHRydWVcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogZWRnZUNvbG9ycyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDRcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogZWRnZVVWcyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDJcclxuICAgIH1cclxuICBdKVxyXG5cclxuICB2YXIgcG9pbnRQb3NpdGlvbnMgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwb2ludENvbG9ycyAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHBvaW50VVZzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgcG9pbnRTaXplcyAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwb2ludElkcyAgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHBvaW50VkFPICAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAgeyBidWZmZXI6IHBvaW50UG9zaXRpb25zLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogM1xyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBwb2ludElkcyxcclxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcclxuICAgICAgc2l6ZTogNCxcclxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBwb2ludENvbG9ycyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDRcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogcG9pbnRVVnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAyXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHBvaW50U2l6ZXMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAxXHJcbiAgICB9XHJcbiAgXSlcclxuXHJcbiAgdmFyIGNvbnRvdXJQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGNvbnRvdXJWQU8gICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgIHsgYnVmZmVyOiBjb250b3VyUG9zaXRpb25zLFxyXG4gICAgICB0eXBlOiAgIGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAgIDNcclxuICAgIH1dKVxyXG5cclxuICB2YXIgbWVzaCA9IG5ldyBTaW1wbGljaWFsTWVzaChnbFxyXG4gICAgLCBtZXNoVGV4dHVyZVxyXG4gICAgLCB0cmlTaGFkZXJcclxuICAgICwgbGluZVNoYWRlclxyXG4gICAgLCBwb2ludFNoYWRlclxyXG4gICAgLCBwaWNrU2hhZGVyXHJcbiAgICAsIHBvaW50UGlja1NoYWRlclxyXG4gICAgLCBjb250b3VyU2hhZGVyXHJcbiAgICAsIHRyaWFuZ2xlUG9zaXRpb25zXHJcbiAgICAsIHRyaWFuZ2xlVmVjdG9yc1xyXG4gICAgLCB0cmlhbmdsZUlkc1xyXG4gICAgLCB0cmlhbmdsZUNvbG9yc1xyXG4gICAgLCB0cmlhbmdsZVVWc1xyXG4gICAgLCB0cmlhbmdsZU5vcm1hbHNcclxuICAgICwgdHJpYW5nbGVWQU9cclxuICAgICwgZWRnZVBvc2l0aW9uc1xyXG4gICAgLCBlZGdlSWRzXHJcbiAgICAsIGVkZ2VDb2xvcnNcclxuICAgICwgZWRnZVVWc1xyXG4gICAgLCBlZGdlVkFPXHJcbiAgICAsIHBvaW50UG9zaXRpb25zXHJcbiAgICAsIHBvaW50SWRzXHJcbiAgICAsIHBvaW50Q29sb3JzXHJcbiAgICAsIHBvaW50VVZzXHJcbiAgICAsIHBvaW50U2l6ZXNcclxuICAgICwgcG9pbnRWQU9cclxuICAgICwgY29udG91clBvc2l0aW9uc1xyXG4gICAgLCBjb250b3VyVkFPKVxyXG5cclxuICBtZXNoLnVwZGF0ZShwYXJhbXMpXHJcblxyXG4gIHJldHVybiBtZXNoXHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2ltcGxpY2lhbE1lc2hcclxuIiwidmFyIGdsc2xpZnkgICAgICAgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxuXHJcbnZhciB0cmlWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmZsb2F0IGludmVyc2UoZmxvYXQgbSkge1xcbiAgcmV0dXJuIDEuMCAvIG07XFxufVxcblxcbm1hdDIgaW52ZXJzZShtYXQyIG0pIHtcXG4gIHJldHVybiBtYXQyKG1bMV1bMV0sLW1bMF1bMV0sXFxuICAgICAgICAgICAgIC1tWzFdWzBdLCBtWzBdWzBdKSAvIChtWzBdWzBdKm1bMV1bMV0gLSBtWzBdWzFdKm1bMV1bMF0pO1xcbn1cXG5cXG5tYXQzIGludmVyc2UobWF0MyBtKSB7XFxuICBmbG9hdCBhMDAgPSBtWzBdWzBdLCBhMDEgPSBtWzBdWzFdLCBhMDIgPSBtWzBdWzJdO1xcbiAgZmxvYXQgYTEwID0gbVsxXVswXSwgYTExID0gbVsxXVsxXSwgYTEyID0gbVsxXVsyXTtcXG4gIGZsb2F0IGEyMCA9IG1bMl1bMF0sIGEyMSA9IG1bMl1bMV0sIGEyMiA9IG1bMl1bMl07XFxuXFxuICBmbG9hdCBiMDEgPSBhMjIgKiBhMTEgLSBhMTIgKiBhMjE7XFxuICBmbG9hdCBiMTEgPSAtYTIyICogYTEwICsgYTEyICogYTIwO1xcbiAgZmxvYXQgYjIxID0gYTIxICogYTEwIC0gYTExICogYTIwO1xcblxcbiAgZmxvYXQgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xcblxcbiAgcmV0dXJuIG1hdDMoYjAxLCAoLWEyMiAqIGEwMSArIGEwMiAqIGEyMSksIChhMTIgKiBhMDEgLSBhMDIgKiBhMTEpLFxcbiAgICAgICAgICAgICAgYjExLCAoYTIyICogYTAwIC0gYTAyICogYTIwKSwgKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApLFxcbiAgICAgICAgICAgICAgYjIxLCAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCksIChhMTEgKiBhMDAgLSBhMDEgKiBhMTApKSAvIGRldDtcXG59XFxuXFxubWF0NCBpbnZlcnNlKG1hdDQgbSkge1xcbiAgZmxvYXRcXG4gICAgICBhMDAgPSBtWzBdWzBdLCBhMDEgPSBtWzBdWzFdLCBhMDIgPSBtWzBdWzJdLCBhMDMgPSBtWzBdWzNdLFxcbiAgICAgIGExMCA9IG1bMV1bMF0sIGExMSA9IG1bMV1bMV0sIGExMiA9IG1bMV1bMl0sIGExMyA9IG1bMV1bM10sXFxuICAgICAgYTIwID0gbVsyXVswXSwgYTIxID0gbVsyXVsxXSwgYTIyID0gbVsyXVsyXSwgYTIzID0gbVsyXVszXSxcXG4gICAgICBhMzAgPSBtWzNdWzBdLCBhMzEgPSBtWzNdWzFdLCBhMzIgPSBtWzNdWzJdLCBhMzMgPSBtWzNdWzNdLFxcblxcbiAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcXG4gICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXFxuICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxcbiAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcXG4gICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXFxuICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxcbiAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcXG4gICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXFxuICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxcbiAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcXG4gICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXFxuICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxcblxcbiAgICAgIGRldCA9IGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcXG5cXG4gIHJldHVybiBtYXQ0KFxcbiAgICAgIGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSxcXG4gICAgICBhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDksXFxuICAgICAgYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzLFxcbiAgICAgIGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMyxcXG4gICAgICBhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcsXFxuICAgICAgYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3LFxcbiAgICAgIGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSxcXG4gICAgICBhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEsXFxuICAgICAgYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2LFxcbiAgICAgIGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNixcXG4gICAgICBhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDAsXFxuICAgICAgYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwLFxcbiAgICAgIGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNixcXG4gICAgICBhMDAgKiBiMDkgLSBhMDEgKiBiMDcgKyBhMDIgKiBiMDYsXFxuICAgICAgYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwLFxcbiAgICAgIGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgLyBkZXQ7XFxufVxcblxcbnZlYzMgZ2V0T3J0aG9nb25hbFZlY3Rvcih2ZWMzIHYpIHtcXG4gIC8vIFJldHVybiB1cC12ZWN0b3IgZm9yIG9ubHkteiB2ZWN0b3IuXFxuICAvLyBSZXR1cm4gYXggKyBieSArIGN6ID0gMCwgYSBwb2ludCB0aGF0IGxpZXMgb24gdGhlIHBsYW5lIHRoYXQgaGFzIHYgYXMgYSBub3JtYWwgYW5kIHRoYXQgaXNuJ3QgKDAsMCwwKS5cXG4gIC8vIEZyb20gdGhlIGFib3ZlIGlmLXN0YXRlbWVudCB3ZSBoYXZlIHx8YXx8ID4gMCAgVSAgfHxifHwgPiAwLlxcbiAgLy8gQXNzaWduIHogPSAwLCB4ID0gLWIsIHkgPSBhOlxcbiAgLy8gYSotYiArIGIqYSArIGMqMCA9IC1iYSArIGJhICsgMCA9IDBcXG4gIGlmICh2Lngqdi54ID4gdi56KnYueiB8fCB2Lnkqdi55ID4gdi56KnYueikge1xcbiAgICByZXR1cm4gbm9ybWFsaXplKHZlYzMoLXYueSwgdi54LCAwLjApKTtcXG4gIH0gZWxzZSB7XFxuICAgIHJldHVybiBub3JtYWxpemUodmVjMygwLjAsIHYueiwgLXYueSkpO1xcbiAgfVxcbn1cXG5cXG4vLyBDYWxjdWxhdGUgdGhlIGNvbmUgdmVydGV4IGFuZCBub3JtYWwgYXQgdGhlIGdpdmVuIGluZGV4Llxcbi8vXFxuLy8gVGhlIHJldHVybmVkIHZlcnRleCBpcyBmb3IgYSBjb25lIHdpdGggaXRzIHRvcCBhdCBvcmlnaW4gYW5kIGhlaWdodCBvZiAxLjAsXFxuLy8gcG9pbnRpbmcgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgdmVjdG9yIGF0dHJpYnV0ZS5cXG4vL1xcbi8vIEVhY2ggY29uZSBpcyBtYWRlIHVwIG9mIGEgdG9wIHZlcnRleCwgYSBjZW50ZXIgYmFzZSB2ZXJ0ZXggYW5kIGJhc2UgcGVyaW1ldGVyIHZlcnRpY2VzLlxcbi8vIFRoZXNlIHZlcnRpY2VzIGFyZSB1c2VkIHRvIG1ha2UgdXAgdGhlIHRyaWFuZ2xlcyBvZiB0aGUgY29uZSBieSB0aGUgZm9sbG93aW5nOlxcbi8vICAgc2VnbWVudCArIDAgdG9wIHZlcnRleFxcbi8vICAgc2VnbWVudCArIDEgcGVyaW1ldGVyIHZlcnRleCBhKzFcXG4vLyAgIHNlZ21lbnQgKyAyIHBlcmltZXRlciB2ZXJ0ZXggYVxcbi8vICAgc2VnbWVudCArIDMgY2VudGVyIGJhc2UgdmVydGV4XFxuLy8gICBzZWdtZW50ICsgNCBwZXJpbWV0ZXIgdmVydGV4IGFcXG4vLyAgIHNlZ21lbnQgKyA1IHBlcmltZXRlciB2ZXJ0ZXggYSsxXFxuLy8gV2hlcmUgc2VnbWVudCBpcyB0aGUgbnVtYmVyIG9mIHRoZSByYWRpYWwgc2VnbWVudCAqIDYgYW5kIGEgaXMgdGhlIGFuZ2xlIGF0IHRoYXQgcmFkaWFsIHNlZ21lbnQuXFxuLy8gVG8gZ28gZnJvbSBpbmRleCB0byBzZWdtZW50LCBmbG9vcihpbmRleCAvIDYpXFxuLy8gVG8gZ28gZnJvbSBzZWdtZW50IHRvIGFuZ2xlLCAyKnBpICogKHNlZ21lbnQvc2VnbWVudENvdW50KVxcbi8vIFRvIGdvIGZyb20gaW5kZXggdG8gc2VnbWVudCBpbmRleCwgaW5kZXggLSAoc2VnbWVudCo2KVxcbi8vXFxudmVjMyBnZXRDb25lUG9zaXRpb24odmVjMyBkLCBmbG9hdCBpbmRleCwgZmxvYXQgY29uZU9mZnNldCwgb3V0IHZlYzMgbm9ybWFsKSB7XFxuXFxuICBjb25zdCBmbG9hdCBzZWdtZW50Q291bnQgPSA4LjA7XFxuXFxuICBpbmRleCA9IG1vZChpbmRleCwgc2VnbWVudENvdW50ICogNi4wKTtcXG5cXG4gIGZsb2F0IHNlZ21lbnQgPSBmbG9vcihpbmRleC82LjApO1xcbiAgZmxvYXQgc2VnbWVudEluZGV4ID0gaW5kZXggLSAoc2VnbWVudCo2LjApO1xcblxcbiAgbm9ybWFsID0gLW5vcm1hbGl6ZShkKTtcXG5cXG4gIGlmIChzZWdtZW50SW5kZXggPT0gMy4wKSB7XFxuICAgIHJldHVybiBtaXgodmVjMygwLjApLCAtZCwgY29uZU9mZnNldCk7XFxuICB9XFxuXFxuICAvLyBhbmdsZSA9IDJwaSAqICgoc2VnbWVudCArICgoc2VnbWVudEluZGV4ID09IDEuMCB8fCBzZWdtZW50SW5kZXggPT0gNS4wKSA/IDEuMCA6IDAuMCkpIC8gc2VnbWVudENvdW50KVxcbiAgZmxvYXQgbmV4dEFuZ2xlID0gZmxvYXQoc2VnbWVudEluZGV4ID09IDEuMCB8fCBzZWdtZW50SW5kZXggPT0gNS4wKTtcXG4gIGZsb2F0IGFuZ2xlID0gMi4wICogMy4xNDE1OSAqICgoc2VnbWVudCArIG5leHRBbmdsZSkgLyBzZWdtZW50Q291bnQpO1xcblxcbiAgdmVjMyB2MSA9IG1peChkLCB2ZWMzKDAuMCksIGNvbmVPZmZzZXQpO1xcbiAgdmVjMyB2MiA9IHYxIC0gZDtcXG5cXG4gIHZlYzMgdSA9IGdldE9ydGhvZ29uYWxWZWN0b3IoZCk7XFxuICB2ZWMzIHYgPSBub3JtYWxpemUoY3Jvc3ModSwgZCkpO1xcblxcbiAgdmVjMyB4ID0gdSAqIGNvcyhhbmdsZSkgKiBsZW5ndGgoZCkqMC4yNTtcXG4gIHZlYzMgeSA9IHYgKiBzaW4oYW5nbGUpICogbGVuZ3RoKGQpKjAuMjU7XFxuICB2ZWMzIHYzID0gdjIgKyB4ICsgeTtcXG4gIGlmIChzZWdtZW50SW5kZXggPD0gMi4wKSB7XFxuICAgIHZlYzMgdHggPSB1ICogc2luKGFuZ2xlKTtcXG4gICAgdmVjMyB0eSA9IHYgKiAtY29zKGFuZ2xlKTtcXG4gICAgdmVjMyB0YW5nZW50ID0gdHggKyB0eTtcXG4gICAgbm9ybWFsID0gbm9ybWFsaXplKGNyb3NzKHYzIC0gdjEsIHRhbmdlbnQpKTtcXG4gIH1cXG5cXG4gIGlmIChzZWdtZW50SW5kZXggPT0gMC4wKSB7XFxuICAgIHJldHVybiBtaXgoZCwgdmVjMygwLjApLCBjb25lT2Zmc2V0KTtcXG4gIH1cXG4gIHJldHVybiB2MztcXG59XFxuXFxuYXR0cmlidXRlIHZlYzMgdmVjdG9yO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yLCBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjMiB1djtcXG51bmlmb3JtIGZsb2F0IHZlY3RvclNjYWxlO1xcbnVuaWZvcm0gZmxvYXQgY29uZVNjYWxlO1xcblxcbnVuaWZvcm0gZmxvYXQgY29uZU9mZnNldDtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWxcXG4gICAgICAgICAgICwgdmlld1xcbiAgICAgICAgICAgLCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBleWVQb3NpdGlvblxcbiAgICAgICAgICAgLCBsaWdodFBvc2l0aW9uO1xcblxcbnZhcnlpbmcgdmVjMyBmX25vcm1hbFxcbiAgICAgICAgICAgLCBmX2xpZ2h0RGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZXllRGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZGF0YVxcbiAgICAgICAgICAgLCBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIC8vIFNjYWxlIHRoZSB2ZWN0b3IgbWFnbml0dWRlIHRvIHN0YXkgY29uc3RhbnQgd2l0aFxcbiAgLy8gbW9kZWwgJiB2aWV3IGNoYW5nZXMuXFxuICB2ZWMzIG5vcm1hbDtcXG4gIHZlYzMgWFlaID0gZ2V0Q29uZVBvc2l0aW9uKG1hdDMobW9kZWwpICogKCh2ZWN0b3JTY2FsZSAqIGNvbmVTY2FsZSkgKiB2ZWN0b3IpLCBwb3NpdGlvbi53LCBjb25lT2Zmc2V0LCBub3JtYWwpO1xcbiAgdmVjNCBjb25lUG9zaXRpb24gPSBtb2RlbCAqIHZlYzQocG9zaXRpb24ueHl6LCAxLjApICsgdmVjNChYWVosIDAuMCk7XFxuICBub3JtYWwgPSBub3JtYWxpemUobm9ybWFsICogaW52ZXJzZShtYXQzKG1vZGVsKSkpO1xcblxcbiAgLy8gdmVjNCBtX3Bvc2l0aW9uICA9IG1vZGVsICogdmVjNChjb25lUG9zaXRpb24sIDEuMCk7XFxuICB2ZWM0IHRfcG9zaXRpb24gID0gdmlldyAqIGNvbmVQb3NpdGlvbjtcXG4gIGdsX1Bvc2l0aW9uICAgICAgPSBwcm9qZWN0aW9uICogdF9wb3NpdGlvbjtcXG4gIGZfY29sb3IgICAgICAgICAgPSBjb2xvcjsgLy92ZWM0KHBvc2l0aW9uLncsIGNvbG9yLnIsIDAsIDApO1xcbiAgZl9ub3JtYWwgICAgICAgICA9IG5vcm1hbDtcXG4gIGZfZGF0YSAgICAgICAgICAgPSBjb25lUG9zaXRpb24ueHl6O1xcbiAgZl9wb3NpdGlvbiAgICAgICA9IHBvc2l0aW9uLnh5ejtcXG4gIGZfZXllRGlyZWN0aW9uICAgPSBleWVQb3NpdGlvbiAgIC0gY29uZVBvc2l0aW9uLnh5ejtcXG4gIGZfbGlnaHREaXJlY3Rpb24gPSBsaWdodFBvc2l0aW9uIC0gY29uZVBvc2l0aW9uLnh5ejtcXG4gIGZfdXYgICAgICAgICAgICAgPSB1djtcXG59XFxuXCJdKVxyXG52YXIgdHJpRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5mbG9hdCBiZWNrbWFubkRpc3RyaWJ1dGlvbihmbG9hdCB4LCBmbG9hdCByb3VnaG5lc3MpIHtcXG4gIGZsb2F0IE5kb3RIID0gbWF4KHgsIDAuMDAwMSk7XFxuICBmbG9hdCBjb3MyQWxwaGEgPSBOZG90SCAqIE5kb3RIO1xcbiAgZmxvYXQgdGFuMkFscGhhID0gKGNvczJBbHBoYSAtIDEuMCkgLyBjb3MyQWxwaGE7XFxuICBmbG9hdCByb3VnaG5lc3MyID0gcm91Z2huZXNzICogcm91Z2huZXNzO1xcbiAgZmxvYXQgZGVub20gPSAzLjE0MTU5MjY1MzU4OTc5MyAqIHJvdWdobmVzczIgKiBjb3MyQWxwaGEgKiBjb3MyQWxwaGE7XFxuICByZXR1cm4gZXhwKHRhbjJBbHBoYSAvIHJvdWdobmVzczIpIC8gZGVub207XFxufVxcblxcbmZsb2F0IGNvb2tUb3JyYW5jZVNwZWN1bGFyKFxcbiAgdmVjMyBsaWdodERpcmVjdGlvbixcXG4gIHZlYzMgdmlld0RpcmVjdGlvbixcXG4gIHZlYzMgc3VyZmFjZU5vcm1hbCxcXG4gIGZsb2F0IHJvdWdobmVzcyxcXG4gIGZsb2F0IGZyZXNuZWwpIHtcXG5cXG4gIGZsb2F0IFZkb3ROID0gbWF4KGRvdCh2aWV3RGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsKSwgMC4wKTtcXG4gIGZsb2F0IExkb3ROID0gbWF4KGRvdChsaWdodERpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbCksIDAuMCk7XFxuXFxuICAvL0hhbGYgYW5nbGUgdmVjdG9yXFxuICB2ZWMzIEggPSBub3JtYWxpemUobGlnaHREaXJlY3Rpb24gKyB2aWV3RGlyZWN0aW9uKTtcXG5cXG4gIC8vR2VvbWV0cmljIHRlcm1cXG4gIGZsb2F0IE5kb3RIID0gbWF4KGRvdChzdXJmYWNlTm9ybWFsLCBIKSwgMC4wKTtcXG4gIGZsb2F0IFZkb3RIID0gbWF4KGRvdCh2aWV3RGlyZWN0aW9uLCBIKSwgMC4wMDAwMDEpO1xcbiAgZmxvYXQgTGRvdEggPSBtYXgoZG90KGxpZ2h0RGlyZWN0aW9uLCBIKSwgMC4wMDAwMDEpO1xcbiAgZmxvYXQgRzEgPSAoMi4wICogTmRvdEggKiBWZG90TikgLyBWZG90SDtcXG4gIGZsb2F0IEcyID0gKDIuMCAqIE5kb3RIICogTGRvdE4pIC8gTGRvdEg7XFxuICBmbG9hdCBHID0gbWluKDEuMCwgbWluKEcxLCBHMikpO1xcbiAgXFxuICAvL0Rpc3RyaWJ1dGlvbiB0ZXJtXFxuICBmbG9hdCBEID0gYmVja21hbm5EaXN0cmlidXRpb24oTmRvdEgsIHJvdWdobmVzcyk7XFxuXFxuICAvL0ZyZXNuZWwgdGVybVxcbiAgZmxvYXQgRiA9IHBvdygxLjAgLSBWZG90TiwgZnJlc25lbCk7XFxuXFxuICAvL011bHRpcGx5IHRlcm1zIGFuZCBkb25lXFxuICByZXR1cm4gIEcgKiBGICogRCAvIG1heCgzLjE0MTU5MjY1ICogVmRvdE4sIDAuMDAwMDAxKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCByb3VnaG5lc3NcXG4gICAgICAgICAgICAsIGZyZXNuZWxcXG4gICAgICAgICAgICAsIGthbWJpZW50XFxuICAgICAgICAgICAgLCBrZGlmZnVzZVxcbiAgICAgICAgICAgICwga3NwZWN1bGFyXFxuICAgICAgICAgICAgLCBvcGFjaXR5O1xcbnVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmU7XFxuXFxudmFyeWluZyB2ZWMzIGZfbm9ybWFsXFxuICAgICAgICAgICAsIGZfbGlnaHREaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9leWVEaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9kYXRhXFxuICAgICAgICAgICAsIGZfcG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMyIGZfdXY7XFxuXFxudm9pZCBtYWluKCkge1xcblxcbiAgaWYgKG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgZl9wb3NpdGlvbikpIGRpc2NhcmQ7XFxuXFxuICB2ZWMzIE4gPSBub3JtYWxpemUoZl9ub3JtYWwpO1xcbiAgdmVjMyBMID0gbm9ybWFsaXplKGZfbGlnaHREaXJlY3Rpb24pO1xcbiAgdmVjMyBWID0gbm9ybWFsaXplKGZfZXllRGlyZWN0aW9uKTtcXG5cXG4gIGlmKCFnbF9Gcm9udEZhY2luZykge1xcbiAgICBOID0gLU47XFxuICB9XFxuXFxuICBmbG9hdCBzcGVjdWxhciA9IGNvb2tUb3JyYW5jZVNwZWN1bGFyKEwsIFYsIE4sIHJvdWdobmVzcywgZnJlc25lbCk7XFxuICBmbG9hdCBkaWZmdXNlICA9IG1pbihrYW1iaWVudCArIGtkaWZmdXNlICogbWF4KGRvdChOLCBMKSwgMC4wKSwgMS4wKTtcXG5cXG4gIHZlYzQgc3VyZmFjZUNvbG9yID0gIHRleHR1cmUyRCh0ZXh0dXJlLCBmX3V2KTtcXG4gIHZlYzQgbGl0Q29sb3IgPSBzdXJmYWNlQ29sb3IuYSAqIHZlYzQoZGlmZnVzZSAqIHN1cmZhY2VDb2xvci5yZ2IgKyBrc3BlY3VsYXIgKiB2ZWMzKDEsMSwxKSAqIHNwZWN1bGFyLCAgMS4wKTtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IGxpdENvbG9yICogb3BhY2l0eTtcXG59XCJdKVxyXG52YXIgcGlja1ZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmVjMyBnZXRPcnRob2dvbmFsVmVjdG9yKHZlYzMgdikge1xcbiAgLy8gUmV0dXJuIHVwLXZlY3RvciBmb3Igb25seS16IHZlY3Rvci5cXG4gIC8vIFJldHVybiBheCArIGJ5ICsgY3ogPSAwLCBhIHBvaW50IHRoYXQgbGllcyBvbiB0aGUgcGxhbmUgdGhhdCBoYXMgdiBhcyBhIG5vcm1hbCBhbmQgdGhhdCBpc24ndCAoMCwwLDApLlxcbiAgLy8gRnJvbSB0aGUgYWJvdmUgaWYtc3RhdGVtZW50IHdlIGhhdmUgfHxhfHwgPiAwICBVICB8fGJ8fCA+IDAuXFxuICAvLyBBc3NpZ24geiA9IDAsIHggPSAtYiwgeSA9IGE6XFxuICAvLyBhKi1iICsgYiphICsgYyowID0gLWJhICsgYmEgKyAwID0gMFxcbiAgaWYgKHYueCp2LnggPiB2Lnoqdi56IHx8IHYueSp2LnkgPiB2Lnoqdi56KSB7XFxuICAgIHJldHVybiBub3JtYWxpemUodmVjMygtdi55LCB2LngsIDAuMCkpO1xcbiAgfSBlbHNlIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKDAuMCwgdi56LCAtdi55KSk7XFxuICB9XFxufVxcblxcbi8vIENhbGN1bGF0ZSB0aGUgY29uZSB2ZXJ0ZXggYW5kIG5vcm1hbCBhdCB0aGUgZ2l2ZW4gaW5kZXguXFxuLy9cXG4vLyBUaGUgcmV0dXJuZWQgdmVydGV4IGlzIGZvciBhIGNvbmUgd2l0aCBpdHMgdG9wIGF0IG9yaWdpbiBhbmQgaGVpZ2h0IG9mIDEuMCxcXG4vLyBwb2ludGluZyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSB2ZWN0b3IgYXR0cmlidXRlLlxcbi8vXFxuLy8gRWFjaCBjb25lIGlzIG1hZGUgdXAgb2YgYSB0b3AgdmVydGV4LCBhIGNlbnRlciBiYXNlIHZlcnRleCBhbmQgYmFzZSBwZXJpbWV0ZXIgdmVydGljZXMuXFxuLy8gVGhlc2UgdmVydGljZXMgYXJlIHVzZWQgdG8gbWFrZSB1cCB0aGUgdHJpYW5nbGVzIG9mIHRoZSBjb25lIGJ5IHRoZSBmb2xsb3dpbmc6XFxuLy8gICBzZWdtZW50ICsgMCB0b3AgdmVydGV4XFxuLy8gICBzZWdtZW50ICsgMSBwZXJpbWV0ZXIgdmVydGV4IGErMVxcbi8vICAgc2VnbWVudCArIDIgcGVyaW1ldGVyIHZlcnRleCBhXFxuLy8gICBzZWdtZW50ICsgMyBjZW50ZXIgYmFzZSB2ZXJ0ZXhcXG4vLyAgIHNlZ21lbnQgKyA0IHBlcmltZXRlciB2ZXJ0ZXggYVxcbi8vICAgc2VnbWVudCArIDUgcGVyaW1ldGVyIHZlcnRleCBhKzFcXG4vLyBXaGVyZSBzZWdtZW50IGlzIHRoZSBudW1iZXIgb2YgdGhlIHJhZGlhbCBzZWdtZW50ICogNiBhbmQgYSBpcyB0aGUgYW5nbGUgYXQgdGhhdCByYWRpYWwgc2VnbWVudC5cXG4vLyBUbyBnbyBmcm9tIGluZGV4IHRvIHNlZ21lbnQsIGZsb29yKGluZGV4IC8gNilcXG4vLyBUbyBnbyBmcm9tIHNlZ21lbnQgdG8gYW5nbGUsIDIqcGkgKiAoc2VnbWVudC9zZWdtZW50Q291bnQpXFxuLy8gVG8gZ28gZnJvbSBpbmRleCB0byBzZWdtZW50IGluZGV4LCBpbmRleCAtIChzZWdtZW50KjYpXFxuLy9cXG52ZWMzIGdldENvbmVQb3NpdGlvbih2ZWMzIGQsIGZsb2F0IGluZGV4LCBmbG9hdCBjb25lT2Zmc2V0LCBvdXQgdmVjMyBub3JtYWwpIHtcXG5cXG4gIGNvbnN0IGZsb2F0IHNlZ21lbnRDb3VudCA9IDguMDtcXG5cXG4gIGluZGV4ID0gbW9kKGluZGV4LCBzZWdtZW50Q291bnQgKiA2LjApO1xcblxcbiAgZmxvYXQgc2VnbWVudCA9IGZsb29yKGluZGV4LzYuMCk7XFxuICBmbG9hdCBzZWdtZW50SW5kZXggPSBpbmRleCAtIChzZWdtZW50KjYuMCk7XFxuXFxuICBub3JtYWwgPSAtbm9ybWFsaXplKGQpO1xcblxcbiAgaWYgKHNlZ21lbnRJbmRleCA9PSAzLjApIHtcXG4gICAgcmV0dXJuIG1peCh2ZWMzKDAuMCksIC1kLCBjb25lT2Zmc2V0KTtcXG4gIH1cXG5cXG4gIC8vIGFuZ2xlID0gMnBpICogKChzZWdtZW50ICsgKChzZWdtZW50SW5kZXggPT0gMS4wIHx8IHNlZ21lbnRJbmRleCA9PSA1LjApID8gMS4wIDogMC4wKSkgLyBzZWdtZW50Q291bnQpXFxuICBmbG9hdCBuZXh0QW5nbGUgPSBmbG9hdChzZWdtZW50SW5kZXggPT0gMS4wIHx8IHNlZ21lbnRJbmRleCA9PSA1LjApO1xcbiAgZmxvYXQgYW5nbGUgPSAyLjAgKiAzLjE0MTU5ICogKChzZWdtZW50ICsgbmV4dEFuZ2xlKSAvIHNlZ21lbnRDb3VudCk7XFxuXFxuICB2ZWMzIHYxID0gbWl4KGQsIHZlYzMoMC4wKSwgY29uZU9mZnNldCk7XFxuICB2ZWMzIHYyID0gdjEgLSBkO1xcblxcbiAgdmVjMyB1ID0gZ2V0T3J0aG9nb25hbFZlY3RvcihkKTtcXG4gIHZlYzMgdiA9IG5vcm1hbGl6ZShjcm9zcyh1LCBkKSk7XFxuXFxuICB2ZWMzIHggPSB1ICogY29zKGFuZ2xlKSAqIGxlbmd0aChkKSowLjI1O1xcbiAgdmVjMyB5ID0gdiAqIHNpbihhbmdsZSkgKiBsZW5ndGgoZCkqMC4yNTtcXG4gIHZlYzMgdjMgPSB2MiArIHggKyB5O1xcbiAgaWYgKHNlZ21lbnRJbmRleCA8PSAyLjApIHtcXG4gICAgdmVjMyB0eCA9IHUgKiBzaW4oYW5nbGUpO1xcbiAgICB2ZWMzIHR5ID0gdiAqIC1jb3MoYW5nbGUpO1xcbiAgICB2ZWMzIHRhbmdlbnQgPSB0eCArIHR5O1xcbiAgICBub3JtYWwgPSBub3JtYWxpemUoY3Jvc3ModjMgLSB2MSwgdGFuZ2VudCkpO1xcbiAgfVxcblxcbiAgaWYgKHNlZ21lbnRJbmRleCA9PSAwLjApIHtcXG4gICAgcmV0dXJuIG1peChkLCB2ZWMzKDAuMCksIGNvbmVPZmZzZXQpO1xcbiAgfVxcbiAgcmV0dXJuIHYzO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjMyB2ZWN0b3I7XFxuYXR0cmlidXRlIHZlYzQgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcblxcbnVuaWZvcm0gZmxvYXQgdmVjdG9yU2NhbGU7XFxudW5pZm9ybSBmbG9hdCBjb25lU2NhbGU7XFxudW5pZm9ybSBmbG9hdCBjb25lT2Zmc2V0O1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgbm9ybWFsO1xcbiAgdmVjMyBYWVogPSBnZXRDb25lUG9zaXRpb24obWF0Myhtb2RlbCkgKiAoKHZlY3RvclNjYWxlICogY29uZVNjYWxlKSAqIHZlY3RvciksIHBvc2l0aW9uLncsIGNvbmVPZmZzZXQsIG5vcm1hbCk7XFxuICB2ZWM0IGNvbmVQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbi54eXosIDEuMCkgKyB2ZWM0KFhZWiwgMC4wKTtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBjb25lUG9zaXRpb247XFxuICBmX2lkICAgICAgICA9IGlkO1xcbiAgZl9wb3NpdGlvbiAgPSBwb3NpdGlvbi54eXo7XFxufVxcblwiXSlcclxudmFyIHBpY2tGcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyAgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHBpY2tJZDtcXG5cXG52YXJ5aW5nIHZlYzMgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9pZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX3Bvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQocGlja0lkLCBmX2lkLnh5eik7XFxufVwiXSlcclxuXHJcbmV4cG9ydHMubWVzaFNoYWRlciA9IHtcclxuICB2ZXJ0ZXg6ICAgdHJpVmVydFNyYyxcclxuICBmcmFnbWVudDogdHJpRnJhZ1NyYyxcclxuICBhdHRyaWJ1dGVzOiBbXHJcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfSxcclxuICAgIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9LFxyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWMyJ30sXHJcbiAgICB7bmFtZTogJ3ZlY3RvcicsIHR5cGU6ICd2ZWMzJ31cclxuICBdXHJcbn1cclxuZXhwb3J0cy5waWNrU2hhZGVyID0ge1xyXG4gIHZlcnRleDogICBwaWNrVmVydFNyYyxcclxuICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAndmVjdG9yJywgdHlwZTogJ3ZlYzMnfVxyXG4gIF1cclxufVxyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgMDogJ05PTkUnLFxuICAxOiAnT05FJyxcbiAgMjogJ0xJTkVfTE9PUCcsXG4gIDM6ICdMSU5FX1NUUklQJyxcbiAgNDogJ1RSSUFOR0xFUycsXG4gIDU6ICdUUklBTkdMRV9TVFJJUCcsXG4gIDY6ICdUUklBTkdMRV9GQU4nLFxuICAyNTY6ICdERVBUSF9CVUZGRVJfQklUJyxcbiAgNTEyOiAnTkVWRVInLFxuICA1MTM6ICdMRVNTJyxcbiAgNTE0OiAnRVFVQUwnLFxuICA1MTU6ICdMRVFVQUwnLFxuICA1MTY6ICdHUkVBVEVSJyxcbiAgNTE3OiAnTk9URVFVQUwnLFxuICA1MTg6ICdHRVFVQUwnLFxuICA1MTk6ICdBTFdBWVMnLFxuICA3Njg6ICdTUkNfQ09MT1InLFxuICA3Njk6ICdPTkVfTUlOVVNfU1JDX0NPTE9SJyxcbiAgNzcwOiAnU1JDX0FMUEhBJyxcbiAgNzcxOiAnT05FX01JTlVTX1NSQ19BTFBIQScsXG4gIDc3MjogJ0RTVF9BTFBIQScsXG4gIDc3MzogJ09ORV9NSU5VU19EU1RfQUxQSEEnLFxuICA3NzQ6ICdEU1RfQ09MT1InLFxuICA3NzU6ICdPTkVfTUlOVVNfRFNUX0NPTE9SJyxcbiAgNzc2OiAnU1JDX0FMUEhBX1NBVFVSQVRFJyxcbiAgMTAyNDogJ1NURU5DSUxfQlVGRkVSX0JJVCcsXG4gIDEwMjg6ICdGUk9OVCcsXG4gIDEwMjk6ICdCQUNLJyxcbiAgMTAzMjogJ0ZST05UX0FORF9CQUNLJyxcbiAgMTI4MDogJ0lOVkFMSURfRU5VTScsXG4gIDEyODE6ICdJTlZBTElEX1ZBTFVFJyxcbiAgMTI4MjogJ0lOVkFMSURfT1BFUkFUSU9OJyxcbiAgMTI4NTogJ09VVF9PRl9NRU1PUlknLFxuICAxMjg2OiAnSU5WQUxJRF9GUkFNRUJVRkZFUl9PUEVSQVRJT04nLFxuICAyMzA0OiAnQ1cnLFxuICAyMzA1OiAnQ0NXJyxcbiAgMjg0OTogJ0xJTkVfV0lEVEgnLFxuICAyODg0OiAnQ1VMTF9GQUNFJyxcbiAgMjg4NTogJ0NVTExfRkFDRV9NT0RFJyxcbiAgMjg4NjogJ0ZST05UX0ZBQ0UnLFxuICAyOTI4OiAnREVQVEhfUkFOR0UnLFxuICAyOTI5OiAnREVQVEhfVEVTVCcsXG4gIDI5MzA6ICdERVBUSF9XUklURU1BU0snLFxuICAyOTMxOiAnREVQVEhfQ0xFQVJfVkFMVUUnLFxuICAyOTMyOiAnREVQVEhfRlVOQycsXG4gIDI5NjA6ICdTVEVOQ0lMX1RFU1QnLFxuICAyOTYxOiAnU1RFTkNJTF9DTEVBUl9WQUxVRScsXG4gIDI5NjI6ICdTVEVOQ0lMX0ZVTkMnLFxuICAyOTYzOiAnU1RFTkNJTF9WQUxVRV9NQVNLJyxcbiAgMjk2NDogJ1NURU5DSUxfRkFJTCcsXG4gIDI5NjU6ICdTVEVOQ0lMX1BBU1NfREVQVEhfRkFJTCcsXG4gIDI5NjY6ICdTVEVOQ0lMX1BBU1NfREVQVEhfUEFTUycsXG4gIDI5Njc6ICdTVEVOQ0lMX1JFRicsXG4gIDI5Njg6ICdTVEVOQ0lMX1dSSVRFTUFTSycsXG4gIDI5Nzg6ICdWSUVXUE9SVCcsXG4gIDMwMjQ6ICdESVRIRVInLFxuICAzMDQyOiAnQkxFTkQnLFxuICAzMDg4OiAnU0NJU1NPUl9CT1gnLFxuICAzMDg5OiAnU0NJU1NPUl9URVNUJyxcbiAgMzEwNjogJ0NPTE9SX0NMRUFSX1ZBTFVFJyxcbiAgMzEwNzogJ0NPTE9SX1dSSVRFTUFTSycsXG4gIDMzMTc6ICdVTlBBQ0tfQUxJR05NRU5UJyxcbiAgMzMzMzogJ1BBQ0tfQUxJR05NRU5UJyxcbiAgMzM3OTogJ01BWF9URVhUVVJFX1NJWkUnLFxuICAzMzg2OiAnTUFYX1ZJRVdQT1JUX0RJTVMnLFxuICAzNDA4OiAnU1VCUElYRUxfQklUUycsXG4gIDM0MTA6ICdSRURfQklUUycsXG4gIDM0MTE6ICdHUkVFTl9CSVRTJyxcbiAgMzQxMjogJ0JMVUVfQklUUycsXG4gIDM0MTM6ICdBTFBIQV9CSVRTJyxcbiAgMzQxNDogJ0RFUFRIX0JJVFMnLFxuICAzNDE1OiAnU1RFTkNJTF9CSVRTJyxcbiAgMzU1MzogJ1RFWFRVUkVfMkQnLFxuICA0MzUyOiAnRE9OVF9DQVJFJyxcbiAgNDM1MzogJ0ZBU1RFU1QnLFxuICA0MzU0OiAnTklDRVNUJyxcbiAgNTEyMDogJ0JZVEUnLFxuICA1MTIxOiAnVU5TSUdORURfQllURScsXG4gIDUxMjI6ICdTSE9SVCcsXG4gIDUxMjM6ICdVTlNJR05FRF9TSE9SVCcsXG4gIDUxMjQ6ICdJTlQnLFxuICA1MTI1OiAnVU5TSUdORURfSU5UJyxcbiAgNTEyNjogJ0ZMT0FUJyxcbiAgNTM4NjogJ0lOVkVSVCcsXG4gIDU4OTA6ICdURVhUVVJFJyxcbiAgNjQwMTogJ1NURU5DSUxfSU5ERVgnLFxuICA2NDAyOiAnREVQVEhfQ09NUE9ORU5UJyxcbiAgNjQwNjogJ0FMUEhBJyxcbiAgNjQwNzogJ1JHQicsXG4gIDY0MDg6ICdSR0JBJyxcbiAgNjQwOTogJ0xVTUlOQU5DRScsXG4gIDY0MTA6ICdMVU1JTkFOQ0VfQUxQSEEnLFxuICA3NjgwOiAnS0VFUCcsXG4gIDc2ODE6ICdSRVBMQUNFJyxcbiAgNzY4MjogJ0lOQ1InLFxuICA3NjgzOiAnREVDUicsXG4gIDc5MzY6ICdWRU5ET1InLFxuICA3OTM3OiAnUkVOREVSRVInLFxuICA3OTM4OiAnVkVSU0lPTicsXG4gIDk3Mjg6ICdORUFSRVNUJyxcbiAgOTcyOTogJ0xJTkVBUicsXG4gIDk5ODQ6ICdORUFSRVNUX01JUE1BUF9ORUFSRVNUJyxcbiAgOTk4NTogJ0xJTkVBUl9NSVBNQVBfTkVBUkVTVCcsXG4gIDk5ODY6ICdORUFSRVNUX01JUE1BUF9MSU5FQVInLFxuICA5OTg3OiAnTElORUFSX01JUE1BUF9MSU5FQVInLFxuICAxMDI0MDogJ1RFWFRVUkVfTUFHX0ZJTFRFUicsXG4gIDEwMjQxOiAnVEVYVFVSRV9NSU5fRklMVEVSJyxcbiAgMTAyNDI6ICdURVhUVVJFX1dSQVBfUycsXG4gIDEwMjQzOiAnVEVYVFVSRV9XUkFQX1QnLFxuICAxMDQ5NzogJ1JFUEVBVCcsXG4gIDEwNzUyOiAnUE9MWUdPTl9PRkZTRVRfVU5JVFMnLFxuICAxNjM4NDogJ0NPTE9SX0JVRkZFUl9CSVQnLFxuICAzMjc2OTogJ0NPTlNUQU5UX0NPTE9SJyxcbiAgMzI3NzA6ICdPTkVfTUlOVVNfQ09OU1RBTlRfQ09MT1InLFxuICAzMjc3MTogJ0NPTlNUQU5UX0FMUEhBJyxcbiAgMzI3NzI6ICdPTkVfTUlOVVNfQ09OU1RBTlRfQUxQSEEnLFxuICAzMjc3MzogJ0JMRU5EX0NPTE9SJyxcbiAgMzI3NzQ6ICdGVU5DX0FERCcsXG4gIDMyNzc3OiAnQkxFTkRfRVFVQVRJT05fUkdCJyxcbiAgMzI3Nzg6ICdGVU5DX1NVQlRSQUNUJyxcbiAgMzI3Nzk6ICdGVU5DX1JFVkVSU0VfU1VCVFJBQ1QnLFxuICAzMjgxOTogJ1VOU0lHTkVEX1NIT1JUXzRfNF80XzQnLFxuICAzMjgyMDogJ1VOU0lHTkVEX1NIT1JUXzVfNV81XzEnLFxuICAzMjgyMzogJ1BPTFlHT05fT0ZGU0VUX0ZJTEwnLFxuICAzMjgyNDogJ1BPTFlHT05fT0ZGU0VUX0ZBQ1RPUicsXG4gIDMyODU0OiAnUkdCQTQnLFxuICAzMjg1NTogJ1JHQjVfQTEnLFxuICAzMjg3MzogJ1RFWFRVUkVfQklORElOR18yRCcsXG4gIDMyOTI2OiAnU0FNUExFX0FMUEhBX1RPX0NPVkVSQUdFJyxcbiAgMzI5Mjg6ICdTQU1QTEVfQ09WRVJBR0UnLFxuICAzMjkzNjogJ1NBTVBMRV9CVUZGRVJTJyxcbiAgMzI5Mzc6ICdTQU1QTEVTJyxcbiAgMzI5Mzg6ICdTQU1QTEVfQ09WRVJBR0VfVkFMVUUnLFxuICAzMjkzOTogJ1NBTVBMRV9DT1ZFUkFHRV9JTlZFUlQnLFxuICAzMjk2ODogJ0JMRU5EX0RTVF9SR0InLFxuICAzMjk2OTogJ0JMRU5EX1NSQ19SR0InLFxuICAzMjk3MDogJ0JMRU5EX0RTVF9BTFBIQScsXG4gIDMyOTcxOiAnQkxFTkRfU1JDX0FMUEhBJyxcbiAgMzMwNzE6ICdDTEFNUF9UT19FREdFJyxcbiAgMzMxNzA6ICdHRU5FUkFURV9NSVBNQVBfSElOVCcsXG4gIDMzMTg5OiAnREVQVEhfQ09NUE9ORU5UMTYnLFxuICAzMzMwNjogJ0RFUFRIX1NURU5DSUxfQVRUQUNITUVOVCcsXG4gIDMzNjM1OiAnVU5TSUdORURfU0hPUlRfNV82XzUnLFxuICAzMzY0ODogJ01JUlJPUkVEX1JFUEVBVCcsXG4gIDMzOTAxOiAnQUxJQVNFRF9QT0lOVF9TSVpFX1JBTkdFJyxcbiAgMzM5MDI6ICdBTElBU0VEX0xJTkVfV0lEVEhfUkFOR0UnLFxuICAzMzk4NDogJ1RFWFRVUkUwJyxcbiAgMzM5ODU6ICdURVhUVVJFMScsXG4gIDMzOTg2OiAnVEVYVFVSRTInLFxuICAzMzk4NzogJ1RFWFRVUkUzJyxcbiAgMzM5ODg6ICdURVhUVVJFNCcsXG4gIDMzOTg5OiAnVEVYVFVSRTUnLFxuICAzMzk5MDogJ1RFWFRVUkU2JyxcbiAgMzM5OTE6ICdURVhUVVJFNycsXG4gIDMzOTkyOiAnVEVYVFVSRTgnLFxuICAzMzk5MzogJ1RFWFRVUkU5JyxcbiAgMzM5OTQ6ICdURVhUVVJFMTAnLFxuICAzMzk5NTogJ1RFWFRVUkUxMScsXG4gIDMzOTk2OiAnVEVYVFVSRTEyJyxcbiAgMzM5OTc6ICdURVhUVVJFMTMnLFxuICAzMzk5ODogJ1RFWFRVUkUxNCcsXG4gIDMzOTk5OiAnVEVYVFVSRTE1JyxcbiAgMzQwMDA6ICdURVhUVVJFMTYnLFxuICAzNDAwMTogJ1RFWFRVUkUxNycsXG4gIDM0MDAyOiAnVEVYVFVSRTE4JyxcbiAgMzQwMDM6ICdURVhUVVJFMTknLFxuICAzNDAwNDogJ1RFWFRVUkUyMCcsXG4gIDM0MDA1OiAnVEVYVFVSRTIxJyxcbiAgMzQwMDY6ICdURVhUVVJFMjInLFxuICAzNDAwNzogJ1RFWFRVUkUyMycsXG4gIDM0MDA4OiAnVEVYVFVSRTI0JyxcbiAgMzQwMDk6ICdURVhUVVJFMjUnLFxuICAzNDAxMDogJ1RFWFRVUkUyNicsXG4gIDM0MDExOiAnVEVYVFVSRTI3JyxcbiAgMzQwMTI6ICdURVhUVVJFMjgnLFxuICAzNDAxMzogJ1RFWFRVUkUyOScsXG4gIDM0MDE0OiAnVEVYVFVSRTMwJyxcbiAgMzQwMTU6ICdURVhUVVJFMzEnLFxuICAzNDAxNjogJ0FDVElWRV9URVhUVVJFJyxcbiAgMzQwMjQ6ICdNQVhfUkVOREVSQlVGRkVSX1NJWkUnLFxuICAzNDA0MTogJ0RFUFRIX1NURU5DSUwnLFxuICAzNDA1NTogJ0lOQ1JfV1JBUCcsXG4gIDM0MDU2OiAnREVDUl9XUkFQJyxcbiAgMzQwNjc6ICdURVhUVVJFX0NVQkVfTUFQJyxcbiAgMzQwNjg6ICdURVhUVVJFX0JJTkRJTkdfQ1VCRV9NQVAnLFxuICAzNDA2OTogJ1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCcsXG4gIDM0MDcwOiAnVEVYVFVSRV9DVUJFX01BUF9ORUdBVElWRV9YJyxcbiAgMzQwNzE6ICdURVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1knLFxuICAzNDA3MjogJ1RFWFRVUkVfQ1VCRV9NQVBfTkVHQVRJVkVfWScsXG4gIDM0MDczOiAnVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9aJyxcbiAgMzQwNzQ6ICdURVhUVVJFX0NVQkVfTUFQX05FR0FUSVZFX1onLFxuICAzNDA3NjogJ01BWF9DVUJFX01BUF9URVhUVVJFX1NJWkUnLFxuICAzNDMzODogJ1ZFUlRFWF9BVFRSSUJfQVJSQVlfRU5BQkxFRCcsXG4gIDM0MzM5OiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9TSVpFJyxcbiAgMzQzNDA6ICdWRVJURVhfQVRUUklCX0FSUkFZX1NUUklERScsXG4gIDM0MzQxOiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9UWVBFJyxcbiAgMzQzNDI6ICdDVVJSRU5UX1ZFUlRFWF9BVFRSSUInLFxuICAzNDM3MzogJ1ZFUlRFWF9BVFRSSUJfQVJSQVlfUE9JTlRFUicsXG4gIDM0NDY2OiAnTlVNX0NPTVBSRVNTRURfVEVYVFVSRV9GT1JNQVRTJyxcbiAgMzQ0Njc6ICdDT01QUkVTU0VEX1RFWFRVUkVfRk9STUFUUycsXG4gIDM0NjYwOiAnQlVGRkVSX1NJWkUnLFxuICAzNDY2MTogJ0JVRkZFUl9VU0FHRScsXG4gIDM0ODE2OiAnU1RFTkNJTF9CQUNLX0ZVTkMnLFxuICAzNDgxNzogJ1NURU5DSUxfQkFDS19GQUlMJyxcbiAgMzQ4MTg6ICdTVEVOQ0lMX0JBQ0tfUEFTU19ERVBUSF9GQUlMJyxcbiAgMzQ4MTk6ICdTVEVOQ0lMX0JBQ0tfUEFTU19ERVBUSF9QQVNTJyxcbiAgMzQ4Nzc6ICdCTEVORF9FUVVBVElPTl9BTFBIQScsXG4gIDM0OTIxOiAnTUFYX1ZFUlRFWF9BVFRSSUJTJyxcbiAgMzQ5MjI6ICdWRVJURVhfQVRUUklCX0FSUkFZX05PUk1BTElaRUQnLFxuICAzNDkzMDogJ01BWF9URVhUVVJFX0lNQUdFX1VOSVRTJyxcbiAgMzQ5NjI6ICdBUlJBWV9CVUZGRVInLFxuICAzNDk2MzogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcbiAgMzQ5NjQ6ICdBUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM0OTY1OiAnRUxFTUVOVF9BUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM0OTc1OiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM1MDQwOiAnU1RSRUFNX0RSQVcnLFxuICAzNTA0NDogJ1NUQVRJQ19EUkFXJyxcbiAgMzUwNDg6ICdEWU5BTUlDX0RSQVcnLFxuICAzNTYzMjogJ0ZSQUdNRU5UX1NIQURFUicsXG4gIDM1NjMzOiAnVkVSVEVYX1NIQURFUicsXG4gIDM1NjYwOiAnTUFYX1ZFUlRFWF9URVhUVVJFX0lNQUdFX1VOSVRTJyxcbiAgMzU2NjE6ICdNQVhfQ09NQklORURfVEVYVFVSRV9JTUFHRV9VTklUUycsXG4gIDM1NjYzOiAnU0hBREVSX1RZUEUnLFxuICAzNTY2NDogJ0ZMT0FUX1ZFQzInLFxuICAzNTY2NTogJ0ZMT0FUX1ZFQzMnLFxuICAzNTY2NjogJ0ZMT0FUX1ZFQzQnLFxuICAzNTY2NzogJ0lOVF9WRUMyJyxcbiAgMzU2Njg6ICdJTlRfVkVDMycsXG4gIDM1NjY5OiAnSU5UX1ZFQzQnLFxuICAzNTY3MDogJ0JPT0wnLFxuICAzNTY3MTogJ0JPT0xfVkVDMicsXG4gIDM1NjcyOiAnQk9PTF9WRUMzJyxcbiAgMzU2NzM6ICdCT09MX1ZFQzQnLFxuICAzNTY3NDogJ0ZMT0FUX01BVDInLFxuICAzNTY3NTogJ0ZMT0FUX01BVDMnLFxuICAzNTY3NjogJ0ZMT0FUX01BVDQnLFxuICAzNTY3ODogJ1NBTVBMRVJfMkQnLFxuICAzNTY4MDogJ1NBTVBMRVJfQ1VCRScsXG4gIDM1NzEyOiAnREVMRVRFX1NUQVRVUycsXG4gIDM1NzEzOiAnQ09NUElMRV9TVEFUVVMnLFxuICAzNTcxNDogJ0xJTktfU1RBVFVTJyxcbiAgMzU3MTU6ICdWQUxJREFURV9TVEFUVVMnLFxuICAzNTcxNjogJ0lORk9fTE9HX0xFTkdUSCcsXG4gIDM1NzE3OiAnQVRUQUNIRURfU0hBREVSUycsXG4gIDM1NzE4OiAnQUNUSVZFX1VOSUZPUk1TJyxcbiAgMzU3MTk6ICdBQ1RJVkVfVU5JRk9STV9NQVhfTEVOR1RIJyxcbiAgMzU3MjA6ICdTSEFERVJfU09VUkNFX0xFTkdUSCcsXG4gIDM1NzIxOiAnQUNUSVZFX0FUVFJJQlVURVMnLFxuICAzNTcyMjogJ0FDVElWRV9BVFRSSUJVVEVfTUFYX0xFTkdUSCcsXG4gIDM1NzI0OiAnU0hBRElOR19MQU5HVUFHRV9WRVJTSU9OJyxcbiAgMzU3MjU6ICdDVVJSRU5UX1BST0dSQU0nLFxuICAzNjAwMzogJ1NURU5DSUxfQkFDS19SRUYnLFxuICAzNjAwNDogJ1NURU5DSUxfQkFDS19WQUxVRV9NQVNLJyxcbiAgMzYwMDU6ICdTVEVOQ0lMX0JBQ0tfV1JJVEVNQVNLJyxcbiAgMzYwMDY6ICdGUkFNRUJVRkZFUl9CSU5ESU5HJyxcbiAgMzYwMDc6ICdSRU5ERVJCVUZGRVJfQklORElORycsXG4gIDM2MDQ4OiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfVFlQRScsXG4gIDM2MDQ5OiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfTkFNRScsXG4gIDM2MDUwOiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9URVhUVVJFX0xFVkVMJyxcbiAgMzYwNTE6ICdGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX1RFWFRVUkVfQ1VCRV9NQVBfRkFDRScsXG4gIDM2MDUzOiAnRlJBTUVCVUZGRVJfQ09NUExFVEUnLFxuICAzNjA1NDogJ0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVCcsXG4gIDM2MDU1OiAnRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlQnLFxuICAzNjA1NzogJ0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OUycsXG4gIDM2MDYxOiAnRlJBTUVCVUZGRVJfVU5TVVBQT1JURUQnLFxuICAzNjA2NDogJ0NPTE9SX0FUVEFDSE1FTlQwJyxcbiAgMzYwOTY6ICdERVBUSF9BVFRBQ0hNRU5UJyxcbiAgMzYxMjg6ICdTVEVOQ0lMX0FUVEFDSE1FTlQnLFxuICAzNjE2MDogJ0ZSQU1FQlVGRkVSJyxcbiAgMzYxNjE6ICdSRU5ERVJCVUZGRVInLFxuICAzNjE2MjogJ1JFTkRFUkJVRkZFUl9XSURUSCcsXG4gIDM2MTYzOiAnUkVOREVSQlVGRkVSX0hFSUdIVCcsXG4gIDM2MTY0OiAnUkVOREVSQlVGRkVSX0lOVEVSTkFMX0ZPUk1BVCcsXG4gIDM2MTY4OiAnU1RFTkNJTF9JTkRFWDgnLFxuICAzNjE3NjogJ1JFTkRFUkJVRkZFUl9SRURfU0laRScsXG4gIDM2MTc3OiAnUkVOREVSQlVGRkVSX0dSRUVOX1NJWkUnLFxuICAzNjE3ODogJ1JFTkRFUkJVRkZFUl9CTFVFX1NJWkUnLFxuICAzNjE3OTogJ1JFTkRFUkJVRkZFUl9BTFBIQV9TSVpFJyxcbiAgMzYxODA6ICdSRU5ERVJCVUZGRVJfREVQVEhfU0laRScsXG4gIDM2MTgxOiAnUkVOREVSQlVGRkVSX1NURU5DSUxfU0laRScsXG4gIDM2MTk0OiAnUkdCNTY1JyxcbiAgMzYzMzY6ICdMT1dfRkxPQVQnLFxuICAzNjMzNzogJ01FRElVTV9GTE9BVCcsXG4gIDM2MzM4OiAnSElHSF9GTE9BVCcsXG4gIDM2MzM5OiAnTE9XX0lOVCcsXG4gIDM2MzQwOiAnTUVESVVNX0lOVCcsXG4gIDM2MzQxOiAnSElHSF9JTlQnLFxuICAzNjM0NjogJ1NIQURFUl9DT01QSUxFUicsXG4gIDM2MzQ3OiAnTUFYX1ZFUlRFWF9VTklGT1JNX1ZFQ1RPUlMnLFxuICAzNjM0ODogJ01BWF9WQVJZSU5HX1ZFQ1RPUlMnLFxuICAzNjM0OTogJ01BWF9GUkFHTUVOVF9VTklGT1JNX1ZFQ1RPUlMnLFxuICAzNzQ0MDogJ1VOUEFDS19GTElQX1lfV0VCR0wnLFxuICAzNzQ0MTogJ1VOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCcsXG4gIDM3NDQyOiAnQ09OVEVYVF9MT1NUX1dFQkdMJyxcbiAgMzc0NDM6ICdVTlBBQ0tfQ09MT1JTUEFDRV9DT05WRVJTSU9OX1dFQkdMJyxcbiAgMzc0NDQ6ICdCUk9XU0VSX0RFRkFVTFRfV0VCR0wnXG59XG4iLCJ2YXIgZ2wxMCA9IHJlcXVpcmUoJy4vMS4wL251bWJlcnMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGxvb2t1cENvbnN0YW50IChudW1iZXIpIHtcbiAgcmV0dXJuIGdsMTBbbnVtYmVyXVxufVxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVycm9yQmFyc1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciAgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG52YXIgY3JlYXRlVkFPICAgICA9IHJlcXVpcmUoJ2dsLXZhbycpXHJcbnZhciBjcmVhdGVTaGFkZXIgID0gcmVxdWlyZSgnLi9zaGFkZXJzL2luZGV4JylcclxuXHJcbnZhciBJREVOVElUWSA9IFsxLDAsMCwwLFxyXG4gICAgICAgICAgICAgICAgMCwxLDAsMCxcclxuICAgICAgICAgICAgICAgIDAsMCwxLDAsXHJcbiAgICAgICAgICAgICAgICAwLDAsMCwxXVxyXG5cclxuZnVuY3Rpb24gRXJyb3JCYXJzKGdsLCBidWZmZXIsIHZhbywgc2hhZGVyKSB7XHJcbiAgdGhpcy5nbCAgICAgICAgICAgPSBnbFxyXG4gIHRoaXMuc2hhZGVyICAgICAgID0gc2hhZGVyXHJcbiAgdGhpcy5idWZmZXIgICAgICAgPSBidWZmZXJcclxuICB0aGlzLnZhbyAgICAgICAgICA9IHZhb1xyXG4gIHRoaXMucGl4ZWxSYXRpbyAgID0gMVxyXG4gIHRoaXMuYm91bmRzICAgICAgID0gW1sgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0sIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXHJcbiAgdGhpcy5jbGlwQm91bmRzICAgPSBbWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSwgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV1cclxuICB0aGlzLmxpbmVXaWR0aCAgICA9IFsxLDEsMV1cclxuICB0aGlzLmNhcFNpemUgICAgICA9IFsxMCwxMCwxMF1cclxuICB0aGlzLmxpbmVDb3VudCAgICA9IFswLDAsMF1cclxuICB0aGlzLmxpbmVPZmZzZXQgICA9IFswLDAsMF1cclxuICB0aGlzLm9wYWNpdHkgICAgICA9IDFcclxufVxyXG5cclxudmFyIHByb3RvID0gRXJyb3JCYXJzLnByb3RvdHlwZVxyXG5cclxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcclxuICByZXR1cm4gdGhpcy5vcGFjaXR5ID49IDFcclxufVxyXG5cclxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKCkge1xyXG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPCAxXHJcbn1cclxuXHJcbnByb3RvLmRyYXdUcmFuc3BhcmVudCA9IHByb3RvLmRyYXcgPSBmdW5jdGlvbihjYW1lcmFQYXJhbXMpIHtcclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcbiAgdmFyIHVuaWZvcm1zICAgICAgICA9IHRoaXMuc2hhZGVyLnVuaWZvcm1zXHJcblxyXG4gIHRoaXMuc2hhZGVyLmJpbmQoKVxyXG4gIHZhciB2aWV3ICAgICAgID0gdW5pZm9ybXMudmlldyAgICAgICA9IGNhbWVyYVBhcmFtcy52aWV3ICAgICAgIHx8IElERU5USVRZXHJcbiAgdmFyIHByb2plY3Rpb24gPSB1bmlmb3Jtcy5wcm9qZWN0aW9uID0gY2FtZXJhUGFyYW1zLnByb2plY3Rpb24gfHwgSURFTlRJVFlcclxuICB1bmlmb3Jtcy5tb2RlbCAgICAgID0gY2FtZXJhUGFyYW1zLm1vZGVsICAgICAgfHwgSURFTlRJVFlcclxuICB1bmlmb3Jtcy5jbGlwQm91bmRzID0gdGhpcy5jbGlwQm91bmRzXHJcbiAgdW5pZm9ybXMub3BhY2l0eSAgICA9IHRoaXMub3BhY2l0eVxyXG5cclxuXHJcbiAgdmFyIGN4ID0gdmlld1sxMl1cclxuICB2YXIgY3kgPSB2aWV3WzEzXVxyXG4gIHZhciBjeiA9IHZpZXdbMTRdXHJcbiAgdmFyIGN3ID0gdmlld1sxNV1cclxuICB2YXIgcGl4ZWxTY2FsZUYgPSB0aGlzLnBpeGVsUmF0aW8gKiAocHJvamVjdGlvblszXSpjeCArIHByb2plY3Rpb25bN10qY3kgKyBwcm9qZWN0aW9uWzExXSpjeiArIHByb2plY3Rpb25bMTVdKmN3KSAvIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcclxuXHJcbiAgdGhpcy52YW8uYmluZCgpXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBnbC5saW5lV2lkdGgodGhpcy5saW5lV2lkdGhbaV0pXHJcbiAgICB1bmlmb3Jtcy5jYXBTaXplID0gdGhpcy5jYXBTaXplW2ldICogcGl4ZWxTY2FsZUZcclxuICAgIGlmICh0aGlzLmxpbmVDb3VudFtpXSkge1xyXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLkxJTkVTLCB0aGlzLmxpbmVPZmZzZXRbaV0sIHRoaXMubGluZUNvdW50W2ldKVxyXG4gICAgfVxyXG4gIH1cclxuICB0aGlzLnZhby51bmJpbmQoKVxyXG59XHJcblxyXG5mdW5jdGlvbiB1cGRhdGVCb3VuZHMoYm91bmRzLCBwb2ludCkge1xyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgYm91bmRzWzBdW2ldID0gTWF0aC5taW4oYm91bmRzWzBdW2ldLCBwb2ludFtpXSlcclxuICAgIGJvdW5kc1sxXVtpXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtpXSwgcG9pbnRbaV0pXHJcbiAgfVxyXG59XHJcblxyXG52YXIgRkFDRV9UQUJMRSA9IChmdW5jdGlvbigpe1xyXG4gIHZhciB0YWJsZSA9IG5ldyBBcnJheSgzKVxyXG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xyXG4gICAgdmFyIHJvdyA9IFtdXHJcbiAgICBmb3IodmFyIGo9MTsgajw9MjsgKytqKSB7XHJcbiAgICAgIGZvcih2YXIgcz0tMTsgczw9MTsgcys9Mikge1xyXG4gICAgICAgIHZhciB1ID0gKGorZCkgJSAzXHJcbiAgICAgICAgdmFyIHkgPSBbMCwwLDBdXHJcbiAgICAgICAgeVt1XSA9IHNcclxuICAgICAgICByb3cucHVzaCh5KVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0YWJsZVtkXSA9IHJvd1xyXG4gIH1cclxuICByZXR1cm4gdGFibGVcclxufSkoKVxyXG5cclxuXHJcbmZ1bmN0aW9uIGVtaXRGYWNlKHZlcnRzLCB4LCBjLCBkKSB7XHJcbiAgdmFyIG9mZnNldHMgPSBGQUNFX1RBQkxFW2RdXHJcbiAgZm9yKHZhciBpPTA7IGk8b2Zmc2V0cy5sZW5ndGg7ICsraSkge1xyXG4gICAgdmFyIG8gPSBvZmZzZXRzW2ldXHJcbiAgICB2ZXJ0cy5wdXNoKHhbMF0sIHhbMV0sIHhbMl0sXHJcbiAgICAgICAgICAgICAgIGNbMF0sIGNbMV0sIGNbMl0sIGNbM10sXHJcbiAgICAgICAgICAgICAgIG9bMF0sIG9bMV0sIG9bMl0pXHJcbiAgfVxyXG4gIHJldHVybiBvZmZzZXRzLmxlbmd0aFxyXG59XHJcblxyXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XHJcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cclxuXHJcbiAgaWYoJ2xpbmVXaWR0aCcgaW4gb3B0aW9ucykge1xyXG4gICAgdGhpcy5saW5lV2lkdGggPSBvcHRpb25zLmxpbmVXaWR0aFxyXG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGhpcy5saW5lV2lkdGgpKSB7XHJcbiAgICAgIHRoaXMubGluZVdpZHRoID0gW3RoaXMubGluZVdpZHRoLCB0aGlzLmxpbmVXaWR0aCwgdGhpcy5saW5lV2lkdGhdXHJcbiAgICB9XHJcbiAgfVxyXG4gIGlmKCdjYXBTaXplJyBpbiBvcHRpb25zKSB7XHJcbiAgICB0aGlzLmNhcFNpemUgPSBvcHRpb25zLmNhcFNpemVcclxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRoaXMuY2FwU2l6ZSkpIHtcclxuICAgICAgdGhpcy5jYXBTaXplID0gW3RoaXMuY2FwU2l6ZSwgdGhpcy5jYXBTaXplLCB0aGlzLmNhcFNpemVdXHJcbiAgICB9XHJcbiAgfVxyXG4gIGlmKCdvcGFjaXR5JyBpbiBvcHRpb25zKSB7XHJcbiAgICB0aGlzLm9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHlcclxuICB9XHJcblxyXG4gIHZhciBjb2xvciAgICA9IG9wdGlvbnMuY29sb3IgfHwgW1swLDAsMF0sWzAsMCwwXSxbMCwwLDBdXVxyXG4gIHZhciBwb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb25cclxuICB2YXIgZXJyb3IgICAgPSBvcHRpb25zLmVycm9yXHJcbiAgaWYoIUFycmF5LmlzQXJyYXkoY29sb3JbMF0pKSB7XHJcbiAgICBjb2xvciA9IFtjb2xvcixjb2xvcixjb2xvcl1cclxuICB9XHJcblxyXG4gIGlmKHBvc2l0aW9uICYmIGVycm9yKSB7XHJcblxyXG4gICAgdmFyIHZlcnRzICAgICAgID0gW11cclxuICAgIHZhciBuICAgICAgICAgICA9IHBvc2l0aW9uLmxlbmd0aFxyXG4gICAgdmFyIHZlcnRleENvdW50ID0gMFxyXG4gICAgdGhpcy5ib3VuZHMgICAgID0gW1sgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XV1cclxuICAgIHRoaXMubGluZUNvdW50ICA9IFswLDAsMF1cclxuXHJcbiAgICAvL0J1aWxkIGdlb21ldHJ5IGZvciBsaW5lc1xyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHRoaXMubGluZU9mZnNldFtqXSA9IHZlcnRleENvdW50XHJcblxyXG5pX2xvb3A6XHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xyXG4gICAgICAgIHZhciBwID0gcG9zaXRpb25baV1cclxuXHJcbiAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcclxuICAgICAgICAgICAgY29udGludWUgaV9sb29wXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2YXIgZSA9IGVycm9yW2ldXHJcbiAgICAgICAgdmFyIGMgPSBjb2xvcltqXVxyXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY1swXSkpIHtcclxuICAgICAgICAgIGMgPSBjb2xvcltpXVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xyXG4gICAgICAgICAgYyA9IFtjWzBdLCBjWzFdLCBjWzJdLCAxXVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZihpc05hTihlWzBdW2pdKSB8fCBpc05hTihlWzFdW2pdKSkge1xyXG4gICAgICAgICAgY29udGludWVcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYoZVswXVtqXSA8IDApIHtcclxuICAgICAgICAgIHZhciB4ID0gcC5zbGljZSgpXHJcbiAgICAgICAgICB4W2pdICs9IGVbMF1bal1cclxuICAgICAgICAgIHZlcnRzLnB1c2gocFswXSwgcFsxXSwgcFsyXSxcclxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgICAgMCwgICAgMCxcclxuICAgICAgICAgICAgICAgICAgICAgeFswXSwgeFsxXSwgeFsyXSxcclxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgICAgMCwgICAgMClcclxuICAgICAgICAgIHVwZGF0ZUJvdW5kcyh0aGlzLmJvdW5kcywgeClcclxuICAgICAgICAgIHZlcnRleENvdW50ICs9IDIgKyBlbWl0RmFjZSh2ZXJ0cywgeCwgYywgailcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYoZVsxXVtqXSA+IDApIHtcclxuICAgICAgICAgIHZhciB4ID0gcC5zbGljZSgpXHJcbiAgICAgICAgICB4W2pdICs9IGVbMV1bal1cclxuICAgICAgICAgIHZlcnRzLnB1c2gocFswXSwgcFsxXSwgcFsyXSxcclxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgICAgMCwgICAgMCxcclxuICAgICAgICAgICAgICAgICAgICAgeFswXSwgeFsxXSwgeFsyXSxcclxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgICAgMCwgICAgMClcclxuICAgICAgICAgIHVwZGF0ZUJvdW5kcyh0aGlzLmJvdW5kcywgeClcclxuICAgICAgICAgIHZlcnRleENvdW50ICs9IDIgKyBlbWl0RmFjZSh2ZXJ0cywgeCwgYywgailcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5saW5lQ291bnRbal0gPSB2ZXJ0ZXhDb3VudCAtIHRoaXMubGluZU9mZnNldFtqXVxyXG4gICAgfVxyXG4gICAgdGhpcy5idWZmZXIudXBkYXRlKHZlcnRzKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMuYnVmZmVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMudmFvLmRpc3Bvc2UoKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVFcnJvckJhcnMob3B0aW9ucykge1xyXG4gIHZhciBnbCA9IG9wdGlvbnMuZ2xcclxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgICAge1xyXG4gICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgICAgIHR5cGU6ICAgZ2wuRkxPQVQsXHJcbiAgICAgICAgc2l6ZTogICAzLFxyXG4gICAgICAgIG9mZnNldDogMCxcclxuICAgICAgICBzdHJpZGU6IDQwXHJcbiAgICAgIH0sXHJcbiAgICAgIHtcclxuICAgICAgICBidWZmZXI6IGJ1ZmZlcixcclxuICAgICAgICB0eXBlOiAgIGdsLkZMT0FULFxyXG4gICAgICAgIHNpemU6ICAgNCxcclxuICAgICAgICBvZmZzZXQ6IDEyLFxyXG4gICAgICAgIHN0cmlkZTogNDBcclxuICAgICAgfSxcclxuICAgICAge1xyXG4gICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgICAgIHR5cGU6ICAgZ2wuRkxPQVQsXHJcbiAgICAgICAgc2l6ZTogICAzLFxyXG4gICAgICAgIG9mZnNldDogMjgsXHJcbiAgICAgICAgc3RyaWRlOiA0MFxyXG4gICAgICB9XHJcbiAgICBdKVxyXG5cclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uICAgID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm9mZnNldC5sb2NhdGlvbiAgID0gMlxyXG5cclxuICB2YXIgcmVzdWx0ID0gbmV3IEVycm9yQmFycyhnbCwgYnVmZmVyLCB2YW8sIHNoYWRlcilcclxuICByZXN1bHQudXBkYXRlKG9wdGlvbnMpXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGdsc2xpZnkgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcblxyXG52YXIgdmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbiwgb2Zmc2V0O1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG51bmlmb3JtIGZsb2F0IGNhcFNpemU7XFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG52YXJ5aW5nIHZlYzMgZnJhZ1Bvc2l0aW9uO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzQgd29ybGRQb3NpdGlvbiAgPSBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICB3b3JsZFBvc2l0aW9uICAgICAgID0gKHdvcmxkUG9zaXRpb24gLyB3b3JsZFBvc2l0aW9uLncpICsgdmVjNChjYXBTaXplICogb2Zmc2V0LCAwLjApO1xcbiAgZ2xfUG9zaXRpb24gICAgICAgICA9IHByb2plY3Rpb24gKiB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gIGZyYWdDb2xvciAgICAgICAgICAgPSBjb2xvcjtcXG4gIGZyYWdQb3NpdGlvbiAgICAgICAgPSBwb3NpdGlvbjtcXG59XCJdKVxyXG52YXIgZnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxudmFyeWluZyB2ZWMzIGZyYWdQb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZyYWdQb3NpdGlvbikpIGRpc2NhcmQ7XFxuXFxuICBnbF9GcmFnQ29sb3IgPSBvcGFjaXR5ICogZnJhZ0NvbG9yO1xcbn1cIl0pXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdsKSB7XHJcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgZnJhZ1NyYywgbnVsbCwgW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXHJcbiAgICB7bmFtZTogJ2NvbG9yJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAnb2Zmc2V0JywgdHlwZTogJ3ZlYzMnfVxyXG4gIF0pXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBjcmVhdGVUZXh0dXJlID0gcmVxdWlyZSgnZ2wtdGV4dHVyZTJkJylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVGQk9cblxudmFyIGNvbG9yQXR0YWNobWVudEFycmF5cyA9IG51bGxcbnZhciBGUkFNRUJVRkZFUl9VTlNVUFBPUlRFRFxudmFyIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVFxudmFyIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OU1xudmFyIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfTUlTU0lOR19BVFRBQ0hNRU5UXG5cbmZ1bmN0aW9uIHNhdmVGQk9TdGF0ZShnbCkge1xuICB2YXIgZmJvID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLkZSQU1FQlVGRkVSX0JJTkRJTkcpXG4gIHZhciByYm8gPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuUkVOREVSQlVGRkVSX0JJTkRJTkcpXG4gIHZhciB0ZXggPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuVEVYVFVSRV9CSU5ESU5HXzJEKVxuICByZXR1cm4gW2ZibywgcmJvLCB0ZXhdXG59XG5cbmZ1bmN0aW9uIHJlc3RvcmVGQk9TdGF0ZShnbCwgZGF0YSkge1xuICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGRhdGFbMF0pXG4gIGdsLmJpbmRSZW5kZXJidWZmZXIoZ2wuUkVOREVSQlVGRkVSLCBkYXRhWzFdKVxuICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBkYXRhWzJdKVxufVxuXG5mdW5jdGlvbiBsYXp5SW5pdENvbG9yQXR0YWNobWVudHMoZ2wsIGV4dCkge1xuICB2YXIgbWF4Q29sb3JBdHRhY2htZW50cyA9IGdsLmdldFBhcmFtZXRlcihleHQuTUFYX0NPTE9SX0FUVEFDSE1FTlRTX1dFQkdMKVxuICBjb2xvckF0dGFjaG1lbnRBcnJheXMgPSBuZXcgQXJyYXkobWF4Q29sb3JBdHRhY2htZW50cyArIDEpXG4gIGZvcih2YXIgaT0wOyBpPD1tYXhDb2xvckF0dGFjaG1lbnRzOyArK2kpIHtcbiAgICB2YXIgeCA9IG5ldyBBcnJheShtYXhDb2xvckF0dGFjaG1lbnRzKVxuICAgIGZvcih2YXIgaj0wOyBqPGk7ICsraikge1xuICAgICAgeFtqXSA9IGdsLkNPTE9SX0FUVEFDSE1FTlQwICsgalxuICAgIH1cbiAgICBmb3IodmFyIGo9aTsgajxtYXhDb2xvckF0dGFjaG1lbnRzOyArK2opIHtcbiAgICAgIHhbal0gPSBnbC5OT05FXG4gICAgfVxuICAgIGNvbG9yQXR0YWNobWVudEFycmF5c1tpXSA9IHhcbiAgfVxufVxuXG4vL1Rocm93IGFuIGFwcHJvcHJpYXRlIGVycm9yXG5mdW5jdGlvbiB0aHJvd0ZCT0Vycm9yKHN0YXR1cykge1xuICBzd2l0Y2goc3RhdHVzKXtcbiAgICBjYXNlIEZSQU1FQlVGRkVSX1VOU1VQUE9SVEVEOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IEZyYW1lYnVmZmVyIHVuc3VwcG9ydGVkJylcbiAgICBjYXNlIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBGcmFtZWJ1ZmZlciBpbmNvbXBsZXRlIGF0dGFjaG1lbnQnKVxuICAgIGNhc2UgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9ESU1FTlNJT05TOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IEZyYW1lYnVmZmVyIGluY29tcGxldGUgZGltZW5zaW9ucycpXG4gICAgY2FzZSBGUkFNRUJVRkZFUl9JTkNPTVBMRVRFX01JU1NJTkdfQVRUQUNITUVOVDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBGcmFtZWJ1ZmZlciBpbmNvbXBsZXRlIG1pc3NpbmcgYXR0YWNobWVudCcpXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBGcmFtZWJ1ZmZlciBmYWlsZWQgZm9yIHVuc3BlY2lmaWVkIHJlYXNvbicpXG4gIH1cbn1cblxuLy9Jbml0aWFsaXplIGEgdGV4dHVyZSBvYmplY3RcbmZ1bmN0aW9uIGluaXRUZXh0dXJlKGdsLCB3aWR0aCwgaGVpZ2h0LCB0eXBlLCBmb3JtYXQsIGF0dGFjaG1lbnQpIHtcbiAgaWYoIXR5cGUpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIHZhciByZXN1bHQgPSBjcmVhdGVUZXh0dXJlKGdsLCB3aWR0aCwgaGVpZ2h0LCBmb3JtYXQsIHR5cGUpXG4gIHJlc3VsdC5tYWdGaWx0ZXIgPSBnbC5ORUFSRVNUXG4gIHJlc3VsdC5taW5GaWx0ZXIgPSBnbC5ORUFSRVNUXG4gIHJlc3VsdC5taXBTYW1wbGVzID0gMVxuICByZXN1bHQuYmluZCgpXG4gIGdsLmZyYW1lYnVmZmVyVGV4dHVyZTJEKGdsLkZSQU1FQlVGRkVSLCBhdHRhY2htZW50LCBnbC5URVhUVVJFXzJELCByZXN1bHQuaGFuZGxlLCAwKVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8vSW5pdGlhbGl6ZSBhIHJlbmRlciBidWZmZXIgb2JqZWN0XG5mdW5jdGlvbiBpbml0UmVuZGVyQnVmZmVyKGdsLCB3aWR0aCwgaGVpZ2h0LCBjb21wb25lbnQsIGF0dGFjaG1lbnQpIHtcbiAgdmFyIHJlc3VsdCA9IGdsLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpXG4gIGdsLmJpbmRSZW5kZXJidWZmZXIoZ2wuUkVOREVSQlVGRkVSLCByZXN1bHQpXG4gIGdsLnJlbmRlcmJ1ZmZlclN0b3JhZ2UoZ2wuUkVOREVSQlVGRkVSLCBjb21wb25lbnQsIHdpZHRoLCBoZWlnaHQpXG4gIGdsLmZyYW1lYnVmZmVyUmVuZGVyYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBhdHRhY2htZW50LCBnbC5SRU5ERVJCVUZGRVIsIHJlc3VsdClcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vL1JlYnVpbGQgdGhlIGZyYW1lIGJ1ZmZlclxuZnVuY3Rpb24gcmVidWlsZEZCTyhmYm8pIHtcblxuICAvL1NhdmUgRkJPIHN0YXRlXG4gIHZhciBzdGF0ZSA9IHNhdmVGQk9TdGF0ZShmYm8uZ2wpXG5cbiAgdmFyIGdsID0gZmJvLmdsXG4gIHZhciBoYW5kbGUgPSBmYm8uaGFuZGxlID0gZ2wuY3JlYXRlRnJhbWVidWZmZXIoKVxuICB2YXIgd2lkdGggPSBmYm8uX3NoYXBlWzBdXG4gIHZhciBoZWlnaHQgPSBmYm8uX3NoYXBlWzFdXG4gIHZhciBudW1Db2xvcnMgPSBmYm8uY29sb3IubGVuZ3RoXG4gIHZhciBleHQgPSBmYm8uX2V4dFxuICB2YXIgdXNlU3RlbmNpbCA9IGZiby5fdXNlU3RlbmNpbFxuICB2YXIgdXNlRGVwdGggPSBmYm8uX3VzZURlcHRoXG4gIHZhciBjb2xvclR5cGUgPSBmYm8uX2NvbG9yVHlwZVxuXG4gIC8vQmluZCB0aGUgZmJvXG4gIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgaGFuZGxlKVxuXG4gIC8vQWxsb2NhdGUgY29sb3IgYnVmZmVyc1xuICBmb3IodmFyIGk9MDsgaTxudW1Db2xvcnM7ICsraSkge1xuICAgIGZiby5jb2xvcltpXSA9IGluaXRUZXh0dXJlKGdsLCB3aWR0aCwgaGVpZ2h0LCBjb2xvclR5cGUsIGdsLlJHQkEsIGdsLkNPTE9SX0FUVEFDSE1FTlQwICsgaSlcbiAgfVxuICBpZihudW1Db2xvcnMgPT09IDApIHtcbiAgICBmYm8uX2NvbG9yX3JiID0gaW5pdFJlbmRlckJ1ZmZlcihnbCwgd2lkdGgsIGhlaWdodCwgZ2wuUkdCQTQsIGdsLkNPTE9SX0FUVEFDSE1FTlQwKVxuICAgIGlmKGV4dCkge1xuICAgICAgZXh0LmRyYXdCdWZmZXJzV0VCR0woY29sb3JBdHRhY2htZW50QXJyYXlzWzBdKVxuICAgIH1cbiAgfSBlbHNlIGlmKG51bUNvbG9ycyA+IDEpIHtcbiAgICBleHQuZHJhd0J1ZmZlcnNXRUJHTChjb2xvckF0dGFjaG1lbnRBcnJheXNbbnVtQ29sb3JzXSlcbiAgfVxuXG4gIC8vQWxsb2NhdGUgZGVwdGgvc3RlbmNpbCBidWZmZXJzXG4gIHZhciBXRUJHTF9kZXB0aF90ZXh0dXJlID0gZ2wuZ2V0RXh0ZW5zaW9uKCdXRUJHTF9kZXB0aF90ZXh0dXJlJylcbiAgaWYoV0VCR0xfZGVwdGhfdGV4dHVyZSkge1xuICAgIGlmKHVzZVN0ZW5jaWwpIHtcbiAgICAgIGZiby5kZXB0aCA9IGluaXRUZXh0dXJlKGdsLCB3aWR0aCwgaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBXRUJHTF9kZXB0aF90ZXh0dXJlLlVOU0lHTkVEX0lOVF8yNF84X1dFQkdMLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnbC5ERVBUSF9TVEVOQ0lMLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnbC5ERVBUSF9TVEVOQ0lMX0FUVEFDSE1FTlQpXG4gICAgfSBlbHNlIGlmKHVzZURlcHRoKSB7XG4gICAgICBmYm8uZGVwdGggPSBpbml0VGV4dHVyZShnbCwgd2lkdGgsIGhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2wuVU5TSUdORURfU0hPUlQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdsLkRFUFRIX0NPTVBPTkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2wuREVQVEhfQVRUQUNITUVOVClcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYodXNlRGVwdGggJiYgdXNlU3RlbmNpbCkge1xuICAgICAgZmJvLl9kZXB0aF9yYiA9IGluaXRSZW5kZXJCdWZmZXIoZ2wsIHdpZHRoLCBoZWlnaHQsIGdsLkRFUFRIX1NURU5DSUwsIGdsLkRFUFRIX1NURU5DSUxfQVRUQUNITUVOVClcbiAgICB9IGVsc2UgaWYodXNlRGVwdGgpIHtcbiAgICAgIGZiby5fZGVwdGhfcmIgPSBpbml0UmVuZGVyQnVmZmVyKGdsLCB3aWR0aCwgaGVpZ2h0LCBnbC5ERVBUSF9DT01QT05FTlQxNiwgZ2wuREVQVEhfQVRUQUNITUVOVClcbiAgICB9IGVsc2UgaWYodXNlU3RlbmNpbCkge1xuICAgICAgZmJvLl9kZXB0aF9yYiA9IGluaXRSZW5kZXJCdWZmZXIoZ2wsIHdpZHRoLCBoZWlnaHQsIGdsLlNURU5DSUxfSU5ERVgsIGdsLlNURU5DSUxfQVRUQUNITUVOVClcbiAgICB9XG4gIH1cblxuICAvL0NoZWNrIGZyYW1lIGJ1ZmZlciBzdGF0ZVxuICB2YXIgc3RhdHVzID0gZ2wuY2hlY2tGcmFtZWJ1ZmZlclN0YXR1cyhnbC5GUkFNRUJVRkZFUilcbiAgaWYoc3RhdHVzICE9PSBnbC5GUkFNRUJVRkZFUl9DT01QTEVURSkge1xuXG4gICAgLy9SZWxlYXNlIGFsbCBwYXJ0aWFsbHkgYWxsb2NhdGVkIHJlc291cmNlc1xuICAgIGZiby5fZGVzdHJveWVkID0gdHJ1ZVxuXG4gICAgLy9SZWxlYXNlIGFsbCByZXNvdXJjZXNcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXG4gICAgZ2wuZGVsZXRlRnJhbWVidWZmZXIoZmJvLmhhbmRsZSlcbiAgICBmYm8uaGFuZGxlID0gbnVsbFxuICAgIGlmKGZiby5kZXB0aCkge1xuICAgICAgZmJvLmRlcHRoLmRpc3Bvc2UoKVxuICAgICAgZmJvLmRlcHRoID0gbnVsbFxuICAgIH1cbiAgICBpZihmYm8uX2RlcHRoX3JiKSB7XG4gICAgICBnbC5kZWxldGVSZW5kZXJidWZmZXIoZmJvLl9kZXB0aF9yYilcbiAgICAgIGZiby5fZGVwdGhfcmIgPSBudWxsXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPGZiby5jb2xvci5sZW5ndGg7ICsraSkge1xuICAgICAgZmJvLmNvbG9yW2ldLmRpc3Bvc2UoKVxuICAgICAgZmJvLmNvbG9yW2ldID0gbnVsbFxuICAgIH1cbiAgICBpZihmYm8uX2NvbG9yX3JiKSB7XG4gICAgICBnbC5kZWxldGVSZW5kZXJidWZmZXIoZmJvLl9jb2xvcl9yYilcbiAgICAgIGZiby5fY29sb3JfcmIgPSBudWxsXG4gICAgfVxuXG4gICAgcmVzdG9yZUZCT1N0YXRlKGdsLCBzdGF0ZSlcblxuICAgIC8vVGhyb3cgdGhlIGZyYW1lIGJ1ZmZlciBlcnJvclxuICAgIHRocm93RkJPRXJyb3Ioc3RhdHVzKVxuICB9XG5cbiAgLy9FdmVyeXRoaW5nIG9rLCBsZXQncyBnZXQgb24gd2l0aCBsaWZlXG4gIHJlc3RvcmVGQk9TdGF0ZShnbCwgc3RhdGUpXG59XG5cbmZ1bmN0aW9uIEZyYW1lYnVmZmVyKGdsLCB3aWR0aCwgaGVpZ2h0LCBjb2xvclR5cGUsIG51bUNvbG9ycywgdXNlRGVwdGgsIHVzZVN0ZW5jaWwsIGV4dCkge1xuXG4gIC8vSGFuZGxlIGFuZCBzZXQgcHJvcGVydGllc1xuICB0aGlzLmdsID0gZ2xcbiAgdGhpcy5fc2hhcGUgPSBbd2lkdGh8MCwgaGVpZ2h0fDBdXG4gIHRoaXMuX2Rlc3Ryb3llZCA9IGZhbHNlXG4gIHRoaXMuX2V4dCA9IGV4dFxuXG4gIC8vQWxsb2NhdGUgYnVmZmVyc1xuICB0aGlzLmNvbG9yID0gbmV3IEFycmF5KG51bUNvbG9ycylcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ29sb3JzOyArK2kpIHtcbiAgICB0aGlzLmNvbG9yW2ldID0gbnVsbFxuICB9XG4gIHRoaXMuX2NvbG9yX3JiID0gbnVsbFxuICB0aGlzLmRlcHRoID0gbnVsbFxuICB0aGlzLl9kZXB0aF9yYiA9IG51bGxcblxuICAvL1NhdmUgZGVwdGggYW5kIHN0ZW5jaWwgZmxhZ3NcbiAgdGhpcy5fY29sb3JUeXBlID0gY29sb3JUeXBlXG4gIHRoaXMuX3VzZURlcHRoID0gdXNlRGVwdGhcbiAgdGhpcy5fdXNlU3RlbmNpbCA9IHVzZVN0ZW5jaWxcblxuICAvL1NoYXBlIHZlY3RvciBmb3IgcmVzaXppbmdcbiAgdmFyIHBhcmVudCA9IHRoaXNcbiAgdmFyIHNoYXBlVmVjdG9yID0gW3dpZHRofDAsIGhlaWdodHwwXVxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhzaGFwZVZlY3Rvciwge1xuICAgIDA6IHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3NoYXBlWzBdXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih3KSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQud2lkdGggPSB3XG4gICAgICB9XG4gICAgfSxcbiAgICAxOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcGFyZW50Ll9zaGFwZVsxXVxuICAgICAgfSxcbiAgICAgIHNldDogZnVuY3Rpb24oaCkge1xuICAgICAgICByZXR1cm4gcGFyZW50LmhlaWdodCA9IGhcbiAgICAgIH1cbiAgICB9XG4gIH0pXG4gIHRoaXMuX3NoYXBlVmVjdG9yID0gc2hhcGVWZWN0b3JcblxuICAvL0luaXRpYWxpemUgYWxsIGF0dGFjaG1lbnRzXG4gIHJlYnVpbGRGQk8odGhpcylcbn1cblxudmFyIHByb3RvID0gRnJhbWVidWZmZXIucHJvdG90eXBlXG5cbmZ1bmN0aW9uIHJlc2hhcGVGQk8oZmJvLCB3LCBoKSB7XG4gIC8vSWYgZmJvIGlzIGludmFsaWQsIGp1c3Qgc2tpcCB0aGlzXG4gIGlmKGZiby5fZGVzdHJveWVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IENhblxcJ3QgcmVzaXplIGRlc3Ryb3llZCBGQk8nKVxuICB9XG5cbiAgLy9Eb24ndCByZXNpemUgaWYgbm8gY2hhbmdlIGluIHNoYXBlXG4gIGlmKCAoZmJvLl9zaGFwZVswXSA9PT0gdykgJiZcbiAgICAgIChmYm8uX3NoYXBlWzFdID09PSBoKSApIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBnbCA9IGZiby5nbFxuXG4gIC8vQ2hlY2sgcGFyYW1ldGVyIHJhbmdlc1xuICB2YXIgbWF4RkJPU2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfUkVOREVSQlVGRkVSX1NJWkUpXG4gIGlmKCB3IDwgMCB8fCB3ID4gbWF4RkJPU2l6ZSB8fFxuICAgICAgaCA8IDAgfHwgaCA+IG1heEZCT1NpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogQ2FuXFwndCByZXNpemUgRkJPLCBpbnZhbGlkIGRpbWVuc2lvbnMnKVxuICB9XG5cbiAgLy9VcGRhdGUgc2hhcGVcbiAgZmJvLl9zaGFwZVswXSA9IHdcbiAgZmJvLl9zaGFwZVsxXSA9IGhcblxuICAvL1NhdmUgZnJhbWVidWZmZXIgc3RhdGVcbiAgdmFyIHN0YXRlID0gc2F2ZUZCT1N0YXRlKGdsKVxuXG4gIC8vUmVzaXplIGZyYW1lYnVmZmVyIGF0dGFjaG1lbnRzXG4gIGZvcih2YXIgaT0wOyBpPGZiby5jb2xvci5sZW5ndGg7ICsraSkge1xuICAgIGZiby5jb2xvcltpXS5zaGFwZSA9IGZiby5fc2hhcGVcbiAgfVxuICBpZihmYm8uX2NvbG9yX3JiKSB7XG4gICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIGZiby5fY29sb3JfcmIpXG4gICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGdsLlJHQkE0LCBmYm8uX3NoYXBlWzBdLCBmYm8uX3NoYXBlWzFdKVxuICB9XG4gIGlmKGZiby5kZXB0aCkge1xuICAgIGZiby5kZXB0aC5zaGFwZSA9IGZiby5fc2hhcGVcbiAgfVxuICBpZihmYm8uX2RlcHRoX3JiKSB7XG4gICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIGZiby5fZGVwdGhfcmIpXG4gICAgaWYoZmJvLl91c2VEZXB0aCAmJiBmYm8uX3VzZVN0ZW5jaWwpIHtcbiAgICAgIGdsLnJlbmRlcmJ1ZmZlclN0b3JhZ2UoZ2wuUkVOREVSQlVGRkVSLCBnbC5ERVBUSF9TVEVOQ0lMLCBmYm8uX3NoYXBlWzBdLCBmYm8uX3NoYXBlWzFdKVxuICAgIH0gZWxzZSBpZihmYm8uX3VzZURlcHRoKSB7XG4gICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKGdsLlJFTkRFUkJVRkZFUiwgZ2wuREVQVEhfQ09NUE9ORU5UMTYsIGZiby5fc2hhcGVbMF0sIGZiby5fc2hhcGVbMV0pXG4gICAgfSBlbHNlIGlmKGZiby5fdXNlU3RlbmNpbCkge1xuICAgICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGdsLlNURU5DSUxfSU5ERVgsIGZiby5fc2hhcGVbMF0sIGZiby5fc2hhcGVbMV0pXG4gICAgfVxuICB9XG5cbiAgLy9DaGVjayBGQk8gc3RhdHVzIGFmdGVyIHJlc2l6ZSwgaWYgc29tZXRoaW5nIGJyb2tlIHRoZW4gZGllIGluIGEgZmlyZVxuICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGZiby5oYW5kbGUpXG4gIHZhciBzdGF0dXMgPSBnbC5jaGVja0ZyYW1lYnVmZmVyU3RhdHVzKGdsLkZSQU1FQlVGRkVSKVxuICBpZihzdGF0dXMgIT09IGdsLkZSQU1FQlVGRkVSX0NPTVBMRVRFKSB7XG4gICAgZmJvLmRpc3Bvc2UoKVxuICAgIHJlc3RvcmVGQk9TdGF0ZShnbCwgc3RhdGUpXG4gICAgdGhyb3dGQk9FcnJvcihzdGF0dXMpXG4gIH1cblxuICAvL1Jlc3RvcmUgZnJhbWVidWZmZXIgc3RhdGVcbiAgcmVzdG9yZUZCT1N0YXRlKGdsLCBzdGF0ZSlcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnRpZXMocHJvdG8sIHtcbiAgJ3NoYXBlJzoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICBpZih0aGlzLl9kZXN0cm95ZWQpIHtcbiAgICAgICAgcmV0dXJuIFswLDBdXG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fc2hhcGVWZWN0b3JcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oeCkge1xuICAgICAgaWYoIUFycmF5LmlzQXJyYXkoeCkpIHtcbiAgICAgICAgeCA9IFt4fDAsIHh8MF1cbiAgICAgIH1cbiAgICAgIGlmKHgubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBTaGFwZSB2ZWN0b3IgbXVzdCBiZSBsZW5ndGggMicpXG4gICAgICB9XG5cbiAgICAgIHZhciB3ID0geFswXXwwXG4gICAgICB2YXIgaCA9IHhbMV18MFxuICAgICAgcmVzaGFwZUZCTyh0aGlzLCB3LCBoKVxuXG4gICAgICByZXR1cm4gW3csIGhdXG4gICAgfSxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZVxuICB9LFxuICAnd2lkdGgnOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmKHRoaXMuX2Rlc3Ryb3llZCkge1xuICAgICAgICByZXR1cm4gMFxuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuX3NoYXBlWzBdXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHcpIHtcbiAgICAgIHcgPSB3fDBcbiAgICAgIHJlc2hhcGVGQk8odGhpcywgdywgdGhpcy5fc2hhcGVbMV0pXG4gICAgICByZXR1cm4gd1xuICAgIH0sXG4gICAgZW51bWVyYWJsZTogZmFsc2VcbiAgfSxcbiAgJ2hlaWdodCc6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYodGhpcy5fZGVzdHJveWVkKSB7XG4gICAgICAgIHJldHVybiAwXG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fc2hhcGVbMV1cbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oaCkge1xuICAgICAgaCA9IGh8MFxuICAgICAgcmVzaGFwZUZCTyh0aGlzLCB0aGlzLl9zaGFwZVswXSwgaClcbiAgICAgIHJldHVybiBoXG4gICAgfSxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZVxuICB9XG59KVxuXG5wcm90by5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIGlmKHRoaXMuX2Rlc3Ryb3llZCkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCB0aGlzLmhhbmRsZSlcbiAgZ2wudmlld3BvcnQoMCwgMCwgdGhpcy5fc2hhcGVbMF0sIHRoaXMuX3NoYXBlWzFdKVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIGlmKHRoaXMuX2Rlc3Ryb3llZCkge1xuICAgIHJldHVyblxuICB9XG4gIHRoaXMuX2Rlc3Ryb3llZCA9IHRydWVcbiAgdmFyIGdsID0gdGhpcy5nbFxuICBnbC5kZWxldGVGcmFtZWJ1ZmZlcih0aGlzLmhhbmRsZSlcbiAgdGhpcy5oYW5kbGUgPSBudWxsXG4gIGlmKHRoaXMuZGVwdGgpIHtcbiAgICB0aGlzLmRlcHRoLmRpc3Bvc2UoKVxuICAgIHRoaXMuZGVwdGggPSBudWxsXG4gIH1cbiAgaWYodGhpcy5fZGVwdGhfcmIpIHtcbiAgICBnbC5kZWxldGVSZW5kZXJidWZmZXIodGhpcy5fZGVwdGhfcmIpXG4gICAgdGhpcy5fZGVwdGhfcmIgPSBudWxsXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8dGhpcy5jb2xvci5sZW5ndGg7ICsraSkge1xuICAgIHRoaXMuY29sb3JbaV0uZGlzcG9zZSgpXG4gICAgdGhpcy5jb2xvcltpXSA9IG51bGxcbiAgfVxuICBpZih0aGlzLl9jb2xvcl9yYikge1xuICAgIGdsLmRlbGV0ZVJlbmRlcmJ1ZmZlcih0aGlzLl9jb2xvcl9yYilcbiAgICB0aGlzLl9jb2xvcl9yYiA9IG51bGxcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVGQk8oZ2wsIHdpZHRoLCBoZWlnaHQsIG9wdGlvbnMpIHtcblxuICAvL1VwZGF0ZSBmcmFtZSBidWZmZXIgZXJyb3IgY29kZSB2YWx1ZXNcbiAgaWYoIUZSQU1FQlVGRkVSX1VOU1VQUE9SVEVEKSB7XG4gICAgRlJBTUVCVUZGRVJfVU5TVVBQT1JURUQgPSBnbC5GUkFNRUJVRkZFUl9VTlNVUFBPUlRFRFxuICAgIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVCA9IGdsLkZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVFxuICAgIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OUyA9IGdsLkZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OU1xuICAgIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfTUlTU0lOR19BVFRBQ0hNRU5UID0gZ2wuRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlRcbiAgfVxuXG4gIC8vTGF6aWx5IGluaXRpYWxpemUgY29sb3IgYXR0YWNobWVudCBhcnJheXNcbiAgdmFyIFdFQkdMX2RyYXdfYnVmZmVycyA9IGdsLmdldEV4dGVuc2lvbignV0VCR0xfZHJhd19idWZmZXJzJylcbiAgaWYoIWNvbG9yQXR0YWNobWVudEFycmF5cyAmJiBXRUJHTF9kcmF3X2J1ZmZlcnMpIHtcbiAgICBsYXp5SW5pdENvbG9yQXR0YWNobWVudHMoZ2wsIFdFQkdMX2RyYXdfYnVmZmVycylcbiAgfVxuXG4gIC8vU3BlY2lhbCBjYXNlOiBDYW4gYWNjZXB0IGFuIGFycmF5IGFzIGFyZ3VtZW50XG4gIGlmKEFycmF5LmlzQXJyYXkod2lkdGgpKSB7XG4gICAgb3B0aW9ucyA9IGhlaWdodFxuICAgIGhlaWdodCA9IHdpZHRoWzFdfDBcbiAgICB3aWR0aCA9IHdpZHRoWzBdfDBcbiAgfVxuXG4gIGlmKHR5cGVvZiB3aWR0aCAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogTWlzc2luZyBzaGFwZSBwYXJhbWV0ZXInKVxuICB9XG5cbiAgLy9WYWxpZGF0ZSB3aWR0aC9oZWlnaHQgcHJvcGVydGllc1xuICB2YXIgbWF4RkJPU2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfUkVOREVSQlVGRkVSX1NJWkUpXG4gIGlmKHdpZHRoIDwgMCB8fCB3aWR0aCA+IG1heEZCT1NpemUgfHwgaGVpZ2h0IDwgMCB8fCBoZWlnaHQgPiBtYXhGQk9TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IFBhcmFtZXRlcnMgYXJlIHRvbyBsYXJnZSBmb3IgRkJPJylcbiAgfVxuXG4gIC8vSGFuZGxlIGVhY2ggb3B0aW9uIHR5cGVcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICAvL0ZpZ3VyZSBvdXQgbnVtYmVyIG9mIGNvbG9yIGJ1ZmZlcnMgdG8gdXNlXG4gIHZhciBudW1Db2xvcnMgPSAxXG4gIGlmKCdjb2xvcicgaW4gb3B0aW9ucykge1xuICAgIG51bUNvbG9ycyA9IE1hdGgubWF4KG9wdGlvbnMuY29sb3J8MCwgMClcbiAgICBpZihudW1Db2xvcnMgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogTXVzdCBzcGVjaWZ5IGEgbm9ubmVnYXRpdmUgbnVtYmVyIG9mIGNvbG9ycycpXG4gICAgfVxuICAgIGlmKG51bUNvbG9ycyA+IDEpIHtcbiAgICAgIC8vQ2hlY2sgaWYgbXVsdGlwbGUgcmVuZGVyIHRhcmdldHMgc3VwcG9ydGVkXG4gICAgICBpZighV0VCR0xfZHJhd19idWZmZXJzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBNdWx0aXBsZSBkcmF3IGJ1ZmZlciBleHRlbnNpb24gbm90IHN1cHBvcnRlZCcpXG4gICAgICB9IGVsc2UgaWYobnVtQ29sb3JzID4gZ2wuZ2V0UGFyYW1ldGVyKFdFQkdMX2RyYXdfYnVmZmVycy5NQVhfQ09MT1JfQVRUQUNITUVOVFNfV0VCR0wpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBDb250ZXh0IGRvZXMgbm90IHN1cHBvcnQgJyArIG51bUNvbG9ycyArICcgZHJhdyBidWZmZXJzJylcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL0RldGVybWluZSB3aGV0aGVyIHRvIHVzZSBmbG9hdGluZyBwb2ludCB0ZXh0dXJlc1xuICB2YXIgY29sb3JUeXBlID0gZ2wuVU5TSUdORURfQllURVxuICB2YXIgT0VTX3RleHR1cmVfZmxvYXQgPSBnbC5nZXRFeHRlbnNpb24oJ09FU190ZXh0dXJlX2Zsb2F0JylcbiAgaWYob3B0aW9ucy5mbG9hdCAmJiBudW1Db2xvcnMgPiAwKSB7XG4gICAgaWYoIU9FU190ZXh0dXJlX2Zsb2F0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogQ29udGV4dCBkb2VzIG5vdCBzdXBwb3J0IGZsb2F0aW5nIHBvaW50IHRleHR1cmVzJylcbiAgICB9XG4gICAgY29sb3JUeXBlID0gZ2wuRkxPQVRcbiAgfSBlbHNlIGlmKG9wdGlvbnMucHJlZmVyRmxvYXQgJiYgbnVtQ29sb3JzID4gMCkge1xuICAgIGlmKE9FU190ZXh0dXJlX2Zsb2F0KSB7XG4gICAgICBjb2xvclR5cGUgPSBnbC5GTE9BVFxuICAgIH1cbiAgfVxuXG4gIC8vQ2hlY2sgaWYgd2Ugc2hvdWxkIHVzZSBkZXB0aCBidWZmZXJcbiAgdmFyIHVzZURlcHRoID0gdHJ1ZVxuICBpZignZGVwdGgnIGluIG9wdGlvbnMpIHtcbiAgICB1c2VEZXB0aCA9ICEhb3B0aW9ucy5kZXB0aFxuICB9XG5cbiAgLy9DaGVjayBpZiB3ZSBzaG91bGQgdXNlIGEgc3RlbmNpbCBidWZmZXJcbiAgdmFyIHVzZVN0ZW5jaWwgPSBmYWxzZVxuICBpZignc3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgIHVzZVN0ZW5jaWwgPSAhIW9wdGlvbnMuc3RlbmNpbFxuICB9XG5cbiAgcmV0dXJuIG5ldyBGcmFtZWJ1ZmZlcihcbiAgICBnbCxcbiAgICB3aWR0aCxcbiAgICBoZWlnaHQsXG4gICAgY29sb3JUeXBlLFxuICAgIG51bUNvbG9ycyxcbiAgICB1c2VEZXB0aCxcbiAgICB1c2VTdGVuY2lsLFxuICAgIFdFQkdMX2RyYXdfYnVmZmVycylcbn1cbiIsIlxudmFyIHNwcmludGYgPSByZXF1aXJlKCdzcHJpbnRmLWpzJykuc3ByaW50ZjtcbnZhciBnbENvbnN0YW50cyA9IHJlcXVpcmUoJ2dsLWNvbnN0YW50cy9sb29rdXAnKTtcbnZhciBzaGFkZXJOYW1lID0gcmVxdWlyZSgnZ2xzbC1zaGFkZXItbmFtZScpO1xudmFyIGFkZExpbmVOdW1iZXJzID0gcmVxdWlyZSgnYWRkLWxpbmUtbnVtYmVycycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZvcm1hdENvbXBpbGVyRXJyb3I7XG5cbmZ1bmN0aW9uIGZvcm1hdENvbXBpbGVyRXJyb3IoZXJyTG9nLCBzcmMsIHR5cGUpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIHZhciBuYW1lID0gc2hhZGVyTmFtZShzcmMpIHx8ICdvZiB1bmtub3duIG5hbWUgKHNlZSBucG0gZ2xzbC1zaGFkZXItbmFtZSknO1xuXG4gICAgdmFyIHR5cGVOYW1lID0gJ3Vua25vd24gdHlwZSc7XG4gICAgaWYgKHR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0eXBlTmFtZSA9IHR5cGUgPT09IGdsQ29uc3RhbnRzLkZSQUdNRU5UX1NIQURFUiA/ICdmcmFnbWVudCcgOiAndmVydGV4J1xuICAgIH1cblxuICAgIHZhciBsb25nRm9ybSA9IHNwcmludGYoJ0Vycm9yIGNvbXBpbGluZyAlcyBzaGFkZXIgJXM6XFxuJywgdHlwZU5hbWUsIG5hbWUpO1xuICAgIHZhciBzaG9ydEZvcm0gPSBzcHJpbnRmKFwiJXMlc1wiLCBsb25nRm9ybSwgZXJyTG9nKTtcblxuICAgIHZhciBlcnJvclN0cmluZ3MgPSBlcnJMb2cuc3BsaXQoJ1xcbicpO1xuICAgIHZhciBlcnJvcnMgPSB7fTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXJyb3JTdHJpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlcnJvclN0cmluZyA9IGVycm9yU3RyaW5nc1tpXTtcbiAgICAgICAgaWYgKGVycm9yU3RyaW5nID09PSAnJyB8fCBlcnJvclN0cmluZyA9PT0gXCJcXDBcIikgY29udGludWU7XG4gICAgICAgIHZhciBsaW5lTm8gPSBwYXJzZUludChlcnJvclN0cmluZy5zcGxpdCgnOicpWzJdKTtcbiAgICAgICAgaWYgKGlzTmFOKGxpbmVObykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihzcHJpbnRmKCdDb3VsZCBub3QgcGFyc2UgZXJyb3I6ICVzJywgZXJyb3JTdHJpbmcpKTtcbiAgICAgICAgfVxuICAgICAgICBlcnJvcnNbbGluZU5vXSA9IGVycm9yU3RyaW5nO1xuICAgIH1cblxuICAgIHZhciBsaW5lcyA9IGFkZExpbmVOdW1iZXJzKHNyYykuc3BsaXQoJ1xcbicpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoIWVycm9yc1tpKzNdICYmICFlcnJvcnNbaSsyXSAmJiAhZXJyb3JzW2krMV0pIGNvbnRpbnVlO1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuICAgICAgICBsb25nRm9ybSArPSBsaW5lICsgJ1xcbic7XG4gICAgICAgIGlmIChlcnJvcnNbaSsxXSkge1xuICAgICAgICAgICAgdmFyIGUgPSBlcnJvcnNbaSsxXTtcbiAgICAgICAgICAgIGUgPSBlLnN1YnN0cihlLnNwbGl0KCc6JywgMykuam9pbignOicpLmxlbmd0aCArIDEpLnRyaW0oKTtcbiAgICAgICAgICAgIGxvbmdGb3JtICs9IHNwcmludGYoJ15eXiAlc1xcblxcbicsIGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbG9uZzogbG9uZ0Zvcm0udHJpbSgpLFxuICAgICAgICBzaG9ydDogc2hvcnRGb3JtLnRyaW0oKVxuICAgIH07XG59XG5cbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVIZWF0bWFwMkRcclxuXHJcbnZhciBic2VhcmNoID0gcmVxdWlyZSgnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxyXG52YXIgaW90YSA9IHJlcXVpcmUoJ2lvdGEtYXJyYXknKVxyXG52YXIgcG9vbCA9IHJlcXVpcmUoJ3R5cGVkYXJyYXktcG9vbCcpXHJcbnZhciBjcmVhdGVTaGFkZXIgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG52YXIgY3JlYXRlQnVmZmVyID0gcmVxdWlyZSgnZ2wtYnVmZmVyJylcclxuXHJcbnZhciBzaGFkZXJzID0gcmVxdWlyZSgnLi9saWIvc2hhZGVycycpXHJcblxyXG5mdW5jdGlvbiBHTEhlYXRtYXAyRCAoXHJcbiAgcGxvdCxcclxuICBzaGFkZXIsXHJcbiAgcGlja1NoYWRlcixcclxuICBwb3NpdGlvbkJ1ZmZlcixcclxuICB3ZWlnaHRCdWZmZXIsXHJcbiAgY29sb3JCdWZmZXIsXHJcbiAgaWRCdWZmZXIpIHtcclxuICB0aGlzLnBsb3QgPSBwbG90XHJcbiAgdGhpcy5zaGFkZXIgPSBzaGFkZXJcclxuICB0aGlzLnBpY2tTaGFkZXIgPSBwaWNrU2hhZGVyXHJcbiAgdGhpcy5wb3NpdGlvbkJ1ZmZlciA9IHBvc2l0aW9uQnVmZmVyXHJcbiAgdGhpcy53ZWlnaHRCdWZmZXIgPSB3ZWlnaHRCdWZmZXJcclxuICB0aGlzLmNvbG9yQnVmZmVyID0gY29sb3JCdWZmZXJcclxuICB0aGlzLmlkQnVmZmVyID0gaWRCdWZmZXJcclxuICB0aGlzLnhEYXRhID0gW11cclxuICB0aGlzLnlEYXRhID0gW11cclxuICB0aGlzLnNoYXBlID0gWzAsIDBdXHJcbiAgdGhpcy5ib3VuZHMgPSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV1cclxuICB0aGlzLnBpY2tPZmZzZXQgPSAwXHJcbn1cclxuXHJcbnZhciBwcm90byA9IEdMSGVhdG1hcDJELnByb3RvdHlwZVxyXG5cclxudmFyIFdFSUdIVFMgPSBbXHJcbiAgMCwgMCxcclxuICAxLCAwLFxyXG4gIDAsIDEsXHJcbiAgMSwgMCxcclxuICAxLCAxLFxyXG4gIDAsIDFcclxuXVxyXG5cclxucHJvdG8uZHJhdyA9IChmdW5jdGlvbiAoKSB7XHJcbiAgdmFyIE1BVFJJWCA9IFtcclxuICAgIDEsIDAsIDAsXHJcbiAgICAwLCAxLCAwLFxyXG4gICAgMCwgMCwgMVxyXG4gIF1cclxuXHJcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcclxuICAgIHZhciBwbG90ID0gdGhpcy5wbG90XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5zaGFkZXJcclxuICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kc1xyXG4gICAgdmFyIG51bVZlcnRpY2VzID0gdGhpcy5udW1WZXJ0aWNlc1xyXG5cclxuICAgIGlmIChudW1WZXJ0aWNlcyA8PSAwKSB7XHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIHZhciBnbCA9IHBsb3QuZ2xcclxuICAgIHZhciBkYXRhQm94ID0gcGxvdC5kYXRhQm94XHJcblxyXG4gICAgdmFyIGJvdW5kWCA9IGJvdW5kc1syXSAtIGJvdW5kc1swXVxyXG4gICAgdmFyIGJvdW5kWSA9IGJvdW5kc1szXSAtIGJvdW5kc1sxXVxyXG4gICAgdmFyIGRhdGFYID0gZGF0YUJveFsyXSAtIGRhdGFCb3hbMF1cclxuICAgIHZhciBkYXRhWSA9IGRhdGFCb3hbM10gLSBkYXRhQm94WzFdXHJcblxyXG4gICAgTUFUUklYWzBdID0gMi4wICogYm91bmRYIC8gZGF0YVhcclxuICAgIE1BVFJJWFs0XSA9IDIuMCAqIGJvdW5kWSAvIGRhdGFZXHJcbiAgICBNQVRSSVhbNl0gPSAyLjAgKiAoYm91bmRzWzBdIC0gZGF0YUJveFswXSkgLyBkYXRhWCAtIDEuMFxyXG4gICAgTUFUUklYWzddID0gMi4wICogKGJvdW5kc1sxXSAtIGRhdGFCb3hbMV0pIC8gZGF0YVkgLSAxLjBcclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcblxyXG4gICAgdmFyIHVuaWZvcm1zID0gc2hhZGVyLnVuaWZvcm1zXHJcbiAgICB1bmlmb3Jtcy52aWV3VHJhbnNmb3JtID0gTUFUUklYXHJcblxyXG4gICAgdW5pZm9ybXMuc2hhcGUgPSB0aGlzLnNoYXBlXHJcblxyXG4gICAgdmFyIGF0dHJpYnV0ZXMgPSBzaGFkZXIuYXR0cmlidXRlc1xyXG4gICAgdGhpcy5wb3NpdGlvbkJ1ZmZlci5iaW5kKClcclxuICAgIGF0dHJpYnV0ZXMucG9zaXRpb24ucG9pbnRlcigpXHJcblxyXG4gICAgdGhpcy53ZWlnaHRCdWZmZXIuYmluZCgpXHJcbiAgICBhdHRyaWJ1dGVzLndlaWdodC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlKVxyXG5cclxuICAgIHRoaXMuY29sb3JCdWZmZXIuYmluZCgpXHJcbiAgICBhdHRyaWJ1dGVzLmNvbG9yLnBvaW50ZXIoZ2wuVU5TSUdORURfQllURSwgdHJ1ZSlcclxuXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgbnVtVmVydGljZXMpXHJcbiAgfVxyXG59KSgpXHJcblxyXG5wcm90by5kcmF3UGljayA9IChmdW5jdGlvbiAoKSB7XHJcbiAgdmFyIE1BVFJJWCA9IFtcclxuICAgIDEsIDAsIDAsXHJcbiAgICAwLCAxLCAwLFxyXG4gICAgMCwgMCwgMVxyXG4gIF1cclxuXHJcbiAgdmFyIFBJQ0tfVkVDVE9SID0gWzAsIDAsIDAsIDBdXHJcblxyXG4gIHJldHVybiBmdW5jdGlvbiAocGlja09mZnNldCkge1xyXG4gICAgdmFyIHBsb3QgPSB0aGlzLnBsb3RcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcclxuICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kc1xyXG4gICAgdmFyIG51bVZlcnRpY2VzID0gdGhpcy5udW1WZXJ0aWNlc1xyXG5cclxuICAgIGlmIChudW1WZXJ0aWNlcyA8PSAwKSB7XHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIHZhciBnbCA9IHBsb3QuZ2xcclxuICAgIHZhciBkYXRhQm94ID0gcGxvdC5kYXRhQm94XHJcblxyXG4gICAgdmFyIGJvdW5kWCA9IGJvdW5kc1syXSAtIGJvdW5kc1swXVxyXG4gICAgdmFyIGJvdW5kWSA9IGJvdW5kc1szXSAtIGJvdW5kc1sxXVxyXG4gICAgdmFyIGRhdGFYID0gZGF0YUJveFsyXSAtIGRhdGFCb3hbMF1cclxuICAgIHZhciBkYXRhWSA9IGRhdGFCb3hbM10gLSBkYXRhQm94WzFdXHJcblxyXG4gICAgTUFUUklYWzBdID0gMi4wICogYm91bmRYIC8gZGF0YVhcclxuICAgIE1BVFJJWFs0XSA9IDIuMCAqIGJvdW5kWSAvIGRhdGFZXHJcbiAgICBNQVRSSVhbNl0gPSAyLjAgKiAoYm91bmRzWzBdIC0gZGF0YUJveFswXSkgLyBkYXRhWCAtIDEuMFxyXG4gICAgTUFUUklYWzddID0gMi4wICogKGJvdW5kc1sxXSAtIGRhdGFCb3hbMV0pIC8gZGF0YVkgLSAxLjBcclxuXHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDQ7ICsraSkge1xyXG4gICAgICBQSUNLX1ZFQ1RPUltpXSA9IChwaWNrT2Zmc2V0ID4+IChpICogOCkpICYgMHhmZlxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMucGlja09mZnNldCA9IHBpY2tPZmZzZXRcclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcblxyXG4gICAgdmFyIHVuaWZvcm1zID0gc2hhZGVyLnVuaWZvcm1zXHJcbiAgICB1bmlmb3Jtcy52aWV3VHJhbnNmb3JtID0gTUFUUklYXHJcbiAgICB1bmlmb3Jtcy5waWNrT2Zmc2V0ID0gUElDS19WRUNUT1JcclxuICAgIHVuaWZvcm1zLnNoYXBlID0gdGhpcy5zaGFwZVxyXG5cclxuICAgIHZhciBhdHRyaWJ1dGVzID0gc2hhZGVyLmF0dHJpYnV0ZXNcclxuICAgIHRoaXMucG9zaXRpb25CdWZmZXIuYmluZCgpXHJcbiAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uLnBvaW50ZXIoKVxyXG5cclxuICAgIHRoaXMud2VpZ2h0QnVmZmVyLmJpbmQoKVxyXG4gICAgYXR0cmlidXRlcy53ZWlnaHQucG9pbnRlcihnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSlcclxuXHJcbiAgICB0aGlzLmlkQnVmZmVyLmJpbmQoKVxyXG4gICAgYXR0cmlidXRlcy5waWNrSWQucG9pbnRlcihnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSlcclxuXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgbnVtVmVydGljZXMpXHJcblxyXG4gICAgcmV0dXJuIHBpY2tPZmZzZXQgKyB0aGlzLnNoYXBlWzBdICogdGhpcy5zaGFwZVsxXVxyXG4gIH1cclxufSkoKVxyXG5cclxucHJvdG8ucGljayA9IGZ1bmN0aW9uICh4LCB5LCB2YWx1ZSkge1xyXG4gIHZhciBwaWNrT2Zmc2V0ID0gdGhpcy5waWNrT2Zmc2V0XHJcbiAgdmFyIHBvaW50Q291bnQgPSB0aGlzLnNoYXBlWzBdICogdGhpcy5zaGFwZVsxXVxyXG4gIGlmICh2YWx1ZSA8IHBpY2tPZmZzZXQgfHwgdmFsdWUgPj0gcGlja09mZnNldCArIHBvaW50Q291bnQpIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG4gIHZhciBwb2ludElkID0gdmFsdWUgLSBwaWNrT2Zmc2V0XHJcbiAgdmFyIHhEYXRhID0gdGhpcy54RGF0YVxyXG4gIHZhciB5RGF0YSA9IHRoaXMueURhdGFcclxuICByZXR1cm4ge1xyXG4gICAgb2JqZWN0OiB0aGlzLFxyXG4gICAgcG9pbnRJZDogcG9pbnRJZCxcclxuICAgIGRhdGFDb29yZDogW1xyXG4gICAgICB4RGF0YVtwb2ludElkICUgdGhpcy5zaGFwZVswXV0sXHJcbiAgICAgIHlEYXRhWyhwb2ludElkIC8gdGhpcy5zaGFwZVswXSkgfCAwXV1cclxuICB9XHJcbn1cclxuXHJcbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cclxuXHJcbiAgdmFyIHNoYXBlID0gb3B0aW9ucy5zaGFwZSB8fCBbMCwgMF1cclxuXHJcbiAgdmFyIHggPSBvcHRpb25zLnggfHwgaW90YShzaGFwZVswXSlcclxuICB2YXIgeSA9IG9wdGlvbnMueSB8fCBpb3RhKHNoYXBlWzFdKVxyXG4gIHZhciB6ID0gb3B0aW9ucy56IHx8IG5ldyBGbG9hdDMyQXJyYXkoc2hhcGVbMF0gKiBzaGFwZVsxXSlcclxuXHJcbiAgdGhpcy54RGF0YSA9IHhcclxuICB0aGlzLnlEYXRhID0geVxyXG5cclxuICB2YXIgY29sb3JMZXZlbHMgPSBvcHRpb25zLmNvbG9yTGV2ZWxzIHx8IFswXVxyXG4gIHZhciBjb2xvclZhbHVlcyA9IG9wdGlvbnMuY29sb3JWYWx1ZXMgfHwgWzAsIDAsIDAsIDFdXHJcbiAgdmFyIGNvbG9yQ291bnQgPSBjb2xvckxldmVscy5sZW5ndGhcclxuXHJcbiAgdmFyIGJvdW5kcyA9IHRoaXMuYm91bmRzXHJcbiAgdmFyIGxveCA9IGJvdW5kc1swXSA9IHhbMF1cclxuICB2YXIgbG95ID0gYm91bmRzWzFdID0geVswXVxyXG4gIHZhciBoaXggPSBib3VuZHNbMl0gPSB4W3gubGVuZ3RoIC0gMV1cclxuICB2YXIgaGl5ID0gYm91bmRzWzNdID0geVt5Lmxlbmd0aCAtIDFdXHJcblxyXG4gIHZhciB4cyA9IDEuMCAvIChoaXggLSBsb3gpXHJcbiAgdmFyIHlzID0gMS4wIC8gKGhpeSAtIGxveSlcclxuXHJcbiAgdmFyIG51bVggPSBzaGFwZVswXVxyXG4gIHZhciBudW1ZID0gc2hhcGVbMV1cclxuXHJcbiAgdGhpcy5zaGFwZSA9IFtudW1YLCBudW1ZXVxyXG5cclxuICB2YXIgbnVtVmVydHMgPSAobnVtWCAtIDEpICogKG51bVkgLSAxKSAqIChXRUlHSFRTLmxlbmd0aCA+Pj4gMSlcclxuXHJcbiAgdGhpcy5udW1WZXJ0aWNlcyA9IG51bVZlcnRzXHJcblxyXG4gIHZhciBjb2xvcnMgPSBwb29sLm1hbGxvY1VpbnQ4KG51bVZlcnRzICogNClcclxuICB2YXIgcG9zaXRpb25zID0gcG9vbC5tYWxsb2NGbG9hdDMyKG51bVZlcnRzICogMilcclxuICB2YXIgd2VpZ2h0cyAgID0gcG9vbC5tYWxsb2NVaW50OCAobnVtVmVydHMgKiAyKVxyXG4gIHZhciBpZHMgPSBwb29sLm1hbGxvY1VpbnQzMihudW1WZXJ0cylcclxuXHJcbiAgdmFyIHB0ciA9IDBcclxuXHJcbiAgZm9yICh2YXIgaiA9IDA7IGogPCBudW1ZIC0gMTsgKytqKSB7XHJcbiAgICB2YXIgeWMwID0geXMgKiAoeVtqXSAtIGxveSlcclxuICAgIHZhciB5YzEgPSB5cyAqICh5W2ogKyAxXSAtIGxveSlcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtWCAtIDE7ICsraSkge1xyXG4gICAgICB2YXIgeGMwID0geHMgKiAoeFtpXSAtIGxveClcclxuICAgICAgdmFyIHhjMSA9IHhzICogKHhbaSArIDFdIC0gbG94KVxyXG5cclxuICAgICAgZm9yICh2YXIgZGQgPSAwOyBkZCA8IFdFSUdIVFMubGVuZ3RoOyBkZCArPSAyKSB7XHJcbiAgICAgICAgdmFyIGR4ID0gV0VJR0hUU1tkZF1cclxuICAgICAgICB2YXIgZHkgPSBXRUlHSFRTW2RkICsgMV1cclxuICAgICAgICB2YXIgb2Zmc2V0ID0gKGogKyBkeSkgKiBudW1YICsgKGkgKyBkeClcclxuICAgICAgICB2YXIgemMgPSB6W29mZnNldF1cclxuICAgICAgICB2YXIgY29sb3JJZHggPSBic2VhcmNoLmxlKGNvbG9yTGV2ZWxzLCB6YylcclxuICAgICAgICB2YXIgciwgZywgYiwgYVxyXG4gICAgICAgIGlmIChjb2xvcklkeCA8IDApIHtcclxuICAgICAgICAgIHIgPSBjb2xvclZhbHVlc1swXVxyXG4gICAgICAgICAgZyA9IGNvbG9yVmFsdWVzWzFdXHJcbiAgICAgICAgICBiID0gY29sb3JWYWx1ZXNbMl1cclxuICAgICAgICAgIGEgPSBjb2xvclZhbHVlc1szXVxyXG4gICAgICAgIH0gZWxzZSBpZiAoY29sb3JJZHggPT09IGNvbG9yQ291bnQgLSAxKSB7XHJcbiAgICAgICAgICByID0gY29sb3JWYWx1ZXNbNCAqIGNvbG9yQ291bnQgLSA0XVxyXG4gICAgICAgICAgZyA9IGNvbG9yVmFsdWVzWzQgKiBjb2xvckNvdW50IC0gM11cclxuICAgICAgICAgIGIgPSBjb2xvclZhbHVlc1s0ICogY29sb3JDb3VudCAtIDJdXHJcbiAgICAgICAgICBhID0gY29sb3JWYWx1ZXNbNCAqIGNvbG9yQ291bnQgLSAxXVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB2YXIgdCA9ICh6YyAtIGNvbG9yTGV2ZWxzW2NvbG9ySWR4XSkgL1xyXG4gICAgICAgICAgICAoY29sb3JMZXZlbHNbY29sb3JJZHggKyAxXSAtIGNvbG9yTGV2ZWxzW2NvbG9ySWR4XSlcclxuICAgICAgICAgIHZhciB0aSA9IDEuMCAtIHRcclxuICAgICAgICAgIHZhciBpMCA9IDQgKiBjb2xvcklkeFxyXG4gICAgICAgICAgdmFyIGkxID0gNCAqIChjb2xvcklkeCArIDEpXHJcbiAgICAgICAgICByID0gdGkgKiBjb2xvclZhbHVlc1tpMF0gKyB0ICogY29sb3JWYWx1ZXNbaTFdXHJcbiAgICAgICAgICBnID0gdGkgKiBjb2xvclZhbHVlc1tpMCArIDFdICsgdCAqIGNvbG9yVmFsdWVzW2kxICsgMV1cclxuICAgICAgICAgIGIgPSB0aSAqIGNvbG9yVmFsdWVzW2kwICsgMl0gKyB0ICogY29sb3JWYWx1ZXNbaTEgKyAyXVxyXG4gICAgICAgICAgYSA9IHRpICogY29sb3JWYWx1ZXNbaTAgKyAzXSArIHQgKiBjb2xvclZhbHVlc1tpMSArIDNdXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb2xvcnNbNCAqIHB0cl0gPSAyNTUgKiByXHJcbiAgICAgICAgY29sb3JzWzQgKiBwdHIgKyAxXSA9IDI1NSAqIGdcclxuICAgICAgICBjb2xvcnNbNCAqIHB0ciArIDJdID0gMjU1ICogYlxyXG4gICAgICAgIGNvbG9yc1s0ICogcHRyICsgM10gPSAyNTUgKiBhXHJcblxyXG4gICAgICAgIHBvc2l0aW9uc1syKnB0cl0gPSB4YzAqLjUgKyB4YzEqLjU7XHJcbiAgICAgICAgcG9zaXRpb25zWzIqcHRyKzFdID0geWMwKi41ICsgeWMxKi41O1xyXG5cclxuICAgICAgICB3ZWlnaHRzWzIqcHRyXSA9IGR4O1xyXG4gICAgICAgIHdlaWdodHNbMipwdHIrMV0gPSBkeTtcclxuXHJcbiAgICAgICAgaWRzW3B0cl0gPSBqICogbnVtWCArIGlcclxuXHJcbiAgICAgICAgcHRyICs9IDFcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGhpcy5wb3NpdGlvbkJ1ZmZlci51cGRhdGUocG9zaXRpb25zKVxyXG4gIHRoaXMud2VpZ2h0QnVmZmVyLnVwZGF0ZSh3ZWlnaHRzKVxyXG4gIHRoaXMuY29sb3JCdWZmZXIudXBkYXRlKGNvbG9ycylcclxuICB0aGlzLmlkQnVmZmVyLnVwZGF0ZShpZHMpXHJcblxyXG4gIHBvb2wuZnJlZShwb3NpdGlvbnMpXHJcbiAgcG9vbC5mcmVlKGNvbG9ycylcclxuICBwb29sLmZyZWUod2VpZ2h0cylcclxuICBwb29sLmZyZWUoaWRzKVxyXG59XHJcblxyXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gKCkge1xyXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcclxuICB0aGlzLnBvc2l0aW9uQnVmZmVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMud2VpZ2h0QnVmZmVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMuY29sb3JCdWZmZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5pZEJ1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLnBsb3QucmVtb3ZlT2JqZWN0KHRoaXMpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUhlYXRtYXAyRCAocGxvdCwgb3B0aW9ucykge1xyXG4gIHZhciBnbCA9IHBsb3QuZ2xcclxuXHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy52ZXJ0ZXgsIHNoYWRlcnMuZnJhZ21lbnQpXHJcbiAgdmFyIHBpY2tTaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHNoYWRlcnMucGlja1ZlcnRleCwgc2hhZGVycy5waWNrRnJhZ21lbnQpXHJcblxyXG4gIHZhciBwb3NpdGlvbkJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgd2VpZ2h0QnVmZmVyICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGNvbG9yQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBpZEJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuXHJcbiAgdmFyIGhlYXRtYXAgPSBuZXcgR0xIZWF0bWFwMkQoXHJcbiAgICBwbG90LFxyXG4gICAgc2hhZGVyLFxyXG4gICAgcGlja1NoYWRlcixcclxuICAgIHBvc2l0aW9uQnVmZmVyLFxyXG4gICAgd2VpZ2h0QnVmZmVyLFxyXG4gICAgY29sb3JCdWZmZXIsXHJcbiAgICBpZEJ1ZmZlcilcclxuXHJcbiAgaGVhdG1hcC51cGRhdGUob3B0aW9ucylcclxuICBwbG90LmFkZE9iamVjdChoZWF0bWFwKVxyXG5cclxuICByZXR1cm4gaGVhdG1hcFxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGdsc2xpZnkgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gIGZyYWdtZW50OiAgICAgZ2xzbGlmeShbXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChmcmFnQ29sb3IucmdiICogZnJhZ0NvbG9yLmEsIGZyYWdDb2xvci5hKTtcXG59XFxuXCJdKSxcclxuICB2ZXJ0ZXg6ICAgICAgIGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5hdHRyaWJ1dGUgdmVjMiB3ZWlnaHQ7XFxuXFxudW5pZm9ybSB2ZWMyIHNoYXBlO1xcbnVuaWZvcm0gbWF0MyB2aWV3VHJhbnNmb3JtO1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyB2UG9zaXRpb24gPSB2aWV3VHJhbnNmb3JtICogdmVjMyggcG9zaXRpb24gKyAod2VpZ2h0LS41KS8oc2hhcGUtMS4pICwgMS4wKTtcXG4gIGZyYWdDb2xvciA9IGNvbG9yO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHZQb3NpdGlvbi54eSwgMCwgdlBvc2l0aW9uLnopO1xcbn1cXG5cIl0pLFxyXG4gIHBpY2tGcmFnbWVudDogZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnZhcnlpbmcgdmVjNCBmcmFnSWQ7XFxudmFyeWluZyB2ZWMyIHZXZWlnaHQ7XFxuXFxudW5pZm9ybSB2ZWMyIHNoYXBlO1xcbnVuaWZvcm0gdmVjNCBwaWNrT2Zmc2V0O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzIgZCA9IHN0ZXAoLjUsIHZXZWlnaHQpO1xcbiAgdmVjNCBpZCA9IGZyYWdJZCArIHBpY2tPZmZzZXQ7XFxuICBpZC54ICs9IGQueCArIGQueSpzaGFwZS54O1xcblxcbiAgaWQueSArPSBmbG9vcihpZC54IC8gMjU2LjApO1xcbiAgaWQueCAtPSBmbG9vcihpZC54IC8gMjU2LjApICogMjU2LjA7XFxuXFxuICBpZC56ICs9IGZsb29yKGlkLnkgLyAyNTYuMCk7XFxuICBpZC55IC09IGZsb29yKGlkLnkgLyAyNTYuMCkgKiAyNTYuMDtcXG5cXG4gIGlkLncgKz0gZmxvb3IoaWQueiAvIDI1Ni4wKTtcXG4gIGlkLnogLT0gZmxvb3IoaWQueiAvIDI1Ni4wKSAqIDI1Ni4wO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gaWQvMjU1LjtcXG59XFxuXCJdKSxcclxuICBwaWNrVmVydGV4OiAgIGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBwaWNrSWQ7XFxuYXR0cmlidXRlIHZlYzIgd2VpZ2h0O1xcblxcbnVuaWZvcm0gdmVjMiBzaGFwZTtcXG51bmlmb3JtIG1hdDMgdmlld1RyYW5zZm9ybTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0lkO1xcbnZhcnlpbmcgdmVjMiB2V2VpZ2h0O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZXZWlnaHQgPSB3ZWlnaHQ7XFxuXFxuICBmcmFnSWQgPSBwaWNrSWQ7XFxuXFxuICB2ZWMzIHZQb3NpdGlvbiA9IHZpZXdUcmFuc2Zvcm0gKiB2ZWMzKCBwb3NpdGlvbiArICh3ZWlnaHQtLjUpLyhzaGFwZS0xLikgLCAxLjApO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHZQb3NpdGlvbi54eSwgMCwgdlBvc2l0aW9uLnopO1xcbn1cXG5cIl0pXHJcbn1cclxuIiwidmFyIGdsc2xpZnkgICAgICAgPSByZXF1aXJlKCdnbHNsaWZ5JylcbnZhciBjcmVhdGVTaGFkZXIgID0gcmVxdWlyZSgnZ2wtc2hhZGVyJylcblxudmFyIHZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb24sIG5leHRQb3NpdGlvbjtcXG5hdHRyaWJ1dGUgZmxvYXQgYXJjTGVuZ3RoLCBsaW5lV2lkdGg7XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuXFxudW5pZm9ybSB2ZWMyIHNjcmVlblNoYXBlO1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbztcXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG52YXJ5aW5nIHZlYzMgd29ybGRQb3NpdGlvbjtcXG52YXJ5aW5nIGZsb2F0IHBpeGVsQXJjTGVuZ3RoO1xcblxcbnZlYzQgcHJvamVjdCh2ZWMzIHApIHtcXG4gIHJldHVybiBwcm9qZWN0aW9uICogdmlldyAqIG1vZGVsICogdmVjNChwLCAxLjApO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICB2ZWM0IHN0YXJ0UG9pbnQgPSBwcm9qZWN0KHBvc2l0aW9uKTtcXG4gIHZlYzQgZW5kUG9pbnQgICA9IHByb2plY3QobmV4dFBvc2l0aW9uKTtcXG5cXG4gIHZlYzIgQSA9IHN0YXJ0UG9pbnQueHkgLyBzdGFydFBvaW50Lnc7XFxuICB2ZWMyIEIgPSAgIGVuZFBvaW50Lnh5IC8gICBlbmRQb2ludC53O1xcblxcbiAgZmxvYXQgY2xpcEFuZ2xlID0gYXRhbihcXG4gICAgKEIueSAtIEEueSkgKiBzY3JlZW5TaGFwZS55LFxcbiAgICAoQi54IC0gQS54KSAqIHNjcmVlblNoYXBlLnhcXG4gICk7XFxuXFxuICB2ZWMyIG9mZnNldCA9IDAuNSAqIHBpeGVsUmF0aW8gKiBsaW5lV2lkdGggKiB2ZWMyKFxcbiAgICBzaW4oY2xpcEFuZ2xlKSxcXG4gICAgLWNvcyhjbGlwQW5nbGUpXFxuICApIC8gc2NyZWVuU2hhcGU7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQoc3RhcnRQb2ludC54eSArIHN0YXJ0UG9pbnQudyAqIG9mZnNldCwgc3RhcnRQb2ludC56dyk7XFxuXFxuICB3b3JsZFBvc2l0aW9uID0gcG9zaXRpb247XFxuICBwaXhlbEFyY0xlbmd0aCA9IGFyY0xlbmd0aDtcXG4gIGZyYWdDb2xvciA9IGNvbG9yO1xcbn1cXG5cIl0pXG52YXIgZm9yd2FyZEZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzICAgICAgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIHNhbXBsZXIyRCBkYXNoVGV4dHVyZTtcXG51bmlmb3JtIGZsb2F0ICAgICBkYXNoU2NhbGU7XFxudW5pZm9ybSBmbG9hdCAgICAgb3BhY2l0eTtcXG5cXG52YXJ5aW5nIHZlYzMgICAgd29ybGRQb3NpdGlvbjtcXG52YXJ5aW5nIGZsb2F0ICAgcGl4ZWxBcmNMZW5ndGg7XFxudmFyeWluZyB2ZWM0ICAgIGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCB3b3JsZFBvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIGZsb2F0IGRhc2hXZWlnaHQgPSB0ZXh0dXJlMkQoZGFzaFRleHR1cmUsIHZlYzIoZGFzaFNjYWxlICogcGl4ZWxBcmNMZW5ndGgsIDApKS5yO1xcbiAgaWYoZGFzaFdlaWdodCA8IDAuNSkge1xcbiAgICBkaXNjYXJkO1xcbiAgfVxcbiAgZ2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yICogb3BhY2l0eTtcXG59XFxuXCJdKVxudmFyIHBpY2tGcmFnID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbiNkZWZpbmUgRkxPQVRfTUFYICAxLjcwMTQxMTg0ZTM4XFxuI2RlZmluZSBGTE9BVF9NSU4gIDEuMTc1NDk0MzVlLTM4XFxuXFxubG93cCB2ZWM0IGVuY29kZV9mbG9hdF8xNTQwMjU5MTMwKGhpZ2hwIGZsb2F0IHYpIHtcXG4gIGhpZ2hwIGZsb2F0IGF2ID0gYWJzKHYpO1xcblxcbiAgLy9IYW5kbGUgc3BlY2lhbCBjYXNlc1xcbiAgaWYoYXYgPCBGTE9BVF9NSU4pIHtcXG4gICAgcmV0dXJuIHZlYzQoMC4wLCAwLjAsIDAuMCwgMC4wKTtcXG4gIH0gZWxzZSBpZih2ID4gRkxPQVRfTUFYKSB7XFxuICAgIHJldHVybiB2ZWM0KDEyNy4wLCAxMjguMCwgMC4wLCAwLjApIC8gMjU1LjA7XFxuICB9IGVsc2UgaWYodiA8IC1GTE9BVF9NQVgpIHtcXG4gICAgcmV0dXJuIHZlYzQoMjU1LjAsIDEyOC4wLCAwLjAsIDAuMCkgLyAyNTUuMDtcXG4gIH1cXG5cXG4gIGhpZ2hwIHZlYzQgYyA9IHZlYzQoMCwwLDAsMCk7XFxuXFxuICAvL0NvbXB1dGUgZXhwb25lbnQgYW5kIG1hbnRpc3NhXFxuICBoaWdocCBmbG9hdCBlID0gZmxvb3IobG9nMihhdikpO1xcbiAgaGlnaHAgZmxvYXQgbSA9IGF2ICogcG93KDIuMCwgLWUpIC0gMS4wO1xcbiAgXFxuICAvL1VucGFjayBtYW50aXNzYVxcbiAgY1sxXSA9IGZsb29yKDEyOC4wICogbSk7XFxuICBtIC09IGNbMV0gLyAxMjguMDtcXG4gIGNbMl0gPSBmbG9vcigzMjc2OC4wICogbSk7XFxuICBtIC09IGNbMl0gLyAzMjc2OC4wO1xcbiAgY1szXSA9IGZsb29yKDgzODg2MDguMCAqIG0pO1xcbiAgXFxuICAvL1VucGFjayBleHBvbmVudFxcbiAgaGlnaHAgZmxvYXQgZWJpYXMgPSBlICsgMTI3LjA7XFxuICBjWzBdID0gZmxvb3IoZWJpYXMgLyAyLjApO1xcbiAgZWJpYXMgLT0gY1swXSAqIDIuMDtcXG4gIGNbMV0gKz0gZmxvb3IoZWJpYXMpICogMTI4LjA7IFxcblxcbiAgLy9VbnBhY2sgc2lnbiBiaXRcXG4gIGNbMF0gKz0gMTI4LjAgKiBzdGVwKDAuMCwgLXYpO1xcblxcbiAgLy9TY2FsZSBiYWNrIHRvIHJhbmdlXFxuICByZXR1cm4gYyAvIDI1NS4wO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIGZsb2F0IHBpY2tJZDtcXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG5cXG52YXJ5aW5nIHZlYzMgd29ybGRQb3NpdGlvbjtcXG52YXJ5aW5nIGZsb2F0IHBpeGVsQXJjTGVuZ3RoO1xcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgd29ybGRQb3NpdGlvbikpIGRpc2NhcmQ7XFxuXFxuICBnbF9GcmFnQ29sb3IgPSB2ZWM0KHBpY2tJZC8yNTUuMCwgZW5jb2RlX2Zsb2F0XzE1NDAyNTkxMzAocGl4ZWxBcmNMZW5ndGgpLnh5eik7XFxufVwiXSlcblxudmFyIEFUVFJJQlVURVMgPSBbXG4gIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxuICB7bmFtZTogJ25leHRQb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gIHtuYW1lOiAnYXJjTGVuZ3RoJywgdHlwZTogJ2Zsb2F0J30sXG4gIHtuYW1lOiAnbGluZVdpZHRoJywgdHlwZTogJ2Zsb2F0J30sXG4gIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9XG5dXG5cbmV4cG9ydHMuY3JlYXRlU2hhZGVyID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgZm9yd2FyZEZyYWcsIG51bGwsIEFUVFJJQlVURVMpXG59XG5cbmV4cG9ydHMuY3JlYXRlUGlja1NoYWRlciA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHZlcnRTcmMsIHBpY2tGcmFnLCBudWxsLCBBVFRSSUJVVEVTKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlTGluZVBsb3RcblxudmFyIGNyZWF0ZUJ1ZmZlciA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXG52YXIgY3JlYXRlVkFPID0gcmVxdWlyZSgnZ2wtdmFvJylcbnZhciBjcmVhdGVUZXh0dXJlID0gcmVxdWlyZSgnZ2wtdGV4dHVyZTJkJylcbnZhciB1bnBhY2tGbG9hdCA9IHJlcXVpcmUoJ2dsc2wtcmVhZC1mbG9hdCcpXG52YXIgYnNlYXJjaCA9IHJlcXVpcmUoJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcbnZhciBuZGFycmF5ID0gcmVxdWlyZSgnbmRhcnJheScpXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vbGliL3NoYWRlcnMnKVxuXG52YXIgY3JlYXRlU2hhZGVyID0gc2hhZGVycy5jcmVhdGVTaGFkZXJcbnZhciBjcmVhdGVQaWNrU2hhZGVyID0gc2hhZGVycy5jcmVhdGVQaWNrU2hhZGVyXG5cbnZhciBpZGVudGl0eSA9IFsxLCAwLCAwLCAwLFxuICAwLCAxLCAwLCAwLFxuICAwLCAwLCAxLCAwLFxuICAwLCAwLCAwLCAxXVxuXG5mdW5jdGlvbiBkaXN0YW5jZSAoYSwgYikge1xuICB2YXIgcyA9IDAuMFxuICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIHZhciBkID0gYVtpXSAtIGJbaV1cbiAgICBzICs9IGQgKiBkXG4gIH1cbiAgcmV0dXJuIE1hdGguc3FydChzKVxufVxuXG5mdW5jdGlvbiBmaWx0ZXJDbGlwQm91bmRzIChib3VuZHMpIHtcbiAgdmFyIHJlc3VsdCA9IFtbLTFlNiwgLTFlNiwgLTFlNl0sIFsxZTYsIDFlNiwgMWU2XV1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICByZXN1bHRbMF1baV0gPSBNYXRoLm1heChib3VuZHNbMF1baV0sIHJlc3VsdFswXVtpXSlcbiAgICByZXN1bHRbMV1baV0gPSBNYXRoLm1pbihib3VuZHNbMV1baV0sIHJlc3VsdFsxXVtpXSlcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIFBpY2tSZXN1bHQgKHRhdSwgcG9zaXRpb24sIGluZGV4LCBkYXRhQ29vcmRpbmF0ZSkge1xuICB0aGlzLmFyY0xlbmd0aCA9IHRhdVxuICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb25cbiAgdGhpcy5pbmRleCA9IGluZGV4XG4gIHRoaXMuZGF0YUNvb3JkaW5hdGUgPSBkYXRhQ29vcmRpbmF0ZVxufVxuXG5mdW5jdGlvbiBMaW5lUGxvdCAoZ2wsIHNoYWRlciwgcGlja1NoYWRlciwgYnVmZmVyLCB2YW8sIHRleHR1cmUpIHtcbiAgdGhpcy5nbCA9IGdsXG4gIHRoaXMuc2hhZGVyID0gc2hhZGVyXG4gIHRoaXMucGlja1NoYWRlciA9IHBpY2tTaGFkZXJcbiAgdGhpcy5idWZmZXIgPSBidWZmZXJcbiAgdGhpcy52YW8gPSB2YW9cbiAgdGhpcy5jbGlwQm91bmRzID0gW1xuICAgIFsgLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eSBdLFxuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eSBdXVxuICB0aGlzLnBvaW50cyA9IFtdXG4gIHRoaXMuYXJjTGVuZ3RoID0gW11cbiAgdGhpcy52ZXJ0ZXhDb3VudCA9IDBcbiAgdGhpcy5ib3VuZHMgPSBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dXG4gIHRoaXMucGlja0lkID0gMFxuICB0aGlzLmxpbmVXaWR0aCA9IDFcbiAgdGhpcy50ZXh0dXJlID0gdGV4dHVyZVxuICB0aGlzLmRhc2hTY2FsZSA9IDFcbiAgdGhpcy5vcGFjaXR5ID0gMVxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuICB0aGlzLnBpeGVsUmF0aW8gPSAxXG59XG5cbnZhciBwcm90byA9IExpbmVQbG90LnByb3RvdHlwZVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5vcGFjaXR5IDwgMVxufVxuXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMub3BhY2l0eSA+PSAxXG59XG5cbnByb3RvLnBpY2tTbG90cyA9IDFcblxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbiAoaWQpIHtcbiAgdGhpcy5waWNrSWQgPSBpZFxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24gKGNhbWVyYSkge1xuICBpZiAoIXRoaXMudmVydGV4Q291bnQpIHJldHVyblxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXIgPSB0aGlzLnNoYWRlclxuICB2YXIgdmFvID0gdGhpcy52YW9cbiAgc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIudW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6IGNhbWVyYS5tb2RlbCB8fCBpZGVudGl0eSxcbiAgICB2aWV3OiBjYW1lcmEudmlldyB8fCBpZGVudGl0eSxcbiAgICBwcm9qZWN0aW9uOiBjYW1lcmEucHJvamVjdGlvbiB8fCBpZGVudGl0eSxcbiAgICBjbGlwQm91bmRzOiBmaWx0ZXJDbGlwQm91bmRzKHRoaXMuY2xpcEJvdW5kcyksXG4gICAgZGFzaFRleHR1cmU6IHRoaXMudGV4dHVyZS5iaW5kKCksXG4gICAgZGFzaFNjYWxlOiB0aGlzLmRhc2hTY2FsZSAvIHRoaXMuYXJjTGVuZ3RoW3RoaXMuYXJjTGVuZ3RoLmxlbmd0aCAtIDFdLFxuICAgIG9wYWNpdHk6IHRoaXMub3BhY2l0eSxcbiAgICBzY3JlZW5TaGFwZTogW2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0sXG4gICAgcGl4ZWxSYXRpbzogdGhpcy5waXhlbFJhdGlvXG4gIH1cbiAgdmFvLmJpbmQoKVxuICB2YW8uZHJhdyhnbC5UUklBTkdMRV9TVFJJUCwgdGhpcy52ZXJ0ZXhDb3VudClcbiAgdmFvLnVuYmluZCgpXG59XG5cbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24gKGNhbWVyYSkge1xuICBpZiAoIXRoaXMudmVydGV4Q291bnQpIHJldHVyblxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcbiAgdmFyIHZhbyA9IHRoaXMudmFvXG4gIHNoYWRlci5iaW5kKClcbiAgc2hhZGVyLnVuaWZvcm1zID0ge1xuICAgIG1vZGVsOiBjYW1lcmEubW9kZWwgfHwgaWRlbnRpdHksXG4gICAgdmlldzogY2FtZXJhLnZpZXcgfHwgaWRlbnRpdHksXG4gICAgcHJvamVjdGlvbjogY2FtZXJhLnByb2plY3Rpb24gfHwgaWRlbnRpdHksXG4gICAgcGlja0lkOiB0aGlzLnBpY2tJZCxcbiAgICBjbGlwQm91bmRzOiBmaWx0ZXJDbGlwQm91bmRzKHRoaXMuY2xpcEJvdW5kcyksXG4gICAgc2NyZWVuU2hhcGU6IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdLFxuICAgIHBpeGVsUmF0aW86IHRoaXMucGl4ZWxSYXRpb1xuICB9XG4gIHZhby5iaW5kKClcbiAgdmFvLmRyYXcoZ2wuVFJJQU5HTEVfU1RSSVAsIHRoaXMudmVydGV4Q291bnQpXG4gIHZhby51bmJpbmQoKVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICB2YXIgaSwgalxuXG4gIHRoaXMuZGlydHkgPSB0cnVlXG5cbiAgdmFyIGNvbm5lY3RHYXBzID0gISFvcHRpb25zLmNvbm5lY3RHYXBzXG5cbiAgaWYgKCdkYXNoU2NhbGUnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmRhc2hTY2FsZSA9IG9wdGlvbnMuZGFzaFNjYWxlXG4gIH1cbiAgaWYgKCdvcGFjaXR5JyBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5vcGFjaXR5ID0gK29wdGlvbnMub3BhY2l0eVxuICB9XG5cbiAgLy8gUmVjYWxjdWxhdGUgYnVmZmVyIGRhdGFcbiAgdmFyIGJ1ZmZlciA9IFtdXG4gIHZhciBhcmNMZW5ndGhBcnJheSA9IFtdXG4gIHZhciBwb2ludEFycmF5ID0gW11cbiAgdmFyIGFyY0xlbmd0aCA9IDAuMFxuICB2YXIgdmVydGV4Q291bnQgPSAwXG4gIHZhciBib3VuZHMgPSBbXG4gICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5IF0sXG4gICAgWyAtSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5IF1dXG5cbiAgdmFyIHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb24gfHwgb3B0aW9ucy5wb3NpdGlvbnNcbiAgaWYgKHBvc2l0aW9ucykge1xuXG4gICAgLy8gRGVmYXVsdCBjb2xvclxuICAgIHZhciBjb2xvcnMgPSBvcHRpb25zLmNvbG9yIHx8IG9wdGlvbnMuY29sb3JzIHx8IFswLCAwLCAwLCAxXVxuXG4gICAgdmFyIGxpbmVXaWR0aCA9IG9wdGlvbnMubGluZVdpZHRoIHx8IDFcblxuICAgIHZhciBoYWRHYXAgPSBmYWxzZVxuXG4gICAgZmlsbF9sb29wOlxuICAgIGZvciAoaSA9IDE7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBhID0gcG9zaXRpb25zW2kgLSAxXVxuICAgICAgdmFyIGIgPSBwb3NpdGlvbnNbaV1cblxuICAgICAgYXJjTGVuZ3RoQXJyYXkucHVzaChhcmNMZW5ndGgpXG4gICAgICBwb2ludEFycmF5LnB1c2goYS5zbGljZSgpKVxuXG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XG4gICAgICAgIGlmIChpc05hTihhW2pdKSB8fCBpc05hTihiW2pdKSB8fFxuICAgICAgICAgICFpc0Zpbml0ZShhW2pdKSB8fCAhaXNGaW5pdGUoYltqXSkpIHtcblxuICAgICAgICAgIGlmICghY29ubmVjdEdhcHMgJiYgYnVmZmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgMjQ7ICsraykge1xuICAgICAgICAgICAgICBidWZmZXIucHVzaChidWZmZXJbYnVmZmVyLmxlbmd0aCAtIDEyXSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZlcnRleENvdW50ICs9IDJcbiAgICAgICAgICAgIGhhZEdhcCA9IHRydWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcbiAgICAgICAgfVxuICAgICAgICBib3VuZHNbMF1bal0gPSBNYXRoLm1pbihib3VuZHNbMF1bal0sIGFbal0sIGJbal0pXG4gICAgICAgIGJvdW5kc1sxXVtqXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtqXSwgYVtqXSwgYltqXSlcbiAgICAgIH1cblxuICAgICAgdmFyIGFjb2xvciwgYmNvbG9yXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xvcnNbMF0pKSB7XG4gICAgICAgIGFjb2xvciA9IChjb2xvcnMubGVuZ3RoID4gaSAtIDEpID8gY29sb3JzW2kgLSAxXSA6ICAgICAgICAgICAgIC8vIHVzaW5nIGluZGV4IHZhbHVlXG4gICAgICAgICAgICAgICAgIChjb2xvcnMubGVuZ3RoID4gMCkgICAgID8gY29sb3JzW2NvbG9ycy5sZW5ndGggLSAxXSA6IC8vIHVzaW5nIGxhc3QgaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLCAwLCAwLCAxXTsgICAgICAgICAgICAgICAvLyB1c2luZyBibGFja1xuXG4gICAgICAgIGJjb2xvciA9IChjb2xvcnMubGVuZ3RoID4gaSkgPyBjb2xvcnNbaV0gOiAgICAgICAgICAgICAgICAgLy8gdXNpbmcgaW5kZXggdmFsdWVcbiAgICAgICAgICAgICAgICAgKGNvbG9ycy5sZW5ndGggPiAwKSA/IGNvbG9yc1tjb2xvcnMubGVuZ3RoIC0gMV0gOiAvLyB1c2luZyBsYXN0IGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLCAwLCAwLCAxXTsgICAgICAgICAgICAgICAvLyB1c2luZyBibGFja1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWNvbG9yID0gYmNvbG9yID0gY29sb3JzXG4gICAgICB9XG5cbiAgICAgIGlmIChhY29sb3IubGVuZ3RoID09PSAzKSB7XG4gICAgICAgIGFjb2xvciA9IFthY29sb3JbMF0sIGFjb2xvclsxXSwgYWNvbG9yWzJdLCAxXVxuICAgICAgfVxuICAgICAgaWYgKGJjb2xvci5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgYmNvbG9yID0gW2Jjb2xvclswXSwgYmNvbG9yWzFdLCBiY29sb3JbMl0sIDFdXG4gICAgICB9XG5cbiAgICAgIHZhciB3MFxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkobGluZVdpZHRoKSkge1xuICAgICAgICB3MCA9IChsaW5lV2lkdGgubGVuZ3RoID4gaSAtIDEpID8gbGluZVdpZHRoW2kgLSAxXSA6ICAgICAgICAgICAgICAgIC8vIHVzaW5nIGluZGV4IHZhbHVlXG4gICAgICAgICAgICAgKGxpbmVXaWR0aC5sZW5ndGggPiAwKSAgICAgPyBsaW5lV2lkdGhbbGluZVdpZHRoLmxlbmd0aCAtIDFdIDogLy8gdXNpbmcgbGFzdCBpdGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwgMCwgMCwgMV07ICAgICAgICAgICAgICAgICAgICAgLy8gdXNpbmcgYmxhY2tcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHcwID0gbGluZVdpZHRoXG4gICAgICB9XG5cbiAgICAgIHZhciB0MCA9IGFyY0xlbmd0aFxuICAgICAgYXJjTGVuZ3RoICs9IGRpc3RhbmNlKGEsIGIpXG5cbiAgICAgIGlmIChoYWRHYXApIHtcbiAgICAgICAgZm9yIChqID0gMDsgaiA8IDI7ICsraikge1xuICAgICAgICAgIGJ1ZmZlci5wdXNoKFxuICAgICAgICAgICAgYVswXSwgYVsxXSwgYVsyXSwgYlswXSwgYlsxXSwgYlsyXSwgdDAsIHcwLCBhY29sb3JbMF0sIGFjb2xvclsxXSwgYWNvbG9yWzJdLCBhY29sb3JbM10pXG4gICAgICAgIH1cbiAgICAgICAgdmVydGV4Q291bnQgKz0gMlxuICAgICAgICBoYWRHYXAgPSBmYWxzZVxuICAgICAgfVxuXG4gICAgICBidWZmZXIucHVzaChcbiAgICAgICAgYVswXSwgYVsxXSwgYVsyXSwgYlswXSwgYlsxXSwgYlsyXSwgdDAsIHcwLCBhY29sb3JbMF0sIGFjb2xvclsxXSwgYWNvbG9yWzJdLCBhY29sb3JbM10sXG4gICAgICAgIGFbMF0sIGFbMV0sIGFbMl0sIGJbMF0sIGJbMV0sIGJbMl0sIHQwLCAtdzAsIGFjb2xvclswXSwgYWNvbG9yWzFdLCBhY29sb3JbMl0sIGFjb2xvclszXSxcbiAgICAgICAgYlswXSwgYlsxXSwgYlsyXSwgYVswXSwgYVsxXSwgYVsyXSwgYXJjTGVuZ3RoLCAtdzAsIGJjb2xvclswXSwgYmNvbG9yWzFdLCBiY29sb3JbMl0sIGJjb2xvclszXSxcbiAgICAgICAgYlswXSwgYlsxXSwgYlsyXSwgYVswXSwgYVsxXSwgYVsyXSwgYXJjTGVuZ3RoLCB3MCwgYmNvbG9yWzBdLCBiY29sb3JbMV0sIGJjb2xvclsyXSwgYmNvbG9yWzNdKVxuXG4gICAgICB2ZXJ0ZXhDb3VudCArPSA0XG4gICAgfVxuICB9XG4gIHRoaXMuYnVmZmVyLnVwZGF0ZShidWZmZXIpXG5cbiAgYXJjTGVuZ3RoQXJyYXkucHVzaChhcmNMZW5ndGgpXG4gIHBvaW50QXJyYXkucHVzaChwb3NpdGlvbnNbcG9zaXRpb25zLmxlbmd0aCAtIDFdLnNsaWNlKCkpXG5cbiAgdGhpcy5ib3VuZHMgPSBib3VuZHNcblxuICB0aGlzLnZlcnRleENvdW50ID0gdmVydGV4Q291bnRcblxuICB0aGlzLnBvaW50cyA9IHBvaW50QXJyYXlcbiAgdGhpcy5hcmNMZW5ndGggPSBhcmNMZW5ndGhBcnJheVxuXG4gIGlmICgnZGFzaGVzJyBpbiBvcHRpb25zKSB7XG4gICAgdmFyIGRhc2hBcnJheSA9IG9wdGlvbnMuZGFzaGVzXG5cbiAgICAvLyBDYWxjdWxhdGUgcHJlZml4IHN1bVxuICAgIHZhciBwcmVmaXhTdW0gPSBkYXNoQXJyYXkuc2xpY2UoKVxuICAgIHByZWZpeFN1bS51bnNoaWZ0KDApXG4gICAgZm9yIChpID0gMTsgaSA8IHByZWZpeFN1bS5sZW5ndGg7ICsraSkge1xuICAgICAgcHJlZml4U3VtW2ldID0gcHJlZml4U3VtW2kgLSAxXSArIHByZWZpeFN1bVtpXVxuICAgIH1cblxuICAgIHZhciBkYXNoVGV4dHVyZSA9IG5kYXJyYXkobmV3IEFycmF5KDI1NiAqIDQpLCBbMjU2LCAxLCA0XSlcbiAgICBmb3IgKGkgPSAwOyBpIDwgMjU2OyArK2kpIHtcbiAgICAgIGZvciAoaiA9IDA7IGogPCA0OyArK2opIHtcbiAgICAgICAgZGFzaFRleHR1cmUuc2V0KGksIDAsIGosIDApXG4gICAgICB9XG4gICAgICBpZiAoYnNlYXJjaC5sZShwcmVmaXhTdW0sIHByZWZpeFN1bVtwcmVmaXhTdW0ubGVuZ3RoIC0gMV0gKiBpIC8gMjU1LjApICYgMSkge1xuICAgICAgICBkYXNoVGV4dHVyZS5zZXQoaSwgMCwgMCwgMClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhc2hUZXh0dXJlLnNldChpLCAwLCAwLCAyNTUpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50ZXh0dXJlLnNldFBpeGVscyhkYXNoVGV4dHVyZSlcbiAgfVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcbiAgdGhpcy52YW8uZGlzcG9zZSgpXG4gIHRoaXMuYnVmZmVyLmRpc3Bvc2UoKVxufVxuXG5wcm90by5waWNrID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICBpZiAoIXNlbGVjdGlvbikge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgaWYgKHNlbGVjdGlvbi5pZCAhPT0gdGhpcy5waWNrSWQpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIHZhciB0YXUgPSB1bnBhY2tGbG9hdChcbiAgICBzZWxlY3Rpb24udmFsdWVbMF0sXG4gICAgc2VsZWN0aW9uLnZhbHVlWzFdLFxuICAgIHNlbGVjdGlvbi52YWx1ZVsyXSxcbiAgICAwKVxuICB2YXIgaW5kZXggPSBic2VhcmNoLmxlKHRoaXMuYXJjTGVuZ3RoLCB0YXUpXG4gIGlmIChpbmRleCA8IDApIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmIChpbmRleCA9PT0gdGhpcy5hcmNMZW5ndGgubGVuZ3RoIC0gMSkge1xuICAgIHJldHVybiBuZXcgUGlja1Jlc3VsdChcbiAgICAgIHRoaXMuYXJjTGVuZ3RoW3RoaXMuYXJjTGVuZ3RoLmxlbmd0aCAtIDFdLFxuICAgICAgdGhpcy5wb2ludHNbdGhpcy5wb2ludHMubGVuZ3RoIC0gMV0uc2xpY2UoKSxcbiAgICAgIGluZGV4KVxuICB9XG4gIHZhciBhID0gdGhpcy5wb2ludHNbaW5kZXhdXG4gIHZhciBiID0gdGhpcy5wb2ludHNbTWF0aC5taW4oaW5kZXggKyAxLCB0aGlzLnBvaW50cy5sZW5ndGggLSAxKV1cbiAgdmFyIHQgPSAodGF1IC0gdGhpcy5hcmNMZW5ndGhbaW5kZXhdKSAvICh0aGlzLmFyY0xlbmd0aFtpbmRleCArIDFdIC0gdGhpcy5hcmNMZW5ndGhbaW5kZXhdKVxuICB2YXIgdGkgPSAxLjAgLSB0XG4gIHZhciB4ID0gWzAsIDAsIDBdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgeFtpXSA9IHRpICogYVtpXSArIHQgKiBiW2ldXG4gIH1cbiAgdmFyIGRhdGFJbmRleCA9IE1hdGgubWluKCh0IDwgMC41KSA/IGluZGV4IDogKGluZGV4ICsgMSksIHRoaXMucG9pbnRzLmxlbmd0aCAtIDEpXG4gIHJldHVybiBuZXcgUGlja1Jlc3VsdChcbiAgICB0YXUsXG4gICAgeCxcbiAgICBkYXRhSW5kZXgsXG4gICAgdGhpcy5wb2ludHNbZGF0YUluZGV4XSlcbn1cblxuZnVuY3Rpb24gY3JlYXRlTGluZVBsb3QgKG9wdGlvbnMpIHtcbiAgdmFyIGdsID0gb3B0aW9ucy5nbCB8fCAob3B0aW9ucy5zY2VuZSAmJiBvcHRpb25zLnNjZW5lLmdsKVxuXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5uZXh0UG9zaXRpb24ubG9jYXRpb24gPSAxXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmFyY0xlbmd0aC5sb2NhdGlvbiA9IDJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMubGluZVdpZHRoLmxvY2F0aW9uID0gM1xuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiA9IDRcblxuICB2YXIgcGlja1NoYWRlciA9IGNyZWF0ZVBpY2tTaGFkZXIoZ2wpXG4gIHBpY2tTaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcbiAgcGlja1NoYWRlci5hdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi5sb2NhdGlvbiA9IDFcbiAgcGlja1NoYWRlci5hdHRyaWJ1dGVzLmFyY0xlbmd0aC5sb2NhdGlvbiA9IDJcbiAgcGlja1NoYWRlci5hdHRyaWJ1dGVzLmxpbmVXaWR0aC5sb2NhdGlvbiA9IDNcbiAgcGlja1NoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uID0gNFxuXG4gIHZhciBidWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICB7XG4gICAgICAnYnVmZmVyJzogYnVmZmVyLFxuICAgICAgJ3NpemUnOiAzLFxuICAgICAgJ29mZnNldCc6IDAsXG4gICAgICAnc3RyaWRlJzogNDhcbiAgICB9LFxuICAgIHtcbiAgICAgICdidWZmZXInOiBidWZmZXIsXG4gICAgICAnc2l6ZSc6IDMsXG4gICAgICAnb2Zmc2V0JzogMTIsXG4gICAgICAnc3RyaWRlJzogNDhcbiAgICB9LFxuICAgIHtcbiAgICAgICdidWZmZXInOiBidWZmZXIsXG4gICAgICAnc2l6ZSc6IDEsXG4gICAgICAnb2Zmc2V0JzogMjQsXG4gICAgICAnc3RyaWRlJzogNDhcbiAgICB9LFxuICAgIHtcbiAgICAgICdidWZmZXInOiBidWZmZXIsXG4gICAgICAnc2l6ZSc6IDEsXG4gICAgICAnb2Zmc2V0JzogMjgsXG4gICAgICAnc3RyaWRlJzogNDhcbiAgICB9LFxuICAgIHtcbiAgICAgICdidWZmZXInOiBidWZmZXIsXG4gICAgICAnc2l6ZSc6IDQsXG4gICAgICAnb2Zmc2V0JzogMzIsXG4gICAgICAnc3RyaWRlJzogNDhcbiAgICB9XG4gIF0pXG5cbiAgLy8gQ3JlYXRlIHRleHR1cmUgZm9yIGRhc2ggcGF0dGVyblxuICB2YXIgZGVmYXVsdFRleHR1cmUgPSBuZGFycmF5KG5ldyBBcnJheSgyNTYgKiA0KSwgWzI1NiwgMSwgNF0pXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMjU2ICogNDsgKytpKSB7XG4gICAgZGVmYXVsdFRleHR1cmUuZGF0YVtpXSA9IDI1NVxuICB9XG4gIHZhciB0ZXh0dXJlID0gY3JlYXRlVGV4dHVyZShnbCwgZGVmYXVsdFRleHR1cmUpXG4gIHRleHR1cmUud3JhcCA9IGdsLlJFUEVBVFxuXG4gIHZhciBsaW5lUGxvdCA9IG5ldyBMaW5lUGxvdChnbCwgc2hhZGVyLCBwaWNrU2hhZGVyLCBidWZmZXIsIHZhbywgdGV4dHVyZSlcbiAgbGluZVBsb3QudXBkYXRlKG9wdGlvbnMpXG4gIHJldHVybiBsaW5lUGxvdFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpbnZlcnRcblxuLyoqXG4gKiBJbnZlcnRzIGEgbWF0MlxuICpcbiAqIEBhbGlhcyBtYXQyLmludmVydFxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5mdW5jdGlvbiBpbnZlcnQob3V0LCBhKSB7XG4gIHZhciBhMCA9IGFbMF1cbiAgdmFyIGExID0gYVsxXVxuICB2YXIgYTIgPSBhWzJdXG4gIHZhciBhMyA9IGFbM11cbiAgdmFyIGRldCA9IGEwICogYTMgLSBhMiAqIGExXG5cbiAgaWYgKCFkZXQpIHJldHVybiBudWxsXG4gIGRldCA9IDEuMCAvIGRldFxuXG4gIG91dFswXSA9ICBhMyAqIGRldFxuICBvdXRbMV0gPSAtYTEgKiBkZXRcbiAgb3V0WzJdID0gLWEyICogZGV0XG4gIG91dFszXSA9ICBhMCAqIGRldFxuXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gaW52ZXJ0XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDNcbiAqXG4gKiBAYWxpYXMgbWF0My5pbnZlcnRcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDN9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuZnVuY3Rpb24gaW52ZXJ0KG91dCwgYSkge1xuICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXVxuICB2YXIgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XVxuICB2YXIgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XVxuXG4gIHZhciBiMDEgPSBhMjIgKiBhMTEgLSBhMTIgKiBhMjFcbiAgdmFyIGIxMSA9IC1hMjIgKiBhMTAgKyBhMTIgKiBhMjBcbiAgdmFyIGIyMSA9IGEyMSAqIGExMCAtIGExMSAqIGEyMFxuXG4gIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgdmFyIGRldCA9IGEwMCAqIGIwMSArIGEwMSAqIGIxMSArIGEwMiAqIGIyMVxuXG4gIGlmICghZGV0KSByZXR1cm4gbnVsbFxuICBkZXQgPSAxLjAgLyBkZXRcblxuICBvdXRbMF0gPSBiMDEgKiBkZXRcbiAgb3V0WzFdID0gKC1hMjIgKiBhMDEgKyBhMDIgKiBhMjEpICogZGV0XG4gIG91dFsyXSA9IChhMTIgKiBhMDEgLSBhMDIgKiBhMTEpICogZGV0XG4gIG91dFszXSA9IGIxMSAqIGRldFxuICBvdXRbNF0gPSAoYTIyICogYTAwIC0gYTAyICogYTIwKSAqIGRldFxuICBvdXRbNV0gPSAoLWExMiAqIGEwMCArIGEwMiAqIGExMCkgKiBkZXRcbiAgb3V0WzZdID0gYjIxICogZGV0XG4gIG91dFs3XSA9ICgtYTIxICogYTAwICsgYTAxICogYTIwKSAqIGRldFxuICBvdXRbOF0gPSAoYTExICogYTAwIC0gYTAxICogYTEwKSAqIGRldFxuXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gY2xvbmU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQ0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xuZnVuY3Rpb24gY2xvbmUoYSkge1xuICAgIHZhciBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICBvdXRbOV0gPSBhWzldO1xuICAgIG91dFsxMF0gPSBhWzEwXTtcbiAgICBvdXRbMTFdID0gYVsxMV07XG4gICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gY3JlYXRlO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0NFxuICpcbiAqIEByZXR1cm5zIHttYXQ0fSBhIG5ldyA0eDQgbWF0cml4XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSgxNik7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGRldGVybWluYW50O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0NFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5mdW5jdGlvbiBkZXRlcm1pbmFudChhKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV0sXG5cbiAgICAgICAgYjAwID0gYTAwICogYTExIC0gYTAxICogYTEwLFxuICAgICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXG4gICAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcbiAgICAgICAgYjAzID0gYTAxICogYTEyIC0gYTAyICogYTExLFxuICAgICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXG4gICAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcbiAgICAgICAgYjA2ID0gYTIwICogYTMxIC0gYTIxICogYTMwLFxuICAgICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXG4gICAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcbiAgICAgICAgYjA5ID0gYTIxICogYTMyIC0gYTIyICogYTMxLFxuICAgICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXG4gICAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMjtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICByZXR1cm4gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGZyb21RdWF0O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIHF1YXRlcm5pb24gcm90YXRpb24uXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtxdWF0NH0gcSBSb3RhdGlvbiBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGZyb21RdWF0KG91dCwgcSkge1xuICAgIHZhciB4ID0gcVswXSwgeSA9IHFbMV0sIHogPSBxWzJdLCB3ID0gcVszXSxcbiAgICAgICAgeDIgPSB4ICsgeCxcbiAgICAgICAgeTIgPSB5ICsgeSxcbiAgICAgICAgejIgPSB6ICsgeixcblxuICAgICAgICB4eCA9IHggKiB4MixcbiAgICAgICAgeXggPSB5ICogeDIsXG4gICAgICAgIHl5ID0geSAqIHkyLFxuICAgICAgICB6eCA9IHogKiB4MixcbiAgICAgICAgenkgPSB6ICogeTIsXG4gICAgICAgIHp6ID0geiAqIHoyLFxuICAgICAgICB3eCA9IHcgKiB4MixcbiAgICAgICAgd3kgPSB3ICogeTIsXG4gICAgICAgIHd6ID0gdyAqIHoyO1xuXG4gICAgb3V0WzBdID0gMSAtIHl5IC0geno7XG4gICAgb3V0WzFdID0geXggKyB3ejtcbiAgICBvdXRbMl0gPSB6eCAtIHd5O1xuICAgIG91dFszXSA9IDA7XG5cbiAgICBvdXRbNF0gPSB5eCAtIHd6O1xuICAgIG91dFs1XSA9IDEgLSB4eCAtIHp6O1xuICAgIG91dFs2XSA9IHp5ICsgd3g7XG4gICAgb3V0WzddID0gMDtcblxuICAgIG91dFs4XSA9IHp4ICsgd3k7XG4gICAgb3V0WzldID0genkgLSB3eDtcbiAgICBvdXRbMTBdID0gMSAtIHh4IC0geXk7XG4gICAgb3V0WzExXSA9IDA7XG5cbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcblxuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gZnJvbVJvdGF0aW9uVHJhbnNsYXRpb247XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiBhbmQgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIHZhciBxdWF0TWF0ID0gbWF0NC5jcmVhdGUoKTtcbiAqICAgICBxdWF0NC50b01hdDQocXVhdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5tdWx0aXBseShkZXN0LCBxdWF0TWF0KTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7dmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24ob3V0LCBxLCB2KSB7XG4gICAgLy8gUXVhdGVybmlvbiBtYXRoXG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB4eSA9IHggKiB5MixcbiAgICAgICAgeHogPSB4ICogejIsXG4gICAgICAgIHl5ID0geSAqIHkyLFxuICAgICAgICB5eiA9IHkgKiB6MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0gKHl5ICsgenopO1xuICAgIG91dFsxXSA9IHh5ICsgd3o7XG4gICAgb3V0WzJdID0geHogLSB3eTtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IHh5IC0gd3o7XG4gICAgb3V0WzVdID0gMSAtICh4eCArIHp6KTtcbiAgICBvdXRbNl0gPSB5eiArIHd4O1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0geHogKyB3eTtcbiAgICBvdXRbOV0gPSB5eiAtIHd4O1xuICAgIG91dFsxMF0gPSAxIC0gKHh4ICsgeXkpO1xuICAgIG91dFsxMV0gPSAwO1xuICAgIG91dFsxMl0gPSB2WzBdO1xuICAgIG91dFsxM10gPSB2WzFdO1xuICAgIG91dFsxNF0gPSB2WzJdO1xuICAgIG91dFsxNV0gPSAxO1xuICAgIFxuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gaWRlbnRpdHk7XG5cbi8qKlxuICogU2V0IGEgbWF0NCB0byB0aGUgaWRlbnRpdHkgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gaWRlbnRpdHkob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IGludmVydDtcblxuLyoqXG4gKiBJbnZlcnRzIGEgbWF0NFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gaW52ZXJ0KG91dCwgYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzIsXG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBkZXRlcm1pbmFudFxuICAgICAgICBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7XG5cbiAgICBpZiAoIWRldCkgeyBcbiAgICAgICAgcmV0dXJuIG51bGw7IFxuICAgIH1cbiAgICBkZXQgPSAxLjAgLyBkZXQ7XG5cbiAgICBvdXRbMF0gPSAoYTExICogYjExIC0gYTEyICogYjEwICsgYTEzICogYjA5KSAqIGRldDtcbiAgICBvdXRbMV0gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgICBvdXRbMl0gPSAoYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzKSAqIGRldDtcbiAgICBvdXRbM10gPSAoYTIyICogYjA0IC0gYTIxICogYjA1IC0gYTIzICogYjAzKSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYTEyICogYjA4IC0gYTEwICogYjExIC0gYTEzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNV0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNl0gPSAoYTMyICogYjAyIC0gYTMwICogYjA1IC0gYTMzICogYjAxKSAqIGRldDtcbiAgICBvdXRbN10gPSAoYTIwICogYjA1IC0gYTIyICogYjAyICsgYTIzICogYjAxKSAqIGRldDtcbiAgICBvdXRbOF0gPSAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldDtcbiAgICBvdXRbOV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTBdID0gKGEzMCAqIGIwNCAtIGEzMSAqIGIwMiArIGEzMyAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzExXSA9IChhMjEgKiBiMDIgLSBhMjAgKiBiMDQgLSBhMjMgKiBiMDApICogZGV0O1xuICAgIG91dFsxMl0gPSAoYTExICogYjA3IC0gYTEwICogYjA5IC0gYTEyICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTNdID0gKGEwMCAqIGIwOSAtIGEwMSAqIGIwNyArIGEwMiAqIGIwNikgKiBkZXQ7XG4gICAgb3V0WzE0XSA9IChhMzEgKiBiMDEgLSBhMzAgKiBiMDMgLSBhMzIgKiBiMDApICogZGV0O1xuICAgIG91dFsxNV0gPSAoYTIwICogYjAzIC0gYTIxICogYjAxICsgYTIyICogYjAwKSAqIGRldDtcblxuICAgIHJldHVybiBvdXQ7XG59OyIsInZhciBpZGVudGl0eSA9IHJlcXVpcmUoJy4vaWRlbnRpdHknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBsb29rQXQ7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgbG9vay1hdCBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gZXllIHBvc2l0aW9uLCBmb2NhbCBwb2ludCwgYW5kIHVwIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge3ZlYzN9IGV5ZSBQb3NpdGlvbiBvZiB0aGUgdmlld2VyXG4gKiBAcGFyYW0ge3ZlYzN9IGNlbnRlciBQb2ludCB0aGUgdmlld2VyIGlzIGxvb2tpbmcgYXRcbiAqIEBwYXJhbSB7dmVjM30gdXAgdmVjMyBwb2ludGluZyB1cFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiBsb29rQXQob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgICB2YXIgeDAsIHgxLCB4MiwgeTAsIHkxLCB5MiwgejAsIHoxLCB6MiwgbGVuLFxuICAgICAgICBleWV4ID0gZXllWzBdLFxuICAgICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgICBleWV6ID0gZXllWzJdLFxuICAgICAgICB1cHggPSB1cFswXSxcbiAgICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICAgIHVweiA9IHVwWzJdLFxuICAgICAgICBjZW50ZXJ4ID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJ5ID0gY2VudGVyWzFdLFxuICAgICAgICBjZW50ZXJ6ID0gY2VudGVyWzJdO1xuXG4gICAgaWYgKE1hdGguYWJzKGV5ZXggLSBjZW50ZXJ4KSA8IDAuMDAwMDAxICYmXG4gICAgICAgIE1hdGguYWJzKGV5ZXkgLSBjZW50ZXJ5KSA8IDAuMDAwMDAxICYmXG4gICAgICAgIE1hdGguYWJzKGV5ZXogLSBjZW50ZXJ6KSA8IDAuMDAwMDAxKSB7XG4gICAgICAgIHJldHVybiBpZGVudGl0eShvdXQpO1xuICAgIH1cblxuICAgIHowID0gZXlleCAtIGNlbnRlcng7XG4gICAgejEgPSBleWV5IC0gY2VudGVyeTtcbiAgICB6MiA9IGV5ZXogLSBjZW50ZXJ6O1xuXG4gICAgbGVuID0gMSAvIE1hdGguc3FydCh6MCAqIHowICsgejEgKiB6MSArIHoyICogejIpO1xuICAgIHowICo9IGxlbjtcbiAgICB6MSAqPSBsZW47XG4gICAgejIgKj0gbGVuO1xuXG4gICAgeDAgPSB1cHkgKiB6MiAtIHVweiAqIHoxO1xuICAgIHgxID0gdXB6ICogejAgLSB1cHggKiB6MjtcbiAgICB4MiA9IHVweCAqIHoxIC0gdXB5ICogejA7XG4gICAgbGVuID0gTWF0aC5zcXJ0KHgwICogeDAgKyB4MSAqIHgxICsgeDIgKiB4Mik7XG4gICAgaWYgKCFsZW4pIHtcbiAgICAgICAgeDAgPSAwO1xuICAgICAgICB4MSA9IDA7XG4gICAgICAgIHgyID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZW4gPSAxIC8gbGVuO1xuICAgICAgICB4MCAqPSBsZW47XG4gICAgICAgIHgxICo9IGxlbjtcbiAgICAgICAgeDIgKj0gbGVuO1xuICAgIH1cblxuICAgIHkwID0gejEgKiB4MiAtIHoyICogeDE7XG4gICAgeTEgPSB6MiAqIHgwIC0gejAgKiB4MjtcbiAgICB5MiA9IHowICogeDEgLSB6MSAqIHgwO1xuXG4gICAgbGVuID0gTWF0aC5zcXJ0KHkwICogeTAgKyB5MSAqIHkxICsgeTIgKiB5Mik7XG4gICAgaWYgKCFsZW4pIHtcbiAgICAgICAgeTAgPSAwO1xuICAgICAgICB5MSA9IDA7XG4gICAgICAgIHkyID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZW4gPSAxIC8gbGVuO1xuICAgICAgICB5MCAqPSBsZW47XG4gICAgICAgIHkxICo9IGxlbjtcbiAgICAgICAgeTIgKj0gbGVuO1xuICAgIH1cblxuICAgIG91dFswXSA9IHgwO1xuICAgIG91dFsxXSA9IHkwO1xuICAgIG91dFsyXSA9IHowO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0geDE7XG4gICAgb3V0WzVdID0geTE7XG4gICAgb3V0WzZdID0gejE7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSB4MjtcbiAgICBvdXRbOV0gPSB5MjtcbiAgICBvdXRbMTBdID0gejI7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IC0oeDAgKiBleWV4ICsgeDEgKiBleWV5ICsgeDIgKiBleWV6KTtcbiAgICBvdXRbMTNdID0gLSh5MCAqIGV5ZXggKyB5MSAqIGV5ZXkgKyB5MiAqIGV5ZXopO1xuICAgIG91dFsxNF0gPSAtKHowICogZXlleCArIHoxICogZXlleSArIHoyICogZXlleik7XG4gICAgb3V0WzE1XSA9IDE7XG5cbiAgICByZXR1cm4gb3V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IG11bHRpcGx5O1xuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIG1hdDQnc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7bWF0NH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbXVsdGlwbHkob3V0LCBhLCBiKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV07XG5cbiAgICAvLyBDYWNoZSBvbmx5IHRoZSBjdXJyZW50IGxpbmUgb2YgdGhlIHNlY29uZCBtYXRyaXhcbiAgICB2YXIgYjAgID0gYlswXSwgYjEgPSBiWzFdLCBiMiA9IGJbMl0sIGIzID0gYlszXTsgIFxuICAgIG91dFswXSA9IGIwKmEwMCArIGIxKmExMCArIGIyKmEyMCArIGIzKmEzMDtcbiAgICBvdXRbMV0gPSBiMCphMDEgKyBiMSphMTEgKyBiMiphMjEgKyBiMyphMzE7XG4gICAgb3V0WzJdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFszXSA9IGIwKmEwMyArIGIxKmExMyArIGIyKmEyMyArIGIzKmEzMztcblxuICAgIGIwID0gYls0XTsgYjEgPSBiWzVdOyBiMiA9IGJbNl07IGIzID0gYls3XTtcbiAgICBvdXRbNF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzVdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFs2XSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbN10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbOF07IGIxID0gYls5XTsgYjIgPSBiWzEwXTsgYjMgPSBiWzExXTtcbiAgICBvdXRbOF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzldID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsxMF0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzExXSA9IGIwKmEwMyArIGIxKmExMyArIGIyKmEyMyArIGIzKmEzMztcblxuICAgIGIwID0gYlsxMl07IGIxID0gYlsxM107IGIyID0gYlsxNF07IGIzID0gYlsxNV07XG4gICAgb3V0WzEyXSA9IGIwKmEwMCArIGIxKmExMCArIGIyKmEyMCArIGIzKmEzMDtcbiAgICBvdXRbMTNdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsxNF0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzE1XSA9IGIwKmEwMyArIGIxKmExMyArIGIyKmEyMyArIGIzKmEzMztcbiAgICByZXR1cm4gb3V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IHBlcnNwZWN0aXZlO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHBlcnNwZWN0aXZlIHByb2plY3Rpb24gbWF0cml4IHdpdGggdGhlIGdpdmVuIGJvdW5kc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgZnJ1c3R1bSBtYXRyaXggd2lsbCBiZSB3cml0dGVuIGludG9cbiAqIEBwYXJhbSB7bnVtYmVyfSBmb3Z5IFZlcnRpY2FsIGZpZWxkIG9mIHZpZXcgaW4gcmFkaWFuc1xuICogQHBhcmFtIHtudW1iZXJ9IGFzcGVjdCBBc3BlY3QgcmF0aW8uIHR5cGljYWxseSB2aWV3cG9ydCB3aWR0aC9oZWlnaHRcbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHBlcnNwZWN0aXZlKG91dCwgZm92eSwgYXNwZWN0LCBuZWFyLCBmYXIpIHtcbiAgICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IGYgLyBhc3BlY3Q7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSBmO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxMV0gPSAtMTtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gKDIgKiBmYXIgKiBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gcm90YXRlO1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQ0IGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcGFyYW0ge3ZlYzN9IGF4aXMgdGhlIGF4aXMgdG8gcm90YXRlIGFyb3VuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiByb3RhdGUob3V0LCBhLCByYWQsIGF4aXMpIHtcbiAgICB2YXIgeCA9IGF4aXNbMF0sIHkgPSBheGlzWzFdLCB6ID0gYXhpc1syXSxcbiAgICAgICAgbGVuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiksXG4gICAgICAgIHMsIGMsIHQsXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjMsXG4gICAgICAgIGIwMCwgYjAxLCBiMDIsXG4gICAgICAgIGIxMCwgYjExLCBiMTIsXG4gICAgICAgIGIyMCwgYjIxLCBiMjI7XG5cbiAgICBpZiAoTWF0aC5hYnMobGVuKSA8IDAuMDAwMDAxKSB7IHJldHVybiBudWxsOyB9XG4gICAgXG4gICAgbGVuID0gMSAvIGxlbjtcbiAgICB4ICo9IGxlbjtcbiAgICB5ICo9IGxlbjtcbiAgICB6ICo9IGxlbjtcblxuICAgIHMgPSBNYXRoLnNpbihyYWQpO1xuICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICAgIHQgPSAxIC0gYztcblxuICAgIGEwMCA9IGFbMF07IGEwMSA9IGFbMV07IGEwMiA9IGFbMl07IGEwMyA9IGFbM107XG4gICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICBhMjAgPSBhWzhdOyBhMjEgPSBhWzldOyBhMjIgPSBhWzEwXTsgYTIzID0gYVsxMV07XG5cbiAgICAvLyBDb25zdHJ1Y3QgdGhlIGVsZW1lbnRzIG9mIHRoZSByb3RhdGlvbiBtYXRyaXhcbiAgICBiMDAgPSB4ICogeCAqIHQgKyBjOyBiMDEgPSB5ICogeCAqIHQgKyB6ICogczsgYjAyID0geiAqIHggKiB0IC0geSAqIHM7XG4gICAgYjEwID0geCAqIHkgKiB0IC0geiAqIHM7IGIxMSA9IHkgKiB5ICogdCArIGM7IGIxMiA9IHogKiB5ICogdCArIHggKiBzO1xuICAgIGIyMCA9IHggKiB6ICogdCArIHkgKiBzOyBiMjEgPSB5ICogeiAqIHQgLSB4ICogczsgYjIyID0geiAqIHogKiB0ICsgYztcblxuICAgIC8vIFBlcmZvcm0gcm90YXRpb24tc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYjAwICsgYTEwICogYjAxICsgYTIwICogYjAyO1xuICAgIG91dFsxXSA9IGEwMSAqIGIwMCArIGExMSAqIGIwMSArIGEyMSAqIGIwMjtcbiAgICBvdXRbMl0gPSBhMDIgKiBiMDAgKyBhMTIgKiBiMDEgKyBhMjIgKiBiMDI7XG4gICAgb3V0WzNdID0gYTAzICogYjAwICsgYTEzICogYjAxICsgYTIzICogYjAyO1xuICAgIG91dFs0XSA9IGEwMCAqIGIxMCArIGExMCAqIGIxMSArIGEyMCAqIGIxMjtcbiAgICBvdXRbNV0gPSBhMDEgKiBiMTAgKyBhMTEgKiBiMTEgKyBhMjEgKiBiMTI7XG4gICAgb3V0WzZdID0gYTAyICogYjEwICsgYTEyICogYjExICsgYTIyICogYjEyO1xuICAgIG91dFs3XSA9IGEwMyAqIGIxMCArIGExMyAqIGIxMSArIGEyMyAqIGIxMjtcbiAgICBvdXRbOF0gPSBhMDAgKiBiMjAgKyBhMTAgKiBiMjEgKyBhMjAgKiBiMjI7XG4gICAgb3V0WzldID0gYTAxICogYjIwICsgYTExICogYjIxICsgYTIxICogYjIyO1xuICAgIG91dFsxMF0gPSBhMDIgKiBiMjAgKyBhMTIgKiBiMjEgKyBhMjIgKiBiMjI7XG4gICAgb3V0WzExXSA9IGEwMyAqIGIyMCArIGExMyAqIGIyMSArIGEyMyAqIGIyMjtcblxuICAgIGlmIChhICE9PSBvdXQpIHsgLy8gSWYgdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gZGlmZmVyLCBjb3B5IHRoZSB1bmNoYW5nZWQgbGFzdCByb3dcbiAgICAgICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTsiLCJtb2R1bGUuZXhwb3J0cyA9IHJvdGF0ZVg7XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiByb3RhdGVYKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSxcbiAgICAgICAgYTIxID0gYVs5XSxcbiAgICAgICAgYTIyID0gYVsxMF0sXG4gICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgICAgIG91dFswXSAgPSBhWzBdO1xuICAgICAgICBvdXRbMV0gID0gYVsxXTtcbiAgICAgICAgb3V0WzJdICA9IGFbMl07XG4gICAgICAgIG91dFszXSAgPSBhWzNdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFs0XSA9IGExMCAqIGMgKyBhMjAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgKyBhMjIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgKyBhMjMgKiBzO1xuICAgIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICAgIG91dFs5XSA9IGEyMSAqIGMgLSBhMTEgKiBzO1xuICAgIG91dFsxMF0gPSBhMjIgKiBjIC0gYTEyICogcztcbiAgICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSByb3RhdGVZO1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWSBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWShvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGEwMCA9IGFbMF0sXG4gICAgICAgIGEwMSA9IGFbMV0sXG4gICAgICAgIGEwMiA9IGFbMl0sXG4gICAgICAgIGEwMyA9IGFbM10sXG4gICAgICAgIGEyMCA9IGFbOF0sXG4gICAgICAgIGEyMSA9IGFbOV0sXG4gICAgICAgIGEyMiA9IGFbMTBdLFxuICAgICAgICBhMjMgPSBhWzExXTtcblxuICAgIGlmIChhICE9PSBvdXQpIHsgLy8gSWYgdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gZGlmZmVyLCBjb3B5IHRoZSB1bmNoYW5nZWQgcm93c1xuICAgICAgICBvdXRbNF0gID0gYVs0XTtcbiAgICAgICAgb3V0WzVdICA9IGFbNV07XG4gICAgICAgIG91dFs2XSAgPSBhWzZdO1xuICAgICAgICBvdXRbN10gID0gYVs3XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBjIC0gYTIwICogcztcbiAgICBvdXRbMV0gPSBhMDEgKiBjIC0gYTIxICogcztcbiAgICBvdXRbMl0gPSBhMDIgKiBjIC0gYTIyICogcztcbiAgICBvdXRbM10gPSBhMDMgKiBjIC0gYTIzICogcztcbiAgICBvdXRbOF0gPSBhMDAgKiBzICsgYTIwICogYztcbiAgICBvdXRbOV0gPSBhMDEgKiBzICsgYTIxICogYztcbiAgICBvdXRbMTBdID0gYTAyICogcyArIGEyMiAqIGM7XG4gICAgb3V0WzExXSA9IGEwMyAqIHMgKyBhMjMgKiBjO1xuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gcm90YXRlWjtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHJvdGF0ZVoob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLFxuICAgICAgICBhMTEgPSBhWzVdLFxuICAgICAgICBhMTIgPSBhWzZdLFxuICAgICAgICBhMTMgPSBhWzddO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgICAgICBvdXRbOF0gID0gYVs4XTtcbiAgICAgICAgb3V0WzldICA9IGFbOV07XG4gICAgICAgIG91dFsxMF0gPSBhWzEwXTtcbiAgICAgICAgb3V0WzExXSA9IGFbMTFdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFswXSA9IGEwMCAqIGMgKyBhMTAgKiBzO1xuICAgIG91dFsxXSA9IGEwMSAqIGMgKyBhMTEgKiBzO1xuICAgIG91dFsyXSA9IGEwMiAqIGMgKyBhMTIgKiBzO1xuICAgIG91dFszXSA9IGEwMyAqIGMgKyBhMTMgKiBzO1xuICAgIG91dFs0XSA9IGExMCAqIGMgLSBhMDAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgLSBhMDEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgLSBhMDIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgLSBhMDMgKiBzO1xuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gc2NhbGU7XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQ0IGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdGhlIHZlYzMgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICoqL1xuZnVuY3Rpb24gc2NhbGUob3V0LCBhLCB2KSB7XG4gICAgdmFyIHggPSB2WzBdLCB5ID0gdlsxXSwgeiA9IHZbMl07XG5cbiAgICBvdXRbMF0gPSBhWzBdICogeDtcbiAgICBvdXRbMV0gPSBhWzFdICogeDtcbiAgICBvdXRbMl0gPSBhWzJdICogeDtcbiAgICBvdXRbM10gPSBhWzNdICogeDtcbiAgICBvdXRbNF0gPSBhWzRdICogeTtcbiAgICBvdXRbNV0gPSBhWzVdICogeTtcbiAgICBvdXRbNl0gPSBhWzZdICogeTtcbiAgICBvdXRbN10gPSBhWzddICogeTtcbiAgICBvdXRbOF0gPSBhWzhdICogejtcbiAgICBvdXRbOV0gPSBhWzldICogejtcbiAgICBvdXRbMTBdID0gYVsxMF0gKiB6O1xuICAgIG91dFsxMV0gPSBhWzExXSAqIHo7XG4gICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIHJldHVybiBvdXQ7XG59OyIsIm1vZHVsZS5leHBvcnRzID0gdHJhbnNsYXRlO1xuXG4vKipcbiAqIFRyYW5zbGF0ZSBhIG1hdDQgYnkgdGhlIGdpdmVuIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjM30gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHRyYW5zbGF0ZShvdXQsIGEsIHYpIHtcbiAgICB2YXIgeCA9IHZbMF0sIHkgPSB2WzFdLCB6ID0gdlsyXSxcbiAgICAgICAgYTAwLCBhMDEsIGEwMiwgYTAzLFxuICAgICAgICBhMTAsIGExMSwgYTEyLCBhMTMsXG4gICAgICAgIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICAgIGlmIChhID09PSBvdXQpIHtcbiAgICAgICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzJdICogeCArIGFbNl0gKiB5ICsgYVsxMF0gKiB6ICsgYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICAgICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICAgICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFswXSA9IGEwMDsgb3V0WzFdID0gYTAxOyBvdXRbMl0gPSBhMDI7IG91dFszXSA9IGEwMztcbiAgICAgICAgb3V0WzRdID0gYTEwOyBvdXRbNV0gPSBhMTE7IG91dFs2XSA9IGExMjsgb3V0WzddID0gYTEzO1xuICAgICAgICBvdXRbOF0gPSBhMjA7IG91dFs5XSA9IGEyMTsgb3V0WzEwXSA9IGEyMjsgb3V0WzExXSA9IGEyMztcblxuICAgICAgICBvdXRbMTJdID0gYTAwICogeCArIGExMCAqIHkgKyBhMjAgKiB6ICsgYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhMDEgKiB4ICsgYTExICogeSArIGEyMSAqIHogKyBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYTAzICogeCArIGExMyAqIHkgKyBhMjMgKiB6ICsgYVsxNV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSB0cmFuc3Bvc2U7XG5cbi8qKlxuICogVHJhbnNwb3NlIHRoZSB2YWx1ZXMgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiB0cmFuc3Bvc2Uob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgICAgICBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGEwMTtcbiAgICAgICAgb3V0WzZdID0gYVs5XTtcbiAgICAgICAgb3V0WzddID0gYVsxM107XG4gICAgICAgIG91dFs4XSA9IGEwMjtcbiAgICAgICAgb3V0WzldID0gYTEyO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhMDM7XG4gICAgICAgIG91dFsxM10gPSBhMTM7XG4gICAgICAgIG91dFsxNF0gPSBhMjM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGFbMV07XG4gICAgICAgIG91dFs1XSA9IGFbNV07XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhWzJdO1xuICAgICAgICBvdXRbOV0gPSBhWzZdO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbM107XG4gICAgICAgIG91dFsxM10gPSBhWzddO1xuICAgICAgICBvdXRbMTRdID0gYVsxMV07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07IiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gaW52ZXJ0XG5cbnZhciBpbnZlcnQyID0gcmVxdWlyZSgnZ2wtbWF0Mi9pbnZlcnQnKVxudmFyIGludmVydDMgPSByZXF1aXJlKCdnbC1tYXQzL2ludmVydCcpXG52YXIgaW52ZXJ0NCA9IHJlcXVpcmUoJ2dsLW1hdDQvaW52ZXJ0JylcblxuZnVuY3Rpb24gaW52ZXJ0KG91dCwgTSkge1xuICBzd2l0Y2goTS5sZW5ndGgpIHtcbiAgICBjYXNlIDA6XG4gICAgYnJlYWtcbiAgICBjYXNlIDE6XG4gICAgICBvdXRbMF0gPSAxLjAgLyBNWzBdXG4gICAgYnJlYWtcbiAgICBjYXNlIDQ6XG4gICAgICBpbnZlcnQyKG91dCwgTSlcbiAgICBicmVha1xuICAgIGNhc2UgOTpcbiAgICAgIGludmVydDMob3V0LCBNKVxuICAgIGJyZWFrXG4gICAgY2FzZSAxNjpcbiAgICAgIGludmVydDQob3V0LCBNKVxuICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudGx5IHN1cHBvcnRzIG1hdHJpY2VzIHVwIHRvIDR4NCcpXG4gICAgYnJlYWtcbiAgfVxuICByZXR1cm4gb3V0XG59IiwidmFyIGdsc2xpZnkgICAgICAgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxuXHJcbnZhciB0cmlWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbiwgbm9ybWFsO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbFxcbiAgICAgICAgICAgLCB2aWV3XFxuICAgICAgICAgICAsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIGV5ZVBvc2l0aW9uXFxuICAgICAgICAgICAsIGxpZ2h0UG9zaXRpb247XFxuXFxudmFyeWluZyB2ZWMzIGZfbm9ybWFsXFxuICAgICAgICAgICAsIGZfbGlnaHREaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9leWVEaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9kYXRhO1xcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzQgbV9wb3NpdGlvbiAgPSBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICB2ZWM0IHRfcG9zaXRpb24gID0gdmlldyAqIG1fcG9zaXRpb247XFxuICBnbF9Qb3NpdGlvbiAgICAgID0gcHJvamVjdGlvbiAqIHRfcG9zaXRpb247XFxuICBmX2NvbG9yICAgICAgICAgID0gY29sb3I7XFxuICBmX25vcm1hbCAgICAgICAgID0gbm9ybWFsO1xcbiAgZl9kYXRhICAgICAgICAgICA9IHBvc2l0aW9uO1xcbiAgZl9leWVEaXJlY3Rpb24gICA9IGV5ZVBvc2l0aW9uICAgLSBwb3NpdGlvbjtcXG4gIGZfbGlnaHREaXJlY3Rpb24gPSBsaWdodFBvc2l0aW9uIC0gcG9zaXRpb247XFxuICBmX3V2ICAgICAgICAgICAgID0gdXY7XFxufVxcblwiXSlcclxudmFyIHRyaUZyYWdTcmMgPSBnbHNsaWZ5KFtcIiNleHRlbnNpb24gR0xfT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzIDogZW5hYmxlXFxuXFxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuZmxvYXQgYmVja21hbm5EaXN0cmlidXRpb24oZmxvYXQgeCwgZmxvYXQgcm91Z2huZXNzKSB7XFxuICBmbG9hdCBOZG90SCA9IG1heCh4LCAwLjAwMDEpO1xcbiAgZmxvYXQgY29zMkFscGhhID0gTmRvdEggKiBOZG90SDtcXG4gIGZsb2F0IHRhbjJBbHBoYSA9IChjb3MyQWxwaGEgLSAxLjApIC8gY29zMkFscGhhO1xcbiAgZmxvYXQgcm91Z2huZXNzMiA9IHJvdWdobmVzcyAqIHJvdWdobmVzcztcXG4gIGZsb2F0IGRlbm9tID0gMy4xNDE1OTI2NTM1ODk3OTMgKiByb3VnaG5lc3MyICogY29zMkFscGhhICogY29zMkFscGhhO1xcbiAgcmV0dXJuIGV4cCh0YW4yQWxwaGEgLyByb3VnaG5lc3MyKSAvIGRlbm9tO1xcbn1cXG5cXG5mbG9hdCBjb29rVG9ycmFuY2VTcGVjdWxhcihcXG4gIHZlYzMgbGlnaHREaXJlY3Rpb24sXFxuICB2ZWMzIHZpZXdEaXJlY3Rpb24sXFxuICB2ZWMzIHN1cmZhY2VOb3JtYWwsXFxuICBmbG9hdCByb3VnaG5lc3MsXFxuICBmbG9hdCBmcmVzbmVsKSB7XFxuXFxuICBmbG9hdCBWZG90TiA9IG1heChkb3Qodmlld0RpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbCksIDAuMCk7XFxuICBmbG9hdCBMZG90TiA9IG1heChkb3QobGlnaHREaXJlY3Rpb24sIHN1cmZhY2VOb3JtYWwpLCAwLjApO1xcblxcbiAgLy9IYWxmIGFuZ2xlIHZlY3RvclxcbiAgdmVjMyBIID0gbm9ybWFsaXplKGxpZ2h0RGlyZWN0aW9uICsgdmlld0RpcmVjdGlvbik7XFxuXFxuICAvL0dlb21ldHJpYyB0ZXJtXFxuICBmbG9hdCBOZG90SCA9IG1heChkb3Qoc3VyZmFjZU5vcm1hbCwgSCksIDAuMCk7XFxuICBmbG9hdCBWZG90SCA9IG1heChkb3Qodmlld0RpcmVjdGlvbiwgSCksIDAuMDAwMDAxKTtcXG4gIGZsb2F0IExkb3RIID0gbWF4KGRvdChsaWdodERpcmVjdGlvbiwgSCksIDAuMDAwMDAxKTtcXG4gIGZsb2F0IEcxID0gKDIuMCAqIE5kb3RIICogVmRvdE4pIC8gVmRvdEg7XFxuICBmbG9hdCBHMiA9ICgyLjAgKiBOZG90SCAqIExkb3ROKSAvIExkb3RIO1xcbiAgZmxvYXQgRyA9IG1pbigxLjAsIG1pbihHMSwgRzIpKTtcXG4gIFxcbiAgLy9EaXN0cmlidXRpb24gdGVybVxcbiAgZmxvYXQgRCA9IGJlY2ttYW5uRGlzdHJpYnV0aW9uKE5kb3RILCByb3VnaG5lc3MpO1xcblxcbiAgLy9GcmVzbmVsIHRlcm1cXG4gIGZsb2F0IEYgPSBwb3coMS4wIC0gVmRvdE4sIGZyZXNuZWwpO1xcblxcbiAgLy9NdWx0aXBseSB0ZXJtcyBhbmQgZG9uZVxcbiAgcmV0dXJuICBHICogRiAqIEQgLyBtYXgoMy4xNDE1OTI2NSAqIFZkb3ROLCAwLjAwMDAwMSk7XFxufVxcblxcbnZlYzMgbm9ybWFscyh2ZWMzIHBvcykge1xcbiAgdmVjMyBmZHggPSBkRmR4KHBvcyk7XFxuICB2ZWMzIGZkeSA9IGRGZHkocG9zKTtcXG4gIHJldHVybiBub3JtYWxpemUoY3Jvc3MoZmR4LCBmZHkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCByb3VnaG5lc3NcXG4gICAgICAgICAgICAsIGZyZXNuZWxcXG4gICAgICAgICAgICAsIGthbWJpZW50XFxuICAgICAgICAgICAgLCBrZGlmZnVzZVxcbiAgICAgICAgICAgICwga3NwZWN1bGFyXFxuICAgICAgICAgICAgLCBvcGFjaXR5O1xcbnVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmU7XFxuXFxudmFyeWluZyB2ZWMzIGZfbm9ybWFsXFxuICAgICAgICAgICAsIGZfbGlnaHREaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9leWVEaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9kYXRhO1xcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfZGF0YSkpIGRpc2NhcmQ7XFxuXFxuICB2ZWMzIE4gPSBub3JtYWxpemUoZl9ub3JtYWwpO1xcbiAgdmVjMyBMID0gbm9ybWFsaXplKGZfbGlnaHREaXJlY3Rpb24pO1xcbiAgdmVjMyBWID0gbm9ybWFsaXplKGZfZXllRGlyZWN0aW9uKTtcXG5cXG4gIHZlYzMgbm9ybWFsID0gbm9ybWFscyhmX2RhdGEpO1xcblxcbiAgaWYgKGRvdChOLCBub3JtYWwpIDwgMC4wKSB7XFxuICAgIE4gPSAtTjtcXG4gIH1cXG5cXG4gIGZsb2F0IHNwZWN1bGFyID0gY29va1RvcnJhbmNlU3BlY3VsYXIoTCwgViwgTiwgcm91Z2huZXNzLCBmcmVzbmVsKTtcXG4gIGZsb2F0IGRpZmZ1c2UgID0gbWluKGthbWJpZW50ICsga2RpZmZ1c2UgKiBtYXgoZG90KE4sIEwpLCAwLjApLCAxLjApO1xcblxcbiAgdmVjNCBzdXJmYWNlQ29sb3IgPSBmX2NvbG9yICogdGV4dHVyZTJEKHRleHR1cmUsIGZfdXYpO1xcbiAgdmVjNCBsaXRDb2xvciA9IHN1cmZhY2VDb2xvci5hICogdmVjNChkaWZmdXNlICogc3VyZmFjZUNvbG9yLnJnYiArIGtzcGVjdWxhciAqIHZlYzMoMSwxLDEpICogc3BlY3VsYXIsICAxLjApO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gbGl0Q29sb3IgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXHJcbnZhciBlZGdlVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5hdHRyaWJ1dGUgdmVjMiB1djtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxuXFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMzIGZfZGF0YTtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHBvc2l0aW9uLCAxLjApO1xcbiAgZl9jb2xvciA9IGNvbG9yO1xcbiAgZl9kYXRhICA9IHBvc2l0aW9uO1xcbiAgZl91diAgICA9IHV2O1xcbn1cIl0pXHJcbnZhciBlZGdlRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlO1xcbnVuaWZvcm0gZmxvYXQgb3BhY2l0eTtcXG5cXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzMgZl9kYXRhO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfZGF0YSkpIGRpc2NhcmQ7XFxuXFxuICBnbF9GcmFnQ29sb3IgPSBmX2NvbG9yICogdGV4dHVyZTJEKHRleHR1cmUsIGZfdXYpICogb3BhY2l0eTtcXG59XCJdKVxyXG52YXIgcG9pbnRWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcbmF0dHJpYnV0ZSBmbG9hdCBwb2ludFNpemU7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcblxcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHBvc2l0aW9uKSkge1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMCwwLDAsMCk7XFxuICB9IGVsc2Uge1xcbiAgICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHBvc2l0aW9uLCAxLjApO1xcbiAgfVxcbiAgZ2xfUG9pbnRTaXplID0gcG9pbnRTaXplO1xcbiAgZl9jb2xvciA9IGNvbG9yO1xcbiAgZl91diA9IHV2O1xcbn1cIl0pXHJcbnZhciBwb2ludEZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTtcXG51bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxuXFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMyIGZfdXY7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMiBwb2ludFIgPSBnbF9Qb2ludENvb3JkLnh5IC0gdmVjMigwLjUsMC41KTtcXG4gIGlmKGRvdChwb2ludFIsIHBvaW50UikgPiAwLjI1KSB7XFxuICAgIGRpc2NhcmQ7XFxuICB9XFxuICBnbF9GcmFnQ29sb3IgPSBmX2NvbG9yICogdGV4dHVyZTJEKHRleHR1cmUsIGZfdXYpICogb3BhY2l0eTtcXG59XCJdKVxyXG52YXIgcGlja1ZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICBmX2lkICAgICAgICA9IGlkO1xcbiAgZl9wb3NpdGlvbiAgPSBwb3NpdGlvbjtcXG59XCJdKVxyXG52YXIgcGlja0ZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzICBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcGlja0lkO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfcG9zaXRpb24pKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChwaWNrSWQsIGZfaWQueHl6KTtcXG59XCJdKVxyXG52YXIgcGlja1BvaW50VmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjMyAgcG9zaXRpb247XFxuYXR0cmlidXRlIGZsb2F0IHBvaW50U2l6ZTtcXG5hdHRyaWJ1dGUgdmVjNCAgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHBvc2l0aW9uKSkge1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMCwwLDAsMCk7XFxuICB9IGVsc2Uge1xcbiAgICBnbF9Qb3NpdGlvbiAgPSBwcm9qZWN0aW9uICogdmlldyAqIG1vZGVsICogdmVjNChwb3NpdGlvbiwgMS4wKTtcXG4gICAgZ2xfUG9pbnRTaXplID0gcG9pbnRTaXplO1xcbiAgfVxcbiAgZl9pZCAgICAgICAgID0gaWQ7XFxuICBmX3Bvc2l0aW9uICAgPSBwb3NpdGlvbjtcXG59XCJdKVxyXG52YXIgY29udG91clZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxufVwiXSlcclxudmFyIGNvbnRvdXJGcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gdmVjMyBjb250b3VyQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChjb250b3VyQ29sb3IsMSk7XFxufVxcblwiXSlcclxuXHJcbmV4cG9ydHMubWVzaFNoYWRlciA9IHtcclxuICB2ZXJ0ZXg6ICAgdHJpVmVydFNyYyxcclxuICBmcmFnbWVudDogdHJpRnJhZ1NyYyxcclxuICBhdHRyaWJ1dGVzOiBbXHJcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzMnfSxcclxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfSxcclxuICAgIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9LFxyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWMyJ31cclxuICBdXHJcbn1cclxuZXhwb3J0cy53aXJlU2hhZGVyID0ge1xyXG4gIHZlcnRleDogICBlZGdlVmVydFNyYyxcclxuICBmcmFnbWVudDogZWRnZUZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXHJcbiAgICB7bmFtZTogJ2NvbG9yJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAndXYnLCB0eXBlOiAndmVjMid9XHJcbiAgXVxyXG59XHJcbmV4cG9ydHMucG9pbnRTaGFkZXIgPSB7XHJcbiAgdmVydGV4OiAgIHBvaW50VmVydFNyYyxcclxuICBmcmFnbWVudDogcG9pbnRGcmFnU3JjLFxyXG4gIGF0dHJpYnV0ZXM6IFtcclxuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxyXG4gICAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ3V2JywgdHlwZTogJ3ZlYzInfSxcclxuICAgIHtuYW1lOiAncG9pbnRTaXplJywgdHlwZTogJ2Zsb2F0J31cclxuICBdXHJcbn1cclxuZXhwb3J0cy5waWNrU2hhZGVyID0ge1xyXG4gIHZlcnRleDogICBwaWNrVmVydFNyYyxcclxuICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXHJcbiAgICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfVxyXG4gIF1cclxufVxyXG5leHBvcnRzLnBvaW50UGlja1NoYWRlciA9IHtcclxuICB2ZXJ0ZXg6ICAgcGlja1BvaW50VmVydFNyYyxcclxuICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXHJcbiAgICB7bmFtZTogJ3BvaW50U2l6ZScsIHR5cGU6ICdmbG9hdCd9LFxyXG4gICAge25hbWU6ICdpZCcsIHR5cGU6ICd2ZWM0J31cclxuICBdXHJcbn1cclxuZXhwb3J0cy5jb250b3VyU2hhZGVyID0ge1xyXG4gIHZlcnRleDogICBjb250b3VyVmVydFNyYyxcclxuICBmcmFnbWVudDogY29udG91ckZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ31cclxuICBdXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgREVGQVVMVF9WRVJURVhfTk9STUFMU19FUFNJTE9OID0gMWUtNjsgLy8gbWF5IGJlIHRvbyBsYXJnZSBpZiB0cmlhbmdsZXMgYXJlIHZlcnkgc21hbGxcclxudmFyIERFRkFVTFRfRkFDRV9OT1JNQUxTX0VQU0lMT04gPSAxZS02O1xyXG5cclxudmFyIGNyZWF0ZVNoYWRlciAgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG52YXIgY3JlYXRlQnVmZmVyICA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXHJcbnZhciBjcmVhdGVWQU8gICAgID0gcmVxdWlyZSgnZ2wtdmFvJylcclxudmFyIGNyZWF0ZVRleHR1cmUgPSByZXF1aXJlKCdnbC10ZXh0dXJlMmQnKVxyXG52YXIgbm9ybWFscyAgICAgICA9IHJlcXVpcmUoJ25vcm1hbHMnKVxyXG52YXIgbXVsdGlwbHkgICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvbXVsdGlwbHknKVxyXG52YXIgaW52ZXJ0ICAgICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvaW52ZXJ0JylcclxudmFyIG5kYXJyYXkgICAgICAgPSByZXF1aXJlKCduZGFycmF5JylcclxudmFyIGNvbG9ybWFwICAgICAgPSByZXF1aXJlKCdjb2xvcm1hcCcpXHJcbnZhciBnZXRDb250b3VyICAgID0gcmVxdWlyZSgnc2ltcGxpY2lhbC1jb21wbGV4LWNvbnRvdXInKVxyXG52YXIgcG9vbCAgICAgICAgICA9IHJlcXVpcmUoJ3R5cGVkYXJyYXktcG9vbCcpXHJcbnZhciBzaGFkZXJzICAgICAgID0gcmVxdWlyZSgnLi9saWIvc2hhZGVycycpXHJcbnZhciBjbG9zZXN0UG9pbnQgID0gcmVxdWlyZSgnLi9saWIvY2xvc2VzdC1wb2ludCcpXHJcblxyXG52YXIgbWVzaFNoYWRlciAgICA9IHNoYWRlcnMubWVzaFNoYWRlclxyXG52YXIgd2lyZVNoYWRlciAgICA9IHNoYWRlcnMud2lyZVNoYWRlclxyXG52YXIgcG9pbnRTaGFkZXIgICA9IHNoYWRlcnMucG9pbnRTaGFkZXJcclxudmFyIHBpY2tTaGFkZXIgICAgPSBzaGFkZXJzLnBpY2tTaGFkZXJcclxudmFyIHBvaW50UGlja1NoYWRlciA9IHNoYWRlcnMucG9pbnRQaWNrU2hhZGVyXHJcbnZhciBjb250b3VyU2hhZGVyID0gc2hhZGVycy5jb250b3VyU2hhZGVyXHJcblxyXG52YXIgaWRlbnRpdHlNYXRyaXggPSBbXHJcbiAgMSwwLDAsMCxcclxuICAwLDEsMCwwLFxyXG4gIDAsMCwxLDAsXHJcbiAgMCwwLDAsMV1cclxuXHJcblxyXG5mdW5jdGlvbiBTaW1wbGljaWFsTWVzaChnbFxyXG4gICwgdGV4dHVyZVxyXG4gICwgdHJpU2hhZGVyXHJcbiAgLCBsaW5lU2hhZGVyXHJcbiAgLCBwb2ludFNoYWRlclxyXG4gICwgcGlja1NoYWRlclxyXG4gICwgcG9pbnRQaWNrU2hhZGVyXHJcbiAgLCBjb250b3VyU2hhZGVyXHJcbiAgLCB0cmlhbmdsZVBvc2l0aW9uc1xyXG4gICwgdHJpYW5nbGVJZHNcclxuICAsIHRyaWFuZ2xlQ29sb3JzXHJcbiAgLCB0cmlhbmdsZVVWc1xyXG4gICwgdHJpYW5nbGVOb3JtYWxzXHJcbiAgLCB0cmlhbmdsZVZBT1xyXG4gICwgZWRnZVBvc2l0aW9uc1xyXG4gICwgZWRnZUlkc1xyXG4gICwgZWRnZUNvbG9yc1xyXG4gICwgZWRnZVVWc1xyXG4gICwgZWRnZVZBT1xyXG4gICwgcG9pbnRQb3NpdGlvbnNcclxuICAsIHBvaW50SWRzXHJcbiAgLCBwb2ludENvbG9yc1xyXG4gICwgcG9pbnRVVnNcclxuICAsIHBvaW50U2l6ZXNcclxuICAsIHBvaW50VkFPXHJcbiAgLCBjb250b3VyUG9zaXRpb25zXHJcbiAgLCBjb250b3VyVkFPKSB7XHJcblxyXG4gIHRoaXMuZ2wgICAgICAgICAgICAgICAgPSBnbFxyXG4gIHRoaXMuY2VsbHMgICAgICAgICAgICAgPSBbXVxyXG4gIHRoaXMucG9zaXRpb25zICAgICAgICAgPSBbXVxyXG4gIHRoaXMuaW50ZW5zaXR5ICAgICAgICAgPSBbXVxyXG4gIHRoaXMudGV4dHVyZSAgICAgICAgICAgPSB0ZXh0dXJlXHJcbiAgdGhpcy5kaXJ0eSAgICAgICAgICAgICA9IHRydWVcclxuXHJcbiAgdGhpcy50cmlTaGFkZXIgICAgICAgICA9IHRyaVNoYWRlclxyXG4gIHRoaXMubGluZVNoYWRlciAgICAgICAgPSBsaW5lU2hhZGVyXHJcbiAgdGhpcy5wb2ludFNoYWRlciAgICAgICA9IHBvaW50U2hhZGVyXHJcbiAgdGhpcy5waWNrU2hhZGVyICAgICAgICA9IHBpY2tTaGFkZXJcclxuICB0aGlzLnBvaW50UGlja1NoYWRlciAgID0gcG9pbnRQaWNrU2hhZGVyXHJcbiAgdGhpcy5jb250b3VyU2hhZGVyICAgICA9IGNvbnRvdXJTaGFkZXJcclxuXHJcbiAgdGhpcy50cmlhbmdsZVBvc2l0aW9ucyA9IHRyaWFuZ2xlUG9zaXRpb25zXHJcbiAgdGhpcy50cmlhbmdsZUNvbG9ycyAgICA9IHRyaWFuZ2xlQ29sb3JzXHJcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMgICA9IHRyaWFuZ2xlTm9ybWFsc1xyXG4gIHRoaXMudHJpYW5nbGVVVnMgICAgICAgPSB0cmlhbmdsZVVWc1xyXG4gIHRoaXMudHJpYW5nbGVJZHMgICAgICAgPSB0cmlhbmdsZUlkc1xyXG4gIHRoaXMudHJpYW5nbGVWQU8gICAgICAgPSB0cmlhbmdsZVZBT1xyXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgICAgPSAwXHJcblxyXG4gIHRoaXMubGluZVdpZHRoICAgICAgICAgPSAxXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zICAgICA9IGVkZ2VQb3NpdGlvbnNcclxuICB0aGlzLmVkZ2VDb2xvcnMgICAgICAgID0gZWRnZUNvbG9yc1xyXG4gIHRoaXMuZWRnZVVWcyAgICAgICAgICAgPSBlZGdlVVZzXHJcbiAgdGhpcy5lZGdlSWRzICAgICAgICAgICA9IGVkZ2VJZHNcclxuICB0aGlzLmVkZ2VWQU8gICAgICAgICAgID0gZWRnZVZBT1xyXG4gIHRoaXMuZWRnZUNvdW50ICAgICAgICAgPSAwXHJcblxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMgICAgPSBwb2ludFBvc2l0aW9uc1xyXG4gIHRoaXMucG9pbnRDb2xvcnMgICAgICAgPSBwb2ludENvbG9yc1xyXG4gIHRoaXMucG9pbnRVVnMgICAgICAgICAgPSBwb2ludFVWc1xyXG4gIHRoaXMucG9pbnRTaXplcyAgICAgICAgPSBwb2ludFNpemVzXHJcbiAgdGhpcy5wb2ludElkcyAgICAgICAgICA9IHBvaW50SWRzXHJcbiAgdGhpcy5wb2ludFZBTyAgICAgICAgICA9IHBvaW50VkFPXHJcbiAgdGhpcy5wb2ludENvdW50ICAgICAgICA9IDBcclxuXHJcbiAgdGhpcy5jb250b3VyTGluZVdpZHRoICA9IDFcclxuICB0aGlzLmNvbnRvdXJQb3NpdGlvbnMgID0gY29udG91clBvc2l0aW9uc1xyXG4gIHRoaXMuY29udG91clZBTyAgICAgICAgPSBjb250b3VyVkFPXHJcbiAgdGhpcy5jb250b3VyQ291bnQgICAgICA9IDBcclxuICB0aGlzLmNvbnRvdXJDb2xvciAgICAgID0gWzAsMCwwXVxyXG4gIHRoaXMuY29udG91ckVuYWJsZSAgICAgPSB0cnVlXHJcblxyXG4gIHRoaXMucGlja0lkICAgICAgICAgICAgPSAxXHJcbiAgdGhpcy5ib3VuZHMgICAgICAgICAgICA9IFtcclxuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0sXHJcbiAgICBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldIF1cclxuICB0aGlzLmNsaXBCb3VuZHMgICAgICAgID0gW1xyXG4gICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSxcclxuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0gXVxyXG5cclxuICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBbMWU1LCAxZTUsIDBdXHJcbiAgdGhpcy5hbWJpZW50TGlnaHQgID0gMC44XHJcbiAgdGhpcy5kaWZmdXNlTGlnaHQgID0gMC44XHJcbiAgdGhpcy5zcGVjdWxhckxpZ2h0ID0gMi4wXHJcbiAgdGhpcy5yb3VnaG5lc3MgICAgID0gMC41XHJcbiAgdGhpcy5mcmVzbmVsICAgICAgID0gMS41XHJcblxyXG4gIHRoaXMub3BhY2l0eSAgICAgICA9IDEuMFxyXG5cclxuICB0aGlzLl9tb2RlbCAgICAgICA9IGlkZW50aXR5TWF0cml4XHJcbiAgdGhpcy5fdmlldyAgICAgICAgPSBpZGVudGl0eU1hdHJpeFxyXG4gIHRoaXMuX3Byb2plY3Rpb24gID0gaWRlbnRpdHlNYXRyaXhcclxuICB0aGlzLl9yZXNvbHV0aW9uICA9IFsxLDFdXHJcbn1cclxuXHJcbnZhciBwcm90byA9IFNpbXBsaWNpYWxNZXNoLnByb3RvdHlwZVxyXG5cclxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcclxuICByZXR1cm4gdGhpcy5vcGFjaXR5ID49IDFcclxufVxyXG5cclxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKCkge1xyXG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPCAxXHJcbn1cclxuXHJcbnByb3RvLnBpY2tTbG90cyA9IDFcclxuXHJcbnByb3RvLnNldFBpY2tCYXNlID0gZnVuY3Rpb24oaWQpIHtcclxuICB0aGlzLnBpY2tJZCA9IGlkXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdlbkNvbG9ybWFwKHBhcmFtKSB7XHJcbiAgdmFyIGNvbG9ycyA9IGNvbG9ybWFwKHtcclxuICAgICAgY29sb3JtYXA6IHBhcmFtXHJcbiAgICAsIG5zaGFkZXM6ICAyNTZcclxuICAgICwgZm9ybWF0OiAgJ3JnYmEnXHJcbiAgfSlcclxuXHJcbiAgdmFyIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KDI1Nio0KVxyXG4gIGZvcih2YXIgaT0wOyBpPDI1NjsgKytpKSB7XHJcbiAgICB2YXIgYyA9IGNvbG9yc1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHJlc3VsdFs0Kmkral0gPSBjW2pdXHJcbiAgICB9XHJcbiAgICByZXN1bHRbNCppKzNdID0gY1szXSoyNTVcclxuICB9XHJcblxyXG4gIHJldHVybiBuZGFycmF5KHJlc3VsdCwgWzI1NiwyNTYsNF0sIFs0LDAsMV0pXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVucGFja0ludGVuc2l0eShjZWxscywgbnVtVmVydHMsIGNlbGxJbnRlbnNpdHkpIHtcclxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG51bVZlcnRzKVxyXG4gIGZvcih2YXIgaT0wOyBpPG51bVZlcnRzOyArK2kpIHtcclxuICAgIHJlc3VsdFtpXSA9IDBcclxuICB9XHJcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXHJcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xyXG4gICAgdmFyIGMgPSBjZWxsc1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8Yy5sZW5ndGg7ICsraikge1xyXG4gICAgICByZXN1bHRbY1tqXV0gPSBjZWxsSW50ZW5zaXR5W2ldXHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiByZXN1bHRcclxufVxyXG5cclxuZnVuY3Rpb24gdGFrZVpDb21wb25lbnQoYXJyYXkpIHtcclxuICB2YXIgbiA9IGFycmF5Lmxlbmd0aFxyXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcclxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcclxuICAgIHJlc3VsdFtpXSA9IGFycmF5W2ldWzJdXHJcbiAgfVxyXG4gIHJldHVybiByZXN1bHRcclxufVxyXG5cclxucHJvdG8uaGlnaGxpZ2h0ID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XHJcbiAgaWYoIXNlbGVjdGlvbiB8fCAhdGhpcy5jb250b3VyRW5hYmxlKSB7XHJcbiAgICB0aGlzLmNvbnRvdXJDb3VudCA9IDBcclxuICAgIHJldHVyblxyXG4gIH1cclxuICB2YXIgbGV2ZWwgPSBnZXRDb250b3VyKHRoaXMuY2VsbHMsIHRoaXMuaW50ZW5zaXR5LCBzZWxlY3Rpb24uaW50ZW5zaXR5KVxyXG4gIHZhciBjZWxscyAgICAgICAgID0gbGV2ZWwuY2VsbHNcclxuICB2YXIgdmVydGV4SWRzICAgICA9IGxldmVsLnZlcnRleElkc1xyXG4gIHZhciB2ZXJ0ZXhXZWlnaHRzID0gbGV2ZWwudmVydGV4V2VpZ2h0c1xyXG4gIHZhciBudW1DZWxscyA9IGNlbGxzLmxlbmd0aFxyXG4gIHZhciByZXN1bHQgPSBwb29sLm1hbGxvY0Zsb2F0MzIoMiAqIDMgKiBudW1DZWxscylcclxuICB2YXIgcHRyID0gMFxyXG4gIGZvcih2YXIgaT0wOyBpPG51bUNlbGxzOyArK2kpIHtcclxuICAgIHZhciBjID0gY2VsbHNbaV1cclxuICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xyXG4gICAgICB2YXIgdiA9IGNbMF1cclxuICAgICAgaWYoYy5sZW5ndGggPT09IDIpIHtcclxuICAgICAgICB2ID0gY1tqXVxyXG4gICAgICB9XHJcbiAgICAgIHZhciBhID0gdmVydGV4SWRzW3ZdWzBdXHJcbiAgICAgIHZhciBiID0gdmVydGV4SWRzW3ZdWzFdXHJcbiAgICAgIHZhciB3ID0gdmVydGV4V2VpZ2h0c1t2XVxyXG4gICAgICB2YXIgd2kgPSAxLjAgLSB3XHJcbiAgICAgIHZhciBwYSA9IHRoaXMucG9zaXRpb25zW2FdXHJcbiAgICAgIHZhciBwYiA9IHRoaXMucG9zaXRpb25zW2JdXHJcbiAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xyXG4gICAgICAgIHJlc3VsdFtwdHIrK10gPSB3ICogcGFba10gKyB3aSAqIHBiW2tdXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgdGhpcy5jb250b3VyQ291bnQgPSAocHRyIC8gMyl8MFxyXG4gIHRoaXMuY29udG91clBvc2l0aW9ucy51cGRhdGUocmVzdWx0LnN1YmFycmF5KDAsIHB0cikpXHJcbiAgcG9vbC5mcmVlKHJlc3VsdClcclxufVxyXG5cclxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XHJcbiAgdmFyIGdsID0gdGhpcy5nbFxyXG5cclxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxyXG5cclxuICBpZignY29udG91ckVuYWJsZScgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmNvbnRvdXJFbmFibGUgPSBwYXJhbXMuY29udG91ckVuYWJsZVxyXG4gIH1cclxuICBpZignY29udG91ckNvbG9yJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuY29udG91ckNvbG9yID0gcGFyYW1zLmNvbnRvdXJDb2xvclxyXG4gIH1cclxuICBpZignbGluZVdpZHRoJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMubGluZVdpZHRoID0gcGFyYW1zLmxpbmVXaWR0aFxyXG4gIH1cclxuICBpZignbGlnaHRQb3NpdGlvbicgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBwYXJhbXMubGlnaHRQb3NpdGlvblxyXG4gIH1cclxuICBpZignb3BhY2l0eScgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLm9wYWNpdHkgPSBwYXJhbXMub3BhY2l0eVxyXG4gIH1cclxuICBpZignYW1iaWVudCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmFtYmllbnRMaWdodCAgPSBwYXJhbXMuYW1iaWVudFxyXG4gIH1cclxuICBpZignZGlmZnVzZScgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmRpZmZ1c2VMaWdodCA9IHBhcmFtcy5kaWZmdXNlXHJcbiAgfVxyXG4gIGlmKCdzcGVjdWxhcicgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLnNwZWN1bGFyTGlnaHQgPSBwYXJhbXMuc3BlY3VsYXJcclxuICB9XHJcbiAgaWYoJ3JvdWdobmVzcycgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLnJvdWdobmVzcyA9IHBhcmFtcy5yb3VnaG5lc3NcclxuICB9XHJcbiAgaWYoJ2ZyZXNuZWwnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5mcmVzbmVsID0gcGFyYW1zLmZyZXNuZWxcclxuICB9XHJcblxyXG4gIGlmKHBhcmFtcy50ZXh0dXJlKSB7XHJcbiAgICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXHJcbiAgICB0aGlzLnRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBwYXJhbXMudGV4dHVyZSlcclxuICB9IGVsc2UgaWYgKHBhcmFtcy5jb2xvcm1hcCkge1xyXG4gICAgdGhpcy50ZXh0dXJlLnNoYXBlID0gWzI1NiwyNTZdXHJcbiAgICB0aGlzLnRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcclxuICAgIHRoaXMudGV4dHVyZS5tYWdGaWx0ZXIgPSBnbC5MSU5FQVJcclxuICAgIHRoaXMudGV4dHVyZS5zZXRQaXhlbHMoZ2VuQ29sb3JtYXAocGFyYW1zLmNvbG9ybWFwKSlcclxuICAgIHRoaXMudGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXHJcbiAgfVxyXG5cclxuICB2YXIgY2VsbHMgPSBwYXJhbXMuY2VsbHNcclxuICB2YXIgcG9zaXRpb25zID0gcGFyYW1zLnBvc2l0aW9uc1xyXG5cclxuICBpZighcG9zaXRpb25zIHx8ICFjZWxscykge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICB2YXIgdFBvcyA9IFtdXHJcbiAgdmFyIHRDb2wgPSBbXVxyXG4gIHZhciB0Tm9yID0gW11cclxuICB2YXIgdFVWcyA9IFtdXHJcbiAgdmFyIHRJZHMgPSBbXVxyXG5cclxuICB2YXIgZVBvcyA9IFtdXHJcbiAgdmFyIGVDb2wgPSBbXVxyXG4gIHZhciBlVVZzID0gW11cclxuICB2YXIgZUlkcyA9IFtdXHJcblxyXG4gIHZhciBwUG9zID0gW11cclxuICB2YXIgcENvbCA9IFtdXHJcbiAgdmFyIHBVVnMgPSBbXVxyXG4gIHZhciBwU2l6ID0gW11cclxuICB2YXIgcElkcyA9IFtdXHJcblxyXG4gIC8vU2F2ZSBnZW9tZXRyeSBkYXRhIGZvciBwaWNraW5nIGNhbGN1bGF0aW9uc1xyXG4gIHRoaXMuY2VsbHMgICAgID0gY2VsbHNcclxuICB0aGlzLnBvc2l0aW9ucyA9IHBvc2l0aW9uc1xyXG5cclxuICAvL0NvbXB1dGUgbm9ybWFsc1xyXG4gIHZhciB2ZXJ0ZXhOb3JtYWxzID0gcGFyYW1zLnZlcnRleE5vcm1hbHNcclxuICB2YXIgY2VsbE5vcm1hbHMgICA9IHBhcmFtcy5jZWxsTm9ybWFsc1xyXG4gIHZhciB2ZXJ0ZXhOb3JtYWxzRXBzaWxvbiA9IHBhcmFtcy52ZXJ0ZXhOb3JtYWxzRXBzaWxvbiA9PT0gdm9pZCgwKSA/IERFRkFVTFRfVkVSVEVYX05PUk1BTFNfRVBTSUxPTiA6IHBhcmFtcy52ZXJ0ZXhOb3JtYWxzRXBzaWxvblxyXG4gIHZhciBmYWNlTm9ybWFsc0Vwc2lsb24gPSBwYXJhbXMuZmFjZU5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA6IHBhcmFtcy5mYWNlTm9ybWFsc0Vwc2lsb25cclxuICBpZihwYXJhbXMudXNlRmFjZXROb3JtYWxzICYmICFjZWxsTm9ybWFscykge1xyXG4gICAgY2VsbE5vcm1hbHMgPSBub3JtYWxzLmZhY2VOb3JtYWxzKGNlbGxzLCBwb3NpdGlvbnMsIGZhY2VOb3JtYWxzRXBzaWxvbilcclxuICB9XHJcbiAgaWYoIWNlbGxOb3JtYWxzICYmICF2ZXJ0ZXhOb3JtYWxzKSB7XHJcbiAgICB2ZXJ0ZXhOb3JtYWxzID0gbm9ybWFscy52ZXJ0ZXhOb3JtYWxzKGNlbGxzLCBwb3NpdGlvbnMsIHZlcnRleE5vcm1hbHNFcHNpbG9uKVxyXG4gIH1cclxuXHJcbiAgLy9Db21wdXRlIGNvbG9yc1xyXG4gIHZhciB2ZXJ0ZXhDb2xvcnMgICAgPSBwYXJhbXMudmVydGV4Q29sb3JzXHJcbiAgdmFyIGNlbGxDb2xvcnMgICAgICA9IHBhcmFtcy5jZWxsQ29sb3JzXHJcbiAgdmFyIG1lc2hDb2xvciAgICAgICA9IHBhcmFtcy5tZXNoQ29sb3IgfHwgWzEsMSwxLDFdXHJcblxyXG4gIC8vVVZzXHJcbiAgdmFyIHZlcnRleFVWcyAgICAgICA9IHBhcmFtcy52ZXJ0ZXhVVnNcclxuICB2YXIgdmVydGV4SW50ZW5zaXR5ID0gcGFyYW1zLnZlcnRleEludGVuc2l0eVxyXG4gIHZhciBjZWxsVVZzICAgICAgICAgPSBwYXJhbXMuY2VsbFVWc1xyXG4gIHZhciBjZWxsSW50ZW5zaXR5ICAgPSBwYXJhbXMuY2VsbEludGVuc2l0eVxyXG5cclxuICB2YXIgaW50ZW5zaXR5TG8gICAgID0gSW5maW5pdHlcclxuICB2YXIgaW50ZW5zaXR5SGkgICAgID0gLUluZmluaXR5XHJcbiAgaWYoIXZlcnRleFVWcyAmJiAhY2VsbFVWcykge1xyXG4gICAgaWYodmVydGV4SW50ZW5zaXR5KSB7XHJcbiAgICAgIGlmKHBhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHMpIHtcclxuICAgICAgICBpbnRlbnNpdHlMbyA9ICtwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzWzBdXHJcbiAgICAgICAgaW50ZW5zaXR5SGkgPSArcGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kc1sxXVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGZvcih2YXIgaT0wOyBpPHZlcnRleEludGVuc2l0eS5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgICAgdmFyIGYgPSB2ZXJ0ZXhJbnRlbnNpdHlbaV1cclxuICAgICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXHJcbiAgICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcclxuICAgICAgZm9yKHZhciBpPTA7IGk8Y2VsbEludGVuc2l0eS5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgIHZhciBmID0gY2VsbEludGVuc2l0eVtpXVxyXG4gICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXHJcbiAgICAgICAgaW50ZW5zaXR5SGkgPSBNYXRoLm1heChpbnRlbnNpdHlIaSwgZilcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZm9yKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgdmFyIGYgPSBwb3NpdGlvbnNbaV1bMl1cclxuICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxyXG4gICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmKHZlcnRleEludGVuc2l0eSkge1xyXG4gICAgdGhpcy5pbnRlbnNpdHkgPSB2ZXJ0ZXhJbnRlbnNpdHlcclxuICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xyXG4gICAgdGhpcy5pbnRlbnNpdHkgPSB1bnBhY2tJbnRlbnNpdHkoY2VsbHMsIHBvc2l0aW9ucy5sZW5ndGgsIGNlbGxJbnRlbnNpdHkpXHJcbiAgfSBlbHNlIHtcclxuICAgIHRoaXMuaW50ZW5zaXR5ID0gdGFrZVpDb21wb25lbnQocG9zaXRpb25zKVxyXG4gIH1cclxuXHJcbiAgLy9Qb2ludCBzaXplXHJcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IHBhcmFtcy5wb2ludFNpemVzXHJcbiAgdmFyIG1lc2hQb2ludFNpemUgICA9IHBhcmFtcy5wb2ludFNpemUgfHwgMS4wXHJcblxyXG4gIC8vVXBkYXRlIGJvdW5kc1xyXG4gIHRoaXMuYm91bmRzICAgICAgID0gW1tJbmZpbml0eSxJbmZpbml0eSxJbmZpbml0eV0sIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXHJcbiAgZm9yKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgKytpKSB7XHJcbiAgICB2YXIgcCA9IHBvc2l0aW9uc1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIGlmKGlzTmFOKHBbal0pIHx8ICFpc0Zpbml0ZShwW2pdKSkge1xyXG4gICAgICAgIGNvbnRpbnVlXHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5ib3VuZHNbMF1bal0gPSBNYXRoLm1pbih0aGlzLmJvdW5kc1swXVtqXSwgcFtqXSlcclxuICAgICAgdGhpcy5ib3VuZHNbMV1bal0gPSBNYXRoLm1heCh0aGlzLmJvdW5kc1sxXVtqXSwgcFtqXSlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vUGFjayBjZWxscyBpbnRvIGJ1ZmZlcnNcclxuICB2YXIgdHJpYW5nbGVDb3VudCA9IDBcclxuICB2YXIgZWRnZUNvdW50ID0gMFxyXG4gIHZhciBwb2ludENvdW50ID0gMFxyXG5cclxuZmlsbF9sb29wOlxyXG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XHJcbiAgICB2YXIgY2VsbCA9IGNlbGxzW2ldXHJcbiAgICBzd2l0Y2goY2VsbC5sZW5ndGgpIHtcclxuICAgICAgY2FzZSAxOlxyXG5cclxuICAgICAgICB2YXIgdiA9IGNlbGxbMF1cclxuICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxyXG5cclxuICAgICAgICAvL0NoZWNrIE5hTnNcclxuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgICAgIGlmKGlzTmFOKHBbal0pIHx8ICFpc0Zpbml0ZShwW2pdKSkge1xyXG4gICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHBQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdKVxyXG5cclxuICAgICAgICB2YXIgY1xyXG4gICAgICAgIGlmKHZlcnRleENvbG9ycykge1xyXG4gICAgICAgICAgYyA9IHZlcnRleENvbG9yc1t2XVxyXG4gICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XHJcbiAgICAgICAgICBjID0gY2VsbENvbG9yc1tpXVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjID0gbWVzaENvbG9yXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmKGMubGVuZ3RoID09PSAzKSB7XHJcbiAgICAgICAgICBwQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgMSlcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIGNbM10pXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2YXIgdXZcclxuICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcclxuICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXHJcbiAgICAgICAgfSBlbHNlIGlmKHZlcnRleEludGVuc2l0eSkge1xyXG4gICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcclxuICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxyXG4gICAgICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAocFsyXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICB9XHJcbiAgICAgICAgcFVWcy5wdXNoKHV2WzBdLCB1dlsxXSlcclxuXHJcbiAgICAgICAgaWYocG9pbnRTaXplcykge1xyXG4gICAgICAgICAgcFNpei5wdXNoKHBvaW50U2l6ZXNbdl0pXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHBTaXoucHVzaChtZXNoUG9pbnRTaXplKVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcElkcy5wdXNoKGkpXHJcblxyXG4gICAgICAgIHBvaW50Q291bnQgKz0gMVxyXG4gICAgICBicmVha1xyXG5cclxuICAgICAgY2FzZSAyOlxyXG5cclxuICAgICAgICAvL0NoZWNrIE5hTnNcclxuICAgICAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcclxuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxyXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cclxuICAgICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xyXG4gICAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcclxuICAgICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XHJcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cclxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXHJcblxyXG4gICAgICAgICAgZVBvcy5wdXNoKHBbMF0sIHBbMV0sIHBbMl0pXHJcblxyXG4gICAgICAgICAgdmFyIGNcclxuICAgICAgICAgIGlmKHZlcnRleENvbG9ycykge1xyXG4gICAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbENvbG9ycykge1xyXG4gICAgICAgICAgICBjID0gY2VsbENvbG9yc1tpXVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgYyA9IG1lc2hDb2xvclxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcclxuICAgICAgICAgICAgZUNvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIDEpXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBlQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB2YXIgdXZcclxuICAgICAgICAgIGlmKHZlcnRleFVWcykge1xyXG4gICAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxyXG4gICAgICAgICAgfSBlbHNlIGlmKHZlcnRleEludGVuc2l0eSkge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xyXG4gICAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAocFsyXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgZVVWcy5wdXNoKHV2WzBdLCB1dlsxXSlcclxuXHJcbiAgICAgICAgICBlSWRzLnB1c2goaSlcclxuICAgICAgICB9XHJcbiAgICAgICAgZWRnZUNvdW50ICs9IDFcclxuICAgICAgYnJlYWtcclxuXHJcbiAgICAgIGNhc2UgMzpcclxuICAgICAgICAvL0NoZWNrIE5hTnNcclxuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxyXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cclxuICAgICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xyXG4gICAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcclxuICAgICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cclxuXHJcbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxyXG4gICAgICAgICAgdFBvcy5wdXNoKHBbMF0sIHBbMV0sIHBbMl0pXHJcblxyXG4gICAgICAgICAgdmFyIGNcclxuICAgICAgICAgIGlmKHZlcnRleENvbG9ycykge1xyXG4gICAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbENvbG9ycykge1xyXG4gICAgICAgICAgICBjID0gY2VsbENvbG9yc1tpXVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgYyA9IG1lc2hDb2xvclxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcclxuICAgICAgICAgICAgdENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIDEpXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB2YXIgdXZcclxuICAgICAgICAgIGlmKHZlcnRleFVWcykge1xyXG4gICAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxyXG4gICAgICAgICAgfSBlbHNlIGlmKHZlcnRleEludGVuc2l0eSkge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xyXG4gICAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cclxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XHJcbiAgICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAocFsyXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdFVWcy5wdXNoKHV2WzBdLCB1dlsxXSlcclxuXHJcbiAgICAgICAgICB2YXIgcVxyXG4gICAgICAgICAgaWYodmVydGV4Tm9ybWFscykge1xyXG4gICAgICAgICAgICBxID0gdmVydGV4Tm9ybWFsc1t2XVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcSA9IGNlbGxOb3JtYWxzW2ldXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICB0Tm9yLnB1c2gocVswXSwgcVsxXSwgcVsyXSlcclxuXHJcbiAgICAgICAgICB0SWRzLnB1c2goaSlcclxuICAgICAgICB9XHJcbiAgICAgICAgdHJpYW5nbGVDb3VudCArPSAxXHJcbiAgICAgIGJyZWFrXHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICBicmVha1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGhpcy5wb2ludENvdW50ICAgICA9IHBvaW50Q291bnRcclxuICB0aGlzLmVkZ2VDb3VudCAgICAgID0gZWRnZUNvdW50XHJcbiAgdGhpcy50cmlhbmdsZUNvdW50ICA9IHRyaWFuZ2xlQ291bnRcclxuXHJcbiAgdGhpcy5wb2ludFBvc2l0aW9ucy51cGRhdGUocFBvcylcclxuICB0aGlzLnBvaW50Q29sb3JzLnVwZGF0ZShwQ29sKVxyXG4gIHRoaXMucG9pbnRVVnMudXBkYXRlKHBVVnMpXHJcbiAgdGhpcy5wb2ludFNpemVzLnVwZGF0ZShwU2l6KVxyXG4gIHRoaXMucG9pbnRJZHMudXBkYXRlKG5ldyBVaW50MzJBcnJheShwSWRzKSlcclxuXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zLnVwZGF0ZShlUG9zKVxyXG4gIHRoaXMuZWRnZUNvbG9ycy51cGRhdGUoZUNvbClcclxuICB0aGlzLmVkZ2VVVnMudXBkYXRlKGVVVnMpXHJcbiAgdGhpcy5lZGdlSWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkoZUlkcykpXHJcblxyXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMudXBkYXRlKHRQb3MpXHJcbiAgdGhpcy50cmlhbmdsZUNvbG9ycy51cGRhdGUodENvbClcclxuICB0aGlzLnRyaWFuZ2xlVVZzLnVwZGF0ZSh0VVZzKVxyXG4gIHRoaXMudHJpYW5nbGVOb3JtYWxzLnVwZGF0ZSh0Tm9yKVxyXG4gIHRoaXMudHJpYW5nbGVJZHMudXBkYXRlKG5ldyBVaW50MzJBcnJheSh0SWRzKSlcclxufVxyXG5cclxucHJvdG8uZHJhd1RyYW5zcGFyZW50ID0gcHJvdG8uZHJhdyA9IGZ1bmN0aW9uKHBhcmFtcykge1xyXG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxyXG4gIHZhciBnbCAgICAgICAgICA9IHRoaXMuZ2xcclxuICB2YXIgbW9kZWwgICAgICAgPSBwYXJhbXMubW9kZWwgICAgICB8fCBpZGVudGl0eU1hdHJpeFxyXG4gIHZhciB2aWV3ICAgICAgICA9IHBhcmFtcy52aWV3ICAgICAgIHx8IGlkZW50aXR5TWF0cml4XHJcbiAgdmFyIHByb2plY3Rpb24gID0gcGFyYW1zLnByb2plY3Rpb24gfHwgaWRlbnRpdHlNYXRyaXhcclxuXHJcbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcclxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXHJcbiAgfVxyXG5cclxuICB2YXIgdW5pZm9ybXMgPSB7XHJcbiAgICBtb2RlbDogICAgICBtb2RlbCxcclxuICAgIHZpZXc6ICAgICAgIHZpZXcsXHJcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxyXG5cclxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXHJcblxyXG4gICAga2FtYmllbnQ6ICAgdGhpcy5hbWJpZW50TGlnaHQsXHJcbiAgICBrZGlmZnVzZTogICB0aGlzLmRpZmZ1c2VMaWdodCxcclxuICAgIGtzcGVjdWxhcjogIHRoaXMuc3BlY3VsYXJMaWdodCxcclxuICAgIHJvdWdobmVzczogIHRoaXMucm91Z2huZXNzLFxyXG4gICAgZnJlc25lbDogICAgdGhpcy5mcmVzbmVsLFxyXG5cclxuICAgIGV5ZVBvc2l0aW9uOiAgIFswLDAsMF0sXHJcbiAgICBsaWdodFBvc2l0aW9uOiBbMCwwLDBdLFxyXG5cclxuICAgIG9wYWNpdHk6ICB0aGlzLm9wYWNpdHksXHJcblxyXG4gICAgY29udG91ckNvbG9yOiB0aGlzLmNvbnRvdXJDb2xvcixcclxuXHJcbiAgICB0ZXh0dXJlOiAgICAwXHJcbiAgfVxyXG5cclxuICB0aGlzLnRleHR1cmUuYmluZCgwKVxyXG5cclxuICB2YXIgaW52Q2FtZXJhTWF0cml4ID0gbmV3IEFycmF5KDE2KVxyXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMudmlldywgdW5pZm9ybXMubW9kZWwpXHJcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXHJcbiAgaW52ZXJ0KGludkNhbWVyYU1hdHJpeCwgaW52Q2FtZXJhTWF0cml4KVxyXG5cclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHVuaWZvcm1zLmV5ZVBvc2l0aW9uW2ldID0gaW52Q2FtZXJhTWF0cml4WzEyK2ldIC8gaW52Q2FtZXJhTWF0cml4WzE1XVxyXG4gIH1cclxuXHJcbiAgdmFyIHcgPSBpbnZDYW1lcmFNYXRyaXhbMTVdXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB3ICs9IHRoaXMubGlnaHRQb3NpdGlvbltpXSAqIGludkNhbWVyYU1hdHJpeFs0KmkrM11cclxuICB9XHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMitpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHMgKz0gaW52Q2FtZXJhTWF0cml4WzQqaitpXSAqIHRoaXMubGlnaHRQb3NpdGlvbltqXVxyXG4gICAgfVxyXG4gICAgdW5pZm9ybXMubGlnaHRQb3NpdGlvbltpXSA9IHMgLyB3XHJcbiAgfVxyXG5cclxuICBpZih0aGlzLnRyaWFuZ2xlQ291bnQgPiAwKSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy50cmlTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcclxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuZWRnZUNvdW50ID4gMCAmJiB0aGlzLmxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmxpbmVTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxyXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcclxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID4gMCkge1xyXG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5wb2ludFZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXHJcbiAgICB0aGlzLnBvaW50VkFPLnVuYmluZCgpXHJcbiAgfVxyXG5cclxuICBpZih0aGlzLmNvbnRvdXJFbmFibGUgJiYgdGhpcy5jb250b3VyQ291bnQgPiAwICYmIHRoaXMuY29udG91ckxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmNvbnRvdXJTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5jb250b3VyVkFPLmJpbmQoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5jb250b3VyQ291bnQpXHJcbiAgICB0aGlzLmNvbnRvdXJWQU8udW5iaW5kKClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XHJcblxyXG4gIHZhciBnbCAgICAgICAgID0gdGhpcy5nbFxyXG5cclxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IGlkZW50aXR5TWF0cml4XHJcbiAgdmFyIHZpZXcgICAgICAgPSBwYXJhbXMudmlldyAgICAgICB8fCBpZGVudGl0eU1hdHJpeFxyXG4gIHZhciBwcm9qZWN0aW9uID0gcGFyYW1zLnByb2plY3Rpb24gfHwgaWRlbnRpdHlNYXRyaXhcclxuXHJcbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcclxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXHJcbiAgfVxyXG5cclxuICAvL1NhdmUgY2FtZXJhIHBhcmFtZXRlcnNcclxuICB0aGlzLl9tb2RlbCAgICAgID0gW10uc2xpY2UuY2FsbChtb2RlbClcclxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxyXG4gIHRoaXMuX3Byb2plY3Rpb24gPSBbXS5zbGljZS5jYWxsKHByb2plY3Rpb24pXHJcbiAgdGhpcy5fcmVzb2x1dGlvbiA9IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdXHJcblxyXG4gIHZhciB1bmlmb3JtcyA9IHtcclxuICAgIG1vZGVsOiAgICAgIG1vZGVsLFxyXG4gICAgdmlldzogICAgICAgdmlldyxcclxuICAgIHByb2plY3Rpb246IHByb2plY3Rpb24sXHJcbiAgICBjbGlwQm91bmRzOiBjbGlwQm91bmRzLFxyXG4gICAgcGlja0lkOiAgICAgdGhpcy5waWNrSWQgLyAyNTUuMCxcclxuICB9XHJcblxyXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcclxuICBzaGFkZXIuYmluZCgpXHJcbiAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcclxuXHJcbiAgaWYodGhpcy50cmlhbmdsZUNvdW50ID4gMCkge1xyXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcclxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuZWRnZUNvdW50ID4gMCkge1xyXG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxyXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcclxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID4gMCkge1xyXG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRQaWNrU2hhZGVyXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xyXG5cclxuICAgIHRoaXMucG9pbnRWQU8uYmluZCgpXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgdGhpcy5wb2ludENvdW50KVxyXG4gICAgdGhpcy5wb2ludFZBTy51bmJpbmQoKVxyXG4gIH1cclxufVxyXG5cclxuXHJcbnByb3RvLnBpY2sgPSBmdW5jdGlvbihwaWNrRGF0YSkge1xyXG4gIGlmKCFwaWNrRGF0YSkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcbiAgaWYocGlja0RhdGEuaWQgIT09IHRoaXMucGlja0lkKSB7XHJcbiAgICByZXR1cm4gbnVsbFxyXG4gIH1cclxuXHJcbiAgdmFyIGNlbGxJZCAgICA9IHBpY2tEYXRhLnZhbHVlWzBdICsgMjU2KnBpY2tEYXRhLnZhbHVlWzFdICsgNjU1MzYqcGlja0RhdGEudmFsdWVbMl1cclxuICB2YXIgY2VsbCAgICAgID0gdGhpcy5jZWxsc1tjZWxsSWRdXHJcbiAgdmFyIHBvc2l0aW9ucyA9IHRoaXMucG9zaXRpb25zXHJcblxyXG4gIHZhciBzaW1wbGV4ICAgPSBuZXcgQXJyYXkoY2VsbC5sZW5ndGgpXHJcbiAgZm9yKHZhciBpPTA7IGk8Y2VsbC5sZW5ndGg7ICsraSkge1xyXG4gICAgc2ltcGxleFtpXSA9IHBvc2l0aW9uc1tjZWxsW2ldXVxyXG4gIH1cclxuXHJcbiAgdmFyIGRhdGEgPSBjbG9zZXN0UG9pbnQoXHJcbiAgICBzaW1wbGV4LFxyXG4gICAgW3BpY2tEYXRhLmNvb3JkWzBdLCB0aGlzLl9yZXNvbHV0aW9uWzFdLXBpY2tEYXRhLmNvb3JkWzFdXSxcclxuICAgIHRoaXMuX21vZGVsLFxyXG4gICAgdGhpcy5fdmlldyxcclxuICAgIHRoaXMuX3Byb2plY3Rpb24sXHJcbiAgICB0aGlzLl9yZXNvbHV0aW9uKVxyXG5cclxuICBpZighZGF0YSkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcblxyXG4gIHZhciB3ZWlnaHRzID0gZGF0YVsyXVxyXG4gIHZhciBpbnRlcnBJbnRlbnNpdHkgPSAwLjBcclxuICBmb3IodmFyIGk9MDsgaTxjZWxsLmxlbmd0aDsgKytpKSB7XHJcbiAgICBpbnRlcnBJbnRlbnNpdHkgKz0gd2VpZ2h0c1tpXSAqIHRoaXMuaW50ZW5zaXR5W2NlbGxbaV1dXHJcbiAgfVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcG9zaXRpb246IGRhdGFbMV0sXHJcbiAgICBpbmRleDogICAgY2VsbFtkYXRhWzBdXSxcclxuICAgIGNlbGw6ICAgICBjZWxsLFxyXG4gICAgY2VsbElkOiAgIGNlbGxJZCxcclxuICAgIGludGVuc2l0eTogIGludGVycEludGVuc2l0eSxcclxuICAgIGRhdGFDb29yZGluYXRlOiB0aGlzLnBvc2l0aW9uc1tjZWxsW2RhdGFbMF1dXVxyXG4gIH1cclxufVxyXG5cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXHJcblxyXG4gIHRoaXMudHJpU2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMubGluZVNoYWRlci5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50U2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50UGlja1NoYWRlci5kaXNwb3NlKClcclxuXHJcbiAgdGhpcy50cmlhbmdsZVZBTy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMuZGlzcG9zZSgpXHJcbiAgdGhpcy50cmlhbmdsZVVWcy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlTm9ybWFscy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlSWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLmVkZ2VWQU8uZGlzcG9zZSgpXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIHRoaXMuZWRnZUNvbG9ycy5kaXNwb3NlKClcclxuICB0aGlzLmVkZ2VVVnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5lZGdlSWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLnBvaW50VkFPLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5wb2ludENvbG9ycy5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50VVZzLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRTaXplcy5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50SWRzLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLmNvbnRvdXJWQU8uZGlzcG9zZSgpXHJcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLmRpc3Bvc2UoKVxyXG4gIHRoaXMuY29udG91clNoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlTWVzaFNoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIG1lc2hTaGFkZXIudmVydGV4LCBtZXNoU2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uICAgID0gMlxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgID0gM1xyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiAgID0gNFxyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlV2lyZVNoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHdpcmVTaGFkZXIudmVydGV4LCB3aXJlU2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uICAgID0gMlxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgID0gM1xyXG4gIHJldHVybiBzaGFkZXJcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlUG9pbnRTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwb2ludFNoYWRlci52ZXJ0ZXgsIHBvaW50U2hhZGVyLmZyYWdtZW50KVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uICA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICAgPSAyXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgID0gM1xyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvaW50U2l6ZS5sb2NhdGlvbiA9IDRcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBpY2tTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwaWNrU2hhZGVyLnZlcnRleCwgcGlja1NoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5pZC5sb2NhdGlvbiAgICAgICA9IDFcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBvaW50UGlja1NoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHBvaW50UGlja1NoYWRlci52ZXJ0ZXgsIHBvaW50UGlja1NoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiAgPSAwXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuaWQubG9jYXRpb24gICAgICAgID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvaW50U2l6ZS5sb2NhdGlvbiA9IDRcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUNvbnRvdXJTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBjb250b3VyU2hhZGVyLnZlcnRleCwgY29udG91clNoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVNpbXBsaWNpYWxNZXNoKGdsLCBwYXJhbXMpIHtcclxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgcGFyYW1zID0gZ2w7XHJcbiAgICBnbCA9IHBhcmFtcy5nbDtcclxuICB9XHJcblxyXG4gIC8vZW5hYmxlIGRlcml2YXRpdmVzIGZvciBmYWNlIG5vcm1hbHNcclxuICB2YXIgZXh0ID0gZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXMnKSB8fCBnbC5nZXRFeHRlbnNpb24oJ01PWl9PRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXMnKSB8fCBnbC5nZXRFeHRlbnNpb24oJ1dFQktJVF9PRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXMnKVxyXG4gIGlmICghZXh0KVxyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdkZXJpdmF0aXZlcyBub3Qgc3VwcG9ydGVkJylcclxuXHJcbiAgdmFyIHRyaVNoYWRlciAgICAgICA9IGNyZWF0ZU1lc2hTaGFkZXIoZ2wpXHJcbiAgdmFyIGxpbmVTaGFkZXIgICAgICA9IGNyZWF0ZVdpcmVTaGFkZXIoZ2wpXHJcbiAgdmFyIHBvaW50U2hhZGVyICAgICA9IGNyZWF0ZVBvaW50U2hhZGVyKGdsKVxyXG4gIHZhciBwaWNrU2hhZGVyICAgICAgPSBjcmVhdGVQaWNrU2hhZGVyKGdsKVxyXG4gIHZhciBwb2ludFBpY2tTaGFkZXIgPSBjcmVhdGVQb2ludFBpY2tTaGFkZXIoZ2wpXHJcbiAgdmFyIGNvbnRvdXJTaGFkZXIgICA9IGNyZWF0ZUNvbnRvdXJTaGFkZXIoZ2wpXHJcblxyXG4gIHZhciBtZXNoVGV4dHVyZSAgICAgICA9IGNyZWF0ZVRleHR1cmUoZ2wsXHJcbiAgICBuZGFycmF5KG5ldyBVaW50OEFycmF5KFsyNTUsMjU1LDI1NSwyNTVdKSwgWzEsMSw0XSkpXHJcbiAgbWVzaFRleHR1cmUuZ2VuZXJhdGVNaXBtYXAoKVxyXG4gIG1lc2hUZXh0dXJlLm1pbkZpbHRlciA9IGdsLkxJTkVBUl9NSVBNQVBfTElORUFSXHJcbiAgbWVzaFRleHR1cmUubWFnRmlsdGVyID0gZ2wuTElORUFSXHJcblxyXG4gIHZhciB0cmlhbmdsZVBvc2l0aW9ucyA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVDb2xvcnMgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlVVZzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB0cmlhbmdsZU5vcm1hbHMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVJZHMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVQb3NpdGlvbnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAzXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlSWRzLFxyXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxyXG4gICAgICBzaXplOiA0LFxyXG4gICAgICBub3JtYWxpemVkOiB0cnVlXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlQ29sb3JzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogNFxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZVVWcyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDJcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVOb3JtYWxzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogM1xyXG4gICAgfVxyXG4gIF0pXHJcblxyXG4gIHZhciBlZGdlUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBlZGdlQ29sb3JzICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBlZGdlVVZzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBlZGdlSWRzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBlZGdlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogZWRnZVBvc2l0aW9ucyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDNcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogZWRnZUlkcyxcclxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcclxuICAgICAgc2l6ZTogNCxcclxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBlZGdlQ29sb3JzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogNFxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBlZGdlVVZzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogMlxyXG4gICAgfVxyXG4gIF0pXHJcblxyXG4gIHZhciBwb2ludFBvc2l0aW9ucyAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHBvaW50Q29sb3JzICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgcG9pbnRVVnMgICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwb2ludFNpemVzICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHBvaW50SWRzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgcG9pbnRWQU8gICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogcG9pbnRQb3NpdGlvbnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAzXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHBvaW50SWRzLFxyXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxyXG4gICAgICBzaXplOiA0LFxyXG4gICAgICBub3JtYWxpemVkOiB0cnVlXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHBvaW50Q29sb3JzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogNFxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBwb2ludFVWcyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDJcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogcG9pbnRTaXplcyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDFcclxuICAgIH1cclxuICBdKVxyXG5cclxuICB2YXIgY29udG91clBvc2l0aW9ucyA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgY29udG91clZBTyAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAgeyBidWZmZXI6IGNvbnRvdXJQb3NpdGlvbnMsXHJcbiAgICAgIHR5cGU6ICAgZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6ICAgM1xyXG4gICAgfV0pXHJcblxyXG4gIHZhciBtZXNoID0gbmV3IFNpbXBsaWNpYWxNZXNoKGdsXHJcbiAgICAsIG1lc2hUZXh0dXJlXHJcbiAgICAsIHRyaVNoYWRlclxyXG4gICAgLCBsaW5lU2hhZGVyXHJcbiAgICAsIHBvaW50U2hhZGVyXHJcbiAgICAsIHBpY2tTaGFkZXJcclxuICAgICwgcG9pbnRQaWNrU2hhZGVyXHJcbiAgICAsIGNvbnRvdXJTaGFkZXJcclxuICAgICwgdHJpYW5nbGVQb3NpdGlvbnNcclxuICAgICwgdHJpYW5nbGVJZHNcclxuICAgICwgdHJpYW5nbGVDb2xvcnNcclxuICAgICwgdHJpYW5nbGVVVnNcclxuICAgICwgdHJpYW5nbGVOb3JtYWxzXHJcbiAgICAsIHRyaWFuZ2xlVkFPXHJcbiAgICAsIGVkZ2VQb3NpdGlvbnNcclxuICAgICwgZWRnZUlkc1xyXG4gICAgLCBlZGdlQ29sb3JzXHJcbiAgICAsIGVkZ2VVVnNcclxuICAgICwgZWRnZVZBT1xyXG4gICAgLCBwb2ludFBvc2l0aW9uc1xyXG4gICAgLCBwb2ludElkc1xyXG4gICAgLCBwb2ludENvbG9yc1xyXG4gICAgLCBwb2ludFVWc1xyXG4gICAgLCBwb2ludFNpemVzXHJcbiAgICAsIHBvaW50VkFPXHJcbiAgICAsIGNvbnRvdXJQb3NpdGlvbnNcclxuICAgICwgY29udG91clZBTylcclxuXHJcbiAgbWVzaC51cGRhdGUocGFyYW1zKVxyXG5cclxuICByZXR1cm4gbWVzaFxyXG59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNpbXBsaWNpYWxNZXNoXHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCb3hlc1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXHJcbnZhciBjcmVhdGVTaGFkZXIgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG5cclxudmFyIHNoYWRlcnMgPSByZXF1aXJlKCcuL3NoYWRlcnMnKVxyXG5cclxuZnVuY3Rpb24gQm94ZXMocGxvdCwgdmJvLCBzaGFkZXIpIHtcclxuICB0aGlzLnBsb3QgICA9IHBsb3RcclxuICB0aGlzLnZibyAgICA9IHZib1xyXG4gIHRoaXMuc2hhZGVyID0gc2hhZGVyXHJcbn1cclxuXHJcbnZhciBwcm90byA9IEJveGVzLnByb3RvdHlwZVxyXG5cclxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKCkge1xyXG4gIHZhciBzaGFkZXIgPSB0aGlzLnNoYWRlclxyXG4gIHRoaXMudmJvLmJpbmQoKVxyXG4gIHRoaXMuc2hhZGVyLmJpbmQoKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvb3JkLnBvaW50ZXIoKVxyXG4gIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5Cb3ggPSB0aGlzLnBsb3Quc2NyZWVuQm94XHJcbn1cclxuXHJcbnByb3RvLmRyYXdCb3ggPSAoZnVuY3Rpb24oKSB7XHJcbiAgdmFyIGxvID0gWzAsMF1cclxuICB2YXIgaGkgPSBbMCwwXVxyXG4gIHJldHVybiBmdW5jdGlvbihsb1gsIGxvWSwgaGlYLCBoaVksIGNvbG9yKSB7XHJcbiAgICB2YXIgcGxvdCAgICAgICA9IHRoaXMucGxvdFxyXG4gICAgdmFyIHNoYWRlciAgICAgPSB0aGlzLnNoYWRlclxyXG4gICAgdmFyIGdsICAgICAgICAgPSBwbG90LmdsXHJcblxyXG4gICAgbG9bMF0gPSBsb1hcclxuICAgIGxvWzFdID0gbG9ZXHJcbiAgICBoaVswXSA9IGhpWFxyXG4gICAgaGlbMV0gPSBoaVlcclxuXHJcbiAgICBzaGFkZXIudW5pZm9ybXMubG8gICAgID0gbG9cclxuICAgIHNoYWRlci51bmlmb3Jtcy5oaSAgICAgPSBoaVxyXG4gICAgc2hhZGVyLnVuaWZvcm1zLmNvbG9yICA9IGNvbG9yXHJcblxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNClcclxuICB9XHJcbn0oKSlcclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnZiby5kaXNwb3NlKClcclxuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlQm94ZXMocGxvdCkge1xyXG4gIHZhciBnbCAgPSBwbG90LmdsXHJcbiAgdmFyIHZibyA9IGNyZWF0ZUJ1ZmZlcihnbCwgW1xyXG4gICAgMCwwLFxyXG4gICAgMCwxLFxyXG4gICAgMSwwLFxyXG4gICAgMSwxXSlcclxuICB2YXIgc2hhZGVyICA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy5ib3hWZXJ0LCBzaGFkZXJzLmxpbmVGcmFnKVxyXG4gIHJldHVybiBuZXcgQm94ZXMocGxvdCwgdmJvLCBzaGFkZXIpXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUdyaWRcclxuXHJcbnZhciBjcmVhdGVCdWZmZXIgID0gcmVxdWlyZSgnZ2wtYnVmZmVyJylcclxudmFyIGNyZWF0ZVNoYWRlciAgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG52YXIgYnNlYXJjaCAgICAgICA9IHJlcXVpcmUoJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcclxudmFyIHNoYWRlcnMgICAgICAgPSByZXF1aXJlKCcuL3NoYWRlcnMnKVxyXG5cclxuZnVuY3Rpb24gR3JpZChwbG90LCB2Ym8sIHNoYWRlciwgdGlja1NoYWRlcikge1xyXG4gIHRoaXMucGxvdCAgID0gcGxvdFxyXG4gIHRoaXMudmJvICAgID0gdmJvXHJcbiAgdGhpcy5zaGFkZXIgPSBzaGFkZXJcclxuICB0aGlzLnRpY2tTaGFkZXIgPSB0aWNrU2hhZGVyXHJcbiAgdGhpcy50aWNrcyAgPSBbW10sIFtdXVxyXG59XHJcblxyXG5mdW5jdGlvbiBjb21wYXJlVGlja051bShhLCBiKSB7XHJcbiAgcmV0dXJuIGEgLSBiXHJcbn1cclxuXHJcbnZhciBwcm90byA9IEdyaWQucHJvdG90eXBlXHJcblxyXG5wcm90by5kcmF3ID0gKGZ1bmN0aW9uKCkge1xyXG5cclxuICB2YXIgREFUQV9TSElGVCA9IFswLDBdXHJcbiAgdmFyIERBVEFfU0NBTEUgPSBbMCwwXVxyXG4gIHZhciBEQVRBX0FYSVMgID0gWzAsMF1cclxuXHJcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xyXG4gICAgdmFyIHBsb3QgICAgICAgPSB0aGlzLnBsb3RcclxuICAgIHZhciB2Ym8gICAgICAgID0gdGhpcy52Ym9cclxuICAgIHZhciBzaGFkZXIgICAgID0gdGhpcy5zaGFkZXJcclxuICAgIHZhciB0aWNrcyAgICAgID0gdGhpcy50aWNrc1xyXG4gICAgdmFyIGdsICAgICAgICAgPSBwbG90LmdsXHJcbiAgICB2YXIgYm91bmRzICAgICA9IHBsb3QuX3RpY2tCb3VuZHNcclxuICAgIHZhciBkYXRhQm94ICAgID0gcGxvdC5kYXRhQm94XHJcbiAgICB2YXIgdmlld1BpeGVscyA9IHBsb3Qudmlld0JveFxyXG4gICAgdmFyIGxpbmVXaWR0aCAgPSBwbG90LmdyaWRMaW5lV2lkdGhcclxuICAgIHZhciBncmlkQ29sb3IgID0gcGxvdC5ncmlkTGluZUNvbG9yXHJcbiAgICB2YXIgZ3JpZEVuYWJsZSA9IHBsb3QuZ3JpZExpbmVFbmFibGVcclxuICAgIHZhciBwaXhlbFJhdGlvID0gcGxvdC5waXhlbFJhdGlvXHJcblxyXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XHJcbiAgICAgIHZhciBsbyA9IGJvdW5kc1tpXVxyXG4gICAgICB2YXIgaGkgPSBib3VuZHNbaSsyXVxyXG4gICAgICB2YXIgYm91bmRTY2FsZSA9IGhpIC0gbG9cclxuICAgICAgdmFyIGRhdGFDZW50ZXIgID0gMC41ICogKGRhdGFCb3hbaSsyXSArIGRhdGFCb3hbaV0pXHJcbiAgICAgIHZhciBkYXRhV2lkdGggICA9IGRhdGFCb3hbaSsyXSAtIGRhdGFCb3hbaV1cclxuICAgICAgREFUQV9TQ0FMRVtpXSA9IDIuMCAqIGJvdW5kU2NhbGUgLyBkYXRhV2lkdGhcclxuICAgICAgREFUQV9TSElGVFtpXSA9IDIuMCAqIChsbyAtIGRhdGFDZW50ZXIpIC8gZGF0YVdpZHRoXHJcbiAgICB9XHJcblxyXG4gICAgc2hhZGVyLmJpbmQoKVxyXG4gICAgdmJvLmJpbmQoKVxyXG4gICAgc2hhZGVyLmF0dHJpYnV0ZXMuZGF0YUNvb3JkLnBvaW50ZXIoKVxyXG4gICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFTaGlmdCA9IERBVEFfU0hJRlRcclxuICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhU2NhbGUgPSBEQVRBX1NDQUxFXHJcblxyXG4gICAgdmFyIG9mZnNldCA9IDBcclxuICAgIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xyXG4gICAgICBEQVRBX0FYSVNbMF0gPSBEQVRBX0FYSVNbMV0gPSAwXHJcbiAgICAgIERBVEFfQVhJU1tpXSA9IDFcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFBeGlzICA9IERBVEFfQVhJU1xyXG4gICAgICBzaGFkZXIudW5pZm9ybXMubGluZVdpZHRoID0gbGluZVdpZHRoW2ldIC8gKHZpZXdQaXhlbHNbaSsyXSAtIHZpZXdQaXhlbHNbaV0pICogcGl4ZWxSYXRpb1xyXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgICAgID0gZ3JpZENvbG9yW2ldXHJcblxyXG4gICAgICB2YXIgc2l6ZSA9IHRpY2tzW2ldLmxlbmd0aCAqIDZcclxuICAgICAgaWYoZ3JpZEVuYWJsZVtpXSAmJiBzaXplKSB7XHJcbiAgICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIG9mZnNldCwgc2l6ZSlcclxuICAgICAgfVxyXG4gICAgICBvZmZzZXQgKz0gc2l6ZVxyXG4gICAgfVxyXG4gIH1cclxufSkoKVxyXG5cclxucHJvdG8uZHJhd1RpY2tNYXJrcyA9IChmdW5jdGlvbigpIHtcclxuICB2YXIgREFUQV9TSElGVCA9IFswLDBdXHJcbiAgdmFyIERBVEFfU0NBTEUgPSBbMCwwXVxyXG4gIHZhciBYX0FYSVMgICAgID0gWzEsMF1cclxuICB2YXIgWV9BWElTICAgICA9IFswLDFdXHJcbiAgdmFyIFNDUl9PRkZTRVQgPSBbMCwwXVxyXG4gIHZhciBUSUNLX1NDQUxFID0gWzAsMF1cclxuXHJcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xyXG4gICAgdmFyIHBsb3QgICAgICAgPSB0aGlzLnBsb3RcclxuICAgIHZhciB2Ym8gICAgICAgID0gdGhpcy52Ym9cclxuICAgIHZhciBzaGFkZXIgICAgID0gdGhpcy50aWNrU2hhZGVyXHJcbiAgICB2YXIgdGlja3MgICAgICA9IHRoaXMudGlja3NcclxuICAgIHZhciBnbCAgICAgICAgID0gcGxvdC5nbFxyXG4gICAgdmFyIGJvdW5kcyAgICAgPSBwbG90Ll90aWNrQm91bmRzXHJcbiAgICB2YXIgZGF0YUJveCAgICA9IHBsb3QuZGF0YUJveFxyXG4gICAgdmFyIHZpZXdCb3ggICAgPSBwbG90LnZpZXdCb3hcclxuICAgIHZhciBwaXhlbFJhdGlvID0gcGxvdC5waXhlbFJhdGlvXHJcbiAgICB2YXIgc2NyZWVuQm94ICA9IHBsb3Quc2NyZWVuQm94XHJcblxyXG4gICAgdmFyIHNjcmVlbldpZHRoICA9IHNjcmVlbkJveFsyXSAtIHNjcmVlbkJveFswXVxyXG4gICAgdmFyIHNjcmVlbkhlaWdodCA9IHNjcmVlbkJveFszXSAtIHNjcmVlbkJveFsxXVxyXG4gICAgdmFyIHZpZXdXaWR0aCAgICA9IHZpZXdCb3hbMl0gICAtIHZpZXdCb3hbMF1cclxuICAgIHZhciB2aWV3SGVpZ2h0ICAgPSB2aWV3Qm94WzNdICAgLSB2aWV3Qm94WzFdXHJcblxyXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XHJcbiAgICAgIHZhciBsbyA9IGJvdW5kc1tpXVxyXG4gICAgICB2YXIgaGkgPSBib3VuZHNbaSsyXVxyXG4gICAgICB2YXIgYm91bmRTY2FsZSA9IGhpIC0gbG9cclxuICAgICAgdmFyIGRhdGFDZW50ZXIgID0gMC41ICogKGRhdGFCb3hbaSsyXSArIGRhdGFCb3hbaV0pXHJcbiAgICAgIHZhciBkYXRhV2lkdGggICA9IChkYXRhQm94W2krMl0gLSBkYXRhQm94W2ldKVxyXG4gICAgICBEQVRBX1NDQUxFW2ldID0gMi4wICogYm91bmRTY2FsZSAvIGRhdGFXaWR0aFxyXG4gICAgICBEQVRBX1NISUZUW2ldID0gMi4wICogKGxvIC0gZGF0YUNlbnRlcikgLyBkYXRhV2lkdGhcclxuICAgIH1cclxuXHJcbiAgICBEQVRBX1NDQUxFWzBdICo9IHZpZXdXaWR0aCAvIHNjcmVlbldpZHRoXHJcbiAgICBEQVRBX1NISUZUWzBdICo9IHZpZXdXaWR0aCAvIHNjcmVlbldpZHRoXHJcblxyXG4gICAgREFUQV9TQ0FMRVsxXSAqPSB2aWV3SGVpZ2h0IC8gc2NyZWVuSGVpZ2h0XHJcbiAgICBEQVRBX1NISUZUWzFdICo9IHZpZXdIZWlnaHQgLyBzY3JlZW5IZWlnaHRcclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcbiAgICB2Ym8uYmluZCgpXHJcblxyXG4gICAgc2hhZGVyLmF0dHJpYnV0ZXMuZGF0YUNvb3JkLnBvaW50ZXIoKVxyXG5cclxuICAgIHZhciB1bmlmb3JtcyA9IHNoYWRlci51bmlmb3Jtc1xyXG4gICAgdW5pZm9ybXMuZGF0YVNoaWZ0ID0gREFUQV9TSElGVFxyXG4gICAgdW5pZm9ybXMuZGF0YVNjYWxlID0gREFUQV9TQ0FMRVxyXG5cclxuICAgIHZhciB0aWNrTWFya0xlbmd0aCA9IHBsb3QudGlja01hcmtMZW5ndGhcclxuICAgIHZhciB0aWNrTWFya1dpZHRoICA9IHBsb3QudGlja01hcmtXaWR0aFxyXG4gICAgdmFyIHRpY2tNYXJrQ29sb3IgID0gcGxvdC50aWNrTWFya0NvbG9yXHJcblxyXG4gICAgdmFyIHhUaWNrc09mZnNldCA9IDBcclxuICAgIHZhciB5VGlja3NPZmZzZXQgPSB0aWNrc1swXS5sZW5ndGggKiA2XHJcblxyXG4gICAgdmFyIHhTdGFydCA9IE1hdGgubWluKGJzZWFyY2guZ2UodGlja3NbMF0sIChkYXRhQm94WzBdIC0gYm91bmRzWzBdKSAvIChib3VuZHNbMl0gLSBib3VuZHNbMF0pLCBjb21wYXJlVGlja051bSksIHRpY2tzWzBdLmxlbmd0aClcclxuICAgIHZhciB4RW5kICAgPSBNYXRoLm1pbihic2VhcmNoLmd0KHRpY2tzWzBdLCAoZGF0YUJveFsyXSAtIGJvdW5kc1swXSkgLyAoYm91bmRzWzJdIC0gYm91bmRzWzBdKSwgY29tcGFyZVRpY2tOdW0pLCB0aWNrc1swXS5sZW5ndGgpXHJcbiAgICB2YXIgeE9mZnNldCA9IHhUaWNrc09mZnNldCArIDYgKiB4U3RhcnRcclxuICAgIHZhciB4Q291bnQgID0gNiAqIE1hdGgubWF4KDAsIHhFbmQgLSB4U3RhcnQpXHJcblxyXG4gICAgdmFyIHlTdGFydCA9IE1hdGgubWluKGJzZWFyY2guZ2UodGlja3NbMV0sIChkYXRhQm94WzFdIC0gYm91bmRzWzFdKSAvIChib3VuZHNbM10gLSBib3VuZHNbMV0pLCBjb21wYXJlVGlja051bSksIHRpY2tzWzFdLmxlbmd0aClcclxuICAgIHZhciB5RW5kICAgPSBNYXRoLm1pbihic2VhcmNoLmd0KHRpY2tzWzFdLCAoZGF0YUJveFszXSAtIGJvdW5kc1sxXSkgLyAoYm91bmRzWzNdIC0gYm91bmRzWzFdKSwgY29tcGFyZVRpY2tOdW0pLCB0aWNrc1sxXS5sZW5ndGgpXHJcbiAgICB2YXIgeU9mZnNldCA9IHlUaWNrc09mZnNldCArIDYgKiB5U3RhcnRcclxuICAgIHZhciB5Q291bnQgID0gNiAqIE1hdGgubWF4KDAsIHlFbmQgLSB5U3RhcnQpXHJcblxyXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gMi4wICogKHZpZXdCb3hbMF0gLSB0aWNrTWFya0xlbmd0aFsxXSkgLyBzY3JlZW5XaWR0aCAtIDEuMFxyXG4gICAgU0NSX09GRlNFVFsxXSAgICAgICAgID0gKHZpZXdCb3hbM10gKyB2aWV3Qm94WzFdKSAvIHNjcmVlbkhlaWdodCAtIDEuMFxyXG4gICAgVElDS19TQ0FMRVswXSAgICAgICAgID0gdGlja01hcmtMZW5ndGhbMV0gKiBwaXhlbFJhdGlvIC8gc2NyZWVuV2lkdGhcclxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrV2lkdGhbMV0gICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxyXG5cclxuICAgIGlmKHlDb3VudCkge1xyXG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzFdXHJcbiAgICAgIHVuaWZvcm1zLnRpY2tTY2FsZSAgICA9IFRJQ0tfU0NBTEVcclxuICAgICAgdW5pZm9ybXMuZGF0YUF4aXMgICAgID0gWV9BWElTXHJcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcclxuICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIHlPZmZzZXQsIHlDb3VudClcclxuICAgIH1cclxuXHJcbiAgICBTQ1JfT0ZGU0VUWzBdICAgICAgICAgPSAodmlld0JveFsyXSArIHZpZXdCb3hbMF0pIC8gc2NyZWVuV2lkdGggLSAxLjBcclxuICAgIFNDUl9PRkZTRVRbMV0gICAgICAgICA9IDIuMCAqICh2aWV3Qm94WzFdIC0gdGlja01hcmtMZW5ndGhbMF0pIC8gc2NyZWVuSGVpZ2h0IC0gMS4wXHJcbiAgICBUSUNLX1NDQUxFWzBdICAgICAgICAgPSB0aWNrTWFya1dpZHRoWzBdICAqIHBpeGVsUmF0aW8gLyBzY3JlZW5XaWR0aFxyXG4gICAgVElDS19TQ0FMRVsxXSAgICAgICAgID0gdGlja01hcmtMZW5ndGhbMF0gKiBwaXhlbFJhdGlvIC8gc2NyZWVuSGVpZ2h0XHJcblxyXG4gICAgaWYoeENvdW50KSB7XHJcbiAgICAgIHVuaWZvcm1zLmNvbG9yICAgICAgICA9IHRpY2tNYXJrQ29sb3JbMF1cclxuICAgICAgdW5pZm9ybXMudGlja1NjYWxlICAgID0gVElDS19TQ0FMRVxyXG4gICAgICB1bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBYX0FYSVNcclxuICAgICAgdW5pZm9ybXMuc2NyZWVuT2Zmc2V0ID0gU0NSX09GRlNFVFxyXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgeE9mZnNldCwgeENvdW50KVxyXG4gICAgfVxyXG5cclxuICAgIFNDUl9PRkZTRVRbMF0gICAgICAgICA9IDIuMCAqICh2aWV3Qm94WzJdICsgdGlja01hcmtMZW5ndGhbM10pIC8gc2NyZWVuV2lkdGggLSAxLjBcclxuICAgIFNDUl9PRkZTRVRbMV0gICAgICAgICA9ICh2aWV3Qm94WzNdICsgdmlld0JveFsxXSkgLyBzY3JlZW5IZWlnaHQgLSAxLjBcclxuICAgIFRJQ0tfU0NBTEVbMF0gICAgICAgICA9IHRpY2tNYXJrTGVuZ3RoWzNdICogcGl4ZWxSYXRpbyAvIHNjcmVlbldpZHRoXHJcbiAgICBUSUNLX1NDQUxFWzFdICAgICAgICAgPSB0aWNrTWFya1dpZHRoWzNdICAqIHBpeGVsUmF0aW8gLyBzY3JlZW5IZWlnaHRcclxuXHJcbiAgICBpZih5Q291bnQpIHtcclxuICAgICAgdW5pZm9ybXMuY29sb3IgICAgICAgID0gdGlja01hcmtDb2xvclszXVxyXG4gICAgICB1bmlmb3Jtcy50aWNrU2NhbGUgICAgPSBUSUNLX1NDQUxFXHJcbiAgICAgIHVuaWZvcm1zLmRhdGFBeGlzICAgICA9IFlfQVhJU1xyXG4gICAgICB1bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JfT0ZGU0VUXHJcbiAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB5T2Zmc2V0LCB5Q291bnQpXHJcbiAgICB9XHJcblxyXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gKHZpZXdCb3hbMl0gKyB2aWV3Qm94WzBdKSAvIHNjcmVlbldpZHRoIC0gMS4wXHJcbiAgICBTQ1JfT0ZGU0VUWzFdICAgICAgICAgPSAyLjAgKiAodmlld0JveFszXSArIHRpY2tNYXJrTGVuZ3RoWzJdKSAvIHNjcmVlbkhlaWdodCAtIDEuMFxyXG4gICAgVElDS19TQ0FMRVswXSAgICAgICAgID0gdGlja01hcmtXaWR0aFsyXSAgKiBwaXhlbFJhdGlvIC8gc2NyZWVuV2lkdGhcclxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrTGVuZ3RoWzJdICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxyXG5cclxuICAgIGlmKHhDb3VudCkge1xyXG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzJdXHJcbiAgICAgIHVuaWZvcm1zLnRpY2tTY2FsZSAgICA9IFRJQ0tfU0NBTEVcclxuICAgICAgdW5pZm9ybXMuZGF0YUF4aXMgICAgID0gWF9BWElTXHJcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcclxuICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIHhPZmZzZXQsIHhDb3VudClcclxuICAgIH1cclxuICB9XHJcbn0pKClcclxuXHJcbnByb3RvLnVwZGF0ZSA9IChmdW5jdGlvbigpIHtcclxuICB2YXIgT0ZGU0VUX1ggPSBbMSwgIDEsIC0xLCAtMSwgIDEsIC0xXVxyXG4gIHZhciBPRkZTRVRfWSA9IFsxLCAtMSwgIDEsICAxLCAtMSwgLTFdXHJcblxyXG4gIHJldHVybiBmdW5jdGlvbihvcHRpb25zKSB7XHJcbiAgICB2YXIgdGlja3MgID0gb3B0aW9ucy50aWNrc1xyXG4gICAgdmFyIGJvdW5kcyA9IG9wdGlvbnMuYm91bmRzXHJcbiAgICB2YXIgZGF0YSAgID0gbmV3IEZsb2F0MzJBcnJheSg2ICogMyAqICh0aWNrc1swXS5sZW5ndGggKyB0aWNrc1sxXS5sZW5ndGgpKVxyXG5cclxuICAgIHZhciB6ZXJvTGluZUVuYWJsZSA9IHRoaXMucGxvdC56ZXJvTGluZUVuYWJsZVxyXG5cclxuICAgIHZhciBwdHIgICAgPSAwXHJcbiAgICB2YXIgZ3JpZFRpY2tzID0gW1tdLCBbXV1cclxuICAgIGZvcih2YXIgZGltPTA7IGRpbTwyOyArK2RpbSkge1xyXG4gICAgICB2YXIgbG9jYWxUaWNrcyA9IGdyaWRUaWNrc1tkaW1dXHJcbiAgICAgIHZhciBheGlzVGlja3MgPSB0aWNrc1tkaW1dXHJcbiAgICAgIHZhciBsbyA9IGJvdW5kc1tkaW1dXHJcbiAgICAgIHZhciBoaSA9IGJvdW5kc1tkaW0rMl1cclxuICAgICAgZm9yKHZhciBpPTA7IGk8YXhpc1RpY2tzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgdmFyIHggPSAoYXhpc1RpY2tzW2ldLnggLSBsbykgLyAoaGkgLSBsbylcclxuICAgICAgICBsb2NhbFRpY2tzLnB1c2goeClcclxuICAgICAgICBmb3IodmFyIGo9MDsgajw2OyArK2opIHtcclxuICAgICAgICAgIGRhdGFbcHRyKytdID0geFxyXG4gICAgICAgICAgZGF0YVtwdHIrK10gPSBPRkZTRVRfWFtqXVxyXG4gICAgICAgICAgZGF0YVtwdHIrK10gPSBPRkZTRVRfWVtqXVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudGlja3MgPSBncmlkVGlja3NcclxuICAgIHRoaXMudmJvLnVwZGF0ZShkYXRhKVxyXG4gIH1cclxufSkoKVxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMudmJvLmRpc3Bvc2UoKVxyXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMudGlja1NoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlR3JpZChwbG90KSB7XHJcbiAgdmFyIGdsICAgICA9IHBsb3QuZ2xcclxuICB2YXIgdmJvICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHNoYWRlcnMuZ3JpZFZlcnQsIHNoYWRlcnMuZ3JpZEZyYWcpXHJcbiAgdmFyIHRpY2tTaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHNoYWRlcnMudGlja1ZlcnQsIHNoYWRlcnMuZ3JpZEZyYWcpXHJcbiAgdmFyIGdyaWQgICA9IG5ldyBHcmlkKHBsb3QsIHZibywgc2hhZGVyLCB0aWNrU2hhZGVyKVxyXG4gIHJldHVybiBncmlkXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUxpbmVzXHJcblxyXG52YXIgY3JlYXRlQnVmZmVyID0gcmVxdWlyZSgnZ2wtYnVmZmVyJylcclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcblxyXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycycpXHJcblxyXG5mdW5jdGlvbiBMaW5lcyhwbG90LCB2Ym8sIHNoYWRlcikge1xyXG4gIHRoaXMucGxvdCAgID0gcGxvdFxyXG4gIHRoaXMudmJvICAgID0gdmJvXHJcbiAgdGhpcy5zaGFkZXIgPSBzaGFkZXJcclxufVxyXG5cclxudmFyIHByb3RvID0gTGluZXMucHJvdG90eXBlXHJcblxyXG5wcm90by5iaW5kID0gZnVuY3Rpb24oKSB7XHJcbiAgdmFyIHNoYWRlciA9IHRoaXMuc2hhZGVyXHJcbiAgdGhpcy52Ym8uYmluZCgpXHJcbiAgdGhpcy5zaGFkZXIuYmluZCgpXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuY29vcmQucG9pbnRlcigpXHJcbiAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkJveCA9IHRoaXMucGxvdC5zY3JlZW5Cb3hcclxufVxyXG5cclxucHJvdG8uZHJhd0xpbmUgPSAoZnVuY3Rpb24oKSB7XHJcbiAgdmFyIHN0YXJ0ID0gWzAsMF1cclxuICB2YXIgZW5kICAgPSBbMCwwXVxyXG4gIHJldHVybiBmdW5jdGlvbihzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSwgd2lkdGgsIGNvbG9yKSB7XHJcbiAgICB2YXIgcGxvdCAgICAgICA9IHRoaXMucGxvdFxyXG4gICAgdmFyIHNoYWRlciAgICAgPSB0aGlzLnNoYWRlclxyXG4gICAgdmFyIGdsICAgICAgICAgPSBwbG90LmdsXHJcblxyXG4gICAgc3RhcnRbMF0gPSBzdGFydFhcclxuICAgIHN0YXJ0WzFdID0gc3RhcnRZXHJcbiAgICBlbmRbMF0gICA9IGVuZFhcclxuICAgIGVuZFsxXSAgID0gZW5kWVxyXG5cclxuICAgIHNoYWRlci51bmlmb3Jtcy5zdGFydCAgPSBzdGFydFxyXG4gICAgc2hhZGVyLnVuaWZvcm1zLmVuZCAgICA9IGVuZFxyXG4gICAgc2hhZGVyLnVuaWZvcm1zLndpZHRoICA9IHdpZHRoICogcGxvdC5waXhlbFJhdGlvXHJcbiAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgID0gY29sb3JcclxuXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KVxyXG4gIH1cclxufSgpKVxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMudmJvLmRpc3Bvc2UoKVxyXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVMaW5lcyhwbG90KSB7XHJcbiAgdmFyIGdsICA9IHBsb3QuZ2xcclxuICB2YXIgdmJvID0gY3JlYXRlQnVmZmVyKGdsLCBbXHJcbiAgICAtMSwtMSxcclxuICAgIC0xLDEsXHJcbiAgICAxLC0xLFxyXG4gICAgMSwxXSlcclxuICB2YXIgc2hhZGVyICA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy5saW5lVmVydCwgc2hhZGVycy5saW5lRnJhZylcclxuICB2YXIgbGluZXMgICA9IG5ldyBMaW5lcyhwbG90LCB2Ym8sIHNoYWRlcilcclxuICByZXR1cm4gbGluZXNcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBnbHNsaWZ5ID0gcmVxdWlyZSgnZ2xzbGlmeScpXHJcblxyXG52YXIgRlJBR01FTlQgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBsb3dwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxudW5pZm9ybSB2ZWM0IGNvbG9yO1xcbnZvaWQgbWFpbigpIHtcXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQoY29sb3IueHl6ICogY29sb3IudywgY29sb3Iudyk7XFxufVxcblwiXSlcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gIGxpbmVWZXJ0OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgY29vcmQ7XFxuXFxudW5pZm9ybSB2ZWM0IHNjcmVlbkJveDtcXG51bmlmb3JtIHZlYzIgc3RhcnQsIGVuZDtcXG51bmlmb3JtIGZsb2F0IHdpZHRoO1xcblxcbnZlYzIgcGVycCh2ZWMyIHYpIHtcXG4gIHJldHVybiB2ZWMyKHYueSwgLXYueCk7XFxufVxcblxcbnZlYzIgc2NyZWVuKHZlYzIgdikge1xcbiAgcmV0dXJuIDIuMCAqICh2IC0gc2NyZWVuQm94Lnh5KSAvIChzY3JlZW5Cb3guencgLSBzY3JlZW5Cb3gueHkpIC0gMS4wO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICB2ZWMyIGRlbHRhID0gbm9ybWFsaXplKHBlcnAoc3RhcnQgLSBlbmQpKTtcXG4gIHZlYzIgb2Zmc2V0ID0gbWl4KHN0YXJ0LCBlbmQsIDAuNSAqIChjb29yZC55KzEuMCkpO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHNjcmVlbihvZmZzZXQgKyAwLjUgKiB3aWR0aCAqIGRlbHRhICogY29vcmQueCksIDAsIDEpO1xcbn1cXG5cIl0pLFxyXG4gIGxpbmVGcmFnOiBGUkFHTUVOVCxcclxuICB0ZXh0VmVydDogZ2xzbGlmeShbXCIjZGVmaW5lIEdMU0xJRlkgMVxcbmF0dHJpYnV0ZSB2ZWMzIHRleHRDb29yZGluYXRlO1xcblxcbnVuaWZvcm0gdmVjMiBkYXRhU2NhbGUsIGRhdGFTaGlmdCwgZGF0YUF4aXMsIHNjcmVlbk9mZnNldCwgdGV4dFNjYWxlO1xcbnVuaWZvcm0gZmxvYXQgYW5nbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZmxvYXQgZGF0YU9mZnNldCAgPSB0ZXh0Q29vcmRpbmF0ZS56O1xcbiAgdmVjMiBnbHlwaE9mZnNldCAgPSB0ZXh0Q29vcmRpbmF0ZS54eTtcXG4gIG1hdDIgZ2x5cGhNYXRyaXggPSBtYXQyKGNvcyhhbmdsZSksIHNpbihhbmdsZSksIC1zaW4oYW5nbGUpLCBjb3MoYW5nbGUpKTtcXG4gIHZlYzIgc2NyZWVuQ29vcmRpbmF0ZSA9IGRhdGFBeGlzICogKGRhdGFTY2FsZSAqIGRhdGFPZmZzZXQgKyBkYXRhU2hpZnQpICtcXG4gICAgZ2x5cGhNYXRyaXggKiBnbHlwaE9mZnNldCAqIHRleHRTY2FsZSArIHNjcmVlbk9mZnNldDtcXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChzY3JlZW5Db29yZGluYXRlLCAwLCAxKTtcXG59XFxuXCJdKSxcclxuICB0ZXh0RnJhZzogRlJBR01FTlQsXHJcbiAgZ3JpZFZlcnQ6IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBkYXRhQ29vcmQ7XFxuXFxudW5pZm9ybSB2ZWMyIGRhdGFBeGlzLCBkYXRhU2hpZnQsIGRhdGFTY2FsZTtcXG51bmlmb3JtIGZsb2F0IGxpbmVXaWR0aDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICB2ZWMyIHBvcyA9IGRhdGFBeGlzICogKGRhdGFTY2FsZSAqIGRhdGFDb29yZC54ICsgZGF0YVNoaWZ0KTtcXG4gIHBvcyArPSAxMC4wICogZGF0YUNvb3JkLnkgKiB2ZWMyKGRhdGFBeGlzLnksIC1kYXRhQXhpcy54KSArIGRhdGFDb29yZC56ICogbGluZVdpZHRoO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvcywgMCwgMSk7XFxufVxcblwiXSksXHJcbiAgZ3JpZEZyYWc6IEZSQUdNRU5ULFxyXG4gIGJveFZlcnQ6ICBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgY29vcmQ7XFxuXFxudW5pZm9ybSB2ZWM0IHNjcmVlbkJveDtcXG51bmlmb3JtIHZlYzIgbG8sIGhpO1xcblxcbnZlYzIgc2NyZWVuKHZlYzIgdikge1xcbiAgcmV0dXJuIDIuMCAqICh2IC0gc2NyZWVuQm94Lnh5KSAvIChzY3JlZW5Cb3guencgLSBzY3JlZW5Cb3gueHkpIC0gMS4wO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQoc2NyZWVuKG1peChsbywgaGksIGNvb3JkKSksIDAsIDEpO1xcbn1cXG5cIl0pLFxyXG4gIHRpY2tWZXJ0OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgZGF0YUNvb3JkO1xcblxcbnVuaWZvcm0gdmVjMiBkYXRhQXhpcywgZGF0YVNoaWZ0LCBkYXRhU2NhbGUsIHNjcmVlbk9mZnNldCwgdGlja1NjYWxlO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzIgcG9zID0gZGF0YUF4aXMgKiAoZGF0YVNjYWxlICogZGF0YUNvb3JkLnggKyBkYXRhU2hpZnQpO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvcyArIHRpY2tTY2FsZSpkYXRhQ29vcmQueXogKyBzY3JlZW5PZmZzZXQsIDAsIDEpO1xcbn1cXG5cIl0pXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVRleHRFbGVtZW50c1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXHJcbnZhciBjcmVhdGVTaGFkZXIgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG52YXIgZ2V0VGV4dCAgICAgID0gcmVxdWlyZSgndGV4dC1jYWNoZScpXHJcbnZhciBic2VhcmNoICAgICAgPSByZXF1aXJlKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXHJcbnZhciBzaGFkZXJzICAgICAgPSByZXF1aXJlKCcuL3NoYWRlcnMnKVxyXG5cclxuZnVuY3Rpb24gVGV4dEVsZW1lbnRzKHBsb3QsIHZibywgc2hhZGVyKSB7XHJcbiAgdGhpcy5wbG90ICAgICAgICAgPSBwbG90XHJcbiAgdGhpcy52Ym8gICAgICAgICAgPSB2Ym9cclxuICB0aGlzLnNoYWRlciAgICAgICA9IHNoYWRlclxyXG4gIHRoaXMudGlja09mZnNldCAgID0gW1tdLFtdXVxyXG4gIHRoaXMudGlja1ggICAgICAgID0gW1tdLFtdXVxyXG4gIHRoaXMubGFiZWxPZmZzZXQgID0gWzAsMF1cclxuICB0aGlzLmxhYmVsQ291bnQgICA9IFswLDBdXHJcbn1cclxuXHJcbnZhciBwcm90byA9IFRleHRFbGVtZW50cy5wcm90b3R5cGVcclxuXHJcbnByb3RvLmRyYXdUaWNrcyA9IChmdW5jdGlvbigpIHtcclxuICB2YXIgREFUQV9BWElTID0gWzAsMF1cclxuICB2YXIgU0NSRUVOX09GRlNFVCA9IFswLDBdXHJcbiAgdmFyIFpFUk9fMiA9IFswLDBdXHJcblxyXG4gIHJldHVybiBmdW5jdGlvbihheGlzKSB7XHJcbiAgICB2YXIgcGxvdCAgICAgICAgPSB0aGlzLnBsb3RcclxuICAgIHZhciBzaGFkZXIgICAgICA9IHRoaXMuc2hhZGVyXHJcbiAgICB2YXIgdGlja1ggICAgICAgPSB0aGlzLnRpY2tYW2F4aXNdXHJcbiAgICB2YXIgdGlja09mZnNldCAgPSB0aGlzLnRpY2tPZmZzZXRbYXhpc11cclxuICAgIHZhciBnbCAgICAgICAgICA9IHBsb3QuZ2xcclxuICAgIHZhciB2aWV3Qm94ICAgICA9IHBsb3Qudmlld0JveFxyXG4gICAgdmFyIGRhdGFCb3ggICAgID0gcGxvdC5kYXRhQm94XHJcbiAgICB2YXIgc2NyZWVuQm94ICAgPSBwbG90LnNjcmVlbkJveFxyXG4gICAgdmFyIHBpeGVsUmF0aW8gID0gcGxvdC5waXhlbFJhdGlvXHJcbiAgICB2YXIgdGlja0VuYWJsZSAgPSBwbG90LnRpY2tFbmFibGVcclxuICAgIHZhciB0aWNrUGFkICAgICA9IHBsb3QudGlja1BhZFxyXG4gICAgdmFyIHRleHRDb2xvciAgID0gcGxvdC50aWNrQ29sb3JcclxuICAgIHZhciB0ZXh0QW5nbGUgICA9IHBsb3QudGlja0FuZ2xlXHJcbiAgICAvLyB0b2RvIGNoZWNrIGlmIHRoaXMgc2hvdWxkIGJlIHVzZWQgKG5vdyB1bnVzZWQpXHJcbiAgICAvLyB2YXIgdGlja0xlbmd0aCAgPSBwbG90LnRpY2tNYXJrTGVuZ3RoXHJcblxyXG4gICAgdmFyIGxhYmVsRW5hYmxlID0gcGxvdC5sYWJlbEVuYWJsZVxyXG4gICAgdmFyIGxhYmVsUGFkICAgID0gcGxvdC5sYWJlbFBhZFxyXG4gICAgdmFyIGxhYmVsQ29sb3IgID0gcGxvdC5sYWJlbENvbG9yXHJcbiAgICB2YXIgbGFiZWxBbmdsZSAgPSBwbG90LmxhYmVsQW5nbGVcclxuICAgIHZhciBsYWJlbE9mZnNldCA9IHRoaXMubGFiZWxPZmZzZXRbYXhpc11cclxuICAgIHZhciBsYWJlbENvdW50ICA9IHRoaXMubGFiZWxDb3VudFtheGlzXVxyXG5cclxuICAgIHZhciBzdGFydCA9IGJzZWFyY2gubHQodGlja1gsIGRhdGFCb3hbYXhpc10pXHJcbiAgICB2YXIgZW5kICAgPSBic2VhcmNoLmxlKHRpY2tYLCBkYXRhQm94W2F4aXMrMl0pXHJcblxyXG4gICAgREFUQV9BWElTWzBdICAgID0gREFUQV9BWElTWzFdID0gMFxyXG4gICAgREFUQV9BWElTW2F4aXNdID0gMVxyXG5cclxuICAgIFNDUkVFTl9PRkZTRVRbYXhpc10gPSAodmlld0JveFsyK2F4aXNdICsgdmlld0JveFtheGlzXSkgLyAoc2NyZWVuQm94WzIrYXhpc10gLSBzY3JlZW5Cb3hbYXhpc10pIC0gMS4wXHJcblxyXG4gICAgdmFyIHNjcmVlblNjYWxlID0gMi4wIC8gc2NyZWVuQm94WzIrKGF4aXNeMSldIC0gc2NyZWVuQm94W2F4aXNeMV1cclxuXHJcbiAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gPSBzY3JlZW5TY2FsZSAqIHZpZXdCb3hbYXhpc14xXSAtIDEuMFxyXG4gICAgaWYodGlja0VuYWJsZVtheGlzXSkge1xyXG4gICAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gLT0gc2NyZWVuU2NhbGUgKiBwaXhlbFJhdGlvICogdGlja1BhZFtheGlzXVxyXG4gICAgICBpZihzdGFydCA8IGVuZCAmJiB0aWNrT2Zmc2V0W2VuZF0gPiB0aWNrT2Zmc2V0W3N0YXJ0XSkge1xyXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBEQVRBX0FYSVNcclxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuc2NyZWVuT2Zmc2V0ID0gU0NSRUVOX09GRlNFVFxyXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0ZXh0Q29sb3JbYXhpc11cclxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuYW5nbGUgICAgICAgID0gdGV4dEFuZ2xlW2F4aXNdXHJcbiAgICAgICAgZ2wuZHJhd0FycmF5cyhcclxuICAgICAgICAgIGdsLlRSSUFOR0xFUyxcclxuICAgICAgICAgIHRpY2tPZmZzZXRbc3RhcnRdLFxyXG4gICAgICAgICAgdGlja09mZnNldFtlbmRdIC0gdGlja09mZnNldFtzdGFydF0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmKGxhYmVsRW5hYmxlW2F4aXNdICYmIGxhYmVsQ291bnQpIHtcclxuICAgICAgU0NSRUVOX09GRlNFVFtheGlzXjFdIC09IHNjcmVlblNjYWxlICogcGl4ZWxSYXRpbyAqIGxhYmVsUGFkW2F4aXNdXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBaRVJPXzJcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUkVFTl9PRkZTRVRcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbG9yICAgICAgICA9IGxhYmVsQ29sb3JbYXhpc11cclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmFuZ2xlICAgICAgICA9IGxhYmVsQW5nbGVbYXhpc11cclxuICAgICAgZ2wuZHJhd0FycmF5cyhcclxuICAgICAgICBnbC5UUklBTkdMRVMsXHJcbiAgICAgICAgbGFiZWxPZmZzZXQsXHJcbiAgICAgICAgbGFiZWxDb3VudClcclxuICAgIH1cclxuXHJcbiAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gPSBzY3JlZW5TY2FsZSAqIHZpZXdCb3hbMisoYXhpc14xKV0gLSAxLjBcclxuICAgIGlmKHRpY2tFbmFibGVbYXhpcysyXSkge1xyXG4gICAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gKz0gc2NyZWVuU2NhbGUgKiBwaXhlbFJhdGlvICogdGlja1BhZFtheGlzKzJdXHJcbiAgICAgIGlmKHN0YXJ0IDwgZW5kICYmIHRpY2tPZmZzZXRbZW5kXSA+IHRpY2tPZmZzZXRbc3RhcnRdKSB7XHJcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFBeGlzICAgICA9IERBVEFfQVhJU1xyXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JFRU5fT0ZGU0VUXHJcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbG9yICAgICAgICA9IHRleHRDb2xvcltheGlzKzJdXHJcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmFuZ2xlICAgICAgICA9IHRleHRBbmdsZVtheGlzKzJdXHJcbiAgICAgICAgZ2wuZHJhd0FycmF5cyhcclxuICAgICAgICAgIGdsLlRSSUFOR0xFUyxcclxuICAgICAgICAgIHRpY2tPZmZzZXRbc3RhcnRdLFxyXG4gICAgICAgICAgdGlja09mZnNldFtlbmRdIC0gdGlja09mZnNldFtzdGFydF0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmKGxhYmVsRW5hYmxlW2F4aXMrMl0gJiYgbGFiZWxDb3VudCkge1xyXG4gICAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gKz0gc2NyZWVuU2NhbGUgKiBwaXhlbFJhdGlvICogbGFiZWxQYWRbYXhpcysyXVxyXG4gICAgICBzaGFkZXIudW5pZm9ybXMuZGF0YUF4aXMgICAgID0gWkVST18yXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JFRU5fT0ZGU0VUXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICAgPSBsYWJlbENvbG9yW2F4aXMrMl1cclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmFuZ2xlICAgICAgICA9IGxhYmVsQW5nbGVbYXhpcysyXVxyXG4gICAgICBnbC5kcmF3QXJyYXlzKFxyXG4gICAgICAgIGdsLlRSSUFOR0xFUyxcclxuICAgICAgICBsYWJlbE9mZnNldCxcclxuICAgICAgICBsYWJlbENvdW50KVxyXG4gICAgfVxyXG5cclxuICB9XHJcbn0pKClcclxuXHJcbnByb3RvLmRyYXdUaXRsZSA9IChmdW5jdGlvbigpIHtcclxuICB2YXIgREFUQV9BWElTID0gWzAsMF1cclxuICB2YXIgU0NSRUVOX09GRlNFVCA9IFswLDBdXHJcblxyXG4gIHJldHVybiBmdW5jdGlvbigpIHtcclxuICAgIHZhciBwbG90ICAgICAgICA9IHRoaXMucGxvdFxyXG4gICAgdmFyIHNoYWRlciAgICAgID0gdGhpcy5zaGFkZXJcclxuICAgIHZhciBnbCAgICAgICAgICA9IHBsb3QuZ2xcclxuICAgIHZhciBzY3JlZW5Cb3ggICA9IHBsb3Quc2NyZWVuQm94XHJcbiAgICB2YXIgdGl0bGVDZW50ZXIgPSBwbG90LnRpdGxlQ2VudGVyXHJcbiAgICB2YXIgdGl0bGVBbmdsZSAgPSBwbG90LnRpdGxlQW5nbGVcclxuICAgIHZhciB0aXRsZUNvbG9yICA9IHBsb3QudGl0bGVDb2xvclxyXG4gICAgdmFyIHBpeGVsUmF0aW8gID0gcGxvdC5waXhlbFJhdGlvXHJcblxyXG4gICAgaWYoIXRoaXMudGl0bGVDb3VudCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuXHJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgICAgU0NSRUVOX09GRlNFVFtpXSA9IDIuMCAqICh0aXRsZUNlbnRlcltpXSpwaXhlbFJhdGlvIC0gc2NyZWVuQm94W2ldKSAvXHJcbiAgICAgICAgKHNjcmVlbkJveFsyK2ldIC0gc2NyZWVuQm94W2ldKSAtIDFcclxuICAgIH1cclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcbiAgICBzaGFkZXIudW5pZm9ybXMuZGF0YUF4aXMgICAgICA9IERBVEFfQVhJU1xyXG4gICAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlbk9mZnNldCAgPSBTQ1JFRU5fT0ZGU0VUXHJcbiAgICBzaGFkZXIudW5pZm9ybXMuYW5nbGUgICAgICAgICA9IHRpdGxlQW5nbGVcclxuICAgIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICAgID0gdGl0bGVDb2xvclxyXG5cclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB0aGlzLnRpdGxlT2Zmc2V0LCB0aGlzLnRpdGxlQ291bnQpXHJcbiAgfVxyXG59KSgpXHJcblxyXG5wcm90by5iaW5kID0gKGZ1bmN0aW9uKCkge1xyXG4gIHZhciBEQVRBX1NISUZUID0gWzAsMF1cclxuICB2YXIgREFUQV9TQ0FMRSA9IFswLDBdXHJcbiAgdmFyIFRFWFRfU0NBTEUgPSBbMCwwXVxyXG5cclxuICByZXR1cm4gZnVuY3Rpb24oKSB7XHJcbiAgICB2YXIgcGxvdCAgICAgID0gdGhpcy5wbG90XHJcbiAgICB2YXIgc2hhZGVyICAgID0gdGhpcy5zaGFkZXJcclxuICAgIHZhciBib3VuZHMgICAgPSBwbG90Ll90aWNrQm91bmRzXHJcbiAgICB2YXIgZGF0YUJveCAgID0gcGxvdC5kYXRhQm94XHJcbiAgICB2YXIgc2NyZWVuQm94ID0gcGxvdC5zY3JlZW5Cb3hcclxuICAgIHZhciB2aWV3Qm94ICAgPSBwbG90LnZpZXdCb3hcclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcblxyXG4gICAgLy9TZXQgdXAgY29vcmRpbmF0ZSBzY2FsaW5nIHVuaWZvcm1zXHJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuXHJcbiAgICAgIHZhciBsbyA9IGJvdW5kc1tpXVxyXG4gICAgICB2YXIgaGkgPSBib3VuZHNbaSsyXVxyXG4gICAgICB2YXIgYm91bmRTY2FsZSA9IGhpIC0gbG9cclxuICAgICAgdmFyIGRhdGFDZW50ZXIgID0gMC41ICogKGRhdGFCb3hbaSsyXSArIGRhdGFCb3hbaV0pXHJcbiAgICAgIHZhciBkYXRhV2lkdGggICA9IChkYXRhQm94W2krMl0gLSBkYXRhQm94W2ldKVxyXG5cclxuICAgICAgdmFyIHZpZXdMbyA9IHZpZXdCb3hbaV1cclxuICAgICAgdmFyIHZpZXdIaSA9IHZpZXdCb3hbaSsyXVxyXG4gICAgICB2YXIgdmlld1NjYWxlID0gdmlld0hpIC0gdmlld0xvXHJcbiAgICAgIHZhciBzY3JlZW5MbyA9IHNjcmVlbkJveFtpXVxyXG4gICAgICB2YXIgc2NyZWVuSGkgPSBzY3JlZW5Cb3hbaSsyXVxyXG4gICAgICB2YXIgc2NyZWVuU2NhbGUgPSBzY3JlZW5IaSAtIHNjcmVlbkxvXHJcblxyXG4gICAgICBEQVRBX1NDQUxFW2ldID0gMi4wICogYm91bmRTY2FsZSAvIGRhdGFXaWR0aCAqIHZpZXdTY2FsZSAvIHNjcmVlblNjYWxlXHJcbiAgICAgIERBVEFfU0hJRlRbaV0gPSAyLjAgKiAobG8gLSBkYXRhQ2VudGVyKSAvIGRhdGFXaWR0aCAqIHZpZXdTY2FsZSAvIHNjcmVlblNjYWxlXHJcbiAgICB9XHJcblxyXG4gICAgVEVYVF9TQ0FMRVsxXSA9IDIuMCAqIHBsb3QucGl4ZWxSYXRpbyAvIChzY3JlZW5Cb3hbM10gLSBzY3JlZW5Cb3hbMV0pXHJcbiAgICBURVhUX1NDQUxFWzBdID0gVEVYVF9TQ0FMRVsxXSAqIChzY3JlZW5Cb3hbM10gLSBzY3JlZW5Cb3hbMV0pIC8gKHNjcmVlbkJveFsyXSAtIHNjcmVlbkJveFswXSlcclxuXHJcbiAgICBzaGFkZXIudW5pZm9ybXMuZGF0YVNjYWxlID0gREFUQV9TQ0FMRVxyXG4gICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFTaGlmdCA9IERBVEFfU0hJRlRcclxuICAgIHNoYWRlci51bmlmb3Jtcy50ZXh0U2NhbGUgPSBURVhUX1NDQUxFXHJcblxyXG4gICAgLy9TZXQgYXR0cmlidXRlc1xyXG4gICAgdGhpcy52Ym8uYmluZCgpXHJcbiAgICBzaGFkZXIuYXR0cmlidXRlcy50ZXh0Q29vcmRpbmF0ZS5wb2ludGVyKClcclxuICB9XHJcbn0pKClcclxuXHJcbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcclxuICB2YXIgdmVydGljZXMgID0gW11cclxuICB2YXIgYXhlc1RpY2tzID0gb3B0aW9ucy50aWNrc1xyXG4gIHZhciBib3VuZHMgICAgPSBvcHRpb25zLmJvdW5kc1xyXG4gIHZhciBpLCBqLCBrLCBkYXRhLCBzY2FsZSwgZGltZW5zaW9uXHJcblxyXG4gIGZvcihkaW1lbnNpb249MDsgZGltZW5zaW9uPDI7ICsrZGltZW5zaW9uKSB7XHJcbiAgICB2YXIgb2Zmc2V0cyA9IFtNYXRoLmZsb29yKHZlcnRpY2VzLmxlbmd0aC8zKV0sIHRpY2tYID0gWy1JbmZpbml0eV1cclxuXHJcbiAgICAvL0NvcHkgdmVydGljZXMgb3ZlciB0byBidWZmZXJcclxuICAgIHZhciB0aWNrcyA9IGF4ZXNUaWNrc1tkaW1lbnNpb25dXHJcbiAgICBmb3IoaT0wOyBpPHRpY2tzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIHZhciB0aWNrICA9IHRpY2tzW2ldXHJcbiAgICAgIHZhciB4ICAgICA9IHRpY2sueFxyXG4gICAgICB2YXIgdGV4dCAgPSB0aWNrLnRleHRcclxuICAgICAgdmFyIGZvbnQgID0gdGljay5mb250IHx8ICdzYW5zLXNlcmlmJ1xyXG4gICAgICBzY2FsZSA9ICh0aWNrLmZvbnRTaXplIHx8IDEyKVxyXG5cclxuICAgICAgdmFyIGNvb3JkU2NhbGUgPSAxLjAgLyAoYm91bmRzW2RpbWVuc2lvbisyXSAtIGJvdW5kc1tkaW1lbnNpb25dKVxyXG4gICAgICB2YXIgY29vcmRTaGlmdCA9IGJvdW5kc1tkaW1lbnNpb25dXHJcblxyXG4gICAgICB2YXIgcm93cyA9IHRleHQuc3BsaXQoJ1xcbicpXHJcbiAgICAgIGZvcih2YXIgciA9IDA7IHIgPCByb3dzLmxlbmd0aDsgcisrKSB7XHJcbiAgICAgICAgZGF0YSA9IGdldFRleHQoZm9udCwgcm93c1tyXSkuZGF0YVxyXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBkYXRhLmxlbmd0aDsgaiArPSAyKSB7XHJcbiAgICAgICAgICB2ZXJ0aWNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgIGRhdGFbal0gKiBzY2FsZSxcclxuICAgICAgICAgICAgICAtZGF0YVtqICsgMV0gKiBzY2FsZSAtIHIgKiBzY2FsZSAqIDEuMixcclxuICAgICAgICAgICAgICAoeCAtIGNvb3JkU2hpZnQpICogY29vcmRTY2FsZSlcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIG9mZnNldHMucHVzaChNYXRoLmZsb29yKHZlcnRpY2VzLmxlbmd0aC8zKSlcclxuICAgICAgdGlja1gucHVzaCh4KVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudGlja09mZnNldFtkaW1lbnNpb25dID0gb2Zmc2V0c1xyXG4gICAgdGhpcy50aWNrWFtkaW1lbnNpb25dID0gdGlja1hcclxuICB9XHJcblxyXG4gIC8vQWRkIGxhYmVsc1xyXG4gIGZvcihkaW1lbnNpb249MDsgZGltZW5zaW9uPDI7ICsrZGltZW5zaW9uKSB7XHJcbiAgICB0aGlzLmxhYmVsT2Zmc2V0W2RpbWVuc2lvbl0gPSBNYXRoLmZsb29yKHZlcnRpY2VzLmxlbmd0aC8zKVxyXG5cclxuICAgIGRhdGEgID0gZ2V0VGV4dChvcHRpb25zLmxhYmVsRm9udFtkaW1lbnNpb25dLCBvcHRpb25zLmxhYmVsc1tkaW1lbnNpb25dLCB7IHRleHRBbGlnbjogJ2NlbnRlcicgfSkuZGF0YVxyXG4gICAgc2NhbGUgPSBvcHRpb25zLmxhYmVsU2l6ZVtkaW1lbnNpb25dXHJcbiAgICBmb3IoaT0wOyBpPGRhdGEubGVuZ3RoOyBpKz0yKSB7XHJcbiAgICAgIHZlcnRpY2VzLnB1c2goZGF0YVtpXSpzY2FsZSwgLWRhdGFbaSsxXSpzY2FsZSwgMClcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmxhYmVsQ291bnRbZGltZW5zaW9uXSA9XHJcbiAgICAgIE1hdGguZmxvb3IodmVydGljZXMubGVuZ3RoLzMpIC0gdGhpcy5sYWJlbE9mZnNldFtkaW1lbnNpb25dXHJcbiAgfVxyXG5cclxuICAvL0FkZCB0aXRsZVxyXG4gIHRoaXMudGl0bGVPZmZzZXQgPSBNYXRoLmZsb29yKHZlcnRpY2VzLmxlbmd0aC8zKVxyXG4gIGRhdGEgPSBnZXRUZXh0KG9wdGlvbnMudGl0bGVGb250LCBvcHRpb25zLnRpdGxlKS5kYXRhXHJcbiAgc2NhbGUgPSBvcHRpb25zLnRpdGxlU2l6ZVxyXG4gIGZvcihpPTA7IGk8ZGF0YS5sZW5ndGg7IGkrPTIpIHtcclxuICAgIHZlcnRpY2VzLnB1c2goZGF0YVtpXSpzY2FsZSwgLWRhdGFbaSsxXSpzY2FsZSwgMClcclxuICB9XHJcbiAgdGhpcy50aXRsZUNvdW50ID0gTWF0aC5mbG9vcih2ZXJ0aWNlcy5sZW5ndGgvMykgLSB0aGlzLnRpdGxlT2Zmc2V0XHJcblxyXG4gIC8vVXBsb2FkIG5ldyB2ZXJ0aWNlc1xyXG4gIHRoaXMudmJvLnVwZGF0ZSh2ZXJ0aWNlcylcclxufVxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMudmJvLmRpc3Bvc2UoKVxyXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVUZXh0RWxlbWVudHMocGxvdCkge1xyXG4gIHZhciBnbCA9IHBsb3QuZ2xcclxuICB2YXIgdmJvID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHNoYWRlcnMudGV4dFZlcnQsIHNoYWRlcnMudGV4dEZyYWcpXHJcbiAgdmFyIHRleHQgPSBuZXcgVGV4dEVsZW1lbnRzKHBsb3QsIHZibywgc2hhZGVyKVxyXG4gIHJldHVybiB0ZXh0XHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUdMUGxvdDJEXHJcblxyXG52YXIgY3JlYXRlUGljayA9IHJlcXVpcmUoJ2dsLXNlbGVjdC1zdGF0aWMnKVxyXG5cclxudmFyIGNyZWF0ZUdyaWQgPSByZXF1aXJlKCcuL2xpYi9ncmlkJylcclxudmFyIGNyZWF0ZVRleHQgPSByZXF1aXJlKCcuL2xpYi90ZXh0JylcclxudmFyIGNyZWF0ZUxpbmUgPSByZXF1aXJlKCcuL2xpYi9saW5lJylcclxudmFyIGNyZWF0ZUJveCAgPSByZXF1aXJlKCcuL2xpYi9ib3gnKVxyXG5cclxuZnVuY3Rpb24gR0xQbG90MkQoZ2wsIHBpY2tCdWZmZXIpIHtcclxuICB0aGlzLmdsICAgICAgICAgICAgICAgPSBnbFxyXG4gIHRoaXMucGlja0J1ZmZlciAgICAgICA9IHBpY2tCdWZmZXJcclxuXHJcbiAgdGhpcy5zY3JlZW5Cb3ggICAgICAgID0gWzAsIDAsIGdsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF1cclxuICB0aGlzLnZpZXdCb3ggICAgICAgICAgPSBbMCwgMCwgMCwgMF1cclxuICB0aGlzLmRhdGFCb3ggICAgICAgICAgPSBbLTEwLCAtMTAsIDEwLCAxMF1cclxuXHJcbiAgdGhpcy5ncmlkTGluZUVuYWJsZSAgID0gW3RydWUsdHJ1ZV1cclxuICB0aGlzLmdyaWRMaW5lV2lkdGggICAgPSBbMSwxXVxyXG4gIHRoaXMuZ3JpZExpbmVDb2xvciAgICA9IFtbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cclxuXHJcbiAgdGhpcy5waXhlbFJhdGlvICAgICAgID0gMVxyXG5cclxuICB0aGlzLnRpY2tNYXJrTGVuZ3RoICAgPSBbMCwwLDAsMF1cclxuICB0aGlzLnRpY2tNYXJrV2lkdGggICAgPSBbMCwwLDAsMF1cclxuICB0aGlzLnRpY2tNYXJrQ29sb3IgICAgPSBbWzAsMCwwLDFdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdXVxyXG5cclxuICB0aGlzLnRpY2tQYWQgICAgICAgICAgPSBbMTUsMTUsMTUsMTVdXHJcbiAgdGhpcy50aWNrQW5nbGUgICAgICAgID0gWzAsMCwwLDBdXHJcbiAgdGhpcy50aWNrRW5hYmxlICAgICAgID0gW3RydWUsdHJ1ZSx0cnVlLHRydWVdXHJcbiAgdGhpcy50aWNrQ29sb3IgICAgICAgID0gW1swLDAsMCwxXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cclxuXHJcbiAgdGhpcy5sYWJlbFBhZCAgICAgICAgID0gWzE1LDE1LDE1LDE1XVxyXG4gIHRoaXMubGFiZWxBbmdsZSAgICAgICA9IFswLE1hdGguUEkvMiwwLDMuMCpNYXRoLlBJLzJdXHJcbiAgdGhpcy5sYWJlbEVuYWJsZSAgICAgID0gW3RydWUsdHJ1ZSx0cnVlLHRydWVdXHJcbiAgdGhpcy5sYWJlbENvbG9yICAgICAgID0gW1swLDAsMCwxXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cclxuXHJcbiAgdGhpcy50aXRsZUNlbnRlciAgICAgID0gWzAsMF1cclxuICB0aGlzLnRpdGxlRW5hYmxlICAgICAgPSB0cnVlXHJcbiAgdGhpcy50aXRsZUFuZ2xlICAgICAgID0gMFxyXG4gIHRoaXMudGl0bGVDb2xvciAgICAgICA9IFswLDAsMCwxXVxyXG5cclxuICB0aGlzLmJvcmRlckNvbG9yICAgICAgPSBbMCwwLDAsMF1cclxuICB0aGlzLmJhY2tncm91bmRDb2xvciAgPSBbMCwwLDAsMF1cclxuXHJcbiAgdGhpcy56ZXJvTGluZUVuYWJsZSAgID0gW3RydWUsIHRydWVdXHJcbiAgdGhpcy56ZXJvTGluZVdpZHRoICAgID0gWzQsIDRdXHJcbiAgdGhpcy56ZXJvTGluZUNvbG9yICAgID0gW1swLCAwLCAwLCAxXSxbMCwgMCwgMCwgMV1dXHJcblxyXG4gIHRoaXMuYm9yZGVyTGluZUVuYWJsZSA9IFt0cnVlLHRydWUsdHJ1ZSx0cnVlXVxyXG4gIHRoaXMuYm9yZGVyTGluZVdpZHRoICA9IFsyLDIsMiwyXVxyXG4gIHRoaXMuYm9yZGVyTGluZUNvbG9yICA9IFtbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV1dXHJcblxyXG4gIC8vRHJhd2luZyBwYXJhbWV0ZXJzXHJcbiAgdGhpcy5ncmlkICAgICAgICAgICAgID0gbnVsbFxyXG4gIHRoaXMudGV4dCAgICAgICAgICAgICA9IG51bGxcclxuICB0aGlzLmxpbmUgICAgICAgICAgICAgPSBudWxsXHJcbiAgdGhpcy5ib3ggICAgICAgICAgICAgID0gbnVsbFxyXG4gIHRoaXMub2JqZWN0cyAgICAgICAgICA9IFtdXHJcbiAgdGhpcy5vdmVybGF5cyAgICAgICAgID0gW11cclxuXHJcbiAgdGhpcy5fdGlja0JvdW5kcyAgICAgID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXHJcblxyXG4gIHRoaXMuc3RhdGljID0gZmFsc2VcclxuXHJcbiAgdGhpcy5kaXJ0eSAgICAgICAgPSBmYWxzZVxyXG4gIHRoaXMucGlja0RpcnR5ICAgID0gZmFsc2VcclxuICB0aGlzLnBpY2tEZWxheSAgICA9IDEyMFxyXG4gIHRoaXMucGlja1JhZGl1cyAgID0gMTBcclxuICB0aGlzLl9waWNrVGltZW91dCA9IG51bGxcclxuICB0aGlzLl9kcmF3UGljayAgICA9IHRoaXMuZHJhd1BpY2suYmluZCh0aGlzKVxyXG5cclxuICB0aGlzLl9kZXB0aENvdW50ZXIgPSAwXHJcbn1cclxuXHJcbnZhciBwcm90byA9IEdMUGxvdDJELnByb3RvdHlwZVxyXG5cclxucHJvdG8uc2V0RGlydHkgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLmRpcnR5ID0gdGhpcy5waWNrRGlydHkgPSB0cnVlXHJcbn1cclxuXHJcbnByb3RvLnNldE92ZXJsYXlEaXJ0eSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMuZGlydHkgPSB0cnVlXHJcbn1cclxuXHJcbnByb3RvLm5leHREZXB0aFZhbHVlID0gZnVuY3Rpb24oKSB7XHJcbiAgcmV0dXJuICh0aGlzLl9kZXB0aENvdW50ZXIrKykgLyA2NTUzNi4wXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGxlcnAoYSwgYiwgdCkge1xyXG4gIHZhciBzID0gMC41ICogKHQgKyAxLjApXHJcbiAgcmV0dXJuIE1hdGguZmxvb3IoKDEuMC1zKSphICsgcypiKXwwXHJcbn1cclxuXHJcbnByb3RvLmRyYXcgPSAoZnVuY3Rpb24oKSB7XHJcbnZhciBUSUNLX01BUktfQk9YID0gWzAsMCwwLDBdXHJcbnJldHVybiBmdW5jdGlvbigpIHtcclxuICB2YXIgZ2wgICAgICAgICA9IHRoaXMuZ2xcclxuICB2YXIgc2NyZWVuQm94ICA9IHRoaXMuc2NyZWVuQm94XHJcbiAgdmFyIHZpZXdQaXhlbHMgPSB0aGlzLnZpZXdCb3hcclxuICB2YXIgZGF0YUJveCAgICA9IHRoaXMuZGF0YUJveFxyXG4gIHZhciBwaXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvXHJcbiAgdmFyIGdyaWQgICAgICAgPSB0aGlzLmdyaWRcclxuICB2YXIgbGluZSAgICAgICA9IHRoaXMubGluZVxyXG4gIHZhciB0ZXh0ICAgICAgID0gdGhpcy50ZXh0XHJcbiAgdmFyIG9iamVjdHMgICAgPSB0aGlzLm9iamVjdHNcclxuXHJcbiAgdGhpcy5fZGVwdGhDb3VudGVyID0gMFxyXG5cclxuICBpZih0aGlzLnBpY2tEaXJ0eSkge1xyXG4gICAgaWYodGhpcy5fcGlja1RpbWVvdXQpIHtcclxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX3BpY2tUaW1lb3V0KVxyXG4gICAgfVxyXG4gICAgdGhpcy5waWNrRGlydHkgPSBmYWxzZVxyXG4gICAgdGhpcy5fcGlja1RpbWVvdXQgPSBzZXRUaW1lb3V0KHRoaXMuX2RyYXdQaWNrLCB0aGlzLnBpY2tEZWxheSlcclxuICB9XHJcblxyXG4gIGlmKCF0aGlzLmRpcnR5KSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcbiAgdGhpcy5kaXJ0eSA9IGZhbHNlXHJcblxyXG4gIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbClcclxuXHJcbiAgLy9UdXJuIG9uIHNjaXNzb3JcclxuICBnbC5lbmFibGUoZ2wuU0NJU1NPUl9URVNUKVxyXG5cclxuICAvL1R1cm4gb2ZmIGRlcHRoIGJ1ZmZlclxyXG4gIGdsLmRpc2FibGUoZ2wuREVQVEhfVEVTVClcclxuICBnbC5kZXB0aEZ1bmMoZ2wuTEVTUylcclxuICBnbC5kZXB0aE1hc2soZmFsc2UpXHJcblxyXG4gIC8vQ29uZmlndXJlIHByZW11bHRpcGxpZWQgYWxwaGEgYmxlbmRpbmdcclxuICBnbC5lbmFibGUoZ2wuQkxFTkQpXHJcbiAgZ2wuYmxlbmRFcXVhdGlvbihnbC5GVU5DX0FERCwgZ2wuRlVOQ19BREQpO1xyXG4gIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xyXG5cclxuICAvL0RyYXcgYm9yZGVyXHJcbiAgaWYgKHRoaXMuYm9yZGVyQ29sb3IpIHtcclxuICAgIGdsLnNjaXNzb3IoXHJcbiAgICAgIHNjcmVlbkJveFswXSxcclxuICAgICAgc2NyZWVuQm94WzFdLFxyXG4gICAgICBzY3JlZW5Cb3hbMl0tc2NyZWVuQm94WzBdLFxyXG4gICAgICBzY3JlZW5Cb3hbM10tc2NyZWVuQm94WzFdKVxyXG4gICAgdmFyIGJvcmRlckNvbG9yID0gdGhpcy5ib3JkZXJDb2xvclxyXG4gICAgZ2wuY2xlYXJDb2xvcihcclxuICAgICAgYm9yZGVyQ29sb3JbMF0qYm9yZGVyQ29sb3JbM10sXHJcbiAgICAgIGJvcmRlckNvbG9yWzFdKmJvcmRlckNvbG9yWzNdLFxyXG4gICAgICBib3JkZXJDb2xvclsyXSpib3JkZXJDb2xvclszXSxcclxuICAgICAgYm9yZGVyQ29sb3JbM10pXHJcbiAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUIHwgZ2wuREVQVEhfQlVGRkVSX0JJVClcclxuICB9XHJcblxyXG4gIC8vRHJhdyBjZW50ZXIgcGFuZVxyXG4gIGdsLnNjaXNzb3IoXHJcbiAgICB2aWV3UGl4ZWxzWzBdLFxyXG4gICAgdmlld1BpeGVsc1sxXSxcclxuICAgIHZpZXdQaXhlbHNbMl0tdmlld1BpeGVsc1swXSxcclxuICAgIHZpZXdQaXhlbHNbM10tdmlld1BpeGVsc1sxXSlcclxuICBnbC52aWV3cG9ydChcclxuICAgIHZpZXdQaXhlbHNbMF0sXHJcbiAgICB2aWV3UGl4ZWxzWzFdLFxyXG4gICAgdmlld1BpeGVsc1syXS12aWV3UGl4ZWxzWzBdLFxyXG4gICAgdmlld1BpeGVsc1szXS12aWV3UGl4ZWxzWzFdKVxyXG4gIHZhciBiYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLmJhY2tncm91bmRDb2xvclxyXG4gIGdsLmNsZWFyQ29sb3IoXHJcbiAgICBiYWNrZ3JvdW5kQ29sb3JbMF0qYmFja2dyb3VuZENvbG9yWzNdLFxyXG4gICAgYmFja2dyb3VuZENvbG9yWzFdKmJhY2tncm91bmRDb2xvclszXSxcclxuICAgIGJhY2tncm91bmRDb2xvclsyXSpiYWNrZ3JvdW5kQ29sb3JbM10sXHJcbiAgICBiYWNrZ3JvdW5kQ29sb3JbM10pXHJcbiAgZ2wuY2xlYXIoZ2wuQ09MT1JfQlVGRkVSX0JJVClcclxuXHJcbiAgLy9EcmF3IGdyaWRcclxuICBncmlkLmRyYXcoKVxyXG5cclxuICAvL0RyYXcgemVybyBsaW5lcyBzZXBhcmF0ZWx5XHJcbiAgdmFyIHplcm9MaW5lRW5hYmxlID0gdGhpcy56ZXJvTGluZUVuYWJsZVxyXG4gIHZhciB6ZXJvTGluZUNvbG9yICA9IHRoaXMuemVyb0xpbmVDb2xvclxyXG4gIHZhciB6ZXJvTGluZVdpZHRoICA9IHRoaXMuemVyb0xpbmVXaWR0aFxyXG4gIGlmKHplcm9MaW5lRW5hYmxlWzBdIHx8IHplcm9MaW5lRW5hYmxlWzFdKSB7XHJcbiAgICBsaW5lLmJpbmQoKVxyXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XHJcbiAgICAgIGlmKCF6ZXJvTGluZUVuYWJsZVtpXSB8fFxyXG4gICAgICAgICEoZGF0YUJveFtpXSA8PSAwICYmIGRhdGFCb3hbaSsyXSA+PSAwKSkge1xyXG4gICAgICAgIGNvbnRpbnVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHZhciB6ZXJvSW50ZXJjZXB0ID0gc2NyZWVuQm94W2ldIC1cclxuICAgICAgICBkYXRhQm94W2ldICogKHNjcmVlbkJveFtpKzJdIC0gc2NyZWVuQm94W2ldKSAvIChkYXRhQm94W2krMl0gLSBkYXRhQm94W2ldKVxyXG5cclxuICAgICAgaWYoaSA9PT0gMCkge1xyXG4gICAgICAgIGxpbmUuZHJhd0xpbmUoXHJcbiAgICAgICAgICB6ZXJvSW50ZXJjZXB0LCBzY3JlZW5Cb3hbMV0sIHplcm9JbnRlcmNlcHQsIHNjcmVlbkJveFszXSxcclxuICAgICAgICAgIHplcm9MaW5lV2lkdGhbaV0sXHJcbiAgICAgICAgICB6ZXJvTGluZUNvbG9yW2ldKVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGxpbmUuZHJhd0xpbmUoXHJcbiAgICAgICAgICBzY3JlZW5Cb3hbMF0sIHplcm9JbnRlcmNlcHQsIHNjcmVlbkJveFsyXSwgemVyb0ludGVyY2VwdCxcclxuICAgICAgICAgIHplcm9MaW5lV2lkdGhbaV0sXHJcbiAgICAgICAgICB6ZXJvTGluZUNvbG9yW2ldKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL0RyYXcgdHJhY2VzXHJcbiAgZm9yKHZhciBpPTA7IGk8b2JqZWN0cy5sZW5ndGg7ICsraSkge1xyXG4gICAgb2JqZWN0c1tpXS5kcmF3KClcclxuICB9XHJcblxyXG4gIC8vUmV0dXJuIHZpZXdwb3J0IHRvIGRlZmF1bHRcclxuICBnbC52aWV3cG9ydChcclxuICAgIHNjcmVlbkJveFswXSxcclxuICAgIHNjcmVlbkJveFsxXSxcclxuICAgIHNjcmVlbkJveFsyXS1zY3JlZW5Cb3hbMF0sXHJcbiAgICBzY3JlZW5Cb3hbM10tc2NyZWVuQm94WzFdKVxyXG4gIGdsLnNjaXNzb3IoXHJcbiAgICBzY3JlZW5Cb3hbMF0sXHJcbiAgICBzY3JlZW5Cb3hbMV0sXHJcbiAgICBzY3JlZW5Cb3hbMl0tc2NyZWVuQm94WzBdLFxyXG4gICAgc2NyZWVuQm94WzNdLXNjcmVlbkJveFsxXSlcclxuXHJcbiAgLy9EcmF3IHRpY2sgbWFya3NcclxuICB0aGlzLmdyaWQuZHJhd1RpY2tNYXJrcygpXHJcblxyXG4gIC8vRHJhdyBsaW5lIGVsZW1lbnRzXHJcbiAgbGluZS5iaW5kKClcclxuXHJcbiAgLy9EcmF3IGJvcmRlciBsaW5lc1xyXG4gIHZhciBib3JkZXJMaW5lRW5hYmxlID0gdGhpcy5ib3JkZXJMaW5lRW5hYmxlXHJcbiAgdmFyIGJvcmRlckxpbmVXaWR0aCAgPSB0aGlzLmJvcmRlckxpbmVXaWR0aFxyXG4gIHZhciBib3JkZXJMaW5lQ29sb3IgID0gdGhpcy5ib3JkZXJMaW5lQ29sb3JcclxuICBpZihib3JkZXJMaW5lRW5hYmxlWzFdKSB7XHJcbiAgICBsaW5lLmRyYXdMaW5lKFxyXG4gICAgICB2aWV3UGl4ZWxzWzBdLCB2aWV3UGl4ZWxzWzFdIC0gMC41KmJvcmRlckxpbmVXaWR0aFsxXSpwaXhlbFJhdGlvLFxyXG4gICAgICB2aWV3UGl4ZWxzWzBdLCB2aWV3UGl4ZWxzWzNdICsgMC41KmJvcmRlckxpbmVXaWR0aFszXSpwaXhlbFJhdGlvLFxyXG4gICAgICBib3JkZXJMaW5lV2lkdGhbMV0sIGJvcmRlckxpbmVDb2xvclsxXSlcclxuICB9XHJcbiAgaWYoYm9yZGVyTGluZUVuYWJsZVswXSkge1xyXG4gICAgbGluZS5kcmF3TGluZShcclxuICAgICAgdmlld1BpeGVsc1swXSAtIDAuNSpib3JkZXJMaW5lV2lkdGhbMF0qcGl4ZWxSYXRpbywgdmlld1BpeGVsc1sxXSxcclxuICAgICAgdmlld1BpeGVsc1syXSArIDAuNSpib3JkZXJMaW5lV2lkdGhbMl0qcGl4ZWxSYXRpbywgdmlld1BpeGVsc1sxXSxcclxuICAgICAgYm9yZGVyTGluZVdpZHRoWzBdLCBib3JkZXJMaW5lQ29sb3JbMF0pXHJcbiAgfVxyXG4gIGlmKGJvcmRlckxpbmVFbmFibGVbM10pIHtcclxuICAgIGxpbmUuZHJhd0xpbmUoXHJcbiAgICAgIHZpZXdQaXhlbHNbMl0sIHZpZXdQaXhlbHNbMV0gLSAwLjUqYm9yZGVyTGluZVdpZHRoWzFdKnBpeGVsUmF0aW8sXHJcbiAgICAgIHZpZXdQaXhlbHNbMl0sIHZpZXdQaXhlbHNbM10gKyAwLjUqYm9yZGVyTGluZVdpZHRoWzNdKnBpeGVsUmF0aW8sXHJcbiAgICAgIGJvcmRlckxpbmVXaWR0aFszXSwgYm9yZGVyTGluZUNvbG9yWzNdKVxyXG4gIH1cclxuICBpZihib3JkZXJMaW5lRW5hYmxlWzJdKSB7XHJcbiAgICBsaW5lLmRyYXdMaW5lKFxyXG4gICAgICB2aWV3UGl4ZWxzWzBdIC0gMC41KmJvcmRlckxpbmVXaWR0aFswXSpwaXhlbFJhdGlvLCB2aWV3UGl4ZWxzWzNdLFxyXG4gICAgICB2aWV3UGl4ZWxzWzJdICsgMC41KmJvcmRlckxpbmVXaWR0aFsyXSpwaXhlbFJhdGlvLCB2aWV3UGl4ZWxzWzNdLFxyXG4gICAgICBib3JkZXJMaW5lV2lkdGhbMl0sIGJvcmRlckxpbmVDb2xvclsyXSlcclxuICB9XHJcblxyXG4gIC8vRHJhdyB0ZXh0IGVsZW1lbnRzXHJcbiAgdGV4dC5iaW5kKClcclxuICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcclxuICAgIHRleHQuZHJhd1RpY2tzKGkpXHJcbiAgfVxyXG4gIGlmKHRoaXMudGl0bGVFbmFibGUpIHtcclxuICAgIHRleHQuZHJhd1RpdGxlKClcclxuICB9XHJcblxyXG4gIC8vRHJhdyBvdGhlciBvdmVybGF5IGVsZW1lbnRzIChzZWxlY3QgYm94ZXMsIGV0Yy4pXHJcbiAgdmFyIG92ZXJsYXlzID0gdGhpcy5vdmVybGF5c1xyXG4gIGZvcih2YXIgaT0wOyBpPG92ZXJsYXlzLmxlbmd0aDsgKytpKSB7XHJcbiAgICBvdmVybGF5c1tpXS5kcmF3KClcclxuICB9XHJcblxyXG4gIC8vVHVybiBvZmYgc2Npc3NvciB0ZXN0XHJcbiAgZ2wuZGlzYWJsZShnbC5TQ0lTU09SX1RFU1QpXHJcbiAgZ2wuZGlzYWJsZShnbC5CTEVORClcclxuICBnbC5kZXB0aE1hc2sodHJ1ZSlcclxufVxyXG59KSgpXHJcblxyXG5wcm90by5kcmF3UGljayA9IChmdW5jdGlvbigpIHtcclxuXHJcbnJldHVybiBmdW5jdGlvbigpIHtcclxuICBpZiAodGhpcy5zdGF0aWMpIHJldHVybjtcclxuXHJcbiAgdmFyIHBpY2tCdWZmZXIgPSB0aGlzLnBpY2tCdWZmZXJcclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcblxyXG4gIHRoaXMuX3BpY2tUaW1lb3V0ID0gbnVsbFxyXG4gIHBpY2tCdWZmZXIuYmVnaW4oKVxyXG5cclxuICB2YXIgcGlja09mZnNldCA9IDFcclxuICB2YXIgb2JqZWN0cyA9IHRoaXMub2JqZWN0c1xyXG4gIGZvcih2YXIgaT0wOyBpPG9iamVjdHMubGVuZ3RoOyArK2kpIHtcclxuICAgIHBpY2tPZmZzZXQgPSBvYmplY3RzW2ldLmRyYXdQaWNrKHBpY2tPZmZzZXQpXHJcbiAgfVxyXG5cclxuICBwaWNrQnVmZmVyLmVuZCgpXHJcbn1cclxufSkoKVxyXG5cclxucHJvdG8ucGljayA9IChmdW5jdGlvbigpIHtcclxucmV0dXJuIGZ1bmN0aW9uKHgsIHkpIHtcclxuICBpZiAodGhpcy5zdGF0aWMpIHJldHVybjtcclxuXHJcbiAgdmFyIHBpeGVsUmF0aW8gICAgID0gdGhpcy5waXhlbFJhdGlvXHJcbiAgdmFyIHBpY2tQaXhlbFJhdGlvID0gdGhpcy5waWNrUGl4ZWxSYXRpb1xyXG4gIHZhciB2aWV3Qm94ICAgICAgICA9IHRoaXMudmlld0JveFxyXG5cclxuICB2YXIgc2NyWCA9IE1hdGgucm91bmQoKHggLSB2aWV3Qm94WzBdIC8gcGl4ZWxSYXRpbykgKiBwaWNrUGl4ZWxSYXRpbyl8MFxyXG4gIHZhciBzY3JZID0gTWF0aC5yb3VuZCgoeSAtIHZpZXdCb3hbMV0gLyBwaXhlbFJhdGlvKSAqIHBpY2tQaXhlbFJhdGlvKXwwXHJcblxyXG4gIHZhciBwaWNrUmVzdWx0ID0gdGhpcy5waWNrQnVmZmVyLnF1ZXJ5KHNjclgsIHNjclksIHRoaXMucGlja1JhZGl1cylcclxuICBpZighcGlja1Jlc3VsdCkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcblxyXG4gIHZhciBwaWNrVmFsdWUgPSBwaWNrUmVzdWx0LmlkICtcclxuICAgIChwaWNrUmVzdWx0LnZhbHVlWzBdPDw4KSAgK1xyXG4gICAgKHBpY2tSZXN1bHQudmFsdWVbMV08PDE2KSArXHJcbiAgICAocGlja1Jlc3VsdC52YWx1ZVsyXTw8MjQpXHJcblxyXG4gIHZhciBvYmplY3RzID0gdGhpcy5vYmplY3RzXHJcbiAgZm9yKHZhciBpPTA7IGk8b2JqZWN0cy5sZW5ndGg7ICsraSkge1xyXG4gICAgdmFyIHJlc3VsdCA9IG9iamVjdHNbaV0ucGljayhzY3JYLCBzY3JZLCBwaWNrVmFsdWUpXHJcbiAgICBpZihyZXN1bHQpIHtcclxuICAgICAgcmV0dXJuIHJlc3VsdFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG51bGxcclxufVxyXG59KSgpXHJcblxyXG5mdW5jdGlvbiBkZWVwQ2xvbmUoYXJyYXkpIHtcclxuICB2YXIgcmVzdWx0ID0gYXJyYXkuc2xpY2UoKVxyXG4gIGZvcih2YXIgaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkge1xyXG4gICAgcmVzdWx0W2ldID0gcmVzdWx0W2ldLnNsaWNlKClcclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5mdW5jdGlvbiBjb21wYXJlVGlja3MoYSwgYikge1xyXG4gIHJldHVybiBhLnggLSBiLnhcclxufVxyXG5cclxucHJvdG8uc2V0U2NyZWVuQm94ID0gZnVuY3Rpb24obmJveCkge1xyXG4gIHZhciBzY3JlZW5Cb3ggPSB0aGlzLnNjcmVlbkJveFxyXG4gIHZhciBwaXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvXHJcblxyXG4gIHNjcmVlbkJveFswXSA9IE1hdGgucm91bmQobmJveFswXSAqIHBpeGVsUmF0aW8pIHwgMFxyXG4gIHNjcmVlbkJveFsxXSA9IE1hdGgucm91bmQobmJveFsxXSAqIHBpeGVsUmF0aW8pIHwgMFxyXG4gIHNjcmVlbkJveFsyXSA9IE1hdGgucm91bmQobmJveFsyXSAqIHBpeGVsUmF0aW8pIHwgMFxyXG4gIHNjcmVlbkJveFszXSA9IE1hdGgucm91bmQobmJveFszXSAqIHBpeGVsUmF0aW8pIHwgMFxyXG5cclxuICB0aGlzLnNldERpcnR5KClcclxufVxyXG5cclxucHJvdG8uc2V0RGF0YUJveCA9IGZ1bmN0aW9uKG5ib3gpIHtcclxuICB2YXIgZGF0YUJveCA9IHRoaXMuZGF0YUJveFxyXG5cclxuICB2YXIgZGlmZmVyZW50ID1cclxuICAgIGRhdGFCb3hbMF0gIT09IG5ib3hbMF0gfHxcclxuICAgIGRhdGFCb3hbMV0gIT09IG5ib3hbMV0gfHxcclxuICAgIGRhdGFCb3hbMl0gIT09IG5ib3hbMl0gfHxcclxuICAgIGRhdGFCb3hbM10gIT09IG5ib3hbM11cclxuXHJcbiAgaWYoZGlmZmVyZW50KSB7XHJcbiAgICBkYXRhQm94WzBdID0gbmJveFswXVxyXG4gICAgZGF0YUJveFsxXSA9IG5ib3hbMV1cclxuICAgIGRhdGFCb3hbMl0gPSBuYm94WzJdXHJcbiAgICBkYXRhQm94WzNdID0gbmJveFszXVxyXG5cclxuICAgIHRoaXMuc2V0RGlydHkoKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8uc2V0Vmlld0JveCA9IGZ1bmN0aW9uKG5ib3gpIHtcclxuICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMucGl4ZWxSYXRpb1xyXG4gIHZhciB2aWV3Qm94ID0gdGhpcy52aWV3Qm94XHJcblxyXG4gIHZpZXdCb3hbMF0gPSBNYXRoLnJvdW5kKG5ib3hbMF0gKiBwaXhlbFJhdGlvKXwwXHJcbiAgdmlld0JveFsxXSA9IE1hdGgucm91bmQobmJveFsxXSAqIHBpeGVsUmF0aW8pfDBcclxuICB2aWV3Qm94WzJdID0gTWF0aC5yb3VuZChuYm94WzJdICogcGl4ZWxSYXRpbyl8MFxyXG4gIHZpZXdCb3hbM10gPSBNYXRoLnJvdW5kKG5ib3hbM10gKiBwaXhlbFJhdGlvKXwwXHJcblxyXG4gIHZhciBwaWNrUGl4ZWxSYXRpbyA9IHRoaXMucGlja1BpeGVsUmF0aW9cclxuICB0aGlzLnBpY2tCdWZmZXIuc2hhcGUgPSBbXHJcbiAgICBNYXRoLnJvdW5kKChuYm94WzJdIC0gbmJveFswXSkgKiBwaWNrUGl4ZWxSYXRpbyl8MCxcclxuICAgIE1hdGgucm91bmQoKG5ib3hbM10gLSBuYm94WzFdKSAqIHBpY2tQaXhlbFJhdGlvKXwwIF1cclxuXHJcbiAgdGhpcy5zZXREaXJ0eSgpXHJcbn1cclxuXHJcbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcclxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxyXG5cclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcblxyXG4gIHRoaXMucGl4ZWxSYXRpbyAgICAgID0gb3B0aW9ucy5waXhlbFJhdGlvIHx8IDFcclxuXHJcbiAgdmFyIHBpeGVsUmF0aW8gICAgICAgPSB0aGlzLnBpeGVsUmF0aW9cclxuICB0aGlzLnBpY2tQaXhlbFJhdGlvICA9IE1hdGgubWF4KHBpeGVsUmF0aW8sIDEpXHJcblxyXG4gIHRoaXMuc2V0U2NyZWVuQm94KG9wdGlvbnMuc2NyZWVuQm94IHx8XHJcbiAgICBbMCwgMCwgZ2wuZHJhd2luZ0J1ZmZlcldpZHRoL3BpeGVsUmF0aW8sIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQvcGl4ZWxSYXRpb10pXHJcblxyXG4gIHZhciBzY3JlZW5Cb3ggPSB0aGlzLnNjcmVlbkJveFxyXG4gIHRoaXMuc2V0Vmlld0JveChvcHRpb25zLnZpZXdCb3ggfHxcclxuICAgIFswLjEyNSoodGhpcy5zY3JlZW5Cb3hbMl0tdGhpcy5zY3JlZW5Cb3hbMF0pL3BpeGVsUmF0aW8sXHJcbiAgICAgMC4xMjUqKHRoaXMuc2NyZWVuQm94WzNdLXRoaXMuc2NyZWVuQm94WzFdKS9waXhlbFJhdGlvLFxyXG4gICAgIDAuODc1Kih0aGlzLnNjcmVlbkJveFsyXS10aGlzLnNjcmVlbkJveFswXSkvcGl4ZWxSYXRpbyxcclxuICAgICAwLjg3NSoodGhpcy5zY3JlZW5Cb3hbM10tdGhpcy5zY3JlZW5Cb3hbMV0pL3BpeGVsUmF0aW9dKVxyXG5cclxuICB2YXIgdmlld0JveCA9IHRoaXMudmlld0JveFxyXG4gIHZhciBhc3BlY3RSYXRpbyA9ICh2aWV3Qm94WzJdIC0gdmlld0JveFswXSkgLyAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pXHJcbiAgdGhpcy5zZXREYXRhQm94KG9wdGlvbnMuZGF0YUJveCB8fCBbLTEwLCAtMTAvYXNwZWN0UmF0aW8sIDEwLCAxMC9hc3BlY3RSYXRpb10pXHJcblxyXG4gIHRoaXMuYm9yZGVyQ29sb3IgICAgID0gb3B0aW9ucy5ib3JkZXJDb2xvciAhPT0gZmFsc2UgPyAob3B0aW9ucy5ib3JkZXJDb2xvciB8fCBbMCwwLDAsMF0pLnNsaWNlKCkgOiBmYWxzZVxyXG4gIHRoaXMuYmFja2dyb3VuZENvbG9yID0gKG9wdGlvbnMuYmFja2dyb3VuZENvbG9yIHx8IFswLDAsMCwwXSkuc2xpY2UoKVxyXG5cclxuICB0aGlzLmdyaWRMaW5lRW5hYmxlICA9IChvcHRpb25zLmdyaWRMaW5lRW5hYmxlIHx8IFt0cnVlLHRydWVdKS5zbGljZSgpXHJcbiAgdGhpcy5ncmlkTGluZVdpZHRoICAgPSAob3B0aW9ucy5ncmlkTGluZVdpZHRoIHx8IFsxLDFdKS5zbGljZSgpXHJcbiAgdGhpcy5ncmlkTGluZUNvbG9yICAgPSBkZWVwQ2xvbmUob3B0aW9ucy5ncmlkTGluZUNvbG9yIHx8XHJcbiAgICBbWzAuNSwwLjUsMC41LDFdLFswLjUsMC41LDAuNSwxXV0pXHJcblxyXG4gIHRoaXMuemVyb0xpbmVFbmFibGUgICA9IChvcHRpb25zLnplcm9MaW5lRW5hYmxlIHx8IFt0cnVlLCB0cnVlXSkuc2xpY2UoKVxyXG4gIHRoaXMuemVyb0xpbmVXaWR0aCAgICA9IChvcHRpb25zLnplcm9MaW5lV2lkdGggfHwgWzQsIDRdKS5zbGljZSgpXHJcbiAgdGhpcy56ZXJvTGluZUNvbG9yICAgID0gZGVlcENsb25lKG9wdGlvbnMuemVyb0xpbmVDb2xvciB8fFxyXG4gICAgW1swLCAwLCAwLCAxXSxbMCwgMCwgMCwgMV1dKVxyXG5cclxuICB0aGlzLnRpY2tNYXJrTGVuZ3RoICAgPSAob3B0aW9ucy50aWNrTWFya0xlbmd0aCB8fCBbMCwwLDAsMF0pLnNsaWNlKClcclxuICB0aGlzLnRpY2tNYXJrV2lkdGggICAgPSAob3B0aW9ucy50aWNrTWFya1dpZHRoIHx8IFswLDAsMCwwXSkuc2xpY2UoKVxyXG4gIHRoaXMudGlja01hcmtDb2xvciAgICA9IGRlZXBDbG9uZShvcHRpb25zLnRpY2tNYXJrQ29sb3IgfHxcclxuICAgIFtbMCwwLDAsMV0sWzAsMCwwLDFdLFswLDAsMCwxXSxbMCwwLDAsMV1dKVxyXG5cclxuICB0aGlzLnRpdGxlQ2VudGVyICAgICAgPSAob3B0aW9ucy50aXRsZUNlbnRlciB8fCBbXHJcbiAgICAwLjUqKHZpZXdCb3hbMF0rdmlld0JveFsyXSkvcGl4ZWxSYXRpbywodmlld0JveFszXSsxMjApL3BpeGVsUmF0aW9dKS5zbGljZSgpXHJcbiAgdGhpcy50aXRsZUVuYWJsZSAgICAgID0gISgndGl0bGVFbmFibGUnIGluIG9wdGlvbnMpIHx8ICEhb3B0aW9ucy50aXRsZUVuYWJsZVxyXG4gIHRoaXMudGl0bGVBbmdsZSAgICAgICA9IG9wdGlvbnMudGl0bGVBbmdsZSB8fCAwXHJcbiAgdGhpcy50aXRsZUNvbG9yICAgICAgID0gKG9wdGlvbnMudGl0bGVDb2xvciB8fCBbMCwwLDAsMV0pLnNsaWNlKClcclxuXHJcbiAgdGhpcy5sYWJlbFBhZCAgICAgICAgID0gKG9wdGlvbnMubGFiZWxQYWQgfHwgWzE1LDE1LDE1LDE1XSkuc2xpY2UoKVxyXG4gIHRoaXMubGFiZWxBbmdsZSAgICAgICA9IChvcHRpb25zLmxhYmVsQW5nbGUgfHxcclxuICAgIFswLE1hdGguUEkvMiwwLDMuMCpNYXRoLlBJLzJdKS5zbGljZSgpXHJcbiAgdGhpcy5sYWJlbEVuYWJsZSAgICAgID0gKG9wdGlvbnMubGFiZWxFbmFibGUgfHwgW3RydWUsdHJ1ZSx0cnVlLHRydWVdKS5zbGljZSgpXHJcbiAgdGhpcy5sYWJlbENvbG9yICAgICAgID0gZGVlcENsb25lKG9wdGlvbnMubGFiZWxDb2xvciB8fFxyXG4gICAgW1swLDAsMCwxXSxbMCwwLDAsMV0sWzAsMCwwLDFdLFswLDAsMCwxXV0pXHJcblxyXG4gIHRoaXMudGlja1BhZCAgICAgICAgID0gKG9wdGlvbnMudGlja1BhZCB8fCBbMTUsMTUsMTUsMTVdKS5zbGljZSgpXHJcbiAgdGhpcy50aWNrQW5nbGUgICAgICAgPSAob3B0aW9ucy50aWNrQW5nbGUgfHwgWzAsMCwwLDBdKS5zbGljZSgpXHJcbiAgdGhpcy50aWNrRW5hYmxlICAgICAgPSAob3B0aW9ucy50aWNrRW5hYmxlIHx8IFt0cnVlLHRydWUsdHJ1ZSx0cnVlXSkuc2xpY2UoKVxyXG4gIHRoaXMudGlja0NvbG9yICAgICAgID0gZGVlcENsb25lKG9wdGlvbnMudGlja0NvbG9yIHx8XHJcbiAgICBbWzAsMCwwLDFdLFswLDAsMCwxXSxbMCwwLDAsMV0sWzAsMCwwLDFdXSlcclxuXHJcbiAgdGhpcy5ib3JkZXJMaW5lRW5hYmxlID0gKG9wdGlvbnMuYm9yZGVyTGluZUVuYWJsZSB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RydWUsdHJ1ZSx0cnVlLHRydWVdKS5zbGljZSgpXHJcbiAgdGhpcy5ib3JkZXJMaW5lV2lkdGggID0gKG9wdGlvbnMuYm9yZGVyTGluZVdpZHRoIHx8IFsyLDIsMiwyXSkuc2xpY2UoKVxyXG4gIHRoaXMuYm9yZGVyTGluZUNvbG9yICA9IGRlZXBDbG9uZShvcHRpb25zLmJvcmRlckxpbmVDb2xvciB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtbMCwwLDAsMV0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV1dKVxyXG5cclxuICB2YXIgdGlja3MgPSBvcHRpb25zLnRpY2tzIHx8IFsgW10sIFtdIF1cclxuXHJcbiAgLy9Db21wdXRlIGJvdW5kcyBvbiB0aWNrc1xyXG4gIHZhciBib3VuZHMgPSB0aGlzLl90aWNrQm91bmRzXHJcbiAgYm91bmRzWzBdID0gYm91bmRzWzFdID0gIEluZmluaXR5XHJcbiAgYm91bmRzWzJdID0gYm91bmRzWzNdID0gLUluZmluaXR5XHJcbiAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XHJcbiAgICB2YXIgYXhpc1RpY2tzID0gdGlja3NbaV0uc2xpY2UoMClcclxuICAgIGlmKGF4aXNUaWNrcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgY29udGludWVcclxuICAgIH1cclxuICAgIGF4aXNUaWNrcy5zb3J0KGNvbXBhcmVUaWNrcylcclxuICAgIGJvdW5kc1tpXSAgID0gTWF0aC5taW4oYm91bmRzW2ldLCBheGlzVGlja3NbMF0ueClcclxuICAgIGJvdW5kc1tpKzJdID0gTWF0aC5tYXgoYm91bmRzW2krMl0sIGF4aXNUaWNrc1theGlzVGlja3MubGVuZ3RoLTFdLngpXHJcbiAgfVxyXG5cclxuICAvL1VwZGF0ZSBncmlkXHJcbiAgdGhpcy5ncmlkLnVwZGF0ZSh7XHJcbiAgICBib3VuZHM6IGJvdW5kcyxcclxuICAgIHRpY2tzOiAgdGlja3NcclxuICB9KVxyXG5cclxuICAvL1VwZGF0ZSB0ZXh0XHJcbiAgdGhpcy50ZXh0LnVwZGF0ZSh7XHJcbiAgICBib3VuZHM6ICAgICBib3VuZHMsXHJcbiAgICB0aWNrczogICAgICB0aWNrcyxcclxuICAgIGxhYmVsczogICAgIG9wdGlvbnMubGFiZWxzICAgIHx8IFsneCcsICd5J10sXHJcbiAgICBsYWJlbFNpemU6ICBvcHRpb25zLmxhYmVsU2l6ZSB8fCBbMTIsMTJdLFxyXG4gICAgbGFiZWxGb250OiAgb3B0aW9ucy5sYWJlbEZvbnQgfHwgWydzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnXSxcclxuICAgIHRpdGxlOiAgICAgIG9wdGlvbnMudGl0bGUgICAgIHx8ICcnLFxyXG4gICAgdGl0bGVTaXplOiAgb3B0aW9ucy50aXRsZVNpemUgfHwgMTgsXHJcbiAgICB0aXRsZUZvbnQ6ICBvcHRpb25zLnRpdGxlRm9udCB8fCAnc2Fucy1zZXJpZidcclxuICB9KVxyXG5cclxuICB0aGlzLnN0YXRpYyA9ICEhb3B0aW9ucy5zdGF0aWM7XHJcblxyXG4gIHRoaXMuc2V0RGlydHkoKVxyXG59XHJcblxyXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XHJcbiAgdGhpcy5ib3guZGlzcG9zZSgpXHJcbiAgdGhpcy5ncmlkLmRpc3Bvc2UoKVxyXG4gIHRoaXMudGV4dC5kaXNwb3NlKClcclxuICB0aGlzLmxpbmUuZGlzcG9zZSgpXHJcbiAgZm9yKHZhciBpPXRoaXMub2JqZWN0cy5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XHJcbiAgICB0aGlzLm9iamVjdHNbaV0uZGlzcG9zZSgpXHJcbiAgfVxyXG4gIHRoaXMub2JqZWN0cy5sZW5ndGggPSAwXHJcbiAgZm9yKHZhciBpPXRoaXMub3ZlcmxheXMubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xyXG4gICAgdGhpcy5vdmVybGF5c1tpXS5kaXNwb3NlKClcclxuICB9XHJcbiAgdGhpcy5vdmVybGF5cy5sZW5ndGggPSAwXHJcblxyXG4gIHRoaXMuZ2wgPSBudWxsXHJcbn1cclxuXHJcbnByb3RvLmFkZE9iamVjdCA9IGZ1bmN0aW9uKG9iamVjdCkge1xyXG4gIGlmKHRoaXMub2JqZWN0cy5pbmRleE9mKG9iamVjdCkgPCAwKSB7XHJcbiAgICB0aGlzLm9iamVjdHMucHVzaChvYmplY3QpXHJcbiAgICB0aGlzLnNldERpcnR5KClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLnJlbW92ZU9iamVjdCA9IGZ1bmN0aW9uKG9iamVjdCkge1xyXG4gIHZhciBvYmplY3RzID0gdGhpcy5vYmplY3RzXHJcbiAgZm9yKHZhciBpPTA7IGk8b2JqZWN0cy5sZW5ndGg7ICsraSkge1xyXG4gICAgaWYob2JqZWN0c1tpXSA9PT0gb2JqZWN0KSB7XHJcbiAgICAgIG9iamVjdHMuc3BsaWNlKGksMSlcclxuICAgICAgdGhpcy5zZXREaXJ0eSgpXHJcbiAgICAgIGJyZWFrXHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5wcm90by5hZGRPdmVybGF5ID0gZnVuY3Rpb24ob2JqZWN0KSB7XHJcbiAgaWYodGhpcy5vdmVybGF5cy5pbmRleE9mKG9iamVjdCkgPCAwKSB7XHJcbiAgICB0aGlzLm92ZXJsYXlzLnB1c2gob2JqZWN0KVxyXG4gICAgdGhpcy5zZXRPdmVybGF5RGlydHkoKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8ucmVtb3ZlT3ZlcmxheSA9IGZ1bmN0aW9uKG9iamVjdCkge1xyXG4gIHZhciBvYmplY3RzID0gdGhpcy5vdmVybGF5c1xyXG4gIGZvcih2YXIgaT0wOyBpPG9iamVjdHMubGVuZ3RoOyArK2kpIHtcclxuICAgIGlmKG9iamVjdHNbaV0gPT09IG9iamVjdCkge1xyXG4gICAgICBvYmplY3RzLnNwbGljZShpLDEpXHJcbiAgICAgIHRoaXMuc2V0T3ZlcmxheURpcnR5KClcclxuICAgICAgYnJlYWtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUdMUGxvdDJEKG9wdGlvbnMpIHtcclxuICB2YXIgZ2wgPSBvcHRpb25zLmdsXHJcbiAgdmFyIHBpY2tCdWZmZXIgPSBjcmVhdGVQaWNrKGdsLCBbXHJcbiAgICBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdKVxyXG4gIHZhciBwbG90ID0gbmV3IEdMUGxvdDJEKGdsLCBwaWNrQnVmZmVyKVxyXG4gIHBsb3QuZ3JpZCA9IGNyZWF0ZUdyaWQocGxvdClcclxuICBwbG90LnRleHQgPSBjcmVhdGVUZXh0KHBsb3QpXHJcbiAgcGxvdC5saW5lID0gY3JlYXRlTGluZShwbG90KVxyXG4gIHBsb3QuYm94ICA9IGNyZWF0ZUJveChwbG90KVxyXG4gIHBsb3QudXBkYXRlKG9wdGlvbnMpXHJcbiAgcmV0dXJuIHBsb3RcclxufVxyXG4iLCJ2YXIgZ2xzbGlmeSAgICAgID0gcmVxdWlyZSgnZ2xzbGlmeScpXHJcbnZhciBjcmVhdGVTaGFkZXIgPSByZXF1aXJlKCdnbC1zaGFkZXInKVxyXG5cclxudmFyIHZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuYXR0cmlidXRlIHZlYzIgcG9zaXRpb247XFxudmFyeWluZyB2ZWMyIHV2O1xcbnZvaWQgbWFpbigpIHtcXG4gIHV2ID0gcG9zaXRpb247XFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zaXRpb24sIDAsIDEpO1xcbn1cIl0pXHJcbnZhciBmcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gc2FtcGxlcjJEIGFjY3VtQnVmZmVyO1xcbnZhcnlpbmcgdmVjMiB1djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICB2ZWM0IGFjY3VtID0gdGV4dHVyZTJEKGFjY3VtQnVmZmVyLCAwLjUgKiAodXYgKyAxLjApKTtcXG4gIGdsX0ZyYWdDb2xvciA9IG1pbih2ZWM0KDEsMSwxLDEpLCBhY2N1bSk7XFxufVwiXSlcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZ2wpIHtcclxuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCB2ZXJ0U3JjLCBmcmFnU3JjLCBudWxsLCBbIHsgbmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzInfV0pXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNjZW5lXHJcblxyXG52YXIgY3JlYXRlQ2FtZXJhID0gcmVxdWlyZSgnM2Qtdmlldy1jb250cm9scycpXHJcbnZhciBjcmVhdGVBeGVzICAgPSByZXF1aXJlKCdnbC1heGVzM2QnKVxyXG52YXIgYXhlc1JhbmdlcyAgID0gcmVxdWlyZSgnZ2wtYXhlczNkL3Byb3BlcnRpZXMnKVxyXG52YXIgY3JlYXRlU3Bpa2VzID0gcmVxdWlyZSgnZ2wtc3Bpa2VzM2QnKVxyXG52YXIgY3JlYXRlU2VsZWN0ID0gcmVxdWlyZSgnZ2wtc2VsZWN0LXN0YXRpYycpXHJcbnZhciBjcmVhdGVGQk8gICAgPSByZXF1aXJlKCdnbC1mYm8nKVxyXG52YXIgZHJhd1RyaWFuZ2xlID0gcmVxdWlyZSgnYS1iaWctdHJpYW5nbGUnKVxyXG52YXIgbW91c2VDaGFuZ2UgID0gcmVxdWlyZSgnbW91c2UtY2hhbmdlJylcclxudmFyIHBlcnNwZWN0aXZlICA9IHJlcXVpcmUoJ2dsLW1hdDQvcGVyc3BlY3RpdmUnKVxyXG52YXIgY3JlYXRlU2hhZGVyID0gcmVxdWlyZSgnLi9saWIvc2hhZGVyJylcclxudmFyIGlzTW9iaWxlID0gcmVxdWlyZSgnaXMtbW9iaWxlJykoeyB0YWJsZXQ6IHRydWUgfSlcclxuXHJcbmZ1bmN0aW9uIE1vdXNlU2VsZWN0KCkge1xyXG4gIHRoaXMubW91c2UgICAgICAgICAgPSBbLTEsLTFdXHJcbiAgdGhpcy5zY3JlZW4gICAgICAgICA9IG51bGxcclxuICB0aGlzLmRpc3RhbmNlICAgICAgID0gSW5maW5pdHlcclxuICB0aGlzLmluZGV4ICAgICAgICAgID0gbnVsbFxyXG4gIHRoaXMuZGF0YUNvb3JkaW5hdGUgPSBudWxsXHJcbiAgdGhpcy5kYXRhUG9zaXRpb24gICA9IG51bGxcclxuICB0aGlzLm9iamVjdCAgICAgICAgID0gbnVsbFxyXG4gIHRoaXMuZGF0YSAgICAgICAgICAgPSBudWxsXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldENvbnRleHQoY2FudmFzLCBvcHRpb25zKSB7XHJcbiAgdmFyIGdsID0gbnVsbFxyXG4gIHRyeSB7XHJcbiAgICBnbCA9IGNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcsIG9wdGlvbnMpXHJcbiAgICBpZighZ2wpIHtcclxuICAgICAgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgb3B0aW9ucylcclxuICAgIH1cclxuICB9IGNhdGNoKGUpIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG4gIHJldHVybiBnbFxyXG59XHJcblxyXG5mdW5jdGlvbiByb3VuZFVwUG93MTAoeCkge1xyXG4gIHZhciB5ID0gTWF0aC5yb3VuZChNYXRoLmxvZyhNYXRoLmFicyh4KSkgLyBNYXRoLmxvZygxMCkpXHJcbiAgaWYoeSA8IDApIHtcclxuICAgIHZhciBiYXNlID0gTWF0aC5yb3VuZChNYXRoLnBvdygxMCwgLXkpKVxyXG4gICAgcmV0dXJuIE1hdGguY2VpbCh4KmJhc2UpIC8gYmFzZVxyXG4gIH0gZWxzZSBpZih5ID4gMCkge1xyXG4gICAgdmFyIGJhc2UgPSBNYXRoLnJvdW5kKE1hdGgucG93KDEwLCB5KSlcclxuICAgIHJldHVybiBNYXRoLmNlaWwoeC9iYXNlKSAqIGJhc2VcclxuICB9XHJcbiAgcmV0dXJuIE1hdGguY2VpbCh4KVxyXG59XHJcblxyXG5mdW5jdGlvbiBkZWZhdWx0Qm9vbCh4KSB7XHJcbiAgaWYodHlwZW9mIHggPT09ICdib29sZWFuJykge1xyXG4gICAgcmV0dXJuIHhcclxuICB9XHJcbiAgcmV0dXJuIHRydWVcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlU2NlbmUob3B0aW9ucykge1xyXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XHJcblxyXG4gIHZhciBzdG9wcGVkID0gZmFsc2VcclxuXHJcbiAgdmFyIHBpeGVsUmF0aW8gPSBvcHRpb25zLnBpeGVsUmF0aW8gfHwgcGFyc2VGbG9hdCh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbylcclxuXHJcbiAgdmFyIGNhbnZhcyA9IG9wdGlvbnMuY2FudmFzXHJcbiAgaWYoIWNhbnZhcykge1xyXG4gICAgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcclxuICAgIGlmKG9wdGlvbnMuY29udGFpbmVyKSB7XHJcbiAgICAgIHZhciBjb250YWluZXIgPSBvcHRpb25zLmNvbnRhaW5lclxyXG4gICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoY2FudmFzKVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjYW52YXMpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgZ2wgPSBvcHRpb25zLmdsXHJcbiAgaWYoIWdsKSB7XHJcbiAgICBnbCA9IGdldENvbnRleHQoY2FudmFzLFxyXG4gICAgICBvcHRpb25zLmdsT3B0aW9ucyB8fCB7XHJcbiAgICAgICAgcHJlbXVsdGlwbGllZEFscGhhOiB0cnVlLFxyXG4gICAgICAgIGFudGlhbGlhczogdHJ1ZSxcclxuICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IGlzTW9iaWxlXHJcbiAgICAgIH0pXHJcbiAgfVxyXG4gIGlmKCFnbCkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCd3ZWJnbCBub3Qgc3VwcG9ydGVkJylcclxuICB9XHJcblxyXG4gIC8vSW5pdGlhbCBib3VuZHNcclxuICB2YXIgYm91bmRzID0gb3B0aW9ucy5ib3VuZHMgfHwgW1stMTAsLTEwLC0xMF0sIFsxMCwxMCwxMF1dXHJcblxyXG4gIC8vQ3JlYXRlIHNlbGVjdGlvblxyXG4gIHZhciBzZWxlY3Rpb24gPSBuZXcgTW91c2VTZWxlY3QoKVxyXG5cclxuICAvL0FjY3VtdWxhdGlvbiBidWZmZXJcclxuICB2YXIgYWNjdW1CdWZmZXIgPSBjcmVhdGVGQk8oZ2wsXHJcbiAgICBbZ2wuZHJhd2luZ0J1ZmZlcldpZHRoLCBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XSwge1xyXG4gICAgICBwcmVmZXJGbG9hdDogIWlzTW9iaWxlXHJcbiAgICB9KVxyXG5cclxuICB2YXIgYWNjdW1TaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wpXHJcblxyXG4gIC8vQ3JlYXRlIGEgY2FtZXJhXHJcbiAgdmFyIGNhbWVyYU9wdGlvbnMgPSBvcHRpb25zLmNhbWVyYSB8fCB7XHJcbiAgICBleWU6ICAgIFsyLDAsMF0sXHJcbiAgICBjZW50ZXI6IFswLDAsMF0sXHJcbiAgICB1cDogICAgIFswLDEsMF0sXHJcbiAgICB6b29tTWluOiAwLjEsXHJcbiAgICB6b29tTWF4OiAxMDAsXHJcbiAgICBtb2RlOiAgICAndHVybnRhYmxlJ1xyXG4gIH1cclxuXHJcbiAgLy9DcmVhdGUgYXhlc1xyXG4gIHZhciBheGVzT3B0aW9ucyA9IG9wdGlvbnMuYXhlcyB8fCB7fVxyXG4gIHZhciBheGVzID0gY3JlYXRlQXhlcyhnbCwgYXhlc09wdGlvbnMpXHJcbiAgYXhlcy5lbmFibGUgPSAhYXhlc09wdGlvbnMuZGlzYWJsZVxyXG5cclxuICAvL0NyZWF0ZSBzcGlrZXNcclxuICB2YXIgc3Bpa2VPcHRpb25zID0gb3B0aW9ucy5zcGlrZXMgfHwge31cclxuICB2YXIgc3Bpa2VzID0gY3JlYXRlU3Bpa2VzKGdsLCBzcGlrZU9wdGlvbnMpXHJcblxyXG4gIC8vT2JqZWN0IGxpc3QgaXMgZW1wdHkgaW5pdGlhbGx5XHJcbiAgdmFyIG9iamVjdHMgICAgICAgICA9IFtdXHJcbiAgdmFyIHBpY2tCdWZmZXJJZHMgICA9IFtdXHJcbiAgdmFyIHBpY2tCdWZmZXJDb3VudCA9IFtdXHJcbiAgdmFyIHBpY2tCdWZmZXJzICAgICA9IFtdXHJcblxyXG4gIC8vRGlydHkgZmxhZywgc2tpcCByZWRyYXcgaWYgc2NlbmUgc3RhdGljXHJcbiAgdmFyIGRpcnR5ICAgICAgID0gdHJ1ZVxyXG4gIHZhciBwaWNrRGlydHkgICA9IHRydWVcclxuXHJcbiAgdmFyIHByb2plY3Rpb24gICAgID0gbmV3IEFycmF5KDE2KVxyXG4gIHZhciBtb2RlbCAgICAgICAgICA9IG5ldyBBcnJheSgxNilcclxuXHJcbiAgdmFyIGNhbWVyYVBhcmFtcyA9IHtcclxuICAgIHZpZXc6ICAgICAgICAgbnVsbCxcclxuICAgIHByb2plY3Rpb246ICAgcHJvamVjdGlvbixcclxuICAgIG1vZGVsOiAgICAgICAgbW9kZWxcclxuICB9XHJcblxyXG4gIHZhciBwaWNrRGlydHkgPSB0cnVlXHJcblxyXG4gIHZhciB2aWV3U2hhcGUgPSBbIGdsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodCBdXHJcblxyXG4gIC8vQ3JlYXRlIHNjZW5lIG9iamVjdFxyXG4gIHZhciBzY2VuZSA9IHtcclxuICAgIGdsOiAgICAgICAgICAgZ2wsXHJcbiAgICBjb250ZXh0TG9zdDogIGZhbHNlLFxyXG4gICAgcGl4ZWxSYXRpbzogICBvcHRpb25zLnBpeGVsUmF0aW8gfHwgcGFyc2VGbG9hdCh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyksXHJcbiAgICBjYW52YXM6ICAgICAgIGNhbnZhcyxcclxuICAgIHNlbGVjdGlvbjogICAgc2VsZWN0aW9uLFxyXG4gICAgY2FtZXJhOiAgICAgICBjcmVhdGVDYW1lcmEoY2FudmFzLCBjYW1lcmFPcHRpb25zKSxcclxuICAgIGF4ZXM6ICAgICAgICAgYXhlcyxcclxuICAgIGF4ZXNQaXhlbHM6ICAgbnVsbCxcclxuICAgIHNwaWtlczogICAgICAgc3Bpa2VzLFxyXG4gICAgYm91bmRzOiAgICAgICBib3VuZHMsXHJcbiAgICBvYmplY3RzOiAgICAgIG9iamVjdHMsXHJcbiAgICBzaGFwZTogICAgICAgIHZpZXdTaGFwZSxcclxuICAgIGFzcGVjdDogICAgICAgb3B0aW9ucy5hc3BlY3RSYXRpbyB8fCBbMSwxLDFdLFxyXG4gICAgcGlja1JhZGl1czogICBvcHRpb25zLnBpY2tSYWRpdXMgfHwgMTAsXHJcbiAgICB6TmVhcjogICAgICAgIG9wdGlvbnMuek5lYXIgfHwgMC4wMSxcclxuICAgIHpGYXI6ICAgICAgICAgb3B0aW9ucy56RmFyICB8fCAxMDAwLFxyXG4gICAgZm92eTogICAgICAgICBvcHRpb25zLmZvdnkgIHx8IE1hdGguUEkvNCxcclxuICAgIGNsZWFyQ29sb3I6ICAgb3B0aW9ucy5jbGVhckNvbG9yIHx8IFswLDAsMCwwXSxcclxuICAgIGF1dG9SZXNpemU6ICAgZGVmYXVsdEJvb2wob3B0aW9ucy5hdXRvUmVzaXplKSxcclxuICAgIGF1dG9Cb3VuZHM6ICAgZGVmYXVsdEJvb2wob3B0aW9ucy5hdXRvQm91bmRzKSxcclxuICAgIGF1dG9TY2FsZTogICAgISFvcHRpb25zLmF1dG9TY2FsZSxcclxuICAgIGF1dG9DZW50ZXI6ICAgZGVmYXVsdEJvb2wob3B0aW9ucy5hdXRvQ2VudGVyKSxcclxuICAgIGNsaXBUb0JvdW5kczogZGVmYXVsdEJvb2wob3B0aW9ucy5jbGlwVG9Cb3VuZHMpLFxyXG4gICAgc25hcFRvRGF0YTogICAhIW9wdGlvbnMuc25hcFRvRGF0YSxcclxuICAgIG9uc2VsZWN0OiAgICAgb3B0aW9ucy5vbnNlbGVjdCB8fCBudWxsLFxyXG4gICAgb25yZW5kZXI6ICAgICBvcHRpb25zLm9ucmVuZGVyIHx8IG51bGwsXHJcbiAgICBvbmNsaWNrOiAgICAgIG9wdGlvbnMub25jbGljayAgfHwgbnVsbCxcclxuICAgIGNhbWVyYVBhcmFtczogY2FtZXJhUGFyYW1zLFxyXG4gICAgb25jb250ZXh0bG9zczogbnVsbCxcclxuICAgIG1vdXNlTGlzdGVuZXI6IG51bGxcclxuICB9XHJcblxyXG4gIHZhciBwaWNrU2hhcGUgPSBbIChnbC5kcmF3aW5nQnVmZmVyV2lkdGgvc2NlbmUucGl4ZWxSYXRpbyl8MCwgKGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQvc2NlbmUucGl4ZWxSYXRpbyl8MCBdXHJcblxyXG4gIGZ1bmN0aW9uIHJlc2l6ZUxpc3RlbmVyKCkge1xyXG4gICAgaWYoc3RvcHBlZCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIGlmKCFzY2VuZS5hdXRvUmVzaXplKSB7XHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG4gICAgdmFyIHBhcmVudCA9IGNhbnZhcy5wYXJlbnROb2RlXHJcbiAgICB2YXIgd2lkdGggID0gMVxyXG4gICAgdmFyIGhlaWdodCA9IDFcclxuICAgIGlmKHBhcmVudCAmJiBwYXJlbnQgIT09IGRvY3VtZW50LmJvZHkpIHtcclxuICAgICAgd2lkdGggID0gcGFyZW50LmNsaWVudFdpZHRoXHJcbiAgICAgIGhlaWdodCA9IHBhcmVudC5jbGllbnRIZWlnaHRcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHdpZHRoICA9IHdpbmRvdy5pbm5lcldpZHRoXHJcbiAgICAgIGhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodFxyXG4gICAgfVxyXG4gICAgdmFyIG5leHRXaWR0aCAgPSBNYXRoLmNlaWwod2lkdGggICogc2NlbmUucGl4ZWxSYXRpbyl8MFxyXG4gICAgdmFyIG5leHRIZWlnaHQgPSBNYXRoLmNlaWwoaGVpZ2h0ICogc2NlbmUucGl4ZWxSYXRpbyl8MFxyXG4gICAgaWYobmV4dFdpZHRoICE9PSBjYW52YXMud2lkdGggfHwgbmV4dEhlaWdodCAhPT0gY2FudmFzLmhlaWdodCkge1xyXG4gICAgICBjYW52YXMud2lkdGggICA9IG5leHRXaWR0aFxyXG4gICAgICBjYW52YXMuaGVpZ2h0ICA9IG5leHRIZWlnaHRcclxuICAgICAgdmFyIHN0eWxlID0gY2FudmFzLnN0eWxlXHJcbiAgICAgIHN0eWxlLnBvc2l0aW9uID0gc3R5bGUucG9zaXRpb24gfHwgJ2Fic29sdXRlJ1xyXG4gICAgICBzdHlsZS5sZWZ0ICAgICA9ICcwcHgnXHJcbiAgICAgIHN0eWxlLnRvcCAgICAgID0gJzBweCdcclxuICAgICAgc3R5bGUud2lkdGggICAgPSB3aWR0aCAgKyAncHgnXHJcbiAgICAgIHN0eWxlLmhlaWdodCAgID0gaGVpZ2h0ICsgJ3B4J1xyXG4gICAgICBkaXJ0eSA9IHRydWVcclxuICAgIH1cclxuICB9XHJcbiAgaWYoc2NlbmUuYXV0b1Jlc2l6ZSkge1xyXG4gICAgcmVzaXplTGlzdGVuZXIoKVxyXG4gIH1cclxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplTGlzdGVuZXIpXHJcblxyXG4gIGZ1bmN0aW9uIHJlYWxsb2NQaWNrSWRzKCkge1xyXG4gICAgdmFyIG51bU9ianMgPSBvYmplY3RzLmxlbmd0aFxyXG4gICAgdmFyIG51bVBpY2sgPSBwaWNrQnVmZmVycy5sZW5ndGhcclxuICAgIGZvcih2YXIgaT0wOyBpPG51bVBpY2s7ICsraSkge1xyXG4gICAgICBwaWNrQnVmZmVyQ291bnRbaV0gPSAwXHJcbiAgICB9XHJcbiAgICBvYmpfbG9vcDpcclxuICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xyXG4gICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxyXG4gICAgICB2YXIgcGlja0NvdW50ID0gb2JqLnBpY2tTbG90c1xyXG4gICAgICBpZighcGlja0NvdW50KSB7XHJcbiAgICAgICAgcGlja0J1ZmZlcklkc1tpXSA9IC0xXHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG4gICAgICBmb3IodmFyIGo9MDsgajxudW1QaWNrOyArK2opIHtcclxuICAgICAgICBpZihwaWNrQnVmZmVyQ291bnRbal0gKyBwaWNrQ291bnQgPCAyNTUpIHtcclxuICAgICAgICAgIHBpY2tCdWZmZXJJZHNbaV0gPSBqXHJcbiAgICAgICAgICBvYmouc2V0UGlja0Jhc2UocGlja0J1ZmZlckNvdW50W2pdKzEpXHJcbiAgICAgICAgICBwaWNrQnVmZmVyQ291bnRbal0gKz0gcGlja0NvdW50XHJcbiAgICAgICAgICBjb250aW51ZSBvYmpfbG9vcFxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICAvL0NyZWF0ZSBuZXcgcGljayBidWZmZXJcclxuICAgICAgdmFyIG5idWZmZXIgPSBjcmVhdGVTZWxlY3QoZ2wsIHZpZXdTaGFwZSlcclxuICAgICAgcGlja0J1ZmZlcklkc1tpXSA9IG51bVBpY2tcclxuICAgICAgcGlja0J1ZmZlcnMucHVzaChuYnVmZmVyKVxyXG4gICAgICBwaWNrQnVmZmVyQ291bnQucHVzaChwaWNrQ291bnQpXHJcbiAgICAgIG9iai5zZXRQaWNrQmFzZSgxKVxyXG4gICAgICBudW1QaWNrICs9IDFcclxuICAgIH1cclxuICAgIHdoaWxlKG51bVBpY2sgPiAwICYmIHBpY2tCdWZmZXJDb3VudFtudW1QaWNrLTFdID09PSAwKSB7XHJcbiAgICAgIHBpY2tCdWZmZXJDb3VudC5wb3AoKVxyXG4gICAgICBwaWNrQnVmZmVycy5wb3AoKS5kaXNwb3NlKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNjZW5lLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcclxuICAgIGlmKHN0b3BwZWQpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxyXG4gICAgZGlydHkgPSB0cnVlXHJcbiAgICBwaWNrRGlydHkgPSB0cnVlXHJcbiAgfVxyXG5cclxuICBzY2VuZS5hZGQgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIGlmKHN0b3BwZWQpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcbiAgICBvYmouYXhlcyA9IGF4ZXNcclxuICAgIG9iamVjdHMucHVzaChvYmopXHJcbiAgICBwaWNrQnVmZmVySWRzLnB1c2goLTEpXHJcbiAgICBkaXJ0eSA9IHRydWVcclxuICAgIHBpY2tEaXJ0eSA9IHRydWVcclxuICAgIHJlYWxsb2NQaWNrSWRzKClcclxuICB9XHJcblxyXG4gIHNjZW5lLnJlbW92ZSA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgaWYoc3RvcHBlZCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIHZhciBpZHggPSBvYmplY3RzLmluZGV4T2Yob2JqKVxyXG4gICAgaWYoaWR4IDwgMCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIG9iamVjdHMuc3BsaWNlKGlkeCwgMSlcclxuICAgIHBpY2tCdWZmZXJJZHMucG9wKClcclxuICAgIGRpcnR5ID0gdHJ1ZVxyXG4gICAgcGlja0RpcnR5ID0gdHJ1ZVxyXG4gICAgcmVhbGxvY1BpY2tJZHMoKVxyXG4gIH1cclxuXHJcbiAgc2NlbmUuZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgaWYoc3RvcHBlZCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuXHJcbiAgICBzdG9wcGVkID0gdHJ1ZVxyXG5cclxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemVMaXN0ZW5lcilcclxuICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgY2hlY2tDb250ZXh0TG9zcylcclxuICAgIHNjZW5lLm1vdXNlTGlzdGVuZXIuZW5hYmxlZCA9IGZhbHNlXHJcblxyXG4gICAgaWYoc2NlbmUuY29udGV4dExvc3QpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcblxyXG4gICAgLy9EZXN0cm95IG9iamVjdHNcclxuICAgIGF4ZXMuZGlzcG9zZSgpXHJcbiAgICBzcGlrZXMuZGlzcG9zZSgpXHJcbiAgICBmb3IodmFyIGk9MDsgaTxvYmplY3RzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIG9iamVjdHNbaV0uZGlzcG9zZSgpXHJcbiAgICB9XHJcblxyXG4gICAgLy9DbGVhbiB1cCBidWZmZXJzXHJcbiAgICBhY2N1bUJ1ZmZlci5kaXNwb3NlKClcclxuICAgIGZvcih2YXIgaT0wOyBpPHBpY2tCdWZmZXJzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIHBpY2tCdWZmZXJzW2ldLmRpc3Bvc2UoKVxyXG4gICAgfVxyXG5cclxuICAgIC8vQ2xlYW4gdXAgc2hhZGVyc1xyXG4gICAgYWNjdW1TaGFkZXIuZGlzcG9zZSgpXHJcblxyXG4gICAgLy9SZWxlYXNlIGFsbCByZWZlcmVuY2VzXHJcbiAgICBnbCA9IG51bGxcclxuICAgIGF4ZXMgPSBudWxsXHJcbiAgICBzcGlrZXMgPSBudWxsXHJcbiAgICBvYmplY3RzID0gW11cclxuICB9XHJcblxyXG4gIC8vVXBkYXRlIG1vdXNlIHBvc2l0aW9uXHJcbiAgdmFyIG1vdXNlUm90YXRpbmcgPSBmYWxzZVxyXG5cclxuICB2YXIgcHJldkJ1dHRvbnMgPSAwXHJcblxyXG4gIHNjZW5lLm1vdXNlTGlzdGVuZXIgPSBtb3VzZUNoYW5nZShjYW52YXMsIGZ1bmN0aW9uKGJ1dHRvbnMsIHgsIHkpIHtcclxuICAgIGlmKHN0b3BwZWQpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIG51bVBpY2sgPSBwaWNrQnVmZmVycy5sZW5ndGhcclxuICAgIHZhciBudW1PYmpzID0gb2JqZWN0cy5sZW5ndGhcclxuICAgIHZhciBwcmV2T2JqID0gc2VsZWN0aW9uLm9iamVjdFxyXG5cclxuICAgIHNlbGVjdGlvbi5kaXN0YW5jZSA9IEluZmluaXR5XHJcbiAgICBzZWxlY3Rpb24ubW91c2VbMF0gPSB4XHJcbiAgICBzZWxlY3Rpb24ubW91c2VbMV0gPSB5XHJcbiAgICBzZWxlY3Rpb24ub2JqZWN0ID0gbnVsbFxyXG4gICAgc2VsZWN0aW9uLnNjcmVlbiA9IG51bGxcclxuICAgIHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZSA9IHNlbGVjdGlvbi5kYXRhUG9zaXRpb24gPSBudWxsXHJcblxyXG4gICAgdmFyIGNoYW5nZSA9IGZhbHNlXHJcblxyXG4gICAgaWYoYnV0dG9ucyAmJiBwcmV2QnV0dG9ucykge1xyXG4gICAgICBtb3VzZVJvdGF0aW5nID0gdHJ1ZVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYobW91c2VSb3RhdGluZykge1xyXG4gICAgICAgIHBpY2tEaXJ0eSA9IHRydWVcclxuICAgICAgfVxyXG4gICAgICBtb3VzZVJvdGF0aW5nID0gZmFsc2VcclxuXHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPG51bVBpY2s7ICsraSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBwaWNrQnVmZmVyc1tpXS5xdWVyeSh4LCBwaWNrU2hhcGVbMV0gLSB5IC0gMSwgc2NlbmUucGlja1JhZGl1cylcclxuICAgICAgICBpZihyZXN1bHQpIHtcclxuICAgICAgICAgIGlmKHJlc3VsdC5kaXN0YW5jZSA+IHNlbGVjdGlvbi5kaXN0YW5jZSkge1xyXG4gICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgZm9yKHZhciBqPTA7IGo8bnVtT2JqczsgKytqKSB7XHJcbiAgICAgICAgICAgIHZhciBvYmogPSBvYmplY3RzW2pdXHJcbiAgICAgICAgICAgIGlmKHBpY2tCdWZmZXJJZHNbal0gIT09IGkpIHtcclxuICAgICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZhciBvYmpQaWNrID0gb2JqLnBpY2socmVzdWx0KVxyXG4gICAgICAgICAgICBpZihvYmpQaWNrKSB7XHJcbiAgICAgICAgICAgICAgc2VsZWN0aW9uLmJ1dHRvbnMgICAgICAgID0gYnV0dG9uc1xyXG4gICAgICAgICAgICAgIHNlbGVjdGlvbi5zY3JlZW4gICAgICAgICA9IHJlc3VsdC5jb29yZFxyXG4gICAgICAgICAgICAgIHNlbGVjdGlvbi5kaXN0YW5jZSAgICAgICA9IHJlc3VsdC5kaXN0YW5jZVxyXG4gICAgICAgICAgICAgIHNlbGVjdGlvbi5vYmplY3QgICAgICAgICA9IG9ialxyXG4gICAgICAgICAgICAgIHNlbGVjdGlvbi5pbmRleCAgICAgICAgICA9IG9ialBpY2suZGlzdGFuY2VcclxuICAgICAgICAgICAgICBzZWxlY3Rpb24uZGF0YVBvc2l0aW9uICAgPSBvYmpQaWNrLnBvc2l0aW9uXHJcbiAgICAgICAgICAgICAgc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlID0gb2JqUGljay5kYXRhQ29vcmRpbmF0ZVxyXG4gICAgICAgICAgICAgIHNlbGVjdGlvbi5kYXRhICAgICAgICAgICA9IG9ialBpY2tcclxuICAgICAgICAgICAgICBjaGFuZ2UgPSB0cnVlXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZihwcmV2T2JqICYmIHByZXZPYmogIT09IHNlbGVjdGlvbi5vYmplY3QpIHtcclxuICAgICAgaWYocHJldk9iai5oaWdobGlnaHQpIHtcclxuICAgICAgICBwcmV2T2JqLmhpZ2hsaWdodChudWxsKVxyXG4gICAgICB9XHJcbiAgICAgIGRpcnR5ID0gdHJ1ZVxyXG4gICAgfVxyXG4gICAgaWYoc2VsZWN0aW9uLm9iamVjdCkge1xyXG4gICAgICBpZihzZWxlY3Rpb24ub2JqZWN0LmhpZ2hsaWdodCkge1xyXG4gICAgICAgIHNlbGVjdGlvbi5vYmplY3QuaGlnaGxpZ2h0KHNlbGVjdGlvbi5kYXRhKVxyXG4gICAgICB9XHJcbiAgICAgIGRpcnR5ID0gdHJ1ZVxyXG4gICAgfVxyXG5cclxuICAgIGNoYW5nZSA9IGNoYW5nZSB8fCAoc2VsZWN0aW9uLm9iamVjdCAhPT0gcHJldk9iailcclxuICAgIGlmKGNoYW5nZSAmJiBzY2VuZS5vbnNlbGVjdCkge1xyXG4gICAgICBzY2VuZS5vbnNlbGVjdChzZWxlY3Rpb24pXHJcbiAgICB9XHJcblxyXG4gICAgaWYoKGJ1dHRvbnMgJiAxKSAmJiAhKHByZXZCdXR0b25zICYgMSkgJiYgc2NlbmUub25jbGljaykge1xyXG4gICAgICBzY2VuZS5vbmNsaWNrKHNlbGVjdGlvbilcclxuICAgIH1cclxuICAgIHByZXZCdXR0b25zID0gYnV0dG9uc1xyXG4gIH0pXHJcblxyXG4gIGZ1bmN0aW9uIGNoZWNrQ29udGV4dExvc3MoKSB7XHJcbiAgICBpZihzY2VuZS5jb250ZXh0TG9zdCkge1xyXG4gICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgfVxyXG4gICAgaWYoZ2wuaXNDb250ZXh0TG9zdCgpKSB7XHJcbiAgICAgIHNjZW5lLmNvbnRleHRMb3N0ID0gdHJ1ZVxyXG4gICAgICBzY2VuZS5tb3VzZUxpc3RlbmVyLmVuYWJsZWQgPSBmYWxzZVxyXG4gICAgICBzY2VuZS5zZWxlY3Rpb24ub2JqZWN0ID0gbnVsbFxyXG4gICAgICBpZihzY2VuZS5vbmNvbnRleHRsb3NzKSB7XHJcbiAgICAgICAgc2NlbmUub25jb250ZXh0bG9zcygpXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgY2hlY2tDb250ZXh0TG9zcylcclxuXHJcbiAgLy9SZW5kZXIgdGhlIHNjZW5lIGZvciBtb3VzZSBwaWNraW5nXHJcbiAgZnVuY3Rpb24gcmVuZGVyUGljaygpIHtcclxuICAgIGlmKGNoZWNrQ29udGV4dExvc3MoKSkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuXHJcbiAgICBnbC5jb2xvck1hc2sodHJ1ZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZSlcclxuICAgIGdsLmRlcHRoTWFzayh0cnVlKVxyXG4gICAgZ2wuZGlzYWJsZShnbC5CTEVORClcclxuICAgIGdsLmVuYWJsZShnbC5ERVBUSF9URVNUKVxyXG5cclxuICAgIHZhciBudW1PYmpzID0gb2JqZWN0cy5sZW5ndGhcclxuICAgIHZhciBudW1QaWNrID0gcGlja0J1ZmZlcnMubGVuZ3RoXHJcbiAgICBmb3IodmFyIGo9MDsgajxudW1QaWNrOyArK2opIHtcclxuICAgICAgdmFyIGJ1ZiA9IHBpY2tCdWZmZXJzW2pdXHJcbiAgICAgIGJ1Zi5zaGFwZSA9IHBpY2tTaGFwZVxyXG4gICAgICBidWYuYmVnaW4oKVxyXG4gICAgICBmb3IodmFyIGk9MDsgaTxudW1PYmpzOyArK2kpIHtcclxuICAgICAgICBpZihwaWNrQnVmZmVySWRzW2ldICE9PSBqKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxyXG4gICAgICAgIGlmKG9iai5kcmF3UGljaykge1xyXG4gICAgICAgICAgb2JqLnBpeGVsUmF0aW8gPSAxXHJcbiAgICAgICAgICBvYmouZHJhd1BpY2soY2FtZXJhUGFyYW1zKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBidWYuZW5kKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHZhciBuQm91bmRzID0gW1xyXG4gICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSxcclxuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXHJcblxyXG4gIHZhciBwcmV2Qm91bmRzID0gW25Cb3VuZHNbMF0uc2xpY2UoKSwgbkJvdW5kc1sxXS5zbGljZSgpXVxyXG5cclxuICBmdW5jdGlvbiByZWRyYXcoKSB7XHJcbiAgICBpZihjaGVja0NvbnRleHRMb3NzKCkpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcblxyXG4gICAgcmVzaXplTGlzdGVuZXIoKVxyXG5cclxuICAgIC8vVGljayBjYW1lcmFcclxuICAgIHZhciBjYW1lcmFNb3ZlZCA9IHNjZW5lLmNhbWVyYS50aWNrKClcclxuICAgIGNhbWVyYVBhcmFtcy52aWV3ID0gc2NlbmUuY2FtZXJhLm1hdHJpeFxyXG4gICAgZGlydHkgICAgID0gZGlydHkgfHwgY2FtZXJhTW92ZWRcclxuICAgIHBpY2tEaXJ0eSA9IHBpY2tEaXJ0eSB8fCBjYW1lcmFNb3ZlZFxyXG5cclxuICAgICAgLy9TZXQgcGl4ZWwgcmF0aW9cclxuICAgIGF4ZXMucGl4ZWxSYXRpbyAgID0gc2NlbmUucGl4ZWxSYXRpb1xyXG4gICAgc3Bpa2VzLnBpeGVsUmF0aW8gPSBzY2VuZS5waXhlbFJhdGlvXHJcblxyXG4gICAgLy9DaGVjayBpZiBhbnkgb2JqZWN0cyBjaGFuZ2VkLCByZWNhbGN1bGF0ZSBib3VuZHNcclxuICAgIHZhciBudW1PYmpzID0gb2JqZWN0cy5sZW5ndGhcclxuICAgIHZhciBsbyA9IG5Cb3VuZHNbMF1cclxuICAgIHZhciBoaSA9IG5Cb3VuZHNbMV1cclxuICAgIGxvWzBdID0gbG9bMV0gPSBsb1syXSA9ICBJbmZpbml0eVxyXG4gICAgaGlbMF0gPSBoaVsxXSA9IGhpWzJdID0gLUluZmluaXR5XHJcbiAgICBmb3IodmFyIGk9MDsgaTxudW1PYmpzOyArK2kpIHtcclxuICAgICAgdmFyIG9iaiA9IG9iamVjdHNbaV1cclxuXHJcbiAgICAgIC8vU2V0IHRoZSBheGVzIHByb3BlcnRpZXMgZm9yIGVhY2ggb2JqZWN0XHJcbiAgICAgIG9iai5waXhlbFJhdGlvID0gc2NlbmUucGl4ZWxSYXRpb1xyXG4gICAgICBvYmouYXhlcyA9IHNjZW5lLmF4ZXNcclxuXHJcbiAgICAgIGRpcnR5ID0gZGlydHkgfHwgISFvYmouZGlydHlcclxuICAgICAgcGlja0RpcnR5ID0gcGlja0RpcnR5IHx8ICEhb2JqLmRpcnR5XHJcbiAgICAgIHZhciBvYmIgPSBvYmouYm91bmRzXHJcbiAgICAgIGlmKG9iYikge1xyXG4gICAgICAgIHZhciBvbG8gPSBvYmJbMF1cclxuICAgICAgICB2YXIgb2hpID0gb2JiWzFdXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgICBsb1tqXSA9IE1hdGgubWluKGxvW2pdLCBvbG9bal0pXHJcbiAgICAgICAgICBoaVtqXSA9IE1hdGgubWF4KGhpW2pdLCBvaGlbal0pXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9SZWNhbGN1bGF0ZSBib3VuZHNcclxuICAgIHZhciBib3VuZHMgPSBzY2VuZS5ib3VuZHNcclxuICAgIGlmKHNjZW5lLmF1dG9Cb3VuZHMpIHtcclxuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgaWYoaGlbal0gPCBsb1tqXSkge1xyXG4gICAgICAgICAgbG9bal0gPSAtMVxyXG4gICAgICAgICAgaGlbal0gPSAxXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmKGxvW2pdID09PSBoaVtqXSkge1xyXG4gICAgICAgICAgICBsb1tqXSAtPSAxXHJcbiAgICAgICAgICAgIGhpW2pdICs9IDFcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHZhciBwYWRkaW5nID0gMC4wNSAqIChoaVtqXSAtIGxvW2pdKVxyXG4gICAgICAgICAgbG9bal0gPSBsb1tqXSAtIHBhZGRpbmdcclxuICAgICAgICAgIGhpW2pdID0gaGlbal0gKyBwYWRkaW5nXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJvdW5kc1swXVtqXSA9IGxvW2pdXHJcbiAgICAgICAgYm91bmRzWzFdW2pdID0gaGlbal1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHZhciBib3VuZHNDaGFuZ2VkID0gZmFsc2VcclxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgIGJvdW5kc0NoYW5nZWQgPSBib3VuZHNDaGFuZ2VkIHx8XHJcbiAgICAgICAgICAgIChwcmV2Qm91bmRzWzBdW2pdICE9PSBib3VuZHNbMF1bal0pICB8fFxyXG4gICAgICAgICAgICAocHJldkJvdW5kc1sxXVtqXSAhPT0gYm91bmRzWzFdW2pdKVxyXG4gICAgICAgIHByZXZCb3VuZHNbMF1bal0gPSBib3VuZHNbMF1bal1cclxuICAgICAgICBwcmV2Qm91bmRzWzFdW2pdID0gYm91bmRzWzFdW2pdXHJcbiAgICB9XHJcblxyXG4gICAgLy9SZWNhbGN1bGF0ZSBib3VuZHNcclxuICAgIHBpY2tEaXJ0eSA9IHBpY2tEaXJ0eSB8fCBib3VuZHNDaGFuZ2VkXHJcbiAgICBkaXJ0eSA9IGRpcnR5IHx8IGJvdW5kc0NoYW5nZWRcclxuXHJcbiAgICBpZighZGlydHkpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcblxyXG4gICAgaWYoYm91bmRzQ2hhbmdlZCkge1xyXG4gICAgICB2YXIgdGlja1NwYWNpbmcgPSBbMCwwLDBdXHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgICAgIHRpY2tTcGFjaW5nW2ldID0gcm91bmRVcFBvdzEwKChib3VuZHNbMV1baV0tYm91bmRzWzBdW2ldKSAvIDEwLjApXHJcbiAgICAgIH1cclxuICAgICAgaWYoYXhlcy5hdXRvVGlja3MpIHtcclxuICAgICAgICBheGVzLnVwZGF0ZSh7XHJcbiAgICAgICAgICBib3VuZHM6IGJvdW5kcyxcclxuICAgICAgICAgIHRpY2tTcGFjaW5nOiB0aWNrU3BhY2luZ1xyXG4gICAgICAgIH0pXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgYXhlcy51cGRhdGUoe1xyXG4gICAgICAgICAgYm91bmRzOiBib3VuZHNcclxuICAgICAgICB9KVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9HZXQgc2NlbmVcclxuICAgIHZhciB3aWR0aCAgPSBnbC5kcmF3aW5nQnVmZmVyV2lkdGhcclxuICAgIHZhciBoZWlnaHQgPSBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XHJcbiAgICB2aWV3U2hhcGVbMF0gPSB3aWR0aFxyXG4gICAgdmlld1NoYXBlWzFdID0gaGVpZ2h0XHJcbiAgICBwaWNrU2hhcGVbMF0gPSBNYXRoLm1heCh3aWR0aC9zY2VuZS5waXhlbFJhdGlvLCAxKXwwXHJcbiAgICBwaWNrU2hhcGVbMV0gPSBNYXRoLm1heChoZWlnaHQvc2NlbmUucGl4ZWxSYXRpbywgMSl8MFxyXG5cclxuICAgIC8vQ29tcHV0ZSBjYW1lcmEgcGFyYW1ldGVyc1xyXG4gICAgcGVyc3BlY3RpdmUocHJvamVjdGlvbixcclxuICAgICAgc2NlbmUuZm92eSxcclxuICAgICAgd2lkdGgvaGVpZ2h0LFxyXG4gICAgICBzY2VuZS56TmVhcixcclxuICAgICAgc2NlbmUuekZhcilcclxuXHJcbiAgICAvL0NvbXB1dGUgbW9kZWwgbWF0cml4XHJcbiAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICAgIG1vZGVsW2ldID0gMFxyXG4gICAgfVxyXG4gICAgbW9kZWxbMTVdID0gMVxyXG5cclxuICAgIHZhciBtYXhTID0gMFxyXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICAgIG1heFMgPSBNYXRoLm1heChtYXhTLCBib3VuZHNbMV1baV0gLSBib3VuZHNbMF1baV0pXHJcbiAgICB9XHJcblxyXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICAgIGlmKHNjZW5lLmF1dG9TY2FsZSkge1xyXG4gICAgICAgIG1vZGVsWzUqaV0gPSBzY2VuZS5hc3BlY3RbaV0gLyAoYm91bmRzWzFdW2ldIC0gYm91bmRzWzBdW2ldKVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIG1vZGVsWzUqaV0gPSAxICAvIG1heFNcclxuICAgICAgfVxyXG4gICAgICBpZihzY2VuZS5hdXRvQ2VudGVyKSB7XHJcbiAgICAgICAgbW9kZWxbMTIraV0gPSAtbW9kZWxbNSppXSAqIDAuNSAqIChib3VuZHNbMF1baV0gKyBib3VuZHNbMV1baV0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL0FwcGx5IGF4ZXMvY2xpcCBib3VuZHNcclxuICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xyXG4gICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxyXG5cclxuICAgICAgLy9TZXQgYXhlcyBib3VuZHNcclxuICAgICAgb2JqLmF4ZXNCb3VuZHMgPSBib3VuZHNcclxuXHJcbiAgICAgIC8vU2V0IGNsaXAgYm91bmRzXHJcbiAgICAgIGlmKHNjZW5lLmNsaXBUb0JvdW5kcykge1xyXG4gICAgICAgIG9iai5jbGlwQm91bmRzID0gYm91bmRzXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vU2V0IHNwaWtlIHBhcmFtZXRlcnNcclxuICAgIGlmKHNlbGVjdGlvbi5vYmplY3QpIHtcclxuICAgICAgaWYoc2NlbmUuc25hcFRvRGF0YSkge1xyXG4gICAgICAgIHNwaWtlcy5wb3NpdGlvbiA9IHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHNwaWtlcy5wb3NpdGlvbiA9IHNlbGVjdGlvbi5kYXRhUG9zaXRpb25cclxuICAgICAgfVxyXG4gICAgICBzcGlrZXMuYm91bmRzID0gYm91bmRzXHJcbiAgICB9XHJcblxyXG4gICAgLy9JZiBzdGF0ZSBjaGFuZ2VkLCB0aGVuIHJlZHJhdyBwaWNrIGJ1ZmZlcnNcclxuICAgIGlmKHBpY2tEaXJ0eSkge1xyXG4gICAgICBwaWNrRGlydHkgPSBmYWxzZVxyXG4gICAgICByZW5kZXJQaWNrKClcclxuICAgIH1cclxuXHJcbiAgICAvL1JlY2FsY3VsYXRlIHBpeGVsIGRhdGFcclxuICAgIHNjZW5lLmF4ZXNQaXhlbHMgPSBheGVzUmFuZ2VzKHNjZW5lLmF4ZXMsIGNhbWVyYVBhcmFtcywgd2lkdGgsIGhlaWdodClcclxuXHJcbiAgICAvL0NhbGwgcmVuZGVyIGNhbGxiYWNrXHJcbiAgICBpZihzY2VuZS5vbnJlbmRlcikge1xyXG4gICAgICBzY2VuZS5vbnJlbmRlcigpXHJcbiAgICB9XHJcblxyXG4gICAgLy9SZWFkIHZhbHVlXHJcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXHJcbiAgICBnbC52aWV3cG9ydCgwLCAwLCB3aWR0aCwgaGVpZ2h0KVxyXG5cclxuICAgIC8vR2VuZXJhbCBzdHJhdGVneTogMyBzdGVwc1xyXG4gICAgLy8gIDEuIHJlbmRlciBub24tdHJhbnNwYXJlbnQgb2JqZWN0c1xyXG4gICAgLy8gIDIuIGFjY3VtdWxhdGUgdHJhbnNwYXJlbnQgb2JqZWN0cyBpbnRvIHNlcGFyYXRlIGZib1xyXG4gICAgLy8gIDMuIGNvbXBvc2l0ZSBmaW5hbCBzY2VuZVxyXG5cclxuICAgIC8vQ2xlYXIgRkJPXHJcbiAgICB2YXIgY2xlYXJDb2xvciA9IHNjZW5lLmNsZWFyQ29sb3JcclxuICAgIGdsLmNsZWFyQ29sb3IoY2xlYXJDb2xvclswXSwgY2xlYXJDb2xvclsxXSwgY2xlYXJDb2xvclsyXSwgY2xlYXJDb2xvclszXSlcclxuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQgfCBnbC5ERVBUSF9CVUZGRVJfQklUKVxyXG4gICAgZ2wuZGVwdGhNYXNrKHRydWUpXHJcbiAgICBnbC5jb2xvck1hc2sodHJ1ZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZSlcclxuICAgIGdsLmVuYWJsZShnbC5ERVBUSF9URVNUKVxyXG4gICAgZ2wuZGVwdGhGdW5jKGdsLkxFUVVBTClcclxuICAgIGdsLmRpc2FibGUoZ2wuQkxFTkQpXHJcbiAgICBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSkgIC8vbW9zdCB2aXN1YWxpemF0aW9uIHN1cmZhY2VzIGFyZSAyIHNpZGVkXHJcblxyXG4gICAgLy9SZW5kZXIgb3BhcXVlIHBhc3NcclxuICAgIHZhciBoYXNUcmFuc3BhcmVudCA9IGZhbHNlXHJcbiAgICBpZihheGVzLmVuYWJsZSkge1xyXG4gICAgICBoYXNUcmFuc3BhcmVudCA9IGhhc1RyYW5zcGFyZW50IHx8IGF4ZXMuaXNUcmFuc3BhcmVudCgpXHJcbiAgICAgIGF4ZXMuZHJhdyhjYW1lcmFQYXJhbXMpXHJcbiAgICB9XHJcbiAgICBzcGlrZXMuYXhlcyA9IGF4ZXNcclxuICAgIGlmKHNlbGVjdGlvbi5vYmplY3QpIHtcclxuICAgICAgc3Bpa2VzLmRyYXcoY2FtZXJhUGFyYW1zKVxyXG4gICAgfVxyXG5cclxuICAgIGdsLmRpc2FibGUoZ2wuQ1VMTF9GQUNFKSAgLy9tb3N0IHZpc3VhbGl6YXRpb24gc3VyZmFjZXMgYXJlIDIgc2lkZWRcclxuXHJcbiAgICBmb3IodmFyIGk9MDsgaTxudW1PYmpzOyArK2kpIHtcclxuICAgICAgdmFyIG9iaiA9IG9iamVjdHNbaV1cclxuICAgICAgb2JqLmF4ZXMgPSBheGVzXHJcbiAgICAgIG9iai5waXhlbFJhdGlvID0gc2NlbmUucGl4ZWxSYXRpb1xyXG4gICAgICBpZihvYmouaXNPcGFxdWUgJiYgb2JqLmlzT3BhcXVlKCkpIHtcclxuICAgICAgICBvYmouZHJhdyhjYW1lcmFQYXJhbXMpXHJcbiAgICAgIH1cclxuICAgICAgaWYob2JqLmlzVHJhbnNwYXJlbnQgJiYgb2JqLmlzVHJhbnNwYXJlbnQoKSkge1xyXG4gICAgICAgIGhhc1RyYW5zcGFyZW50ID0gdHJ1ZVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYoaGFzVHJhbnNwYXJlbnQpIHtcclxuICAgICAgLy9SZW5kZXIgdHJhbnNwYXJlbnQgcGFzc1xyXG4gICAgICBhY2N1bUJ1ZmZlci5zaGFwZSA9IHZpZXdTaGFwZVxyXG4gICAgICBhY2N1bUJ1ZmZlci5iaW5kKClcclxuICAgICAgZ2wuY2xlYXIoZ2wuREVQVEhfQlVGRkVSX0JJVClcclxuICAgICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKVxyXG4gICAgICBnbC5kZXB0aE1hc2sodHJ1ZSlcclxuICAgICAgZ2wuZGVwdGhGdW5jKGdsLkxFU1MpXHJcblxyXG4gICAgICAvL1JlbmRlciBmb3J3YXJkIGZhY2luZyBvYmplY3RzXHJcbiAgICAgIGlmKGF4ZXMuZW5hYmxlICYmIGF4ZXMuaXNUcmFuc3BhcmVudCgpKSB7XHJcbiAgICAgICAgYXhlcy5kcmF3VHJhbnNwYXJlbnQoY2FtZXJhUGFyYW1zKVxyXG4gICAgICB9XHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xyXG4gICAgICAgIHZhciBvYmogPSBvYmplY3RzW2ldXHJcbiAgICAgICAgaWYob2JqLmlzT3BhcXVlICYmIG9iai5pc09wYXF1ZSgpKSB7XHJcbiAgICAgICAgICBvYmouZHJhdyhjYW1lcmFQYXJhbXMpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL1JlbmRlciB0cmFuc3BhcmVudCBwYXNzXHJcbiAgICAgIGdsLmVuYWJsZShnbC5CTEVORClcclxuICAgICAgZ2wuYmxlbmRFcXVhdGlvbihnbC5GVU5DX0FERClcclxuICAgICAgZ2wuYmxlbmRGdW5jKGdsLk9ORSwgZ2wuT05FX01JTlVTX1NSQ19BTFBIQSlcclxuICAgICAgZ2wuY29sb3JNYXNrKHRydWUsIHRydWUsIHRydWUsIHRydWUpXHJcbiAgICAgIGdsLmRlcHRoTWFzayhmYWxzZSlcclxuICAgICAgZ2wuY2xlYXJDb2xvcigwLDAsMCwwKVxyXG4gICAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKVxyXG5cclxuICAgICAgaWYoYXhlcy5pc1RyYW5zcGFyZW50KCkpIHtcclxuICAgICAgICBheGVzLmRyYXdUcmFuc3BhcmVudChjYW1lcmFQYXJhbXMpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xyXG4gICAgICAgIHZhciBvYmogPSBvYmplY3RzW2ldXHJcbiAgICAgICAgaWYob2JqLmlzVHJhbnNwYXJlbnQgJiYgb2JqLmlzVHJhbnNwYXJlbnQoKSkge1xyXG4gICAgICAgICAgb2JqLmRyYXdUcmFuc3BhcmVudChjYW1lcmFQYXJhbXMpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL1VuYmluZCBmcmFtZWJ1ZmZlclxyXG4gICAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXHJcblxyXG4gICAgICAvL0RyYXcgY29tcG9zaXRlIHBhc3NcclxuICAgICAgZ2wuYmxlbmRGdW5jKGdsLk9ORSwgZ2wuT05FX01JTlVTX1NSQ19BTFBIQSlcclxuICAgICAgZ2wuZGlzYWJsZShnbC5ERVBUSF9URVNUKVxyXG4gICAgICBhY2N1bVNoYWRlci5iaW5kKClcclxuICAgICAgYWNjdW1CdWZmZXIuY29sb3JbMF0uYmluZCgwKVxyXG4gICAgICBhY2N1bVNoYWRlci51bmlmb3Jtcy5hY2N1bUJ1ZmZlciA9IDBcclxuICAgICAgZHJhd1RyaWFuZ2xlKGdsKVxyXG5cclxuICAgICAgLy9UdXJuIG9mZiBibGVuZGluZ1xyXG4gICAgICBnbC5kaXNhYmxlKGdsLkJMRU5EKVxyXG4gICAgfVxyXG5cclxuICAgIC8vQ2xlYXIgZGlydHkgZmxhZ3NcclxuICAgIGRpcnR5ID0gZmFsc2VcclxuICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xyXG4gICAgICBvYmplY3RzW2ldLmRpcnR5ID0gZmFsc2VcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxuICAvL0RyYXcgdGhlIHdob2xlIHNjZW5lXHJcbiAgZnVuY3Rpb24gcmVuZGVyKCkge1xyXG4gICAgaWYoc3RvcHBlZCB8fCBzY2VuZS5jb250ZXh0TG9zdCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIC8vIHRoaXMgb3JkZXIgaXMgaW1wb3J0YW50OiBpb3Mgc2FmYXJpIHNvbWV0aW1lcyBoYXMgc3luYyByYWZcclxuICAgIHJlZHJhdygpXHJcbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVuZGVyKVxyXG4gIH1cclxuICByZW5kZXIoKVxyXG5cclxuICAvL0ZvcmNlIHJlZHJhdyBvZiB3aG9sZSBzY2VuZVxyXG4gIHNjZW5lLnJlZHJhdyA9IGZ1bmN0aW9uKCkge1xyXG4gICAgaWYoc3RvcHBlZCkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIGRpcnR5ID0gdHJ1ZVxyXG4gICAgcmVkcmF3KClcclxuICB9XHJcblxyXG4gIHJldHVybiBzY2VuZVxyXG59XHJcbiIsInZhciBnbHNsaWZ5ID0gcmVxdWlyZSgnZ2xzbGlmeScpXHJcblxyXG5leHBvcnRzLnBvaW50VmVydGV4ICAgICAgID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uO1xcblxcbnVuaWZvcm0gbWF0MyBtYXRyaXg7XFxudW5pZm9ybSBmbG9hdCBwb2ludFNpemU7XFxudW5pZm9ybSBmbG9hdCBwb2ludENsb3VkO1xcblxcbmhpZ2hwIGZsb2F0IHJhbmQodmVjMiBjbykge1xcbiAgaGlnaHAgZmxvYXQgYSA9IDEyLjk4OTg7XFxuICBoaWdocCBmbG9hdCBiID0gNzguMjMzO1xcbiAgaGlnaHAgZmxvYXQgYyA9IDQzNzU4LjU0NTM7XFxuICBoaWdocCBmbG9hdCBkID0gZG90KGNvLnh5LCB2ZWMyKGEsIGIpKTtcXG4gIGhpZ2hwIGZsb2F0IGUgPSBtb2QoZCwgMy4xNCk7XFxuICByZXR1cm4gZnJhY3Qoc2luKGUpICogYyk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgaGdQb3NpdGlvbiA9IG1hdHJpeCAqIHZlYzMocG9zaXRpb24sIDEpO1xcbiAgZ2xfUG9zaXRpb24gID0gdmVjNChoZ1Bvc2l0aW9uLnh5LCAwLCBoZ1Bvc2l0aW9uLnopO1xcbiAgICAvLyBpZiB3ZSBkb24ndCBqaXR0ZXIgdGhlIHBvaW50IHNpemUgYSBiaXQsIG92ZXJhbGwgcG9pbnQgY2xvdWRcXG4gICAgLy8gc2F0dXJhdGlvbiAnanVtcHMnIG9uIHpvb21pbmcsIHdoaWNoIGlzIGRpc3R1cmJpbmcgYW5kIGNvbmZ1c2luZ1xcbiAgZ2xfUG9pbnRTaXplID0gcG9pbnRTaXplICogKCgxOS41ICsgcmFuZChwb3NpdGlvbikpIC8gMjAuMCk7XFxuICBpZihwb2ludENsb3VkICE9IDAuMCkgeyAvLyBwb2ludENsb3VkIGlzIHRydXRoeVxcbiAgICAvLyBnZXQgdGhlIHNhbWUgc3F1YXJlIHN1cmZhY2UgYXMgY2lyY2xlIHdvdWxkIGJlXFxuICAgIGdsX1BvaW50U2l6ZSAqPSAwLjg4NjtcXG4gIH1cXG59XCJdKVxyXG5leHBvcnRzLnBvaW50RnJhZ21lbnQgICAgID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gdmVjNCBjb2xvciwgYm9yZGVyQ29sb3I7XFxudW5pZm9ybSBmbG9hdCBjZW50ZXJGcmFjdGlvbjtcXG51bmlmb3JtIGZsb2F0IHBvaW50Q2xvdWQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZmxvYXQgcmFkaXVzO1xcbiAgdmVjNCBiYXNlQ29sb3I7XFxuICBpZihwb2ludENsb3VkICE9IDAuMCkgeyAvLyBwb2ludENsb3VkIGlzIHRydXRoeVxcbiAgICBpZihjZW50ZXJGcmFjdGlvbiA9PSAxLjApIHtcXG4gICAgICBnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG4gICAgfSBlbHNlIHtcXG4gICAgICBnbF9GcmFnQ29sb3IgPSBtaXgoYm9yZGVyQ29sb3IsIGNvbG9yLCBjZW50ZXJGcmFjdGlvbik7XFxuICAgIH1cXG4gIH0gZWxzZSB7XFxuICAgIHJhZGl1cyA9IGxlbmd0aCgyLjAgKiBnbF9Qb2ludENvb3JkLnh5IC0gMS4wKTtcXG4gICAgaWYocmFkaXVzID4gMS4wKSB7XFxuICAgICAgZGlzY2FyZDtcXG4gICAgfVxcbiAgICBiYXNlQ29sb3IgPSBtaXgoYm9yZGVyQ29sb3IsIGNvbG9yLCBzdGVwKHJhZGl1cywgY2VudGVyRnJhY3Rpb24pKTtcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNChiYXNlQ29sb3IucmdiICogYmFzZUNvbG9yLmEsIGJhc2VDb2xvci5hKTtcXG4gIH1cXG59XFxuXCJdKVxyXG5leHBvcnRzLnBpY2tWZXJ0ZXggICAgICAgID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IHBpY2tJZDtcXG5cXG51bmlmb3JtIG1hdDMgbWF0cml4O1xcbnVuaWZvcm0gZmxvYXQgcG9pbnRTaXplO1xcbnVuaWZvcm0gdmVjNCBwaWNrT2Zmc2V0O1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnSWQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBoZ1Bvc2l0aW9uID0gbWF0cml4ICogdmVjMyhwb3NpdGlvbiwgMSk7XFxuICBnbF9Qb3NpdGlvbiAgPSB2ZWM0KGhnUG9zaXRpb24ueHksIDAsIGhnUG9zaXRpb24ueik7XFxuICBnbF9Qb2ludFNpemUgPSBwb2ludFNpemU7XFxuXFxuICB2ZWM0IGlkID0gcGlja0lkICsgcGlja09mZnNldDtcXG4gIGlkLnkgKz0gZmxvb3IoaWQueCAvIDI1Ni4wKTtcXG4gIGlkLnggLT0gZmxvb3IoaWQueCAvIDI1Ni4wKSAqIDI1Ni4wO1xcblxcbiAgaWQueiArPSBmbG9vcihpZC55IC8gMjU2LjApO1xcbiAgaWQueSAtPSBmbG9vcihpZC55IC8gMjU2LjApICogMjU2LjA7XFxuXFxuICBpZC53ICs9IGZsb29yKGlkLnogLyAyNTYuMCk7XFxuICBpZC56IC09IGZsb29yKGlkLnogLyAyNTYuMCkgKiAyNTYuMDtcXG5cXG4gIGZyYWdJZCA9IGlkO1xcbn1cXG5cIl0pXHJcbmV4cG9ydHMucGlja0ZyYWdtZW50ICAgICAgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdJZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBmbG9hdCByYWRpdXMgPSBsZW5ndGgoMi4wICogZ2xfUG9pbnRDb29yZC54eSAtIDEuMCk7XFxuICBpZihyYWRpdXMgPiAxLjApIHtcXG4gICAgZGlzY2FyZDtcXG4gIH1cXG4gIGdsX0ZyYWdDb2xvciA9IGZyYWdJZCAvIDI1NS4wO1xcbn1cXG5cIl0pXHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcbnZhciBjcmVhdGVCdWZmZXIgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG5cclxudmFyIHBvb2wgPSByZXF1aXJlKCd0eXBlZGFycmF5LXBvb2wnKVxyXG5cclxudmFyIFNIQURFUlMgPSByZXF1aXJlKCcuL2xpYi9zaGFkZXInKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQb2ludGNsb3VkMkRcclxuXHJcbmZ1bmN0aW9uIFBvaW50Y2xvdWQyRChwbG90LCBvZmZzZXRCdWZmZXIsIHBpY2tCdWZmZXIsIHNoYWRlciwgcGlja1NoYWRlcikge1xyXG4gIHRoaXMucGxvdCAgICAgICAgICAgPSBwbG90XHJcbiAgdGhpcy5vZmZzZXRCdWZmZXIgICA9IG9mZnNldEJ1ZmZlclxyXG4gIHRoaXMucGlja0J1ZmZlciAgICAgPSBwaWNrQnVmZmVyXHJcbiAgdGhpcy5zaGFkZXIgICAgICAgICA9IHNoYWRlclxyXG4gIHRoaXMucGlja1NoYWRlciAgICAgPSBwaWNrU2hhZGVyXHJcbiAgdGhpcy5zaXplTWluICAgICAgICA9IDAuNVxyXG4gIHRoaXMuc2l6ZU1pbkNhcCAgICAgPSAyXHJcbiAgdGhpcy5zaXplTWF4ICAgICAgICA9IDIwXHJcbiAgdGhpcy5hcmVhUmF0aW8gICAgICA9IDEuMFxyXG4gIHRoaXMucG9pbnRDb3VudCAgICAgPSAwXHJcbiAgdGhpcy5jb2xvciAgICAgICAgICA9IFsxLCAwLCAwLCAxXVxyXG4gIHRoaXMuYm9yZGVyQ29sb3IgICAgPSBbMCwgMCwgMCwgMV1cclxuICB0aGlzLmJsZW5kICAgICAgICAgID0gZmFsc2VcclxuICB0aGlzLnBpY2tPZmZzZXQgICAgID0gMFxyXG4gIHRoaXMucG9pbnRzICAgICAgICAgPSBudWxsXHJcbn1cclxuXHJcbnZhciBwcm90byA9IFBvaW50Y2xvdWQyRC5wcm90b3R5cGVcclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcclxuICB0aGlzLnBpY2tTaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5vZmZzZXRCdWZmZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5waWNrQnVmZmVyLmRpc3Bvc2UoKVxyXG4gIHRoaXMucGxvdC5yZW1vdmVPYmplY3QodGhpcylcclxufVxyXG5cclxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xyXG5cclxuICB2YXIgaVxyXG5cclxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxyXG5cclxuICBmdW5jdGlvbiBkZmx0KG9wdCwgdmFsdWUpIHtcclxuICAgIGlmKG9wdCBpbiBvcHRpb25zKSB7XHJcbiAgICAgIHJldHVybiBvcHRpb25zW29wdF1cclxuICAgIH1cclxuICAgIHJldHVybiB2YWx1ZVxyXG4gIH1cclxuXHJcbiAgdGhpcy5zaXplTWluICAgICAgPSBkZmx0KCdzaXplTWluJywgMC41KVxyXG4gIC8vIHRoaXMuc2l6ZU1pbkNhcCAgICAgID0gZGZsdCgnc2l6ZU1pbkNhcCcsIDIpXHJcbiAgdGhpcy5zaXplTWF4ICAgICAgPSBkZmx0KCdzaXplTWF4JywgMjApXHJcbiAgdGhpcy5jb2xvciAgICAgICAgPSBkZmx0KCdjb2xvcicsIFsxLCAwLCAwLCAxXSkuc2xpY2UoKVxyXG4gIHRoaXMuYXJlYVJhdGlvICAgID0gZGZsdCgnYXJlYVJhdGlvJywgMSlcclxuICB0aGlzLmJvcmRlckNvbG9yICA9IGRmbHQoJ2JvcmRlckNvbG9yJywgWzAsIDAsIDAsIDFdKS5zbGljZSgpXHJcbiAgdGhpcy5ibGVuZCAgICAgICAgPSBkZmx0KCdibGVuZCcsIGZhbHNlKVxyXG5cclxuICAvL1VwZGF0ZSBwb2ludCBkYXRhXHJcblxyXG4gIC8vIEF0dGVtcHQgc3RyYWlnaHQtdGhyb3VnaCBwcm9jZXNzaW5nIChTVFApIHRvIGF2b2lkIGFsbG9jYXRpb24gYW5kIGNvcHlcclxuICAvLyBUT0RPIGV2ZW50dWFsbHkgYWJzdHJhY3Qgb3V0IFNUUCBsb2dpYywgbWF5YmUgaW50byBgcG9vbGAgb3IgYSBsYXllciBhYm92ZVxyXG4gIHZhciBwb2ludENvdW50ID0gb3B0aW9ucy5wb3NpdGlvbnMubGVuZ3RoID4+PiAxXHJcbiAgdmFyIGRhdGFTdHJhaWdodFRocm91Z2ggPSBvcHRpb25zLnBvc2l0aW9ucyBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheVxyXG4gIHZhciBpZFN0cmFpZ2h0VGhyb3VnaCA9IG9wdGlvbnMuaWRUb0luZGV4IGluc3RhbmNlb2YgSW50MzJBcnJheSAmJiBvcHRpb25zLmlkVG9JbmRleC5sZW5ndGggPj0gcG9pbnRDb3VudCAvLyBwZXJtaXQgbGFyZ2VyIHRvIGhlbHAgcmV1c2VcclxuXHJcbiAgdmFyIGRhdGEgICAgICAgICAgPSBvcHRpb25zLnBvc2l0aW9uc1xyXG4gIHZhciBwYWNrZWQgICAgICAgID0gZGF0YVN0cmFpZ2h0VGhyb3VnaCA/IGRhdGEgOiBwb29sLm1hbGxvY0Zsb2F0MzIoZGF0YS5sZW5ndGgpXHJcbiAgdmFyIHBhY2tlZElkICAgICAgPSBpZFN0cmFpZ2h0VGhyb3VnaCA/IG9wdGlvbnMuaWRUb0luZGV4IDogcG9vbC5tYWxsb2NJbnQzMihwb2ludENvdW50KVxyXG5cclxuICBpZighZGF0YVN0cmFpZ2h0VGhyb3VnaCkge1xyXG4gICAgcGFja2VkLnNldChkYXRhKVxyXG4gIH1cclxuXHJcbiAgaWYoIWlkU3RyYWlnaHRUaHJvdWdoKSB7XHJcbiAgICBwYWNrZWQuc2V0KGRhdGEpXHJcbiAgICBmb3IoaSA9IDA7IGkgPCBwb2ludENvdW50OyBpKyspIHtcclxuICAgICAgcGFja2VkSWRbaV0gPSBpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0aGlzLnBvaW50cyAgICAgICA9IGRhdGFcclxuXHJcbiAgdGhpcy5vZmZzZXRCdWZmZXIudXBkYXRlKHBhY2tlZClcclxuICB0aGlzLnBpY2tCdWZmZXIudXBkYXRlKHBhY2tlZElkKVxyXG5cclxuICBpZighZGF0YVN0cmFpZ2h0VGhyb3VnaCkge1xyXG4gICAgcG9vbC5mcmVlKHBhY2tlZClcclxuICB9XHJcblxyXG4gIGlmKCFpZFN0cmFpZ2h0VGhyb3VnaCkge1xyXG4gICAgcG9vbC5mcmVlKHBhY2tlZElkKVxyXG4gIH1cclxuXHJcbiAgdGhpcy5wb2ludENvdW50ID0gcG9pbnRDb3VudFxyXG4gIHRoaXMucGlja09mZnNldCA9IDBcclxufVxyXG5cclxuZnVuY3Rpb24gY291bnQocG9pbnRzLCBkYXRhQm94KSB7XHJcbiAgdmFyIHZpc2libGVQb2ludENvdW50RXN0aW1hdGUgPSAwXHJcbiAgdmFyIGxlbmd0aCA9IHBvaW50cy5sZW5ndGggPj4+IDFcclxuICB2YXIgaVxyXG4gIGZvcihpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICB2YXIgeCA9IHBvaW50c1tpICogMl1cclxuICAgIHZhciB5ID0gcG9pbnRzW2kgKiAyICsgMV1cclxuICAgIGlmKHggPj0gZGF0YUJveFswXSAmJiB4IDw9IGRhdGFCb3hbMl0gJiYgeSA+PSBkYXRhQm94WzFdICYmIHkgPD0gZGF0YUJveFszXSlcclxuICAgICAgdmlzaWJsZVBvaW50Q291bnRFc3RpbWF0ZSsrXHJcbiAgfVxyXG4gIHJldHVybiB2aXNpYmxlUG9pbnRDb3VudEVzdGltYXRlXHJcbn1cclxuXHJcbnByb3RvLnVuaWZpZWREcmF3ID0gKGZ1bmN0aW9uKCkge1xyXG4gIHZhciBNQVRSSVggPSBbMSwgMCwgMCxcclxuICAgICAgICAgICAgICAgIDAsIDEsIDAsXHJcbiAgICAgICAgICAgICAgICAwLCAwLCAxXVxyXG4gIHZhciBQSUNLX1ZFQzQgPSBbMCwgMCwgMCwgMF1cclxucmV0dXJuIGZ1bmN0aW9uKHBpY2tPZmZzZXQpIHtcclxuICB2YXIgcGljayA9IHBpY2tPZmZzZXQgIT09IHZvaWQoMClcclxuXHJcbiAgdmFyIHNoYWRlciAgICAgICAgPSBwaWNrID8gdGhpcy5waWNrU2hhZGVyIDogdGhpcy5zaGFkZXJcclxuICB2YXIgZ2wgICAgICAgICAgICA9IHRoaXMucGxvdC5nbFxyXG4gIHZhciBkYXRhQm94ICAgICAgID0gdGhpcy5wbG90LmRhdGFCb3hcclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID09PSAwKSB7XHJcbiAgICByZXR1cm4gcGlja09mZnNldFxyXG4gIH1cclxuXHJcbiAgdmFyIGRhdGFYICAgPSBkYXRhQm94WzJdIC0gZGF0YUJveFswXVxyXG4gIHZhciBkYXRhWSAgID0gZGF0YUJveFszXSAtIGRhdGFCb3hbMV1cclxuXHJcbiAgdmFyIHZpc2libGVQb2ludENvdW50RXN0aW1hdGUgPSBjb3VudCh0aGlzLnBvaW50cywgZGF0YUJveClcclxuICB2YXIgYmFzaWNQb2ludFNpemUgPSAgdGhpcy5wbG90LnBpY2tQaXhlbFJhdGlvICogTWF0aC5tYXgoTWF0aC5taW4odGhpcy5zaXplTWluQ2FwLCB0aGlzLnNpemVNaW4pLCBNYXRoLm1pbih0aGlzLnNpemVNYXgsIHRoaXMuc2l6ZU1heCAvIE1hdGgucG93KHZpc2libGVQb2ludENvdW50RXN0aW1hdGUsIDAuMzMzMzMpKSlcclxuXHJcbiAgTUFUUklYWzBdID0gMi4wIC8gZGF0YVhcclxuICBNQVRSSVhbNF0gPSAyLjAgLyBkYXRhWVxyXG4gIE1BVFJJWFs2XSA9IC0yLjAgKiBkYXRhQm94WzBdIC8gZGF0YVggLSAxLjBcclxuICBNQVRSSVhbN10gPSAtMi4wICogZGF0YUJveFsxXSAvIGRhdGFZIC0gMS4wXHJcblxyXG4gIHRoaXMub2Zmc2V0QnVmZmVyLmJpbmQoKVxyXG5cclxuICBzaGFkZXIuYmluZCgpXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9zaXRpb24ucG9pbnRlcigpXHJcbiAgc2hhZGVyLnVuaWZvcm1zLm1hdHJpeCAgICAgID0gTUFUUklYXHJcbiAgc2hhZGVyLnVuaWZvcm1zLmNvbG9yICAgICAgID0gdGhpcy5jb2xvclxyXG4gIHNoYWRlci51bmlmb3Jtcy5ib3JkZXJDb2xvciA9IHRoaXMuYm9yZGVyQ29sb3JcclxuICBzaGFkZXIudW5pZm9ybXMucG9pbnRDbG91ZCA9IGJhc2ljUG9pbnRTaXplIDwgNVxyXG4gIHNoYWRlci51bmlmb3Jtcy5wb2ludFNpemUgPSBiYXNpY1BvaW50U2l6ZVxyXG4gIHNoYWRlci51bmlmb3Jtcy5jZW50ZXJGcmFjdGlvbiA9IE1hdGgubWluKDEsIE1hdGgubWF4KDAsIE1hdGguc3FydCgxIC0gdGhpcy5hcmVhUmF0aW8pKSlcclxuXHJcbiAgaWYocGljaykge1xyXG5cclxuICAgIFBJQ0tfVkVDNFswXSA9ICggcGlja09mZnNldCAgICAgICAgJiAweGZmKVxyXG4gICAgUElDS19WRUM0WzFdID0gKChwaWNrT2Zmc2V0ID4+IDgpICAmIDB4ZmYpXHJcbiAgICBQSUNLX1ZFQzRbMl0gPSAoKHBpY2tPZmZzZXQgPj4gMTYpICYgMHhmZilcclxuICAgIFBJQ0tfVkVDNFszXSA9ICgocGlja09mZnNldCA+PiAyNCkgJiAweGZmKVxyXG5cclxuICAgIHRoaXMucGlja0J1ZmZlci5iaW5kKClcclxuICAgIHNoYWRlci5hdHRyaWJ1dGVzLnBpY2tJZC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUpXHJcbiAgICBzaGFkZXIudW5pZm9ybXMucGlja09mZnNldCA9IFBJQ0tfVkVDNFxyXG4gICAgdGhpcy5waWNrT2Zmc2V0ID0gcGlja09mZnNldFxyXG4gIH1cclxuXHJcbiAgLy8gV29ydGggc3dpdGNoaW5nIHRoZXNlIG9mZiwgYnV0IHdlIGNhbid0IG1ha2UgYXNzdW1wdGlvbnMgYWJvdXQgb3RoZXJcclxuICAvLyByZW5kZXJlcnMsIHNvIGxldCdzIHJlc3RvcmUgaXQgYWZ0ZXIgZWFjaCBkcmF3XHJcbiAgdmFyIGJsZW5kID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLkJMRU5EKVxyXG4gIHZhciBkaXRoZXIgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuRElUSEVSKVxyXG5cclxuICBpZihibGVuZCAmJiAhdGhpcy5ibGVuZClcclxuICAgIGdsLmRpc2FibGUoZ2wuQkxFTkQpXHJcbiAgaWYoZGl0aGVyKVxyXG4gICAgZ2wuZGlzYWJsZShnbC5ESVRIRVIpXHJcblxyXG4gIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXHJcblxyXG4gIGlmKGJsZW5kICYmICF0aGlzLmJsZW5kKVxyXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKVxyXG4gIGlmKGRpdGhlcilcclxuICAgIGdsLmVuYWJsZShnbC5ESVRIRVIpXHJcblxyXG4gIHJldHVybiBwaWNrT2Zmc2V0ICsgdGhpcy5wb2ludENvdW50XHJcbn1cclxufSkoKVxyXG5cclxucHJvdG8uZHJhdyA9IHByb3RvLnVuaWZpZWREcmF3XHJcbnByb3RvLmRyYXdQaWNrID0gcHJvdG8udW5pZmllZERyYXdcclxuXHJcbnByb3RvLnBpY2sgPSBmdW5jdGlvbih4LCB5LCB2YWx1ZSkge1xyXG4gIHZhciBwaWNrT2Zmc2V0ID0gdGhpcy5waWNrT2Zmc2V0XHJcbiAgdmFyIHBvaW50Q291bnQgPSB0aGlzLnBvaW50Q291bnRcclxuICBpZih2YWx1ZSA8IHBpY2tPZmZzZXQgfHwgdmFsdWUgPj0gcGlja09mZnNldCArIHBvaW50Q291bnQpIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG4gIHZhciBwb2ludElkID0gdmFsdWUgLSBwaWNrT2Zmc2V0XHJcbiAgdmFyIHBvaW50cyA9IHRoaXMucG9pbnRzXHJcbiAgcmV0dXJuIHtcclxuICAgIG9iamVjdDogdGhpcyxcclxuICAgIHBvaW50SWQ6IHBvaW50SWQsXHJcbiAgICBkYXRhQ29vcmQ6IFtwb2ludHNbMiAqIHBvaW50SWRdLCBwb2ludHNbMiAqIHBvaW50SWQgKyAxXSBdXHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVQb2ludGNsb3VkMkQocGxvdCwgb3B0aW9ucykge1xyXG4gIHZhciBnbCA9IHBsb3QuZ2xcclxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwaWNrQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIFNIQURFUlMucG9pbnRWZXJ0ZXgsIFNIQURFUlMucG9pbnRGcmFnbWVudClcclxuICB2YXIgcGlja1NoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgU0hBREVSUy5waWNrVmVydGV4LCBTSEFERVJTLnBpY2tGcmFnbWVudClcclxuXHJcbiAgdmFyIHJlc3VsdCA9IG5ldyBQb2ludGNsb3VkMkQocGxvdCwgYnVmZmVyLCBwaWNrQnVmZmVyLCBzaGFkZXIsIHBpY2tTaGFkZXIpXHJcbiAgcmVzdWx0LnVwZGF0ZShvcHRpb25zKVxyXG5cclxuICAvL1JlZ2lzdGVyIHdpdGggcGxvdFxyXG4gIHBsb3QuYWRkT2JqZWN0KHJlc3VsdClcclxuXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcbiIsIm1vZHVsZS5leHBvcnRzID0gc2xlcnBcblxuLyoqXG4gKiBQZXJmb3JtcyBhIHNwaGVyaWNhbCBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xuZnVuY3Rpb24gc2xlcnAgKG91dCwgYSwgYiwgdCkge1xuICAvLyBiZW5jaG1hcmtzOlxuICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuXG4gIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgYnggPSBiWzBdLCBieSA9IGJbMV0sIGJ6ID0gYlsyXSwgYncgPSBiWzNdXG5cbiAgdmFyIG9tZWdhLCBjb3NvbSwgc2lub20sIHNjYWxlMCwgc2NhbGUxXG5cbiAgLy8gY2FsYyBjb3NpbmVcbiAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3XG4gIC8vIGFkanVzdCBzaWducyAoaWYgbmVjZXNzYXJ5KVxuICBpZiAoY29zb20gPCAwLjApIHtcbiAgICBjb3NvbSA9IC1jb3NvbVxuICAgIGJ4ID0gLWJ4XG4gICAgYnkgPSAtYnlcbiAgICBieiA9IC1ielxuICAgIGJ3ID0gLWJ3XG4gIH1cbiAgLy8gY2FsY3VsYXRlIGNvZWZmaWNpZW50c1xuICBpZiAoKDEuMCAtIGNvc29tKSA+IDAuMDAwMDAxKSB7XG4gICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgb21lZ2EgPSBNYXRoLmFjb3MoY29zb20pXG4gICAgc2lub20gPSBNYXRoLnNpbihvbWVnYSlcbiAgICBzY2FsZTAgPSBNYXRoLnNpbigoMS4wIC0gdCkgKiBvbWVnYSkgLyBzaW5vbVxuICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbVxuICB9IGVsc2Uge1xuICAgIC8vIFwiZnJvbVwiIGFuZCBcInRvXCIgcXVhdGVybmlvbnMgYXJlIHZlcnkgY2xvc2VcbiAgICAvLyAgLi4uIHNvIHdlIGNhbiBkbyBhIGxpbmVhciBpbnRlcnBvbGF0aW9uXG4gICAgc2NhbGUwID0gMS4wIC0gdFxuICAgIHNjYWxlMSA9IHRcbiAgfVxuICAvLyBjYWxjdWxhdGUgZmluYWwgdmFsdWVzXG4gIG91dFswXSA9IHNjYWxlMCAqIGF4ICsgc2NhbGUxICogYnhcbiAgb3V0WzFdID0gc2NhbGUwICogYXkgKyBzY2FsZTEgKiBieVxuICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6XG4gIG91dFszXSA9IHNjYWxlMCAqIGF3ICsgc2NhbGUxICogYndcblxuICByZXR1cm4gb3V0XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYSl7XG4gIHJldHVybiAoIWEgJiYgYSAhPT0gMCkgPyAnJyA6IGEudG9TdHJpbmcoKTtcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciB2ZWN0b3JpemVUZXh0ID0gcmVxdWlyZShcInZlY3Rvcml6ZS10ZXh0XCIpXG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0R2x5cGhcblxudmFyIEdMWVBIX0NBQ0hFID0ge31cblxuZnVuY3Rpb24gZ2V0R2x5cGgoc3ltYm9sLCBmb250KSB7XG4gIHZhciBmb250Q2FjaGUgPSBHTFlQSF9DQUNIRVtmb250XVxuICBpZighZm9udENhY2hlKSB7XG4gICAgZm9udENhY2hlID0gR0xZUEhfQ0FDSEVbZm9udF0gPSB7fVxuICB9XG4gIGlmKHN5bWJvbCBpbiBmb250Q2FjaGUpIHtcbiAgICByZXR1cm4gZm9udENhY2hlW3N5bWJvbF1cbiAgfVxuXG4gIC8vR2V0IGxpbmUgYW5kIHRyaWFuZ2xlIG1lc2hlcyBmb3IgZ2x5cGhcbiAgdmFyIGxpbmVTeW1ib2wgPSB2ZWN0b3JpemVUZXh0KHN5bWJvbCwge1xuICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxuICAgICAgdGV4dEJhc2VsaW5lOiBcIm1pZGRsZVwiLFxuICAgICAgbGluZUhlaWdodDogMS4wLFxuICAgICAgZm9udDogZm9udFxuICAgIH0pXG4gIHZhciB0cmlTeW1ib2wgPSB2ZWN0b3JpemVUZXh0KHN5bWJvbCwge1xuICAgICAgdHJpYW5nbGVzOiB0cnVlLFxuICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxuICAgICAgdGV4dEJhc2VsaW5lOiBcIm1pZGRsZVwiLFxuICAgICAgbGluZUhlaWdodDogMS4wLFxuICAgICAgZm9udDogZm9udFxuICAgIH0pIFxuXG4gIC8vQ2FsY3VsYXRlIGJvdW5kaW5nIGJveFxuICB2YXIgYm91bmRzID0gW1tJbmZpbml0eSxJbmZpbml0eV0sIFstSW5maW5pdHksLUluZmluaXR5XV1cbiAgZm9yKHZhciBpPTA7IGk8bGluZVN5bWJvbC5wb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcCA9IGxpbmVTeW1ib2wucG9zaXRpb25zW2ldXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICBib3VuZHNbMF1bal0gPSBNYXRoLm1pbihib3VuZHNbMF1bal0sIHBbal0pXG4gICAgICBib3VuZHNbMV1bal0gPSBNYXRoLm1heChib3VuZHNbMV1bal0sIHBbal0pXG4gICAgfVxuICB9XG5cbiAgLy9TYXZlIGNhY2hlZCBzeW1ib2xcbiAgcmV0dXJuIGZvbnRDYWNoZVtzeW1ib2xdID0gW3RyaVN5bWJvbCwgbGluZVN5bWJvbCwgYm91bmRzXVxufSIsInZhciBjcmVhdGVTaGFkZXJXcmFwcGVyID0gcmVxdWlyZSgnZ2wtc2hhZGVyJylcbnZhciBnbHNsaWZ5ID0gcmVxdWlyZSgnZ2xzbGlmeScpXG5cbnZhciBwZXJzcGVjdGl2ZVZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuYXR0cmlidXRlIHZlYzIgZ2x5cGg7XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSB2ZWM0IGhpZ2hsaWdodElkO1xcbnVuaWZvcm0gZmxvYXQgaGlnaGxpZ2h0U2NhbGU7XFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcblxcbnZhcnlpbmcgdmVjNCBpbnRlcnBDb2xvcjtcXG52YXJ5aW5nIHZlYzQgcGlja0lkO1xcbnZhcnlpbmcgdmVjMyBkYXRhQ29vcmRpbmF0ZTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBwb3NpdGlvbikpIHtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KDAsMCwwLDApO1xcbiAgfSBlbHNlIHtcXG4gICAgZmxvYXQgc2NhbGUgPSAxLjA7XFxuICAgIGlmKGRpc3RhbmNlKGhpZ2hsaWdodElkLCBpZCkgPCAwLjAwMDEpIHtcXG4gICAgICBzY2FsZSA9IGhpZ2hsaWdodFNjYWxlO1xcbiAgICB9XFxuXFxuICAgIHZlYzQgd29ybGRQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbiwgMSk7XFxuICAgIHZlYzQgdmlld1Bvc2l0aW9uID0gdmlldyAqIHdvcmxkUG9zaXRpb247XFxuICAgIHZpZXdQb3NpdGlvbiA9IHZpZXdQb3NpdGlvbiAvIHZpZXdQb3NpdGlvbi53O1xcbiAgICB2ZWM0IGNsaXBQb3NpdGlvbiA9IHByb2plY3Rpb24gKiAodmlld1Bvc2l0aW9uICsgc2NhbGUgKiB2ZWM0KGdseXBoLngsIC1nbHlwaC55LCAwLCAwKSk7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gY2xpcFBvc2l0aW9uO1xcbiAgICBpbnRlcnBDb2xvciA9IGNvbG9yO1xcbiAgICBwaWNrSWQgPSBpZDtcXG4gICAgZGF0YUNvb3JkaW5hdGUgPSBwb3NpdGlvbjtcXG4gIH1cXG59XCJdKVxudmFyIG9ydGhvZ3JhcGhpY1ZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuYXR0cmlidXRlIHZlYzIgZ2x5cGg7XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMiBzY3JlZW5TaXplO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgaGlnaGxpZ2h0U2NhbGUsIHBpeGVsUmF0aW87XFxudW5pZm9ybSB2ZWM0IGhpZ2hsaWdodElkO1xcblxcbnZhcnlpbmcgdmVjNCBpbnRlcnBDb2xvcjtcXG52YXJ5aW5nIHZlYzQgcGlja0lkO1xcbnZhcnlpbmcgdmVjMyBkYXRhQ29vcmRpbmF0ZTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBwb3NpdGlvbikpIHtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KDAsMCwwLDApO1xcbiAgfSBlbHNlIHtcXG4gICAgZmxvYXQgc2NhbGUgPSBwaXhlbFJhdGlvO1xcbiAgICBpZihkaXN0YW5jZShoaWdobGlnaHRJZC5iZ3IsIGlkLmJncikgPCAwLjAwMSkge1xcbiAgICAgIHNjYWxlICo9IGhpZ2hsaWdodFNjYWxlO1xcbiAgICB9XFxuXFxuICAgIHZlYzQgd29ybGRQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbiwgMS4wKTtcXG4gICAgdmVjNCB2aWV3UG9zaXRpb24gPSB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gICAgdmVjNCBjbGlwUG9zaXRpb24gPSBwcm9qZWN0aW9uICogdmlld1Bvc2l0aW9uO1xcbiAgICBjbGlwUG9zaXRpb24gLz0gY2xpcFBvc2l0aW9uLnc7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gY2xpcFBvc2l0aW9uICsgdmVjNChzY3JlZW5TaXplICogc2NhbGUgKiB2ZWMyKGdseXBoLngsIC1nbHlwaC55KSwgMC4wLCAwLjApO1xcbiAgICBpbnRlcnBDb2xvciA9IGNvbG9yO1xcbiAgICBwaWNrSWQgPSBpZDtcXG4gICAgZGF0YUNvb3JkaW5hdGUgPSBwb3NpdGlvbjtcXG4gIH1cXG59XCJdKVxudmFyIHByb2plY3Rpb25WZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIGdseXBoO1xcbmF0dHJpYnV0ZSB2ZWM0IGlkO1xcblxcbnVuaWZvcm0gZmxvYXQgaGlnaGxpZ2h0U2NhbGU7XFxudW5pZm9ybSB2ZWM0IGhpZ2hsaWdodElkO1xcbnVuaWZvcm0gdmVjMyBheGVzWzJdO1xcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG51bmlmb3JtIHZlYzIgc2NyZWVuU2l6ZTtcXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHNjYWxlLCBwaXhlbFJhdGlvO1xcblxcbnZhcnlpbmcgdmVjNCBpbnRlcnBDb2xvcjtcXG52YXJ5aW5nIHZlYzQgcGlja0lkO1xcbnZhcnlpbmcgdmVjMyBkYXRhQ29vcmRpbmF0ZTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBwb3NpdGlvbikpIHtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KDAsMCwwLDApO1xcbiAgfSBlbHNlIHtcXG4gICAgZmxvYXQgbHNjYWxlID0gcGl4ZWxSYXRpbyAqIHNjYWxlO1xcbiAgICBpZihkaXN0YW5jZShoaWdobGlnaHRJZCwgaWQpIDwgMC4wMDAxKSB7XFxuICAgICAgbHNjYWxlICo9IGhpZ2hsaWdodFNjYWxlO1xcbiAgICB9XFxuXFxuICAgIHZlYzQgY2xpcENlbnRlciAgID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEpO1xcbiAgICB2ZWMzIGRhdGFQb3NpdGlvbiA9IHBvc2l0aW9uICsgMC41KmxzY2FsZSooYXhlc1swXSAqIGdseXBoLnggKyBheGVzWzFdICogZ2x5cGgueSkgKiBjbGlwQ2VudGVyLncgKiBzY3JlZW5TaXplLnk7XFxuICAgIHZlYzQgY2xpcFBvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQoZGF0YVBvc2l0aW9uLCAxKTtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSBjbGlwUG9zaXRpb247XFxuICAgIGludGVycENvbG9yID0gY29sb3I7XFxuICAgIHBpY2tJZCA9IGlkO1xcbiAgICBkYXRhQ29vcmRpbmF0ZSA9IGRhdGFQb3NpdGlvbjtcXG4gIH1cXG59XFxuXCJdKVxudmFyIGRyYXdGcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyBmcmFnQ2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxuXFxudmFyeWluZyB2ZWM0IGludGVycENvbG9yO1xcbnZhcnlpbmcgdmVjNCBwaWNrSWQ7XFxudmFyeWluZyB2ZWMzIGRhdGFDb29yZGluYXRlO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGZyYWdDbGlwQm91bmRzWzBdLCBmcmFnQ2xpcEJvdW5kc1sxXSwgZGF0YUNvb3JkaW5hdGUpKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gaW50ZXJwQ29sb3IgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXG52YXIgcGlja0ZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGZyYWdDbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcGlja0dyb3VwO1xcblxcbnZhcnlpbmcgdmVjNCBwaWNrSWQ7XFxudmFyeWluZyB2ZWMzIGRhdGFDb29yZGluYXRlO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGZyYWdDbGlwQm91bmRzWzBdLCBmcmFnQ2xpcEJvdW5kc1sxXSwgZGF0YUNvb3JkaW5hdGUpKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChwaWNrR3JvdXAsIHBpY2tJZC5iZ3IpO1xcbn1cIl0pXG5cbnZhciBBVFRSSUJVVEVTID0gW1xuICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzMnfSxcbiAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J30sXG4gIHtuYW1lOiAnZ2x5cGgnLCB0eXBlOiAndmVjMid9LFxuICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfVxuXVxuXG52YXIgcGVyc3BlY3RpdmUgPSB7XG4gICAgdmVydGV4OiBwZXJzcGVjdGl2ZVZlcnRTcmMsXG4gICAgZnJhZ21lbnQ6IGRyYXdGcmFnU3JjLFxuICAgIGF0dHJpYnV0ZXM6IEFUVFJJQlVURVNcbiAgfSxcbiAgb3J0aG8gPSB7XG4gICAgdmVydGV4OiBvcnRob2dyYXBoaWNWZXJ0U3JjLFxuICAgIGZyYWdtZW50OiBkcmF3RnJhZ1NyYyxcbiAgICBhdHRyaWJ1dGVzOiBBVFRSSUJVVEVTXG4gIH0sXG4gIHByb2plY3QgPSB7XG4gICAgdmVydGV4OiBwcm9qZWN0aW9uVmVydFNyYyxcbiAgICBmcmFnbWVudDogZHJhd0ZyYWdTcmMsXG4gICAgYXR0cmlidXRlczogQVRUUklCVVRFU1xuICB9LFxuICBwaWNrUGVyc3BlY3RpdmUgPSB7XG4gICAgdmVydGV4OiBwZXJzcGVjdGl2ZVZlcnRTcmMsXG4gICAgZnJhZ21lbnQ6IHBpY2tGcmFnU3JjLFxuICAgIGF0dHJpYnV0ZXM6IEFUVFJJQlVURVNcbiAgfSxcbiAgcGlja09ydGhvID0ge1xuICAgIHZlcnRleDogb3J0aG9ncmFwaGljVmVydFNyYyxcbiAgICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXG4gICAgYXR0cmlidXRlczogQVRUUklCVVRFU1xuICB9LFxuICBwaWNrUHJvamVjdCA9IHtcbiAgICB2ZXJ0ZXg6IHByb2plY3Rpb25WZXJ0U3JjLFxuICAgIGZyYWdtZW50OiBwaWNrRnJhZ1NyYyxcbiAgICBhdHRyaWJ1dGVzOiBBVFRSSUJVVEVTXG4gIH1cblxuZnVuY3Rpb24gY3JlYXRlU2hhZGVyKGdsLCBzcmMpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcldyYXBwZXIoZ2wsIHNyYylcbiAgdmFyIGF0dHIgPSBzaGFkZXIuYXR0cmlidXRlc1xuICBhdHRyLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBhdHRyLmNvbG9yLmxvY2F0aW9uID0gMVxuICBhdHRyLmdseXBoLmxvY2F0aW9uID0gMlxuICBhdHRyLmlkLmxvY2F0aW9uID0gM1xuICByZXR1cm4gc2hhZGVyXG59XG5cbmV4cG9ydHMuY3JlYXRlUGVyc3BlY3RpdmUgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBwZXJzcGVjdGl2ZSlcbn1cbmV4cG9ydHMuY3JlYXRlT3J0aG8gPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBvcnRobylcbn1cbmV4cG9ydHMuY3JlYXRlUHJvamVjdCA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHByb2plY3QpXG59XG5leHBvcnRzLmNyZWF0ZVBpY2tQZXJzcGVjdGl2ZSA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHBpY2tQZXJzcGVjdGl2ZSlcbn1cbmV4cG9ydHMuY3JlYXRlUGlja09ydGhvID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgcGlja09ydGhvKVxufVxuZXhwb3J0cy5jcmVhdGVQaWNrUHJvamVjdCA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHBpY2tQcm9qZWN0KVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBpc0FsbEJsYW5rICAgICAgPSByZXF1aXJlKCdpcy1zdHJpbmctYmxhbmsnKVxudmFyIGNyZWF0ZUJ1ZmZlciAgICA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXG52YXIgY3JlYXRlVkFPICAgICAgID0gcmVxdWlyZSgnZ2wtdmFvJylcbnZhciBwb29sICAgICAgICAgICAgPSByZXF1aXJlKCd0eXBlZGFycmF5LXBvb2wnKVxudmFyIG1hdDRtdWx0ICAgICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvbXVsdGlwbHknKVxudmFyIHNoYWRlcnMgICAgICAgICA9IHJlcXVpcmUoJy4vbGliL3NoYWRlcnMnKVxudmFyIGdldEdseXBoICAgICAgICA9IHJlcXVpcmUoJy4vbGliL2dseXBocycpXG52YXIgZ2V0U2ltcGxlU3RyaW5nID0gcmVxdWlyZSgnLi9saWIvZ2V0LXNpbXBsZS1zdHJpbmcnKVxuXG52YXIgSURFTlRJVFkgPSBbMSwwLDAsMCxcbiAgICAgICAgICAgICAgICAwLDEsMCwwLFxuICAgICAgICAgICAgICAgIDAsMCwxLDAsXG4gICAgICAgICAgICAgICAgMCwwLDAsMV1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQb2ludENsb3VkXG5cbmZ1bmN0aW9uIHRyYW5zZm9ybU1hdDQoeCwgbSkge1xuICB2YXIgeDAgPSB4WzBdXG4gIHZhciB4MSA9IHhbMV1cbiAgdmFyIHgyID0geFsyXVxuICB2YXIgeDMgPSB4WzNdXG4gIHhbMF0gPSBtWzBdICogeDAgKyBtWzRdICogeDEgKyBtWzhdICAqIHgyICsgbVsxMl0gKiB4M1xuICB4WzFdID0gbVsxXSAqIHgwICsgbVs1XSAqIHgxICsgbVs5XSAgKiB4MiArIG1bMTNdICogeDNcbiAgeFsyXSA9IG1bMl0gKiB4MCArIG1bNl0gKiB4MSArIG1bMTBdICogeDIgKyBtWzE0XSAqIHgzXG4gIHhbM10gPSBtWzNdICogeDAgKyBtWzddICogeDEgKyBtWzExXSAqIHgyICsgbVsxNV0gKiB4M1xuICByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBwcm9qZWN0KHAsIHYsIG0sIHgpIHtcbiAgdHJhbnNmb3JtTWF0NCh4LCB4LCBtKVxuICB0cmFuc2Zvcm1NYXQ0KHgsIHgsIHYpXG4gIHJldHVybiB0cmFuc2Zvcm1NYXQ0KHgsIHgsIHApXG59XG5cbmZ1bmN0aW9uIGNsYW1wVmVjKHYpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSgzKVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBNYXRoLm1pbihNYXRoLm1heCh2W2ldLCAtMWU4KSwgMWU4KVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gU2NhdHRlclBsb3RQaWNrUmVzdWx0KGluZGV4LCBwb3NpdGlvbikge1xuICB0aGlzLmluZGV4ID0gaW5kZXhcbiAgdGhpcy5kYXRhQ29vcmRpbmF0ZSA9IHRoaXMucG9zaXRpb24gPSBwb3NpdGlvblxufVxuXG5mdW5jdGlvbiBQb2ludENsb3VkKFxuICBnbCxcbiAgc2hhZGVyLFxuICBvcnRob1NoYWRlcixcbiAgcHJvamVjdFNoYWRlcixcbiAgcG9pbnRCdWZmZXIsXG4gIGNvbG9yQnVmZmVyLFxuICBnbHlwaEJ1ZmZlcixcbiAgaWRCdWZmZXIsXG4gIHZhbyxcbiAgcGlja1BlcnNwZWN0aXZlU2hhZGVyLFxuICBwaWNrT3J0aG9TaGFkZXIsXG4gIHBpY2tQcm9qZWN0U2hhZGVyKSB7XG5cbiAgdGhpcy5nbCAgICAgICAgICAgICAgPSBnbFxuXG4gIHRoaXMucGl4ZWxSYXRpbyAgICAgID0gMVxuXG4gIHRoaXMuc2hhZGVyICAgICAgICAgID0gc2hhZGVyXG4gIHRoaXMub3J0aG9TaGFkZXIgICAgID0gb3J0aG9TaGFkZXJcbiAgdGhpcy5wcm9qZWN0U2hhZGVyICAgPSBwcm9qZWN0U2hhZGVyXG5cbiAgdGhpcy5wb2ludEJ1ZmZlciAgICAgPSBwb2ludEJ1ZmZlclxuICB0aGlzLmNvbG9yQnVmZmVyICAgICA9IGNvbG9yQnVmZmVyXG4gIHRoaXMuZ2x5cGhCdWZmZXIgICAgID0gZ2x5cGhCdWZmZXJcbiAgdGhpcy5pZEJ1ZmZlciAgICAgICAgPSBpZEJ1ZmZlclxuICB0aGlzLnZhbyAgICAgICAgICAgICA9IHZhb1xuICB0aGlzLnZlcnRleENvdW50ICAgICA9IDBcbiAgdGhpcy5saW5lVmVydGV4Q291bnQgPSAwXG5cbiAgdGhpcy5vcGFjaXR5ICAgICAgICAgPSAxLjBcblxuICB0aGlzLmxpbmVXaWR0aCAgICAgICA9IDBcbiAgdGhpcy5wcm9qZWN0U2NhbGUgICAgPSBbMi4wLzMuMCwgMi4wLzMuMCwgMi4wLzMuMF1cbiAgdGhpcy5wcm9qZWN0T3BhY2l0eSAgPSBbMSwxLDFdXG5cbiAgdGhpcy5waWNrSWQgICAgICAgICAgICAgICAgPSAwXG4gIHRoaXMucGlja1BlcnNwZWN0aXZlU2hhZGVyID0gcGlja1BlcnNwZWN0aXZlU2hhZGVyXG4gIHRoaXMucGlja09ydGhvU2hhZGVyICAgICAgID0gcGlja09ydGhvU2hhZGVyXG4gIHRoaXMucGlja1Byb2plY3RTaGFkZXIgICAgID0gcGlja1Byb2plY3RTaGFkZXJcbiAgdGhpcy5wb2ludHMgICAgICAgICAgICAgICAgPSBbXVxuXG4gIHRoaXMuX3NlbGVjdFJlc3VsdCA9IG5ldyBTY2F0dGVyUGxvdFBpY2tSZXN1bHQoMCwgWzAsMCwwXSlcblxuICB0aGlzLnVzZU9ydGhvID0gdHJ1ZVxuICB0aGlzLmJvdW5kcyAgID0gW1sgSW5maW5pdHksSW5maW5pdHksSW5maW5pdHldLFxuICAgICAgICAgICAgICAgICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXG5cbiAgLy9BeGVzIHByb2plY3Rpb25zXG4gIHRoaXMuYXhlc1Byb2plY3QgPSBbIHRydWUsIHRydWUsIHRydWUgXVxuICB0aGlzLmF4ZXNCb3VuZHMgPSBbWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSxcbiAgICAgICAgICAgICAgICAgICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV1dXG5cbiAgdGhpcy5oaWdobGlnaHRJZCAgICA9IFsxLDEsMSwxXVxuICB0aGlzLmhpZ2hsaWdodFNjYWxlID0gMlxuXG4gIHRoaXMuY2xpcEJvdW5kcyA9IFtbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldLFxuICAgICAgICAgICAgICAgICAgICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV1cblxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxufVxuXG52YXIgcHJvdG8gPSBQb2ludENsb3VkLnByb3RvdHlwZVxuXG5wcm90by5waWNrU2xvdHMgPSAxXG5cbnByb3RvLnNldFBpY2tCYXNlID0gZnVuY3Rpb24ocGlja0Jhc2UpIHtcbiAgdGhpcy5waWNrSWQgPSBwaWNrQmFzZVxufVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XG4gIGlmKHRoaXMub3BhY2l0eSA8IDEpICB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBpZih0aGlzLmF4ZXNQcm9qZWN0W2ldICYmIHRoaXMucHJvamVjdE9wYWNpdHlbaV0gPCAxKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcbiAgaWYodGhpcy5vcGFjaXR5ID49IDEpICB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBpZih0aGlzLmF4ZXNQcm9qZWN0W2ldICYmIHRoaXMucHJvamVjdE9wYWNpdHlbaV0gPj0gMSkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbnZhciBWSUVXX1NIQVBFID0gWzAsMF1cbnZhciBVX1ZFQyA9IFswLDAsMF1cbnZhciBWX1ZFQyA9IFswLDAsMF1cbnZhciBNVV9WRUMgPSBbMCwwLDAsMV1cbnZhciBNVl9WRUMgPSBbMCwwLDAsMV1cbnZhciBTQ1JBVENIX01BVFJJWCA9IElERU5USVRZLnNsaWNlKClcbnZhciBTQ1JBVENIX1ZFQyA9IFswLDAsMF1cbnZhciBDTElQX0JPVU5EUyA9IFtbMCwwLDBdLCBbMCwwLDBdXVxuXG5mdW5jdGlvbiB6ZXJvVmVjKGEpIHtcbiAgYVswXSA9IGFbMV0gPSBhWzJdID0gMFxuICByZXR1cm4gYVxufVxuXG5mdW5jdGlvbiBhdWdtZW50KGhnLCBhZikge1xuICBoZ1swXSA9IGFmWzBdXG4gIGhnWzFdID0gYWZbMV1cbiAgaGdbMl0gPSBhZlsyXVxuICBoZ1szXSA9IDFcbiAgcmV0dXJuIGhnXG59XG5cbmZ1bmN0aW9uIHNldENvbXBvbmVudChvdXQsIHYsIGksIHgpIHtcbiAgb3V0WzBdID0gdlswXVxuICBvdXRbMV0gPSB2WzFdXG4gIG91dFsyXSA9IHZbMl1cbiAgb3V0W2ldID0geFxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIGdldENsaXBCb3VuZHMoYm91bmRzKSB7XG4gIHZhciByZXN1bHQgPSBDTElQX0JPVU5EU1xuICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHJlc3VsdFtpXVtqXSA9IE1hdGgubWF4KE1hdGgubWluKGJvdW5kc1tpXVtqXSwgMWU4KSwgLTFlOClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBkcmF3UHJvamVjdChzaGFkZXIsIHBvaW50cywgY2FtZXJhLCB0cmFuc3BhcmVudCwgZm9yY2VEcmF3KSB7XG4gIHZhciBheGVzUHJvamVjdCA9IHBvaW50cy5heGVzUHJvamVjdFxuXG4gIHZhciBnbCAgICAgICAgID0gcG9pbnRzLmdsXG4gIHZhciB1bmlmb3JtcyAgID0gc2hhZGVyLnVuaWZvcm1zXG4gIHZhciBtb2RlbCAgICAgID0gY2FtZXJhLm1vZGVsICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHZpZXcgICAgICAgPSBjYW1lcmEudmlldyAgICAgICB8fCBJREVOVElUWVxuICB2YXIgcHJvamVjdGlvbiA9IGNhbWVyYS5wcm9qZWN0aW9uIHx8IElERU5USVRZXG4gIHZhciBib3VuZHMgICAgID0gcG9pbnRzLmF4ZXNCb3VuZHNcbiAgdmFyIGNsaXBCb3VuZHMgPSBnZXRDbGlwQm91bmRzKHBvaW50cy5jbGlwQm91bmRzKVxuXG4gIHZhciBjdWJlQXhpc1xuICBpZihwb2ludHMuYXhlcyAmJiBwb2ludHMuYXhlcy5sYXN0Q3ViZVByb3BzKSB7XG4gICAgY3ViZUF4aXMgPSBwb2ludHMuYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXNcbiAgfSBlbHNlIHtcbiAgICBjdWJlQXhpcyA9IFsxLDEsMV1cbiAgfVxuXG4gIFZJRVdfU0hBUEVbMF0gPSAyLjAvZ2wuZHJhd2luZ0J1ZmZlcldpZHRoXG4gIFZJRVdfU0hBUEVbMV0gPSAyLjAvZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxuXG4gIHNoYWRlci5iaW5kKClcbiAgdW5pZm9ybXMudmlldyAgICAgICAgICAgPSB2aWV3XG4gIHVuaWZvcm1zLnByb2plY3Rpb24gICAgID0gcHJvamVjdGlvblxuICB1bmlmb3Jtcy5zY3JlZW5TaXplICAgICA9IFZJRVdfU0hBUEVcbiAgdW5pZm9ybXMuaGlnaGxpZ2h0SWQgICAgPSBwb2ludHMuaGlnaGxpZ2h0SWRcbiAgdW5pZm9ybXMuaGlnaGxpZ2h0U2NhbGUgPSBwb2ludHMuaGlnaGxpZ2h0U2NhbGVcbiAgdW5pZm9ybXMuY2xpcEJvdW5kcyAgICAgPSBjbGlwQm91bmRzXG4gIHVuaWZvcm1zLnBpY2tHcm91cCAgICAgID0gcG9pbnRzLnBpY2tJZCAvIDI1NS4wXG4gIHVuaWZvcm1zLnBpeGVsUmF0aW8gICAgID0gcG9pbnRzLnBpeGVsUmF0aW9cblxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBpZighYXhlc1Byb2plY3RbaV0pIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKChwb2ludHMucHJvamVjdE9wYWNpdHlbaV0gPCAxKSAhPT0gdHJhbnNwYXJlbnQpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgdW5pZm9ybXMuc2NhbGUgICAgICAgICAgPSBwb2ludHMucHJvamVjdFNjYWxlW2ldXG4gICAgdW5pZm9ybXMub3BhY2l0eSAgICAgICAgPSBwb2ludHMucHJvamVjdE9wYWNpdHlbaV1cblxuICAgIC8vUHJvamVjdCBtb2RlbCBtYXRyaXhcbiAgICB2YXIgcG1vZGVsID0gU0NSQVRDSF9NQVRSSVhcbiAgICBmb3IodmFyIGo9MDsgajwxNjsgKytqKSB7XG4gICAgICBwbW9kZWxbal0gPSAwXG4gICAgfVxuICAgIGZvcih2YXIgaj0wOyBqPDQ7ICsraikge1xuICAgICAgcG1vZGVsWzUqal0gPSAxXG4gICAgfVxuICAgIHBtb2RlbFs1KmldID0gMFxuICAgIGlmKGN1YmVBeGlzW2ldIDwgMCkge1xuICAgICAgcG1vZGVsWzEyK2ldID0gYm91bmRzWzBdW2ldXG4gICAgfSBlbHNlIHtcbiAgICAgIHBtb2RlbFsxMitpXSA9IGJvdW5kc1sxXVtpXVxuICAgIH1cbiAgICBtYXQ0bXVsdChwbW9kZWwsIG1vZGVsLCBwbW9kZWwpXG4gICAgdW5pZm9ybXMubW9kZWwgPSBwbW9kZWxcblxuICAgIC8vQ29tcHV0ZSBpbml0aWFsIGF4ZXNcbiAgICB2YXIgdSA9IChpKzEpJTNcbiAgICB2YXIgdiA9IChpKzIpJTNcbiAgICB2YXIgZHUgPSB6ZXJvVmVjKFVfVkVDKVxuICAgIHZhciBkdiA9IHplcm9WZWMoVl9WRUMpXG4gICAgZHVbdV0gPSAxXG4gICAgZHZbdl0gPSAxXG5cbiAgICAvL0FsaWduIG9yaWVudGF0aW9uIHJlbGF0aXZlIHRvIHZpZXdlclxuICAgIHZhciBtZHUgPSBwcm9qZWN0KHByb2plY3Rpb24sIHZpZXcsIG1vZGVsLCBhdWdtZW50KE1VX1ZFQywgZHUpKVxuICAgIHZhciBtZHYgPSBwcm9qZWN0KHByb2plY3Rpb24sIHZpZXcsIG1vZGVsLCBhdWdtZW50KE1WX1ZFQywgZHYpKVxuICAgIGlmKE1hdGguYWJzKG1kdVsxXSkgPiBNYXRoLmFicyhtZHZbMV0pKSB7XG4gICAgICB2YXIgdG1wID0gbWR1XG4gICAgICBtZHUgPSBtZHZcbiAgICAgIG1kdiA9IHRtcFxuICAgICAgdG1wID0gZHVcbiAgICAgIGR1ID0gZHZcbiAgICAgIGR2ID0gdG1wXG4gICAgICB2YXIgdCA9IHVcbiAgICAgIHUgPSB2XG4gICAgICB2ID0gdFxuICAgIH1cbiAgICBpZihtZHVbMF0gPCAwKSB7XG4gICAgICBkdVt1XSA9IC0xXG4gICAgfVxuICAgIGlmKG1kdlsxXSA+IDApIHtcbiAgICAgIGR2W3ZdID0gLTFcbiAgICB9XG4gICAgdmFyIHN1ID0gMC4wXG4gICAgdmFyIHN2ID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8NDsgKytqKSB7XG4gICAgICBzdSArPSBNYXRoLnBvdyhtb2RlbFs0KnUral0sIDIpXG4gICAgICBzdiArPSBNYXRoLnBvdyhtb2RlbFs0KnYral0sIDIpXG4gICAgfVxuICAgIGR1W3VdIC89IE1hdGguc3FydChzdSlcbiAgICBkdlt2XSAvPSBNYXRoLnNxcnQoc3YpXG4gICAgdW5pZm9ybXMuYXhlc1swXSA9IGR1XG4gICAgdW5pZm9ybXMuYXhlc1sxXSA9IGR2XG5cbiAgICAvL1VwZGF0ZSBmcmFnbWVudCBjbGlwIGJvdW5kc1xuICAgIHVuaWZvcm1zLmZyYWdDbGlwQm91bmRzWzBdID0gc2V0Q29tcG9uZW50KFNDUkFUQ0hfVkVDLCBjbGlwQm91bmRzWzBdLCBpLCAtMWU4KVxuICAgIHVuaWZvcm1zLmZyYWdDbGlwQm91bmRzWzFdID0gc2V0Q29tcG9uZW50KFNDUkFUQ0hfVkVDLCBjbGlwQm91bmRzWzFdLCBpLCAxZTgpXG5cbiAgICAvL0RyYXcgaW50ZXJpb3JcbiAgICBwb2ludHMudmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCBwb2ludHMudmVydGV4Q291bnQpXG5cbiAgICAvL0RyYXcgZWRnZXNcbiAgICBpZihwb2ludHMubGluZVdpZHRoID4gMCkge1xuICAgICAgZ2wubGluZVdpZHRoKHBvaW50cy5saW5lV2lkdGgpXG4gICAgICBwb2ludHMudmFvLmRyYXcoZ2wuTElORVMsIHBvaW50cy5saW5lVmVydGV4Q291bnQsIHBvaW50cy52ZXJ0ZXhDb3VudClcbiAgICB9XG4gIH1cbn1cblxuXG52YXIgTkVHX0lORklOSVRZMyA9IFstMWU4LCAtMWU4LCAtMWU4XVxudmFyIFBPU19JTkZJTklUWTMgPSBbMWU4LCAxZTgsIDFlOF1cbnZhciBDTElQX0dST1VQICAgID0gW05FR19JTkZJTklUWTMsIFBPU19JTkZJTklUWTNdXG5cbmZ1bmN0aW9uIGRyYXdGdWxsKHNoYWRlciwgcHNoYWRlciwgcG9pbnRzLCBjYW1lcmEsIHRyYW5zcGFyZW50LCBmb3JjZURyYXcpIHtcbiAgdmFyIGdsID0gcG9pbnRzLmdsXG5cbiAgcG9pbnRzLnZhby5iaW5kKClcblxuICBpZih0cmFuc3BhcmVudCA9PT0gKHBvaW50cy5vcGFjaXR5IDwgMSkgfHwgZm9yY2VEcmF3KSB7XG4gICAgc2hhZGVyLmJpbmQoKVxuICAgIHZhciB1bmlmb3JtcyA9IHNoYWRlci51bmlmb3Jtc1xuXG4gICAgdW5pZm9ybXMubW9kZWwgICAgICA9IGNhbWVyYS5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gICAgdW5pZm9ybXMudmlldyAgICAgICA9IGNhbWVyYS52aWV3ICAgICAgIHx8IElERU5USVRZXG4gICAgdW5pZm9ybXMucHJvamVjdGlvbiA9IGNhbWVyYS5wcm9qZWN0aW9uIHx8IElERU5USVRZXG5cbiAgICBWSUVXX1NIQVBFWzBdICAgICAgID0gMi4wL2dsLmRyYXdpbmdCdWZmZXJXaWR0aFxuICAgIFZJRVdfU0hBUEVbMV0gICAgICAgPSAyLjAvZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxuICAgIHVuaWZvcm1zLnNjcmVlblNpemUgPSBWSUVXX1NIQVBFXG5cbiAgICB1bmlmb3Jtcy5oaWdobGlnaHRJZCAgICA9IHBvaW50cy5oaWdobGlnaHRJZFxuICAgIHVuaWZvcm1zLmhpZ2hsaWdodFNjYWxlID0gcG9pbnRzLmhpZ2hsaWdodFNjYWxlXG5cbiAgICB1bmlmb3Jtcy5mcmFnQ2xpcEJvdW5kcyA9IENMSVBfR1JPVVBcbiAgICB1bmlmb3Jtcy5jbGlwQm91bmRzICAgICA9IHBvaW50cy5heGVzLmJvdW5kc1xuXG4gICAgdW5pZm9ybXMub3BhY2l0eSAgICA9IHBvaW50cy5vcGFjaXR5XG4gICAgdW5pZm9ybXMucGlja0dyb3VwICA9IHBvaW50cy5waWNrSWQgLyAyNTUuMFxuXG4gICAgdW5pZm9ybXMucGl4ZWxSYXRpbyA9IHBvaW50cy5waXhlbFJhdGlvXG5cbiAgICAvL0RyYXcgaW50ZXJpb3JcbiAgICBwb2ludHMudmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCBwb2ludHMudmVydGV4Q291bnQpXG5cbiAgICAvL0RyYXcgZWRnZXNcbiAgICBpZihwb2ludHMubGluZVdpZHRoID4gMCkge1xuICAgICAgZ2wubGluZVdpZHRoKHBvaW50cy5saW5lV2lkdGgpXG4gICAgICBwb2ludHMudmFvLmRyYXcoZ2wuTElORVMsIHBvaW50cy5saW5lVmVydGV4Q291bnQsIHBvaW50cy52ZXJ0ZXhDb3VudClcbiAgICB9XG4gIH1cblxuICBkcmF3UHJvamVjdChwc2hhZGVyLCBwb2ludHMsIGNhbWVyYSwgdHJhbnNwYXJlbnQsIGZvcmNlRHJhdylcblxuICBwb2ludHMudmFvLnVuYmluZCgpXG59XG5cbnByb3RvLmRyYXcgPSBmdW5jdGlvbihjYW1lcmEpIHtcbiAgdmFyIHNoYWRlciA9IHRoaXMudXNlT3J0aG8gPyB0aGlzLm9ydGhvU2hhZGVyIDogdGhpcy5zaGFkZXJcbiAgZHJhd0Z1bGwoc2hhZGVyLCB0aGlzLnByb2plY3RTaGFkZXIsIHRoaXMsIGNhbWVyYSwgZmFsc2UsIGZhbHNlKVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBmdW5jdGlvbihjYW1lcmEpIHtcbiAgdmFyIHNoYWRlciA9IHRoaXMudXNlT3J0aG8gPyB0aGlzLm9ydGhvU2hhZGVyIDogdGhpcy5zaGFkZXJcbiAgZHJhd0Z1bGwoc2hhZGVyLCB0aGlzLnByb2plY3RTaGFkZXIsIHRoaXMsIGNhbWVyYSwgdHJ1ZSwgZmFsc2UpXG59XG5cbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24oY2FtZXJhKSB7XG4gIHZhciBzaGFkZXIgPSB0aGlzLnVzZU9ydGhvID8gdGhpcy5waWNrT3J0aG9TaGFkZXIgOiB0aGlzLnBpY2tQZXJzcGVjdGl2ZVNoYWRlclxuICBkcmF3RnVsbChzaGFkZXIsIHRoaXMucGlja1Byb2plY3RTaGFkZXIsIHRoaXMsIGNhbWVyYSwgZmFsc2UsIHRydWUpXG59XG5cbnByb3RvLnBpY2sgPSBmdW5jdGlvbihzZWxlY3RlZCkge1xuICBpZighc2VsZWN0ZWQpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmKHNlbGVjdGVkLmlkICE9PSB0aGlzLnBpY2tJZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgdmFyIHggPSBzZWxlY3RlZC52YWx1ZVsyXSArIChzZWxlY3RlZC52YWx1ZVsxXTw8OCkgKyAoc2VsZWN0ZWQudmFsdWVbMF08PDE2KVxuICBpZih4ID49IHRoaXMucG9pbnRDb3VudCB8fCB4IDwgMCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvL1VucGFjayByZXN1bHRcbiAgdmFyIGNvb3JkID0gdGhpcy5wb2ludHNbeF1cbiAgdmFyIHJlc3VsdCA9IHRoaXMuX3NlbGVjdFJlc3VsdFxuICByZXN1bHQuaW5kZXggPSB4XG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHJlc3VsdC5wb3NpdGlvbltpXSA9IHJlc3VsdC5kYXRhQ29vcmRpbmF0ZVtpXSA9IGNvb3JkW2ldXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5oaWdobGlnaHQgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgaWYoIXNlbGVjdGlvbikge1xuICAgIHRoaXMuaGlnaGxpZ2h0SWQgPSBbMSwxLDEsMV1cbiAgfSBlbHNlIHtcbiAgICB2YXIgcG9pbnRJZCA9IHNlbGVjdGlvbi5pbmRleFxuICAgIHZhciBhMCA9ICBwb2ludElkICAgICAmMHhmZlxuICAgIHZhciBhMSA9IChwb2ludElkPj44KSAmMHhmZlxuICAgIHZhciBhMiA9IChwb2ludElkPj4xNikmMHhmZlxuICAgIHRoaXMuaGlnaGxpZ2h0SWQgPSBbYTAvMjU1LjAsIGExLzI1NS4wLCBhMi8yNTUuMCwgMF1cbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRfZ2x5cGhEYXRhKGdseXBocywgaW5kZXgsIGZvbnQpIHtcbiAgdmFyIHN0clxuXG4gIC8vIHVzZSB0aGUgZGF0YSBpZiBwcmVzZW50ZWQgaW4gYW4gYXJyYXlcbiAgaWYoQXJyYXkuaXNBcnJheShnbHlwaHMpKSB7XG4gICAgaWYoaW5kZXggPCBnbHlwaHMubGVuZ3RoKSB7XG4gICAgICBzdHIgPSBnbHlwaHNbaW5kZXhdXG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IHVuZGVmaW5lZFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzdHIgPSBnbHlwaHNcbiAgfVxuXG4gIHN0ciA9IGdldFNpbXBsZVN0cmluZyhzdHIpIC8vIHRoaXMgd291bGQgaGFuZGxlIHVuZGVmaW5lZCBjYXNlc1xuXG4gIHZhciB2aXNpYmxlID0gdHJ1ZVxuICBpZihpc0FsbEJsYW5rKHN0cikpIHtcbiAgICBzdHIgPSAn4pa8JyAvLyBOb3RlOiB0aGlzIHNwZWNpYWwgY2hhcmFjdGVyIG1heSBoYXZlIG1pbmltdW0gbnVtYmVyIG9mIHN1cmZhY2VzXG4gICAgdmlzaWJsZSA9IGZhbHNlXG4gIH1cblxuICB2YXIgZ2x5cGggPSBnZXRHbHlwaChzdHIsIGZvbnQpXG5cbiAgcmV0dXJuIHsgbWVzaDpnbHlwaFswXSxcbiAgICAgICAgICBsaW5lczpnbHlwaFsxXSxcbiAgICAgICAgIGJvdW5kczpnbHlwaFsyXSxcbiAgICAgICAgdmlzaWJsZTp2aXNpYmxlIH07XG59XG5cblxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICBpZigncGVyc3BlY3RpdmUnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLnVzZU9ydGhvID0gIW9wdGlvbnMucGVyc3BlY3RpdmVcbiAgfVxuICBpZignb3J0aG9ncmFwaGljJyBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy51c2VPcnRobyA9ICEhb3B0aW9ucy5vcnRob2dyYXBoaWNcbiAgfVxuICBpZignbGluZVdpZHRoJyBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5saW5lV2lkdGggPSBvcHRpb25zLmxpbmVXaWR0aFxuICB9XG4gIGlmKCdwcm9qZWN0JyBpbiBvcHRpb25zKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShvcHRpb25zLnByb2plY3QpKSB7XG4gICAgICB0aGlzLmF4ZXNQcm9qZWN0ID0gb3B0aW9ucy5wcm9qZWN0XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB2ID0gISFvcHRpb25zLnByb2plY3RcbiAgICAgIHRoaXMuYXhlc1Byb2plY3QgPSBbdix2LHZdXG4gICAgfVxuICB9XG4gIGlmKCdwcm9qZWN0U2NhbGUnIGluIG9wdGlvbnMpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KG9wdGlvbnMucHJvamVjdFNjYWxlKSkge1xuICAgICAgdGhpcy5wcm9qZWN0U2NhbGUgPSBvcHRpb25zLnByb2plY3RTY2FsZS5zbGljZSgpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBzID0gK29wdGlvbnMucHJvamVjdFNjYWxlXG4gICAgICB0aGlzLnByb2plY3RTY2FsZSA9IFtzLHMsc11cbiAgICB9XG4gIH1cbiAgaWYoJ3Byb2plY3RPcGFjaXR5JyBpbiBvcHRpb25zKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShvcHRpb25zLnByb2plY3RPcGFjaXR5KSkge1xuICAgICAgdGhpcy5wcm9qZWN0T3BhY2l0eSA9IG9wdGlvbnMucHJvamVjdE9wYWNpdHkuc2xpY2UoKVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgcyA9ICtvcHRpb25zLnByb2plY3RPcGFjaXR5XG4gICAgICB0aGlzLnByb2plY3RPcGFjaXR5ID0gW3MscyxzXVxuICAgIH1cbiAgfVxuICBpZignb3BhY2l0eScgaW4gb3B0aW9ucykge1xuICAgIHRoaXMub3BhY2l0eSA9IG9wdGlvbnMub3BhY2l0eVxuICB9XG5cbiAgLy9TZXQgZGlydHkgZmxhZ1xuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuXG4gIC8vQ3JlYXRlIG5ldyBidWZmZXJzXG4gIHZhciBwb2ludHMgPSBvcHRpb25zLnBvc2l0aW9uXG5cbiAgLy9UZXh0IGZvbnRcbiAgdmFyIGZvbnQgICAgICA9IG9wdGlvbnMuZm9udCAgICAgIHx8ICdub3JtYWwnXG4gIHZhciBhbGlnbm1lbnQgPSBvcHRpb25zLmFsaWdubWVudCB8fCBbMCwwXVxuXG4gIC8vQm91bmRzXG4gIHZhciBsb3dlckJvdW5kID0gWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XVxuICB2YXIgdXBwZXJCb3VuZCA9IFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1cblxuICAvL1VucGFjayBvcHRpb25zXG4gIHZhciBnbHlwaHMgICAgID0gb3B0aW9ucy5nbHlwaFxuICB2YXIgY29sb3JzICAgICA9IG9wdGlvbnMuY29sb3JcbiAgdmFyIHNpemVzICAgICAgPSBvcHRpb25zLnNpemVcbiAgdmFyIGFuZ2xlcyAgICAgPSBvcHRpb25zLmFuZ2xlXG4gIHZhciBsaW5lQ29sb3JzID0gb3B0aW9ucy5saW5lQ29sb3JcblxuICAvL1BpY2tpbmcgZ2VvbWV0cnlcbiAgdmFyIHBpY2tDb3VudGVyID0gLTFcblxuICAvL0ZpcnN0IGRvIHBhc3MgdG8gY29tcHV0ZSBidWZmZXIgc2l6ZXNcbiAgdmFyIHRyaVZlcnRleENvdW50ICA9IDBcbiAgdmFyIGxpbmVWZXJ0ZXhDb3VudCA9IDBcblxuICB2YXIgbnVtUG9pbnRzID0gMDtcblxuICBpZihwb2ludHMubGVuZ3RoKSB7XG5cbiAgICAvL0NvdW50IG51bWJlciBvZiBwb2ludHMgYW5kIGJ1ZmZlciBzaXplXG4gICAgbnVtUG9pbnRzID0gcG9pbnRzLmxlbmd0aFxuXG4gIGNvdW50X2xvb3A6XG4gICAgZm9yKHZhciBpPTA7IGk8bnVtUG9pbnRzOyArK2kpIHtcbiAgICAgIHZhciB4ID0gcG9pbnRzW2ldXG4gICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgaWYoaXNOYU4oeFtqXSkgfHwgIWlzRmluaXRlKHhbal0pKSB7XG4gICAgICAgICAgY29udGludWUgY291bnRfbG9vcFxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBnbHlwaERhdGEgPSBnZXRfZ2x5cGhEYXRhKGdseXBocywgaSwgZm9udClcblxuICAgICAgdmFyIGdseXBoTWVzaCAgID0gZ2x5cGhEYXRhLm1lc2hcbiAgICAgIHZhciBnbHlwaExpbmVzICA9IGdseXBoRGF0YS5saW5lc1xuICAgICAgdmFyIGdseXBoQm91bmRzID0gZ2x5cGhEYXRhLmJvdW5kc1xuXG4gICAgICB0cmlWZXJ0ZXhDb3VudCAgKz0gZ2x5cGhNZXNoLmNlbGxzLmxlbmd0aCAqIDNcbiAgICAgIGxpbmVWZXJ0ZXhDb3VudCArPSBnbHlwaExpbmVzLmVkZ2VzLmxlbmd0aCAqIDJcbiAgICB9XG4gIH1cblxuICB2YXIgdmVydGV4Q291bnQgICA9IHRyaVZlcnRleENvdW50ICsgbGluZVZlcnRleENvdW50XG5cbiAgLy9QcmVhbGxvY2F0ZSBkYXRhXG4gIHZhciBwb3NpdGlvbkFycmF5ID0gcG9vbC5tYWxsb2NGbG9hdCgzKnZlcnRleENvdW50KVxuICB2YXIgY29sb3JBcnJheSAgICA9IHBvb2wubWFsbG9jRmxvYXQoNCp2ZXJ0ZXhDb3VudClcbiAgdmFyIGdseXBoQXJyYXkgICAgPSBwb29sLm1hbGxvY0Zsb2F0KDIqdmVydGV4Q291bnQpXG4gIHZhciBpZEFycmF5ICAgICAgID0gcG9vbC5tYWxsb2NVaW50MzIodmVydGV4Q291bnQpXG5cbiAgaWYodmVydGV4Q291bnQgPiAwKSB7XG4gICAgdmFyIHRyaU9mZnNldCAgPSAwXG4gICAgdmFyIGxpbmVPZmZzZXQgPSB0cmlWZXJ0ZXhDb3VudFxuICAgIHZhciBjb2xvciAgICAgID0gWzAsMCwwLDFdXG4gICAgdmFyIGxpbmVDb2xvciAgPSBbMCwwLDAsMV1cblxuICAgIHZhciBpc0NvbG9yQXJyYXkgICAgICA9IEFycmF5LmlzQXJyYXkoY29sb3JzKSAgICAgJiYgQXJyYXkuaXNBcnJheShjb2xvcnNbMF0pXG4gICAgdmFyIGlzTGluZUNvbG9yQXJyYXkgID0gQXJyYXkuaXNBcnJheShsaW5lQ29sb3JzKSAmJiBBcnJheS5pc0FycmF5KGxpbmVDb2xvcnNbMF0pXG5cbiAgZmlsbF9sb29wOlxuICAgIGZvcih2YXIgaT0wOyBpPG51bVBvaW50czsgKytpKSB7XG4gICAgICAvL0luY3JlbWVudCBwaWNrQ291bnRlclxuICAgICAgcGlja0NvdW50ZXIgKz0gMVxuXG4gICAgICB2YXIgeCA9IHBvaW50c1tpXVxuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgIGlmKGlzTmFOKHhbal0pIHx8ICFpc0Zpbml0ZSh4W2pdKSkge1xuICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICB9XG5cbiAgICAgICAgdXBwZXJCb3VuZFtqXSA9IE1hdGgubWF4KHVwcGVyQm91bmRbal0sIHhbal0pXG4gICAgICAgIGxvd2VyQm91bmRbal0gPSBNYXRoLm1pbihsb3dlckJvdW5kW2pdLCB4W2pdKVxuICAgICAgfVxuXG4gICAgICB2YXIgZ2x5cGhEYXRhID0gZ2V0X2dseXBoRGF0YShnbHlwaHMsIGksIGZvbnQpXG5cbiAgICAgIHZhciBnbHlwaE1lc2ggICA9IGdseXBoRGF0YS5tZXNoXG4gICAgICB2YXIgZ2x5cGhMaW5lcyAgPSBnbHlwaERhdGEubGluZXNcbiAgICAgIHZhciBnbHlwaEJvdW5kcyA9IGdseXBoRGF0YS5ib3VuZHNcbiAgICAgIHZhciBnbHlwaFZpc2libGUgPSBnbHlwaERhdGEudmlzaWJsZVxuXG4gICAgICAvL0dldCBjb2xvclxuICAgICAgaWYoIWdseXBoVmlzaWJsZSkgY29sb3IgPSBbMSwxLDEsMF1cbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShjb2xvcnMpKSB7XG4gICAgICAgIHZhciBjXG4gICAgICAgIGlmKGlzQ29sb3JBcnJheSkge1xuICAgICAgICAgIGlmKGkgPCBjb2xvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjID0gY29sb3JzW2ldXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMgPSBbMCwwLDAsMF1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYyA9IGNvbG9yc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgICAgIGNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb2xvclszXSA9IDFcbiAgICAgICAgfSBlbHNlIGlmKGMubGVuZ3RoID09PSA0KSB7XG4gICAgICAgICAgZm9yKHZhciBqPTA7IGo8NDsgKytqKSB7XG4gICAgICAgICAgICBjb2xvcltqXSA9IGNbal1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbG9yWzBdID0gY29sb3JbMV0gPSBjb2xvclsyXSA9IDBcbiAgICAgICAgY29sb3JbM10gPSAxXG4gICAgICB9XG5cblxuICAgICAgLy9HZXQgbGluZUNvbG9yXG4gICAgICBpZighZ2x5cGhWaXNpYmxlKSBsaW5lQ29sb3IgPSBbMSwxLDEsMF1cbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShsaW5lQ29sb3JzKSkge1xuICAgICAgICB2YXIgY1xuICAgICAgICBpZihpc0xpbmVDb2xvckFycmF5KSB7XG4gICAgICAgICAgaWYoaSA8IGxpbmVDb2xvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjID0gbGluZUNvbG9yc1tpXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjID0gWzAsMCwwLDBdXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGMgPSBsaW5lQ29sb3JzXG4gICAgICAgIH1cblxuICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICAgICAgbGluZUNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBsaW5lQ29sb3Jbal0gPSAxXG4gICAgICAgIH0gZWxzZSBpZihjLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPDQ7ICsraikge1xuICAgICAgICAgICAgbGluZUNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGluZUNvbG9yWzBdID0gbGluZUNvbG9yWzFdID0gbGluZUNvbG9yWzJdID0gMFxuICAgICAgICBsaW5lQ29sb3JbM10gPSAxXG4gICAgICB9XG5cblxuICAgICAgdmFyIHNpemUgPSAwLjVcbiAgICAgIGlmKCFnbHlwaFZpc2libGUpIHNpemUgPSAwLjBcbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShzaXplcykpIHtcbiAgICAgICAgaWYoaSA8IHNpemVzLmxlbmd0aCkge1xuICAgICAgICAgIHNpemUgPSArc2l6ZXNbaV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzaXplID0gMTJcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmKHNpemVzKSB7XG4gICAgICAgIHNpemUgPSArc2l6ZXNcbiAgICAgIH0gZWxzZSBpZih0aGlzLnVzZU9ydGhvKSB7XG4gICAgICAgIHNpemUgPSAxMlxuICAgICAgfVxuXG5cbiAgICAgIHZhciBhbmdsZSA9IDBcbiAgICAgIGlmKEFycmF5LmlzQXJyYXkoYW5nbGVzKSkge1xuICAgICAgICBpZihpIDwgYW5nbGVzLmxlbmd0aCkge1xuICAgICAgICAgIGFuZ2xlID0gK2FuZ2xlc1tpXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFuZ2xlID0gMFxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoYW5nbGVzKSB7XG4gICAgICAgIGFuZ2xlID0gK2FuZ2xlc1xuICAgICAgfVxuXG4gICAgICAvL0xvb3AgdGhyb3VnaCBtYXJrZXJzIGFuZCBhcHBlbmQgdG8gYnVmZmVyc1xuICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKVxuICAgICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKVxuXG4gICAgICB2YXIgeCA9IHBvaW50c1tpXVxuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgIHVwcGVyQm91bmRbal0gPSBNYXRoLm1heCh1cHBlckJvdW5kW2pdLCB4W2pdKVxuICAgICAgICBsb3dlckJvdW5kW2pdID0gTWF0aC5taW4obG93ZXJCb3VuZFtqXSwgeFtqXSlcbiAgICAgIH1cblxuICAgICAgLy9DYWxjdWxhdGUgdGV4dCBvZmZzZXRcbiAgICAgIHZhciB0ZXh0T2Zmc2V0ID0gW2FsaWdubWVudFswXSwgYWxpZ25tZW50WzFdXVxuICAgICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICAgIGlmKGFsaWdubWVudFtqXSA+IDApIHtcbiAgICAgICAgICB0ZXh0T2Zmc2V0W2pdICo9ICgxLWdseXBoQm91bmRzWzBdW2pdKVxuICAgICAgICB9IGVsc2UgaWYoYWxpZ25tZW50W2pdIDwgMCkge1xuICAgICAgICAgIHRleHRPZmZzZXRbal0gKj0gKDErZ2x5cGhCb3VuZHNbMV1bal0pXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy9Xcml0ZSBvdXQgaW5uZXIgbWFya2VyXG4gICAgICB2YXIgY2VsbHMgPSBnbHlwaE1lc2guY2VsbHMgfHwgW11cbiAgICAgIHZhciB2ZXJ0cyA9IGdseXBoTWVzaC5wb3NpdGlvbnMgfHwgW11cblxuICAgICAgZm9yKHZhciBqPTA7IGo8Y2VsbHMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGNlbGwgPSBjZWxsc1tqXVxuICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgICBmb3IodmFyIGw9MDsgbDwzOyArK2wpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uQXJyYXlbMyp0cmlPZmZzZXQrbF0gPSB4W2xdXG4gICAgICAgICAgfVxuICAgICAgICAgIGZvcih2YXIgbD0wOyBsPDQ7ICsrbCkge1xuICAgICAgICAgICAgY29sb3JBcnJheVs0KnRyaU9mZnNldCtsXSA9IGNvbG9yW2xdXG4gICAgICAgICAgfVxuICAgICAgICAgIGlkQXJyYXlbdHJpT2Zmc2V0XSA9IHBpY2tDb3VudGVyXG4gICAgICAgICAgdmFyIHAgPSB2ZXJ0c1tjZWxsW2tdXVxuICAgICAgICAgIGdseXBoQXJyYXlbMip0cmlPZmZzZXRdICAgPSBzaXplICogKGNvcypwWzBdIC0gc2luKnBbMV0gKyB0ZXh0T2Zmc2V0WzBdKVxuICAgICAgICAgIGdseXBoQXJyYXlbMip0cmlPZmZzZXQrMV0gPSBzaXplICogKHNpbipwWzBdICsgY29zKnBbMV0gKyB0ZXh0T2Zmc2V0WzFdKVxuICAgICAgICAgIHRyaU9mZnNldCArPSAxXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIGNlbGxzID0gZ2x5cGhMaW5lcy5lZGdlc1xuICAgICAgdmFyIHZlcnRzID0gZ2x5cGhMaW5lcy5wb3NpdGlvbnNcblxuICAgICAgZm9yKHZhciBqPTA7IGo8Y2VsbHMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGNlbGwgPSBjZWxsc1tqXVxuICAgICAgICBmb3IodmFyIGs9MDsgazwyOyArK2spIHtcbiAgICAgICAgICBmb3IodmFyIGw9MDsgbDwzOyArK2wpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uQXJyYXlbMypsaW5lT2Zmc2V0K2xdID0geFtsXVxuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IodmFyIGw9MDsgbDw0OyArK2wpIHtcbiAgICAgICAgICAgIGNvbG9yQXJyYXlbNCpsaW5lT2Zmc2V0K2xdID0gbGluZUNvbG9yW2xdXG4gICAgICAgICAgfVxuICAgICAgICAgIGlkQXJyYXlbbGluZU9mZnNldF0gPSBwaWNrQ291bnRlclxuICAgICAgICAgIHZhciBwID0gdmVydHNbY2VsbFtrXV1cbiAgICAgICAgICBnbHlwaEFycmF5WzIqbGluZU9mZnNldF0gICA9IHNpemUgKiAoY29zKnBbMF0gLSBzaW4qcFsxXSArIHRleHRPZmZzZXRbMF0pXG4gICAgICAgICAgZ2x5cGhBcnJheVsyKmxpbmVPZmZzZXQrMV0gPSBzaXplICogKHNpbipwWzBdICsgY29zKnBbMV0gKyB0ZXh0T2Zmc2V0WzFdKVxuICAgICAgICAgIGxpbmVPZmZzZXQgKz0gMVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICB9XG5cblxuXG4gIH1cblxuICAvL1VwZGF0ZSBib3VuZHNcbiAgdGhpcy5ib3VuZHMgPSBbbG93ZXJCb3VuZCwgdXBwZXJCb3VuZF1cblxuICAvL1NhdmUgcG9pbnRzXG4gIHRoaXMucG9pbnRzID0gcG9pbnRzXG5cbiAgLy9TYXZlIG51bWJlciBvZiBwb2ludHNcbiAgdGhpcy5wb2ludENvdW50ID0gcG9pbnRzLmxlbmd0aFxuXG4gIC8vVXBkYXRlIHZlcnRleCBjb3VudHNcbiAgdGhpcy52ZXJ0ZXhDb3VudCAgICAgID0gdHJpVmVydGV4Q291bnRcbiAgdGhpcy5saW5lVmVydGV4Q291bnQgID0gbGluZVZlcnRleENvdW50XG5cbiAgdGhpcy5wb2ludEJ1ZmZlci51cGRhdGUocG9zaXRpb25BcnJheSlcbiAgdGhpcy5jb2xvckJ1ZmZlci51cGRhdGUoY29sb3JBcnJheSlcbiAgdGhpcy5nbHlwaEJ1ZmZlci51cGRhdGUoZ2x5cGhBcnJheSlcbiAgLy90aGlzLmlkQnVmZmVyLnVwZGF0ZShuZXcgVWludDMyQXJyYXkoaWRBcnJheSkpXG4gIHRoaXMuaWRCdWZmZXIudXBkYXRlKGlkQXJyYXkpXG5cbiAgcG9vbC5mcmVlKHBvc2l0aW9uQXJyYXkpXG4gIHBvb2wuZnJlZShjb2xvckFycmF5KVxuICBwb29sLmZyZWUoZ2x5cGhBcnJheSlcbiAgcG9vbC5mcmVlKGlkQXJyYXkpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgLy9TaGFkZXJzXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLm9ydGhvU2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnBpY2tQZXJzcGVjdGl2ZVNoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5waWNrT3J0aG9TaGFkZXIuZGlzcG9zZSgpXG5cbiAgLy9WZXJ0ZXggYXJyYXlcbiAgdGhpcy52YW8uZGlzcG9zZSgpXG5cbiAgLy9CdWZmZXJzXG4gIHRoaXMucG9pbnRCdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuY29sb3JCdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuZ2x5cGhCdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuaWRCdWZmZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBvaW50Q2xvdWQob3B0aW9ucykge1xuICB2YXIgZ2wgPSBvcHRpb25zLmdsXG5cbiAgdmFyIHNoYWRlciAgICAgICAgICAgICAgICA9IHNoYWRlcnMuY3JlYXRlUGVyc3BlY3RpdmUoZ2wpXG4gIHZhciBvcnRob1NoYWRlciAgICAgICAgICAgPSBzaGFkZXJzLmNyZWF0ZU9ydGhvKGdsKVxuICB2YXIgcHJvamVjdFNoYWRlciAgICAgICAgID0gc2hhZGVycy5jcmVhdGVQcm9qZWN0KGdsKVxuICB2YXIgcGlja1BlcnNwZWN0aXZlU2hhZGVyID0gc2hhZGVycy5jcmVhdGVQaWNrUGVyc3BlY3RpdmUoZ2wpXG4gIHZhciBwaWNrT3J0aG9TaGFkZXIgICAgICAgPSBzaGFkZXJzLmNyZWF0ZVBpY2tPcnRobyhnbClcbiAgdmFyIHBpY2tQcm9qZWN0U2hhZGVyICAgICA9IHNoYWRlcnMuY3JlYXRlUGlja1Byb2plY3QoZ2wpXG5cbiAgdmFyIHBvaW50QnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgY29sb3JCdWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBnbHlwaEJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGlkQnVmZmVyICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdmFvID0gY3JlYXRlVkFPKGdsLCBbXG4gICAge1xuICAgICAgYnVmZmVyOiBwb2ludEJ1ZmZlcixcbiAgICAgIHNpemU6IDMsXG4gICAgICB0eXBlOiBnbC5GTE9BVFxuICAgIH0sXG4gICAge1xuICAgICAgYnVmZmVyOiBjb2xvckJ1ZmZlcixcbiAgICAgIHNpemU6IDQsXG4gICAgICB0eXBlOiBnbC5GTE9BVFxuICAgIH0sXG4gICAge1xuICAgICAgYnVmZmVyOiBnbHlwaEJ1ZmZlcixcbiAgICAgIHNpemU6IDIsXG4gICAgICB0eXBlOiBnbC5GTE9BVFxuICAgIH0sXG4gICAge1xuICAgICAgYnVmZmVyOiBpZEJ1ZmZlcixcbiAgICAgIHNpemU6IDQsXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxuICAgIH1cbiAgXSlcblxuICB2YXIgcG9pbnRDbG91ZCA9IG5ldyBQb2ludENsb3VkKFxuICAgIGdsLFxuICAgIHNoYWRlcixcbiAgICBvcnRob1NoYWRlcixcbiAgICBwcm9qZWN0U2hhZGVyLFxuICAgIHBvaW50QnVmZmVyLFxuICAgIGNvbG9yQnVmZmVyLFxuICAgIGdseXBoQnVmZmVyLFxuICAgIGlkQnVmZmVyLFxuICAgIHZhbyxcbiAgICBwaWNrUGVyc3BlY3RpdmVTaGFkZXIsXG4gICAgcGlja09ydGhvU2hhZGVyLFxuICAgIHBpY2tQcm9qZWN0U2hhZGVyKVxuXG4gIHBvaW50Q2xvdWQudXBkYXRlKG9wdGlvbnMpXG5cbiAgcmV0dXJuIHBvaW50Q2xvdWRcbn1cbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGdsc2xpZnkgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxuXHJcbmV4cG9ydHMuYm94VmVydGV4ID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIHZlcnRleDtcXG5cXG51bmlmb3JtIHZlYzIgY29ybmVyQSwgY29ybmVyQjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQobWl4KGNvcm5lckEsIGNvcm5lckIsIHZlcnRleCksIDAsIDEpO1xcbn1cXG5cIl0pXHJcbmV4cG9ydHMuYm94RnJhZ21lbnQgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSB2ZWM0IGNvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbn1cXG5cIl0pXHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcbnZhciBjcmVhdGVCdWZmZXIgPSByZXF1aXJlKCdnbC1idWZmZXInKVxyXG5cclxudmFyIFNIQURFUlMgPSByZXF1aXJlKCcuL2xpYi9zaGFkZXJzJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2VsZWN0Qm94XHJcblxyXG5mdW5jdGlvbiBTZWxlY3RCb3gocGxvdCwgYm94QnVmZmVyLCBib3hTaGFkZXIpIHtcclxuICB0aGlzLnBsb3QgPSBwbG90XHJcbiAgdGhpcy5ib3hCdWZmZXIgPSBib3hCdWZmZXJcclxuICB0aGlzLmJveFNoYWRlciA9IGJveFNoYWRlclxyXG5cclxuICB0aGlzLmVuYWJsZWQgPSB0cnVlXHJcblxyXG4gIHRoaXMuc2VsZWN0Qm94ID0gW0luZmluaXR5LEluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldXHJcblxyXG4gIHRoaXMuYm9yZGVyQ29sb3IgPSBbMCwwLDAsMV1cclxuICB0aGlzLmlubmVyRmlsbCAgID0gZmFsc2VcclxuICB0aGlzLmlubmVyQ29sb3IgID0gWzAsMCwwLDAuMjVdXHJcbiAgdGhpcy5vdXRlckZpbGwgICA9IHRydWVcclxuICB0aGlzLm91dGVyQ29sb3IgID0gWzAsMCwwLDAuNV1cclxuICB0aGlzLmJvcmRlcldpZHRoID0gMTBcclxufVxyXG5cclxudmFyIHByb3RvID0gU2VsZWN0Qm94LnByb3RvdHlwZVxyXG5cclxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKCkge1xyXG4gIGlmKCF0aGlzLmVuYWJsZWQpIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgdmFyIHBsb3QgICAgICAgICA9IHRoaXMucGxvdFxyXG4gIHZhciBzZWxlY3RCb3ggICAgPSB0aGlzLnNlbGVjdEJveFxyXG4gIHZhciBsaW5lV2lkdGggICAgPSB0aGlzLmJvcmRlcldpZHRoXHJcblxyXG4gIHZhciBpbm5lckZpbGwgICAgPSB0aGlzLmlubmVyRmlsbFxyXG4gIHZhciBpbm5lckNvbG9yICAgPSB0aGlzLmlubmVyQ29sb3JcclxuICB2YXIgb3V0ZXJGaWxsICAgID0gdGhpcy5vdXRlckZpbGxcclxuICB2YXIgb3V0ZXJDb2xvciAgID0gdGhpcy5vdXRlckNvbG9yXHJcbiAgdmFyIGJvcmRlckNvbG9yICA9IHRoaXMuYm9yZGVyQ29sb3JcclxuXHJcbiAgdmFyIGJveGVzICAgICAgICA9IHBsb3QuYm94XHJcbiAgdmFyIHNjcmVlbkJveCAgICA9IHBsb3Quc2NyZWVuQm94XHJcbiAgdmFyIGRhdGFCb3ggICAgICA9IHBsb3QuZGF0YUJveFxyXG4gIHZhciB2aWV3Qm94ICAgICAgPSBwbG90LnZpZXdCb3hcclxuICB2YXIgcGl4ZWxSYXRpbyAgID0gcGxvdC5waXhlbFJhdGlvXHJcblxyXG4gIC8vTWFwIHNlbGVjdCBib3ggaW50byBwaXhlbCBjb29yZGluYXRlc1xyXG4gIHZhciBsb1ggPSAoc2VsZWN0Qm94WzBdLWRhdGFCb3hbMF0pKih2aWV3Qm94WzJdLXZpZXdCb3hbMF0pLyhkYXRhQm94WzJdLWRhdGFCb3hbMF0pK3ZpZXdCb3hbMF1cclxuICB2YXIgbG9ZID0gKHNlbGVjdEJveFsxXS1kYXRhQm94WzFdKSoodmlld0JveFszXS12aWV3Qm94WzFdKS8oZGF0YUJveFszXS1kYXRhQm94WzFdKSt2aWV3Qm94WzFdXHJcbiAgdmFyIGhpWCA9IChzZWxlY3RCb3hbMl0tZGF0YUJveFswXSkqKHZpZXdCb3hbMl0tdmlld0JveFswXSkvKGRhdGFCb3hbMl0tZGF0YUJveFswXSkrdmlld0JveFswXVxyXG4gIHZhciBoaVkgPSAoc2VsZWN0Qm94WzNdLWRhdGFCb3hbMV0pKih2aWV3Qm94WzNdLXZpZXdCb3hbMV0pLyhkYXRhQm94WzNdLWRhdGFCb3hbMV0pK3ZpZXdCb3hbMV1cclxuXHJcbiAgbG9YID0gTWF0aC5tYXgobG9YLCB2aWV3Qm94WzBdKVxyXG4gIGxvWSA9IE1hdGgubWF4KGxvWSwgdmlld0JveFsxXSlcclxuICBoaVggPSBNYXRoLm1pbihoaVgsIHZpZXdCb3hbMl0pXHJcbiAgaGlZID0gTWF0aC5taW4oaGlZLCB2aWV3Qm94WzNdKVxyXG5cclxuICBpZihoaVggPCBsb1ggfHwgaGlZIDwgbG9ZKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGJveGVzLmJpbmQoKVxyXG5cclxuICAvL0RyYXcgYm94XHJcbiAgdmFyIHNjcmVlbldpZHRoICA9IHNjcmVlbkJveFsyXSAtIHNjcmVlbkJveFswXVxyXG4gIHZhciBzY3JlZW5IZWlnaHQgPSBzY3JlZW5Cb3hbM10gLSBzY3JlZW5Cb3hbMV1cclxuXHJcbiAgaWYodGhpcy5vdXRlckZpbGwpIHtcclxuICAgIGJveGVzLmRyYXdCb3goMCwgMCwgc2NyZWVuV2lkdGgsIGxvWSwgb3V0ZXJDb2xvcilcclxuICAgIGJveGVzLmRyYXdCb3goMCwgbG9ZLCBsb1gsIGhpWSwgb3V0ZXJDb2xvcilcclxuICAgIGJveGVzLmRyYXdCb3goMCwgaGlZLCBzY3JlZW5XaWR0aCwgc2NyZWVuSGVpZ2h0LCBvdXRlckNvbG9yKVxyXG4gICAgYm94ZXMuZHJhd0JveChoaVgsIGxvWSwgc2NyZWVuV2lkdGgsIGhpWSwgb3V0ZXJDb2xvcilcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuaW5uZXJGaWxsKSB7XHJcbiAgICBib3hlcy5kcmF3Qm94KGxvWCwgbG9ZLCBoaVgsIGhpWSwgaW5uZXJDb2xvcilcclxuICB9XHJcblxyXG4gIC8vRHJhdyBib3JkZXJcclxuICBpZihsaW5lV2lkdGggPiAwKSB7XHJcblxyXG4gICAgLy9EcmF3IGJvcmRlclxyXG4gICAgdmFyIHcgPSBsaW5lV2lkdGggKiBwaXhlbFJhdGlvXHJcbiAgICBib3hlcy5kcmF3Qm94KGxvWC13LCBsb1ktdywgaGlYK3csIGxvWSt3LCBib3JkZXJDb2xvcilcclxuICAgIGJveGVzLmRyYXdCb3gobG9YLXcsIGhpWS13LCBoaVgrdywgaGlZK3csIGJvcmRlckNvbG9yKVxyXG4gICAgYm94ZXMuZHJhd0JveChsb1gtdywgbG9ZLXcsIGxvWCt3LCBoaVkrdywgYm9yZGVyQ29sb3IpXHJcbiAgICBib3hlcy5kcmF3Qm94KGhpWC13LCBsb1ktdywgaGlYK3csIGhpWSt3LCBib3JkZXJDb2xvcilcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcclxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxyXG5cclxuICB0aGlzLmlubmVyRmlsbCAgICA9ICEhb3B0aW9ucy5pbm5lckZpbGxcclxuICB0aGlzLm91dGVyRmlsbCAgICA9ICEhb3B0aW9ucy5vdXRlckZpbGxcclxuICB0aGlzLmlubmVyQ29sb3IgICA9IChvcHRpb25zLmlubmVyQ29sb3IgICB8fCBbMCwwLDAsMC41XSkuc2xpY2UoKVxyXG4gIHRoaXMub3V0ZXJDb2xvciAgID0gKG9wdGlvbnMub3V0ZXJDb2xvciAgIHx8IFswLDAsMCwwLjVdKS5zbGljZSgpXHJcbiAgdGhpcy5ib3JkZXJDb2xvciAgPSAob3B0aW9ucy5ib3JkZXJDb2xvciB8fCBbMCwwLDAsMV0pLnNsaWNlKClcclxuICB0aGlzLmJvcmRlcldpZHRoICA9IG9wdGlvbnMuYm9yZGVyV2lkdGggfHwgMFxyXG4gIHRoaXMuc2VsZWN0Qm94ICAgID0gKG9wdGlvbnMuc2VsZWN0Qm94IHx8IHRoaXMuc2VsZWN0Qm94KS5zbGljZSgpXHJcbn1cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLmJveEJ1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLmJveFNoYWRlci5kaXNwb3NlKClcclxuICB0aGlzLnBsb3QucmVtb3ZlT3ZlcmxheSh0aGlzKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVTZWxlY3RCb3gocGxvdCwgb3B0aW9ucykge1xyXG4gIHZhciBnbCA9IHBsb3QuZ2xcclxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsLCBbXHJcbiAgICAwLCAwLFxyXG4gICAgMCwgMSxcclxuICAgIDEsIDAsXHJcbiAgICAxLCAxIF0pXHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgU0hBREVSUy5ib3hWZXJ0ZXgsIFNIQURFUlMuYm94RnJhZ21lbnQpXHJcbiAgdmFyIHNlbGVjdEJveCA9IG5ldyBTZWxlY3RCb3gocGxvdCwgYnVmZmVyLCBzaGFkZXIpXHJcbiAgc2VsZWN0Qm94LnVwZGF0ZShvcHRpb25zKVxyXG4gIHBsb3QuYWRkT3ZlcmxheShzZWxlY3RCb3gpXHJcbiAgcmV0dXJuIHNlbGVjdEJveFxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNlbGVjdEJ1ZmZlclxuXG52YXIgY3JlYXRlRkJPID0gcmVxdWlyZSgnZ2wtZmJvJylcbnZhciBwb29sICAgICAgPSByZXF1aXJlKCd0eXBlZGFycmF5LXBvb2wnKVxudmFyIG5kYXJyYXkgICA9IHJlcXVpcmUoJ25kYXJyYXknKVxuXG52YXIgbmV4dFBvdzIgID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKS5uZXh0UG93MlxuXG52YXIgc2VsZWN0UmFuZ2UgPSByZXF1aXJlKCdjd2lzZS9saWIvd3JhcHBlcicpKHtcImFyZ3NcIjpbXCJhcnJheVwiLHtcIm9mZnNldFwiOlswLDAsMV0sXCJhcnJheVwiOjB9LHtcIm9mZnNldFwiOlswLDAsMl0sXCJhcnJheVwiOjB9LHtcIm9mZnNldFwiOlswLDAsM10sXCJhcnJheVwiOjB9LFwic2NhbGFyXCIsXCJzY2FsYXJcIixcImluZGV4XCJdLFwicHJlXCI6e1wiYm9keVwiOlwie3RoaXNfY2xvc2VzdEQyPTFlOCx0aGlzX2Nsb3Nlc3RYPS0xLHRoaXNfY2xvc2VzdFk9LTF9XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltcInRoaXNfY2xvc2VzdEQyXCIsXCJ0aGlzX2Nsb3Nlc3RYXCIsXCJ0aGlzX2Nsb3Nlc3RZXCJdLFwibG9jYWxWYXJzXCI6W119LFwiYm9keVwiOntcImJvZHlcIjpcIntpZihfaW5saW5lXzE2X2FyZzBfPDI1NXx8X2lubGluZV8xNl9hcmcxXzwyNTV8fF9pbmxpbmVfMTZfYXJnMl88MjU1fHxfaW5saW5lXzE2X2FyZzNfPDI1NSl7dmFyIF9pbmxpbmVfMTZfbD1faW5saW5lXzE2X2FyZzRfLV9pbmxpbmVfMTZfYXJnNl9bMF0sX2lubGluZV8xNl9hPV9pbmxpbmVfMTZfYXJnNV8tX2lubGluZV8xNl9hcmc2X1sxXSxfaW5saW5lXzE2X2Y9X2lubGluZV8xNl9sKl9pbmxpbmVfMTZfbCtfaW5saW5lXzE2X2EqX2lubGluZV8xNl9hO19pbmxpbmVfMTZfZjx0aGlzX2Nsb3Nlc3REMiYmKHRoaXNfY2xvc2VzdEQyPV9pbmxpbmVfMTZfZix0aGlzX2Nsb3Nlc3RYPV9pbmxpbmVfMTZfYXJnNl9bMF0sdGhpc19jbG9zZXN0WT1faW5saW5lXzE2X2FyZzZfWzFdKX19XCIsXCJhcmdzXCI6W3tcIm5hbWVcIjpcIl9pbmxpbmVfMTZfYXJnMF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xNl9hcmcxX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzE2X2FyZzJfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTZfYXJnM19cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xNl9hcmc0X1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzE2X2FyZzVfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTZfYXJnNl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6NH1dLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX2Nsb3Nlc3REMlwiLFwidGhpc19jbG9zZXN0WFwiLFwidGhpc19jbG9zZXN0WVwiXSxcImxvY2FsVmFyc1wiOltcIl9pbmxpbmVfMTZfYVwiLFwiX2lubGluZV8xNl9mXCIsXCJfaW5saW5lXzE2X2xcIl19LFwicG9zdFwiOntcImJvZHlcIjpcIntyZXR1cm5bdGhpc19jbG9zZXN0WCx0aGlzX2Nsb3Nlc3RZLHRoaXNfY2xvc2VzdEQyXX1cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W1widGhpc19jbG9zZXN0RDJcIixcInRoaXNfY2xvc2VzdFhcIixcInRoaXNfY2xvc2VzdFlcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJkZWJ1Z1wiOmZhbHNlLFwiZnVuY05hbWVcIjpcImN3aXNlXCIsXCJibG9ja1NpemVcIjo2NH0pXG5cbmZ1bmN0aW9uIFNlbGVjdFJlc3VsdCh4LCB5LCBpZCwgdmFsdWUsIGRpc3RhbmNlKSB7XG4gIHRoaXMuY29vcmQgPSBbeCwgeV1cbiAgdGhpcy5pZCA9IGlkXG4gIHRoaXMudmFsdWUgPSB2YWx1ZVxuICB0aGlzLmRpc3RhbmNlID0gZGlzdGFuY2Vcbn1cblxuZnVuY3Rpb24gU2VsZWN0QnVmZmVyKGdsLCBmYm8sIGJ1ZmZlcikge1xuICB0aGlzLmdsICAgICA9IGdsXG4gIHRoaXMuZmJvICAgID0gZmJvXG4gIHRoaXMuYnVmZmVyID0gYnVmZmVyXG4gIHRoaXMuX3JlYWRUaW1lb3V0ID0gbnVsbFxuICB2YXIgc2VsZiA9IHRoaXNcblxuICB0aGlzLl9yZWFkQ2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcbiAgICBpZighc2VsZi5nbCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGZiby5iaW5kKClcbiAgICBnbC5yZWFkUGl4ZWxzKDAsMCxmYm8uc2hhcGVbMF0sZmJvLnNoYXBlWzFdLGdsLlJHQkEsZ2wuVU5TSUdORURfQllURSxzZWxmLmJ1ZmZlcilcbiAgICBzZWxmLl9yZWFkVGltZW91dCA9IG51bGxcbiAgfVxufVxuXG52YXIgcHJvdG8gPSBTZWxlY3RCdWZmZXIucHJvdG90eXBlXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywgJ3NoYXBlJywge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKCF0aGlzLmdsKSB7XG4gICAgICByZXR1cm4gWzAsMF1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZmJvLnNoYXBlLnNsaWNlKClcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgaWYoIXRoaXMuZ2wpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLmZiby5zaGFwZSA9IHZcbiAgICB2YXIgYyA9IHRoaXMuZmJvLnNoYXBlWzBdXG4gICAgdmFyIHIgPSB0aGlzLmZiby5zaGFwZVsxXVxuICAgIGlmKHIqYyo0ID4gdGhpcy5idWZmZXIubGVuZ3RoKSB7XG4gICAgICBwb29sLmZyZWUodGhpcy5idWZmZXIpXG4gICAgICB2YXIgYnVmZmVyID0gdGhpcy5idWZmZXIgPSBwb29sLm1hbGxvY1VpbnQ4KG5leHRQb3cyKHIqYyo0KSlcbiAgICAgIGZvcih2YXIgaT0wOyBpPHIqYyo0OyArK2kpIHtcbiAgICAgICAgYnVmZmVyW2ldID0gMHhmZlxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdlxuICB9XG59KVxuXG5wcm90by5iZWdpbiA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIHZhciBzaGFwZSA9IHRoaXMuc2hhcGVcbiAgaWYoIWdsKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB0aGlzLmZiby5iaW5kKClcbiAgZ2wuY2xlYXJDb2xvcigxLDEsMSwxKVxuICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUIHwgZ2wuREVQVEhfQlVGRkVSX0JJVClcbn1cblxucHJvdG8uZW5kID0gZnVuY3Rpb24oKSB7XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgaWYoIWdsKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKVxuICBpZighdGhpcy5fcmVhZFRpbWVvdXQpIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5fcmVhZFRpbWVvdXQpXG4gIH1cbiAgdGhpcy5fcmVhZFRpbWVvdXQgPSBzZXRUaW1lb3V0KHRoaXMuX3JlYWRDYWxsYmFjaywgMSlcbn1cblxucHJvdG8ucXVlcnkgPSBmdW5jdGlvbih4LCB5LCByYWRpdXMpIHtcbiAgaWYoIXRoaXMuZ2wpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIHNoYXBlID0gdGhpcy5mYm8uc2hhcGUuc2xpY2UoKVxuXG4gIHggPSB4fDBcbiAgeSA9IHl8MFxuICBpZih0eXBlb2YgcmFkaXVzICE9PSAnbnVtYmVyJykge1xuICAgIHJhZGl1cyA9IDEuMFxuICB9XG5cbiAgdmFyIHgwID0gTWF0aC5taW4oTWF0aC5tYXgoeCAtIHJhZGl1cywgMCksIHNoYXBlWzBdKXwwXG4gIHZhciB4MSA9IE1hdGgubWluKE1hdGgubWF4KHggKyByYWRpdXMsIDApLCBzaGFwZVswXSl8MFxuICB2YXIgeTAgPSBNYXRoLm1pbihNYXRoLm1heCh5IC0gcmFkaXVzLCAwKSwgc2hhcGVbMV0pfDBcbiAgdmFyIHkxID0gTWF0aC5taW4oTWF0aC5tYXgoeSArIHJhZGl1cywgMCksIHNoYXBlWzFdKXwwXG5cbiAgaWYoeDEgPD0geDAgfHwgeTEgPD0geTApIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIGRpbXMgICA9IFt4MS14MCx5MS15MF1cbiAgdmFyIHJlZ2lvbiA9IG5kYXJyYXkoXG4gICAgdGhpcy5idWZmZXIsXG4gICAgW2RpbXNbMF0sIGRpbXNbMV0sIDRdLFxuICAgIFs0LCBzaGFwZVswXSo0LCAxXSxcbiAgICA0Kih4MCArIHNoYXBlWzBdKnkwKSk7XG5cbiAgdmFyIGNsb3Nlc3QgPSBzZWxlY3RSYW5nZShyZWdpb24uaGkoZGltc1swXSxkaW1zWzFdLDEpLCByYWRpdXMsIHJhZGl1cylcbiAgdmFyIGR4ID0gY2xvc2VzdFswXVxuICB2YXIgZHkgPSBjbG9zZXN0WzFdXG4gIGlmKGR4IDwgMCB8fCBNYXRoLnBvdyh0aGlzLnJhZGl1cywgMikgPCBjbG9zZXN0WzJdKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBjMCA9IHJlZ2lvbi5nZXQoZHgsIGR5LCAwKVxuICB2YXIgYzEgPSByZWdpb24uZ2V0KGR4LCBkeSwgMSlcbiAgdmFyIGMyID0gcmVnaW9uLmdldChkeCwgZHksIDIpXG4gIHZhciBjMyA9IHJlZ2lvbi5nZXQoZHgsIGR5LCAzKVxuXG4gIHJldHVybiBuZXcgU2VsZWN0UmVzdWx0KFxuICAgICAoZHggKyB4MCl8MCxcbiAgICAgKGR5ICsgeTApfDAsXG4gICAgIGMwLFxuICAgICBbYzEsIGMyLCBjM10sXG4gICAgIE1hdGguc3FydChjbG9zZXN0WzJdKSlcbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICBpZighdGhpcy5nbCkge1xuICAgIHJldHVyblxuICB9XG4gIHRoaXMuZmJvLmRpc3Bvc2UoKVxuICBwb29sLmZyZWUodGhpcy5idWZmZXIpXG4gIHRoaXMuZ2wgPSBudWxsXG4gIGlmKHRoaXMuX3JlYWRUaW1lb3V0KSB7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuX3JlYWRUaW1lb3V0KVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNlbGVjdEJ1ZmZlcihnbCwgc2hhcGUpIHtcbiAgdmFyIGZibyA9IGNyZWF0ZUZCTyhnbCwgc2hhcGUpXG4gIHZhciBidWZmZXIgPSBwb29sLm1hbGxvY1VpbnQ4KHNoYXBlWzBdKnNoYXBlWzFdKjQpXG4gIHJldHVybiBuZXcgU2VsZWN0QnVmZmVyKGdsLCBmYm8sIGJ1ZmZlcilcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgY3JlYXRlVW5pZm9ybVdyYXBwZXIgICA9IHJlcXVpcmUoJy4vbGliL2NyZWF0ZS11bmlmb3JtcycpXG52YXIgY3JlYXRlQXR0cmlidXRlV3JhcHBlciA9IHJlcXVpcmUoJy4vbGliL2NyZWF0ZS1hdHRyaWJ1dGVzJylcbnZhciBtYWtlUmVmbGVjdCAgICAgICAgICAgID0gcmVxdWlyZSgnLi9saWIvcmVmbGVjdCcpXG52YXIgc2hhZGVyQ2FjaGUgICAgICAgICAgICA9IHJlcXVpcmUoJy4vbGliL3NoYWRlci1jYWNoZScpXG52YXIgcnVudGltZSAgICAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vbGliL3J1bnRpbWUtcmVmbGVjdCcpXG52YXIgR0xFcnJvciAgICAgICAgICAgICAgICA9IHJlcXVpcmUoXCIuL2xpYi9HTEVycm9yXCIpXG5cbi8vU2hhZGVyIG9iamVjdFxuZnVuY3Rpb24gU2hhZGVyKGdsKSB7XG4gIHRoaXMuZ2wgICAgICAgICA9IGdsXG4gIHRoaXMuZ2wubGFzdEF0dHJpYkNvdW50ID0gMCAgLy8gZml4bWUgd2hlcmUgZWxzZSBzaG91bGQgd2Ugc3RvcmUgaW5mbywgc2FmZSBidXQgbm90IG5pY2Ugb24gdGhlIGdsIG9iamVjdFxuXG4gIC8vRGVmYXVsdCBpbml0aWFsaXplIHRoZXNlIHRvIG51bGxcbiAgdGhpcy5fdnJlZiAgICAgID1cbiAgdGhpcy5fZnJlZiAgICAgID1cbiAgdGhpcy5fcmVsaW5rICAgID1cbiAgdGhpcy52ZXJ0U2hhZGVyID1cbiAgdGhpcy5mcmFnU2hhZGVyID1cbiAgdGhpcy5wcm9ncmFtICAgID1cbiAgdGhpcy5hdHRyaWJ1dGVzID1cbiAgdGhpcy51bmlmb3JtcyAgID1cbiAgdGhpcy50eXBlcyAgICAgID0gbnVsbFxufVxuXG52YXIgcHJvdG8gPSBTaGFkZXIucHJvdG90eXBlXG5cbnByb3RvLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgaWYoIXRoaXMucHJvZ3JhbSkge1xuICAgIHRoaXMuX3JlbGluaygpXG4gIH1cblxuICAvLyBlbnN1cmluZyB0aGF0IHdlIGhhdmUgdGhlIHJpZ2h0IG51bWJlciBvZiBlbmFibGVkIHZlcnRleCBhdHRyaWJ1dGVzXG4gIHZhciBpXG4gIHZhciBuZXdBdHRyaWJDb3VudCA9IHRoaXMuZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcih0aGlzLnByb2dyYW0sIHRoaXMuZ2wuQUNUSVZFX0FUVFJJQlVURVMpIC8vIG1vcmUgcm9idXN0IGFwcHJvYWNoXG4gIC8vdmFyIG5ld0F0dHJpYkNvdW50ID0gT2JqZWN0LmtleXModGhpcy5hdHRyaWJ1dGVzKS5sZW5ndGggLy8gYXZvaWRzIHRoZSBwcm9iYWJseSBpbW1hdGVyaWFsIGludHJvc3BlY3Rpb24gc2xvd2Rvd25cbiAgdmFyIG9sZEF0dHJpYkNvdW50ID0gdGhpcy5nbC5sYXN0QXR0cmliQ291bnRcbiAgaWYobmV3QXR0cmliQ291bnQgPiBvbGRBdHRyaWJDb3VudCkge1xuICAgIGZvcihpID0gb2xkQXR0cmliQ291bnQ7IGkgPCBuZXdBdHRyaWJDb3VudDsgaSsrKSB7XG4gICAgICB0aGlzLmdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpXG4gICAgfVxuICB9IGVsc2UgaWYob2xkQXR0cmliQ291bnQgPiBuZXdBdHRyaWJDb3VudCkge1xuICAgIGZvcihpID0gbmV3QXR0cmliQ291bnQ7IGkgPCBvbGRBdHRyaWJDb3VudDsgaSsrKSB7XG4gICAgICB0aGlzLmdsLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShpKVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuZ2wubGFzdEF0dHJpYkNvdW50ID0gbmV3QXR0cmliQ291bnRcblxuICB0aGlzLmdsLnVzZVByb2dyYW0odGhpcy5wcm9ncmFtKVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG5cbiAgLy8gZGlzYWJsaW5nIHZlcnRleCBhdHRyaWJ1dGVzIHNvIG5ldyBzaGFkZXIgc3RhcnRzIHdpdGggemVyb1xuICAvLyBhbmQgaXQncyBhbHNvIHVzZWZ1bCBpZiBhbGwgc2hhZGVycyBhcmUgZGlzcG9zZWQgYnV0IHRoZVxuICAvLyBnbCBjb250ZXh0IGlzIHJldXNlZCBmb3Igc3Vic2VxdWVudCByZXBsb3R0aW5nXG4gIHZhciBvbGRBdHRyaWJDb3VudCA9IHRoaXMuZ2wubGFzdEF0dHJpYkNvdW50XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgb2xkQXR0cmliQ291bnQ7IGkrKykge1xuICAgIHRoaXMuZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpXG4gIH1cbiAgdGhpcy5nbC5sYXN0QXR0cmliQ291bnQgPSAwXG5cbiAgaWYodGhpcy5fZnJlZikge1xuICAgIHRoaXMuX2ZyZWYuZGlzcG9zZSgpXG4gIH1cbiAgaWYodGhpcy5fdnJlZikge1xuICAgIHRoaXMuX3ZyZWYuZGlzcG9zZSgpXG4gIH1cbiAgdGhpcy5hdHRyaWJ1dGVzID1cbiAgdGhpcy50eXBlcyAgICAgID1cbiAgdGhpcy52ZXJ0U2hhZGVyID1cbiAgdGhpcy5mcmFnU2hhZGVyID1cbiAgdGhpcy5wcm9ncmFtICAgID1cbiAgdGhpcy5fcmVsaW5rICAgID1cbiAgdGhpcy5fZnJlZiAgICAgID1cbiAgdGhpcy5fdnJlZiAgICAgID0gbnVsbFxufVxuXG5mdW5jdGlvbiBjb21wYXJlQXR0cmlidXRlcyhhLCBiKSB7XG4gIGlmKGEubmFtZSA8IGIubmFtZSkge1xuICAgIHJldHVybiAtMVxuICB9XG4gIHJldHVybiAxXG59XG5cbi8vVXBkYXRlIGV4cG9ydCBob29rIGZvciBnbHNsaWZ5LWxpdmVcbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKFxuICAgIHZlcnRTb3VyY2VcbiAgLCBmcmFnU291cmNlXG4gICwgdW5pZm9ybXNcbiAgLCBhdHRyaWJ1dGVzKSB7XG5cbiAgLy9JZiBvbmx5IG9uZSBvYmplY3QgcGFzc2VkLCBhc3N1bWUgZ2xzbGlmeSBzdHlsZSBvdXRwdXRcbiAgaWYoIWZyYWdTb3VyY2UgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgIHZhciBvYmogPSB2ZXJ0U291cmNlXG4gICAgdmVydFNvdXJjZSA9IG9iai52ZXJ0ZXhcbiAgICBmcmFnU291cmNlID0gb2JqLmZyYWdtZW50XG4gICAgdW5pZm9ybXMgICA9IG9iai51bmlmb3Jtc1xuICAgIGF0dHJpYnV0ZXMgPSBvYmouYXR0cmlidXRlc1xuICB9XG5cbiAgdmFyIHdyYXBwZXIgPSB0aGlzXG4gIHZhciBnbCAgICAgID0gd3JhcHBlci5nbFxuXG4gIC8vQ29tcGlsZSB2ZXJ0ZXggYW5kIGZyYWdtZW50IHNoYWRlcnNcbiAgdmFyIHB2cmVmID0gd3JhcHBlci5fdnJlZlxuICB3cmFwcGVyLl92cmVmID0gc2hhZGVyQ2FjaGUuc2hhZGVyKGdsLCBnbC5WRVJURVhfU0hBREVSLCB2ZXJ0U291cmNlKVxuICBpZihwdnJlZikge1xuICAgIHB2cmVmLmRpc3Bvc2UoKVxuICB9XG4gIHdyYXBwZXIudmVydFNoYWRlciA9IHdyYXBwZXIuX3ZyZWYuc2hhZGVyXG4gIHZhciBwZnJlZiA9IHRoaXMuX2ZyZWZcbiAgd3JhcHBlci5fZnJlZiA9IHNoYWRlckNhY2hlLnNoYWRlcihnbCwgZ2wuRlJBR01FTlRfU0hBREVSLCBmcmFnU291cmNlKVxuICBpZihwZnJlZikge1xuICAgIHBmcmVmLmRpc3Bvc2UoKVxuICB9XG4gIHdyYXBwZXIuZnJhZ1NoYWRlciA9IHdyYXBwZXIuX2ZyZWYuc2hhZGVyXG5cbiAgLy9JZiB1bmlmb3Jtcy9hdHRyaWJ1dGVzIGlzIG5vdCBzcGVjaWZpZWQsIHVzZSBSVCByZWZsZWN0aW9uXG4gIGlmKCF1bmlmb3JtcyB8fCAhYXR0cmlidXRlcykge1xuXG4gICAgLy9DcmVhdGUgaW5pdGlhbCB0ZXN0IHByb2dyYW1cbiAgICB2YXIgdGVzdFByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKClcbiAgICBnbC5hdHRhY2hTaGFkZXIodGVzdFByb2dyYW0sIHdyYXBwZXIuZnJhZ1NoYWRlcilcbiAgICBnbC5hdHRhY2hTaGFkZXIodGVzdFByb2dyYW0sIHdyYXBwZXIudmVydFNoYWRlcilcbiAgICBnbC5saW5rUHJvZ3JhbSh0ZXN0UHJvZ3JhbSlcbiAgICBpZighZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcih0ZXN0UHJvZ3JhbSwgZ2wuTElOS19TVEFUVVMpKSB7XG4gICAgICB2YXIgZXJyTG9nID0gZ2wuZ2V0UHJvZ3JhbUluZm9Mb2codGVzdFByb2dyYW0pXG4gICAgICB0aHJvdyBuZXcgR0xFcnJvcihlcnJMb2csICdFcnJvciBsaW5raW5nIHByb2dyYW06JyArIGVyckxvZylcbiAgICB9XG5cbiAgICAvL0xvYWQgZGF0YSBmcm9tIHJ1bnRpbWVcbiAgICB1bmlmb3JtcyAgID0gdW5pZm9ybXMgICB8fCBydW50aW1lLnVuaWZvcm1zKGdsLCB0ZXN0UHJvZ3JhbSlcbiAgICBhdHRyaWJ1dGVzID0gYXR0cmlidXRlcyB8fCBydW50aW1lLmF0dHJpYnV0ZXMoZ2wsIHRlc3RQcm9ncmFtKVxuXG4gICAgLy9SZWxlYXNlIHRlc3QgcHJvZ3JhbVxuICAgIGdsLmRlbGV0ZVByb2dyYW0odGVzdFByb2dyYW0pXG4gIH1cblxuICAvL1NvcnQgYXR0cmlidXRlcyBsZXhpY29ncmFwaGljYWxseVxuICAvLyBvdmVycmlkZXMgdW5kZWZpbmVkIFdlYkdMIGJlaGF2aW9yIGZvciBhdHRyaWJ1dGUgbG9jYXRpb25zXG4gIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzLnNsaWNlKClcbiAgYXR0cmlidXRlcy5zb3J0KGNvbXBhcmVBdHRyaWJ1dGVzKVxuXG4gIC8vQ29udmVydCBhdHRyaWJ1dGUgdHlwZXMsIHJlYWQgb3V0IGxvY2F0aW9uc1xuICB2YXIgYXR0cmlidXRlVW5wYWNrZWQgID0gW11cbiAgdmFyIGF0dHJpYnV0ZU5hbWVzICAgICA9IFtdXG4gIHZhciBhdHRyaWJ1dGVMb2NhdGlvbnMgPSBbXVxuICB2YXIgaVxuICBmb3IoaT0wOyBpPGF0dHJpYnV0ZXMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYXR0ciA9IGF0dHJpYnV0ZXNbaV1cbiAgICBpZihhdHRyLnR5cGUuaW5kZXhPZignbWF0JykgPj0gMCkge1xuICAgICAgdmFyIHNpemUgPSBhdHRyLnR5cGUuY2hhckF0KGF0dHIudHlwZS5sZW5ndGgtMSl8MFxuICAgICAgdmFyIGxvY1ZlY3RvciA9IG5ldyBBcnJheShzaXplKVxuICAgICAgZm9yKHZhciBqPTA7IGo8c2l6ZTsgKytqKSB7XG4gICAgICAgIGxvY1ZlY3RvcltqXSA9IGF0dHJpYnV0ZUxvY2F0aW9ucy5sZW5ndGhcbiAgICAgICAgYXR0cmlidXRlTmFtZXMucHVzaChhdHRyLm5hbWUgKyAnWycgKyBqICsgJ10nKVxuICAgICAgICBpZih0eXBlb2YgYXR0ci5sb2NhdGlvbiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVMb2NhdGlvbnMucHVzaChhdHRyLmxvY2F0aW9uICsgailcbiAgICAgICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkoYXR0ci5sb2NhdGlvbikgJiZcbiAgICAgICAgICAgICAgICAgIGF0dHIubG9jYXRpb24ubGVuZ3RoID09PSBzaXplICYmXG4gICAgICAgICAgICAgICAgICB0eXBlb2YgYXR0ci5sb2NhdGlvbltqXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVMb2NhdGlvbnMucHVzaChhdHRyLmxvY2F0aW9uW2pdfDApXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXR0cmlidXRlTG9jYXRpb25zLnB1c2goLTEpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGF0dHJpYnV0ZVVucGFja2VkLnB1c2goe1xuICAgICAgICBuYW1lOiBhdHRyLm5hbWUsXG4gICAgICAgIHR5cGU6IGF0dHIudHlwZSxcbiAgICAgICAgbG9jYXRpb25zOiBsb2NWZWN0b3JcbiAgICAgIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIGF0dHJpYnV0ZVVucGFja2VkLnB1c2goe1xuICAgICAgICBuYW1lOiBhdHRyLm5hbWUsXG4gICAgICAgIHR5cGU6IGF0dHIudHlwZSxcbiAgICAgICAgbG9jYXRpb25zOiBbIGF0dHJpYnV0ZUxvY2F0aW9ucy5sZW5ndGggXVxuICAgICAgfSlcbiAgICAgIGF0dHJpYnV0ZU5hbWVzLnB1c2goYXR0ci5uYW1lKVxuICAgICAgaWYodHlwZW9mIGF0dHIubG9jYXRpb24gPT09ICdudW1iZXInKSB7XG4gICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9ucy5wdXNoKGF0dHIubG9jYXRpb258MClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9ucy5wdXNoKC0xKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vRm9yIGFsbCB1bnNwZWNpZmllZCBhdHRyaWJ1dGVzLCBhc3NpZ24gdGhlbSBsZXhpY29ncmFwaGljYWxseSBtaW4gYXR0cmlidXRlXG4gIHZhciBjdXJMb2NhdGlvbiA9IDBcbiAgZm9yKGk9MDsgaTxhdHRyaWJ1dGVMb2NhdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICBpZihhdHRyaWJ1dGVMb2NhdGlvbnNbaV0gPCAwKSB7XG4gICAgICB3aGlsZShhdHRyaWJ1dGVMb2NhdGlvbnMuaW5kZXhPZihjdXJMb2NhdGlvbikgPj0gMCkge1xuICAgICAgICBjdXJMb2NhdGlvbiArPSAxXG4gICAgICB9XG4gICAgICBhdHRyaWJ1dGVMb2NhdGlvbnNbaV0gPSBjdXJMb2NhdGlvblxuICAgIH1cbiAgfVxuXG4gIC8vUmVidWlsZCBwcm9ncmFtIGFuZCByZWNvbXB1dGUgYWxsIHVuaWZvcm0gbG9jYXRpb25zXG4gIHZhciB1bmlmb3JtTG9jYXRpb25zID0gbmV3IEFycmF5KHVuaWZvcm1zLmxlbmd0aClcbiAgZnVuY3Rpb24gcmVsaW5rKCkge1xuICAgIHdyYXBwZXIucHJvZ3JhbSA9IHNoYWRlckNhY2hlLnByb2dyYW0oXG4gICAgICAgIGdsXG4gICAgICAsIHdyYXBwZXIuX3ZyZWZcbiAgICAgICwgd3JhcHBlci5fZnJlZlxuICAgICAgLCBhdHRyaWJ1dGVOYW1lc1xuICAgICAgLCBhdHRyaWJ1dGVMb2NhdGlvbnMpXG5cbiAgICBmb3IodmFyIGk9MDsgaTx1bmlmb3Jtcy5sZW5ndGg7ICsraSkge1xuICAgICAgdW5pZm9ybUxvY2F0aW9uc1tpXSA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihcbiAgICAgICAgICB3cmFwcGVyLnByb2dyYW1cbiAgICAgICAgLCB1bmlmb3Jtc1tpXS5uYW1lKVxuICAgIH1cbiAgfVxuXG4gIC8vUGVyZm9ybSBpbml0aWFsIGxpbmtpbmcsIHJldXNlIHByb2dyYW0gdXNlZCBmb3IgcmVmbGVjdGlvblxuICByZWxpbmsoKVxuXG4gIC8vU2F2ZSByZWxpbmtpbmcgcHJvY2VkdXJlLCBkZWZlciB1bnRpbCBydW50aW1lXG4gIHdyYXBwZXIuX3JlbGluayA9IHJlbGlua1xuXG4gIC8vR2VuZXJhdGUgdHlwZSBpbmZvXG4gIHdyYXBwZXIudHlwZXMgPSB7XG4gICAgdW5pZm9ybXM6ICAgbWFrZVJlZmxlY3QodW5pZm9ybXMpLFxuICAgIGF0dHJpYnV0ZXM6IG1ha2VSZWZsZWN0KGF0dHJpYnV0ZXMpXG4gIH1cblxuICAvL0dlbmVyYXRlIGF0dHJpYnV0ZSB3cmFwcGVyc1xuICB3cmFwcGVyLmF0dHJpYnV0ZXMgPSBjcmVhdGVBdHRyaWJ1dGVXcmFwcGVyKFxuICAgICAgZ2xcbiAgICAsIHdyYXBwZXJcbiAgICAsIGF0dHJpYnV0ZVVucGFja2VkXG4gICAgLCBhdHRyaWJ1dGVMb2NhdGlvbnMpXG5cbiAgLy9HZW5lcmF0ZSB1bmlmb3JtIHdyYXBwZXJzXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3cmFwcGVyLCAndW5pZm9ybXMnLCBjcmVhdGVVbmlmb3JtV3JhcHBlcihcbiAgICAgIGdsXG4gICAgLCB3cmFwcGVyXG4gICAgLCB1bmlmb3Jtc1xuICAgICwgdW5pZm9ybUxvY2F0aW9ucykpXG59XG5cbi8vQ29tcGlsZXMgYW5kIGxpbmtzIGEgc2hhZGVyIHByb2dyYW0gd2l0aCB0aGUgZ2l2ZW4gYXR0cmlidXRlIGFuZCB2ZXJ0ZXggbGlzdFxuZnVuY3Rpb24gY3JlYXRlU2hhZGVyKFxuICAgIGdsXG4gICwgdmVydFNvdXJjZVxuICAsIGZyYWdTb3VyY2VcbiAgLCB1bmlmb3Jtc1xuICAsIGF0dHJpYnV0ZXMpIHtcblxuICB2YXIgc2hhZGVyID0gbmV3IFNoYWRlcihnbClcblxuICBzaGFkZXIudXBkYXRlKFxuICAgICAgdmVydFNvdXJjZVxuICAgICwgZnJhZ1NvdXJjZVxuICAgICwgdW5pZm9ybXNcbiAgICAsIGF0dHJpYnV0ZXMpXG5cbiAgcmV0dXJuIHNoYWRlclxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNoYWRlclxuIiwiZnVuY3Rpb24gR0xFcnJvciAocmF3RXJyb3IsIHNob3J0TWVzc2FnZSwgbG9uZ01lc3NhZ2UpIHtcbiAgICB0aGlzLnNob3J0TWVzc2FnZSA9IHNob3J0TWVzc2FnZSB8fCAnJ1xuICAgIHRoaXMubG9uZ01lc3NhZ2UgPSBsb25nTWVzc2FnZSB8fCAnJ1xuICAgIHRoaXMucmF3RXJyb3IgPSByYXdFcnJvciB8fCAnJ1xuICAgIHRoaXMubWVzc2FnZSA9XG4gICAgICAnZ2wtc2hhZGVyOiAnICsgKHNob3J0TWVzc2FnZSB8fCByYXdFcnJvciB8fCAnJykgK1xuICAgICAgKGxvbmdNZXNzYWdlID8gJ1xcbicrbG9uZ01lc3NhZ2UgOiAnJylcbiAgICB0aGlzLnN0YWNrID0gKG5ldyBFcnJvcigpKS5zdGFja1xufVxuR0xFcnJvci5wcm90b3R5cGUgPSBuZXcgRXJyb3JcbkdMRXJyb3IucHJvdG90eXBlLm5hbWUgPSAnR0xFcnJvcidcbkdMRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gR0xFcnJvclxubW9kdWxlLmV4cG9ydHMgPSBHTEVycm9yXG4iLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBdHRyaWJ1dGVXcmFwcGVyXG5cbnZhciBHTEVycm9yID0gcmVxdWlyZShcIi4vR0xFcnJvclwiKVxuXG5mdW5jdGlvbiBTaGFkZXJBdHRyaWJ1dGUoXG4gICAgZ2xcbiAgLCB3cmFwcGVyXG4gICwgaW5kZXhcbiAgLCBsb2NhdGlvbnNcbiAgLCBkaW1lbnNpb25cbiAgLCBjb25zdEZ1bmMpIHtcbiAgdGhpcy5fZ2wgICAgICAgID0gZ2xcbiAgdGhpcy5fd3JhcHBlciAgID0gd3JhcHBlclxuICB0aGlzLl9pbmRleCAgICAgPSBpbmRleFxuICB0aGlzLl9sb2NhdGlvbnMgPSBsb2NhdGlvbnNcbiAgdGhpcy5fZGltZW5zaW9uID0gZGltZW5zaW9uXG4gIHRoaXMuX2NvbnN0RnVuYyA9IGNvbnN0RnVuY1xufVxuXG52YXIgcHJvdG8gPSBTaGFkZXJBdHRyaWJ1dGUucHJvdG90eXBlXG5cbnByb3RvLnBvaW50ZXIgPSBmdW5jdGlvbiBzZXRBdHRyaWJQb2ludGVyKFxuICAgIHR5cGVcbiAgLCBub3JtYWxpemVkXG4gICwgc3RyaWRlXG4gICwgb2Zmc2V0KSB7XG5cbiAgdmFyIHNlbGYgICAgICA9IHRoaXNcbiAgdmFyIGdsICAgICAgICA9IHNlbGYuX2dsXG4gIHZhciBsb2NhdGlvbiAgPSBzZWxmLl9sb2NhdGlvbnNbc2VsZi5faW5kZXhdXG5cbiAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihcbiAgICAgIGxvY2F0aW9uXG4gICAgLCBzZWxmLl9kaW1lbnNpb25cbiAgICAsIHR5cGUgfHwgZ2wuRkxPQVRcbiAgICAsICEhbm9ybWFsaXplZFxuICAgICwgc3RyaWRlIHx8IDBcbiAgICAsIG9mZnNldCB8fCAwKVxuICBnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShsb2NhdGlvbilcbn1cblxucHJvdG8uc2V0ID0gZnVuY3Rpb24oeDAsIHgxLCB4MiwgeDMpIHtcbiAgcmV0dXJuIHRoaXMuX2NvbnN0RnVuYyh0aGlzLl9sb2NhdGlvbnNbdGhpcy5faW5kZXhdLCB4MCwgeDEsIHgyLCB4Mylcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCAnbG9jYXRpb24nLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xvY2F0aW9uc1t0aGlzLl9pbmRleF1cbiAgfVxuICAsIHNldDogZnVuY3Rpb24odikge1xuICAgIGlmKHYgIT09IHRoaXMuX2xvY2F0aW9uc1t0aGlzLl9pbmRleF0pIHtcbiAgICAgIHRoaXMuX2xvY2F0aW9uc1t0aGlzLl9pbmRleF0gPSB2fDBcbiAgICAgIHRoaXMuX3dyYXBwZXIucHJvZ3JhbSA9IG51bGxcbiAgICB9XG4gICAgcmV0dXJuIHZ8MFxuICB9XG59KVxuXG4vL0FkZHMgYSB2ZWN0b3IgYXR0cmlidXRlIHRvIG9ialxuZnVuY3Rpb24gYWRkVmVjdG9yQXR0cmlidXRlKFxuICAgIGdsXG4gICwgd3JhcHBlclxuICAsIGluZGV4XG4gICwgbG9jYXRpb25zXG4gICwgZGltZW5zaW9uXG4gICwgb2JqXG4gICwgbmFtZSkge1xuXG4gIC8vQ29uc3RydWN0IGNvbnN0YW50IGZ1bmN0aW9uXG4gIHZhciBjb25zdEZ1bmNBcmdzID0gWyAnZ2wnLCAndicgXVxuICB2YXIgdmFyTmFtZXMgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvbnN0RnVuY0FyZ3MucHVzaCgneCcraSlcbiAgICB2YXJOYW1lcy5wdXNoKCd4JytpKVxuICB9XG4gIGNvbnN0RnVuY0FyZ3MucHVzaChcbiAgICAnaWYoeDAubGVuZ3RoPT09dm9pZCAwKXtyZXR1cm4gZ2wudmVydGV4QXR0cmliJyArXG4gICAgZGltZW5zaW9uICsgJ2YodiwnICtcbiAgICB2YXJOYW1lcy5qb2luKCkgK1xuICAgICcpfWVsc2V7cmV0dXJuIGdsLnZlcnRleEF0dHJpYicgK1xuICAgIGRpbWVuc2lvbiArXG4gICAgJ2Z2KHYseDApfScpXG4gIHZhciBjb25zdEZ1bmMgPSBGdW5jdGlvbi5hcHBseShudWxsLCBjb25zdEZ1bmNBcmdzKVxuXG4gIC8vQ3JlYXRlIGF0dHJpYnV0ZSB3cmFwcGVyXG4gIHZhciBhdHRyID0gbmV3IFNoYWRlckF0dHJpYnV0ZShcbiAgICAgIGdsXG4gICAgLCB3cmFwcGVyXG4gICAgLCBpbmRleFxuICAgICwgbG9jYXRpb25zXG4gICAgLCBkaW1lbnNpb25cbiAgICAsIGNvbnN0RnVuYylcblxuICAvL0NyZWF0ZSBhY2Nlc3NvclxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBuYW1lLCB7XG4gICAgc2V0OiBmdW5jdGlvbih4KSB7XG4gICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb25zW2luZGV4XSlcbiAgICAgIGNvbnN0RnVuYyhnbCwgbG9jYXRpb25zW2luZGV4XSwgeClcbiAgICAgIHJldHVybiB4XG4gICAgfVxuICAgICwgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBhdHRyXG4gICAgfVxuICAgICwgZW51bWVyYWJsZTogdHJ1ZVxuICB9KVxufVxuXG5mdW5jdGlvbiBhZGRNYXRyaXhBdHRyaWJ1dGUoXG4gICAgZ2xcbiAgLCB3cmFwcGVyXG4gICwgaW5kZXhcbiAgLCBsb2NhdGlvbnNcbiAgLCBkaW1lbnNpb25cbiAgLCBvYmpcbiAgLCBuYW1lKSB7XG5cbiAgdmFyIHBhcnRzID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgdmFyIGF0dHJzID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBhZGRWZWN0b3JBdHRyaWJ1dGUoXG4gICAgICAgIGdsXG4gICAgICAsIHdyYXBwZXJcbiAgICAgICwgaW5kZXhbaV1cbiAgICAgICwgbG9jYXRpb25zXG4gICAgICAsIGRpbWVuc2lvblxuICAgICAgLCBwYXJ0c1xuICAgICAgLCBpKVxuICAgIGF0dHJzW2ldID0gcGFydHNbaV1cbiAgfVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShwYXJ0cywgJ2xvY2F0aW9uJywge1xuICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgaWYoQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgICAgIGF0dHJzW2ldLmxvY2F0aW9uID0gdltpXVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgICAgIGF0dHJzW2ldLmxvY2F0aW9uID0gdiArIGlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHZcbiAgICB9XG4gICAgLCBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gICAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgICByZXN1bHRbaV0gPSBsb2NhdGlvbnNbaW5kZXhbaV1dXG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuICAgICwgZW51bWVyYWJsZTogdHJ1ZVxuICB9KVxuXG4gIHBhcnRzLnBvaW50ZXIgPSBmdW5jdGlvbih0eXBlLCBub3JtYWxpemVkLCBzdHJpZGUsIG9mZnNldCkge1xuICAgIHR5cGUgICAgICAgPSB0eXBlIHx8IGdsLkZMT0FUXG4gICAgbm9ybWFsaXplZCA9ICEhbm9ybWFsaXplZFxuICAgIHN0cmlkZSAgICAgPSBzdHJpZGUgfHwgKGRpbWVuc2lvbiAqIGRpbWVuc2lvbilcbiAgICBvZmZzZXQgICAgID0gb2Zmc2V0IHx8IDBcbiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgdmFyIGxvY2F0aW9uID0gbG9jYXRpb25zW2luZGV4W2ldXVxuICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihcbiAgICAgICAgICAgIGxvY2F0aW9uXG4gICAgICAgICAgLCBkaW1lbnNpb25cbiAgICAgICAgICAsIHR5cGVcbiAgICAgICAgICAsIG5vcm1hbGl6ZWRcbiAgICAgICAgICAsIHN0cmlkZVxuICAgICAgICAgICwgb2Zmc2V0ICsgaSAqIGRpbWVuc2lvbilcbiAgICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGxvY2F0aW9uKVxuICAgIH1cbiAgfVxuXG4gIHZhciBzY3JhdGNoID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgdmFyIHZlcnRleEF0dHJpYiA9IGdsWyd2ZXJ0ZXhBdHRyaWInICsgZGltZW5zaW9uICsgJ2Z2J11cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBuYW1lLCB7XG4gICAgc2V0OiBmdW5jdGlvbih4KSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgICB2YXIgbG9jID0gbG9jYXRpb25zW2luZGV4W2ldXVxuICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkobG9jKVxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHhbMF0pKSB7XG4gICAgICAgICAgdmVydGV4QXR0cmliLmNhbGwoZ2wsIGxvYywgeFtpXSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikge1xuICAgICAgICAgICAgc2NyYXRjaFtqXSA9IHhbZGltZW5zaW9uKmkgKyBqXVxuICAgICAgICAgIH1cbiAgICAgICAgICB2ZXJ0ZXhBdHRyaWIuY2FsbChnbCwgbG9jLCBzY3JhdGNoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4geFxuICAgIH1cbiAgICAsIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGFydHNcbiAgICB9XG4gICAgLCBlbnVtZXJhYmxlOiB0cnVlXG4gIH0pXG59XG5cbi8vQ3JlYXRlIHNoaW1zIGZvciBhdHRyaWJ1dGVzXG5mdW5jdGlvbiBjcmVhdGVBdHRyaWJ1dGVXcmFwcGVyKFxuICAgIGdsXG4gICwgd3JhcHBlclxuICAsIGF0dHJpYnV0ZXNcbiAgLCBsb2NhdGlvbnMpIHtcblxuICB2YXIgb2JqID0ge31cbiAgZm9yKHZhciBpPTAsIG49YXR0cmlidXRlcy5sZW5ndGg7IGk8bjsgKytpKSB7XG5cbiAgICB2YXIgYSA9IGF0dHJpYnV0ZXNbaV1cbiAgICB2YXIgbmFtZSA9IGEubmFtZVxuICAgIHZhciB0eXBlID0gYS50eXBlXG4gICAgdmFyIGxvY3MgPSBhLmxvY2F0aW9uc1xuXG4gICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgY2FzZSAnaW50JzpcbiAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgICAgYWRkVmVjdG9yQXR0cmlidXRlKFxuICAgICAgICAgICAgZ2xcbiAgICAgICAgICAsIHdyYXBwZXJcbiAgICAgICAgICAsIGxvY3NbMF1cbiAgICAgICAgICAsIGxvY2F0aW9uc1xuICAgICAgICAgICwgMVxuICAgICAgICAgICwgb2JqXG4gICAgICAgICAgLCBuYW1lKVxuICAgICAgYnJlYWtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYodHlwZS5pbmRleE9mKCd2ZWMnKSA+PSAwKSB7XG4gICAgICAgICAgdmFyIGQgPSB0eXBlLmNoYXJDb2RlQXQodHlwZS5sZW5ndGgtMSkgLSA0OFxuICAgICAgICAgIGlmKGQgPCAyIHx8IGQgPiA0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ0ludmFsaWQgZGF0YSB0eXBlIGZvciBhdHRyaWJ1dGUgJyArIG5hbWUgKyAnOiAnICsgdHlwZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgYWRkVmVjdG9yQXR0cmlidXRlKFxuICAgICAgICAgICAgICBnbFxuICAgICAgICAgICAgLCB3cmFwcGVyXG4gICAgICAgICAgICAsIGxvY3NbMF1cbiAgICAgICAgICAgICwgbG9jYXRpb25zXG4gICAgICAgICAgICAsIGRcbiAgICAgICAgICAgICwgb2JqXG4gICAgICAgICAgICAsIG5hbWUpXG4gICAgICAgIH0gZWxzZSBpZih0eXBlLmluZGV4T2YoJ21hdCcpID49IDApIHtcbiAgICAgICAgICB2YXIgZCA9IHR5cGUuY2hhckNvZGVBdCh0eXBlLmxlbmd0aC0xKSAtIDQ4XG4gICAgICAgICAgaWYoZCA8IDIgfHwgZCA+IDQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnSW52YWxpZCBkYXRhIHR5cGUgZm9yIGF0dHJpYnV0ZSAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICAgIH1cbiAgICAgICAgICBhZGRNYXRyaXhBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIGdsXG4gICAgICAgICAgICAsIHdyYXBwZXJcbiAgICAgICAgICAgICwgbG9jc1xuICAgICAgICAgICAgLCBsb2NhdGlvbnNcbiAgICAgICAgICAgICwgZFxuICAgICAgICAgICAgLCBvYmpcbiAgICAgICAgICAgICwgbmFtZSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ1Vua25vd24gZGF0YSB0eXBlIGZvciBhdHRyaWJ1dGUgJyArIG5hbWUgKyAnOiAnICsgdHlwZSlcbiAgICAgICAgfVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG9ialxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBjb2FsbGVzY2VVbmlmb3JtcyA9IHJlcXVpcmUoJy4vcmVmbGVjdCcpXG52YXIgR0xFcnJvciA9IHJlcXVpcmUoXCIuL0dMRXJyb3JcIilcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVVbmlmb3JtV3JhcHBlclxuXG4vL0JpbmRzIGEgZnVuY3Rpb24gYW5kIHJldHVybnMgYSB2YWx1ZVxuZnVuY3Rpb24gaWRlbnRpdHkoeCkge1xuICB2YXIgYyA9IG5ldyBGdW5jdGlvbigneScsICdyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4geX0nKVxuICByZXR1cm4gYyh4KVxufVxuXG5mdW5jdGlvbiBtYWtlVmVjdG9yKGxlbmd0aCwgZmlsbCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8bGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBmaWxsXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vL0NyZWF0ZSBzaGltcyBmb3IgdW5pZm9ybXNcbmZ1bmN0aW9uIGNyZWF0ZVVuaWZvcm1XcmFwcGVyKGdsLCB3cmFwcGVyLCB1bmlmb3JtcywgbG9jYXRpb25zKSB7XG5cbiAgZnVuY3Rpb24gbWFrZUdldHRlcihpbmRleCkge1xuICAgIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFxuICAgICAgICAnZ2wnXG4gICAgICAsICd3cmFwcGVyJ1xuICAgICAgLCAnbG9jYXRpb25zJ1xuICAgICAgLCAncmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGdsLmdldFVuaWZvcm0od3JhcHBlci5wcm9ncmFtLGxvY2F0aW9uc1snICsgaW5kZXggKyAnXSl9JylcbiAgICByZXR1cm4gcHJvYyhnbCwgd3JhcHBlciwgbG9jYXRpb25zKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFrZVByb3BTZXR0ZXIocGF0aCwgaW5kZXgsIHR5cGUpIHtcbiAgICBzd2l0Y2godHlwZSkge1xuICAgICAgY2FzZSAnYm9vbCc6XG4gICAgICBjYXNlICdpbnQnOlxuICAgICAgY2FzZSAnc2FtcGxlcjJEJzpcbiAgICAgIGNhc2UgJ3NhbXBsZXJDdWJlJzpcbiAgICAgICAgcmV0dXJuICdnbC51bmlmb3JtMWkobG9jYXRpb25zWycgKyBpbmRleCArICddLG9iaicgKyBwYXRoICsgJyknXG4gICAgICBjYXNlICdmbG9hdCc6XG4gICAgICAgIHJldHVybiAnZ2wudW5pZm9ybTFmKGxvY2F0aW9uc1snICsgaW5kZXggKyAnXSxvYmonICsgcGF0aCArICcpJ1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdmFyIHZpZHggPSB0eXBlLmluZGV4T2YoJ3ZlYycpXG4gICAgICAgIGlmKDAgPD0gdmlkeCAmJiB2aWR4IDw9IDEgJiYgdHlwZS5sZW5ndGggPT09IDQgKyB2aWR4KSB7XG4gICAgICAgICAgdmFyIGQgPSB0eXBlLmNoYXJDb2RlQXQodHlwZS5sZW5ndGgtMSkgLSA0OFxuICAgICAgICAgIGlmKGQgPCAyIHx8IGQgPiA0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ0ludmFsaWQgZGF0YSB0eXBlJylcbiAgICAgICAgICB9XG4gICAgICAgICAgc3dpdGNoKHR5cGUuY2hhckF0KDApKSB7XG4gICAgICAgICAgICBjYXNlICdiJzpcbiAgICAgICAgICAgIGNhc2UgJ2knOlxuICAgICAgICAgICAgICByZXR1cm4gJ2dsLnVuaWZvcm0nICsgZCArICdpdihsb2NhdGlvbnNbJyArIGluZGV4ICsgJ10sb2JqJyArIHBhdGggKyAnKSdcbiAgICAgICAgICAgIGNhc2UgJ3YnOlxuICAgICAgICAgICAgICByZXR1cm4gJ2dsLnVuaWZvcm0nICsgZCArICdmdihsb2NhdGlvbnNbJyArIGluZGV4ICsgJ10sb2JqJyArIHBhdGggKyAnKSdcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnVW5yZWNvZ25pemVkIGRhdGEgdHlwZSBmb3IgdmVjdG9yICcgKyBuYW1lICsgJzogJyArIHR5cGUpXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYodHlwZS5pbmRleE9mKCdtYXQnKSA9PT0gMCAmJiB0eXBlLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIHZhciBkID0gdHlwZS5jaGFyQ29kZUF0KHR5cGUubGVuZ3RoLTEpIC0gNDhcbiAgICAgICAgICBpZihkIDwgMiB8fCBkID4gNCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoJycsICdJbnZhbGlkIHVuaWZvcm0gZGltZW5zaW9uIHR5cGUgZm9yIG1hdHJpeCAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gJ2dsLnVuaWZvcm1NYXRyaXgnICsgZCArICdmdihsb2NhdGlvbnNbJyArIGluZGV4ICsgJ10sZmFsc2Usb2JqJyArIHBhdGggKyAnKSdcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ1Vua25vd24gdW5pZm9ybSBkYXRhIHR5cGUgZm9yICcgKyBuYW1lICsgJzogJyArIHR5cGUpXG4gICAgICAgIH1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW51bWVyYXRlSW5kaWNlcyhwcmVmaXgsIHR5cGUpIHtcbiAgICBpZih0eXBlb2YgdHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBbIFtwcmVmaXgsIHR5cGVdIF1cbiAgICB9XG4gICAgdmFyIGluZGljZXMgPSBbXVxuICAgIGZvcih2YXIgaWQgaW4gdHlwZSkge1xuICAgICAgdmFyIHByb3AgPSB0eXBlW2lkXVxuICAgICAgdmFyIHRwcmVmaXggPSBwcmVmaXhcbiAgICAgIGlmKHBhcnNlSW50KGlkKSArICcnID09PSBpZCkge1xuICAgICAgICB0cHJlZml4ICs9ICdbJyArIGlkICsgJ10nXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cHJlZml4ICs9ICcuJyArIGlkXG4gICAgICB9XG4gICAgICBpZih0eXBlb2YgcHJvcCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgaW5kaWNlcy5wdXNoLmFwcGx5KGluZGljZXMsIGVudW1lcmF0ZUluZGljZXModHByZWZpeCwgcHJvcCkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbmRpY2VzLnB1c2goW3RwcmVmaXgsIHByb3BdKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5kaWNlc1xuICB9XG5cbiAgZnVuY3Rpb24gbWFrZVNldHRlcih0eXBlKSB7XG4gICAgdmFyIGNvZGUgPSBbICdyZXR1cm4gZnVuY3Rpb24gdXBkYXRlUHJvcGVydHkob2JqKXsnIF1cbiAgICB2YXIgaW5kaWNlcyA9IGVudW1lcmF0ZUluZGljZXMoJycsIHR5cGUpXG4gICAgZm9yKHZhciBpPTA7IGk8aW5kaWNlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGl0ZW0gPSBpbmRpY2VzW2ldXG4gICAgICB2YXIgcGF0aCA9IGl0ZW1bMF1cbiAgICAgIHZhciBpZHggID0gaXRlbVsxXVxuICAgICAgaWYobG9jYXRpb25zW2lkeF0pIHtcbiAgICAgICAgY29kZS5wdXNoKG1ha2VQcm9wU2V0dGVyKHBhdGgsIGlkeCwgdW5pZm9ybXNbaWR4XS50eXBlKSlcbiAgICAgIH1cbiAgICB9XG4gICAgY29kZS5wdXNoKCdyZXR1cm4gb2JqfScpXG4gICAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oJ2dsJywgJ2xvY2F0aW9ucycsIGNvZGUuam9pbignXFxuJykpXG4gICAgcmV0dXJuIHByb2MoZ2wsIGxvY2F0aW9ucylcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlZmF1bHRWYWx1ZSh0eXBlKSB7XG4gICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGNhc2UgJ2ludCc6XG4gICAgICBjYXNlICdzYW1wbGVyMkQnOlxuICAgICAgY2FzZSAnc2FtcGxlckN1YmUnOlxuICAgICAgICByZXR1cm4gMFxuICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICByZXR1cm4gMC4wXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgdmlkeCA9IHR5cGUuaW5kZXhPZigndmVjJylcbiAgICAgICAgaWYoMCA8PSB2aWR4ICYmIHZpZHggPD0gMSAmJiB0eXBlLmxlbmd0aCA9PT0gNCArIHZpZHgpIHtcbiAgICAgICAgICB2YXIgZCA9IHR5cGUuY2hhckNvZGVBdCh0eXBlLmxlbmd0aC0xKSAtIDQ4XG4gICAgICAgICAgaWYoZCA8IDIgfHwgZCA+IDQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnSW52YWxpZCBkYXRhIHR5cGUnKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZih0eXBlLmNoYXJBdCgwKSA9PT0gJ2InKSB7XG4gICAgICAgICAgICByZXR1cm4gbWFrZVZlY3RvcihkLCBmYWxzZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1ha2VWZWN0b3IoZCwgMClcbiAgICAgICAgfSBlbHNlIGlmKHR5cGUuaW5kZXhPZignbWF0JykgPT09IDAgJiYgdHlwZS5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICB2YXIgZCA9IHR5cGUuY2hhckNvZGVBdCh0eXBlLmxlbmd0aC0xKSAtIDQ4XG4gICAgICAgICAgaWYoZCA8IDIgfHwgZCA+IDQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnSW52YWxpZCB1bmlmb3JtIGRpbWVuc2lvbiB0eXBlIGZvciBtYXRyaXggJyArIG5hbWUgKyAnOiAnICsgdHlwZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1ha2VWZWN0b3IoZCpkLCAwKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnVW5rbm93biB1bmlmb3JtIGRhdGEgdHlwZSBmb3IgJyArIG5hbWUgKyAnOiAnICsgdHlwZSlcbiAgICAgICAgfVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzdG9yZVByb3BlcnR5KG9iaiwgcHJvcCwgdHlwZSkge1xuICAgIGlmKHR5cGVvZiB0eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgdmFyIGNoaWxkID0gcHJvY2Vzc09iamVjdCh0eXBlKVxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgcHJvcCwge1xuICAgICAgICBnZXQ6IGlkZW50aXR5KGNoaWxkKSxcbiAgICAgICAgc2V0OiBtYWtlU2V0dGVyKHR5cGUpLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlXG4gICAgICB9KVxuICAgIH0gZWxzZSB7XG4gICAgICBpZihsb2NhdGlvbnNbdHlwZV0pIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgcHJvcCwge1xuICAgICAgICAgIGdldDogbWFrZUdldHRlcih0eXBlKSxcbiAgICAgICAgICBzZXQ6IG1ha2VTZXR0ZXIodHlwZSksXG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlXG4gICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmpbcHJvcF0gPSBkZWZhdWx0VmFsdWUodW5pZm9ybXNbdHlwZV0udHlwZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBwcm9jZXNzT2JqZWN0KG9iaikge1xuICAgIHZhciByZXN1bHRcbiAgICBpZihBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShvYmoubGVuZ3RoKVxuICAgICAgZm9yKHZhciBpPTA7IGk8b2JqLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHN0b3JlUHJvcGVydHkocmVzdWx0LCBpLCBvYmpbaV0pXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCA9IHt9XG4gICAgICBmb3IodmFyIGlkIGluIG9iaikge1xuICAgICAgICBzdG9yZVByb3BlcnR5KHJlc3VsdCwgaWQsIG9ialtpZF0pXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8vUmV0dXJuIGRhdGFcbiAgdmFyIGNvYWxsZXNjZWQgPSBjb2FsbGVzY2VVbmlmb3Jtcyh1bmlmb3JtcywgdHJ1ZSlcbiAgcmV0dXJuIHtcbiAgICBnZXQ6IGlkZW50aXR5KHByb2Nlc3NPYmplY3QoY29hbGxlc2NlZCkpLFxuICAgIHNldDogbWFrZVNldHRlcihjb2FsbGVzY2VkKSxcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9XG59XG4iLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBtYWtlUmVmbGVjdFR5cGVzXG5cbi8vQ29uc3RydWN0IHR5cGUgaW5mbyBmb3IgcmVmbGVjdGlvbi5cbi8vXG4vLyBUaGlzIGl0ZXJhdGVzIG92ZXIgdGhlIGZsYXR0ZW5lZCBsaXN0IG9mIHVuaWZvcm0gdHlwZSB2YWx1ZXMgYW5kIHNtYXNoZXMgdGhlbSBpbnRvIGEgSlNPTiBvYmplY3QuXG4vL1xuLy8gVGhlIGxlYXZlcyBvZiB0aGUgcmVzdWx0aW5nIG9iamVjdCBhcmUgZWl0aGVyIGluZGljZXMgb3IgdHlwZSBzdHJpbmdzIHJlcHJlc2VudGluZyBwcmltaXRpdmUgZ2xzbGlmeSB0eXBlc1xuZnVuY3Rpb24gbWFrZVJlZmxlY3RUeXBlcyh1bmlmb3JtcywgdXNlSW5kZXgpIHtcbiAgdmFyIG9iaiA9IHt9XG4gIGZvcih2YXIgaT0wOyBpPHVuaWZvcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIG4gPSB1bmlmb3Jtc1tpXS5uYW1lXG4gICAgdmFyIHBhcnRzID0gbi5zcGxpdChcIi5cIilcbiAgICB2YXIgbyA9IG9ialxuICAgIGZvcih2YXIgaj0wOyBqPHBhcnRzLmxlbmd0aDsgKytqKSB7XG4gICAgICB2YXIgeCA9IHBhcnRzW2pdLnNwbGl0KFwiW1wiKVxuICAgICAgaWYoeC5sZW5ndGggPiAxKSB7XG4gICAgICAgIGlmKCEoeFswXSBpbiBvKSkge1xuICAgICAgICAgIG9beFswXV0gPSBbXVxuICAgICAgICB9XG4gICAgICAgIG8gPSBvW3hbMF1dXG4gICAgICAgIGZvcih2YXIgaz0xOyBrPHgubGVuZ3RoOyArK2spIHtcbiAgICAgICAgICB2YXIgeSA9IHBhcnNlSW50KHhba10pXG4gICAgICAgICAgaWYoazx4Lmxlbmd0aC0xIHx8IGo8cGFydHMubGVuZ3RoLTEpIHtcbiAgICAgICAgICAgIGlmKCEoeSBpbiBvKSkge1xuICAgICAgICAgICAgICBpZihrIDwgeC5sZW5ndGgtMSkge1xuICAgICAgICAgICAgICAgIG9beV0gPSBbXVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9beV0gPSB7fVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvID0gb1t5XVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZih1c2VJbmRleCkge1xuICAgICAgICAgICAgICBvW3ldID0gaVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgb1t5XSA9IHVuaWZvcm1zW2ldLnR5cGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZihqIDwgcGFydHMubGVuZ3RoLTEpIHtcbiAgICAgICAgaWYoISh4WzBdIGluIG8pKSB7XG4gICAgICAgICAgb1t4WzBdXSA9IHt9XG4gICAgICAgIH1cbiAgICAgICAgbyA9IG9beFswXV1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHVzZUluZGV4KSB7XG4gICAgICAgICAgb1t4WzBdXSA9IGlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvW3hbMF1dID0gdW5pZm9ybXNbaV0udHlwZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmpcbn0iLCIndXNlIHN0cmljdCdcblxuZXhwb3J0cy51bmlmb3JtcyAgICA9IHJ1bnRpbWVVbmlmb3Jtc1xuZXhwb3J0cy5hdHRyaWJ1dGVzICA9IHJ1bnRpbWVBdHRyaWJ1dGVzXG5cbnZhciBHTF9UT19HTFNMX1RZUEVTID0ge1xuICAnRkxPQVQnOiAgICAgICAnZmxvYXQnLFxuICAnRkxPQVRfVkVDMic6ICAndmVjMicsXG4gICdGTE9BVF9WRUMzJzogICd2ZWMzJyxcbiAgJ0ZMT0FUX1ZFQzQnOiAgJ3ZlYzQnLFxuICAnSU5UJzogICAgICAgICAnaW50JyxcbiAgJ0lOVF9WRUMyJzogICAgJ2l2ZWMyJyxcbiAgJ0lOVF9WRUMzJzogICAgJ2l2ZWMzJyxcbiAgJ0lOVF9WRUM0JzogICAgJ2l2ZWM0JyxcbiAgJ0JPT0wnOiAgICAgICAgJ2Jvb2wnLFxuICAnQk9PTF9WRUMyJzogICAnYnZlYzInLFxuICAnQk9PTF9WRUMzJzogICAnYnZlYzMnLFxuICAnQk9PTF9WRUM0JzogICAnYnZlYzQnLFxuICAnRkxPQVRfTUFUMic6ICAnbWF0MicsXG4gICdGTE9BVF9NQVQzJzogICdtYXQzJyxcbiAgJ0ZMT0FUX01BVDQnOiAgJ21hdDQnLFxuICAnU0FNUExFUl8yRCc6ICAnc2FtcGxlcjJEJyxcbiAgJ1NBTVBMRVJfQ1VCRSc6J3NhbXBsZXJDdWJlJ1xufVxuXG52YXIgR0xfVEFCTEUgPSBudWxsXG5cbmZ1bmN0aW9uIGdldFR5cGUoZ2wsIHR5cGUpIHtcbiAgaWYoIUdMX1RBQkxFKSB7XG4gICAgdmFyIHR5cGVOYW1lcyA9IE9iamVjdC5rZXlzKEdMX1RPX0dMU0xfVFlQRVMpXG4gICAgR0xfVEFCTEUgPSB7fVxuICAgIGZvcih2YXIgaT0wOyBpPHR5cGVOYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHRuID0gdHlwZU5hbWVzW2ldXG4gICAgICBHTF9UQUJMRVtnbFt0bl1dID0gR0xfVE9fR0xTTF9UWVBFU1t0bl1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIEdMX1RBQkxFW3R5cGVdXG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVVbmlmb3JtcyhnbCwgcHJvZ3JhbSkge1xuICB2YXIgbnVtVW5pZm9ybXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkFDVElWRV9VTklGT1JNUylcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG51bVVuaWZvcm1zOyArK2kpIHtcbiAgICB2YXIgaW5mbyA9IGdsLmdldEFjdGl2ZVVuaWZvcm0ocHJvZ3JhbSwgaSlcbiAgICBpZihpbmZvKSB7XG4gICAgICB2YXIgdHlwZSA9IGdldFR5cGUoZ2wsIGluZm8udHlwZSlcbiAgICAgIGlmKGluZm8uc2l6ZSA+IDEpIHtcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8aW5mby5zaXplOyArK2opIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBpbmZvLm5hbWUucmVwbGFjZSgnWzBdJywgJ1snICsgaiArICddJyksXG4gICAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgIG5hbWU6IGluZm8ubmFtZSxcbiAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gcnVudGltZUF0dHJpYnV0ZXMoZ2wsIHByb2dyYW0pIHtcbiAgdmFyIG51bUF0dHJpYnV0ZXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkFDVElWRV9BVFRSSUJVVEVTKVxuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bnVtQXR0cmlidXRlczsgKytpKSB7XG4gICAgdmFyIGluZm8gPSBnbC5nZXRBY3RpdmVBdHRyaWIocHJvZ3JhbSwgaSlcbiAgICBpZihpbmZvKSB7XG4gICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgIG5hbWU6IGluZm8ubmFtZSxcbiAgICAgICAgdHlwZTogZ2V0VHlwZShnbCwgaW5mby50eXBlKVxuICAgICAgfSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbmV4cG9ydHMuc2hhZGVyICAgPSBnZXRTaGFkZXJSZWZlcmVuY2VcbmV4cG9ydHMucHJvZ3JhbSAgPSBjcmVhdGVQcm9ncmFtXG5cbnZhciBHTEVycm9yID0gcmVxdWlyZShcIi4vR0xFcnJvclwiKVxudmFyIGZvcm1hdENvbXBpbGVyRXJyb3IgPSByZXF1aXJlKCdnbC1mb3JtYXQtY29tcGlsZXItZXJyb3InKTtcblxudmFyIHdlYWtNYXAgPSB0eXBlb2YgV2Vha01hcCA9PT0gJ3VuZGVmaW5lZCcgPyByZXF1aXJlKCd3ZWFrbWFwLXNoaW0nKSA6IFdlYWtNYXBcbnZhciBDQUNIRSA9IG5ldyB3ZWFrTWFwKClcblxudmFyIFNIQURFUl9DT1VOVEVSID0gMFxuXG5mdW5jdGlvbiBTaGFkZXJSZWZlcmVuY2UoaWQsIHNyYywgdHlwZSwgc2hhZGVyLCBwcm9ncmFtcywgY291bnQsIGNhY2hlKSB7XG4gIHRoaXMuaWQgICAgICAgPSBpZFxuICB0aGlzLnNyYyAgICAgID0gc3JjXG4gIHRoaXMudHlwZSAgICAgPSB0eXBlXG4gIHRoaXMuc2hhZGVyICAgPSBzaGFkZXJcbiAgdGhpcy5jb3VudCAgICA9IGNvdW50XG4gIHRoaXMucHJvZ3JhbXMgPSBbXVxuICB0aGlzLmNhY2hlICAgID0gY2FjaGVcbn1cblxuU2hhZGVyUmVmZXJlbmNlLnByb3RvdHlwZS5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIGlmKC0tdGhpcy5jb3VudCA9PT0gMCkge1xuICAgIHZhciBjYWNoZSAgICA9IHRoaXMuY2FjaGVcbiAgICB2YXIgZ2wgICAgICAgPSBjYWNoZS5nbFxuXG4gICAgLy9SZW1vdmUgcHJvZ3JhbSByZWZlcmVuY2VzXG4gICAgdmFyIHByb2dyYW1zID0gdGhpcy5wcm9ncmFtc1xuICAgIGZvcih2YXIgaT0wLCBuPXByb2dyYW1zLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICAgIHZhciBwID0gY2FjaGUucHJvZ3JhbXNbcHJvZ3JhbXNbaV1dXG4gICAgICBpZihwKSB7XG4gICAgICAgIGRlbGV0ZSBjYWNoZS5wcm9ncmFtc1tpXVxuICAgICAgICBnbC5kZWxldGVQcm9ncmFtKHApXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9SZW1vdmUgc2hhZGVyIHJlZmVyZW5jZVxuICAgIGdsLmRlbGV0ZVNoYWRlcih0aGlzLnNoYWRlcilcbiAgICBkZWxldGUgY2FjaGUuc2hhZGVyc1sodGhpcy50eXBlID09PSBnbC5GUkFHTUVOVF9TSEFERVIpfDBdW3RoaXMuc3JjXVxuICB9XG59XG5cbmZ1bmN0aW9uIENvbnRleHRDYWNoZShnbCkge1xuICB0aGlzLmdsICAgICAgID0gZ2xcbiAgdGhpcy5zaGFkZXJzICA9IFt7fSwge31dXG4gIHRoaXMucHJvZ3JhbXMgPSB7fVxufVxuXG52YXIgcHJvdG8gPSBDb250ZXh0Q2FjaGUucHJvdG90eXBlXG5cbmZ1bmN0aW9uIGNvbXBpbGVTaGFkZXIoZ2wsIHR5cGUsIHNyYykge1xuICB2YXIgc2hhZGVyID0gZ2wuY3JlYXRlU2hhZGVyKHR5cGUpXG4gIGdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNyYylcbiAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpXG4gIGlmKCFnbC5nZXRTaGFkZXJQYXJhbWV0ZXIoc2hhZGVyLCBnbC5DT01QSUxFX1NUQVRVUykpIHtcbiAgICB2YXIgZXJyTG9nID0gZ2wuZ2V0U2hhZGVySW5mb0xvZyhzaGFkZXIpXG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIGZtdCA9IGZvcm1hdENvbXBpbGVyRXJyb3IoZXJyTG9nLCBzcmMsIHR5cGUpO1xuICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBmb3JtYXQgY29tcGlsZXIgZXJyb3I6ICcgKyBlKTtcbiAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoZXJyTG9nLCAnRXJyb3IgY29tcGlsaW5nIHNoYWRlcjpcXG4nICsgZXJyTG9nKVxuICAgIH1cbiAgICB0aHJvdyBuZXcgR0xFcnJvcihlcnJMb2csIGZtdC5zaG9ydCwgZm10LmxvbmcpXG4gIH1cbiAgcmV0dXJuIHNoYWRlclxufVxuXG5wcm90by5nZXRTaGFkZXJSZWZlcmVuY2UgPSBmdW5jdGlvbih0eXBlLCBzcmMpIHtcbiAgdmFyIGdsICAgICAgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXJzID0gdGhpcy5zaGFkZXJzWyh0eXBlID09PSBnbC5GUkFHTUVOVF9TSEFERVIpfDBdXG4gIHZhciBzaGFkZXIgID0gc2hhZGVyc1tzcmNdXG4gIGlmKCFzaGFkZXIgfHwgIWdsLmlzU2hhZGVyKHNoYWRlci5zaGFkZXIpKSB7XG4gICAgdmFyIHNoYWRlck9iaiA9IGNvbXBpbGVTaGFkZXIoZ2wsIHR5cGUsIHNyYylcbiAgICBzaGFkZXIgPSBzaGFkZXJzW3NyY10gPSBuZXcgU2hhZGVyUmVmZXJlbmNlKFxuICAgICAgU0hBREVSX0NPVU5URVIrKyxcbiAgICAgIHNyYyxcbiAgICAgIHR5cGUsXG4gICAgICBzaGFkZXJPYmosXG4gICAgICBbXSxcbiAgICAgIDEsXG4gICAgICB0aGlzKVxuICB9IGVsc2Uge1xuICAgIHNoYWRlci5jb3VudCArPSAxXG4gIH1cbiAgcmV0dXJuIHNoYWRlclxufVxuXG5mdW5jdGlvbiBsaW5rUHJvZ3JhbShnbCwgdnNoYWRlciwgZnNoYWRlciwgYXR0cmlicywgbG9jYXRpb25zKSB7XG4gIHZhciBwcm9ncmFtID0gZ2wuY3JlYXRlUHJvZ3JhbSgpXG4gIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCB2c2hhZGVyKVxuICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnNoYWRlcilcbiAgZm9yKHZhciBpPTA7IGk8YXR0cmlicy5sZW5ndGg7ICsraSkge1xuICAgIGdsLmJpbmRBdHRyaWJMb2NhdGlvbihwcm9ncmFtLCBsb2NhdGlvbnNbaV0sIGF0dHJpYnNbaV0pXG4gIH1cbiAgZ2wubGlua1Byb2dyYW0ocHJvZ3JhbSlcbiAgaWYoIWdsLmdldFByb2dyYW1QYXJhbWV0ZXIocHJvZ3JhbSwgZ2wuTElOS19TVEFUVVMpKSB7XG4gICAgdmFyIGVyckxvZyA9IGdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pXG4gICAgdGhyb3cgbmV3IEdMRXJyb3IoZXJyTG9nLCAnRXJyb3IgbGlua2luZyBwcm9ncmFtOiAnICsgZXJyTG9nKVxuICB9XG4gIHJldHVybiBwcm9ncmFtXG59XG5cbnByb3RvLmdldFByb2dyYW0gPSBmdW5jdGlvbih2cmVmLCBmcmVmLCBhdHRyaWJzLCBsb2NhdGlvbnMpIHtcbiAgdmFyIHRva2VuID0gW3ZyZWYuaWQsIGZyZWYuaWQsIGF0dHJpYnMuam9pbignOicpLCBsb2NhdGlvbnMuam9pbignOicpXS5qb2luKCdAJylcbiAgdmFyIHByb2cgID0gdGhpcy5wcm9ncmFtc1t0b2tlbl1cbiAgaWYoIXByb2cgfHwgIXRoaXMuZ2wuaXNQcm9ncmFtKHByb2cpKSB7XG4gICAgdGhpcy5wcm9ncmFtc1t0b2tlbl0gPSBwcm9nID0gbGlua1Byb2dyYW0oXG4gICAgICB0aGlzLmdsLFxuICAgICAgdnJlZi5zaGFkZXIsXG4gICAgICBmcmVmLnNoYWRlcixcbiAgICAgIGF0dHJpYnMsXG4gICAgICBsb2NhdGlvbnMpXG4gICAgdnJlZi5wcm9ncmFtcy5wdXNoKHRva2VuKVxuICAgIGZyZWYucHJvZ3JhbXMucHVzaCh0b2tlbilcbiAgfVxuICByZXR1cm4gcHJvZ1xufVxuXG5mdW5jdGlvbiBnZXRDYWNoZShnbCkge1xuICB2YXIgY3R4Q2FjaGUgPSBDQUNIRS5nZXQoZ2wpXG4gIGlmKCFjdHhDYWNoZSkge1xuICAgIGN0eENhY2hlID0gbmV3IENvbnRleHRDYWNoZShnbClcbiAgICBDQUNIRS5zZXQoZ2wsIGN0eENhY2hlKVxuICB9XG4gIHJldHVybiBjdHhDYWNoZVxufVxuXG5mdW5jdGlvbiBnZXRTaGFkZXJSZWZlcmVuY2UoZ2wsIHR5cGUsIHNyYykge1xuICByZXR1cm4gZ2V0Q2FjaGUoZ2wpLmdldFNoYWRlclJlZmVyZW5jZSh0eXBlLCBzcmMpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVByb2dyYW0oZ2wsIHZyZWYsIGZyZWYsIGF0dHJpYnMsIGxvY2F0aW9ucykge1xuICByZXR1cm4gZ2V0Q2FjaGUoZ2wpLmdldFByb2dyYW0odnJlZiwgZnJlZiwgYXR0cmlicywgbG9jYXRpb25zKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3Bpa2VzMkRcblxuZnVuY3Rpb24gR0xTcGlrZXMyRChwbG90KSB7XG4gIHRoaXMucGxvdCA9IHBsb3RcbiAgdGhpcy5lbmFibGUgPSBbdHJ1ZSwgdHJ1ZSwgZmFsc2UsIGZhbHNlXVxuICB0aGlzLndpZHRoICA9IFsxLCAxLCAxLCAxXVxuICB0aGlzLmNvbG9yICA9IFtbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICBbMCwwLDAsMV1dXG4gIHRoaXMuY2VudGVyID0gW0luZmluaXR5LCBJbmZpbml0eV1cbn1cblxudmFyIHByb3RvID0gR0xTcGlrZXMyRC5wcm90b3R5cGVcblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICB0aGlzLmVuYWJsZSA9IChvcHRpb25zLmVuYWJsZSB8fCBbdHJ1ZSx0cnVlLGZhbHNlLGZhbHNlXSkuc2xpY2UoKVxuICB0aGlzLndpZHRoICA9IChvcHRpb25zLndpZHRoIHx8IFsxLDEsMSwxXSkuc2xpY2UoKVxuICB0aGlzLmNvbG9yICA9IChvcHRpb25zLmNvbG9yIHx8IFtcbiAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV0pLm1hcChmdW5jdGlvbih4KSB7IHJldHVybiB4LnNsaWNlKCkgfSlcbiAgdGhpcy5jZW50ZXIgPSAob3B0aW9ucy5jZW50ZXIgfHwgW0luZmluaXR5LEluZmluaXR5XSkuc2xpY2UoKVxuICB0aGlzLnBsb3Quc2V0T3ZlcmxheURpcnR5KClcbn1cblxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc3Bpa2VFbmFibGUgPSB0aGlzLmVuYWJsZVxuICB2YXIgc3Bpa2VXaWR0aCAgPSB0aGlzLndpZHRoXG4gIHZhciBzcGlrZUNvbG9yICA9IHRoaXMuY29sb3JcbiAgdmFyIHNwaWtlQ2VudGVyID0gdGhpcy5jZW50ZXJcbiAgdmFyIHBsb3QgICAgICAgID0gdGhpcy5wbG90XG4gIHZhciBsaW5lICAgICAgICA9IHBsb3QubGluZVxuXG4gIHZhciBkYXRhQm94ICAgICA9IHBsb3QuZGF0YUJveFxuICB2YXIgdmlld1BpeGVscyAgPSBwbG90LnZpZXdCb3hcblxuICBsaW5lLmJpbmQoKVxuXG4gIGlmKGRhdGFCb3hbMF0gPD0gc3Bpa2VDZW50ZXJbMF0gJiYgc3Bpa2VDZW50ZXJbMF0gPD0gZGF0YUJveFsyXSAmJlxuICAgICBkYXRhQm94WzFdIDw9IHNwaWtlQ2VudGVyWzFdICYmIHNwaWtlQ2VudGVyWzFdIDw9IGRhdGFCb3hbM10pIHtcblxuICAgIHZhciBjZW50ZXJYID0gdmlld1BpeGVsc1swXSArIChzcGlrZUNlbnRlclswXSAtIGRhdGFCb3hbMF0pIC8gKGRhdGFCb3hbMl0gLSBkYXRhQm94WzBdKSAqICh2aWV3UGl4ZWxzWzJdIC0gdmlld1BpeGVsc1swXSlcbiAgICB2YXIgY2VudGVyWSA9IHZpZXdQaXhlbHNbMV0gKyAoc3Bpa2VDZW50ZXJbMV0gLSBkYXRhQm94WzFdKSAvIChkYXRhQm94WzNdIC0gZGF0YUJveFsxXSkgKiAodmlld1BpeGVsc1szXSAtIHZpZXdQaXhlbHNbMV0pXG5cbiAgICBpZihzcGlrZUVuYWJsZVswXSkge1xuICAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgIGNlbnRlclgsIGNlbnRlclksXG4gICAgICAgdmlld1BpeGVsc1swXSwgY2VudGVyWSxcbiAgICAgICBzcGlrZVdpZHRoWzBdLCBzcGlrZUNvbG9yWzBdKVxuICAgIH1cbiAgICBpZihzcGlrZUVuYWJsZVsxXSkge1xuICAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgIGNlbnRlclgsIGNlbnRlclksXG4gICAgICAgY2VudGVyWCwgdmlld1BpeGVsc1sxXSxcbiAgICAgICBzcGlrZVdpZHRoWzFdLCBzcGlrZUNvbG9yWzFdKVxuICAgIH1cbiAgICBpZihzcGlrZUVuYWJsZVsyXSkge1xuICAgICAgbGluZS5kcmF3TGluZShcbiAgICAgICAgY2VudGVyWCwgY2VudGVyWSxcbiAgICAgICAgdmlld1BpeGVsc1syXSwgY2VudGVyWSxcbiAgICAgICAgc3Bpa2VXaWR0aFsyXSwgc3Bpa2VDb2xvclsyXSlcbiAgICB9XG4gICAgaWYoc3Bpa2VFbmFibGVbM10pIHtcbiAgICAgIGxpbmUuZHJhd0xpbmUoXG4gICAgICAgIGNlbnRlclgsIGNlbnRlclksXG4gICAgICAgIGNlbnRlclgsIHZpZXdQaXhlbHNbM10sXG4gICAgICAgIHNwaWtlV2lkdGhbM10sIHNwaWtlQ29sb3JbM10pXG4gICAgfVxuICB9XG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5wbG90LnJlbW92ZU92ZXJsYXkodGhpcylcbn1cblxuZnVuY3Rpb24gY3JlYXRlU3Bpa2VzMkQocGxvdCwgb3B0aW9ucykge1xuICB2YXIgc3Bpa2VzID0gbmV3IEdMU3Bpa2VzMkQocGxvdClcbiAgc3Bpa2VzLnVwZGF0ZShvcHRpb25zKVxuICBwbG90LmFkZE92ZXJsYXkoc3Bpa2VzKVxuICByZXR1cm4gc3Bpa2VzXG59XG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBnbHNsaWZ5ICAgICAgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxudmFyIGNyZWF0ZVNoYWRlciA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcblxyXG52YXIgdmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbiwgY29sb3I7XFxuYXR0cmlidXRlIGZsb2F0IHdlaWdodDtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIGNvb3JkaW5hdGVzWzNdO1xcbnVuaWZvcm0gdmVjNCBjb2xvcnNbM107XFxudW5pZm9ybSB2ZWMyIHNjcmVlblNoYXBlO1xcbnVuaWZvcm0gZmxvYXQgbGluZVdpZHRoO1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyB2ZXJ0ZXhQb3NpdGlvbiA9IG1peChjb29yZGluYXRlc1swXSxcXG4gICAgbWl4KGNvb3JkaW5hdGVzWzJdLCBjb29yZGluYXRlc1sxXSwgMC41ICogKHBvc2l0aW9uICsgMS4wKSksIGFicyhwb3NpdGlvbikpO1xcblxcbiAgdmVjNCBjbGlwUG9zID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQodmVydGV4UG9zaXRpb24sIDEuMCk7XFxuICB2ZWMyIGNsaXBPZmZzZXQgPSAocHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQoY29sb3IsIDAuMCkpLnh5O1xcbiAgdmVjMiBkZWx0YSA9IHdlaWdodCAqIGNsaXBPZmZzZXQgKiBzY3JlZW5TaGFwZTtcXG4gIHZlYzIgbGluZU9mZnNldCA9IG5vcm1hbGl6ZSh2ZWMyKGRlbHRhLnksIC1kZWx0YS54KSkgLyBzY3JlZW5TaGFwZTtcXG5cXG4gIGdsX1Bvc2l0aW9uICAgPSB2ZWM0KGNsaXBQb3MueHkgKyBjbGlwUG9zLncgKiAwLjUgKiBsaW5lV2lkdGggKiBsaW5lT2Zmc2V0LCBjbGlwUG9zLnosIGNsaXBQb3Mudyk7XFxuICBmcmFnQ29sb3IgICAgID0gY29sb3IueCAqIGNvbG9yc1swXSArIGNvbG9yLnkgKiBjb2xvcnNbMV0gKyBjb2xvci56ICogY29sb3JzWzJdO1xcbn1cXG5cIl0pXHJcbnZhciBmcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcbn1cIl0pXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdsKSB7XHJcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgZnJhZ1NyYywgbnVsbCwgW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXHJcbiAgICB7bmFtZTogJ2NvbG9yJywgdHlwZTogJ3ZlYzMnfSxcclxuICAgIHtuYW1lOiAnd2VpZ2h0JywgdHlwZTogJ2Zsb2F0J31cclxuICBdKVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGNyZWF0ZUJ1ZmZlciA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXHJcbnZhciBjcmVhdGVWQU8gPSByZXF1aXJlKCdnbC12YW8nKVxyXG52YXIgY3JlYXRlU2hhZGVyID0gcmVxdWlyZSgnLi9zaGFkZXJzL2luZGV4JylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3Bpa2VzXHJcblxyXG52YXIgaWRlbnRpdHkgPSBbMSwwLDAsMCxcclxuICAgICAgICAgICAgICAgIDAsMSwwLDAsXHJcbiAgICAgICAgICAgICAgICAwLDAsMSwwLFxyXG4gICAgICAgICAgICAgICAgMCwwLDAsMV1cclxuXHJcbmZ1bmN0aW9uIEF4aXNTcGlrZXMoZ2wsIGJ1ZmZlciwgdmFvLCBzaGFkZXIpIHtcclxuICB0aGlzLmdsICAgICAgICAgPSBnbFxyXG4gIHRoaXMuYnVmZmVyICAgICA9IGJ1ZmZlclxyXG4gIHRoaXMudmFvICAgICAgICA9IHZhb1xyXG4gIHRoaXMuc2hhZGVyICAgICA9IHNoYWRlclxyXG4gIHRoaXMucGl4ZWxSYXRpbyA9IDFcclxuICB0aGlzLmJvdW5kcyAgICAgPSBbWy0xMDAwLC0xMDAwLC0xMDAwXSwgWzEwMDAsMTAwMCwxMDAwXV1cclxuICB0aGlzLnBvc2l0aW9uICAgPSBbMCwwLDBdXHJcbiAgdGhpcy5saW5lV2lkdGggID0gWzIsMiwyXVxyXG4gIHRoaXMuY29sb3JzICAgICA9IFtbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdXVxyXG4gIHRoaXMuZW5hYmxlZCAgICA9IFt0cnVlLHRydWUsdHJ1ZV1cclxuICB0aGlzLmRyYXdTaWRlcyAgPSBbdHJ1ZSx0cnVlLHRydWVdXHJcbiAgdGhpcy5heGVzICAgICAgID0gbnVsbFxyXG59XHJcblxyXG52YXIgcHJvdG8gPSBBeGlzU3Bpa2VzLnByb3RvdHlwZVxyXG5cclxudmFyIE9VVEVSX0ZBQ0UgPSBbMCwwLDBdXHJcbnZhciBJTk5FUl9GQUNFID0gWzAsMCwwXVxyXG5cclxudmFyIFNIQVBFID0gWzAsMF1cclxuXHJcbnByb3RvLmlzVHJhbnNwYXJlbnQgPSBmdW5jdGlvbigpIHtcclxuICByZXR1cm4gZmFsc2VcclxufVxyXG5cclxucHJvdG8uZHJhd1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oY2FtZXJhKSB7fVxyXG5cclxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKGNhbWVyYSkge1xyXG4gIHZhciBnbCA9IHRoaXMuZ2xcclxuICB2YXIgdmFvID0gdGhpcy52YW9cclxuICB2YXIgc2hhZGVyID0gdGhpcy5zaGFkZXJcclxuXHJcbiAgdmFvLmJpbmQoKVxyXG4gIHNoYWRlci5iaW5kKClcclxuXHJcbiAgdmFyIG1vZGVsICAgICAgPSBjYW1lcmEubW9kZWwgfHwgaWRlbnRpdHlcclxuICB2YXIgdmlldyAgICAgICA9IGNhbWVyYS52aWV3IHx8IGlkZW50aXR5XHJcbiAgdmFyIHByb2plY3Rpb24gPSBjYW1lcmEucHJvamVjdGlvbiB8fCBpZGVudGl0eVxyXG5cclxuICB2YXIgYXhpc1xyXG4gIGlmKHRoaXMuYXhlcykge1xyXG4gICAgYXhpcyA9IHRoaXMuYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXNcclxuICB9XHJcblxyXG4gIHZhciBvdXRlckZhY2UgPSBPVVRFUl9GQUNFXHJcbiAgdmFyIGlubmVyRmFjZSA9IElOTkVSX0ZBQ0VcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIGlmKGF4aXMgJiYgYXhpc1tpXSA8IDApIHtcclxuICAgICAgb3V0ZXJGYWNlW2ldID0gdGhpcy5ib3VuZHNbMF1baV1cclxuICAgICAgaW5uZXJGYWNlW2ldID0gdGhpcy5ib3VuZHNbMV1baV1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIG91dGVyRmFjZVtpXSA9IHRoaXMuYm91bmRzWzFdW2ldXHJcbiAgICAgIGlubmVyRmFjZVtpXSA9IHRoaXMuYm91bmRzWzBdW2ldXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBTSEFQRVswXSA9IGdsLmRyYXdpbmdCdWZmZXJXaWR0aFxyXG4gIFNIQVBFWzFdID0gZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxyXG5cclxuICBzaGFkZXIudW5pZm9ybXMubW9kZWwgICAgICAgPSBtb2RlbFxyXG4gIHNoYWRlci51bmlmb3Jtcy52aWV3ICAgICAgICA9IHZpZXdcclxuICBzaGFkZXIudW5pZm9ybXMucHJvamVjdGlvbiAgPSBwcm9qZWN0aW9uXHJcbiAgc2hhZGVyLnVuaWZvcm1zLmNvb3JkaW5hdGVzID0gW3RoaXMucG9zaXRpb24sIG91dGVyRmFjZSwgaW5uZXJGYWNlXVxyXG4gIHNoYWRlci51bmlmb3Jtcy5jb2xvcnMgICAgICA9IHRoaXMuY29sb3JzXHJcbiAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlblNoYXBlID0gU0hBUEVcclxuXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBzaGFkZXIudW5pZm9ybXMubGluZVdpZHRoID0gdGhpcy5saW5lV2lkdGhbaV0gKiB0aGlzLnBpeGVsUmF0aW9cclxuICAgIGlmKHRoaXMuZW5hYmxlZFtpXSkge1xyXG4gICAgICB2YW8uZHJhdyhnbC5UUklBTkdMRVMsIDYsIDYqaSlcclxuICAgICAgaWYodGhpcy5kcmF3U2lkZXNbaV0pIHtcclxuICAgICAgICB2YW8uZHJhdyhnbC5UUklBTkdMRVMsIDEyLCAxOCsxMippKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YW8udW5iaW5kKClcclxufVxyXG5cclxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xyXG4gIGlmKCFvcHRpb25zKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcbiAgaWYoXCJib3VuZHNcIiBpbiBvcHRpb25zKSB7XHJcbiAgICB0aGlzLmJvdW5kcyA9IG9wdGlvbnMuYm91bmRzXHJcbiAgfVxyXG4gIGlmKFwicG9zaXRpb25cIiBpbiBvcHRpb25zKSB7XHJcbiAgICB0aGlzLnBvc2l0aW9uID0gb3B0aW9ucy5wb3NpdGlvblxyXG4gIH1cclxuICBpZihcImxpbmVXaWR0aFwiIGluIG9wdGlvbnMpIHtcclxuICAgIHRoaXMubGluZVdpZHRoID0gb3B0aW9ucy5saW5lV2lkdGhcclxuICB9XHJcbiAgaWYoXCJjb2xvcnNcIiBpbiBvcHRpb25zKSB7XHJcbiAgICB0aGlzLmNvbG9ycyA9IG9wdGlvbnMuY29sb3JzXHJcbiAgfVxyXG4gIGlmKFwiZW5hYmxlZFwiIGluIG9wdGlvbnMpIHtcclxuICAgIHRoaXMuZW5hYmxlZCA9IG9wdGlvbnMuZW5hYmxlZFxyXG4gIH1cclxuICBpZihcImRyYXdTaWRlc1wiIGluIG9wdGlvbnMpIHtcclxuICAgIHRoaXMuZHJhd1NpZGVzID0gb3B0aW9ucy5kcmF3U2lkZXNcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcclxuICB0aGlzLnZhby5kaXNwb3NlKClcclxuICB0aGlzLmJ1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcclxufVxyXG5cclxuXHJcblxyXG5mdW5jdGlvbiBjcmVhdGVTcGlrZXMoZ2wsIG9wdGlvbnMpIHtcclxuICAvL0NyZWF0ZSBidWZmZXJzXHJcbiAgdmFyIGRhdGEgPSBbIF1cclxuXHJcbiAgZnVuY3Rpb24gbGluZSh4LHkseixpLGwsaCkge1xyXG4gICAgdmFyIHJvdyA9IFt4LHkseiwgIDAsMCwwLCAgMV1cclxuICAgIHJvd1tpKzNdID0gMVxyXG4gICAgcm93W2ldID0gbFxyXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcclxuICAgIHJvd1s2XSA9IC0xXHJcbiAgICBkYXRhLnB1c2guYXBwbHkoZGF0YSwgcm93KVxyXG4gICAgcm93W2ldID0gaFxyXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcclxuICAgIGRhdGEucHVzaC5hcHBseShkYXRhLCByb3cpXHJcbiAgICByb3dbNl0gPSAxXHJcbiAgICBkYXRhLnB1c2guYXBwbHkoZGF0YSwgcm93KVxyXG4gICAgcm93W2ldID0gbFxyXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcclxuICB9XHJcblxyXG4gIGxpbmUoMCwwLDAsIDAsIDAsIDEpXHJcbiAgbGluZSgwLDAsMCwgMSwgMCwgMSlcclxuICBsaW5lKDAsMCwwLCAyLCAwLCAxKVxyXG5cclxuICBsaW5lKDEsMCwwLCAgMSwgIC0xLDEpXHJcbiAgbGluZSgxLDAsMCwgIDIsICAtMSwxKVxyXG5cclxuICBsaW5lKDAsMSwwLCAgMCwgIC0xLDEpXHJcbiAgbGluZSgwLDEsMCwgIDIsICAtMSwxKVxyXG5cclxuICBsaW5lKDAsMCwxLCAgMCwgIC0xLDEpXHJcbiAgbGluZSgwLDAsMSwgIDEsICAtMSwxKVxyXG5cclxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsLCBkYXRhKVxyXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFt7XHJcbiAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgc2l6ZTogMyxcclxuICAgIG9mZnNldDogMCxcclxuICAgIHN0cmlkZTogMjhcclxuICB9LCB7XHJcbiAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgIGJ1ZmZlcjogYnVmZmVyLFxyXG4gICAgc2l6ZTogMyxcclxuICAgIG9mZnNldDogMTIsXHJcbiAgICBzdHJpZGU6IDI4XHJcbiAgfSwge1xyXG4gICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICBidWZmZXI6IGJ1ZmZlcixcclxuICAgIHNpemU6IDEsXHJcbiAgICBvZmZzZXQ6IDI0LFxyXG4gICAgc3RyaWRlOiAyOFxyXG4gIH1dKVxyXG5cclxuICAvL0NyZWF0ZSBzaGFkZXJcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLndlaWdodC5sb2NhdGlvbiA9IDJcclxuXHJcbiAgLy9DcmVhdGUgc3Bpa2Ugb2JqZWN0XHJcbiAgdmFyIHNwaWtlcyA9IG5ldyBBeGlzU3Bpa2VzKGdsLCBidWZmZXIsIHZhbywgc2hhZGVyKVxyXG5cclxuICAvL1NldCBwYXJhbWV0ZXJzXHJcbiAgc3Bpa2VzLnVwZGF0ZShvcHRpb25zKVxyXG5cclxuICAvL1JldHVybiByZXN1bHRpbmcgb2JqZWN0XHJcbiAgcmV0dXJuIHNwaWtlc1xyXG59XHJcbiIsInZhciBnbHNsaWZ5ICAgICAgID0gcmVxdWlyZSgnZ2xzbGlmeScpXHJcblxyXG52YXIgdHJpVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5mbG9hdCBpbnZlcnNlKGZsb2F0IG0pIHtcXG4gIHJldHVybiAxLjAgLyBtO1xcbn1cXG5cXG5tYXQyIGludmVyc2UobWF0MiBtKSB7XFxuICByZXR1cm4gbWF0MihtWzFdWzFdLC1tWzBdWzFdLFxcbiAgICAgICAgICAgICAtbVsxXVswXSwgbVswXVswXSkgLyAobVswXVswXSptWzFdWzFdIC0gbVswXVsxXSptWzFdWzBdKTtcXG59XFxuXFxubWF0MyBpbnZlcnNlKG1hdDMgbSkge1xcbiAgZmxvYXQgYTAwID0gbVswXVswXSwgYTAxID0gbVswXVsxXSwgYTAyID0gbVswXVsyXTtcXG4gIGZsb2F0IGExMCA9IG1bMV1bMF0sIGExMSA9IG1bMV1bMV0sIGExMiA9IG1bMV1bMl07XFxuICBmbG9hdCBhMjAgPSBtWzJdWzBdLCBhMjEgPSBtWzJdWzFdLCBhMjIgPSBtWzJdWzJdO1xcblxcbiAgZmxvYXQgYjAxID0gYTIyICogYTExIC0gYTEyICogYTIxO1xcbiAgZmxvYXQgYjExID0gLWEyMiAqIGExMCArIGExMiAqIGEyMDtcXG4gIGZsb2F0IGIyMSA9IGEyMSAqIGExMCAtIGExMSAqIGEyMDtcXG5cXG4gIGZsb2F0IGRldCA9IGEwMCAqIGIwMSArIGEwMSAqIGIxMSArIGEwMiAqIGIyMTtcXG5cXG4gIHJldHVybiBtYXQzKGIwMSwgKC1hMjIgKiBhMDEgKyBhMDIgKiBhMjEpLCAoYTEyICogYTAxIC0gYTAyICogYTExKSxcXG4gICAgICAgICAgICAgIGIxMSwgKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCksICgtYTEyICogYTAwICsgYTAyICogYTEwKSxcXG4gICAgICAgICAgICAgIGIyMSwgKC1hMjEgKiBhMDAgKyBhMDEgKiBhMjApLCAoYTExICogYTAwIC0gYTAxICogYTEwKSkgLyBkZXQ7XFxufVxcblxcbm1hdDQgaW52ZXJzZShtYXQ0IG0pIHtcXG4gIGZsb2F0XFxuICAgICAgYTAwID0gbVswXVswXSwgYTAxID0gbVswXVsxXSwgYTAyID0gbVswXVsyXSwgYTAzID0gbVswXVszXSxcXG4gICAgICBhMTAgPSBtWzFdWzBdLCBhMTEgPSBtWzFdWzFdLCBhMTIgPSBtWzFdWzJdLCBhMTMgPSBtWzFdWzNdLFxcbiAgICAgIGEyMCA9IG1bMl1bMF0sIGEyMSA9IG1bMl1bMV0sIGEyMiA9IG1bMl1bMl0sIGEyMyA9IG1bMl1bM10sXFxuICAgICAgYTMwID0gbVszXVswXSwgYTMxID0gbVszXVsxXSwgYTMyID0gbVszXVsyXSwgYTMzID0gbVszXVszXSxcXG5cXG4gICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXFxuICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxcbiAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcXG4gICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXFxuICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxcbiAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcXG4gICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXFxuICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxcbiAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcXG4gICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXFxuICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxcbiAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMixcXG5cXG4gICAgICBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7XFxuXFxuICByZXR1cm4gbWF0NChcXG4gICAgICBhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDksXFxuICAgICAgYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5LFxcbiAgICAgIGEzMSAqIGIwNSAtIGEzMiAqIGIwNCArIGEzMyAqIGIwMyxcXG4gICAgICBhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMsXFxuICAgICAgYTEyICogYjA4IC0gYTEwICogYjExIC0gYTEzICogYjA3LFxcbiAgICAgIGEwMCAqIGIxMSAtIGEwMiAqIGIwOCArIGEwMyAqIGIwNyxcXG4gICAgICBhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEsXFxuICAgICAgYTIwICogYjA1IC0gYTIyICogYjAyICsgYTIzICogYjAxLFxcbiAgICAgIGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNixcXG4gICAgICBhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYsXFxuICAgICAgYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwLFxcbiAgICAgIGEyMSAqIGIwMiAtIGEyMCAqIGIwNCAtIGEyMyAqIGIwMCxcXG4gICAgICBhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYsXFxuICAgICAgYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2LFxcbiAgICAgIGEzMSAqIGIwMSAtIGEzMCAqIGIwMyAtIGEzMiAqIGIwMCxcXG4gICAgICBhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApIC8gZGV0O1xcbn1cXG5cXG52ZWMzIGdldE9ydGhvZ29uYWxWZWN0b3IodmVjMyB2KSB7XFxuICAvLyBSZXR1cm4gdXAtdmVjdG9yIGZvciBvbmx5LXogdmVjdG9yLlxcbiAgLy8gUmV0dXJuIGF4ICsgYnkgKyBjeiA9IDAsIGEgcG9pbnQgdGhhdCBsaWVzIG9uIHRoZSBwbGFuZSB0aGF0IGhhcyB2IGFzIGEgbm9ybWFsIGFuZCB0aGF0IGlzbid0ICgwLDAsMCkuXFxuICAvLyBGcm9tIHRoZSBhYm92ZSBpZi1zdGF0ZW1lbnQgd2UgaGF2ZSB8fGF8fCA+IDAgIFUgIHx8Ynx8ID4gMC5cXG4gIC8vIEFzc2lnbiB6ID0gMCwgeCA9IC1iLCB5ID0gYTpcXG4gIC8vIGEqLWIgKyBiKmEgKyBjKjAgPSAtYmEgKyBiYSArIDAgPSAwXFxuICBpZiAodi54KnYueCA+IHYueip2LnogfHwgdi55KnYueSA+IHYueip2LnopIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKC12LnksIHYueCwgMC4wKSk7XFxuICB9IGVsc2Uge1xcbiAgICByZXR1cm4gbm9ybWFsaXplKHZlYzMoMC4wLCB2LnosIC12LnkpKTtcXG4gIH1cXG59XFxuXFxuLy8gQ2FsY3VsYXRlIHRoZSB0dWJlIHZlcnRleCBhbmQgbm9ybWFsIGF0IHRoZSBnaXZlbiBpbmRleC5cXG4vL1xcbi8vIFRoZSByZXR1cm5lZCB2ZXJ0ZXggaXMgZm9yIGEgdHViZSByaW5nIHdpdGggaXRzIGNlbnRlciBhdCBvcmlnaW4sIHJhZGl1cyBvZiBsZW5ndGgoZCksIHBvaW50aW5nIGluIHRoZSBkaXJlY3Rpb24gb2YgZC5cXG4vL1xcbi8vIEVhY2ggdHViZSBzZWdtZW50IGlzIG1hZGUgdXAgb2YgYSByaW5nIG9mIHZlcnRpY2VzLlxcbi8vIFRoZXNlIHZlcnRpY2VzIGFyZSB1c2VkIHRvIG1ha2UgdXAgdGhlIHRyaWFuZ2xlcyBvZiB0aGUgdHViZSBieSBjb25uZWN0aW5nIHRoZW0gdG9nZXRoZXIgaW4gdGhlIHZlcnRleCBhcnJheS5cXG4vLyBUaGUgaW5kZXhlcyBvZiB0dWJlIHNlZ21lbnRzIHJ1biBmcm9tIDAgdG8gOC5cXG4vL1xcbnZlYzMgZ2V0VHViZVBvc2l0aW9uKHZlYzMgZCwgZmxvYXQgaW5kZXgsIG91dCB2ZWMzIG5vcm1hbCkge1xcbiAgZmxvYXQgc2VnbWVudENvdW50ID0gOC4wO1xcblxcbiAgZmxvYXQgYW5nbGUgPSAyLjAgKiAzLjE0MTU5ICogKGluZGV4IC8gc2VnbWVudENvdW50KTtcXG5cXG4gIHZlYzMgdSA9IGdldE9ydGhvZ29uYWxWZWN0b3IoZCk7XFxuICB2ZWMzIHYgPSBub3JtYWxpemUoY3Jvc3ModSwgZCkpO1xcblxcbiAgdmVjMyB4ID0gdSAqIGNvcyhhbmdsZSkgKiBsZW5ndGgoZCk7XFxuICB2ZWMzIHkgPSB2ICogc2luKGFuZ2xlKSAqIGxlbmd0aChkKTtcXG4gIHZlYzMgdjMgPSB4ICsgeTtcXG5cXG4gIG5vcm1hbCA9IG5vcm1hbGl6ZSh2Myk7XFxuXFxuICByZXR1cm4gdjM7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHZlY3RvcjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvciwgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzIgdXY7XFxudW5pZm9ybSBmbG9hdCB0dWJlU2NhbGU7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsXFxuICAgICAgICAgICAsIHZpZXdcXG4gICAgICAgICAgICwgcHJvamVjdGlvbjtcXG51bmlmb3JtIHZlYzMgZXllUG9zaXRpb25cXG4gICAgICAgICAgICwgbGlnaHRQb3NpdGlvbjtcXG5cXG52YXJ5aW5nIHZlYzMgZl9ub3JtYWxcXG4gICAgICAgICAgICwgZl9saWdodERpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2V5ZURpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2RhdGFcXG4gICAgICAgICAgICwgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAvLyBTY2FsZSB0aGUgdmVjdG9yIG1hZ25pdHVkZSB0byBzdGF5IGNvbnN0YW50IHdpdGhcXG4gIC8vIG1vZGVsICYgdmlldyBjaGFuZ2VzLlxcbiAgdmVjMyBub3JtYWw7XFxuICB2ZWMzIFhZWiA9IGdldFR1YmVQb3NpdGlvbihtYXQzKG1vZGVsKSAqICh0dWJlU2NhbGUgKiB2ZWN0b3IudyAqIG5vcm1hbGl6ZSh2ZWN0b3IueHl6KSksIHBvc2l0aW9uLncsIG5vcm1hbCk7XFxuICB2ZWM0IHR1YmVQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbi54eXosIDEuMCkgKyB2ZWM0KFhZWiwgMC4wKTtcXG4gIG5vcm1hbCA9IG5vcm1hbGl6ZShub3JtYWwgKiBpbnZlcnNlKG1hdDMobW9kZWwpKSk7XFxuXFxuICBnbF9Qb3NpdGlvbiAgICAgID0gcHJvamVjdGlvbiAqIHZpZXcgKiB0dWJlUG9zaXRpb247XFxuICBmX2NvbG9yICAgICAgICAgID0gY29sb3I7XFxuICBmX25vcm1hbCAgICAgICAgID0gbm9ybWFsO1xcbiAgZl9kYXRhICAgICAgICAgICA9IHR1YmVQb3NpdGlvbi54eXo7XFxuICBmX3Bvc2l0aW9uICAgICAgID0gcG9zaXRpb24ueHl6O1xcbiAgZl9leWVEaXJlY3Rpb24gICA9IGV5ZVBvc2l0aW9uICAgLSB0dWJlUG9zaXRpb24ueHl6O1xcbiAgZl9saWdodERpcmVjdGlvbiA9IGxpZ2h0UG9zaXRpb24gLSB0dWJlUG9zaXRpb24ueHl6O1xcbiAgZl91diAgICAgICAgICAgICA9IHV2O1xcbn1cXG5cIl0pXHJcbnZhciB0cmlGcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmZsb2F0IGJlY2ttYW5uRGlzdHJpYnV0aW9uKGZsb2F0IHgsIGZsb2F0IHJvdWdobmVzcykge1xcbiAgZmxvYXQgTmRvdEggPSBtYXgoeCwgMC4wMDAxKTtcXG4gIGZsb2F0IGNvczJBbHBoYSA9IE5kb3RIICogTmRvdEg7XFxuICBmbG9hdCB0YW4yQWxwaGEgPSAoY29zMkFscGhhIC0gMS4wKSAvIGNvczJBbHBoYTtcXG4gIGZsb2F0IHJvdWdobmVzczIgPSByb3VnaG5lc3MgKiByb3VnaG5lc3M7XFxuICBmbG9hdCBkZW5vbSA9IDMuMTQxNTkyNjUzNTg5NzkzICogcm91Z2huZXNzMiAqIGNvczJBbHBoYSAqIGNvczJBbHBoYTtcXG4gIHJldHVybiBleHAodGFuMkFscGhhIC8gcm91Z2huZXNzMikgLyBkZW5vbTtcXG59XFxuXFxuZmxvYXQgY29va1RvcnJhbmNlU3BlY3VsYXIoXFxuICB2ZWMzIGxpZ2h0RGlyZWN0aW9uLFxcbiAgdmVjMyB2aWV3RGlyZWN0aW9uLFxcbiAgdmVjMyBzdXJmYWNlTm9ybWFsLFxcbiAgZmxvYXQgcm91Z2huZXNzLFxcbiAgZmxvYXQgZnJlc25lbCkge1xcblxcbiAgZmxvYXQgVmRvdE4gPSBtYXgoZG90KHZpZXdEaXJlY3Rpb24sIHN1cmZhY2VOb3JtYWwpLCAwLjApO1xcbiAgZmxvYXQgTGRvdE4gPSBtYXgoZG90KGxpZ2h0RGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsKSwgMC4wKTtcXG5cXG4gIC8vSGFsZiBhbmdsZSB2ZWN0b3JcXG4gIHZlYzMgSCA9IG5vcm1hbGl6ZShsaWdodERpcmVjdGlvbiArIHZpZXdEaXJlY3Rpb24pO1xcblxcbiAgLy9HZW9tZXRyaWMgdGVybVxcbiAgZmxvYXQgTmRvdEggPSBtYXgoZG90KHN1cmZhY2VOb3JtYWwsIEgpLCAwLjApO1xcbiAgZmxvYXQgVmRvdEggPSBtYXgoZG90KHZpZXdEaXJlY3Rpb24sIEgpLCAwLjAwMDAwMSk7XFxuICBmbG9hdCBMZG90SCA9IG1heChkb3QobGlnaHREaXJlY3Rpb24sIEgpLCAwLjAwMDAwMSk7XFxuICBmbG9hdCBHMSA9ICgyLjAgKiBOZG90SCAqIFZkb3ROKSAvIFZkb3RIO1xcbiAgZmxvYXQgRzIgPSAoMi4wICogTmRvdEggKiBMZG90TikgLyBMZG90SDtcXG4gIGZsb2F0IEcgPSBtaW4oMS4wLCBtaW4oRzEsIEcyKSk7XFxuICBcXG4gIC8vRGlzdHJpYnV0aW9uIHRlcm1cXG4gIGZsb2F0IEQgPSBiZWNrbWFubkRpc3RyaWJ1dGlvbihOZG90SCwgcm91Z2huZXNzKTtcXG5cXG4gIC8vRnJlc25lbCB0ZXJtXFxuICBmbG9hdCBGID0gcG93KDEuMCAtIFZkb3ROLCBmcmVzbmVsKTtcXG5cXG4gIC8vTXVsdGlwbHkgdGVybXMgYW5kIGRvbmVcXG4gIHJldHVybiAgRyAqIEYgKiBEIC8gbWF4KDMuMTQxNTkyNjUgKiBWZG90TiwgMC4wMDAwMDEpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHJvdWdobmVzc1xcbiAgICAgICAgICAgICwgZnJlc25lbFxcbiAgICAgICAgICAgICwga2FtYmllbnRcXG4gICAgICAgICAgICAsIGtkaWZmdXNlXFxuICAgICAgICAgICAgLCBrc3BlY3VsYXJcXG4gICAgICAgICAgICAsIG9wYWNpdHk7XFxudW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTtcXG5cXG52YXJ5aW5nIHZlYzMgZl9ub3JtYWxcXG4gICAgICAgICAgICwgZl9saWdodERpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2V5ZURpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2RhdGFcXG4gICAgICAgICAgICwgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuXFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX3Bvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIHZlYzMgTiA9IG5vcm1hbGl6ZShmX25vcm1hbCk7XFxuICB2ZWMzIEwgPSBub3JtYWxpemUoZl9saWdodERpcmVjdGlvbik7XFxuICB2ZWMzIFYgPSBub3JtYWxpemUoZl9leWVEaXJlY3Rpb24pO1xcblxcbiAgaWYoIWdsX0Zyb250RmFjaW5nKSB7XFxuICAgIE4gPSAtTjtcXG4gIH1cXG5cXG4gIGZsb2F0IHNwZWN1bGFyID0gY29va1RvcnJhbmNlU3BlY3VsYXIoTCwgViwgTiwgcm91Z2huZXNzLCBmcmVzbmVsKTtcXG4gIGZsb2F0IGRpZmZ1c2UgID0gbWluKGthbWJpZW50ICsga2RpZmZ1c2UgKiBtYXgoZG90KE4sIEwpLCAwLjApLCAxLjApO1xcblxcbiAgdmVjNCBzdXJmYWNlQ29sb3IgPSAgdGV4dHVyZTJEKHRleHR1cmUsIGZfdXYpO1xcbiAgdmVjNCBsaXRDb2xvciA9IHN1cmZhY2VDb2xvci5hICogdmVjNChkaWZmdXNlICogc3VyZmFjZUNvbG9yLnJnYiArIGtzcGVjdWxhciAqIHZlYzMoMSwxLDEpICogc3BlY3VsYXIsICAxLjApO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gbGl0Q29sb3IgKiBvcGFjaXR5O1xcbn1cIl0pXHJcbnZhciBwaWNrVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52ZWMzIGdldE9ydGhvZ29uYWxWZWN0b3IodmVjMyB2KSB7XFxuICAvLyBSZXR1cm4gdXAtdmVjdG9yIGZvciBvbmx5LXogdmVjdG9yLlxcbiAgLy8gUmV0dXJuIGF4ICsgYnkgKyBjeiA9IDAsIGEgcG9pbnQgdGhhdCBsaWVzIG9uIHRoZSBwbGFuZSB0aGF0IGhhcyB2IGFzIGEgbm9ybWFsIGFuZCB0aGF0IGlzbid0ICgwLDAsMCkuXFxuICAvLyBGcm9tIHRoZSBhYm92ZSBpZi1zdGF0ZW1lbnQgd2UgaGF2ZSB8fGF8fCA+IDAgIFUgIHx8Ynx8ID4gMC5cXG4gIC8vIEFzc2lnbiB6ID0gMCwgeCA9IC1iLCB5ID0gYTpcXG4gIC8vIGEqLWIgKyBiKmEgKyBjKjAgPSAtYmEgKyBiYSArIDAgPSAwXFxuICBpZiAodi54KnYueCA+IHYueip2LnogfHwgdi55KnYueSA+IHYueip2LnopIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKC12LnksIHYueCwgMC4wKSk7XFxuICB9IGVsc2Uge1xcbiAgICByZXR1cm4gbm9ybWFsaXplKHZlYzMoMC4wLCB2LnosIC12LnkpKTtcXG4gIH1cXG59XFxuXFxuLy8gQ2FsY3VsYXRlIHRoZSB0dWJlIHZlcnRleCBhbmQgbm9ybWFsIGF0IHRoZSBnaXZlbiBpbmRleC5cXG4vL1xcbi8vIFRoZSByZXR1cm5lZCB2ZXJ0ZXggaXMgZm9yIGEgdHViZSByaW5nIHdpdGggaXRzIGNlbnRlciBhdCBvcmlnaW4sIHJhZGl1cyBvZiBsZW5ndGgoZCksIHBvaW50aW5nIGluIHRoZSBkaXJlY3Rpb24gb2YgZC5cXG4vL1xcbi8vIEVhY2ggdHViZSBzZWdtZW50IGlzIG1hZGUgdXAgb2YgYSByaW5nIG9mIHZlcnRpY2VzLlxcbi8vIFRoZXNlIHZlcnRpY2VzIGFyZSB1c2VkIHRvIG1ha2UgdXAgdGhlIHRyaWFuZ2xlcyBvZiB0aGUgdHViZSBieSBjb25uZWN0aW5nIHRoZW0gdG9nZXRoZXIgaW4gdGhlIHZlcnRleCBhcnJheS5cXG4vLyBUaGUgaW5kZXhlcyBvZiB0dWJlIHNlZ21lbnRzIHJ1biBmcm9tIDAgdG8gOC5cXG4vL1xcbnZlYzMgZ2V0VHViZVBvc2l0aW9uKHZlYzMgZCwgZmxvYXQgaW5kZXgsIG91dCB2ZWMzIG5vcm1hbCkge1xcbiAgZmxvYXQgc2VnbWVudENvdW50ID0gOC4wO1xcblxcbiAgZmxvYXQgYW5nbGUgPSAyLjAgKiAzLjE0MTU5ICogKGluZGV4IC8gc2VnbWVudENvdW50KTtcXG5cXG4gIHZlYzMgdSA9IGdldE9ydGhvZ29uYWxWZWN0b3IoZCk7XFxuICB2ZWMzIHYgPSBub3JtYWxpemUoY3Jvc3ModSwgZCkpO1xcblxcbiAgdmVjMyB4ID0gdSAqIGNvcyhhbmdsZSkgKiBsZW5ndGgoZCk7XFxuICB2ZWMzIHkgPSB2ICogc2luKGFuZ2xlKSAqIGxlbmd0aChkKTtcXG4gIHZlYzMgdjMgPSB4ICsgeTtcXG5cXG4gIG5vcm1hbCA9IG5vcm1hbGl6ZSh2Myk7XFxuXFxuICByZXR1cm4gdjM7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHZlY3RvcjtcXG5hdHRyaWJ1dGUgdmVjNCBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBpZDtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSBmbG9hdCB0dWJlU2NhbGU7XFxuXFxudmFyeWluZyB2ZWMzIGZfcG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZfaWQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBub3JtYWw7XFxuICB2ZWMzIFhZWiA9IGdldFR1YmVQb3NpdGlvbihtYXQzKG1vZGVsKSAqICh0dWJlU2NhbGUgKiB2ZWN0b3IudyAqIG5vcm1hbGl6ZSh2ZWN0b3IueHl6KSksIHBvc2l0aW9uLncsIG5vcm1hbCk7XFxuICB2ZWM0IHR1YmVQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbi54eXosIDEuMCkgKyB2ZWM0KFhZWiwgMC4wKTtcXG5cXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiB0dWJlUG9zaXRpb247XFxuICBmX2lkICAgICAgICA9IGlkO1xcbiAgZl9wb3NpdGlvbiAgPSBwb3NpdGlvbi54eXo7XFxufVxcblwiXSlcclxudmFyIHBpY2tGcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyAgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHBpY2tJZDtcXG5cXG52YXJ5aW5nIHZlYzMgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9pZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX3Bvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQocGlja0lkLCBmX2lkLnh5eik7XFxufVwiXSlcclxuXHJcbmV4cG9ydHMubWVzaFNoYWRlciA9IHtcclxuICB2ZXJ0ZXg6ICAgdHJpVmVydFNyYyxcclxuICBmcmFnbWVudDogdHJpRnJhZ1NyYyxcclxuICBhdHRyaWJ1dGVzOiBbXHJcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfSxcclxuICAgIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9LFxyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWMyJ30sXHJcbiAgICB7bmFtZTogJ3ZlY3RvcicsIHR5cGU6ICd2ZWM0J31cclxuICBdXHJcbn1cclxuZXhwb3J0cy5waWNrU2hhZGVyID0ge1xyXG4gIHZlcnRleDogICBwaWNrVmVydFNyYyxcclxuICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXHJcbiAgYXR0cmlidXRlczogW1xyXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfSxcclxuICAgIHtuYW1lOiAndmVjdG9yJywgdHlwZTogJ3ZlYzQnfVxyXG4gIF1cclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gPSAxZS02OyAvLyBtYXkgYmUgdG9vIGxhcmdlIGlmIHRyaWFuZ2xlcyBhcmUgdmVyeSBzbWFsbFxyXG52YXIgREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA9IDFlLTY7XHJcblxyXG52YXIgY3JlYXRlU2hhZGVyICA9IHJlcXVpcmUoJ2dsLXNoYWRlcicpXHJcbnZhciBjcmVhdGVCdWZmZXIgID0gcmVxdWlyZSgnZ2wtYnVmZmVyJylcclxudmFyIGNyZWF0ZVZBTyAgICAgPSByZXF1aXJlKCdnbC12YW8nKVxyXG52YXIgY3JlYXRlVGV4dHVyZSA9IHJlcXVpcmUoJ2dsLXRleHR1cmUyZCcpXHJcbnZhciBub3JtYWxzICAgICAgID0gcmVxdWlyZSgnbm9ybWFscycpXHJcbnZhciBtdWx0aXBseSAgICAgID0gcmVxdWlyZSgnZ2wtbWF0NC9tdWx0aXBseScpXHJcbnZhciBpbnZlcnQgICAgICAgID0gcmVxdWlyZSgnZ2wtbWF0NC9pbnZlcnQnKVxyXG52YXIgbmRhcnJheSAgICAgICA9IHJlcXVpcmUoJ25kYXJyYXknKVxyXG52YXIgY29sb3JtYXAgICAgICA9IHJlcXVpcmUoJ2NvbG9ybWFwJylcclxudmFyIGdldENvbnRvdXIgICAgPSByZXF1aXJlKCdzaW1wbGljaWFsLWNvbXBsZXgtY29udG91cicpXHJcbnZhciBwb29sICAgICAgICAgID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcclxudmFyIHNoYWRlcnMgICAgICAgPSByZXF1aXJlKCcuL3NoYWRlcnMnKVxyXG52YXIgY2xvc2VzdFBvaW50ICA9IHJlcXVpcmUoJy4vY2xvc2VzdC1wb2ludCcpXHJcblxyXG52YXIgbWVzaFNoYWRlciAgICA9IHNoYWRlcnMubWVzaFNoYWRlclxyXG52YXIgcGlja1NoYWRlciAgICA9IHNoYWRlcnMucGlja1NoYWRlclxyXG5cclxudmFyIGlkZW50aXR5TWF0cml4ID0gW1xyXG4gIDEsMCwwLDAsXHJcbiAgMCwxLDAsMCxcclxuICAwLDAsMSwwLFxyXG4gIDAsMCwwLDFdXHJcblxyXG5mdW5jdGlvbiBTaW1wbGljaWFsTWVzaChnbFxyXG4gICwgdGV4dHVyZVxyXG4gICwgdHJpU2hhZGVyXHJcbiAgLCBsaW5lU2hhZGVyXHJcbiAgLCBwb2ludFNoYWRlclxyXG4gICwgcGlja1NoYWRlclxyXG4gICwgcG9pbnRQaWNrU2hhZGVyXHJcbiAgLCBjb250b3VyU2hhZGVyXHJcbiAgLCB0cmlhbmdsZVBvc2l0aW9uc1xyXG4gICwgdHJpYW5nbGVWZWN0b3JzXHJcbiAgLCB0cmlhbmdsZUlkc1xyXG4gICwgdHJpYW5nbGVDb2xvcnNcclxuICAsIHRyaWFuZ2xlVVZzXHJcbiAgLCB0cmlhbmdsZU5vcm1hbHNcclxuICAsIHRyaWFuZ2xlVkFPXHJcbiAgLCBlZGdlUG9zaXRpb25zXHJcbiAgLCBlZGdlSWRzXHJcbiAgLCBlZGdlQ29sb3JzXHJcbiAgLCBlZGdlVVZzXHJcbiAgLCBlZGdlVkFPXHJcbiAgLCBwb2ludFBvc2l0aW9uc1xyXG4gICwgcG9pbnRJZHNcclxuICAsIHBvaW50Q29sb3JzXHJcbiAgLCBwb2ludFVWc1xyXG4gICwgcG9pbnRTaXplc1xyXG4gICwgcG9pbnRWQU9cclxuICAsIGNvbnRvdXJQb3NpdGlvbnNcclxuICAsIGNvbnRvdXJWQU8pIHtcclxuXHJcbiAgdGhpcy5nbCAgICAgICAgICAgICAgICA9IGdsXHJcbiAgdGhpcy5jZWxscyAgICAgICAgICAgICA9IFtdXHJcbiAgdGhpcy5wb3NpdGlvbnMgICAgICAgICA9IFtdXHJcbiAgdGhpcy5pbnRlbnNpdHkgICAgICAgICA9IFtdXHJcbiAgdGhpcy50ZXh0dXJlICAgICAgICAgICA9IHRleHR1cmVcclxuICB0aGlzLmRpcnR5ICAgICAgICAgICAgID0gdHJ1ZVxyXG5cclxuICB0aGlzLnRyaVNoYWRlciAgICAgICAgID0gdHJpU2hhZGVyXHJcbiAgdGhpcy5saW5lU2hhZGVyICAgICAgICA9IGxpbmVTaGFkZXJcclxuICB0aGlzLnBvaW50U2hhZGVyICAgICAgID0gcG9pbnRTaGFkZXJcclxuICB0aGlzLnBpY2tTaGFkZXIgICAgICAgID0gcGlja1NoYWRlclxyXG4gIHRoaXMucG9pbnRQaWNrU2hhZGVyICAgPSBwb2ludFBpY2tTaGFkZXJcclxuICB0aGlzLmNvbnRvdXJTaGFkZXIgICAgID0gY29udG91clNoYWRlclxyXG5cclxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zID0gdHJpYW5nbGVQb3NpdGlvbnNcclxuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycyAgID0gdHJpYW5nbGVWZWN0b3JzXHJcbiAgdGhpcy50cmlhbmdsZUNvbG9ycyAgICA9IHRyaWFuZ2xlQ29sb3JzXHJcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMgICA9IHRyaWFuZ2xlTm9ybWFsc1xyXG4gIHRoaXMudHJpYW5nbGVVVnMgICAgICAgPSB0cmlhbmdsZVVWc1xyXG4gIHRoaXMudHJpYW5nbGVJZHMgICAgICAgPSB0cmlhbmdsZUlkc1xyXG4gIHRoaXMudHJpYW5nbGVWQU8gICAgICAgPSB0cmlhbmdsZVZBT1xyXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgICAgPSAwXHJcblxyXG4gIHRoaXMubGluZVdpZHRoICAgICAgICAgPSAxXHJcbiAgdGhpcy5lZGdlUG9zaXRpb25zICAgICA9IGVkZ2VQb3NpdGlvbnNcclxuICB0aGlzLmVkZ2VDb2xvcnMgICAgICAgID0gZWRnZUNvbG9yc1xyXG4gIHRoaXMuZWRnZVVWcyAgICAgICAgICAgPSBlZGdlVVZzXHJcbiAgdGhpcy5lZGdlSWRzICAgICAgICAgICA9IGVkZ2VJZHNcclxuICB0aGlzLmVkZ2VWQU8gICAgICAgICAgID0gZWRnZVZBT1xyXG4gIHRoaXMuZWRnZUNvdW50ICAgICAgICAgPSAwXHJcblxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMgICAgPSBwb2ludFBvc2l0aW9uc1xyXG4gIHRoaXMucG9pbnRDb2xvcnMgICAgICAgPSBwb2ludENvbG9yc1xyXG4gIHRoaXMucG9pbnRVVnMgICAgICAgICAgPSBwb2ludFVWc1xyXG4gIHRoaXMucG9pbnRTaXplcyAgICAgICAgPSBwb2ludFNpemVzXHJcbiAgdGhpcy5wb2ludElkcyAgICAgICAgICA9IHBvaW50SWRzXHJcbiAgdGhpcy5wb2ludFZBTyAgICAgICAgICA9IHBvaW50VkFPXHJcbiAgdGhpcy5wb2ludENvdW50ICAgICAgICA9IDBcclxuXHJcbiAgdGhpcy5jb250b3VyTGluZVdpZHRoICA9IDFcclxuICB0aGlzLmNvbnRvdXJQb3NpdGlvbnMgID0gY29udG91clBvc2l0aW9uc1xyXG4gIHRoaXMuY29udG91clZBTyAgICAgICAgPSBjb250b3VyVkFPXHJcbiAgdGhpcy5jb250b3VyQ291bnQgICAgICA9IDBcclxuICB0aGlzLmNvbnRvdXJDb2xvciAgICAgID0gWzAsMCwwXVxyXG4gIHRoaXMuY29udG91ckVuYWJsZSAgICAgPSBmYWxzZVxyXG5cclxuICB0aGlzLnBpY2tJZCAgICAgICAgICAgID0gMVxyXG4gIHRoaXMuYm91bmRzICAgICAgICAgICAgPSBbXHJcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLFxyXG4gICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSBdXHJcbiAgdGhpcy5jbGlwQm91bmRzICAgICAgICA9IFtcclxuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV0sXHJcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldIF1cclxuXHJcbiAgdGhpcy5saWdodFBvc2l0aW9uID0gWzFlNSwgMWU1LCAwXVxyXG4gIHRoaXMuYW1iaWVudExpZ2h0ICA9IDAuOFxyXG4gIHRoaXMuZGlmZnVzZUxpZ2h0ICA9IDAuOFxyXG4gIHRoaXMuc3BlY3VsYXJMaWdodCA9IDIuMFxyXG4gIHRoaXMucm91Z2huZXNzICAgICA9IDAuNVxyXG4gIHRoaXMuZnJlc25lbCAgICAgICA9IDEuNVxyXG5cclxuICB0aGlzLm9wYWNpdHkgICAgICAgPSAxLjBcclxuXHJcbiAgdGhpcy50dWJlU2NhbGUgICAgID0gMS4wXHJcblxyXG4gIHRoaXMuX21vZGVsICAgICAgID0gaWRlbnRpdHlNYXRyaXhcclxuICB0aGlzLl92aWV3ICAgICAgICA9IGlkZW50aXR5TWF0cml4XHJcbiAgdGhpcy5fcHJvamVjdGlvbiAgPSBpZGVudGl0eU1hdHJpeFxyXG4gIHRoaXMuX3Jlc29sdXRpb24gID0gWzEsMV1cclxufVxyXG5cclxudmFyIHByb3RvID0gU2ltcGxpY2lhbE1lc2gucHJvdG90eXBlXHJcblxyXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPj0gMVxyXG59XHJcblxyXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XHJcbiAgcmV0dXJuIHRoaXMub3BhY2l0eSA8IDFcclxufVxyXG5cclxucHJvdG8ucGlja1Nsb3RzID0gMVxyXG5cclxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbihpZCkge1xyXG4gIHRoaXMucGlja0lkID0gaWRcclxufVxyXG5cclxuZnVuY3Rpb24gZ2VuQ29sb3JtYXAocGFyYW0pIHtcclxuICB2YXIgY29sb3JzID0gY29sb3JtYXAoe1xyXG4gICAgICBjb2xvcm1hcDogcGFyYW1cclxuICAgICwgbnNoYWRlczogIDI1NlxyXG4gICAgLCBmb3JtYXQ6ICAncmdiYSdcclxuICB9KVxyXG5cclxuICB2YXIgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoMjU2KjQpXHJcbiAgZm9yKHZhciBpPTA7IGk8MjU2OyArK2kpIHtcclxuICAgIHZhciBjID0gY29sb3JzW2ldXHJcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcclxuICAgICAgcmVzdWx0WzQqaStqXSA9IGNbal1cclxuICAgIH1cclxuICAgIHJlc3VsdFs0KmkrM10gPSBjWzNdKjI1NVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5kYXJyYXkocmVzdWx0LCBbMjU2LDI1Niw0XSwgWzQsMCwxXSlcclxufVxyXG5cclxuZnVuY3Rpb24gdW5wYWNrSW50ZW5zaXR5KGNlbGxzLCBudW1WZXJ0cywgY2VsbEludGVuc2l0eSkge1xyXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobnVtVmVydHMpXHJcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydHM7ICsraSkge1xyXG4gICAgcmVzdWx0W2ldID0gMFxyXG4gIH1cclxuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcclxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XHJcbiAgICB2YXIgYyA9IGNlbGxzW2ldXHJcbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XHJcbiAgICAgIHJlc3VsdFtjW2pdXSA9IGNlbGxJbnRlbnNpdHlbaV1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5mdW5jdGlvbiB0YWtlWkNvbXBvbmVudChhcnJheSkge1xyXG4gIHZhciBuID0gYXJyYXkubGVuZ3RoXHJcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKVxyXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xyXG4gICAgcmVzdWx0W2ldID0gYXJyYXlbaV1bMl1cclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5wcm90by5oaWdobGlnaHQgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcclxuICBpZighc2VsZWN0aW9uIHx8ICF0aGlzLmNvbnRvdXJFbmFibGUpIHtcclxuICAgIHRoaXMuY29udG91ckNvdW50ID0gMFxyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG4gIHZhciBsZXZlbCA9IGdldENvbnRvdXIodGhpcy5jZWxscywgdGhpcy5pbnRlbnNpdHksIHNlbGVjdGlvbi5pbnRlbnNpdHkpXHJcbiAgdmFyIGNlbGxzICAgICAgICAgPSBsZXZlbC5jZWxsc1xyXG4gIHZhciB2ZXJ0ZXhJZHMgICAgID0gbGV2ZWwudmVydGV4SWRzXHJcbiAgdmFyIHZlcnRleFdlaWdodHMgPSBsZXZlbC52ZXJ0ZXhXZWlnaHRzXHJcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXHJcbiAgdmFyIHJlc3VsdCA9IHBvb2wubWFsbG9jRmxvYXQzMigyICogMyAqIG51bUNlbGxzKVxyXG4gIHZhciBwdHIgPSAwXHJcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xyXG4gICAgdmFyIGMgPSBjZWxsc1tpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XHJcbiAgICAgIHZhciB2ID0gY1swXVxyXG4gICAgICBpZihjLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICAgIHYgPSBjW2pdXHJcbiAgICAgIH1cclxuICAgICAgdmFyIGEgPSB2ZXJ0ZXhJZHNbdl1bMF1cclxuICAgICAgdmFyIGIgPSB2ZXJ0ZXhJZHNbdl1bMV1cclxuICAgICAgdmFyIHcgPSB2ZXJ0ZXhXZWlnaHRzW3ZdXHJcbiAgICAgIHZhciB3aSA9IDEuMCAtIHdcclxuICAgICAgdmFyIHBhID0gdGhpcy5wb3NpdGlvbnNbYV1cclxuICAgICAgdmFyIHBiID0gdGhpcy5wb3NpdGlvbnNbYl1cclxuICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XHJcbiAgICAgICAgcmVzdWx0W3B0cisrXSA9IHcgKiBwYVtrXSArIHdpICogcGJba11cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICB0aGlzLmNvbnRvdXJDb3VudCA9IChwdHIgLyAzKXwwXHJcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLnVwZGF0ZShyZXN1bHQuc3ViYXJyYXkoMCwgcHRyKSlcclxuICBwb29sLmZyZWUocmVzdWx0KVxyXG59XHJcblxyXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihwYXJhbXMpIHtcclxuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cclxuICB2YXIgZ2wgPSB0aGlzLmdsXHJcblxyXG4gIHRoaXMuZGlydHkgPSB0cnVlXHJcblxyXG4gIGlmKCdjb250b3VyRW5hYmxlJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuY29udG91ckVuYWJsZSA9IHBhcmFtcy5jb250b3VyRW5hYmxlXHJcbiAgfVxyXG4gIGlmKCdjb250b3VyQ29sb3InIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5jb250b3VyQ29sb3IgPSBwYXJhbXMuY29udG91ckNvbG9yXHJcbiAgfVxyXG4gIGlmKCdsaW5lV2lkdGgnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5saW5lV2lkdGggPSBwYXJhbXMubGluZVdpZHRoXHJcbiAgfVxyXG4gIGlmKCdsaWdodFBvc2l0aW9uJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMubGlnaHRQb3NpdGlvbiA9IHBhcmFtcy5saWdodFBvc2l0aW9uXHJcbiAgfVxyXG4gIGlmKCdvcGFjaXR5JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMub3BhY2l0eSA9IHBhcmFtcy5vcGFjaXR5XHJcbiAgfVxyXG4gIGlmKCdhbWJpZW50JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuYW1iaWVudExpZ2h0ICA9IHBhcmFtcy5hbWJpZW50XHJcbiAgfVxyXG4gIGlmKCdkaWZmdXNlJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuZGlmZnVzZUxpZ2h0ID0gcGFyYW1zLmRpZmZ1c2VcclxuICB9XHJcbiAgaWYoJ3NwZWN1bGFyJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuc3BlY3VsYXJMaWdodCA9IHBhcmFtcy5zcGVjdWxhclxyXG4gIH1cclxuICBpZigncm91Z2huZXNzJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMucm91Z2huZXNzID0gcGFyYW1zLnJvdWdobmVzc1xyXG4gIH1cclxuICBpZignZnJlc25lbCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmZyZXNuZWwgPSBwYXJhbXMuZnJlc25lbFxyXG4gIH1cclxuXHJcbiAgaWYocGFyYW1zLnRleHR1cmUpIHtcclxuICAgIHRoaXMudGV4dHVyZS5kaXNwb3NlKClcclxuICAgIHRoaXMudGV4dHVyZSA9IGNyZWF0ZVRleHR1cmUoZ2wsIHBhcmFtcy50ZXh0dXJlKVxyXG4gIH0gZWxzZSBpZiAocGFyYW1zLmNvbG9ybWFwKSB7XHJcbiAgICB0aGlzLnRleHR1cmUuc2hhcGUgPSBbMjU2LDI1Nl1cclxuICAgIHRoaXMudGV4dHVyZS5taW5GaWx0ZXIgPSBnbC5MSU5FQVJfTUlQTUFQX0xJTkVBUlxyXG4gICAgdGhpcy50ZXh0dXJlLm1hZ0ZpbHRlciA9IGdsLkxJTkVBUlxyXG4gICAgdGhpcy50ZXh0dXJlLnNldFBpeGVscyhnZW5Db2xvcm1hcChwYXJhbXMuY29sb3JtYXApKVxyXG4gICAgdGhpcy50ZXh0dXJlLmdlbmVyYXRlTWlwbWFwKClcclxuICB9XHJcblxyXG4gIHZhciBjZWxscyA9IHBhcmFtcy5jZWxsc1xyXG4gIHZhciBwb3NpdGlvbnMgPSBwYXJhbXMucG9zaXRpb25zXHJcbiAgdmFyIHZlY3RvcnMgPSBwYXJhbXMudmVjdG9yc1xyXG5cclxuICBpZighcG9zaXRpb25zIHx8ICFjZWxscyB8fCAhdmVjdG9ycykge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICBpZiAocGFyYW1zLnR1YmVTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLnR1YmVTY2FsZSA9IHBhcmFtcy50dWJlU2NhbGU7XHJcbiAgfVxyXG5cclxuICB2YXIgdFBvcyA9IFtdXHJcbiAgdmFyIHRWZWMgPSBbXVxyXG4gIHZhciB0Q29sID0gW11cclxuICB2YXIgdE5vciA9IFtdXHJcbiAgdmFyIHRVVnMgPSBbXVxyXG4gIHZhciB0SWRzID0gW11cclxuXHJcbiAgdmFyIGVQb3MgPSBbXVxyXG4gIHZhciBlQ29sID0gW11cclxuICB2YXIgZVVWcyA9IFtdXHJcbiAgdmFyIGVJZHMgPSBbXVxyXG5cclxuICB2YXIgcFBvcyA9IFtdXHJcbiAgdmFyIHBDb2wgPSBbXVxyXG4gIHZhciBwVVZzID0gW11cclxuICB2YXIgcFNpeiA9IFtdXHJcbiAgdmFyIHBJZHMgPSBbXVxyXG5cclxuICAvL1NhdmUgZ2VvbWV0cnkgZGF0YSBmb3IgcGlja2luZyBjYWxjdWxhdGlvbnNcclxuICB0aGlzLmNlbGxzICAgICA9IGNlbGxzXHJcbiAgdGhpcy5wb3NpdGlvbnMgPSBwb3NpdGlvbnNcclxuICB0aGlzLnZlY3RvcnMgICA9IHZlY3RvcnNcclxuXHJcbiAgLy9Db21wdXRlIG5vcm1hbHNcclxuICB2YXIgdmVydGV4Tm9ybWFscyA9IHBhcmFtcy52ZXJ0ZXhOb3JtYWxzXHJcbiAgdmFyIGNlbGxOb3JtYWxzICAgPSBwYXJhbXMuY2VsbE5vcm1hbHNcclxuICB2YXIgdmVydGV4Tm9ybWFsc0Vwc2lsb24gPSBwYXJhbXMudmVydGV4Tm9ybWFsc0Vwc2lsb24gPT09IHZvaWQoMCkgPyBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gOiBwYXJhbXMudmVydGV4Tm9ybWFsc0Vwc2lsb25cclxuICB2YXIgZmFjZU5vcm1hbHNFcHNpbG9uID0gcGFyYW1zLmZhY2VOb3JtYWxzRXBzaWxvbiA9PT0gdm9pZCgwKSA/IERFRkFVTFRfRkFDRV9OT1JNQUxTX0VQU0lMT04gOiBwYXJhbXMuZmFjZU5vcm1hbHNFcHNpbG9uXHJcbiAgaWYocGFyYW1zLnVzZUZhY2V0Tm9ybWFscyAmJiAhY2VsbE5vcm1hbHMpIHtcclxuICAgIGNlbGxOb3JtYWxzID0gbm9ybWFscy5mYWNlTm9ybWFscyhjZWxscywgcG9zaXRpb25zLCBmYWNlTm9ybWFsc0Vwc2lsb24pXHJcbiAgfVxyXG4gIGlmKCFjZWxsTm9ybWFscyAmJiAhdmVydGV4Tm9ybWFscykge1xyXG4gICAgdmVydGV4Tm9ybWFscyA9IG5vcm1hbHMudmVydGV4Tm9ybWFscyhjZWxscywgcG9zaXRpb25zLCB2ZXJ0ZXhOb3JtYWxzRXBzaWxvbilcclxuICB9XHJcblxyXG4gIC8vQ29tcHV0ZSBjb2xvcnNcclxuICB2YXIgdmVydGV4Q29sb3JzICAgID0gcGFyYW1zLnZlcnRleENvbG9yc1xyXG4gIHZhciBjZWxsQ29sb3JzICAgICAgPSBwYXJhbXMuY2VsbENvbG9yc1xyXG4gIHZhciBtZXNoQ29sb3IgICAgICAgPSBwYXJhbXMubWVzaENvbG9yIHx8IFsxLDEsMSwxXVxyXG5cclxuICAvL1VWc1xyXG4gIHZhciB2ZXJ0ZXhVVnMgICAgICAgPSBwYXJhbXMudmVydGV4VVZzXHJcbiAgdmFyIHZlcnRleEludGVuc2l0eSA9IHBhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlcclxuICB2YXIgY2VsbFVWcyAgICAgICAgID0gcGFyYW1zLmNlbGxVVnNcclxuICB2YXIgY2VsbEludGVuc2l0eSAgID0gcGFyYW1zLmNlbGxJbnRlbnNpdHlcclxuXHJcbiAgdmFyIGludGVuc2l0eUxvICAgICA9IEluZmluaXR5XHJcbiAgdmFyIGludGVuc2l0eUhpICAgICA9IC1JbmZpbml0eVxyXG4gIGlmKCF2ZXJ0ZXhVVnMgJiYgIWNlbGxVVnMpIHtcclxuICAgIGlmKHZlcnRleEludGVuc2l0eSkge1xyXG4gICAgICBpZihwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzKSB7XHJcbiAgICAgICAgaW50ZW5zaXR5TG8gPSArcGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kc1swXVxyXG4gICAgICAgIGludGVuc2l0eUhpID0gK3BhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHNbMV1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBmb3IodmFyIGk9MDsgaTx2ZXJ0ZXhJbnRlbnNpdHkubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICAgIHZhciBmID0gdmVydGV4SW50ZW5zaXR5W2ldXHJcbiAgICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxyXG4gICAgICAgICAgaW50ZW5zaXR5SGkgPSBNYXRoLm1heChpbnRlbnNpdHlIaSwgZilcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPGNlbGxJbnRlbnNpdHkubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICB2YXIgZiA9IGNlbGxJbnRlbnNpdHlbaV1cclxuICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxyXG4gICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgIHZhciBmID0gcG9zaXRpb25zW2ldWzJdXHJcbiAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcclxuICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcclxuICAgIHRoaXMuaW50ZW5zaXR5ID0gdmVydGV4SW50ZW5zaXR5XHJcbiAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcclxuICAgIHRoaXMuaW50ZW5zaXR5ID0gdW5wYWNrSW50ZW5zaXR5KGNlbGxzLCBwb3NpdGlvbnMubGVuZ3RoLCBjZWxsSW50ZW5zaXR5KVxyXG4gIH0gZWxzZSB7XHJcbiAgICB0aGlzLmludGVuc2l0eSA9IHRha2VaQ29tcG9uZW50KHBvc2l0aW9ucylcclxuICB9XHJcblxyXG4gIC8vUG9pbnQgc2l6ZVxyXG4gIHZhciBwb2ludFNpemVzICAgICAgPSBwYXJhbXMucG9pbnRTaXplc1xyXG4gIHZhciBtZXNoUG9pbnRTaXplICAgPSBwYXJhbXMucG9pbnRTaXplIHx8IDEuMFxyXG5cclxuICAvL1VwZGF0ZSBib3VuZHNcclxuICB0aGlzLmJvdW5kcyAgICAgICA9IFtbSW5maW5pdHksSW5maW5pdHksSW5maW5pdHldLCBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldXVxyXG4gIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xyXG4gICAgdmFyIHAgPSBwb3NpdGlvbnNbaV1cclxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICBpZihpc05hTihwW2pdKSB8fCAhaXNGaW5pdGUocFtqXSkpIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuYm91bmRzWzBdW2pdID0gTWF0aC5taW4odGhpcy5ib3VuZHNbMF1bal0sIHBbal0pXHJcbiAgICAgIHRoaXMuYm91bmRzWzFdW2pdID0gTWF0aC5tYXgodGhpcy5ib3VuZHNbMV1bal0sIHBbal0pXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL1BhY2sgY2VsbHMgaW50byBidWZmZXJzXHJcbiAgdmFyIHRyaWFuZ2xlQ291bnQgPSAwXHJcbiAgdmFyIGVkZ2VDb3VudCA9IDBcclxuICB2YXIgcG9pbnRDb3VudCA9IDBcclxuXHJcbmZpbGxfbG9vcDpcclxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xyXG4gICAgdmFyIGNlbGwgPSBjZWxsc1tpXVxyXG4gICAgc3dpdGNoKGNlbGwubGVuZ3RoKSB7XHJcbiAgICAgIGNhc2UgMTpcclxuXHJcbiAgICAgICAgdmFyIHYgPSBjZWxsWzBdXHJcbiAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cclxuXHJcbiAgICAgICAgLy9DaGVjayBOYU5zXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgICBpZihpc05hTihwW2pdKSB8fCAhaXNGaW5pdGUocFtqXSkpIHtcclxuICAgICAgICAgICAgY29udGludWUgZmlsbF9sb29wXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBwUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSwgcFszXSlcclxuXHJcbiAgICAgICAgdmFyIGNcclxuICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cclxuICAgICAgICB9IGVsc2UgaWYoY2VsbENvbG9ycykge1xyXG4gICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgYyA9IG1lc2hDb2xvclxyXG4gICAgICAgIH1cclxuICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xyXG4gICAgICAgICAgcENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIDEpXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHBDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdKVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIHV2XHJcbiAgICAgICAgaWYodmVydGV4VVZzKSB7XHJcbiAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxyXG4gICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcclxuICAgICAgICAgIHV2ID0gW1xyXG4gICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgIH0gZWxzZSBpZihjZWxsVVZzKSB7XHJcbiAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cclxuICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xyXG4gICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cclxuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHBVVnMucHVzaCh1dlswXSwgdXZbMV0pXHJcblxyXG4gICAgICAgIGlmKHBvaW50U2l6ZXMpIHtcclxuICAgICAgICAgIHBTaXoucHVzaChwb2ludFNpemVzW3ZdKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBwU2l6LnB1c2gobWVzaFBvaW50U2l6ZSlcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHBJZHMucHVzaChpKVxyXG5cclxuICAgICAgICBwb2ludENvdW50ICs9IDFcclxuICAgICAgYnJlYWtcclxuXHJcbiAgICAgIGNhc2UgMjpcclxuXHJcbiAgICAgICAgLy9DaGVjayBOYU5zXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XHJcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cclxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXHJcbiAgICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcclxuICAgICAgICAgICAgaWYoaXNOYU4ocFtrXSkgfHwgIWlzRmluaXRlKHBba10pKSB7XHJcbiAgICAgICAgICAgICAgY29udGludWUgZmlsbF9sb29wXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xyXG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXHJcbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxyXG5cclxuICAgICAgICAgIGVQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdKVxyXG5cclxuICAgICAgICAgIHZhciBjXHJcbiAgICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgICAgYyA9IHZlcnRleENvbG9yc1t2XVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcclxuICAgICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGMgPSBtZXNoQ29sb3JcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmKGMubGVuZ3RoID09PSAzKSB7XHJcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZUNvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIGNbM10pXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgdmFyIHV2XHJcbiAgICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcclxuICAgICAgICAgICAgdXYgPSB2ZXJ0ZXhVVnNbdl1cclxuICAgICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcclxuICAgICAgICAgICAgdXYgPSBjZWxsVVZzW2ldXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAoY2VsbEludGVuc2l0eVtpXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGVVVnMucHVzaCh1dlswXSwgdXZbMV0pXHJcblxyXG4gICAgICAgICAgZUlkcy5wdXNoKGkpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVkZ2VDb3VudCArPSAxXHJcbiAgICAgIGJyZWFrXHJcblxyXG4gICAgICBjYXNlIDM6XHJcbiAgICAgICAgLy9DaGVjayBOYU5zXHJcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cclxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXHJcbiAgICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcclxuICAgICAgICAgICAgaWYoaXNOYU4ocFtrXSkgfHwgIWlzRmluaXRlKHBba10pKSB7XHJcbiAgICAgICAgICAgICAgY29udGludWUgZmlsbF9sb29wXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xyXG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXHJcblxyXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cclxuICAgICAgICAgIHRQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdLCBwWzNdKVxyXG5cclxuICAgICAgICAgIHZhciB3ID0gdmVjdG9yc1t2XVxyXG4gICAgICAgICAgdFZlYy5wdXNoKHdbMF0sIHdbMV0sIHdbMl0sIHdbM10pO1xyXG5cclxuICAgICAgICAgIHZhciBjXHJcbiAgICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgICAgYyA9IHZlcnRleENvbG9yc1t2XVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcclxuICAgICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGMgPSBtZXNoQ29sb3JcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmKGMubGVuZ3RoID09PSAzKSB7XHJcbiAgICAgICAgICAgIHRDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIGNbM10pXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgdmFyIHV2XHJcbiAgICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcclxuICAgICAgICAgICAgdXYgPSB2ZXJ0ZXhVVnNbdl1cclxuICAgICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcclxuICAgICAgICAgICAgdXYgPSBjZWxsVVZzW2ldXHJcbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xyXG4gICAgICAgICAgICB1diA9IFtcclxuICAgICAgICAgICAgICAoY2VsbEludGVuc2l0eVtpXSAtIGludGVuc2l0eUxvKSAvXHJcbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdXYgPSBbXHJcbiAgICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xyXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRVVnMucHVzaCh1dlswXSwgdXZbMV0pXHJcblxyXG4gICAgICAgICAgdmFyIHFcclxuICAgICAgICAgIGlmKHZlcnRleE5vcm1hbHMpIHtcclxuICAgICAgICAgICAgcSA9IHZlcnRleE5vcm1hbHNbdl1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHEgPSBjZWxsTm9ybWFsc1tpXVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdE5vci5wdXNoKHFbMF0sIHFbMV0sIHFbMl0pXHJcblxyXG4gICAgICAgICAgdElkcy5wdXNoKGkpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyaWFuZ2xlQ291bnQgKz0gMVxyXG4gICAgICBicmVha1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgYnJlYWtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHRoaXMucG9pbnRDb3VudCAgICAgPSBwb2ludENvdW50XHJcbiAgdGhpcy5lZGdlQ291bnQgICAgICA9IGVkZ2VDb3VudFxyXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgPSB0cmlhbmdsZUNvdW50XHJcblxyXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMudXBkYXRlKHBQb3MpXHJcbiAgdGhpcy5wb2ludENvbG9ycy51cGRhdGUocENvbClcclxuICB0aGlzLnBvaW50VVZzLnVwZGF0ZShwVVZzKVxyXG4gIHRoaXMucG9pbnRTaXplcy51cGRhdGUocFNpeilcclxuICB0aGlzLnBvaW50SWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkocElkcykpXHJcblxyXG4gIHRoaXMuZWRnZVBvc2l0aW9ucy51cGRhdGUoZVBvcylcclxuICB0aGlzLmVkZ2VDb2xvcnMudXBkYXRlKGVDb2wpXHJcbiAgdGhpcy5lZGdlVVZzLnVwZGF0ZShlVVZzKVxyXG4gIHRoaXMuZWRnZUlkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KGVJZHMpKVxyXG5cclxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLnVwZGF0ZSh0UG9zKVxyXG4gIHRoaXMudHJpYW5nbGVWZWN0b3JzLnVwZGF0ZSh0VmVjKVxyXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMudXBkYXRlKHRDb2wpXHJcbiAgdGhpcy50cmlhbmdsZVVWcy51cGRhdGUodFVWcylcclxuICB0aGlzLnRyaWFuZ2xlTm9ybWFscy51cGRhdGUodE5vcilcclxuICB0aGlzLnRyaWFuZ2xlSWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkodElkcykpXHJcbn1cclxuXHJcbnByb3RvLmRyYXdUcmFuc3BhcmVudCA9IHByb3RvLmRyYXcgPSBmdW5jdGlvbihwYXJhbXMpIHtcclxuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cclxuICB2YXIgZ2wgICAgICAgICAgPSB0aGlzLmdsXHJcbiAgdmFyIG1vZGVsICAgICAgID0gcGFyYW1zLm1vZGVsICAgICAgfHwgaWRlbnRpdHlNYXRyaXhcclxuICB2YXIgdmlldyAgICAgICAgPSBwYXJhbXMudmlldyAgICAgICB8fCBpZGVudGl0eU1hdHJpeFxyXG4gIHZhciBwcm9qZWN0aW9uICA9IHBhcmFtcy5wcm9qZWN0aW9uIHx8IGlkZW50aXR5TWF0cml4XHJcblxyXG4gIHZhciBjbGlwQm91bmRzID0gW1stMWU2LC0xZTYsLTFlNl0sWzFlNiwxZTYsMWU2XV1cclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIGNsaXBCb3VuZHNbMF1baV0gPSBNYXRoLm1heChjbGlwQm91bmRzWzBdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMF1baV0pXHJcbiAgICBjbGlwQm91bmRzWzFdW2ldID0gTWF0aC5taW4oY2xpcEJvdW5kc1sxXVtpXSwgdGhpcy5jbGlwQm91bmRzWzFdW2ldKVxyXG4gIH1cclxuXHJcbiAgdmFyIHVuaWZvcm1zID0ge1xyXG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXHJcbiAgICB2aWV3OiAgICAgICB2aWV3LFxyXG4gICAgcHJvamVjdGlvbjogcHJvamVjdGlvbixcclxuXHJcbiAgICBjbGlwQm91bmRzOiBjbGlwQm91bmRzLFxyXG5cclxuICAgIGthbWJpZW50OiAgIHRoaXMuYW1iaWVudExpZ2h0LFxyXG4gICAga2RpZmZ1c2U6ICAgdGhpcy5kaWZmdXNlTGlnaHQsXHJcbiAgICBrc3BlY3VsYXI6ICB0aGlzLnNwZWN1bGFyTGlnaHQsXHJcbiAgICByb3VnaG5lc3M6ICB0aGlzLnJvdWdobmVzcyxcclxuICAgIGZyZXNuZWw6ICAgIHRoaXMuZnJlc25lbCxcclxuXHJcbiAgICBleWVQb3NpdGlvbjogICBbMCwwLDBdLFxyXG4gICAgbGlnaHRQb3NpdGlvbjogWzAsMCwwXSxcclxuXHJcbiAgICBvcGFjaXR5OiAgdGhpcy5vcGFjaXR5LFxyXG5cclxuICAgIHR1YmVTY2FsZTogdGhpcy50dWJlU2NhbGUsXHJcblxyXG4gICAgY29udG91ckNvbG9yOiB0aGlzLmNvbnRvdXJDb2xvcixcclxuXHJcbiAgICB0ZXh0dXJlOiAgICAwXHJcbiAgfVxyXG5cclxuICB0aGlzLnRleHR1cmUuYmluZCgwKVxyXG5cclxuICB2YXIgaW52Q2FtZXJhTWF0cml4ID0gbmV3IEFycmF5KDE2KVxyXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMudmlldywgdW5pZm9ybXMubW9kZWwpXHJcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXHJcbiAgaW52ZXJ0KGludkNhbWVyYU1hdHJpeCwgaW52Q2FtZXJhTWF0cml4KVxyXG5cclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIHVuaWZvcm1zLmV5ZVBvc2l0aW9uW2ldID0gaW52Q2FtZXJhTWF0cml4WzEyK2ldIC8gaW52Q2FtZXJhTWF0cml4WzE1XVxyXG4gIH1cclxuXHJcbiAgdmFyIHcgPSBpbnZDYW1lcmFNYXRyaXhbMTVdXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB3ICs9IHRoaXMubGlnaHRQb3NpdGlvbltpXSAqIGludkNhbWVyYU1hdHJpeFs0KmkrM11cclxuICB9XHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMitpXVxyXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XHJcbiAgICAgIHMgKz0gaW52Q2FtZXJhTWF0cml4WzQqaitpXSAqIHRoaXMubGlnaHRQb3NpdGlvbltqXVxyXG4gICAgfVxyXG4gICAgdW5pZm9ybXMubGlnaHRQb3NpdGlvbltpXSA9IHMgLyB3XHJcbiAgfVxyXG5cclxuICBpZih0aGlzLnRyaWFuZ2xlQ291bnQgPiAwKSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy50cmlTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcclxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuZWRnZUNvdW50ID4gMCAmJiB0aGlzLmxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmxpbmVTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxyXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcclxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID4gMCkge1xyXG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5wb2ludFZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXHJcbiAgICB0aGlzLnBvaW50VkFPLnVuYmluZCgpXHJcbiAgfVxyXG5cclxuICBpZih0aGlzLmNvbnRvdXJFbmFibGUgJiYgdGhpcy5jb250b3VyQ291bnQgPiAwICYmIHRoaXMuY29udG91ckxpbmVXaWR0aCA+IDApIHtcclxuICAgIHZhciBzaGFkZXIgPSB0aGlzLmNvbnRvdXJTaGFkZXJcclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgdGhpcy5jb250b3VyVkFPLmJpbmQoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5jb250b3VyQ291bnQpXHJcbiAgICB0aGlzLmNvbnRvdXJWQU8udW5iaW5kKClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24ocGFyYW1zKSB7XHJcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XHJcblxyXG4gIHZhciBnbCAgICAgICAgID0gdGhpcy5nbFxyXG5cclxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IGlkZW50aXR5TWF0cml4XHJcbiAgdmFyIHZpZXcgICAgICAgPSBwYXJhbXMudmlldyAgICAgICB8fCBpZGVudGl0eU1hdHJpeFxyXG4gIHZhciBwcm9qZWN0aW9uID0gcGFyYW1zLnByb2plY3Rpb24gfHwgaWRlbnRpdHlNYXRyaXhcclxuXHJcbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcclxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXHJcbiAgfVxyXG5cclxuICAvL1NhdmUgY2FtZXJhIHBhcmFtZXRlcnNcclxuICB0aGlzLl9tb2RlbCAgICAgID0gW10uc2xpY2UuY2FsbChtb2RlbClcclxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxyXG4gIHRoaXMuX3Byb2plY3Rpb24gPSBbXS5zbGljZS5jYWxsKHByb2plY3Rpb24pXHJcbiAgdGhpcy5fcmVzb2x1dGlvbiA9IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdXHJcblxyXG4gIHZhciB1bmlmb3JtcyA9IHtcclxuICAgIG1vZGVsOiAgICAgIG1vZGVsLFxyXG4gICAgdmlldzogICAgICAgdmlldyxcclxuICAgIHByb2plY3Rpb246IHByb2plY3Rpb24sXHJcbiAgICBjbGlwQm91bmRzOiBjbGlwQm91bmRzLFxyXG5cclxuICAgIHR1YmVTY2FsZTogdGhpcy50dWJlU2NhbGUsXHJcblxyXG4gICAgcGlja0lkOiAgICAgdGhpcy5waWNrSWQgLyAyNTUuMCxcclxuICB9XHJcblxyXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcclxuICBzaGFkZXIuYmluZCgpXHJcbiAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcclxuXHJcbiAgaWYodGhpcy50cmlhbmdsZUNvdW50ID4gMCkge1xyXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcclxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcclxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcclxuICB9XHJcblxyXG4gIGlmKHRoaXMuZWRnZUNvdW50ID4gMCkge1xyXG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxyXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoKVxyXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcclxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYodGhpcy5wb2ludENvdW50ID4gMCkge1xyXG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRQaWNrU2hhZGVyXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xyXG5cclxuICAgIHRoaXMucG9pbnRWQU8uYmluZCgpXHJcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgdGhpcy5wb2ludENvdW50KVxyXG4gICAgdGhpcy5wb2ludFZBTy51bmJpbmQoKVxyXG4gIH1cclxufVxyXG5cclxuXHJcbnByb3RvLnBpY2sgPSBmdW5jdGlvbihwaWNrRGF0YSkge1xyXG4gIGlmKCFwaWNrRGF0YSkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcbiAgaWYocGlja0RhdGEuaWQgIT09IHRoaXMucGlja0lkKSB7XHJcbiAgICByZXR1cm4gbnVsbFxyXG4gIH1cclxuXHJcbiAgdmFyIGNlbGxJZCA9IHBpY2tEYXRhLnZhbHVlWzBdICsgMjU2KnBpY2tEYXRhLnZhbHVlWzFdICsgNjU1MzYqcGlja0RhdGEudmFsdWVbMl1cclxuICB2YXIgY2VsbCA9IHRoaXMuY2VsbHNbY2VsbElkXVxyXG5cclxuICB2YXIgcG9zID0gdGhpcy5wb3NpdGlvbnNbY2VsbFsxXV0uc2xpY2UoMCwgMylcclxuICB2YXIgaW50ZW5zaXR5ID0gdGhpcy5pbnRlbnNpdHlbY2VsbFsxXV1cclxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLnZlY3RvcnNbY2VsbFsxXV0uc2xpY2UoMCwgMylcclxuICB2YXIgZGl2ZXJnZW5jZSA9IHRoaXMudmVjdG9yc1tjZWxsWzFdXVszXVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgaW5kZXg6IGNlbGxJZCxcclxuICAgIHBvc2l0aW9uOiBwb3MsXHJcbiAgICBpbnRlbnNpdHk6IGludGVuc2l0eSxcclxuICAgIHZlbG9jaXR5OiB2ZWxvY2l0eSxcclxuICAgIGRpdmVyZ2VuY2U6IGRpdmVyZ2VuY2UsXHJcbiAgICBkYXRhQ29vcmRpbmF0ZTogcG9zXHJcbiAgfVxyXG59XHJcblxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gIHRoaXMudGV4dHVyZS5kaXNwb3NlKClcclxuXHJcbiAgdGhpcy50cmlTaGFkZXIuZGlzcG9zZSgpXHJcbiAgLy8gdGhpcy5saW5lU2hhZGVyLmRpc3Bvc2UoKVxyXG4gIC8vIHRoaXMucG9pbnRTaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5waWNrU2hhZGVyLmRpc3Bvc2UoKVxyXG4gIC8vIHRoaXMucG9pbnRQaWNrU2hhZGVyLmRpc3Bvc2UoKVxyXG5cclxuICB0aGlzLnRyaWFuZ2xlVkFPLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMuZGlzcG9zZSgpXHJcbiAgdGhpcy50cmlhbmdsZVZlY3RvcnMuZGlzcG9zZSgpXHJcbiAgdGhpcy50cmlhbmdsZUNvbG9ycy5kaXNwb3NlKClcclxuICB0aGlzLnRyaWFuZ2xlVVZzLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVOb3JtYWxzLmRpc3Bvc2UoKVxyXG4gIHRoaXMudHJpYW5nbGVJZHMuZGlzcG9zZSgpXHJcblxyXG4gIHRoaXMuZWRnZVZBTy5kaXNwb3NlKClcclxuICB0aGlzLmVkZ2VQb3NpdGlvbnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5lZGdlQ29sb3JzLmRpc3Bvc2UoKVxyXG4gIHRoaXMuZWRnZVVWcy5kaXNwb3NlKClcclxuICB0aGlzLmVkZ2VJZHMuZGlzcG9zZSgpXHJcblxyXG4gIHRoaXMucG9pbnRWQU8uZGlzcG9zZSgpXHJcbiAgdGhpcy5wb2ludFBvc2l0aW9ucy5kaXNwb3NlKClcclxuICB0aGlzLnBvaW50Q29sb3JzLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRVVnMuZGlzcG9zZSgpXHJcbiAgdGhpcy5wb2ludFNpemVzLmRpc3Bvc2UoKVxyXG4gIHRoaXMucG9pbnRJZHMuZGlzcG9zZSgpXHJcblxyXG4gIHRoaXMuY29udG91clZBTy5kaXNwb3NlKClcclxuICB0aGlzLmNvbnRvdXJQb3NpdGlvbnMuZGlzcG9zZSgpXHJcbiAgLy8gdGhpcy5jb250b3VyU2hhZGVyLmRpc3Bvc2UoKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVNZXNoU2hhZGVyKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgbWVzaFNoYWRlci52ZXJ0ZXgsIG1lc2hTaGFkZXIuZnJhZ21lbnQsIG51bGwsIG1lc2hTaGFkZXIuYXR0cmlidXRlcylcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcclxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiAgICAgICA9IDNcclxuICBzaGFkZXIuYXR0cmlidXRlcy52ZWN0b3IubG9jYXRpb24gICA9IDVcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVdpcmVTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCB3aXJlU2hhZGVyLnZlcnRleCwgd2lyZVNoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcclxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiAgICAgICA9IDNcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBvaW50U2hhZGVyKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcG9pbnRTaGFkZXIudmVydGV4LCBwb2ludFNoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiAgPSAwXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuY29sb3IubG9jYXRpb24gICAgID0gMlxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgICA9IDNcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb2ludFNpemUubG9jYXRpb24gPSA0XHJcbiAgcmV0dXJuIHNoYWRlclxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVQaWNrU2hhZGVyKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcGlja1NoYWRlci52ZXJ0ZXgsIHBpY2tTaGFkZXIuZnJhZ21lbnQsIG51bGwsIHBpY2tTaGFkZXIuYXR0cmlidXRlcylcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5pZC5sb2NhdGlvbiAgICAgICA9IDFcclxuICBzaGFkZXIuYXR0cmlidXRlcy52ZWN0b3IubG9jYXRpb24gICA9IDVcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBvaW50UGlja1NoYWRlcihnbCkge1xyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHBvaW50UGlja1NoYWRlci52ZXJ0ZXgsIHBvaW50UGlja1NoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiAgPSAwXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuaWQubG9jYXRpb24gICAgICAgID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvaW50U2l6ZS5sb2NhdGlvbiA9IDRcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUNvbnRvdXJTaGFkZXIoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBjb250b3VyU2hhZGVyLnZlcnRleCwgY29udG91clNoYWRlci5mcmFnbWVudClcclxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVNpbXBsaWNpYWxNZXNoKGdsLCBwYXJhbXMpIHtcclxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgcGFyYW1zID0gZ2w7XHJcbiAgICBnbCA9IHBhcmFtcy5nbDtcclxuICB9XHJcblxyXG4gIHZhciB0cmlTaGFkZXIgICAgICAgPSBwYXJhbXMudHJpU2hhZGVyIHx8IGNyZWF0ZU1lc2hTaGFkZXIoZ2wpXHJcbiAgdmFyIGxpbmVTaGFkZXIgICAgICA9IG51bGw7IC8vY3JlYXRlV2lyZVNoYWRlcihnbClcclxuICB2YXIgcG9pbnRTaGFkZXIgICAgID0gbnVsbDsgLy9jcmVhdGVQb2ludFNoYWRlcihnbClcclxuICB2YXIgcGlja1NoYWRlciAgICAgID0gY3JlYXRlUGlja1NoYWRlcihnbClcclxuICB2YXIgcG9pbnRQaWNrU2hhZGVyID0gbnVsbDsgLy9jcmVhdGVQb2ludFBpY2tTaGFkZXIoZ2wpXHJcbiAgdmFyIGNvbnRvdXJTaGFkZXIgICA9IG51bGw7IC8vY3JlYXRlQ29udG91clNoYWRlcihnbClcclxuXHJcbiAgdmFyIG1lc2hUZXh0dXJlICAgICAgID0gY3JlYXRlVGV4dHVyZShnbCxcclxuICAgIG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoWzI1NSwyNTUsMjU1LDI1NV0pLCBbMSwxLDRdKSlcclxuICBtZXNoVGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXHJcbiAgbWVzaFRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcclxuICBtZXNoVGV4dHVyZS5tYWdGaWx0ZXIgPSBnbC5MSU5FQVJcclxuXHJcbiAgdmFyIHRyaWFuZ2xlUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB0cmlhbmdsZVZlY3RvcnMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVDb2xvcnMgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlVVZzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciB0cmlhbmdsZU5vcm1hbHMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdHJpYW5nbGVJZHMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHRyaWFuZ2xlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVQb3NpdGlvbnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiA0XHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlSWRzLFxyXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxyXG4gICAgICBzaXplOiA0LFxyXG4gICAgICBub3JtYWxpemVkOiB0cnVlXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlQ29sb3JzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogNFxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZVVWcyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDJcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVOb3JtYWxzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogM1xyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZVZlY3RvcnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiA0XHJcbiAgICB9XHJcbiAgXSlcclxuXHJcbiAgdmFyIGVkZ2VQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGVkZ2VDb2xvcnMgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGVkZ2VVVnMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGVkZ2VJZHMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIGVkZ2VWQU8gICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgIHsgYnVmZmVyOiBlZGdlUG9zaXRpb25zLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogM1xyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBlZGdlSWRzLFxyXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxyXG4gICAgICBzaXplOiA0LFxyXG4gICAgICBub3JtYWxpemVkOiB0cnVlXHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IGVkZ2VDb2xvcnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiA0XHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IGVkZ2VVVnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiAyXHJcbiAgICB9XHJcbiAgXSlcclxuXHJcbiAgdmFyIHBvaW50UG9zaXRpb25zICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgcG9pbnRDb2xvcnMgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwb2ludFVWcyAgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXHJcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgcG9pbnRJZHMgICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBwb2ludFZBTyAgICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcclxuICAgIHsgYnVmZmVyOiBwb2ludFBvc2l0aW9ucyxcclxuICAgICAgdHlwZTogZ2wuRkxPQVQsXHJcbiAgICAgIHNpemU6IDNcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogcG9pbnRJZHMsXHJcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXHJcbiAgICAgIHNpemU6IDQsXHJcbiAgICAgIG5vcm1hbGl6ZWQ6IHRydWVcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogcG9pbnRDb2xvcnMsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxyXG4gICAgICBzaXplOiA0XHJcbiAgICB9LFxyXG4gICAgeyBidWZmZXI6IHBvaW50VVZzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogMlxyXG4gICAgfSxcclxuICAgIHsgYnVmZmVyOiBwb2ludFNpemVzLFxyXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogMVxyXG4gICAgfVxyXG4gIF0pXHJcblxyXG4gIHZhciBjb250b3VyUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBjb250b3VyVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogY29udG91clBvc2l0aW9ucyxcclxuICAgICAgdHlwZTogICBnbC5GTE9BVCxcclxuICAgICAgc2l6ZTogICAzXHJcbiAgICB9XSlcclxuXHJcbiAgdmFyIG1lc2ggPSBuZXcgU2ltcGxpY2lhbE1lc2goZ2xcclxuICAgICwgbWVzaFRleHR1cmVcclxuICAgICwgdHJpU2hhZGVyXHJcbiAgICAsIGxpbmVTaGFkZXJcclxuICAgICwgcG9pbnRTaGFkZXJcclxuICAgICwgcGlja1NoYWRlclxyXG4gICAgLCBwb2ludFBpY2tTaGFkZXJcclxuICAgICwgY29udG91clNoYWRlclxyXG4gICAgLCB0cmlhbmdsZVBvc2l0aW9uc1xyXG4gICAgLCB0cmlhbmdsZVZlY3RvcnNcclxuICAgICwgdHJpYW5nbGVJZHNcclxuICAgICwgdHJpYW5nbGVDb2xvcnNcclxuICAgICwgdHJpYW5nbGVVVnNcclxuICAgICwgdHJpYW5nbGVOb3JtYWxzXHJcbiAgICAsIHRyaWFuZ2xlVkFPXHJcbiAgICAsIGVkZ2VQb3NpdGlvbnNcclxuICAgICwgZWRnZUlkc1xyXG4gICAgLCBlZGdlQ29sb3JzXHJcbiAgICAsIGVkZ2VVVnNcclxuICAgICwgZWRnZVZBT1xyXG4gICAgLCBwb2ludFBvc2l0aW9uc1xyXG4gICAgLCBwb2ludElkc1xyXG4gICAgLCBwb2ludENvbG9yc1xyXG4gICAgLCBwb2ludFVWc1xyXG4gICAgLCBwb2ludFNpemVzXHJcbiAgICAsIHBvaW50VkFPXHJcbiAgICAsIGNvbnRvdXJQb3NpdGlvbnNcclxuICAgICwgY29udG91clZBTylcclxuXHJcbiAgbWVzaC51cGRhdGUocGFyYW1zKVxyXG5cclxuICByZXR1cm4gbWVzaFxyXG59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNpbXBsaWNpYWxNZXNoXHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5cclxudmFyIHZlYzMgPSByZXF1aXJlKCdnbC12ZWMzJyk7XHJcbnZhciB2ZWM0ID0gcmVxdWlyZSgnZ2wtdmVjNCcpO1xyXG5cclxudmFyIHN0cmVhbVRvVHViZSA9IGZ1bmN0aW9uKHN0cmVhbSwgbWF4RGl2ZXJnZW5jZSwgbWluRGlzdGFuY2UsIG1heE5vcm0pIHtcclxuXHR2YXIgcG9pbnRzID0gc3RyZWFtLnBvaW50cztcclxuXHR2YXIgdmVsb2NpdGllcyA9IHN0cmVhbS52ZWxvY2l0aWVzO1xyXG5cdHZhciBkaXZlcmdlbmNlcyA9IHN0cmVhbS5kaXZlcmdlbmNlcztcclxuXHJcblx0dmFyIHAsIGZ3ZCwgciwgdSwgdiwgdXA7XHJcblx0dXAgPSB2ZWMzLnNldCh2ZWMzLmNyZWF0ZSgpLCAwLCAxLCAwKTtcclxuXHR1ID0gdmVjMy5jcmVhdGUoKTtcclxuXHR2ID0gdmVjMy5jcmVhdGUoKTtcclxuXHR2YXIgcDIgPSB2ZWMzLmNyZWF0ZSgpO1xyXG5cclxuXHR2YXIgdmVydHMgPSBbXTtcclxuXHR2YXIgZmFjZXMgPSBbXTtcclxuXHR2YXIgdmVjdG9ycyA9IFtdO1xyXG5cdHZhciBwcmV2aW91c1ZlcnRzID0gW107XHJcblx0dmFyIGN1cnJlbnRWZXJ0cyA9IFtdO1xyXG5cdHZhciBpbnRlbnNpdGllcyA9IFtdO1xyXG5cdHZhciBwcmV2aW91c0ludGVuc2l0eSA9IDA7XHJcblx0dmFyIGN1cnJlbnRJbnRlbnNpdHkgPSAwO1xyXG5cdHZhciBjdXJyZW50VmVjdG9yID0gdmVjNC5jcmVhdGUoKTtcclxuXHR2YXIgcHJldmlvdXNWZWN0b3IgPSB2ZWM0LmNyZWF0ZSgpO1xyXG5cclxuXHR2YXIgZmFjZXRzID0gODtcclxuXHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHAgPSBwb2ludHNbaV07XHJcblx0XHRmd2QgPSB2ZWxvY2l0aWVzW2ldO1xyXG5cdFx0ciA9IGRpdmVyZ2VuY2VzW2ldO1xyXG5cdFx0aWYgKG1heERpdmVyZ2VuY2UgPT09IDApIHtcclxuXHRcdFx0ciA9IG1pbkRpc3RhbmNlICogMC4wNTtcclxuXHRcdH1cclxuXHRcdGN1cnJlbnRJbnRlbnNpdHkgPSB2ZWMzLmxlbmd0aChmd2QpIC8gbWF4Tm9ybTtcclxuXHRcdGN1cnJlbnRWZWN0b3IgPSB2ZWM0LmNyZWF0ZSgpO1xyXG5cdFx0dmVjMy5jb3B5KGN1cnJlbnRWZWN0b3IsIGZ3ZCk7XHJcblx0XHRjdXJyZW50VmVjdG9yWzNdID0gcjtcclxuXHRcdFxyXG5cdFx0Zm9yICh2YXIgYSA9IDA7IGEgPCBmYWNldHM7IGErKykge1xyXG5cdFx0XHRjdXJyZW50VmVydHNbYV0gPSBbcFswXSwgcFsxXSwgcFsyXSwgYV07XHJcblx0XHR9XHJcblx0XHRpZiAocHJldmlvdXNWZXJ0cy5sZW5ndGggPiAwKSB7XHJcblx0XHRcdGZvciAodmFyIGEgPSAwOyBhIDwgZmFjZXRzOyBhKyspIHtcclxuXHRcdFx0XHR2YXIgYTEgPSAoYSsxKSAlIGZhY2V0cztcclxuXHRcdFx0XHR2ZXJ0cy5wdXNoKFxyXG5cdFx0XHRcdFx0cHJldmlvdXNWZXJ0c1thXSxcclxuXHRcdFx0XHRcdGN1cnJlbnRWZXJ0c1thXSxcclxuXHRcdFx0XHRcdGN1cnJlbnRWZXJ0c1thMV0sXHJcblxyXG5cdFx0XHRcdFx0Y3VycmVudFZlcnRzW2ExXSxcclxuXHRcdFx0XHRcdHByZXZpb3VzVmVydHNbYTFdLFxyXG5cdFx0XHRcdFx0cHJldmlvdXNWZXJ0c1thXVxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdFx0dmVjdG9ycy5wdXNoKFxyXG5cdFx0XHRcdFx0cHJldmlvdXNWZWN0b3IsXHJcblx0XHRcdFx0XHRjdXJyZW50VmVjdG9yLFxyXG5cdFx0XHRcdFx0Y3VycmVudFZlY3RvcixcclxuXHJcblx0XHRcdFx0XHRjdXJyZW50VmVjdG9yLFxyXG5cdFx0XHRcdFx0cHJldmlvdXNWZWN0b3IsXHJcblx0XHRcdFx0XHRwcmV2aW91c1ZlY3RvclxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdFx0aW50ZW5zaXRpZXMucHVzaChcclxuXHRcdFx0XHRcdHByZXZpb3VzSW50ZW5zaXR5LFxyXG5cdFx0XHRcdFx0Y3VycmVudEludGVuc2l0eSxcclxuXHRcdFx0XHRcdGN1cnJlbnRJbnRlbnNpdHksXHJcblxyXG5cdFx0XHRcdFx0Y3VycmVudEludGVuc2l0eSxcclxuXHRcdFx0XHRcdHByZXZpb3VzSW50ZW5zaXR5LFxyXG5cdFx0XHRcdFx0cHJldmlvdXNJbnRlbnNpdHlcclxuXHRcdFx0XHQpO1xyXG5cdFx0XHRcdGZhY2VzLnB1c2goXHJcblx0XHRcdFx0XHRbdmVydHMubGVuZ3RoLTYsIHZlcnRzLmxlbmd0aC01LCB2ZXJ0cy5sZW5ndGgtNF0sXHJcblx0XHRcdFx0XHRbdmVydHMubGVuZ3RoLTMsIHZlcnRzLmxlbmd0aC0yLCB2ZXJ0cy5sZW5ndGgtMV1cclxuXHRcdFx0XHQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHR2YXIgdG1wID0gcHJldmlvdXNWZXJ0cztcclxuXHRcdHByZXZpb3VzVmVydHMgPSBjdXJyZW50VmVydHM7XHJcblx0XHRjdXJyZW50VmVydHMgPSB0bXA7XHJcblx0XHR0bXAgPSBwcmV2aW91c1ZlY3RvcjtcclxuXHRcdHByZXZpb3VzVmVjdG9yID0gY3VycmVudFZlY3RvcjtcclxuXHRcdGN1cnJlbnRWZWN0b3IgPSB0bXA7XHJcblx0XHR0bXAgPSBwcmV2aW91c0ludGVuc2l0eTtcclxuXHRcdHByZXZpb3VzSW50ZW5zaXR5ID0gY3VycmVudEludGVuc2l0eTtcclxuXHRcdGN1cnJlbnRJbnRlbnNpdHkgPSB0bXA7XHJcblx0fVxyXG5cdHJldHVybiB7XHJcblx0XHRwb3NpdGlvbnM6IHZlcnRzLFxyXG5cdFx0Y2VsbHM6IGZhY2VzLFxyXG5cdFx0dmVjdG9yczogdmVjdG9ycyxcclxuXHRcdHZlcnRleEludGVuc2l0eTogaW50ZW5zaXRpZXNcclxuXHR9O1xyXG5cclxufTtcclxuXHJcbnZhciBjcmVhdGVUdWJlcyA9IGZ1bmN0aW9uKHN0cmVhbXMsIGNvbG9ybWFwLCBtYXhEaXZlcmdlbmNlLCBtaW5EaXN0YW5jZSkge1xyXG5cclxuXHR2YXIgbWF4Tm9ybSA9IDA7XHJcblx0Zm9yICh2YXIgaT0wOyBpPHN0cmVhbXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciB2ZWxvY2l0aWVzID0gc3RyZWFtc1tpXS52ZWxvY2l0aWVzO1xyXG5cdFx0Zm9yICh2YXIgaj0wOyBqPHZlbG9jaXRpZXMubGVuZ3RoOyBqKyspIHtcclxuXHRcdFx0dmFyIG5vcm0gPSB2ZWMzLmxlbmd0aCh2ZWxvY2l0aWVzW2pdKTtcclxuXHRcdFx0aWYgKG5vcm0gPiBtYXhOb3JtKSB7XHJcblx0XHRcdFx0bWF4Tm9ybSA9IG5vcm07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHZhciB0dWJlcyA9IHN0cmVhbXMubWFwKGZ1bmN0aW9uKHMpIHtcclxuXHRcdHJldHVybiBzdHJlYW1Ub1R1YmUocywgbWF4RGl2ZXJnZW5jZSwgbWluRGlzdGFuY2UsIG1heE5vcm0pO1xyXG5cdH0pO1xyXG5cclxuXHR2YXIgcG9zaXRpb25zID0gW107XHJcblx0dmFyIGNlbGxzID0gW107XHJcblx0dmFyIHZlY3RvcnMgPSBbXTtcclxuXHR2YXIgdmVydGV4SW50ZW5zaXR5ID0gW107XHJcblx0Zm9yICh2YXIgaT0wOyBpIDwgdHViZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciB0dWJlID0gdHViZXNbaV07XHJcblx0XHR2YXIgb2Zmc2V0ID0gcG9zaXRpb25zLmxlbmd0aDtcclxuXHRcdHBvc2l0aW9ucyA9IHBvc2l0aW9ucy5jb25jYXQodHViZS5wb3NpdGlvbnMpO1xyXG5cdFx0dmVjdG9ycyA9IHZlY3RvcnMuY29uY2F0KHR1YmUudmVjdG9ycyk7XHJcblx0XHR2ZXJ0ZXhJbnRlbnNpdHkgPSB2ZXJ0ZXhJbnRlbnNpdHkuY29uY2F0KHR1YmUudmVydGV4SW50ZW5zaXR5KTtcclxuXHRcdGZvciAodmFyIGo9MDsgajx0dWJlLmNlbGxzLmxlbmd0aDsgaisrKSB7XHJcblx0XHRcdHZhciBjZWxsID0gdHViZS5jZWxsc1tqXTtcclxuXHRcdFx0dmFyIG5ld0NlbGwgPSBbXTtcclxuXHRcdFx0Y2VsbHMucHVzaChuZXdDZWxsKTtcclxuXHRcdFx0Zm9yICh2YXIgaz0wOyBrPGNlbGwubGVuZ3RoOyBrKyspIHtcclxuXHRcdFx0XHRuZXdDZWxsLnB1c2goY2VsbFtrXSArIG9mZnNldCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIHtcclxuXHRcdHBvc2l0aW9uczogcG9zaXRpb25zLFxyXG5cdFx0Y2VsbHM6IGNlbGxzLFxyXG5cdFx0dmVjdG9yczogdmVjdG9ycyxcclxuXHRcdHZlcnRleEludGVuc2l0eTogdmVydGV4SW50ZW5zaXR5LFxyXG5cdFx0Y29sb3JtYXA6IGNvbG9ybWFwXHJcblx0fTtcclxufTtcclxuXHJcbnZhciBkZWZhdWx0R2V0RGl2ZXJnZW5jZSA9IGZ1bmN0aW9uKHAsIHYwKSB7XHJcblx0dmFyIGRwID0gdmVjMy5jcmVhdGUoKTtcclxuXHR2YXIgZSA9IDEvMTAwMDA7XHJcblxyXG5cdHZlYzMuYWRkKGRwLCBwLCBbZSwgMCwgMF0pO1xyXG5cdHZhciB2eCA9IHRoaXMuZ2V0VmVsb2NpdHkoZHApO1xyXG5cdHZlYzMuc3VidHJhY3QodngsIHZ4LCB2MCk7XHJcblx0dmVjMy5zY2FsZSh2eCwgdngsIDEvZSk7XHJcblxyXG5cdHZlYzMuYWRkKGRwLCBwLCBbMCwgZSwgMF0pO1xyXG5cdHZhciB2eSA9IHRoaXMuZ2V0VmVsb2NpdHkoZHApO1xyXG5cdHZlYzMuc3VidHJhY3QodnksIHZ5LCB2MCk7XHJcblx0dmVjMy5zY2FsZSh2eSwgdnksIDEvZSk7XHJcblxyXG5cdHZlYzMuYWRkKGRwLCBwLCBbMCwgMCwgZV0pO1xyXG5cdHZhciB2eiA9IHRoaXMuZ2V0VmVsb2NpdHkoZHApO1xyXG5cdHZlYzMuc3VidHJhY3QodnosIHZ6LCB2MCk7XHJcblx0dmVjMy5zY2FsZSh2eiwgdnosIDEvZSk7XHJcblxyXG5cdHZlYzMuYWRkKGRwLCB2eCwgdnkpO1xyXG5cdHZlYzMuYWRkKGRwLCBkcCwgdnopO1xyXG5cdHJldHVybiBkcDtcclxufTtcclxuXHJcbnZhciBkZWZhdWx0R2V0VmVsb2NpdHkgPSBmdW5jdGlvbihwKSB7XHJcbiAgICB2YXIgdSA9IHNhbXBsZU1lc2hncmlkKHAsIHRoaXMudmVjdG9ycywgdGhpcy5tZXNoZ3JpZCwgdGhpcy5jbGFtcEJvcmRlcnMpO1xyXG4gICAgcmV0dXJuIHU7XHJcbn07XHJcblxyXG5cclxudmFyIGZpbmRMYXN0U21hbGxlckluZGV4ID0gZnVuY3Rpb24ocG9pbnRzLCB2KSB7XHJcbiAgZm9yICh2YXIgaT0wOyBpPHBvaW50cy5sZW5ndGg7IGkrKykge1xyXG4gIFx0dmFyIHAgPSBwb2ludHNbaV07XHJcbiAgXHRpZiAocCA9PT0gdikgcmV0dXJuIGk7XHJcbiAgICBpZiAocCA+IHYpIHJldHVybiBpLTE7XHJcbiAgfVxyXG4gIHJldHVybiBpO1xyXG59O1xyXG5cclxudmFyIHRtcCA9IHZlYzMuY3JlYXRlKCk7XHJcbnZhciB0bXAyID0gdmVjMy5jcmVhdGUoKTtcclxuXHJcbnZhciBjbGFtcCA9IGZ1bmN0aW9uKHYsIG1pbiwgbWF4KSB7XHJcblx0cmV0dXJuIHYgPCBtaW4gPyBtaW4gOiAodiA+IG1heCA/IG1heCA6IHYpO1xyXG59O1xyXG5cclxudmFyIHNhbXBsZU1lc2hncmlkID0gZnVuY3Rpb24ocG9pbnQsIGFycmF5LCBtZXNoZ3JpZCwgY2xhbXBPdmVyZmxvdykge1xyXG5cdHZhciB4ID0gcG9pbnRbMF07XHJcblx0dmFyIHkgPSBwb2ludFsxXTtcclxuXHR2YXIgeiA9IHBvaW50WzJdO1xyXG5cclxuXHR2YXIgdyA9IG1lc2hncmlkWzBdLmxlbmd0aDtcclxuXHR2YXIgaCA9IG1lc2hncmlkWzFdLmxlbmd0aDtcclxuXHR2YXIgZCA9IG1lc2hncmlkWzJdLmxlbmd0aDtcclxuXHJcblx0Ly8gRmluZCB0aGUgaW5kZXggb2YgdGhlIG5lYXJlc3Qgc21hbGxlciB2YWx1ZSBpbiB0aGUgbWVzaGdyaWQgZm9yIGVhY2ggY29vcmRpbmF0ZSBvZiAoeCx5LHopLlxyXG5cdC8vIFRoZSBuZWFyZXN0IHNtYWxsZXIgdmFsdWUgaW5kZXggZm9yIHggaXMgdGhlIGluZGV4IHgwIHN1Y2ggdGhhdFxyXG5cdC8vIG1lc2hncmlkWzBdW3gwXSA8IHggYW5kIGZvciBhbGwgeDEgPiB4MCwgbWVzaGdyaWRbMF1beDFdID49IHguXHJcblx0dmFyIHgwID0gZmluZExhc3RTbWFsbGVySW5kZXgobWVzaGdyaWRbMF0sIHgpO1xyXG5cdHZhciB5MCA9IGZpbmRMYXN0U21hbGxlckluZGV4KG1lc2hncmlkWzFdLCB5KTtcclxuXHR2YXIgejAgPSBmaW5kTGFzdFNtYWxsZXJJbmRleChtZXNoZ3JpZFsyXSwgeik7XHJcblxyXG5cdC8vIEdldCB0aGUgbmVhcmVzdCBsYXJnZXIgbWVzaGdyaWQgdmFsdWUgaW5kaWNlcy5cclxuXHQvLyBGcm9tIHRoZSBhYm92ZSBcIm5lYXJlc3Qgc21hbGxlciB2YWx1ZVwiLCB3ZSBrbm93IHRoYXRcclxuXHQvLyAgIG1lc2hncmlkWzBdW3gwXSA8IHhcclxuXHQvLyAgIG1lc2hncmlkWzBdW3gwKzFdID49IHhcclxuXHR2YXIgeDEgPSB4MCArIDE7XHJcblx0dmFyIHkxID0geTAgKyAxO1xyXG5cdHZhciB6MSA9IHowICsgMTtcclxuXHJcblx0aWYgKG1lc2hncmlkWzBdW3gwXSA9PT0geCkgeDEgPSB4MDtcclxuXHRpZiAobWVzaGdyaWRbMV1beTBdID09PSB5KSB5MSA9IHkwO1xyXG5cdGlmIChtZXNoZ3JpZFsyXVt6MF0gPT09IHopIHoxID0gejA7XHJcblxyXG5cdGlmIChjbGFtcE92ZXJmbG93KSB7XHJcblx0XHR4MCA9IGNsYW1wKHgwLCAwLCB3LTEpO1xyXG5cdFx0eDEgPSBjbGFtcCh4MSwgMCwgdy0xKTtcclxuXHRcdHkwID0gY2xhbXAoeTAsIDAsIGgtMSk7XHJcblx0XHR5MSA9IGNsYW1wKHkxLCAwLCBoLTEpO1xyXG5cdFx0ejAgPSBjbGFtcCh6MCwgMCwgZC0xKTtcclxuXHRcdHoxID0gY2xhbXAoejEsIDAsIGQtMSk7XHJcblx0fVxyXG5cclxuXHQvLyBSZWplY3QgcG9pbnRzIG91dHNpZGUgdGhlIG1lc2hncmlkLCByZXR1cm4gYSB6ZXJvIHZlY3Rvci5cclxuXHRpZiAoeDAgPCAwIHx8IHkwIDwgMCB8fCB6MCA8IDAgfHwgeDEgPj0gdyB8fCB5MSA+PSBoIHx8IHoxID49IGQpIHtcclxuXHRcdHJldHVybiB2ZWMzLmNyZWF0ZSgpO1xyXG5cdH1cclxuXHJcblx0Ly8gTm9ybWFsaXplIHBvaW50IGNvb3JkaW5hdGVzIHRvIDAuLjEgc2NhbGluZyBmYWN0b3IgYmV0d2VlbiB4MCBhbmQgeDEuXHJcblx0dmFyIHhmID0gKHggLSBtZXNoZ3JpZFswXVt4MF0pIC8gKG1lc2hncmlkWzBdW3gxXSAtIG1lc2hncmlkWzBdW3gwXSk7XHJcblx0dmFyIHlmID0gKHkgLSBtZXNoZ3JpZFsxXVt5MF0pIC8gKG1lc2hncmlkWzFdW3kxXSAtIG1lc2hncmlkWzFdW3kwXSk7XHJcblx0dmFyIHpmID0gKHogLSBtZXNoZ3JpZFsyXVt6MF0pIC8gKG1lc2hncmlkWzJdW3oxXSAtIG1lc2hncmlkWzJdW3owXSk7XHJcblxyXG5cdGlmICh4ZiA8IDAgfHwgeGYgPiAxIHx8IGlzTmFOKHhmKSkgeGYgPSAwO1xyXG5cdGlmICh5ZiA8IDAgfHwgeWYgPiAxIHx8IGlzTmFOKHlmKSkgeWYgPSAwO1xyXG5cdGlmICh6ZiA8IDAgfHwgemYgPiAxIHx8IGlzTmFOKHpmKSkgemYgPSAwO1xyXG5cclxuXHR2YXIgejBvZmYgPSB6MCp3Kmg7XHJcblx0dmFyIHoxb2ZmID0gejEqdypoO1xyXG5cclxuXHR2YXIgeTBvZmYgPSB5MCp3O1xyXG5cdHZhciB5MW9mZiA9IHkxKnc7XHJcblxyXG5cdHZhciB4MG9mZiA9IHgwO1xyXG5cdHZhciB4MW9mZiA9IHgxO1xyXG5cclxuXHQvLyBTYW1wbGUgZGF0YSBhcnJheSBhcm91bmQgdGhlICh4LHkseikgcG9pbnQuXHJcblx0Ly8gIHZaWVggPSBhcnJheVt6Wm9mZiArIHlZb2ZmICsgeFhvZmZdXHJcblx0dmFyIHYwMDAgPSBhcnJheVt5MG9mZiArIHowb2ZmICsgeDBvZmZdO1xyXG5cdHZhciB2MDAxID0gYXJyYXlbeTBvZmYgKyB6MG9mZiArIHgxb2ZmXTtcclxuXHR2YXIgdjAxMCA9IGFycmF5W3kxb2ZmICsgejBvZmYgKyB4MG9mZl07XHJcblx0dmFyIHYwMTEgPSBhcnJheVt5MW9mZiArIHowb2ZmICsgeDFvZmZdO1xyXG5cdHZhciB2MTAwID0gYXJyYXlbeTBvZmYgKyB6MW9mZiArIHgwb2ZmXTtcclxuXHR2YXIgdjEwMSA9IGFycmF5W3kwb2ZmICsgejFvZmYgKyB4MW9mZl07XHJcblx0dmFyIHYxMTAgPSBhcnJheVt5MW9mZiArIHoxb2ZmICsgeDBvZmZdO1xyXG5cdHZhciB2MTExID0gYXJyYXlbeTFvZmYgKyB6MW9mZiArIHgxb2ZmXTtcclxuXHJcblx0dmFyIHJlc3VsdCA9IHZlYzMuY3JlYXRlKCk7XHJcblxyXG5cdC8vIEF2ZXJhZ2Ugc2FtcGxlcyBhY2NvcmRpbmcgdG8gZGlzdGFuY2UgdG8gcG9pbnQuXHJcblx0dmVjMy5sZXJwKHJlc3VsdCwgdjAwMCwgdjAwMSwgeGYpO1xyXG5cdHZlYzMubGVycCh0bXAsIHYwMTAsIHYwMTEsIHhmKTtcclxuXHR2ZWMzLmxlcnAocmVzdWx0LCByZXN1bHQsIHRtcCwgeWYpO1xyXG5cdHZlYzMubGVycCh0bXAsIHYxMDAsIHYxMDEsIHhmKTtcclxuXHR2ZWMzLmxlcnAodG1wMiwgdjExMCwgdjExMSwgeGYpO1xyXG5cdHZlYzMubGVycCh0bXAsIHRtcCwgdG1wMiwgeWYpO1xyXG5cdHZlYzMubGVycChyZXN1bHQsIHJlc3VsdCwgdG1wLCB6Zik7XHJcblxyXG5cdHJldHVybiByZXN1bHQ7XHJcbn07XHJcblxyXG5cclxudmFyIHZhYnMgPSBmdW5jdGlvbihkc3QsIHYpIHtcclxuXHR2YXIgeCA9IHZbMF07XHJcblx0dmFyIHkgPSB2WzFdO1xyXG5cdHZhciB6ID0gdlsyXTtcclxuXHRkc3RbMF0gPSB4ID49IDAgPyB4IDogLXg7XHJcblx0ZHN0WzFdID0geSA+PSAwID8geSA6IC15O1xyXG5cdGRzdFsyXSA9IHogPj0gMCA/IHogOiAtejtcclxuXHRyZXR1cm4gZHN0O1xyXG59O1xyXG5cclxudmFyIGZpbmRNaW5TZXBhcmF0aW9uID0gZnVuY3Rpb24oeHMpIHtcclxuXHR2YXIgbWluU2VwYXJhdGlvbiA9IDEvMDtcclxuXHR4cy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9KTtcclxuXHRmb3IgKHZhciBpPTE7IGk8eHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciBkID0gTWF0aC5hYnMoeHNbaV0gLSB4c1tpLTFdKTtcclxuXHRcdGlmIChkIDwgbWluU2VwYXJhdGlvbikge1xyXG5cdFx0XHRtaW5TZXBhcmF0aW9uID0gZDtcclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIG1pblNlcGFyYXRpb247XHJcbn07XHJcblxyXG4vLyBGaW5kcyB0aGUgbWluaW11bSBwZXItY29tcG9uZW50IGRpc3RhbmNlIGluIHBvc2l0aW9ucy5cclxuLy8gXHJcbnZhciBjYWxjdWxhdGVNaW5Qb3NpdGlvbkRpc3RhbmNlID0gZnVuY3Rpb24ocG9zaXRpb25zKSB7XHJcblx0dmFyIHhzID0gW10sIHlzID0gW10sIHpzID0gW107XHJcblx0dmFyIHhpID0ge30sIHlpID0ge30sIHppID0ge307XHJcblx0Zm9yICh2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7IGkrKykge1xyXG5cdFx0dmFyIHAgPSBwb3NpdGlvbnNbaV07XHJcblx0XHR2YXIgeCA9IHBbMF0sIHkgPSBwWzFdLCB6ID0gcFsyXTtcclxuXHJcblx0XHQvLyBTcGxpdCB0aGUgcG9zaXRpb25zIGFycmF5IGludG8gYXJyYXlzIG9mIHVuaXF1ZSBjb21wb25lbnQgdmFsdWVzLlxyXG5cdFx0Ly9cclxuXHRcdC8vIFdoeSBnbyB0aHJvdWdoIHRoZSB0cm91YmxlIG9mIHVzaW5nIGEgdW5pcXVlbmVzcyBoYXNoIHRhYmxlIHZzXHJcblx0XHQvLyBzb3J0IGFuZCB1bmlxOiBcclxuXHRcdC8vXHJcblx0XHQvLyBTdXBwb3NlIHlvdSd2ZSBnb3QgYSBtaWxsaW9uIHBvc2l0aW9ucyBpbiBhIDEwMHgxMDB4MTAwIGdyaWQuXHJcblx0XHQvL1xyXG5cdFx0Ly8gVXNpbmcgYSB1bmlxdWVuZXNzIGhhc2ggdGFibGUsIHlvdSdyZSBkb2luZyAxTSBhcnJheSByZWFkcywgXHJcblx0XHQvLyAzTSBoYXNoIHRhYmxlIGxvb2t1cHMgZnJvbSAxMDAtZWxlbWVudCBoYXNoZXMsIDMwMCBoYXNoIHRhYmxlIGluc2VydHMsIHRoZW5cclxuXHRcdC8vIHNvcnRpbmcgdGhyZWUgMTAwLWVsZW1lbnQgYXJyYXlzIGFuZCBpdGVyYXRpbmcgb3ZlciB0aGVtLlxyXG5cdFx0Ly8gUm91Z2hseSwgMU0gKyAzTSAqIGxuKDEwMCkgKyAzMDAgKiBsbigxMDAvMikgKyAzICogMTAwICogbG4oMTAwKSArIDMgKiAxMDAgPSBcclxuXHRcdC8vICAgICAgICAgIDFNICsgMTMuOE0gKyAwLjAwMTJNICsgIDAuMDAxNE0gKyAwLjAwMDNNIFxyXG5cdFx0Ly8gICAgICAgICAgPX4gMTVNXHJcblx0XHQvL1xyXG5cdFx0Ly8gU29ydCBhbmQgdW5pcSBzb2x1dGlvbiB3b3VsZCBkbyAxTSBhcnJheSByZWFkcywgM00gYXJyYXkgaW5zZXJ0cyxcclxuXHRcdC8vIHNvcnQgdGhyZWUgMU0tZWxlbWVudCBhcnJheXMgYW5kIGl0ZXJhdGUgb3ZlciB0aGVtLlxyXG5cdFx0Ly8gUm91Z2hseSwgMU0gKyAzTSArIDMgKiAxTSAqIGxuKDFNKSArIDMgKiAxTSA9IFxyXG5cdFx0Ly8gICAgICAgICAgMU0gKyAzTSArIDQxLjRNICsgM00gXHJcblx0XHQvLyAgICAgICAgICA9fiA0OC40TVxyXG5cdFx0Ly9cclxuXHRcdC8vIEd1ZXNzaW5nIHRoYXQgYSBoYXJkLWNvZGVkIHNvcnQgJiB1bmlxIHdvdWxkIGJlIGZhc3RlciBkdWUgdG8gbm90IGhhdmluZ1xyXG5cdFx0Ly8gdG8gcnVuIGEgaGFzaGluZyBmdW5jdGlvbiBvbiBldmVyeXRoaW5nLiBNb3JlIG1lbW9yeSB1c2FnZSB0aG91Z2ggXHJcblx0XHQvLyAoYnVuY2ggb2Ygc21hbGwgaGFzaCB0YWJsZXMgdnMuIGR1cGxpY2F0aW5nIHRoZSBpbnB1dCBhcnJheS4pXHJcblx0XHQvL1xyXG5cdFx0Ly8gSW4gSlMtbGFuZCwgd2hvIGtub3dzLiBNYXliZSB4aVt4XSBjYXN0cyB4IHRvIHN0cmluZyBhbmQgZGVzdHJveXMgcGVyZiwgXHJcblx0XHQvLyBtYXliZSBudW1lcmljIGtleXMgZ2V0IHNwZWNpYWwtY2FzZWQsIG1heWJlIHRoZSBvYmplY3QgbG9va3VwcyBydW4gYXQgbmVhciBPKDEpLXNwZWVkcy5cclxuXHRcdC8vIE1heWJlIHRoZSBzb3J0aW5nIGNvbXBhcmlzb24gZnVuY3Rpb24gaXMgZXhwZW5zaXZlIHRvIGNhbGwsIG1heWJlIGl0IGdldHMgaW5saW5lZCBvciBzcGVjaWFsLWNhc2VkLlxyXG5cdFx0Ly9cclxuXHRcdC8vIC4uLiBZb3UncmUgcHJvYmFibHkgbm90IGdvaW5nIHRvIGNhbGwgdGhpcyB3aXRoIG1vcmUgdGhhbiAxMGsgcG9zaXRpb25zIGFueWhvdywgc28gdGhpcyBpcyB2ZXJ5IGFjYWRlbWljLlxyXG5cdFx0Ly9cclxuXHRcdGlmICgheGlbeF0pIHtcclxuXHRcdFx0eHMucHVzaCh4KTtcclxuXHRcdFx0eGlbeF0gPSB0cnVlO1xyXG5cdFx0fVxyXG5cdFx0aWYgKCF5aVt5XSkge1xyXG5cdFx0XHR5cy5wdXNoKHkpO1xyXG5cdFx0XHR5aVt5XSA9IHRydWU7XHJcblx0XHR9XHJcblx0XHRpZiAoIXppW3pdKSB7XHJcblx0XHRcdHpzLnB1c2goeik7XHJcblx0XHRcdHppW3pdID0gdHJ1ZTtcclxuXHRcdH1cclxuXHR9XHJcblx0dmFyIHhTZXAgPSBmaW5kTWluU2VwYXJhdGlvbih4cyk7XHJcblx0dmFyIHlTZXAgPSBmaW5kTWluU2VwYXJhdGlvbih5cyk7XHJcblx0dmFyIHpTZXAgPSBmaW5kTWluU2VwYXJhdGlvbih6cyk7XHJcblx0dmFyIG1pblNlcGFyYXRpb24gPSBNYXRoLm1pbih4U2VwLCB5U2VwLCB6U2VwKTtcclxuXHRpZiAoIWlzRmluaXRlKG1pblNlcGFyYXRpb24pKSB7XHJcblx0XHRyZXR1cm4gMTtcclxuXHR9XHJcblx0cmV0dXJuIG1pblNlcGFyYXRpb247XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHZlY3RvckZpZWxkLCBib3VuZHMpIHtcclxuXHR2YXIgcG9zaXRpb25zID0gdmVjdG9yRmllbGQuc3RhcnRpbmdQb3NpdGlvbnM7XHJcblx0dmFyIG1heExlbmd0aCA9IHZlY3RvckZpZWxkLm1heExlbmd0aCB8fCAxMDAwO1xyXG5cdHZhciB0dWJlU2l6ZSA9IHZlY3RvckZpZWxkLnR1YmVTaXplIHx8IDE7XHJcblx0dmFyIGFic29sdXRlVHViZVNpemUgPSB2ZWN0b3JGaWVsZC5hYnNvbHV0ZVR1YmVTaXplO1xyXG5cclxuXHRpZiAoIXZlY3RvckZpZWxkLmdldERpdmVyZ2VuY2UpIHtcclxuXHRcdHZlY3RvckZpZWxkLmdldERpdmVyZ2VuY2UgPSBkZWZhdWx0R2V0RGl2ZXJnZW5jZTtcclxuXHR9XHJcblxyXG5cdGlmICghdmVjdG9yRmllbGQuZ2V0VmVsb2NpdHkpIHtcclxuXHRcdHZlY3RvckZpZWxkLmdldFZlbG9jaXR5ID0gZGVmYXVsdEdldFZlbG9jaXR5O1xyXG5cdH1cclxuXHJcblx0aWYgKHZlY3RvckZpZWxkLmNsYW1wQm9yZGVycyA9PT0gdW5kZWZpbmVkKSB7XHJcblx0XHR2ZWN0b3JGaWVsZC5jbGFtcEJvcmRlcnMgPSB0cnVlO1xyXG5cdH1cclxuXHJcblx0dmFyIHN0cmVhbXMgPSBbXTtcclxuXHJcblx0dmFyIG1pblggPSBib3VuZHNbMF1bMF0sIG1pblkgPSBib3VuZHNbMF1bMV0sIG1pblogPSBib3VuZHNbMF1bMl07XHJcblx0dmFyIG1heFggPSBib3VuZHNbMV1bMF0sIG1heFkgPSBib3VuZHNbMV1bMV0sIG1heFogPSBib3VuZHNbMV1bMl07XHJcblxyXG5cdHZhciBpbkJvdW5kcyA9IGZ1bmN0aW9uKGJvdW5kcywgcCkge1xyXG5cdFx0dmFyIHggPSBwWzBdO1xyXG5cdFx0dmFyIHkgPSBwWzFdO1xyXG5cdFx0dmFyIHogPSBwWzJdO1xyXG5cdFx0cmV0dXJuIChcclxuXHRcdFx0eCA+PSBtaW5YICYmIHggPD0gbWF4WCAmJlxyXG5cdFx0XHR5ID49IG1pblkgJiYgeSA8PSBtYXhZICYmXHJcblx0XHRcdHogPj0gbWluWiAmJiB6IDw9IG1heFpcclxuXHRcdCk7XHJcblx0fTtcclxuXHJcblx0dmFyIGJvdW5kc1NpemUgPSB2ZWMzLmRpc3RhbmNlKGJvdW5kc1swXSwgYm91bmRzWzFdKTtcclxuXHR2YXIgbWF4U3RlcFNpemUgPSAxMCAqIGJvdW5kc1NpemUgLyBtYXhMZW5ndGg7XHJcblx0dmFyIG1heFN0ZXBTaXplU3EgPSBtYXhTdGVwU2l6ZSAqIG1heFN0ZXBTaXplO1xyXG5cclxuXHR2YXIgbWluRGlzdGFuY2UgPSAxO1xyXG5cdHZhciBtYXhEaXZlcmdlbmNlID0gMDsgLy8gRm9yIGNvbXBvbmVudC13aXNlIGRpdmVyZ2VuY2UgdmVjMy5jcmVhdGUoKTtcclxuXHR2YXIgdG1wID0gdmVjMy5jcmVhdGUoKTtcclxuXHJcblx0aWYgKHBvc2l0aW9ucy5sZW5ndGggPj0gMikge1xyXG5cdFx0bWluRGlzdGFuY2UgPSBjYWxjdWxhdGVNaW5Qb3NpdGlvbkRpc3RhbmNlKHBvc2l0aW9ucyk7XHJcblx0fVxyXG5cclxuXHRmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykge1xyXG5cdFx0dmFyIHAgPSB2ZWMzLmNyZWF0ZSgpO1xyXG5cdFx0dmVjMy5jb3B5KHAsIHBvc2l0aW9uc1tpXSk7XHJcblxyXG5cdFx0dmFyIHN0cmVhbSA9IFtwXTtcclxuXHRcdHZhciB2ZWxvY2l0aWVzID0gW107XHJcblx0XHR2YXIgdiA9IHZlY3RvckZpZWxkLmdldFZlbG9jaXR5KHApO1xyXG5cdFx0dmFyIG9wID0gcDtcclxuXHRcdHZlbG9jaXRpZXMucHVzaCh2KTtcclxuXHJcblx0XHR2YXIgZGl2ZXJnZW5jZXMgPSBbXTtcclxuXHJcblx0XHR2YXIgZHYgPSB2ZWN0b3JGaWVsZC5nZXREaXZlcmdlbmNlKHAsIHYpO1xyXG5cdFx0dmFyIGR2TGVuZ3RoID0gdmVjMy5sZW5ndGgoZHYpO1xyXG5cdFx0aWYgKGR2TGVuZ3RoID4gbWF4RGl2ZXJnZW5jZSAmJiAhaXNOYU4oZHZMZW5ndGgpICYmIGlzRmluaXRlKGR2TGVuZ3RoKSkge1xyXG5cdFx0XHRtYXhEaXZlcmdlbmNlID0gZHZMZW5ndGg7XHJcblx0XHR9XHJcblx0XHQvLyBJbiBjYXNlIHdlIG5lZWQgdG8gZG8gY29tcG9uZW50LXdpc2UgZGl2ZXJnZW5jZSB2aXN1YWxpemF0aW9uXHJcblx0XHQvLyB2ZWMzLm1heChtYXhEaXZlcmdlbmNlLCBtYXhEaXZlcmdlbmNlLCB2YWJzKHRtcCwgZHYpKTtcclxuXHRcdGRpdmVyZ2VuY2VzLnB1c2goZHZMZW5ndGgpO1xyXG5cclxuXHRcdHN0cmVhbXMucHVzaCh7cG9pbnRzOiBzdHJlYW0sIHZlbG9jaXRpZXM6IHZlbG9jaXRpZXMsIGRpdmVyZ2VuY2VzOiBkaXZlcmdlbmNlc30pO1xyXG5cclxuXHRcdHZhciBqID0gMDtcclxuXHJcblx0XHR3aGlsZSAoaiA8IG1heExlbmd0aCAqIDEwMCAmJiBzdHJlYW0ubGVuZ3RoIDwgbWF4TGVuZ3RoICYmIGluQm91bmRzKGJvdW5kcywgcCkpIHtcclxuXHRcdFx0aisrO1xyXG5cdFx0XHR2YXIgbnAgPSB2ZWMzLmNsb25lKHYpO1xyXG5cdFx0XHR2YXIgc3FMZW4gPSB2ZWMzLnNxdWFyZWRMZW5ndGgobnApO1xyXG5cdFx0XHRpZiAoc3FMZW4gPT09IDApIHtcclxuXHRcdFx0XHRicmVhaztcclxuXHRcdFx0fSBlbHNlIGlmIChzcUxlbiA+IG1heFN0ZXBTaXplU3EpIHtcclxuXHRcdFx0XHR2ZWMzLnNjYWxlKG5wLCBucCwgbWF4U3RlcFNpemUgLyBNYXRoLnNxcnQoc3FMZW4pKTtcclxuXHRcdFx0fVxyXG5cdFx0XHR2ZWMzLmFkZChucCwgbnAsIHApO1xyXG5cclxuXHRcdFx0diA9IHZlY3RvckZpZWxkLmdldFZlbG9jaXR5KG5wKTtcclxuXHJcblx0XHRcdGlmICh2ZWMzLnNxdWFyZWREaXN0YW5jZShvcCwgbnApIC0gbWF4U3RlcFNpemVTcSA+IC0wLjAwMDEgKiBtYXhTdGVwU2l6ZVNxKSB7XHJcblx0XHRcdFx0c3RyZWFtLnB1c2gobnApO1xyXG5cdFx0XHRcdG9wID0gbnA7XHJcblx0XHRcdFx0dmVsb2NpdGllcy5wdXNoKHYpO1xyXG5cdFx0XHRcdHZhciBkdiA9IHZlY3RvckZpZWxkLmdldERpdmVyZ2VuY2UobnAsIHYpO1xyXG5cdFx0XHRcdHZhciBkdkxlbmd0aCA9IHZlYzMubGVuZ3RoKGR2KTtcclxuXHRcdFx0XHRpZiAoZHZMZW5ndGggPiBtYXhEaXZlcmdlbmNlICYmICFpc05hTihkdkxlbmd0aCkgJiYgaXNGaW5pdGUoZHZMZW5ndGgpKSB7XHJcblx0XHRcdFx0XHRtYXhEaXZlcmdlbmNlID0gZHZMZW5ndGg7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdC8vIEluIGNhc2Ugd2UgbmVlZCB0byBkbyBjb21wb25lbnQtd2lzZSBkaXZlcmdlbmNlIHZpc3VhbGl6YXRpb25cclxuXHRcdFx0XHQvL3ZlYzMubWF4KG1heERpdmVyZ2VuY2UsIG1heERpdmVyZ2VuY2UsIHZhYnModG1wLCBkdikpO1xyXG5cdFx0XHRcdGRpdmVyZ2VuY2VzLnB1c2goZHZMZW5ndGgpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRwID0gbnA7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBSZXBsYWNlIE5hTnMgYW5kIEluZmluaXRpZXMgd2l0aCBub24tTmFOLCBmaW5pdGUgbWF4RGl2ZXJnZW5jZVxyXG5cdGZvciAodmFyIGk9MDsgaTxkaXZlcmdlbmNlcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0dmFyIGR2TGVuZ3RoID0gZGl2ZXJnZW5jZXNbaV07XHJcblx0XHRpZiAoaXNOYU4oZHZMZW5ndGgpIHx8ICFpc0Zpbml0ZShkdkxlbmd0aCkpIHtcclxuXHRcdFx0ZGl2ZXJnZW5jZXNbaV0gPSBtYXhEaXZlcmdlbmNlO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0dmFyIHR1YmVzID0gY3JlYXRlVHViZXMoc3RyZWFtcywgdmVjdG9yRmllbGQuY29sb3JtYXAsIG1heERpdmVyZ2VuY2UsIG1pbkRpc3RhbmNlKTtcclxuXHJcblx0aWYgKGFic29sdXRlVHViZVNpemUpIHtcclxuXHRcdHR1YmVzLnR1YmVTY2FsZSA9IGFic29sdXRlVHViZVNpemU7XHJcblx0fSBlbHNlIHtcclxuXHRcdC8vIEF2b2lkIGRpdmlzaW9uIGJ5IHplcm8uXHJcblx0XHRpZiAobWF4RGl2ZXJnZW5jZSA9PT0gMCkge1xyXG5cdFx0XHRtYXhEaXZlcmdlbmNlID0gMTtcclxuXHRcdH1cclxuXHRcdHR1YmVzLnR1YmVTY2FsZSA9IHR1YmVTaXplICogMC41ICogbWluRGlzdGFuY2UgLyBtYXhEaXZlcmdlbmNlO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIHR1YmVzO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMuY3JlYXRlVHViZU1lc2ggPSByZXF1aXJlKCcuL2xpYi90dWJlbWVzaCcpO1xyXG4iLCJ2YXIgY3JlYXRlU2hhZGVyID0gcmVxdWlyZSgnZ2wtc2hhZGVyJylcclxudmFyIGdsc2xpZnkgPSByZXF1aXJlKCdnbHNsaWZ5JylcclxuXHJcbnZhciB2ZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHV2O1xcbmF0dHJpYnV0ZSB2ZWMzIGY7XFxuYXR0cmlidXRlIHZlYzMgbm9ybWFsO1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgaW52ZXJzZU1vZGVsO1xcbnVuaWZvcm0gdmVjMyBsaWdodFBvc2l0aW9uLCBleWVQb3NpdGlvbjtcXG51bmlmb3JtIHNhbXBsZXIyRCBjb2xvcm1hcDtcXG5cXG52YXJ5aW5nIGZsb2F0IHZhbHVlLCBraWxsO1xcbnZhcnlpbmcgdmVjMyB3b3JsZENvb3JkaW5hdGU7XFxudmFyeWluZyB2ZWMyIHBsYW5lQ29vcmRpbmF0ZTtcXG52YXJ5aW5nIHZlYzMgbGlnaHREaXJlY3Rpb24sIGV5ZURpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbDtcXG52YXJ5aW5nIHZlYzQgdkNvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHdvcmxkQ29vcmRpbmF0ZSA9IHZlYzModXYuencsIGYueCk7XFxuICB2ZWM0IHdvcmxkUG9zaXRpb24gPSBtb2RlbCAqIHZlYzQod29ybGRDb29yZGluYXRlLCAxLjApO1xcbiAgdmVjNCBjbGlwUG9zaXRpb24gPSBwcm9qZWN0aW9uICogdmlldyAqIHdvcmxkUG9zaXRpb247XFxuICBnbF9Qb3NpdGlvbiA9IGNsaXBQb3NpdGlvbjtcXG4gIGtpbGwgPSBmLnk7XFxuICB2YWx1ZSA9IGYuejtcXG4gIHBsYW5lQ29vcmRpbmF0ZSA9IHV2Lnh5O1xcblxcbiAgdkNvbG9yID0gdGV4dHVyZTJEKGNvbG9ybWFwLCB2ZWMyKHZhbHVlLCB2YWx1ZSkpO1xcblxcbiAgLy9MaWdodGluZyBnZW9tZXRyeSBwYXJhbWV0ZXJzXFxuICB2ZWM0IGNhbWVyYUNvb3JkaW5hdGUgPSB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gIGNhbWVyYUNvb3JkaW5hdGUueHl6IC89IGNhbWVyYUNvb3JkaW5hdGUudztcXG4gIGxpZ2h0RGlyZWN0aW9uID0gbGlnaHRQb3NpdGlvbiAtIGNhbWVyYUNvb3JkaW5hdGUueHl6O1xcbiAgZXllRGlyZWN0aW9uICAgPSBleWVQb3NpdGlvbiAtIGNhbWVyYUNvb3JkaW5hdGUueHl6O1xcbiAgc3VyZmFjZU5vcm1hbCAgPSBub3JtYWxpemUoKHZlYzQobm9ybWFsLDApICogaW52ZXJzZU1vZGVsKS54eXopO1xcbn1cXG5cIl0pXHJcbnZhciBmcmFnU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmZsb2F0IGJlY2ttYW5uRGlzdHJpYnV0aW9uKGZsb2F0IHgsIGZsb2F0IHJvdWdobmVzcykge1xcbiAgZmxvYXQgTmRvdEggPSBtYXgoeCwgMC4wMDAxKTtcXG4gIGZsb2F0IGNvczJBbHBoYSA9IE5kb3RIICogTmRvdEg7XFxuICBmbG9hdCB0YW4yQWxwaGEgPSAoY29zMkFscGhhIC0gMS4wKSAvIGNvczJBbHBoYTtcXG4gIGZsb2F0IHJvdWdobmVzczIgPSByb3VnaG5lc3MgKiByb3VnaG5lc3M7XFxuICBmbG9hdCBkZW5vbSA9IDMuMTQxNTkyNjUzNTg5NzkzICogcm91Z2huZXNzMiAqIGNvczJBbHBoYSAqIGNvczJBbHBoYTtcXG4gIHJldHVybiBleHAodGFuMkFscGhhIC8gcm91Z2huZXNzMikgLyBkZW5vbTtcXG59XFxuXFxuZmxvYXQgYmVja21hbm5TcGVjdWxhcihcXG4gIHZlYzMgbGlnaHREaXJlY3Rpb24sXFxuICB2ZWMzIHZpZXdEaXJlY3Rpb24sXFxuICB2ZWMzIHN1cmZhY2VOb3JtYWwsXFxuICBmbG9hdCByb3VnaG5lc3MpIHtcXG4gIHJldHVybiBiZWNrbWFubkRpc3RyaWJ1dGlvbihkb3Qoc3VyZmFjZU5vcm1hbCwgbm9ybWFsaXplKGxpZ2h0RGlyZWN0aW9uICsgdmlld0RpcmVjdGlvbikpLCByb3VnaG5lc3MpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgbG93ZXJCb3VuZCwgdXBwZXJCb3VuZDtcXG51bmlmb3JtIGZsb2F0IGNvbnRvdXJUaW50O1xcbnVuaWZvcm0gdmVjNCBjb250b3VyQ29sb3I7XFxudW5pZm9ybSBzYW1wbGVyMkQgY29sb3JtYXA7XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCByb3VnaG5lc3MsIGZyZXNuZWwsIGthbWJpZW50LCBrZGlmZnVzZSwga3NwZWN1bGFyLCBvcGFjaXR5O1xcbnVuaWZvcm0gZmxvYXQgdmVydGV4Q29sb3I7XFxuXFxudmFyeWluZyBmbG9hdCB2YWx1ZSwga2lsbDtcXG52YXJ5aW5nIHZlYzMgd29ybGRDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMyBsaWdodERpcmVjdGlvbiwgZXllRGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsO1xcbnZhcnlpbmcgdmVjNCB2Q29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKChraWxsID4gMC4wKSB8fFxcbiAgICAgIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHdvcmxkQ29vcmRpbmF0ZSkpKSBkaXNjYXJkO1xcblxcbiAgdmVjMyBOID0gbm9ybWFsaXplKHN1cmZhY2VOb3JtYWwpO1xcbiAgdmVjMyBWID0gbm9ybWFsaXplKGV5ZURpcmVjdGlvbik7XFxuICB2ZWMzIEwgPSBub3JtYWxpemUobGlnaHREaXJlY3Rpb24pO1xcblxcbiAgaWYoZ2xfRnJvbnRGYWNpbmcpIHtcXG4gICAgTiA9IC1OO1xcbiAgfVxcblxcbiAgZmxvYXQgc3BlY3VsYXIgPSBtYXgoYmVja21hbm5TcGVjdWxhcihMLCBWLCBOLCByb3VnaG5lc3MpLCAwLik7XFxuICBmbG9hdCBkaWZmdXNlICA9IG1pbihrYW1iaWVudCArIGtkaWZmdXNlICogbWF4KGRvdChOLCBMKSwgMC4wKSwgMS4wKTtcXG5cXG4gIC8vZGVjaWRlIGhvdyB0byBpbnRlcnBvbGF0ZSBjb2xvciDigJQgaW4gdmVydGV4IG9yIGluIGZyYWdtZW50XFxuICB2ZWM0IHN1cmZhY2VDb2xvciA9IHN0ZXAodmVydGV4Q29sb3IsIC41KSAqIHRleHR1cmUyRChjb2xvcm1hcCwgdmVjMih2YWx1ZSwgdmFsdWUpKSArIHN0ZXAoLjUsIHZlcnRleENvbG9yKSAqIHZDb2xvcjtcXG5cXG4gIHZlYzQgbGl0Q29sb3IgPSBzdXJmYWNlQ29sb3IuYSAqIHZlYzQoZGlmZnVzZSAqIHN1cmZhY2VDb2xvci5yZ2IgKyBrc3BlY3VsYXIgKiB2ZWMzKDEsMSwxKSAqIHNwZWN1bGFyLCAgMS4wKTtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IG1peChsaXRDb2xvciwgY29udG91ckNvbG9yLCBjb250b3VyVGludCkgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXHJcbnZhciBjb250b3VyVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjNCB1djtcXG5hdHRyaWJ1dGUgZmxvYXQgZjtcXG5cXG51bmlmb3JtIG1hdDMgcGVybXV0YXRpb247XFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gZmxvYXQgaGVpZ2h0LCB6T2Zmc2V0O1xcbnVuaWZvcm0gc2FtcGxlcjJEIGNvbG9ybWFwO1xcblxcbnZhcnlpbmcgZmxvYXQgdmFsdWUsIGtpbGw7XFxudmFyeWluZyB2ZWMzIHdvcmxkQ29vcmRpbmF0ZTtcXG52YXJ5aW5nIHZlYzIgcGxhbmVDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMyBsaWdodERpcmVjdGlvbiwgZXllRGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsO1xcbnZhcnlpbmcgdmVjNCB2Q29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBkYXRhQ29vcmRpbmF0ZSA9IHBlcm11dGF0aW9uICogdmVjMyh1di54eSwgaGVpZ2h0KTtcXG4gIHZlYzQgd29ybGRQb3NpdGlvbiA9IG1vZGVsICogdmVjNChkYXRhQ29vcmRpbmF0ZSwgMS4wKTtcXG5cXG4gIHZlYzQgY2xpcFBvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiB3b3JsZFBvc2l0aW9uO1xcbiAgY2xpcFBvc2l0aW9uLnogPSBjbGlwUG9zaXRpb24ueiArIHpPZmZzZXQ7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IGNsaXBQb3NpdGlvbjtcXG4gIHZhbHVlID0gZjtcXG4gIGtpbGwgPSAtMS4wO1xcbiAgd29ybGRDb29yZGluYXRlID0gZGF0YUNvb3JkaW5hdGU7XFxuICBwbGFuZUNvb3JkaW5hdGUgPSB1di56dztcXG5cXG4gIHZDb2xvciA9IHRleHR1cmUyRChjb2xvcm1hcCwgdmVjMih2YWx1ZSwgdmFsdWUpKTtcXG5cXG4gIC8vRG9uJ3QgZG8gbGlnaHRpbmcgZm9yIGNvbnRvdXJzXFxuICBzdXJmYWNlTm9ybWFsICAgPSB2ZWMzKDEsMCwwKTtcXG4gIGV5ZURpcmVjdGlvbiAgICA9IHZlYzMoMCwxLDApO1xcbiAgbGlnaHREaXJlY3Rpb24gID0gdmVjMygwLDAsMSk7XFxufVxcblwiXSlcclxudmFyIHBpY2tTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMyIHNoYXBlO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcGlja0lkO1xcblxcbnZhcnlpbmcgZmxvYXQgdmFsdWUsIGtpbGw7XFxudmFyeWluZyB2ZWMzIHdvcmxkQ29vcmRpbmF0ZTtcXG52YXJ5aW5nIHZlYzIgcGxhbmVDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMyBzdXJmYWNlTm9ybWFsO1xcblxcbnZlYzIgc3BsaXRGbG9hdChmbG9hdCB2KSB7XFxuICBmbG9hdCB2aCA9IDI1NS4wICogdjtcXG4gIGZsb2F0IHVwcGVyID0gZmxvb3IodmgpO1xcbiAgZmxvYXQgbG93ZXIgPSBmcmFjdCh2aCk7XFxuICByZXR1cm4gdmVjMih1cHBlciAvIDI1NS4wLCBmbG9vcihsb3dlciAqIDE2LjApIC8gMTYuMCk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmICgoa2lsbCA+IDAuMCkgfHxcXG4gICAgICAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCB3b3JsZENvb3JkaW5hdGUpKSkgZGlzY2FyZDtcXG5cXG4gIHZlYzIgdXggPSBzcGxpdEZsb2F0KHBsYW5lQ29vcmRpbmF0ZS54IC8gc2hhcGUueCk7XFxuICB2ZWMyIHV5ID0gc3BsaXRGbG9hdChwbGFuZUNvb3JkaW5hdGUueSAvIHNoYXBlLnkpO1xcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChwaWNrSWQsIHV4LngsIHV5LngsIHV4LnkgKyAodXkueS8xNi4wKSk7XFxufVxcblwiXSlcclxuXHJcbmV4cG9ydHMuY3JlYXRlU2hhZGVyID0gZnVuY3Rpb24gKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgZnJhZ1NyYywgbnVsbCwgW1xyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ2YnLCB0eXBlOiAndmVjMyd9LFxyXG4gICAge25hbWU6ICdub3JtYWwnLCB0eXBlOiAndmVjMyd9XHJcbiAgXSlcclxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5mLmxvY2F0aW9uID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiA9IDJcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuZXhwb3J0cy5jcmVhdGVQaWNrU2hhZGVyID0gZnVuY3Rpb24gKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgcGlja1NyYywgbnVsbCwgW1xyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ2YnLCB0eXBlOiAndmVjMyd9LFxyXG4gICAge25hbWU6ICdub3JtYWwnLCB0eXBlOiAndmVjMyd9XHJcbiAgXSlcclxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiA9IDBcclxuICBzaGFkZXIuYXR0cmlidXRlcy5mLmxvY2F0aW9uID0gMVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiA9IDJcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuZXhwb3J0cy5jcmVhdGVDb250b3VyU2hhZGVyID0gZnVuY3Rpb24gKGdsKSB7XHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgY29udG91clZlcnRTcmMsIGZyYWdTcmMsIG51bGwsIFtcclxuICAgIHtuYW1lOiAndXYnLCB0eXBlOiAndmVjNCd9LFxyXG4gICAge25hbWU6ICdmJywgdHlwZTogJ2Zsb2F0J31cclxuICBdKVxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uID0gMFxyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmYubG9jYXRpb24gPSAxXHJcbiAgcmV0dXJuIHNoYWRlclxyXG59XHJcbmV4cG9ydHMuY3JlYXRlUGlja0NvbnRvdXJTaGFkZXIgPSBmdW5jdGlvbiAoZ2wpIHtcclxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBjb250b3VyVmVydFNyYywgcGlja1NyYywgbnVsbCwgW1xyXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWM0J30sXHJcbiAgICB7bmFtZTogJ2YnLCB0eXBlOiAnZmxvYXQnfVxyXG4gIF0pXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gPSAwXHJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuZi5sb2NhdGlvbiA9IDFcclxuICByZXR1cm4gc2hhZGVyXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVN1cmZhY2VQbG90XHJcblxyXG52YXIgYml0cyA9IHJlcXVpcmUoJ2JpdC10d2lkZGxlJylcclxudmFyIGNyZWF0ZUJ1ZmZlciA9IHJlcXVpcmUoJ2dsLWJ1ZmZlcicpXHJcbnZhciBjcmVhdGVWQU8gPSByZXF1aXJlKCdnbC12YW8nKVxyXG52YXIgY3JlYXRlVGV4dHVyZSA9IHJlcXVpcmUoJ2dsLXRleHR1cmUyZCcpXHJcbnZhciBwb29sID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcclxudmFyIGNvbG9ybWFwID0gcmVxdWlyZSgnY29sb3JtYXAnKVxyXG52YXIgb3BzID0gcmVxdWlyZSgnbmRhcnJheS1vcHMnKVxyXG52YXIgcGFjayA9IHJlcXVpcmUoJ25kYXJyYXktcGFjaycpXHJcbnZhciBuZGFycmF5ID0gcmVxdWlyZSgnbmRhcnJheScpXHJcbnZhciBzdXJmYWNlTmV0cyA9IHJlcXVpcmUoJ3N1cmZhY2UtbmV0cycpXHJcbnZhciBtdWx0aXBseSA9IHJlcXVpcmUoJ2dsLW1hdDQvbXVsdGlwbHknKVxyXG52YXIgaW52ZXJ0ID0gcmVxdWlyZSgnZ2wtbWF0NC9pbnZlcnQnKVxyXG52YXIgYnNlYXJjaCA9IHJlcXVpcmUoJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcclxudmFyIGdyYWRpZW50ID0gcmVxdWlyZSgnbmRhcnJheS1ncmFkaWVudCcpXHJcbnZhciBzaGFkZXJzID0gcmVxdWlyZSgnLi9saWIvc2hhZGVycycpXHJcblxyXG52YXIgY3JlYXRlU2hhZGVyID0gc2hhZGVycy5jcmVhdGVTaGFkZXJcclxudmFyIGNyZWF0ZUNvbnRvdXJTaGFkZXIgPSBzaGFkZXJzLmNyZWF0ZUNvbnRvdXJTaGFkZXJcclxudmFyIGNyZWF0ZVBpY2tTaGFkZXIgPSBzaGFkZXJzLmNyZWF0ZVBpY2tTaGFkZXJcclxudmFyIGNyZWF0ZVBpY2tDb250b3VyU2hhZGVyID0gc2hhZGVycy5jcmVhdGVQaWNrQ29udG91clNoYWRlclxyXG5cclxudmFyIFNVUkZBQ0VfVkVSVEVYX1NJWkUgPSA0ICogKDQgKyAzICsgMylcclxuXHJcbnZhciBJREVOVElUWSA9IFtcclxuICAxLCAwLCAwLCAwLFxyXG4gIDAsIDEsIDAsIDAsXHJcbiAgMCwgMCwgMSwgMCxcclxuICAwLCAwLCAwLCAxIF1cclxuXHJcbnZhciBRVUFEID0gW1xyXG4gIFswLCAwXSxcclxuICBbMCwgMV0sXHJcbiAgWzEsIDBdLFxyXG4gIFsxLCAxXSxcclxuICBbMSwgMF0sXHJcbiAgWzAsIDFdXHJcbl1cclxuXHJcbnZhciBQRVJNVVRBVElPTlMgPSBbXHJcbiAgWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDBdLFxyXG4gIFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwXSxcclxuICBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF1cclxuXVxyXG5cclxuOyhmdW5jdGlvbiAoKSB7XHJcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgIHZhciBwID0gUEVSTVVUQVRJT05TW2ldXHJcbiAgICB2YXIgdSA9IChpICsgMSkgJSAzXHJcbiAgICB2YXIgdiA9IChpICsgMikgJSAzXHJcbiAgICBwW3UgKyAwXSA9IDFcclxuICAgIHBbdiArIDNdID0gMVxyXG4gICAgcFtpICsgNl0gPSAxXHJcbiAgfVxyXG59KSgpXHJcblxyXG5mdW5jdGlvbiBTdXJmYWNlUGlja1Jlc3VsdCAocG9zaXRpb24sIGluZGV4LCB1diwgbGV2ZWwsIGRhdGFDb29yZGluYXRlKSB7XHJcbiAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uXHJcbiAgdGhpcy5pbmRleCA9IGluZGV4XHJcbiAgdGhpcy51diA9IHV2XHJcbiAgdGhpcy5sZXZlbCA9IGxldmVsXHJcbiAgdGhpcy5kYXRhQ29vcmRpbmF0ZSA9IGRhdGFDb29yZGluYXRlXHJcbn1cclxuXHJcbnZhciBOX0NPTE9SUyA9IDI1NlxyXG5cclxuZnVuY3Rpb24gZ2VuQ29sb3JtYXAgKG5hbWUpIHtcclxuICB2YXIgeCA9IHBhY2soW2NvbG9ybWFwKHtcclxuICAgIGNvbG9ybWFwOiBuYW1lLFxyXG4gICAgbnNoYWRlczogTl9DT0xPUlMsXHJcbiAgICBmb3JtYXQ6ICdyZ2JhJ1xyXG4gIH0pLm1hcChmdW5jdGlvbiAoYykge1xyXG4gICAgcmV0dXJuIFtjWzBdLCBjWzFdLCBjWzJdLCAyNTUgKiBjWzNdXVxyXG4gIH0pXSlcclxuICBvcHMuZGl2c2VxKHgsIDI1NS4wKVxyXG4gIHJldHVybiB4XHJcbn1cclxuXHJcbmZ1bmN0aW9uIFN1cmZhY2VQbG90IChcclxuICBnbCxcclxuICBzaGFwZSxcclxuICBib3VuZHMsXHJcbiAgc2hhZGVyLFxyXG4gIHBpY2tTaGFkZXIsXHJcbiAgY29vcmRpbmF0ZXMsXHJcbiAgdmFvLFxyXG4gIGNvbG9yTWFwLFxyXG4gIGNvbnRvdXJTaGFkZXIsXHJcbiAgY29udG91clBpY2tTaGFkZXIsXHJcbiAgY29udG91ckJ1ZmZlcixcclxuICBjb250b3VyVkFPLFxyXG4gIGR5bmFtaWNCdWZmZXIsXHJcbiAgZHluYW1pY1ZBTykge1xyXG4gIHRoaXMuZ2wgPSBnbFxyXG4gIHRoaXMuc2hhcGUgPSBzaGFwZVxyXG4gIHRoaXMuYm91bmRzID0gYm91bmRzXHJcbiAgdGhpcy5pbnRlbnNpdHlCb3VuZHMgPSBbXTtcclxuXHJcbiAgdGhpcy5fc2hhZGVyID0gc2hhZGVyXHJcbiAgdGhpcy5fcGlja1NoYWRlciA9IHBpY2tTaGFkZXJcclxuICB0aGlzLl9jb29yZGluYXRlQnVmZmVyID0gY29vcmRpbmF0ZXNcclxuICB0aGlzLl92YW8gPSB2YW9cclxuICB0aGlzLl9jb2xvck1hcCA9IGNvbG9yTWFwXHJcblxyXG4gIHRoaXMuX2NvbnRvdXJTaGFkZXIgPSBjb250b3VyU2hhZGVyXHJcbiAgdGhpcy5fY29udG91clBpY2tTaGFkZXIgPSBjb250b3VyUGlja1NoYWRlclxyXG4gIHRoaXMuX2NvbnRvdXJCdWZmZXIgPSBjb250b3VyQnVmZmVyXHJcbiAgdGhpcy5fY29udG91clZBTyA9IGNvbnRvdXJWQU9cclxuICB0aGlzLl9jb250b3VyT2Zmc2V0cyA9IFtbXSwgW10sIFtdXVxyXG4gIHRoaXMuX2NvbnRvdXJDb3VudHMgPSBbW10sIFtdLCBbXV1cclxuICB0aGlzLl92ZXJ0ZXhDb3VudCA9IDBcclxuXHJcbiAgdGhpcy5fcGlja1Jlc3VsdCA9IG5ldyBTdXJmYWNlUGlja1Jlc3VsdChbMCwgMCwgMF0sIFswLCAwXSwgWzAsIDBdLCBbMCwgMCwgMF0sIFswLCAwLCAwXSlcclxuXHJcbiAgdGhpcy5fZHluYW1pY0J1ZmZlciA9IGR5bmFtaWNCdWZmZXJcclxuICB0aGlzLl9keW5hbWljVkFPID0gZHluYW1pY1ZBT1xyXG4gIHRoaXMuX2R5bmFtaWNPZmZzZXRzID0gWzAsIDAsIDBdXHJcbiAgdGhpcy5fZHluYW1pY0NvdW50cyA9IFswLCAwLCAwXVxyXG5cclxuICB0aGlzLmNvbnRvdXJXaWR0aCA9IFsgMSwgMSwgMSBdXHJcbiAgdGhpcy5jb250b3VyTGV2ZWxzID0gW1sxXSwgWzFdLCBbMV1dXHJcbiAgdGhpcy5jb250b3VyVGludCA9IFswLCAwLCAwXVxyXG4gIHRoaXMuY29udG91ckNvbG9yID0gW1swLjUsIDAuNSwgMC41LCAxXSwgWzAuNSwgMC41LCAwLjUsIDFdLCBbMC41LCAwLjUsIDAuNSwgMV1dXHJcblxyXG4gIHRoaXMuc2hvd0NvbnRvdXIgPSB0cnVlXHJcbiAgdGhpcy5zaG93U3VyZmFjZSA9IHRydWVcclxuXHJcbiAgdGhpcy5lbmFibGVIaWdobGlnaHQgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZV1cclxuICB0aGlzLmhpZ2hsaWdodENvbG9yID0gW1swLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV1dXHJcbiAgdGhpcy5oaWdobGlnaHRUaW50ID0gWyAxLCAxLCAxIF1cclxuICB0aGlzLmhpZ2hsaWdodExldmVsID0gWy0xLCAtMSwgLTFdXHJcblxyXG4gIC8vIER5bmFtaWMgY29udG91ciBvcHRpb25zXHJcbiAgdGhpcy5lbmFibGVEeW5hbWljID0gWyB0cnVlLCB0cnVlLCB0cnVlIF1cclxuICB0aGlzLmR5bmFtaWNMZXZlbCA9IFsgTmFOLCBOYU4sIE5hTiBdXHJcbiAgdGhpcy5keW5hbWljQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXVxyXG4gIHRoaXMuZHluYW1pY1RpbnQgPSBbIDEsIDEsIDEgXVxyXG4gIHRoaXMuZHluYW1pY1dpZHRoID0gWyAxLCAxLCAxIF1cclxuXHJcbiAgdGhpcy5heGVzQm91bmRzID0gW1tJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSwgWy1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXVxyXG4gIHRoaXMuc3VyZmFjZVByb2plY3QgPSBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXVxyXG4gIHRoaXMuY29udG91clByb2plY3QgPSBbWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF0sXHJcbiAgICBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXSxcclxuICAgIFsgZmFsc2UsIGZhbHNlLCBmYWxzZSBdXVxyXG5cclxuICB0aGlzLmNvbG9yQm91bmRzID0gWyBmYWxzZSwgZmFsc2UgXVxyXG5cclxuICAvLyBTdG9yZSB4eXogZmllbGRzLCBuZWVkIHRoaXMgZm9yIHBpY2tpbmdcclxuICB0aGlzLl9maWVsZCA9IFtcclxuICAgIG5kYXJyYXkocG9vbC5tYWxsb2NGbG9hdCgxMDI0KSwgWzAsIDBdKSxcclxuICAgIG5kYXJyYXkocG9vbC5tYWxsb2NGbG9hdCgxMDI0KSwgWzAsIDBdKSxcclxuICAgIG5kYXJyYXkocG9vbC5tYWxsb2NGbG9hdCgxMDI0KSwgWzAsIDBdKSBdXHJcblxyXG4gIHRoaXMucGlja0lkID0gMVxyXG4gIHRoaXMuY2xpcEJvdW5kcyA9IFtbLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0sIFtJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV1cclxuXHJcbiAgdGhpcy5zbmFwVG9EYXRhID0gZmFsc2VcclxuXHJcbiAgdGhpcy5vcGFjaXR5ID0gMS4wXHJcblxyXG4gIHRoaXMubGlnaHRQb3NpdGlvbiA9IFsxMCwgMTAwMDAsIDBdXHJcbiAgdGhpcy5hbWJpZW50TGlnaHQgPSAwLjhcclxuICB0aGlzLmRpZmZ1c2VMaWdodCA9IDAuOFxyXG4gIHRoaXMuc3BlY3VsYXJMaWdodCA9IDIuMFxyXG4gIHRoaXMucm91Z2huZXNzID0gMC41XHJcbiAgdGhpcy5mcmVzbmVsID0gMS41XHJcbiAgdGhpcy52ZXJ0ZXhDb2xvciA9IDA7XHJcblxyXG4gIHRoaXMuZGlydHkgPSB0cnVlXHJcbn1cclxuXHJcbnZhciBwcm90byA9IFN1cmZhY2VQbG90LnByb3RvdHlwZVxyXG5cclxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uICgpIHtcclxuICByZXR1cm4gdGhpcy5vcGFjaXR5IDwgMVxyXG59XHJcblxyXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uICgpIHtcclxuICBpZiAodGhpcy5vcGFjaXR5ID49IDEpIHtcclxuICAgIHJldHVybiB0cnVlXHJcbiAgfVxyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICBpZiAodGhpcy5fY29udG91ckNvdW50c1tpXS5sZW5ndGggPiAwIHx8IHRoaXMuX2R5bmFtaWNDb3VudHNbaV0gPiAwKSB7XHJcbiAgICAgIHJldHVybiB0cnVlXHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiBmYWxzZVxyXG59XHJcblxyXG5wcm90by5waWNrU2xvdHMgPSAxXHJcblxyXG5wcm90by5zZXRQaWNrQmFzZSA9IGZ1bmN0aW9uIChpZCkge1xyXG4gIHRoaXMucGlja0lkID0gaWRcclxufVxyXG5cclxudmFyIFpFUk9fVkVDID0gWzAsIDAsIDBdXHJcblxyXG52YXIgUFJPSkVDVF9EQVRBID0ge1xyXG4gIHNob3dTdXJmYWNlOiBmYWxzZSxcclxuICBzaG93Q29udG91cjogZmFsc2UsXHJcbiAgcHJvamVjdGlvbnM6IFtJREVOVElUWS5zbGljZSgpLCBJREVOVElUWS5zbGljZSgpLCBJREVOVElUWS5zbGljZSgpXSxcclxuICBjbGlwQm91bmRzOiBbXHJcbiAgICBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxyXG4gICAgW1swLCAwLCAwXSwgWzAsIDAsIDBdXSxcclxuICAgIFtbMCwgMCwgMF0sIFswLCAwLCAwXV1dXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNvbXB1dGVQcm9qZWN0aW9uRGF0YSAoY2FtZXJhLCBvYmopIHtcclxuICB2YXIgaSwgaiwga1xyXG5cclxuICAvLyBDb21wdXRlIGN1YmUgcHJvcGVydGllc1xyXG4gIHZhciBjdWJlQXhpcyA9IChvYmouYXhlcyAmJiBvYmouYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXMpIHx8IFpFUk9fVkVDXHJcblxyXG4gIHZhciBzaG93U3VyZmFjZSA9IG9iai5zaG93U3VyZmFjZVxyXG4gIHZhciBzaG93Q29udG91ciA9IG9iai5zaG93Q29udG91clxyXG5cclxuICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICBzaG93U3VyZmFjZSA9IHNob3dTdXJmYWNlIHx8IG9iai5zdXJmYWNlUHJvamVjdFtpXVxyXG4gICAgZm9yIChqID0gMDsgaiA8IDM7ICsraikge1xyXG4gICAgICBzaG93Q29udG91ciA9IHNob3dDb250b3VyIHx8IG9iai5jb250b3VyUHJvamVjdFtpXVtqXVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xyXG4gICAgLy8gQ29uc3RydWN0IHByb2plY3Rpb24gb250byBheGlzXHJcbiAgICB2YXIgYXhpc1NxdWlzaCA9IFBST0pFQ1RfREFUQS5wcm9qZWN0aW9uc1tpXVxyXG4gICAgZm9yIChqID0gMDsgaiA8IDE2OyArK2opIHtcclxuICAgICAgYXhpc1NxdWlzaFtqXSA9IDBcclxuICAgIH1cclxuICAgIGZvciAoaiA9IDA7IGogPCA0OyArK2opIHtcclxuICAgICAgYXhpc1NxdWlzaFs1ICogal0gPSAxXHJcbiAgICB9XHJcbiAgICBheGlzU3F1aXNoWzUgKiBpXSA9IDBcclxuICAgIGF4aXNTcXVpc2hbMTIgKyBpXSA9IG9iai5heGVzQm91bmRzWysoY3ViZUF4aXNbaV0gPiAwKV1baV1cclxuICAgIG11bHRpcGx5KGF4aXNTcXVpc2gsIGNhbWVyYS5tb2RlbCwgYXhpc1NxdWlzaClcclxuXHJcbiAgICB2YXIgbmNsaXBCb3VuZHMgPSBQUk9KRUNUX0RBVEEuY2xpcEJvdW5kc1tpXVxyXG4gICAgZm9yIChrID0gMDsgayA8IDI7ICsraykge1xyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XHJcbiAgICAgICAgbmNsaXBCb3VuZHNba11bal0gPSBjYW1lcmEuY2xpcEJvdW5kc1trXVtqXVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBuY2xpcEJvdW5kc1swXVtpXSA9IC0xZThcclxuICAgIG5jbGlwQm91bmRzWzFdW2ldID0gMWU4XHJcbiAgfVxyXG5cclxuICBQUk9KRUNUX0RBVEEuc2hvd1N1cmZhY2UgPSBzaG93U3VyZmFjZVxyXG4gIFBST0pFQ1RfREFUQS5zaG93Q29udG91ciA9IHNob3dDb250b3VyXHJcblxyXG4gIHJldHVybiBQUk9KRUNUX0RBVEFcclxufVxyXG5cclxudmFyIFVOSUZPUk1TID0ge1xyXG4gIG1vZGVsOiBJREVOVElUWSxcclxuICB2aWV3OiBJREVOVElUWSxcclxuICBwcm9qZWN0aW9uOiBJREVOVElUWSxcclxuICBpbnZlcnNlTW9kZWw6IElERU5USVRZLnNsaWNlKCksXHJcbiAgbG93ZXJCb3VuZDogWzAsIDAsIDBdLFxyXG4gIHVwcGVyQm91bmQ6IFswLCAwLCAwXSxcclxuICBjb2xvck1hcDogMCxcclxuICBjbGlwQm91bmRzOiBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxyXG4gIGhlaWdodDogMC4wLFxyXG4gIGNvbnRvdXJUaW50OiAwLFxyXG4gIGNvbnRvdXJDb2xvcjogWzAsIDAsIDAsIDFdLFxyXG4gIHBlcm11dGF0aW9uOiBbMSwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMV0sXHJcbiAgek9mZnNldDogLTFlLTQsXHJcbiAga2FtYmllbnQ6IDEsXHJcbiAga2RpZmZ1c2U6IDEsXHJcbiAga3NwZWN1bGFyOiAxLFxyXG4gIGxpZ2h0UG9zaXRpb246IFsxMDAwLCAxMDAwLCAxMDAwXSxcclxuICBleWVQb3NpdGlvbjogWzAsIDAsIDBdLFxyXG4gIHJvdWdobmVzczogMSxcclxuICBmcmVzbmVsOiAxLFxyXG4gIG9wYWNpdHk6IDEsXHJcbiAgdmVydGV4Q29sb3I6IDBcclxufVxyXG5cclxudmFyIE1BVFJJWF9JTlZFUlNFID0gSURFTlRJVFkuc2xpY2UoKVxyXG52YXIgREVGQVVMVF9QRVJNID0gWzEsIDAsIDAsIDAsIDEsIDAsIDAsIDAsIDFdXHJcblxyXG5mdW5jdGlvbiBkcmF3Q29yZSAocGFyYW1zLCB0cmFuc3BhcmVudCkge1xyXG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxyXG4gIHZhciBnbCA9IHRoaXMuZ2xcclxuXHJcbiAgZ2wuZGlzYWJsZShnbC5DVUxMX0ZBQ0UpXHJcblxyXG4gIHRoaXMuX2NvbG9yTWFwLmJpbmQoMClcclxuXHJcbiAgdmFyIHVuaWZvcm1zID0gVU5JRk9STVNcclxuICB1bmlmb3Jtcy5tb2RlbCA9IHBhcmFtcy5tb2RlbCB8fCBJREVOVElUWVxyXG4gIHVuaWZvcm1zLnZpZXcgPSBwYXJhbXMudmlldyB8fCBJREVOVElUWVxyXG4gIHVuaWZvcm1zLnByb2plY3Rpb24gPSBwYXJhbXMucHJvamVjdGlvbiB8fCBJREVOVElUWVxyXG4gIHVuaWZvcm1zLmxvd2VyQm91bmQgPSBbdGhpcy5ib3VuZHNbMF1bMF0sIHRoaXMuYm91bmRzWzBdWzFdLCB0aGlzLmNvbG9yQm91bmRzWzBdIHx8IHRoaXMuYm91bmRzWzBdWzJdXVxyXG4gIHVuaWZvcm1zLnVwcGVyQm91bmQgPSBbdGhpcy5ib3VuZHNbMV1bMF0sIHRoaXMuYm91bmRzWzFdWzFdLCB0aGlzLmNvbG9yQm91bmRzWzFdIHx8IHRoaXMuYm91bmRzWzFdWzJdXVxyXG4gIHVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuY29udG91ckNvbG9yWzBdXHJcblxyXG4gIHVuaWZvcm1zLmludmVyc2VNb2RlbCA9IGludmVydCh1bmlmb3Jtcy5pbnZlcnNlTW9kZWwsIHVuaWZvcm1zLm1vZGVsKVxyXG5cclxuICBmb3IgKHZhciBpID0gMDsgaSA8IDI7ICsraSkge1xyXG4gICAgdmFyIGNsaXBDbGFtcGVkID0gdW5pZm9ybXMuY2xpcEJvdW5kc1tpXVxyXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAzOyArK2opIHtcclxuICAgICAgY2xpcENsYW1wZWRbal0gPSBNYXRoLm1pbihNYXRoLm1heCh0aGlzLmNsaXBCb3VuZHNbaV1bal0sIC0xZTgpLCAxZTgpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB1bmlmb3Jtcy5rYW1iaWVudCA9IHRoaXMuYW1iaWVudExpZ2h0XHJcbiAgdW5pZm9ybXMua2RpZmZ1c2UgPSB0aGlzLmRpZmZ1c2VMaWdodFxyXG4gIHVuaWZvcm1zLmtzcGVjdWxhciA9IHRoaXMuc3BlY3VsYXJMaWdodFxyXG5cclxuICB1bmlmb3Jtcy5yb3VnaG5lc3MgPSB0aGlzLnJvdWdobmVzc1xyXG4gIHVuaWZvcm1zLmZyZXNuZWwgPSB0aGlzLmZyZXNuZWxcclxuICB1bmlmb3Jtcy5vcGFjaXR5ID0gdGhpcy5vcGFjaXR5XHJcblxyXG4gIHVuaWZvcm1zLmhlaWdodCA9IDAuMFxyXG4gIHVuaWZvcm1zLnBlcm11dGF0aW9uID0gREVGQVVMVF9QRVJNXHJcblxyXG4gIHVuaWZvcm1zLnZlcnRleENvbG9yID0gdGhpcy52ZXJ0ZXhDb2xvclxyXG5cclxuICAvLyBDb21wdXRlIGNhbWVyYSBtYXRyaXggaW52ZXJzZVxyXG4gIHZhciBpbnZDYW1lcmFNYXRyaXggPSBNQVRSSVhfSU5WRVJTRVxyXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMudmlldywgdW5pZm9ybXMubW9kZWwpXHJcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXHJcbiAgaW52ZXJ0KGludkNhbWVyYU1hdHJpeCwgaW52Q2FtZXJhTWF0cml4KVxyXG5cclxuICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICB1bmlmb3Jtcy5leWVQb3NpdGlvbltpXSA9IGludkNhbWVyYU1hdHJpeFsxMiArIGldIC8gaW52Q2FtZXJhTWF0cml4WzE1XVxyXG4gIH1cclxuXHJcbiAgdmFyIHcgPSBpbnZDYW1lcmFNYXRyaXhbMTVdXHJcbiAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xyXG4gICAgdyArPSB0aGlzLmxpZ2h0UG9zaXRpb25baV0gKiBpbnZDYW1lcmFNYXRyaXhbNCAqIGkgKyAzXVxyXG4gIH1cclxuICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMiArIGldXHJcbiAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XHJcbiAgICAgIHMgKz0gaW52Q2FtZXJhTWF0cml4WzQgKiBqICsgaV0gKiB0aGlzLmxpZ2h0UG9zaXRpb25bal1cclxuICAgIH1cclxuICAgIHVuaWZvcm1zLmxpZ2h0UG9zaXRpb25baV0gPSBzIC8gd1xyXG4gIH1cclxuXHJcbiAgdmFyIHByb2plY3REYXRhID0gY29tcHV0ZVByb2plY3Rpb25EYXRhKHVuaWZvcm1zLCB0aGlzKVxyXG5cclxuICBpZiAocHJvamVjdERhdGEuc2hvd1N1cmZhY2UgJiYgKHRyYW5zcGFyZW50ID09PSAodGhpcy5vcGFjaXR5IDwgMSkpKSB7XHJcbiAgICAvLyBTZXQgdXAgdW5pZm9ybXNcclxuICAgIHRoaXMuX3NoYWRlci5iaW5kKClcclxuICAgIHRoaXMuX3NoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgLy8gRHJhdyBpdFxyXG4gICAgdGhpcy5fdmFvLmJpbmQoKVxyXG5cclxuICAgIGlmICh0aGlzLnNob3dTdXJmYWNlICYmIHRoaXMuX3ZlcnRleENvdW50KSB7XHJcbiAgICAgIHRoaXMuX3Zhby5kcmF3KGdsLlRSSUFOR0xFUywgdGhpcy5fdmVydGV4Q291bnQpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gRHJhdyBwcm9qZWN0aW9ucyBvZiBzdXJmYWNlXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICAgIGlmICghdGhpcy5zdXJmYWNlUHJvamVjdFtpXSB8fCAhdGhpcy52ZXJ0ZXhDb3VudCkge1xyXG4gICAgICAgIGNvbnRpbnVlXHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5fc2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gcHJvamVjdERhdGEucHJvamVjdGlvbnNbaV1cclxuICAgICAgdGhpcy5fc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSBwcm9qZWN0RGF0YS5jbGlwQm91bmRzW2ldXHJcbiAgICAgIHRoaXMuX3Zhby5kcmF3KGdsLlRSSUFOR0xFUywgdGhpcy5fdmVydGV4Q291bnQpXHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fdmFvLnVuYmluZCgpXHJcbiAgfVxyXG5cclxuICBpZiAocHJvamVjdERhdGEuc2hvd0NvbnRvdXIgJiYgIXRyYW5zcGFyZW50KSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5fY29udG91clNoYWRlclxyXG5cclxuICAgIC8vIERvbid0IGFwcGx5IGxpZ2h0aW5nIHRvIGNvbnRvdXJzXHJcbiAgICB1bmlmb3Jtcy5rYW1iaWVudCA9IDEuMFxyXG4gICAgdW5pZm9ybXMua2RpZmZ1c2UgPSAwLjBcclxuICAgIHVuaWZvcm1zLmtzcGVjdWxhciA9IDAuMFxyXG4gICAgdW5pZm9ybXMub3BhY2l0eSA9IDEuMFxyXG5cclxuICAgIHNoYWRlci5iaW5kKClcclxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgLy8gRHJhdyBjb250b3VyIGxpbmVzXHJcbiAgICB2YXIgdmFvID0gdGhpcy5fY29udG91clZBT1xyXG4gICAgdmFvLmJpbmQoKVxyXG5cclxuICAgIC8vIERyYXcgY29udG91ciBsZXZlbHNcclxuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLnBlcm11dGF0aW9uID0gUEVSTVVUQVRJT05TW2ldXHJcbiAgICAgIGdsLmxpbmVXaWR0aCh0aGlzLmNvbnRvdXJXaWR0aFtpXSlcclxuXHJcbiAgICAgIGZvciAoaiA9IDA7IGogPCB0aGlzLmNvbnRvdXJMZXZlbHNbaV0ubGVuZ3RoOyArK2opIHtcclxuICAgICAgICBpZiAoaiA9PT0gdGhpcy5oaWdobGlnaHRMZXZlbFtpXSkge1xyXG4gICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuaGlnaGxpZ2h0Q29sb3JbaV1cclxuICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyVGludCA9IHRoaXMuaGlnaGxpZ2h0VGludFtpXVxyXG4gICAgICAgIH0gZWxzZSBpZiAoaiA9PT0gMCB8fCAoaiAtIDEpID09PSB0aGlzLmhpZ2hsaWdodExldmVsW2ldKSB7XHJcbiAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91ckNvbG9yID0gdGhpcy5jb250b3VyQ29sb3JbaV1cclxuICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyVGludCA9IHRoaXMuY29udG91clRpbnRbaV1cclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCF0aGlzLl9jb250b3VyQ291bnRzW2ldW2pdKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuaGVpZ2h0ID0gdGhpcy5jb250b3VyTGV2ZWxzW2ldW2pdXHJcbiAgICAgICAgdmFvLmRyYXcoZ2wuTElORVMsIHRoaXMuX2NvbnRvdXJDb3VudHNbaV1bal0sIHRoaXMuX2NvbnRvdXJPZmZzZXRzW2ldW2pdKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRHJhdyBwcm9qZWN0aW9ucyBvZiBzdXJmYWNlXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5tb2RlbCA9IHByb2plY3REYXRhLnByb2plY3Rpb25zW2ldXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5jbGlwQm91bmRzID0gcHJvamVjdERhdGEuY2xpcEJvdW5kc1tpXVxyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRvdXJQcm9qZWN0W2ldW2pdKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuICAgICAgICBzaGFkZXIudW5pZm9ybXMucGVybXV0YXRpb24gPSBQRVJNVVRBVElPTlNbal1cclxuICAgICAgICBnbC5saW5lV2lkdGgodGhpcy5jb250b3VyV2lkdGhbal0pXHJcbiAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmNvbnRvdXJMZXZlbHNbal0ubGVuZ3RoOyArK2spIHtcclxuICAgICAgICAgIGlmIChrID09PSB0aGlzLmhpZ2hsaWdodExldmVsW2pdKSB7XHJcbiAgICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyQ29sb3IgPSB0aGlzLmhpZ2hsaWdodENvbG9yW2pdXHJcbiAgICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyVGludCA9IHRoaXMuaGlnaGxpZ2h0VGludFtqXVxyXG4gICAgICAgICAgfSBlbHNlIGlmIChrID09PSAwIHx8IChrIC0gMSkgPT09IHRoaXMuaGlnaGxpZ2h0TGV2ZWxbal0pIHtcclxuICAgICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuY29udG91ckNvbG9yW2pdXHJcbiAgICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyVGludCA9IHRoaXMuY29udG91clRpbnRbal1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1ba11cclxuICAgICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9jb250b3VyQ291bnRzW2pdW2tdLCB0aGlzLl9jb250b3VyT2Zmc2V0c1tqXVtrXSlcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHZhby51bmJpbmQoKVxyXG5cclxuICAgIC8vIERyYXcgZHluYW1pYyBjb250b3Vyc1xyXG4gICAgdmFvID0gdGhpcy5fZHluYW1pY1ZBT1xyXG4gICAgdmFvLmJpbmQoKVxyXG5cclxuICAgIC8vIERyYXcgY29udG91ciBsZXZlbHNcclxuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgICAgaWYgKHRoaXMuX2R5bmFtaWNDb3VudHNbaV0gPT09IDApIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcblxyXG4gICAgICBzaGFkZXIudW5pZm9ybXMubW9kZWwgPSB1bmlmb3Jtcy5tb2RlbFxyXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY2xpcEJvdW5kcyA9IHVuaWZvcm1zLmNsaXBCb3VuZHNcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLnBlcm11dGF0aW9uID0gUEVSTVVUQVRJT05TW2ldXHJcbiAgICAgIGdsLmxpbmVXaWR0aCh0aGlzLmR5bmFtaWNXaWR0aFtpXSlcclxuXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyQ29sb3IgPSB0aGlzLmR5bmFtaWNDb2xvcltpXVxyXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91clRpbnQgPSB0aGlzLmR5bmFtaWNUaW50W2ldXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmR5bmFtaWNMZXZlbFtpXVxyXG4gICAgICB2YW8uZHJhdyhnbC5MSU5FUywgdGhpcy5fZHluYW1pY0NvdW50c1tpXSwgdGhpcy5fZHluYW1pY09mZnNldHNbaV0pXHJcblxyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRvdXJQcm9qZWN0W2pdW2ldKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gcHJvamVjdERhdGEucHJvamVjdGlvbnNbal1cclxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuY2xpcEJvdW5kcyA9IHByb2plY3REYXRhLmNsaXBCb3VuZHNbal1cclxuICAgICAgICB2YW8uZHJhdyhnbC5MSU5FUywgdGhpcy5fZHluYW1pY0NvdW50c1tpXSwgdGhpcy5fZHluYW1pY09mZnNldHNbaV0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB2YW8udW5iaW5kKClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmRyYXcgPSBmdW5jdGlvbiAocGFyYW1zKSB7XHJcbiAgcmV0dXJuIGRyYXdDb3JlLmNhbGwodGhpcywgcGFyYW1zLCBmYWxzZSlcclxufVxyXG5cclxucHJvdG8uZHJhd1RyYW5zcGFyZW50ID0gZnVuY3Rpb24gKHBhcmFtcykge1xyXG4gIHJldHVybiBkcmF3Q29yZS5jYWxsKHRoaXMsIHBhcmFtcywgdHJ1ZSlcclxufVxyXG5cclxudmFyIFBJQ0tfVU5JRk9STVMgPSB7XHJcbiAgbW9kZWw6IElERU5USVRZLFxyXG4gIHZpZXc6IElERU5USVRZLFxyXG4gIHByb2plY3Rpb246IElERU5USVRZLFxyXG4gIGludmVyc2VNb2RlbDogSURFTlRJVFksXHJcbiAgY2xpcEJvdW5kczogW1swLCAwLCAwXSwgWzAsIDAsIDBdXSxcclxuICBoZWlnaHQ6IDAuMCxcclxuICBzaGFwZTogWzAsIDBdLFxyXG4gIHBpY2tJZDogMCxcclxuICBsb3dlckJvdW5kOiBbMCwgMCwgMF0sXHJcbiAgdXBwZXJCb3VuZDogWzAsIDAsIDBdLFxyXG4gIHpPZmZzZXQ6IDAuMCxcclxuICBwZXJtdXRhdGlvbjogWzEsIDAsIDAsIDAsIDEsIDAsIDAsIDAsIDFdLFxyXG4gIGxpZ2h0UG9zaXRpb246IFswLCAwLCAwXSxcclxuICBleWVQb3NpdGlvbjogWzAsIDAsIDBdXHJcbn1cclxuXHJcbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24gKHBhcmFtcykge1xyXG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxyXG4gIHZhciBnbCA9IHRoaXMuZ2xcclxuICBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSlcclxuXHJcbiAgdmFyIHVuaWZvcm1zID0gUElDS19VTklGT1JNU1xyXG4gIHVuaWZvcm1zLm1vZGVsID0gcGFyYW1zLm1vZGVsIHx8IElERU5USVRZXHJcbiAgdW5pZm9ybXMudmlldyA9IHBhcmFtcy52aWV3IHx8IElERU5USVRZXHJcbiAgdW5pZm9ybXMucHJvamVjdGlvbiA9IHBhcmFtcy5wcm9qZWN0aW9uIHx8IElERU5USVRZXHJcbiAgdW5pZm9ybXMuc2hhcGUgPSB0aGlzLl9maWVsZFsyXS5zaGFwZVxyXG4gIHVuaWZvcm1zLnBpY2tJZCA9IHRoaXMucGlja0lkIC8gMjU1LjBcclxuICB1bmlmb3Jtcy5sb3dlckJvdW5kID0gdGhpcy5ib3VuZHNbMF1cclxuICB1bmlmb3Jtcy51cHBlckJvdW5kID0gdGhpcy5ib3VuZHNbMV1cclxuICB1bmlmb3Jtcy5wZXJtdXRhdGlvbiA9IERFRkFVTFRfUEVSTVxyXG5cclxuICBmb3IgKHZhciBpID0gMDsgaSA8IDI7ICsraSkge1xyXG4gICAgdmFyIGNsaXBDbGFtcGVkID0gdW5pZm9ybXMuY2xpcEJvdW5kc1tpXVxyXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAzOyArK2opIHtcclxuICAgICAgY2xpcENsYW1wZWRbal0gPSBNYXRoLm1pbihNYXRoLm1heCh0aGlzLmNsaXBCb3VuZHNbaV1bal0sIC0xZTgpLCAxZTgpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgcHJvamVjdERhdGEgPSBjb21wdXRlUHJvamVjdGlvbkRhdGEodW5pZm9ybXMsIHRoaXMpXHJcblxyXG4gIGlmIChwcm9qZWN0RGF0YS5zaG93U3VyZmFjZSkge1xyXG4gICAgLy8gU2V0IHVwIHVuaWZvcm1zXHJcbiAgICB0aGlzLl9waWNrU2hhZGVyLmJpbmQoKVxyXG4gICAgdGhpcy5fcGlja1NoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXHJcblxyXG4gICAgLy8gRHJhdyBpdFxyXG4gICAgdGhpcy5fdmFvLmJpbmQoKVxyXG4gICAgdGhpcy5fdmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCB0aGlzLl92ZXJ0ZXhDb3VudClcclxuXHJcbiAgICAvLyBEcmF3IHByb2plY3Rpb25zIG9mIHN1cmZhY2VcclxuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgICAgaWYgKCF0aGlzLnN1cmZhY2VQcm9qZWN0W2ldKSB7XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG4gICAgICB0aGlzLl9waWNrU2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gcHJvamVjdERhdGEucHJvamVjdGlvbnNbaV1cclxuICAgICAgdGhpcy5fcGlja1NoYWRlci51bmlmb3Jtcy5jbGlwQm91bmRzID0gcHJvamVjdERhdGEuY2xpcEJvdW5kc1tpXVxyXG4gICAgICB0aGlzLl92YW8uZHJhdyhnbC5UUklBTkdMRVMsIHRoaXMuX3ZlcnRleENvdW50KVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3Zhby51bmJpbmQoKVxyXG4gIH1cclxuXHJcbiAgaWYgKHByb2plY3REYXRhLnNob3dDb250b3VyKSB7XHJcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5fY29udG91clBpY2tTaGFkZXJcclxuXHJcbiAgICBzaGFkZXIuYmluZCgpXHJcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xyXG5cclxuICAgIHZhciB2YW8gPSB0aGlzLl9jb250b3VyVkFPXHJcbiAgICB2YW8uYmluZCgpXHJcblxyXG4gICAgZm9yIChqID0gMDsgaiA8IDM7ICsraikge1xyXG4gICAgICBnbC5saW5lV2lkdGgodGhpcy5jb250b3VyV2lkdGhbal0pXHJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5wZXJtdXRhdGlvbiA9IFBFUk1VVEFUSU9OU1tqXVxyXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb250b3VyTGV2ZWxzW2pdLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2NvbnRvdXJDb3VudHNbal1baV0pIHtcclxuICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1baV1cclxuICAgICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9jb250b3VyQ291bnRzW2pdW2ldLCB0aGlzLl9jb250b3VyT2Zmc2V0c1tqXVtpXSlcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBEcmF3IHByb2plY3Rpb25zIG9mIHN1cmZhY2VcclxuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gcHJvamVjdERhdGEucHJvamVjdGlvbnNbaV1cclxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSBwcm9qZWN0RGF0YS5jbGlwQm91bmRzW2ldXHJcblxyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRvdXJQcm9qZWN0W2ldW2pdKSB7XHJcbiAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLnBlcm11dGF0aW9uID0gUEVSTVVUQVRJT05TW2pdXHJcbiAgICAgICAgZ2wubGluZVdpZHRoKHRoaXMuY29udG91cldpZHRoW2pdKVxyXG4gICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGhpcy5jb250b3VyTGV2ZWxzW2pdLmxlbmd0aDsgKytrKSB7XHJcbiAgICAgICAgICBpZiAodGhpcy5fY29udG91ckNvdW50c1tqXVtrXSkge1xyXG4gICAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuaGVpZ2h0ID0gdGhpcy5jb250b3VyTGV2ZWxzW2pdW2tdXHJcbiAgICAgICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9jb250b3VyQ291bnRzW2pdW2tdLCB0aGlzLl9jb250b3VyT2Zmc2V0c1tqXVtrXSlcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB2YW8udW5iaW5kKClcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLnBpY2sgPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XHJcbiAgaWYgKCFzZWxlY3Rpb24pIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG5cclxuICBpZiAoc2VsZWN0aW9uLmlkICE9PSB0aGlzLnBpY2tJZCkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcblxyXG4gIHZhciBzaGFwZSA9IHRoaXMuX2ZpZWxkWzJdLnNoYXBlXHJcblxyXG4gIHZhciByZXN1bHQgPSB0aGlzLl9waWNrUmVzdWx0XHJcblxyXG4gIC8vIENvbXB1dGUgdXYgY29vcmRpbmF0ZVxyXG4gIHZhciB4ID0gc2hhcGVbMF0gKiAoc2VsZWN0aW9uLnZhbHVlWzBdICsgKHNlbGVjdGlvbi52YWx1ZVsyXSA+PiA0KSAvIDE2LjApIC8gMjU1LjBcclxuICB2YXIgaXggPSBNYXRoLmZsb29yKHgpXHJcbiAgdmFyIGZ4ID0geCAtIGl4XHJcblxyXG4gIHZhciB5ID0gc2hhcGVbMV0gKiAoc2VsZWN0aW9uLnZhbHVlWzFdICsgKHNlbGVjdGlvbi52YWx1ZVsyXSAmIDE1KSAvIDE2LjApIC8gMjU1LjBcclxuICB2YXIgaXkgPSBNYXRoLmZsb29yKHkpXHJcbiAgdmFyIGZ5ID0geSAtIGl5XHJcblxyXG4gIGl4ICs9IDFcclxuICBpeSArPSAxXHJcblxyXG4gIC8vIENvbXB1dGUgeHl6IGNvb3JkaW5hdGVcclxuICB2YXIgcG9zID0gcmVzdWx0LnBvc2l0aW9uXHJcbiAgcG9zWzBdID0gcG9zWzFdID0gcG9zWzJdID0gMFxyXG4gIGZvciAodmFyIGR4ID0gMDsgZHggPCAyOyArK2R4KSB7XHJcbiAgICB2YXIgcyA9IGR4ID8gZnggOiAxLjAgLSBmeFxyXG4gICAgZm9yICh2YXIgZHkgPSAwOyBkeSA8IDI7ICsrZHkpIHtcclxuICAgICAgdmFyIHQgPSBkeSA/IGZ5IDogMS4wIC0gZnlcclxuXHJcbiAgICAgIHZhciByID0gaXggKyBkeFxyXG4gICAgICB2YXIgYyA9IGl5ICsgZHlcclxuICAgICAgdmFyIHcgPSBzICogdFxyXG5cclxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgICAgICBwb3NbaV0gKz0gdGhpcy5fZmllbGRbaV0uZ2V0KHIsIGMpICogd1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBGaW5kIGNsb3Nlc3QgbGV2ZWxcclxuICB2YXIgbGV2ZWxJbmRleCA9IHRoaXMuX3BpY2tSZXN1bHQubGV2ZWxcclxuICBmb3IgKHZhciBqID0gMDsgaiA8IDM7ICsraikge1xyXG4gICAgbGV2ZWxJbmRleFtqXSA9IGJzZWFyY2gubGUodGhpcy5jb250b3VyTGV2ZWxzW2pdLCBwb3Nbal0pXHJcbiAgICBpZiAobGV2ZWxJbmRleFtqXSA8IDApIHtcclxuICAgICAgaWYgKHRoaXMuY29udG91ckxldmVsc1tqXS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgbGV2ZWxJbmRleFtqXSA9IDBcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmIChsZXZlbEluZGV4W2pdIDwgdGhpcy5jb250b3VyTGV2ZWxzW2pdLmxlbmd0aCAtIDEpIHtcclxuICAgICAgdmFyIGEgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1bbGV2ZWxJbmRleFtqXV1cclxuICAgICAgdmFyIGIgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1bbGV2ZWxJbmRleFtqXSArIDFdXHJcbiAgICAgIGlmIChNYXRoLmFicyhhIC0gcG9zW2pdKSA+IE1hdGguYWJzKGIgLSBwb3Nbal0pKSB7XHJcbiAgICAgICAgbGV2ZWxJbmRleFtqXSArPSAxXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJlc3VsdC5pbmRleFswXSA9IGZ4IDwgMC41ID8gaXggOiAoaXggKyAxKVxyXG4gIHJlc3VsdC5pbmRleFsxXSA9IGZ5IDwgMC41ID8gaXkgOiAoaXkgKyAxKVxyXG5cclxuICByZXN1bHQudXZbMF0gPSB4IC8gc2hhcGVbMF1cclxuICByZXN1bHQudXZbMV0gPSB5IC8gc2hhcGVbMV1cclxuXHJcbiAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xyXG4gICAgcmVzdWx0LmRhdGFDb29yZGluYXRlW2ldID0gdGhpcy5fZmllbGRbaV0uZ2V0KHJlc3VsdC5pbmRleFswXSwgcmVzdWx0LmluZGV4WzFdKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5mdW5jdGlvbiBwYWRGaWVsZCAobmZpZWxkLCBmaWVsZCkge1xyXG4gIHZhciBzaGFwZSA9IGZpZWxkLnNoYXBlLnNsaWNlKClcclxuICB2YXIgbnNoYXBlID0gbmZpZWxkLnNoYXBlLnNsaWNlKClcclxuXHJcbiAgLy8gQ2VudGVyXHJcbiAgb3BzLmFzc2lnbihuZmllbGQubG8oMSwgMSkuaGkoc2hhcGVbMF0sIHNoYXBlWzFdKSwgZmllbGQpXHJcblxyXG4gIC8vIEVkZ2VzXHJcbiAgb3BzLmFzc2lnbihuZmllbGQubG8oMSkuaGkoc2hhcGVbMF0sIDEpLFxyXG4gICAgZmllbGQuaGkoc2hhcGVbMF0sIDEpKVxyXG4gIG9wcy5hc3NpZ24obmZpZWxkLmxvKDEsIG5zaGFwZVsxXSAtIDEpLmhpKHNoYXBlWzBdLCAxKSxcclxuICAgIGZpZWxkLmxvKDAsIHNoYXBlWzFdIC0gMSkuaGkoc2hhcGVbMF0sIDEpKVxyXG4gIG9wcy5hc3NpZ24obmZpZWxkLmxvKDAsIDEpLmhpKDEsIHNoYXBlWzFdKSxcclxuICAgIGZpZWxkLmhpKDEpKVxyXG4gIG9wcy5hc3NpZ24obmZpZWxkLmxvKG5zaGFwZVswXSAtIDEsIDEpLmhpKDEsIHNoYXBlWzFdKSxcclxuICAgIGZpZWxkLmxvKHNoYXBlWzBdIC0gMSkpXHJcbiAgLy8gQ29ybmVyc1xyXG4gIG5maWVsZC5zZXQoMCwgMCwgZmllbGQuZ2V0KDAsIDApKVxyXG4gIG5maWVsZC5zZXQoMCwgbnNoYXBlWzFdIC0gMSwgZmllbGQuZ2V0KDAsIHNoYXBlWzFdIC0gMSkpXHJcbiAgbmZpZWxkLnNldChuc2hhcGVbMF0gLSAxLCAwLCBmaWVsZC5nZXQoc2hhcGVbMF0gLSAxLCAwKSlcclxuICBuZmllbGQuc2V0KG5zaGFwZVswXSAtIDEsIG5zaGFwZVsxXSAtIDEsIGZpZWxkLmdldChzaGFwZVswXSAtIDEsIHNoYXBlWzFdIC0gMSkpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGhhbmRsZUFycmF5IChwYXJhbSwgY3Rvcikge1xyXG4gIGlmIChBcnJheS5pc0FycmF5KHBhcmFtKSkge1xyXG4gICAgcmV0dXJuIFsgY3RvcihwYXJhbVswXSksIGN0b3IocGFyYW1bMV0pLCBjdG9yKHBhcmFtWzJdKSBdXHJcbiAgfVxyXG4gIHJldHVybiBbIGN0b3IocGFyYW0pLCBjdG9yKHBhcmFtKSwgY3RvcihwYXJhbSkgXVxyXG59XHJcblxyXG5mdW5jdGlvbiB0b0NvbG9yICh4KSB7XHJcbiAgaWYgKEFycmF5LmlzQXJyYXkoeCkpIHtcclxuICAgIGlmICh4Lmxlbmd0aCA9PT0gMykge1xyXG4gICAgICByZXR1cm4gW3hbMF0sIHhbMV0sIHhbMl0sIDFdXHJcbiAgICB9XHJcbiAgICByZXR1cm4gW3hbMF0sIHhbMV0sIHhbMl0sIHhbM11dXHJcbiAgfVxyXG4gIHJldHVybiBbMCwgMCwgMCwgMV1cclxufVxyXG5cclxuZnVuY3Rpb24gaGFuZGxlQ29sb3IgKHBhcmFtKSB7XHJcbiAgaWYgKEFycmF5LmlzQXJyYXkocGFyYW0pKSB7XHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbSkpIHtcclxuICAgICAgcmV0dXJuIFtcclxuICAgICAgICB0b0NvbG9yKHBhcmFtWzBdKSxcclxuICAgICAgICB0b0NvbG9yKHBhcmFtWzFdKSxcclxuICAgICAgICB0b0NvbG9yKHBhcmFtWzJdKSBdXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB2YXIgYyA9IHRvQ29sb3IocGFyYW0pXHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgYy5zbGljZSgpLFxyXG4gICAgICAgIGMuc2xpY2UoKSxcclxuICAgICAgICBjLnNsaWNlKCkgXVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24gKHBhcmFtcykge1xyXG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxyXG5cclxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxyXG5cclxuICBpZiAoJ2NvbnRvdXJXaWR0aCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmNvbnRvdXJXaWR0aCA9IGhhbmRsZUFycmF5KHBhcmFtcy5jb250b3VyV2lkdGgsIE51bWJlcilcclxuICB9XHJcbiAgaWYgKCdzaG93Q29udG91cicgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLnNob3dDb250b3VyID0gaGFuZGxlQXJyYXkocGFyYW1zLnNob3dDb250b3VyLCBCb29sZWFuKVxyXG4gIH1cclxuICBpZiAoJ3Nob3dTdXJmYWNlJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuc2hvd1N1cmZhY2UgPSAhIXBhcmFtcy5zaG93U3VyZmFjZVxyXG4gIH1cclxuICBpZiAoJ2NvbnRvdXJUaW50JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuY29udG91clRpbnQgPSBoYW5kbGVBcnJheShwYXJhbXMuY29udG91clRpbnQsIEJvb2xlYW4pXHJcbiAgfVxyXG4gIGlmICgnY29udG91ckNvbG9yJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMuY29udG91ckNvbG9yID0gaGFuZGxlQ29sb3IocGFyYW1zLmNvbnRvdXJDb2xvcilcclxuICB9XHJcbiAgaWYgKCdjb250b3VyUHJvamVjdCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmNvbnRvdXJQcm9qZWN0ID0gaGFuZGxlQXJyYXkocGFyYW1zLmNvbnRvdXJQcm9qZWN0LCBmdW5jdGlvbiAoeCkge1xyXG4gICAgICByZXR1cm4gaGFuZGxlQXJyYXkoeCwgQm9vbGVhbilcclxuICAgIH0pXHJcbiAgfVxyXG4gIGlmICgnc3VyZmFjZVByb2plY3QnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5zdXJmYWNlUHJvamVjdCA9IHBhcmFtcy5zdXJmYWNlUHJvamVjdFxyXG4gIH1cclxuICBpZiAoJ2R5bmFtaWNDb2xvcicgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmR5bmFtaWNDb2xvciA9IGhhbmRsZUNvbG9yKHBhcmFtcy5keW5hbWljQ29sb3IpXHJcbiAgfVxyXG4gIGlmICgnZHluYW1pY1RpbnQnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5keW5hbWljVGludCA9IGhhbmRsZUFycmF5KHBhcmFtcy5keW5hbWljVGludCwgTnVtYmVyKVxyXG4gIH1cclxuICBpZiAoJ2R5bmFtaWNXaWR0aCcgaW4gcGFyYW1zKSB7XHJcbiAgICB0aGlzLmR5bmFtaWNXaWR0aCA9IGhhbmRsZUFycmF5KHBhcmFtcy5keW5hbWljV2lkdGgsIE51bWJlcilcclxuICB9XHJcbiAgaWYgKCdvcGFjaXR5JyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMub3BhY2l0eSA9IHBhcmFtcy5vcGFjaXR5XHJcbiAgfVxyXG4gIGlmICgnY29sb3JCb3VuZHMnIGluIHBhcmFtcykge1xyXG4gICAgdGhpcy5jb2xvckJvdW5kcyA9IHBhcmFtcy5jb2xvckJvdW5kc1xyXG4gIH1cclxuICBpZiAoJ3ZlcnRleENvbG9yJyBpbiBwYXJhbXMpIHtcclxuICAgIHRoaXMudmVydGV4Q29sb3IgPSBwYXJhbXMudmVydGV4Q29sb3IgPyAxIDogMDtcclxuICB9XHJcblxyXG4gIHZhciBmaWVsZCA9IHBhcmFtcy5maWVsZCB8fCAocGFyYW1zLmNvb3JkcyAmJiBwYXJhbXMuY29vcmRzWzJdKSB8fCBudWxsXHJcbiAgdmFyIGxldmVsc0NoYW5nZWQgPSBmYWxzZVxyXG5cclxuICBpZiAoIWZpZWxkKSB7XHJcbiAgICBpZiAodGhpcy5fZmllbGRbMl0uc2hhcGVbMF0gfHwgdGhpcy5fZmllbGRbMl0uc2hhcGVbMl0pIHtcclxuICAgICAgZmllbGQgPSB0aGlzLl9maWVsZFsyXS5sbygxLCAxKS5oaSh0aGlzLl9maWVsZFsyXS5zaGFwZVswXSAtIDIsIHRoaXMuX2ZpZWxkWzJdLnNoYXBlWzFdIC0gMilcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGZpZWxkID0gdGhpcy5fZmllbGRbMl0uaGkoMCwgMClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIFVwZGF0ZSBmaWVsZFxyXG4gIGlmICgnZmllbGQnIGluIHBhcmFtcyB8fCAnY29vcmRzJyBpbiBwYXJhbXMpIHtcclxuICAgIHZhciBmc2l6ZSA9IChmaWVsZC5zaGFwZVswXSArIDIpICogKGZpZWxkLnNoYXBlWzFdICsgMilcclxuXHJcbiAgICAvLyBSZXNpemUgaWYgbmVjZXNzYXJ5XHJcbiAgICBpZiAoZnNpemUgPiB0aGlzLl9maWVsZFsyXS5kYXRhLmxlbmd0aCkge1xyXG4gICAgICBwb29sLmZyZWVGbG9hdCh0aGlzLl9maWVsZFsyXS5kYXRhKVxyXG4gICAgICB0aGlzLl9maWVsZFsyXS5kYXRhID0gcG9vbC5tYWxsb2NGbG9hdChiaXRzLm5leHRQb3cyKGZzaXplKSlcclxuICAgIH1cclxuXHJcbiAgICAvLyBQYWQgZmllbGRcclxuICAgIHRoaXMuX2ZpZWxkWzJdID0gbmRhcnJheSh0aGlzLl9maWVsZFsyXS5kYXRhLCBbZmllbGQuc2hhcGVbMF0gKyAyLCBmaWVsZC5zaGFwZVsxXSArIDJdKVxyXG4gICAgcGFkRmllbGQodGhpcy5fZmllbGRbMl0sIGZpZWxkKVxyXG5cclxuICAgIC8vIFNhdmUgc2hhcGUgb2YgZmllbGRcclxuICAgIHRoaXMuc2hhcGUgPSBmaWVsZC5zaGFwZS5zbGljZSgpXHJcbiAgICB2YXIgc2hhcGUgPSB0aGlzLnNoYXBlXHJcblxyXG4gICAgLy8gUmVzaXplIGNvb3JkaW5hdGUgZmllbGRzIGlmIG5lY2Vzc2FyeVxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAyOyArK2kpIHtcclxuICAgICAgaWYgKHRoaXMuX2ZpZWxkWzJdLnNpemUgPiB0aGlzLl9maWVsZFtpXS5kYXRhLmxlbmd0aCkge1xyXG4gICAgICAgIHBvb2wuZnJlZUZsb2F0KHRoaXMuX2ZpZWxkW2ldLmRhdGEpXHJcbiAgICAgICAgdGhpcy5fZmllbGRbaV0uZGF0YSA9IHBvb2wubWFsbG9jRmxvYXQodGhpcy5fZmllbGRbMl0uc2l6ZSlcclxuICAgICAgfVxyXG4gICAgICB0aGlzLl9maWVsZFtpXSA9IG5kYXJyYXkodGhpcy5fZmllbGRbaV0uZGF0YSwgW3NoYXBlWzBdICsgMiwgc2hhcGVbMV0gKyAyXSlcclxuICAgIH1cclxuXHJcbiAgICAvLyBHZW5lcmF0ZSB4L3kgY29vcmRpbmF0ZXNcclxuICAgIGlmIChwYXJhbXMuY29vcmRzKSB7XHJcbiAgICAgIHZhciBjb29yZHMgPSBwYXJhbXMuY29vcmRzXHJcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb29yZHMpIHx8IGNvb3Jkcy5sZW5ndGggIT09IDMpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXN1cmZhY2U6IGludmFsaWQgY29vcmRpbmF0ZXMgZm9yIHgveScpXHJcbiAgICAgIH1cclxuICAgICAgZm9yIChpID0gMDsgaSA8IDI7ICsraSkge1xyXG4gICAgICAgIHZhciBjb29yZCA9IGNvb3Jkc1tpXVxyXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCAyOyArK2opIHtcclxuICAgICAgICAgIGlmIChjb29yZC5zaGFwZVtqXSAhPT0gc2hhcGVbal0pIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1zdXJmYWNlOiBjb29yZHMgaGF2ZSBpbmNvcnJlY3Qgc2hhcGUnKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBwYWRGaWVsZCh0aGlzLl9maWVsZFtpXSwgY29vcmQpXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAocGFyYW1zLnRpY2tzKSB7XHJcbiAgICAgIHZhciB0aWNrcyA9IHBhcmFtcy50aWNrc1xyXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGlja3MpIHx8IHRpY2tzLmxlbmd0aCAhPT0gMikge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtc3VyZmFjZTogaW52YWxpZCB0aWNrcycpXHJcbiAgICAgIH1cclxuICAgICAgZm9yIChpID0gMDsgaSA8IDI7ICsraSkge1xyXG4gICAgICAgIHZhciB0aWNrID0gdGlja3NbaV1cclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aWNrKSB8fCB0aWNrLmxlbmd0aCkge1xyXG4gICAgICAgICAgdGljayA9IG5kYXJyYXkodGljaylcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHRpY2suc2hhcGVbMF0gIT09IHNoYXBlW2ldKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXN1cmZhY2U6IGludmFsaWQgdGljayBsZW5ndGgnKVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBNYWtlIGEgY29weSB2aWV3IG9mIHRoZSB0aWNrIGFycmF5XHJcbiAgICAgICAgdmFyIHRpY2syID0gbmRhcnJheSh0aWNrLmRhdGEsIHNoYXBlKVxyXG4gICAgICAgIHRpY2syLnN0cmlkZVtpXSA9IHRpY2suc3RyaWRlWzBdXHJcbiAgICAgICAgdGljazIuc3RyaWRlW2kgXiAxXSA9IDBcclxuXHJcbiAgICAgICAgLy8gRmlsbCBpbiBmaWVsZCBhcnJheVxyXG4gICAgICAgIHBhZEZpZWxkKHRoaXMuX2ZpZWxkW2ldLCB0aWNrMilcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZm9yIChpID0gMDsgaSA8IDI7ICsraSkge1xyXG4gICAgICAgIHZhciBvZmZzZXQgPSBbMCwgMF1cclxuICAgICAgICBvZmZzZXRbaV0gPSAxXHJcbiAgICAgICAgdGhpcy5fZmllbGRbaV0gPSBuZGFycmF5KHRoaXMuX2ZpZWxkW2ldLmRhdGEsIFtzaGFwZVswXSArIDIsIHNoYXBlWzFdICsgMl0sIG9mZnNldCwgMClcclxuICAgICAgfVxyXG4gICAgICB0aGlzLl9maWVsZFswXS5zZXQoMCwgMCwgMClcclxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzaGFwZVswXTsgKytqKSB7XHJcbiAgICAgICAgdGhpcy5fZmllbGRbMF0uc2V0KGogKyAxLCAwLCBqKVxyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuX2ZpZWxkWzBdLnNldChzaGFwZVswXSArIDEsIDAsIHNoYXBlWzBdIC0gMSlcclxuICAgICAgdGhpcy5fZmllbGRbMV0uc2V0KDAsIDAsIDApXHJcbiAgICAgIGZvciAoaiA9IDA7IGogPCBzaGFwZVsxXTsgKytqKSB7XHJcbiAgICAgICAgdGhpcy5fZmllbGRbMV0uc2V0KDAsIGogKyAxLCBqKVxyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuX2ZpZWxkWzFdLnNldCgwLCBzaGFwZVsxXSArIDEsIHNoYXBlWzFdIC0gMSlcclxuICAgIH1cclxuXHJcbiAgICAvLyBTYXZlIHNoYXBlXHJcbiAgICB2YXIgZmllbGRzID0gdGhpcy5fZmllbGRcclxuXHJcbiAgICAvLyBDb21wdXRlIHN1cmZhY2Ugbm9ybWFsc1xyXG4gICAgdmFyIGRmaWVsZHMgPSBuZGFycmF5KHBvb2wubWFsbG9jRmxvYXQoZmllbGRzWzJdLnNpemUgKiAzICogMiksIFszLCBzaGFwZVswXSArIDIsIHNoYXBlWzFdICsgMiwgMl0pXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICAgIGdyYWRpZW50KGRmaWVsZHMucGljayhpKSwgZmllbGRzW2ldLCAnbWlycm9yJylcclxuICAgIH1cclxuICAgIHZhciBub3JtYWxzID0gbmRhcnJheShwb29sLm1hbGxvY0Zsb2F0KGZpZWxkc1syXS5zaXplICogMyksIFtzaGFwZVswXSArIDIsIHNoYXBlWzFdICsgMiwgM10pXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgc2hhcGVbMF0gKyAyOyArK2kpIHtcclxuICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlWzFdICsgMjsgKytqKSB7XHJcbiAgICAgICAgdmFyIGR4ZHUgPSBkZmllbGRzLmdldCgwLCBpLCBqLCAwKVxyXG4gICAgICAgIHZhciBkeGR2ID0gZGZpZWxkcy5nZXQoMCwgaSwgaiwgMSlcclxuICAgICAgICB2YXIgZHlkdSA9IGRmaWVsZHMuZ2V0KDEsIGksIGosIDApXHJcbiAgICAgICAgdmFyIGR5ZHYgPSBkZmllbGRzLmdldCgxLCBpLCBqLCAxKVxyXG4gICAgICAgIHZhciBkemR1ID0gZGZpZWxkcy5nZXQoMiwgaSwgaiwgMClcclxuICAgICAgICB2YXIgZHpkdiA9IGRmaWVsZHMuZ2V0KDIsIGksIGosIDEpXHJcblxyXG4gICAgICAgIHZhciBueCA9IGR5ZHUgKiBkemR2IC0gZHlkdiAqIGR6ZHVcclxuICAgICAgICB2YXIgbnkgPSBkemR1ICogZHhkdiAtIGR6ZHYgKiBkeGR1XHJcbiAgICAgICAgdmFyIG56ID0gZHhkdSAqIGR5ZHYgLSBkeGR2ICogZHlkdVxyXG5cclxuICAgICAgICB2YXIgbmwgPSBNYXRoLnNxcnQobnggKiBueCArIG55ICogbnkgKyBueiAqIG56KVxyXG4gICAgICAgIGlmIChubCA8IDFlLTgpIHtcclxuICAgICAgICAgIG5sID0gTWF0aC5tYXgoTWF0aC5hYnMobngpLCBNYXRoLmFicyhueSksIE1hdGguYWJzKG56KSlcclxuICAgICAgICAgIGlmIChubCA8IDFlLTgpIHtcclxuICAgICAgICAgICAgbnogPSAxLjBcclxuICAgICAgICAgICAgbnkgPSBueCA9IDAuMFxyXG4gICAgICAgICAgICBubCA9IDEuMFxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbmwgPSAxLjAgLyBubFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBubCA9IDEuMCAvIE1hdGguc3FydChubClcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIG5vcm1hbHMuc2V0KGksIGosIDAsIG54ICogbmwpXHJcbiAgICAgICAgbm9ybWFscy5zZXQoaSwgaiwgMSwgbnkgKiBubClcclxuICAgICAgICBub3JtYWxzLnNldChpLCBqLCAyLCBueiAqIG5sKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBwb29sLmZyZWUoZGZpZWxkcy5kYXRhKVxyXG5cclxuICAgIC8vIEluaXRpYWxpemUgc3VyZmFjZVxyXG4gICAgdmFyIGxvID0gWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5IF1cclxuICAgIHZhciBoaSA9IFsgLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eSBdXHJcbiAgICB2YXIgbG9faW50ZW5zaXR5ID0gSW5maW5pdHlcclxuICAgIHZhciBoaV9pbnRlbnNpdHkgPSAtSW5maW5pdHlcclxuICAgIHZhciBjb3VudCA9IChzaGFwZVswXSAtIDEpICogKHNoYXBlWzFdIC0gMSkgKiA2XHJcbiAgICB2YXIgdHZlcnRzID0gcG9vbC5tYWxsb2NGbG9hdChiaXRzLm5leHRQb3cyKDEwICogY291bnQpKVxyXG4gICAgdmFyIHRwdHIgPSAwXHJcbiAgICB2YXIgdmVydGV4Q291bnQgPSAwXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgc2hhcGVbMF0gLSAxOyArK2kpIHtcclxuICAgICAgal9sb29wOlxyXG4gICAgICBmb3IgKGogPSAwOyBqIDwgc2hhcGVbMV0gLSAxOyArK2opIHtcclxuICAgICAgICAvLyBUZXN0IGZvciBOYU5zXHJcbiAgICAgICAgZm9yICh2YXIgZHggPSAwOyBkeCA8IDI7ICsrZHgpIHtcclxuICAgICAgICAgIGZvciAodmFyIGR5ID0gMDsgZHkgPCAyOyArK2R5KSB7XHJcbiAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgMzsgKytrKSB7XHJcbiAgICAgICAgICAgICAgdmFyIGYgPSB0aGlzLl9maWVsZFtrXS5nZXQoMSArIGkgKyBkeCwgMSArIGogKyBkeSlcclxuICAgICAgICAgICAgICBpZiAoaXNOYU4oZikgfHwgIWlzRmluaXRlKGYpKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZSBqX2xvb3BcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChrID0gMDsgayA8IDY7ICsraykge1xyXG4gICAgICAgICAgdmFyIHIgPSBpICsgUVVBRFtrXVswXVxyXG4gICAgICAgICAgdmFyIGMgPSBqICsgUVVBRFtrXVsxXVxyXG5cclxuICAgICAgICAgIHZhciB0eCA9IHRoaXMuX2ZpZWxkWzBdLmdldChyICsgMSwgYyArIDEpXHJcbiAgICAgICAgICB2YXIgdHkgPSB0aGlzLl9maWVsZFsxXS5nZXQociArIDEsIGMgKyAxKVxyXG4gICAgICAgICAgZiA9IHRoaXMuX2ZpZWxkWzJdLmdldChyICsgMSwgYyArIDEpXHJcbiAgICAgICAgICB2YXIgdmYgPSBmXHJcbiAgICAgICAgICBueCA9IG5vcm1hbHMuZ2V0KHIgKyAxLCBjICsgMSwgMClcclxuICAgICAgICAgIG55ID0gbm9ybWFscy5nZXQociArIDEsIGMgKyAxLCAxKVxyXG4gICAgICAgICAgbnogPSBub3JtYWxzLmdldChyICsgMSwgYyArIDEsIDIpXHJcblxyXG4gICAgICAgICAgaWYgKHBhcmFtcy5pbnRlbnNpdHkpIHtcclxuICAgICAgICAgICAgdmYgPSBwYXJhbXMuaW50ZW5zaXR5LmdldChyLCBjKVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gclxyXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBjXHJcbiAgICAgICAgICB0dmVydHNbdHB0cisrXSA9IHR4XHJcbiAgICAgICAgICB0dmVydHNbdHB0cisrXSA9IHR5XHJcbiAgICAgICAgICB0dmVydHNbdHB0cisrXSA9IGZcclxuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gMFxyXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSB2ZlxyXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBueFxyXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBueVxyXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBuelxyXG5cclxuICAgICAgICAgIGxvWzBdID0gTWF0aC5taW4obG9bMF0sIHR4KVxyXG4gICAgICAgICAgbG9bMV0gPSBNYXRoLm1pbihsb1sxXSwgdHkpXHJcbiAgICAgICAgICBsb1syXSA9IE1hdGgubWluKGxvWzJdLCBmKVxyXG4gICAgICAgICAgbG9faW50ZW5zaXR5ID0gTWF0aC5taW4obG9faW50ZW5zaXR5LCB2ZilcclxuXHJcbiAgICAgICAgICBoaVswXSA9IE1hdGgubWF4KGhpWzBdLCB0eClcclxuICAgICAgICAgIGhpWzFdID0gTWF0aC5tYXgoaGlbMV0sIHR5KVxyXG4gICAgICAgICAgaGlbMl0gPSBNYXRoLm1heChoaVsyXSwgZilcclxuICAgICAgICAgIGhpX2ludGVuc2l0eSA9IE1hdGgubWF4KGhpX2ludGVuc2l0eSwgdmYpXHJcblxyXG4gICAgICAgICAgdmVydGV4Q291bnQgKz0gMVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChwYXJhbXMuaW50ZW5zaXR5Qm91bmRzKSB7XHJcbiAgICAgIGxvX2ludGVuc2l0eSA9ICtwYXJhbXMuaW50ZW5zaXR5Qm91bmRzWzBdXHJcbiAgICAgIGhpX2ludGVuc2l0eSA9ICtwYXJhbXMuaW50ZW5zaXR5Qm91bmRzWzFdXHJcbiAgICB9XHJcblxyXG4gICAgLy8gU2NhbGUgYWxsIHZlcnRleCBpbnRlbnNpdGllc1xyXG4gICAgZm9yIChpID0gNjsgaSA8IHRwdHI7IGkgKz0gMTApIHtcclxuICAgICAgdHZlcnRzW2ldID0gKHR2ZXJ0c1tpXSAtIGxvX2ludGVuc2l0eSkgLyAoaGlfaW50ZW5zaXR5IC0gbG9faW50ZW5zaXR5KVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3ZlcnRleENvdW50ID0gdmVydGV4Q291bnRcclxuICAgIHRoaXMuX2Nvb3JkaW5hdGVCdWZmZXIudXBkYXRlKHR2ZXJ0cy5zdWJhcnJheSgwLCB0cHRyKSlcclxuICAgIHBvb2wuZnJlZUZsb2F0KHR2ZXJ0cylcclxuICAgIHBvb2wuZnJlZShub3JtYWxzLmRhdGEpXHJcblxyXG4gICAgLy8gVXBkYXRlIGJvdW5kc1xyXG4gICAgdGhpcy5ib3VuZHMgPSBbbG8sIGhpXVxyXG5cclxuICAgIC8vIFNhdmUgaW50ZW5zaXR5XHJcbiAgICB0aGlzLmludGVuc2l0eSA9IHBhcmFtcy5pbnRlbnNpdHkgfHwgdGhpcy5fZmllbGRbMl1cclxuXHJcbiAgICBpZih0aGlzLmludGVuc2l0eUJvdW5kc1swXSAhPT0gbG9faW50ZW5zaXR5IHx8IHRoaXMuaW50ZW5zaXR5Qm91bmRzWzFdICE9PSBoaV9pbnRlbnNpdHkpIHtcclxuICAgICAgICBsZXZlbHNDaGFuZ2VkID0gdHJ1ZVxyXG4gICAgfVxyXG5cclxuICAgIC8vIFNhdmUgaW50ZW5zaXR5IGJvdW5kXHJcbiAgICB0aGlzLmludGVuc2l0eUJvdW5kcyA9IFtsb19pbnRlbnNpdHksIGhpX2ludGVuc2l0eV1cclxuICB9XHJcblxyXG4gIC8vIFVwZGF0ZSBsZXZlbCBjcm9zc2luZ3NcclxuICBpZiAoJ2xldmVscycgaW4gcGFyYW1zKSB7XHJcbiAgICB2YXIgbGV2ZWxzID0gcGFyYW1zLmxldmVsc1xyXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxldmVsc1swXSkpIHtcclxuICAgICAgbGV2ZWxzID0gWyBbXSwgW10sIGxldmVscyBdXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsZXZlbHMgPSBsZXZlbHMuc2xpY2UoKVxyXG4gICAgfVxyXG4gICAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xyXG4gICAgICBsZXZlbHNbaV0gPSBsZXZlbHNbaV0uc2xpY2UoKVxyXG4gICAgICBsZXZlbHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xyXG4gICAgICAgIHJldHVybiBhIC0gYlxyXG4gICAgICB9KVxyXG4gICAgfVxyXG4gICAgY2hhbmdlX3Rlc3Q6XHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICAgIGlmIChsZXZlbHNbaV0ubGVuZ3RoICE9PSB0aGlzLmNvbnRvdXJMZXZlbHNbaV0ubGVuZ3RoKSB7XHJcbiAgICAgICAgbGV2ZWxzQ2hhbmdlZCA9IHRydWVcclxuICAgICAgICBicmVha1xyXG4gICAgICB9XHJcbiAgICAgIGZvciAoaiA9IDA7IGogPCBsZXZlbHNbaV0ubGVuZ3RoOyArK2opIHtcclxuICAgICAgICBpZiAobGV2ZWxzW2ldW2pdICE9PSB0aGlzLmNvbnRvdXJMZXZlbHNbaV1bal0pIHtcclxuICAgICAgICAgIGxldmVsc0NoYW5nZWQgPSB0cnVlXHJcbiAgICAgICAgICBicmVhayBjaGFuZ2VfdGVzdFxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5jb250b3VyTGV2ZWxzID0gbGV2ZWxzXHJcbiAgfVxyXG5cclxuICBpZiAobGV2ZWxzQ2hhbmdlZCkge1xyXG4gICAgZmllbGRzID0gdGhpcy5fZmllbGRcclxuICAgIHNoYXBlID0gdGhpcy5zaGFwZVxyXG5cclxuICAgIC8vIFVwZGF0ZSBjb250b3VyIGxpbmVzXHJcbiAgICB2YXIgY29udG91clZlcnRzID0gW11cclxuXHJcbiAgICBmb3IgKHZhciBkaW0gPSAwOyBkaW0gPCAzOyArK2RpbSkge1xyXG4gICAgICBsZXZlbHMgPSB0aGlzLmNvbnRvdXJMZXZlbHNbZGltXVxyXG4gICAgICB2YXIgbGV2ZWxPZmZzZXRzID0gW11cclxuICAgICAgdmFyIGxldmVsQ291bnRzID0gW11cclxuXHJcbiAgICAgIHZhciBwYXJ0cyA9IFswLCAwLCAwXVxyXG5cclxuICAgICAgZm9yIChpID0gMDsgaSA8IGxldmVscy5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgIHZhciBncmFwaCA9IHN1cmZhY2VOZXRzKHRoaXMuX2ZpZWxkW2RpbV0sIGxldmVsc1tpXSlcclxuICAgICAgICBsZXZlbE9mZnNldHMucHVzaCgoY29udG91clZlcnRzLmxlbmd0aCAvIDUpIHwgMClcclxuICAgICAgICB2ZXJ0ZXhDb3VudCA9IDBcclxuXHJcbiAgICAgICAgZWRnZV9sb29wOlxyXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBncmFwaC5jZWxscy5sZW5ndGg7ICsraikge1xyXG4gICAgICAgICAgdmFyIGUgPSBncmFwaC5jZWxsc1tqXVxyXG4gICAgICAgICAgZm9yIChrID0gMDsgayA8IDI7ICsraykge1xyXG4gICAgICAgICAgICB2YXIgcCA9IGdyYXBoLnBvc2l0aW9uc1tlW2tdXVxyXG5cclxuICAgICAgICAgICAgdmFyIHggPSBwWzBdXHJcbiAgICAgICAgICAgIHZhciBpeCA9IE1hdGguZmxvb3IoeCkgfCAwXHJcbiAgICAgICAgICAgIHZhciBmeCA9IHggLSBpeFxyXG5cclxuICAgICAgICAgICAgdmFyIHkgPSBwWzFdXHJcbiAgICAgICAgICAgIHZhciBpeSA9IE1hdGguZmxvb3IoeSkgfCAwXHJcbiAgICAgICAgICAgIHZhciBmeSA9IHkgLSBpeVxyXG5cclxuICAgICAgICAgICAgdmFyIGhvbGUgPSBmYWxzZVxyXG4gICAgICAgICAgICBkZF9sb29wOlxyXG4gICAgICAgICAgICBmb3IgKHZhciBkZCA9IDA7IGRkIDwgMzsgKytkZCkge1xyXG4gICAgICAgICAgICAgIHBhcnRzW2RkXSA9IDAuMFxyXG4gICAgICAgICAgICAgIHZhciBpdSA9IChkaW0gKyBkZCArIDEpICUgM1xyXG4gICAgICAgICAgICAgIGZvciAoZHggPSAwOyBkeCA8IDI7ICsrZHgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBzID0gZHggPyBmeCA6IDEuMCAtIGZ4XHJcbiAgICAgICAgICAgICAgICByID0gTWF0aC5taW4oTWF0aC5tYXgoaXggKyBkeCwgMCksIHNoYXBlWzBdKSB8IDBcclxuICAgICAgICAgICAgICAgIGZvciAoZHkgPSAwOyBkeSA8IDI7ICsrZHkpIHtcclxuICAgICAgICAgICAgICAgICAgdmFyIHQgPSBkeSA/IGZ5IDogMS4wIC0gZnlcclxuICAgICAgICAgICAgICAgICAgYyA9IE1hdGgubWluKE1hdGgubWF4KGl5ICsgZHksIDApLCBzaGFwZVsxXSkgfCAwXHJcblxyXG4gICAgICAgICAgICAgICAgICBpZiAoZGQgPCAyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZiA9IHRoaXMuX2ZpZWxkW2l1XS5nZXQociwgYylcclxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBmID0gKHRoaXMuaW50ZW5zaXR5LmdldChyLCBjKSAtIHRoaXMuaW50ZW5zaXR5Qm91bmRzWzBdKSAvICh0aGlzLmludGVuc2l0eUJvdW5kc1sxXSAtIHRoaXMuaW50ZW5zaXR5Qm91bmRzWzBdKVxyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIGlmICghaXNGaW5pdGUoZikgfHwgaXNOYU4oZikpIHtcclxuICAgICAgICAgICAgICAgICAgICBob2xlID0gdHJ1ZVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrIGRkX2xvb3BcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgdmFyIHcgPSBzICogdFxyXG4gICAgICAgICAgICAgICAgICBwYXJ0c1tkZF0gKz0gdyAqIGZcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghaG9sZSkge1xyXG4gICAgICAgICAgICAgIGNvbnRvdXJWZXJ0cy5wdXNoKHBhcnRzWzBdLCBwYXJ0c1sxXSwgcFswXSwgcFsxXSwgcGFydHNbMl0pXHJcbiAgICAgICAgICAgICAgdmVydGV4Q291bnQgKz0gMVxyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGlmIChrID4gMCkge1xyXG4gICAgICAgICAgICAgICAgLy8gSWYgd2UgYWxyZWFkeSBhZGRlZCBmaXJzdCBlZGdlLCBwb3Agb2ZmIHZlcnRzXHJcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBsID0gMDsgbCA8IDU7ICsrbCkge1xyXG4gICAgICAgICAgICAgICAgICBjb250b3VyVmVydHMucG9wKClcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHZlcnRleENvdW50IC09IDFcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY29udGludWUgZWRnZV9sb29wXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgbGV2ZWxDb3VudHMucHVzaCh2ZXJ0ZXhDb3VudClcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gU3RvcmUgcmVzdWx0c1xyXG4gICAgICB0aGlzLl9jb250b3VyT2Zmc2V0c1tkaW1dID0gbGV2ZWxPZmZzZXRzXHJcbiAgICAgIHRoaXMuX2NvbnRvdXJDb3VudHNbZGltXSA9IGxldmVsQ291bnRzXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGZsb2F0QnVmZmVyID0gcG9vbC5tYWxsb2NGbG9hdChjb250b3VyVmVydHMubGVuZ3RoKVxyXG4gICAgZm9yIChpID0gMDsgaSA8IGNvbnRvdXJWZXJ0cy5sZW5ndGg7ICsraSkge1xyXG4gICAgICBmbG9hdEJ1ZmZlcltpXSA9IGNvbnRvdXJWZXJ0c1tpXVxyXG4gICAgfVxyXG4gICAgdGhpcy5fY29udG91ckJ1ZmZlci51cGRhdGUoZmxvYXRCdWZmZXIpXHJcbiAgICBwb29sLmZyZWVGbG9hdChmbG9hdEJ1ZmZlcilcclxuICB9XHJcblxyXG4gIGlmIChwYXJhbXMuY29sb3JtYXApIHtcclxuICAgIHRoaXMuX2NvbG9yTWFwLnNldFBpeGVscyhnZW5Db2xvcm1hcChwYXJhbXMuY29sb3JtYXApKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcclxuICB0aGlzLl9zaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5fdmFvLmRpc3Bvc2UoKVxyXG4gIHRoaXMuX2Nvb3JkaW5hdGVCdWZmZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5fY29sb3JNYXAuZGlzcG9zZSgpXHJcbiAgdGhpcy5fY29udG91ckJ1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLl9jb250b3VyVkFPLmRpc3Bvc2UoKVxyXG4gIHRoaXMuX2NvbnRvdXJTaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5fY29udG91clBpY2tTaGFkZXIuZGlzcG9zZSgpXHJcbiAgdGhpcy5fZHluYW1pY0J1ZmZlci5kaXNwb3NlKClcclxuICB0aGlzLl9keW5hbWljVkFPLmRpc3Bvc2UoKVxyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XHJcbiAgICBwb29sLmZyZWVGbG9hdCh0aGlzLl9maWVsZFtpXS5kYXRhKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8uaGlnaGxpZ2h0ID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xyXG4gIGlmICghc2VsZWN0aW9uKSB7XHJcbiAgICB0aGlzLl9keW5hbWljQ291bnRzID0gWzAsIDAsIDBdXHJcbiAgICB0aGlzLmR5YW5hbWljTGV2ZWwgPSBbTmFOLCBOYU4sIE5hTl1cclxuICAgIHRoaXMuaGlnaGxpZ2h0TGV2ZWwgPSBbLTEsIC0xLCAtMV1cclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcclxuICAgIGlmICh0aGlzLmVuYWJsZUhpZ2hsaWdodFtpXSkge1xyXG4gICAgICB0aGlzLmhpZ2hsaWdodExldmVsW2ldID0gc2VsZWN0aW9uLmxldmVsW2ldXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmhpZ2hsaWdodExldmVsW2ldID0gLTFcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHZhciBsZXZlbHNcclxuICBpZiAodGhpcy5zbmFwVG9EYXRhKSB7XHJcbiAgICBsZXZlbHMgPSBzZWxlY3Rpb24uZGF0YUNvb3JkaW5hdGVcclxuICB9IGVsc2Uge1xyXG4gICAgbGV2ZWxzID0gc2VsZWN0aW9uLnBvc2l0aW9uXHJcbiAgfVxyXG4gIGlmICgoIXRoaXMuZW5hYmxlRHluYW1pY1swXSB8fCBsZXZlbHNbMF0gPT09IHRoaXMuZHluYW1pY0xldmVsWzBdKSAmJlxyXG4gICAgKCF0aGlzLmVuYWJsZUR5bmFtaWNbMV0gfHwgbGV2ZWxzWzFdID09PSB0aGlzLmR5bmFtaWNMZXZlbFsxXSkgJiZcclxuICAgICghdGhpcy5lbmFibGVEeW5hbWljWzJdIHx8IGxldmVsc1syXSA9PT0gdGhpcy5keW5hbWljTGV2ZWxbMl0pKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIHZhciB2ZXJ0ZXhDb3VudCA9IDBcclxuICB2YXIgc2hhcGUgPSB0aGlzLnNoYXBlXHJcbiAgdmFyIHNjcmF0Y2hCdWZmZXIgPSBwb29sLm1hbGxvY0Zsb2F0KDEyICogc2hhcGVbMF0gKiBzaGFwZVsxXSlcclxuXHJcbiAgZm9yICh2YXIgZCA9IDA7IGQgPCAzOyArK2QpIHtcclxuICAgIGlmICghdGhpcy5lbmFibGVEeW5hbWljW2RdKSB7XHJcbiAgICAgIHRoaXMuZHluYW1pY0xldmVsW2RdID0gTmFOXHJcbiAgICAgIHRoaXMuX2R5bmFtaWNDb3VudHNbZF0gPSAwXHJcbiAgICAgIGNvbnRpbnVlXHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5keW5hbWljTGV2ZWxbZF0gPSBsZXZlbHNbZF1cclxuXHJcbiAgICB2YXIgdSA9IChkICsgMSkgJSAzXHJcbiAgICB2YXIgdiA9IChkICsgMikgJSAzXHJcblxyXG4gICAgdmFyIGYgPSB0aGlzLl9maWVsZFtkXVxyXG4gICAgdmFyIGcgPSB0aGlzLl9maWVsZFt1XVxyXG4gICAgdmFyIGggPSB0aGlzLl9maWVsZFt2XVxyXG4gICAgdmFyIGludGVuc2l0eSA9IHRoaXMuaW50ZW5zaXR5XHJcblxyXG4gICAgdmFyIGdyYXBoID0gc3VyZmFjZU5ldHMoZiwgbGV2ZWxzW2RdKVxyXG4gICAgdmFyIGVkZ2VzID0gZ3JhcGguY2VsbHNcclxuICAgIHZhciBwb3NpdGlvbnMgPSBncmFwaC5wb3NpdGlvbnNcclxuXHJcbiAgICB0aGlzLl9keW5hbWljT2Zmc2V0c1tkXSA9IHZlcnRleENvdW50XHJcblxyXG4gICAgZm9yIChpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgIHZhciBlID0gZWRnZXNbaV1cclxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCAyOyArK2opIHtcclxuICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1tlW2pdXVxyXG5cclxuICAgICAgICB2YXIgeCA9ICtwWzBdXHJcbiAgICAgICAgdmFyIGl4ID0geCB8IDBcclxuICAgICAgICB2YXIganggPSBNYXRoLm1pbihpeCArIDEsIHNoYXBlWzBdKSB8IDBcclxuICAgICAgICB2YXIgZnggPSB4IC0gaXhcclxuICAgICAgICB2YXIgaHggPSAxLjAgLSBmeFxyXG5cclxuICAgICAgICB2YXIgeSA9ICtwWzFdXHJcbiAgICAgICAgdmFyIGl5ID0geSB8IDBcclxuICAgICAgICB2YXIgankgPSBNYXRoLm1pbihpeSArIDEsIHNoYXBlWzFdKSB8IDBcclxuICAgICAgICB2YXIgZnkgPSB5IC0gaXlcclxuICAgICAgICB2YXIgaHkgPSAxLjAgLSBmeVxyXG5cclxuICAgICAgICB2YXIgdzAwID0gaHggKiBoeVxyXG4gICAgICAgIHZhciB3MDEgPSBoeCAqIGZ5XHJcbiAgICAgICAgdmFyIHcxMCA9IGZ4ICogaHlcclxuICAgICAgICB2YXIgdzExID0gZnggKiBmeVxyXG5cclxuICAgICAgICB2YXIgY3UgPSB3MDAgKiBnLmdldChpeCwgaXkpICtcclxuICAgICAgICAgIHcwMSAqIGcuZ2V0KGl4LCBqeSkgK1xyXG4gICAgICAgICAgdzEwICogZy5nZXQoangsIGl5KSArXHJcbiAgICAgICAgICB3MTEgKiBnLmdldChqeCwgankpXHJcblxyXG4gICAgICAgIHZhciBjdiA9IHcwMCAqIGguZ2V0KGl4LCBpeSkgK1xyXG4gICAgICAgICAgdzAxICogaC5nZXQoaXgsIGp5KSArXHJcbiAgICAgICAgICB3MTAgKiBoLmdldChqeCwgaXkpICtcclxuICAgICAgICAgIHcxMSAqIGguZ2V0KGp4LCBqeSlcclxuXHJcbiAgICAgICAgaWYgKGlzTmFOKGN1KSB8fCBpc05hTihjdikpIHtcclxuICAgICAgICAgIGlmIChqKSB7XHJcbiAgICAgICAgICAgIHZlcnRleENvdW50IC09IDFcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzY3JhdGNoQnVmZmVyWzIgKiB2ZXJ0ZXhDb3VudCArIDBdID0gY3VcclxuICAgICAgICBzY3JhdGNoQnVmZmVyWzIgKiB2ZXJ0ZXhDb3VudCArIDFdID0gY3ZcclxuXHJcbiAgICAgICAgdmVydGV4Q291bnQgKz0gMVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fZHluYW1pY0NvdW50c1tkXSA9IHZlcnRleENvdW50IC0gdGhpcy5fZHluYW1pY09mZnNldHNbZF1cclxuICB9XHJcblxyXG4gIHRoaXMuX2R5bmFtaWNCdWZmZXIudXBkYXRlKHNjcmF0Y2hCdWZmZXIuc3ViYXJyYXkoMCwgMiAqIHZlcnRleENvdW50KSlcclxuICBwb29sLmZyZWVGbG9hdChzY3JhdGNoQnVmZmVyKVxyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVTdXJmYWNlUGxvdCAocGFyYW1zKSB7XHJcbiAgdmFyIGdsID0gcGFyYW1zLmdsXHJcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcclxuICB2YXIgcGlja1NoYWRlciA9IGNyZWF0ZVBpY2tTaGFkZXIoZ2wpXHJcbiAgdmFyIGNvbnRvdXJTaGFkZXIgPSBjcmVhdGVDb250b3VyU2hhZGVyKGdsKVxyXG4gIHZhciBjb250b3VyUGlja1NoYWRlciA9IGNyZWF0ZVBpY2tDb250b3VyU2hhZGVyKGdsKVxyXG5cclxuICB2YXIgY29vcmRpbmF0ZUJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgdmFvID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7IGJ1ZmZlcjogY29vcmRpbmF0ZUJ1ZmZlcixcclxuICAgICAgc2l6ZTogNCxcclxuICAgICAgc3RyaWRlOiBTVVJGQUNFX1ZFUlRFWF9TSVpFLFxyXG4gICAgICBvZmZzZXQ6IDBcclxuICAgIH0sXHJcbiAgICB7IGJ1ZmZlcjogY29vcmRpbmF0ZUJ1ZmZlcixcclxuICAgICAgc2l6ZTogMyxcclxuICAgICAgc3RyaWRlOiBTVVJGQUNFX1ZFUlRFWF9TSVpFLFxyXG4gICAgICBvZmZzZXQ6IDE2XHJcbiAgICB9LFxyXG4gICAge1xyXG4gICAgICBidWZmZXI6IGNvb3JkaW5hdGVCdWZmZXIsXHJcbiAgICAgIHNpemU6IDMsXHJcbiAgICAgIHN0cmlkZTogU1VSRkFDRV9WRVJURVhfU0laRSxcclxuICAgICAgb2Zmc2V0OiAyOFxyXG4gICAgfVxyXG4gIF0pXHJcblxyXG4gIHZhciBjb250b3VyQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxyXG4gIHZhciBjb250b3VyVkFPID0gY3JlYXRlVkFPKGdsLCBbXHJcbiAgICB7XHJcbiAgICAgIGJ1ZmZlcjogY29udG91ckJ1ZmZlcixcclxuICAgICAgc2l6ZTogNCxcclxuICAgICAgc3RyaWRlOiAyMCxcclxuICAgICAgb2Zmc2V0OiAwXHJcbiAgICB9LFxyXG4gICAge1xyXG4gICAgICBidWZmZXI6IGNvbnRvdXJCdWZmZXIsXHJcbiAgICAgIHNpemU6IDEsXHJcbiAgICAgIHN0cmlkZTogMjAsXHJcbiAgICAgIG9mZnNldDogMTZcclxuICAgIH1cclxuICBdKVxyXG5cclxuICB2YXIgZHluYW1pY0J1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcclxuICB2YXIgZHluYW1pY1ZBTyA9IGNyZWF0ZVZBTyhnbCwgW1xyXG4gICAge1xyXG4gICAgICBidWZmZXI6IGR5bmFtaWNCdWZmZXIsXHJcbiAgICAgIHNpemU6IDIsXHJcbiAgICAgIHR5cGU6IGdsLkZMT0FUXHJcbiAgICB9XSlcclxuXHJcbiAgdmFyIGNtYXAgPSBjcmVhdGVUZXh0dXJlKGdsLCAxLCBOX0NPTE9SUywgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSlcclxuICBjbWFwLm1pbkZpbHRlciA9IGdsLkxJTkVBUlxyXG4gIGNtYXAubWFnRmlsdGVyID0gZ2wuTElORUFSXHJcblxyXG4gIHZhciBzdXJmYWNlID0gbmV3IFN1cmZhY2VQbG90KFxyXG4gICAgZ2wsXHJcbiAgICBbMCwgMF0sXHJcbiAgICBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxyXG4gICAgc2hhZGVyLFxyXG4gICAgcGlja1NoYWRlcixcclxuICAgIGNvb3JkaW5hdGVCdWZmZXIsXHJcbiAgICB2YW8sXHJcbiAgICBjbWFwLFxyXG4gICAgY29udG91clNoYWRlcixcclxuICAgIGNvbnRvdXJQaWNrU2hhZGVyLFxyXG4gICAgY29udG91ckJ1ZmZlcixcclxuICAgIGNvbnRvdXJWQU8sXHJcbiAgICBkeW5hbWljQnVmZmVyLFxyXG4gICAgZHluYW1pY1ZBT1xyXG4gIClcclxuXHJcbiAgdmFyIG5wYXJhbXMgPSB7XHJcbiAgICBsZXZlbHM6IFtbXSwgW10sIFtdXVxyXG4gIH1cclxuICBmb3IgKHZhciBpZCBpbiBwYXJhbXMpIHtcclxuICAgIG5wYXJhbXNbaWRdID0gcGFyYW1zW2lkXVxyXG4gIH1cclxuICBucGFyYW1zLmNvbG9ybWFwID0gbnBhcmFtcy5jb2xvcm1hcCB8fCAnamV0J1xyXG5cclxuICBzdXJmYWNlLnVwZGF0ZShucGFyYW1zKVxyXG5cclxuICByZXR1cm4gc3VyZmFjZVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIEZvbnQgPSByZXF1aXJlKCdjc3MtZm9udCcpXHJcbnZhciBwaWNrID0gcmVxdWlyZSgncGljay1ieS1hbGlhcycpXHJcbnZhciBjcmVhdGVSZWdsID0gcmVxdWlyZSgncmVnbCcpXHJcbnZhciBjcmVhdGVHbCA9IHJlcXVpcmUoJ2dsLXV0aWwvY29udGV4dCcpXHJcbnZhciBXZWFrTWFwID0gcmVxdWlyZSgnZXM2LXdlYWstbWFwJylcclxudmFyIHJnYmEgPSByZXF1aXJlKCdjb2xvci1ub3JtYWxpemUnKVxyXG52YXIgZm9udEF0bGFzID0gcmVxdWlyZSgnZm9udC1hdGxhcycpXHJcbnZhciBwb29sID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcclxudmFyIHBhcnNlUmVjdCA9IHJlcXVpcmUoJ3BhcnNlLXJlY3QnKVxyXG52YXIgaXNPYmogPSByZXF1aXJlKCdpcy1wbGFpbi1vYmonKVxyXG52YXIgcGFyc2VVbml0ID0gcmVxdWlyZSgncGFyc2UtdW5pdCcpXHJcbnZhciBweCA9IHJlcXVpcmUoJ3RvLXB4JylcclxudmFyIGtlcm5pbmcgPSByZXF1aXJlKCdkZXRlY3Qta2VybmluZycpXHJcbnZhciBleHRlbmQgPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJylcclxudmFyIG1ldHJpY3MgPSByZXF1aXJlKCdmb250LW1lYXN1cmUnKVxyXG52YXIgZmxhdHRlbiA9IHJlcXVpcmUoJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKVxyXG52YXIgcmVmID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKTtcbnZhciBuZXh0UG93MiA9IHJlZi5uZXh0UG93MjtcclxuXHJcbnZhciBzaGFkZXJDYWNoZSA9IG5ldyBXZWFrTWFwXHJcblxyXG5cclxuLy8gU2FmYXJpIGRvZXMgbm90IHN1cHBvcnQgZm9udC1zdHJldGNoXHJcbnZhciBpc1N0cmV0Y2hTdXBwb3J0ZWQgPSBmYWxzZVxyXG5pZiAoZG9jdW1lbnQuYm9keSkge1xyXG4gICAgdmFyIGVsID0gZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSlcclxuICAgIGVsLnN0eWxlLmZvbnQgPSAnaXRhbGljIHNtYWxsLWNhcHMgYm9sZCBjb25kZW5zZWQgMTZweC8yIGN1cnNpdmUnXHJcbiAgICBpZiAoZ2V0Q29tcHV0ZWRTdHlsZShlbCkuZm9udFN0cmV0Y2gpIHtcclxuICAgICAgICBpc1N0cmV0Y2hTdXBwb3J0ZWQgPSB0cnVlXHJcbiAgICB9XHJcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGVsKVxyXG59XHJcblxyXG52YXIgR2xUZXh0ID0gZnVuY3Rpb24gR2xUZXh0IChvKSB7XHJcblx0aWYgKGlzUmVnbChvKSkge1xyXG5cdFx0byA9IHtyZWdsOiBvfVxyXG5cdFx0dGhpcy5nbCA9IG8ucmVnbC5fZ2xcclxuXHR9XHJcblx0ZWxzZSB7XHJcblx0XHR0aGlzLmdsID0gY3JlYXRlR2wobylcclxuXHR9XHJcblxyXG5cdHRoaXMuc2hhZGVyID0gc2hhZGVyQ2FjaGUuZ2V0KHRoaXMuZ2wpXHJcblxyXG5cdGlmICghdGhpcy5zaGFkZXIpIHtcclxuXHRcdHRoaXMucmVnbCA9IG8ucmVnbCB8fCBjcmVhdGVSZWdsKHsgZ2w6IHRoaXMuZ2wgfSlcclxuXHR9XHJcblx0ZWxzZSB7XHJcblx0XHR0aGlzLnJlZ2wgPSB0aGlzLnNoYWRlci5yZWdsXHJcblx0fVxyXG5cclxuXHR0aGlzLmNoYXJCdWZmZXIgPSB0aGlzLnJlZ2wuYnVmZmVyKHsgdHlwZTogJ3VpbnQ4JywgdXNhZ2U6ICdzdHJlYW0nIH0pXHJcblx0dGhpcy5zaXplQnVmZmVyID0gdGhpcy5yZWdsLmJ1ZmZlcih7IHR5cGU6ICdmbG9hdCcsIHVzYWdlOiAnc3RyZWFtJyB9KVxyXG5cclxuXHRpZiAoIXRoaXMuc2hhZGVyKSB7XHJcblx0XHR0aGlzLnNoYWRlciA9IHRoaXMuY3JlYXRlU2hhZGVyKClcclxuXHRcdHNoYWRlckNhY2hlLnNldCh0aGlzLmdsLCB0aGlzLnNoYWRlcilcclxuXHR9XHJcblxyXG5cdHRoaXMuYmF0Y2ggPSBbXVxyXG5cclxuXHQvLyBtdWx0aXBsZSBvcHRpb25zIGluaXRpYWwgc3RhdGVcclxuXHR0aGlzLmZvbnRTaXplID0gW11cclxuXHR0aGlzLmZvbnQgPSBbXVxyXG5cdHRoaXMuZm9udEF0bGFzID0gW11cclxuXHJcblx0dGhpcy5kcmF3ID0gdGhpcy5zaGFkZXIuZHJhdy5iaW5kKHRoaXMpXHJcblx0dGhpcy5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBGSVhNRTogYWRkIFNhZmFyaSByZWdsIHJlcG9ydCBoZXJlOlxyXG5cdFx0Ly8gY2hhckJ1ZmZlciBhbmQgd2lkdGgganVzdCBkbyBub3QgdHJpZ2dlclxyXG5cdFx0dGhpcy5yZWdsLl9yZWZyZXNoKClcclxuXHRcdHRoaXMuZHJhdyh0aGlzLmJhdGNoKVxyXG5cdH1cclxuXHR0aGlzLmNhbnZhcyA9IHRoaXMuZ2wuY2FudmFzXHJcblxyXG5cdHRoaXMudXBkYXRlKGlzT2JqKG8pID8gbyA6IHt9KVxyXG59O1xyXG5cclxuR2xUZXh0LnByb3RvdHlwZS5jcmVhdGVTaGFkZXIgPSBmdW5jdGlvbiBjcmVhdGVTaGFkZXIgKCkge1xyXG5cdHZhciByZWdsID0gdGhpcy5yZWdsXHJcblxyXG5cdC8vIEZJWE1FOiBzdG9yZSAyIHNoYWRlciB2ZXJzaW9uczogd2l0aCBub3JtYWwgdmlld3BvcnQgYW5kIHdpdGhvdXRcclxuXHQvLyBkcmF3IHRleHR1cmUgbWV0aG9kXHJcblx0dmFyIGRyYXcgPSByZWdsKHtcclxuXHRcdGJsZW5kOiB7XHJcblx0XHRcdGVuYWJsZTogdHJ1ZSxcclxuXHRcdFx0Y29sb3I6IFswLDAsMCwxXSxcclxuXHJcblx0XHRcdGZ1bmM6IHtcclxuXHRcdFx0XHRzcmNSR0I6ICdzcmMgYWxwaGEnLFxyXG5cdFx0XHRcdGRzdFJHQjogJ29uZSBtaW51cyBzcmMgYWxwaGEnLFxyXG5cdFx0XHRcdHNyY0FscGhhOiAnb25lIG1pbnVzIGRzdCBhbHBoYScsXHJcblx0XHRcdFx0ZHN0QWxwaGE6ICdvbmUnXHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHRzdGVuY2lsOiB7ZW5hYmxlOiBmYWxzZX0sXHJcblx0XHRkZXB0aDoge2VuYWJsZTogZmFsc2V9LFxyXG5cclxuXHRcdGNvdW50OiByZWdsLnByb3AoJ2NvdW50JyksXHJcblx0XHRvZmZzZXQ6IHJlZ2wucHJvcCgnb2Zmc2V0JyksXHJcblx0XHRhdHRyaWJ1dGVzOiB7XHJcblx0XHRcdGNoYXJPZmZzZXQ6IHtcclxuXHRcdFx0XHRvZmZzZXQ6IDQsXHJcblx0XHRcdFx0c3RyaWRlOiA4LFxyXG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC50aGlzKCdzaXplQnVmZmVyJylcclxuXHRcdFx0fSxcclxuXHRcdFx0d2lkdGg6IHtcclxuXHRcdFx0XHRvZmZzZXQ6IDAsXHJcblx0XHRcdFx0c3RyaWRlOiA4LFxyXG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC50aGlzKCdzaXplQnVmZmVyJylcclxuXHRcdFx0fSxcclxuXHRcdFx0Y2hhcjogcmVnbC50aGlzKCdjaGFyQnVmZmVyJyksXHJcblx0XHRcdHBvc2l0aW9uOiByZWdsLnRoaXMoJ3Bvc2l0aW9uJylcclxuXHRcdH0sXHJcblx0XHR1bmlmb3Jtczoge1xyXG5cdFx0XHRhdGxhc1NpemU6IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBbcC5hdGxhcy53aWR0aCwgcC5hdGxhcy5oZWlnaHRdOyB9LFxyXG5cdFx0XHRhdGxhc0RpbTogZnVuY3Rpb24gKGMsIHApIHsgcmV0dXJuIFtwLmF0bGFzLmNvbHMsIHAuYXRsYXMucm93c107IH0sXHJcblx0XHRcdGF0bGFzOiBmdW5jdGlvbiAoYywgcCkgeyByZXR1cm4gcC5hdGxhcy50ZXh0dXJlOyB9LFxyXG5cdFx0XHRjaGFyU3RlcDogZnVuY3Rpb24gKGMsIHApIHsgcmV0dXJuIHAuYXRsYXMuc3RlcDsgfSxcclxuXHRcdFx0ZW06IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBwLmF0bGFzLmVtOyB9LFxyXG5cdFx0XHRjb2xvcjogcmVnbC5wcm9wKCdjb2xvcicpLFxyXG5cdFx0XHRvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcclxuXHRcdFx0dmlld3BvcnQ6IHJlZ2wudGhpcygndmlld3BvcnRBcnJheScpLFxyXG5cdFx0XHRzY2FsZTogcmVnbC50aGlzKCdzY2FsZScpLFxyXG5cdFx0XHRhbGlnbjogcmVnbC5wcm9wKCdhbGlnbicpLFxyXG5cdFx0XHRiYXNlbGluZTogcmVnbC5wcm9wKCdiYXNlbGluZScpLFxyXG5cdFx0XHR0cmFuc2xhdGU6IHJlZ2wudGhpcygndHJhbnNsYXRlJyksXHJcblx0XHRcdHBvc2l0aW9uT2Zmc2V0OiByZWdsLnByb3AoJ3Bvc2l0aW9uT2Zmc2V0JylcclxuXHRcdH0sXHJcblx0XHRwcmltaXRpdmU6ICdwb2ludHMnLFxyXG5cdFx0dmlld3BvcnQ6IHJlZ2wudGhpcygndmlld3BvcnQnKSxcclxuXHJcblx0XHR2ZXJ0OiAoXCJcXG5cXHRcXHRcXHRwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuXFx0XFx0XFx0YXR0cmlidXRlIGZsb2F0IHdpZHRoLCBjaGFyT2Zmc2V0LCBjaGFyO1xcblxcdFxcdFxcdGF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uO1xcblxcdFxcdFxcdHVuaWZvcm0gZmxvYXQgZm9udFNpemUsIGNoYXJTdGVwLCBlbSwgYWxpZ24sIGJhc2VsaW5lO1xcblxcdFxcdFxcdHVuaWZvcm0gdmVjNCB2aWV3cG9ydDtcXG5cXHRcXHRcXHR1bmlmb3JtIHZlYzQgY29sb3I7XFxuXFx0XFx0XFx0dW5pZm9ybSB2ZWMyIGF0bGFzU2l6ZSwgYXRsYXNEaW0sIHNjYWxlLCB0cmFuc2xhdGUsIHBvc2l0aW9uT2Zmc2V0O1xcblxcdFxcdFxcdHZhcnlpbmcgdmVjMiBjaGFyQ29vcmQsIGNoYXJJZDtcXG5cXHRcXHRcXHR2YXJ5aW5nIGZsb2F0IGNoYXJXaWR0aDtcXG5cXHRcXHRcXHR2YXJ5aW5nIHZlYzQgZm9udENvbG9yO1xcblxcdFxcdFxcdHZvaWQgbWFpbiAoKSB7XFxuXFx0XFx0XFx0XFx0XCIgKyAoIUdsVGV4dC5ub3JtYWxWaWV3cG9ydCA/ICd2ZWMyIHBvc2l0aW9uT2Zmc2V0ID0gdmVjMihwb3NpdGlvbk9mZnNldC54LC0gcG9zaXRpb25PZmZzZXQueSk7JyA6ICcnKSArIFwiXFxuXFxuXFx0XFx0XFx0XFx0dmVjMiBvZmZzZXQgPSBmbG9vcihlbSAqICh2ZWMyKGFsaWduICsgY2hhck9mZnNldCwgYmFzZWxpbmUpXFxuXFx0XFx0XFx0XFx0XFx0KyBwb3NpdGlvbk9mZnNldCkpXFxuXFx0XFx0XFx0XFx0XFx0LyAodmlld3BvcnQuencgKiBzY2FsZS54eSk7XFxuXFxuXFx0XFx0XFx0XFx0dmVjMiBwb3NpdGlvbiA9IChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZTtcXG5cXHRcXHRcXHRcXHRwb3NpdGlvbiArPSBvZmZzZXQgKiBzY2FsZTtcXG5cXG5cXHRcXHRcXHRcXHRcIiArIChHbFRleHQubm9ybWFsVmlld3BvcnQgPyAncG9zaXRpb24ueSA9IDEuIC0gcG9zaXRpb24ueTsnIDogJycpICsgXCJcXG5cXG5cXHRcXHRcXHRcXHRjaGFyQ29vcmQgPSBwb3NpdGlvbiAqIHZpZXdwb3J0Lnp3ICsgdmlld3BvcnQueHk7XFxuXFxuXFx0XFx0XFx0XFx0Z2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uICogMi4gLSAxLiwgMCwgMSk7XFxuXFxuXFx0XFx0XFx0XFx0Z2xfUG9pbnRTaXplID0gY2hhclN0ZXA7XFxuXFxuXFx0XFx0XFx0XFx0Y2hhcklkLnggPSBtb2QoY2hhciwgYXRsYXNEaW0ueCk7XFxuXFx0XFx0XFx0XFx0Y2hhcklkLnkgPSBmbG9vcihjaGFyIC8gYXRsYXNEaW0ueCk7XFxuXFxuXFx0XFx0XFx0XFx0Y2hhcldpZHRoID0gd2lkdGggKiBlbTtcXG5cXG5cXHRcXHRcXHRcXHRmb250Q29sb3IgPSBjb2xvciAvIDI1NS47XFxuXFx0XFx0XFx0fVwiKSxcclxuXHJcblx0XHRmcmFnOiBcIlxcblxcdFxcdFxcdHByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG5cXHRcXHRcXHR1bmlmb3JtIHNhbXBsZXIyRCBhdGxhcztcXG5cXHRcXHRcXHR1bmlmb3JtIGZsb2F0IGZvbnRTaXplLCBjaGFyU3RlcCwgb3BhY2l0eTtcXG5cXHRcXHRcXHR1bmlmb3JtIHZlYzIgYXRsYXNTaXplO1xcblxcdFxcdFxcdHVuaWZvcm0gdmVjNCB2aWV3cG9ydDtcXG5cXHRcXHRcXHR2YXJ5aW5nIHZlYzQgZm9udENvbG9yO1xcblxcdFxcdFxcdHZhcnlpbmcgdmVjMiBjaGFyQ29vcmQsIGNoYXJJZDtcXG5cXHRcXHRcXHR2YXJ5aW5nIGZsb2F0IGNoYXJXaWR0aDtcXG5cXG5cXHRcXHRcXHRmbG9hdCBsaWdodG5lc3ModmVjNCBjb2xvcikge1xcblxcdFxcdFxcdFxcdHJldHVybiBjb2xvci5yICogMC4yOTkgKyBjb2xvci5nICogMC41ODcgKyBjb2xvci5iICogMC4xMTQ7XFxuXFx0XFx0XFx0fVxcblxcblxcdFxcdFxcdHZvaWQgbWFpbiAoKSB7XFxuXFx0XFx0XFx0XFx0dmVjMiB1diA9IGdsX0ZyYWdDb29yZC54eSAtIGNoYXJDb29yZCArIGNoYXJTdGVwICogLjU7XFxuXFx0XFx0XFx0XFx0ZmxvYXQgaGFsZkNoYXJTdGVwID0gZmxvb3IoY2hhclN0ZXAgKiAuNSArIC41KTtcXG5cXG5cXHRcXHRcXHRcXHQvLyBpbnZlcnQgeSBhbmQgc2hpZnQgYnkgMXB4IChGRiBleHBlY2lhbGx5IG5lZWRzIHRoYXQpXFxuXFx0XFx0XFx0XFx0dXYueSA9IGNoYXJTdGVwIC0gdXYueTtcXG5cXG5cXHRcXHRcXHRcXHQvLyBpZ25vcmUgcG9pbnRzIG91dHNpZGUgb2YgY2hhcmFjdGVyIGJvdW5kaW5nIGJveFxcblxcdFxcdFxcdFxcdGZsb2F0IGhhbGZDaGFyV2lkdGggPSBjZWlsKGNoYXJXaWR0aCAqIC41KTtcXG5cXHRcXHRcXHRcXHRpZiAoZmxvb3IodXYueCkgPiBoYWxmQ2hhclN0ZXAgKyBoYWxmQ2hhcldpZHRoIHx8XFxuXFx0XFx0XFx0XFx0XFx0Zmxvb3IodXYueCkgPCBoYWxmQ2hhclN0ZXAgLSBoYWxmQ2hhcldpZHRoKSByZXR1cm47XFxuXFxuXFx0XFx0XFx0XFx0dXYgKz0gY2hhcklkICogY2hhclN0ZXA7XFxuXFx0XFx0XFx0XFx0dXYgPSB1diAvIGF0bGFzU2l6ZTtcXG5cXG5cXHRcXHRcXHRcXHR2ZWM0IGNvbG9yID0gZm9udENvbG9yO1xcblxcdFxcdFxcdFxcdHZlYzQgbWFzayA9IHRleHR1cmUyRChhdGxhcywgdXYpO1xcblxcblxcdFxcdFxcdFxcdGZsb2F0IG1hc2tZID0gbGlnaHRuZXNzKG1hc2spO1xcblxcdFxcdFxcdFxcdC8vIGZsb2F0IGNvbG9yWSA9IGxpZ2h0bmVzcyhjb2xvcik7XFxuXFx0XFx0XFx0XFx0Y29sb3IuYSAqPSBtYXNrWTtcXG5cXHRcXHRcXHRcXHRjb2xvci5hICo9IG9wYWNpdHk7XFxuXFxuXFx0XFx0XFx0XFx0Ly8gY29sb3IuYSArPSAuMTtcXG5cXG5cXHRcXHRcXHRcXHQvLyBhbnRpYWxpYXNpbmcsIHNlZSB5aXEgY29sb3Igc3BhY2UgeS1jaGFubmVsIGZvcm11bGFcXG5cXHRcXHRcXHRcXHQvLyBjb2xvci5yZ2IgKz0gKDEuIC0gY29sb3IucmdiKSAqICgxLiAtIG1hc2sucmdiKTtcXG5cXG5cXHRcXHRcXHRcXHRnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG5cXHRcXHRcXHR9XCJcclxuXHR9KVxyXG5cclxuXHQvLyBwZXIgZm9udC1zaXplIGF0bGFzXHJcblx0dmFyIGF0bGFzID0ge31cclxuXHJcblx0cmV0dXJuIHsgcmVnbDogcmVnbCwgZHJhdzogZHJhdywgYXRsYXM6IGF0bGFzIH1cclxufTtcclxuXHJcbkdsVGV4dC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlIChvKSB7XG5cdFx0dmFyIHRoaXMkMSA9IHRoaXM7XG5cclxuXHRpZiAodHlwZW9mIG8gPT09ICdzdHJpbmcnKSB7IG8gPSB7IHRleHQ6IG8gfSB9XHJcblx0ZWxzZSBpZiAoIW8pIHsgcmV0dXJuIH1cclxuXHJcblx0Ly8gRklYTUU6IG1ha2UgdGhpcyBhIHN0YXRpYyB0cmFuc2Zvcm0gb3IgbW9yZSBnZW5lcmFsIGFwcHJvYWN0XHJcblx0byA9IHBpY2sobywge1xyXG5cdFx0cG9zaXRpb246ICdwb3NpdGlvbiBwb3NpdGlvbnMgY29vcmQgY29vcmRzIGNvb3JkaW5hdGVzJyxcclxuXHRcdGZvbnQ6ICdmb250IGZvbnRGYWNlIGZvbnRmYWNlIHR5cGVmYWNlIGNzc0ZvbnQgY3NzLWZvbnQgZmFtaWx5IGZvbnRGYW1pbHknLFxyXG5cdFx0Zm9udFNpemU6ICdmb250U2l6ZSBmb250c2l6ZSBzaXplIGZvbnQtc2l6ZScsXHJcblx0XHR0ZXh0OiAndGV4dCB0ZXh0cyBjaGFycyBjaGFyYWN0ZXJzIHZhbHVlIHZhbHVlcyBzeW1ib2xzJyxcclxuXHRcdGFsaWduOiAnYWxpZ24gYWxpZ25tZW50IHRleHRBbGlnbiB0ZXh0YmFzZWxpbmUnLFxyXG5cdFx0YmFzZWxpbmU6ICdiYXNlbGluZSB0ZXh0QmFzZWxpbmUgdGV4dGJhc2VsaW5lJyxcclxuXHRcdGRpcmVjdGlvbjogJ2RpciBkaXJlY3Rpb24gdGV4dERpcmVjdGlvbicsXHJcblx0XHRjb2xvcjogJ2NvbG9yIGNvbG91ciBmaWxsIGZpbGwtY29sb3IgZmlsbENvbG9yIHRleHRDb2xvciB0ZXh0Y29sb3InLFxyXG5cdFx0a2VybmluZzogJ2tlcm5pbmcga2VybicsXHJcblx0XHRyYW5nZTogJ3JhbmdlIGRhdGFCb3gnLFxyXG5cdFx0dmlld3BvcnQ6ICd2cCB2aWV3cG9ydCB2aWV3Qm94IHZpZXdib3ggdmlld1BvcnQnLFxyXG5cdFx0b3BhY2l0eTogJ29wYWNpdHkgYWxwaGEgdHJhbnNwYXJlbmN5IHZpc2libGUgdmlzaWJpbGl0eSBvcGFxdWUnLFxyXG5cdFx0b2Zmc2V0OiAnb2Zmc2V0IHBvc2l0aW9uT2Zmc2V0IHBhZGRpbmcgc2hpZnQgaW5kZW50IGluZGVudGF0aW9uJ1xyXG5cdH0sIHRydWUpXHJcblxyXG5cclxuXHRpZiAoby5vcGFjaXR5ICE9IG51bGwpIHtcclxuXHRcdGlmIChBcnJheS5pc0FycmF5KG8ub3BhY2l0eSkpIHtcclxuXHRcdFx0dGhpcy5vcGFjaXR5ID0gby5vcGFjaXR5Lm1hcChmdW5jdGlvbiAobykgeyByZXR1cm4gcGFyc2VGbG9hdChvKTsgfSlcclxuXHRcdH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHR0aGlzLm9wYWNpdHkgPSBwYXJzZUZsb2F0KG8ub3BhY2l0eSlcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGlmIChvLnZpZXdwb3J0ICE9IG51bGwpIHtcclxuXHRcdHRoaXMudmlld3BvcnQgPSBwYXJzZVJlY3Qoby52aWV3cG9ydClcclxuXHJcblx0XHRpZiAoR2xUZXh0Lm5vcm1hbFZpZXdwb3J0KSB7XHJcblx0XHRcdHRoaXMudmlld3BvcnQueSA9IHRoaXMuY2FudmFzLmhlaWdodCAtIHRoaXMudmlld3BvcnQueSAtIHRoaXMudmlld3BvcnQuaGVpZ2h0XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy52aWV3cG9ydEFycmF5ID0gW3RoaXMudmlld3BvcnQueCwgdGhpcy52aWV3cG9ydC55LCB0aGlzLnZpZXdwb3J0LndpZHRoLCB0aGlzLnZpZXdwb3J0LmhlaWdodF1cclxuXHJcblx0fVxyXG5cdGlmICh0aGlzLnZpZXdwb3J0ID09IG51bGwpIHtcclxuXHRcdHRoaXMudmlld3BvcnQgPSB7XHJcblx0XHRcdHg6IDAsIHk6IDAsXHJcblx0XHRcdHdpZHRoOiB0aGlzLmdsLmRyYXdpbmdCdWZmZXJXaWR0aCxcclxuXHRcdFx0aGVpZ2h0OiB0aGlzLmdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcclxuXHRcdH1cclxuXHRcdHRoaXMudmlld3BvcnRBcnJheSA9IFt0aGlzLnZpZXdwb3J0LngsIHRoaXMudmlld3BvcnQueSwgdGhpcy52aWV3cG9ydC53aWR0aCwgdGhpcy52aWV3cG9ydC5oZWlnaHRdXHJcblx0fVxyXG5cclxuXHRpZiAoby5rZXJuaW5nICE9IG51bGwpIHsgdGhpcy5rZXJuaW5nID0gby5rZXJuaW5nIH1cclxuXHJcblx0aWYgKG8ub2Zmc2V0ICE9IG51bGwpIHtcclxuXHRcdGlmICh0eXBlb2Ygby5vZmZzZXQgPT09ICdudW1iZXInKSB7IG8ub2Zmc2V0ID0gW28ub2Zmc2V0LCAwXSB9XHJcblxyXG5cdFx0dGhpcy5wb3NpdGlvbk9mZnNldCA9IGZsYXR0ZW4oby5vZmZzZXQpXHJcblx0fVxyXG5cclxuXHRpZiAoby5kaXJlY3Rpb24pIHsgdGhpcy5kaXJlY3Rpb24gPSBvLmRpcmVjdGlvbiB9XHJcblxyXG5cdGlmIChvLnJhbmdlKSB7XHJcblx0XHR0aGlzLnJhbmdlID0gby5yYW5nZVxyXG5cdFx0dGhpcy5zY2FsZSA9IFsxIC8gKG8ucmFuZ2VbMl0gLSBvLnJhbmdlWzBdKSwgMSAvIChvLnJhbmdlWzNdIC0gby5yYW5nZVsxXSldXHJcblx0XHR0aGlzLnRyYW5zbGF0ZSA9IFstby5yYW5nZVswXSwgLW8ucmFuZ2VbMV1dXHJcblx0fVxyXG5cdGlmIChvLnNjYWxlKSB7IHRoaXMuc2NhbGUgPSBvLnNjYWxlIH1cclxuXHRpZiAoby50cmFuc2xhdGUpIHsgdGhpcy50cmFuc2xhdGUgPSBvLnRyYW5zbGF0ZSB9XHJcblxyXG5cdC8vIGRlZmF1bHQgc2NhbGUgY29ycmVzcG9uZHMgdG8gdmlld3BvcnRcclxuXHRpZiAoIXRoaXMuc2NhbGUpIHsgdGhpcy5zY2FsZSA9IFsxIC8gdGhpcy52aWV3cG9ydC53aWR0aCwgMSAvIHRoaXMudmlld3BvcnQuaGVpZ2h0XSB9XHJcblxyXG5cdGlmICghdGhpcy50cmFuc2xhdGUpIHsgdGhpcy50cmFuc2xhdGUgPSBbMCwgMF0gfVxyXG5cclxuXHRpZiAoIXRoaXMuZm9udC5sZW5ndGggJiYgIW8uZm9udCkgeyBvLmZvbnQgPSBHbFRleHQuYmFzZUZvbnRTaXplICsgJ3B4IHNhbnMtc2VyaWYnIH1cclxuXHJcblx0Ly8gbm9ybWFsaXplIGZvbnQgY2FjaGluZyBzdHJpbmdcclxuXHR2YXIgbmV3Rm9udCA9IGZhbHNlLCBuZXdGb250U2l6ZSA9IGZhbHNlXHJcblxyXG5cdC8vIG9idGFpbiBuZXcgZm9udCBkYXRhXHJcblx0aWYgKG8uZm9udCkge1xyXG5cdFx0KEFycmF5LmlzQXJyYXkoby5mb250KSA/IG8uZm9udCA6IFtvLmZvbnRdKS5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpKSB7XHJcblx0XHRcdC8vIG5vcm1hbGl6ZSBmb250XHJcblx0XHRcdGlmICh0eXBlb2YgZm9udCA9PT0gJ3N0cmluZycpIHtcclxuXHRcdFx0XHR0cnkge1xyXG5cdFx0XHRcdFx0Zm9udCA9IEZvbnQucGFyc2UoZm9udClcclxuXHRcdFx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdFx0XHRmb250ID0gRm9udC5wYXJzZShHbFRleHQuYmFzZUZvbnRTaXplICsgJ3B4ICcgKyBmb250KVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHsgZm9udCA9IEZvbnQucGFyc2UoRm9udC5zdHJpbmdpZnkoZm9udCkpIH1cclxuXHJcblx0XHRcdHZhciBiYXNlU3RyaW5nID0gRm9udC5zdHJpbmdpZnkoe1xyXG5cdFx0XHRcdHNpemU6IEdsVGV4dC5iYXNlRm9udFNpemUsXHJcblx0XHRcdFx0ZmFtaWx5OiBmb250LmZhbWlseSxcclxuXHRcdFx0XHRzdHJldGNoOiBpc1N0cmV0Y2hTdXBwb3J0ZWQgPyBmb250LnN0cmV0Y2ggOiB1bmRlZmluZWQsXHJcblx0XHRcdFx0dmFyaWFudDogZm9udC52YXJpYW50LFxyXG5cdFx0XHRcdHdlaWdodDogZm9udC53ZWlnaHQsXHJcblx0XHRcdFx0c3R5bGU6IGZvbnQuc3R5bGVcclxuXHRcdFx0fSlcclxuXHJcblx0XHRcdHZhciB1bml0ID0gcGFyc2VVbml0KGZvbnQuc2l6ZSlcclxuXHRcdFx0dmFyIGZzID0gTWF0aC5yb3VuZCh1bml0WzBdICogcHgodW5pdFsxXSkpXHJcblx0XHRcdGlmIChmcyAhPT0gdGhpcyQxLmZvbnRTaXplW2ldKSB7XHJcblx0XHRcdFx0bmV3Rm9udFNpemUgPSB0cnVlXHJcblx0XHRcdFx0dGhpcyQxLmZvbnRTaXplW2ldID0gZnNcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gY2FsYyBuZXcgZm9udCBtZXRyaWNzL2F0bGFzXHJcblx0XHRcdGlmICghdGhpcyQxLmZvbnRbaV0gfHwgYmFzZVN0cmluZyAhPSB0aGlzJDEuZm9udFtpXS5iYXNlU3RyaW5nKSB7XHJcblx0XHRcdFx0bmV3Rm9udCA9IHRydWVcclxuXHJcblx0XHRcdFx0Ly8gb2J0YWluIGZvbnQgY2FjaGUgb3IgY3JlYXRlIG9uZVxyXG5cdFx0XHRcdHRoaXMkMS5mb250W2ldID0gR2xUZXh0LmZvbnRzW2Jhc2VTdHJpbmddXHJcblx0XHRcdFx0aWYgKCF0aGlzJDEuZm9udFtpXSkge1xyXG5cdFx0XHRcdFx0dmFyIGZhbWlseSA9IGZvbnQuZmFtaWx5LmpvaW4oJywgJylcclxuXHRcdFx0XHRcdHZhciBzdHlsZSA9IFtmb250LnN0eWxlXVxyXG5cdFx0XHRcdFx0aWYgKGZvbnQuc3R5bGUgIT0gZm9udC52YXJpYW50KSB7IHN0eWxlLnB1c2goZm9udC52YXJpYW50KSB9XHJcblx0XHRcdFx0XHRpZiAoZm9udC52YXJpYW50ICE9IGZvbnQud2VpZ2h0KSB7IHN0eWxlLnB1c2goZm9udC53ZWlnaHQpIH1cclxuXHRcdFx0XHRcdGlmIChpc1N0cmV0Y2hTdXBwb3J0ZWQgJiYgZm9udC53ZWlnaHQgIT0gZm9udC5zdHJldGNoKSB7IHN0eWxlLnB1c2goZm9udC5zdHJldGNoKSB9XHJcblxyXG5cdFx0XHRcdFx0dGhpcyQxLmZvbnRbaV0gPSB7XHJcblx0XHRcdFx0XHRcdGJhc2VTdHJpbmc6IGJhc2VTdHJpbmcsXHJcblxyXG5cdFx0XHRcdFx0XHQvLyB0eXBlZmFjZVxyXG5cdFx0XHRcdFx0XHRmYW1pbHk6IGZhbWlseSxcclxuXHRcdFx0XHRcdFx0d2VpZ2h0OiBmb250LndlaWdodCxcclxuXHRcdFx0XHRcdFx0c3RyZXRjaDogZm9udC5zdHJldGNoLFxyXG5cdFx0XHRcdFx0XHRzdHlsZTogZm9udC5zdHlsZSxcclxuXHRcdFx0XHRcdFx0dmFyaWFudDogZm9udC52YXJpYW50LFxyXG5cclxuXHRcdFx0XHRcdFx0Ly8gd2lkdGhzIG9mIGNoYXJhY3RlcnNcclxuXHRcdFx0XHRcdFx0d2lkdGg6IHt9LFxyXG5cclxuXHRcdFx0XHRcdFx0Ly8ga2VybmluIHBhaXJzIG9mZnNldHNcclxuXHRcdFx0XHRcdFx0a2VybmluZzoge30sXHJcblxyXG5cdFx0XHRcdFx0XHRtZXRyaWNzOiBtZXRyaWNzKGZhbWlseSwge1xyXG5cdFx0XHRcdFx0XHRcdG9yaWdpbjogJ3RvcCcsXHJcblx0XHRcdFx0XHRcdFx0Zm9udFNpemU6IEdsVGV4dC5iYXNlRm9udFNpemUsXHJcblx0XHRcdFx0XHRcdFx0Zm9udFN0eWxlOiBzdHlsZS5qb2luKCcgJylcclxuXHRcdFx0XHRcdFx0fSlcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRHbFRleHQuZm9udHNbYmFzZVN0cmluZ10gPSB0aGlzJDEuZm9udFtpXVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSlcclxuXHR9XHJcblxyXG5cdC8vIEZJWE1FOiBtYWtlIGluZGVwZW5kZW5kIGZvbnQtc2l6ZVxyXG5cdC8vIGlmIChvLmZvbnRTaXplKSB7XHJcblx0Ly8gbGV0IHVuaXQgPSBwYXJzZVVuaXQoby5mb250U2l6ZSlcclxuXHQvLyBsZXQgZnMgPSBNYXRoLnJvdW5kKHVuaXRbMF0gKiBweCh1bml0WzFdKSlcclxuXHJcblx0Ly8gaWYgKGZzICE9IHRoaXMuZm9udFNpemUpIHtcclxuXHQvLyBcdG5ld0ZvbnRTaXplID0gdHJ1ZVxyXG5cdC8vIFx0dGhpcy5mb250U2l6ZSA9IGZzXHJcblx0Ly8gfVxyXG5cdC8vIH1cclxuXHJcblx0aWYgKG5ld0ZvbnQgfHwgbmV3Rm9udFNpemUpIHtcclxuXHRcdHRoaXMuZm9udC5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpKSB7XHJcblx0XHRcdHZhciBmb250U3RyaW5nID0gRm9udC5zdHJpbmdpZnkoe1xyXG5cdFx0XHRcdHNpemU6IHRoaXMkMS5mb250U2l6ZVtpXSxcclxuXHRcdFx0XHRmYW1pbHk6IGZvbnQuZmFtaWx5LFxyXG5cdFx0XHRcdHN0cmV0Y2g6IGlzU3RyZXRjaFN1cHBvcnRlZCA/IGZvbnQuc3RyZXRjaCA6IHVuZGVmaW5lZCxcclxuXHRcdFx0XHR2YXJpYW50OiBmb250LnZhcmlhbnQsXHJcblx0XHRcdFx0d2VpZ2h0OiBmb250LndlaWdodCxcclxuXHRcdFx0XHRzdHlsZTogZm9udC5zdHlsZVxyXG5cdFx0XHR9KVxyXG5cclxuXHRcdFx0Ly8gY2FsYyBuZXcgZm9udCBzaXplIGF0bGFzXHJcblx0XHRcdHRoaXMkMS5mb250QXRsYXNbaV0gPSB0aGlzJDEuc2hhZGVyLmF0bGFzW2ZvbnRTdHJpbmddXHJcblxyXG5cdFx0XHRpZiAoIXRoaXMkMS5mb250QXRsYXNbaV0pIHtcclxuXHRcdFx0XHR2YXIgbWV0cmljcyA9IGZvbnQubWV0cmljc1xyXG5cclxuXHRcdFx0XHR0aGlzJDEuc2hhZGVyLmF0bGFzW2ZvbnRTdHJpbmddID1cclxuXHRcdFx0XHR0aGlzJDEuZm9udEF0bGFzW2ldID0ge1xyXG5cdFx0XHRcdFx0Zm9udFN0cmluZzogZm9udFN0cmluZyxcclxuXHRcdFx0XHRcdC8vIGV2ZW4gc3RlcCBpcyBiZXR0ZXIgZm9yIHJlbmRlcmVkIGNoYXJhY3RlcnNcclxuXHRcdFx0XHRcdHN0ZXA6IE1hdGguY2VpbCh0aGlzJDEuZm9udFNpemVbaV0gKiBtZXRyaWNzLmJvdHRvbSAqIC41KSAqIDIsXHJcblx0XHRcdFx0XHRlbTogdGhpcyQxLmZvbnRTaXplW2ldLFxyXG5cdFx0XHRcdFx0Y29sczogMCxcclxuXHRcdFx0XHRcdHJvd3M6IDAsXHJcblx0XHRcdFx0XHRoZWlnaHQ6IDAsXHJcblx0XHRcdFx0XHR3aWR0aDogMCxcclxuXHRcdFx0XHRcdGNoYXJzOiBbXSxcclxuXHRcdFx0XHRcdGlkczoge30sXHJcblx0XHRcdFx0XHR0ZXh0dXJlOiB0aGlzJDEucmVnbC50ZXh0dXJlKClcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIGJ1bXAgYXRsYXMgY2hhcmFjdGVyc1xyXG5cdFx0XHRpZiAoby50ZXh0ID09IG51bGwpIHsgby50ZXh0ID0gdGhpcyQxLnRleHQgfVxyXG5cdFx0fSlcclxuXHR9XHJcblxyXG5cdC8vIGlmIG11bHRpcGxlIHBvc2l0aW9ucyAtIGR1cGxpY2F0ZSB0ZXh0IGFyZ3VtZW50c1xyXG5cdC8vIEZJWE1FOiB0aGlzIHBvc3NpYmx5IGNhbiBiZSBkb25lIGJldHRlciB0byBhdm9pZCBhcnJheSBzcGF3blxyXG5cdGlmICh0eXBlb2Ygby50ZXh0ID09PSAnc3RyaW5nJyAmJiBvLnBvc2l0aW9uICYmIG8ucG9zaXRpb24ubGVuZ3RoID4gMikge1xyXG5cdFx0dmFyIHRleHRBcnJheSA9IEFycmF5KG8ucG9zaXRpb24ubGVuZ3RoICogLjUpXHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRleHRBcnJheS5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHR0ZXh0QXJyYXlbaV0gPSBvLnRleHRcclxuXHRcdH1cclxuXHRcdG8udGV4dCA9IHRleHRBcnJheVxyXG5cdH1cclxuXHJcblx0Ly8gY2FsY3VsYXRlIG9mZnNldHMgZm9yIHRoZSBuZXcgZm9udC90ZXh0XHJcblx0dmFyIG5ld0F0bGFzQ2hhcnNcclxuXHRpZiAoby50ZXh0ICE9IG51bGwgfHwgbmV3Rm9udCkge1xyXG5cdFx0Ly8gRklYTUU6IGlnbm9yZSBzcGFjZXNcclxuXHRcdC8vIHRleHQgb2Zmc2V0cyB3aXRoaW4gdGhlIHRleHQgYnVmZmVyXHJcblx0XHR0aGlzLnRleHRPZmZzZXRzID0gWzBdXHJcblxyXG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoby50ZXh0KSkge1xyXG5cdFx0XHR0aGlzLmNvdW50ID0gby50ZXh0WzBdLmxlbmd0aFxyXG5cdFx0XHR0aGlzLmNvdW50cyA9IFt0aGlzLmNvdW50XVxyXG5cdFx0XHRmb3IgKHZhciBpJDEgPSAxOyBpJDEgPCBvLnRleHQubGVuZ3RoOyBpJDErKykge1xyXG5cdFx0XHRcdHRoaXMkMS50ZXh0T2Zmc2V0c1tpJDFdID0gdGhpcyQxLnRleHRPZmZzZXRzW2kkMSAtIDFdICsgby50ZXh0W2kkMSAtIDFdLmxlbmd0aFxyXG5cdFx0XHRcdHRoaXMkMS5jb3VudCArPSBvLnRleHRbaSQxXS5sZW5ndGhcclxuXHRcdFx0XHR0aGlzJDEuY291bnRzLnB1c2goby50ZXh0W2kkMV0ubGVuZ3RoKVxyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMudGV4dCA9IG8udGV4dC5qb2luKCcnKVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHRoaXMudGV4dCA9IG8udGV4dFxyXG5cdFx0XHR0aGlzLmNvdW50ID0gdGhpcy50ZXh0Lmxlbmd0aFxyXG5cdFx0XHR0aGlzLmNvdW50cyA9IFt0aGlzLmNvdW50XVxyXG5cdFx0fVxyXG5cclxuXHRcdG5ld0F0bGFzQ2hhcnMgPSBbXVxyXG5cclxuXHRcdC8vIGRldGVjdCAmIG1lYXN1cmUgbmV3IGNoYXJhY3RlcnNcclxuXHRcdHRoaXMuZm9udC5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpZHgpIHtcclxuXHRcdFx0R2xUZXh0LmF0bGFzQ29udGV4dC5mb250ID0gZm9udC5iYXNlU3RyaW5nXHJcblxyXG5cdFx0XHR2YXIgYXRsYXMgPSB0aGlzJDEuZm9udEF0bGFzW2lkeF1cclxuXHJcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcyQxLnRleHQubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0XHR2YXIgY2hhciA9IHRoaXMkMS50ZXh0LmNoYXJBdChpKVxyXG5cclxuXHRcdFx0XHRpZiAoYXRsYXMuaWRzW2NoYXJdID09IG51bGwpIHtcclxuXHRcdFx0XHRcdGF0bGFzLmlkc1tjaGFyXSA9IGF0bGFzLmNoYXJzLmxlbmd0aFxyXG5cdFx0XHRcdFx0YXRsYXMuY2hhcnMucHVzaChjaGFyKVxyXG5cdFx0XHRcdFx0bmV3QXRsYXNDaGFycy5wdXNoKGNoYXIpXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRpZiAoZm9udC53aWR0aFtjaGFyXSA9PSBudWxsKSB7XHJcblx0XHRcdFx0XHRmb250LndpZHRoW2NoYXJdID0gR2xUZXh0LmF0bGFzQ29udGV4dC5tZWFzdXJlVGV4dChjaGFyKS53aWR0aCAvIEdsVGV4dC5iYXNlRm9udFNpemVcclxuXHJcblx0XHRcdFx0XHQvLyBtZWFzdXJlIGtlcm5pbmcgcGFpcnMgZm9yIHRoZSBuZXcgY2hhcmFjdGVyXHJcblx0XHRcdFx0XHRpZiAodGhpcyQxLmtlcm5pbmcpIHtcclxuXHRcdFx0XHRcdFx0dmFyIHBhaXJzID0gW11cclxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgYmFzZUNoYXIgaW4gZm9udC53aWR0aCkge1xyXG5cdFx0XHRcdFx0XHRcdHBhaXJzLnB1c2goYmFzZUNoYXIgKyBjaGFyLCBjaGFyICsgYmFzZUNoYXIpXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0ZXh0ZW5kKGZvbnQua2VybmluZywga2VybmluZyhmb250LmZhbWlseSwge1xyXG5cdFx0XHRcdFx0XHRcdHBhaXJzOiBwYWlyc1xyXG5cdFx0XHRcdFx0XHR9KSlcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0pXHJcblx0fVxyXG5cclxuXHQvLyBjcmVhdGUgc2luZ2xlIHBvc2l0aW9uIGJ1ZmZlciAoZmFzdGVyIHRoYW4gYmF0Y2ggb3IgbXVsdGlwbGUgc2VwYXJhdGUgaW5zdGFuY2VzKVxyXG5cdGlmIChvLnBvc2l0aW9uKSB7XHJcblx0XHRpZiAoby5wb3NpdGlvbi5sZW5ndGggPiAyKSB7XHJcblx0XHRcdHZhciBmbGF0ID0gIW8ucG9zaXRpb25bMF0ubGVuZ3RoXHJcblx0XHRcdHZhciBwb3NpdGlvbkRhdGEgPSBwb29sLm1hbGxvY0Zsb2F0KHRoaXMuY291bnQgKiAyKVxyXG5cdFx0XHRmb3IgKHZhciBpJDIgPSAwLCBwdHIgPSAwOyBpJDIgPCB0aGlzLmNvdW50cy5sZW5ndGg7IGkkMisrKSB7XHJcblx0XHRcdFx0dmFyIGNvdW50ID0gdGhpcyQxLmNvdW50c1tpJDJdXHJcblx0XHRcdFx0aWYgKGZsYXQpIHtcclxuXHRcdFx0XHRcdGZvciAodmFyIGogPSAwOyBqIDwgY291bnQ7IGorKykge1xyXG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDIgKiAyXVxyXG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDIgKiAyICsgMV1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRmb3IgKHZhciBqJDEgPSAwOyBqJDEgPCBjb3VudDsgaiQxKyspIHtcclxuXHRcdFx0XHRcdFx0cG9zaXRpb25EYXRhW3B0cisrXSA9IG8ucG9zaXRpb25baSQyXVswXVxyXG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDJdWzFdXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmICh0aGlzLnBvc2l0aW9uLmNhbGwpIHtcclxuXHRcdFx0XHR0aGlzLnBvc2l0aW9uKHtcclxuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCcsXHJcblx0XHRcdFx0XHRkYXRhOiBwb3NpdGlvbkRhdGFcclxuXHRcdFx0XHR9KVxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRoaXMucG9zaXRpb24gPSB0aGlzLnJlZ2wuYnVmZmVyKHtcclxuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCcsXHJcblx0XHRcdFx0XHRkYXRhOiBwb3NpdGlvbkRhdGFcclxuXHRcdFx0XHR9KVxyXG5cdFx0XHR9XHJcblx0XHRcdHBvb2wuZnJlZUZsb2F0KHBvc2l0aW9uRGF0YSlcclxuXHRcdH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRpZiAodGhpcy5wb3NpdGlvbi5kZXN0cm95KSB7IHRoaXMucG9zaXRpb24uZGVzdHJveSgpIH1cclxuXHRcdFx0dGhpcy5wb3NpdGlvbiA9IHtcclxuXHRcdFx0XHRjb25zdGFudDogby5wb3NpdGlvblxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBwb3B1bGF0ZSB0ZXh0L29mZnNldCBidWZmZXJzIGlmIGZvbnQvdGV4dCBoYXMgY2hhbmdlZFxyXG5cdC8vIGFzIFtjaGFyV2lkdGgsIG9mZnNldCwgY2hhcldpZHRoLCBvZmZzZXQuLi5dXHJcblx0Ly8gdGhhdCBpcyBpbiBlbSB1bml0cyBzaW5jZSBmb250LXNpemUgY2FuIGNoYW5nZSBvZnRlblxyXG5cdGlmIChvLnRleHQgfHwgbmV3Rm9udCkge1xyXG5cdFx0dmFyIGNoYXJJZHMgPSBwb29sLm1hbGxvY1VpbnQ4KHRoaXMuY291bnQpXHJcblx0XHR2YXIgc2l6ZURhdGEgPSBwb29sLm1hbGxvY0Zsb2F0KHRoaXMuY291bnQgKiAyKVxyXG5cdFx0dGhpcy50ZXh0V2lkdGggPSBbXVxyXG5cclxuXHRcdGZvciAodmFyIGkkMyA9IDAsIHB0ciQxID0gMDsgaSQzIDwgdGhpcy5jb3VudHMubGVuZ3RoOyBpJDMrKykge1xyXG5cdFx0XHR2YXIgY291bnQkMSA9IHRoaXMkMS5jb3VudHNbaSQzXVxyXG5cdFx0XHR2YXIgZm9udCA9IHRoaXMkMS5mb250W2kkM10gfHwgdGhpcyQxLmZvbnRbMF1cclxuXHRcdFx0dmFyIGF0bGFzID0gdGhpcyQxLmZvbnRBdGxhc1tpJDNdIHx8IHRoaXMkMS5mb250QXRsYXNbMF1cclxuXHJcblx0XHRcdGZvciAodmFyIGokMiA9IDA7IGokMiA8IGNvdW50JDE7IGokMisrKSB7XHJcblx0XHRcdFx0dmFyIGNoYXIgPSB0aGlzJDEudGV4dC5jaGFyQXQocHRyJDEpXHJcblx0XHRcdFx0dmFyIHByZXZDaGFyID0gdGhpcyQxLnRleHQuY2hhckF0KHB0ciQxIC0gMSlcclxuXHJcblx0XHRcdFx0Y2hhcklkc1twdHIkMV0gPSBhdGxhcy5pZHNbY2hhcl1cclxuXHRcdFx0XHRzaXplRGF0YVtwdHIkMSAqIDJdID0gZm9udC53aWR0aFtjaGFyXVxyXG5cclxuXHRcdFx0XHRpZiAoaiQyKSB7XHJcblx0XHRcdFx0XHR2YXIgcHJldldpZHRoID0gc2l6ZURhdGFbcHRyJDEgKiAyIC0gMl1cclxuXHRcdFx0XHRcdHZhciBjdXJyV2lkdGggPSBzaXplRGF0YVtwdHIkMSAqIDJdXHJcblx0XHRcdFx0XHR2YXIgcHJldk9mZnNldCA9IHNpemVEYXRhW3B0ciQxICogMiAtIDFdXHJcblx0XHRcdFx0XHR2YXIgb2Zmc2V0ID0gcHJldk9mZnNldCArIHByZXZXaWR0aCAqIC41ICsgY3VycldpZHRoICogLjU7XHJcblxyXG5cdFx0XHRcdFx0aWYgKHRoaXMkMS5rZXJuaW5nKSB7XHJcblx0XHRcdFx0XHRcdHZhciBrZXJuaW5nJDEgPSBmb250Lmtlcm5pbmdbcHJldkNoYXIgKyBjaGFyXVxyXG5cdFx0XHRcdFx0XHRpZiAoa2VybmluZyQxKSB7XHJcblx0XHRcdFx0XHRcdFx0b2Zmc2V0ICs9IGtlcm5pbmckMSAqIDFlLTNcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdHNpemVEYXRhW3B0ciQxICogMiArIDFdID0gb2Zmc2V0XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0c2l6ZURhdGFbcHRyJDEgKiAyICsgMV0gPSBzaXplRGF0YVtwdHIkMSAqIDJdICogLjVcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdHB0ciQxKytcclxuXHRcdFx0fVxyXG5cdFx0XHR0aGlzJDEudGV4dFdpZHRoLnB1c2goXHJcblx0XHRcdFx0IXNpemVEYXRhLmxlbmd0aCA/IDAgOlxyXG5cdFx0XHRcdC8vIGxhc3Qgb2Zmc2V0ICsgaGFsZiBsYXN0IHdpZHRoXHJcblx0XHRcdFx0c2l6ZURhdGFbcHRyJDEgKiAyIC0gMl0gKiAuNSArIHNpemVEYXRhW3B0ciQxICogMiAtIDFdXHJcblx0XHRcdClcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0Ly8gYnVtcCByZWNhbGMgYWxpZ24gb2Zmc2V0XHJcblx0XHRpZiAoIW8uYWxpZ24pIHsgby5hbGlnbiA9IHRoaXMuYWxpZ24gfVxyXG5cdFx0dGhpcy5jaGFyQnVmZmVyKHtkYXRhOiBjaGFySWRzLCB0eXBlOiAndWludDgnLCB1c2FnZTogJ3N0cmVhbSd9KVxyXG5cdFx0dGhpcy5zaXplQnVmZmVyKHtkYXRhOiBzaXplRGF0YSwgdHlwZTogJ2Zsb2F0JywgdXNhZ2U6ICdzdHJlYW0nfSlcclxuXHRcdHBvb2wuZnJlZVVpbnQ4KGNoYXJJZHMpXHJcblx0XHRwb29sLmZyZWVGbG9hdChzaXplRGF0YSlcclxuXHJcblx0XHQvLyB1ZHBhdGUgZm9udCBhdGxhcyBhbmQgdGV4dHVyZVxyXG5cdFx0aWYgKG5ld0F0bGFzQ2hhcnMubGVuZ3RoKSB7XHJcblx0XHRcdHRoaXMuZm9udC5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpKSB7XHJcblx0XHRcdFx0dmFyIGF0bGFzID0gdGhpcyQxLmZvbnRBdGxhc1tpXVxyXG5cclxuXHRcdFx0XHQvLyBGSVhNRTogaW5zZXJ0IG1ldHJpY3MtYmFzZWQgcmF0aW8gaGVyZVxyXG5cdFx0XHRcdHZhciBzdGVwID0gYXRsYXMuc3RlcFxyXG5cclxuXHRcdFx0XHR2YXIgbWF4Q29scyA9IE1hdGguZmxvb3IoR2xUZXh0Lm1heEF0bGFzU2l6ZSAvIHN0ZXApXHJcblx0XHRcdFx0dmFyIGNvbHMgPSBNYXRoLm1pbihtYXhDb2xzLCBhdGxhcy5jaGFycy5sZW5ndGgpXHJcblx0XHRcdFx0dmFyIHJvd3MgPSBNYXRoLmNlaWwoYXRsYXMuY2hhcnMubGVuZ3RoIC8gY29scylcclxuXHJcblx0XHRcdFx0dmFyIGF0bGFzV2lkdGggPSBuZXh0UG93MiggY29scyAqIHN0ZXAgKVxyXG5cdFx0XHRcdC8vIGxldCBhdGxhc0hlaWdodCA9IE1hdGgubWluKHJvd3MgKiBzdGVwICsgc3RlcCAqIC41LCBHbFRleHQubWF4QXRsYXNTaXplKTtcclxuXHRcdFx0XHR2YXIgYXRsYXNIZWlnaHQgPSBuZXh0UG93Miggcm93cyAqIHN0ZXAgKTtcclxuXHJcblx0XHRcdFx0YXRsYXMud2lkdGggPSBhdGxhc1dpZHRoXHJcblx0XHRcdFx0YXRsYXMuaGVpZ2h0ID0gYXRsYXNIZWlnaHQ7XHJcblx0XHRcdFx0YXRsYXMucm93cyA9IHJvd3NcclxuXHRcdFx0XHRhdGxhcy5jb2xzID0gY29sc1xyXG5cclxuXHRcdFx0XHRpZiAoIWF0bGFzLmVtKSB7IHJldHVybiB9XHJcblxyXG5cdFx0XHRcdGF0bGFzLnRleHR1cmUoe1xyXG5cdFx0XHRcdFx0ZGF0YTogZm9udEF0bGFzKHtcclxuXHRcdFx0XHRcdFx0Y2FudmFzOiBHbFRleHQuYXRsYXNDYW52YXMsXHJcblx0XHRcdFx0XHRcdGZvbnQ6IGF0bGFzLmZvbnRTdHJpbmcsXHJcblx0XHRcdFx0XHRcdGNoYXJzOiBhdGxhcy5jaGFycyxcclxuXHRcdFx0XHRcdFx0c2hhcGU6IFthdGxhc1dpZHRoLCBhdGxhc0hlaWdodF0sXHJcblx0XHRcdFx0XHRcdHN0ZXA6IFtzdGVwLCBzdGVwXVxyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHR9KVxyXG5cclxuXHRcdFx0fSlcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGlmIChvLmFsaWduKSB7XHJcblx0XHR0aGlzLmFsaWduID0gby5hbGlnblxyXG5cdFx0dGhpcy5hbGlnbk9mZnNldCA9IHRoaXMudGV4dFdpZHRoLm1hcChmdW5jdGlvbiAodGV4dFdpZHRoLCBpKSB7XHJcblx0XHRcdHZhciBhbGlnbiA9ICFBcnJheS5pc0FycmF5KHRoaXMkMS5hbGlnbikgPyB0aGlzJDEuYWxpZ24gOiB0aGlzJDEuYWxpZ24ubGVuZ3RoID4gMSA/IHRoaXMkMS5hbGlnbltpXSA6IHRoaXMkMS5hbGlnblswXVxyXG5cclxuXHRcdFx0aWYgKHR5cGVvZiBhbGlnbiA9PT0gJ251bWJlcicpIHsgcmV0dXJuIGFsaWduIH1cclxuXHRcdFx0c3dpdGNoIChhbGlnbikge1xyXG5cdFx0XHRcdGNhc2UgJ3JpZ2h0JzpcclxuXHRcdFx0XHRjYXNlICdlbmQnOlxyXG5cdFx0XHRcdFx0cmV0dXJuIC10ZXh0V2lkdGhcclxuXHRcdFx0XHRjYXNlICdjZW50ZXInOlxyXG5cdFx0XHRcdGNhc2UgJ2NlbnRyZSc6XHJcblx0XHRcdFx0Y2FzZSAnbWlkZGxlJzpcclxuXHRcdFx0XHRcdHJldHVybiAtdGV4dFdpZHRoICogLjVcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0cmV0dXJuIDBcclxuXHRcdH0pXHJcblx0fVxyXG5cclxuXHRpZiAodGhpcy5iYXNlbGluZSA9PSBudWxsICYmIG8uYmFzZWxpbmUgPT0gbnVsbCkge1xyXG5cdFx0by5iYXNlbGluZSA9IDBcclxuXHR9XHJcblx0aWYgKG8uYmFzZWxpbmUgIT0gbnVsbCkge1xyXG5cdFx0dGhpcy5iYXNlbGluZSA9IG8uYmFzZWxpbmVcclxuXHRcdGlmICghQXJyYXkuaXNBcnJheSh0aGlzLmJhc2VsaW5lKSkgeyB0aGlzLmJhc2VsaW5lID0gW3RoaXMuYmFzZWxpbmVdIH1cclxuXHRcdHRoaXMuYmFzZWxpbmVPZmZzZXQgPSB0aGlzLmJhc2VsaW5lLm1hcChmdW5jdGlvbiAoYmFzZWxpbmUsIGkpIHtcclxuXHRcdFx0dmFyIG0gPSAodGhpcyQxLmZvbnRbaV0gfHwgdGhpcyQxLmZvbnRbMF0pLm1ldHJpY3NcclxuXHRcdFx0dmFyIGJhc2UgPSAwXHJcblxyXG5cdFx0XHRiYXNlICs9IG0uYm90dG9tICogLjVcclxuXHJcblx0XHRcdGlmICh0eXBlb2YgYmFzZWxpbmUgPT09ICdudW1iZXInKSB7XHJcblx0XHRcdFx0YmFzZSArPSAoYmFzZWxpbmUgLSBtLmJhc2VsaW5lKVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGJhc2UgKz0gLW1bYmFzZWxpbmVdXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmICghR2xUZXh0Lm5vcm1hbFZpZXdwb3J0KSB7IGJhc2UgKj0gLTEgfVxyXG5cdFx0XHRyZXR1cm4gYmFzZVxyXG5cdFx0fSlcclxuXHR9XHJcblxyXG5cdC8vIGZsYXR0ZW4gY29sb3JzIHRvIGEgc2luZ2xlIHVpbnQ4IGFycmF5XHJcblx0aWYgKG8uY29sb3IgIT0gbnVsbCkge1xyXG5cdFx0aWYgKCFvLmNvbG9yKSB7IG8uY29sb3IgPSAndHJhbnNwYXJlbnQnIH1cclxuXHJcblx0XHQvLyBzaW5nbGUgY29sb3JcclxuXHRcdGlmICh0eXBlb2Ygby5jb2xvciA9PT0gJ3N0cmluZycgfHwgIWlzTmFOKG8uY29sb3IpKSB7XHJcblx0XHRcdHRoaXMuY29sb3IgPSByZ2JhKG8uY29sb3IsICd1aW50OCcpXHJcblx0XHR9XHJcblx0XHQvLyBhcnJheVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHZhciBjb2xvckRhdGFcclxuXHJcblx0XHRcdC8vIGZsYXQgYXJyYXlcclxuXHRcdFx0aWYgKHR5cGVvZiBvLmNvbG9yWzBdID09PSAnbnVtYmVyJyAmJiBvLmNvbG9yLmxlbmd0aCA+IHRoaXMuY291bnRzLmxlbmd0aCkge1xyXG5cdFx0XHRcdHZhciBsID0gby5jb2xvci5sZW5ndGhcclxuXHRcdFx0XHRjb2xvckRhdGEgPSBwb29sLm1hbGxvY1VpbnQ4KGwpXHJcblx0XHRcdFx0dmFyIHN1YiA9IChvLmNvbG9yLnN1YmFycmF5IHx8IG8uY29sb3Iuc2xpY2UpLmJpbmQoby5jb2xvcilcclxuXHRcdFx0XHRmb3IgKHZhciBpJDQgPSAwOyBpJDQgPCBsOyBpJDQgKz0gNCkge1xyXG5cdFx0XHRcdFx0Y29sb3JEYXRhLnNldChyZ2JhKHN1YihpJDQsIGkkNCArIDQpLCAndWludDgnKSwgaSQ0KVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHQvLyBuZXN0ZWQgYXJyYXlcclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0dmFyIGwkMSA9IG8uY29sb3IubGVuZ3RoXHJcblx0XHRcdFx0Y29sb3JEYXRhID0gcG9vbC5tYWxsb2NVaW50OChsJDEgKiA0KVxyXG5cdFx0XHRcdGZvciAodmFyIGkkNSA9IDA7IGkkNSA8IGwkMTsgaSQ1KyspIHtcclxuXHRcdFx0XHRcdGNvbG9yRGF0YS5zZXQocmdiYShvLmNvbG9yW2kkNV0gfHwgMCwgJ3VpbnQ4JyksIGkkNSAqIDQpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLmNvbG9yID0gY29sb3JEYXRhXHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyB1cGRhdGUgcmVuZGVyIGJhdGNoXHJcblx0aWYgKG8ucG9zaXRpb24gfHwgby50ZXh0IHx8IG8uY29sb3IgfHwgby5iYXNlbGluZSB8fCBvLmFsaWduIHx8IG8uZm9udCB8fCBvLm9mZnNldCB8fCBvLm9wYWNpdHkpIHtcclxuXHRcdHZhciBpc0JhdGNoID0gKHRoaXMuY29sb3IubGVuZ3RoID4gNClcclxuXHRcdFx0fHwgKHRoaXMuYmFzZWxpbmVPZmZzZXQubGVuZ3RoID4gMSlcclxuXHRcdFx0fHwgKHRoaXMuYWxpZ24gJiYgdGhpcy5hbGlnbi5sZW5ndGggPiAxKVxyXG5cdFx0XHR8fCAodGhpcy5mb250QXRsYXMubGVuZ3RoID4gMSlcclxuXHRcdFx0fHwgKHRoaXMucG9zaXRpb25PZmZzZXQubGVuZ3RoID4gMilcclxuXHRcdGlmIChpc0JhdGNoKSB7XHJcblx0XHRcdHZhciBsZW5ndGggPSBNYXRoLm1heChcclxuXHRcdFx0XHR0aGlzLnBvc2l0aW9uLmxlbmd0aCAqIC41IHx8IDAsXHJcblx0XHRcdFx0dGhpcy5jb2xvci5sZW5ndGggKiAuMjUgfHwgMCxcclxuXHRcdFx0XHR0aGlzLmJhc2VsaW5lT2Zmc2V0Lmxlbmd0aCB8fCAwLFxyXG5cdFx0XHRcdHRoaXMuYWxpZ25PZmZzZXQubGVuZ3RoIHx8IDAsXHJcblx0XHRcdFx0dGhpcy5mb250Lmxlbmd0aCB8fCAwLFxyXG5cdFx0XHRcdHRoaXMub3BhY2l0eS5sZW5ndGggfHwgMCxcclxuXHRcdFx0XHR0aGlzLnBvc2l0aW9uT2Zmc2V0Lmxlbmd0aCAqIC41IHx8IDBcclxuXHRcdFx0KVxyXG5cdFx0XHR0aGlzLmJhdGNoID0gQXJyYXkobGVuZ3RoKVxyXG5cdFx0XHRmb3IgKHZhciBpJDYgPSAwOyBpJDYgPCB0aGlzLmJhdGNoLmxlbmd0aDsgaSQ2KyspIHtcclxuXHRcdFx0XHR0aGlzJDEuYmF0Y2hbaSQ2XSA9IHtcclxuXHRcdFx0XHRcdGNvdW50OiB0aGlzJDEuY291bnRzLmxlbmd0aCA+IDEgPyB0aGlzJDEuY291bnRzW2kkNl0gOiB0aGlzJDEuY291bnRzWzBdLFxyXG5cdFx0XHRcdFx0b2Zmc2V0OiB0aGlzJDEudGV4dE9mZnNldHMubGVuZ3RoID4gMSA/IHRoaXMkMS50ZXh0T2Zmc2V0c1tpJDZdIDogdGhpcyQxLnRleHRPZmZzZXRzWzBdLFxyXG5cdFx0XHRcdFx0Y29sb3I6ICF0aGlzJDEuY29sb3IgPyBbMCwwLDAsMjU1XSA6IHRoaXMkMS5jb2xvci5sZW5ndGggPD0gNCA/IHRoaXMkMS5jb2xvciA6IHRoaXMkMS5jb2xvci5zdWJhcnJheShpJDYgKiA0LCBpJDYgKiA0ICsgNCksXHJcblx0XHRcdFx0XHRvcGFjaXR5OiBBcnJheS5pc0FycmF5KHRoaXMkMS5vcGFjaXR5KSA/IHRoaXMkMS5vcGFjaXR5W2kkNl0gOiB0aGlzJDEub3BhY2l0eSxcclxuXHRcdFx0XHRcdGJhc2VsaW5lOiB0aGlzJDEuYmFzZWxpbmVPZmZzZXRbaSQ2XSAhPSBudWxsID8gdGhpcyQxLmJhc2VsaW5lT2Zmc2V0W2kkNl0gOiB0aGlzJDEuYmFzZWxpbmVPZmZzZXRbMF0sXHJcblx0XHRcdFx0XHRhbGlnbjogIXRoaXMkMS5hbGlnbiA/IDAgOiB0aGlzJDEuYWxpZ25PZmZzZXRbaSQ2XSAhPSBudWxsID8gdGhpcyQxLmFsaWduT2Zmc2V0W2kkNl0gOiB0aGlzJDEuYWxpZ25PZmZzZXRbMF0sXHJcblx0XHRcdFx0XHRhdGxhczogdGhpcyQxLmZvbnRBdGxhc1tpJDZdIHx8IHRoaXMkMS5mb250QXRsYXNbMF0sXHJcblx0XHRcdFx0XHRwb3NpdGlvbk9mZnNldDogdGhpcyQxLnBvc2l0aW9uT2Zmc2V0Lmxlbmd0aCA+IDIgPyB0aGlzJDEucG9zaXRpb25PZmZzZXQuc3ViYXJyYXkoaSQ2ICogMiwgaSQ2ICogMiArIDIpIDogdGhpcyQxLnBvc2l0aW9uT2Zmc2V0XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHQvLyBzaW5nbGUtY29sb3IsIHNpbmdsZS1iYXNlbGluZSwgc2luZ2xlLWFsaWduIGJhdGNoIGlzIGZhc3RlciB0byByZW5kZXJcclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRpZiAodGhpcy5jb3VudCkge1xyXG5cdFx0XHRcdHRoaXMuYmF0Y2ggPSBbe1xyXG5cdFx0XHRcdFx0Y291bnQ6IHRoaXMuY291bnQsXHJcblx0XHRcdFx0XHRvZmZzZXQ6IDAsXHJcblx0XHRcdFx0XHRjb2xvcjogdGhpcy5jb2xvciB8fCBbMCwwLDAsMjU1XSxcclxuXHRcdFx0XHRcdG9wYWNpdHk6IEFycmF5LmlzQXJyYXkodGhpcy5vcGFjaXR5KSA/IHRoaXMub3BhY2l0eVswXSA6IHRoaXMub3BhY2l0eSxcclxuXHRcdFx0XHRcdGJhc2VsaW5lOiB0aGlzLmJhc2VsaW5lT2Zmc2V0WzBdLFxyXG5cdFx0XHRcdFx0YWxpZ246IHRoaXMuYWxpZ25PZmZzZXQgPyB0aGlzLmFsaWduT2Zmc2V0WzBdIDogMCxcclxuXHRcdFx0XHRcdGF0bGFzOiB0aGlzLmZvbnRBdGxhc1swXSxcclxuXHRcdFx0XHRcdHBvc2l0aW9uT2Zmc2V0OiB0aGlzLnBvc2l0aW9uT2Zmc2V0XHJcblx0XHRcdFx0fV1cclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHR0aGlzLmJhdGNoID0gW11cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxufTtcclxuXHJcbkdsVGV4dC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3kgKCkge1xyXG5cdC8vIFRPRE86IGNvdW50IGluc3RhbmNlcyBvZiBhdGxhc2VzIGFuZCBkZXN0cm95IGFsbCBvbiBudWxsXHJcbn07XHJcblxyXG5cclxuLy8gZGVmYXVsdHNcclxuR2xUZXh0LnByb3RvdHlwZS5rZXJuaW5nID0gdHJ1ZVxyXG5HbFRleHQucHJvdG90eXBlLnBvc2l0aW9uID0geyBjb25zdGFudDogbmV3IEZsb2F0MzJBcnJheSgyKSB9XHJcbkdsVGV4dC5wcm90b3R5cGUudHJhbnNsYXRlID0gbnVsbFxyXG5HbFRleHQucHJvdG90eXBlLnNjYWxlID0gbnVsbFxyXG5HbFRleHQucHJvdG90eXBlLmZvbnQgPSBudWxsXHJcbkdsVGV4dC5wcm90b3R5cGUudGV4dCA9ICcnXHJcbkdsVGV4dC5wcm90b3R5cGUucG9zaXRpb25PZmZzZXQgPSBbMCwgMF1cclxuR2xUZXh0LnByb3RvdHlwZS5vcGFjaXR5ID0gMVxyXG5HbFRleHQucHJvdG90eXBlLmNvbG9yID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDAsIDAsIDI1NV0pXHJcbkdsVGV4dC5wcm90b3R5cGUuYWxpZ25PZmZzZXQgPSBbMCwgMF1cclxuXHJcblxyXG4vLyB3aGV0aGVyIHZpZXdwb3J0IHNob3VsZCBiZSB0b3DihpNib3R0b20gMmQgb25lICh0cnVlKSBvciB3ZWJnbCBvbmUgKGZhbHNlKVxyXG5HbFRleHQubm9ybWFsVmlld3BvcnQgPSBmYWxzZVxyXG5cclxuLy8gc2l6ZSBvZiBhbiBhdGxhc1xyXG5HbFRleHQubWF4QXRsYXNTaXplID0gMTAyNFxyXG5cclxuLy8gZm9udCBhdGxhcyBjYW52YXMgaXMgc2luZ2xldG9uXHJcbkdsVGV4dC5hdGxhc0NhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbkdsVGV4dC5hdGxhc0NvbnRleHQgPSBHbFRleHQuYXRsYXNDYW52YXMuZ2V0Q29udGV4dCgnMmQnLCB7YWxwaGE6IGZhbHNlfSlcclxuXHJcbi8vIGZvbnQtc2l6ZSB1c2VkIGZvciBtZXRyaWNzLCBhdGxhcyBzdGVwIGNhbGN1bGF0aW9uXHJcbkdsVGV4dC5iYXNlRm9udFNpemUgPSA2NFxyXG5cclxuLy8gZm9udHMgc3RvcmFnZVxyXG5HbFRleHQuZm9udHMgPSB7fVxyXG5cclxuLy8gbWF4IG51bWJlciBvZiBkaWZmZXJlbnQgZm9udCBhdGxhc2VzL3RleHR1cmVzIGNhY2hlZFxyXG4vLyBGSVhNRTogZW5hYmxlIGF0bGFzIHNpemUgbGltaXRhdGlvbiB2aWEgTFJVXHJcbi8vIEdsVGV4dC5hdGxhc0NhY2hlU2l6ZSA9IDY0XHJcblxyXG5mdW5jdGlvbiBpc1JlZ2wgKG8pIHtcclxuXHRyZXR1cm4gdHlwZW9mIG8gPT09ICdmdW5jdGlvbicgJiZcclxuXHRvLl9nbCAmJlxyXG5cdG8ucHJvcCAmJlxyXG5cdG8udGV4dHVyZSAmJlxyXG5cdG8uYnVmZmVyXHJcbn1cclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IEdsVGV4dFxyXG5cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgbmRhcnJheSA9IHJlcXVpcmUoJ25kYXJyYXknKVxudmFyIG9wcyAgICAgPSByZXF1aXJlKCduZGFycmF5LW9wcycpXG52YXIgcG9vbCAgICA9IHJlcXVpcmUoJ3R5cGVkYXJyYXktcG9vbCcpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGV4dHVyZTJEXG5cbnZhciBsaW5lYXJUeXBlcyA9IG51bGxcbnZhciBmaWx0ZXJUeXBlcyA9IG51bGxcbnZhciB3cmFwVHlwZXMgICA9IG51bGxcblxuZnVuY3Rpb24gbGF6eUluaXRMaW5lYXJUeXBlcyhnbCkge1xuICBsaW5lYXJUeXBlcyA9IFtcbiAgICBnbC5MSU5FQVIsXG4gICAgZ2wuTkVBUkVTVF9NSVBNQVBfTElORUFSLFxuICAgIGdsLkxJTkVBUl9NSVBNQVBfTkVBUkVTVCxcbiAgICBnbC5MSU5FQVJfTUlQTUFQX05FQVJFU1RcbiAgXVxuICBmaWx0ZXJUeXBlcyA9IFtcbiAgICBnbC5ORUFSRVNULFxuICAgIGdsLkxJTkVBUixcbiAgICBnbC5ORUFSRVNUX01JUE1BUF9ORUFSRVNULFxuICAgIGdsLk5FQVJFU1RfTUlQTUFQX0xJTkVBUixcbiAgICBnbC5MSU5FQVJfTUlQTUFQX05FQVJFU1QsXG4gICAgZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcbiAgXVxuICB3cmFwVHlwZXMgPSBbXG4gICAgZ2wuUkVQRUFULFxuICAgIGdsLkNMQU1QX1RPX0VER0UsXG4gICAgZ2wuTUlSUk9SRURfUkVQRUFUXG4gIF1cbn1cblxuZnVuY3Rpb24gYWNjZXB0VGV4dHVyZURPTSAob2JqKSB7XG4gIHJldHVybiAoXG4gICAgKCd1bmRlZmluZWQnICE9IHR5cGVvZiBIVE1MQ2FudmFzRWxlbWVudCAmJiBvYmogaW5zdGFuY2VvZiBIVE1MQ2FudmFzRWxlbWVudCkgfHxcbiAgICAoJ3VuZGVmaW5lZCcgIT0gdHlwZW9mIEhUTUxJbWFnZUVsZW1lbnQgJiYgb2JqIGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudCkgfHxcbiAgICAoJ3VuZGVmaW5lZCcgIT0gdHlwZW9mIEhUTUxWaWRlb0VsZW1lbnQgJiYgb2JqIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkgfHxcbiAgICAoJ3VuZGVmaW5lZCcgIT0gdHlwZW9mIEltYWdlRGF0YSAmJiBvYmogaW5zdGFuY2VvZiBJbWFnZURhdGEpKVxufVxuXG52YXIgY29udmVydEZsb2F0VG9VaW50OCA9IGZ1bmN0aW9uKG91dCwgaW5wKSB7XG4gIG9wcy5tdWxzKG91dCwgaW5wLCAyNTUuMClcbn1cblxuZnVuY3Rpb24gcmVzaGFwZVRleHR1cmUodGV4LCB3LCBoKSB7XG4gIHZhciBnbCA9IHRleC5nbFxuICB2YXIgbWF4U2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfVEVYVFVSRV9TSVpFKVxuICBpZih3IDwgMCB8fCB3ID4gbWF4U2l6ZSB8fCBoIDwgMCB8fCBoID4gbWF4U2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHRleHR1cmUgc2l6ZScpXG4gIH1cbiAgdGV4Ll9zaGFwZSA9IFt3LCBoXVxuICB0ZXguYmluZCgpXG4gIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgdGV4LmZvcm1hdCwgdywgaCwgMCwgdGV4LmZvcm1hdCwgdGV4LnR5cGUsIG51bGwpXG4gIHRleC5fbWlwTGV2ZWxzID0gWzBdXG4gIHJldHVybiB0ZXhcbn1cblxuZnVuY3Rpb24gVGV4dHVyZTJEKGdsLCBoYW5kbGUsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSkge1xuICB0aGlzLmdsID0gZ2xcbiAgdGhpcy5oYW5kbGUgPSBoYW5kbGVcbiAgdGhpcy5mb3JtYXQgPSBmb3JtYXRcbiAgdGhpcy50eXBlID0gdHlwZVxuICB0aGlzLl9zaGFwZSA9IFt3aWR0aCwgaGVpZ2h0XVxuICB0aGlzLl9taXBMZXZlbHMgPSBbMF1cbiAgdGhpcy5fbWFnRmlsdGVyID0gZ2wuTkVBUkVTVFxuICB0aGlzLl9taW5GaWx0ZXIgPSBnbC5ORUFSRVNUXG4gIHRoaXMuX3dyYXBTID0gZ2wuQ0xBTVBfVE9fRURHRVxuICB0aGlzLl93cmFwVCA9IGdsLkNMQU1QX1RPX0VER0VcbiAgdGhpcy5fYW5pc29TYW1wbGVzID0gMVxuXG4gIHZhciBwYXJlbnQgPSB0aGlzXG4gIHZhciB3cmFwVmVjdG9yID0gW3RoaXMuX3dyYXBTLCB0aGlzLl93cmFwVF1cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMod3JhcFZlY3RvciwgW1xuICAgIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3dyYXBTXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQud3JhcFMgPSB2XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcGFyZW50Ll93cmFwVFxuICAgICAgfSxcbiAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICByZXR1cm4gcGFyZW50LndyYXBUID0gdlxuICAgICAgfVxuICAgIH1cbiAgXSlcbiAgdGhpcy5fd3JhcFZlY3RvciA9IHdyYXBWZWN0b3JcblxuICB2YXIgc2hhcGVWZWN0b3IgPSBbdGhpcy5fc2hhcGVbMF0sIHRoaXMuX3NoYXBlWzFdXVxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhzaGFwZVZlY3RvciwgW1xuICAgIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3NoYXBlWzBdXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQud2lkdGggPSB2XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcGFyZW50Ll9zaGFwZVsxXVxuICAgICAgfSxcbiAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICByZXR1cm4gcGFyZW50LmhlaWdodCA9IHZcbiAgICAgIH1cbiAgICB9XG4gIF0pXG4gIHRoaXMuX3NoYXBlVmVjdG9yID0gc2hhcGVWZWN0b3Jcbn1cblxudmFyIHByb3RvID0gVGV4dHVyZTJELnByb3RvdHlwZVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhwcm90bywge1xuICBtaW5GaWx0ZXI6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX21pbkZpbHRlclxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICB0aGlzLmJpbmQoKVxuICAgICAgdmFyIGdsID0gdGhpcy5nbFxuICAgICAgaWYodGhpcy50eXBlID09PSBnbC5GTE9BVCAmJiBsaW5lYXJUeXBlcy5pbmRleE9mKHYpID49IDApIHtcbiAgICAgICAgaWYoIWdsLmdldEV4dGVuc2lvbignT0VTX3RleHR1cmVfZmxvYXRfbGluZWFyJykpIHtcbiAgICAgICAgICB2ID0gZ2wuTkVBUkVTVFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZihmaWx0ZXJUeXBlcy5pbmRleE9mKHYpIDwgMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogVW5rbm93biBmaWx0ZXIgbW9kZSAnICsgdilcbiAgICAgIH1cbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCB2KVxuICAgICAgcmV0dXJuIHRoaXMuX21pbkZpbHRlciA9IHZcbiAgICB9XG4gIH0sXG4gIG1hZ0ZpbHRlcjoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbWFnRmlsdGVyXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICAgIHRoaXMuYmluZCgpXG4gICAgICB2YXIgZ2wgPSB0aGlzLmdsXG4gICAgICBpZih0aGlzLnR5cGUgPT09IGdsLkZMT0FUICYmIGxpbmVhclR5cGVzLmluZGV4T2YodikgPj0gMCkge1xuICAgICAgICBpZighZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfdGV4dHVyZV9mbG9hdF9saW5lYXInKSkge1xuICAgICAgICAgIHYgPSBnbC5ORUFSRVNUXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmKGZpbHRlclR5cGVzLmluZGV4T2YodikgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBVbmtub3duIGZpbHRlciBtb2RlICcgKyB2KVxuICAgICAgfVxuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIHYpXG4gICAgICByZXR1cm4gdGhpcy5fbWFnRmlsdGVyID0gdlxuICAgIH1cbiAgfSxcbiAgbWlwU2FtcGxlczoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fYW5pc29TYW1wbGVzXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKGkpIHtcbiAgICAgIHZhciBwc2FtcGxlcyA9IHRoaXMuX2FuaXNvU2FtcGxlc1xuICAgICAgdGhpcy5fYW5pc29TYW1wbGVzID0gTWF0aC5tYXgoaSwgMSl8MFxuICAgICAgaWYocHNhbXBsZXMgIT09IHRoaXMuX2FuaXNvU2FtcGxlcykge1xuICAgICAgICB2YXIgZXh0ID0gdGhpcy5nbC5nZXRFeHRlbnNpb24oJ0VYVF90ZXh0dXJlX2ZpbHRlcl9hbmlzb3Ryb3BpYycpXG4gICAgICAgIGlmKGV4dCkge1xuICAgICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyZih0aGlzLmdsLlRFWFRVUkVfMkQsIGV4dC5URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCwgdGhpcy5fYW5pc29TYW1wbGVzKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fYW5pc29TYW1wbGVzXG4gICAgfVxuICB9LFxuICB3cmFwUzoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcFNcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgdGhpcy5iaW5kKClcbiAgICAgIGlmKHdyYXBUeXBlcy5pbmRleE9mKHYpIDwgMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogVW5rbm93biB3cmFwIG1vZGUgJyArIHYpXG4gICAgICB9XG4gICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLmdsLlRFWFRVUkVfV1JBUF9TLCB2KVxuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBTID0gdlxuICAgIH1cbiAgfSxcbiAgd3JhcFQ6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBUXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICAgIHRoaXMuYmluZCgpXG4gICAgICBpZih3cmFwVHlwZXMuaW5kZXhPZih2KSA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IFVua25vd24gd3JhcCBtb2RlICcgKyB2KVxuICAgICAgfVxuICAgICAgdGhpcy5nbC50ZXhQYXJhbWV0ZXJpKHRoaXMuZ2wuVEVYVFVSRV8yRCwgdGhpcy5nbC5URVhUVVJFX1dSQVBfVCwgdilcbiAgICAgIHJldHVybiB0aGlzLl93cmFwVCA9IHZcbiAgICB9XG4gIH0sXG4gIHdyYXA6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBWZWN0b3JcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgaWYoIUFycmF5LmlzQXJyYXkodikpIHtcbiAgICAgICAgdiA9IFt2LHZdXG4gICAgICB9XG4gICAgICBpZih2Lmxlbmd0aCAhPT0gMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogTXVzdCBzcGVjaWZ5IHdyYXAgbW9kZSBmb3Igcm93cyBhbmQgY29sdW1ucycpXG4gICAgICB9XG4gICAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgICAgaWYod3JhcFR5cGVzLmluZGV4T2YodltpXSkgPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IFVua25vd24gd3JhcCBtb2RlICcgKyB2KVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLl93cmFwUyA9IHZbMF1cbiAgICAgIHRoaXMuX3dyYXBUID0gdlsxXVxuXG4gICAgICB2YXIgZ2wgPSB0aGlzLmdsXG4gICAgICB0aGlzLmJpbmQoKVxuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgdGhpcy5fd3JhcFMpXG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCB0aGlzLl93cmFwVClcblxuICAgICAgcmV0dXJuIHZcbiAgICB9XG4gIH0sXG4gIHNoYXBlOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zaGFwZVZlY3RvclxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih4KSB7XG4gICAgICBpZighQXJyYXkuaXNBcnJheSh4KSkge1xuICAgICAgICB4ID0gW3h8MCx4fDBdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZih4Lmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHRleHR1cmUgc2hhcGUnKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXNoYXBlVGV4dHVyZSh0aGlzLCB4WzBdfDAsIHhbMV18MClcbiAgICAgIHJldHVybiBbeFswXXwwLCB4WzFdfDBdXG4gICAgfVxuICB9LFxuICB3aWR0aDoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2hhcGVbMF1cbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odykge1xuICAgICAgdyA9IHd8MFxuICAgICAgcmVzaGFwZVRleHR1cmUodGhpcywgdywgdGhpcy5fc2hhcGVbMV0pXG4gICAgICByZXR1cm4gd1xuICAgIH1cbiAgfSxcbiAgaGVpZ2h0OiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zaGFwZVsxXVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihoKSB7XG4gICAgICBoID0gaHwwXG4gICAgICByZXNoYXBlVGV4dHVyZSh0aGlzLCB0aGlzLl9zaGFwZVswXSwgaClcbiAgICAgIHJldHVybiBoXG4gICAgfVxuICB9XG59KVxuXG5wcm90by5iaW5kID0gZnVuY3Rpb24odW5pdCkge1xuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIGlmKHVuaXQgIT09IHVuZGVmaW5lZCkge1xuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTAgKyAodW5pdHwwKSlcbiAgfVxuICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLmhhbmRsZSlcbiAgaWYodW5pdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuICh1bml0fDApXG4gIH1cbiAgcmV0dXJuIGdsLmdldFBhcmFtZXRlcihnbC5BQ1RJVkVfVEVYVFVSRSkgLSBnbC5URVhUVVJFMFxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZ2wuZGVsZXRlVGV4dHVyZSh0aGlzLmhhbmRsZSlcbn1cblxucHJvdG8uZ2VuZXJhdGVNaXBtYXAgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5iaW5kKClcbiAgdGhpcy5nbC5nZW5lcmF0ZU1pcG1hcCh0aGlzLmdsLlRFWFRVUkVfMkQpXG5cbiAgLy9VcGRhdGUgbWlwIGxldmVsc1xuICB2YXIgbCA9IE1hdGgubWluKHRoaXMuX3NoYXBlWzBdLCB0aGlzLl9zaGFwZVsxXSlcbiAgZm9yKHZhciBpPTA7IGw+MDsgKytpLCBsPj4+PTEpIHtcbiAgICBpZih0aGlzLl9taXBMZXZlbHMuaW5kZXhPZihpKSA8IDApIHtcbiAgICAgIHRoaXMuX21pcExldmVscy5wdXNoKGkpXG4gICAgfVxuICB9XG59XG5cbnByb3RvLnNldFBpeGVscyA9IGZ1bmN0aW9uKGRhdGEsIHhfb2ZmLCB5X29mZiwgbWlwX2xldmVsKSB7XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgdGhpcy5iaW5kKClcbiAgaWYoQXJyYXkuaXNBcnJheSh4X29mZikpIHtcbiAgICBtaXBfbGV2ZWwgPSB5X29mZlxuICAgIHlfb2ZmID0geF9vZmZbMV18MFxuICAgIHhfb2ZmID0geF9vZmZbMF18MFxuICB9IGVsc2Uge1xuICAgIHhfb2ZmID0geF9vZmYgfHwgMFxuICAgIHlfb2ZmID0geV9vZmYgfHwgMFxuICB9XG4gIG1pcF9sZXZlbCA9IG1pcF9sZXZlbCB8fCAwXG4gIHZhciBkaXJlY3REYXRhID0gYWNjZXB0VGV4dHVyZURPTShkYXRhKSA/IGRhdGEgOiBkYXRhLnJhd1xuICBpZihkaXJlY3REYXRhKSB7XG4gICAgdmFyIG5lZWRzTWlwID0gdGhpcy5fbWlwTGV2ZWxzLmluZGV4T2YobWlwX2xldmVsKSA8IDBcbiAgICBpZihuZWVkc01pcCkge1xuICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCB0aGlzLmZvcm1hdCwgdGhpcy5mb3JtYXQsIHRoaXMudHlwZSwgZGlyZWN0RGF0YSlcbiAgICAgIHRoaXMuX21pcExldmVscy5wdXNoKG1pcF9sZXZlbClcbiAgICB9IGVsc2Uge1xuICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCBtaXBfbGV2ZWwsIHhfb2ZmLCB5X29mZiwgdGhpcy5mb3JtYXQsIHRoaXMudHlwZSwgZGlyZWN0RGF0YSlcbiAgICB9XG4gIH0gZWxzZSBpZihkYXRhLnNoYXBlICYmIGRhdGEuc3RyaWRlICYmIGRhdGEuZGF0YSkge1xuICAgIGlmKGRhdGEuc2hhcGUubGVuZ3RoIDwgMiB8fFxuICAgICAgIHhfb2ZmICsgZGF0YS5zaGFwZVsxXSA+IHRoaXMuX3NoYXBlWzFdPj4+bWlwX2xldmVsIHx8XG4gICAgICAgeV9vZmYgKyBkYXRhLnNoYXBlWzBdID4gdGhpcy5fc2hhcGVbMF0+Pj5taXBfbGV2ZWwgfHxcbiAgICAgICB4X29mZiA8IDAgfHxcbiAgICAgICB5X29mZiA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBUZXh0dXJlIGRpbWVuc2lvbnMgYXJlIG91dCBvZiBib3VuZHMnKVxuICAgIH1cbiAgICB0ZXhTdWJJbWFnZUFycmF5KGdsLCB4X29mZiwgeV9vZmYsIG1pcF9sZXZlbCwgdGhpcy5mb3JtYXQsIHRoaXMudHlwZSwgdGhpcy5fbWlwTGV2ZWxzLCBkYXRhKVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBVbnN1cHBvcnRlZCBkYXRhIHR5cGUnKVxuICB9XG59XG5cblxuZnVuY3Rpb24gaXNQYWNrZWQoc2hhcGUsIHN0cmlkZSkge1xuICBpZihzaGFwZS5sZW5ndGggPT09IDMpIHtcbiAgICByZXR1cm4gIChzdHJpZGVbMl0gPT09IDEpICYmXG4gICAgICAgICAgICAoc3RyaWRlWzFdID09PSBzaGFwZVswXSpzaGFwZVsyXSkgJiZcbiAgICAgICAgICAgIChzdHJpZGVbMF0gPT09IHNoYXBlWzJdKVxuICB9XG4gIHJldHVybiAgKHN0cmlkZVswXSA9PT0gMSkgJiZcbiAgICAgICAgICAoc3RyaWRlWzFdID09PSBzaGFwZVswXSlcbn1cblxuZnVuY3Rpb24gdGV4U3ViSW1hZ2VBcnJheShnbCwgeF9vZmYsIHlfb2ZmLCBtaXBfbGV2ZWwsIGNmb3JtYXQsIGN0eXBlLCBtaXBMZXZlbHMsIGFycmF5KSB7XG4gIHZhciBkdHlwZSA9IGFycmF5LmR0eXBlXG4gIHZhciBzaGFwZSA9IGFycmF5LnNoYXBlLnNsaWNlKClcbiAgaWYoc2hhcGUubGVuZ3RoIDwgMiB8fCBzaGFwZS5sZW5ndGggPiAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgbmRhcnJheSwgbXVzdCBiZSAyZCBvciAzZCcpXG4gIH1cbiAgdmFyIHR5cGUgPSAwLCBmb3JtYXQgPSAwXG4gIHZhciBwYWNrZWQgPSBpc1BhY2tlZChzaGFwZSwgYXJyYXkuc3RyaWRlLnNsaWNlKCkpXG4gIGlmKGR0eXBlID09PSAnZmxvYXQzMicpIHtcbiAgICB0eXBlID0gZ2wuRkxPQVRcbiAgfSBlbHNlIGlmKGR0eXBlID09PSAnZmxvYXQ2NCcpIHtcbiAgICB0eXBlID0gZ2wuRkxPQVRcbiAgICBwYWNrZWQgPSBmYWxzZVxuICAgIGR0eXBlID0gJ2Zsb2F0MzInXG4gIH0gZWxzZSBpZihkdHlwZSA9PT0gJ3VpbnQ4Jykge1xuICAgIHR5cGUgPSBnbC5VTlNJR05FRF9CWVRFXG4gIH0gZWxzZSB7XG4gICAgdHlwZSA9IGdsLlVOU0lHTkVEX0JZVEVcbiAgICBwYWNrZWQgPSBmYWxzZVxuICAgIGR0eXBlID0gJ3VpbnQ4J1xuICB9XG4gIHZhciBjaGFubmVscyA9IDFcbiAgaWYoc2hhcGUubGVuZ3RoID09PSAyKSB7XG4gICAgZm9ybWF0ID0gZ2wuTFVNSU5BTkNFXG4gICAgc2hhcGUgPSBbc2hhcGVbMF0sIHNoYXBlWzFdLCAxXVxuICAgIGFycmF5ID0gbmRhcnJheShhcnJheS5kYXRhLCBzaGFwZSwgW2FycmF5LnN0cmlkZVswXSwgYXJyYXkuc3RyaWRlWzFdLCAxXSwgYXJyYXkub2Zmc2V0KVxuICB9IGVsc2UgaWYoc2hhcGUubGVuZ3RoID09PSAzKSB7XG4gICAgaWYoc2hhcGVbMl0gPT09IDEpIHtcbiAgICAgIGZvcm1hdCA9IGdsLkFMUEhBXG4gICAgfSBlbHNlIGlmKHNoYXBlWzJdID09PSAyKSB7XG4gICAgICBmb3JtYXQgPSBnbC5MVU1JTkFOQ0VfQUxQSEFcbiAgICB9IGVsc2UgaWYoc2hhcGVbMl0gPT09IDMpIHtcbiAgICAgIGZvcm1hdCA9IGdsLlJHQlxuICAgIH0gZWxzZSBpZihzaGFwZVsyXSA9PT0gNCkge1xuICAgICAgZm9ybWF0ID0gZ2wuUkdCQVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCBzaGFwZSBmb3IgcGl4ZWwgY29vcmRzJylcbiAgICB9XG4gICAgY2hhbm5lbHMgPSBzaGFwZVsyXVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHNoYXBlIGZvciB0ZXh0dXJlJylcbiAgfVxuICAvL0ZvciAxLWNoYW5uZWwgdGV4dHVyZXMgYWxsb3cgY29udmVyc2lvbiBiZXR3ZWVuIGZvcm1hdHNcbiAgaWYoKGZvcm1hdCAgPT09IGdsLkxVTUlOQU5DRSB8fCBmb3JtYXQgID09PSBnbC5BTFBIQSkgJiZcbiAgICAgKGNmb3JtYXQgPT09IGdsLkxVTUlOQU5DRSB8fCBjZm9ybWF0ID09PSBnbC5BTFBIQSkpIHtcbiAgICBmb3JtYXQgPSBjZm9ybWF0XG4gIH1cbiAgaWYoZm9ybWF0ICE9PSBjZm9ybWF0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEluY29tcGF0aWJsZSB0ZXh0dXJlIGZvcm1hdCBmb3Igc2V0UGl4ZWxzJylcbiAgfVxuICB2YXIgc2l6ZSA9IGFycmF5LnNpemVcbiAgdmFyIG5lZWRzTWlwID0gbWlwTGV2ZWxzLmluZGV4T2YobWlwX2xldmVsKSA8IDBcbiAgaWYobmVlZHNNaXApIHtcbiAgICBtaXBMZXZlbHMucHVzaChtaXBfbGV2ZWwpXG4gIH1cbiAgaWYodHlwZSA9PT0gY3R5cGUgJiYgcGFja2VkKSB7XG4gICAgLy9BcnJheSBkYXRhIHR5cGVzIGFyZSBjb21wYXRpYmxlLCBjYW4gZGlyZWN0bHkgY29weSBpbnRvIHRleHR1cmVcbiAgICBpZihhcnJheS5vZmZzZXQgPT09IDAgJiYgYXJyYXkuZGF0YS5sZW5ndGggPT09IHNpemUpIHtcbiAgICAgIGlmKG5lZWRzTWlwKSB7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgbWlwX2xldmVsLCBjZm9ybWF0LCBzaGFwZVswXSwgc2hhcGVbMV0sIDAsIGNmb3JtYXQsIGN0eXBlLCBhcnJheS5kYXRhKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCBtaXBfbGV2ZWwsIHhfb2ZmLCB5X29mZiwgc2hhcGVbMF0sIHNoYXBlWzFdLCBjZm9ybWF0LCBjdHlwZSwgYXJyYXkuZGF0YSlcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYobmVlZHNNaXApIHtcbiAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCBtaXBfbGV2ZWwsIGNmb3JtYXQsIHNoYXBlWzBdLCBzaGFwZVsxXSwgMCwgY2Zvcm1hdCwgY3R5cGUsIGFycmF5LmRhdGEuc3ViYXJyYXkoYXJyYXkub2Zmc2V0LCBhcnJheS5vZmZzZXQrc2l6ZSkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgeF9vZmYsIHlfb2ZmLCBzaGFwZVswXSwgc2hhcGVbMV0sIGNmb3JtYXQsIGN0eXBlLCBhcnJheS5kYXRhLnN1YmFycmF5KGFycmF5Lm9mZnNldCwgYXJyYXkub2Zmc2V0K3NpemUpKVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvL05lZWQgdG8gZG8gdHlwZSBjb252ZXJzaW9uIHRvIHBhY2sgZGF0YSBpbnRvIGJ1ZmZlclxuICAgIHZhciBwYWNrX2J1ZmZlclxuICAgIGlmKGN0eXBlID09PSBnbC5GTE9BVCkge1xuICAgICAgcGFja19idWZmZXIgPSBwb29sLm1hbGxvY0Zsb2F0MzIoc2l6ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgcGFja19idWZmZXIgPSBwb29sLm1hbGxvY1VpbnQ4KHNpemUpXG4gICAgfVxuICAgIHZhciBwYWNrX3ZpZXcgPSBuZGFycmF5KHBhY2tfYnVmZmVyLCBzaGFwZSwgW3NoYXBlWzJdLCBzaGFwZVsyXSpzaGFwZVswXSwgMV0pXG4gICAgaWYodHlwZSA9PT0gZ2wuRkxPQVQgJiYgY3R5cGUgPT09IGdsLlVOU0lHTkVEX0JZVEUpIHtcbiAgICAgIGNvbnZlcnRGbG9hdFRvVWludDgocGFja192aWV3LCBhcnJheSlcbiAgICB9IGVsc2Uge1xuICAgICAgb3BzLmFzc2lnbihwYWNrX3ZpZXcsIGFycmF5KVxuICAgIH1cbiAgICBpZihuZWVkc01pcCkge1xuICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCBtaXBfbGV2ZWwsIGNmb3JtYXQsIHNoYXBlWzBdLCBzaGFwZVsxXSwgMCwgY2Zvcm1hdCwgY3R5cGUsIHBhY2tfYnVmZmVyLnN1YmFycmF5KDAsIHNpemUpKVxuICAgIH0gZWxzZSB7XG4gICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgeF9vZmYsIHlfb2ZmLCBzaGFwZVswXSwgc2hhcGVbMV0sIGNmb3JtYXQsIGN0eXBlLCBwYWNrX2J1ZmZlci5zdWJhcnJheSgwLCBzaXplKSlcbiAgICB9XG4gICAgaWYoY3R5cGUgPT09IGdsLkZMT0FUKSB7XG4gICAgICBwb29sLmZyZWVGbG9hdDMyKHBhY2tfYnVmZmVyKVxuICAgIH0gZWxzZSB7XG4gICAgICBwb29sLmZyZWVVaW50OChwYWNrX2J1ZmZlcilcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5pdFRleHR1cmUoZ2wpIHtcbiAgdmFyIHRleCA9IGdsLmNyZWF0ZVRleHR1cmUoKVxuICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0ZXgpXG4gIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5ORUFSRVNUKVxuICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTkVBUkVTVClcbiAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgZ2wuQ0xBTVBfVE9fRURHRSlcbiAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSlcbiAgcmV0dXJuIHRleFxufVxuXG5mdW5jdGlvbiBjcmVhdGVUZXh0dXJlU2hhcGUoZ2wsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSkge1xuICB2YXIgbWF4VGV4dHVyZVNpemUgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuTUFYX1RFWFRVUkVfU0laRSlcbiAgaWYod2lkdGggPCAwIHx8IHdpZHRoID4gbWF4VGV4dHVyZVNpemUgfHwgaGVpZ2h0IDwgMCB8fCBoZWlnaHQgID4gbWF4VGV4dHVyZVNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCB0ZXh0dXJlIHNoYXBlJylcbiAgfVxuICBpZih0eXBlID09PSBnbC5GTE9BVCAmJiAhZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfdGV4dHVyZV9mbG9hdCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEZsb2F0aW5nIHBvaW50IHRleHR1cmVzIG5vdCBzdXBwb3J0ZWQgb24gdGhpcyBwbGF0Zm9ybScpXG4gIH1cbiAgdmFyIHRleCA9IGluaXRUZXh0dXJlKGdsKVxuICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgMCwgZm9ybWF0LCB0eXBlLCBudWxsKVxuICByZXR1cm4gbmV3IFRleHR1cmUyRChnbCwgdGV4LCB3aWR0aCwgaGVpZ2h0LCBmb3JtYXQsIHR5cGUpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVET00oZ2wsIGRpcmVjdERhdGEsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSkge1xuICB2YXIgdGV4ID0gaW5pdFRleHR1cmUoZ2wpXG4gIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZm9ybWF0LCBmb3JtYXQsIHR5cGUsIGRpcmVjdERhdGEpXG4gIHJldHVybiBuZXcgVGV4dHVyZTJEKGdsLCB0ZXgsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSlcbn1cblxuLy9DcmVhdGVzIGEgdGV4dHVyZSBmcm9tIGFuIG5kYXJyYXlcbmZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVBcnJheShnbCwgYXJyYXkpIHtcbiAgdmFyIGR0eXBlID0gYXJyYXkuZHR5cGVcbiAgdmFyIHNoYXBlID0gYXJyYXkuc2hhcGUuc2xpY2UoKVxuICB2YXIgbWF4U2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfVEVYVFVSRV9TSVpFKVxuICBpZihzaGFwZVswXSA8IDAgfHwgc2hhcGVbMF0gPiBtYXhTaXplIHx8IHNoYXBlWzFdIDwgMCB8fCBzaGFwZVsxXSA+IG1heFNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCB0ZXh0dXJlIHNpemUnKVxuICB9XG4gIHZhciBwYWNrZWQgPSBpc1BhY2tlZChzaGFwZSwgYXJyYXkuc3RyaWRlLnNsaWNlKCkpXG4gIHZhciB0eXBlID0gMFxuICBpZihkdHlwZSA9PT0gJ2Zsb2F0MzInKSB7XG4gICAgdHlwZSA9IGdsLkZMT0FUXG4gIH0gZWxzZSBpZihkdHlwZSA9PT0gJ2Zsb2F0NjQnKSB7XG4gICAgdHlwZSA9IGdsLkZMT0FUXG4gICAgcGFja2VkID0gZmFsc2VcbiAgICBkdHlwZSA9ICdmbG9hdDMyJ1xuICB9IGVsc2UgaWYoZHR5cGUgPT09ICd1aW50OCcpIHtcbiAgICB0eXBlID0gZ2wuVU5TSUdORURfQllURVxuICB9IGVsc2Uge1xuICAgIHR5cGUgPSBnbC5VTlNJR05FRF9CWVRFXG4gICAgcGFja2VkID0gZmFsc2VcbiAgICBkdHlwZSA9ICd1aW50OCdcbiAgfVxuICB2YXIgZm9ybWF0ID0gMFxuICBpZihzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICBmb3JtYXQgPSBnbC5MVU1JTkFOQ0VcbiAgICBzaGFwZSA9IFtzaGFwZVswXSwgc2hhcGVbMV0sIDFdXG4gICAgYXJyYXkgPSBuZGFycmF5KGFycmF5LmRhdGEsIHNoYXBlLCBbYXJyYXkuc3RyaWRlWzBdLCBhcnJheS5zdHJpZGVbMV0sIDFdLCBhcnJheS5vZmZzZXQpXG4gIH0gZWxzZSBpZihzaGFwZS5sZW5ndGggPT09IDMpIHtcbiAgICBpZihzaGFwZVsyXSA9PT0gMSkge1xuICAgICAgZm9ybWF0ID0gZ2wuQUxQSEFcbiAgICB9IGVsc2UgaWYoc2hhcGVbMl0gPT09IDIpIHtcbiAgICAgIGZvcm1hdCA9IGdsLkxVTUlOQU5DRV9BTFBIQVxuICAgIH0gZWxzZSBpZihzaGFwZVsyXSA9PT0gMykge1xuICAgICAgZm9ybWF0ID0gZ2wuUkdCXG4gICAgfSBlbHNlIGlmKHNoYXBlWzJdID09PSA0KSB7XG4gICAgICBmb3JtYXQgPSBnbC5SR0JBXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHNoYXBlIGZvciBwaXhlbCBjb29yZHMnKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCBzaGFwZSBmb3IgdGV4dHVyZScpXG4gIH1cbiAgaWYodHlwZSA9PT0gZ2wuRkxPQVQgJiYgIWdsLmdldEV4dGVuc2lvbignT0VTX3RleHR1cmVfZmxvYXQnKSkge1xuICAgIHR5cGUgPSBnbC5VTlNJR05FRF9CWVRFXG4gICAgcGFja2VkID0gZmFsc2VcbiAgfVxuICB2YXIgYnVmZmVyLCBidWZfc3RvcmVcbiAgdmFyIHNpemUgPSBhcnJheS5zaXplXG4gIGlmKCFwYWNrZWQpIHtcbiAgICB2YXIgc3RyaWRlID0gW3NoYXBlWzJdLCBzaGFwZVsyXSpzaGFwZVswXSwgMV1cbiAgICBidWZfc3RvcmUgPSBwb29sLm1hbGxvYyhzaXplLCBkdHlwZSlcbiAgICB2YXIgYnVmX2FycmF5ID0gbmRhcnJheShidWZfc3RvcmUsIHNoYXBlLCBzdHJpZGUsIDApXG4gICAgaWYoKGR0eXBlID09PSAnZmxvYXQzMicgfHwgZHR5cGUgPT09ICdmbG9hdDY0JykgJiYgdHlwZSA9PT0gZ2wuVU5TSUdORURfQllURSkge1xuICAgICAgY29udmVydEZsb2F0VG9VaW50OChidWZfYXJyYXksIGFycmF5KVxuICAgIH0gZWxzZSB7XG4gICAgICBvcHMuYXNzaWduKGJ1Zl9hcnJheSwgYXJyYXkpXG4gICAgfVxuICAgIGJ1ZmZlciA9IGJ1Zl9zdG9yZS5zdWJhcnJheSgwLCBzaXplKVxuICB9IGVsc2UgaWYgKGFycmF5Lm9mZnNldCA9PT0gMCAmJiBhcnJheS5kYXRhLmxlbmd0aCA9PT0gc2l6ZSkge1xuICAgIGJ1ZmZlciA9IGFycmF5LmRhdGFcbiAgfSBlbHNlIHtcbiAgICBidWZmZXIgPSBhcnJheS5kYXRhLnN1YmFycmF5KGFycmF5Lm9mZnNldCwgYXJyYXkub2Zmc2V0ICsgc2l6ZSlcbiAgfVxuICB2YXIgdGV4ID0gaW5pdFRleHR1cmUoZ2wpXG4gIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZm9ybWF0LCBzaGFwZVswXSwgc2hhcGVbMV0sIDAsIGZvcm1hdCwgdHlwZSwgYnVmZmVyKVxuICBpZighcGFja2VkKSB7XG4gICAgcG9vbC5mcmVlKGJ1Zl9zdG9yZSlcbiAgfVxuICByZXR1cm4gbmV3IFRleHR1cmUyRChnbCwgdGV4LCBzaGFwZVswXSwgc2hhcGVbMV0sIGZvcm1hdCwgdHlwZSlcbn1cblxuZnVuY3Rpb24gY3JlYXRlVGV4dHVyZTJEKGdsKSB7XG4gIGlmKGFyZ3VtZW50cy5sZW5ndGggPD0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBNaXNzaW5nIGFyZ3VtZW50cyBmb3IgdGV4dHVyZTJkIGNvbnN0cnVjdG9yJylcbiAgfVxuICBpZighbGluZWFyVHlwZXMpIHtcbiAgICBsYXp5SW5pdExpbmVhclR5cGVzKGdsKVxuICB9XG4gIGlmKHR5cGVvZiBhcmd1bWVudHNbMV0gPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGNyZWF0ZVRleHR1cmVTaGFwZShnbCwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXXx8Z2wuUkdCQSwgYXJndW1lbnRzWzRdfHxnbC5VTlNJR05FRF9CWVRFKVxuICB9XG4gIGlmKEFycmF5LmlzQXJyYXkoYXJndW1lbnRzWzFdKSkge1xuICAgIHJldHVybiBjcmVhdGVUZXh0dXJlU2hhcGUoZ2wsIGFyZ3VtZW50c1sxXVswXXwwLCBhcmd1bWVudHNbMV1bMV18MCwgYXJndW1lbnRzWzJdfHxnbC5SR0JBLCBhcmd1bWVudHNbM118fGdsLlVOU0lHTkVEX0JZVEUpXG4gIH1cbiAgaWYodHlwZW9mIGFyZ3VtZW50c1sxXSA9PT0gJ29iamVjdCcpIHtcbiAgICB2YXIgb2JqID0gYXJndW1lbnRzWzFdXG4gICAgdmFyIGRpcmVjdERhdGEgPSBhY2NlcHRUZXh0dXJlRE9NKG9iaikgPyBvYmogOiBvYmoucmF3XG4gICAgaWYgKGRpcmVjdERhdGEpIHtcbiAgICAgIHJldHVybiBjcmVhdGVUZXh0dXJlRE9NKGdsLCBkaXJlY3REYXRhLCBvYmoud2lkdGh8MCwgb2JqLmhlaWdodHwwLCBhcmd1bWVudHNbMl18fGdsLlJHQkEsIGFyZ3VtZW50c1szXXx8Z2wuVU5TSUdORURfQllURSlcbiAgICB9IGVsc2UgaWYob2JqLnNoYXBlICYmIG9iai5kYXRhICYmIG9iai5zdHJpZGUpIHtcbiAgICAgIHJldHVybiBjcmVhdGVUZXh0dXJlQXJyYXkoZ2wsIG9iailcbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgYXJndW1lbnRzIGZvciB0ZXh0dXJlMmQgY29uc3RydWN0b3InKVxufVxuIiwiLyoqIEBtb2R1bGUgIGdsLXV0aWwvY29udGV4dCAqL1xyXG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBwaWNrID0gcmVxdWlyZSgncGljay1ieS1hbGlhcycpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNldENvbnRleHQgKG8pIHtcclxuXHRpZiAoIW8pIG8gPSB7fVxyXG5cdGVsc2UgaWYgKHR5cGVvZiBvID09PSAnc3RyaW5nJykgbyA9IHtjb250YWluZXI6IG99XHJcblxyXG5cdC8vIEhUTUxDYW52YXNFbGVtZW50XHJcblx0aWYgKGlzQ2FudmFzKG8pKSB7XHJcblx0XHRvID0ge2NvbnRhaW5lcjogb31cclxuXHR9XHJcblx0Ly8gSFRNTEVsZW1lbnRcclxuXHRlbHNlIGlmIChpc0VsZW1lbnQobykpIHtcclxuXHRcdG8gPSB7Y29udGFpbmVyOiBvfVxyXG5cdH1cclxuXHQvLyBXZWJHTENvbnRleHRcclxuXHRlbHNlIGlmIChpc0NvbnRleHQobykpIHtcclxuXHRcdG8gPSB7Z2w6IG99XHJcblx0fVxyXG5cdC8vIG9wdGlvbnMgb2JqZWN0XHJcblx0ZWxzZSB7XHJcblx0XHRvID0gcGljayhvLCB7XHJcblx0XHRcdGNvbnRhaW5lcjogJ2NvbnRhaW5lciB0YXJnZXQgZWxlbWVudCBlbCBjYW52YXMgaG9sZGVyIHBhcmVudCBwYXJlbnROb2RlIHdyYXBwZXIgdXNlIHJlZiByb290IG5vZGUnLFxyXG5cdFx0XHRnbDogJ2dsIGNvbnRleHQgd2ViZ2wgZ2xDb250ZXh0JyxcclxuXHRcdFx0YXR0cnM6ICdhdHRyaWJ1dGVzIGF0dHJzIGNvbnRleHRBdHRyaWJ1dGVzJyxcclxuXHRcdFx0cGl4ZWxSYXRpbzogJ3BpeGVsUmF0aW8gcHhSYXRpbyBweCByYXRpbyBweHJhdGlvIHBpeGVscmF0aW8nXHJcblx0XHR9LCB0cnVlKVxyXG5cdH1cclxuXHJcblx0aWYgKCFvLnBpeGVsUmF0aW8pIG8ucGl4ZWxSYXRpbyA9IHdpbmRvdy5waXhlbFJhdGlvIHx8IDFcclxuXHJcblx0Ly8gbWFrZSBzdXJlIHRoZXJlIGlzIGNvbnRhaW5lciBhbmQgY2FudmFzXHJcblx0aWYgKG8uZ2wpIHtcclxuXHRcdHJldHVybiBvLmdsXHJcblx0fVxyXG5cdGlmIChvLmNhbnZhcykge1xyXG5cdFx0by5jb250YWluZXIgPSBvLmNhbnZhcy5wYXJlbnROb2RlXHJcblx0fVxyXG5cdGlmIChvLmNvbnRhaW5lcikge1xyXG5cdFx0aWYgKHR5cGVvZiBvLmNvbnRhaW5lciA9PT0gJ3N0cmluZycpIHtcclxuXHRcdFx0dmFyIGMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKG8uY29udGFpbmVyKVxyXG5cdFx0XHRpZiAoIWMpIHRocm93IEVycm9yKCdFbGVtZW50ICcgKyBvLmNvbnRhaW5lciArICcgaXMgbm90IGZvdW5kJylcclxuXHRcdFx0by5jb250YWluZXIgPSBjXHJcblx0XHR9XHJcblx0XHRpZiAoaXNDYW52YXMoby5jb250YWluZXIpKSB7XHJcblx0XHRcdG8uY2FudmFzID0gby5jb250YWluZXJcclxuXHRcdFx0by5jb250YWluZXIgPSBvLmNhbnZhcy5wYXJlbnROb2RlXHJcblx0XHR9XHJcblx0XHRlbHNlIGlmICghby5jYW52YXMpIHtcclxuXHRcdFx0by5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxyXG5cdFx0XHRvLmNvbnRhaW5lci5hcHBlbmRDaGlsZChvLmNhbnZhcylcclxuXHRcdFx0cmVzaXplKG8pXHJcblx0XHR9XHJcblx0fVxyXG5cdC8vIGJsYW5rIG5ldyBjYW52YXNcclxuXHRlbHNlIGlmICghby5jYW52YXMpIHtcclxuXHRcdG8uY29udGFpbmVyID0gZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnRcclxuXHRcdG8uY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcclxuXHRcdG8uY2FudmFzLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJ1xyXG5cdFx0by5jYW52YXMuc3R5bGUudG9wID0gMFxyXG5cdFx0by5jYW52YXMuc3R5bGUubGVmdCA9IDBcclxuXHRcdG8uY29udGFpbmVyLmFwcGVuZENoaWxkKG8uY2FudmFzKVxyXG5cdFx0cmVzaXplKG8pXHJcblx0fVxyXG5cclxuXHQvLyBtYWtlIHN1cmUgdGhlcmUgaXMgY29udGV4dFxyXG5cdGlmICghby5nbCkge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0by5nbCA9IG8uY2FudmFzLmdldENvbnRleHQoJ3dlYmdsJywgby5hdHRycylcclxuXHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRvLmdsID0gby5jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgby5hdHRycylcclxuXHRcdFx0fVxyXG5cdFx0XHRjYXRjaCAoZSkge1xyXG5cdFx0XHRcdG8uZ2wgPSBvLmNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbC1leHBlcmltZW50YWwnLCBvLmF0dHJzKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gby5nbFxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcmVzaXplIChvKSB7XHJcblx0aWYgKG8uY29udGFpbmVyKSB7XHJcblx0XHRpZiAoby5jb250YWluZXIgPT0gZG9jdW1lbnQuYm9keSkge1xyXG5cdFx0XHRpZiAoIWRvY3VtZW50LmJvZHkuc3R5bGUud2lkdGgpIG8uY2FudmFzLndpZHRoID0gby53aWR0aCB8fCAoby5waXhlbFJhdGlvICogd2luZG93LmlubmVyV2lkdGgpXHJcblx0XHRcdGlmICghZG9jdW1lbnQuYm9keS5zdHlsZS5oZWlnaHQpIG8uY2FudmFzLmhlaWdodCA9IG8uaGVpZ2h0IHx8IChvLnBpeGVsUmF0aW8gKiB3aW5kb3cuaW5uZXJIZWlnaHQpXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0dmFyIGJvdW5kcyA9IG8uY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpXHJcblx0XHRcdG8uY2FudmFzLndpZHRoID0gby53aWR0aCB8fCAoYm91bmRzLnJpZ2h0IC0gYm91bmRzLmxlZnQpXHJcblx0XHRcdG8uY2FudmFzLmhlaWdodCA9IG8uaGVpZ2h0IHx8IChib3VuZHMuYm90dG9tIC0gYm91bmRzLnRvcClcclxuXHRcdH1cclxuXHR9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGlzQ2FudmFzIChlKSB7XHJcblx0cmV0dXJuIHR5cGVvZiBlLmdldENvbnRleHQgPT09ICdmdW5jdGlvbidcclxuXHRcdCYmICd3aWR0aCcgaW4gZVxyXG5cdFx0JiYgJ2hlaWdodCcgaW4gZVxyXG59XHJcblxyXG5mdW5jdGlvbiBpc0VsZW1lbnQgKGUpIHtcclxuXHRyZXR1cm4gdHlwZW9mIGUubm9kZU5hbWUgPT09ICdzdHJpbmcnICYmXHJcblx0XHR0eXBlb2YgZS5hcHBlbmRDaGlsZCA9PT0gJ2Z1bmN0aW9uJyAmJlxyXG5cdFx0dHlwZW9mIGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID09PSAnZnVuY3Rpb24nXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGlzQ29udGV4dCAoZSkge1xyXG5cdHJldHVybiB0eXBlb2YgZS5kcmF3QXJyYXlzID09PSAnZnVuY3Rpb24nIHx8XHJcblx0XHR0eXBlb2YgZS5kcmF3RWxlbWVudHMgPT09ICdmdW5jdGlvbidcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIlxuXG5mdW5jdGlvbiBkb0JpbmQoZ2wsIGVsZW1lbnRzLCBhdHRyaWJ1dGVzKSB7XG4gIGlmKGVsZW1lbnRzKSB7XG4gICAgZWxlbWVudHMuYmluZCgpXG4gIH0gZWxzZSB7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgbnVsbClcbiAgfVxuICB2YXIgbmF0dHJpYnMgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuTUFYX1ZFUlRFWF9BVFRSSUJTKXwwXG4gIGlmKGF0dHJpYnV0ZXMpIHtcbiAgICBpZihhdHRyaWJ1dGVzLmxlbmd0aCA+IG5hdHRyaWJzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC12YW86IFRvbyBtYW55IHZlcnRleCBhdHRyaWJ1dGVzXCIpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPGF0dHJpYnV0ZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBhdHRyaWIgPSBhdHRyaWJ1dGVzW2ldXG4gICAgICBpZihhdHRyaWIuYnVmZmVyKSB7XG4gICAgICAgIHZhciBidWZmZXIgPSBhdHRyaWIuYnVmZmVyXG4gICAgICAgIHZhciBzaXplID0gYXR0cmliLnNpemUgfHwgNFxuICAgICAgICB2YXIgdHlwZSA9IGF0dHJpYi50eXBlIHx8IGdsLkZMT0FUXG4gICAgICAgIHZhciBub3JtYWxpemVkID0gISFhdHRyaWIubm9ybWFsaXplZFxuICAgICAgICB2YXIgc3RyaWRlID0gYXR0cmliLnN0cmlkZSB8fCAwXG4gICAgICAgIHZhciBvZmZzZXQgPSBhdHRyaWIub2Zmc2V0IHx8IDBcbiAgICAgICAgYnVmZmVyLmJpbmQoKVxuICAgICAgICBnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShpKVxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGksIHNpemUsIHR5cGUsIG5vcm1hbGl6ZWQsIHN0cmlkZSwgb2Zmc2V0KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYodHlwZW9mIGF0dHJpYiA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgIGdsLnZlcnRleEF0dHJpYjFmKGksIGF0dHJpYilcbiAgICAgICAgfSBlbHNlIGlmKGF0dHJpYi5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBnbC52ZXJ0ZXhBdHRyaWIxZihpLCBhdHRyaWJbMF0pXG4gICAgICAgIH0gZWxzZSBpZihhdHRyaWIubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgZ2wudmVydGV4QXR0cmliMmYoaSwgYXR0cmliWzBdLCBhdHRyaWJbMV0pXG4gICAgICAgIH0gZWxzZSBpZihhdHRyaWIubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgZ2wudmVydGV4QXR0cmliM2YoaSwgYXR0cmliWzBdLCBhdHRyaWJbMV0sIGF0dHJpYlsyXSlcbiAgICAgICAgfSBlbHNlIGlmKGF0dHJpYi5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICBnbC52ZXJ0ZXhBdHRyaWI0ZihpLCBhdHRyaWJbMF0sIGF0dHJpYlsxXSwgYXR0cmliWzJdLCBhdHRyaWJbM10pXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZ2wtdmFvOiBJbnZhbGlkIHZlcnRleCBhdHRyaWJ1dGVcIilcbiAgICAgICAgfVxuICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSlcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yKDsgaTxuYXR0cmliczsgKytpKSB7XG4gICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIG51bGwpXG4gICAgZm9yKHZhciBpPTA7IGk8bmF0dHJpYnM7ICsraSkge1xuICAgICAgZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpXG4gICAgfVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZG9CaW5kIiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGJpbmRBdHRyaWJzID0gcmVxdWlyZShcIi4vZG8tYmluZC5qc1wiKVxuXG5mdW5jdGlvbiBWQU9FbXVsYXRlZChnbCkge1xuICB0aGlzLmdsID0gZ2xcbiAgdGhpcy5fZWxlbWVudHMgPSBudWxsXG4gIHRoaXMuX2F0dHJpYnV0ZXMgPSBudWxsXG4gIHRoaXMuX2VsZW1lbnRzVHlwZSA9IGdsLlVOU0lHTkVEX1NIT1JUXG59XG5cblZBT0VtdWxhdGVkLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIGJpbmRBdHRyaWJzKHRoaXMuZ2wsIHRoaXMuX2VsZW1lbnRzLCB0aGlzLl9hdHRyaWJ1dGVzKVxufVxuXG5WQU9FbXVsYXRlZC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24oYXR0cmlidXRlcywgZWxlbWVudHMsIGVsZW1lbnRzVHlwZSkge1xuICB0aGlzLl9lbGVtZW50cyA9IGVsZW1lbnRzXG4gIHRoaXMuX2F0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzXG4gIHRoaXMuX2VsZW1lbnRzVHlwZSA9IGVsZW1lbnRzVHlwZSB8fCB0aGlzLmdsLlVOU0lHTkVEX1NIT1JUXG59XG5cblZBT0VtdWxhdGVkLnByb3RvdHlwZS5kaXNwb3NlID0gZnVuY3Rpb24oKSB7IH1cblZBT0VtdWxhdGVkLnByb3RvdHlwZS51bmJpbmQgPSBmdW5jdGlvbigpIHsgfVxuXG5WQU9FbXVsYXRlZC5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uKG1vZGUsIGNvdW50LCBvZmZzZXQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHx8IDBcbiAgdmFyIGdsID0gdGhpcy5nbFxuICBpZih0aGlzLl9lbGVtZW50cykge1xuICAgIGdsLmRyYXdFbGVtZW50cyhtb2RlLCBjb3VudCwgdGhpcy5fZWxlbWVudHNUeXBlLCBvZmZzZXQpXG4gIH0gZWxzZSB7XG4gICAgZ2wuZHJhd0FycmF5cyhtb2RlLCBvZmZzZXQsIGNvdW50KVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVZBT0VtdWxhdGVkKGdsKSB7XG4gIHJldHVybiBuZXcgVkFPRW11bGF0ZWQoZ2wpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVkFPRW11bGF0ZWQiLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgYmluZEF0dHJpYnMgPSByZXF1aXJlKFwiLi9kby1iaW5kLmpzXCIpXG5cbmZ1bmN0aW9uIFZlcnRleEF0dHJpYnV0ZShsb2NhdGlvbiwgZGltZW5zaW9uLCBhLCBiLCBjLCBkKSB7XG4gIHRoaXMubG9jYXRpb24gPSBsb2NhdGlvblxuICB0aGlzLmRpbWVuc2lvbiA9IGRpbWVuc2lvblxuICB0aGlzLmEgPSBhXG4gIHRoaXMuYiA9IGJcbiAgdGhpcy5jID0gY1xuICB0aGlzLmQgPSBkXG59XG5cblZlcnRleEF0dHJpYnV0ZS5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gIHN3aXRjaCh0aGlzLmRpbWVuc2lvbikge1xuICAgIGNhc2UgMTpcbiAgICAgIGdsLnZlcnRleEF0dHJpYjFmKHRoaXMubG9jYXRpb24sIHRoaXMuYSlcbiAgICBicmVha1xuICAgIGNhc2UgMjpcbiAgICAgIGdsLnZlcnRleEF0dHJpYjJmKHRoaXMubG9jYXRpb24sIHRoaXMuYSwgdGhpcy5iKVxuICAgIGJyZWFrXG4gICAgY2FzZSAzOlxuICAgICAgZ2wudmVydGV4QXR0cmliM2YodGhpcy5sb2NhdGlvbiwgdGhpcy5hLCB0aGlzLmIsIHRoaXMuYylcbiAgICBicmVha1xuICAgIGNhc2UgNDpcbiAgICAgIGdsLnZlcnRleEF0dHJpYjRmKHRoaXMubG9jYXRpb24sIHRoaXMuYSwgdGhpcy5iLCB0aGlzLmMsIHRoaXMuZClcbiAgICBicmVha1xuICB9XG59XG5cbmZ1bmN0aW9uIFZBT05hdGl2ZShnbCwgZXh0LCBoYW5kbGUpIHtcbiAgdGhpcy5nbCA9IGdsXG4gIHRoaXMuX2V4dCA9IGV4dFxuICB0aGlzLmhhbmRsZSA9IGhhbmRsZVxuICB0aGlzLl9hdHRyaWJzID0gW11cbiAgdGhpcy5fdXNlRWxlbWVudHMgPSBmYWxzZVxuICB0aGlzLl9lbGVtZW50c1R5cGUgPSBnbC5VTlNJR05FRF9TSE9SVFxufVxuXG5WQU9OYXRpdmUucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fZXh0LmJpbmRWZXJ0ZXhBcnJheU9FUyh0aGlzLmhhbmRsZSlcbiAgZm9yKHZhciBpPTA7IGk8dGhpcy5fYXR0cmlicy5sZW5ndGg7ICsraSkge1xuICAgIHRoaXMuX2F0dHJpYnNbaV0uYmluZCh0aGlzLmdsKVxuICB9XG59XG5cblZBT05hdGl2ZS5wcm90b3R5cGUudW5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuX2V4dC5iaW5kVmVydGV4QXJyYXlPRVMobnVsbClcbn1cblxuVkFPTmF0aXZlLnByb3RvdHlwZS5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuX2V4dC5kZWxldGVWZXJ0ZXhBcnJheU9FUyh0aGlzLmhhbmRsZSlcbn1cblxuVkFPTmF0aXZlLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbihhdHRyaWJ1dGVzLCBlbGVtZW50cywgZWxlbWVudHNUeXBlKSB7XG4gIHRoaXMuYmluZCgpXG4gIGJpbmRBdHRyaWJzKHRoaXMuZ2wsIGVsZW1lbnRzLCBhdHRyaWJ1dGVzKVxuICB0aGlzLnVuYmluZCgpXG4gIHRoaXMuX2F0dHJpYnMubGVuZ3RoID0gMFxuICBpZihhdHRyaWJ1dGVzKVxuICBmb3IodmFyIGk9MDsgaTxhdHRyaWJ1dGVzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGEgPSBhdHRyaWJ1dGVzW2ldXG4gICAgaWYodHlwZW9mIGEgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgIHRoaXMuX2F0dHJpYnMucHVzaChuZXcgVmVydGV4QXR0cmlidXRlKGksIDEsIGEpKVxuICAgIH0gZWxzZSBpZihBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICB0aGlzLl9hdHRyaWJzLnB1c2gobmV3IFZlcnRleEF0dHJpYnV0ZShpLCBhLmxlbmd0aCwgYVswXSwgYVsxXSwgYVsyXSwgYVszXSkpXG4gICAgfVxuICB9XG4gIHRoaXMuX3VzZUVsZW1lbnRzID0gISFlbGVtZW50c1xuICB0aGlzLl9lbGVtZW50c1R5cGUgPSBlbGVtZW50c1R5cGUgfHwgdGhpcy5nbC5VTlNJR05FRF9TSE9SVFxufVxuXG5WQU9OYXRpdmUucHJvdG90eXBlLmRyYXcgPSBmdW5jdGlvbihtb2RlLCBjb3VudCwgb2Zmc2V0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8fCAwXG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgaWYodGhpcy5fdXNlRWxlbWVudHMpIHtcbiAgICBnbC5kcmF3RWxlbWVudHMobW9kZSwgY291bnQsIHRoaXMuX2VsZW1lbnRzVHlwZSwgb2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGdsLmRyYXdBcnJheXMobW9kZSwgb2Zmc2V0LCBjb3VudClcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVWQU9OYXRpdmUoZ2wsIGV4dCkge1xuICByZXR1cm4gbmV3IFZBT05hdGl2ZShnbCwgZXh0LCBleHQuY3JlYXRlVmVydGV4QXJyYXlPRVMoKSlcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVWQU9OYXRpdmUiLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgY3JlYXRlVkFPTmF0aXZlID0gcmVxdWlyZShcIi4vbGliL3Zhby1uYXRpdmUuanNcIilcbnZhciBjcmVhdGVWQU9FbXVsYXRlZCA9IHJlcXVpcmUoXCIuL2xpYi92YW8tZW11bGF0ZWQuanNcIilcblxuZnVuY3Rpb24gRXh0ZW5zaW9uU2hpbSAoZ2wpIHtcbiAgdGhpcy5iaW5kVmVydGV4QXJyYXlPRVMgPSBnbC5iaW5kVmVydGV4QXJyYXkuYmluZChnbClcbiAgdGhpcy5jcmVhdGVWZXJ0ZXhBcnJheU9FUyA9IGdsLmNyZWF0ZVZlcnRleEFycmF5LmJpbmQoZ2wpXG4gIHRoaXMuZGVsZXRlVmVydGV4QXJyYXlPRVMgPSBnbC5kZWxldGVWZXJ0ZXhBcnJheS5iaW5kKGdsKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVWQU8oZ2wsIGF0dHJpYnV0ZXMsIGVsZW1lbnRzLCBlbGVtZW50c1R5cGUpIHtcbiAgdmFyIGV4dCA9IGdsLmNyZWF0ZVZlcnRleEFycmF5XG4gICAgPyBuZXcgRXh0ZW5zaW9uU2hpbShnbClcbiAgICA6IGdsLmdldEV4dGVuc2lvbignT0VTX3ZlcnRleF9hcnJheV9vYmplY3QnKVxuICB2YXIgdmFvXG5cbiAgaWYoZXh0KSB7XG4gICAgdmFvID0gY3JlYXRlVkFPTmF0aXZlKGdsLCBleHQpXG4gIH0gZWxzZSB7XG4gICAgdmFvID0gY3JlYXRlVkFPRW11bGF0ZWQoZ2wpXG4gIH1cbiAgdmFvLnVwZGF0ZShhdHRyaWJ1dGVzLCBlbGVtZW50cywgZWxlbWVudHNUeXBlKVxuICByZXR1cm4gdmFvXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVkFPXG4iLCJtb2R1bGUuZXhwb3J0cyA9IGFkZDtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGFkZChvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXVxuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdXG4gICAgb3V0WzJdID0gYVsyXSArIGJbMl1cbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSBhbmdsZVxuXG52YXIgZnJvbVZhbHVlcyA9IHJlcXVpcmUoJy4vZnJvbVZhbHVlcycpXG52YXIgbm9ybWFsaXplID0gcmVxdWlyZSgnLi9ub3JtYWxpemUnKVxudmFyIGRvdCA9IHJlcXVpcmUoJy4vZG90JylcblxuLyoqXG4gKiBHZXQgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIDNEIHZlY3RvcnNcbiAqIEBwYXJhbSB7dmVjM30gYSBUaGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gVGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqL1xuZnVuY3Rpb24gYW5nbGUoYSwgYikge1xuICAgIHZhciB0ZW1wQSA9IGZyb21WYWx1ZXMoYVswXSwgYVsxXSwgYVsyXSlcbiAgICB2YXIgdGVtcEIgPSBmcm9tVmFsdWVzKGJbMF0sIGJbMV0sIGJbMl0pXG4gXG4gICAgbm9ybWFsaXplKHRlbXBBLCB0ZW1wQSlcbiAgICBub3JtYWxpemUodGVtcEIsIHRlbXBCKVxuIFxuICAgIHZhciBjb3NpbmUgPSBkb3QodGVtcEEsIHRlbXBCKVxuXG4gICAgaWYoY29zaW5lID4gMS4wKXtcbiAgICAgICAgcmV0dXJuIDBcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gTWF0aC5hY29zKGNvc2luZSlcbiAgICB9ICAgICBcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gY2VpbFxuXG4vKipcbiAqIE1hdGguY2VpbCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjZWlsXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNlaWwob3V0LCBhKSB7XG4gIG91dFswXSA9IE1hdGguY2VpbChhWzBdKVxuICBvdXRbMV0gPSBNYXRoLmNlaWwoYVsxXSlcbiAgb3V0WzJdID0gTWF0aC5jZWlsKGFbMl0pXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gY2xvbmU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzN9IGEgbmV3IDNEIHZlY3RvclxuICovXG5mdW5jdGlvbiBjbG9uZShhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoMylcbiAgICBvdXRbMF0gPSBhWzBdXG4gICAgb3V0WzFdID0gYVsxXVxuICAgIG91dFsyXSA9IGFbMl1cbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSBjb3B5O1xuXG4vKipcbiAqIENvcHkgdGhlIHZhbHVlcyBmcm9tIG9uZSB2ZWMzIHRvIGFub3RoZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBzb3VyY2UgdmVjdG9yXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNvcHkob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXVxuICAgIG91dFsxXSA9IGFbMV1cbiAgICBvdXRbMl0gPSBhWzJdXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gY3JlYXRlO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSgzKVxuICAgIG91dFswXSA9IDBcbiAgICBvdXRbMV0gPSAwXG4gICAgb3V0WzJdID0gMFxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGNyb3NzO1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNyb3NzKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdXG5cbiAgICBvdXRbMF0gPSBheSAqIGJ6IC0gYXogKiBieVxuICAgIG91dFsxXSA9IGF6ICogYnggLSBheCAqIGJ6XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYnhcbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2Rpc3RhbmNlJylcbiIsIm1vZHVsZS5leHBvcnRzID0gZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIGRpc3RhbmNlKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXVxuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5ICsgeip6KVxufSIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9kaXZpZGUnKVxuIiwibW9kdWxlLmV4cG9ydHMgPSBkaXZpZGU7XG5cbi8qKlxuICogRGl2aWRlcyB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBkaXZpZGUob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF1cbiAgICBvdXRbMV0gPSBhWzFdIC8gYlsxXVxuICAgIG91dFsyXSA9IGFbMl0gLyBiWzJdXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gZG90O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqL1xuZnVuY3Rpb24gZG90KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdXG59IiwibW9kdWxlLmV4cG9ydHMgPSAwLjAwMDAwMVxuIiwibW9kdWxlLmV4cG9ydHMgPSBlcXVhbHNcblxudmFyIEVQU0lMT04gPSByZXF1aXJlKCcuL2Vwc2lsb24nKVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHZlY3RvcnMgaGF2ZSBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uLlxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSBUaGUgZmlyc3QgdmVjdG9yLlxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBzZWNvbmQgdmVjdG9yLlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIHZlY3RvcnMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uIGVxdWFscyhhLCBiKSB7XG4gIHZhciBhMCA9IGFbMF1cbiAgdmFyIGExID0gYVsxXVxuICB2YXIgYTIgPSBhWzJdXG4gIHZhciBiMCA9IGJbMF1cbiAgdmFyIGIxID0gYlsxXVxuICB2YXIgYjIgPSBiWzJdXG4gIHJldHVybiAoTWF0aC5hYnMoYTAgLSBiMCkgPD0gRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTApLCBNYXRoLmFicyhiMCkpICYmXG4gICAgICAgICAgTWF0aC5hYnMoYTEgLSBiMSkgPD0gRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTEpLCBNYXRoLmFicyhiMSkpICYmXG4gICAgICAgICAgTWF0aC5hYnMoYTIgLSBiMikgPD0gRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTIpLCBNYXRoLmFicyhiMikpKVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBleGFjdEVxdWFsc1xuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHZlY3RvcnMgZXhhY3RseSBoYXZlIHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uICh3aGVuIGNvbXBhcmVkIHdpdGggPT09KVxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSBUaGUgZmlyc3QgdmVjdG9yLlxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBzZWNvbmQgdmVjdG9yLlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIHZlY3RvcnMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uIGV4YWN0RXF1YWxzKGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gPT09IGJbMF0gJiYgYVsxXSA9PT0gYlsxXSAmJiBhWzJdID09PSBiWzJdXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZsb29yXG5cbi8qKlxuICogTWF0aC5mbG9vciB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBmbG9vclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBmbG9vcihvdXQsIGEpIHtcbiAgb3V0WzBdID0gTWF0aC5mbG9vcihhWzBdKVxuICBvdXRbMV0gPSBNYXRoLmZsb29yKGFbMV0pXG4gIG91dFsyXSA9IE1hdGguZmxvb3IoYVsyXSlcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBmb3JFYWNoO1xuXG52YXIgdmVjID0gcmVxdWlyZSgnLi9jcmVhdGUnKSgpXG5cbi8qKlxuICogUGVyZm9ybSBzb21lIG9wZXJhdGlvbiBvdmVyIGFuIGFycmF5IG9mIHZlYzNzLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGEgdGhlIGFycmF5IG9mIHZlY3RvcnMgdG8gaXRlcmF0ZSBvdmVyXG4gKiBAcGFyYW0ge051bWJlcn0gc3RyaWRlIE51bWJlciBvZiBlbGVtZW50cyBiZXR3ZWVuIHRoZSBzdGFydCBvZiBlYWNoIHZlYzMuIElmIDAgYXNzdW1lcyB0aWdodGx5IHBhY2tlZFxuICogQHBhcmFtIHtOdW1iZXJ9IG9mZnNldCBOdW1iZXIgb2YgZWxlbWVudHMgdG8gc2tpcCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhcnJheVxuICogQHBhcmFtIHtOdW1iZXJ9IGNvdW50IE51bWJlciBvZiB2ZWMzcyB0byBpdGVyYXRlIG92ZXIuIElmIDAgaXRlcmF0ZXMgb3ZlciBlbnRpcmUgYXJyYXlcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGNhbGwgZm9yIGVhY2ggdmVjdG9yIGluIHRoZSBhcnJheVxuICogQHBhcmFtIHtPYmplY3R9IFthcmddIGFkZGl0aW9uYWwgYXJndW1lbnQgdG8gcGFzcyB0byBmblxuICogQHJldHVybnMge0FycmF5fSBhXG4gKiBAZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gZm9yRWFjaChhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGxcbiAgICAgICAgaWYoIXN0cmlkZSkge1xuICAgICAgICAgICAgc3RyaWRlID0gM1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMFxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbCA9IGEubGVuZ3RoXG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldIFxuICAgICAgICAgICAgdmVjWzFdID0gYVtpKzFdIFxuICAgICAgICAgICAgdmVjWzJdID0gYVtpKzJdXG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKVxuICAgICAgICAgICAgYVtpXSA9IHZlY1swXSBcbiAgICAgICAgICAgIGFbaSsxXSA9IHZlY1sxXSBcbiAgICAgICAgICAgIGFbaSsyXSA9IHZlY1syXVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gYVxufSIsIm1vZHVsZS5leHBvcnRzID0gZnJvbVZhbHVlcztcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHZlYzMgaW5pdGlhbGl6ZWQgd2l0aCB0aGUgZ2l2ZW4gdmFsdWVzXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzN9IGEgbmV3IDNEIHZlY3RvclxuICovXG5mdW5jdGlvbiBmcm9tVmFsdWVzKHgsIHksIHopIHtcbiAgICB2YXIgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSgzKVxuICAgIG91dFswXSA9IHhcbiAgICBvdXRbMV0gPSB5XG4gICAgb3V0WzJdID0gelxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgRVBTSUxPTjogcmVxdWlyZSgnLi9lcHNpbG9uJylcbiAgLCBjcmVhdGU6IHJlcXVpcmUoJy4vY3JlYXRlJylcbiAgLCBjbG9uZTogcmVxdWlyZSgnLi9jbG9uZScpXG4gICwgYW5nbGU6IHJlcXVpcmUoJy4vYW5nbGUnKVxuICAsIGZyb21WYWx1ZXM6IHJlcXVpcmUoJy4vZnJvbVZhbHVlcycpXG4gICwgY29weTogcmVxdWlyZSgnLi9jb3B5JylcbiAgLCBzZXQ6IHJlcXVpcmUoJy4vc2V0JylcbiAgLCBlcXVhbHM6IHJlcXVpcmUoJy4vZXF1YWxzJylcbiAgLCBleGFjdEVxdWFsczogcmVxdWlyZSgnLi9leGFjdEVxdWFscycpXG4gICwgYWRkOiByZXF1aXJlKCcuL2FkZCcpXG4gICwgc3VidHJhY3Q6IHJlcXVpcmUoJy4vc3VidHJhY3QnKVxuICAsIHN1YjogcmVxdWlyZSgnLi9zdWInKVxuICAsIG11bHRpcGx5OiByZXF1aXJlKCcuL211bHRpcGx5JylcbiAgLCBtdWw6IHJlcXVpcmUoJy4vbXVsJylcbiAgLCBkaXZpZGU6IHJlcXVpcmUoJy4vZGl2aWRlJylcbiAgLCBkaXY6IHJlcXVpcmUoJy4vZGl2JylcbiAgLCBtaW46IHJlcXVpcmUoJy4vbWluJylcbiAgLCBtYXg6IHJlcXVpcmUoJy4vbWF4JylcbiAgLCBmbG9vcjogcmVxdWlyZSgnLi9mbG9vcicpXG4gICwgY2VpbDogcmVxdWlyZSgnLi9jZWlsJylcbiAgLCByb3VuZDogcmVxdWlyZSgnLi9yb3VuZCcpXG4gICwgc2NhbGU6IHJlcXVpcmUoJy4vc2NhbGUnKVxuICAsIHNjYWxlQW5kQWRkOiByZXF1aXJlKCcuL3NjYWxlQW5kQWRkJylcbiAgLCBkaXN0YW5jZTogcmVxdWlyZSgnLi9kaXN0YW5jZScpXG4gICwgZGlzdDogcmVxdWlyZSgnLi9kaXN0JylcbiAgLCBzcXVhcmVkRGlzdGFuY2U6IHJlcXVpcmUoJy4vc3F1YXJlZERpc3RhbmNlJylcbiAgLCBzcXJEaXN0OiByZXF1aXJlKCcuL3NxckRpc3QnKVxuICAsIGxlbmd0aDogcmVxdWlyZSgnLi9sZW5ndGgnKVxuICAsIGxlbjogcmVxdWlyZSgnLi9sZW4nKVxuICAsIHNxdWFyZWRMZW5ndGg6IHJlcXVpcmUoJy4vc3F1YXJlZExlbmd0aCcpXG4gICwgc3FyTGVuOiByZXF1aXJlKCcuL3NxckxlbicpXG4gICwgbmVnYXRlOiByZXF1aXJlKCcuL25lZ2F0ZScpXG4gICwgaW52ZXJzZTogcmVxdWlyZSgnLi9pbnZlcnNlJylcbiAgLCBub3JtYWxpemU6IHJlcXVpcmUoJy4vbm9ybWFsaXplJylcbiAgLCBkb3Q6IHJlcXVpcmUoJy4vZG90JylcbiAgLCBjcm9zczogcmVxdWlyZSgnLi9jcm9zcycpXG4gICwgbGVycDogcmVxdWlyZSgnLi9sZXJwJylcbiAgLCByYW5kb206IHJlcXVpcmUoJy4vcmFuZG9tJylcbiAgLCB0cmFuc2Zvcm1NYXQ0OiByZXF1aXJlKCcuL3RyYW5zZm9ybU1hdDQnKVxuICAsIHRyYW5zZm9ybU1hdDM6IHJlcXVpcmUoJy4vdHJhbnNmb3JtTWF0MycpXG4gICwgdHJhbnNmb3JtUXVhdDogcmVxdWlyZSgnLi90cmFuc2Zvcm1RdWF0JylcbiAgLCByb3RhdGVYOiByZXF1aXJlKCcuL3JvdGF0ZVgnKVxuICAsIHJvdGF0ZVk6IHJlcXVpcmUoJy4vcm90YXRlWScpXG4gICwgcm90YXRlWjogcmVxdWlyZSgnLi9yb3RhdGVaJylcbiAgLCBmb3JFYWNoOiByZXF1aXJlKCcuL2ZvckVhY2gnKVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpbnZlcnNlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGludmVyc2Ugb2YgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gaW52ZXJ0XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGludmVyc2Uob3V0LCBhKSB7XG4gIG91dFswXSA9IDEuMCAvIGFbMF1cbiAgb3V0WzFdID0gMS4wIC8gYVsxXVxuICBvdXRbMl0gPSAxLjAgLyBhWzJdXG4gIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGVuZ3RoJylcbiIsIm1vZHVsZS5leHBvcnRzID0gbGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbmZ1bmN0aW9uIGxlbmd0aChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl1cbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeilcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGxlcnAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl1cbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KVxuICAgIG91dFsxXSA9IGF5ICsgdCAqIChiWzFdIC0gYXkpXG4gICAgb3V0WzJdID0gYXogKyB0ICogKGJbMl0gLSBheilcbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSBtYXg7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWF4aW11bSBvZiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBtYXgob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSlcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKVxuICAgIG91dFsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gbWluO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gbWluKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pXG4gICAgb3V0WzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSlcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKVxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbXVsdGlwbHknKVxuIiwibW9kdWxlLmV4cG9ydHMgPSBtdWx0aXBseTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIG11bHRpcGx5KG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiWzBdXG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV1cbiAgICBvdXRbMl0gPSBhWzJdICogYlsyXVxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IG5lZ2F0ZTtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBuZWdhdGUob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF1cbiAgICBvdXRbMV0gPSAtYVsxXVxuICAgIG91dFsyXSA9IC1hWzJdXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gbm9ybWFsaXplO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplKG91dCwgYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV0sXG4gICAgICAgIHogPSBhWzJdXG4gICAgdmFyIGxlbiA9IHgqeCArIHkqeSArIHoqelxuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKVxuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuXG4gICAgICAgIG91dFsxXSA9IGFbMV0gKiBsZW5cbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlblxuICAgIH1cbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSByYW5kb207XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcmFuZG9tKG91dCwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDEuMFxuXG4gICAgdmFyIHIgPSBNYXRoLnJhbmRvbSgpICogMi4wICogTWF0aC5QSVxuICAgIHZhciB6ID0gKE1hdGgucmFuZG9tKCkgKiAyLjApIC0gMS4wXG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlXG5cbiAgICBvdXRbMF0gPSBNYXRoLmNvcyhyKSAqIHpTY2FsZVxuICAgIG91dFsxXSA9IE1hdGguc2luKHIpICogelNjYWxlXG4gICAgb3V0WzJdID0geiAqIHNjYWxlXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gcm90YXRlWDtcblxuLyoqXG4gKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB4LWF4aXNcbiAqIEBwYXJhbSB7dmVjM30gb3V0IFRoZSByZWNlaXZpbmcgdmVjM1xuICogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYyBUaGUgYW5nbGUgb2Ygcm90YXRpb25cbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWChvdXQsIGEsIGIsIGMpe1xuICAgIHZhciBieSA9IGJbMV1cbiAgICB2YXIgYnogPSBiWzJdXG5cbiAgICAvLyBUcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICAgIHZhciBweSA9IGFbMV0gLSBieVxuICAgIHZhciBweiA9IGFbMl0gLSBielxuXG4gICAgdmFyIHNjID0gTWF0aC5zaW4oYylcbiAgICB2YXIgY2MgPSBNYXRoLmNvcyhjKVxuXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBhWzBdXG4gICAgb3V0WzFdID0gYnkgKyBweSAqIGNjIC0gcHogKiBzY1xuICAgIG91dFsyXSA9IGJ6ICsgcHkgKiBzYyArIHB6ICogY2NcblxuICAgIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gcm90YXRlWTtcblxuLyoqXG4gKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB5LWF4aXNcbiAqIEBwYXJhbSB7dmVjM30gb3V0IFRoZSByZWNlaXZpbmcgdmVjM1xuICogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYyBUaGUgYW5nbGUgb2Ygcm90YXRpb25cbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWShvdXQsIGEsIGIsIGMpe1xuICAgIHZhciBieCA9IGJbMF1cbiAgICB2YXIgYnogPSBiWzJdXG5cbiAgICAvLyB0cmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICAgIHZhciBweCA9IGFbMF0gLSBieFxuICAgIHZhciBweiA9IGFbMl0gLSBielxuICAgIFxuICAgIHZhciBzYyA9IE1hdGguc2luKGMpXG4gICAgdmFyIGNjID0gTWF0aC5jb3MoYylcbiAgXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBieCArIHB6ICogc2MgKyBweCAqIGNjXG4gICAgb3V0WzFdID0gYVsxXVxuICAgIG91dFsyXSA9IGJ6ICsgcHogKiBjYyAtIHB4ICogc2NcbiAgXG4gICAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByb3RhdGVaO1xuXG4vKipcbiAqIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHotYXhpc1xuICogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4gKiBAcGFyYW0ge3ZlYzN9IGEgVGhlIHZlYzMgcG9pbnQgdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiAqIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiByb3RhdGVaKG91dCwgYSwgYiwgYyl7XG4gICAgdmFyIGJ4ID0gYlswXVxuICAgIHZhciBieSA9IGJbMV1cblxuICAgIC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgICB2YXIgcHggPSBhWzBdIC0gYnhcbiAgICB2YXIgcHkgPSBhWzFdIC0gYnlcbiAgXG4gICAgdmFyIHNjID0gTWF0aC5zaW4oYylcbiAgICB2YXIgY2MgPSBNYXRoLmNvcyhjKVxuXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBieCArIHB4ICogY2MgLSBweSAqIHNjXG4gICAgb3V0WzFdID0gYnkgKyBweCAqIHNjICsgcHkgKiBjY1xuICAgIG91dFsyXSA9IGFbMl1cbiAgXG4gICAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByb3VuZFxuXG4vKipcbiAqIE1hdGgucm91bmQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gcm91bmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm91bmQob3V0LCBhKSB7XG4gIG91dFswXSA9IE1hdGgucm91bmQoYVswXSlcbiAgb3V0WzFdID0gTWF0aC5yb3VuZChhWzFdKVxuICBvdXRbMl0gPSBNYXRoLnJvdW5kKGFbMl0pXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gc2NhbGU7XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHNjYWxlKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiXG4gICAgb3V0WzFdID0gYVsxXSAqIGJcbiAgICBvdXRbMl0gPSBhWzJdICogYlxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IHNjYWxlQW5kQWRkO1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBzY2FsZUFuZEFkZChvdXQsIGEsIGIsIHNjYWxlKSB7XG4gICAgb3V0WzBdID0gYVswXSArIChiWzBdICogc2NhbGUpXG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpXG4gICAgb3V0WzJdID0gYVsyXSArIChiWzJdICogc2NhbGUpXG4gICAgcmV0dXJuIG91dFxufSIsIm1vZHVsZS5leHBvcnRzID0gc2V0O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzMgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHNldChvdXQsIHgsIHksIHopIHtcbiAgICBvdXRbMF0gPSB4XG4gICAgb3V0WzFdID0geVxuICAgIG91dFsyXSA9IHpcbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3NxdWFyZWREaXN0YW5jZScpXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vc3F1YXJlZExlbmd0aCcpXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIHNxdWFyZWREaXN0YW5jZShhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl1cbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6XG59IiwibW9kdWxlLmV4cG9ydHMgPSBzcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKi9cbmZ1bmN0aW9uIHNxdWFyZWRMZW5ndGgoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV0sXG4gICAgICAgIHogPSBhWzJdXG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqelxufSIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9zdWJ0cmFjdCcpXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHN1YnRyYWN0O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBzdWJ0cmFjdChvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC0gYlswXVxuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdXG4gICAgb3V0WzJdID0gYVsyXSAtIGJbMl1cbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1NYXQzO1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHRyYW5zZm9ybU1hdDMob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl1cbiAgICBvdXRbMF0gPSB4ICogbVswXSArIHkgKiBtWzNdICsgeiAqIG1bNl1cbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN11cbiAgICBvdXRbMl0gPSB4ICogbVsyXSArIHkgKiBtWzVdICsgeiAqIG1bOF1cbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1NYXQ0O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gdHJhbnNmb3JtTWF0NChvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSxcbiAgICAgICAgdyA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XVxuICAgIHcgPSB3IHx8IDEuMFxuICAgIG91dFswXSA9IChtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSkgLyB3XG4gICAgb3V0WzFdID0gKG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdKSAvIHdcbiAgICBvdXRbMl0gPSAobVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdKSAvIHdcbiAgICByZXR1cm4gb3V0XG59IiwibW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1RdWF0O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiB0cmFuc2Zvcm1RdWF0KG91dCwgYSwgcSkge1xuICAgIC8vIGJlbmNobWFya3M6IGh0dHA6Ly9qc3BlcmYuY29tL3F1YXRlcm5pb24tdHJhbnNmb3JtLXZlYzMtaW1wbGVtZW50YXRpb25zXG5cbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSxcbiAgICAgICAgcXggPSBxWzBdLCBxeSA9IHFbMV0sIHF6ID0gcVsyXSwgcXcgPSBxWzNdLFxuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSBxdWF0ICogdmVjXG4gICAgICAgIGl4ID0gcXcgKiB4ICsgcXkgKiB6IC0gcXogKiB5LFxuICAgICAgICBpeSA9IHF3ICogeSArIHF6ICogeCAtIHF4ICogeixcbiAgICAgICAgaXogPSBxdyAqIHogKyBxeCAqIHkgLSBxeSAqIHgsXG4gICAgICAgIGl3ID0gLXF4ICogeCAtIHF5ICogeSAtIHF6ICogelxuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXlcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6XG4gICAgb3V0WzJdID0gaXogKiBxdyArIGl3ICogLXF6ICsgaXggKiAtcXkgLSBpeSAqIC1xeFxuICAgIHJldHVybiBvdXRcbn0iLCJtb2R1bGUuZXhwb3J0cyA9IGFkZFxuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gYWRkIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSArIGJbMF1cbiAgb3V0WzFdID0gYVsxXSArIGJbMV1cbiAgb3V0WzJdID0gYVsyXSArIGJbMl1cbiAgb3V0WzNdID0gYVszXSArIGJbM11cbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBjbG9uZVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWM0fSBhIG5ldyA0RCB2ZWN0b3JcbiAqL1xuZnVuY3Rpb24gY2xvbmUgKGEpIHtcbiAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoNClcbiAgb3V0WzBdID0gYVswXVxuICBvdXRbMV0gPSBhWzFdXG4gIG91dFsyXSA9IGFbMl1cbiAgb3V0WzNdID0gYVszXVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGNvcHlcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjNCB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBjb3B5IChvdXQsIGEpIHtcbiAgb3V0WzBdID0gYVswXVxuICBvdXRbMV0gPSBhWzFdXG4gIG91dFsyXSA9IGFbMl1cbiAgb3V0WzNdID0gYVszXVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZSAoKSB7XG4gIHZhciBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KDQpXG4gIG91dFswXSA9IDBcbiAgb3V0WzFdID0gMFxuICBvdXRbMl0gPSAwXG4gIG91dFszXSA9IDBcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBkaXN0YW5jZVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG5mdW5jdGlvbiBkaXN0YW5jZSAoYSwgYikge1xuICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgIHkgPSBiWzFdIC0gYVsxXSxcbiAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgdyA9IGJbM10gLSBhWzNdXG4gIHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHcpXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGRpdmlkZVxuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gZGl2aWRlIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAvIGJbMF1cbiAgb3V0WzFdID0gYVsxXSAvIGJbMV1cbiAgb3V0WzJdID0gYVsyXSAvIGJbMl1cbiAgb3V0WzNdID0gYVszXSAvIGJbM11cbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBkb3RcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIGRvdCAoYSwgYikge1xuICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM11cbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gZnJvbVZhbHVlc1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG5mdW5jdGlvbiBmcm9tVmFsdWVzICh4LCB5LCB6LCB3KSB7XG4gIHZhciBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KDQpXG4gIG91dFswXSA9IHhcbiAgb3V0WzFdID0geVxuICBvdXRbMl0gPSB6XG4gIG91dFszXSA9IHdcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIGNyZWF0ZTogcmVxdWlyZSgnLi9jcmVhdGUnKSxcbiAgY2xvbmU6IHJlcXVpcmUoJy4vY2xvbmUnKSxcbiAgZnJvbVZhbHVlczogcmVxdWlyZSgnLi9mcm9tVmFsdWVzJyksXG4gIGNvcHk6IHJlcXVpcmUoJy4vY29weScpLFxuICBzZXQ6IHJlcXVpcmUoJy4vc2V0JyksXG4gIGFkZDogcmVxdWlyZSgnLi9hZGQnKSxcbiAgc3VidHJhY3Q6IHJlcXVpcmUoJy4vc3VidHJhY3QnKSxcbiAgbXVsdGlwbHk6IHJlcXVpcmUoJy4vbXVsdGlwbHknKSxcbiAgZGl2aWRlOiByZXF1aXJlKCcuL2RpdmlkZScpLFxuICBtaW46IHJlcXVpcmUoJy4vbWluJyksXG4gIG1heDogcmVxdWlyZSgnLi9tYXgnKSxcbiAgc2NhbGU6IHJlcXVpcmUoJy4vc2NhbGUnKSxcbiAgc2NhbGVBbmRBZGQ6IHJlcXVpcmUoJy4vc2NhbGVBbmRBZGQnKSxcbiAgZGlzdGFuY2U6IHJlcXVpcmUoJy4vZGlzdGFuY2UnKSxcbiAgc3F1YXJlZERpc3RhbmNlOiByZXF1aXJlKCcuL3NxdWFyZWREaXN0YW5jZScpLFxuICBsZW5ndGg6IHJlcXVpcmUoJy4vbGVuZ3RoJyksXG4gIHNxdWFyZWRMZW5ndGg6IHJlcXVpcmUoJy4vc3F1YXJlZExlbmd0aCcpLFxuICBuZWdhdGU6IHJlcXVpcmUoJy4vbmVnYXRlJyksXG4gIGludmVyc2U6IHJlcXVpcmUoJy4vaW52ZXJzZScpLFxuICBub3JtYWxpemU6IHJlcXVpcmUoJy4vbm9ybWFsaXplJyksXG4gIGRvdDogcmVxdWlyZSgnLi9kb3QnKSxcbiAgbGVycDogcmVxdWlyZSgnLi9sZXJwJyksXG4gIHJhbmRvbTogcmVxdWlyZSgnLi9yYW5kb20nKSxcbiAgdHJhbnNmb3JtTWF0NDogcmVxdWlyZSgnLi90cmFuc2Zvcm1NYXQ0JyksXG4gIHRyYW5zZm9ybVF1YXQ6IHJlcXVpcmUoJy4vdHJhbnNmb3JtUXVhdCcpXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGludmVyc2VcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbnZlcnNlIG9mIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjNFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGludmVydFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBpbnZlcnNlIChvdXQsIGEpIHtcbiAgb3V0WzBdID0gMS4wIC8gYVswXVxuICBvdXRbMV0gPSAxLjAgLyBhWzFdXG4gIG91dFsyXSA9IDEuMCAvIGFbMl1cbiAgb3V0WzNdID0gMS4wIC8gYVszXVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGxlbmd0aFxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbmZ1bmN0aW9uIGxlbmd0aCAoYSkge1xuICB2YXIgeCA9IGFbMF0sXG4gICAgeSA9IGFbMV0sXG4gICAgeiA9IGFbMl0sXG4gICAgdyA9IGFbM11cbiAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogdylcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gbGVycFxuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBsZXJwIChvdXQsIGEsIGIsIHQpIHtcbiAgdmFyIGF4ID0gYVswXSxcbiAgICBheSA9IGFbMV0sXG4gICAgYXogPSBhWzJdLFxuICAgIGF3ID0gYVszXVxuICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KVxuICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KVxuICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KVxuICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IG1heFxuXG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbWF4IChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSlcbiAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSlcbiAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSlcbiAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSlcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBtaW5cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtaW5pbXVtIG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIG1pbiAob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pXG4gIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pXG4gIG91dFsyXSA9IE1hdGgubWluKGFbMl0sIGJbMl0pXG4gIG91dFszXSA9IE1hdGgubWluKGFbM10sIGJbM10pXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gbXVsdGlwbHlcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIG11bHRpcGx5IChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAqIGJbMF1cbiAgb3V0WzFdID0gYVsxXSAqIGJbMV1cbiAgb3V0WzJdID0gYVsyXSAqIGJbMl1cbiAgb3V0WzNdID0gYVszXSAqIGJbM11cbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBuZWdhdGVcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjNFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBuZWdhdGUgKG91dCwgYSkge1xuICBvdXRbMF0gPSAtYVswXVxuICBvdXRbMV0gPSAtYVsxXVxuICBvdXRbMl0gPSAtYVsyXVxuICBvdXRbM10gPSAtYVszXVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IG5vcm1hbGl6ZVxuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplIChvdXQsIGEpIHtcbiAgdmFyIHggPSBhWzBdLFxuICAgIHkgPSBhWzFdLFxuICAgIHogPSBhWzJdLFxuICAgIHcgPSBhWzNdXG4gIHZhciBsZW4gPSB4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogd1xuICBpZiAobGVuID4gMCkge1xuICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKVxuICAgIG91dFswXSA9IHggKiBsZW5cbiAgICBvdXRbMV0gPSB5ICogbGVuXG4gICAgb3V0WzJdID0geiAqIGxlblxuICAgIG91dFszXSA9IHcgKiBsZW5cbiAgfVxuICByZXR1cm4gb3V0XG59XG4iLCJ2YXIgdmVjTm9ybWFsaXplID0gcmVxdWlyZSgnLi9ub3JtYWxpemUnKVxudmFyIHZlY1NjYWxlID0gcmVxdWlyZSgnLi9zY2FsZScpXG5cbm1vZHVsZS5leHBvcnRzID0gcmFuZG9tXG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gcmFuZG9tIChvdXQsIHNjYWxlKSB7XG4gIHNjYWxlID0gc2NhbGUgfHwgMS4wXG5cbiAgLy8gVE9ETzogVGhpcyBpcyBhIHByZXR0eSBhd2Z1bCB3YXkgb2YgZG9pbmcgdGhpcy4gRmluZCBzb21ldGhpbmcgYmV0dGVyLlxuICBvdXRbMF0gPSBNYXRoLnJhbmRvbSgpXG4gIG91dFsxXSA9IE1hdGgucmFuZG9tKClcbiAgb3V0WzJdID0gTWF0aC5yYW5kb20oKVxuICBvdXRbM10gPSBNYXRoLnJhbmRvbSgpXG4gIHZlY05vcm1hbGl6ZShvdXQsIG91dClcbiAgdmVjU2NhbGUob3V0LCBvdXQsIHNjYWxlKVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHNjYWxlXG5cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHNjYWxlIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAqIGJcbiAgb3V0WzFdID0gYVsxXSAqIGJcbiAgb3V0WzJdID0gYVsyXSAqIGJcbiAgb3V0WzNdID0gYVszXSAqIGJcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBzY2FsZUFuZEFkZFxuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBzY2FsZUFuZEFkZCAob3V0LCBhLCBiLCBzY2FsZSkge1xuICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSlcbiAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpXG4gIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKVxuICBvdXRbM10gPSBhWzNdICsgKGJbM10gKiBzY2FsZSlcbiAgcmV0dXJuIG91dFxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBzZXRcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gc2V0IChvdXQsIHgsIHksIHosIHcpIHtcbiAgb3V0WzBdID0geFxuICBvdXRbMV0gPSB5XG4gIG91dFsyXSA9IHpcbiAgb3V0WzNdID0gd1xuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHNxdWFyZWREaXN0YW5jZVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xuZnVuY3Rpb24gc3F1YXJlZERpc3RhbmNlIChhLCBiKSB7XG4gIHZhciB4ID0gYlswXSAtIGFbMF0sXG4gICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgIHogPSBiWzJdIC0gYVsyXSxcbiAgICB3ID0gYlszXSAtIGFbM11cbiAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHNxdWFyZWRMZW5ndGhcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG5mdW5jdGlvbiBzcXVhcmVkTGVuZ3RoIChhKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICB5ID0gYVsxXSxcbiAgICB6ID0gYVsyXSxcbiAgICB3ID0gYVszXVxuICByZXR1cm4geCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHdcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gc3VidHJhY3RcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gc3VidHJhY3QgKG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdIC0gYlswXVxuICBvdXRbMV0gPSBhWzFdIC0gYlsxXVxuICBvdXRbMl0gPSBhWzJdIC0gYlsyXVxuICBvdXRbM10gPSBhWzNdIC0gYlszXVxuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHRyYW5zZm9ybU1hdDRcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWM0IHdpdGggYSBtYXQ0LlxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gdHJhbnNmb3JtTWF0NCAob3V0LCBhLCBtKSB7XG4gIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLCB3ID0gYVszXVxuICBvdXRbMF0gPSBtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSAqIHdcbiAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM10gKiB3XG4gIG91dFsyXSA9IG1bMl0gKiB4ICsgbVs2XSAqIHkgKyBtWzEwXSAqIHogKyBtWzE0XSAqIHdcbiAgb3V0WzNdID0gbVszXSAqIHggKyBtWzddICogeSArIG1bMTFdICogeiArIG1bMTVdICogd1xuICByZXR1cm4gb3V0XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHRyYW5zZm9ybVF1YXRcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWM0IHdpdGggYSBxdWF0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHtxdWF0fSBxIHF1YXRlcm5pb24gdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gdHJhbnNmb3JtUXVhdCAob3V0LCBhLCBxKSB7XG4gIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLFxuICAgIHF4ID0gcVswXSwgcXkgPSBxWzFdLCBxeiA9IHFbMl0sIHF3ID0gcVszXSxcblxuICAgIC8vIGNhbGN1bGF0ZSBxdWF0ICogdmVjXG4gICAgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHksXG4gICAgaXkgPSBxdyAqIHkgKyBxeiAqIHggLSBxeCAqIHosXG4gICAgaXogPSBxdyAqIHogKyBxeCAqIHkgLSBxeSAqIHgsXG4gICAgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6XG5cbiAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICBvdXRbMF0gPSBpeCAqIHF3ICsgaXcgKiAtcXggKyBpeSAqIC1xeiAtIGl6ICogLXF5XG4gIG91dFsxXSA9IGl5ICogcXcgKyBpdyAqIC1xeSArIGl6ICogLXF4IC0gaXggKiAtcXpcbiAgb3V0WzJdID0gaXogKiBxdyArIGl3ICogLXF6ICsgaXggKiAtcXkgLSBpeSAqIC1xeFxuICBvdXRbM10gPSBhWzNdXG4gIHJldHVybiBvdXRcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gZGVjb2RlRmxvYXRcblxudmFyIFVJTlQ4X1ZJRVcgPSBuZXcgVWludDhBcnJheSg0KVxudmFyIEZMT0FUX1ZJRVcgPSBuZXcgRmxvYXQzMkFycmF5KFVJTlQ4X1ZJRVcuYnVmZmVyKVxuXG5mdW5jdGlvbiBkZWNvZGVGbG9hdCh4LCB5LCB6LCB3KSB7XG4gIFVJTlQ4X1ZJRVdbMF0gPSB3XG4gIFVJTlQ4X1ZJRVdbMV0gPSB6XG4gIFVJTlQ4X1ZJRVdbMl0gPSB5XG4gIFVJTlQ4X1ZJRVdbM10gPSB4XG4gIHJldHVybiBGTE9BVF9WSUVXWzBdXG59XG4iLCJ2YXIgdG9rZW5pemUgPSByZXF1aXJlKCdnbHNsLXRva2VuaXplcicpXG52YXIgYXRvYiAgICAgPSByZXF1aXJlKCdhdG9iLWxpdGUnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldE5hbWVcblxuZnVuY3Rpb24gZ2V0TmFtZShzcmMpIHtcbiAgdmFyIHRva2VucyA9IEFycmF5LmlzQXJyYXkoc3JjKVxuICAgID8gc3JjXG4gICAgOiB0b2tlbml6ZShzcmMpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdG9rZW4gPSB0b2tlbnNbaV1cbiAgICBpZiAodG9rZW4udHlwZSAhPT0gJ3ByZXByb2Nlc3NvcicpIGNvbnRpbnVlXG4gICAgdmFyIG1hdGNoID0gdG9rZW4uZGF0YS5tYXRjaCgvXFwjZGVmaW5lXFxzK1NIQURFUl9OQU1FKF9CNjQpP1xccysoLispJC8pXG4gICAgaWYgKCFtYXRjaCkgY29udGludWVcbiAgICBpZiAoIW1hdGNoWzJdKSBjb250aW51ZVxuXG4gICAgdmFyIGI2NCAgPSBtYXRjaFsxXVxuICAgIHZhciBuYW1lID0gbWF0Y2hbMl1cblxuICAgIHJldHVybiAoYjY0ID8gYXRvYihuYW1lKSA6IG5hbWUpLnRyaW0oKVxuICB9XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHRva2VuaXplXG5cbnZhciBsaXRlcmFsczEwMCA9IHJlcXVpcmUoJy4vbGliL2xpdGVyYWxzJylcbiAgLCBvcGVyYXRvcnMgPSByZXF1aXJlKCcuL2xpYi9vcGVyYXRvcnMnKVxuICAsIGJ1aWx0aW5zMTAwID0gcmVxdWlyZSgnLi9saWIvYnVpbHRpbnMnKVxuICAsIGxpdGVyYWxzMzAwZXMgPSByZXF1aXJlKCcuL2xpYi9saXRlcmFscy0zMDBlcycpXG4gICwgYnVpbHRpbnMzMDBlcyA9IHJlcXVpcmUoJy4vbGliL2J1aWx0aW5zLTMwMGVzJylcblxudmFyIE5PUk1BTCA9IDk5OSAgICAgICAgICAvLyA8LS0gbmV2ZXIgZW1pdHRlZFxuICAsIFRPS0VOID0gOTk5OSAgICAgICAgICAvLyA8LS0gbmV2ZXIgZW1pdHRlZFxuICAsIEJMT0NLX0NPTU1FTlQgPSAwXG4gICwgTElORV9DT01NRU5UID0gMVxuICAsIFBSRVBST0NFU1NPUiA9IDJcbiAgLCBPUEVSQVRPUiA9IDNcbiAgLCBJTlRFR0VSID0gNFxuICAsIEZMT0FUID0gNVxuICAsIElERU5UID0gNlxuICAsIEJVSUxUSU4gPSA3XG4gICwgS0VZV09SRCA9IDhcbiAgLCBXSElURVNQQUNFID0gOVxuICAsIEVPRiA9IDEwXG4gICwgSEVYID0gMTFcblxudmFyIG1hcCA9IFtcbiAgICAnYmxvY2stY29tbWVudCdcbiAgLCAnbGluZS1jb21tZW50J1xuICAsICdwcmVwcm9jZXNzb3InXG4gICwgJ29wZXJhdG9yJ1xuICAsICdpbnRlZ2VyJ1xuICAsICdmbG9hdCdcbiAgLCAnaWRlbnQnXG4gICwgJ2J1aWx0aW4nXG4gICwgJ2tleXdvcmQnXG4gICwgJ3doaXRlc3BhY2UnXG4gICwgJ2VvZidcbiAgLCAnaW50ZWdlcidcbl1cblxuZnVuY3Rpb24gdG9rZW5pemUob3B0KSB7XG4gIHZhciBpID0gMFxuICAgICwgdG90YWwgPSAwXG4gICAgLCBtb2RlID0gTk9STUFMXG4gICAgLCBjXG4gICAgLCBsYXN0XG4gICAgLCBjb250ZW50ID0gW11cbiAgICAsIHRva2VucyA9IFtdXG4gICAgLCB0b2tlbl9pZHggPSAwXG4gICAgLCB0b2tlbl9vZmZzID0gMFxuICAgICwgbGluZSA9IDFcbiAgICAsIGNvbCA9IDBcbiAgICAsIHN0YXJ0ID0gMFxuICAgICwgaXNudW0gPSBmYWxzZVxuICAgICwgaXNvcGVyYXRvciA9IGZhbHNlXG4gICAgLCBpbnB1dCA9ICcnXG4gICAgLCBsZW5cblxuICBvcHQgPSBvcHQgfHwge31cbiAgdmFyIGFsbEJ1aWx0aW5zID0gYnVpbHRpbnMxMDBcbiAgdmFyIGFsbExpdGVyYWxzID0gbGl0ZXJhbHMxMDBcbiAgaWYgKG9wdC52ZXJzaW9uID09PSAnMzAwIGVzJykge1xuICAgIGFsbEJ1aWx0aW5zID0gYnVpbHRpbnMzMDBlc1xuICAgIGFsbExpdGVyYWxzID0gbGl0ZXJhbHMzMDBlc1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB0b2tlbnMgPSBbXVxuICAgIGlmIChkYXRhICE9PSBudWxsKSByZXR1cm4gd3JpdGUoZGF0YS5yZXBsYWNlID8gZGF0YS5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpIDogZGF0YSlcbiAgICByZXR1cm4gZW5kKClcbiAgfVxuXG4gIGZ1bmN0aW9uIHRva2VuKGRhdGEpIHtcbiAgICBpZiAoZGF0YS5sZW5ndGgpIHtcbiAgICAgIHRva2Vucy5wdXNoKHtcbiAgICAgICAgdHlwZTogbWFwW21vZGVdXG4gICAgICAsIGRhdGE6IGRhdGFcbiAgICAgICwgcG9zaXRpb246IHN0YXJ0XG4gICAgICAsIGxpbmU6IGxpbmVcbiAgICAgICwgY29sdW1uOiBjb2xcbiAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gd3JpdGUoY2h1bmspIHtcbiAgICBpID0gMFxuICAgIGlucHV0ICs9IGNodW5rXG4gICAgbGVuID0gaW5wdXQubGVuZ3RoXG5cbiAgICB2YXIgbGFzdFxuXG4gICAgd2hpbGUoYyA9IGlucHV0W2ldLCBpIDwgbGVuKSB7XG4gICAgICBsYXN0ID0gaVxuXG4gICAgICBzd2l0Y2gobW9kZSkge1xuICAgICAgICBjYXNlIEJMT0NLX0NPTU1FTlQ6IGkgPSBibG9ja19jb21tZW50KCk7IGJyZWFrXG4gICAgICAgIGNhc2UgTElORV9DT01NRU5UOiBpID0gbGluZV9jb21tZW50KCk7IGJyZWFrXG4gICAgICAgIGNhc2UgUFJFUFJPQ0VTU09SOiBpID0gcHJlcHJvY2Vzc29yKCk7IGJyZWFrXG4gICAgICAgIGNhc2UgT1BFUkFUT1I6IGkgPSBvcGVyYXRvcigpOyBicmVha1xuICAgICAgICBjYXNlIElOVEVHRVI6IGkgPSBpbnRlZ2VyKCk7IGJyZWFrXG4gICAgICAgIGNhc2UgSEVYOiBpID0gaGV4KCk7IGJyZWFrXG4gICAgICAgIGNhc2UgRkxPQVQ6IGkgPSBkZWNpbWFsKCk7IGJyZWFrXG4gICAgICAgIGNhc2UgVE9LRU46IGkgPSByZWFkdG9rZW4oKTsgYnJlYWtcbiAgICAgICAgY2FzZSBXSElURVNQQUNFOiBpID0gd2hpdGVzcGFjZSgpOyBicmVha1xuICAgICAgICBjYXNlIE5PUk1BTDogaSA9IG5vcm1hbCgpOyBicmVha1xuICAgICAgfVxuXG4gICAgICBpZihsYXN0ICE9PSBpKSB7XG4gICAgICAgIHN3aXRjaChpbnB1dFtsYXN0XSkge1xuICAgICAgICAgIGNhc2UgJ1xcbic6IGNvbCA9IDA7ICsrbGluZTsgYnJlYWtcbiAgICAgICAgICBkZWZhdWx0OiArK2NvbDsgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRvdGFsICs9IGlcbiAgICBpbnB1dCA9IGlucHV0LnNsaWNlKGkpXG4gICAgcmV0dXJuIHRva2Vuc1xuICB9XG5cbiAgZnVuY3Rpb24gZW5kKGNodW5rKSB7XG4gICAgaWYoY29udGVudC5sZW5ndGgpIHtcbiAgICAgIHRva2VuKGNvbnRlbnQuam9pbignJykpXG4gICAgfVxuXG4gICAgbW9kZSA9IEVPRlxuICAgIHRva2VuKCcoZW9mKScpXG4gICAgcmV0dXJuIHRva2Vuc1xuICB9XG5cbiAgZnVuY3Rpb24gbm9ybWFsKCkge1xuICAgIGNvbnRlbnQgPSBjb250ZW50Lmxlbmd0aCA/IFtdIDogY29udGVudFxuXG4gICAgaWYobGFzdCA9PT0gJy8nICYmIGMgPT09ICcqJykge1xuICAgICAgc3RhcnQgPSB0b3RhbCArIGkgLSAxXG4gICAgICBtb2RlID0gQkxPQ0tfQ09NTUVOVFxuICAgICAgbGFzdCA9IGNcbiAgICAgIHJldHVybiBpICsgMVxuICAgIH1cblxuICAgIGlmKGxhc3QgPT09ICcvJyAmJiBjID09PSAnLycpIHtcbiAgICAgIHN0YXJ0ID0gdG90YWwgKyBpIC0gMVxuICAgICAgbW9kZSA9IExJTkVfQ09NTUVOVFxuICAgICAgbGFzdCA9IGNcbiAgICAgIHJldHVybiBpICsgMVxuICAgIH1cblxuICAgIGlmKGMgPT09ICcjJykge1xuICAgICAgbW9kZSA9IFBSRVBST0NFU1NPUlxuICAgICAgc3RhcnQgPSB0b3RhbCArIGlcbiAgICAgIHJldHVybiBpXG4gICAgfVxuXG4gICAgaWYoL1xccy8udGVzdChjKSkge1xuICAgICAgbW9kZSA9IFdISVRFU1BBQ0VcbiAgICAgIHN0YXJ0ID0gdG90YWwgKyBpXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGlzbnVtID0gL1xcZC8udGVzdChjKVxuICAgIGlzb3BlcmF0b3IgPSAvW15cXHdfXS8udGVzdChjKVxuXG4gICAgc3RhcnQgPSB0b3RhbCArIGlcbiAgICBtb2RlID0gaXNudW0gPyBJTlRFR0VSIDogaXNvcGVyYXRvciA/IE9QRVJBVE9SIDogVE9LRU5cbiAgICByZXR1cm4gaVxuICB9XG5cbiAgZnVuY3Rpb24gd2hpdGVzcGFjZSgpIHtcbiAgICBpZigvW15cXHNdL2cudGVzdChjKSkge1xuICAgICAgdG9rZW4oY29udGVudC5qb2luKCcnKSlcbiAgICAgIG1vZGUgPSBOT1JNQUxcbiAgICAgIHJldHVybiBpXG4gICAgfVxuICAgIGNvbnRlbnQucHVzaChjKVxuICAgIGxhc3QgPSBjXG4gICAgcmV0dXJuIGkgKyAxXG4gIH1cblxuICBmdW5jdGlvbiBwcmVwcm9jZXNzb3IoKSB7XG4gICAgaWYoKGMgPT09ICdcXHInIHx8IGMgPT09ICdcXG4nKSAmJiBsYXN0ICE9PSAnXFxcXCcpIHtcbiAgICAgIHRva2VuKGNvbnRlbnQuam9pbignJykpXG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaVxuICAgIH1cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gbGluZV9jb21tZW50KCkge1xuICAgIHJldHVybiBwcmVwcm9jZXNzb3IoKVxuICB9XG5cbiAgZnVuY3Rpb24gYmxvY2tfY29tbWVudCgpIHtcbiAgICBpZihjID09PSAnLycgJiYgbGFzdCA9PT0gJyonKSB7XG4gICAgICBjb250ZW50LnB1c2goYylcbiAgICAgIHRva2VuKGNvbnRlbnQuam9pbignJykpXG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gb3BlcmF0b3IoKSB7XG4gICAgaWYobGFzdCA9PT0gJy4nICYmIC9cXGQvLnRlc3QoYykpIHtcbiAgICAgIG1vZGUgPSBGTE9BVFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBpZihsYXN0ID09PSAnLycgJiYgYyA9PT0gJyonKSB7XG4gICAgICBtb2RlID0gQkxPQ0tfQ09NTUVOVFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBpZihsYXN0ID09PSAnLycgJiYgYyA9PT0gJy8nKSB7XG4gICAgICBtb2RlID0gTElORV9DT01NRU5UXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGlmKGMgPT09ICcuJyAmJiBjb250ZW50Lmxlbmd0aCkge1xuICAgICAgd2hpbGUoZGV0ZXJtaW5lX29wZXJhdG9yKGNvbnRlbnQpKTtcblxuICAgICAgbW9kZSA9IEZMT0FUXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGlmKGMgPT09ICc7JyB8fCBjID09PSAnKScgfHwgYyA9PT0gJygnKSB7XG4gICAgICBpZihjb250ZW50Lmxlbmd0aCkgd2hpbGUoZGV0ZXJtaW5lX29wZXJhdG9yKGNvbnRlbnQpKTtcbiAgICAgIHRva2VuKGMpXG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICB2YXIgaXNfY29tcG9zaXRlX29wZXJhdG9yID0gY29udGVudC5sZW5ndGggPT09IDIgJiYgYyAhPT0gJz0nXG4gICAgaWYoL1tcXHdfXFxkXFxzXS8udGVzdChjKSB8fCBpc19jb21wb3NpdGVfb3BlcmF0b3IpIHtcbiAgICAgIHdoaWxlKGRldGVybWluZV9vcGVyYXRvcihjb250ZW50KSk7XG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGNvbnRlbnQucHVzaChjKVxuICAgIGxhc3QgPSBjXG4gICAgcmV0dXJuIGkgKyAxXG4gIH1cblxuICBmdW5jdGlvbiBkZXRlcm1pbmVfb3BlcmF0b3IoYnVmKSB7XG4gICAgdmFyIGogPSAwXG4gICAgICAsIGlkeFxuICAgICAgLCByZXNcblxuICAgIGRvIHtcbiAgICAgIGlkeCA9IG9wZXJhdG9ycy5pbmRleE9mKGJ1Zi5zbGljZSgwLCBidWYubGVuZ3RoICsgaikuam9pbignJykpXG4gICAgICByZXMgPSBvcGVyYXRvcnNbaWR4XVxuXG4gICAgICBpZihpZHggPT09IC0xKSB7XG4gICAgICAgIGlmKGotLSArIGJ1Zi5sZW5ndGggPiAwKSBjb250aW51ZVxuICAgICAgICByZXMgPSBidWYuc2xpY2UoMCwgMSkuam9pbignJylcbiAgICAgIH1cblxuICAgICAgdG9rZW4ocmVzKVxuXG4gICAgICBzdGFydCArPSByZXMubGVuZ3RoXG4gICAgICBjb250ZW50ID0gY29udGVudC5zbGljZShyZXMubGVuZ3RoKVxuICAgICAgcmV0dXJuIGNvbnRlbnQubGVuZ3RoXG4gICAgfSB3aGlsZSgxKVxuICB9XG5cbiAgZnVuY3Rpb24gaGV4KCkge1xuICAgIGlmKC9bXmEtZkEtRjAtOV0vLnRlc3QoYykpIHtcbiAgICAgIHRva2VuKGNvbnRlbnQuam9pbignJykpXG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGNvbnRlbnQucHVzaChjKVxuICAgIGxhc3QgPSBjXG4gICAgcmV0dXJuIGkgKyAxXG4gIH1cblxuICBmdW5jdGlvbiBpbnRlZ2VyKCkge1xuICAgIGlmKGMgPT09ICcuJykge1xuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICBtb2RlID0gRkxPQVRcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZigvW2VFXS8udGVzdChjKSkge1xuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICBtb2RlID0gRkxPQVRcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZihjID09PSAneCcgJiYgY29udGVudC5sZW5ndGggPT09IDEgJiYgY29udGVudFswXSA9PT0gJzAnKSB7XG4gICAgICBtb2RlID0gSEVYXG4gICAgICBjb250ZW50LnB1c2goYylcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZigvW15cXGRdLy50ZXN0KGMpKSB7XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gZGVjaW1hbCgpIHtcbiAgICBpZihjID09PSAnZicpIHtcbiAgICAgIGNvbnRlbnQucHVzaChjKVxuICAgICAgbGFzdCA9IGNcbiAgICAgIGkgKz0gMVxuICAgIH1cblxuICAgIGlmKC9bZUVdLy50ZXN0KGMpKSB7XG4gICAgICBjb250ZW50LnB1c2goYylcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZiAoYyA9PT0gJy0nICYmIC9bZUVdLy50ZXN0KGxhc3QpKSB7XG4gICAgICBjb250ZW50LnB1c2goYylcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZigvW15cXGRdLy50ZXN0KGMpKSB7XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZHRva2VuKCkge1xuICAgIGlmKC9bXlxcZFxcd19dLy50ZXN0KGMpKSB7XG4gICAgICB2YXIgY29udGVudHN0ciA9IGNvbnRlbnQuam9pbignJylcbiAgICAgIGlmKGFsbExpdGVyYWxzLmluZGV4T2YoY29udGVudHN0cikgPiAtMSkge1xuICAgICAgICBtb2RlID0gS0VZV09SRFxuICAgICAgfSBlbHNlIGlmKGFsbEJ1aWx0aW5zLmluZGV4T2YoY29udGVudHN0cikgPiAtMSkge1xuICAgICAgICBtb2RlID0gQlVJTFRJTlxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbW9kZSA9IElERU5UXG4gICAgICB9XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG4gICAgY29udGVudC5wdXNoKGMpXG4gICAgbGFzdCA9IGNcbiAgICByZXR1cm4gaSArIDFcbiAgfVxufVxuIiwiLy8gMzAwZXMgYnVpbHRpbnMvcmVzZXJ2ZWQgd29yZHMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgdmFsaWQgaW4gdjEwMFxudmFyIHYxMDAgPSByZXF1aXJlKCcuL2J1aWx0aW5zJylcblxuLy8gVGhlIHRleHR1cmUyRHxDdWJlIGZ1bmN0aW9ucyBoYXZlIGJlZW4gcmVtb3ZlZFxuLy8gQW5kIHRoZSBnbF8gZmVhdHVyZXMgYXJlIHVwZGF0ZWRcbnYxMDAgPSB2MTAwLnNsaWNlKCkuZmlsdGVyKGZ1bmN0aW9uIChiKSB7XG4gIHJldHVybiAhL14oZ2xcXF98dGV4dHVyZSkvLnRlc3QoYilcbn0pXG5cbm1vZHVsZS5leHBvcnRzID0gdjEwMC5jb25jYXQoW1xuICAvLyB0aGUgdXBkYXRlZCBnbF8gY29uc3RhbnRzXG4gICAgJ2dsX1ZlcnRleElEJ1xuICAsICdnbF9JbnN0YW5jZUlEJ1xuICAsICdnbF9Qb3NpdGlvbidcbiAgLCAnZ2xfUG9pbnRTaXplJ1xuICAsICdnbF9GcmFnQ29vcmQnXG4gICwgJ2dsX0Zyb250RmFjaW5nJ1xuICAsICdnbF9GcmFnRGVwdGgnXG4gICwgJ2dsX1BvaW50Q29vcmQnXG4gICwgJ2dsX01heFZlcnRleEF0dHJpYnMnXG4gICwgJ2dsX01heFZlcnRleFVuaWZvcm1WZWN0b3JzJ1xuICAsICdnbF9NYXhWZXJ0ZXhPdXRwdXRWZWN0b3JzJ1xuICAsICdnbF9NYXhGcmFnbWVudElucHV0VmVjdG9ycydcbiAgLCAnZ2xfTWF4VmVydGV4VGV4dHVyZUltYWdlVW5pdHMnXG4gICwgJ2dsX01heENvbWJpbmVkVGV4dHVyZUltYWdlVW5pdHMnXG4gICwgJ2dsX01heFRleHR1cmVJbWFnZVVuaXRzJ1xuICAsICdnbF9NYXhGcmFnbWVudFVuaWZvcm1WZWN0b3JzJ1xuICAsICdnbF9NYXhEcmF3QnVmZmVycydcbiAgLCAnZ2xfTWluUHJvZ3JhbVRleGVsT2Zmc2V0J1xuICAsICdnbF9NYXhQcm9ncmFtVGV4ZWxPZmZzZXQnXG4gICwgJ2dsX0RlcHRoUmFuZ2VQYXJhbWV0ZXJzJ1xuICAsICdnbF9EZXB0aFJhbmdlJ1xuXG4gIC8vIG90aGVyIGJ1aWx0aW5zXG4gICwgJ3RydW5jJ1xuICAsICdyb3VuZCdcbiAgLCAncm91bmRFdmVuJ1xuICAsICdpc25hbidcbiAgLCAnaXNpbmYnXG4gICwgJ2Zsb2F0Qml0c1RvSW50J1xuICAsICdmbG9hdEJpdHNUb1VpbnQnXG4gICwgJ2ludEJpdHNUb0Zsb2F0J1xuICAsICd1aW50Qml0c1RvRmxvYXQnXG4gICwgJ3BhY2tTbm9ybTJ4MTYnXG4gICwgJ3VucGFja1Nub3JtMngxNidcbiAgLCAncGFja1Vub3JtMngxNidcbiAgLCAndW5wYWNrVW5vcm0yeDE2J1xuICAsICdwYWNrSGFsZjJ4MTYnXG4gICwgJ3VucGFja0hhbGYyeDE2J1xuICAsICdvdXRlclByb2R1Y3QnXG4gICwgJ3RyYW5zcG9zZSdcbiAgLCAnZGV0ZXJtaW5hbnQnXG4gICwgJ2ludmVyc2UnXG4gICwgJ3RleHR1cmUnXG4gICwgJ3RleHR1cmVTaXplJ1xuICAsICd0ZXh0dXJlUHJvaidcbiAgLCAndGV4dHVyZUxvZCdcbiAgLCAndGV4dHVyZU9mZnNldCdcbiAgLCAndGV4ZWxGZXRjaCdcbiAgLCAndGV4ZWxGZXRjaE9mZnNldCdcbiAgLCAndGV4dHVyZVByb2pPZmZzZXQnXG4gICwgJ3RleHR1cmVMb2RPZmZzZXQnXG4gICwgJ3RleHR1cmVQcm9qTG9kJ1xuICAsICd0ZXh0dXJlUHJvakxvZE9mZnNldCdcbiAgLCAndGV4dHVyZUdyYWQnXG4gICwgJ3RleHR1cmVHcmFkT2Zmc2V0J1xuICAsICd0ZXh0dXJlUHJvakdyYWQnXG4gICwgJ3RleHR1cmVQcm9qR3JhZE9mZnNldCdcbl0pXG4iLCJtb2R1bGUuZXhwb3J0cyA9IFtcbiAgLy8gS2VlcCB0aGlzIGxpc3Qgc29ydGVkXG4gICdhYnMnXG4gICwgJ2Fjb3MnXG4gICwgJ2FsbCdcbiAgLCAnYW55J1xuICAsICdhc2luJ1xuICAsICdhdGFuJ1xuICAsICdjZWlsJ1xuICAsICdjbGFtcCdcbiAgLCAnY29zJ1xuICAsICdjcm9zcydcbiAgLCAnZEZkeCdcbiAgLCAnZEZkeSdcbiAgLCAnZGVncmVlcydcbiAgLCAnZGlzdGFuY2UnXG4gICwgJ2RvdCdcbiAgLCAnZXF1YWwnXG4gICwgJ2V4cCdcbiAgLCAnZXhwMidcbiAgLCAnZmFjZWZvcndhcmQnXG4gICwgJ2Zsb29yJ1xuICAsICdmcmFjdCdcbiAgLCAnZ2xfQmFja0NvbG9yJ1xuICAsICdnbF9CYWNrTGlnaHRNb2RlbFByb2R1Y3QnXG4gICwgJ2dsX0JhY2tMaWdodFByb2R1Y3QnXG4gICwgJ2dsX0JhY2tNYXRlcmlhbCdcbiAgLCAnZ2xfQmFja1NlY29uZGFyeUNvbG9yJ1xuICAsICdnbF9DbGlwUGxhbmUnXG4gICwgJ2dsX0NsaXBWZXJ0ZXgnXG4gICwgJ2dsX0NvbG9yJ1xuICAsICdnbF9EZXB0aFJhbmdlJ1xuICAsICdnbF9EZXB0aFJhbmdlUGFyYW1ldGVycydcbiAgLCAnZ2xfRXllUGxhbmVRJ1xuICAsICdnbF9FeWVQbGFuZVInXG4gICwgJ2dsX0V5ZVBsYW5lUydcbiAgLCAnZ2xfRXllUGxhbmVUJ1xuICAsICdnbF9Gb2cnXG4gICwgJ2dsX0ZvZ0Nvb3JkJ1xuICAsICdnbF9Gb2dGcmFnQ29vcmQnXG4gICwgJ2dsX0ZvZ1BhcmFtZXRlcnMnXG4gICwgJ2dsX0ZyYWdDb2xvcidcbiAgLCAnZ2xfRnJhZ0Nvb3JkJ1xuICAsICdnbF9GcmFnRGF0YSdcbiAgLCAnZ2xfRnJhZ0RlcHRoJ1xuICAsICdnbF9GcmFnRGVwdGhFWFQnXG4gICwgJ2dsX0Zyb250Q29sb3InXG4gICwgJ2dsX0Zyb250RmFjaW5nJ1xuICAsICdnbF9Gcm9udExpZ2h0TW9kZWxQcm9kdWN0J1xuICAsICdnbF9Gcm9udExpZ2h0UHJvZHVjdCdcbiAgLCAnZ2xfRnJvbnRNYXRlcmlhbCdcbiAgLCAnZ2xfRnJvbnRTZWNvbmRhcnlDb2xvcidcbiAgLCAnZ2xfTGlnaHRNb2RlbCdcbiAgLCAnZ2xfTGlnaHRNb2RlbFBhcmFtZXRlcnMnXG4gICwgJ2dsX0xpZ2h0TW9kZWxQcm9kdWN0cydcbiAgLCAnZ2xfTGlnaHRQcm9kdWN0cydcbiAgLCAnZ2xfTGlnaHRTb3VyY2UnXG4gICwgJ2dsX0xpZ2h0U291cmNlUGFyYW1ldGVycydcbiAgLCAnZ2xfTWF0ZXJpYWxQYXJhbWV0ZXJzJ1xuICAsICdnbF9NYXhDbGlwUGxhbmVzJ1xuICAsICdnbF9NYXhDb21iaW5lZFRleHR1cmVJbWFnZVVuaXRzJ1xuICAsICdnbF9NYXhEcmF3QnVmZmVycydcbiAgLCAnZ2xfTWF4RnJhZ21lbnRVbmlmb3JtQ29tcG9uZW50cydcbiAgLCAnZ2xfTWF4TGlnaHRzJ1xuICAsICdnbF9NYXhUZXh0dXJlQ29vcmRzJ1xuICAsICdnbF9NYXhUZXh0dXJlSW1hZ2VVbml0cydcbiAgLCAnZ2xfTWF4VGV4dHVyZVVuaXRzJ1xuICAsICdnbF9NYXhWYXJ5aW5nRmxvYXRzJ1xuICAsICdnbF9NYXhWZXJ0ZXhBdHRyaWJzJ1xuICAsICdnbF9NYXhWZXJ0ZXhUZXh0dXJlSW1hZ2VVbml0cydcbiAgLCAnZ2xfTWF4VmVydGV4VW5pZm9ybUNvbXBvbmVudHMnXG4gICwgJ2dsX01vZGVsVmlld01hdHJpeCdcbiAgLCAnZ2xfTW9kZWxWaWV3TWF0cml4SW52ZXJzZSdcbiAgLCAnZ2xfTW9kZWxWaWV3TWF0cml4SW52ZXJzZVRyYW5zcG9zZSdcbiAgLCAnZ2xfTW9kZWxWaWV3TWF0cml4VHJhbnNwb3NlJ1xuICAsICdnbF9Nb2RlbFZpZXdQcm9qZWN0aW9uTWF0cml4J1xuICAsICdnbF9Nb2RlbFZpZXdQcm9qZWN0aW9uTWF0cml4SW52ZXJzZSdcbiAgLCAnZ2xfTW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeEludmVyc2VUcmFuc3Bvc2UnXG4gICwgJ2dsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXhUcmFuc3Bvc2UnXG4gICwgJ2dsX011bHRpVGV4Q29vcmQwJ1xuICAsICdnbF9NdWx0aVRleENvb3JkMSdcbiAgLCAnZ2xfTXVsdGlUZXhDb29yZDInXG4gICwgJ2dsX011bHRpVGV4Q29vcmQzJ1xuICAsICdnbF9NdWx0aVRleENvb3JkNCdcbiAgLCAnZ2xfTXVsdGlUZXhDb29yZDUnXG4gICwgJ2dsX011bHRpVGV4Q29vcmQ2J1xuICAsICdnbF9NdWx0aVRleENvb3JkNydcbiAgLCAnZ2xfTm9ybWFsJ1xuICAsICdnbF9Ob3JtYWxNYXRyaXgnXG4gICwgJ2dsX05vcm1hbFNjYWxlJ1xuICAsICdnbF9PYmplY3RQbGFuZVEnXG4gICwgJ2dsX09iamVjdFBsYW5lUidcbiAgLCAnZ2xfT2JqZWN0UGxhbmVTJ1xuICAsICdnbF9PYmplY3RQbGFuZVQnXG4gICwgJ2dsX1BvaW50J1xuICAsICdnbF9Qb2ludENvb3JkJ1xuICAsICdnbF9Qb2ludFBhcmFtZXRlcnMnXG4gICwgJ2dsX1BvaW50U2l6ZSdcbiAgLCAnZ2xfUG9zaXRpb24nXG4gICwgJ2dsX1Byb2plY3Rpb25NYXRyaXgnXG4gICwgJ2dsX1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlJ1xuICAsICdnbF9Qcm9qZWN0aW9uTWF0cml4SW52ZXJzZVRyYW5zcG9zZSdcbiAgLCAnZ2xfUHJvamVjdGlvbk1hdHJpeFRyYW5zcG9zZSdcbiAgLCAnZ2xfU2Vjb25kYXJ5Q29sb3InXG4gICwgJ2dsX1RleENvb3JkJ1xuICAsICdnbF9UZXh0dXJlRW52Q29sb3InXG4gICwgJ2dsX1RleHR1cmVNYXRyaXgnXG4gICwgJ2dsX1RleHR1cmVNYXRyaXhJbnZlcnNlJ1xuICAsICdnbF9UZXh0dXJlTWF0cml4SW52ZXJzZVRyYW5zcG9zZSdcbiAgLCAnZ2xfVGV4dHVyZU1hdHJpeFRyYW5zcG9zZSdcbiAgLCAnZ2xfVmVydGV4J1xuICAsICdncmVhdGVyVGhhbidcbiAgLCAnZ3JlYXRlclRoYW5FcXVhbCdcbiAgLCAnaW52ZXJzZXNxcnQnXG4gICwgJ2xlbmd0aCdcbiAgLCAnbGVzc1RoYW4nXG4gICwgJ2xlc3NUaGFuRXF1YWwnXG4gICwgJ2xvZydcbiAgLCAnbG9nMidcbiAgLCAnbWF0cml4Q29tcE11bHQnXG4gICwgJ21heCdcbiAgLCAnbWluJ1xuICAsICdtaXgnXG4gICwgJ21vZCdcbiAgLCAnbm9ybWFsaXplJ1xuICAsICdub3QnXG4gICwgJ25vdEVxdWFsJ1xuICAsICdwb3cnXG4gICwgJ3JhZGlhbnMnXG4gICwgJ3JlZmxlY3QnXG4gICwgJ3JlZnJhY3QnXG4gICwgJ3NpZ24nXG4gICwgJ3NpbidcbiAgLCAnc21vb3Roc3RlcCdcbiAgLCAnc3FydCdcbiAgLCAnc3RlcCdcbiAgLCAndGFuJ1xuICAsICd0ZXh0dXJlMkQnXG4gICwgJ3RleHR1cmUyRExvZCdcbiAgLCAndGV4dHVyZTJEUHJvaidcbiAgLCAndGV4dHVyZTJEUHJvakxvZCdcbiAgLCAndGV4dHVyZUN1YmUnXG4gICwgJ3RleHR1cmVDdWJlTG9kJ1xuICAsICd0ZXh0dXJlMkRMb2RFWFQnXG4gICwgJ3RleHR1cmUyRFByb2pMb2RFWFQnXG4gICwgJ3RleHR1cmVDdWJlTG9kRVhUJ1xuICAsICd0ZXh0dXJlMkRHcmFkRVhUJ1xuICAsICd0ZXh0dXJlMkRQcm9qR3JhZEVYVCdcbiAgLCAndGV4dHVyZUN1YmVHcmFkRVhUJ1xuXVxuIiwidmFyIHYxMDAgPSByZXF1aXJlKCcuL2xpdGVyYWxzJylcblxubW9kdWxlLmV4cG9ydHMgPSB2MTAwLnNsaWNlKCkuY29uY2F0KFtcbiAgICdsYXlvdXQnXG4gICwgJ2NlbnRyb2lkJ1xuICAsICdzbW9vdGgnXG4gICwgJ2Nhc2UnXG4gICwgJ21hdDJ4MidcbiAgLCAnbWF0MngzJ1xuICAsICdtYXQyeDQnXG4gICwgJ21hdDN4MidcbiAgLCAnbWF0M3gzJ1xuICAsICdtYXQzeDQnXG4gICwgJ21hdDR4MidcbiAgLCAnbWF0NHgzJ1xuICAsICdtYXQ0eDQnXG4gICwgJ3VpbnQnXG4gICwgJ3V2ZWMyJ1xuICAsICd1dmVjMydcbiAgLCAndXZlYzQnXG4gICwgJ3NhbXBsZXJDdWJlU2hhZG93J1xuICAsICdzYW1wbGVyMkRBcnJheSdcbiAgLCAnc2FtcGxlcjJEQXJyYXlTaGFkb3cnXG4gICwgJ2lzYW1wbGVyMkQnXG4gICwgJ2lzYW1wbGVyM0QnXG4gICwgJ2lzYW1wbGVyQ3ViZSdcbiAgLCAnaXNhbXBsZXIyREFycmF5J1xuICAsICd1c2FtcGxlcjJEJ1xuICAsICd1c2FtcGxlcjNEJ1xuICAsICd1c2FtcGxlckN1YmUnXG4gICwgJ3VzYW1wbGVyMkRBcnJheSdcbiAgLCAnY29oZXJlbnQnXG4gICwgJ3Jlc3RyaWN0J1xuICAsICdyZWFkb25seSdcbiAgLCAnd3JpdGVvbmx5J1xuICAsICdyZXNvdXJjZSdcbiAgLCAnYXRvbWljX3VpbnQnXG4gICwgJ25vcGVyc3BlY3RpdmUnXG4gICwgJ3BhdGNoJ1xuICAsICdzYW1wbGUnXG4gICwgJ3N1YnJvdXRpbmUnXG4gICwgJ2NvbW1vbidcbiAgLCAncGFydGl0aW9uJ1xuICAsICdhY3RpdmUnXG4gICwgJ2ZpbHRlcidcbiAgLCAnaW1hZ2UxRCdcbiAgLCAnaW1hZ2UyRCdcbiAgLCAnaW1hZ2UzRCdcbiAgLCAnaW1hZ2VDdWJlJ1xuICAsICdpaW1hZ2UxRCdcbiAgLCAnaWltYWdlMkQnXG4gICwgJ2lpbWFnZTNEJ1xuICAsICdpaW1hZ2VDdWJlJ1xuICAsICd1aW1hZ2UxRCdcbiAgLCAndWltYWdlMkQnXG4gICwgJ3VpbWFnZTNEJ1xuICAsICd1aW1hZ2VDdWJlJ1xuICAsICdpbWFnZTFEQXJyYXknXG4gICwgJ2ltYWdlMkRBcnJheSdcbiAgLCAnaWltYWdlMURBcnJheSdcbiAgLCAnaWltYWdlMkRBcnJheSdcbiAgLCAndWltYWdlMURBcnJheSdcbiAgLCAndWltYWdlMkRBcnJheSdcbiAgLCAnaW1hZ2UxRFNoYWRvdydcbiAgLCAnaW1hZ2UyRFNoYWRvdydcbiAgLCAnaW1hZ2UxREFycmF5U2hhZG93J1xuICAsICdpbWFnZTJEQXJyYXlTaGFkb3cnXG4gICwgJ2ltYWdlQnVmZmVyJ1xuICAsICdpaW1hZ2VCdWZmZXInXG4gICwgJ3VpbWFnZUJ1ZmZlcidcbiAgLCAnc2FtcGxlcjFEQXJyYXknXG4gICwgJ3NhbXBsZXIxREFycmF5U2hhZG93J1xuICAsICdpc2FtcGxlcjFEJ1xuICAsICdpc2FtcGxlcjFEQXJyYXknXG4gICwgJ3VzYW1wbGVyMUQnXG4gICwgJ3VzYW1wbGVyMURBcnJheSdcbiAgLCAnaXNhbXBsZXIyRFJlY3QnXG4gICwgJ3VzYW1wbGVyMkRSZWN0J1xuICAsICdzYW1wbGVyQnVmZmVyJ1xuICAsICdpc2FtcGxlckJ1ZmZlcidcbiAgLCAndXNhbXBsZXJCdWZmZXInXG4gICwgJ3NhbXBsZXIyRE1TJ1xuICAsICdpc2FtcGxlcjJETVMnXG4gICwgJ3VzYW1wbGVyMkRNUydcbiAgLCAnc2FtcGxlcjJETVNBcnJheSdcbiAgLCAnaXNhbXBsZXIyRE1TQXJyYXknXG4gICwgJ3VzYW1wbGVyMkRNU0FycmF5J1xuXSlcbiIsIm1vZHVsZS5leHBvcnRzID0gW1xuICAvLyBjdXJyZW50XG4gICAgJ3ByZWNpc2lvbidcbiAgLCAnaGlnaHAnXG4gICwgJ21lZGl1bXAnXG4gICwgJ2xvd3AnXG4gICwgJ2F0dHJpYnV0ZSdcbiAgLCAnY29uc3QnXG4gICwgJ3VuaWZvcm0nXG4gICwgJ3ZhcnlpbmcnXG4gICwgJ2JyZWFrJ1xuICAsICdjb250aW51ZSdcbiAgLCAnZG8nXG4gICwgJ2ZvcidcbiAgLCAnd2hpbGUnXG4gICwgJ2lmJ1xuICAsICdlbHNlJ1xuICAsICdpbidcbiAgLCAnb3V0J1xuICAsICdpbm91dCdcbiAgLCAnZmxvYXQnXG4gICwgJ2ludCdcbiAgLCAndm9pZCdcbiAgLCAnYm9vbCdcbiAgLCAndHJ1ZSdcbiAgLCAnZmFsc2UnXG4gICwgJ2Rpc2NhcmQnXG4gICwgJ3JldHVybidcbiAgLCAnbWF0MidcbiAgLCAnbWF0MydcbiAgLCAnbWF0NCdcbiAgLCAndmVjMidcbiAgLCAndmVjMydcbiAgLCAndmVjNCdcbiAgLCAnaXZlYzInXG4gICwgJ2l2ZWMzJ1xuICAsICdpdmVjNCdcbiAgLCAnYnZlYzInXG4gICwgJ2J2ZWMzJ1xuICAsICdidmVjNCdcbiAgLCAnc2FtcGxlcjFEJ1xuICAsICdzYW1wbGVyMkQnXG4gICwgJ3NhbXBsZXIzRCdcbiAgLCAnc2FtcGxlckN1YmUnXG4gICwgJ3NhbXBsZXIxRFNoYWRvdydcbiAgLCAnc2FtcGxlcjJEU2hhZG93J1xuICAsICdzdHJ1Y3QnXG5cbiAgLy8gZnV0dXJlXG4gICwgJ2FzbSdcbiAgLCAnY2xhc3MnXG4gICwgJ3VuaW9uJ1xuICAsICdlbnVtJ1xuICAsICd0eXBlZGVmJ1xuICAsICd0ZW1wbGF0ZSdcbiAgLCAndGhpcydcbiAgLCAncGFja2VkJ1xuICAsICdnb3RvJ1xuICAsICdzd2l0Y2gnXG4gICwgJ2RlZmF1bHQnXG4gICwgJ2lubGluZSdcbiAgLCAnbm9pbmxpbmUnXG4gICwgJ3ZvbGF0aWxlJ1xuICAsICdwdWJsaWMnXG4gICwgJ3N0YXRpYydcbiAgLCAnZXh0ZXJuJ1xuICAsICdleHRlcm5hbCdcbiAgLCAnaW50ZXJmYWNlJ1xuICAsICdsb25nJ1xuICAsICdzaG9ydCdcbiAgLCAnZG91YmxlJ1xuICAsICdoYWxmJ1xuICAsICdmaXhlZCdcbiAgLCAndW5zaWduZWQnXG4gICwgJ2lucHV0J1xuICAsICdvdXRwdXQnXG4gICwgJ2h2ZWMyJ1xuICAsICdodmVjMydcbiAgLCAnaHZlYzQnXG4gICwgJ2R2ZWMyJ1xuICAsICdkdmVjMydcbiAgLCAnZHZlYzQnXG4gICwgJ2Z2ZWMyJ1xuICAsICdmdmVjMydcbiAgLCAnZnZlYzQnXG4gICwgJ3NhbXBsZXIyRFJlY3QnXG4gICwgJ3NhbXBsZXIzRFJlY3QnXG4gICwgJ3NhbXBsZXIyRFJlY3RTaGFkb3cnXG4gICwgJ3NpemVvZidcbiAgLCAnY2FzdCdcbiAgLCAnbmFtZXNwYWNlJ1xuICAsICd1c2luZydcbl1cbiIsIm1vZHVsZS5leHBvcnRzID0gW1xuICAgICc8PD0nXG4gICwgJz4+PSdcbiAgLCAnKysnXG4gICwgJy0tJ1xuICAsICc8PCdcbiAgLCAnPj4nXG4gICwgJzw9J1xuICAsICc+PSdcbiAgLCAnPT0nXG4gICwgJyE9J1xuICAsICcmJidcbiAgLCAnfHwnXG4gICwgJys9J1xuICAsICctPSdcbiAgLCAnKj0nXG4gICwgJy89J1xuICAsICclPSdcbiAgLCAnJj0nXG4gICwgJ15eJ1xuICAsICdePSdcbiAgLCAnfD0nXG4gICwgJygnXG4gICwgJyknXG4gICwgJ1snXG4gICwgJ10nXG4gICwgJy4nXG4gICwgJyEnXG4gICwgJ34nXG4gICwgJyonXG4gICwgJy8nXG4gICwgJyUnXG4gICwgJysnXG4gICwgJy0nXG4gICwgJzwnXG4gICwgJz4nXG4gICwgJyYnXG4gICwgJ14nXG4gICwgJ3wnXG4gICwgJz8nXG4gICwgJzonXG4gICwgJz0nXG4gICwgJywnXG4gICwgJzsnXG4gICwgJ3snXG4gICwgJ30nXG5dXG4iLCJ2YXIgdG9rZW5pemUgPSByZXF1aXJlKCcuL2luZGV4JylcblxubW9kdWxlLmV4cG9ydHMgPSB0b2tlbml6ZVN0cmluZ1xuXG5mdW5jdGlvbiB0b2tlbml6ZVN0cmluZyhzdHIsIG9wdCkge1xuICB2YXIgZ2VuZXJhdG9yID0gdG9rZW5pemUob3B0KVxuICB2YXIgdG9rZW5zID0gW11cblxuICB0b2tlbnMgPSB0b2tlbnMuY29uY2F0KGdlbmVyYXRvcihzdHIpKVxuICB0b2tlbnMgPSB0b2tlbnMuY29uY2F0KGdlbmVyYXRvcihudWxsKSlcblxuICByZXR1cm4gdG9rZW5zXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cmluZ3MpIHtcclxuICBpZiAodHlwZW9mIHN0cmluZ3MgPT09ICdzdHJpbmcnKSBzdHJpbmdzID0gW3N0cmluZ3NdXHJcbiAgdmFyIGV4cHJzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsMSlcclxuICB2YXIgcGFydHMgPSBbXVxyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5ncy5sZW5ndGgtMTsgaSsrKSB7XHJcbiAgICBwYXJ0cy5wdXNoKHN0cmluZ3NbaV0sIGV4cHJzW2ldIHx8ICcnKVxyXG4gIH1cclxuICBwYXJ0cy5wdXNoKHN0cmluZ3NbaV0pXHJcbiAgcmV0dXJuIHBhcnRzLmpvaW4oJycpXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgaXNCcm93c2VyID0gcmVxdWlyZSgnaXMtYnJvd3NlcicpXHJcbnZhciBoYXNIb3ZlclxyXG5cclxuaWYgKHR5cGVvZiBnbG9iYWwubWF0Y2hNZWRpYSA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdGhhc0hvdmVyID0gIWdsb2JhbC5tYXRjaE1lZGlhKCcoaG92ZXI6IG5vbmUpJykubWF0Y2hlc1xyXG59XHJcbmVsc2Uge1xyXG5cdGhhc0hvdmVyID0gaXNCcm93c2VyXHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gaGFzSG92ZXJcclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgaXNCcm93c2VyID0gcmVxdWlyZSgnaXMtYnJvd3NlcicpXHJcblxyXG5mdW5jdGlvbiBkZXRlY3QoKSB7XHJcblx0dmFyIHN1cHBvcnRlZCA9IGZhbHNlXHJcblxyXG5cdHRyeSB7XHJcblx0XHR2YXIgb3B0cyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ3Bhc3NpdmUnLCB7XHJcblx0XHRcdGdldDogZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0c3VwcG9ydGVkID0gdHJ1ZVxyXG5cdFx0XHR9XHJcblx0XHR9KVxyXG5cclxuXHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgbnVsbCwgb3B0cylcclxuXHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd0ZXN0JywgbnVsbCwgb3B0cylcclxuXHR9IGNhdGNoKGUpIHtcclxuXHRcdHN1cHBvcnRlZCA9IGZhbHNlXHJcblx0fVxyXG5cclxuXHRyZXR1cm4gc3VwcG9ydGVkXHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gaXNCcm93c2VyICYmIGRldGVjdCgpXHJcbiIsImV4cG9ydHMucmVhZCA9IGZ1bmN0aW9uIChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gKGUgKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gKG0gKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzXG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KVxuICB9IGVsc2Uge1xuICAgIG0gPSBtICsgTWF0aC5wb3coMiwgbUxlbilcbiAgICBlID0gZSAtIGVCaWFzXG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbilcbn1cblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uIChidWZmZXIsIHZhbHVlLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSwgY1xuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAoKHZhbHVlICogYykgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbi8vSGlnaCBsZXZlbCBpZGVhOlxuLy8gMS4gVXNlIENsYXJrc29uJ3MgaW5jcmVtZW50YWwgY29uc3RydWN0aW9uIHRvIGZpbmQgY29udmV4IGh1bGxcbi8vIDIuIFBvaW50IGxvY2F0aW9uIGluIHRyaWFuZ3VsYXRpb24gYnkganVtcCBhbmQgd2Fsa1xuXG5tb2R1bGUuZXhwb3J0cyA9IGluY3JlbWVudGFsQ29udmV4SHVsbFxuXG52YXIgb3JpZW50ID0gcmVxdWlyZShcInJvYnVzdC1vcmllbnRhdGlvblwiKVxudmFyIGNvbXBhcmVDZWxsID0gcmVxdWlyZShcInNpbXBsaWNpYWwtY29tcGxleFwiKS5jb21wYXJlQ2VsbHNcblxuZnVuY3Rpb24gY29tcGFyZUludChhLCBiKSB7XG4gIHJldHVybiBhIC0gYlxufVxuXG5mdW5jdGlvbiBTaW1wbGV4KHZlcnRpY2VzLCBhZGphY2VudCwgYm91bmRhcnkpIHtcbiAgdGhpcy52ZXJ0aWNlcyA9IHZlcnRpY2VzXG4gIHRoaXMuYWRqYWNlbnQgPSBhZGphY2VudFxuICB0aGlzLmJvdW5kYXJ5ID0gYm91bmRhcnlcbiAgdGhpcy5sYXN0VmlzaXRlZCA9IC0xXG59XG5cblNpbXBsZXgucHJvdG90eXBlLmZsaXAgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHQgPSB0aGlzLnZlcnRpY2VzWzBdXG4gIHRoaXMudmVydGljZXNbMF0gPSB0aGlzLnZlcnRpY2VzWzFdXG4gIHRoaXMudmVydGljZXNbMV0gPSB0XG4gIHZhciB1ID0gdGhpcy5hZGphY2VudFswXVxuICB0aGlzLmFkamFjZW50WzBdID0gdGhpcy5hZGphY2VudFsxXVxuICB0aGlzLmFkamFjZW50WzFdID0gdVxufVxuXG5mdW5jdGlvbiBHbHVlRmFjZXQodmVydGljZXMsIGNlbGwsIGluZGV4KSB7XG4gIHRoaXMudmVydGljZXMgPSB2ZXJ0aWNlc1xuICB0aGlzLmNlbGwgPSBjZWxsXG4gIHRoaXMuaW5kZXggPSBpbmRleFxufVxuXG5mdW5jdGlvbiBjb21wYXJlR2x1ZShhLCBiKSB7XG4gIHJldHVybiBjb21wYXJlQ2VsbChhLnZlcnRpY2VzLCBiLnZlcnRpY2VzKVxufVxuXG5mdW5jdGlvbiBiYWtlT3JpZW50KGQpIHtcbiAgdmFyIGNvZGUgPSBbXCJmdW5jdGlvbiBvcmllbnQoKXt2YXIgdHVwbGU9dGhpcy50dXBsZTtyZXR1cm4gdGVzdChcIl1cbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIGlmKGkgPiAwKSB7XG4gICAgICBjb2RlLnB1c2goXCIsXCIpXG4gICAgfVxuICAgIGNvZGUucHVzaChcInR1cGxlW1wiLCBpLCBcIl1cIilcbiAgfVxuICBjb2RlLnB1c2goXCIpfXJldHVybiBvcmllbnRcIilcbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oXCJ0ZXN0XCIsIGNvZGUuam9pbihcIlwiKSlcbiAgdmFyIHRlc3QgPSBvcmllbnRbZCsxXVxuICBpZighdGVzdCkge1xuICAgIHRlc3QgPSBvcmllbnRcbiAgfVxuICByZXR1cm4gcHJvYyh0ZXN0KVxufVxuXG52YXIgQkFLRUQgPSBbXVxuXG5mdW5jdGlvbiBUcmlhbmd1bGF0aW9uKGRpbWVuc2lvbiwgdmVydGljZXMsIHNpbXBsaWNlcykge1xuICB0aGlzLmRpbWVuc2lvbiA9IGRpbWVuc2lvblxuICB0aGlzLnZlcnRpY2VzID0gdmVydGljZXNcbiAgdGhpcy5zaW1wbGljZXMgPSBzaW1wbGljZXNcbiAgdGhpcy5pbnRlcmlvciA9IHNpbXBsaWNlcy5maWx0ZXIoZnVuY3Rpb24oYykge1xuICAgIHJldHVybiAhYy5ib3VuZGFyeVxuICB9KVxuXG4gIHRoaXMudHVwbGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKzEpXG4gIGZvcih2YXIgaT0wOyBpPD1kaW1lbnNpb247ICsraSkge1xuICAgIHRoaXMudHVwbGVbaV0gPSB0aGlzLnZlcnRpY2VzW2ldXG4gIH1cblxuICB2YXIgbyA9IEJBS0VEW2RpbWVuc2lvbl1cbiAgaWYoIW8pIHtcbiAgICBvID0gQkFLRURbZGltZW5zaW9uXSA9IGJha2VPcmllbnQoZGltZW5zaW9uKVxuICB9XG4gIHRoaXMub3JpZW50ID0gb1xufVxuXG52YXIgcHJvdG8gPSBUcmlhbmd1bGF0aW9uLnByb3RvdHlwZVxuXG4vL0RlZ2VuZXJhdGUgc2l0dWF0aW9uIHdoZXJlIHdlIGFyZSBvbiBib3VuZGFyeSwgYnV0IGNvcGxhbmFyIHRvIGZhY2VcbnByb3RvLmhhbmRsZUJvdW5kYXJ5RGVnZW5lcmFjeSA9IGZ1bmN0aW9uKGNlbGwsIHBvaW50KSB7XG4gIHZhciBkID0gdGhpcy5kaW1lbnNpb25cbiAgdmFyIG4gPSB0aGlzLnZlcnRpY2VzLmxlbmd0aCAtIDFcbiAgdmFyIHR1cGxlID0gdGhpcy50dXBsZVxuICB2YXIgdmVydHMgPSB0aGlzLnZlcnRpY2VzXG5cbiAgLy9EdW1iIHNvbHV0aW9uOiBKdXN0IGRvIGRmcyBmcm9tIGJvdW5kYXJ5IGNlbGwgdW50aWwgd2UgZmluZCBhbnkgcGVhaywgb3IgdGVybWluYXRlXG4gIHZhciB0b1Zpc2l0ID0gWyBjZWxsIF1cbiAgY2VsbC5sYXN0VmlzaXRlZCA9IC1uXG4gIHdoaWxlKHRvVmlzaXQubGVuZ3RoID4gMCkge1xuICAgIGNlbGwgPSB0b1Zpc2l0LnBvcCgpXG4gICAgdmFyIGNlbGxWZXJ0cyA9IGNlbGwudmVydGljZXNcbiAgICB2YXIgY2VsbEFkaiA9IGNlbGwuYWRqYWNlbnRcbiAgICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgICB2YXIgbmVpZ2hib3IgPSBjZWxsQWRqW2ldXG4gICAgICBpZighbmVpZ2hib3IuYm91bmRhcnkgfHwgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPD0gLW4pIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHZhciBudiA9IG5laWdoYm9yLnZlcnRpY2VzXG4gICAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICAgIHZhciB2diA9IG52W2pdXG4gICAgICAgIGlmKHZ2IDwgMCkge1xuICAgICAgICAgIHR1cGxlW2pdID0gcG9pbnRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0dXBsZVtqXSA9IHZlcnRzW3Z2XVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgbyA9IHRoaXMub3JpZW50KClcbiAgICAgIGlmKG8gPiAwKSB7XG4gICAgICAgIHJldHVybiBuZWlnaGJvclxuICAgICAgfVxuICAgICAgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPSAtblxuICAgICAgaWYobyA9PT0gMCkge1xuICAgICAgICB0b1Zpc2l0LnB1c2gobmVpZ2hib3IpXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsXG59XG5cbnByb3RvLndhbGsgPSBmdW5jdGlvbihwb2ludCwgcmFuZG9tKSB7XG4gIC8vQWxpYXMgbG9jYWwgcHJvcGVydGllc1xuICB2YXIgbiA9IHRoaXMudmVydGljZXMubGVuZ3RoIC0gMVxuICB2YXIgZCA9IHRoaXMuZGltZW5zaW9uXG4gIHZhciB2ZXJ0cyA9IHRoaXMudmVydGljZXNcbiAgdmFyIHR1cGxlID0gdGhpcy50dXBsZVxuXG4gIC8vQ29tcHV0ZSBpbml0aWFsIGp1bXAgY2VsbFxuICB2YXIgaW5pdEluZGV4ID0gcmFuZG9tID8gKHRoaXMuaW50ZXJpb3IubGVuZ3RoICogTWF0aC5yYW5kb20oKSl8MCA6ICh0aGlzLmludGVyaW9yLmxlbmd0aC0xKVxuICB2YXIgY2VsbCA9IHRoaXMuaW50ZXJpb3JbIGluaXRJbmRleCBdXG5cbiAgLy9TdGFydCB3YWxraW5nXG5vdXRlckxvb3A6XG4gIHdoaWxlKCFjZWxsLmJvdW5kYXJ5KSB7XG4gICAgdmFyIGNlbGxWZXJ0cyA9IGNlbGwudmVydGljZXNcbiAgICB2YXIgY2VsbEFkaiA9IGNlbGwuYWRqYWNlbnRcblxuICAgIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICAgIHR1cGxlW2ldID0gdmVydHNbY2VsbFZlcnRzW2ldXVxuICAgIH1cbiAgICBjZWxsLmxhc3RWaXNpdGVkID0gblxuXG4gICAgLy9GaW5kIGZhcnRoZXN0IGFkamFjZW50IGNlbGxcbiAgICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgICB2YXIgbmVpZ2hib3IgPSBjZWxsQWRqW2ldXG4gICAgICBpZihuZWlnaGJvci5sYXN0VmlzaXRlZCA+PSBuKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICB2YXIgcHJldiA9IHR1cGxlW2ldXG4gICAgICB0dXBsZVtpXSA9IHBvaW50XG4gICAgICB2YXIgbyA9IHRoaXMub3JpZW50KClcbiAgICAgIHR1cGxlW2ldID0gcHJldlxuICAgICAgaWYobyA8IDApIHtcbiAgICAgICAgY2VsbCA9IG5laWdoYm9yXG4gICAgICAgIGNvbnRpbnVlIG91dGVyTG9vcFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYoIW5laWdoYm9yLmJvdW5kYXJ5KSB7XG4gICAgICAgICAgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPSBuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPSAtblxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVyblxuICB9XG5cbiAgcmV0dXJuIGNlbGxcbn1cblxucHJvdG8uYWRkUGVha3MgPSBmdW5jdGlvbihwb2ludCwgY2VsbCkge1xuICB2YXIgbiA9IHRoaXMudmVydGljZXMubGVuZ3RoIC0gMVxuICB2YXIgZCA9IHRoaXMuZGltZW5zaW9uXG4gIHZhciB2ZXJ0cyA9IHRoaXMudmVydGljZXNcbiAgdmFyIHR1cGxlID0gdGhpcy50dXBsZVxuICB2YXIgaW50ZXJpb3IgPSB0aGlzLmludGVyaW9yXG4gIHZhciBzaW1wbGljZXMgPSB0aGlzLnNpbXBsaWNlc1xuXG4gIC8vV2Fsa2luZyBmaW5pc2hlZCBhdCBib3VuZGFyeSwgdGltZSB0byBhZGQgcGVha3NcbiAgdmFyIHRvdmlzaXQgPSBbIGNlbGwgXVxuXG4gIC8vU3RyZXRjaCBpbml0aWFsIGJvdW5kYXJ5IGNlbGwgaW50byBhIHBlYWtcbiAgY2VsbC5sYXN0VmlzaXRlZCA9IG5cbiAgY2VsbC52ZXJ0aWNlc1tjZWxsLnZlcnRpY2VzLmluZGV4T2YoLTEpXSA9IG5cbiAgY2VsbC5ib3VuZGFyeSA9IGZhbHNlXG4gIGludGVyaW9yLnB1c2goY2VsbClcblxuICAvL1JlY29yZCBhIGxpc3Qgb2YgYWxsIG5ldyBib3VuZGFyaWVzIGNyZWF0ZWQgYnkgYWRkZWQgcGVha3Mgc28gd2UgY2FuIGdsdWUgdGhlbSB0b2dldGhlciB3aGVuIHdlIGFyZSBhbGwgZG9uZVxuICB2YXIgZ2x1ZUZhY2V0cyA9IFtdXG5cbiAgLy9EbyBhIHRyYXZlcnNhbCBvZiB0aGUgYm91bmRhcnkgd2Fsa2luZyBvdXR3YXJkIGZyb20gc3RhcnRpbmcgcGVha1xuICB3aGlsZSh0b3Zpc2l0Lmxlbmd0aCA+IDApIHtcbiAgICAvL1BvcCBvZmYgcGVhayBhbmQgd2FsayBvdmVyIGFkamFjZW50IGNlbGxzXG4gICAgdmFyIGNlbGwgPSB0b3Zpc2l0LnBvcCgpXG4gICAgdmFyIGNlbGxWZXJ0cyA9IGNlbGwudmVydGljZXNcbiAgICB2YXIgY2VsbEFkaiA9IGNlbGwuYWRqYWNlbnRcbiAgICB2YXIgaW5kZXhPZk4gPSBjZWxsVmVydHMuaW5kZXhPZihuKVxuICAgIGlmKGluZGV4T2ZOIDwgMCkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgICBpZihpID09PSBpbmRleE9mTikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvL0ZvciBlYWNoIGJvdW5kYXJ5IG5laWdoYm9yIG9mIHRoZSBjZWxsXG4gICAgICB2YXIgbmVpZ2hib3IgPSBjZWxsQWRqW2ldXG4gICAgICBpZighbmVpZ2hib3IuYm91bmRhcnkgfHwgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPj0gbikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICB2YXIgbnYgPSBuZWlnaGJvci52ZXJ0aWNlc1xuXG4gICAgICAvL1Rlc3QgaWYgbmVpZ2hib3IgaXMgYSBwZWFrXG4gICAgICBpZihuZWlnaGJvci5sYXN0VmlzaXRlZCAhPT0gLW4pIHsgICAgICBcbiAgICAgICAgLy9Db21wdXRlIG9yaWVudGF0aW9uIG9mIHAgcmVsYXRpdmUgdG8gZWFjaCBib3VuZGFyeSBwZWFrXG4gICAgICAgIHZhciBpbmRleE9mTmVnMSA9IDBcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgICAgIGlmKG52W2pdIDwgMCkge1xuICAgICAgICAgICAgaW5kZXhPZk5lZzEgPSBqXG4gICAgICAgICAgICB0dXBsZVtqXSA9IHBvaW50XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHR1cGxlW2pdID0gdmVydHNbbnZbal1dXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBvID0gdGhpcy5vcmllbnQoKVxuXG4gICAgICAgIC8vVGVzdCBpZiBuZWlnaGJvciBjZWxsIGlzIGFsc28gYSBwZWFrXG4gICAgICAgIGlmKG8gPiAwKSB7XG4gICAgICAgICAgbnZbaW5kZXhPZk5lZzFdID0gblxuICAgICAgICAgIG5laWdoYm9yLmJvdW5kYXJ5ID0gZmFsc2VcbiAgICAgICAgICBpbnRlcmlvci5wdXNoKG5laWdoYm9yKVxuICAgICAgICAgIHRvdmlzaXQucHVzaChuZWlnaGJvcilcbiAgICAgICAgICBuZWlnaGJvci5sYXN0VmlzaXRlZCA9IG5cbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5laWdoYm9yLmxhc3RWaXNpdGVkID0gLW5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgbmEgPSBuZWlnaGJvci5hZGphY2VudFxuXG4gICAgICAvL090aGVyd2lzZSwgcmVwbGFjZSBuZWlnaGJvciB3aXRoIG5ldyBmYWNlXG4gICAgICB2YXIgdnZlcnRzID0gY2VsbFZlcnRzLnNsaWNlKClcbiAgICAgIHZhciB2YWRqID0gY2VsbEFkai5zbGljZSgpXG4gICAgICB2YXIgbmNlbGwgPSBuZXcgU2ltcGxleCh2dmVydHMsIHZhZGosIHRydWUpXG4gICAgICBzaW1wbGljZXMucHVzaChuY2VsbClcblxuICAgICAgLy9Db25uZWN0IHRvIG5laWdoYm9yXG4gICAgICB2YXIgb3Bwb3NpdGUgPSBuYS5pbmRleE9mKGNlbGwpXG4gICAgICBpZihvcHBvc2l0ZSA8IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIG5hW29wcG9zaXRlXSA9IG5jZWxsXG4gICAgICB2YWRqW2luZGV4T2ZOXSA9IG5laWdoYm9yXG5cbiAgICAgIC8vQ29ubmVjdCB0byBjZWxsXG4gICAgICB2dmVydHNbaV0gPSAtMVxuICAgICAgdmFkaltpXSA9IGNlbGxcbiAgICAgIGNlbGxBZGpbaV0gPSBuY2VsbFxuXG4gICAgICAvL0ZsaXAgZmFjZXRcbiAgICAgIG5jZWxsLmZsaXAoKVxuXG4gICAgICAvL0FkZCB0byBnbHVlIGxpc3RcbiAgICAgIGZvcih2YXIgaj0wOyBqPD1kOyArK2opIHtcbiAgICAgICAgdmFyIHV1ID0gdnZlcnRzW2pdXG4gICAgICAgIGlmKHV1IDwgMCB8fCB1dSA9PT0gbikge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5mYWNlID0gbmV3IEFycmF5KGQtMSlcbiAgICAgICAgdmFyIG5wdHIgPSAwXG4gICAgICAgIGZvcih2YXIgaz0wOyBrPD1kOyArK2spIHtcbiAgICAgICAgICB2YXIgdnYgPSB2dmVydHNba11cbiAgICAgICAgICBpZih2diA8IDAgfHwgayA9PT0gaikge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG4gICAgICAgICAgbmZhY2VbbnB0cisrXSA9IHZ2XG4gICAgICAgIH1cbiAgICAgICAgZ2x1ZUZhY2V0cy5wdXNoKG5ldyBHbHVlRmFjZXQobmZhY2UsIG5jZWxsLCBqKSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL0dsdWUgYm91bmRhcnkgZmFjZXRzIHRvZ2V0aGVyXG4gIGdsdWVGYWNldHMuc29ydChjb21wYXJlR2x1ZSlcblxuICBmb3IodmFyIGk9MDsgaSsxPGdsdWVGYWNldHMubGVuZ3RoOyBpKz0yKSB7XG4gICAgdmFyIGEgPSBnbHVlRmFjZXRzW2ldXG4gICAgdmFyIGIgPSBnbHVlRmFjZXRzW2krMV1cbiAgICB2YXIgYWkgPSBhLmluZGV4XG4gICAgdmFyIGJpID0gYi5pbmRleFxuICAgIGlmKGFpIDwgMCB8fCBiaSA8IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGEuY2VsbC5hZGphY2VudFthLmluZGV4XSA9IGIuY2VsbFxuICAgIGIuY2VsbC5hZGphY2VudFtiLmluZGV4XSA9IGEuY2VsbFxuICB9XG59XG5cbnByb3RvLmluc2VydCA9IGZ1bmN0aW9uKHBvaW50LCByYW5kb20pIHtcbiAgLy9BZGQgcG9pbnRcbiAgdmFyIHZlcnRzID0gdGhpcy52ZXJ0aWNlc1xuICB2ZXJ0cy5wdXNoKHBvaW50KVxuXG4gIHZhciBjZWxsID0gdGhpcy53YWxrKHBvaW50LCByYW5kb20pXG4gIGlmKCFjZWxsKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvL0FsaWFzIGxvY2FsIHByb3BlcnRpZXNcbiAgdmFyIGQgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgdHVwbGUgPSB0aGlzLnR1cGxlXG5cbiAgLy9EZWdlbmVyYXRlIGNhc2U6IElmIHBvaW50IGlzIGNvcGxhbmFyIHRvIGNlbGwsIHRoZW4gd2FsayB1bnRpbCB3ZSBmaW5kIGEgbm9uLWRlZ2VuZXJhdGUgYm91bmRhcnlcbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIHZhciB2diA9IGNlbGwudmVydGljZXNbaV1cbiAgICBpZih2diA8IDApIHtcbiAgICAgIHR1cGxlW2ldID0gcG9pbnRcbiAgICB9IGVsc2Uge1xuICAgICAgdHVwbGVbaV0gPSB2ZXJ0c1t2dl1cbiAgICB9XG4gIH1cbiAgdmFyIG8gPSB0aGlzLm9yaWVudCh0dXBsZSlcbiAgaWYobyA8IDApIHtcbiAgICByZXR1cm5cbiAgfSBlbHNlIGlmKG8gPT09IDApIHtcbiAgICBjZWxsID0gdGhpcy5oYW5kbGVCb3VuZGFyeURlZ2VuZXJhY3koY2VsbCwgcG9pbnQpXG4gICAgaWYoIWNlbGwpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgfVxuXG4gIC8vQWRkIHBlYWtzXG4gIHRoaXMuYWRkUGVha3MocG9pbnQsIGNlbGwpXG59XG5cbi8vRXh0cmFjdCBhbGwgYm91bmRhcnkgY2VsbHNcbnByb3RvLmJvdW5kYXJ5ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBkID0gdGhpcy5kaW1lbnNpb25cbiAgdmFyIGJvdW5kYXJ5ID0gW11cbiAgdmFyIGNlbGxzID0gdGhpcy5zaW1wbGljZXNcbiAgdmFyIG5jID0gY2VsbHMubGVuZ3RoXG4gIGZvcih2YXIgaT0wOyBpPG5jOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgaWYoYy5ib3VuZGFyeSkge1xuICAgICAgdmFyIGJjZWxsID0gbmV3IEFycmF5KGQpXG4gICAgICB2YXIgY3YgPSBjLnZlcnRpY2VzXG4gICAgICB2YXIgcHRyID0gMFxuICAgICAgdmFyIHBhcml0eSA9IDBcbiAgICAgIGZvcih2YXIgaj0wOyBqPD1kOyArK2opIHtcbiAgICAgICAgaWYoY3Zbal0gPj0gMCkge1xuICAgICAgICAgIGJjZWxsW3B0cisrXSA9IGN2W2pdXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyaXR5ID0gaiYxXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmKHBhcml0eSA9PT0gKGQmMSkpIHtcbiAgICAgICAgdmFyIHQgPSBiY2VsbFswXVxuICAgICAgICBiY2VsbFswXSA9IGJjZWxsWzFdXG4gICAgICAgIGJjZWxsWzFdID0gdFxuICAgICAgfVxuICAgICAgYm91bmRhcnkucHVzaChiY2VsbClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJvdW5kYXJ5XG59XG5cbmZ1bmN0aW9uIGluY3JlbWVudGFsQ29udmV4SHVsbChwb2ludHMsIHJhbmRvbVNlYXJjaCkge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcbiAgaWYobiA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIk11c3QgaGF2ZSBhdCBsZWFzdCBkKzEgcG9pbnRzXCIpXG4gIH1cbiAgdmFyIGQgPSBwb2ludHNbMF0ubGVuZ3RoXG4gIGlmKG4gPD0gZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIk11c3QgaW5wdXQgYXQgbGVhc3QgZCsxIHBvaW50c1wiKVxuICB9XG5cbiAgLy9GSVhNRTogVGhpcyBjb3VsZCBiZSBkZWdlbmVyYXRlLCBidXQgbmVlZCB0byBzZWxlY3QgZCsxIG5vbi1jb3BsYW5hciBwb2ludHMgdG8gYm9vdHN0cmFwIHByb2Nlc3NcbiAgdmFyIGluaXRpYWxTaW1wbGV4ID0gcG9pbnRzLnNsaWNlKDAsIGQrMSlcblxuICAvL01ha2Ugc3VyZSBpbml0aWFsIHNpbXBsZXggaXMgcG9zaXRpdmVseSBvcmllbnRlZFxuICB2YXIgbyA9IG9yaWVudC5hcHBseSh2b2lkIDAsIGluaXRpYWxTaW1wbGV4KVxuICBpZihvID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW5wdXQgbm90IGluIGdlbmVyYWwgcG9zaXRpb25cIilcbiAgfVxuICB2YXIgaW5pdGlhbENvb3JkcyA9IG5ldyBBcnJheShkKzEpXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICBpbml0aWFsQ29vcmRzW2ldID0gaVxuICB9XG4gIGlmKG8gPCAwKSB7XG4gICAgaW5pdGlhbENvb3Jkc1swXSA9IDFcbiAgICBpbml0aWFsQ29vcmRzWzFdID0gMFxuICB9XG5cbiAgLy9DcmVhdGUgaW5pdGlhbCB0b3BvbG9naWNhbCBpbmRleCwgZ2x1ZSBwb2ludGVycyB0b2dldGhlciAoa2luZCBvZiBtZXNzeSlcbiAgdmFyIGluaXRpYWxDZWxsID0gbmV3IFNpbXBsZXgoaW5pdGlhbENvb3JkcywgbmV3IEFycmF5KGQrMSksIGZhbHNlKVxuICB2YXIgYm91bmRhcnkgPSBpbml0aWFsQ2VsbC5hZGphY2VudFxuICB2YXIgbGlzdCA9IG5ldyBBcnJheShkKzIpXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICB2YXIgdmVydHMgPSBpbml0aWFsQ29vcmRzLnNsaWNlKClcbiAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICBpZihqID09PSBpKSB7XG4gICAgICAgIHZlcnRzW2pdID0gLTFcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHQgPSB2ZXJ0c1swXVxuICAgIHZlcnRzWzBdID0gdmVydHNbMV1cbiAgICB2ZXJ0c1sxXSA9IHRcbiAgICB2YXIgY2VsbCA9IG5ldyBTaW1wbGV4KHZlcnRzLCBuZXcgQXJyYXkoZCsxKSwgdHJ1ZSlcbiAgICBib3VuZGFyeVtpXSA9IGNlbGxcbiAgICBsaXN0W2ldID0gY2VsbFxuICB9XG4gIGxpc3RbZCsxXSA9IGluaXRpYWxDZWxsXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICB2YXIgdmVydHMgPSBib3VuZGFyeVtpXS52ZXJ0aWNlc1xuICAgIHZhciBhZGogPSBib3VuZGFyeVtpXS5hZGphY2VudFxuICAgIGZvcih2YXIgaj0wOyBqPD1kOyArK2opIHtcbiAgICAgIHZhciB2ID0gdmVydHNbal1cbiAgICAgIGlmKHYgPCAwKSB7XG4gICAgICAgIGFkaltqXSA9IGluaXRpYWxDZWxsXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBmb3IodmFyIGs9MDsgazw9ZDsgKytrKSB7XG4gICAgICAgIGlmKGJvdW5kYXJ5W2tdLnZlcnRpY2VzLmluZGV4T2YodikgPCAwKSB7XG4gICAgICAgICAgYWRqW2pdID0gYm91bmRhcnlba11cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vSW5pdGlhbGl6ZSB0cmlhbmdsZXNcbiAgdmFyIHRyaWFuZ2xlcyA9IG5ldyBUcmlhbmd1bGF0aW9uKGQsIGluaXRpYWxTaW1wbGV4LCBsaXN0KVxuXG4gIC8vSW5zZXJ0IHJlbWFpbmluZyBwb2ludHNcbiAgdmFyIHVzZVJhbmRvbSA9ICEhcmFuZG9tU2VhcmNoXG4gIGZvcih2YXIgaT1kKzE7IGk8bjsgKytpKSB7XG4gICAgdHJpYW5nbGVzLmluc2VydChwb2ludHNbaV0sIHVzZVJhbmRvbSlcbiAgfVxuICBcbiAgLy9FeHRyYWN0IGJvdW5kYXJ5IGNlbGxzXG4gIHJldHVybiB0cmlhbmdsZXMuYm91bmRhcnkoKVxufSIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBib3VuZHMgPSByZXF1aXJlKFwiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIilcblxudmFyIE5PVF9GT1VORCA9IDBcbnZhciBTVUNDRVNTID0gMVxudmFyIEVNUFRZID0gMlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVdyYXBwZXJcblxuZnVuY3Rpb24gSW50ZXJ2YWxUcmVlTm9kZShtaWQsIGxlZnQsIHJpZ2h0LCBsZWZ0UG9pbnRzLCByaWdodFBvaW50cykge1xuICB0aGlzLm1pZCA9IG1pZFxuICB0aGlzLmxlZnQgPSBsZWZ0XG4gIHRoaXMucmlnaHQgPSByaWdodFxuICB0aGlzLmxlZnRQb2ludHMgPSBsZWZ0UG9pbnRzXG4gIHRoaXMucmlnaHRQb2ludHMgPSByaWdodFBvaW50c1xuICB0aGlzLmNvdW50ID0gKGxlZnQgPyBsZWZ0LmNvdW50IDogMCkgKyAocmlnaHQgPyByaWdodC5jb3VudCA6IDApICsgbGVmdFBvaW50cy5sZW5ndGhcbn1cblxudmFyIHByb3RvID0gSW50ZXJ2YWxUcmVlTm9kZS5wcm90b3R5cGVcblxuZnVuY3Rpb24gY29weShhLCBiKSB7XG4gIGEubWlkID0gYi5taWRcbiAgYS5sZWZ0ID0gYi5sZWZ0XG4gIGEucmlnaHQgPSBiLnJpZ2h0XG4gIGEubGVmdFBvaW50cyA9IGIubGVmdFBvaW50c1xuICBhLnJpZ2h0UG9pbnRzID0gYi5yaWdodFBvaW50c1xuICBhLmNvdW50ID0gYi5jb3VudFxufVxuXG5mdW5jdGlvbiByZWJ1aWxkKG5vZGUsIGludGVydmFscykge1xuICB2YXIgbnRyZWUgPSBjcmVhdGVJbnRlcnZhbFRyZWUoaW50ZXJ2YWxzKVxuICBub2RlLm1pZCA9IG50cmVlLm1pZFxuICBub2RlLmxlZnQgPSBudHJlZS5sZWZ0XG4gIG5vZGUucmlnaHQgPSBudHJlZS5yaWdodFxuICBub2RlLmxlZnRQb2ludHMgPSBudHJlZS5sZWZ0UG9pbnRzXG4gIG5vZGUucmlnaHRQb2ludHMgPSBudHJlZS5yaWdodFBvaW50c1xuICBub2RlLmNvdW50ID0gbnRyZWUuY291bnRcbn1cblxuZnVuY3Rpb24gcmVidWlsZFdpdGhJbnRlcnZhbChub2RlLCBpbnRlcnZhbCkge1xuICB2YXIgaW50ZXJ2YWxzID0gbm9kZS5pbnRlcnZhbHMoW10pXG4gIGludGVydmFscy5wdXNoKGludGVydmFsKVxuICByZWJ1aWxkKG5vZGUsIGludGVydmFscykgICAgXG59XG5cbmZ1bmN0aW9uIHJlYnVpbGRXaXRob3V0SW50ZXJ2YWwobm9kZSwgaW50ZXJ2YWwpIHtcbiAgdmFyIGludGVydmFscyA9IG5vZGUuaW50ZXJ2YWxzKFtdKVxuICB2YXIgaWR4ID0gaW50ZXJ2YWxzLmluZGV4T2YoaW50ZXJ2YWwpXG4gIGlmKGlkeCA8IDApIHtcbiAgICByZXR1cm4gTk9UX0ZPVU5EXG4gIH1cbiAgaW50ZXJ2YWxzLnNwbGljZShpZHgsIDEpXG4gIHJlYnVpbGQobm9kZSwgaW50ZXJ2YWxzKVxuICByZXR1cm4gU1VDQ0VTU1xufVxuXG5wcm90by5pbnRlcnZhbHMgPSBmdW5jdGlvbihyZXN1bHQpIHtcbiAgcmVzdWx0LnB1c2guYXBwbHkocmVzdWx0LCB0aGlzLmxlZnRQb2ludHMpXG4gIGlmKHRoaXMubGVmdCkge1xuICAgIHRoaXMubGVmdC5pbnRlcnZhbHMocmVzdWx0KVxuICB9XG4gIGlmKHRoaXMucmlnaHQpIHtcbiAgICB0aGlzLnJpZ2h0LmludGVydmFscyhyZXN1bHQpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5pbnNlcnQgPSBmdW5jdGlvbihpbnRlcnZhbCkge1xuICB2YXIgd2VpZ2h0ID0gdGhpcy5jb3VudCAtIHRoaXMubGVmdFBvaW50cy5sZW5ndGhcbiAgdGhpcy5jb3VudCArPSAxXG4gIGlmKGludGVydmFsWzFdIDwgdGhpcy5taWQpIHtcbiAgICBpZih0aGlzLmxlZnQpIHtcbiAgICAgIGlmKDQqKHRoaXMubGVmdC5jb3VudCsxKSA+IDMqKHdlaWdodCsxKSkge1xuICAgICAgICByZWJ1aWxkV2l0aEludGVydmFsKHRoaXMsIGludGVydmFsKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sZWZ0Lmluc2VydChpbnRlcnZhbClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sZWZ0ID0gY3JlYXRlSW50ZXJ2YWxUcmVlKFtpbnRlcnZhbF0pXG4gICAgfVxuICB9IGVsc2UgaWYoaW50ZXJ2YWxbMF0gPiB0aGlzLm1pZCkge1xuICAgIGlmKHRoaXMucmlnaHQpIHtcbiAgICAgIGlmKDQqKHRoaXMucmlnaHQuY291bnQrMSkgPiAzKih3ZWlnaHQrMSkpIHtcbiAgICAgICAgcmVidWlsZFdpdGhJbnRlcnZhbCh0aGlzLCBpbnRlcnZhbClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmlnaHQuaW5zZXJ0KGludGVydmFsKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJpZ2h0ID0gY3JlYXRlSW50ZXJ2YWxUcmVlKFtpbnRlcnZhbF0pXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBsID0gYm91bmRzLmdlKHRoaXMubGVmdFBvaW50cywgaW50ZXJ2YWwsIGNvbXBhcmVCZWdpbilcbiAgICB2YXIgciA9IGJvdW5kcy5nZSh0aGlzLnJpZ2h0UG9pbnRzLCBpbnRlcnZhbCwgY29tcGFyZUVuZClcbiAgICB0aGlzLmxlZnRQb2ludHMuc3BsaWNlKGwsIDAsIGludGVydmFsKVxuICAgIHRoaXMucmlnaHRQb2ludHMuc3BsaWNlKHIsIDAsIGludGVydmFsKVxuICB9XG59XG5cbnByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uKGludGVydmFsKSB7XG4gIHZhciB3ZWlnaHQgPSB0aGlzLmNvdW50IC0gdGhpcy5sZWZ0UG9pbnRzXG4gIGlmKGludGVydmFsWzFdIDwgdGhpcy5taWQpIHtcbiAgICBpZighdGhpcy5sZWZ0KSB7XG4gICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgfVxuICAgIHZhciBydyA9IHRoaXMucmlnaHQgPyB0aGlzLnJpZ2h0LmNvdW50IDogMFxuICAgIGlmKDQgKiBydyA+IDMgKiAod2VpZ2h0LTEpKSB7XG4gICAgICByZXR1cm4gcmVidWlsZFdpdGhvdXRJbnRlcnZhbCh0aGlzLCBpbnRlcnZhbClcbiAgICB9XG4gICAgdmFyIHIgPSB0aGlzLmxlZnQucmVtb3ZlKGludGVydmFsKVxuICAgIGlmKHIgPT09IEVNUFRZKSB7XG4gICAgICB0aGlzLmxlZnQgPSBudWxsXG4gICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfSBlbHNlIGlmKHIgPT09IFNVQ0NFU1MpIHtcbiAgICAgIHRoaXMuY291bnQgLT0gMVxuICAgIH1cbiAgICByZXR1cm4gclxuICB9IGVsc2UgaWYoaW50ZXJ2YWxbMF0gPiB0aGlzLm1pZCkge1xuICAgIGlmKCF0aGlzLnJpZ2h0KSB7XG4gICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgfVxuICAgIHZhciBsdyA9IHRoaXMubGVmdCA/IHRoaXMubGVmdC5jb3VudCA6IDBcbiAgICBpZig0ICogbHcgPiAzICogKHdlaWdodC0xKSkge1xuICAgICAgcmV0dXJuIHJlYnVpbGRXaXRob3V0SW50ZXJ2YWwodGhpcywgaW50ZXJ2YWwpXG4gICAgfVxuICAgIHZhciByID0gdGhpcy5yaWdodC5yZW1vdmUoaW50ZXJ2YWwpXG4gICAgaWYociA9PT0gRU1QVFkpIHtcbiAgICAgIHRoaXMucmlnaHQgPSBudWxsXG4gICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfSBlbHNlIGlmKHIgPT09IFNVQ0NFU1MpIHtcbiAgICAgIHRoaXMuY291bnQgLT0gMVxuICAgIH1cbiAgICByZXR1cm4gclxuICB9IGVsc2Uge1xuICAgIGlmKHRoaXMuY291bnQgPT09IDEpIHtcbiAgICAgIGlmKHRoaXMubGVmdFBvaW50c1swXSA9PT0gaW50ZXJ2YWwpIHtcbiAgICAgICAgcmV0dXJuIEVNUFRZXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgICB9XG4gICAgfVxuICAgIGlmKHRoaXMubGVmdFBvaW50cy5sZW5ndGggPT09IDEgJiYgdGhpcy5sZWZ0UG9pbnRzWzBdID09PSBpbnRlcnZhbCkge1xuICAgICAgaWYodGhpcy5sZWZ0ICYmIHRoaXMucmlnaHQpIHtcbiAgICAgICAgdmFyIHAgPSB0aGlzXG4gICAgICAgIHZhciBuID0gdGhpcy5sZWZ0XG4gICAgICAgIHdoaWxlKG4ucmlnaHQpIHtcbiAgICAgICAgICBwID0gblxuICAgICAgICAgIG4gPSBuLnJpZ2h0XG4gICAgICAgIH1cbiAgICAgICAgaWYocCA9PT0gdGhpcykge1xuICAgICAgICAgIG4ucmlnaHQgPSB0aGlzLnJpZ2h0XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGwgPSB0aGlzLmxlZnRcbiAgICAgICAgICB2YXIgciA9IHRoaXMucmlnaHRcbiAgICAgICAgICBwLmNvdW50IC09IG4uY291bnRcbiAgICAgICAgICBwLnJpZ2h0ID0gbi5sZWZ0XG4gICAgICAgICAgbi5sZWZ0ID0gbFxuICAgICAgICAgIG4ucmlnaHQgPSByXG4gICAgICAgIH1cbiAgICAgICAgY29weSh0aGlzLCBuKVxuICAgICAgICB0aGlzLmNvdW50ID0gKHRoaXMubGVmdD90aGlzLmxlZnQuY291bnQ6MCkgKyAodGhpcy5yaWdodD90aGlzLnJpZ2h0LmNvdW50OjApICsgdGhpcy5sZWZ0UG9pbnRzLmxlbmd0aFxuICAgICAgfSBlbHNlIGlmKHRoaXMubGVmdCkge1xuICAgICAgICBjb3B5KHRoaXMsIHRoaXMubGVmdClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvcHkodGhpcywgdGhpcy5yaWdodClcbiAgICAgIH1cbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfVxuICAgIGZvcih2YXIgbCA9IGJvdW5kcy5nZSh0aGlzLmxlZnRQb2ludHMsIGludGVydmFsLCBjb21wYXJlQmVnaW4pOyBsPHRoaXMubGVmdFBvaW50cy5sZW5ndGg7ICsrbCkge1xuICAgICAgaWYodGhpcy5sZWZ0UG9pbnRzW2xdWzBdICE9PSBpbnRlcnZhbFswXSkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgaWYodGhpcy5sZWZ0UG9pbnRzW2xdID09PSBpbnRlcnZhbCkge1xuICAgICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgICAgdGhpcy5sZWZ0UG9pbnRzLnNwbGljZShsLCAxKVxuICAgICAgICBmb3IodmFyIHIgPSBib3VuZHMuZ2UodGhpcy5yaWdodFBvaW50cywgaW50ZXJ2YWwsIGNvbXBhcmVFbmQpOyByPHRoaXMucmlnaHRQb2ludHMubGVuZ3RoOyArK3IpIHtcbiAgICAgICAgICBpZih0aGlzLnJpZ2h0UG9pbnRzW3JdWzFdICE9PSBpbnRlcnZhbFsxXSkge1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9IGVsc2UgaWYodGhpcy5yaWdodFBvaW50c1tyXSA9PT0gaW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIHRoaXMucmlnaHRQb2ludHMuc3BsaWNlKHIsIDEpXG4gICAgICAgICAgICByZXR1cm4gU1VDQ0VTU1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gTk9UX0ZPVU5EXG4gIH1cbn1cblxuZnVuY3Rpb24gcmVwb3J0TGVmdFJhbmdlKGFyciwgaGksIGNiKSB7XG4gIGZvcih2YXIgaT0wOyBpPGFyci5sZW5ndGggJiYgYXJyW2ldWzBdIDw9IGhpOyArK2kpIHtcbiAgICB2YXIgciA9IGNiKGFycltpXSlcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxufVxuXG5mdW5jdGlvbiByZXBvcnRSaWdodFJhbmdlKGFyciwgbG8sIGNiKSB7XG4gIGZvcih2YXIgaT1hcnIubGVuZ3RoLTE7IGk+PTAgJiYgYXJyW2ldWzFdID49IGxvOyAtLWkpIHtcbiAgICB2YXIgciA9IGNiKGFycltpXSlcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxufVxuXG5mdW5jdGlvbiByZXBvcnRSYW5nZShhcnIsIGNiKSB7XG4gIGZvcih2YXIgaT0wOyBpPGFyci5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gY2IoYXJyW2ldKVxuICAgIGlmKHIpIHsgcmV0dXJuIHIgfVxuICB9XG59XG5cbnByb3RvLnF1ZXJ5UG9pbnQgPSBmdW5jdGlvbih4LCBjYikge1xuICBpZih4IDwgdGhpcy5taWQpIHtcbiAgICBpZih0aGlzLmxlZnQpIHtcbiAgICAgIHZhciByID0gdGhpcy5sZWZ0LnF1ZXJ5UG9pbnQoeCwgY2IpXG4gICAgICBpZihyKSB7IHJldHVybiByIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcG9ydExlZnRSYW5nZSh0aGlzLmxlZnRQb2ludHMsIHgsIGNiKVxuICB9IGVsc2UgaWYoeCA+IHRoaXMubWlkKSB7XG4gICAgaWYodGhpcy5yaWdodCkge1xuICAgICAgdmFyIHIgPSB0aGlzLnJpZ2h0LnF1ZXJ5UG9pbnQoeCwgY2IpXG4gICAgICBpZihyKSB7IHJldHVybiByIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcG9ydFJpZ2h0UmFuZ2UodGhpcy5yaWdodFBvaW50cywgeCwgY2IpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcG9ydFJhbmdlKHRoaXMubGVmdFBvaW50cywgY2IpXG4gIH1cbn1cblxucHJvdG8ucXVlcnlJbnRlcnZhbCA9IGZ1bmN0aW9uKGxvLCBoaSwgY2IpIHtcbiAgaWYobG8gPCB0aGlzLm1pZCAmJiB0aGlzLmxlZnQpIHtcbiAgICB2YXIgciA9IHRoaXMubGVmdC5xdWVyeUludGVydmFsKGxvLCBoaSwgY2IpXG4gICAgaWYocikgeyByZXR1cm4gciB9XG4gIH1cbiAgaWYoaGkgPiB0aGlzLm1pZCAmJiB0aGlzLnJpZ2h0KSB7XG4gICAgdmFyIHIgPSB0aGlzLnJpZ2h0LnF1ZXJ5SW50ZXJ2YWwobG8sIGhpLCBjYilcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxuICBpZihoaSA8IHRoaXMubWlkKSB7XG4gICAgcmV0dXJuIHJlcG9ydExlZnRSYW5nZSh0aGlzLmxlZnRQb2ludHMsIGhpLCBjYilcbiAgfSBlbHNlIGlmKGxvID4gdGhpcy5taWQpIHtcbiAgICByZXR1cm4gcmVwb3J0UmlnaHRSYW5nZSh0aGlzLnJpZ2h0UG9pbnRzLCBsbywgY2IpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcG9ydFJhbmdlKHRoaXMubGVmdFBvaW50cywgY2IpXG4gIH1cbn1cblxuZnVuY3Rpb24gY29tcGFyZU51bWJlcnMoYSwgYikge1xuICByZXR1cm4gYSAtIGJcbn1cblxuZnVuY3Rpb24gY29tcGFyZUJlZ2luKGEsIGIpIHtcbiAgdmFyIGQgPSBhWzBdIC0gYlswXVxuICBpZihkKSB7IHJldHVybiBkIH1cbiAgcmV0dXJuIGFbMV0gLSBiWzFdXG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVFbmQoYSwgYikge1xuICB2YXIgZCA9IGFbMV0gLSBiWzFdXG4gIGlmKGQpIHsgcmV0dXJuIGQgfVxuICByZXR1cm4gYVswXSAtIGJbMF1cbn1cblxuZnVuY3Rpb24gY3JlYXRlSW50ZXJ2YWxUcmVlKGludGVydmFscykge1xuICBpZihpbnRlcnZhbHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICB2YXIgcHRzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8aW50ZXJ2YWxzLmxlbmd0aDsgKytpKSB7XG4gICAgcHRzLnB1c2goaW50ZXJ2YWxzW2ldWzBdLCBpbnRlcnZhbHNbaV1bMV0pXG4gIH1cbiAgcHRzLnNvcnQoY29tcGFyZU51bWJlcnMpXG5cbiAgdmFyIG1pZCA9IHB0c1twdHMubGVuZ3RoPj4xXVxuXG4gIHZhciBsZWZ0SW50ZXJ2YWxzID0gW11cbiAgdmFyIHJpZ2h0SW50ZXJ2YWxzID0gW11cbiAgdmFyIGNlbnRlckludGVydmFscyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGludGVydmFscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBzID0gaW50ZXJ2YWxzW2ldXG4gICAgaWYoc1sxXSA8IG1pZCkge1xuICAgICAgbGVmdEludGVydmFscy5wdXNoKHMpXG4gICAgfSBlbHNlIGlmKG1pZCA8IHNbMF0pIHtcbiAgICAgIHJpZ2h0SW50ZXJ2YWxzLnB1c2gocylcbiAgICB9IGVsc2Uge1xuICAgICAgY2VudGVySW50ZXJ2YWxzLnB1c2gocylcbiAgICB9XG4gIH1cblxuICAvL1NwbGl0IGNlbnRlciBpbnRlcnZhbHNcbiAgdmFyIGxlZnRQb2ludHMgPSBjZW50ZXJJbnRlcnZhbHNcbiAgdmFyIHJpZ2h0UG9pbnRzID0gY2VudGVySW50ZXJ2YWxzLnNsaWNlKClcbiAgbGVmdFBvaW50cy5zb3J0KGNvbXBhcmVCZWdpbilcbiAgcmlnaHRQb2ludHMuc29ydChjb21wYXJlRW5kKVxuXG4gIHJldHVybiBuZXcgSW50ZXJ2YWxUcmVlTm9kZShtaWQsIFxuICAgIGNyZWF0ZUludGVydmFsVHJlZShsZWZ0SW50ZXJ2YWxzKSxcbiAgICBjcmVhdGVJbnRlcnZhbFRyZWUocmlnaHRJbnRlcnZhbHMpLFxuICAgIGxlZnRQb2ludHMsXG4gICAgcmlnaHRQb2ludHMpXG59XG5cbi8vVXNlciBmcmllbmRseSB3cmFwcGVyIHRoYXQgbWFrZXMgaXQgcG9zc2libGUgdG8gc3VwcG9ydCBlbXB0eSB0cmVlc1xuZnVuY3Rpb24gSW50ZXJ2YWxUcmVlKHJvb3QpIHtcbiAgdGhpcy5yb290ID0gcm9vdFxufVxuXG52YXIgdHByb3RvID0gSW50ZXJ2YWxUcmVlLnByb3RvdHlwZVxuXG50cHJvdG8uaW5zZXJ0ID0gZnVuY3Rpb24oaW50ZXJ2YWwpIHtcbiAgaWYodGhpcy5yb290KSB7XG4gICAgdGhpcy5yb290Lmluc2VydChpbnRlcnZhbClcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnJvb3QgPSBuZXcgSW50ZXJ2YWxUcmVlTm9kZShpbnRlcnZhbFswXSwgbnVsbCwgbnVsbCwgW2ludGVydmFsXSwgW2ludGVydmFsXSlcbiAgfVxufVxuXG50cHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24oaW50ZXJ2YWwpIHtcbiAgaWYodGhpcy5yb290KSB7XG4gICAgdmFyIHIgPSB0aGlzLnJvb3QucmVtb3ZlKGludGVydmFsKVxuICAgIGlmKHIgPT09IEVNUFRZKSB7XG4gICAgICB0aGlzLnJvb3QgPSBudWxsXG4gICAgfVxuICAgIHJldHVybiByICE9PSBOT1RfRk9VTkRcbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxudHByb3RvLnF1ZXJ5UG9pbnQgPSBmdW5jdGlvbihwLCBjYikge1xuICBpZih0aGlzLnJvb3QpIHtcbiAgICByZXR1cm4gdGhpcy5yb290LnF1ZXJ5UG9pbnQocCwgY2IpXG4gIH1cbn1cblxudHByb3RvLnF1ZXJ5SW50ZXJ2YWwgPSBmdW5jdGlvbihsbywgaGksIGNiKSB7XG4gIGlmKGxvIDw9IGhpICYmIHRoaXMucm9vdCkge1xuICAgIHJldHVybiB0aGlzLnJvb3QucXVlcnlJbnRlcnZhbChsbywgaGksIGNiKVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0cHJvdG8sIFwiY291bnRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMucm9vdCkge1xuICAgICAgcmV0dXJuIHRoaXMucm9vdC5jb3VudFxuICAgIH1cbiAgICByZXR1cm4gMFxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodHByb3RvLCBcImludGVydmFsc1wiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5yb290KSB7XG4gICAgICByZXR1cm4gdGhpcy5yb290LmludGVydmFscyhbXSlcbiAgICB9XG4gICAgcmV0dXJuIFtdXG4gIH1cbn0pXG5cbmZ1bmN0aW9uIGNyZWF0ZVdyYXBwZXIoaW50ZXJ2YWxzKSB7XG4gIGlmKCFpbnRlcnZhbHMgfHwgaW50ZXJ2YWxzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgSW50ZXJ2YWxUcmVlKG51bGwpXG4gIH1cbiAgcmV0dXJuIG5ldyBJbnRlcnZhbFRyZWUoY3JlYXRlSW50ZXJ2YWxUcmVlKGludGVydmFscykpXG59XG4iLCJcInVzZSBzdHJpY3RcIlxuXG5mdW5jdGlvbiBpbnZlcnRQZXJtdXRhdGlvbihwaSwgcmVzdWx0KSB7XG4gIHJlc3VsdCA9IHJlc3VsdCB8fCBuZXcgQXJyYXkocGkubGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxwaS5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtwaVtpXV0gPSBpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGludmVydFBlcm11dGF0aW9uIiwiXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gaW90YShuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gaVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpb3RhIiwibW9kdWxlLmV4cG9ydHMgPSB0cnVlOyIsIi8qIVxuICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlclxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxuLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZ1xuLy8gT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpXG59XG5cbmZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHtcbiAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iailcbn1cblxuLy8gRm9yIE5vZGUgdjAuMTAgc3VwcG9ydC4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseS5cbmZ1bmN0aW9uIGlzU2xvd0J1ZmZlciAob2JqKSB7XG4gIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJlxuXHQoL01TSUUvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgfHwgL1RyaWRlbnRcXC8vLnRlc3QobmF2aWdhdG9yLmFwcFZlcnNpb24pKTtcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzTW9iaWxlO1xubW9kdWxlLmV4cG9ydHMuaXNNb2JpbGUgPSBpc01vYmlsZTtcblxudmFyIG1vYmlsZVJFID0gLyhhbmRyb2lkfGJiXFxkK3xtZWVnbykuK21vYmlsZXxhdmFudGdvfGJhZGFcXC98YmxhY2tiZXJyeXxibGF6ZXJ8Y29tcGFsfGVsYWluZXxmZW5uZWN8aGlwdG9wfGllbW9iaWxlfGlwKGhvbmV8b2QpfGlyaXN8a2luZGxlfGxnZSB8bWFlbW98bWlkcHxtbXB8bW9iaWxlLitmaXJlZm94fG5ldGZyb250fG9wZXJhIG0ob2J8aW4paXxwYWxtKCBvcyk/fHBob25lfHAoaXhpfHJlKVxcL3xwbHVja2VyfHBvY2tldHxwc3B8c2VyaWVzKDR8NikwfHN5bWJpYW58dHJlb3x1cFxcLihicm93c2VyfGxpbmspfHZvZGFmb25lfHdhcHx3aW5kb3dzIChjZXxwaG9uZSl8eGRhfHhpaW5vL2k7XG5cbnZhciB0YWJsZXRSRSA9IC8oYW5kcm9pZHxiYlxcZCt8bWVlZ28pLittb2JpbGV8YXZhbnRnb3xiYWRhXFwvfGJsYWNrYmVycnl8YmxhemVyfGNvbXBhbHxlbGFpbmV8ZmVubmVjfGhpcHRvcHxpZW1vYmlsZXxpcChob25lfG9kKXxpcmlzfGtpbmRsZXxsZ2UgfG1hZW1vfG1pZHB8bW1wfG1vYmlsZS4rZmlyZWZveHxuZXRmcm9udHxvcGVyYSBtKG9ifGluKWl8cGFsbSggb3MpP3xwaG9uZXxwKGl4aXxyZSlcXC98cGx1Y2tlcnxwb2NrZXR8cHNwfHNlcmllcyg0fDYpMHxzeW1iaWFufHRyZW98dXBcXC4oYnJvd3NlcnxsaW5rKXx2b2RhZm9uZXx3YXB8d2luZG93cyAoY2V8cGhvbmUpfHhkYXx4aWlub3xhbmRyb2lkfGlwYWR8cGxheWJvb2t8c2lsay9pO1xuXG5mdW5jdGlvbiBpc01vYmlsZSAob3B0cykge1xuICBpZiAoIW9wdHMpIG9wdHMgPSB7fVxuICB2YXIgdWEgPSBvcHRzLnVhXG4gIGlmICghdWEgJiYgdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcpIHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgaWYgKHVhICYmIHVhLmhlYWRlcnMgJiYgdHlwZW9mIHVhLmhlYWRlcnNbJ3VzZXItYWdlbnQnXSA9PT0gJ3N0cmluZycpIHtcbiAgICB1YSA9IHVhLmhlYWRlcnNbJ3VzZXItYWdlbnQnXTtcbiAgfVxuICBpZiAodHlwZW9mIHVhICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlO1xuXG4gIHJldHVybiBvcHRzLnRhYmxldFxuICAgID8gdGFibGV0UkUudGVzdCh1YSlcbiAgICA6IG1vYmlsZVJFLnRlc3QodWEpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoeCkge1xuXHR2YXIgdHlwZSA9IHR5cGVvZiB4O1xuXHRyZXR1cm4geCAhPT0gbnVsbCAmJiAodHlwZSA9PT0gJ29iamVjdCcgfHwgdHlwZSA9PT0gJ2Z1bmN0aW9uJyk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoeCkge1xuXHR2YXIgcHJvdG90eXBlO1xuXHRyZXR1cm4gdG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgT2JqZWN0XScgJiYgKHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih4KSwgcHJvdG90eXBlID09PSBudWxsIHx8IHByb3RvdHlwZSA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHt9KSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxuLyoqXHJcbiAqIElzIHRoaXMgc3RyaW5nIGFsbCB3aGl0ZXNwYWNlP1xyXG4gKiBUaGlzIHNvbHV0aW9uIGtpbmQgb2YgbWFrZXMgbXkgYnJhaW4gaHVydCwgYnV0IGl0J3Mgc2lnbmlmaWNhbnRseSBmYXN0ZXJcclxuICogdGhhbiAhc3RyLnRyaW0oKSBvciBhbnkgb3RoZXIgc29sdXRpb24gSSBjb3VsZCBmaW5kLlxyXG4gKlxyXG4gKiB3aGl0ZXNwYWNlIGNvZGVzIGZyb206IGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2hpdGVzcGFjZV9jaGFyYWN0ZXJcclxuICogYW5kIHZlcmlmaWVkIHdpdGg6XHJcbiAqXHJcbiAqICBmb3IodmFyIGkgPSAwOyBpIDwgNjU1MzY7IGkrKykge1xyXG4gKiAgICAgIHZhciBzID0gU3RyaW5nLmZyb21DaGFyQ29kZShpKTtcclxuICogICAgICBpZigrcz09PTAgJiYgIXMudHJpbSgpKSBjb25zb2xlLmxvZyhpLCBzKTtcclxuICogIH1cclxuICpcclxuICogd2hpY2ggY291bnRzIGEgY291cGxlIG9mIHRoZXNlIGFzICpub3QqIHdoaXRlc3BhY2UsIGJ1dCBmaW5kcyBub3RoaW5nIGVsc2VcclxuICogdGhhdCAqaXMqIHdoaXRlc3BhY2UuIE5vdGUgdGhhdCBjaGFyQ29kZUF0IHN0b3BzIGF0IDE2IGJpdHMsIGJ1dCBpdCBhcHBlYXJzXHJcbiAqIHRoYXQgdGhlcmUgYXJlIG5vIHdoaXRlc3BhY2UgY2hhcmFjdGVycyBhYm92ZSB0aGlzLCBhbmQgY29kZSBwb2ludHMgYWJvdmVcclxuICogdGhpcyBkbyBub3QgbWFwIG9udG8gd2hpdGUgc3BhY2UgY2hhcmFjdGVycy5cclxuICovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cil7XHJcbiAgICB2YXIgbCA9IHN0ci5sZW5ndGgsXHJcbiAgICAgICAgYTtcclxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBhID0gc3RyLmNoYXJDb2RlQXQoaSk7XHJcbiAgICAgICAgaWYoKGEgPCA5IHx8IGEgPiAxMykgJiYgKGEgIT09IDMyKSAmJiAoYSAhPT0gMTMzKSAmJiAoYSAhPT0gMTYwKSAmJlxyXG4gICAgICAgICAgICAoYSAhPT0gNTc2MCkgJiYgKGEgIT09IDYxNTgpICYmIChhIDwgODE5MiB8fCBhID4gODIwNSkgJiZcclxuICAgICAgICAgICAgKGEgIT09IDgyMzIpICYmIChhICE9PSA4MjMzKSAmJiAoYSAhPT0gODIzOSkgJiYgKGEgIT09IDgyODcpICYmXHJcbiAgICAgICAgICAgIChhICE9PSA4Mjg4KSAmJiAoYSAhPT0gMTIyODgpICYmIChhICE9PSA2NTI3OSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNQYXRoKHN0cikge1xyXG5cdGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlXHJcblxyXG5cdHN0ciA9IHN0ci50cmltKClcclxuXHJcblx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL1NWRy9wYXRocy5odG1sI1BhdGhEYXRhQk5GXHJcblx0aWYgKC9eW216bGh2Y3NxdGFdXFxzKlstKy4wLTldW15tbGh2emNzcXRhXSsvaS50ZXN0KHN0cikgJiYgL1tcXGR6XSQvaS50ZXN0KHN0cikgJiYgc3RyLmxlbmd0aCA+IDQpIHJldHVybiB0cnVlXHJcblxyXG5cdHJldHVybiBmYWxzZVxyXG59XHJcbiIsImZ1bmN0aW9uIGxlcnAodjAsIHYxLCB0KSB7XG4gICAgcmV0dXJuIHYwKigxLXQpK3YxKnRcbn1cbm1vZHVsZS5leHBvcnRzID0gbGVycCIsIihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcblx0KGdsb2JhbC5tYXBib3hnbCA9IGZhY3RvcnkoKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuLyogZXNsaW50LWRpc2FibGUgKi9cblxudmFyIHNoYXJlZCwgd29ya2VyLCBtYXBib3hnbDtcbi8vIGRlZmluZSBnZXRzIGNhbGxlZCB0aHJlZSB0aW1lczogb25lIGZvciBlYWNoIGNodW5rLiB3ZSByZWx5IG9uIHRoZSBvcmRlclxuLy8gdGhleSdyZSBpbXBvcnRlZCB0byBrbm93IHdoaWNoIGlzIHdoaWNoXG5mdW5jdGlvbiBkZWZpbmUoXywgY2h1bmspIHtcbmlmICghc2hhcmVkKSB7XG4gICAgc2hhcmVkID0gY2h1bms7XG59IGVsc2UgaWYgKCF3b3JrZXIpIHtcbiAgICB3b3JrZXIgPSBjaHVuaztcbn0gZWxzZSB7XG4gICAgdmFyIHdvcmtlckJ1bmRsZVN0cmluZyA9ICd2YXIgc2hhcmVkQ2h1bmsgPSB7fTsgKCcgKyBzaGFyZWQgKyAnKShzaGFyZWRDaHVuayk7ICgnICsgd29ya2VyICsgJykoc2hhcmVkQ2h1bmspOydcblxuICAgIHZhciBzaGFyZWRDaHVuayA9IHt9O1xuICAgIHNoYXJlZChzaGFyZWRDaHVuayk7XG4gICAgbWFwYm94Z2wgPSBjaHVuayhzaGFyZWRDaHVuayk7XG4gICAgbWFwYm94Z2wud29ya2VyVXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoW3dvcmtlckJ1bmRsZVN0cmluZ10sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSkpO1xufVxufVxuXG5cbmRlZmluZShbXCJleHBvcnRzXCJdLGZ1bmN0aW9uKHQpe1widXNlIHN0cmljdFwiO3ZhciBlPVwidW5kZWZpbmVkXCIhPXR5cGVvZiB3aW5kb3c/d2luZG93OlwidW5kZWZpbmVkXCIhPXR5cGVvZiBnbG9iYWw/Z2xvYmFsOlwidW5kZWZpbmVkXCIhPXR5cGVvZiBzZWxmP3NlbGY6e307ZnVuY3Rpb24gcih0KXtyZXR1cm4gdCYmdC5fX2VzTW9kdWxlJiZPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxcImRlZmF1bHRcIik/dC5kZWZhdWx0OnR9ZnVuY3Rpb24gbih0LGUpe3JldHVybiB0KGU9e2V4cG9ydHM6e319LGUuZXhwb3J0cyksZS5leHBvcnRzfXZhciBpPW87ZnVuY3Rpb24gbyh0LGUscixuKXt0aGlzLmN4PTMqdCx0aGlzLmJ4PTMqKHItdCktdGhpcy5jeCx0aGlzLmF4PTEtdGhpcy5jeC10aGlzLmJ4LHRoaXMuY3k9MyplLHRoaXMuYnk9Myoobi1lKS10aGlzLmN5LHRoaXMuYXk9MS10aGlzLmN5LXRoaXMuYnksdGhpcy5wMXg9dCx0aGlzLnAxeT1uLHRoaXMucDJ4PXIsdGhpcy5wMnk9bjt9by5wcm90b3R5cGUuc2FtcGxlQ3VydmVYPWZ1bmN0aW9uKHQpe3JldHVybigodGhpcy5heCp0K3RoaXMuYngpKnQrdGhpcy5jeCkqdH0sby5wcm90b3R5cGUuc2FtcGxlQ3VydmVZPWZ1bmN0aW9uKHQpe3JldHVybigodGhpcy5heSp0K3RoaXMuYnkpKnQrdGhpcy5jeSkqdH0sby5wcm90b3R5cGUuc2FtcGxlQ3VydmVEZXJpdmF0aXZlWD1mdW5jdGlvbih0KXtyZXR1cm4oMyp0aGlzLmF4KnQrMip0aGlzLmJ4KSp0K3RoaXMuY3h9LG8ucHJvdG90eXBlLnNvbHZlQ3VydmVYPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixpLG8sYTtmb3Iodm9pZCAwPT09ZSYmKGU9MWUtNiksaT10LGE9MDthPDg7YSsrKXtpZihvPXRoaXMuc2FtcGxlQ3VydmVYKGkpLXQsTWF0aC5hYnMobyk8ZSlyZXR1cm4gaTt2YXIgcz10aGlzLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVgoaSk7aWYoTWF0aC5hYnMocyk8MWUtNilicmVhaztpLT1vL3M7fWlmKChpPXQpPChyPTApKXJldHVybiByO2lmKGk+KG49MSkpcmV0dXJuIG47Zm9yKDtyPG47KXtpZihvPXRoaXMuc2FtcGxlQ3VydmVYKGkpLE1hdGguYWJzKG8tdCk8ZSlyZXR1cm4gaTt0Pm8/cj1pOm49aSxpPS41KihuLXIpK3I7fXJldHVybiBpfSxvLnByb3RvdHlwZS5zb2x2ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHQsZSkpfTt2YXIgYT1mdW5jdGlvbih0LGUscil7dGhpcy5jb2x1bW49dCx0aGlzLnJvdz1lLHRoaXMuem9vbT1yO307YS5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGEodGhpcy5jb2x1bW4sdGhpcy5yb3csdGhpcy56b29tKX0sYS5wcm90b3R5cGUuem9vbVRvPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX3pvb21Ubyh0KX0sYS5wcm90b3R5cGUuc3ViPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX3N1Yih0KX0sYS5wcm90b3R5cGUuX3pvb21Ubz1mdW5jdGlvbih0KXt2YXIgZT1NYXRoLnBvdygyLHQtdGhpcy56b29tKTtyZXR1cm4gdGhpcy5jb2x1bW4qPWUsdGhpcy5yb3cqPWUsdGhpcy56b29tPXQsdGhpc30sYS5wcm90b3R5cGUuX3N1Yj1mdW5jdGlvbih0KXtyZXR1cm4gdD10Lnpvb21Ubyh0aGlzLnpvb20pLHRoaXMuY29sdW1uLT10LmNvbHVtbix0aGlzLnJvdy09dC5yb3csdGhpc307dmFyIHM9dTtmdW5jdGlvbiB1KHQsZSl7dGhpcy54PXQsdGhpcy55PWU7fWZ1bmN0aW9uIGwodCxlLHIsbil7dmFyIG89bmV3IGkodCxlLHIsbik7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiBvLnNvbHZlKHQpfX11LnByb3RvdHlwZT17Y2xvbmU6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHUodGhpcy54LHRoaXMueSl9LGFkZDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9hZGQodCl9LHN1YjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWIodCl9LG11bHRCeVBvaW50OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX211bHRCeVBvaW50KHQpfSxkaXZCeVBvaW50OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX2RpdkJ5UG9pbnQodCl9LG11bHQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fbXVsdCh0KX0sZGl2OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX2Rpdih0KX0scm90YXRlOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZSh0KX0scm90YXRlQXJvdW5kOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fcm90YXRlQXJvdW5kKHQsZSl9LG1hdE11bHQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fbWF0TXVsdCh0KX0sdW5pdDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmNsb25lKCkuX3VuaXQoKX0scGVycDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKX0scm91bmQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9yb3VuZCgpfSxtYWc6ZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5zcXJ0KHRoaXMueCp0aGlzLngrdGhpcy55KnRoaXMueSl9LGVxdWFsczpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy54PT09dC54JiZ0aGlzLnk9PT10Lnl9LGRpc3Q6ZnVuY3Rpb24odCl7cmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIodCkpfSxkaXN0U3FyOmZ1bmN0aW9uKHQpe3ZhciBlPXQueC10aGlzLngscj10LnktdGhpcy55O3JldHVybiBlKmUrcipyfSxhbmdsZTpmdW5jdGlvbigpe3JldHVybiBNYXRoLmF0YW4yKHRoaXMueSx0aGlzLngpfSxhbmdsZVRvOmZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmF0YW4yKHRoaXMueS10LnksdGhpcy54LXQueCl9LGFuZ2xlV2l0aDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5hbmdsZVdpdGhTZXAodC54LHQueSl9LGFuZ2xlV2l0aFNlcDpmdW5jdGlvbih0LGUpe3JldHVybiBNYXRoLmF0YW4yKHRoaXMueCplLXRoaXMueSp0LHRoaXMueCp0K3RoaXMueSplKX0sX21hdE11bHQ6ZnVuY3Rpb24odCl7dmFyIGU9dFswXSp0aGlzLngrdFsxXSp0aGlzLnkscj10WzJdKnRoaXMueCt0WzNdKnRoaXMueTtyZXR1cm4gdGhpcy54PWUsdGhpcy55PXIsdGhpc30sX2FkZDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy54Kz10LngsdGhpcy55Kz10LnksdGhpc30sX3N1YjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy54LT10LngsdGhpcy55LT10LnksdGhpc30sX211bHQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueCo9dCx0aGlzLnkqPXQsdGhpc30sX2RpdjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy54Lz10LHRoaXMueS89dCx0aGlzfSxfbXVsdEJ5UG9pbnQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueCo9dC54LHRoaXMueSo9dC55LHRoaXN9LF9kaXZCeVBvaW50OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLngvPXQueCx0aGlzLnkvPXQueSx0aGlzfSxfdW5pdDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9kaXYodGhpcy5tYWcoKSksdGhpc30sX3BlcnA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLnk7cmV0dXJuIHRoaXMueT10aGlzLngsdGhpcy54PS10LHRoaXN9LF9yb3RhdGU6ZnVuY3Rpb24odCl7dmFyIGU9TWF0aC5jb3ModCkscj1NYXRoLnNpbih0KSxuPWUqdGhpcy54LXIqdGhpcy55LGk9cip0aGlzLngrZSp0aGlzLnk7cmV0dXJuIHRoaXMueD1uLHRoaXMueT1pLHRoaXN9LF9yb3RhdGVBcm91bmQ6ZnVuY3Rpb24odCxlKXt2YXIgcj1NYXRoLmNvcyh0KSxuPU1hdGguc2luKHQpLGk9ZS54K3IqKHRoaXMueC1lLngpLW4qKHRoaXMueS1lLnkpLG89ZS55K24qKHRoaXMueC1lLngpK3IqKHRoaXMueS1lLnkpO3JldHVybiB0aGlzLng9aSx0aGlzLnk9byx0aGlzfSxfcm91bmQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy54PU1hdGgucm91bmQodGhpcy54KSx0aGlzLnk9TWF0aC5yb3VuZCh0aGlzLnkpLHRoaXN9fSx1LmNvbnZlcnQ9ZnVuY3Rpb24odCl7cmV0dXJuIHQgaW5zdGFuY2VvZiB1P3Q6QXJyYXkuaXNBcnJheSh0KT9uZXcgdSh0WzBdLHRbMV0pOnR9O3ZhciBwPWwoLjI1LC4xLC4yNSwxKTtmdW5jdGlvbiBjKHQsZSxyKXtyZXR1cm4gTWF0aC5taW4ocixNYXRoLm1heChlLHQpKX1mdW5jdGlvbiBoKHQpe2Zvcih2YXIgZT1bXSxyPWFyZ3VtZW50cy5sZW5ndGgtMTtyLS0gPjA7KWVbcl09YXJndW1lbnRzW3IrMV07Zm9yKHZhciBuPTAsaT1lO248aS5sZW5ndGg7bis9MSl7dmFyIG89aVtuXTtmb3IodmFyIGEgaW4gbyl0W2FdPW9bYV07fXJldHVybiB0fXZhciBmPTE7ZnVuY3Rpb24geSh0LGUpe3QuZm9yRWFjaChmdW5jdGlvbih0KXtlW3RdJiYoZVt0XT1lW3RdLmJpbmQoZSkpO30pO31mdW5jdGlvbiBkKHQsZSl7cmV0dXJuLTEhPT10LmluZGV4T2YoZSx0Lmxlbmd0aC1lLmxlbmd0aCl9ZnVuY3Rpb24gdih0LGUscil7dmFyIG49e307Zm9yKHZhciBpIGluIHQpbltpXT1lLmNhbGwocnx8dGhpcyx0W2ldLGksdCk7cmV0dXJuIG59ZnVuY3Rpb24gbSh0LGUscil7dmFyIG49e307Zm9yKHZhciBpIGluIHQpZS5jYWxsKHJ8fHRoaXMsdFtpXSxpLHQpJiYobltpXT10W2ldKTtyZXR1cm4gbn1mdW5jdGlvbiBnKHQpe3JldHVybiBBcnJheS5pc0FycmF5KHQpP3QubWFwKGcpOlwib2JqZWN0XCI9PXR5cGVvZiB0JiZ0P3YodCxnKTp0fXZhciB4PXt9O2Z1bmN0aW9uIGIodCl7eFt0XXx8KFwidW5kZWZpbmVkXCIhPXR5cGVvZiBjb25zb2xlJiZjb25zb2xlLndhcm4odCkseFt0XT0hMCk7fWZ1bmN0aW9uIHcodCxlLHIpe3JldHVybihyLnktdC55KSooZS54LXQueCk+KGUueS10LnkpKihyLngtdC54KX1mdW5jdGlvbiBfKHQpe2Zvcih2YXIgZT0wLHI9MCxuPXQubGVuZ3RoLGk9bi0xLG89dm9pZCAwLGE9dm9pZCAwO3I8bjtpPXIrKylvPXRbcl0sZSs9KChhPXRbaV0pLngtby54KSooby55K2EueSk7cmV0dXJuIGV9dmFyIEE9e1Vua25vd246XCJVbmtub3duXCIsU3R5bGU6XCJTdHlsZVwiLFNvdXJjZTpcIlNvdXJjZVwiLFRpbGU6XCJUaWxlXCIsR2x5cGhzOlwiR2x5cGhzXCIsU3ByaXRlSW1hZ2U6XCJTcHJpdGVJbWFnZVwiLFNwcml0ZUpTT046XCJTcHJpdGVKU09OXCIsSW1hZ2U6XCJJbWFnZVwifTtcImZ1bmN0aW9uXCI9PXR5cGVvZiBPYmplY3QuZnJlZXplJiZPYmplY3QuZnJlZXplKEEpO3ZhciBrPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyLG4pe3QuY2FsbCh0aGlzLGUpLHRoaXMuc3RhdHVzPXIsdGhpcy51cmw9bix0aGlzLm5hbWU9dGhpcy5jb25zdHJ1Y3Rvci5uYW1lLHRoaXMubWVzc2FnZT1lO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5uYW1lK1wiOiBcIit0aGlzLm1lc3NhZ2UrXCIgKFwiK3RoaXMuc3RhdHVzK1wiKTogXCIrdGhpcy51cmx9LGV9KEVycm9yKTtmdW5jdGlvbiB6KHQpe3ZhciBlPW5ldyBzZWxmLlhNTEh0dHBSZXF1ZXN0O2Zvcih2YXIgciBpbiBlLm9wZW4oXCJHRVRcIix0LnVybCwhMCksdC5oZWFkZXJzKWUuc2V0UmVxdWVzdEhlYWRlcihyLHQuaGVhZGVyc1tyXSk7cmV0dXJuIGUud2l0aENyZWRlbnRpYWxzPVwiaW5jbHVkZVwiPT09dC5jcmVkZW50aWFscyxlfXZhciBTPWZ1bmN0aW9uKHQsZSl7dmFyIHI9eih0KTtyZXR1cm4gci5yZXNwb25zZVR5cGU9XCJhcnJheWJ1ZmZlclwiLHIub25lcnJvcj1mdW5jdGlvbigpe2UobmV3IEVycm9yKHIuc3RhdHVzVGV4dCkpO30sci5vbmxvYWQ9ZnVuY3Rpb24oKXt2YXIgbj1yLnJlc3BvbnNlO2lmKDA9PT1uLmJ5dGVMZW5ndGgmJjIwMD09PXIuc3RhdHVzKXJldHVybiBlKG5ldyBFcnJvcihcImh0dHAgc3RhdHVzIDIwMCByZXR1cm5lZCB3aXRob3V0IGNvbnRlbnQuXCIpKTtyLnN0YXR1cz49MjAwJiZyLnN0YXR1czwzMDAmJnIucmVzcG9uc2U/ZShudWxsLHtkYXRhOm4sY2FjaGVDb250cm9sOnIuZ2V0UmVzcG9uc2VIZWFkZXIoXCJDYWNoZS1Db250cm9sXCIpLGV4cGlyZXM6ci5nZXRSZXNwb25zZUhlYWRlcihcIkV4cGlyZXNcIil9KTplKG5ldyBrKHIuc3RhdHVzVGV4dCxyLnN0YXR1cyx0LnVybCkpO30sci5zZW5kKCkscn07ZnVuY3Rpb24gTSh0LGUscil7clt0XT1yW3RdfHxbXSxyW3RdLnB1c2goZSk7fWZ1bmN0aW9uIFYodCxlLHIpe2lmKHImJnJbdF0pe3ZhciBuPXJbdF0uaW5kZXhPZihlKTstMSE9PW4mJnJbdF0uc3BsaWNlKG4sMSk7fX12YXIgQj1mdW5jdGlvbih0LGUpe3ZvaWQgMD09PWUmJihlPXt9KSxoKHRoaXMsZSksdGhpcy50eXBlPXQ7fSxDPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyKXt2b2lkIDA9PT1yJiYocj17fSksdC5jYWxsKHRoaXMsXCJlcnJvclwiLGgoe2Vycm9yOmV9LHIpKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGV9KEIpLEk9ZnVuY3Rpb24oKXt9O0kucHJvdG90eXBlLm9uPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuX2xpc3RlbmVycz10aGlzLl9saXN0ZW5lcnN8fHt9LE0odCxlLHRoaXMuX2xpc3RlbmVycyksdGhpc30sSS5wcm90b3R5cGUub2ZmPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIFYodCxlLHRoaXMuX2xpc3RlbmVycyksVih0LGUsdGhpcy5fb25lVGltZUxpc3RlbmVycyksdGhpc30sSS5wcm90b3R5cGUub25jZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9vbmVUaW1lTGlzdGVuZXJzPXRoaXMuX29uZVRpbWVMaXN0ZW5lcnN8fHt9LE0odCxlLHRoaXMuX29uZVRpbWVMaXN0ZW5lcnMpLHRoaXN9LEkucHJvdG90eXBlLmZpcmU9ZnVuY3Rpb24odCl7XCJzdHJpbmdcIj09dHlwZW9mIHQmJih0PW5ldyBCKHQsYXJndW1lbnRzWzFdfHx7fSkpO3ZhciBlPXQudHlwZTtpZih0aGlzLmxpc3RlbnMoZSkpe3QudGFyZ2V0PXRoaXM7Zm9yKHZhciByPTAsbj10aGlzLl9saXN0ZW5lcnMmJnRoaXMuX2xpc3RlbmVyc1tlXT90aGlzLl9saXN0ZW5lcnNbZV0uc2xpY2UoKTpbXTtyPG4ubGVuZ3RoO3IrPTEpe25bcl0uY2FsbCh0aGlzLHQpO31mb3IodmFyIGk9MCxvPXRoaXMuX29uZVRpbWVMaXN0ZW5lcnMmJnRoaXMuX29uZVRpbWVMaXN0ZW5lcnNbZV0/dGhpcy5fb25lVGltZUxpc3RlbmVyc1tlXS5zbGljZSgpOltdO2k8by5sZW5ndGg7aSs9MSl7dmFyIGE9b1tpXTtWKGUsYSx0aGlzLl9vbmVUaW1lTGlzdGVuZXJzKSxhLmNhbGwodGhpcyx0KTt9dmFyIHM9dGhpcy5fZXZlbnRlZFBhcmVudDtzJiYoaCh0LFwiZnVuY3Rpb25cIj09dHlwZW9mIHRoaXMuX2V2ZW50ZWRQYXJlbnREYXRhP3RoaXMuX2V2ZW50ZWRQYXJlbnREYXRhKCk6dGhpcy5fZXZlbnRlZFBhcmVudERhdGEpLHMuZmlyZSh0KSk7fWVsc2UgZChlLFwiZXJyb3JcIik/Y29uc29sZS5lcnJvcih0JiZ0LmVycm9yfHx0fHxcIkVtcHR5IGVycm9yIGV2ZW50XCIpOmQoZSxcIndhcm5pbmdcIikmJmNvbnNvbGUud2Fybih0JiZ0Lndhcm5pbmd8fHR8fFwiRW1wdHkgd2FybmluZyBldmVudFwiKTtyZXR1cm4gdGhpc30sSS5wcm90b3R5cGUubGlzdGVucz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbGlzdGVuZXJzJiZ0aGlzLl9saXN0ZW5lcnNbdF0mJnRoaXMuX2xpc3RlbmVyc1t0XS5sZW5ndGg+MHx8dGhpcy5fb25lVGltZUxpc3RlbmVycyYmdGhpcy5fb25lVGltZUxpc3RlbmVyc1t0XSYmdGhpcy5fb25lVGltZUxpc3RlbmVyc1t0XS5sZW5ndGg+MHx8dGhpcy5fZXZlbnRlZFBhcmVudCYmdGhpcy5fZXZlbnRlZFBhcmVudC5saXN0ZW5zKHQpfSxJLnByb3RvdHlwZS5zZXRFdmVudGVkUGFyZW50PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuX2V2ZW50ZWRQYXJlbnQ9dCx0aGlzLl9ldmVudGVkUGFyZW50RGF0YT1lLHRoaXN9O3ZhciBFPXskdmVyc2lvbjo4LCRyb290Ont2ZXJzaW9uOntyZXF1aXJlZDohMCx0eXBlOlwiZW51bVwiLHZhbHVlczpbOF19LG5hbWU6e3R5cGU6XCJzdHJpbmdcIn0sbWV0YWRhdGE6e3R5cGU6XCIqXCJ9LGNlbnRlcjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIn0sem9vbTp7dHlwZTpcIm51bWJlclwifSxiZWFyaW5nOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHBlcmlvZDozNjAsdW5pdHM6XCJkZWdyZWVzXCJ9LHBpdGNoOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHVuaXRzOlwiZGVncmVlc1wifSxsaWdodDp7dHlwZTpcImxpZ2h0XCJ9LHNvdXJjZXM6e3JlcXVpcmVkOiEwLHR5cGU6XCJzb3VyY2VzXCJ9LHNwcml0ZTp7dHlwZTpcInN0cmluZ1wifSxnbHlwaHM6e3R5cGU6XCJzdHJpbmdcIn0sdHJhbnNpdGlvbjp7dHlwZTpcInRyYW5zaXRpb25cIn0sbGF5ZXJzOntyZXF1aXJlZDohMCx0eXBlOlwiYXJyYXlcIix2YWx1ZTpcImxheWVyXCJ9fSxzb3VyY2VzOntcIipcIjp7dHlwZTpcInNvdXJjZVwifX0sc291cmNlOltcInNvdXJjZV92ZWN0b3JcIixcInNvdXJjZV9yYXN0ZXJcIixcInNvdXJjZV9yYXN0ZXJfZGVtXCIsXCJzb3VyY2VfZ2VvanNvblwiLFwic291cmNlX3ZpZGVvXCIsXCJzb3VyY2VfaW1hZ2VcIl0sc291cmNlX3ZlY3Rvcjp7dHlwZTp7cmVxdWlyZWQ6ITAsdHlwZTpcImVudW1cIix2YWx1ZXM6e3ZlY3Rvcjp7fX19LHVybDp7dHlwZTpcInN0cmluZ1wifSx0aWxlczp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJzdHJpbmdcIn0sYm91bmRzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDo0LGRlZmF1bHQ6Wy0xODAsLTg1LjA1MTEsMTgwLDg1LjA1MTFdfSxtaW56b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowfSxtYXh6b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoyMn0sYXR0cmlidXRpb246e3R5cGU6XCJzdHJpbmdcIn0sXCIqXCI6e3R5cGU6XCIqXCJ9fSxzb3VyY2VfcmFzdGVyOnt0eXBlOntyZXF1aXJlZDohMCx0eXBlOlwiZW51bVwiLHZhbHVlczp7cmFzdGVyOnt9fX0sdXJsOnt0eXBlOlwic3RyaW5nXCJ9LHRpbGVzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcInN0cmluZ1wifSxib3VuZHM6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjQsZGVmYXVsdDpbLTE4MCwtODUuMDUxMSwxODAsODUuMDUxMV19LG1pbnpvb206e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjB9LG1heHpvb206e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjIyfSx0aWxlU2l6ZTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6NTEyLHVuaXRzOlwicGl4ZWxzXCJ9LHNjaGVtZTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3h5ejp7fSx0bXM6e319LGRlZmF1bHQ6XCJ4eXpcIn0sYXR0cmlidXRpb246e3R5cGU6XCJzdHJpbmdcIn0sXCIqXCI6e3R5cGU6XCIqXCJ9fSxzb3VyY2VfcmFzdGVyX2RlbTp7dHlwZTp7cmVxdWlyZWQ6ITAsdHlwZTpcImVudW1cIix2YWx1ZXM6e1wicmFzdGVyLWRlbVwiOnt9fX0sdXJsOnt0eXBlOlwic3RyaW5nXCJ9LHRpbGVzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcInN0cmluZ1wifSxib3VuZHM6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjQsZGVmYXVsdDpbLTE4MCwtODUuMDUxMSwxODAsODUuMDUxMV19LG1pbnpvb206e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjB9LG1heHpvb206e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjIyfSx0aWxlU2l6ZTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6NTEyLHVuaXRzOlwicGl4ZWxzXCJ9LGF0dHJpYnV0aW9uOnt0eXBlOlwic3RyaW5nXCJ9LGVuY29kaW5nOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7dGVycmFyaXVtOnt9LG1hcGJveDp7fX0sZGVmYXVsdDpcIm1hcGJveFwifSxcIipcIjp7dHlwZTpcIipcIn19LHNvdXJjZV9nZW9qc29uOnt0eXBlOntyZXF1aXJlZDohMCx0eXBlOlwiZW51bVwiLHZhbHVlczp7Z2VvanNvbjp7fX19LGRhdGE6e3R5cGU6XCIqXCJ9LG1heHpvb206e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjE4fSxidWZmZXI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEyOCxtYXhpbXVtOjUxMixtaW5pbXVtOjB9LHRvbGVyYW5jZTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6LjM3NX0sY2x1c3Rlcjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExfSxjbHVzdGVyUmFkaXVzOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDo1MCxtaW5pbXVtOjB9LGNsdXN0ZXJNYXhab29tOnt0eXBlOlwibnVtYmVyXCJ9LGxpbmVNZXRyaWNzOnt0eXBlOlwiYm9vbGVhblwiLGRlZmF1bHQ6ITF9fSxzb3VyY2VfdmlkZW86e3R5cGU6e3JlcXVpcmVkOiEwLHR5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aWRlbzp7fX19LHVybHM6e3JlcXVpcmVkOiEwLHR5cGU6XCJhcnJheVwiLHZhbHVlOlwic3RyaW5nXCJ9LGNvb3JkaW5hdGVzOntyZXF1aXJlZDohMCx0eXBlOlwiYXJyYXlcIixsZW5ndGg6NCx2YWx1ZTp7dHlwZTpcImFycmF5XCIsbGVuZ3RoOjIsdmFsdWU6XCJudW1iZXJcIn19fSxzb3VyY2VfaW1hZ2U6e3R5cGU6e3JlcXVpcmVkOiEwLHR5cGU6XCJlbnVtXCIsdmFsdWVzOntpbWFnZTp7fX19LHVybDp7cmVxdWlyZWQ6ITAsdHlwZTpcInN0cmluZ1wifSxjb29yZGluYXRlczp7cmVxdWlyZWQ6ITAsdHlwZTpcImFycmF5XCIsbGVuZ3RoOjQsdmFsdWU6e3R5cGU6XCJhcnJheVwiLGxlbmd0aDoyLHZhbHVlOlwibnVtYmVyXCJ9fX0sbGF5ZXI6e2lkOnt0eXBlOlwic3RyaW5nXCIscmVxdWlyZWQ6ITB9LHR5cGU6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntmaWxsOnt9LGxpbmU6e30sc3ltYm9sOnt9LGNpcmNsZTp7fSxoZWF0bWFwOnt9LFwiZmlsbC1leHRydXNpb25cIjp7fSxyYXN0ZXI6e30saGlsbHNoYWRlOnt9LGJhY2tncm91bmQ6e319LHJlcXVpcmVkOiEwfSxtZXRhZGF0YTp7dHlwZTpcIipcIn0sc291cmNlOnt0eXBlOlwic3RyaW5nXCJ9LFwic291cmNlLWxheWVyXCI6e3R5cGU6XCJzdHJpbmdcIn0sbWluem9vbTp7dHlwZTpcIm51bWJlclwiLG1pbmltdW06MCxtYXhpbXVtOjI0fSxtYXh6b29tOnt0eXBlOlwibnVtYmVyXCIsbWluaW11bTowLG1heGltdW06MjR9LGZpbHRlcjp7dHlwZTpcImZpbHRlclwifSxsYXlvdXQ6e3R5cGU6XCJsYXlvdXRcIn0scGFpbnQ6e3R5cGU6XCJwYWludFwifX0sbGF5b3V0OltcImxheW91dF9maWxsXCIsXCJsYXlvdXRfbGluZVwiLFwibGF5b3V0X2NpcmNsZVwiLFwibGF5b3V0X2hlYXRtYXBcIixcImxheW91dF9maWxsLWV4dHJ1c2lvblwiLFwibGF5b3V0X3N5bWJvbFwiLFwibGF5b3V0X3Jhc3RlclwiLFwibGF5b3V0X2hpbGxzaGFkZVwiLFwibGF5b3V0X2JhY2tncm91bmRcIl0sbGF5b3V0X2JhY2tncm91bmQ6e3Zpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCJ9fSxsYXlvdXRfZmlsbDp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIn19LGxheW91dF9jaXJjbGU6e3Zpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCJ9fSxsYXlvdXRfaGVhdG1hcDp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIn19LGxheW91dF9saW5lOntcImxpbmUtY2FwXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e2J1dHQ6e30scm91bmQ6e30sc3F1YXJlOnt9fSxkZWZhdWx0OlwiYnV0dFwifSxcImxpbmUtam9pblwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHZhbHVlczp7YmV2ZWw6e30scm91bmQ6e30sbWl0ZXI6e319LGRlZmF1bHQ6XCJtaXRlclwifSxcImxpbmUtbWl0ZXItbGltaXRcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOlt7XCJsaW5lLWpvaW5cIjpcIm1pdGVyXCJ9XX0sXCJsaW5lLXJvdW5kLWxpbWl0XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEuMDUsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxyZXF1aXJlczpbe1wibGluZS1qb2luXCI6XCJyb3VuZFwifV19LHZpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCJ9fSxsYXlvdXRfc3ltYm9sOntcInN5bWJvbC1wbGFjZW1lbnRcIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHZhbHVlczp7cG9pbnQ6e30sbGluZTp7fX0sZGVmYXVsdDpcInBvaW50XCJ9LFwic3ltYm9sLXNwYWNpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MjUwLG1pbmltdW06MSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W3tcInN5bWJvbC1wbGFjZW1lbnRcIjpcImxpbmVcIn1dfSxcInN5bWJvbC1hdm9pZC1lZGdlc1wiOnt0eXBlOlwiYm9vbGVhblwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsZGVmYXVsdDohMX0sXCJpY29uLWFsbG93LW92ZXJsYXBcIjp7dHlwZTpcImJvb2xlYW5cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6ITEscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLWlnbm9yZS1wbGFjZW1lbnRcIjp7dHlwZTpcImJvb2xlYW5cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6ITEscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLW9wdGlvbmFsXCI6e3R5cGU6XCJib29sZWFuXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OiExLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcInRleHQtZmllbGRcIl19LFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9LGF1dG86e319LGRlZmF1bHQ6XCJhdXRvXCIscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLXNpemVcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdW5pdHM6XCJmYWN0b3Igb2YgdGhlIG9yaWdpbmFsIGljb24gc2l6ZVwiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi10ZXh0LWZpdFwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdmFsdWVzOntub25lOnt9LHdpZHRoOnt9LGhlaWdodDp7fSxib3RoOnt9fSxkZWZhdWx0Olwibm9uZVwiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcInRleHQtZmllbGRcIl19LFwiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjQsZGVmYXVsdDpbMCwwLDAsMF0sdW5pdHM6XCJwaXhlbHNcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcInRleHQtZmllbGRcIix7XCJpY29uLXRleHQtZml0XCI6W1wiYm90aFwiLFwid2lkdGhcIixcImhlaWdodFwiXX1dfSxcImljb24taW1hZ2VcIjp7dHlwZTpcInN0cmluZ1wiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRva2VuczohMH0sXCJpY29uLXJvdGF0ZVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHBlcmlvZDozNjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdW5pdHM6XCJkZWdyZWVzXCIscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLXBhZGRpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MixtaW5pbXVtOjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi1rZWVwLXVwcmlnaHRcIjp7dHlwZTpcImJvb2xlYW5cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6ITEscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiLHtcImljb24tcm90YXRpb24tYWxpZ25tZW50XCI6XCJtYXBcIn0se1wic3ltYm9sLXBsYWNlbWVudFwiOlwibGluZVwifV19LFwiaWNvbi1vZmZzZXRcIjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIixsZW5ndGg6MixkZWZhdWx0OlswLDBdLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi1hbmNob3JcIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx2YWx1ZXM6e2NlbnRlcjp7fSxsZWZ0Ont9LHJpZ2h0Ont9LHRvcDp7fSxib3R0b206e30sXCJ0b3AtbGVmdFwiOnt9LFwidG9wLXJpZ2h0XCI6e30sXCJib3R0b20tbGVmdFwiOnt9LFwiYm90dG9tLXJpZ2h0XCI6e319LGRlZmF1bHQ6XCJjZW50ZXJcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdfSxcImljb24tcGl0Y2gtYWxpZ25tZW50XCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fSxhdXRvOnt9fSxkZWZhdWx0OlwiYXV0b1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwidGV4dC1waXRjaC1hbGlnbm1lbnRcIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9LGF1dG86e319LGRlZmF1bHQ6XCJhdXRvXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e30sYXV0bzp7fX0sZGVmYXVsdDpcImF1dG9cIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtZmllbGRcIjp7dHlwZTpcInN0cmluZ1wiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6XCJcIix0b2tlbnM6ITB9LFwidGV4dC1mb250XCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwic3RyaW5nXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsZGVmYXVsdDpbXCJPcGVuIFNhbnMgUmVndWxhclwiLFwiQXJpYWwgVW5pY29kZSBNUyBSZWd1bGFyXCJdLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1zaXplXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjE2LG1pbmltdW06MCx1bml0czpcInBpeGVsc1wiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1tYXgtd2lkdGhcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MTAsbWluaW11bTowLHVuaXRzOlwiZW1zXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEuMix1bml0czpcImVtc1wiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsdW5pdHM6XCJlbXNcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtanVzdGlmeVwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHZhbHVlczp7bGVmdDp7fSxjZW50ZXI6e30scmlnaHQ6e319LGRlZmF1bHQ6XCJjZW50ZXJcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdmFsdWVzOntjZW50ZXI6e30sbGVmdDp7fSxyaWdodDp7fSx0b3A6e30sYm90dG9tOnt9LFwidG9wLWxlZnRcIjp7fSxcInRvcC1yaWdodFwiOnt9LFwiYm90dG9tLWxlZnRcIjp7fSxcImJvdHRvbS1yaWdodFwiOnt9fSxkZWZhdWx0OlwiY2VudGVyXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LW1heC1hbmdsZVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDo0NSx1bml0czpcImRlZ3JlZXNcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOltcInRleHQtZmllbGRcIix7XCJzeW1ib2wtcGxhY2VtZW50XCI6XCJsaW5lXCJ9XX0sXCJ0ZXh0LXJvdGF0ZVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHBlcmlvZDozNjAsdW5pdHM6XCJkZWdyZWVzXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LXBhZGRpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MixtaW5pbXVtOjAsdW5pdHM6XCJwaXhlbHNcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1rZWVwLXVwcmlnaHRcIjp7dHlwZTpcImJvb2xlYW5cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6ITAscmVxdWlyZXM6W1widGV4dC1maWVsZFwiLHtcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCI6XCJtYXBcIn0se1wic3ltYm9sLXBsYWNlbWVudFwiOlwibGluZVwifV19LFwidGV4dC10cmFuc2Zvcm1cIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx2YWx1ZXM6e25vbmU6e30sdXBwZXJjYXNlOnt9LGxvd2VyY2FzZTp7fX0sZGVmYXVsdDpcIm5vbmVcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtb2Zmc2V0XCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsdW5pdHM6XCJlbXNcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCxsZW5ndGg6MixkZWZhdWx0OlswLDBdLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1hbGxvdy1vdmVybGFwXCI6e3R5cGU6XCJib29sZWFuXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OiExLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCI6e3R5cGU6XCJib29sZWFuXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OiExLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1vcHRpb25hbFwiOnt0eXBlOlwiYm9vbGVhblwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsZGVmYXVsdDohMSxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCIsXCJpY29uLWltYWdlXCJdfSx2aXNpYmlsaXR5Ont0eXBlOlwiZW51bVwiLHZhbHVlczp7dmlzaWJsZTp7fSxub25lOnt9fSxkZWZhdWx0OlwidmlzaWJsZVwifX0sbGF5b3V0X3Jhc3Rlcjp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIn19LGxheW91dF9oaWxsc2hhZGU6e3Zpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCJ9fSxmaWx0ZXI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwiKlwifSxmaWx0ZXJfb3BlcmF0b3I6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntcIj09XCI6e30sXCIhPVwiOnt9LFwiPlwiOnt9LFwiPj1cIjp7fSxcIjxcIjp7fSxcIjw9XCI6e30saW46e30sXCIhaW5cIjp7fSxhbGw6e30sYW55Ont9LG5vbmU6e30saGFzOnt9LFwiIWhhc1wiOnt9fX0sZ2VvbWV0cnlfdHlwZTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e1BvaW50Ont9LExpbmVTdHJpbmc6e30sUG9seWdvbjp7fX19LGZ1bmN0aW9uX3N0b3A6e3R5cGU6XCJhcnJheVwiLG1pbmltdW06MCxtYXhpbXVtOjIyLHZhbHVlOltcIm51bWJlclwiLFwiY29sb3JcIl0sbGVuZ3RoOjJ9LGV4cHJlc3Npb246e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwiKlwiLG1pbmltdW06MX0sZXhwcmVzc2lvbl9uYW1lOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bGV0Ontncm91cDpcIlZhcmlhYmxlIGJpbmRpbmdcIn0sdmFyOntncm91cDpcIlZhcmlhYmxlIGJpbmRpbmdcIn0sbGl0ZXJhbDp7Z3JvdXA6XCJUeXBlc1wifSxhcnJheTp7Z3JvdXA6XCJUeXBlc1wifSxhdDp7Z3JvdXA6XCJMb29rdXBcIn0sY2FzZTp7Z3JvdXA6XCJEZWNpc2lvblwifSxtYXRjaDp7Z3JvdXA6XCJEZWNpc2lvblwifSxjb2FsZXNjZTp7Z3JvdXA6XCJEZWNpc2lvblwifSxzdGVwOntncm91cDpcIlJhbXBzLCBzY2FsZXMsIGN1cnZlc1wifSxpbnRlcnBvbGF0ZTp7Z3JvdXA6XCJSYW1wcywgc2NhbGVzLCBjdXJ2ZXNcIn0sbG4yOntncm91cDpcIk1hdGhcIn0scGk6e2dyb3VwOlwiTWF0aFwifSxlOntncm91cDpcIk1hdGhcIn0sdHlwZW9mOntncm91cDpcIlR5cGVzXCJ9LHN0cmluZzp7Z3JvdXA6XCJUeXBlc1wifSxudW1iZXI6e2dyb3VwOlwiVHlwZXNcIn0sYm9vbGVhbjp7Z3JvdXA6XCJUeXBlc1wifSxvYmplY3Q6e2dyb3VwOlwiVHlwZXNcIn0sY29sbGF0b3I6e2dyb3VwOlwiVHlwZXNcIn0sXCJ0by1zdHJpbmdcIjp7Z3JvdXA6XCJUeXBlc1wifSxcInRvLW51bWJlclwiOntncm91cDpcIlR5cGVzXCJ9LFwidG8tYm9vbGVhblwiOntncm91cDpcIlR5cGVzXCJ9LFwidG8tcmdiYVwiOntncm91cDpcIkNvbG9yXCJ9LFwidG8tY29sb3JcIjp7Z3JvdXA6XCJUeXBlc1wifSxyZ2I6e2dyb3VwOlwiQ29sb3JcIn0scmdiYTp7Z3JvdXA6XCJDb2xvclwifSxnZXQ6e2dyb3VwOlwiTG9va3VwXCJ9LGhhczp7Z3JvdXA6XCJMb29rdXBcIn0sbGVuZ3RoOntncm91cDpcIkxvb2t1cFwifSxwcm9wZXJ0aWVzOntncm91cDpcIkZlYXR1cmUgZGF0YVwifSxcImdlb21ldHJ5LXR5cGVcIjp7Z3JvdXA6XCJGZWF0dXJlIGRhdGFcIn0saWQ6e2dyb3VwOlwiRmVhdHVyZSBkYXRhXCJ9LHpvb206e2dyb3VwOlwiWm9vbVwifSxcImhlYXRtYXAtZGVuc2l0eVwiOntncm91cDpcIkhlYXRtYXBcIn0sXCJsaW5lLXByb2dyZXNzXCI6e2dyb3VwOlwiSGVhdG1hcFwifSxcIitcIjp7Z3JvdXA6XCJNYXRoXCJ9LFwiKlwiOntncm91cDpcIk1hdGhcIn0sXCItXCI6e2dyb3VwOlwiTWF0aFwifSxcIi9cIjp7Z3JvdXA6XCJNYXRoXCJ9LFwiJVwiOntncm91cDpcIk1hdGhcIn0sXCJeXCI6e2dyb3VwOlwiTWF0aFwifSxzcXJ0Ontncm91cDpcIk1hdGhcIn0sbG9nMTA6e2dyb3VwOlwiTWF0aFwifSxsbjp7Z3JvdXA6XCJNYXRoXCJ9LGxvZzI6e2dyb3VwOlwiTWF0aFwifSxzaW46e2dyb3VwOlwiTWF0aFwifSxjb3M6e2dyb3VwOlwiTWF0aFwifSx0YW46e2dyb3VwOlwiTWF0aFwifSxhc2luOntncm91cDpcIk1hdGhcIn0sYWNvczp7Z3JvdXA6XCJNYXRoXCJ9LGF0YW46e2dyb3VwOlwiTWF0aFwifSxtaW46e2dyb3VwOlwiTWF0aFwifSxtYXg6e2dyb3VwOlwiTWF0aFwifSxyb3VuZDp7Z3JvdXA6XCJNYXRoXCJ9LGFiczp7Z3JvdXA6XCJNYXRoXCJ9LGNlaWw6e2dyb3VwOlwiTWF0aFwifSxmbG9vcjp7Z3JvdXA6XCJNYXRoXCJ9LFwiPT1cIjp7Z3JvdXA6XCJEZWNpc2lvblwifSxcIiE9XCI6e2dyb3VwOlwiRGVjaXNpb25cIn0sXCI+XCI6e2dyb3VwOlwiRGVjaXNpb25cIn0sXCI8XCI6e2dyb3VwOlwiRGVjaXNpb25cIn0sXCI+PVwiOntncm91cDpcIkRlY2lzaW9uXCJ9LFwiPD1cIjp7Z3JvdXA6XCJEZWNpc2lvblwifSxhbGw6e2dyb3VwOlwiRGVjaXNpb25cIn0sYW55Ontncm91cDpcIkRlY2lzaW9uXCJ9LFwiIVwiOntncm91cDpcIkRlY2lzaW9uXCJ9LFwiaXMtc3VwcG9ydGVkLXNjcmlwdFwiOntncm91cDpcIlN0cmluZ1wifSx1cGNhc2U6e2dyb3VwOlwiU3RyaW5nXCJ9LGRvd25jYXNlOntncm91cDpcIlN0cmluZ1wifSxjb25jYXQ6e2dyb3VwOlwiU3RyaW5nXCJ9LFwicmVzb2x2ZWQtbG9jYWxlXCI6e2dyb3VwOlwiU3RyaW5nXCJ9fX0sbGlnaHQ6e2FuY2hvcjp7dHlwZTpcImVudW1cIixkZWZhdWx0Olwidmlld3BvcnRcIix2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sdHJhbnNpdGlvbjohMSxcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITEsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIn0scG9zaXRpb246e3R5cGU6XCJhcnJheVwiLGRlZmF1bHQ6WzEuMTUsMjEwLDMwXSxsZW5ndGg6Myx2YWx1ZTpcIm51bWJlclwiLHRyYW5zaXRpb246ITAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITF9LGNvbG9yOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiI2ZmZmZmZlwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiExLHRyYW5zaXRpb246ITB9LGludGVuc2l0eTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6LjUsbWluaW11bTowLG1heGltdW06MSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMSx0cmFuc2l0aW9uOiEwfX0scGFpbnQ6W1wicGFpbnRfZmlsbFwiLFwicGFpbnRfbGluZVwiLFwicGFpbnRfY2lyY2xlXCIsXCJwYWludF9oZWF0bWFwXCIsXCJwYWludF9maWxsLWV4dHJ1c2lvblwiLFwicGFpbnRfc3ltYm9sXCIsXCJwYWludF9yYXN0ZXJcIixcInBhaW50X2hpbGxzaGFkZVwiLFwicGFpbnRfYmFja2dyb3VuZFwiXSxwYWludF9maWxsOntcImZpbGwtYW50aWFsaWFzXCI6e3R5cGU6XCJib29sZWFuXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OiEwfSxcImZpbGwtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMH0sXCJmaWxsLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiZmlsbC1wYXR0ZXJuXCJ9XX0sXCJmaWxsLW91dGxpbmUtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiZmlsbC1wYXR0ZXJuXCJ9LHtcImZpbGwtYW50aWFsaWFzXCI6ITB9XX0sXCJmaWxsLXRyYW5zbGF0ZVwiOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDoyLGRlZmF1bHQ6WzAsMF0sZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCJ9LFwiZmlsbC10cmFuc2xhdGUtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcImZpbGwtdHJhbnNsYXRlXCJdfSxcImZpbGwtcGF0dGVyblwiOnt0eXBlOlwic3RyaW5nXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfX0scGFpbnRfbGluZTp7XCJsaW5lLW9wYWNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLHRyYW5zaXRpb246ITB9LFwibGluZS1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiIzAwMDAwMFwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAscmVxdWlyZXM6W3tcIiFcIjpcImxpbmUtcGF0dGVyblwifV19LFwibGluZS10cmFuc2xhdGVcIjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIixsZW5ndGg6MixkZWZhdWx0OlswLDBdLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wifSxcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIixyZXF1aXJlczpbXCJsaW5lLXRyYW5zbGF0ZVwiXX0sXCJsaW5lLXdpZHRoXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIn0sXCJsaW5lLWdhcC13aWR0aFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCJ9LFwibGluZS1vZmZzZXRcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCJ9LFwibGluZS1ibHVyXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsbWluaW11bTowLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIn0sXCJsaW5lLWRhc2hhcnJheVwiOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsbWluaW11bTowLHRyYW5zaXRpb246ITAsdW5pdHM6XCJsaW5lIHdpZHRoc1wiLHJlcXVpcmVzOlt7XCIhXCI6XCJsaW5lLXBhdHRlcm5cIn1dfSxcImxpbmUtcGF0dGVyblwiOnt0eXBlOlwic3RyaW5nXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfSxcImxpbmUtZ3JhZGllbnRcIjp7dHlwZTpcImNvbG9yXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMSxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITEsdHJhbnNpdGlvbjohMSxyZXF1aXJlczpbe1wiIVwiOlwibGluZS1kYXNoYXJyYXlcIn0se1wiIVwiOlwibGluZS1wYXR0ZXJuXCJ9LHtzb3VyY2U6XCJnZW9qc29uXCIsaGFzOntsaW5lTWV0cmljczohMH19XX19LHBhaW50X2NpcmNsZTp7XCJjaXJjbGUtcmFkaXVzXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjUsbWluaW11bTowLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIn0sXCJjaXJjbGUtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfSxcImNpcmNsZS1ibHVyXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJjaXJjbGUtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJjaXJjbGUtdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIn0sXCJjaXJjbGUtdHJhbnNsYXRlLWFuY2hvclwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIixyZXF1aXJlczpbXCJjaXJjbGUtdHJhbnNsYXRlXCJdfSxcImNpcmNsZS1waXRjaC1zY2FsZVwiOnt0eXBlOlwiZW51bVwiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIn0sXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcInZpZXdwb3J0XCJ9LFwiY2lyY2xlLXN0cm9rZS13aWR0aFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCJ9LFwiY2lyY2xlLXN0cm9rZS1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiIzAwMDAwMFwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITB9LFwiY2lyY2xlLXN0cm9rZS1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfX0scGFpbnRfaGVhdG1hcDp7XCJoZWF0bWFwLXJhZGl1c1wiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDozMCxtaW5pbXVtOjEsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wifSxcImhlYXRtYXAtd2VpZ2h0XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITF9LFwiaGVhdG1hcC1pbnRlbnNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITEsdHJhbnNpdGlvbjohMH0sXCJoZWF0bWFwLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6W1wiaW50ZXJwb2xhdGVcIixbXCJsaW5lYXJcIl0sW1wiaGVhdG1hcC1kZW5zaXR5XCJdLDAsXCJyZ2JhKDAsIDAsIDI1NSwgMClcIiwuMSxcInJveWFsYmx1ZVwiLC4zLFwiY3lhblwiLC41LFwibGltZVwiLC43LFwieWVsbG93XCIsMSxcInJlZFwiXSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiExLFwicHJvcGVydHktZnVuY3Rpb25cIjohMSx0cmFuc2l0aW9uOiExfSxcImhlYXRtYXAtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITEsdHJhbnNpdGlvbjohMH19LHBhaW50X3N5bWJvbDp7XCJpY29uLW9wYWNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdfSxcImljb24taGFsby1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwicmdiYSgwLCAwLCAwLCAwKVwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsXCJwcm9wZXJ0eS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXX0sXCJpY29uLWhhbG8td2lkdGhcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi1oYWxvLWJsdXJcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi10cmFuc2xhdGVcIjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIixsZW5ndGg6MixkZWZhdWx0OlswLDBdLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl19LFwiaWNvbi10cmFuc2xhdGUtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcImljb24tdHJhbnNsYXRlXCJdfSxcInRleHQtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl19LFwidGV4dC1oYWxvLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCJyZ2JhKDAsIDAsIDAsIDApXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdfSxcInRleHQtaGFsby13aWR0aFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LWhhbG8tYmx1clwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LXRyYW5zbGF0ZVwiOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDoyLGRlZmF1bHQ6WzAsMF0sZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXX0sXCJ0ZXh0LXRyYW5zbGF0ZS1hbmNob3JcIjp7dHlwZTpcImVudW1cIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9fSxkZWZhdWx0OlwibWFwXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiLFwidGV4dC10cmFuc2xhdGVcIl19fSxwYWludF9yYXN0ZXI6e1wicmFzdGVyLW9wYWNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJyYXN0ZXItaHVlLXJvdGF0ZVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHBlcmlvZDozNjAsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwiZGVncmVlc1wifSxcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOnt0eXBlOlwibnVtYmVyXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OjAsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwfSxcInJhc3Rlci1icmlnaHRuZXNzLW1heFwiOnt0eXBlOlwibnVtYmVyXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwfSxcInJhc3Rlci1zYXR1cmF0aW9uXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsbWluaW11bTotMSxtYXhpbXVtOjEsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfSxcInJhc3Rlci1jb250cmFzdFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06LTEsbWF4aW11bToxLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDozMDAsbWluaW11bTowLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMSx1bml0czpcIm1pbGxpc2Vjb25kc1wifX0scGFpbnRfaGlsbHNoYWRlOntcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tZGlyZWN0aW9uXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjMzNSxtaW5pbXVtOjAsbWF4aW11bTozNTksZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiExfSxcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcInZpZXdwb3J0XCJ9LFwiaGlsbHNoYWRlLWV4YWdnZXJhdGlvblwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDouNSxtaW5pbXVtOjAsbWF4aW11bToxLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJoaWxsc2hhZGUtc2hhZG93LWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCx0cmFuc2l0aW9uOiEwfSxcImhpbGxzaGFkZS1oaWdobGlnaHQtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiNGRkZGRkZcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITB9LFwiaGlsbHNoYWRlLWFjY2VudC1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiIzAwMDAwMFwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH19LHBhaW50X2JhY2tncm91bmQ6e1wiYmFja2dyb3VuZC1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiIzAwMDAwMFwiLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiYmFja2dyb3VuZC1wYXR0ZXJuXCJ9XX0sXCJiYWNrZ3JvdW5kLXBhdHRlcm5cIjp7dHlwZTpcInN0cmluZ1wiLGZ1bmN0aW9uOlwicGllY2V3aXNlLWNvbnN0YW50XCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH0sXCJiYWNrZ3JvdW5kLW9wYWNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLGZ1bmN0aW9uOlwiaW50ZXJwb2xhdGVkXCIsXCJ6b29tLWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMH19LHRyYW5zaXRpb246e2R1cmF0aW9uOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDozMDAsbWluaW11bTowLHVuaXRzOlwibWlsbGlzZWNvbmRzXCJ9LGRlbGF5Ont0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCx1bml0czpcIm1pbGxpc2Vjb25kc1wifX0sXCJsYXlvdXRfZmlsbC1leHRydXNpb25cIjp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIn19LGZ1bmN0aW9uOntleHByZXNzaW9uOnt0eXBlOlwiZXhwcmVzc2lvblwifSxzdG9wczp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJmdW5jdGlvbl9zdG9wXCJ9LGJhc2U6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowfSxwcm9wZXJ0eTp7dHlwZTpcInN0cmluZ1wiLGRlZmF1bHQ6XCIkem9vbVwifSx0eXBlOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7aWRlbnRpdHk6e30sZXhwb25lbnRpYWw6e30saW50ZXJ2YWw6e30sY2F0ZWdvcmljYWw6e319LGRlZmF1bHQ6XCJleHBvbmVudGlhbFwifSxjb2xvclNwYWNlOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7cmdiOnt9LGxhYjp7fSxoY2w6e319LGRlZmF1bHQ6XCJyZ2JcIn0sZGVmYXVsdDp7dHlwZTpcIipcIixyZXF1aXJlZDohMX19LFwicGFpbnRfZmlsbC1leHRydXNpb25cIjp7XCJmaWxsLWV4dHJ1c2lvbi1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMSxkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwfSxcImZpbGwtZXh0cnVzaW9uLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsZnVuY3Rpb246XCJpbnRlcnBvbGF0ZWRcIixcInpvb20tZnVuY3Rpb25cIjohMCxcInByb3BlcnR5LWZ1bmN0aW9uXCI6ITAsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiZmlsbC1leHRydXNpb24tcGF0dGVyblwifV19LFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSxmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIn0sXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGUtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsZnVuY3Rpb246XCJwaWVjZXdpc2UtY29uc3RhbnRcIixcInpvb20tZnVuY3Rpb25cIjohMCx2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiXX0sXCJmaWxsLWV4dHJ1c2lvbi1wYXR0ZXJuXCI6e3R5cGU6XCJzdHJpbmdcIixmdW5jdGlvbjpcInBpZWNld2lzZS1jb25zdGFudFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLHRyYW5zaXRpb246ITB9LFwiZmlsbC1leHRydXNpb24taGVpZ2h0XCI6e3R5cGU6XCJudW1iZXJcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCxkZWZhdWx0OjAsbWluaW11bTowLHVuaXRzOlwibWV0ZXJzXCIsdHJhbnNpdGlvbjohMH0sXCJmaWxsLWV4dHJ1c2lvbi1iYXNlXCI6e3R5cGU6XCJudW1iZXJcIixmdW5jdGlvbjpcImludGVycG9sYXRlZFwiLFwiem9vbS1mdW5jdGlvblwiOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCxkZWZhdWx0OjAsbWluaW11bTowLHVuaXRzOlwibWV0ZXJzXCIsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJmaWxsLWV4dHJ1c2lvbi1oZWlnaHRcIl19fX0sRj1mdW5jdGlvbih0LGUscixuKXt0aGlzLm1lc3NhZ2U9KHQ/dCtcIjogXCI6XCJcIikrcixuJiYodGhpcy5pZGVudGlmaWVyPW4pLG51bGwhPWUmJmUuX19saW5lX18mJih0aGlzLmxpbmU9ZS5fX2xpbmVfXyk7fTtmdW5jdGlvbiBQKHQpe3ZhciBlPXQua2V5LHI9dC52YWx1ZTtyZXR1cm4gcj9bbmV3IEYoZSxyLFwiY29uc3RhbnRzIGhhdmUgYmVlbiBkZXByZWNhdGVkIGFzIG9mIHY4XCIpXTpbXX1mdW5jdGlvbiBUKHQpe2Zvcih2YXIgZT1bXSxyPWFyZ3VtZW50cy5sZW5ndGgtMTtyLS0gPjA7KWVbcl09YXJndW1lbnRzW3IrMV07Zm9yKHZhciBuPTAsaT1lO248aS5sZW5ndGg7bis9MSl7dmFyIG89aVtuXTtmb3IodmFyIGEgaW4gbyl0W2FdPW9bYV07fXJldHVybiB0fWZ1bmN0aW9uIE8odCl7cmV0dXJuIHQgaW5zdGFuY2VvZiBOdW1iZXJ8fHQgaW5zdGFuY2VvZiBTdHJpbmd8fHQgaW5zdGFuY2VvZiBCb29sZWFuP3QudmFsdWVPZigpOnR9ZnVuY3Rpb24gTCh0KXtyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90Lm1hcChMKTpPKHQpfXZhciBqPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyKXt0LmNhbGwodGhpcyxyKSx0aGlzLm1lc3NhZ2U9cix0aGlzLmtleT1lO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZX0oRXJyb3IpLHE9ZnVuY3Rpb24odCxlKXt2b2lkIDA9PT1lJiYoZT1bXSksdGhpcy5wYXJlbnQ9dCx0aGlzLmJpbmRpbmdzPXt9O2Zvcih2YXIgcj0wLG49ZTtyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl0sbz1pWzBdLGE9aVsxXTt0aGlzLmJpbmRpbmdzW29dPWE7fX07cS5wcm90b3R5cGUuY29uY2F0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgcSh0aGlzLHQpfSxxLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5iaW5kaW5nc1t0XSlyZXR1cm4gdGhpcy5iaW5kaW5nc1t0XTtpZih0aGlzLnBhcmVudClyZXR1cm4gdGhpcy5wYXJlbnQuZ2V0KHQpO3Rocm93IG5ldyBFcnJvcih0K1wiIG5vdCBmb3VuZCBpbiBzY29wZS5cIil9LHEucHJvdG90eXBlLmhhcz1mdW5jdGlvbih0KXtyZXR1cm4hIXRoaXMuYmluZGluZ3NbdF18fCEhdGhpcy5wYXJlbnQmJnRoaXMucGFyZW50Lmhhcyh0KX07dmFyIFI9e2tpbmQ6XCJudWxsXCJ9LFU9e2tpbmQ6XCJudW1iZXJcIn0sRD17a2luZDpcInN0cmluZ1wifSxOPXtraW5kOlwiYm9vbGVhblwifSxaPXtraW5kOlwiY29sb3JcIn0sSz17a2luZDpcIm9iamVjdFwifSxKPXtraW5kOlwidmFsdWVcIn0sJD17a2luZDpcImNvbGxhdG9yXCJ9O2Z1bmN0aW9uIEgodCxlKXtyZXR1cm57a2luZDpcImFycmF5XCIsaXRlbVR5cGU6dCxOOmV9fWZ1bmN0aW9uIFgodCl7aWYoXCJhcnJheVwiPT09dC5raW5kKXt2YXIgZT1YKHQuaXRlbVR5cGUpO3JldHVyblwibnVtYmVyXCI9PXR5cGVvZiB0Lk4/XCJhcnJheTxcIitlK1wiLCBcIit0Lk4rXCI+XCI6XCJ2YWx1ZVwiPT09dC5pdGVtVHlwZS5raW5kP1wiYXJyYXlcIjpcImFycmF5PFwiK2UrXCI+XCJ9cmV0dXJuIHQua2luZH12YXIgRz1bUixVLEQsTixaLEssSChKKV07ZnVuY3Rpb24gWSh0LGUpe2lmKFwiZXJyb3JcIj09PWUua2luZClyZXR1cm4gbnVsbDtpZihcImFycmF5XCI9PT10LmtpbmQpe2lmKFwiYXJyYXlcIj09PWUua2luZCYmIVkodC5pdGVtVHlwZSxlLml0ZW1UeXBlKSYmKFwibnVtYmVyXCIhPXR5cGVvZiB0Lk58fHQuTj09PWUuTikpcmV0dXJuIG51bGx9ZWxzZXtpZih0LmtpbmQ9PT1lLmtpbmQpcmV0dXJuIG51bGw7aWYoXCJ2YWx1ZVwiPT09dC5raW5kKWZvcih2YXIgcj0wLG49RztyPG4ubGVuZ3RoO3IrPTEpe2lmKCFZKG5bcl0sZSkpcmV0dXJuIG51bGx9fXJldHVyblwiRXhwZWN0ZWQgXCIrWCh0KStcIiBidXQgZm91bmQgXCIrWChlKStcIiBpbnN0ZWFkLlwifXZhciBXPW4oZnVuY3Rpb24odCxlKXt2YXIgcj17dHJhbnNwYXJlbnQ6WzAsMCwwLDBdLGFsaWNlYmx1ZTpbMjQwLDI0OCwyNTUsMV0sYW50aXF1ZXdoaXRlOlsyNTAsMjM1LDIxNSwxXSxhcXVhOlswLDI1NSwyNTUsMV0sYXF1YW1hcmluZTpbMTI3LDI1NSwyMTIsMV0sYXp1cmU6WzI0MCwyNTUsMjU1LDFdLGJlaWdlOlsyNDUsMjQ1LDIyMCwxXSxiaXNxdWU6WzI1NSwyMjgsMTk2LDFdLGJsYWNrOlswLDAsMCwxXSxibGFuY2hlZGFsbW9uZDpbMjU1LDIzNSwyMDUsMV0sYmx1ZTpbMCwwLDI1NSwxXSxibHVldmlvbGV0OlsxMzgsNDMsMjI2LDFdLGJyb3duOlsxNjUsNDIsNDIsMV0sYnVybHl3b29kOlsyMjIsMTg0LDEzNSwxXSxjYWRldGJsdWU6Wzk1LDE1OCwxNjAsMV0sY2hhcnRyZXVzZTpbMTI3LDI1NSwwLDFdLGNob2NvbGF0ZTpbMjEwLDEwNSwzMCwxXSxjb3JhbDpbMjU1LDEyNyw4MCwxXSxjb3JuZmxvd2VyYmx1ZTpbMTAwLDE0OSwyMzcsMV0sY29ybnNpbGs6WzI1NSwyNDgsMjIwLDFdLGNyaW1zb246WzIyMCwyMCw2MCwxXSxjeWFuOlswLDI1NSwyNTUsMV0sZGFya2JsdWU6WzAsMCwxMzksMV0sZGFya2N5YW46WzAsMTM5LDEzOSwxXSxkYXJrZ29sZGVucm9kOlsxODQsMTM0LDExLDFdLGRhcmtncmF5OlsxNjksMTY5LDE2OSwxXSxkYXJrZ3JlZW46WzAsMTAwLDAsMV0sZGFya2dyZXk6WzE2OSwxNjksMTY5LDFdLGRhcmtraGFraTpbMTg5LDE4MywxMDcsMV0sZGFya21hZ2VudGE6WzEzOSwwLDEzOSwxXSxkYXJrb2xpdmVncmVlbjpbODUsMTA3LDQ3LDFdLGRhcmtvcmFuZ2U6WzI1NSwxNDAsMCwxXSxkYXJrb3JjaGlkOlsxNTMsNTAsMjA0LDFdLGRhcmtyZWQ6WzEzOSwwLDAsMV0sZGFya3NhbG1vbjpbMjMzLDE1MCwxMjIsMV0sZGFya3NlYWdyZWVuOlsxNDMsMTg4LDE0MywxXSxkYXJrc2xhdGVibHVlOls3Miw2MSwxMzksMV0sZGFya3NsYXRlZ3JheTpbNDcsNzksNzksMV0sZGFya3NsYXRlZ3JleTpbNDcsNzksNzksMV0sZGFya3R1cnF1b2lzZTpbMCwyMDYsMjA5LDFdLGRhcmt2aW9sZXQ6WzE0OCwwLDIxMSwxXSxkZWVwcGluazpbMjU1LDIwLDE0NywxXSxkZWVwc2t5Ymx1ZTpbMCwxOTEsMjU1LDFdLGRpbWdyYXk6WzEwNSwxMDUsMTA1LDFdLGRpbWdyZXk6WzEwNSwxMDUsMTA1LDFdLGRvZGdlcmJsdWU6WzMwLDE0NCwyNTUsMV0sZmlyZWJyaWNrOlsxNzgsMzQsMzQsMV0sZmxvcmFsd2hpdGU6WzI1NSwyNTAsMjQwLDFdLGZvcmVzdGdyZWVuOlszNCwxMzksMzQsMV0sZnVjaHNpYTpbMjU1LDAsMjU1LDFdLGdhaW5zYm9ybzpbMjIwLDIyMCwyMjAsMV0sZ2hvc3R3aGl0ZTpbMjQ4LDI0OCwyNTUsMV0sZ29sZDpbMjU1LDIxNSwwLDFdLGdvbGRlbnJvZDpbMjE4LDE2NSwzMiwxXSxncmF5OlsxMjgsMTI4LDEyOCwxXSxncmVlbjpbMCwxMjgsMCwxXSxncmVlbnllbGxvdzpbMTczLDI1NSw0NywxXSxncmV5OlsxMjgsMTI4LDEyOCwxXSxob25leWRldzpbMjQwLDI1NSwyNDAsMV0saG90cGluazpbMjU1LDEwNSwxODAsMV0saW5kaWFucmVkOlsyMDUsOTIsOTIsMV0saW5kaWdvOls3NSwwLDEzMCwxXSxpdm9yeTpbMjU1LDI1NSwyNDAsMV0sa2hha2k6WzI0MCwyMzAsMTQwLDFdLGxhdmVuZGVyOlsyMzAsMjMwLDI1MCwxXSxsYXZlbmRlcmJsdXNoOlsyNTUsMjQwLDI0NSwxXSxsYXduZ3JlZW46WzEyNCwyNTIsMCwxXSxsZW1vbmNoaWZmb246WzI1NSwyNTAsMjA1LDFdLGxpZ2h0Ymx1ZTpbMTczLDIxNiwyMzAsMV0sbGlnaHRjb3JhbDpbMjQwLDEyOCwxMjgsMV0sbGlnaHRjeWFuOlsyMjQsMjU1LDI1NSwxXSxsaWdodGdvbGRlbnJvZHllbGxvdzpbMjUwLDI1MCwyMTAsMV0sbGlnaHRncmF5OlsyMTEsMjExLDIxMSwxXSxsaWdodGdyZWVuOlsxNDQsMjM4LDE0NCwxXSxsaWdodGdyZXk6WzIxMSwyMTEsMjExLDFdLGxpZ2h0cGluazpbMjU1LDE4MiwxOTMsMV0sbGlnaHRzYWxtb246WzI1NSwxNjAsMTIyLDFdLGxpZ2h0c2VhZ3JlZW46WzMyLDE3OCwxNzAsMV0sbGlnaHRza3libHVlOlsxMzUsMjA2LDI1MCwxXSxsaWdodHNsYXRlZ3JheTpbMTE5LDEzNiwxNTMsMV0sbGlnaHRzbGF0ZWdyZXk6WzExOSwxMzYsMTUzLDFdLGxpZ2h0c3RlZWxibHVlOlsxNzYsMTk2LDIyMiwxXSxsaWdodHllbGxvdzpbMjU1LDI1NSwyMjQsMV0sbGltZTpbMCwyNTUsMCwxXSxsaW1lZ3JlZW46WzUwLDIwNSw1MCwxXSxsaW5lbjpbMjUwLDI0MCwyMzAsMV0sbWFnZW50YTpbMjU1LDAsMjU1LDFdLG1hcm9vbjpbMTI4LDAsMCwxXSxtZWRpdW1hcXVhbWFyaW5lOlsxMDIsMjA1LDE3MCwxXSxtZWRpdW1ibHVlOlswLDAsMjA1LDFdLG1lZGl1bW9yY2hpZDpbMTg2LDg1LDIxMSwxXSxtZWRpdW1wdXJwbGU6WzE0NywxMTIsMjE5LDFdLG1lZGl1bXNlYWdyZWVuOls2MCwxNzksMTEzLDFdLG1lZGl1bXNsYXRlYmx1ZTpbMTIzLDEwNCwyMzgsMV0sbWVkaXVtc3ByaW5nZ3JlZW46WzAsMjUwLDE1NCwxXSxtZWRpdW10dXJxdW9pc2U6WzcyLDIwOSwyMDQsMV0sbWVkaXVtdmlvbGV0cmVkOlsxOTksMjEsMTMzLDFdLG1pZG5pZ2h0Ymx1ZTpbMjUsMjUsMTEyLDFdLG1pbnRjcmVhbTpbMjQ1LDI1NSwyNTAsMV0sbWlzdHlyb3NlOlsyNTUsMjI4LDIyNSwxXSxtb2NjYXNpbjpbMjU1LDIyOCwxODEsMV0sbmF2YWpvd2hpdGU6WzI1NSwyMjIsMTczLDFdLG5hdnk6WzAsMCwxMjgsMV0sb2xkbGFjZTpbMjUzLDI0NSwyMzAsMV0sb2xpdmU6WzEyOCwxMjgsMCwxXSxvbGl2ZWRyYWI6WzEwNywxNDIsMzUsMV0sb3JhbmdlOlsyNTUsMTY1LDAsMV0sb3JhbmdlcmVkOlsyNTUsNjksMCwxXSxvcmNoaWQ6WzIxOCwxMTIsMjE0LDFdLHBhbGVnb2xkZW5yb2Q6WzIzOCwyMzIsMTcwLDFdLHBhbGVncmVlbjpbMTUyLDI1MSwxNTIsMV0scGFsZXR1cnF1b2lzZTpbMTc1LDIzOCwyMzgsMV0scGFsZXZpb2xldHJlZDpbMjE5LDExMiwxNDcsMV0scGFwYXlhd2hpcDpbMjU1LDIzOSwyMTMsMV0scGVhY2hwdWZmOlsyNTUsMjE4LDE4NSwxXSxwZXJ1OlsyMDUsMTMzLDYzLDFdLHBpbms6WzI1NSwxOTIsMjAzLDFdLHBsdW06WzIyMSwxNjAsMjIxLDFdLHBvd2RlcmJsdWU6WzE3NiwyMjQsMjMwLDFdLHB1cnBsZTpbMTI4LDAsMTI4LDFdLHJlYmVjY2FwdXJwbGU6WzEwMiw1MSwxNTMsMV0scmVkOlsyNTUsMCwwLDFdLHJvc3licm93bjpbMTg4LDE0MywxNDMsMV0scm95YWxibHVlOls2NSwxMDUsMjI1LDFdLHNhZGRsZWJyb3duOlsxMzksNjksMTksMV0sc2FsbW9uOlsyNTAsMTI4LDExNCwxXSxzYW5keWJyb3duOlsyNDQsMTY0LDk2LDFdLHNlYWdyZWVuOls0NiwxMzksODcsMV0sc2Vhc2hlbGw6WzI1NSwyNDUsMjM4LDFdLHNpZW5uYTpbMTYwLDgyLDQ1LDFdLHNpbHZlcjpbMTkyLDE5MiwxOTIsMV0sc2t5Ymx1ZTpbMTM1LDIwNiwyMzUsMV0sc2xhdGVibHVlOlsxMDYsOTAsMjA1LDFdLHNsYXRlZ3JheTpbMTEyLDEyOCwxNDQsMV0sc2xhdGVncmV5OlsxMTIsMTI4LDE0NCwxXSxzbm93OlsyNTUsMjUwLDI1MCwxXSxzcHJpbmdncmVlbjpbMCwyNTUsMTI3LDFdLHN0ZWVsYmx1ZTpbNzAsMTMwLDE4MCwxXSx0YW46WzIxMCwxODAsMTQwLDFdLHRlYWw6WzAsMTI4LDEyOCwxXSx0aGlzdGxlOlsyMTYsMTkxLDIxNiwxXSx0b21hdG86WzI1NSw5OSw3MSwxXSx0dXJxdW9pc2U6WzY0LDIyNCwyMDgsMV0sdmlvbGV0OlsyMzgsMTMwLDIzOCwxXSx3aGVhdDpbMjQ1LDIyMiwxNzksMV0sd2hpdGU6WzI1NSwyNTUsMjU1LDFdLHdoaXRlc21va2U6WzI0NSwyNDUsMjQ1LDFdLHllbGxvdzpbMjU1LDI1NSwwLDFdLHllbGxvd2dyZWVuOlsxNTQsMjA1LDUwLDFdfTtmdW5jdGlvbiBuKHQpe3JldHVybih0PU1hdGgucm91bmQodCkpPDA/MDp0PjI1NT8yNTU6dH1mdW5jdGlvbiBpKHQpe3JldHVybiB0PDA/MDp0PjE/MTp0fWZ1bmN0aW9uIG8odCl7cmV0dXJuXCIlXCI9PT10W3QubGVuZ3RoLTFdP24ocGFyc2VGbG9hdCh0KS8xMDAqMjU1KTpuKHBhcnNlSW50KHQpKX1mdW5jdGlvbiBhKHQpe3JldHVyblwiJVwiPT09dFt0Lmxlbmd0aC0xXT9pKHBhcnNlRmxvYXQodCkvMTAwKTppKHBhcnNlRmxvYXQodCkpfWZ1bmN0aW9uIHModCxlLHIpe3JldHVybiByPDA/cis9MTpyPjEmJihyLT0xKSw2KnI8MT90KyhlLXQpKnIqNjoyKnI8MT9lOjMqcjwyP3QrKGUtdCkqKDIvMy1yKSo2OnR9dHJ5e2UucGFyc2VDU1NDb2xvcj1mdW5jdGlvbih0KXt2YXIgZSxpPXQucmVwbGFjZSgvIC9nLFwiXCIpLnRvTG93ZXJDYXNlKCk7aWYoaSBpbiByKXJldHVybiByW2ldLnNsaWNlKCk7aWYoXCIjXCI9PT1pWzBdKXJldHVybiA0PT09aS5sZW5ndGg/KGU9cGFyc2VJbnQoaS5zdWJzdHIoMSksMTYpKT49MCYmZTw9NDA5NT9bKDM4NDAmZSk+PjR8KDM4NDAmZSk+PjgsMjQwJmV8KDI0MCZlKT4+NCwxNSZlfCgxNSZlKTw8NCwxXTpudWxsOjc9PT1pLmxlbmd0aCYmKGU9cGFyc2VJbnQoaS5zdWJzdHIoMSksMTYpKT49MCYmZTw9MTY3NzcyMTU/WygxNjcxMTY4MCZlKT4+MTYsKDY1MjgwJmUpPj44LDI1NSZlLDFdOm51bGw7dmFyIHU9aS5pbmRleE9mKFwiKFwiKSxsPWkuaW5kZXhPZihcIilcIik7aWYoLTEhPT11JiZsKzE9PT1pLmxlbmd0aCl7dmFyIHA9aS5zdWJzdHIoMCx1KSxjPWkuc3Vic3RyKHUrMSxsLSh1KzEpKS5zcGxpdChcIixcIiksaD0xO3N3aXRjaChwKXtjYXNlXCJyZ2JhXCI6aWYoNCE9PWMubGVuZ3RoKXJldHVybiBudWxsO2g9YShjLnBvcCgpKTtjYXNlXCJyZ2JcIjpyZXR1cm4gMyE9PWMubGVuZ3RoP251bGw6W28oY1swXSksbyhjWzFdKSxvKGNbMl0pLGhdO2Nhc2VcImhzbGFcIjppZig0IT09Yy5sZW5ndGgpcmV0dXJuIG51bGw7aD1hKGMucG9wKCkpO2Nhc2VcImhzbFwiOmlmKDMhPT1jLmxlbmd0aClyZXR1cm4gbnVsbDt2YXIgZj0ocGFyc2VGbG9hdChjWzBdKSUzNjArMzYwKSUzNjAvMzYwLHk9YShjWzFdKSxkPWEoY1syXSksdj1kPD0uNT9kKih5KzEpOmQreS1kKnksbT0yKmQtdjtyZXR1cm5bbigyNTUqcyhtLHYsZisxLzMpKSxuKDI1NSpzKG0sdixmKSksbigyNTUqcyhtLHYsZi0xLzMpKSxoXTtkZWZhdWx0OnJldHVybiBudWxsfX1yZXR1cm4gbnVsbH07fWNhdGNoKHQpe319KS5wYXJzZUNTU0NvbG9yLFE9ZnVuY3Rpb24odCxlLHIsbil7dm9pZCAwPT09biYmKG49MSksdGhpcy5yPXQsdGhpcy5nPWUsdGhpcy5iPXIsdGhpcy5hPW47fTtRLnBhcnNlPWZ1bmN0aW9uKHQpe2lmKHQpe2lmKHQgaW5zdGFuY2VvZiBRKXJldHVybiB0O2lmKFwic3RyaW5nXCI9PXR5cGVvZiB0KXt2YXIgZT1XKHQpO2lmKGUpcmV0dXJuIG5ldyBRKGVbMF0vMjU1KmVbM10sZVsxXS8yNTUqZVszXSxlWzJdLzI1NSplWzNdLGVbM10pfX19LFEucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy50b0FycmF5KCksZT10WzBdLHI9dFsxXSxuPXRbMl0saT10WzNdO3JldHVyblwicmdiYShcIitNYXRoLnJvdW5kKGUpK1wiLFwiK01hdGgucm91bmQocikrXCIsXCIrTWF0aC5yb3VuZChuKStcIixcIitpK1wiKVwifSxRLnByb3RvdHlwZS50b0FycmF5PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yLGU9dGhpcy5nLHI9dGhpcy5iLG49dGhpcy5hO3JldHVybiAwPT09bj9bMCwwLDAsMF06WzI1NSp0L24sMjU1KmUvbiwyNTUqci9uLG5dfSxRLmJsYWNrPW5ldyBRKDAsMCwwLDEpLFEud2hpdGU9bmV3IFEoMSwxLDEsMSksUS50cmFuc3BhcmVudD1uZXcgUSgwLDAsMCwwKTt2YXIgdHQ9ZnVuY3Rpb24odCxlLHIpe3RoaXMuc2Vuc2l0aXZpdHk9dD9lP1widmFyaWFudFwiOlwiY2FzZVwiOmU/XCJhY2NlbnRcIjpcImJhc2VcIix0aGlzLmxvY2FsZT1yLHRoaXMuY29sbGF0b3I9bmV3IEludGwuQ29sbGF0b3IodGhpcy5sb2NhbGU/dGhpcy5sb2NhbGU6W10se3NlbnNpdGl2aXR5OnRoaXMuc2Vuc2l0aXZpdHksdXNhZ2U6XCJzZWFyY2hcIn0pO307dHQucHJvdG90eXBlLmNvbXBhcmU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5jb2xsYXRvci5jb21wYXJlKHQsZSl9LHR0LnByb3RvdHlwZS5yZXNvbHZlZExvY2FsZT1mdW5jdGlvbigpe3JldHVybiBuZXcgSW50bC5Db2xsYXRvcih0aGlzLmxvY2FsZT90aGlzLmxvY2FsZTpbXSkucmVzb2x2ZWRPcHRpb25zKCkubG9jYWxlfTt2YXIgZXQ9ZnVuY3Rpb24odCxlLHIpe3RoaXMudHlwZT0kLHRoaXMubG9jYWxlPXIsdGhpcy5jYXNlU2Vuc2l0aXZlPXQsdGhpcy5kaWFjcml0aWNTZW5zaXRpdmU9ZTt9O2Z1bmN0aW9uIHJ0KHQsZSxyLG4pe3JldHVyblwibnVtYmVyXCI9PXR5cGVvZiB0JiZ0Pj0wJiZ0PD0yNTUmJlwibnVtYmVyXCI9PXR5cGVvZiBlJiZlPj0wJiZlPD0yNTUmJlwibnVtYmVyXCI9PXR5cGVvZiByJiZyPj0wJiZyPD0yNTU/dm9pZCAwPT09bnx8XCJudW1iZXJcIj09dHlwZW9mIG4mJm4+PTAmJm48PTE/bnVsbDpcIkludmFsaWQgcmdiYSB2YWx1ZSBbXCIrW3QsZSxyLG5dLmpvaW4oXCIsIFwiKStcIl06ICdhJyBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMS5cIjpcIkludmFsaWQgcmdiYSB2YWx1ZSBbXCIrKFwibnVtYmVyXCI9PXR5cGVvZiBuP1t0LGUscixuXTpbdCxlLHJdKS5qb2luKFwiLCBcIikrXCJdOiAncicsICdnJywgYW5kICdiJyBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMjU1LlwifWZ1bmN0aW9uIG50KHQpe2lmKG51bGw9PT10KXJldHVybiBSO2lmKFwic3RyaW5nXCI9PXR5cGVvZiB0KXJldHVybiBEO2lmKFwiYm9vbGVhblwiPT10eXBlb2YgdClyZXR1cm4gTjtpZihcIm51bWJlclwiPT10eXBlb2YgdClyZXR1cm4gVTtpZih0IGluc3RhbmNlb2YgUSlyZXR1cm4gWjtpZih0IGluc3RhbmNlb2YgdHQpcmV0dXJuICQ7aWYoQXJyYXkuaXNBcnJheSh0KSl7Zm9yKHZhciBlLHI9dC5sZW5ndGgsbj0wLGk9dDtuPGkubGVuZ3RoO24rPTEpe3ZhciBvPW50KGlbbl0pO2lmKGUpe2lmKGU9PT1vKWNvbnRpbnVlO2U9SjticmVha31lPW87fXJldHVybiBIKGV8fEoscil9cmV0dXJuIEt9ZXQucGFyc2U9ZnVuY3Rpb24odCxlKXtpZigyIT09dC5sZW5ndGgpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBvbmUgYXJndW1lbnQuXCIpO3ZhciByPXRbMV07aWYoXCJvYmplY3RcIiE9dHlwZW9mIHJ8fEFycmF5LmlzQXJyYXkocikpcmV0dXJuIGUuZXJyb3IoXCJDb2xsYXRvciBvcHRpb25zIGFyZ3VtZW50IG11c3QgYmUgYW4gb2JqZWN0LlwiKTt2YXIgbj1lLnBhcnNlKHZvaWQgMCE9PXJbXCJjYXNlLXNlbnNpdGl2ZVwiXSYmcltcImNhc2Utc2Vuc2l0aXZlXCJdLDEsTik7aWYoIW4pcmV0dXJuIG51bGw7dmFyIGk9ZS5wYXJzZSh2b2lkIDAhPT1yW1wiZGlhY3JpdGljLXNlbnNpdGl2ZVwiXSYmcltcImRpYWNyaXRpYy1zZW5zaXRpdmVcIl0sMSxOKTtpZighaSlyZXR1cm4gbnVsbDt2YXIgbz1udWxsO3JldHVybiByLmxvY2FsZSYmIShvPWUucGFyc2Uoci5sb2NhbGUsMSxEKSk/bnVsbDpuZXcgZXQobixpLG8pfSxldC5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyB0dCh0aGlzLmNhc2VTZW5zaXRpdmUuZXZhbHVhdGUodCksdGhpcy5kaWFjcml0aWNTZW5zaXRpdmUuZXZhbHVhdGUodCksdGhpcy5sb2NhbGU/dGhpcy5sb2NhbGUuZXZhbHVhdGUodCk6bnVsbCl9LGV0LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmNhc2VTZW5zaXRpdmUpLHQodGhpcy5kaWFjcml0aWNTZW5zaXRpdmUpLHRoaXMubG9jYWxlJiZ0KHRoaXMubG9jYWxlKTt9LGV0LnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm5bdm9pZCAwXX0sZXQucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PXt9O3JldHVybiB0W1wiY2FzZS1zZW5zaXRpdmVcIl09dGhpcy5jYXNlU2Vuc2l0aXZlLnNlcmlhbGl6ZSgpLHRbXCJkaWFjcml0aWMtc2Vuc2l0aXZlXCJdPXRoaXMuZGlhY3JpdGljU2Vuc2l0aXZlLnNlcmlhbGl6ZSgpLHRoaXMubG9jYWxlJiYodC5sb2NhbGU9dGhpcy5sb2NhbGUuc2VyaWFsaXplKCkpLFtcImNvbGxhdG9yXCIsdF19O3ZhciBpdD1mdW5jdGlvbih0LGUpe3RoaXMudHlwZT10LHRoaXMudmFsdWU9ZTt9O2l0LnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYoMiE9PXQubGVuZ3RoKXJldHVybiBlLmVycm9yKFwiJ2xpdGVyYWwnIGV4cHJlc3Npb24gcmVxdWlyZXMgZXhhY3RseSBvbmUgYXJndW1lbnQsIGJ1dCBmb3VuZCBcIisodC5sZW5ndGgtMSkrXCIgaW5zdGVhZC5cIik7aWYoIWZ1bmN0aW9uIHQoZSl7aWYobnVsbD09PWUpcmV0dXJuITA7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGUpcmV0dXJuITA7aWYoXCJib29sZWFuXCI9PXR5cGVvZiBlKXJldHVybiEwO2lmKFwibnVtYmVyXCI9PXR5cGVvZiBlKXJldHVybiEwO2lmKGUgaW5zdGFuY2VvZiBRKXJldHVybiEwO2lmKGUgaW5zdGFuY2VvZiB0dClyZXR1cm4hMDtpZihBcnJheS5pc0FycmF5KGUpKXtmb3IodmFyIHI9MCxuPWU7cjxuLmxlbmd0aDtyKz0xKWlmKCF0KG5bcl0pKXJldHVybiExO3JldHVybiEwfWlmKFwib2JqZWN0XCI9PXR5cGVvZiBlKXtmb3IodmFyIGkgaW4gZSlpZighdChlW2ldKSlyZXR1cm4hMTtyZXR1cm4hMH1yZXR1cm4hMX0odFsxXSkpcmV0dXJuIGUuZXJyb3IoXCJpbnZhbGlkIHZhbHVlXCIpO3ZhciByPXRbMV0sbj1udChyKSxpPWUuZXhwZWN0ZWRUeXBlO3JldHVyblwiYXJyYXlcIiE9PW4ua2luZHx8MCE9PW4uTnx8IWl8fFwiYXJyYXlcIiE9PWkua2luZHx8XCJudW1iZXJcIj09dHlwZW9mIGkuTiYmMCE9PWkuTnx8KG49aSksbmV3IGl0KG4scil9LGl0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnZhbHVlfSxpdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKCl7fSxpdC5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuW3RoaXMudmFsdWVdfSxpdC5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuXCJhcnJheVwiPT09dGhpcy50eXBlLmtpbmR8fFwib2JqZWN0XCI9PT10aGlzLnR5cGUua2luZD9bXCJsaXRlcmFsXCIsdGhpcy52YWx1ZV06dGhpcy52YWx1ZSBpbnN0YW5jZW9mIFE/W1wicmdiYVwiXS5jb25jYXQodGhpcy52YWx1ZS50b0FycmF5KCkpOnRoaXMudmFsdWV9O3ZhciBvdD1mdW5jdGlvbih0KXt0aGlzLm5hbWU9XCJFeHByZXNzaW9uRXZhbHVhdGlvbkVycm9yXCIsdGhpcy5tZXNzYWdlPXQ7fTtvdC5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubWVzc2FnZX07dmFyIGF0PXtzdHJpbmc6RCxudW1iZXI6VSxib29sZWFuOk4sb2JqZWN0Okt9LHN0PWZ1bmN0aW9uKHQsZSl7dGhpcy50eXBlPXQsdGhpcy5hcmdzPWU7fTtzdC5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPDIpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCBvbmUgYXJndW1lbnQuXCIpO2Zvcih2YXIgcj10WzBdLG49YXRbcl0saT1bXSxvPTE7bzx0Lmxlbmd0aDtvKyspe3ZhciBhPWUucGFyc2UodFtvXSxvLEopO2lmKCFhKXJldHVybiBudWxsO2kucHVzaChhKTt9cmV0dXJuIG5ldyBzdChuLGkpfSxzdC5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTA7ZTx0aGlzLmFyZ3MubGVuZ3RoO2UrKyl7dmFyIHI9dGhpcy5hcmdzW2VdLmV2YWx1YXRlKHQpO2lmKCFZKHRoaXMudHlwZSxudChyKSkpcmV0dXJuIHI7aWYoZT09PXRoaXMuYXJncy5sZW5ndGgtMSl0aHJvdyBuZXcgb3QoXCJFeHBlY3RlZCB2YWx1ZSB0byBiZSBvZiB0eXBlIFwiK1godGhpcy50eXBlKStcIiwgYnV0IGZvdW5kIFwiK1gobnQocikpK1wiIGluc3RlYWQuXCIpfXJldHVybiBudWxsfSxzdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3RoaXMuYXJncy5mb3JFYWNoKHQpO30sc3QucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybih0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLmFyZ3MubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpO3ZhciB0O30sc3QucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3JldHVyblt0aGlzLnR5cGUua2luZF0uY29uY2F0KHRoaXMuYXJncy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuc2VyaWFsaXplKCl9KSl9O3ZhciB1dD17c3RyaW5nOkQsbnVtYmVyOlUsYm9vbGVhbjpOfSxsdD1mdW5jdGlvbih0LGUpe3RoaXMudHlwZT10LHRoaXMuaW5wdXQ9ZTt9O2x0LnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYodC5sZW5ndGg8Mnx8dC5sZW5ndGg+NClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIDEsIDIsIG9yIDMgYXJndW1lbnRzLCBidXQgZm91bmQgXCIrKHQubGVuZ3RoLTEpK1wiIGluc3RlYWQuXCIpO3ZhciByLG47aWYodC5sZW5ndGg+Mil7dmFyIGk9dFsxXTtpZihcInN0cmluZ1wiIT10eXBlb2YgaXx8IShpIGluIHV0KSlyZXR1cm4gZS5lcnJvcignVGhlIGl0ZW0gdHlwZSBhcmd1bWVudCBvZiBcImFycmF5XCIgbXVzdCBiZSBvbmUgb2Ygc3RyaW5nLCBudW1iZXIsIGJvb2xlYW4nLDEpO3I9dXRbaV07fWVsc2Ugcj1KO2lmKHQubGVuZ3RoPjMpe2lmKFwibnVtYmVyXCIhPXR5cGVvZiB0WzJdfHx0WzJdPDB8fHRbMl0hPT1NYXRoLmZsb29yKHRbMl0pKXJldHVybiBlLmVycm9yKCdUaGUgbGVuZ3RoIGFyZ3VtZW50IHRvIFwiYXJyYXlcIiBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlciBsaXRlcmFsJywyKTtuPXRbMl07fXZhciBvPUgocixuKSxhPWUucGFyc2UodFt0Lmxlbmd0aC0xXSx0Lmxlbmd0aC0xLEopO3JldHVybiBhP25ldyBsdChvLGEpOm51bGx9LGx0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmlucHV0LmV2YWx1YXRlKHQpO2lmKFkodGhpcy50eXBlLG50KGUpKSl0aHJvdyBuZXcgb3QoXCJFeHBlY3RlZCB2YWx1ZSB0byBiZSBvZiB0eXBlIFwiK1godGhpcy50eXBlKStcIiwgYnV0IGZvdW5kIFwiK1gobnQoZSkpK1wiIGluc3RlYWQuXCIpO3JldHVybiBlfSxsdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3QodGhpcy5pbnB1dCk7fSxsdC5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuaW5wdXQucG9zc2libGVPdXRwdXRzKCl9LGx0LnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD1bXCJhcnJheVwiXSxlPXRoaXMudHlwZS5pdGVtVHlwZTtpZihcInN0cmluZ1wiPT09ZS5raW5kfHxcIm51bWJlclwiPT09ZS5raW5kfHxcImJvb2xlYW5cIj09PWUua2luZCl7dC5wdXNoKGUua2luZCk7dmFyIHI9dGhpcy50eXBlLk47XCJudW1iZXJcIj09dHlwZW9mIHImJnQucHVzaChyKTt9cmV0dXJuIHQucHVzaCh0aGlzLmlucHV0LnNlcmlhbGl6ZSgpKSx0fTt2YXIgcHQ9e1widG8tbnVtYmVyXCI6VSxcInRvLWNvbG9yXCI6Wn0sY3Q9ZnVuY3Rpb24odCxlKXt0aGlzLnR5cGU9dCx0aGlzLmFyZ3M9ZTt9O2N0LnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYodC5sZW5ndGg8MilyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGF0IGxlYXN0IG9uZSBhcmd1bWVudC5cIik7Zm9yKHZhciByPXRbMF0sbj1wdFtyXSxpPVtdLG89MTtvPHQubGVuZ3RoO28rKyl7dmFyIGE9ZS5wYXJzZSh0W29dLG8sSik7aWYoIWEpcmV0dXJuIG51bGw7aS5wdXNoKGEpO31yZXR1cm4gbmV3IGN0KG4saSl9LGN0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtpZihcImNvbG9yXCI9PT10aGlzLnR5cGUua2luZCl7Zm9yKHZhciBlLHIsbj0wLGk9dGhpcy5hcmdzO248aS5sZW5ndGg7bis9MSl7aWYocj1udWxsLFwic3RyaW5nXCI9PXR5cGVvZihlPWlbbl0uZXZhbHVhdGUodCkpKXt2YXIgbz10LnBhcnNlQ29sb3IoZSk7aWYobylyZXR1cm4gb31lbHNlIGlmKEFycmF5LmlzQXJyYXkoZSkmJiEocj1lLmxlbmd0aDwzfHxlLmxlbmd0aD40P1wiSW52YWxpZCByYmdhIHZhbHVlIFwiK0pTT04uc3RyaW5naWZ5KGUpK1wiOiBleHBlY3RlZCBhbiBhcnJheSBjb250YWluaW5nIGVpdGhlciB0aHJlZSBvciBmb3VyIG51bWVyaWMgdmFsdWVzLlwiOnJ0KGVbMF0sZVsxXSxlWzJdLGVbM10pKSlyZXR1cm4gbmV3IFEoZVswXS8yNTUsZVsxXS8yNTUsZVsyXS8yNTUsZVszXSl9dGhyb3cgbmV3IG90KHJ8fFwiQ291bGQgbm90IHBhcnNlIGNvbG9yIGZyb20gdmFsdWUgJ1wiKyhcInN0cmluZ1wiPT10eXBlb2YgZT9lOkpTT04uc3RyaW5naWZ5KGUpKStcIidcIil9Zm9yKHZhciBhPW51bGwscz0wLHU9dGhpcy5hcmdzO3M8dS5sZW5ndGg7cys9MSl7aWYobnVsbCE9PShhPXVbc10uZXZhbHVhdGUodCkpKXt2YXIgbD1OdW1iZXIoYSk7aWYoIWlzTmFOKGwpKXJldHVybiBsfX10aHJvdyBuZXcgb3QoXCJDb3VsZCBub3QgY29udmVydCBcIitKU09OLnN0cmluZ2lmeShhKStcIiB0byBudW1iZXIuXCIpfSxjdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3RoaXMuYXJncy5mb3JFYWNoKHQpO30sY3QucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybih0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLmFyZ3MubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpO3ZhciB0O30sY3QucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PVtcInRvLVwiK3RoaXMudHlwZS5raW5kXTtyZXR1cm4gdGhpcy5lYWNoQ2hpbGQoZnVuY3Rpb24oZSl7dC5wdXNoKGUuc2VyaWFsaXplKCkpO30pLHR9O3ZhciBodD1bXCJVbmtub3duXCIsXCJQb2ludFwiLFwiTGluZVN0cmluZ1wiLFwiUG9seWdvblwiXSxmdD1mdW5jdGlvbigpe3RoaXMuX3BhcnNlQ29sb3JDYWNoZT17fTt9O2Z0LnByb3RvdHlwZS5pZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmUmJlwiaWRcImluIHRoaXMuZmVhdHVyZT90aGlzLmZlYXR1cmUuaWQ6bnVsbH0sZnQucHJvdG90eXBlLmdlb21ldHJ5VHlwZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmU/XCJudW1iZXJcIj09dHlwZW9mIHRoaXMuZmVhdHVyZS50eXBlP2h0W3RoaXMuZmVhdHVyZS50eXBlXTp0aGlzLmZlYXR1cmUudHlwZTpudWxsfSxmdC5wcm90b3R5cGUucHJvcGVydGllcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmUmJnRoaXMuZmVhdHVyZS5wcm9wZXJ0aWVzfHx7fX0sZnQucHJvdG90eXBlLnBhcnNlQ29sb3I9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fcGFyc2VDb2xvckNhY2hlW3RdO3JldHVybiBlfHwoZT10aGlzLl9wYXJzZUNvbG9yQ2FjaGVbdF09US5wYXJzZSh0KSksZX07dmFyIHl0PWZ1bmN0aW9uKHQsZSxyLG4pe3RoaXMubmFtZT10LHRoaXMudHlwZT1lLHRoaXMuX2V2YWx1YXRlPXIsdGhpcy5hcmdzPW47fTtmdW5jdGlvbiBkdCh0KXtpZih0IGluc3RhbmNlb2YgeXQpe2lmKFwiZ2V0XCI9PT10Lm5hbWUmJjE9PT10LmFyZ3MubGVuZ3RoKXJldHVybiExO2lmKFwiaGFzXCI9PT10Lm5hbWUmJjE9PT10LmFyZ3MubGVuZ3RoKXJldHVybiExO2lmKFwicHJvcGVydGllc1wiPT09dC5uYW1lfHxcImdlb21ldHJ5LXR5cGVcIj09PXQubmFtZXx8XCJpZFwiPT09dC5uYW1lKXJldHVybiExO2lmKC9eZmlsdGVyLS8udGVzdCh0Lm5hbWUpKXJldHVybiExfXZhciBlPSEwO3JldHVybiB0LmVhY2hDaGlsZChmdW5jdGlvbih0KXtlJiYhZHQodCkmJihlPSExKTt9KSxlfWZ1bmN0aW9uIHZ0KHQsZSl7aWYodCBpbnN0YW5jZW9mIHl0JiZlLmluZGV4T2YodC5uYW1lKT49MClyZXR1cm4hMTt2YXIgcj0hMDtyZXR1cm4gdC5lYWNoQ2hpbGQoZnVuY3Rpb24odCl7ciYmIXZ0KHQsZSkmJihyPSExKTt9KSxyfXl0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fZXZhbHVhdGUodCx0aGlzLmFyZ3MpfSx5dC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3RoaXMuYXJncy5mb3JFYWNoKHQpO30seXQucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVyblt2b2lkIDBdfSx5dC5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuW3RoaXMubmFtZV0uY29uY2F0KHRoaXMuYXJncy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuc2VyaWFsaXplKCl9KSl9LHl0LnBhcnNlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dFswXSxuPXl0LmRlZmluaXRpb25zW3JdO2lmKCFuKXJldHVybiBlLmVycm9yKCdVbmtub3duIGV4cHJlc3Npb24gXCInK3IrJ1wiLiBJZiB5b3Ugd2FudGVkIGEgbGl0ZXJhbCBhcnJheSwgdXNlIFtcImxpdGVyYWxcIiwgWy4uLl1dLicsMCk7Zm9yKHZhciBpPUFycmF5LmlzQXJyYXkobik/blswXTpuLnR5cGUsbz1BcnJheS5pc0FycmF5KG4pP1tbblsxXSxuWzJdXV06bi5vdmVybG9hZHMsYT1vLmZpbHRlcihmdW5jdGlvbihlKXt2YXIgcj1lWzBdO3JldHVybiFBcnJheS5pc0FycmF5KHIpfHxyLmxlbmd0aD09PXQubGVuZ3RoLTF9KSxzPVtdLHU9MTt1PHQubGVuZ3RoO3UrKyl7dmFyIGw9dFt1XSxwPXZvaWQgMDtpZigxPT09YS5sZW5ndGgpe3ZhciBjPWFbMF1bMF07cD1BcnJheS5pc0FycmF5KGMpP2NbdS0xXTpjLnR5cGU7fXZhciBoPWUucGFyc2UobCwxK3MubGVuZ3RoLHApO2lmKCFoKXJldHVybiBudWxsO3MucHVzaChoKTt9Zm9yKHZhciBmPW51bGwseT0wLGQ9YTt5PGQubGVuZ3RoO3krPTEpe3ZhciB2PWRbeV0sbT12WzBdLGc9dlsxXTtpZihmPW5ldyBndChlLnJlZ2lzdHJ5LGUucGF0aCxudWxsLGUuc2NvcGUpLEFycmF5LmlzQXJyYXkobSkmJm0ubGVuZ3RoIT09cy5sZW5ndGgpZi5lcnJvcihcIkV4cGVjdGVkIFwiK20ubGVuZ3RoK1wiIGFyZ3VtZW50cywgYnV0IGZvdW5kIFwiK3MubGVuZ3RoK1wiIGluc3RlYWQuXCIpO2Vsc2V7Zm9yKHZhciB4PTA7eDxzLmxlbmd0aDt4Kyspe3ZhciBiPUFycmF5LmlzQXJyYXkobSk/bVt4XTptLnR5cGUsdz1zW3hdO2YuY29uY2F0KHgrMSkuY2hlY2tTdWJ0eXBlKGIsdy50eXBlKTt9aWYoMD09PWYuZXJyb3JzLmxlbmd0aClyZXR1cm4gbmV3IHl0KHIsaSxnLHMpfX1pZigxPT09YS5sZW5ndGgpZS5lcnJvcnMucHVzaC5hcHBseShlLmVycm9ycyxmLmVycm9ycyk7ZWxzZXt2YXIgXz0oYS5sZW5ndGg/YTpvKS5tYXAoZnVuY3Rpb24odCl7dmFyIGUscj10WzBdO3JldHVybiBlPXIsQXJyYXkuaXNBcnJheShlKT9cIihcIitlLm1hcChYKS5qb2luKFwiLCBcIikrXCIpXCI6XCIoXCIrWChlLnR5cGUpK1wiLi4uKVwifSkuam9pbihcIiB8IFwiKSxBPXMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBYKHQudHlwZSl9KS5qb2luKFwiLCBcIik7ZS5lcnJvcihcIkV4cGVjdGVkIGFyZ3VtZW50cyBvZiB0eXBlIFwiK18rXCIsIGJ1dCBmb3VuZCAoXCIrQStcIikgaW5zdGVhZC5cIik7fXJldHVybiBudWxsfSx5dC5yZWdpc3Rlcj1mdW5jdGlvbih0LGUpe2Zvcih2YXIgciBpbiB5dC5kZWZpbml0aW9ucz1lLGUpdFtyXT15dDt9O3ZhciBtdD1mdW5jdGlvbih0LGUpe3RoaXMudHlwZT1lLnR5cGUsdGhpcy5uYW1lPXQsdGhpcy5ib3VuZEV4cHJlc3Npb249ZTt9O210LnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYoMiE9PXQubGVuZ3RofHxcInN0cmluZ1wiIT10eXBlb2YgdFsxXSlyZXR1cm4gZS5lcnJvcihcIid2YXInIGV4cHJlc3Npb24gcmVxdWlyZXMgZXhhY3RseSBvbmUgc3RyaW5nIGxpdGVyYWwgYXJndW1lbnQuXCIpO3ZhciByPXRbMV07cmV0dXJuIGUuc2NvcGUuaGFzKHIpP25ldyBtdChyLGUuc2NvcGUuZ2V0KHIpKTplLmVycm9yKCdVbmtub3duIHZhcmlhYmxlIFwiJytyKydcIi4gTWFrZSBzdXJlIFwiJytyKydcIiBoYXMgYmVlbiBib3VuZCBpbiBhbiBlbmNsb3NpbmcgXCJsZXRcIiBleHByZXNzaW9uIGJlZm9yZSB1c2luZyBpdC4nLDEpfSxtdC5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYm91bmRFeHByZXNzaW9uLmV2YWx1YXRlKHQpfSxtdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKCl7fSxtdC5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuW3ZvaWQgMF19LG10LnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm5bXCJ2YXJcIix0aGlzLm5hbWVdfTt2YXIgZ3Q9ZnVuY3Rpb24odCxlLHIsbixpKXt2b2lkIDA9PT1lJiYoZT1bXSksdm9pZCAwPT09biYmKG49bmV3IHEpLHZvaWQgMD09PWkmJihpPVtdKSx0aGlzLnJlZ2lzdHJ5PXQsdGhpcy5wYXRoPWUsdGhpcy5rZXk9ZS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuXCJbXCIrdCtcIl1cIn0pLmpvaW4oXCJcIiksdGhpcy5zY29wZT1uLHRoaXMuZXJyb3JzPWksdGhpcy5leHBlY3RlZFR5cGU9cjt9O2Z1bmN0aW9uIHh0KHQsZSl7Zm9yKHZhciByLG4saT0wLG89dC5sZW5ndGgtMSxhPTA7aTw9bzspe2lmKHI9dFthPU1hdGguZmxvb3IoKGkrbykvMildLG49dFthKzFdLGU9PT1yfHxlPnImJmU8bilyZXR1cm4gYTtpZihyPGUpaT1hKzE7ZWxzZXtpZighKHI+ZSkpdGhyb3cgbmV3IG90KFwiSW5wdXQgaXMgbm90IGEgbnVtYmVyLlwiKTtvPWEtMTt9fXJldHVybiBNYXRoLm1heChhLTEsMCl9Z3QucHJvdG90eXBlLnBhcnNlPWZ1bmN0aW9uKHQsZSxyLG4saSl7cmV0dXJuIHZvaWQgMD09PWkmJihpPXt9KSxlP3RoaXMuY29uY2F0KGUscixuKS5fcGFyc2UodCxpKTp0aGlzLl9wYXJzZSh0LGkpfSxndC5wcm90b3R5cGUuX3BhcnNlPWZ1bmN0aW9uKHQsZSl7aWYobnVsbCE9PXQmJlwic3RyaW5nXCIhPXR5cGVvZiB0JiZcImJvb2xlYW5cIiE9dHlwZW9mIHQmJlwibnVtYmVyXCIhPXR5cGVvZiB0fHwodD1bXCJsaXRlcmFsXCIsdF0pLEFycmF5LmlzQXJyYXkodCkpe2lmKDA9PT10Lmxlbmd0aClyZXR1cm4gdGhpcy5lcnJvcignRXhwZWN0ZWQgYW4gYXJyYXkgd2l0aCBhdCBsZWFzdCBvbmUgZWxlbWVudC4gSWYgeW91IHdhbnRlZCBhIGxpdGVyYWwgYXJyYXksIHVzZSBbXCJsaXRlcmFsXCIsIFtdXS4nKTt2YXIgcj10WzBdO2lmKFwic3RyaW5nXCIhPXR5cGVvZiByKXJldHVybiB0aGlzLmVycm9yKFwiRXhwcmVzc2lvbiBuYW1lIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCBmb3VuZCBcIit0eXBlb2YgcisnIGluc3RlYWQuIElmIHlvdSB3YW50ZWQgYSBsaXRlcmFsIGFycmF5LCB1c2UgW1wibGl0ZXJhbFwiLCBbLi4uXV0uJywwKSxudWxsO3ZhciBuPXRoaXMucmVnaXN0cnlbcl07aWYobil7dmFyIGk9bi5wYXJzZSh0LHRoaXMpO2lmKCFpKXJldHVybiBudWxsO2lmKHRoaXMuZXhwZWN0ZWRUeXBlKXt2YXIgbz10aGlzLmV4cGVjdGVkVHlwZSxhPWkudHlwZTtpZihcInN0cmluZ1wiIT09by5raW5kJiZcIm51bWJlclwiIT09by5raW5kJiZcImJvb2xlYW5cIiE9PW8ua2luZCYmXCJvYmplY3RcIiE9PW8ua2luZHx8XCJ2YWx1ZVwiIT09YS5raW5kKWlmKFwiYXJyYXlcIj09PW8ua2luZCYmXCJ2YWx1ZVwiPT09YS5raW5kKWUub21pdFR5cGVBbm5vdGF0aW9uc3x8KGk9bmV3IGx0KG8saSkpO2Vsc2UgaWYoXCJjb2xvclwiIT09by5raW5kfHxcInZhbHVlXCIhPT1hLmtpbmQmJlwic3RyaW5nXCIhPT1hLmtpbmQpe2lmKHRoaXMuY2hlY2tTdWJ0eXBlKHRoaXMuZXhwZWN0ZWRUeXBlLGkudHlwZSkpcmV0dXJuIG51bGx9ZWxzZSBlLm9taXRUeXBlQW5ub3RhdGlvbnN8fChpPW5ldyBjdChvLFtpXSkpO2Vsc2UgZS5vbWl0VHlwZUFubm90YXRpb25zfHwoaT1uZXcgc3QobyxbaV0pKTt9aWYoIShpIGluc3RhbmNlb2YgaXQpJiZmdW5jdGlvbiB0KGUpe2lmKGUgaW5zdGFuY2VvZiBtdClyZXR1cm4gdChlLmJvdW5kRXhwcmVzc2lvbik7aWYoZSBpbnN0YW5jZW9mIHl0JiZcImVycm9yXCI9PT1lLm5hbWUpcmV0dXJuITE7aWYoZSBpbnN0YW5jZW9mIGV0KXJldHVybiExO3ZhciByPWUgaW5zdGFuY2VvZiBjdHx8ZSBpbnN0YW5jZW9mIHN0fHxlIGluc3RhbmNlb2YgbHQ7dmFyIG49ITA7ZS5lYWNoQ2hpbGQoZnVuY3Rpb24oZSl7bj1yP24mJnQoZSk6biYmZSBpbnN0YW5jZW9mIGl0O30pO2lmKCFuKXJldHVybiExO3JldHVybiBkdChlKSYmdnQoZSxbXCJ6b29tXCIsXCJoZWF0bWFwLWRlbnNpdHlcIixcImxpbmUtcHJvZ3Jlc3NcIixcImlzLXN1cHBvcnRlZC1zY3JpcHRcIl0pfShpKSl7dmFyIHM9bmV3IGZ0O3RyeXtpPW5ldyBpdChpLnR5cGUsaS5ldmFsdWF0ZShzKSk7fWNhdGNoKHQpe3JldHVybiB0aGlzLmVycm9yKHQubWVzc2FnZSksbnVsbH19cmV0dXJuIGl9cmV0dXJuIHRoaXMuZXJyb3IoJ1Vua25vd24gZXhwcmVzc2lvbiBcIicrcisnXCIuIElmIHlvdSB3YW50ZWQgYSBsaXRlcmFsIGFycmF5LCB1c2UgW1wibGl0ZXJhbFwiLCBbLi4uXV0uJywwKX1yZXR1cm4gdm9pZCAwPT09dD90aGlzLmVycm9yKFwiJ3VuZGVmaW5lZCcgdmFsdWUgaW52YWxpZC4gVXNlIG51bGwgaW5zdGVhZC5cIik6XCJvYmplY3RcIj09dHlwZW9mIHQ/dGhpcy5lcnJvcignQmFyZSBvYmplY3RzIGludmFsaWQuIFVzZSBbXCJsaXRlcmFsXCIsIHsuLi59XSBpbnN0ZWFkLicpOnRoaXMuZXJyb3IoXCJFeHBlY3RlZCBhbiBhcnJheSwgYnV0IGZvdW5kIFwiK3R5cGVvZiB0K1wiIGluc3RlYWQuXCIpfSxndC5wcm90b3R5cGUuY29uY2F0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1cIm51bWJlclwiPT10eXBlb2YgdD90aGlzLnBhdGguY29uY2F0KHQpOnRoaXMucGF0aCxpPXI/dGhpcy5zY29wZS5jb25jYXQocik6dGhpcy5zY29wZTtyZXR1cm4gbmV3IGd0KHRoaXMucmVnaXN0cnksbixlfHxudWxsLGksdGhpcy5lcnJvcnMpfSxndC5wcm90b3R5cGUuZXJyb3I9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPVtdLHI9YXJndW1lbnRzLmxlbmd0aC0xO3ItLSA+MDspZVtyXT1hcmd1bWVudHNbcisxXTt2YXIgbj1cIlwiK3RoaXMua2V5K2UubWFwKGZ1bmN0aW9uKHQpe3JldHVyblwiW1wiK3QrXCJdXCJ9KS5qb2luKFwiXCIpO3RoaXMuZXJyb3JzLnB1c2gobmV3IGoobix0KSk7fSxndC5wcm90b3R5cGUuY2hlY2tTdWJ0eXBlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9WSh0LGUpO3JldHVybiByJiZ0aGlzLmVycm9yKHIpLHJ9O3ZhciBidD1mdW5jdGlvbih0LGUscil7dGhpcy50eXBlPXQsdGhpcy5pbnB1dD1lLHRoaXMubGFiZWxzPVtdLHRoaXMub3V0cHV0cz1bXTtmb3IodmFyIG49MCxpPXI7bjxpLmxlbmd0aDtuKz0xKXt2YXIgbz1pW25dLGE9b1swXSxzPW9bMV07dGhpcy5sYWJlbHMucHVzaChhKSx0aGlzLm91dHB1dHMucHVzaChzKTt9fTtmdW5jdGlvbiB3dCh0LGUscil7cmV0dXJuIHQqKDEtcikrZSpyfWJ0LnBhcnNlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dFsxXSxuPXQuc2xpY2UoMik7aWYodC5sZW5ndGgtMTw0KXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgNCBhcmd1bWVudHMsIGJ1dCBmb3VuZCBvbmx5IFwiKyh0Lmxlbmd0aC0xKStcIi5cIik7aWYoKHQubGVuZ3RoLTEpJTIhPTApcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhbiBldmVuIG51bWJlciBvZiBhcmd1bWVudHMuXCIpO2lmKCEocj1lLnBhcnNlKHIsMSxVKSkpcmV0dXJuIG51bGw7dmFyIGk9W10sbz1udWxsO2UuZXhwZWN0ZWRUeXBlJiZcInZhbHVlXCIhPT1lLmV4cGVjdGVkVHlwZS5raW5kJiYobz1lLmV4cGVjdGVkVHlwZSksbi51bnNoaWZ0KC0xLzApO2Zvcih2YXIgYT0wO2E8bi5sZW5ndGg7YSs9Mil7dmFyIHM9blthXSx1PW5bYSsxXSxsPWErMSxwPWErMjtpZihcIm51bWJlclwiIT10eXBlb2YgcylyZXR1cm4gZS5lcnJvcignSW5wdXQvb3V0cHV0IHBhaXJzIGZvciBcInN0ZXBcIiBleHByZXNzaW9ucyBtdXN0IGJlIGRlZmluZWQgdXNpbmcgbGl0ZXJhbCBudW1lcmljIHZhbHVlcyAobm90IGNvbXB1dGVkIGV4cHJlc3Npb25zKSBmb3IgdGhlIGlucHV0IHZhbHVlcy4nLGwpO2lmKGkubGVuZ3RoJiZpW2kubGVuZ3RoLTFdWzBdPj1zKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwic3RlcFwiIGV4cHJlc3Npb25zIG11c3QgYmUgYXJyYW5nZWQgd2l0aCBpbnB1dCB2YWx1ZXMgaW4gc3RyaWN0bHkgYXNjZW5kaW5nIG9yZGVyLicsbCk7dmFyIGM9ZS5wYXJzZSh1LHAsbyk7aWYoIWMpcmV0dXJuIG51bGw7bz1vfHxjLnR5cGUsaS5wdXNoKFtzLGNdKTt9cmV0dXJuIG5ldyBidChvLHIsaSl9LGJ0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmxhYmVscyxyPXRoaXMub3V0cHV0cztpZigxPT09ZS5sZW5ndGgpcmV0dXJuIHJbMF0uZXZhbHVhdGUodCk7dmFyIG49dGhpcy5pbnB1dC5ldmFsdWF0ZSh0KTtpZihuPD1lWzBdKXJldHVybiByWzBdLmV2YWx1YXRlKHQpO3ZhciBpPWUubGVuZ3RoO3JldHVybiBuPj1lW2ktMV0/cltpLTFdLmV2YWx1YXRlKHQpOnJbeHQoZSxuKV0uZXZhbHVhdGUodCl9LGJ0LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmlucHV0KTtmb3IodmFyIGU9MCxyPXRoaXMub3V0cHV0cztlPHIubGVuZ3RoO2UrPTEpe3QocltlXSk7fX0sYnQucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybih0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLm91dHB1dHMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpO3ZhciB0O30sYnQucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe2Zvcih2YXIgdD1bXCJzdGVwXCIsdGhpcy5pbnB1dC5zZXJpYWxpemUoKV0sZT0wO2U8dGhpcy5sYWJlbHMubGVuZ3RoO2UrKyllPjAmJnQucHVzaCh0aGlzLmxhYmVsc1tlXSksdC5wdXNoKHRoaXMub3V0cHV0c1tlXS5zZXJpYWxpemUoKSk7cmV0dXJuIHR9O3ZhciBfdD1PYmplY3QuZnJlZXplKHtudW1iZXI6d3QsY29sb3I6ZnVuY3Rpb24odCxlLHIpe3JldHVybiBuZXcgUSh3dCh0LnIsZS5yLHIpLHd0KHQuZyxlLmcsciksd3QodC5iLGUuYixyKSx3dCh0LmEsZS5hLHIpKX0sYXJyYXk6ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0Lm1hcChmdW5jdGlvbih0LG4pe3JldHVybiB3dCh0LGVbbl0scil9KX19KSxBdD1mdW5jdGlvbih0LGUscixuKXt0aGlzLnR5cGU9dCx0aGlzLmludGVycG9sYXRpb249ZSx0aGlzLmlucHV0PXIsdGhpcy5sYWJlbHM9W10sdGhpcy5vdXRwdXRzPVtdO2Zvcih2YXIgaT0wLG89bjtpPG8ubGVuZ3RoO2krPTEpe3ZhciBhPW9baV0scz1hWzBdLHU9YVsxXTt0aGlzLmxhYmVscy5wdXNoKHMpLHRoaXMub3V0cHV0cy5wdXNoKHUpO319O2Z1bmN0aW9uIGt0KHQsZSxyLG4pe3ZhciBpPW4tcixvPXQtcjtyZXR1cm4gMD09PWk/MDoxPT09ZT9vL2k6KE1hdGgucG93KGUsbyktMSkvKE1hdGgucG93KGUsaSktMSl9QXQuaW50ZXJwb2xhdGlvbkZhY3Rvcj1mdW5jdGlvbih0LGUscixuKXt2YXIgbz0wO2lmKFwiZXhwb25lbnRpYWxcIj09PXQubmFtZSlvPWt0KGUsdC5iYXNlLHIsbik7ZWxzZSBpZihcImxpbmVhclwiPT09dC5uYW1lKW89a3QoZSwxLHIsbik7ZWxzZSBpZihcImN1YmljLWJlemllclwiPT09dC5uYW1lKXt2YXIgYT10LmNvbnRyb2xQb2ludHM7bz1uZXcgaShhWzBdLGFbMV0sYVsyXSxhWzNdKS5zb2x2ZShrdChlLDEscixuKSk7fXJldHVybiBvfSxBdC5wYXJzZT1mdW5jdGlvbih0LGUpe3ZhciByPXRbMV0sbj10WzJdLGk9dC5zbGljZSgzKTtpZighQXJyYXkuaXNBcnJheShyKXx8MD09PXIubGVuZ3RoKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYW4gaW50ZXJwb2xhdGlvbiB0eXBlIGV4cHJlc3Npb24uXCIsMSk7aWYoXCJsaW5lYXJcIj09PXJbMF0pcj17bmFtZTpcImxpbmVhclwifTtlbHNlIGlmKFwiZXhwb25lbnRpYWxcIj09PXJbMF0pe3ZhciBvPXJbMV07aWYoXCJudW1iZXJcIiE9dHlwZW9mIG8pcmV0dXJuIGUuZXJyb3IoXCJFeHBvbmVudGlhbCBpbnRlcnBvbGF0aW9uIHJlcXVpcmVzIGEgbnVtZXJpYyBiYXNlLlwiLDEsMSk7cj17bmFtZTpcImV4cG9uZW50aWFsXCIsYmFzZTpvfTt9ZWxzZXtpZihcImN1YmljLWJlemllclwiIT09clswXSlyZXR1cm4gZS5lcnJvcihcIlVua25vd24gaW50ZXJwb2xhdGlvbiB0eXBlIFwiK1N0cmluZyhyWzBdKSwxLDApO3ZhciBhPXIuc2xpY2UoMSk7aWYoNCE9PWEubGVuZ3RofHxhLnNvbWUoZnVuY3Rpb24odCl7cmV0dXJuXCJudW1iZXJcIiE9dHlwZW9mIHR8fHQ8MHx8dD4xfSkpcmV0dXJuIGUuZXJyb3IoXCJDdWJpYyBiZXppZXIgaW50ZXJwb2xhdGlvbiByZXF1aXJlcyBmb3VyIG51bWVyaWMgYXJndW1lbnRzIHdpdGggdmFsdWVzIGJldHdlZW4gMCBhbmQgMS5cIiwxKTtyPXtuYW1lOlwiY3ViaWMtYmV6aWVyXCIsY29udHJvbFBvaW50czphfTt9aWYodC5sZW5ndGgtMTw0KXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgNCBhcmd1bWVudHMsIGJ1dCBmb3VuZCBvbmx5IFwiKyh0Lmxlbmd0aC0xKStcIi5cIik7aWYoKHQubGVuZ3RoLTEpJTIhPTApcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhbiBldmVuIG51bWJlciBvZiBhcmd1bWVudHMuXCIpO2lmKCEobj1lLnBhcnNlKG4sMixVKSkpcmV0dXJuIG51bGw7dmFyIHM9W10sdT1udWxsO2UuZXhwZWN0ZWRUeXBlJiZcInZhbHVlXCIhPT1lLmV4cGVjdGVkVHlwZS5raW5kJiYodT1lLmV4cGVjdGVkVHlwZSk7Zm9yKHZhciBsPTA7bDxpLmxlbmd0aDtsKz0yKXt2YXIgcD1pW2xdLGM9aVtsKzFdLGg9bCszLGY9bCs0O2lmKFwibnVtYmVyXCIhPXR5cGVvZiBwKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9ucyBtdXN0IGJlIGRlZmluZWQgdXNpbmcgbGl0ZXJhbCBudW1lcmljIHZhbHVlcyAobm90IGNvbXB1dGVkIGV4cHJlc3Npb25zKSBmb3IgdGhlIGlucHV0IHZhbHVlcy4nLGgpO2lmKHMubGVuZ3RoJiZzW3MubGVuZ3RoLTFdWzBdPj1wKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9ucyBtdXN0IGJlIGFycmFuZ2VkIHdpdGggaW5wdXQgdmFsdWVzIGluIHN0cmljdGx5IGFzY2VuZGluZyBvcmRlci4nLGgpO3ZhciB5PWUucGFyc2UoYyxmLHUpO2lmKCF5KXJldHVybiBudWxsO3U9dXx8eS50eXBlLHMucHVzaChbcCx5XSk7fXJldHVyblwibnVtYmVyXCI9PT11LmtpbmR8fFwiY29sb3JcIj09PXUua2luZHx8XCJhcnJheVwiPT09dS5raW5kJiZcIm51bWJlclwiPT09dS5pdGVtVHlwZS5raW5kJiZcIm51bWJlclwiPT10eXBlb2YgdS5OP25ldyBBdCh1LHIsbixzKTplLmVycm9yKFwiVHlwZSBcIitYKHUpK1wiIGlzIG5vdCBpbnRlcnBvbGF0YWJsZS5cIil9LEF0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmxhYmVscyxyPXRoaXMub3V0cHV0cztpZigxPT09ZS5sZW5ndGgpcmV0dXJuIHJbMF0uZXZhbHVhdGUodCk7dmFyIG49dGhpcy5pbnB1dC5ldmFsdWF0ZSh0KTtpZihuPD1lWzBdKXJldHVybiByWzBdLmV2YWx1YXRlKHQpO3ZhciBpPWUubGVuZ3RoO2lmKG4+PWVbaS0xXSlyZXR1cm4gcltpLTFdLmV2YWx1YXRlKHQpO3ZhciBvPXh0KGUsbiksYT1lW29dLHM9ZVtvKzFdLHU9QXQuaW50ZXJwb2xhdGlvbkZhY3Rvcih0aGlzLmludGVycG9sYXRpb24sbixhLHMpLGw9cltvXS5ldmFsdWF0ZSh0KSxwPXJbbysxXS5ldmFsdWF0ZSh0KTtyZXR1cm4gX3RbdGhpcy50eXBlLmtpbmQudG9Mb3dlckNhc2UoKV0obCxwLHUpfSxBdC5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3QodGhpcy5pbnB1dCk7Zm9yKHZhciBlPTAscj10aGlzLm91dHB1dHM7ZTxyLmxlbmd0aDtlKz0xKXt0KHJbZV0pO319LEF0LnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4odD1bXSkuY29uY2F0LmFwcGx5KHQsdGhpcy5vdXRwdXRzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5wb3NzaWJsZU91dHB1dHMoKX0pKTt2YXIgdDt9LEF0LnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9W1wiaW50ZXJwb2xhdGVcIixcImxpbmVhclwiPT09dGhpcy5pbnRlcnBvbGF0aW9uLm5hbWU/W1wibGluZWFyXCJdOlwiZXhwb25lbnRpYWxcIj09PXRoaXMuaW50ZXJwb2xhdGlvbi5uYW1lPzE9PT10aGlzLmludGVycG9sYXRpb24uYmFzZT9bXCJsaW5lYXJcIl06W1wiZXhwb25lbnRpYWxcIix0aGlzLmludGVycG9sYXRpb24uYmFzZV06W1wiY3ViaWMtYmV6aWVyXCJdLmNvbmNhdCh0aGlzLmludGVycG9sYXRpb24uY29udHJvbFBvaW50cyksdGhpcy5pbnB1dC5zZXJpYWxpemUoKV0sZT0wO2U8dGhpcy5sYWJlbHMubGVuZ3RoO2UrKyl0LnB1c2godGhpcy5sYWJlbHNbZV0sdGhpcy5vdXRwdXRzW2VdLnNlcmlhbGl6ZSgpKTtyZXR1cm4gdH07dmFyIHp0PWZ1bmN0aW9uKHQsZSl7dGhpcy50eXBlPXQsdGhpcy5hcmdzPWU7fTt6dC5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPDIpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlY3RlZCBhdCBsZWFzdCBvbmUgYXJndW1lbnQuXCIpO3ZhciByPW51bGwsbj1lLmV4cGVjdGVkVHlwZTtuJiZcInZhbHVlXCIhPT1uLmtpbmQmJihyPW4pO2Zvcih2YXIgaT1bXSxvPTAsYT10LnNsaWNlKDEpO288YS5sZW5ndGg7bys9MSl7dmFyIHM9YVtvXSx1PWUucGFyc2UocywxK2kubGVuZ3RoLHIsdm9pZCAwLHtvbWl0VHlwZUFubm90YXRpb25zOiEwfSk7aWYoIXUpcmV0dXJuIG51bGw7cj1yfHx1LnR5cGUsaS5wdXNoKHUpO312YXIgbD1uJiZpLnNvbWUoZnVuY3Rpb24odCl7cmV0dXJuIFkobix0LnR5cGUpfSk7cmV0dXJuIG5ldyB6dChsP0o6cixpKX0senQucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1udWxsLHI9MCxuPXRoaXMuYXJncztyPG4ubGVuZ3RoO3IrPTEpe2lmKG51bGwhPT0oZT1uW3JdLmV2YWx1YXRlKHQpKSlicmVha31yZXR1cm4gZX0senQucHJvdG90eXBlLmVhY2hDaGlsZD1mdW5jdGlvbih0KXt0aGlzLmFyZ3MuZm9yRWFjaCh0KTt9LHp0LnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4odD1bXSkuY29uY2F0LmFwcGx5KHQsdGhpcy5hcmdzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5wb3NzaWJsZU91dHB1dHMoKX0pKTt2YXIgdDt9LHp0LnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD1bXCJjb2FsZXNjZVwiXTtyZXR1cm4gdGhpcy5lYWNoQ2hpbGQoZnVuY3Rpb24oZSl7dC5wdXNoKGUuc2VyaWFsaXplKCkpO30pLHR9O3ZhciBTdD1mdW5jdGlvbih0LGUpe3RoaXMudHlwZT1lLnR5cGUsdGhpcy5iaW5kaW5ncz1bXS5jb25jYXQodCksdGhpcy5yZXN1bHQ9ZTt9O1N0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5yZXN1bHQuZXZhbHVhdGUodCl9LFN0LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmJpbmRpbmdzO2U8ci5sZW5ndGg7ZSs9MSl7dChyW2VdWzFdKTt9dCh0aGlzLnJlc3VsdCk7fSxTdC5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPDQpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCAzIGFyZ3VtZW50cywgYnV0IGZvdW5kIFwiKyh0Lmxlbmd0aC0xKStcIiBpbnN0ZWFkLlwiKTtmb3IodmFyIHI9W10sbj0xO248dC5sZW5ndGgtMTtuKz0yKXt2YXIgaT10W25dO2lmKFwic3RyaW5nXCIhPXR5cGVvZiBpKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgc3RyaW5nLCBidXQgZm91bmQgXCIrdHlwZW9mIGkrXCIgaW5zdGVhZC5cIixuKTtpZigvW15hLXpBLVowLTlfXS8udGVzdChpKSlyZXR1cm4gZS5lcnJvcihcIlZhcmlhYmxlIG5hbWVzIG11c3QgY29udGFpbiBvbmx5IGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzIG9yICdfJy5cIixuKTt2YXIgbz1lLnBhcnNlKHRbbisxXSxuKzEpO2lmKCFvKXJldHVybiBudWxsO3IucHVzaChbaSxvXSk7fXZhciBhPWUucGFyc2UodFt0Lmxlbmd0aC0xXSx0Lmxlbmd0aC0xLHZvaWQgMCxyKTtyZXR1cm4gYT9uZXcgU3QocixhKTpudWxsfSxTdC5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVzdWx0LnBvc3NpYmxlT3V0cHV0cygpfSxTdC5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PVtcImxldFwiXSxlPTAscj10aGlzLmJpbmRpbmdzO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPW5bMF0sbz1uWzFdO3QucHVzaChpLG8uc2VyaWFsaXplKCkpO31yZXR1cm4gdC5wdXNoKHRoaXMucmVzdWx0LnNlcmlhbGl6ZSgpKSx0fTt2YXIgTXQ9ZnVuY3Rpb24odCxlLHIpe3RoaXMudHlwZT10LHRoaXMuaW5kZXg9ZSx0aGlzLmlucHV0PXI7fTtNdC5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKDMhPT10Lmxlbmd0aClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIDIgYXJndW1lbnRzLCBidXQgZm91bmQgXCIrKHQubGVuZ3RoLTEpK1wiIGluc3RlYWQuXCIpO3ZhciByPWUucGFyc2UodFsxXSwxLFUpLG49ZS5wYXJzZSh0WzJdLDIsSChlLmV4cGVjdGVkVHlwZXx8SikpO2lmKCFyfHwhbilyZXR1cm4gbnVsbDt2YXIgaT1uLnR5cGU7cmV0dXJuIG5ldyBNdChpLml0ZW1UeXBlLHIsbil9LE10LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmluZGV4LmV2YWx1YXRlKHQpLHI9dGhpcy5pbnB1dC5ldmFsdWF0ZSh0KTtpZihlPDApdGhyb3cgbmV3IG90KFwiQXJyYXkgaW5kZXggb3V0IG9mIGJvdW5kczogXCIrZStcIiA8IDAuXCIpO2lmKGU+PXIubGVuZ3RoKXRocm93IG5ldyBvdChcIkFycmF5IGluZGV4IG91dCBvZiBib3VuZHM6IFwiK2UrXCIgPiBcIisoci5sZW5ndGgtMSkrXCIuXCIpO2lmKGUhPT1NYXRoLmZsb29yKGUpKXRocm93IG5ldyBvdChcIkFycmF5IGluZGV4IG11c3QgYmUgYW4gaW50ZWdlciwgYnV0IGZvdW5kIFwiK2UrXCIgaW5zdGVhZC5cIik7cmV0dXJuIHJbZV19LE10LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmluZGV4KSx0KHRoaXMuaW5wdXQpO30sTXQucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVyblt2b2lkIDBdfSxNdC5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuW1wiYXRcIix0aGlzLmluZGV4LnNlcmlhbGl6ZSgpLHRoaXMuaW5wdXQuc2VyaWFsaXplKCldfTt2YXIgVnQ9ZnVuY3Rpb24odCxlLHIsbixpLG8pe3RoaXMuaW5wdXRUeXBlPXQsdGhpcy50eXBlPWUsdGhpcy5pbnB1dD1yLHRoaXMuY2FzZXM9bix0aGlzLm91dHB1dHM9aSx0aGlzLm90aGVyd2lzZT1vO307VnQucGFyc2U9ZnVuY3Rpb24odCxlKXtpZih0Lmxlbmd0aDw1KXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgNCBhcmd1bWVudHMsIGJ1dCBmb3VuZCBvbmx5IFwiKyh0Lmxlbmd0aC0xKStcIi5cIik7aWYodC5sZW5ndGglMiE9MSlyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGFuIGV2ZW4gbnVtYmVyIG9mIGFyZ3VtZW50cy5cIik7dmFyIHIsbjtlLmV4cGVjdGVkVHlwZSYmXCJ2YWx1ZVwiIT09ZS5leHBlY3RlZFR5cGUua2luZCYmKG49ZS5leHBlY3RlZFR5cGUpO2Zvcih2YXIgaT17fSxvPVtdLGE9MjthPHQubGVuZ3RoLTE7YSs9Mil7dmFyIHM9dFthXSx1PXRbYSsxXTtBcnJheS5pc0FycmF5KHMpfHwocz1bc10pO3ZhciBsPWUuY29uY2F0KGEpO2lmKDA9PT1zLmxlbmd0aClyZXR1cm4gbC5lcnJvcihcIkV4cGVjdGVkIGF0IGxlYXN0IG9uZSBicmFuY2ggbGFiZWwuXCIpO2Zvcih2YXIgcD0wLGM9cztwPGMubGVuZ3RoO3ArPTEpe3ZhciBoPWNbcF07aWYoXCJudW1iZXJcIiE9dHlwZW9mIGgmJlwic3RyaW5nXCIhPXR5cGVvZiBoKXJldHVybiBsLmVycm9yKFwiQnJhbmNoIGxhYmVscyBtdXN0IGJlIG51bWJlcnMgb3Igc3RyaW5ncy5cIik7aWYoXCJudW1iZXJcIj09dHlwZW9mIGgmJk1hdGguYWJzKGgpPk51bWJlci5NQVhfU0FGRV9JTlRFR0VSKXJldHVybiBsLmVycm9yKFwiQnJhbmNoIGxhYmVscyBtdXN0IGJlIGludGVnZXJzIG5vIGxhcmdlciB0aGFuIFwiK051bWJlci5NQVhfU0FGRV9JTlRFR0VSK1wiLlwiKTtpZihcIm51bWJlclwiPT10eXBlb2YgaCYmTWF0aC5mbG9vcihoKSE9PWgpcmV0dXJuIGwuZXJyb3IoXCJOdW1lcmljIGJyYW5jaCBsYWJlbHMgbXVzdCBiZSBpbnRlZ2VyIHZhbHVlcy5cIik7aWYocil7aWYobC5jaGVja1N1YnR5cGUocixudChoKSkpcmV0dXJuIG51bGx9ZWxzZSByPW50KGgpO2lmKHZvaWQgMCE9PWlbU3RyaW5nKGgpXSlyZXR1cm4gbC5lcnJvcihcIkJyYW5jaCBsYWJlbHMgbXVzdCBiZSB1bmlxdWUuXCIpO2lbU3RyaW5nKGgpXT1vLmxlbmd0aDt9dmFyIGY9ZS5wYXJzZSh1LGEsbik7aWYoIWYpcmV0dXJuIG51bGw7bj1ufHxmLnR5cGUsby5wdXNoKGYpO312YXIgeT1lLnBhcnNlKHRbMV0sMSxyKTtpZigheSlyZXR1cm4gbnVsbDt2YXIgZD1lLnBhcnNlKHRbdC5sZW5ndGgtMV0sdC5sZW5ndGgtMSxuKTtyZXR1cm4gZD9uZXcgVnQocixuLHksaSxvLGQpOm51bGx9LFZ0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmlucHV0LmV2YWx1YXRlKHQpO3JldHVybih0aGlzLm91dHB1dHNbdGhpcy5jYXNlc1tlXV18fHRoaXMub3RoZXJ3aXNlKS5ldmFsdWF0ZSh0KX0sVnQucHJvdG90eXBlLmVhY2hDaGlsZD1mdW5jdGlvbih0KXt0KHRoaXMuaW5wdXQpLHRoaXMub3V0cHV0cy5mb3JFYWNoKHQpLHQodGhpcy5vdGhlcndpc2UpO30sVnQucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybih0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLm91dHB1dHMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpLmNvbmNhdCh0aGlzLm90aGVyd2lzZS5wb3NzaWJsZU91dHB1dHMoKSk7dmFyIHQ7fSxWdC5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PXRoaXMsZT1bXCJtYXRjaFwiLHRoaXMuaW5wdXQuc2VyaWFsaXplKCldLHI9W10sbj17fSxpPTAsbz1PYmplY3Qua2V5cyh0aGlzLmNhc2VzKS5zb3J0KCk7aTxvLmxlbmd0aDtpKz0xKXt2YXIgYT1vW2ldLHM9blt0LmNhc2VzW2FdXTt2b2lkIDA9PT1zPyhuW3QuY2FzZXNbYV1dPXIubGVuZ3RoLHIucHVzaChbdC5jYXNlc1thXSxbYV1dKSk6cltzXVsxXS5wdXNoKGEpO31mb3IodmFyIHU9ZnVuY3Rpb24oZSl7cmV0dXJuXCJudW1iZXJcIj09PXQuaW5wdXQudHlwZS5raW5kP051bWJlcihlKTplfSxsPTAscD1yO2w8cC5sZW5ndGg7bCs9MSl7dmFyIGM9cFtsXSxoPWNbMF0sZj1jWzFdOzE9PT1mLmxlbmd0aD9lLnB1c2godShmWzBdKSk6ZS5wdXNoKGYubWFwKHUpKSxlLnB1c2godC5vdXRwdXRzW2hdLnNlcmlhbGl6ZSgpKTt9cmV0dXJuIGUucHVzaCh0aGlzLm90aGVyd2lzZS5zZXJpYWxpemUoKSksZX07dmFyIEJ0PWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnR5cGU9dCx0aGlzLmJyYW5jaGVzPWUsdGhpcy5vdGhlcndpc2U9cjt9O2Z1bmN0aW9uIEN0KHQpe3JldHVyblwic3RyaW5nXCI9PT10LmtpbmR8fFwibnVtYmVyXCI9PT10LmtpbmR8fFwiYm9vbGVhblwiPT09dC5raW5kfHxcIm51bGxcIj09PXQua2luZH1mdW5jdGlvbiBJdCh0LGUpe3JldHVybiBmdW5jdGlvbigpe2Z1bmN0aW9uIHIodCxlLHIpe3RoaXMudHlwZT1OLHRoaXMubGhzPXQsdGhpcy5yaHM9ZSx0aGlzLmNvbGxhdG9yPXI7fXJldHVybiByLnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYoMyE9PXQubGVuZ3RoJiY0IT09dC5sZW5ndGgpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCB0d28gb3IgdGhyZWUgYXJndW1lbnRzLlwiKTt2YXIgbj1lLnBhcnNlKHRbMV0sMSxKKTtpZighbilyZXR1cm4gbnVsbDt2YXIgaT1lLnBhcnNlKHRbMl0sMixKKTtpZighaSlyZXR1cm4gbnVsbDtpZighQ3Qobi50eXBlKSYmIUN0KGkudHlwZSkpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCBvbmUgYXJndW1lbnQgdG8gYmUgYSBzdHJpbmcsIG51bWJlciwgYm9vbGVhbiwgb3IgbnVsbCwgYnV0IGZvdW5kIChcIitYKG4udHlwZSkrXCIsIFwiK1goaS50eXBlKStcIikgaW5zdGVhZC5cIik7aWYobi50eXBlLmtpbmQhPT1pLnR5cGUua2luZCYmXCJ2YWx1ZVwiIT09bi50eXBlLmtpbmQmJlwidmFsdWVcIiE9PWkudHlwZS5raW5kKXJldHVybiBlLmVycm9yKFwiQ2Fubm90IGNvbXBhcmUgXCIrWChuLnR5cGUpK1wiIGFuZCBcIitYKGkudHlwZSkrXCIuXCIpO3ZhciBvPW51bGw7aWYoND09PXQubGVuZ3RoKXtpZihcInN0cmluZ1wiIT09bi50eXBlLmtpbmQmJlwic3RyaW5nXCIhPT1pLnR5cGUua2luZClyZXR1cm4gZS5lcnJvcihcIkNhbm5vdCB1c2UgY29sbGF0b3IgdG8gY29tcGFyZSBub24tc3RyaW5nIHR5cGVzLlwiKTtpZighKG89ZS5wYXJzZSh0WzNdLDMsJCkpKXJldHVybiBudWxsfXJldHVybiBuZXcgcihuLGksbyl9LHIucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3ZhciByPXRoaXMuY29sbGF0b3I/MD09PXRoaXMuY29sbGF0b3IuZXZhbHVhdGUodCkuY29tcGFyZSh0aGlzLmxocy5ldmFsdWF0ZSh0KSx0aGlzLnJocy5ldmFsdWF0ZSh0KSk6dGhpcy5saHMuZXZhbHVhdGUodCk9PT10aGlzLnJocy5ldmFsdWF0ZSh0KTtyZXR1cm4gZT8hcjpyfSxyLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmxocyksdCh0aGlzLnJocyksdGhpcy5jb2xsYXRvciYmdCh0aGlzLmNvbGxhdG9yKTt9LHIucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVyblshMCwhMV19LHIucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciBlPVt0XTtyZXR1cm4gdGhpcy5lYWNoQ2hpbGQoZnVuY3Rpb24odCl7ZS5wdXNoKHQuc2VyaWFsaXplKCkpO30pLGV9LHJ9KCl9QnQucGFyc2U9ZnVuY3Rpb24odCxlKXtpZih0Lmxlbmd0aDw0KXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgMyBhcmd1bWVudHMsIGJ1dCBmb3VuZCBvbmx5IFwiKyh0Lmxlbmd0aC0xKStcIi5cIik7aWYodC5sZW5ndGglMiE9MClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGFuIG9kZCBudW1iZXIgb2YgYXJndW1lbnRzLlwiKTt2YXIgcjtlLmV4cGVjdGVkVHlwZSYmXCJ2YWx1ZVwiIT09ZS5leHBlY3RlZFR5cGUua2luZCYmKHI9ZS5leHBlY3RlZFR5cGUpO2Zvcih2YXIgbj1bXSxpPTE7aTx0Lmxlbmd0aC0xO2krPTIpe3ZhciBvPWUucGFyc2UodFtpXSxpLE4pO2lmKCFvKXJldHVybiBudWxsO3ZhciBhPWUucGFyc2UodFtpKzFdLGkrMSxyKTtpZighYSlyZXR1cm4gbnVsbDtuLnB1c2goW28sYV0pLHI9cnx8YS50eXBlO312YXIgcz1lLnBhcnNlKHRbdC5sZW5ndGgtMV0sdC5sZW5ndGgtMSxyKTtyZXR1cm4gcz9uZXcgQnQocixuLHMpOm51bGx9LEJ0LnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtmb3IodmFyIGU9MCxyPXRoaXMuYnJhbmNoZXM7ZTxyLmxlbmd0aDtlKz0xKXt2YXIgbj1yW2VdLGk9blswXSxvPW5bMV07aWYoaS5ldmFsdWF0ZSh0KSlyZXR1cm4gby5ldmFsdWF0ZSh0KX1yZXR1cm4gdGhpcy5vdGhlcndpc2UuZXZhbHVhdGUodCl9LEJ0LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmJyYW5jaGVzO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPW5bMF0sbz1uWzFdO3QoaSksdChvKTt9dCh0aGlzLm90aGVyd2lzZSk7fSxCdC5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuKHQ9W10pLmNvbmNhdC5hcHBseSh0LHRoaXMuYnJhbmNoZXMubWFwKGZ1bmN0aW9uKHQpe3RbMF07cmV0dXJuIHRbMV0ucG9zc2libGVPdXRwdXRzKCl9KSkuY29uY2F0KHRoaXMub3RoZXJ3aXNlLnBvc3NpYmxlT3V0cHV0cygpKTt2YXIgdDt9LEJ0LnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD1bXCJjYXNlXCJdO3JldHVybiB0aGlzLmVhY2hDaGlsZChmdW5jdGlvbihlKXt0LnB1c2goZS5zZXJpYWxpemUoKSk7fSksdH07dmFyIEV0PUl0KFwiPT1cIiwhMSksRnQ9SXQoXCIhPVwiLCEwKSxQdD1mdW5jdGlvbih0KXt0aGlzLnR5cGU9VSx0aGlzLmlucHV0PXQ7fTtQdC5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKDIhPT10Lmxlbmd0aClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIDEgYXJndW1lbnQsIGJ1dCBmb3VuZCBcIisodC5sZW5ndGgtMSkrXCIgaW5zdGVhZC5cIik7dmFyIHI9ZS5wYXJzZSh0WzFdLDEpO3JldHVybiByP1wiYXJyYXlcIiE9PXIudHlwZS5raW5kJiZcInN0cmluZ1wiIT09ci50eXBlLmtpbmQmJlwidmFsdWVcIiE9PXIudHlwZS5raW5kP2UuZXJyb3IoXCJFeHBlY3RlZCBhcmd1bWVudCBvZiB0eXBlIHN0cmluZyBvciBhcnJheSwgYnV0IGZvdW5kIFwiK1goci50eXBlKStcIiBpbnN0ZWFkLlwiKTpuZXcgUHQocik6bnVsbH0sUHQucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuaW5wdXQuZXZhbHVhdGUodCk7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGUpcmV0dXJuIGUubGVuZ3RoO2lmKEFycmF5LmlzQXJyYXkoZSkpcmV0dXJuIGUubGVuZ3RoO3Rocm93IG5ldyBvdChcIkV4cGVjdGVkIHZhbHVlIHRvIGJlIG9mIHR5cGUgc3RyaW5nIG9yIGFycmF5LCBidXQgZm91bmQgXCIrWChudChlKSkrXCIgaW5zdGVhZC5cIil9LFB0LnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmlucHV0KTt9LFB0LnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm5bdm9pZCAwXX0sUHQucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PVtcImxlbmd0aFwiXTtyZXR1cm4gdGhpcy5lYWNoQ2hpbGQoZnVuY3Rpb24oZSl7dC5wdXNoKGUuc2VyaWFsaXplKCkpO30pLHR9O3ZhciBUdD17XCI9PVwiOkV0LFwiIT1cIjpGdCxhcnJheTpsdCxhdDpNdCxib29sZWFuOnN0LGNhc2U6QnQsY29hbGVzY2U6enQsY29sbGF0b3I6ZXQsaW50ZXJwb2xhdGU6QXQsbGVuZ3RoOlB0LGxldDpTdCxsaXRlcmFsOml0LG1hdGNoOlZ0LG51bWJlcjpzdCxvYmplY3Q6c3Qsc3RlcDpidCxzdHJpbmc6c3QsXCJ0by1jb2xvclwiOmN0LFwidG8tbnVtYmVyXCI6Y3QsdmFyOm10fTtmdW5jdGlvbiBPdCh0LGUpe3ZhciByPWVbMF0sbj1lWzFdLGk9ZVsyXSxvPWVbM107cj1yLmV2YWx1YXRlKHQpLG49bi5ldmFsdWF0ZSh0KSxpPWkuZXZhbHVhdGUodCk7dmFyIGE9bz9vLmV2YWx1YXRlKHQpOjEscz1ydChyLG4saSxhKTtpZihzKXRocm93IG5ldyBvdChzKTtyZXR1cm4gbmV3IFEoci8yNTUqYSxuLzI1NSphLGkvMjU1KmEsYSl9ZnVuY3Rpb24gTHQodCxlKXtyZXR1cm4gdCBpbiBlfWZ1bmN0aW9uIGp0KHQsZSl7dmFyIHI9ZVt0XTtyZXR1cm4gdm9pZCAwPT09cj9udWxsOnJ9ZnVuY3Rpb24gcXQodCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gci5ldmFsdWF0ZSh0KTxuLmV2YWx1YXRlKHQpfWZ1bmN0aW9uIFJ0KHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCk+bi5ldmFsdWF0ZSh0KX1mdW5jdGlvbiBVdCh0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiByLmV2YWx1YXRlKHQpPD1uLmV2YWx1YXRlKHQpfWZ1bmN0aW9uIER0KHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCk+PW4uZXZhbHVhdGUodCl9ZnVuY3Rpb24gTnQodCl7cmV0dXJue3R5cGU6dH19ZnVuY3Rpb24gWnQodCl7cmV0dXJue3Jlc3VsdDpcInN1Y2Nlc3NcIix2YWx1ZTp0fX1mdW5jdGlvbiBLdCh0KXtyZXR1cm57cmVzdWx0OlwiZXJyb3JcIix2YWx1ZTp0fX15dC5yZWdpc3RlcihUdCx7ZXJyb3I6W3traW5kOlwiZXJyb3JcIn0sW0RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTt0aHJvdyBuZXcgb3Qoci5ldmFsdWF0ZSh0KSl9XSx0eXBlb2Y6W0QsW0pdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIFgobnQoZVswXS5ldmFsdWF0ZSh0KSkpfV0sXCJ0by1zdHJpbmdcIjpbRCxbSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49dHlwZW9mKHI9ci5ldmFsdWF0ZSh0KSk7cmV0dXJuIG51bGw9PT1yP1wiXCI6XCJzdHJpbmdcIj09PW58fFwibnVtYmVyXCI9PT1ufHxcImJvb2xlYW5cIj09PW4/U3RyaW5nKHIpOnIgaW5zdGFuY2VvZiBRP3IudG9TdHJpbmcoKTpKU09OLnN0cmluZ2lmeShyKX1dLFwidG8tYm9vbGVhblwiOltOLFtKXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIEJvb2xlYW4oci5ldmFsdWF0ZSh0KSl9XSxcInRvLXJnYmFcIjpbSChVLDQpLFtaXSxmdW5jdGlvbih0LGUpe3JldHVybiBlWzBdLmV2YWx1YXRlKHQpLnRvQXJyYXkoKX1dLHJnYjpbWixbVSxVLFVdLE90XSxyZ2JhOltaLFtVLFUsVSxVXSxPdF0saGFzOnt0eXBlOk4sb3ZlcmxvYWRzOltbW0RdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIEx0KGVbMF0uZXZhbHVhdGUodCksdC5wcm9wZXJ0aWVzKCkpfV0sW1tELEtdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIEx0KHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSl9XV19LGdldDp7dHlwZTpKLG92ZXJsb2FkczpbW1tEXSxmdW5jdGlvbih0LGUpe3JldHVybiBqdChlWzBdLmV2YWx1YXRlKHQpLHQucHJvcGVydGllcygpKX1dLFtbRCxLXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiBqdChyLmV2YWx1YXRlKHQpLG4uZXZhbHVhdGUodCkpfV1dfSxwcm9wZXJ0aWVzOltLLFtdLGZ1bmN0aW9uKHQpe3JldHVybiB0LnByb3BlcnRpZXMoKX1dLFwiZ2VvbWV0cnktdHlwZVwiOltELFtdLGZ1bmN0aW9uKHQpe3JldHVybiB0Lmdlb21ldHJ5VHlwZSgpfV0saWQ6W0osW10sZnVuY3Rpb24odCl7cmV0dXJuIHQuaWQoKX1dLHpvb206W1UsW10sZnVuY3Rpb24odCl7cmV0dXJuIHQuZ2xvYmFscy56b29tfV0sXCJoZWF0bWFwLWRlbnNpdHlcIjpbVSxbXSxmdW5jdGlvbih0KXtyZXR1cm4gdC5nbG9iYWxzLmhlYXRtYXBEZW5zaXR5fHwwfV0sXCJsaW5lLXByb2dyZXNzXCI6W1UsW10sZnVuY3Rpb24odCl7cmV0dXJuIHQuZ2xvYmFscy5saW5lUHJvZ3Jlc3N8fDB9XSxcIitcIjpbVSxOdChVKSxmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49MCxpPWU7bjxpLmxlbmd0aDtuKz0xKXtyKz1pW25dLmV2YWx1YXRlKHQpO31yZXR1cm4gcn1dLFwiKlwiOltVLE50KFUpLGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTEsbj0wLGk9ZTtuPGkubGVuZ3RoO24rPTEpe3IqPWlbbl0uZXZhbHVhdGUodCk7fXJldHVybiByfV0sXCItXCI6e3R5cGU6VSxvdmVybG9hZHM6W1tbVSxVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiByLmV2YWx1YXRlKHQpLW4uZXZhbHVhdGUodCl9XSxbW1VdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuLWVbMF0uZXZhbHVhdGUodCl9XV19LFwiL1wiOltVLFtVLFVdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCkvbi5ldmFsdWF0ZSh0KX1dLFwiJVwiOltVLFtVLFVdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCklbi5ldmFsdWF0ZSh0KX1dLGxuMjpbVSxbXSxmdW5jdGlvbigpe3JldHVybiBNYXRoLkxOMn1dLHBpOltVLFtdLGZ1bmN0aW9uKCl7cmV0dXJuIE1hdGguUEl9XSxlOltVLFtdLGZ1bmN0aW9uKCl7cmV0dXJuIE1hdGguRX1dLFwiXlwiOltVLFtVLFVdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIE1hdGgucG93KHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSl9XSxzcXJ0OltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguc3FydChyLmV2YWx1YXRlKHQpKX1dLGxvZzEwOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGgubG9nMTAoci5ldmFsdWF0ZSh0KSl9XSxsbjpbVSxbVV0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmxvZyhyLmV2YWx1YXRlKHQpKX1dLGxvZzI6W1UsW1VdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gTWF0aC5sb2cyKHIuZXZhbHVhdGUodCkpfV0sc2luOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguc2luKHIuZXZhbHVhdGUodCkpfV0sY29zOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguY29zKHIuZXZhbHVhdGUodCkpfV0sdGFuOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGgudGFuKHIuZXZhbHVhdGUodCkpfV0sYXNpbjpbVSxbVV0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmFzaW4oci5ldmFsdWF0ZSh0KSl9XSxhY29zOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguYWNvcyhyLmV2YWx1YXRlKHQpKX1dLGF0YW46W1UsW1VdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gTWF0aC5hdGFuKHIuZXZhbHVhdGUodCkpfV0sbWluOltVLE50KFUpLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIE1hdGgubWluLmFwcGx5KE1hdGgsZS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGUuZXZhbHVhdGUodCl9KSl9XSxtYXg6W1UsTnQoVSksZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5tYXguYXBwbHkoTWF0aCxlLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gZS5ldmFsdWF0ZSh0KX0pKX1dLGFiczpbVSxbVV0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmFicyhyLmV2YWx1YXRlKHQpKX1dLHJvdW5kOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0uZXZhbHVhdGUodCk7cmV0dXJuIHI8MD8tTWF0aC5yb3VuZCgtcik6TWF0aC5yb3VuZChyKX1dLGZsb29yOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguZmxvb3Ioci5ldmFsdWF0ZSh0KSl9XSxjZWlsOltVLFtVXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguY2VpbChyLmV2YWx1YXRlKHQpKX1dLFwiZmlsdGVyLT09XCI6W04sW0QsSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gdC5wcm9wZXJ0aWVzKClbci52YWx1ZV09PT1uLnZhbHVlfV0sXCJmaWx0ZXItaWQtPT1cIjpbTixbSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiB0LmlkKCk9PT1yLnZhbHVlfV0sXCJmaWx0ZXItdHlwZS09PVwiOltOLFtEXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIHQuZ2VvbWV0cnlUeXBlKCk9PT1yLnZhbHVlfV0sXCJmaWx0ZXItPFwiOltOLFtELEpdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV0saT10LnByb3BlcnRpZXMoKVtyLnZhbHVlXSxvPW4udmFsdWU7cmV0dXJuIHR5cGVvZiBpPT10eXBlb2YgbyYmaTxvfV0sXCJmaWx0ZXItaWQtPFwiOltOLFtKXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj10LmlkKCksaT1yLnZhbHVlO3JldHVybiB0eXBlb2Ygbj09dHlwZW9mIGkmJm48aX1dLFwiZmlsdGVyLT5cIjpbTixbRCxKXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdLGk9dC5wcm9wZXJ0aWVzKClbci52YWx1ZV0sbz1uLnZhbHVlO3JldHVybiB0eXBlb2YgaT09dHlwZW9mIG8mJmk+b31dLFwiZmlsdGVyLWlkLT5cIjpbTixbSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49dC5pZCgpLGk9ci52YWx1ZTtyZXR1cm4gdHlwZW9mIG49PXR5cGVvZiBpJiZuPml9XSxcImZpbHRlci08PVwiOltOLFtELEpdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV0saT10LnByb3BlcnRpZXMoKVtyLnZhbHVlXSxvPW4udmFsdWU7cmV0dXJuIHR5cGVvZiBpPT10eXBlb2YgbyYmaTw9b31dLFwiZmlsdGVyLWlkLTw9XCI6W04sW0pdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPXQuaWQoKSxpPXIudmFsdWU7cmV0dXJuIHR5cGVvZiBuPT10eXBlb2YgaSYmbjw9aX1dLFwiZmlsdGVyLT49XCI6W04sW0QsSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXSxpPXQucHJvcGVydGllcygpW3IudmFsdWVdLG89bi52YWx1ZTtyZXR1cm4gdHlwZW9mIGk9PXR5cGVvZiBvJiZpPj1vfV0sXCJmaWx0ZXItaWQtPj1cIjpbTixbSl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49dC5pZCgpLGk9ci52YWx1ZTtyZXR1cm4gdHlwZW9mIG49PXR5cGVvZiBpJiZuPj1pfV0sXCJmaWx0ZXItaGFzXCI6W04sW0pdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGVbMF0udmFsdWUgaW4gdC5wcm9wZXJ0aWVzKCl9XSxcImZpbHRlci1oYXMtaWRcIjpbTixbXSxmdW5jdGlvbih0KXtyZXR1cm4gbnVsbCE9PXQuaWQoKX1dLFwiZmlsdGVyLXR5cGUtaW5cIjpbTixbSChEKV0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS52YWx1ZS5pbmRleE9mKHQuZ2VvbWV0cnlUeXBlKCkpPj0wfV0sXCJmaWx0ZXItaWQtaW5cIjpbTixbSChKKV0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS52YWx1ZS5pbmRleE9mKHQuaWQoKSk+PTB9XSxcImZpbHRlci1pbi1zbWFsbFwiOltOLFtELEgoSildLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gZVsxXS52YWx1ZS5pbmRleE9mKHQucHJvcGVydGllcygpW3IudmFsdWVdKT49MH1dLFwiZmlsdGVyLWluLWxhcmdlXCI6W04sW0QsSChKKV0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gZnVuY3Rpb24odCxlLHIsbil7Zm9yKDtyPD1uOyl7dmFyIGk9cituPj4xO2lmKGVbaV09PT10KXJldHVybiEwO2VbaV0+dD9uPWktMTpyPWkrMTt9cmV0dXJuITF9KHQucHJvcGVydGllcygpW3IudmFsdWVdLG4udmFsdWUsMCxuLnZhbHVlLmxlbmd0aC0xKX1dLFwiPlwiOnt0eXBlOk4sb3ZlcmxvYWRzOltbW1UsVV0sUnRdLFtbRCxEXSxSdF0sW1tELEQsJF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gZVsyXS5ldmFsdWF0ZSh0KS5jb21wYXJlKHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSk+MH1dXX0sXCI8XCI6e3R5cGU6TixvdmVybG9hZHM6W1tbVSxVXSxxdF0sW1tELERdLHF0XSxbW0QsRCwkXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiBlWzJdLmV2YWx1YXRlKHQpLmNvbXBhcmUoci5ldmFsdWF0ZSh0KSxuLmV2YWx1YXRlKHQpKTwwfV1dfSxcIj49XCI6e3R5cGU6TixvdmVybG9hZHM6W1tbVSxVXSxEdF0sW1tELERdLER0XSxbW0QsRCwkXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiBlWzJdLmV2YWx1YXRlKHQpLmNvbXBhcmUoci5ldmFsdWF0ZSh0KSxuLmV2YWx1YXRlKHQpKT49MH1dXX0sXCI8PVwiOnt0eXBlOk4sb3ZlcmxvYWRzOltbW1UsVV0sVXRdLFtbRCxEXSxVdF0sW1tELEQsJF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gZVsyXS5ldmFsdWF0ZSh0KS5jb21wYXJlKHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSk8PTB9XV19LGFsbDp7dHlwZTpOLG92ZXJsb2FkczpbW1tOLE5dLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCkmJm4uZXZhbHVhdGUodCl9XSxbTnQoTiksZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPWU7cjxuLmxlbmd0aDtyKz0xKXtpZighbltyXS5ldmFsdWF0ZSh0KSlyZXR1cm4hMX1yZXR1cm4hMH1dXX0sYW55Ont0eXBlOk4sb3ZlcmxvYWRzOltbW04sTl0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gci5ldmFsdWF0ZSh0KXx8bi5ldmFsdWF0ZSh0KX1dLFtOdChOKSxmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49ZTtyPG4ubGVuZ3RoO3IrPTEpe2lmKG5bcl0uZXZhbHVhdGUodCkpcmV0dXJuITB9cmV0dXJuITF9XV19LFwiIVwiOltOLFtOXSxmdW5jdGlvbih0LGUpe3JldHVybiFlWzBdLmV2YWx1YXRlKHQpfV0sXCJpcy1zdXBwb3J0ZWQtc2NyaXB0XCI6W04sW0RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPXQuZ2xvYmFscyYmdC5nbG9iYWxzLmlzU3VwcG9ydGVkU2NyaXB0O3JldHVybiFufHxuKHIuZXZhbHVhdGUodCkpfV0sdXBjYXNlOltELFtEXSxmdW5jdGlvbih0LGUpe3JldHVybiBlWzBdLmV2YWx1YXRlKHQpLnRvVXBwZXJDYXNlKCl9XSxkb3duY2FzZTpbRCxbRF0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS5ldmFsdWF0ZSh0KS50b0xvd2VyQ2FzZSgpfV0sY29uY2F0OltELE50KEQpLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGUubWFwKGZ1bmN0aW9uKGUpe3JldHVybiBlLmV2YWx1YXRlKHQpfSkuam9pbihcIlwiKX1dLFwicmVzb2x2ZWQtbG9jYWxlXCI6W0QsWyRdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGVbMF0uZXZhbHVhdGUodCkucmVzb2x2ZWRMb2NhbGUoKX1dfSk7dmFyIEp0PS45NTA0NywkdD0xLEh0PTEuMDg4ODMsWHQ9NC8yOSxHdD02LzI5LFl0PTMqR3QqR3QsV3Q9R3QqR3QqR3QsUXQ9TWF0aC5QSS8xODAsdGU9MTgwL01hdGguUEk7ZnVuY3Rpb24gZWUodCl7cmV0dXJuIHQ+V3Q/TWF0aC5wb3codCwxLzMpOnQvWXQrWHR9ZnVuY3Rpb24gcmUodCl7cmV0dXJuIHQ+R3Q/dCp0KnQ6WXQqKHQtWHQpfWZ1bmN0aW9uIG5lKHQpe3JldHVybiAyNTUqKHQ8PS4wMDMxMzA4PzEyLjkyKnQ6MS4wNTUqTWF0aC5wb3codCwxLzIuNCktLjA1NSl9ZnVuY3Rpb24gaWUodCl7cmV0dXJuKHQvPTI1NSk8PS4wNDA0NT90LzEyLjkyOk1hdGgucG93KCh0Ky4wNTUpLzEuMDU1LDIuNCl9ZnVuY3Rpb24gb2UodCl7dmFyIGU9aWUodC5yKSxyPWllKHQuZyksbj1pZSh0LmIpLGk9ZWUoKC40MTI0NTY0KmUrLjM1NzU3NjEqcisuMTgwNDM3NSpuKS9KdCksbz1lZSgoLjIxMjY3MjkqZSsuNzE1MTUyMipyKy4wNzIxNzUqbikvJHQpO3JldHVybntsOjExNipvLTE2LGE6NTAwKihpLW8pLGI6MjAwKihvLWVlKCguMDE5MzMzOSplKy4xMTkxOTIqcisuOTUwMzA0MSpuKS9IdCkpLGFscGhhOnQuYX19ZnVuY3Rpb24gYWUodCl7dmFyIGU9KHQubCsxNikvMTE2LHI9aXNOYU4odC5hKT9lOmUrdC5hLzUwMCxuPWlzTmFOKHQuYik/ZTplLXQuYi8yMDA7cmV0dXJuIGU9JHQqcmUoZSkscj1KdCpyZShyKSxuPUh0KnJlKG4pLG5ldyBRKG5lKDMuMjQwNDU0MipyLTEuNTM3MTM4NSplLS40OTg1MzE0Km4pLG5lKC0uOTY5MjY2KnIrMS44NzYwMTA4KmUrLjA0MTU1NipuKSxuZSguMDU1NjQzNCpyLS4yMDQwMjU5KmUrMS4wNTcyMjUyKm4pLHQuYWxwaGEpfXZhciBzZT17Zm9yd2FyZDpvZSxyZXZlcnNlOmFlLGludGVycG9sYXRlOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm57bDp3dCh0LmwsZS5sLHIpLGE6d3QodC5hLGUuYSxyKSxiOnd0KHQuYixlLmIsciksYWxwaGE6d3QodC5hbHBoYSxlLmFscGhhLHIpfX19LHVlPXtmb3J3YXJkOmZ1bmN0aW9uKHQpe3ZhciBlPW9lKHQpLHI9ZS5sLG49ZS5hLGk9ZS5iLG89TWF0aC5hdGFuMihpLG4pKnRlO3JldHVybntoOm88MD9vKzM2MDpvLGM6TWF0aC5zcXJ0KG4qbitpKmkpLGw6cixhbHBoYTp0LmF9fSxyZXZlcnNlOmZ1bmN0aW9uKHQpe3ZhciBlPXQuaCpRdCxyPXQuYztyZXR1cm4gYWUoe2w6dC5sLGE6TWF0aC5jb3MoZSkqcixiOk1hdGguc2luKGUpKnIsYWxwaGE6dC5hbHBoYX0pfSxpbnRlcnBvbGF0ZTpmdW5jdGlvbih0LGUscil7cmV0dXJue2g6ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWUtdDtyZXR1cm4gdCtyKihuPjE4MHx8bjwtMTgwP24tMzYwKk1hdGgucm91bmQobi8zNjApOm4pfSh0LmgsZS5oLHIpLGM6d3QodC5jLGUuYyxyKSxsOnd0KHQubCxlLmwsciksYWxwaGE6d3QodC5hbHBoYSxlLmFscGhhLHIpfX19LGxlPU9iamVjdC5mcmVlemUoe2xhYjpzZSxoY2w6dWV9KTtmdW5jdGlvbiBwZSh0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIE51bWJlcj9cIm51bWJlclwiOnQgaW5zdGFuY2VvZiBTdHJpbmc/XCJzdHJpbmdcIjp0IGluc3RhbmNlb2YgQm9vbGVhbj9cImJvb2xlYW5cIjpBcnJheS5pc0FycmF5KHQpP1wiYXJyYXlcIjpudWxsPT09dD9cIm51bGxcIjp0eXBlb2YgdH1mdW5jdGlvbiBjZSh0KXtyZXR1cm5cIm9iamVjdFwiPT10eXBlb2YgdCYmbnVsbCE9PXQmJiFBcnJheS5pc0FycmF5KHQpfWZ1bmN0aW9uIGhlKHQpe3JldHVybiB0fWZ1bmN0aW9uIGZlKHQsZSxyKXtyZXR1cm4gdm9pZCAwIT09dD90OnZvaWQgMCE9PWU/ZTp2b2lkIDAhPT1yP3I6dm9pZCAwfWZ1bmN0aW9uIHllKHQsZSxyLG4saSl7cmV0dXJuIGZlKHR5cGVvZiByPT09aT9uW3JdOnZvaWQgMCx0LmRlZmF1bHQsZS5kZWZhdWx0KX1mdW5jdGlvbiBkZSh0LGUscil7aWYoXCJudW1iZXJcIiE9PXBlKHIpKXJldHVybiBmZSh0LmRlZmF1bHQsZS5kZWZhdWx0KTt2YXIgbj10LnN0b3BzLmxlbmd0aDtpZigxPT09bilyZXR1cm4gdC5zdG9wc1swXVsxXTtpZihyPD10LnN0b3BzWzBdWzBdKXJldHVybiB0LnN0b3BzWzBdWzFdO2lmKHI+PXQuc3RvcHNbbi0xXVswXSlyZXR1cm4gdC5zdG9wc1tuLTFdWzFdO3ZhciBpPWdlKHQuc3RvcHMscik7cmV0dXJuIHQuc3RvcHNbaV1bMV19ZnVuY3Rpb24gdmUodCxlLHIpe3ZhciBuPXZvaWQgMCE9PXQuYmFzZT90LmJhc2U6MTtpZihcIm51bWJlclwiIT09cGUocikpcmV0dXJuIGZlKHQuZGVmYXVsdCxlLmRlZmF1bHQpO3ZhciBpPXQuc3RvcHMubGVuZ3RoO2lmKDE9PT1pKXJldHVybiB0LnN0b3BzWzBdWzFdO2lmKHI8PXQuc3RvcHNbMF1bMF0pcmV0dXJuIHQuc3RvcHNbMF1bMV07aWYocj49dC5zdG9wc1tpLTFdWzBdKXJldHVybiB0LnN0b3BzW2ktMV1bMV07dmFyIG89Z2UodC5zdG9wcyxyKSxhPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPW4tcixvPXQtcjtyZXR1cm4gMD09PWk/MDoxPT09ZT9vL2k6KE1hdGgucG93KGUsbyktMSkvKE1hdGgucG93KGUsaSktMSl9KHIsbix0LnN0b3BzW29dWzBdLHQuc3RvcHNbbysxXVswXSkscz10LnN0b3BzW29dWzFdLHU9dC5zdG9wc1tvKzFdWzFdLGw9X3RbZS50eXBlXXx8aGU7aWYodC5jb2xvclNwYWNlJiZcInJnYlwiIT09dC5jb2xvclNwYWNlKXt2YXIgcD1sZVt0LmNvbG9yU3BhY2VdO2w9ZnVuY3Rpb24odCxlKXtyZXR1cm4gcC5yZXZlcnNlKHAuaW50ZXJwb2xhdGUocC5mb3J3YXJkKHQpLHAuZm9yd2FyZChlKSxhKSl9O31yZXR1cm5cImZ1bmN0aW9uXCI9PXR5cGVvZiBzLmV2YWx1YXRlP3tldmFsdWF0ZTpmdW5jdGlvbigpe2Zvcih2YXIgdD1bXSxlPWFyZ3VtZW50cy5sZW5ndGg7ZS0tOyl0W2VdPWFyZ3VtZW50c1tlXTt2YXIgcj1zLmV2YWx1YXRlLmFwcGx5KHZvaWQgMCx0KSxuPXUuZXZhbHVhdGUuYXBwbHkodm9pZCAwLHQpO2lmKHZvaWQgMCE9PXImJnZvaWQgMCE9PW4pcmV0dXJuIGwocixuLGEpfX06bChzLHUsYSl9ZnVuY3Rpb24gbWUodCxlLHIpe3JldHVyblwiY29sb3JcIj09PWUudHlwZT9yPVEucGFyc2Uocik6cGUocik9PT1lLnR5cGV8fFwiZW51bVwiPT09ZS50eXBlJiZlLnZhbHVlc1tyXXx8KHI9dm9pZCAwKSxmZShyLHQuZGVmYXVsdCxlLmRlZmF1bHQpfWZ1bmN0aW9uIGdlKHQsZSl7Zm9yKHZhciByLG4saT0wLG89dC5sZW5ndGgtMSxhPTA7aTw9bzspe2lmKHI9dFthPU1hdGguZmxvb3IoKGkrbykvMildWzBdLG49dFthKzFdWzBdLGU9PT1yfHxlPnImJmU8bilyZXR1cm4gYTtyPGU/aT1hKzE6cj5lJiYobz1hLTEpO31yZXR1cm4gTWF0aC5tYXgoYS0xLDApfXZhciB4ZT1mdW5jdGlvbih0LGUpe3ZhciByO3RoaXMuZXhwcmVzc2lvbj10LHRoaXMuX3dhcm5pbmdIaXN0b3J5PXt9LHRoaXMuX2RlZmF1bHRWYWx1ZT1cImNvbG9yXCI9PT0ocj1lKS50eXBlJiZjZShyLmRlZmF1bHQpP25ldyBRKDAsMCwwLDApOlwiY29sb3JcIj09PXIudHlwZT9RLnBhcnNlKHIuZGVmYXVsdCl8fG51bGw6dm9pZCAwPT09ci5kZWZhdWx0P251bGw6ci5kZWZhdWx0LFwiZW51bVwiPT09ZS50eXBlJiYodGhpcy5fZW51bVZhbHVlcz1lLnZhbHVlcyk7fTtmdW5jdGlvbiBiZSh0KXtyZXR1cm4gQXJyYXkuaXNBcnJheSh0KSYmdC5sZW5ndGg+MCYmXCJzdHJpbmdcIj09dHlwZW9mIHRbMF0mJnRbMF1pbiBUdH1mdW5jdGlvbiB3ZSh0LGUpe3ZhciByPW5ldyBndChUdCxbXSxmdW5jdGlvbih0KXt2YXIgZT17Y29sb3I6WixzdHJpbmc6RCxudW1iZXI6VSxlbnVtOkQsYm9vbGVhbjpOfTtpZihcImFycmF5XCI9PT10LnR5cGUpcmV0dXJuIEgoZVt0LnZhbHVlXXx8Six0Lmxlbmd0aCk7cmV0dXJuIGVbdC50eXBlXXx8bnVsbH0oZSkpLG49ci5wYXJzZSh0KTtyZXR1cm4gbj9adChuZXcgeGUobixlKSk6S3Qoci5lcnJvcnMpfXhlLnByb3RvdHlwZS5ldmFsdWF0ZVdpdGhvdXRFcnJvckhhbmRsaW5nPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuX2V2YWx1YXRvcnx8KHRoaXMuX2V2YWx1YXRvcj1uZXcgZnQpLHRoaXMuX2V2YWx1YXRvci5nbG9iYWxzPXQsdGhpcy5fZXZhbHVhdG9yLmZlYXR1cmU9ZSx0aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUodGhpcy5fZXZhbHVhdG9yKX0seGUucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQsZSl7dGhpcy5fZXZhbHVhdG9yfHwodGhpcy5fZXZhbHVhdG9yPW5ldyBmdCksdGhpcy5fZXZhbHVhdG9yLmdsb2JhbHM9dCx0aGlzLl9ldmFsdWF0b3IuZmVhdHVyZT1lO3RyeXt2YXIgcj10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUodGhpcy5fZXZhbHVhdG9yKTtpZihudWxsPT1yKXJldHVybiB0aGlzLl9kZWZhdWx0VmFsdWU7aWYodGhpcy5fZW51bVZhbHVlcyYmIShyIGluIHRoaXMuX2VudW1WYWx1ZXMpKXRocm93IG5ldyBvdChcIkV4cGVjdGVkIHZhbHVlIHRvIGJlIG9uZSBvZiBcIitPYmplY3Qua2V5cyh0aGlzLl9lbnVtVmFsdWVzKS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIEpTT04uc3RyaW5naWZ5KHQpfSkuam9pbihcIiwgXCIpK1wiLCBidXQgZm91bmQgXCIrSlNPTi5zdHJpbmdpZnkocikrXCIgaW5zdGVhZC5cIik7cmV0dXJuIHJ9Y2F0Y2godCl7cmV0dXJuIHRoaXMuX3dhcm5pbmdIaXN0b3J5W3QubWVzc2FnZV18fCh0aGlzLl93YXJuaW5nSGlzdG9yeVt0Lm1lc3NhZ2VdPSEwLFwidW5kZWZpbmVkXCIhPXR5cGVvZiBjb25zb2xlJiZjb25zb2xlLndhcm4odC5tZXNzYWdlKSksdGhpcy5fZGVmYXVsdFZhbHVlfX07dmFyIF9lPWZ1bmN0aW9uKHQsZSl7dGhpcy5raW5kPXQsdGhpcy5fc3R5bGVFeHByZXNzaW9uPWU7fTtfZS5wcm90b3R5cGUuZXZhbHVhdGVXaXRob3V0RXJyb3JIYW5kbGluZz1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9zdHlsZUV4cHJlc3Npb24uZXZhbHVhdGVXaXRob3V0RXJyb3JIYW5kbGluZyh0LGUpfSxfZS5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5fc3R5bGVFeHByZXNzaW9uLmV2YWx1YXRlKHQsZSl9O3ZhciBBZT1mdW5jdGlvbih0LGUscil7dGhpcy5raW5kPXQsdGhpcy56b29tU3RvcHM9ci5sYWJlbHMsdGhpcy5fc3R5bGVFeHByZXNzaW9uPWUsciBpbnN0YW5jZW9mIEF0JiYodGhpcy5faW50ZXJwb2xhdGlvblR5cGU9ci5pbnRlcnBvbGF0aW9uKTt9O2Z1bmN0aW9uIGtlKHQsZSl7aWYoXCJlcnJvclwiPT09KHQ9d2UodCxlKSkucmVzdWx0KXJldHVybiB0O3ZhciByPXQudmFsdWUuZXhwcmVzc2lvbixuPWR0KHIpO2lmKCFuJiYhZVtcInByb3BlcnR5LWZ1bmN0aW9uXCJdKXJldHVybiBLdChbbmV3IGooXCJcIixcInByb3BlcnR5IGV4cHJlc3Npb25zIG5vdCBzdXBwb3J0ZWRcIildKTt2YXIgaT12dChyLFtcInpvb21cIl0pO2lmKCFpJiYhMT09PWVbXCJ6b29tLWZ1bmN0aW9uXCJdKXJldHVybiBLdChbbmV3IGooXCJcIixcInpvb20gZXhwcmVzc2lvbnMgbm90IHN1cHBvcnRlZFwiKV0pO3ZhciBvPWZ1bmN0aW9uIHQoZSl7dmFyIHI9bnVsbDtpZihlIGluc3RhbmNlb2YgU3Qpcj10KGUucmVzdWx0KTtlbHNlIGlmKGUgaW5zdGFuY2VvZiB6dClmb3IodmFyIG49MCxpPWUuYXJncztuPGkubGVuZ3RoO24rPTEpe3ZhciBvPWlbbl07aWYocj10KG8pKWJyZWFrfWVsc2UoZSBpbnN0YW5jZW9mIGJ0fHxlIGluc3RhbmNlb2YgQXQpJiZlLmlucHV0IGluc3RhbmNlb2YgeXQmJlwiem9vbVwiPT09ZS5pbnB1dC5uYW1lJiYocj1lKTtpZihyIGluc3RhbmNlb2YgailyZXR1cm4gcjtlLmVhY2hDaGlsZChmdW5jdGlvbihlKXt2YXIgbj10KGUpO24gaW5zdGFuY2VvZiBqP3I9bjohciYmbj9yPW5ldyBqKFwiXCIsJ1wiem9vbVwiIGV4cHJlc3Npb24gbWF5IG9ubHkgYmUgdXNlZCBhcyBpbnB1dCB0byBhIHRvcC1sZXZlbCBcInN0ZXBcIiBvciBcImludGVycG9sYXRlXCIgZXhwcmVzc2lvbi4nKTpyJiZuJiZyIT09biYmKHI9bmV3IGooXCJcIiwnT25seSBvbmUgem9vbS1iYXNlZCBcInN0ZXBcIiBvciBcImludGVycG9sYXRlXCIgc3ViZXhwcmVzc2lvbiBtYXkgYmUgdXNlZCBpbiBhbiBleHByZXNzaW9uLicpKTt9KTtyZXR1cm4gcn0ocik7cmV0dXJuIG98fGk/byBpbnN0YW5jZW9mIGo/S3QoW29dKTpvIGluc3RhbmNlb2YgQXQmJlwicGllY2V3aXNlLWNvbnN0YW50XCI9PT1lLmZ1bmN0aW9uP0t0KFtuZXcgaihcIlwiLCdcImludGVycG9sYXRlXCIgZXhwcmVzc2lvbnMgY2Fubm90IGJlIHVzZWQgd2l0aCB0aGlzIHByb3BlcnR5JyldKTpadChvP25ldyBBZShuP1wiY2FtZXJhXCI6XCJjb21wb3NpdGVcIix0LnZhbHVlLG8pOm5ldyBfZShuP1wiY29uc3RhbnRcIjpcInNvdXJjZVwiLHQudmFsdWUpKTpLdChbbmV3IGooXCJcIiwnXCJ6b29tXCIgZXhwcmVzc2lvbiBtYXkgb25seSBiZSB1c2VkIGFzIGlucHV0IHRvIGEgdG9wLWxldmVsIFwic3RlcFwiIG9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9uLicpXSl9QWUucHJvdG90eXBlLmV2YWx1YXRlV2l0aG91dEVycm9ySGFuZGxpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5fc3R5bGVFeHByZXNzaW9uLmV2YWx1YXRlV2l0aG91dEVycm9ySGFuZGxpbmcodCxlKX0sQWUucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuX3N0eWxlRXhwcmVzc2lvbi5ldmFsdWF0ZSh0LGUpfSxBZS5wcm90b3R5cGUuaW50ZXJwb2xhdGlvbkZhY3Rvcj1mdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuX2ludGVycG9sYXRpb25UeXBlP0F0LmludGVycG9sYXRpb25GYWN0b3IodGhpcy5faW50ZXJwb2xhdGlvblR5cGUsdCxlLHIpOjB9O3ZhciB6ZT1mdW5jdGlvbih0LGUpe3RoaXMuX3BhcmFtZXRlcnM9dCx0aGlzLl9zcGVjaWZpY2F0aW9uPWUsVCh0aGlzLGZ1bmN0aW9uIHQoZSxyKXt2YXIgbixpLG8sYT1cImNvbG9yXCI9PT1yLnR5cGUscz1lLnN0b3BzJiZcIm9iamVjdFwiPT10eXBlb2YgZS5zdG9wc1swXVswXSx1PXN8fHZvaWQgMCE9PWUucHJvcGVydHksbD1zfHwhdSxwPWUudHlwZXx8KFwiaW50ZXJwb2xhdGVkXCI9PT1yLmZ1bmN0aW9uP1wiZXhwb25lbnRpYWxcIjpcImludGVydmFsXCIpO2lmKGEmJigoZT1UKHt9LGUpKS5zdG9wcyYmKGUuc3RvcHM9ZS5zdG9wcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuW3RbMF0sUS5wYXJzZSh0WzFdKV19KSksZS5kZWZhdWx0P2UuZGVmYXVsdD1RLnBhcnNlKGUuZGVmYXVsdCk6ZS5kZWZhdWx0PVEucGFyc2Uoci5kZWZhdWx0KSksZS5jb2xvclNwYWNlJiZcInJnYlwiIT09ZS5jb2xvclNwYWNlJiYhbGVbZS5jb2xvclNwYWNlXSl0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIGNvbG9yIHNwYWNlOiBcIitlLmNvbG9yU3BhY2UpO2lmKFwiZXhwb25lbnRpYWxcIj09PXApbj12ZTtlbHNlIGlmKFwiaW50ZXJ2YWxcIj09PXApbj1kZTtlbHNlIGlmKFwiY2F0ZWdvcmljYWxcIj09PXApe249eWUsaT1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcih2YXIgYz0wLGg9ZS5zdG9wcztjPGgubGVuZ3RoO2MrPTEpe3ZhciBmPWhbY107aVtmWzBdXT1mWzFdO31vPXR5cGVvZiBlLnN0b3BzWzBdWzBdO31lbHNle2lmKFwiaWRlbnRpdHlcIiE9PXApdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGZ1bmN0aW9uIHR5cGUgXCInK3ArJ1wiJyk7bj1tZTt9aWYocyl7Zm9yKHZhciB5PXt9LGQ9W10sdj0wO3Y8ZS5zdG9wcy5sZW5ndGg7disrKXt2YXIgbT1lLnN0b3BzW3ZdLGc9bVswXS56b29tO3ZvaWQgMD09PXlbZ10mJih5W2ddPXt6b29tOmcsdHlwZTplLnR5cGUscHJvcGVydHk6ZS5wcm9wZXJ0eSxkZWZhdWx0OmUuZGVmYXVsdCxzdG9wczpbXX0sZC5wdXNoKGcpKSx5W2ddLnN0b3BzLnB1c2goW21bMF0udmFsdWUsbVsxXV0pO31mb3IodmFyIHg9W10sYj0wLHc9ZDtiPHcubGVuZ3RoO2IrPTEpe3ZhciBfPXdbYl07eC5wdXNoKFt5W19dLnpvb20sdCh5W19dLHIpXSk7fXJldHVybntraW5kOlwiY29tcG9zaXRlXCIsaW50ZXJwb2xhdGlvbkZhY3RvcjpBdC5pbnRlcnBvbGF0aW9uRmFjdG9yLmJpbmQodm9pZCAwLHtuYW1lOlwibGluZWFyXCJ9KSx6b29tU3RvcHM6eC5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHRbMF19KSxldmFsdWF0ZTpmdW5jdGlvbih0LG4pe3ZhciBpPXQuem9vbTtyZXR1cm4gdmUoe3N0b3BzOngsYmFzZTplLmJhc2V9LHIsaSkuZXZhbHVhdGUoaSxuKX19fXJldHVybiBsP3traW5kOlwiY2FtZXJhXCIsaW50ZXJwb2xhdGlvbkZhY3RvcjpcImV4cG9uZW50aWFsXCI9PT1wP0F0LmludGVycG9sYXRpb25GYWN0b3IuYmluZCh2b2lkIDAse25hbWU6XCJleHBvbmVudGlhbFwiLGJhc2U6dm9pZCAwIT09ZS5iYXNlP2UuYmFzZToxfSk6ZnVuY3Rpb24oKXtyZXR1cm4gMH0sem9vbVN0b3BzOmUuc3RvcHMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0WzBdfSksZXZhbHVhdGU6ZnVuY3Rpb24odCl7dmFyIGE9dC56b29tO3JldHVybiBuKGUscixhLGksbyl9fTp7a2luZDpcInNvdXJjZVwiLGV2YWx1YXRlOmZ1bmN0aW9uKHQsYSl7dmFyIHM9YSYmYS5wcm9wZXJ0aWVzP2EucHJvcGVydGllc1tlLnByb3BlcnR5XTp2b2lkIDA7cmV0dXJuIHZvaWQgMD09PXM/ZmUoZS5kZWZhdWx0LHIuZGVmYXVsdCk6bihlLHIscyxpLG8pfX19KHRoaXMuX3BhcmFtZXRlcnMsdGhpcy5fc3BlY2lmaWNhdGlvbikpO307ZnVuY3Rpb24gU2UodCxlKXtpZihjZSh0KSlyZXR1cm4gbmV3IHplKHQsZSk7aWYoYmUodCkpe3ZhciByPWtlKHQsZSk7aWYoXCJlcnJvclwiPT09ci5yZXN1bHQpdGhyb3cgbmV3IEVycm9yKHIudmFsdWUubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmtleStcIjogXCIrdC5tZXNzYWdlfSkuam9pbihcIiwgXCIpKTtyZXR1cm4gci52YWx1ZX12YXIgbj10O3JldHVyblwic3RyaW5nXCI9PXR5cGVvZiB0JiZcImNvbG9yXCI9PT1lLnR5cGUmJihuPVEucGFyc2UodCkpLHtraW5kOlwiY29uc3RhbnRcIixldmFsdWF0ZTpmdW5jdGlvbigpe3JldHVybiBufX19ZnVuY3Rpb24gTWUodCl7dmFyIGU9dC5rZXkscj10LnZhbHVlLG49dC52YWx1ZVNwZWN8fHt9LGk9dC5vYmplY3RFbGVtZW50VmFsaWRhdG9yc3x8e30sbz10LnN0eWxlLGE9dC5zdHlsZVNwZWMscz1bXSx1PXBlKHIpO2lmKFwib2JqZWN0XCIhPT11KXJldHVybltuZXcgRihlLHIsXCJvYmplY3QgZXhwZWN0ZWQsIFwiK3UrXCIgZm91bmRcIildO2Zvcih2YXIgbCBpbiByKXt2YXIgcD1sLnNwbGl0KFwiLlwiKVswXSxjPW5bcF18fG5bXCIqXCJdLGg9dm9pZCAwO2lmKGlbcF0paD1pW3BdO2Vsc2UgaWYobltwXSloPVllO2Vsc2UgaWYoaVtcIipcIl0paD1pW1wiKlwiXTtlbHNle2lmKCFuW1wiKlwiXSl7cy5wdXNoKG5ldyBGKGUscltsXSwndW5rbm93biBwcm9wZXJ0eSBcIicrbCsnXCInKSk7Y29udGludWV9aD1ZZTt9cz1zLmNvbmNhdChoKHtrZXk6KGU/ZStcIi5cIjplKStsLHZhbHVlOnJbbF0sdmFsdWVTcGVjOmMsc3R5bGU6byxzdHlsZVNwZWM6YSxvYmplY3Q6cixvYmplY3RLZXk6bH0scikpO31mb3IodmFyIGYgaW4gbilpW2ZdfHxuW2ZdLnJlcXVpcmVkJiZ2b2lkIDA9PT1uW2ZdLmRlZmF1bHQmJnZvaWQgMD09PXJbZl0mJnMucHVzaChuZXcgRihlLHIsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCInK2YrJ1wiJykpO3JldHVybiBzfWZ1bmN0aW9uIFZlKHQpe3ZhciBlPXQudmFsdWUscj10LnZhbHVlU3BlYyxuPXQuc3R5bGUsaT10LnN0eWxlU3BlYyxvPXQua2V5LGE9dC5hcnJheUVsZW1lbnRWYWxpZGF0b3J8fFllO2lmKFwiYXJyYXlcIiE9PXBlKGUpKXJldHVybltuZXcgRihvLGUsXCJhcnJheSBleHBlY3RlZCwgXCIrcGUoZSkrXCIgZm91bmRcIildO2lmKHIubGVuZ3RoJiZlLmxlbmd0aCE9PXIubGVuZ3RoKXJldHVybltuZXcgRihvLGUsXCJhcnJheSBsZW5ndGggXCIrci5sZW5ndGgrXCIgZXhwZWN0ZWQsIGxlbmd0aCBcIitlLmxlbmd0aCtcIiBmb3VuZFwiKV07aWYocltcIm1pbi1sZW5ndGhcIl0mJmUubGVuZ3RoPHJbXCJtaW4tbGVuZ3RoXCJdKXJldHVybltuZXcgRihvLGUsXCJhcnJheSBsZW5ndGggYXQgbGVhc3QgXCIrcltcIm1pbi1sZW5ndGhcIl0rXCIgZXhwZWN0ZWQsIGxlbmd0aCBcIitlLmxlbmd0aCtcIiBmb3VuZFwiKV07dmFyIHM9e3R5cGU6ci52YWx1ZX07aS4kdmVyc2lvbjw3JiYocy5mdW5jdGlvbj1yLmZ1bmN0aW9uKSxcIm9iamVjdFwiPT09cGUoci52YWx1ZSkmJihzPXIudmFsdWUpO2Zvcih2YXIgdT1bXSxsPTA7bDxlLmxlbmd0aDtsKyspdT11LmNvbmNhdChhKHthcnJheTplLGFycmF5SW5kZXg6bCx2YWx1ZTplW2xdLHZhbHVlU3BlYzpzLHN0eWxlOm4sc3R5bGVTcGVjOmksa2V5Om8rXCJbXCIrbCtcIl1cIn0pKTtyZXR1cm4gdX1mdW5jdGlvbiBCZSh0KXt2YXIgZT10LmtleSxyPXQudmFsdWUsbj10LnZhbHVlU3BlYyxpPXBlKHIpO3JldHVyblwibnVtYmVyXCIhPT1pP1tuZXcgRihlLHIsXCJudW1iZXIgZXhwZWN0ZWQsIFwiK2krXCIgZm91bmRcIildOlwibWluaW11bVwiaW4gbiYmcjxuLm1pbmltdW0/W25ldyBGKGUscixyK1wiIGlzIGxlc3MgdGhhbiB0aGUgbWluaW11bSB2YWx1ZSBcIituLm1pbmltdW0pXTpcIm1heGltdW1cImluIG4mJnI+bi5tYXhpbXVtP1tuZXcgRihlLHIscitcIiBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gdmFsdWUgXCIrbi5tYXhpbXVtKV06W119ZnVuY3Rpb24gQ2UodCl7dmFyIGUscixuLGk9dC52YWx1ZVNwZWMsbz1PKHQudmFsdWUudHlwZSksYT17fSxzPVwiY2F0ZWdvcmljYWxcIiE9PW8mJnZvaWQgMD09PXQudmFsdWUucHJvcGVydHksdT0hcyxsPVwiYXJyYXlcIj09PXBlKHQudmFsdWUuc3RvcHMpJiZcImFycmF5XCI9PT1wZSh0LnZhbHVlLnN0b3BzWzBdKSYmXCJvYmplY3RcIj09PXBlKHQudmFsdWUuc3RvcHNbMF1bMF0pLHA9TWUoe2tleTp0LmtleSx2YWx1ZTp0LnZhbHVlLHZhbHVlU3BlYzp0LnN0eWxlU3BlYy5mdW5jdGlvbixzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlYyxvYmplY3RFbGVtZW50VmFsaWRhdG9yczp7c3RvcHM6ZnVuY3Rpb24odCl7aWYoXCJpZGVudGl0eVwiPT09bylyZXR1cm5bbmV3IEYodC5rZXksdC52YWx1ZSwnaWRlbnRpdHkgZnVuY3Rpb24gbWF5IG5vdCBoYXZlIGEgXCJzdG9wc1wiIHByb3BlcnR5JyldO3ZhciBlPVtdLHI9dC52YWx1ZTtlPWUuY29uY2F0KFZlKHtrZXk6dC5rZXksdmFsdWU6cix2YWx1ZVNwZWM6dC52YWx1ZVNwZWMsc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWMsYXJyYXlFbGVtZW50VmFsaWRhdG9yOmN9KSksXCJhcnJheVwiPT09cGUocikmJjA9PT1yLmxlbmd0aCYmZS5wdXNoKG5ldyBGKHQua2V5LHIsXCJhcnJheSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHN0b3BcIikpO3JldHVybiBlfSxkZWZhdWx0OmZ1bmN0aW9uKHQpe3JldHVybiBZZSh7a2V5OnQua2V5LHZhbHVlOnQudmFsdWUsdmFsdWVTcGVjOmksc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWN9KX19fSk7cmV0dXJuXCJpZGVudGl0eVwiPT09byYmcyYmcC5wdXNoKG5ldyBGKHQua2V5LHQudmFsdWUsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCJwcm9wZXJ0eVwiJykpLFwiaWRlbnRpdHlcIj09PW98fHQudmFsdWUuc3RvcHN8fHAucHVzaChuZXcgRih0LmtleSx0LnZhbHVlLCdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwic3RvcHNcIicpKSxcImV4cG9uZW50aWFsXCI9PT1vJiZcInBpZWNld2lzZS1jb25zdGFudFwiPT09dC52YWx1ZVNwZWMuZnVuY3Rpb24mJnAucHVzaChuZXcgRih0LmtleSx0LnZhbHVlLFwiZXhwb25lbnRpYWwgZnVuY3Rpb25zIG5vdCBzdXBwb3J0ZWRcIikpLHQuc3R5bGVTcGVjLiR2ZXJzaW9uPj04JiYodSYmIXQudmFsdWVTcGVjW1wicHJvcGVydHktZnVuY3Rpb25cIl0/cC5wdXNoKG5ldyBGKHQua2V5LHQudmFsdWUsXCJwcm9wZXJ0eSBmdW5jdGlvbnMgbm90IHN1cHBvcnRlZFwiKSk6cyYmIXQudmFsdWVTcGVjW1wiem9vbS1mdW5jdGlvblwiXSYmXCJoZWF0bWFwLWNvbG9yXCIhPT10Lm9iamVjdEtleSYmXCJsaW5lLWdyYWRpZW50XCIhPT10Lm9iamVjdEtleSYmcC5wdXNoKG5ldyBGKHQua2V5LHQudmFsdWUsXCJ6b29tIGZ1bmN0aW9ucyBub3Qgc3VwcG9ydGVkXCIpKSksXCJjYXRlZ29yaWNhbFwiIT09byYmIWx8fHZvaWQgMCE9PXQudmFsdWUucHJvcGVydHl8fHAucHVzaChuZXcgRih0LmtleSx0LnZhbHVlLCdcInByb3BlcnR5XCIgcHJvcGVydHkgaXMgcmVxdWlyZWQnKSkscDtmdW5jdGlvbiBjKHQpe3ZhciBlPVtdLG89dC52YWx1ZSxzPXQua2V5O2lmKFwiYXJyYXlcIiE9PXBlKG8pKXJldHVybltuZXcgRihzLG8sXCJhcnJheSBleHBlY3RlZCwgXCIrcGUobykrXCIgZm91bmRcIildO2lmKDIhPT1vLmxlbmd0aClyZXR1cm5bbmV3IEYocyxvLFwiYXJyYXkgbGVuZ3RoIDIgZXhwZWN0ZWQsIGxlbmd0aCBcIitvLmxlbmd0aCtcIiBmb3VuZFwiKV07aWYobCl7aWYoXCJvYmplY3RcIiE9PXBlKG9bMF0pKXJldHVybltuZXcgRihzLG8sXCJvYmplY3QgZXhwZWN0ZWQsIFwiK3BlKG9bMF0pK1wiIGZvdW5kXCIpXTtpZih2b2lkIDA9PT1vWzBdLnpvb20pcmV0dXJuW25ldyBGKHMsbyxcIm9iamVjdCBzdG9wIGtleSBtdXN0IGhhdmUgem9vbVwiKV07aWYodm9pZCAwPT09b1swXS52YWx1ZSlyZXR1cm5bbmV3IEYocyxvLFwib2JqZWN0IHN0b3Aga2V5IG11c3QgaGF2ZSB2YWx1ZVwiKV07aWYobiYmbj5PKG9bMF0uem9vbSkpcmV0dXJuW25ldyBGKHMsb1swXS56b29tLFwic3RvcCB6b29tIHZhbHVlcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXJcIildO08ob1swXS56b29tKSE9PW4mJihuPU8ob1swXS56b29tKSxyPXZvaWQgMCxhPXt9KSxlPWUuY29uY2F0KE1lKHtrZXk6cytcIlswXVwiLHZhbHVlOm9bMF0sdmFsdWVTcGVjOnt6b29tOnt9fSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlYyxvYmplY3RFbGVtZW50VmFsaWRhdG9yczp7em9vbTpCZSx2YWx1ZTpofX0pKTt9ZWxzZSBlPWUuY29uY2F0KGgoe2tleTpzK1wiWzBdXCIsdmFsdWU6b1swXSx2YWx1ZVNwZWM6e30sc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWN9LG8pKTtyZXR1cm4gZS5jb25jYXQoWWUoe2tleTpzK1wiWzFdXCIsdmFsdWU6b1sxXSx2YWx1ZVNwZWM6aSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlY30pKX1mdW5jdGlvbiBoKHQsbil7dmFyIHM9cGUodC52YWx1ZSksdT1PKHQudmFsdWUpLGw9bnVsbCE9PXQudmFsdWU/dC52YWx1ZTpuO2lmKGUpe2lmKHMhPT1lKXJldHVybltuZXcgRih0LmtleSxsLHMrXCIgc3RvcCBkb21haW4gdHlwZSBtdXN0IG1hdGNoIHByZXZpb3VzIHN0b3AgZG9tYWluIHR5cGUgXCIrZSldfWVsc2UgZT1zO2lmKFwibnVtYmVyXCIhPT1zJiZcInN0cmluZ1wiIT09cyYmXCJib29sZWFuXCIhPT1zKXJldHVybltuZXcgRih0LmtleSxsLFwic3RvcCBkb21haW4gdmFsdWUgbXVzdCBiZSBhIG51bWJlciwgc3RyaW5nLCBvciBib29sZWFuXCIpXTtpZihcIm51bWJlclwiIT09cyYmXCJjYXRlZ29yaWNhbFwiIT09byl7dmFyIHA9XCJudW1iZXIgZXhwZWN0ZWQsIFwiK3MrXCIgZm91bmRcIjtyZXR1cm4gaVtcInByb3BlcnR5LWZ1bmN0aW9uXCJdJiZ2b2lkIDA9PT1vJiYocCs9J1xcbklmIHlvdSBpbnRlbmRlZCB0byB1c2UgYSBjYXRlZ29yaWNhbCBmdW5jdGlvbiwgc3BlY2lmeSBgXCJ0eXBlXCI6IFwiY2F0ZWdvcmljYWxcImAuJyksW25ldyBGKHQua2V5LGwscCldfXJldHVyblwiY2F0ZWdvcmljYWxcIiE9PW98fFwibnVtYmVyXCIhPT1zfHxpc0Zpbml0ZSh1KSYmTWF0aC5mbG9vcih1KT09PXU/XCJjYXRlZ29yaWNhbFwiIT09byYmXCJudW1iZXJcIj09PXMmJnZvaWQgMCE9PXImJnU8cj9bbmV3IEYodC5rZXksbCxcInN0b3AgZG9tYWluIHZhbHVlcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXJcIildOihyPXUsXCJjYXRlZ29yaWNhbFwiPT09byYmdSBpbiBhP1tuZXcgRih0LmtleSxsLFwic3RvcCBkb21haW4gdmFsdWVzIG11c3QgYmUgdW5pcXVlXCIpXTooYVt1XT0hMCxbXSkpOltuZXcgRih0LmtleSxsLFwiaW50ZWdlciBleHBlY3RlZCwgZm91bmQgXCIrdSldfX1mdW5jdGlvbiBJZSh0KXt2YXIgZT0oXCJwcm9wZXJ0eVwiPT09dC5leHByZXNzaW9uQ29udGV4dD9rZTp3ZSkoTCh0LnZhbHVlKSx0LnZhbHVlU3BlYyk7cmV0dXJuXCJlcnJvclwiPT09ZS5yZXN1bHQ/ZS52YWx1ZS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyBGKFwiXCIrdC5rZXkrZS5rZXksdC52YWx1ZSxlLm1lc3NhZ2UpfSk6XCJwcm9wZXJ0eVwiPT09dC5leHByZXNzaW9uQ29udGV4dCYmXCJ0ZXh0LWZvbnRcIj09PXQucHJvcGVydHlLZXkmJi0xIT09ZS52YWx1ZS5fc3R5bGVFeHByZXNzaW9uLmV4cHJlc3Npb24ucG9zc2libGVPdXRwdXRzKCkuaW5kZXhPZih2b2lkIDApP1tuZXcgRih0LmtleSx0LnZhbHVlLCdJbnZhbGlkIGRhdGEgZXhwcmVzc2lvbiBmb3IgXCJ0ZXh0LWZvbnRcIi4gT3V0cHV0IHZhbHVlcyBtdXN0IGJlIGNvbnRhaW5lZCBhcyBsaXRlcmFscyB3aXRoaW4gdGhlIGV4cHJlc3Npb24uJyldOltdfWZ1bmN0aW9uIEVlKHQpe3ZhciBlPXQua2V5LHI9dC52YWx1ZSxuPXQudmFsdWVTcGVjLGk9W107cmV0dXJuIEFycmF5LmlzQXJyYXkobi52YWx1ZXMpPy0xPT09bi52YWx1ZXMuaW5kZXhPZihPKHIpKSYmaS5wdXNoKG5ldyBGKGUscixcImV4cGVjdGVkIG9uZSBvZiBbXCIrbi52YWx1ZXMuam9pbihcIiwgXCIpK1wiXSwgXCIrSlNPTi5zdHJpbmdpZnkocikrXCIgZm91bmRcIikpOi0xPT09T2JqZWN0LmtleXMobi52YWx1ZXMpLmluZGV4T2YoTyhyKSkmJmkucHVzaChuZXcgRihlLHIsXCJleHBlY3RlZCBvbmUgb2YgW1wiK09iamVjdC5rZXlzKG4udmFsdWVzKS5qb2luKFwiLCBcIikrXCJdLCBcIitKU09OLnN0cmluZ2lmeShyKStcIiBmb3VuZFwiKSksaX1mdW5jdGlvbiBGZSh0KXtpZighQXJyYXkuaXNBcnJheSh0KXx8MD09PXQubGVuZ3RoKXJldHVybiExO3N3aXRjaCh0WzBdKXtjYXNlXCJoYXNcIjpyZXR1cm4gdC5sZW5ndGg+PTImJlwiJGlkXCIhPT10WzFdJiZcIiR0eXBlXCIhPT10WzFdO2Nhc2VcImluXCI6Y2FzZVwiIWluXCI6Y2FzZVwiIWhhc1wiOmNhc2VcIm5vbmVcIjpyZXR1cm4hMTtjYXNlXCI9PVwiOmNhc2VcIiE9XCI6Y2FzZVwiPlwiOmNhc2VcIj49XCI6Y2FzZVwiPFwiOmNhc2VcIjw9XCI6cmV0dXJuIDM9PT10Lmxlbmd0aCYmKEFycmF5LmlzQXJyYXkodFsxXSl8fEFycmF5LmlzQXJyYXkodFsyXSkpO2Nhc2VcImFueVwiOmNhc2VcImFsbFwiOmZvcih2YXIgZT0wLHI9dC5zbGljZSgxKTtlPHIubGVuZ3RoO2UrPTEpe3ZhciBuPXJbZV07aWYoIUZlKG4pJiZcImJvb2xlYW5cIiE9dHlwZW9mIG4pcmV0dXJuITF9cmV0dXJuITA7ZGVmYXVsdDpyZXR1cm4hMH19emUuZGVzZXJpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyB6ZSh0Ll9wYXJhbWV0ZXJzLHQuX3NwZWNpZmljYXRpb24pfSx6ZS5zZXJpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJue19wYXJhbWV0ZXJzOnQuX3BhcmFtZXRlcnMsX3NwZWNpZmljYXRpb246dC5fc3BlY2lmaWNhdGlvbn19O3ZhciBQZT17dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLGZ1bmN0aW9uOiEwLFwicHJvcGVydHktZnVuY3Rpb25cIjohMCxcInpvb20tZnVuY3Rpb25cIjohMH07ZnVuY3Rpb24gVGUodCl7aWYoIXQpcmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuITB9O0ZlKHQpfHwodD1MZSh0KSk7dmFyIGU9d2UodCxQZSk7aWYoXCJlcnJvclwiPT09ZS5yZXN1bHQpdGhyb3cgbmV3IEVycm9yKGUudmFsdWUubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmtleStcIjogXCIrdC5tZXNzYWdlfSkuam9pbihcIiwgXCIpKTtyZXR1cm4gZnVuY3Rpb24odCxyKXtyZXR1cm4gZS52YWx1ZS5ldmFsdWF0ZSh0LHIpfX1mdW5jdGlvbiBPZSh0LGUpe3JldHVybiB0PGU/LTE6dD5lPzE6MH1mdW5jdGlvbiBMZSh0KXtpZighdClyZXR1cm4hMDt2YXIgZSxyPXRbMF07cmV0dXJuIHQubGVuZ3RoPD0xP1wiYW55XCIhPT1yOlwiPT1cIj09PXI/amUodFsxXSx0WzJdLFwiPT1cIik6XCIhPVwiPT09cj9VZShqZSh0WzFdLHRbMl0sXCI9PVwiKSk6XCI8XCI9PT1yfHxcIj5cIj09PXJ8fFwiPD1cIj09PXJ8fFwiPj1cIj09PXI/amUodFsxXSx0WzJdLHIpOlwiYW55XCI9PT1yPyhlPXQuc2xpY2UoMSksW1wiYW55XCJdLmNvbmNhdChlLm1hcChMZSkpKTpcImFsbFwiPT09cj9bXCJhbGxcIl0uY29uY2F0KHQuc2xpY2UoMSkubWFwKExlKSk6XCJub25lXCI9PT1yP1tcImFsbFwiXS5jb25jYXQodC5zbGljZSgxKS5tYXAoTGUpLm1hcChVZSkpOlwiaW5cIj09PXI/cWUodFsxXSx0LnNsaWNlKDIpKTpcIiFpblwiPT09cj9VZShxZSh0WzFdLHQuc2xpY2UoMikpKTpcImhhc1wiPT09cj9SZSh0WzFdKTpcIiFoYXNcIiE9PXJ8fFVlKFJlKHRbMV0pKX1mdW5jdGlvbiBqZSh0LGUscil7c3dpdGNoKHQpe2Nhc2VcIiR0eXBlXCI6cmV0dXJuW1wiZmlsdGVyLXR5cGUtXCIrcixlXTtjYXNlXCIkaWRcIjpyZXR1cm5bXCJmaWx0ZXItaWQtXCIrcixlXTtkZWZhdWx0OnJldHVybltcImZpbHRlci1cIityLHQsZV19fWZ1bmN0aW9uIHFlKHQsZSl7aWYoMD09PWUubGVuZ3RoKXJldHVybiExO3N3aXRjaCh0KXtjYXNlXCIkdHlwZVwiOnJldHVybltcImZpbHRlci10eXBlLWluXCIsW1wibGl0ZXJhbFwiLGVdXTtjYXNlXCIkaWRcIjpyZXR1cm5bXCJmaWx0ZXItaWQtaW5cIixbXCJsaXRlcmFsXCIsZV1dO2RlZmF1bHQ6cmV0dXJuIGUubGVuZ3RoPjIwMCYmIWUuc29tZShmdW5jdGlvbih0KXtyZXR1cm4gdHlwZW9mIHQhPXR5cGVvZiBlWzBdfSk/W1wiZmlsdGVyLWluLWxhcmdlXCIsdCxbXCJsaXRlcmFsXCIsZS5zb3J0KE9lKV1dOltcImZpbHRlci1pbi1zbWFsbFwiLHQsW1wibGl0ZXJhbFwiLGVdXX19ZnVuY3Rpb24gUmUodCl7c3dpdGNoKHQpe2Nhc2VcIiR0eXBlXCI6cmV0dXJuITA7Y2FzZVwiJGlkXCI6cmV0dXJuW1wiZmlsdGVyLWhhcy1pZFwiXTtkZWZhdWx0OnJldHVybltcImZpbHRlci1oYXNcIix0XX19ZnVuY3Rpb24gVWUodCl7cmV0dXJuW1wiIVwiLHRdfWZ1bmN0aW9uIERlKHQpe3JldHVybiBGZShMKHQudmFsdWUpKT9JZShUKHt9LHQse2V4cHJlc3Npb25Db250ZXh0OlwiZmlsdGVyXCIsdmFsdWVTcGVjOnt2YWx1ZTpcImJvb2xlYW5cIn19KSk6ZnVuY3Rpb24gdChlKXt2YXIgcj1lLnZhbHVlO3ZhciBuPWUua2V5O2lmKFwiYXJyYXlcIiE9PXBlKHIpKXJldHVybltuZXcgRihuLHIsXCJhcnJheSBleHBlY3RlZCwgXCIrcGUocikrXCIgZm91bmRcIildO3ZhciBpPWUuc3R5bGVTcGVjO3ZhciBvO3ZhciBhPVtdO2lmKHIubGVuZ3RoPDEpcmV0dXJuW25ldyBGKG4scixcImZpbHRlciBhcnJheSBtdXN0IGhhdmUgYXQgbGVhc3QgMSBlbGVtZW50XCIpXTthPWEuY29uY2F0KEVlKHtrZXk6bitcIlswXVwiLHZhbHVlOnJbMF0sdmFsdWVTcGVjOmkuZmlsdGVyX29wZXJhdG9yLHN0eWxlOmUuc3R5bGUsc3R5bGVTcGVjOmUuc3R5bGVTcGVjfSkpO3N3aXRjaChPKHJbMF0pKXtjYXNlXCI8XCI6Y2FzZVwiPD1cIjpjYXNlXCI+XCI6Y2FzZVwiPj1cIjpyLmxlbmd0aD49MiYmXCIkdHlwZVwiPT09TyhyWzFdKSYmYS5wdXNoKG5ldyBGKG4sciwnXCIkdHlwZVwiIGNhbm5vdCBiZSB1c2Ugd2l0aCBvcGVyYXRvciBcIicrclswXSsnXCInKSk7Y2FzZVwiPT1cIjpjYXNlXCIhPVwiOjMhPT1yLmxlbmd0aCYmYS5wdXNoKG5ldyBGKG4sciwnZmlsdGVyIGFycmF5IGZvciBvcGVyYXRvciBcIicrclswXSsnXCIgbXVzdCBoYXZlIDMgZWxlbWVudHMnKSk7Y2FzZVwiaW5cIjpjYXNlXCIhaW5cIjpyLmxlbmd0aD49MiYmXCJzdHJpbmdcIiE9PShvPXBlKHJbMV0pKSYmYS5wdXNoKG5ldyBGKG4rXCJbMV1cIixyWzFdLFwic3RyaW5nIGV4cGVjdGVkLCBcIitvK1wiIGZvdW5kXCIpKTtmb3IodmFyIHM9MjtzPHIubGVuZ3RoO3MrKylvPXBlKHJbc10pLFwiJHR5cGVcIj09PU8oclsxXSk/YT1hLmNvbmNhdChFZSh7a2V5Om4rXCJbXCIrcytcIl1cIix2YWx1ZTpyW3NdLHZhbHVlU3BlYzppLmdlb21ldHJ5X3R5cGUsc3R5bGU6ZS5zdHlsZSxzdHlsZVNwZWM6ZS5zdHlsZVNwZWN9KSk6XCJzdHJpbmdcIiE9PW8mJlwibnVtYmVyXCIhPT1vJiZcImJvb2xlYW5cIiE9PW8mJmEucHVzaChuZXcgRihuK1wiW1wiK3MrXCJdXCIscltzXSxcInN0cmluZywgbnVtYmVyLCBvciBib29sZWFuIGV4cGVjdGVkLCBcIitvK1wiIGZvdW5kXCIpKTticmVhaztjYXNlXCJhbnlcIjpjYXNlXCJhbGxcIjpjYXNlXCJub25lXCI6Zm9yKHZhciB1PTE7dTxyLmxlbmd0aDt1KyspYT1hLmNvbmNhdCh0KHtrZXk6bitcIltcIit1K1wiXVwiLHZhbHVlOnJbdV0sc3R5bGU6ZS5zdHlsZSxzdHlsZVNwZWM6ZS5zdHlsZVNwZWN9KSk7YnJlYWs7Y2FzZVwiaGFzXCI6Y2FzZVwiIWhhc1wiOm89cGUoclsxXSksMiE9PXIubGVuZ3RoP2EucHVzaChuZXcgRihuLHIsJ2ZpbHRlciBhcnJheSBmb3IgXCInK3JbMF0rJ1wiIG9wZXJhdG9yIG11c3QgaGF2ZSAyIGVsZW1lbnRzJykpOlwic3RyaW5nXCIhPT1vJiZhLnB1c2gobmV3IEYobitcIlsxXVwiLHJbMV0sXCJzdHJpbmcgZXhwZWN0ZWQsIFwiK28rXCIgZm91bmRcIikpO31yZXR1cm4gYX0odCl9ZnVuY3Rpb24gTmUodCxlKXt2YXIgcj10LmtleSxuPXQuc3R5bGUsaT10LnN0eWxlU3BlYyxvPXQudmFsdWUsYT10Lm9iamVjdEtleSxzPWlbZStcIl9cIit0LmxheWVyVHlwZV07aWYoIXMpcmV0dXJuW107dmFyIHU9YS5tYXRjaCgvXiguKiktdHJhbnNpdGlvbiQvKTtpZihcInBhaW50XCI9PT1lJiZ1JiZzW3VbMV1dJiZzW3VbMV1dLnRyYW5zaXRpb24pcmV0dXJuIFllKHtrZXk6cix2YWx1ZTpvLHZhbHVlU3BlYzppLnRyYW5zaXRpb24sc3R5bGU6bixzdHlsZVNwZWM6aX0pO3ZhciBsLHA9dC52YWx1ZVNwZWN8fHNbYV07aWYoIXApcmV0dXJuW25ldyBGKHIsbywndW5rbm93biBwcm9wZXJ0eSBcIicrYSsnXCInKV07aWYoXCJzdHJpbmdcIj09PXBlKG8pJiZwW1wicHJvcGVydHktZnVuY3Rpb25cIl0mJiFwLnRva2VucyYmKGw9L157KFtefV0rKX0kLy5leGVjKG8pKSlyZXR1cm5bbmV3IEYocixvLCdcIicrYSsnXCIgZG9lcyBub3Qgc3VwcG9ydCBpbnRlcnBvbGF0aW9uIHN5bnRheFxcblVzZSBhbiBpZGVudGl0eSBwcm9wZXJ0eSBmdW5jdGlvbiBpbnN0ZWFkOiBgeyBcInR5cGVcIjogXCJpZGVudGl0eVwiLCBcInByb3BlcnR5XCI6ICcrSlNPTi5zdHJpbmdpZnkobFsxXSkrXCIgfWAuXCIpXTt2YXIgYz1bXTtyZXR1cm5cInN5bWJvbFwiPT09dC5sYXllclR5cGUmJihcInRleHQtZmllbGRcIj09PWEmJm4mJiFuLmdseXBocyYmYy5wdXNoKG5ldyBGKHIsbywndXNlIG9mIFwidGV4dC1maWVsZFwiIHJlcXVpcmVzIGEgc3R5bGUgXCJnbHlwaHNcIiBwcm9wZXJ0eScpKSxcInRleHQtZm9udFwiPT09YSYmY2UoTChvKSkmJlwiaWRlbnRpdHlcIj09PU8oby50eXBlKSYmYy5wdXNoKG5ldyBGKHIsbywnXCJ0ZXh0LWZvbnRcIiBkb2VzIG5vdCBzdXBwb3J0IGlkZW50aXR5IGZ1bmN0aW9ucycpKSksYy5jb25jYXQoWWUoe2tleTp0LmtleSx2YWx1ZTpvLHZhbHVlU3BlYzpwLHN0eWxlOm4sc3R5bGVTcGVjOmksZXhwcmVzc2lvbkNvbnRleHQ6XCJwcm9wZXJ0eVwiLHByb3BlcnR5S2V5OmF9KSl9ZnVuY3Rpb24gWmUodCl7cmV0dXJuIE5lKHQsXCJwYWludFwiKX1mdW5jdGlvbiBLZSh0KXtyZXR1cm4gTmUodCxcImxheW91dFwiKX1mdW5jdGlvbiBKZSh0KXt2YXIgZT1bXSxyPXQudmFsdWUsbj10LmtleSxpPXQuc3R5bGUsbz10LnN0eWxlU3BlYztyLnR5cGV8fHIucmVmfHxlLnB1c2gobmV3IEYobixyLCdlaXRoZXIgXCJ0eXBlXCIgb3IgXCJyZWZcIiBpcyByZXF1aXJlZCcpKTt2YXIgYSxzPU8oci50eXBlKSx1PU8oci5yZWYpO2lmKHIuaWQpZm9yKHZhciBsPU8oci5pZCkscD0wO3A8dC5hcnJheUluZGV4O3ArKyl7dmFyIGM9aS5sYXllcnNbcF07TyhjLmlkKT09PWwmJmUucHVzaChuZXcgRihuLHIuaWQsJ2R1cGxpY2F0ZSBsYXllciBpZCBcIicrci5pZCsnXCIsIHByZXZpb3VzbHkgdXNlZCBhdCBsaW5lICcrYy5pZC5fX2xpbmVfXykpO31pZihcInJlZlwiaW4gcilbXCJ0eXBlXCIsXCJzb3VyY2VcIixcInNvdXJjZS1sYXllclwiLFwiZmlsdGVyXCIsXCJsYXlvdXRcIl0uZm9yRWFjaChmdW5jdGlvbih0KXt0IGluIHImJmUucHVzaChuZXcgRihuLHJbdF0sJ1wiJyt0KydcIiBpcyBwcm9oaWJpdGVkIGZvciByZWYgbGF5ZXJzJykpO30pLGkubGF5ZXJzLmZvckVhY2goZnVuY3Rpb24odCl7Tyh0LmlkKT09PXUmJihhPXQpO30pLGE/YS5yZWY/ZS5wdXNoKG5ldyBGKG4sci5yZWYsXCJyZWYgY2Fubm90IHJlZmVyZW5jZSBhbm90aGVyIHJlZiBsYXllclwiKSk6cz1PKGEudHlwZSk6ZS5wdXNoKG5ldyBGKG4sci5yZWYsJ3JlZiBsYXllciBcIicrdSsnXCIgbm90IGZvdW5kJykpO2Vsc2UgaWYoXCJiYWNrZ3JvdW5kXCIhPT1zKWlmKHIuc291cmNlKXt2YXIgaD1pLnNvdXJjZXMmJmkuc291cmNlc1tyLnNvdXJjZV0sZj1oJiZPKGgudHlwZSk7aD9cInZlY3RvclwiPT09ZiYmXCJyYXN0ZXJcIj09PXM/ZS5wdXNoKG5ldyBGKG4sci5zb3VyY2UsJ2xheWVyIFwiJytyLmlkKydcIiByZXF1aXJlcyBhIHJhc3RlciBzb3VyY2UnKSk6XCJyYXN0ZXJcIj09PWYmJlwicmFzdGVyXCIhPT1zP2UucHVzaChuZXcgRihuLHIuc291cmNlLCdsYXllciBcIicrci5pZCsnXCIgcmVxdWlyZXMgYSB2ZWN0b3Igc291cmNlJykpOlwidmVjdG9yXCIhPT1mfHxyW1wic291cmNlLWxheWVyXCJdP1wicmFzdGVyLWRlbVwiPT09ZiYmXCJoaWxsc2hhZGVcIiE9PXM/ZS5wdXNoKG5ldyBGKG4sci5zb3VyY2UsXCJyYXN0ZXItZGVtIHNvdXJjZSBjYW4gb25seSBiZSB1c2VkIHdpdGggbGF5ZXIgdHlwZSAnaGlsbHNoYWRlJy5cIikpOlwibGluZVwiIT09c3x8IXIucGFpbnR8fCFyLnBhaW50W1wibGluZS1ncmFkaWVudFwiXXx8XCJnZW9qc29uXCI9PT1mJiZoLmxpbmVNZXRyaWNzfHxlLnB1c2gobmV3IEYobixyLCdsYXllciBcIicrci5pZCsnXCIgc3BlY2lmaWVzIGEgbGluZS1ncmFkaWVudCwgd2hpY2ggcmVxdWlyZXMgYSBHZW9KU09OIHNvdXJjZSB3aXRoIGBsaW5lTWV0cmljc2AgZW5hYmxlZC4nKSk6ZS5wdXNoKG5ldyBGKG4sciwnbGF5ZXIgXCInK3IuaWQrJ1wiIG11c3Qgc3BlY2lmeSBhIFwic291cmNlLWxheWVyXCInKSk6ZS5wdXNoKG5ldyBGKG4sci5zb3VyY2UsJ3NvdXJjZSBcIicrci5zb3VyY2UrJ1wiIG5vdCBmb3VuZCcpKTt9ZWxzZSBlLnB1c2gobmV3IEYobixyLCdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwic291cmNlXCInKSk7cmV0dXJuIGU9ZS5jb25jYXQoTWUoe2tleTpuLHZhbHVlOnIsdmFsdWVTcGVjOm8ubGF5ZXIsc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWMsb2JqZWN0RWxlbWVudFZhbGlkYXRvcnM6e1wiKlwiOmZ1bmN0aW9uKCl7cmV0dXJuW119LHR5cGU6ZnVuY3Rpb24oKXtyZXR1cm4gWWUoe2tleTpuK1wiLnR5cGVcIix2YWx1ZTpyLnR5cGUsdmFsdWVTcGVjOm8ubGF5ZXIudHlwZSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlYyxvYmplY3Q6cixvYmplY3RLZXk6XCJ0eXBlXCJ9KX0sZmlsdGVyOkRlLGxheW91dDpmdW5jdGlvbih0KXtyZXR1cm4gTWUoe2xheWVyOnIsa2V5OnQua2V5LHZhbHVlOnQudmFsdWUsc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWMsb2JqZWN0RWxlbWVudFZhbGlkYXRvcnM6e1wiKlwiOmZ1bmN0aW9uKHQpe3JldHVybiBLZShUKHtsYXllclR5cGU6c30sdCkpfX19KX0scGFpbnQ6ZnVuY3Rpb24odCl7cmV0dXJuIE1lKHtsYXllcjpyLGtleTp0LmtleSx2YWx1ZTp0LnZhbHVlLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLG9iamVjdEVsZW1lbnRWYWxpZGF0b3JzOntcIipcIjpmdW5jdGlvbih0KXtyZXR1cm4gWmUoVCh7bGF5ZXJUeXBlOnN9LHQpKX19fSl9fX0pKX1mdW5jdGlvbiAkZSh0KXt2YXIgZT10LnZhbHVlLHI9dC5rZXksbj10LnN0eWxlU3BlYyxpPXQuc3R5bGU7aWYoIWUudHlwZSlyZXR1cm5bbmV3IEYocixlLCdcInR5cGVcIiBpcyByZXF1aXJlZCcpXTt2YXIgbz1PKGUudHlwZSksYT1bXTtzd2l0Y2gobyl7Y2FzZVwidmVjdG9yXCI6Y2FzZVwicmFzdGVyXCI6Y2FzZVwicmFzdGVyLWRlbVwiOmlmKGE9YS5jb25jYXQoTWUoe2tleTpyLHZhbHVlOmUsdmFsdWVTcGVjOm5bXCJzb3VyY2VfXCIrby5yZXBsYWNlKFwiLVwiLFwiX1wiKV0sc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6bn0pKSxcInVybFwiaW4gZSlmb3IodmFyIHMgaW4gZSlbXCJ0eXBlXCIsXCJ1cmxcIixcInRpbGVTaXplXCJdLmluZGV4T2Yocyk8MCYmYS5wdXNoKG5ldyBGKHIrXCIuXCIrcyxlW3NdLCdhIHNvdXJjZSB3aXRoIGEgXCJ1cmxcIiBwcm9wZXJ0eSBtYXkgbm90IGluY2x1ZGUgYSBcIicrcysnXCIgcHJvcGVydHknKSk7cmV0dXJuIGE7Y2FzZVwiZ2VvanNvblwiOnJldHVybiBNZSh7a2V5OnIsdmFsdWU6ZSx2YWx1ZVNwZWM6bi5zb3VyY2VfZ2VvanNvbixzdHlsZTppLHN0eWxlU3BlYzpufSk7Y2FzZVwidmlkZW9cIjpyZXR1cm4gTWUoe2tleTpyLHZhbHVlOmUsdmFsdWVTcGVjOm4uc291cmNlX3ZpZGVvLHN0eWxlOmksc3R5bGVTcGVjOm59KTtjYXNlXCJpbWFnZVwiOnJldHVybiBNZSh7a2V5OnIsdmFsdWU6ZSx2YWx1ZVNwZWM6bi5zb3VyY2VfaW1hZ2Usc3R5bGU6aSxzdHlsZVNwZWM6bn0pO2Nhc2VcImNhbnZhc1wiOnJldHVybiBhLnB1c2gobmV3IEYocixudWxsLFwiUGxlYXNlIHVzZSBydW50aW1lIEFQSXMgdG8gYWRkIGNhbnZhcyBzb3VyY2VzLCByYXRoZXIgdGhhbiBpbmNsdWRpbmcgdGhlbSBpbiBzdHlsZXNoZWV0cy5cIixcInNvdXJjZS5jYW52YXNcIikpLGE7ZGVmYXVsdDpyZXR1cm4gRWUoe2tleTpyK1wiLnR5cGVcIix2YWx1ZTplLnR5cGUsdmFsdWVTcGVjOnt2YWx1ZXM6W1widmVjdG9yXCIsXCJyYXN0ZXJcIixcInJhc3Rlci1kZW1cIixcImdlb2pzb25cIixcInZpZGVvXCIsXCJpbWFnZVwiXX0sc3R5bGU6aSxzdHlsZVNwZWM6bn0pfX1mdW5jdGlvbiBIZSh0KXt2YXIgZT10LnZhbHVlLHI9dC5zdHlsZVNwZWMsbj1yLmxpZ2h0LGk9dC5zdHlsZSxvPVtdLGE9cGUoZSk7aWYodm9pZCAwPT09ZSlyZXR1cm4gbztpZihcIm9iamVjdFwiIT09YSlyZXR1cm4gbz1vLmNvbmNhdChbbmV3IEYoXCJsaWdodFwiLGUsXCJvYmplY3QgZXhwZWN0ZWQsIFwiK2ErXCIgZm91bmRcIildKTtmb3IodmFyIHMgaW4gZSl7dmFyIHU9cy5tYXRjaCgvXiguKiktdHJhbnNpdGlvbiQvKTtvPXUmJm5bdVsxXV0mJm5bdVsxXV0udHJhbnNpdGlvbj9vLmNvbmNhdChZZSh7a2V5OnMsdmFsdWU6ZVtzXSx2YWx1ZVNwZWM6ci50cmFuc2l0aW9uLHN0eWxlOmksc3R5bGVTcGVjOnJ9KSk6bltzXT9vLmNvbmNhdChZZSh7a2V5OnMsdmFsdWU6ZVtzXSx2YWx1ZVNwZWM6bltzXSxzdHlsZTppLHN0eWxlU3BlYzpyfSkpOm8uY29uY2F0KFtuZXcgRihzLGVbc10sJ3Vua25vd24gcHJvcGVydHkgXCInK3MrJ1wiJyldKTt9cmV0dXJuIG99ZnVuY3Rpb24gWGUodCl7dmFyIGU9dC52YWx1ZSxyPXQua2V5LG49cGUoZSk7cmV0dXJuXCJzdHJpbmdcIiE9PW4/W25ldyBGKHIsZSxcInN0cmluZyBleHBlY3RlZCwgXCIrbitcIiBmb3VuZFwiKV06W119dmFyIEdlPXtcIipcIjpmdW5jdGlvbigpe3JldHVybltdfSxhcnJheTpWZSxib29sZWFuOmZ1bmN0aW9uKHQpe3ZhciBlPXQudmFsdWUscj10LmtleSxuPXBlKGUpO3JldHVyblwiYm9vbGVhblwiIT09bj9bbmV3IEYocixlLFwiYm9vbGVhbiBleHBlY3RlZCwgXCIrbitcIiBmb3VuZFwiKV06W119LG51bWJlcjpCZSxjb2xvcjpmdW5jdGlvbih0KXt2YXIgZT10LmtleSxyPXQudmFsdWUsbj1wZShyKTtyZXR1cm5cInN0cmluZ1wiIT09bj9bbmV3IEYoZSxyLFwiY29sb3IgZXhwZWN0ZWQsIFwiK24rXCIgZm91bmRcIildOm51bGw9PT1XKHIpP1tuZXcgRihlLHIsJ2NvbG9yIGV4cGVjdGVkLCBcIicrcisnXCIgZm91bmQnKV06W119LGNvbnN0YW50czpQLGVudW06RWUsZmlsdGVyOkRlLGZ1bmN0aW9uOkNlLGxheWVyOkplLG9iamVjdDpNZSxzb3VyY2U6JGUsbGlnaHQ6SGUsc3RyaW5nOlhlfTtmdW5jdGlvbiBZZSh0KXt2YXIgZT10LnZhbHVlLHI9dC52YWx1ZVNwZWMsbj10LnN0eWxlU3BlYztyZXR1cm4gci5mdW5jdGlvbiYmY2UoTyhlKSk/Q2UodCk6ci5mdW5jdGlvbiYmYmUoTChlKSk/SWUodCk6ci50eXBlJiZHZVtyLnR5cGVdP0dlW3IudHlwZV0odCk6TWUoVCh7fSx0LHt2YWx1ZVNwZWM6ci50eXBlP25bci50eXBlXTpyfSkpfWZ1bmN0aW9uIFdlKHQpe3ZhciBlPXQudmFsdWUscj10LmtleSxuPVhlKHQpO3JldHVybiBuLmxlbmd0aD9uOigtMT09PWUuaW5kZXhPZihcIntmb250c3RhY2t9XCIpJiZuLnB1c2gobmV3IEYocixlLCdcImdseXBoc1wiIHVybCBtdXN0IGluY2x1ZGUgYSBcIntmb250c3RhY2t9XCIgdG9rZW4nKSksLTE9PT1lLmluZGV4T2YoXCJ7cmFuZ2V9XCIpJiZuLnB1c2gobmV3IEYocixlLCdcImdseXBoc1wiIHVybCBtdXN0IGluY2x1ZGUgYSBcIntyYW5nZX1cIiB0b2tlbicpKSxuKX1mdW5jdGlvbiBRZSh0LGUpe2U9ZXx8RTt2YXIgcj1bXTtyZXR1cm4gcj1yLmNvbmNhdChZZSh7a2V5OlwiXCIsdmFsdWU6dCx2YWx1ZVNwZWM6ZS4kcm9vdCxzdHlsZVNwZWM6ZSxzdHlsZTp0LG9iamVjdEVsZW1lbnRWYWxpZGF0b3JzOntnbHlwaHM6V2UsXCIqXCI6ZnVuY3Rpb24oKXtyZXR1cm5bXX19fSkpLHQuY29uc3RhbnRzJiYocj1yLmNvbmNhdChQKHtrZXk6XCJjb25zdGFudHNcIix2YWx1ZTp0LmNvbnN0YW50cyxzdHlsZTp0LHN0eWxlU3BlYzplfSkpKSx0cihyKX1mdW5jdGlvbiB0cih0KXtyZXR1cm5bXS5jb25jYXQodCkuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiB0LmxpbmUtZS5saW5lfSl9ZnVuY3Rpb24gZXIodCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHRyKHQuYXBwbHkodGhpcyxhcmd1bWVudHMpKX19UWUuc291cmNlPWVyKCRlKSxRZS5saWdodD1lcihIZSksUWUubGF5ZXI9ZXIoSmUpLFFlLmZpbHRlcj1lcihEZSksUWUucGFpbnRQcm9wZXJ0eT1lcihaZSksUWUubGF5b3V0UHJvcGVydHk9ZXIoS2UpO3ZhciBycj1RZSxucj1RZS5saWdodCxpcj1RZS5wYWludFByb3BlcnR5LG9yPVFlLmxheW91dFByb3BlcnR5O2Z1bmN0aW9uIGFyKHQsZSl7dmFyIHI9ITE7aWYoZSYmZS5sZW5ndGgpZm9yKHZhciBuPTAsaT1lO248aS5sZW5ndGg7bis9MSl7dmFyIG89aVtuXTt0LmZpcmUobmV3IEMobmV3IEVycm9yKG8ubWVzc2FnZSkpKSxyPSEwO31yZXR1cm4gcn12YXIgc3I9bHIsdXI9MztmdW5jdGlvbiBscih0LGUscil7dmFyIG49dGhpcy5jZWxscz1bXTtpZih0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe3RoaXMuYXJyYXlCdWZmZXI9dDt2YXIgaT1uZXcgSW50MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt0PWlbMF0sZT1pWzFdLHI9aVsyXSx0aGlzLmQ9ZSsyKnI7Zm9yKHZhciBvPTA7bzx0aGlzLmQqdGhpcy5kO28rKyl7dmFyIGE9aVt1citvXSxzPWlbdXIrbysxXTtuLnB1c2goYT09PXM/bnVsbDppLnN1YmFycmF5KGEscykpO312YXIgdT1pW3VyK24ubGVuZ3RoXSxsPWlbdXIrbi5sZW5ndGgrMV07dGhpcy5rZXlzPWkuc3ViYXJyYXkodSxsKSx0aGlzLmJib3hlcz1pLnN1YmFycmF5KGwpLHRoaXMuaW5zZXJ0PXRoaXMuX2luc2VydFJlYWRvbmx5O31lbHNle3RoaXMuZD1lKzIqcjtmb3IodmFyIHA9MDtwPHRoaXMuZCp0aGlzLmQ7cCsrKW4ucHVzaChbXSk7dGhpcy5rZXlzPVtdLHRoaXMuYmJveGVzPVtdO310aGlzLm49ZSx0aGlzLmV4dGVudD10LHRoaXMucGFkZGluZz1yLHRoaXMuc2NhbGU9ZS90LHRoaXMudWlkPTA7dmFyIGM9ci9lKnQ7dGhpcy5taW49LWMsdGhpcy5tYXg9dCtjO31sci5wcm90b3R5cGUuaW5zZXJ0PWZ1bmN0aW9uKHQsZSxyLG4saSl7dGhpcy5fZm9yRWFjaENlbGwoZSxyLG4saSx0aGlzLl9pbnNlcnRDZWxsLHRoaXMudWlkKyspLHRoaXMua2V5cy5wdXNoKHQpLHRoaXMuYmJveGVzLnB1c2goZSksdGhpcy5iYm94ZXMucHVzaChyKSx0aGlzLmJib3hlcy5wdXNoKG4pLHRoaXMuYmJveGVzLnB1c2goaSk7fSxsci5wcm90b3R5cGUuX2luc2VydFJlYWRvbmx5PWZ1bmN0aW9uKCl7dGhyb3dcIkNhbm5vdCBpbnNlcnQgaW50byBhIEdyaWRJbmRleCBjcmVhdGVkIGZyb20gYW4gQXJyYXlCdWZmZXIuXCJ9LGxyLnByb3RvdHlwZS5faW5zZXJ0Q2VsbD1mdW5jdGlvbih0LGUscixuLGksbyl7dGhpcy5jZWxsc1tpXS5wdXNoKG8pO30sbHIucHJvdG90eXBlLnF1ZXJ5PWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMubWluLG89dGhpcy5tYXg7aWYodDw9aSYmZTw9aSYmbzw9ciYmbzw9bilyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5rZXlzKTt2YXIgYT1bXTtyZXR1cm4gdGhpcy5fZm9yRWFjaENlbGwodCxlLHIsbix0aGlzLl9xdWVyeUNlbGwsYSx7fSksYX0sbHIucHJvdG90eXBlLl9xdWVyeUNlbGw9ZnVuY3Rpb24odCxlLHIsbixpLG8sYSl7dmFyIHM9dGhpcy5jZWxsc1tpXTtpZihudWxsIT09cylmb3IodmFyIHU9dGhpcy5rZXlzLGw9dGhpcy5iYm94ZXMscD0wO3A8cy5sZW5ndGg7cCsrKXt2YXIgYz1zW3BdO2lmKHZvaWQgMD09PWFbY10pe3ZhciBoPTQqYzt0PD1sW2grMl0mJmU8PWxbaCszXSYmcj49bFtoKzBdJiZuPj1sW2grMV0/KGFbY109ITAsby5wdXNoKHVbY10pKTphW2NdPSExO319fSxsci5wcm90b3R5cGUuX2ZvckVhY2hDZWxsPWZ1bmN0aW9uKHQsZSxyLG4saSxvLGEpe2Zvcih2YXIgcz10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQodCksdT10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQoZSksbD10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQocikscD10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQobiksYz1zO2M8PWw7YysrKWZvcih2YXIgaD11O2g8PXA7aCsrKXt2YXIgZj10aGlzLmQqaCtjO2lmKGkuY2FsbCh0aGlzLHQsZSxyLG4sZixvLGEpKXJldHVybn19LGxyLnByb3RvdHlwZS5fY29udmVydFRvQ2VsbENvb3JkPWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLm1heCgwLE1hdGgubWluKHRoaXMuZC0xLE1hdGguZmxvb3IodCp0aGlzLnNjYWxlKSt0aGlzLnBhZGRpbmcpKX0sbHIucHJvdG90eXBlLnRvQXJyYXlCdWZmZXI9ZnVuY3Rpb24oKXtpZih0aGlzLmFycmF5QnVmZmVyKXJldHVybiB0aGlzLmFycmF5QnVmZmVyO2Zvcih2YXIgdD10aGlzLmNlbGxzLGU9dXIrdGhpcy5jZWxscy5sZW5ndGgrMSsxLHI9MCxuPTA7bjx0aGlzLmNlbGxzLmxlbmd0aDtuKyspcis9dGhpcy5jZWxsc1tuXS5sZW5ndGg7dmFyIGk9bmV3IEludDMyQXJyYXkoZStyK3RoaXMua2V5cy5sZW5ndGgrdGhpcy5iYm94ZXMubGVuZ3RoKTtpWzBdPXRoaXMuZXh0ZW50LGlbMV09dGhpcy5uLGlbMl09dGhpcy5wYWRkaW5nO2Zvcih2YXIgbz1lLGE9MDthPHQubGVuZ3RoO2ErKyl7dmFyIHM9dFthXTtpW3VyK2FdPW8saS5zZXQocyxvKSxvKz1zLmxlbmd0aDt9cmV0dXJuIGlbdXIrdC5sZW5ndGhdPW8saS5zZXQodGhpcy5rZXlzLG8pLG8rPXRoaXMua2V5cy5sZW5ndGgsaVt1cit0Lmxlbmd0aCsxXT1vLGkuc2V0KHRoaXMuYmJveGVzLG8pLG8rPXRoaXMuYmJveGVzLmxlbmd0aCxpLmJ1ZmZlcn07dmFyIHByPXNlbGYuSW1hZ2VEYXRhLGNyPXt9O2Z1bmN0aW9uIGhyKHQsZSxyKXt2b2lkIDA9PT1yJiYocj17fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsXCJfY2xhc3NSZWdpc3RyeUtleVwiLHt2YWx1ZTp0LHdyaXRlYWJsZTohMX0pLGNyW3RdPXtrbGFzczplLG9taXQ6ci5vbWl0fHxbXSxzaGFsbG93OnIuc2hhbGxvd3x8W119O31mb3IodmFyIGZyIGluIGhyKFwiT2JqZWN0XCIsT2JqZWN0KSxzci5zZXJpYWxpemU9ZnVuY3Rpb24odCxlKXt2YXIgcj10LnRvQXJyYXlCdWZmZXIoKTtyZXR1cm4gZSYmZS5wdXNoKHIpLHJ9LHNyLmRlc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgc3IodCl9LGhyKFwiR3JpZFwiLHNyKSxocihcIkNvbG9yXCIsUSksaHIoXCJFcnJvclwiLEVycm9yKSxocihcIlN0eWxlUHJvcGVydHlGdW5jdGlvblwiLHplKSxocihcIlN0eWxlRXhwcmVzc2lvblwiLHhlLHtvbWl0OltcIl9ldmFsdWF0b3JcIl19KSxocihcIlpvb21EZXBlbmRlbnRFeHByZXNzaW9uXCIsQWUpLGhyKFwiWm9vbUNvbnN0YW50RXhwcmVzc2lvblwiLF9lKSxocihcIkNvbXBvdW5kRXhwcmVzc2lvblwiLHl0LHtvbWl0OltcIl9ldmFsdWF0ZVwiXX0pLFR0KVR0W2ZyXS5fY2xhc3NSZWdpc3RyeUtleXx8aHIoXCJFeHByZXNzaW9uX1wiK2ZyLFR0W2ZyXSk7ZnVuY3Rpb24geXIodCxlKXtpZihudWxsPT10fHxcImJvb2xlYW5cIj09dHlwZW9mIHR8fFwibnVtYmVyXCI9PXR5cGVvZiB0fHxcInN0cmluZ1wiPT10eXBlb2YgdHx8dCBpbnN0YW5jZW9mIEJvb2xlYW58fHQgaW5zdGFuY2VvZiBOdW1iZXJ8fHQgaW5zdGFuY2VvZiBTdHJpbmd8fHQgaW5zdGFuY2VvZiBEYXRlfHx0IGluc3RhbmNlb2YgUmVnRXhwKXJldHVybiB0O2lmKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gZSYmZS5wdXNoKHQpLHQ7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpKXt2YXIgcj10O3JldHVybiBlJiZlLnB1c2goci5idWZmZXIpLHJ9aWYodCBpbnN0YW5jZW9mIHByKXJldHVybiBlJiZlLnB1c2godC5kYXRhLmJ1ZmZlciksdDtpZihBcnJheS5pc0FycmF5KHQpKXtmb3IodmFyIG49W10saT0wLG89dDtpPG8ubGVuZ3RoO2krPTEpe3ZhciBhPW9baV07bi5wdXNoKHlyKGEsZSkpO31yZXR1cm4gbn1pZihcIm9iamVjdFwiPT10eXBlb2YgdCl7dmFyIHM9dC5jb25zdHJ1Y3Rvcix1PXMuX2NsYXNzUmVnaXN0cnlLZXk7aWYoIXUpdGhyb3cgbmV3IEVycm9yKFwiY2FuJ3Qgc2VyaWFsaXplIG9iamVjdCBvZiB1bnJlZ2lzdGVyZWQgY2xhc3NcIik7dmFyIGw9e307aWYocy5zZXJpYWxpemUpbC5fc2VyaWFsaXplZD1zLnNlcmlhbGl6ZSh0LGUpO2Vsc2V7Zm9yKHZhciBwIGluIHQpaWYodC5oYXNPd25Qcm9wZXJ0eShwKSYmIShjclt1XS5vbWl0LmluZGV4T2YocCk+PTApKXt2YXIgYz10W3BdO2xbcF09Y3JbdV0uc2hhbGxvdy5pbmRleE9mKHApPj0wP2M6eXIoYyxlKTt9dCBpbnN0YW5jZW9mIEVycm9yJiYobC5tZXNzYWdlPXQubWVzc2FnZSk7fXJldHVybntuYW1lOnUscHJvcGVydGllczpsfX10aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCBzZXJpYWxpemUgb2JqZWN0IG9mIHR5cGUgXCIrdHlwZW9mIHQpfWZ1bmN0aW9uIGRyKHQpe2lmKG51bGw9PXR8fFwiYm9vbGVhblwiPT10eXBlb2YgdHx8XCJudW1iZXJcIj09dHlwZW9mIHR8fFwic3RyaW5nXCI9PXR5cGVvZiB0fHx0IGluc3RhbmNlb2YgQm9vbGVhbnx8dCBpbnN0YW5jZW9mIE51bWJlcnx8dCBpbnN0YW5jZW9mIFN0cmluZ3x8dCBpbnN0YW5jZW9mIERhdGV8fHQgaW5zdGFuY2VvZiBSZWdFeHB8fHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8QXJyYXlCdWZmZXIuaXNWaWV3KHQpfHx0IGluc3RhbmNlb2YgcHIpcmV0dXJuIHQ7aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIGRyKHQpfSk7aWYoXCJvYmplY3RcIj09dHlwZW9mIHQpe3ZhciBlPXQscj1lLm5hbWUsbj1lLnByb3BlcnRpZXM7aWYoIXIpdGhyb3cgbmV3IEVycm9yKFwiY2FuJ3QgZGVzZXJpYWxpemUgb2JqZWN0IG9mIGFub255bW91cyBjbGFzc1wiKTt2YXIgaT1jcltyXS5rbGFzcztpZighaSl0aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCBkZXNlcmlhbGl6ZSB1bnJlZ2lzdGVyZWQgY2xhc3MgXCIrcik7aWYoaS5kZXNlcmlhbGl6ZSlyZXR1cm4gaS5kZXNlcmlhbGl6ZShuLl9zZXJpYWxpemVkKTtmb3IodmFyIG89T2JqZWN0LmNyZWF0ZShpLnByb3RvdHlwZSksYT0wLHM9T2JqZWN0LmtleXMobik7YTxzLmxlbmd0aDthKz0xKXt2YXIgdT1zW2FdO29bdV09Y3Jbcl0uc2hhbGxvdy5pbmRleE9mKHUpPj0wP25bdV06ZHIoblt1XSk7fXJldHVybiBvfXRocm93IG5ldyBFcnJvcihcImNhbid0IGRlc2VyaWFsaXplIG9iamVjdCBvZiB0eXBlIFwiK3R5cGVvZiB0KX12YXIgdnI9ZnVuY3Rpb24oKXt0aGlzLmZpcnN0PSEwO307dnIucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0LGUpe3ZhciByPU1hdGguZmxvb3IodCk7cmV0dXJuIHRoaXMuZmlyc3Q/KHRoaXMuZmlyc3Q9ITEsdGhpcy5sYXN0SW50ZWdlclpvb209cix0aGlzLmxhc3RJbnRlZ2VyWm9vbVRpbWU9MCx0aGlzLmxhc3Rab29tPXQsdGhpcy5sYXN0Rmxvb3Jab29tPXIsITApOih0aGlzLmxhc3RGbG9vclpvb20+cj8odGhpcy5sYXN0SW50ZWdlclpvb209cisxLHRoaXMubGFzdEludGVnZXJab29tVGltZT1lKTp0aGlzLmxhc3RGbG9vclpvb208ciYmKHRoaXMubGFzdEludGVnZXJab29tPXIsdGhpcy5sYXN0SW50ZWdlclpvb21UaW1lPWUpLHQhPT10aGlzLmxhc3Rab29tJiYodGhpcy5sYXN0Wm9vbT10LHRoaXMubGFzdEZsb29yWm9vbT1yLCEwKSl9O3ZhciBtcj17XCJMYXRpbi0xIFN1cHBsZW1lbnRcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI4JiZ0PD0yNTV9LEFyYWJpYzpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTUzNiYmdDw9MTc5MX0sXCJBcmFiaWMgU3VwcGxlbWVudFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xODcyJiZ0PD0xOTE5fSxcIkFyYWJpYyBFeHRlbmRlZC1BXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTIyMDgmJnQ8PTIzMDN9LFwiSGFuZ3VsIEphbW9cIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NDM1MiYmdDw9NDYwN30sXCJVbmlmaWVkIENhbmFkaWFuIEFib3JpZ2luYWwgU3lsbGFiaWNzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTUxMjAmJnQ8PTU3NTl9LEtobWVyOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02MDE2JiZ0PD02MTQzfSxcIlVuaWZpZWQgQ2FuYWRpYW4gQWJvcmlnaW5hbCBTeWxsYWJpY3MgRXh0ZW5kZWRcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NjMyMCYmdDw9NjM5OX0sXCJHZW5lcmFsIFB1bmN0dWF0aW9uXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTgxOTImJnQ8PTgzMDN9LFwiTGV0dGVybGlrZSBTeW1ib2xzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTg0NDgmJnQ8PTg1Mjd9LFwiTnVtYmVyIEZvcm1zXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTg1MjgmJnQ8PTg1OTF9LFwiTWlzY2VsbGFuZW91cyBUZWNobmljYWxcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49ODk2MCYmdDw9OTIxNX0sXCJDb250cm9sIFBpY3R1cmVzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTkyMTYmJnQ8PTkyNzl9LFwiT3B0aWNhbCBDaGFyYWN0ZXIgUmVjb2duaXRpb25cIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49OTI4MCYmdDw9OTMxMX0sXCJFbmNsb3NlZCBBbHBoYW51bWVyaWNzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTkzMTImJnQ8PTk0NzF9LFwiR2VvbWV0cmljIFNoYXBlc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj05NjMyJiZ0PD05NzI3fSxcIk1pc2NlbGxhbmVvdXMgU3ltYm9sc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj05NzI4JiZ0PD05OTgzfSxcIk1pc2NlbGxhbmVvdXMgU3ltYm9scyBhbmQgQXJyb3dzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTExMDA4JiZ0PD0xMTI2M30sXCJDSksgUmFkaWNhbHMgU3VwcGxlbWVudFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMTkwNCYmdDw9MTIwMzF9LFwiS2FuZ3hpIFJhZGljYWxzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEyMDMyJiZ0PD0xMjI1NX0sXCJJZGVvZ3JhcGhpYyBEZXNjcmlwdGlvbiBDaGFyYWN0ZXJzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEyMjcyJiZ0PD0xMjI4N30sXCJDSksgU3ltYm9scyBhbmQgUHVuY3R1YXRpb25cIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTIyODgmJnQ8PTEyMzUxfSxIaXJhZ2FuYTpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTIzNTImJnQ8PTEyNDQ3fSxLYXRha2FuYTpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI0NDgmJnQ8PTEyNTQzfSxCb3BvbW9mbzpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI1NDQmJnQ8PTEyNTkxfSxcIkhhbmd1bCBDb21wYXRpYmlsaXR5IEphbW9cIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI1OTImJnQ8PTEyNjg3fSxLYW5idW46ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEyNjg4JiZ0PD0xMjcwM30sXCJCb3BvbW9mbyBFeHRlbmRlZFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjcwNCYmdDw9MTI3MzV9LFwiQ0pLIFN0cm9rZXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI3MzYmJnQ8PTEyNzgzfSxcIkthdGFrYW5hIFBob25ldGljIEV4dGVuc2lvbnNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI3ODQmJnQ8PTEyNzk5fSxcIkVuY2xvc2VkIENKSyBMZXR0ZXJzIGFuZCBNb250aHNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI4MDAmJnQ8PTEzMDU1fSxcIkNKSyBDb21wYXRpYmlsaXR5XCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEzMDU2JiZ0PD0xMzMxMX0sXCJDSksgVW5pZmllZCBJZGVvZ3JhcGhzIEV4dGVuc2lvbiBBXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEzMzEyJiZ0PD0xOTkwM30sXCJZaWppbmcgSGV4YWdyYW0gU3ltYm9sc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xOTkwNCYmdDw9MTk5Njd9LFwiQ0pLIFVuaWZpZWQgSWRlb2dyYXBoc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xOTk2OCYmdDw9NDA5NTl9LFwiWWkgU3lsbGFibGVzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTQwOTYwJiZ0PD00MjEyN30sXCJZaSBSYWRpY2Fsc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj00MjEyOCYmdDw9NDIxOTF9LFwiSGFuZ3VsIEphbW8gRXh0ZW5kZWQtQVwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj00MzM2MCYmdDw9NDMzOTF9LFwiSGFuZ3VsIFN5bGxhYmxlc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj00NDAzMiYmdDw9NTUyMTV9LFwiSGFuZ3VsIEphbW8gRXh0ZW5kZWQtQlwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj01NTIxNiYmdDw9NTUyOTV9LFwiUHJpdmF0ZSBVc2UgQXJlYVwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj01NzM0NCYmdDw9NjM3NDN9LFwiQ0pLIENvbXBhdGliaWxpdHkgSWRlb2dyYXBoc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02Mzc0NCYmdDw9NjQyNTV9LFwiQXJhYmljIFByZXNlbnRhdGlvbiBGb3Jtcy1BXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTY0MzM2JiZ0PD02NTAyM30sXCJWZXJ0aWNhbCBGb3Jtc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02NTA0MCYmdDw9NjUwNTV9LFwiQ0pLIENvbXBhdGliaWxpdHkgRm9ybXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NjUwNzImJnQ8PTY1MTAzfSxcIlNtYWxsIEZvcm0gVmFyaWFudHNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NjUxMDQmJnQ8PTY1MTM1fSxcIkFyYWJpYyBQcmVzZW50YXRpb24gRm9ybXMtQlwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02NTEzNiYmdDw9NjUyNzl9LFwiSGFsZndpZHRoIGFuZCBGdWxsd2lkdGggRm9ybXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NjUyODAmJnQ8PTY1NTE5fX07ZnVuY3Rpb24gZ3IodCl7Zm9yKHZhciBlPTAscj10O2U8ci5sZW5ndGg7ZSs9MSl7aWYoYnIocltlXS5jaGFyQ29kZUF0KDApKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiB4cih0KXtyZXR1cm4hbXIuQXJhYmljKHQpJiYoIW1yW1wiQXJhYmljIFN1cHBsZW1lbnRcIl0odCkmJighbXJbXCJBcmFiaWMgRXh0ZW5kZWQtQVwiXSh0KSYmKCFtcltcIkFyYWJpYyBQcmVzZW50YXRpb24gRm9ybXMtQVwiXSh0KSYmIW1yW1wiQXJhYmljIFByZXNlbnRhdGlvbiBGb3Jtcy1CXCJdKHQpKSkpfWZ1bmN0aW9uIGJyKHQpe3JldHVybiA3NDY9PT10fHw3NDc9PT10fHwhKHQ8NDM1MikmJighIW1yW1wiQm9wb21vZm8gRXh0ZW5kZWRcIl0odCl8fCghIW1yLkJvcG9tb2ZvKHQpfHwoISghbXJbXCJDSksgQ29tcGF0aWJpbGl0eSBGb3Jtc1wiXSh0KXx8dD49NjUwOTcmJnQ8PTY1MTAzKXx8KCEhbXJbXCJDSksgQ29tcGF0aWJpbGl0eSBJZGVvZ3JhcGhzXCJdKHQpfHwoISFtcltcIkNKSyBDb21wYXRpYmlsaXR5XCJdKHQpfHwoISFtcltcIkNKSyBSYWRpY2FscyBTdXBwbGVtZW50XCJdKHQpfHwoISFtcltcIkNKSyBTdHJva2VzXCJdKHQpfHwoISghbXJbXCJDSksgU3ltYm9scyBhbmQgUHVuY3R1YXRpb25cIl0odCl8fHQ+PTEyMjk2JiZ0PD0xMjMwNXx8dD49MTIzMDgmJnQ8PTEyMzE5fHwxMjMzNj09PXQpfHwoISFtcltcIkNKSyBVbmlmaWVkIElkZW9ncmFwaHMgRXh0ZW5zaW9uIEFcIl0odCl8fCghIW1yW1wiQ0pLIFVuaWZpZWQgSWRlb2dyYXBoc1wiXSh0KXx8KCEhbXJbXCJFbmNsb3NlZCBDSksgTGV0dGVycyBhbmQgTW9udGhzXCJdKHQpfHwoISFtcltcIkhhbmd1bCBDb21wYXRpYmlsaXR5IEphbW9cIl0odCl8fCghIW1yW1wiSGFuZ3VsIEphbW8gRXh0ZW5kZWQtQVwiXSh0KXx8KCEhbXJbXCJIYW5ndWwgSmFtbyBFeHRlbmRlZC1CXCJdKHQpfHwoISFtcltcIkhhbmd1bCBKYW1vXCJdKHQpfHwoISFtcltcIkhhbmd1bCBTeWxsYWJsZXNcIl0odCl8fCghIW1yLkhpcmFnYW5hKHQpfHwoISFtcltcIklkZW9ncmFwaGljIERlc2NyaXB0aW9uIENoYXJhY3RlcnNcIl0odCl8fCghIW1yLkthbmJ1bih0KXx8KCEhbXJbXCJLYW5neGkgUmFkaWNhbHNcIl0odCl8fCghIW1yW1wiS2F0YWthbmEgUGhvbmV0aWMgRXh0ZW5zaW9uc1wiXSh0KXx8KCEoIW1yLkthdGFrYW5hKHQpfHwxMjU0MD09PXQpfHwoISghbXJbXCJIYWxmd2lkdGggYW5kIEZ1bGx3aWR0aCBGb3Jtc1wiXSh0KXx8NjUyODg9PT10fHw2NTI4OT09PXR8fDY1MjkzPT09dHx8dD49NjUzMDYmJnQ8PTY1MzEwfHw2NTMzOT09PXR8fDY1MzQxPT09dHx8NjUzNDM9PT10fHx0Pj02NTM3MSYmdDw9NjU1MDN8fDY1NTA3PT09dHx8dD49NjU1MTImJnQ8PTY1NTE5KXx8KCEoIW1yW1wiU21hbGwgRm9ybSBWYXJpYW50c1wiXSh0KXx8dD49NjUxMTImJnQ8PTY1MTE4fHx0Pj02NTEyMyYmdDw9NjUxMjYpfHwoISFtcltcIlVuaWZpZWQgQ2FuYWRpYW4gQWJvcmlnaW5hbCBTeWxsYWJpY3NcIl0odCl8fCghIW1yW1wiVW5pZmllZCBDYW5hZGlhbiBBYm9yaWdpbmFsIFN5bGxhYmljcyBFeHRlbmRlZFwiXSh0KXx8KCEhbXJbXCJWZXJ0aWNhbCBGb3Jtc1wiXSh0KXx8KCEhbXJbXCJZaWppbmcgSGV4YWdyYW0gU3ltYm9sc1wiXSh0KXx8KCEhbXJbXCJZaSBTeWxsYWJsZXNcIl0odCl8fCEhbXJbXCJZaSBSYWRpY2Fsc1wiXSh0KSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpfWZ1bmN0aW9uIHdyKHQpe3JldHVybiEoYnIodCl8fGZ1bmN0aW9uKHQpe3JldHVybiEhKG1yW1wiTGF0aW4tMSBTdXBwbGVtZW50XCJdKHQpJiYoMTY3PT09dHx8MTY5PT09dHx8MTc0PT09dHx8MTc3PT09dHx8MTg4PT09dHx8MTg5PT09dHx8MTkwPT09dHx8MjE1PT09dHx8MjQ3PT09dCl8fG1yW1wiR2VuZXJhbCBQdW5jdHVhdGlvblwiXSh0KSYmKDgyMTQ9PT10fHw4MjI0PT09dHx8ODIyNT09PXR8fDgyNDA9PT10fHw4MjQxPT09dHx8ODI1MT09PXR8fDgyNTI9PT10fHw4MjU4PT09dHx8ODI2Mz09PXR8fDgyNjQ9PT10fHw4MjY1PT09dHx8ODI3Mz09PXQpfHxtcltcIkxldHRlcmxpa2UgU3ltYm9sc1wiXSh0KXx8bXJbXCJOdW1iZXIgRm9ybXNcIl0odCl8fG1yW1wiTWlzY2VsbGFuZW91cyBUZWNobmljYWxcIl0odCkmJih0Pj04OTYwJiZ0PD04OTY3fHx0Pj04OTcyJiZ0PD04OTkxfHx0Pj04OTk2JiZ0PD05ZTN8fDkwMDM9PT10fHx0Pj05MDg1JiZ0PD05MTE0fHx0Pj05MTUwJiZ0PD05MTY1fHw5MTY3PT09dHx8dD49OTE2OSYmdDw9OTE3OXx8dD49OTE4NiYmdDw9OTIxNSl8fG1yW1wiQ29udHJvbCBQaWN0dXJlc1wiXSh0KSYmOTI1MSE9PXR8fG1yW1wiT3B0aWNhbCBDaGFyYWN0ZXIgUmVjb2duaXRpb25cIl0odCl8fG1yW1wiRW5jbG9zZWQgQWxwaGFudW1lcmljc1wiXSh0KXx8bXJbXCJHZW9tZXRyaWMgU2hhcGVzXCJdKHQpfHxtcltcIk1pc2NlbGxhbmVvdXMgU3ltYm9sc1wiXSh0KSYmISh0Pj05NzU0JiZ0PD05NzU5KXx8bXJbXCJNaXNjZWxsYW5lb3VzIFN5bWJvbHMgYW5kIEFycm93c1wiXSh0KSYmKHQ+PTExMDI2JiZ0PD0xMTA1NXx8dD49MTEwODgmJnQ8PTExMDk3fHx0Pj0xMTE5MiYmdDw9MTEyNDMpfHxtcltcIkNKSyBTeW1ib2xzIGFuZCBQdW5jdHVhdGlvblwiXSh0KXx8bXIuS2F0YWthbmEodCl8fG1yW1wiUHJpdmF0ZSBVc2UgQXJlYVwiXSh0KXx8bXJbXCJDSksgQ29tcGF0aWJpbGl0eSBGb3Jtc1wiXSh0KXx8bXJbXCJTbWFsbCBGb3JtIFZhcmlhbnRzXCJdKHQpfHxtcltcIkhhbGZ3aWR0aCBhbmQgRnVsbHdpZHRoIEZvcm1zXCJdKHQpfHw4NzM0PT09dHx8ODc1Nj09PXR8fDg3NTc9PT10fHx0Pj05OTg0JiZ0PD0xMDA4N3x8dD49MTAxMDImJnQ8PTEwMTMxfHw2NTUzMj09PXR8fDY1NTMzPT09dCl9KHQpKX1mdW5jdGlvbiBfcih0LGUpe3JldHVybiEoIWUmJih0Pj0xNDI0JiZ0PD0yMzAzfHxtcltcIkFyYWJpYyBQcmVzZW50YXRpb24gRm9ybXMtQVwiXSh0KXx8bXJbXCJBcmFiaWMgUHJlc2VudGF0aW9uIEZvcm1zLUJcIl0odCkpKSYmISh0Pj0yMzA0JiZ0PD0zNTgzfHx0Pj0zODQwJiZ0PD00MjU1fHxtci5LaG1lcih0KSl9dmFyIEFyLGtyPSExLHpyPW51bGwsU3I9ITEsTXI9bmV3IEksVnI9e2FwcGx5QXJhYmljU2hhcGluZzpudWxsLHByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dDpudWxsLGlzTG9hZGVkOmZ1bmN0aW9uKCl7cmV0dXJuIFNyfHxudWxsIT1Wci5hcHBseUFyYWJpY1NoYXBpbmd9fSxCcj1mdW5jdGlvbih0LGUpe3RoaXMuem9vbT10LGU/KHRoaXMubm93PWUubm93LHRoaXMuZmFkZUR1cmF0aW9uPWUuZmFkZUR1cmF0aW9uLHRoaXMuem9vbUhpc3Rvcnk9ZS56b29tSGlzdG9yeSx0aGlzLnRyYW5zaXRpb249ZS50cmFuc2l0aW9uKToodGhpcy5ub3c9MCx0aGlzLmZhZGVEdXJhdGlvbj0wLHRoaXMuem9vbUhpc3Rvcnk9bmV3IHZyLHRoaXMudHJhbnNpdGlvbj17fSk7fTtCci5wcm90b3R5cGUuaXNTdXBwb3J0ZWRTY3JpcHQ9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj10O3I8bi5sZW5ndGg7cis9MSlpZighX3IobltyXS5jaGFyQ29kZUF0KDApLGUpKXJldHVybiExO3JldHVybiEwfSh0LFZyLmlzTG9hZGVkKCkpfSxCci5wcm90b3R5cGUuY3Jvc3NGYWRpbmdGYWN0b3I9ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMuZmFkZUR1cmF0aW9uPzE6TWF0aC5taW4oKHRoaXMubm93LXRoaXMuem9vbUhpc3RvcnkubGFzdEludGVnZXJab29tVGltZSkvdGhpcy5mYWRlRHVyYXRpb24sMSl9O3ZhciBDcj1mdW5jdGlvbih0LGUpe3RoaXMucHJvcGVydHk9dCx0aGlzLnZhbHVlPWUsdGhpcy5leHByZXNzaW9uPVNlKHZvaWQgMD09PWU/dC5zcGVjaWZpY2F0aW9uLmRlZmF1bHQ6ZSx0LnNwZWNpZmljYXRpb24pO307Q3IucHJvdG90eXBlLmlzRGF0YURyaXZlbj1mdW5jdGlvbigpe3JldHVyblwic291cmNlXCI9PT10aGlzLmV4cHJlc3Npb24ua2luZHx8XCJjb21wb3NpdGVcIj09PXRoaXMuZXhwcmVzc2lvbi5raW5kfSxDci5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5wcm9wZXJ0eS5wb3NzaWJseUV2YWx1YXRlKHRoaXMsdCl9O3ZhciBJcj1mdW5jdGlvbih0KXt0aGlzLnByb3BlcnR5PXQsdGhpcy52YWx1ZT1uZXcgQ3IodCx2b2lkIDApO307SXIucHJvdG90eXBlLnRyYW5zaXRpb25lZD1mdW5jdGlvbih0LGUpe3JldHVybiBuZXcgRnIodGhpcy5wcm9wZXJ0eSx0aGlzLnZhbHVlLGUsaCh7fSx0LnRyYW5zaXRpb24sdGhpcy50cmFuc2l0aW9uKSx0Lm5vdyl9LElyLnByb3RvdHlwZS51bnRyYW5zaXRpb25lZD1mdW5jdGlvbigpe3JldHVybiBuZXcgRnIodGhpcy5wcm9wZXJ0eSx0aGlzLnZhbHVlLG51bGwse30sMCl9O3ZhciBFcj1mdW5jdGlvbih0KXt0aGlzLl9wcm9wZXJ0aWVzPXQsdGhpcy5fdmFsdWVzPU9iamVjdC5jcmVhdGUodC5kZWZhdWx0VHJhbnNpdGlvbmFibGVQcm9wZXJ0eVZhbHVlcyk7fTtFci5wcm90b3R5cGUuZ2V0VmFsdWU9ZnVuY3Rpb24odCl7cmV0dXJuIGcodGhpcy5fdmFsdWVzW3RdLnZhbHVlLnZhbHVlKX0sRXIucHJvdG90eXBlLnNldFZhbHVlPWZ1bmN0aW9uKHQsZSl7dGhpcy5fdmFsdWVzLmhhc093blByb3BlcnR5KHQpfHwodGhpcy5fdmFsdWVzW3RdPW5ldyBJcih0aGlzLl92YWx1ZXNbdF0ucHJvcGVydHkpKSx0aGlzLl92YWx1ZXNbdF0udmFsdWU9bmV3IENyKHRoaXMuX3ZhbHVlc1t0XS5wcm9wZXJ0eSxudWxsPT09ZT92b2lkIDA6ZyhlKSk7fSxFci5wcm90b3R5cGUuZ2V0VHJhbnNpdGlvbj1mdW5jdGlvbih0KXtyZXR1cm4gZyh0aGlzLl92YWx1ZXNbdF0udHJhbnNpdGlvbil9LEVyLnByb3RvdHlwZS5zZXRUcmFuc2l0aW9uPWZ1bmN0aW9uKHQsZSl7dGhpcy5fdmFsdWVzLmhhc093blByb3BlcnR5KHQpfHwodGhpcy5fdmFsdWVzW3RdPW5ldyBJcih0aGlzLl92YWx1ZXNbdF0ucHJvcGVydHkpKSx0aGlzLl92YWx1ZXNbdF0udHJhbnNpdGlvbj1nKGUpfHx2b2lkIDA7fSxFci5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PXt9LGU9MCxyPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7ZTxyLmxlbmd0aDtlKz0xKXt2YXIgbj1yW2VdLGk9dGhpcy5nZXRWYWx1ZShuKTt2b2lkIDAhPT1pJiYodFtuXT1pKTt2YXIgbz10aGlzLmdldFRyYW5zaXRpb24obik7dm9pZCAwIT09byYmKHRbbitcIi10cmFuc2l0aW9uXCJdPW8pO31yZXR1cm4gdH0sRXIucHJvdG90eXBlLnRyYW5zaXRpb25lZD1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj1uZXcgUHIodGhpcy5fcHJvcGVydGllcyksbj0wLGk9T2JqZWN0LmtleXModGhpcy5fdmFsdWVzKTtuPGkubGVuZ3RoO24rPTEpe3ZhciBvPWlbbl07ci5fdmFsdWVzW29dPXRoaXMuX3ZhbHVlc1tvXS50cmFuc2l0aW9uZWQodCxlLl92YWx1ZXNbb10pO31yZXR1cm4gcn0sRXIucHJvdG90eXBlLnVudHJhbnNpdGlvbmVkPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PW5ldyBQcih0aGlzLl9wcm9wZXJ0aWVzKSxlPTAscj1PYmplY3Qua2V5cyh0aGlzLl92YWx1ZXMpO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXTt0Ll92YWx1ZXNbbl09dGhpcy5fdmFsdWVzW25dLnVudHJhbnNpdGlvbmVkKCk7fXJldHVybiB0fTt2YXIgRnI9ZnVuY3Rpb24odCxlLHIsbixpKXt0aGlzLnByb3BlcnR5PXQsdGhpcy52YWx1ZT1lLHRoaXMuYmVnaW49aStuLmRlbGF5fHwwLHRoaXMuZW5kPXRoaXMuYmVnaW4rbi5kdXJhdGlvbnx8MCx0LnNwZWNpZmljYXRpb24udHJhbnNpdGlvbiYmKG4uZGVsYXl8fG4uZHVyYXRpb24pJiYodGhpcy5wcmlvcj1yKTt9O0ZyLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKHQpe3ZhciBlPXQubm93fHwwLHI9dGhpcy52YWx1ZS5wb3NzaWJseUV2YWx1YXRlKHQpLG49dGhpcy5wcmlvcjtpZihuKXtpZihlPnRoaXMuZW5kKXJldHVybiB0aGlzLnByaW9yPW51bGwscjtpZih0aGlzLnZhbHVlLmlzRGF0YURyaXZlbigpKXJldHVybiB0aGlzLnByaW9yPW51bGwscjtpZihlPHRoaXMuYmVnaW4pcmV0dXJuIG4ucG9zc2libHlFdmFsdWF0ZSh0KTt2YXIgaT0oZS10aGlzLmJlZ2luKS8odGhpcy5lbmQtdGhpcy5iZWdpbik7cmV0dXJuIHRoaXMucHJvcGVydHkuaW50ZXJwb2xhdGUobi5wb3NzaWJseUV2YWx1YXRlKHQpLHIsZnVuY3Rpb24odCl7aWYodDw9MClyZXR1cm4gMDtpZih0Pj0xKXJldHVybiAxO3ZhciBlPXQqdCxyPWUqdDtyZXR1cm4gNCoodDwuNT9yOjMqKHQtZSkrci0uNzUpfShpKSl9cmV0dXJuIHJ9O3ZhciBQcj1mdW5jdGlvbih0KXt0aGlzLl9wcm9wZXJ0aWVzPXQsdGhpcy5fdmFsdWVzPU9iamVjdC5jcmVhdGUodC5kZWZhdWx0VHJhbnNpdGlvbmluZ1Byb3BlcnR5VmFsdWVzKTt9O1ByLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1uZXcgTHIodGhpcy5fcHJvcGVydGllcykscj0wLG49T2JqZWN0LmtleXModGhpcy5fdmFsdWVzKTtyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl07ZS5fdmFsdWVzW2ldPXRoaXMuX3ZhbHVlc1tpXS5wb3NzaWJseUV2YWx1YXRlKHQpO31yZXR1cm4gZX0sUHIucHJvdG90eXBlLmhhc1RyYW5zaXRpb249ZnVuY3Rpb24oKXtmb3IodmFyIHQ9MCxlPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7dDxlLmxlbmd0aDt0Kz0xKXt2YXIgcj1lW3RdO2lmKHRoaXMuX3ZhbHVlc1tyXS5wcmlvcilyZXR1cm4hMH1yZXR1cm4hMX07dmFyIFRyPWZ1bmN0aW9uKHQpe3RoaXMuX3Byb3BlcnRpZXM9dCx0aGlzLl92YWx1ZXM9T2JqZWN0LmNyZWF0ZSh0LmRlZmF1bHRQcm9wZXJ0eVZhbHVlcyk7fTtUci5wcm90b3R5cGUuZ2V0VmFsdWU9ZnVuY3Rpb24odCl7cmV0dXJuIGcodGhpcy5fdmFsdWVzW3RdLnZhbHVlKX0sVHIucHJvdG90eXBlLnNldFZhbHVlPWZ1bmN0aW9uKHQsZSl7dGhpcy5fdmFsdWVzW3RdPW5ldyBDcih0aGlzLl92YWx1ZXNbdF0ucHJvcGVydHksbnVsbD09PWU/dm9pZCAwOmcoZSkpO30sVHIucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe2Zvcih2YXIgdD17fSxlPTAscj1PYmplY3Qua2V5cyh0aGlzLl92YWx1ZXMpO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPXRoaXMuZ2V0VmFsdWUobik7dm9pZCAwIT09aSYmKHRbbl09aSk7fXJldHVybiB0fSxUci5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0KXtmb3IodmFyIGU9bmV3IExyKHRoaXMuX3Byb3BlcnRpZXMpLHI9MCxuPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdO2UuX3ZhbHVlc1tpXT10aGlzLl92YWx1ZXNbaV0ucG9zc2libHlFdmFsdWF0ZSh0KTt9cmV0dXJuIGV9O3ZhciBPcj1mdW5jdGlvbih0LGUscil7dGhpcy5wcm9wZXJ0eT10LHRoaXMudmFsdWU9ZSx0aGlzLmdsb2JhbHM9cjt9O09yLnByb3RvdHlwZS5pc0NvbnN0YW50PWZ1bmN0aW9uKCl7cmV0dXJuXCJjb25zdGFudFwiPT09dGhpcy52YWx1ZS5raW5kfSxPci5wcm90b3R5cGUuY29uc3RhbnRPcj1mdW5jdGlvbih0KXtyZXR1cm5cImNvbnN0YW50XCI9PT10aGlzLnZhbHVlLmtpbmQ/dGhpcy52YWx1ZS52YWx1ZTp0fSxPci5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucHJvcGVydHkuZXZhbHVhdGUodGhpcy52YWx1ZSx0aGlzLmdsb2JhbHMsdCl9O3ZhciBMcj1mdW5jdGlvbih0KXt0aGlzLl9wcm9wZXJ0aWVzPXQsdGhpcy5fdmFsdWVzPU9iamVjdC5jcmVhdGUodC5kZWZhdWx0UG9zc2libHlFdmFsdWF0ZWRWYWx1ZXMpO307THIucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fdmFsdWVzW3RdfTt2YXIganI9ZnVuY3Rpb24odCl7dGhpcy5zcGVjaWZpY2F0aW9uPXQ7fTtqci5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0LmV4cHJlc3Npb24uZXZhbHVhdGUoZSl9LGpyLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbih0LGUscil7dmFyIG49X3RbdGhpcy5zcGVjaWZpY2F0aW9uLnR5cGVdO3JldHVybiBuP24odCxlLHIpOnR9O3ZhciBxcj1mdW5jdGlvbih0KXt0aGlzLnNwZWNpZmljYXRpb249dDt9O3FyLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuXCJjb25zdGFudFwiPT09dC5leHByZXNzaW9uLmtpbmR8fFwiY2FtZXJhXCI9PT10LmV4cHJlc3Npb24ua2luZD9uZXcgT3IodGhpcyx7a2luZDpcImNvbnN0YW50XCIsdmFsdWU6dC5leHByZXNzaW9uLmV2YWx1YXRlKGUpfSxlKTpuZXcgT3IodGhpcyx0LmV4cHJlc3Npb24sZSl9LHFyLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbih0LGUscil7aWYoXCJjb25zdGFudFwiIT09dC52YWx1ZS5raW5kfHxcImNvbnN0YW50XCIhPT1lLnZhbHVlLmtpbmQpcmV0dXJuIHQ7aWYodm9pZCAwPT09dC52YWx1ZS52YWx1ZXx8dm9pZCAwPT09ZS52YWx1ZS52YWx1ZSlyZXR1cm4gbmV3IE9yKHRoaXMse2tpbmQ6XCJjb25zdGFudFwiLHZhbHVlOnZvaWQgMH0sdC5nbG9iYWxzKTt2YXIgbj1fdFt0aGlzLnNwZWNpZmljYXRpb24udHlwZV07cmV0dXJuIG4/bmV3IE9yKHRoaXMse2tpbmQ6XCJjb25zdGFudFwiLHZhbHVlOm4odC52YWx1ZS52YWx1ZSxlLnZhbHVlLnZhbHVlLHIpfSx0Lmdsb2JhbHMpOnR9LHFyLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0LGUscil7cmV0dXJuXCJjb25zdGFudFwiPT09dC5raW5kP3QudmFsdWU6dC5ldmFsdWF0ZShlLHIpfTt2YXIgUnI9ZnVuY3Rpb24odCl7dGhpcy5zcGVjaWZpY2F0aW9uPXQ7fTtSci5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0LGUpe2lmKHZvaWQgMCE9PXQudmFsdWUpe2lmKFwiY29uc3RhbnRcIj09PXQuZXhwcmVzc2lvbi5raW5kKXt2YXIgcj10LmV4cHJlc3Npb24uZXZhbHVhdGUoZSk7cmV0dXJuIHRoaXMuX2NhbGN1bGF0ZShyLHIscixlKX1yZXR1cm4gdGhpcy5fY2FsY3VsYXRlKHQuZXhwcmVzc2lvbi5ldmFsdWF0ZShuZXcgQnIoTWF0aC5mbG9vcihlLnpvb20tMSksZSkpLHQuZXhwcmVzc2lvbi5ldmFsdWF0ZShuZXcgQnIoTWF0aC5mbG9vcihlLnpvb20pLGUpKSx0LmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IEJyKE1hdGguZmxvb3IoZS56b29tKzEpLGUpKSxlKX19LFJyLnByb3RvdHlwZS5fY2FsY3VsYXRlPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPW4uem9vbSxvPWktTWF0aC5mbG9vcihpKSxhPW4uY3Jvc3NGYWRpbmdGYWN0b3IoKTtyZXR1cm4gaT5uLnpvb21IaXN0b3J5Lmxhc3RJbnRlZ2VyWm9vbT97ZnJvbTp0LHRvOmUsZnJvbVNjYWxlOjIsdG9TY2FsZToxLHQ6bysoMS1vKSphfTp7ZnJvbTpyLHRvOmUsZnJvbVNjYWxlOi41LHRvU2NhbGU6MSx0OjEtKDEtYSkqb319LFJyLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdH07dmFyIFVyPWZ1bmN0aW9uKHQpe3RoaXMuc3BlY2lmaWNhdGlvbj10O307VXIucHJvdG90eXBlLnBvc3NpYmx5RXZhbHVhdGU9ZnVuY3Rpb24odCxlKXtyZXR1cm4hIXQuZXhwcmVzc2lvbi5ldmFsdWF0ZShlKX0sVXIucHJvdG90eXBlLmludGVycG9sYXRlPWZ1bmN0aW9uKCl7cmV0dXJuITF9O3ZhciBEcj1mdW5jdGlvbih0KXtmb3IodmFyIGUgaW4gdGhpcy5wcm9wZXJ0aWVzPXQsdGhpcy5kZWZhdWx0UHJvcGVydHlWYWx1ZXM9e30sdGhpcy5kZWZhdWx0VHJhbnNpdGlvbmFibGVQcm9wZXJ0eVZhbHVlcz17fSx0aGlzLmRlZmF1bHRUcmFuc2l0aW9uaW5nUHJvcGVydHlWYWx1ZXM9e30sdGhpcy5kZWZhdWx0UG9zc2libHlFdmFsdWF0ZWRWYWx1ZXM9e30sdCl7dmFyIHI9dFtlXSxuPXRoaXMuZGVmYXVsdFByb3BlcnR5VmFsdWVzW2VdPW5ldyBDcihyLHZvaWQgMCksaT10aGlzLmRlZmF1bHRUcmFuc2l0aW9uYWJsZVByb3BlcnR5VmFsdWVzW2VdPW5ldyBJcihyKTt0aGlzLmRlZmF1bHRUcmFuc2l0aW9uaW5nUHJvcGVydHlWYWx1ZXNbZV09aS51bnRyYW5zaXRpb25lZCgpLHRoaXMuZGVmYXVsdFBvc3NpYmx5RXZhbHVhdGVkVmFsdWVzW2VdPW4ucG9zc2libHlFdmFsdWF0ZSh7fSk7fX07aHIoXCJEYXRhRHJpdmVuUHJvcGVydHlcIixxciksaHIoXCJEYXRhQ29uc3RhbnRQcm9wZXJ0eVwiLGpyKSxocihcIkNyb3NzRmFkZWRQcm9wZXJ0eVwiLFJyKSxocihcIkNvbG9yUmFtcFByb3BlcnR5XCIsVXIpO3ZhciBOcj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7Zm9yKHZhciBuIGluIHQuY2FsbCh0aGlzKSx0aGlzLmlkPWUuaWQsdGhpcy5tZXRhZGF0YT1lLm1ldGFkYXRhLHRoaXMudHlwZT1lLnR5cGUsdGhpcy5taW56b29tPWUubWluem9vbSx0aGlzLm1heHpvb209ZS5tYXh6b29tLHRoaXMudmlzaWJpbGl0eT1cInZpc2libGVcIixcImJhY2tncm91bmRcIiE9PWUudHlwZSYmKHRoaXMuc291cmNlPWUuc291cmNlLHRoaXMuc291cmNlTGF5ZXI9ZVtcInNvdXJjZS1sYXllclwiXSx0aGlzLmZpbHRlcj1lLmZpbHRlciksdGhpcy5fZmVhdHVyZUZpbHRlcj1mdW5jdGlvbigpe3JldHVybiEwfSxyLmxheW91dCYmKHRoaXMuX3VuZXZhbHVhdGVkTGF5b3V0PW5ldyBUcihyLmxheW91dCkpLHRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQ9bmV3IEVyKHIucGFpbnQpLGUucGFpbnQpdGhpcy5zZXRQYWludFByb3BlcnR5KG4sZS5wYWludFtuXSx7dmFsaWRhdGU6ITF9KTtmb3IodmFyIGkgaW4gZS5sYXlvdXQpdGhpcy5zZXRMYXlvdXRQcm9wZXJ0eShpLGUubGF5b3V0W2ldLHt2YWxpZGF0ZTohMX0pO3RoaXMuX3RyYW5zaXRpb25pbmdQYWludD10aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LnVudHJhbnNpdGlvbmVkKCk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbih0KXtyZXR1cm5cInZpc2liaWxpdHlcIj09PXQ/dGhpcy52aXNpYmlsaXR5OnRoaXMuX3VuZXZhbHVhdGVkTGF5b3V0LmdldFZhbHVlKHQpfSxlLnByb3RvdHlwZS5zZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbih0LGUscil7aWYobnVsbCE9ZSl7dmFyIG49XCJsYXllcnMuXCIrdGhpcy5pZCtcIi5sYXlvdXQuXCIrdDtpZih0aGlzLl92YWxpZGF0ZShvcixuLHQsZSxyKSlyZXR1cm59XCJ2aXNpYmlsaXR5XCIhPT10P3RoaXMuX3VuZXZhbHVhdGVkTGF5b3V0LnNldFZhbHVlKHQsZSk6dGhpcy52aXNpYmlsaXR5PVwibm9uZVwiPT09ZT9lOlwidmlzaWJsZVwiO30sZS5wcm90b3R5cGUuZ2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbih0KXtyZXR1cm4gZCh0LFwiLXRyYW5zaXRpb25cIik/dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5nZXRUcmFuc2l0aW9uKHQuc2xpY2UoMCwtXCItdHJhbnNpdGlvblwiLmxlbmd0aCkpOnRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQuZ2V0VmFsdWUodCl9LGUucHJvdG90eXBlLnNldFBhaW50UHJvcGVydHk9ZnVuY3Rpb24odCxlLHIpe2lmKG51bGwhPWUpe3ZhciBuPVwibGF5ZXJzLlwiK3RoaXMuaWQrXCIucGFpbnQuXCIrdDtpZih0aGlzLl92YWxpZGF0ZShpcixuLHQsZSxyKSlyZXR1cm59ZCh0LFwiLXRyYW5zaXRpb25cIik/dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5zZXRUcmFuc2l0aW9uKHQuc2xpY2UoMCwtXCItdHJhbnNpdGlvblwiLmxlbmd0aCksZXx8dm9pZCAwKTp0aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LnNldFZhbHVlKHQsZSk7fSxlLnByb3RvdHlwZS5pc0hpZGRlbj1mdW5jdGlvbih0KXtyZXR1cm4hISh0aGlzLm1pbnpvb20mJnQ8dGhpcy5taW56b29tKXx8KCEhKHRoaXMubWF4em9vbSYmdD49dGhpcy5tYXh6b29tKXx8XCJub25lXCI9PT10aGlzLnZpc2liaWxpdHkpfSxlLnByb3RvdHlwZS51cGRhdGVUcmFuc2l0aW9ucz1mdW5jdGlvbih0KXt0aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQ9dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC50cmFuc2l0aW9uZWQodCx0aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQpO30sZS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQuaGFzVHJhbnNpdGlvbigpfSxlLnByb3RvdHlwZS5yZWNhbGN1bGF0ZT1mdW5jdGlvbih0KXt0aGlzLl91bmV2YWx1YXRlZExheW91dCYmKHRoaXMubGF5b3V0PXRoaXMuX3VuZXZhbHVhdGVkTGF5b3V0LnBvc3NpYmx5RXZhbHVhdGUodCkpLHRoaXMucGFpbnQ9dGhpcy5fdHJhbnNpdGlvbmluZ1BhaW50LnBvc3NpYmx5RXZhbHVhdGUodCk7fSxlLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD17aWQ6dGhpcy5pZCx0eXBlOnRoaXMudHlwZSxzb3VyY2U6dGhpcy5zb3VyY2UsXCJzb3VyY2UtbGF5ZXJcIjp0aGlzLnNvdXJjZUxheWVyLG1ldGFkYXRhOnRoaXMubWV0YWRhdGEsbWluem9vbTp0aGlzLm1pbnpvb20sbWF4em9vbTp0aGlzLm1heHpvb20sZmlsdGVyOnRoaXMuZmlsdGVyLGxheW91dDp0aGlzLl91bmV2YWx1YXRlZExheW91dCYmdGhpcy5fdW5ldmFsdWF0ZWRMYXlvdXQuc2VyaWFsaXplKCkscGFpbnQ6dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludCYmdGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5zZXJpYWxpemUoKX07cmV0dXJuXCJub25lXCI9PT10aGlzLnZpc2liaWxpdHkmJih0LmxheW91dD10LmxheW91dHx8e30sdC5sYXlvdXQudmlzaWJpbGl0eT1cIm5vbmVcIiksbSh0LGZ1bmN0aW9uKHQsZSl7cmV0dXJuISh2b2lkIDA9PT10fHxcImxheW91dFwiPT09ZSYmIU9iamVjdC5rZXlzKHQpLmxlbmd0aHx8XCJwYWludFwiPT09ZSYmIU9iamVjdC5rZXlzKHQpLmxlbmd0aCl9KX0sZS5wcm90b3R5cGUuX3ZhbGlkYXRlPWZ1bmN0aW9uKHQsZSxyLG4saSl7cmV0dXJuKCFpfHwhMSE9PWkudmFsaWRhdGUpJiZhcih0aGlzLHQuY2FsbChycix7a2V5OmUsbGF5ZXJUeXBlOnRoaXMudHlwZSxvYmplY3RLZXk6cix2YWx1ZTpuLHN0eWxlU3BlYzpFLHN0eWxlOntnbHlwaHM6ITAsc3ByaXRlOiEwfX0pKX0sZS5wcm90b3R5cGUuaGFzT2Zmc2NyZWVuUGFzcz1mdW5jdGlvbigpe3JldHVybiExfSxlLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oKXt9LGV9KEkpLFpyPXtJbnQ4OkludDhBcnJheSxVaW50ODpVaW50OEFycmF5LEludDE2OkludDE2QXJyYXksVWludDE2OlVpbnQxNkFycmF5LEludDMyOkludDMyQXJyYXksVWludDMyOlVpbnQzMkFycmF5LEZsb2F0MzI6RmxvYXQzMkFycmF5fSxLcj1mdW5jdGlvbih0LGUpe3RoaXMuX3N0cnVjdEFycmF5PXQsdGhpcy5fcG9zMT1lKnRoaXMuc2l6ZSx0aGlzLl9wb3MyPXRoaXMuX3BvczEvMix0aGlzLl9wb3M0PXRoaXMuX3BvczEvNCx0aGlzLl9wb3M4PXRoaXMuX3BvczEvODt9LEpyPWZ1bmN0aW9uKCl7dGhpcy5pc1RyYW5zZmVycmVkPSExLHRoaXMuY2FwYWNpdHk9LTEsdGhpcy5yZXNpemUoMCk7fTtmdW5jdGlvbiAkcih0LGUpe3ZvaWQgMD09PWUmJihlPTEpO3ZhciByPTAsbj0wO3JldHVybnttZW1iZXJzOnQubWFwKGZ1bmN0aW9uKHQpe3ZhciBpLG89KGk9dC50eXBlLFpyW2ldLkJZVEVTX1BFUl9FTEVNRU5UKSxhPXI9SHIocixNYXRoLm1heChlLG8pKSxzPXQuY29tcG9uZW50c3x8MTtyZXR1cm4gbj1NYXRoLm1heChuLG8pLHIrPW8qcyx7bmFtZTp0Lm5hbWUsdHlwZTp0LnR5cGUsY29tcG9uZW50czpzLG9mZnNldDphfX0pLHNpemU6SHIocixNYXRoLm1heChuLGUpKSxhbGlnbm1lbnQ6ZX19ZnVuY3Rpb24gSHIodCxlKXtyZXR1cm4gTWF0aC5jZWlsKHQvZSkqZX1Kci5zZXJpYWxpemU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5fdHJpbSgpLGUmJih0LmlzVHJhbnNmZXJyZWQ9ITAsZS5wdXNoKHQuYXJyYXlCdWZmZXIpKSx7bGVuZ3RoOnQubGVuZ3RoLGFycmF5QnVmZmVyOnQuYXJyYXlCdWZmZXJ9fSxKci5kZXNlcmlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgZT1PYmplY3QuY3JlYXRlKHRoaXMucHJvdG90eXBlKTtyZXR1cm4gZS5hcnJheUJ1ZmZlcj10LmFycmF5QnVmZmVyLGUubGVuZ3RoPXQubGVuZ3RoLGUuY2FwYWNpdHk9dC5hcnJheUJ1ZmZlci5ieXRlTGVuZ3RoL2UuYnl0ZXNQZXJFbGVtZW50LGUuX3JlZnJlc2hWaWV3cygpLGV9LEpyLnByb3RvdHlwZS5fdHJpbT1mdW5jdGlvbigpe3RoaXMubGVuZ3RoIT09dGhpcy5jYXBhY2l0eSYmKHRoaXMuY2FwYWNpdHk9dGhpcy5sZW5ndGgsdGhpcy5hcnJheUJ1ZmZlcj10aGlzLmFycmF5QnVmZmVyLnNsaWNlKDAsdGhpcy5sZW5ndGgqdGhpcy5ieXRlc1BlckVsZW1lbnQpLHRoaXMuX3JlZnJlc2hWaWV3cygpKTt9LEpyLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3RoaXMubGVuZ3RoPTA7fSxKci5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKHQpe3RoaXMucmVzZXJ2ZSh0KSx0aGlzLmxlbmd0aD10O30sSnIucHJvdG90eXBlLnJlc2VydmU9ZnVuY3Rpb24odCl7aWYodD50aGlzLmNhcGFjaXR5KXt0aGlzLmNhcGFjaXR5PU1hdGgubWF4KHQsTWF0aC5mbG9vcig1KnRoaXMuY2FwYWNpdHkpLDEyOCksdGhpcy5hcnJheUJ1ZmZlcj1uZXcgQXJyYXlCdWZmZXIodGhpcy5jYXBhY2l0eSp0aGlzLmJ5dGVzUGVyRWxlbWVudCk7dmFyIGU9dGhpcy51aW50ODt0aGlzLl9yZWZyZXNoVmlld3MoKSxlJiZ0aGlzLnVpbnQ4LnNldChlKTt9fSxKci5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3Rocm93IG5ldyBFcnJvcihcIl9yZWZyZXNoVmlld3MoKSBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IGVhY2ggY29uY3JldGUgU3RydWN0QXJyYXkgbGF5b3V0XCIpfTt2YXIgWHI9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5sZW5ndGg7dGhpcy5yZXNpemUocisxKTt2YXIgbj0yKnI7cmV0dXJuIHRoaXMuaW50MTZbbiswXT10LHRoaXMuaW50MTZbbisxXT1lLHJ9LGV9KEpyKTtYci5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTQsaHIoXCJTdHJ1Y3RBcnJheUxheW91dDJpNFwiLFhyKTt2YXIgR3I9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKGkrMSk7dmFyIG89NCppO3JldHVybiB0aGlzLmludDE2W28rMF09dCx0aGlzLmludDE2W28rMV09ZSx0aGlzLmludDE2W28rMl09cix0aGlzLmludDE2W28rM109bixpfSxlfShKcik7R3IucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD04LGhyKFwiU3RydWN0QXJyYXlMYXlvdXQ0aThcIixHcik7dmFyIFlyPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuaW50MTY9bmV3IEludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksbyl7dmFyIGE9dGhpcy5sZW5ndGg7dGhpcy5yZXNpemUoYSsxKTt2YXIgcz02KmE7cmV0dXJuIHRoaXMuaW50MTZbcyswXT10LHRoaXMuaW50MTZbcysxXT1lLHRoaXMuaW50MTZbcysyXT1yLHRoaXMuaW50MTZbcyszXT1uLHRoaXMuaW50MTZbcys0XT1pLHRoaXMuaW50MTZbcys1XT1vLGF9LGV9KEpyKTtZci5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTEyLGhyKFwiU3RydWN0QXJyYXlMYXlvdXQyaTRpMTJcIixZcik7dmFyIFdyPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuaW50MTY9bmV3IEludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksbyxhLHMpe3ZhciB1PXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKHUrMSk7dmFyIGw9Nip1LHA9MTIqdTtyZXR1cm4gdGhpcy5pbnQxNltsKzBdPXQsdGhpcy5pbnQxNltsKzFdPWUsdGhpcy5pbnQxNltsKzJdPXIsdGhpcy5pbnQxNltsKzNdPW4sdGhpcy51aW50OFtwKzhdPWksdGhpcy51aW50OFtwKzldPW8sdGhpcy51aW50OFtwKzEwXT1hLHRoaXMudWludDhbcCsxMV09cyx1fSxlfShKcik7V3IucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xMixocihcIlN0cnVjdEFycmF5TGF5b3V0NGk0dWIxMlwiLFdyKTt2YXIgUXI9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksbyxhLHMpe3ZhciB1PXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKHUrMSk7dmFyIGw9OCp1O3JldHVybiB0aGlzLmludDE2W2wrMF09dCx0aGlzLmludDE2W2wrMV09ZSx0aGlzLmludDE2W2wrMl09cix0aGlzLmludDE2W2wrM109bix0aGlzLnVpbnQxNltsKzRdPWksdGhpcy51aW50MTZbbCs1XT1vLHRoaXMudWludDE2W2wrNl09YSx0aGlzLnVpbnQxNltsKzddPXMsdX0sZX0oSnIpO1FyLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9MTYsaHIoXCJTdHJ1Y3RBcnJheUxheW91dDRpNHVpMTZcIixRcik7dmFyIHRuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuZmxvYXQzMj1uZXcgRmxvYXQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKG4rMSk7dmFyIGk9MypuO3JldHVybiB0aGlzLmZsb2F0MzJbaSswXT10LHRoaXMuZmxvYXQzMltpKzFdPWUsdGhpcy5mbG9hdDMyW2krMl09cixufSxlfShKcik7dG4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xMixocihcIlN0cnVjdEFycmF5TGF5b3V0M2YxMlwiLHRuKTt2YXIgZW49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MzI9bmV3IFVpbnQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5sZW5ndGg7dGhpcy5yZXNpemUoZSsxKTt2YXIgcj0xKmU7cmV0dXJuIHRoaXMudWludDMyW3IrMF09dCxlfSxlfShKcik7ZW4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD00LGhyKFwiU3RydWN0QXJyYXlMYXlvdXQxdWw0XCIsZW4pO3ZhciBybj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmludDE2PW5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDMyPW5ldyBVaW50MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksbyxhLHMsdSxsLHApe3ZhciBjPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKGMrMSk7dmFyIGg9MTIqYyxmPTYqYztyZXR1cm4gdGhpcy5pbnQxNltoKzBdPXQsdGhpcy5pbnQxNltoKzFdPWUsdGhpcy5pbnQxNltoKzJdPXIsdGhpcy5pbnQxNltoKzNdPW4sdGhpcy5pbnQxNltoKzRdPWksdGhpcy5pbnQxNltoKzVdPW8sdGhpcy51aW50MzJbZiszXT1hLHRoaXMudWludDE2W2grOF09cyx0aGlzLnVpbnQxNltoKzldPXUsdGhpcy5pbnQxNltoKzEwXT1sLHRoaXMuaW50MTZbaCsxMV09cCxjfSxlfShKcik7cm4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0yNCxocihcIlN0cnVjdEFycmF5TGF5b3V0NmkxdWwydWkyaTI0XCIscm4pO3ZhciBubj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmludDE2PW5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIsbixpLG8pe3ZhciBhPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKGErMSk7dmFyIHM9NiphO3JldHVybiB0aGlzLmludDE2W3MrMF09dCx0aGlzLmludDE2W3MrMV09ZSx0aGlzLmludDE2W3MrMl09cix0aGlzLmludDE2W3MrM109bix0aGlzLmludDE2W3MrNF09aSx0aGlzLmludDE2W3MrNV09byxhfSxlfShKcik7bm4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xMixocihcIlN0cnVjdEFycmF5TGF5b3V0MmkyaTJpMTJcIixubik7dmFyIG9uPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlKXt2YXIgcj10aGlzLmxlbmd0aDt0aGlzLnJlc2l6ZShyKzEpO3ZhciBuPTQqcjtyZXR1cm4gdGhpcy51aW50OFtuKzBdPXQsdGhpcy51aW50OFtuKzFdPWUscn0sZX0oSnIpO29uLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9NCxocihcIlN0cnVjdEFycmF5TGF5b3V0MnViNFwiLG9uKTt2YXIgYW49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MzI9bmV3IFVpbnQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuZmxvYXQzMj1uZXcgRmxvYXQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIsbixpLG8sYSxzLHUsbCxwLGMsaCxmKXt2YXIgeT10aGlzLmxlbmd0aDt0aGlzLnJlc2l6ZSh5KzEpO3ZhciBkPTIwKnksdj0xMCp5LG09NDAqeTtyZXR1cm4gdGhpcy5pbnQxNltkKzBdPXQsdGhpcy5pbnQxNltkKzFdPWUsdGhpcy51aW50MTZbZCsyXT1yLHRoaXMudWludDE2W2QrM109bix0aGlzLnVpbnQzMlt2KzJdPWksdGhpcy51aW50MzJbdiszXT1vLHRoaXMudWludDMyW3YrNF09YSx0aGlzLnVpbnQxNltkKzEwXT1zLHRoaXMudWludDE2W2QrMTFdPXUsdGhpcy51aW50MTZbZCsxMl09bCx0aGlzLmZsb2F0MzJbdis3XT1wLHRoaXMuZmxvYXQzMlt2KzhdPWMsdGhpcy51aW50OFttKzM2XT1oLHRoaXMudWludDhbbSszN109Zix5fSxlfShKcik7YW4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD00MCxocihcIlN0cnVjdEFycmF5TGF5b3V0MmkydWkzdWwzdWkyZjJ1YjQwXCIsYW4pO3ZhciBzbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmZsb2F0MzI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKGUrMSk7dmFyIHI9MSplO3JldHVybiB0aGlzLmZsb2F0MzJbciswXT10LGV9LGV9KEpyKTtzbi5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTQsaHIoXCJTdHJ1Y3RBcnJheUxheW91dDFmNFwiLHNuKTt2YXIgdW49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLmxlbmd0aDt0aGlzLnJlc2l6ZShuKzEpO3ZhciBpPTMqbjtyZXR1cm4gdGhpcy5pbnQxNltpKzBdPXQsdGhpcy5pbnQxNltpKzFdPWUsdGhpcy5pbnQxNltpKzJdPXIsbn0sZX0oSnIpO3VuLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9NixocihcIlN0cnVjdEFycmF5TGF5b3V0M2k2XCIsdW4pO3ZhciBsbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQzMj1uZXcgVWludDMyQXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MTY9bmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKG4rMSk7dmFyIGk9MipuLG89NCpuO3JldHVybiB0aGlzLnVpbnQzMltpKzBdPXQsdGhpcy51aW50MTZbbysyXT1lLHRoaXMudWludDE2W28rM109cixufSxlfShKcik7bG4ucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD04LGhyKFwiU3RydWN0QXJyYXlMYXlvdXQxdWwydWk4XCIsbG4pO3ZhciBwbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscil7dmFyIG49dGhpcy5sZW5ndGg7dGhpcy5yZXNpemUobisxKTt2YXIgaT0zKm47cmV0dXJuIHRoaXMudWludDE2W2krMF09dCx0aGlzLnVpbnQxNltpKzFdPWUsdGhpcy51aW50MTZbaSsyXT1yLG59LGV9KEpyKTtwbi5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTYsaHIoXCJTdHJ1Y3RBcnJheUxheW91dDN1aTZcIixwbik7dmFyIGNuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDE2PW5ldyBVaW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5sZW5ndGg7dGhpcy5yZXNpemUocisxKTt2YXIgbj0yKnI7cmV0dXJuIHRoaXMudWludDE2W24rMF09dCx0aGlzLnVpbnQxNltuKzFdPWUscn0sZX0oSnIpO2NuLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9NCxocihcIlN0cnVjdEFycmF5TGF5b3V0MnVpNFwiLGNuKTt2YXIgaG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5mbG9hdDMyPW5ldyBGbG9hdDMyQXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKHIrMSk7dmFyIG49MipyO3JldHVybiB0aGlzLmZsb2F0MzJbbiswXT10LHRoaXMuZmxvYXQzMltuKzFdPWUscn0sZX0oSnIpO2huLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9OCxocihcIlN0cnVjdEFycmF5TGF5b3V0MmY4XCIsaG4pO3ZhciBmbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmZsb2F0MzI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMubGVuZ3RoO3RoaXMucmVzaXplKGkrMSk7dmFyIG89NCppO3JldHVybiB0aGlzLmZsb2F0MzJbbyswXT10LHRoaXMuZmxvYXQzMltvKzFdPWUsdGhpcy5mbG9hdDMyW28rMl09cix0aGlzLmZsb2F0MzJbbyszXT1uLGl9LGV9KEpyKTtmbi5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTE2LGhyKFwiU3RydWN0QXJyYXlMYXlvdXQ0ZjE2XCIsZm4pO3ZhciB5bj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO3ZhciByPXthbmNob3JQb2ludFg6e2NvbmZpZ3VyYWJsZTohMH0sYW5jaG9yUG9pbnRZOntjb25maWd1cmFibGU6ITB9LHgxOntjb25maWd1cmFibGU6ITB9LHkxOntjb25maWd1cmFibGU6ITB9LHgyOntjb25maWd1cmFibGU6ITB9LHkyOntjb25maWd1cmFibGU6ITB9LGZlYXR1cmVJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxzb3VyY2VMYXllckluZGV4Ontjb25maWd1cmFibGU6ITB9LGJ1Y2tldEluZGV4Ontjb25maWd1cmFibGU6ITB9LHJhZGl1czp7Y29uZmlndXJhYmxlOiEwfSxzaWduZWREaXN0YW5jZUZyb21BbmNob3I6e2NvbmZpZ3VyYWJsZTohMH0sYW5jaG9yUG9pbnQ6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiByLmFuY2hvclBvaW50WC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiswXX0sci5hbmNob3JQb2ludFguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF09dDt9LHIuYW5jaG9yUG9pbnRZLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzFdfSxyLmFuY2hvclBvaW50WS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXT10O30sci54MS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisyXX0sci54MS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisyXT10O30sci55MS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiszXX0sci55MS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiszXT10O30sci54Mi5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMis0XX0sci54Mi5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMis0XT10O30sci55Mi5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMis1XX0sci55Mi5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMis1XT10O30sci5mZWF0dXJlSW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzNdfSxyLmZlYXR1cmVJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrM109dDt9LHIuc291cmNlTGF5ZXJJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrOF19LHIuc291cmNlTGF5ZXJJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrOF09dDt9LHIuYnVja2V0SW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzldfSxyLmJ1Y2tldEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMis5XT10O30sci5yYWRpdXMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMTBdfSxyLnJhZGl1cy5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxMF09dDt9LHIuc2lnbmVkRGlzdGFuY2VGcm9tQW5jaG9yLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzExXX0sci5zaWduZWREaXN0YW5jZUZyb21BbmNob3Iuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMTFdPXQ7fSxyLmFuY2hvclBvaW50LmdldD1mdW5jdGlvbigpe3JldHVybiBuZXcgcyh0aGlzLmFuY2hvclBvaW50WCx0aGlzLmFuY2hvclBvaW50WSl9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLHIpLGV9KEtyKTt5bi5wcm90b3R5cGUuc2l6ZT0yNDt2YXIgZG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgeW4odGhpcyx0KX0sZX0ocm4pO2hyKFwiQ29sbGlzaW9uQm94QXJyYXlcIixkbik7dmFyIHZuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9dCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWU7dmFyIHI9e2FuY2hvclg6e2NvbmZpZ3VyYWJsZTohMH0sYW5jaG9yWTp7Y29uZmlndXJhYmxlOiEwfSxnbHlwaFN0YXJ0SW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sbnVtR2x5cGhzOntjb25maWd1cmFibGU6ITB9LHZlcnRleFN0YXJ0SW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sbGluZVN0YXJ0SW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sbGluZUxlbmd0aDp7Y29uZmlndXJhYmxlOiEwfSxzZWdtZW50Ontjb25maWd1cmFibGU6ITB9LGxvd2VyU2l6ZTp7Y29uZmlndXJhYmxlOiEwfSx1cHBlclNpemU6e2NvbmZpZ3VyYWJsZTohMH0sbGluZU9mZnNldFg6e2NvbmZpZ3VyYWJsZTohMH0sbGluZU9mZnNldFk6e2NvbmZpZ3VyYWJsZTohMH0sd3JpdGluZ01vZGU6e2NvbmZpZ3VyYWJsZTohMH0saGlkZGVuOntjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gci5hbmNob3JYLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzBdfSxyLmFuY2hvclguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF09dDt9LHIuYW5jaG9yWS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXX0sci5hbmNob3JZLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzFdPXQ7fSxyLmdseXBoU3RhcnRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMl19LHIuZ2x5cGhTdGFydEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMisyXT10O30sci5udW1HbHlwaHMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzNdfSxyLm51bUdseXBocy5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrM109dDt9LHIudmVydGV4U3RhcnRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrMl19LHIudmVydGV4U3RhcnRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrMl09dDt9LHIubGluZVN0YXJ0SW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzNdfSxyLmxpbmVTdGFydEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCszXT10O30sci5saW5lTGVuZ3RoLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCs0XX0sci5saW5lTGVuZ3RoLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCs0XT10O30sci5zZWdtZW50LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMisxMF19LHIuc2VnbWVudC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTBdPXQ7fSxyLmxvd2VyU2l6ZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTFdfSxyLmxvd2VyU2l6ZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTFdPXQ7fSxyLnVwcGVyU2l6ZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTJdfSxyLnVwcGVyU2l6ZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTJdPXQ7fSxyLmxpbmVPZmZzZXRYLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5mbG9hdDMyW3RoaXMuX3BvczQrN119LHIubGluZU9mZnNldFguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmZsb2F0MzJbdGhpcy5fcG9zNCs3XT10O30sci5saW5lT2Zmc2V0WS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzhdfSxyLmxpbmVPZmZzZXRZLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5mbG9hdDMyW3RoaXMuX3BvczQrOF09dDt9LHIud3JpdGluZ01vZGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQ4W3RoaXMuX3BvczErMzZdfSxyLndyaXRpbmdNb2RlLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50OFt0aGlzLl9wb3MxKzM2XT10O30sci5oaWRkZW4uZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQ4W3RoaXMuX3BvczErMzddfSxyLmhpZGRlbi5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDhbdGhpcy5fcG9zMSszN109dDt9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLHIpLGV9KEtyKTt2bi5wcm90b3R5cGUuc2l6ZT00MDt2YXIgbW49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgdm4odGhpcyx0KX0sZX0oYW4pO2hyKFwiUGxhY2VkU3ltYm9sQXJyYXlcIixtbik7dmFyIGduPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9dCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWU7dmFyIHI9e29mZnNldFg6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiByLm9mZnNldFguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmZsb2F0MzJbdGhpcy5fcG9zNCswXX0sci5vZmZzZXRYLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5mbG9hdDMyW3RoaXMuX3BvczQrMF09dDt9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLHIpLGV9KEtyKTtnbi5wcm90b3R5cGUuc2l6ZT00O3ZhciB4bj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXRvZmZzZXRYPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmZsb2F0MzJbMSp0KzBdfSxlLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBnbih0aGlzLHQpfSxlfShzbik7aHIoXCJHbHlwaE9mZnNldEFycmF5XCIseG4pO3ZhciBibj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO3ZhciByPXt4Ontjb25maWd1cmFibGU6ITB9LHk6e2NvbmZpZ3VyYWJsZTohMH0sdGlsZVVuaXREaXN0YW5jZUZyb21BbmNob3I6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiByLnguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF19LHIueC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiswXT10O30sci55LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzFdfSxyLnkuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMV09dDt9LHIudGlsZVVuaXREaXN0YW5jZUZyb21BbmNob3IuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMl19LHIudGlsZVVuaXREaXN0YW5jZUZyb21BbmNob3Iuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMl09dDt9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLHIpLGV9KEtyKTtibi5wcm90b3R5cGUuc2l6ZT02O3ZhciB3bj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXR4PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmludDE2WzMqdCswXX0sZS5wcm90b3R5cGUuZ2V0eT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5pbnQxNlszKnQrMV19LGUucHJvdG90eXBlLmdldHRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmludDE2WzMqdCsyXX0sZS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYm4odGhpcyx0KX0sZX0odW4pO2hyKFwiU3ltYm9sTGluZVZlcnRleEFycmF5XCIsd24pO3ZhciBfbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO3ZhciByPXtmZWF0dXJlSW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sc291cmNlTGF5ZXJJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxidWNrZXRJbmRleDp7Y29uZmlndXJhYmxlOiEwfX07cmV0dXJuIHIuZmVhdHVyZUluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCswXX0sci5mZWF0dXJlSW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzBdPXQ7fSxyLnNvdXJjZUxheWVySW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzJdfSxyLnNvdXJjZUxheWVySW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzJdPXQ7fSxyLmJ1Y2tldEluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMiszXX0sci5idWNrZXRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrM109dDt9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLHIpLGV9KEtyKTtfbi5wcm90b3R5cGUuc2l6ZT04O3ZhciBBbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBfbih0aGlzLHQpfSxlfShsbik7aHIoXCJGZWF0dXJlSW5kZXhBcnJheVwiLEFuKTt2YXIga249JHIoW3tuYW1lOlwiYV9wb3NcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9XSw0KS5tZW1iZXJzLHpuPWZ1bmN0aW9uKHQpe3ZvaWQgMD09PXQmJih0PVtdKSx0aGlzLnNlZ21lbnRzPXQ7fTt6bi5wcm90b3R5cGUucHJlcGFyZVNlZ21lbnQ9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXMuc2VnbWVudHNbdGhpcy5zZWdtZW50cy5sZW5ndGgtMV07cmV0dXJuIHQ+em4uTUFYX1ZFUlRFWF9BUlJBWV9MRU5HVEgmJmIoXCJNYXggdmVydGljZXMgcGVyIHNlZ21lbnQgaXMgXCIrem4uTUFYX1ZFUlRFWF9BUlJBWV9MRU5HVEgrXCI6IGJ1Y2tldCByZXF1ZXN0ZWQgXCIrdCksKCFufHxuLnZlcnRleExlbmd0aCt0PnpuLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIKSYmKG49e3ZlcnRleE9mZnNldDplLmxlbmd0aCxwcmltaXRpdmVPZmZzZXQ6ci5sZW5ndGgsdmVydGV4TGVuZ3RoOjAscHJpbWl0aXZlTGVuZ3RoOjB9LHRoaXMuc2VnbWVudHMucHVzaChuKSksbn0sem4ucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNlZ21lbnRzfSx6bi5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe2Zvcih2YXIgdD0wLGU9dGhpcy5zZWdtZW50czt0PGUubGVuZ3RoO3QrPTEpe3ZhciByPWVbdF07Zm9yKHZhciBuIGluIHIudmFvcylyLnZhb3Nbbl0uZGVzdHJveSgpO319LHpuLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIPU1hdGgucG93KDIsMTYpLTEsaHIoXCJTZWdtZW50VmVjdG9yXCIsem4pO3ZhciBTbj1mdW5jdGlvbih0LGUpe3JldHVybiAyNTYqKHQ9YyhNYXRoLmZsb29yKHQpLDAsMjU1KSkrKGU9YyhNYXRoLmZsb29yKGUpLDAsMjU1KSl9O2Z1bmN0aW9uIE1uKHQpe3JldHVybltTbigyNTUqdC5yLDI1NSp0LmcpLFNuKDI1NSp0LmIsMjU1KnQuYSldfXZhciBWbj1mdW5jdGlvbih0LGUscil7dGhpcy52YWx1ZT10LHRoaXMubmFtZT1lLHRoaXMudHlwZT1yLHRoaXMuc3RhdGlzdGljcz17bWF4Oi0xLzB9O307Vm4ucHJvdG90eXBlLmRlZmluZXM9ZnVuY3Rpb24oKXtyZXR1cm5bXCIjZGVmaW5lIEhBU19VTklGT1JNX3VfXCIrdGhpcy5uYW1lXX0sVm4ucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbigpe30sVm4ucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbigpe30sVm4ucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt9LFZuLnByb3RvdHlwZS5zZXRVbmlmb3Jtcz1mdW5jdGlvbih0LGUscixuKXt2YXIgaT1uLmNvbnN0YW50T3IodGhpcy52YWx1ZSksbz10LmdsO1wiY29sb3JcIj09PXRoaXMudHlwZT9vLnVuaWZvcm00ZihlLnVuaWZvcm1zW1widV9cIit0aGlzLm5hbWVdLGkucixpLmcsaS5iLGkuYSk6by51bmlmb3JtMWYoZS51bmlmb3Jtc1tcInVfXCIrdGhpcy5uYW1lXSxpKTt9O3ZhciBCbj1mdW5jdGlvbih0LGUscil7dGhpcy5leHByZXNzaW9uPXQsdGhpcy5uYW1lPWUsdGhpcy50eXBlPXIsdGhpcy5zdGF0aXN0aWNzPXttYXg6LTEvMH07dmFyIG49XCJjb2xvclwiPT09cj9objpzbjt0aGlzLnBhaW50VmVydGV4QXR0cmlidXRlcz1be25hbWU6XCJhX1wiK2UsdHlwZTpcIkZsb2F0MzJcIixjb21wb25lbnRzOlwiY29sb3JcIj09PXI/MjoxLG9mZnNldDowfV0sdGhpcy5wYWludFZlcnRleEFycmF5PW5ldyBuO307Qm4ucHJvdG90eXBlLmRlZmluZXM9ZnVuY3Rpb24oKXtyZXR1cm5bXX0sQm4ucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMucGFpbnRWZXJ0ZXhBcnJheSxuPXIubGVuZ3RoO3IucmVzZXJ2ZSh0KTt2YXIgaT10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IEJyKDApLGUpO2lmKFwiY29sb3JcIj09PXRoaXMudHlwZSlmb3IodmFyIG89TW4oaSksYT1uO2E8dDthKyspci5lbXBsYWNlQmFjayhvWzBdLG9bMV0pO2Vsc2V7Zm9yKHZhciBzPW47czx0O3MrKylyLmVtcGxhY2VCYWNrKGkpO3RoaXMuc3RhdGlzdGljcy5tYXg9TWF0aC5tYXgodGhpcy5zdGF0aXN0aWNzLm1heCxpKTt9fSxCbi5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe3RoaXMucGFpbnRWZXJ0ZXhBcnJheSYmKHRoaXMucGFpbnRWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5wYWludFZlcnRleEFycmF5LHRoaXMucGFpbnRWZXJ0ZXhBdHRyaWJ1dGVzKSk7fSxCbi5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMucGFpbnRWZXJ0ZXhCdWZmZXImJnRoaXMucGFpbnRWZXJ0ZXhCdWZmZXIuZGVzdHJveSgpO30sQm4ucHJvdG90eXBlLnNldFVuaWZvcm1zPWZ1bmN0aW9uKHQsZSl7dC5nbC51bmlmb3JtMWYoZS51bmlmb3Jtc1tcImFfXCIrdGhpcy5uYW1lK1wiX3RcIl0sMCk7fTt2YXIgQ249ZnVuY3Rpb24odCxlLHIsbixpKXt0aGlzLmV4cHJlc3Npb249dCx0aGlzLm5hbWU9ZSx0aGlzLnR5cGU9cix0aGlzLnVzZUludGVnZXJab29tPW4sdGhpcy56b29tPWksdGhpcy5zdGF0aXN0aWNzPXttYXg6LTEvMH07dmFyIG89XCJjb2xvclwiPT09cj9mbjpobjt0aGlzLnBhaW50VmVydGV4QXR0cmlidXRlcz1be25hbWU6XCJhX1wiK2UsdHlwZTpcIkZsb2F0MzJcIixjb21wb25lbnRzOlwiY29sb3JcIj09PXI/NDoyLG9mZnNldDowfV0sdGhpcy5wYWludFZlcnRleEFycmF5PW5ldyBvO307Q24ucHJvdG90eXBlLmRlZmluZXM9ZnVuY3Rpb24oKXtyZXR1cm5bXX0sQ24ucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMucGFpbnRWZXJ0ZXhBcnJheSxuPXIubGVuZ3RoO3IucmVzZXJ2ZSh0KTt2YXIgaT10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IEJyKHRoaXMuem9vbSksZSksbz10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IEJyKHRoaXMuem9vbSsxKSxlKTtpZihcImNvbG9yXCI9PT10aGlzLnR5cGUpZm9yKHZhciBhPU1uKGkpLHM9TW4obyksdT1uO3U8dDt1Kyspci5lbXBsYWNlQmFjayhhWzBdLGFbMV0sc1swXSxzWzFdKTtlbHNle2Zvcih2YXIgbD1uO2w8dDtsKyspci5lbXBsYWNlQmFjayhpLG8pO3RoaXMuc3RhdGlzdGljcy5tYXg9TWF0aC5tYXgodGhpcy5zdGF0aXN0aWNzLm1heCxpLG8pO319LENuLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy5wYWludFZlcnRleEFycmF5JiYodGhpcy5wYWludFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLnBhaW50VmVydGV4QXJyYXksdGhpcy5wYWludFZlcnRleEF0dHJpYnV0ZXMpKTt9LENuLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5wYWludFZlcnRleEJ1ZmZlciYmdGhpcy5wYWludFZlcnRleEJ1ZmZlci5kZXN0cm95KCk7fSxDbi5wcm90b3R5cGUuaW50ZXJwb2xhdGlvbkZhY3Rvcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy51c2VJbnRlZ2VyWm9vbT90aGlzLmV4cHJlc3Npb24uaW50ZXJwb2xhdGlvbkZhY3RvcihNYXRoLmZsb29yKHQpLHRoaXMuem9vbSx0aGlzLnpvb20rMSk6dGhpcy5leHByZXNzaW9uLmludGVycG9sYXRpb25GYWN0b3IodCx0aGlzLnpvb20sdGhpcy56b29tKzEpfSxDbi5wcm90b3R5cGUuc2V0VW5pZm9ybXM9ZnVuY3Rpb24odCxlLHIpe3QuZ2wudW5pZm9ybTFmKGUudW5pZm9ybXNbXCJhX1wiK3RoaXMubmFtZStcIl90XCJdLHRoaXMuaW50ZXJwb2xhdGlvbkZhY3RvcihyLnpvb20pKTt9O3ZhciBJbj1mdW5jdGlvbigpe3RoaXMuYmluZGVycz17fSx0aGlzLmNhY2hlS2V5PVwiXCIsdGhpcy5fYnVmZmVycz1bXTt9O0luLmNyZWF0ZUR5bmFtaWM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPW5ldyBJbixpPVtdO2Zvcih2YXIgbyBpbiB0LnBhaW50Ll92YWx1ZXMpaWYocihvKSl7dmFyIGE9dC5wYWludC5nZXQobyk7aWYoYSBpbnN0YW5jZW9mIE9yJiZhLnByb3BlcnR5LnNwZWNpZmljYXRpb25bXCJwcm9wZXJ0eS1mdW5jdGlvblwiXSl7dmFyIHM9Rm4obyx0LnR5cGUpLHU9YS5wcm9wZXJ0eS5zcGVjaWZpY2F0aW9uLnR5cGUsbD1hLnByb3BlcnR5LnVzZUludGVnZXJab29tO1wiY29uc3RhbnRcIj09PWEudmFsdWUua2luZD8obi5iaW5kZXJzW29dPW5ldyBWbihhLnZhbHVlLHMsdSksaS5wdXNoKFwiL3VfXCIrcykpOlwic291cmNlXCI9PT1hLnZhbHVlLmtpbmQ/KG4uYmluZGVyc1tvXT1uZXcgQm4oYS52YWx1ZSxzLHUpLGkucHVzaChcIi9hX1wiK3MpKToobi5iaW5kZXJzW29dPW5ldyBDbihhLnZhbHVlLHMsdSxsLGUpLGkucHVzaChcIi96X1wiK3MpKTt9fXJldHVybiBuLmNhY2hlS2V5PWkuc29ydCgpLmpvaW4oXCJcIiksbn0sSW4ucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHIgaW4gdGhpcy5iaW5kZXJzKXRoaXMuYmluZGVyc1tyXS5wb3B1bGF0ZVBhaW50QXJyYXkodCxlKTt9LEluLnByb3RvdHlwZS5kZWZpbmVzPWZ1bmN0aW9uKCl7dmFyIHQ9W107Zm9yKHZhciBlIGluIHRoaXMuYmluZGVycyl0LnB1c2guYXBwbHkodCx0aGlzLmJpbmRlcnNbZV0uZGVmaW5lcygpKTtyZXR1cm4gdH0sSW4ucHJvdG90eXBlLnNldFVuaWZvcm1zPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaSBpbiB0aGlzLmJpbmRlcnMpe3RoaXMuYmluZGVyc1tpXS5zZXRVbmlmb3Jtcyh0LGUsbixyLmdldChpKSk7fX0sSW4ucHJvdG90eXBlLmdldFBhaW50VmVydGV4QnVmZmVycz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9idWZmZXJzfSxJbi5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZSBpbiB0aGlzLmJpbmRlcnMpdGhpcy5iaW5kZXJzW2VdLnVwbG9hZCh0KTt2YXIgcj1bXTtmb3IodmFyIG4gaW4gdGhpcy5iaW5kZXJzKXt2YXIgaT10aGlzLmJpbmRlcnNbbl07KGkgaW5zdGFuY2VvZiBCbnx8aSBpbnN0YW5jZW9mIENuKSYmaS5wYWludFZlcnRleEJ1ZmZlciYmci5wdXNoKGkucGFpbnRWZXJ0ZXhCdWZmZXIpO310aGlzLl9idWZmZXJzPXI7fSxJbi5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe2Zvcih2YXIgdCBpbiB0aGlzLmJpbmRlcnMpdGhpcy5iaW5kZXJzW3RdLmRlc3Ryb3koKTt9O3ZhciBFbj1mdW5jdGlvbih0LGUscixuKXt2b2lkIDA9PT1uJiYobj1mdW5jdGlvbigpe3JldHVybiEwfSksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnM9e307Zm9yKHZhciBpPTAsbz1lO2k8by5sZW5ndGg7aSs9MSl7dmFyIGE9b1tpXTt0aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1thLmlkXT1Jbi5jcmVhdGVEeW5hbWljKGEscixuKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1thLmlkXS5sYXlvdXRBdHRyaWJ1dGVzPXQ7fX07ZnVuY3Rpb24gRm4odCxlKXtyZXR1cm57XCJ0ZXh0LW9wYWNpdHlcIjpcIm9wYWNpdHlcIixcImljb24tb3BhY2l0eVwiOlwib3BhY2l0eVwiLFwidGV4dC1jb2xvclwiOlwiZmlsbF9jb2xvclwiLFwiaWNvbi1jb2xvclwiOlwiZmlsbF9jb2xvclwiLFwidGV4dC1oYWxvLWNvbG9yXCI6XCJoYWxvX2NvbG9yXCIsXCJpY29uLWhhbG8tY29sb3JcIjpcImhhbG9fY29sb3JcIixcInRleHQtaGFsby1ibHVyXCI6XCJoYWxvX2JsdXJcIixcImljb24taGFsby1ibHVyXCI6XCJoYWxvX2JsdXJcIixcInRleHQtaGFsby13aWR0aFwiOlwiaGFsb193aWR0aFwiLFwiaWNvbi1oYWxvLXdpZHRoXCI6XCJoYWxvX3dpZHRoXCIsXCJsaW5lLWdhcC13aWR0aFwiOlwiZ2Fwd2lkdGhcIn1bdF18fHQucmVwbGFjZShlK1wiLVwiLFwiXCIpLnJlcGxhY2UoLy0vZyxcIl9cIil9RW4ucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHIgaW4gdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMpdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnNbcl0ucG9wdWxhdGVQYWludEFycmF5cyh0LGUpO30sRW4ucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnNbdF19LEVuLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zKXRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zW2VdLnVwbG9hZCh0KTt9LEVuLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zKXRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zW3RdLmRlc3Ryb3koKTt9LGhyKFwiQ29uc3RhbnRCaW5kZXJcIixWbiksaHIoXCJTb3VyY2VFeHByZXNzaW9uQmluZGVyXCIsQm4pLGhyKFwiQ29tcG9zaXRlRXhwcmVzc2lvbkJpbmRlclwiLENuKSxocihcIlByb2dyYW1Db25maWd1cmF0aW9uXCIsSW4se29taXQ6W1wiX2J1ZmZlcnNcIl19KSxocihcIlByb2dyYW1Db25maWd1cmF0aW9uU2V0XCIsRW4pO3ZhciBQbj04MTkyO3ZhciBUbixPbj0oVG49MTYse21pbjotMSpNYXRoLnBvdygyLFRuLTEpLG1heDpNYXRoLnBvdygyLFRuLTEpLTF9KTtmdW5jdGlvbiBMbih0KXtmb3IodmFyIGU9UG4vdC5leHRlbnQscj10LmxvYWRHZW9tZXRyeSgpLG49MDtuPHIubGVuZ3RoO24rKylmb3IodmFyIGk9cltuXSxvPTA7bzxpLmxlbmd0aDtvKyspe3ZhciBhPWlbb107YS54PU1hdGgucm91bmQoYS54KmUpLGEueT1NYXRoLnJvdW5kKGEueSplKSwoYS54PE9uLm1pbnx8YS54Pk9uLm1heHx8YS55PE9uLm1pbnx8YS55Pk9uLm1heCkmJmIoXCJHZW9tZXRyeSBleGNlZWRzIGFsbG93ZWQgZXh0ZW50LCByZWR1Y2UgeW91ciB2ZWN0b3IgdGlsZSBidWZmZXIgc2l6ZVwiKTt9cmV0dXJuIHJ9ZnVuY3Rpb24gam4odCxlLHIsbixpKXt0LmVtcGxhY2VCYWNrKDIqZSsobisxKS8yLDIqcisoaSsxKS8yKTt9dmFyIHFuPWZ1bmN0aW9uKHQpe3RoaXMuem9vbT10Lnpvb20sdGhpcy5vdmVyc2NhbGluZz10Lm92ZXJzY2FsaW5nLHRoaXMubGF5ZXJzPXQubGF5ZXJzLHRoaXMubGF5ZXJJZHM9dGhpcy5sYXllcnMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSksdGhpcy5pbmRleD10LmluZGV4LHRoaXMubGF5b3V0VmVydGV4QXJyYXk9bmV3IFhyLHRoaXMuaW5kZXhBcnJheT1uZXcgcG4sdGhpcy5zZWdtZW50cz1uZXcgem4sdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnM9bmV3IEVuKGtuLHQubGF5ZXJzLHQuem9vbSk7fTtmdW5jdGlvbiBSbih0LGUscil7Zm9yKHZhciBuPTA7bjx0Lmxlbmd0aDtuKyspe3ZhciBpPXRbbl07aWYoWG4oaSxlKSlyZXR1cm4hMDtpZihKbihlLGkscikpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gVW4odCxlKXtpZigxPT09dC5sZW5ndGgmJjE9PT10WzBdLmxlbmd0aClyZXR1cm4gSG4oZSx0WzBdWzBdKTtmb3IodmFyIHI9MDtyPGUubGVuZ3RoO3IrKylmb3IodmFyIG49ZVtyXSxpPTA7aTxuLmxlbmd0aDtpKyspaWYoSG4odCxuW2ldKSlyZXR1cm4hMDtmb3IodmFyIG89MDtvPHQubGVuZ3RoO28rKyl7Zm9yKHZhciBhPXRbb10scz0wO3M8YS5sZW5ndGg7cysrKWlmKEhuKGUsYVtzXSkpcmV0dXJuITA7Zm9yKHZhciB1PTA7dTxlLmxlbmd0aDt1KyspaWYoWm4oYSxlW3VdKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiBEbih0LGUscil7Zm9yKHZhciBuPTA7bjxlLmxlbmd0aDtuKyspZm9yKHZhciBpPWVbbl0sbz0wO288dC5sZW5ndGg7bysrKXt2YXIgYT10W29dO2lmKGEubGVuZ3RoPj0zKWZvcih2YXIgcz0wO3M8aS5sZW5ndGg7cysrKWlmKFhuKGEsaVtzXSkpcmV0dXJuITA7aWYoTm4oYSxpLHIpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIE5uKHQsZSxyKXtpZih0Lmxlbmd0aD4xKXtpZihabih0LGUpKXJldHVybiEwO2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bisrKWlmKEpuKGVbbl0sdCxyKSlyZXR1cm4hMH1mb3IodmFyIGk9MDtpPHQubGVuZ3RoO2krKylpZihKbih0W2ldLGUscikpcmV0dXJuITA7cmV0dXJuITF9ZnVuY3Rpb24gWm4odCxlKXtpZigwPT09dC5sZW5ndGh8fDA9PT1lLmxlbmd0aClyZXR1cm4hMTtmb3IodmFyIHI9MDtyPHQubGVuZ3RoLTE7cisrKWZvcih2YXIgbj10W3JdLGk9dFtyKzFdLG89MDtvPGUubGVuZ3RoLTE7bysrKXtpZihLbihuLGksZVtvXSxlW28rMV0pKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIEtuKHQsZSxyLG4pe3JldHVybiB3KHQscixuKSE9PXcoZSxyLG4pJiZ3KHQsZSxyKSE9PXcodCxlLG4pfWZ1bmN0aW9uIEpuKHQsZSxyKXt2YXIgbj1yKnI7aWYoMT09PWUubGVuZ3RoKXJldHVybiB0LmRpc3RTcXIoZVswXSk8bjtmb3IodmFyIGk9MTtpPGUubGVuZ3RoO2krKyl7aWYoJG4odCxlW2ktMV0sZVtpXSk8bilyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiAkbih0LGUscil7dmFyIG49ZS5kaXN0U3FyKHIpO2lmKDA9PT1uKXJldHVybiB0LmRpc3RTcXIoZSk7dmFyIGk9KCh0LngtZS54KSooci54LWUueCkrKHQueS1lLnkpKihyLnktZS55KSkvbjtyZXR1cm4gaTwwP3QuZGlzdFNxcihlKTppPjE/dC5kaXN0U3FyKHIpOnQuZGlzdFNxcihyLnN1YihlKS5fbXVsdChpKS5fYWRkKGUpKX1mdW5jdGlvbiBIbih0LGUpe2Zvcih2YXIgcixuLGksbz0hMSxhPTA7YTx0Lmxlbmd0aDthKyspZm9yKHZhciBzPTAsdT0ocj10W2FdKS5sZW5ndGgtMTtzPHIubGVuZ3RoO3U9cysrKW49cltzXSxpPXJbdV0sbi55PmUueSE9aS55PmUueSYmZS54PChpLngtbi54KSooZS55LW4ueSkvKGkueS1uLnkpK24ueCYmKG89IW8pO3JldHVybiBvfWZ1bmN0aW9uIFhuKHQsZSl7Zm9yKHZhciByPSExLG49MCxpPXQubGVuZ3RoLTE7bjx0Lmxlbmd0aDtpPW4rKyl7dmFyIG89dFtuXSxhPXRbaV07by55PmUueSE9YS55PmUueSYmZS54PChhLngtby54KSooZS55LW8ueSkvKGEueS1vLnkpK28ueCYmKHI9IXIpO31yZXR1cm4gcn1mdW5jdGlvbiBHbih0LGUscil7dmFyIG49ZS5wYWludC5nZXQodCkudmFsdWU7cmV0dXJuXCJjb25zdGFudFwiPT09bi5raW5kP24udmFsdWU6ci5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGUuaWQpLmJpbmRlcnNbdF0uc3RhdGlzdGljcy5tYXh9ZnVuY3Rpb24gWW4odCl7cmV0dXJuIE1hdGguc3FydCh0WzBdKnRbMF0rdFsxXSp0WzFdKX1mdW5jdGlvbiBXbih0LGUscixuLGkpe2lmKCFlWzBdJiYhZVsxXSlyZXR1cm4gdDt2YXIgbz1zLmNvbnZlcnQoZSk7XCJ2aWV3cG9ydFwiPT09ciYmby5fcm90YXRlKC1uKTtmb3IodmFyIGE9W10sdT0wO3U8dC5sZW5ndGg7dSsrKXtmb3IodmFyIGw9dFt1XSxwPVtdLGM9MDtjPGwubGVuZ3RoO2MrKylwLnB1c2gobFtjXS5zdWIoby5fbXVsdChpKSkpO2EucHVzaChwKTt9cmV0dXJuIGF9cW4ucHJvdG90eXBlLnBvcHVsYXRlPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj10O3I8bi5sZW5ndGg7cis9MSl7dmFyIGk9bltyXSxvPWkuZmVhdHVyZSxhPWkuaW5kZXgscz1pLnNvdXJjZUxheWVySW5kZXg7aWYodGhpcy5sYXllcnNbMF0uX2ZlYXR1cmVGaWx0ZXIobmV3IEJyKHRoaXMuem9vbSksbykpe3ZhciB1PUxuKG8pO3RoaXMuYWRkRmVhdHVyZShvLHUpLGUuZmVhdHVyZUluZGV4Lmluc2VydChvLHUsYSxzLHRoaXMuaW5kZXgpO319fSxxbi5wcm90b3R5cGUuaXNFbXB0eT1mdW5jdGlvbigpe3JldHVybiAwPT09dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheS5sZW5ndGh9LHFuLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxrbiksdGhpcy5pbmRleEJ1ZmZlcj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheSksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBsb2FkKHQpO30scW4ucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlciYmKHRoaXMubGF5b3V0VmVydGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLmluZGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5kZXN0cm95KCksdGhpcy5zZWdtZW50cy5kZXN0cm95KCkpO30scW4ucHJvdG90eXBlLmFkZEZlYXR1cmU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPWU7cjxuLmxlbmd0aDtyKz0xKWZvcih2YXIgaT0wLG89bltyXTtpPG8ubGVuZ3RoO2krPTEpe3ZhciBhPW9baV0scz1hLngsdT1hLnk7aWYoIShzPDB8fHM+PVBufHx1PDB8fHU+PVBuKSl7dmFyIGw9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KSxwPWwudmVydGV4TGVuZ3RoO2puKHRoaXMubGF5b3V0VmVydGV4QXJyYXkscyx1LC0xLC0xKSxqbih0aGlzLmxheW91dFZlcnRleEFycmF5LHMsdSwxLC0xKSxqbih0aGlzLmxheW91dFZlcnRleEFycmF5LHMsdSwxLDEpLGpuKHRoaXMubGF5b3V0VmVydGV4QXJyYXkscyx1LC0xLDEpLHRoaXMuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhwLHArMSxwKzIpLHRoaXMuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhwLHArMyxwKzIpLGwudmVydGV4TGVuZ3RoKz00LGwucHJpbWl0aXZlTGVuZ3RoKz0yO319dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMucG9wdWxhdGVQYWludEFycmF5cyh0aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aCx0KTt9LGhyKFwiQ2lyY2xlQnVja2V0XCIscW4se29taXQ6W1wibGF5ZXJzXCJdfSk7dmFyIFFuPXtwYWludDpuZXcgRHIoe1wiY2lyY2xlLXJhZGl1c1wiOm5ldyBxcihFLnBhaW50X2NpcmNsZVtcImNpcmNsZS1yYWRpdXNcIl0pLFwiY2lyY2xlLWNvbG9yXCI6bmV3IHFyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLWNvbG9yXCJdKSxcImNpcmNsZS1ibHVyXCI6bmV3IHFyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLWJsdXJcIl0pLFwiY2lyY2xlLW9wYWNpdHlcIjpuZXcgcXIoRS5wYWludF9jaXJjbGVbXCJjaXJjbGUtb3BhY2l0eVwiXSksXCJjaXJjbGUtdHJhbnNsYXRlXCI6bmV3IGpyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXRyYW5zbGF0ZVwiXSksXCJjaXJjbGUtdHJhbnNsYXRlLWFuY2hvclwiOm5ldyBqcihFLnBhaW50X2NpcmNsZVtcImNpcmNsZS10cmFuc2xhdGUtYW5jaG9yXCJdKSxcImNpcmNsZS1waXRjaC1zY2FsZVwiOm5ldyBqcihFLnBhaW50X2NpcmNsZVtcImNpcmNsZS1waXRjaC1zY2FsZVwiXSksXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCI6bmV3IGpyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXBpdGNoLWFsaWdubWVudFwiXSksXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCI6bmV3IHFyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXN0cm9rZS13aWR0aFwiXSksXCJjaXJjbGUtc3Ryb2tlLWNvbG9yXCI6bmV3IHFyKEUucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXN0cm9rZS1jb2xvclwiXSksXCJjaXJjbGUtc3Ryb2tlLW9wYWNpdHlcIjpuZXcgcXIoRS5wYWludF9jaXJjbGVbXCJjaXJjbGUtc3Ryb2tlLW9wYWNpdHlcIl0pfSl9LHRpPW4oZnVuY3Rpb24odCxlKXt2YXIgcjt0LmV4cG9ydHM9KChyPW5ldyBGbG9hdDMyQXJyYXkoMykpWzBdPTAsclsxXT0wLHJbMl09MCxmdW5jdGlvbigpe3ZhciB0PW5ldyBGbG9hdDMyQXJyYXkoNCk7dFswXT0wLHRbMV09MCx0WzJdPTAsdFszXT0wO30oKSx7dmVjMzp7dHJhbnNmb3JtTWF0MzpmdW5jdGlvbih0LGUscil7dmFyIG49ZVswXSxpPWVbMV0sbz1lWzJdO3JldHVybiB0WzBdPW4qclswXStpKnJbM10rbypyWzZdLHRbMV09bipyWzFdK2kqcls0XStvKnJbN10sdFsyXT1uKnJbMl0raSpyWzVdK28qcls4XSx0fX0sdmVjNDp7dHJhbnNmb3JtTWF0NDpmdW5jdGlvbih0LGUscil7dmFyIG49ZVswXSxpPWVbMV0sbz1lWzJdLGE9ZVszXTtyZXR1cm4gdFswXT1yWzBdKm4rcls0XSppK3JbOF0qbytyWzEyXSphLHRbMV09clsxXSpuK3JbNV0qaStyWzldKm8rclsxM10qYSx0WzJdPXJbMl0qbityWzZdKmkrclsxMF0qbytyWzE0XSphLHRbM109clszXSpuK3JbN10qaStyWzExXSpvK3JbMTVdKmEsdH19LG1hdDI6e2NyZWF0ZTpmdW5jdGlvbigpe3ZhciB0PW5ldyBGbG9hdDMyQXJyYXkoNCk7cmV0dXJuIHRbMF09MSx0WzFdPTAsdFsyXT0wLHRbM109MSx0fSxyb3RhdGU6ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWVbMF0saT1lWzFdLG89ZVsyXSxhPWVbM10scz1NYXRoLnNpbihyKSx1PU1hdGguY29zKHIpO3JldHVybiB0WzBdPW4qdStvKnMsdFsxXT1pKnUrYSpzLHRbMl09biotcytvKnUsdFszXT1pKi1zK2EqdSx0fSxzY2FsZTpmdW5jdGlvbih0LGUscil7dmFyIG49ZVswXSxpPWVbMV0sbz1lWzJdLGE9ZVszXSxzPXJbMF0sdT1yWzFdO3JldHVybiB0WzBdPW4qcyx0WzFdPWkqcyx0WzJdPW8qdSx0WzNdPWEqdSx0fX0sbWF0Mzp7Y3JlYXRlOmZ1bmN0aW9uKCl7dmFyIHQ9bmV3IEZsb2F0MzJBcnJheSg5KTtyZXR1cm4gdFswXT0xLHRbMV09MCx0WzJdPTAsdFszXT0wLHRbNF09MSx0WzVdPTAsdFs2XT0wLHRbN109MCx0WzhdPTEsdH0sZnJvbVJvdGF0aW9uOmZ1bmN0aW9uKHQsZSl7dmFyIHI9TWF0aC5zaW4oZSksbj1NYXRoLmNvcyhlKTtyZXR1cm4gdFswXT1uLHRbMV09cix0WzJdPTAsdFszXT0tcix0WzRdPW4sdFs1XT0wLHRbNl09MCx0WzddPTAsdFs4XT0xLHR9fSxtYXQ0OntjcmVhdGU6ZnVuY3Rpb24oKXt2YXIgdD1uZXcgRmxvYXQzMkFycmF5KDE2KTtyZXR1cm4gdFswXT0xLHRbMV09MCx0WzJdPTAsdFszXT0wLHRbNF09MCx0WzVdPTEsdFs2XT0wLHRbN109MCx0WzhdPTAsdFs5XT0wLHRbMTBdPTEsdFsxMV09MCx0WzEyXT0wLHRbMTNdPTAsdFsxNF09MCx0WzE1XT0xLHR9LGlkZW50aXR5OmZ1bmN0aW9uKHQpe3JldHVybiB0WzBdPTEsdFsxXT0wLHRbMl09MCx0WzNdPTAsdFs0XT0wLHRbNV09MSx0WzZdPTAsdFs3XT0wLHRbOF09MCx0WzldPTAsdFsxMF09MSx0WzExXT0wLHRbMTJdPTAsdFsxM109MCx0WzE0XT0wLHRbMTVdPTEsdH0sdHJhbnNsYXRlOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbixpLG8sYSxzLHUsbCxwLGMsaCxmLHksZD1yWzBdLHY9clsxXSxtPXJbMl07cmV0dXJuIGU9PT10Pyh0WzEyXT1lWzBdKmQrZVs0XSp2K2VbOF0qbStlWzEyXSx0WzEzXT1lWzFdKmQrZVs1XSp2K2VbOV0qbStlWzEzXSx0WzE0XT1lWzJdKmQrZVs2XSp2K2VbMTBdKm0rZVsxNF0sdFsxNV09ZVszXSpkK2VbN10qditlWzExXSptK2VbMTVdKToobj1lWzBdLGk9ZVsxXSxvPWVbMl0sYT1lWzNdLHM9ZVs0XSx1PWVbNV0sbD1lWzZdLHA9ZVs3XSxjPWVbOF0saD1lWzldLGY9ZVsxMF0seT1lWzExXSx0WzBdPW4sdFsxXT1pLHRbMl09byx0WzNdPWEsdFs0XT1zLHRbNV09dSx0WzZdPWwsdFs3XT1wLHRbOF09Yyx0WzldPWgsdFsxMF09Zix0WzExXT15LHRbMTJdPW4qZCtzKnYrYyptK2VbMTJdLHRbMTNdPWkqZCt1KnYraCptK2VbMTNdLHRbMTRdPW8qZCtsKnYrZiptK2VbMTRdLHRbMTVdPWEqZCtwKnYreSptK2VbMTVdKSx0fSxzY2FsZTpmdW5jdGlvbih0LGUscil7dmFyIG49clswXSxpPXJbMV0sbz1yWzJdO3JldHVybiB0WzBdPWVbMF0qbix0WzFdPWVbMV0qbix0WzJdPWVbMl0qbix0WzNdPWVbM10qbix0WzRdPWVbNF0qaSx0WzVdPWVbNV0qaSx0WzZdPWVbNl0qaSx0WzddPWVbN10qaSx0WzhdPWVbOF0qbyx0WzldPWVbOV0qbyx0WzEwXT1lWzEwXSpvLHRbMTFdPWVbMTFdKm8sdFsxMl09ZVsxMl0sdFsxM109ZVsxM10sdFsxNF09ZVsxNF0sdFsxNV09ZVsxNV0sdH0sbXVsdGlwbHk6ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWVbMF0saT1lWzFdLG89ZVsyXSxhPWVbM10scz1lWzRdLHU9ZVs1XSxsPWVbNl0scD1lWzddLGM9ZVs4XSxoPWVbOV0sZj1lWzEwXSx5PWVbMTFdLGQ9ZVsxMl0sdj1lWzEzXSxtPWVbMTRdLGc9ZVsxNV0seD1yWzBdLGI9clsxXSx3PXJbMl0sXz1yWzNdO3JldHVybiB0WzBdPXgqbitiKnMrdypjK18qZCx0WzFdPXgqaStiKnUrdypoK18qdix0WzJdPXgqbytiKmwrdypmK18qbSx0WzNdPXgqYStiKnArdyp5K18qZyx4PXJbNF0sYj1yWzVdLHc9cls2XSxfPXJbN10sdFs0XT14Km4rYipzK3cqYytfKmQsdFs1XT14KmkrYip1K3cqaCtfKnYsdFs2XT14Km8rYipsK3cqZitfKm0sdFs3XT14KmErYipwK3cqeStfKmcseD1yWzhdLGI9cls5XSx3PXJbMTBdLF89clsxMV0sdFs4XT14Km4rYipzK3cqYytfKmQsdFs5XT14KmkrYip1K3cqaCtfKnYsdFsxMF09eCpvK2IqbCt3KmYrXyptLHRbMTFdPXgqYStiKnArdyp5K18qZyx4PXJbMTJdLGI9clsxM10sdz1yWzE0XSxfPXJbMTVdLHRbMTJdPXgqbitiKnMrdypjK18qZCx0WzEzXT14KmkrYip1K3cqaCtfKnYsdFsxNF09eCpvK2IqbCt3KmYrXyptLHRbMTVdPXgqYStiKnArdyp5K18qZyx0fSxwZXJzcGVjdGl2ZTpmdW5jdGlvbih0LGUscixuLGkpe3ZhciBvPTEvTWF0aC50YW4oZS8yKSxhPTEvKG4taSk7cmV0dXJuIHRbMF09by9yLHRbMV09MCx0WzJdPTAsdFszXT0wLHRbNF09MCx0WzVdPW8sdFs2XT0wLHRbN109MCx0WzhdPTAsdFs5XT0wLHRbMTBdPShpK24pKmEsdFsxMV09LTEsdFsxMl09MCx0WzEzXT0wLHRbMTRdPTIqaSpuKmEsdFsxNV09MCx0fSxyb3RhdGVYOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLnNpbihyKSxpPU1hdGguY29zKHIpLG89ZVs0XSxhPWVbNV0scz1lWzZdLHU9ZVs3XSxsPWVbOF0scD1lWzldLGM9ZVsxMF0saD1lWzExXTtyZXR1cm4gZSE9PXQmJih0WzBdPWVbMF0sdFsxXT1lWzFdLHRbMl09ZVsyXSx0WzNdPWVbM10sdFsxMl09ZVsxMl0sdFsxM109ZVsxM10sdFsxNF09ZVsxNF0sdFsxNV09ZVsxNV0pLHRbNF09byppK2wqbix0WzVdPWEqaStwKm4sdFs2XT1zKmkrYypuLHRbN109dSppK2gqbix0WzhdPWwqaS1vKm4sdFs5XT1wKmktYSpuLHRbMTBdPWMqaS1zKm4sdFsxMV09aCppLXUqbix0fSxyb3RhdGVaOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLnNpbihyKSxpPU1hdGguY29zKHIpLG89ZVswXSxhPWVbMV0scz1lWzJdLHU9ZVszXSxsPWVbNF0scD1lWzVdLGM9ZVs2XSxoPWVbN107cmV0dXJuIGUhPT10JiYodFs4XT1lWzhdLHRbOV09ZVs5XSx0WzEwXT1lWzEwXSx0WzExXT1lWzExXSx0WzEyXT1lWzEyXSx0WzEzXT1lWzEzXSx0WzE0XT1lWzE0XSx0WzE1XT1lWzE1XSksdFswXT1vKmkrbCpuLHRbMV09YSppK3Aqbix0WzJdPXMqaStjKm4sdFszXT11KmkraCpuLHRbNF09bCppLW8qbix0WzVdPXAqaS1hKm4sdFs2XT1jKmktcypuLHRbN109aCppLXUqbix0fSxpbnZlcnQ6ZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXSxpPWVbMl0sbz1lWzNdLGE9ZVs0XSxzPWVbNV0sdT1lWzZdLGw9ZVs3XSxwPWVbOF0sYz1lWzldLGg9ZVsxMF0sZj1lWzExXSx5PWVbMTJdLGQ9ZVsxM10sdj1lWzE0XSxtPWVbMTVdLGc9cipzLW4qYSx4PXIqdS1pKmEsYj1yKmwtbyphLHc9bip1LWkqcyxfPW4qbC1vKnMsQT1pKmwtbyp1LGs9cCpkLWMqeSx6PXAqdi1oKnksUz1wKm0tZip5LE09Yyp2LWgqZCxWPWMqbS1mKmQsQj1oKm0tZip2LEM9ZypCLXgqVitiKk0rdypTLV8qeitBKms7cmV0dXJuIEM/KEM9MS9DLHRbMF09KHMqQi11KlYrbCpNKSpDLHRbMV09KGkqVi1uKkItbypNKSpDLHRbMl09KGQqQS12Kl8rbSp3KSpDLHRbM109KGgqXy1jKkEtZip3KSpDLHRbNF09KHUqUy1hKkItbCp6KSpDLHRbNV09KHIqQi1pKlMrbyp6KSpDLHRbNl09KHYqYi15KkEtbSp4KSpDLHRbN109KHAqQS1oKmIrZip4KSpDLHRbOF09KGEqVi1zKlMrbCprKSpDLHRbOV09KG4qUy1yKlYtbyprKSpDLHRbMTBdPSh5Kl8tZCpiK20qZykqQyx0WzExXT0oYypiLXAqXy1mKmcpKkMsdFsxMl09KHMqei1hKk0tdSprKSpDLHRbMTNdPShyKk0tbip6K2kqaykqQyx0WzE0XT0oZCp4LXkqdy12KmcpKkMsdFsxNV09KHAqdy1jKngraCpnKSpDLHQpOm51bGx9LG9ydGhvOmZ1bmN0aW9uKHQsZSxyLG4saSxvLGEpe3ZhciBzPTEvKGUtciksdT0xLyhuLWkpLGw9MS8oby1hKTtyZXR1cm4gdFswXT0tMipzLHRbMV09MCx0WzJdPTAsdFszXT0wLHRbNF09MCx0WzVdPS0yKnUsdFs2XT0wLHRbN109MCx0WzhdPTAsdFs5XT0wLHRbMTBdPTIqbCx0WzExXT0wLHRbMTJdPShlK3IpKnMsdFsxM109KGkrbikqdSx0WzE0XT0oYStvKSpsLHRbMTVdPTEsdH19fSk7fSksZWk9KHRpLnZlYzMsdGkudmVjNCkscmk9KHRpLm1hdDIsdGkubWF0Myx0aS5tYXQ0KSxuaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUsUW4pO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuY3JlYXRlQnVja2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgcW4odCl9LGUucHJvdG90eXBlLnF1ZXJ5UmFkaXVzPWZ1bmN0aW9uKHQpe3ZhciBlPXQ7cmV0dXJuIEduKFwiY2lyY2xlLXJhZGl1c1wiLHRoaXMsZSkrR24oXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCIsdGhpcyxlKStZbih0aGlzLnBhaW50LmdldChcImNpcmNsZS10cmFuc2xhdGVcIikpfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4saSxvLGEpe2Zvcih2YXIgcz1Xbih0LHRoaXMucGFpbnQuZ2V0KFwiY2lyY2xlLXRyYW5zbGF0ZVwiKSx0aGlzLnBhaW50LmdldChcImNpcmNsZS10cmFuc2xhdGUtYW5jaG9yXCIpLGkuYW5nbGUsbyksdT10aGlzLnBhaW50LmdldChcImNpcmNsZS1yYWRpdXNcIikuZXZhbHVhdGUoZSkrdGhpcy5wYWludC5nZXQoXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCIpLmV2YWx1YXRlKGUpLGw9XCJtYXBcIj09PXRoaXMucGFpbnQuZ2V0KFwiY2lyY2xlLXBpdGNoLWFsaWdubWVudFwiKSxwPWw/czpmdW5jdGlvbih0LGUscil7cmV0dXJuIHQubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0Lm1hcChmdW5jdGlvbih0KXtyZXR1cm4gaWkodCxlLHIpfSl9KX0ocyxhLGkpLGM9bD91Km86dSxoPTAsZj1yO2g8Zi5sZW5ndGg7aCs9MSlmb3IodmFyIHk9MCxkPWZbaF07eTxkLmxlbmd0aDt5Kz0xKXt2YXIgdj1kW3ldLG09bD92OmlpKHYsYSxpKSxnPWMseD1laS50cmFuc2Zvcm1NYXQ0KFtdLFt2Lngsdi55LDAsMV0sYSk7aWYoXCJ2aWV3cG9ydFwiPT09dGhpcy5wYWludC5nZXQoXCJjaXJjbGUtcGl0Y2gtc2NhbGVcIikmJlwibWFwXCI9PT10aGlzLnBhaW50LmdldChcImNpcmNsZS1waXRjaC1hbGlnbm1lbnRcIik/Zyo9eFszXS9pLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2U6XCJtYXBcIj09PXRoaXMucGFpbnQuZ2V0KFwiY2lyY2xlLXBpdGNoLXNjYWxlXCIpJiZcInZpZXdwb3J0XCI9PT10aGlzLnBhaW50LmdldChcImNpcmNsZS1waXRjaC1hbGlnbm1lbnRcIikmJihnKj1pLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UveFszXSksUm4ocCxtLGcpKXJldHVybiEwfXJldHVybiExfSxlfShOcik7ZnVuY3Rpb24gaWkodCxlLHIpe3ZhciBuPWVpLnRyYW5zZm9ybU1hdDQoW10sW3QueCx0LnksMCwxXSxlKTtyZXR1cm4gbmV3IHMoKG5bMF0vblszXSsxKSpyLndpZHRoKi41LChuWzFdL25bM10rMSkqci5oZWlnaHQqLjUpfXZhciBvaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlfShxbik7ZnVuY3Rpb24gYWkodCxlLHIsbil7dmFyIGk9ZS53aWR0aCxvPWUuaGVpZ2h0O2lmKG4pe2lmKG4ubGVuZ3RoIT09aSpvKnIpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJtaXNtYXRjaGVkIGltYWdlIHNpemVcIil9ZWxzZSBuPW5ldyBVaW50OEFycmF5KGkqbypyKTtyZXR1cm4gdC53aWR0aD1pLHQuaGVpZ2h0PW8sdC5kYXRhPW4sdH1mdW5jdGlvbiBzaSh0LGUscil7dmFyIG49ZS53aWR0aCxpPWUuaGVpZ2h0O2lmKG4hPT10LndpZHRofHxpIT09dC5oZWlnaHQpe3ZhciBvPWFpKHt9LHt3aWR0aDpuLGhlaWdodDppfSxyKTt1aSh0LG8se3g6MCx5OjB9LHt4OjAseTowfSx7d2lkdGg6TWF0aC5taW4odC53aWR0aCxuKSxoZWlnaHQ6TWF0aC5taW4odC5oZWlnaHQsaSl9LHIpLHQud2lkdGg9bix0LmhlaWdodD1pLHQuZGF0YT1vLmRhdGE7fX1mdW5jdGlvbiB1aSh0LGUscixuLGksbyl7aWYoMD09PWkud2lkdGh8fDA9PT1pLmhlaWdodClyZXR1cm4gZTtpZihpLndpZHRoPnQud2lkdGh8fGkuaGVpZ2h0PnQuaGVpZ2h0fHxyLng+dC53aWR0aC1pLndpZHRofHxyLnk+dC5oZWlnaHQtaS5oZWlnaHQpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJvdXQgb2YgcmFuZ2Ugc291cmNlIGNvb3JkaW5hdGVzIGZvciBpbWFnZSBjb3B5XCIpO2lmKGkud2lkdGg+ZS53aWR0aHx8aS5oZWlnaHQ+ZS5oZWlnaHR8fG4ueD5lLndpZHRoLWkud2lkdGh8fG4ueT5lLmhlaWdodC1pLmhlaWdodCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIm91dCBvZiByYW5nZSBkZXN0aW5hdGlvbiBjb29yZGluYXRlcyBmb3IgaW1hZ2UgY29weVwiKTtmb3IodmFyIGE9dC5kYXRhLHM9ZS5kYXRhLHU9MDt1PGkuaGVpZ2h0O3UrKylmb3IodmFyIGw9KChyLnkrdSkqdC53aWR0aCtyLngpKm8scD0oKG4ueSt1KSplLndpZHRoK24ueCkqbyxjPTA7YzxpLndpZHRoKm87YysrKXNbcCtjXT1hW2wrY107cmV0dXJuIGV9aHIoXCJIZWF0bWFwQnVja2V0XCIsb2kse29taXQ6W1wibGF5ZXJzXCJdfSk7dmFyIGxpPWZ1bmN0aW9uKHQsZSl7YWkodGhpcyx0LDEsZSk7fTtsaS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKHQpe3NpKHRoaXMsdCwxKTt9LGxpLnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3JldHVybiBuZXcgbGkoe3dpZHRoOnRoaXMud2lkdGgsaGVpZ2h0OnRoaXMuaGVpZ2h0fSxuZXcgVWludDhBcnJheSh0aGlzLmRhdGEpKX0sbGkuY29weT1mdW5jdGlvbih0LGUscixuLGkpe3VpKHQsZSxyLG4saSwxKTt9O3ZhciBwaT1mdW5jdGlvbih0LGUpe2FpKHRoaXMsdCw0LGUpO307cGkucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbih0KXtzaSh0aGlzLHQsNCk7fSxwaS5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHBpKHt3aWR0aDp0aGlzLndpZHRoLGhlaWdodDp0aGlzLmhlaWdodH0sbmV3IFVpbnQ4QXJyYXkodGhpcy5kYXRhKSl9LHBpLmNvcHk9ZnVuY3Rpb24odCxlLHIsbixpKXt1aSh0LGUscixuLGksNCk7fSxocihcIkFscGhhSW1hZ2VcIixsaSksaHIoXCJSR0JBSW1hZ2VcIixwaSk7dmFyIGNpPXtwYWludDpuZXcgRHIoe1wiaGVhdG1hcC1yYWRpdXNcIjpuZXcgcXIoRS5wYWludF9oZWF0bWFwW1wiaGVhdG1hcC1yYWRpdXNcIl0pLFwiaGVhdG1hcC13ZWlnaHRcIjpuZXcgcXIoRS5wYWludF9oZWF0bWFwW1wiaGVhdG1hcC13ZWlnaHRcIl0pLFwiaGVhdG1hcC1pbnRlbnNpdHlcIjpuZXcganIoRS5wYWludF9oZWF0bWFwW1wiaGVhdG1hcC1pbnRlbnNpdHlcIl0pLFwiaGVhdG1hcC1jb2xvclwiOm5ldyBVcihFLnBhaW50X2hlYXRtYXBbXCJoZWF0bWFwLWNvbG9yXCJdKSxcImhlYXRtYXAtb3BhY2l0eVwiOm5ldyBqcihFLnBhaW50X2hlYXRtYXBbXCJoZWF0bWFwLW9wYWNpdHlcIl0pfSl9O2Z1bmN0aW9uIGhpKHQsZSl7Zm9yKHZhciByPW5ldyBVaW50OEFycmF5KDEwMjQpLG49e30saT0wLG89MDtpPDI1NjtpKyssbys9NCl7bltlXT1pLzI1NTt2YXIgYT10LmV2YWx1YXRlKG4pO3JbbyswXT1NYXRoLmZsb29yKDI1NSphLnIvYS5hKSxyW28rMV09TWF0aC5mbG9vcigyNTUqYS5nL2EuYSkscltvKzJdPU1hdGguZmxvb3IoMjU1KmEuYi9hLmEpLHJbbyszXT1NYXRoLmZsb29yKDI1NSphLmEpO31yZXR1cm4gbmV3IHBpKHt3aWR0aDoyNTYsaGVpZ2h0OjF9LHIpfXZhciBmaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUsY2kpLHRoaXMuX3VwZGF0ZUNvbG9yUmFtcCgpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuY3JlYXRlQnVja2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgb2kodCl9LGUucHJvdG90eXBlLnNldFBhaW50UHJvcGVydHk9ZnVuY3Rpb24oZSxyLG4pe3QucHJvdG90eXBlLnNldFBhaW50UHJvcGVydHkuY2FsbCh0aGlzLGUscixuKSxcImhlYXRtYXAtY29sb3JcIj09PWUmJnRoaXMuX3VwZGF0ZUNvbG9yUmFtcCgpO30sZS5wcm90b3R5cGUuX3VwZGF0ZUNvbG9yUmFtcD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQuX3ZhbHVlc1tcImhlYXRtYXAtY29sb3JcIl0udmFsdWUuZXhwcmVzc2lvbjt0aGlzLmNvbG9yUmFtcD1oaSh0LFwiaGVhdG1hcERlbnNpdHlcIiksdGhpcy5jb2xvclJhbXBUZXh0dXJlPW51bGw7fSxlLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oKXt0aGlzLmhlYXRtYXBGYm8mJih0aGlzLmhlYXRtYXBGYm8uZGVzdHJveSgpLHRoaXMuaGVhdG1hcEZibz1udWxsKTt9LGUucHJvdG90eXBlLnF1ZXJ5UmFkaXVzPWZ1bmN0aW9uKCl7cmV0dXJuIDB9LGUucHJvdG90eXBlLnF1ZXJ5SW50ZXJzZWN0c0ZlYXR1cmU9ZnVuY3Rpb24oKXtyZXR1cm4hMX0sZS5wcm90b3R5cGUuaGFzT2Zmc2NyZWVuUGFzcz1mdW5jdGlvbigpe3JldHVybiAwIT09dGhpcy5wYWludC5nZXQoXCJoZWF0bWFwLW9wYWNpdHlcIikmJlwibm9uZVwiIT09dGhpcy52aXNpYmlsaXR5fSxlfShOcikseWk9e3BhaW50Om5ldyBEcih7XCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWRpcmVjdGlvblwiOm5ldyBqcihFLnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tZGlyZWN0aW9uXCJdKSxcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tYW5jaG9yXCI6bmV3IGpyKEUucGFpbnRfaGlsbHNoYWRlW1wiaGlsbHNoYWRlLWlsbHVtaW5hdGlvbi1hbmNob3JcIl0pLFwiaGlsbHNoYWRlLWV4YWdnZXJhdGlvblwiOm5ldyBqcihFLnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIl0pLFwiaGlsbHNoYWRlLXNoYWRvdy1jb2xvclwiOm5ldyBqcihFLnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1zaGFkb3ctY29sb3JcIl0pLFwiaGlsbHNoYWRlLWhpZ2hsaWdodC1jb2xvclwiOm5ldyBqcihFLnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1oaWdobGlnaHQtY29sb3JcIl0pLFwiaGlsbHNoYWRlLWFjY2VudC1jb2xvclwiOm5ldyBqcihFLnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1hY2NlbnQtY29sb3JcIl0pfSl9LGRpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSx5aSk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5oYXNPZmZzY3JlZW5QYXNzPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPT10aGlzLnBhaW50LmdldChcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIikmJlwibm9uZVwiIT09dGhpcy52aXNpYmlsaXR5fSxlfShOciksdmk9JHIoW3tuYW1lOlwiYV9wb3NcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9XSw0KS5tZW1iZXJzLG1pPXhpLGdpPXhpO2Z1bmN0aW9uIHhpKHQsZSxyKXtyPXJ8fDI7dmFyIG4saSxvLGEscyx1LGwscD1lJiZlLmxlbmd0aCxjPXA/ZVswXSpyOnQubGVuZ3RoLGg9YmkodCwwLGMsciwhMCksZj1bXTtpZighaClyZXR1cm4gZjtpZihwJiYoaD1mdW5jdGlvbih0LGUscixuKXt2YXIgaSxvLGEscyx1LGw9W107Zm9yKGk9MCxvPWUubGVuZ3RoO2k8bztpKyspYT1lW2ldKm4scz1pPG8tMT9lW2krMV0qbjp0Lmxlbmd0aCwodT1iaSh0LGEscyxuLCExKSk9PT11Lm5leHQmJih1LnN0ZWluZXI9ITApLGwucHVzaChDaSh1KSk7Zm9yKGwuc29ydChNaSksaT0wO2k8bC5sZW5ndGg7aSsrKVZpKGxbaV0scikscj13aShyLHIubmV4dCk7cmV0dXJuIHJ9KHQsZSxoLHIpKSx0Lmxlbmd0aD44MCpyKXtuPW89dFswXSxpPWE9dFsxXTtmb3IodmFyIHk9cjt5PGM7eSs9cikocz10W3ldKTxuJiYobj1zKSwodT10W3krMV0pPGkmJihpPXUpLHM+byYmKG89cyksdT5hJiYoYT11KTtsPTAhPT0obD1NYXRoLm1heChvLW4sYS1pKSk/MS9sOjA7fXJldHVybiBfaShoLGYscixuLGksbCksZn1mdW5jdGlvbiBiaSh0LGUscixuLGkpe3ZhciBvLGE7aWYoaT09PVVpKHQsZSxyLG4pPjApZm9yKG89ZTtvPHI7bys9bilhPWppKG8sdFtvXSx0W28rMV0sYSk7ZWxzZSBmb3Iobz1yLW47bz49ZTtvLT1uKWE9amkobyx0W29dLHRbbysxXSxhKTtyZXR1cm4gYSYmUGkoYSxhLm5leHQpJiYocWkoYSksYT1hLm5leHQpLGF9ZnVuY3Rpb24gd2kodCxlKXtpZighdClyZXR1cm4gdDtlfHwoZT10KTt2YXIgcixuPXQ7ZG97aWYocj0hMSxuLnN0ZWluZXJ8fCFQaShuLG4ubmV4dCkmJjAhPT1GaShuLnByZXYsbixuLm5leHQpKW49bi5uZXh0O2Vsc2V7aWYocWkobiksKG49ZT1uLnByZXYpPT09bi5uZXh0KWJyZWFrO3I9ITA7fX13aGlsZShyfHxuIT09ZSk7cmV0dXJuIGV9ZnVuY3Rpb24gX2kodCxlLHIsbixpLG8sYSl7aWYodCl7IWEmJm8mJmZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXQ7ZG97bnVsbD09PWkueiYmKGkuej1CaShpLngsaS55LGUscixuKSksaS5wcmV2Wj1pLnByZXYsaS5uZXh0Wj1pLm5leHQsaT1pLm5leHQ7fXdoaWxlKGkhPT10KTtpLnByZXZaLm5leHRaPW51bGwsaS5wcmV2Wj1udWxsLGZ1bmN0aW9uKHQpe3ZhciBlLHIsbixpLG8sYSxzLHUsbD0xO2Rve2ZvcihyPXQsdD1udWxsLG89bnVsbCxhPTA7cjspe2ZvcihhKyssbj1yLHM9MCxlPTA7ZTxsJiYocysrLG49bi5uZXh0Wik7ZSsrKTtmb3IodT1sO3M+MHx8dT4wJiZuOykwIT09cyYmKDA9PT11fHwhbnx8ci56PD1uLnopPyhpPXIscj1yLm5leHRaLHMtLSk6KGk9bixuPW4ubmV4dFosdS0tKSxvP28ubmV4dFo9aTp0PWksaS5wcmV2Wj1vLG89aTtyPW47fW8ubmV4dFo9bnVsbCxsKj0yO313aGlsZShhPjEpfShpKTt9KHQsbixpLG8pO2Zvcih2YXIgcyx1LGw9dDt0LnByZXYhPT10Lm5leHQ7KWlmKHM9dC5wcmV2LHU9dC5uZXh0LG8/a2kodCxuLGksbyk6QWkodCkpZS5wdXNoKHMuaS9yKSxlLnB1c2godC5pL3IpLGUucHVzaCh1LmkvcikscWkodCksdD11Lm5leHQsbD11Lm5leHQ7ZWxzZSBpZigodD11KT09PWwpe2E/MT09PWE/X2kodD16aSh0LGUsciksZSxyLG4saSxvLDIpOjI9PT1hJiZTaSh0LGUscixuLGksbyk6X2kod2kodCksZSxyLG4saSxvLDEpO2JyZWFrfX19ZnVuY3Rpb24gQWkodCl7dmFyIGU9dC5wcmV2LHI9dCxuPXQubmV4dDtpZihGaShlLHIsbik+PTApcmV0dXJuITE7Zm9yKHZhciBpPXQubmV4dC5uZXh0O2khPT10LnByZXY7KXtpZihJaShlLngsZS55LHIueCxyLnksbi54LG4ueSxpLngsaS55KSYmRmkoaS5wcmV2LGksaS5uZXh0KT49MClyZXR1cm4hMTtpPWkubmV4dDt9cmV0dXJuITB9ZnVuY3Rpb24ga2kodCxlLHIsbil7dmFyIGk9dC5wcmV2LG89dCxhPXQubmV4dDtpZihGaShpLG8sYSk+PTApcmV0dXJuITE7Zm9yKHZhciBzPWkueDxvLng/aS54PGEueD9pLng6YS54Om8ueDxhLng/by54OmEueCx1PWkueTxvLnk/aS55PGEueT9pLnk6YS55Om8ueTxhLnk/by55OmEueSxsPWkueD5vLng/aS54PmEueD9pLng6YS54Om8ueD5hLng/by54OmEueCxwPWkueT5vLnk/aS55PmEueT9pLnk6YS55Om8ueT5hLnk/by55OmEueSxjPUJpKHMsdSxlLHIsbiksaD1CaShsLHAsZSxyLG4pLGY9dC5wcmV2Wix5PXQubmV4dFo7ZiYmZi56Pj1jJiZ5JiZ5Lno8PWg7KXtpZihmIT09dC5wcmV2JiZmIT09dC5uZXh0JiZJaShpLngsaS55LG8ueCxvLnksYS54LGEueSxmLngsZi55KSYmRmkoZi5wcmV2LGYsZi5uZXh0KT49MClyZXR1cm4hMTtpZihmPWYucHJldloseSE9PXQucHJldiYmeSE9PXQubmV4dCYmSWkoaS54LGkueSxvLngsby55LGEueCxhLnkseS54LHkueSkmJkZpKHkucHJldix5LHkubmV4dCk+PTApcmV0dXJuITE7eT15Lm5leHRaO31mb3IoO2YmJmYuej49Yzspe2lmKGYhPT10LnByZXYmJmYhPT10Lm5leHQmJklpKGkueCxpLnksby54LG8ueSxhLngsYS55LGYueCxmLnkpJiZGaShmLnByZXYsZixmLm5leHQpPj0wKXJldHVybiExO2Y9Zi5wcmV2Wjt9Zm9yKDt5JiZ5Lno8PWg7KXtpZih5IT09dC5wcmV2JiZ5IT09dC5uZXh0JiZJaShpLngsaS55LG8ueCxvLnksYS54LGEueSx5LngseS55KSYmRmkoeS5wcmV2LHkseS5uZXh0KT49MClyZXR1cm4hMTt5PXkubmV4dFo7fXJldHVybiEwfWZ1bmN0aW9uIHppKHQsZSxyKXt2YXIgbj10O2Rve3ZhciBpPW4ucHJldixvPW4ubmV4dC5uZXh0OyFQaShpLG8pJiZUaShpLG4sbi5uZXh0LG8pJiZPaShpLG8pJiZPaShvLGkpJiYoZS5wdXNoKGkuaS9yKSxlLnB1c2gobi5pL3IpLGUucHVzaChvLmkvcikscWkobikscWkobi5uZXh0KSxuPXQ9byksbj1uLm5leHQ7fXdoaWxlKG4hPT10KTtyZXR1cm4gbn1mdW5jdGlvbiBTaSh0LGUscixuLGksbyl7dmFyIGE9dDtkb3tmb3IodmFyIHM9YS5uZXh0Lm5leHQ7cyE9PWEucHJldjspe2lmKGEuaSE9PXMuaSYmRWkoYSxzKSl7dmFyIHU9TGkoYSxzKTtyZXR1cm4gYT13aShhLGEubmV4dCksdT13aSh1LHUubmV4dCksX2koYSxlLHIsbixpLG8pLHZvaWQgX2kodSxlLHIsbixpLG8pfXM9cy5uZXh0O31hPWEubmV4dDt9d2hpbGUoYSE9PXQpfWZ1bmN0aW9uIE1pKHQsZSl7cmV0dXJuIHQueC1lLnh9ZnVuY3Rpb24gVmkodCxlKXtpZihlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbj1lLGk9dC54LG89dC55LGE9LTEvMDtkb3tpZihvPD1uLnkmJm8+PW4ubmV4dC55JiZuLm5leHQueSE9PW4ueSl7dmFyIHM9bi54KyhvLW4ueSkqKG4ubmV4dC54LW4ueCkvKG4ubmV4dC55LW4ueSk7aWYoczw9aSYmcz5hKXtpZihhPXMscz09PWkpe2lmKG89PT1uLnkpcmV0dXJuIG47aWYobz09PW4ubmV4dC55KXJldHVybiBuLm5leHR9cj1uLng8bi5uZXh0Lng/bjpuLm5leHQ7fX1uPW4ubmV4dDt9d2hpbGUobiE9PWUpO2lmKCFyKXJldHVybiBudWxsO2lmKGk9PT1hKXJldHVybiByLnByZXY7dmFyIHUsbD1yLHA9ci54LGM9ci55LGg9MS8wO249ci5uZXh0O2Zvcig7biE9PWw7KWk+PW4ueCYmbi54Pj1wJiZpIT09bi54JiZJaShvPGM/aTphLG8scCxjLG88Yz9hOmksbyxuLngsbi55KSYmKCh1PU1hdGguYWJzKG8tbi55KS8oaS1uLngpKTxofHx1PT09aCYmbi54PnIueCkmJk9pKG4sdCkmJihyPW4saD11KSxuPW4ubmV4dDtyZXR1cm4gcn0odCxlKSl7dmFyIHI9TGkoZSx0KTt3aShyLHIubmV4dCk7fX1mdW5jdGlvbiBCaSh0LGUscixuLGkpe3JldHVybih0PTE0MzE2NTU3NjUmKCh0PTg1ODk5MzQ1OSYoKHQ9MjUyNjQ1MTM1JigodD0xNjcxMTkzNSYoKHQ9MzI3NjcqKHQtcikqaSl8dDw8OCkpfHQ8PDQpKXx0PDwyKSl8dDw8MSkpfChlPTE0MzE2NTU3NjUmKChlPTg1ODk5MzQ1OSYoKGU9MjUyNjQ1MTM1JigoZT0xNjcxMTkzNSYoKGU9MzI3NjcqKGUtbikqaSl8ZTw8OCkpfGU8PDQpKXxlPDwyKSl8ZTw8MSkpPDwxfWZ1bmN0aW9uIENpKHQpe3ZhciBlPXQscj10O2Rve2UueDxyLngmJihyPWUpLGU9ZS5uZXh0O313aGlsZShlIT09dCk7cmV0dXJuIHJ9ZnVuY3Rpb24gSWkodCxlLHIsbixpLG8sYSxzKXtyZXR1cm4oaS1hKSooZS1zKS0odC1hKSooby1zKT49MCYmKHQtYSkqKG4tcyktKHItYSkqKGUtcyk+PTAmJihyLWEpKihvLXMpLShpLWEpKihuLXMpPj0wfWZ1bmN0aW9uIEVpKHQsZSl7cmV0dXJuIHQubmV4dC5pIT09ZS5pJiZ0LnByZXYuaSE9PWUuaSYmIWZ1bmN0aW9uKHQsZSl7dmFyIHI9dDtkb3tpZihyLmkhPT10LmkmJnIubmV4dC5pIT09dC5pJiZyLmkhPT1lLmkmJnIubmV4dC5pIT09ZS5pJiZUaShyLHIubmV4dCx0LGUpKXJldHVybiEwO3I9ci5uZXh0O313aGlsZShyIT09dCk7cmV0dXJuITF9KHQsZSkmJk9pKHQsZSkmJk9pKGUsdCkmJmZ1bmN0aW9uKHQsZSl7dmFyIHI9dCxuPSExLGk9KHQueCtlLngpLzIsbz0odC55K2UueSkvMjtkb3tyLnk+byE9ci5uZXh0Lnk+byYmci5uZXh0LnkhPT1yLnkmJmk8KHIubmV4dC54LXIueCkqKG8tci55KS8oci5uZXh0Lnktci55KStyLngmJihuPSFuKSxyPXIubmV4dDt9d2hpbGUociE9PXQpO3JldHVybiBufSh0LGUpfWZ1bmN0aW9uIEZpKHQsZSxyKXtyZXR1cm4oZS55LXQueSkqKHIueC1lLngpLShlLngtdC54KSooci55LWUueSl9ZnVuY3Rpb24gUGkodCxlKXtyZXR1cm4gdC54PT09ZS54JiZ0Lnk9PT1lLnl9ZnVuY3Rpb24gVGkodCxlLHIsbil7cmV0dXJuISEoUGkodCxlKSYmUGkocixuKXx8UGkodCxuKSYmUGkocixlKSl8fEZpKHQsZSxyKT4wIT1GaSh0LGUsbik+MCYmRmkocixuLHQpPjAhPUZpKHIsbixlKT4wfWZ1bmN0aW9uIE9pKHQsZSl7cmV0dXJuIEZpKHQucHJldix0LHQubmV4dCk8MD9GaSh0LGUsdC5uZXh0KT49MCYmRmkodCx0LnByZXYsZSk+PTA6RmkodCxlLHQucHJldik8MHx8RmkodCx0Lm5leHQsZSk8MH1mdW5jdGlvbiBMaSh0LGUpe3ZhciByPW5ldyBSaSh0LmksdC54LHQueSksbj1uZXcgUmkoZS5pLGUueCxlLnkpLGk9dC5uZXh0LG89ZS5wcmV2O3JldHVybiB0Lm5leHQ9ZSxlLnByZXY9dCxyLm5leHQ9aSxpLnByZXY9cixuLm5leHQ9cixyLnByZXY9bixvLm5leHQ9bixuLnByZXY9byxufWZ1bmN0aW9uIGppKHQsZSxyLG4pe3ZhciBpPW5ldyBSaSh0LGUscik7cmV0dXJuIG4/KGkubmV4dD1uLm5leHQsaS5wcmV2PW4sbi5uZXh0LnByZXY9aSxuLm5leHQ9aSk6KGkucHJldj1pLGkubmV4dD1pKSxpfWZ1bmN0aW9uIHFpKHQpe3QubmV4dC5wcmV2PXQucHJldix0LnByZXYubmV4dD10Lm5leHQsdC5wcmV2WiYmKHQucHJldloubmV4dFo9dC5uZXh0WiksdC5uZXh0WiYmKHQubmV4dFoucHJldlo9dC5wcmV2Wik7fWZ1bmN0aW9uIFJpKHQsZSxyKXt0aGlzLmk9dCx0aGlzLng9ZSx0aGlzLnk9cix0aGlzLnByZXY9bnVsbCx0aGlzLm5leHQ9bnVsbCx0aGlzLno9bnVsbCx0aGlzLnByZXZaPW51bGwsdGhpcy5uZXh0Wj1udWxsLHRoaXMuc3RlaW5lcj0hMTt9ZnVuY3Rpb24gVWkodCxlLHIsbil7Zm9yKHZhciBpPTAsbz1lLGE9ci1uO288cjtvKz1uKWkrPSh0W2FdLXRbb10pKih0W28rMV0rdFthKzFdKSxhPW87cmV0dXJuIGl9eGkuZGV2aWF0aW9uPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPWUmJmUubGVuZ3RoLG89aT9lWzBdKnI6dC5sZW5ndGgsYT1NYXRoLmFicyhVaSh0LDAsbyxyKSk7aWYoaSlmb3IodmFyIHM9MCx1PWUubGVuZ3RoO3M8dTtzKyspe3ZhciBsPWVbc10qcixwPXM8dS0xP2VbcysxXSpyOnQubGVuZ3RoO2EtPU1hdGguYWJzKFVpKHQsbCxwLHIpKTt9dmFyIGM9MDtmb3Iocz0wO3M8bi5sZW5ndGg7cys9Myl7dmFyIGg9bltzXSpyLGY9bltzKzFdKnIseT1uW3MrMl0qcjtjKz1NYXRoLmFicygodFtoXS10W3ldKSoodFtmKzFdLXRbaCsxXSktKHRbaF0tdFtmXSkqKHRbeSsxXS10W2grMV0pKTt9cmV0dXJuIDA9PT1hJiYwPT09Yz8wOk1hdGguYWJzKChjLWEpL2EpfSx4aS5mbGF0dGVuPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10WzBdWzBdLmxlbmd0aCxyPXt2ZXJ0aWNlczpbXSxob2xlczpbXSxkaW1lbnNpb25zOmV9LG49MCxpPTA7aTx0Lmxlbmd0aDtpKyspe2Zvcih2YXIgbz0wO288dFtpXS5sZW5ndGg7bysrKWZvcih2YXIgYT0wO2E8ZTthKyspci52ZXJ0aWNlcy5wdXNoKHRbaV1bb11bYV0pO2k+MCYmKG4rPXRbaS0xXS5sZW5ndGgsci5ob2xlcy5wdXNoKG4pKTt9cmV0dXJuIHJ9LG1pLmRlZmF1bHQ9Z2k7dmFyIERpPVppLE5pPVppO2Z1bmN0aW9uIFppKHQsZSxyLG4saSl7IWZ1bmN0aW9uIHQoZSxyLG4saSxvKXtmb3IoO2k+bjspe2lmKGktbj42MDApe3ZhciBhPWktbisxLHM9ci1uKzEsdT1NYXRoLmxvZyhhKSxsPS41Kk1hdGguZXhwKDIqdS8zKSxwPS41Kk1hdGguc3FydCh1KmwqKGEtbCkvYSkqKHMtYS8yPDA/LTE6MSksYz1NYXRoLm1heChuLE1hdGguZmxvb3Ioci1zKmwvYStwKSksaD1NYXRoLm1pbihpLE1hdGguZmxvb3IocisoYS1zKSpsL2ErcCkpO3QoZSxyLGMsaCxvKTt9dmFyIGY9ZVtyXSx5PW4sZD1pO2ZvcihLaShlLG4sciksbyhlW2ldLGYpPjAmJktpKGUsbixpKTt5PGQ7KXtmb3IoS2koZSx5LGQpLHkrKyxkLS07byhlW3ldLGYpPDA7KXkrKztmb3IoO28oZVtkXSxmKT4wOylkLS07fTA9PT1vKGVbbl0sZik/S2koZSxuLGQpOktpKGUsKytkLGkpLGQ8PXImJihuPWQrMSkscjw9ZCYmKGk9ZC0xKTt9fSh0LGUscnx8MCxufHx0Lmxlbmd0aC0xLGl8fEppKTt9ZnVuY3Rpb24gS2kodCxlLHIpe3ZhciBuPXRbZV07dFtlXT10W3JdLHRbcl09bjt9ZnVuY3Rpb24gSmkodCxlKXtyZXR1cm4gdDxlPy0xOnQ+ZT8xOjB9ZnVuY3Rpb24gJGkodCxlKXt2YXIgcj10Lmxlbmd0aDtpZihyPD0xKXJldHVyblt0XTtmb3IodmFyIG4saSxvPVtdLGE9MDthPHI7YSsrKXt2YXIgcz1fKHRbYV0pOzAhPT1zJiYodFthXS5hcmVhPU1hdGguYWJzKHMpLHZvaWQgMD09PWkmJihpPXM8MCksaT09PXM8MD8obiYmby5wdXNoKG4pLG49W3RbYV1dKTpuLnB1c2godFthXSkpO31pZihuJiZvLnB1c2gobiksZT4xKWZvcih2YXIgdT0wO3U8by5sZW5ndGg7dSsrKW9bdV0ubGVuZ3RoPD1lfHwoRGkob1t1XSxlLDEsb1t1XS5sZW5ndGgtMSxIaSksb1t1XT1vW3VdLnNsaWNlKDAsZSkpO3JldHVybiBvfWZ1bmN0aW9uIEhpKHQsZSl7cmV0dXJuIGUuYXJlYS10LmFyZWF9RGkuZGVmYXVsdD1OaTt2YXIgWGk9ZnVuY3Rpb24odCl7dGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheT1uZXcgWHIsdGhpcy5pbmRleEFycmF5PW5ldyBwbix0aGlzLmluZGV4QXJyYXkyPW5ldyBjbix0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucz1uZXcgRW4odmksdC5sYXllcnMsdC56b29tKSx0aGlzLnNlZ21lbnRzPW5ldyB6bix0aGlzLnNlZ21lbnRzMj1uZXcgem47fTtYaS5wcm90b3R5cGUucG9wdWxhdGU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLG89aS5mZWF0dXJlLGE9aS5pbmRleCxzPWkuc291cmNlTGF5ZXJJbmRleDtpZih0aGlzLmxheWVyc1swXS5fZmVhdHVyZUZpbHRlcihuZXcgQnIodGhpcy56b29tKSxvKSl7dmFyIHU9TG4obyk7dGhpcy5hZGRGZWF0dXJlKG8sdSksZS5mZWF0dXJlSW5kZXguaW5zZXJ0KG8sdSxhLHMsdGhpcy5pbmRleCk7fX19LFhpLnByb3RvdHlwZS5pc0VtcHR5PWZ1bmN0aW9uKCl7cmV0dXJuIDA9PT10aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aH0sWGkucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmxheW91dFZlcnRleEFycmF5LHZpKSx0aGlzLmluZGV4QnVmZmVyPXQuY3JlYXRlSW5kZXhCdWZmZXIodGhpcy5pbmRleEFycmF5KSx0aGlzLmluZGV4QnVmZmVyMj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheTIpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnVwbG9hZCh0KTt9LFhpLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlcjIuZGVzdHJveSgpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzMi5kZXN0cm95KCkpO30sWGkucHJvdG90eXBlLmFkZEZlYXR1cmU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPSRpKGUsNTAwKTtyPG4ubGVuZ3RoO3IrPTEpe2Zvcih2YXIgaT1uW3JdLG89MCxhPTAscz1pO2E8cy5sZW5ndGg7YSs9MSl7bys9c1thXS5sZW5ndGg7fWZvcih2YXIgdT10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KG8sdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpLGw9dS52ZXJ0ZXhMZW5ndGgscD1bXSxjPVtdLGg9MCxmPWk7aDxmLmxlbmd0aDtoKz0xKXt2YXIgeT1mW2hdO2lmKDAhPT15Lmxlbmd0aCl7eSE9PWlbMF0mJmMucHVzaChwLmxlbmd0aC8yKTt2YXIgZD10aGlzLnNlZ21lbnRzMi5wcmVwYXJlU2VnbWVudCh5Lmxlbmd0aCx0aGlzLmxheW91dFZlcnRleEFycmF5LHRoaXMuaW5kZXhBcnJheTIpLHY9ZC52ZXJ0ZXhMZW5ndGg7dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheS5lbXBsYWNlQmFjayh5WzBdLngseVswXS55KSx0aGlzLmluZGV4QXJyYXkyLmVtcGxhY2VCYWNrKHYreS5sZW5ndGgtMSx2KSxwLnB1c2goeVswXS54KSxwLnB1c2goeVswXS55KTtmb3IodmFyIG09MTttPHkubGVuZ3RoO20rKyl0aGlzLmxheW91dFZlcnRleEFycmF5LmVtcGxhY2VCYWNrKHlbbV0ueCx5W21dLnkpLHRoaXMuaW5kZXhBcnJheTIuZW1wbGFjZUJhY2sodittLTEsdittKSxwLnB1c2goeVttXS54KSxwLnB1c2goeVttXS55KTtkLnZlcnRleExlbmd0aCs9eS5sZW5ndGgsZC5wcmltaXRpdmVMZW5ndGgrPXkubGVuZ3RoO319Zm9yKHZhciBnPW1pKHAsYykseD0wO3g8Zy5sZW5ndGg7eCs9Myl0aGlzLmluZGV4QXJyYXkuZW1wbGFjZUJhY2sobCtnW3hdLGwrZ1t4KzFdLGwrZ1t4KzJdKTt1LnZlcnRleExlbmd0aCs9byx1LnByaW1pdGl2ZUxlbmd0aCs9Zy5sZW5ndGgvMzt9dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMucG9wdWxhdGVQYWludEFycmF5cyh0aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aCx0KTt9LGhyKFwiRmlsbEJ1Y2tldFwiLFhpLHtvbWl0OltcImxheWVyc1wiXX0pO3ZhciBHaT17cGFpbnQ6bmV3IERyKHtcImZpbGwtYW50aWFsaWFzXCI6bmV3IGpyKEUucGFpbnRfZmlsbFtcImZpbGwtYW50aWFsaWFzXCJdKSxcImZpbGwtb3BhY2l0eVwiOm5ldyBxcihFLnBhaW50X2ZpbGxbXCJmaWxsLW9wYWNpdHlcIl0pLFwiZmlsbC1jb2xvclwiOm5ldyBxcihFLnBhaW50X2ZpbGxbXCJmaWxsLWNvbG9yXCJdKSxcImZpbGwtb3V0bGluZS1jb2xvclwiOm5ldyBxcihFLnBhaW50X2ZpbGxbXCJmaWxsLW91dGxpbmUtY29sb3JcIl0pLFwiZmlsbC10cmFuc2xhdGVcIjpuZXcganIoRS5wYWludF9maWxsW1wiZmlsbC10cmFuc2xhdGVcIl0pLFwiZmlsbC10cmFuc2xhdGUtYW5jaG9yXCI6bmV3IGpyKEUucGFpbnRfZmlsbFtcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiXSksXCJmaWxsLXBhdHRlcm5cIjpuZXcgUnIoRS5wYWludF9maWxsW1wiZmlsbC1wYXR0ZXJuXCJdKX0pfSxZaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUsR2kpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUucmVjYWxjdWxhdGU9ZnVuY3Rpb24odCl7dGhpcy5wYWludD10aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQucG9zc2libHlFdmFsdWF0ZSh0KTt2YXIgZT10aGlzLnBhaW50Ll92YWx1ZXNbXCJmaWxsLW91dGxpbmUtY29sb3JcIl07XCJjb25zdGFudFwiPT09ZS52YWx1ZS5raW5kJiZ2b2lkIDA9PT1lLnZhbHVlLnZhbHVlJiYodGhpcy5wYWludC5fdmFsdWVzW1wiZmlsbC1vdXRsaW5lLWNvbG9yXCJdPXRoaXMucGFpbnQuX3ZhbHVlc1tcImZpbGwtY29sb3JcIl0pO30sZS5wcm90b3R5cGUuY3JlYXRlQnVja2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgWGkodCl9LGUucHJvdG90eXBlLnF1ZXJ5UmFkaXVzPWZ1bmN0aW9uKCl7cmV0dXJuIFluKHRoaXMucGFpbnQuZ2V0KFwiZmlsbC10cmFuc2xhdGVcIikpfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4saSxvKXtyZXR1cm4gVW4oV24odCx0aGlzLnBhaW50LmdldChcImZpbGwtdHJhbnNsYXRlXCIpLHRoaXMucGFpbnQuZ2V0KFwiZmlsbC10cmFuc2xhdGUtYW5jaG9yXCIpLGkuYW5nbGUsbykscil9LGV9KE5yKSxXaT0kcihbe25hbWU6XCJhX3Bvc1wiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn0se25hbWU6XCJhX25vcm1hbF9lZFwiLGNvbXBvbmVudHM6NCx0eXBlOlwiSW50MTZcIn1dLDQpLm1lbWJlcnMsUWk9TWF0aC5wb3coMiwxMyk7ZnVuY3Rpb24gdG8odCxlLHIsbixpLG8sYSxzKXt0LmVtcGxhY2VCYWNrKGUsciwyKk1hdGguZmxvb3IobipRaSkrYSxpKlFpKjIsbypRaSoyLE1hdGgucm91bmQocykpO312YXIgZW89ZnVuY3Rpb24odCl7dGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheT1uZXcgWXIsdGhpcy5pbmRleEFycmF5PW5ldyBwbix0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucz1uZXcgRW4oV2ksdC5sYXllcnMsdC56b29tKSx0aGlzLnNlZ21lbnRzPW5ldyB6bjt9O2Z1bmN0aW9uIHJvKHQsZSl7cmV0dXJuIHQueD09PWUueCYmKHQueDwwfHx0Lng+UG4pfHx0Lnk9PT1lLnkmJih0Lnk8MHx8dC55PlBuKX1mdW5jdGlvbiBubyh0KXtyZXR1cm4gdC5ldmVyeShmdW5jdGlvbih0KXtyZXR1cm4gdC54PDB9KXx8dC5ldmVyeShmdW5jdGlvbih0KXtyZXR1cm4gdC54PlBufSl8fHQuZXZlcnkoZnVuY3Rpb24odCl7cmV0dXJuIHQueTwwfSl8fHQuZXZlcnkoZnVuY3Rpb24odCl7cmV0dXJuIHQueT5Qbn0pfWVvLnByb3RvdHlwZS5wb3B1bGF0ZT1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49dDtyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl0sbz1pLmZlYXR1cmUsYT1pLmluZGV4LHM9aS5zb3VyY2VMYXllckluZGV4O2lmKHRoaXMubGF5ZXJzWzBdLl9mZWF0dXJlRmlsdGVyKG5ldyBCcih0aGlzLnpvb20pLG8pKXt2YXIgdT1MbihvKTt0aGlzLmFkZEZlYXR1cmUobyx1KSxlLmZlYXR1cmVJbmRleC5pbnNlcnQobyx1LGEscyx0aGlzLmluZGV4KTt9fX0sZW8ucHJvdG90eXBlLmlzRW1wdHk9ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RofSxlby5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe3RoaXMubGF5b3V0VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMubGF5b3V0VmVydGV4QXJyYXksV2kpLHRoaXMuaW5kZXhCdWZmZXI9dC5jcmVhdGVJbmRleEJ1ZmZlcih0aGlzLmluZGV4QXJyYXkpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnVwbG9hZCh0KTt9LGVvLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZGVzdHJveSgpLHRoaXMuc2VnbWVudHMuZGVzdHJveSgpKTt9LGVvLnByb3RvdHlwZS5hZGRGZWF0dXJlPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj0kaShlLDUwMCk7cjxuLmxlbmd0aDtyKz0xKXtmb3IodmFyIGk9bltyXSxvPTAsYT0wLHM9aTthPHMubGVuZ3RoO2ErPTEpe28rPXNbYV0ubGVuZ3RoO31mb3IodmFyIHU9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KSxsPTAscD1pO2w8cC5sZW5ndGg7bCs9MSl7dmFyIGM9cFtsXTtpZigwIT09Yy5sZW5ndGgmJiFubyhjKSlmb3IodmFyIGg9MCxmPTA7ZjxjLmxlbmd0aDtmKyspe3ZhciB5PWNbZl07aWYoZj49MSl7dmFyIGQ9Y1tmLTFdO2lmKCFybyh5LGQpKXt1LnZlcnRleExlbmd0aCs0PnpuLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIJiYodT10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDQsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpKTt2YXIgdj15LnN1YihkKS5fcGVycCgpLl91bml0KCksbT1kLmRpc3QoeSk7aCttPjMyNzY4JiYoaD0wKSx0byh0aGlzLmxheW91dFZlcnRleEFycmF5LHkueCx5Lnksdi54LHYueSwwLDAsaCksdG8odGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx5LngseS55LHYueCx2LnksMCwxLGgpLGgrPW0sdG8odGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxkLngsZC55LHYueCx2LnksMCwwLGgpLHRvKHRoaXMubGF5b3V0VmVydGV4QXJyYXksZC54LGQueSx2Lngsdi55LDAsMSxoKTt2YXIgZz11LnZlcnRleExlbmd0aDt0aGlzLmluZGV4QXJyYXkuZW1wbGFjZUJhY2soZyxnKzEsZysyKSx0aGlzLmluZGV4QXJyYXkuZW1wbGFjZUJhY2soZysxLGcrMixnKzMpLHUudmVydGV4TGVuZ3RoKz00LHUucHJpbWl0aXZlTGVuZ3RoKz0yO319fX11LnZlcnRleExlbmd0aCtvPnpuLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIJiYodT10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KG8sdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpKTtmb3IodmFyIHg9W10sYj1bXSx3PXUudmVydGV4TGVuZ3RoLF89MCxBPWk7XzxBLmxlbmd0aDtfKz0xKXt2YXIgaz1BW19dO2lmKDAhPT1rLmxlbmd0aCl7ayE9PWlbMF0mJmIucHVzaCh4Lmxlbmd0aC8yKTtmb3IodmFyIHo9MDt6PGsubGVuZ3RoO3orKyl7dmFyIFM9a1t6XTt0byh0aGlzLmxheW91dFZlcnRleEFycmF5LFMueCxTLnksMCwwLDEsMSwwKSx4LnB1c2goUy54KSx4LnB1c2goUy55KTt9fX1mb3IodmFyIE09bWkoeCxiKSxWPTA7VjxNLmxlbmd0aDtWKz0zKXRoaXMuaW5kZXhBcnJheS5lbXBsYWNlQmFjayh3K01bVl0sdytNW1YrMV0sdytNW1YrMl0pO3UucHJpbWl0aXZlTGVuZ3RoKz1NLmxlbmd0aC8zLHUudmVydGV4TGVuZ3RoKz1vO310aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5wb3B1bGF0ZVBhaW50QXJyYXlzKHRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RoLHQpO30saHIoXCJGaWxsRXh0cnVzaW9uQnVja2V0XCIsZW8se29taXQ6W1wibGF5ZXJzXCJdfSk7dmFyIGlvPXtwYWludDpuZXcgRHIoe1wiZmlsbC1leHRydXNpb24tb3BhY2l0eVwiOm5ldyBqcihFW1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi1vcGFjaXR5XCJdKSxcImZpbGwtZXh0cnVzaW9uLWNvbG9yXCI6bmV3IHFyKEVbXCJwYWludF9maWxsLWV4dHJ1c2lvblwiXVtcImZpbGwtZXh0cnVzaW9uLWNvbG9yXCJdKSxcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiOm5ldyBqcihFW1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGVcIl0pLFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlLWFuY2hvclwiOm5ldyBqcihFW1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGUtYW5jaG9yXCJdKSxcImZpbGwtZXh0cnVzaW9uLXBhdHRlcm5cIjpuZXcgUnIoRVtcInBhaW50X2ZpbGwtZXh0cnVzaW9uXCJdW1wiZmlsbC1leHRydXNpb24tcGF0dGVyblwiXSksXCJmaWxsLWV4dHJ1c2lvbi1oZWlnaHRcIjpuZXcgcXIoRVtcInBhaW50X2ZpbGwtZXh0cnVzaW9uXCJdW1wiZmlsbC1leHRydXNpb24taGVpZ2h0XCJdKSxcImZpbGwtZXh0cnVzaW9uLWJhc2VcIjpuZXcgcXIoRVtcInBhaW50X2ZpbGwtZXh0cnVzaW9uXCJdW1wiZmlsbC1leHRydXNpb24tYmFzZVwiXSl9KX0sb289ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlKXt0LmNhbGwodGhpcyxlLGlvKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmNyZWF0ZUJ1Y2tldD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGVvKHQpfSxlLnByb3RvdHlwZS5xdWVyeVJhZGl1cz1mdW5jdGlvbigpe3JldHVybiBZbih0aGlzLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiKSl9LGUucHJvdG90eXBlLnF1ZXJ5SW50ZXJzZWN0c0ZlYXR1cmU9ZnVuY3Rpb24odCxlLHIsbixpLG8pe3JldHVybiBVbihXbih0LHRoaXMucGFpbnQuZ2V0KFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlXCIpLHRoaXMucGFpbnQuZ2V0KFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlLWFuY2hvclwiKSxpLmFuZ2xlLG8pLHIpfSxlLnByb3RvdHlwZS5oYXNPZmZzY3JlZW5QYXNzPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPT10aGlzLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLW9wYWNpdHlcIikmJlwibm9uZVwiIT09dGhpcy52aXNpYmlsaXR5fSxlLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oKXt0aGlzLnZpZXdwb3J0RnJhbWUmJih0aGlzLnZpZXdwb3J0RnJhbWUuZGVzdHJveSgpLHRoaXMudmlld3BvcnRGcmFtZT1udWxsKTt9LGV9KE5yKSxhbz0kcihbe25hbWU6XCJhX3Bvc19ub3JtYWxcIixjb21wb25lbnRzOjQsdHlwZTpcIkludDE2XCJ9LHtuYW1lOlwiYV9kYXRhXCIsY29tcG9uZW50czo0LHR5cGU6XCJVaW50OFwifV0sNCkubWVtYmVycyxzbz11bztmdW5jdGlvbiB1byh0LGUscixuLGkpe3RoaXMucHJvcGVydGllcz17fSx0aGlzLmV4dGVudD1yLHRoaXMudHlwZT0wLHRoaXMuX3BiZj10LHRoaXMuX2dlb21ldHJ5PS0xLHRoaXMuX2tleXM9bix0aGlzLl92YWx1ZXM9aSx0LnJlYWRGaWVsZHMobG8sdGhpcyxlKTt9ZnVuY3Rpb24gbG8odCxlLHIpezE9PXQ/ZS5pZD1yLnJlYWRWYXJpbnQoKToyPT10P2Z1bmN0aW9uKHQsZSl7dmFyIHI9dC5yZWFkVmFyaW50KCkrdC5wb3M7Zm9yKDt0LnBvczxyOyl7dmFyIG49ZS5fa2V5c1t0LnJlYWRWYXJpbnQoKV0saT1lLl92YWx1ZXNbdC5yZWFkVmFyaW50KCldO2UucHJvcGVydGllc1tuXT1pO319KHIsZSk6Mz09dD9lLnR5cGU9ci5yZWFkVmFyaW50KCk6ND09dCYmKGUuX2dlb21ldHJ5PXIucG9zKTt9ZnVuY3Rpb24gcG8odCl7Zm9yKHZhciBlLHIsbj0wLGk9MCxvPXQubGVuZ3RoLGE9by0xO2k8bzthPWkrKyllPXRbaV0sbis9KChyPXRbYV0pLngtZS54KSooZS55K3IueSk7cmV0dXJuIG59dW8udHlwZXM9W1wiVW5rbm93blwiLFwiUG9pbnRcIixcIkxpbmVTdHJpbmdcIixcIlBvbHlnb25cIl0sdW8ucHJvdG90eXBlLmxvYWRHZW9tZXRyeT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3BiZjt0LnBvcz10aGlzLl9nZW9tZXRyeTtmb3IodmFyIGUscj10LnJlYWRWYXJpbnQoKSt0LnBvcyxuPTEsaT0wLG89MCxhPTAsdT1bXTt0LnBvczxyOyl7aWYoaTw9MCl7dmFyIGw9dC5yZWFkVmFyaW50KCk7bj03JmwsaT1sPj4zO31pZihpLS0sMT09PW58fDI9PT1uKW8rPXQucmVhZFNWYXJpbnQoKSxhKz10LnJlYWRTVmFyaW50KCksMT09PW4mJihlJiZ1LnB1c2goZSksZT1bXSksZS5wdXNoKG5ldyBzKG8sYSkpO2Vsc2V7aWYoNyE9PW4pdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biBjb21tYW5kIFwiK24pO2UmJmUucHVzaChlWzBdLmNsb25lKCkpO319cmV0dXJuIGUmJnUucHVzaChlKSx1fSx1by5wcm90b3R5cGUuYmJveD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3BiZjt0LnBvcz10aGlzLl9nZW9tZXRyeTtmb3IodmFyIGU9dC5yZWFkVmFyaW50KCkrdC5wb3Mscj0xLG49MCxpPTAsbz0wLGE9MS8wLHM9LTEvMCx1PTEvMCxsPS0xLzA7dC5wb3M8ZTspe2lmKG48PTApe3ZhciBwPXQucmVhZFZhcmludCgpO3I9NyZwLG49cD4+Mzt9aWYobi0tLDE9PT1yfHwyPT09cikoaSs9dC5yZWFkU1ZhcmludCgpKTxhJiYoYT1pKSxpPnMmJihzPWkpLChvKz10LnJlYWRTVmFyaW50KCkpPHUmJih1PW8pLG8+bCYmKGw9byk7ZWxzZSBpZig3IT09cil0aHJvdyBuZXcgRXJyb3IoXCJ1bmtub3duIGNvbW1hbmQgXCIrcil9cmV0dXJuW2EsdSxzLGxdfSx1by5wcm90b3R5cGUudG9HZW9KU09OPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixpLG89dGhpcy5leHRlbnQqTWF0aC5wb3coMixyKSxhPXRoaXMuZXh0ZW50KnQscz10aGlzLmV4dGVudCplLHU9dGhpcy5sb2FkR2VvbWV0cnkoKSxsPXVvLnR5cGVzW3RoaXMudHlwZV07ZnVuY3Rpb24gcCh0KXtmb3IodmFyIGU9MDtlPHQubGVuZ3RoO2UrKyl7dmFyIHI9dFtlXSxuPTE4MC0zNjAqKHIueStzKS9vO3RbZV09WzM2MCooci54K2EpL28tMTgwLDM2MC9NYXRoLlBJKk1hdGguYXRhbihNYXRoLmV4cChuKk1hdGguUEkvMTgwKSktOTBdO319c3dpdGNoKHRoaXMudHlwZSl7Y2FzZSAxOnZhciBjPVtdO2ZvcihuPTA7bjx1Lmxlbmd0aDtuKyspY1tuXT11W25dWzBdO3AodT1jKTticmVhaztjYXNlIDI6Zm9yKG49MDtuPHUubGVuZ3RoO24rKylwKHVbbl0pO2JyZWFrO2Nhc2UgMzpmb3IodT1mdW5jdGlvbih0KXt2YXIgZT10Lmxlbmd0aDtpZihlPD0xKXJldHVyblt0XTtmb3IodmFyIHIsbixpPVtdLG89MDtvPGU7bysrKXt2YXIgYT1wbyh0W29dKTswIT09YSYmKHZvaWQgMD09PW4mJihuPWE8MCksbj09PWE8MD8ociYmaS5wdXNoKHIpLHI9W3Rbb11dKTpyLnB1c2godFtvXSkpO31yJiZpLnB1c2gocik7cmV0dXJuIGl9KHUpLG49MDtuPHUubGVuZ3RoO24rKylmb3IoaT0wO2k8dVtuXS5sZW5ndGg7aSsrKXAodVtuXVtpXSk7fTE9PT11Lmxlbmd0aD91PXVbMF06bD1cIk11bHRpXCIrbDt2YXIgaD17dHlwZTpcIkZlYXR1cmVcIixnZW9tZXRyeTp7dHlwZTpsLGNvb3JkaW5hdGVzOnV9LHByb3BlcnRpZXM6dGhpcy5wcm9wZXJ0aWVzfTtyZXR1cm5cImlkXCJpbiB0aGlzJiYoaC5pZD10aGlzLmlkKSxofTt2YXIgY289aG87ZnVuY3Rpb24gaG8odCxlKXt0aGlzLnZlcnNpb249MSx0aGlzLm5hbWU9bnVsbCx0aGlzLmV4dGVudD00MDk2LHRoaXMubGVuZ3RoPTAsdGhpcy5fcGJmPXQsdGhpcy5fa2V5cz1bXSx0aGlzLl92YWx1ZXM9W10sdGhpcy5fZmVhdHVyZXM9W10sdC5yZWFkRmllbGRzKGZvLHRoaXMsZSksdGhpcy5sZW5ndGg9dGhpcy5fZmVhdHVyZXMubGVuZ3RoO31mdW5jdGlvbiBmbyh0LGUscil7MTU9PT10P2UudmVyc2lvbj1yLnJlYWRWYXJpbnQoKToxPT09dD9lLm5hbWU9ci5yZWFkU3RyaW5nKCk6NT09PXQ/ZS5leHRlbnQ9ci5yZWFkVmFyaW50KCk6Mj09PXQ/ZS5fZmVhdHVyZXMucHVzaChyLnBvcyk6Mz09PXQ/ZS5fa2V5cy5wdXNoKHIucmVhZFN0cmluZygpKTo0PT09dCYmZS5fdmFsdWVzLnB1c2goZnVuY3Rpb24odCl7dmFyIGU9bnVsbCxyPXQucmVhZFZhcmludCgpK3QucG9zO2Zvcig7dC5wb3M8cjspe3ZhciBuPXQucmVhZFZhcmludCgpPj4zO2U9MT09PW4/dC5yZWFkU3RyaW5nKCk6Mj09PW4/dC5yZWFkRmxvYXQoKTozPT09bj90LnJlYWREb3VibGUoKTo0PT09bj90LnJlYWRWYXJpbnQ2NCgpOjU9PT1uP3QucmVhZFZhcmludCgpOjY9PT1uP3QucmVhZFNWYXJpbnQoKTo3PT09bj90LnJlYWRCb29sZWFuKCk6bnVsbDt9cmV0dXJuIGV9KHIpKTt9ZnVuY3Rpb24geW8odCxlLHIpe2lmKDM9PT10KXt2YXIgbj1uZXcgY28ocixyLnJlYWRWYXJpbnQoKStyLnBvcyk7bi5sZW5ndGgmJihlW24ubmFtZV09bik7fX1oby5wcm90b3R5cGUuZmVhdHVyZT1mdW5jdGlvbih0KXtpZih0PDB8fHQ+PXRoaXMuX2ZlYXR1cmVzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoXCJmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHNcIik7dGhpcy5fcGJmLnBvcz10aGlzLl9mZWF0dXJlc1t0XTt2YXIgZT10aGlzLl9wYmYucmVhZFZhcmludCgpK3RoaXMuX3BiZi5wb3M7cmV0dXJuIG5ldyBzbyh0aGlzLl9wYmYsZSx0aGlzLmV4dGVudCx0aGlzLl9rZXlzLHRoaXMuX3ZhbHVlcyl9O3ZhciB2bz17VmVjdG9yVGlsZTpmdW5jdGlvbih0LGUpe3RoaXMubGF5ZXJzPXQucmVhZEZpZWxkcyh5byx7fSxlKTt9LFZlY3RvclRpbGVGZWF0dXJlOnNvLFZlY3RvclRpbGVMYXllcjpjb30sbW89dm8uVmVjdG9yVGlsZUZlYXR1cmUudHlwZXMsZ289NjMseG89TWF0aC5jb3MoTWF0aC5QSS8xODAqMzcuNSksYm89LjUsd289TWF0aC5wb3coMiwxNCkvYm87ZnVuY3Rpb24gX28odCxlLHIsbixpLG8sYSl7dC5lbXBsYWNlQmFjayhlLngsZS55LG4/MTowLGk/MTotMSxNYXRoLnJvdW5kKGdvKnIueCkrMTI4LE1hdGgucm91bmQoZ28qci55KSsxMjgsMSsoMD09PW8/MDpvPDA/LTE6MSl8KGEqYm8mNjMpPDwyLGEqYm8+PjYpO312YXIgQW89ZnVuY3Rpb24odCl7dGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheT1uZXcgV3IsdGhpcy5pbmRleEFycmF5PW5ldyBwbix0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucz1uZXcgRW4oYW8sdC5sYXllcnMsdC56b29tKSx0aGlzLnNlZ21lbnRzPW5ldyB6bjt9O2Z1bmN0aW9uIGtvKHQsZSl7cmV0dXJuKHQvZS50aWxlVG90YWwqKGUuZW5kLWUuc3RhcnQpK2Uuc3RhcnQpKih3by0xKX1Bby5wcm90b3R5cGUucG9wdWxhdGU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLG89aS5mZWF0dXJlLGE9aS5pbmRleCxzPWkuc291cmNlTGF5ZXJJbmRleDtpZih0aGlzLmxheWVyc1swXS5fZmVhdHVyZUZpbHRlcihuZXcgQnIodGhpcy56b29tKSxvKSl7dmFyIHU9TG4obyk7dGhpcy5hZGRGZWF0dXJlKG8sdSksZS5mZWF0dXJlSW5kZXguaW5zZXJ0KG8sdSxhLHMsdGhpcy5pbmRleCk7fX19LEFvLnByb3RvdHlwZS5pc0VtcHR5PWZ1bmN0aW9uKCl7cmV0dXJuIDA9PT10aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aH0sQW8ucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmxheW91dFZlcnRleEFycmF5LGFvKSx0aGlzLmluZGV4QnVmZmVyPXQuY3JlYXRlSW5kZXhCdWZmZXIodGhpcy5pbmRleEFycmF5KSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy51cGxvYWQodCk7fSxBby5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMubGF5b3V0VmVydGV4QnVmZmVyJiYodGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXIuZGVzdHJveSgpLHRoaXMuaW5kZXhCdWZmZXIuZGVzdHJveSgpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzLmRlc3Ryb3koKSk7fSxBby5wcm90b3R5cGUuYWRkRmVhdHVyZT1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj10aGlzLmxheWVyc1swXS5sYXlvdXQsbj1yLmdldChcImxpbmUtam9pblwiKS5ldmFsdWF0ZSh0KSxpPXIuZ2V0KFwibGluZS1jYXBcIiksbz1yLmdldChcImxpbmUtbWl0ZXItbGltaXRcIiksYT1yLmdldChcImxpbmUtcm91bmQtbGltaXRcIikscz0wLHU9ZTtzPHUubGVuZ3RoO3MrPTEpe3ZhciBsPXVbc107dGhpcy5hZGRMaW5lKGwsdCxuLGksbyxhKTt9fSxBby5wcm90b3R5cGUuYWRkTGluZT1mdW5jdGlvbih0LGUscixuLGksbyl7dmFyIGE9bnVsbDtlLnByb3BlcnRpZXMmJmUucHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShcIm1hcGJveF9jbGlwX3N0YXJ0XCIpJiZlLnByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkoXCJtYXBib3hfY2xpcF9lbmRcIikmJihhPXtzdGFydDplLnByb3BlcnRpZXMubWFwYm94X2NsaXBfc3RhcnQsZW5kOmUucHJvcGVydGllcy5tYXBib3hfY2xpcF9lbmQsdGlsZVRvdGFsOnZvaWQgMH0pO2Zvcih2YXIgcz1cIlBvbHlnb25cIj09PW1vW2UudHlwZV0sdT10Lmxlbmd0aDt1Pj0yJiZ0W3UtMV0uZXF1YWxzKHRbdS0yXSk7KXUtLTtmb3IodmFyIGw9MDtsPHUtMSYmdFtsXS5lcXVhbHModFtsKzFdKTspbCsrO2lmKCEodTwocz8zOjIpKSl7YSYmKGEudGlsZVRvdGFsPWZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG4saSxvPTAsYT1lO2E8ci0xO2ErKyluPXRbYV0saT10W2ErMV0sbys9bi5kaXN0KGkpO3JldHVybiBvfSh0LGwsdSkpLFwiYmV2ZWxcIj09PXImJihpPTEuMDUpO3ZhciBwPVBuLyg1MTIqdGhpcy5vdmVyc2NhbGluZykqMTUsYz10W2xdLGg9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCgxMCp1LHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KTt0aGlzLmRpc3RhbmNlPTA7dmFyIGYseSxkLHY9bixtPXM/XCJidXR0XCI6bixnPSEwLHg9dm9pZCAwLGI9dm9pZCAwLHc9dm9pZCAwLF89dm9pZCAwO3RoaXMuZTE9dGhpcy5lMj10aGlzLmUzPS0xLHMmJihmPXRbdS0yXSxfPWMuc3ViKGYpLl91bml0KCkuX3BlcnAoKSk7Zm9yKHZhciBBPWw7QTx1O0ErKylpZighKGI9cyYmQT09PXUtMT90W2wrMV06dFtBKzFdKXx8IXRbQV0uZXF1YWxzKGIpKXtfJiYodz1fKSxmJiYoeD1mKSxmPXRbQV0sXz1iP2Iuc3ViKGYpLl91bml0KCkuX3BlcnAoKTp3O3ZhciBrPSh3PXd8fF8pLmFkZChfKTswPT09ay54JiYwPT09ay55fHxrLl91bml0KCk7dmFyIHo9ay54Kl8ueCtrLnkqXy55LFM9MCE9PXo/MS96OjEvMCxNPXo8eG8mJngmJmI7aWYoTSYmQT5sKXt2YXIgVj1mLmRpc3QoeCk7aWYoVj4yKnApe3ZhciBCPWYuc3ViKGYuc3ViKHgpLl9tdWx0KHAvVikuX3JvdW5kKCkpO3RoaXMuZGlzdGFuY2UrPUIuZGlzdCh4KSx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoQix0aGlzLmRpc3RhbmNlLHcubXVsdCgxKSwwLDAsITEsaCxhKSx4PUI7fX12YXIgQz14JiZiLEk9Qz9yOmI/djptO2lmKEMmJlwicm91bmRcIj09PUkmJihTPG8/ST1cIm1pdGVyXCI6Uzw9MiYmKEk9XCJmYWtlcm91bmRcIikpLFwibWl0ZXJcIj09PUkmJlM+aSYmKEk9XCJiZXZlbFwiKSxcImJldmVsXCI9PT1JJiYoUz4yJiYoST1cImZsaXBiZXZlbFwiKSxTPGkmJihJPVwibWl0ZXJcIikpLHgmJih0aGlzLmRpc3RhbmNlKz1mLmRpc3QoeCkpLFwibWl0ZXJcIj09PUkpay5fbXVsdChTKSx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLGssMCwwLCExLGgsYSk7ZWxzZSBpZihcImZsaXBiZXZlbFwiPT09SSl7aWYoUz4xMDApaz1fLmNsb25lKCkubXVsdCgtMSk7ZWxzZXt2YXIgRT13LngqXy55LXcueSpfLng+MD8tMToxLEY9Uyp3LmFkZChfKS5tYWcoKS93LnN1YihfKS5tYWcoKTtrLl9wZXJwKCkuX211bHQoRipFKTt9dGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSxrLDAsMCwhMSxoLGEpLHRoaXMuYWRkQ3VycmVudFZlcnRleChmLHRoaXMuZGlzdGFuY2Usay5tdWx0KC0xKSwwLDAsITEsaCxhKTt9ZWxzZSBpZihcImJldmVsXCI9PT1JfHxcImZha2Vyb3VuZFwiPT09SSl7dmFyIFA9dy54Kl8ueS13LnkqXy54PjAsVD0tTWF0aC5zcXJ0KFMqUy0xKTtpZihQPyhkPTAseT1UKTooeT0wLGQ9VCksZ3x8dGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSx3LHksZCwhMSxoLGEpLFwiZmFrZXJvdW5kXCI9PT1JKXtmb3IodmFyIE89TWF0aC5mbG9vcig4KiguNS0oei0uNSkpKSxMPXZvaWQgMCxqPTA7ajxPO2orKylMPV8ubXVsdCgoaisxKS8oTysxKSkuX2FkZCh3KS5fdW5pdCgpLHRoaXMuYWRkUGllU2xpY2VWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLEwsUCxoLGEpO3RoaXMuYWRkUGllU2xpY2VWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLGssUCxoLGEpO2Zvcih2YXIgcT1PLTE7cT49MDtxLS0pTD13Lm11bHQoKHErMSkvKE8rMSkpLl9hZGQoXykuX3VuaXQoKSx0aGlzLmFkZFBpZVNsaWNlVmVydGV4KGYsdGhpcy5kaXN0YW5jZSxMLFAsaCxhKTt9YiYmdGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSxfLC15LC1kLCExLGgsYSk7fWVsc2VcImJ1dHRcIj09PUk/KGd8fHRoaXMuYWRkQ3VycmVudFZlcnRleChmLHRoaXMuZGlzdGFuY2UsdywwLDAsITEsaCxhKSxiJiZ0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLF8sMCwwLCExLGgsYSkpOlwic3F1YXJlXCI9PT1JPyhnfHwodGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSx3LDEsMSwhMSxoLGEpLHRoaXMuZTE9dGhpcy5lMj0tMSksYiYmdGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSxfLC0xLC0xLCExLGgsYSkpOlwicm91bmRcIj09PUkmJihnfHwodGhpcy5hZGRDdXJyZW50VmVydGV4KGYsdGhpcy5kaXN0YW5jZSx3LDAsMCwhMSxoLGEpLHRoaXMuYWRkQ3VycmVudFZlcnRleChmLHRoaXMuZGlzdGFuY2UsdywxLDEsITAsaCxhKSx0aGlzLmUxPXRoaXMuZTI9LTEpLGImJih0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLF8sLTEsLTEsITAsaCxhKSx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZix0aGlzLmRpc3RhbmNlLF8sMCwwLCExLGgsYSkpKTtpZihNJiZBPHUtMSl7dmFyIFI9Zi5kaXN0KGIpO2lmKFI+MipwKXt2YXIgVT1mLmFkZChiLnN1YihmKS5fbXVsdChwL1IpLl9yb3VuZCgpKTt0aGlzLmRpc3RhbmNlKz1VLmRpc3QoZiksdGhpcy5hZGRDdXJyZW50VmVydGV4KFUsdGhpcy5kaXN0YW5jZSxfLm11bHQoMSksMCwwLCExLGgsYSksZj1VO319Zz0hMTt9dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMucG9wdWxhdGVQYWludEFycmF5cyh0aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aCxlKTt9fSxBby5wcm90b3R5cGUuYWRkQ3VycmVudFZlcnRleD1mdW5jdGlvbih0LGUscixuLGksbyxhLHMpe3ZhciB1LGw9dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxwPXRoaXMuaW5kZXhBcnJheTtzJiYoZT1rbyhlLHMpKSx1PXIuY2xvbmUoKSxuJiZ1Ll9zdWIoci5wZXJwKCkuX211bHQobikpLF9vKGwsdCx1LG8sITEsbixlKSx0aGlzLmUzPWEudmVydGV4TGVuZ3RoKyssdGhpcy5lMT49MCYmdGhpcy5lMj49MCYmKHAuZW1wbGFjZUJhY2sodGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMpLGEucHJpbWl0aXZlTGVuZ3RoKyspLHRoaXMuZTE9dGhpcy5lMix0aGlzLmUyPXRoaXMuZTMsdT1yLm11bHQoLTEpLGkmJnUuX3N1YihyLnBlcnAoKS5fbXVsdChpKSksX28obCx0LHUsbywhMCwtaSxlKSx0aGlzLmUzPWEudmVydGV4TGVuZ3RoKyssdGhpcy5lMT49MCYmdGhpcy5lMj49MCYmKHAuZW1wbGFjZUJhY2sodGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMpLGEucHJpbWl0aXZlTGVuZ3RoKyspLHRoaXMuZTE9dGhpcy5lMix0aGlzLmUyPXRoaXMuZTMsZT53by8yJiYhcyYmKHRoaXMuZGlzdGFuY2U9MCx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgodCx0aGlzLmRpc3RhbmNlLHIsbixpLG8sYSkpO30sQW8ucHJvdG90eXBlLmFkZFBpZVNsaWNlVmVydGV4PWZ1bmN0aW9uKHQsZSxyLG4saSxvKXtyPXIubXVsdChuPy0xOjEpO3ZhciBhPXRoaXMubGF5b3V0VmVydGV4QXJyYXkscz10aGlzLmluZGV4QXJyYXk7byYmKGU9a28oZSxvKSksX28oYSx0LHIsITEsbiwwLGUpLHRoaXMuZTM9aS52ZXJ0ZXhMZW5ndGgrKyx0aGlzLmUxPj0wJiZ0aGlzLmUyPj0wJiYocy5lbXBsYWNlQmFjayh0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyksaS5wcmltaXRpdmVMZW5ndGgrKyksbj90aGlzLmUyPXRoaXMuZTM6dGhpcy5lMT10aGlzLmUzO30saHIoXCJMaW5lQnVja2V0XCIsQW8se29taXQ6W1wibGF5ZXJzXCJdfSk7dmFyIHpvPW5ldyBEcih7XCJsaW5lLWNhcFwiOm5ldyBqcihFLmxheW91dF9saW5lW1wibGluZS1jYXBcIl0pLFwibGluZS1qb2luXCI6bmV3IHFyKEUubGF5b3V0X2xpbmVbXCJsaW5lLWpvaW5cIl0pLFwibGluZS1taXRlci1saW1pdFwiOm5ldyBqcihFLmxheW91dF9saW5lW1wibGluZS1taXRlci1saW1pdFwiXSksXCJsaW5lLXJvdW5kLWxpbWl0XCI6bmV3IGpyKEUubGF5b3V0X2xpbmVbXCJsaW5lLXJvdW5kLWxpbWl0XCJdKX0pLFNvPXtwYWludDpuZXcgRHIoe1wibGluZS1vcGFjaXR5XCI6bmV3IHFyKEUucGFpbnRfbGluZVtcImxpbmUtb3BhY2l0eVwiXSksXCJsaW5lLWNvbG9yXCI6bmV3IHFyKEUucGFpbnRfbGluZVtcImxpbmUtY29sb3JcIl0pLFwibGluZS10cmFuc2xhdGVcIjpuZXcganIoRS5wYWludF9saW5lW1wibGluZS10cmFuc2xhdGVcIl0pLFwibGluZS10cmFuc2xhdGUtYW5jaG9yXCI6bmV3IGpyKEUucGFpbnRfbGluZVtcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiXSksXCJsaW5lLXdpZHRoXCI6bmV3IHFyKEUucGFpbnRfbGluZVtcImxpbmUtd2lkdGhcIl0pLFwibGluZS1nYXAtd2lkdGhcIjpuZXcgcXIoRS5wYWludF9saW5lW1wibGluZS1nYXAtd2lkdGhcIl0pLFwibGluZS1vZmZzZXRcIjpuZXcgcXIoRS5wYWludF9saW5lW1wibGluZS1vZmZzZXRcIl0pLFwibGluZS1ibHVyXCI6bmV3IHFyKEUucGFpbnRfbGluZVtcImxpbmUtYmx1clwiXSksXCJsaW5lLWRhc2hhcnJheVwiOm5ldyBScihFLnBhaW50X2xpbmVbXCJsaW5lLWRhc2hhcnJheVwiXSksXCJsaW5lLXBhdHRlcm5cIjpuZXcgUnIoRS5wYWludF9saW5lW1wibGluZS1wYXR0ZXJuXCJdKSxcImxpbmUtZ3JhZGllbnRcIjpuZXcgVXIoRS5wYWludF9saW5lW1wibGluZS1ncmFkaWVudFwiXSl9KSxsYXlvdXQ6em99LE1vPW5ldyhmdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKGUscil7cmV0dXJuIHI9bmV3IEJyKE1hdGguZmxvb3Ioci56b29tKSx7bm93OnIubm93LGZhZGVEdXJhdGlvbjpyLmZhZGVEdXJhdGlvbix6b29tSGlzdG9yeTpyLnpvb21IaXN0b3J5LHRyYW5zaXRpb246ci50cmFuc2l0aW9ufSksdC5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZS5jYWxsKHRoaXMsZSxyKX0sZS5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24oZSxyLG4pe3JldHVybiByPWgoe30scix7em9vbTpNYXRoLmZsb29yKHIuem9vbSl9KSx0LnByb3RvdHlwZS5ldmFsdWF0ZS5jYWxsKHRoaXMsZSxyLG4pfSxlfShxcikpKFNvLnBhaW50LnByb3BlcnRpZXNbXCJsaW5lLXdpZHRoXCJdLnNwZWNpZmljYXRpb24pO01vLnVzZUludGVnZXJab29tPSEwO3ZhciBWbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUsU28pO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuc2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbihlLHIsbil7dC5wcm90b3R5cGUuc2V0UGFpbnRQcm9wZXJ0eS5jYWxsKHRoaXMsZSxyLG4pLFwibGluZS1ncmFkaWVudFwiPT09ZSYmdGhpcy5fdXBkYXRlR3JhZGllbnQoKTt9LGUucHJvdG90eXBlLl91cGRhdGVHcmFkaWVudD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQuX3ZhbHVlc1tcImxpbmUtZ3JhZGllbnRcIl0udmFsdWUuZXhwcmVzc2lvbjt0aGlzLmdyYWRpZW50PWhpKHQsXCJsaW5lUHJvZ3Jlc3NcIiksdGhpcy5ncmFkaWVudFRleHR1cmU9bnVsbDt9LGUucHJvdG90eXBlLnJlY2FsY3VsYXRlPWZ1bmN0aW9uKGUpe3QucHJvdG90eXBlLnJlY2FsY3VsYXRlLmNhbGwodGhpcyxlKSx0aGlzLnBhaW50Ll92YWx1ZXNbXCJsaW5lLWZsb29yd2lkdGhcIl09TW8ucG9zc2libHlFdmFsdWF0ZSh0aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQuX3ZhbHVlc1tcImxpbmUtd2lkdGhcIl0udmFsdWUsZSk7fSxlLnByb3RvdHlwZS5jcmVhdGVCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBBbyh0KX0sZS5wcm90b3R5cGUucXVlcnlSYWRpdXM9ZnVuY3Rpb24odCl7dmFyIGU9dCxyPUJvKEduKFwibGluZS13aWR0aFwiLHRoaXMsZSksR24oXCJsaW5lLWdhcC13aWR0aFwiLHRoaXMsZSkpLG49R24oXCJsaW5lLW9mZnNldFwiLHRoaXMsZSk7cmV0dXJuIHIvMitNYXRoLmFicyhuKStZbih0aGlzLnBhaW50LmdldChcImxpbmUtdHJhbnNsYXRlXCIpKX0sZS5wcm90b3R5cGUucXVlcnlJbnRlcnNlY3RzRmVhdHVyZT1mdW5jdGlvbih0LGUscixuLGksbyl7dmFyIGE9V24odCx0aGlzLnBhaW50LmdldChcImxpbmUtdHJhbnNsYXRlXCIpLHRoaXMucGFpbnQuZ2V0KFwibGluZS10cmFuc2xhdGUtYW5jaG9yXCIpLGkuYW5nbGUsbyksdT1vLzIqQm8odGhpcy5wYWludC5nZXQoXCJsaW5lLXdpZHRoXCIpLmV2YWx1YXRlKGUpLHRoaXMucGFpbnQuZ2V0KFwibGluZS1nYXAtd2lkdGhcIikuZXZhbHVhdGUoZSkpLGw9dGhpcy5wYWludC5nZXQoXCJsaW5lLW9mZnNldFwiKS5ldmFsdWF0ZShlKTtyZXR1cm4gbCYmKHI9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9W10sbj1uZXcgcygwLDApLGk9MDtpPHQubGVuZ3RoO2krKyl7Zm9yKHZhciBvPXRbaV0sYT1bXSx1PTA7dTxvLmxlbmd0aDt1Kyspe3ZhciBsPW9bdS0xXSxwPW9bdV0sYz1vW3UrMV0saD0wPT09dT9uOnAuc3ViKGwpLl91bml0KCkuX3BlcnAoKSxmPXU9PT1vLmxlbmd0aC0xP246Yy5zdWIocCkuX3VuaXQoKS5fcGVycCgpLHk9aC5fYWRkKGYpLl91bml0KCksZD15LngqZi54K3kueSpmLnk7eS5fbXVsdCgxL2QpLGEucHVzaCh5Ll9tdWx0KGUpLl9hZGQocCkpO31yLnB1c2goYSk7fXJldHVybiByfShyLGwqbykpLERuKGEscix1KX0sZX0oTnIpO2Z1bmN0aW9uIEJvKHQsZSl7cmV0dXJuIGU+MD9lKzIqdDp0fXZhciBDbz0kcihbe25hbWU6XCJhX3Bvc19vZmZzZXRcIixjb21wb25lbnRzOjQsdHlwZTpcIkludDE2XCJ9LHtuYW1lOlwiYV9kYXRhXCIsY29tcG9uZW50czo0LHR5cGU6XCJVaW50MTZcIn1dKSxJbz0kcihbe25hbWU6XCJhX3Byb2plY3RlZF9wb3NcIixjb21wb25lbnRzOjMsdHlwZTpcIkZsb2F0MzJcIn1dLDQpLEVvPSgkcihbe25hbWU6XCJhX2ZhZGVfb3BhY2l0eVwiLGNvbXBvbmVudHM6MSx0eXBlOlwiVWludDMyXCJ9XSw0KSwkcihbe25hbWU6XCJhX3BsYWNlZFwiLGNvbXBvbmVudHM6Mix0eXBlOlwiVWludDhcIn1dLDQpKSxGbz0oJHIoW3t0eXBlOlwiSW50MTZcIixuYW1lOlwiYW5jaG9yUG9pbnRYXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwiYW5jaG9yUG9pbnRZXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwieDFcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJ5MVwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcIngyXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwieTJcIn0se3R5cGU6XCJVaW50MzJcIixuYW1lOlwiZmVhdHVyZUluZGV4XCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcInNvdXJjZUxheWVySW5kZXhcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwiYnVja2V0SW5kZXhcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJyYWRpdXNcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJzaWduZWREaXN0YW5jZUZyb21BbmNob3JcIn1dKSwkcihbe25hbWU6XCJhX3Bvc1wiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn0se25hbWU6XCJhX2FuY2hvcl9wb3NcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9LHtuYW1lOlwiYV9leHRydWRlXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifV0sNCkpLFBvPSRyKFt7bmFtZTpcImFfcG9zXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifSx7bmFtZTpcImFfYW5jaG9yX3Bvc1wiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn0se25hbWU6XCJhX2V4dHJ1ZGVcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9XSw0KTskcihbe3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJhbmNob3JYXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwiYW5jaG9yWVwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJnbHlwaFN0YXJ0SW5kZXhcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwibnVtR2x5cGhzXCJ9LHt0eXBlOlwiVWludDMyXCIsbmFtZTpcInZlcnRleFN0YXJ0SW5kZXhcIn0se3R5cGU6XCJVaW50MzJcIixuYW1lOlwibGluZVN0YXJ0SW5kZXhcIn0se3R5cGU6XCJVaW50MzJcIixuYW1lOlwibGluZUxlbmd0aFwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJzZWdtZW50XCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcImxvd2VyU2l6ZVwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJ1cHBlclNpemVcIn0se3R5cGU6XCJGbG9hdDMyXCIsbmFtZTpcImxpbmVPZmZzZXRYXCJ9LHt0eXBlOlwiRmxvYXQzMlwiLG5hbWU6XCJsaW5lT2Zmc2V0WVwifSx7dHlwZTpcIlVpbnQ4XCIsbmFtZTpcIndyaXRpbmdNb2RlXCJ9LHt0eXBlOlwiVWludDhcIixuYW1lOlwiaGlkZGVuXCJ9XSksJHIoW3t0eXBlOlwiRmxvYXQzMlwiLG5hbWU6XCJvZmZzZXRYXCJ9XSksJHIoW3t0eXBlOlwiSW50MTZcIixuYW1lOlwieFwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInlcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJ0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvclwifV0pO2Z1bmN0aW9uIFRvKHQsZSxyKXt2YXIgbj1lLmxheW91dC5nZXQoXCJ0ZXh0LXRyYW5zZm9ybVwiKS5ldmFsdWF0ZShyKTtyZXR1cm5cInVwcGVyY2FzZVwiPT09bj90PXQudG9Mb2NhbGVVcHBlckNhc2UoKTpcImxvd2VyY2FzZVwiPT09biYmKHQ9dC50b0xvY2FsZUxvd2VyQ2FzZSgpKSxWci5hcHBseUFyYWJpY1NoYXBpbmcmJih0PVZyLmFwcGx5QXJhYmljU2hhcGluZyh0KSksdH12YXIgT289e1wiIVwiOlwi77iVXCIsXCIjXCI6XCLvvINcIiwkOlwi77yEXCIsXCIlXCI6XCLvvIVcIixcIiZcIjpcIu+8hlwiLFwiKFwiOlwi77i1XCIsXCIpXCI6XCLvuLZcIixcIipcIjpcIu+8ilwiLFwiK1wiOlwi77yLXCIsXCIsXCI6XCLvuJBcIixcIi1cIjpcIu+4slwiLFwiLlwiOlwi44O7XCIsXCIvXCI6XCLvvI9cIixcIjpcIjpcIu+4k1wiLFwiO1wiOlwi77iUXCIsXCI8XCI6XCLvuL9cIixcIj1cIjpcIu+8nVwiLFwiPlwiOlwi77mAXCIsXCI/XCI6XCLvuJZcIixcIkBcIjpcIu+8oFwiLFwiW1wiOlwi77mHXCIsXCJcXFxcXCI6XCLvvLxcIixcIl1cIjpcIu+5iFwiLFwiXlwiOlwi77y+XCIsXzpcIu+4s1wiLFwiYFwiOlwi772AXCIsXCJ7XCI6XCLvuLdcIixcInxcIjpcIuKAlVwiLFwifVwiOlwi77i4XCIsXCJ+XCI6XCLvvZ5cIixcIsKiXCI6XCLvv6BcIixcIsKjXCI6XCLvv6FcIixcIsKlXCI6XCLvv6VcIixcIsKmXCI6XCLvv6RcIixcIsKsXCI6XCLvv6JcIixcIsKvXCI6XCLvv6NcIixcIuKAk1wiOlwi77iyXCIsXCLigJRcIjpcIu+4sVwiLFwi4oCYXCI6XCLvuYNcIixcIuKAmVwiOlwi77mEXCIsXCLigJxcIjpcIu+5gVwiLFwi4oCdXCI6XCLvuYJcIixcIuKAplwiOlwi77iZXCIsXCLigKdcIjpcIuODu1wiLFwi4oKpXCI6XCLvv6ZcIixcIuOAgVwiOlwi77iRXCIsXCLjgIJcIjpcIu+4klwiLFwi44CIXCI6XCLvuL9cIixcIuOAiVwiOlwi77mAXCIsXCLjgIpcIjpcIu+4vVwiLFwi44CLXCI6XCLvuL5cIixcIuOAjFwiOlwi77mBXCIsXCLjgI1cIjpcIu+5glwiLFwi44COXCI6XCLvuYNcIixcIuOAj1wiOlwi77mEXCIsXCLjgJBcIjpcIu+4u1wiLFwi44CRXCI6XCLvuLxcIixcIuOAlFwiOlwi77i5XCIsXCLjgJVcIjpcIu+4ulwiLFwi44CWXCI6XCLvuJdcIixcIuOAl1wiOlwi77iYXCIsXCLvvIFcIjpcIu+4lVwiLFwi77yIXCI6XCLvuLVcIixcIu+8iVwiOlwi77i2XCIsXCLvvIxcIjpcIu+4kFwiLFwi77yNXCI6XCLvuLJcIixcIu+8jlwiOlwi44O7XCIsXCLvvJpcIjpcIu+4k1wiLFwi77ybXCI6XCLvuJRcIixcIu+8nFwiOlwi77i/XCIsXCLvvJ5cIjpcIu+5gFwiLFwi77yfXCI6XCLvuJZcIixcIu+8u1wiOlwi77mHXCIsXCLvvL1cIjpcIu+5iFwiLFwi77y/XCI6XCLvuLNcIixcIu+9m1wiOlwi77i3XCIsXCLvvZxcIjpcIuKAlVwiLFwi772dXCI6XCLvuLhcIixcIu+9n1wiOlwi77i1XCIsXCLvvaBcIjpcIu+4tlwiLFwi772hXCI6XCLvuJJcIixcIu+9olwiOlwi77mBXCIsXCLvvaNcIjpcIu+5glwifTt2YXIgTG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLHIsbixpKXt0LmNhbGwodGhpcyxlLHIpLHRoaXMuYW5nbGU9bix2b2lkIDAhPT1pJiYodGhpcy5zZWdtZW50PWkpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGUodGhpcy54LHRoaXMueSx0aGlzLmFuZ2xlLHRoaXMuc2VnbWVudCl9LGV9KHMpO2Z1bmN0aW9uIGpvKHQsZSl7dmFyIHI9ZS5leHByZXNzaW9uO2lmKFwiY29uc3RhbnRcIj09PXIua2luZClyZXR1cm57ZnVuY3Rpb25UeXBlOlwiY29uc3RhbnRcIixsYXlvdXRTaXplOnIuZXZhbHVhdGUobmV3IEJyKHQrMSkpfTtpZihcInNvdXJjZVwiPT09ci5raW5kKXJldHVybntmdW5jdGlvblR5cGU6XCJzb3VyY2VcIn07Zm9yKHZhciBuPXIuem9vbVN0b3BzLGk9MDtpPG4ubGVuZ3RoJiZuW2ldPD10OylpKys7Zm9yKHZhciBvPWk9TWF0aC5tYXgoMCxpLTEpO288bi5sZW5ndGgmJm5bb108dCsxOylvKys7bz1NYXRoLm1pbihuLmxlbmd0aC0xLG8pO3ZhciBhPXttaW46bltpXSxtYXg6bltvXX07cmV0dXJuXCJjb21wb3NpdGVcIj09PXIua2luZD97ZnVuY3Rpb25UeXBlOlwiY29tcG9zaXRlXCIsem9vbVJhbmdlOmEscHJvcGVydHlWYWx1ZTplLnZhbHVlfTp7ZnVuY3Rpb25UeXBlOlwiY2FtZXJhXCIsbGF5b3V0U2l6ZTpyLmV2YWx1YXRlKG5ldyBCcih0KzEpKSx6b29tUmFuZ2U6YSxzaXplUmFuZ2U6e21pbjpyLmV2YWx1YXRlKG5ldyBCcihhLm1pbikpLG1heDpyLmV2YWx1YXRlKG5ldyBCcihhLm1heCkpfSxwcm9wZXJ0eVZhbHVlOmUudmFsdWV9fWhyKFwiQW5jaG9yXCIsTG8pO3ZhciBxbz12by5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyxSbz1be25hbWU6XCJhX2ZhZGVfb3BhY2l0eVwiLGNvbXBvbmVudHM6MSx0eXBlOlwiVWludDhcIixvZmZzZXQ6MH1dO2Z1bmN0aW9uIFVvKHQsZSxyLG4saSxvLGEscyl7dC5lbXBsYWNlQmFjayhlLHIsTWF0aC5yb3VuZCgzMipuKSxNYXRoLnJvdW5kKDMyKmkpLG8sYSxzP3NbMF06MCxzP3NbMV06MCk7fWZ1bmN0aW9uIERvKHQsZSxyKXt0LmVtcGxhY2VCYWNrKGUueCxlLnksciksdC5lbXBsYWNlQmFjayhlLngsZS55LHIpLHQuZW1wbGFjZUJhY2soZS54LGUueSxyKSx0LmVtcGxhY2VCYWNrKGUueCxlLnkscik7fXZhciBObz1mdW5jdGlvbih0KXt0aGlzLmxheW91dFZlcnRleEFycmF5PW5ldyBRcix0aGlzLmluZGV4QXJyYXk9bmV3IHBuLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zPXQsdGhpcy5zZWdtZW50cz1uZXcgem4sdGhpcy5keW5hbWljTGF5b3V0VmVydGV4QXJyYXk9bmV3IHRuLHRoaXMub3BhY2l0eVZlcnRleEFycmF5PW5ldyBlbix0aGlzLnBsYWNlZFN5bWJvbEFycmF5PW5ldyBtbjt9O05vLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCxlKXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmxheW91dFZlcnRleEFycmF5LENvLm1lbWJlcnMpLHRoaXMuaW5kZXhCdWZmZXI9dC5jcmVhdGVJbmRleEJ1ZmZlcih0aGlzLmluZGV4QXJyYXksZSksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBsb2FkKHQpLHRoaXMuZHluYW1pY0xheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmR5bmFtaWNMYXlvdXRWZXJ0ZXhBcnJheSxJby5tZW1iZXJzLCEwKSx0aGlzLm9wYWNpdHlWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5vcGFjaXR5VmVydGV4QXJyYXksUm8sITApLHRoaXMub3BhY2l0eVZlcnRleEJ1ZmZlci5pdGVtU2l6ZT0xO30sTm8ucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlciYmKHRoaXMubGF5b3V0VmVydGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLmluZGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5kZXN0cm95KCksdGhpcy5zZWdtZW50cy5kZXN0cm95KCksdGhpcy5keW5hbWljTGF5b3V0VmVydGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLm9wYWNpdHlWZXJ0ZXhCdWZmZXIuZGVzdHJveSgpKTt9LGhyKFwiU3ltYm9sQnVmZmVyc1wiLE5vKTt2YXIgWm89ZnVuY3Rpb24odCxlLHIpe3RoaXMubGF5b3V0VmVydGV4QXJyYXk9bmV3IHQsdGhpcy5sYXlvdXRBdHRyaWJ1dGVzPWUsdGhpcy5pbmRleEFycmF5PW5ldyByLHRoaXMuc2VnbWVudHM9bmV3IHpuLHRoaXMuY29sbGlzaW9uVmVydGV4QXJyYXk9bmV3IG9uO307Wm8ucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmxheW91dFZlcnRleEFycmF5LHRoaXMubGF5b3V0QXR0cmlidXRlcyksdGhpcy5pbmRleEJ1ZmZlcj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheSksdGhpcy5jb2xsaXNpb25WZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5jb2xsaXNpb25WZXJ0ZXhBcnJheSxFby5tZW1iZXJzLCEwKTt9LFpvLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5zZWdtZW50cy5kZXN0cm95KCksdGhpcy5jb2xsaXNpb25WZXJ0ZXhCdWZmZXIuZGVzdHJveSgpKTt9LGhyKFwiQ29sbGlzaW9uQnVmZmVyc1wiLFpvKTt2YXIgS289ZnVuY3Rpb24odCl7dGhpcy5jb2xsaXNpb25Cb3hBcnJheT10LmNvbGxpc2lvbkJveEFycmF5LHRoaXMuem9vbT10Lnpvb20sdGhpcy5vdmVyc2NhbGluZz10Lm92ZXJzY2FsaW5nLHRoaXMubGF5ZXJzPXQubGF5ZXJzLHRoaXMubGF5ZXJJZHM9dGhpcy5sYXllcnMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSksdGhpcy5pbmRleD10LmluZGV4LHRoaXMucGl4ZWxSYXRpbz10LnBpeGVsUmF0aW8sdGhpcy5zb3VyY2VMYXllckluZGV4PXQuc291cmNlTGF5ZXJJbmRleDt2YXIgZT10aGlzLmxheWVyc1swXS5fdW5ldmFsdWF0ZWRMYXlvdXQuX3ZhbHVlczt0aGlzLnRleHRTaXplRGF0YT1qbyh0aGlzLnpvb20sZVtcInRleHQtc2l6ZVwiXSksdGhpcy5pY29uU2l6ZURhdGE9am8odGhpcy56b29tLGVbXCJpY29uLXNpemVcIl0pO3ZhciByPXRoaXMubGF5ZXJzWzBdLmxheW91dDt0aGlzLnNvcnRGZWF0dXJlc0J5WT1yLmdldChcInRleHQtYWxsb3ctb3ZlcmxhcFwiKXx8ci5nZXQoXCJpY29uLWFsbG93LW92ZXJsYXBcIil8fHIuZ2V0KFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCIpfHxyLmdldChcImljb24taWdub3JlLXBsYWNlbWVudFwiKTt9O0tvLnByb3RvdHlwZS5jcmVhdGVBcnJheXM9ZnVuY3Rpb24oKXt0aGlzLnRleHQ9bmV3IE5vKG5ldyBFbihDby5tZW1iZXJzLHRoaXMubGF5ZXJzLHRoaXMuem9vbSxmdW5jdGlvbih0KXtyZXR1cm4vXnRleHQvLnRlc3QodCl9KSksdGhpcy5pY29uPW5ldyBObyhuZXcgRW4oQ28ubWVtYmVycyx0aGlzLmxheWVycyx0aGlzLnpvb20sZnVuY3Rpb24odCl7cmV0dXJuL15pY29uLy50ZXN0KHQpfSkpLHRoaXMuY29sbGlzaW9uQm94PW5ldyBabyhubixGby5tZW1iZXJzLGNuKSx0aGlzLmNvbGxpc2lvbkNpcmNsZT1uZXcgWm8obm4sUG8ubWVtYmVycyxwbiksdGhpcy5nbHlwaE9mZnNldEFycmF5PW5ldyB4bix0aGlzLmxpbmVWZXJ0ZXhBcnJheT1uZXcgd247fSxLby5wcm90b3R5cGUucG9wdWxhdGU9ZnVuY3Rpb24odCxlKXt2YXIgcj10aGlzLmxheWVyc1swXSxuPXIubGF5b3V0LGk9bi5nZXQoXCJ0ZXh0LWZvbnRcIiksbz1uLmdldChcInRleHQtZmllbGRcIiksYT1uLmdldChcImljb24taW1hZ2VcIikscz0oXCJjb25zdGFudFwiIT09by52YWx1ZS5raW5kfHxvLnZhbHVlLnZhbHVlLmxlbmd0aD4wKSYmKFwiY29uc3RhbnRcIiE9PWkudmFsdWUua2luZHx8aS52YWx1ZS52YWx1ZS5sZW5ndGg+MCksdT1cImNvbnN0YW50XCIhPT1hLnZhbHVlLmtpbmR8fGEudmFsdWUudmFsdWUmJmEudmFsdWUudmFsdWUubGVuZ3RoPjA7aWYodGhpcy5mZWF0dXJlcz1bXSxzfHx1KXtmb3IodmFyIGw9ZS5pY29uRGVwZW5kZW5jaWVzLHA9ZS5nbHlwaERlcGVuZGVuY2llcyxjPW5ldyBCcih0aGlzLnpvb20pLGg9MCxmPXQ7aDxmLmxlbmd0aDtoKz0xKXt2YXIgeT1mW2hdLGQ9eS5mZWF0dXJlLHY9eS5pbmRleCxtPXkuc291cmNlTGF5ZXJJbmRleDtpZihyLl9mZWF0dXJlRmlsdGVyKGMsZCkpe3ZhciBnPXZvaWQgMDtzJiYoZz1UbyhnPXIuZ2V0VmFsdWVBbmRSZXNvbHZlVG9rZW5zKFwidGV4dC1maWVsZFwiLGQpLHIsZCkpO3ZhciB4PXZvaWQgMDtpZih1JiYoeD1yLmdldFZhbHVlQW5kUmVzb2x2ZVRva2VucyhcImljb24taW1hZ2VcIixkKSksZ3x8eCl7dmFyIGI9e3RleHQ6ZyxpY29uOngsaW5kZXg6dixzb3VyY2VMYXllckluZGV4Om0sZ2VvbWV0cnk6TG4oZCkscHJvcGVydGllczpkLnByb3BlcnRpZXMsdHlwZTpxb1tkLnR5cGVdfTtpZih2b2lkIDAhPT1kLmlkJiYoYi5pZD1kLmlkKSx0aGlzLmZlYXR1cmVzLnB1c2goYikseCYmKGxbeF09ITApLGcpZm9yKHZhciB3PWkuZXZhbHVhdGUoZCkuam9pbihcIixcIiksXz1wW3ddPXBbd118fHt9LEE9XCJtYXBcIj09PW4uZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIikmJlwibGluZVwiPT09bi5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpLGs9Z3IoZyksej0wO3o8Zy5sZW5ndGg7eisrKWlmKF9bZy5jaGFyQ29kZUF0KHopXT0hMCxBJiZrKXt2YXIgUz1Pb1tnLmNoYXJBdCh6KV07UyYmKF9bUy5jaGFyQ29kZUF0KDApXT0hMCk7fX19fVwibGluZVwiPT09bi5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpJiYodGhpcy5mZWF0dXJlcz1mdW5jdGlvbih0KXt2YXIgZT17fSxyPXt9LG49W10saT0wO2Z1bmN0aW9uIG8oZSl7bi5wdXNoKHRbZV0pLGkrKzt9ZnVuY3Rpb24gYSh0LGUsaSl7dmFyIG89clt0XTtyZXR1cm4gZGVsZXRlIHJbdF0scltlXT1vLG5bb10uZ2VvbWV0cnlbMF0ucG9wKCksbltvXS5nZW9tZXRyeVswXT1uW29dLmdlb21ldHJ5WzBdLmNvbmNhdChpWzBdKSxvfWZ1bmN0aW9uIHModCxyLGkpe3ZhciBvPWVbcl07cmV0dXJuIGRlbGV0ZSBlW3JdLGVbdF09byxuW29dLmdlb21ldHJ5WzBdLnNoaWZ0KCksbltvXS5nZW9tZXRyeVswXT1pWzBdLmNvbmNhdChuW29dLmdlb21ldHJ5WzBdKSxvfWZ1bmN0aW9uIHUodCxlLHIpe3ZhciBuPXI/ZVswXVtlWzBdLmxlbmd0aC0xXTplWzBdWzBdO3JldHVybiB0K1wiOlwiK24ueCtcIjpcIituLnl9Zm9yKHZhciBsPTA7bDx0Lmxlbmd0aDtsKyspe3ZhciBwPXRbbF0sYz1wLmdlb21ldHJ5LGg9cC50ZXh0O2lmKGgpe3ZhciBmPXUoaCxjKSx5PXUoaCxjLCEwKTtpZihmIGluIHImJnkgaW4gZSYmcltmXSE9PWVbeV0pe3ZhciBkPXMoZix5LGMpLHY9YShmLHksbltkXS5nZW9tZXRyeSk7ZGVsZXRlIGVbZl0sZGVsZXRlIHJbeV0sclt1KGgsblt2XS5nZW9tZXRyeSwhMCldPXYsbltkXS5nZW9tZXRyeT1udWxsO31lbHNlIGYgaW4gcj9hKGYseSxjKTp5IGluIGU/cyhmLHksYyk6KG8obCksZVtmXT1pLTEsclt5XT1pLTEpO31lbHNlIG8obCk7fXJldHVybiBuLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gdC5nZW9tZXRyeX0pfSh0aGlzLmZlYXR1cmVzKSk7fX0sS28ucHJvdG90eXBlLmlzRW1wdHk9ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMuc3ltYm9sSW5zdGFuY2VzLmxlbmd0aH0sS28ucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLnRleHQudXBsb2FkKHQsdGhpcy5zb3J0RmVhdHVyZXNCeVkpLHRoaXMuaWNvbi51cGxvYWQodCx0aGlzLnNvcnRGZWF0dXJlc0J5WSksdGhpcy5jb2xsaXNpb25Cb3gudXBsb2FkKHQpLHRoaXMuY29sbGlzaW9uQ2lyY2xlLnVwbG9hZCh0KTt9LEtvLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy50ZXh0LmRlc3Ryb3koKSx0aGlzLmljb24uZGVzdHJveSgpLHRoaXMuY29sbGlzaW9uQm94LmRlc3Ryb3koKSx0aGlzLmNvbGxpc2lvbkNpcmNsZS5kZXN0cm95KCk7fSxLby5wcm90b3R5cGUuYWRkVG9MaW5lVmVydGV4QXJyYXk9ZnVuY3Rpb24odCxlKXt2YXIgcj10aGlzLmxpbmVWZXJ0ZXhBcnJheS5sZW5ndGg7aWYodm9pZCAwIT09dC5zZWdtZW50KXtmb3IodmFyIG49dC5kaXN0KGVbdC5zZWdtZW50KzFdKSxpPXQuZGlzdChlW3Quc2VnbWVudF0pLG89e30sYT10LnNlZ21lbnQrMTthPGUubGVuZ3RoO2ErKylvW2FdPXt4OmVbYV0ueCx5OmVbYV0ueSx0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcjpufSxhPGUubGVuZ3RoLTEmJihuKz1lW2ErMV0uZGlzdChlW2FdKSk7Zm9yKHZhciBzPXQuc2VnbWVudHx8MDtzPj0wO3MtLSlvW3NdPXt4OmVbc10ueCx5OmVbc10ueSx0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcjppfSxzPjAmJihpKz1lW3MtMV0uZGlzdChlW3NdKSk7Zm9yKHZhciB1PTA7dTxlLmxlbmd0aDt1Kyspe3ZhciBsPW9bdV07dGhpcy5saW5lVmVydGV4QXJyYXkuZW1wbGFjZUJhY2sobC54LGwueSxsLnRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yKTt9fXJldHVybntsaW5lU3RhcnRJbmRleDpyLGxpbmVMZW5ndGg6dGhpcy5saW5lVmVydGV4QXJyYXkubGVuZ3RoLXJ9fSxLby5wcm90b3R5cGUuYWRkU3ltYm9scz1mdW5jdGlvbih0LGUscixuLGksbyxhLHMsdSxsKXtmb3IodmFyIHA9dC5pbmRleEFycmF5LGM9dC5sYXlvdXRWZXJ0ZXhBcnJheSxoPXQuZHluYW1pY0xheW91dFZlcnRleEFycmF5LGY9dC5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0KmUubGVuZ3RoLHQubGF5b3V0VmVydGV4QXJyYXksdC5pbmRleEFycmF5KSx5PXRoaXMuZ2x5cGhPZmZzZXRBcnJheS5sZW5ndGgsZD1mLnZlcnRleExlbmd0aCx2PTAsbT1lO3Y8bS5sZW5ndGg7dis9MSl7dmFyIGc9bVt2XSx4PWcudGwsYj1nLnRyLHc9Zy5ibCxfPWcuYnIsQT1nLnRleCxrPWYudmVydGV4TGVuZ3RoLHo9Zy5nbHlwaE9mZnNldFsxXTtVbyhjLHMueCxzLnkseC54LHoreC55LEEueCxBLnksciksVW8oYyxzLngscy55LGIueCx6K2IueSxBLngrQS53LEEueSxyKSxVbyhjLHMueCxzLnksdy54LHordy55LEEueCxBLnkrQS5oLHIpLFVvKGMscy54LHMueSxfLngseitfLnksQS54K0EudyxBLnkrQS5oLHIpLERvKGgscywwKSxwLmVtcGxhY2VCYWNrKGssaysxLGsrMikscC5lbXBsYWNlQmFjayhrKzEsaysyLGsrMyksZi52ZXJ0ZXhMZW5ndGgrPTQsZi5wcmltaXRpdmVMZW5ndGgrPTIsdGhpcy5nbHlwaE9mZnNldEFycmF5LmVtcGxhY2VCYWNrKGcuZ2x5cGhPZmZzZXRbMF0pO310LnBsYWNlZFN5bWJvbEFycmF5LmVtcGxhY2VCYWNrKHMueCxzLnkseSx0aGlzLmdseXBoT2Zmc2V0QXJyYXkubGVuZ3RoLXksZCx1LGwscy5zZWdtZW50LHI/clswXTowLHI/clsxXTowLG5bMF0sblsxXSxhLCExKSx0LnByb2dyYW1Db25maWd1cmF0aW9ucy5wb3B1bGF0ZVBhaW50QXJyYXlzKHQubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RoLG8pO30sS28ucHJvdG90eXBlLl9hZGRDb2xsaXNpb25EZWJ1Z1ZlcnRleD1mdW5jdGlvbih0LGUscixuLGkpe3JldHVybiBlLmVtcGxhY2VCYWNrKDAsMCksdC5lbXBsYWNlQmFjayhyLngsci55LG4ueCxuLnksTWF0aC5yb3VuZChpLngpLE1hdGgucm91bmQoaS55KSl9LEtvLnByb3RvdHlwZS5hZGRDb2xsaXNpb25EZWJ1Z1ZlcnRpY2VzPWZ1bmN0aW9uKHQsZSxyLG4saSxvLGEsdSl7dmFyIGw9aS5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LGkubGF5b3V0VmVydGV4QXJyYXksaS5pbmRleEFycmF5KSxwPWwudmVydGV4TGVuZ3RoLGM9aS5sYXlvdXRWZXJ0ZXhBcnJheSxoPWkuY29sbGlzaW9uVmVydGV4QXJyYXk7aWYodGhpcy5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXgoYyxoLG8sYS5hbmNob3IsbmV3IHModCxlKSksdGhpcy5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXgoYyxoLG8sYS5hbmNob3IsbmV3IHMocixlKSksdGhpcy5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXgoYyxoLG8sYS5hbmNob3IsbmV3IHMocixuKSksdGhpcy5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXgoYyxoLG8sYS5hbmNob3IsbmV3IHModCxuKSksbC52ZXJ0ZXhMZW5ndGgrPTQsdSl7dmFyIGY9aS5pbmRleEFycmF5O2YuZW1wbGFjZUJhY2socCxwKzEscCsyKSxmLmVtcGxhY2VCYWNrKHAscCsyLHArMyksbC5wcmltaXRpdmVMZW5ndGgrPTI7fWVsc2V7dmFyIHk9aS5pbmRleEFycmF5O3kuZW1wbGFjZUJhY2socCxwKzEpLHkuZW1wbGFjZUJhY2socCsxLHArMikseS5lbXBsYWNlQmFjayhwKzIscCszKSx5LmVtcGxhY2VCYWNrKHArMyxwKSxsLnByaW1pdGl2ZUxlbmd0aCs9NDt9fSxLby5wcm90b3R5cGUuZ2VuZXJhdGVDb2xsaXNpb25EZWJ1Z0J1ZmZlcnM9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9MCxlPXRoaXMuc3ltYm9sSW5zdGFuY2VzO3Q8ZS5sZW5ndGg7dCs9MSl7dmFyIHI9ZVt0XTtyLnRleHRDb2xsaXNpb25GZWF0dXJlPXtib3hTdGFydEluZGV4OnIudGV4dEJveFN0YXJ0SW5kZXgsYm94RW5kSW5kZXg6ci50ZXh0Qm94RW5kSW5kZXh9LHIuaWNvbkNvbGxpc2lvbkZlYXR1cmU9e2JveFN0YXJ0SW5kZXg6ci5pY29uQm94U3RhcnRJbmRleCxib3hFbmRJbmRleDpyLmljb25Cb3hFbmRJbmRleH07Zm9yKHZhciBuPTA7bjwyO24rKyl7dmFyIGk9clswPT09bj9cInRleHRDb2xsaXNpb25GZWF0dXJlXCI6XCJpY29uQ29sbGlzaW9uRmVhdHVyZVwiXTtpZihpKWZvcih2YXIgbz1pLmJveFN0YXJ0SW5kZXg7bzxpLmJveEVuZEluZGV4O28rKyl7dmFyIGE9dGhpcy5jb2xsaXNpb25Cb3hBcnJheS5nZXQobykscz1hLngxLHU9YS55MSxsPWEueDIscD1hLnkyLGM9YS5yYWRpdXM+MDt0aGlzLmFkZENvbGxpc2lvbkRlYnVnVmVydGljZXMocyx1LGwscCxjP3RoaXMuY29sbGlzaW9uQ2lyY2xlOnRoaXMuY29sbGlzaW9uQm94LGEuYW5jaG9yUG9pbnQscixjKTt9fX19LEtvLnByb3RvdHlwZS5kZXNlcmlhbGl6ZUNvbGxpc2lvbkJveGVzPWZ1bmN0aW9uKHQsZSxyLG4saSl7Zm9yKHZhciBvPXt9LGE9ZTthPHI7YSsrKXt2YXIgcz10LmdldChhKTtpZigwPT09cy5yYWRpdXMpe28udGV4dEJveD17eDE6cy54MSx5MTpzLnkxLHgyOnMueDIseTI6cy55MixhbmNob3JQb2ludFg6cy5hbmNob3JQb2ludFgsYW5jaG9yUG9pbnRZOnMuYW5jaG9yUG9pbnRZfSxvLnRleHRGZWF0dXJlSW5kZXg9cy5mZWF0dXJlSW5kZXg7YnJlYWt9by50ZXh0Q2lyY2xlc3x8KG8udGV4dENpcmNsZXM9W10sby50ZXh0RmVhdHVyZUluZGV4PXMuZmVhdHVyZUluZGV4KTtvLnRleHRDaXJjbGVzLnB1c2gocy5hbmNob3JQb2ludFgscy5hbmNob3JQb2ludFkscy5yYWRpdXMscy5zaWduZWREaXN0YW5jZUZyb21BbmNob3IsMSk7fWZvcih2YXIgdT1uO3U8aTt1Kyspe3ZhciBsPXQuZ2V0KHUpO2lmKDA9PT1sLnJhZGl1cyl7by5pY29uQm94PXt4MTpsLngxLHkxOmwueTEseDI6bC54Mix5MjpsLnkyLGFuY2hvclBvaW50WDpsLmFuY2hvclBvaW50WCxhbmNob3JQb2ludFk6bC5hbmNob3JQb2ludFl9LG8uaWNvbkZlYXR1cmVJbmRleD1sLmZlYXR1cmVJbmRleDticmVha319cmV0dXJuIG99LEtvLnByb3RvdHlwZS5oYXNUZXh0RGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRleHQuc2VnbWVudHMuZ2V0KCkubGVuZ3RoPjB9LEtvLnByb3RvdHlwZS5oYXNJY29uRGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmljb24uc2VnbWVudHMuZ2V0KCkubGVuZ3RoPjB9LEtvLnByb3RvdHlwZS5oYXNDb2xsaXNpb25Cb3hEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY29sbGlzaW9uQm94LnNlZ21lbnRzLmdldCgpLmxlbmd0aD4wfSxLby5wcm90b3R5cGUuaGFzQ29sbGlzaW9uQ2lyY2xlRGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmNvbGxpc2lvbkNpcmNsZS5zZWdtZW50cy5nZXQoKS5sZW5ndGg+MH0sS28ucHJvdG90eXBlLnNvcnRGZWF0dXJlcz1mdW5jdGlvbih0KXt2YXIgZT10aGlzO2lmKHRoaXMuc29ydEZlYXR1cmVzQnlZJiZ0aGlzLnNvcnRlZEFuZ2xlIT09dCYmKHRoaXMuc29ydGVkQW5nbGU9dCwhKHRoaXMudGV4dC5zZWdtZW50cy5nZXQoKS5sZW5ndGg+MXx8dGhpcy5pY29uLnNlZ21lbnRzLmdldCgpLmxlbmd0aD4xKSkpe2Zvcih2YXIgcj1bXSxuPTA7bjx0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7bisrKXIucHVzaChuKTt2YXIgaT1NYXRoLnNpbih0KSxvPU1hdGguY29zKHQpO3Iuc29ydChmdW5jdGlvbih0LHIpe3ZhciBuPWUuc3ltYm9sSW5zdGFuY2VzW3RdLGE9ZS5zeW1ib2xJbnN0YW5jZXNbcl07cmV0dXJuKGkqbi5hbmNob3IueCtvKm4uYW5jaG9yLnl8MCktKGkqYS5hbmNob3IueCtvKmEuYW5jaG9yLnl8MCl8fGEuZmVhdHVyZUluZGV4LW4uZmVhdHVyZUluZGV4fSksdGhpcy50ZXh0LmluZGV4QXJyYXkuY2xlYXIoKSx0aGlzLmljb24uaW5kZXhBcnJheS5jbGVhcigpLHRoaXMuZmVhdHVyZVNvcnRPcmRlcj1bXTtmb3IodmFyIGE9MCxzPXI7YTxzLmxlbmd0aDthKz0xKXt2YXIgdT1zW2FdLGw9ZS5zeW1ib2xJbnN0YW5jZXNbdV07ZS5mZWF0dXJlU29ydE9yZGVyLnB1c2gobC5mZWF0dXJlSW5kZXgpO2Zvcih2YXIgcD0wLGM9bC5wbGFjZWRUZXh0U3ltYm9sSW5kaWNlcztwPGMubGVuZ3RoO3ArPTEpZm9yKHZhciBoPWNbcF0sZj1lLnRleHQucGxhY2VkU3ltYm9sQXJyYXkuZ2V0KGgpLHk9Zi52ZXJ0ZXhTdGFydEluZGV4KzQqZi5udW1HbHlwaHMsZD1mLnZlcnRleFN0YXJ0SW5kZXg7ZDx5O2QrPTQpZS50ZXh0LmluZGV4QXJyYXkuZW1wbGFjZUJhY2soZCxkKzEsZCsyKSxlLnRleHQuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhkKzEsZCsyLGQrMyk7dmFyIHY9ZS5pY29uLnBsYWNlZFN5bWJvbEFycmF5LmdldCh1KTtpZih2Lm51bUdseXBocyl7dmFyIG09di52ZXJ0ZXhTdGFydEluZGV4O2UuaWNvbi5pbmRleEFycmF5LmVtcGxhY2VCYWNrKG0sbSsxLG0rMiksZS5pY29uLmluZGV4QXJyYXkuZW1wbGFjZUJhY2sobSsxLG0rMixtKzMpO319dGhpcy50ZXh0LmluZGV4QnVmZmVyJiZ0aGlzLnRleHQuaW5kZXhCdWZmZXIudXBkYXRlRGF0YSh0aGlzLnRleHQuaW5kZXhBcnJheSksdGhpcy5pY29uLmluZGV4QnVmZmVyJiZ0aGlzLmljb24uaW5kZXhCdWZmZXIudXBkYXRlRGF0YSh0aGlzLmljb24uaW5kZXhBcnJheSk7fX0saHIoXCJTeW1ib2xCdWNrZXRcIixLbyx7b21pdDpbXCJsYXllcnNcIixcImNvbGxpc2lvbkJveEFycmF5XCIsXCJmZWF0dXJlc1wiLFwiY29tcGFyZVRleHRcIl0sc2hhbGxvdzpbXCJzeW1ib2xJbnN0YW5jZXNcIl19KSxLby5NQVhfR0xZUEhTPTY1NTM1LEtvLmFkZER5bmFtaWNBdHRyaWJ1dGVzPURvO3ZhciBKbz1uZXcgRHIoe1wic3ltYm9sLXBsYWNlbWVudFwiOm5ldyBqcihFLmxheW91dF9zeW1ib2xbXCJzeW1ib2wtcGxhY2VtZW50XCJdKSxcInN5bWJvbC1zcGFjaW5nXCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcInN5bWJvbC1zcGFjaW5nXCJdKSxcInN5bWJvbC1hdm9pZC1lZGdlc1wiOm5ldyBqcihFLmxheW91dF9zeW1ib2xbXCJzeW1ib2wtYXZvaWQtZWRnZXNcIl0pLFwiaWNvbi1hbGxvdy1vdmVybGFwXCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcImljb24tYWxsb3ctb3ZlcmxhcFwiXSksXCJpY29uLWlnbm9yZS1wbGFjZW1lbnRcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi1pZ25vcmUtcGxhY2VtZW50XCJdKSxcImljb24tb3B0aW9uYWxcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi1vcHRpb25hbFwiXSksXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiOm5ldyBqcihFLmxheW91dF9zeW1ib2xbXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiXSksXCJpY29uLXNpemVcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi1zaXplXCJdKSxcImljb24tdGV4dC1maXRcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi10ZXh0LWZpdFwiXSksXCJpY29uLXRleHQtZml0LXBhZGRpbmdcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCJdKSxcImljb24taW1hZ2VcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi1pbWFnZVwiXSksXCJpY29uLXJvdGF0ZVwiOm5ldyBxcihFLmxheW91dF9zeW1ib2xbXCJpY29uLXJvdGF0ZVwiXSksXCJpY29uLXBhZGRpbmdcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1wiaWNvbi1wYWRkaW5nXCJdKSxcImljb24ta2VlcC11cHJpZ2h0XCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcImljb24ta2VlcC11cHJpZ2h0XCJdKSxcImljb24tb2Zmc2V0XCI6bmV3IHFyKEUubGF5b3V0X3N5bWJvbFtcImljb24tb2Zmc2V0XCJdKSxcImljb24tYW5jaG9yXCI6bmV3IHFyKEUubGF5b3V0X3N5bWJvbFtcImljb24tYW5jaG9yXCJdKSxcImljb24tcGl0Y2gtYWxpZ25tZW50XCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcImljb24tcGl0Y2gtYWxpZ25tZW50XCJdKSxcInRleHQtcGl0Y2gtYWxpZ25tZW50XCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtcGl0Y2gtYWxpZ25tZW50XCJdKSxcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCJdKSxcInRleHQtZmllbGRcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1maWVsZFwiXSksXCJ0ZXh0LWZvbnRcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1mb250XCJdKSxcInRleHQtc2l6ZVwiOm5ldyBxcihFLmxheW91dF9zeW1ib2xbXCJ0ZXh0LXNpemVcIl0pLFwidGV4dC1tYXgtd2lkdGhcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1tYXgtd2lkdGhcIl0pLFwidGV4dC1saW5lLWhlaWdodFwiOm5ldyBqcihFLmxheW91dF9zeW1ib2xbXCJ0ZXh0LWxpbmUtaGVpZ2h0XCJdKSxcInRleHQtbGV0dGVyLXNwYWNpbmdcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1sZXR0ZXItc3BhY2luZ1wiXSksXCJ0ZXh0LWp1c3RpZnlcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1qdXN0aWZ5XCJdKSxcInRleHQtYW5jaG9yXCI6bmV3IHFyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtYW5jaG9yXCJdKSxcInRleHQtbWF4LWFuZ2xlXCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtbWF4LWFuZ2xlXCJdKSxcInRleHQtcm90YXRlXCI6bmV3IHFyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtcm90YXRlXCJdKSxcInRleHQtcGFkZGluZ1wiOm5ldyBqcihFLmxheW91dF9zeW1ib2xbXCJ0ZXh0LXBhZGRpbmdcIl0pLFwidGV4dC1rZWVwLXVwcmlnaHRcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1rZWVwLXVwcmlnaHRcIl0pLFwidGV4dC10cmFuc2Zvcm1cIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC10cmFuc2Zvcm1cIl0pLFwidGV4dC1vZmZzZXRcIjpuZXcgcXIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1vZmZzZXRcIl0pLFwidGV4dC1hbGxvdy1vdmVybGFwXCI6bmV3IGpyKEUubGF5b3V0X3N5bWJvbFtcInRleHQtYWxsb3ctb3ZlcmxhcFwiXSksXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1pZ25vcmUtcGxhY2VtZW50XCJdKSxcInRleHQtb3B0aW9uYWxcIjpuZXcganIoRS5sYXlvdXRfc3ltYm9sW1widGV4dC1vcHRpb25hbFwiXSl9KSwkbz17cGFpbnQ6bmV3IERyKHtcImljb24tb3BhY2l0eVwiOm5ldyBxcihFLnBhaW50X3N5bWJvbFtcImljb24tb3BhY2l0eVwiXSksXCJpY29uLWNvbG9yXCI6bmV3IHFyKEUucGFpbnRfc3ltYm9sW1wiaWNvbi1jb2xvclwiXSksXCJpY29uLWhhbG8tY29sb3JcIjpuZXcgcXIoRS5wYWludF9zeW1ib2xbXCJpY29uLWhhbG8tY29sb3JcIl0pLFwiaWNvbi1oYWxvLXdpZHRoXCI6bmV3IHFyKEUucGFpbnRfc3ltYm9sW1wiaWNvbi1oYWxvLXdpZHRoXCJdKSxcImljb24taGFsby1ibHVyXCI6bmV3IHFyKEUucGFpbnRfc3ltYm9sW1wiaWNvbi1oYWxvLWJsdXJcIl0pLFwiaWNvbi10cmFuc2xhdGVcIjpuZXcganIoRS5wYWludF9zeW1ib2xbXCJpY29uLXRyYW5zbGF0ZVwiXSksXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcganIoRS5wYWludF9zeW1ib2xbXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIl0pLFwidGV4dC1vcGFjaXR5XCI6bmV3IHFyKEUucGFpbnRfc3ltYm9sW1widGV4dC1vcGFjaXR5XCJdKSxcInRleHQtY29sb3JcIjpuZXcgcXIoRS5wYWludF9zeW1ib2xbXCJ0ZXh0LWNvbG9yXCJdKSxcInRleHQtaGFsby1jb2xvclwiOm5ldyBxcihFLnBhaW50X3N5bWJvbFtcInRleHQtaGFsby1jb2xvclwiXSksXCJ0ZXh0LWhhbG8td2lkdGhcIjpuZXcgcXIoRS5wYWludF9zeW1ib2xbXCJ0ZXh0LWhhbG8td2lkdGhcIl0pLFwidGV4dC1oYWxvLWJsdXJcIjpuZXcgcXIoRS5wYWludF9zeW1ib2xbXCJ0ZXh0LWhhbG8tYmx1clwiXSksXCJ0ZXh0LXRyYW5zbGF0ZVwiOm5ldyBqcihFLnBhaW50X3N5bWJvbFtcInRleHQtdHJhbnNsYXRlXCJdKSxcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiOm5ldyBqcihFLnBhaW50X3N5bWJvbFtcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiXSl9KSxsYXlvdXQ6Sm99LEhvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSwkbyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5yZWNhbGN1bGF0ZT1mdW5jdGlvbihlKXt0LnByb3RvdHlwZS5yZWNhbGN1bGF0ZS5jYWxsKHRoaXMsZSksXCJhdXRvXCI9PT10aGlzLmxheW91dC5nZXQoXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiKSYmKFwibGluZVwiPT09dGhpcy5sYXlvdXQuZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKT90aGlzLmxheW91dC5fdmFsdWVzW1wiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJtYXBcIjp0aGlzLmxheW91dC5fdmFsdWVzW1wiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJ2aWV3cG9ydFwiKSxcImF1dG9cIj09PXRoaXMubGF5b3V0LmdldChcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCIpJiYoXCJsaW5lXCI9PT10aGlzLmxheW91dC5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpP3RoaXMubGF5b3V0Ll92YWx1ZXNbXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiXT1cIm1hcFwiOnRoaXMubGF5b3V0Ll92YWx1ZXNbXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiXT1cInZpZXdwb3J0XCIpLFwiYXV0b1wiPT09dGhpcy5sYXlvdXQuZ2V0KFwidGV4dC1waXRjaC1hbGlnbm1lbnRcIikmJih0aGlzLmxheW91dC5fdmFsdWVzW1widGV4dC1waXRjaC1hbGlnbm1lbnRcIl09dGhpcy5sYXlvdXQuZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIikpLFwiYXV0b1wiPT09dGhpcy5sYXlvdXQuZ2V0KFwiaWNvbi1waXRjaC1hbGlnbm1lbnRcIikmJih0aGlzLmxheW91dC5fdmFsdWVzW1wiaWNvbi1waXRjaC1hbGlnbm1lbnRcIl09dGhpcy5sYXlvdXQuZ2V0KFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIikpO30sZS5wcm90b3R5cGUuZ2V0VmFsdWVBbmRSZXNvbHZlVG9rZW5zPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbj10aGlzLmxheW91dC5nZXQodCkuZXZhbHVhdGUoZSksaT10aGlzLl91bmV2YWx1YXRlZExheW91dC5fdmFsdWVzW3RdO3JldHVybiBpLmlzRGF0YURyaXZlbigpfHxiZShpLnZhbHVlKT9uOihyPWUucHJvcGVydGllcyxuLnJlcGxhY2UoL3soW157fV0rKX0vZyxmdW5jdGlvbih0LGUpe3JldHVybiBlIGluIHI/U3RyaW5nKHJbZV0pOlwiXCJ9KSl9LGUucHJvdG90eXBlLmNyZWF0ZUJ1Y2tldD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IEtvKHQpfSxlLnByb3RvdHlwZS5xdWVyeVJhZGl1cz1mdW5jdGlvbigpe3JldHVybiAwfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKCl7cmV0dXJuITF9LGV9KE5yKSxYbz17cGFpbnQ6bmV3IERyKHtcImJhY2tncm91bmQtY29sb3JcIjpuZXcganIoRS5wYWludF9iYWNrZ3JvdW5kW1wiYmFja2dyb3VuZC1jb2xvclwiXSksXCJiYWNrZ3JvdW5kLXBhdHRlcm5cIjpuZXcgUnIoRS5wYWludF9iYWNrZ3JvdW5kW1wiYmFja2dyb3VuZC1wYXR0ZXJuXCJdKSxcImJhY2tncm91bmQtb3BhY2l0eVwiOm5ldyBqcihFLnBhaW50X2JhY2tncm91bmRbXCJiYWNrZ3JvdW5kLW9wYWNpdHlcIl0pfSl9LEdvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxYbyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlfShOciksWW89e3BhaW50Om5ldyBEcih7XCJyYXN0ZXItb3BhY2l0eVwiOm5ldyBqcihFLnBhaW50X3Jhc3RlcltcInJhc3Rlci1vcGFjaXR5XCJdKSxcInJhc3Rlci1odWUtcm90YXRlXCI6bmV3IGpyKEUucGFpbnRfcmFzdGVyW1wicmFzdGVyLWh1ZS1yb3RhdGVcIl0pLFwicmFzdGVyLWJyaWdodG5lc3MtbWluXCI6bmV3IGpyKEUucGFpbnRfcmFzdGVyW1wicmFzdGVyLWJyaWdodG5lc3MtbWluXCJdKSxcInJhc3Rlci1icmlnaHRuZXNzLW1heFwiOm5ldyBqcihFLnBhaW50X3Jhc3RlcltcInJhc3Rlci1icmlnaHRuZXNzLW1heFwiXSksXCJyYXN0ZXItc2F0dXJhdGlvblwiOm5ldyBqcihFLnBhaW50X3Jhc3RlcltcInJhc3Rlci1zYXR1cmF0aW9uXCJdKSxcInJhc3Rlci1jb250cmFzdFwiOm5ldyBqcihFLnBhaW50X3Jhc3RlcltcInJhc3Rlci1jb250cmFzdFwiXSksXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOm5ldyBqcihFLnBhaW50X3Jhc3RlcltcInJhc3Rlci1mYWRlLWR1cmF0aW9uXCJdKX0pfSxXbz17Y2lyY2xlOm5pLGhlYXRtYXA6ZmksaGlsbHNoYWRlOmRpLGZpbGw6WWksXCJmaWxsLWV4dHJ1c2lvblwiOm9vLGxpbmU6Vm8sc3ltYm9sOkhvLGJhY2tncm91bmQ6R28scmFzdGVyOmZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxZbyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlfShOcil9O3ZhciBRbz1uKGZ1bmN0aW9uKHQsZSl7dC5leHBvcnRzPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUscil7cj1yfHx7fSx0aGlzLnc9dHx8NjQsdGhpcy5oPWV8fDY0LHRoaXMuYXV0b1Jlc2l6ZT0hIXIuYXV0b1Jlc2l6ZSx0aGlzLnNoZWx2ZXM9W10sdGhpcy5mcmVlYmlucz1bXSx0aGlzLnN0YXRzPXt9LHRoaXMuYmlucz17fSx0aGlzLm1heElkPTA7fWZ1bmN0aW9uIGUodCxlLHIpe3RoaXMueD0wLHRoaXMueT10LHRoaXMudz10aGlzLmZyZWU9ZSx0aGlzLmg9cjt9cmV0dXJuIHQucHJvdG90eXBlLnBhY2s9ZnVuY3Rpb24odCxlKXt0PVtdLmNvbmNhdCh0KSxlPWV8fHt9O2Zvcih2YXIgcixuLGksbyxhPVtdLHM9MDtzPHQubGVuZ3RoO3MrKylpZihyPXRbc10ud3x8dFtzXS53aWR0aCxuPXRbc10uaHx8dFtzXS5oZWlnaHQsaT10W3NdLmlkLHImJm4pe2lmKCEobz10aGlzLnBhY2tPbmUocixuLGkpKSljb250aW51ZTtlLmluUGxhY2UmJih0W3NdLng9by54LHRbc10ueT1vLnksdFtzXS5pZD1vLmlkKSxhLnB1c2gobyk7fXJldHVybiB0aGlzLnNocmluaygpLGF9LHQucHJvdG90eXBlLnBhY2tPbmU9ZnVuY3Rpb24odCxyLG4pe3ZhciBpLG8sYSxzLHUsbCxwLGMsaD17ZnJlZWJpbjotMSxzaGVsZjotMSx3YXN0ZToxLzB9LGY9MDtpZihcInN0cmluZ1wiPT10eXBlb2Ygbnx8XCJudW1iZXJcIj09dHlwZW9mIG4pe2lmKGk9dGhpcy5nZXRCaW4obikpcmV0dXJuIHRoaXMucmVmKGkpLGk7XCJudW1iZXJcIj09dHlwZW9mIG4mJih0aGlzLm1heElkPU1hdGgubWF4KG4sdGhpcy5tYXhJZCkpO31lbHNlIG49Kyt0aGlzLm1heElkO2ZvcihzPTA7czx0aGlzLmZyZWViaW5zLmxlbmd0aDtzKyspe2lmKHI9PT0oaT10aGlzLmZyZWViaW5zW3NdKS5tYXhoJiZ0PT09aS5tYXh3KXJldHVybiB0aGlzLmFsbG9jRnJlZWJpbihzLHQscixuKTtyPmkubWF4aHx8dD5pLm1heHd8fHI8PWkubWF4aCYmdDw9aS5tYXh3JiYoYT1pLm1heHcqaS5tYXhoLXQqcik8aC53YXN0ZSYmKGgud2FzdGU9YSxoLmZyZWViaW49cyk7fWZvcihzPTA7czx0aGlzLnNoZWx2ZXMubGVuZ3RoO3MrKylpZihmKz0obz10aGlzLnNoZWx2ZXNbc10pLmgsISh0Pm8uZnJlZSkpe2lmKHI9PT1vLmgpcmV0dXJuIHRoaXMuYWxsb2NTaGVsZihzLHQscixuKTtyPm8uaHx8cjxvLmgmJihhPShvLmgtcikqdCk8aC53YXN0ZSYmKGguZnJlZWJpbj0tMSxoLndhc3RlPWEsaC5zaGVsZj1zKTt9cmV0dXJuLTEhPT1oLmZyZWViaW4/dGhpcy5hbGxvY0ZyZWViaW4oaC5mcmVlYmluLHQscixuKTotMSE9PWguc2hlbGY/dGhpcy5hbGxvY1NoZWxmKGguc2hlbGYsdCxyLG4pOnI8PXRoaXMuaC1mJiZ0PD10aGlzLnc/KG89bmV3IGUoZix0aGlzLncsciksdGhpcy5hbGxvY1NoZWxmKHRoaXMuc2hlbHZlcy5wdXNoKG8pLTEsdCxyLG4pKTp0aGlzLmF1dG9SZXNpemU/KHU9bD10aGlzLmgsKChwPWM9dGhpcy53KTw9dXx8dD5wKSYmKGM9MipNYXRoLm1heCh0LHApKSwodTxwfHxyPnUpJiYobD0yKk1hdGgubWF4KHIsdSkpLHRoaXMucmVzaXplKGMsbCksdGhpcy5wYWNrT25lKHQscixuKSk6bnVsbH0sdC5wcm90b3R5cGUuYWxsb2NGcmVlYmluPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMuZnJlZWJpbnMuc3BsaWNlKHQsMSlbMF07cmV0dXJuIGkuaWQ9bixpLnc9ZSxpLmg9cixpLnJlZmNvdW50PTAsdGhpcy5iaW5zW25dPWksdGhpcy5yZWYoaSksaX0sdC5wcm90b3R5cGUuYWxsb2NTaGVsZj1mdW5jdGlvbih0LGUscixuKXt2YXIgaT10aGlzLnNoZWx2ZXNbdF0uYWxsb2MoZSxyLG4pO3JldHVybiB0aGlzLmJpbnNbbl09aSx0aGlzLnJlZihpKSxpfSx0LnByb3RvdHlwZS5zaHJpbms9ZnVuY3Rpb24oKXtpZih0aGlzLnNoZWx2ZXMubGVuZ3RoPjApe2Zvcih2YXIgdD0wLGU9MCxyPTA7cjx0aGlzLnNoZWx2ZXMubGVuZ3RoO3IrKyl7dmFyIG49dGhpcy5zaGVsdmVzW3JdO2UrPW4uaCx0PU1hdGgubWF4KG4udy1uLmZyZWUsdCk7fXRoaXMucmVzaXplKHQsZSk7fX0sdC5wcm90b3R5cGUuZ2V0QmluPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmJpbnNbdF19LHQucHJvdG90eXBlLnJlZj1mdW5jdGlvbih0KXtpZigxPT0rK3QucmVmY291bnQpe3ZhciBlPXQuaDt0aGlzLnN0YXRzW2VdPTErKDB8dGhpcy5zdGF0c1tlXSk7fXJldHVybiB0LnJlZmNvdW50fSx0LnByb3RvdHlwZS51bnJlZj1mdW5jdGlvbih0KXtyZXR1cm4gMD09PXQucmVmY291bnQ/MDooMD09LS10LnJlZmNvdW50JiYodGhpcy5zdGF0c1t0LmhdLS0sZGVsZXRlIHRoaXMuYmluc1t0LmlkXSx0aGlzLmZyZWViaW5zLnB1c2godCkpLHQucmVmY291bnQpfSx0LnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3RoaXMuc2hlbHZlcz1bXSx0aGlzLmZyZWViaW5zPVtdLHRoaXMuc3RhdHM9e30sdGhpcy5iaW5zPXt9LHRoaXMubWF4SWQ9MDt9LHQucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbih0LGUpe3RoaXMudz10LHRoaXMuaD1lO2Zvcih2YXIgcj0wO3I8dGhpcy5zaGVsdmVzLmxlbmd0aDtyKyspdGhpcy5zaGVsdmVzW3JdLnJlc2l6ZSh0KTtyZXR1cm4hMH0sZS5wcm90b3R5cGUuYWxsb2M9ZnVuY3Rpb24odCxlLHIpe2lmKHQ+dGhpcy5mcmVlfHxlPnRoaXMuaClyZXR1cm4gbnVsbDt2YXIgbj10aGlzLng7cmV0dXJuIHRoaXMueCs9dCx0aGlzLmZyZWUtPXQsbmV3IGZ1bmN0aW9uKHQsZSxyLG4saSxvLGEpe3RoaXMuaWQ9dCx0aGlzLng9ZSx0aGlzLnk9cix0aGlzLnc9bix0aGlzLmg9aSx0aGlzLm1heHc9b3x8bix0aGlzLm1heGg9YXx8aSx0aGlzLnJlZmNvdW50PTA7fShyLG4sdGhpcy55LHQsZSx0LHRoaXMuaCl9LGUucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5mcmVlKz10LXRoaXMudyx0aGlzLnc9dCwhMH0sdH0oKTt9KSx0YT1mdW5jdGlvbih0LGUpe3ZhciByPWUucGl4ZWxSYXRpbzt0aGlzLnBhZGRlZFJlY3Q9dCx0aGlzLnBpeGVsUmF0aW89cjt9LGVhPXt0bDp7Y29uZmlndXJhYmxlOiEwfSxicjp7Y29uZmlndXJhYmxlOiEwfSxkaXNwbGF5U2l6ZTp7Y29uZmlndXJhYmxlOiEwfX07ZWEudGwuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuW3RoaXMucGFkZGVkUmVjdC54KzEsdGhpcy5wYWRkZWRSZWN0LnkrMV19LGVhLmJyLmdldD1mdW5jdGlvbigpe3JldHVyblt0aGlzLnBhZGRlZFJlY3QueCt0aGlzLnBhZGRlZFJlY3Qudy0xLHRoaXMucGFkZGVkUmVjdC55K3RoaXMucGFkZGVkUmVjdC5oLTFdfSxlYS5kaXNwbGF5U2l6ZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm5bKHRoaXMucGFkZGVkUmVjdC53LTIpL3RoaXMucGl4ZWxSYXRpbywodGhpcy5wYWRkZWRSZWN0LmgtMikvdGhpcy5waXhlbFJhdGlvXX0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGEucHJvdG90eXBlLGVhKTt2YXIgcmE9ZnVuY3Rpb24odCl7dmFyIGU9bmV3IHBpKHt3aWR0aDowLGhlaWdodDowfSkscj17fSxuPW5ldyBRbygwLDAse2F1dG9SZXNpemU6ITB9KTtmb3IodmFyIGkgaW4gdCl7dmFyIG89dFtpXSxhPW4ucGFja09uZShvLmRhdGEud2lkdGgrMixvLmRhdGEuaGVpZ2h0KzIpO2UucmVzaXplKHt3aWR0aDpuLncsaGVpZ2h0Om4uaH0pLHBpLmNvcHkoby5kYXRhLGUse3g6MCx5OjB9LHt4OmEueCsxLHk6YS55KzF9LG8uZGF0YSkscltpXT1uZXcgdGEoYSxvKTt9bi5zaHJpbmsoKSxlLnJlc2l6ZSh7d2lkdGg6bi53LGhlaWdodDpuLmh9KSx0aGlzLmltYWdlPWUsdGhpcy5wb3NpdGlvbnM9cjt9O2hyKFwiSW1hZ2VQb3NpdGlvblwiLHRhKSxocihcIkltYWdlQXRsYXNcIixyYSk7dmFyIG5hPWZ1bmN0aW9uKHQsZSxyLG4saSl7dmFyIG8sYSxzPTgqaS1uLTEsdT0oMTw8cyktMSxsPXU+PjEscD0tNyxjPXI/aS0xOjAsaD1yPy0xOjEsZj10W2UrY107Zm9yKGMrPWgsbz1mJigxPDwtcCktMSxmPj49LXAscCs9cztwPjA7bz0yNTYqbyt0W2UrY10sYys9aCxwLT04KTtmb3IoYT1vJigxPDwtcCktMSxvPj49LXAscCs9bjtwPjA7YT0yNTYqYSt0W2UrY10sYys9aCxwLT04KTtpZigwPT09bylvPTEtbDtlbHNle2lmKG89PT11KXJldHVybiBhP05hTjoxLzAqKGY/LTE6MSk7YSs9TWF0aC5wb3coMixuKSxvLT1sO31yZXR1cm4oZj8tMToxKSphKk1hdGgucG93KDIsby1uKX0saWE9ZnVuY3Rpb24odCxlLHIsbixpLG8pe3ZhciBhLHMsdSxsPTgqby1pLTEscD0oMTw8bCktMSxjPXA+PjEsaD0yMz09PWk/TWF0aC5wb3coMiwtMjQpLU1hdGgucG93KDIsLTc3KTowLGY9bj8wOm8tMSx5PW4/MTotMSxkPWU8MHx8MD09PWUmJjEvZTwwPzE6MDtmb3IoZT1NYXRoLmFicyhlKSxpc05hTihlKXx8ZT09PTEvMD8ocz1pc05hTihlKT8xOjAsYT1wKTooYT1NYXRoLmZsb29yKE1hdGgubG9nKGUpL01hdGguTE4yKSxlKih1PU1hdGgucG93KDIsLWEpKTwxJiYoYS0tLHUqPTIpLChlKz1hK2M+PTE/aC91OmgqTWF0aC5wb3coMiwxLWMpKSp1Pj0yJiYoYSsrLHUvPTIpLGErYz49cD8ocz0wLGE9cCk6YStjPj0xPyhzPShlKnUtMSkqTWF0aC5wb3coMixpKSxhKz1jKToocz1lKk1hdGgucG93KDIsYy0xKSpNYXRoLnBvdygyLGkpLGE9MCkpO2k+PTg7dFtyK2ZdPTI1NSZzLGYrPXkscy89MjU2LGktPTgpO2ZvcihhPWE8PGl8cyxsKz1pO2w+MDt0W3IrZl09MjU1JmEsZis9eSxhLz0yNTYsbC09OCk7dFtyK2YteV18PTEyOCpkO30sb2E9YWE7ZnVuY3Rpb24gYWEodCl7dGhpcy5idWY9QXJyYXlCdWZmZXIuaXNWaWV3JiZBcnJheUJ1ZmZlci5pc1ZpZXcodCk/dDpuZXcgVWludDhBcnJheSh0fHwwKSx0aGlzLnBvcz0wLHRoaXMudHlwZT0wLHRoaXMubGVuZ3RoPXRoaXMuYnVmLmxlbmd0aDt9YWEuVmFyaW50PTAsYWEuRml4ZWQ2ND0xLGFhLkJ5dGVzPTIsYWEuRml4ZWQzMj01O2Z1bmN0aW9uIHNhKHQpe3JldHVybiB0LnR5cGU9PT1hYS5CeXRlcz90LnJlYWRWYXJpbnQoKSt0LnBvczp0LnBvcysxfWZ1bmN0aW9uIHVhKHQsZSxyKXtyZXR1cm4gcj80Mjk0OTY3Mjk2KmUrKHQ+Pj4wKTo0Mjk0OTY3Mjk2KihlPj4+MCkrKHQ+Pj4wKX1mdW5jdGlvbiBsYSh0LGUscil7dmFyIG49ZTw9MTYzODM/MTplPD0yMDk3MTUxPzI6ZTw9MjY4NDM1NDU1PzM6TWF0aC5jZWlsKE1hdGgubG9nKGUpLyg3Kk1hdGguTE4yKSk7ci5yZWFsbG9jKG4pO2Zvcih2YXIgaT1yLnBvcy0xO2k+PXQ7aS0tKXIuYnVmW2krbl09ci5idWZbaV07fWZ1bmN0aW9uIHBhKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZVZhcmludCh0W3JdKTt9ZnVuY3Rpb24gY2EodCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyllLndyaXRlU1ZhcmludCh0W3JdKTt9ZnVuY3Rpb24gaGEodCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyllLndyaXRlRmxvYXQodFtyXSk7fWZ1bmN0aW9uIGZhKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZURvdWJsZSh0W3JdKTt9ZnVuY3Rpb24geWEodCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyllLndyaXRlQm9vbGVhbih0W3JdKTt9ZnVuY3Rpb24gZGEodCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyllLndyaXRlRml4ZWQzMih0W3JdKTt9ZnVuY3Rpb24gdmEodCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyllLndyaXRlU0ZpeGVkMzIodFtyXSk7fWZ1bmN0aW9uIG1hKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZUZpeGVkNjQodFtyXSk7fWZ1bmN0aW9uIGdhKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZVNGaXhlZDY0KHRbcl0pO31mdW5jdGlvbiB4YSh0LGUpe3JldHVybih0W2VdfHRbZSsxXTw8OHx0W2UrMl08PDE2KSsxNjc3NzIxNip0W2UrM119ZnVuY3Rpb24gYmEodCxlLHIpe3Rbcl09ZSx0W3IrMV09ZT4+PjgsdFtyKzJdPWU+Pj4xNix0W3IrM109ZT4+PjI0O31mdW5jdGlvbiB3YSh0LGUpe3JldHVybih0W2VdfHRbZSsxXTw8OHx0W2UrMl08PDE2KSsodFtlKzNdPDwyNCl9YWEucHJvdG90eXBlPXtkZXN0cm95OmZ1bmN0aW9uKCl7dGhpcy5idWY9bnVsbDt9LHJlYWRGaWVsZHM6ZnVuY3Rpb24odCxlLHIpe2ZvcihyPXJ8fHRoaXMubGVuZ3RoO3RoaXMucG9zPHI7KXt2YXIgbj10aGlzLnJlYWRWYXJpbnQoKSxpPW4+PjMsbz10aGlzLnBvczt0aGlzLnR5cGU9NyZuLHQoaSxlLHRoaXMpLHRoaXMucG9zPT09byYmdGhpcy5za2lwKG4pO31yZXR1cm4gZX0scmVhZE1lc3NhZ2U6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5yZWFkRmllbGRzKHQsZSx0aGlzLnJlYWRWYXJpbnQoKSt0aGlzLnBvcyl9LHJlYWRGaXhlZDMyOmZ1bmN0aW9uKCl7dmFyIHQ9eGEodGhpcy5idWYsdGhpcy5wb3MpO3JldHVybiB0aGlzLnBvcys9NCx0fSxyZWFkU0ZpeGVkMzI6ZnVuY3Rpb24oKXt2YXIgdD13YSh0aGlzLmJ1Zix0aGlzLnBvcyk7cmV0dXJuIHRoaXMucG9zKz00LHR9LHJlYWRGaXhlZDY0OmZ1bmN0aW9uKCl7dmFyIHQ9eGEodGhpcy5idWYsdGhpcy5wb3MpKzQyOTQ5NjcyOTYqeGEodGhpcy5idWYsdGhpcy5wb3MrNCk7cmV0dXJuIHRoaXMucG9zKz04LHR9LHJlYWRTRml4ZWQ2NDpmdW5jdGlvbigpe3ZhciB0PXhhKHRoaXMuYnVmLHRoaXMucG9zKSs0Mjk0OTY3Mjk2KndhKHRoaXMuYnVmLHRoaXMucG9zKzQpO3JldHVybiB0aGlzLnBvcys9OCx0fSxyZWFkRmxvYXQ6ZnVuY3Rpb24oKXt2YXIgdD1uYSh0aGlzLmJ1Zix0aGlzLnBvcywhMCwyMyw0KTtyZXR1cm4gdGhpcy5wb3MrPTQsdH0scmVhZERvdWJsZTpmdW5jdGlvbigpe3ZhciB0PW5hKHRoaXMuYnVmLHRoaXMucG9zLCEwLDUyLDgpO3JldHVybiB0aGlzLnBvcys9OCx0fSxyZWFkVmFyaW50OmZ1bmN0aW9uKHQpe3ZhciBlLHIsbj10aGlzLmJ1ZjtyZXR1cm4gZT0xMjcmKHI9blt0aGlzLnBvcysrXSkscjwxMjg/ZTooZXw9KDEyNyYocj1uW3RoaXMucG9zKytdKSk8PDcscjwxMjg/ZTooZXw9KDEyNyYocj1uW3RoaXMucG9zKytdKSk8PDE0LHI8MTI4P2U6KGV8PSgxMjcmKHI9blt0aGlzLnBvcysrXSkpPDwyMSxyPDEyOD9lOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbixpLG89ci5idWY7aWYoaT1vW3IucG9zKytdLG49KDExMiZpKT4+NCxpPDEyOClyZXR1cm4gdWEodCxuLGUpO2lmKGk9b1tyLnBvcysrXSxufD0oMTI3JmkpPDwzLGk8MTI4KXJldHVybiB1YSh0LG4sZSk7aWYoaT1vW3IucG9zKytdLG58PSgxMjcmaSk8PDEwLGk8MTI4KXJldHVybiB1YSh0LG4sZSk7aWYoaT1vW3IucG9zKytdLG58PSgxMjcmaSk8PDE3LGk8MTI4KXJldHVybiB1YSh0LG4sZSk7aWYoaT1vW3IucG9zKytdLG58PSgxMjcmaSk8PDI0LGk8MTI4KXJldHVybiB1YSh0LG4sZSk7aWYoaT1vW3IucG9zKytdLG58PSgxJmkpPDwzMSxpPDEyOClyZXR1cm4gdWEodCxuLGUpO3Rocm93IG5ldyBFcnJvcihcIkV4cGVjdGVkIHZhcmludCBub3QgbW9yZSB0aGFuIDEwIGJ5dGVzXCIpfShlfD0oMTUmKHI9blt0aGlzLnBvc10pKTw8MjgsdCx0aGlzKSkpKX0scmVhZFZhcmludDY0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVhZFZhcmludCghMCl9LHJlYWRTVmFyaW50OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yZWFkVmFyaW50KCk7cmV0dXJuIHQlMj09MT8odCsxKS8tMjp0LzJ9LHJlYWRCb29sZWFuOmZ1bmN0aW9uKCl7cmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpfSxyZWFkU3RyaW5nOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yZWFkVmFyaW50KCkrdGhpcy5wb3MsZT1mdW5jdGlvbih0LGUscil7dmFyIG49XCJcIixpPWU7Zm9yKDtpPHI7KXt2YXIgbyxhLHMsdT10W2ldLGw9bnVsbCxwPXU+MjM5PzQ6dT4yMjM/Mzp1PjE5MT8yOjE7aWYoaStwPnIpYnJlYWs7MT09PXA/dTwxMjgmJihsPXUpOjI9PT1wPzEyOD09KDE5MiYobz10W2krMV0pKSYmKGw9KDMxJnUpPDw2fDYzJm8pPD0xMjcmJihsPW51bGwpOjM9PT1wPyhvPXRbaSsxXSxhPXRbaSsyXSwxMjg9PSgxOTImbykmJjEyOD09KDE5MiZhKSYmKChsPSgxNSZ1KTw8MTJ8KDYzJm8pPDw2fDYzJmEpPD0yMDQ3fHxsPj01NTI5NiYmbDw9NTczNDMpJiYobD1udWxsKSk6ND09PXAmJihvPXRbaSsxXSxhPXRbaSsyXSxzPXRbaSszXSwxMjg9PSgxOTImbykmJjEyOD09KDE5MiZhKSYmMTI4PT0oMTkyJnMpJiYoKGw9KDE1JnUpPDwxOHwoNjMmbyk8PDEyfCg2MyZhKTw8Nnw2MyZzKTw9NjU1MzV8fGw+PTExMTQxMTIpJiYobD1udWxsKSksbnVsbD09PWw/KGw9NjU1MzMscD0xKTpsPjY1NTM1JiYobC09NjU1MzYsbis9U3RyaW5nLmZyb21DaGFyQ29kZShsPj4+MTAmMTAyM3w1NTI5NiksbD01NjMyMHwxMDIzJmwpLG4rPVN0cmluZy5mcm9tQ2hhckNvZGUobCksaSs9cDt9cmV0dXJuIG59KHRoaXMuYnVmLHRoaXMucG9zLHQpO3JldHVybiB0aGlzLnBvcz10LGV9LHJlYWRCeXRlczpmdW5jdGlvbigpe3ZhciB0PXRoaXMucmVhZFZhcmludCgpK3RoaXMucG9zLGU9dGhpcy5idWYuc3ViYXJyYXkodGhpcy5wb3MsdCk7cmV0dXJuIHRoaXMucG9zPXQsZX0scmVhZFBhY2tlZFZhcmludDpmdW5jdGlvbih0LGUpe3ZhciByPXNhKHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPHI7KXQucHVzaCh0aGlzLnJlYWRWYXJpbnQoZSkpO3JldHVybiB0fSxyZWFkUGFja2VkU1ZhcmludDpmdW5jdGlvbih0KXt2YXIgZT1zYSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxlOyl0LnB1c2godGhpcy5yZWFkU1ZhcmludCgpKTtyZXR1cm4gdH0scmVhZFBhY2tlZEJvb2xlYW46ZnVuY3Rpb24odCl7dmFyIGU9c2EodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZEJvb2xlYW4oKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWRGbG9hdDpmdW5jdGlvbih0KXt2YXIgZT1zYSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxlOyl0LnB1c2godGhpcy5yZWFkRmxvYXQoKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWREb3VibGU6ZnVuY3Rpb24odCl7dmFyIGU9c2EodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZERvdWJsZSgpKTtyZXR1cm4gdH0scmVhZFBhY2tlZEZpeGVkMzI6ZnVuY3Rpb24odCl7dmFyIGU9c2EodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZEZpeGVkMzIoKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWRTRml4ZWQzMjpmdW5jdGlvbih0KXt2YXIgZT1zYSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxlOyl0LnB1c2godGhpcy5yZWFkU0ZpeGVkMzIoKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWRGaXhlZDY0OmZ1bmN0aW9uKHQpe3ZhciBlPXNhKHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPGU7KXQucHVzaCh0aGlzLnJlYWRGaXhlZDY0KCkpO3JldHVybiB0fSxyZWFkUGFja2VkU0ZpeGVkNjQ6ZnVuY3Rpb24odCl7dmFyIGU9c2EodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZFNGaXhlZDY0KCkpO3JldHVybiB0fSxza2lwOmZ1bmN0aW9uKHQpe3ZhciBlPTcmdDtpZihlPT09YWEuVmFyaW50KWZvcig7dGhpcy5idWZbdGhpcy5wb3MrK10+MTI3Oyk7ZWxzZSBpZihlPT09YWEuQnl0ZXMpdGhpcy5wb3M9dGhpcy5yZWFkVmFyaW50KCkrdGhpcy5wb3M7ZWxzZSBpZihlPT09YWEuRml4ZWQzMil0aGlzLnBvcys9NDtlbHNle2lmKGUhPT1hYS5GaXhlZDY0KXRocm93IG5ldyBFcnJvcihcIlVuaW1wbGVtZW50ZWQgdHlwZTogXCIrZSk7dGhpcy5wb3MrPTg7fX0sd3JpdGVUYWc6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVmFyaW50KHQ8PDN8ZSk7fSxyZWFsbG9jOmZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10aGlzLmxlbmd0aHx8MTY7ZTx0aGlzLnBvcyt0OyllKj0yO2lmKGUhPT10aGlzLmxlbmd0aCl7dmFyIHI9bmV3IFVpbnQ4QXJyYXkoZSk7ci5zZXQodGhpcy5idWYpLHRoaXMuYnVmPXIsdGhpcy5sZW5ndGg9ZTt9fSxmaW5pc2g6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5sZW5ndGg9dGhpcy5wb3MsdGhpcy5wb3M9MCx0aGlzLmJ1Zi5zdWJhcnJheSgwLHRoaXMubGVuZ3RoKX0sd3JpdGVGaXhlZDMyOmZ1bmN0aW9uKHQpe3RoaXMucmVhbGxvYyg0KSxiYSh0aGlzLmJ1Zix0LHRoaXMucG9zKSx0aGlzLnBvcys9NDt9LHdyaXRlU0ZpeGVkMzI6ZnVuY3Rpb24odCl7dGhpcy5yZWFsbG9jKDQpLGJhKHRoaXMuYnVmLHQsdGhpcy5wb3MpLHRoaXMucG9zKz00O30sd3JpdGVGaXhlZDY0OmZ1bmN0aW9uKHQpe3RoaXMucmVhbGxvYyg4KSxiYSh0aGlzLmJ1ZiwtMSZ0LHRoaXMucG9zKSxiYSh0aGlzLmJ1ZixNYXRoLmZsb29yKHQqKDEvNDI5NDk2NzI5NikpLHRoaXMucG9zKzQpLHRoaXMucG9zKz04O30sd3JpdGVTRml4ZWQ2NDpmdW5jdGlvbih0KXt0aGlzLnJlYWxsb2MoOCksYmEodGhpcy5idWYsLTEmdCx0aGlzLnBvcyksYmEodGhpcy5idWYsTWF0aC5mbG9vcih0KigxLzQyOTQ5NjcyOTYpKSx0aGlzLnBvcys0KSx0aGlzLnBvcys9ODt9LHdyaXRlVmFyaW50OmZ1bmN0aW9uKHQpeyh0PSt0fHwwKT4yNjg0MzU0NTV8fHQ8MD9mdW5jdGlvbih0LGUpe3ZhciByLG47dD49MD8ocj10JTQyOTQ5NjcyOTZ8MCxuPXQvNDI5NDk2NzI5NnwwKToobj1+KC10LzQyOTQ5NjcyOTYpLDQyOTQ5NjcyOTVeKHI9figtdCU0Mjk0OTY3Mjk2KSk/cj1yKzF8MDoocj0wLG49bisxfDApKTtpZih0Pj0weDEwMDAwMDAwMDAwMDAwMDAwfHx0PC0weDEwMDAwMDAwMDAwMDAwMDAwKXRocm93IG5ldyBFcnJvcihcIkdpdmVuIHZhcmludCBkb2Vzbid0IGZpdCBpbnRvIDEwIGJ5dGVzXCIpO2UucmVhbGxvYygxMCksZnVuY3Rpb24odCxlLHIpe3IuYnVmW3IucG9zKytdPTEyNyZ0fDEyOCx0Pj4+PTcsci5idWZbci5wb3MrK109MTI3JnR8MTI4LHQ+Pj49NyxyLmJ1ZltyLnBvcysrXT0xMjcmdHwxMjgsdD4+Pj03LHIuYnVmW3IucG9zKytdPTEyNyZ0fDEyOCx0Pj4+PTcsci5idWZbci5wb3NdPTEyNyZ0O30ociwwLGUpLGZ1bmN0aW9uKHQsZSl7dmFyIHI9KDcmdCk8PDQ7aWYoZS5idWZbZS5wb3MrK118PXJ8KCh0Pj4+PTMpPzEyODowKSwhdClyZXR1cm47aWYoZS5idWZbZS5wb3MrK109MTI3JnR8KCh0Pj4+PTcpPzEyODowKSwhdClyZXR1cm47aWYoZS5idWZbZS5wb3MrK109MTI3JnR8KCh0Pj4+PTcpPzEyODowKSwhdClyZXR1cm47aWYoZS5idWZbZS5wb3MrK109MTI3JnR8KCh0Pj4+PTcpPzEyODowKSwhdClyZXR1cm47aWYoZS5idWZbZS5wb3MrK109MTI3JnR8KCh0Pj4+PTcpPzEyODowKSwhdClyZXR1cm47ZS5idWZbZS5wb3MrK109MTI3JnQ7fShuLGUpO30odCx0aGlzKToodGhpcy5yZWFsbG9jKDQpLHRoaXMuYnVmW3RoaXMucG9zKytdPTEyNyZ0fCh0PjEyNz8xMjg6MCksdDw9MTI3fHwodGhpcy5idWZbdGhpcy5wb3MrK109MTI3Jih0Pj4+PTcpfCh0PjEyNz8xMjg6MCksdDw9MTI3fHwodGhpcy5idWZbdGhpcy5wb3MrK109MTI3Jih0Pj4+PTcpfCh0PjEyNz8xMjg6MCksdDw9MTI3fHwodGhpcy5idWZbdGhpcy5wb3MrK109dD4+PjcmMTI3KSkpKTt9LHdyaXRlU1ZhcmludDpmdW5jdGlvbih0KXt0aGlzLndyaXRlVmFyaW50KHQ8MD8yKi10LTE6Mip0KTt9LHdyaXRlQm9vbGVhbjpmdW5jdGlvbih0KXt0aGlzLndyaXRlVmFyaW50KEJvb2xlYW4odCkpO30sd3JpdGVTdHJpbmc6ZnVuY3Rpb24odCl7dD1TdHJpbmcodCksdGhpcy5yZWFsbG9jKDQqdC5sZW5ndGgpLHRoaXMucG9zKys7dmFyIGU9dGhpcy5wb3M7dGhpcy5wb3M9ZnVuY3Rpb24odCxlLHIpe2Zvcih2YXIgbixpLG89MDtvPGUubGVuZ3RoO28rKyl7aWYoKG49ZS5jaGFyQ29kZUF0KG8pKT41NTI5NSYmbjw1NzM0NCl7aWYoIWkpe24+NTYzMTl8fG8rMT09PWUubGVuZ3RoPyh0W3IrK109MjM5LHRbcisrXT0xOTEsdFtyKytdPTE4OSk6aT1uO2NvbnRpbnVlfWlmKG48NTYzMjApe3RbcisrXT0yMzksdFtyKytdPTE5MSx0W3IrK109MTg5LGk9bjtjb250aW51ZX1uPWktNTUyOTY8PDEwfG4tNTYzMjB8NjU1MzYsaT1udWxsO31lbHNlIGkmJih0W3IrK109MjM5LHRbcisrXT0xOTEsdFtyKytdPTE4OSxpPW51bGwpO248MTI4P3RbcisrXT1uOihuPDIwNDg/dFtyKytdPW4+PjZ8MTkyOihuPDY1NTM2P3RbcisrXT1uPj4xMnwyMjQ6KHRbcisrXT1uPj4xOHwyNDAsdFtyKytdPW4+PjEyJjYzfDEyOCksdFtyKytdPW4+PjYmNjN8MTI4KSx0W3IrK109NjMmbnwxMjgpO31yZXR1cm4gcn0odGhpcy5idWYsdCx0aGlzLnBvcyk7dmFyIHI9dGhpcy5wb3MtZTtyPj0xMjgmJmxhKGUscix0aGlzKSx0aGlzLnBvcz1lLTEsdGhpcy53cml0ZVZhcmludChyKSx0aGlzLnBvcys9cjt9LHdyaXRlRmxvYXQ6ZnVuY3Rpb24odCl7dGhpcy5yZWFsbG9jKDQpLGlhKHRoaXMuYnVmLHQsdGhpcy5wb3MsITAsMjMsNCksdGhpcy5wb3MrPTQ7fSx3cml0ZURvdWJsZTpmdW5jdGlvbih0KXt0aGlzLnJlYWxsb2MoOCksaWEodGhpcy5idWYsdCx0aGlzLnBvcywhMCw1Miw4KSx0aGlzLnBvcys9ODt9LHdyaXRlQnl0ZXM6ZnVuY3Rpb24odCl7dmFyIGU9dC5sZW5ndGg7dGhpcy53cml0ZVZhcmludChlKSx0aGlzLnJlYWxsb2MoZSk7Zm9yKHZhciByPTA7cjxlO3IrKyl0aGlzLmJ1Zlt0aGlzLnBvcysrXT10W3JdO30sd3JpdGVSYXdNZXNzYWdlOmZ1bmN0aW9uKHQsZSl7dGhpcy5wb3MrKzt2YXIgcj10aGlzLnBvczt0KGUsdGhpcyk7dmFyIG49dGhpcy5wb3MtcjtuPj0xMjgmJmxhKHIsbix0aGlzKSx0aGlzLnBvcz1yLTEsdGhpcy53cml0ZVZhcmludChuKSx0aGlzLnBvcys9bjt9LHdyaXRlTWVzc2FnZTpmdW5jdGlvbih0LGUscil7dGhpcy53cml0ZVRhZyh0LGFhLkJ5dGVzKSx0aGlzLndyaXRlUmF3TWVzc2FnZShlLHIpO30sd3JpdGVQYWNrZWRWYXJpbnQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlTWVzc2FnZSh0LHBhLGUpO30sd3JpdGVQYWNrZWRTVmFyaW50OmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZU1lc3NhZ2UodCxjYSxlKTt9LHdyaXRlUGFja2VkQm9vbGVhbjpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVNZXNzYWdlKHQseWEsZSk7fSx3cml0ZVBhY2tlZEZsb2F0OmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZU1lc3NhZ2UodCxoYSxlKTt9LHdyaXRlUGFja2VkRG91YmxlOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZU1lc3NhZ2UodCxmYSxlKTt9LHdyaXRlUGFja2VkRml4ZWQzMjpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVNZXNzYWdlKHQsZGEsZSk7fSx3cml0ZVBhY2tlZFNGaXhlZDMyOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZU1lc3NhZ2UodCx2YSxlKTt9LHdyaXRlUGFja2VkRml4ZWQ2NDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVNZXNzYWdlKHQsbWEsZSk7fSx3cml0ZVBhY2tlZFNGaXhlZDY0OmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZU1lc3NhZ2UodCxnYSxlKTt9LHdyaXRlQnl0ZXNGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxhYS5CeXRlcyksdGhpcy53cml0ZUJ5dGVzKGUpO30sd3JpdGVGaXhlZDMyRmllbGQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVGFnKHQsYWEuRml4ZWQzMiksdGhpcy53cml0ZUZpeGVkMzIoZSk7fSx3cml0ZVNGaXhlZDMyRmllbGQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVGFnKHQsYWEuRml4ZWQzMiksdGhpcy53cml0ZVNGaXhlZDMyKGUpO30sd3JpdGVGaXhlZDY0RmllbGQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVGFnKHQsYWEuRml4ZWQ2NCksdGhpcy53cml0ZUZpeGVkNjQoZSk7fSx3cml0ZVNGaXhlZDY0RmllbGQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVGFnKHQsYWEuRml4ZWQ2NCksdGhpcy53cml0ZVNGaXhlZDY0KGUpO30sd3JpdGVWYXJpbnRGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxhYS5WYXJpbnQpLHRoaXMud3JpdGVWYXJpbnQoZSk7fSx3cml0ZVNWYXJpbnRGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxhYS5WYXJpbnQpLHRoaXMud3JpdGVTVmFyaW50KGUpO30sd3JpdGVTdHJpbmdGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxhYS5CeXRlcyksdGhpcy53cml0ZVN0cmluZyhlKTt9LHdyaXRlRmxvYXRGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxhYS5GaXhlZDMyKSx0aGlzLndyaXRlRmxvYXQoZSk7fSx3cml0ZURvdWJsZUZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LGFhLkZpeGVkNjQpLHRoaXMud3JpdGVEb3VibGUoZSk7fSx3cml0ZUJvb2xlYW5GaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVWYXJpbnRGaWVsZCh0LEJvb2xlYW4oZSkpO319O3ZhciBfYT0zO2Z1bmN0aW9uIEFhKHQsZSxyKXsxPT09dCYmci5yZWFkTWVzc2FnZShrYSxlKTt9ZnVuY3Rpb24ga2EodCxlLHIpe2lmKDM9PT10KXt2YXIgbj1yLnJlYWRNZXNzYWdlKHphLHt9KSxpPW4uaWQsbz1uLmJpdG1hcCxhPW4ud2lkdGgscz1uLmhlaWdodCx1PW4ubGVmdCxsPW4udG9wLHA9bi5hZHZhbmNlO2UucHVzaCh7aWQ6aSxiaXRtYXA6bmV3IGxpKHt3aWR0aDphKzIqX2EsaGVpZ2h0OnMrMipfYX0sbyksbWV0cmljczp7d2lkdGg6YSxoZWlnaHQ6cyxsZWZ0OnUsdG9wOmwsYWR2YW5jZTpwfX0pO319ZnVuY3Rpb24gemEodCxlLHIpezE9PT10P2UuaWQ9ci5yZWFkVmFyaW50KCk6Mj09PXQ/ZS5iaXRtYXA9ci5yZWFkQnl0ZXMoKTozPT09dD9lLndpZHRoPXIucmVhZFZhcmludCgpOjQ9PT10P2UuaGVpZ2h0PXIucmVhZFZhcmludCgpOjU9PT10P2UubGVmdD1yLnJlYWRTVmFyaW50KCk6Nj09PXQ/ZS50b3A9ci5yZWFkU1ZhcmludCgpOjc9PT10JiYoZS5hZHZhbmNlPXIucmVhZFZhcmludCgpKTt9dmFyIFNhPV9hLE1hPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnRhcmdldD10LHRoaXMucGFyZW50PWUsdGhpcy5tYXBJZD1yLHRoaXMuY2FsbGJhY2tzPXt9LHRoaXMuY2FsbGJhY2tJRD0wLHkoW1wicmVjZWl2ZVwiXSx0aGlzKSx0aGlzLnRhcmdldC5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLHRoaXMucmVjZWl2ZSwhMSk7fTtNYS5wcm90b3R5cGUuc2VuZD1mdW5jdGlvbih0LGUscixuKXt2YXIgaT1yP3RoaXMubWFwSWQrXCI6XCIrdGhpcy5jYWxsYmFja0lEKys6bnVsbDtyJiYodGhpcy5jYWxsYmFja3NbaV09cik7dmFyIG89W107dGhpcy50YXJnZXQucG9zdE1lc3NhZ2Uoe3RhcmdldE1hcElkOm4sc291cmNlTWFwSWQ6dGhpcy5tYXBJZCx0eXBlOnQsaWQ6U3RyaW5nKGkpLGRhdGE6eXIoZSxvKX0sbyk7fSxNYS5wcm90b3R5cGUucmVjZWl2ZT1mdW5jdGlvbih0KXt2YXIgZSxyPXRoaXMsbj10LmRhdGEsaT1uLmlkO2lmKCFuLnRhcmdldE1hcElkfHx0aGlzLm1hcElkPT09bi50YXJnZXRNYXBJZCl7dmFyIG89ZnVuY3Rpb24odCxlKXt2YXIgbj1bXTtyLnRhcmdldC5wb3N0TWVzc2FnZSh7c291cmNlTWFwSWQ6ci5tYXBJZCx0eXBlOlwiPHJlc3BvbnNlPlwiLGlkOlN0cmluZyhpKSxlcnJvcjp0P3lyKHQpOm51bGwsZGF0YTp5cihlLG4pfSxuKTt9O2lmKFwiPHJlc3BvbnNlPlwiPT09bi50eXBlKWU9dGhpcy5jYWxsYmFja3Nbbi5pZF0sZGVsZXRlIHRoaXMuY2FsbGJhY2tzW24uaWRdLGUmJm4uZXJyb3I/ZShkcihuLmVycm9yKSk6ZSYmZShudWxsLGRyKG4uZGF0YSkpO2Vsc2UgaWYodm9pZCAwIT09bi5pZCYmdGhpcy5wYXJlbnRbbi50eXBlXSl0aGlzLnBhcmVudFtuLnR5cGVdKG4uc291cmNlTWFwSWQsZHIobi5kYXRhKSxvKTtlbHNlIGlmKHZvaWQgMCE9PW4uaWQmJnRoaXMucGFyZW50LmdldFdvcmtlclNvdXJjZSl7dmFyIGE9bi50eXBlLnNwbGl0KFwiLlwiKTt0aGlzLnBhcmVudC5nZXRXb3JrZXJTb3VyY2Uobi5zb3VyY2VNYXBJZCxhWzBdLGFbMV0pW2FbMl1dKGRyKG4uZGF0YSksbyk7fWVsc2UgdGhpcy5wYXJlbnRbbi50eXBlXShkcihuLmRhdGEpKTt9fSxNYS5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7dGhpcy50YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIix0aGlzLnJlY2VpdmUsITEpO307dmFyIFZhPXIobihmdW5jdGlvbih0LGUpeyFmdW5jdGlvbih0KXtmdW5jdGlvbiBlKHQsZSxuKXtlPU1hdGgucG93KDIsbiktZS0xO3ZhciBpPXIoMjU2KnQsMjU2KmUsbiksbz1yKDI1NioodCsxKSwyNTYqKGUrMSksbik7cmV0dXJuIGlbMF0rXCIsXCIraVsxXStcIixcIitvWzBdK1wiLFwiK29bMV19ZnVuY3Rpb24gcih0LGUscil7dmFyIG49MipNYXRoLlBJKjYzNzgxMzcvMjU2L01hdGgucG93KDIsciksaT10Km4tMipNYXRoLlBJKjYzNzgxMzcvMixvPWUqbi0yKk1hdGguUEkqNjM3ODEzNy8yO3JldHVybltpLG9dfXQuZ2V0VVJMPWZ1bmN0aW9uKHQscixuLGksbyxhKXtyZXR1cm4gYT1hfHx7fSx0K1wiP1wiK1tcImJib3g9XCIrZShuLGksbyksXCJmb3JtYXQ9XCIrKGEuZm9ybWF0fHxcImltYWdlL3BuZ1wiKSxcInNlcnZpY2U9XCIrKGEuc2VydmljZXx8XCJXTVNcIiksXCJ2ZXJzaW9uPVwiKyhhLnZlcnNpb258fFwiMS4xLjFcIiksXCJyZXF1ZXN0PVwiKyhhLnJlcXVlc3R8fFwiR2V0TWFwXCIpLFwic3JzPVwiKyhhLnNyc3x8XCJFUFNHOjM4NTdcIiksXCJ3aWR0aD1cIisoYS53aWR0aHx8MjU2KSxcImhlaWdodD1cIisoYS5oZWlnaHR8fDI1NiksXCJsYXllcnM9XCIrcl0uam9pbihcIiZcIil9LHQuZ2V0VGlsZUJCb3g9ZSx0LmdldE1lcmNDb29yZHM9cixPYmplY3QuZGVmaW5lUHJvcGVydHkodCxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt9KGUpO30pKSxCYT1mdW5jdGlvbih0LGUscil7dGhpcy56PXQsdGhpcy54PWUsdGhpcy55PXIsdGhpcy5rZXk9RWEoMCx0LGUscik7fTtCYS5wcm90b3R5cGUuZXF1YWxzPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLno9PT10LnomJnRoaXMueD09PXQueCYmdGhpcy55PT09dC55fSxCYS5wcm90b3R5cGUudXJsPWZ1bmN0aW9uKHQsZSl7dmFyIHI9VmEuZ2V0VGlsZUJCb3godGhpcy54LHRoaXMueSx0aGlzLnopLG49ZnVuY3Rpb24odCxlLHIpe2Zvcih2YXIgbixpPVwiXCIsbz10O28+MDtvLS0paSs9KGUmKG49MTw8by0xKT8xOjApKyhyJm4/MjowKTtyZXR1cm4gaX0odGhpcy56LHRoaXMueCx0aGlzLnkpO3JldHVybiB0Wyh0aGlzLngrdGhpcy55KSV0Lmxlbmd0aF0ucmVwbGFjZShcIntwcmVmaXh9XCIsKHRoaXMueCUxNikudG9TdHJpbmcoMTYpKyh0aGlzLnklMTYpLnRvU3RyaW5nKDE2KSkucmVwbGFjZShcInt6fVwiLFN0cmluZyh0aGlzLnopKS5yZXBsYWNlKFwie3h9XCIsU3RyaW5nKHRoaXMueCkpLnJlcGxhY2UoXCJ7eX1cIixTdHJpbmcoXCJ0bXNcIj09PWU/TWF0aC5wb3coMix0aGlzLnopLXRoaXMueS0xOnRoaXMueSkpLnJlcGxhY2UoXCJ7cXVhZGtleX1cIixuKS5yZXBsYWNlKFwie2Jib3gtZXBzZy0zODU3fVwiLHIpfTt2YXIgQ2E9ZnVuY3Rpb24odCxlKXt0aGlzLndyYXA9dCx0aGlzLmNhbm9uaWNhbD1lLHRoaXMua2V5PUVhKHQsZS56LGUueCxlLnkpO30sSWE9ZnVuY3Rpb24odCxlLHIsbixpKXt0aGlzLm92ZXJzY2FsZWRaPXQsdGhpcy53cmFwPWUsdGhpcy5jYW5vbmljYWw9bmV3IEJhKHIsK24sK2kpLHRoaXMua2V5PUVhKGUsdCxuLGkpO307ZnVuY3Rpb24gRWEodCxlLHIsbil7KHQqPTIpPDAmJih0PS0xKnQtMSk7dmFyIGk9MTw8ZTtyZXR1cm4gMzIqKGkqaSp0K2kqbityKStlfUlhLnByb3RvdHlwZS5lcXVhbHM9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMub3ZlcnNjYWxlZFo9PT10Lm92ZXJzY2FsZWRaJiZ0aGlzLndyYXA9PT10LndyYXAmJnRoaXMuY2Fub25pY2FsLmVxdWFscyh0LmNhbm9uaWNhbCl9LElhLnByb3RvdHlwZS5zY2FsZWRUbz1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmNhbm9uaWNhbC56LXQ7cmV0dXJuIHQ+dGhpcy5jYW5vbmljYWwuej9uZXcgSWEodCx0aGlzLndyYXAsdGhpcy5jYW5vbmljYWwueix0aGlzLmNhbm9uaWNhbC54LHRoaXMuY2Fub25pY2FsLnkpOm5ldyBJYSh0LHRoaXMud3JhcCx0LHRoaXMuY2Fub25pY2FsLng+PmUsdGhpcy5jYW5vbmljYWwueT4+ZSl9LElhLnByb3RvdHlwZS5pc0NoaWxkT2Y9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jYW5vbmljYWwuei10LmNhbm9uaWNhbC56O3JldHVybiAwPT09dC5vdmVyc2NhbGVkWnx8dC5vdmVyc2NhbGVkWjx0aGlzLm92ZXJzY2FsZWRaJiZ0LmNhbm9uaWNhbC54PT09dGhpcy5jYW5vbmljYWwueD4+ZSYmdC5jYW5vbmljYWwueT09PXRoaXMuY2Fub25pY2FsLnk+PmV9LElhLnByb3RvdHlwZS5jaGlsZHJlbj1mdW5jdGlvbih0KXtpZih0aGlzLm92ZXJzY2FsZWRaPj10KXJldHVybltuZXcgSWEodGhpcy5vdmVyc2NhbGVkWisxLHRoaXMud3JhcCx0aGlzLmNhbm9uaWNhbC56LHRoaXMuY2Fub25pY2FsLngsdGhpcy5jYW5vbmljYWwueSldO3ZhciBlPXRoaXMuY2Fub25pY2FsLnorMSxyPTIqdGhpcy5jYW5vbmljYWwueCxuPTIqdGhpcy5jYW5vbmljYWwueTtyZXR1cm5bbmV3IElhKGUsdGhpcy53cmFwLGUscixuKSxuZXcgSWEoZSx0aGlzLndyYXAsZSxyKzEsbiksbmV3IElhKGUsdGhpcy53cmFwLGUscixuKzEpLG5ldyBJYShlLHRoaXMud3JhcCxlLHIrMSxuKzEpXX0sSWEucHJvdG90eXBlLmlzTGVzc1RoYW49ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMud3JhcDx0LndyYXB8fCEodGhpcy53cmFwPnQud3JhcCkmJih0aGlzLm92ZXJzY2FsZWRaPHQub3ZlcnNjYWxlZFp8fCEodGhpcy5vdmVyc2NhbGVkWj50Lm92ZXJzY2FsZWRaKSYmKHRoaXMuY2Fub25pY2FsLng8dC5jYW5vbmljYWwueHx8ISh0aGlzLmNhbm9uaWNhbC54PnQuY2Fub25pY2FsLngpJiZ0aGlzLmNhbm9uaWNhbC55PHQuY2Fub25pY2FsLnkpKX0sSWEucHJvdG90eXBlLndyYXBwZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IElhKHRoaXMub3ZlcnNjYWxlZFosMCx0aGlzLmNhbm9uaWNhbC56LHRoaXMuY2Fub25pY2FsLngsdGhpcy5jYW5vbmljYWwueSl9LElhLnByb3RvdHlwZS51bndyYXBUbz1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IElhKHRoaXMub3ZlcnNjYWxlZFosdCx0aGlzLmNhbm9uaWNhbC56LHRoaXMuY2Fub25pY2FsLngsdGhpcy5jYW5vbmljYWwueSl9LElhLnByb3RvdHlwZS5vdmVyc2NhbGVGYWN0b3I9ZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5wb3coMix0aGlzLm92ZXJzY2FsZWRaLXRoaXMuY2Fub25pY2FsLnopfSxJYS5wcm90b3R5cGUudG9VbndyYXBwZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IENhKHRoaXMud3JhcCx0aGlzLmNhbm9uaWNhbCl9LElhLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLm92ZXJzY2FsZWRaK1wiL1wiK3RoaXMuY2Fub25pY2FsLngrXCIvXCIrdGhpcy5jYW5vbmljYWwueX0sSWEucHJvdG90eXBlLnRvQ29vcmRpbmF0ZT1mdW5jdGlvbigpe3JldHVybiBuZXcgYSh0aGlzLmNhbm9uaWNhbC54K01hdGgucG93KDIsdGhpcy53cmFwKSx0aGlzLmNhbm9uaWNhbC55LHRoaXMuY2Fub25pY2FsLnopfSxocihcIkNhbm9uaWNhbFRpbGVJRFwiLEJhKSxocihcIk92ZXJzY2FsZWRUaWxlSURcIixJYSx7b21pdDpbXCJwb3NNYXRyaXhcIl19KTt2YXIgRmE9ZnVuY3Rpb24odCxlLHIpe2lmKHQ8PTApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJMZXZlbCBtdXN0IGhhdmUgcG9zaXRpdmUgZGltZW5zaW9uXCIpO3RoaXMuZGltPXQsdGhpcy5ib3JkZXI9ZSx0aGlzLnN0cmlkZT10aGlzLmRpbSsyKnRoaXMuYm9yZGVyLHRoaXMuZGF0YT1yfHxuZXcgSW50MzJBcnJheSgodGhpcy5kaW0rMip0aGlzLmJvcmRlcikqKHRoaXMuZGltKzIqdGhpcy5ib3JkZXIpKTt9O0ZhLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCxlLHIpe3RoaXMuZGF0YVt0aGlzLl9pZHgodCxlKV09cis2NTUzNjt9LEZhLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5kYXRhW3RoaXMuX2lkeCh0LGUpXS02NTUzNn0sRmEucHJvdG90eXBlLl9pZHg9ZnVuY3Rpb24odCxlKXtpZih0PC10aGlzLmJvcmRlcnx8dD49dGhpcy5kaW0rdGhpcy5ib3JkZXJ8fGU8LXRoaXMuYm9yZGVyfHxlPj10aGlzLmRpbSt0aGlzLmJvcmRlcil0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIm91dCBvZiByYW5nZSBzb3VyY2UgY29vcmRpbmF0ZXMgZm9yIERFTSBkYXRhXCIpO3JldHVybihlK3RoaXMuYm9yZGVyKSp0aGlzLnN0cmlkZSsodCt0aGlzLmJvcmRlcil9LGhyKFwiTGV2ZWxcIixGYSk7dmFyIFBhPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnVpZD10LHRoaXMuc2NhbGU9ZXx8MSx0aGlzLmxldmVsPXJ8fG5ldyBGYSgyNTYsNTEyKSx0aGlzLmxvYWRlZD0hIXI7fTtQYS5wcm90b3R5cGUubG9hZEZyb21JbWFnZT1mdW5jdGlvbih0LGUpe2lmKHQuaGVpZ2h0IT09dC53aWR0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkRFTSB0aWxlcyBtdXN0IGJlIHNxdWFyZVwiKTtpZihlJiZcIm1hcGJveFwiIT09ZSYmXCJ0ZXJyYXJpdW1cIiE9PWUpcmV0dXJuIGIoJ1wiJytlKydcIiBpcyBub3QgYSB2YWxpZCBlbmNvZGluZyB0eXBlLiBWYWxpZCB0eXBlcyBpbmNsdWRlIFwibWFwYm94XCIgYW5kIFwidGVycmFyaXVtXCIuJyk7dmFyIHI9dGhpcy5sZXZlbD1uZXcgRmEodC53aWR0aCx0LndpZHRoLzIpLG49dC5kYXRhO3RoaXMuX3VucGFja0RhdGEocixuLGV8fFwibWFwYm94XCIpO2Zvcih2YXIgaT0wO2k8ci5kaW07aSsrKXIuc2V0KC0xLGksci5nZXQoMCxpKSksci5zZXQoci5kaW0saSxyLmdldChyLmRpbS0xLGkpKSxyLnNldChpLC0xLHIuZ2V0KGksMCkpLHIuc2V0KGksci5kaW0sci5nZXQoaSxyLmRpbS0xKSk7ci5zZXQoLTEsLTEsci5nZXQoMCwwKSksci5zZXQoci5kaW0sLTEsci5nZXQoci5kaW0tMSwwKSksci5zZXQoLTEsci5kaW0sci5nZXQoMCxyLmRpbS0xKSksci5zZXQoci5kaW0sci5kaW0sci5nZXQoci5kaW0tMSxyLmRpbS0xKSksdGhpcy5sb2FkZWQ9ITA7fSxQYS5wcm90b3R5cGUuX3VucGFja01hcGJveD1mdW5jdGlvbih0LGUscil7cmV0dXJuKDI1Nip0KjI1NisyNTYqZStyKS8xMC0xZTR9LFBhLnByb3RvdHlwZS5fdW5wYWNrVGVycmFyaXVtPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gMjU2KnQrZStyLzI1Ni0zMjc2OH0sUGEucHJvdG90eXBlLl91bnBhY2tEYXRhPWZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG49e21hcGJveDp0aGlzLl91bnBhY2tNYXBib3gsdGVycmFyaXVtOnRoaXMuX3VucGFja1RlcnJhcml1bX1bcl0saT0wO2k8dC5kaW07aSsrKWZvcih2YXIgbz0wO288dC5kaW07bysrKXt2YXIgYT00KihpKnQuZGltK28pO3Quc2V0KG8saSx0aGlzLnNjYWxlKm4oZVthXSxlW2ErMV0sZVthKzJdKSk7fX0sUGEucHJvdG90eXBlLmdldFBpeGVscz1mdW5jdGlvbigpe3JldHVybiBuZXcgcGkoe3dpZHRoOnRoaXMubGV2ZWwuZGltKzIqdGhpcy5sZXZlbC5ib3JkZXIsaGVpZ2h0OnRoaXMubGV2ZWwuZGltKzIqdGhpcy5sZXZlbC5ib3JkZXJ9LG5ldyBVaW50OEFycmF5KHRoaXMubGV2ZWwuZGF0YS5idWZmZXIpKX0sUGEucHJvdG90eXBlLmJhY2tmaWxsQm9yZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLmxldmVsLGk9dC5sZXZlbDtpZihuLmRpbSE9PWkuZGltKXRocm93IG5ldyBFcnJvcihcImxldmVsIG1pc21hdGNoIChkZW0gZGltZW5zaW9uKVwiKTt2YXIgbz1lKm4uZGltLGE9ZSpuLmRpbStuLmRpbSxzPXIqbi5kaW0sdT1yKm4uZGltK24uZGltO3N3aXRjaChlKXtjYXNlLTE6bz1hLTE7YnJlYWs7Y2FzZSAxOmE9bysxO31zd2l0Y2gocil7Y2FzZS0xOnM9dS0xO2JyZWFrO2Nhc2UgMTp1PXMrMTt9Zm9yKHZhciBsPWMobywtbi5ib3JkZXIsbi5kaW0rbi5ib3JkZXIpLHA9YyhhLC1uLmJvcmRlcixuLmRpbStuLmJvcmRlciksaD1jKHMsLW4uYm9yZGVyLG4uZGltK24uYm9yZGVyKSxmPWModSwtbi5ib3JkZXIsbi5kaW0rbi5ib3JkZXIpLHk9LWUqbi5kaW0sZD0tcipuLmRpbSx2PWg7djxmO3YrKylmb3IodmFyIG09bDttPHA7bSsrKW4uc2V0KG0sdixpLmdldChtK3ksditkKSk7fSxocihcIkRFTURhdGFcIixQYSk7dmFyIFRhPWZ1bmN0aW9uKHQpe3RoaXMuX3N0cmluZ1RvTnVtYmVyPXt9LHRoaXMuX251bWJlclRvU3RyaW5nPVtdO2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKXt2YXIgcj10W2VdO3RoaXMuX3N0cmluZ1RvTnVtYmVyW3JdPWUsdGhpcy5fbnVtYmVyVG9TdHJpbmdbZV09cjt9fTtUYS5wcm90b3R5cGUuZW5jb2RlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zdHJpbmdUb051bWJlclt0XX0sVGEucHJvdG90eXBlLmRlY29kZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbnVtYmVyVG9TdHJpbmdbdF19O3ZhciBPYT1mdW5jdGlvbih0LGUscixuKXt0aGlzLnR5cGU9XCJGZWF0dXJlXCIsdGhpcy5fdmVjdG9yVGlsZUZlYXR1cmU9dCx0Ll96PWUsdC5feD1yLHQuX3k9bix0aGlzLnByb3BlcnRpZXM9dC5wcm9wZXJ0aWVzLG51bGwhPXQuaWQmJih0aGlzLmlkPXQuaWQpO30sTGE9e2dlb21ldHJ5Ontjb25maWd1cmFibGU6ITB9fTtMYS5nZW9tZXRyeS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdm9pZCAwPT09dGhpcy5fZ2VvbWV0cnkmJih0aGlzLl9nZW9tZXRyeT10aGlzLl92ZWN0b3JUaWxlRmVhdHVyZS50b0dlb0pTT04odGhpcy5fdmVjdG9yVGlsZUZlYXR1cmUuX3gsdGhpcy5fdmVjdG9yVGlsZUZlYXR1cmUuX3ksdGhpcy5fdmVjdG9yVGlsZUZlYXR1cmUuX3opLmdlb21ldHJ5KSx0aGlzLl9nZW9tZXRyeX0sTGEuZ2VvbWV0cnkuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX2dlb21ldHJ5PXQ7fSxPYS5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7dmFyIHQ9e2dlb21ldHJ5OnRoaXMuZ2VvbWV0cnl9O2Zvcih2YXIgZSBpbiB0aGlzKVwiX2dlb21ldHJ5XCIhPT1lJiZcIl92ZWN0b3JUaWxlRmVhdHVyZVwiIT09ZSYmKHRbZV09dGhpc1tlXSk7cmV0dXJuIHR9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE9hLnByb3RvdHlwZSxMYSk7dmFyIGphPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnRpbGVJRD10LHRoaXMueD10LmNhbm9uaWNhbC54LHRoaXMueT10LmNhbm9uaWNhbC55LHRoaXMuej10LmNhbm9uaWNhbC56LHRoaXMuZ3JpZD1lfHxuZXcgc3IoUG4sMTYsMCksdGhpcy5mZWF0dXJlSW5kZXhBcnJheT1yfHxuZXcgQW47fTtmdW5jdGlvbiBxYSh0LGUpe3JldHVybiBlLXR9amEucHJvdG90eXBlLmluc2VydD1mdW5jdGlvbih0LGUscixuLGkpe3ZhciBvPXRoaXMuZmVhdHVyZUluZGV4QXJyYXkubGVuZ3RoO3RoaXMuZmVhdHVyZUluZGV4QXJyYXkuZW1wbGFjZUJhY2socixuLGkpO2Zvcih2YXIgYT0wO2E8ZS5sZW5ndGg7YSsrKXtmb3IodmFyIHM9ZVthXSx1PVsxLzAsMS8wLC0xLzAsLTEvMF0sbD0wO2w8cy5sZW5ndGg7bCsrKXt2YXIgcD1zW2xdO3VbMF09TWF0aC5taW4odVswXSxwLngpLHVbMV09TWF0aC5taW4odVsxXSxwLnkpLHVbMl09TWF0aC5tYXgodVsyXSxwLngpLHVbM109TWF0aC5tYXgodVszXSxwLnkpO311WzBdPFBuJiZ1WzFdPFBuJiZ1WzJdPj0wJiZ1WzNdPj0wJiZ0aGlzLmdyaWQuaW5zZXJ0KG8sdVswXSx1WzFdLHVbMl0sdVszXSk7fX0samEucHJvdG90eXBlLmxvYWRWVExheWVycz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnZ0TGF5ZXJzfHwodGhpcy52dExheWVycz1uZXcgdm8uVmVjdG9yVGlsZShuZXcgb2EodGhpcy5yYXdUaWxlRGF0YSkpLmxheWVycyx0aGlzLnNvdXJjZUxheWVyQ29kZXI9bmV3IFRhKHRoaXMudnRMYXllcnM/T2JqZWN0LmtleXModGhpcy52dExheWVycykuc29ydCgpOltcIl9nZW9qc29uVGlsZUxheWVyXCJdKSksdGhpcy52dExheWVyc30samEucHJvdG90eXBlLnF1ZXJ5PWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpczt0aGlzLmxvYWRWVExheWVycygpO2Zvcih2YXIgbj10LnBhcmFtc3x8e30saT1Qbi90LnRpbGVTaXplL3Quc2NhbGUsbz1UZShuLmZpbHRlciksYT10LnF1ZXJ5R2VvbWV0cnkscz10LnF1ZXJ5UGFkZGluZyppLHU9MS8wLGw9MS8wLHA9LTEvMCxjPS0xLzAsaD0wO2g8YS5sZW5ndGg7aCsrKWZvcih2YXIgZj1hW2hdLHk9MDt5PGYubGVuZ3RoO3krKyl7dmFyIGQ9Zlt5XTt1PU1hdGgubWluKHUsZC54KSxsPU1hdGgubWluKGwsZC55KSxwPU1hdGgubWF4KHAsZC54KSxjPU1hdGgubWF4KGMsZC55KTt9dmFyIHY9dGhpcy5ncmlkLnF1ZXJ5KHUtcyxsLXMscCtzLGMrcyk7di5zb3J0KHFhKTtmb3IodmFyIG0sZz17fSx4PWZ1bmN0aW9uKHMpe3ZhciB1PXZbc107aWYodSE9PW0pe209dTt2YXIgbD1yLmZlYXR1cmVJbmRleEFycmF5LmdldCh1KSxwPW51bGw7ci5sb2FkTWF0Y2hpbmdGZWF0dXJlKGcsbC5idWNrZXRJbmRleCxsLnNvdXJjZUxheWVySW5kZXgsbC5mZWF0dXJlSW5kZXgsbyxuLmxheWVycyxlLGZ1bmN0aW9uKGUsbil7cmV0dXJuIHB8fChwPUxuKGUpKSxuLnF1ZXJ5SW50ZXJzZWN0c0ZlYXR1cmUoYSxlLHAsci56LHQudHJhbnNmb3JtLGksdC5wb3NNYXRyaXgpfSk7fX0sYj0wO2I8di5sZW5ndGg7YisrKXgoYik7cmV0dXJuIGd9LGphLnByb3RvdHlwZS5sb2FkTWF0Y2hpbmdGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4saSxvLGEscyl7dmFyIHU9dGhpcy5idWNrZXRMYXllcklEc1tlXTtpZighb3x8ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKylpZihlLmluZGV4T2YodFtyXSk+PTApcmV0dXJuITA7cmV0dXJuITF9KG8sdSkpe3ZhciBsPXRoaXMuc291cmNlTGF5ZXJDb2Rlci5kZWNvZGUocikscD10aGlzLnZ0TGF5ZXJzW2xdLmZlYXR1cmUobik7aWYoaShuZXcgQnIodGhpcy50aWxlSUQub3ZlcnNjYWxlZFopLHApKWZvcih2YXIgYz0wO2M8dS5sZW5ndGg7YysrKXt2YXIgaD11W2NdO2lmKCEobyYmby5pbmRleE9mKGgpPDApKXt2YXIgZj1hW2hdO2lmKGYmJighc3x8cyhwLGYpKSl7dmFyIHk9bmV3IE9hKHAsdGhpcy56LHRoaXMueCx0aGlzLnkpO3kubGF5ZXI9Zi5zZXJpYWxpemUoKTt2YXIgZD10W2hdO3ZvaWQgMD09PWQmJihkPXRbaF09W10pLGQucHVzaCh7ZmVhdHVyZUluZGV4Om4sZmVhdHVyZTp5fSk7fX19fX0samEucHJvdG90eXBlLmxvb2t1cFN5bWJvbEZlYXR1cmVzPWZ1bmN0aW9uKHQsZSxyLG4saSxvKXt2YXIgYT17fTt0aGlzLmxvYWRWVExheWVycygpO2Zvcih2YXIgcz1UZShuKSx1PTAsbD10O3U8bC5sZW5ndGg7dSs9MSl7dmFyIHA9bFt1XTt0aGlzLmxvYWRNYXRjaGluZ0ZlYXR1cmUoYSxlLHIscCxzLGksbyk7fXJldHVybiBhfSxqYS5wcm90b3R5cGUuaGFzTGF5ZXI9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmJ1Y2tldExheWVySURzO2U8ci5sZW5ndGg7ZSs9MSlmb3IodmFyIG49MCxpPXJbZV07bjxpLmxlbmd0aDtuKz0xKXtpZih0PT09aVtuXSlyZXR1cm4hMH1yZXR1cm4hMX0saHIoXCJGZWF0dXJlSW5kZXhcIixqYSx7b21pdDpbXCJyYXdUaWxlRGF0YVwiLFwic291cmNlTGF5ZXJDb2RlclwiXX0pO3ZhciBSYT17aG9yaXpvbnRhbDoxLHZlcnRpY2FsOjIsaG9yaXpvbnRhbE9ubHk6M307dmFyIFVhPXs5OiEwLDEwOiEwLDExOiEwLDEyOiEwLDEzOiEwLDMyOiEwfSxEYT17fTtmdW5jdGlvbiBOYSh0LGUscixuKXt2YXIgaT1NYXRoLnBvdyh0LWUsMik7cmV0dXJuIG4/dDxlP2kvMjoyKmk6aStNYXRoLmFicyhyKSpyfWZ1bmN0aW9uIFphKHQsZSl7dmFyIHI9MDtyZXR1cm4gMTA9PT10JiYoci09MWU0KSw0MCE9PXQmJjY1Mjg4IT09dHx8KHIrPTUwKSw0MSE9PWUmJjY1Mjg5IT09ZXx8KHIrPTUwKSxyfWZ1bmN0aW9uIEthKHQsZSxyLG4saSxvKXtmb3IodmFyIGE9bnVsbCxzPU5hKGUscixpLG8pLHU9MCxsPW47dTxsLmxlbmd0aDt1Kz0xKXt2YXIgcD1sW3VdLGM9TmEoZS1wLngscixpLG8pK3AuYmFkbmVzcztjPD1zJiYoYT1wLHM9Yyk7fXJldHVybntpbmRleDp0LHg6ZSxwcmlvckJyZWFrOmEsYmFkbmVzczpzfX1mdW5jdGlvbiBKYSh0LGUscixuKXtpZighcilyZXR1cm5bXTtpZighdClyZXR1cm5bXTtmb3IodmFyIGksbz1bXSxhPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaT0wLG89MDtvPHQubGVuZ3RoO28rKyl7dmFyIGE9blt0LmNoYXJDb2RlQXQobyldO2EmJihpKz1hLm1ldHJpY3MuYWR2YW5jZStlKTt9cmV0dXJuIGkvTWF0aC5tYXgoMSxNYXRoLmNlaWwoaS9yKSl9KHQsZSxyLG4pLHM9MCx1PTA7dTx0Lmxlbmd0aDt1Kyspe3ZhciBsPXQuY2hhckNvZGVBdCh1KSxwPW5bbF07cCYmIVVhW2xdJiYocys9cC5tZXRyaWNzLmFkdmFuY2UrZSksdTx0Lmxlbmd0aC0xJiYoRGFbbF18fCEoKGk9bCk8MTE5MDQpJiYobXJbXCJCb3BvbW9mbyBFeHRlbmRlZFwiXShpKXx8bXIuQm9wb21vZm8oaSl8fG1yW1wiQ0pLIENvbXBhdGliaWxpdHkgRm9ybXNcIl0oaSl8fG1yW1wiQ0pLIENvbXBhdGliaWxpdHkgSWRlb2dyYXBoc1wiXShpKXx8bXJbXCJDSksgQ29tcGF0aWJpbGl0eVwiXShpKXx8bXJbXCJDSksgUmFkaWNhbHMgU3VwcGxlbWVudFwiXShpKXx8bXJbXCJDSksgU3Ryb2tlc1wiXShpKXx8bXJbXCJDSksgU3ltYm9scyBhbmQgUHVuY3R1YXRpb25cIl0oaSl8fG1yW1wiQ0pLIFVuaWZpZWQgSWRlb2dyYXBocyBFeHRlbnNpb24gQVwiXShpKXx8bXJbXCJDSksgVW5pZmllZCBJZGVvZ3JhcGhzXCJdKGkpfHxtcltcIkVuY2xvc2VkIENKSyBMZXR0ZXJzIGFuZCBNb250aHNcIl0oaSl8fG1yW1wiSGFsZndpZHRoIGFuZCBGdWxsd2lkdGggRm9ybXNcIl0oaSl8fG1yLkhpcmFnYW5hKGkpfHxtcltcIklkZW9ncmFwaGljIERlc2NyaXB0aW9uIENoYXJhY3RlcnNcIl0oaSl8fG1yW1wiS2FuZ3hpIFJhZGljYWxzXCJdKGkpfHxtcltcIkthdGFrYW5hIFBob25ldGljIEV4dGVuc2lvbnNcIl0oaSl8fG1yLkthdGFrYW5hKGkpfHxtcltcIlZlcnRpY2FsIEZvcm1zXCJdKGkpfHxtcltcIllpIFJhZGljYWxzXCJdKGkpfHxtcltcIllpIFN5bGxhYmxlc1wiXShpKSkpJiZvLnB1c2goS2EodSsxLHMsYSxvLFphKGwsdC5jaGFyQ29kZUF0KHUrMSkpLCExKSk7fXJldHVybiBmdW5jdGlvbiB0KGUpe3JldHVybiBlP3QoZS5wcmlvckJyZWFrKS5jb25jYXQoZS5pbmRleCk6W119KEthKHQubGVuZ3RoLHMsYSxvLDAsITApKX1mdW5jdGlvbiAkYSh0KXt2YXIgZT0uNSxyPS41O3N3aXRjaCh0KXtjYXNlXCJyaWdodFwiOmNhc2VcInRvcC1yaWdodFwiOmNhc2VcImJvdHRvbS1yaWdodFwiOmU9MTticmVhaztjYXNlXCJsZWZ0XCI6Y2FzZVwidG9wLWxlZnRcIjpjYXNlXCJib3R0b20tbGVmdFwiOmU9MDt9c3dpdGNoKHQpe2Nhc2VcImJvdHRvbVwiOmNhc2VcImJvdHRvbS1yaWdodFwiOmNhc2VcImJvdHRvbS1sZWZ0XCI6cj0xO2JyZWFrO2Nhc2VcInRvcFwiOmNhc2VcInRvcC1yaWdodFwiOmNhc2VcInRvcC1sZWZ0XCI6cj0wO31yZXR1cm57aG9yaXpvbnRhbEFsaWduOmUsdmVydGljYWxBbGlnbjpyfX1mdW5jdGlvbiBIYSh0LGUscixuLGkpe2lmKGkpe3ZhciBvPWVbdFtuXS5nbHlwaF07aWYobylmb3IodmFyIGE9by5tZXRyaWNzLmFkdmFuY2Uscz0odFtuXS54K2EpKmksdT1yO3U8PW47dSsrKXRbdV0ueC09czt9fURhWzEwXT0hMCxEYVszMl09ITAsRGFbMzhdPSEwLERhWzQwXT0hMCxEYVs0MV09ITAsRGFbNDNdPSEwLERhWzQ1XT0hMCxEYVs0N109ITAsRGFbMTczXT0hMCxEYVsxODNdPSEwLERhWzgyMDNdPSEwLERhWzgyMDhdPSEwLERhWzgyMTFdPSEwLERhWzgyMzFdPSEwLHQuY29tbW9uanNHbG9iYWw9ZSx0LnVud3JhcEV4cG9ydHM9cix0LmNyZWF0ZUNvbW1vbmpzTW9kdWxlPW4sdC5kZWZhdWx0PXNlbGYsdC5kZWZhdWx0JDE9cyx0LmdldEpTT049ZnVuY3Rpb24odCxlKXt2YXIgcj16KHQpO3JldHVybiByLnNldFJlcXVlc3RIZWFkZXIoXCJBY2NlcHRcIixcImFwcGxpY2F0aW9uL2pzb25cIiksci5vbmVycm9yPWZ1bmN0aW9uKCl7ZShuZXcgRXJyb3Ioci5zdGF0dXNUZXh0KSk7fSxyLm9ubG9hZD1mdW5jdGlvbigpe2lmKHIuc3RhdHVzPj0yMDAmJnIuc3RhdHVzPDMwMCYmci5yZXNwb25zZSl7dmFyIG47dHJ5e249SlNPTi5wYXJzZShyLnJlc3BvbnNlKTt9Y2F0Y2godCl7cmV0dXJuIGUodCl9ZShudWxsLG4pO31lbHNlIDQwMT09PXIuc3RhdHVzJiZ0LnVybC5tYXRjaCgvbWFwYm94LmNvbS8pP2UobmV3IGsoci5zdGF0dXNUZXh0K1wiOiB5b3UgbWF5IGhhdmUgcHJvdmlkZWQgYW4gaW52YWxpZCBNYXBib3ggYWNjZXNzIHRva2VuLiBTZWUgaHR0cHM6Ly93d3cubWFwYm94LmNvbS9hcGktZG9jdW1lbnRhdGlvbi8jYWNjZXNzLXRva2Vuc1wiLHIuc3RhdHVzLHQudXJsKSk6ZShuZXcgayhyLnN0YXR1c1RleHQsci5zdGF0dXMsdC51cmwpKTt9LHIuc2VuZCgpLHJ9LHQuZ2V0SW1hZ2U9ZnVuY3Rpb24odCxlKXtyZXR1cm4gUyh0LGZ1bmN0aW9uKHQscil7aWYodCllKHQpO2Vsc2UgaWYocil7dmFyIG49bmV3IHNlbGYuSW1hZ2UsaT1zZWxmLlVSTHx8c2VsZi53ZWJraXRVUkw7bi5vbmxvYWQ9ZnVuY3Rpb24oKXtlKG51bGwsbiksaS5yZXZva2VPYmplY3RVUkwobi5zcmMpO307dmFyIG89bmV3IHNlbGYuQmxvYihbbmV3IFVpbnQ4QXJyYXkoci5kYXRhKV0se3R5cGU6XCJpbWFnZS9wbmdcIn0pO24uY2FjaGVDb250cm9sPXIuY2FjaGVDb250cm9sLG4uZXhwaXJlcz1yLmV4cGlyZXMsbi5zcmM9ci5kYXRhLmJ5dGVMZW5ndGg/aS5jcmVhdGVPYmplY3RVUkwobyk6XCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFFQUFBQUJDQVlBQUFBZkZjU0pBQUFBQzBsRVFWUVlWMk5nQUFJQUFBVUFBYXJWeUZFQUFBQUFTVVZPUks1Q1lJST1cIjt9fSl9LHQuUmVzb3VyY2VUeXBlPUEsdC5SR0JBSW1hZ2U9cGksdC5kZWZhdWx0JDI9UW8sdC5JbWFnZVBvc2l0aW9uPXRhLHQuZ2V0QXJyYXlCdWZmZXI9Uyx0LmRlZmF1bHQkMz1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IG9hKHQpLnJlYWRGaWVsZHMoQWEsW10pfSx0LmRlZmF1bHQkND1tcix0LmFzeW5jQWxsPWZ1bmN0aW9uKHQsZSxyKXtpZighdC5sZW5ndGgpcmV0dXJuIHIobnVsbCxbXSk7dmFyIG49dC5sZW5ndGgsaT1uZXcgQXJyYXkodC5sZW5ndGgpLG89bnVsbDt0LmZvckVhY2goZnVuY3Rpb24odCxhKXtlKHQsZnVuY3Rpb24odCxlKXt0JiYobz10KSxpW2FdPWUsMD09LS1uJiZyKG8saSk7fSk7fSk7fSx0LkFscGhhSW1hZ2U9bGksdC5kZWZhdWx0JDU9RSx0LmVuZHNXaXRoPWQsdC5leHRlbmQ9aCx0LnNwaGVyaWNhbFRvQ2FydGVzaWFuPWZ1bmN0aW9uKHQpe3ZhciBlPXRbMF0scj10WzFdLG49dFsyXTtyZXR1cm4gcis9OTAscio9TWF0aC5QSS8xODAsbio9TWF0aC5QSS8xODAse3g6ZSpNYXRoLmNvcyhyKSpNYXRoLnNpbihuKSx5OmUqTWF0aC5zaW4ocikqTWF0aC5zaW4obiksejplKk1hdGguY29zKG4pfX0sdC5FdmVudGVkPUksdC52YWxpZGF0ZVN0eWxlPXJyLHQudmFsaWRhdGVMaWdodD1ucix0LmVtaXRWYWxpZGF0aW9uRXJyb3JzPWFyLHQuZGVmYXVsdCQ2PVEsdC5udW1iZXI9d3QsdC5Qcm9wZXJ0aWVzPURyLHQuVHJhbnNpdGlvbmFibGU9RXIsdC5UcmFuc2l0aW9uaW5nPVByLHQuUG9zc2libHlFdmFsdWF0ZWQ9THIsdC5EYXRhQ29uc3RhbnRQcm9wZXJ0eT1qcix0Lndhcm5PbmNlPWIsdC51bmlxdWVJZD1mdW5jdGlvbigpe3JldHVybiBmKyt9LHQuZGVmYXVsdCQ3PU1hLHQucGljaz1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj17fSxuPTA7bjxlLmxlbmd0aDtuKyspe3ZhciBpPWVbbl07aSBpbiB0JiYocltpXT10W2ldKTt9cmV0dXJuIHJ9LHQud3JhcD1mdW5jdGlvbih0LGUscil7dmFyIG49ci1lLGk9KCh0LWUpJW4rbiklbitlO3JldHVybiBpPT09ZT9yOml9LHQuY2xhbXA9Yyx0LkV2ZW50PUIsdC5FcnJvckV2ZW50PUMsdC5PdmVyc2NhbGVkVGlsZUlEPUlhLHQuZGVmYXVsdCQ4PVBuLHQuY3JlYXRlTGF5b3V0PSRyLHQuZ2V0Q29vcmRpbmF0ZXNDZW50ZXI9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTEvMCxyPTEvMCxuPS0xLzAsaT0tMS8wLG89MDtvPHQubGVuZ3RoO28rKyllPU1hdGgubWluKGUsdFtvXS5jb2x1bW4pLHI9TWF0aC5taW4ocix0W29dLnJvdyksbj1NYXRoLm1heChuLHRbb10uY29sdW1uKSxpPU1hdGgubWF4KGksdFtvXS5yb3cpO3ZhciBzPW4tZSx1PWktcixsPU1hdGgubWF4KHMsdSkscD1NYXRoLm1heCgwLE1hdGguZmxvb3IoLU1hdGgubG9nKGwpL01hdGguTE4yKSk7cmV0dXJuIG5ldyBhKChlK24pLzIsKHIraSkvMiwwKS56b29tVG8ocCl9LHQuQ2Fub25pY2FsVGlsZUlEPUJhLHQuUmFzdGVyQm91bmRzQXJyYXk9R3IsdC5nZXRWaWRlbz1mdW5jdGlvbih0LGUpe3ZhciByLG4saT1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtpLm9ubG9hZHN0YXJ0PWZ1bmN0aW9uKCl7ZShudWxsLGkpO307Zm9yKHZhciBvPTA7bzx0Lmxlbmd0aDtvKyspe3ZhciBhPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNvdXJjZVwiKTtyPXRbb10sbj12b2lkIDAsKG49c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKSkuaHJlZj1yLChuLnByb3RvY29sIT09c2VsZi5kb2N1bWVudC5sb2NhdGlvbi5wcm90b2NvbHx8bi5ob3N0IT09c2VsZi5kb2N1bWVudC5sb2NhdGlvbi5ob3N0KSYmKGkuY3Jvc3NPcmlnaW49XCJBbm9ueW1vdXNcIiksYS5zcmM9dFtvXSxpLmFwcGVuZENoaWxkKGEpO31yZXR1cm4gaX0sdC5kZWZhdWx0JDk9Rix0LmJpbmRBbGw9eSx0LmRlZmF1bHQkMTA9ZnVuY3Rpb24gdChlLHIpe2lmKEFycmF5LmlzQXJyYXkoZSkpe2lmKCFBcnJheS5pc0FycmF5KHIpfHxlLmxlbmd0aCE9PXIubGVuZ3RoKXJldHVybiExO2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bisrKWlmKCF0KGVbbl0scltuXSkpcmV0dXJuITE7cmV0dXJuITB9aWYoXCJvYmplY3RcIj09dHlwZW9mIGUmJm51bGwhPT1lJiZudWxsIT09cil7aWYoXCJvYmplY3RcIiE9dHlwZW9mIHIpcmV0dXJuITE7aWYoT2JqZWN0LmtleXMoZSkubGVuZ3RoIT09T2JqZWN0LmtleXMocikubGVuZ3RoKXJldHVybiExO2Zvcih2YXIgaSBpbiBlKWlmKCF0KGVbaV0scltpXSkpcmV0dXJuITE7cmV0dXJuITB9cmV0dXJuIGU9PT1yfSx0LnBhcnNlQ2FjaGVDb250cm9sPWZ1bmN0aW9uKHQpe3ZhciBlPXt9O2lmKHQucmVwbGFjZSgvKD86XnwoPzpcXHMqXFwsXFxzKikpKFteXFx4MDAtXFx4MjBcXChcXCk8PkBcXCw7XFw6XFxcXFwiXFwvXFxbXFxdXFw/XFw9XFx7XFx9XFx4N0ZdKykoPzpcXD0oPzooW15cXHgwMC1cXHgyMFxcKFxcKTw+QFxcLDtcXDpcXFxcXCJcXC9cXFtcXF1cXD9cXD1cXHtcXH1cXHg3Rl0rKXwoPzpcXFwiKCg/OlteXCJcXFxcXXxcXFxcLikqKVxcXCIpKSk/L2csZnVuY3Rpb24odCxyLG4saSl7dmFyIG89bnx8aTtyZXR1cm4gZVtyXT0hb3x8by50b0xvd2VyQ2FzZSgpLFwiXCJ9KSxlW1wibWF4LWFnZVwiXSl7dmFyIHI9cGFyc2VJbnQoZVtcIm1heC1hZ2VcIl0sMTApO2lzTmFOKHIpP2RlbGV0ZSBlW1wibWF4LWFnZVwiXTplW1wibWF4LWFnZVwiXT1yO31yZXR1cm4gZX0sdC5kZWZhdWx0JDExPWphLHQuZGVmYXVsdCQxMj1PYSx0LmRlZmF1bHQkMTM9VGUsdC5kZWZhdWx0JDE0PUtvLHQuQ29sbGlzaW9uQm94QXJyYXk9ZG4sdC5kZWZhdWx0JDE1PXpuLHQuVHJpYW5nbGVJbmRleEFycmF5PXBuLHQuZGVmYXVsdCQxNj1Ccix0LmRlZmF1bHQkMTc9YSx0LmtleXNEaWZmZXJlbmNlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9W107Zm9yKHZhciBuIGluIHQpbiBpbiBlfHxyLnB1c2gobik7cmV0dXJuIHJ9LHQuZGVmYXVsdCQxOD1bXCJ0eXBlXCIsXCJzb3VyY2VcIixcInNvdXJjZS1sYXllclwiLFwibWluem9vbVwiLFwibWF4em9vbVwiLFwiZmlsdGVyXCIsXCJsYXlvdXRcIl0sdC5tYXQ0PXJpLHQudmVjND1laSx0LmdldFNpemVEYXRhPWpvLHQuZXZhbHVhdGVTaXplRm9yRmVhdHVyZT1mdW5jdGlvbih0LGUscil7dmFyIG49ZTtyZXR1cm5cInNvdXJjZVwiPT09dC5mdW5jdGlvblR5cGU/ci5sb3dlclNpemUvMTA6XCJjb21wb3NpdGVcIj09PXQuZnVuY3Rpb25UeXBlP3d0KHIubG93ZXJTaXplLzEwLHIudXBwZXJTaXplLzEwLG4udVNpemVUKTpuLnVTaXplfSx0LmV2YWx1YXRlU2l6ZUZvclpvb209ZnVuY3Rpb24odCxlLHIpe2lmKFwiY29uc3RhbnRcIj09PXQuZnVuY3Rpb25UeXBlKXJldHVybnt1U2l6ZVQ6MCx1U2l6ZTp0LmxheW91dFNpemV9O2lmKFwic291cmNlXCI9PT10LmZ1bmN0aW9uVHlwZSlyZXR1cm57dVNpemVUOjAsdVNpemU6MH07aWYoXCJjYW1lcmFcIj09PXQuZnVuY3Rpb25UeXBlKXt2YXIgbj10LnByb3BlcnR5VmFsdWUsaT10Lnpvb21SYW5nZSxvPXQuc2l6ZVJhbmdlLGE9YyhTZShuLHIuc3BlY2lmaWNhdGlvbikuaW50ZXJwb2xhdGlvbkZhY3RvcihlLGkubWluLGkubWF4KSwwLDEpO3JldHVybnt1U2l6ZVQ6MCx1U2l6ZTpvLm1pbithKihvLm1heC1vLm1pbil9fXZhciBzPXQucHJvcGVydHlWYWx1ZSx1PXQuem9vbVJhbmdlO3JldHVybnt1U2l6ZVQ6YyhTZShzLHIuc3BlY2lmaWNhdGlvbikuaW50ZXJwb2xhdGlvbkZhY3RvcihlLHUubWluLHUubWF4KSwwLDEpLHVTaXplOjB9fSx0LmFkZER5bmFtaWNBdHRyaWJ1dGVzPURvLHQuZGVmYXVsdCQxOT0kbyx0LldyaXRpbmdNb2RlPVJhLHQubXVsdGlQb2x5Z29uSW50ZXJzZWN0c0J1ZmZlcmVkUG9pbnQ9Um4sdC5tdWx0aVBvbHlnb25JbnRlcnNlY3RzTXVsdGlQb2x5Z29uPVVuLHQubXVsdGlQb2x5Z29uSW50ZXJzZWN0c0J1ZmZlcmVkTXVsdGlMaW5lPURuLHQucG9seWdvbkludGVyc2VjdHNQb2x5Z29uPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspaWYoWG4oZSx0W3JdKSlyZXR1cm4hMDtmb3IodmFyIG49MDtuPGUubGVuZ3RoO24rKylpZihYbih0LGVbbl0pKXJldHVybiEwO3JldHVybiEhWm4odCxlKX0sdC5kaXN0VG9TZWdtZW50U3F1YXJlZD0kbix0LmRlZmF1bHQkMjA9dGksdC5kZWZhdWx0JDIxPU5yLHQuZGVmYXVsdCQyMj1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IFdvW3QudHlwZV0odCl9LHQuY2xvbmU9Zyx0LmZpbHRlck9iamVjdD1tLHQubWFwT2JqZWN0PXYsdC5yZWdpc3RlckZvclBsdWdpbkF2YWlsYWJpbGl0eT1mdW5jdGlvbih0KXtyZXR1cm4genI/dCh7cGx1Z2luVVJMOnpyLGNvbXBsZXRpb25DYWxsYmFjazpBcn0pOk1yLm9uY2UoXCJwbHVnaW5BdmFpbGFibGVcIix0KSx0fSx0LmV2ZW50ZWQ9TXIsdC5kZWZhdWx0JDIzPXZyLHQuZGVmYXVsdCQyND1Jbix0LlBvc0FycmF5PVhyLHQuVW53cmFwcGVkVGlsZUlEPUNhLHQuZWFzZT1wLHQuYmV6aWVyPWwsdC5zZXRSVExUZXh0UGx1Z2luPWZ1bmN0aW9uKHQsZSl7aWYoa3IpdGhyb3cgbmV3IEVycm9yKFwic2V0UlRMVGV4dFBsdWdpbiBjYW5ub3QgYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzLlwiKTtrcj0hMCx6cj10LEFyPWZ1bmN0aW9uKHQpe3Q/KGtyPSExLHpyPW51bGwsZSYmZSh0KSk6U3I9ITA7fSxNci5maXJlKG5ldyBCKFwicGx1Z2luQXZhaWxhYmxlXCIse3BsdWdpblVSTDp6cixjb21wbGV0aW9uQ2FsbGJhY2s6QXJ9KSk7fSx0LnZhbHVlcz1mdW5jdGlvbih0KXt2YXIgZT1bXTtmb3IodmFyIHIgaW4gdCllLnB1c2godFtyXSk7cmV0dXJuIGV9LHQuZGVmYXVsdCQyNT1Mbyx0LnJlZ2lzdGVyPWhyLHQuR0xZUEhfUEJGX0JPUkRFUj1TYSx0LnNoYXBlVGV4dD1mdW5jdGlvbih0LGUscixuLGksbyxhLHMsdSxsKXt2YXIgcD10LnRyaW0oKTtsPT09UmEudmVydGljYWwmJihwPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1cIlwiLHI9MDtyPHQubGVuZ3RoO3IrKyl7dmFyIG49dC5jaGFyQ29kZUF0KHIrMSl8fG51bGwsaT10LmNoYXJDb2RlQXQoci0xKXx8bnVsbDtuJiZ3cihuKSYmIU9vW3RbcisxXV18fGkmJndyKGkpJiYhT29bdFtyLTFdXXx8IU9vW3Rbcl1dP2UrPXRbcl06ZSs9T29bdFtyXV07fXJldHVybiBlfShwKSk7dmFyIGM9W10saD17cG9zaXRpb25lZEdseXBoczpjLHRleHQ6cCx0b3A6c1sxXSxib3R0b206c1sxXSxsZWZ0OnNbMF0scmlnaHQ6c1swXSx3cml0aW5nTW9kZTpsfSxmPVZyLnByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dDtyZXR1cm4gZnVuY3Rpb24odCxlLHIsbixpLG8sYSxzLHUpe2Zvcih2YXIgbD0wLHA9LTE3LGM9MCxoPXQucG9zaXRpb25lZEdseXBocyxmPVwicmlnaHRcIj09PW8/MTpcImxlZnRcIj09PW8/MDouNSx5PTAsZD1yO3k8ZC5sZW5ndGg7eSs9MSl7dmFyIHY9ZFt5XTtpZigodj12LnRyaW0oKSkubGVuZ3RoKXtmb3IodmFyIG09aC5sZW5ndGgsZz0wO2c8di5sZW5ndGg7ZysrKXt2YXIgeD12LmNoYXJDb2RlQXQoZyksYj1lW3hdO2ImJihicih4KSYmYSE9PVJhLmhvcml6b250YWw/KGgucHVzaCh7Z2x5cGg6eCx4OmwseTowLHZlcnRpY2FsOiEwfSksbCs9dStzKTooaC5wdXNoKHtnbHlwaDp4LHg6bCx5OnAsdmVydGljYWw6ITF9KSxsKz1iLm1ldHJpY3MuYWR2YW5jZStzKSk7fWlmKGgubGVuZ3RoIT09bSl7dmFyIHc9bC1zO2M9TWF0aC5tYXgodyxjKSxIYShoLGUsbSxoLmxlbmd0aC0xLGYpO31sPTAscCs9bjt9ZWxzZSBwKz1uO312YXIgXz0kYShpKSxBPV8uaG9yaXpvbnRhbEFsaWduLGs9Xy52ZXJ0aWNhbEFsaWduOyFmdW5jdGlvbih0LGUscixuLGksbyxhKXtmb3IodmFyIHM9KGUtcikqaSx1PSgtbiphKy41KSpvLGw9MDtsPHQubGVuZ3RoO2wrKyl0W2xdLngrPXMsdFtsXS55Kz11O30oaCxmLEEsayxjLG4sci5sZW5ndGgpO3ZhciB6PXIubGVuZ3RoKm47dC50b3ArPS1rKnosdC5ib3R0b209dC50b3Areix0LmxlZnQrPS1BKmMsdC5yaWdodD10LmxlZnQrYzt9KGgsZSxmP2YocCxKYShwLGEscixlKSk6ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9W10sbj0wLGk9MCxvPWU7aTxvLmxlbmd0aDtpKz0xKXt2YXIgYT1vW2ldO3IucHVzaCh0LnN1YnN0cmluZyhuLGEpKSxuPWE7fXJldHVybiBuPHQubGVuZ3RoJiZyLnB1c2godC5zdWJzdHJpbmcobix0Lmxlbmd0aCkpLHJ9KHAsSmEocCxhLHIsZSkpLG4saSxvLGwsYSx1KSwhIWMubGVuZ3RoJiZofSx0LnNoYXBlSWNvbj1mdW5jdGlvbih0LGUscil7dmFyIG49JGEociksaT1uLmhvcml6b250YWxBbGlnbixvPW4udmVydGljYWxBbGlnbixhPWVbMF0scz1lWzFdLHU9YS10LmRpc3BsYXlTaXplWzBdKmksbD11K3QuZGlzcGxheVNpemVbMF0scD1zLXQuZGlzcGxheVNpemVbMV0qbztyZXR1cm57aW1hZ2U6dCx0b3A6cCxib3R0b206cCt0LmRpc3BsYXlTaXplWzFdLGxlZnQ6dSxyaWdodDpsfX0sdC5hbGxvd3NWZXJ0aWNhbFdyaXRpbmdNb2RlPWdyLHQuYWxsb3dzTGV0dGVyU3BhY2luZz1mdW5jdGlvbih0KXtmb3IodmFyIGU9MCxyPXQ7ZTxyLmxlbmd0aDtlKz0xKWlmKCF4cihyW2VdLmNoYXJDb2RlQXQoMCkpKXJldHVybiExO3JldHVybiEwfSx0LmRlZmF1bHQkMjY9JGksdC5kZWZhdWx0JDI3PVRhLHQuZGVmYXVsdCQyOD1yYSx0LmRlZmF1bHQkMjk9dm8sdC5kZWZhdWx0JDMwPW9hLHQuZGVmYXVsdCQzMT1QYSx0Ll9fbW9kdWxlRXhwb3J0cz12byx0LmRlZmF1bHQkMzI9cyx0Ll9fbW9kdWxlRXhwb3J0cyQxPW9hLHQucGx1Z2luPVZyO30pO1xuXG5kZWZpbmUoW1wiLi9jaHVuazEuanNcIl0sZnVuY3Rpb24oZSl7XCJ1c2Ugc3RyaWN0XCI7ZnVuY3Rpb24gdChlKXt2YXIgaT10eXBlb2YgZTtpZihcIm51bWJlclwiPT09aXx8XCJib29sZWFuXCI9PT1pfHxcInN0cmluZ1wiPT09aXx8bnVsbD09ZSlyZXR1cm4gSlNPTi5zdHJpbmdpZnkoZSk7aWYoQXJyYXkuaXNBcnJheShlKSl7Zm9yKHZhciByPVwiW1wiLG49MCxvPWU7bjxvLmxlbmd0aDtuKz0xKXtyKz10KG9bbl0pK1wiLFwiO31yZXR1cm4gcitcIl1cIn1mb3IodmFyIGE9T2JqZWN0LmtleXMoZSkuc29ydCgpLHM9XCJ7XCIsbD0wO2w8YS5sZW5ndGg7bCsrKXMrPUpTT04uc3RyaW5naWZ5KGFbbF0pK1wiOlwiK3QoZVthW2xdXSkrXCIsXCI7cmV0dXJuIHMrXCJ9XCJ9ZnVuY3Rpb24gaShpKXtmb3IodmFyIHI9XCJcIixuPTAsbz1lLmRlZmF1bHQkMTg7bjxvLmxlbmd0aDtuKz0xKXtyKz1cIi9cIit0KGlbb1tuXV0pO31yZXR1cm4gcn12YXIgcj1mdW5jdGlvbihlKXtlJiZ0aGlzLnJlcGxhY2UoZSk7fTtmdW5jdGlvbiBuKGUsdCxpLHIsbil7aWYodm9pZCAwPT09dC5zZWdtZW50KXJldHVybiEwO2Zvcih2YXIgbz10LGE9dC5zZWdtZW50KzEscz0wO3M+LWkvMjspe2lmKC0tYTwwKXJldHVybiExO3MtPWVbYV0uZGlzdChvKSxvPWVbYV07fXMrPWVbYV0uZGlzdChlW2ErMV0pLGErKztmb3IodmFyIGw9W10sdT0wO3M8aS8yOyl7dmFyIGg9ZVthLTFdLGM9ZVthXSxmPWVbYSsxXTtpZighZilyZXR1cm4hMTt2YXIgcD1oLmFuZ2xlVG8oYyktYy5hbmdsZVRvKGYpO2ZvcihwPU1hdGguYWJzKChwKzMqTWF0aC5QSSklKDIqTWF0aC5QSSktTWF0aC5QSSksbC5wdXNoKHtkaXN0YW5jZTpzLGFuZ2xlRGVsdGE6cH0pLHUrPXA7cy1sWzBdLmRpc3RhbmNlPnI7KXUtPWwuc2hpZnQoKS5hbmdsZURlbHRhO2lmKHU+bilyZXR1cm4hMTthKysscys9Yy5kaXN0KGYpO31yZXR1cm4hMH1mdW5jdGlvbiBvKHQsaSxyLG8sYSxzLGwsdSxoKXt2YXIgYz1vPy42KnMqbDowLGY9TWF0aC5tYXgobz9vLnJpZ2h0LW8ubGVmdDowLGE/YS5yaWdodC1hLmxlZnQ6MCkscD0wPT09dFswXS54fHx0WzBdLng9PT1ofHwwPT09dFswXS55fHx0WzBdLnk9PT1oO3JldHVybiBpLWYqbDxpLzQmJihpPWYqbCtpLzQpLGZ1bmN0aW9uIHQoaSxyLG8sYSxzLGwsdSxoLGMpe3ZhciBmPWwvMjt2YXIgcD0wO2Zvcih2YXIgZD0wO2Q8aS5sZW5ndGgtMTtkKyspcCs9aVtkXS5kaXN0KGlbZCsxXSk7dmFyIGc9MCx2PXItbzt2YXIgeT1bXTtmb3IodmFyIG09MDttPGkubGVuZ3RoLTE7bSsrKXtmb3IodmFyIHg9aVttXSx3PWlbbSsxXSxTPXguZGlzdCh3KSxNPXcuYW5nbGVUbyh4KTt2K288ZytTOyl7dmFyIGI9KCh2Kz1vKS1nKS9TLF89ZS5udW1iZXIoeC54LHcueCxiKSxJPWUubnVtYmVyKHgueSx3LnksYik7aWYoXz49MCYmXzxjJiZJPj0wJiZJPGMmJnYtZj49MCYmditmPD1wKXt2YXIgej1uZXcgZS5kZWZhdWx0JDI1KF8sSSxNLG0pO3ouX3JvdW5kKCksYSYmIW4oaSx6LGwsYSxzKXx8eS5wdXNoKHopO319Zys9Uzt9aHx8eS5sZW5ndGh8fHV8fCh5PXQoaSxnLzIsbyxhLHMsbCx1LCEwLGMpKTtyZXR1cm4geX0odCxwP2kvMip1JWk6KGYvMisyKnMpKmwqdSVpLGksYyxyLGYqbCxwLCExLGgpfXIucHJvdG90eXBlLnJlcGxhY2U9ZnVuY3Rpb24oZSl7dGhpcy5fbGF5ZXJDb25maWdzPXt9LHRoaXMuX2xheWVycz17fSx0aGlzLnVwZGF0ZShlLFtdKTt9LHIucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0LHIpe2Zvcih2YXIgbj10aGlzLG89MCxhPXQ7bzxhLmxlbmd0aDtvKz0xKXt2YXIgcz1hW29dO24uX2xheWVyQ29uZmlnc1tzLmlkXT1zO3ZhciBsPW4uX2xheWVyc1tzLmlkXT1lLmRlZmF1bHQkMjIocyk7bC5fZmVhdHVyZUZpbHRlcj1lLmRlZmF1bHQkMTMobC5maWx0ZXIpO31mb3IodmFyIHU9MCxoPXI7dTxoLmxlbmd0aDt1Kz0xKXt2YXIgYz1oW3VdO2RlbGV0ZSBuLl9sYXllckNvbmZpZ3NbY10sZGVsZXRlIG4uX2xheWVyc1tjXTt9dGhpcy5mYW1pbGllc0J5U291cmNlPXt9O2Zvcih2YXIgZj0wLHA9ZnVuY3Rpb24oZSl7Zm9yKHZhciB0PXt9LHI9MDtyPGUubGVuZ3RoO3IrKyl7dmFyIG49aShlW3JdKSxvPXRbbl07b3x8KG89dFtuXT1bXSksby5wdXNoKGVbcl0pO312YXIgYT1bXTtmb3IodmFyIHMgaW4gdClhLnB1c2godFtzXSk7cmV0dXJuIGF9KGUudmFsdWVzKHRoaXMuX2xheWVyQ29uZmlncykpO2Y8cC5sZW5ndGg7Zis9MSl7dmFyIGQ9cFtmXS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIG4uX2xheWVyc1tlLmlkXX0pLGc9ZFswXTtpZihcIm5vbmVcIiE9PWcudmlzaWJpbGl0eSl7dmFyIHY9Zy5zb3VyY2V8fFwiXCIseT1uLmZhbWlsaWVzQnlTb3VyY2Vbdl07eXx8KHk9bi5mYW1pbGllc0J5U291cmNlW3ZdPXt9KTt2YXIgbT1nLnNvdXJjZUxheWVyfHxcIl9nZW9qc29uVGlsZUxheWVyXCIseD15W21dO3h8fCh4PXlbbV09W10pLHgucHVzaChkKTt9fX07dmFyIGE9ZnVuY3Rpb24oKXt0aGlzLm9wYWNpdHk9MCx0aGlzLnRhcmdldE9wYWNpdHk9MCx0aGlzLnRpbWU9MDt9O2EucHJvdG90eXBlLmNsb25lPWZ1bmN0aW9uKCl7dmFyIGU9bmV3IGE7cmV0dXJuIGUub3BhY2l0eT10aGlzLm9wYWNpdHksZS50YXJnZXRPcGFjaXR5PXRoaXMudGFyZ2V0T3BhY2l0eSxlLnRpbWU9dGhpcy50aW1lLGV9LGUucmVnaXN0ZXIoXCJPcGFjaXR5U3RhdGVcIixhKTt2YXIgcz1mdW5jdGlvbihlLHQsaSxyLG4sbyxhLHMsbCx1LGgpe3ZhciBjPWEudG9wKnMtbCxmPWEuYm90dG9tKnMrbCxwPWEubGVmdCpzLWwsZD1hLnJpZ2h0KnMrbDtpZih0aGlzLmJveFN0YXJ0SW5kZXg9ZS5sZW5ndGgsdSl7dmFyIGc9Zi1jLHY9ZC1wO2c+MCYmKGc9TWF0aC5tYXgoMTAqcyxnKSx0aGlzLl9hZGRMaW5lQ29sbGlzaW9uQ2lyY2xlcyhlLHQsaSxpLnNlZ21lbnQsdixnLHIsbixvLGgpKTt9ZWxzZSBlLmVtcGxhY2VCYWNrKGkueCxpLnkscCxjLGQsZixyLG4sbywwLDApO3RoaXMuYm94RW5kSW5kZXg9ZS5sZW5ndGg7fTtzLnByb3RvdHlwZS5fYWRkTGluZUNvbGxpc2lvbkNpcmNsZXM9ZnVuY3Rpb24oZSx0LGkscixuLG8sYSxzLGwsdSl7dmFyIGg9by8yLGM9TWF0aC5mbG9vcihuL2gpLGY9MSsuNCpNYXRoLmxvZyh1KS9NYXRoLkxOMixwPU1hdGguZmxvb3IoYypmLzIpLGQ9LW8vMixnPWksdj1yKzEseT1kLG09LW4vMix4PW0tbi80O2Rve2lmKC0tdjwwKXtpZih5Pm0pcmV0dXJuO3Y9MDticmVha315LT10W3ZdLmRpc3QoZyksZz10W3ZdO313aGlsZSh5PngpO2Zvcih2YXIgdz10W3ZdLmRpc3QodFt2KzFdKSxTPS1wO1M8YytwO1MrKyl7dmFyIE09UypoLGI9bStNO2lmKE08MCYmKGIrPU0pLE0+biYmKGIrPU0tbiksIShiPHkpKXtmb3IoO3krdzxiOyl7aWYoeSs9dywrK3YrMT49dC5sZW5ndGgpcmV0dXJuO3c9dFt2XS5kaXN0KHRbdisxXSk7fXZhciBfPWIteSxJPXRbdl0sej10W3YrMV0uc3ViKEkpLl91bml0KCkuX211bHQoXykuX2FkZChJKS5fcm91bmQoKSxUPU1hdGguYWJzKGItZCk8aD8wOi44KihiLWQpO2UuZW1wbGFjZUJhY2soei54LHoueSwtby8yLC1vLzIsby8yLG8vMixhLHMsbCxvLzIsVCk7fX19O3ZhciBsPWgsdT1oO2Z1bmN0aW9uIGgoZSx0KXtpZighKHRoaXMgaW5zdGFuY2VvZiBoKSlyZXR1cm4gbmV3IGgoZSx0KTtpZih0aGlzLmRhdGE9ZXx8W10sdGhpcy5sZW5ndGg9dGhpcy5kYXRhLmxlbmd0aCx0aGlzLmNvbXBhcmU9dHx8Yyx0aGlzLmxlbmd0aD4wKWZvcih2YXIgaT0odGhpcy5sZW5ndGg+PjEpLTE7aT49MDtpLS0pdGhpcy5fZG93bihpKTt9ZnVuY3Rpb24gYyhlLHQpe3JldHVybiBlPHQ/LTE6ZT50PzE6MH1mdW5jdGlvbiBmKHQsaSxyKXt2b2lkIDA9PT1pJiYoaT0xKSx2b2lkIDA9PT1yJiYocj0hMSk7Zm9yKHZhciBuPTEvMCxvPTEvMCxhPS0xLzAscz0tMS8wLHU9dFswXSxoPTA7aDx1Lmxlbmd0aDtoKyspe3ZhciBjPXVbaF07KCFofHxjLng8bikmJihuPWMueCksKCFofHxjLnk8bykmJihvPWMueSksKCFofHxjLng+YSkmJihhPWMueCksKCFofHxjLnk+cykmJihzPWMueSk7fXZhciBmPWEtbixnPXMtbyx2PU1hdGgubWluKGYsZykseT12LzIsbT1uZXcgbChudWxsLHApO2lmKDA9PT12KXJldHVybiBuZXcgZS5kZWZhdWx0JDEobixvKTtmb3IodmFyIHg9bjt4PGE7eCs9dilmb3IodmFyIHc9bzt3PHM7dys9diltLnB1c2gobmV3IGQoeCt5LHcreSx5LHQpKTtmb3IodmFyIFM9ZnVuY3Rpb24oZSl7Zm9yKHZhciB0PTAsaT0wLHI9MCxuPWVbMF0sbz0wLGE9bi5sZW5ndGgscz1hLTE7bzxhO3M9bysrKXt2YXIgbD1uW29dLHU9bltzXSxoPWwueCp1LnktdS54KmwueTtpKz0obC54K3UueCkqaCxyKz0obC55K3UueSkqaCx0Kz0zKmg7fXJldHVybiBuZXcgZChpL3Qsci90LDAsZSl9KHQpLE09bS5sZW5ndGg7bS5sZW5ndGg7KXt2YXIgYj1tLnBvcCgpOyhiLmQ+Uy5kfHwhUy5kKSYmKFM9YixyJiZjb25zb2xlLmxvZyhcImZvdW5kIGJlc3QgJWQgYWZ0ZXIgJWQgcHJvYmVzXCIsTWF0aC5yb3VuZCgxZTQqYi5kKS8xZTQsTSkpLGIubWF4LVMuZDw9aXx8KHk9Yi5oLzIsbS5wdXNoKG5ldyBkKGIucC54LXksYi5wLnkteSx5LHQpKSxtLnB1c2gobmV3IGQoYi5wLngreSxiLnAueS15LHksdCkpLG0ucHVzaChuZXcgZChiLnAueC15LGIucC55K3kseSx0KSksbS5wdXNoKG5ldyBkKGIucC54K3ksYi5wLnkreSx5LHQpKSxNKz00KTt9cmV0dXJuIHImJihjb25zb2xlLmxvZyhcIm51bSBwcm9iZXM6IFwiK00pLGNvbnNvbGUubG9nKFwiYmVzdCBkaXN0YW5jZTogXCIrUy5kKSksUy5wfWZ1bmN0aW9uIHAoZSx0KXtyZXR1cm4gdC5tYXgtZS5tYXh9ZnVuY3Rpb24gZCh0LGkscixuKXt0aGlzLnA9bmV3IGUuZGVmYXVsdCQxKHQsaSksdGhpcy5oPXIsdGhpcy5kPWZ1bmN0aW9uKHQsaSl7Zm9yKHZhciByPSExLG49MS8wLG89MDtvPGkubGVuZ3RoO28rKylmb3IodmFyIGE9aVtvXSxzPTAsbD1hLmxlbmd0aCx1PWwtMTtzPGw7dT1zKyspe3ZhciBoPWFbc10sYz1hW3VdO2gueT50LnkhPWMueT50LnkmJnQueDwoYy54LWgueCkqKHQueS1oLnkpLyhjLnktaC55KStoLngmJihyPSFyKSxuPU1hdGgubWluKG4sZS5kaXN0VG9TZWdtZW50U3F1YXJlZCh0LGgsYykpO31yZXR1cm4ocj8xOi0xKSpNYXRoLnNxcnQobil9KHRoaXMucCxuKSx0aGlzLm1heD10aGlzLmQrdGhpcy5oKk1hdGguU1FSVDI7fWZ1bmN0aW9uIGcodCxpLHIsbixvLGEpe3QuY3JlYXRlQXJyYXlzKCksdC5zeW1ib2xJbnN0YW5jZXM9W107dmFyIHM9NTEyKnQub3ZlcnNjYWxpbmc7dC50aWxlUGl4ZWxSYXRpbz1lLmRlZmF1bHQkOC9zLHQuY29tcGFyZVRleHQ9e30sdC5pY29uc05lZWRMaW5lYXI9ITE7dmFyIGw9dC5sYXllcnNbMF0ubGF5b3V0LHU9dC5sYXllcnNbMF0uX3VuZXZhbHVhdGVkTGF5b3V0Ll92YWx1ZXMsaD17fTtpZihcImNvbXBvc2l0ZVwiPT09dC50ZXh0U2l6ZURhdGEuZnVuY3Rpb25UeXBlKXt2YXIgYz10LnRleHRTaXplRGF0YS56b29tUmFuZ2UsZj1jLm1pbixwPWMubWF4O2guY29tcG9zaXRlVGV4dFNpemVzPVt1W1widGV4dC1zaXplXCJdLnBvc3NpYmx5RXZhbHVhdGUobmV3IGUuZGVmYXVsdCQxNihmKSksdVtcInRleHQtc2l6ZVwiXS5wb3NzaWJseUV2YWx1YXRlKG5ldyBlLmRlZmF1bHQkMTYocCkpXTt9aWYoXCJjb21wb3NpdGVcIj09PXQuaWNvblNpemVEYXRhLmZ1bmN0aW9uVHlwZSl7dmFyIGQ9dC5pY29uU2l6ZURhdGEuem9vbVJhbmdlLGc9ZC5taW4seT1kLm1heDtoLmNvbXBvc2l0ZUljb25TaXplcz1bdVtcImljb24tc2l6ZVwiXS5wb3NzaWJseUV2YWx1YXRlKG5ldyBlLmRlZmF1bHQkMTYoZykpLHVbXCJpY29uLXNpemVcIl0ucG9zc2libHlFdmFsdWF0ZShuZXcgZS5kZWZhdWx0JDE2KHkpKV07fWgubGF5b3V0VGV4dFNpemU9dVtcInRleHQtc2l6ZVwiXS5wb3NzaWJseUV2YWx1YXRlKG5ldyBlLmRlZmF1bHQkMTYodC56b29tKzEpKSxoLmxheW91dEljb25TaXplPXVbXCJpY29uLXNpemVcIl0ucG9zc2libHlFdmFsdWF0ZShuZXcgZS5kZWZhdWx0JDE2KHQuem9vbSsxKSksaC50ZXh0TWF4U2l6ZT11W1widGV4dC1zaXplXCJdLnBvc3NpYmx5RXZhbHVhdGUobmV3IGUuZGVmYXVsdCQxNigxOCkpO2Zvcih2YXIgbT0yNCpsLmdldChcInRleHQtbGluZS1oZWlnaHRcIikseD1cIm1hcFwiPT09bC5nZXQoXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiKSYmXCJsaW5lXCI9PT1sLmdldChcInN5bWJvbC1wbGFjZW1lbnRcIiksdz1sLmdldChcInRleHQta2VlcC11cHJpZ2h0XCIpLFM9MCxNPXQuZmVhdHVyZXM7UzxNLmxlbmd0aDtTKz0xKXt2YXIgYj1NW1NdLF89bC5nZXQoXCJ0ZXh0LWZvbnRcIikuZXZhbHVhdGUoYikuam9pbihcIixcIiksST1pW19dfHx7fSx6PXJbX118fHt9LFQ9e30sUD1iLnRleHQ7aWYoUCl7dmFyIGs9bC5nZXQoXCJ0ZXh0LW9mZnNldFwiKS5ldmFsdWF0ZShiKS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIDI0KmV9KSxMPTI0KmwuZ2V0KFwidGV4dC1sZXR0ZXItc3BhY2luZ1wiKS5ldmFsdWF0ZShiKSwkPWUuYWxsb3dzTGV0dGVyU3BhY2luZyhQKT9MOjAsRD1sLmdldChcInRleHQtYW5jaG9yXCIpLmV2YWx1YXRlKGIpLE89bC5nZXQoXCJ0ZXh0LWp1c3RpZnlcIikuZXZhbHVhdGUoYiksQz1cImxpbmVcIiE9PWwuZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKT8yNCpsLmdldChcInRleHQtbWF4LXdpZHRoXCIpLmV2YWx1YXRlKGIpOjA7VC5ob3Jpem9udGFsPWUuc2hhcGVUZXh0KFAsSSxDLG0sRCxPLCQsaywyNCxlLldyaXRpbmdNb2RlLmhvcml6b250YWwpLGUuYWxsb3dzVmVydGljYWxXcml0aW5nTW9kZShQKSYmeCYmdyYmKFQudmVydGljYWw9ZS5zaGFwZVRleHQoUCxJLEMsbSxELE8sJCxrLDI0LGUuV3JpdGluZ01vZGUudmVydGljYWwpKTt9dmFyIEE9dm9pZCAwO2lmKGIuaWNvbil7dmFyIEU9bltiLmljb25dO0UmJihBPWUuc2hhcGVJY29uKG9bYi5pY29uXSxsLmdldChcImljb24tb2Zmc2V0XCIpLmV2YWx1YXRlKGIpLGwuZ2V0KFwiaWNvbi1hbmNob3JcIikuZXZhbHVhdGUoYikpLHZvaWQgMD09PXQuc2RmSWNvbnM/dC5zZGZJY29ucz1FLnNkZjp0LnNkZkljb25zIT09RS5zZGYmJmUud2Fybk9uY2UoXCJTdHlsZSBzaGVldCB3YXJuaW5nOiBDYW5ub3QgbWl4IFNERiBhbmQgbm9uLVNERiBpY29ucyBpbiBvbmUgYnVmZmVyXCIpLEUucGl4ZWxSYXRpbyE9PXQucGl4ZWxSYXRpbz90Lmljb25zTmVlZExpbmVhcj0hMDowIT09bC5nZXQoXCJpY29uLXJvdGF0ZVwiKS5jb25zdGFudE9yKDEpJiYodC5pY29uc05lZWRMaW5lYXI9ITApKTt9KFQuaG9yaXpvbnRhbHx8QSkmJnYodCxiLFQsQSx6LGgpO31hJiZ0LmdlbmVyYXRlQ29sbGlzaW9uRGVidWdCdWZmZXJzKCk7fWZ1bmN0aW9uIHYodCxpLHIsbixsLHUpe3ZhciBoPXUubGF5b3V0VGV4dFNpemUuZXZhbHVhdGUoaSksYz11LmxheW91dEljb25TaXplLmV2YWx1YXRlKGkpLHA9dS50ZXh0TWF4U2l6ZS5ldmFsdWF0ZShpKTt2b2lkIDA9PT1wJiYocD1oKTt2YXIgZD10LmxheWVyc1swXS5sYXlvdXQsZz1kLmdldChcInRleHQtb2Zmc2V0XCIpLmV2YWx1YXRlKGkpLHY9ZC5nZXQoXCJpY29uLW9mZnNldFwiKS5ldmFsdWF0ZShpKSx4PWgvMjQsdz10LnRpbGVQaXhlbFJhdGlvKngsUz10LnRpbGVQaXhlbFJhdGlvKnAvMjQsTT10LnRpbGVQaXhlbFJhdGlvKmMsYj10LnRpbGVQaXhlbFJhdGlvKmQuZ2V0KFwic3ltYm9sLXNwYWNpbmdcIiksXz1kLmdldChcInRleHQtcGFkZGluZ1wiKSp0LnRpbGVQaXhlbFJhdGlvLEk9ZC5nZXQoXCJpY29uLXBhZGRpbmdcIikqdC50aWxlUGl4ZWxSYXRpbyx6PWQuZ2V0KFwidGV4dC1tYXgtYW5nbGVcIikvMTgwKk1hdGguUEksVD1cIm1hcFwiPT09ZC5nZXQoXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiKSYmXCJsaW5lXCI9PT1kLmdldChcInN5bWJvbC1wbGFjZW1lbnRcIiksUD1cIm1hcFwiPT09ZC5nZXQoXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiKSYmXCJsaW5lXCI9PT1kLmdldChcInN5bWJvbC1wbGFjZW1lbnRcIiksaz1iLzIsTD1mdW5jdGlvbihvLGgpe2gueDwwfHxoLng+PWUuZGVmYXVsdCQ4fHxoLnk8MHx8aC55Pj1lLmRlZmF1bHQkOHx8dC5zeW1ib2xJbnN0YW5jZXMucHVzaChmdW5jdGlvbih0LGkscixuLG8sbCx1LGgsYyxmLHAsZCxnLHYsbSx4LHcsUyxNLGIsXyl7dmFyIEkseixUPXQuYWRkVG9MaW5lVmVydGV4QXJyYXkoaSxyKSxQPTAsaz0wLEw9MCwkPW4uaG9yaXpvbnRhbD9uLmhvcml6b250YWwudGV4dDpcIlwiLEQ9W107bi5ob3Jpem9udGFsJiYoST1uZXcgcyh1LHIsaSxoLGMsZixuLmhvcml6b250YWwscCxkLGcsdC5vdmVyc2NhbGluZyksays9eSh0LGksbi5ob3Jpem9udGFsLGwsZyxNLHYsVCxuLnZlcnRpY2FsP2UuV3JpdGluZ01vZGUuaG9yaXpvbnRhbDplLldyaXRpbmdNb2RlLmhvcml6b250YWxPbmx5LEQsYixfKSxuLnZlcnRpY2FsJiYoTCs9eSh0LGksbi52ZXJ0aWNhbCxsLGcsTSx2LFQsZS5Xcml0aW5nTW9kZS52ZXJ0aWNhbCxELGIsXykpKTt2YXIgTz1JP0kuYm94U3RhcnRJbmRleDp0LmNvbGxpc2lvbkJveEFycmF5Lmxlbmd0aCxDPUk/SS5ib3hFbmRJbmRleDp0LmNvbGxpc2lvbkJveEFycmF5Lmxlbmd0aDtpZihvKXt2YXIgQT1mdW5jdGlvbih0LGkscixuLG8sYSl7dmFyIHMsbCx1LGgsYz1pLmltYWdlLGY9ci5sYXlvdXQscD1pLnRvcC0xL2MucGl4ZWxSYXRpbyxkPWkubGVmdC0xL2MucGl4ZWxSYXRpbyxnPWkuYm90dG9tKzEvYy5waXhlbFJhdGlvLHY9aS5yaWdodCsxL2MucGl4ZWxSYXRpbztpZihcIm5vbmVcIiE9PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKSYmbyl7dmFyIHk9di1kLG09Zy1wLHg9Zi5nZXQoXCJ0ZXh0LXNpemVcIikuZXZhbHVhdGUoYSkvMjQsdz1vLmxlZnQqeCxTPW8ucmlnaHQqeCxNPW8udG9wKngsYj1TLXcsXz1vLmJvdHRvbSp4LU0sST1mLmdldChcImljb24tdGV4dC1maXQtcGFkZGluZ1wiKVswXSx6PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCIpWzFdLFQ9Zi5nZXQoXCJpY29uLXRleHQtZml0LXBhZGRpbmdcIilbMl0sUD1mLmdldChcImljb24tdGV4dC1maXQtcGFkZGluZ1wiKVszXSxrPVwid2lkdGhcIj09PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKT8uNSooXy1tKTowLEw9XCJoZWlnaHRcIj09PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKT8uNSooYi15KTowLCQ9XCJ3aWR0aFwiPT09Zi5nZXQoXCJpY29uLXRleHQtZml0XCIpfHxcImJvdGhcIj09PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKT9iOnksRD1cImhlaWdodFwiPT09Zi5nZXQoXCJpY29uLXRleHQtZml0XCIpfHxcImJvdGhcIj09PWYuZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKT9fOm07cz1uZXcgZS5kZWZhdWx0JDEodytMLVAsTStrLUkpLGw9bmV3IGUuZGVmYXVsdCQxKHcrTCt6KyQsTStrLUkpLHU9bmV3IGUuZGVmYXVsdCQxKHcrTCt6KyQsTStrK1QrRCksaD1uZXcgZS5kZWZhdWx0JDEodytMLVAsTStrK1QrRCk7fWVsc2Ugcz1uZXcgZS5kZWZhdWx0JDEoZCxwKSxsPW5ldyBlLmRlZmF1bHQkMSh2LHApLHU9bmV3IGUuZGVmYXVsdCQxKHYsZyksaD1uZXcgZS5kZWZhdWx0JDEoZCxnKTt2YXIgTz1yLmxheW91dC5nZXQoXCJpY29uLXJvdGF0ZVwiKS5ldmFsdWF0ZShhKSpNYXRoLlBJLzE4MDtpZihPKXt2YXIgQz1NYXRoLnNpbihPKSxBPU1hdGguY29zKE8pLEU9W0EsLUMsQyxBXTtzLl9tYXRNdWx0KEUpLGwuX21hdE11bHQoRSksaC5fbWF0TXVsdChFKSx1Ll9tYXRNdWx0KEUpO31yZXR1cm5be3RsOnMsdHI6bCxibDpoLGJyOnUsdGV4OmMucGFkZGVkUmVjdCx3cml0aW5nTW9kZTp2b2lkIDAsZ2x5cGhPZmZzZXQ6WzAsMF19XX0oMCxvLGwsMCxuLmhvcml6b250YWwsTSk7ej1uZXcgcyh1LHIsaSxoLGMsZixvLG0seCwhMSx0Lm92ZXJzY2FsaW5nKSxQPTQqQS5sZW5ndGg7dmFyIEU9dC5pY29uU2l6ZURhdGEsTj1udWxsO1wic291cmNlXCI9PT1FLmZ1bmN0aW9uVHlwZT9OPVsxMCpsLmxheW91dC5nZXQoXCJpY29uLXNpemVcIikuZXZhbHVhdGUoTSldOlwiY29tcG9zaXRlXCI9PT1FLmZ1bmN0aW9uVHlwZSYmKE49WzEwKl8uY29tcG9zaXRlSWNvblNpemVzWzBdLmV2YWx1YXRlKE0pLDEwKl8uY29tcG9zaXRlSWNvblNpemVzWzFdLmV2YWx1YXRlKE0pXSksdC5hZGRTeW1ib2xzKHQuaWNvbixBLE4sUyx3LE0sITEsaSxULmxpbmVTdGFydEluZGV4LFQubGluZUxlbmd0aCk7fXZhciBSPXo/ei5ib3hTdGFydEluZGV4OnQuY29sbGlzaW9uQm94QXJyYXkubGVuZ3RoLEI9ej96LmJveEVuZEluZGV4OnQuY29sbGlzaW9uQm94QXJyYXkubGVuZ3RoO3QuZ2x5cGhPZmZzZXRBcnJheS5sZW5ndGg+PWUuZGVmYXVsdCQxNC5NQVhfR0xZUEhTJiZlLndhcm5PbmNlKFwiVG9vIG1hbnkgZ2x5cGhzIGJlaW5nIHJlbmRlcmVkIGluIGEgdGlsZS4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXBib3gvbWFwYm94LWdsLWpzL2lzc3Vlcy8yOTA3XCIpO3ZhciBGPW5ldyBhLEc9bmV3IGE7cmV0dXJue2tleTokLHRleHRCb3hTdGFydEluZGV4Ok8sdGV4dEJveEVuZEluZGV4OkMsaWNvbkJveFN0YXJ0SW5kZXg6UixpY29uQm94RW5kSW5kZXg6Qix0ZXh0T2Zmc2V0OnYsaWNvbk9mZnNldDpTLGFuY2hvcjppLGxpbmU6cixmZWF0dXJlSW5kZXg6aCxmZWF0dXJlOk0sbnVtR2x5cGhWZXJ0aWNlczprLG51bVZlcnRpY2FsR2x5cGhWZXJ0aWNlczpMLG51bUljb25WZXJ0aWNlczpQLHRleHRPcGFjaXR5U3RhdGU6RixpY29uT3BhY2l0eVN0YXRlOkcsaXNEdXBsaWNhdGU6ITEscGxhY2VkVGV4dFN5bWJvbEluZGljZXM6RCxjcm9zc1RpbGVJRDowfX0odCxoLG8scixuLHQubGF5ZXJzWzBdLHQuY29sbGlzaW9uQm94QXJyYXksaS5pbmRleCxpLnNvdXJjZUxheWVySW5kZXgsdC5pbmRleCx3LF8sVCxnLE0sSSxQLHYsaSxsLHUpKTt9O2lmKFwibGluZVwiPT09ZC5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpKWZvcih2YXIgJD0wLEQ9ZnVuY3Rpb24odCxpLHIsbixvKXtmb3IodmFyIGE9W10scz0wO3M8dC5sZW5ndGg7cysrKWZvcih2YXIgbD10W3NdLHU9dm9pZCAwLGg9MDtoPGwubGVuZ3RoLTE7aCsrKXt2YXIgYz1sW2hdLGY9bFtoKzFdO2MueDxpJiZmLng8aXx8KGMueDxpP2M9bmV3IGUuZGVmYXVsdCQxKGksYy55KyhmLnktYy55KSooKGktYy54KS8oZi54LWMueCkpKS5fcm91bmQoKTpmLng8aSYmKGY9bmV3IGUuZGVmYXVsdCQxKGksYy55KyhmLnktYy55KSooKGktYy54KS8oZi54LWMueCkpKS5fcm91bmQoKSksYy55PHImJmYueTxyfHwoYy55PHI/Yz1uZXcgZS5kZWZhdWx0JDEoYy54KyhmLngtYy54KSooKHItYy55KS8oZi55LWMueSkpLHIpLl9yb3VuZCgpOmYueTxyJiYoZj1uZXcgZS5kZWZhdWx0JDEoYy54KyhmLngtYy54KSooKHItYy55KS8oZi55LWMueSkpLHIpLl9yb3VuZCgpKSxjLng+PW4mJmYueD49bnx8KGMueD49bj9jPW5ldyBlLmRlZmF1bHQkMShuLGMueSsoZi55LWMueSkqKChuLWMueCkvKGYueC1jLngpKSkuX3JvdW5kKCk6Zi54Pj1uJiYoZj1uZXcgZS5kZWZhdWx0JDEobixjLnkrKGYueS1jLnkpKigobi1jLngpLyhmLngtYy54KSkpLl9yb3VuZCgpKSxjLnk+PW8mJmYueT49b3x8KGMueT49bz9jPW5ldyBlLmRlZmF1bHQkMShjLngrKGYueC1jLngpKigoby1jLnkpLyhmLnktYy55KSksbykuX3JvdW5kKCk6Zi55Pj1vJiYoZj1uZXcgZS5kZWZhdWx0JDEoYy54KyhmLngtYy54KSooKG8tYy55KS8oZi55LWMueSkpLG8pLl9yb3VuZCgpKSx1JiZjLmVxdWFscyh1W3UubGVuZ3RoLTFdKXx8KHU9W2NdLGEucHVzaCh1KSksdS5wdXNoKGYpKSkpKTt9cmV0dXJuIGF9KGkuZ2VvbWV0cnksMCwwLGUuZGVmYXVsdCQ4LGUuZGVmYXVsdCQ4KTskPEQubGVuZ3RoOyQrPTEpZm9yKHZhciBPPURbJF0sQz0wLEE9byhPLGIseixyLnZlcnRpY2FsfHxyLmhvcml6b250YWwsbiwyNCxTLHQub3ZlcnNjYWxpbmcsZS5kZWZhdWx0JDgpO0M8QS5sZW5ndGg7Qys9MSl7dmFyIEU9QVtDXSxOPXIuaG9yaXpvbnRhbDtOJiZtKHQsTi50ZXh0LGssRSl8fEwoTyxFKTt9ZWxzZSBpZihcIlBvbHlnb25cIj09PWkudHlwZSlmb3IodmFyIFI9MCxCPWUuZGVmYXVsdCQyNihpLmdlb21ldHJ5LDApO1I8Qi5sZW5ndGg7Uis9MSl7dmFyIEY9QltSXSxHPWYoRiwxNik7TChGWzBdLG5ldyBlLmRlZmF1bHQkMjUoRy54LEcueSwwKSk7fWVsc2UgaWYoXCJMaW5lU3RyaW5nXCI9PT1pLnR5cGUpZm9yKHZhciBWPTAsSj1pLmdlb21ldHJ5O1Y8Si5sZW5ndGg7Vis9MSl7dmFyIFc9SltWXTtMKFcsbmV3IGUuZGVmYXVsdCQyNShXWzBdLngsV1swXS55LDApKTt9ZWxzZSBpZihcIlBvaW50XCI9PT1pLnR5cGUpZm9yKHZhciBZPTAsWj1pLmdlb21ldHJ5O1k8Wi5sZW5ndGg7WSs9MSlmb3IodmFyIGo9MCxYPVpbWV07ajxYLmxlbmd0aDtqKz0xKXt2YXIgcT1YW2pdO0woW3FdLG5ldyBlLmRlZmF1bHQkMjUocS54LHEueSwwKSk7fX1mdW5jdGlvbiB5KHQsaSxyLG4sbyxhLHMsbCx1LGgsYyxmKXt2YXIgcD1mdW5jdGlvbih0LGkscixuLG8sYSl7Zm9yKHZhciBzPXIubGF5b3V0LmdldChcInRleHQtcm90YXRlXCIpLmV2YWx1YXRlKG8pKk1hdGguUEkvMTgwLGw9ci5sYXlvdXQuZ2V0KFwidGV4dC1vZmZzZXRcIikuZXZhbHVhdGUobykubWFwKGZ1bmN0aW9uKGUpe3JldHVybiAyNCplfSksdT1pLnBvc2l0aW9uZWRHbHlwaHMsaD1bXSxjPTA7Yzx1Lmxlbmd0aDtjKyspe3ZhciBmPXVbY10scD1hW2YuZ2x5cGhdO2lmKHApe3ZhciBkPXAucmVjdDtpZihkKXt2YXIgZz1lLkdMWVBIX1BCRl9CT1JERVIrMSx2PXAubWV0cmljcy5hZHZhbmNlLzIseT1uP1tmLngrdixmLnldOlswLDBdLG09bj9bMCwwXTpbZi54K3YrbFswXSxmLnkrbFsxXV0seD1wLm1ldHJpY3MubGVmdC1nLXYrbVswXSx3PS1wLm1ldHJpY3MudG9wLWcrbVsxXSxTPXgrZC53LE09dytkLmgsYj1uZXcgZS5kZWZhdWx0JDEoeCx3KSxfPW5ldyBlLmRlZmF1bHQkMShTLHcpLEk9bmV3IGUuZGVmYXVsdCQxKHgsTSksej1uZXcgZS5kZWZhdWx0JDEoUyxNKTtpZihuJiZmLnZlcnRpY2FsKXt2YXIgVD1uZXcgZS5kZWZhdWx0JDEoLXYsdiksUD0tTWF0aC5QSS8yLGs9bmV3IGUuZGVmYXVsdCQxKDUsMCk7Yi5fcm90YXRlQXJvdW5kKFAsVCkuX2FkZChrKSxfLl9yb3RhdGVBcm91bmQoUCxUKS5fYWRkKGspLEkuX3JvdGF0ZUFyb3VuZChQLFQpLl9hZGQoayksei5fcm90YXRlQXJvdW5kKFAsVCkuX2FkZChrKTt9aWYocyl7dmFyIEw9TWF0aC5zaW4ocyksJD1NYXRoLmNvcyhzKSxEPVskLC1MLEwsJF07Yi5fbWF0TXVsdChEKSxfLl9tYXRNdWx0KEQpLEkuX21hdE11bHQoRCksei5fbWF0TXVsdChEKTt9aC5wdXNoKHt0bDpiLHRyOl8sYmw6SSxicjp6LHRleDpkLHdyaXRpbmdNb2RlOmkud3JpdGluZ01vZGUsZ2x5cGhPZmZzZXQ6eX0pO319fXJldHVybiBofSgwLHIsbixvLGEsYyksZD10LnRleHRTaXplRGF0YSxnPW51bGw7cmV0dXJuXCJzb3VyY2VcIj09PWQuZnVuY3Rpb25UeXBlP2c9WzEwKm4ubGF5b3V0LmdldChcInRleHQtc2l6ZVwiKS5ldmFsdWF0ZShhKV06XCJjb21wb3NpdGVcIj09PWQuZnVuY3Rpb25UeXBlJiYoZz1bMTAqZi5jb21wb3NpdGVUZXh0U2l6ZXNbMF0uZXZhbHVhdGUoYSksMTAqZi5jb21wb3NpdGVUZXh0U2l6ZXNbMV0uZXZhbHVhdGUoYSldKSx0LmFkZFN5bWJvbHModC50ZXh0LHAsZyxzLG8sYSx1LGksbC5saW5lU3RhcnRJbmRleCxsLmxpbmVMZW5ndGgpLGgucHVzaCh0LnRleHQucGxhY2VkU3ltYm9sQXJyYXkubGVuZ3RoLTEpLDQqcC5sZW5ndGh9ZnVuY3Rpb24gbShlLHQsaSxyKXt2YXIgbj1lLmNvbXBhcmVUZXh0O2lmKHQgaW4gbil7Zm9yKHZhciBvPW5bdF0sYT1vLmxlbmd0aC0xO2E+PTA7YS0tKWlmKHIuZGlzdChvW2FdKTxpKXJldHVybiEwfWVsc2Ugblt0XT1bXTtyZXR1cm4gblt0XS5wdXNoKHIpLCExfWgucHJvdG90eXBlPXtwdXNoOmZ1bmN0aW9uKGUpe3RoaXMuZGF0YS5wdXNoKGUpLHRoaXMubGVuZ3RoKyssdGhpcy5fdXAodGhpcy5sZW5ndGgtMSk7fSxwb3A6ZnVuY3Rpb24oKXtpZigwIT09dGhpcy5sZW5ndGgpe3ZhciBlPXRoaXMuZGF0YVswXTtyZXR1cm4gdGhpcy5sZW5ndGgtLSx0aGlzLmxlbmd0aD4wJiYodGhpcy5kYXRhWzBdPXRoaXMuZGF0YVt0aGlzLmxlbmd0aF0sdGhpcy5fZG93bigwKSksdGhpcy5kYXRhLnBvcCgpLGV9fSxwZWVrOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGF0YVswXX0sX3VwOmZ1bmN0aW9uKGUpe2Zvcih2YXIgdD10aGlzLmRhdGEsaT10aGlzLmNvbXBhcmUscj10W2VdO2U+MDspe3ZhciBuPWUtMT4+MSxvPXRbbl07aWYoaShyLG8pPj0wKWJyZWFrO3RbZV09byxlPW47fXRbZV09cjt9LF9kb3duOmZ1bmN0aW9uKGUpe2Zvcih2YXIgdD10aGlzLmRhdGEsaT10aGlzLmNvbXBhcmUscj10aGlzLmxlbmd0aD4+MSxuPXRbZV07ZTxyOyl7dmFyIG89MSsoZTw8MSksYT1vKzEscz10W29dO2lmKGE8dGhpcy5sZW5ndGgmJmkodFthXSxzKTwwJiYobz1hLHM9dFthXSksaShzLG4pPj0wKWJyZWFrO3RbZV09cyxlPW87fXRbZV09bjt9fSxsLmRlZmF1bHQ9dTt2YXIgeD1mdW5jdGlvbih0KXt2YXIgaT1uZXcgZS5BbHBoYUltYWdlKHt3aWR0aDowLGhlaWdodDowfSkscj17fSxuPW5ldyBlLmRlZmF1bHQkMigwLDAse2F1dG9SZXNpemU6ITB9KTtmb3IodmFyIG8gaW4gdCl7dmFyIGE9dFtvXSxzPXJbb109e307Zm9yKHZhciBsIGluIGEpe3ZhciB1PWFbK2xdO2lmKHUmJjAhPT11LmJpdG1hcC53aWR0aCYmMCE9PXUuYml0bWFwLmhlaWdodCl7dmFyIGg9bi5wYWNrT25lKHUuYml0bWFwLndpZHRoKzIsdS5iaXRtYXAuaGVpZ2h0KzIpO2kucmVzaXplKHt3aWR0aDpuLncsaGVpZ2h0Om4uaH0pLGUuQWxwaGFJbWFnZS5jb3B5KHUuYml0bWFwLGkse3g6MCx5OjB9LHt4OmgueCsxLHk6aC55KzF9LHUuYml0bWFwKSxzW2xdPXtyZWN0OmgsbWV0cmljczp1Lm1ldHJpY3N9O319fW4uc2hyaW5rKCksaS5yZXNpemUoe3dpZHRoOm4udyxoZWlnaHQ6bi5ofSksdGhpcy5pbWFnZT1pLHRoaXMucG9zaXRpb25zPXI7fTtlLnJlZ2lzdGVyKFwiR2x5cGhBdGxhc1wiLHgpO3ZhciB3PWZ1bmN0aW9uKHQpe3RoaXMudGlsZUlEPW5ldyBlLk92ZXJzY2FsZWRUaWxlSUQodC50aWxlSUQub3ZlcnNjYWxlZFosdC50aWxlSUQud3JhcCx0LnRpbGVJRC5jYW5vbmljYWwueix0LnRpbGVJRC5jYW5vbmljYWwueCx0LnRpbGVJRC5jYW5vbmljYWwueSksdGhpcy51aWQ9dC51aWQsdGhpcy56b29tPXQuem9vbSx0aGlzLnBpeGVsUmF0aW89dC5waXhlbFJhdGlvLHRoaXMudGlsZVNpemU9dC50aWxlU2l6ZSx0aGlzLnNvdXJjZT10LnNvdXJjZSx0aGlzLm92ZXJzY2FsaW5nPXRoaXMudGlsZUlELm92ZXJzY2FsZUZhY3RvcigpLHRoaXMuc2hvd0NvbGxpc2lvbkJveGVzPXQuc2hvd0NvbGxpc2lvbkJveGVzLHRoaXMuY29sbGVjdFJlc291cmNlVGltaW5nPSEhdC5jb2xsZWN0UmVzb3VyY2VUaW1pbmc7fTtmdW5jdGlvbiBTKHQsaSl7Zm9yKHZhciByPW5ldyBlLmRlZmF1bHQkMTYoaSksbj0wLG89dDtuPG8ubGVuZ3RoO24rPTEpe29bbl0ucmVjYWxjdWxhdGUocik7fX13LnByb3RvdHlwZS5wYXJzZT1mdW5jdGlvbih0LGkscixuKXt2YXIgbz10aGlzO3RoaXMuc3RhdHVzPVwicGFyc2luZ1wiLHRoaXMuZGF0YT10LHRoaXMuY29sbGlzaW9uQm94QXJyYXk9bmV3IGUuQ29sbGlzaW9uQm94QXJyYXk7dmFyIGE9bmV3IGUuZGVmYXVsdCQyNyhPYmplY3Qua2V5cyh0LmxheWVycykuc29ydCgpKSxzPW5ldyBlLmRlZmF1bHQkMTEodGhpcy50aWxlSUQpO3MuYnVja2V0TGF5ZXJJRHM9W107dmFyIGwsdSxoLGM9e30sZj17ZmVhdHVyZUluZGV4OnMsaWNvbkRlcGVuZGVuY2llczp7fSxnbHlwaERlcGVuZGVuY2llczp7fX0scD1pLmZhbWlsaWVzQnlTb3VyY2VbdGhpcy5zb3VyY2VdO2Zvcih2YXIgZCBpbiBwKXt2YXIgdj10LmxheWVyc1tkXTtpZih2KXsxPT09di52ZXJzaW9uJiZlLndhcm5PbmNlKCdWZWN0b3IgdGlsZSBzb3VyY2UgXCInK28uc291cmNlKydcIiBsYXllciBcIicrZCsnXCIgZG9lcyBub3QgdXNlIHZlY3RvciB0aWxlIHNwZWMgdjIgYW5kIHRoZXJlZm9yZSBtYXkgaGF2ZSBzb21lIHJlbmRlcmluZyBlcnJvcnMuJyk7Zm9yKHZhciB5PWEuZW5jb2RlKGQpLG09W10sdz0wO3c8di5sZW5ndGg7dysrKXt2YXIgTT12LmZlYXR1cmUodyk7bS5wdXNoKHtmZWF0dXJlOk0saW5kZXg6dyxzb3VyY2VMYXllckluZGV4Onl9KTt9Zm9yKHZhciBiPTAsXz1wW2RdO2I8Xy5sZW5ndGg7Yis9MSl7dmFyIEk9X1tiXSx6PUlbMF07aWYoISh6Lm1pbnpvb20mJm8uem9vbTxNYXRoLmZsb29yKHoubWluem9vbSkpKWlmKCEoei5tYXh6b29tJiZvLnpvb20+PXoubWF4em9vbSkpaWYoXCJub25lXCIhPT16LnZpc2liaWxpdHkpUyhJLG8uem9vbSksKGNbei5pZF09ei5jcmVhdGVCdWNrZXQoe2luZGV4OnMuYnVja2V0TGF5ZXJJRHMubGVuZ3RoLGxheWVyczpJLHpvb206by56b29tLHBpeGVsUmF0aW86by5waXhlbFJhdGlvLG92ZXJzY2FsaW5nOm8ub3ZlcnNjYWxpbmcsY29sbGlzaW9uQm94QXJyYXk6by5jb2xsaXNpb25Cb3hBcnJheSxzb3VyY2VMYXllckluZGV4Onl9KSkucG9wdWxhdGUobSxmKSxzLmJ1Y2tldExheWVySURzLnB1c2goSS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGUuaWR9KSk7fX19dmFyIFQ9ZS5tYXBPYmplY3QoZi5nbHlwaERlcGVuZGVuY2llcyxmdW5jdGlvbihlKXtyZXR1cm4gT2JqZWN0LmtleXMoZSkubWFwKE51bWJlcil9KTtPYmplY3Qua2V5cyhUKS5sZW5ndGg/ci5zZW5kKFwiZ2V0R2x5cGhzXCIse3VpZDp0aGlzLnVpZCxzdGFja3M6VH0sZnVuY3Rpb24oZSx0KXtsfHwobD1lLHU9dCxrLmNhbGwobykpO30pOnU9e307dmFyIFA9T2JqZWN0LmtleXMoZi5pY29uRGVwZW5kZW5jaWVzKTtmdW5jdGlvbiBrKCl7aWYobClyZXR1cm4gbihsKTtpZih1JiZoKXt2YXIgdD1uZXcgeCh1KSxpPW5ldyBlLmRlZmF1bHQkMjgoaCk7Zm9yKHZhciByIGluIGMpe3ZhciBvPWNbcl07byBpbnN0YW5jZW9mIGUuZGVmYXVsdCQxNCYmKFMoby5sYXllcnMsdGhpcy56b29tKSxnKG8sdSx0LnBvc2l0aW9ucyxoLGkucG9zaXRpb25zLHRoaXMuc2hvd0NvbGxpc2lvbkJveGVzKSk7fXRoaXMuc3RhdHVzPVwiZG9uZVwiLG4obnVsbCx7YnVja2V0czplLnZhbHVlcyhjKS5maWx0ZXIoZnVuY3Rpb24oZSl7cmV0dXJuIWUuaXNFbXB0eSgpfSksZmVhdHVyZUluZGV4OnMsY29sbGlzaW9uQm94QXJyYXk6dGhpcy5jb2xsaXNpb25Cb3hBcnJheSxnbHlwaEF0bGFzSW1hZ2U6dC5pbWFnZSxpY29uQXRsYXNJbWFnZTppLmltYWdlfSk7fX1QLmxlbmd0aD9yLnNlbmQoXCJnZXRJbWFnZXNcIix7aWNvbnM6UH0sZnVuY3Rpb24oZSx0KXtsfHwobD1lLGg9dCxrLmNhbGwobykpO30pOmg9e30say5jYWxsKHRoaXMpO307dmFyIE09ZnVuY3Rpb24oZSl7cmV0dXJuISghcGVyZm9ybWFuY2V8fCFwZXJmb3JtYW5jZS5nZXRFbnRyaWVzQnlOYW1lKSYmcGVyZm9ybWFuY2UuZ2V0RW50cmllc0J5TmFtZShlKX07ZnVuY3Rpb24gYih0LGkpe3ZhciByPWUuZ2V0QXJyYXlCdWZmZXIodC5yZXF1ZXN0LGZ1bmN0aW9uKHQscil7dD9pKHQpOnImJmkobnVsbCx7dmVjdG9yVGlsZTpuZXcgZS5kZWZhdWx0JDI5LlZlY3RvclRpbGUobmV3IGUuZGVmYXVsdCQzMChyLmRhdGEpKSxyYXdEYXRhOnIuZGF0YSxjYWNoZUNvbnRyb2w6ci5jYWNoZUNvbnRyb2wsZXhwaXJlczpyLmV4cGlyZXN9KTt9KTtyZXR1cm4gZnVuY3Rpb24oKXtyLmFib3J0KCksaSgpO319dmFyIF89ZnVuY3Rpb24oZSx0LGkpe3RoaXMuYWN0b3I9ZSx0aGlzLmxheWVySW5kZXg9dCx0aGlzLmxvYWRWZWN0b3JEYXRhPWl8fGIsdGhpcy5sb2FkaW5nPXt9LHRoaXMubG9hZGVkPXt9O307Xy5wcm90b3R5cGUubG9hZFRpbGU9ZnVuY3Rpb24odCxpKXt2YXIgcj10aGlzLG49dC51aWQ7dGhpcy5sb2FkaW5nfHwodGhpcy5sb2FkaW5nPXt9KTt2YXIgbz10aGlzLmxvYWRpbmdbbl09bmV3IHcodCk7by5hYm9ydD10aGlzLmxvYWRWZWN0b3JEYXRhKHQsZnVuY3Rpb24oYSxzKXtpZihkZWxldGUgci5sb2FkaW5nW25dLGF8fCFzKXJldHVybiBpKGEpO3ZhciBsPXMucmF3RGF0YSx1PXt9O3MuZXhwaXJlcyYmKHUuZXhwaXJlcz1zLmV4cGlyZXMpLHMuY2FjaGVDb250cm9sJiYodS5jYWNoZUNvbnRyb2w9cy5jYWNoZUNvbnRyb2wpO3ZhciBoPXt9O2lmKHQucmVxdWVzdCYmdC5yZXF1ZXN0LmNvbGxlY3RSZXNvdXJjZVRpbWluZyl7dmFyIGM9TSh0LnJlcXVlc3QudXJsKTtjJiYoaC5yZXNvdXJjZVRpbWluZz1KU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGMpKSk7fW8udmVjdG9yVGlsZT1zLnZlY3RvclRpbGUsby5wYXJzZShzLnZlY3RvclRpbGUsci5sYXllckluZGV4LHIuYWN0b3IsZnVuY3Rpb24odCxyKXtpZih0fHwhcilyZXR1cm4gaSh0KTtpKG51bGwsZS5leHRlbmQoe3Jhd1RpbGVEYXRhOmwuc2xpY2UoMCl9LHIsdSxoKSk7fSksci5sb2FkZWQ9ci5sb2FkZWR8fHt9LHIubG9hZGVkW25dPW87fSk7fSxfLnByb3RvdHlwZS5yZWxvYWRUaWxlPWZ1bmN0aW9uKGUsdCl7dmFyIGk9dGhpcy5sb2FkZWQscj1lLnVpZCxuPXRoaXM7aWYoaSYmaVtyXSl7dmFyIG89aVtyXTtvLnNob3dDb2xsaXNpb25Cb3hlcz1lLnNob3dDb2xsaXNpb25Cb3hlczt2YXIgYT1mdW5jdGlvbihlLGkpe3ZhciByPW8ucmVsb2FkQ2FsbGJhY2s7ciYmKGRlbGV0ZSBvLnJlbG9hZENhbGxiYWNrLG8ucGFyc2Uoby52ZWN0b3JUaWxlLG4ubGF5ZXJJbmRleCxuLmFjdG9yLHIpKSx0KGUsaSk7fTtcInBhcnNpbmdcIj09PW8uc3RhdHVzP28ucmVsb2FkQ2FsbGJhY2s9YTpcImRvbmVcIj09PW8uc3RhdHVzJiZvLnBhcnNlKG8udmVjdG9yVGlsZSx0aGlzLmxheWVySW5kZXgsdGhpcy5hY3RvcixhKTt9fSxfLnByb3RvdHlwZS5hYm9ydFRpbGU9ZnVuY3Rpb24oZSx0KXt2YXIgaT10aGlzLmxvYWRpbmcscj1lLnVpZDtpJiZpW3JdJiZpW3JdLmFib3J0JiYoaVtyXS5hYm9ydCgpLGRlbGV0ZSBpW3JdKSx0KCk7fSxfLnByb3RvdHlwZS5yZW1vdmVUaWxlPWZ1bmN0aW9uKGUsdCl7dmFyIGk9dGhpcy5sb2FkZWQscj1lLnVpZDtpJiZpW3JdJiZkZWxldGUgaVtyXSx0KCk7fTt2YXIgST1mdW5jdGlvbigpe3RoaXMubG9hZGluZz17fSx0aGlzLmxvYWRlZD17fTt9O0kucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKHQsaSl7dmFyIHI9dC51aWQsbj10LmVuY29kaW5nLG89bmV3IGUuZGVmYXVsdCQzMShyKTt0aGlzLmxvYWRpbmdbcl09byxvLmxvYWRGcm9tSW1hZ2UodC5yYXdJbWFnZURhdGEsbiksZGVsZXRlIHRoaXMubG9hZGluZ1tyXSx0aGlzLmxvYWRlZD10aGlzLmxvYWRlZHx8e30sdGhpcy5sb2FkZWRbcl09byxpKG51bGwsbyk7fSxJLnByb3RvdHlwZS5yZW1vdmVUaWxlPWZ1bmN0aW9uKGUpe3ZhciB0PXRoaXMubG9hZGVkLGk9ZS51aWQ7dCYmdFtpXSYmZGVsZXRlIHRbaV07fTt2YXIgej17UkFESVVTOjYzNzgxMzcsRkxBVFRFTklORzoxLzI5OC4yNTcyMjM1NjMsUE9MQVJfUkFESVVTOjYzNTY3NTIuMzE0Mn07ZnVuY3Rpb24gVChlKXt2YXIgdD0wO2lmKGUmJmUubGVuZ3RoPjApe3QrPU1hdGguYWJzKFAoZVswXSkpO2Zvcih2YXIgaT0xO2k8ZS5sZW5ndGg7aSsrKXQtPU1hdGguYWJzKFAoZVtpXSkpO31yZXR1cm4gdH1mdW5jdGlvbiBQKGUpe3ZhciB0LGkscixuLG8sYSxzPTAsbD1lLmxlbmd0aDtpZihsPjIpe2ZvcihhPTA7YTxsO2ErKylhPT09bC0yPyhyPWwtMixuPWwtMSxvPTApOmE9PT1sLTE/KHI9bC0xLG49MCxvPTEpOihyPWEsbj1hKzEsbz1hKzIpLHQ9ZVtyXSxpPWVbbl0scys9KGsoZVtvXVswXSktayh0WzBdKSkqTWF0aC5zaW4oayhpWzFdKSk7cz1zKnouUkFESVVTKnouUkFESVVTLzI7fXJldHVybiBzfWZ1bmN0aW9uIGsoZSl7cmV0dXJuIGUqTWF0aC5QSS8xODB9dmFyIEw9e2dlb21ldHJ5OmZ1bmN0aW9uIGUodCl7dmFyIGkscj0wO3N3aXRjaCh0LnR5cGUpe2Nhc2VcIlBvbHlnb25cIjpyZXR1cm4gVCh0LmNvb3JkaW5hdGVzKTtjYXNlXCJNdWx0aVBvbHlnb25cIjpmb3IoaT0wO2k8dC5jb29yZGluYXRlcy5sZW5ndGg7aSsrKXIrPVQodC5jb29yZGluYXRlc1tpXSk7cmV0dXJuIHI7Y2FzZVwiUG9pbnRcIjpjYXNlXCJNdWx0aVBvaW50XCI6Y2FzZVwiTGluZVN0cmluZ1wiOmNhc2VcIk11bHRpTGluZVN0cmluZ1wiOnJldHVybiAwO2Nhc2VcIkdlb21ldHJ5Q29sbGVjdGlvblwiOmZvcihpPTA7aTx0Lmdlb21ldHJpZXMubGVuZ3RoO2krKylyKz1lKHQuZ2VvbWV0cmllc1tpXSk7cmV0dXJuIHJ9fSxyaW5nOlB9LCQ9ZnVuY3Rpb24gZSh0LGkpe3N3aXRjaCh0JiZ0LnR5cGV8fG51bGwpe2Nhc2VcIkZlYXR1cmVDb2xsZWN0aW9uXCI6cmV0dXJuIHQuZmVhdHVyZXM9dC5mZWF0dXJlcy5tYXAoRChlLGkpKSx0O2Nhc2VcIkZlYXR1cmVcIjpyZXR1cm4gdC5nZW9tZXRyeT1lKHQuZ2VvbWV0cnksaSksdDtjYXNlXCJQb2x5Z29uXCI6Y2FzZVwiTXVsdGlQb2x5Z29uXCI6cmV0dXJuIGZ1bmN0aW9uKGUsdCl7XCJQb2x5Z29uXCI9PT1lLnR5cGU/ZS5jb29yZGluYXRlcz1PKGUuY29vcmRpbmF0ZXMsdCk6XCJNdWx0aVBvbHlnb25cIj09PWUudHlwZSYmKGUuY29vcmRpbmF0ZXM9ZS5jb29yZGluYXRlcy5tYXAoRChPLHQpKSk7cmV0dXJuIGV9KHQsaSk7ZGVmYXVsdDpyZXR1cm4gdH19O2Z1bmN0aW9uIEQoZSx0KXtyZXR1cm4gZnVuY3Rpb24oaSl7cmV0dXJuIGUoaSx0KX19ZnVuY3Rpb24gTyhlLHQpe3Q9ISF0LGVbMF09QyhlWzBdLHQpO2Zvcih2YXIgaT0xO2k8ZS5sZW5ndGg7aSsrKWVbaV09QyhlW2ldLCF0KTtyZXR1cm4gZX1mdW5jdGlvbiBDKGUsdCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiBMLnJpbmcoZSk+PTB9KGUpPT09dD9lOmUucmV2ZXJzZSgpfXZhciBBPWUuZGVmYXVsdCQyOS5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUudG9HZW9KU09OLEU9ZnVuY3Rpb24odCl7dGhpcy5fZmVhdHVyZT10LHRoaXMuZXh0ZW50PWUuZGVmYXVsdCQ4LHRoaXMudHlwZT10LnR5cGUsdGhpcy5wcm9wZXJ0aWVzPXQudGFncyxcImlkXCJpbiB0JiYhaXNOYU4odC5pZCkmJih0aGlzLmlkPXBhcnNlSW50KHQuaWQsMTApKTt9O0UucHJvdG90eXBlLmxvYWRHZW9tZXRyeT1mdW5jdGlvbigpe2lmKDE9PT10aGlzLl9mZWF0dXJlLnR5cGUpe2Zvcih2YXIgdD1bXSxpPTAscj10aGlzLl9mZWF0dXJlLmdlb21ldHJ5O2k8ci5sZW5ndGg7aSs9MSl7dmFyIG49cltpXTt0LnB1c2goW25ldyBlLmRlZmF1bHQkMShuWzBdLG5bMV0pXSk7fXJldHVybiB0fWZvcih2YXIgbz1bXSxhPTAscz10aGlzLl9mZWF0dXJlLmdlb21ldHJ5O2E8cy5sZW5ndGg7YSs9MSl7Zm9yKHZhciBsPVtdLHU9MCxoPXNbYV07dTxoLmxlbmd0aDt1Kz0xKXt2YXIgYz1oW3VdO2wucHVzaChuZXcgZS5kZWZhdWx0JDEoY1swXSxjWzFdKSk7fW8ucHVzaChsKTt9cmV0dXJuIG99LEUucHJvdG90eXBlLnRvR2VvSlNPTj1mdW5jdGlvbihlLHQsaSl7cmV0dXJuIEEuY2FsbCh0aGlzLGUsdCxpKX07dmFyIE49ZnVuY3Rpb24odCl7dGhpcy5sYXllcnM9e19nZW9qc29uVGlsZUxheWVyOnRoaXN9LHRoaXMubmFtZT1cIl9nZW9qc29uVGlsZUxheWVyXCIsdGhpcy5leHRlbnQ9ZS5kZWZhdWx0JDgsdGhpcy5sZW5ndGg9dC5sZW5ndGgsdGhpcy5fZmVhdHVyZXM9dDt9O04ucHJvdG90eXBlLmZlYXR1cmU9ZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyBFKHRoaXMuX2ZlYXR1cmVzW2VdKX07dmFyIFI9ZS5fX21vZHVsZUV4cG9ydHMuVmVjdG9yVGlsZUZlYXR1cmUsQj1GO2Z1bmN0aW9uIEYoZSx0KXt0aGlzLm9wdGlvbnM9dHx8e30sdGhpcy5mZWF0dXJlcz1lLHRoaXMubGVuZ3RoPWUubGVuZ3RoO31mdW5jdGlvbiBHKGUsdCl7dGhpcy5pZD1cIm51bWJlclwiPT10eXBlb2YgZS5pZD9lLmlkOnZvaWQgMCx0aGlzLnR5cGU9ZS50eXBlLHRoaXMucmF3R2VvbWV0cnk9MT09PWUudHlwZT9bZS5nZW9tZXRyeV06ZS5nZW9tZXRyeSx0aGlzLnByb3BlcnRpZXM9ZS50YWdzLHRoaXMuZXh0ZW50PXR8fDQwOTY7fUYucHJvdG90eXBlLmZlYXR1cmU9ZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyBHKHRoaXMuZmVhdHVyZXNbZV0sdGhpcy5vcHRpb25zLmV4dGVudCl9LEcucHJvdG90eXBlLmxvYWRHZW9tZXRyeT1mdW5jdGlvbigpe3ZhciB0PXRoaXMucmF3R2VvbWV0cnk7dGhpcy5nZW9tZXRyeT1bXTtmb3IodmFyIGk9MDtpPHQubGVuZ3RoO2krKyl7Zm9yKHZhciByPXRbaV0sbj1bXSxvPTA7bzxyLmxlbmd0aDtvKyspbi5wdXNoKG5ldyBlLmRlZmF1bHQkMzIocltvXVswXSxyW29dWzFdKSk7dGhpcy5nZW9tZXRyeS5wdXNoKG4pO31yZXR1cm4gdGhpcy5nZW9tZXRyeX0sRy5wcm90b3R5cGUuYmJveD1mdW5jdGlvbigpe3RoaXMuZ2VvbWV0cnl8fHRoaXMubG9hZEdlb21ldHJ5KCk7Zm9yKHZhciBlPXRoaXMuZ2VvbWV0cnksdD0xLzAsaT0tMS8wLHI9MS8wLG49LTEvMCxvPTA7bzxlLmxlbmd0aDtvKyspZm9yKHZhciBhPWVbb10scz0wO3M8YS5sZW5ndGg7cysrKXt2YXIgbD1hW3NdO3Q9TWF0aC5taW4odCxsLngpLGk9TWF0aC5tYXgoaSxsLngpLHI9TWF0aC5taW4ocixsLnkpLG49TWF0aC5tYXgobixsLnkpO31yZXR1cm5bdCxyLGksbl19LEcucHJvdG90eXBlLnRvR2VvSlNPTj1SLnByb3RvdHlwZS50b0dlb0pTT047dmFyIFY9WixKPVosVz1mdW5jdGlvbihlLHQpe3Q9dHx8e307dmFyIGk9e307Zm9yKHZhciByIGluIGUpaVtyXT1uZXcgQihlW3JdLmZlYXR1cmVzLHQpLGlbcl0ubmFtZT1yLGlbcl0udmVyc2lvbj10LnZlcnNpb24saVtyXS5leHRlbnQ9dC5leHRlbnQ7cmV0dXJuIFooe2xheWVyczppfSl9LFk9QjtmdW5jdGlvbiBaKHQpe3ZhciBpPW5ldyBlLl9fbW9kdWxlRXhwb3J0cyQxO3JldHVybiBmdW5jdGlvbihlLHQpe2Zvcih2YXIgaSBpbiBlLmxheWVycyl0LndyaXRlTWVzc2FnZSgzLGosZS5sYXllcnNbaV0pO30odCxpKSxpLmZpbmlzaCgpfWZ1bmN0aW9uIGooZSx0KXt2YXIgaTt0LndyaXRlVmFyaW50RmllbGQoMTUsZS52ZXJzaW9ufHwxKSx0LndyaXRlU3RyaW5nRmllbGQoMSxlLm5hbWV8fFwiXCIpLHQud3JpdGVWYXJpbnRGaWVsZCg1LGUuZXh0ZW50fHw0MDk2KTt2YXIgcj17a2V5czpbXSx2YWx1ZXM6W10sa2V5Y2FjaGU6e30sdmFsdWVjYWNoZTp7fX07Zm9yKGk9MDtpPGUubGVuZ3RoO2krKylyLmZlYXR1cmU9ZS5mZWF0dXJlKGkpLHQud3JpdGVNZXNzYWdlKDIsWCxyKTt2YXIgbj1yLmtleXM7Zm9yKGk9MDtpPG4ubGVuZ3RoO2krKyl0LndyaXRlU3RyaW5nRmllbGQoMyxuW2ldKTt2YXIgbz1yLnZhbHVlcztmb3IoaT0wO2k8by5sZW5ndGg7aSsrKXQud3JpdGVNZXNzYWdlKDQsSyxvW2ldKTt9ZnVuY3Rpb24gWChlLHQpe3ZhciBpPWUuZmVhdHVyZTt2b2lkIDAhPT1pLmlkJiZ0LndyaXRlVmFyaW50RmllbGQoMSxpLmlkKSx0LndyaXRlTWVzc2FnZSgyLHEsZSksdC53cml0ZVZhcmludEZpZWxkKDMsaS50eXBlKSx0LndyaXRlTWVzc2FnZSg0LFEsaSk7fWZ1bmN0aW9uIHEoZSx0KXt2YXIgaT1lLmZlYXR1cmUscj1lLmtleXMsbj1lLnZhbHVlcyxvPWUua2V5Y2FjaGUsYT1lLnZhbHVlY2FjaGU7Zm9yKHZhciBzIGluIGkucHJvcGVydGllcyl7dmFyIGw9b1tzXTt2b2lkIDA9PT1sJiYoci5wdXNoKHMpLGw9ci5sZW5ndGgtMSxvW3NdPWwpLHQud3JpdGVWYXJpbnQobCk7dmFyIHU9aS5wcm9wZXJ0aWVzW3NdLGg9dHlwZW9mIHU7XCJzdHJpbmdcIiE9PWgmJlwiYm9vbGVhblwiIT09aCYmXCJudW1iZXJcIiE9PWgmJih1PUpTT04uc3RyaW5naWZ5KHUpKTt2YXIgYz1oK1wiOlwiK3UsZj1hW2NdO3ZvaWQgMD09PWYmJihuLnB1c2godSksZj1uLmxlbmd0aC0xLGFbY109ZiksdC53cml0ZVZhcmludChmKTt9fWZ1bmN0aW9uIFUoZSx0KXtyZXR1cm4odDw8MykrKDcmZSl9ZnVuY3Rpb24gSChlKXtyZXR1cm4gZTw8MV5lPj4zMX1mdW5jdGlvbiBRKGUsdCl7Zm9yKHZhciBpPWUubG9hZEdlb21ldHJ5KCkscj1lLnR5cGUsbj0wLG89MCxhPWkubGVuZ3RoLHM9MDtzPGE7cysrKXt2YXIgbD1pW3NdLHU9MTsxPT09ciYmKHU9bC5sZW5ndGgpLHQud3JpdGVWYXJpbnQoVSgxLHUpKTtmb3IodmFyIGg9Mz09PXI/bC5sZW5ndGgtMTpsLmxlbmd0aCxjPTA7YzxoO2MrKyl7MT09PWMmJjEhPT1yJiZ0LndyaXRlVmFyaW50KFUoMixoLTEpKTt2YXIgZj1sW2NdLngtbixwPWxbY10ueS1vO3Qud3JpdGVWYXJpbnQoSChmKSksdC53cml0ZVZhcmludChIKHApKSxuKz1mLG8rPXA7fTM9PT1yJiZ0LndyaXRlVmFyaW50KFUoNywwKSk7fX1mdW5jdGlvbiBLKGUsdCl7dmFyIGk9dHlwZW9mIGU7XCJzdHJpbmdcIj09PWk/dC53cml0ZVN0cmluZ0ZpZWxkKDEsZSk6XCJib29sZWFuXCI9PT1pP3Qud3JpdGVCb29sZWFuRmllbGQoNyxlKTpcIm51bWJlclwiPT09aSYmKGUlMSE9MD90LndyaXRlRG91YmxlRmllbGQoMyxlKTplPDA/dC53cml0ZVNWYXJpbnRGaWVsZCg2LGUpOnQud3JpdGVWYXJpbnRGaWVsZCg1LGUpKTt9Vi5mcm9tVmVjdG9yVGlsZUpzPUosVi5mcm9tR2VvanNvblZ0PVcsVi5HZW9KU09OV3JhcHBlcj1ZO3ZhciBlZT1mdW5jdGlvbiBlKHQsaSxyLG4sbyxhKXtpZihvLW48PXIpcmV0dXJuO3ZhciBzPU1hdGguZmxvb3IoKG4rbykvMik7IWZ1bmN0aW9uIGUodCxpLHIsbixvLGEpe2Zvcig7bz5uOyl7aWYoby1uPjYwMCl7dmFyIHM9by1uKzEsbD1yLW4rMSx1PU1hdGgubG9nKHMpLGg9LjUqTWF0aC5leHAoMip1LzMpLGM9LjUqTWF0aC5zcXJ0KHUqaCoocy1oKS9zKSoobC1zLzI8MD8tMToxKSxmPU1hdGgubWF4KG4sTWF0aC5mbG9vcihyLWwqaC9zK2MpKSxwPU1hdGgubWluKG8sTWF0aC5mbG9vcihyKyhzLWwpKmgvcytjKSk7ZSh0LGkscixmLHAsYSk7fXZhciBkPWlbMipyK2FdLGc9bix2PW87Zm9yKHRlKHQsaSxuLHIpLGlbMipvK2FdPmQmJnRlKHQsaSxuLG8pO2c8djspe2Zvcih0ZSh0LGksZyx2KSxnKyssdi0tO2lbMipnK2FdPGQ7KWcrKztmb3IoO2lbMip2K2FdPmQ7KXYtLTt9aVsyKm4rYV09PT1kP3RlKHQsaSxuLHYpOnRlKHQsaSwrK3Ysbyksdjw9ciYmKG49disxKSxyPD12JiYobz12LTEpO319KHQsaSxzLG4sbyxhJTIpO2UodCxpLHIsbixzLTEsYSsxKTtlKHQsaSxyLHMrMSxvLGErMSk7fTtmdW5jdGlvbiB0ZShlLHQsaSxyKXtpZShlLGksciksaWUodCwyKmksMipyKSxpZSh0LDIqaSsxLDIqcisxKTt9ZnVuY3Rpb24gaWUoZSx0LGkpe3ZhciByPWVbdF07ZVt0XT1lW2ldLGVbaV09cjt9dmFyIHJlPWZ1bmN0aW9uKGUsdCxpLHIsbixvLGEpe3ZhciBzLGwsdT1bMCxlLmxlbmd0aC0xLDBdLGg9W107Zm9yKDt1Lmxlbmd0aDspe3ZhciBjPXUucG9wKCksZj11LnBvcCgpLHA9dS5wb3AoKTtpZihmLXA8PWEpZm9yKHZhciBkPXA7ZDw9ZjtkKyspcz10WzIqZF0sbD10WzIqZCsxXSxzPj1pJiZzPD1uJiZsPj1yJiZsPD1vJiZoLnB1c2goZVtkXSk7ZWxzZXt2YXIgZz1NYXRoLmZsb29yKChwK2YpLzIpO3M9dFsyKmddLGw9dFsyKmcrMV0scz49aSYmczw9biYmbD49ciYmbDw9byYmaC5wdXNoKGVbZ10pO3ZhciB2PShjKzEpJTI7KDA9PT1jP2k8PXM6cjw9bCkmJih1LnB1c2gocCksdS5wdXNoKGctMSksdS5wdXNoKHYpKSwoMD09PWM/bj49czpvPj1sKSYmKHUucHVzaChnKzEpLHUucHVzaChmKSx1LnB1c2godikpO319cmV0dXJuIGh9O3ZhciBuZT1mdW5jdGlvbihlLHQsaSxyLG4sbyl7dmFyIGE9WzAsZS5sZW5ndGgtMSwwXSxzPVtdLGw9bipuO2Zvcig7YS5sZW5ndGg7KXt2YXIgdT1hLnBvcCgpLGg9YS5wb3AoKSxjPWEucG9wKCk7aWYoaC1jPD1vKWZvcih2YXIgZj1jO2Y8PWg7ZisrKW9lKHRbMipmXSx0WzIqZisxXSxpLHIpPD1sJiZzLnB1c2goZVtmXSk7ZWxzZXt2YXIgcD1NYXRoLmZsb29yKChjK2gpLzIpLGQ9dFsyKnBdLGc9dFsyKnArMV07b2UoZCxnLGkscik8PWwmJnMucHVzaChlW3BdKTt2YXIgdj0odSsxKSUyOygwPT09dT9pLW48PWQ6ci1uPD1nKSYmKGEucHVzaChjKSxhLnB1c2gocC0xKSxhLnB1c2godikpLCgwPT09dT9pK24+PWQ6cituPj1nKSYmKGEucHVzaChwKzEpLGEucHVzaChoKSxhLnB1c2godikpO319cmV0dXJuIHN9O2Z1bmN0aW9uIG9lKGUsdCxpLHIpe3ZhciBuPWUtaSxvPXQtcjtyZXR1cm4gbipuK28qb312YXIgYWU9ZnVuY3Rpb24oZSx0LGkscixuKXtyZXR1cm4gbmV3IHNlKGUsdCxpLHIsbil9O2Z1bmN0aW9uIHNlKGUsdCxpLHIsbil7dD10fHxsZSxpPWl8fHVlLG49bnx8QXJyYXksdGhpcy5ub2RlU2l6ZT1yfHw2NCx0aGlzLnBvaW50cz1lLHRoaXMuaWRzPW5ldyBuKGUubGVuZ3RoKSx0aGlzLmNvb3Jkcz1uZXcgbigyKmUubGVuZ3RoKTtmb3IodmFyIG89MDtvPGUubGVuZ3RoO28rKyl0aGlzLmlkc1tvXT1vLHRoaXMuY29vcmRzWzIqb109dChlW29dKSx0aGlzLmNvb3Jkc1syKm8rMV09aShlW29dKTtlZSh0aGlzLmlkcyx0aGlzLmNvb3Jkcyx0aGlzLm5vZGVTaXplLDAsdGhpcy5pZHMubGVuZ3RoLTEsMCk7fWZ1bmN0aW9uIGxlKGUpe3JldHVybiBlWzBdfWZ1bmN0aW9uIHVlKGUpe3JldHVybiBlWzFdfXNlLnByb3RvdHlwZT17cmFuZ2U6ZnVuY3Rpb24oZSx0LGkscil7cmV0dXJuIHJlKHRoaXMuaWRzLHRoaXMuY29vcmRzLGUsdCxpLHIsdGhpcy5ub2RlU2l6ZSl9LHdpdGhpbjpmdW5jdGlvbihlLHQsaSl7cmV0dXJuIG5lKHRoaXMuaWRzLHRoaXMuY29vcmRzLGUsdCxpLHRoaXMubm9kZVNpemUpfX07dmFyIGhlPWZ1bmN0aW9uKGUpe3JldHVybiBuZXcgY2UoZSl9O2Z1bmN0aW9uIGNlKGUpe3RoaXMub3B0aW9ucz1tZShPYmplY3QuY3JlYXRlKHRoaXMub3B0aW9ucyksZSksdGhpcy50cmVlcz1uZXcgQXJyYXkodGhpcy5vcHRpb25zLm1heFpvb20rMSk7fWZ1bmN0aW9uIGZlKGUsdCxpLHIsbil7cmV0dXJue3g6ZSx5OnQsem9vbToxLzAsaWQ6cixwcm9wZXJ0aWVzOm4scGFyZW50SWQ6LTEsbnVtUG9pbnRzOml9fWZ1bmN0aW9uIHBlKGUsdCl7dmFyIGk9ZS5nZW9tZXRyeS5jb29yZGluYXRlcztyZXR1cm57eDp2ZShpWzBdKSx5OnllKGlbMV0pLHpvb206MS8wLGlkOnQscGFyZW50SWQ6LTF9fWZ1bmN0aW9uIGRlKGUpe3JldHVybnt0eXBlOlwiRmVhdHVyZVwiLHByb3BlcnRpZXM6Z2UoZSksZ2VvbWV0cnk6e3R5cGU6XCJQb2ludFwiLGNvb3JkaW5hdGVzOlsocj1lLngsMzYwKihyLS41KSksKHQ9ZS55LGk9KDE4MC0zNjAqdCkqTWF0aC5QSS8xODAsMzYwKk1hdGguYXRhbihNYXRoLmV4cChpKSkvTWF0aC5QSS05MCldfX07dmFyIHQsaSxyO31mdW5jdGlvbiBnZShlKXt2YXIgdD1lLm51bVBvaW50cyxpPXQ+PTFlND9NYXRoLnJvdW5kKHQvMWUzKStcImtcIjp0Pj0xZTM/TWF0aC5yb3VuZCh0LzEwMCkvMTArXCJrXCI6dDtyZXR1cm4gbWUobWUoe30sZS5wcm9wZXJ0aWVzKSx7Y2x1c3RlcjohMCxjbHVzdGVyX2lkOmUuaWQscG9pbnRfY291bnQ6dCxwb2ludF9jb3VudF9hYmJyZXZpYXRlZDppfSl9ZnVuY3Rpb24gdmUoZSl7cmV0dXJuIGUvMzYwKy41fWZ1bmN0aW9uIHllKGUpe3ZhciB0PU1hdGguc2luKGUqTWF0aC5QSS8xODApLGk9LjUtLjI1Kk1hdGgubG9nKCgxK3QpLygxLXQpKS9NYXRoLlBJO3JldHVybiBpPDA/MDppPjE/MTppfWZ1bmN0aW9uIG1lKGUsdCl7Zm9yKHZhciBpIGluIHQpZVtpXT10W2ldO3JldHVybiBlfWZ1bmN0aW9uIHhlKGUpe3JldHVybiBlLnh9ZnVuY3Rpb24gd2UoZSl7cmV0dXJuIGUueX1mdW5jdGlvbiBTZShlLHQsaSxyLG4sbyl7dmFyIGE9bi1pLHM9by1yO2lmKDAhPT1hfHwwIT09cyl7dmFyIGw9KChlLWkpKmErKHQtcikqcykvKGEqYStzKnMpO2w+MT8oaT1uLHI9byk6bD4wJiYoaSs9YSpsLHIrPXMqbCk7fXJldHVybihhPWUtaSkqYSsocz10LXIpKnN9ZnVuY3Rpb24gTWUoZSx0LGkscil7dmFyIG49e2lkOmV8fG51bGwsdHlwZTp0LGdlb21ldHJ5OmksdGFnczpyLG1pblg6MS8wLG1pblk6MS8wLG1heFg6LTEvMCxtYXhZOi0xLzB9O3JldHVybiBmdW5jdGlvbihlKXt2YXIgdD1lLmdlb21ldHJ5LGk9ZS50eXBlO2lmKFwiUG9pbnRcIj09PWl8fFwiTXVsdGlQb2ludFwiPT09aXx8XCJMaW5lU3RyaW5nXCI9PT1pKWJlKGUsdCk7ZWxzZSBpZihcIlBvbHlnb25cIj09PWl8fFwiTXVsdGlMaW5lU3RyaW5nXCI9PT1pKWZvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWJlKGUsdFtyXSk7ZWxzZSBpZihcIk11bHRpUG9seWdvblwiPT09aSlmb3Iocj0wO3I8dC5sZW5ndGg7cisrKWZvcih2YXIgbj0wO248dFtyXS5sZW5ndGg7bisrKWJlKGUsdFtyXVtuXSk7fShuKSxufWZ1bmN0aW9uIGJlKGUsdCl7Zm9yKHZhciBpPTA7aTx0Lmxlbmd0aDtpKz0zKWUubWluWD1NYXRoLm1pbihlLm1pblgsdFtpXSksZS5taW5ZPU1hdGgubWluKGUubWluWSx0W2krMV0pLGUubWF4WD1NYXRoLm1heChlLm1heFgsdFtpXSksZS5tYXhZPU1hdGgubWF4KGUubWF4WSx0W2krMV0pO31mdW5jdGlvbiBfZShlLHQsaSl7aWYodC5nZW9tZXRyeSl7dmFyIHI9dC5nZW9tZXRyeS5jb29yZGluYXRlcyxuPXQuZ2VvbWV0cnkudHlwZSxvPU1hdGgucG93KGkudG9sZXJhbmNlLygoMTw8aS5tYXhab29tKSppLmV4dGVudCksMiksYT1bXTtpZihcIlBvaW50XCI9PT1uKUllKHIsYSk7ZWxzZSBpZihcIk11bHRpUG9pbnRcIj09PW4pZm9yKHZhciBzPTA7czxyLmxlbmd0aDtzKyspSWUocltzXSxhKTtlbHNlIGlmKFwiTGluZVN0cmluZ1wiPT09bil6ZShyLGEsbywhMSk7ZWxzZSBpZihcIk11bHRpTGluZVN0cmluZ1wiPT09bilpZihpLmxpbmVNZXRyaWNzKWZvcihzPTA7czxyLmxlbmd0aDtzKyspcmV0dXJuIGE9W10semUocltzXSxhLG8sITEpLHZvaWQgZS5wdXNoKE1lKHQuaWQsXCJMaW5lU3RyaW5nXCIsYSx0LnByb3BlcnRpZXMpKTtlbHNlIFRlKHIsYSxvLCExKTtlbHNlIGlmKFwiUG9seWdvblwiPT09bilUZShyLGEsbywhMCk7ZWxzZXtpZihcIk11bHRpUG9seWdvblwiIT09bil7aWYoXCJHZW9tZXRyeUNvbGxlY3Rpb25cIj09PW4pe2ZvcihzPTA7czx0Lmdlb21ldHJ5Lmdlb21ldHJpZXMubGVuZ3RoO3MrKylfZShlLHtpZDp0LmlkLGdlb21ldHJ5OnQuZ2VvbWV0cnkuZ2VvbWV0cmllc1tzXSxwcm9wZXJ0aWVzOnQucHJvcGVydGllc30saSk7cmV0dXJufXRocm93IG5ldyBFcnJvcihcIklucHV0IGRhdGEgaXMgbm90IGEgdmFsaWQgR2VvSlNPTiBvYmplY3QuXCIpfWZvcihzPTA7czxyLmxlbmd0aDtzKyspe3ZhciBsPVtdO1RlKHJbc10sbCxvLCEwKSxhLnB1c2gobCk7fX1lLnB1c2goTWUodC5pZCxuLGEsdC5wcm9wZXJ0aWVzKSk7fX1mdW5jdGlvbiBJZShlLHQpe3QucHVzaChQZShlWzBdKSksdC5wdXNoKGtlKGVbMV0pKSx0LnB1c2goMCk7fWZ1bmN0aW9uIHplKGUsdCxpLHIpe2Zvcih2YXIgbixvLGE9MCxzPTA7czxlLmxlbmd0aDtzKyspe3ZhciBsPVBlKGVbc11bMF0pLHU9a2UoZVtzXVsxXSk7dC5wdXNoKGwpLHQucHVzaCh1KSx0LnB1c2goMCkscz4wJiYoYSs9cj8obip1LWwqbykvMjpNYXRoLnNxcnQoTWF0aC5wb3cobC1uLDIpK01hdGgucG93KHUtbywyKSkpLG49bCxvPXU7fXZhciBoPXQubGVuZ3RoLTM7dFsyXT0xLGZ1bmN0aW9uIGUodCxpLHIsbil7Zm9yKHZhciBvLGE9bixzPXRbaV0sbD10W2krMV0sdT10W3JdLGg9dFtyKzFdLGM9aSszO2M8cjtjKz0zKXt2YXIgZj1TZSh0W2NdLHRbYysxXSxzLGwsdSxoKTtmPmEmJihvPWMsYT1mKTt9YT5uJiYoby1pPjMmJmUodCxpLG8sbiksdFtvKzJdPWEsci1vPjMmJmUodCxvLHIsbikpO30odCwwLGgsaSksdFtoKzJdPTEsdC5zaXplPU1hdGguYWJzKGEpLHQuc3RhcnQ9MCx0LmVuZD10LnNpemU7fWZ1bmN0aW9uIFRlKGUsdCxpLHIpe2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bisrKXt2YXIgbz1bXTt6ZShlW25dLG8saSxyKSx0LnB1c2gobyk7fX1mdW5jdGlvbiBQZShlKXtyZXR1cm4gZS8zNjArLjV9ZnVuY3Rpb24ga2UoZSl7dmFyIHQ9TWF0aC5zaW4oZSpNYXRoLlBJLzE4MCksaT0uNS0uMjUqTWF0aC5sb2coKDErdCkvKDEtdCkpL01hdGguUEk7cmV0dXJuIGk8MD8wOmk+MT8xOml9ZnVuY3Rpb24gTGUoZSx0LGkscixuLG8sYSxzKXtpZihyLz10LG8+PShpLz10KSYmYTw9cilyZXR1cm4gZTtpZihvPnJ8fGE8aSlyZXR1cm4gbnVsbDtmb3IodmFyIGw9W10sdT0wO3U8ZS5sZW5ndGg7dSsrKXt2YXIgaD1lW3VdLGM9aC5nZW9tZXRyeSxmPWgudHlwZSxwPTA9PT1uP2gubWluWDpoLm1pblksZD0wPT09bj9oLm1heFg6aC5tYXhZO2lmKHA+PWkmJmQ8PXIpbC5wdXNoKGgpO2Vsc2UgaWYoIShwPnJ8fGQ8aSkpe3ZhciBnPVtdO2lmKFwiUG9pbnRcIj09PWZ8fFwiTXVsdGlQb2ludFwiPT09ZikkZShjLGcsaSxyLG4pO2Vsc2UgaWYoXCJMaW5lU3RyaW5nXCI9PT1mKURlKGMsZyxpLHIsbiwhMSxzLmxpbmVNZXRyaWNzKTtlbHNlIGlmKFwiTXVsdGlMaW5lU3RyaW5nXCI9PT1mKUNlKGMsZyxpLHIsbiwhMSk7ZWxzZSBpZihcIlBvbHlnb25cIj09PWYpQ2UoYyxnLGkscixuLCEwKTtlbHNlIGlmKFwiTXVsdGlQb2x5Z29uXCI9PT1mKWZvcih2YXIgdj0wO3Y8Yy5sZW5ndGg7disrKXt2YXIgeT1bXTtDZShjW3ZdLHksaSxyLG4sITApLHkubGVuZ3RoJiZnLnB1c2goeSk7fWlmKGcubGVuZ3RoKXtpZihzLmxpbmVNZXRyaWNzJiZcIkxpbmVTdHJpbmdcIj09PWYpe2Zvcih2PTA7djxnLmxlbmd0aDt2KyspbC5wdXNoKE1lKGguaWQsZixnW3ZdLGgudGFncykpO2NvbnRpbnVlfVwiTGluZVN0cmluZ1wiIT09ZiYmXCJNdWx0aUxpbmVTdHJpbmdcIiE9PWZ8fCgxPT09Zy5sZW5ndGg/KGY9XCJMaW5lU3RyaW5nXCIsZz1nWzBdKTpmPVwiTXVsdGlMaW5lU3RyaW5nXCIpLFwiUG9pbnRcIiE9PWYmJlwiTXVsdGlQb2ludFwiIT09Znx8KGY9Mz09PWcubGVuZ3RoP1wiUG9pbnRcIjpcIk11bHRpUG9pbnRcIiksbC5wdXNoKE1lKGguaWQsZixnLGgudGFncykpO319fXJldHVybiBsLmxlbmd0aD9sOm51bGx9ZnVuY3Rpb24gJGUoZSx0LGkscixuKXtmb3IodmFyIG89MDtvPGUubGVuZ3RoO28rPTMpe3ZhciBhPWVbbytuXTthPj1pJiZhPD1yJiYodC5wdXNoKGVbb10pLHQucHVzaChlW28rMV0pLHQucHVzaChlW28rMl0pKTt9fWZ1bmN0aW9uIERlKGUsdCxpLHIsbixvLGEpe2Zvcih2YXIgcyxsLHU9T2UoZSksaD0wPT09bj9FZTpOZSxjPWUuc3RhcnQsZj0wO2Y8ZS5sZW5ndGgtMztmKz0zKXt2YXIgcD1lW2ZdLGQ9ZVtmKzFdLGc9ZVtmKzJdLHY9ZVtmKzNdLHk9ZVtmKzRdLG09MD09PW4/cDpkLHg9MD09PW4/djp5LHc9ITE7YSYmKHM9TWF0aC5zcXJ0KE1hdGgucG93KHAtdiwyKStNYXRoLnBvdyhkLXksMikpKSxtPGk/eD49aSYmKGw9aCh1LHAsZCx2LHksaSksYSYmKHUuc3RhcnQ9YytzKmwpKTptPnI/eDw9ciYmKGw9aCh1LHAsZCx2LHksciksYSYmKHUuc3RhcnQ9YytzKmwpKTpBZSh1LHAsZCxnKSx4PGkmJm0+PWkmJihsPWgodSxwLGQsdix5LGkpLHc9ITApLHg+ciYmbTw9ciYmKGw9aCh1LHAsZCx2LHksciksdz0hMCksIW8mJncmJihhJiYodS5lbmQ9YytzKmwpLHQucHVzaCh1KSx1PU9lKGUpKSxhJiYoYys9cyk7fXZhciBTPWUubGVuZ3RoLTM7cD1lW1NdLGQ9ZVtTKzFdLGc9ZVtTKzJdLChtPTA9PT1uP3A6ZCk+PWkmJm08PXImJkFlKHUscCxkLGcpLFM9dS5sZW5ndGgtMyxvJiZTPj0zJiYodVtTXSE9PXVbMF18fHVbUysxXSE9PXVbMV0pJiZBZSh1LHVbMF0sdVsxXSx1WzJdKSx1Lmxlbmd0aCYmdC5wdXNoKHUpO31mdW5jdGlvbiBPZShlKXt2YXIgdD1bXTtyZXR1cm4gdC5zaXplPWUuc2l6ZSx0LnN0YXJ0PWUuc3RhcnQsdC5lbmQ9ZS5lbmQsdH1mdW5jdGlvbiBDZShlLHQsaSxyLG4sbyl7Zm9yKHZhciBhPTA7YTxlLmxlbmd0aDthKyspRGUoZVthXSx0LGkscixuLG8sITEpO31mdW5jdGlvbiBBZShlLHQsaSxyKXtlLnB1c2godCksZS5wdXNoKGkpLGUucHVzaChyKTt9ZnVuY3Rpb24gRWUoZSx0LGkscixuLG8pe3ZhciBhPShvLXQpLyhyLXQpO3JldHVybiBlLnB1c2gobyksZS5wdXNoKGkrKG4taSkqYSksZS5wdXNoKDEpLGF9ZnVuY3Rpb24gTmUoZSx0LGkscixuLG8pe3ZhciBhPShvLWkpLyhuLWkpO3JldHVybiBlLnB1c2godCsoci10KSphKSxlLnB1c2gobyksZS5wdXNoKDEpLGF9ZnVuY3Rpb24gUmUoZSx0KXtmb3IodmFyIGk9W10scj0wO3I8ZS5sZW5ndGg7cisrKXt2YXIgbixvPWVbcl0sYT1vLnR5cGU7aWYoXCJQb2ludFwiPT09YXx8XCJNdWx0aVBvaW50XCI9PT1hfHxcIkxpbmVTdHJpbmdcIj09PWEpbj1CZShvLmdlb21ldHJ5LHQpO2Vsc2UgaWYoXCJNdWx0aUxpbmVTdHJpbmdcIj09PWF8fFwiUG9seWdvblwiPT09YSl7bj1bXTtmb3IodmFyIHM9MDtzPG8uZ2VvbWV0cnkubGVuZ3RoO3MrKyluLnB1c2goQmUoby5nZW9tZXRyeVtzXSx0KSk7fWVsc2UgaWYoXCJNdWx0aVBvbHlnb25cIj09PWEpZm9yKG49W10scz0wO3M8by5nZW9tZXRyeS5sZW5ndGg7cysrKXtmb3IodmFyIGw9W10sdT0wO3U8by5nZW9tZXRyeVtzXS5sZW5ndGg7dSsrKWwucHVzaChCZShvLmdlb21ldHJ5W3NdW3VdLHQpKTtuLnB1c2gobCk7fWkucHVzaChNZShvLmlkLGEsbixvLnRhZ3MpKTt9cmV0dXJuIGl9ZnVuY3Rpb24gQmUoZSx0KXt2YXIgaT1bXTtpLnNpemU9ZS5zaXplLHZvaWQgMCE9PWUuc3RhcnQmJihpLnN0YXJ0PWUuc3RhcnQsaS5lbmQ9ZS5lbmQpO2Zvcih2YXIgcj0wO3I8ZS5sZW5ndGg7cis9MylpLnB1c2goZVtyXSt0LGVbcisxXSxlW3IrMl0pO3JldHVybiBpfWZ1bmN0aW9uIEZlKGUsdCl7aWYoZS50cmFuc2Zvcm1lZClyZXR1cm4gZTt2YXIgaSxyLG4sbz0xPDxlLnosYT1lLngscz1lLnk7Zm9yKGk9MDtpPGUuZmVhdHVyZXMubGVuZ3RoO2krKyl7dmFyIGw9ZS5mZWF0dXJlc1tpXSx1PWwuZ2VvbWV0cnksaD1sLnR5cGU7aWYobC5nZW9tZXRyeT1bXSwxPT09aClmb3Iocj0wO3I8dS5sZW5ndGg7cis9MilsLmdlb21ldHJ5LnB1c2goR2UodVtyXSx1W3IrMV0sdCxvLGEscykpO2Vsc2UgZm9yKHI9MDtyPHUubGVuZ3RoO3IrKyl7dmFyIGM9W107Zm9yKG49MDtuPHVbcl0ubGVuZ3RoO24rPTIpYy5wdXNoKEdlKHVbcl1bbl0sdVtyXVtuKzFdLHQsbyxhLHMpKTtsLmdlb21ldHJ5LnB1c2goYyk7fX1yZXR1cm4gZS50cmFuc2Zvcm1lZD0hMCxlfWZ1bmN0aW9uIEdlKGUsdCxpLHIsbixvKXtyZXR1cm5bTWF0aC5yb3VuZChpKihlKnItbikpLE1hdGgucm91bmQoaSoodCpyLW8pKV19ZnVuY3Rpb24gVmUoZSx0LGkscixuKXtmb3IodmFyIG89dD09PW4ubWF4Wm9vbT8wOm4udG9sZXJhbmNlLygoMTw8dCkqbi5leHRlbnQpLGE9e2ZlYXR1cmVzOltdLG51bVBvaW50czowLG51bVNpbXBsaWZpZWQ6MCxudW1GZWF0dXJlczowLHNvdXJjZTpudWxsLHg6aSx5OnIsejp0LHRyYW5zZm9ybWVkOiExLG1pblg6MixtaW5ZOjEsbWF4WDotMSxtYXhZOjB9LHM9MDtzPGUubGVuZ3RoO3MrKyl7YS5udW1GZWF0dXJlcysrLEplKGEsZVtzXSxvLG4pO3ZhciBsPWVbc10ubWluWCx1PWVbc10ubWluWSxoPWVbc10ubWF4WCxjPWVbc10ubWF4WTtsPGEubWluWCYmKGEubWluWD1sKSx1PGEubWluWSYmKGEubWluWT11KSxoPmEubWF4WCYmKGEubWF4WD1oKSxjPmEubWF4WSYmKGEubWF4WT1jKTt9cmV0dXJuIGF9ZnVuY3Rpb24gSmUoZSx0LGkscil7dmFyIG49dC5nZW9tZXRyeSxvPXQudHlwZSxhPVtdO2lmKFwiUG9pbnRcIj09PW98fFwiTXVsdGlQb2ludFwiPT09bylmb3IodmFyIHM9MDtzPG4ubGVuZ3RoO3MrPTMpYS5wdXNoKG5bc10pLGEucHVzaChuW3MrMV0pLGUubnVtUG9pbnRzKyssZS5udW1TaW1wbGlmaWVkKys7ZWxzZSBpZihcIkxpbmVTdHJpbmdcIj09PW8pV2UoYSxuLGUsaSwhMSwhMSk7ZWxzZSBpZihcIk11bHRpTGluZVN0cmluZ1wiPT09b3x8XCJQb2x5Z29uXCI9PT1vKWZvcihzPTA7czxuLmxlbmd0aDtzKyspV2UoYSxuW3NdLGUsaSxcIlBvbHlnb25cIj09PW8sMD09PXMpO2Vsc2UgaWYoXCJNdWx0aVBvbHlnb25cIj09PW8pZm9yKHZhciBsPTA7bDxuLmxlbmd0aDtsKyspe3ZhciB1PW5bbF07Zm9yKHM9MDtzPHUubGVuZ3RoO3MrKylXZShhLHVbc10sZSxpLCEwLDA9PT1zKTt9aWYoYS5sZW5ndGgpe3ZhciBoPXQudGFnc3x8bnVsbDtpZihcIkxpbmVTdHJpbmdcIj09PW8mJnIubGluZU1ldHJpY3Mpe2Zvcih2YXIgYyBpbiBoPXt9LHQudGFncyloW2NdPXQudGFnc1tjXTtoLm1hcGJveF9jbGlwX3N0YXJ0PW4uc3RhcnQvbi5zaXplLGgubWFwYm94X2NsaXBfZW5kPW4uZW5kL24uc2l6ZTt9dmFyIGY9e2dlb21ldHJ5OmEsdHlwZTpcIlBvbHlnb25cIj09PW98fFwiTXVsdGlQb2x5Z29uXCI9PT1vPzM6XCJMaW5lU3RyaW5nXCI9PT1vfHxcIk11bHRpTGluZVN0cmluZ1wiPT09bz8yOjEsdGFnczpofTtudWxsIT09dC5pZCYmKGYuaWQ9dC5pZCksZS5mZWF0dXJlcy5wdXNoKGYpO319ZnVuY3Rpb24gV2UoZSx0LGkscixuLG8pe3ZhciBhPXIqcjtpZihyPjAmJnQuc2l6ZTwobj9hOnIpKWkubnVtUG9pbnRzKz10Lmxlbmd0aC8zO2Vsc2V7Zm9yKHZhciBzPVtdLGw9MDtsPHQubGVuZ3RoO2wrPTMpKDA9PT1yfHx0W2wrMl0+YSkmJihpLm51bVNpbXBsaWZpZWQrKyxzLnB1c2godFtsXSkscy5wdXNoKHRbbCsxXSkpLGkubnVtUG9pbnRzKys7biYmZnVuY3Rpb24oZSx0KXtmb3IodmFyIGk9MCxyPTAsbj1lLmxlbmd0aCxvPW4tMjtyPG47bz1yLHIrPTIpaSs9KGVbcl0tZVtvXSkqKGVbcisxXStlW28rMV0pO2lmKGk+MD09PXQpZm9yKHI9MCxuPWUubGVuZ3RoO3I8bi8yO3IrPTIpe3ZhciBhPWVbcl0scz1lW3IrMV07ZVtyXT1lW24tMi1yXSxlW3IrMV09ZVtuLTEtcl0sZVtuLTItcl09YSxlW24tMS1yXT1zO319KHMsbyksZS5wdXNoKHMpO319ZnVuY3Rpb24gWWUoZSx0KXt2YXIgaT0odD10aGlzLm9wdGlvbnM9ZnVuY3Rpb24oZSx0KXtmb3IodmFyIGkgaW4gdCllW2ldPXRbaV07cmV0dXJuIGV9KE9iamVjdC5jcmVhdGUodGhpcy5vcHRpb25zKSx0KSkuZGVidWc7aWYoaSYmY29uc29sZS50aW1lKFwicHJlcHJvY2VzcyBkYXRhXCIpLHQubWF4Wm9vbTwwfHx0Lm1heFpvb20+MjQpdGhyb3cgbmV3IEVycm9yKFwibWF4Wm9vbSBzaG91bGQgYmUgaW4gdGhlIDAtMjQgcmFuZ2VcIik7dmFyIHI9ZnVuY3Rpb24oZSx0KXt2YXIgaT1bXTtpZihcIkZlYXR1cmVDb2xsZWN0aW9uXCI9PT1lLnR5cGUpZm9yKHZhciByPTA7cjxlLmZlYXR1cmVzLmxlbmd0aDtyKyspX2UoaSxlLmZlYXR1cmVzW3JdLHQpO2Vsc2VcIkZlYXR1cmVcIj09PWUudHlwZT9fZShpLGUsdCk6X2UoaSx7Z2VvbWV0cnk6ZX0sdCk7cmV0dXJuIGl9KGUsdCk7dGhpcy50aWxlcz17fSx0aGlzLnRpbGVDb29yZHM9W10saSYmKGNvbnNvbGUudGltZUVuZChcInByZXByb2Nlc3MgZGF0YVwiKSxjb25zb2xlLmxvZyhcImluZGV4OiBtYXhab29tOiAlZCwgbWF4UG9pbnRzOiAlZFwiLHQuaW5kZXhNYXhab29tLHQuaW5kZXhNYXhQb2ludHMpLGNvbnNvbGUudGltZShcImdlbmVyYXRlIHRpbGVzXCIpLHRoaXMuc3RhdHM9e30sdGhpcy50b3RhbD0wKSwocj1mdW5jdGlvbihlLHQpe3ZhciBpPXQuYnVmZmVyL3QuZXh0ZW50LHI9ZSxuPUxlKGUsMSwtMS1pLGksMCwtMSwyLHQpLG89TGUoZSwxLDEtaSwyK2ksMCwtMSwyLHQpO3JldHVybihufHxvKSYmKHI9TGUoZSwxLC1pLDEraSwwLC0xLDIsdCl8fFtdLG4mJihyPVJlKG4sMSkuY29uY2F0KHIpKSxvJiYocj1yLmNvbmNhdChSZShvLC0xKSkpKSxyfShyLHQpKS5sZW5ndGgmJnRoaXMuc3BsaXRUaWxlKHIsMCwwLDApLGkmJihyLmxlbmd0aCYmY29uc29sZS5sb2coXCJmZWF0dXJlczogJWQsIHBvaW50czogJWRcIix0aGlzLnRpbGVzWzBdLm51bUZlYXR1cmVzLHRoaXMudGlsZXNbMF0ubnVtUG9pbnRzKSxjb25zb2xlLnRpbWVFbmQoXCJnZW5lcmF0ZSB0aWxlc1wiKSxjb25zb2xlLmxvZyhcInRpbGVzIGdlbmVyYXRlZDpcIix0aGlzLnRvdGFsLEpTT04uc3RyaW5naWZ5KHRoaXMuc3RhdHMpKSk7fWZ1bmN0aW9uIFplKGUsdCxpKXtyZXR1cm4gMzIqKCgxPDxlKSppK3QpK2V9ZnVuY3Rpb24gamUoZSx0KXt2YXIgaT1lLnRpbGVJRC5jYW5vbmljYWw7aWYoIXRoaXMuX2dlb0pTT05JbmRleClyZXR1cm4gdChudWxsLG51bGwpO3ZhciByPXRoaXMuX2dlb0pTT05JbmRleC5nZXRUaWxlKGkueixpLngsaS55KTtpZighcilyZXR1cm4gdChudWxsLG51bGwpO3ZhciBuPW5ldyBOKHIuZmVhdHVyZXMpLG89VihuKTswPT09by5ieXRlT2Zmc2V0JiZvLmJ5dGVMZW5ndGg9PT1vLmJ1ZmZlci5ieXRlTGVuZ3RofHwobz1uZXcgVWludDhBcnJheShvKSksdChudWxsLHt2ZWN0b3JUaWxlOm4scmF3RGF0YTpvLmJ1ZmZlcn0pO31jZS5wcm90b3R5cGU9e29wdGlvbnM6e21pblpvb206MCxtYXhab29tOjE2LHJhZGl1czo0MCxleHRlbnQ6NTEyLG5vZGVTaXplOjY0LGxvZzohMSxyZWR1Y2U6bnVsbCxpbml0aWFsOmZ1bmN0aW9uKCl7cmV0dXJue319LG1hcDpmdW5jdGlvbihlKXtyZXR1cm4gZX19LGxvYWQ6ZnVuY3Rpb24oZSl7dmFyIHQ9dGhpcy5vcHRpb25zLmxvZzt0JiZjb25zb2xlLnRpbWUoXCJ0b3RhbCB0aW1lXCIpO3ZhciBpPVwicHJlcGFyZSBcIitlLmxlbmd0aCtcIiBwb2ludHNcIjt0JiZjb25zb2xlLnRpbWUoaSksdGhpcy5wb2ludHM9ZTt2YXIgcj1lLm1hcChwZSk7dCYmY29uc29sZS50aW1lRW5kKGkpO2Zvcih2YXIgbj10aGlzLm9wdGlvbnMubWF4Wm9vbTtuPj10aGlzLm9wdGlvbnMubWluWm9vbTtuLS0pe3ZhciBvPStEYXRlLm5vdygpO3RoaXMudHJlZXNbbisxXT1hZShyLHhlLHdlLHRoaXMub3B0aW9ucy5ub2RlU2l6ZSxGbG9hdDMyQXJyYXkpLHI9dGhpcy5fY2x1c3RlcihyLG4pLHQmJmNvbnNvbGUubG9nKFwieiVkOiAlZCBjbHVzdGVycyBpbiAlZG1zXCIsbixyLmxlbmd0aCwrRGF0ZS5ub3coKS1vKTt9cmV0dXJuIHRoaXMudHJlZXNbdGhpcy5vcHRpb25zLm1pblpvb21dPWFlKHIseGUsd2UsdGhpcy5vcHRpb25zLm5vZGVTaXplLEZsb2F0MzJBcnJheSksdCYmY29uc29sZS50aW1lRW5kKFwidG90YWwgdGltZVwiKSx0aGlzfSxnZXRDbHVzdGVyczpmdW5jdGlvbihlLHQpe2Zvcih2YXIgaT10aGlzLnRyZWVzW3RoaXMuX2xpbWl0Wm9vbSh0KV0scj1pLnJhbmdlKHZlKGVbMF0pLHllKGVbM10pLHZlKGVbMl0pLHllKGVbMV0pKSxuPVtdLG89MDtvPHIubGVuZ3RoO28rKyl7dmFyIGE9aS5wb2ludHNbcltvXV07bi5wdXNoKGEubnVtUG9pbnRzP2RlKGEpOnRoaXMucG9pbnRzW2EuaWRdKTt9cmV0dXJuIG59LGdldENoaWxkcmVuOmZ1bmN0aW9uKGUsdCl7Zm9yKHZhciBpPXRoaXMudHJlZXNbdCsxXS5wb2ludHNbZV0scj10aGlzLm9wdGlvbnMucmFkaXVzLyh0aGlzLm9wdGlvbnMuZXh0ZW50Kk1hdGgucG93KDIsdCkpLG49dGhpcy50cmVlc1t0KzFdLndpdGhpbihpLngsaS55LHIpLG89W10sYT0wO2E8bi5sZW5ndGg7YSsrKXt2YXIgcz10aGlzLnRyZWVzW3QrMV0ucG9pbnRzW25bYV1dO3MucGFyZW50SWQ9PT1lJiZvLnB1c2gocy5udW1Qb2ludHM/ZGUocyk6dGhpcy5wb2ludHNbcy5pZF0pO31yZXR1cm4gb30sZ2V0TGVhdmVzOmZ1bmN0aW9uKGUsdCxpLHIpe2k9aXx8MTAscj1yfHwwO3ZhciBuPVtdO3JldHVybiB0aGlzLl9hcHBlbmRMZWF2ZXMobixlLHQsaSxyLDApLG59LGdldFRpbGU6ZnVuY3Rpb24oZSx0LGkpe3ZhciByPXRoaXMudHJlZXNbdGhpcy5fbGltaXRab29tKGUpXSxuPU1hdGgucG93KDIsZSksbz10aGlzLm9wdGlvbnMuZXh0ZW50LGE9dGhpcy5vcHRpb25zLnJhZGl1cy9vLHM9KGktYSkvbixsPShpKzErYSkvbix1PXtmZWF0dXJlczpbXX07cmV0dXJuIHRoaXMuX2FkZFRpbGVGZWF0dXJlcyhyLnJhbmdlKCh0LWEpL24scywodCsxK2EpL24sbCksci5wb2ludHMsdCxpLG4sdSksMD09PXQmJnRoaXMuX2FkZFRpbGVGZWF0dXJlcyhyLnJhbmdlKDEtYS9uLHMsMSxsKSxyLnBvaW50cyxuLGksbix1KSx0PT09bi0xJiZ0aGlzLl9hZGRUaWxlRmVhdHVyZXMoci5yYW5nZSgwLHMsYS9uLGwpLHIucG9pbnRzLC0xLGksbix1KSx1LmZlYXR1cmVzLmxlbmd0aD91Om51bGx9LGdldENsdXN0ZXJFeHBhbnNpb25ab29tOmZ1bmN0aW9uKGUsdCl7Zm9yKDt0PHRoaXMub3B0aW9ucy5tYXhab29tOyl7dmFyIGk9dGhpcy5nZXRDaGlsZHJlbihlLHQpO2lmKHQrKywxIT09aS5sZW5ndGgpYnJlYWs7ZT1pWzBdLnByb3BlcnRpZXMuY2x1c3Rlcl9pZDt9cmV0dXJuIHR9LF9hcHBlbmRMZWF2ZXM6ZnVuY3Rpb24oZSx0LGkscixuLG8pe2Zvcih2YXIgYT10aGlzLmdldENoaWxkcmVuKHQsaSkscz0wO3M8YS5sZW5ndGg7cysrKXt2YXIgbD1hW3NdLnByb3BlcnRpZXM7aWYobC5jbHVzdGVyP28rbC5wb2ludF9jb3VudDw9bj9vKz1sLnBvaW50X2NvdW50Om89dGhpcy5fYXBwZW5kTGVhdmVzKGUsbC5jbHVzdGVyX2lkLGkrMSxyLG4sbyk6bzxuP28rKzplLnB1c2goYVtzXSksZS5sZW5ndGg9PT1yKWJyZWFrfXJldHVybiBvfSxfYWRkVGlsZUZlYXR1cmVzOmZ1bmN0aW9uKGUsdCxpLHIsbixvKXtmb3IodmFyIGE9MDthPGUubGVuZ3RoO2ErKyl7dmFyIHM9dFtlW2FdXTtvLmZlYXR1cmVzLnB1c2goe3R5cGU6MSxnZW9tZXRyeTpbW01hdGgucm91bmQodGhpcy5vcHRpb25zLmV4dGVudCoocy54Km4taSkpLE1hdGgucm91bmQodGhpcy5vcHRpb25zLmV4dGVudCoocy55Km4tcikpXV0sdGFnczpzLm51bVBvaW50cz9nZShzKTp0aGlzLnBvaW50c1tzLmlkXS5wcm9wZXJ0aWVzfSk7fX0sX2xpbWl0Wm9vbTpmdW5jdGlvbihlKXtyZXR1cm4gTWF0aC5tYXgodGhpcy5vcHRpb25zLm1pblpvb20sTWF0aC5taW4oZSx0aGlzLm9wdGlvbnMubWF4Wm9vbSsxKSl9LF9jbHVzdGVyOmZ1bmN0aW9uKGUsdCl7Zm9yKHZhciBpPVtdLHI9dGhpcy5vcHRpb25zLnJhZGl1cy8odGhpcy5vcHRpb25zLmV4dGVudCpNYXRoLnBvdygyLHQpKSxuPTA7bjxlLmxlbmd0aDtuKyspe3ZhciBvPWVbbl07aWYoIShvLnpvb208PXQpKXtvLnpvb209dDt2YXIgYT10aGlzLnRyZWVzW3QrMV0scz1hLndpdGhpbihvLngsby55LHIpLGw9by5udW1Qb2ludHN8fDEsdT1vLngqbCxoPW8ueSpsLGM9bnVsbDt0aGlzLm9wdGlvbnMucmVkdWNlJiYoYz10aGlzLm9wdGlvbnMuaW5pdGlhbCgpLHRoaXMuX2FjY3VtdWxhdGUoYyxvKSk7Zm9yKHZhciBmPTA7ZjxzLmxlbmd0aDtmKyspe3ZhciBwPWEucG9pbnRzW3NbZl1dO2lmKHQ8cC56b29tKXt2YXIgZD1wLm51bVBvaW50c3x8MTtwLnpvb209dCx1Kz1wLngqZCxoKz1wLnkqZCxsKz1kLHAucGFyZW50SWQ9bix0aGlzLm9wdGlvbnMucmVkdWNlJiZ0aGlzLl9hY2N1bXVsYXRlKGMscCk7fX0xPT09bD9pLnB1c2gobyk6KG8ucGFyZW50SWQ9bixpLnB1c2goZmUodS9sLGgvbCxsLG4sYykpKTt9fXJldHVybiBpfSxfYWNjdW11bGF0ZTpmdW5jdGlvbihlLHQpe3ZhciBpPXQubnVtUG9pbnRzP3QucHJvcGVydGllczp0aGlzLm9wdGlvbnMubWFwKHRoaXMucG9pbnRzW3QuaWRdLnByb3BlcnRpZXMpO3RoaXMub3B0aW9ucy5yZWR1Y2UoZSxpKTt9fSxZZS5wcm90b3R5cGUub3B0aW9ucz17bWF4Wm9vbToxNCxpbmRleE1heFpvb206NSxpbmRleE1heFBvaW50czoxZTUsdG9sZXJhbmNlOjMsZXh0ZW50OjQwOTYsYnVmZmVyOjY0LGxpbmVNZXRyaWNzOiExLGRlYnVnOjB9LFllLnByb3RvdHlwZS5zcGxpdFRpbGU9ZnVuY3Rpb24oZSx0LGkscixuLG8sYSl7Zm9yKHZhciBzPVtlLHQsaSxyXSxsPXRoaXMub3B0aW9ucyx1PWwuZGVidWc7cy5sZW5ndGg7KXtyPXMucG9wKCksaT1zLnBvcCgpLHQ9cy5wb3AoKSxlPXMucG9wKCk7dmFyIGg9MTw8dCxjPVplKHQsaSxyKSxmPXRoaXMudGlsZXNbY107aWYoIWYmJih1PjEmJmNvbnNvbGUudGltZShcImNyZWF0aW9uXCIpLGY9dGhpcy50aWxlc1tjXT1WZShlLHQsaSxyLGwpLHRoaXMudGlsZUNvb3Jkcy5wdXNoKHt6OnQseDppLHk6cn0pLHUpKXt1PjEmJihjb25zb2xlLmxvZyhcInRpbGUgeiVkLSVkLSVkIChmZWF0dXJlczogJWQsIHBvaW50czogJWQsIHNpbXBsaWZpZWQ6ICVkKVwiLHQsaSxyLGYubnVtRmVhdHVyZXMsZi5udW1Qb2ludHMsZi5udW1TaW1wbGlmaWVkKSxjb25zb2xlLnRpbWVFbmQoXCJjcmVhdGlvblwiKSk7dmFyIHA9XCJ6XCIrdDt0aGlzLnN0YXRzW3BdPSh0aGlzLnN0YXRzW3BdfHwwKSsxLHRoaXMudG90YWwrKzt9aWYoZi5zb3VyY2U9ZSxuKXtpZih0PT09bC5tYXhab29tfHx0PT09biljb250aW51ZTt2YXIgZD0xPDxuLXQ7aWYoaSE9PU1hdGguZmxvb3Ioby9kKXx8ciE9PU1hdGguZmxvb3IoYS9kKSljb250aW51ZX1lbHNlIGlmKHQ9PT1sLmluZGV4TWF4Wm9vbXx8Zi5udW1Qb2ludHM8PWwuaW5kZXhNYXhQb2ludHMpY29udGludWU7aWYoZi5zb3VyY2U9bnVsbCwwIT09ZS5sZW5ndGgpe3U+MSYmY29uc29sZS50aW1lKFwiY2xpcHBpbmdcIik7dmFyIGcsdix5LG0seCx3LFM9LjUqbC5idWZmZXIvbC5leHRlbnQsTT0uNS1TLGI9LjUrUyxfPTErUztnPXY9eT1tPW51bGwseD1MZShlLGgsaS1TLGkrYiwwLGYubWluWCxmLm1heFgsbCksdz1MZShlLGgsaStNLGkrXywwLGYubWluWCxmLm1heFgsbCksZT1udWxsLHgmJihnPUxlKHgsaCxyLVMscitiLDEsZi5taW5ZLGYubWF4WSxsKSx2PUxlKHgsaCxyK00scitfLDEsZi5taW5ZLGYubWF4WSxsKSx4PW51bGwpLHcmJih5PUxlKHcsaCxyLVMscitiLDEsZi5taW5ZLGYubWF4WSxsKSxtPUxlKHcsaCxyK00scitfLDEsZi5taW5ZLGYubWF4WSxsKSx3PW51bGwpLHU+MSYmY29uc29sZS50aW1lRW5kKFwiY2xpcHBpbmdcIikscy5wdXNoKGd8fFtdLHQrMSwyKmksMipyKSxzLnB1c2godnx8W10sdCsxLDIqaSwyKnIrMSkscy5wdXNoKHl8fFtdLHQrMSwyKmkrMSwyKnIpLHMucHVzaChtfHxbXSx0KzEsMippKzEsMipyKzEpO319fSxZZS5wcm90b3R5cGUuZ2V0VGlsZT1mdW5jdGlvbihlLHQsaSl7dmFyIHI9dGhpcy5vcHRpb25zLG49ci5leHRlbnQsbz1yLmRlYnVnO2lmKGU8MHx8ZT4yNClyZXR1cm4gbnVsbDt2YXIgYT0xPDxlLHM9WmUoZSx0PSh0JWErYSklYSxpKTtpZih0aGlzLnRpbGVzW3NdKXJldHVybiBGZSh0aGlzLnRpbGVzW3NdLG4pO28+MSYmY29uc29sZS5sb2coXCJkcmlsbGluZyBkb3duIHRvIHolZC0lZC0lZFwiLGUsdCxpKTtmb3IodmFyIGwsdT1lLGg9dCxjPWk7IWwmJnU+MDspdS0tLGg9TWF0aC5mbG9vcihoLzIpLGM9TWF0aC5mbG9vcihjLzIpLGw9dGhpcy50aWxlc1taZSh1LGgsYyldO3JldHVybiBsJiZsLnNvdXJjZT8obz4xJiZjb25zb2xlLmxvZyhcImZvdW5kIHBhcmVudCB0aWxlIHolZC0lZC0lZFwiLHUsaCxjKSxvPjEmJmNvbnNvbGUudGltZShcImRyaWxsaW5nIGRvd25cIiksdGhpcy5zcGxpdFRpbGUobC5zb3VyY2UsdSxoLGMsZSx0LGkpLG8+MSYmY29uc29sZS50aW1lRW5kKFwiZHJpbGxpbmcgZG93blwiKSx0aGlzLnRpbGVzW3NdP0ZlKHRoaXMudGlsZXNbc10sbik6bnVsbCk6bnVsbH07dmFyIFhlPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGkoZSxpLHIpe3QuY2FsbCh0aGlzLGUsaSxqZSksciYmKHRoaXMubG9hZEdlb0pTT049cik7fXJldHVybiB0JiYoaS5fX3Byb3RvX189dCksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5sb2FkRGF0YT1mdW5jdGlvbihlLHQpe3RoaXMuX3BlbmRpbmdDYWxsYmFjayYmdGhpcy5fcGVuZGluZ0NhbGxiYWNrKG51bGwse2FiYW5kb25lZDohMH0pLHRoaXMuX3BlbmRpbmdDYWxsYmFjaz10LHRoaXMuX3BlbmRpbmdMb2FkRGF0YVBhcmFtcz1lLHRoaXMuX3N0YXRlJiZcIklkbGVcIiE9PXRoaXMuX3N0YXRlP3RoaXMuX3N0YXRlPVwiTmVlZHNMb2FkRGF0YVwiOih0aGlzLl9zdGF0ZT1cIkNvYWxlc2NpbmdcIix0aGlzLl9sb2FkRGF0YSgpKTt9LGkucHJvdG90eXBlLl9sb2FkRGF0YT1mdW5jdGlvbigpe3ZhciBlPXRoaXM7aWYodGhpcy5fcGVuZGluZ0NhbGxiYWNrJiZ0aGlzLl9wZW5kaW5nTG9hZERhdGFQYXJhbXMpe3ZhciB0PXRoaXMuX3BlbmRpbmdDYWxsYmFjayxpPXRoaXMuX3BlbmRpbmdMb2FkRGF0YVBhcmFtcztkZWxldGUgdGhpcy5fcGVuZGluZ0NhbGxiYWNrLGRlbGV0ZSB0aGlzLl9wZW5kaW5nTG9hZERhdGFQYXJhbXMsdGhpcy5sb2FkR2VvSlNPTihpLGZ1bmN0aW9uKHIsbil7aWYocnx8IW4pcmV0dXJuIHQocik7aWYoXCJvYmplY3RcIiE9dHlwZW9mIG4pcmV0dXJuIHQobmV3IEVycm9yKFwiSW5wdXQgZGF0YSBpcyBub3QgYSB2YWxpZCBHZW9KU09OIG9iamVjdC5cIikpOyQobiwhMCk7dHJ5e2UuX2dlb0pTT05JbmRleD1pLmNsdXN0ZXI/aGUoaS5zdXBlcmNsdXN0ZXJPcHRpb25zKS5sb2FkKG4uZmVhdHVyZXMpOmZ1bmN0aW9uKGUsdCl7cmV0dXJuIG5ldyBZZShlLHQpfShuLGkuZ2VvanNvblZ0T3B0aW9ucyk7fWNhdGNoKHIpe3JldHVybiB0KHIpfWUubG9hZGVkPXt9O3ZhciBvPXt9O2lmKGkucmVxdWVzdCYmaS5yZXF1ZXN0LmNvbGxlY3RSZXNvdXJjZVRpbWluZyl7dmFyIGE9TShpLnJlcXVlc3QudXJsKTthJiYoby5yZXNvdXJjZVRpbWluZz17fSxvLnJlc291cmNlVGltaW5nW2kuc291cmNlXT1KU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGEpKSk7fXQobnVsbCxvKTt9KTt9fSxpLnByb3RvdHlwZS5jb2FsZXNjZT1mdW5jdGlvbigpe1wiQ29hbGVzY2luZ1wiPT09dGhpcy5fc3RhdGU/dGhpcy5fc3RhdGU9XCJJZGxlXCI6XCJOZWVkc0xvYWREYXRhXCI9PT10aGlzLl9zdGF0ZSYmKHRoaXMuX3N0YXRlPVwiQ29hbGVzY2luZ1wiLHRoaXMuX2xvYWREYXRhKCkpO30saS5wcm90b3R5cGUucmVsb2FkVGlsZT1mdW5jdGlvbihlLGkpe3ZhciByPXRoaXMubG9hZGVkLG49ZS51aWQ7cmV0dXJuIHImJnJbbl0/dC5wcm90b3R5cGUucmVsb2FkVGlsZS5jYWxsKHRoaXMsZSxpKTp0aGlzLmxvYWRUaWxlKGUsaSl9LGkucHJvdG90eXBlLmxvYWRHZW9KU09OPWZ1bmN0aW9uKHQsaSl7aWYodC5yZXF1ZXN0KWUuZ2V0SlNPTih0LnJlcXVlc3QsaSk7ZWxzZXtpZihcInN0cmluZ1wiIT10eXBlb2YgdC5kYXRhKXJldHVybiBpKG5ldyBFcnJvcihcIklucHV0IGRhdGEgaXMgbm90IGEgdmFsaWQgR2VvSlNPTiBvYmplY3QuXCIpKTt0cnl7cmV0dXJuIGkobnVsbCxKU09OLnBhcnNlKHQuZGF0YSkpfWNhdGNoKGUpe3JldHVybiBpKG5ldyBFcnJvcihcIklucHV0IGRhdGEgaXMgbm90IGEgdmFsaWQgR2VvSlNPTiBvYmplY3QuXCIpKX19fSxpLnByb3RvdHlwZS5yZW1vdmVTb3VyY2U9ZnVuY3Rpb24oZSx0KXt0aGlzLl9wZW5kaW5nQ2FsbGJhY2smJnRoaXMuX3BlbmRpbmdDYWxsYmFjayhudWxsLHthYmFuZG9uZWQ6ITB9KSx0KCk7fSxpfShfKSxxZT1mdW5jdGlvbih0KXt2YXIgaT10aGlzO3RoaXMuc2VsZj10LHRoaXMuYWN0b3I9bmV3IGUuZGVmYXVsdCQ3KHQsdGhpcyksdGhpcy5sYXllckluZGV4ZXM9e30sdGhpcy53b3JrZXJTb3VyY2VUeXBlcz17dmVjdG9yOl8sZ2VvanNvbjpYZX0sdGhpcy53b3JrZXJTb3VyY2VzPXt9LHRoaXMuZGVtV29ya2VyU291cmNlcz17fSx0aGlzLnNlbGYucmVnaXN0ZXJXb3JrZXJTb3VyY2U9ZnVuY3Rpb24oZSx0KXtpZihpLndvcmtlclNvdXJjZVR5cGVzW2VdKXRocm93IG5ldyBFcnJvcignV29ya2VyIHNvdXJjZSB3aXRoIG5hbWUgXCInK2UrJ1wiIGFscmVhZHkgcmVnaXN0ZXJlZC4nKTtpLndvcmtlclNvdXJjZVR5cGVzW2VdPXQ7fSx0aGlzLnNlbGYucmVnaXN0ZXJSVExUZXh0UGx1Z2luPWZ1bmN0aW9uKHQpe2lmKGUucGx1Z2luLmlzTG9hZGVkKCkpdGhyb3cgbmV3IEVycm9yKFwiUlRMIHRleHQgcGx1Z2luIGFscmVhZHkgcmVnaXN0ZXJlZC5cIik7ZS5wbHVnaW4uYXBwbHlBcmFiaWNTaGFwaW5nPXQuYXBwbHlBcmFiaWNTaGFwaW5nLGUucGx1Z2luLnByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dD10LnByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dDt9O307cmV0dXJuIHFlLnByb3RvdHlwZS5zZXRMYXllcnM9ZnVuY3Rpb24oZSx0LGkpe3RoaXMuZ2V0TGF5ZXJJbmRleChlKS5yZXBsYWNlKHQpLGkoKTt9LHFlLnByb3RvdHlwZS51cGRhdGVMYXllcnM9ZnVuY3Rpb24oZSx0LGkpe3RoaXMuZ2V0TGF5ZXJJbmRleChlKS51cGRhdGUodC5sYXllcnMsdC5yZW1vdmVkSWRzKSxpKCk7fSxxZS5wcm90b3R5cGUubG9hZFRpbGU9ZnVuY3Rpb24oZSx0LGkpe3RoaXMuZ2V0V29ya2VyU291cmNlKGUsdC50eXBlLHQuc291cmNlKS5sb2FkVGlsZSh0LGkpO30scWUucHJvdG90eXBlLmxvYWRERU1UaWxlPWZ1bmN0aW9uKGUsdCxpKXt0aGlzLmdldERFTVdvcmtlclNvdXJjZShlLHQuc291cmNlKS5sb2FkVGlsZSh0LGkpO30scWUucHJvdG90eXBlLnJlbG9hZFRpbGU9ZnVuY3Rpb24oZSx0LGkpe3RoaXMuZ2V0V29ya2VyU291cmNlKGUsdC50eXBlLHQuc291cmNlKS5yZWxvYWRUaWxlKHQsaSk7fSxxZS5wcm90b3R5cGUuYWJvcnRUaWxlPWZ1bmN0aW9uKGUsdCxpKXt0aGlzLmdldFdvcmtlclNvdXJjZShlLHQudHlwZSx0LnNvdXJjZSkuYWJvcnRUaWxlKHQsaSk7fSxxZS5wcm90b3R5cGUucmVtb3ZlVGlsZT1mdW5jdGlvbihlLHQsaSl7dGhpcy5nZXRXb3JrZXJTb3VyY2UoZSx0LnR5cGUsdC5zb3VyY2UpLnJlbW92ZVRpbGUodCxpKTt9LHFlLnByb3RvdHlwZS5yZW1vdmVERU1UaWxlPWZ1bmN0aW9uKGUsdCl7dGhpcy5nZXRERU1Xb3JrZXJTb3VyY2UoZSx0LnNvdXJjZSkucmVtb3ZlVGlsZSh0KTt9LHFlLnByb3RvdHlwZS5yZW1vdmVTb3VyY2U9ZnVuY3Rpb24oZSx0LGkpe2lmKHRoaXMud29ya2VyU291cmNlc1tlXSYmdGhpcy53b3JrZXJTb3VyY2VzW2VdW3QudHlwZV0mJnRoaXMud29ya2VyU291cmNlc1tlXVt0LnR5cGVdW3Quc291cmNlXSl7dmFyIHI9dGhpcy53b3JrZXJTb3VyY2VzW2VdW3QudHlwZV1bdC5zb3VyY2VdO2RlbGV0ZSB0aGlzLndvcmtlclNvdXJjZXNbZV1bdC50eXBlXVt0LnNvdXJjZV0sdm9pZCAwIT09ci5yZW1vdmVTb3VyY2U/ci5yZW1vdmVTb3VyY2UodCxpKTppKCk7fX0scWUucHJvdG90eXBlLmxvYWRXb3JrZXJTb3VyY2U9ZnVuY3Rpb24oZSx0LGkpe3RyeXt0aGlzLnNlbGYuaW1wb3J0U2NyaXB0cyh0LnVybCksaSgpO31jYXRjaChlKXtpKGUudG9TdHJpbmcoKSk7fX0scWUucHJvdG90eXBlLmxvYWRSVExUZXh0UGx1Z2luPWZ1bmN0aW9uKHQsaSxyKXt0cnl7ZS5wbHVnaW4uaXNMb2FkZWQoKXx8KHRoaXMuc2VsZi5pbXBvcnRTY3JpcHRzKGkpLHIoZS5wbHVnaW4uaXNMb2FkZWQoKT9udWxsOm5ldyBFcnJvcihcIlJUTCBUZXh0IFBsdWdpbiBmYWlsZWQgdG8gaW1wb3J0IHNjcmlwdHMgZnJvbSBcIitpKSkpO31jYXRjaChlKXtyKGUudG9TdHJpbmcoKSk7fX0scWUucHJvdG90eXBlLmdldExheWVySW5kZXg9ZnVuY3Rpb24oZSl7dmFyIHQ9dGhpcy5sYXllckluZGV4ZXNbZV07cmV0dXJuIHR8fCh0PXRoaXMubGF5ZXJJbmRleGVzW2VdPW5ldyByKSx0fSxxZS5wcm90b3R5cGUuZ2V0V29ya2VyU291cmNlPWZ1bmN0aW9uKGUsdCxpKXt2YXIgcj10aGlzO2lmKHRoaXMud29ya2VyU291cmNlc1tlXXx8KHRoaXMud29ya2VyU291cmNlc1tlXT17fSksdGhpcy53b3JrZXJTb3VyY2VzW2VdW3RdfHwodGhpcy53b3JrZXJTb3VyY2VzW2VdW3RdPXt9KSwhdGhpcy53b3JrZXJTb3VyY2VzW2VdW3RdW2ldKXt2YXIgbj17c2VuZDpmdW5jdGlvbih0LGksbil7ci5hY3Rvci5zZW5kKHQsaSxuLGUpO319O3RoaXMud29ya2VyU291cmNlc1tlXVt0XVtpXT1uZXcgdGhpcy53b3JrZXJTb3VyY2VUeXBlc1t0XShuLHRoaXMuZ2V0TGF5ZXJJbmRleChlKSk7fXJldHVybiB0aGlzLndvcmtlclNvdXJjZXNbZV1bdF1baV19LHFlLnByb3RvdHlwZS5nZXRERU1Xb3JrZXJTb3VyY2U9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gdGhpcy5kZW1Xb3JrZXJTb3VyY2VzW2VdfHwodGhpcy5kZW1Xb3JrZXJTb3VyY2VzW2VdPXt9KSx0aGlzLmRlbVdvcmtlclNvdXJjZXNbZV1bdF18fCh0aGlzLmRlbVdvcmtlclNvdXJjZXNbZV1bdF09bmV3IEkpLHRoaXMuZGVtV29ya2VyU291cmNlc1tlXVt0XX0sXCJ1bmRlZmluZWRcIiE9dHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlJiZcInVuZGVmaW5lZFwiIT10eXBlb2Ygc2VsZiYmc2VsZiBpbnN0YW5jZW9mIFdvcmtlckdsb2JhbFNjb3BlJiZuZXcgcWUoc2VsZikscWV9KTtcblxuZGVmaW5lKFtcIi4vY2h1bmsxLmpzXCJdLGZ1bmN0aW9uKHQpe1widXNlIHN0cmljdFwiO3ZhciBlPXQuY3JlYXRlQ29tbW9uanNNb2R1bGUoZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0KXtyZXR1cm4hIShcInVuZGVmaW5lZFwiIT10eXBlb2Ygd2luZG93JiZcInVuZGVmaW5lZFwiIT10eXBlb2YgZG9jdW1lbnQmJkFycmF5LnByb3RvdHlwZSYmQXJyYXkucHJvdG90eXBlLmV2ZXJ5JiZBcnJheS5wcm90b3R5cGUuZmlsdGVyJiZBcnJheS5wcm90b3R5cGUuZm9yRWFjaCYmQXJyYXkucHJvdG90eXBlLmluZGV4T2YmJkFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZiYmQXJyYXkucHJvdG90eXBlLm1hcCYmQXJyYXkucHJvdG90eXBlLnNvbWUmJkFycmF5LnByb3RvdHlwZS5yZWR1Y2UmJkFycmF5LnByb3RvdHlwZS5yZWR1Y2VSaWdodCYmQXJyYXkuaXNBcnJheSYmRnVuY3Rpb24ucHJvdG90eXBlJiZGdW5jdGlvbi5wcm90b3R5cGUuYmluZCYmT2JqZWN0LmtleXMmJk9iamVjdC5jcmVhdGUmJk9iamVjdC5nZXRQcm90b3R5cGVPZiYmT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMmJk9iamVjdC5pc1NlYWxlZCYmT2JqZWN0LmlzRnJvemVuJiZPYmplY3QuaXNFeHRlbnNpYmxlJiZPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yJiZPYmplY3QuZGVmaW5lUHJvcGVydHkmJk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzJiZPYmplY3Quc2VhbCYmT2JqZWN0LmZyZWV6ZSYmT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zJiZcIkpTT05cImluIHdpbmRvdyYmXCJwYXJzZVwiaW4gSlNPTiYmXCJzdHJpbmdpZnlcImluIEpTT04mJmZ1bmN0aW9uKCl7aWYoIShcIldvcmtlclwiaW4gd2luZG93JiZcIkJsb2JcImluIHdpbmRvdyYmXCJVUkxcImluIHdpbmRvdykpcmV0dXJuITE7dmFyIHQsZSxpPW5ldyBCbG9iKFtcIlwiXSx7dHlwZTpcInRleHQvamF2YXNjcmlwdFwifSksbj1VUkwuY3JlYXRlT2JqZWN0VVJMKGkpO3RyeXtlPW5ldyBXb3JrZXIobiksdD0hMDt9Y2F0Y2goZSl7dD0hMTt9ZSYmZS50ZXJtaW5hdGUoKTtyZXR1cm4gVVJMLnJldm9rZU9iamVjdFVSTChuKSx0fSgpJiZcIlVpbnQ4Q2xhbXBlZEFycmF5XCJpbiB3aW5kb3cmJmZ1bmN0aW9uKHQpe3ZvaWQgMD09PWlbdF0mJihpW3RdPWZ1bmN0aW9uKHQpe3ZhciBpPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksbj1PYmplY3QuY3JlYXRlKGUud2ViR0xDb250ZXh0QXR0cmlidXRlcyk7cmV0dXJuIG4uZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdD10LGkucHJvYmFibHlTdXBwb3J0c0NvbnRleHQ/aS5wcm9iYWJseVN1cHBvcnRzQ29udGV4dChcIndlYmdsXCIsbil8fGkucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoXCJleHBlcmltZW50YWwtd2ViZ2xcIixuKTppLnN1cHBvcnRzQ29udGV4dD9pLnN1cHBvcnRzQ29udGV4dChcIndlYmdsXCIsbil8fGkuc3VwcG9ydHNDb250ZXh0KFwiZXhwZXJpbWVudGFsLXdlYmdsXCIsbik6aS5nZXRDb250ZXh0KFwid2ViZ2xcIixuKXx8aS5nZXRDb250ZXh0KFwiZXhwZXJpbWVudGFsLXdlYmdsXCIsbil9KHQpKTtyZXR1cm4gaVt0XX0odCYmdC5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0KSl9dC5leHBvcnRzP3QuZXhwb3J0cz1lOndpbmRvdyYmKHdpbmRvdy5tYXBib3hnbD13aW5kb3cubWFwYm94Z2x8fHt9LHdpbmRvdy5tYXBib3hnbC5zdXBwb3J0ZWQ9ZSk7dmFyIGk9e307ZS53ZWJHTENvbnRleHRBdHRyaWJ1dGVzPXthbnRpYWxpYXM6ITEsYWxwaGE6ITAsc3RlbmNpbDohMCxkZXB0aDohMH07fSksaT10LmRlZmF1bHQucGVyZm9ybWFuY2UmJnQuZGVmYXVsdC5wZXJmb3JtYW5jZS5ub3c/dC5kZWZhdWx0LnBlcmZvcm1hbmNlLm5vdy5iaW5kKHQuZGVmYXVsdC5wZXJmb3JtYW5jZSk6RGF0ZS5ub3cuYmluZChEYXRlKSxuPXQuZGVmYXVsdC5yZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fHQuZGVmYXVsdC5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fHQuZGVmYXVsdC53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fHQuZGVmYXVsdC5tc1JlcXVlc3RBbmltYXRpb25GcmFtZSxvPXQuZGVmYXVsdC5jYW5jZWxBbmltYXRpb25GcmFtZXx8dC5kZWZhdWx0Lm1vekNhbmNlbEFuaW1hdGlvbkZyYW1lfHx0LmRlZmF1bHQud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWV8fHQuZGVmYXVsdC5tc0NhbmNlbEFuaW1hdGlvbkZyYW1lLHI9e25vdzppLGZyYW1lOmZ1bmN0aW9uKHQpe3JldHVybiBuKHQpfSxjYW5jZWxGcmFtZTpmdW5jdGlvbih0KXtyZXR1cm4gbyh0KX0sZ2V0SW1hZ2VEYXRhOmZ1bmN0aW9uKGUpe3ZhciBpPXQuZGVmYXVsdC5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpLG49aS5nZXRDb250ZXh0KFwiMmRcIik7aWYoIW4pdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIGNyZWF0ZSBjYW52YXMgMmQgY29udGV4dFwiKTtyZXR1cm4gaS53aWR0aD1lLndpZHRoLGkuaGVpZ2h0PWUuaGVpZ2h0LG4uZHJhd0ltYWdlKGUsMCwwLGUud2lkdGgsZS5oZWlnaHQpLG4uZ2V0SW1hZ2VEYXRhKDAsMCxlLndpZHRoLGUuaGVpZ2h0KX0saGFyZHdhcmVDb25jdXJyZW5jeTp0LmRlZmF1bHQubmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3l8fDQsZ2V0IGRldmljZVBpeGVsUmF0aW8oKXtyZXR1cm4gdC5kZWZhdWx0LmRldmljZVBpeGVsUmF0aW99LHN1cHBvcnRzV2VicDohMX07aWYodC5kZWZhdWx0LmRvY3VtZW50KXt2YXIgYT10LmRlZmF1bHQuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImltZ1wiKTthLm9ubG9hZD1mdW5jdGlvbigpe3Iuc3VwcG9ydHNXZWJwPSEwO30sYS5zcmM9XCJkYXRhOmltYWdlL3dlYnA7YmFzZTY0LFVrbEdSaDRBQUFCWFJVSlFWbEE0VEJFQUFBQXZBUUFBQUFmUS8vNzN2LytCaU9oL0FBQT1cIjt9dmFyIHM9e2NyZWF0ZTpmdW5jdGlvbihlLGksbil7dmFyIG89dC5kZWZhdWx0LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoZSk7cmV0dXJuIGkmJihvLmNsYXNzTmFtZT1pKSxuJiZuLmFwcGVuZENoaWxkKG8pLG99LGNyZWF0ZU5TOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHQuZGVmYXVsdC5kb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoZSxpKX19LGw9dC5kZWZhdWx0LmRvY3VtZW50P3QuZGVmYXVsdC5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU6bnVsbDtmdW5jdGlvbiBjKHQpe2lmKCFsKXJldHVybiBudWxsO2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKWlmKHRbZV1pbiBsKXJldHVybiB0W2VdO3JldHVybiB0WzBdfXZhciB1LGg9YyhbXCJ1c2VyU2VsZWN0XCIsXCJNb3pVc2VyU2VsZWN0XCIsXCJXZWJraXRVc2VyU2VsZWN0XCIsXCJtc1VzZXJTZWxlY3RcIl0pO3MuZGlzYWJsZURyYWc9ZnVuY3Rpb24oKXtsJiZoJiYodT1sW2hdLGxbaF09XCJub25lXCIpO30scy5lbmFibGVEcmFnPWZ1bmN0aW9uKCl7bCYmaCYmKGxbaF09dSk7fTt2YXIgcD1jKFtcInRyYW5zZm9ybVwiLFwiV2Via2l0VHJhbnNmb3JtXCJdKTtzLnNldFRyYW5zZm9ybT1mdW5jdGlvbih0LGUpe3Quc3R5bGVbcF09ZTt9O3ZhciBkPSExO3RyeXt2YXIgZj1PYmplY3QuZGVmaW5lUHJvcGVydHkoe30sXCJwYXNzaXZlXCIse2dldDpmdW5jdGlvbigpe2Q9ITA7fX0pO3QuZGVmYXVsdC5hZGRFdmVudExpc3RlbmVyKFwidGVzdFwiLGYsZiksdC5kZWZhdWx0LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJ0ZXN0XCIsZixmKTt9Y2F0Y2godCl7ZD0hMTt9cy5hZGRFdmVudExpc3RlbmVyPWZ1bmN0aW9uKHQsZSxpLG4pe3ZvaWQgMD09PW4mJihuPXt9KSxcInBhc3NpdmVcImluIG4mJmQ/dC5hZGRFdmVudExpc3RlbmVyKGUsaSxuKTp0LmFkZEV2ZW50TGlzdGVuZXIoZSxpLG4uY2FwdHVyZSk7fSxzLnJlbW92ZUV2ZW50TGlzdGVuZXI9ZnVuY3Rpb24odCxlLGksbil7dm9pZCAwPT09biYmKG49e30pLFwicGFzc2l2ZVwiaW4gbiYmZD90LnJlbW92ZUV2ZW50TGlzdGVuZXIoZSxpLG4pOnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihlLGksbi5jYXB0dXJlKTt9O3ZhciBtPWZ1bmN0aW9uKGUpe2UucHJldmVudERlZmF1bHQoKSxlLnN0b3BQcm9wYWdhdGlvbigpLHQuZGVmYXVsdC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIixtLCEwKTt9O3Muc3VwcHJlc3NDbGljaz1mdW5jdGlvbigpe3QuZGVmYXVsdC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIixtLCEwKSx0LmRlZmF1bHQuc2V0VGltZW91dChmdW5jdGlvbigpe3QuZGVmYXVsdC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIixtLCEwKTt9LDApO30scy5tb3VzZVBvcz1mdW5jdGlvbihlLGkpe3ZhciBuPWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7cmV0dXJuIGk9aS50b3VjaGVzP2kudG91Y2hlc1swXTppLG5ldyB0LmRlZmF1bHQkMShpLmNsaWVudFgtbi5sZWZ0LWUuY2xpZW50TGVmdCxpLmNsaWVudFktbi50b3AtZS5jbGllbnRUb3ApfSxzLnRvdWNoUG9zPWZ1bmN0aW9uKGUsaSl7Zm9yKHZhciBuPWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksbz1bXSxyPVwidG91Y2hlbmRcIj09PWkudHlwZT9pLmNoYW5nZWRUb3VjaGVzOmkudG91Y2hlcyxhPTA7YTxyLmxlbmd0aDthKyspby5wdXNoKG5ldyB0LmRlZmF1bHQkMShyW2FdLmNsaWVudFgtbi5sZWZ0LWUuY2xpZW50TGVmdCxyW2FdLmNsaWVudFktbi50b3AtZS5jbGllbnRUb3ApKTtyZXR1cm4gb30scy5tb3VzZUJ1dHRvbj1mdW5jdGlvbihlKXtyZXR1cm4gdm9pZCAwIT09dC5kZWZhdWx0Lkluc3RhbGxUcmlnZ2VyJiYyPT09ZS5idXR0b24mJmUuY3RybEtleSYmdC5kZWZhdWx0Lm5hdmlnYXRvci5wbGF0Zm9ybS50b1VwcGVyQ2FzZSgpLmluZGV4T2YoXCJNQUNcIik+PTA/MDplLmJ1dHRvbn0scy5yZW1vdmU9ZnVuY3Rpb24odCl7dC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodCk7fTt2YXIgXz17QVBJX1VSTDpcImh0dHBzOi8vYXBpLm1hcGJveC5jb21cIixSRVFVSVJFX0FDQ0VTU19UT0tFTjohMCxBQ0NFU1NfVE9LRU46bnVsbH0sZz1cIlNlZSBodHRwczovL3d3dy5tYXBib3guY29tL2FwaS1kb2N1bWVudGF0aW9uLyNhY2Nlc3MtdG9rZW5zXCI7ZnVuY3Rpb24gdih0LGUpe3ZhciBpPUMoXy5BUElfVVJMKTtpZih0LnByb3RvY29sPWkucHJvdG9jb2wsdC5hdXRob3JpdHk9aS5hdXRob3JpdHksXCIvXCIhPT1pLnBhdGgmJih0LnBhdGg9XCJcIitpLnBhdGgrdC5wYXRoKSwhXy5SRVFVSVJFX0FDQ0VTU19UT0tFTilyZXR1cm4gUyh0KTtpZighKGU9ZXx8Xy5BQ0NFU1NfVE9LRU4pKXRocm93IG5ldyBFcnJvcihcIkFuIEFQSSBhY2Nlc3MgdG9rZW4gaXMgcmVxdWlyZWQgdG8gdXNlIE1hcGJveCBHTC4gXCIrZyk7aWYoXCJzXCI9PT1lWzBdKXRocm93IG5ldyBFcnJvcihcIlVzZSBhIHB1YmxpYyBhY2Nlc3MgdG9rZW4gKHBrLiopIHdpdGggTWFwYm94IEdMLCBub3QgYSBzZWNyZXQgYWNjZXNzIHRva2VuIChzay4qKS4gXCIrZyk7cmV0dXJuIHQucGFyYW1zLnB1c2goXCJhY2Nlc3NfdG9rZW49XCIrZSksUyh0KX1mdW5jdGlvbiB5KHQpe3JldHVybiAwPT09dC5pbmRleE9mKFwibWFwYm94OlwiKX12YXIgeD1mdW5jdGlvbih0LGUpe2lmKCF5KHQpKXJldHVybiB0O3ZhciBpPUModCk7cmV0dXJuIGkucGF0aD1cIi9mb250cy92MVwiK2kucGF0aCx2KGksZSl9LGI9ZnVuY3Rpb24odCxlKXtpZigheSh0KSlyZXR1cm4gdDt2YXIgaT1DKHQpO3JldHVybiBpLnBhdGg9XCIvdjQvXCIraS5hdXRob3JpdHkrXCIuanNvblwiLGkucGFyYW1zLnB1c2goXCJzZWN1cmVcIiksdihpLGUpfSx3PWZ1bmN0aW9uKHQsZSxpLG4pe3ZhciBvPUModCk7cmV0dXJuIHkodCk/KG8ucGF0aD1cIi9zdHlsZXMvdjFcIitvLnBhdGgrXCIvc3ByaXRlXCIrZStpLHYobyxuKSk6KG8ucGF0aCs9XCJcIitlK2ksUyhvKSl9LEU9LyhcXC4ocG5nfGpwZylcXGQqKSg/PSQpLyxUPWZ1bmN0aW9uKHQsZSxpKXtpZighZXx8IXkoZSkpcmV0dXJuIHQ7dmFyIG49Qyh0KSxvPXIuZGV2aWNlUGl4ZWxSYXRpbz49Mnx8NTEyPT09aT9cIkAyeFwiOlwiXCIsYT1yLnN1cHBvcnRzV2VicD9cIi53ZWJwXCI6XCIkMVwiO3JldHVybiBuLnBhdGg9bi5wYXRoLnJlcGxhY2UoRSxcIlwiK28rYSksZnVuY3Rpb24odCl7Zm9yKHZhciBlPTA7ZTx0Lmxlbmd0aDtlKyspMD09PXRbZV0uaW5kZXhPZihcImFjY2Vzc190b2tlbj10ay5cIikmJih0W2VdPVwiYWNjZXNzX3Rva2VuPVwiKyhfLkFDQ0VTU19UT0tFTnx8XCJcIikpO30obi5wYXJhbXMpLFMobil9O3ZhciBJPS9eKFxcdyspOlxcL1xcLyhbXi8/XSopKFxcL1teP10rKT9cXD8/KC4rKT8vO2Z1bmN0aW9uIEModCl7dmFyIGU9dC5tYXRjaChJKTtpZighZSl0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcGFyc2UgVVJMIG9iamVjdFwiKTtyZXR1cm57cHJvdG9jb2w6ZVsxXSxhdXRob3JpdHk6ZVsyXSxwYXRoOmVbM118fFwiL1wiLHBhcmFtczplWzRdP2VbNF0uc3BsaXQoXCImXCIpOltdfX1mdW5jdGlvbiBTKHQpe3ZhciBlPXQucGFyYW1zLmxlbmd0aD9cIj9cIit0LnBhcmFtcy5qb2luKFwiJlwiKTpcIlwiO3JldHVybiB0LnByb3RvY29sK1wiOi8vXCIrdC5hdXRob3JpdHkrdC5wYXRoK2V9dmFyIHo9dC5kZWZhdWx0LkhUTUxJbWFnZUVsZW1lbnQsQT10LmRlZmF1bHQuSFRNTENhbnZhc0VsZW1lbnQsUj10LmRlZmF1bHQuSFRNTFZpZGVvRWxlbWVudCxEPXQuZGVmYXVsdC5JbWFnZURhdGEsTT1mdW5jdGlvbih0LGUsaSxuKXt0aGlzLmNvbnRleHQ9dCx0aGlzLmZvcm1hdD1pLHRoaXMudGV4dHVyZT10LmdsLmNyZWF0ZVRleHR1cmUoKSx0aGlzLnVwZGF0ZShlLG4pO307TS5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKHQsZSl7dmFyIGk9dC53aWR0aCxuPXQuaGVpZ2h0LG89IXRoaXMuc2l6ZXx8dGhpcy5zaXplWzBdIT09aXx8dGhpcy5zaXplWzFdIT09bixyPXRoaXMuY29udGV4dCxhPXIuZ2w7dGhpcy51c2VNaXBtYXA9Qm9vbGVhbihlJiZlLnVzZU1pcG1hcCksYS5iaW5kVGV4dHVyZShhLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlKSxvPyh0aGlzLnNpemU9W2ksbl0sci5waXhlbFN0b3JlVW5wYWNrLnNldCgxKSx0aGlzLmZvcm1hdCE9PWEuUkdCQXx8ZSYmITE9PT1lLnByZW11bHRpcGx5fHxyLnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhLnNldCghMCksdCBpbnN0YW5jZW9mIHp8fHQgaW5zdGFuY2VvZiBBfHx0IGluc3RhbmNlb2YgUnx8dCBpbnN0YW5jZW9mIEQ/YS50ZXhJbWFnZTJEKGEuVEVYVFVSRV8yRCwwLHRoaXMuZm9ybWF0LHRoaXMuZm9ybWF0LGEuVU5TSUdORURfQllURSx0KTphLnRleEltYWdlMkQoYS5URVhUVVJFXzJELDAsdGhpcy5mb3JtYXQsaSxuLDAsdGhpcy5mb3JtYXQsYS5VTlNJR05FRF9CWVRFLHQuZGF0YSkpOnQgaW5zdGFuY2VvZiB6fHx0IGluc3RhbmNlb2YgQXx8dCBpbnN0YW5jZW9mIFJ8fHQgaW5zdGFuY2VvZiBEP2EudGV4U3ViSW1hZ2UyRChhLlRFWFRVUkVfMkQsMCwwLDAsYS5SR0JBLGEuVU5TSUdORURfQllURSx0KTphLnRleFN1YkltYWdlMkQoYS5URVhUVVJFXzJELDAsMCwwLGksbixhLlJHQkEsYS5VTlNJR05FRF9CWVRFLHQuZGF0YSksdGhpcy51c2VNaXBtYXAmJnRoaXMuaXNTaXplUG93ZXJPZlR3bygpJiZhLmdlbmVyYXRlTWlwbWFwKGEuVEVYVFVSRV8yRCk7fSxNLnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj10aGlzLmNvbnRleHQuZ2w7bi5iaW5kVGV4dHVyZShuLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlKSxpIT09bi5MSU5FQVJfTUlQTUFQX05FQVJFU1R8fHRoaXMuaXNTaXplUG93ZXJPZlR3bygpfHwoaT1uLkxJTkVBUiksdCE9PXRoaXMuZmlsdGVyJiYobi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfTUFHX0ZJTFRFUix0KSxuLnRleFBhcmFtZXRlcmkobi5URVhUVVJFXzJELG4uVEVYVFVSRV9NSU5fRklMVEVSLGl8fHQpLHRoaXMuZmlsdGVyPXQpLGUhPT10aGlzLndyYXAmJihuLnRleFBhcmFtZXRlcmkobi5URVhUVVJFXzJELG4uVEVYVFVSRV9XUkFQX1MsZSksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfV1JBUF9ULGUpLHRoaXMud3JhcD1lKTt9LE0ucHJvdG90eXBlLmlzU2l6ZVBvd2VyT2ZUd289ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zaXplWzBdPT09dGhpcy5zaXplWzFdJiZNYXRoLmxvZyh0aGlzLnNpemVbMF0pL01hdGguTE4yJTE9PTB9LE0ucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmNvbnRleHQuZ2wuZGVsZXRlVGV4dHVyZSh0aGlzLnRleHR1cmUpLHRoaXMudGV4dHVyZT1udWxsO307dmFyIEw9ZnVuY3Rpb24oKXt0aGlzLmltYWdlcz17fSx0aGlzLmxvYWRlZD0hMSx0aGlzLnJlcXVlc3RvcnM9W10sdGhpcy5zaGVsZlBhY2s9bmV3IHQuZGVmYXVsdCQyKDY0LDY0LHthdXRvUmVzaXplOiEwfSksdGhpcy5wYXR0ZXJucz17fSx0aGlzLmF0bGFzSW1hZ2U9bmV3IHQuUkdCQUltYWdlKHt3aWR0aDo2NCxoZWlnaHQ6NjR9KSx0aGlzLmRpcnR5PSEwO307TC5wcm90b3R5cGUuaXNMb2FkZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5sb2FkZWR9LEwucHJvdG90eXBlLnNldExvYWRlZD1mdW5jdGlvbih0KXtpZih0aGlzLmxvYWRlZCE9PXQmJih0aGlzLmxvYWRlZD10LHQpKXtmb3IodmFyIGU9MCxpPXRoaXMucmVxdWVzdG9ycztlPGkubGVuZ3RoO2UrPTEpe3ZhciBuPWlbZV0sbz1uLmlkcyxyPW4uY2FsbGJhY2s7dGhpcy5fbm90aWZ5KG8scik7fXRoaXMucmVxdWVzdG9ycz1bXTt9fSxMLnByb3RvdHlwZS5nZXRJbWFnZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5pbWFnZXNbdF19LEwucHJvdG90eXBlLmFkZEltYWdlPWZ1bmN0aW9uKHQsZSl7dGhpcy5pbWFnZXNbdF09ZTt9LEwucHJvdG90eXBlLnJlbW92ZUltYWdlPWZ1bmN0aW9uKHQpe2RlbGV0ZSB0aGlzLmltYWdlc1t0XTt2YXIgZT10aGlzLnBhdHRlcm5zW3RdO2UmJih0aGlzLnNoZWxmUGFjay51bnJlZihlLmJpbiksZGVsZXRlIHRoaXMucGF0dGVybnNbdF0pO30sTC5wcm90b3R5cGUuZ2V0SW1hZ2VzPWZ1bmN0aW9uKHQsZSl7dmFyIGk9ITA7aWYoIXRoaXMuaXNMb2FkZWQoKSlmb3IodmFyIG49MCxvPXQ7bjxvLmxlbmd0aDtuKz0xKXt2YXIgcj1vW25dO3RoaXMuaW1hZ2VzW3JdfHwoaT0hMSk7fXRoaXMuaXNMb2FkZWQoKXx8aT90aGlzLl9ub3RpZnkodCxlKTp0aGlzLnJlcXVlc3RvcnMucHVzaCh7aWRzOnQsY2FsbGJhY2s6ZX0pO30sTC5wcm90b3R5cGUuX25vdGlmeT1mdW5jdGlvbih0LGUpe2Zvcih2YXIgaT17fSxuPTAsbz10O248by5sZW5ndGg7bis9MSl7dmFyIHI9b1tuXSxhPXRoaXMuaW1hZ2VzW3JdO2EmJihpW3JdPXtkYXRhOmEuZGF0YS5jbG9uZSgpLHBpeGVsUmF0aW86YS5waXhlbFJhdGlvLHNkZjphLnNkZn0pO31lKG51bGwsaSk7fSxMLnByb3RvdHlwZS5nZXRQaXhlbFNpemU9ZnVuY3Rpb24oKXtyZXR1cm57d2lkdGg6dGhpcy5zaGVsZlBhY2sudyxoZWlnaHQ6dGhpcy5zaGVsZlBhY2suaH19LEwucHJvdG90eXBlLmdldFBhdHRlcm49ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5wYXR0ZXJuc1tlXTtpZihpKXJldHVybiBpLnBvc2l0aW9uO3ZhciBuPXRoaXMuZ2V0SW1hZ2UoZSk7aWYoIW4pcmV0dXJuIG51bGw7dmFyIG89bi5kYXRhLndpZHRoKzIscj1uLmRhdGEuaGVpZ2h0KzIsYT10aGlzLnNoZWxmUGFjay5wYWNrT25lKG8scik7aWYoIWEpcmV0dXJuIG51bGw7dGhpcy5hdGxhc0ltYWdlLnJlc2l6ZSh0aGlzLmdldFBpeGVsU2l6ZSgpKTt2YXIgcz1uLmRhdGEsbD10aGlzLmF0bGFzSW1hZ2UsYz1hLngrMSx1PWEueSsxLGg9cy53aWR0aCxwPXMuaGVpZ2h0O3QuUkdCQUltYWdlLmNvcHkocyxsLHt4OjAseTowfSx7eDpjLHk6dX0se3dpZHRoOmgsaGVpZ2h0OnB9KSx0LlJHQkFJbWFnZS5jb3B5KHMsbCx7eDowLHk6cC0xfSx7eDpjLHk6dS0xfSx7d2lkdGg6aCxoZWlnaHQ6MX0pLHQuUkdCQUltYWdlLmNvcHkocyxsLHt4OjAseTowfSx7eDpjLHk6dStwfSx7d2lkdGg6aCxoZWlnaHQ6MX0pLHQuUkdCQUltYWdlLmNvcHkocyxsLHt4OmgtMSx5OjB9LHt4OmMtMSx5OnV9LHt3aWR0aDoxLGhlaWdodDpwfSksdC5SR0JBSW1hZ2UuY29weShzLGwse3g6MCx5OjB9LHt4OmMraCx5OnV9LHt3aWR0aDoxLGhlaWdodDpwfSksdGhpcy5kaXJ0eT0hMDt2YXIgZD1uZXcgdC5JbWFnZVBvc2l0aW9uKGEsbik7cmV0dXJuIHRoaXMucGF0dGVybnNbZV09e2JpbjphLHBvc2l0aW9uOmR9LGR9LEwucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24odCl7dmFyIGU9dC5nbDt0aGlzLmF0bGFzVGV4dHVyZT90aGlzLmRpcnR5JiYodGhpcy5hdGxhc1RleHR1cmUudXBkYXRlKHRoaXMuYXRsYXNJbWFnZSksdGhpcy5kaXJ0eT0hMSk6dGhpcy5hdGxhc1RleHR1cmU9bmV3IE0odCx0aGlzLmF0bGFzSW1hZ2UsZS5SR0JBKSx0aGlzLmF0bGFzVGV4dHVyZS5iaW5kKGUuTElORUFSLGUuQ0xBTVBfVE9fRURHRSk7fTt2YXIgUD1CLGs9MWUyMDtmdW5jdGlvbiBCKHQsZSxpLG4sbyxyKXt0aGlzLmZvbnRTaXplPXR8fDI0LHRoaXMuYnVmZmVyPXZvaWQgMD09PWU/MzplLHRoaXMuY3V0b2ZmPW58fC4yNSx0aGlzLmZvbnRGYW1pbHk9b3x8XCJzYW5zLXNlcmlmXCIsdGhpcy5mb250V2VpZ2h0PXJ8fFwibm9ybWFsXCIsdGhpcy5yYWRpdXM9aXx8ODt2YXIgYT10aGlzLnNpemU9dGhpcy5mb250U2l6ZSsyKnRoaXMuYnVmZmVyO3RoaXMuY2FudmFzPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksdGhpcy5jYW52YXMud2lkdGg9dGhpcy5jYW52YXMuaGVpZ2h0PWEsdGhpcy5jdHg9dGhpcy5jYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpLHRoaXMuY3R4LmZvbnQ9dGhpcy5mb250V2VpZ2h0K1wiIFwiK3RoaXMuZm9udFNpemUrXCJweCBcIit0aGlzLmZvbnRGYW1pbHksdGhpcy5jdHgudGV4dEJhc2VsaW5lPVwibWlkZGxlXCIsdGhpcy5jdHguZmlsbFN0eWxlPVwiYmxhY2tcIix0aGlzLmdyaWRPdXRlcj1uZXcgRmxvYXQ2NEFycmF5KGEqYSksdGhpcy5ncmlkSW5uZXI9bmV3IEZsb2F0NjRBcnJheShhKmEpLHRoaXMuZj1uZXcgRmxvYXQ2NEFycmF5KGEpLHRoaXMuZD1uZXcgRmxvYXQ2NEFycmF5KGEpLHRoaXMuej1uZXcgRmxvYXQ2NEFycmF5KGErMSksdGhpcy52PW5ldyBJbnQxNkFycmF5KGEpLHRoaXMubWlkZGxlPU1hdGgucm91bmQoYS8yKihuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoXCJHZWNrby9cIik+PTA/MS4yOjEpKTt9ZnVuY3Rpb24gTyh0LGUsaSxuLG8scixhKXtmb3IodmFyIHM9MDtzPGU7cysrKXtmb3IodmFyIGw9MDtsPGk7bCsrKW5bbF09dFtsKmUrc107Zm9yKEYobixvLHIsYSxpKSxsPTA7bDxpO2wrKyl0W2wqZStzXT1vW2xdO31mb3IobD0wO2w8aTtsKyspe2ZvcihzPTA7czxlO3MrKyluW3NdPXRbbCplK3NdO2ZvcihGKG4sbyxyLGEsZSkscz0wO3M8ZTtzKyspdFtsKmUrc109TWF0aC5zcXJ0KG9bc10pO319ZnVuY3Rpb24gRih0LGUsaSxuLG8pe2lbMF09MCxuWzBdPS1rLG5bMV09K2s7Zm9yKHZhciByPTEsYT0wO3I8bztyKyspe2Zvcih2YXIgcz0odFtyXStyKnItKHRbaVthXV0raVthXSppW2FdKSkvKDIqci0yKmlbYV0pO3M8PW5bYV07KWEtLSxzPSh0W3JdK3Iqci0odFtpW2FdXStpW2FdKmlbYV0pKS8oMipyLTIqaVthXSk7aVsrK2FdPXIsblthXT1zLG5bYSsxXT0razt9Zm9yKHI9MCxhPTA7cjxvO3IrKyl7Zm9yKDtuW2ErMV08cjspYSsrO2Vbcl09KHItaVthXSkqKHItaVthXSkrdFtpW2FdXTt9fUIucHJvdG90eXBlLmRyYXc9ZnVuY3Rpb24odCl7dGhpcy5jdHguY2xlYXJSZWN0KDAsMCx0aGlzLnNpemUsdGhpcy5zaXplKSx0aGlzLmN0eC5maWxsVGV4dCh0LHRoaXMuYnVmZmVyLHRoaXMubWlkZGxlKTtmb3IodmFyIGU9dGhpcy5jdHguZ2V0SW1hZ2VEYXRhKDAsMCx0aGlzLnNpemUsdGhpcy5zaXplKSxpPW5ldyBVaW50OENsYW1wZWRBcnJheSh0aGlzLnNpemUqdGhpcy5zaXplKSxuPTA7bjx0aGlzLnNpemUqdGhpcy5zaXplO24rKyl7dmFyIG89ZS5kYXRhWzQqbiszXS8yNTU7dGhpcy5ncmlkT3V0ZXJbbl09MT09PW8/MDowPT09bz9rOk1hdGgucG93KE1hdGgubWF4KDAsLjUtbyksMiksdGhpcy5ncmlkSW5uZXJbbl09MT09PW8/azowPT09bz8wOk1hdGgucG93KE1hdGgubWF4KDAsby0uNSksMik7fWZvcihPKHRoaXMuZ3JpZE91dGVyLHRoaXMuc2l6ZSx0aGlzLnNpemUsdGhpcy5mLHRoaXMuZCx0aGlzLnYsdGhpcy56KSxPKHRoaXMuZ3JpZElubmVyLHRoaXMuc2l6ZSx0aGlzLnNpemUsdGhpcy5mLHRoaXMuZCx0aGlzLnYsdGhpcy56KSxuPTA7bjx0aGlzLnNpemUqdGhpcy5zaXplO24rKyl7dmFyIHI9dGhpcy5ncmlkT3V0ZXJbbl0tdGhpcy5ncmlkSW5uZXJbbl07aVtuXT1NYXRoLm1heCgwLE1hdGgubWluKDI1NSxNYXRoLnJvdW5kKDI1NS0yNTUqKHIvdGhpcy5yYWRpdXMrdGhpcy5jdXRvZmYpKSkpO31yZXR1cm4gaX07dmFyIE49ZnVuY3Rpb24odCxlKXt0aGlzLnJlcXVlc3RUcmFuc2Zvcm09dCx0aGlzLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseT1lLHRoaXMuZW50cmllcz17fTt9O04ucHJvdG90eXBlLnNldFVSTD1mdW5jdGlvbih0KXt0aGlzLnVybD10O30sTi5wcm90b3R5cGUuZ2V0R2x5cGhzPWZ1bmN0aW9uKGUsaSl7dmFyIG49dGhpcyxvPVtdO2Zvcih2YXIgciBpbiBlKWZvcih2YXIgYT0wLHM9ZVtyXTthPHMubGVuZ3RoO2ErPTEpe3ZhciBsPXNbYV07by5wdXNoKHtzdGFjazpyLGlkOmx9KTt9dC5hc3luY0FsbChvLGZ1bmN0aW9uKHQsZSl7dmFyIGk9dC5zdGFjayxvPXQuaWQscj1uLmVudHJpZXNbaV07cnx8KHI9bi5lbnRyaWVzW2ldPXtnbHlwaHM6e30scmVxdWVzdHM6e319KTt2YXIgYT1yLmdseXBoc1tvXTtpZih2b2lkIDA9PT1hKWlmKGE9bi5fdGlueVNERihyLGksbykpZShudWxsLHtzdGFjazppLGlkOm8sZ2x5cGg6YX0pO2Vsc2V7dmFyIHM9TWF0aC5mbG9vcihvLzI1Nik7aWYoMjU2KnM+NjU1MzUpZShuZXcgRXJyb3IoXCJnbHlwaHMgPiA2NTUzNSBub3Qgc3VwcG9ydGVkXCIpKTtlbHNle3ZhciBsPXIucmVxdWVzdHNbc107bHx8KGw9ci5yZXF1ZXN0c1tzXT1bXSxOLmxvYWRHbHlwaFJhbmdlKGkscyxuLnVybCxuLnJlcXVlc3RUcmFuc2Zvcm0sZnVuY3Rpb24odCxlKXtpZihlKWZvcih2YXIgaSBpbiBlKXIuZ2x5cGhzWytpXT1lWytpXTtmb3IodmFyIG49MCxvPWw7bjxvLmxlbmd0aDtuKz0xKXsoMCxvW25dKSh0LGUpO31kZWxldGUgci5yZXF1ZXN0c1tzXTt9KSksbC5wdXNoKGZ1bmN0aW9uKHQsbil7dD9lKHQpOm4mJmUobnVsbCx7c3RhY2s6aSxpZDpvLGdseXBoOm5bb118fG51bGx9KTt9KTt9fWVsc2UgZShudWxsLHtzdGFjazppLGlkOm8sZ2x5cGg6YX0pO30sZnVuY3Rpb24odCxlKXtpZih0KWkodCk7ZWxzZSBpZihlKXtmb3IodmFyIG49e30sbz0wLHI9ZTtvPHIubGVuZ3RoO28rPTEpe3ZhciBhPXJbb10scz1hLnN0YWNrLGw9YS5pZCxjPWEuZ2x5cGg7KG5bc118fChuW3NdPXt9KSlbbF09YyYme2lkOmMuaWQsYml0bWFwOmMuYml0bWFwLmNsb25lKCksbWV0cmljczpjLm1ldHJpY3N9O31pKG51bGwsbik7fX0pO30sTi5wcm90b3R5cGUuX3RpbnlTREY9ZnVuY3Rpb24oZSxpLG4pe3ZhciBvPXRoaXMubG9jYWxJZGVvZ3JhcGhGb250RmFtaWx5O2lmKG8mJih0LmRlZmF1bHQkNFtcIkNKSyBVbmlmaWVkIElkZW9ncmFwaHNcIl0obil8fHQuZGVmYXVsdCQ0W1wiSGFuZ3VsIFN5bGxhYmxlc1wiXShuKSkpe3ZhciByPWUudGlueVNERjtpZighcil7dmFyIGE9XCI0MDBcIjsvYm9sZC9pLnRlc3QoaSk/YT1cIjkwMFwiOi9tZWRpdW0vaS50ZXN0KGkpP2E9XCI1MDBcIjovbGlnaHQvaS50ZXN0KGkpJiYoYT1cIjIwMFwiKSxyPWUudGlueVNERj1uZXcgTi5UaW55U0RGKDI0LDMsOCwuMjUsbyxhKTt9cmV0dXJue2lkOm4sYml0bWFwOm5ldyB0LkFscGhhSW1hZ2Uoe3dpZHRoOjMwLGhlaWdodDozMH0sci5kcmF3KFN0cmluZy5mcm9tQ2hhckNvZGUobikpKSxtZXRyaWNzOnt3aWR0aDoyNCxoZWlnaHQ6MjQsbGVmdDowLHRvcDotOCxhZHZhbmNlOjI0fX19fSxOLmxvYWRHbHlwaFJhbmdlPWZ1bmN0aW9uKGUsaSxuLG8scil7dmFyIGE9MjU2Kmkscz1hKzI1NSxsPW8oeChuKS5yZXBsYWNlKFwie2ZvbnRzdGFja31cIixlKS5yZXBsYWNlKFwie3JhbmdlfVwiLGErXCItXCIrcyksdC5SZXNvdXJjZVR5cGUuR2x5cGhzKTt0LmdldEFycmF5QnVmZmVyKGwsZnVuY3Rpb24oZSxpKXtpZihlKXIoZSk7ZWxzZSBpZihpKXtmb3IodmFyIG49e30sbz0wLGE9dC5kZWZhdWx0JDMoaS5kYXRhKTtvPGEubGVuZ3RoO28rPTEpe3ZhciBzPWFbb107bltzLmlkXT1zO31yKG51bGwsbik7fX0pO30sTi5UaW55U0RGPVA7dmFyIFU9ZnVuY3Rpb24oKXt0aGlzLnNwZWNpZmljYXRpb249dC5kZWZhdWx0JDUubGlnaHQucG9zaXRpb247fTtVLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKGUsaSl7cmV0dXJuIHQuc3BoZXJpY2FsVG9DYXJ0ZXNpYW4oZS5leHByZXNzaW9uLmV2YWx1YXRlKGkpKX0sVS5wcm90b3R5cGUuaW50ZXJwb2xhdGU9ZnVuY3Rpb24oZSxpLG4pe3JldHVybnt4OnQubnVtYmVyKGUueCxpLngsbikseTp0Lm51bWJlcihlLnksaS55LG4pLHo6dC5udW1iZXIoZS56LGkueixuKX19O3ZhciBaPW5ldyB0LlByb3BlcnRpZXMoe2FuY2hvcjpuZXcgdC5EYXRhQ29uc3RhbnRQcm9wZXJ0eSh0LmRlZmF1bHQkNS5saWdodC5hbmNob3IpLHBvc2l0aW9uOm5ldyBVLGNvbG9yOm5ldyB0LkRhdGFDb25zdGFudFByb3BlcnR5KHQuZGVmYXVsdCQ1LmxpZ2h0LmNvbG9yKSxpbnRlbnNpdHk6bmV3IHQuRGF0YUNvbnN0YW50UHJvcGVydHkodC5kZWZhdWx0JDUubGlnaHQuaW50ZW5zaXR5KX0pLFY9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpKXtlLmNhbGwodGhpcyksdGhpcy5fdHJhbnNpdGlvbmFibGU9bmV3IHQuVHJhbnNpdGlvbmFibGUoWiksdGhpcy5zZXRMaWdodChpKSx0aGlzLl90cmFuc2l0aW9uaW5nPXRoaXMuX3RyYW5zaXRpb25hYmxlLnVudHJhbnNpdGlvbmVkKCk7fXJldHVybiBlJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5nZXRMaWdodD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl90cmFuc2l0aW9uYWJsZS5zZXJpYWxpemUoKX0saS5wcm90b3R5cGUuc2V0TGlnaHQ9ZnVuY3Rpb24oZSl7aWYoIXRoaXMuX3ZhbGlkYXRlKHQudmFsaWRhdGVMaWdodCxlKSlmb3IodmFyIGkgaW4gZSl7dmFyIG49ZVtpXTt0LmVuZHNXaXRoKGksXCItdHJhbnNpdGlvblwiKT90aGlzLl90cmFuc2l0aW9uYWJsZS5zZXRUcmFuc2l0aW9uKGkuc2xpY2UoMCwtXCItdHJhbnNpdGlvblwiLmxlbmd0aCksbik6dGhpcy5fdHJhbnNpdGlvbmFibGUuc2V0VmFsdWUoaSxuKTt9fSxpLnByb3RvdHlwZS51cGRhdGVUcmFuc2l0aW9ucz1mdW5jdGlvbih0KXt0aGlzLl90cmFuc2l0aW9uaW5nPXRoaXMuX3RyYW5zaXRpb25hYmxlLnRyYW5zaXRpb25lZCh0LHRoaXMuX3RyYW5zaXRpb25pbmcpO30saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl90cmFuc2l0aW9uaW5nLmhhc1RyYW5zaXRpb24oKX0saS5wcm90b3R5cGUucmVjYWxjdWxhdGU9ZnVuY3Rpb24odCl7dGhpcy5wcm9wZXJ0aWVzPXRoaXMuX3RyYW5zaXRpb25pbmcucG9zc2libHlFdmFsdWF0ZSh0KTt9LGkucHJvdG90eXBlLl92YWxpZGF0ZT1mdW5jdGlvbihlLGkpe3JldHVybiB0LmVtaXRWYWxpZGF0aW9uRXJyb3JzKHRoaXMsZS5jYWxsKHQudmFsaWRhdGVTdHlsZSx0LmV4dGVuZCh7dmFsdWU6aSxzdHlsZTp7Z2x5cGhzOiEwLHNwcml0ZTohMH0sc3R5bGVTcGVjOnQuZGVmYXVsdCQ1fSkpKX0saX0odC5FdmVudGVkKSxqPWZ1bmN0aW9uKHQsZSl7dGhpcy53aWR0aD10LHRoaXMuaGVpZ2h0PWUsdGhpcy5uZXh0Um93PTAsdGhpcy5ieXRlcz00LHRoaXMuZGF0YT1uZXcgVWludDhBcnJheSh0aGlzLndpZHRoKnRoaXMuaGVpZ2h0KnRoaXMuYnl0ZXMpLHRoaXMucG9zaXRpb25zPXt9O307ai5wcm90b3R5cGUuZ2V0RGFzaD1mdW5jdGlvbih0LGUpe3ZhciBpPXQuam9pbihcIixcIikrU3RyaW5nKGUpO3JldHVybiB0aGlzLnBvc2l0aW9uc1tpXXx8KHRoaXMucG9zaXRpb25zW2ldPXRoaXMuYWRkRGFzaCh0LGUpKSx0aGlzLnBvc2l0aW9uc1tpXX0sai5wcm90b3R5cGUuYWRkRGFzaD1mdW5jdGlvbihlLGkpe3ZhciBuPWk/NzowLG89MipuKzE7aWYodGhpcy5uZXh0Um93K28+dGhpcy5oZWlnaHQpcmV0dXJuIHQud2Fybk9uY2UoXCJMaW5lQXRsYXMgb3V0IG9mIHNwYWNlXCIpLG51bGw7Zm9yKHZhciByPTAsYT0wO2E8ZS5sZW5ndGg7YSsrKXIrPWVbYV07Zm9yKHZhciBzPXRoaXMud2lkdGgvcixsPXMvMixjPWUubGVuZ3RoJTI9PTEsdT0tbjt1PD1uO3UrKylmb3IodmFyIGg9dGhpcy5uZXh0Um93K24rdSxwPXRoaXMud2lkdGgqaCxkPWM/LWVbZS5sZW5ndGgtMV06MCxmPWVbMF0sbT0xLF89MDtfPHRoaXMud2lkdGg7XysrKXtmb3IoO2Y8Xy9zOylkPWYsZis9ZVttXSxjJiZtPT09ZS5sZW5ndGgtMSYmKGYrPWVbMF0pLG0rKzt2YXIgZz1NYXRoLmFicyhfLWQqcyksdj1NYXRoLmFicyhfLWYqcykseT1NYXRoLm1pbihnLHYpLHg9bSUyPT0xLGI9dm9pZCAwO2lmKGkpe3ZhciB3PW4/dS9uKihsKzEpOjA7aWYoeCl7dmFyIEU9bC1NYXRoLmFicyh3KTtiPU1hdGguc3FydCh5KnkrRSpFKTt9ZWxzZSBiPWwtTWF0aC5zcXJ0KHkqeSt3KncpO31lbHNlIGI9KHg/MTotMSkqeTt0aGlzLmRhdGFbMys0KihwK18pXT1NYXRoLm1heCgwLE1hdGgubWluKDI1NSxiKzEyOCkpO312YXIgVD17eToodGhpcy5uZXh0Um93K24rLjUpL3RoaXMuaGVpZ2h0LGhlaWdodDoyKm4vdGhpcy5oZWlnaHQsd2lkdGg6cn07cmV0dXJuIHRoaXMubmV4dFJvdys9byx0aGlzLmRpcnR5PSEwLFR9LGoucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24odCl7dmFyIGU9dC5nbDt0aGlzLnRleHR1cmU/KGUuYmluZFRleHR1cmUoZS5URVhUVVJFXzJELHRoaXMudGV4dHVyZSksdGhpcy5kaXJ0eSYmKHRoaXMuZGlydHk9ITEsZS50ZXhTdWJJbWFnZTJEKGUuVEVYVFVSRV8yRCwwLDAsMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0LGUuUkdCQSxlLlVOU0lHTkVEX0JZVEUsdGhpcy5kYXRhKSkpOih0aGlzLnRleHR1cmU9ZS5jcmVhdGVUZXh0dXJlKCksZS5iaW5kVGV4dHVyZShlLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlKSxlLnRleFBhcmFtZXRlcmkoZS5URVhUVVJFXzJELGUuVEVYVFVSRV9XUkFQX1MsZS5SRVBFQVQpLGUudGV4UGFyYW1ldGVyaShlLlRFWFRVUkVfMkQsZS5URVhUVVJFX1dSQVBfVCxlLlJFUEVBVCksZS50ZXhQYXJhbWV0ZXJpKGUuVEVYVFVSRV8yRCxlLlRFWFRVUkVfTUlOX0ZJTFRFUixlLkxJTkVBUiksZS50ZXhQYXJhbWV0ZXJpKGUuVEVYVFVSRV8yRCxlLlRFWFRVUkVfTUFHX0ZJTFRFUixlLkxJTkVBUiksZS50ZXhJbWFnZTJEKGUuVEVYVFVSRV8yRCwwLGUuUkdCQSx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0LDAsZS5SR0JBLGUuVU5TSUdORURfQllURSx0aGlzLmRhdGEpKTt9O3ZhciAkPWZ1bmN0aW9uIGUoaSxuKXt0aGlzLndvcmtlclBvb2w9aSx0aGlzLmFjdG9ycz1bXSx0aGlzLmN1cnJlbnRBY3Rvcj0wLHRoaXMuaWQ9dC51bmlxdWVJZCgpO2Zvcih2YXIgbz10aGlzLndvcmtlclBvb2wuYWNxdWlyZSh0aGlzLmlkKSxyPTA7cjxvLmxlbmd0aDtyKyspe3ZhciBhPW9bcl0scz1uZXcgZS5BY3RvcihhLG4sdGhpcy5pZCk7cy5uYW1lPVwiV29ya2VyIFwiK3IsdGhpcy5hY3RvcnMucHVzaChzKTt9fTtmdW5jdGlvbiBHKGUsaSxuKXt2YXIgbz1mdW5jdGlvbihlLGkpe2lmKGUpcmV0dXJuIG4oZSk7aWYoaSl7dmFyIG89dC5waWNrKGksW1widGlsZXNcIixcIm1pbnpvb21cIixcIm1heHpvb21cIixcImF0dHJpYnV0aW9uXCIsXCJtYXBib3hfbG9nb1wiLFwiYm91bmRzXCJdKTtpLnZlY3Rvcl9sYXllcnMmJihvLnZlY3RvckxheWVycz1pLnZlY3Rvcl9sYXllcnMsby52ZWN0b3JMYXllcklkcz1vLnZlY3RvckxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSksbihudWxsLG8pO319O2UudXJsP3QuZ2V0SlNPTihpKGIoZS51cmwpLHQuUmVzb3VyY2VUeXBlLlNvdXJjZSksbyk6ci5mcmFtZShmdW5jdGlvbigpe3JldHVybiBvKG51bGwsZSl9KTt9JC5wcm90b3R5cGUuYnJvYWRjYXN0PWZ1bmN0aW9uKGUsaSxuKXtuPW58fGZ1bmN0aW9uKCl7fSx0LmFzeW5jQWxsKHRoaXMuYWN0b3JzLGZ1bmN0aW9uKHQsbil7dC5zZW5kKGUsaSxuKTt9LG4pO30sJC5wcm90b3R5cGUuc2VuZD1mdW5jdGlvbih0LGUsaSxuKXtyZXR1cm4oXCJudW1iZXJcIiE9dHlwZW9mIG58fGlzTmFOKG4pKSYmKG49dGhpcy5jdXJyZW50QWN0b3I9KHRoaXMuY3VycmVudEFjdG9yKzEpJXRoaXMuYWN0b3JzLmxlbmd0aCksdGhpcy5hY3RvcnNbbl0uc2VuZCh0LGUsaSksbn0sJC5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7dGhpcy5hY3RvcnMuZm9yRWFjaChmdW5jdGlvbih0KXt0LnJlbW92ZSgpO30pLHRoaXMuYWN0b3JzPVtdLHRoaXMud29ya2VyUG9vbC5yZWxlYXNlKHRoaXMuaWQpO30sJC5BY3Rvcj10LmRlZmF1bHQkNzt2YXIgVz1mdW5jdGlvbih0LGUpe2lmKGlzTmFOKHQpfHxpc05hTihlKSl0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIExuZ0xhdCBvYmplY3Q6IChcIit0K1wiLCBcIitlK1wiKVwiKTtpZih0aGlzLmxuZz0rdCx0aGlzLmxhdD0rZSx0aGlzLmxhdD45MHx8dGhpcy5sYXQ8LTkwKXRocm93IG5ldyBFcnJvcihcIkludmFsaWQgTG5nTGF0IGxhdGl0dWRlIHZhbHVlOiBtdXN0IGJlIGJldHdlZW4gLTkwIGFuZCA5MFwiKX07Vy5wcm90b3R5cGUud3JhcD1mdW5jdGlvbigpe3JldHVybiBuZXcgVyh0LndyYXAodGhpcy5sbmcsLTE4MCwxODApLHRoaXMubGF0KX0sVy5wcm90b3R5cGUudG9BcnJheT1mdW5jdGlvbigpe3JldHVyblt0aGlzLmxuZyx0aGlzLmxhdF19LFcucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJMbmdMYXQoXCIrdGhpcy5sbmcrXCIsIFwiK3RoaXMubGF0K1wiKVwifSxXLnByb3RvdHlwZS50b0JvdW5kcz1mdW5jdGlvbih0KXt2YXIgZT0zNjAqdC80MDA3NTAxNyxpPWUvTWF0aC5jb3MoTWF0aC5QSS8xODAqdGhpcy5sYXQpO3JldHVybiBuZXcgcShuZXcgVyh0aGlzLmxuZy1pLHRoaXMubGF0LWUpLG5ldyBXKHRoaXMubG5nK2ksdGhpcy5sYXQrZSkpfSxXLmNvbnZlcnQ9ZnVuY3Rpb24odCl7aWYodCBpbnN0YW5jZW9mIFcpcmV0dXJuIHQ7aWYoQXJyYXkuaXNBcnJheSh0KSYmKDI9PT10Lmxlbmd0aHx8Mz09PXQubGVuZ3RoKSlyZXR1cm4gbmV3IFcoTnVtYmVyKHRbMF0pLE51bWJlcih0WzFdKSk7aWYoIUFycmF5LmlzQXJyYXkodCkmJlwib2JqZWN0XCI9PXR5cGVvZiB0JiZudWxsIT09dClyZXR1cm4gbmV3IFcoTnVtYmVyKHQubG5nKSxOdW1iZXIodC5sYXQpKTt0aHJvdyBuZXcgRXJyb3IoXCJgTG5nTGF0TGlrZWAgYXJndW1lbnQgbXVzdCBiZSBzcGVjaWZpZWQgYXMgYSBMbmdMYXQgaW5zdGFuY2UsIGFuIG9iamVjdCB7bG5nOiA8bG5nPiwgbGF0OiA8bGF0Pn0sIG9yIGFuIGFycmF5IG9mIFs8bG5nPiwgPGxhdD5dXCIpfTt2YXIgcT1mdW5jdGlvbih0LGUpe3QmJihlP3RoaXMuc2V0U291dGhXZXN0KHQpLnNldE5vcnRoRWFzdChlKTo0PT09dC5sZW5ndGg/dGhpcy5zZXRTb3V0aFdlc3QoW3RbMF0sdFsxXV0pLnNldE5vcnRoRWFzdChbdFsyXSx0WzNdXSk6dGhpcy5zZXRTb3V0aFdlc3QodFswXSkuc2V0Tm9ydGhFYXN0KHRbMV0pKTt9O3EucHJvdG90eXBlLnNldE5vcnRoRWFzdD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbmU9dCBpbnN0YW5jZW9mIFc/bmV3IFcodC5sbmcsdC5sYXQpOlcuY29udmVydCh0KSx0aGlzfSxxLnByb3RvdHlwZS5zZXRTb3V0aFdlc3Q9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3N3PXQgaW5zdGFuY2VvZiBXP25ldyBXKHQubG5nLHQubGF0KTpXLmNvbnZlcnQodCksdGhpc30scS5wcm90b3R5cGUuZXh0ZW5kPWZ1bmN0aW9uKHQpe3ZhciBlLGksbj10aGlzLl9zdyxvPXRoaXMuX25lO2lmKHQgaW5zdGFuY2VvZiBXKWU9dCxpPXQ7ZWxzZXtpZighKHQgaW5zdGFuY2VvZiBxKSlyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90LmV2ZXJ5KEFycmF5LmlzQXJyYXkpP3RoaXMuZXh0ZW5kKHEuY29udmVydCh0KSk6dGhpcy5leHRlbmQoVy5jb252ZXJ0KHQpKTp0aGlzO2lmKGU9dC5fc3csaT10Ll9uZSwhZXx8IWkpcmV0dXJuIHRoaXN9cmV0dXJuIG58fG8/KG4ubG5nPU1hdGgubWluKGUubG5nLG4ubG5nKSxuLmxhdD1NYXRoLm1pbihlLmxhdCxuLmxhdCksby5sbmc9TWF0aC5tYXgoaS5sbmcsby5sbmcpLG8ubGF0PU1hdGgubWF4KGkubGF0LG8ubGF0KSk6KHRoaXMuX3N3PW5ldyBXKGUubG5nLGUubGF0KSx0aGlzLl9uZT1uZXcgVyhpLmxuZyxpLmxhdCkpLHRoaXN9LHEucHJvdG90eXBlLmdldENlbnRlcj1mdW5jdGlvbigpe3JldHVybiBuZXcgVygodGhpcy5fc3cubG5nK3RoaXMuX25lLmxuZykvMiwodGhpcy5fc3cubGF0K3RoaXMuX25lLmxhdCkvMil9LHEucHJvdG90eXBlLmdldFNvdXRoV2VzdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zd30scS5wcm90b3R5cGUuZ2V0Tm9ydGhFYXN0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX25lfSxxLnByb3RvdHlwZS5nZXROb3J0aFdlc3Q9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFcodGhpcy5nZXRXZXN0KCksdGhpcy5nZXROb3J0aCgpKX0scS5wcm90b3R5cGUuZ2V0U291dGhFYXN0PWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBXKHRoaXMuZ2V0RWFzdCgpLHRoaXMuZ2V0U291dGgoKSl9LHEucHJvdG90eXBlLmdldFdlc3Q9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3cubG5nfSxxLnByb3RvdHlwZS5nZXRTb3V0aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdy5sYXR9LHEucHJvdG90eXBlLmdldEVhc3Q9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbmUubG5nfSxxLnByb3RvdHlwZS5nZXROb3J0aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9uZS5sYXR9LHEucHJvdG90eXBlLnRvQXJyYXk9ZnVuY3Rpb24oKXtyZXR1cm5bdGhpcy5fc3cudG9BcnJheSgpLHRoaXMuX25lLnRvQXJyYXkoKV19LHEucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJMbmdMYXRCb3VuZHMoXCIrdGhpcy5fc3cudG9TdHJpbmcoKStcIiwgXCIrdGhpcy5fbmUudG9TdHJpbmcoKStcIilcIn0scS5wcm90b3R5cGUuaXNFbXB0eT1mdW5jdGlvbigpe3JldHVybiEodGhpcy5fc3cmJnRoaXMuX25lKX0scS5jb252ZXJ0PWZ1bmN0aW9uKHQpe3JldHVybiF0fHx0IGluc3RhbmNlb2YgcT90Om5ldyBxKHQpfTt2YXIgWD1mdW5jdGlvbih0LGUsaSl7dGhpcy5ib3VuZHM9cS5jb252ZXJ0KHRoaXMudmFsaWRhdGVCb3VuZHModCkpLHRoaXMubWluem9vbT1lfHwwLHRoaXMubWF4em9vbT1pfHwyNDt9O1gucHJvdG90eXBlLnZhbGlkYXRlQm91bmRzPWZ1bmN0aW9uKHQpe3JldHVybiBBcnJheS5pc0FycmF5KHQpJiY0PT09dC5sZW5ndGg/W01hdGgubWF4KC0xODAsdFswXSksTWF0aC5tYXgoLTkwLHRbMV0pLE1hdGgubWluKDE4MCx0WzJdKSxNYXRoLm1pbig5MCx0WzNdKV06Wy0xODAsLTkwLDE4MCw5MF19LFgucHJvdG90eXBlLmNvbnRhaW5zPWZ1bmN0aW9uKHQpe3ZhciBlPU1hdGguZmxvb3IodGhpcy5sbmdYKHRoaXMuYm91bmRzLmdldFdlc3QoKSx0LnopKSxpPU1hdGguZmxvb3IodGhpcy5sYXRZKHRoaXMuYm91bmRzLmdldE5vcnRoKCksdC56KSksbj1NYXRoLmNlaWwodGhpcy5sbmdYKHRoaXMuYm91bmRzLmdldEVhc3QoKSx0LnopKSxvPU1hdGguY2VpbCh0aGlzLmxhdFkodGhpcy5ib3VuZHMuZ2V0U291dGgoKSx0LnopKTtyZXR1cm4gdC54Pj1lJiZ0Lng8biYmdC55Pj1pJiZ0Lnk8b30sWC5wcm90b3R5cGUubG5nWD1mdW5jdGlvbih0LGUpe3JldHVybih0KzE4MCkqKE1hdGgucG93KDIsZSkvMzYwKX0sWC5wcm90b3R5cGUubGF0WT1mdW5jdGlvbihlLGkpe3ZhciBuPXQuY2xhbXAoTWF0aC5zaW4oTWF0aC5QSS8xODAqZSksLS45OTk5LC45OTk5KSxvPU1hdGgucG93KDIsaSkvKDIqTWF0aC5QSSk7cmV0dXJuIE1hdGgucG93KDIsaS0xKSsuNSpNYXRoLmxvZygoMStuKS8oMS1uKSkqLW99O3ZhciBIPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoaSxuLG8scil7aWYoZS5jYWxsKHRoaXMpLHRoaXMuaWQ9aSx0aGlzLmRpc3BhdGNoZXI9byx0aGlzLnR5cGU9XCJ2ZWN0b3JcIix0aGlzLm1pbnpvb209MCx0aGlzLm1heHpvb209MjIsdGhpcy5zY2hlbWU9XCJ4eXpcIix0aGlzLnRpbGVTaXplPTUxMix0aGlzLnJlcGFyc2VPdmVyc2NhbGVkPSEwLHRoaXMuaXNUaWxlQ2xpcHBlZD0hMCx0LmV4dGVuZCh0aGlzLHQucGljayhuLFtcInVybFwiLFwic2NoZW1lXCIsXCJ0aWxlU2l6ZVwiXSkpLHRoaXMuX29wdGlvbnM9dC5leHRlbmQoe3R5cGU6XCJ2ZWN0b3JcIn0sbiksdGhpcy5fY29sbGVjdFJlc291cmNlVGltaW5nPW4uY29sbGVjdFJlc291cmNlVGltaW5nLDUxMiE9PXRoaXMudGlsZVNpemUpdGhyb3cgbmV3IEVycm9yKFwidmVjdG9yIHRpbGUgc291cmNlcyBtdXN0IGhhdmUgYSB0aWxlU2l6ZSBvZiA1MTJcIik7dGhpcy5zZXRFdmVudGVkUGFyZW50KHIpO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUubG9hZD1mdW5jdGlvbigpe3ZhciBlPXRoaXM7dGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YWxvYWRpbmdcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIn0pKSxHKHRoaXMuX29wdGlvbnMsdGhpcy5tYXAuX3RyYW5zZm9ybVJlcXVlc3QsZnVuY3Rpb24oaSxuKXtpP2UuZmlyZShuZXcgdC5FcnJvckV2ZW50KGkpKTpuJiYodC5leHRlbmQoZSxuKSxuLmJvdW5kcyYmKGUudGlsZUJvdW5kcz1uZXcgWChuLmJvdW5kcyxlLm1pbnpvb20sZS5tYXh6b29tKSksZS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwibWV0YWRhdGFcIn0pKSxlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse2RhdGFUeXBlOlwic291cmNlXCIsc291cmNlRGF0YVR5cGU6XCJjb250ZW50XCJ9KSkpO30pO30saS5wcm90b3R5cGUuaGFzVGlsZT1mdW5jdGlvbih0KXtyZXR1cm4hdGhpcy50aWxlQm91bmRzfHx0aGlzLnRpbGVCb3VuZHMuY29udGFpbnModC5jYW5vbmljYWwpfSxpLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt0aGlzLm1hcD10LHRoaXMubG9hZCgpO30saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHQuZXh0ZW5kKHt9LHRoaXMuX29wdGlvbnMpfSxpLnByb3RvdHlwZS5sb2FkVGlsZT1mdW5jdGlvbihlLGkpe3ZhciBuPVQoZS50aWxlSUQuY2Fub25pY2FsLnVybCh0aGlzLnRpbGVzLHRoaXMuc2NoZW1lKSx0aGlzLnVybCksbz17cmVxdWVzdDp0aGlzLm1hcC5fdHJhbnNmb3JtUmVxdWVzdChuLHQuUmVzb3VyY2VUeXBlLlRpbGUpLHVpZDplLnVpZCx0aWxlSUQ6ZS50aWxlSUQsem9vbTplLnRpbGVJRC5vdmVyc2NhbGVkWix0aWxlU2l6ZTp0aGlzLnRpbGVTaXplKmUudGlsZUlELm92ZXJzY2FsZUZhY3RvcigpLHR5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLmlkLHBpeGVsUmF0aW86ci5kZXZpY2VQaXhlbFJhdGlvLHNob3dDb2xsaXNpb25Cb3hlczp0aGlzLm1hcC5zaG93Q29sbGlzaW9uQm94ZXN9O2Z1bmN0aW9uIGEodCxuKXtyZXR1cm4gZS5hYm9ydGVkP2kobnVsbCk6dD9pKHQpOihuJiZuLnJlc291cmNlVGltaW5nJiYoZS5yZXNvdXJjZVRpbWluZz1uLnJlc291cmNlVGltaW5nKSx0aGlzLm1hcC5fcmVmcmVzaEV4cGlyZWRUaWxlcyYmZS5zZXRFeHBpcnlEYXRhKG4pLGUubG9hZFZlY3RvckRhdGEobix0aGlzLm1hcC5wYWludGVyKSxpKG51bGwpLHZvaWQoZS5yZWxvYWRDYWxsYmFjayYmKHRoaXMubG9hZFRpbGUoZSxlLnJlbG9hZENhbGxiYWNrKSxlLnJlbG9hZENhbGxiYWNrPW51bGwpKSl9by5yZXF1ZXN0LmNvbGxlY3RSZXNvdXJjZVRpbWluZz10aGlzLl9jb2xsZWN0UmVzb3VyY2VUaW1pbmcsdm9pZCAwPT09ZS53b3JrZXJJRHx8XCJleHBpcmVkXCI9PT1lLnN0YXRlP2Uud29ya2VySUQ9dGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJsb2FkVGlsZVwiLG8sYS5iaW5kKHRoaXMpKTpcImxvYWRpbmdcIj09PWUuc3RhdGU/ZS5yZWxvYWRDYWxsYmFjaz1pOnRoaXMuZGlzcGF0Y2hlci5zZW5kKFwicmVsb2FkVGlsZVwiLG8sYS5iaW5kKHRoaXMpLGUud29ya2VySUQpO30saS5wcm90b3R5cGUuYWJvcnRUaWxlPWZ1bmN0aW9uKHQpe3RoaXMuZGlzcGF0Y2hlci5zZW5kKFwiYWJvcnRUaWxlXCIse3VpZDp0LnVpZCx0eXBlOnRoaXMudHlwZSxzb3VyY2U6dGhpcy5pZH0sdm9pZCAwLHQud29ya2VySUQpO30saS5wcm90b3R5cGUudW5sb2FkVGlsZT1mdW5jdGlvbih0KXt0LnVubG9hZFZlY3RvckRhdGEoKSx0aGlzLmRpc3BhdGNoZXIuc2VuZChcInJlbW92ZVRpbGVcIix7dWlkOnQudWlkLHR5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLmlkfSx2b2lkIDAsdC53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuITF9LGl9KHQuRXZlbnRlZCksSz1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbixvLHIpe2UuY2FsbCh0aGlzKSx0aGlzLmlkPWksdGhpcy5kaXNwYXRjaGVyPW8sdGhpcy5zZXRFdmVudGVkUGFyZW50KHIpLHRoaXMudHlwZT1cInJhc3RlclwiLHRoaXMubWluem9vbT0wLHRoaXMubWF4em9vbT0yMix0aGlzLnJvdW5kWm9vbT0hMCx0aGlzLnNjaGVtZT1cInh5elwiLHRoaXMudGlsZVNpemU9NTEyLHRoaXMuX2xvYWRlZD0hMSx0aGlzLl9vcHRpb25zPXQuZXh0ZW5kKHt9LG4pLHQuZXh0ZW5kKHRoaXMsdC5waWNrKG4sW1widXJsXCIsXCJzY2hlbWVcIixcInRpbGVTaXplXCJdKSk7fXJldHVybiBlJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dmFyIGU9dGhpczt0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInNvdXJjZVwifSkpLEcodGhpcy5fb3B0aW9ucyx0aGlzLm1hcC5fdHJhbnNmb3JtUmVxdWVzdCxmdW5jdGlvbihpLG4pe2k/ZS5maXJlKG5ldyB0LkVycm9yRXZlbnQoaSkpOm4mJih0LmV4dGVuZChlLG4pLG4uYm91bmRzJiYoZS50aWxlQm91bmRzPW5ldyBYKG4uYm91bmRzLGUubWluem9vbSxlLm1heHpvb20pKSxlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse2RhdGFUeXBlOlwic291cmNlXCIsc291cmNlRGF0YVR5cGU6XCJtZXRhZGF0YVwifSkpLGUuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIixzb3VyY2VEYXRhVHlwZTpcImNvbnRlbnRcIn0pKSk7fSk7fSxpLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt0aGlzLm1hcD10LHRoaXMubG9hZCgpO30saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHQuZXh0ZW5kKHt9LHRoaXMuX29wdGlvbnMpfSxpLnByb3RvdHlwZS5oYXNUaWxlPWZ1bmN0aW9uKHQpe3JldHVybiF0aGlzLnRpbGVCb3VuZHN8fHRoaXMudGlsZUJvdW5kcy5jb250YWlucyh0LmNhbm9uaWNhbCl9LGkucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKGUsaSl7dmFyIG49dGhpcyxvPVQoZS50aWxlSUQuY2Fub25pY2FsLnVybCh0aGlzLnRpbGVzLHRoaXMuc2NoZW1lKSx0aGlzLnVybCx0aGlzLnRpbGVTaXplKTtlLnJlcXVlc3Q9dC5nZXRJbWFnZSh0aGlzLm1hcC5fdHJhbnNmb3JtUmVxdWVzdChvLHQuUmVzb3VyY2VUeXBlLlRpbGUpLGZ1bmN0aW9uKHQsbyl7aWYoZGVsZXRlIGUucmVxdWVzdCxlLmFib3J0ZWQpZS5zdGF0ZT1cInVubG9hZGVkXCIsaShudWxsKTtlbHNlIGlmKHQpZS5zdGF0ZT1cImVycm9yZWRcIixpKHQpO2Vsc2UgaWYobyl7bi5tYXAuX3JlZnJlc2hFeHBpcmVkVGlsZXMmJmUuc2V0RXhwaXJ5RGF0YShvKSxkZWxldGUgby5jYWNoZUNvbnRyb2wsZGVsZXRlIG8uZXhwaXJlczt2YXIgcj1uLm1hcC5wYWludGVyLmNvbnRleHQsYT1yLmdsO2UudGV4dHVyZT1uLm1hcC5wYWludGVyLmdldFRpbGVUZXh0dXJlKG8ud2lkdGgpLGUudGV4dHVyZT9lLnRleHR1cmUudXBkYXRlKG8se3VzZU1pcG1hcDohMH0pOihlLnRleHR1cmU9bmV3IE0ocixvLGEuUkdCQSx7dXNlTWlwbWFwOiEwfSksZS50ZXh0dXJlLmJpbmQoYS5MSU5FQVIsYS5DTEFNUF9UT19FREdFLGEuTElORUFSX01JUE1BUF9ORUFSRVNUKSxyLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYyYmYS50ZXhQYXJhbWV0ZXJmKGEuVEVYVFVSRV8yRCxyLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYy5URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCxyLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpY01heCkpLGUuc3RhdGU9XCJsb2FkZWRcIixpKG51bGwpO319KTt9LGkucHJvdG90eXBlLmFib3J0VGlsZT1mdW5jdGlvbih0LGUpe3QucmVxdWVzdCYmKHQucmVxdWVzdC5hYm9ydCgpLGRlbGV0ZSB0LnJlcXVlc3QpLGUoKTt9LGkucHJvdG90eXBlLnVubG9hZFRpbGU9ZnVuY3Rpb24odCxlKXt0LnRleHR1cmUmJnRoaXMubWFwLnBhaW50ZXIuc2F2ZVRpbGVUZXh0dXJlKHQudGV4dHVyZSksZSgpO30saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiExfSxpfSh0LkV2ZW50ZWQpLFk9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpLG4sbyxyKXtlLmNhbGwodGhpcyxpLG4sbyxyKSx0aGlzLnR5cGU9XCJyYXN0ZXItZGVtXCIsdGhpcy5tYXh6b29tPTIyLHRoaXMuX29wdGlvbnM9dC5leHRlbmQoe30sbiksdGhpcy5lbmNvZGluZz1uLmVuY29kaW5nfHxcIm1hcGJveFwiO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJue3R5cGU6XCJyYXN0ZXItZGVtXCIsdXJsOnRoaXMudXJsLHRpbGVTaXplOnRoaXMudGlsZVNpemUsdGlsZXM6dGhpcy50aWxlcyxib3VuZHM6dGhpcy5ib3VuZHMsZW5jb2Rpbmc6dGhpcy5lbmNvZGluZ319LGkucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKGUsaSl7dmFyIG49VChlLnRpbGVJRC5jYW5vbmljYWwudXJsKHRoaXMudGlsZXMsdGhpcy5zY2hlbWUpLHRoaXMudXJsLHRoaXMudGlsZVNpemUpO2UucmVxdWVzdD10LmdldEltYWdlKHRoaXMubWFwLl90cmFuc2Zvcm1SZXF1ZXN0KG4sdC5SZXNvdXJjZVR5cGUuVGlsZSksZnVuY3Rpb24odCxuKXtpZihkZWxldGUgZS5yZXF1ZXN0LGUuYWJvcnRlZCllLnN0YXRlPVwidW5sb2FkZWRcIixpKG51bGwpO2Vsc2UgaWYodCllLnN0YXRlPVwiZXJyb3JlZFwiLGkodCk7ZWxzZSBpZihuKXt0aGlzLm1hcC5fcmVmcmVzaEV4cGlyZWRUaWxlcyYmZS5zZXRFeHBpcnlEYXRhKG4pLGRlbGV0ZSBuLmNhY2hlQ29udHJvbCxkZWxldGUgbi5leHBpcmVzO3ZhciBvPXIuZ2V0SW1hZ2VEYXRhKG4pLGE9e3VpZDplLnVpZCxjb29yZDplLnRpbGVJRCxzb3VyY2U6dGhpcy5pZCxyYXdJbWFnZURhdGE6byxlbmNvZGluZzp0aGlzLmVuY29kaW5nfTtlLndvcmtlcklEJiZcImV4cGlyZWRcIiE9PWUuc3RhdGV8fChlLndvcmtlcklEPXRoaXMuZGlzcGF0Y2hlci5zZW5kKFwibG9hZERFTVRpbGVcIixhLGZ1bmN0aW9uKHQsbil7dCYmKGUuc3RhdGU9XCJlcnJvcmVkXCIsaSh0KSk7biYmKGUuZGVtPW4sZS5uZWVkc0hpbGxzaGFkZVByZXBhcmU9ITAsZS5zdGF0ZT1cImxvYWRlZFwiLGkobnVsbCkpO30uYmluZCh0aGlzKSkpO319LmJpbmQodGhpcykpLGUubmVpZ2hib3JpbmdUaWxlcz10aGlzLl9nZXROZWlnaGJvcmluZ1RpbGVzKGUudGlsZUlEKTt9LGkucHJvdG90eXBlLl9nZXROZWlnaGJvcmluZ1RpbGVzPWZ1bmN0aW9uKGUpe3ZhciBpPWUuY2Fub25pY2FsLG49TWF0aC5wb3coMixpLnopLG89KGkueC0xK24pJW4scj0wPT09aS54P2Uud3JhcC0xOmUud3JhcCxhPShpLngrMStuKSVuLHM9aS54KzE9PT1uP2Uud3JhcCsxOmUud3JhcCxsPXt9O3JldHVybiBsW25ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoZS5vdmVyc2NhbGVkWixyLGkueixvLGkueSkua2V5XT17YmFja2ZpbGxlZDohMX0sbFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFoscyxpLnosYSxpLnkpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGkueT4wJiYobFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFoscixpLnosbyxpLnktMSkua2V5XT17YmFja2ZpbGxlZDohMX0sbFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFosZS53cmFwLGkueixpLngsaS55LTEpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLHMsaS56LGEsaS55LTEpLmtleV09e2JhY2tmaWxsZWQ6ITF9KSxpLnkrMTxuJiYobFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFoscixpLnosbyxpLnkrMSkua2V5XT17YmFja2ZpbGxlZDohMX0sbFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFosZS53cmFwLGkueixpLngsaS55KzEpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLHMsaS56LGEsaS55KzEpLmtleV09e2JhY2tmaWxsZWQ6ITF9KSxsfSxpLnByb3RvdHlwZS51bmxvYWRUaWxlPWZ1bmN0aW9uKHQpe3QuZGVtVGV4dHVyZSYmdGhpcy5tYXAucGFpbnRlci5zYXZlVGlsZVRleHR1cmUodC5kZW1UZXh0dXJlKSx0LmZibyYmKHQuZmJvLmRlc3Ryb3koKSxkZWxldGUgdC5mYm8pLHQuZGVtJiZkZWxldGUgdC5kZW0sZGVsZXRlIHQubmVpZ2hib3JpbmdUaWxlcyx0LnN0YXRlPVwidW5sb2FkZWRcIix0aGlzLmRpc3BhdGNoZXIuc2VuZChcInJlbW92ZURFTVRpbGVcIix7dWlkOnQudWlkLHNvdXJjZTp0aGlzLmlkfSx2b2lkIDAsdC53b3JrZXJJRCk7fSxpfShLKSxKPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoaSxuLG8scil7ZS5jYWxsKHRoaXMpLHRoaXMuaWQ9aSx0aGlzLnR5cGU9XCJnZW9qc29uXCIsdGhpcy5taW56b29tPTAsdGhpcy5tYXh6b29tPTE4LHRoaXMudGlsZVNpemU9NTEyLHRoaXMuaXNUaWxlQ2xpcHBlZD0hMCx0aGlzLnJlcGFyc2VPdmVyc2NhbGVkPSEwLHRoaXMuX3JlbW92ZWQ9ITEsdGhpcy5kaXNwYXRjaGVyPW8sdGhpcy5zZXRFdmVudGVkUGFyZW50KHIpLHRoaXMuX2RhdGE9bi5kYXRhLHRoaXMuX29wdGlvbnM9dC5leHRlbmQoe30sbiksdGhpcy5fY29sbGVjdFJlc291cmNlVGltaW5nPW4uY29sbGVjdFJlc291cmNlVGltaW5nLHRoaXMuX3Jlc291cmNlVGltaW5nPVtdLHZvaWQgMCE9PW4ubWF4em9vbSYmKHRoaXMubWF4em9vbT1uLm1heHpvb20pLG4udHlwZSYmKHRoaXMudHlwZT1uLnR5cGUpO3ZhciBhPXQuZGVmYXVsdCQ4L3RoaXMudGlsZVNpemU7dGhpcy53b3JrZXJPcHRpb25zPXQuZXh0ZW5kKHtzb3VyY2U6dGhpcy5pZCxjbHVzdGVyOm4uY2x1c3Rlcnx8ITEsZ2VvanNvblZ0T3B0aW9uczp7YnVmZmVyOih2b2lkIDAhPT1uLmJ1ZmZlcj9uLmJ1ZmZlcjoxMjgpKmEsdG9sZXJhbmNlOih2b2lkIDAhPT1uLnRvbGVyYW5jZT9uLnRvbGVyYW5jZTouMzc1KSphLGV4dGVudDp0LmRlZmF1bHQkOCxtYXhab29tOnRoaXMubWF4em9vbSxsaW5lTWV0cmljczpuLmxpbmVNZXRyaWNzfHwhMX0sc3VwZXJjbHVzdGVyT3B0aW9uczp7bWF4Wm9vbTp2b2lkIDAhPT1uLmNsdXN0ZXJNYXhab29tP01hdGgubWluKG4uY2x1c3Rlck1heFpvb20sdGhpcy5tYXh6b29tLTEpOnRoaXMubWF4em9vbS0xLGV4dGVudDp0LmRlZmF1bHQkOCxyYWRpdXM6KG4uY2x1c3RlclJhZGl1c3x8NTApKmEsbG9nOiExfX0sbi53b3JrZXJPcHRpb25zKTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt2YXIgZT10aGlzO3RoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFsb2FkaW5nXCIse2RhdGFUeXBlOlwic291cmNlXCJ9KSksdGhpcy5fdXBkYXRlV29ya2VyRGF0YShmdW5jdGlvbihpKXtpZihpKWUuZmlyZShuZXcgdC5FcnJvckV2ZW50KGkpKTtlbHNle3ZhciBuPXtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwibWV0YWRhdGFcIn07ZS5fY29sbGVjdFJlc291cmNlVGltaW5nJiZlLl9yZXNvdXJjZVRpbWluZyYmZS5fcmVzb3VyY2VUaW1pbmcubGVuZ3RoPjAmJihuLnJlc291cmNlVGltaW5nPWUuX3Jlc291cmNlVGltaW5nLGUuX3Jlc291cmNlVGltaW5nPVtdKSxlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIsbikpO319KTt9LGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwPXQsdGhpcy5sb2FkKCk7fSxpLnByb3RvdHlwZS5zZXREYXRhPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXM7cmV0dXJuIHRoaXMuX2RhdGE9ZSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInNvdXJjZVwifSkpLHRoaXMuX3VwZGF0ZVdvcmtlckRhdGEoZnVuY3Rpb24oZSl7aWYoZSlyZXR1cm4gaS5maXJlKG5ldyB0LkVycm9yRXZlbnQoZSkpO3ZhciBuPXtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwiY29udGVudFwifTtpLl9jb2xsZWN0UmVzb3VyY2VUaW1pbmcmJmkuX3Jlc291cmNlVGltaW5nJiZpLl9yZXNvdXJjZVRpbWluZy5sZW5ndGg+MCYmKG4ucmVzb3VyY2VUaW1pbmc9aS5fcmVzb3VyY2VUaW1pbmcsaS5fcmVzb3VyY2VUaW1pbmc9W10pLGkuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIixuKSk7fSksdGhpc30saS5wcm90b3R5cGUuX3VwZGF0ZVdvcmtlckRhdGE9ZnVuY3Rpb24oZSl7dmFyIGksbixvPXRoaXMscj10LmV4dGVuZCh7fSx0aGlzLndvcmtlck9wdGlvbnMpLGE9dGhpcy5fZGF0YTtcInN0cmluZ1wiPT10eXBlb2YgYT8oci5yZXF1ZXN0PXRoaXMubWFwLl90cmFuc2Zvcm1SZXF1ZXN0KChpPWEsKG49dC5kZWZhdWx0LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpKS5ocmVmPWksbi5ocmVmKSx0LlJlc291cmNlVHlwZS5Tb3VyY2UpLHIucmVxdWVzdC5jb2xsZWN0UmVzb3VyY2VUaW1pbmc9dGhpcy5fY29sbGVjdFJlc291cmNlVGltaW5nKTpyLmRhdGE9SlNPTi5zdHJpbmdpZnkoYSksdGhpcy53b3JrZXJJRD10aGlzLmRpc3BhdGNoZXIuc2VuZCh0aGlzLnR5cGUrXCIuXCIrci5zb3VyY2UrXCIubG9hZERhdGFcIixyLGZ1bmN0aW9uKHQsaSl7by5fcmVtb3ZlZHx8aSYmaS5hYmFuZG9uZWR8fChvLl9sb2FkZWQ9ITAsaSYmaS5yZXNvdXJjZVRpbWluZyYmaS5yZXNvdXJjZVRpbWluZ1tvLmlkXSYmKG8uX3Jlc291cmNlVGltaW5nPWkucmVzb3VyY2VUaW1pbmdbby5pZF0uc2xpY2UoMCkpLG8uZGlzcGF0Y2hlci5zZW5kKG8udHlwZStcIi5cIityLnNvdXJjZStcIi5jb2FsZXNjZVwiLG51bGwsbnVsbCxvLndvcmtlcklEKSxlKHQpKTt9LHRoaXMud29ya2VySUQpO30saS5wcm90b3R5cGUubG9hZFRpbGU9ZnVuY3Rpb24odCxlKXt2YXIgaT10aGlzLG49dm9pZCAwPT09dC53b3JrZXJJRD9cImxvYWRUaWxlXCI6XCJyZWxvYWRUaWxlXCIsbz17dHlwZTp0aGlzLnR5cGUsdWlkOnQudWlkLHRpbGVJRDp0LnRpbGVJRCx6b29tOnQudGlsZUlELm92ZXJzY2FsZWRaLG1heFpvb206dGhpcy5tYXh6b29tLHRpbGVTaXplOnRoaXMudGlsZVNpemUsc291cmNlOnRoaXMuaWQscGl4ZWxSYXRpbzpyLmRldmljZVBpeGVsUmF0aW8sc2hvd0NvbGxpc2lvbkJveGVzOnRoaXMubWFwLnNob3dDb2xsaXNpb25Cb3hlc307dC53b3JrZXJJRD10aGlzLmRpc3BhdGNoZXIuc2VuZChuLG8sZnVuY3Rpb24obyxyKXtyZXR1cm4gdC51bmxvYWRWZWN0b3JEYXRhKCksdC5hYm9ydGVkP2UobnVsbCk6bz9lKG8pOih0LmxvYWRWZWN0b3JEYXRhKHIsaS5tYXAucGFpbnRlcixcInJlbG9hZFRpbGVcIj09PW4pLGUobnVsbCkpfSx0aGlzLndvcmtlcklEKTt9LGkucHJvdG90eXBlLmFib3J0VGlsZT1mdW5jdGlvbih0KXt0LmFib3J0ZWQ9ITA7fSxpLnByb3RvdHlwZS51bmxvYWRUaWxlPWZ1bmN0aW9uKHQpe3QudW5sb2FkVmVjdG9yRGF0YSgpLHRoaXMuZGlzcGF0Y2hlci5zZW5kKFwicmVtb3ZlVGlsZVwiLHt1aWQ6dC51aWQsdHlwZTp0aGlzLnR5cGUsc291cmNlOnRoaXMuaWR9LG51bGwsdC53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe3RoaXMuX3JlbW92ZWQ9ITAsdGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJyZW1vdmVTb3VyY2VcIix7dHlwZTp0aGlzLnR5cGUsc291cmNlOnRoaXMuaWR9LG51bGwsdGhpcy53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4gdC5leHRlbmQoe30sdGhpcy5fb3B0aW9ucyx7dHlwZTp0aGlzLnR5cGUsZGF0YTp0aGlzLl9kYXRhfSl9LGkucHJvdG90eXBlLmhhc1RyYW5zaXRpb249ZnVuY3Rpb24oKXtyZXR1cm4hMX0saX0odC5FdmVudGVkKTt2YXIgUT10LmNyZWF0ZUxheW91dChbe25hbWU6XCJhX3Bvc1wiLHR5cGU6XCJJbnQxNlwiLGNvbXBvbmVudHM6Mn0se25hbWU6XCJhX3RleHR1cmVfcG9zXCIsdHlwZTpcIkludDE2XCIsY29tcG9uZW50czoyfV0pLHR0PWZ1bmN0aW9uKCl7dGhpcy5ib3VuZFByb2dyYW09bnVsbCx0aGlzLmJvdW5kTGF5b3V0VmVydGV4QnVmZmVyPW51bGwsdGhpcy5ib3VuZFBhaW50VmVydGV4QnVmZmVycz1bXSx0aGlzLmJvdW5kSW5kZXhCdWZmZXI9bnVsbCx0aGlzLmJvdW5kVmVydGV4T2Zmc2V0PW51bGwsdGhpcy5ib3VuZER5bmFtaWNWZXJ0ZXhCdWZmZXI9bnVsbCx0aGlzLnZhbz1udWxsO307dHQucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24odCxlLGksbixvLHIsYSxzKXt0aGlzLmNvbnRleHQ9dDtmb3IodmFyIGw9dGhpcy5ib3VuZFBhaW50VmVydGV4QnVmZmVycy5sZW5ndGghPT1uLmxlbmd0aCxjPTA7IWwmJmM8bi5sZW5ndGg7YysrKXRoaXMuYm91bmRQYWludFZlcnRleEJ1ZmZlcnNbY10hPT1uW2NdJiYobD0hMCk7dmFyIHU9IXRoaXMudmFvfHx0aGlzLmJvdW5kUHJvZ3JhbSE9PWV8fHRoaXMuYm91bmRMYXlvdXRWZXJ0ZXhCdWZmZXIhPT1pfHxsfHx0aGlzLmJvdW5kSW5kZXhCdWZmZXIhPT1vfHx0aGlzLmJvdW5kVmVydGV4T2Zmc2V0IT09cnx8dGhpcy5ib3VuZER5bmFtaWNWZXJ0ZXhCdWZmZXIhPT1hfHx0aGlzLmJvdW5kRHluYW1pY1ZlcnRleEJ1ZmZlcjIhPT1zOyF0LmV4dFZlcnRleEFycmF5T2JqZWN0fHx1P3RoaXMuZnJlc2hCaW5kKGUsaSxuLG8scixhLHMpOih0LmJpbmRWZXJ0ZXhBcnJheU9FUy5zZXQodGhpcy52YW8pLGEmJmEuYmluZCgpLG8mJm8uZHluYW1pY0RyYXcmJm8uYmluZCgpLHMmJnMuYmluZCgpKTt9LHR0LnByb3RvdHlwZS5mcmVzaEJpbmQ9ZnVuY3Rpb24odCxlLGksbixvLHIsYSl7dmFyIHMsbD10Lm51bUF0dHJpYnV0ZXMsYz10aGlzLmNvbnRleHQsdT1jLmdsO2lmKGMuZXh0VmVydGV4QXJyYXlPYmplY3QpdGhpcy52YW8mJnRoaXMuZGVzdHJveSgpLHRoaXMudmFvPWMuZXh0VmVydGV4QXJyYXlPYmplY3QuY3JlYXRlVmVydGV4QXJyYXlPRVMoKSxjLmJpbmRWZXJ0ZXhBcnJheU9FUy5zZXQodGhpcy52YW8pLHM9MCx0aGlzLmJvdW5kUHJvZ3JhbT10LHRoaXMuYm91bmRMYXlvdXRWZXJ0ZXhCdWZmZXI9ZSx0aGlzLmJvdW5kUGFpbnRWZXJ0ZXhCdWZmZXJzPWksdGhpcy5ib3VuZEluZGV4QnVmZmVyPW4sdGhpcy5ib3VuZFZlcnRleE9mZnNldD1vLHRoaXMuYm91bmREeW5hbWljVmVydGV4QnVmZmVyPXIsdGhpcy5ib3VuZER5bmFtaWNWZXJ0ZXhCdWZmZXIyPWE7ZWxzZXtzPWMuY3VycmVudE51bUF0dHJpYnV0ZXN8fDA7Zm9yKHZhciBoPWw7aDxzO2grKyl1LmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShoKTt9ZS5lbmFibGVBdHRyaWJ1dGVzKHUsdCk7Zm9yKHZhciBwPTAsZD1pO3A8ZC5sZW5ndGg7cCs9MSl7ZFtwXS5lbmFibGVBdHRyaWJ1dGVzKHUsdCk7fXImJnIuZW5hYmxlQXR0cmlidXRlcyh1LHQpLGEmJmEuZW5hYmxlQXR0cmlidXRlcyh1LHQpLGUuYmluZCgpLGUuc2V0VmVydGV4QXR0cmliUG9pbnRlcnModSx0LG8pO2Zvcih2YXIgZj0wLG09aTtmPG0ubGVuZ3RoO2YrPTEpe3ZhciBfPW1bZl07Xy5iaW5kKCksXy5zZXRWZXJ0ZXhBdHRyaWJQb2ludGVycyh1LHQsbyk7fXImJihyLmJpbmQoKSxyLnNldFZlcnRleEF0dHJpYlBvaW50ZXJzKHUsdCxvKSksbiYmbi5iaW5kKCksYSYmKGEuYmluZCgpLGEuc2V0VmVydGV4QXR0cmliUG9pbnRlcnModSx0LG8pKSxjLmN1cnJlbnROdW1BdHRyaWJ1dGVzPWw7fSx0dC5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMudmFvJiYodGhpcy5jb250ZXh0LmV4dFZlcnRleEFycmF5T2JqZWN0LmRlbGV0ZVZlcnRleEFycmF5T0VTKHRoaXMudmFvKSx0aGlzLnZhbz1udWxsKTt9O3ZhciBldD1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKHQsaSxuLG8pe2UuY2FsbCh0aGlzKSx0aGlzLmlkPXQsdGhpcy5kaXNwYXRjaGVyPW4sdGhpcy5jb29yZGluYXRlcz1pLmNvb3JkaW5hdGVzLHRoaXMudHlwZT1cImltYWdlXCIsdGhpcy5taW56b29tPTAsdGhpcy5tYXh6b29tPTIyLHRoaXMudGlsZVNpemU9NTEyLHRoaXMudGlsZXM9e30sdGhpcy5zZXRFdmVudGVkUGFyZW50KG8pLHRoaXMub3B0aW9ucz1pO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUubG9hZD1mdW5jdGlvbigpe3ZhciBlPXRoaXM7dGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YWxvYWRpbmdcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIn0pKSx0aGlzLnVybD10aGlzLm9wdGlvbnMudXJsLHQuZ2V0SW1hZ2UodGhpcy5tYXAuX3RyYW5zZm9ybVJlcXVlc3QodGhpcy51cmwsdC5SZXNvdXJjZVR5cGUuSW1hZ2UpLGZ1bmN0aW9uKGksbil7aT9lLmZpcmUobmV3IHQuRXJyb3JFdmVudChpKSk6biYmKGUuaW1hZ2U9ci5nZXRJbWFnZURhdGEobiksZS5fZmluaXNoTG9hZGluZygpKTt9KTt9LGkucHJvdG90eXBlLl9maW5pc2hMb2FkaW5nPWZ1bmN0aW9uKCl7dGhpcy5tYXAmJih0aGlzLnNldENvb3JkaW5hdGVzKHRoaXMuY29vcmRpbmF0ZXMpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIixzb3VyY2VEYXRhVHlwZTpcIm1ldGFkYXRhXCJ9KSkpO30saS5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5tYXA9dCx0aGlzLmxvYWQoKTt9LGkucHJvdG90eXBlLnNldENvb3JkaW5hdGVzPWZ1bmN0aW9uKGUpe3RoaXMuY29vcmRpbmF0ZXM9ZTt2YXIgaT10aGlzLm1hcCxuPWUubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBpLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUoVy5jb252ZXJ0KHQpKS56b29tVG8oMCl9KSxvPXRoaXMuY2VudGVyQ29vcmQ9dC5nZXRDb29yZGluYXRlc0NlbnRlcihuKTtvLmNvbHVtbj1NYXRoLmZsb29yKG8uY29sdW1uKSxvLnJvdz1NYXRoLmZsb29yKG8ucm93KSx0aGlzLnRpbGVJRD1uZXcgdC5DYW5vbmljYWxUaWxlSUQoby56b29tLG8uY29sdW1uLG8ucm93KSx0aGlzLm1pbnpvb209dGhpcy5tYXh6b29tPW8uem9vbTt2YXIgcj1uLm1hcChmdW5jdGlvbihlKXt2YXIgaT1lLnpvb21UbyhvLnpvb20pO3JldHVybiBuZXcgdC5kZWZhdWx0JDEoTWF0aC5yb3VuZCgoaS5jb2x1bW4tby5jb2x1bW4pKnQuZGVmYXVsdCQ4KSxNYXRoLnJvdW5kKChpLnJvdy1vLnJvdykqdC5kZWZhdWx0JDgpKX0pO3JldHVybiB0aGlzLl9ib3VuZHNBcnJheT1uZXcgdC5SYXN0ZXJCb3VuZHNBcnJheSx0aGlzLl9ib3VuZHNBcnJheS5lbXBsYWNlQmFjayhyWzBdLngsclswXS55LDAsMCksdGhpcy5fYm91bmRzQXJyYXkuZW1wbGFjZUJhY2soclsxXS54LHJbMV0ueSx0LmRlZmF1bHQkOCwwKSx0aGlzLl9ib3VuZHNBcnJheS5lbXBsYWNlQmFjayhyWzNdLngsclszXS55LDAsdC5kZWZhdWx0JDgpLHRoaXMuX2JvdW5kc0FycmF5LmVtcGxhY2VCYWNrKHJbMl0ueCxyWzJdLnksdC5kZWZhdWx0JDgsdC5kZWZhdWx0JDgpLHRoaXMuYm91bmRzQnVmZmVyJiYodGhpcy5ib3VuZHNCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLmJvdW5kc0J1ZmZlciksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwiY29udGVudFwifSkpLHRoaXN9LGkucHJvdG90eXBlLnByZXBhcmU9ZnVuY3Rpb24oKXtpZigwIT09T2JqZWN0LmtleXModGhpcy50aWxlcykubGVuZ3RoJiZ0aGlzLmltYWdlKXt2YXIgdD10aGlzLm1hcC5wYWludGVyLmNvbnRleHQsZT10LmdsO2Zvcih2YXIgaSBpbiB0aGlzLmJvdW5kc0J1ZmZlcnx8KHRoaXMuYm91bmRzQnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMuX2JvdW5kc0FycmF5LFEubWVtYmVycykpLHRoaXMuYm91bmRzVkFPfHwodGhpcy5ib3VuZHNWQU89bmV3IHR0KSx0aGlzLnRleHR1cmV8fCh0aGlzLnRleHR1cmU9bmV3IE0odCx0aGlzLmltYWdlLGUuUkdCQSksdGhpcy50ZXh0dXJlLmJpbmQoZS5MSU5FQVIsZS5DTEFNUF9UT19FREdFKSksdGhpcy50aWxlcyl7dmFyIG49dGhpcy50aWxlc1tpXTtcImxvYWRlZFwiIT09bi5zdGF0ZSYmKG4uc3RhdGU9XCJsb2FkZWRcIixuLnRleHR1cmU9dGhpcy50ZXh0dXJlKTt9fX0saS5wcm90b3R5cGUubG9hZFRpbGU9ZnVuY3Rpb24odCxlKXt0aGlzLnRpbGVJRCYmdGhpcy50aWxlSUQuZXF1YWxzKHQudGlsZUlELmNhbm9uaWNhbCk/KHRoaXMudGlsZXNbU3RyaW5nKHQudGlsZUlELndyYXApXT10LHQuYnVja2V0cz17fSxlKG51bGwpKToodC5zdGF0ZT1cImVycm9yZWRcIixlKG51bGwpKTt9LGkucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3JldHVybnt0eXBlOlwiaW1hZ2VcIix1cmw6dGhpcy5vcHRpb25zLnVybCxjb29yZGluYXRlczp0aGlzLmNvb3JkaW5hdGVzfX0saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiExfSxpfSh0LkV2ZW50ZWQpLGl0PWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkodCxpLG4sbyl7ZS5jYWxsKHRoaXMsdCxpLG4sbyksdGhpcy5yb3VuZFpvb209ITAsdGhpcy50eXBlPVwidmlkZW9cIix0aGlzLm9wdGlvbnM9aTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLGk9dGhpcy5vcHRpb25zO3RoaXMudXJscz1bXTtmb3IodmFyIG49MCxvPWkudXJscztuPG8ubGVuZ3RoO24rPTEpe3ZhciByPW9bbl07ZS51cmxzLnB1c2goZS5tYXAuX3RyYW5zZm9ybVJlcXVlc3Qocix0LlJlc291cmNlVHlwZS5Tb3VyY2UpLnVybCk7fXQuZ2V0VmlkZW8odGhpcy51cmxzLGZ1bmN0aW9uKGksbil7aT9lLmZpcmUobmV3IHQuRXJyb3JFdmVudChpKSk6biYmKGUudmlkZW89bixlLnZpZGVvLmxvb3A9ITAsZS52aWRlby5hZGRFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLGZ1bmN0aW9uKCl7ZS5tYXAuX3JlcmVuZGVyKCk7fSksZS5tYXAmJmUudmlkZW8ucGxheSgpLGUuX2ZpbmlzaExvYWRpbmcoKSk7fSk7fSxpLnByb3RvdHlwZS5nZXRWaWRlbz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnZpZGVvfSxpLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt0aGlzLm1hcHx8KHRoaXMubWFwPXQsdGhpcy5sb2FkKCksdGhpcy52aWRlbyYmKHRoaXMudmlkZW8ucGxheSgpLHRoaXMuc2V0Q29vcmRpbmF0ZXModGhpcy5jb29yZGluYXRlcykpKTt9LGkucHJvdG90eXBlLnByZXBhcmU9ZnVuY3Rpb24oKXtpZighKDA9PT1PYmplY3Qua2V5cyh0aGlzLnRpbGVzKS5sZW5ndGh8fHRoaXMudmlkZW8ucmVhZHlTdGF0ZTwyKSl7dmFyIHQ9dGhpcy5tYXAucGFpbnRlci5jb250ZXh0LGU9dC5nbDtmb3IodmFyIGkgaW4gdGhpcy5ib3VuZHNCdWZmZXJ8fCh0aGlzLmJvdW5kc0J1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLl9ib3VuZHNBcnJheSxRLm1lbWJlcnMpKSx0aGlzLmJvdW5kc1ZBT3x8KHRoaXMuYm91bmRzVkFPPW5ldyB0dCksdGhpcy50ZXh0dXJlP3RoaXMudmlkZW8ucGF1c2VkfHwodGhpcy50ZXh0dXJlLmJpbmQoZS5MSU5FQVIsZS5DTEFNUF9UT19FREdFKSxlLnRleFN1YkltYWdlMkQoZS5URVhUVVJFXzJELDAsMCwwLGUuUkdCQSxlLlVOU0lHTkVEX0JZVEUsdGhpcy52aWRlbykpOih0aGlzLnRleHR1cmU9bmV3IE0odCx0aGlzLnZpZGVvLGUuUkdCQSksdGhpcy50ZXh0dXJlLmJpbmQoZS5MSU5FQVIsZS5DTEFNUF9UT19FREdFKSksdGhpcy50aWxlcyl7dmFyIG49dGhpcy50aWxlc1tpXTtcImxvYWRlZFwiIT09bi5zdGF0ZSYmKG4uc3RhdGU9XCJsb2FkZWRcIixuLnRleHR1cmU9dGhpcy50ZXh0dXJlKTt9fX0saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJue3R5cGU6XCJ2aWRlb1wiLHVybHM6dGhpcy51cmxzLGNvb3JkaW5hdGVzOnRoaXMuY29vcmRpbmF0ZXN9fSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmlkZW8mJiF0aGlzLnZpZGVvLnBhdXNlZH0saX0oZXQpLG50PWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoaSxuLG8scil7ZS5jYWxsKHRoaXMsaSxuLG8sciksbi5jb29yZGluYXRlcz9BcnJheS5pc0FycmF5KG4uY29vcmRpbmF0ZXMpJiY0PT09bi5jb29yZGluYXRlcy5sZW5ndGgmJiFuLmNvb3JkaW5hdGVzLnNvbWUoZnVuY3Rpb24odCl7cmV0dXJuIUFycmF5LmlzQXJyYXkodCl8fDIhPT10Lmxlbmd0aHx8dC5zb21lKGZ1bmN0aW9uKHQpe3JldHVyblwibnVtYmVyXCIhPXR5cGVvZiB0fSl9KXx8dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuZGVmYXVsdCQ5KFwic291cmNlcy5cIitpLG51bGwsJ1wiY29vcmRpbmF0ZXNcIiBwcm9wZXJ0eSBtdXN0IGJlIGFuIGFycmF5IG9mIDQgbG9uZ2l0dWRlL2xhdGl0dWRlIGFycmF5IHBhaXJzJykpKTp0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgdC5kZWZhdWx0JDkoXCJzb3VyY2VzLlwiK2ksbnVsbCwnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcImNvb3JkaW5hdGVzXCInKSkpLG4uYW5pbWF0ZSYmXCJib29sZWFuXCIhPXR5cGVvZiBuLmFuaW1hdGUmJnRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyB0LmRlZmF1bHQkOShcInNvdXJjZXMuXCIraSxudWxsLCdvcHRpb25hbCBcImFuaW1hdGVcIiBwcm9wZXJ0eSBtdXN0IGJlIGEgYm9vbGVhbiB2YWx1ZScpKSksbi5jYW52YXM/XCJzdHJpbmdcIj09dHlwZW9mIG4uY2FudmFzfHxuLmNhbnZhcyBpbnN0YW5jZW9mIHQuZGVmYXVsdC5IVE1MQ2FudmFzRWxlbWVudHx8dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuZGVmYXVsdCQ5KFwic291cmNlcy5cIitpLG51bGwsJ1wiY2FudmFzXCIgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBJRCBvZiB0aGUgY2FudmFzIGVsZW1lbnQgZnJvbSB3aGljaCB0byByZWFkLCBvciBhbiBIVE1MQ2FudmFzRWxlbWVudCBpbnN0YW5jZScpKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuZGVmYXVsdCQ5KFwic291cmNlcy5cIitpLG51bGwsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCJjYW52YXNcIicpKSksdGhpcy5vcHRpb25zPW4sdGhpcy5hbmltYXRlPXZvaWQgMD09PW4uYW5pbWF0ZXx8bi5hbmltYXRlO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUubG9hZD1mdW5jdGlvbigpe3RoaXMuY2FudmFzfHwodGhpcy5jYW52YXM9dGhpcy5vcHRpb25zLmNhbnZhcyBpbnN0YW5jZW9mIHQuZGVmYXVsdC5IVE1MQ2FudmFzRWxlbWVudD90aGlzLm9wdGlvbnMuY2FudmFzOnQuZGVmYXVsdC5kb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLm9wdGlvbnMuY2FudmFzKSksdGhpcy53aWR0aD10aGlzLmNhbnZhcy53aWR0aCx0aGlzLmhlaWdodD10aGlzLmNhbnZhcy5oZWlnaHQsdGhpcy5faGFzSW52YWxpZERpbWVuc2lvbnMoKT90aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJDYW52YXMgZGltZW5zaW9ucyBjYW5ub3QgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHplcm8uXCIpKSk6KHRoaXMucGxheT1mdW5jdGlvbigpe3RoaXMuX3BsYXlpbmc9ITAsdGhpcy5tYXAuX3JlcmVuZGVyKCk7fSx0aGlzLnBhdXNlPWZ1bmN0aW9uKCl7dGhpcy5fcGxheWluZz0hMTt9LHRoaXMuX2ZpbmlzaExvYWRpbmcoKSk7fSxpLnByb3RvdHlwZS5nZXRDYW52YXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jYW52YXN9LGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwPXQsdGhpcy5sb2FkKCksdGhpcy5jYW52YXMmJnRoaXMuYW5pbWF0ZSYmdGhpcy5wbGF5KCk7fSxpLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe3RoaXMucGF1c2UoKTt9LGkucHJvdG90eXBlLnByZXBhcmU9ZnVuY3Rpb24oKXt2YXIgdD0hMTtpZih0aGlzLmNhbnZhcy53aWR0aCE9PXRoaXMud2lkdGgmJih0aGlzLndpZHRoPXRoaXMuY2FudmFzLndpZHRoLHQ9ITApLHRoaXMuY2FudmFzLmhlaWdodCE9PXRoaXMuaGVpZ2h0JiYodGhpcy5oZWlnaHQ9dGhpcy5jYW52YXMuaGVpZ2h0LHQ9ITApLCF0aGlzLl9oYXNJbnZhbGlkRGltZW5zaW9ucygpJiYwIT09T2JqZWN0LmtleXModGhpcy50aWxlcykubGVuZ3RoKXt2YXIgZT10aGlzLm1hcC5wYWludGVyLmNvbnRleHQsaT1lLmdsO2Zvcih2YXIgbiBpbiB0aGlzLmJvdW5kc0J1ZmZlcnx8KHRoaXMuYm91bmRzQnVmZmVyPWUuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMuX2JvdW5kc0FycmF5LFEubWVtYmVycykpLHRoaXMuYm91bmRzVkFPfHwodGhpcy5ib3VuZHNWQU89bmV3IHR0KSx0aGlzLnRleHR1cmU/dD90aGlzLnRleHR1cmUudXBkYXRlKHRoaXMuY2FudmFzKTp0aGlzLl9wbGF5aW5nJiYodGhpcy50ZXh0dXJlLmJpbmQoaS5MSU5FQVIsaS5DTEFNUF9UT19FREdFKSxpLnRleFN1YkltYWdlMkQoaS5URVhUVVJFXzJELDAsMCwwLGkuUkdCQSxpLlVOU0lHTkVEX0JZVEUsdGhpcy5jYW52YXMpKToodGhpcy50ZXh0dXJlPW5ldyBNKGUsdGhpcy5jYW52YXMsaS5SR0JBKSx0aGlzLnRleHR1cmUuYmluZChpLkxJTkVBUixpLkNMQU1QX1RPX0VER0UpKSx0aGlzLnRpbGVzKXt2YXIgbz10aGlzLnRpbGVzW25dO1wibG9hZGVkXCIhPT1vLnN0YXRlJiYoby5zdGF0ZT1cImxvYWRlZFwiLG8udGV4dHVyZT10aGlzLnRleHR1cmUpO319fSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm57dHlwZTpcImNhbnZhc1wiLGNvb3JkaW5hdGVzOnRoaXMuY29vcmRpbmF0ZXN9fSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3BsYXlpbmd9LGkucHJvdG90eXBlLl9oYXNJbnZhbGlkRGltZW5zaW9ucz1mdW5jdGlvbigpe2Zvcih2YXIgdD0wLGU9W3RoaXMuY2FudmFzLndpZHRoLHRoaXMuY2FudmFzLmhlaWdodF07dDxlLmxlbmd0aDt0Kz0xKXt2YXIgaT1lW3RdO2lmKGlzTmFOKGkpfHxpPD0wKXJldHVybiEwfXJldHVybiExfSxpfShldCksb3Q9e3ZlY3RvcjpILHJhc3RlcjpLLFwicmFzdGVyLWRlbVwiOlksZ2VvanNvbjpKLHZpZGVvOml0LGltYWdlOmV0LGNhbnZhczpudH0scnQ9ZnVuY3Rpb24oZSxpLG4sbyl7dmFyIHI9bmV3IG90W2kudHlwZV0oZSxpLG4sbyk7aWYoci5pZCE9PWUpdGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0ZWQgU291cmNlIGlkIHRvIGJlIFwiK2UrXCIgaW5zdGVhZCBvZiBcIityLmlkKTtyZXR1cm4gdC5iaW5kQWxsKFtcImxvYWRcIixcImFib3J0XCIsXCJ1bmxvYWRcIixcInNlcmlhbGl6ZVwiLFwicHJlcGFyZVwiXSxyKSxyfTtmdW5jdGlvbiBhdCh0LGUsaSxuLG8pe3ZhciByPW8ubWF4UGl0Y2hTY2FsZUZhY3RvcigpLGE9dC50aWxlc0luKGkscik7YS5zb3J0KHN0KTtmb3IodmFyIHM9W10sbD0wLGM9YTtsPGMubGVuZ3RoO2wrPTEpe3ZhciB1PWNbbF07cy5wdXNoKHt3cmFwcGVkVGlsZUlEOnUudGlsZUlELndyYXBwZWQoKS5rZXkscXVlcnlSZXN1bHRzOnUudGlsZS5xdWVyeVJlbmRlcmVkRmVhdHVyZXMoZSx1LnF1ZXJ5R2VvbWV0cnksdS5zY2FsZSxuLG8scix0LnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgodS50aWxlSUQudG9VbndyYXBwZWQoKSkpfSk7fXJldHVybiBmdW5jdGlvbih0KXtmb3IodmFyIGU9e30saT17fSxuPTAsbz10O248by5sZW5ndGg7bis9MSl7dmFyIHI9b1tuXSxhPXIucXVlcnlSZXN1bHRzLHM9ci53cmFwcGVkVGlsZUlELGw9aVtzXT1pW3NdfHx7fTtmb3IodmFyIGMgaW4gYSlmb3IodmFyIHU9YVtjXSxoPWxbY109bFtjXXx8e30scD1lW2NdPWVbY118fFtdLGQ9MCxmPXU7ZDxmLmxlbmd0aDtkKz0xKXt2YXIgbT1mW2RdO2hbbS5mZWF0dXJlSW5kZXhdfHwoaFttLmZlYXR1cmVJbmRleF09ITAscC5wdXNoKG0uZmVhdHVyZSkpO319cmV0dXJuIGV9KHMpfWZ1bmN0aW9uIHN0KHQsZSl7dmFyIGk9dC50aWxlSUQsbj1lLnRpbGVJRDtyZXR1cm4gaS5vdmVyc2NhbGVkWi1uLm92ZXJzY2FsZWRafHxpLmNhbm9uaWNhbC55LW4uY2Fub25pY2FsLnl8fGkud3JhcC1uLndyYXB8fGkuY2Fub25pY2FsLngtbi5jYW5vbmljYWwueH12YXIgbHQ9ZnVuY3Rpb24oZSxpKXt0aGlzLnRpbGVJRD1lLHRoaXMudWlkPXQudW5pcXVlSWQoKSx0aGlzLnVzZXM9MCx0aGlzLnRpbGVTaXplPWksdGhpcy5idWNrZXRzPXt9LHRoaXMuZXhwaXJhdGlvblRpbWU9bnVsbCx0aGlzLnF1ZXJ5UGFkZGluZz0wLHRoaXMuZXhwaXJlZFJlcXVlc3RDb3VudD0wLHRoaXMuc3RhdGU9XCJsb2FkaW5nXCI7fTtsdC5wcm90b3R5cGUucmVnaXN0ZXJGYWRlRHVyYXRpb249ZnVuY3Rpb24odCl7dmFyIGU9dCt0aGlzLnRpbWVBZGRlZDtlPHIubm93KCl8fHRoaXMuZmFkZUVuZFRpbWUmJmU8dGhpcy5mYWRlRW5kVGltZXx8KHRoaXMuZmFkZUVuZFRpbWU9ZSk7fSxsdC5wcm90b3R5cGUud2FzUmVxdWVzdGVkPWZ1bmN0aW9uKCl7cmV0dXJuXCJlcnJvcmVkXCI9PT10aGlzLnN0YXRlfHxcImxvYWRlZFwiPT09dGhpcy5zdGF0ZXx8XCJyZWxvYWRpbmdcIj09PXRoaXMuc3RhdGV9LGx0LnByb3RvdHlwZS5sb2FkVmVjdG9yRGF0YT1mdW5jdGlvbihlLGksbil7aWYodGhpcy5oYXNEYXRhKCkmJnRoaXMudW5sb2FkVmVjdG9yRGF0YSgpLHRoaXMuc3RhdGU9XCJsb2FkZWRcIixlKXtpZihlLmZlYXR1cmVJbmRleCYmKHRoaXMubGF0ZXN0RmVhdHVyZUluZGV4PWUuZmVhdHVyZUluZGV4LGUucmF3VGlsZURhdGE/KHRoaXMubGF0ZXN0UmF3VGlsZURhdGE9ZS5yYXdUaWxlRGF0YSx0aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5yYXdUaWxlRGF0YT1lLnJhd1RpbGVEYXRhKTp0aGlzLmxhdGVzdFJhd1RpbGVEYXRhJiYodGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgucmF3VGlsZURhdGE9dGhpcy5sYXRlc3RSYXdUaWxlRGF0YSkpLHRoaXMuY29sbGlzaW9uQm94QXJyYXk9ZS5jb2xsaXNpb25Cb3hBcnJheSx0aGlzLmJ1Y2tldHM9ZnVuY3Rpb24odCxlKXt2YXIgaT17fTtpZighZSlyZXR1cm4gaTtmb3IodmFyIG49MCxvPXQ7bjxvLmxlbmd0aDtuKz0xKXt2YXIgcj1vW25dLGE9ci5sYXllcklkcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIGUuZ2V0TGF5ZXIodCl9KS5maWx0ZXIoQm9vbGVhbik7aWYoMCE9PWEubGVuZ3RoKXtyLmxheWVycz1hO2Zvcih2YXIgcz0wLGw9YTtzPGwubGVuZ3RoO3MrPTEpaVtsW3NdLmlkXT1yO319cmV0dXJuIGl9KGUuYnVja2V0cyxpLnN0eWxlKSxuKWZvcih2YXIgbyBpbiB0aGlzLmJ1Y2tldHMpe3ZhciByPXRoaXMuYnVja2V0c1tvXTtyIGluc3RhbmNlb2YgdC5kZWZhdWx0JDE0JiYoci5qdXN0UmVsb2FkZWQ9ITApO31mb3IodmFyIGEgaW4gdGhpcy5xdWVyeVBhZGRpbmc9MCx0aGlzLmJ1Y2tldHMpe3ZhciBzPXRoaXMuYnVja2V0c1thXTt0aGlzLnF1ZXJ5UGFkZGluZz1NYXRoLm1heCh0aGlzLnF1ZXJ5UGFkZGluZyxpLnN0eWxlLmdldExheWVyKHMubGF5ZXJJZHNbMF0pLnF1ZXJ5UmFkaXVzKHMpKTt9ZS5pY29uQXRsYXNJbWFnZSYmKHRoaXMuaWNvbkF0bGFzSW1hZ2U9ZS5pY29uQXRsYXNJbWFnZSksZS5nbHlwaEF0bGFzSW1hZ2UmJih0aGlzLmdseXBoQXRsYXNJbWFnZT1lLmdseXBoQXRsYXNJbWFnZSk7fWVsc2UgdGhpcy5jb2xsaXNpb25Cb3hBcnJheT1uZXcgdC5Db2xsaXNpb25Cb3hBcnJheTt9LGx0LnByb3RvdHlwZS51bmxvYWRWZWN0b3JEYXRhPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuYnVja2V0cyl0aGlzLmJ1Y2tldHNbdF0uZGVzdHJveSgpO3RoaXMuYnVja2V0cz17fSx0aGlzLmljb25BdGxhc1RleHR1cmUmJnRoaXMuaWNvbkF0bGFzVGV4dHVyZS5kZXN0cm95KCksdGhpcy5nbHlwaEF0bGFzVGV4dHVyZSYmdGhpcy5nbHlwaEF0bGFzVGV4dHVyZS5kZXN0cm95KCksdGhpcy5sYXRlc3RGZWF0dXJlSW5kZXg9bnVsbCx0aGlzLnN0YXRlPVwidW5sb2FkZWRcIjt9LGx0LnByb3RvdHlwZS51bmxvYWRERU1EYXRhPWZ1bmN0aW9uKCl7dGhpcy5kZW09bnVsbCx0aGlzLm5laWdoYm9yaW5nVGlsZXM9bnVsbCx0aGlzLnN0YXRlPVwidW5sb2FkZWRcIjt9LGx0LnByb3RvdHlwZS5nZXRCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYnVja2V0c1t0LmlkXX0sbHQucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXtmb3IodmFyIGUgaW4gdGhpcy5idWNrZXRzKXt2YXIgaT10aGlzLmJ1Y2tldHNbZV07aS51cGxvYWRlZHx8KGkudXBsb2FkKHQpLGkudXBsb2FkZWQ9ITApO312YXIgbj10LmdsO3RoaXMuaWNvbkF0bGFzSW1hZ2UmJih0aGlzLmljb25BdGxhc1RleHR1cmU9bmV3IE0odCx0aGlzLmljb25BdGxhc0ltYWdlLG4uUkdCQSksdGhpcy5pY29uQXRsYXNJbWFnZT1udWxsKSx0aGlzLmdseXBoQXRsYXNJbWFnZSYmKHRoaXMuZ2x5cGhBdGxhc1RleHR1cmU9bmV3IE0odCx0aGlzLmdseXBoQXRsYXNJbWFnZSxuLkFMUEhBKSx0aGlzLmdseXBoQXRsYXNJbWFnZT1udWxsKTt9LGx0LnByb3RvdHlwZS5xdWVyeVJlbmRlcmVkRmVhdHVyZXM9ZnVuY3Rpb24odCxlLGksbixvLHIsYSl7cmV0dXJuIHRoaXMubGF0ZXN0RmVhdHVyZUluZGV4JiZ0aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5yYXdUaWxlRGF0YT90aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5xdWVyeSh7cXVlcnlHZW9tZXRyeTplLHNjYWxlOmksdGlsZVNpemU6dGhpcy50aWxlU2l6ZSxwb3NNYXRyaXg6YSx0cmFuc2Zvcm06byxwYXJhbXM6bixxdWVyeVBhZGRpbmc6dGhpcy5xdWVyeVBhZGRpbmcqcn0sdCk6e319LGx0LnByb3RvdHlwZS5xdWVyeVNvdXJjZUZlYXR1cmVzPWZ1bmN0aW9uKGUsaSl7aWYodGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgmJnRoaXMubGF0ZXN0RmVhdHVyZUluZGV4LnJhd1RpbGVEYXRhKXt2YXIgbj10aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5sb2FkVlRMYXllcnMoKSxvPWk/aS5zb3VyY2VMYXllcjpcIlwiLHI9bi5fZ2VvanNvblRpbGVMYXllcnx8bltvXTtpZihyKWZvcih2YXIgYT10LmRlZmF1bHQkMTMoaSYmaS5maWx0ZXIpLHM9e3o6dGhpcy50aWxlSUQub3ZlcnNjYWxlZFoseDp0aGlzLnRpbGVJRC5jYW5vbmljYWwueCx5OnRoaXMudGlsZUlELmNhbm9uaWNhbC55fSxsPTA7bDxyLmxlbmd0aDtsKyspe3ZhciBjPXIuZmVhdHVyZShsKTtpZihhKG5ldyB0LmRlZmF1bHQkMTYodGhpcy50aWxlSUQub3ZlcnNjYWxlZFopLGMpKXt2YXIgdT1uZXcgdC5kZWZhdWx0JDEyKGMscy56LHMueCxzLnkpO3UudGlsZT1zLGUucHVzaCh1KTt9fX19LGx0LnByb3RvdHlwZS5jbGVhck1hc2s9ZnVuY3Rpb24oKXt0aGlzLnNlZ21lbnRzJiYodGhpcy5zZWdtZW50cy5kZXN0cm95KCksZGVsZXRlIHRoaXMuc2VnbWVudHMpLHRoaXMubWFza2VkQm91bmRzQnVmZmVyJiYodGhpcy5tYXNrZWRCb3VuZHNCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLm1hc2tlZEJvdW5kc0J1ZmZlciksdGhpcy5tYXNrZWRJbmRleEJ1ZmZlciYmKHRoaXMubWFza2VkSW5kZXhCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLm1hc2tlZEluZGV4QnVmZmVyKTt9LGx0LnByb3RvdHlwZS5zZXRNYXNrPWZ1bmN0aW9uKGUsaSl7aWYoIXQuZGVmYXVsdCQxMCh0aGlzLm1hc2ssZSkmJih0aGlzLm1hc2s9ZSx0aGlzLmNsZWFyTWFzaygpLCF0LmRlZmF1bHQkMTAoZSx7MDohMH0pKSl7dmFyIG49bmV3IHQuUmFzdGVyQm91bmRzQXJyYXksbz1uZXcgdC5UcmlhbmdsZUluZGV4QXJyYXk7dGhpcy5zZWdtZW50cz1uZXcgdC5kZWZhdWx0JDE1LHRoaXMuc2VnbWVudHMucHJlcGFyZVNlZ21lbnQoMCxuLG8pO2Zvcih2YXIgcj1PYmplY3Qua2V5cyhlKSxhPTA7YTxyLmxlbmd0aDthKyspe3ZhciBzPWVbclthXV0sbD10LmRlZmF1bHQkOD4+cy56LGM9bmV3IHQuZGVmYXVsdCQxKHMueCpsLHMueSpsKSx1PW5ldyB0LmRlZmF1bHQkMShjLngrbCxjLnkrbCksaD10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDQsbixvKTtuLmVtcGxhY2VCYWNrKGMueCxjLnksYy54LGMueSksbi5lbXBsYWNlQmFjayh1LngsYy55LHUueCxjLnkpLG4uZW1wbGFjZUJhY2soYy54LHUueSxjLngsdS55KSxuLmVtcGxhY2VCYWNrKHUueCx1LnksdS54LHUueSk7dmFyIHA9aC52ZXJ0ZXhMZW5ndGg7by5lbXBsYWNlQmFjayhwLHArMSxwKzIpLG8uZW1wbGFjZUJhY2socCsxLHArMixwKzMpLGgudmVydGV4TGVuZ3RoKz00LGgucHJpbWl0aXZlTGVuZ3RoKz0yO310aGlzLm1hc2tlZEJvdW5kc0J1ZmZlcj1pLmNyZWF0ZVZlcnRleEJ1ZmZlcihuLFEubWVtYmVycyksdGhpcy5tYXNrZWRJbmRleEJ1ZmZlcj1pLmNyZWF0ZUluZGV4QnVmZmVyKG8pO319LGx0LnByb3RvdHlwZS5oYXNEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuXCJsb2FkZWRcIj09PXRoaXMuc3RhdGV8fFwicmVsb2FkaW5nXCI9PT10aGlzLnN0YXRlfHxcImV4cGlyZWRcIj09PXRoaXMuc3RhdGV9LGx0LnByb3RvdHlwZS5zZXRFeHBpcnlEYXRhPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuZXhwaXJhdGlvblRpbWU7aWYoZS5jYWNoZUNvbnRyb2wpe3ZhciBuPXQucGFyc2VDYWNoZUNvbnRyb2woZS5jYWNoZUNvbnRyb2wpO25bXCJtYXgtYWdlXCJdJiYodGhpcy5leHBpcmF0aW9uVGltZT1EYXRlLm5vdygpKzFlMypuW1wibWF4LWFnZVwiXSk7fWVsc2UgZS5leHBpcmVzJiYodGhpcy5leHBpcmF0aW9uVGltZT1uZXcgRGF0ZShlLmV4cGlyZXMpLmdldFRpbWUoKSk7aWYodGhpcy5leHBpcmF0aW9uVGltZSl7dmFyIG89RGF0ZS5ub3coKSxyPSExO2lmKHRoaXMuZXhwaXJhdGlvblRpbWU+bylyPSExO2Vsc2UgaWYoaSlpZih0aGlzLmV4cGlyYXRpb25UaW1lPGkpcj0hMDtlbHNle3ZhciBhPXRoaXMuZXhwaXJhdGlvblRpbWUtaTthP3RoaXMuZXhwaXJhdGlvblRpbWU9bytNYXRoLm1heChhLDNlNCk6cj0hMDt9ZWxzZSByPSEwO3I/KHRoaXMuZXhwaXJlZFJlcXVlc3RDb3VudCsrLHRoaXMuc3RhdGU9XCJleHBpcmVkXCIpOnRoaXMuZXhwaXJlZFJlcXVlc3RDb3VudD0wO319LGx0LnByb3RvdHlwZS5nZXRFeHBpcnlUaW1lb3V0PWZ1bmN0aW9uKCl7aWYodGhpcy5leHBpcmF0aW9uVGltZSlyZXR1cm4gdGhpcy5leHBpcmVkUmVxdWVzdENvdW50PzFlMyooMTw8TWF0aC5taW4odGhpcy5leHBpcmVkUmVxdWVzdENvdW50LTEsMzEpKTpNYXRoLm1pbih0aGlzLmV4cGlyYXRpb25UaW1lLShuZXcgRGF0ZSkuZ2V0VGltZSgpLE1hdGgucG93KDIsMzEpLTEpfTt2YXIgY3Q9ZnVuY3Rpb24odCxlKXt0aGlzLm1heD10LHRoaXMub25SZW1vdmU9ZSx0aGlzLnJlc2V0KCk7fTtjdC5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXtmb3IodmFyIHQgaW4gdGhpcy5kYXRhKWZvcih2YXIgZT0wLGk9dGhpcy5kYXRhW3RdO2U8aS5sZW5ndGg7ZSs9MSl7dmFyIG49aVtlXTtuLnRpbWVvdXQmJmNsZWFyVGltZW91dChuLnRpbWVvdXQpLHRoaXMub25SZW1vdmUobi52YWx1ZSk7fXJldHVybiB0aGlzLmRhdGE9e30sdGhpcy5vcmRlcj1bXSx0aGlzfSxjdC5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj10aGlzLG89dC53cmFwcGVkKCkua2V5O3ZvaWQgMD09PXRoaXMuZGF0YVtvXSYmKHRoaXMuZGF0YVtvXT1bXSk7dmFyIHI9e3ZhbHVlOmUsdGltZW91dDp2b2lkIDB9O2lmKHZvaWQgMCE9PWkmJihyLnRpbWVvdXQ9c2V0VGltZW91dChmdW5jdGlvbigpe24ucmVtb3ZlKHQscik7fSxpKSksdGhpcy5kYXRhW29dLnB1c2gociksdGhpcy5vcmRlci5wdXNoKG8pLHRoaXMub3JkZXIubGVuZ3RoPnRoaXMubWF4KXt2YXIgYT10aGlzLl9nZXRBbmRSZW1vdmVCeUtleSh0aGlzLm9yZGVyWzBdKTthJiZ0aGlzLm9uUmVtb3ZlKGEpO31yZXR1cm4gdGhpc30sY3QucHJvdG90eXBlLmhhcz1mdW5jdGlvbih0KXtyZXR1cm4gdC53cmFwcGVkKCkua2V5IGluIHRoaXMuZGF0YX0sY3QucHJvdG90eXBlLmdldEFuZFJlbW92ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5oYXModCk/dGhpcy5fZ2V0QW5kUmVtb3ZlQnlLZXkodC53cmFwcGVkKCkua2V5KTpudWxsfSxjdC5wcm90b3R5cGUuX2dldEFuZFJlbW92ZUJ5S2V5PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZGF0YVt0XS5zaGlmdCgpO3JldHVybiBlLnRpbWVvdXQmJmNsZWFyVGltZW91dChlLnRpbWVvdXQpLDA9PT10aGlzLmRhdGFbdF0ubGVuZ3RoJiZkZWxldGUgdGhpcy5kYXRhW3RdLHRoaXMub3JkZXIuc3BsaWNlKHRoaXMub3JkZXIuaW5kZXhPZih0KSwxKSxlLnZhbHVlfSxjdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmhhcyh0KT90aGlzLmRhdGFbdC53cmFwcGVkKCkua2V5XVswXS52YWx1ZTpudWxsfSxjdC5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKHQsZSl7aWYoIXRoaXMuaGFzKHQpKXJldHVybiB0aGlzO3ZhciBpPXQud3JhcHBlZCgpLmtleSxuPXZvaWQgMD09PWU/MDp0aGlzLmRhdGFbaV0uaW5kZXhPZihlKSxvPXRoaXMuZGF0YVtpXVtuXTtyZXR1cm4gdGhpcy5kYXRhW2ldLnNwbGljZShuLDEpLG8udGltZW91dCYmY2xlYXJUaW1lb3V0KG8udGltZW91dCksMD09PXRoaXMuZGF0YVtpXS5sZW5ndGgmJmRlbGV0ZSB0aGlzLmRhdGFbaV0sdGhpcy5vblJlbW92ZShvLnZhbHVlKSx0aGlzLm9yZGVyLnNwbGljZSh0aGlzLm9yZGVyLmluZGV4T2YoaSksMSksdGhpc30sY3QucHJvdG90eXBlLnNldE1heFNpemU9ZnVuY3Rpb24odCl7Zm9yKHRoaXMubWF4PXQ7dGhpcy5vcmRlci5sZW5ndGg+dGhpcy5tYXg7KXt2YXIgZT10aGlzLl9nZXRBbmRSZW1vdmVCeUtleSh0aGlzLm9yZGVyWzBdKTtlJiZ0aGlzLm9uUmVtb3ZlKGUpO31yZXR1cm4gdGhpc307dmFyIHV0PWZ1bmN0aW9uKHQsZSxpKXt0aGlzLmNvbnRleHQ9dDt2YXIgbj10LmdsO3RoaXMuYnVmZmVyPW4uY3JlYXRlQnVmZmVyKCksdGhpcy5keW5hbWljRHJhdz1Cb29sZWFuKGkpLHRoaXMudW5iaW5kVkFPKCksdC5iaW5kRWxlbWVudEJ1ZmZlci5zZXQodGhpcy5idWZmZXIpLG4uYnVmZmVyRGF0YShuLkVMRU1FTlRfQVJSQVlfQlVGRkVSLGUuYXJyYXlCdWZmZXIsdGhpcy5keW5hbWljRHJhdz9uLkRZTkFNSUNfRFJBVzpuLlNUQVRJQ19EUkFXKSx0aGlzLmR5bmFtaWNEcmF3fHxkZWxldGUgZS5hcnJheUJ1ZmZlcjt9O3V0LnByb3RvdHlwZS51bmJpbmRWQU89ZnVuY3Rpb24oKXt0aGlzLmNvbnRleHQuZXh0VmVydGV4QXJyYXlPYmplY3QmJnRoaXMuY29udGV4dC5iaW5kVmVydGV4QXJyYXlPRVMuc2V0KG51bGwpO30sdXQucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24oKXt0aGlzLmNvbnRleHQuYmluZEVsZW1lbnRCdWZmZXIuc2V0KHRoaXMuYnVmZmVyKTt9LHV0LnByb3RvdHlwZS51cGRhdGVEYXRhPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY29udGV4dC5nbDt0aGlzLnVuYmluZFZBTygpLHRoaXMuYmluZCgpLGUuYnVmZmVyU3ViRGF0YShlLkVMRU1FTlRfQVJSQVlfQlVGRkVSLDAsdC5hcnJheUJ1ZmZlcik7fSx1dC5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuY29udGV4dC5nbDt0aGlzLmJ1ZmZlciYmKHQuZGVsZXRlQnVmZmVyKHRoaXMuYnVmZmVyKSxkZWxldGUgdGhpcy5idWZmZXIpO307dmFyIGh0PXtJbnQ4OlwiQllURVwiLFVpbnQ4OlwiVU5TSUdORURfQllURVwiLEludDE2OlwiU0hPUlRcIixVaW50MTY6XCJVTlNJR05FRF9TSE9SVFwiLEludDMyOlwiSU5UXCIsVWludDMyOlwiVU5TSUdORURfSU5UXCIsRmxvYXQzMjpcIkZMT0FUXCJ9LHB0PWZ1bmN0aW9uKHQsZSxpLG4pe3RoaXMubGVuZ3RoPWUubGVuZ3RoLHRoaXMuYXR0cmlidXRlcz1pLHRoaXMuaXRlbVNpemU9ZS5ieXRlc1BlckVsZW1lbnQsdGhpcy5keW5hbWljRHJhdz1uLHRoaXMuY29udGV4dD10O3ZhciBvPXQuZ2w7dGhpcy5idWZmZXI9by5jcmVhdGVCdWZmZXIoKSx0LmJpbmRWZXJ0ZXhCdWZmZXIuc2V0KHRoaXMuYnVmZmVyKSxvLmJ1ZmZlckRhdGEoby5BUlJBWV9CVUZGRVIsZS5hcnJheUJ1ZmZlcix0aGlzLmR5bmFtaWNEcmF3P28uRFlOQU1JQ19EUkFXOm8uU1RBVElDX0RSQVcpLHRoaXMuZHluYW1pY0RyYXd8fGRlbGV0ZSBlLmFycmF5QnVmZmVyO307cHQucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24oKXt0aGlzLmNvbnRleHQuYmluZFZlcnRleEJ1ZmZlci5zZXQodGhpcy5idWZmZXIpO30scHQucHJvdG90eXBlLnVwZGF0ZURhdGE9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO3RoaXMuYmluZCgpLGUuYnVmZmVyU3ViRGF0YShlLkFSUkFZX0JVRkZFUiwwLHQuYXJyYXlCdWZmZXIpO30scHQucHJvdG90eXBlLmVuYWJsZUF0dHJpYnV0ZXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIGk9MDtpPHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7aSsrKXt2YXIgbj10aGlzLmF0dHJpYnV0ZXNbaV0sbz1lLmF0dHJpYnV0ZXNbbi5uYW1lXTt2b2lkIDAhPT1vJiZ0LmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KG8pO319LHB0LnByb3RvdHlwZS5zZXRWZXJ0ZXhBdHRyaWJQb2ludGVycz1mdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBuPTA7bjx0aGlzLmF0dHJpYnV0ZXMubGVuZ3RoO24rKyl7dmFyIG89dGhpcy5hdHRyaWJ1dGVzW25dLHI9ZS5hdHRyaWJ1dGVzW28ubmFtZV07dm9pZCAwIT09ciYmdC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHIsby5jb21wb25lbnRzLHRbaHRbby50eXBlXV0sITEsdGhpcy5pdGVtU2l6ZSxvLm9mZnNldCt0aGlzLml0ZW1TaXplKihpfHwwKSk7fX0scHQucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmNvbnRleHQuZ2w7dGhpcy5idWZmZXImJih0LmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlciksZGVsZXRlIHRoaXMuYnVmZmVyKTt9O3ZhciBkdD1mdW5jdGlvbihlKXt0aGlzLmNvbnRleHQ9ZSx0aGlzLmN1cnJlbnQ9dC5kZWZhdWx0JDYudHJhbnNwYXJlbnQ7fTtkdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sZHQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7dC5yPT09ZS5yJiZ0Lmc9PT1lLmcmJnQuYj09PWUuYiYmdC5hPT09ZS5hfHwodGhpcy5jb250ZXh0LmdsLmNsZWFyQ29sb3IodC5yLHQuZyx0LmIsdC5hKSx0aGlzLmN1cnJlbnQ9dCk7fTt2YXIgZnQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PTE7fTtmdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sZnQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt0aGlzLmN1cnJlbnQhPT10JiYodGhpcy5jb250ZXh0LmdsLmNsZWFyRGVwdGgodCksdGhpcy5jdXJyZW50PXQpO307dmFyIG10PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD0wO307bXQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LG10LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5jdXJyZW50IT09dCYmKHRoaXMuY29udGV4dC5nbC5jbGVhclN0ZW5jaWwodCksdGhpcy5jdXJyZW50PXQpO307dmFyIF90PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD1bITAsITAsITAsITBdO307X3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LF90LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50O3RbMF09PT1lWzBdJiZ0WzFdPT09ZVsxXSYmdFsyXT09PWVbMl0mJnRbM109PT1lWzNdfHwodGhpcy5jb250ZXh0LmdsLmNvbG9yTWFzayh0WzBdLHRbMV0sdFsyXSx0WzNdKSx0aGlzLmN1cnJlbnQ9dCk7fTt2YXIgZ3Q9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PSEwO307Z3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LGd0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5jdXJyZW50IT09dCYmKHRoaXMuY29udGV4dC5nbC5kZXB0aE1hc2sodCksdGhpcy5jdXJyZW50PXQpO307dmFyIHZ0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD0yNTU7fTt2dC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sdnQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt0aGlzLmN1cnJlbnQhPT10JiYodGhpcy5jb250ZXh0LmdsLnN0ZW5jaWxNYXNrKHQpLHRoaXMuY3VycmVudD10KTt9O3ZhciB5dD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dCx0aGlzLmN1cnJlbnQ9e2Z1bmM6dC5nbC5BTFdBWVMscmVmOjAsbWFzazoyNTV9O307eXQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LHl0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50O3QuZnVuYz09PWUuZnVuYyYmdC5yZWY9PT1lLnJlZiYmdC5tYXNrPT09ZS5tYXNrfHwodGhpcy5jb250ZXh0LmdsLnN0ZW5jaWxGdW5jKHQuZnVuYyx0LnJlZix0Lm1hc2spLHRoaXMuY3VycmVudD10KTt9O3ZhciB4dD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dDt2YXIgZT10aGlzLmNvbnRleHQuZ2w7dGhpcy5jdXJyZW50PVtlLktFRVAsZS5LRUVQLGUuS0VFUF07fTt4dC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0seHQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7dFswXT09PWVbMF0mJnRbMV09PT1lWzFdJiZ0WzJdPT09ZVsyXXx8KHRoaXMuY29udGV4dC5nbC5zdGVuY2lsT3AodFswXSx0WzFdLHRbMl0pLHRoaXMuY3VycmVudD10KTt9O3ZhciBidD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dCx0aGlzLmN1cnJlbnQ9ITE7fTtidC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sYnQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0aGlzLmN1cnJlbnQhPT10KXt2YXIgZT10aGlzLmNvbnRleHQuZ2w7dD9lLmVuYWJsZShlLlNURU5DSUxfVEVTVCk6ZS5kaXNhYmxlKGUuU1RFTkNJTF9URVNUKSx0aGlzLmN1cnJlbnQ9dDt9fTt2YXIgd3Q9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PVswLDFdO307d3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LHd0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50O3RbMF09PT1lWzBdJiZ0WzFdPT09ZVsxXXx8KHRoaXMuY29udGV4dC5nbC5kZXB0aFJhbmdlKHRbMF0sdFsxXSksdGhpcy5jdXJyZW50PXQpO307dmFyIEV0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD0hMTt9O0V0LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fSxFdC5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHRoaXMuY3VycmVudCE9PXQpe3ZhciBlPXRoaXMuY29udGV4dC5nbDt0P2UuZW5hYmxlKGUuREVQVEhfVEVTVCk6ZS5kaXNhYmxlKGUuREVQVEhfVEVTVCksdGhpcy5jdXJyZW50PXQ7fX07dmFyIFR0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD10LmdsLkxFU1M7fTtUdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sVHQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt0aGlzLmN1cnJlbnQhPT10JiYodGhpcy5jb250ZXh0LmdsLmRlcHRoRnVuYyh0KSx0aGlzLmN1cnJlbnQ9dCk7fTt2YXIgSXQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PSExO307SXQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LEl0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5jdXJyZW50IT09dCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO3Q/ZS5lbmFibGUoZS5CTEVORCk6ZS5kaXNhYmxlKGUuQkxFTkQpLHRoaXMuY3VycmVudD10O319O3ZhciBDdD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dDt2YXIgZT10aGlzLmNvbnRleHQuZ2w7dGhpcy5jdXJyZW50PVtlLk9ORSxlLlpFUk9dO307Q3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LEN0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50O3RbMF09PT1lWzBdJiZ0WzFdPT09ZVsxXXx8KHRoaXMuY29udGV4dC5nbC5ibGVuZEZ1bmModFswXSx0WzFdKSx0aGlzLmN1cnJlbnQ9dCk7fTt2YXIgU3Q9ZnVuY3Rpb24oZSl7dGhpcy5jb250ZXh0PWUsdGhpcy5jdXJyZW50PXQuZGVmYXVsdCQ2LnRyYW5zcGFyZW50O307U3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LFN0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50O3Qucj09PWUuciYmdC5nPT09ZS5nJiZ0LmI9PT1lLmImJnQuYT09PWUuYXx8KHRoaXMuY29udGV4dC5nbC5ibGVuZENvbG9yKHQucix0LmcsdC5iLHQuYSksdGhpcy5jdXJyZW50PXQpO307dmFyIHp0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD1udWxsO307enQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LHp0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5jdXJyZW50IT09dCYmKHRoaXMuY29udGV4dC5nbC51c2VQcm9ncmFtKHQpLHRoaXMuY3VycmVudD10KTt9O3ZhciBBdD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dCx0aGlzLmN1cnJlbnQ9MTt9O0F0LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fSxBdC5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuY29udGV4dC5saW5lV2lkdGhSYW5nZSxuPXQuY2xhbXAoZSxpWzBdLGlbMV0pO3RoaXMuY3VycmVudCE9PW4mJih0aGlzLmNvbnRleHQuZ2wubGluZVdpZHRoKG4pLHRoaXMuY3VycmVudD1lKTt9O3ZhciBSdD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dCx0aGlzLmN1cnJlbnQ9dC5nbC5URVhUVVJFMDt9O1J0LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fSxSdC5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuY3VycmVudCE9PXQmJih0aGlzLmNvbnRleHQuZ2wuYWN0aXZlVGV4dHVyZSh0KSx0aGlzLmN1cnJlbnQ9dCk7fTt2YXIgRHQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQ7dmFyIGU9dGhpcy5jb250ZXh0LmdsO3RoaXMuY3VycmVudD1bMCwwLGUuZHJhd2luZ0J1ZmZlcldpZHRoLGUuZHJhd2luZ0J1ZmZlckhlaWdodF07fTtEdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sRHQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7dFswXT09PWVbMF0mJnRbMV09PT1lWzFdJiZ0WzJdPT09ZVsyXSYmdFszXT09PWVbM118fCh0aGlzLmNvbnRleHQuZ2wudmlld3BvcnQodFswXSx0WzFdLHRbMl0sdFszXSksdGhpcy5jdXJyZW50PXQpO307dmFyIE10PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD1udWxsO307TXQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LE10LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5jdXJyZW50IT09dCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO2UuYmluZEZyYW1lYnVmZmVyKGUuRlJBTUVCVUZGRVIsdCksdGhpcy5jdXJyZW50PXQ7fX07dmFyIEx0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD1udWxsO307THQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LEx0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5jdXJyZW50IT09dCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO2UuYmluZFJlbmRlcmJ1ZmZlcihlLlJFTkRFUkJVRkZFUix0KSx0aGlzLmN1cnJlbnQ9dDt9fTt2YXIgUHQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PW51bGw7fTtQdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sUHQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0aGlzLmN1cnJlbnQhPT10KXt2YXIgZT10aGlzLmNvbnRleHQuZ2w7ZS5iaW5kVGV4dHVyZShlLlRFWFRVUkVfMkQsdCksdGhpcy5jdXJyZW50PXQ7fX07dmFyIGt0PWZ1bmN0aW9uKHQpe3RoaXMuY29udGV4dD10LHRoaXMuY3VycmVudD1udWxsO307a3QucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LGt0LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5jdXJyZW50IT09dCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO2UuYmluZEJ1ZmZlcihlLkFSUkFZX0JVRkZFUix0KSx0aGlzLmN1cnJlbnQ9dDt9fTt2YXIgQnQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PW51bGw7fTtCdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sQnQucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmNvbnRleHQuZ2w7ZS5iaW5kQnVmZmVyKGUuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdCksdGhpcy5jdXJyZW50PXQ7fTt2YXIgT3Q9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PW51bGw7fTtPdC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY3VycmVudH0sT3QucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt0aGlzLmN1cnJlbnQhPT10JiZ0aGlzLmNvbnRleHQuZXh0VmVydGV4QXJyYXlPYmplY3QmJih0aGlzLmNvbnRleHQuZXh0VmVydGV4QXJyYXlPYmplY3QuYmluZFZlcnRleEFycmF5T0VTKHQpLHRoaXMuY3VycmVudD10KTt9O3ZhciBGdD1mdW5jdGlvbih0KXt0aGlzLmNvbnRleHQ9dCx0aGlzLmN1cnJlbnQ9NDt9O0Z0LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fSxGdC5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHRoaXMuY3VycmVudCE9PXQpe3ZhciBlPXRoaXMuY29udGV4dC5nbDtlLnBpeGVsU3RvcmVpKGUuVU5QQUNLX0FMSUdOTUVOVCx0KSx0aGlzLmN1cnJlbnQ9dDt9fTt2YXIgTnQ9ZnVuY3Rpb24odCl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PSExO307TnQucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnR9LE50LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodGhpcy5jdXJyZW50IT09dCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO2UucGl4ZWxTdG9yZWkoZS5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsdCksdGhpcy5jdXJyZW50PXQ7fX07dmFyIFV0PWZ1bmN0aW9uKHQsZSl7dGhpcy5jb250ZXh0PXQsdGhpcy5jdXJyZW50PW51bGwsdGhpcy5wYXJlbnQ9ZTt9O1V0LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fTt2YXIgWnQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLGkpe3QuY2FsbCh0aGlzLGUsaSksdGhpcy5kaXJ0eT0hMTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0aGlzLmRpcnR5fHx0aGlzLmN1cnJlbnQhPT10KXt2YXIgZT10aGlzLmNvbnRleHQuZ2w7dGhpcy5jb250ZXh0LmJpbmRGcmFtZWJ1ZmZlci5zZXQodGhpcy5wYXJlbnQpLGUuZnJhbWVidWZmZXJUZXh0dXJlMkQoZS5GUkFNRUJVRkZFUixlLkNPTE9SX0FUVEFDSE1FTlQwLGUuVEVYVFVSRV8yRCx0LDApLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITE7fX0sZS5wcm90b3R5cGUuc2V0RGlydHk9ZnVuY3Rpb24oKXt0aGlzLmRpcnR5PSEwO30sZX0oVXQpLFZ0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0aGlzLmN1cnJlbnQhPT10KXt2YXIgZT10aGlzLmNvbnRleHQuZ2w7dGhpcy5jb250ZXh0LmJpbmRGcmFtZWJ1ZmZlci5zZXQodGhpcy5wYXJlbnQpLGUuZnJhbWVidWZmZXJSZW5kZXJidWZmZXIoZS5GUkFNRUJVRkZFUixlLkRFUFRIX0FUVEFDSE1FTlQsZS5SRU5ERVJCVUZGRVIsdCksdGhpcy5jdXJyZW50PXQ7fX0sZX0oVXQpLGp0PWZ1bmN0aW9uKHQsZSxpKXt0aGlzLmNvbnRleHQ9dCx0aGlzLndpZHRoPWUsdGhpcy5oZWlnaHQ9aTt2YXIgbj10LmdsLG89dGhpcy5mcmFtZWJ1ZmZlcj1uLmNyZWF0ZUZyYW1lYnVmZmVyKCk7dGhpcy5jb2xvckF0dGFjaG1lbnQ9bmV3IFp0KHQsbyksdGhpcy5kZXB0aEF0dGFjaG1lbnQ9bmV3IFZ0KHQsbyk7fTtqdC5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuY29udGV4dC5nbCxlPXRoaXMuY29sb3JBdHRhY2htZW50LmdldCgpO2UmJnQuZGVsZXRlVGV4dHVyZShlKTt2YXIgaT10aGlzLmRlcHRoQXR0YWNobWVudC5nZXQoKTtpJiZ0LmRlbGV0ZVJlbmRlcmJ1ZmZlcihpKSx0LmRlbGV0ZUZyYW1lYnVmZmVyKHRoaXMuZnJhbWVidWZmZXIpO307dmFyICR0PWZ1bmN0aW9uKHQsZSxpKXt0aGlzLmZ1bmM9dCx0aGlzLm1hc2s9ZSx0aGlzLnJhbmdlPWk7fTskdC5SZWFkT25seT0hMSwkdC5SZWFkV3JpdGU9ITAsJHQuZGlzYWJsZWQ9bmV3ICR0KDUxOSwkdC5SZWFkT25seSxbMCwxXSk7dmFyIEd0PWZ1bmN0aW9uKHQsZSxpLG4sbyxyKXt0aGlzLnRlc3Q9dCx0aGlzLnJlZj1lLHRoaXMubWFzaz1pLHRoaXMuZmFpbD1uLHRoaXMuZGVwdGhGYWlsPW8sdGhpcy5wYXNzPXI7fTtHdC5kaXNhYmxlZD1uZXcgR3Qoe2Z1bmM6NTE5LG1hc2s6MH0sMCwwLDc2ODAsNzY4MCw3NjgwKTt2YXIgV3Q9ZnVuY3Rpb24odCxlLGkpe3RoaXMuYmxlbmRGdW5jdGlvbj10LHRoaXMuYmxlbmRDb2xvcj1lLHRoaXMubWFzaz1pO307V3QuUmVwbGFjZT1bMSwwXSxXdC5kaXNhYmxlZD1uZXcgV3QoV3QuUmVwbGFjZSx0LmRlZmF1bHQkNi50cmFuc3BhcmVudCxbITEsITEsITEsITFdKSxXdC51bmJsZW5kZWQ9bmV3IFd0KFd0LlJlcGxhY2UsdC5kZWZhdWx0JDYudHJhbnNwYXJlbnQsWyEwLCEwLCEwLCEwXSksV3QuYWxwaGFCbGVuZGVkPW5ldyBXdChbMSw3NzFdLHQuZGVmYXVsdCQ2LnRyYW5zcGFyZW50LFshMCwhMCwhMCwhMF0pO3ZhciBxdD1mdW5jdGlvbih0KXt0aGlzLmdsPXQsdGhpcy5leHRWZXJ0ZXhBcnJheU9iamVjdD10aGlzLmdsLmdldEV4dGVuc2lvbihcIk9FU192ZXJ0ZXhfYXJyYXlfb2JqZWN0XCIpLHRoaXMubGluZVdpZHRoUmFuZ2U9dC5nZXRQYXJhbWV0ZXIodC5BTElBU0VEX0xJTkVfV0lEVEhfUkFOR0UpLHRoaXMuY2xlYXJDb2xvcj1uZXcgZHQodGhpcyksdGhpcy5jbGVhckRlcHRoPW5ldyBmdCh0aGlzKSx0aGlzLmNsZWFyU3RlbmNpbD1uZXcgbXQodGhpcyksdGhpcy5jb2xvck1hc2s9bmV3IF90KHRoaXMpLHRoaXMuZGVwdGhNYXNrPW5ldyBndCh0aGlzKSx0aGlzLnN0ZW5jaWxNYXNrPW5ldyB2dCh0aGlzKSx0aGlzLnN0ZW5jaWxGdW5jPW5ldyB5dCh0aGlzKSx0aGlzLnN0ZW5jaWxPcD1uZXcgeHQodGhpcyksdGhpcy5zdGVuY2lsVGVzdD1uZXcgYnQodGhpcyksdGhpcy5kZXB0aFJhbmdlPW5ldyB3dCh0aGlzKSx0aGlzLmRlcHRoVGVzdD1uZXcgRXQodGhpcyksdGhpcy5kZXB0aEZ1bmM9bmV3IFR0KHRoaXMpLHRoaXMuYmxlbmQ9bmV3IEl0KHRoaXMpLHRoaXMuYmxlbmRGdW5jPW5ldyBDdCh0aGlzKSx0aGlzLmJsZW5kQ29sb3I9bmV3IFN0KHRoaXMpLHRoaXMucHJvZ3JhbT1uZXcgenQodGhpcyksdGhpcy5saW5lV2lkdGg9bmV3IEF0KHRoaXMpLHRoaXMuYWN0aXZlVGV4dHVyZT1uZXcgUnQodGhpcyksdGhpcy52aWV3cG9ydD1uZXcgRHQodGhpcyksdGhpcy5iaW5kRnJhbWVidWZmZXI9bmV3IE10KHRoaXMpLHRoaXMuYmluZFJlbmRlcmJ1ZmZlcj1uZXcgTHQodGhpcyksdGhpcy5iaW5kVGV4dHVyZT1uZXcgUHQodGhpcyksdGhpcy5iaW5kVmVydGV4QnVmZmVyPW5ldyBrdCh0aGlzKSx0aGlzLmJpbmRFbGVtZW50QnVmZmVyPW5ldyBCdCh0aGlzKSx0aGlzLmJpbmRWZXJ0ZXhBcnJheU9FUz10aGlzLmV4dFZlcnRleEFycmF5T2JqZWN0JiZuZXcgT3QodGhpcyksdGhpcy5waXhlbFN0b3JlVW5wYWNrPW5ldyBGdCh0aGlzKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhPW5ldyBOdCh0aGlzKSx0aGlzLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYz10LmdldEV4dGVuc2lvbihcIkVYVF90ZXh0dXJlX2ZpbHRlcl9hbmlzb3Ryb3BpY1wiKXx8dC5nZXRFeHRlbnNpb24oXCJNT1pfRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljXCIpfHx0LmdldEV4dGVuc2lvbihcIldFQktJVF9FWFRfdGV4dHVyZV9maWx0ZXJfYW5pc290cm9waWNcIiksdGhpcy5leHRUZXh0dXJlRmlsdGVyQW5pc290cm9waWMmJih0aGlzLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpY01heD10LmdldFBhcmFtZXRlcih0aGlzLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYy5NQVhfVEVYVFVSRV9NQVhfQU5JU09UUk9QWV9FWFQpKSx0aGlzLmV4dFRleHR1cmVIYWxmRmxvYXQ9dC5nZXRFeHRlbnNpb24oXCJPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0XCIpLHRoaXMuZXh0VGV4dHVyZUhhbGZGbG9hdCYmdC5nZXRFeHRlbnNpb24oXCJPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0X2xpbmVhclwiKTt9O3F0LnByb3RvdHlwZS5jcmVhdGVJbmRleEJ1ZmZlcj1mdW5jdGlvbih0LGUpe3JldHVybiBuZXcgdXQodGhpcyx0LGUpfSxxdC5wcm90b3R5cGUuY3JlYXRlVmVydGV4QnVmZmVyPWZ1bmN0aW9uKHQsZSxpKXtyZXR1cm4gbmV3IHB0KHRoaXMsdCxlLGkpfSxxdC5wcm90b3R5cGUuY3JlYXRlUmVuZGVyYnVmZmVyPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj10aGlzLmdsLG89bi5jcmVhdGVSZW5kZXJidWZmZXIoKTtyZXR1cm4gdGhpcy5iaW5kUmVuZGVyYnVmZmVyLnNldChvKSxuLnJlbmRlcmJ1ZmZlclN0b3JhZ2Uobi5SRU5ERVJCVUZGRVIsdCxlLGkpLHRoaXMuYmluZFJlbmRlcmJ1ZmZlci5zZXQobnVsbCksb30scXQucHJvdG90eXBlLmNyZWF0ZUZyYW1lYnVmZmVyPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIG5ldyBqdCh0aGlzLHQsZSl9LHF0LnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbih0KXt2YXIgZT10LmNvbG9yLGk9dC5kZXB0aCxuPXRoaXMuZ2wsbz0wO2UmJihvfD1uLkNPTE9SX0JVRkZFUl9CSVQsdGhpcy5jbGVhckNvbG9yLnNldChlKSx0aGlzLmNvbG9yTWFzay5zZXQoWyEwLCEwLCEwLCEwXSkpLHZvaWQgMCE9PWkmJihvfD1uLkRFUFRIX0JVRkZFUl9CSVQsdGhpcy5jbGVhckRlcHRoLnNldChpKSx0aGlzLmRlcHRoTWFzay5zZXQoITApKSxuLmNsZWFyKG8pO30scXQucHJvdG90eXBlLnNldERlcHRoTW9kZT1mdW5jdGlvbih0KXt0LmZ1bmMhPT10aGlzLmdsLkFMV0FZU3x8dC5tYXNrPyh0aGlzLmRlcHRoVGVzdC5zZXQoITApLHRoaXMuZGVwdGhGdW5jLnNldCh0LmZ1bmMpLHRoaXMuZGVwdGhNYXNrLnNldCh0Lm1hc2spLHRoaXMuZGVwdGhSYW5nZS5zZXQodC5yYW5nZSkpOnRoaXMuZGVwdGhUZXN0LnNldCghMSk7fSxxdC5wcm90b3R5cGUuc2V0U3RlbmNpbE1vZGU9ZnVuY3Rpb24odCl7dC50ZXN0LmZ1bmMhPT10aGlzLmdsLkFMV0FZU3x8dC5tYXNrPyh0aGlzLnN0ZW5jaWxUZXN0LnNldCghMCksdGhpcy5zdGVuY2lsTWFzay5zZXQodC5tYXNrKSx0aGlzLnN0ZW5jaWxPcC5zZXQoW3QuZmFpbCx0LmRlcHRoRmFpbCx0LnBhc3NdKSx0aGlzLnN0ZW5jaWxGdW5jLnNldCh7ZnVuYzp0LnRlc3QuZnVuYyxyZWY6dC5yZWYsbWFzazp0LnRlc3QubWFza30pKTp0aGlzLnN0ZW5jaWxUZXN0LnNldCghMSk7fSxxdC5wcm90b3R5cGUuc2V0Q29sb3JNb2RlPWZ1bmN0aW9uKGUpe3QuZGVmYXVsdCQxMChlLmJsZW5kRnVuY3Rpb24sV3QuUmVwbGFjZSk/dGhpcy5ibGVuZC5zZXQoITEpOih0aGlzLmJsZW5kLnNldCghMCksdGhpcy5ibGVuZEZ1bmMuc2V0KGUuYmxlbmRGdW5jdGlvbiksdGhpcy5ibGVuZENvbG9yLnNldChlLmJsZW5kQ29sb3IpKSx0aGlzLmNvbG9yTWFzay5zZXQoZS5tYXNrKTt9O3ZhciBYdD1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKHQsaSxuKXt2YXIgbz10aGlzO2UuY2FsbCh0aGlzKSx0aGlzLmlkPXQsdGhpcy5kaXNwYXRjaGVyPW4sdGhpcy5vbihcImRhdGFcIixmdW5jdGlvbih0KXtcInNvdXJjZVwiPT09dC5kYXRhVHlwZSYmXCJtZXRhZGF0YVwiPT09dC5zb3VyY2VEYXRhVHlwZSYmKG8uX3NvdXJjZUxvYWRlZD0hMCksby5fc291cmNlTG9hZGVkJiYhby5fcGF1c2VkJiZcInNvdXJjZVwiPT09dC5kYXRhVHlwZSYmXCJjb250ZW50XCI9PT10LnNvdXJjZURhdGFUeXBlJiYoby5yZWxvYWQoKSxvLnRyYW5zZm9ybSYmby51cGRhdGUoby50cmFuc2Zvcm0pKTt9KSx0aGlzLm9uKFwiZXJyb3JcIixmdW5jdGlvbigpe28uX3NvdXJjZUVycm9yZWQ9ITA7fSksdGhpcy5fc291cmNlPXJ0KHQsaSxuLHRoaXMpLHRoaXMuX3RpbGVzPXt9LHRoaXMuX2NhY2hlPW5ldyBjdCgwLHRoaXMuX3VubG9hZFRpbGUuYmluZCh0aGlzKSksdGhpcy5fdGltZXJzPXt9LHRoaXMuX2NhY2hlVGltZXJzPXt9LHRoaXMuX21heFRpbGVDYWNoZVNpemU9bnVsbCx0aGlzLl9pc0lkUmVuZGVyYWJsZT10aGlzLl9pc0lkUmVuZGVyYWJsZS5iaW5kKHRoaXMpLHRoaXMuX2NvdmVyZWRUaWxlcz17fTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwPXQsdGhpcy5fbWF4VGlsZUNhY2hlU2l6ZT10P3QuX21heFRpbGVDYWNoZVNpemU6bnVsbCx0aGlzLl9zb3VyY2UmJnRoaXMuX3NvdXJjZS5vbkFkZCYmdGhpcy5fc291cmNlLm9uQWRkKHQpO30saS5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24odCl7dGhpcy5fc291cmNlJiZ0aGlzLl9zb3VyY2Uub25SZW1vdmUmJnRoaXMuX3NvdXJjZS5vblJlbW92ZSh0KTt9LGkucHJvdG90eXBlLmxvYWRlZD1mdW5jdGlvbigpe2lmKHRoaXMuX3NvdXJjZUVycm9yZWQpcmV0dXJuITA7aWYoIXRoaXMuX3NvdXJjZUxvYWRlZClyZXR1cm4hMTtmb3IodmFyIHQgaW4gdGhpcy5fdGlsZXMpe3ZhciBlPXRoaXMuX3RpbGVzW3RdO2lmKFwibG9hZGVkXCIhPT1lLnN0YXRlJiZcImVycm9yZWRcIiE9PWUuc3RhdGUpcmV0dXJuITF9cmV0dXJuITB9LGkucHJvdG90eXBlLmdldFNvdXJjZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zb3VyY2V9LGkucHJvdG90eXBlLnBhdXNlPWZ1bmN0aW9uKCl7dGhpcy5fcGF1c2VkPSEwO30saS5wcm90b3R5cGUucmVzdW1lPWZ1bmN0aW9uKCl7aWYodGhpcy5fcGF1c2VkKXt2YXIgdD10aGlzLl9zaG91bGRSZWxvYWRPblJlc3VtZTt0aGlzLl9wYXVzZWQ9ITEsdGhpcy5fc2hvdWxkUmVsb2FkT25SZXN1bWU9ITEsdCYmdGhpcy5yZWxvYWQoKSx0aGlzLnRyYW5zZm9ybSYmdGhpcy51cGRhdGUodGhpcy50cmFuc2Zvcm0pO319LGkucHJvdG90eXBlLl9sb2FkVGlsZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9zb3VyY2UubG9hZFRpbGUodCxlKX0saS5wcm90b3R5cGUuX3VubG9hZFRpbGU9ZnVuY3Rpb24odCl7aWYodGhpcy5fc291cmNlLnVubG9hZFRpbGUpcmV0dXJuIHRoaXMuX3NvdXJjZS51bmxvYWRUaWxlKHQsZnVuY3Rpb24oKXt9KX0saS5wcm90b3R5cGUuX2Fib3J0VGlsZT1mdW5jdGlvbih0KXtpZih0aGlzLl9zb3VyY2UuYWJvcnRUaWxlKXJldHVybiB0aGlzLl9zb3VyY2UuYWJvcnRUaWxlKHQsZnVuY3Rpb24oKXt9KX0saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3NvdXJjZS5zZXJpYWxpemUoKX0saS5wcm90b3R5cGUucHJlcGFyZT1mdW5jdGlvbih0KXtmb3IodmFyIGUgaW4gdGhpcy5fc291cmNlLnByZXBhcmUmJnRoaXMuX3NvdXJjZS5wcmVwYXJlKCksdGhpcy5fdGlsZXMpdGhpcy5fdGlsZXNbZV0udXBsb2FkKHQpO30saS5wcm90b3R5cGUuZ2V0SWRzPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcztyZXR1cm4gT2JqZWN0LmtleXModGhpcy5fdGlsZXMpLm1hcChOdW1iZXIpLnNvcnQoZnVuY3Rpb24oaSxuKXt2YXIgbz1lLl90aWxlc1tpXS50aWxlSUQscj1lLl90aWxlc1tuXS50aWxlSUQsYT1uZXcgdC5kZWZhdWx0JDEoby5jYW5vbmljYWwueCxvLmNhbm9uaWNhbC55KS5yb3RhdGUoZS50cmFuc2Zvcm0uYW5nbGUpLHM9bmV3IHQuZGVmYXVsdCQxKHIuY2Fub25pY2FsLngsci5jYW5vbmljYWwueSkucm90YXRlKGUudHJhbnNmb3JtLmFuZ2xlKTtyZXR1cm4gby5vdmVyc2NhbGVkWi1yLm92ZXJzY2FsZWRafHxzLnktYS55fHxzLngtYS54fSl9LGkucHJvdG90eXBlLmdldFJlbmRlcmFibGVJZHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nZXRJZHMoKS5maWx0ZXIodGhpcy5faXNJZFJlbmRlcmFibGUpfSxpLnByb3RvdHlwZS5oYXNSZW5kZXJhYmxlUGFyZW50PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZmluZExvYWRlZFBhcmVudCh0LDAse30pO3JldHVybiEhZSYmdGhpcy5faXNJZFJlbmRlcmFibGUoZS50aWxlSUQua2V5KX0saS5wcm90b3R5cGUuX2lzSWRSZW5kZXJhYmxlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl90aWxlc1t0XSYmdGhpcy5fdGlsZXNbdF0uaGFzRGF0YSgpJiYhdGhpcy5fY292ZXJlZFRpbGVzW3RdfSxpLnByb3RvdHlwZS5yZWxvYWQ9ZnVuY3Rpb24oKXtpZih0aGlzLl9wYXVzZWQpdGhpcy5fc2hvdWxkUmVsb2FkT25SZXN1bWU9ITA7ZWxzZSBmb3IodmFyIHQgaW4gdGhpcy5fY2FjaGUucmVzZXQoKSx0aGlzLl90aWxlcyl0aGlzLl9yZWxvYWRUaWxlKHQsXCJyZWxvYWRpbmdcIik7fSxpLnByb3RvdHlwZS5fcmVsb2FkVGlsZT1mdW5jdGlvbih0LGUpe3ZhciBpPXRoaXMuX3RpbGVzW3RdO2kmJihcImxvYWRpbmdcIiE9PWkuc3RhdGUmJihpLnN0YXRlPWUpLHRoaXMuX2xvYWRUaWxlKGksdGhpcy5fdGlsZUxvYWRlZC5iaW5kKHRoaXMsaSx0LGUpKSk7fSxpLnByb3RvdHlwZS5fdGlsZUxvYWRlZD1mdW5jdGlvbihlLGksbixvKXtpZihvKXJldHVybiBlLnN0YXRlPVwiZXJyb3JlZFwiLHZvaWQoNDA0IT09by5zdGF0dXM/dGhpcy5fc291cmNlLmZpcmUobmV3IHQuRXJyb3JFdmVudChvLHt0aWxlOmV9KSk6dGhpcy51cGRhdGUodGhpcy50cmFuc2Zvcm0pKTtlLnRpbWVBZGRlZD1yLm5vdygpLFwiZXhwaXJlZFwiPT09biYmKGUucmVmcmVzaGVkVXBvbkV4cGlyYXRpb249ITApLHRoaXMuX3NldFRpbGVSZWxvYWRUaW1lcihpLGUpLFwicmFzdGVyLWRlbVwiPT09dGhpcy5nZXRTb3VyY2UoKS50eXBlJiZlLmRlbSYmdGhpcy5fYmFja2ZpbGxERU0oZSksdGhpcy5fc291cmNlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse2RhdGFUeXBlOlwic291cmNlXCIsdGlsZTplLGNvb3JkOmUudGlsZUlEfSkpLHRoaXMubWFwJiYodGhpcy5tYXAucGFpbnRlci50aWxlRXh0ZW50VkFPLnZhbz1udWxsKTt9LGkucHJvdG90eXBlLl9iYWNrZmlsbERFTT1mdW5jdGlvbih0KXtmb3IodmFyIGU9dGhpcy5nZXRSZW5kZXJhYmxlSWRzKCksaT0wO2k8ZS5sZW5ndGg7aSsrKXt2YXIgbj1lW2ldO2lmKHQubmVpZ2hib3JpbmdUaWxlcyYmdC5uZWlnaGJvcmluZ1RpbGVzW25dKXt2YXIgbz10aGlzLmdldFRpbGVCeUlEKG4pO3IodCxvKSxyKG8sdCk7fX1mdW5jdGlvbiByKHQsZSl7dC5uZWVkc0hpbGxzaGFkZVByZXBhcmU9ITA7dmFyIGk9ZS50aWxlSUQuY2Fub25pY2FsLngtdC50aWxlSUQuY2Fub25pY2FsLngsbj1lLnRpbGVJRC5jYW5vbmljYWwueS10LnRpbGVJRC5jYW5vbmljYWwueSxvPU1hdGgucG93KDIsdC50aWxlSUQuY2Fub25pY2FsLnopLHI9ZS50aWxlSUQua2V5OzA9PT1pJiYwPT09bnx8TWF0aC5hYnMobik+MXx8KE1hdGguYWJzKGkpPjEmJigxPT09TWF0aC5hYnMoaStvKT9pKz1vOjE9PT1NYXRoLmFicyhpLW8pJiYoaS09bykpLGUuZGVtJiZ0LmRlbSYmKHQuZGVtLmJhY2tmaWxsQm9yZGVyKGUuZGVtLGksbiksdC5uZWlnaGJvcmluZ1RpbGVzJiZ0Lm5laWdoYm9yaW5nVGlsZXNbcl0mJih0Lm5laWdoYm9yaW5nVGlsZXNbcl0uYmFja2ZpbGxlZD0hMCkpKTt9fSxpLnByb3RvdHlwZS5nZXRUaWxlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmdldFRpbGVCeUlEKHQua2V5KX0saS5wcm90b3R5cGUuZ2V0VGlsZUJ5SUQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3RpbGVzW3RdfSxpLnByb3RvdHlwZS5nZXRab29tPWZ1bmN0aW9uKHQpe3JldHVybiB0Lnpvb20rdC5zY2FsZVpvb20odC50aWxlU2l6ZS90aGlzLl9zb3VyY2UudGlsZVNpemUpfSxpLnByb3RvdHlwZS5fZmluZExvYWRlZENoaWxkcmVuPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj0hMTtmb3IodmFyIG8gaW4gdGhpcy5fdGlsZXMpe3ZhciByPXRoaXMuX3RpbGVzW29dO2lmKCEoaVtvXXx8IXIuaGFzRGF0YSgpfHxyLnRpbGVJRC5vdmVyc2NhbGVkWjw9dC5vdmVyc2NhbGVkWnx8ci50aWxlSUQub3ZlcnNjYWxlZFo+ZSkpe3ZhciBhPU1hdGgucG93KDIsci50aWxlSUQuY2Fub25pY2FsLnotdC5jYW5vbmljYWwueik7aWYoTWF0aC5mbG9vcihyLnRpbGVJRC5jYW5vbmljYWwueC9hKT09PXQuY2Fub25pY2FsLngmJk1hdGguZmxvb3Ioci50aWxlSUQuY2Fub25pY2FsLnkvYSk9PT10LmNhbm9uaWNhbC55KWZvcihpW29dPXIudGlsZUlELG49ITA7ciYmci50aWxlSUQub3ZlcnNjYWxlZFotMT50Lm92ZXJzY2FsZWRaOyl7dmFyIHM9ci50aWxlSUQuc2NhbGVkVG8oci50aWxlSUQub3ZlcnNjYWxlZFotMSk7aWYoIXMpYnJlYWs7KHI9dGhpcy5fdGlsZXNbcy5rZXldKSYmci5oYXNEYXRhKCkmJihkZWxldGUgaVtvXSxpW3Mua2V5XT1zKTt9fX1yZXR1cm4gbn0saS5wcm90b3R5cGUuZmluZExvYWRlZFBhcmVudD1mdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBuPXQub3ZlcnNjYWxlZFotMTtuPj1lO24tLSl7dmFyIG89dC5zY2FsZWRUbyhuKTtpZighbylyZXR1cm47dmFyIHI9U3RyaW5nKG8ua2V5KSxhPXRoaXMuX3RpbGVzW3JdO2lmKGEmJmEuaGFzRGF0YSgpKXJldHVybiBpW3JdPW8sYTtpZih0aGlzLl9jYWNoZS5oYXMobykpcmV0dXJuIGlbcl09byx0aGlzLl9jYWNoZS5nZXQobyl9fSxpLnByb3RvdHlwZS51cGRhdGVDYWNoZVNpemU9ZnVuY3Rpb24odCl7dmFyIGU9KE1hdGguY2VpbCh0LndpZHRoL3RoaXMuX3NvdXJjZS50aWxlU2l6ZSkrMSkqKE1hdGguY2VpbCh0LmhlaWdodC90aGlzLl9zb3VyY2UudGlsZVNpemUpKzEpLGk9TWF0aC5mbG9vcig1KmUpLG49XCJudW1iZXJcIj09dHlwZW9mIHRoaXMuX21heFRpbGVDYWNoZVNpemU/TWF0aC5taW4odGhpcy5fbWF4VGlsZUNhY2hlU2l6ZSxpKTppO3RoaXMuX2NhY2hlLnNldE1heFNpemUobik7fSxpLnByb3RvdHlwZS5oYW5kbGVXcmFwSnVtcD1mdW5jdGlvbih0KXt2YXIgZT0odC0odm9pZCAwPT09dGhpcy5fcHJldkxuZz90OnRoaXMuX3ByZXZMbmcpKS8zNjAsaT1NYXRoLnJvdW5kKGUpO2lmKHRoaXMuX3ByZXZMbmc9dCxpKXt2YXIgbj17fTtmb3IodmFyIG8gaW4gdGhpcy5fdGlsZXMpe3ZhciByPXRoaXMuX3RpbGVzW29dO3IudGlsZUlEPXIudGlsZUlELnVud3JhcFRvKHIudGlsZUlELndyYXAraSksbltyLnRpbGVJRC5rZXldPXI7fWZvcih2YXIgYSBpbiB0aGlzLl90aWxlcz1uLHRoaXMuX3RpbWVycyljbGVhclRpbWVvdXQodGhpcy5fdGltZXJzW2FdKSxkZWxldGUgdGhpcy5fdGltZXJzW2FdO2Zvcih2YXIgcyBpbiB0aGlzLl90aWxlcyl7dmFyIGw9dGhpcy5fdGlsZXNbc107dGhpcy5fc2V0VGlsZVJlbG9hZFRpbWVyKHMsbCk7fX19LGkucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbihlKXt2YXIgbj10aGlzO2lmKHRoaXMudHJhbnNmb3JtPWUsdGhpcy5fc291cmNlTG9hZGVkJiYhdGhpcy5fcGF1c2VkKXt2YXIgbzt0aGlzLnVwZGF0ZUNhY2hlU2l6ZShlKSx0aGlzLmhhbmRsZVdyYXBKdW1wKHRoaXMudHJhbnNmb3JtLmNlbnRlci5sbmcpLHRoaXMuX2NvdmVyZWRUaWxlcz17fSx0aGlzLnVzZWQ/dGhpcy5fc291cmNlLnRpbGVJRD9vPWUuZ2V0VmlzaWJsZVVud3JhcHBlZENvb3JkaW5hdGVzKHRoaXMuX3NvdXJjZS50aWxlSUQpLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLmNhbm9uaWNhbC56LGUud3JhcCxlLmNhbm9uaWNhbC56LGUuY2Fub25pY2FsLngsZS5jYW5vbmljYWwueSl9KToobz1lLmNvdmVyaW5nVGlsZXMoe3RpbGVTaXplOnRoaXMuX3NvdXJjZS50aWxlU2l6ZSxtaW56b29tOnRoaXMuX3NvdXJjZS5taW56b29tLG1heHpvb206dGhpcy5fc291cmNlLm1heHpvb20scm91bmRab29tOnRoaXMuX3NvdXJjZS5yb3VuZFpvb20scmVwYXJzZU92ZXJzY2FsZWQ6dGhpcy5fc291cmNlLnJlcGFyc2VPdmVyc2NhbGVkfSksdGhpcy5fc291cmNlLmhhc1RpbGUmJihvPW8uZmlsdGVyKGZ1bmN0aW9uKHQpe3JldHVybiBuLl9zb3VyY2UuaGFzVGlsZSh0KX0pKSk6bz1bXTt2YXIgYSxzPSh0aGlzLl9zb3VyY2Uucm91bmRab29tP01hdGgucm91bmQ6TWF0aC5mbG9vcikodGhpcy5nZXRab29tKGUpKSxsPU1hdGgubWF4KHMtaS5tYXhPdmVyem9vbWluZyx0aGlzLl9zb3VyY2UubWluem9vbSksYz1NYXRoLm1heChzK2kubWF4VW5kZXJ6b29taW5nLHRoaXMuX3NvdXJjZS5taW56b29tKSx1PXRoaXMuX3VwZGF0ZVJldGFpbmVkVGlsZXMobyxzKSxoPXt9O2lmKEt0KHRoaXMuX3NvdXJjZS50eXBlKSlmb3IodmFyIHA9T2JqZWN0LmtleXModSksZD0wO2Q8cC5sZW5ndGg7ZCsrKXt2YXIgZj1wW2RdLG09dVtmXSxfPW4uX3RpbGVzW2ZdO2lmKF8mJih2b2lkIDA9PT1fLmZhZGVFbmRUaW1lfHxfLmZhZGVFbmRUaW1lPj1yLm5vdygpKSl7bi5fZmluZExvYWRlZENoaWxkcmVuKG0sYyx1KSYmKHVbZl09bSk7dmFyIGc9bi5maW5kTG9hZGVkUGFyZW50KG0sbCxoKTtnJiZuLl9hZGRUaWxlKGcudGlsZUlEKTt9fWZvcihhIGluIGgpdVthXXx8KG4uX2NvdmVyZWRUaWxlc1thXT0hMCk7Zm9yKGEgaW4gaCl1W2FdPWhbYV07Zm9yKHZhciB2PXQua2V5c0RpZmZlcmVuY2UodGhpcy5fdGlsZXMsdSkseT0wO3k8di5sZW5ndGg7eSsrKW4uX3JlbW92ZVRpbGUodlt5XSk7fX0saS5wcm90b3R5cGUuX3VwZGF0ZVJldGFpbmVkVGlsZXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIG49e30sbz17fSxyPU1hdGgubWF4KGUtaS5tYXhPdmVyem9vbWluZyx0aGlzLl9zb3VyY2UubWluem9vbSksYT1NYXRoLm1heChlK2kubWF4VW5kZXJ6b29taW5nLHRoaXMuX3NvdXJjZS5taW56b29tKSxzPTA7czx0Lmxlbmd0aDtzKyspe3ZhciBsPXRbc10sYz10aGlzLl9hZGRUaWxlKGwpLHU9ITE7aWYoYy5oYXNEYXRhKCkpbltsLmtleV09bDtlbHNle3U9Yy53YXNSZXF1ZXN0ZWQoKSxuW2wua2V5XT1sO3ZhciBoPSEwO2lmKGUrMT50aGlzLl9zb3VyY2UubWF4em9vbSl7dmFyIHA9bC5jaGlsZHJlbih0aGlzLl9zb3VyY2UubWF4em9vbSlbMF0sZD10aGlzLmdldFRpbGUocCk7ZCYmZC5oYXNEYXRhKCk/bltwLmtleV09cDpoPSExO31lbHNle3RoaXMuX2ZpbmRMb2FkZWRDaGlsZHJlbihsLGEsbik7Zm9yKHZhciBmPWwuY2hpbGRyZW4odGhpcy5fc291cmNlLm1heHpvb20pLG09MDttPGYubGVuZ3RoO20rKylpZighbltmW21dLmtleV0pe2g9ITE7YnJlYWt9fWlmKCFoKWZvcih2YXIgXz1sLm92ZXJzY2FsZWRaLTE7Xz49cjstLV8pe3ZhciBnPWwuc2NhbGVkVG8oXyk7aWYob1tnLmtleV0pYnJlYWs7aWYob1tnLmtleV09ITAsIShjPXRoaXMuZ2V0VGlsZShnKSkmJnUmJihjPXRoaXMuX2FkZFRpbGUoZykpLGMmJihuW2cua2V5XT1nLHU9Yy53YXNSZXF1ZXN0ZWQoKSxjLmhhc0RhdGEoKSkpYnJlYWt9fX1yZXR1cm4gbn0saS5wcm90b3R5cGUuX2FkZFRpbGU9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5fdGlsZXNbZS5rZXldO2lmKGkpcmV0dXJuIGk7KGk9dGhpcy5fY2FjaGUuZ2V0QW5kUmVtb3ZlKGUpKSYmKHRoaXMuX3NldFRpbGVSZWxvYWRUaW1lcihlLmtleSxpKSxpLnRpbGVJRD1lKTt2YXIgbj1Cb29sZWFuKGkpO3JldHVybiBufHwoaT1uZXcgbHQoZSx0aGlzLl9zb3VyY2UudGlsZVNpemUqZS5vdmVyc2NhbGVGYWN0b3IoKSksdGhpcy5fbG9hZFRpbGUoaSx0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcyxpLGUua2V5LGkuc3RhdGUpKSksaT8oaS51c2VzKyssdGhpcy5fdGlsZXNbZS5rZXldPWksbnx8dGhpcy5fc291cmNlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHt0aWxlOmksY29vcmQ6aS50aWxlSUQsZGF0YVR5cGU6XCJzb3VyY2VcIn0pKSxpKTpudWxsfSxpLnByb3RvdHlwZS5fc2V0VGlsZVJlbG9hZFRpbWVyPWZ1bmN0aW9uKHQsZSl7dmFyIGk9dGhpczt0IGluIHRoaXMuX3RpbWVycyYmKGNsZWFyVGltZW91dCh0aGlzLl90aW1lcnNbdF0pLGRlbGV0ZSB0aGlzLl90aW1lcnNbdF0pO3ZhciBuPWUuZ2V0RXhwaXJ5VGltZW91dCgpO24mJih0aGlzLl90aW1lcnNbdF09c2V0VGltZW91dChmdW5jdGlvbigpe2kuX3JlbG9hZFRpbGUodCxcImV4cGlyZWRcIiksZGVsZXRlIGkuX3RpbWVyc1t0XTt9LG4pKTt9LGkucHJvdG90eXBlLl9yZW1vdmVUaWxlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuX3RpbGVzW3RdO2UmJihlLnVzZXMtLSxkZWxldGUgdGhpcy5fdGlsZXNbdF0sdGhpcy5fdGltZXJzW3RdJiYoY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyc1t0XSksZGVsZXRlIHRoaXMuX3RpbWVyc1t0XSksZS51c2VzPjB8fChlLmhhc0RhdGEoKT90aGlzLl9jYWNoZS5hZGQoZS50aWxlSUQsZSxlLmdldEV4cGlyeVRpbWVvdXQoKSk6KGUuYWJvcnRlZD0hMCx0aGlzLl9hYm9ydFRpbGUoZSksdGhpcy5fdW5sb2FkVGlsZShlKSkpKTt9LGkucHJvdG90eXBlLmNsZWFyVGlsZXM9ZnVuY3Rpb24oKXtmb3IodmFyIHQgaW4gdGhpcy5fc2hvdWxkUmVsb2FkT25SZXN1bWU9ITEsdGhpcy5fcGF1c2VkPSExLHRoaXMuX3RpbGVzKXRoaXMuX3JlbW92ZVRpbGUodCk7dGhpcy5fY2FjaGUucmVzZXQoKTt9LGkucHJvdG90eXBlLnRpbGVzSW49ZnVuY3Rpb24oZSxpKXtmb3IodmFyIG49W10sbz10aGlzLmdldElkcygpLHI9MS8wLGE9MS8wLHM9LTEvMCxsPS0xLzAsYz1lWzBdLnpvb20sdT0wO3U8ZS5sZW5ndGg7dSsrKXt2YXIgaD1lW3VdO3I9TWF0aC5taW4ocixoLmNvbHVtbiksYT1NYXRoLm1pbihhLGgucm93KSxzPU1hdGgubWF4KHMsaC5jb2x1bW4pLGw9TWF0aC5tYXgobCxoLnJvdyk7fWZvcih2YXIgcD0wO3A8by5sZW5ndGg7cCsrKXt2YXIgZD10aGlzLl90aWxlc1tvW3BdXSxmPWQudGlsZUlELG09TWF0aC5wb3coMix0aGlzLnRyYW5zZm9ybS56b29tLWQudGlsZUlELm92ZXJzY2FsZWRaKSxfPWkqZC5xdWVyeVBhZGRpbmcqdC5kZWZhdWx0JDgvZC50aWxlU2l6ZS9tLGc9W0h0KGYsbmV3IHQuZGVmYXVsdCQxNyhyLGEsYykpLEh0KGYsbmV3IHQuZGVmYXVsdCQxNyhzLGwsYykpXTtpZihnWzBdLngtXzx0LmRlZmF1bHQkOCYmZ1swXS55LV88dC5kZWZhdWx0JDgmJmdbMV0ueCtfPj0wJiZnWzFdLnkrXz49MCl7Zm9yKHZhciB2PVtdLHk9MDt5PGUubGVuZ3RoO3krKyl2LnB1c2goSHQoZixlW3ldKSk7bi5wdXNoKHt0aWxlOmQsdGlsZUlEOmYscXVlcnlHZW9tZXRyeTpbdl0sc2NhbGU6bX0pO319cmV0dXJuIG59LGkucHJvdG90eXBlLmdldFZpc2libGVDb29yZGluYXRlcz1mdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLGU9dGhpcy5nZXRSZW5kZXJhYmxlSWRzKCkubWFwKGZ1bmN0aW9uKGUpe3JldHVybiB0Ll90aWxlc1tlXS50aWxlSUR9KSxpPTAsbj1lO2k8bi5sZW5ndGg7aSs9MSl7dmFyIG89bltpXTtvLnBvc01hdHJpeD10LnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgoby50b1Vud3JhcHBlZCgpKTt9cmV0dXJuIGV9LGkucHJvdG90eXBlLmhhc1RyYW5zaXRpb249ZnVuY3Rpb24oKXtpZih0aGlzLl9zb3VyY2UuaGFzVHJhbnNpdGlvbigpKXJldHVybiEwO2lmKEt0KHRoaXMuX3NvdXJjZS50eXBlKSlmb3IodmFyIHQgaW4gdGhpcy5fdGlsZXMpe3ZhciBlPXRoaXMuX3RpbGVzW3RdO2lmKHZvaWQgMCE9PWUuZmFkZUVuZFRpbWUmJmUuZmFkZUVuZFRpbWU+PXIubm93KCkpcmV0dXJuITB9cmV0dXJuITF9LGl9KHQuRXZlbnRlZCk7ZnVuY3Rpb24gSHQoZSxpKXt2YXIgbj1pLnpvb21UbyhlLmNhbm9uaWNhbC56KTtyZXR1cm4gbmV3IHQuZGVmYXVsdCQxKChuLmNvbHVtbi0oZS5jYW5vbmljYWwueCtlLndyYXAqTWF0aC5wb3coMixlLmNhbm9uaWNhbC56KSkpKnQuZGVmYXVsdCQ4LChuLnJvdy1lLmNhbm9uaWNhbC55KSp0LmRlZmF1bHQkOCl9ZnVuY3Rpb24gS3QodCl7cmV0dXJuXCJyYXN0ZXJcIj09PXR8fFwiaW1hZ2VcIj09PXR8fFwidmlkZW9cIj09PXR9ZnVuY3Rpb24gWXQoKXtyZXR1cm4gbmV3IHQuZGVmYXVsdC5Xb3JrZXIoUm4ud29ya2VyVXJsKX1YdC5tYXhPdmVyem9vbWluZz0xMCxYdC5tYXhVbmRlcnpvb21pbmc9Mzt2YXIgSnQsUXQ9ZnVuY3Rpb24oKXt0aGlzLmFjdGl2ZT17fTt9O2Z1bmN0aW9uIHRlKGUsaSl7dmFyIG49e307Zm9yKHZhciBvIGluIGUpXCJyZWZcIiE9PW8mJihuW29dPWVbb10pO3JldHVybiB0LmRlZmF1bHQkMTguZm9yRWFjaChmdW5jdGlvbih0KXt0IGluIGkmJihuW3RdPWlbdF0pO30pLG59ZnVuY3Rpb24gZWUodCl7dD10LnNsaWNlKCk7Zm9yKHZhciBlPU9iamVjdC5jcmVhdGUobnVsbCksaT0wO2k8dC5sZW5ndGg7aSsrKWVbdFtpXS5pZF09dFtpXTtmb3IodmFyIG49MDtuPHQubGVuZ3RoO24rKylcInJlZlwiaW4gdFtuXSYmKHRbbl09dGUodFtuXSxlW3Rbbl0ucmVmXSkpO3JldHVybiB0fVF0LnByb3RvdHlwZS5hY3F1aXJlPWZ1bmN0aW9uKHQpe2lmKCF0aGlzLndvcmtlcnMpe3ZhciBlPVJuLndvcmtlckNvdW50O2Zvcih0aGlzLndvcmtlcnM9W107dGhpcy53b3JrZXJzLmxlbmd0aDxlOyl0aGlzLndvcmtlcnMucHVzaChuZXcgWXQpO31yZXR1cm4gdGhpcy5hY3RpdmVbdF09ITAsdGhpcy53b3JrZXJzLnNsaWNlKCl9LFF0LnByb3RvdHlwZS5yZWxlYXNlPWZ1bmN0aW9uKHQpe2RlbGV0ZSB0aGlzLmFjdGl2ZVt0XSwwPT09T2JqZWN0LmtleXModGhpcy5hY3RpdmUpLmxlbmd0aCYmKHRoaXMud29ya2Vycy5mb3JFYWNoKGZ1bmN0aW9uKHQpe3QudGVybWluYXRlKCk7fSksdGhpcy53b3JrZXJzPW51bGwpO307dmFyIGllPXtzZXRTdHlsZTpcInNldFN0eWxlXCIsYWRkTGF5ZXI6XCJhZGRMYXllclwiLHJlbW92ZUxheWVyOlwicmVtb3ZlTGF5ZXJcIixzZXRQYWludFByb3BlcnR5Olwic2V0UGFpbnRQcm9wZXJ0eVwiLHNldExheW91dFByb3BlcnR5Olwic2V0TGF5b3V0UHJvcGVydHlcIixzZXRGaWx0ZXI6XCJzZXRGaWx0ZXJcIixhZGRTb3VyY2U6XCJhZGRTb3VyY2VcIixyZW1vdmVTb3VyY2U6XCJyZW1vdmVTb3VyY2VcIixzZXRHZW9KU09OU291cmNlRGF0YTpcInNldEdlb0pTT05Tb3VyY2VEYXRhXCIsc2V0TGF5ZXJab29tUmFuZ2U6XCJzZXRMYXllclpvb21SYW5nZVwiLHNldExheWVyUHJvcGVydHk6XCJzZXRMYXllclByb3BlcnR5XCIsc2V0Q2VudGVyOlwic2V0Q2VudGVyXCIsc2V0Wm9vbTpcInNldFpvb21cIixzZXRCZWFyaW5nOlwic2V0QmVhcmluZ1wiLHNldFBpdGNoOlwic2V0UGl0Y2hcIixzZXRTcHJpdGU6XCJzZXRTcHJpdGVcIixzZXRHbHlwaHM6XCJzZXRHbHlwaHNcIixzZXRUcmFuc2l0aW9uOlwic2V0VHJhbnNpdGlvblwiLHNldExpZ2h0Olwic2V0TGlnaHRcIn07ZnVuY3Rpb24gbmUodCxlLGkpe2kucHVzaCh7Y29tbWFuZDppZS5hZGRTb3VyY2UsYXJnczpbdCxlW3RdXX0pO31mdW5jdGlvbiBvZSh0LGUsaSl7ZS5wdXNoKHtjb21tYW5kOmllLnJlbW92ZVNvdXJjZSxhcmdzOlt0XX0pLGlbdF09ITA7fWZ1bmN0aW9uIHJlKHQsZSxpLG4pe29lKHQsaSxuKSxuZSh0LGUsaSk7fWZ1bmN0aW9uIGFlKGUsaSxuKXt2YXIgbztmb3IobyBpbiBlW25dKWlmKGVbbl0uaGFzT3duUHJvcGVydHkobykmJlwiZGF0YVwiIT09byYmIXQuZGVmYXVsdCQxMChlW25dW29dLGlbbl1bb10pKXJldHVybiExO2ZvcihvIGluIGlbbl0paWYoaVtuXS5oYXNPd25Qcm9wZXJ0eShvKSYmXCJkYXRhXCIhPT1vJiYhdC5kZWZhdWx0JDEwKGVbbl1bb10saVtuXVtvXSkpcmV0dXJuITE7cmV0dXJuITB9ZnVuY3Rpb24gc2UoZSxpLG4sbyxyLGEpe3ZhciBzO2ZvcihzIGluIGk9aXx8e30sZT1lfHx7fSllLmhhc093blByb3BlcnR5KHMpJiYodC5kZWZhdWx0JDEwKGVbc10saVtzXSl8fG4ucHVzaCh7Y29tbWFuZDphLGFyZ3M6W28scyxpW3NdLHJdfSkpO2ZvcihzIGluIGkpaS5oYXNPd25Qcm9wZXJ0eShzKSYmIWUuaGFzT3duUHJvcGVydHkocykmJih0LmRlZmF1bHQkMTAoZVtzXSxpW3NdKXx8bi5wdXNoKHtjb21tYW5kOmEsYXJnczpbbyxzLGlbc10scl19KSk7fWZ1bmN0aW9uIGxlKHQpe3JldHVybiB0LmlkfWZ1bmN0aW9uIGNlKHQsZSl7cmV0dXJuIHRbZS5pZF09ZSx0fWZ1bmN0aW9uIHVlKGUsaSl7aWYoIWUpcmV0dXJuW3tjb21tYW5kOmllLnNldFN0eWxlLGFyZ3M6W2ldfV07dmFyIG49W107dHJ5e2lmKCF0LmRlZmF1bHQkMTAoZS52ZXJzaW9uLGkudmVyc2lvbikpcmV0dXJuW3tjb21tYW5kOmllLnNldFN0eWxlLGFyZ3M6W2ldfV07dC5kZWZhdWx0JDEwKGUuY2VudGVyLGkuY2VudGVyKXx8bi5wdXNoKHtjb21tYW5kOmllLnNldENlbnRlcixhcmdzOltpLmNlbnRlcl19KSx0LmRlZmF1bHQkMTAoZS56b29tLGkuem9vbSl8fG4ucHVzaCh7Y29tbWFuZDppZS5zZXRab29tLGFyZ3M6W2kuem9vbV19KSx0LmRlZmF1bHQkMTAoZS5iZWFyaW5nLGkuYmVhcmluZyl8fG4ucHVzaCh7Y29tbWFuZDppZS5zZXRCZWFyaW5nLGFyZ3M6W2kuYmVhcmluZ119KSx0LmRlZmF1bHQkMTAoZS5waXRjaCxpLnBpdGNoKXx8bi5wdXNoKHtjb21tYW5kOmllLnNldFBpdGNoLGFyZ3M6W2kucGl0Y2hdfSksdC5kZWZhdWx0JDEwKGUuc3ByaXRlLGkuc3ByaXRlKXx8bi5wdXNoKHtjb21tYW5kOmllLnNldFNwcml0ZSxhcmdzOltpLnNwcml0ZV19KSx0LmRlZmF1bHQkMTAoZS5nbHlwaHMsaS5nbHlwaHMpfHxuLnB1c2goe2NvbW1hbmQ6aWUuc2V0R2x5cGhzLGFyZ3M6W2kuZ2x5cGhzXX0pLHQuZGVmYXVsdCQxMChlLnRyYW5zaXRpb24saS50cmFuc2l0aW9uKXx8bi5wdXNoKHtjb21tYW5kOmllLnNldFRyYW5zaXRpb24sYXJnczpbaS50cmFuc2l0aW9uXX0pLHQuZGVmYXVsdCQxMChlLmxpZ2h0LGkubGlnaHQpfHxuLnB1c2goe2NvbW1hbmQ6aWUuc2V0TGlnaHQsYXJnczpbaS5saWdodF19KTt2YXIgbz17fSxyPVtdOyFmdW5jdGlvbihlLGksbixvKXt2YXIgcjtmb3IociBpbiBpPWl8fHt9LGU9ZXx8e30pZS5oYXNPd25Qcm9wZXJ0eShyKSYmKGkuaGFzT3duUHJvcGVydHkocil8fG9lKHIsbixvKSk7Zm9yKHIgaW4gaSlpLmhhc093blByb3BlcnR5KHIpJiYoZS5oYXNPd25Qcm9wZXJ0eShyKT90LmRlZmF1bHQkMTAoZVtyXSxpW3JdKXx8KFwiZ2VvanNvblwiPT09ZVtyXS50eXBlJiZcImdlb2pzb25cIj09PWlbcl0udHlwZSYmYWUoZSxpLHIpP24ucHVzaCh7Y29tbWFuZDppZS5zZXRHZW9KU09OU291cmNlRGF0YSxhcmdzOltyLGlbcl0uZGF0YV19KTpyZShyLGksbixvKSk6bmUocixpLG4pKTt9KGUuc291cmNlcyxpLnNvdXJjZXMscixvKTt2YXIgYT1bXTtlLmxheWVycyYmZS5sYXllcnMuZm9yRWFjaChmdW5jdGlvbih0KXtvW3Quc291cmNlXT9uLnB1c2goe2NvbW1hbmQ6aWUucmVtb3ZlTGF5ZXIsYXJnczpbdC5pZF19KTphLnB1c2godCk7fSksbj1uLmNvbmNhdChyKSxmdW5jdGlvbihlLGksbil7aT1pfHxbXTt2YXIgbyxyLGEscyxsLGMsdSxoPShlPWV8fFtdKS5tYXAobGUpLHA9aS5tYXAobGUpLGQ9ZS5yZWR1Y2UoY2Use30pLGY9aS5yZWR1Y2UoY2Use30pLG09aC5zbGljZSgpLF89T2JqZWN0LmNyZWF0ZShudWxsKTtmb3Iobz0wLHI9MDtvPGgubGVuZ3RoO28rKylhPWhbb10sZi5oYXNPd25Qcm9wZXJ0eShhKT9yKys6KG4ucHVzaCh7Y29tbWFuZDppZS5yZW1vdmVMYXllcixhcmdzOlthXX0pLG0uc3BsaWNlKG0uaW5kZXhPZihhLHIpLDEpKTtmb3Iobz0wLHI9MDtvPHAubGVuZ3RoO28rKylhPXBbcC5sZW5ndGgtMS1vXSxtW20ubGVuZ3RoLTEtb10hPT1hJiYoZC5oYXNPd25Qcm9wZXJ0eShhKT8obi5wdXNoKHtjb21tYW5kOmllLnJlbW92ZUxheWVyLGFyZ3M6W2FdfSksbS5zcGxpY2UobS5sYXN0SW5kZXhPZihhLG0ubGVuZ3RoLXIpLDEpKTpyKyssYz1tW20ubGVuZ3RoLW9dLG4ucHVzaCh7Y29tbWFuZDppZS5hZGRMYXllcixhcmdzOltmW2FdLGNdfSksbS5zcGxpY2UobS5sZW5ndGgtbywwLGEpLF9bYV09ITApO2ZvcihvPTA7bzxwLmxlbmd0aDtvKyspaWYocz1kW2E9cFtvXV0sbD1mW2FdLCFfW2FdJiYhdC5kZWZhdWx0JDEwKHMsbCkpaWYodC5kZWZhdWx0JDEwKHMuc291cmNlLGwuc291cmNlKSYmdC5kZWZhdWx0JDEwKHNbXCJzb3VyY2UtbGF5ZXJcIl0sbFtcInNvdXJjZS1sYXllclwiXSkmJnQuZGVmYXVsdCQxMChzLnR5cGUsbC50eXBlKSl7Zm9yKHUgaW4gc2Uocy5sYXlvdXQsbC5sYXlvdXQsbixhLG51bGwsaWUuc2V0TGF5b3V0UHJvcGVydHkpLHNlKHMucGFpbnQsbC5wYWludCxuLGEsbnVsbCxpZS5zZXRQYWludFByb3BlcnR5KSx0LmRlZmF1bHQkMTAocy5maWx0ZXIsbC5maWx0ZXIpfHxuLnB1c2goe2NvbW1hbmQ6aWUuc2V0RmlsdGVyLGFyZ3M6W2EsbC5maWx0ZXJdfSksdC5kZWZhdWx0JDEwKHMubWluem9vbSxsLm1pbnpvb20pJiZ0LmRlZmF1bHQkMTAocy5tYXh6b29tLGwubWF4em9vbSl8fG4ucHVzaCh7Y29tbWFuZDppZS5zZXRMYXllclpvb21SYW5nZSxhcmdzOlthLGwubWluem9vbSxsLm1heHpvb21dfSkscylzLmhhc093blByb3BlcnR5KHUpJiZcImxheW91dFwiIT09dSYmXCJwYWludFwiIT09dSYmXCJmaWx0ZXJcIiE9PXUmJlwibWV0YWRhdGFcIiE9PXUmJlwibWluem9vbVwiIT09dSYmXCJtYXh6b29tXCIhPT11JiYoMD09PXUuaW5kZXhPZihcInBhaW50LlwiKT9zZShzW3VdLGxbdV0sbixhLHUuc2xpY2UoNiksaWUuc2V0UGFpbnRQcm9wZXJ0eSk6dC5kZWZhdWx0JDEwKHNbdV0sbFt1XSl8fG4ucHVzaCh7Y29tbWFuZDppZS5zZXRMYXllclByb3BlcnR5LGFyZ3M6W2EsdSxsW3VdXX0pKTtmb3IodSBpbiBsKWwuaGFzT3duUHJvcGVydHkodSkmJiFzLmhhc093blByb3BlcnR5KHUpJiZcImxheW91dFwiIT09dSYmXCJwYWludFwiIT09dSYmXCJmaWx0ZXJcIiE9PXUmJlwibWV0YWRhdGFcIiE9PXUmJlwibWluem9vbVwiIT09dSYmXCJtYXh6b29tXCIhPT11JiYoMD09PXUuaW5kZXhPZihcInBhaW50LlwiKT9zZShzW3VdLGxbdV0sbixhLHUuc2xpY2UoNiksaWUuc2V0UGFpbnRQcm9wZXJ0eSk6dC5kZWZhdWx0JDEwKHNbdV0sbFt1XSl8fG4ucHVzaCh7Y29tbWFuZDppZS5zZXRMYXllclByb3BlcnR5LGFyZ3M6W2EsdSxsW3VdXX0pKTt9ZWxzZSBuLnB1c2goe2NvbW1hbmQ6aWUucmVtb3ZlTGF5ZXIsYXJnczpbYV19KSxjPW1bbS5sYXN0SW5kZXhPZihhKSsxXSxuLnB1c2goe2NvbW1hbmQ6aWUuYWRkTGF5ZXIsYXJnczpbbCxjXX0pO30oYSxpLmxheWVycyxuKTt9Y2F0Y2godCl7Y29uc29sZS53YXJuKFwiVW5hYmxlIHRvIGNvbXB1dGUgc3R5bGUgZGlmZjpcIix0KSxuPVt7Y29tbWFuZDppZS5zZXRTdHlsZSxhcmdzOltpXX1dO31yZXR1cm4gbn12YXIgaGU9ZnVuY3Rpb24odCxlLGkpe3ZhciBuPXRoaXMuYm94Q2VsbHM9W10sbz10aGlzLmNpcmNsZUNlbGxzPVtdO3RoaXMueENlbGxDb3VudD1NYXRoLmNlaWwodC9pKSx0aGlzLnlDZWxsQ291bnQ9TWF0aC5jZWlsKGUvaSk7Zm9yKHZhciByPTA7cjx0aGlzLnhDZWxsQ291bnQqdGhpcy55Q2VsbENvdW50O3IrKyluLnB1c2goW10pLG8ucHVzaChbXSk7dGhpcy5jaXJjbGVLZXlzPVtdLHRoaXMuYm94S2V5cz1bXSx0aGlzLmJib3hlcz1bXSx0aGlzLmNpcmNsZXM9W10sdGhpcy53aWR0aD10LHRoaXMuaGVpZ2h0PWUsdGhpcy54U2NhbGU9dGhpcy54Q2VsbENvdW50L3QsdGhpcy55U2NhbGU9dGhpcy55Q2VsbENvdW50L2UsdGhpcy5ib3hVaWQ9MCx0aGlzLmNpcmNsZVVpZD0wO307aGUucHJvdG90eXBlLmtleXNMZW5ndGg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5ib3hLZXlzLmxlbmd0aCt0aGlzLmNpcmNsZUtleXMubGVuZ3RofSxoZS5wcm90b3R5cGUuaW5zZXJ0PWZ1bmN0aW9uKHQsZSxpLG4sbyl7dGhpcy5fZm9yRWFjaENlbGwoZSxpLG4sbyx0aGlzLl9pbnNlcnRCb3hDZWxsLHRoaXMuYm94VWlkKyspLHRoaXMuYm94S2V5cy5wdXNoKHQpLHRoaXMuYmJveGVzLnB1c2goZSksdGhpcy5iYm94ZXMucHVzaChpKSx0aGlzLmJib3hlcy5wdXNoKG4pLHRoaXMuYmJveGVzLnB1c2gobyk7fSxoZS5wcm90b3R5cGUuaW5zZXJ0Q2lyY2xlPWZ1bmN0aW9uKHQsZSxpLG4pe3RoaXMuX2ZvckVhY2hDZWxsKGUtbixpLW4sZStuLGkrbix0aGlzLl9pbnNlcnRDaXJjbGVDZWxsLHRoaXMuY2lyY2xlVWlkKyspLHRoaXMuY2lyY2xlS2V5cy5wdXNoKHQpLHRoaXMuY2lyY2xlcy5wdXNoKGUpLHRoaXMuY2lyY2xlcy5wdXNoKGkpLHRoaXMuY2lyY2xlcy5wdXNoKG4pO30saGUucHJvdG90eXBlLl9pbnNlcnRCb3hDZWxsPWZ1bmN0aW9uKHQsZSxpLG4sbyxyKXt0aGlzLmJveENlbGxzW29dLnB1c2gocik7fSxoZS5wcm90b3R5cGUuX2luc2VydENpcmNsZUNlbGw9ZnVuY3Rpb24odCxlLGksbixvLHIpe3RoaXMuY2lyY2xlQ2VsbHNbb10ucHVzaChyKTt9LGhlLnByb3RvdHlwZS5fcXVlcnk9ZnVuY3Rpb24odCxlLGksbixvKXtpZihpPDB8fHQ+dGhpcy53aWR0aHx8bjwwfHxlPnRoaXMuaGVpZ2h0KXJldHVybiFvJiZbXTt2YXIgcj1bXTtpZih0PD0wJiZlPD0wJiZ0aGlzLndpZHRoPD1pJiZ0aGlzLmhlaWdodDw9bil7aWYobylyZXR1cm4hMDtmb3IodmFyIGE9MDthPHRoaXMuYm94S2V5cy5sZW5ndGg7YSsrKXIucHVzaCh7a2V5OnRoaXMuYm94S2V5c1thXSx4MTp0aGlzLmJib3hlc1s0KmFdLHkxOnRoaXMuYmJveGVzWzQqYSsxXSx4Mjp0aGlzLmJib3hlc1s0KmErMl0seTI6dGhpcy5iYm94ZXNbNCphKzNdfSk7Zm9yKHZhciBzPTA7czx0aGlzLmNpcmNsZUtleXMubGVuZ3RoO3MrKyl7dmFyIGw9dGhpcy5jaXJjbGVzWzMqc10sYz10aGlzLmNpcmNsZXNbMypzKzFdLHU9dGhpcy5jaXJjbGVzWzMqcysyXTtyLnB1c2goe2tleTp0aGlzLmNpcmNsZUtleXNbc10seDE6bC11LHkxOmMtdSx4MjpsK3UseTI6Yyt1fSk7fX1lbHNle3ZhciBoPXtoaXRUZXN0Om8sc2VlblVpZHM6e2JveDp7fSxjaXJjbGU6e319fTt0aGlzLl9mb3JFYWNoQ2VsbCh0LGUsaSxuLHRoaXMuX3F1ZXJ5Q2VsbCxyLGgpO31yZXR1cm4gbz9yLmxlbmd0aD4wOnJ9LGhlLnByb3RvdHlwZS5fcXVlcnlDaXJjbGU9ZnVuY3Rpb24odCxlLGksbil7dmFyIG89dC1pLHI9dCtpLGE9ZS1pLHM9ZStpO2lmKHI8MHx8bz50aGlzLndpZHRofHxzPDB8fGE+dGhpcy5oZWlnaHQpcmV0dXJuIW4mJltdO3ZhciBsPVtdLGM9e2hpdFRlc3Q6bixjaXJjbGU6e3g6dCx5OmUscmFkaXVzOml9LHNlZW5VaWRzOntib3g6e30sY2lyY2xlOnt9fX07cmV0dXJuIHRoaXMuX2ZvckVhY2hDZWxsKG8sYSxyLHMsdGhpcy5fcXVlcnlDZWxsQ2lyY2xlLGwsYyksbj9sLmxlbmd0aD4wOmx9LGhlLnByb3RvdHlwZS5xdWVyeT1mdW5jdGlvbih0LGUsaSxuKXtyZXR1cm4gdGhpcy5fcXVlcnkodCxlLGksbiwhMSl9LGhlLnByb3RvdHlwZS5oaXRUZXN0PWZ1bmN0aW9uKHQsZSxpLG4pe3JldHVybiB0aGlzLl9xdWVyeSh0LGUsaSxuLCEwKX0saGUucHJvdG90eXBlLmhpdFRlc3RDaXJjbGU9ZnVuY3Rpb24odCxlLGkpe3JldHVybiB0aGlzLl9xdWVyeUNpcmNsZSh0LGUsaSwhMCl9LGhlLnByb3RvdHlwZS5fcXVlcnlDZWxsPWZ1bmN0aW9uKHQsZSxpLG4sbyxyLGEpe3ZhciBzPWEuc2VlblVpZHMsbD10aGlzLmJveENlbGxzW29dO2lmKG51bGwhPT1sKWZvcih2YXIgYz10aGlzLmJib3hlcyx1PTAsaD1sO3U8aC5sZW5ndGg7dSs9MSl7dmFyIHA9aFt1XTtpZighcy5ib3hbcF0pe3MuYm94W3BdPSEwO3ZhciBkPTQqcDtpZih0PD1jW2QrMl0mJmU8PWNbZCszXSYmaT49Y1tkKzBdJiZuPj1jW2QrMV0pe2lmKGEuaGl0VGVzdClyZXR1cm4gci5wdXNoKCEwKSwhMDtyLnB1c2goe2tleTp0aGlzLmJveEtleXNbcF0seDE6Y1tkXSx5MTpjW2QrMV0seDI6Y1tkKzJdLHkyOmNbZCszXX0pO319fXZhciBmPXRoaXMuY2lyY2xlQ2VsbHNbb107aWYobnVsbCE9PWYpZm9yKHZhciBtPXRoaXMuY2lyY2xlcyxfPTAsZz1mO188Zy5sZW5ndGg7Xys9MSl7dmFyIHY9Z1tfXTtpZighcy5jaXJjbGVbdl0pe3MuY2lyY2xlW3ZdPSEwO3ZhciB5PTMqdjtpZih0aGlzLl9jaXJjbGVBbmRSZWN0Q29sbGlkZShtW3ldLG1beSsxXSxtW3krMl0sdCxlLGksbikpe2lmKGEuaGl0VGVzdClyZXR1cm4gci5wdXNoKCEwKSwhMDt2YXIgeD1tW3ldLGI9bVt5KzFdLHc9bVt5KzJdO3IucHVzaCh7a2V5OnRoaXMuY2lyY2xlS2V5c1t2XSx4MTp4LXcseTE6Yi13LHgyOngrdyx5MjpiK3d9KTt9fX19LGhlLnByb3RvdHlwZS5fcXVlcnlDZWxsQ2lyY2xlPWZ1bmN0aW9uKHQsZSxpLG4sbyxyLGEpe3ZhciBzPWEuY2lyY2xlLGw9YS5zZWVuVWlkcyxjPXRoaXMuYm94Q2VsbHNbb107aWYobnVsbCE9PWMpZm9yKHZhciB1PXRoaXMuYmJveGVzLGg9MCxwPWM7aDxwLmxlbmd0aDtoKz0xKXt2YXIgZD1wW2hdO2lmKCFsLmJveFtkXSl7bC5ib3hbZF09ITA7dmFyIGY9NCpkO2lmKHRoaXMuX2NpcmNsZUFuZFJlY3RDb2xsaWRlKHMueCxzLnkscy5yYWRpdXMsdVtmKzBdLHVbZisxXSx1W2YrMl0sdVtmKzNdKSlyZXR1cm4gci5wdXNoKCEwKSwhMH19dmFyIG09dGhpcy5jaXJjbGVDZWxsc1tvXTtpZihudWxsIT09bSlmb3IodmFyIF89dGhpcy5jaXJjbGVzLGc9MCx2PW07Zzx2Lmxlbmd0aDtnKz0xKXt2YXIgeT12W2ddO2lmKCFsLmNpcmNsZVt5XSl7bC5jaXJjbGVbeV09ITA7dmFyIHg9Myp5O2lmKHRoaXMuX2NpcmNsZXNDb2xsaWRlKF9beF0sX1t4KzFdLF9beCsyXSxzLngscy55LHMucmFkaXVzKSlyZXR1cm4gci5wdXNoKCEwKSwhMH19fSxoZS5wcm90b3R5cGUuX2ZvckVhY2hDZWxsPWZ1bmN0aW9uKHQsZSxpLG4sbyxyLGEpe2Zvcih2YXIgcz10aGlzLl9jb252ZXJ0VG9YQ2VsbENvb3JkKHQpLGw9dGhpcy5fY29udmVydFRvWUNlbGxDb29yZChlKSxjPXRoaXMuX2NvbnZlcnRUb1hDZWxsQ29vcmQoaSksdT10aGlzLl9jb252ZXJ0VG9ZQ2VsbENvb3JkKG4pLGg9cztoPD1jO2grKylmb3IodmFyIHA9bDtwPD11O3ArKyl7dmFyIGQ9dGhpcy54Q2VsbENvdW50KnAraDtpZihvLmNhbGwodGhpcyx0LGUsaSxuLGQscixhKSlyZXR1cm59fSxoZS5wcm90b3R5cGUuX2NvbnZlcnRUb1hDZWxsQ29vcmQ9ZnVuY3Rpb24odCl7cmV0dXJuIE1hdGgubWF4KDAsTWF0aC5taW4odGhpcy54Q2VsbENvdW50LTEsTWF0aC5mbG9vcih0KnRoaXMueFNjYWxlKSkpfSxoZS5wcm90b3R5cGUuX2NvbnZlcnRUb1lDZWxsQ29vcmQ9ZnVuY3Rpb24odCl7cmV0dXJuIE1hdGgubWF4KDAsTWF0aC5taW4odGhpcy55Q2VsbENvdW50LTEsTWF0aC5mbG9vcih0KnRoaXMueVNjYWxlKSkpfSxoZS5wcm90b3R5cGUuX2NpcmNsZXNDb2xsaWRlPWZ1bmN0aW9uKHQsZSxpLG4sbyxyKXt2YXIgYT1uLXQscz1vLWUsbD1pK3I7cmV0dXJuIGwqbD5hKmErcypzfSxoZS5wcm90b3R5cGUuX2NpcmNsZUFuZFJlY3RDb2xsaWRlPWZ1bmN0aW9uKHQsZSxpLG4sbyxyLGEpe3ZhciBzPShyLW4pLzIsbD1NYXRoLmFicyh0LShuK3MpKTtpZihsPnMraSlyZXR1cm4hMTt2YXIgYz0oYS1vKS8yLHU9TWF0aC5hYnMoZS0obytjKSk7aWYodT5jK2kpcmV0dXJuITE7aWYobDw9c3x8dTw9YylyZXR1cm4hMDt2YXIgaD1sLXMscD11LWM7cmV0dXJuIGgqaCtwKnA8PWkqaX07dmFyIHBlPXQuZGVmYXVsdCQxOS5sYXlvdXQ7ZnVuY3Rpb24gZGUoZSxpLG4sbyxyKXt2YXIgYT10Lm1hdDQuaWRlbnRpdHkobmV3IEZsb2F0MzJBcnJheSgxNikpO3JldHVybiBpPyh0Lm1hdDQuaWRlbnRpdHkoYSksdC5tYXQ0LnNjYWxlKGEsYSxbMS9yLDEvciwxXSksbnx8dC5tYXQ0LnJvdGF0ZVooYSxhLG8uYW5nbGUpKToodC5tYXQ0LnNjYWxlKGEsYSxbby53aWR0aC8yLC1vLmhlaWdodC8yLDFdKSx0Lm1hdDQudHJhbnNsYXRlKGEsYSxbMSwtMSwwXSksdC5tYXQ0Lm11bHRpcGx5KGEsYSxlKSksYX1mdW5jdGlvbiBmZShlLGksbixvLHIpe3ZhciBhPXQubWF0NC5pZGVudGl0eShuZXcgRmxvYXQzMkFycmF5KDE2KSk7cmV0dXJuIGk/KHQubWF0NC5tdWx0aXBseShhLGEsZSksdC5tYXQ0LnNjYWxlKGEsYSxbcixyLDFdKSxufHx0Lm1hdDQucm90YXRlWihhLGEsLW8uYW5nbGUpKToodC5tYXQ0LnNjYWxlKGEsYSxbMSwtMSwxXSksdC5tYXQ0LnRyYW5zbGF0ZShhLGEsWy0xLC0xLDBdKSx0Lm1hdDQuc2NhbGUoYSxhLFsyL28ud2lkdGgsMi9vLmhlaWdodCwxXSkpLGF9ZnVuY3Rpb24gbWUoZSxpKXt2YXIgbj1bZS54LGUueSwwLDFdO0llKG4sbixpKTt2YXIgbz1uWzNdO3JldHVybntwb2ludDpuZXcgdC5kZWZhdWx0JDEoblswXS9vLG5bMV0vbyksc2lnbmVkRGlzdGFuY2VGcm9tQ2FtZXJhOm99fWZ1bmN0aW9uIF9lKHQsZSl7dmFyIGk9dFswXS90WzNdLG49dFsxXS90WzNdO3JldHVybiBpPj0tZVswXSYmaTw9ZVswXSYmbj49LWVbMV0mJm48PWVbMV19ZnVuY3Rpb24gZ2UoZSxpLG4sbyxyLGEscyxsKXt2YXIgYz1vP2UudGV4dFNpemVEYXRhOmUuaWNvblNpemVEYXRhLHU9dC5ldmFsdWF0ZVNpemVGb3Jab29tKGMsbi50cmFuc2Zvcm0uem9vbSxwZS5wcm9wZXJ0aWVzW28/XCJ0ZXh0LXNpemVcIjpcImljb24tc2l6ZVwiXSksaD1bMjU2L24ud2lkdGgqMisxLDI1Ni9uLmhlaWdodCoyKzFdLHA9bz9lLnRleHQuZHluYW1pY0xheW91dFZlcnRleEFycmF5OmUuaWNvbi5keW5hbWljTGF5b3V0VmVydGV4QXJyYXk7cC5jbGVhcigpO2Zvcih2YXIgZD1lLmxpbmVWZXJ0ZXhBcnJheSxmPW8/ZS50ZXh0LnBsYWNlZFN5bWJvbEFycmF5OmUuaWNvbi5wbGFjZWRTeW1ib2xBcnJheSxtPW4udHJhbnNmb3JtLndpZHRoL24udHJhbnNmb3JtLmhlaWdodCxfPSExLGc9MDtnPGYubGVuZ3RoO2crKyl7dmFyIHY9Zi5nZXQoZyk7aWYodi5oaWRkZW58fHYud3JpdGluZ01vZGU9PT10LldyaXRpbmdNb2RlLnZlcnRpY2FsJiYhXylUZSh2Lm51bUdseXBocyxwKTtlbHNle189ITE7dmFyIHk9W3YuYW5jaG9yWCx2LmFuY2hvclksMCwxXTtpZih0LnZlYzQudHJhbnNmb3JtTWF0NCh5LHksaSksX2UoeSxoKSl7dmFyIHg9LjUreVszXS9uLnRyYW5zZm9ybS5jYW1lcmFUb0NlbnRlckRpc3RhbmNlKi41LGI9dC5ldmFsdWF0ZVNpemVGb3JGZWF0dXJlKGMsdSx2KSx3PXM/Yip4OmIveCxFPW5ldyB0LmRlZmF1bHQkMSh2LmFuY2hvclgsdi5hbmNob3JZKSxUPW1lKEUscikucG9pbnQsST17fSxDPXhlKHYsdywhMSxsLGkscixhLGUuZ2x5cGhPZmZzZXRBcnJheSxkLHAsVCxFLEksbSk7Xz1DLnVzZVZlcnRpY2FsLChDLm5vdEVub3VnaFJvb218fF98fEMubmVlZHNGbGlwcGluZyYmeGUodix3LCEwLGwsaSxyLGEsZS5nbHlwaE9mZnNldEFycmF5LGQscCxULEUsSSxtKS5ub3RFbm91Z2hSb29tKSYmVGUodi5udW1HbHlwaHMscCk7fWVsc2UgVGUodi5udW1HbHlwaHMscCk7fX1vP2UudGV4dC5keW5hbWljTGF5b3V0VmVydGV4QnVmZmVyLnVwZGF0ZURhdGEocCk6ZS5pY29uLmR5bmFtaWNMYXlvdXRWZXJ0ZXhCdWZmZXIudXBkYXRlRGF0YShwKTt9ZnVuY3Rpb24gdmUodCxlLGksbixvLHIsYSxzLGwsYyx1LGgpe3ZhciBwPXMuZ2x5cGhTdGFydEluZGV4K3MubnVtR2x5cGhzLGQ9cy5saW5lU3RhcnRJbmRleCxmPXMubGluZVN0YXJ0SW5kZXgrcy5saW5lTGVuZ3RoLG09ZS5nZXRvZmZzZXRYKHMuZ2x5cGhTdGFydEluZGV4KSxfPWUuZ2V0b2Zmc2V0WChwLTEpLGc9d2UodCptLGksbixvLHIsYSxzLnNlZ21lbnQsZCxmLGwsYyx1LGgpO2lmKCFnKXJldHVybiBudWxsO3ZhciB2PXdlKHQqXyxpLG4sbyxyLGEscy5zZWdtZW50LGQsZixsLGMsdSxoKTtyZXR1cm4gdj97Zmlyc3Q6ZyxsYXN0OnZ9Om51bGx9ZnVuY3Rpb24geWUoZSxpLG4sbyl7aWYoZT09PXQuV3JpdGluZ01vZGUuaG9yaXpvbnRhbCYmTWF0aC5hYnMobi55LWkueSk+TWF0aC5hYnMobi54LWkueCkqbylyZXR1cm57dXNlVmVydGljYWw6ITB9O3JldHVybihlPT09dC5Xcml0aW5nTW9kZS52ZXJ0aWNhbD9pLnk8bi55OmkueD5uLngpP3tuZWVkc0ZsaXBwaW5nOiEwfTpudWxsfWZ1bmN0aW9uIHhlKGUsaSxuLG8scixhLHMsbCxjLHUsaCxwLGQsZil7dmFyIG0sXz1pLzI0LGc9ZS5saW5lT2Zmc2V0WCppLHY9ZS5saW5lT2Zmc2V0WSppO2lmKGUubnVtR2x5cGhzPjEpe3ZhciB5PWUuZ2x5cGhTdGFydEluZGV4K2UubnVtR2x5cGhzLHg9ZS5saW5lU3RhcnRJbmRleCxiPWUubGluZVN0YXJ0SW5kZXgrZS5saW5lTGVuZ3RoLHc9dmUoXyxsLGcsdixuLGgscCxlLGMsYSxkLCExKTtpZighdylyZXR1cm57bm90RW5vdWdoUm9vbTohMH07dmFyIEU9bWUody5maXJzdC5wb2ludCxzKS5wb2ludCxUPW1lKHcubGFzdC5wb2ludCxzKS5wb2ludDtpZihvJiYhbil7dmFyIEk9eWUoZS53cml0aW5nTW9kZSxFLFQsZik7aWYoSSlyZXR1cm4gSX1tPVt3LmZpcnN0XTtmb3IodmFyIEM9ZS5nbHlwaFN0YXJ0SW5kZXgrMTtDPHktMTtDKyspbS5wdXNoKHdlKF8qbC5nZXRvZmZzZXRYKEMpLGcsdixuLGgscCxlLnNlZ21lbnQseCxiLGMsYSxkLCExKSk7bS5wdXNoKHcubGFzdCk7fWVsc2V7aWYobyYmIW4pe3ZhciBTPW1lKHAscikucG9pbnQsej1lLmxpbmVTdGFydEluZGV4K2Uuc2VnbWVudCsxLEE9bmV3IHQuZGVmYXVsdCQxKGMuZ2V0eCh6KSxjLmdldHkoeikpLFI9bWUoQSxyKSxEPVIuc2lnbmVkRGlzdGFuY2VGcm9tQ2FtZXJhPjA/Ui5wb2ludDpiZShwLEEsUywxLHIpLE09eWUoZS53cml0aW5nTW9kZSxTLEQsZik7aWYoTSlyZXR1cm4gTX12YXIgTD13ZShfKmwuZ2V0b2Zmc2V0WChlLmdseXBoU3RhcnRJbmRleCksZyx2LG4saCxwLGUuc2VnbWVudCxlLmxpbmVTdGFydEluZGV4LGUubGluZVN0YXJ0SW5kZXgrZS5saW5lTGVuZ3RoLGMsYSxkLCExKTtpZighTClyZXR1cm57bm90RW5vdWdoUm9vbTohMH07bT1bTF07fWZvcih2YXIgUD0wLGs9bTtQPGsubGVuZ3RoO1ArPTEpe3ZhciBCPWtbUF07dC5hZGREeW5hbWljQXR0cmlidXRlcyh1LEIucG9pbnQsQi5hbmdsZSk7fXJldHVybnt9fWZ1bmN0aW9uIGJlKHQsZSxpLG4sbyl7dmFyIHI9bWUodC5hZGQodC5zdWIoZSkuX3VuaXQoKSksbykucG9pbnQsYT1pLnN1YihyKTtyZXR1cm4gaS5hZGQoYS5fbXVsdChuL2EubWFnKCkpKX1mdW5jdGlvbiB3ZShlLGksbixvLHIsYSxzLGwsYyx1LGgscCxkKXt2YXIgZj1vP2UtaTplK2ksbT1mPjA/MTotMSxfPTA7byYmKG0qPS0xLF89TWF0aC5QSSksbTwwJiYoXys9TWF0aC5QSSk7Zm9yKHZhciBnPW0+MD9sK3M6bCtzKzEsdj1nLHk9cix4PXIsYj0wLHc9MCxFPU1hdGguYWJzKGYpO2Irdzw9RTspe2lmKChnKz1tKTxsfHxnPj1jKXJldHVybiBudWxsO2lmKHg9eSx2b2lkIDA9PT0oeT1wW2ddKSl7dmFyIFQ9bmV3IHQuZGVmYXVsdCQxKHUuZ2V0eChnKSx1LmdldHkoZykpLEk9bWUoVCxoKTtpZihJLnNpZ25lZERpc3RhbmNlRnJvbUNhbWVyYT4wKXk9cFtnXT1JLnBvaW50O2Vsc2V7dmFyIEM9Zy1tO3k9YmUoMD09PWI/YTpuZXcgdC5kZWZhdWx0JDEodS5nZXR4KEMpLHUuZ2V0eShDKSksVCx4LEUtYisxLGgpO319Yis9dyx3PXguZGlzdCh5KTt9dmFyIFM9KEUtYikvdyx6PXkuc3ViKHgpLEE9ei5tdWx0KFMpLl9hZGQoeCk7cmV0dXJuIEEuX2FkZCh6Ll91bml0KCkuX3BlcnAoKS5fbXVsdChuKm0pKSx7cG9pbnQ6QSxhbmdsZTpfK01hdGguYXRhbjIoeS55LXgueSx5LngteC54KSx0aWxlRGlzdGFuY2U6ZD97cHJldlRpbGVEaXN0YW5jZTpnLW09PT12PzA6dS5nZXR0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcihnLW0pLGxhc3RTZWdtZW50Vmlld3BvcnREaXN0YW5jZTpFLWJ9Om51bGx9fXZhciBFZT1uZXcgRmxvYXQzMkFycmF5KFstMS8wLC0xLzAsMCwtMS8wLC0xLzAsMCwtMS8wLC0xLzAsMCwtMS8wLC0xLzAsMF0pO2Z1bmN0aW9uIFRlKHQsZSl7Zm9yKHZhciBpPTA7aTx0O2krKyl7dmFyIG49ZS5sZW5ndGg7ZS5yZXNpemUobis0KSxlLmZsb2F0MzIuc2V0KEVlLDMqbik7fX1mdW5jdGlvbiBJZSh0LGUsaSl7dmFyIG49ZVswXSxvPWVbMV07cmV0dXJuIHRbMF09aVswXSpuK2lbNF0qbytpWzEyXSx0WzFdPWlbMV0qbitpWzVdKm8raVsxM10sdFszXT1pWzNdKm4raVs3XSpvK2lbMTVdLHR9dC5kZWZhdWx0JDIwLm1hdDQ7dmFyIENlPWZ1bmN0aW9uKHQsZSxpKXt2b2lkIDA9PT1lJiYoZT1uZXcgaGUodC53aWR0aCsyMDAsdC5oZWlnaHQrMjAwLDI1KSksdm9pZCAwPT09aSYmKGk9bmV3IGhlKHQud2lkdGgrMjAwLHQuaGVpZ2h0KzIwMCwyNSkpLHRoaXMudHJhbnNmb3JtPXQsdGhpcy5ncmlkPWUsdGhpcy5pZ25vcmVkR3JpZD1pLHRoaXMucGl0Y2hmYWN0b3I9TWF0aC5jb3ModC5fcGl0Y2gpKnQuY2FtZXJhVG9DZW50ZXJEaXN0YW5jZSx0aGlzLnNjcmVlblJpZ2h0Qm91bmRhcnk9dC53aWR0aCsxMDAsdGhpcy5zY3JlZW5Cb3R0b21Cb3VuZGFyeT10LmhlaWdodCsxMDA7fTtmdW5jdGlvbiBTZSh0LGUsaSl7dFtlKzRdPWk/MTowO31mdW5jdGlvbiB6ZShlLGksbil7cmV0dXJuIGkqKHQuZGVmYXVsdCQ4LyhlLnRpbGVTaXplKk1hdGgucG93KDIsbi1lLnRpbGVJRC5vdmVyc2NhbGVkWikpKX1DZS5wcm90b3R5cGUucGxhY2VDb2xsaXNpb25Cb3g9ZnVuY3Rpb24odCxlLGksbil7dmFyIG89dGhpcy5wcm9qZWN0QW5kR2V0UGVyc3BlY3RpdmVSYXRpbyhuLHQuYW5jaG9yUG9pbnRYLHQuYW5jaG9yUG9pbnRZKSxyPWkqby5wZXJzcGVjdGl2ZVJhdGlvLGE9dC54MSpyK28ucG9pbnQueCxzPXQueTEqcitvLnBvaW50LnksbD10LngyKnIrby5wb2ludC54LGM9dC55MipyK28ucG9pbnQueTtyZXR1cm4hZSYmdGhpcy5ncmlkLmhpdFRlc3QoYSxzLGwsYyk/e2JveDpbXSxvZmZzY3JlZW46ITF9Ontib3g6W2EscyxsLGNdLG9mZnNjcmVlbjp0aGlzLmlzT2Zmc2NyZWVuKGEscyxsLGMpfX0sQ2UucHJvdG90eXBlLmFwcHJveGltYXRlVGlsZURpc3RhbmNlPWZ1bmN0aW9uKHQsZSxpLG4sbyl7dmFyIHI9bz8xOm4vdGhpcy5waXRjaGZhY3RvcixhPXQubGFzdFNlZ21lbnRWaWV3cG9ydERpc3RhbmNlKmk7cmV0dXJuIHQucHJldlRpbGVEaXN0YW5jZSthKyhyLTEpKmEqTWF0aC5hYnMoTWF0aC5zaW4oZSkpfSxDZS5wcm90b3R5cGUucGxhY2VDb2xsaXNpb25DaXJjbGVzPWZ1bmN0aW9uKGUsaSxuLG8scixhLHMsbCxjLHUsaCxwLGQpe3ZhciBmPVtdLG09dGhpcy5wcm9qZWN0QW5jaG9yKHUsYS5hbmNob3JYLGEuYW5jaG9yWSksXz1jLzI0LGc9YS5saW5lT2Zmc2V0WCpjLHY9YS5saW5lT2Zmc2V0WSpjLHk9bmV3IHQuZGVmYXVsdCQxKGEuYW5jaG9yWCxhLmFuY2hvclkpLHg9dmUoXyxsLGcsdiwhMSxtZSh5LGgpLnBvaW50LHksYSxzLGgse30sITApLGI9ITEsdz0hMCxFPW0ucGVyc3BlY3RpdmVSYXRpbypvLFQ9MS8obypuKSxJPTAsQz0wO3gmJihJPXRoaXMuYXBwcm94aW1hdGVUaWxlRGlzdGFuY2UoeC5maXJzdC50aWxlRGlzdGFuY2UseC5maXJzdC5hbmdsZSxULG0uY2FtZXJhRGlzdGFuY2UsZCksQz10aGlzLmFwcHJveGltYXRlVGlsZURpc3RhbmNlKHgubGFzdC50aWxlRGlzdGFuY2UseC5sYXN0LmFuZ2xlLFQsbS5jYW1lcmFEaXN0YW5jZSxkKSk7Zm9yKHZhciBTPTA7UzxlLmxlbmd0aDtTKz01KXt2YXIgej1lW1NdLEE9ZVtTKzFdLFI9ZVtTKzJdLEQ9ZVtTKzNdO2lmKCF4fHxEPC1JfHxEPkMpU2UoZSxTLCExKTtlbHNle3ZhciBNPXRoaXMucHJvamVjdFBvaW50KHUseixBKSxMPVIqRTtpZihmLmxlbmd0aD4wKXt2YXIgUD1NLngtZltmLmxlbmd0aC00XSxrPU0ueS1mW2YubGVuZ3RoLTNdO2lmKEwqTCoyPlAqUCtrKmspaWYoUys4PGUubGVuZ3RoKXt2YXIgQj1lW1MrOF07aWYoQj4tSSYmQjxDKXtTZShlLFMsITEpO2NvbnRpbnVlfX19dmFyIE89Uy81O2lmKGYucHVzaChNLngsTS55LEwsTyksU2UoZSxTLCEwKSx3PXcmJnRoaXMuaXNPZmZzY3JlZW4oTS54LUwsTS55LUwsTS54K0wsTS55K0wpLCFpJiZ0aGlzLmdyaWQuaGl0VGVzdENpcmNsZShNLngsTS55LEwpKXtpZighcClyZXR1cm57Y2lyY2xlczpbXSxvZmZzY3JlZW46ITF9O2I9ITA7fX19cmV0dXJue2NpcmNsZXM6Yj9bXTpmLG9mZnNjcmVlbjp3fX0sQ2UucHJvdG90eXBlLnF1ZXJ5UmVuZGVyZWRTeW1ib2xzPWZ1bmN0aW9uKGUpe2lmKDA9PT1lLmxlbmd0aHx8MD09PXRoaXMuZ3JpZC5rZXlzTGVuZ3RoKCkmJjA9PT10aGlzLmlnbm9yZWRHcmlkLmtleXNMZW5ndGgoKSlyZXR1cm57fTtmb3IodmFyIGk9W10sbj0xLzAsbz0xLzAscj0tMS8wLGE9LTEvMCxzPTAsbD1lO3M8bC5sZW5ndGg7cys9MSl7dmFyIGM9bFtzXSx1PW5ldyB0LmRlZmF1bHQkMShjLngrMTAwLGMueSsxMDApO249TWF0aC5taW4obix1LngpLG89TWF0aC5taW4obyx1LnkpLHI9TWF0aC5tYXgocix1LngpLGE9TWF0aC5tYXgoYSx1LnkpLGkucHVzaCh1KTt9Zm9yKHZhciBoPXt9LHA9e30sZD0wLGY9dGhpcy5ncmlkLnF1ZXJ5KG4sbyxyLGEpLmNvbmNhdCh0aGlzLmlnbm9yZWRHcmlkLnF1ZXJ5KG4sbyxyLGEpKTtkPGYubGVuZ3RoO2QrPTEpe3ZhciBtPWZbZF0sXz1tLmtleTtpZih2b2lkIDA9PT1oW18uYnVja2V0SW5zdGFuY2VJZF0mJihoW18uYnVja2V0SW5zdGFuY2VJZF09e30pLCFoW18uYnVja2V0SW5zdGFuY2VJZF1bXy5mZWF0dXJlSW5kZXhdKXt2YXIgZz1bbmV3IHQuZGVmYXVsdCQxKG0ueDEsbS55MSksbmV3IHQuZGVmYXVsdCQxKG0ueDIsbS55MSksbmV3IHQuZGVmYXVsdCQxKG0ueDIsbS55MiksbmV3IHQuZGVmYXVsdCQxKG0ueDEsbS55MildO3QucG9seWdvbkludGVyc2VjdHNQb2x5Z29uKGksZykmJihoW18uYnVja2V0SW5zdGFuY2VJZF1bXy5mZWF0dXJlSW5kZXhdPSEwLHZvaWQgMD09PXBbXy5idWNrZXRJbnN0YW5jZUlkXSYmKHBbXy5idWNrZXRJbnN0YW5jZUlkXT1bXSkscFtfLmJ1Y2tldEluc3RhbmNlSWRdLnB1c2goXy5mZWF0dXJlSW5kZXgpKTt9fXJldHVybiBwfSxDZS5wcm90b3R5cGUuaW5zZXJ0Q29sbGlzaW9uQm94PWZ1bmN0aW9uKHQsZSxpLG4pe3ZhciBvPXtidWNrZXRJbnN0YW5jZUlkOmksZmVhdHVyZUluZGV4Om59OyhlP3RoaXMuaWdub3JlZEdyaWQ6dGhpcy5ncmlkKS5pbnNlcnQobyx0WzBdLHRbMV0sdFsyXSx0WzNdKTt9LENlLnByb3RvdHlwZS5pbnNlcnRDb2xsaXNpb25DaXJjbGVzPWZ1bmN0aW9uKHQsZSxpLG4pe2Zvcih2YXIgbz1lP3RoaXMuaWdub3JlZEdyaWQ6dGhpcy5ncmlkLHI9e2J1Y2tldEluc3RhbmNlSWQ6aSxmZWF0dXJlSW5kZXg6bn0sYT0wO2E8dC5sZW5ndGg7YSs9NClvLmluc2VydENpcmNsZShyLHRbYV0sdFthKzFdLHRbYSsyXSk7fSxDZS5wcm90b3R5cGUucHJvamVjdEFuY2hvcj1mdW5jdGlvbih0LGUsaSl7dmFyIG49W2UsaSwwLDFdO3JldHVybiBJZShuLG4sdCkse3BlcnNwZWN0aXZlUmF0aW86LjUrdGhpcy50cmFuc2Zvcm0uY2FtZXJhVG9DZW50ZXJEaXN0YW5jZS9uWzNdKi41LGNhbWVyYURpc3RhbmNlOm5bM119fSxDZS5wcm90b3R5cGUucHJvamVjdFBvaW50PWZ1bmN0aW9uKGUsaSxuKXt2YXIgbz1baSxuLDAsMV07cmV0dXJuIEllKG8sbyxlKSxuZXcgdC5kZWZhdWx0JDEoKG9bMF0vb1szXSsxKS8yKnRoaXMudHJhbnNmb3JtLndpZHRoKzEwMCwoLW9bMV0vb1szXSsxKS8yKnRoaXMudHJhbnNmb3JtLmhlaWdodCsxMDApfSxDZS5wcm90b3R5cGUucHJvamVjdEFuZEdldFBlcnNwZWN0aXZlUmF0aW89ZnVuY3Rpb24oZSxpLG4pe3ZhciBvPVtpLG4sMCwxXTtyZXR1cm4gSWUobyxvLGUpLHtwb2ludDpuZXcgdC5kZWZhdWx0JDEoKG9bMF0vb1szXSsxKS8yKnRoaXMudHJhbnNmb3JtLndpZHRoKzEwMCwoLW9bMV0vb1szXSsxKS8yKnRoaXMudHJhbnNmb3JtLmhlaWdodCsxMDApLHBlcnNwZWN0aXZlUmF0aW86LjUrdGhpcy50cmFuc2Zvcm0uY2FtZXJhVG9DZW50ZXJEaXN0YW5jZS9vWzNdKi41fX0sQ2UucHJvdG90eXBlLmlzT2Zmc2NyZWVuPWZ1bmN0aW9uKHQsZSxpLG4pe3JldHVybiBpPDEwMHx8dD49dGhpcy5zY3JlZW5SaWdodEJvdW5kYXJ5fHxuPDEwMHx8ZT50aGlzLnNjcmVlbkJvdHRvbUJvdW5kYXJ5fTt2YXIgQWU9dC5kZWZhdWx0JDE5LmxheW91dCxSZT1mdW5jdGlvbih0LGUsaSxuKXt0aGlzLm9wYWNpdHk9dD9NYXRoLm1heCgwLE1hdGgubWluKDEsdC5vcGFjaXR5Kyh0LnBsYWNlZD9lOi1lKSkpOm4mJmk/MTowLHRoaXMucGxhY2VkPWk7fTtSZS5wcm90b3R5cGUuaXNIaWRkZW49ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMub3BhY2l0eSYmIXRoaXMucGxhY2VkfTt2YXIgRGU9ZnVuY3Rpb24odCxlLGksbixvKXt0aGlzLnRleHQ9bmV3IFJlKHQ/dC50ZXh0Om51bGwsZSxpLG8pLHRoaXMuaWNvbj1uZXcgUmUodD90Lmljb246bnVsbCxlLG4sbyk7fTtEZS5wcm90b3R5cGUuaXNIaWRkZW49ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50ZXh0LmlzSGlkZGVuKCkmJnRoaXMuaWNvbi5pc0hpZGRlbigpfTt2YXIgTWU9ZnVuY3Rpb24odCxlLGkpe3RoaXMudGV4dD10LHRoaXMuaWNvbj1lLHRoaXMuc2tpcEZhZGU9aTt9LExlPWZ1bmN0aW9uKHQsZSl7dGhpcy50cmFuc2Zvcm09dC5jbG9uZSgpLHRoaXMuY29sbGlzaW9uSW5kZXg9bmV3IENlKHRoaXMudHJhbnNmb3JtKSx0aGlzLnBsYWNlbWVudHM9e30sdGhpcy5vcGFjaXRpZXM9e30sdGhpcy5zdGFsZT0hMSx0aGlzLmZhZGVEdXJhdGlvbj1lLHRoaXMucmV0YWluZWRRdWVyeURhdGE9e307fTtmdW5jdGlvbiBQZSh0LGUsaSl7dC5lbXBsYWNlQmFjayhlPzE6MCxpPzE6MCksdC5lbXBsYWNlQmFjayhlPzE6MCxpPzE6MCksdC5lbXBsYWNlQmFjayhlPzE6MCxpPzE6MCksdC5lbXBsYWNlQmFjayhlPzE6MCxpPzE6MCk7fUxlLnByb3RvdHlwZS5wbGFjZUxheWVyVGlsZT1mdW5jdGlvbihlLGksbixvKXt2YXIgcj1pLmdldEJ1Y2tldChlKSxhPWkubGF0ZXN0RmVhdHVyZUluZGV4O2lmKHImJmEmJmUuaWQ9PT1yLmxheWVySWRzWzBdKXt2YXIgcz1pLmNvbGxpc2lvbkJveEFycmF5LGw9ci5sYXllcnNbMF0ubGF5b3V0LGM9TWF0aC5wb3coMix0aGlzLnRyYW5zZm9ybS56b29tLWkudGlsZUlELm92ZXJzY2FsZWRaKSx1PWkudGlsZVNpemUvdC5kZWZhdWx0JDgsaD10aGlzLnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgoaS50aWxlSUQudG9VbndyYXBwZWQoKSkscD1kZShoLFwibWFwXCI9PT1sLmdldChcInRleHQtcGl0Y2gtYWxpZ25tZW50XCIpLFwibWFwXCI9PT1sLmdldChcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCIpLHRoaXMudHJhbnNmb3JtLHplKGksMSx0aGlzLnRyYW5zZm9ybS56b29tKSksZD1kZShoLFwibWFwXCI9PT1sLmdldChcImljb24tcGl0Y2gtYWxpZ25tZW50XCIpLFwibWFwXCI9PT1sLmdldChcImljb24tcm90YXRpb24tYWxpZ25tZW50XCIpLHRoaXMudHJhbnNmb3JtLHplKGksMSx0aGlzLnRyYW5zZm9ybS56b29tKSk7dGhpcy5yZXRhaW5lZFF1ZXJ5RGF0YVtyLmJ1Y2tldEluc3RhbmNlSWRdPW5ldyBmdW5jdGlvbih0LGUsaSxuLG8pe3RoaXMuYnVja2V0SW5zdGFuY2VJZD10LHRoaXMuZmVhdHVyZUluZGV4PWUsdGhpcy5zb3VyY2VMYXllckluZGV4PWksdGhpcy5idWNrZXRJbmRleD1uLHRoaXMudGlsZUlEPW87fShyLmJ1Y2tldEluc3RhbmNlSWQsYSxyLnNvdXJjZUxheWVySW5kZXgsci5pbmRleCxpLnRpbGVJRCksdGhpcy5wbGFjZUxheWVyQnVja2V0KHIsaCxwLGQsYyx1LG4sbyxzKTt9fSxMZS5wcm90b3R5cGUucGxhY2VMYXllckJ1Y2tldD1mdW5jdGlvbihlLGksbixvLHIsYSxzLGwsYyl7Zm9yKHZhciB1PWUubGF5ZXJzWzBdLmxheW91dCxoPXQuZXZhbHVhdGVTaXplRm9yWm9vbShlLnRleHRTaXplRGF0YSx0aGlzLnRyYW5zZm9ybS56b29tLEFlLnByb3BlcnRpZXNbXCJ0ZXh0LXNpemVcIl0pLHA9IWUuaGFzVGV4dERhdGEoKXx8dS5nZXQoXCJ0ZXh0LW9wdGlvbmFsXCIpLGQ9IWUuaGFzSWNvbkRhdGEoKXx8dS5nZXQoXCJpY29uLW9wdGlvbmFsXCIpLGY9MCxtPWUuc3ltYm9sSW5zdGFuY2VzO2Y8bS5sZW5ndGg7Zis9MSl7dmFyIF89bVtmXTtpZighbFtfLmNyb3NzVGlsZUlEXSl7dmFyIGc9dm9pZCAwIT09Xy5mZWF0dXJlLnRleHQsdj12b2lkIDAhPT1fLmZlYXR1cmUuaWNvbix5PSEwLHg9bnVsbCxiPW51bGwsdz1udWxsLEU9MCxUPTA7Xy5jb2xsaXNpb25BcnJheXN8fChfLmNvbGxpc2lvbkFycmF5cz1lLmRlc2VyaWFsaXplQ29sbGlzaW9uQm94ZXMoYyxfLnRleHRCb3hTdGFydEluZGV4LF8udGV4dEJveEVuZEluZGV4LF8uaWNvbkJveFN0YXJ0SW5kZXgsXy5pY29uQm94RW5kSW5kZXgpKSxfLmNvbGxpc2lvbkFycmF5cy50ZXh0RmVhdHVyZUluZGV4JiYoRT1fLmNvbGxpc2lvbkFycmF5cy50ZXh0RmVhdHVyZUluZGV4KSxfLmNvbGxpc2lvbkFycmF5cy50ZXh0Qm94JiYoZz0oeD10aGlzLmNvbGxpc2lvbkluZGV4LnBsYWNlQ29sbGlzaW9uQm94KF8uY29sbGlzaW9uQXJyYXlzLnRleHRCb3gsdS5nZXQoXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIiksYSxpKSkuYm94Lmxlbmd0aD4wLHk9eSYmeC5vZmZzY3JlZW4pO3ZhciBJPV8uY29sbGlzaW9uQXJyYXlzLnRleHRDaXJjbGVzO2lmKEkpe3ZhciBDPWUudGV4dC5wbGFjZWRTeW1ib2xBcnJheS5nZXQoXy5wbGFjZWRUZXh0U3ltYm9sSW5kaWNlc1swXSksUz10LmV2YWx1YXRlU2l6ZUZvckZlYXR1cmUoZS50ZXh0U2l6ZURhdGEsaCxDKTtiPXRoaXMuY29sbGlzaW9uSW5kZXgucGxhY2VDb2xsaXNpb25DaXJjbGVzKEksdS5nZXQoXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIikscixhLF8ua2V5LEMsZS5saW5lVmVydGV4QXJyYXksZS5nbHlwaE9mZnNldEFycmF5LFMsaSxuLHMsXCJtYXBcIj09PXUuZ2V0KFwidGV4dC1waXRjaC1hbGlnbm1lbnRcIikpLGc9dS5nZXQoXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIil8fGIuY2lyY2xlcy5sZW5ndGg+MCx5PXkmJmIub2Zmc2NyZWVuO31fLmNvbGxpc2lvbkFycmF5cy5pY29uRmVhdHVyZUluZGV4JiYoVD1fLmNvbGxpc2lvbkFycmF5cy5pY29uRmVhdHVyZUluZGV4KSxfLmNvbGxpc2lvbkFycmF5cy5pY29uQm94JiYodj0odz10aGlzLmNvbGxpc2lvbkluZGV4LnBsYWNlQ29sbGlzaW9uQm94KF8uY29sbGlzaW9uQXJyYXlzLmljb25Cb3gsdS5nZXQoXCJpY29uLWFsbG93LW92ZXJsYXBcIiksYSxpKSkuYm94Lmxlbmd0aD4wLHk9eSYmdy5vZmZzY3JlZW4pLHB8fGQ/ZD9wfHwodj12JiZnKTpnPXYmJmc6dj1nPXYmJmcsZyYmeCYmdGhpcy5jb2xsaXNpb25JbmRleC5pbnNlcnRDb2xsaXNpb25Cb3goeC5ib3gsdS5nZXQoXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIiksZS5idWNrZXRJbnN0YW5jZUlkLEUpLHYmJncmJnRoaXMuY29sbGlzaW9uSW5kZXguaW5zZXJ0Q29sbGlzaW9uQm94KHcuYm94LHUuZ2V0KFwiaWNvbi1pZ25vcmUtcGxhY2VtZW50XCIpLGUuYnVja2V0SW5zdGFuY2VJZCxUKSxnJiZiJiZ0aGlzLmNvbGxpc2lvbkluZGV4Lmluc2VydENvbGxpc2lvbkNpcmNsZXMoYi5jaXJjbGVzLHUuZ2V0KFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCIpLGUuYnVja2V0SW5zdGFuY2VJZCxFKSx0aGlzLnBsYWNlbWVudHNbXy5jcm9zc1RpbGVJRF09bmV3IE1lKGcsdix5fHxlLmp1c3RSZWxvYWRlZCksbFtfLmNyb3NzVGlsZUlEXT0hMDt9fWUuanVzdFJlbG9hZGVkPSExO30sTGUucHJvdG90eXBlLmNvbW1pdD1mdW5jdGlvbih0LGUpe3RoaXMuY29tbWl0VGltZT1lO3ZhciBpPSExLG49dCYmMCE9PXRoaXMuZmFkZUR1cmF0aW9uPyh0aGlzLmNvbW1pdFRpbWUtdC5jb21taXRUaW1lKS90aGlzLmZhZGVEdXJhdGlvbjoxLG89dD90Lm9wYWNpdGllczp7fTtmb3IodmFyIHIgaW4gdGhpcy5wbGFjZW1lbnRzKXt2YXIgYT10aGlzLnBsYWNlbWVudHNbcl0scz1vW3JdO3M/KHRoaXMub3BhY2l0aWVzW3JdPW5ldyBEZShzLG4sYS50ZXh0LGEuaWNvbiksaT1pfHxhLnRleHQhPT1zLnRleHQucGxhY2VkfHxhLmljb24hPT1zLmljb24ucGxhY2VkKToodGhpcy5vcGFjaXRpZXNbcl09bmV3IERlKG51bGwsbixhLnRleHQsYS5pY29uLGEuc2tpcEZhZGUpLGk9aXx8YS50ZXh0fHxhLmljb24pO31mb3IodmFyIGwgaW4gbyl7dmFyIGM9b1tsXTtpZighdGhpcy5vcGFjaXRpZXNbbF0pe3ZhciB1PW5ldyBEZShjLG4sITEsITEpO3UuaXNIaWRkZW4oKXx8KHRoaXMub3BhY2l0aWVzW2xdPXUsaT1pfHxjLnRleHQucGxhY2VkfHxjLmljb24ucGxhY2VkKTt9fWk/dGhpcy5sYXN0UGxhY2VtZW50Q2hhbmdlVGltZT1lOlwibnVtYmVyXCIhPXR5cGVvZiB0aGlzLmxhc3RQbGFjZW1lbnRDaGFuZ2VUaW1lJiYodGhpcy5sYXN0UGxhY2VtZW50Q2hhbmdlVGltZT10P3QubGFzdFBsYWNlbWVudENoYW5nZVRpbWU6ZSk7fSxMZS5wcm90b3R5cGUudXBkYXRlTGF5ZXJPcGFjaXRpZXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIGk9e30sbj0wLG89ZTtuPG8ubGVuZ3RoO24rPTEpe3ZhciByPW9bbl0sYT1yLmdldEJ1Y2tldCh0KTthJiZyLmxhdGVzdEZlYXR1cmVJbmRleCYmdC5pZD09PWEubGF5ZXJJZHNbMF0mJnRoaXMudXBkYXRlQnVja2V0T3BhY2l0aWVzKGEsaSxyLmNvbGxpc2lvbkJveEFycmF5KTt9fSxMZS5wcm90b3R5cGUudXBkYXRlQnVja2V0T3BhY2l0aWVzPWZ1bmN0aW9uKHQsZSxpKXt0Lmhhc1RleHREYXRhKCkmJnQudGV4dC5vcGFjaXR5VmVydGV4QXJyYXkuY2xlYXIoKSx0Lmhhc0ljb25EYXRhKCkmJnQuaWNvbi5vcGFjaXR5VmVydGV4QXJyYXkuY2xlYXIoKSx0Lmhhc0NvbGxpc2lvbkJveERhdGEoKSYmdC5jb2xsaXNpb25Cb3guY29sbGlzaW9uVmVydGV4QXJyYXkuY2xlYXIoKSx0Lmhhc0NvbGxpc2lvbkNpcmNsZURhdGEoKSYmdC5jb2xsaXNpb25DaXJjbGUuY29sbGlzaW9uVmVydGV4QXJyYXkuY2xlYXIoKTtmb3IodmFyIG49dC5sYXllcnNbMF0ubGF5b3V0LG89bmV3IERlKG51bGwsMCwhMSwhMSwhMCkscj1uZXcgRGUobnVsbCwwLG4uZ2V0KFwidGV4dC1hbGxvdy1vdmVybGFwXCIpLG4uZ2V0KFwiaWNvbi1hbGxvdy1vdmVybGFwXCIpLCEwKSxhPTA7YTx0LnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7YSsrKXt2YXIgcz10LnN5bWJvbEluc3RhbmNlc1thXSxsPWVbcy5jcm9zc1RpbGVJRF0sYz10aGlzLm9wYWNpdGllc1tzLmNyb3NzVGlsZUlEXTtsP2M9bzpjfHwoYz1yLHRoaXMub3BhY2l0aWVzW3MuY3Jvc3NUaWxlSURdPWMpLGVbcy5jcm9zc1RpbGVJRF09ITA7dmFyIHU9cy5udW1HbHlwaFZlcnRpY2VzPjB8fHMubnVtVmVydGljYWxHbHlwaFZlcnRpY2VzPjAsaD1zLm51bUljb25WZXJ0aWNlcz4wO2lmKHUpe2Zvcih2YXIgcD1WZShjLnRleHQpLGQ9KHMubnVtR2x5cGhWZXJ0aWNlcytzLm51bVZlcnRpY2FsR2x5cGhWZXJ0aWNlcykvNCxmPTA7ZjxkO2YrKyl0LnRleHQub3BhY2l0eVZlcnRleEFycmF5LmVtcGxhY2VCYWNrKHApO2Zvcih2YXIgbT0wLF89cy5wbGFjZWRUZXh0U3ltYm9sSW5kaWNlczttPF8ubGVuZ3RoO20rPTEpe3ZhciBnPV9bbV07dC50ZXh0LnBsYWNlZFN5bWJvbEFycmF5LmdldChnKS5oaWRkZW49Yy50ZXh0LmlzSGlkZGVuKCk7fX1pZihoKXtmb3IodmFyIHY9VmUoYy5pY29uKSx5PTA7eTxzLm51bUljb25WZXJ0aWNlcy80O3krKyl0Lmljb24ub3BhY2l0eVZlcnRleEFycmF5LmVtcGxhY2VCYWNrKHYpO3QuaWNvbi5wbGFjZWRTeW1ib2xBcnJheS5nZXQoYSkuaGlkZGVuPWMuaWNvbi5pc0hpZGRlbigpO31zLmNvbGxpc2lvbkFycmF5c3x8KHMuY29sbGlzaW9uQXJyYXlzPXQuZGVzZXJpYWxpemVDb2xsaXNpb25Cb3hlcyhpLHMudGV4dEJveFN0YXJ0SW5kZXgscy50ZXh0Qm94RW5kSW5kZXgscy5pY29uQm94U3RhcnRJbmRleCxzLmljb25Cb3hFbmRJbmRleCkpO3ZhciB4PXMuY29sbGlzaW9uQXJyYXlzO2lmKHgpe3gudGV4dEJveCYmdC5oYXNDb2xsaXNpb25Cb3hEYXRhKCkmJlBlKHQuY29sbGlzaW9uQm94LmNvbGxpc2lvblZlcnRleEFycmF5LGMudGV4dC5wbGFjZWQsITEpLHguaWNvbkJveCYmdC5oYXNDb2xsaXNpb25Cb3hEYXRhKCkmJlBlKHQuY29sbGlzaW9uQm94LmNvbGxpc2lvblZlcnRleEFycmF5LGMuaWNvbi5wbGFjZWQsITEpO3ZhciBiPXgudGV4dENpcmNsZXM7aWYoYiYmdC5oYXNDb2xsaXNpb25DaXJjbGVEYXRhKCkpZm9yKHZhciB3PTA7dzxiLmxlbmd0aDt3Kz01KXt2YXIgRT1sfHwwPT09Ylt3KzRdO1BlKHQuY29sbGlzaW9uQ2lyY2xlLmNvbGxpc2lvblZlcnRleEFycmF5LGMudGV4dC5wbGFjZWQsRSk7fX19dC5zb3J0RmVhdHVyZXModGhpcy50cmFuc2Zvcm0uYW5nbGUpLHRoaXMucmV0YWluZWRRdWVyeURhdGFbdC5idWNrZXRJbnN0YW5jZUlkXSYmKHRoaXMucmV0YWluZWRRdWVyeURhdGFbdC5idWNrZXRJbnN0YW5jZUlkXS5mZWF0dXJlU29ydE9yZGVyPXQuZmVhdHVyZVNvcnRPcmRlciksdC5oYXNUZXh0RGF0YSgpJiZ0LnRleHQub3BhY2l0eVZlcnRleEJ1ZmZlciYmdC50ZXh0Lm9wYWNpdHlWZXJ0ZXhCdWZmZXIudXBkYXRlRGF0YSh0LnRleHQub3BhY2l0eVZlcnRleEFycmF5KSx0Lmhhc0ljb25EYXRhKCkmJnQuaWNvbi5vcGFjaXR5VmVydGV4QnVmZmVyJiZ0Lmljb24ub3BhY2l0eVZlcnRleEJ1ZmZlci51cGRhdGVEYXRhKHQuaWNvbi5vcGFjaXR5VmVydGV4QXJyYXkpLHQuaGFzQ29sbGlzaW9uQm94RGF0YSgpJiZ0LmNvbGxpc2lvbkJveC5jb2xsaXNpb25WZXJ0ZXhCdWZmZXImJnQuY29sbGlzaW9uQm94LmNvbGxpc2lvblZlcnRleEJ1ZmZlci51cGRhdGVEYXRhKHQuY29sbGlzaW9uQm94LmNvbGxpc2lvblZlcnRleEFycmF5KSx0Lmhhc0NvbGxpc2lvbkNpcmNsZURhdGEoKSYmdC5jb2xsaXNpb25DaXJjbGUuY29sbGlzaW9uVmVydGV4QnVmZmVyJiZ0LmNvbGxpc2lvbkNpcmNsZS5jb2xsaXNpb25WZXJ0ZXhCdWZmZXIudXBkYXRlRGF0YSh0LmNvbGxpc2lvbkNpcmNsZS5jb2xsaXNpb25WZXJ0ZXhBcnJheSk7fSxMZS5wcm90b3R5cGUuc3ltYm9sRmFkZUNoYW5nZT1mdW5jdGlvbih0KXtyZXR1cm4gMD09PXRoaXMuZmFkZUR1cmF0aW9uPzE6KHQtdGhpcy5jb21taXRUaW1lKS90aGlzLmZhZGVEdXJhdGlvbn0sTGUucHJvdG90eXBlLmhhc1RyYW5zaXRpb25zPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnN0YWxlfHx0LXRoaXMubGFzdFBsYWNlbWVudENoYW5nZVRpbWU8dGhpcy5mYWRlRHVyYXRpb259LExlLnByb3RvdHlwZS5zdGlsbFJlY2VudD1mdW5jdGlvbih0KXtyZXR1cm5cInVuZGVmaW5lZFwiIT09dGhpcy5jb21taXRUaW1lJiZ0aGlzLmNvbW1pdFRpbWUrdGhpcy5mYWRlRHVyYXRpb24+dH0sTGUucHJvdG90eXBlLnNldFN0YWxlPWZ1bmN0aW9uKCl7dGhpcy5zdGFsZT0hMDt9O3ZhciBrZT1NYXRoLnBvdygyLDI1KSxCZT1NYXRoLnBvdygyLDI0KSxPZT1NYXRoLnBvdygyLDE3KSxGZT1NYXRoLnBvdygyLDE2KSxOZT1NYXRoLnBvdygyLDkpLFVlPU1hdGgucG93KDIsOCksWmU9TWF0aC5wb3coMiwxKTtmdW5jdGlvbiBWZSh0KXtpZigwPT09dC5vcGFjaXR5JiYhdC5wbGFjZWQpcmV0dXJuIDA7aWYoMT09PXQub3BhY2l0eSYmdC5wbGFjZWQpcmV0dXJuIDQyOTQ5NjcyOTU7dmFyIGU9dC5wbGFjZWQ/MTowLGk9TWF0aC5mbG9vcigxMjcqdC5vcGFjaXR5KTtyZXR1cm4gaSprZStlKkJlK2kqT2UrZSpGZStpKk5lK2UqVWUraSpaZStlfXZhciBqZT1mdW5jdGlvbigpe3RoaXMuX2N1cnJlbnRUaWxlSW5kZXg9MCx0aGlzLl9zZWVuQ3Jvc3NUaWxlSURzPXt9O307amUucHJvdG90eXBlLmNvbnRpbnVlUGxhY2VtZW50PWZ1bmN0aW9uKHQsZSxpLG4sbyl7Zm9yKDt0aGlzLl9jdXJyZW50VGlsZUluZGV4PHQubGVuZ3RoOyl7dmFyIHI9dFt0aGlzLl9jdXJyZW50VGlsZUluZGV4XTtpZihlLnBsYWNlTGF5ZXJUaWxlKG4scixpLHRoaXMuX3NlZW5Dcm9zc1RpbGVJRHMpLHRoaXMuX2N1cnJlbnRUaWxlSW5kZXgrKyxvKCkpcmV0dXJuITB9fTt2YXIgJGU9ZnVuY3Rpb24odCxlLGksbixvKXt0aGlzLnBsYWNlbWVudD1uZXcgTGUodCxvKSx0aGlzLl9jdXJyZW50UGxhY2VtZW50SW5kZXg9ZS5sZW5ndGgtMSx0aGlzLl9mb3JjZUZ1bGxQbGFjZW1lbnQ9aSx0aGlzLl9zaG93Q29sbGlzaW9uQm94ZXM9bix0aGlzLl9kb25lPSExO307JGUucHJvdG90eXBlLmlzRG9uZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9kb25lfSwkZS5wcm90b3R5cGUuY29udGludWVQbGFjZW1lbnQ9ZnVuY3Rpb24odCxlLGkpe2Zvcih2YXIgbj10aGlzLG89ci5ub3coKSxhPWZ1bmN0aW9uKCl7dmFyIHQ9ci5ub3coKS1vO3JldHVybiFuLl9mb3JjZUZ1bGxQbGFjZW1lbnQmJnQ+Mn07dGhpcy5fY3VycmVudFBsYWNlbWVudEluZGV4Pj0wOyl7dmFyIHM9ZVt0W24uX2N1cnJlbnRQbGFjZW1lbnRJbmRleF1dLGw9bi5wbGFjZW1lbnQuY29sbGlzaW9uSW5kZXgudHJhbnNmb3JtLnpvb207aWYoXCJzeW1ib2xcIj09PXMudHlwZSYmKCFzLm1pbnpvb218fHMubWluem9vbTw9bCkmJighcy5tYXh6b29tfHxzLm1heHpvb20+bCkpe2lmKG4uX2luUHJvZ3Jlc3NMYXllcnx8KG4uX2luUHJvZ3Jlc3NMYXllcj1uZXcgamUpLG4uX2luUHJvZ3Jlc3NMYXllci5jb250aW51ZVBsYWNlbWVudChpW3Muc291cmNlXSxuLnBsYWNlbWVudCxuLl9zaG93Q29sbGlzaW9uQm94ZXMscyxhKSlyZXR1cm47ZGVsZXRlIG4uX2luUHJvZ3Jlc3NMYXllcjt9bi5fY3VycmVudFBsYWNlbWVudEluZGV4LS07fXRoaXMuX2RvbmU9ITA7fSwkZS5wcm90b3R5cGUuY29tbWl0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMucGxhY2VtZW50LmNvbW1pdCh0LGUpLHRoaXMucGxhY2VtZW50fTt2YXIgR2U9NTEyL3QuZGVmYXVsdCQ4LzIsV2U9ZnVuY3Rpb24odCxlLGkpe3RoaXMudGlsZUlEPXQsdGhpcy5pbmRleGVkU3ltYm9sSW5zdGFuY2VzPXt9LHRoaXMuYnVja2V0SW5zdGFuY2VJZD1pO2Zvcih2YXIgbj0wLG89ZTtuPG8ubGVuZ3RoO24rPTEpe3ZhciByPW9bbl0sYT1yLmtleTt0aGlzLmluZGV4ZWRTeW1ib2xJbnN0YW5jZXNbYV18fCh0aGlzLmluZGV4ZWRTeW1ib2xJbnN0YW5jZXNbYV09W10pLHRoaXMuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1thXS5wdXNoKHtjcm9zc1RpbGVJRDpyLmNyb3NzVGlsZUlELGNvb3JkOnRoaXMuZ2V0U2NhbGVkQ29vcmRpbmF0ZXMocix0KX0pO319O1dlLnByb3RvdHlwZS5nZXRTY2FsZWRDb29yZGluYXRlcz1mdW5jdGlvbihlLGkpe3ZhciBuPWkuY2Fub25pY2FsLnotdGhpcy50aWxlSUQuY2Fub25pY2FsLnosbz1HZS9NYXRoLnBvdygyLG4pLHI9ZS5hbmNob3I7cmV0dXJue3g6TWF0aC5mbG9vcigoaS5jYW5vbmljYWwueCp0LmRlZmF1bHQkOCtyLngpKm8pLHk6TWF0aC5mbG9vcigoaS5jYW5vbmljYWwueSp0LmRlZmF1bHQkOCtyLnkpKm8pfX0sV2UucHJvdG90eXBlLmZpbmRNYXRjaGVzPWZ1bmN0aW9uKHQsZSxpKXtmb3IodmFyIG49dGhpcy50aWxlSUQuY2Fub25pY2FsLno8ZS5jYW5vbmljYWwuej8xOk1hdGgucG93KDIsdGhpcy50aWxlSUQuY2Fub25pY2FsLnotZS5jYW5vbmljYWwueiksbz0wLHI9dDtvPHIubGVuZ3RoO28rPTEpe3ZhciBhPXJbb107aWYoIWEuY3Jvc3NUaWxlSUQpe3ZhciBzPXRoaXMuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1thLmtleV07aWYocylmb3IodmFyIGw9dGhpcy5nZXRTY2FsZWRDb29yZGluYXRlcyhhLGUpLGM9MCx1PXM7Yzx1Lmxlbmd0aDtjKz0xKXt2YXIgaD11W2NdO2lmKE1hdGguYWJzKGguY29vcmQueC1sLngpPD1uJiZNYXRoLmFicyhoLmNvb3JkLnktbC55KTw9biYmIWlbaC5jcm9zc1RpbGVJRF0pe2lbaC5jcm9zc1RpbGVJRF09ITAsYS5jcm9zc1RpbGVJRD1oLmNyb3NzVGlsZUlEO2JyZWFrfX19fX07dmFyIHFlPWZ1bmN0aW9uKCl7dGhpcy5tYXhDcm9zc1RpbGVJRD0wO307cWUucHJvdG90eXBlLmdlbmVyYXRlPWZ1bmN0aW9uKCl7cmV0dXJuKyt0aGlzLm1heENyb3NzVGlsZUlEfTt2YXIgWGU9ZnVuY3Rpb24oKXt0aGlzLmluZGV4ZXM9e30sdGhpcy51c2VkQ3Jvc3NUaWxlSURzPXt9LHRoaXMubG5nPTA7fTtYZS5wcm90b3R5cGUuaGFuZGxlV3JhcEp1bXA9ZnVuY3Rpb24odCl7dmFyIGU9TWF0aC5yb3VuZCgodC10aGlzLmxuZykvMzYwKTtpZigwIT09ZSlmb3IodmFyIGkgaW4gdGhpcy5pbmRleGVzKXt2YXIgbj10aGlzLmluZGV4ZXNbaV0sbz17fTtmb3IodmFyIHIgaW4gbil7dmFyIGE9bltyXTthLnRpbGVJRD1hLnRpbGVJRC51bndyYXBUbyhhLnRpbGVJRC53cmFwK2UpLG9bYS50aWxlSUQua2V5XT1hO310aGlzLmluZGV4ZXNbaV09bzt9dGhpcy5sbmc9dDt9LFhlLnByb3RvdHlwZS5hZGRCdWNrZXQ9ZnVuY3Rpb24odCxlLGkpe2lmKHRoaXMuaW5kZXhlc1t0Lm92ZXJzY2FsZWRaXSYmdGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdW3Qua2V5XSl7aWYodGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdW3Qua2V5XS5idWNrZXRJbnN0YW5jZUlkPT09ZS5idWNrZXRJbnN0YW5jZUlkKXJldHVybiExO3RoaXMucmVtb3ZlQnVja2V0Q3Jvc3NUaWxlSURzKHQub3ZlcnNjYWxlZFosdGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdW3Qua2V5XSk7fWZvcih2YXIgbj0wLG89ZS5zeW1ib2xJbnN0YW5jZXM7bjxvLmxlbmd0aDtuKz0xKXtvW25dLmNyb3NzVGlsZUlEPTA7fXRoaXMudXNlZENyb3NzVGlsZUlEc1t0Lm92ZXJzY2FsZWRaXXx8KHRoaXMudXNlZENyb3NzVGlsZUlEc1t0Lm92ZXJzY2FsZWRaXT17fSk7dmFyIHI9dGhpcy51c2VkQ3Jvc3NUaWxlSURzW3Qub3ZlcnNjYWxlZFpdO2Zvcih2YXIgYSBpbiB0aGlzLmluZGV4ZXMpe3ZhciBzPXRoaXMuaW5kZXhlc1thXTtpZihOdW1iZXIoYSk+dC5vdmVyc2NhbGVkWilmb3IodmFyIGwgaW4gcyl7dmFyIGM9c1tsXTtjLnRpbGVJRC5pc0NoaWxkT2YodCkmJmMuZmluZE1hdGNoZXMoZS5zeW1ib2xJbnN0YW5jZXMsdCxyKTt9ZWxzZXt2YXIgdT1zW3Quc2NhbGVkVG8oTnVtYmVyKGEpKS5rZXldO3UmJnUuZmluZE1hdGNoZXMoZS5zeW1ib2xJbnN0YW5jZXMsdCxyKTt9fWZvcih2YXIgaD0wLHA9ZS5zeW1ib2xJbnN0YW5jZXM7aDxwLmxlbmd0aDtoKz0xKXt2YXIgZD1wW2hdO2QuY3Jvc3NUaWxlSUR8fChkLmNyb3NzVGlsZUlEPWkuZ2VuZXJhdGUoKSxyW2QuY3Jvc3NUaWxlSURdPSEwKTt9cmV0dXJuIHZvaWQgMD09PXRoaXMuaW5kZXhlc1t0Lm92ZXJzY2FsZWRaXSYmKHRoaXMuaW5kZXhlc1t0Lm92ZXJzY2FsZWRaXT17fSksdGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdW3Qua2V5XT1uZXcgV2UodCxlLnN5bWJvbEluc3RhbmNlcyxlLmJ1Y2tldEluc3RhbmNlSWQpLCEwfSxYZS5wcm90b3R5cGUucmVtb3ZlQnVja2V0Q3Jvc3NUaWxlSURzPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBpIGluIGUuaW5kZXhlZFN5bWJvbEluc3RhbmNlcylmb3IodmFyIG49MCxvPWUuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1tpXTtuPG8ubGVuZ3RoO24rPTEpe3ZhciByPW9bbl07ZGVsZXRlIHRoaXMudXNlZENyb3NzVGlsZUlEc1t0XVtyLmNyb3NzVGlsZUlEXTt9fSxYZS5wcm90b3R5cGUucmVtb3ZlU3RhbGVCdWNrZXRzPWZ1bmN0aW9uKHQpe3ZhciBlPSExO2Zvcih2YXIgaSBpbiB0aGlzLmluZGV4ZXMpe3ZhciBuPXRoaXMuaW5kZXhlc1tpXTtmb3IodmFyIG8gaW4gbil0W25bb10uYnVja2V0SW5zdGFuY2VJZF18fCh0aGlzLnJlbW92ZUJ1Y2tldENyb3NzVGlsZUlEcyhpLG5bb10pLGRlbGV0ZSBuW29dLGU9ITApO31yZXR1cm4gZX07dmFyIEhlPWZ1bmN0aW9uKCl7dGhpcy5sYXllckluZGV4ZXM9e30sdGhpcy5jcm9zc1RpbGVJRHM9bmV3IHFlLHRoaXMubWF4QnVja2V0SW5zdGFuY2VJZD0wLHRoaXMuYnVja2V0c0luQ3VycmVudFBsYWNlbWVudD17fTt9O0hlLnByb3RvdHlwZS5hZGRMYXllcj1mdW5jdGlvbih0LGUsaSl7dmFyIG49dGhpcy5sYXllckluZGV4ZXNbdC5pZF07dm9pZCAwPT09biYmKG49dGhpcy5sYXllckluZGV4ZXNbdC5pZF09bmV3IFhlKTt2YXIgbz0hMSxyPXt9O24uaGFuZGxlV3JhcEp1bXAoaSk7Zm9yKHZhciBhPTAscz1lO2E8cy5sZW5ndGg7YSs9MSl7dmFyIGw9c1thXSxjPWwuZ2V0QnVja2V0KHQpO2MmJnQuaWQ9PT1jLmxheWVySWRzWzBdJiYoYy5idWNrZXRJbnN0YW5jZUlkfHwoYy5idWNrZXRJbnN0YW5jZUlkPSsrdGhpcy5tYXhCdWNrZXRJbnN0YW5jZUlkKSxuLmFkZEJ1Y2tldChsLnRpbGVJRCxjLHRoaXMuY3Jvc3NUaWxlSURzKSYmKG89ITApLHJbYy5idWNrZXRJbnN0YW5jZUlkXT0hMCk7fXJldHVybiBuLnJlbW92ZVN0YWxlQnVja2V0cyhyKSYmKG89ITApLG99LEhlLnByb3RvdHlwZS5wcnVuZVVudXNlZExheWVycz1mdW5jdGlvbih0KXt2YXIgZT17fTtmb3IodmFyIGkgaW4gdC5mb3JFYWNoKGZ1bmN0aW9uKHQpe2VbdF09ITA7fSksdGhpcy5sYXllckluZGV4ZXMpZVtpXXx8ZGVsZXRlIHRoaXMubGF5ZXJJbmRleGVzW2ldO307dmFyIEtlPWZ1bmN0aW9uKGUsaSl7cmV0dXJuIHQuZW1pdFZhbGlkYXRpb25FcnJvcnMoZSxpJiZpLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm5cInNvdXJjZS5jYW52YXNcIiE9PXQuaWRlbnRpZmllcn0pKX0sWWU9dC5waWNrKGllLFtcImFkZExheWVyXCIsXCJyZW1vdmVMYXllclwiLFwic2V0UGFpbnRQcm9wZXJ0eVwiLFwic2V0TGF5b3V0UHJvcGVydHlcIixcInNldEZpbHRlclwiLFwiYWRkU291cmNlXCIsXCJyZW1vdmVTb3VyY2VcIixcInNldExheWVyWm9vbVJhbmdlXCIsXCJzZXRMaWdodFwiLFwic2V0VHJhbnNpdGlvblwiLFwic2V0R2VvSlNPTlNvdXJjZURhdGFcIl0pLEplPXQucGljayhpZSxbXCJzZXRDZW50ZXJcIixcInNldFpvb21cIixcInNldEJlYXJpbmdcIixcInNldFBpdGNoXCJdKSxRZT1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKG4sbyl7dmFyIHI9dGhpczt2b2lkIDA9PT1vJiYobz17fSksZS5jYWxsKHRoaXMpLHRoaXMubWFwPW4sdGhpcy5kaXNwYXRjaGVyPW5ldyAkKChKdHx8KEp0PW5ldyBRdCksSnQpLHRoaXMpLHRoaXMuaW1hZ2VNYW5hZ2VyPW5ldyBMLHRoaXMuZ2x5cGhNYW5hZ2VyPW5ldyBOKG4uX3RyYW5zZm9ybVJlcXVlc3Qsby5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHkpLHRoaXMubGluZUF0bGFzPW5ldyBqKDI1Niw1MTIpLHRoaXMuY3Jvc3NUaWxlU3ltYm9sSW5kZXg9bmV3IEhlLHRoaXMuX2xheWVycz17fSx0aGlzLl9vcmRlcj1bXSx0aGlzLnNvdXJjZUNhY2hlcz17fSx0aGlzLnpvb21IaXN0b3J5PW5ldyB0LmRlZmF1bHQkMjMsdGhpcy5fbG9hZGVkPSExLHRoaXMuX3Jlc2V0VXBkYXRlcygpO3ZhciBhPXRoaXM7dGhpcy5fcnRsVGV4dFBsdWdpbkNhbGxiYWNrPWkucmVnaXN0ZXJGb3JQbHVnaW5BdmFpbGFiaWxpdHkoZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIGEuZGlzcGF0Y2hlci5icm9hZGNhc3QoXCJsb2FkUlRMVGV4dFBsdWdpblwiLHQucGx1Z2luVVJMLHQuY29tcGxldGlvbkNhbGxiYWNrKSxhLnNvdXJjZUNhY2hlcylhLnNvdXJjZUNhY2hlc1tlXS5yZWxvYWQoKTt9KSx0aGlzLm9uKFwiZGF0YVwiLGZ1bmN0aW9uKHQpe2lmKFwic291cmNlXCI9PT10LmRhdGFUeXBlJiZcIm1ldGFkYXRhXCI9PT10LnNvdXJjZURhdGFUeXBlKXt2YXIgZT1yLnNvdXJjZUNhY2hlc1t0LnNvdXJjZUlkXTtpZihlKXt2YXIgaT1lLmdldFNvdXJjZSgpO2lmKGkmJmkudmVjdG9yTGF5ZXJJZHMpZm9yKHZhciBuIGluIHIuX2xheWVycyl7dmFyIG89ci5fbGF5ZXJzW25dO28uc291cmNlPT09aS5pZCYmci5fdmFsaWRhdGVMYXllcihvKTt9fX19KTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWRVUkw9ZnVuY3Rpb24oZSxpKXt2YXIgbj10aGlzO3ZvaWQgMD09PWkmJihpPXt9KSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSk7dmFyIG89XCJib29sZWFuXCI9PXR5cGVvZiBpLnZhbGlkYXRlP2kudmFsaWRhdGU6IXkoZSk7ZT1mdW5jdGlvbih0LGUpe2lmKCF5KHQpKXJldHVybiB0O3ZhciBpPUModCk7cmV0dXJuIGkucGF0aD1cIi9zdHlsZXMvdjFcIitpLnBhdGgsdihpLGUpfShlLGkuYWNjZXNzVG9rZW4pO3ZhciByPXRoaXMubWFwLl90cmFuc2Zvcm1SZXF1ZXN0KGUsdC5SZXNvdXJjZVR5cGUuU3R5bGUpO3QuZ2V0SlNPTihyLGZ1bmN0aW9uKGUsaSl7ZT9uLmZpcmUobmV3IHQuRXJyb3JFdmVudChlKSk6aSYmbi5fbG9hZChpLG8pO30pO30saS5wcm90b3R5cGUubG9hZEpTT049ZnVuY3Rpb24oZSxpKXt2YXIgbj10aGlzO3ZvaWQgMD09PWkmJihpPXt9KSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSksci5mcmFtZShmdW5jdGlvbigpe24uX2xvYWQoZSwhMSE9PWkudmFsaWRhdGUpO30pO30saS5wcm90b3R5cGUuX2xvYWQ9ZnVuY3Rpb24oZSxpKXt2YXIgbj10aGlzO2lmKCFpfHwhS2UodGhpcyx0LnZhbGlkYXRlU3R5bGUoZSkpKXtmb3IodmFyIG8gaW4gdGhpcy5fbG9hZGVkPSEwLHRoaXMuc3R5bGVzaGVldD1lLGUuc291cmNlcyluLmFkZFNvdXJjZShvLGUuc291cmNlc1tvXSx7dmFsaWRhdGU6ITF9KTtlLnNwcml0ZT9mdW5jdGlvbihlLGksbil7dmFyIG8sYSxzLGw9ci5kZXZpY2VQaXhlbFJhdGlvPjE/XCJAMnhcIjpcIlwiO2Z1bmN0aW9uIGMoKXtpZihzKW4ocyk7ZWxzZSBpZihvJiZhKXt2YXIgZT1yLmdldEltYWdlRGF0YShhKSxpPXt9O2Zvcih2YXIgbCBpbiBvKXt2YXIgYz1vW2xdLHU9Yy53aWR0aCxoPWMuaGVpZ2h0LHA9Yy54LGQ9Yy55LGY9Yy5zZGYsbT1jLnBpeGVsUmF0aW8sXz1uZXcgdC5SR0JBSW1hZ2Uoe3dpZHRoOnUsaGVpZ2h0Omh9KTt0LlJHQkFJbWFnZS5jb3B5KGUsXyx7eDpwLHk6ZH0se3g6MCx5OjB9LHt3aWR0aDp1LGhlaWdodDpofSksaVtsXT17ZGF0YTpfLHBpeGVsUmF0aW86bSxzZGY6Zn07fW4obnVsbCxpKTt9fXQuZ2V0SlNPTihpKHcoZSxsLFwiLmpzb25cIiksdC5SZXNvdXJjZVR5cGUuU3ByaXRlSlNPTiksZnVuY3Rpb24odCxlKXtzfHwocz10LG89ZSxjKCkpO30pLHQuZ2V0SW1hZ2UoaSh3KGUsbCxcIi5wbmdcIiksdC5SZXNvdXJjZVR5cGUuU3ByaXRlSW1hZ2UpLGZ1bmN0aW9uKHQsZSl7c3x8KHM9dCxhPWUsYygpKTt9KTt9KGUuc3ByaXRlLHRoaXMubWFwLl90cmFuc2Zvcm1SZXF1ZXN0LGZ1bmN0aW9uKGUsaSl7aWYoZSluLmZpcmUobmV3IHQuRXJyb3JFdmVudChlKSk7ZWxzZSBpZihpKWZvcih2YXIgbyBpbiBpKW4uaW1hZ2VNYW5hZ2VyLmFkZEltYWdlKG8saVtvXSk7bi5pbWFnZU1hbmFnZXIuc2V0TG9hZGVkKCEwKSxuLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse2RhdGFUeXBlOlwic3R5bGVcIn0pKTt9KTp0aGlzLmltYWdlTWFuYWdlci5zZXRMb2FkZWQoITApLHRoaXMuZ2x5cGhNYW5hZ2VyLnNldFVSTChlLmdseXBocyk7dmFyIGE9ZWUodGhpcy5zdHlsZXNoZWV0LmxheWVycyk7dGhpcy5fb3JkZXI9YS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLl9sYXllcnM9e307Zm9yKHZhciBzPTAsbD1hO3M8bC5sZW5ndGg7cys9MSl7dmFyIGM9bFtzXTsoYz10LmRlZmF1bHQkMjIoYykpLnNldEV2ZW50ZWRQYXJlbnQobix7bGF5ZXI6e2lkOmMuaWR9fSksbi5fbGF5ZXJzW2MuaWRdPWM7fXRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoXCJzZXRMYXllcnNcIix0aGlzLl9zZXJpYWxpemVMYXllcnModGhpcy5fb3JkZXIpKSx0aGlzLmxpZ2h0PW5ldyBWKHRoaXMuc3R5bGVzaGVldC5saWdodCksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwic3R5bGUubG9hZFwiKSk7fX0saS5wcm90b3R5cGUuX3ZhbGlkYXRlTGF5ZXI9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5zb3VyY2VDYWNoZXNbZS5zb3VyY2VdO2lmKGkpe3ZhciBuPWUuc291cmNlTGF5ZXI7aWYobil7dmFyIG89aS5nZXRTb3VyY2UoKTsoXCJnZW9qc29uXCI9PT1vLnR5cGV8fG8udmVjdG9yTGF5ZXJJZHMmJi0xPT09by52ZWN0b3JMYXllcklkcy5pbmRleE9mKG4pKSYmdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKCdTb3VyY2UgbGF5ZXIgXCInK24rJ1wiIGRvZXMgbm90IGV4aXN0IG9uIHNvdXJjZSBcIicrby5pZCsnXCIgYXMgc3BlY2lmaWVkIGJ5IHN0eWxlIGxheWVyIFwiJytlLmlkKydcIicpKSk7fX19LGkucHJvdG90eXBlLmxvYWRlZD1mdW5jdGlvbigpe2lmKCF0aGlzLl9sb2FkZWQpcmV0dXJuITE7aWYoT2JqZWN0LmtleXModGhpcy5fdXBkYXRlZFNvdXJjZXMpLmxlbmd0aClyZXR1cm4hMTtmb3IodmFyIHQgaW4gdGhpcy5zb3VyY2VDYWNoZXMpaWYoIXRoaXMuc291cmNlQ2FjaGVzW3RdLmxvYWRlZCgpKXJldHVybiExO3JldHVybiEhdGhpcy5pbWFnZU1hbmFnZXIuaXNMb2FkZWQoKX0saS5wcm90b3R5cGUuX3NlcmlhbGl6ZUxheWVycz1mdW5jdGlvbih0KXt2YXIgZT10aGlzO3JldHVybiB0Lm1hcChmdW5jdGlvbih0KXtyZXR1cm4gZS5fbGF5ZXJzW3RdLnNlcmlhbGl6ZSgpfSl9LGkucHJvdG90eXBlLmhhc1RyYW5zaXRpb25zPWZ1bmN0aW9uKCl7aWYodGhpcy5saWdodCYmdGhpcy5saWdodC5oYXNUcmFuc2l0aW9uKCkpcmV0dXJuITA7Zm9yKHZhciB0IGluIHRoaXMuc291cmNlQ2FjaGVzKWlmKHRoaXMuc291cmNlQ2FjaGVzW3RdLmhhc1RyYW5zaXRpb24oKSlyZXR1cm4hMDtmb3IodmFyIGUgaW4gdGhpcy5fbGF5ZXJzKWlmKHRoaXMuX2xheWVyc1tlXS5oYXNUcmFuc2l0aW9uKCkpcmV0dXJuITA7cmV0dXJuITF9LGkucHJvdG90eXBlLl9jaGVja0xvYWRlZD1mdW5jdGlvbigpe2lmKCF0aGlzLl9sb2FkZWQpdGhyb3cgbmV3IEVycm9yKFwiU3R5bGUgaXMgbm90IGRvbmUgbG9hZGluZ1wiKX0saS5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKGUpe2lmKHRoaXMuX2xvYWRlZCl7aWYodGhpcy5fY2hhbmdlZCl7dmFyIGk9T2JqZWN0LmtleXModGhpcy5fdXBkYXRlZExheWVycyksbj1PYmplY3Qua2V5cyh0aGlzLl9yZW1vdmVkTGF5ZXJzKTtmb3IodmFyIG8gaW4oaS5sZW5ndGh8fG4ubGVuZ3RoKSYmdGhpcy5fdXBkYXRlV29ya2VyTGF5ZXJzKGksbiksdGhpcy5fdXBkYXRlZFNvdXJjZXMpe3ZhciByPXRoaXMuX3VwZGF0ZWRTb3VyY2VzW29dO1wicmVsb2FkXCI9PT1yP3RoaXMuX3JlbG9hZFNvdXJjZShvKTpcImNsZWFyXCI9PT1yJiZ0aGlzLl9jbGVhclNvdXJjZShvKTt9Zm9yKHZhciBhIGluIHRoaXMuX3VwZGF0ZWRQYWludFByb3BzKXRoaXMuX2xheWVyc1thXS51cGRhdGVUcmFuc2l0aW9ucyhlKTt0aGlzLmxpZ2h0LnVwZGF0ZVRyYW5zaXRpb25zKGUpLHRoaXMuX3Jlc2V0VXBkYXRlcygpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpO31mb3IodmFyIHMgaW4gdGhpcy5zb3VyY2VDYWNoZXMpdGhpcy5zb3VyY2VDYWNoZXNbc10udXNlZD0hMTtmb3IodmFyIGw9MCxjPXRoaXMuX29yZGVyO2w8Yy5sZW5ndGg7bCs9MSl7dmFyIHU9Y1tsXSxoPXRoaXMuX2xheWVyc1t1XTtoLnJlY2FsY3VsYXRlKGUpLCFoLmlzSGlkZGVuKGUuem9vbSkmJmguc291cmNlJiYodGhpcy5zb3VyY2VDYWNoZXNbaC5zb3VyY2VdLnVzZWQ9ITApO310aGlzLmxpZ2h0LnJlY2FsY3VsYXRlKGUpLHRoaXMuej1lLnpvb207fX0saS5wcm90b3R5cGUuX3VwZGF0ZVdvcmtlckxheWVycz1mdW5jdGlvbih0LGUpe3RoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoXCJ1cGRhdGVMYXllcnNcIix7bGF5ZXJzOnRoaXMuX3NlcmlhbGl6ZUxheWVycyh0KSxyZW1vdmVkSWRzOmV9KTt9LGkucHJvdG90eXBlLl9yZXNldFVwZGF0ZXM9ZnVuY3Rpb24oKXt0aGlzLl9jaGFuZ2VkPSExLHRoaXMuX3VwZGF0ZWRMYXllcnM9e30sdGhpcy5fcmVtb3ZlZExheWVycz17fSx0aGlzLl91cGRhdGVkU291cmNlcz17fSx0aGlzLl91cGRhdGVkUGFpbnRQcm9wcz17fTt9LGkucHJvdG90eXBlLnNldFN0YXRlPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXM7aWYodGhpcy5fY2hlY2tMb2FkZWQoKSxLZSh0aGlzLHQudmFsaWRhdGVTdHlsZShlKSkpcmV0dXJuITE7KGU9dC5jbG9uZShlKSkubGF5ZXJzPWVlKGUubGF5ZXJzKTt2YXIgbj11ZSh0aGlzLnNlcmlhbGl6ZSgpLGUpLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4hKHQuY29tbWFuZCBpbiBKZSl9KTtpZigwPT09bi5sZW5ndGgpcmV0dXJuITE7dmFyIG89bi5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuISh0LmNvbW1hbmQgaW4gWWUpfSk7aWYoby5sZW5ndGg+MCl0aHJvdyBuZXcgRXJyb3IoXCJVbmltcGxlbWVudGVkOiBcIitvLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5jb21tYW5kfSkuam9pbihcIiwgXCIpK1wiLlwiKTtyZXR1cm4gbi5mb3JFYWNoKGZ1bmN0aW9uKHQpe1wic2V0VHJhbnNpdGlvblwiIT09dC5jb21tYW5kJiZpW3QuY29tbWFuZF0uYXBwbHkoaSx0LmFyZ3MpO30pLHRoaXMuc3R5bGVzaGVldD1lLCEwfSxpLnByb3RvdHlwZS5hZGRJbWFnZT1mdW5jdGlvbihlLGkpe2lmKHRoaXMuZ2V0SW1hZ2UoZSkpcmV0dXJuIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIkFuIGltYWdlIHdpdGggdGhpcyBuYW1lIGFscmVhZHkgZXhpc3RzLlwiKSkpO3RoaXMuaW1hZ2VNYW5hZ2VyLmFkZEltYWdlKGUsaSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSk7fSxpLnByb3RvdHlwZS5nZXRJbWFnZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5pbWFnZU1hbmFnZXIuZ2V0SW1hZ2UodCl9LGkucHJvdG90eXBlLnJlbW92ZUltYWdlPWZ1bmN0aW9uKGUpe2lmKCF0aGlzLmdldEltYWdlKGUpKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJObyBpbWFnZSB3aXRoIHRoaXMgbmFtZSBleGlzdHMuXCIpKSk7dGhpcy5pbWFnZU1hbmFnZXIucmVtb3ZlSW1hZ2UoZSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSk7fSxpLnByb3RvdHlwZS5hZGRTb3VyY2U9ZnVuY3Rpb24oZSxpLG4pe3ZhciBvPXRoaXM7aWYodGhpcy5fY2hlY2tMb2FkZWQoKSx2b2lkIDAhPT10aGlzLnNvdXJjZUNhY2hlc1tlXSl0aHJvdyBuZXcgRXJyb3IoXCJUaGVyZSBpcyBhbHJlYWR5IGEgc291cmNlIHdpdGggdGhpcyBJRFwiKTtpZighaS50eXBlKXRocm93IG5ldyBFcnJvcihcIlRoZSB0eXBlIHByb3BlcnR5IG11c3QgYmUgZGVmaW5lZCwgYnV0IHRoZSBvbmx5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB3ZXJlIGdpdmVuOiBcIitPYmplY3Qua2V5cyhpKS5qb2luKFwiLCBcIikrXCIuXCIpO2lmKCEoW1widmVjdG9yXCIsXCJyYXN0ZXJcIixcImdlb2pzb25cIixcInZpZGVvXCIsXCJpbWFnZVwiXS5pbmRleE9mKGkudHlwZSk+PTApfHwhdGhpcy5fdmFsaWRhdGUodC52YWxpZGF0ZVN0eWxlLnNvdXJjZSxcInNvdXJjZXMuXCIrZSxpLG51bGwsbikpe3RoaXMubWFwJiZ0aGlzLm1hcC5fY29sbGVjdFJlc291cmNlVGltaW5nJiYoaS5jb2xsZWN0UmVzb3VyY2VUaW1pbmc9ITApO3ZhciByPXRoaXMuc291cmNlQ2FjaGVzW2VdPW5ldyBYdChlLGksdGhpcy5kaXNwYXRjaGVyKTtyLnN0eWxlPXRoaXMsci5zZXRFdmVudGVkUGFyZW50KHRoaXMsZnVuY3Rpb24oKXtyZXR1cm57aXNTb3VyY2VMb2FkZWQ6by5sb2FkZWQoKSxzb3VyY2U6ci5zZXJpYWxpemUoKSxzb3VyY2VJZDplfX0pLHIub25BZGQodGhpcy5tYXApLHRoaXMuX2NoYW5nZWQ9ITA7fX0saS5wcm90b3R5cGUucmVtb3ZlU291cmNlPWZ1bmN0aW9uKGUpe2lmKHRoaXMuX2NoZWNrTG9hZGVkKCksdm9pZCAwPT09dGhpcy5zb3VyY2VDYWNoZXNbZV0pdGhyb3cgbmV3IEVycm9yKFwiVGhlcmUgaXMgbm8gc291cmNlIHdpdGggdGhpcyBJRFwiKTtmb3IodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKWlmKHRoaXMuX2xheWVyc1tpXS5zb3VyY2U9PT1lKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoJ1NvdXJjZSBcIicrZSsnXCIgY2Fubm90IGJlIHJlbW92ZWQgd2hpbGUgbGF5ZXIgXCInK2krJ1wiIGlzIHVzaW5nIGl0LicpKSk7dmFyIG49dGhpcy5zb3VyY2VDYWNoZXNbZV07ZGVsZXRlIHRoaXMuc291cmNlQ2FjaGVzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkU291cmNlc1tlXSxuLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse3NvdXJjZURhdGFUeXBlOlwibWV0YWRhdGFcIixkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZUlkOmV9KSksbi5zZXRFdmVudGVkUGFyZW50KG51bGwpLG4uY2xlYXJUaWxlcygpLG4ub25SZW1vdmUmJm4ub25SZW1vdmUodGhpcy5tYXApLHRoaXMuX2NoYW5nZWQ9ITA7fSxpLnByb3RvdHlwZS5zZXRHZW9KU09OU291cmNlRGF0YT1mdW5jdGlvbih0LGUpe3RoaXMuX2NoZWNrTG9hZGVkKCksdGhpcy5zb3VyY2VDYWNoZXNbdF0uZ2V0U291cmNlKCkuc2V0RGF0YShlKSx0aGlzLl9jaGFuZ2VkPSEwO30saS5wcm90b3R5cGUuZ2V0U291cmNlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnNvdXJjZUNhY2hlc1t0XSYmdGhpcy5zb3VyY2VDYWNoZXNbdF0uZ2V0U291cmNlKCl9LGkucHJvdG90eXBlLmFkZExheWVyPWZ1bmN0aW9uKGUsaSxuKXt0aGlzLl9jaGVja0xvYWRlZCgpO3ZhciBvPWUuaWQ7aWYodGhpcy5nZXRMYXllcihvKSl0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoJ0xheWVyIHdpdGggaWQgXCInK28rJ1wiIGFscmVhZHkgZXhpc3RzIG9uIHRoaXMgbWFwJykpKTtlbHNlIGlmKFwib2JqZWN0XCI9PXR5cGVvZiBlLnNvdXJjZSYmKHRoaXMuYWRkU291cmNlKG8sZS5zb3VyY2UpLGU9dC5jbG9uZShlKSxlPXQuZXh0ZW5kKGUse3NvdXJjZTpvfSkpLCF0aGlzLl92YWxpZGF0ZSh0LnZhbGlkYXRlU3R5bGUubGF5ZXIsXCJsYXllcnMuXCIrbyxlLHthcnJheUluZGV4Oi0xfSxuKSl7dmFyIHI9dC5kZWZhdWx0JDIyKGUpO3RoaXMuX3ZhbGlkYXRlTGF5ZXIociksci5zZXRFdmVudGVkUGFyZW50KHRoaXMse2xheWVyOntpZDpvfX0pO3ZhciBhPWk/dGhpcy5fb3JkZXIuaW5kZXhPZihpKTp0aGlzLl9vcmRlci5sZW5ndGg7aWYoaSYmLTE9PT1hKXRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcignTGF5ZXIgd2l0aCBpZCBcIicraSsnXCIgZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBtYXAuJykpKTtlbHNle2lmKHRoaXMuX29yZGVyLnNwbGljZShhLDAsbyksdGhpcy5fbGF5ZXJPcmRlckNoYW5nZWQ9ITAsdGhpcy5fbGF5ZXJzW29dPXIsdGhpcy5fcmVtb3ZlZExheWVyc1tvXSYmci5zb3VyY2Upe3ZhciBzPXRoaXMuX3JlbW92ZWRMYXllcnNbb107ZGVsZXRlIHRoaXMuX3JlbW92ZWRMYXllcnNbb10scy50eXBlIT09ci50eXBlP3RoaXMuX3VwZGF0ZWRTb3VyY2VzW3Iuc291cmNlXT1cImNsZWFyXCI6KHRoaXMuX3VwZGF0ZWRTb3VyY2VzW3Iuc291cmNlXT1cInJlbG9hZFwiLHRoaXMuc291cmNlQ2FjaGVzW3Iuc291cmNlXS5wYXVzZSgpKTt9dGhpcy5fdXBkYXRlTGF5ZXIocik7fX19LGkucHJvdG90eXBlLm1vdmVMYXllcj1mdW5jdGlvbihlLGkpe2lmKHRoaXMuX2NoZWNrTG9hZGVkKCksdGhpcy5fY2hhbmdlZD0hMCx0aGlzLl9sYXllcnNbZV0pe2lmKGUhPT1pKXt2YXIgbj10aGlzLl9vcmRlci5pbmRleE9mKGUpO3RoaXMuX29yZGVyLnNwbGljZShuLDEpO3ZhciBvPWk/dGhpcy5fb3JkZXIuaW5kZXhPZihpKTp0aGlzLl9vcmRlci5sZW5ndGg7aSYmLTE9PT1vP3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcignTGF5ZXIgd2l0aCBpZCBcIicraSsnXCIgZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBtYXAuJykpKToodGhpcy5fb3JkZXIuc3BsaWNlKG8sMCxlKSx0aGlzLl9sYXllck9yZGVyQ2hhbmdlZD0hMCk7fX1lbHNlIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgbW92ZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5yZW1vdmVMYXllcj1mdW5jdGlvbihlKXt0aGlzLl9jaGVja0xvYWRlZCgpO3ZhciBpPXRoaXMuX2xheWVyc1tlXTtpZihpKXtpLnNldEV2ZW50ZWRQYXJlbnQobnVsbCk7dmFyIG49dGhpcy5fb3JkZXIuaW5kZXhPZihlKTt0aGlzLl9vcmRlci5zcGxpY2UobiwxKSx0aGlzLl9sYXllck9yZGVyQ2hhbmdlZD0hMCx0aGlzLl9jaGFuZ2VkPSEwLHRoaXMuX3JlbW92ZWRMYXllcnNbZV09aSxkZWxldGUgdGhpcy5fbGF5ZXJzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkTGF5ZXJzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkUGFpbnRQcm9wc1tlXTt9ZWxzZSB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJUaGUgbGF5ZXIgJ1wiK2UrXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBtYXAncyBzdHlsZSBhbmQgY2Fubm90IGJlIHJlbW92ZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5nZXRMYXllcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbGF5ZXJzW3RdfSxpLnByb3RvdHlwZS5zZXRMYXllclpvb21SYW5nZT1mdW5jdGlvbihlLGksbil7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgbz10aGlzLmdldExheWVyKGUpO28/by5taW56b29tPT09aSYmby5tYXh6b29tPT09bnx8KG51bGwhPWkmJihvLm1pbnpvb209aSksbnVsbCE9biYmKG8ubWF4em9vbT1uKSx0aGlzLl91cGRhdGVMYXllcihvKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIGxheWVyICdcIitlK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUgYW5kIGNhbm5vdCBoYXZlIHpvb20gZXh0ZW50LlwiKSkpO30saS5wcm90b3R5cGUuc2V0RmlsdGVyPWZ1bmN0aW9uKGUsaSl7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgbj10aGlzLmdldExheWVyKGUpO2lmKG4pe2lmKCF0LmRlZmF1bHQkMTAobi5maWx0ZXIsaSkpcmV0dXJuIG51bGw9PWk/KG4uZmlsdGVyPXZvaWQgMCx2b2lkIHRoaXMuX3VwZGF0ZUxheWVyKG4pKTp2b2lkKHRoaXMuX3ZhbGlkYXRlKHQudmFsaWRhdGVTdHlsZS5maWx0ZXIsXCJsYXllcnMuXCIrbi5pZCtcIi5maWx0ZXJcIixpKXx8KG4uZmlsdGVyPXQuY2xvbmUoaSksdGhpcy5fdXBkYXRlTGF5ZXIobikpKX1lbHNlIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgZmlsdGVyZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5nZXRGaWx0ZXI9ZnVuY3Rpb24oZSl7cmV0dXJuIHQuY2xvbmUodGhpcy5nZXRMYXllcihlKS5maWx0ZXIpfSxpLnByb3RvdHlwZS5zZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbihlLGksbil7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgbz10aGlzLmdldExheWVyKGUpO28/dC5kZWZhdWx0JDEwKG8uZ2V0TGF5b3V0UHJvcGVydHkoaSksbil8fChvLnNldExheW91dFByb3BlcnR5KGksbiksdGhpcy5fdXBkYXRlTGF5ZXIobykpOnRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgc3R5bGVkLlwiKSkpO30saS5wcm90b3R5cGUuZ2V0TGF5b3V0UHJvcGVydHk9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5nZXRMYXllcih0KS5nZXRMYXlvdXRQcm9wZXJ0eShlKX0saS5wcm90b3R5cGUuc2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbihlLGksbil7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgbz10aGlzLmdldExheWVyKGUpO2lmKG8pe2lmKCF0LmRlZmF1bHQkMTAoby5nZXRQYWludFByb3BlcnR5KGkpLG4pKXt2YXIgcj1vLl90cmFuc2l0aW9uYWJsZVBhaW50Ll92YWx1ZXNbaV0udmFsdWUuaXNEYXRhRHJpdmVuKCk7by5zZXRQYWludFByb3BlcnR5KGksbiksKG8uX3RyYW5zaXRpb25hYmxlUGFpbnQuX3ZhbHVlc1tpXS52YWx1ZS5pc0RhdGFEcml2ZW4oKXx8cikmJnRoaXMuX3VwZGF0ZUxheWVyKG8pLHRoaXMuX2NoYW5nZWQ9ITAsdGhpcy5fdXBkYXRlZFBhaW50UHJvcHNbZV09ITA7fX1lbHNlIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgc3R5bGVkLlwiKSkpO30saS5wcm90b3R5cGUuZ2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmdldExheWVyKHQpLmdldFBhaW50UHJvcGVydHkoZSl9LGkucHJvdG90eXBlLmdldFRyYW5zaXRpb249ZnVuY3Rpb24oKXtyZXR1cm4gdC5leHRlbmQoe2R1cmF0aW9uOjMwMCxkZWxheTowfSx0aGlzLnN0eWxlc2hlZXQmJnRoaXMuc3R5bGVzaGVldC50cmFuc2l0aW9uKX0saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcztyZXR1cm4gdC5maWx0ZXJPYmplY3Qoe3ZlcnNpb246dGhpcy5zdHlsZXNoZWV0LnZlcnNpb24sbmFtZTp0aGlzLnN0eWxlc2hlZXQubmFtZSxtZXRhZGF0YTp0aGlzLnN0eWxlc2hlZXQubWV0YWRhdGEsbGlnaHQ6dGhpcy5zdHlsZXNoZWV0LmxpZ2h0LGNlbnRlcjp0aGlzLnN0eWxlc2hlZXQuY2VudGVyLHpvb206dGhpcy5zdHlsZXNoZWV0Lnpvb20sYmVhcmluZzp0aGlzLnN0eWxlc2hlZXQuYmVhcmluZyxwaXRjaDp0aGlzLnN0eWxlc2hlZXQucGl0Y2gsc3ByaXRlOnRoaXMuc3R5bGVzaGVldC5zcHJpdGUsZ2x5cGhzOnRoaXMuc3R5bGVzaGVldC5nbHlwaHMsdHJhbnNpdGlvbjp0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbixzb3VyY2VzOnQubWFwT2JqZWN0KHRoaXMuc291cmNlQ2FjaGVzLGZ1bmN0aW9uKHQpe3JldHVybiB0LnNlcmlhbGl6ZSgpfSksbGF5ZXJzOnRoaXMuX29yZGVyLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gZS5fbGF5ZXJzW3RdLnNlcmlhbGl6ZSgpfSl9LGZ1bmN0aW9uKHQpe3JldHVybiB2b2lkIDAhPT10fSl9LGkucHJvdG90eXBlLl91cGRhdGVMYXllcj1mdW5jdGlvbih0KXt0aGlzLl91cGRhdGVkTGF5ZXJzW3QuaWRdPSEwLHQuc291cmNlJiYhdGhpcy5fdXBkYXRlZFNvdXJjZXNbdC5zb3VyY2VdJiYodGhpcy5fdXBkYXRlZFNvdXJjZXNbdC5zb3VyY2VdPVwicmVsb2FkXCIsdGhpcy5zb3VyY2VDYWNoZXNbdC5zb3VyY2VdLnBhdXNlKCkpLHRoaXMuX2NoYW5nZWQ9ITA7fSxpLnByb3RvdHlwZS5fZmxhdHRlblJlbmRlcmVkRmVhdHVyZXM9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPVtdLGk9dGhpcy5fb3JkZXIubGVuZ3RoLTE7aT49MDtpLS0pZm9yKHZhciBuPXRoaXMuX29yZGVyW2ldLG89MCxyPXQ7bzxyLmxlbmd0aDtvKz0xKXt2YXIgYT1yW29dW25dO2lmKGEpZm9yKHZhciBzPTAsbD1hO3M8bC5sZW5ndGg7cys9MSl7dmFyIGM9bFtzXTtlLnB1c2goYyk7fX1yZXR1cm4gZX0saS5wcm90b3R5cGUucXVlcnlSZW5kZXJlZEZlYXR1cmVzPWZ1bmN0aW9uKGUsaSxuKXtpJiZpLmZpbHRlciYmdGhpcy5fdmFsaWRhdGUodC52YWxpZGF0ZVN0eWxlLmZpbHRlcixcInF1ZXJ5UmVuZGVyZWRGZWF0dXJlcy5maWx0ZXJcIixpLmZpbHRlcik7dmFyIG89e307aWYoaSYmaS5sYXllcnMpe2lmKCFBcnJheS5pc0FycmF5KGkubGF5ZXJzKSlyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwicGFyYW1ldGVycy5sYXllcnMgbXVzdCBiZSBhbiBBcnJheS5cIikpKSxbXTtmb3IodmFyIHI9MCxhPWkubGF5ZXJzO3I8YS5sZW5ndGg7cis9MSl7dmFyIHM9YVtyXSxsPXRoaXMuX2xheWVyc1tzXTtpZighbClyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIGxheWVyICdcIitzK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUgYW5kIGNhbm5vdCBiZSBxdWVyaWVkIGZvciBmZWF0dXJlcy5cIikpKSxbXTtvW2wuc291cmNlXT0hMDt9fXZhciBjPVtdO2Zvcih2YXIgdSBpbiB0aGlzLnNvdXJjZUNhY2hlcylpLmxheWVycyYmIW9bdV18fGMucHVzaChhdCh0aGlzLnNvdXJjZUNhY2hlc1t1XSx0aGlzLl9sYXllcnMsZS53b3JsZENvb3JkaW5hdGUsaSxuKSk7cmV0dXJuIHRoaXMucGxhY2VtZW50JiZjLnB1c2goZnVuY3Rpb24odCxlLGksbixvKXtmb3IodmFyIHI9e30sYT1uLnF1ZXJ5UmVuZGVyZWRTeW1ib2xzKGUpLHM9W10sbD0wLGM9T2JqZWN0LmtleXMoYSkubWFwKE51bWJlcik7bDxjLmxlbmd0aDtsKz0xKXt2YXIgdT1jW2xdO3MucHVzaChvW3VdKTt9cy5zb3J0KHN0KTtmb3IodmFyIGg9ZnVuY3Rpb24oKXt2YXIgZT1kW3BdLG49ZS5mZWF0dXJlSW5kZXgubG9va3VwU3ltYm9sRmVhdHVyZXMoYVtlLmJ1Y2tldEluc3RhbmNlSWRdLGUuYnVja2V0SW5kZXgsZS5zb3VyY2VMYXllckluZGV4LGkuZmlsdGVyLGkubGF5ZXJzLHQpO2Zvcih2YXIgbyBpbiBuKXt2YXIgcz1yW29dPXJbb118fFtdLGw9bltvXTtsLnNvcnQoZnVuY3Rpb24odCxpKXt2YXIgbj1lLmZlYXR1cmVTb3J0T3JkZXI7aWYobil7dmFyIG89bi5pbmRleE9mKHQuZmVhdHVyZUluZGV4KTtyZXR1cm4gbi5pbmRleE9mKGkuZmVhdHVyZUluZGV4KS1vfXJldHVybiBpLmZlYXR1cmVJbmRleC10LmZlYXR1cmVJbmRleH0pO2Zvcih2YXIgYz0wLHU9bDtjPHUubGVuZ3RoO2MrPTEpe3ZhciBoPXVbY107cy5wdXNoKGguZmVhdHVyZSk7fX19LHA9MCxkPXM7cDxkLmxlbmd0aDtwKz0xKWgoKTtyZXR1cm4gcn0odGhpcy5fbGF5ZXJzLGUudmlld3BvcnQsaSx0aGlzLnBsYWNlbWVudC5jb2xsaXNpb25JbmRleCx0aGlzLnBsYWNlbWVudC5yZXRhaW5lZFF1ZXJ5RGF0YSkpLHRoaXMuX2ZsYXR0ZW5SZW5kZXJlZEZlYXR1cmVzKGMpfSxpLnByb3RvdHlwZS5xdWVyeVNvdXJjZUZlYXR1cmVzPWZ1bmN0aW9uKGUsaSl7aSYmaS5maWx0ZXImJnRoaXMuX3ZhbGlkYXRlKHQudmFsaWRhdGVTdHlsZS5maWx0ZXIsXCJxdWVyeVNvdXJjZUZlYXR1cmVzLmZpbHRlclwiLGkuZmlsdGVyKTt2YXIgbj10aGlzLnNvdXJjZUNhY2hlc1tlXTtyZXR1cm4gbj9mdW5jdGlvbih0LGUpe2Zvcih2YXIgaT10LmdldFJlbmRlcmFibGVJZHMoKS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIHQuZ2V0VGlsZUJ5SUQoZSl9KSxuPVtdLG89e30scj0wO3I8aS5sZW5ndGg7cisrKXt2YXIgYT1pW3JdLHM9YS50aWxlSUQuY2Fub25pY2FsLmtleTtvW3NdfHwob1tzXT0hMCxhLnF1ZXJ5U291cmNlRmVhdHVyZXMobixlKSk7fXJldHVybiBufShuLGkpOltdfSxpLnByb3RvdHlwZS5hZGRTb3VyY2VUeXBlPWZ1bmN0aW9uKHQsZSxuKXtyZXR1cm4gaS5nZXRTb3VyY2VUeXBlKHQpP24obmV3IEVycm9yKCdBIHNvdXJjZSB0eXBlIGNhbGxlZCBcIicrdCsnXCIgYWxyZWFkeSBleGlzdHMuJykpOihpLnNldFNvdXJjZVR5cGUodCxlKSxlLndvcmtlclNvdXJjZVVSTD92b2lkIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoXCJsb2FkV29ya2VyU291cmNlXCIse25hbWU6dCx1cmw6ZS53b3JrZXJTb3VyY2VVUkx9LG4pOm4obnVsbCxudWxsKSl9LGkucHJvdG90eXBlLmdldExpZ2h0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGlnaHQuZ2V0TGlnaHQoKX0saS5wcm90b3R5cGUuc2V0TGlnaHQ9ZnVuY3Rpb24oZSl7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgaT10aGlzLmxpZ2h0LmdldExpZ2h0KCksbj0hMTtmb3IodmFyIG8gaW4gZSlpZighdC5kZWZhdWx0JDEwKGVbb10saVtvXSkpe249ITA7YnJlYWt9aWYobil7dmFyIGE9e25vdzpyLm5vdygpLHRyYW5zaXRpb246dC5leHRlbmQoe2R1cmF0aW9uOjMwMCxkZWxheTowfSx0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbil9O3RoaXMubGlnaHQuc2V0TGlnaHQoZSksdGhpcy5saWdodC51cGRhdGVUcmFuc2l0aW9ucyhhKTt9fSxpLnByb3RvdHlwZS5fdmFsaWRhdGU9ZnVuY3Rpb24oZSxpLG4sbyxyKXtyZXR1cm4oIXJ8fCExIT09ci52YWxpZGF0ZSkmJktlKHRoaXMsZS5jYWxsKHQudmFsaWRhdGVTdHlsZSx0LmV4dGVuZCh7a2V5Omksc3R5bGU6dGhpcy5zZXJpYWxpemUoKSx2YWx1ZTpuLHN0eWxlU3BlYzp0LmRlZmF1bHQkNX0sbykpKX0saS5wcm90b3R5cGUuX3JlbW92ZT1mdW5jdGlvbigpe2Zvcih2YXIgZSBpbiB0LmV2ZW50ZWQub2ZmKFwicGx1Z2luQXZhaWxhYmxlXCIsdGhpcy5fcnRsVGV4dFBsdWdpbkNhbGxiYWNrKSx0aGlzLnNvdXJjZUNhY2hlcyl0aGlzLnNvdXJjZUNhY2hlc1tlXS5jbGVhclRpbGVzKCk7dGhpcy5kaXNwYXRjaGVyLnJlbW92ZSgpO30saS5wcm90b3R5cGUuX2NsZWFyU291cmNlPWZ1bmN0aW9uKHQpe3RoaXMuc291cmNlQ2FjaGVzW3RdLmNsZWFyVGlsZXMoKTt9LGkucHJvdG90eXBlLl9yZWxvYWRTb3VyY2U9ZnVuY3Rpb24odCl7dGhpcy5zb3VyY2VDYWNoZXNbdF0ucmVzdW1lKCksdGhpcy5zb3VyY2VDYWNoZXNbdF0ucmVsb2FkKCk7fSxpLnByb3RvdHlwZS5fdXBkYXRlU291cmNlcz1mdW5jdGlvbih0KXtmb3IodmFyIGUgaW4gdGhpcy5zb3VyY2VDYWNoZXMpdGhpcy5zb3VyY2VDYWNoZXNbZV0udXBkYXRlKHQpO30saS5wcm90b3R5cGUuX2dlbmVyYXRlQ29sbGlzaW9uQm94ZXM9ZnVuY3Rpb24oKXtmb3IodmFyIHQgaW4gdGhpcy5zb3VyY2VDYWNoZXMpdGhpcy5fcmVsb2FkU291cmNlKHQpO30saS5wcm90b3R5cGUuX3VwZGF0ZVBsYWNlbWVudD1mdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBuPSExLG89ITEsYT17fSxzPTAsbD10aGlzLl9vcmRlcjtzPGwubGVuZ3RoO3MrPTEpe3ZhciBjPWxbc10sdT10aGlzLl9sYXllcnNbY107aWYoXCJzeW1ib2xcIj09PXUudHlwZSl7aWYoIWFbdS5zb3VyY2VdKXt2YXIgaD10aGlzLnNvdXJjZUNhY2hlc1t1LnNvdXJjZV07YVt1LnNvdXJjZV09aC5nZXRSZW5kZXJhYmxlSWRzKCkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBoLmdldFRpbGVCeUlEKHQpfSkuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiBlLnRpbGVJRC5vdmVyc2NhbGVkWi10LnRpbGVJRC5vdmVyc2NhbGVkWnx8KHQudGlsZUlELmlzTGVzc1RoYW4oZS50aWxlSUQpPy0xOjEpfSk7fXZhciBwPXRoaXMuY3Jvc3NUaWxlU3ltYm9sSW5kZXguYWRkTGF5ZXIodSxhW3Uuc291cmNlXSx0LmNlbnRlci5sbmcpO249bnx8cDt9fXRoaXMuY3Jvc3NUaWxlU3ltYm9sSW5kZXgucHJ1bmVVbnVzZWRMYXllcnModGhpcy5fb3JkZXIpO3ZhciBkPXRoaXMuX2xheWVyT3JkZXJDaGFuZ2VkO2lmKChkfHwhdGhpcy5wYXVzZWFibGVQbGFjZW1lbnR8fHRoaXMucGF1c2VhYmxlUGxhY2VtZW50LmlzRG9uZSgpJiYhdGhpcy5wbGFjZW1lbnQuc3RpbGxSZWNlbnQoci5ub3coKSkpJiYodGhpcy5wYXVzZWFibGVQbGFjZW1lbnQ9bmV3ICRlKHQsdGhpcy5fb3JkZXIsZCxlLGkpLHRoaXMuX2xheWVyT3JkZXJDaGFuZ2VkPSExKSx0aGlzLnBhdXNlYWJsZVBsYWNlbWVudC5pc0RvbmUoKT90aGlzLnBsYWNlbWVudC5zZXRTdGFsZSgpOih0aGlzLnBhdXNlYWJsZVBsYWNlbWVudC5jb250aW51ZVBsYWNlbWVudCh0aGlzLl9vcmRlcix0aGlzLl9sYXllcnMsYSksdGhpcy5wYXVzZWFibGVQbGFjZW1lbnQuaXNEb25lKCkmJih0aGlzLnBsYWNlbWVudD10aGlzLnBhdXNlYWJsZVBsYWNlbWVudC5jb21taXQodGhpcy5wbGFjZW1lbnQsci5ub3coKSksbz0hMCksbiYmdGhpcy5wYXVzZWFibGVQbGFjZW1lbnQucGxhY2VtZW50LnNldFN0YWxlKCkpLG98fG4pZm9yKHZhciBmPTAsbT10aGlzLl9vcmRlcjtmPG0ubGVuZ3RoO2YrPTEpe3ZhciBfPW1bZl0sZz10aGlzLl9sYXllcnNbX107XCJzeW1ib2xcIj09PWcudHlwZSYmdGhpcy5wbGFjZW1lbnQudXBkYXRlTGF5ZXJPcGFjaXRpZXMoZyxhW2cuc291cmNlXSk7fXJldHVybiF0aGlzLnBhdXNlYWJsZVBsYWNlbWVudC5pc0RvbmUoKXx8dGhpcy5wbGFjZW1lbnQuaGFzVHJhbnNpdGlvbnMoci5ub3coKSl9LGkucHJvdG90eXBlLmdldEltYWdlcz1mdW5jdGlvbih0LGUsaSl7dGhpcy5pbWFnZU1hbmFnZXIuZ2V0SW1hZ2VzKGUuaWNvbnMsaSk7fSxpLnByb3RvdHlwZS5nZXRHbHlwaHM9ZnVuY3Rpb24odCxlLGkpe3RoaXMuZ2x5cGhNYW5hZ2VyLmdldEdseXBocyhlLnN0YWNrcyxpKTt9LGl9KHQuRXZlbnRlZCk7UWUuZ2V0U291cmNlVHlwZT1mdW5jdGlvbih0KXtyZXR1cm4gb3RbdF19LFFlLnNldFNvdXJjZVR5cGU9ZnVuY3Rpb24odCxlKXtvdFt0XT1lO30sUWUucmVnaXN0ZXJGb3JQbHVnaW5BdmFpbGFiaWxpdHk9dC5yZWdpc3RlckZvclBsdWdpbkF2YWlsYWJpbGl0eTt2YXIgdGk9dC5jcmVhdGVMYXlvdXQoW3tuYW1lOlwiYV9wb3NcIix0eXBlOlwiSW50MTZcIixjb21wb25lbnRzOjJ9XSksZWk9e3ByZWx1ZGU6e2ZyYWdtZW50U291cmNlOlwiI2lmZGVmIEdMX0VTXFxucHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2Vsc2VcXG5cXG4jaWYgIWRlZmluZWQobG93cClcXG4jZGVmaW5lIGxvd3BcXG4jZW5kaWZcXG5cXG4jaWYgIWRlZmluZWQobWVkaXVtcClcXG4jZGVmaW5lIG1lZGl1bXBcXG4jZW5kaWZcXG5cXG4jaWYgIWRlZmluZWQoaGlnaHApXFxuI2RlZmluZSBoaWdocFxcbiNlbmRpZlxcblxcbiNlbmRpZlxcblwiLHZlcnRleFNvdXJjZTpcIiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZWxzZVxcblxcbiNpZiAhZGVmaW5lZChsb3dwKVxcbiNkZWZpbmUgbG93cFxcbiNlbmRpZlxcblxcbiNpZiAhZGVmaW5lZChtZWRpdW1wKVxcbiNkZWZpbmUgbWVkaXVtcFxcbiNlbmRpZlxcblxcbiNpZiAhZGVmaW5lZChoaWdocClcXG4jZGVmaW5lIGhpZ2hwXFxuI2VuZGlmXFxuXFxuI2VuZGlmXFxuXFxuLy8gVW5wYWNrIGEgcGFpciBvZiB2YWx1ZXMgdGhhdCBoYXZlIGJlZW4gcGFja2VkIGludG8gYSBzaW5nbGUgZmxvYXQuXFxuLy8gVGhlIHBhY2tlZCB2YWx1ZXMgYXJlIGFzc3VtZWQgdG8gYmUgOC1iaXQgdW5zaWduZWQgaW50ZWdlcnMsIGFuZCBhcmVcXG4vLyBwYWNrZWQgbGlrZSBzbzpcXG4vLyBwYWNrZWRWYWx1ZSA9IGZsb29yKGlucHV0WzBdKSAqIDI1NiArIGlucHV0WzFdLFxcbnZlYzIgdW5wYWNrX2Zsb2F0KGNvbnN0IGZsb2F0IHBhY2tlZFZhbHVlKSB7XFxuICAgIGludCBwYWNrZWRJbnRWYWx1ZSA9IGludChwYWNrZWRWYWx1ZSk7XFxuICAgIGludCB2MCA9IHBhY2tlZEludFZhbHVlIC8gMjU2O1xcbiAgICByZXR1cm4gdmVjMih2MCwgcGFja2VkSW50VmFsdWUgLSB2MCAqIDI1Nik7XFxufVxcblxcbnZlYzIgdW5wYWNrX29wYWNpdHkoY29uc3QgZmxvYXQgcGFja2VkT3BhY2l0eSkge1xcbiAgICBpbnQgaW50T3BhY2l0eSA9IGludChwYWNrZWRPcGFjaXR5KSAvIDI7XFxuICAgIHJldHVybiB2ZWMyKGZsb2F0KGludE9wYWNpdHkpIC8gMTI3LjAsIG1vZChwYWNrZWRPcGFjaXR5LCAyLjApKTtcXG59XFxuXFxuLy8gVG8gbWluaW1pemUgdGhlIG51bWJlciBvZiBhdHRyaWJ1dGVzIG5lZWRlZCwgd2UgZW5jb2RlIGEgNC1jb21wb25lbnRcXG4vLyBjb2xvciBpbnRvIGEgcGFpciBvZiBmbG9hdHMgKGkuZS4gYSB2ZWMyKSBhcyBmb2xsb3dzOlxcbi8vIFsgZmxvb3IoY29sb3IuciAqIDI1NSkgKiAyNTYgKyBjb2xvci5nICogMjU1LFxcbi8vICAgZmxvb3IoY29sb3IuYiAqIDI1NSkgKiAyNTYgKyBjb2xvci5nICogMjU1IF1cXG52ZWM0IGRlY29kZV9jb2xvcihjb25zdCB2ZWMyIGVuY29kZWRDb2xvcikge1xcbiAgICByZXR1cm4gdmVjNChcXG4gICAgICAgIHVucGFja19mbG9hdChlbmNvZGVkQ29sb3JbMF0pIC8gMjU1LjAsXFxuICAgICAgICB1bnBhY2tfZmxvYXQoZW5jb2RlZENvbG9yWzFdKSAvIDI1NS4wXFxuICAgICk7XFxufVxcblxcbi8vIFVucGFjayBhIHBhaXIgb2YgcGFpbnQgdmFsdWVzIGFuZCBpbnRlcnBvbGF0ZSBiZXR3ZWVuIHRoZW0uXFxuZmxvYXQgdW5wYWNrX21peF92ZWMyKGNvbnN0IHZlYzIgcGFja2VkVmFsdWUsIGNvbnN0IGZsb2F0IHQpIHtcXG4gICAgcmV0dXJuIG1peChwYWNrZWRWYWx1ZVswXSwgcGFja2VkVmFsdWVbMV0sIHQpO1xcbn1cXG5cXG4vLyBVbnBhY2sgYSBwYWlyIG9mIHBhaW50IHZhbHVlcyBhbmQgaW50ZXJwb2xhdGUgYmV0d2VlbiB0aGVtLlxcbnZlYzQgdW5wYWNrX21peF92ZWM0KGNvbnN0IHZlYzQgcGFja2VkQ29sb3JzLCBjb25zdCBmbG9hdCB0KSB7XFxuICAgIHZlYzQgbWluQ29sb3IgPSBkZWNvZGVfY29sb3IodmVjMihwYWNrZWRDb2xvcnNbMF0sIHBhY2tlZENvbG9yc1sxXSkpO1xcbiAgICB2ZWM0IG1heENvbG9yID0gZGVjb2RlX2NvbG9yKHZlYzIocGFja2VkQ29sb3JzWzJdLCBwYWNrZWRDb2xvcnNbM10pKTtcXG4gICAgcmV0dXJuIG1peChtaW5Db2xvciwgbWF4Q29sb3IsIHQpO1xcbn1cXG5cXG4vLyBUaGUgb2Zmc2V0IGRlcGVuZHMgb24gaG93IG1hbnkgcGl4ZWxzIGFyZSBiZXR3ZWVuIHRoZSB3b3JsZCBvcmlnaW4gYW5kIHRoZSBlZGdlIG9mIHRoZSB0aWxlOlxcbi8vIHZlYzIgb2Zmc2V0ID0gbW9kKHBpeGVsX2Nvb3JkLCBzaXplKVxcbi8vXFxuLy8gQXQgaGlnaCB6b29tIGxldmVscyB0aGVyZSBhcmUgYSB0b24gb2YgcGl4ZWxzIGJldHdlZW4gdGhlIHdvcmxkIG9yaWdpbiBhbmQgdGhlIGVkZ2Ugb2YgdGhlIHRpbGUuXFxuLy8gVGhlIGdsc2wgc3BlYyBvbmx5IGd1YXJhbnRlZXMgMTYgYml0cyBvZiBwcmVjaXNpb24gZm9yIGhpZ2hwIGZsb2F0cy4gV2UgbmVlZCBtb3JlIHRoYW4gdGhhdC5cXG4vL1xcbi8vIFRoZSBwaXhlbF9jb29yZCBpcyBwYXNzZWQgaW4gYXMgdHdvIDE2IGJpdCB2YWx1ZXM6XFxuLy8gcGl4ZWxfY29vcmRfdXBwZXIgPSBmbG9vcihwaXhlbF9jb29yZCAvIDJeMTYpXFxuLy8gcGl4ZWxfY29vcmRfbG93ZXIgPSBtb2QocGl4ZWxfY29vcmQsIDJeMTYpXFxuLy9cXG4vLyBUaGUgb2Zmc2V0IGlzIGNhbGN1bGF0ZWQgaW4gYSBzZXJpZXMgb2Ygc3RlcHMgdGhhdCBzaG91bGQgcHJlc2VydmUgdGhpcyBwcmVjaXNpb246XFxudmVjMiBnZXRfcGF0dGVybl9wb3MoY29uc3QgdmVjMiBwaXhlbF9jb29yZF91cHBlciwgY29uc3QgdmVjMiBwaXhlbF9jb29yZF9sb3dlcixcXG4gICAgY29uc3QgdmVjMiBwYXR0ZXJuX3NpemUsIGNvbnN0IGZsb2F0IHRpbGVfdW5pdHNfdG9fcGl4ZWxzLCBjb25zdCB2ZWMyIHBvcykge1xcblxcbiAgICB2ZWMyIG9mZnNldCA9IG1vZChtb2QobW9kKHBpeGVsX2Nvb3JkX3VwcGVyLCBwYXR0ZXJuX3NpemUpICogMjU2LjAsIHBhdHRlcm5fc2l6ZSkgKiAyNTYuMCArIHBpeGVsX2Nvb3JkX2xvd2VyLCBwYXR0ZXJuX3NpemUpO1xcbiAgICByZXR1cm4gKHRpbGVfdW5pdHNfdG9fcGl4ZWxzICogcG9zICsgb2Zmc2V0KSAvIHBhdHRlcm5fc2l6ZTtcXG59XFxuXCJ9LGJhY2tncm91bmQ6e2ZyYWdtZW50U291cmNlOlwidW5pZm9ybSB2ZWM0IHVfY29sb3I7XFxudW5pZm9ybSBmbG9hdCB1X29wYWNpdHk7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9GcmFnQ29sb3IgPSB1X2NvbG9yICogdV9vcGFjaXR5O1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJhdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChhX3BvcywgMCwgMSk7XFxufVxcblwifSxiYWNrZ3JvdW5kUGF0dGVybjp7ZnJhZ21lbnRTb3VyY2U6XCJ1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9icl9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fdGxfYjtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyX2I7XFxudW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTtcXG51bmlmb3JtIGZsb2F0IHVfbWl4O1xcbnVuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O1xcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuXFxudmFyeWluZyB2ZWMyIHZfcG9zX2E7XFxudmFyeWluZyB2ZWMyIHZfcG9zX2I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICB2ZWMyIGltYWdlY29vcmQgPSBtb2Qodl9wb3NfYSwgMS4wKTtcXG4gICAgdmVjMiBwb3MgPSBtaXgodV9wYXR0ZXJuX3RsX2EgLyB1X3RleHNpemUsIHVfcGF0dGVybl9icl9hIC8gdV90ZXhzaXplLCBpbWFnZWNvb3JkKTtcXG4gICAgdmVjNCBjb2xvcjEgPSB0ZXh0dXJlMkQodV9pbWFnZSwgcG9zKTtcXG5cXG4gICAgdmVjMiBpbWFnZWNvb3JkX2IgPSBtb2Qodl9wb3NfYiwgMS4wKTtcXG4gICAgdmVjMiBwb3MyID0gbWl4KHVfcGF0dGVybl90bF9iIC8gdV90ZXhzaXplLCB1X3BhdHRlcm5fYnJfYiAvIHVfdGV4c2l6ZSwgaW1hZ2Vjb29yZF9iKTtcXG4gICAgdmVjNCBjb2xvcjIgPSB0ZXh0dXJlMkQodV9pbWFnZSwgcG9zMik7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IG1peChjb2xvcjEsIGNvbG9yMiwgdV9taXgpICogdV9vcGFjaXR5O1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9zaXplX2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9zaXplX2I7XFxudW5pZm9ybSB2ZWMyIHVfcGl4ZWxfY29vcmRfdXBwZXI7XFxudW5pZm9ybSB2ZWMyIHVfcGl4ZWxfY29vcmRfbG93ZXI7XFxudW5pZm9ybSBmbG9hdCB1X3NjYWxlX2E7XFxudW5pZm9ybSBmbG9hdCB1X3NjYWxlX2I7XFxudW5pZm9ybSBmbG9hdCB1X3RpbGVfdW5pdHNfdG9fcGl4ZWxzO1xcblxcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcblxcbnZhcnlpbmcgdmVjMiB2X3Bvc19hO1xcbnZhcnlpbmcgdmVjMiB2X3Bvc19iO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MsIDAsIDEpO1xcblxcbiAgICB2X3Bvc19hID0gZ2V0X3BhdHRlcm5fcG9zKHVfcGl4ZWxfY29vcmRfdXBwZXIsIHVfcGl4ZWxfY29vcmRfbG93ZXIsIHVfc2NhbGVfYSAqIHVfcGF0dGVybl9zaXplX2EsIHVfdGlsZV91bml0c190b19waXhlbHMsIGFfcG9zKTtcXG4gICAgdl9wb3NfYiA9IGdldF9wYXR0ZXJuX3Bvcyh1X3BpeGVsX2Nvb3JkX3VwcGVyLCB1X3BpeGVsX2Nvb3JkX2xvd2VyLCB1X3NjYWxlX2IgKiB1X3BhdHRlcm5fc2l6ZV9iLCB1X3RpbGVfdW5pdHNfdG9fcGl4ZWxzLCBhX3Bvcyk7XFxufVxcblwifSxjaXJjbGU6e2ZyYWdtZW50U291cmNlOlwiI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHJhZGl1c1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgc3Ryb2tlX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHN0cm9rZV93aWR0aFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBzdHJva2Vfb3BhY2l0eVxcblxcbnZhcnlpbmcgdmVjMyB2X2RhdGE7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgcmFkaXVzXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBzdHJva2VfY29sb3JcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCBzdHJva2Vfd2lkdGhcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBzdHJva2Vfb3BhY2l0eVxcblxcbiAgICB2ZWMyIGV4dHJ1ZGUgPSB2X2RhdGEueHk7XFxuICAgIGZsb2F0IGV4dHJ1ZGVfbGVuZ3RoID0gbGVuZ3RoKGV4dHJ1ZGUpO1xcblxcbiAgICBsb3dwIGZsb2F0IGFudGlhbGlhc2JsdXIgPSB2X2RhdGEuejtcXG4gICAgZmxvYXQgYW50aWFsaWFzZWRfYmx1ciA9IC1tYXgoYmx1ciwgYW50aWFsaWFzYmx1cik7XFxuXFxuICAgIGZsb2F0IG9wYWNpdHlfdCA9IHNtb290aHN0ZXAoMC4wLCBhbnRpYWxpYXNlZF9ibHVyLCBleHRydWRlX2xlbmd0aCAtIDEuMCk7XFxuXFxuICAgIGZsb2F0IGNvbG9yX3QgPSBzdHJva2Vfd2lkdGggPCAwLjAxID8gMC4wIDogc21vb3Roc3RlcChcXG4gICAgICAgIGFudGlhbGlhc2VkX2JsdXIsXFxuICAgICAgICAwLjAsXFxuICAgICAgICBleHRydWRlX2xlbmd0aCAtIHJhZGl1cyAvIChyYWRpdXMgKyBzdHJva2Vfd2lkdGgpXFxuICAgICk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IG9wYWNpdHlfdCAqIG1peChjb2xvciAqIG9wYWNpdHksIHN0cm9rZV9jb2xvciAqIHN0cm9rZV9vcGFjaXR5LCBjb2xvcl90KTtcXG5cXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XFxuXCIsdmVydGV4U291cmNlOlwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gYm9vbCB1X3NjYWxlX3dpdGhfbWFwO1xcbnVuaWZvcm0gYm9vbCB1X3BpdGNoX3dpdGhfbWFwO1xcbnVuaWZvcm0gdmVjMiB1X2V4dHJ1ZGVfc2NhbGU7XFxudW5pZm9ybSBoaWdocCBmbG9hdCB1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2U7XFxuXFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHJhZGl1c1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgc3Ryb2tlX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHN0cm9rZV93aWR0aFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBzdHJva2Vfb3BhY2l0eVxcblxcbnZhcnlpbmcgdmVjMyB2X2RhdGE7XFxuXFxudm9pZCBtYWluKHZvaWQpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHJhZGl1c1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgc3Ryb2tlX2NvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgc3Ryb2tlX3dpZHRoXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgc3Ryb2tlX29wYWNpdHlcXG5cXG4gICAgLy8gdW5lbmNvZGUgdGhlIGV4dHJ1c2lvbiB2ZWN0b3IgdGhhdCB3ZSBzbnVjayBpbnRvIHRoZSBhX3BvcyB2ZWN0b3JcXG4gICAgdmVjMiBleHRydWRlID0gdmVjMihtb2QoYV9wb3MsIDIuMCkgKiAyLjAgLSAxLjApO1xcblxcbiAgICAvLyBtdWx0aXBseSBhX3BvcyBieSAwLjUsIHNpbmNlIHdlIGhhZCBpdCAqIDIgaW4gb3JkZXIgdG8gc25lYWtcXG4gICAgLy8gaW4gZXh0cnVzaW9uIGRhdGFcXG4gICAgdmVjMiBjaXJjbGVfY2VudGVyID0gZmxvb3IoYV9wb3MgKiAwLjUpO1xcbiAgICBpZiAodV9waXRjaF93aXRoX21hcCkge1xcbiAgICAgICAgdmVjMiBjb3JuZXJfcG9zaXRpb24gPSBjaXJjbGVfY2VudGVyO1xcbiAgICAgICAgaWYgKHVfc2NhbGVfd2l0aF9tYXApIHtcXG4gICAgICAgICAgICBjb3JuZXJfcG9zaXRpb24gKz0gZXh0cnVkZSAqIChyYWRpdXMgKyBzdHJva2Vfd2lkdGgpICogdV9leHRydWRlX3NjYWxlO1xcbiAgICAgICAgfSBlbHNlIHtcXG4gICAgICAgICAgICAvLyBQaXRjaGluZyB0aGUgY2lyY2xlIHdpdGggdGhlIG1hcCBlZmZlY3RpdmVseSBzY2FsZXMgaXQgd2l0aCB0aGUgbWFwXFxuICAgICAgICAgICAgLy8gVG8gY291bnRlcmFjdCB0aGUgZWZmZWN0IGZvciBwaXRjaC1zY2FsZTogdmlld3BvcnQsIHdlIHJlc2NhbGUgdGhlXFxuICAgICAgICAgICAgLy8gd2hvbGUgY2lyY2xlIGJhc2VkIG9uIHRoZSBwaXRjaCBzY2FsaW5nIGVmZmVjdCBhdCBpdHMgY2VudHJhbCBwb2ludFxcbiAgICAgICAgICAgIHZlYzQgcHJvamVjdGVkX2NlbnRlciA9IHVfbWF0cml4ICogdmVjNChjaXJjbGVfY2VudGVyLCAwLCAxKTtcXG4gICAgICAgICAgICBjb3JuZXJfcG9zaXRpb24gKz0gZXh0cnVkZSAqIChyYWRpdXMgKyBzdHJva2Vfd2lkdGgpICogdV9leHRydWRlX3NjYWxlICogKHByb2plY3RlZF9jZW50ZXIudyAvIHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSk7XFxuICAgICAgICB9XFxuXFxuICAgICAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChjb3JuZXJfcG9zaXRpb24sIDAsIDEpO1xcbiAgICB9IGVsc2Uge1xcbiAgICAgICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoY2lyY2xlX2NlbnRlciwgMCwgMSk7XFxuXFxuICAgICAgICBpZiAodV9zY2FsZV93aXRoX21hcCkge1xcbiAgICAgICAgICAgIGdsX1Bvc2l0aW9uLnh5ICs9IGV4dHJ1ZGUgKiAocmFkaXVzICsgc3Ryb2tlX3dpZHRoKSAqIHVfZXh0cnVkZV9zY2FsZSAqIHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTtcXG4gICAgICAgIH0gZWxzZSB7XFxuICAgICAgICAgICAgZ2xfUG9zaXRpb24ueHkgKz0gZXh0cnVkZSAqIChyYWRpdXMgKyBzdHJva2Vfd2lkdGgpICogdV9leHRydWRlX3NjYWxlICogZ2xfUG9zaXRpb24udztcXG4gICAgICAgIH1cXG4gICAgfVxcblxcbiAgICAvLyBUaGlzIGlzIGEgbWluaW11bSBibHVyIGRpc3RhbmNlIHRoYXQgc2VydmVzIGFzIGEgZmF1eC1hbnRpYWxpYXNpbmcgZm9yXFxuICAgIC8vIHRoZSBjaXJjbGUuIHNpbmNlIGJsdXIgaXMgYSByYXRpbyBvZiB0aGUgY2lyY2xlJ3Mgc2l6ZSBhbmQgdGhlIGludGVudCBpc1xcbiAgICAvLyB0byBrZWVwIHRoZSBibHVyIGF0IHJvdWdobHkgMXB4LCB0aGUgdHdvIGFyZSBpbnZlcnNlbHkgcmVsYXRlZC5cXG4gICAgbG93cCBmbG9hdCBhbnRpYWxpYXNibHVyID0gMS4wIC8gREVWSUNFX1BJWEVMX1JBVElPIC8gKHJhZGl1cyArIHN0cm9rZV93aWR0aCk7XFxuXFxuICAgIHZfZGF0YSA9IHZlYzMoZXh0cnVkZS54LCBleHRydWRlLnksIGFudGlhbGlhc2JsdXIpO1xcbn1cXG5cIn0sY2xpcHBpbmdNYXNrOntmcmFnbWVudFNvdXJjZTpcInZvaWQgbWFpbigpIHtcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJhdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChhX3BvcywgMCwgMSk7XFxufVxcblwifSxoZWF0bWFwOntmcmFnbWVudFNvdXJjZTpcIiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgZmxvYXQgd2VpZ2h0XFxuXFxudW5pZm9ybSBoaWdocCBmbG9hdCB1X2ludGVuc2l0eTtcXG52YXJ5aW5nIHZlYzIgdl9leHRydWRlO1xcblxcbi8vIEdhdXNzaWFuIGtlcm5lbCBjb2VmZmljaWVudDogMSAvIHNxcnQoMiAqIFBJKVxcbiNkZWZpbmUgR0FVU1NfQ09FRiAwLjM5ODk0MjI4MDQwMTQzMjdcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIGZsb2F0IHdlaWdodFxcblxcbiAgICAvLyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHdpdGggYSBHYXVzc2lhbiBrZXJuZWwgb2Ygc2l6ZSA1eDVcXG4gICAgZmxvYXQgZCA9IC0wLjUgKiAzLjAgKiAzLjAgKiBkb3Qodl9leHRydWRlLCB2X2V4dHJ1ZGUpO1xcbiAgICBmbG9hdCB2YWwgPSB3ZWlnaHQgKiB1X2ludGVuc2l0eSAqIEdBVVNTX0NPRUYgKiBleHAoZCk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQodmFsLCAxLjAsIDEuMCwgMS4wKTtcXG5cXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XFxuXCIsdmVydGV4U291cmNlOlwiI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCBmbG9hdCB3ZWlnaHRcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgcmFkaXVzXFxuXFxudW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gZmxvYXQgdV9leHRydWRlX3NjYWxlO1xcbnVuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O1xcbnVuaWZvcm0gZmxvYXQgdV9pbnRlbnNpdHk7XFxuXFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuXFxudmFyeWluZyB2ZWMyIHZfZXh0cnVkZTtcXG5cXG4vLyBFZmZlY3RpdmUgXFxcIjBcXFwiIGluIHRoZSBrZXJuZWwgZGVuc2l0eSB0ZXh0dXJlIHRvIGFkanVzdCB0aGUga2VybmVsIHNpemUgdG87XFxuLy8gdGhpcyBlbXBpcmljYWxseSBjaG9zZW4gbnVtYmVyIG1pbmltaXplcyBhcnRpZmFjdHMgb24gb3ZlcmxhcHBpbmcga2VybmVsc1xcbi8vIGZvciB0eXBpY2FsIGhlYXRtYXAgY2FzZXMgKGFzc3VtaW5nIGNsdXN0ZXJlZCBzb3VyY2UpXFxuY29uc3QgaGlnaHAgZmxvYXQgWkVSTyA9IDEuMCAvIDI1NS4wIC8gMTYuMDtcXG5cXG4vLyBHYXVzc2lhbiBrZXJuZWwgY29lZmZpY2llbnQ6IDEgLyBzcXJ0KDIgKiBQSSlcXG4jZGVmaW5lIEdBVVNTX0NPRUYgMC4zOTg5NDIyODA0MDE0MzI3XFxuXFxudm9pZCBtYWluKHZvaWQpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgZmxvYXQgd2VpZ2h0XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgcmFkaXVzXFxuXFxuICAgIC8vIHVuZW5jb2RlIHRoZSBleHRydXNpb24gdmVjdG9yIHRoYXQgd2Ugc251Y2sgaW50byB0aGUgYV9wb3MgdmVjdG9yXFxuICAgIHZlYzIgdW5zY2FsZWRfZXh0cnVkZSA9IHZlYzIobW9kKGFfcG9zLCAyLjApICogMi4wIC0gMS4wKTtcXG5cXG4gICAgLy8gVGhpcyAnZXh0cnVkZScgY29tZXMgaW4gcmFuZ2luZyBmcm9tIFstMSwgLTFdLCB0byBbMSwgMV0uICBXZSdsbCB1c2VcXG4gICAgLy8gaXQgdG8gcHJvZHVjZSB0aGUgdmVydGljZXMgb2YgYSBzcXVhcmUgbWVzaCBmcmFtaW5nIHRoZSBwb2ludCBmZWF0dXJlXFxuICAgIC8vIHdlJ3JlIGFkZGluZyB0byB0aGUga2VybmVsIGRlbnNpdHkgdGV4dHVyZS4gIFdlJ2xsIGFsc28gcGFzcyBpdCBhc1xcbiAgICAvLyBhIHZhcnlpbmcsIHNvIHRoYXQgdGhlIGZyYWdtZW50IHNoYWRlciBjYW4gZGV0ZXJtaW5lIHRoZSBkaXN0YW5jZSBvZlxcbiAgICAvLyBlYWNoIGZyYWdtZW50IGZyb20gdGhlIHBvaW50IGZlYXR1cmUuXFxuICAgIC8vIEJlZm9yZSB3ZSBkbyBzbywgd2UgbmVlZCB0byBzY2FsZSBpdCB1cCBzdWZmaWNpZW50bHkgc28gdGhhdCB0aGVcXG4gICAgLy8ga2VybmVsIGZhbGxzIGVmZmVjdGl2ZWx5IHRvIHplcm8gYXQgdGhlIGVkZ2Ugb2YgdGhlIG1lc2guXFxuICAgIC8vIFRoYXQgaXMsIHdlIHdhbnQgdG8ga25vdyBTIHN1Y2ggdGhhdFxcbiAgICAvLyB3ZWlnaHQgKiB1X2ludGVuc2l0eSAqIEdBVVNTX0NPRUYgKiBleHAoLTAuNSAqIDMuMF4yICogU14yKSA9PSBaRVJPXFxuICAgIC8vIFdoaWNoIHNvbHZlcyB0bzpcXG4gICAgLy8gUyA9IHNxcnQoLTIuMCAqIGxvZyhaRVJPIC8gKHdlaWdodCAqIHVfaW50ZW5zaXR5ICogR0FVU1NfQ09FRikpKSAvIDMuMFxcbiAgICBmbG9hdCBTID0gc3FydCgtMi4wICogbG9nKFpFUk8gLyB3ZWlnaHQgLyB1X2ludGVuc2l0eSAvIEdBVVNTX0NPRUYpKSAvIDMuMDtcXG5cXG4gICAgLy8gUGFzcyB0aGUgdmFyeWluZyBpbiB1bml0cyBvZiByYWRpdXNcXG4gICAgdl9leHRydWRlID0gUyAqIHVuc2NhbGVkX2V4dHJ1ZGU7XFxuXFxuICAgIC8vIFNjYWxlIGJ5IHJhZGl1cyBhbmQgdGhlIHpvb20tYmFzZWQgc2NhbGUgZmFjdG9yIHRvIHByb2R1Y2UgYWN0dWFsXFxuICAgIC8vIG1lc2ggcG9zaXRpb25cXG4gICAgdmVjMiBleHRydWRlID0gdl9leHRydWRlICogcmFkaXVzICogdV9leHRydWRlX3NjYWxlO1xcblxcbiAgICAvLyBtdWx0aXBseSBhX3BvcyBieSAwLjUsIHNpbmNlIHdlIGhhZCBpdCAqIDIgaW4gb3JkZXIgdG8gc25lYWtcXG4gICAgLy8gaW4gZXh0cnVzaW9uIGRhdGFcXG4gICAgdmVjNCBwb3MgPSB2ZWM0KGZsb29yKGFfcG9zICogMC41KSArIGV4dHJ1ZGUsIDAsIDEpO1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogcG9zO1xcbn1cXG5cIn0saGVhdG1hcFRleHR1cmU6e2ZyYWdtZW50U291cmNlOlwidW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2NvbG9yX3JhbXA7XFxudW5pZm9ybSBmbG9hdCB1X29wYWNpdHk7XFxudmFyeWluZyB2ZWMyIHZfcG9zO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgZmxvYXQgdCA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3BvcykucjtcXG4gICAgdmVjNCBjb2xvciA9IHRleHR1cmUyRCh1X2NvbG9yX3JhbXAsIHZlYzIodCwgMC41KSk7XFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yICogdV9vcGFjaXR5O1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgwLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfd29ybGQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxudmFyeWluZyB2ZWMyIHZfcG9zO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MgKiB1X3dvcmxkLCAwLCAxKTtcXG5cXG4gICAgdl9wb3MueCA9IGFfcG9zLng7XFxuICAgIHZfcG9zLnkgPSAxLjAgLSBhX3Bvcy55O1xcbn1cXG5cIn0sY29sbGlzaW9uQm94OntmcmFnbWVudFNvdXJjZTpcIlxcbnZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7XFxudmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7XFxuXFxudm9pZCBtYWluKCkge1xcblxcbiAgICBmbG9hdCBhbHBoYSA9IDAuNTtcXG5cXG4gICAgLy8gUmVkID0gY29sbGlzaW9uLCBoaWRlIGxhYmVsXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wLCAwLjAsIDAuMCwgMS4wKSAqIGFscGhhO1xcblxcbiAgICAvLyBCbHVlID0gbm8gY29sbGlzaW9uLCBsYWJlbCBpcyBzaG93aW5nXFxuICAgIGlmICh2X3BsYWNlZCA+IDAuNSkge1xcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgwLjAsIDAuMCwgMS4wLCAwLjUpICogYWxwaGE7XFxuICAgIH1cXG5cXG4gICAgaWYgKHZfbm90VXNlZCA+IDAuNSkge1xcbiAgICAgICAgLy8gVGhpcyBib3ggbm90IHVzZWQsIGZhZGUgaXQgb3V0XFxuICAgICAgICBnbF9GcmFnQ29sb3IgKj0gLjE7XFxuICAgIH1cXG59XCIsdmVydGV4U291cmNlOlwiYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuYXR0cmlidXRlIHZlYzIgYV9hbmNob3JfcG9zO1xcbmF0dHJpYnV0ZSB2ZWMyIGFfZXh0cnVkZTtcXG5hdHRyaWJ1dGUgdmVjMiBhX3BsYWNlZDtcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfZXh0cnVkZV9zY2FsZTtcXG51bmlmb3JtIGZsb2F0IHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTtcXG5cXG52YXJ5aW5nIGZsb2F0IHZfcGxhY2VkO1xcbnZhcnlpbmcgZmxvYXQgdl9ub3RVc2VkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgdmVjNCBwcm9qZWN0ZWRQb2ludCA9IHVfbWF0cml4ICogdmVjNChhX2FuY2hvcl9wb3MsIDAsIDEpO1xcbiAgICBoaWdocCBmbG9hdCBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlID0gcHJvamVjdGVkUG9pbnQudztcXG4gICAgaGlnaHAgZmxvYXQgY29sbGlzaW9uX3BlcnNwZWN0aXZlX3JhdGlvID0gY2xhbXAoXFxuICAgICAgICAwLjUgKyAwLjUgKiAodV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlIC8gY2FtZXJhX3RvX2FuY2hvcl9kaXN0YW5jZSksXFxuICAgICAgICAwLjAsIC8vIFByZXZlbnRzIG92ZXJzaXplZCBuZWFyLWZpZWxkIGJveGVzIGluIHBpdGNoZWQvb3Zlcnpvb21lZCB0aWxlc1xcbiAgICAgICAgNC4wKTtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MsIDAuMCwgMS4wKTtcXG4gICAgZ2xfUG9zaXRpb24ueHkgKz0gYV9leHRydWRlICogdV9leHRydWRlX3NjYWxlICogZ2xfUG9zaXRpb24udyAqIGNvbGxpc2lvbl9wZXJzcGVjdGl2ZV9yYXRpbztcXG5cXG4gICAgdl9wbGFjZWQgPSBhX3BsYWNlZC54O1xcbiAgICB2X25vdFVzZWQgPSBhX3BsYWNlZC55O1xcbn1cXG5cIn0sY29sbGlzaW9uQ2lyY2xlOntmcmFnbWVudFNvdXJjZTpcInVuaWZvcm0gZmxvYXQgdV9vdmVyc2NhbGVfZmFjdG9yO1xcblxcbnZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7XFxudmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7XFxudmFyeWluZyBmbG9hdCB2X3JhZGl1cztcXG52YXJ5aW5nIHZlYzIgdl9leHRydWRlO1xcbnZhcnlpbmcgdmVjMiB2X2V4dHJ1ZGVfc2NhbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBmbG9hdCBhbHBoYSA9IDAuNTtcXG5cXG4gICAgLy8gUmVkID0gY29sbGlzaW9uLCBoaWRlIGxhYmVsXFxuICAgIHZlYzQgY29sb3IgPSB2ZWM0KDEuMCwgMC4wLCAwLjAsIDEuMCkgKiBhbHBoYTtcXG5cXG4gICAgLy8gQmx1ZSA9IG5vIGNvbGxpc2lvbiwgbGFiZWwgaXMgc2hvd2luZ1xcbiAgICBpZiAodl9wbGFjZWQgPiAwLjUpIHtcXG4gICAgICAgIGNvbG9yID0gdmVjNCgwLjAsIDAuMCwgMS4wLCAwLjUpICogYWxwaGE7XFxuICAgIH1cXG5cXG4gICAgaWYgKHZfbm90VXNlZCA+IDAuNSkge1xcbiAgICAgICAgLy8gVGhpcyBib3ggbm90IHVzZWQsIGZhZGUgaXQgb3V0XFxuICAgICAgICBjb2xvciAqPSAuMjtcXG4gICAgfVxcblxcbiAgICBmbG9hdCBleHRydWRlX3NjYWxlX2xlbmd0aCA9IGxlbmd0aCh2X2V4dHJ1ZGVfc2NhbGUpO1xcbiAgICBmbG9hdCBleHRydWRlX2xlbmd0aCA9IGxlbmd0aCh2X2V4dHJ1ZGUpICogZXh0cnVkZV9zY2FsZV9sZW5ndGg7XFxuICAgIGZsb2F0IHN0cm9rZV93aWR0aCA9IDE1LjAgKiBleHRydWRlX3NjYWxlX2xlbmd0aCAvIHVfb3ZlcnNjYWxlX2ZhY3RvcjtcXG4gICAgZmxvYXQgcmFkaXVzID0gdl9yYWRpdXMgKiBleHRydWRlX3NjYWxlX2xlbmd0aDtcXG5cXG4gICAgZmxvYXQgZGlzdGFuY2VfdG9fZWRnZSA9IGFicyhleHRydWRlX2xlbmd0aCAtIHJhZGl1cyk7XFxuICAgIGZsb2F0IG9wYWNpdHlfdCA9IHNtb290aHN0ZXAoLXN0cm9rZV93aWR0aCwgMC4wLCAtZGlzdGFuY2VfdG9fZWRnZSk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IG9wYWNpdHlfdCAqIGNvbG9yO1xcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJhdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5hdHRyaWJ1dGUgdmVjMiBhX2FuY2hvcl9wb3M7XFxuYXR0cmlidXRlIHZlYzIgYV9leHRydWRlO1xcbmF0dHJpYnV0ZSB2ZWMyIGFfcGxhY2VkO1xcblxcbnVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG51bmlmb3JtIHZlYzIgdV9leHRydWRlX3NjYWxlO1xcbnVuaWZvcm0gZmxvYXQgdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlO1xcblxcbnZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7XFxudmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7XFxudmFyeWluZyBmbG9hdCB2X3JhZGl1cztcXG5cXG52YXJ5aW5nIHZlYzIgdl9leHRydWRlO1xcbnZhcnlpbmcgdmVjMiB2X2V4dHJ1ZGVfc2NhbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICB2ZWM0IHByb2plY3RlZFBvaW50ID0gdV9tYXRyaXggKiB2ZWM0KGFfYW5jaG9yX3BvcywgMCwgMSk7XFxuICAgIGhpZ2hwIGZsb2F0IGNhbWVyYV90b19hbmNob3JfZGlzdGFuY2UgPSBwcm9qZWN0ZWRQb2ludC53O1xcbiAgICBoaWdocCBmbG9hdCBjb2xsaXNpb25fcGVyc3BlY3RpdmVfcmF0aW8gPSBjbGFtcChcXG4gICAgICAgIDAuNSArIDAuNSAqICh1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UgLyBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlKSxcXG4gICAgICAgIDAuMCwgLy8gUHJldmVudHMgb3ZlcnNpemVkIG5lYXItZmllbGQgY2lyY2xlcyBpbiBwaXRjaGVkL292ZXJ6b29tZWQgdGlsZXNcXG4gICAgICAgIDQuMCk7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLjAsIDEuMCk7XFxuXFxuICAgIGhpZ2hwIGZsb2F0IHBhZGRpbmdfZmFjdG9yID0gMS4yOyAvLyBQYWQgdGhlIHZlcnRpY2VzIHNsaWdodGx5IHRvIG1ha2Ugcm9vbSBmb3IgYW50aS1hbGlhcyBibHVyXFxuICAgIGdsX1Bvc2l0aW9uLnh5ICs9IGFfZXh0cnVkZSAqIHVfZXh0cnVkZV9zY2FsZSAqIHBhZGRpbmdfZmFjdG9yICogZ2xfUG9zaXRpb24udyAqIGNvbGxpc2lvbl9wZXJzcGVjdGl2ZV9yYXRpbztcXG5cXG4gICAgdl9wbGFjZWQgPSBhX3BsYWNlZC54O1xcbiAgICB2X25vdFVzZWQgPSBhX3BsYWNlZC55O1xcbiAgICB2X3JhZGl1cyA9IGFicyhhX2V4dHJ1ZGUueSk7IC8vIFdlIGRvbid0IHBpdGNoIHRoZSBjaXJjbGVzLCBzbyBib3RoIHVuaXRzIG9mIHRoZSBleHRydXNpb24gdmVjdG9yIGFyZSBlcXVhbCBpbiBtYWduaXR1ZGUgdG8gdGhlIHJhZGl1c1xcblxcbiAgICB2X2V4dHJ1ZGUgPSBhX2V4dHJ1ZGUgKiBwYWRkaW5nX2ZhY3RvcjtcXG4gICAgdl9leHRydWRlX3NjYWxlID0gdV9leHRydWRlX3NjYWxlICogdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlICogY29sbGlzaW9uX3BlcnNwZWN0aXZlX3JhdGlvO1xcbn1cXG5cIn0sZGVidWc6e2ZyYWdtZW50U291cmNlOlwidW5pZm9ybSBoaWdocCB2ZWM0IHVfY29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9GcmFnQ29sb3IgPSB1X2NvbG9yO1xcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJhdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChhX3BvcywgMCwgMSk7XFxufVxcblwifSxmaWxsOntmcmFnbWVudFNvdXJjZTpcIiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbiAgICBnbF9GcmFnQ29sb3IgPSBjb2xvciAqIG9wYWNpdHk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcImF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcblxcbnVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MsIDAsIDEpO1xcbn1cXG5cIn0sZmlsbE91dGxpbmU6e2ZyYWdtZW50U291cmNlOlwiI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnZhcnlpbmcgdmVjMiB2X3BvcztcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgb3V0bGluZV9jb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG4gICAgZmxvYXQgZGlzdCA9IGxlbmd0aCh2X3BvcyAtIGdsX0ZyYWdDb29yZC54eSk7XFxuICAgIGZsb2F0IGFscGhhID0gMS4wIC0gc21vb3Roc3RlcCgwLjAsIDEuMCwgZGlzdCk7XFxuICAgIGdsX0ZyYWdDb2xvciA9IG91dGxpbmVfY29sb3IgKiAoYWxwaGEgKiBvcGFjaXR5KTtcXG5cXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XFxuXCIsdmVydGV4U291cmNlOlwiYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuXFxudW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gdmVjMiB1X3dvcmxkO1xcblxcbnZhcnlpbmcgdmVjMiB2X3BvcztcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgb3V0bGluZV9jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG4gICAgdl9wb3MgPSAoZ2xfUG9zaXRpb24ueHkgLyBnbF9Qb3NpdGlvbi53ICsgMS4wKSAvIDIuMCAqIHVfd29ybGQ7XFxufVxcblwifSxmaWxsT3V0bGluZVBhdHRlcm46e2ZyYWdtZW50U291cmNlOlwidW5pZm9ybSB2ZWMyIHVfcGF0dGVybl90bF9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fYnJfYTtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2I7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9icl9iO1xcbnVuaWZvcm0gdmVjMiB1X3RleHNpemU7XFxudW5pZm9ybSBmbG9hdCB1X21peDtcXG5cXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcblxcbnZhcnlpbmcgdmVjMiB2X3Bvc19hO1xcbnZhcnlpbmcgdmVjMiB2X3Bvc19iO1xcbnZhcnlpbmcgdmVjMiB2X3BvcztcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxuICAgIHZlYzIgaW1hZ2Vjb29yZCA9IG1vZCh2X3Bvc19hLCAxLjApO1xcbiAgICB2ZWMyIHBvcyA9IG1peCh1X3BhdHRlcm5fdGxfYSAvIHVfdGV4c2l6ZSwgdV9wYXR0ZXJuX2JyX2EgLyB1X3RleHNpemUsIGltYWdlY29vcmQpO1xcbiAgICB2ZWM0IGNvbG9yMSA9IHRleHR1cmUyRCh1X2ltYWdlLCBwb3MpO1xcblxcbiAgICB2ZWMyIGltYWdlY29vcmRfYiA9IG1vZCh2X3Bvc19iLCAxLjApO1xcbiAgICB2ZWMyIHBvczIgPSBtaXgodV9wYXR0ZXJuX3RsX2IgLyB1X3RleHNpemUsIHVfcGF0dGVybl9icl9iIC8gdV90ZXhzaXplLCBpbWFnZWNvb3JkX2IpO1xcbiAgICB2ZWM0IGNvbG9yMiA9IHRleHR1cmUyRCh1X2ltYWdlLCBwb3MyKTtcXG5cXG4gICAgLy8gZmluZCBkaXN0YW5jZSB0byBvdXRsaW5lIGZvciBhbHBoYSBpbnRlcnBvbGF0aW9uXFxuXFxuICAgIGZsb2F0IGRpc3QgPSBsZW5ndGgodl9wb3MgLSBnbF9GcmFnQ29vcmQueHkpO1xcbiAgICBmbG9hdCBhbHBoYSA9IDEuMCAtIHNtb290aHN0ZXAoMC4wLCAxLjAsIGRpc3QpO1xcblxcblxcbiAgICBnbF9GcmFnQ29sb3IgPSBtaXgoY29sb3IxLCBjb2xvcjIsIHVfbWl4KSAqIGFscGhhICogb3BhY2l0eTtcXG5cXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XFxuXCIsdmVydGV4U291cmNlOlwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gdmVjMiB1X3dvcmxkO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9iO1xcbnVuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX3VwcGVyO1xcbnVuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX2xvd2VyO1xcbnVuaWZvcm0gZmxvYXQgdV9zY2FsZV9hO1xcbnVuaWZvcm0gZmxvYXQgdV9zY2FsZV9iO1xcbnVuaWZvcm0gZmxvYXQgdV90aWxlX3VuaXRzX3RvX3BpeGVscztcXG5cXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5cXG52YXJ5aW5nIHZlYzIgdl9wb3NfYTtcXG52YXJ5aW5nIHZlYzIgdl9wb3NfYjtcXG52YXJ5aW5nIHZlYzIgdl9wb3M7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChhX3BvcywgMCwgMSk7XFxuXFxuICAgIHZfcG9zX2EgPSBnZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlciwgdV9waXhlbF9jb29yZF9sb3dlciwgdV9zY2FsZV9hICogdV9wYXR0ZXJuX3NpemVfYSwgdV90aWxlX3VuaXRzX3RvX3BpeGVscywgYV9wb3MpO1xcbiAgICB2X3Bvc19iID0gZ2V0X3BhdHRlcm5fcG9zKHVfcGl4ZWxfY29vcmRfdXBwZXIsIHVfcGl4ZWxfY29vcmRfbG93ZXIsIHVfc2NhbGVfYiAqIHVfcGF0dGVybl9zaXplX2IsIHVfdGlsZV91bml0c190b19waXhlbHMsIGFfcG9zKTtcXG5cXG4gICAgdl9wb3MgPSAoZ2xfUG9zaXRpb24ueHkgLyBnbF9Qb3NpdGlvbi53ICsgMS4wKSAvIDIuMCAqIHVfd29ybGQ7XFxufVxcblwifSxmaWxsUGF0dGVybjp7ZnJhZ21lbnRTb3VyY2U6XCJ1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9icl9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fdGxfYjtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyX2I7XFxudW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTtcXG51bmlmb3JtIGZsb2F0IHVfbWl4O1xcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuXFxudmFyeWluZyB2ZWMyIHZfcG9zX2E7XFxudmFyeWluZyB2ZWMyIHZfcG9zX2I7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbiAgICB2ZWMyIGltYWdlY29vcmQgPSBtb2Qodl9wb3NfYSwgMS4wKTtcXG4gICAgdmVjMiBwb3MgPSBtaXgodV9wYXR0ZXJuX3RsX2EgLyB1X3RleHNpemUsIHVfcGF0dGVybl9icl9hIC8gdV90ZXhzaXplLCBpbWFnZWNvb3JkKTtcXG4gICAgdmVjNCBjb2xvcjEgPSB0ZXh0dXJlMkQodV9pbWFnZSwgcG9zKTtcXG5cXG4gICAgdmVjMiBpbWFnZWNvb3JkX2IgPSBtb2Qodl9wb3NfYiwgMS4wKTtcXG4gICAgdmVjMiBwb3MyID0gbWl4KHVfcGF0dGVybl90bF9iIC8gdV90ZXhzaXplLCB1X3BhdHRlcm5fYnJfYiAvIHVfdGV4c2l6ZSwgaW1hZ2Vjb29yZF9iKTtcXG4gICAgdmVjNCBjb2xvcjIgPSB0ZXh0dXJlMkQodV9pbWFnZSwgcG9zMik7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IG1peChjb2xvcjEsIGNvbG9yMiwgdV9taXgpICogb3BhY2l0eTtcXG5cXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XFxuXCIsdmVydGV4U291cmNlOlwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9iO1xcbnVuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX3VwcGVyO1xcbnVuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX2xvd2VyO1xcbnVuaWZvcm0gZmxvYXQgdV9zY2FsZV9hO1xcbnVuaWZvcm0gZmxvYXQgdV9zY2FsZV9iO1xcbnVuaWZvcm0gZmxvYXQgdV90aWxlX3VuaXRzX3RvX3BpeGVscztcXG5cXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5cXG52YXJ5aW5nIHZlYzIgdl9wb3NfYTtcXG52YXJ5aW5nIHZlYzIgdl9wb3NfYjtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG5cXG4gICAgdl9wb3NfYSA9IGdldF9wYXR0ZXJuX3Bvcyh1X3BpeGVsX2Nvb3JkX3VwcGVyLCB1X3BpeGVsX2Nvb3JkX2xvd2VyLCB1X3NjYWxlX2EgKiB1X3BhdHRlcm5fc2l6ZV9hLCB1X3RpbGVfdW5pdHNfdG9fcGl4ZWxzLCBhX3Bvcyk7XFxuICAgIHZfcG9zX2IgPSBnZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlciwgdV9waXhlbF9jb29yZF9sb3dlciwgdV9zY2FsZV9iICogdV9wYXR0ZXJuX3NpemVfYiwgdV90aWxlX3VuaXRzX3RvX3BpeGVscywgYV9wb3MpO1xcbn1cXG5cIn0sZmlsbEV4dHJ1c2lvbjp7ZnJhZ21lbnRTb3VyY2U6XCJ2YXJ5aW5nIHZlYzQgdl9jb2xvcjtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmFzZVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBoZWlnaHRcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmFzZVxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGhlaWdodFxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZfY29sb3I7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcInVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG51bmlmb3JtIHZlYzMgdV9saWdodGNvbG9yO1xcbnVuaWZvcm0gbG93cCB2ZWMzIHVfbGlnaHRwb3M7XFxudW5pZm9ybSBsb3dwIGZsb2F0IHVfbGlnaHRpbnRlbnNpdHk7XFxuXFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxuYXR0cmlidXRlIHZlYzQgYV9ub3JtYWxfZWQ7XFxuXFxudmFyeWluZyB2ZWM0IHZfY29sb3I7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJhc2VcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgaGVpZ2h0XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJhc2VcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoZWlnaHRcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcblxcbiAgICB2ZWMzIG5vcm1hbCA9IGFfbm9ybWFsX2VkLnh5ejtcXG5cXG4gICAgYmFzZSA9IG1heCgwLjAsIGJhc2UpO1xcbiAgICBoZWlnaHQgPSBtYXgoMC4wLCBoZWlnaHQpO1xcblxcbiAgICBmbG9hdCB0ID0gbW9kKG5vcm1hbC54LCAyLjApO1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHVfbWF0cml4ICogdmVjNChhX3BvcywgdCA+IDAuMCA/IGhlaWdodCA6IGJhc2UsIDEpO1xcblxcbiAgICAvLyBSZWxhdGl2ZSBsdW1pbmFuY2UgKGhvdyBkYXJrL2JyaWdodCBpcyB0aGUgc3VyZmFjZSBjb2xvcj8pXFxuICAgIGZsb2F0IGNvbG9ydmFsdWUgPSBjb2xvci5yICogMC4yMTI2ICsgY29sb3IuZyAqIDAuNzE1MiArIGNvbG9yLmIgKiAwLjA3MjI7XFxuXFxuICAgIHZfY29sb3IgPSB2ZWM0KDAuMCwgMC4wLCAwLjAsIDEuMCk7XFxuXFxuICAgIC8vIEFkZCBzbGlnaHQgYW1iaWVudCBsaWdodGluZyBzbyBubyBleHRydXNpb25zIGFyZSB0b3RhbGx5IGJsYWNrXFxuICAgIHZlYzQgYW1iaWVudGxpZ2h0ID0gdmVjNCgwLjAzLCAwLjAzLCAwLjAzLCAxLjApO1xcbiAgICBjb2xvciArPSBhbWJpZW50bGlnaHQ7XFxuXFxuICAgIC8vIENhbGN1bGF0ZSBjb3ModGhldGEpLCB3aGVyZSB0aGV0YSBpcyB0aGUgYW5nbGUgYmV0d2VlbiBzdXJmYWNlIG5vcm1hbCBhbmQgZGlmZnVzZSBsaWdodCByYXlcXG4gICAgZmxvYXQgZGlyZWN0aW9uYWwgPSBjbGFtcChkb3Qobm9ybWFsIC8gMTYzODQuMCwgdV9saWdodHBvcyksIDAuMCwgMS4wKTtcXG5cXG4gICAgLy8gQWRqdXN0IGRpcmVjdGlvbmFsIHNvIHRoYXRcXG4gICAgLy8gdGhlIHJhbmdlIG9mIHZhbHVlcyBmb3IgaGlnaGxpZ2h0L3NoYWRpbmcgaXMgbmFycm93ZXJcXG4gICAgLy8gd2l0aCBsb3dlciBsaWdodCBpbnRlbnNpdHlcXG4gICAgLy8gYW5kIHdpdGggbGlnaHRlci9icmlnaHRlciBzdXJmYWNlIGNvbG9yc1xcbiAgICBkaXJlY3Rpb25hbCA9IG1peCgoMS4wIC0gdV9saWdodGludGVuc2l0eSksIG1heCgoMS4wIC0gY29sb3J2YWx1ZSArIHVfbGlnaHRpbnRlbnNpdHkpLCAxLjApLCBkaXJlY3Rpb25hbCk7XFxuXFxuICAgIC8vIEFkZCBncmFkaWVudCBhbG9uZyB6IGF4aXMgb2Ygc2lkZSBzdXJmYWNlc1xcbiAgICBpZiAobm9ybWFsLnkgIT0gMC4wKSB7XFxuICAgICAgICBkaXJlY3Rpb25hbCAqPSBjbGFtcCgodCArIGJhc2UpICogcG93KGhlaWdodCAvIDE1MC4wLCAwLjUpLCBtaXgoMC43LCAwLjk4LCAxLjAgLSB1X2xpZ2h0aW50ZW5zaXR5KSwgMS4wKTtcXG4gICAgfVxcblxcbiAgICAvLyBBc3NpZ24gZmluYWwgY29sb3IgYmFzZWQgb24gc3VyZmFjZSArIGFtYmllbnQgbGlnaHQgY29sb3IsIGRpZmZ1c2UgbGlnaHQgZGlyZWN0aW9uYWwsIGFuZCBsaWdodCBjb2xvclxcbiAgICAvLyB3aXRoIGxvd2VyIGJvdW5kcyBhZGp1c3RlZCB0byBodWUgb2YgbGlnaHRcXG4gICAgLy8gc28gdGhhdCBzaGFkaW5nIGlzIHRpbnRlZCB3aXRoIHRoZSBjb21wbGVtZW50YXJ5IChvcHBvc2l0ZSkgY29sb3IgdG8gdGhlIGxpZ2h0IGNvbG9yXFxuICAgIHZfY29sb3IuciArPSBjbGFtcChjb2xvci5yICogZGlyZWN0aW9uYWwgKiB1X2xpZ2h0Y29sb3IuciwgbWl4KDAuMCwgMC4zLCAxLjAgLSB1X2xpZ2h0Y29sb3IuciksIDEuMCk7XFxuICAgIHZfY29sb3IuZyArPSBjbGFtcChjb2xvci5nICogZGlyZWN0aW9uYWwgKiB1X2xpZ2h0Y29sb3IuZywgbWl4KDAuMCwgMC4zLCAxLjAgLSB1X2xpZ2h0Y29sb3IuZyksIDEuMCk7XFxuICAgIHZfY29sb3IuYiArPSBjbGFtcChjb2xvci5iICogZGlyZWN0aW9uYWwgKiB1X2xpZ2h0Y29sb3IuYiwgbWl4KDAuMCwgMC4zLCAxLjAgLSB1X2xpZ2h0Y29sb3IuYiksIDEuMCk7XFxufVxcblwifSxmaWxsRXh0cnVzaW9uUGF0dGVybjp7ZnJhZ21lbnRTb3VyY2U6XCJ1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl9icl9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fdGxfYjtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyX2I7XFxudW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTtcXG51bmlmb3JtIGZsb2F0IHVfbWl4O1xcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuXFxudmFyeWluZyB2ZWMyIHZfcG9zX2E7XFxudmFyeWluZyB2ZWMyIHZfcG9zX2I7XFxudmFyeWluZyB2ZWM0IHZfbGlnaHRpbmc7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJhc2VcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgaGVpZ2h0XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJhc2VcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoZWlnaHRcXG5cXG4gICAgdmVjMiBpbWFnZWNvb3JkID0gbW9kKHZfcG9zX2EsIDEuMCk7XFxuICAgIHZlYzIgcG9zID0gbWl4KHVfcGF0dGVybl90bF9hIC8gdV90ZXhzaXplLCB1X3BhdHRlcm5fYnJfYSAvIHVfdGV4c2l6ZSwgaW1hZ2Vjb29yZCk7XFxuICAgIHZlYzQgY29sb3IxID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHBvcyk7XFxuXFxuICAgIHZlYzIgaW1hZ2Vjb29yZF9iID0gbW9kKHZfcG9zX2IsIDEuMCk7XFxuICAgIHZlYzIgcG9zMiA9IG1peCh1X3BhdHRlcm5fdGxfYiAvIHVfdGV4c2l6ZSwgdV9wYXR0ZXJuX2JyX2IgLyB1X3RleHNpemUsIGltYWdlY29vcmRfYik7XFxuICAgIHZlYzQgY29sb3IyID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHBvczIpO1xcblxcbiAgICB2ZWM0IG1peGVkQ29sb3IgPSBtaXgoY29sb3IxLCBjb2xvcjIsIHVfbWl4KTtcXG5cXG4gICAgZ2xfRnJhZ0NvbG9yID0gbWl4ZWRDb2xvciAqIHZfbGlnaHRpbmc7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcInVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3NpemVfYTtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3NpemVfYjtcXG51bmlmb3JtIHZlYzIgdV9waXhlbF9jb29yZF91cHBlcjtcXG51bmlmb3JtIHZlYzIgdV9waXhlbF9jb29yZF9sb3dlcjtcXG51bmlmb3JtIGZsb2F0IHVfc2NhbGVfYTtcXG51bmlmb3JtIGZsb2F0IHVfc2NhbGVfYjtcXG51bmlmb3JtIGZsb2F0IHVfdGlsZV91bml0c190b19waXhlbHM7XFxudW5pZm9ybSBmbG9hdCB1X2hlaWdodF9mYWN0b3I7XFxuXFxudW5pZm9ybSB2ZWMzIHVfbGlnaHRjb2xvcjtcXG51bmlmb3JtIGxvd3AgdmVjMyB1X2xpZ2h0cG9zO1xcbnVuaWZvcm0gbG93cCBmbG9hdCB1X2xpZ2h0aW50ZW5zaXR5O1xcblxcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zO1xcbmF0dHJpYnV0ZSB2ZWM0IGFfbm9ybWFsX2VkO1xcblxcbnZhcnlpbmcgdmVjMiB2X3Bvc19hO1xcbnZhcnlpbmcgdmVjMiB2X3Bvc19iO1xcbnZhcnlpbmcgdmVjNCB2X2xpZ2h0aW5nO1xcbnZhcnlpbmcgZmxvYXQgdl9kaXJlY3Rpb25hbDtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmFzZVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBoZWlnaHRcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmFzZVxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGhlaWdodFxcblxcbiAgICB2ZWMzIG5vcm1hbCA9IGFfbm9ybWFsX2VkLnh5ejtcXG4gICAgZmxvYXQgZWRnZWRpc3RhbmNlID0gYV9ub3JtYWxfZWQudztcXG5cXG4gICAgYmFzZSA9IG1heCgwLjAsIGJhc2UpO1xcbiAgICBoZWlnaHQgPSBtYXgoMC4wLCBoZWlnaHQpO1xcblxcbiAgICBmbG9hdCB0ID0gbW9kKG5vcm1hbC54LCAyLjApO1xcbiAgICBmbG9hdCB6ID0gdCA+IDAuMCA/IGhlaWdodCA6IGJhc2U7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCB6LCAxKTtcXG5cXG4gICAgdmVjMiBwb3MgPSBub3JtYWwueCA9PSAxLjAgJiYgbm9ybWFsLnkgPT0gMC4wICYmIG5vcm1hbC56ID09IDE2Mzg0LjBcXG4gICAgICAgID8gYV9wb3MgLy8gZXh0cnVzaW9uIHRvcFxcbiAgICAgICAgOiB2ZWMyKGVkZ2VkaXN0YW5jZSwgeiAqIHVfaGVpZ2h0X2ZhY3Rvcik7IC8vIGV4dHJ1c2lvbiBzaWRlXFxuXFxuICAgIHZfcG9zX2EgPSBnZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlciwgdV9waXhlbF9jb29yZF9sb3dlciwgdV9zY2FsZV9hICogdV9wYXR0ZXJuX3NpemVfYSwgdV90aWxlX3VuaXRzX3RvX3BpeGVscywgcG9zKTtcXG4gICAgdl9wb3NfYiA9IGdldF9wYXR0ZXJuX3Bvcyh1X3BpeGVsX2Nvb3JkX3VwcGVyLCB1X3BpeGVsX2Nvb3JkX2xvd2VyLCB1X3NjYWxlX2IgKiB1X3BhdHRlcm5fc2l6ZV9iLCB1X3RpbGVfdW5pdHNfdG9fcGl4ZWxzLCBwb3MpO1xcblxcbiAgICB2X2xpZ2h0aW5nID0gdmVjNCgwLjAsIDAuMCwgMC4wLCAxLjApO1xcbiAgICBmbG9hdCBkaXJlY3Rpb25hbCA9IGNsYW1wKGRvdChub3JtYWwgLyAxNjM4My4wLCB1X2xpZ2h0cG9zKSwgMC4wLCAxLjApO1xcbiAgICBkaXJlY3Rpb25hbCA9IG1peCgoMS4wIC0gdV9saWdodGludGVuc2l0eSksIG1heCgoMC41ICsgdV9saWdodGludGVuc2l0eSksIDEuMCksIGRpcmVjdGlvbmFsKTtcXG5cXG4gICAgaWYgKG5vcm1hbC55ICE9IDAuMCkge1xcbiAgICAgICAgZGlyZWN0aW9uYWwgKj0gY2xhbXAoKHQgKyBiYXNlKSAqIHBvdyhoZWlnaHQgLyAxNTAuMCwgMC41KSwgbWl4KDAuNywgMC45OCwgMS4wIC0gdV9saWdodGludGVuc2l0eSksIDEuMCk7XFxuICAgIH1cXG5cXG4gICAgdl9saWdodGluZy5yZ2IgKz0gY2xhbXAoZGlyZWN0aW9uYWwgKiB1X2xpZ2h0Y29sb3IsIG1peCh2ZWMzKDAuMCksIHZlYzMoMC4zKSwgMS4wIC0gdV9saWdodGNvbG9yKSwgdmVjMygxLjApKTtcXG59XFxuXCJ9LGV4dHJ1c2lvblRleHR1cmU6e2ZyYWdtZW50U291cmNlOlwidW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG51bmlmb3JtIGZsb2F0IHVfb3BhY2l0eTtcXG52YXJ5aW5nIHZlYzIgdl9wb3M7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl9wb3MpICogdV9vcGFjaXR5O1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgwLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfd29ybGQ7XFxuYXR0cmlidXRlIHZlYzIgYV9wb3M7XFxudmFyeWluZyB2ZWMyIHZfcG9zO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MgKiB1X3dvcmxkLCAwLCAxKTtcXG5cXG4gICAgdl9wb3MueCA9IGFfcG9zLng7XFxuICAgIHZfcG9zLnkgPSAxLjAgLSBhX3Bvcy55O1xcbn1cXG5cIn0saGlsbHNoYWRlUHJlcGFyZTp7ZnJhZ21lbnRTb3VyY2U6XCIjaWZkZWYgR0xfRVNcXG5wcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2VuZGlmXFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG52YXJ5aW5nIHZlYzIgdl9wb3M7XFxudW5pZm9ybSB2ZWMyIHVfZGltZW5zaW9uO1xcbnVuaWZvcm0gZmxvYXQgdV96b29tO1xcbnVuaWZvcm0gZmxvYXQgdV9tYXh6b29tO1xcblxcbmZsb2F0IGdldEVsZXZhdGlvbih2ZWMyIGNvb3JkLCBmbG9hdCBiaWFzKSB7XFxuICAgIC8vIENvbnZlcnQgZW5jb2RlZCBlbGV2YXRpb24gdmFsdWUgdG8gbWV0ZXJzXFxuICAgIHZlYzQgZGF0YSA9IHRleHR1cmUyRCh1X2ltYWdlLCBjb29yZCkgKiAyNTUuMDtcXG4gICAgcmV0dXJuIChkYXRhLnIgKyBkYXRhLmcgKiAyNTYuMCArIGRhdGEuYiAqIDI1Ni4wICogMjU2LjApIC8gNC4wO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIHZlYzIgZXBzaWxvbiA9IDEuMCAvIHVfZGltZW5zaW9uO1xcblxcbiAgICAvLyBxdWVyaWVkIHBpeGVsczpcXG4gICAgLy8gKy0tLS0tLS0tLS0tK1xcbiAgICAvLyB8ICAgfCAgIHwgICB8XFxuICAgIC8vIHwgYSB8IGIgfCBjIHxcXG4gICAgLy8gfCAgIHwgICB8ICAgfFxcbiAgICAvLyArLS0tLS0tLS0tLS0rXFxuICAgIC8vIHwgICB8ICAgfCAgIHxcXG4gICAgLy8gfCBkIHwgZSB8IGYgfFxcbiAgICAvLyB8ICAgfCAgIHwgICB8XFxuICAgIC8vICstLS0tLS0tLS0tLStcXG4gICAgLy8gfCAgIHwgICB8ICAgfFxcbiAgICAvLyB8IGcgfCBoIHwgaSB8XFxuICAgIC8vIHwgICB8ICAgfCAgIHxcXG4gICAgLy8gKy0tLS0tLS0tLS0tK1xcblxcbiAgICBmbG9hdCBhID0gZ2V0RWxldmF0aW9uKHZfcG9zICsgdmVjMigtZXBzaWxvbi54LCAtZXBzaWxvbi55KSwgMC4wKTtcXG4gICAgZmxvYXQgYiA9IGdldEVsZXZhdGlvbih2X3BvcyArIHZlYzIoMCwgLWVwc2lsb24ueSksIDAuMCk7XFxuICAgIGZsb2F0IGMgPSBnZXRFbGV2YXRpb24odl9wb3MgKyB2ZWMyKGVwc2lsb24ueCwgLWVwc2lsb24ueSksIDAuMCk7XFxuICAgIGZsb2F0IGQgPSBnZXRFbGV2YXRpb24odl9wb3MgKyB2ZWMyKC1lcHNpbG9uLngsIDApLCAwLjApO1xcbiAgICBmbG9hdCBlID0gZ2V0RWxldmF0aW9uKHZfcG9zLCAwLjApO1xcbiAgICBmbG9hdCBmID0gZ2V0RWxldmF0aW9uKHZfcG9zICsgdmVjMihlcHNpbG9uLngsIDApLCAwLjApO1xcbiAgICBmbG9hdCBnID0gZ2V0RWxldmF0aW9uKHZfcG9zICsgdmVjMigtZXBzaWxvbi54LCBlcHNpbG9uLnkpLCAwLjApO1xcbiAgICBmbG9hdCBoID0gZ2V0RWxldmF0aW9uKHZfcG9zICsgdmVjMigwLCBlcHNpbG9uLnkpLCAwLjApO1xcbiAgICBmbG9hdCBpID0gZ2V0RWxldmF0aW9uKHZfcG9zICsgdmVjMihlcHNpbG9uLngsIGVwc2lsb24ueSksIDAuMCk7XFxuXFxuICAgIC8vIGhlcmUgd2UgZGl2aWRlIHRoZSB4IGFuZCB5IHNsb3BlcyBieSA4ICogcGl4ZWwgc2l6ZVxcbiAgICAvLyB3aGVyZSBwaXhlbCBzaXplIChha2EgbWV0ZXJzL3BpeGVsKSBpczpcXG4gICAgLy8gY2lyY3VtZmVyZW5jZSBvZiB0aGUgd29ybGQgLyAocGl4ZWxzIHBlciB0aWxlICogbnVtYmVyIG9mIHRpbGVzKVxcbiAgICAvLyB3aGljaCBpcyBlcXVpdmFsZW50IHRvOiA4ICogNDAwNzUwMTYuNjg1NTc4NSAvICg1MTIgKiBwb3coMiwgdV96b29tKSlcXG4gICAgLy8gd2hpY2ggY2FuIGJlIHJlZHVjZWQgdG86IHBvdygyLCAxOS4yNTYxOTk3ODUyNyAtIHVfem9vbSlcXG4gICAgLy8gd2Ugd2FudCB0byB2ZXJ0aWNhbGx5IGV4YWdnZXJhdGUgdGhlIGhpbGxzaGFkaW5nIHRob3VnaCwgYmVjYXVzZSBvdGhlcndpc2VcXG4gICAgLy8gaXQgaXMgYmFyZWx5IG5vdGljZWFibGUgYXQgbG93IHpvb21zLiB0byBkbyB0aGlzLCB3ZSBtdWx0aXBseSB0aGlzIGJ5IHNvbWVcXG4gICAgLy8gc2NhbGUgZmFjdG9yIHBvdygyLCAodV96b29tIC0gdV9tYXh6b29tKSAqIGEpIHdoZXJlIGEgaXMgYW4gYXJiaXRyYXJ5IHZhbHVlXFxuICAgIC8vIEhlcmUgd2UgdXNlIGE9MC4zIHdoaWNoIHdvcmtzIG91dCB0byB0aGUgZXhwcmVzc2lvbiBiZWxvdy4gc2VlIFxcbiAgICAvLyBuaWNraWRsdWdhc2gncyBhd2Vzb21lIGJyZWFrZG93biBmb3IgbW9yZSBpbmZvXFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXBib3gvbWFwYm94LWdsLWpzL3B1bGwvNTI4NiNkaXNjdXNzaW9uX3IxNDg0MTk1NTZcXG4gICAgZmxvYXQgZXhhZ2dlcmF0aW9uID0gdV96b29tIDwgMi4wID8gMC40IDogdV96b29tIDwgNC41ID8gMC4zNSA6IDAuMztcXG5cXG4gICAgdmVjMiBkZXJpdiA9IHZlYzIoXFxuICAgICAgICAoYyArIGYgKyBmICsgaSkgLSAoYSArIGQgKyBkICsgZyksXFxuICAgICAgICAoZyArIGggKyBoICsgaSkgLSAoYSArIGIgKyBiICsgYylcXG4gICAgKSAvICBwb3coMi4wLCAodV96b29tIC0gdV9tYXh6b29tKSAqIGV4YWdnZXJhdGlvbiArIDE5LjI1NjIgLSB1X3pvb20pO1xcblxcbiAgICBnbF9GcmFnQ29sb3IgPSBjbGFtcCh2ZWM0KFxcbiAgICAgICAgZGVyaXYueCAvIDIuMCArIDAuNSxcXG4gICAgICAgIGRlcml2LnkgLyAyLjAgKyAwLjUsXFxuICAgICAgICAxLjAsXFxuICAgICAgICAxLjApLCAwLjAsIDEuMCk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcInVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG5cXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5hdHRyaWJ1dGUgdmVjMiBhX3RleHR1cmVfcG9zO1xcblxcbnZhcnlpbmcgdmVjMiB2X3BvcztcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG4gICAgdl9wb3MgPSAoYV90ZXh0dXJlX3BvcyAvIDgxOTIuMCkgLyAyLjAgKyAwLjI1O1xcbn1cXG5cIn0saGlsbHNoYWRlOntmcmFnbWVudFNvdXJjZTpcInVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxudmFyeWluZyB2ZWMyIHZfcG9zO1xcblxcbnVuaWZvcm0gdmVjMiB1X2xhdHJhbmdlO1xcbnVuaWZvcm0gdmVjMiB1X2xpZ2h0O1xcbnVuaWZvcm0gdmVjNCB1X3NoYWRvdztcXG51bmlmb3JtIHZlYzQgdV9oaWdobGlnaHQ7XFxudW5pZm9ybSB2ZWM0IHVfYWNjZW50O1xcblxcbiNkZWZpbmUgUEkgMy4xNDE1OTI2NTM1ODk3OTNcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIHZlYzQgcGl4ZWwgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl9wb3MpO1xcblxcbiAgICB2ZWMyIGRlcml2ID0gKChwaXhlbC5yZyAqIDIuMCkgLSAxLjApO1xcblxcbiAgICAvLyBXZSBkaXZpZGUgdGhlIHNsb3BlIGJ5IGEgc2NhbGUgZmFjdG9yIGJhc2VkIG9uIHRoZSBjb3NpbiBvZiB0aGUgcGl4ZWwncyBhcHByb3hpbWF0ZSBsYXRpdHVkZVxcbiAgICAvLyB0byBhY2NvdW50IGZvciBtZXJjYXRvciBwcm9qZWN0aW9uIGRpc3RvcnRpb24uIHNlZSAjNDgwNyBmb3IgZGV0YWlsc1xcbiAgICBmbG9hdCBzY2FsZUZhY3RvciA9IGNvcyhyYWRpYW5zKCh1X2xhdHJhbmdlWzBdIC0gdV9sYXRyYW5nZVsxXSkgKiAoMS4wIC0gdl9wb3MueSkgKyB1X2xhdHJhbmdlWzFdKSk7XFxuICAgIC8vIFdlIGFsc28gbXVsdGlwbHkgdGhlIHNsb3BlIGJ5IGFuIGFyYml0cmFyeSB6LWZhY3RvciBvZiAxLjI1XFxuICAgIGZsb2F0IHNsb3BlID0gYXRhbigxLjI1ICogbGVuZ3RoKGRlcml2KSAvIHNjYWxlRmFjdG9yKTtcXG4gICAgZmxvYXQgYXNwZWN0ID0gZGVyaXYueCAhPSAwLjAgPyBhdGFuKGRlcml2LnksIC1kZXJpdi54KSA6IFBJIC8gMi4wICogKGRlcml2LnkgPiAwLjAgPyAxLjAgOiAtMS4wKTtcXG5cXG4gICAgZmxvYXQgaW50ZW5zaXR5ID0gdV9saWdodC54O1xcbiAgICAvLyBXZSBhZGQgUEkgdG8gbWFrZSB0aGlzIHByb3BlcnR5IG1hdGNoIHRoZSBnbG9iYWwgbGlnaHQgb2JqZWN0LCB3aGljaCBhZGRzIFBJLzIgdG8gdGhlIGxpZ2h0J3MgYXppbXV0aGFsXFxuICAgIC8vIHBvc2l0aW9uIHByb3BlcnR5IHRvIGFjY291bnQgZm9yIDBkZWcgY29ycmVzcG9uZGluZyB0byBub3J0aC90aGUgdG9wIG9mIHRoZSB2aWV3cG9ydCBpbiB0aGUgc3R5bGUgc3BlY1xcbiAgICAvLyBhbmQgdGhlIG9yaWdpbmFsIHNoYWRlciB3YXMgd3JpdHRlbiB0byBhY2NlcHQgKC1pbGx1bWluYXRpb25EaXJlY3Rpb24gLSA5MCkgYXMgdGhlIGF6aW11dGhhbC5cXG4gICAgZmxvYXQgYXppbXV0aCA9IHVfbGlnaHQueSArIFBJO1xcblxcbiAgICAvLyBXZSBzY2FsZSB0aGUgc2xvcGUgZXhwb25lbnRpYWxseSBiYXNlZCBvbiBpbnRlbnNpdHksIHVzaW5nIGEgY2FsY3VsYXRpb24gc2ltaWxhciB0b1xcbiAgICAvLyB0aGUgZXhwb25lbnRpYWwgaW50ZXJwb2xhdGlvbiBmdW5jdGlvbiBpbiB0aGUgc3R5bGUgc3BlYzpcXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21hcGJveC9tYXBib3gtZ2wtanMvYmxvYi9tYXN0ZXIvc3JjL3N0eWxlLXNwZWMvZXhwcmVzc2lvbi9kZWZpbml0aW9ucy9pbnRlcnBvbGF0ZS5qcyNMMjE3LUwyMjhcXG4gICAgLy8gc28gdGhhdCBoaWdoZXIgaW50ZW5zaXR5IHZhbHVlcyBjcmVhdGUgbW9yZSBvcGFxdWUgaGlsbHNoYWRpbmcuXFxuICAgIGZsb2F0IGJhc2UgPSAxLjg3NSAtIGludGVuc2l0eSAqIDEuNzU7XFxuICAgIGZsb2F0IG1heFZhbHVlID0gMC41ICogUEk7XFxuICAgIGZsb2F0IHNjYWxlZFNsb3BlID0gaW50ZW5zaXR5ICE9IDAuNSA/ICgocG93KGJhc2UsIHNsb3BlKSAtIDEuMCkgLyAocG93KGJhc2UsIG1heFZhbHVlKSAtIDEuMCkpICogbWF4VmFsdWUgOiBzbG9wZTtcXG5cXG4gICAgLy8gVGhlIGFjY2VudCBjb2xvciBpcyBjYWxjdWxhdGVkIHdpdGggdGhlIGNvc2luZSBvZiB0aGUgc2xvcGUgd2hpbGUgdGhlIHNoYWRlIGNvbG9yIGlzIGNhbGN1bGF0ZWQgd2l0aCB0aGUgc2luZVxcbiAgICAvLyBzbyB0aGF0IHRoZSBhY2NlbnQgY29sb3IncyByYXRlIG9mIGNoYW5nZSBlYXNlcyBpbiB3aGlsZSB0aGUgc2hhZGUgY29sb3IncyBlYXNlcyBvdXQuXFxuICAgIGZsb2F0IGFjY2VudCA9IGNvcyhzY2FsZWRTbG9wZSk7XFxuICAgIC8vIFdlIG11bHRpcGx5IGJvdGggdGhlIGFjY2VudCBhbmQgc2hhZGUgY29sb3IgYnkgYSBjbGFtcGVkIGludGVuc2l0eSB2YWx1ZVxcbiAgICAvLyBzbyB0aGF0IGludGVuc2l0aWVzID49IDAuNSBkbyBub3QgYWRkaXRpb25hbGx5IGFmZmVjdCB0aGUgY29sb3IgdmFsdWVzXFxuICAgIC8vIHdoaWxlIGludGVuc2l0eSB2YWx1ZXMgPCAwLjUgbWFrZSB0aGUgb3ZlcmFsbCBjb2xvciBtb3JlIHRyYW5zcGFyZW50LlxcbiAgICB2ZWM0IGFjY2VudF9jb2xvciA9ICgxLjAgLSBhY2NlbnQpICogdV9hY2NlbnQgKiBjbGFtcChpbnRlbnNpdHkgKiAyLjAsIDAuMCwgMS4wKTtcXG4gICAgZmxvYXQgc2hhZGUgPSBhYnMobW9kKChhc3BlY3QgKyBhemltdXRoKSAvIFBJICsgMC41LCAyLjApIC0gMS4wKTtcXG4gICAgdmVjNCBzaGFkZV9jb2xvciA9IG1peCh1X3NoYWRvdywgdV9oaWdobGlnaHQsIHNoYWRlKSAqIHNpbihzY2FsZWRTbG9wZSkgKiBjbGFtcChpbnRlbnNpdHkgKiAyLjAsIDAuMCwgMS4wKTtcXG4gICAgZ2xfRnJhZ0NvbG9yID0gYWNjZW50X2NvbG9yICogKDEuMCAtIHNoYWRlX2NvbG9yLmEpICsgc2hhZGVfY29sb3I7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcInVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG5cXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5hdHRyaWJ1dGUgdmVjMiBhX3RleHR1cmVfcG9zO1xcblxcbnZhcnlpbmcgdmVjMiB2X3BvcztcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG4gICAgdl9wb3MgPSBhX3RleHR1cmVfcG9zIC8gODE5Mi4wO1xcbn1cXG5cIn0sbGluZTp7ZnJhZ21lbnRTb3VyY2U6XCIjcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxudmFyeWluZyB2ZWMyIHZfd2lkdGgyO1xcbnZhcnlpbmcgdmVjMiB2X25vcm1hbDtcXG52YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBvZiB0aGUgcGl4ZWwgZnJvbSB0aGUgbGluZSBpbiBwaXhlbHMuXFxuICAgIGZsb2F0IGRpc3QgPSBsZW5ndGgodl9ub3JtYWwpICogdl93aWR0aDIucztcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhbnRpYWxpYXNpbmcgZmFkZSBmYWN0b3IuIFRoaXMgaXMgZWl0aGVyIHdoZW4gZmFkaW5nIGluXFxuICAgIC8vIHRoZSBsaW5lIGluIGNhc2Ugb2YgYW4gb2Zmc2V0IGxpbmUgKHZfd2lkdGgyLnQpIG9yIHdoZW4gZmFkaW5nIG91dFxcbiAgICAvLyAodl93aWR0aDIucylcXG4gICAgZmxvYXQgYmx1cjIgPSAoYmx1ciArIDEuMCAvIERFVklDRV9QSVhFTF9SQVRJTykgKiB2X2dhbW1hX3NjYWxlO1xcbiAgICBmbG9hdCBhbHBoYSA9IGNsYW1wKG1pbihkaXN0IC0gKHZfd2lkdGgyLnQgLSBibHVyMiksIHZfd2lkdGgyLnMgLSBkaXN0KSAvIGJsdXIyLCAwLjAsIDEuMCk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yICogKGFscGhhICogb3BhY2l0eSk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcIlxcblxcbi8vIHRoZSBkaXN0YW5jZSBvdmVyIHdoaWNoIHRoZSBsaW5lIGVkZ2UgZmFkZXMgb3V0Llxcbi8vIFJldGluYSBkZXZpY2VzIG5lZWQgYSBzbWFsbGVyIGRpc3RhbmNlIHRvIGF2b2lkIGFsaWFzaW5nLlxcbiNkZWZpbmUgQU5USUFMSUFTSU5HIDEuMCAvIERFVklDRV9QSVhFTF9SQVRJTyAvIDIuMFxcblxcbi8vIGZsb29yKDEyNyAvIDIpID09IDYzLjBcXG4vLyB0aGUgbWF4aW11bSBhbGxvd2VkIG1pdGVyIGxpbWl0IGlzIDIuMCBhdCB0aGUgbW9tZW50LiB0aGUgZXh0cnVkZSBub3JtYWwgaXNcXG4vLyBzdG9yZWQgaW4gYSBieXRlICgtMTI4Li4xMjcpLiB3ZSBzY2FsZSByZWd1bGFyIG5vcm1hbHMgdXAgdG8gbGVuZ3RoIDYzLCBidXRcXG4vLyB0aGVyZSBhcmUgYWxzbyBcXFwic3BlY2lhbFxcXCIgbm9ybWFscyB0aGF0IGhhdmUgYSBiaWdnZXIgbGVuZ3RoIChvZiB1cCB0byAxMjYgaW5cXG4vLyB0aGlzIGNhc2UpLlxcbi8vICNkZWZpbmUgc2NhbGUgNjMuMFxcbiNkZWZpbmUgc2NhbGUgMC4wMTU4NzMwMTZcXG5cXG5hdHRyaWJ1dGUgdmVjNCBhX3Bvc19ub3JtYWw7XFxuYXR0cmlidXRlIHZlYzQgYV9kYXRhO1xcblxcbnVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG51bmlmb3JtIG1lZGl1bXAgZmxvYXQgdV9yYXRpbztcXG51bmlmb3JtIHZlYzIgdV9nbF91bml0c190b19waXhlbHM7XFxuXFxudmFyeWluZyB2ZWMyIHZfbm9ybWFsO1xcbnZhcnlpbmcgdmVjMiB2X3dpZHRoMjtcXG52YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7XFxudmFyeWluZyBoaWdocCBmbG9hdCB2X2xpbmVzb2ZhcjtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9mZnNldFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvZmZzZXRcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcblxcbiAgICB2ZWMyIGFfZXh0cnVkZSA9IGFfZGF0YS54eSAtIDEyOC4wO1xcbiAgICBmbG9hdCBhX2RpcmVjdGlvbiA9IG1vZChhX2RhdGEueiwgNC4wKSAtIDEuMDtcXG5cXG4gICAgdl9saW5lc29mYXIgPSAoZmxvb3IoYV9kYXRhLnogLyA0LjApICsgYV9kYXRhLncgKiA2NC4wKSAqIDIuMDtcXG5cXG4gICAgdmVjMiBwb3MgPSBhX3Bvc19ub3JtYWwueHk7XFxuXFxuICAgIC8vIHggaXMgMSBpZiBpdCdzIGEgcm91bmQgY2FwLCAwIG90aGVyd2lzZVxcbiAgICAvLyB5IGlzIDEgaWYgdGhlIG5vcm1hbCBwb2ludHMgdXAsIGFuZCAtMSBpZiBpdCBwb2ludHMgZG93blxcbiAgICBtZWRpdW1wIHZlYzIgbm9ybWFsID0gYV9wb3Nfbm9ybWFsLnp3O1xcbiAgICB2X25vcm1hbCA9IG5vcm1hbDtcXG5cXG4gICAgLy8gdGhlc2UgdHJhbnNmb3JtYXRpb25zIHVzZWQgdG8gYmUgYXBwbGllZCBpbiB0aGUgSlMgYW5kIG5hdGl2ZSBjb2RlIGJhc2VzLlxcbiAgICAvLyBtb3ZlZCB0aGVtIGludG8gdGhlIHNoYWRlciBmb3IgY2xhcml0eSBhbmQgc2ltcGxpY2l0eS5cXG4gICAgZ2Fwd2lkdGggPSBnYXB3aWR0aCAvIDIuMDtcXG4gICAgZmxvYXQgaGFsZndpZHRoID0gd2lkdGggLyAyLjA7XFxuICAgIG9mZnNldCA9IC0xLjAgKiBvZmZzZXQ7XFxuXFxuICAgIGZsb2F0IGluc2V0ID0gZ2Fwd2lkdGggKyAoZ2Fwd2lkdGggPiAwLjAgPyBBTlRJQUxJQVNJTkcgOiAwLjApO1xcbiAgICBmbG9hdCBvdXRzZXQgPSBnYXB3aWR0aCArIGhhbGZ3aWR0aCAqIChnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkgKyBBTlRJQUxJQVNJTkc7XFxuXFxuICAgIC8vIFNjYWxlIHRoZSBleHRydXNpb24gdmVjdG9yIGRvd24gdG8gYSBub3JtYWwgYW5kIHRoZW4gdXAgYnkgdGhlIGxpbmUgd2lkdGhcXG4gICAgLy8gb2YgdGhpcyB2ZXJ0ZXguXFxuICAgIG1lZGl1bXAgdmVjMiBkaXN0ID0gb3V0c2V0ICogYV9leHRydWRlICogc2NhbGU7XFxuXFxuICAgIC8vIENhbGN1bGF0ZSB0aGUgb2Zmc2V0IHdoZW4gZHJhd2luZyBhIGxpbmUgdGhhdCBpcyB0byB0aGUgc2lkZSBvZiB0aGUgYWN0dWFsIGxpbmUuXFxuICAgIC8vIFdlIGRvIHRoaXMgYnkgY3JlYXRpbmcgYSB2ZWN0b3IgdGhhdCBwb2ludHMgdG93YXJkcyB0aGUgZXh0cnVkZSwgYnV0IHJvdGF0ZVxcbiAgICAvLyBpdCB3aGVuIHdlJ3JlIGRyYXdpbmcgcm91bmQgZW5kIHBvaW50cyAoYV9kaXJlY3Rpb24gPSAtMSBvciAxKSBzaW5jZSB0aGVpclxcbiAgICAvLyBleHRydWRlIHZlY3RvciBwb2ludHMgaW4gYW5vdGhlciBkaXJlY3Rpb24uXFxuICAgIG1lZGl1bXAgZmxvYXQgdSA9IDAuNSAqIGFfZGlyZWN0aW9uO1xcbiAgICBtZWRpdW1wIGZsb2F0IHQgPSAxLjAgLSBhYnModSk7XFxuICAgIG1lZGl1bXAgdmVjMiBvZmZzZXQyID0gb2Zmc2V0ICogYV9leHRydWRlICogc2NhbGUgKiBub3JtYWwueSAqIG1hdDIodCwgLXUsIHUsIHQpO1xcblxcbiAgICB2ZWM0IHByb2plY3RlZF9leHRydWRlID0gdV9tYXRyaXggKiB2ZWM0KGRpc3QgLyB1X3JhdGlvLCAwLjAsIDAuMCk7XFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KHBvcyArIG9mZnNldDIgLyB1X3JhdGlvLCAwLjAsIDEuMCkgKyBwcm9qZWN0ZWRfZXh0cnVkZTtcXG5cXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIHRoZSBwZXJzcGVjdGl2ZSB2aWV3IHNxdWlzaGVzIG9yIHN0cmV0Y2hlcyB0aGUgZXh0cnVkZVxcbiAgICBmbG9hdCBleHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlID0gbGVuZ3RoKGRpc3QpO1xcbiAgICBmbG9hdCBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlID0gbGVuZ3RoKHByb2plY3RlZF9leHRydWRlLnh5IC8gZ2xfUG9zaXRpb24udyAqIHVfZ2xfdW5pdHNfdG9fcGl4ZWxzKTtcXG4gICAgdl9nYW1tYV9zY2FsZSA9IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUgLyBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlO1xcblxcbiAgICB2X3dpZHRoMiA9IHZlYzIob3V0c2V0LCBpbnNldCk7XFxufVxcblwifSxsaW5lR3JhZGllbnQ6e2ZyYWdtZW50U291cmNlOlwiXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuXFxudmFyeWluZyB2ZWMyIHZfd2lkdGgyO1xcbnZhcnlpbmcgdmVjMiB2X25vcm1hbDtcXG52YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7XFxudmFyeWluZyBoaWdocCBmbG9hdCB2X2xpbmVwcm9ncmVzcztcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBvZiB0aGUgcGl4ZWwgZnJvbSB0aGUgbGluZSBpbiBwaXhlbHMuXFxuICAgIGZsb2F0IGRpc3QgPSBsZW5ndGgodl9ub3JtYWwpICogdl93aWR0aDIucztcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhbnRpYWxpYXNpbmcgZmFkZSBmYWN0b3IuIFRoaXMgaXMgZWl0aGVyIHdoZW4gZmFkaW5nIGluXFxuICAgIC8vIHRoZSBsaW5lIGluIGNhc2Ugb2YgYW4gb2Zmc2V0IGxpbmUgKHZfd2lkdGgyLnQpIG9yIHdoZW4gZmFkaW5nIG91dFxcbiAgICAvLyAodl93aWR0aDIucylcXG4gICAgZmxvYXQgYmx1cjIgPSAoYmx1ciArIDEuMCAvIERFVklDRV9QSVhFTF9SQVRJTykgKiB2X2dhbW1hX3NjYWxlO1xcbiAgICBmbG9hdCBhbHBoYSA9IGNsYW1wKG1pbihkaXN0IC0gKHZfd2lkdGgyLnQgLSBibHVyMiksIHZfd2lkdGgyLnMgLSBkaXN0KSAvIGJsdXIyLCAwLjAsIDEuMCk7XFxuXFxuICAgIC8vIEZvciBncmFkaWVudCBsaW5lcywgdl9saW5lcHJvZ3Jlc3MgaXMgdGhlIHJhdGlvIGFsb25nIHRoZSBlbnRpcmUgbGluZSxcXG4gICAgLy8gc2NhbGVkIHRvIFswLCAyXjE1KSwgYW5kIHRoZSBncmFkaWVudCByYW1wIGlzIHN0b3JlZCBpbiBhIHRleHR1cmUuXFxuICAgIHZlYzQgY29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdmVjMih2X2xpbmVwcm9ncmVzcywgMC41KSk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yICogKGFscGhhICogb3BhY2l0eSk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcIlxcbi8vIHRoZSBhdHRyaWJ1dGUgY29udmV5aW5nIHByb2dyZXNzIGFsb25nIGEgbGluZSBpcyBzY2FsZWQgdG8gWzAsIDJeMTUpXFxuI2RlZmluZSBNQVhfTElORV9ESVNUQU5DRSAzMjc2Ny4wXFxuXFxuLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXFxuLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXFxuI2RlZmluZSBBTlRJQUxJQVNJTkcgMS4wIC8gREVWSUNFX1BJWEVMX1JBVElPIC8gMi4wXFxuXFxuLy8gZmxvb3IoMTI3IC8gMikgPT0gNjMuMFxcbi8vIHRoZSBtYXhpbXVtIGFsbG93ZWQgbWl0ZXIgbGltaXQgaXMgMi4wIGF0IHRoZSBtb21lbnQuIHRoZSBleHRydWRlIG5vcm1hbCBpc1xcbi8vIHN0b3JlZCBpbiBhIGJ5dGUgKC0xMjguLjEyNykuIHdlIHNjYWxlIHJlZ3VsYXIgbm9ybWFscyB1cCB0byBsZW5ndGggNjMsIGJ1dFxcbi8vIHRoZXJlIGFyZSBhbHNvIFxcXCJzcGVjaWFsXFxcIiBub3JtYWxzIHRoYXQgaGF2ZSBhIGJpZ2dlciBsZW5ndGggKG9mIHVwIHRvIDEyNiBpblxcbi8vIHRoaXMgY2FzZSkuXFxuLy8gI2RlZmluZSBzY2FsZSA2My4wXFxuI2RlZmluZSBzY2FsZSAwLjAxNTg3MzAxNlxcblxcbmF0dHJpYnV0ZSB2ZWM0IGFfcG9zX25vcm1hbDtcXG5hdHRyaWJ1dGUgdmVjNCBhX2RhdGE7XFxuXFxudW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gbWVkaXVtcCBmbG9hdCB1X3JhdGlvO1xcbnVuaWZvcm0gdmVjMiB1X2dsX3VuaXRzX3RvX3BpeGVscztcXG5cXG52YXJ5aW5nIHZlYzIgdl9ub3JtYWw7XFxudmFyeWluZyB2ZWMyIHZfd2lkdGgyO1xcbnZhcnlpbmcgZmxvYXQgdl9nYW1tYV9zY2FsZTtcXG52YXJ5aW5nIGhpZ2hwIGZsb2F0IHZfbGluZXByb2dyZXNzO1xcblxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb2Zmc2V0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvZmZzZXRcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcblxcbiAgICB2ZWMyIGFfZXh0cnVkZSA9IGFfZGF0YS54eSAtIDEyOC4wO1xcbiAgICBmbG9hdCBhX2RpcmVjdGlvbiA9IG1vZChhX2RhdGEueiwgNC4wKSAtIDEuMDtcXG5cXG4gICAgdl9saW5lcHJvZ3Jlc3MgPSAoZmxvb3IoYV9kYXRhLnogLyA0LjApICsgYV9kYXRhLncgKiA2NC4wKSAqIDIuMCAvIE1BWF9MSU5FX0RJU1RBTkNFO1xcblxcbiAgICB2ZWMyIHBvcyA9IGFfcG9zX25vcm1hbC54eTtcXG5cXG4gICAgLy8geCBpcyAxIGlmIGl0J3MgYSByb3VuZCBjYXAsIDAgb3RoZXJ3aXNlXFxuICAgIC8vIHkgaXMgMSBpZiB0aGUgbm9ybWFsIHBvaW50cyB1cCwgYW5kIC0xIGlmIGl0IHBvaW50cyBkb3duXFxuICAgIG1lZGl1bXAgdmVjMiBub3JtYWwgPSBhX3Bvc19ub3JtYWwuenc7XFxuICAgIHZfbm9ybWFsID0gbm9ybWFsO1xcblxcbiAgICAvLyB0aGVzZSB0cmFuc2Zvcm1hdGlvbnMgdXNlZCB0byBiZSBhcHBsaWVkIGluIHRoZSBKUyBhbmQgbmF0aXZlIGNvZGUgYmFzZXMuXFxuICAgIC8vIG1vdmVkIHRoZW0gaW50byB0aGUgc2hhZGVyIGZvciBjbGFyaXR5IGFuZCBzaW1wbGljaXR5LlxcbiAgICBnYXB3aWR0aCA9IGdhcHdpZHRoIC8gMi4wO1xcbiAgICBmbG9hdCBoYWxmd2lkdGggPSB3aWR0aCAvIDIuMDtcXG4gICAgb2Zmc2V0ID0gLTEuMCAqIG9mZnNldDtcXG5cXG4gICAgZmxvYXQgaW5zZXQgPSBnYXB3aWR0aCArIChnYXB3aWR0aCA+IDAuMCA/IEFOVElBTElBU0lORyA6IDAuMCk7XFxuICAgIGZsb2F0IG91dHNldCA9IGdhcHdpZHRoICsgaGFsZndpZHRoICogKGdhcHdpZHRoID4gMC4wID8gMi4wIDogMS4wKSArIEFOVElBTElBU0lORztcXG5cXG4gICAgLy8gU2NhbGUgdGhlIGV4dHJ1c2lvbiB2ZWN0b3IgZG93biB0byBhIG5vcm1hbCBhbmQgdGhlbiB1cCBieSB0aGUgbGluZSB3aWR0aFxcbiAgICAvLyBvZiB0aGlzIHZlcnRleC5cXG4gICAgbWVkaXVtcCB2ZWMyIGRpc3QgPSBvdXRzZXQgKiBhX2V4dHJ1ZGUgKiBzY2FsZTtcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBvZmZzZXQgd2hlbiBkcmF3aW5nIGEgbGluZSB0aGF0IGlzIHRvIHRoZSBzaWRlIG9mIHRoZSBhY3R1YWwgbGluZS5cXG4gICAgLy8gV2UgZG8gdGhpcyBieSBjcmVhdGluZyBhIHZlY3RvciB0aGF0IHBvaW50cyB0b3dhcmRzIHRoZSBleHRydWRlLCBidXQgcm90YXRlXFxuICAgIC8vIGl0IHdoZW4gd2UncmUgZHJhd2luZyByb3VuZCBlbmQgcG9pbnRzIChhX2RpcmVjdGlvbiA9IC0xIG9yIDEpIHNpbmNlIHRoZWlyXFxuICAgIC8vIGV4dHJ1ZGUgdmVjdG9yIHBvaW50cyBpbiBhbm90aGVyIGRpcmVjdGlvbi5cXG4gICAgbWVkaXVtcCBmbG9hdCB1ID0gMC41ICogYV9kaXJlY3Rpb247XFxuICAgIG1lZGl1bXAgZmxvYXQgdCA9IDEuMCAtIGFicyh1KTtcXG4gICAgbWVkaXVtcCB2ZWMyIG9mZnNldDIgPSBvZmZzZXQgKiBhX2V4dHJ1ZGUgKiBzY2FsZSAqIG5vcm1hbC55ICogbWF0Mih0LCAtdSwgdSwgdCk7XFxuXFxuICAgIHZlYzQgcHJvamVjdGVkX2V4dHJ1ZGUgPSB1X21hdHJpeCAqIHZlYzQoZGlzdCAvIHVfcmF0aW8sIDAuMCwgMC4wKTtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQocG9zICsgb2Zmc2V0MiAvIHVfcmF0aW8sIDAuMCwgMS4wKSArIHByb2plY3RlZF9leHRydWRlO1xcblxcbiAgICAvLyBjYWxjdWxhdGUgaG93IG11Y2ggdGhlIHBlcnNwZWN0aXZlIHZpZXcgc3F1aXNoZXMgb3Igc3RyZXRjaGVzIHRoZSBleHRydWRlXFxuICAgIGZsb2F0IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUgPSBsZW5ndGgoZGlzdCk7XFxuICAgIGZsb2F0IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhfcGVyc3BlY3RpdmUgPSBsZW5ndGgocHJvamVjdGVkX2V4dHJ1ZGUueHkgLyBnbF9Qb3NpdGlvbi53ICogdV9nbF91bml0c190b19waXhlbHMpO1xcbiAgICB2X2dhbW1hX3NjYWxlID0gZXh0cnVkZV9sZW5ndGhfd2l0aG91dF9wZXJzcGVjdGl2ZSAvIGV4dHJ1ZGVfbGVuZ3RoX3dpdGhfcGVyc3BlY3RpdmU7XFxuXFxuICAgIHZfd2lkdGgyID0gdmVjMihvdXRzZXQsIGluc2V0KTtcXG59XFxuXCJ9LGxpbmVQYXR0ZXJuOntmcmFnbWVudFNvdXJjZTpcInVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9hO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fc2l6ZV9iO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fdGxfYTtcXG51bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyX2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybl90bF9iO1xcbnVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fYnJfYjtcXG51bmlmb3JtIHZlYzIgdV90ZXhzaXplO1xcbnVuaWZvcm0gZmxvYXQgdV9mYWRlO1xcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuXFxudmFyeWluZyB2ZWMyIHZfbm9ybWFsO1xcbnZhcnlpbmcgdmVjMiB2X3dpZHRoMjtcXG52YXJ5aW5nIGZsb2F0IHZfbGluZXNvZmFyO1xcbnZhcnlpbmcgZmxvYXQgdl9nYW1tYV9zY2FsZTtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxuICAgIC8vIENhbGN1bGF0ZSB0aGUgZGlzdGFuY2Ugb2YgdGhlIHBpeGVsIGZyb20gdGhlIGxpbmUgaW4gcGl4ZWxzLlxcbiAgICBmbG9hdCBkaXN0ID0gbGVuZ3RoKHZfbm9ybWFsKSAqIHZfd2lkdGgyLnM7XFxuXFxuICAgIC8vIENhbGN1bGF0ZSB0aGUgYW50aWFsaWFzaW5nIGZhZGUgZmFjdG9yLiBUaGlzIGlzIGVpdGhlciB3aGVuIGZhZGluZyBpblxcbiAgICAvLyB0aGUgbGluZSBpbiBjYXNlIG9mIGFuIG9mZnNldCBsaW5lICh2X3dpZHRoMi50KSBvciB3aGVuIGZhZGluZyBvdXRcXG4gICAgLy8gKHZfd2lkdGgyLnMpXFxuICAgIGZsb2F0IGJsdXIyID0gKGJsdXIgKyAxLjAgLyBERVZJQ0VfUElYRUxfUkFUSU8pICogdl9nYW1tYV9zY2FsZTtcXG4gICAgZmxvYXQgYWxwaGEgPSBjbGFtcChtaW4oZGlzdCAtICh2X3dpZHRoMi50IC0gYmx1cjIpLCB2X3dpZHRoMi5zIC0gZGlzdCkgLyBibHVyMiwgMC4wLCAxLjApO1xcblxcbiAgICBmbG9hdCB4X2EgPSBtb2Qodl9saW5lc29mYXIgLyB1X3BhdHRlcm5fc2l6ZV9hLngsIDEuMCk7XFxuICAgIGZsb2F0IHhfYiA9IG1vZCh2X2xpbmVzb2ZhciAvIHVfcGF0dGVybl9zaXplX2IueCwgMS4wKTtcXG5cXG4gICAgLy8gdl9ub3JtYWwueSBpcyAwIGF0IHRoZSBtaWRwb2ludCBvZiB0aGUgbGluZSwgLTEgYXQgdGhlIGxvd2VyIGVkZ2UsIDEgYXQgdGhlIHVwcGVyIGVkZ2VcXG4gICAgLy8gd2UgY2xhbXAgdGhlIGxpbmUgd2lkdGggb3V0c2V0IHRvIGJlIGJldHdlZW4gMCBhbmQgaGFsZiB0aGUgcGF0dGVybiBoZWlnaHQgcGx1cyBwYWRkaW5nICgyLjApXFxuICAgIC8vIHRvIGVuc3VyZSB3ZSBkb24ndCBzYW1wbGUgb3V0c2lkZSB0aGUgZGVzaWduYXRlZCBzeW1ib2wgb24gdGhlIHNwcml0ZSBzaGVldC5cXG4gICAgLy8gMC41IGlzIGFkZGVkIHRvIHNoaWZ0IHRoZSBjb21wb25lbnQgdG8gYmUgYm91bmRlZCBiZXR3ZWVuIDAgYW5kIDEgZm9yIGludGVycG9sYXRpb24gb2ZcXG4gICAgLy8gdGhlIHRleHR1cmUgY29vcmRpbmF0ZVxcbiAgICBmbG9hdCB5X2EgPSAwLjUgKyAodl9ub3JtYWwueSAqIGNsYW1wKHZfd2lkdGgyLnMsIDAuMCwgKHVfcGF0dGVybl9zaXplX2EueSArIDIuMCkgLyAyLjApIC8gdV9wYXR0ZXJuX3NpemVfYS55KTtcXG4gICAgZmxvYXQgeV9iID0gMC41ICsgKHZfbm9ybWFsLnkgKiBjbGFtcCh2X3dpZHRoMi5zLCAwLjAsICh1X3BhdHRlcm5fc2l6ZV9iLnkgKyAyLjApIC8gMi4wKSAvIHVfcGF0dGVybl9zaXplX2IueSk7XFxuICAgIHZlYzIgcG9zX2EgPSBtaXgodV9wYXR0ZXJuX3RsX2EgLyB1X3RleHNpemUsIHVfcGF0dGVybl9icl9hIC8gdV90ZXhzaXplLCB2ZWMyKHhfYSwgeV9hKSk7XFxuICAgIHZlYzIgcG9zX2IgPSBtaXgodV9wYXR0ZXJuX3RsX2IgLyB1X3RleHNpemUsIHVfcGF0dGVybl9icl9iIC8gdV90ZXhzaXplLCB2ZWMyKHhfYiwgeV9iKSk7XFxuXFxuICAgIHZlYzQgY29sb3IgPSBtaXgodGV4dHVyZTJEKHVfaW1hZ2UsIHBvc19hKSwgdGV4dHVyZTJEKHVfaW1hZ2UsIHBvc19iKSwgdV9mYWRlKTtcXG5cXG4gICAgZ2xfRnJhZ0NvbG9yID0gY29sb3IgKiBhbHBoYSAqIG9wYWNpdHk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcIi8vIGZsb29yKDEyNyAvIDIpID09IDYzLjBcXG4vLyB0aGUgbWF4aW11bSBhbGxvd2VkIG1pdGVyIGxpbWl0IGlzIDIuMCBhdCB0aGUgbW9tZW50LiB0aGUgZXh0cnVkZSBub3JtYWwgaXNcXG4vLyBzdG9yZWQgaW4gYSBieXRlICgtMTI4Li4xMjcpLiB3ZSBzY2FsZSByZWd1bGFyIG5vcm1hbHMgdXAgdG8gbGVuZ3RoIDYzLCBidXRcXG4vLyB0aGVyZSBhcmUgYWxzbyBcXFwic3BlY2lhbFxcXCIgbm9ybWFscyB0aGF0IGhhdmUgYSBiaWdnZXIgbGVuZ3RoIChvZiB1cCB0byAxMjYgaW5cXG4vLyB0aGlzIGNhc2UpLlxcbi8vICNkZWZpbmUgc2NhbGUgNjMuMFxcbiNkZWZpbmUgc2NhbGUgMC4wMTU4NzMwMTZcXG5cXG4vLyBXZSBzY2FsZSB0aGUgZGlzdGFuY2UgYmVmb3JlIGFkZGluZyBpdCB0byB0aGUgYnVmZmVycyBzbyB0aGF0IHdlIGNhbiBzdG9yZVxcbi8vIGxvbmcgZGlzdGFuY2VzIGZvciBsb25nIHNlZ21lbnRzLiBVc2UgdGhpcyB2YWx1ZSB0byB1bnNjYWxlIHRoZSBkaXN0YW5jZS5cXG4jZGVmaW5lIExJTkVfRElTVEFOQ0VfU0NBTEUgMi4wXFxuXFxuLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXFxuLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXFxuI2RlZmluZSBBTlRJQUxJQVNJTkcgMS4wIC8gREVWSUNFX1BJWEVMX1JBVElPIC8gMi4wXFxuXFxuYXR0cmlidXRlIHZlYzQgYV9wb3Nfbm9ybWFsO1xcbmF0dHJpYnV0ZSB2ZWM0IGFfZGF0YTtcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSBtZWRpdW1wIGZsb2F0IHVfcmF0aW87XFxudW5pZm9ybSB2ZWMyIHVfZ2xfdW5pdHNfdG9fcGl4ZWxzO1xcblxcbnZhcnlpbmcgdmVjMiB2X25vcm1hbDtcXG52YXJ5aW5nIHZlYzIgdl93aWR0aDI7XFxudmFyeWluZyBmbG9hdCB2X2xpbmVzb2ZhcjtcXG52YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvZmZzZXRcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgd2lkdGhcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvZmZzZXRcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCBnYXB3aWR0aFxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuXFxuICAgIHZlYzIgYV9leHRydWRlID0gYV9kYXRhLnh5IC0gMTI4LjA7XFxuICAgIGZsb2F0IGFfZGlyZWN0aW9uID0gbW9kKGFfZGF0YS56LCA0LjApIC0gMS4wO1xcbiAgICBmbG9hdCBhX2xpbmVzb2ZhciA9IChmbG9vcihhX2RhdGEueiAvIDQuMCkgKyBhX2RhdGEudyAqIDY0LjApICogTElORV9ESVNUQU5DRV9TQ0FMRTtcXG5cXG4gICAgdmVjMiBwb3MgPSBhX3Bvc19ub3JtYWwueHk7XFxuXFxuICAgIC8vIHggaXMgMSBpZiBpdCdzIGEgcm91bmQgY2FwLCAwIG90aGVyd2lzZVxcbiAgICAvLyB5IGlzIDEgaWYgdGhlIG5vcm1hbCBwb2ludHMgdXAsIGFuZCAtMSBpZiBpdCBwb2ludHMgZG93blxcbiAgICBtZWRpdW1wIHZlYzIgbm9ybWFsID0gYV9wb3Nfbm9ybWFsLnp3O1xcbiAgICB2X25vcm1hbCA9IG5vcm1hbDtcXG5cXG4gICAgLy8gdGhlc2UgdHJhbnNmb3JtYXRpb25zIHVzZWQgdG8gYmUgYXBwbGllZCBpbiB0aGUgSlMgYW5kIG5hdGl2ZSBjb2RlIGJhc2VzLlxcbiAgICAvLyBtb3ZlZCB0aGVtIGludG8gdGhlIHNoYWRlciBmb3IgY2xhcml0eSBhbmQgc2ltcGxpY2l0eS5cXG4gICAgZ2Fwd2lkdGggPSBnYXB3aWR0aCAvIDIuMDtcXG4gICAgZmxvYXQgaGFsZndpZHRoID0gd2lkdGggLyAyLjA7XFxuICAgIG9mZnNldCA9IC0xLjAgKiBvZmZzZXQ7XFxuXFxuICAgIGZsb2F0IGluc2V0ID0gZ2Fwd2lkdGggKyAoZ2Fwd2lkdGggPiAwLjAgPyBBTlRJQUxJQVNJTkcgOiAwLjApO1xcbiAgICBmbG9hdCBvdXRzZXQgPSBnYXB3aWR0aCArIGhhbGZ3aWR0aCAqIChnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkgKyBBTlRJQUxJQVNJTkc7XFxuXFxuICAgIC8vIFNjYWxlIHRoZSBleHRydXNpb24gdmVjdG9yIGRvd24gdG8gYSBub3JtYWwgYW5kIHRoZW4gdXAgYnkgdGhlIGxpbmUgd2lkdGhcXG4gICAgLy8gb2YgdGhpcyB2ZXJ0ZXguXFxuICAgIG1lZGl1bXAgdmVjMiBkaXN0ID0gb3V0c2V0ICogYV9leHRydWRlICogc2NhbGU7XFxuXFxuICAgIC8vIENhbGN1bGF0ZSB0aGUgb2Zmc2V0IHdoZW4gZHJhd2luZyBhIGxpbmUgdGhhdCBpcyB0byB0aGUgc2lkZSBvZiB0aGUgYWN0dWFsIGxpbmUuXFxuICAgIC8vIFdlIGRvIHRoaXMgYnkgY3JlYXRpbmcgYSB2ZWN0b3IgdGhhdCBwb2ludHMgdG93YXJkcyB0aGUgZXh0cnVkZSwgYnV0IHJvdGF0ZVxcbiAgICAvLyBpdCB3aGVuIHdlJ3JlIGRyYXdpbmcgcm91bmQgZW5kIHBvaW50cyAoYV9kaXJlY3Rpb24gPSAtMSBvciAxKSBzaW5jZSB0aGVpclxcbiAgICAvLyBleHRydWRlIHZlY3RvciBwb2ludHMgaW4gYW5vdGhlciBkaXJlY3Rpb24uXFxuICAgIG1lZGl1bXAgZmxvYXQgdSA9IDAuNSAqIGFfZGlyZWN0aW9uO1xcbiAgICBtZWRpdW1wIGZsb2F0IHQgPSAxLjAgLSBhYnModSk7XFxuICAgIG1lZGl1bXAgdmVjMiBvZmZzZXQyID0gb2Zmc2V0ICogYV9leHRydWRlICogc2NhbGUgKiBub3JtYWwueSAqIG1hdDIodCwgLXUsIHUsIHQpO1xcblxcbiAgICB2ZWM0IHByb2plY3RlZF9leHRydWRlID0gdV9tYXRyaXggKiB2ZWM0KGRpc3QgLyB1X3JhdGlvLCAwLjAsIDAuMCk7XFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KHBvcyArIG9mZnNldDIgLyB1X3JhdGlvLCAwLjAsIDEuMCkgKyBwcm9qZWN0ZWRfZXh0cnVkZTtcXG5cXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIHRoZSBwZXJzcGVjdGl2ZSB2aWV3IHNxdWlzaGVzIG9yIHN0cmV0Y2hlcyB0aGUgZXh0cnVkZVxcbiAgICBmbG9hdCBleHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlID0gbGVuZ3RoKGRpc3QpO1xcbiAgICBmbG9hdCBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlID0gbGVuZ3RoKHByb2plY3RlZF9leHRydWRlLnh5IC8gZ2xfUG9zaXRpb24udyAqIHVfZ2xfdW5pdHNfdG9fcGl4ZWxzKTtcXG4gICAgdl9nYW1tYV9zY2FsZSA9IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUgLyBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlO1xcblxcbiAgICB2X2xpbmVzb2ZhciA9IGFfbGluZXNvZmFyO1xcbiAgICB2X3dpZHRoMiA9IHZlYzIob3V0c2V0LCBpbnNldCk7XFxufVxcblwifSxsaW5lU0RGOntmcmFnbWVudFNvdXJjZTpcIlxcbnVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxudW5pZm9ybSBmbG9hdCB1X3NkZmdhbW1hO1xcbnVuaWZvcm0gZmxvYXQgdV9taXg7XFxuXFxudmFyeWluZyB2ZWMyIHZfbm9ybWFsO1xcbnZhcnlpbmcgdmVjMiB2X3dpZHRoMjtcXG52YXJ5aW5nIHZlYzIgdl90ZXhfYTtcXG52YXJ5aW5nIHZlYzIgdl90ZXhfYjtcXG52YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBmbG9vcndpZHRoXFxuXFxudm9pZCBtYWluKCkge1xcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBvZiB0aGUgcGl4ZWwgZnJvbSB0aGUgbGluZSBpbiBwaXhlbHMuXFxuICAgIGZsb2F0IGRpc3QgPSBsZW5ndGgodl9ub3JtYWwpICogdl93aWR0aDIucztcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhbnRpYWxpYXNpbmcgZmFkZSBmYWN0b3IuIFRoaXMgaXMgZWl0aGVyIHdoZW4gZmFkaW5nIGluXFxuICAgIC8vIHRoZSBsaW5lIGluIGNhc2Ugb2YgYW4gb2Zmc2V0IGxpbmUgKHZfd2lkdGgyLnQpIG9yIHdoZW4gZmFkaW5nIG91dFxcbiAgICAvLyAodl93aWR0aDIucylcXG4gICAgZmxvYXQgYmx1cjIgPSAoYmx1ciArIDEuMCAvIERFVklDRV9QSVhFTF9SQVRJTykgKiB2X2dhbW1hX3NjYWxlO1xcbiAgICBmbG9hdCBhbHBoYSA9IGNsYW1wKG1pbihkaXN0IC0gKHZfd2lkdGgyLnQgLSBibHVyMiksIHZfd2lkdGgyLnMgLSBkaXN0KSAvIGJsdXIyLCAwLjAsIDEuMCk7XFxuXFxuICAgIGZsb2F0IHNkZmRpc3RfYSA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleF9hKS5hO1xcbiAgICBmbG9hdCBzZGZkaXN0X2IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhfYikuYTtcXG4gICAgZmxvYXQgc2RmZGlzdCA9IG1peChzZGZkaXN0X2EsIHNkZmRpc3RfYiwgdV9taXgpO1xcbiAgICBhbHBoYSAqPSBzbW9vdGhzdGVwKDAuNSAtIHVfc2RmZ2FtbWEgLyBmbG9vcndpZHRoLCAwLjUgKyB1X3NkZmdhbW1hIC8gZmxvb3J3aWR0aCwgc2RmZGlzdCk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yICogKGFscGhhICogb3BhY2l0eSk7XFxuXFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVxcblwiLHZlcnRleFNvdXJjZTpcIi8vIGZsb29yKDEyNyAvIDIpID09IDYzLjBcXG4vLyB0aGUgbWF4aW11bSBhbGxvd2VkIG1pdGVyIGxpbWl0IGlzIDIuMCBhdCB0aGUgbW9tZW50LiB0aGUgZXh0cnVkZSBub3JtYWwgaXNcXG4vLyBzdG9yZWQgaW4gYSBieXRlICgtMTI4Li4xMjcpLiB3ZSBzY2FsZSByZWd1bGFyIG5vcm1hbHMgdXAgdG8gbGVuZ3RoIDYzLCBidXRcXG4vLyB0aGVyZSBhcmUgYWxzbyBcXFwic3BlY2lhbFxcXCIgbm9ybWFscyB0aGF0IGhhdmUgYSBiaWdnZXIgbGVuZ3RoIChvZiB1cCB0byAxMjYgaW5cXG4vLyB0aGlzIGNhc2UpLlxcbi8vICNkZWZpbmUgc2NhbGUgNjMuMFxcbiNkZWZpbmUgc2NhbGUgMC4wMTU4NzMwMTZcXG5cXG4vLyBXZSBzY2FsZSB0aGUgZGlzdGFuY2UgYmVmb3JlIGFkZGluZyBpdCB0byB0aGUgYnVmZmVycyBzbyB0aGF0IHdlIGNhbiBzdG9yZVxcbi8vIGxvbmcgZGlzdGFuY2VzIGZvciBsb25nIHNlZ21lbnRzLiBVc2UgdGhpcyB2YWx1ZSB0byB1bnNjYWxlIHRoZSBkaXN0YW5jZS5cXG4jZGVmaW5lIExJTkVfRElTVEFOQ0VfU0NBTEUgMi4wXFxuXFxuLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXFxuLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXFxuI2RlZmluZSBBTlRJQUxJQVNJTkcgMS4wIC8gREVWSUNFX1BJWEVMX1JBVElPIC8gMi4wXFxuXFxuYXR0cmlidXRlIHZlYzQgYV9wb3Nfbm9ybWFsO1xcbmF0dHJpYnV0ZSB2ZWM0IGFfZGF0YTtcXG5cXG51bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSBtZWRpdW1wIGZsb2F0IHVfcmF0aW87XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybnNjYWxlX2E7XFxudW5pZm9ybSBmbG9hdCB1X3RleF95X2E7XFxudW5pZm9ybSB2ZWMyIHVfcGF0dGVybnNjYWxlX2I7XFxudW5pZm9ybSBmbG9hdCB1X3RleF95X2I7XFxudW5pZm9ybSB2ZWMyIHVfZ2xfdW5pdHNfdG9fcGl4ZWxzO1xcblxcbnZhcnlpbmcgdmVjMiB2X25vcm1hbDtcXG52YXJ5aW5nIHZlYzIgdl93aWR0aDI7XFxudmFyeWluZyB2ZWMyIHZfdGV4X2E7XFxudmFyeWluZyB2ZWMyIHZfdGV4X2I7XFxudmFyeWluZyBmbG9hdCB2X2dhbW1hX3NjYWxlO1xcblxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb2Zmc2V0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgY29sb3JcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBibHVyXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb2Zmc2V0XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgd2lkdGhcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBmbG9vcndpZHRoXFxuXFxuICAgIHZlYzIgYV9leHRydWRlID0gYV9kYXRhLnh5IC0gMTI4LjA7XFxuICAgIGZsb2F0IGFfZGlyZWN0aW9uID0gbW9kKGFfZGF0YS56LCA0LjApIC0gMS4wO1xcbiAgICBmbG9hdCBhX2xpbmVzb2ZhciA9IChmbG9vcihhX2RhdGEueiAvIDQuMCkgKyBhX2RhdGEudyAqIDY0LjApICogTElORV9ESVNUQU5DRV9TQ0FMRTtcXG5cXG4gICAgdmVjMiBwb3MgPSBhX3Bvc19ub3JtYWwueHk7XFxuXFxuICAgIC8vIHggaXMgMSBpZiBpdCdzIGEgcm91bmQgY2FwLCAwIG90aGVyd2lzZVxcbiAgICAvLyB5IGlzIDEgaWYgdGhlIG5vcm1hbCBwb2ludHMgdXAsIGFuZCAtMSBpZiBpdCBwb2ludHMgZG93blxcbiAgICBtZWRpdW1wIHZlYzIgbm9ybWFsID0gYV9wb3Nfbm9ybWFsLnp3O1xcbiAgICB2X25vcm1hbCA9IG5vcm1hbDtcXG5cXG4gICAgLy8gdGhlc2UgdHJhbnNmb3JtYXRpb25zIHVzZWQgdG8gYmUgYXBwbGllZCBpbiB0aGUgSlMgYW5kIG5hdGl2ZSBjb2RlIGJhc2VzLlxcbiAgICAvLyBtb3ZlZCB0aGVtIGludG8gdGhlIHNoYWRlciBmb3IgY2xhcml0eSBhbmQgc2ltcGxpY2l0eS5cXG4gICAgZ2Fwd2lkdGggPSBnYXB3aWR0aCAvIDIuMDtcXG4gICAgZmxvYXQgaGFsZndpZHRoID0gd2lkdGggLyAyLjA7XFxuICAgIG9mZnNldCA9IC0xLjAgKiBvZmZzZXQ7XFxuXFxuICAgIGZsb2F0IGluc2V0ID0gZ2Fwd2lkdGggKyAoZ2Fwd2lkdGggPiAwLjAgPyBBTlRJQUxJQVNJTkcgOiAwLjApO1xcbiAgICBmbG9hdCBvdXRzZXQgPSBnYXB3aWR0aCArIGhhbGZ3aWR0aCAqIChnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkgKyBBTlRJQUxJQVNJTkc7XFxuXFxuICAgIC8vIFNjYWxlIHRoZSBleHRydXNpb24gdmVjdG9yIGRvd24gdG8gYSBub3JtYWwgYW5kIHRoZW4gdXAgYnkgdGhlIGxpbmUgd2lkdGhcXG4gICAgLy8gb2YgdGhpcyB2ZXJ0ZXguXFxuICAgIG1lZGl1bXAgdmVjMiBkaXN0ID1vdXRzZXQgKiBhX2V4dHJ1ZGUgKiBzY2FsZTtcXG5cXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBvZmZzZXQgd2hlbiBkcmF3aW5nIGEgbGluZSB0aGF0IGlzIHRvIHRoZSBzaWRlIG9mIHRoZSBhY3R1YWwgbGluZS5cXG4gICAgLy8gV2UgZG8gdGhpcyBieSBjcmVhdGluZyBhIHZlY3RvciB0aGF0IHBvaW50cyB0b3dhcmRzIHRoZSBleHRydWRlLCBidXQgcm90YXRlXFxuICAgIC8vIGl0IHdoZW4gd2UncmUgZHJhd2luZyByb3VuZCBlbmQgcG9pbnRzIChhX2RpcmVjdGlvbiA9IC0xIG9yIDEpIHNpbmNlIHRoZWlyXFxuICAgIC8vIGV4dHJ1ZGUgdmVjdG9yIHBvaW50cyBpbiBhbm90aGVyIGRpcmVjdGlvbi5cXG4gICAgbWVkaXVtcCBmbG9hdCB1ID0gMC41ICogYV9kaXJlY3Rpb247XFxuICAgIG1lZGl1bXAgZmxvYXQgdCA9IDEuMCAtIGFicyh1KTtcXG4gICAgbWVkaXVtcCB2ZWMyIG9mZnNldDIgPSBvZmZzZXQgKiBhX2V4dHJ1ZGUgKiBzY2FsZSAqIG5vcm1hbC55ICogbWF0Mih0LCAtdSwgdSwgdCk7XFxuXFxuICAgIHZlYzQgcHJvamVjdGVkX2V4dHJ1ZGUgPSB1X21hdHJpeCAqIHZlYzQoZGlzdCAvIHVfcmF0aW8sIDAuMCwgMC4wKTtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X21hdHJpeCAqIHZlYzQocG9zICsgb2Zmc2V0MiAvIHVfcmF0aW8sIDAuMCwgMS4wKSArIHByb2plY3RlZF9leHRydWRlO1xcblxcbiAgICAvLyBjYWxjdWxhdGUgaG93IG11Y2ggdGhlIHBlcnNwZWN0aXZlIHZpZXcgc3F1aXNoZXMgb3Igc3RyZXRjaGVzIHRoZSBleHRydWRlXFxuICAgIGZsb2F0IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUgPSBsZW5ndGgoZGlzdCk7XFxuICAgIGZsb2F0IGV4dHJ1ZGVfbGVuZ3RoX3dpdGhfcGVyc3BlY3RpdmUgPSBsZW5ndGgocHJvamVjdGVkX2V4dHJ1ZGUueHkgLyBnbF9Qb3NpdGlvbi53ICogdV9nbF91bml0c190b19waXhlbHMpO1xcbiAgICB2X2dhbW1hX3NjYWxlID0gZXh0cnVkZV9sZW5ndGhfd2l0aG91dF9wZXJzcGVjdGl2ZSAvIGV4dHJ1ZGVfbGVuZ3RoX3dpdGhfcGVyc3BlY3RpdmU7XFxuXFxuICAgIHZfdGV4X2EgPSB2ZWMyKGFfbGluZXNvZmFyICogdV9wYXR0ZXJuc2NhbGVfYS54IC8gZmxvb3J3aWR0aCwgbm9ybWFsLnkgKiB1X3BhdHRlcm5zY2FsZV9hLnkgKyB1X3RleF95X2EpO1xcbiAgICB2X3RleF9iID0gdmVjMihhX2xpbmVzb2ZhciAqIHVfcGF0dGVybnNjYWxlX2IueCAvIGZsb29yd2lkdGgsIG5vcm1hbC55ICogdV9wYXR0ZXJuc2NhbGVfYi55ICsgdV90ZXhfeV9iKTtcXG5cXG4gICAgdl93aWR0aDIgPSB2ZWMyKG91dHNldCwgaW5zZXQpO1xcbn1cXG5cIn0scmFzdGVyOntmcmFnbWVudFNvdXJjZTpcInVuaWZvcm0gZmxvYXQgdV9mYWRlX3Q7XFxudW5pZm9ybSBmbG9hdCB1X29wYWNpdHk7XFxudW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTA7XFxudW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTE7XFxudmFyeWluZyB2ZWMyIHZfcG9zMDtcXG52YXJ5aW5nIHZlYzIgdl9wb3MxO1xcblxcbnVuaWZvcm0gZmxvYXQgdV9icmlnaHRuZXNzX2xvdztcXG51bmlmb3JtIGZsb2F0IHVfYnJpZ2h0bmVzc19oaWdoO1xcblxcbnVuaWZvcm0gZmxvYXQgdV9zYXR1cmF0aW9uX2ZhY3RvcjtcXG51bmlmb3JtIGZsb2F0IHVfY29udHJhc3RfZmFjdG9yO1xcbnVuaWZvcm0gdmVjMyB1X3NwaW5fd2VpZ2h0cztcXG5cXG52b2lkIG1haW4oKSB7XFxuXFxuICAgIC8vIHJlYWQgYW5kIGNyb3NzLWZhZGUgY29sb3JzIGZyb20gdGhlIG1haW4gYW5kIHBhcmVudCB0aWxlc1xcbiAgICB2ZWM0IGNvbG9yMCA9IHRleHR1cmUyRCh1X2ltYWdlMCwgdl9wb3MwKTtcXG4gICAgdmVjNCBjb2xvcjEgPSB0ZXh0dXJlMkQodV9pbWFnZTEsIHZfcG9zMSk7XFxuICAgIGlmIChjb2xvcjAuYSA+IDAuMCkge1xcbiAgICAgICAgY29sb3IwLnJnYiA9IGNvbG9yMC5yZ2IgLyBjb2xvcjAuYTtcXG4gICAgfVxcbiAgICBpZiAoY29sb3IxLmEgPiAwLjApIHtcXG4gICAgICAgIGNvbG9yMS5yZ2IgPSBjb2xvcjEucmdiIC8gY29sb3IxLmE7XFxuICAgIH1cXG4gICAgdmVjNCBjb2xvciA9IG1peChjb2xvcjAsIGNvbG9yMSwgdV9mYWRlX3QpO1xcbiAgICBjb2xvci5hICo9IHVfb3BhY2l0eTtcXG4gICAgdmVjMyByZ2IgPSBjb2xvci5yZ2I7XFxuXFxuICAgIC8vIHNwaW5cXG4gICAgcmdiID0gdmVjMyhcXG4gICAgICAgIGRvdChyZ2IsIHVfc3Bpbl93ZWlnaHRzLnh5eiksXFxuICAgICAgICBkb3QocmdiLCB1X3NwaW5fd2VpZ2h0cy56eHkpLFxcbiAgICAgICAgZG90KHJnYiwgdV9zcGluX3dlaWdodHMueXp4KSk7XFxuXFxuICAgIC8vIHNhdHVyYXRpb25cXG4gICAgZmxvYXQgYXZlcmFnZSA9IChjb2xvci5yICsgY29sb3IuZyArIGNvbG9yLmIpIC8gMy4wO1xcbiAgICByZ2IgKz0gKGF2ZXJhZ2UgLSByZ2IpICogdV9zYXR1cmF0aW9uX2ZhY3RvcjtcXG5cXG4gICAgLy8gY29udHJhc3RcXG4gICAgcmdiID0gKHJnYiAtIDAuNSkgKiB1X2NvbnRyYXN0X2ZhY3RvciArIDAuNTtcXG5cXG4gICAgLy8gYnJpZ2h0bmVzc1xcbiAgICB2ZWMzIHVfaGlnaF92ZWMgPSB2ZWMzKHVfYnJpZ2h0bmVzc19sb3csIHVfYnJpZ2h0bmVzc19sb3csIHVfYnJpZ2h0bmVzc19sb3cpO1xcbiAgICB2ZWMzIHVfbG93X3ZlYyA9IHZlYzModV9icmlnaHRuZXNzX2hpZ2gsIHVfYnJpZ2h0bmVzc19oaWdoLCB1X2JyaWdodG5lc3NfaGlnaCk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQobWl4KHVfaGlnaF92ZWMsIHVfbG93X3ZlYywgcmdiKSAqIGNvbG9yLmEsIGNvbG9yLmEpO1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7XFxudW5pZm9ybSB2ZWMyIHVfdGxfcGFyZW50O1xcbnVuaWZvcm0gZmxvYXQgdV9zY2FsZV9wYXJlbnQ7XFxudW5pZm9ybSBmbG9hdCB1X2J1ZmZlcl9zY2FsZTtcXG5cXG5hdHRyaWJ1dGUgdmVjMiBhX3BvcztcXG5hdHRyaWJ1dGUgdmVjMiBhX3RleHR1cmVfcG9zO1xcblxcbnZhcnlpbmcgdmVjMiB2X3BvczA7XFxudmFyeWluZyB2ZWMyIHZfcG9zMTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgIGdsX1Bvc2l0aW9uID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG4gICAgLy8gV2UgYXJlIHVzaW5nIEludDE2IGZvciB0ZXh0dXJlIHBvc2l0aW9uIGNvb3JkaW5hdGVzIHRvIGdpdmUgdXMgZW5vdWdoIHByZWNpc2lvbiBmb3JcXG4gICAgLy8gZnJhY3Rpb25hbCBjb29yZGluYXRlcy4gV2UgdXNlIDgxOTIgdG8gc2NhbGUgdGhlIHRleHR1cmUgY29vcmRpbmF0ZXMgaW4gdGhlIGJ1ZmZlclxcbiAgICAvLyBhcyBhbiBhcmJpdHJhcmlseSBoaWdoIG51bWJlciB0byBwcmVzZXJ2ZSBhZGVxdWF0ZSBwcmVjaXNpb24gd2hlbiByZW5kZXJpbmcuXFxuICAgIC8vIFRoaXMgaXMgYWxzbyB0aGUgc2FtZSB2YWx1ZSBhcyB0aGUgRVhURU5UIHdlIGFyZSB1c2luZyBmb3Igb3VyIHRpbGUgYnVmZmVyIHBvcyBjb29yZGluYXRlcyxcXG4gICAgLy8gc28gbWF0aCBmb3IgbW9kaWZ5aW5nIGVpdGhlciBpcyBjb25zaXN0ZW50LlxcbiAgICB2X3BvczAgPSAoKChhX3RleHR1cmVfcG9zIC8gODE5Mi4wKSAtIDAuNSkgLyB1X2J1ZmZlcl9zY2FsZSApICsgMC41O1xcbiAgICB2X3BvczEgPSAodl9wb3MwICogdV9zY2FsZV9wYXJlbnQpICsgdV90bF9wYXJlbnQ7XFxufVxcblwifSxzeW1ib2xJY29uOntmcmFnbWVudFNvdXJjZTpcInVuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnZhcnlpbmcgdmVjMiB2X3RleDtcXG52YXJ5aW5nIGZsb2F0IHZfZmFkZV9vcGFjaXR5O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuXFxuICAgIGxvd3AgZmxvYXQgYWxwaGEgPSBvcGFjaXR5ICogdl9mYWRlX29wYWNpdHk7XFxuICAgIGdsX0ZyYWdDb2xvciA9IHRleHR1cmUyRCh1X3RleHR1cmUsIHZfdGV4KSAqIGFscGhhO1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJjb25zdCBmbG9hdCBQSSA9IDMuMTQxNTkyNjUzNTg5NzkzO1xcblxcbmF0dHJpYnV0ZSB2ZWM0IGFfcG9zX29mZnNldDtcXG5hdHRyaWJ1dGUgdmVjNCBhX2RhdGE7XFxuYXR0cmlidXRlIHZlYzMgYV9wcm9qZWN0ZWRfcG9zO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX2ZhZGVfb3BhY2l0eTtcXG5cXG51bmlmb3JtIGJvb2wgdV9pc19zaXplX3pvb21fY29uc3RhbnQ7XFxudW5pZm9ybSBib29sIHVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50O1xcbnVuaWZvcm0gaGlnaHAgZmxvYXQgdV9zaXplX3Q7IC8vIHVzZWQgdG8gaW50ZXJwb2xhdGUgYmV0d2VlbiB6b29tIHN0b3BzIHdoZW4gc2l6ZSBpcyBhIGNvbXBvc2l0ZSBmdW5jdGlvblxcbnVuaWZvcm0gaGlnaHAgZmxvYXQgdV9zaXplOyAvLyB1c2VkIHdoZW4gc2l6ZSBpcyBib3RoIHpvb20gYW5kIGZlYXR1cmUgY29uc3RhbnRcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTtcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfcGl0Y2g7XFxudW5pZm9ybSBib29sIHVfcm90YXRlX3N5bWJvbDtcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfYXNwZWN0X3JhdGlvO1xcbnVuaWZvcm0gZmxvYXQgdV9mYWRlX2NoYW5nZTtcXG5cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbnVuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG51bmlmb3JtIG1hdDQgdV9sYWJlbF9wbGFuZV9tYXRyaXg7XFxudW5pZm9ybSBtYXQ0IHVfZ2xfY29vcmRfbWF0cml4O1xcblxcbnVuaWZvcm0gYm9vbCB1X2lzX3RleHQ7XFxudW5pZm9ybSBib29sIHVfcGl0Y2hfd2l0aF9tYXA7XFxuXFxudW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTtcXG5cXG52YXJ5aW5nIHZlYzIgdl90ZXg7XFxudmFyeWluZyBmbG9hdCB2X2ZhZGVfb3BhY2l0eTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcblxcbiAgICB2ZWMyIGFfcG9zID0gYV9wb3Nfb2Zmc2V0Lnh5O1xcbiAgICB2ZWMyIGFfb2Zmc2V0ID0gYV9wb3Nfb2Zmc2V0Lnp3O1xcblxcbiAgICB2ZWMyIGFfdGV4ID0gYV9kYXRhLnh5O1xcbiAgICB2ZWMyIGFfc2l6ZSA9IGFfZGF0YS56dztcXG5cXG4gICAgaGlnaHAgZmxvYXQgc2VnbWVudF9hbmdsZSA9IC1hX3Byb2plY3RlZF9wb3NbMl07XFxuXFxuICAgIGZsb2F0IHNpemU7XFxuICAgIGlmICghdV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgIXVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSB7XFxuICAgICAgICBzaXplID0gbWl4KGFfc2l6ZVswXSwgYV9zaXplWzFdLCB1X3NpemVfdCkgLyAxMC4wO1xcbiAgICB9IGVsc2UgaWYgKHVfaXNfc2l6ZV96b29tX2NvbnN0YW50ICYmICF1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudCkge1xcbiAgICAgICAgc2l6ZSA9IGFfc2l6ZVswXSAvIDEwLjA7XFxuICAgIH0gZWxzZSBpZiAoIXVfaXNfc2l6ZV96b29tX2NvbnN0YW50ICYmIHVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSB7XFxuICAgICAgICBzaXplID0gdV9zaXplO1xcbiAgICB9IGVsc2Uge1xcbiAgICAgICAgc2l6ZSA9IHVfc2l6ZTtcXG4gICAgfVxcblxcbiAgICB2ZWM0IHByb2plY3RlZFBvaW50ID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zLCAwLCAxKTtcXG4gICAgaGlnaHAgZmxvYXQgY2FtZXJhX3RvX2FuY2hvcl9kaXN0YW5jZSA9IHByb2plY3RlZFBvaW50Lnc7XFxuICAgIC8vIFNlZSBjb21tZW50cyBpbiBzeW1ib2xfc2RmLnZlcnRleFxcbiAgICBoaWdocCBmbG9hdCBkaXN0YW5jZV9yYXRpbyA9IHVfcGl0Y2hfd2l0aF9tYXAgP1xcbiAgICAgICAgY2FtZXJhX3RvX2FuY2hvcl9kaXN0YW5jZSAvIHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSA6XFxuICAgICAgICB1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UgLyBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlO1xcbiAgICBoaWdocCBmbG9hdCBwZXJzcGVjdGl2ZV9yYXRpbyA9IGNsYW1wKFxcbiAgICAgICAgICAgIDAuNSArIDAuNSAqIGRpc3RhbmNlX3JhdGlvLFxcbiAgICAgICAgICAgIDAuMCwgLy8gUHJldmVudHMgb3ZlcnNpemVkIG5lYXItZmllbGQgc3ltYm9scyBpbiBwaXRjaGVkL292ZXJ6b29tZWQgdGlsZXNcXG4gICAgICAgICAgICA0LjApO1xcblxcbiAgICBzaXplICo9IHBlcnNwZWN0aXZlX3JhdGlvO1xcblxcbiAgICBmbG9hdCBmb250U2NhbGUgPSB1X2lzX3RleHQgPyBzaXplIC8gMjQuMCA6IHNpemU7XFxuXFxuICAgIGhpZ2hwIGZsb2F0IHN5bWJvbF9yb3RhdGlvbiA9IDAuMDtcXG4gICAgaWYgKHVfcm90YXRlX3N5bWJvbCkge1xcbiAgICAgICAgLy8gU2VlIGNvbW1lbnRzIGluIHN5bWJvbF9zZGYudmVydGV4XFxuICAgICAgICB2ZWM0IG9mZnNldFByb2plY3RlZFBvaW50ID0gdV9tYXRyaXggKiB2ZWM0KGFfcG9zICsgdmVjMigxLCAwKSwgMCwgMSk7XFxuXFxuICAgICAgICB2ZWMyIGEgPSBwcm9qZWN0ZWRQb2ludC54eSAvIHByb2plY3RlZFBvaW50Lnc7XFxuICAgICAgICB2ZWMyIGIgPSBvZmZzZXRQcm9qZWN0ZWRQb2ludC54eSAvIG9mZnNldFByb2plY3RlZFBvaW50Lnc7XFxuXFxuICAgICAgICBzeW1ib2xfcm90YXRpb24gPSBhdGFuKChiLnkgLSBhLnkpIC8gdV9hc3BlY3RfcmF0aW8sIGIueCAtIGEueCk7XFxuICAgIH1cXG5cXG4gICAgaGlnaHAgZmxvYXQgYW5nbGVfc2luID0gc2luKHNlZ21lbnRfYW5nbGUgKyBzeW1ib2xfcm90YXRpb24pO1xcbiAgICBoaWdocCBmbG9hdCBhbmdsZV9jb3MgPSBjb3Moc2VnbWVudF9hbmdsZSArIHN5bWJvbF9yb3RhdGlvbik7XFxuICAgIG1hdDIgcm90YXRpb25fbWF0cml4ID0gbWF0MihhbmdsZV9jb3MsIC0xLjAgKiBhbmdsZV9zaW4sIGFuZ2xlX3NpbiwgYW5nbGVfY29zKTtcXG5cXG4gICAgdmVjNCBwcm9qZWN0ZWRfcG9zID0gdV9sYWJlbF9wbGFuZV9tYXRyaXggKiB2ZWM0KGFfcHJvamVjdGVkX3Bvcy54eSwgMC4wLCAxLjApO1xcbiAgICBnbF9Qb3NpdGlvbiA9IHVfZ2xfY29vcmRfbWF0cml4ICogdmVjNChwcm9qZWN0ZWRfcG9zLnh5IC8gcHJvamVjdGVkX3Bvcy53ICsgcm90YXRpb25fbWF0cml4ICogKGFfb2Zmc2V0IC8gMzIuMCAqIGZvbnRTY2FsZSksIDAuMCwgMS4wKTtcXG5cXG4gICAgdl90ZXggPSBhX3RleCAvIHVfdGV4c2l6ZTtcXG4gICAgdmVjMiBmYWRlX29wYWNpdHkgPSB1bnBhY2tfb3BhY2l0eShhX2ZhZGVfb3BhY2l0eSk7XFxuICAgIGZsb2F0IGZhZGVfY2hhbmdlID0gZmFkZV9vcGFjaXR5WzFdID4gMC41ID8gdV9mYWRlX2NoYW5nZSA6IC11X2ZhZGVfY2hhbmdlO1xcbiAgICB2X2ZhZGVfb3BhY2l0eSA9IG1heCgwLjAsIG1pbigxLjAsIGZhZGVfb3BhY2l0eVswXSArIGZhZGVfY2hhbmdlKSk7XFxufVxcblwifSxzeW1ib2xTREY6e2ZyYWdtZW50U291cmNlOlwiI2RlZmluZSBTREZfUFggOC4wXFxuI2RlZmluZSBFREdFX0dBTU1BIDAuMTA1L0RFVklDRV9QSVhFTF9SQVRJT1xcblxcbnVuaWZvcm0gYm9vbCB1X2lzX2hhbG87XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGZpbGxfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgaGFsb19jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGhhbG9fd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgaGFsb19ibHVyXFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgdV90ZXh0dXJlO1xcbnVuaWZvcm0gaGlnaHAgZmxvYXQgdV9nYW1tYV9zY2FsZTtcXG51bmlmb3JtIGJvb2wgdV9pc190ZXh0O1xcblxcbnZhcnlpbmcgdmVjMiB2X2RhdGEwO1xcbnZhcnlpbmcgdmVjMyB2X2RhdGExO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBmaWxsX2NvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgaGFsb19jb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoYWxvX3dpZHRoXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgaGFsb19ibHVyXFxuXFxuICAgIHZlYzIgdGV4ID0gdl9kYXRhMC54eTtcXG4gICAgZmxvYXQgZ2FtbWFfc2NhbGUgPSB2X2RhdGExLng7XFxuICAgIGZsb2F0IHNpemUgPSB2X2RhdGExLnk7XFxuICAgIGZsb2F0IGZhZGVfb3BhY2l0eSA9IHZfZGF0YTFbMl07XFxuXFxuICAgIGZsb2F0IGZvbnRTY2FsZSA9IHVfaXNfdGV4dCA/IHNpemUgLyAyNC4wIDogc2l6ZTtcXG5cXG4gICAgbG93cCB2ZWM0IGNvbG9yID0gZmlsbF9jb2xvcjtcXG4gICAgaGlnaHAgZmxvYXQgZ2FtbWEgPSBFREdFX0dBTU1BIC8gKGZvbnRTY2FsZSAqIHVfZ2FtbWFfc2NhbGUpO1xcbiAgICBsb3dwIGZsb2F0IGJ1ZmYgPSAoMjU2LjAgLSA2NC4wKSAvIDI1Ni4wO1xcbiAgICBpZiAodV9pc19oYWxvKSB7XFxuICAgICAgICBjb2xvciA9IGhhbG9fY29sb3I7XFxuICAgICAgICBnYW1tYSA9IChoYWxvX2JsdXIgKiAxLjE5IC8gU0RGX1BYICsgRURHRV9HQU1NQSkgLyAoZm9udFNjYWxlICogdV9nYW1tYV9zY2FsZSk7XFxuICAgICAgICBidWZmID0gKDYuMCAtIGhhbG9fd2lkdGggLyBmb250U2NhbGUpIC8gU0RGX1BYO1xcbiAgICB9XFxuXFxuICAgIGxvd3AgZmxvYXQgZGlzdCA9IHRleHR1cmUyRCh1X3RleHR1cmUsIHRleCkuYTtcXG4gICAgaGlnaHAgZmxvYXQgZ2FtbWFfc2NhbGVkID0gZ2FtbWEgKiBnYW1tYV9zY2FsZTtcXG4gICAgaGlnaHAgZmxvYXQgYWxwaGEgPSBzbW9vdGhzdGVwKGJ1ZmYgLSBnYW1tYV9zY2FsZWQsIGJ1ZmYgKyBnYW1tYV9zY2FsZWQsIGRpc3QpO1xcblxcbiAgICBnbF9GcmFnQ29sb3IgPSBjb2xvciAqIChhbHBoYSAqIG9wYWNpdHkgKiBmYWRlX29wYWNpdHkpO1xcblxcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cXG5cIix2ZXJ0ZXhTb3VyY2U6XCJjb25zdCBmbG9hdCBQSSA9IDMuMTQxNTkyNjUzNTg5NzkzO1xcblxcbmF0dHJpYnV0ZSB2ZWM0IGFfcG9zX29mZnNldDtcXG5hdHRyaWJ1dGUgdmVjNCBhX2RhdGE7XFxuYXR0cmlidXRlIHZlYzMgYV9wcm9qZWN0ZWRfcG9zO1xcbmF0dHJpYnV0ZSBmbG9hdCBhX2ZhZGVfb3BhY2l0eTtcXG5cXG4vLyBjb250ZW50cyBvZiBhX3NpemUgdmFyeSBiYXNlZCBvbiB0aGUgdHlwZSBvZiBwcm9wZXJ0eSB2YWx1ZVxcbi8vIHVzZWQgZm9yIHt0ZXh0LGljb259LXNpemUuXFxuLy8gRm9yIGNvbnN0YW50cywgYV9zaXplIGlzIGRpc2FibGVkLlxcbi8vIEZvciBzb3VyY2UgZnVuY3Rpb25zLCB3ZSBiaW5kIG9ubHkgb25lIHZhbHVlIHBlciB2ZXJ0ZXg6IHRoZSB2YWx1ZSBvZiB7dGV4dCxpY29ufS1zaXplIGV2YWx1YXRlZCBmb3IgdGhlIGN1cnJlbnQgZmVhdHVyZS5cXG4vLyBGb3IgY29tcG9zaXRlIGZ1bmN0aW9uczpcXG4vLyBbIHRleHQtc2l6ZShsb3dlclpvb21TdG9wLCBmZWF0dXJlKSxcXG4vLyAgIHRleHQtc2l6ZSh1cHBlclpvb21TdG9wLCBmZWF0dXJlKSBdXFxudW5pZm9ybSBib29sIHVfaXNfc2l6ZV96b29tX2NvbnN0YW50O1xcbnVuaWZvcm0gYm9vbCB1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudDtcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfc2l6ZV90OyAvLyB1c2VkIHRvIGludGVycG9sYXRlIGJldHdlZW4gem9vbSBzdG9wcyB3aGVuIHNpemUgaXMgYSBjb21wb3NpdGUgZnVuY3Rpb25cXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfc2l6ZTsgLy8gdXNlZCB3aGVuIHNpemUgaXMgYm90aCB6b29tIGFuZCBmZWF0dXJlIGNvbnN0YW50XFxuXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGZpbGxfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgaGFsb19jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGhhbG9fd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgaGFsb19ibHVyXFxuXFxudW5pZm9ybSBtYXQ0IHVfbWF0cml4O1xcbnVuaWZvcm0gbWF0NCB1X2xhYmVsX3BsYW5lX21hdHJpeDtcXG51bmlmb3JtIG1hdDQgdV9nbF9jb29yZF9tYXRyaXg7XFxuXFxudW5pZm9ybSBib29sIHVfaXNfdGV4dDtcXG51bmlmb3JtIGJvb2wgdV9waXRjaF93aXRoX21hcDtcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfcGl0Y2g7XFxudW5pZm9ybSBib29sIHVfcm90YXRlX3N5bWJvbDtcXG51bmlmb3JtIGhpZ2hwIGZsb2F0IHVfYXNwZWN0X3JhdGlvO1xcbnVuaWZvcm0gaGlnaHAgZmxvYXQgdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlO1xcbnVuaWZvcm0gZmxvYXQgdV9mYWRlX2NoYW5nZTtcXG5cXG51bmlmb3JtIHZlYzIgdV90ZXhzaXplO1xcblxcbnZhcnlpbmcgdmVjMiB2X2RhdGEwO1xcbnZhcnlpbmcgdmVjMyB2X2RhdGExO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBmaWxsX2NvbG9yXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgaGFsb19jb2xvclxcbiAgICAjcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4gICAgI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoYWxvX3dpZHRoXFxuICAgICNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgaGFsb19ibHVyXFxuXFxuICAgIHZlYzIgYV9wb3MgPSBhX3Bvc19vZmZzZXQueHk7XFxuICAgIHZlYzIgYV9vZmZzZXQgPSBhX3Bvc19vZmZzZXQuenc7XFxuXFxuICAgIHZlYzIgYV90ZXggPSBhX2RhdGEueHk7XFxuICAgIHZlYzIgYV9zaXplID0gYV9kYXRhLnp3O1xcblxcbiAgICBoaWdocCBmbG9hdCBzZWdtZW50X2FuZ2xlID0gLWFfcHJvamVjdGVkX3Bvc1syXTtcXG4gICAgZmxvYXQgc2l6ZTtcXG5cXG4gICAgaWYgKCF1X2lzX3NpemVfem9vbV9jb25zdGFudCAmJiAhdV9pc19zaXplX2ZlYXR1cmVfY29uc3RhbnQpIHtcXG4gICAgICAgIHNpemUgPSBtaXgoYV9zaXplWzBdLCBhX3NpemVbMV0sIHVfc2l6ZV90KSAvIDEwLjA7XFxuICAgIH0gZWxzZSBpZiAodV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgIXVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSB7XFxuICAgICAgICBzaXplID0gYV9zaXplWzBdIC8gMTAuMDtcXG4gICAgfSBlbHNlIGlmICghdV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgdV9pc19zaXplX2ZlYXR1cmVfY29uc3RhbnQpIHtcXG4gICAgICAgIHNpemUgPSB1X3NpemU7XFxuICAgIH0gZWxzZSB7XFxuICAgICAgICBzaXplID0gdV9zaXplO1xcbiAgICB9XFxuXFxuICAgIHZlYzQgcHJvamVjdGVkUG9pbnQgPSB1X21hdHJpeCAqIHZlYzQoYV9wb3MsIDAsIDEpO1xcbiAgICBoaWdocCBmbG9hdCBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlID0gcHJvamVjdGVkUG9pbnQudztcXG4gICAgLy8gSWYgdGhlIGxhYmVsIGlzIHBpdGNoZWQgd2l0aCB0aGUgbWFwLCBsYXlvdXQgaXMgZG9uZSBpbiBwaXRjaGVkIHNwYWNlLFxcbiAgICAvLyB3aGljaCBtYWtlcyBsYWJlbHMgaW4gdGhlIGRpc3RhbmNlIHNtYWxsZXIgcmVsYXRpdmUgdG8gdmlld3BvcnQgc3BhY2UuXFxuICAgIC8vIFdlIGNvdW50ZXJhY3QgcGFydCBvZiB0aGF0IGVmZmVjdCBieSBtdWx0aXBseWluZyBieSB0aGUgcGVyc3BlY3RpdmUgcmF0aW8uXFxuICAgIC8vIElmIHRoZSBsYWJlbCBpc24ndCBwaXRjaGVkIHdpdGggdGhlIG1hcCwgd2UgZG8gbGF5b3V0IGluIHZpZXdwb3J0IHNwYWNlLFxcbiAgICAvLyB3aGljaCBtYWtlcyBsYWJlbHMgaW4gdGhlIGRpc3RhbmNlIGxhcmdlciByZWxhdGl2ZSB0byB0aGUgZmVhdHVyZXMgYXJvdW5kXFxuICAgIC8vIHRoZW0uIFdlIGNvdW50ZXJhY3QgcGFydCBvZiB0aGF0IGVmZmVjdCBieSBkaXZpZGluZyBieSB0aGUgcGVyc3BlY3RpdmUgcmF0aW8uXFxuICAgIGhpZ2hwIGZsb2F0IGRpc3RhbmNlX3JhdGlvID0gdV9waXRjaF93aXRoX21hcCA/XFxuICAgICAgICBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlIC8gdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlIDpcXG4gICAgICAgIHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSAvIGNhbWVyYV90b19hbmNob3JfZGlzdGFuY2U7XFxuICAgIGhpZ2hwIGZsb2F0IHBlcnNwZWN0aXZlX3JhdGlvID0gY2xhbXAoXFxuICAgICAgICAwLjUgKyAwLjUgKiBkaXN0YW5jZV9yYXRpbyxcXG4gICAgICAgIDAuMCwgLy8gUHJldmVudHMgb3ZlcnNpemVkIG5lYXItZmllbGQgc3ltYm9scyBpbiBwaXRjaGVkL292ZXJ6b29tZWQgdGlsZXNcXG4gICAgICAgIDQuMCk7XFxuXFxuICAgIHNpemUgKj0gcGVyc3BlY3RpdmVfcmF0aW87XFxuXFxuICAgIGZsb2F0IGZvbnRTY2FsZSA9IHVfaXNfdGV4dCA/IHNpemUgLyAyNC4wIDogc2l6ZTtcXG5cXG4gICAgaGlnaHAgZmxvYXQgc3ltYm9sX3JvdGF0aW9uID0gMC4wO1xcbiAgICBpZiAodV9yb3RhdGVfc3ltYm9sKSB7XFxuICAgICAgICAvLyBQb2ludCBsYWJlbHMgd2l0aCAncm90YXRpb24tYWxpZ25tZW50OiBtYXAnIGFyZSBob3Jpem9udGFsIHdpdGggcmVzcGVjdCB0byB0aWxlIHVuaXRzXFxuICAgICAgICAvLyBUbyBmaWd1cmUgb3V0IHRoYXQgYW5nbGUgaW4gcHJvamVjdGVkIHNwYWNlLCB3ZSBkcmF3IGEgc2hvcnQgaG9yaXpvbnRhbCBsaW5lIGluIHRpbGVcXG4gICAgICAgIC8vIHNwYWNlLCBwcm9qZWN0IGl0LCBhbmQgbWVhc3VyZSBpdHMgYW5nbGUgaW4gcHJvamVjdGVkIHNwYWNlLlxcbiAgICAgICAgdmVjNCBvZmZzZXRQcm9qZWN0ZWRQb2ludCA9IHVfbWF0cml4ICogdmVjNChhX3BvcyArIHZlYzIoMSwgMCksIDAsIDEpO1xcblxcbiAgICAgICAgdmVjMiBhID0gcHJvamVjdGVkUG9pbnQueHkgLyBwcm9qZWN0ZWRQb2ludC53O1xcbiAgICAgICAgdmVjMiBiID0gb2Zmc2V0UHJvamVjdGVkUG9pbnQueHkgLyBvZmZzZXRQcm9qZWN0ZWRQb2ludC53O1xcblxcbiAgICAgICAgc3ltYm9sX3JvdGF0aW9uID0gYXRhbigoYi55IC0gYS55KSAvIHVfYXNwZWN0X3JhdGlvLCBiLnggLSBhLngpO1xcbiAgICB9XFxuXFxuICAgIGhpZ2hwIGZsb2F0IGFuZ2xlX3NpbiA9IHNpbihzZWdtZW50X2FuZ2xlICsgc3ltYm9sX3JvdGF0aW9uKTtcXG4gICAgaGlnaHAgZmxvYXQgYW5nbGVfY29zID0gY29zKHNlZ21lbnRfYW5nbGUgKyBzeW1ib2xfcm90YXRpb24pO1xcbiAgICBtYXQyIHJvdGF0aW9uX21hdHJpeCA9IG1hdDIoYW5nbGVfY29zLCAtMS4wICogYW5nbGVfc2luLCBhbmdsZV9zaW4sIGFuZ2xlX2Nvcyk7XFxuXFxuICAgIHZlYzQgcHJvamVjdGVkX3BvcyA9IHVfbGFiZWxfcGxhbmVfbWF0cml4ICogdmVjNChhX3Byb2plY3RlZF9wb3MueHksIDAuMCwgMS4wKTtcXG4gICAgZ2xfUG9zaXRpb24gPSB1X2dsX2Nvb3JkX21hdHJpeCAqIHZlYzQocHJvamVjdGVkX3Bvcy54eSAvIHByb2plY3RlZF9wb3MudyArIHJvdGF0aW9uX21hdHJpeCAqIChhX29mZnNldCAvIDMyLjAgKiBmb250U2NhbGUpLCAwLjAsIDEuMCk7XFxuICAgIGZsb2F0IGdhbW1hX3NjYWxlID0gZ2xfUG9zaXRpb24udztcXG5cXG4gICAgdmVjMiB0ZXggPSBhX3RleCAvIHVfdGV4c2l6ZTtcXG4gICAgdmVjMiBmYWRlX29wYWNpdHkgPSB1bnBhY2tfb3BhY2l0eShhX2ZhZGVfb3BhY2l0eSk7XFxuICAgIGZsb2F0IGZhZGVfY2hhbmdlID0gZmFkZV9vcGFjaXR5WzFdID4gMC41ID8gdV9mYWRlX2NoYW5nZSA6IC11X2ZhZGVfY2hhbmdlO1xcbiAgICBmbG9hdCBpbnRlcnBvbGF0ZWRfZmFkZV9vcGFjaXR5ID0gbWF4KDAuMCwgbWluKDEuMCwgZmFkZV9vcGFjaXR5WzBdICsgZmFkZV9jaGFuZ2UpKTtcXG5cXG4gICAgdl9kYXRhMCA9IHZlYzIodGV4LngsIHRleC55KTtcXG4gICAgdl9kYXRhMSA9IHZlYzMoZ2FtbWFfc2NhbGUsIHNpemUsIGludGVycG9sYXRlZF9mYWRlX29wYWNpdHkpO1xcbn1cXG5cIn19LGlpPS8jcHJhZ21hIG1hcGJveDogKFtcXHddKykgKFtcXHddKykgKFtcXHddKykgKFtcXHddKykvZyxuaT1mdW5jdGlvbih0KXt2YXIgZT1laVt0XSxpPXt9O2UuZnJhZ21lbnRTb3VyY2U9ZS5mcmFnbWVudFNvdXJjZS5yZXBsYWNlKGlpLGZ1bmN0aW9uKHQsZSxuLG8scil7cmV0dXJuIGlbcl09ITAsXCJkZWZpbmVcIj09PWU/XCJcXG4jaWZuZGVmIEhBU19VTklGT1JNX3VfXCIrcitcIlxcbnZhcnlpbmcgXCIrbitcIiBcIitvK1wiIFwiK3IrXCI7XFxuI2Vsc2VcXG51bmlmb3JtIFwiK24rXCIgXCIrbytcIiB1X1wiK3IrXCI7XFxuI2VuZGlmXFxuXCI6XCJcXG4jaWZkZWYgSEFTX1VOSUZPUk1fdV9cIityK1wiXFxuICAgIFwiK24rXCIgXCIrbytcIiBcIityK1wiID0gdV9cIityK1wiO1xcbiNlbmRpZlxcblwifSksZS52ZXJ0ZXhTb3VyY2U9ZS52ZXJ0ZXhTb3VyY2UucmVwbGFjZShpaSxmdW5jdGlvbih0LGUsbixvLHIpe3ZhciBhPVwiZmxvYXRcIj09PW8/XCJ2ZWMyXCI6XCJ2ZWM0XCI7cmV0dXJuIGlbcl0/XCJkZWZpbmVcIj09PWU/XCJcXG4jaWZuZGVmIEhBU19VTklGT1JNX3VfXCIrcitcIlxcbnVuaWZvcm0gbG93cCBmbG9hdCBhX1wiK3IrXCJfdDtcXG5hdHRyaWJ1dGUgXCIrbitcIiBcIithK1wiIGFfXCIrcitcIjtcXG52YXJ5aW5nIFwiK24rXCIgXCIrbytcIiBcIityK1wiO1xcbiNlbHNlXFxudW5pZm9ybSBcIituK1wiIFwiK28rXCIgdV9cIityK1wiO1xcbiNlbmRpZlxcblwiOlwiXFxuI2lmbmRlZiBIQVNfVU5JRk9STV91X1wiK3IrXCJcXG4gICAgXCIrcitcIiA9IHVucGFja19taXhfXCIrYStcIihhX1wiK3IrXCIsIGFfXCIrcitcIl90KTtcXG4jZWxzZVxcbiAgICBcIituK1wiIFwiK28rXCIgXCIrcitcIiA9IHVfXCIrcitcIjtcXG4jZW5kaWZcXG5cIjpcImRlZmluZVwiPT09ZT9cIlxcbiNpZm5kZWYgSEFTX1VOSUZPUk1fdV9cIityK1wiXFxudW5pZm9ybSBsb3dwIGZsb2F0IGFfXCIrcitcIl90O1xcbmF0dHJpYnV0ZSBcIituK1wiIFwiK2ErXCIgYV9cIityK1wiO1xcbiNlbHNlXFxudW5pZm9ybSBcIituK1wiIFwiK28rXCIgdV9cIityK1wiO1xcbiNlbmRpZlxcblwiOlwiXFxuI2lmbmRlZiBIQVNfVU5JRk9STV91X1wiK3IrXCJcXG4gICAgXCIrbitcIiBcIitvK1wiIFwiK3IrXCIgPSB1bnBhY2tfbWl4X1wiK2ErXCIoYV9cIityK1wiLCBhX1wiK3IrXCJfdCk7XFxuI2Vsc2VcXG4gICAgXCIrbitcIiBcIitvK1wiIFwiK3IrXCIgPSB1X1wiK3IrXCI7XFxuI2VuZGlmXFxuXCJ9KTt9O2Zvcih2YXIgb2kgaW4gZWkpbmkob2kpO3ZhciByaT1laSxhaT1mdW5jdGlvbih0LGUsaSxuKXt2YXIgbz10LmdsO3RoaXMucHJvZ3JhbT1vLmNyZWF0ZVByb2dyYW0oKTt2YXIgYT1pLmRlZmluZXMoKS5jb25jYXQoXCIjZGVmaW5lIERFVklDRV9QSVhFTF9SQVRJTyBcIityLmRldmljZVBpeGVsUmF0aW8udG9GaXhlZCgxKSk7biYmYS5wdXNoKFwiI2RlZmluZSBPVkVSRFJBV19JTlNQRUNUT1I7XCIpO3ZhciBzPWEuY29uY2F0KHJpLnByZWx1ZGUuZnJhZ21lbnRTb3VyY2UsZS5mcmFnbWVudFNvdXJjZSkuam9pbihcIlxcblwiKSxsPWEuY29uY2F0KHJpLnByZWx1ZGUudmVydGV4U291cmNlLGUudmVydGV4U291cmNlKS5qb2luKFwiXFxuXCIpLGM9by5jcmVhdGVTaGFkZXIoby5GUkFHTUVOVF9TSEFERVIpO28uc2hhZGVyU291cmNlKGMscyksby5jb21waWxlU2hhZGVyKGMpLG8uYXR0YWNoU2hhZGVyKHRoaXMucHJvZ3JhbSxjKTt2YXIgdT1vLmNyZWF0ZVNoYWRlcihvLlZFUlRFWF9TSEFERVIpO28uc2hhZGVyU291cmNlKHUsbCksby5jb21waWxlU2hhZGVyKHUpLG8uYXR0YWNoU2hhZGVyKHRoaXMucHJvZ3JhbSx1KTtmb3IodmFyIGg9aS5sYXlvdXRBdHRyaWJ1dGVzfHxbXSxwPTA7cDxoLmxlbmd0aDtwKyspby5iaW5kQXR0cmliTG9jYXRpb24odGhpcy5wcm9ncmFtLHAsaFtwXS5uYW1lKTtvLmxpbmtQcm9ncmFtKHRoaXMucHJvZ3JhbSksdGhpcy5udW1BdHRyaWJ1dGVzPW8uZ2V0UHJvZ3JhbVBhcmFtZXRlcih0aGlzLnByb2dyYW0sby5BQ1RJVkVfQVRUUklCVVRFUyksdGhpcy5hdHRyaWJ1dGVzPXt9LHRoaXMudW5pZm9ybXM9e307Zm9yKHZhciBkPTA7ZDx0aGlzLm51bUF0dHJpYnV0ZXM7ZCsrKXt2YXIgZj1vLmdldEFjdGl2ZUF0dHJpYih0aGlzLnByb2dyYW0sZCk7ZiYmKHRoaXMuYXR0cmlidXRlc1tmLm5hbWVdPW8uZ2V0QXR0cmliTG9jYXRpb24odGhpcy5wcm9ncmFtLGYubmFtZSkpO31mb3IodmFyIG09by5nZXRQcm9ncmFtUGFyYW1ldGVyKHRoaXMucHJvZ3JhbSxvLkFDVElWRV9VTklGT1JNUyksXz0wO188bTtfKyspe3ZhciBnPW8uZ2V0QWN0aXZlVW5pZm9ybSh0aGlzLnByb2dyYW0sXyk7ZyYmKHRoaXMudW5pZm9ybXNbZy5uYW1lXT1vLmdldFVuaWZvcm1Mb2NhdGlvbih0aGlzLnByb2dyYW0sZy5uYW1lKSk7fX07ZnVuY3Rpb24gc2koZSxpLG4sbyxyKXtmb3IodmFyIGE9MDthPG4ubGVuZ3RoO2ErKyl7dmFyIHM9blthXTtpZihvLmlzTGVzc1RoYW4ocy50aWxlSUQpKWJyZWFrO2lmKGkua2V5PT09cy50aWxlSUQua2V5KXJldHVybjtpZihzLnRpbGVJRC5pc0NoaWxkT2YoaSkpe2Zvcih2YXIgbD1pLmNoaWxkcmVuKDEvMCksYz0wO2M8bC5sZW5ndGg7YysrKXtzaShlLGxbY10sbi5zbGljZShhKSxvLHIpO31yZXR1cm59fXZhciB1PWkub3ZlcnNjYWxlZFotZS5vdmVyc2NhbGVkWixoPW5ldyB0LkNhbm9uaWNhbFRpbGVJRCh1LGkuY2Fub25pY2FsLngtKGUuY2Fub25pY2FsLng8PHUpLGkuY2Fub25pY2FsLnktKGUuY2Fub25pY2FsLnk8PHUpKTtyW2gua2V5XT1yW2gua2V5XXx8aDt9ZnVuY3Rpb24gbGkodCxlLGksbixvKXt2YXIgcj10LmNvbnRleHQsYT1yLmdsLHM9bz90LnVzZVByb2dyYW0oXCJjb2xsaXNpb25DaXJjbGVcIik6dC51c2VQcm9ncmFtKFwiY29sbGlzaW9uQm94XCIpO3Iuc2V0RGVwdGhNb2RlKCR0LmRpc2FibGVkKSxyLnNldFN0ZW5jaWxNb2RlKEd0LmRpc2FibGVkKSxyLnNldENvbG9yTW9kZSh0LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSk7Zm9yKHZhciBsPTA7bDxuLmxlbmd0aDtsKyspe3ZhciBjPW5bbF0sdT1lLmdldFRpbGUoYyksaD11LmdldEJ1Y2tldChpKTtpZihoKXt2YXIgcD1vP2guY29sbGlzaW9uQ2lyY2xlOmguY29sbGlzaW9uQm94O2lmKHApe2EudW5pZm9ybU1hdHJpeDRmdihzLnVuaWZvcm1zLnVfbWF0cml4LCExLGMucG9zTWF0cml4KSxvfHxyLmxpbmVXaWR0aC5zZXQoMSksYS51bmlmb3JtMWYocy51bmlmb3Jtcy51X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UsdC50cmFuc2Zvcm0uY2FtZXJhVG9DZW50ZXJEaXN0YW5jZSk7dmFyIGQ9emUodSwxLHQudHJhbnNmb3JtLnpvb20pLGY9TWF0aC5wb3coMix0LnRyYW5zZm9ybS56b29tLXUudGlsZUlELm92ZXJzY2FsZWRaKTthLnVuaWZvcm0xZihzLnVuaWZvcm1zLnVfcGl4ZWxzX3RvX3RpbGVfdW5pdHMsZCksYS51bmlmb3JtMmYocy51bmlmb3Jtcy51X2V4dHJ1ZGVfc2NhbGUsdC50cmFuc2Zvcm0ucGl4ZWxzVG9HTFVuaXRzWzBdLyhkKmYpLHQudHJhbnNmb3JtLnBpeGVsc1RvR0xVbml0c1sxXS8oZCpmKSksYS51bmlmb3JtMWYocy51bmlmb3Jtcy51X292ZXJzY2FsZV9mYWN0b3IsdS50aWxlSUQub3ZlcnNjYWxlRmFjdG9yKCkpLHMuZHJhdyhyLG8/YS5UUklBTkdMRVM6YS5MSU5FUyxpLmlkLHAubGF5b3V0VmVydGV4QnVmZmVyLHAuaW5kZXhCdWZmZXIscC5zZWdtZW50cyxudWxsLHAuY29sbGlzaW9uVmVydGV4QnVmZmVyLG51bGwpO319fX1haS5wcm90b3R5cGUuZHJhdz1mdW5jdGlvbih0LGUsaSxuLG8scixhLHMsbCl7Zm9yKHZhciBjLHU9dC5nbCxoPShjPXt9LGNbdS5MSU5FU109MixjW3UuVFJJQU5HTEVTXT0zLGMpW2VdLHA9MCxkPXIuZ2V0KCk7cDxkLmxlbmd0aDtwKz0xKXt2YXIgZj1kW3BdLG09Zi52YW9zfHwoZi52YW9zPXt9KTsobVtpXXx8KG1baV09bmV3IHR0KSkuYmluZCh0LHRoaXMsbixhP2EuZ2V0UGFpbnRWZXJ0ZXhCdWZmZXJzKCk6W10sbyxmLnZlcnRleE9mZnNldCxzLGwpLHUuZHJhd0VsZW1lbnRzKGUsZi5wcmltaXRpdmVMZW5ndGgqaCx1LlVOU0lHTkVEX1NIT1JULGYucHJpbWl0aXZlT2Zmc2V0KmgqMik7fX07dmFyIGNpPXQubWF0NC5pZGVudGl0eShuZXcgRmxvYXQzMkFycmF5KDE2KSksdWk9dC5kZWZhdWx0JDE5LmxheW91dDtmdW5jdGlvbiBoaSh0LGUsaSxuLG8scixhLHMsbCxjKXt2YXIgdSxoPXQuY29udGV4dCxwPWguZ2wsZD10LnRyYW5zZm9ybSxmPVwibWFwXCI9PT1zLG09XCJtYXBcIj09PWwsXz1mJiZcImxpbmVcIj09PWkubGF5b3V0LmdldChcInN5bWJvbC1wbGFjZW1lbnRcIiksZz1mJiYhbSYmIV8sdj1tO2guc2V0RGVwdGhNb2RlKHY/dC5kZXB0aE1vZGVGb3JTdWJsYXllcigwLCR0LlJlYWRPbmx5KTokdC5kaXNhYmxlZCk7Zm9yKHZhciB5PTAseD1uO3k8eC5sZW5ndGg7eSs9MSl7dmFyIGI9eFt5XSx3PWUuZ2V0VGlsZShiKSxFPXcuZ2V0QnVja2V0KGkpO2lmKEUpe3ZhciBUPW8/RS50ZXh0OkUuaWNvbjtpZihUJiZULnNlZ21lbnRzLmdldCgpLmxlbmd0aCl7dmFyIEk9VC5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGkuaWQpLEM9b3x8RS5zZGZJY29ucyxTPW8/RS50ZXh0U2l6ZURhdGE6RS5pY29uU2l6ZURhdGE7aWYodXx8KHU9dC51c2VQcm9ncmFtKEM/XCJzeW1ib2xTREZcIjpcInN5bWJvbEljb25cIixJKSxJLnNldFVuaWZvcm1zKHQuY29udGV4dCx1LGkucGFpbnQse3pvb206dC50cmFuc2Zvcm0uem9vbX0pLHBpKHUsdCxpLG8sZyxtLFMpKSxoLmFjdGl2ZVRleHR1cmUuc2V0KHAuVEVYVFVSRTApLHAudW5pZm9ybTFpKHUudW5pZm9ybXMudV90ZXh0dXJlLDApLG8pdy5nbHlwaEF0bGFzVGV4dHVyZS5iaW5kKHAuTElORUFSLHAuQ0xBTVBfVE9fRURHRSkscC51bmlmb3JtMmZ2KHUudW5pZm9ybXMudV90ZXhzaXplLHcuZ2x5cGhBdGxhc1RleHR1cmUuc2l6ZSk7ZWxzZXt2YXIgej0xIT09aS5sYXlvdXQuZ2V0KFwiaWNvbi1zaXplXCIpLmNvbnN0YW50T3IoMCl8fEUuaWNvbnNOZWVkTGluZWFyLEE9bXx8MCE9PWQucGl0Y2g7dy5pY29uQXRsYXNUZXh0dXJlLmJpbmQoQ3x8dC5vcHRpb25zLnJvdGF0aW5nfHx0Lm9wdGlvbnMuem9vbWluZ3x8enx8QT9wLkxJTkVBUjpwLk5FQVJFU1QscC5DTEFNUF9UT19FREdFKSxwLnVuaWZvcm0yZnYodS51bmlmb3Jtcy51X3RleHNpemUsdy5pY29uQXRsYXNUZXh0dXJlLnNpemUpO31wLnVuaWZvcm1NYXRyaXg0ZnYodS51bmlmb3Jtcy51X21hdHJpeCwhMSx0LnRyYW5zbGF0ZVBvc01hdHJpeChiLnBvc01hdHJpeCx3LHIsYSkpO3ZhciBSPXplKHcsMSx0LnRyYW5zZm9ybS56b29tKSxEPWRlKGIucG9zTWF0cml4LG0sZix0LnRyYW5zZm9ybSxSKSxNPWZlKGIucG9zTWF0cml4LG0sZix0LnRyYW5zZm9ybSxSKTtwLnVuaWZvcm1NYXRyaXg0ZnYodS51bmlmb3Jtcy51X2dsX2Nvb3JkX21hdHJpeCwhMSx0LnRyYW5zbGF0ZVBvc01hdHJpeChNLHcscixhLCEwKSksXz8ocC51bmlmb3JtTWF0cml4NGZ2KHUudW5pZm9ybXMudV9sYWJlbF9wbGFuZV9tYXRyaXgsITEsY2kpLGdlKEUsYi5wb3NNYXRyaXgsdCxvLEQsTSxtLGMpKTpwLnVuaWZvcm1NYXRyaXg0ZnYodS51bmlmb3Jtcy51X2xhYmVsX3BsYW5lX21hdHJpeCwhMSxEKSxwLnVuaWZvcm0xZih1LnVuaWZvcm1zLnVfZmFkZV9jaGFuZ2UsdC5vcHRpb25zLmZhZGVEdXJhdGlvbj90LnN5bWJvbEZhZGVDaGFuZ2U6MSksZGkodSxJLHQsaSx3LFQsbyxDLG0pO319fX1mdW5jdGlvbiBwaShlLGksbixvLHIsYSxzKXt2YXIgbD1pLmNvbnRleHQuZ2wsYz1pLnRyYW5zZm9ybTtsLnVuaWZvcm0xaShlLnVuaWZvcm1zLnVfcGl0Y2hfd2l0aF9tYXAsYT8xOjApLGwudW5pZm9ybTFmKGUudW5pZm9ybXMudV9pc190ZXh0LG8/MTowKSxsLnVuaWZvcm0xZihlLnVuaWZvcm1zLnVfcGl0Y2gsYy5waXRjaC8zNjAqMipNYXRoLlBJKTt2YXIgdT1cImNvbnN0YW50XCI9PT1zLmZ1bmN0aW9uVHlwZXx8XCJzb3VyY2VcIj09PXMuZnVuY3Rpb25UeXBlLGg9XCJjb25zdGFudFwiPT09cy5mdW5jdGlvblR5cGV8fFwiY2FtZXJhXCI9PT1zLmZ1bmN0aW9uVHlwZTtsLnVuaWZvcm0xaShlLnVuaWZvcm1zLnVfaXNfc2l6ZV96b29tX2NvbnN0YW50LHU/MTowKSxsLnVuaWZvcm0xaShlLnVuaWZvcm1zLnVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50LGg/MTowKSxsLnVuaWZvcm0xZihlLnVuaWZvcm1zLnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSxjLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UpO3ZhciBwPXQuZXZhbHVhdGVTaXplRm9yWm9vbShzLGMuem9vbSx1aS5wcm9wZXJ0aWVzW28/XCJ0ZXh0LXNpemVcIjpcImljb24tc2l6ZVwiXSk7dm9pZCAwIT09cC51U2l6ZVQmJmwudW5pZm9ybTFmKGUudW5pZm9ybXMudV9zaXplX3QscC51U2l6ZVQpLHZvaWQgMCE9PXAudVNpemUmJmwudW5pZm9ybTFmKGUudW5pZm9ybXMudV9zaXplLHAudVNpemUpLGwudW5pZm9ybTFmKGUudW5pZm9ybXMudV9hc3BlY3RfcmF0aW8sYy53aWR0aC9jLmhlaWdodCksbC51bmlmb3JtMWkoZS51bmlmb3Jtcy51X3JvdGF0ZV9zeW1ib2wscj8xOjApO31mdW5jdGlvbiBkaSh0LGUsaSxuLG8scixhLHMsbCl7dmFyIGM9aS5jb250ZXh0LHU9Yy5nbCxoPWkudHJhbnNmb3JtO2lmKHMpe3ZhciBwPTAhPT1uLnBhaW50LmdldChhP1widGV4dC1oYWxvLXdpZHRoXCI6XCJpY29uLWhhbG8td2lkdGhcIikuY29uc3RhbnRPcigxKSxkPWw/TWF0aC5jb3MoaC5fcGl0Y2gpKmguY2FtZXJhVG9DZW50ZXJEaXN0YW5jZToxO3UudW5pZm9ybTFmKHQudW5pZm9ybXMudV9nYW1tYV9zY2FsZSxkKSxwJiYodS51bmlmb3JtMWYodC51bmlmb3Jtcy51X2lzX2hhbG8sMSksZmkocixuLGMsdCkpLHUudW5pZm9ybTFmKHQudW5pZm9ybXMudV9pc19oYWxvLDApO31maShyLG4sYyx0KTt9ZnVuY3Rpb24gZmkodCxlLGksbil7bi5kcmF3KGksaS5nbC5UUklBTkdMRVMsZS5pZCx0LmxheW91dFZlcnRleEJ1ZmZlcix0LmluZGV4QnVmZmVyLHQuc2VnbWVudHMsdC5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGUuaWQpLHQuZHluYW1pY0xheW91dFZlcnRleEJ1ZmZlcix0Lm9wYWNpdHlWZXJ0ZXhCdWZmZXIpO31mdW5jdGlvbiBtaSh0LGUsaSxuLG8sYSxzLGwsYyl7dmFyIHUsaCxwLGQsZj1lLmNvbnRleHQsbT1mLmdsLF89by5wYWludC5nZXQoXCJsaW5lLWRhc2hhcnJheVwiKSxnPW8ucGFpbnQuZ2V0KFwibGluZS1wYXR0ZXJuXCIpO2lmKGx8fGMpe3ZhciB2PTEvemUoaSwxLGUudHJhbnNmb3JtLnRpbGVab29tKTtpZihfKXt1PWUubGluZUF0bGFzLmdldERhc2goXy5mcm9tLFwicm91bmRcIj09PW8ubGF5b3V0LmdldChcImxpbmUtY2FwXCIpKSxoPWUubGluZUF0bGFzLmdldERhc2goXy50byxcInJvdW5kXCI9PT1vLmxheW91dC5nZXQoXCJsaW5lLWNhcFwiKSk7dmFyIHk9dS53aWR0aCpfLmZyb21TY2FsZSx4PWgud2lkdGgqXy50b1NjYWxlO20udW5pZm9ybTJmKHQudW5pZm9ybXMudV9wYXR0ZXJuc2NhbGVfYSx2L3ksLXUuaGVpZ2h0LzIpLG0udW5pZm9ybTJmKHQudW5pZm9ybXMudV9wYXR0ZXJuc2NhbGVfYix2L3gsLWguaGVpZ2h0LzIpLG0udW5pZm9ybTFmKHQudW5pZm9ybXMudV9zZGZnYW1tYSxlLmxpbmVBdGxhcy53aWR0aC8oMjU2Kk1hdGgubWluKHkseCkqci5kZXZpY2VQaXhlbFJhdGlvKS8yKTt9ZWxzZSBpZihnKXtpZihwPWUuaW1hZ2VNYW5hZ2VyLmdldFBhdHRlcm4oZy5mcm9tKSxkPWUuaW1hZ2VNYW5hZ2VyLmdldFBhdHRlcm4oZy50byksIXB8fCFkKXJldHVybjttLnVuaWZvcm0yZih0LnVuaWZvcm1zLnVfcGF0dGVybl9zaXplX2EscC5kaXNwbGF5U2l6ZVswXSpnLmZyb21TY2FsZS92LHAuZGlzcGxheVNpemVbMV0pLG0udW5pZm9ybTJmKHQudW5pZm9ybXMudV9wYXR0ZXJuX3NpemVfYixkLmRpc3BsYXlTaXplWzBdKmcudG9TY2FsZS92LGQuZGlzcGxheVNpemVbMV0pO3ZhciBiPWUuaW1hZ2VNYW5hZ2VyLmdldFBpeGVsU2l6ZSgpLHc9Yi53aWR0aCxFPWIuaGVpZ2h0O20udW5pZm9ybTJmdih0LnVuaWZvcm1zLnVfdGV4c2l6ZSxbdyxFXSk7fW0udW5pZm9ybTJmKHQudW5pZm9ybXMudV9nbF91bml0c190b19waXhlbHMsMS9lLnRyYW5zZm9ybS5waXhlbHNUb0dMVW5pdHNbMF0sMS9lLnRyYW5zZm9ybS5waXhlbHNUb0dMVW5pdHNbMV0pO31sJiYoXz8obS51bmlmb3JtMWkodC51bmlmb3Jtcy51X2ltYWdlLDApLGYuYWN0aXZlVGV4dHVyZS5zZXQobS5URVhUVVJFMCksZS5saW5lQXRsYXMuYmluZChmKSxtLnVuaWZvcm0xZih0LnVuaWZvcm1zLnVfdGV4X3lfYSx1LnkpLG0udW5pZm9ybTFmKHQudW5pZm9ybXMudV90ZXhfeV9iLGgueSksbS51bmlmb3JtMWYodC51bmlmb3Jtcy51X21peCxfLnQpKTpnJiYobS51bmlmb3JtMWkodC51bmlmb3Jtcy51X2ltYWdlLDApLGYuYWN0aXZlVGV4dHVyZS5zZXQobS5URVhUVVJFMCksZS5pbWFnZU1hbmFnZXIuYmluZChmKSxtLnVuaWZvcm0yZnYodC51bmlmb3Jtcy51X3BhdHRlcm5fdGxfYSxwLnRsKSxtLnVuaWZvcm0yZnYodC51bmlmb3Jtcy51X3BhdHRlcm5fYnJfYSxwLmJyKSxtLnVuaWZvcm0yZnYodC51bmlmb3Jtcy51X3BhdHRlcm5fdGxfYixkLnRsKSxtLnVuaWZvcm0yZnYodC51bmlmb3Jtcy51X3BhdHRlcm5fYnJfYixkLmJyKSxtLnVuaWZvcm0xZih0LnVuaWZvcm1zLnVfZmFkZSxnLnQpKSksZi5zZXRTdGVuY2lsTW9kZShlLnN0ZW5jaWxNb2RlRm9yQ2xpcHBpbmcoYSkpO3ZhciBUPWUudHJhbnNsYXRlUG9zTWF0cml4KGEucG9zTWF0cml4LGksby5wYWludC5nZXQoXCJsaW5lLXRyYW5zbGF0ZVwiKSxvLnBhaW50LmdldChcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiKSk7aWYobS51bmlmb3JtTWF0cml4NGZ2KHQudW5pZm9ybXMudV9tYXRyaXgsITEsVCksbS51bmlmb3JtMWYodC51bmlmb3Jtcy51X3JhdGlvLDEvemUoaSwxLGUudHJhbnNmb3JtLnpvb20pKSxvLnBhaW50LmdldChcImxpbmUtZ3JhZGllbnRcIikpe2YuYWN0aXZlVGV4dHVyZS5zZXQobS5URVhUVVJFMCk7dmFyIEk9by5ncmFkaWVudFRleHR1cmU7aWYoIW8uZ3JhZGllbnQpcmV0dXJuO0l8fChJPW8uZ3JhZGllbnRUZXh0dXJlPW5ldyBNKGYsby5ncmFkaWVudCxtLlJHQkEpKSxJLmJpbmQobS5MSU5FQVIsbS5DTEFNUF9UT19FREdFKSxtLnVuaWZvcm0xaSh0LnVuaWZvcm1zLnVfaW1hZ2UsMCk7fXQuZHJhdyhmLG0uVFJJQU5HTEVTLG8uaWQsbi5sYXlvdXRWZXJ0ZXhCdWZmZXIsbi5pbmRleEJ1ZmZlcixuLnNlZ21lbnRzLHMpO312YXIgX2k9ZnVuY3Rpb24odCxlKXtpZighdClyZXR1cm4hMTt2YXIgaT1lLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQuZnJvbSksbj1lLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQudG8pO3JldHVybiFpfHwhbn0sZ2k9ZnVuY3Rpb24odCxlLGkpe3ZhciBuPWUuY29udGV4dCxvPW4uZ2wscj1lLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQuZnJvbSksYT1lLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQudG8pO28udW5pZm9ybTFpKGkudW5pZm9ybXMudV9pbWFnZSwwKSxvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3BhdHRlcm5fdGxfYSxyLnRsKSxvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3BhdHRlcm5fYnJfYSxyLmJyKSxvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3BhdHRlcm5fdGxfYixhLnRsKSxvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3BhdHRlcm5fYnJfYixhLmJyKTt2YXIgcz1lLmltYWdlTWFuYWdlci5nZXRQaXhlbFNpemUoKSxsPXMud2lkdGgsYz1zLmhlaWdodDtvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3RleHNpemUsW2wsY10pLG8udW5pZm9ybTFmKGkudW5pZm9ybXMudV9taXgsdC50KSxvLnVuaWZvcm0yZnYoaS51bmlmb3Jtcy51X3BhdHRlcm5fc2l6ZV9hLHIuZGlzcGxheVNpemUpLG8udW5pZm9ybTJmdihpLnVuaWZvcm1zLnVfcGF0dGVybl9zaXplX2IsYS5kaXNwbGF5U2l6ZSksby51bmlmb3JtMWYoaS51bmlmb3Jtcy51X3NjYWxlX2EsdC5mcm9tU2NhbGUpLG8udW5pZm9ybTFmKGkudW5pZm9ybXMudV9zY2FsZV9iLHQudG9TY2FsZSksbi5hY3RpdmVUZXh0dXJlLnNldChvLlRFWFRVUkUwKSxlLmltYWdlTWFuYWdlci5iaW5kKGUuY29udGV4dCk7fSx2aT1mdW5jdGlvbih0LGUsaSl7dmFyIG49ZS5jb250ZXh0LmdsO24udW5pZm9ybTFmKGkudW5pZm9ybXMudV90aWxlX3VuaXRzX3RvX3BpeGVscywxL3plKHQsMSxlLnRyYW5zZm9ybS50aWxlWm9vbSkpO3ZhciBvPU1hdGgucG93KDIsdC50aWxlSUQub3ZlcnNjYWxlZFopLHI9dC50aWxlU2l6ZSpNYXRoLnBvdygyLGUudHJhbnNmb3JtLnRpbGVab29tKS9vLGE9cioodC50aWxlSUQuY2Fub25pY2FsLngrdC50aWxlSUQud3JhcCpvKSxzPXIqdC50aWxlSUQuY2Fub25pY2FsLnk7bi51bmlmb3JtMmYoaS51bmlmb3Jtcy51X3BpeGVsX2Nvb3JkX3VwcGVyLGE+PjE2LHM+PjE2KSxuLnVuaWZvcm0yZihpLnVuaWZvcm1zLnVfcGl4ZWxfY29vcmRfbG93ZXIsNjU1MzUmYSw2NTUzNSZzKTt9O2Z1bmN0aW9uIHlpKHQsZSxpLG4sbyl7aWYoIV9pKGkucGFpbnQuZ2V0KFwiZmlsbC1wYXR0ZXJuXCIpLHQpKWZvcih2YXIgcj0hMCxhPTAscz1uO2E8cy5sZW5ndGg7YSs9MSl7dmFyIGw9c1thXSxjPWUuZ2V0VGlsZShsKSx1PWMuZ2V0QnVja2V0KGkpO3UmJih0LmNvbnRleHQuc2V0U3RlbmNpbE1vZGUodC5zdGVuY2lsTW9kZUZvckNsaXBwaW5nKGwpKSxvKHQsZSxpLGMsbCx1LHIpLHI9ITEpO319ZnVuY3Rpb24geGkodCxlLGksbixvLHIsYSl7dmFyIHM9dC5jb250ZXh0LmdsLGw9ci5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGkuaWQpO3dpKFwiZmlsbFwiLGkucGFpbnQuZ2V0KFwiZmlsbC1wYXR0ZXJuXCIpLHQsbCxpLG4sbyxhKS5kcmF3KHQuY29udGV4dCxzLlRSSUFOR0xFUyxpLmlkLHIubGF5b3V0VmVydGV4QnVmZmVyLHIuaW5kZXhCdWZmZXIsci5zZWdtZW50cyxsKTt9ZnVuY3Rpb24gYmkodCxlLGksbixvLHIsYSl7dmFyIHM9dC5jb250ZXh0LmdsLGw9ci5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGkuaWQpLGM9d2koXCJmaWxsT3V0bGluZVwiLGkuZ2V0UGFpbnRQcm9wZXJ0eShcImZpbGwtb3V0bGluZS1jb2xvclwiKT9udWxsOmkucGFpbnQuZ2V0KFwiZmlsbC1wYXR0ZXJuXCIpLHQsbCxpLG4sbyxhKTtzLnVuaWZvcm0yZihjLnVuaWZvcm1zLnVfd29ybGQscy5kcmF3aW5nQnVmZmVyV2lkdGgscy5kcmF3aW5nQnVmZmVySGVpZ2h0KSxjLmRyYXcodC5jb250ZXh0LHMuTElORVMsaS5pZCxyLmxheW91dFZlcnRleEJ1ZmZlcixyLmluZGV4QnVmZmVyMixyLnNlZ21lbnRzMixsKTt9ZnVuY3Rpb24gd2kodCxlLGksbixvLHIsYSxzKXt2YXIgbCxjPWkuY29udGV4dC5wcm9ncmFtLmdldCgpO3JldHVybiBlPyhsPWkudXNlUHJvZ3JhbSh0K1wiUGF0dGVyblwiLG4pLChzfHxsLnByb2dyYW0hPT1jKSYmKG4uc2V0VW5pZm9ybXMoaS5jb250ZXh0LGwsby5wYWludCx7em9vbTppLnRyYW5zZm9ybS56b29tfSksZ2koZSxpLGwpKSx2aShyLGksbCkpOihsPWkudXNlUHJvZ3JhbSh0LG4pLChzfHxsLnByb2dyYW0hPT1jKSYmbi5zZXRVbmlmb3JtcyhpLmNvbnRleHQsbCxvLnBhaW50LHt6b29tOmkudHJhbnNmb3JtLnpvb219KSksaS5jb250ZXh0LmdsLnVuaWZvcm1NYXRyaXg0ZnYobC51bmlmb3Jtcy51X21hdHJpeCwhMSxpLnRyYW5zbGF0ZVBvc01hdHJpeChhLnBvc01hdHJpeCxyLG8ucGFpbnQuZ2V0KFwiZmlsbC10cmFuc2xhdGVcIiksby5wYWludC5nZXQoXCJmaWxsLXRyYW5zbGF0ZS1hbmNob3JcIikpKSxsfXZhciBFaT10LmRlZmF1bHQkMjAubWF0MyxUaT10LmRlZmF1bHQkMjAubWF0NCxJaT10LmRlZmF1bHQkMjAudmVjMztmdW5jdGlvbiBDaSh0LGUsaSxuLG8scixhKXt2YXIgcz10LmNvbnRleHQsbD1zLmdsLGM9aS5wYWludC5nZXQoXCJmaWxsLWV4dHJ1c2lvbi1wYXR0ZXJuXCIpLHU9dC5jb250ZXh0LnByb2dyYW0uZ2V0KCksaD1yLnByb2dyYW1Db25maWd1cmF0aW9ucy5nZXQoaS5pZCkscD10LnVzZVByb2dyYW0oYz9cImZpbGxFeHRydXNpb25QYXR0ZXJuXCI6XCJmaWxsRXh0cnVzaW9uXCIsaCk7aWYoKGF8fHAucHJvZ3JhbSE9PXUpJiZoLnNldFVuaWZvcm1zKHMscCxpLnBhaW50LHt6b29tOnQudHJhbnNmb3JtLnpvb219KSxjKXtpZihfaShjLHQpKXJldHVybjtnaShjLHQscCksdmkobix0LHApLGwudW5pZm9ybTFmKHAudW5pZm9ybXMudV9oZWlnaHRfZmFjdG9yLC1NYXRoLnBvdygyLG8ub3ZlcnNjYWxlZFopL24udGlsZVNpemUvOCk7fXQuY29udGV4dC5nbC51bmlmb3JtTWF0cml4NGZ2KHAudW5pZm9ybXMudV9tYXRyaXgsITEsdC50cmFuc2xhdGVQb3NNYXRyaXgoby5wb3NNYXRyaXgsbixpLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZS1hbmNob3JcIikpKSxmdW5jdGlvbih0LGUpe3ZhciBpPWUuY29udGV4dC5nbCxuPWUuc3R5bGUubGlnaHQsbz1uLnByb3BlcnRpZXMuZ2V0KFwicG9zaXRpb25cIikscj1bby54LG8ueSxvLnpdLGE9RWkuY3JlYXRlKCk7XCJ2aWV3cG9ydFwiPT09bi5wcm9wZXJ0aWVzLmdldChcImFuY2hvclwiKSYmRWkuZnJvbVJvdGF0aW9uKGEsLWUudHJhbnNmb3JtLmFuZ2xlKTtJaS50cmFuc2Zvcm1NYXQzKHIscixhKTt2YXIgcz1uLnByb3BlcnRpZXMuZ2V0KFwiY29sb3JcIik7aS51bmlmb3JtM2Z2KHQudW5pZm9ybXMudV9saWdodHBvcyxyKSxpLnVuaWZvcm0xZih0LnVuaWZvcm1zLnVfbGlnaHRpbnRlbnNpdHksbi5wcm9wZXJ0aWVzLmdldChcImludGVuc2l0eVwiKSksaS51bmlmb3JtM2YodC51bmlmb3Jtcy51X2xpZ2h0Y29sb3Iscy5yLHMuZyxzLmIpO30ocCx0KSxwLmRyYXcocyxsLlRSSUFOR0xFUyxpLmlkLHIubGF5b3V0VmVydGV4QnVmZmVyLHIuaW5kZXhCdWZmZXIsci5zZWdtZW50cyxoKTt9ZnVuY3Rpb24gU2koZSxpLG4pe3ZhciBvPWUuY29udGV4dCxyPW8uZ2wsYT1pLmZibztpZihhKXt2YXIgcz1lLnVzZVByb2dyYW0oXCJoaWxsc2hhZGVcIiksbD1lLnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgoaS50aWxlSUQudG9VbndyYXBwZWQoKSwhMCk7IWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj1pLnBhaW50LmdldChcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tZGlyZWN0aW9uXCIpKihNYXRoLlBJLzE4MCk7XCJ2aWV3cG9ydFwiPT09aS5wYWludC5nZXQoXCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWFuY2hvclwiKSYmKG4tPWUudHJhbnNmb3JtLmFuZ2xlKSxlLmNvbnRleHQuZ2wudW5pZm9ybTJmKHQudW5pZm9ybXMudV9saWdodCxpLnBhaW50LmdldChcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIiksbik7fShzLGUsbik7dmFyIGM9ZnVuY3Rpb24oZSxpKXt2YXIgbj1pLnRvQ29vcmRpbmF0ZSgpLG89bmV3IHQuZGVmYXVsdCQxNyhuLmNvbHVtbixuLnJvdysxLG4uem9vbSk7cmV0dXJuW2UudHJhbnNmb3JtLmNvb3JkaW5hdGVMb2NhdGlvbihuKS5sYXQsZS50cmFuc2Zvcm0uY29vcmRpbmF0ZUxvY2F0aW9uKG8pLmxhdF19KGUsaS50aWxlSUQpO28uYWN0aXZlVGV4dHVyZS5zZXQoci5URVhUVVJFMCksci5iaW5kVGV4dHVyZShyLlRFWFRVUkVfMkQsYS5jb2xvckF0dGFjaG1lbnQuZ2V0KCkpLHIudW5pZm9ybU1hdHJpeDRmdihzLnVuaWZvcm1zLnVfbWF0cml4LCExLGwpLHIudW5pZm9ybTJmdihzLnVuaWZvcm1zLnVfbGF0cmFuZ2UsYyksci51bmlmb3JtMWkocy51bmlmb3Jtcy51X2ltYWdlLDApO3ZhciB1PW4ucGFpbnQuZ2V0KFwiaGlsbHNoYWRlLXNoYWRvdy1jb2xvclwiKTtyLnVuaWZvcm00ZihzLnVuaWZvcm1zLnVfc2hhZG93LHUucix1LmcsdS5iLHUuYSk7dmFyIGg9bi5wYWludC5nZXQoXCJoaWxsc2hhZGUtaGlnaGxpZ2h0LWNvbG9yXCIpO3IudW5pZm9ybTRmKHMudW5pZm9ybXMudV9oaWdobGlnaHQsaC5yLGguZyxoLmIsaC5hKTt2YXIgcD1uLnBhaW50LmdldChcImhpbGxzaGFkZS1hY2NlbnQtY29sb3JcIik7aWYoci51bmlmb3JtNGYocy51bmlmb3Jtcy51X2FjY2VudCxwLnIscC5nLHAuYixwLmEpLGkubWFza2VkQm91bmRzQnVmZmVyJiZpLm1hc2tlZEluZGV4QnVmZmVyJiZpLnNlZ21lbnRzKXMuZHJhdyhvLHIuVFJJQU5HTEVTLG4uaWQsaS5tYXNrZWRCb3VuZHNCdWZmZXIsaS5tYXNrZWRJbmRleEJ1ZmZlcixpLnNlZ21lbnRzKTtlbHNle3ZhciBkPWUucmFzdGVyQm91bmRzQnVmZmVyO2UucmFzdGVyQm91bmRzVkFPLmJpbmQobyxzLGQsW10pLHIuZHJhd0FycmF5cyhyLlRSSUFOR0xFX1NUUklQLDAsZC5sZW5ndGgpO319fWZ1bmN0aW9uIHppKGUsaSxuKXt2YXIgbz1lLmNvbnRleHQscj1vLmdsO2lmKGkuZGVtJiZpLmRlbS5sZXZlbCl7dmFyIGE9aS5kZW0ubGV2ZWwuZGltLHM9aS5kZW0uZ2V0UGl4ZWxzKCk7aWYoby5hY3RpdmVUZXh0dXJlLnNldChyLlRFWFRVUkUxKSxvLnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhLnNldCghMSksaS5kZW1UZXh0dXJlPWkuZGVtVGV4dHVyZXx8ZS5nZXRUaWxlVGV4dHVyZShpLnRpbGVTaXplKSxpLmRlbVRleHR1cmUpe3ZhciBsPWkuZGVtVGV4dHVyZTtsLnVwZGF0ZShzLHtwcmVtdWx0aXBseTohMX0pLGwuYmluZChyLk5FQVJFU1Qsci5DTEFNUF9UT19FREdFKTt9ZWxzZSBpLmRlbVRleHR1cmU9bmV3IE0obyxzLHIuUkdCQSx7cHJlbXVsdGlwbHk6ITF9KSxpLmRlbVRleHR1cmUuYmluZChyLk5FQVJFU1Qsci5DTEFNUF9UT19FREdFKTtvLmFjdGl2ZVRleHR1cmUuc2V0KHIuVEVYVFVSRTApO3ZhciBjPWkuZmJvO2lmKCFjKXt2YXIgdT1uZXcgTShvLHt3aWR0aDphLGhlaWdodDphLGRhdGE6bnVsbH0sci5SR0JBKTt1LmJpbmQoci5MSU5FQVIsci5DTEFNUF9UT19FREdFKSwoYz1pLmZibz1vLmNyZWF0ZUZyYW1lYnVmZmVyKGEsYSkpLmNvbG9yQXR0YWNobWVudC5zZXQodS50ZXh0dXJlKTt9by5iaW5kRnJhbWVidWZmZXIuc2V0KGMuZnJhbWVidWZmZXIpLG8udmlld3BvcnQuc2V0KFswLDAsYSxhXSk7dmFyIGg9dC5tYXQ0LmNyZWF0ZSgpO3QubWF0NC5vcnRobyhoLDAsdC5kZWZhdWx0JDgsLXQuZGVmYXVsdCQ4LDAsMCwxKSx0Lm1hdDQudHJhbnNsYXRlKGgsaCxbMCwtdC5kZWZhdWx0JDgsMF0pO3ZhciBwPWUudXNlUHJvZ3JhbShcImhpbGxzaGFkZVByZXBhcmVcIik7ci51bmlmb3JtTWF0cml4NGZ2KHAudW5pZm9ybXMudV9tYXRyaXgsITEsaCksci51bmlmb3JtMWYocC51bmlmb3Jtcy51X3pvb20saS50aWxlSUQub3ZlcnNjYWxlZFopLHIudW5pZm9ybTJmdihwLnVuaWZvcm1zLnVfZGltZW5zaW9uLFsyKmEsMiphXSksci51bmlmb3JtMWkocC51bmlmb3Jtcy51X2ltYWdlLDEpLHIudW5pZm9ybTFmKHAudW5pZm9ybXMudV9tYXh6b29tLG4pO3ZhciBkPWUucmFzdGVyQm91bmRzQnVmZmVyO2UucmFzdGVyQm91bmRzVkFPLmJpbmQobyxwLGQsW10pLHIuZHJhd0FycmF5cyhyLlRSSUFOR0xFX1NUUklQLDAsZC5sZW5ndGgpLGkubmVlZHNIaWxsc2hhZGVQcmVwYXJlPSExO319ZnVuY3Rpb24gQWkoZSxpLG4sbyxhKXt2YXIgcz1vLnBhaW50LmdldChcInJhc3Rlci1mYWRlLWR1cmF0aW9uXCIpO2lmKHM+MCl7dmFyIGw9ci5ub3coKSxjPShsLWUudGltZUFkZGVkKS9zLHU9aT8obC1pLnRpbWVBZGRlZCkvczotMSxoPW4uZ2V0U291cmNlKCkscD1hLmNvdmVyaW5nWm9vbUxldmVsKHt0aWxlU2l6ZTpoLnRpbGVTaXplLHJvdW5kWm9vbTpoLnJvdW5kWm9vbX0pLGQ9IWl8fE1hdGguYWJzKGkudGlsZUlELm92ZXJzY2FsZWRaLXApPk1hdGguYWJzKGUudGlsZUlELm92ZXJzY2FsZWRaLXApLGY9ZCYmZS5yZWZyZXNoZWRVcG9uRXhwaXJhdGlvbj8xOnQuY2xhbXAoZD9jOjEtdSwwLDEpO3JldHVybiBlLnJlZnJlc2hlZFVwb25FeHBpcmF0aW9uJiZjPj0xJiYoZS5yZWZyZXNoZWRVcG9uRXhwaXJhdGlvbj0hMSksaT97b3BhY2l0eToxLG1peDoxLWZ9OntvcGFjaXR5OmYsbWl4OjB9fXJldHVybntvcGFjaXR5OjEsbWl4OjB9fWZ1bmN0aW9uIFJpKGUsaSxuKXt2YXIgbz1lLmNvbnRleHQsYT1vLmdsO28ubGluZVdpZHRoLnNldCgxKnIuZGV2aWNlUGl4ZWxSYXRpbyk7dmFyIHM9bi5wb3NNYXRyaXgsbD1lLnVzZVByb2dyYW0oXCJkZWJ1Z1wiKTtvLnNldERlcHRoTW9kZSgkdC5kaXNhYmxlZCksby5zZXRTdGVuY2lsTW9kZShHdC5kaXNhYmxlZCksby5zZXRDb2xvck1vZGUoZS5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCkpLGEudW5pZm9ybU1hdHJpeDRmdihsLnVuaWZvcm1zLnVfbWF0cml4LCExLHMpLGEudW5pZm9ybTRmKGwudW5pZm9ybXMudV9jb2xvciwxLDAsMCwxKSxlLmRlYnVnVkFPLmJpbmQobyxsLGUuZGVidWdCdWZmZXIsW10pLGEuZHJhd0FycmF5cyhhLkxJTkVfU1RSSVAsMCxlLmRlYnVnQnVmZmVyLmxlbmd0aCk7Zm9yKHZhciBjPWZ1bmN0aW9uKHQsZSxpLG4pe249bnx8MTt2YXIgbyxyLGEscyxsLGMsdSxoLHA9W107Zm9yKG89MCxyPXQubGVuZ3RoO288cjtvKyspaWYobD1EaVt0W29dXSl7Zm9yKGg9bnVsbCxhPTAscz1sWzFdLmxlbmd0aDthPHM7YSs9MiktMT09PWxbMV1bYV0mJi0xPT09bFsxXVthKzFdP2g9bnVsbDooYz1lK2xbMV1bYV0qbix1PWktbFsxXVthKzFdKm4saCYmcC5wdXNoKGgueCxoLnksYyx1KSxoPXt4OmMseTp1fSk7ZSs9bFswXSpuO31yZXR1cm4gcH0obi50b1N0cmluZygpLDUwLDIwMCw1KSx1PW5ldyB0LlBvc0FycmF5LGg9MDtoPGMubGVuZ3RoO2grPTIpdS5lbXBsYWNlQmFjayhjW2hdLGNbaCsxXSk7dmFyIHA9by5jcmVhdGVWZXJ0ZXhCdWZmZXIodSx0aS5tZW1iZXJzKTsobmV3IHR0KS5iaW5kKG8sbCxwLFtdKSxhLnVuaWZvcm00ZihsLnVuaWZvcm1zLnVfY29sb3IsMSwxLDEsMSk7Zm9yKHZhciBkPWkuZ2V0VGlsZShuKS50aWxlU2l6ZSxmPXQuZGVmYXVsdCQ4LyhNYXRoLnBvdygyLGUudHJhbnNmb3JtLnpvb20tbi5vdmVyc2NhbGVkWikqZCksbT1bWy0xLC0xXSxbLTEsMV0sWzEsLTFdLFsxLDFdXSxfPTA7XzxtLmxlbmd0aDtfKyspe3ZhciBnPW1bX107YS51bmlmb3JtTWF0cml4NGZ2KGwudW5pZm9ybXMudV9tYXRyaXgsITEsdC5tYXQ0LnRyYW5zbGF0ZShbXSxzLFtmKmdbMF0sZipnWzFdLDBdKSksYS5kcmF3QXJyYXlzKGEuTElORVMsMCxwLmxlbmd0aCk7fWEudW5pZm9ybTRmKGwudW5pZm9ybXMudV9jb2xvciwwLDAsMCwxKSxhLnVuaWZvcm1NYXRyaXg0ZnYobC51bmlmb3Jtcy51X21hdHJpeCwhMSxzKSxhLmRyYXdBcnJheXMoYS5MSU5FUywwLHAubGVuZ3RoKTt9dmFyIERpPXtcIiBcIjpbMTYsW11dLFwiIVwiOlsxMCxbNSwyMSw1LDcsLTEsLTEsNSwyLDQsMSw1LDAsNiwxLDUsMl1dLCdcIic6WzE2LFs0LDIxLDQsMTQsLTEsLTEsMTIsMjEsMTIsMTRdXSxcIiNcIjpbMjEsWzExLDI1LDQsLTcsLTEsLTEsMTcsMjUsMTAsLTcsLTEsLTEsNCwxMiwxOCwxMiwtMSwtMSwzLDYsMTcsNl1dLCQ6WzIwLFs4LDI1LDgsLTQsLTEsLTEsMTIsMjUsMTIsLTQsLTEsLTEsMTcsMTgsMTUsMjAsMTIsMjEsOCwyMSw1LDIwLDMsMTgsMywxNiw0LDE0LDUsMTMsNywxMiwxMywxMCwxNSw5LDE2LDgsMTcsNiwxNywzLDE1LDEsMTIsMCw4LDAsNSwxLDMsM11dLFwiJVwiOlsyNCxbMjEsMjEsMywwLC0xLC0xLDgsMjEsMTAsMTksMTAsMTcsOSwxNSw3LDE0LDUsMTQsMywxNiwzLDE4LDQsMjAsNiwyMSw4LDIxLDEwLDIwLDEzLDE5LDE2LDE5LDE5LDIwLDIxLDIxLC0xLC0xLDE3LDcsMTUsNiwxNCw0LDE0LDIsMTYsMCwxOCwwLDIwLDEsMjEsMywyMSw1LDE5LDcsMTcsN11dLFwiJlwiOlsyNixbMjMsMTIsMjMsMTMsMjIsMTQsMjEsMTQsMjAsMTMsMTksMTEsMTcsNiwxNSwzLDEzLDEsMTEsMCw3LDAsNSwxLDQsMiwzLDQsMyw2LDQsOCw1LDksMTIsMTMsMTMsMTQsMTQsMTYsMTQsMTgsMTMsMjAsMTEsMjEsOSwyMCw4LDE4LDgsMTYsOSwxMywxMSwxMCwxNiwzLDE4LDEsMjAsMCwyMiwwLDIzLDEsMjMsMl1dLFwiJ1wiOlsxMCxbNSwxOSw0LDIwLDUsMjEsNiwyMCw2LDE4LDUsMTYsNCwxNV1dLFwiKFwiOlsxNCxbMTEsMjUsOSwyMyw3LDIwLDUsMTYsNCwxMSw0LDcsNSwyLDcsLTIsOSwtNSwxMSwtN11dLFwiKVwiOlsxNCxbMywyNSw1LDIzLDcsMjAsOSwxNiwxMCwxMSwxMCw3LDksMiw3LC0yLDUsLTUsMywtN11dLFwiKlwiOlsxNixbOCwyMSw4LDksLTEsLTEsMywxOCwxMywxMiwtMSwtMSwxMywxOCwzLDEyXV0sXCIrXCI6WzI2LFsxMywxOCwxMywwLC0xLC0xLDQsOSwyMiw5XV0sXCIsXCI6WzEwLFs2LDEsNSwwLDQsMSw1LDIsNiwxLDYsLTEsNSwtMyw0LC00XV0sXCItXCI6WzI2LFs0LDksMjIsOV1dLFwiLlwiOlsxMCxbNSwyLDQsMSw1LDAsNiwxLDUsMl1dLFwiL1wiOlsyMixbMjAsMjUsMiwtN11dLDA6WzIwLFs5LDIxLDYsMjAsNCwxNywzLDEyLDMsOSw0LDQsNiwxLDksMCwxMSwwLDE0LDEsMTYsNCwxNyw5LDE3LDEyLDE2LDE3LDE0LDIwLDExLDIxLDksMjFdXSwxOlsyMCxbNiwxNyw4LDE4LDExLDIxLDExLDBdXSwyOlsyMCxbNCwxNiw0LDE3LDUsMTksNiwyMCw4LDIxLDEyLDIxLDE0LDIwLDE1LDE5LDE2LDE3LDE2LDE1LDE1LDEzLDEzLDEwLDMsMCwxNywwXV0sMzpbMjAsWzUsMjEsMTYsMjEsMTAsMTMsMTMsMTMsMTUsMTIsMTYsMTEsMTcsOCwxNyw2LDE2LDMsMTQsMSwxMSwwLDgsMCw1LDEsNCwyLDMsNF1dLDQ6WzIwLFsxMywyMSwzLDcsMTgsNywtMSwtMSwxMywyMSwxMywwXV0sNTpbMjAsWzE1LDIxLDUsMjEsNCwxMiw1LDEzLDgsMTQsMTEsMTQsMTQsMTMsMTYsMTEsMTcsOCwxNyw2LDE2LDMsMTQsMSwxMSwwLDgsMCw1LDEsNCwyLDMsNF1dLDY6WzIwLFsxNiwxOCwxNSwyMCwxMiwyMSwxMCwyMSw3LDIwLDUsMTcsNCwxMiw0LDcsNSwzLDcsMSwxMCwwLDExLDAsMTQsMSwxNiwzLDE3LDYsMTcsNywxNiwxMCwxNCwxMiwxMSwxMywxMCwxMyw3LDEyLDUsMTAsNCw3XV0sNzpbMjAsWzE3LDIxLDcsMCwtMSwtMSwzLDIxLDE3LDIxXV0sODpbMjAsWzgsMjEsNSwyMCw0LDE4LDQsMTYsNSwxNCw3LDEzLDExLDEyLDE0LDExLDE2LDksMTcsNywxNyw0LDE2LDIsMTUsMSwxMiwwLDgsMCw1LDEsNCwyLDMsNCwzLDcsNCw5LDYsMTEsOSwxMiwxMywxMywxNSwxNCwxNiwxNiwxNiwxOCwxNSwyMCwxMiwyMSw4LDIxXV0sOTpbMjAsWzE2LDE0LDE1LDExLDEzLDksMTAsOCw5LDgsNiw5LDQsMTEsMywxNCwzLDE1LDQsMTgsNiwyMCw5LDIxLDEwLDIxLDEzLDIwLDE1LDE4LDE2LDE0LDE2LDksMTUsNCwxMywxLDEwLDAsOCwwLDUsMSw0LDNdXSxcIjpcIjpbMTAsWzUsMTQsNCwxMyw1LDEyLDYsMTMsNSwxNCwtMSwtMSw1LDIsNCwxLDUsMCw2LDEsNSwyXV0sXCI7XCI6WzEwLFs1LDE0LDQsMTMsNSwxMiw2LDEzLDUsMTQsLTEsLTEsNiwxLDUsMCw0LDEsNSwyLDYsMSw2LC0xLDUsLTMsNCwtNF1dLFwiPFwiOlsyNCxbMjAsMTgsNCw5LDIwLDBdXSxcIj1cIjpbMjYsWzQsMTIsMjIsMTIsLTEsLTEsNCw2LDIyLDZdXSxcIj5cIjpbMjQsWzQsMTgsMjAsOSw0LDBdXSxcIj9cIjpbMTgsWzMsMTYsMywxNyw0LDE5LDUsMjAsNywyMSwxMSwyMSwxMywyMCwxNCwxOSwxNSwxNywxNSwxNSwxNCwxMywxMywxMiw5LDEwLDksNywtMSwtMSw5LDIsOCwxLDksMCwxMCwxLDksMl1dLFwiQFwiOlsyNyxbMTgsMTMsMTcsMTUsMTUsMTYsMTIsMTYsMTAsMTUsOSwxNCw4LDExLDgsOCw5LDYsMTEsNSwxNCw1LDE2LDYsMTcsOCwtMSwtMSwxMiwxNiwxMCwxNCw5LDExLDksOCwxMCw2LDExLDUsLTEsLTEsMTgsMTYsMTcsOCwxNyw2LDE5LDUsMjEsNSwyMyw3LDI0LDEwLDI0LDEyLDIzLDE1LDIyLDE3LDIwLDE5LDE4LDIwLDE1LDIxLDEyLDIxLDksMjAsNywxOSw1LDE3LDQsMTUsMywxMiwzLDksNCw2LDUsNCw3LDIsOSwxLDEyLDAsMTUsMCwxOCwxLDIwLDIsMjEsMywtMSwtMSwxOSwxNiwxOCw4LDE4LDYsMTksNV1dLEE6WzE4LFs5LDIxLDEsMCwtMSwtMSw5LDIxLDE3LDAsLTEsLTEsNCw3LDE0LDddXSxCOlsyMSxbNCwyMSw0LDAsLTEsLTEsNCwyMSwxMywyMSwxNiwyMCwxNywxOSwxOCwxNywxOCwxNSwxNywxMywxNiwxMiwxMywxMSwtMSwtMSw0LDExLDEzLDExLDE2LDEwLDE3LDksMTgsNywxOCw0LDE3LDIsMTYsMSwxMywwLDQsMF1dLEM6WzIxLFsxOCwxNiwxNywxOCwxNSwyMCwxMywyMSw5LDIxLDcsMjAsNSwxOCw0LDE2LDMsMTMsMyw4LDQsNSw1LDMsNywxLDksMCwxMywwLDE1LDEsMTcsMywxOCw1XV0sRDpbMjEsWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTEsMjEsMTQsMjAsMTYsMTgsMTcsMTYsMTgsMTMsMTgsOCwxNyw1LDE2LDMsMTQsMSwxMSwwLDQsMF1dLEU6WzE5LFs0LDIxLDQsMCwtMSwtMSw0LDIxLDE3LDIxLC0xLC0xLDQsMTEsMTIsMTEsLTEsLTEsNCwwLDE3LDBdXSxGOlsxOCxbNCwyMSw0LDAsLTEsLTEsNCwyMSwxNywyMSwtMSwtMSw0LDExLDEyLDExXV0sRzpbMjEsWzE4LDE2LDE3LDE4LDE1LDIwLDEzLDIxLDksMjEsNywyMCw1LDE4LDQsMTYsMywxMywzLDgsNCw1LDUsMyw3LDEsOSwwLDEzLDAsMTUsMSwxNywzLDE4LDUsMTgsOCwtMSwtMSwxMyw4LDE4LDhdXSxIOlsyMixbNCwyMSw0LDAsLTEsLTEsMTgsMjEsMTgsMCwtMSwtMSw0LDExLDE4LDExXV0sSTpbOCxbNCwyMSw0LDBdXSxKOlsxNixbMTIsMjEsMTIsNSwxMSwyLDEwLDEsOCwwLDYsMCw0LDEsMywyLDIsNSwyLDddXSxLOlsyMSxbNCwyMSw0LDAsLTEsLTEsMTgsMjEsNCw3LC0xLC0xLDksMTIsMTgsMF1dLEw6WzE3LFs0LDIxLDQsMCwtMSwtMSw0LDAsMTYsMF1dLE06WzI0LFs0LDIxLDQsMCwtMSwtMSw0LDIxLDEyLDAsLTEsLTEsMjAsMjEsMTIsMCwtMSwtMSwyMCwyMSwyMCwwXV0sTjpbMjIsWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTgsMCwtMSwtMSwxOCwyMSwxOCwwXV0sTzpbMjIsWzksMjEsNywyMCw1LDE4LDQsMTYsMywxMywzLDgsNCw1LDUsMyw3LDEsOSwwLDEzLDAsMTUsMSwxNywzLDE4LDUsMTksOCwxOSwxMywxOCwxNiwxNywxOCwxNSwyMCwxMywyMSw5LDIxXV0sUDpbMjEsWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTMsMjEsMTYsMjAsMTcsMTksMTgsMTcsMTgsMTQsMTcsMTIsMTYsMTEsMTMsMTAsNCwxMF1dLFE6WzIyLFs5LDIxLDcsMjAsNSwxOCw0LDE2LDMsMTMsMyw4LDQsNSw1LDMsNywxLDksMCwxMywwLDE1LDEsMTcsMywxOCw1LDE5LDgsMTksMTMsMTgsMTYsMTcsMTgsMTUsMjAsMTMsMjEsOSwyMSwtMSwtMSwxMiw0LDE4LC0yXV0sUjpbMjEsWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTMsMjEsMTYsMjAsMTcsMTksMTgsMTcsMTgsMTUsMTcsMTMsMTYsMTIsMTMsMTEsNCwxMSwtMSwtMSwxMSwxMSwxOCwwXV0sUzpbMjAsWzE3LDE4LDE1LDIwLDEyLDIxLDgsMjEsNSwyMCwzLDE4LDMsMTYsNCwxNCw1LDEzLDcsMTIsMTMsMTAsMTUsOSwxNiw4LDE3LDYsMTcsMywxNSwxLDEyLDAsOCwwLDUsMSwzLDNdXSxUOlsxNixbOCwyMSw4LDAsLTEsLTEsMSwyMSwxNSwyMV1dLFU6WzIyLFs0LDIxLDQsNiw1LDMsNywxLDEwLDAsMTIsMCwxNSwxLDE3LDMsMTgsNiwxOCwyMV1dLFY6WzE4LFsxLDIxLDksMCwtMSwtMSwxNywyMSw5LDBdXSxXOlsyNCxbMiwyMSw3LDAsLTEsLTEsMTIsMjEsNywwLC0xLC0xLDEyLDIxLDE3LDAsLTEsLTEsMjIsMjEsMTcsMF1dLFg6WzIwLFszLDIxLDE3LDAsLTEsLTEsMTcsMjEsMywwXV0sWTpbMTgsWzEsMjEsOSwxMSw5LDAsLTEsLTEsMTcsMjEsOSwxMV1dLFo6WzIwLFsxNywyMSwzLDAsLTEsLTEsMywyMSwxNywyMSwtMSwtMSwzLDAsMTcsMF1dLFwiW1wiOlsxNCxbNCwyNSw0LC03LC0xLC0xLDUsMjUsNSwtNywtMSwtMSw0LDI1LDExLDI1LC0xLC0xLDQsLTcsMTEsLTddXSxcIlxcXFxcIjpbMTQsWzAsMjEsMTQsLTNdXSxcIl1cIjpbMTQsWzksMjUsOSwtNywtMSwtMSwxMCwyNSwxMCwtNywtMSwtMSwzLDI1LDEwLDI1LC0xLC0xLDMsLTcsMTAsLTddXSxcIl5cIjpbMTYsWzYsMTUsOCwxOCwxMCwxNSwtMSwtMSwzLDEyLDgsMTcsMTMsMTIsLTEsLTEsOCwxNyw4LDBdXSxfOlsxNixbMCwtMiwxNiwtMl1dLFwiYFwiOlsxMCxbNiwyMSw1LDIwLDQsMTgsNCwxNiw1LDE1LDYsMTYsNSwxN11dLGE6WzE5LFsxNSwxNCwxNSwwLC0xLC0xLDE1LDExLDEzLDEzLDExLDE0LDgsMTQsNiwxMyw0LDExLDMsOCwzLDYsNCwzLDYsMSw4LDAsMTEsMCwxMywxLDE1LDNdXSxiOlsxOSxbNCwyMSw0LDAsLTEsLTEsNCwxMSw2LDEzLDgsMTQsMTEsMTQsMTMsMTMsMTUsMTEsMTYsOCwxNiw2LDE1LDMsMTMsMSwxMSwwLDgsMCw2LDEsNCwzXV0sYzpbMTgsWzE1LDExLDEzLDEzLDExLDE0LDgsMTQsNiwxMyw0LDExLDMsOCwzLDYsNCwzLDYsMSw4LDAsMTEsMCwxMywxLDE1LDNdXSxkOlsxOSxbMTUsMjEsMTUsMCwtMSwtMSwxNSwxMSwxMywxMywxMSwxNCw4LDE0LDYsMTMsNCwxMSwzLDgsMyw2LDQsMyw2LDEsOCwwLDExLDAsMTMsMSwxNSwzXV0sZTpbMTgsWzMsOCwxNSw4LDE1LDEwLDE0LDEyLDEzLDEzLDExLDE0LDgsMTQsNiwxMyw0LDExLDMsOCwzLDYsNCwzLDYsMSw4LDAsMTEsMCwxMywxLDE1LDNdXSxmOlsxMixbMTAsMjEsOCwyMSw2LDIwLDUsMTcsNSwwLC0xLC0xLDIsMTQsOSwxNF1dLGc6WzE5LFsxNSwxNCwxNSwtMiwxNCwtNSwxMywtNiwxMSwtNyw4LC03LDYsLTYsLTEsLTEsMTUsMTEsMTMsMTMsMTEsMTQsOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsM11dLGg6WzE5LFs0LDIxLDQsMCwtMSwtMSw0LDEwLDcsMTMsOSwxNCwxMiwxNCwxNCwxMywxNSwxMCwxNSwwXV0saTpbOCxbMywyMSw0LDIwLDUsMjEsNCwyMiwzLDIxLC0xLC0xLDQsMTQsNCwwXV0sajpbMTAsWzUsMjEsNiwyMCw3LDIxLDYsMjIsNSwyMSwtMSwtMSw2LDE0LDYsLTMsNSwtNiwzLC03LDEsLTddXSxrOlsxNyxbNCwyMSw0LDAsLTEsLTEsMTQsMTQsNCw0LC0xLC0xLDgsOCwxNSwwXV0sbDpbOCxbNCwyMSw0LDBdXSxtOlszMCxbNCwxNCw0LDAsLTEsLTEsNCwxMCw3LDEzLDksMTQsMTIsMTQsMTQsMTMsMTUsMTAsMTUsMCwtMSwtMSwxNSwxMCwxOCwxMywyMCwxNCwyMywxNCwyNSwxMywyNiwxMCwyNiwwXV0sbjpbMTksWzQsMTQsNCwwLC0xLC0xLDQsMTAsNywxMyw5LDE0LDEyLDE0LDE0LDEzLDE1LDEwLDE1LDBdXSxvOlsxOSxbOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsMywxNiw2LDE2LDgsMTUsMTEsMTMsMTMsMTEsMTQsOCwxNF1dLHA6WzE5LFs0LDE0LDQsLTcsLTEsLTEsNCwxMSw2LDEzLDgsMTQsMTEsMTQsMTMsMTMsMTUsMTEsMTYsOCwxNiw2LDE1LDMsMTMsMSwxMSwwLDgsMCw2LDEsNCwzXV0scTpbMTksWzE1LDE0LDE1LC03LC0xLC0xLDE1LDExLDEzLDEzLDExLDE0LDgsMTQsNiwxMyw0LDExLDMsOCwzLDYsNCwzLDYsMSw4LDAsMTEsMCwxMywxLDE1LDNdXSxyOlsxMyxbNCwxNCw0LDAsLTEsLTEsNCw4LDUsMTEsNywxMyw5LDE0LDEyLDE0XV0sczpbMTcsWzE0LDExLDEzLDEzLDEwLDE0LDcsMTQsNCwxMywzLDExLDQsOSw2LDgsMTEsNywxMyw2LDE0LDQsMTQsMywxMywxLDEwLDAsNywwLDQsMSwzLDNdXSx0OlsxMixbNSwyMSw1LDQsNiwxLDgsMCwxMCwwLC0xLC0xLDIsMTQsOSwxNF1dLHU6WzE5LFs0LDE0LDQsNCw1LDEsNywwLDEwLDAsMTIsMSwxNSw0LC0xLC0xLDE1LDE0LDE1LDBdXSx2OlsxNixbMiwxNCw4LDAsLTEsLTEsMTQsMTQsOCwwXV0sdzpbMjIsWzMsMTQsNywwLC0xLC0xLDExLDE0LDcsMCwtMSwtMSwxMSwxNCwxNSwwLC0xLC0xLDE5LDE0LDE1LDBdXSx4OlsxNyxbMywxNCwxNCwwLC0xLC0xLDE0LDE0LDMsMF1dLHk6WzE2LFsyLDE0LDgsMCwtMSwtMSwxNCwxNCw4LDAsNiwtNCw0LC02LDIsLTcsMSwtN11dLHo6WzE3LFsxNCwxNCwzLDAsLTEsLTEsMywxNCwxNCwxNCwtMSwtMSwzLDAsMTQsMF1dLFwie1wiOlsxNCxbOSwyNSw3LDI0LDYsMjMsNSwyMSw1LDE5LDYsMTcsNywxNiw4LDE0LDgsMTIsNiwxMCwtMSwtMSw3LDI0LDYsMjIsNiwyMCw3LDE4LDgsMTcsOSwxNSw5LDEzLDgsMTEsNCw5LDgsNyw5LDUsOSwzLDgsMSw3LDAsNiwtMiw2LC00LDcsLTYsLTEsLTEsNiw4LDgsNiw4LDQsNywyLDYsMSw1LC0xLDUsLTMsNiwtNSw3LC02LDksLTddXSxcInxcIjpbOCxbNCwyNSw0LC03XV0sXCJ9XCI6WzE0LFs1LDI1LDcsMjQsOCwyMyw5LDIxLDksMTksOCwxNyw3LDE2LDYsMTQsNiwxMiw4LDEwLC0xLC0xLDcsMjQsOCwyMiw4LDIwLDcsMTgsNiwxNyw1LDE1LDUsMTMsNiwxMSwxMCw5LDYsNyw1LDUsNSwzLDYsMSw3LDAsOCwtMiw4LC00LDcsLTYsLTEsLTEsOCw4LDYsNiw2LDQsNywyLDgsMSw5LC0xLDksLTMsOCwtNSw3LC02LDUsLTddXSxcIn5cIjpbMjQsWzMsNiwzLDgsNCwxMSw2LDEyLDgsMTIsMTAsMTEsMTQsOCwxNiw3LDE4LDcsMjAsOCwyMSwxMCwtMSwtMSwzLDgsNCwxMCw2LDExLDgsMTEsMTAsMTAsMTQsNywxNiw2LDE4LDYsMjAsNywyMSwxMCwyMSwxMl1dfTt2YXIgTWk9e3N5bWJvbDpmdW5jdGlvbih0LGUsaSxuKXtpZihcInRyYW5zbHVjZW50XCI9PT10LnJlbmRlclBhc3Mpe3ZhciBvPXQuY29udGV4dDtvLnNldFN0ZW5jaWxNb2RlKEd0LmRpc2FibGVkKSxvLnNldENvbG9yTW9kZSh0LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSksMCE9PWkucGFpbnQuZ2V0KFwiaWNvbi1vcGFjaXR5XCIpLmNvbnN0YW50T3IoMSkmJmhpKHQsZSxpLG4sITEsaS5wYWludC5nZXQoXCJpY29uLXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcImljb24tdHJhbnNsYXRlLWFuY2hvclwiKSxpLmxheW91dC5nZXQoXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiKSxpLmxheW91dC5nZXQoXCJpY29uLXBpdGNoLWFsaWdubWVudFwiKSxpLmxheW91dC5nZXQoXCJpY29uLWtlZXAtdXByaWdodFwiKSksMCE9PWkucGFpbnQuZ2V0KFwidGV4dC1vcGFjaXR5XCIpLmNvbnN0YW50T3IoMSkmJmhpKHQsZSxpLG4sITAsaS5wYWludC5nZXQoXCJ0ZXh0LXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiKSxpLmxheW91dC5nZXQoXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiKSxpLmxheW91dC5nZXQoXCJ0ZXh0LXBpdGNoLWFsaWdubWVudFwiKSxpLmxheW91dC5nZXQoXCJ0ZXh0LWtlZXAtdXByaWdodFwiKSksZS5tYXAuc2hvd0NvbGxpc2lvbkJveGVzJiZmdW5jdGlvbih0LGUsaSxuKXtsaSh0LGUsaSxuLCExKSxsaSh0LGUsaSxuLCEwKTt9KHQsZSxpLG4pO319LGNpcmNsZTpmdW5jdGlvbih0LGUsaSxuKXtpZihcInRyYW5zbHVjZW50XCI9PT10LnJlbmRlclBhc3Mpe3ZhciBvPWkucGFpbnQuZ2V0KFwiY2lyY2xlLW9wYWNpdHlcIikscj1pLnBhaW50LmdldChcImNpcmNsZS1zdHJva2Utd2lkdGhcIiksYT1pLnBhaW50LmdldChcImNpcmNsZS1zdHJva2Utb3BhY2l0eVwiKTtpZigwIT09by5jb25zdGFudE9yKDEpfHwwIT09ci5jb25zdGFudE9yKDEpJiYwIT09YS5jb25zdGFudE9yKDEpKXt2YXIgcz10LmNvbnRleHQsbD1zLmdsO3Muc2V0RGVwdGhNb2RlKHQuZGVwdGhNb2RlRm9yU3VibGF5ZXIoMCwkdC5SZWFkT25seSkpLHMuc2V0U3RlbmNpbE1vZGUoR3QuZGlzYWJsZWQpLHMuc2V0Q29sb3JNb2RlKHQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpKTtmb3IodmFyIGM9ITAsdT0wO3U8bi5sZW5ndGg7dSsrKXt2YXIgaD1uW3VdLHA9ZS5nZXRUaWxlKGgpLGQ9cC5nZXRCdWNrZXQoaSk7aWYoZCl7dmFyIGY9dC5jb250ZXh0LnByb2dyYW0uZ2V0KCksbT1kLnByb2dyYW1Db25maWd1cmF0aW9ucy5nZXQoaS5pZCksXz10LnVzZVByb2dyYW0oXCJjaXJjbGVcIixtKTtpZigoY3x8Xy5wcm9ncmFtIT09ZikmJihtLnNldFVuaWZvcm1zKHMsXyxpLnBhaW50LHt6b29tOnQudHJhbnNmb3JtLnpvb219KSxjPSExKSxsLnVuaWZvcm0xZihfLnVuaWZvcm1zLnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSx0LnRyYW5zZm9ybS5jYW1lcmFUb0NlbnRlckRpc3RhbmNlKSxsLnVuaWZvcm0xaShfLnVuaWZvcm1zLnVfc2NhbGVfd2l0aF9tYXAsXCJtYXBcIj09PWkucGFpbnQuZ2V0KFwiY2lyY2xlLXBpdGNoLXNjYWxlXCIpPzE6MCksXCJtYXBcIj09PWkucGFpbnQuZ2V0KFwiY2lyY2xlLXBpdGNoLWFsaWdubWVudFwiKSl7bC51bmlmb3JtMWkoXy51bmlmb3Jtcy51X3BpdGNoX3dpdGhfbWFwLDEpO3ZhciBnPXplKHAsMSx0LnRyYW5zZm9ybS56b29tKTtsLnVuaWZvcm0yZihfLnVuaWZvcm1zLnVfZXh0cnVkZV9zY2FsZSxnLGcpO31lbHNlIGwudW5pZm9ybTFpKF8udW5pZm9ybXMudV9waXRjaF93aXRoX21hcCwwKSxsLnVuaWZvcm0yZnYoXy51bmlmb3Jtcy51X2V4dHJ1ZGVfc2NhbGUsdC50cmFuc2Zvcm0ucGl4ZWxzVG9HTFVuaXRzKTtsLnVuaWZvcm1NYXRyaXg0ZnYoXy51bmlmb3Jtcy51X21hdHJpeCwhMSx0LnRyYW5zbGF0ZVBvc01hdHJpeChoLnBvc01hdHJpeCxwLGkucGFpbnQuZ2V0KFwiY2lyY2xlLXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcImNpcmNsZS10cmFuc2xhdGUtYW5jaG9yXCIpKSksXy5kcmF3KHMsbC5UUklBTkdMRVMsaS5pZCxkLmxheW91dFZlcnRleEJ1ZmZlcixkLmluZGV4QnVmZmVyLGQuc2VnbWVudHMsbSk7fX19fX0saGVhdG1hcDpmdW5jdGlvbihlLGksbixvKXtpZigwIT09bi5wYWludC5nZXQoXCJoZWF0bWFwLW9wYWNpdHlcIikpaWYoXCJvZmZzY3JlZW5cIj09PWUucmVuZGVyUGFzcyl7dmFyIHI9ZS5jb250ZXh0LGE9ci5nbDtyLnNldERlcHRoTW9kZShlLmRlcHRoTW9kZUZvclN1YmxheWVyKDAsJHQuUmVhZE9ubHkpKSxyLnNldFN0ZW5jaWxNb2RlKEd0LmRpc2FibGVkKSxmdW5jdGlvbih0LGUsaSl7dmFyIG49dC5nbDt0LmFjdGl2ZVRleHR1cmUuc2V0KG4uVEVYVFVSRTEpLHQudmlld3BvcnQuc2V0KFswLDAsZS53aWR0aC80LGUuaGVpZ2h0LzRdKTt2YXIgbz1pLmhlYXRtYXBGYm87aWYobyluLmJpbmRUZXh0dXJlKG4uVEVYVFVSRV8yRCxvLmNvbG9yQXR0YWNobWVudC5nZXQoKSksdC5iaW5kRnJhbWVidWZmZXIuc2V0KG8uZnJhbWVidWZmZXIpO2Vsc2V7dmFyIHI9bi5jcmVhdGVUZXh0dXJlKCk7bi5iaW5kVGV4dHVyZShuLlRFWFRVUkVfMkQsciksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfV1JBUF9TLG4uQ0xBTVBfVE9fRURHRSksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfV1JBUF9ULG4uQ0xBTVBfVE9fRURHRSksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfTUlOX0ZJTFRFUixuLkxJTkVBUiksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfTUFHX0ZJTFRFUixuLkxJTkVBUiksbz1pLmhlYXRtYXBGYm89dC5jcmVhdGVGcmFtZWJ1ZmZlcihlLndpZHRoLzQsZS5oZWlnaHQvNCksZnVuY3Rpb24gdChlLGksbixvKXt2YXIgcj1lLmdsO3IudGV4SW1hZ2UyRChyLlRFWFRVUkVfMkQsMCxyLlJHQkEsaS53aWR0aC80LGkuaGVpZ2h0LzQsMCxyLlJHQkEsZS5leHRUZXh0dXJlSGFsZkZsb2F0P2UuZXh0VGV4dHVyZUhhbGZGbG9hdC5IQUxGX0ZMT0FUX09FUzpyLlVOU0lHTkVEX0JZVEUsbnVsbCksby5jb2xvckF0dGFjaG1lbnQuc2V0KG4pLGUuZXh0VGV4dHVyZUhhbGZGbG9hdCYmci5jaGVja0ZyYW1lYnVmZmVyU3RhdHVzKHIuRlJBTUVCVUZGRVIpIT09ci5GUkFNRUJVRkZFUl9DT01QTEVURSYmKGUuZXh0VGV4dHVyZUhhbGZGbG9hdD1udWxsLG8uY29sb3JBdHRhY2htZW50LnNldERpcnR5KCksdChlLGksbixvKSk7fSh0LGUscixvKTt9fShyLGUsbiksci5jbGVhcih7Y29sb3I6dC5kZWZhdWx0JDYudHJhbnNwYXJlbnR9KSxyLnNldENvbG9yTW9kZShuZXcgV3QoW2EuT05FLGEuT05FXSx0LmRlZmF1bHQkNi50cmFuc3BhcmVudCxbITAsITAsITAsITBdKSk7Zm9yKHZhciBzPSEwLGw9MDtsPG8ubGVuZ3RoO2wrKyl7dmFyIGM9b1tsXTtpZighaS5oYXNSZW5kZXJhYmxlUGFyZW50KGMpKXt2YXIgdT1pLmdldFRpbGUoYyksaD11LmdldEJ1Y2tldChuKTtpZihoKXt2YXIgcD1lLmNvbnRleHQucHJvZ3JhbS5nZXQoKSxkPWgucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmdldChuLmlkKSxmPWUudXNlUHJvZ3JhbShcImhlYXRtYXBcIixkKSxtPWUudHJhbnNmb3JtLnpvb207KHN8fGYucHJvZ3JhbSE9PXApJiYoZC5zZXRVbmlmb3JtcyhlLmNvbnRleHQsZixuLnBhaW50LHt6b29tOm19KSxzPSExKSxhLnVuaWZvcm0xZihmLnVuaWZvcm1zLnVfZXh0cnVkZV9zY2FsZSx6ZSh1LDEsbSkpLGEudW5pZm9ybTFmKGYudW5pZm9ybXMudV9pbnRlbnNpdHksbi5wYWludC5nZXQoXCJoZWF0bWFwLWludGVuc2l0eVwiKSksYS51bmlmb3JtTWF0cml4NGZ2KGYudW5pZm9ybXMudV9tYXRyaXgsITEsYy5wb3NNYXRyaXgpLGYuZHJhdyhyLGEuVFJJQU5HTEVTLG4uaWQsaC5sYXlvdXRWZXJ0ZXhCdWZmZXIsaC5pbmRleEJ1ZmZlcixoLnNlZ21lbnRzLGQpO319fXIudmlld3BvcnQuc2V0KFswLDAsZS53aWR0aCxlLmhlaWdodF0pO31lbHNlXCJ0cmFuc2x1Y2VudFwiPT09ZS5yZW5kZXJQYXNzJiYoZS5jb250ZXh0LnNldENvbG9yTW9kZShlLmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSksZnVuY3Rpb24oZSxpKXt2YXIgbj1lLmNvbnRleHQsbz1uLmdsLHI9aS5oZWF0bWFwRmJvO2lmKHIpe24uYWN0aXZlVGV4dHVyZS5zZXQoby5URVhUVVJFMCksby5iaW5kVGV4dHVyZShvLlRFWFRVUkVfMkQsci5jb2xvckF0dGFjaG1lbnQuZ2V0KCkpLG4uYWN0aXZlVGV4dHVyZS5zZXQoby5URVhUVVJFMSk7dmFyIGE9aS5jb2xvclJhbXBUZXh0dXJlO2F8fChhPWkuY29sb3JSYW1wVGV4dHVyZT1uZXcgTShuLGkuY29sb3JSYW1wLG8uUkdCQSkpLGEuYmluZChvLkxJTkVBUixvLkNMQU1QX1RPX0VER0UpLG4uc2V0RGVwdGhNb2RlKCR0LmRpc2FibGVkKTt2YXIgcz1lLnVzZVByb2dyYW0oXCJoZWF0bWFwVGV4dHVyZVwiKSxsPWkucGFpbnQuZ2V0KFwiaGVhdG1hcC1vcGFjaXR5XCIpO28udW5pZm9ybTFmKHMudW5pZm9ybXMudV9vcGFjaXR5LGwpLG8udW5pZm9ybTFpKHMudW5pZm9ybXMudV9pbWFnZSwwKSxvLnVuaWZvcm0xaShzLnVuaWZvcm1zLnVfY29sb3JfcmFtcCwxKTt2YXIgYz10Lm1hdDQuY3JlYXRlKCk7dC5tYXQ0Lm9ydGhvKGMsMCxlLndpZHRoLGUuaGVpZ2h0LDAsMCwxKSxvLnVuaWZvcm1NYXRyaXg0ZnYocy51bmlmb3Jtcy51X21hdHJpeCwhMSxjKSxvLnVuaWZvcm0yZihzLnVuaWZvcm1zLnVfd29ybGQsby5kcmF3aW5nQnVmZmVyV2lkdGgsby5kcmF3aW5nQnVmZmVySGVpZ2h0KSxlLnZpZXdwb3J0VkFPLmJpbmQoZS5jb250ZXh0LHMsZS52aWV3cG9ydEJ1ZmZlcixbXSksby5kcmF3QXJyYXlzKG8uVFJJQU5HTEVfU1RSSVAsMCw0KTt9fShlLG4pKTt9LGxpbmU6ZnVuY3Rpb24odCxlLGksbil7aWYoXCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzJiYwIT09aS5wYWludC5nZXQoXCJsaW5lLW9wYWNpdHlcIikuY29uc3RhbnRPcigxKSl7dmFyIG89dC5jb250ZXh0O28uc2V0RGVwdGhNb2RlKHQuZGVwdGhNb2RlRm9yU3VibGF5ZXIoMCwkdC5SZWFkT25seSkpLG8uc2V0Q29sb3JNb2RlKHQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpKTtmb3IodmFyIHIsYT1pLnBhaW50LmdldChcImxpbmUtZGFzaGFycmF5XCIpP1wibGluZVNERlwiOmkucGFpbnQuZ2V0KFwibGluZS1wYXR0ZXJuXCIpP1wibGluZVBhdHRlcm5cIjppLnBhaW50LmdldChcImxpbmUtZ3JhZGllbnRcIik/XCJsaW5lR3JhZGllbnRcIjpcImxpbmVcIixzPSEwLGw9MCxjPW47bDxjLmxlbmd0aDtsKz0xKXt2YXIgdT1jW2xdLGg9ZS5nZXRUaWxlKHUpLHA9aC5nZXRCdWNrZXQoaSk7aWYocCl7dmFyIGQ9cC5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGkuaWQpLGY9dC5jb250ZXh0LnByb2dyYW0uZ2V0KCksbT10LnVzZVByb2dyYW0oYSxkKSxfPXN8fG0ucHJvZ3JhbSE9PWYsZz1yIT09aC50aWxlSUQub3ZlcnNjYWxlZFo7XyYmZC5zZXRVbmlmb3Jtcyh0LmNvbnRleHQsbSxpLnBhaW50LHt6b29tOnQudHJhbnNmb3JtLnpvb219KSxtaShtLHQsaCxwLGksdSxkLF8sZykscj1oLnRpbGVJRC5vdmVyc2NhbGVkWixzPSExO319fX0sZmlsbDpmdW5jdGlvbihlLGksbixvKXt2YXIgcj1uLnBhaW50LmdldChcImZpbGwtY29sb3JcIiksYT1uLnBhaW50LmdldChcImZpbGwtb3BhY2l0eVwiKTtpZigwIT09YS5jb25zdGFudE9yKDEpKXt2YXIgcz1lLmNvbnRleHQ7cy5zZXRDb2xvck1vZGUoZS5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCkpO3ZhciBsPW4ucGFpbnQuZ2V0KFwiZmlsbC1wYXR0ZXJuXCIpfHwxIT09ci5jb25zdGFudE9yKHQuZGVmYXVsdCQ2LnRyYW5zcGFyZW50KS5hfHwxIT09YS5jb25zdGFudE9yKDApP1widHJhbnNsdWNlbnRcIjpcIm9wYXF1ZVwiO2UucmVuZGVyUGFzcz09PWwmJihzLnNldERlcHRoTW9kZShlLmRlcHRoTW9kZUZvclN1YmxheWVyKDEsXCJvcGFxdWVcIj09PWUucmVuZGVyUGFzcz8kdC5SZWFkV3JpdGU6JHQuUmVhZE9ubHkpKSx5aShlLGksbixvLHhpKSksXCJ0cmFuc2x1Y2VudFwiPT09ZS5yZW5kZXJQYXNzJiZuLnBhaW50LmdldChcImZpbGwtYW50aWFsaWFzXCIpJiYocy5saW5lV2lkdGguc2V0KDIpLHMuc2V0RGVwdGhNb2RlKGUuZGVwdGhNb2RlRm9yU3VibGF5ZXIobi5nZXRQYWludFByb3BlcnR5KFwiZmlsbC1vdXRsaW5lLWNvbG9yXCIpPzI6MCwkdC5SZWFkT25seSkpLHlpKGUsaSxuLG8sYmkpKTt9fSxcImZpbGwtZXh0cnVzaW9uXCI6ZnVuY3Rpb24oZSxpLG4sbyl7aWYoMCE9PW4ucGFpbnQuZ2V0KFwiZmlsbC1leHRydXNpb24tb3BhY2l0eVwiKSlpZihcIm9mZnNjcmVlblwiPT09ZS5yZW5kZXJQYXNzKXshZnVuY3Rpb24oZSxpKXt2YXIgbj1lLmNvbnRleHQsbz1uLmdsLHI9aS52aWV3cG9ydEZyYW1lO2lmKGUuZGVwdGhSYm9OZWVkc0NsZWFyJiZlLnNldHVwT2Zmc2NyZWVuRGVwdGhSZW5kZXJidWZmZXIoKSwhcil7dmFyIGE9bmV3IE0obix7d2lkdGg6ZS53aWR0aCxoZWlnaHQ6ZS5oZWlnaHQsZGF0YTpudWxsfSxvLlJHQkEpO2EuYmluZChvLkxJTkVBUixvLkNMQU1QX1RPX0VER0UpLChyPWkudmlld3BvcnRGcmFtZT1uLmNyZWF0ZUZyYW1lYnVmZmVyKGUud2lkdGgsZS5oZWlnaHQpKS5jb2xvckF0dGFjaG1lbnQuc2V0KGEudGV4dHVyZSk7fW4uYmluZEZyYW1lYnVmZmVyLnNldChyLmZyYW1lYnVmZmVyKSxyLmRlcHRoQXR0YWNobWVudC5zZXQoZS5kZXB0aFJibyksZS5kZXB0aFJib05lZWRzQ2xlYXImJihuLmNsZWFyKHtkZXB0aDoxfSksZS5kZXB0aFJib05lZWRzQ2xlYXI9ITEpLG4uY2xlYXIoe2NvbG9yOnQuZGVmYXVsdCQ2LnRyYW5zcGFyZW50fSksbi5zZXRTdGVuY2lsTW9kZShHdC5kaXNhYmxlZCksbi5zZXREZXB0aE1vZGUobmV3ICR0KG8uTEVRVUFMLCR0LlJlYWRXcml0ZSxbMCwxXSkpLG4uc2V0Q29sb3JNb2RlKGUuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpKTt9KGUsbik7Zm9yKHZhciByPSEwLGE9MCxzPW87YTxzLmxlbmd0aDthKz0xKXt2YXIgbD1zW2FdLGM9aS5nZXRUaWxlKGwpLHU9Yy5nZXRCdWNrZXQobik7dSYmKENpKGUsMCxuLGMsbCx1LHIpLHI9ITEpO319ZWxzZVwidHJhbnNsdWNlbnRcIj09PWUucmVuZGVyUGFzcyYmZnVuY3Rpb24odCxlKXt2YXIgaT1lLnZpZXdwb3J0RnJhbWU7aWYoaSl7dmFyIG49dC5jb250ZXh0LG89bi5nbCxyPXQudXNlUHJvZ3JhbShcImV4dHJ1c2lvblRleHR1cmVcIik7bi5zZXRTdGVuY2lsTW9kZShHdC5kaXNhYmxlZCksbi5zZXREZXB0aE1vZGUoJHQuZGlzYWJsZWQpLG4uc2V0Q29sb3JNb2RlKHQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpKSxuLmFjdGl2ZVRleHR1cmUuc2V0KG8uVEVYVFVSRTApLG8uYmluZFRleHR1cmUoby5URVhUVVJFXzJELGkuY29sb3JBdHRhY2htZW50LmdldCgpKSxvLnVuaWZvcm0xZihyLnVuaWZvcm1zLnVfb3BhY2l0eSxlLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLW9wYWNpdHlcIikpLG8udW5pZm9ybTFpKHIudW5pZm9ybXMudV9pbWFnZSwwKTt2YXIgYT1UaS5jcmVhdGUoKTtUaS5vcnRobyhhLDAsdC53aWR0aCx0LmhlaWdodCwwLDAsMSksby51bmlmb3JtTWF0cml4NGZ2KHIudW5pZm9ybXMudV9tYXRyaXgsITEsYSksby51bmlmb3JtMmYoci51bmlmb3Jtcy51X3dvcmxkLG8uZHJhd2luZ0J1ZmZlcldpZHRoLG8uZHJhd2luZ0J1ZmZlckhlaWdodCksdC52aWV3cG9ydFZBTy5iaW5kKG4scix0LnZpZXdwb3J0QnVmZmVyLFtdKSxvLmRyYXdBcnJheXMoby5UUklBTkdMRV9TVFJJUCwwLDQpO319KGUsbik7fSxoaWxsc2hhZGU6ZnVuY3Rpb24odCxlLGksbil7aWYoXCJvZmZzY3JlZW5cIj09PXQucmVuZGVyUGFzc3x8XCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzKXt2YXIgbz10LmNvbnRleHQscj1lLmdldFNvdXJjZSgpLm1heHpvb207by5zZXREZXB0aE1vZGUodC5kZXB0aE1vZGVGb3JTdWJsYXllcigwLCR0LlJlYWRPbmx5KSksby5zZXRTdGVuY2lsTW9kZShHdC5kaXNhYmxlZCksby5zZXRDb2xvck1vZGUodC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCkpO2Zvcih2YXIgYT0wLHM9bjthPHMubGVuZ3RoO2ErPTEpe3ZhciBsPXNbYV0sYz1lLmdldFRpbGUobCk7Yy5uZWVkc0hpbGxzaGFkZVByZXBhcmUmJlwib2Zmc2NyZWVuXCI9PT10LnJlbmRlclBhc3M/emkodCxjLHIpOlwidHJhbnNsdWNlbnRcIj09PXQucmVuZGVyUGFzcyYmU2kodCxjLGkpO31vLnZpZXdwb3J0LnNldChbMCwwLHQud2lkdGgsdC5oZWlnaHRdKTt9fSxyYXN0ZXI6ZnVuY3Rpb24odCxlLGksbil7aWYoXCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzJiYwIT09aS5wYWludC5nZXQoXCJyYXN0ZXItb3BhY2l0eVwiKSl7dmFyIG8scixhPXQuY29udGV4dCxzPWEuZ2wsbD1lLmdldFNvdXJjZSgpLGM9dC51c2VQcm9ncmFtKFwicmFzdGVyXCIpO2Euc2V0U3RlbmNpbE1vZGUoR3QuZGlzYWJsZWQpLGEuc2V0Q29sb3JNb2RlKHQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpKSxzLnVuaWZvcm0xZihjLnVuaWZvcm1zLnVfYnJpZ2h0bmVzc19sb3csaS5wYWludC5nZXQoXCJyYXN0ZXItYnJpZ2h0bmVzcy1taW5cIikpLHMudW5pZm9ybTFmKGMudW5pZm9ybXMudV9icmlnaHRuZXNzX2hpZ2gsaS5wYWludC5nZXQoXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIikpLHMudW5pZm9ybTFmKGMudW5pZm9ybXMudV9zYXR1cmF0aW9uX2ZhY3Rvciwobz1pLnBhaW50LmdldChcInJhc3Rlci1zYXR1cmF0aW9uXCIpKT4wPzEtMS8oMS4wMDEtbyk6LW8pLHMudW5pZm9ybTFmKGMudW5pZm9ybXMudV9jb250cmFzdF9mYWN0b3IsKHI9aS5wYWludC5nZXQoXCJyYXN0ZXItY29udHJhc3RcIikpPjA/MS8oMS1yKToxK3IpLHMudW5pZm9ybTNmdihjLnVuaWZvcm1zLnVfc3Bpbl93ZWlnaHRzLGZ1bmN0aW9uKHQpe3QqPU1hdGguUEkvMTgwO3ZhciBlPU1hdGguc2luKHQpLGk9TWF0aC5jb3ModCk7cmV0dXJuWygyKmkrMSkvMywoLU1hdGguc3FydCgzKSplLWkrMSkvMywoTWF0aC5zcXJ0KDMpKmUtaSsxKS8zXX0oaS5wYWludC5nZXQoXCJyYXN0ZXItaHVlLXJvdGF0ZVwiKSkpLHMudW5pZm9ybTFmKGMudW5pZm9ybXMudV9idWZmZXJfc2NhbGUsMSkscy51bmlmb3JtMWkoYy51bmlmb3Jtcy51X2ltYWdlMCwwKSxzLnVuaWZvcm0xaShjLnVuaWZvcm1zLnVfaW1hZ2UxLDEpO2Zvcih2YXIgdT1uLmxlbmd0aCYmblswXS5vdmVyc2NhbGVkWixoPTAscD1uO2g8cC5sZW5ndGg7aCs9MSl7dmFyIGQ9cFtoXTthLnNldERlcHRoTW9kZSh0LmRlcHRoTW9kZUZvclN1YmxheWVyKGQub3ZlcnNjYWxlZFotdSwxPT09aS5wYWludC5nZXQoXCJyYXN0ZXItb3BhY2l0eVwiKT8kdC5SZWFkV3JpdGU6JHQuUmVhZE9ubHkscy5MRVNTKSk7dmFyIGY9ZS5nZXRUaWxlKGQpLG09dC50cmFuc2Zvcm0uY2FsY3VsYXRlUG9zTWF0cml4KGQudG9VbndyYXBwZWQoKSwhMCk7Zi5yZWdpc3RlckZhZGVEdXJhdGlvbihpLnBhaW50LmdldChcInJhc3Rlci1mYWRlLWR1cmF0aW9uXCIpKSxzLnVuaWZvcm1NYXRyaXg0ZnYoYy51bmlmb3Jtcy51X21hdHJpeCwhMSxtKTt2YXIgXz1lLmZpbmRMb2FkZWRQYXJlbnQoZCwwLHt9KSxnPUFpKGYsXyxlLGksdC50cmFuc2Zvcm0pLHY9dm9pZCAwLHk9dm9pZCAwO2lmKGEuYWN0aXZlVGV4dHVyZS5zZXQocy5URVhUVVJFMCksZi50ZXh0dXJlLmJpbmQocy5MSU5FQVIscy5DTEFNUF9UT19FREdFLHMuTElORUFSX01JUE1BUF9ORUFSRVNUKSxhLmFjdGl2ZVRleHR1cmUuc2V0KHMuVEVYVFVSRTEpLF8/KF8udGV4dHVyZS5iaW5kKHMuTElORUFSLHMuQ0xBTVBfVE9fRURHRSxzLkxJTkVBUl9NSVBNQVBfTkVBUkVTVCksdj1NYXRoLnBvdygyLF8udGlsZUlELm92ZXJzY2FsZWRaLWYudGlsZUlELm92ZXJzY2FsZWRaKSx5PVtmLnRpbGVJRC5jYW5vbmljYWwueCp2JTEsZi50aWxlSUQuY2Fub25pY2FsLnkqdiUxXSk6Zi50ZXh0dXJlLmJpbmQocy5MSU5FQVIscy5DTEFNUF9UT19FREdFLHMuTElORUFSX01JUE1BUF9ORUFSRVNUKSxzLnVuaWZvcm0yZnYoYy51bmlmb3Jtcy51X3RsX3BhcmVudCx5fHxbMCwwXSkscy51bmlmb3JtMWYoYy51bmlmb3Jtcy51X3NjYWxlX3BhcmVudCx2fHwxKSxzLnVuaWZvcm0xZihjLnVuaWZvcm1zLnVfZmFkZV90LGcubWl4KSxzLnVuaWZvcm0xZihjLnVuaWZvcm1zLnVfb3BhY2l0eSxnLm9wYWNpdHkqaS5wYWludC5nZXQoXCJyYXN0ZXItb3BhY2l0eVwiKSksbCBpbnN0YW5jZW9mIGV0KXt2YXIgeD1sLmJvdW5kc0J1ZmZlcjtsLmJvdW5kc1ZBTy5iaW5kKGEsYyx4LFtdKSxzLmRyYXdBcnJheXMocy5UUklBTkdMRV9TVFJJUCwwLHgubGVuZ3RoKTt9ZWxzZSBpZihmLm1hc2tlZEJvdW5kc0J1ZmZlciYmZi5tYXNrZWRJbmRleEJ1ZmZlciYmZi5zZWdtZW50cyljLmRyYXcoYSxzLlRSSUFOR0xFUyxpLmlkLGYubWFza2VkQm91bmRzQnVmZmVyLGYubWFza2VkSW5kZXhCdWZmZXIsZi5zZWdtZW50cyk7ZWxzZXt2YXIgYj10LnJhc3RlckJvdW5kc0J1ZmZlcjt0LnJhc3RlckJvdW5kc1ZBTy5iaW5kKGEsYyxiLFtdKSxzLmRyYXdBcnJheXMocy5UUklBTkdMRV9TVFJJUCwwLGIubGVuZ3RoKTt9fX19LGJhY2tncm91bmQ6ZnVuY3Rpb24odCxlLGkpe3ZhciBuPWkucGFpbnQuZ2V0KFwiYmFja2dyb3VuZC1jb2xvclwiKSxvPWkucGFpbnQuZ2V0KFwiYmFja2dyb3VuZC1vcGFjaXR5XCIpO2lmKDAhPT1vKXt2YXIgcj10LmNvbnRleHQsYT1yLmdsLHM9dC50cmFuc2Zvcm0sbD1zLnRpbGVTaXplLGM9aS5wYWludC5nZXQoXCJiYWNrZ3JvdW5kLXBhdHRlcm5cIiksdT1jfHwxIT09bi5hfHwxIT09bz9cInRyYW5zbHVjZW50XCI6XCJvcGFxdWVcIjtpZih0LnJlbmRlclBhc3M9PT11KXt2YXIgaDtpZihyLnNldFN0ZW5jaWxNb2RlKEd0LmRpc2FibGVkKSxyLnNldERlcHRoTW9kZSh0LmRlcHRoTW9kZUZvclN1YmxheWVyKDAsXCJvcGFxdWVcIj09PXU/JHQuUmVhZFdyaXRlOiR0LlJlYWRPbmx5KSksci5zZXRDb2xvck1vZGUodC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCkpLGMpe2lmKF9pKGMsdCkpcmV0dXJuO2g9dC51c2VQcm9ncmFtKFwiYmFja2dyb3VuZFBhdHRlcm5cIiksZ2koYyx0LGgpLHQudGlsZUV4dGVudFBhdHRlcm5WQU8uYmluZChyLGgsdC50aWxlRXh0ZW50QnVmZmVyLFtdKTt9ZWxzZSBoPXQudXNlUHJvZ3JhbShcImJhY2tncm91bmRcIiksYS51bmlmb3JtNGZ2KGgudW5pZm9ybXMudV9jb2xvcixbbi5yLG4uZyxuLmIsbi5hXSksdC50aWxlRXh0ZW50VkFPLmJpbmQocixoLHQudGlsZUV4dGVudEJ1ZmZlcixbXSk7YS51bmlmb3JtMWYoaC51bmlmb3Jtcy51X29wYWNpdHksbyk7Zm9yKHZhciBwPTAsZD1zLmNvdmVyaW5nVGlsZXMoe3RpbGVTaXplOmx9KTtwPGQubGVuZ3RoO3ArPTEpe3ZhciBmPWRbcF07YyYmdmkoe3RpbGVJRDpmLHRpbGVTaXplOmx9LHQsaCksYS51bmlmb3JtTWF0cml4NGZ2KGgudW5pZm9ybXMudV9tYXRyaXgsITEsdC50cmFuc2Zvcm0uY2FsY3VsYXRlUG9zTWF0cml4KGYudG9VbndyYXBwZWQoKSkpLGEuZHJhd0FycmF5cyhhLlRSSUFOR0xFX1NUUklQLDAsdC50aWxlRXh0ZW50QnVmZmVyLmxlbmd0aCk7fX19fSxkZWJ1ZzpmdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBuPTA7bjxpLmxlbmd0aDtuKyspUmkodCxlLGlbbl0pO319LExpPWZ1bmN0aW9uKGUsaSl7dGhpcy5jb250ZXh0PW5ldyBxdChlKSx0aGlzLnRyYW5zZm9ybT1pLHRoaXMuX3RpbGVUZXh0dXJlcz17fSx0aGlzLnNldHVwKCksdGhpcy5udW1TdWJsYXllcnM9WHQubWF4VW5kZXJ6b29taW5nK1h0Lm1heE92ZXJ6b29taW5nKzEsdGhpcy5kZXB0aEVwc2lsb249MS9NYXRoLnBvdygyLDE2KSx0aGlzLmRlcHRoUmJvTmVlZHNDbGVhcj0hMCx0aGlzLmVtcHR5UHJvZ3JhbUNvbmZpZ3VyYXRpb249bmV3IHQuZGVmYXVsdCQyNCx0aGlzLmNyb3NzVGlsZVN5bWJvbEluZGV4PW5ldyBIZTt9O2Z1bmN0aW9uIFBpKHQsZSl7aWYodC5yb3c+ZS5yb3cpe3ZhciBpPXQ7dD1lLGU9aTt9cmV0dXJue3gwOnQuY29sdW1uLHkwOnQucm93LHgxOmUuY29sdW1uLHkxOmUucm93LGR4OmUuY29sdW1uLXQuY29sdW1uLGR5OmUucm93LXQucm93fX1mdW5jdGlvbiBraSh0LGUsaSxuLG8pe3ZhciByPU1hdGgubWF4KGksTWF0aC5mbG9vcihlLnkwKSksYT1NYXRoLm1pbihuLE1hdGguY2VpbChlLnkxKSk7aWYodC54MD09PWUueDAmJnQueTA9PT1lLnkwP3QueDArZS5keS90LmR5KnQuZHg8ZS54MTp0LngxLWUuZHkvdC5keSp0LmR4PGUueDApe3ZhciBzPXQ7dD1lLGU9czt9Zm9yKHZhciBsPXQuZHgvdC5keSxjPWUuZHgvZS5keSx1PXQuZHg+MCxoPWUuZHg8MCxwPXI7cDxhO3ArKyl7dmFyIGQ9bCpNYXRoLm1heCgwLE1hdGgubWluKHQuZHkscCt1LXQueTApKSt0LngwLGY9YypNYXRoLm1heCgwLE1hdGgubWluKGUuZHkscCtoLWUueTApKStlLngwO28oTWF0aC5mbG9vcihmKSxNYXRoLmNlaWwoZCkscCk7fX1mdW5jdGlvbiBCaSh0LGUsaSxuLG8scil7dmFyIGEscz1QaSh0LGUpLGw9UGkoZSxpKSxjPVBpKGksdCk7cy5keT5sLmR5JiYoYT1zLHM9bCxsPWEpLHMuZHk+Yy5keSYmKGE9cyxzPWMsYz1hKSxsLmR5PmMuZHkmJihhPWwsbD1jLGM9YSkscy5keSYma2koYyxzLG4sbyxyKSxsLmR5JiZraShjLGwsbixvLHIpO31MaS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKHQsZSl7dmFyIGk9dGhpcy5jb250ZXh0LmdsO2lmKHRoaXMud2lkdGg9dCpyLmRldmljZVBpeGVsUmF0aW8sdGhpcy5oZWlnaHQ9ZSpyLmRldmljZVBpeGVsUmF0aW8sdGhpcy5jb250ZXh0LnZpZXdwb3J0LnNldChbMCwwLHRoaXMud2lkdGgsdGhpcy5oZWlnaHRdKSx0aGlzLnN0eWxlKWZvcih2YXIgbj0wLG89dGhpcy5zdHlsZS5fb3JkZXI7bjxvLmxlbmd0aDtuKz0xKXt2YXIgYT1vW25dO3RoaXMuc3R5bGUuX2xheWVyc1thXS5yZXNpemUoKTt9dGhpcy5kZXB0aFJibyYmKGkuZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMuZGVwdGhSYm8pLHRoaXMuZGVwdGhSYm89bnVsbCk7fSxMaS5wcm90b3R5cGUuc2V0dXA9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLmNvbnRleHQsaT1uZXcgdC5Qb3NBcnJheTtpLmVtcGxhY2VCYWNrKDAsMCksaS5lbXBsYWNlQmFjayh0LmRlZmF1bHQkOCwwKSxpLmVtcGxhY2VCYWNrKDAsdC5kZWZhdWx0JDgpLGkuZW1wbGFjZUJhY2sodC5kZWZhdWx0JDgsdC5kZWZhdWx0JDgpLHRoaXMudGlsZUV4dGVudEJ1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihpLHRpLm1lbWJlcnMpLHRoaXMudGlsZUV4dGVudFZBTz1uZXcgdHQsdGhpcy50aWxlRXh0ZW50UGF0dGVyblZBTz1uZXcgdHQ7dmFyIG49bmV3IHQuUG9zQXJyYXk7bi5lbXBsYWNlQmFjaygwLDApLG4uZW1wbGFjZUJhY2sodC5kZWZhdWx0JDgsMCksbi5lbXBsYWNlQmFjayh0LmRlZmF1bHQkOCx0LmRlZmF1bHQkOCksbi5lbXBsYWNlQmFjaygwLHQuZGVmYXVsdCQ4KSxuLmVtcGxhY2VCYWNrKDAsMCksdGhpcy5kZWJ1Z0J1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihuLHRpLm1lbWJlcnMpLHRoaXMuZGVidWdWQU89bmV3IHR0O3ZhciBvPW5ldyB0LlJhc3RlckJvdW5kc0FycmF5O28uZW1wbGFjZUJhY2soMCwwLDAsMCksby5lbXBsYWNlQmFjayh0LmRlZmF1bHQkOCwwLHQuZGVmYXVsdCQ4LDApLG8uZW1wbGFjZUJhY2soMCx0LmRlZmF1bHQkOCwwLHQuZGVmYXVsdCQ4KSxvLmVtcGxhY2VCYWNrKHQuZGVmYXVsdCQ4LHQuZGVmYXVsdCQ4LHQuZGVmYXVsdCQ4LHQuZGVmYXVsdCQ4KSx0aGlzLnJhc3RlckJvdW5kc0J1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihvLFEubWVtYmVycyksdGhpcy5yYXN0ZXJCb3VuZHNWQU89bmV3IHR0O3ZhciByPW5ldyB0LlBvc0FycmF5O3IuZW1wbGFjZUJhY2soMCwwKSxyLmVtcGxhY2VCYWNrKDEsMCksci5lbXBsYWNlQmFjaygwLDEpLHIuZW1wbGFjZUJhY2soMSwxKSx0aGlzLnZpZXdwb3J0QnVmZmVyPWUuY3JlYXRlVmVydGV4QnVmZmVyKHIsdGkubWVtYmVycyksdGhpcy52aWV3cG9ydFZBTz1uZXcgdHQ7fSxMaS5wcm90b3R5cGUuY2xlYXJTdGVuY2lsPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5jb250ZXh0LGk9ZS5nbDtlLnNldENvbG9yTW9kZShXdC5kaXNhYmxlZCksZS5zZXREZXB0aE1vZGUoJHQuZGlzYWJsZWQpLGUuc2V0U3RlbmNpbE1vZGUobmV3IEd0KHtmdW5jOmkuQUxXQVlTLG1hc2s6MH0sMCwyNTUsaS5aRVJPLGkuWkVSTyxpLlpFUk8pKTt2YXIgbj10Lm1hdDQuY3JlYXRlKCk7dC5tYXQ0Lm9ydGhvKG4sMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0LDAsMCwxKSx0Lm1hdDQuc2NhbGUobixuLFtpLmRyYXdpbmdCdWZmZXJXaWR0aCxpLmRyYXdpbmdCdWZmZXJIZWlnaHQsMF0pO3ZhciBvPXRoaXMudXNlUHJvZ3JhbShcImNsaXBwaW5nTWFza1wiKTtpLnVuaWZvcm1NYXRyaXg0ZnYoby51bmlmb3Jtcy51X21hdHJpeCwhMSxuKSx0aGlzLnZpZXdwb3J0VkFPLmJpbmQoZSxvLHRoaXMudmlld3BvcnRCdWZmZXIsW10pLGkuZHJhd0FycmF5cyhpLlRSSUFOR0xFX1NUUklQLDAsNCk7fSxMaS5wcm90b3R5cGUuX3JlbmRlclRpbGVDbGlwcGluZ01hc2tzPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY29udGV4dCxpPWUuZ2w7ZS5zZXRDb2xvck1vZGUoV3QuZGlzYWJsZWQpLGUuc2V0RGVwdGhNb2RlKCR0LmRpc2FibGVkKTt2YXIgbj0xO3RoaXMuX3RpbGVDbGlwcGluZ01hc2tJRHM9e307Zm9yKHZhciBvPTAscj10O288ci5sZW5ndGg7bys9MSl7dmFyIGE9cltvXSxzPXRoaXMuX3RpbGVDbGlwcGluZ01hc2tJRHNbYS5rZXldPW4rKztlLnNldFN0ZW5jaWxNb2RlKG5ldyBHdCh7ZnVuYzppLkFMV0FZUyxtYXNrOjB9LHMsMjU1LGkuS0VFUCxpLktFRVAsaS5SRVBMQUNFKSk7dmFyIGw9dGhpcy51c2VQcm9ncmFtKFwiY2xpcHBpbmdNYXNrXCIpO2kudW5pZm9ybU1hdHJpeDRmdihsLnVuaWZvcm1zLnVfbWF0cml4LCExLGEucG9zTWF0cml4KSx0aGlzLnRpbGVFeHRlbnRWQU8uYmluZCh0aGlzLmNvbnRleHQsbCx0aGlzLnRpbGVFeHRlbnRCdWZmZXIsW10pLGkuZHJhd0FycmF5cyhpLlRSSUFOR0xFX1NUUklQLDAsdGhpcy50aWxlRXh0ZW50QnVmZmVyLmxlbmd0aCk7fX0sTGkucHJvdG90eXBlLnN0ZW5jaWxNb2RlRm9yQ2xpcHBpbmc9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO3JldHVybiBuZXcgR3Qoe2Z1bmM6ZS5FUVVBTCxtYXNrOjI1NX0sdGhpcy5fdGlsZUNsaXBwaW5nTWFza0lEc1t0LmtleV0sMCxlLktFRVAsZS5LRUVQLGUuUkVQTEFDRSl9LExpLnByb3RvdHlwZS5jb2xvck1vZGVGb3JSZW5kZXJQYXNzPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO2lmKHRoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3Rvcil7cmV0dXJuIG5ldyBXdChbZS5DT05TVEFOVF9DT0xPUixlLk9ORV0sbmV3IHQuZGVmYXVsdCQ2KDEvOCwxLzgsMS84LDApLFshMCwhMCwhMCwhMF0pfXJldHVyblwib3BhcXVlXCI9PT10aGlzLnJlbmRlclBhc3M/V3QudW5ibGVuZGVkOld0LmFscGhhQmxlbmRlZH0sTGkucHJvdG90eXBlLmRlcHRoTW9kZUZvclN1YmxheWVyPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbj0xLSgoMSt0aGlzLmN1cnJlbnRMYXllcikqdGhpcy5udW1TdWJsYXllcnMrdCkqdGhpcy5kZXB0aEVwc2lsb24sbz1uLTErdGhpcy5kZXB0aFJhbmdlO3JldHVybiBuZXcgJHQoaXx8dGhpcy5jb250ZXh0LmdsLkxFUVVBTCxlLFtvLG5dKX0sTGkucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbihlLGkpe3ZhciBuPXRoaXM7Zm9yKHZhciBvIGluIHRoaXMuc3R5bGU9ZSx0aGlzLm9wdGlvbnM9aSx0aGlzLmxpbmVBdGxhcz1lLmxpbmVBdGxhcyx0aGlzLmltYWdlTWFuYWdlcj1lLmltYWdlTWFuYWdlcix0aGlzLmdseXBoTWFuYWdlcj1lLmdseXBoTWFuYWdlcix0aGlzLnN5bWJvbEZhZGVDaGFuZ2U9ZS5wbGFjZW1lbnQuc3ltYm9sRmFkZUNoYW5nZShyLm5vdygpKSxlLnNvdXJjZUNhY2hlcyl7dmFyIGE9bi5zdHlsZS5zb3VyY2VDYWNoZXNbb107YS51c2VkJiZhLnByZXBhcmUobi5jb250ZXh0KTt9dmFyIHM9dGhpcy5zdHlsZS5fb3JkZXIsbD10LmZpbHRlck9iamVjdCh0aGlzLnN0eWxlLnNvdXJjZUNhY2hlcyxmdW5jdGlvbih0KXtyZXR1cm5cInJhc3RlclwiPT09dC5nZXRTb3VyY2UoKS50eXBlfHxcInJhc3Rlci1kZW1cIj09PXQuZ2V0U291cmNlKCkudHlwZX0pLGM9ZnVuY3Rpb24oZSl7dmFyIGk9bFtlXTshZnVuY3Rpb24oZSxpKXtmb3IodmFyIG49ZS5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQudGlsZUlELmlzTGVzc1RoYW4oZS50aWxlSUQpPy0xOmUudGlsZUlELmlzTGVzc1RoYW4odC50aWxlSUQpPzE6MH0pLG89MDtvPG4ubGVuZ3RoO28rKyl7dmFyIHI9e30sYT1uW29dLHM9bi5zbGljZShvKzEpO3NpKGEudGlsZUlELndyYXBwZWQoKSxhLnRpbGVJRCxzLG5ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoMCxhLnRpbGVJRC53cmFwKzEsMCwwLDApLHIpLGEuc2V0TWFzayhyLGkpO319KGkuZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBpLmdldFRpbGUodCl9KSxuLmNvbnRleHQpO307Zm9yKHZhciB1IGluIGwpYyh1KTt0aGlzLnJlbmRlclBhc3M9XCJvZmZzY3JlZW5cIjt2YXIgaCxwPVtdO3RoaXMuZGVwdGhSYm9OZWVkc0NsZWFyPSEwO2Zvcih2YXIgZD0wO2Q8cy5sZW5ndGg7ZCsrKXt2YXIgZj1uLnN0eWxlLl9sYXllcnNbc1tkXV07Zi5oYXNPZmZzY3JlZW5QYXNzKCkmJiFmLmlzSGlkZGVuKG4udHJhbnNmb3JtLnpvb20pJiYoZi5zb3VyY2UhPT0oaCYmaC5pZCkmJihwPVtdLChoPW4uc3R5bGUuc291cmNlQ2FjaGVzW2Yuc291cmNlXSkmJihwPWguZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCkpLnJldmVyc2UoKSkscC5sZW5ndGgmJm4ucmVuZGVyTGF5ZXIobixoLGYscCkpO310aGlzLmNvbnRleHQuYmluZEZyYW1lYnVmZmVyLnNldChudWxsKSx0aGlzLmNvbnRleHQuY2xlYXIoe2NvbG9yOmkuc2hvd092ZXJkcmF3SW5zcGVjdG9yP3QuZGVmYXVsdCQ2LmJsYWNrOnQuZGVmYXVsdCQ2LnRyYW5zcGFyZW50LGRlcHRoOjF9KSx0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3I9aS5zaG93T3ZlcmRyYXdJbnNwZWN0b3IsdGhpcy5kZXB0aFJhbmdlPShlLl9vcmRlci5sZW5ndGgrMikqdGhpcy5udW1TdWJsYXllcnMqdGhpcy5kZXB0aEVwc2lsb24sdGhpcy5yZW5kZXJQYXNzPVwib3BhcXVlXCI7dmFyIG0sXz1bXTtmb3IodGhpcy5jdXJyZW50TGF5ZXI9cy5sZW5ndGgtMSx0aGlzLmN1cnJlbnRMYXllcjt0aGlzLmN1cnJlbnRMYXllcj49MDt0aGlzLmN1cnJlbnRMYXllci0tKXt2YXIgZz1uLnN0eWxlLl9sYXllcnNbc1tuLmN1cnJlbnRMYXllcl1dO2cuc291cmNlIT09KG0mJm0uaWQpJiYoXz1bXSwobT1uLnN0eWxlLnNvdXJjZUNhY2hlc1tnLnNvdXJjZV0pJiYobi5jbGVhclN0ZW5jaWwoKSxfPW0uZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCksbS5nZXRTb3VyY2UoKS5pc1RpbGVDbGlwcGVkJiZuLl9yZW5kZXJUaWxlQ2xpcHBpbmdNYXNrcyhfKSkpLG4ucmVuZGVyTGF5ZXIobixtLGcsXyk7fXRoaXMucmVuZGVyUGFzcz1cInRyYW5zbHVjZW50XCI7dmFyIHYseT1bXTtmb3IodGhpcy5jdXJyZW50TGF5ZXI9MCx0aGlzLmN1cnJlbnRMYXllcjt0aGlzLmN1cnJlbnRMYXllcjxzLmxlbmd0aDt0aGlzLmN1cnJlbnRMYXllcisrKXt2YXIgeD1uLnN0eWxlLl9sYXllcnNbc1tuLmN1cnJlbnRMYXllcl1dO3guc291cmNlIT09KHYmJnYuaWQpJiYoeT1bXSwodj1uLnN0eWxlLnNvdXJjZUNhY2hlc1t4LnNvdXJjZV0pJiYobi5jbGVhclN0ZW5jaWwoKSx5PXYuZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCksdi5nZXRTb3VyY2UoKS5pc1RpbGVDbGlwcGVkJiZuLl9yZW5kZXJUaWxlQ2xpcHBpbmdNYXNrcyh5KSkseS5yZXZlcnNlKCkpLG4ucmVuZGVyTGF5ZXIobix2LHgseSk7fWlmKHRoaXMub3B0aW9ucy5zaG93VGlsZUJvdW5kYXJpZXMpe3ZhciBiPXRoaXMuc3R5bGUuc291cmNlQ2FjaGVzW09iamVjdC5rZXlzKHRoaXMuc3R5bGUuc291cmNlQ2FjaGVzKVswXV07YiYmTWkuZGVidWcodGhpcyxiLGIuZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCkpO319LExpLnByb3RvdHlwZS5zZXR1cE9mZnNjcmVlbkRlcHRoUmVuZGVyYnVmZmVyPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5jb250ZXh0O3RoaXMuZGVwdGhSYm98fCh0aGlzLmRlcHRoUmJvPXQuY3JlYXRlUmVuZGVyYnVmZmVyKHQuZ2wuREVQVEhfQ09NUE9ORU5UMTYsdGhpcy53aWR0aCx0aGlzLmhlaWdodCkpO30sTGkucHJvdG90eXBlLnJlbmRlckxheWVyPWZ1bmN0aW9uKHQsZSxpLG4pe2kuaXNIaWRkZW4odGhpcy50cmFuc2Zvcm0uem9vbSl8fChcImJhY2tncm91bmRcIj09PWkudHlwZXx8bi5sZW5ndGgpJiYodGhpcy5pZD1pLmlkLE1pW2kudHlwZV0odCxlLGksbikpO30sTGkucHJvdG90eXBlLnRyYW5zbGF0ZVBvc01hdHJpeD1mdW5jdGlvbihlLGksbixvLHIpe2lmKCFuWzBdJiYhblsxXSlyZXR1cm4gZTt2YXIgYT1yP1wibWFwXCI9PT1vP3RoaXMudHJhbnNmb3JtLmFuZ2xlOjA6XCJ2aWV3cG9ydFwiPT09bz8tdGhpcy50cmFuc2Zvcm0uYW5nbGU6MDtpZihhKXt2YXIgcz1NYXRoLnNpbihhKSxsPU1hdGguY29zKGEpO249W25bMF0qbC1uWzFdKnMsblswXSpzK25bMV0qbF07fXZhciBjPVtyP25bMF06emUoaSxuWzBdLHRoaXMudHJhbnNmb3JtLnpvb20pLHI/blsxXTp6ZShpLG5bMV0sdGhpcy50cmFuc2Zvcm0uem9vbSksMF0sdT1uZXcgRmxvYXQzMkFycmF5KDE2KTtyZXR1cm4gdC5tYXQ0LnRyYW5zbGF0ZSh1LGUsYyksdX0sTGkucHJvdG90eXBlLnNhdmVUaWxlVGV4dHVyZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLl90aWxlVGV4dHVyZXNbdC5zaXplWzBdXTtlP2UucHVzaCh0KTp0aGlzLl90aWxlVGV4dHVyZXNbdC5zaXplWzBdXT1bdF07fSxMaS5wcm90b3R5cGUuZ2V0VGlsZVRleHR1cmU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fdGlsZVRleHR1cmVzW3RdO3JldHVybiBlJiZlLmxlbmd0aD4wP2UucG9wKCk6bnVsbH0sTGkucHJvdG90eXBlLl9jcmVhdGVQcm9ncmFtQ2FjaGVkPWZ1bmN0aW9uKHQsZSl7dGhpcy5jYWNoZT10aGlzLmNhY2hlfHx7fTt2YXIgaT1cIlwiK3QrKGUuY2FjaGVLZXl8fFwiXCIpKyh0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3I/XCIvb3ZlcmRyYXdcIjpcIlwiKTtyZXR1cm4gdGhpcy5jYWNoZVtpXXx8KHRoaXMuY2FjaGVbaV09bmV3IGFpKHRoaXMuY29udGV4dCxyaVt0XSxlLHRoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3RvcikpLHRoaXMuY2FjaGVbaV19LExpLnByb3RvdHlwZS51c2VQcm9ncmFtPWZ1bmN0aW9uKHQsZSl7dmFyIGk9dGhpcy5fY3JlYXRlUHJvZ3JhbUNhY2hlZCh0LGV8fHRoaXMuZW1wdHlQcm9ncmFtQ29uZmlndXJhdGlvbik7cmV0dXJuIHRoaXMuY29udGV4dC5wcm9ncmFtLnNldChpLnByb2dyYW0pLGl9O3ZhciBPaT10LmRlZmF1bHQkMjAudmVjNCxGaT10LmRlZmF1bHQkMjAubWF0NCxOaT10LmRlZmF1bHQkMjAubWF0MixVaT1mdW5jdGlvbih0LGUsaSl7dGhpcy50aWxlU2l6ZT01MTIsdGhpcy5fcmVuZGVyV29ybGRDb3BpZXM9dm9pZCAwPT09aXx8aSx0aGlzLl9taW5ab29tPXR8fDAsdGhpcy5fbWF4Wm9vbT1lfHwyMix0aGlzLmxhdFJhbmdlPVstODUuMDUxMTMsODUuMDUxMTNdLHRoaXMud2lkdGg9MCx0aGlzLmhlaWdodD0wLHRoaXMuX2NlbnRlcj1uZXcgVygwLDApLHRoaXMuem9vbT0wLHRoaXMuYW5nbGU9MCx0aGlzLl9mb3Y9LjY0MzUwMTEwODc5MzI4NDQsdGhpcy5fcGl0Y2g9MCx0aGlzLl91bm1vZGlmaWVkPSEwLHRoaXMuX3Bvc01hdHJpeENhY2hlPXt9LHRoaXMuX2FsaWduZWRQb3NNYXRyaXhDYWNoZT17fTt9LFppPXttaW5ab29tOntjb25maWd1cmFibGU6ITB9LG1heFpvb206e2NvbmZpZ3VyYWJsZTohMH0scmVuZGVyV29ybGRDb3BpZXM6e2NvbmZpZ3VyYWJsZTohMH0sd29ybGRTaXplOntjb25maWd1cmFibGU6ITB9LGNlbnRlclBvaW50Ontjb25maWd1cmFibGU6ITB9LHNpemU6e2NvbmZpZ3VyYWJsZTohMH0sYmVhcmluZzp7Y29uZmlndXJhYmxlOiEwfSxwaXRjaDp7Y29uZmlndXJhYmxlOiEwfSxmb3Y6e2NvbmZpZ3VyYWJsZTohMH0sem9vbTp7Y29uZmlndXJhYmxlOiEwfSxjZW50ZXI6e2NvbmZpZ3VyYWJsZTohMH0sdW5tb2RpZmllZDp7Y29uZmlndXJhYmxlOiEwfSx4Ontjb25maWd1cmFibGU6ITB9LHk6e2NvbmZpZ3VyYWJsZTohMH0scG9pbnQ6e2NvbmZpZ3VyYWJsZTohMH19O1VpLnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3ZhciB0PW5ldyBVaSh0aGlzLl9taW5ab29tLHRoaXMuX21heFpvb20sdGhpcy5fcmVuZGVyV29ybGRDb3BpZXMpO3JldHVybiB0LnRpbGVTaXplPXRoaXMudGlsZVNpemUsdC5sYXRSYW5nZT10aGlzLmxhdFJhbmdlLHQud2lkdGg9dGhpcy53aWR0aCx0LmhlaWdodD10aGlzLmhlaWdodCx0Ll9jZW50ZXI9dGhpcy5fY2VudGVyLHQuem9vbT10aGlzLnpvb20sdC5hbmdsZT10aGlzLmFuZ2xlLHQuX2Zvdj10aGlzLl9mb3YsdC5fcGl0Y2g9dGhpcy5fcGl0Y2gsdC5fdW5tb2RpZmllZD10aGlzLl91bm1vZGlmaWVkLHQuX2NhbGNNYXRyaWNlcygpLHR9LFppLm1pblpvb20uZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX21pblpvb219LFppLm1pblpvb20uc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX21pblpvb20hPT10JiYodGhpcy5fbWluWm9vbT10LHRoaXMuem9vbT1NYXRoLm1heCh0aGlzLnpvb20sdCkpO30sWmkubWF4Wm9vbS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbWF4Wm9vbX0sWmkubWF4Wm9vbS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fbWF4Wm9vbSE9PXQmJih0aGlzLl9tYXhab29tPXQsdGhpcy56b29tPU1hdGgubWluKHRoaXMuem9vbSx0KSk7fSxaaS5yZW5kZXJXb3JsZENvcGllcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fcmVuZGVyV29ybGRDb3BpZXN9LFppLnJlbmRlcldvcmxkQ29waWVzLnNldD1mdW5jdGlvbih0KXt2b2lkIDA9PT10P3Q9ITA6bnVsbD09PXQmJih0PSExKSx0aGlzLl9yZW5kZXJXb3JsZENvcGllcz10O30sWmkud29ybGRTaXplLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRpbGVTaXplKnRoaXMuc2NhbGV9LFppLmNlbnRlclBvaW50LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNpemUuX2RpdigyKX0sWmkuc2l6ZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHQuZGVmYXVsdCQxKHRoaXMud2lkdGgsdGhpcy5oZWlnaHQpfSxaaS5iZWFyaW5nLmdldD1mdW5jdGlvbigpe3JldHVybi10aGlzLmFuZ2xlL01hdGguUEkqMTgwfSxaaS5iZWFyaW5nLnNldD1mdW5jdGlvbihlKXt2YXIgaT0tdC53cmFwKGUsLTE4MCwxODApKk1hdGguUEkvMTgwO3RoaXMuYW5nbGUhPT1pJiYodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLmFuZ2xlPWksdGhpcy5fY2FsY01hdHJpY2VzKCksdGhpcy5yb3RhdGlvbk1hdHJpeD1OaS5jcmVhdGUoKSxOaS5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCx0aGlzLnJvdGF0aW9uTWF0cml4LHRoaXMuYW5nbGUpKTt9LFppLnBpdGNoLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9waXRjaC9NYXRoLlBJKjE4MH0sWmkucGl0Y2guc2V0PWZ1bmN0aW9uKGUpe3ZhciBpPXQuY2xhbXAoZSwwLDYwKS8xODAqTWF0aC5QSTt0aGlzLl9waXRjaCE9PWkmJih0aGlzLl91bm1vZGlmaWVkPSExLHRoaXMuX3BpdGNoPWksdGhpcy5fY2FsY01hdHJpY2VzKCkpO30sWmkuZm92LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9mb3YvTWF0aC5QSSoxODB9LFppLmZvdi5zZXQ9ZnVuY3Rpb24odCl7dD1NYXRoLm1heCguMDEsTWF0aC5taW4oNjAsdCkpLHRoaXMuX2ZvdiE9PXQmJih0aGlzLl91bm1vZGlmaWVkPSExLHRoaXMuX2Zvdj10LzE4MCpNYXRoLlBJLHRoaXMuX2NhbGNNYXRyaWNlcygpKTt9LFppLnpvb20uZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3pvb219LFppLnpvb20uc2V0PWZ1bmN0aW9uKHQpe3ZhciBlPU1hdGgubWluKE1hdGgubWF4KHQsdGhpcy5taW5ab29tKSx0aGlzLm1heFpvb20pO3RoaXMuX3pvb20hPT1lJiYodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLl96b29tPWUsdGhpcy5zY2FsZT10aGlzLnpvb21TY2FsZShlKSx0aGlzLnRpbGVab29tPU1hdGguZmxvb3IoZSksdGhpcy56b29tRnJhY3Rpb249ZS10aGlzLnRpbGVab29tLHRoaXMuX2NvbnN0cmFpbigpLHRoaXMuX2NhbGNNYXRyaWNlcygpKTt9LFppLmNlbnRlci5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fY2VudGVyfSxaaS5jZW50ZXIuc2V0PWZ1bmN0aW9uKHQpe3QubGF0PT09dGhpcy5fY2VudGVyLmxhdCYmdC5sbmc9PT10aGlzLl9jZW50ZXIubG5nfHwodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLl9jZW50ZXI9dCx0aGlzLl9jb25zdHJhaW4oKSx0aGlzLl9jYWxjTWF0cmljZXMoKSk7fSxVaS5wcm90b3R5cGUuY292ZXJpbmdab29tTGV2ZWw9ZnVuY3Rpb24odCl7cmV0dXJuKHQucm91bmRab29tP01hdGgucm91bmQ6TWF0aC5mbG9vcikodGhpcy56b29tK3RoaXMuc2NhbGVab29tKHRoaXMudGlsZVNpemUvdC50aWxlU2l6ZSkpfSxVaS5wcm90b3R5cGUuZ2V0VmlzaWJsZVVud3JhcHBlZENvb3JkaW5hdGVzPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LmRlZmF1bHQkMSgwLDApLDApLG49dGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuZGVmYXVsdCQxKHRoaXMud2lkdGgsMCksMCksbz1NYXRoLmZsb29yKGkuY29sdW1uKSxyPU1hdGguZmxvb3Iobi5jb2x1bW4pLGE9W25ldyB0LlVud3JhcHBlZFRpbGVJRCgwLGUpXTtpZih0aGlzLl9yZW5kZXJXb3JsZENvcGllcylmb3IodmFyIHM9bztzPD1yO3MrKykwIT09cyYmYS5wdXNoKG5ldyB0LlVud3JhcHBlZFRpbGVJRChzLGUpKTtyZXR1cm4gYX0sVWkucHJvdG90eXBlLmNvdmVyaW5nVGlsZXM9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5jb3ZlcmluZ1pvb21MZXZlbChlKSxuPWk7aWYodm9pZCAwIT09ZS5taW56b29tJiZpPGUubWluem9vbSlyZXR1cm5bXTt2b2lkIDAhPT1lLm1heHpvb20mJmk+ZS5tYXh6b29tJiYoaT1lLm1heHpvb20pO3ZhciBvPXRoaXMucG9pbnRDb29yZGluYXRlKHRoaXMuY2VudGVyUG9pbnQsaSkscj1uZXcgdC5kZWZhdWx0JDEoby5jb2x1bW4tLjUsby5yb3ctLjUpO3JldHVybiBmdW5jdGlvbihlLGksbixvKXt2b2lkIDA9PT1vJiYobz0hMCk7dmFyIHI9MTw8ZSxhPXt9O2Z1bmN0aW9uIHMoaSxzLGwpe3ZhciBjLHUsaCxwO2lmKGw+PTAmJmw8PXIpZm9yKGM9aTtjPHM7YysrKXU9TWF0aC5mbG9vcihjL3IpLGg9KGMlcityKSVyLDAhPT11JiYhMCE9PW98fChwPW5ldyB0Lk92ZXJzY2FsZWRUaWxlSUQobix1LGUsaCxsKSxhW3Aua2V5XT1wKTt9cmV0dXJuIEJpKGlbMF0saVsxXSxpWzJdLDAscixzKSxCaShpWzJdLGlbM10saVswXSwwLHIscyksT2JqZWN0LmtleXMoYSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBhW3RdfSl9KGksW3RoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LmRlZmF1bHQkMSgwLDApLGkpLHRoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LmRlZmF1bHQkMSh0aGlzLndpZHRoLDApLGkpLHRoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LmRlZmF1bHQkMSh0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KSxpKSx0aGlzLnBvaW50Q29vcmRpbmF0ZShuZXcgdC5kZWZhdWx0JDEoMCx0aGlzLmhlaWdodCksaSldLGUucmVwYXJzZU92ZXJzY2FsZWQ/bjppLHRoaXMuX3JlbmRlcldvcmxkQ29waWVzKS5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHIuZGlzdCh0LmNhbm9uaWNhbCktci5kaXN0KGUuY2Fub25pY2FsKX0pfSxVaS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKHQsZSl7dGhpcy53aWR0aD10LHRoaXMuaGVpZ2h0PWUsdGhpcy5waXhlbHNUb0dMVW5pdHM9WzIvdCwtMi9lXSx0aGlzLl9jb25zdHJhaW4oKSx0aGlzLl9jYWxjTWF0cmljZXMoKTt9LFppLnVubW9kaWZpZWQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3VubW9kaWZpZWR9LFVpLnByb3RvdHlwZS56b29tU2NhbGU9ZnVuY3Rpb24odCl7cmV0dXJuIE1hdGgucG93KDIsdCl9LFVpLnByb3RvdHlwZS5zY2FsZVpvb209ZnVuY3Rpb24odCl7cmV0dXJuIE1hdGgubG9nKHQpL01hdGguTE4yfSxVaS5wcm90b3R5cGUucHJvamVjdD1mdW5jdGlvbihlKXtyZXR1cm4gbmV3IHQuZGVmYXVsdCQxKHRoaXMubG5nWChlLmxuZyksdGhpcy5sYXRZKGUubGF0KSl9LFVpLnByb3RvdHlwZS51bnByb2plY3Q9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBXKHRoaXMueExuZyh0LngpLHRoaXMueUxhdCh0LnkpKX0sWmkueC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5sbmdYKHRoaXMuY2VudGVyLmxuZyl9LFppLnkuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGF0WSh0aGlzLmNlbnRlci5sYXQpfSxaaS5wb2ludC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHQuZGVmYXVsdCQxKHRoaXMueCx0aGlzLnkpfSxVaS5wcm90b3R5cGUubG5nWD1mdW5jdGlvbih0KXtyZXR1cm4oMTgwK3QpKnRoaXMud29ybGRTaXplLzM2MH0sVWkucHJvdG90eXBlLmxhdFk9ZnVuY3Rpb24odCl7cmV0dXJuKDE4MC0xODAvTWF0aC5QSSpNYXRoLmxvZyhNYXRoLnRhbihNYXRoLlBJLzQrdCpNYXRoLlBJLzM2MCkpKSp0aGlzLndvcmxkU2l6ZS8zNjB9LFVpLnByb3RvdHlwZS54TG5nPWZ1bmN0aW9uKHQpe3JldHVybiAzNjAqdC90aGlzLndvcmxkU2l6ZS0xODB9LFVpLnByb3RvdHlwZS55TGF0PWZ1bmN0aW9uKHQpe3ZhciBlPTE4MC0zNjAqdC90aGlzLndvcmxkU2l6ZTtyZXR1cm4gMzYwL01hdGguUEkqTWF0aC5hdGFuKE1hdGguZXhwKGUqTWF0aC5QSS8xODApKS05MH0sVWkucHJvdG90eXBlLnNldExvY2F0aW9uQXRQb2ludD1mdW5jdGlvbih0LGUpe3ZhciBpPXRoaXMucG9pbnRDb29yZGluYXRlKGUpLl9zdWIodGhpcy5wb2ludENvb3JkaW5hdGUodGhpcy5jZW50ZXJQb2ludCkpO3RoaXMuY2VudGVyPXRoaXMuY29vcmRpbmF0ZUxvY2F0aW9uKHRoaXMubG9jYXRpb25Db29yZGluYXRlKHQpLl9zdWIoaSkpLHRoaXMuX3JlbmRlcldvcmxkQ29waWVzJiYodGhpcy5jZW50ZXI9dGhpcy5jZW50ZXIud3JhcCgpKTt9LFVpLnByb3RvdHlwZS5sb2NhdGlvblBvaW50PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZSh0KSl9LFVpLnByb3RvdHlwZS5wb2ludExvY2F0aW9uPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZSh0KSl9LFVpLnByb3RvdHlwZS5sb2NhdGlvbkNvb3JkaW5hdGU9ZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyB0LmRlZmF1bHQkMTcodGhpcy5sbmdYKGUubG5nKS90aGlzLnRpbGVTaXplLHRoaXMubGF0WShlLmxhdCkvdGhpcy50aWxlU2l6ZSx0aGlzLnpvb20pLnpvb21Ubyh0aGlzLnRpbGVab29tKX0sVWkucHJvdG90eXBlLmNvb3JkaW5hdGVMb2NhdGlvbj1mdW5jdGlvbih0KXt2YXIgZT10Lnpvb21Ubyh0aGlzLnpvb20pO3JldHVybiBuZXcgVyh0aGlzLnhMbmcoZS5jb2x1bW4qdGhpcy50aWxlU2l6ZSksdGhpcy55TGF0KGUucm93KnRoaXMudGlsZVNpemUpKX0sVWkucHJvdG90eXBlLnBvaW50Q29vcmRpbmF0ZT1mdW5jdGlvbihlLGkpe3ZvaWQgMD09PWkmJihpPXRoaXMudGlsZVpvb20pO3ZhciBuPVtlLngsZS55LDAsMV0sbz1bZS54LGUueSwxLDFdO09pLnRyYW5zZm9ybU1hdDQobixuLHRoaXMucGl4ZWxNYXRyaXhJbnZlcnNlKSxPaS50cmFuc2Zvcm1NYXQ0KG8sbyx0aGlzLnBpeGVsTWF0cml4SW52ZXJzZSk7dmFyIHI9blszXSxhPW9bM10scz1uWzBdL3IsbD1vWzBdL2EsYz1uWzFdL3IsdT1vWzFdL2EsaD1uWzJdL3IscD1vWzJdL2EsZD1oPT09cD8wOigwLWgpLyhwLWgpO3JldHVybiBuZXcgdC5kZWZhdWx0JDE3KHQubnVtYmVyKHMsbCxkKS90aGlzLnRpbGVTaXplLHQubnVtYmVyKGMsdSxkKS90aGlzLnRpbGVTaXplLHRoaXMuem9vbSkuX3pvb21UbyhpKX0sVWkucHJvdG90eXBlLmNvb3JkaW5hdGVQb2ludD1mdW5jdGlvbihlKXt2YXIgaT1lLnpvb21Ubyh0aGlzLnpvb20pLG49W2kuY29sdW1uKnRoaXMudGlsZVNpemUsaS5yb3cqdGhpcy50aWxlU2l6ZSwwLDFdO3JldHVybiBPaS50cmFuc2Zvcm1NYXQ0KG4sbix0aGlzLnBpeGVsTWF0cml4KSxuZXcgdC5kZWZhdWx0JDEoblswXS9uWzNdLG5bMV0vblszXSl9LFVpLnByb3RvdHlwZS5jYWxjdWxhdGVQb3NNYXRyaXg9ZnVuY3Rpb24oZSxpKXt2b2lkIDA9PT1pJiYoaT0hMSk7dmFyIG49ZS5rZXksbz1pP3RoaXMuX2FsaWduZWRQb3NNYXRyaXhDYWNoZTp0aGlzLl9wb3NNYXRyaXhDYWNoZTtpZihvW25dKXJldHVybiBvW25dO3ZhciByPWUuY2Fub25pY2FsLGE9dGhpcy53b3JsZFNpemUvdGhpcy56b29tU2NhbGUoci56KSxzPXIueCtNYXRoLnBvdygyLHIueikqZS53cmFwLGw9RmkuaWRlbnRpdHkobmV3IEZsb2F0NjRBcnJheSgxNikpO3JldHVybiBGaS50cmFuc2xhdGUobCxsLFtzKmEsci55KmEsMF0pLEZpLnNjYWxlKGwsbCxbYS90LmRlZmF1bHQkOCxhL3QuZGVmYXVsdCQ4LDFdKSxGaS5tdWx0aXBseShsLGk/dGhpcy5hbGlnbmVkUHJvak1hdHJpeDp0aGlzLnByb2pNYXRyaXgsbCksb1tuXT1uZXcgRmxvYXQzMkFycmF5KGwpLG9bbl19LFVpLnByb3RvdHlwZS5fY29uc3RyYWluPWZ1bmN0aW9uKCl7aWYodGhpcy5jZW50ZXImJnRoaXMud2lkdGgmJnRoaXMuaGVpZ2h0JiYhdGhpcy5fY29uc3RyYWluaW5nKXt0aGlzLl9jb25zdHJhaW5pbmc9ITA7dmFyIGUsaSxuLG8scj0tOTAsYT05MCxzPS0xODAsbD0xODAsYz10aGlzLnNpemUsdT10aGlzLl91bm1vZGlmaWVkO2lmKHRoaXMubGF0UmFuZ2Upe3ZhciBoPXRoaXMubGF0UmFuZ2U7cj10aGlzLmxhdFkoaFsxXSksZT0oYT10aGlzLmxhdFkoaFswXSkpLXI8Yy55P2MueS8oYS1yKTowO31pZih0aGlzLmxuZ1JhbmdlKXt2YXIgcD10aGlzLmxuZ1JhbmdlO3M9dGhpcy5sbmdYKHBbMF0pLGk9KGw9dGhpcy5sbmdYKHBbMV0pKS1zPGMueD9jLngvKGwtcyk6MDt9dmFyIGQ9TWF0aC5tYXgoaXx8MCxlfHwwKTtpZihkKXJldHVybiB0aGlzLmNlbnRlcj10aGlzLnVucHJvamVjdChuZXcgdC5kZWZhdWx0JDEoaT8obCtzKS8yOnRoaXMueCxlPyhhK3IpLzI6dGhpcy55KSksdGhpcy56b29tKz10aGlzLnNjYWxlWm9vbShkKSx0aGlzLl91bm1vZGlmaWVkPXUsdm9pZCh0aGlzLl9jb25zdHJhaW5pbmc9ITEpO2lmKHRoaXMubGF0UmFuZ2Upe3ZhciBmPXRoaXMueSxtPWMueS8yO2YtbTxyJiYobz1yK20pLGYrbT5hJiYobz1hLW0pO31pZih0aGlzLmxuZ1JhbmdlKXt2YXIgXz10aGlzLngsZz1jLngvMjtfLWc8cyYmKG49cytnKSxfK2c+bCYmKG49bC1nKTt9dm9pZCAwPT09biYmdm9pZCAwPT09b3x8KHRoaXMuY2VudGVyPXRoaXMudW5wcm9qZWN0KG5ldyB0LmRlZmF1bHQkMSh2b2lkIDAhPT1uP246dGhpcy54LHZvaWQgMCE9PW8/bzp0aGlzLnkpKSksdGhpcy5fdW5tb2RpZmllZD11LHRoaXMuX2NvbnN0cmFpbmluZz0hMTt9fSxVaS5wcm90b3R5cGUuX2NhbGNNYXRyaWNlcz1mdW5jdGlvbigpe2lmKHRoaXMuaGVpZ2h0KXt0aGlzLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2U9LjUvTWF0aC50YW4odGhpcy5fZm92LzIpKnRoaXMuaGVpZ2h0O3ZhciB0PXRoaXMuX2Zvdi8yLGU9TWF0aC5QSS8yK3RoaXMuX3BpdGNoLGk9TWF0aC5zaW4odCkqdGhpcy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlL01hdGguc2luKE1hdGguUEktZS10KSxuPXRoaXMueCxvPXRoaXMueSxyPTEuMDEqKE1hdGguY29zKE1hdGguUEkvMi10aGlzLl9waXRjaCkqaSt0aGlzLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UpLGE9bmV3IEZsb2F0NjRBcnJheSgxNik7RmkucGVyc3BlY3RpdmUoYSx0aGlzLl9mb3YsdGhpcy53aWR0aC90aGlzLmhlaWdodCwxLHIpLEZpLnNjYWxlKGEsYSxbMSwtMSwxXSksRmkudHJhbnNsYXRlKGEsYSxbMCwwLC10aGlzLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2VdKSxGaS5yb3RhdGVYKGEsYSx0aGlzLl9waXRjaCksRmkucm90YXRlWihhLGEsdGhpcy5hbmdsZSksRmkudHJhbnNsYXRlKGEsYSxbLW4sLW8sMF0pO3ZhciBzPXRoaXMud29ybGRTaXplLygyKk1hdGguUEkqNjM3ODEzNypNYXRoLmFicyhNYXRoLmNvcyh0aGlzLmNlbnRlci5sYXQqKE1hdGguUEkvMTgwKSkpKTtGaS5zY2FsZShhLGEsWzEsMSxzLDFdKSx0aGlzLnByb2pNYXRyaXg9YTt2YXIgbD10aGlzLndpZHRoJTIvMixjPXRoaXMuaGVpZ2h0JTIvMix1PU1hdGguY29zKHRoaXMuYW5nbGUpLGg9TWF0aC5zaW4odGhpcy5hbmdsZSkscD1uLU1hdGgucm91bmQobikrdSpsK2gqYyxkPW8tTWF0aC5yb3VuZChvKSt1KmMraCpsLGY9bmV3IEZsb2F0NjRBcnJheShhKTtpZihGaS50cmFuc2xhdGUoZixmLFtwPi41P3AtMTpwLGQ+LjU/ZC0xOmQsMF0pLHRoaXMuYWxpZ25lZFByb2pNYXRyaXg9ZixhPUZpLmNyZWF0ZSgpLEZpLnNjYWxlKGEsYSxbdGhpcy53aWR0aC8yLC10aGlzLmhlaWdodC8yLDFdKSxGaS50cmFuc2xhdGUoYSxhLFsxLC0xLDBdKSx0aGlzLnBpeGVsTWF0cml4PUZpLm11bHRpcGx5KG5ldyBGbG9hdDY0QXJyYXkoMTYpLGEsdGhpcy5wcm9qTWF0cml4KSwhKGE9RmkuaW52ZXJ0KG5ldyBGbG9hdDY0QXJyYXkoMTYpLHRoaXMucGl4ZWxNYXRyaXgpKSl0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gaW52ZXJ0IG1hdHJpeFwiKTt0aGlzLnBpeGVsTWF0cml4SW52ZXJzZT1hLHRoaXMuX3Bvc01hdHJpeENhY2hlPXt9LHRoaXMuX2FsaWduZWRQb3NNYXRyaXhDYWNoZT17fTt9fSxVaS5wcm90b3R5cGUubWF4UGl0Y2hTY2FsZUZhY3Rvcj1mdW5jdGlvbigpe2lmKCF0aGlzLnBpeGVsTWF0cml4SW52ZXJzZSlyZXR1cm4gMTt2YXIgZT10aGlzLnBvaW50Q29vcmRpbmF0ZShuZXcgdC5kZWZhdWx0JDEoMCwwKSkuem9vbVRvKHRoaXMuem9vbSksaT1bZS5jb2x1bW4qdGhpcy50aWxlU2l6ZSxlLnJvdyp0aGlzLnRpbGVTaXplLDAsMV07cmV0dXJuIE9pLnRyYW5zZm9ybU1hdDQoaSxpLHRoaXMucGl4ZWxNYXRyaXgpWzNdL3RoaXMuY2FtZXJhVG9DZW50ZXJEaXN0YW5jZX0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoVWkucHJvdG90eXBlLFppKTt2YXIgVmk9ZnVuY3Rpb24oKXt2YXIgZSxpLG4sbyxyO3QuYmluZEFsbChbXCJfb25IYXNoQ2hhbmdlXCIsXCJfdXBkYXRlSGFzaFwiXSx0aGlzKSx0aGlzLl91cGRhdGVIYXNoPShlPXRoaXMuX3VwZGF0ZUhhc2hVbnRocm90dGxlZC5iaW5kKHRoaXMpLGk9MzAwLG49ITEsbz0wLHI9ZnVuY3Rpb24oKXtvPTAsbiYmKGUoKSxvPXNldFRpbWVvdXQocixpKSxuPSExKTt9LGZ1bmN0aW9uKCl7cmV0dXJuIG49ITAsb3x8cigpLG99KTt9O1ZpLnByb3RvdHlwZS5hZGRUbz1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5fbWFwPWUsdC5kZWZhdWx0LmFkZEV2ZW50TGlzdGVuZXIoXCJoYXNoY2hhbmdlXCIsdGhpcy5fb25IYXNoQ2hhbmdlLCExKSx0aGlzLl9tYXAub24oXCJtb3ZlZW5kXCIsdGhpcy5fdXBkYXRlSGFzaCksdGhpc30sVmkucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbigpe3JldHVybiB0LmRlZmF1bHQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImhhc2hjaGFuZ2VcIix0aGlzLl9vbkhhc2hDaGFuZ2UsITEpLHRoaXMuX21hcC5vZmYoXCJtb3ZlZW5kXCIsdGhpcy5fdXBkYXRlSGFzaCksY2xlYXJUaW1lb3V0KHRoaXMuX3VwZGF0ZUhhc2goKSksZGVsZXRlIHRoaXMuX21hcCx0aGlzfSxWaS5wcm90b3R5cGUuZ2V0SGFzaFN0cmluZz1mdW5jdGlvbih0KXt2YXIgZT10aGlzLl9tYXAuZ2V0Q2VudGVyKCksaT1NYXRoLnJvdW5kKDEwMCp0aGlzLl9tYXAuZ2V0Wm9vbSgpKS8xMDAsbj1NYXRoLmNlaWwoKGkqTWF0aC5MTjIrTWF0aC5sb2coNTEyLzM2MC8uNSkpL01hdGguTE4xMCksbz1NYXRoLnBvdygxMCxuKSxyPU1hdGgucm91bmQoZS5sbmcqbykvbyxhPU1hdGgucm91bmQoZS5sYXQqbykvbyxzPXRoaXMuX21hcC5nZXRCZWFyaW5nKCksbD10aGlzLl9tYXAuZ2V0UGl0Y2goKSxjPVwiXCI7cmV0dXJuIGMrPXQ/XCIjL1wiK3IrXCIvXCIrYStcIi9cIitpOlwiI1wiK2krXCIvXCIrYStcIi9cIityLChzfHxsKSYmKGMrPVwiL1wiK01hdGgucm91bmQoMTAqcykvMTApLGwmJihjKz1cIi9cIitNYXRoLnJvdW5kKGwpKSxjfSxWaS5wcm90b3R5cGUuX29uSGFzaENoYW5nZT1mdW5jdGlvbigpe3ZhciBlPXQuZGVmYXVsdC5sb2NhdGlvbi5oYXNoLnJlcGxhY2UoXCIjXCIsXCJcIikuc3BsaXQoXCIvXCIpO3JldHVybiBlLmxlbmd0aD49MyYmKHRoaXMuX21hcC5qdW1wVG8oe2NlbnRlcjpbK2VbMl0sK2VbMV1dLHpvb206K2VbMF0sYmVhcmluZzorKGVbM118fDApLHBpdGNoOisoZVs0XXx8MCl9KSwhMCl9LFZpLnByb3RvdHlwZS5fdXBkYXRlSGFzaFVudGhyb3R0bGVkPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5nZXRIYXNoU3RyaW5nKCk7dC5kZWZhdWx0Lmhpc3RvcnkucmVwbGFjZVN0YXRlKHQuZGVmYXVsdC5oaXN0b3J5LnN0YXRlLFwiXCIsZSk7fTt2YXIgamk9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpLG4sbyxyKXt2b2lkIDA9PT1yJiYocj17fSk7dmFyIGE9cy5tb3VzZVBvcyhuLmdldENhbnZhc0NvbnRhaW5lcigpLG8pLGw9bi51bnByb2plY3QoYSk7ZS5jYWxsKHRoaXMsaSx0LmV4dGVuZCh7cG9pbnQ6YSxsbmdMYXQ6bCxvcmlnaW5hbEV2ZW50Om99LHIpKSx0aGlzLl9kZWZhdWx0UHJldmVudGVkPSExLHRoaXMudGFyZ2V0PW47fWUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pO3ZhciBuPXtkZWZhdWx0UHJldmVudGVkOntjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gaS5wcm90b3R5cGUucHJldmVudERlZmF1bHQ9ZnVuY3Rpb24oKXt0aGlzLl9kZWZhdWx0UHJldmVudGVkPSEwO30sbi5kZWZhdWx0UHJldmVudGVkLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9kZWZhdWx0UHJldmVudGVkfSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhpLnByb3RvdHlwZSxuKSxpfSh0LkV2ZW50KSwkaT1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbixvKXt2YXIgcj1zLnRvdWNoUG9zKG4uZ2V0Q2FudmFzQ29udGFpbmVyKCksbyksYT1yLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gbi51bnByb2plY3QodCl9KSxsPXIucmVkdWNlKGZ1bmN0aW9uKHQsZSxpLG4pe3JldHVybiB0LmFkZChlLmRpdihuLmxlbmd0aCkpfSxuZXcgdC5kZWZhdWx0JDEoMCwwKSksYz1uLnVucHJvamVjdChsKTtlLmNhbGwodGhpcyxpLHtwb2ludHM6cixwb2ludDpsLGxuZ0xhdHM6YSxsbmdMYXQ6YyxvcmlnaW5hbEV2ZW50Om99KSx0aGlzLl9kZWZhdWx0UHJldmVudGVkPSExO31lJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aTt2YXIgbj17ZGVmYXVsdFByZXZlbnRlZDp7Y29uZmlndXJhYmxlOiEwfX07cmV0dXJuIGkucHJvdG90eXBlLnByZXZlbnREZWZhdWx0PWZ1bmN0aW9uKCl7dGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMDt9LG4uZGVmYXVsdFByZXZlbnRlZC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZGVmYXVsdFByZXZlbnRlZH0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoaS5wcm90b3R5cGUsbiksaX0odC5FdmVudCksR2k9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLGksbil7dC5jYWxsKHRoaXMsZSx7b3JpZ2luYWxFdmVudDpufSksdGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMTt9dCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWU7dmFyIGk9e2RlZmF1bHRQcmV2ZW50ZWQ6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiBlLnByb3RvdHlwZS5wcmV2ZW50RGVmYXVsdD1mdW5jdGlvbigpe3RoaXMuX2RlZmF1bHRQcmV2ZW50ZWQ9ITA7fSxpLmRlZmF1bHRQcmV2ZW50ZWQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2RlZmF1bHRQcmV2ZW50ZWR9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLGkpLGV9KHQuRXZlbnQpLFdpPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdGhpcy5fZGVsdGE9MCx0LmJpbmRBbGwoW1wiX29uV2hlZWxcIixcIl9vblRpbWVvdXRcIixcIl9vblNjcm9sbEZyYW1lXCIsXCJfb25TY3JvbGxGaW5pc2hlZFwiXSx0aGlzKTt9O1dpLnByb3RvdHlwZS5pc0VuYWJsZWQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX2VuYWJsZWR9LFdpLnByb3RvdHlwZS5pc0FjdGl2ZT1mdW5jdGlvbigpe3JldHVybiEhdGhpcy5fYWN0aXZlfSxXaS5wcm90b3R5cGUuZW5hYmxlPWZ1bmN0aW9uKHQpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbmFibGVkPSEwLHRoaXMuX2Fyb3VuZENlbnRlcj10JiZcImNlbnRlclwiPT09dC5hcm91bmQpO30sV2kucHJvdG90eXBlLmRpc2FibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpJiYodGhpcy5fZW5hYmxlZD0hMSk7fSxXaS5wcm90b3R5cGUub25XaGVlbD1mdW5jdGlvbihlKXtpZih0aGlzLmlzRW5hYmxlZCgpKXt2YXIgaT1lLmRlbHRhTW9kZT09PXQuZGVmYXVsdC5XaGVlbEV2ZW50LkRPTV9ERUxUQV9MSU5FPzQwKmUuZGVsdGFZOmUuZGVsdGFZLG49ci5ub3coKSxvPW4tKHRoaXMuX2xhc3RXaGVlbEV2ZW50VGltZXx8MCk7dGhpcy5fbGFzdFdoZWVsRXZlbnRUaW1lPW4sMCE9PWkmJmklNC4wMDAyNDQxNDA2MjU9PTA/dGhpcy5fdHlwZT1cIndoZWVsXCI6MCE9PWkmJk1hdGguYWJzKGkpPDQ/dGhpcy5fdHlwZT1cInRyYWNrcGFkXCI6bz40MDA/KHRoaXMuX3R5cGU9bnVsbCx0aGlzLl9sYXN0VmFsdWU9aSx0aGlzLl90aW1lb3V0PXNldFRpbWVvdXQodGhpcy5fb25UaW1lb3V0LDQwLGUpKTp0aGlzLl90eXBlfHwodGhpcy5fdHlwZT1NYXRoLmFicyhvKmkpPDIwMD9cInRyYWNrcGFkXCI6XCJ3aGVlbFwiLHRoaXMuX3RpbWVvdXQmJihjbGVhclRpbWVvdXQodGhpcy5fdGltZW91dCksdGhpcy5fdGltZW91dD1udWxsLGkrPXRoaXMuX2xhc3RWYWx1ZSkpLGUuc2hpZnRLZXkmJmkmJihpLz00KSx0aGlzLl90eXBlJiYodGhpcy5fbGFzdFdoZWVsRXZlbnQ9ZSx0aGlzLl9kZWx0YS09aSx0aGlzLmlzQWN0aXZlKCl8fHRoaXMuX3N0YXJ0KGUpKSxlLnByZXZlbnREZWZhdWx0KCk7fX0sV2kucHJvdG90eXBlLl9vblRpbWVvdXQ9ZnVuY3Rpb24odCl7dGhpcy5fdHlwZT1cIndoZWVsXCIsdGhpcy5fZGVsdGEtPXRoaXMuX2xhc3RWYWx1ZSx0aGlzLmlzQWN0aXZlKCl8fHRoaXMuX3N0YXJ0KHQpO30sV2kucHJvdG90eXBlLl9zdGFydD1mdW5jdGlvbihlKXtpZih0aGlzLl9kZWx0YSl7dGhpcy5fZnJhbWVJZCYmKHRoaXMuX21hcC5fY2FuY2VsUmVuZGVyRnJhbWUodGhpcy5fZnJhbWVJZCksdGhpcy5fZnJhbWVJZD1udWxsKSx0aGlzLl9hY3RpdmU9ITAsdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJtb3Zlc3RhcnRcIix7b3JpZ2luYWxFdmVudDplfSkpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwiem9vbXN0YXJ0XCIse29yaWdpbmFsRXZlbnQ6ZX0pKSx0aGlzLl9maW5pc2hUaW1lb3V0JiZjbGVhclRpbWVvdXQodGhpcy5fZmluaXNoVGltZW91dCk7dmFyIGk9cy5tb3VzZVBvcyh0aGlzLl9lbCxlKTt0aGlzLl9hcm91bmQ9Vy5jb252ZXJ0KHRoaXMuX2Fyb3VuZENlbnRlcj90aGlzLl9tYXAuZ2V0Q2VudGVyKCk6dGhpcy5fbWFwLnVucHJvamVjdChpKSksdGhpcy5fYXJvdW5kUG9pbnQ9dGhpcy5fbWFwLnRyYW5zZm9ybS5sb2NhdGlvblBvaW50KHRoaXMuX2Fyb3VuZCksdGhpcy5fZnJhbWVJZHx8KHRoaXMuX2ZyYW1lSWQ9dGhpcy5fbWFwLl9yZXF1ZXN0UmVuZGVyRnJhbWUodGhpcy5fb25TY3JvbGxGcmFtZSkpO319LFdpLnByb3RvdHlwZS5fb25TY3JvbGxGcmFtZT1mdW5jdGlvbigpe3ZhciBlPXRoaXM7aWYodGhpcy5fZnJhbWVJZD1udWxsLHRoaXMuaXNBY3RpdmUoKSl7dmFyIGk9dGhpcy5fbWFwLnRyYW5zZm9ybTtpZigwIT09dGhpcy5fZGVsdGEpe3ZhciBuPVwid2hlZWxcIj09PXRoaXMuX3R5cGUmJk1hdGguYWJzKHRoaXMuX2RlbHRhKT40LjAwMDI0NDE0MDYyNT8xLzQ1MDouMDEsbz0yLygxK01hdGguZXhwKC1NYXRoLmFicyh0aGlzLl9kZWx0YSpuKSkpO3RoaXMuX2RlbHRhPDAmJjAhPT1vJiYobz0xL28pO3ZhciBhPVwibnVtYmVyXCI9PXR5cGVvZiB0aGlzLl90YXJnZXRab29tP2kuem9vbVNjYWxlKHRoaXMuX3RhcmdldFpvb20pOmkuc2NhbGU7dGhpcy5fdGFyZ2V0Wm9vbT1NYXRoLm1pbihpLm1heFpvb20sTWF0aC5tYXgoaS5taW5ab29tLGkuc2NhbGVab29tKGEqbykpKSxcIndoZWVsXCI9PT10aGlzLl90eXBlJiYodGhpcy5fc3RhcnRab29tPWkuem9vbSx0aGlzLl9lYXNpbmc9dGhpcy5fc21vb3RoT3V0RWFzaW5nKDIwMCkpLHRoaXMuX2RlbHRhPTA7fXZhciBzPSExO2lmKFwid2hlZWxcIj09PXRoaXMuX3R5cGUpe3ZhciBsPU1hdGgubWluKChyLm5vdygpLXRoaXMuX2xhc3RXaGVlbEV2ZW50VGltZSkvMjAwLDEpLGM9dGhpcy5fZWFzaW5nKGwpO2kuem9vbT10Lm51bWJlcih0aGlzLl9zdGFydFpvb20sdGhpcy5fdGFyZ2V0Wm9vbSxjKSxsPDE/dGhpcy5fZnJhbWVJZHx8KHRoaXMuX2ZyYW1lSWQ9dGhpcy5fbWFwLl9yZXF1ZXN0UmVuZGVyRnJhbWUodGhpcy5fb25TY3JvbGxGcmFtZSkpOnM9ITA7fWVsc2UgaS56b29tPXRoaXMuX3RhcmdldFpvb20scz0hMDtpLnNldExvY2F0aW9uQXRQb2ludCh0aGlzLl9hcm91bmQsdGhpcy5fYXJvdW5kUG9pbnQpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLHtvcmlnaW5hbEV2ZW50OnRoaXMuX2xhc3RXaGVlbEV2ZW50fSkpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwiem9vbVwiLHtvcmlnaW5hbEV2ZW50OnRoaXMuX2xhc3RXaGVlbEV2ZW50fSkpLHMmJih0aGlzLl9hY3RpdmU9ITEsdGhpcy5fZmluaXNoVGltZW91dD1zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7ZS5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tZW5kXCIse29yaWdpbmFsRXZlbnQ6ZS5fbGFzdFdoZWVsRXZlbnR9KSksZS5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlZW5kXCIse29yaWdpbmFsRXZlbnQ6ZS5fbGFzdFdoZWVsRXZlbnR9KSksZGVsZXRlIGUuX3RhcmdldFpvb207fSwyMDApKTt9fSxXaS5wcm90b3R5cGUuX3Ntb290aE91dEVhc2luZz1mdW5jdGlvbihlKXt2YXIgaT10LmVhc2U7aWYodGhpcy5fcHJldkVhc2Upe3ZhciBuPXRoaXMuX3ByZXZFYXNlLG89KHIubm93KCktbi5zdGFydCkvbi5kdXJhdGlvbixhPW4uZWFzaW5nKG8rLjAxKS1uLmVhc2luZyhvKSxzPS4yNy9NYXRoLnNxcnQoYSphKzFlLTQpKi4wMSxsPU1hdGguc3FydCguMDcyOS1zKnMpO2k9dC5iZXppZXIocyxsLC4yNSwxKTt9cmV0dXJuIHRoaXMuX3ByZXZFYXNlPXtzdGFydDpyLm5vdygpLGR1cmF0aW9uOmUsZWFzaW5nOml9LGl9O3ZhciBxaT1mdW5jdGlvbihlKXt0aGlzLl9tYXA9ZSx0aGlzLl9lbD1lLmdldENhbnZhc0NvbnRhaW5lcigpLHRoaXMuX2NvbnRhaW5lcj1lLmdldENvbnRhaW5lcigpLHQuYmluZEFsbChbXCJfb25Nb3VzZU1vdmVcIixcIl9vbk1vdXNlVXBcIixcIl9vbktleURvd25cIl0sdGhpcyk7fTtxaS5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuISF0aGlzLl9lbmFibGVkfSxxaS5wcm90b3R5cGUuaXNBY3RpdmU9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX2FjdGl2ZX0scWkucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbmFibGVkPSEwKTt9LHFpLnByb3RvdHlwZS5kaXNhYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKSYmKHRoaXMuX2VuYWJsZWQ9ITEpO30scWkucHJvdG90eXBlLm9uTW91c2VEb3duPWZ1bmN0aW9uKGUpe3RoaXMuaXNFbmFibGVkKCkmJmUuc2hpZnRLZXkmJjA9PT1lLmJ1dHRvbiYmKHQuZGVmYXVsdC5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsdGhpcy5fb25Nb3VzZU1vdmUsITEpLHQuZGVmYXVsdC5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwia2V5ZG93blwiLHRoaXMuX29uS2V5RG93biwhMSksdC5kZWZhdWx0LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwLCExKSxzLmRpc2FibGVEcmFnKCksdGhpcy5fc3RhcnRQb3M9cy5tb3VzZVBvcyh0aGlzLl9lbCxlKSx0aGlzLl9hY3RpdmU9ITApO30scWkucHJvdG90eXBlLl9vbk1vdXNlTW92ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLl9zdGFydFBvcyxpPXMubW91c2VQb3ModGhpcy5fZWwsdCk7dGhpcy5fYm94fHwodGhpcy5fYm94PXMuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1ib3h6b29tXCIsdGhpcy5fY29udGFpbmVyKSx0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWNyb3NzaGFpclwiKSx0aGlzLl9maXJlRXZlbnQoXCJib3h6b29tc3RhcnRcIix0KSk7dmFyIG49TWF0aC5taW4oZS54LGkueCksbz1NYXRoLm1heChlLngsaS54KSxyPU1hdGgubWluKGUueSxpLnkpLGE9TWF0aC5tYXgoZS55LGkueSk7cy5zZXRUcmFuc2Zvcm0odGhpcy5fYm94LFwidHJhbnNsYXRlKFwiK24rXCJweCxcIityK1wicHgpXCIpLHRoaXMuX2JveC5zdHlsZS53aWR0aD1vLW4rXCJweFwiLHRoaXMuX2JveC5zdHlsZS5oZWlnaHQ9YS1yK1wicHhcIjt9LHFpLnByb3RvdHlwZS5fb25Nb3VzZVVwPWZ1bmN0aW9uKGUpe2lmKDA9PT1lLmJ1dHRvbil7dmFyIGk9dGhpcy5fc3RhcnRQb3Msbj1zLm1vdXNlUG9zKHRoaXMuX2VsLGUpLG89KG5ldyBxKS5leHRlbmQodGhpcy5fbWFwLnVucHJvamVjdChpKSkuZXh0ZW5kKHRoaXMuX21hcC51bnByb2plY3QobikpO3RoaXMuX2ZpbmlzaCgpLHMuc3VwcHJlc3NDbGljaygpLGkueD09PW4ueCYmaS55PT09bi55P3RoaXMuX2ZpcmVFdmVudChcImJveHpvb21jYW5jZWxcIixlKTp0aGlzLl9tYXAuZml0Qm91bmRzKG8se2xpbmVhcjohMH0pLmZpcmUobmV3IHQuRXZlbnQoXCJib3h6b29tZW5kXCIse29yaWdpbmFsRXZlbnQ6ZSxib3hab29tQm91bmRzOm99KSk7fX0scWkucHJvdG90eXBlLl9vbktleURvd249ZnVuY3Rpb24odCl7Mjc9PT10LmtleUNvZGUmJih0aGlzLl9maW5pc2goKSx0aGlzLl9maXJlRXZlbnQoXCJib3h6b29tY2FuY2VsXCIsdCkpO30scWkucHJvdG90eXBlLl9maW5pc2g9ZnVuY3Rpb24oKXt0aGlzLl9hY3RpdmU9ITEsdC5kZWZhdWx0LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdXNlTW92ZSwhMSksdC5kZWZhdWx0LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsdGhpcy5fb25LZXlEb3duLCExKSx0LmRlZmF1bHQuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIix0aGlzLl9vbk1vdXNlVXAsITEpLHRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3Jvc3NoYWlyXCIpLHRoaXMuX2JveCYmKHMucmVtb3ZlKHRoaXMuX2JveCksdGhpcy5fYm94PW51bGwpLHMuZW5hYmxlRHJhZygpO30scWkucHJvdG90eXBlLl9maXJlRXZlbnQ9ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoZSx7b3JpZ2luYWxFdmVudDppfSkpfTt2YXIgWGk9dC5iZXppZXIoMCwwLC4yNSwxKSxIaT1mdW5jdGlvbihlLGkpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWkuZWxlbWVudHx8ZS5nZXRDYW52YXNDb250YWluZXIoKSx0aGlzLl9zdGF0ZT1cImRpc2FibGVkXCIsdGhpcy5fYnV0dG9uPWkuYnV0dG9ufHxcInJpZ2h0XCIsdGhpcy5fYmVhcmluZ1NuYXA9aS5iZWFyaW5nU25hcHx8MCx0aGlzLl9waXRjaFdpdGhSb3RhdGU9ITEhPT1pLnBpdGNoV2l0aFJvdGF0ZSx0LmJpbmRBbGwoW1wiX29uTW91c2VNb3ZlXCIsXCJfb25Nb3VzZVVwXCIsXCJfb25CbHVyXCIsXCJfb25EcmFnRnJhbWVcIl0sdGhpcyk7fTtIaS5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuXCJkaXNhYmxlZFwiIT09dGhpcy5fc3RhdGV9LEhpLnByb3RvdHlwZS5pc0FjdGl2ZT1mdW5jdGlvbigpe3JldHVyblwiYWN0aXZlXCI9PT10aGlzLl9zdGF0ZX0sSGkucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIik7fSxIaS5wcm90b3R5cGUuZGlzYWJsZT1mdW5jdGlvbigpe2lmKHRoaXMuaXNFbmFibGVkKCkpc3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImRpc2FibGVkXCIsdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2ZpcmVFdmVudChcInJvdGF0ZWVuZFwiKSx0aGlzLl9waXRjaFdpdGhSb3RhdGUmJnRoaXMuX2ZpcmVFdmVudChcInBpdGNoZW5kXCIpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVlbmRcIik7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIix0aGlzLl91bmJpbmQoKTticmVhaztkZWZhdWx0OnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIjt9fSxIaS5wcm90b3R5cGUub25Nb3VzZURvd249ZnVuY3Rpb24oZSl7aWYoXCJlbmFibGVkXCI9PT10aGlzLl9zdGF0ZSl7aWYoXCJyaWdodFwiPT09dGhpcy5fYnV0dG9uKXtpZih0aGlzLl9ldmVudEJ1dHRvbj1zLm1vdXNlQnV0dG9uKGUpLHRoaXMuX2V2ZW50QnV0dG9uIT09KGUuY3RybEtleT8wOjIpKXJldHVybn1lbHNle2lmKGUuY3RybEtleXx8MCE9PXMubW91c2VCdXR0b24oZSkpcmV0dXJuO3RoaXMuX2V2ZW50QnV0dG9uPTA7fXMuZGlzYWJsZURyYWcoKSx0LmRlZmF1bHQuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlbW92ZVwiLHRoaXMuX29uTW91c2VNb3ZlLHtjYXB0dXJlOiEwfSksdC5kZWZhdWx0LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwKSx0LmRlZmF1bHQuYWRkRXZlbnRMaXN0ZW5lcihcImJsdXJcIix0aGlzLl9vbkJsdXIpLHRoaXMuX3N0YXRlPVwicGVuZGluZ1wiLHRoaXMuX2luZXJ0aWE9W1tyLm5vdygpLHRoaXMuX21hcC5nZXRCZWFyaW5nKCldXSx0aGlzLl9wcmV2aW91c1Bvcz1zLm1vdXNlUG9zKHRoaXMuX2VsLGUpLHRoaXMuX2NlbnRlcj10aGlzLl9tYXAudHJhbnNmb3JtLmNlbnRlclBvaW50LGUucHJldmVudERlZmF1bHQoKTt9fSxIaS5wcm90b3R5cGUuX29uTW91c2VNb3ZlPWZ1bmN0aW9uKHQpe3RoaXMuX2xhc3RNb3ZlRXZlbnQ9dCx0aGlzLl9wb3M9cy5tb3VzZVBvcyh0aGlzLl9lbCx0KSxcInBlbmRpbmdcIj09PXRoaXMuX3N0YXRlJiYodGhpcy5fc3RhdGU9XCJhY3RpdmVcIix0aGlzLl9maXJlRXZlbnQoXCJyb3RhdGVzdGFydFwiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVzdGFydFwiLHQpLHRoaXMuX3BpdGNoV2l0aFJvdGF0ZSYmdGhpcy5fZmlyZUV2ZW50KFwicGl0Y2hzdGFydFwiLHQpKSx0aGlzLl9mcmFtZUlkfHwodGhpcy5fZnJhbWVJZD10aGlzLl9tYXAuX3JlcXVlc3RSZW5kZXJGcmFtZSh0aGlzLl9vbkRyYWdGcmFtZSkpO30sSGkucHJvdG90eXBlLl9vbkRyYWdGcmFtZT1mdW5jdGlvbigpe3RoaXMuX2ZyYW1lSWQ9bnVsbDt2YXIgdD10aGlzLl9sYXN0TW92ZUV2ZW50O2lmKHQpe3ZhciBlPXRoaXMuX21hcC50cmFuc2Zvcm0saT10aGlzLl9wcmV2aW91c1BvcyxuPXRoaXMuX3BvcyxvPS44KihpLngtbi54KSxhPS0uNSooaS55LW4ueSkscz1lLmJlYXJpbmctbyxsPWUucGl0Y2gtYSxjPXRoaXMuX2luZXJ0aWEsdT1jW2MubGVuZ3RoLTFdO3RoaXMuX2RyYWluSW5lcnRpYUJ1ZmZlcigpLGMucHVzaChbci5ub3coKSx0aGlzLl9tYXAuX25vcm1hbGl6ZUJlYXJpbmcocyx1WzFdKV0pLGUuYmVhcmluZz1zLHRoaXMuX3BpdGNoV2l0aFJvdGF0ZSYmKHRoaXMuX2ZpcmVFdmVudChcInBpdGNoXCIsdCksZS5waXRjaD1sKSx0aGlzLl9maXJlRXZlbnQoXCJyb3RhdGVcIix0KSx0aGlzLl9maXJlRXZlbnQoXCJtb3ZlXCIsdCksZGVsZXRlIHRoaXMuX2xhc3RNb3ZlRXZlbnQsdGhpcy5fcHJldmlvdXNQb3M9dGhpcy5fcG9zO319LEhpLnByb3RvdHlwZS5fb25Nb3VzZVVwPWZ1bmN0aW9uKHQpe2lmKHMubW91c2VCdXR0b24odCk9PT10aGlzLl9ldmVudEJ1dHRvbilzd2l0Y2godGhpcy5fc3RhdGUpe2Nhc2VcImFjdGl2ZVwiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHMuc3VwcHJlc3NDbGljaygpLHRoaXMuX3VuYmluZCgpLHRoaXMuX2RlYWN0aXZhdGUoKSx0aGlzLl9pbmVydGlhbFJvdGF0ZSh0KTticmVhaztjYXNlXCJwZW5kaW5nXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsdGhpcy5fdW5iaW5kKCk7fX0sSGkucHJvdG90eXBlLl9vbkJsdXI9ZnVuY3Rpb24odCl7c3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKSx0aGlzLl9kZWFjdGl2YXRlKCksdGhpcy5fZmlyZUV2ZW50KFwicm90YXRlZW5kXCIsdCksdGhpcy5fcGl0Y2hXaXRoUm90YXRlJiZ0aGlzLl9maXJlRXZlbnQoXCJwaXRjaGVuZFwiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVlbmRcIix0KTticmVhaztjYXNlXCJwZW5kaW5nXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsdGhpcy5fdW5iaW5kKCk7fX0sSGkucHJvdG90eXBlLl91bmJpbmQ9ZnVuY3Rpb24oKXt0LmRlZmF1bHQuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNlbW92ZVwiLHRoaXMuX29uTW91c2VNb3ZlLHtjYXB0dXJlOiEwfSksdC5kZWZhdWx0LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwKSx0LmRlZmF1bHQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImJsdXJcIix0aGlzLl9vbkJsdXIpLHMuZW5hYmxlRHJhZygpO30sSGkucHJvdG90eXBlLl9kZWFjdGl2YXRlPWZ1bmN0aW9uKCl7dGhpcy5fZnJhbWVJZCYmKHRoaXMuX21hcC5fY2FuY2VsUmVuZGVyRnJhbWUodGhpcy5fZnJhbWVJZCksdGhpcy5fZnJhbWVJZD1udWxsKSxkZWxldGUgdGhpcy5fbGFzdE1vdmVFdmVudCxkZWxldGUgdGhpcy5fcHJldmlvdXNQb3M7fSxIaS5wcm90b3R5cGUuX2luZXJ0aWFsUm90YXRlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXM7dGhpcy5fZmlyZUV2ZW50KFwicm90YXRlZW5kXCIsdCksdGhpcy5fZHJhaW5JbmVydGlhQnVmZmVyKCk7dmFyIGk9dGhpcy5fbWFwLG49aS5nZXRCZWFyaW5nKCksbz10aGlzLl9pbmVydGlhLHI9ZnVuY3Rpb24oKXtNYXRoLmFicyhuKTxlLl9iZWFyaW5nU25hcD9pLnJlc2V0Tm9ydGgoe25vTW92ZVN0YXJ0OiEwfSx7b3JpZ2luYWxFdmVudDp0fSk6ZS5fZmlyZUV2ZW50KFwibW92ZWVuZFwiLHQpLGUuX3BpdGNoV2l0aFJvdGF0ZSYmZS5fZmlyZUV2ZW50KFwicGl0Y2hlbmRcIix0KTt9O2lmKG8ubGVuZ3RoPDIpcigpO2Vsc2V7dmFyIGE9b1swXSxzPW9bby5sZW5ndGgtMV0sbD1vW28ubGVuZ3RoLTJdLGM9aS5fbm9ybWFsaXplQmVhcmluZyhuLGxbMV0pLHU9c1sxXS1hWzFdLGg9dTwwPy0xOjEscD0oc1swXS1hWzBdKS8xZTM7aWYoMCE9PXUmJjAhPT1wKXt2YXIgZD1NYXRoLmFicyh1KiguMjUvcCkpO2Q+MTgwJiYoZD0xODApO3ZhciBmPWQvMTgwO2MrPWgqZCooZi8yKSxNYXRoLmFicyhpLl9ub3JtYWxpemVCZWFyaW5nKGMsMCkpPHRoaXMuX2JlYXJpbmdTbmFwJiYoYz1pLl9ub3JtYWxpemVCZWFyaW5nKDAsYykpLGkucm90YXRlVG8oYyx7ZHVyYXRpb246MWUzKmYsZWFzaW5nOlhpLG5vTW92ZVN0YXJ0OiEwfSx7b3JpZ2luYWxFdmVudDp0fSk7fWVsc2UgcigpO319LEhpLnByb3RvdHlwZS5fZmlyZUV2ZW50PWZ1bmN0aW9uKGUsaSl7cmV0dXJuIHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KGUsaT97b3JpZ2luYWxFdmVudDppfTp7fSkpfSxIaS5wcm90b3R5cGUuX2RyYWluSW5lcnRpYUJ1ZmZlcj1mdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLl9pbmVydGlhLGU9ci5ub3coKTt0Lmxlbmd0aD4wJiZlLXRbMF1bMF0+MTYwOyl0LnNoaWZ0KCk7fTt2YXIgS2k9dC5iZXppZXIoMCwwLC4zLDEpLFlpPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdGhpcy5fc3RhdGU9XCJkaXNhYmxlZFwiLHQuYmluZEFsbChbXCJfb25Nb3ZlXCIsXCJfb25Nb3VzZVVwXCIsXCJfb25Ub3VjaEVuZFwiLFwiX29uQmx1clwiLFwiX29uRHJhZ0ZyYW1lXCJdLHRoaXMpO307WWkucHJvdG90eXBlLmlzRW5hYmxlZD1mdW5jdGlvbigpe3JldHVyblwiZGlzYWJsZWRcIiE9PXRoaXMuX3N0YXRlfSxZaS5wcm90b3R5cGUuaXNBY3RpdmU9ZnVuY3Rpb24oKXtyZXR1cm5cImFjdGl2ZVwiPT09dGhpcy5fc3RhdGV9LFlpLnByb3RvdHlwZS5lbmFibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpfHwodGhpcy5fZWwuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLXRvdWNoLWRyYWctcGFuXCIpLHRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiKTt9LFlpLnByb3RvdHlwZS5kaXNhYmxlPWZ1bmN0aW9uKCl7aWYodGhpcy5pc0VuYWJsZWQoKSlzd2l0Y2godGhpcy5fZWwuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLXRvdWNoLWRyYWctcGFuXCIpLHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImRpc2FibGVkXCIsdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2ZpcmVFdmVudChcImRyYWdlbmRcIiksdGhpcy5fZmlyZUV2ZW50KFwibW92ZWVuZFwiKTticmVhaztjYXNlXCJwZW5kaW5nXCI6dGhpcy5fc3RhdGU9XCJkaXNhYmxlZFwiLHRoaXMuX3VuYmluZCgpO2JyZWFrO2RlZmF1bHQ6dGhpcy5fc3RhdGU9XCJkaXNhYmxlZFwiO319LFlpLnByb3RvdHlwZS5vbk1vdXNlRG93bj1mdW5jdGlvbihlKXtcImVuYWJsZWRcIj09PXRoaXMuX3N0YXRlJiYoZS5jdHJsS2V5fHwwIT09cy5tb3VzZUJ1dHRvbihlKXx8KHMuYWRkRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQuZG9jdW1lbnQsXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdmUse2NhcHR1cmU6ITB9KSxzLmFkZEV2ZW50TGlzdGVuZXIodC5kZWZhdWx0LmRvY3VtZW50LFwibW91c2V1cFwiLHRoaXMuX29uTW91c2VVcCksdGhpcy5fc3RhcnQoZSkpKTt9LFlpLnByb3RvdHlwZS5vblRvdWNoU3RhcnQ9ZnVuY3Rpb24oZSl7XCJlbmFibGVkXCI9PT10aGlzLl9zdGF0ZSYmKGUudG91Y2hlcy5sZW5ndGg+MXx8KHMuYWRkRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQuZG9jdW1lbnQsXCJ0b3VjaG1vdmVcIix0aGlzLl9vbk1vdmUse2NhcHR1cmU6ITAscGFzc2l2ZTohMX0pLHMuYWRkRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uVG91Y2hFbmQpLHRoaXMuX3N0YXJ0KGUpKSk7fSxZaS5wcm90b3R5cGUuX3N0YXJ0PWZ1bmN0aW9uKGUpe3QuZGVmYXVsdC5hZGRFdmVudExpc3RlbmVyKFwiYmx1clwiLHRoaXMuX29uQmx1ciksdGhpcy5fc3RhdGU9XCJwZW5kaW5nXCIsdGhpcy5fcHJldmlvdXNQb3M9cy5tb3VzZVBvcyh0aGlzLl9lbCxlKSx0aGlzLl9pbmVydGlhPVtbci5ub3coKSx0aGlzLl9wcmV2aW91c1Bvc11dO30sWWkucHJvdG90eXBlLl9vbk1vdmU9ZnVuY3Rpb24odCl7dGhpcy5fbGFzdE1vdmVFdmVudD10LHQucHJldmVudERlZmF1bHQoKSx0aGlzLl9wb3M9cy5tb3VzZVBvcyh0aGlzLl9lbCx0KSx0aGlzLl9kcmFpbkluZXJ0aWFCdWZmZXIoKSx0aGlzLl9pbmVydGlhLnB1c2goW3Iubm93KCksdGhpcy5fcG9zXSksXCJwZW5kaW5nXCI9PT10aGlzLl9zdGF0ZSYmKHRoaXMuX3N0YXRlPVwiYWN0aXZlXCIsdGhpcy5fZmlyZUV2ZW50KFwiZHJhZ3N0YXJ0XCIsdCksdGhpcy5fZmlyZUV2ZW50KFwibW92ZXN0YXJ0XCIsdCkpLHRoaXMuX2ZyYW1lSWR8fCh0aGlzLl9mcmFtZUlkPXRoaXMuX21hcC5fcmVxdWVzdFJlbmRlckZyYW1lKHRoaXMuX29uRHJhZ0ZyYW1lKSk7fSxZaS5wcm90b3R5cGUuX29uRHJhZ0ZyYW1lPWZ1bmN0aW9uKCl7dGhpcy5fZnJhbWVJZD1udWxsO3ZhciB0PXRoaXMuX2xhc3RNb3ZlRXZlbnQ7aWYodCl7dmFyIGU9dGhpcy5fbWFwLnRyYW5zZm9ybTtlLnNldExvY2F0aW9uQXRQb2ludChlLnBvaW50TG9jYXRpb24odGhpcy5fcHJldmlvdXNQb3MpLHRoaXMuX3BvcyksdGhpcy5fZmlyZUV2ZW50KFwiZHJhZ1wiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVcIix0KSx0aGlzLl9wcmV2aW91c1Bvcz10aGlzLl9wb3MsZGVsZXRlIHRoaXMuX2xhc3RNb3ZlRXZlbnQ7fX0sWWkucHJvdG90eXBlLl9vbk1vdXNlVXA9ZnVuY3Rpb24odCl7aWYoMD09PXMubW91c2VCdXR0b24odCkpc3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIixzLnN1cHByZXNzQ2xpY2soKSx0aGlzLl91bmJpbmQoKSx0aGlzLl9kZWFjdGl2YXRlKCksdGhpcy5faW5lcnRpYWxQYW4odCk7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHRoaXMuX3VuYmluZCgpO319LFlpLnByb3RvdHlwZS5fb25Ub3VjaEVuZD1mdW5jdGlvbih0KXtzd2l0Y2godGhpcy5fc3RhdGUpe2Nhc2VcImFjdGl2ZVwiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHRoaXMuX3VuYmluZCgpLHRoaXMuX2RlYWN0aXZhdGUoKSx0aGlzLl9pbmVydGlhbFBhbih0KTticmVhaztjYXNlXCJwZW5kaW5nXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsdGhpcy5fdW5iaW5kKCk7fX0sWWkucHJvdG90eXBlLl9vbkJsdXI9ZnVuY3Rpb24odCl7c3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKSx0aGlzLl9kZWFjdGl2YXRlKCksdGhpcy5fZmlyZUV2ZW50KFwiZHJhZ2VuZFwiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVlbmRcIix0KTticmVhaztjYXNlXCJwZW5kaW5nXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsdGhpcy5fdW5iaW5kKCk7fX0sWWkucHJvdG90eXBlLl91bmJpbmQ9ZnVuY3Rpb24oKXtzLnJlbW92ZUV2ZW50TGlzdGVuZXIodC5kZWZhdWx0LmRvY3VtZW50LFwidG91Y2htb3ZlXCIsdGhpcy5fb25Nb3ZlLHtjYXB0dXJlOiEwLHBhc3NpdmU6ITF9KSxzLnJlbW92ZUV2ZW50TGlzdGVuZXIodC5kZWZhdWx0LmRvY3VtZW50LFwidG91Y2hlbmRcIix0aGlzLl9vblRvdWNoRW5kKSxzLnJlbW92ZUV2ZW50TGlzdGVuZXIodC5kZWZhdWx0LmRvY3VtZW50LFwibW91c2Vtb3ZlXCIsdGhpcy5fb25Nb3ZlLHtjYXB0dXJlOiEwfSkscy5yZW1vdmVFdmVudExpc3RlbmVyKHQuZGVmYXVsdC5kb2N1bWVudCxcIm1vdXNldXBcIix0aGlzLl9vbk1vdXNlVXApLHMucmVtb3ZlRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQsXCJibHVyXCIsdGhpcy5fb25CbHVyKTt9LFlpLnByb3RvdHlwZS5fZGVhY3RpdmF0ZT1mdW5jdGlvbigpe3RoaXMuX2ZyYW1lSWQmJih0aGlzLl9tYXAuX2NhbmNlbFJlbmRlckZyYW1lKHRoaXMuX2ZyYW1lSWQpLHRoaXMuX2ZyYW1lSWQ9bnVsbCksZGVsZXRlIHRoaXMuX2xhc3RNb3ZlRXZlbnQsZGVsZXRlIHRoaXMuX3ByZXZpb3VzUG9zLGRlbGV0ZSB0aGlzLl9wb3M7fSxZaS5wcm90b3R5cGUuX2luZXJ0aWFsUGFuPWZ1bmN0aW9uKHQpe3RoaXMuX2ZpcmVFdmVudChcImRyYWdlbmRcIix0KSx0aGlzLl9kcmFpbkluZXJ0aWFCdWZmZXIoKTt2YXIgZT10aGlzLl9pbmVydGlhO2lmKGUubGVuZ3RoPDIpdGhpcy5fZmlyZUV2ZW50KFwibW92ZWVuZFwiLHQpO2Vsc2V7dmFyIGk9ZVtlLmxlbmd0aC0xXSxuPWVbMF0sbz1pWzFdLnN1YihuWzFdKSxyPShpWzBdLW5bMF0pLzFlMztpZigwPT09cnx8aVsxXS5lcXVhbHMoblsxXSkpdGhpcy5fZmlyZUV2ZW50KFwibW92ZWVuZFwiLHQpO2Vsc2V7dmFyIGE9by5tdWx0KC4zL3IpLHM9YS5tYWcoKTtzPjE0MDAmJihzPTE0MDAsYS5fdW5pdCgpLl9tdWx0KHMpKTt2YXIgbD1zLzc1MCxjPWEubXVsdCgtbC8yKTt0aGlzLl9tYXAucGFuQnkoYyx7ZHVyYXRpb246MWUzKmwsZWFzaW5nOktpLG5vTW92ZVN0YXJ0OiEwfSx7b3JpZ2luYWxFdmVudDp0fSk7fX19LFlpLnByb3RvdHlwZS5fZmlyZUV2ZW50PWZ1bmN0aW9uKGUsaSl7cmV0dXJuIHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KGUsaT97b3JpZ2luYWxFdmVudDppfTp7fSkpfSxZaS5wcm90b3R5cGUuX2RyYWluSW5lcnRpYUJ1ZmZlcj1mdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLl9pbmVydGlhLGU9ci5ub3coKTt0Lmxlbmd0aD4wJiZlLXRbMF1bMF0+MTYwOyl0LnNoaWZ0KCk7fTt2YXIgSmk9ZnVuY3Rpb24oZSl7dGhpcy5fbWFwPWUsdGhpcy5fZWw9ZS5nZXRDYW52YXNDb250YWluZXIoKSx0LmJpbmRBbGwoW1wiX29uS2V5RG93blwiXSx0aGlzKTt9O2Z1bmN0aW9uIFFpKHQpe3JldHVybiB0KigyLXQpfUppLnByb3RvdHlwZS5pc0VuYWJsZWQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX2VuYWJsZWR9LEppLnByb3RvdHlwZS5lbmFibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpfHwodGhpcy5fZWwuYWRkRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIix0aGlzLl9vbktleURvd24sITEpLHRoaXMuX2VuYWJsZWQ9ITApO30sSmkucHJvdG90eXBlLmRpc2FibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpJiYodGhpcy5fZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIix0aGlzLl9vbktleURvd24pLHRoaXMuX2VuYWJsZWQ9ITEpO30sSmkucHJvdG90eXBlLl9vbktleURvd249ZnVuY3Rpb24odCl7aWYoISh0LmFsdEtleXx8dC5jdHJsS2V5fHx0Lm1ldGFLZXkpKXt2YXIgZT0wLGk9MCxuPTAsbz0wLHI9MDtzd2l0Y2godC5rZXlDb2RlKXtjYXNlIDYxOmNhc2UgMTA3OmNhc2UgMTcxOmNhc2UgMTg3OmU9MTticmVhaztjYXNlIDE4OTpjYXNlIDEwOTpjYXNlIDE3MzplPS0xO2JyZWFrO2Nhc2UgMzc6dC5zaGlmdEtleT9pPS0xOih0LnByZXZlbnREZWZhdWx0KCksbz0tMSk7YnJlYWs7Y2FzZSAzOTp0LnNoaWZ0S2V5P2k9MToodC5wcmV2ZW50RGVmYXVsdCgpLG89MSk7YnJlYWs7Y2FzZSAzODp0LnNoaWZ0S2V5P249MToodC5wcmV2ZW50RGVmYXVsdCgpLHI9LTEpO2JyZWFrO2Nhc2UgNDA6dC5zaGlmdEtleT9uPS0xOihyPTEsdC5wcmV2ZW50RGVmYXVsdCgpKTticmVhaztkZWZhdWx0OnJldHVybn12YXIgYT10aGlzLl9tYXAscz1hLmdldFpvb20oKSxsPXtkdXJhdGlvbjozMDAsZGVsYXlFbmRFdmVudHM6NTAwLGVhc2luZzpRaSx6b29tOmU/TWF0aC5yb3VuZChzKStlKih0LnNoaWZ0S2V5PzI6MSk6cyxiZWFyaW5nOmEuZ2V0QmVhcmluZygpKzE1KmkscGl0Y2g6YS5nZXRQaXRjaCgpKzEwKm4sb2Zmc2V0OlsxMDAqLW8sMTAwKi1yXSxjZW50ZXI6YS5nZXRDZW50ZXIoKX07YS5lYXNlVG8obCx7b3JpZ2luYWxFdmVudDp0fSk7fX07dmFyIHRuPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHQuYmluZEFsbChbXCJfb25EYmxDbGlja1wiLFwiX29uWm9vbUVuZFwiXSx0aGlzKTt9O3RuLnByb3RvdHlwZS5pc0VuYWJsZWQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX2VuYWJsZWR9LHRuLnByb3RvdHlwZS5pc0FjdGl2ZT1mdW5jdGlvbigpe3JldHVybiEhdGhpcy5fYWN0aXZlfSx0bi5wcm90b3R5cGUuZW5hYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKXx8KHRoaXMuX2VuYWJsZWQ9ITApO30sdG4ucHJvdG90eXBlLmRpc2FibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpJiYodGhpcy5fZW5hYmxlZD0hMSk7fSx0bi5wcm90b3R5cGUub25Ub3VjaFN0YXJ0PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXM7dGhpcy5pc0VuYWJsZWQoKSYmKHQucG9pbnRzLmxlbmd0aD4xfHwodGhpcy5fdGFwcGVkPyhjbGVhclRpbWVvdXQodGhpcy5fdGFwcGVkKSx0aGlzLl90YXBwZWQ9bnVsbCx0aGlzLl96b29tKHQpKTp0aGlzLl90YXBwZWQ9c2V0VGltZW91dChmdW5jdGlvbigpe2UuX3RhcHBlZD1udWxsO30sMzAwKSkpO30sdG4ucHJvdG90eXBlLm9uRGJsQ2xpY2s9ZnVuY3Rpb24odCl7dGhpcy5pc0VuYWJsZWQoKSYmKHQub3JpZ2luYWxFdmVudC5wcmV2ZW50RGVmYXVsdCgpLHRoaXMuX3pvb20odCkpO30sdG4ucHJvdG90eXBlLl96b29tPWZ1bmN0aW9uKHQpe3RoaXMuX2FjdGl2ZT0hMCx0aGlzLl9tYXAub24oXCJ6b29tZW5kXCIsdGhpcy5fb25ab29tRW5kKSx0aGlzLl9tYXAuem9vbVRvKHRoaXMuX21hcC5nZXRab29tKCkrKHQub3JpZ2luYWxFdmVudC5zaGlmdEtleT8tMToxKSx7YXJvdW5kOnQubG5nTGF0fSx0KTt9LHRuLnByb3RvdHlwZS5fb25ab29tRW5kPWZ1bmN0aW9uKCl7dGhpcy5fYWN0aXZlPSExLHRoaXMuX21hcC5vZmYoXCJ6b29tZW5kXCIsdGhpcy5fb25ab29tRW5kKTt9O3ZhciBlbj10LmJlemllcigwLDAsLjE1LDEpLG5uPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdC5iaW5kQWxsKFtcIl9vbk1vdmVcIixcIl9vbkVuZFwiLFwiX29uVG91Y2hGcmFtZVwiXSx0aGlzKTt9O25uLnByb3RvdHlwZS5pc0VuYWJsZWQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX2VuYWJsZWR9LG5uLnByb3RvdHlwZS5lbmFibGU9ZnVuY3Rpb24odCl7dGhpcy5pc0VuYWJsZWQoKXx8KHRoaXMuX2VsLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC10b3VjaC16b29tLXJvdGF0ZVwiKSx0aGlzLl9lbmFibGVkPSEwLHRoaXMuX2Fyb3VuZENlbnRlcj0hIXQmJlwiY2VudGVyXCI9PT10LmFyb3VuZCk7fSxubi5wcm90b3R5cGUuZGlzYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCkmJih0aGlzLl9lbC5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtdG91Y2gtem9vbS1yb3RhdGVcIiksdGhpcy5fZW5hYmxlZD0hMSk7fSxubi5wcm90b3R5cGUuZGlzYWJsZVJvdGF0aW9uPWZ1bmN0aW9uKCl7dGhpcy5fcm90YXRpb25EaXNhYmxlZD0hMDt9LG5uLnByb3RvdHlwZS5lbmFibGVSb3RhdGlvbj1mdW5jdGlvbigpe3RoaXMuX3JvdGF0aW9uRGlzYWJsZWQ9ITE7fSxubi5wcm90b3R5cGUub25TdGFydD1mdW5jdGlvbihlKXtpZih0aGlzLmlzRW5hYmxlZCgpJiYyPT09ZS50b3VjaGVzLmxlbmd0aCl7dmFyIGk9cy5tb3VzZVBvcyh0aGlzLl9lbCxlLnRvdWNoZXNbMF0pLG49cy5tb3VzZVBvcyh0aGlzLl9lbCxlLnRvdWNoZXNbMV0pO3RoaXMuX3N0YXJ0VmVjPWkuc3ViKG4pLHRoaXMuX2dlc3R1cmVJbnRlbnQ9dm9pZCAwLHRoaXMuX2luZXJ0aWE9W10scy5hZGRFdmVudExpc3RlbmVyKHQuZGVmYXVsdC5kb2N1bWVudCxcInRvdWNobW92ZVwiLHRoaXMuX29uTW92ZSx7cGFzc2l2ZTohMX0pLHMuYWRkRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uRW5kKTt9fSxubi5wcm90b3R5cGUuX2dldFRvdWNoRXZlbnREYXRhPWZ1bmN0aW9uKHQpe3ZhciBlPXMubW91c2VQb3ModGhpcy5fZWwsdC50b3VjaGVzWzBdKSxpPXMubW91c2VQb3ModGhpcy5fZWwsdC50b3VjaGVzWzFdKSxuPWUuc3ViKGkpO3JldHVybnt2ZWM6bixjZW50ZXI6ZS5hZGQoaSkuZGl2KDIpLHNjYWxlOm4ubWFnKCkvdGhpcy5fc3RhcnRWZWMubWFnKCksYmVhcmluZzp0aGlzLl9yb3RhdGlvbkRpc2FibGVkPzA6MTgwKm4uYW5nbGVXaXRoKHRoaXMuX3N0YXJ0VmVjKS9NYXRoLlBJfX0sbm4ucHJvdG90eXBlLl9vbk1vdmU9ZnVuY3Rpb24oZSl7aWYoMj09PWUudG91Y2hlcy5sZW5ndGgpe3ZhciBpPXRoaXMuX2dldFRvdWNoRXZlbnREYXRhKGUpLG49aS52ZWMsbz1pLnNjYWxlLHI9aS5iZWFyaW5nO2lmKCF0aGlzLl9nZXN0dXJlSW50ZW50KXt2YXIgYT1NYXRoLmFicygxLW8pPi4xNTtNYXRoLmFicyhyKT4xMD90aGlzLl9nZXN0dXJlSW50ZW50PVwicm90YXRlXCI6YSYmKHRoaXMuX2dlc3R1cmVJbnRlbnQ9XCJ6b29tXCIpLHRoaXMuX2dlc3R1cmVJbnRlbnQmJih0aGlzLl9tYXAuZmlyZShuZXcgdC5FdmVudCh0aGlzLl9nZXN0dXJlSW50ZW50K1wic3RhcnRcIix7b3JpZ2luYWxFdmVudDplfSkpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwibW92ZXN0YXJ0XCIse29yaWdpbmFsRXZlbnQ6ZX0pKSx0aGlzLl9zdGFydFZlYz1uKTt9dGhpcy5fbGFzdFRvdWNoRXZlbnQ9ZSx0aGlzLl9mcmFtZUlkfHwodGhpcy5fZnJhbWVJZD10aGlzLl9tYXAuX3JlcXVlc3RSZW5kZXJGcmFtZSh0aGlzLl9vblRvdWNoRnJhbWUpKSxlLnByZXZlbnREZWZhdWx0KCk7fX0sbm4ucHJvdG90eXBlLl9vblRvdWNoRnJhbWU9ZnVuY3Rpb24oKXt0aGlzLl9mcmFtZUlkPW51bGw7dmFyIGU9dGhpcy5fZ2VzdHVyZUludGVudDtpZihlKXt2YXIgaT10aGlzLl9tYXAudHJhbnNmb3JtO3RoaXMuX3N0YXJ0U2NhbGV8fCh0aGlzLl9zdGFydFNjYWxlPWkuc2NhbGUsdGhpcy5fc3RhcnRCZWFyaW5nPWkuYmVhcmluZyk7dmFyIG49dGhpcy5fZ2V0VG91Y2hFdmVudERhdGEodGhpcy5fbGFzdFRvdWNoRXZlbnQpLG89bi5jZW50ZXIsYT1uLmJlYXJpbmcscz1uLnNjYWxlLGw9aS5wb2ludExvY2F0aW9uKG8pLGM9aS5sb2NhdGlvblBvaW50KGwpO1wicm90YXRlXCI9PT1lJiYoaS5iZWFyaW5nPXRoaXMuX3N0YXJ0QmVhcmluZythKSxpLnpvb209aS5zY2FsZVpvb20odGhpcy5fc3RhcnRTY2FsZSpzKSxpLnNldExvY2F0aW9uQXRQb2ludChsLGMpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KGUse29yaWdpbmFsRXZlbnQ6dGhpcy5fbGFzdFRvdWNoRXZlbnR9KSksdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlXCIse29yaWdpbmFsRXZlbnQ6dGhpcy5fbGFzdFRvdWNoRXZlbnR9KSksdGhpcy5fZHJhaW5JbmVydGlhQnVmZmVyKCksdGhpcy5faW5lcnRpYS5wdXNoKFtyLm5vdygpLHMsb10pO319LG5uLnByb3RvdHlwZS5fb25FbmQ9ZnVuY3Rpb24oZSl7cy5yZW1vdmVFdmVudExpc3RlbmVyKHQuZGVmYXVsdC5kb2N1bWVudCxcInRvdWNobW92ZVwiLHRoaXMuX29uTW92ZSx7cGFzc2l2ZTohMX0pLHMucmVtb3ZlRXZlbnRMaXN0ZW5lcih0LmRlZmF1bHQuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uRW5kKTt2YXIgaT10aGlzLl9nZXN0dXJlSW50ZW50LG49dGhpcy5fc3RhcnRTY2FsZTtpZih0aGlzLl9mcmFtZUlkJiYodGhpcy5fbWFwLl9jYW5jZWxSZW5kZXJGcmFtZSh0aGlzLl9mcmFtZUlkKSx0aGlzLl9mcmFtZUlkPW51bGwpLGRlbGV0ZSB0aGlzLl9nZXN0dXJlSW50ZW50LGRlbGV0ZSB0aGlzLl9zdGFydFNjYWxlLGRlbGV0ZSB0aGlzLl9zdGFydEJlYXJpbmcsZGVsZXRlIHRoaXMuX2xhc3RUb3VjaEV2ZW50LGkpe3RoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KGkrXCJlbmRcIix7b3JpZ2luYWxFdmVudDplfSkpLHRoaXMuX2RyYWluSW5lcnRpYUJ1ZmZlcigpO3ZhciBvPXRoaXMuX2luZXJ0aWEscj10aGlzLl9tYXA7aWYoby5sZW5ndGg8MilyLnNuYXBUb05vcnRoKHt9LHtvcmlnaW5hbEV2ZW50OmV9KTtlbHNle3ZhciBhPW9bby5sZW5ndGgtMV0sbD1vWzBdLGM9ci50cmFuc2Zvcm0uc2NhbGVab29tKG4qYVsxXSksdT1yLnRyYW5zZm9ybS5zY2FsZVpvb20obipsWzFdKSxoPWMtdSxwPShhWzBdLWxbMF0pLzFlMyxkPWFbMl07aWYoMCE9PXAmJmMhPT11KXt2YXIgZj0uMTUqaC9wO01hdGguYWJzKGYpPjIuNSYmKGY9Zj4wPzIuNTotMi41KTt2YXIgbT0xZTMqTWF0aC5hYnMoZi8oMTIqLjE1KSksXz1jK2YqbS8yZTM7XzwwJiYoXz0wKSxyLmVhc2VUbyh7em9vbTpfLGR1cmF0aW9uOm0sZWFzaW5nOmVuLGFyb3VuZDp0aGlzLl9hcm91bmRDZW50ZXI/ci5nZXRDZW50ZXIoKTpyLnVucHJvamVjdChkKSxub01vdmVTdGFydDohMH0se29yaWdpbmFsRXZlbnQ6ZX0pO31lbHNlIHIuc25hcFRvTm9ydGgoe30se29yaWdpbmFsRXZlbnQ6ZX0pO319fSxubi5wcm90b3R5cGUuX2RyYWluSW5lcnRpYUJ1ZmZlcj1mdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLl9pbmVydGlhLGU9ci5ub3coKTt0Lmxlbmd0aD4yJiZlLXRbMF1bMF0+MTYwOyl0LnNoaWZ0KCk7fTt2YXIgb249e3Njcm9sbFpvb206V2ksYm94Wm9vbTpxaSxkcmFnUm90YXRlOkhpLGRyYWdQYW46WWksa2V5Ym9hcmQ6SmksZG91YmxlQ2xpY2tab29tOnRuLHRvdWNoWm9vbVJvdGF0ZTpubn07dmFyIHJuPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoaSxuKXtlLmNhbGwodGhpcyksdGhpcy5fbW92aW5nPSExLHRoaXMuX3pvb21pbmc9ITEsdGhpcy50cmFuc2Zvcm09aSx0aGlzLl9iZWFyaW5nU25hcD1uLmJlYXJpbmdTbmFwLHQuYmluZEFsbChbXCJfcmVuZGVyRnJhbWVDYWxsYmFja1wiXSx0aGlzKTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmdldENlbnRlcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5jZW50ZXJ9LGkucHJvdG90eXBlLnNldENlbnRlcj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmp1bXBUbyh7Y2VudGVyOnR9LGUpfSxpLnByb3RvdHlwZS5wYW5CeT1mdW5jdGlvbihlLGksbil7cmV0dXJuIGU9dC5kZWZhdWx0JDEuY29udmVydChlKS5tdWx0KC0xKSx0aGlzLnBhblRvKHRoaXMudHJhbnNmb3JtLmNlbnRlcix0LmV4dGVuZCh7b2Zmc2V0OmV9LGkpLG4pfSxpLnByb3RvdHlwZS5wYW5Ubz1mdW5jdGlvbihlLGksbil7cmV0dXJuIHRoaXMuZWFzZVRvKHQuZXh0ZW5kKHtjZW50ZXI6ZX0saSksbil9LGkucHJvdG90eXBlLmdldFpvb209ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0uem9vbX0saS5wcm90b3R5cGUuc2V0Wm9vbT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmp1bXBUbyh7em9vbTp0fSxlKSx0aGlzfSxpLnByb3RvdHlwZS56b29tVG89ZnVuY3Rpb24oZSxpLG4pe3JldHVybiB0aGlzLmVhc2VUbyh0LmV4dGVuZCh7em9vbTplfSxpKSxuKX0saS5wcm90b3R5cGUuem9vbUluPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuem9vbVRvKHRoaXMuZ2V0Wm9vbSgpKzEsdCxlKSx0aGlzfSxpLnByb3RvdHlwZS56b29tT3V0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuem9vbVRvKHRoaXMuZ2V0Wm9vbSgpLTEsdCxlKSx0aGlzfSxpLnByb3RvdHlwZS5nZXRCZWFyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLmJlYXJpbmd9LGkucHJvdG90eXBlLnNldEJlYXJpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5qdW1wVG8oe2JlYXJpbmc6dH0sZSksdGhpc30saS5wcm90b3R5cGUucm90YXRlVG89ZnVuY3Rpb24oZSxpLG4pe3JldHVybiB0aGlzLmVhc2VUbyh0LmV4dGVuZCh7YmVhcmluZzplfSxpKSxuKX0saS5wcm90b3R5cGUucmVzZXROb3J0aD1mdW5jdGlvbihlLGkpe3JldHVybiB0aGlzLnJvdGF0ZVRvKDAsdC5leHRlbmQoe2R1cmF0aW9uOjFlM30sZSksaSksdGhpc30saS5wcm90b3R5cGUuc25hcFRvTm9ydGg9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5hYnModGhpcy5nZXRCZWFyaW5nKCkpPHRoaXMuX2JlYXJpbmdTbmFwP3RoaXMucmVzZXROb3J0aCh0LGUpOnRoaXN9LGkucHJvdG90eXBlLmdldFBpdGNoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLnBpdGNofSxpLnByb3RvdHlwZS5zZXRQaXRjaD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmp1bXBUbyh7cGl0Y2g6dH0sZSksdGhpc30saS5wcm90b3R5cGUuZml0Qm91bmRzPWZ1bmN0aW9uKGUsaSxuKXtpZihcIm51bWJlclwiPT10eXBlb2YoaT10LmV4dGVuZCh7cGFkZGluZzp7dG9wOjAsYm90dG9tOjAscmlnaHQ6MCxsZWZ0OjB9LG9mZnNldDpbMCwwXSxtYXhab29tOnRoaXMudHJhbnNmb3JtLm1heFpvb219LGkpKS5wYWRkaW5nKXt2YXIgbz1pLnBhZGRpbmc7aS5wYWRkaW5nPXt0b3A6byxib3R0b206byxyaWdodDpvLGxlZnQ6b307fWlmKCF0LmRlZmF1bHQkMTAoT2JqZWN0LmtleXMoaS5wYWRkaW5nKS5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ8ZT8tMTp0PmU/MTowfSksW1wiYm90dG9tXCIsXCJsZWZ0XCIsXCJyaWdodFwiLFwidG9wXCJdKSlyZXR1cm4gdC53YXJuT25jZShcIm9wdGlvbnMucGFkZGluZyBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyLCBvciBhbiBPYmplY3Qgd2l0aCBrZXlzICdib3R0b20nLCAnbGVmdCcsICdyaWdodCcsICd0b3AnXCIpLHRoaXM7ZT1xLmNvbnZlcnQoZSk7dmFyIHI9WyhpLnBhZGRpbmcubGVmdC1pLnBhZGRpbmcucmlnaHQpLzIsKGkucGFkZGluZy50b3AtaS5wYWRkaW5nLmJvdHRvbSkvMl0sYT1NYXRoLm1pbihpLnBhZGRpbmcucmlnaHQsaS5wYWRkaW5nLmxlZnQpLHM9TWF0aC5taW4oaS5wYWRkaW5nLnRvcCxpLnBhZGRpbmcuYm90dG9tKTtpLm9mZnNldD1baS5vZmZzZXRbMF0rclswXSxpLm9mZnNldFsxXStyWzFdXTt2YXIgbD10LmRlZmF1bHQkMS5jb252ZXJ0KGkub2Zmc2V0KSxjPXRoaXMudHJhbnNmb3JtLHU9Yy5wcm9qZWN0KGUuZ2V0Tm9ydGhXZXN0KCkpLGg9Yy5wcm9qZWN0KGUuZ2V0U291dGhFYXN0KCkpLHA9aC5zdWIodSksZD0oYy53aWR0aC0yKmEtMipNYXRoLmFicyhsLngpKS9wLngsZj0oYy5oZWlnaHQtMipzLTIqTWF0aC5hYnMobC55KSkvcC55O3JldHVybiBmPDB8fGQ8MD8odC53YXJuT25jZShcIk1hcCBjYW5ub3QgZml0IHdpdGhpbiBjYW52YXMgd2l0aCB0aGUgZ2l2ZW4gYm91bmRzLCBwYWRkaW5nLCBhbmQvb3Igb2Zmc2V0LlwiKSx0aGlzKTooaS5jZW50ZXI9Yy51bnByb2plY3QodS5hZGQoaCkuZGl2KDIpKSxpLnpvb209TWF0aC5taW4oYy5zY2FsZVpvb20oYy5zY2FsZSpNYXRoLm1pbihkLGYpKSxpLm1heFpvb20pLGkuYmVhcmluZz0wLGkubGluZWFyP3RoaXMuZWFzZVRvKGksbik6dGhpcy5mbHlUbyhpLG4pKX0saS5wcm90b3R5cGUuanVtcFRvPWZ1bmN0aW9uKGUsaSl7dGhpcy5zdG9wKCk7dmFyIG49dGhpcy50cmFuc2Zvcm0sbz0hMSxyPSExLGE9ITE7cmV0dXJuXCJ6b29tXCJpbiBlJiZuLnpvb20hPT0rZS56b29tJiYobz0hMCxuLnpvb209K2Uuem9vbSksdm9pZCAwIT09ZS5jZW50ZXImJihuLmNlbnRlcj1XLmNvbnZlcnQoZS5jZW50ZXIpKSxcImJlYXJpbmdcImluIGUmJm4uYmVhcmluZyE9PStlLmJlYXJpbmcmJihyPSEwLG4uYmVhcmluZz0rZS5iZWFyaW5nKSxcInBpdGNoXCJpbiBlJiZuLnBpdGNoIT09K2UucGl0Y2gmJihhPSEwLG4ucGl0Y2g9K2UucGl0Y2gpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIm1vdmVzdGFydFwiLGkpKS5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLGkpKSxvJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInpvb21cIixpKSkuZmlyZShuZXcgdC5FdmVudChcInpvb21lbmRcIixpKSksciYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInJvdGF0ZVwiLGkpKS5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlZW5kXCIsaSkpLGEmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInBpdGNoc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInBpdGNoXCIsaSkpLmZpcmUobmV3IHQuRXZlbnQoXCJwaXRjaGVuZFwiLGkpKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlZW5kXCIsaSkpfSxpLnByb3RvdHlwZS5lYXNlVG89ZnVuY3Rpb24oZSxpKXt2YXIgbj10aGlzO3RoaXMuc3RvcCgpLCExPT09KGU9dC5leHRlbmQoe29mZnNldDpbMCwwXSxkdXJhdGlvbjo1MDAsZWFzaW5nOnQuZWFzZX0sZSkpLmFuaW1hdGUmJihlLmR1cmF0aW9uPTApO3ZhciBvPXRoaXMudHJhbnNmb3JtLHI9dGhpcy5nZXRab29tKCksYT10aGlzLmdldEJlYXJpbmcoKSxzPXRoaXMuZ2V0UGl0Y2goKSxsPVwiem9vbVwiaW4gZT8rZS56b29tOnIsYz1cImJlYXJpbmdcImluIGU/dGhpcy5fbm9ybWFsaXplQmVhcmluZyhlLmJlYXJpbmcsYSk6YSx1PVwicGl0Y2hcImluIGU/K2UucGl0Y2g6cyxoPW8uY2VudGVyUG9pbnQuYWRkKHQuZGVmYXVsdCQxLmNvbnZlcnQoZS5vZmZzZXQpKSxwPW8ucG9pbnRMb2NhdGlvbihoKSxkPVcuY29udmVydChlLmNlbnRlcnx8cCk7dGhpcy5fbm9ybWFsaXplQ2VudGVyKGQpO3ZhciBmLG0sXz1vLnByb2plY3QocCksZz1vLnByb2plY3QoZCkuc3ViKF8pLHY9by56b29tU2NhbGUobC1yKTtyZXR1cm4gZS5hcm91bmQmJihmPVcuY29udmVydChlLmFyb3VuZCksbT1vLmxvY2F0aW9uUG9pbnQoZikpLHRoaXMuX3pvb21pbmc9bCE9PXIsdGhpcy5fcm90YXRpbmc9YSE9PWMsdGhpcy5fcGl0Y2hpbmc9dSE9PXMsdGhpcy5fcHJlcGFyZUVhc2UoaSxlLm5vTW92ZVN0YXJ0KSxjbGVhclRpbWVvdXQodGhpcy5fZWFzZUVuZFRpbWVvdXRJRCksdGhpcy5fZWFzZShmdW5jdGlvbihlKXtpZihuLl96b29taW5nJiYoby56b29tPXQubnVtYmVyKHIsbCxlKSksbi5fcm90YXRpbmcmJihvLmJlYXJpbmc9dC5udW1iZXIoYSxjLGUpKSxuLl9waXRjaGluZyYmKG8ucGl0Y2g9dC5udW1iZXIocyx1LGUpKSxmKW8uc2V0TG9jYXRpb25BdFBvaW50KGYsbSk7ZWxzZXt2YXIgcD1vLnpvb21TY2FsZShvLnpvb20tciksZD1sPnI/TWF0aC5taW4oMix2KTpNYXRoLm1heCguNSx2KSx5PU1hdGgucG93KGQsMS1lKSx4PW8udW5wcm9qZWN0KF8uYWRkKGcubXVsdChlKnkpKS5tdWx0KHApKTtvLnNldExvY2F0aW9uQXRQb2ludChvLnJlbmRlcldvcmxkQ29waWVzP3gud3JhcCgpOngsaCk7fW4uX2ZpcmVNb3ZlRXZlbnRzKGkpO30sZnVuY3Rpb24oKXtlLmRlbGF5RW5kRXZlbnRzP24uX2Vhc2VFbmRUaW1lb3V0SUQ9c2V0VGltZW91dChmdW5jdGlvbigpe3JldHVybiBuLl9hZnRlckVhc2UoaSl9LGUuZGVsYXlFbmRFdmVudHMpOm4uX2FmdGVyRWFzZShpKTt9LGUpLHRoaXN9LGkucHJvdG90eXBlLl9wcmVwYXJlRWFzZT1mdW5jdGlvbihlLGkpe3RoaXMuX21vdmluZz0hMCxpfHx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3Zlc3RhcnRcIixlKSksdGhpcy5fem9vbWluZyYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiem9vbXN0YXJ0XCIsZSkpLHRoaXMuX3JvdGF0aW5nJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJyb3RhdGVzdGFydFwiLGUpKSx0aGlzLl9waXRjaGluZyYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicGl0Y2hzdGFydFwiLGUpKTt9LGkucHJvdG90eXBlLl9maXJlTW92ZUV2ZW50cz1mdW5jdGlvbihlKXt0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlXCIsZSkpLHRoaXMuX3pvb21pbmcmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInpvb21cIixlKSksdGhpcy5fcm90YXRpbmcmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInJvdGF0ZVwiLGUpKSx0aGlzLl9waXRjaGluZyYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicGl0Y2hcIixlKSk7fSxpLnByb3RvdHlwZS5fYWZ0ZXJFYXNlPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuX3pvb21pbmcsbj10aGlzLl9yb3RhdGluZyxvPXRoaXMuX3BpdGNoaW5nO3RoaXMuX21vdmluZz0hMSx0aGlzLl96b29taW5nPSExLHRoaXMuX3JvdGF0aW5nPSExLHRoaXMuX3BpdGNoaW5nPSExLGkmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInpvb21lbmRcIixlKSksbiYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlZW5kXCIsZSkpLG8mJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInBpdGNoZW5kXCIsZSkpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIm1vdmVlbmRcIixlKSk7fSxpLnByb3RvdHlwZS5mbHlUbz1mdW5jdGlvbihlLGkpe3ZhciBuPXRoaXM7dGhpcy5zdG9wKCksZT10LmV4dGVuZCh7b2Zmc2V0OlswLDBdLHNwZWVkOjEuMixjdXJ2ZToxLjQyLGVhc2luZzp0LmVhc2V9LGUpO3ZhciBvPXRoaXMudHJhbnNmb3JtLHI9dGhpcy5nZXRab29tKCksYT10aGlzLmdldEJlYXJpbmcoKSxzPXRoaXMuZ2V0UGl0Y2goKSxsPVwiem9vbVwiaW4gZT90LmNsYW1wKCtlLnpvb20sby5taW5ab29tLG8ubWF4Wm9vbSk6cixjPVwiYmVhcmluZ1wiaW4gZT90aGlzLl9ub3JtYWxpemVCZWFyaW5nKGUuYmVhcmluZyxhKTphLHU9XCJwaXRjaFwiaW4gZT8rZS5waXRjaDpzLGg9by56b29tU2NhbGUobC1yKSxwPW8uY2VudGVyUG9pbnQuYWRkKHQuZGVmYXVsdCQxLmNvbnZlcnQoZS5vZmZzZXQpKSxkPW8ucG9pbnRMb2NhdGlvbihwKSxmPVcuY29udmVydChlLmNlbnRlcnx8ZCk7dGhpcy5fbm9ybWFsaXplQ2VudGVyKGYpO3ZhciBtPW8ucHJvamVjdChkKSxfPW8ucHJvamVjdChmKS5zdWIobSksZz1lLmN1cnZlLHY9TWF0aC5tYXgoby53aWR0aCxvLmhlaWdodCkseT12L2gseD1fLm1hZygpO2lmKFwibWluWm9vbVwiaW4gZSl7dmFyIGI9dC5jbGFtcChNYXRoLm1pbihlLm1pblpvb20scixsKSxvLm1pblpvb20sby5tYXhab29tKSx3PXYvby56b29tU2NhbGUoYi1yKTtnPU1hdGguc3FydCh3L3gqMik7fXZhciBFPWcqZztmdW5jdGlvbiBUKHQpe3ZhciBlPSh5Knktdip2Kyh0Py0xOjEpKkUqRSp4KngpLygyKih0P3k6dikqRSp4KTtyZXR1cm4gTWF0aC5sb2coTWF0aC5zcXJ0KGUqZSsxKS1lKX1mdW5jdGlvbiBJKHQpe3JldHVybihNYXRoLmV4cCh0KS1NYXRoLmV4cCgtdCkpLzJ9ZnVuY3Rpb24gQyh0KXtyZXR1cm4oTWF0aC5leHAodCkrTWF0aC5leHAoLXQpKS8yfXZhciBTPVQoMCksej1mdW5jdGlvbih0KXtyZXR1cm4gQyhTKS9DKFMrZyp0KX0sQT1mdW5jdGlvbih0KXtyZXR1cm4gdiooKEMoUykqKEkoZT1TK2cqdCkvQyhlKSktSShTKSkvRSkveDt2YXIgZTt9LFI9KFQoMSktUykvZztpZihNYXRoLmFicyh4KTwxZS02fHwhaXNGaW5pdGUoUikpe2lmKE1hdGguYWJzKHYteSk8MWUtNilyZXR1cm4gdGhpcy5lYXNlVG8oZSxpKTt2YXIgRD15PHY/LTE6MTtSPU1hdGguYWJzKE1hdGgubG9nKHkvdikpL2csQT1mdW5jdGlvbigpe3JldHVybiAwfSx6PWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmV4cChEKmcqdCl9O31pZihcImR1cmF0aW9uXCJpbiBlKWUuZHVyYXRpb249K2UuZHVyYXRpb247ZWxzZXt2YXIgTT1cInNjcmVlblNwZWVkXCJpbiBlPytlLnNjcmVlblNwZWVkL2c6K2Uuc3BlZWQ7ZS5kdXJhdGlvbj0xZTMqUi9NO31yZXR1cm4gZS5tYXhEdXJhdGlvbiYmZS5kdXJhdGlvbj5lLm1heER1cmF0aW9uJiYoZS5kdXJhdGlvbj0wKSx0aGlzLl96b29taW5nPSEwLHRoaXMuX3JvdGF0aW5nPWEhPT1jLHRoaXMuX3BpdGNoaW5nPXUhPT1zLHRoaXMuX3ByZXBhcmVFYXNlKGksITEpLHRoaXMuX2Vhc2UoZnVuY3Rpb24oZSl7dmFyIGw9ZSpSLGg9MS96KGwpO28uem9vbT1yK28uc2NhbGVab29tKGgpLG4uX3JvdGF0aW5nJiYoby5iZWFyaW5nPXQubnVtYmVyKGEsYyxlKSksbi5fcGl0Y2hpbmcmJihvLnBpdGNoPXQubnVtYmVyKHMsdSxlKSk7dmFyIGQ9by51bnByb2plY3QobS5hZGQoXy5tdWx0KEEobCkpKS5tdWx0KGgpKTtvLnNldExvY2F0aW9uQXRQb2ludChvLnJlbmRlcldvcmxkQ29waWVzP2Qud3JhcCgpOmQscCksbi5fZmlyZU1vdmVFdmVudHMoaSk7fSxmdW5jdGlvbigpe3JldHVybiBuLl9hZnRlckVhc2UoaSl9LGUpLHRoaXN9LGkucHJvdG90eXBlLmlzRWFzaW5nPWZ1bmN0aW9uKCl7cmV0dXJuISF0aGlzLl9lYXNlRnJhbWVJZH0saS5wcm90b3R5cGUuc3RvcD1mdW5jdGlvbigpe2lmKHRoaXMuX2Vhc2VGcmFtZUlkJiYodGhpcy5fY2FuY2VsUmVuZGVyRnJhbWUodGhpcy5fZWFzZUZyYW1lSWQpLGRlbGV0ZSB0aGlzLl9lYXNlRnJhbWVJZCxkZWxldGUgdGhpcy5fb25FYXNlRnJhbWUpLHRoaXMuX29uRWFzZUVuZCl7dmFyIHQ9dGhpcy5fb25FYXNlRW5kO2RlbGV0ZSB0aGlzLl9vbkVhc2VFbmQsdC5jYWxsKHRoaXMpO31yZXR1cm4gdGhpc30saS5wcm90b3R5cGUuX2Vhc2U9ZnVuY3Rpb24odCxlLGkpeyExPT09aS5hbmltYXRlfHwwPT09aS5kdXJhdGlvbj8odCgxKSxlKCkpOih0aGlzLl9lYXNlU3RhcnQ9ci5ub3coKSx0aGlzLl9lYXNlT3B0aW9ucz1pLHRoaXMuX29uRWFzZUZyYW1lPXQsdGhpcy5fb25FYXNlRW5kPWUsdGhpcy5fZWFzZUZyYW1lSWQ9dGhpcy5fcmVxdWVzdFJlbmRlckZyYW1lKHRoaXMuX3JlbmRlckZyYW1lQ2FsbGJhY2spKTt9LGkucHJvdG90eXBlLl9yZW5kZXJGcmFtZUNhbGxiYWNrPWZ1bmN0aW9uKCl7dmFyIHQ9TWF0aC5taW4oKHIubm93KCktdGhpcy5fZWFzZVN0YXJ0KS90aGlzLl9lYXNlT3B0aW9ucy5kdXJhdGlvbiwxKTt0aGlzLl9vbkVhc2VGcmFtZSh0aGlzLl9lYXNlT3B0aW9ucy5lYXNpbmcodCkpLHQ8MT90aGlzLl9lYXNlRnJhbWVJZD10aGlzLl9yZXF1ZXN0UmVuZGVyRnJhbWUodGhpcy5fcmVuZGVyRnJhbWVDYWxsYmFjayk6dGhpcy5zdG9wKCk7fSxpLnByb3RvdHlwZS5fbm9ybWFsaXplQmVhcmluZz1mdW5jdGlvbihlLGkpe2U9dC53cmFwKGUsLTE4MCwxODApO3ZhciBuPU1hdGguYWJzKGUtaSk7cmV0dXJuIE1hdGguYWJzKGUtMzYwLWkpPG4mJihlLT0zNjApLE1hdGguYWJzKGUrMzYwLWkpPG4mJihlKz0zNjApLGV9LGkucHJvdG90eXBlLl9ub3JtYWxpemVDZW50ZXI9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy50cmFuc2Zvcm07aWYoZS5yZW5kZXJXb3JsZENvcGllcyYmIWUubG5nUmFuZ2Upe3ZhciBpPXQubG5nLWUuY2VudGVyLmxuZzt0LmxuZys9aT4xODA/LTM2MDppPC0xODA/MzYwOjA7fX0saX0odC5FdmVudGVkKSxhbj1mdW5jdGlvbihlKXt2b2lkIDA9PT1lJiYoZT17fSksdGhpcy5vcHRpb25zPWUsdC5iaW5kQWxsKFtcIl91cGRhdGVFZGl0TGlua1wiLFwiX3VwZGF0ZURhdGFcIixcIl91cGRhdGVDb21wYWN0XCJdLHRoaXMpO307YW4ucHJvdG90eXBlLmdldERlZmF1bHRQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVyblwiYm90dG9tLXJpZ2h0XCJ9LGFuLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLm9wdGlvbnMmJnRoaXMub3B0aW9ucy5jb21wYWN0O3JldHVybiB0aGlzLl9tYXA9dCx0aGlzLl9jb250YWluZXI9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWN0cmwgbWFwYm94Z2wtY3RybC1hdHRyaWJcIiksZSYmdGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jb21wYWN0XCIpLHRoaXMuX3VwZGF0ZUF0dHJpYnV0aW9ucygpLHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCksdGhpcy5fbWFwLm9uKFwic291cmNlZGF0YVwiLHRoaXMuX3VwZGF0ZURhdGEpLHRoaXMuX21hcC5vbihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGVFZGl0TGluayksdm9pZCAwPT09ZSYmKHRoaXMuX21hcC5vbihcInJlc2l6ZVwiLHRoaXMuX3VwZGF0ZUNvbXBhY3QpLHRoaXMuX3VwZGF0ZUNvbXBhY3QoKSksdGhpcy5fY29udGFpbmVyfSxhbi5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXtzLnJlbW92ZSh0aGlzLl9jb250YWluZXIpLHRoaXMuX21hcC5vZmYoXCJzb3VyY2VkYXRhXCIsdGhpcy5fdXBkYXRlRGF0YSksdGhpcy5fbWFwLm9mZihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGVFZGl0TGluayksdGhpcy5fbWFwLm9mZihcInJlc2l6ZVwiLHRoaXMuX3VwZGF0ZUNvbXBhY3QpLHRoaXMuX21hcD12b2lkIDA7fSxhbi5wcm90b3R5cGUuX3VwZGF0ZUVkaXRMaW5rPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fZWRpdExpbms7dHx8KHQ9dGhpcy5fZWRpdExpbms9dGhpcy5fY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoXCIubWFwYm94LWltcHJvdmUtbWFwXCIpKTt2YXIgZT1be2tleTpcIm93bmVyXCIsdmFsdWU6dGhpcy5zdHlsZU93bmVyfSx7a2V5OlwiaWRcIix2YWx1ZTp0aGlzLnN0eWxlSWR9LHtrZXk6XCJhY2Nlc3NfdG9rZW5cIix2YWx1ZTpfLkFDQ0VTU19UT0tFTn1dO2lmKHQpe3ZhciBpPWUucmVkdWNlKGZ1bmN0aW9uKHQsaSxuKXtyZXR1cm4gaS52YWx1ZSYmKHQrPWkua2V5K1wiPVwiK2kudmFsdWUrKG48ZS5sZW5ndGgtMT9cIiZcIjpcIlwiKSksdH0sXCI/XCIpO3QuaHJlZj1cImh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZmVlZGJhY2svXCIraSsodGhpcy5fbWFwLl9oYXNoP3RoaXMuX21hcC5faGFzaC5nZXRIYXNoU3RyaW5nKCEwKTpcIlwiKTt9fSxhbi5wcm90b3R5cGUuX3VwZGF0ZURhdGE9ZnVuY3Rpb24odCl7dCYmXCJtZXRhZGF0YVwiPT09dC5zb3VyY2VEYXRhVHlwZSYmKHRoaXMuX3VwZGF0ZUF0dHJpYnV0aW9ucygpLHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCkpO30sYW4ucHJvdG90eXBlLl91cGRhdGVBdHRyaWJ1dGlvbnM9ZnVuY3Rpb24oKXtpZih0aGlzLl9tYXAuc3R5bGUpe3ZhciB0PVtdO2lmKHRoaXMuX21hcC5zdHlsZS5zdHlsZXNoZWV0KXt2YXIgZT10aGlzLl9tYXAuc3R5bGUuc3R5bGVzaGVldDt0aGlzLnN0eWxlT3duZXI9ZS5vd25lcix0aGlzLnN0eWxlSWQ9ZS5pZDt9dmFyIGk9dGhpcy5fbWFwLnN0eWxlLnNvdXJjZUNhY2hlcztmb3IodmFyIG4gaW4gaSl7dmFyIG89aVtuXS5nZXRTb3VyY2UoKTtvLmF0dHJpYnV0aW9uJiZ0LmluZGV4T2Yoby5hdHRyaWJ1dGlvbik8MCYmdC5wdXNoKG8uYXR0cmlidXRpb24pO310LnNvcnQoZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5sZW5ndGgtZS5sZW5ndGh9KSwodD10LmZpbHRlcihmdW5jdGlvbihlLGkpe2Zvcih2YXIgbj1pKzE7bjx0Lmxlbmd0aDtuKyspaWYodFtuXS5pbmRleE9mKGUpPj0wKXJldHVybiExO3JldHVybiEwfSkpLmxlbmd0aD8odGhpcy5fY29udGFpbmVyLmlubmVySFRNTD10LmpvaW4oXCIgfCBcIiksdGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1hdHRyaWItZW1wdHlcIikpOnRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtYXR0cmliLWVtcHR5XCIpLHRoaXMuX2VkaXRMaW5rPW51bGw7fX0sYW4ucHJvdG90eXBlLl91cGRhdGVDb21wYWN0PWZ1bmN0aW9uKCl7dGhpcy5fbWFwLmdldENhbnZhc0NvbnRhaW5lcigpLm9mZnNldFdpZHRoPD02NDA/dGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jb21wYWN0XCIpOnRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY29tcGFjdFwiKTt9O3ZhciBzbj1mdW5jdGlvbigpe3QuYmluZEFsbChbXCJfdXBkYXRlTG9nb1wiXSx0aGlzKTt9O3NuLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt0aGlzLl9tYXA9dCx0aGlzLl9jb250YWluZXI9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWN0cmxcIik7dmFyIGU9cy5jcmVhdGUoXCJhXCIsXCJtYXBib3hnbC1jdHJsLWxvZ29cIik7cmV0dXJuIGUudGFyZ2V0PVwiX2JsYW5rXCIsZS5ocmVmPVwiaHR0cHM6Ly93d3cubWFwYm94LmNvbS9cIixlLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIixcIk1hcGJveCBsb2dvXCIpLHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZChlKSx0aGlzLl9jb250YWluZXIuc3R5bGUuZGlzcGxheT1cIm5vbmVcIix0aGlzLl9tYXAub24oXCJzb3VyY2VkYXRhXCIsdGhpcy5fdXBkYXRlTG9nbyksdGhpcy5fdXBkYXRlTG9nbygpLHRoaXMuX2NvbnRhaW5lcn0sc24ucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7cy5yZW1vdmUodGhpcy5fY29udGFpbmVyKSx0aGlzLl9tYXAub2ZmKFwic291cmNlZGF0YVwiLHRoaXMuX3VwZGF0ZUxvZ28pO30sc24ucHJvdG90eXBlLmdldERlZmF1bHRQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVyblwiYm90dG9tLWxlZnRcIn0sc24ucHJvdG90eXBlLl91cGRhdGVMb2dvPWZ1bmN0aW9uKHQpe3QmJlwibWV0YWRhdGFcIiE9PXQuc291cmNlRGF0YVR5cGV8fCh0aGlzLl9jb250YWluZXIuc3R5bGUuZGlzcGxheT10aGlzLl9sb2dvUmVxdWlyZWQoKT9cImJsb2NrXCI6XCJub25lXCIpO30sc24ucHJvdG90eXBlLl9sb2dvUmVxdWlyZWQ9ZnVuY3Rpb24oKXtpZih0aGlzLl9tYXAuc3R5bGUpe3ZhciB0PXRoaXMuX21hcC5zdHlsZS5zb3VyY2VDYWNoZXM7Zm9yKHZhciBlIGluIHQpe2lmKHRbZV0uZ2V0U291cmNlKCkubWFwYm94X2xvZ28pcmV0dXJuITB9cmV0dXJuITF9fTt2YXIgbG49ZnVuY3Rpb24oKXt0aGlzLl9xdWV1ZT1bXSx0aGlzLl9pZD0wLHRoaXMuX2NsZWFyZWQ9ITEsdGhpcy5fY3VycmVudGx5UnVubmluZz0hMTt9O2xuLnByb3RvdHlwZS5hZGQ9ZnVuY3Rpb24odCl7dmFyIGU9Kyt0aGlzLl9pZDtyZXR1cm4gdGhpcy5fcXVldWUucHVzaCh7Y2FsbGJhY2s6dCxpZDplLGNhbmNlbGxlZDohMX0pLGV9LGxuLnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXRoaXMuX2N1cnJlbnRseVJ1bm5pbmcsaT0wLG49ZT90aGlzLl9xdWV1ZS5jb25jYXQoZSk6dGhpcy5fcXVldWU7aTxuLmxlbmd0aDtpKz0xKXt2YXIgbz1uW2ldO2lmKG8uaWQ9PT10KXJldHVybiB2b2lkKG8uY2FuY2VsbGVkPSEwKX19LGxuLnByb3RvdHlwZS5ydW49ZnVuY3Rpb24oKXt2YXIgdD10aGlzLl9jdXJyZW50bHlSdW5uaW5nPXRoaXMuX3F1ZXVlO3RoaXMuX3F1ZXVlPVtdO2Zvcih2YXIgZT0wLGk9dDtlPGkubGVuZ3RoO2UrPTEpe3ZhciBuPWlbZV07aWYoIW4uY2FuY2VsbGVkJiYobi5jYWxsYmFjaygpLHRoaXMuX2NsZWFyZWQpKWJyZWFrfXRoaXMuX2NsZWFyZWQ9ITEsdGhpcy5fY3VycmVudGx5UnVubmluZz0hMTt9LGxuLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3RoaXMuX2N1cnJlbnRseVJ1bm5pbmcmJih0aGlzLl9jbGVhcmVkPSEwKSx0aGlzLl9xdWV1ZT1bXTt9O3ZhciBjbj10LmRlZmF1bHQuSFRNTEltYWdlRWxlbWVudCx1bj10LmRlZmF1bHQuSFRNTEVsZW1lbnQsaG49e2NlbnRlcjpbMCwwXSx6b29tOjAsYmVhcmluZzowLHBpdGNoOjAsbWluWm9vbTowLG1heFpvb206MjIsaW50ZXJhY3RpdmU6ITAsc2Nyb2xsWm9vbTohMCxib3hab29tOiEwLGRyYWdSb3RhdGU6ITAsZHJhZ1BhbjohMCxrZXlib2FyZDohMCxkb3VibGVDbGlja1pvb206ITAsdG91Y2hab29tUm90YXRlOiEwLGJlYXJpbmdTbmFwOjcsaGFzaDohMSxhdHRyaWJ1dGlvbkNvbnRyb2w6ITAsZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDohMSxwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6ITEsdHJhY2tSZXNpemU6ITAscmVuZGVyV29ybGRDb3BpZXM6ITAscmVmcmVzaEV4cGlyZWRUaWxlczohMCxtYXhUaWxlQ2FjaGVTaXplOm51bGwsdHJhbnNmb3JtUmVxdWVzdDpudWxsLGZhZGVEdXJhdGlvbjozMDB9LHBuPWZ1bmN0aW9uKGkpe2Z1bmN0aW9uIG4oZSl7aWYobnVsbCE9KGU9dC5leHRlbmQoe30saG4sZSkpLm1pblpvb20mJm51bGwhPWUubWF4Wm9vbSYmZS5taW5ab29tPmUubWF4Wm9vbSl0aHJvdyBuZXcgRXJyb3IoXCJtYXhab29tIG11c3QgYmUgZ3JlYXRlciB0aGFuIG1pblpvb21cIik7dmFyIG49bmV3IFVpKGUubWluWm9vbSxlLm1heFpvb20sZS5yZW5kZXJXb3JsZENvcGllcyk7aS5jYWxsKHRoaXMsbixlKSx0aGlzLl9pbnRlcmFjdGl2ZT1lLmludGVyYWN0aXZlLHRoaXMuX21heFRpbGVDYWNoZVNpemU9ZS5tYXhUaWxlQ2FjaGVTaXplLHRoaXMuX2ZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9ZS5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0LHRoaXMuX3ByZXNlcnZlRHJhd2luZ0J1ZmZlcj1lLnByZXNlcnZlRHJhd2luZ0J1ZmZlcix0aGlzLl90cmFja1Jlc2l6ZT1lLnRyYWNrUmVzaXplLHRoaXMuX2JlYXJpbmdTbmFwPWUuYmVhcmluZ1NuYXAsdGhpcy5fcmVmcmVzaEV4cGlyZWRUaWxlcz1lLnJlZnJlc2hFeHBpcmVkVGlsZXMsdGhpcy5fZmFkZUR1cmF0aW9uPWUuZmFkZUR1cmF0aW9uLHRoaXMuX2Nyb3NzRmFkaW5nRmFjdG9yPTEsdGhpcy5fY29sbGVjdFJlc291cmNlVGltaW5nPWUuY29sbGVjdFJlc291cmNlVGltaW5nLHRoaXMuX3JlbmRlclRhc2tRdWV1ZT1uZXcgbG47dmFyIG89ZS50cmFuc2Zvcm1SZXF1ZXN0O2lmKHRoaXMuX3RyYW5zZm9ybVJlcXVlc3Q9bz9mdW5jdGlvbih0LGUpe3JldHVybiBvKHQsZSl8fHt1cmw6dH19OmZ1bmN0aW9uKHQpe3JldHVybnt1cmw6dH19LFwic3RyaW5nXCI9PXR5cGVvZiBlLmNvbnRhaW5lcil7dmFyIHI9dC5kZWZhdWx0LmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGUuY29udGFpbmVyKTtpZighcil0aHJvdyBuZXcgRXJyb3IoXCJDb250YWluZXIgJ1wiK2UuY29udGFpbmVyK1wiJyBub3QgZm91bmQuXCIpO3RoaXMuX2NvbnRhaW5lcj1yO31lbHNle2lmKCEoZS5jb250YWluZXIgaW5zdGFuY2VvZiB1bikpdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCB0eXBlOiAnY29udGFpbmVyJyBtdXN0IGJlIGEgU3RyaW5nIG9yIEhUTUxFbGVtZW50LlwiKTt0aGlzLl9jb250YWluZXI9ZS5jb250YWluZXI7fWUubWF4Qm91bmRzJiZ0aGlzLnNldE1heEJvdW5kcyhlLm1heEJvdW5kcyksdC5iaW5kQWxsKFtcIl9vbldpbmRvd09ubGluZVwiLFwiX29uV2luZG93UmVzaXplXCIsXCJfY29udGV4dExvc3RcIixcIl9jb250ZXh0UmVzdG9yZWRcIixcIl91cGRhdGVcIixcIl9yZW5kZXJcIixcIl9vbkRhdGFcIixcIl9vbkRhdGFMb2FkaW5nXCJdLHRoaXMpLHRoaXMuX3NldHVwQ29udGFpbmVyKCksdGhpcy5fc2V0dXBQYWludGVyKCksdGhpcy5vbihcIm1vdmVcIix0aGlzLl91cGRhdGUuYmluZCh0aGlzLCExKSksdGhpcy5vbihcInpvb21cIix0aGlzLl91cGRhdGUuYmluZCh0aGlzLCEwKSksdm9pZCAwIT09dC5kZWZhdWx0JiYodC5kZWZhdWx0LmFkZEV2ZW50TGlzdGVuZXIoXCJvbmxpbmVcIix0aGlzLl9vbldpbmRvd09ubGluZSwhMSksdC5kZWZhdWx0LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIix0aGlzLl9vbldpbmRvd1Jlc2l6ZSwhMSkpLGZ1bmN0aW9uKHQsZSl7dmFyIGk9dC5nZXRDYW52YXNDb250YWluZXIoKSxuPW51bGwsbz0hMTtmb3IodmFyIHIgaW4gb24pdFtyXT1uZXcgb25bcl0odCxlKSxlLmludGVyYWN0aXZlJiZlW3JdJiZ0W3JdLmVuYWJsZShlW3JdKTtzLmFkZEV2ZW50TGlzdGVuZXIoaSxcIm1vdXNlb3V0XCIsZnVuY3Rpb24oZSl7dC5maXJlKG5ldyBqaShcIm1vdXNlb3V0XCIsdCxlKSk7fSkscy5hZGRFdmVudExpc3RlbmVyKGksXCJtb3VzZWRvd25cIixmdW5jdGlvbihpKXtvPSEwO3ZhciBuPW5ldyBqaShcIm1vdXNlZG93blwiLHQsaSk7dC5maXJlKG4pLG4uZGVmYXVsdFByZXZlbnRlZHx8KGUuaW50ZXJhY3RpdmUmJiF0LmRvdWJsZUNsaWNrWm9vbS5pc0FjdGl2ZSgpJiZ0LnN0b3AoKSx0LmJveFpvb20ub25Nb3VzZURvd24oaSksdC5ib3hab29tLmlzQWN0aXZlKCl8fHQuZHJhZ1Bhbi5pc0FjdGl2ZSgpfHx0LmRyYWdSb3RhdGUub25Nb3VzZURvd24oaSksdC5ib3hab29tLmlzQWN0aXZlKCl8fHQuZHJhZ1JvdGF0ZS5pc0FjdGl2ZSgpfHx0LmRyYWdQYW4ub25Nb3VzZURvd24oaSkpO30pLHMuYWRkRXZlbnRMaXN0ZW5lcihpLFwibW91c2V1cFwiLGZ1bmN0aW9uKGUpe3ZhciBpPXQuZHJhZ1JvdGF0ZS5pc0FjdGl2ZSgpO24mJiFpJiZ0LmZpcmUobmV3IGppKFwiY29udGV4dG1lbnVcIix0LG4pKSxuPW51bGwsbz0hMSx0LmZpcmUobmV3IGppKFwibW91c2V1cFwiLHQsZSkpO30pLHMuYWRkRXZlbnRMaXN0ZW5lcihpLFwibW91c2Vtb3ZlXCIsZnVuY3Rpb24oZSl7aWYoIXQuZHJhZ1Bhbi5pc0FjdGl2ZSgpJiYhdC5kcmFnUm90YXRlLmlzQWN0aXZlKCkpe2Zvcih2YXIgbj1lLnRvRWxlbWVudHx8ZS50YXJnZXQ7biYmbiE9PWk7KW49bi5wYXJlbnROb2RlO249PT1pJiZ0LmZpcmUobmV3IGppKFwibW91c2Vtb3ZlXCIsdCxlKSk7fX0pLHMuYWRkRXZlbnRMaXN0ZW5lcihpLFwibW91c2VvdmVyXCIsZnVuY3Rpb24oZSl7Zm9yKHZhciBuPWUudG9FbGVtZW50fHxlLnRhcmdldDtuJiZuIT09aTspbj1uLnBhcmVudE5vZGU7bj09PWkmJnQuZmlyZShuZXcgamkoXCJtb3VzZW92ZXJcIix0LGUpKTt9KSxzLmFkZEV2ZW50TGlzdGVuZXIoaSxcInRvdWNoc3RhcnRcIixmdW5jdGlvbihpKXt2YXIgbj1uZXcgJGkoXCJ0b3VjaHN0YXJ0XCIsdCxpKTt0LmZpcmUobiksbi5kZWZhdWx0UHJldmVudGVkfHwoZS5pbnRlcmFjdGl2ZSYmdC5zdG9wKCksdC5ib3hab29tLmlzQWN0aXZlKCl8fHQuZHJhZ1JvdGF0ZS5pc0FjdGl2ZSgpfHx0LmRyYWdQYW4ub25Ub3VjaFN0YXJ0KGkpLHQudG91Y2hab29tUm90YXRlLm9uU3RhcnQoaSksdC5kb3VibGVDbGlja1pvb20ub25Ub3VjaFN0YXJ0KG4pKTt9LHtwYXNzaXZlOiExfSkscy5hZGRFdmVudExpc3RlbmVyKGksXCJ0b3VjaG1vdmVcIixmdW5jdGlvbihlKXt0LmZpcmUobmV3ICRpKFwidG91Y2htb3ZlXCIsdCxlKSk7fSx7cGFzc2l2ZTohMX0pLHMuYWRkRXZlbnRMaXN0ZW5lcihpLFwidG91Y2hlbmRcIixmdW5jdGlvbihlKXt0LmZpcmUobmV3ICRpKFwidG91Y2hlbmRcIix0LGUpKTt9KSxzLmFkZEV2ZW50TGlzdGVuZXIoaSxcInRvdWNoY2FuY2VsXCIsZnVuY3Rpb24oZSl7dC5maXJlKG5ldyAkaShcInRvdWNoY2FuY2VsXCIsdCxlKSk7fSkscy5hZGRFdmVudExpc3RlbmVyKGksXCJjbGlja1wiLGZ1bmN0aW9uKGUpe3QuZmlyZShuZXcgamkoXCJjbGlja1wiLHQsZSkpO30pLHMuYWRkRXZlbnRMaXN0ZW5lcihpLFwiZGJsY2xpY2tcIixmdW5jdGlvbihlKXt2YXIgaT1uZXcgamkoXCJkYmxjbGlja1wiLHQsZSk7dC5maXJlKGkpLGkuZGVmYXVsdFByZXZlbnRlZHx8dC5kb3VibGVDbGlja1pvb20ub25EYmxDbGljayhpKTt9KSxzLmFkZEV2ZW50TGlzdGVuZXIoaSxcImNvbnRleHRtZW51XCIsZnVuY3Rpb24oZSl7dmFyIGk9dC5kcmFnUm90YXRlLmlzQWN0aXZlKCk7b3x8aT9vJiYobj1lKTp0LmZpcmUobmV3IGppKFwiY29udGV4dG1lbnVcIix0LGUpKSxlLnByZXZlbnREZWZhdWx0KCk7fSkscy5hZGRFdmVudExpc3RlbmVyKGksXCJ3aGVlbFwiLGZ1bmN0aW9uKGUpe3ZhciBpPW5ldyBHaShcIndoZWVsXCIsdCxlKTt0LmZpcmUoaSksaS5kZWZhdWx0UHJldmVudGVkfHx0LnNjcm9sbFpvb20ub25XaGVlbChlKTt9LHtwYXNzaXZlOiExfSk7fSh0aGlzLGUpLHRoaXMuX2hhc2g9ZS5oYXNoJiYobmV3IFZpKS5hZGRUbyh0aGlzKSx0aGlzLl9oYXNoJiZ0aGlzLl9oYXNoLl9vbkhhc2hDaGFuZ2UoKXx8dGhpcy5qdW1wVG8oe2NlbnRlcjplLmNlbnRlcix6b29tOmUuem9vbSxiZWFyaW5nOmUuYmVhcmluZyxwaXRjaDplLnBpdGNofSksdGhpcy5yZXNpemUoKSxlLnN0eWxlJiZ0aGlzLnNldFN0eWxlKGUuc3R5bGUse2xvY2FsSWRlb2dyYXBoRm9udEZhbWlseTplLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseX0pLGUuYXR0cmlidXRpb25Db250cm9sJiZ0aGlzLmFkZENvbnRyb2wobmV3IGFuKSx0aGlzLmFkZENvbnRyb2wobmV3IHNuLGUubG9nb1Bvc2l0aW9uKSx0aGlzLm9uKFwic3R5bGUubG9hZFwiLGZ1bmN0aW9uKCl7dGhpcy50cmFuc2Zvcm0udW5tb2RpZmllZCYmdGhpcy5qdW1wVG8odGhpcy5zdHlsZS5zdHlsZXNoZWV0KTt9KSx0aGlzLm9uKFwiZGF0YVwiLHRoaXMuX29uRGF0YSksdGhpcy5vbihcImRhdGFsb2FkaW5nXCIsdGhpcy5fb25EYXRhTG9hZGluZyk7fWkmJihuLl9fcHJvdG9fXz1pKSxuLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGkmJmkucHJvdG90eXBlKSxuLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1uO3ZhciBvPXtzaG93VGlsZUJvdW5kYXJpZXM6e2NvbmZpZ3VyYWJsZTohMH0sc2hvd0NvbGxpc2lvbkJveGVzOntjb25maWd1cmFibGU6ITB9LHNob3dPdmVyZHJhd0luc3BlY3Rvcjp7Y29uZmlndXJhYmxlOiEwfSxyZXBhaW50Ontjb25maWd1cmFibGU6ITB9LHZlcnRpY2VzOntjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gbi5wcm90b3R5cGUuYWRkQ29udHJvbD1mdW5jdGlvbih0LGUpe3ZvaWQgMD09PWUmJnQuZ2V0RGVmYXVsdFBvc2l0aW9uJiYoZT10LmdldERlZmF1bHRQb3NpdGlvbigpKSx2b2lkIDA9PT1lJiYoZT1cInRvcC1yaWdodFwiKTt2YXIgaT10Lm9uQWRkKHRoaXMpLG49dGhpcy5fY29udHJvbFBvc2l0aW9uc1tlXTtyZXR1cm4tMSE9PWUuaW5kZXhPZihcImJvdHRvbVwiKT9uLmluc2VydEJlZm9yZShpLG4uZmlyc3RDaGlsZCk6bi5hcHBlbmRDaGlsZChpKSx0aGlzfSxuLnByb3RvdHlwZS5yZW1vdmVDb250cm9sPWZ1bmN0aW9uKHQpe3JldHVybiB0Lm9uUmVtb3ZlKHRoaXMpLHRoaXN9LG4ucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbihlKXt2YXIgaT10aGlzLl9jb250YWluZXJEaW1lbnNpb25zKCksbj1pWzBdLG89aVsxXTtyZXR1cm4gdGhpcy5fcmVzaXplQ2FudmFzKG4sbyksdGhpcy50cmFuc2Zvcm0ucmVzaXplKG4sbyksdGhpcy5wYWludGVyLnJlc2l6ZShuLG8pLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIm1vdmVzdGFydFwiLGUpKS5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLGUpKS5maXJlKG5ldyB0LkV2ZW50KFwicmVzaXplXCIsZSkpLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlZW5kXCIsZSkpfSxuLnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oKXt2YXIgZT1uZXcgcSh0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyB0LmRlZmF1bHQkMSgwLHRoaXMudHJhbnNmb3JtLmhlaWdodCkpLHRoaXMudHJhbnNmb3JtLnBvaW50TG9jYXRpb24obmV3IHQuZGVmYXVsdCQxKHRoaXMudHJhbnNmb3JtLndpZHRoLDApKSk7cmV0dXJuKHRoaXMudHJhbnNmb3JtLmFuZ2xlfHx0aGlzLnRyYW5zZm9ybS5waXRjaCkmJihlLmV4dGVuZCh0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyB0LmRlZmF1bHQkMSh0aGlzLnRyYW5zZm9ybS5zaXplLngsMCkpKSxlLmV4dGVuZCh0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyB0LmRlZmF1bHQkMSgwLHRoaXMudHJhbnNmb3JtLnNpemUueSkpKSksZX0sbi5wcm90b3R5cGUuZ2V0TWF4Qm91bmRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLmxhdFJhbmdlJiYyPT09dGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2UubGVuZ3RoJiZ0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZSYmMj09PXRoaXMudHJhbnNmb3JtLmxuZ1JhbmdlLmxlbmd0aD9uZXcgcShbdGhpcy50cmFuc2Zvcm0ubG5nUmFuZ2VbMF0sdGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2VbMF1dLFt0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZVsxXSx0aGlzLnRyYW5zZm9ybS5sYXRSYW5nZVsxXV0pOm51bGx9LG4ucHJvdG90eXBlLnNldE1heEJvdW5kcz1mdW5jdGlvbih0KXtpZih0KXt2YXIgZT1xLmNvbnZlcnQodCk7dGhpcy50cmFuc2Zvcm0ubG5nUmFuZ2U9W2UuZ2V0V2VzdCgpLGUuZ2V0RWFzdCgpXSx0aGlzLnRyYW5zZm9ybS5sYXRSYW5nZT1bZS5nZXRTb3V0aCgpLGUuZ2V0Tm9ydGgoKV0sdGhpcy50cmFuc2Zvcm0uX2NvbnN0cmFpbigpLHRoaXMuX3VwZGF0ZSgpO31lbHNlIG51bGw9PXQmJih0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZT1udWxsLHRoaXMudHJhbnNmb3JtLmxhdFJhbmdlPW51bGwsdGhpcy5fdXBkYXRlKCkpO3JldHVybiB0aGlzfSxuLnByb3RvdHlwZS5zZXRNaW5ab29tPWZ1bmN0aW9uKHQpe2lmKCh0PW51bGw9PXQ/MDp0KT49MCYmdDw9dGhpcy50cmFuc2Zvcm0ubWF4Wm9vbSlyZXR1cm4gdGhpcy50cmFuc2Zvcm0ubWluWm9vbT10LHRoaXMuX3VwZGF0ZSgpLHRoaXMuZ2V0Wm9vbSgpPHQmJnRoaXMuc2V0Wm9vbSh0KSx0aGlzO3Rocm93IG5ldyBFcnJvcihcIm1pblpvb20gbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIHRoZSBjdXJyZW50IG1heFpvb20sIGluY2x1c2l2ZVwiKX0sbi5wcm90b3R5cGUuZ2V0TWluWm9vbT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5taW5ab29tfSxuLnByb3RvdHlwZS5zZXRNYXhab29tPWZ1bmN0aW9uKHQpe2lmKCh0PW51bGw9PXQ/MjI6dCk+PXRoaXMudHJhbnNmb3JtLm1pblpvb20pcmV0dXJuIHRoaXMudHJhbnNmb3JtLm1heFpvb209dCx0aGlzLl91cGRhdGUoKSx0aGlzLmdldFpvb20oKT50JiZ0aGlzLnNldFpvb20odCksdGhpczt0aHJvdyBuZXcgRXJyb3IoXCJtYXhab29tIG11c3QgYmUgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IG1pblpvb21cIil9LG4ucHJvdG90eXBlLmdldFJlbmRlcldvcmxkQ29waWVzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLnJlbmRlcldvcmxkQ29waWVzfSxuLnByb3RvdHlwZS5zZXRSZW5kZXJXb3JsZENvcGllcz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0ucmVuZGVyV29ybGRDb3BpZXM9dCx0aGlzLl91cGRhdGUoKSx0aGlzfSxuLnByb3RvdHlwZS5nZXRNYXhab29tPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLm1heFpvb219LG4ucHJvdG90eXBlLnByb2plY3Q9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLmxvY2F0aW9uUG9pbnQoVy5jb252ZXJ0KHQpKX0sbi5wcm90b3R5cGUudW5wcm9qZWN0PWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKHQuZGVmYXVsdCQxLmNvbnZlcnQoZSkpfSxuLnByb3RvdHlwZS5pc01vdmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9tb3Zpbmd8fHRoaXMuZHJhZ1Bhbi5pc0FjdGl2ZSgpfHx0aGlzLmRyYWdSb3RhdGUuaXNBY3RpdmUoKXx8dGhpcy5zY3JvbGxab29tLmlzQWN0aXZlKCl9LG4ucHJvdG90eXBlLmlzWm9vbWluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl96b29taW5nfHx0aGlzLnNjcm9sbFpvb20uaXNBY3RpdmUoKX0sbi5wcm90b3R5cGUuaXNSb3RhdGluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9yb3RhdGluZ3x8dGhpcy5kcmFnUm90YXRlLmlzQWN0aXZlKCl9LG4ucHJvdG90eXBlLm9uPWZ1bmN0aW9uKHQsZSxuKXt2YXIgbyxyPXRoaXM7aWYodm9pZCAwPT09bilyZXR1cm4gaS5wcm90b3R5cGUub24uY2FsbCh0aGlzLHQsZSk7dmFyIGE9ZnVuY3Rpb24oKXtpZihcIm1vdXNlZW50ZXJcIj09PXR8fFwibW91c2VvdmVyXCI9PT10KXt2YXIgaT0hMTtyZXR1cm57bGF5ZXI6ZSxsaXN0ZW5lcjpuLGRlbGVnYXRlczp7bW91c2Vtb3ZlOmZ1bmN0aW9uKG8pe3ZhciBhPXIuZ2V0TGF5ZXIoZSk/ci5xdWVyeVJlbmRlcmVkRmVhdHVyZXMoby5wb2ludCx7bGF5ZXJzOltlXX0pOltdO2EubGVuZ3RoP2l8fChpPSEwLG4uY2FsbChyLG5ldyBqaSh0LHIsby5vcmlnaW5hbEV2ZW50LHtmZWF0dXJlczphfSkpKTppPSExO30sbW91c2VvdXQ6ZnVuY3Rpb24oKXtpPSExO319fX1pZihcIm1vdXNlbGVhdmVcIj09PXR8fFwibW91c2VvdXRcIj09PXQpe3ZhciBhPSExO3JldHVybntsYXllcjplLGxpc3RlbmVyOm4sZGVsZWdhdGVzOnttb3VzZW1vdmU6ZnVuY3Rpb24oaSl7KHIuZ2V0TGF5ZXIoZSk/ci5xdWVyeVJlbmRlcmVkRmVhdHVyZXMoaS5wb2ludCx7bGF5ZXJzOltlXX0pOltdKS5sZW5ndGg/YT0hMDphJiYoYT0hMSxuLmNhbGwocixuZXcgamkodCxyLGkub3JpZ2luYWxFdmVudCkpKTt9LG1vdXNlb3V0OmZ1bmN0aW9uKGUpe2EmJihhPSExLG4uY2FsbChyLG5ldyBqaSh0LHIsZS5vcmlnaW5hbEV2ZW50KSkpO319fX1yZXR1cm57bGF5ZXI6ZSxsaXN0ZW5lcjpuLGRlbGVnYXRlczoobz17fSxvW3RdPWZ1bmN0aW9uKHQpe3ZhciBpPXIuZ2V0TGF5ZXIoZSk/ci5xdWVyeVJlbmRlcmVkRmVhdHVyZXModC5wb2ludCx7bGF5ZXJzOltlXX0pOltdO2kubGVuZ3RoJiYodC5mZWF0dXJlcz1pLG4uY2FsbChyLHQpLGRlbGV0ZSB0LmZlYXR1cmVzKTt9LG8pfX0oKTtmb3IodmFyIHMgaW4gdGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzPXRoaXMuX2RlbGVnYXRlZExpc3RlbmVyc3x8e30sdGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzW3RdPXRoaXMuX2RlbGVnYXRlZExpc3RlbmVyc1t0XXx8W10sdGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzW3RdLnB1c2goYSksYS5kZWxlZ2F0ZXMpci5vbihzLGEuZGVsZWdhdGVzW3NdKTtyZXR1cm4gdGhpc30sbi5wcm90b3R5cGUub2ZmPWZ1bmN0aW9uKHQsZSxuKXtpZih2b2lkIDA9PT1uKXJldHVybiBpLnByb3RvdHlwZS5vZmYuY2FsbCh0aGlzLHQsZSk7aWYodGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzJiZ0aGlzLl9kZWxlZ2F0ZWRMaXN0ZW5lcnNbdF0pZm9yKHZhciBvPXRoaXMuX2RlbGVnYXRlZExpc3RlbmVyc1t0XSxyPTA7cjxvLmxlbmd0aDtyKyspe3ZhciBhPW9bcl07aWYoYS5sYXllcj09PWUmJmEubGlzdGVuZXI9PT1uKXtmb3IodmFyIHMgaW4gYS5kZWxlZ2F0ZXMpdGhpcy5vZmYocyxhLmRlbGVnYXRlc1tzXSk7cmV0dXJuIG8uc3BsaWNlKHIsMSksdGhpc319cmV0dXJuIHRoaXN9LG4ucHJvdG90eXBlLnF1ZXJ5UmVuZGVyZWRGZWF0dXJlcz1mdW5jdGlvbihlLGkpe3ZhciBuO3JldHVybiAyPT09YXJndW1lbnRzLmxlbmd0aD8oZT1hcmd1bWVudHNbMF0saT1hcmd1bWVudHNbMV0pOjE9PT1hcmd1bWVudHMubGVuZ3RoJiYoKG49YXJndW1lbnRzWzBdKWluc3RhbmNlb2YgdC5kZWZhdWx0JDF8fEFycmF5LmlzQXJyYXkobikpPyhlPWFyZ3VtZW50c1swXSxpPXt9KToxPT09YXJndW1lbnRzLmxlbmd0aD8oZT12b2lkIDAsaT1hcmd1bWVudHNbMF0pOihlPXZvaWQgMCxpPXt9KSx0aGlzLnN0eWxlP3RoaXMuc3R5bGUucXVlcnlSZW5kZXJlZEZlYXR1cmVzKHRoaXMuX21ha2VRdWVyeUdlb21ldHJ5KGUpLGksdGhpcy50cmFuc2Zvcm0pOltdfSxuLnByb3RvdHlwZS5fbWFrZVF1ZXJ5R2VvbWV0cnk9ZnVuY3Rpb24oZSl7dmFyIGksbj10aGlzO2lmKHZvaWQgMD09PWUmJihlPVt0LmRlZmF1bHQkMS5jb252ZXJ0KFswLDBdKSx0LmRlZmF1bHQkMS5jb252ZXJ0KFt0aGlzLnRyYW5zZm9ybS53aWR0aCx0aGlzLnRyYW5zZm9ybS5oZWlnaHRdKV0pLGUgaW5zdGFuY2VvZiB0LmRlZmF1bHQkMXx8XCJudW1iZXJcIj09dHlwZW9mIGVbMF0pe2k9W3QuZGVmYXVsdCQxLmNvbnZlcnQoZSldO31lbHNle3ZhciBvPVt0LmRlZmF1bHQkMS5jb252ZXJ0KGVbMF0pLHQuZGVmYXVsdCQxLmNvbnZlcnQoZVsxXSldO2k9W29bMF0sbmV3IHQuZGVmYXVsdCQxKG9bMV0ueCxvWzBdLnkpLG9bMV0sbmV3IHQuZGVmYXVsdCQxKG9bMF0ueCxvWzFdLnkpLG9bMF1dO31yZXR1cm57dmlld3BvcnQ6aSx3b3JsZENvb3JkaW5hdGU6aS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIG4udHJhbnNmb3JtLnBvaW50Q29vcmRpbmF0ZSh0KX0pfX0sbi5wcm90b3R5cGUucXVlcnlTb3VyY2VGZWF0dXJlcz1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnN0eWxlLnF1ZXJ5U291cmNlRmVhdHVyZXModCxlKX0sbi5wcm90b3R5cGUuc2V0U3R5bGU9ZnVuY3Rpb24oZSxpKXtpZigoIWl8fCExIT09aS5kaWZmJiYhaS5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHkpJiZ0aGlzLnN0eWxlJiZlJiZcIm9iamVjdFwiPT10eXBlb2YgZSl0cnl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0U3RhdGUoZSkmJnRoaXMuX3VwZGF0ZSghMCksdGhpc31jYXRjaChlKXt0Lndhcm5PbmNlKFwiVW5hYmxlIHRvIHBlcmZvcm0gc3R5bGUgZGlmZjogXCIrKGUubWVzc2FnZXx8ZS5lcnJvcnx8ZSkrXCIuICBSZWJ1aWxkaW5nIHRoZSBzdHlsZSBmcm9tIHNjcmF0Y2guXCIpO31yZXR1cm4gdGhpcy5zdHlsZSYmKHRoaXMuc3R5bGUuc2V0RXZlbnRlZFBhcmVudChudWxsKSx0aGlzLnN0eWxlLl9yZW1vdmUoKSksZT8odGhpcy5zdHlsZT1uZXcgUWUodGhpcyxpfHx7fSksdGhpcy5zdHlsZS5zZXRFdmVudGVkUGFyZW50KHRoaXMse3N0eWxlOnRoaXMuc3R5bGV9KSxcInN0cmluZ1wiPT10eXBlb2YgZT90aGlzLnN0eWxlLmxvYWRVUkwoZSk6dGhpcy5zdHlsZS5sb2FkSlNPTihlKSx0aGlzKTooZGVsZXRlIHRoaXMuc3R5bGUsdGhpcyl9LG4ucHJvdG90eXBlLmdldFN0eWxlPWZ1bmN0aW9uKCl7aWYodGhpcy5zdHlsZSlyZXR1cm4gdGhpcy5zdHlsZS5zZXJpYWxpemUoKX0sbi5wcm90b3R5cGUuaXNTdHlsZUxvYWRlZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnN0eWxlP3RoaXMuc3R5bGUubG9hZGVkKCk6dC53YXJuT25jZShcIlRoZXJlIGlzIG5vIHN0eWxlIGFkZGVkIHRvIHRoZSBtYXAuXCIpfSxuLnByb3RvdHlwZS5hZGRTb3VyY2U9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zdHlsZS5hZGRTb3VyY2UodCxlKSx0aGlzLl91cGRhdGUoITApLHRoaXN9LG4ucHJvdG90eXBlLmlzU291cmNlTG9hZGVkPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuc3R5bGUmJnRoaXMuc3R5bGUuc291cmNlQ2FjaGVzW2VdO2lmKHZvaWQgMCE9PWkpcmV0dXJuIGkubG9hZGVkKCk7dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlcmUgaXMgbm8gc291cmNlIHdpdGggSUQgJ1wiK2UrXCInXCIpKSk7fSxuLnByb3RvdHlwZS5hcmVUaWxlc0xvYWRlZD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuc3R5bGUmJnRoaXMuc3R5bGUuc291cmNlQ2FjaGVzO2Zvcih2YXIgZSBpbiB0KXt2YXIgaT10W2VdLl90aWxlcztmb3IodmFyIG4gaW4gaSl7dmFyIG89aVtuXTtpZihcImxvYWRlZFwiIT09by5zdGF0ZSYmXCJlcnJvcmVkXCIhPT1vLnN0YXRlKXJldHVybiExfX1yZXR1cm4hMH0sbi5wcm90b3R5cGUuYWRkU291cmNlVHlwZT1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIHRoaXMuc3R5bGUuYWRkU291cmNlVHlwZSh0LGUsaSl9LG4ucHJvdG90eXBlLnJlbW92ZVNvdXJjZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5yZW1vdmVTb3VyY2UodCksdGhpcy5fdXBkYXRlKCEwKSx0aGlzfSxuLnByb3RvdHlwZS5nZXRTb3VyY2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc3R5bGUuZ2V0U291cmNlKHQpfSxuLnByb3RvdHlwZS5hZGRJbWFnZT1mdW5jdGlvbihlLGksbil7dm9pZCAwPT09biYmKG49e30pO3ZhciBvPW4ucGl4ZWxSYXRpbzt2b2lkIDA9PT1vJiYobz0xKTt2YXIgYT1uLnNkZjtpZih2b2lkIDA9PT1hJiYoYT0hMSksaSBpbnN0YW5jZW9mIGNuKXt2YXIgcz1yLmdldEltYWdlRGF0YShpKSxsPXMud2lkdGgsYz1zLmhlaWdodCx1PXMuZGF0YTt0aGlzLnN0eWxlLmFkZEltYWdlKGUse2RhdGE6bmV3IHQuUkdCQUltYWdlKHt3aWR0aDpsLGhlaWdodDpjfSx1KSxwaXhlbFJhdGlvOm8sc2RmOmF9KTt9ZWxzZXtpZih2b2lkIDA9PT1pLndpZHRofHx2b2lkIDA9PT1pLmhlaWdodClyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiSW52YWxpZCBhcmd1bWVudHMgdG8gbWFwLmFkZEltYWdlKCkuIFRoZSBzZWNvbmQgYXJndW1lbnQgbXVzdCBiZSBhbiBgSFRNTEltYWdlRWxlbWVudGAsIGBJbWFnZURhdGFgLCBvciBvYmplY3Qgd2l0aCBgd2lkdGhgLCBgaGVpZ2h0YCwgYW5kIGBkYXRhYCBwcm9wZXJ0aWVzIHdpdGggdGhlIHNhbWUgZm9ybWF0IGFzIGBJbWFnZURhdGFgXCIpKSk7dmFyIGg9aS53aWR0aCxwPWkuaGVpZ2h0LGQ9aS5kYXRhO3RoaXMuc3R5bGUuYWRkSW1hZ2UoZSx7ZGF0YTpuZXcgdC5SR0JBSW1hZ2Uoe3dpZHRoOmgsaGVpZ2h0OnB9LGQuc2xpY2UoMCkpLHBpeGVsUmF0aW86byxzZGY6YX0pO319LG4ucHJvdG90eXBlLmhhc0ltYWdlPWZ1bmN0aW9uKGUpe3JldHVybiBlPyEhdGhpcy5zdHlsZS5nZXRJbWFnZShlKToodGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiTWlzc2luZyByZXF1aXJlZCBpbWFnZSBpZFwiKSkpLCExKX0sbi5wcm90b3R5cGUucmVtb3ZlSW1hZ2U9ZnVuY3Rpb24odCl7dGhpcy5zdHlsZS5yZW1vdmVJbWFnZSh0KTt9LG4ucHJvdG90eXBlLmxvYWRJbWFnZT1mdW5jdGlvbihlLGkpe3QuZ2V0SW1hZ2UodGhpcy5fdHJhbnNmb3JtUmVxdWVzdChlLHQuUmVzb3VyY2VUeXBlLkltYWdlKSxpKTt9LG4ucHJvdG90eXBlLmFkZExheWVyPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuYWRkTGF5ZXIodCxlKSx0aGlzLl91cGRhdGUoITApLHRoaXN9LG4ucHJvdG90eXBlLm1vdmVMYXllcj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnN0eWxlLm1vdmVMYXllcih0LGUpLHRoaXMuX3VwZGF0ZSghMCksdGhpc30sbi5wcm90b3R5cGUucmVtb3ZlTGF5ZXI9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc3R5bGUucmVtb3ZlTGF5ZXIodCksdGhpcy5fdXBkYXRlKCEwKSx0aGlzfSxuLnByb3RvdHlwZS5nZXRMYXllcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5nZXRMYXllcih0KX0sbi5wcm90b3R5cGUuc2V0RmlsdGVyPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0RmlsdGVyKHQsZSksdGhpcy5fdXBkYXRlKCEwKSx0aGlzfSxuLnByb3RvdHlwZS5zZXRMYXllclpvb21SYW5nZT1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0TGF5ZXJab29tUmFuZ2UodCxlLGkpLHRoaXMuX3VwZGF0ZSghMCksdGhpc30sbi5wcm90b3R5cGUuZ2V0RmlsdGVyPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnN0eWxlLmdldEZpbHRlcih0KX0sbi5wcm90b3R5cGUuc2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0UGFpbnRQcm9wZXJ0eSh0LGUsaSksdGhpcy5fdXBkYXRlKCEwKSx0aGlzfSxuLnByb3RvdHlwZS5nZXRQYWludFByb3BlcnR5PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuZ2V0UGFpbnRQcm9wZXJ0eSh0LGUpfSxuLnByb3RvdHlwZS5zZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0TGF5b3V0UHJvcGVydHkodCxlLGkpLHRoaXMuX3VwZGF0ZSghMCksdGhpc30sbi5wcm90b3R5cGUuZ2V0TGF5b3V0UHJvcGVydHk9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zdHlsZS5nZXRMYXlvdXRQcm9wZXJ0eSh0LGUpfSxuLnByb3RvdHlwZS5zZXRMaWdodD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5zZXRMaWdodCh0KSx0aGlzLl91cGRhdGUoITApLHRoaXN9LG4ucHJvdG90eXBlLmdldExpZ2h0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGlnaHQoKX0sbi5wcm90b3R5cGUuZ2V0Q29udGFpbmVyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbnRhaW5lcn0sbi5wcm90b3R5cGUuZ2V0Q2FudmFzQ29udGFpbmVyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NhbnZhc0NvbnRhaW5lcn0sbi5wcm90b3R5cGUuZ2V0Q2FudmFzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NhbnZhc30sbi5wcm90b3R5cGUuX2NvbnRhaW5lckRpbWVuc2lvbnM9ZnVuY3Rpb24oKXt2YXIgdD0wLGU9MDtyZXR1cm4gdGhpcy5fY29udGFpbmVyJiYodD10aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGh8fDQwMCxlPXRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHR8fDMwMCksW3QsZV19LG4ucHJvdG90eXBlLl9zZXR1cENvbnRhaW5lcj1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX2NvbnRhaW5lcjt0LmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1tYXBcIiksKHRoaXMuX21pc3NpbmdDU1NDb250YWluZXI9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLW1pc3NpbmctY3NzXCIsdCkpLmlubmVySFRNTD1cIk1pc3NpbmcgTWFwYm94IEdMIEpTIENTU1wiO3ZhciBlPXRoaXMuX2NhbnZhc0NvbnRhaW5lcj1zLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtY2FudmFzLWNvbnRhaW5lclwiLHQpO3RoaXMuX2ludGVyYWN0aXZlJiZlLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1pbnRlcmFjdGl2ZVwiKSx0aGlzLl9jYW52YXM9cy5jcmVhdGUoXCJjYW52YXNcIixcIm1hcGJveGdsLWNhbnZhc1wiLGUpLHRoaXMuX2NhbnZhcy5zdHlsZS5wb3NpdGlvbj1cImFic29sdXRlXCIsdGhpcy5fY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoXCJ3ZWJnbGNvbnRleHRsb3N0XCIsdGhpcy5fY29udGV4dExvc3QsITEpLHRoaXMuX2NhbnZhcy5hZGRFdmVudExpc3RlbmVyKFwid2ViZ2xjb250ZXh0cmVzdG9yZWRcIix0aGlzLl9jb250ZXh0UmVzdG9yZWQsITEpLHRoaXMuX2NhbnZhcy5zZXRBdHRyaWJ1dGUoXCJ0YWJpbmRleFwiLFwiMFwiKSx0aGlzLl9jYW52YXMuc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLFwiTWFwXCIpO3ZhciBpPXRoaXMuX2NvbnRhaW5lckRpbWVuc2lvbnMoKTt0aGlzLl9yZXNpemVDYW52YXMoaVswXSxpWzFdKTt2YXIgbj10aGlzLl9jb250cm9sQ29udGFpbmVyPXMuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jb250cm9sLWNvbnRhaW5lclwiLHQpLG89dGhpcy5fY29udHJvbFBvc2l0aW9ucz17fTtbXCJ0b3AtbGVmdFwiLFwidG9wLXJpZ2h0XCIsXCJib3R0b20tbGVmdFwiLFwiYm90dG9tLXJpZ2h0XCJdLmZvckVhY2goZnVuY3Rpb24odCl7b1t0XT1zLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtY3RybC1cIit0LG4pO30pO30sbi5wcm90b3R5cGUuX3Jlc2l6ZUNhbnZhcz1mdW5jdGlvbihlLGkpe3ZhciBuPXQuZGVmYXVsdC5kZXZpY2VQaXhlbFJhdGlvfHwxO3RoaXMuX2NhbnZhcy53aWR0aD1uKmUsdGhpcy5fY2FudmFzLmhlaWdodD1uKmksdGhpcy5fY2FudmFzLnN0eWxlLndpZHRoPWUrXCJweFwiLHRoaXMuX2NhbnZhcy5zdHlsZS5oZWlnaHQ9aStcInB4XCI7fSxuLnByb3RvdHlwZS5fc2V0dXBQYWludGVyPWZ1bmN0aW9uKCl7dmFyIGk9dC5leHRlbmQoe2ZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ6dGhpcy5fZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCxwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6dGhpcy5fcHJlc2VydmVEcmF3aW5nQnVmZmVyfSxlLndlYkdMQ29udGV4dEF0dHJpYnV0ZXMpLG49dGhpcy5fY2FudmFzLmdldENvbnRleHQoXCJ3ZWJnbFwiLGkpfHx0aGlzLl9jYW52YXMuZ2V0Q29udGV4dChcImV4cGVyaW1lbnRhbC13ZWJnbFwiLGkpO24/dGhpcy5wYWludGVyPW5ldyBMaShuLHRoaXMudHJhbnNmb3JtKTp0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJGYWlsZWQgdG8gaW5pdGlhbGl6ZSBXZWJHTFwiKSkpO30sbi5wcm90b3R5cGUuX2NvbnRleHRMb3N0PWZ1bmN0aW9uKGUpe2UucHJldmVudERlZmF1bHQoKSx0aGlzLl9mcmFtZUlkJiYoci5jYW5jZWxGcmFtZSh0aGlzLl9mcmFtZUlkKSx0aGlzLl9mcmFtZUlkPW51bGwpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIndlYmdsY29udGV4dGxvc3RcIix7b3JpZ2luYWxFdmVudDplfSkpO30sbi5wcm90b3R5cGUuX2NvbnRleHRSZXN0b3JlZD1mdW5jdGlvbihlKXt0aGlzLl9zZXR1cFBhaW50ZXIoKSx0aGlzLnJlc2l6ZSgpLHRoaXMuX3VwZGF0ZSgpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIndlYmdsY29udGV4dHJlc3RvcmVkXCIse29yaWdpbmFsRXZlbnQ6ZX0pKTt9LG4ucHJvdG90eXBlLmxvYWRlZD1mdW5jdGlvbigpe3JldHVybiF0aGlzLl9zdHlsZURpcnR5JiYhdGhpcy5fc291cmNlc0RpcnR5JiYhKCF0aGlzLnN0eWxlfHwhdGhpcy5zdHlsZS5sb2FkZWQoKSl9LG4ucHJvdG90eXBlLl91cGRhdGU9ZnVuY3Rpb24odCl7dGhpcy5zdHlsZSYmKHRoaXMuX3N0eWxlRGlydHk9dGhpcy5fc3R5bGVEaXJ0eXx8dCx0aGlzLl9zb3VyY2VzRGlydHk9ITAsdGhpcy5fcmVyZW5kZXIoKSk7fSxuLnByb3RvdHlwZS5fcmVxdWVzdFJlbmRlckZyYW1lPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl91cGRhdGUoKSx0aGlzLl9yZW5kZXJUYXNrUXVldWUuYWRkKHQpfSxuLnByb3RvdHlwZS5fY2FuY2VsUmVuZGVyRnJhbWU9ZnVuY3Rpb24odCl7dGhpcy5fcmVuZGVyVGFza1F1ZXVlLnJlbW92ZSh0KTt9LG4ucHJvdG90eXBlLl9yZW5kZXI9ZnVuY3Rpb24oKXt0aGlzLl9yZW5kZXJUYXNrUXVldWUucnVuKCk7dmFyIGU9ITE7aWYodGhpcy5zdHlsZSYmdGhpcy5fc3R5bGVEaXJ0eSl7dGhpcy5fc3R5bGVEaXJ0eT0hMTt2YXIgaT10aGlzLnRyYW5zZm9ybS56b29tLG49ci5ub3coKTt0aGlzLnN0eWxlLnpvb21IaXN0b3J5LnVwZGF0ZShpLG4pO3ZhciBvPW5ldyB0LmRlZmF1bHQkMTYoaSx7bm93Om4sZmFkZUR1cmF0aW9uOnRoaXMuX2ZhZGVEdXJhdGlvbix6b29tSGlzdG9yeTp0aGlzLnN0eWxlLnpvb21IaXN0b3J5LHRyYW5zaXRpb246dGhpcy5zdHlsZS5nZXRUcmFuc2l0aW9uKCl9KSxhPW8uY3Jvc3NGYWRpbmdGYWN0b3IoKTsxPT09YSYmYT09PXRoaXMuX2Nyb3NzRmFkaW5nRmFjdG9yfHwoZT0hMCx0aGlzLl9jcm9zc0ZhZGluZ0ZhY3Rvcj1hKSx0aGlzLnN0eWxlLnVwZGF0ZShvKTt9cmV0dXJuIHRoaXMuc3R5bGUmJnRoaXMuX3NvdXJjZXNEaXJ0eSYmKHRoaXMuX3NvdXJjZXNEaXJ0eT0hMSx0aGlzLnN0eWxlLl91cGRhdGVTb3VyY2VzKHRoaXMudHJhbnNmb3JtKSksdGhpcy5fcGxhY2VtZW50RGlydHk9dGhpcy5zdHlsZSYmdGhpcy5zdHlsZS5fdXBkYXRlUGxhY2VtZW50KHRoaXMucGFpbnRlci50cmFuc2Zvcm0sdGhpcy5zaG93Q29sbGlzaW9uQm94ZXMsdGhpcy5fZmFkZUR1cmF0aW9uKSx0aGlzLnBhaW50ZXIucmVuZGVyKHRoaXMuc3R5bGUse3Nob3dUaWxlQm91bmRhcmllczp0aGlzLnNob3dUaWxlQm91bmRhcmllcyxzaG93T3ZlcmRyYXdJbnNwZWN0b3I6dGhpcy5fc2hvd092ZXJkcmF3SW5zcGVjdG9yLHJvdGF0aW5nOnRoaXMuaXNSb3RhdGluZygpLHpvb21pbmc6dGhpcy5pc1pvb21pbmcoKSxmYWRlRHVyYXRpb246dGhpcy5fZmFkZUR1cmF0aW9ufSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicmVuZGVyXCIpKSx0aGlzLmxvYWRlZCgpJiYhdGhpcy5fbG9hZGVkJiYodGhpcy5fbG9hZGVkPSEwLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImxvYWRcIikpKSx0aGlzLnN0eWxlJiYodGhpcy5zdHlsZS5oYXNUcmFuc2l0aW9ucygpfHxlKSYmKHRoaXMuX3N0eWxlRGlydHk9ITApLCh0aGlzLl9zb3VyY2VzRGlydHl8fHRoaXMuX3JlcGFpbnR8fHRoaXMuX3N0eWxlRGlydHl8fHRoaXMuX3BsYWNlbWVudERpcnR5KSYmdGhpcy5fcmVyZW5kZXIoKSx0aGlzfSxuLnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24oKXt0aGlzLl9oYXNoJiZ0aGlzLl9oYXNoLnJlbW92ZSgpLHIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCksdGhpcy5fcmVuZGVyVGFza1F1ZXVlLmNsZWFyKCksdGhpcy5fZnJhbWVJZD1udWxsLHRoaXMuc2V0U3R5bGUobnVsbCksdm9pZCAwIT09dC5kZWZhdWx0JiYodC5kZWZhdWx0LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIix0aGlzLl9vbldpbmRvd1Jlc2l6ZSwhMSksdC5kZWZhdWx0LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJvbmxpbmVcIix0aGlzLl9vbldpbmRvd09ubGluZSwhMSkpO3ZhciBlPXRoaXMucGFpbnRlci5jb250ZXh0LmdsLmdldEV4dGVuc2lvbihcIldFQkdMX2xvc2VfY29udGV4dFwiKTtlJiZlLmxvc2VDb250ZXh0KCksZG4odGhpcy5fY2FudmFzQ29udGFpbmVyKSxkbih0aGlzLl9jb250cm9sQ29udGFpbmVyKSxkbih0aGlzLl9taXNzaW5nQ1NTQ29udGFpbmVyKSx0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLW1hcFwiKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJyZW1vdmVcIikpO30sbi5wcm90b3R5cGUuX3JlcmVuZGVyPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpczt0aGlzLnN0eWxlJiYhdGhpcy5fZnJhbWVJZCYmKHRoaXMuX2ZyYW1lSWQ9ci5mcmFtZShmdW5jdGlvbigpe3QuX2ZyYW1lSWQ9bnVsbCx0Ll9yZW5kZXIoKTt9KSk7fSxuLnByb3RvdHlwZS5fb25XaW5kb3dPbmxpbmU9ZnVuY3Rpb24oKXt0aGlzLl91cGRhdGUoKTt9LG4ucHJvdG90eXBlLl9vbldpbmRvd1Jlc2l6ZT1mdW5jdGlvbigpe3RoaXMuX3RyYWNrUmVzaXplJiZ0aGlzLnN0b3AoKS5yZXNpemUoKS5fdXBkYXRlKCk7fSxvLnNob3dUaWxlQm91bmRhcmllcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX3Nob3dUaWxlQm91bmRhcmllc30sby5zaG93VGlsZUJvdW5kYXJpZXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3Nob3dUaWxlQm91bmRhcmllcyE9PXQmJih0aGlzLl9zaG93VGlsZUJvdW5kYXJpZXM9dCx0aGlzLl91cGRhdGUoKSk7fSxvLnNob3dDb2xsaXNpb25Cb3hlcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX3Nob3dDb2xsaXNpb25Cb3hlc30sby5zaG93Q29sbGlzaW9uQm94ZXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3Nob3dDb2xsaXNpb25Cb3hlcyE9PXQmJih0aGlzLl9zaG93Q29sbGlzaW9uQm94ZXM9dCx0P3RoaXMuc3R5bGUuX2dlbmVyYXRlQ29sbGlzaW9uQm94ZXMoKTp0aGlzLl91cGRhdGUoKSk7fSxvLnNob3dPdmVyZHJhd0luc3BlY3Rvci5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3Rvcn0sby5zaG93T3ZlcmRyYXdJbnNwZWN0b3Iuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3RvciE9PXQmJih0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3I9dCx0aGlzLl91cGRhdGUoKSk7fSxvLnJlcGFpbnQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuISF0aGlzLl9yZXBhaW50fSxvLnJlcGFpbnQuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3JlcGFpbnQ9dCx0aGlzLl91cGRhdGUoKTt9LG8udmVydGljZXMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuISF0aGlzLl92ZXJ0aWNlc30sby52ZXJ0aWNlcy5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fdmVydGljZXM9dCx0aGlzLl91cGRhdGUoKTt9LG4ucHJvdG90eXBlLl9vbkRhdGE9ZnVuY3Rpb24oZSl7dGhpcy5fdXBkYXRlKFwic3R5bGVcIj09PWUuZGF0YVR5cGUpLHRoaXMuZmlyZShuZXcgdC5FdmVudChlLmRhdGFUeXBlK1wiZGF0YVwiLGUpKTt9LG4ucHJvdG90eXBlLl9vbkRhdGFMb2FkaW5nPWZ1bmN0aW9uKGUpe3RoaXMuZmlyZShuZXcgdC5FdmVudChlLmRhdGFUeXBlK1wiZGF0YWxvYWRpbmdcIixlKSk7fSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhuLnByb3RvdHlwZSxvKSxufShybik7ZnVuY3Rpb24gZG4odCl7dC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodCk7fXZhciBmbj17c2hvd0NvbXBhc3M6ITAsc2hvd1pvb206ITB9LG1uPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXM7dGhpcy5vcHRpb25zPXQuZXh0ZW5kKHt9LGZuLGUpLHRoaXMuX2NvbnRhaW5lcj1zLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtY3RybCBtYXBib3hnbC1jdHJsLWdyb3VwXCIpLHRoaXMuX2NvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKFwiY29udGV4dG1lbnVcIixmdW5jdGlvbih0KXtyZXR1cm4gdC5wcmV2ZW50RGVmYXVsdCgpfSksdGhpcy5vcHRpb25zLnNob3dab29tJiYodGhpcy5fem9vbUluQnV0dG9uPXRoaXMuX2NyZWF0ZUJ1dHRvbihcIm1hcGJveGdsLWN0cmwtaWNvbiBtYXBib3hnbC1jdHJsLXpvb20taW5cIixcIlpvb20gSW5cIixmdW5jdGlvbigpe3JldHVybiBpLl9tYXAuem9vbUluKCl9KSx0aGlzLl96b29tT3V0QnV0dG9uPXRoaXMuX2NyZWF0ZUJ1dHRvbihcIm1hcGJveGdsLWN0cmwtaWNvbiBtYXBib3hnbC1jdHJsLXpvb20tb3V0XCIsXCJab29tIE91dFwiLGZ1bmN0aW9uKCl7cmV0dXJuIGkuX21hcC56b29tT3V0KCl9KSksdGhpcy5vcHRpb25zLnNob3dDb21wYXNzJiYodC5iaW5kQWxsKFtcIl9yb3RhdGVDb21wYXNzQXJyb3dcIl0sdGhpcyksdGhpcy5fY29tcGFzcz10aGlzLl9jcmVhdGVCdXR0b24oXCJtYXBib3hnbC1jdHJsLWljb24gbWFwYm94Z2wtY3RybC1jb21wYXNzXCIsXCJSZXNldCBOb3J0aFwiLGZ1bmN0aW9uKCl7cmV0dXJuIGkuX21hcC5yZXNldE5vcnRoKCl9KSx0aGlzLl9jb21wYXNzQXJyb3c9cy5jcmVhdGUoXCJzcGFuXCIsXCJtYXBib3hnbC1jdHJsLWNvbXBhc3MtYXJyb3dcIix0aGlzLl9jb21wYXNzKSk7fTtmdW5jdGlvbiBfbih0LGUsaSl7aWYodD1uZXcgVyh0LmxuZyx0LmxhdCksZSl7dmFyIG49bmV3IFcodC5sbmctMzYwLHQubGF0KSxvPW5ldyBXKHQubG5nKzM2MCx0LmxhdCkscj1pLmxvY2F0aW9uUG9pbnQodCkuZGlzdFNxcihlKTtpLmxvY2F0aW9uUG9pbnQobikuZGlzdFNxcihlKTxyP3Q9bjppLmxvY2F0aW9uUG9pbnQobykuZGlzdFNxcihlKTxyJiYodD1vKTt9Zm9yKDtNYXRoLmFicyh0LmxuZy1pLmNlbnRlci5sbmcpPjE4MDspe3ZhciBhPWkubG9jYXRpb25Qb2ludCh0KTtpZihhLng+PTAmJmEueT49MCYmYS54PD1pLndpZHRoJiZhLnk8PWkuaGVpZ2h0KWJyZWFrO3QubG5nPmkuY2VudGVyLmxuZz90LmxuZy09MzYwOnQubG5nKz0zNjA7fXJldHVybiB0fW1uLnByb3RvdHlwZS5fcm90YXRlQ29tcGFzc0Fycm93PWZ1bmN0aW9uKCl7dmFyIHQ9XCJyb3RhdGUoXCIrdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSooMTgwL01hdGguUEkpK1wiZGVnKVwiO3RoaXMuX2NvbXBhc3NBcnJvdy5zdHlsZS50cmFuc2Zvcm09dDt9LG1uLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbWFwPXQsdGhpcy5vcHRpb25zLnNob3dDb21wYXNzJiYodGhpcy5fbWFwLm9uKFwicm90YXRlXCIsdGhpcy5fcm90YXRlQ29tcGFzc0Fycm93KSx0aGlzLl9yb3RhdGVDb21wYXNzQXJyb3coKSx0aGlzLl9oYW5kbGVyPW5ldyBIaSh0LHtidXR0b246XCJsZWZ0XCIsZWxlbWVudDp0aGlzLl9jb21wYXNzfSksdGhpcy5faGFuZGxlci5lbmFibGUoKSksdGhpcy5fY29udGFpbmVyfSxtbi5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXtzLnJlbW92ZSh0aGlzLl9jb250YWluZXIpLHRoaXMub3B0aW9ucy5zaG93Q29tcGFzcyYmKHRoaXMuX21hcC5vZmYoXCJyb3RhdGVcIix0aGlzLl9yb3RhdGVDb21wYXNzQXJyb3cpLHRoaXMuX2hhbmRsZXIuZGlzYWJsZSgpLGRlbGV0ZSB0aGlzLl9oYW5kbGVyKSxkZWxldGUgdGhpcy5fbWFwO30sbW4ucHJvdG90eXBlLl9jcmVhdGVCdXR0b249ZnVuY3Rpb24odCxlLGkpe3ZhciBuPXMuY3JlYXRlKFwiYnV0dG9uXCIsdCx0aGlzLl9jb250YWluZXIpO3JldHVybiBuLnR5cGU9XCJidXR0b25cIixuLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIixlKSxuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLGkpLG59O3ZhciBnbj17Y2VudGVyOlwidHJhbnNsYXRlKC01MCUsLTUwJSlcIix0b3A6XCJ0cmFuc2xhdGUoLTUwJSwwKVwiLFwidG9wLWxlZnRcIjpcInRyYW5zbGF0ZSgwLDApXCIsXCJ0b3AtcmlnaHRcIjpcInRyYW5zbGF0ZSgtMTAwJSwwKVwiLGJvdHRvbTpcInRyYW5zbGF0ZSgtNTAlLC0xMDAlKVwiLFwiYm90dG9tLWxlZnRcIjpcInRyYW5zbGF0ZSgwLC0xMDAlKVwiLFwiYm90dG9tLXJpZ2h0XCI6XCJ0cmFuc2xhdGUoLTEwMCUsLTEwMCUpXCIsbGVmdDpcInRyYW5zbGF0ZSgwLC01MCUpXCIscmlnaHQ6XCJ0cmFuc2xhdGUoLTEwMCUsLTUwJSlcIn07ZnVuY3Rpb24gdm4odCxlLGkpe3ZhciBuPXQuY2xhc3NMaXN0O2Zvcih2YXIgbyBpbiBnbiluLnJlbW92ZShcIm1hcGJveGdsLVwiK2krXCItYW5jaG9yLVwiK28pO24uYWRkKFwibWFwYm94Z2wtXCIraStcIi1hbmNob3ItXCIrZSk7fXZhciB5bj1mdW5jdGlvbihlKXtpZigoYXJndW1lbnRzWzBdaW5zdGFuY2VvZiB0LmRlZmF1bHQuSFRNTEVsZW1lbnR8fDI9PT1hcmd1bWVudHMubGVuZ3RoKSYmKGU9dC5leHRlbmQoe2VsZW1lbnQ6ZX0sYXJndW1lbnRzWzFdKSksdC5iaW5kQWxsKFtcIl91cGRhdGVcIixcIl9vbk1hcENsaWNrXCJdLHRoaXMpLHRoaXMuX2FuY2hvcj1lJiZlLmFuY2hvcnx8XCJjZW50ZXJcIix0aGlzLl9jb2xvcj1lJiZlLmNvbG9yfHxcIiMzRkIxQ0VcIixlJiZlLmVsZW1lbnQpdGhpcy5fZWxlbWVudD1lLmVsZW1lbnQsdGhpcy5fb2Zmc2V0PXQuZGVmYXVsdCQxLmNvbnZlcnQoZSYmZS5vZmZzZXR8fFswLDBdKTtlbHNle3RoaXMuX2RlZmF1bHRNYXJrZXI9ITAsdGhpcy5fZWxlbWVudD1zLmNyZWF0ZShcImRpdlwiKTt2YXIgaT1zLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcInN2Z1wiKTtpLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJoZWlnaHRcIixcIjQxcHhcIiksaS5zZXRBdHRyaWJ1dGVOUyhudWxsLFwid2lkdGhcIixcIjI3cHhcIiksaS5zZXRBdHRyaWJ1dGVOUyhudWxsLFwidmlld0JveFwiLFwiMCAwIDI3IDQxXCIpO3ZhciBuPXMuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZ1wiKTtuLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJzdHJva2VcIixcIm5vbmVcIiksbi5zZXRBdHRyaWJ1dGVOUyhudWxsLFwic3Ryb2tlLXdpZHRoXCIsXCIxXCIpLG4uc2V0QXR0cmlidXRlTlMobnVsbCxcImZpbGxcIixcIm5vbmVcIiksbi5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbC1ydWxlXCIsXCJldmVub2RkXCIpO3ZhciBvPXMuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZ1wiKTtvLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsLXJ1bGVcIixcIm5vbnplcm9cIik7dmFyIHI9cy5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO3Iuc2V0QXR0cmlidXRlTlMobnVsbCxcInRyYW5zZm9ybVwiLFwidHJhbnNsYXRlKDMuMCwgMjkuMClcIiksci5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLFwiIzAwMDAwMFwiKTtmb3IodmFyIGE9MCxsPVt7cng6XCIxMC41XCIscnk6XCI1LjI1MDAyMjczXCJ9LHtyeDpcIjEwLjVcIixyeTpcIjUuMjUwMDIyNzNcIn0se3J4OlwiOS41XCIscnk6XCI0Ljc3Mjc1MDA3XCJ9LHtyeDpcIjguNVwiLHJ5OlwiNC4yOTU0OTkzNlwifSx7cng6XCI3LjVcIixyeTpcIjMuODE4MjIzMDhcIn0se3J4OlwiNi41XCIscnk6XCIzLjM0MDk0Njc5XCJ9LHtyeDpcIjUuNVwiLHJ5OlwiMi44NjM2NzA1MVwifSx7cng6XCI0LjVcIixyeTpcIjIuMzg2MzY4NjRcIn1dO2E8bC5sZW5ndGg7YSs9MSl7dmFyIGM9bFthXSx1PXMuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZWxsaXBzZVwiKTt1LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJvcGFjaXR5XCIsXCIwLjA0XCIpLHUuc2V0QXR0cmlidXRlTlMobnVsbCxcImN4XCIsXCIxMC41XCIpLHUuc2V0QXR0cmlidXRlTlMobnVsbCxcImN5XCIsXCI1LjgwMDI5MDA4XCIpLHUuc2V0QXR0cmlidXRlTlMobnVsbCxcInJ4XCIsYy5yeCksdS5zZXRBdHRyaWJ1dGVOUyhudWxsLFwicnlcIixjLnJ5KSxyLmFwcGVuZENoaWxkKHUpO312YXIgaD1zLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcImdcIik7aC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLHRoaXMuX2NvbG9yKTt2YXIgcD1zLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcInBhdGhcIik7cC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZFwiLFwiTTI3LDEzLjUgQzI3LDE5LjA3NDY0NCAyMC4yNTAwMDEsMjcuMDAwMDAyIDE0Ljc1LDM0LjUwMDAwMiBDMTQuMDE2NjY1LDM1LjUwMDAwNCAxMi45ODMzMzUsMzUuNTAwMDA0IDEyLjI1LDM0LjUwMDAwMiBDNi43NDk5OTkzLDI3LjAwMDAwMiAwLDE5LjIyMjU2MiAwLDEzLjUgQzAsNi4wNDQxNTU5IDYuMDQ0MTU1OSwwIDEzLjUsMCBDMjAuOTU1ODQ0LDAgMjcsNi4wNDQxNTU5IDI3LDEzLjUgWlwiKSxoLmFwcGVuZENoaWxkKHApO3ZhciBkPXMuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZ1wiKTtkLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJvcGFjaXR5XCIsXCIwLjI1XCIpLGQuc2V0QXR0cmlidXRlTlMobnVsbCxcImZpbGxcIixcIiMwMDAwMDBcIik7dmFyIGY9cy5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJwYXRoXCIpO2Yuc2V0QXR0cmlidXRlTlMobnVsbCxcImRcIixcIk0xMy41LDAgQzYuMDQ0MTU1OSwwIDAsNi4wNDQxNTU5IDAsMTMuNSBDMCwxOS4yMjI1NjIgNi43NDk5OTkzLDI3IDEyLjI1LDM0LjUgQzEzLDM1LjUyMjcyNyAxNC4wMTY2NjQsMzUuNTAwMDA0IDE0Ljc1LDM0LjUgQzIwLjI1MDAwMSwyNyAyNywxOS4wNzQ2NDQgMjcsMTMuNSBDMjcsNi4wNDQxNTU5IDIwLjk1NTg0NCwwIDEzLjUsMCBaIE0xMy41LDEgQzIwLjQxNTQwNCwxIDI2LDYuNTg0NTk2IDI2LDEzLjUgQzI2LDE1Ljg5ODY1NyAyNC40OTU1ODQsMTkuMTgxNDMxIDIyLjIyMDcwMywyMi43MzgyODEgQzE5Ljk0NTgyMywyNi4yOTUxMzIgMTYuNzA1MTE5LDMwLjE0MjE2NyAxMy45NDMzNTksMzMuOTA4MjAzIEMxMy43NDM0NDUsMzQuMTgwODE0IDEzLjYxMjcxNSwzNC4zMjI3MzggMTMuNSwzNC40NDE0MDYgQzEzLjM4NzI4NSwzNC4zMjI3MzggMTMuMjU2NTU1LDM0LjE4MDgxNCAxMy4wNTY2NDEsMzMuOTA4MjAzIEMxMC4yODQ0ODEsMzAuMTI3OTg1IDcuNDE0ODY4NCwyNi4zMTQxNTkgNS4wMTU2MjUsMjIuNzczNDM4IEMyLjYxNjM4MTYsMTkuMjMyNzE1IDEsMTUuOTUzNTM4IDEsMTMuNSBDMSw2LjU4NDU5NiA2LjU4NDU5NiwxIDEzLjUsMSBaXCIpLGQuYXBwZW5kQ2hpbGQoZik7dmFyIG09cy5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO20uc2V0QXR0cmlidXRlTlMobnVsbCxcInRyYW5zZm9ybVwiLFwidHJhbnNsYXRlKDYuMCwgNy4wKVwiKSxtLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsXCIsXCIjRkZGRkZGXCIpO3ZhciBfPXMuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZ1wiKTtfLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJ0cmFuc2Zvcm1cIixcInRyYW5zbGF0ZSg4LjAsIDguMClcIik7dmFyIGc9cy5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJjaXJjbGVcIik7Zy5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLFwiIzAwMDAwMFwiKSxnLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJvcGFjaXR5XCIsXCIwLjI1XCIpLGcuc2V0QXR0cmlidXRlTlMobnVsbCxcImN4XCIsXCI1LjVcIiksZy5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiY3lcIixcIjUuNVwiKSxnLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJyXCIsXCI1LjQ5OTk5NjJcIik7dmFyIHY9cy5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJjaXJjbGVcIik7di5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLFwiI0ZGRkZGRlwiKSx2LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJjeFwiLFwiNS41XCIpLHYuc2V0QXR0cmlidXRlTlMobnVsbCxcImN5XCIsXCI1LjVcIiksdi5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiclwiLFwiNS40OTk5OTYyXCIpLF8uYXBwZW5kQ2hpbGQoZyksXy5hcHBlbmRDaGlsZCh2KSxvLmFwcGVuZENoaWxkKHIpLG8uYXBwZW5kQ2hpbGQoaCksby5hcHBlbmRDaGlsZChkKSxvLmFwcGVuZENoaWxkKG0pLG8uYXBwZW5kQ2hpbGQoXyksaS5hcHBlbmRDaGlsZChvKSx0aGlzLl9lbGVtZW50LmFwcGVuZENoaWxkKGkpLHRoaXMuX29mZnNldD10LmRlZmF1bHQkMS5jb252ZXJ0KGUmJmUub2Zmc2V0fHxbMCwtMTRdKTt9dGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtbWFya2VyXCIpLHRoaXMuX3BvcHVwPW51bGw7fTt5bi5wcm90b3R5cGUuYWRkVG89ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucmVtb3ZlKCksdGhpcy5fbWFwPXQsdC5nZXRDYW52YXNDb250YWluZXIoKS5hcHBlbmRDaGlsZCh0aGlzLl9lbGVtZW50KSx0Lm9uKFwibW92ZVwiLHRoaXMuX3VwZGF0ZSksdC5vbihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGUpLHRoaXMuX3VwZGF0ZSgpLHRoaXMuX21hcC5vbihcImNsaWNrXCIsdGhpcy5fb25NYXBDbGljayksdGhpc30seW4ucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9tYXAmJih0aGlzLl9tYXAub2ZmKFwiY2xpY2tcIix0aGlzLl9vbk1hcENsaWNrKSx0aGlzLl9tYXAub2ZmKFwibW92ZVwiLHRoaXMuX3VwZGF0ZSksdGhpcy5fbWFwLm9mZihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGUpLGRlbGV0ZSB0aGlzLl9tYXApLHMucmVtb3ZlKHRoaXMuX2VsZW1lbnQpLHRoaXMuX3BvcHVwJiZ0aGlzLl9wb3B1cC5yZW1vdmUoKSx0aGlzfSx5bi5wcm90b3R5cGUuZ2V0TG5nTGF0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2xuZ0xhdH0seW4ucHJvdG90eXBlLnNldExuZ0xhdD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbG5nTGF0PVcuY29udmVydCh0KSx0aGlzLl9wb3M9bnVsbCx0aGlzLl9wb3B1cCYmdGhpcy5fcG9wdXAuc2V0TG5nTGF0KHRoaXMuX2xuZ0xhdCksdGhpcy5fdXBkYXRlKCksdGhpc30seW4ucHJvdG90eXBlLmdldEVsZW1lbnQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZWxlbWVudH0seW4ucHJvdG90eXBlLnNldFBvcHVwPWZ1bmN0aW9uKHQpe2lmKHRoaXMuX3BvcHVwJiYodGhpcy5fcG9wdXAucmVtb3ZlKCksdGhpcy5fcG9wdXA9bnVsbCksdCl7aWYoIShcIm9mZnNldFwiaW4gdC5vcHRpb25zKSl7dmFyIGU9TWF0aC5zcXJ0KE1hdGgucG93KDEzLjUsMikvMik7dC5vcHRpb25zLm9mZnNldD10aGlzLl9kZWZhdWx0TWFya2VyP3t0b3A6WzAsMF0sXCJ0b3AtbGVmdFwiOlswLDBdLFwidG9wLXJpZ2h0XCI6WzAsMF0sYm90dG9tOlswLC0zOC4xXSxcImJvdHRvbS1sZWZ0XCI6W2UsLTEqKDI0LjYrZSldLFwiYm90dG9tLXJpZ2h0XCI6Wy1lLC0xKigyNC42K2UpXSxsZWZ0OlsxMy41LC0yNC42XSxyaWdodDpbLTEzLjUsLTI0LjZdfTp0aGlzLl9vZmZzZXQ7fXRoaXMuX3BvcHVwPXQsdGhpcy5fbG5nTGF0JiZ0aGlzLl9wb3B1cC5zZXRMbmdMYXQodGhpcy5fbG5nTGF0KTt9cmV0dXJuIHRoaXN9LHluLnByb3RvdHlwZS5fb25NYXBDbGljaz1mdW5jdGlvbih0KXt2YXIgZT10Lm9yaWdpbmFsRXZlbnQudGFyZ2V0LGk9dGhpcy5fZWxlbWVudDt0aGlzLl9wb3B1cCYmKGU9PT1pfHxpLmNvbnRhaW5zKGUpKSYmdGhpcy50b2dnbGVQb3B1cCgpO30seW4ucHJvdG90eXBlLmdldFBvcHVwPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3BvcHVwfSx5bi5wcm90b3R5cGUudG9nZ2xlUG9wdXA9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLl9wb3B1cDtyZXR1cm4gdD8odC5pc09wZW4oKT90LnJlbW92ZSgpOnQuYWRkVG8odGhpcy5fbWFwKSx0aGlzKTp0aGlzfSx5bi5wcm90b3R5cGUuX3VwZGF0ZT1mdW5jdGlvbih0KXt0aGlzLl9tYXAmJih0aGlzLl9tYXAudHJhbnNmb3JtLnJlbmRlcldvcmxkQ29waWVzJiYodGhpcy5fbG5nTGF0PV9uKHRoaXMuX2xuZ0xhdCx0aGlzLl9wb3MsdGhpcy5fbWFwLnRyYW5zZm9ybSkpLHRoaXMuX3Bvcz10aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sbmdMYXQpLl9hZGQodGhpcy5fb2Zmc2V0KSx0JiZcIm1vdmVlbmRcIiE9PXQudHlwZXx8KHRoaXMuX3Bvcz10aGlzLl9wb3Mucm91bmQoKSkscy5zZXRUcmFuc2Zvcm0odGhpcy5fZWxlbWVudCxnblt0aGlzLl9hbmNob3JdK1wiIHRyYW5zbGF0ZShcIit0aGlzLl9wb3MueCtcInB4LCBcIit0aGlzLl9wb3MueStcInB4KVwiKSx2bih0aGlzLl9lbGVtZW50LHRoaXMuX2FuY2hvcixcIm1hcmtlclwiKSk7fSx5bi5wcm90b3R5cGUuZ2V0T2Zmc2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX29mZnNldH0seW4ucHJvdG90eXBlLnNldE9mZnNldD1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5fb2Zmc2V0PXQuZGVmYXVsdCQxLmNvbnZlcnQoZSksdGhpcy5fdXBkYXRlKCksdGhpc307dmFyIHhuLGJuPXtwb3NpdGlvbk9wdGlvbnM6e2VuYWJsZUhpZ2hBY2N1cmFjeTohMSxtYXhpbXVtQWdlOjAsdGltZW91dDo2ZTN9LGZpdEJvdW5kc09wdGlvbnM6e21heFpvb206MTV9LHRyYWNrVXNlckxvY2F0aW9uOiExLHNob3dVc2VyTG9jYXRpb246ITB9O3ZhciB3bj1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGkpe2UuY2FsbCh0aGlzKSx0aGlzLm9wdGlvbnM9dC5leHRlbmQoe30sYm4saSksdC5iaW5kQWxsKFtcIl9vblN1Y2Nlc3NcIixcIl9vbkVycm9yXCIsXCJfZmluaXNoXCIsXCJfc2V0dXBVSVwiLFwiX3VwZGF0ZUNhbWVyYVwiLFwiX3VwZGF0ZU1hcmtlclwiXSx0aGlzKTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKGUpe3ZhciBpO3JldHVybiB0aGlzLl9tYXA9ZSx0aGlzLl9jb250YWluZXI9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWN0cmwgbWFwYm94Z2wtY3RybC1ncm91cFwiKSxpPXRoaXMuX3NldHVwVUksdm9pZCAwIT09eG4/aSh4bik6dm9pZCAwIT09dC5kZWZhdWx0Lm5hdmlnYXRvci5wZXJtaXNzaW9ucz90LmRlZmF1bHQubmF2aWdhdG9yLnBlcm1pc3Npb25zLnF1ZXJ5KHtuYW1lOlwiZ2VvbG9jYXRpb25cIn0pLnRoZW4oZnVuY3Rpb24odCl7eG49XCJkZW5pZWRcIiE9PXQuc3RhdGUsaSh4bik7fSk6KHhuPSEhdC5kZWZhdWx0Lm5hdmlnYXRvci5nZW9sb2NhdGlvbixpKHhuKSksdGhpcy5fY29udGFpbmVyfSxpLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe3ZvaWQgMCE9PXRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRCYmKHQuZGVmYXVsdC5uYXZpZ2F0b3IuZ2VvbG9jYXRpb24uY2xlYXJXYXRjaCh0aGlzLl9nZW9sb2NhdGlvbldhdGNoSUQpLHRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRD12b2lkIDApLHRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZ0aGlzLl91c2VyTG9jYXRpb25Eb3RNYXJrZXIucmVtb3ZlKCkscy5yZW1vdmUodGhpcy5fY29udGFpbmVyKSx0aGlzLl9tYXA9dm9pZCAwO30saS5wcm90b3R5cGUuX29uU3VjY2Vzcz1mdW5jdGlvbihlKXtpZih0aGlzLm9wdGlvbnMudHJhY2tVc2VyTG9jYXRpb24pc3dpdGNoKHRoaXMuX2xhc3RLbm93blBvc2l0aW9uPWUsdGhpcy5fd2F0Y2hTdGF0ZSl7Y2FzZVwiV0FJVElOR19BQ1RJVkVcIjpjYXNlXCJBQ1RJVkVfTE9DS1wiOmNhc2VcIkFDVElWRV9FUlJPUlwiOnRoaXMuX3dhdGNoU3RhdGU9XCJBQ1RJVkVfTE9DS1wiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZS1lcnJvclwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKTticmVhaztjYXNlXCJCQUNLR1JPVU5EXCI6Y2FzZVwiQkFDS0dST1VORF9FUlJPUlwiOnRoaXMuX3dhdGNoU3RhdGU9XCJCQUNLR1JPVU5EXCIsdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS13YWl0aW5nXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZC1lcnJvclwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIik7fXRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZcIk9GRlwiIT09dGhpcy5fd2F0Y2hTdGF0ZSYmdGhpcy5fdXBkYXRlTWFya2VyKGUpLHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbiYmXCJBQ1RJVkVfTE9DS1wiIT09dGhpcy5fd2F0Y2hTdGF0ZXx8dGhpcy5fdXBkYXRlQ2FtZXJhKGUpLHRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZ0aGlzLl9kb3RFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC11c2VyLWxvY2F0aW9uLWRvdC1zdGFsZVwiKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJnZW9sb2NhdGVcIixlKSksdGhpcy5fZmluaXNoKCk7fSxpLnByb3RvdHlwZS5fdXBkYXRlQ2FtZXJhPWZ1bmN0aW9uKHQpe3ZhciBlPW5ldyBXKHQuY29vcmRzLmxvbmdpdHVkZSx0LmNvb3Jkcy5sYXRpdHVkZSksaT10LmNvb3Jkcy5hY2N1cmFjeTt0aGlzLl9tYXAuZml0Qm91bmRzKGUudG9Cb3VuZHMoaSksdGhpcy5vcHRpb25zLmZpdEJvdW5kc09wdGlvbnMse2dlb2xvY2F0ZVNvdXJjZTohMH0pO30saS5wcm90b3R5cGUuX3VwZGF0ZU1hcmtlcj1mdW5jdGlvbih0KXt0P3RoaXMuX3VzZXJMb2NhdGlvbkRvdE1hcmtlci5zZXRMbmdMYXQoW3QuY29vcmRzLmxvbmdpdHVkZSx0LmNvb3Jkcy5sYXRpdHVkZV0pLmFkZFRvKHRoaXMuX21hcCk6dGhpcy5fdXNlckxvY2F0aW9uRG90TWFya2VyLnJlbW92ZSgpO30saS5wcm90b3R5cGUuX29uRXJyb3I9ZnVuY3Rpb24oZSl7aWYodGhpcy5vcHRpb25zLnRyYWNrVXNlckxvY2F0aW9uKWlmKDE9PT1lLmNvZGUpdGhpcy5fd2F0Y2hTdGF0ZT1cIk9GRlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZS1lcnJvclwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHZvaWQgMCE9PXRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRCYmdGhpcy5fY2xlYXJXYXRjaCgpO2Vsc2Ugc3dpdGNoKHRoaXMuX3dhdGNoU3RhdGUpe2Nhc2VcIldBSVRJTkdfQUNUSVZFXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9FUlJPUlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpO2JyZWFrO2Nhc2VcIkFDVElWRV9MT0NLXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9FUlJPUlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKTticmVhaztjYXNlXCJCQUNLR1JPVU5EXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkJBQ0tHUk9VTkRfRVJST1JcIix0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKTt9XCJPRkZcIiE9PXRoaXMuX3dhdGNoU3RhdGUmJnRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZ0aGlzLl9kb3RFbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC11c2VyLWxvY2F0aW9uLWRvdC1zdGFsZVwiKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJlcnJvclwiLGUpKSx0aGlzLl9maW5pc2goKTt9LGkucHJvdG90eXBlLl9maW5pc2g9ZnVuY3Rpb24oKXt0aGlzLl90aW1lb3V0SWQmJmNsZWFyVGltZW91dCh0aGlzLl90aW1lb3V0SWQpLHRoaXMuX3RpbWVvdXRJZD12b2lkIDA7fSxpLnByb3RvdHlwZS5fc2V0dXBVST1mdW5jdGlvbihlKXt2YXIgaT10aGlzOyExIT09ZSYmKHRoaXMuX2NvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKFwiY29udGV4dG1lbnVcIixmdW5jdGlvbih0KXtyZXR1cm4gdC5wcmV2ZW50RGVmYXVsdCgpfSksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uPXMuY3JlYXRlKFwiYnV0dG9uXCIsXCJtYXBib3hnbC1jdHJsLWljb24gbWFwYm94Z2wtY3RybC1nZW9sb2NhdGVcIix0aGlzLl9jb250YWluZXIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi50eXBlPVwiYnV0dG9uXCIsdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIixcIkdlb2xvY2F0ZVwiKSx0aGlzLm9wdGlvbnMudHJhY2tVc2VyTG9jYXRpb24mJih0aGlzLl9nZW9sb2NhdGVCdXR0b24uc2V0QXR0cmlidXRlKFwiYXJpYS1wcmVzc2VkXCIsXCJmYWxzZVwiKSx0aGlzLl93YXRjaFN0YXRlPVwiT0ZGXCIpLHRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiYodGhpcy5fZG90RWxlbWVudD1zLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtdXNlci1sb2NhdGlvbi1kb3RcIiksdGhpcy5fdXNlckxvY2F0aW9uRG90TWFya2VyPW5ldyB5bih0aGlzLl9kb3RFbGVtZW50KSx0aGlzLm9wdGlvbnMudHJhY2tVc2VyTG9jYXRpb24mJih0aGlzLl93YXRjaFN0YXRlPVwiT0ZGXCIpKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsdGhpcy50cmlnZ2VyLmJpbmQodGhpcykpLHRoaXMuX3NldHVwPSEwLHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbiYmdGhpcy5fbWFwLm9uKFwibW92ZXN0YXJ0XCIsZnVuY3Rpb24oZSl7ZS5nZW9sb2NhdGVTb3VyY2V8fFwiQUNUSVZFX0xPQ0tcIiE9PWkuX3dhdGNoU3RhdGV8fChpLl93YXRjaFN0YXRlPVwiQkFDS0dST1VORFwiLGkuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZFwiKSxpLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKSxpLmZpcmUobmV3IHQuRXZlbnQoXCJ0cmFja3VzZXJsb2NhdGlvbmVuZFwiKSkpO30pKTt9LGkucHJvdG90eXBlLnRyaWdnZXI9ZnVuY3Rpb24oKXtpZighdGhpcy5fc2V0dXApcmV0dXJuIHQud2Fybk9uY2UoXCJHZW9sb2NhdGUgY29udHJvbCB0cmlnZ2VyZWQgYmVmb3JlIGFkZGVkIHRvIGEgbWFwXCIpLCExO2lmKHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbil7c3dpdGNoKHRoaXMuX3dhdGNoU3RhdGUpe2Nhc2VcIk9GRlwiOnRoaXMuX3dhdGNoU3RhdGU9XCJXQUlUSU5HX0FDVElWRVwiLHRoaXMuZmlyZShuZXcgdC5FdmVudChcInRyYWNrdXNlcmxvY2F0aW9uc3RhcnRcIikpO2JyZWFrO2Nhc2VcIldBSVRJTkdfQUNUSVZFXCI6Y2FzZVwiQUNUSVZFX0xPQ0tcIjpjYXNlXCJBQ1RJVkVfRVJST1JcIjpjYXNlXCJCQUNLR1JPVU5EX0VSUk9SXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIk9GRlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZS1lcnJvclwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcInRyYWNrdXNlcmxvY2F0aW9uZW5kXCIpKTticmVhaztjYXNlXCJCQUNLR1JPVU5EXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9MT0NLXCIsdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kXCIpLHRoaXMuX2xhc3RLbm93blBvc2l0aW9uJiZ0aGlzLl91cGRhdGVDYW1lcmEodGhpcy5fbGFzdEtub3duUG9zaXRpb24pLHRoaXMuZmlyZShuZXcgdC5FdmVudChcInRyYWNrdXNlcmxvY2F0aW9uc3RhcnRcIikpO31zd2l0Y2godGhpcy5fd2F0Y2hTdGF0ZSl7Y2FzZVwiV0FJVElOR19BQ1RJVkVcIjp0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1hY3RpdmVcIik7YnJlYWs7Y2FzZVwiQUNUSVZFX0xPQ0tcIjp0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKTticmVhaztjYXNlXCJBQ1RJVkVfRVJST1JcIjp0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1hY3RpdmUtZXJyb3JcIik7YnJlYWs7Y2FzZVwiQkFDS0dST1VORFwiOnRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZFwiKTticmVhaztjYXNlXCJCQUNLR1JPVU5EX0VSUk9SXCI6dGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS13YWl0aW5nXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZC1lcnJvclwiKTt9XCJPRkZcIj09PXRoaXMuX3dhdGNoU3RhdGUmJnZvaWQgMCE9PXRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRD90aGlzLl9jbGVhcldhdGNoKCk6dm9pZCAwPT09dGhpcy5fZ2VvbG9jYXRpb25XYXRjaElEJiYodGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS13YWl0aW5nXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5zZXRBdHRyaWJ1dGUoXCJhcmlhLXByZXNzZWRcIixcInRydWVcIiksdGhpcy5fZ2VvbG9jYXRpb25XYXRjaElEPXQuZGVmYXVsdC5uYXZpZ2F0b3IuZ2VvbG9jYXRpb24ud2F0Y2hQb3NpdGlvbih0aGlzLl9vblN1Y2Nlc3MsdGhpcy5fb25FcnJvcix0aGlzLm9wdGlvbnMucG9zaXRpb25PcHRpb25zKSk7fWVsc2UgdC5kZWZhdWx0Lm5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24odGhpcy5fb25TdWNjZXNzLHRoaXMuX29uRXJyb3IsdGhpcy5vcHRpb25zLnBvc2l0aW9uT3B0aW9ucyksdGhpcy5fdGltZW91dElkPXNldFRpbWVvdXQodGhpcy5fZmluaXNoLDFlNCk7cmV0dXJuITB9LGkucHJvdG90eXBlLl9jbGVhcldhdGNoPWZ1bmN0aW9uKCl7dC5kZWZhdWx0Lm5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKHRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRCksdGhpcy5fZ2VvbG9jYXRpb25XYXRjaElEPXZvaWQgMCx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtcHJlc3NlZFwiLFwiZmFsc2VcIiksdGhpcy5vcHRpb25zLnNob3dVc2VyTG9jYXRpb24mJnRoaXMuX3VwZGF0ZU1hcmtlcihudWxsKTt9LGl9KHQuRXZlbnRlZCksRW49e21heFdpZHRoOjEwMCx1bml0OlwibWV0cmljXCJ9LFRuPWZ1bmN0aW9uKGUpe3RoaXMub3B0aW9ucz10LmV4dGVuZCh7fSxFbixlKSx0LmJpbmRBbGwoW1wiX29uTW92ZVwiLFwic2V0VW5pdFwiXSx0aGlzKTt9O2Z1bmN0aW9uIEluKHQsZSxpKXt2YXIgbixvLHIsYSxzLGwsYz1pJiZpLm1heFdpZHRofHwxMDAsdT10Ll9jb250YWluZXIuY2xpZW50SGVpZ2h0LzIsaD0obj10LnVucHJvamVjdChbMCx1XSksbz10LnVucHJvamVjdChbYyx1XSkscj1NYXRoLlBJLzE4MCxhPW4ubGF0KnIscz1vLmxhdCpyLGw9TWF0aC5zaW4oYSkqTWF0aC5zaW4ocykrTWF0aC5jb3MoYSkqTWF0aC5jb3MocykqTWF0aC5jb3MoKG8ubG5nLW4ubG5nKSpyKSw2MzcxZTMqTWF0aC5hY29zKE1hdGgubWluKGwsMSkpKTtpZihpJiZcImltcGVyaWFsXCI9PT1pLnVuaXQpe3ZhciBwPTMuMjgwOCpoO2lmKHA+NTI4MClDbihlLGMscC81MjgwLFwibWlcIik7ZWxzZSBDbihlLGMscCxcImZ0XCIpO31lbHNlIGlmKGkmJlwibmF1dGljYWxcIj09PWkudW5pdCl7Q24oZSxjLGgvMTg1MixcIm5tXCIpO31lbHNlIENuKGUsYyxoLFwibVwiKTt9ZnVuY3Rpb24gQ24odCxlLGksbil7dmFyIG8scixhLHM9KG89aSwocj1NYXRoLnBvdygxMCwoXCJcIitNYXRoLmZsb29yKG8pKS5sZW5ndGgtMSkpKihhPShhPW8vcik+PTEwPzEwOmE+PTU/NTphPj0zPzM6YT49Mj8yOjEpKSxsPXMvaTtcIm1cIj09PW4mJnM+PTFlMyYmKHMvPTFlMyxuPVwia21cIiksdC5zdHlsZS53aWR0aD1lKmwrXCJweFwiLHQuaW5uZXJIVE1MPXMrbjt9VG4ucHJvdG90eXBlLmdldERlZmF1bHRQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVyblwiYm90dG9tLWxlZnRcIn0sVG4ucHJvdG90eXBlLl9vbk1vdmU9ZnVuY3Rpb24oKXtJbih0aGlzLl9tYXAsdGhpcy5fY29udGFpbmVyLHRoaXMub3B0aW9ucyk7fSxUbi5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX21hcD10LHRoaXMuX2NvbnRhaW5lcj1zLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtY3RybCBtYXBib3hnbC1jdHJsLXNjYWxlXCIsdC5nZXRDb250YWluZXIoKSksdGhpcy5fbWFwLm9uKFwibW92ZVwiLHRoaXMuX29uTW92ZSksdGhpcy5fb25Nb3ZlKCksdGhpcy5fY29udGFpbmVyfSxUbi5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXtzLnJlbW92ZSh0aGlzLl9jb250YWluZXIpLHRoaXMuX21hcC5vZmYoXCJtb3ZlXCIsdGhpcy5fb25Nb3ZlKSx0aGlzLl9tYXA9dm9pZCAwO30sVG4ucHJvdG90eXBlLnNldFVuaXQ9ZnVuY3Rpb24odCl7dGhpcy5vcHRpb25zLnVuaXQ9dCxJbih0aGlzLl9tYXAsdGhpcy5fY29udGFpbmVyLHRoaXMub3B0aW9ucyk7fTt2YXIgU249ZnVuY3Rpb24oKXt0aGlzLl9mdWxsc2NyZWVuPSExLHQuYmluZEFsbChbXCJfb25DbGlja0Z1bGxzY3JlZW5cIixcIl9jaGFuZ2VJY29uXCJdLHRoaXMpLFwib25mdWxsc2NyZWVuY2hhbmdlXCJpbiB0LmRlZmF1bHQuZG9jdW1lbnQ/dGhpcy5fZnVsbHNjcmVlbmNoYW5nZT1cImZ1bGxzY3JlZW5jaGFuZ2VcIjpcIm9ubW96ZnVsbHNjcmVlbmNoYW5nZVwiaW4gdC5kZWZhdWx0LmRvY3VtZW50P3RoaXMuX2Z1bGxzY3JlZW5jaGFuZ2U9XCJtb3pmdWxsc2NyZWVuY2hhbmdlXCI6XCJvbndlYmtpdGZ1bGxzY3JlZW5jaGFuZ2VcImluIHQuZGVmYXVsdC5kb2N1bWVudD90aGlzLl9mdWxsc2NyZWVuY2hhbmdlPVwid2Via2l0ZnVsbHNjcmVlbmNoYW5nZVwiOlwib25tc2Z1bGxzY3JlZW5jaGFuZ2VcImluIHQuZGVmYXVsdC5kb2N1bWVudCYmKHRoaXMuX2Z1bGxzY3JlZW5jaGFuZ2U9XCJNU0Z1bGxzY3JlZW5DaGFuZ2VcIiksdGhpcy5fY2xhc3NOYW1lPVwibWFwYm94Z2wtY3RybFwiO307U24ucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLl9tYXA9ZSx0aGlzLl9tYXBDb250YWluZXI9dGhpcy5fbWFwLmdldENvbnRhaW5lcigpLHRoaXMuX2NvbnRhaW5lcj1zLmNyZWF0ZShcImRpdlwiLHRoaXMuX2NsYXNzTmFtZStcIiBtYXBib3hnbC1jdHJsLWdyb3VwXCIpLHRoaXMuX2NoZWNrRnVsbHNjcmVlblN1cHBvcnQoKT90aGlzLl9zZXR1cFVJKCk6KHRoaXMuX2NvbnRhaW5lci5zdHlsZS5kaXNwbGF5PVwibm9uZVwiLHQud2Fybk9uY2UoXCJUaGlzIGRldmljZSBkb2VzIG5vdCBzdXBwb3J0IGZ1bGxzY3JlZW4gbW9kZS5cIikpLHRoaXMuX2NvbnRhaW5lcn0sU24ucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7cy5yZW1vdmUodGhpcy5fY29udGFpbmVyKSx0aGlzLl9tYXA9bnVsbCx0LmRlZmF1bHQuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLl9mdWxsc2NyZWVuY2hhbmdlLHRoaXMuX2NoYW5nZUljb24pO30sU24ucHJvdG90eXBlLl9jaGVja0Z1bGxzY3JlZW5TdXBwb3J0PWZ1bmN0aW9uKCl7cmV0dXJuISEodC5kZWZhdWx0LmRvY3VtZW50LmZ1bGxzY3JlZW5FbmFibGVkfHx0LmRlZmF1bHQuZG9jdW1lbnQubW96RnVsbFNjcmVlbkVuYWJsZWR8fHQuZGVmYXVsdC5kb2N1bWVudC5tc0Z1bGxzY3JlZW5FbmFibGVkfHx0LmRlZmF1bHQuZG9jdW1lbnQud2Via2l0RnVsbHNjcmVlbkVuYWJsZWQpfSxTbi5wcm90b3R5cGUuX3NldHVwVUk9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLl9mdWxsc2NyZWVuQnV0dG9uPXMuY3JlYXRlKFwiYnV0dG9uXCIsdGhpcy5fY2xhc3NOYW1lK1wiLWljb24gXCIrdGhpcy5fY2xhc3NOYW1lK1wiLWZ1bGxzY3JlZW5cIix0aGlzLl9jb250YWluZXIpO2Uuc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLFwiVG9nZ2xlIGZ1bGxzY3JlZW5cIiksZS50eXBlPVwiYnV0dG9uXCIsdGhpcy5fZnVsbHNjcmVlbkJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIix0aGlzLl9vbkNsaWNrRnVsbHNjcmVlbiksdC5kZWZhdWx0LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIodGhpcy5fZnVsbHNjcmVlbmNoYW5nZSx0aGlzLl9jaGFuZ2VJY29uKTt9LFNuLnByb3RvdHlwZS5faXNGdWxsc2NyZWVuPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2Z1bGxzY3JlZW59LFNuLnByb3RvdHlwZS5fY2hhbmdlSWNvbj1mdW5jdGlvbigpeyh0LmRlZmF1bHQuZG9jdW1lbnQuZnVsbHNjcmVlbkVsZW1lbnR8fHQuZGVmYXVsdC5kb2N1bWVudC5tb3pGdWxsU2NyZWVuRWxlbWVudHx8dC5kZWZhdWx0LmRvY3VtZW50LndlYmtpdEZ1bGxzY3JlZW5FbGVtZW50fHx0LmRlZmF1bHQuZG9jdW1lbnQubXNGdWxsc2NyZWVuRWxlbWVudCk9PT10aGlzLl9tYXBDb250YWluZXIhPT10aGlzLl9mdWxsc2NyZWVuJiYodGhpcy5fZnVsbHNjcmVlbj0hdGhpcy5fZnVsbHNjcmVlbix0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUodGhpcy5fY2xhc3NOYW1lK1wiLXNocmlua1wiKSx0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUodGhpcy5fY2xhc3NOYW1lK1wiLWZ1bGxzY3JlZW5cIikpO30sU24ucHJvdG90eXBlLl9vbkNsaWNrRnVsbHNjcmVlbj1mdW5jdGlvbigpe3RoaXMuX2lzRnVsbHNjcmVlbigpP3QuZGVmYXVsdC5kb2N1bWVudC5leGl0RnVsbHNjcmVlbj90LmRlZmF1bHQuZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4oKTp0LmRlZmF1bHQuZG9jdW1lbnQubW96Q2FuY2VsRnVsbFNjcmVlbj90LmRlZmF1bHQuZG9jdW1lbnQubW96Q2FuY2VsRnVsbFNjcmVlbigpOnQuZGVmYXVsdC5kb2N1bWVudC5tc0V4aXRGdWxsc2NyZWVuP3QuZGVmYXVsdC5kb2N1bWVudC5tc0V4aXRGdWxsc2NyZWVuKCk6dC5kZWZhdWx0LmRvY3VtZW50LndlYmtpdENhbmNlbEZ1bGxTY3JlZW4mJnQuZGVmYXVsdC5kb2N1bWVudC53ZWJraXRDYW5jZWxGdWxsU2NyZWVuKCk6dGhpcy5fbWFwQ29udGFpbmVyLnJlcXVlc3RGdWxsc2NyZWVuP3RoaXMuX21hcENvbnRhaW5lci5yZXF1ZXN0RnVsbHNjcmVlbigpOnRoaXMuX21hcENvbnRhaW5lci5tb3pSZXF1ZXN0RnVsbFNjcmVlbj90aGlzLl9tYXBDb250YWluZXIubW96UmVxdWVzdEZ1bGxTY3JlZW4oKTp0aGlzLl9tYXBDb250YWluZXIubXNSZXF1ZXN0RnVsbHNjcmVlbj90aGlzLl9tYXBDb250YWluZXIubXNSZXF1ZXN0RnVsbHNjcmVlbigpOnRoaXMuX21hcENvbnRhaW5lci53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbiYmdGhpcy5fbWFwQ29udGFpbmVyLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKCk7fTt2YXIgem49e2Nsb3NlQnV0dG9uOiEwLGNsb3NlT25DbGljazohMH0sQW49ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpKXtlLmNhbGwodGhpcyksdGhpcy5vcHRpb25zPXQuZXh0ZW5kKE9iamVjdC5jcmVhdGUoem4pLGkpLHQuYmluZEFsbChbXCJfdXBkYXRlXCIsXCJfb25DbGlja0Nsb3NlXCJdLHRoaXMpO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUuYWRkVG89ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuX21hcD1lLHRoaXMuX21hcC5vbihcIm1vdmVcIix0aGlzLl91cGRhdGUpLHRoaXMub3B0aW9ucy5jbG9zZU9uQ2xpY2smJnRoaXMuX21hcC5vbihcImNsaWNrXCIsdGhpcy5fb25DbGlja0Nsb3NlKSx0aGlzLl91cGRhdGUoKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJvcGVuXCIpKSx0aGlzfSxpLnByb3RvdHlwZS5pc09wZW49ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuX21hcH0saS5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbnRlbnQmJnMucmVtb3ZlKHRoaXMuX2NvbnRlbnQpLHRoaXMuX2NvbnRhaW5lciYmKHMucmVtb3ZlKHRoaXMuX2NvbnRhaW5lciksZGVsZXRlIHRoaXMuX2NvbnRhaW5lciksdGhpcy5fbWFwJiYodGhpcy5fbWFwLm9mZihcIm1vdmVcIix0aGlzLl91cGRhdGUpLHRoaXMuX21hcC5vZmYoXCJjbGlja1wiLHRoaXMuX29uQ2xpY2tDbG9zZSksZGVsZXRlIHRoaXMuX21hcCksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiY2xvc2VcIikpLHRoaXN9LGkucHJvdG90eXBlLmdldExuZ0xhdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9sbmdMYXR9LGkucHJvdG90eXBlLnNldExuZ0xhdD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbG5nTGF0PVcuY29udmVydCh0KSx0aGlzLl9wb3M9bnVsbCx0aGlzLl91cGRhdGUoKSx0aGlzfSxpLnByb3RvdHlwZS5zZXRUZXh0PWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLnNldERPTUNvbnRlbnQodC5kZWZhdWx0LmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGUpKX0saS5wcm90b3R5cGUuc2V0SFRNTD1mdW5jdGlvbihlKXt2YXIgaSxuPXQuZGVmYXVsdC5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksbz10LmRlZmF1bHQuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJvZHlcIik7Zm9yKG8uaW5uZXJIVE1MPWU7aT1vLmZpcnN0Q2hpbGQ7KW4uYXBwZW5kQ2hpbGQoaSk7cmV0dXJuIHRoaXMuc2V0RE9NQ29udGVudChuKX0saS5wcm90b3R5cGUuc2V0RE9NQ29udGVudD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fY3JlYXRlQ29udGVudCgpLHRoaXMuX2NvbnRlbnQuYXBwZW5kQ2hpbGQodCksdGhpcy5fdXBkYXRlKCksdGhpc30saS5wcm90b3R5cGUuX2NyZWF0ZUNvbnRlbnQ9ZnVuY3Rpb24oKXt0aGlzLl9jb250ZW50JiZzLnJlbW92ZSh0aGlzLl9jb250ZW50KSx0aGlzLl9jb250ZW50PXMuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1wb3B1cC1jb250ZW50XCIsdGhpcy5fY29udGFpbmVyKSx0aGlzLm9wdGlvbnMuY2xvc2VCdXR0b24mJih0aGlzLl9jbG9zZUJ1dHRvbj1zLmNyZWF0ZShcImJ1dHRvblwiLFwibWFwYm94Z2wtcG9wdXAtY2xvc2UtYnV0dG9uXCIsdGhpcy5fY29udGVudCksdGhpcy5fY2xvc2VCdXR0b24udHlwZT1cImJ1dHRvblwiLHRoaXMuX2Nsb3NlQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIixcIkNsb3NlIHBvcHVwXCIpLHRoaXMuX2Nsb3NlQnV0dG9uLmlubmVySFRNTD1cIiYjMjE1O1wiLHRoaXMuX2Nsb3NlQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLHRoaXMuX29uQ2xpY2tDbG9zZSkpO30saS5wcm90b3R5cGUuX3VwZGF0ZT1mdW5jdGlvbigpe2lmKHRoaXMuX21hcCYmdGhpcy5fbG5nTGF0JiZ0aGlzLl9jb250ZW50KXt0aGlzLl9jb250YWluZXJ8fCh0aGlzLl9jb250YWluZXI9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLXBvcHVwXCIsdGhpcy5fbWFwLmdldENvbnRhaW5lcigpKSx0aGlzLl90aXA9cy5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLXBvcHVwLXRpcFwiLHRoaXMuX2NvbnRhaW5lciksdGhpcy5fY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpKSx0aGlzLl9tYXAudHJhbnNmb3JtLnJlbmRlcldvcmxkQ29waWVzJiYodGhpcy5fbG5nTGF0PV9uKHRoaXMuX2xuZ0xhdCx0aGlzLl9wb3MsdGhpcy5fbWFwLnRyYW5zZm9ybSkpO3ZhciBlPXRoaXMuX3Bvcz10aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sbmdMYXQpLGk9dGhpcy5vcHRpb25zLmFuY2hvcixuPWZ1bmN0aW9uIGUoaSl7aWYoaSl7aWYoXCJudW1iZXJcIj09dHlwZW9mIGkpe3ZhciBuPU1hdGgucm91bmQoTWF0aC5zcXJ0KC41Kk1hdGgucG93KGksMikpKTtyZXR1cm57Y2VudGVyOm5ldyB0LmRlZmF1bHQkMSgwLDApLHRvcDpuZXcgdC5kZWZhdWx0JDEoMCxpKSxcInRvcC1sZWZ0XCI6bmV3IHQuZGVmYXVsdCQxKG4sbiksXCJ0b3AtcmlnaHRcIjpuZXcgdC5kZWZhdWx0JDEoLW4sbiksYm90dG9tOm5ldyB0LmRlZmF1bHQkMSgwLC1pKSxcImJvdHRvbS1sZWZ0XCI6bmV3IHQuZGVmYXVsdCQxKG4sLW4pLFwiYm90dG9tLXJpZ2h0XCI6bmV3IHQuZGVmYXVsdCQxKC1uLC1uKSxsZWZ0Om5ldyB0LmRlZmF1bHQkMShpLDApLHJpZ2h0Om5ldyB0LmRlZmF1bHQkMSgtaSwwKX19aWYoaSBpbnN0YW5jZW9mIHQuZGVmYXVsdCQxfHxBcnJheS5pc0FycmF5KGkpKXt2YXIgbz10LmRlZmF1bHQkMS5jb252ZXJ0KGkpO3JldHVybntjZW50ZXI6byx0b3A6byxcInRvcC1sZWZ0XCI6byxcInRvcC1yaWdodFwiOm8sYm90dG9tOm8sXCJib3R0b20tbGVmdFwiOm8sXCJib3R0b20tcmlnaHRcIjpvLGxlZnQ6byxyaWdodDpvfX1yZXR1cm57Y2VudGVyOnQuZGVmYXVsdCQxLmNvbnZlcnQoaS5jZW50ZXJ8fFswLDBdKSx0b3A6dC5kZWZhdWx0JDEuY29udmVydChpLnRvcHx8WzAsMF0pLFwidG9wLWxlZnRcIjp0LmRlZmF1bHQkMS5jb252ZXJ0KGlbXCJ0b3AtbGVmdFwiXXx8WzAsMF0pLFwidG9wLXJpZ2h0XCI6dC5kZWZhdWx0JDEuY29udmVydChpW1widG9wLXJpZ2h0XCJdfHxbMCwwXSksYm90dG9tOnQuZGVmYXVsdCQxLmNvbnZlcnQoaS5ib3R0b218fFswLDBdKSxcImJvdHRvbS1sZWZ0XCI6dC5kZWZhdWx0JDEuY29udmVydChpW1wiYm90dG9tLWxlZnRcIl18fFswLDBdKSxcImJvdHRvbS1yaWdodFwiOnQuZGVmYXVsdCQxLmNvbnZlcnQoaVtcImJvdHRvbS1yaWdodFwiXXx8WzAsMF0pLGxlZnQ6dC5kZWZhdWx0JDEuY29udmVydChpLmxlZnR8fFswLDBdKSxyaWdodDp0LmRlZmF1bHQkMS5jb252ZXJ0KGkucmlnaHR8fFswLDBdKX19cmV0dXJuIGUobmV3IHQuZGVmYXVsdCQxKDAsMCkpfSh0aGlzLm9wdGlvbnMub2Zmc2V0KTtpZighaSl7dmFyIG8scj10aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsYT10aGlzLl9jb250YWluZXIub2Zmc2V0SGVpZ2h0O289ZS55K24uYm90dG9tLnk8YT9bXCJ0b3BcIl06ZS55PnRoaXMuX21hcC50cmFuc2Zvcm0uaGVpZ2h0LWE/W1wiYm90dG9tXCJdOltdLGUueDxyLzI/by5wdXNoKFwibGVmdFwiKTplLng+dGhpcy5fbWFwLnRyYW5zZm9ybS53aWR0aC1yLzImJm8ucHVzaChcInJpZ2h0XCIpLGk9MD09PW8ubGVuZ3RoP1wiYm90dG9tXCI6by5qb2luKFwiLVwiKTt9dmFyIGw9ZS5hZGQobltpXSkucm91bmQoKTtzLnNldFRyYW5zZm9ybSh0aGlzLl9jb250YWluZXIsZ25baV0rXCIgdHJhbnNsYXRlKFwiK2wueCtcInB4LFwiK2wueStcInB4KVwiKSx2bih0aGlzLl9jb250YWluZXIsaSxcInBvcHVwXCIpO319LGkucHJvdG90eXBlLl9vbkNsaWNrQ2xvc2U9ZnVuY3Rpb24oKXt0aGlzLnJlbW92ZSgpO30saX0odC5FdmVudGVkKTt2YXIgUm49e3ZlcnNpb246XCIwLjQ1LjBcIixzdXBwb3J0ZWQ6ZSx3b3JrZXJDb3VudDpNYXRoLm1heChNYXRoLmZsb29yKHIuaGFyZHdhcmVDb25jdXJyZW5jeS8yKSwxKSxzZXRSVExUZXh0UGx1Z2luOnQuc2V0UlRMVGV4dFBsdWdpbixNYXA6cG4sTmF2aWdhdGlvbkNvbnRyb2w6bW4sR2VvbG9jYXRlQ29udHJvbDp3bixBdHRyaWJ1dGlvbkNvbnRyb2w6YW4sU2NhbGVDb250cm9sOlRuLEZ1bGxzY3JlZW5Db250cm9sOlNuLFBvcHVwOkFuLE1hcmtlcjp5bixTdHlsZTpRZSxMbmdMYXQ6VyxMbmdMYXRCb3VuZHM6cSxQb2ludDp0LmRlZmF1bHQkMSxFdmVudGVkOnQuRXZlbnRlZCxjb25maWc6XyxnZXQgYWNjZXNzVG9rZW4oKXtyZXR1cm4gXy5BQ0NFU1NfVE9LRU59LHNldCBhY2Nlc3NUb2tlbih0KXtfLkFDQ0VTU19UT0tFTj10O30sd29ya2VyVXJsOlwiXCJ9O3JldHVybiBSbn0pO1xuXG4vL1xuXG5yZXR1cm4gbWFwYm94Z2w7XG5cbn0pKSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tYXBib3gtZ2wuanMubWFwXG4iLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUYWJsZVxuXG52YXIgY2h1bGwgPSByZXF1aXJlKCdjb252ZXgtaHVsbCcpXG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFZlcnRleChkLCBhLCBiKSB7XG4gIHZhciB4ID0gbmV3IEFycmF5KGQpXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHhbaV0gPSAwLjBcbiAgICBpZihpID09PSBhKSB7XG4gICAgICB4W2ldICs9IDAuNVxuICAgIH1cbiAgICBpZihpID09PSBiKSB7XG4gICAgICB4W2ldICs9IDAuNVxuICAgIH1cbiAgfVxuICByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3RDZWxsKGRpbWVuc2lvbiwgbWFzaykge1xuICBpZihtYXNrID09PSAwIHx8IG1hc2sgPT09ICgxPDwoZGltZW5zaW9uKzEpKS0xKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIHBvaW50cyA9IFtdXG4gIHZhciBpbmRleCAgPSBbXVxuICBmb3IodmFyIGk9MDsgaTw9ZGltZW5zaW9uOyArK2kpIHtcbiAgICBpZihtYXNrICYgKDE8PGkpKSB7XG4gICAgICBwb2ludHMucHVzaChjb25zdHJ1Y3RWZXJ0ZXgoZGltZW5zaW9uLCBpLTEsIGktMSkpXG4gICAgICBpbmRleC5wdXNoKG51bGwpXG4gICAgICBmb3IodmFyIGo9MDsgajw9ZGltZW5zaW9uOyArK2opIHtcbiAgICAgICAgaWYofm1hc2sgJiAoMTw8aikpIHtcbiAgICAgICAgICBwb2ludHMucHVzaChjb25zdHJ1Y3RWZXJ0ZXgoZGltZW5zaW9uLCBpLTEsIGotMSkpXG4gICAgICAgICAgaW5kZXgucHVzaChbaSxqXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBcbiAgLy9QcmVwcm9jZXNzIHBvaW50cyBzbyBmaXJzdCBkKzEgcG9pbnRzIGFyZSBsaW5lYXJseSBpbmRlcGVuZGVudFxuICB2YXIgaHVsbCA9IGNodWxsKHBvaW50cylcbiAgdmFyIGZhY2VzID0gW11cbmlfbG9vcDpcbiAgZm9yKHZhciBpPTA7IGk8aHVsbC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBmYWNlID0gaHVsbFtpXVxuICAgIHZhciBuZmFjZSA9IFtdXG4gICAgZm9yKHZhciBqPTA7IGo8ZmFjZS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoIWluZGV4W2ZhY2Vbal1dKSB7XG4gICAgICAgIGNvbnRpbnVlIGlfbG9vcFxuICAgICAgfVxuICAgICAgbmZhY2UucHVzaChpbmRleFtmYWNlW2pdXS5zbGljZSgpKVxuICAgIH1cbiAgICBmYWNlcy5wdXNoKG5mYWNlKVxuICB9XG4gIHJldHVybiBmYWNlc1xufVxuXG5mdW5jdGlvbiBjcmVhdGVUYWJsZShkaW1lbnNpb24pIHtcbiAgdmFyIG51bUNlbGxzID0gMTw8KGRpbWVuc2lvbisxKVxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG51bUNlbGxzKVxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gY29uc3RydWN0Q2VsbChkaW1lbnNpb24sIGkpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufSIsIi8qanNoaW50IHVudXNlZDp0cnVlKi9cbi8qXG5JbnB1dDogIG1hdHJpeCAgICAgIDsgYSA0eDQgbWF0cml4XG5PdXRwdXQ6IHRyYW5zbGF0aW9uIDsgYSAzIGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgc2NhbGUgICAgICAgOyBhIDMgY29tcG9uZW50IHZlY3RvclxuICAgICAgICBza2V3ICAgICAgICA7IHNrZXcgZmFjdG9ycyBYWSxYWixZWiByZXByZXNlbnRlZCBhcyBhIDMgY29tcG9uZW50IHZlY3RvclxuICAgICAgICBwZXJzcGVjdGl2ZSA7IGEgNCBjb21wb25lbnQgdmVjdG9yXG4gICAgICAgIHF1YXRlcm5pb24gIDsgYSA0IGNvbXBvbmVudCB2ZWN0b3JcblJldHVybnMgZmFsc2UgaWYgdGhlIG1hdHJpeCBjYW5ub3QgYmUgZGVjb21wb3NlZCwgdHJ1ZSBpZiBpdCBjYW5cblxuXG5SZWZlcmVuY2VzOlxuaHR0cHM6Ly9naXRodWIuY29tL2thbWljYW5lL21hdHJpeDNkL2Jsb2IvbWFzdGVyL2xpYi9NYXRyaXgzZC5qc1xuaHR0cHM6Ly9naXRodWIuY29tL0Nocm9taXVtV2ViQXBwcy9jaHJvbWl1bS9ibG9iL21hc3Rlci91aS9nZngvdHJhbnNmb3JtX3V0aWwuY2Ncbmh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtdHJhbnNmb3Jtcy8jZGVjb21wb3NpbmctYS0zZC1tYXRyaXhcbiovXG5cbnZhciBub3JtYWxpemUgPSByZXF1aXJlKCcuL25vcm1hbGl6ZScpXG5cbnZhciBjcmVhdGUgPSByZXF1aXJlKCdnbC1tYXQ0L2NyZWF0ZScpXG52YXIgY2xvbmUgPSByZXF1aXJlKCdnbC1tYXQ0L2Nsb25lJylcbnZhciBkZXRlcm1pbmFudCA9IHJlcXVpcmUoJ2dsLW1hdDQvZGV0ZXJtaW5hbnQnKVxudmFyIGludmVydCA9IHJlcXVpcmUoJ2dsLW1hdDQvaW52ZXJ0JylcbnZhciB0cmFuc3Bvc2UgPSByZXF1aXJlKCdnbC1tYXQ0L3RyYW5zcG9zZScpXG52YXIgdmVjMyA9IHtcbiAgICBsZW5ndGg6IHJlcXVpcmUoJ2dsLXZlYzMvbGVuZ3RoJyksXG4gICAgbm9ybWFsaXplOiByZXF1aXJlKCdnbC12ZWMzL25vcm1hbGl6ZScpLFxuICAgIGRvdDogcmVxdWlyZSgnZ2wtdmVjMy9kb3QnKSxcbiAgICBjcm9zczogcmVxdWlyZSgnZ2wtdmVjMy9jcm9zcycpXG59XG5cbnZhciB0bXAgPSBjcmVhdGUoKVxudmFyIHBlcnNwZWN0aXZlTWF0cml4ID0gY3JlYXRlKClcbnZhciB0bXBWZWM0ID0gWzAsIDAsIDAsIDBdXG52YXIgcm93ID0gWyBbMCwwLDBdLCBbMCwwLDBdLCBbMCwwLDBdIF1cbnZhciBwZHVtMyA9IFswLDAsMF1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkZWNvbXBvc2VNYXQ0KG1hdHJpeCwgdHJhbnNsYXRpb24sIHNjYWxlLCBza2V3LCBwZXJzcGVjdGl2ZSwgcXVhdGVybmlvbikge1xuICAgIGlmICghdHJhbnNsYXRpb24pIHRyYW5zbGF0aW9uID0gWzAsMCwwXVxuICAgIGlmICghc2NhbGUpIHNjYWxlID0gWzAsMCwwXVxuICAgIGlmICghc2tldykgc2tldyA9IFswLDAsMF1cbiAgICBpZiAoIXBlcnNwZWN0aXZlKSBwZXJzcGVjdGl2ZSA9IFswLDAsMCwxXVxuICAgIGlmICghcXVhdGVybmlvbikgcXVhdGVybmlvbiA9IFswLDAsMCwxXVxuXG4gICAgLy9ub3JtYWxpemUsIGlmIG5vdCBwb3NzaWJsZSB0aGVuIGJhaWwgb3V0IGVhcmx5XG4gICAgaWYgKCFub3JtYWxpemUodG1wLCBtYXRyaXgpKVxuICAgICAgICByZXR1cm4gZmFsc2VcblxuICAgIC8vIHBlcnNwZWN0aXZlTWF0cml4IGlzIHVzZWQgdG8gc29sdmUgZm9yIHBlcnNwZWN0aXZlLCBidXQgaXQgYWxzbyBwcm92aWRlc1xuICAgIC8vIGFuIGVhc3kgd2F5IHRvIHRlc3QgZm9yIHNpbmd1bGFyaXR5IG9mIHRoZSB1cHBlciAzeDMgY29tcG9uZW50LlxuICAgIGNsb25lKHBlcnNwZWN0aXZlTWF0cml4LCB0bXApXG5cbiAgICBwZXJzcGVjdGl2ZU1hdHJpeFszXSA9IDBcbiAgICBwZXJzcGVjdGl2ZU1hdHJpeFs3XSA9IDBcbiAgICBwZXJzcGVjdGl2ZU1hdHJpeFsxMV0gPSAwXG4gICAgcGVyc3BlY3RpdmVNYXRyaXhbMTVdID0gMVxuXG4gICAgLy8gSWYgdGhlIHBlcnNwZWN0aXZlTWF0cml4IGlzIG5vdCBpbnZlcnRpYmxlLCB3ZSBhcmUgYWxzbyB1bmFibGUgdG9cbiAgICAvLyBkZWNvbXBvc2UsIHNvIHdlJ2xsIGJhaWwgZWFybHkuIENvbnN0YW50IHRha2VuIGZyb20gU2tNYXRyaXg0NDo6aW52ZXJ0LlxuICAgIGlmIChNYXRoLmFicyhkZXRlcm1pbmFudChwZXJzcGVjdGl2ZU1hdHJpeCkgPCAxZS04KSlcbiAgICAgICAgcmV0dXJuIGZhbHNlXG5cbiAgICB2YXIgYTAzID0gdG1wWzNdLCBhMTMgPSB0bXBbN10sIGEyMyA9IHRtcFsxMV0sXG4gICAgICAgICAgICBhMzAgPSB0bXBbMTJdLCBhMzEgPSB0bXBbMTNdLCBhMzIgPSB0bXBbMTRdLCBhMzMgPSB0bXBbMTVdXG5cbiAgICAvLyBGaXJzdCwgaXNvbGF0ZSBwZXJzcGVjdGl2ZS5cbiAgICBpZiAoYTAzICE9PSAwIHx8IGExMyAhPT0gMCB8fCBhMjMgIT09IDApIHtcbiAgICAgICAgdG1wVmVjNFswXSA9IGEwM1xuICAgICAgICB0bXBWZWM0WzFdID0gYTEzXG4gICAgICAgIHRtcFZlYzRbMl0gPSBhMjNcbiAgICAgICAgdG1wVmVjNFszXSA9IGEzM1xuXG4gICAgICAgIC8vIFNvbHZlIHRoZSBlcXVhdGlvbiBieSBpbnZlcnRpbmcgcGVyc3BlY3RpdmVNYXRyaXggYW5kIG11bHRpcGx5aW5nXG4gICAgICAgIC8vIHJpZ2h0SGFuZFNpZGUgYnkgdGhlIGludmVyc2UuXG4gICAgICAgIC8vIHJlc3VpbmcgdGhlIHBlcnNwZWN0aXZlTWF0cml4IGhlcmUgc2luY2UgaXQncyBubyBsb25nZXIgbmVlZGVkXG4gICAgICAgIHZhciByZXQgPSBpbnZlcnQocGVyc3BlY3RpdmVNYXRyaXgsIHBlcnNwZWN0aXZlTWF0cml4KVxuICAgICAgICBpZiAoIXJldCkgcmV0dXJuIGZhbHNlXG4gICAgICAgIHRyYW5zcG9zZShwZXJzcGVjdGl2ZU1hdHJpeCwgcGVyc3BlY3RpdmVNYXRyaXgpXG5cbiAgICAgICAgLy9tdWx0aXBseSBieSB0cmFuc3Bvc2VkIGludmVyc2UgcGVyc3BlY3RpdmUgbWF0cml4LCBpbnRvIHBlcnNwZWN0aXZlIHZlYzRcbiAgICAgICAgdmVjNG11bHRNYXQ0KHBlcnNwZWN0aXZlLCB0bXBWZWM0LCBwZXJzcGVjdGl2ZU1hdHJpeClcbiAgICB9IGVsc2UgeyBcbiAgICAgICAgLy9ubyBwZXJzcGVjdGl2ZVxuICAgICAgICBwZXJzcGVjdGl2ZVswXSA9IHBlcnNwZWN0aXZlWzFdID0gcGVyc3BlY3RpdmVbMl0gPSAwXG4gICAgICAgIHBlcnNwZWN0aXZlWzNdID0gMVxuICAgIH1cblxuICAgIC8vIE5leHQgdGFrZSBjYXJlIG9mIHRyYW5zbGF0aW9uXG4gICAgdHJhbnNsYXRpb25bMF0gPSBhMzBcbiAgICB0cmFuc2xhdGlvblsxXSA9IGEzMVxuICAgIHRyYW5zbGF0aW9uWzJdID0gYTMyXG5cbiAgICAvLyBOb3cgZ2V0IHNjYWxlIGFuZCBzaGVhci4gJ3JvdycgaXMgYSAzIGVsZW1lbnQgYXJyYXkgb2YgMyBjb21wb25lbnQgdmVjdG9yc1xuICAgIG1hdDNmcm9tNChyb3csIHRtcClcblxuICAgIC8vIENvbXB1dGUgWCBzY2FsZSBmYWN0b3IgYW5kIG5vcm1hbGl6ZSBmaXJzdCByb3cuXG4gICAgc2NhbGVbMF0gPSB2ZWMzLmxlbmd0aChyb3dbMF0pXG4gICAgdmVjMy5ub3JtYWxpemUocm93WzBdLCByb3dbMF0pXG5cbiAgICAvLyBDb21wdXRlIFhZIHNoZWFyIGZhY3RvciBhbmQgbWFrZSAybmQgcm93IG9ydGhvZ29uYWwgdG8gMXN0LlxuICAgIHNrZXdbMF0gPSB2ZWMzLmRvdChyb3dbMF0sIHJvd1sxXSlcbiAgICBjb21iaW5lKHJvd1sxXSwgcm93WzFdLCByb3dbMF0sIDEuMCwgLXNrZXdbMF0pXG5cbiAgICAvLyBOb3csIGNvbXB1dGUgWSBzY2FsZSBhbmQgbm9ybWFsaXplIDJuZCByb3cuXG4gICAgc2NhbGVbMV0gPSB2ZWMzLmxlbmd0aChyb3dbMV0pXG4gICAgdmVjMy5ub3JtYWxpemUocm93WzFdLCByb3dbMV0pXG4gICAgc2tld1swXSAvPSBzY2FsZVsxXVxuXG4gICAgLy8gQ29tcHV0ZSBYWiBhbmQgWVogc2hlYXJzLCBvcnRob2dvbmFsaXplIDNyZCByb3dcbiAgICBza2V3WzFdID0gdmVjMy5kb3Qocm93WzBdLCByb3dbMl0pXG4gICAgY29tYmluZShyb3dbMl0sIHJvd1syXSwgcm93WzBdLCAxLjAsIC1za2V3WzFdKVxuICAgIHNrZXdbMl0gPSB2ZWMzLmRvdChyb3dbMV0sIHJvd1syXSlcbiAgICBjb21iaW5lKHJvd1syXSwgcm93WzJdLCByb3dbMV0sIDEuMCwgLXNrZXdbMl0pXG5cbiAgICAvLyBOZXh0LCBnZXQgWiBzY2FsZSBhbmQgbm9ybWFsaXplIDNyZCByb3cuXG4gICAgc2NhbGVbMl0gPSB2ZWMzLmxlbmd0aChyb3dbMl0pXG4gICAgdmVjMy5ub3JtYWxpemUocm93WzJdLCByb3dbMl0pXG4gICAgc2tld1sxXSAvPSBzY2FsZVsyXVxuICAgIHNrZXdbMl0gLz0gc2NhbGVbMl1cblxuXG4gICAgLy8gQXQgdGhpcyBwb2ludCwgdGhlIG1hdHJpeCAoaW4gcm93cykgaXMgb3J0aG9ub3JtYWwuXG4gICAgLy8gQ2hlY2sgZm9yIGEgY29vcmRpbmF0ZSBzeXN0ZW0gZmxpcC4gIElmIHRoZSBkZXRlcm1pbmFudFxuICAgIC8vIGlzIC0xLCB0aGVuIG5lZ2F0ZSB0aGUgbWF0cml4IGFuZCB0aGUgc2NhbGluZyBmYWN0b3JzLlxuICAgIHZlYzMuY3Jvc3MocGR1bTMsIHJvd1sxXSwgcm93WzJdKVxuICAgIGlmICh2ZWMzLmRvdChyb3dbMF0sIHBkdW0zKSA8IDApIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgIHNjYWxlW2ldICo9IC0xO1xuICAgICAgICAgICAgcm93W2ldWzBdICo9IC0xXG4gICAgICAgICAgICByb3dbaV1bMV0gKj0gLTFcbiAgICAgICAgICAgIHJvd1tpXVsyXSAqPSAtMVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTm93LCBnZXQgdGhlIHJvdGF0aW9ucyBvdXRcbiAgICBxdWF0ZXJuaW9uWzBdID0gMC41ICogTWF0aC5zcXJ0KE1hdGgubWF4KDEgKyByb3dbMF1bMF0gLSByb3dbMV1bMV0gLSByb3dbMl1bMl0sIDApKVxuICAgIHF1YXRlcm5pb25bMV0gPSAwLjUgKiBNYXRoLnNxcnQoTWF0aC5tYXgoMSAtIHJvd1swXVswXSArIHJvd1sxXVsxXSAtIHJvd1syXVsyXSwgMCkpXG4gICAgcXVhdGVybmlvblsyXSA9IDAuNSAqIE1hdGguc3FydChNYXRoLm1heCgxIC0gcm93WzBdWzBdIC0gcm93WzFdWzFdICsgcm93WzJdWzJdLCAwKSlcbiAgICBxdWF0ZXJuaW9uWzNdID0gMC41ICogTWF0aC5zcXJ0KE1hdGgubWF4KDEgKyByb3dbMF1bMF0gKyByb3dbMV1bMV0gKyByb3dbMl1bMl0sIDApKVxuXG4gICAgaWYgKHJvd1syXVsxXSA+IHJvd1sxXVsyXSlcbiAgICAgICAgcXVhdGVybmlvblswXSA9IC1xdWF0ZXJuaW9uWzBdXG4gICAgaWYgKHJvd1swXVsyXSA+IHJvd1syXVswXSlcbiAgICAgICAgcXVhdGVybmlvblsxXSA9IC1xdWF0ZXJuaW9uWzFdXG4gICAgaWYgKHJvd1sxXVswXSA+IHJvd1swXVsxXSlcbiAgICAgICAgcXVhdGVybmlvblsyXSA9IC1xdWF0ZXJuaW9uWzJdXG4gICAgcmV0dXJuIHRydWVcbn1cblxuLy93aWxsIGJlIHJlcGxhY2VkIGJ5IGdsLXZlYzQgZXZlbnR1YWxseVxuZnVuY3Rpb24gdmVjNG11bHRNYXQ0KG91dCwgYSwgbSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLCB3ID0gYVszXTtcbiAgICBvdXRbMF0gPSBtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSAqIHc7XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM10gKiB3O1xuICAgIG91dFsyXSA9IG1bMl0gKiB4ICsgbVs2XSAqIHkgKyBtWzEwXSAqIHogKyBtWzE0XSAqIHc7XG4gICAgb3V0WzNdID0gbVszXSAqIHggKyBtWzddICogeSArIG1bMTFdICogeiArIG1bMTVdICogdztcbiAgICByZXR1cm4gb3V0O1xufVxuXG4vL2dldHMgdXBwZXItbGVmdCBvZiBhIDR4NCBtYXRyaXggaW50byBhIDN4MyBvZiB2ZWN0b3JzXG5mdW5jdGlvbiBtYXQzZnJvbTQob3V0LCBtYXQ0eDQpIHtcbiAgICBvdXRbMF1bMF0gPSBtYXQ0eDRbMF1cbiAgICBvdXRbMF1bMV0gPSBtYXQ0eDRbMV1cbiAgICBvdXRbMF1bMl0gPSBtYXQ0eDRbMl1cbiAgICBcbiAgICBvdXRbMV1bMF0gPSBtYXQ0eDRbNF1cbiAgICBvdXRbMV1bMV0gPSBtYXQ0eDRbNV1cbiAgICBvdXRbMV1bMl0gPSBtYXQ0eDRbNl1cblxuICAgIG91dFsyXVswXSA9IG1hdDR4NFs4XVxuICAgIG91dFsyXVsxXSA9IG1hdDR4NFs5XVxuICAgIG91dFsyXVsyXSA9IG1hdDR4NFsxMF1cbn1cblxuZnVuY3Rpb24gY29tYmluZShvdXQsIGEsIGIsIHNjYWxlMSwgc2NhbGUyKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIHNjYWxlMSArIGJbMF0gKiBzY2FsZTJcbiAgICBvdXRbMV0gPSBhWzFdICogc2NhbGUxICsgYlsxXSAqIHNjYWxlMlxuICAgIG91dFsyXSA9IGFbMl0gKiBzY2FsZTEgKyBiWzJdICogc2NhbGUyXG59IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBub3JtYWxpemUob3V0LCBtYXQpIHtcbiAgICB2YXIgbTQ0ID0gbWF0WzE1XVxuICAgIC8vIENhbm5vdCBub3JtYWxpemUuXG4gICAgaWYgKG00NCA9PT0gMCkgXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIHZhciBzY2FsZSA9IDEgLyBtNDRcbiAgICBmb3IgKHZhciBpPTA7IGk8MTY7IGkrKylcbiAgICAgICAgb3V0W2ldID0gbWF0W2ldICogc2NhbGVcbiAgICByZXR1cm4gdHJ1ZVxufSIsInZhciBsZXJwID0gcmVxdWlyZSgnZ2wtdmVjMy9sZXJwJylcblxudmFyIHJlY29tcG9zZSA9IHJlcXVpcmUoJ21hdDQtcmVjb21wb3NlJylcbnZhciBkZWNvbXBvc2UgPSByZXF1aXJlKCdtYXQ0LWRlY29tcG9zZScpXG52YXIgZGV0ZXJtaW5hbnQgPSByZXF1aXJlKCdnbC1tYXQ0L2RldGVybWluYW50JylcbnZhciBzbGVycCA9IHJlcXVpcmUoJ3F1YXQtc2xlcnAnKVxuXG52YXIgc3RhdGUwID0gc3RhdGUoKVxudmFyIHN0YXRlMSA9IHN0YXRlKClcbnZhciB0bXAgPSBzdGF0ZSgpXG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGVcbmZ1bmN0aW9uIGludGVycG9sYXRlKG91dCwgc3RhcnQsIGVuZCwgYWxwaGEpIHtcbiAgICBpZiAoZGV0ZXJtaW5hbnQoc3RhcnQpID09PSAwIHx8IGRldGVybWluYW50KGVuZCkgPT09IDApXG4gICAgICAgIHJldHVybiBmYWxzZVxuXG4gICAgLy9kZWNvbXBvc2UgdGhlIHN0YXJ0IGFuZCBlbmQgbWF0cmljZXMgaW50byBpbmRpdmlkdWFsIGNvbXBvbmVudHNcbiAgICB2YXIgcjAgPSBkZWNvbXBvc2Uoc3RhcnQsIHN0YXRlMC50cmFuc2xhdGUsIHN0YXRlMC5zY2FsZSwgc3RhdGUwLnNrZXcsIHN0YXRlMC5wZXJzcGVjdGl2ZSwgc3RhdGUwLnF1YXRlcm5pb24pXG4gICAgdmFyIHIxID0gZGVjb21wb3NlKGVuZCwgc3RhdGUxLnRyYW5zbGF0ZSwgc3RhdGUxLnNjYWxlLCBzdGF0ZTEuc2tldywgc3RhdGUxLnBlcnNwZWN0aXZlLCBzdGF0ZTEucXVhdGVybmlvbilcbiAgICBpZiAoIXIwIHx8ICFyMSlcbiAgICAgICAgcmV0dXJuIGZhbHNlICAgIFxuXG5cbiAgICAvL25vdyBsZXJwL3NsZXJwIHRoZSBzdGFydCBhbmQgZW5kIGNvbXBvbmVudHMgaW50byBhIHRlbXBvcmFyeSAgICAgbGVycCh0bXB0cmFuc2xhdGUsIHN0YXRlMC50cmFuc2xhdGUsIHN0YXRlMS50cmFuc2xhdGUsIGFscGhhKVxuICAgIGxlcnAodG1wLnRyYW5zbGF0ZSwgc3RhdGUwLnRyYW5zbGF0ZSwgc3RhdGUxLnRyYW5zbGF0ZSwgYWxwaGEpXG4gICAgbGVycCh0bXAuc2tldywgc3RhdGUwLnNrZXcsIHN0YXRlMS5za2V3LCBhbHBoYSlcbiAgICBsZXJwKHRtcC5zY2FsZSwgc3RhdGUwLnNjYWxlLCBzdGF0ZTEuc2NhbGUsIGFscGhhKVxuICAgIGxlcnAodG1wLnBlcnNwZWN0aXZlLCBzdGF0ZTAucGVyc3BlY3RpdmUsIHN0YXRlMS5wZXJzcGVjdGl2ZSwgYWxwaGEpXG4gICAgc2xlcnAodG1wLnF1YXRlcm5pb24sIHN0YXRlMC5xdWF0ZXJuaW9uLCBzdGF0ZTEucXVhdGVybmlvbiwgYWxwaGEpXG5cbiAgICAvL2FuZCByZWNvbXBvc2UgaW50byBvdXIgJ291dCcgbWF0cml4XG4gICAgcmVjb21wb3NlKG91dCwgdG1wLnRyYW5zbGF0ZSwgdG1wLnNjYWxlLCB0bXAuc2tldywgdG1wLnBlcnNwZWN0aXZlLCB0bXAucXVhdGVybmlvbilcbiAgICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBzdGF0ZSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0cmFuc2xhdGU6IHZlYzMoKSxcbiAgICAgICAgc2NhbGU6IHZlYzMoMSksXG4gICAgICAgIHNrZXc6IHZlYzMoKSxcbiAgICAgICAgcGVyc3BlY3RpdmU6IHZlYzQoKSxcbiAgICAgICAgcXVhdGVybmlvbjogdmVjNCgpXG4gICAgfVxufVxuXG5mdW5jdGlvbiB2ZWMzKG4pIHtcbiAgICByZXR1cm4gW258fDAsbnx8MCxufHwwXVxufVxuXG5mdW5jdGlvbiB2ZWM0KCkge1xuICAgIHJldHVybiBbMCwwLDAsMV1cbn0iLCIvKlxuSW5wdXQ6ICB0cmFuc2xhdGlvbiA7IGEgMyBjb21wb25lbnQgdmVjdG9yXG4gICAgICAgIHNjYWxlICAgICAgIDsgYSAzIGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgc2tldyAgICAgICAgOyBza2V3IGZhY3RvcnMgWFksWFosWVogcmVwcmVzZW50ZWQgYXMgYSAzIGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgcGVyc3BlY3RpdmUgOyBhIDQgY29tcG9uZW50IHZlY3RvclxuICAgICAgICBxdWF0ZXJuaW9uICA7IGEgNCBjb21wb25lbnQgdmVjdG9yXG5PdXRwdXQ6IG1hdHJpeCAgICAgIDsgYSA0eDQgbWF0cml4XG5cbkZyb206IGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtdHJhbnNmb3Jtcy8jcmVjb21wb3NpbmctdG8tYS0zZC1tYXRyaXhcbiovXG5cbnZhciBtYXQ0ID0ge1xuICAgIGlkZW50aXR5OiByZXF1aXJlKCdnbC1tYXQ0L2lkZW50aXR5JyksXG4gICAgdHJhbnNsYXRlOiByZXF1aXJlKCdnbC1tYXQ0L3RyYW5zbGF0ZScpLFxuICAgIG11bHRpcGx5OiByZXF1aXJlKCdnbC1tYXQ0L211bHRpcGx5JyksXG4gICAgY3JlYXRlOiByZXF1aXJlKCdnbC1tYXQ0L2NyZWF0ZScpLFxuICAgIHNjYWxlOiByZXF1aXJlKCdnbC1tYXQ0L3NjYWxlJyksXG4gICAgZnJvbVJvdGF0aW9uVHJhbnNsYXRpb246IHJlcXVpcmUoJ2dsLW1hdDQvZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24nKVxufVxuXG52YXIgcm90YXRpb25NYXRyaXggPSBtYXQ0LmNyZWF0ZSgpXG52YXIgdGVtcCA9IG1hdDQuY3JlYXRlKClcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiByZWNvbXBvc2VNYXQ0KG1hdHJpeCwgdHJhbnNsYXRpb24sIHNjYWxlLCBza2V3LCBwZXJzcGVjdGl2ZSwgcXVhdGVybmlvbikge1xuICAgIG1hdDQuaWRlbnRpdHkobWF0cml4KVxuXG4gICAgLy9hcHBseSB0cmFuc2xhdGlvbiAmIHJvdGF0aW9uXG4gICAgbWF0NC5mcm9tUm90YXRpb25UcmFuc2xhdGlvbihtYXRyaXgsIHF1YXRlcm5pb24sIHRyYW5zbGF0aW9uKVxuXG4gICAgLy9hcHBseSBwZXJzcGVjdGl2ZVxuICAgIG1hdHJpeFszXSA9IHBlcnNwZWN0aXZlWzBdXG4gICAgbWF0cml4WzddID0gcGVyc3BlY3RpdmVbMV1cbiAgICBtYXRyaXhbMTFdID0gcGVyc3BlY3RpdmVbMl1cbiAgICBtYXRyaXhbMTVdID0gcGVyc3BlY3RpdmVbM11cbiAgICAgICAgXG4gICAgLy8gYXBwbHkgc2tld1xuICAgIC8vIHRlbXAgaXMgYSBpZGVudGl0eSA0eDQgbWF0cml4IGluaXRpYWxseVxuICAgIG1hdDQuaWRlbnRpdHkodGVtcClcblxuICAgIGlmIChza2V3WzJdICE9PSAwKSB7XG4gICAgICAgIHRlbXBbOV0gPSBza2V3WzJdXG4gICAgICAgIG1hdDQubXVsdGlwbHkobWF0cml4LCBtYXRyaXgsIHRlbXApXG4gICAgfVxuXG4gICAgaWYgKHNrZXdbMV0gIT09IDApIHtcbiAgICAgICAgdGVtcFs5XSA9IDBcbiAgICAgICAgdGVtcFs4XSA9IHNrZXdbMV1cbiAgICAgICAgbWF0NC5tdWx0aXBseShtYXRyaXgsIG1hdHJpeCwgdGVtcClcbiAgICB9XG5cbiAgICBpZiAoc2tld1swXSAhPT0gMCkge1xuICAgICAgICB0ZW1wWzhdID0gMFxuICAgICAgICB0ZW1wWzRdID0gc2tld1swXVxuICAgICAgICBtYXQ0Lm11bHRpcGx5KG1hdHJpeCwgbWF0cml4LCB0ZW1wKVxuICAgIH1cblxuICAgIC8vYXBwbHkgc2NhbGVcbiAgICBtYXQ0LnNjYWxlKG1hdHJpeCwgbWF0cml4LCBzY2FsZSlcbiAgICByZXR1cm4gbWF0cml4XG59IiwiJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSBNYXRoLmxvZzIgfHwgZnVuY3Rpb24gKHgpIHtcblx0cmV0dXJuIE1hdGgubG9nKHgpICogTWF0aC5MT0cyRTtcbn07XG4iLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBic2VhcmNoICAgPSByZXF1aXJlKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXHJcbnZhciBtNGludGVycCAgPSByZXF1aXJlKCdtYXQ0LWludGVycG9sYXRlJylcclxudmFyIGludmVydDQ0ICA9IHJlcXVpcmUoJ2dsLW1hdDQvaW52ZXJ0JylcclxudmFyIHJvdGF0ZVggICA9IHJlcXVpcmUoJ2dsLW1hdDQvcm90YXRlWCcpXHJcbnZhciByb3RhdGVZICAgPSByZXF1aXJlKCdnbC1tYXQ0L3JvdGF0ZVknKVxyXG52YXIgcm90YXRlWiAgID0gcmVxdWlyZSgnZ2wtbWF0NC9yb3RhdGVaJylcclxudmFyIGxvb2tBdCAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvbG9va0F0JylcclxudmFyIHRyYW5zbGF0ZSA9IHJlcXVpcmUoJ2dsLW1hdDQvdHJhbnNsYXRlJylcclxudmFyIHNjYWxlICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvc2NhbGUnKVxyXG52YXIgbm9ybWFsaXplID0gcmVxdWlyZSgnZ2wtdmVjMy9ub3JtYWxpemUnKVxyXG5cclxudmFyIERFRkFVTFRfQ0VOVEVSID0gWzAsMCwwXVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNYXRyaXhDYW1lcmFDb250cm9sbGVyXHJcblxyXG5mdW5jdGlvbiBNYXRyaXhDYW1lcmFDb250cm9sbGVyKGluaXRpYWxNYXRyaXgpIHtcclxuICB0aGlzLl9jb21wb25lbnRzICAgID0gaW5pdGlhbE1hdHJpeC5zbGljZSgpXHJcbiAgdGhpcy5fdGltZSAgICAgICAgICA9IFswXVxyXG4gIHRoaXMucHJldk1hdHJpeCAgICAgPSBpbml0aWFsTWF0cml4LnNsaWNlKClcclxuICB0aGlzLm5leHRNYXRyaXggICAgID0gaW5pdGlhbE1hdHJpeC5zbGljZSgpXHJcbiAgdGhpcy5jb21wdXRlZE1hdHJpeCA9IGluaXRpYWxNYXRyaXguc2xpY2UoKVxyXG4gIHRoaXMuY29tcHV0ZWRJbnZlcnNlID0gaW5pdGlhbE1hdHJpeC5zbGljZSgpXHJcbiAgdGhpcy5jb21wdXRlZEV5ZSAgICA9IFswLDAsMF1cclxuICB0aGlzLmNvbXB1dGVkVXAgICAgID0gWzAsMCwwXVxyXG4gIHRoaXMuY29tcHV0ZWRDZW50ZXIgPSBbMCwwLDBdXHJcbiAgdGhpcy5jb21wdXRlZFJhZGl1cyA9IFswXVxyXG4gIHRoaXMuX2xpbWl0cyAgICAgICAgPSBbLUluZmluaXR5LCBJbmZpbml0eV1cclxufVxyXG5cclxudmFyIHByb3RvID0gTWF0cml4Q2FtZXJhQ29udHJvbGxlci5wcm90b3R5cGVcclxuXHJcbnByb3RvLnJlY2FsY01hdHJpeCA9IGZ1bmN0aW9uKHQpIHtcclxuICB2YXIgdGltZSA9IHRoaXMuX3RpbWVcclxuICB2YXIgdGlkeCA9IGJzZWFyY2gubGUodGltZSwgdClcclxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxyXG4gIGlmKHRpZHggPCAwKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcbiAgdmFyIGNvbXBzID0gdGhpcy5fY29tcG9uZW50c1xyXG4gIGlmKHRpZHggPT09IHRpbWUubGVuZ3RoLTEpIHtcclxuICAgIHZhciBwdHIgPSAxNip0aWR4XHJcbiAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICAgIG1hdFtpXSA9IGNvbXBzW3B0cisrXVxyXG4gICAgfVxyXG4gIH0gZWxzZSB7XHJcbiAgICB2YXIgZHQgPSAodGltZVt0aWR4KzFdIC0gdGltZVt0aWR4XSlcclxuICAgIHZhciBwdHIgPSAxNip0aWR4XHJcbiAgICB2YXIgcHJldiA9IHRoaXMucHJldk1hdHJpeFxyXG4gICAgdmFyIGFsbEVxdWFsID0gdHJ1ZVxyXG4gICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xyXG4gICAgICBwcmV2W2ldID0gY29tcHNbcHRyKytdXHJcbiAgICB9XHJcbiAgICB2YXIgbmV4dCA9IHRoaXMubmV4dE1hdHJpeFxyXG4gICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xyXG4gICAgICBuZXh0W2ldID0gY29tcHNbcHRyKytdXHJcbiAgICAgIGFsbEVxdWFsID0gYWxsRXF1YWwgJiYgKHByZXZbaV0gPT09IG5leHRbaV0pXHJcbiAgICB9XHJcbiAgICBpZihkdCA8IDFlLTYgfHwgYWxsRXF1YWwpIHtcclxuICAgICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xyXG4gICAgICAgIG1hdFtpXSA9IHByZXZbaV1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbTRpbnRlcnAobWF0LCBwcmV2LCBuZXh0LCAodCAtIHRpbWVbdGlkeF0pL2R0KVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdmFyIHVwID0gdGhpcy5jb21wdXRlZFVwXHJcbiAgdXBbMF0gPSBtYXRbMV1cclxuICB1cFsxXSA9IG1hdFs1XVxyXG4gIHVwWzJdID0gbWF0WzldXHJcbiAgbm9ybWFsaXplKHVwLCB1cClcclxuXHJcbiAgdmFyIGltYXQgPSB0aGlzLmNvbXB1dGVkSW52ZXJzZVxyXG4gIGludmVydDQ0KGltYXQsIG1hdClcclxuICB2YXIgZXllID0gdGhpcy5jb21wdXRlZEV5ZVxyXG4gIHZhciB3ID0gaW1hdFsxNV1cclxuICBleWVbMF0gPSBpbWF0WzEyXS93XHJcbiAgZXllWzFdID0gaW1hdFsxM10vd1xyXG4gIGV5ZVsyXSA9IGltYXRbMTRdL3dcclxuXHJcbiAgdmFyIGNlbnRlciA9IHRoaXMuY29tcHV0ZWRDZW50ZXJcclxuICB2YXIgcmFkaXVzID0gTWF0aC5leHAodGhpcy5jb21wdXRlZFJhZGl1c1swXSlcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIGNlbnRlcltpXSA9IGV5ZVtpXSAtIG1hdFsyKzQqaV0gKiByYWRpdXNcclxuICB9XHJcbn1cclxuXHJcbnByb3RvLmlkbGUgPSBmdW5jdGlvbih0KSB7XHJcbiAgaWYodCA8IHRoaXMubGFzdFQoKSkge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG4gIHZhciBtYyA9IHRoaXMuX2NvbXBvbmVudHNcclxuICB2YXIgcHRyID0gbWMubGVuZ3RoLTE2XHJcbiAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xyXG4gICAgbWMucHVzaChtY1twdHIrK10pXHJcbiAgfVxyXG4gIHRoaXMuX3RpbWUucHVzaCh0KVxyXG59XHJcblxyXG5wcm90by5mbHVzaCA9IGZ1bmN0aW9uKHQpIHtcclxuICB2YXIgaWR4ID0gYnNlYXJjaC5ndCh0aGlzLl90aW1lLCB0KSAtIDJcclxuICBpZihpZHggPCAwKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcbiAgdGhpcy5fdGltZS5zcGxpY2UoMCwgaWR4KVxyXG4gIHRoaXMuX2NvbXBvbmVudHMuc3BsaWNlKDAsIDE2KmlkeClcclxufVxyXG5cclxucHJvdG8ubGFzdFQgPSBmdW5jdGlvbigpIHtcclxuICByZXR1cm4gdGhpcy5fdGltZVt0aGlzLl90aW1lLmxlbmd0aC0xXVxyXG59XHJcblxyXG5wcm90by5sb29rQXQgPSBmdW5jdGlvbih0LCBleWUsIGNlbnRlciwgdXApIHtcclxuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxyXG4gIGV5ZSAgICA9IGV5ZSB8fCB0aGlzLmNvbXB1dGVkRXllXHJcbiAgY2VudGVyID0gY2VudGVyIHx8IERFRkFVTFRfQ0VOVEVSXHJcbiAgdXAgICAgID0gdXAgfHwgdGhpcy5jb21wdXRlZFVwXHJcbiAgdGhpcy5zZXRNYXRyaXgodCwgbG9va0F0KHRoaXMuY29tcHV0ZWRNYXRyaXgsIGV5ZSwgY2VudGVyLCB1cCkpXHJcbiAgdmFyIGQyID0gMC4wXHJcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XHJcbiAgICBkMiArPSBNYXRoLnBvdyhjZW50ZXJbaV0gLSBleWVbaV0sIDIpXHJcbiAgfVxyXG4gIGQyID0gTWF0aC5sb2coTWF0aC5zcXJ0KGQyKSlcclxuICB0aGlzLmNvbXB1dGVkUmFkaXVzWzBdID0gZDJcclxufVxyXG5cclxucHJvdG8ucm90YXRlID0gZnVuY3Rpb24odCwgeWF3LCBwaXRjaCwgcm9sbCkge1xyXG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXHJcbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRJbnZlcnNlXHJcbiAgaWYoeWF3KSAgIHJvdGF0ZVkobWF0LCBtYXQsIHlhdylcclxuICBpZihwaXRjaCkgcm90YXRlWChtYXQsIG1hdCwgcGl0Y2gpXHJcbiAgaWYocm9sbCkgIHJvdGF0ZVoobWF0LCBtYXQsIHJvbGwpXHJcbiAgdGhpcy5zZXRNYXRyaXgodCwgaW52ZXJ0NDQodGhpcy5jb21wdXRlZE1hdHJpeCwgbWF0KSlcclxufVxyXG5cclxudmFyIHR2ZWMgPSBbMCwwLDBdXHJcblxyXG5wcm90by5wYW4gPSBmdW5jdGlvbih0LCBkeCwgZHksIGR6KSB7XHJcbiAgdHZlY1swXSA9IC0oZHggfHwgMC4wKVxyXG4gIHR2ZWNbMV0gPSAtKGR5IHx8IDAuMClcclxuICB0dmVjWzJdID0gLShkeiB8fCAwLjApXHJcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcclxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZEludmVyc2VcclxuICB0cmFuc2xhdGUobWF0LCBtYXQsIHR2ZWMpXHJcbiAgdGhpcy5zZXRNYXRyaXgodCwgaW52ZXJ0NDQobWF0LCBtYXQpKVxyXG59XHJcblxyXG5wcm90by50cmFuc2xhdGUgPSBmdW5jdGlvbih0LCBkeCwgZHksIGR6KSB7XHJcbiAgdHZlY1swXSA9IGR4IHx8IDAuMFxyXG4gIHR2ZWNbMV0gPSBkeSB8fCAwLjBcclxuICB0dmVjWzJdID0gZHogfHwgMC4wXHJcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcclxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxyXG4gIHRyYW5zbGF0ZShtYXQsIG1hdCwgdHZlYylcclxuICB0aGlzLnNldE1hdHJpeCh0LCBtYXQpXHJcbn1cclxuXHJcbnByb3RvLnNldE1hdHJpeCA9IGZ1bmN0aW9uKHQsIG1hdCkge1xyXG4gIGlmKHQgPCB0aGlzLmxhc3RUKCkpIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuICB0aGlzLl90aW1lLnB1c2godClcclxuICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICB0aGlzLl9jb21wb25lbnRzLnB1c2gobWF0W2ldKVxyXG4gIH1cclxufVxyXG5cclxucHJvdG8uc2V0RGlzdGFuY2UgPSBmdW5jdGlvbih0LCBkKSB7XHJcbiAgdGhpcy5jb21wdXRlZFJhZGl1c1swXSA9IGRcclxufVxyXG5cclxucHJvdG8uc2V0RGlzdGFuY2VMaW1pdHMgPSBmdW5jdGlvbihhLGIpIHtcclxuICB2YXIgbGltID0gdGhpcy5fbGltaXRzXHJcbiAgbGltWzBdID0gYVxyXG4gIGxpbVsxXSA9IGJcclxufVxyXG5cclxucHJvdG8uZ2V0RGlzdGFuY2VMaW1pdHMgPSBmdW5jdGlvbihvdXQpIHtcclxuICB2YXIgbGltID0gdGhpcy5fbGltaXRzXHJcbiAgaWYob3V0KSB7XHJcbiAgICBvdXRbMF0gPSBsaW1bMF1cclxuICAgIG91dFsxXSA9IGxpbVsxXVxyXG4gICAgcmV0dXJuIG91dFxyXG4gIH1cclxuICByZXR1cm4gbGltXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZU1hdHJpeENhbWVyYUNvbnRyb2xsZXIob3B0aW9ucykge1xyXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XHJcbiAgdmFyIG1hdHJpeCA9IG9wdGlvbnMubWF0cml4IHx8IFxyXG4gICAgICAgICAgICAgIFsxLDAsMCwwLFxyXG4gICAgICAgICAgICAgICAwLDEsMCwwLFxyXG4gICAgICAgICAgICAgICAwLDAsMSwwLFxyXG4gICAgICAgICAgICAgICAwLDAsMCwxXVxyXG4gIHJldHVybiBuZXcgTWF0cml4Q2FtZXJhQ29udHJvbGxlcihtYXRyaXgpXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gbW9ub3RvbmVDb252ZXhIdWxsMkRcblxudmFyIG9yaWVudCA9IHJlcXVpcmUoJ3JvYnVzdC1vcmllbnRhdGlvbicpWzNdXG5cbmZ1bmN0aW9uIG1vbm90b25lQ29udmV4SHVsbDJEKHBvaW50cykge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcblxuICBpZihuIDwgMykge1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIHJlc3VsdFtpXSA9IGlcbiAgICB9XG5cbiAgICBpZihuID09PSAyICYmXG4gICAgICAgcG9pbnRzWzBdWzBdID09PSBwb2ludHNbMV1bMF0gJiZcbiAgICAgICBwb2ludHNbMF1bMV0gPT09IHBvaW50c1sxXVsxXSkge1xuICAgICAgcmV0dXJuIFswXVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8vU29ydCBwb2ludCBpbmRpY2VzIGFsb25nIHgtYXhpc1xuICB2YXIgc29ydGVkID0gbmV3IEFycmF5KG4pXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHNvcnRlZFtpXSA9IGlcbiAgfVxuICBzb3J0ZWQuc29ydChmdW5jdGlvbihhLGIpIHtcbiAgICB2YXIgZCA9IHBvaW50c1thXVswXS1wb2ludHNbYl1bMF1cbiAgICBpZihkKSB7XG4gICAgICByZXR1cm4gZFxuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzW2FdWzFdIC0gcG9pbnRzW2JdWzFdXG4gIH0pXG5cbiAgLy9Db25zdHJ1Y3QgdXBwZXIgYW5kIGxvd2VyIGh1bGxzXG4gIHZhciBsb3dlciA9IFtzb3J0ZWRbMF0sIHNvcnRlZFsxXV1cbiAgdmFyIHVwcGVyID0gW3NvcnRlZFswXSwgc29ydGVkWzFdXVxuXG4gIGZvcih2YXIgaT0yOyBpPG47ICsraSkge1xuICAgIHZhciBpZHggPSBzb3J0ZWRbaV1cbiAgICB2YXIgcCAgID0gcG9pbnRzW2lkeF1cblxuICAgIC8vSW5zZXJ0IGludG8gbG93ZXIgbGlzdFxuICAgIHZhciBtID0gbG93ZXIubGVuZ3RoXG4gICAgd2hpbGUobSA+IDEgJiYgb3JpZW50KFxuICAgICAgICBwb2ludHNbbG93ZXJbbS0yXV0sIFxuICAgICAgICBwb2ludHNbbG93ZXJbbS0xXV0sIFxuICAgICAgICBwKSA8PSAwKSB7XG4gICAgICBtIC09IDFcbiAgICAgIGxvd2VyLnBvcCgpXG4gICAgfVxuICAgIGxvd2VyLnB1c2goaWR4KVxuXG4gICAgLy9JbnNlcnQgaW50byB1cHBlciBsaXN0XG4gICAgbSA9IHVwcGVyLmxlbmd0aFxuICAgIHdoaWxlKG0gPiAxICYmIG9yaWVudChcbiAgICAgICAgcG9pbnRzW3VwcGVyW20tMl1dLCBcbiAgICAgICAgcG9pbnRzW3VwcGVyW20tMV1dLCBcbiAgICAgICAgcCkgPj0gMCkge1xuICAgICAgbSAtPSAxXG4gICAgICB1cHBlci5wb3AoKVxuICAgIH1cbiAgICB1cHBlci5wdXNoKGlkeClcbiAgfVxuXG4gIC8vTWVyZ2UgbGlzdHMgdG9nZXRoZXJcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh1cHBlci5sZW5ndGggKyBsb3dlci5sZW5ndGggLSAyKVxuICB2YXIgcHRyICAgID0gMFxuICBmb3IodmFyIGk9MCwgbmw9bG93ZXIubGVuZ3RoOyBpPG5sOyArK2kpIHtcbiAgICByZXN1bHRbcHRyKytdID0gbG93ZXJbaV1cbiAgfVxuICBmb3IodmFyIGo9dXBwZXIubGVuZ3RoLTI7IGo+MDsgLS1qKSB7XG4gICAgcmVzdWx0W3B0cisrXSA9IHVwcGVyW2pdXG4gIH1cblxuICAvL1JldHVybiByZXN1bHRcbiAgcmV0dXJuIHJlc3VsdFxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IG1vdXNlTGlzdGVuXG5cbnZhciBtb3VzZSA9IHJlcXVpcmUoJ21vdXNlLWV2ZW50JylcblxuZnVuY3Rpb24gbW91c2VMaXN0ZW4gKGVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gIGlmICghY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGVsZW1lbnRcbiAgICBlbGVtZW50ID0gd2luZG93XG4gIH1cblxuICB2YXIgYnV0dG9uU3RhdGUgPSAwXG4gIHZhciB4ID0gMFxuICB2YXIgeSA9IDBcbiAgdmFyIG1vZHMgPSB7XG4gICAgc2hpZnQ6IGZhbHNlLFxuICAgIGFsdDogZmFsc2UsXG4gICAgY29udHJvbDogZmFsc2UsXG4gICAgbWV0YTogZmFsc2VcbiAgfVxuICB2YXIgYXR0YWNoZWQgPSBmYWxzZVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZU1vZHMgKGV2KSB7XG4gICAgdmFyIGNoYW5nZWQgPSBmYWxzZVxuICAgIGlmICgnYWx0S2V5JyBpbiBldikge1xuICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgZXYuYWx0S2V5ICE9PSBtb2RzLmFsdFxuICAgICAgbW9kcy5hbHQgPSAhIWV2LmFsdEtleVxuICAgIH1cbiAgICBpZiAoJ3NoaWZ0S2V5JyBpbiBldikge1xuICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgZXYuc2hpZnRLZXkgIT09IG1vZHMuc2hpZnRcbiAgICAgIG1vZHMuc2hpZnQgPSAhIWV2LnNoaWZ0S2V5XG4gICAgfVxuICAgIGlmICgnY3RybEtleScgaW4gZXYpIHtcbiAgICAgIGNoYW5nZWQgPSBjaGFuZ2VkIHx8IGV2LmN0cmxLZXkgIT09IG1vZHMuY29udHJvbFxuICAgICAgbW9kcy5jb250cm9sID0gISFldi5jdHJsS2V5XG4gICAgfVxuICAgIGlmICgnbWV0YUtleScgaW4gZXYpIHtcbiAgICAgIGNoYW5nZWQgPSBjaGFuZ2VkIHx8IGV2Lm1ldGFLZXkgIT09IG1vZHMubWV0YVxuICAgICAgbW9kcy5tZXRhID0gISFldi5tZXRhS2V5XG4gICAgfVxuICAgIHJldHVybiBjaGFuZ2VkXG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVFdmVudCAobmV4dEJ1dHRvbnMsIGV2KSB7XG4gICAgdmFyIG5leHRYID0gbW91c2UueChldilcbiAgICB2YXIgbmV4dFkgPSBtb3VzZS55KGV2KVxuICAgIGlmICgnYnV0dG9ucycgaW4gZXYpIHtcbiAgICAgIG5leHRCdXR0b25zID0gZXYuYnV0dG9ucyB8IDBcbiAgICB9XG4gICAgaWYgKG5leHRCdXR0b25zICE9PSBidXR0b25TdGF0ZSB8fFxuICAgICAgbmV4dFggIT09IHggfHxcbiAgICAgIG5leHRZICE9PSB5IHx8XG4gICAgICB1cGRhdGVNb2RzKGV2KSkge1xuICAgICAgYnV0dG9uU3RhdGUgPSBuZXh0QnV0dG9ucyB8IDBcbiAgICAgIHggPSBuZXh0WCB8fCAwXG4gICAgICB5ID0gbmV4dFkgfHwgMFxuICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soYnV0dG9uU3RhdGUsIHgsIHksIG1vZHMpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJTdGF0ZSAoZXYpIHtcbiAgICBoYW5kbGVFdmVudCgwLCBldilcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUJsdXIgKCkge1xuICAgIGlmIChidXR0b25TdGF0ZSB8fFxuICAgICAgeCB8fFxuICAgICAgeSB8fFxuICAgICAgbW9kcy5zaGlmdCB8fFxuICAgICAgbW9kcy5hbHQgfHxcbiAgICAgIG1vZHMubWV0YSB8fFxuICAgICAgbW9kcy5jb250cm9sKSB7XG4gICAgICB4ID0geSA9IDBcbiAgICAgIGJ1dHRvblN0YXRlID0gMFxuICAgICAgbW9kcy5zaGlmdCA9IG1vZHMuYWx0ID0gbW9kcy5jb250cm9sID0gbW9kcy5tZXRhID0gZmFsc2VcbiAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKDAsIDAsIDAsIG1vZHMpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlTW9kcyAoZXYpIHtcbiAgICBpZiAodXBkYXRlTW9kcyhldikpIHtcbiAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKGJ1dHRvblN0YXRlLCB4LCB5LCBtb2RzKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZU1vdXNlTW92ZSAoZXYpIHtcbiAgICBpZiAobW91c2UuYnV0dG9ucyhldikgPT09IDApIHtcbiAgICAgIGhhbmRsZUV2ZW50KDAsIGV2KVxuICAgIH0gZWxzZSB7XG4gICAgICBoYW5kbGVFdmVudChidXR0b25TdGF0ZSwgZXYpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlTW91c2VEb3duIChldikge1xuICAgIGhhbmRsZUV2ZW50KGJ1dHRvblN0YXRlIHwgbW91c2UuYnV0dG9ucyhldiksIGV2KVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlTW91c2VVcCAoZXYpIHtcbiAgICBoYW5kbGVFdmVudChidXR0b25TdGF0ZSAmIH5tb3VzZS5idXR0b25zKGV2KSwgZXYpXG4gIH1cblxuICBmdW5jdGlvbiBhdHRhY2hMaXN0ZW5lcnMgKCkge1xuICAgIGlmIChhdHRhY2hlZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGF0dGFjaGVkID0gdHJ1ZVxuXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBoYW5kbGVNb3VzZU1vdmUpXG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGhhbmRsZU1vdXNlRG93bilcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIGhhbmRsZU1vdXNlVXApXG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBjbGVhclN0YXRlKVxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIGNsZWFyU3RhdGUpXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIGNsZWFyU3RhdGUpXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCBjbGVhclN0YXRlKVxuXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgaGFuZGxlQmx1cilcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCBoYW5kbGVNb2RzKVxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZU1vZHMpXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIGhhbmRsZU1vZHMpXG5cbiAgICBpZiAoZWxlbWVudCAhPT0gd2luZG93KSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIGhhbmRsZUJsdXIpXG5cbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIGhhbmRsZU1vZHMpXG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZU1vZHMpXG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCBoYW5kbGVNb2RzKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGRldGFjaExpc3RlbmVycyAoKSB7XG4gICAgaWYgKCFhdHRhY2hlZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGF0dGFjaGVkID0gZmFsc2VcblxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgaGFuZGxlTW91c2VNb3ZlKVxuXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBoYW5kbGVNb3VzZURvd24pXG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBoYW5kbGVNb3VzZVVwKVxuXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgY2xlYXJTdGF0ZSlcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCBjbGVhclN0YXRlKVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCBjbGVhclN0YXRlKVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VvdmVyJywgY2xlYXJTdGF0ZSlcblxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmx1cicsIGhhbmRsZUJsdXIpXG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXVwJywgaGFuZGxlTW9kcylcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBoYW5kbGVNb2RzKVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCBoYW5kbGVNb2RzKVxuXG4gICAgaWYgKGVsZW1lbnQgIT09IHdpbmRvdykge1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCBoYW5kbGVCbHVyKVxuXG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCBoYW5kbGVNb2RzKVxuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBoYW5kbGVNb2RzKVxuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXByZXNzJywgaGFuZGxlTW9kcylcbiAgICB9XG4gIH1cblxuICAvLyBBdHRhY2ggbGlzdGVuZXJzXG4gIGF0dGFjaExpc3RlbmVycygpXG5cbiAgdmFyIHJlc3VsdCA9IHtcbiAgICBlbGVtZW50OiBlbGVtZW50XG4gIH1cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhyZXN1bHQsIHtcbiAgICBlbmFibGVkOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGF0dGFjaGVkIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgIGlmIChmKSB7XG4gICAgICAgICAgYXR0YWNoTGlzdGVuZXJzKClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkZXRhY2hMaXN0ZW5lcnMoKVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH0sXG4gICAgYnV0dG9uczoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBidXR0b25TdGF0ZSB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH0sXG4gICAgeDoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB4IH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHkgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIG1vZHM6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gbW9kcyB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH1cbiAgfSlcblxuICByZXR1cm4gcmVzdWx0XG59XG4iLCJ2YXIgcm9vdFBvc2l0aW9uID0geyBsZWZ0OiAwLCB0b3A6IDAgfVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1vdXNlRXZlbnRPZmZzZXRcbmZ1bmN0aW9uIG1vdXNlRXZlbnRPZmZzZXQgKGV2LCB0YXJnZXQsIG91dCkge1xuICB0YXJnZXQgPSB0YXJnZXQgfHwgZXYuY3VycmVudFRhcmdldCB8fCBldi5zcmNFbGVtZW50XG4gIGlmICghQXJyYXkuaXNBcnJheShvdXQpKSB7XG4gICAgb3V0ID0gWyAwLCAwIF1cbiAgfVxuICB2YXIgY3ggPSBldi5jbGllbnRYIHx8IDBcbiAgdmFyIGN5ID0gZXYuY2xpZW50WSB8fCAwXG4gIHZhciByZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRPZmZzZXQodGFyZ2V0KVxuICBvdXRbMF0gPSBjeCAtIHJlY3QubGVmdFxuICBvdXRbMV0gPSBjeSAtIHJlY3QudG9wXG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gZ2V0Qm91bmRpbmdDbGllbnRPZmZzZXQgKGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQgPT09IHdpbmRvdyB8fFxuICAgICAgZWxlbWVudCA9PT0gZG9jdW1lbnQgfHxcbiAgICAgIGVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICByZXR1cm4gcm9vdFBvc2l0aW9uXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbmZ1bmN0aW9uIG1vdXNlQnV0dG9ucyhldikge1xuICBpZih0eXBlb2YgZXYgPT09ICdvYmplY3QnKSB7XG4gICAgaWYoJ2J1dHRvbnMnIGluIGV2KSB7XG4gICAgICByZXR1cm4gZXYuYnV0dG9uc1xuICAgIH0gZWxzZSBpZignd2hpY2gnIGluIGV2KSB7XG4gICAgICB2YXIgYiA9IGV2LndoaWNoXG4gICAgICBpZihiID09PSAyKSB7XG4gICAgICAgIHJldHVybiA0XG4gICAgICB9IGVsc2UgaWYoYiA9PT0gMykge1xuICAgICAgICByZXR1cm4gMlxuICAgICAgfSBlbHNlIGlmKGIgPiAwKSB7XG4gICAgICAgIHJldHVybiAxPDwoYi0xKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZignYnV0dG9uJyBpbiBldikge1xuICAgICAgdmFyIGIgPSBldi5idXR0b25cbiAgICAgIGlmKGIgPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIDRcbiAgICAgIH0gZWxzZSBpZihiID09PSAyKSB7XG4gICAgICAgIHJldHVybiAyXG4gICAgICB9IGVsc2UgaWYoYiA+PSAwKSB7XG4gICAgICAgIHJldHVybiAxPDxiXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiAwXG59XG5leHBvcnRzLmJ1dHRvbnMgPSBtb3VzZUJ1dHRvbnNcblxuZnVuY3Rpb24gbW91c2VFbGVtZW50KGV2KSB7XG4gIHJldHVybiBldi50YXJnZXQgfHwgZXYuc3JjRWxlbWVudCB8fCB3aW5kb3dcbn1cbmV4cG9ydHMuZWxlbWVudCA9IG1vdXNlRWxlbWVudFxuXG5mdW5jdGlvbiBtb3VzZVJlbGF0aXZlWChldikge1xuICBpZih0eXBlb2YgZXYgPT09ICdvYmplY3QnKSB7XG4gICAgaWYoJ29mZnNldFgnIGluIGV2KSB7XG4gICAgICByZXR1cm4gZXYub2Zmc2V0WFxuICAgIH1cbiAgICB2YXIgdGFyZ2V0ID0gbW91c2VFbGVtZW50KGV2KVxuICAgIHZhciBib3VuZHMgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICByZXR1cm4gZXYuY2xpZW50WCAtIGJvdW5kcy5sZWZ0XG4gIH1cbiAgcmV0dXJuIDBcbn1cbmV4cG9ydHMueCA9IG1vdXNlUmVsYXRpdmVYXG5cbmZ1bmN0aW9uIG1vdXNlUmVsYXRpdmVZKGV2KSB7XG4gIGlmKHR5cGVvZiBldiA9PT0gJ29iamVjdCcpIHtcbiAgICBpZignb2Zmc2V0WScgaW4gZXYpIHtcbiAgICAgIHJldHVybiBldi5vZmZzZXRZXG4gICAgfVxuICAgIHZhciB0YXJnZXQgPSBtb3VzZUVsZW1lbnQoZXYpXG4gICAgdmFyIGJvdW5kcyA9IHRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgIHJldHVybiBldi5jbGllbnRZIC0gYm91bmRzLnRvcFxuICB9XG4gIHJldHVybiAwXG59XG5leHBvcnRzLnkgPSBtb3VzZVJlbGF0aXZlWVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciB0b1BYID0gcmVxdWlyZSgndG8tcHgnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1vdXNlV2hlZWxMaXN0ZW5cblxuZnVuY3Rpb24gbW91c2VXaGVlbExpc3RlbihlbGVtZW50LCBjYWxsYmFjaywgbm9TY3JvbGwpIHtcbiAgaWYodHlwZW9mIGVsZW1lbnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICBub1Njcm9sbCA9ICEhY2FsbGJhY2tcbiAgICBjYWxsYmFjayA9IGVsZW1lbnRcbiAgICBlbGVtZW50ID0gd2luZG93XG4gIH1cbiAgdmFyIGxpbmVIZWlnaHQgPSB0b1BYKCdleCcsIGVsZW1lbnQpXG4gIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uKGV2KSB7XG4gICAgaWYobm9TY3JvbGwpIHtcbiAgICAgIGV2LnByZXZlbnREZWZhdWx0KClcbiAgICB9XG4gICAgdmFyIGR4ID0gZXYuZGVsdGFYIHx8IDBcbiAgICB2YXIgZHkgPSBldi5kZWx0YVkgfHwgMFxuICAgIHZhciBkeiA9IGV2LmRlbHRhWiB8fCAwXG4gICAgdmFyIG1vZGUgPSBldi5kZWx0YU1vZGVcbiAgICB2YXIgc2NhbGUgPSAxXG4gICAgc3dpdGNoKG1vZGUpIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgc2NhbGUgPSBsaW5lSGVpZ2h0XG4gICAgICBicmVha1xuICAgICAgY2FzZSAyOlxuICAgICAgICBzY2FsZSA9IHdpbmRvdy5pbm5lckhlaWdodFxuICAgICAgYnJlYWtcbiAgICB9XG4gICAgZHggKj0gc2NhbGVcbiAgICBkeSAqPSBzY2FsZVxuICAgIGR6ICo9IHNjYWxlXG4gICAgaWYoZHggfHwgZHkgfHwgZHopIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhkeCwgZHksIGR6LCBldilcbiAgICB9XG4gIH1cbiAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd3aGVlbCcsIGxpc3RlbmVyKVxuICByZXR1cm4gbGlzdGVuZXJcbn1cbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBwb29sID0gcmVxdWlyZShcInR5cGVkYXJyYXktcG9vbFwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVN1cmZhY2VFeHRyYWN0b3JcblxuLy9IZWxwZXIgbWFjcm9zXG5mdW5jdGlvbiBhcnJheShpKSB7XG4gIHJldHVybiBcImFcIiArIGlcbn1cbmZ1bmN0aW9uIGRhdGEoaSkge1xuICByZXR1cm4gXCJkXCIgKyBpXG59XG5mdW5jdGlvbiBjdWJlKGksYml0bWFzaykge1xuICByZXR1cm4gXCJjXCIgKyBpICsgXCJfXCIgKyBiaXRtYXNrXG59XG5mdW5jdGlvbiBzaGFwZShpKSB7XG4gIHJldHVybiBcInNcIiArIGlcbn1cbmZ1bmN0aW9uIHN0cmlkZShpLGopIHtcbiAgcmV0dXJuIFwidFwiICsgaSArIFwiX1wiICsgalxufVxuZnVuY3Rpb24gb2Zmc2V0KGkpIHtcbiAgcmV0dXJuIFwib1wiICsgaVxufVxuZnVuY3Rpb24gc2NhbGFyKGkpIHtcbiAgcmV0dXJuIFwieFwiICsgaVxufVxuZnVuY3Rpb24gcG9pbnRlcihpKSB7XG4gIHJldHVybiBcInBcIiArIGlcbn1cbmZ1bmN0aW9uIGRlbHRhKGksYml0bWFzaykge1xuICByZXR1cm4gXCJkXCIgKyBpICsgXCJfXCIgKyBiaXRtYXNrXG59XG5mdW5jdGlvbiBpbmRleChpKSB7XG4gIHJldHVybiBcImlcIiArIGlcbn1cbmZ1bmN0aW9uIHN0ZXAoaSxqKSB7XG4gIHJldHVybiBcInVcIiArIGkgKyBcIl9cIiArIGpcbn1cbmZ1bmN0aW9uIHBjdWJlKGJpdG1hc2spIHtcbiAgcmV0dXJuIFwiYlwiICsgYml0bWFza1xufVxuZnVuY3Rpb24gcWN1YmUoYml0bWFzaykge1xuICByZXR1cm4gXCJ5XCIgKyBiaXRtYXNrXG59XG5mdW5jdGlvbiBwZGVsdGEoYml0bWFzaykge1xuICByZXR1cm4gXCJlXCIgKyBiaXRtYXNrXG59XG5mdW5jdGlvbiB2ZXJ0KGkpIHtcbiAgcmV0dXJuIFwidlwiICsgaVxufVxudmFyIFZFUlRFWF9JRFMgPSBcIlZcIlxudmFyIFBIQVNFUyA9IFwiUFwiXG52YXIgVkVSVEVYX0NPVU5UID0gXCJOXCJcbnZhciBQT09MX1NJWkUgPSBcIlFcIlxudmFyIFBPSU5URVIgPSBcIlhcIlxudmFyIFRFTVBPUkFSWSA9IFwiVFwiXG5cbmZ1bmN0aW9uIHBlcm1CaXRtYXNrKGRpbWVuc2lvbiwgbWFzaywgb3JkZXIpIHtcbiAgdmFyIHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgaWYobWFzayAmICgxPDxpKSkge1xuICAgICAgciB8PSAoMTw8b3JkZXJbaV0pXG4gICAgfVxuICB9XG4gIHJldHVybiByXG59XG5cbi8vR2VuZXJhdGVzIHRoZSBzdXJmYWNlIHByb2NlZHVyZVxuZnVuY3Rpb24gY29tcGlsZVN1cmZhY2VQcm9jZWR1cmUodmVydGV4RnVuYywgZmFjZUZ1bmMsIHBoYXNlRnVuYywgc2NhbGFyQXJncywgb3JkZXIsIHR5cGVzaWcpIHtcbiAgdmFyIGFycmF5QXJncyA9IHR5cGVzaWcubGVuZ3RoXG4gIHZhciBkaW1lbnNpb24gPSBvcmRlci5sZW5ndGhcblxuICBpZihkaW1lbnNpb24gPCAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibmRhcnJheS1leHRyYWN0LWNvbnRvdXI6IERpbWVuc2lvbiBtdXN0IGJlIGF0IGxlYXN0IDJcIilcbiAgfVxuXG4gIHZhciBmdW5jTmFtZSA9IFwiZXh0cmFjdENvbnRvdXJcIiArIG9yZGVyLmpvaW4oXCJfXCIpXG4gIHZhciBjb2RlID0gW11cbiAgdmFyIHZhcnMgPSBbXVxuICB2YXIgYXJncyA9IFtdXG5cbiAgLy9Bc3NlbWJsZSBhcmd1bWVudHNcbiAgZm9yKHZhciBpPTA7IGk8YXJyYXlBcmdzOyArK2kpIHtcbiAgICBhcmdzLnB1c2goYXJyYXkoaSkpICBcbiAgfVxuICBmb3IodmFyIGk9MDsgaTxzY2FsYXJBcmdzOyArK2kpIHtcbiAgICBhcmdzLnB1c2goc2NhbGFyKGkpKVxuICB9XG5cbiAgLy9TaGFwZVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIHZhcnMucHVzaChzaGFwZShpKSArIFwiPVwiICsgYXJyYXkoMCkgKyBcIi5zaGFwZVtcIiArIGkgKyBcIl18MFwiKVxuICB9XG4gIC8vRGF0YSwgc3RyaWRlLCBvZmZzZXQgcG9pbnRlcnNcbiAgZm9yKHZhciBpPTA7IGk8YXJyYXlBcmdzOyArK2kpIHtcbiAgICB2YXJzLnB1c2goZGF0YShpKSArIFwiPVwiICsgYXJyYXkoaSkgKyBcIi5kYXRhXCIsXG4gICAgICAgICAgICAgIG9mZnNldChpKSArIFwiPVwiICsgYXJyYXkoaSkgKyBcIi5vZmZzZXR8MFwiKVxuICAgIGZvcih2YXIgaj0wOyBqPGRpbWVuc2lvbjsgKytqKSB7XG4gICAgICB2YXJzLnB1c2goc3RyaWRlKGksaikgKyBcIj1cIiArIGFycmF5KGkpICsgXCIuc3RyaWRlW1wiICsgaiArIFwiXXwwXCIpXG4gICAgfVxuICB9XG4gIC8vUG9pbnRlciwgZGVsdGEgYW5kIGN1YmUgdmFyaWFibGVzXG4gIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgdmFycy5wdXNoKHBvaW50ZXIoaSkgKyBcIj1cIiArIG9mZnNldChpKSlcbiAgICB2YXJzLnB1c2goY3ViZShpLDApKVxuICAgIGZvcih2YXIgaj0xOyBqPCgxPDxkaW1lbnNpb24pOyArK2opIHtcbiAgICAgIHZhciBwdHJTdHIgPSBbXVxuICAgICAgZm9yKHZhciBrPTA7IGs8ZGltZW5zaW9uOyArK2spIHtcbiAgICAgICAgaWYoaiAmICgxPDxrKSkge1xuICAgICAgICAgIHB0clN0ci5wdXNoKFwiLVwiICsgc3RyaWRlKGksaykpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhcnMucHVzaChkZWx0YShpLGopICsgXCI9KFwiICsgcHRyU3RyLmpvaW4oXCJcIikgKyBcIil8MFwiKVxuICAgICAgdmFycy5wdXNoKGN1YmUoaSxqKSArIFwiPTBcIilcbiAgICB9XG4gIH1cbiAgLy9DcmVhdGUgc3RlcCB2YXJpYWJsZXNcbiAgZm9yKHZhciBpPTA7IGk8YXJyYXlBcmdzOyArK2kpIHtcbiAgICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikge1xuICAgICAgdmFyIHN0ZXBWYWwgPSBbIHN0cmlkZShpLG9yZGVyW2pdKSBdXG4gICAgICBpZihqID4gMCkge1xuICAgICAgICBzdGVwVmFsLnB1c2goc3RyaWRlKGksIG9yZGVyW2otMV0pICsgXCIqXCIgKyBzaGFwZShvcmRlcltqLTFdKSApXG4gICAgICB9XG4gICAgICB2YXJzLnB1c2goc3RlcChpLG9yZGVyW2pdKSArIFwiPShcIiArIHN0ZXBWYWwuam9pbihcIi1cIikgKyBcIil8MFwiKVxuICAgIH1cbiAgfVxuICAvL0NyZWF0ZSBpbmRleCB2YXJpYWJsZXNcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICB2YXJzLnB1c2goaW5kZXgoaSkgKyBcIj0wXCIpXG4gIH1cbiAgLy9WZXJ0ZXggY291bnRcbiAgdmFycy5wdXNoKFZFUlRFWF9DT1VOVCArIFwiPTBcIilcbiAgLy9Db21wdXRlIHBvb2wgc2l6ZSwgaW5pdGlhbGl6ZSBwb29sIHN0ZXBcbiAgdmFyIHNpemVWYXJpYWJsZSA9IFtcIjJcIl1cbiAgZm9yKHZhciBpPWRpbWVuc2lvbi0yOyBpPj0wOyAtLWkpIHtcbiAgICBzaXplVmFyaWFibGUucHVzaChzaGFwZShvcmRlcltpXSkpXG4gIH1cbiAgLy9QcmV2aW91cyBwaGFzZXMgYW5kIHZlcnRleF9pZHNcbiAgdmFycy5wdXNoKFBPT0xfU0laRSArIFwiPShcIiArIHNpemVWYXJpYWJsZS5qb2luKFwiKlwiKSArIFwiKXwwXCIsXG4gICAgICAgICAgICBQSEFTRVMgKyBcIj1tYWxsb2NVaW50MzIoXCIgKyBQT09MX1NJWkUgKyBcIilcIixcbiAgICAgICAgICAgIFZFUlRFWF9JRFMgKyBcIj1tYWxsb2NVaW50MzIoXCIgKyBQT09MX1NJWkUgKyBcIilcIixcbiAgICAgICAgICAgIFBPSU5URVIgKyBcIj0wXCIpXG4gIC8vQ3JlYXRlIGN1YmUgdmFyaWFibGVzIGZvciBwaGFzZXNcbiAgdmFycy5wdXNoKHBjdWJlKDApICsgXCI9MFwiKVxuICBmb3IodmFyIGo9MTsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgdmFyIGN1YmVEZWx0YSA9IFtdXG4gICAgdmFyIGN1YmVTdGVwID0gWyBdXG4gICAgZm9yKHZhciBrPTA7IGs8ZGltZW5zaW9uOyArK2spIHtcbiAgICAgIGlmKGogJiAoMTw8aykpIHtcbiAgICAgICAgaWYoY3ViZVN0ZXAubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY3ViZURlbHRhLnB1c2goXCIxXCIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3ViZURlbHRhLnVuc2hpZnQoY3ViZVN0ZXAuam9pbihcIipcIikpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGN1YmVTdGVwLnB1c2goc2hhcGUob3JkZXJba10pKVxuICAgIH1cbiAgICB2YXIgc2lnbkZsYWcgPSBcIlwiXG4gICAgaWYoY3ViZURlbHRhWzBdLmluZGV4T2Yoc2hhcGUob3JkZXJbZGltZW5zaW9uLTJdKSkgPCAwKSB7XG4gICAgICBzaWduRmxhZyA9IFwiLVwiXG4gICAgfVxuICAgIHZhciBqcGVybSA9IHBlcm1CaXRtYXNrKGRpbWVuc2lvbiwgaiwgb3JkZXIpXG4gICAgdmFycy5wdXNoKHBkZWx0YShqcGVybSkgKyBcIj0oLVwiICsgY3ViZURlbHRhLmpvaW4oXCItXCIpICsgXCIpfDBcIixcbiAgICAgICAgICAgICAgcWN1YmUoanBlcm0pICsgXCI9KFwiICsgc2lnbkZsYWcgKyBjdWJlRGVsdGEuam9pbihcIi1cIikgKyBcIil8MFwiLFxuICAgICAgICAgICAgICBwY3ViZShqcGVybSkgKyBcIj0wXCIpXG4gIH1cbiAgdmFycy5wdXNoKHZlcnQoMCkgKyBcIj0wXCIsIFRFTVBPUkFSWSArIFwiPTBcIilcblxuICBmdW5jdGlvbiBmb3JMb29wQmVnaW4oaSwgc3RhcnQpIHtcbiAgICBjb2RlLnB1c2goXCJmb3IoXCIsIGluZGV4KG9yZGVyW2ldKSwgXCI9XCIsIHN0YXJ0LCBcIjtcIixcbiAgICAgIGluZGV4KG9yZGVyW2ldKSwgXCI8XCIsIHNoYXBlKG9yZGVyW2ldKSwgXCI7XCIsXG4gICAgICBcIisrXCIsIGluZGV4KG9yZGVyW2ldKSwgXCIpe1wiKVxuICB9XG5cbiAgZnVuY3Rpb24gZm9yTG9vcEVuZChpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8YXJyYXlBcmdzOyArK2opIHtcbiAgICAgIGNvZGUucHVzaChwb2ludGVyKGopLCBcIis9XCIsIHN0ZXAoaixvcmRlcltpXSksIFwiO1wiKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJ9XCIpXG4gIH1cblxuICBmdW5jdGlvbiBmaWxsRW1wdHlTbGljZShrKSB7XG4gICAgZm9yKHZhciBpPWstMTsgaT49MDsgLS1pKSB7XG4gICAgICBmb3JMb29wQmVnaW4oaSwgMCkgXG4gICAgfVxuICAgIHZhciBwaGFzZUZ1bmNBcmdzID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxhcnJheUFyZ3M7ICsraSkge1xuICAgICAgaWYodHlwZXNpZ1tpXSkge1xuICAgICAgICBwaGFzZUZ1bmNBcmdzLnB1c2goZGF0YShpKSArIFwiLmdldChcIiArIHBvaW50ZXIoaSkgKyBcIilcIilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBoYXNlRnVuY0FyZ3MucHVzaChkYXRhKGkpICsgXCJbXCIgKyBwb2ludGVyKGkpICsgXCJdXCIpXG4gICAgICB9XG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPHNjYWxhckFyZ3M7ICsraSkge1xuICAgICAgcGhhc2VGdW5jQXJncy5wdXNoKHNjYWxhcihpKSlcbiAgICB9XG4gICAgY29kZS5wdXNoKFBIQVNFUywgXCJbXCIsIFBPSU5URVIsIFwiKytdPXBoYXNlKFwiLCBwaGFzZUZ1bmNBcmdzLmpvaW4oKSwgXCIpO1wiKVxuICAgIGZvcih2YXIgaT0wOyBpPGs7ICsraSkge1xuICAgICAgZm9yTG9vcEVuZChpKVxuICAgIH1cbiAgICBmb3IodmFyIGo9MDsgajxhcnJheUFyZ3M7ICsraikge1xuICAgICAgY29kZS5wdXNoKHBvaW50ZXIoaiksIFwiKz1cIiwgc3RlcChqLG9yZGVyW2tdKSwgXCI7XCIpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc0dyaWRDZWxsKG1hc2spIHtcbiAgICAvL1JlYWQgaW4gbG9jYWwgZGF0YVxuICAgIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgICBpZih0eXBlc2lnW2ldKSB7XG4gICAgICAgIGNvZGUucHVzaChjdWJlKGksMCksIFwiPVwiLCBkYXRhKGkpLCBcIi5nZXQoXCIsIHBvaW50ZXIoaSksIFwiKTtcIilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvZGUucHVzaChjdWJlKGksMCksIFwiPVwiLCBkYXRhKGkpLCBcIltcIiwgcG9pbnRlcihpKSwgXCJdO1wiKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vUmVhZCBpbiBwaGFzZVxuICAgIHZhciBwaGFzZUZ1bmNBcmdzID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxhcnJheUFyZ3M7ICsraSkge1xuICAgICAgcGhhc2VGdW5jQXJncy5wdXNoKGN1YmUoaSwwKSlcbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8c2NhbGFyQXJnczsgKytpKSB7XG4gICAgICBwaGFzZUZ1bmNBcmdzLnB1c2goc2NhbGFyKGkpKVxuICAgIH1cbiAgICBcbiAgICBjb2RlLnB1c2gocGN1YmUoMCksIFwiPVwiLCBQSEFTRVMsIFwiW1wiLCBQT0lOVEVSLCBcIl09cGhhc2UoXCIsIHBoYXNlRnVuY0FyZ3Muam9pbigpLCBcIik7XCIpXG4gICAgXG4gICAgLy9SZWFkIGluIG90aGVyIGN1YmUgZGF0YVxuICAgIGZvcih2YXIgaj0xOyBqPCgxPDxkaW1lbnNpb24pOyArK2opIHtcbiAgICAgIGNvZGUucHVzaChwY3ViZShqKSwgXCI9XCIsIFBIQVNFUywgXCJbXCIsIFBPSU5URVIsIFwiK1wiLCBwZGVsdGEoaiksIFwiXTtcIilcbiAgICB9XG5cbiAgICAvL0NoZWNrIGZvciBib3VuZGFyeSBjcm9zc2luZ1xuICAgIHZhciB2ZXJ0ZXhQcmVkaWNhdGUgPSBbXVxuICAgIGZvcih2YXIgaj0xOyBqPCgxPDxkaW1lbnNpb24pOyArK2opIHtcbiAgICAgIHZlcnRleFByZWRpY2F0ZS5wdXNoKFwiKFwiICsgcGN1YmUoMCkgKyBcIiE9PVwiICsgcGN1YmUoaikgKyBcIilcIilcbiAgICB9XG4gICAgY29kZS5wdXNoKFwiaWYoXCIsIHZlcnRleFByZWRpY2F0ZS5qb2luKFwifHxcIiksIFwiKXtcIilcblxuICAgIC8vUmVhZCBpbiBib3VuZGFyeSBkYXRhXG4gICAgdmFyIHZlcnRleEFyZ3MgPSBbXVxuICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICB2ZXJ0ZXhBcmdzLnB1c2goaW5kZXgoaSkpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgICB2ZXJ0ZXhBcmdzLnB1c2goY3ViZShpLDApKVxuICAgICAgZm9yKHZhciBqPTE7IGo8KDE8PGRpbWVuc2lvbik7ICsraikge1xuICAgICAgICBpZih0eXBlc2lnW2ldKSB7XG4gICAgICAgICAgY29kZS5wdXNoKGN1YmUoaSxqKSwgXCI9XCIsIGRhdGEoaSksIFwiLmdldChcIiwgcG9pbnRlcihpKSwgXCIrXCIsIGRlbHRhKGksaiksIFwiKTtcIilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb2RlLnB1c2goY3ViZShpLGopLCBcIj1cIiwgZGF0YShpKSwgXCJbXCIsIHBvaW50ZXIoaSksIFwiK1wiLCBkZWx0YShpLGopLCBcIl07XCIpXG4gICAgICAgIH1cbiAgICAgICAgdmVydGV4QXJncy5wdXNoKGN1YmUoaSxqKSlcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8KDE8PGRpbWVuc2lvbik7ICsraSkge1xuICAgICAgdmVydGV4QXJncy5wdXNoKHBjdWJlKGkpKVxuICAgIH1cbiAgICBmb3IodmFyIGk9MDsgaTxzY2FsYXJBcmdzOyArK2kpIHtcbiAgICAgIHZlcnRleEFyZ3MucHVzaChzY2FsYXIoaSkpXG4gICAgfVxuXG4gICAgLy9HZW5lcmF0ZSB2ZXJ0ZXhcbiAgICBjb2RlLnB1c2goXCJ2ZXJ0ZXgoXCIsIHZlcnRleEFyZ3Muam9pbigpLCBcIik7XCIsXG4gICAgICB2ZXJ0KDApLCBcIj1cIiwgVkVSVEVYX0lEUywgXCJbXCIsIFBPSU5URVIsIFwiXT1cIiwgVkVSVEVYX0NPVU5ULCBcIisrO1wiKVxuXG4gICAgLy9DaGVjayBmb3IgZmFjZSBjcm9zc2luZ3NcbiAgICB2YXIgYmFzZSA9ICgxPDxkaW1lbnNpb24pLTFcbiAgICB2YXIgY29ybmVyID0gcGN1YmUoYmFzZSlcbiAgICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikge1xuICAgICAgaWYoKG1hc2sgJiB+KDE8PGopKT09PTApIHtcbiAgICAgICAgLy9DaGVjayBmYWNlXG4gICAgICAgIHZhciBzdWJzZXQgPSBiYXNlXigxPDxqKVxuICAgICAgICB2YXIgZWRnZSA9IHBjdWJlKHN1YnNldClcbiAgICAgICAgdmFyIGZhY2VBcmdzID0gWyBdXG4gICAgICAgIGZvcih2YXIgaz1zdWJzZXQ7IGs+MDsgaz0oay0xKSZzdWJzZXQpIHtcbiAgICAgICAgICBmYWNlQXJncy5wdXNoKFZFUlRFWF9JRFMgKyBcIltcIiArIFBPSU5URVIgKyBcIitcIiArIHBkZWx0YShrKSArIFwiXVwiKVxuICAgICAgICB9XG4gICAgICAgIGZhY2VBcmdzLnB1c2godmVydCgwKSlcbiAgICAgICAgZm9yKHZhciBrPTA7IGs8YXJyYXlBcmdzOyArK2spIHtcbiAgICAgICAgICBpZihqJjEpIHtcbiAgICAgICAgICAgIGZhY2VBcmdzLnB1c2goY3ViZShrLGJhc2UpLCBjdWJlKGssc3Vic2V0KSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmFjZUFyZ3MucHVzaChjdWJlKGssc3Vic2V0KSwgY3ViZShrLGJhc2UpKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZihqJjEpIHtcbiAgICAgICAgICBmYWNlQXJncy5wdXNoKGNvcm5lciwgZWRnZSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmYWNlQXJncy5wdXNoKGVkZ2UsIGNvcm5lcilcbiAgICAgICAgfVxuICAgICAgICBmb3IodmFyIGs9MDsgazxzY2FsYXJBcmdzOyArK2spIHtcbiAgICAgICAgICBmYWNlQXJncy5wdXNoKHNjYWxhcihrKSlcbiAgICAgICAgfVxuICAgICAgICBjb2RlLnB1c2goXCJpZihcIiwgY29ybmVyLCBcIiE9PVwiLCBlZGdlLCBcIil7XCIsXG4gICAgICAgICAgXCJmYWNlKFwiLCBmYWNlQXJncy5qb2luKCksIFwiKX1cIilcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy9JbmNyZW1lbnQgcG9pbnRlciwgY2xvc2Ugb2ZmIGlmIHN0YXRlbWVudFxuICAgIGNvZGUucHVzaChcIn1cIixcbiAgICAgIFBPSU5URVIsIFwiKz0xO1wiKVxuICB9XG5cbiAgZnVuY3Rpb24gZmxpcCgpIHtcbiAgICBmb3IodmFyIGo9MTsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgICBjb2RlLnB1c2goVEVNUE9SQVJZLCBcIj1cIiwgcGRlbHRhKGopLCBcIjtcIixcbiAgICAgICAgICAgICAgICBwZGVsdGEoaiksIFwiPVwiLCBxY3ViZShqKSwgXCI7XCIsXG4gICAgICAgICAgICAgICAgcWN1YmUoaiksIFwiPVwiLCBURU1QT1JBUlksIFwiO1wiKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZUxvb3AoaSwgbWFzaykge1xuICAgIGlmKGkgPCAwKSB7XG4gICAgICBwcm9jZXNzR3JpZENlbGwobWFzaylcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBmaWxsRW1wdHlTbGljZShpKVxuICAgIGNvZGUucHVzaChcImlmKFwiLCBzaGFwZShvcmRlcltpXSksIFwiPjApe1wiLFxuICAgICAgaW5kZXgob3JkZXJbaV0pLCBcIj0xO1wiKVxuICAgIGNyZWF0ZUxvb3AoaS0xLCBtYXNrfCgxPDxvcmRlcltpXSkpXG5cbiAgICBmb3IodmFyIGo9MDsgajxhcnJheUFyZ3M7ICsraikge1xuICAgICAgY29kZS5wdXNoKHBvaW50ZXIoaiksIFwiKz1cIiwgc3RlcChqLG9yZGVyW2ldKSwgXCI7XCIpXG4gICAgfVxuICAgIGlmKGkgPT09IGRpbWVuc2lvbi0xKSB7XG4gICAgICBjb2RlLnB1c2goUE9JTlRFUiwgXCI9MDtcIilcbiAgICAgIGZsaXAoKVxuICAgIH1cbiAgICBmb3JMb29wQmVnaW4oaSwgMilcbiAgICBjcmVhdGVMb29wKGktMSwgbWFzaylcbiAgICBpZihpID09PSBkaW1lbnNpb24tMSkge1xuICAgICAgY29kZS5wdXNoKFwiaWYoXCIsIGluZGV4KG9yZGVyW2RpbWVuc2lvbi0xXSksIFwiJjEpe1wiLFxuICAgICAgICBQT0lOVEVSLCBcIj0wO31cIilcbiAgICAgIGZsaXAoKVxuICAgIH1cbiAgICBmb3JMb29wRW5kKGkpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICB9XG5cbiAgY3JlYXRlTG9vcChkaW1lbnNpb24tMSwgMClcblxuICAvL1JlbGVhc2Ugc2NyYXRjaCBtZW1vcnlcbiAgY29kZS5wdXNoKFwiZnJlZVVpbnQzMihcIiwgVkVSVEVYX0lEUywgXCIpO2ZyZWVVaW50MzIoXCIsIFBIQVNFUywgXCIpO1wiKVxuXG4gIC8vQ29tcGlsZSBhbmQgbGluayBwcm9jZWR1cmVcbiAgdmFyIHByb2NlZHVyZUNvZGUgPSBbXG4gICAgXCIndXNlIHN0cmljdCc7XCIsXG4gICAgXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKFwiLCBhcmdzLmpvaW4oKSwgXCIpe1wiLFxuICAgICAgXCJ2YXIgXCIsIHZhcnMuam9pbigpLCBcIjtcIixcbiAgICAgIGNvZGUuam9pbihcIlwiKSxcbiAgICBcIn1cIixcbiAgICBcInJldHVybiBcIiwgZnVuY05hbWUgXS5qb2luKFwiXCIpXG5cbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oXG4gICAgXCJ2ZXJ0ZXhcIiwgXG4gICAgXCJmYWNlXCIsIFxuICAgIFwicGhhc2VcIiwgXG4gICAgXCJtYWxsb2NVaW50MzJcIiwgXG4gICAgXCJmcmVlVWludDMyXCIsXG4gICAgcHJvY2VkdXJlQ29kZSlcbiAgcmV0dXJuIHByb2MoXG4gICAgdmVydGV4RnVuYywgXG4gICAgZmFjZUZ1bmMsIFxuICAgIHBoYXNlRnVuYywgXG4gICAgcG9vbC5tYWxsb2NVaW50MzIsIFxuICAgIHBvb2wuZnJlZVVpbnQzMilcbn1cblxuZnVuY3Rpb24gY3JlYXRlU3VyZmFjZUV4dHJhY3RvcihhcmdzKSB7XG4gIGZ1bmN0aW9uIGVycm9yKG1zZykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm5kYXJyYXktZXh0cmFjdC1jb250b3VyOiBcIiArIG1zZylcbiAgfVxuICBpZih0eXBlb2YgYXJncyAhPT0gXCJvYmplY3RcIikge1xuICAgIGVycm9yKFwiTXVzdCBzcGVjaWZ5IGFyZ3VtZW50c1wiKVxuICB9XG4gIHZhciBvcmRlciA9IGFyZ3Mub3JkZXJcbiAgaWYoIUFycmF5LmlzQXJyYXkob3JkZXIpKSB7XG4gICAgZXJyb3IoXCJNdXN0IHNwZWNpZnkgb3JkZXJcIilcbiAgfVxuICB2YXIgYXJyYXlzID0gYXJncy5hcnJheUFyZ3VtZW50c3x8MVxuICBpZihhcnJheXMgPCAxKSB7XG4gICAgZXJyb3IoXCJNdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGFycmF5IGFyZ3VtZW50XCIpXG4gIH1cbiAgdmFyIHNjYWxhcnMgPSBhcmdzLnNjYWxhckFyZ3VtZW50c3x8MFxuICBpZihzY2FsYXJzIDwgMCkge1xuICAgIGVycm9yKFwiU2NhbGFyIGFyZyBjb3VudCBtdXN0IGJlID4gMFwiKVxuICB9XG4gIGlmKHR5cGVvZiBhcmdzLnZlcnRleCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgZXJyb3IoXCJNdXN0IHNwZWNpZnkgdmVydGV4IGNyZWF0aW9uIGZ1bmN0aW9uXCIpXG4gIH1cbiAgaWYodHlwZW9mIGFyZ3MuY2VsbCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgZXJyb3IoXCJNdXN0IHNwZWNpZnkgY2VsbCBjcmVhdGlvbiBmdW5jdGlvblwiKVxuICB9XG4gIGlmKHR5cGVvZiBhcmdzLnBoYXNlICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBlcnJvcihcIk11c3Qgc3BlY2lmeSBwaGFzZSBmdW5jdGlvblwiKVxuICB9XG4gIHZhciBnZXR0ZXJzID0gYXJncy5nZXR0ZXJzIHx8IFtdXG4gIHZhciB0eXBlc2lnID0gbmV3IEFycmF5KGFycmF5cylcbiAgZm9yKHZhciBpPTA7IGk8YXJyYXlzOyArK2kpIHtcbiAgICBpZihnZXR0ZXJzLmluZGV4T2YoaSkgPj0gMCkge1xuICAgICAgdHlwZXNpZ1tpXSA9IHRydWVcbiAgICB9IGVsc2Uge1xuICAgICAgdHlwZXNpZ1tpXSA9IGZhbHNlXG4gICAgfVxuICB9XG4gIHJldHVybiBjb21waWxlU3VyZmFjZVByb2NlZHVyZShcbiAgICBhcmdzLnZlcnRleCxcbiAgICBhcmdzLmNlbGwsXG4gICAgYXJncy5waGFzZSxcbiAgICBzY2FsYXJzLFxuICAgIG9yZGVyLFxuICAgIHR5cGVzaWcpXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxuXG5cbnZhciBmaWxsID0gcmVxdWlyZSgnY3dpc2UvbGliL3dyYXBwZXInKSh7XCJhcmdzXCI6W1wiaW5kZXhcIixcImFycmF5XCIsXCJzY2FsYXJcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImJvZHlcIjp7XCJib2R5XCI6XCJ7X2lubGluZV8xX2FyZzFfPV9pbmxpbmVfMV9hcmcyXy5hcHBseSh2b2lkIDAsX2lubGluZV8xX2FyZzBfKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMV9hcmcxX1wiLFwibHZhbHVlXCI6dHJ1ZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzFfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcInBvc3RcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwiY3dpc2VcIixcImJsb2NrU2l6ZVwiOjY0fSlcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhcnJheSwgZikge1xuICBmaWxsKGFycmF5LCBmKVxuICByZXR1cm4gYXJyYXlcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyAgICAgID0gZ3JhZGllbnRcblxudmFyIGR1cCAgICAgICAgICAgICA9IHJlcXVpcmUoJ2R1cCcpXG52YXIgY3dpc2VDb21waWxlciAgID0gcmVxdWlyZSgnY3dpc2UtY29tcGlsZXInKVxuXG52YXIgVEVNUExBVEVfQ0FDSEUgID0ge31cbnZhciBHUkFESUVOVF9DQUNIRSAgPSB7fVxuXG52YXIgRW1wdHlQcm9jID0ge1xuICBib2R5OiBcIlwiLFxuICBhcmdzOiBbXSxcbiAgdGhpc1ZhcnM6IFtdLFxuICBsb2NhbFZhcnM6IFtdXG59XG5cbnZhciBjZW50cmFsRGlmZiA9IGN3aXNlQ29tcGlsZXIoe1xuICBhcmdzOiBbICdhcnJheScsICdhcnJheScsICdhcnJheScgXSxcbiAgcHJlOiBFbXB0eVByb2MsXG4gIHBvc3Q6IEVtcHR5UHJvYyxcbiAgYm9keToge1xuICAgIGFyZ3M6IFsge1xuICAgICAgbmFtZTogJ291dCcsIFxuICAgICAgbHZhbHVlOiB0cnVlLFxuICAgICAgcnZhbHVlOiBmYWxzZSxcbiAgICAgIGNvdW50OiAxXG4gICAgfSwge1xuICAgICAgbmFtZTogJ2xlZnQnLCBcbiAgICAgIGx2YWx1ZTogZmFsc2UsXG4gICAgICBydmFsdWU6IHRydWUsXG4gICAgICBjb3VudDogMVxuICAgIH0sIHtcbiAgICAgIG5hbWU6ICdyaWdodCcsIFxuICAgICAgbHZhbHVlOiBmYWxzZSxcbiAgICAgIHJ2YWx1ZTogdHJ1ZSxcbiAgICAgIGNvdW50OiAxXG4gICAgfV0sXG4gICAgYm9keTogXCJvdXQ9MC41KihsZWZ0LXJpZ2h0KVwiLFxuICAgIHRoaXNWYXJzOiBbXSxcbiAgICBsb2NhbFZhcnM6IFtdXG4gIH0sXG4gIGZ1bmNOYW1lOiAnY2RpZmYnXG59KVxuXG52YXIgemVyb091dCA9IGN3aXNlQ29tcGlsZXIoe1xuICBhcmdzOiBbICdhcnJheScgXSxcbiAgcHJlOiBFbXB0eVByb2MsXG4gIHBvc3Q6IEVtcHR5UHJvYyxcbiAgYm9keToge1xuICAgIGFyZ3M6IFsge1xuICAgICAgbmFtZTogJ291dCcsIFxuICAgICAgbHZhbHVlOiB0cnVlLFxuICAgICAgcnZhbHVlOiBmYWxzZSxcbiAgICAgIGNvdW50OiAxXG4gICAgfV0sXG4gICAgYm9keTogXCJvdXQ9MFwiLFxuICAgIHRoaXNWYXJzOiBbXSxcbiAgICBsb2NhbFZhcnM6IFtdXG4gIH0sXG4gIGZ1bmNOYW1lOiAnemVybydcbn0pXG5cbmZ1bmN0aW9uIGdlbmVyYXRlVGVtcGxhdGUoZCkge1xuICBpZihkIGluIFRFTVBMQVRFX0NBQ0hFKSB7XG4gICAgcmV0dXJuIFRFTVBMQVRFX0NBQ0hFW2RdXG4gIH1cbiAgdmFyIGNvZGUgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICBjb2RlLnB1c2goJ291dCcsIGksICdzPTAuNSooaW5wJywgaSwgJ2wtaW5wJywgaSwgJ3IpOycpXG4gIH1cbiAgdmFyIGFyZ3MgPSBbICdhcnJheScgXVxuICB2YXIgbmFtZXMgPSBbJ2p1bmsnXVxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICBhcmdzLnB1c2goJ2FycmF5JylcbiAgICBuYW1lcy5wdXNoKCdvdXQnICsgaSArICdzJylcbiAgICB2YXIgbyA9IGR1cChkKVxuICAgIG9baV0gPSAtMVxuICAgIGFyZ3MucHVzaCh7XG4gICAgICBhcnJheTogMCxcbiAgICAgIG9mZnNldDogby5zbGljZSgpXG4gICAgfSlcbiAgICBvW2ldID0gMVxuICAgIGFyZ3MucHVzaCh7XG4gICAgICBhcnJheTogMCxcbiAgICAgIG9mZnNldDogby5zbGljZSgpXG4gICAgfSlcbiAgICBuYW1lcy5wdXNoKCdpbnAnICsgaSArICdsJywgJ2lucCcgKyBpICsgJ3InKVxuICB9XG4gIHJldHVybiBURU1QTEFURV9DQUNIRVtkXSA9IGN3aXNlQ29tcGlsZXIoe1xuICAgIGFyZ3M6IGFyZ3MsXG4gICAgcHJlOiAgRW1wdHlQcm9jLFxuICAgIHBvc3Q6IEVtcHR5UHJvYyxcbiAgICBib2R5OiB7XG4gICAgICBib2R5OiBjb2RlLmpvaW4oJycpLFxuICAgICAgYXJnczogbmFtZXMubWFwKGZ1bmN0aW9uKG4pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBuYW1lOiBuLFxuICAgICAgICAgIGx2YWx1ZTogbi5pbmRleE9mKCdvdXQnKSA9PT0gMCxcbiAgICAgICAgICBydmFsdWU6IG4uaW5kZXhPZignaW5wJykgPT09IDAsXG4gICAgICAgICAgY291bnQ6IChuIT09J2p1bmsnKXwwXG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICAgdGhpc1ZhcnM6IFtdLFxuICAgICAgbG9jYWxWYXJzOiBbXVxuICAgIH0sXG4gICAgZnVuY05hbWU6ICdmZFRlbXBsYXRlJyArIGRcbiAgfSlcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVHcmFkaWVudChib3VuZGFyeUNvbmRpdGlvbnMpIHtcbiAgdmFyIHRva2VuID0gYm91bmRhcnlDb25kaXRpb25zLmpvaW4oKVxuICB2YXIgcHJvYyA9IEdSQURJRU5UX0NBQ0hFW3Rva2VuXVxuICBpZihwcm9jKSB7XG4gICAgcmV0dXJuIHByb2NcbiAgfVxuXG4gIHZhciBkID0gYm91bmRhcnlDb25kaXRpb25zLmxlbmd0aFxuICB2YXIgY29kZSA9IFsnZnVuY3Rpb24gZ3JhZGllbnQoZHN0LHNyYyl7dmFyIHM9c3JjLnNoYXBlLnNsaWNlKCk7JyBdXG4gIFxuICBmdW5jdGlvbiBoYW5kbGVCb3VuZGFyeShmYWNldCkge1xuICAgIHZhciBjb2QgPSBkIC0gZmFjZXQubGVuZ3RoXG5cbiAgICB2YXIgbG9TdHIgPSBbXVxuICAgIHZhciBoaVN0ciA9IFtdXG4gICAgdmFyIHBpY2tTdHIgPSBbXVxuICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgICAgaWYoZmFjZXQuaW5kZXhPZihpKzEpID49IDApIHtcbiAgICAgICAgcGlja1N0ci5wdXNoKCcwJylcbiAgICAgIH0gZWxzZSBpZihmYWNldC5pbmRleE9mKC0oaSsxKSkgPj0gMCkge1xuICAgICAgICBwaWNrU3RyLnB1c2goJ3NbJytpKyddLTEnKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGlja1N0ci5wdXNoKCctMScpXG4gICAgICAgIGxvU3RyLnB1c2goJzEnKVxuICAgICAgICBoaVN0ci5wdXNoKCdzWycraSsnXS0yJylcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGJvdW5kU3RyID0gJy5sbygnICsgbG9TdHIuam9pbigpICsgJykuaGkoJyArIGhpU3RyLmpvaW4oKSArICcpJ1xuICAgIGlmKGxvU3RyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYm91bmRTdHIgPSAnJ1xuICAgIH1cbiAgICAgICAgXG4gICAgaWYoY29kID4gMCkge1xuICAgICAgY29kZS5wdXNoKCdpZigxJykgXG4gICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgICAgaWYoZmFjZXQuaW5kZXhPZihpKzEpID49IDAgfHwgZmFjZXQuaW5kZXhPZigtKGkrMSkpID49IDApIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGNvZGUucHVzaCgnJiZzWycsIGksICddPjInKVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKCcpe2dyYWQnLCBjb2QsICcoc3JjLnBpY2soJywgcGlja1N0ci5qb2luKCksICcpJywgYm91bmRTdHIpXG4gICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgICAgaWYoZmFjZXQuaW5kZXhPZihpKzEpID49IDAgfHwgZmFjZXQuaW5kZXhPZigtKGkrMSkpID49IDApIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGNvZGUucHVzaCgnLGRzdC5waWNrKCcsIHBpY2tTdHIuam9pbigpLCAnLCcsIGksICcpJywgYm91bmRTdHIpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goJyk7JylcbiAgICB9XG5cbiAgICBmb3IodmFyIGk9MDsgaTxmYWNldC5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGJuZCA9IE1hdGguYWJzKGZhY2V0W2ldKS0xXG4gICAgICB2YXIgb3V0U3RyID0gJ2RzdC5waWNrKCcgKyBwaWNrU3RyLmpvaW4oKSArICcsJyArIGJuZCArICcpJyArIGJvdW5kU3RyXG4gICAgICBzd2l0Y2goYm91bmRhcnlDb25kaXRpb25zW2JuZF0pIHtcblxuICAgICAgICBjYXNlICdjbGFtcCc6XG4gICAgICAgICAgdmFyIGNQaWNrU3RyID0gcGlja1N0ci5zbGljZSgpXG4gICAgICAgICAgdmFyIGRQaWNrU3RyID0gcGlja1N0ci5zbGljZSgpXG4gICAgICAgICAgaWYoZmFjZXRbaV0gPCAwKSB7XG4gICAgICAgICAgICBjUGlja1N0cltibmRdID0gJ3NbJyArIGJuZCArICddLTInXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRQaWNrU3RyW2JuZF0gPSAnMSdcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoY29kID09PSAwKSB7XG4gICAgICAgICAgICBjb2RlLnB1c2goJ2lmKHNbJywgYm5kLCAnXT4xKXtkc3Quc2V0KCcsXG4gICAgICAgICAgICAgIHBpY2tTdHIuam9pbigpLCAnLCcsIGJuZCwgJywwLjUqKHNyYy5nZXQoJyxcbiAgICAgICAgICAgICAgICBjUGlja1N0ci5qb2luKCksICcpLXNyYy5nZXQoJyxcbiAgICAgICAgICAgICAgICBkUGlja1N0ci5qb2luKCksICcpKSl9ZWxzZXtkc3Quc2V0KCcsXG4gICAgICAgICAgICAgIHBpY2tTdHIuam9pbigpLCAnLCcsIGJuZCwgJywwKX07JylcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29kZS5wdXNoKCdpZihzWycsIGJuZCwgJ10+MSl7ZGlmZignLCBvdXRTdHIsIFxuICAgICAgICAgICAgICAgICcsc3JjLnBpY2soJywgY1BpY2tTdHIuam9pbigpLCAnKScsIGJvdW5kU3RyLCBcbiAgICAgICAgICAgICAgICAnLHNyYy5waWNrKCcsIGRQaWNrU3RyLmpvaW4oKSwgJyknLCBib3VuZFN0ciwgXG4gICAgICAgICAgICAgICAgJyk7fWVsc2V7emVybygnLCBvdXRTdHIsICcpO307JylcbiAgICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSAnbWlycm9yJzpcbiAgICAgICAgICBpZihjb2QgPT09IDApIHtcbiAgICAgICAgICAgIGNvZGUucHVzaCgnZHN0LnNldCgnLCBwaWNrU3RyLmpvaW4oKSwgJywnLCBibmQsICcsMCk7JylcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29kZS5wdXNoKCd6ZXJvKCcsIG91dFN0ciwgJyk7JylcbiAgICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSAnd3JhcCc6XG4gICAgICAgICAgdmFyIGFQaWNrU3RyID0gcGlja1N0ci5zbGljZSgpXG4gICAgICAgICAgdmFyIGJQaWNrU3RyID0gcGlja1N0ci5zbGljZSgpXG4gICAgICAgICAgaWYoZmFjZXRbaV0gPCAwKSB7XG4gICAgICAgICAgICBhUGlja1N0cltibmRdID0gJ3NbJyArIGJuZCArICddLTInXG4gICAgICAgICAgICBiUGlja1N0cltibmRdID0gJzAnXG4gICAgICAgICAgICBcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYVBpY2tTdHJbYm5kXSA9ICdzWycgKyBibmQgKyAnXS0xJ1xuICAgICAgICAgICAgYlBpY2tTdHJbYm5kXSA9ICcxJ1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZihjb2QgPT09IDApIHtcbiAgICAgICAgICAgIGNvZGUucHVzaCgnaWYoc1snLCBibmQsICddPjIpe2RzdC5zZXQoJyxcbiAgICAgICAgICAgICAgcGlja1N0ci5qb2luKCksICcsJywgYm5kLCAnLDAuNSooc3JjLmdldCgnLFxuICAgICAgICAgICAgICAgIGFQaWNrU3RyLmpvaW4oKSwgJyktc3JjLmdldCgnLFxuICAgICAgICAgICAgICAgIGJQaWNrU3RyLmpvaW4oKSwgJykpKX1lbHNle2RzdC5zZXQoJyxcbiAgICAgICAgICAgICAgcGlja1N0ci5qb2luKCksICcsJywgYm5kLCAnLDApfTsnKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb2RlLnB1c2goJ2lmKHNbJywgYm5kLCAnXT4yKXtkaWZmKCcsIG91dFN0ciwgXG4gICAgICAgICAgICAgICAgJyxzcmMucGljaygnLCBhUGlja1N0ci5qb2luKCksICcpJywgYm91bmRTdHIsIFxuICAgICAgICAgICAgICAgICcsc3JjLnBpY2soJywgYlBpY2tTdHIuam9pbigpLCAnKScsIGJvdW5kU3RyLCBcbiAgICAgICAgICAgICAgICAnKTt9ZWxzZXt6ZXJvKCcsIG91dFN0ciwgJyk7fTsnKVxuICAgICAgICAgIH1cbiAgICAgICAgYnJlYWtcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbmRhcnJheS1ncmFkaWVudDogSW52YWxpZCBib3VuZGFyeSBjb25kaXRpb24nKVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNvZCA+IDApIHtcbiAgICAgIGNvZGUucHVzaCgnfTsnKVxuICAgIH1cbiAgfVxuXG4gIC8vRW51bWVyYXRlIHJpZGdlcywgZmFjZXRzLCBldGMuIG9mIGh5cGVyY3ViZVxuICBmb3IodmFyIGk9MDsgaTwoMTw8ZCk7ICsraSkge1xuICAgIHZhciBmYWNlcyA9IFtdXG4gICAgZm9yKHZhciBqPTA7IGo8ZDsgKytqKSB7XG4gICAgICBpZihpICYgKDE8PGopKSB7XG4gICAgICAgIGZhY2VzLnB1c2goaisxKVxuICAgICAgfVxuICAgIH1cbiAgICBmb3IodmFyIGs9MDsgazwoMTw8ZmFjZXMubGVuZ3RoKTsgKytrKSB7XG4gICAgICB2YXIgc2ZhY2VzID0gZmFjZXMuc2xpY2UoKVxuICAgICAgZm9yKHZhciBqPTA7IGo8ZmFjZXMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgaWYoayAmICgxPDxqKSkge1xuICAgICAgICAgIHNmYWNlc1tqXSA9IC1zZmFjZXNbal1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaGFuZGxlQm91bmRhcnkoc2ZhY2VzKVxuICAgIH1cbiAgfVxuXG4gIGNvZGUucHVzaCgncmV0dXJuIGRzdDt9O3JldHVybiBncmFkaWVudCcpXG5cbiAgLy9Db21waWxlIGFuZCBsaW5rIHJvdXRpbmUsIHNhdmUgY2FjaGVkIHByb2NlZHVyZVxuICB2YXIgbGlua05hbWVzID0gWyAnZGlmZicsICd6ZXJvJyBdXG4gIHZhciBsaW5rQXJncyAgPSBbIGNlbnRyYWxEaWZmLCB6ZXJvT3V0IF1cbiAgZm9yKHZhciBpPTE7IGk8PWQ7ICsraSkge1xuICAgIGxpbmtOYW1lcy5wdXNoKCdncmFkJyArIGkpXG4gICAgbGlua0FyZ3MucHVzaChnZW5lcmF0ZVRlbXBsYXRlKGkpKVxuICB9XG4gIGxpbmtOYW1lcy5wdXNoKGNvZGUuam9pbignJykpXG5cbiAgdmFyIGxpbmsgPSBGdW5jdGlvbi5hcHBseSh2b2lkIDAsIGxpbmtOYW1lcylcbiAgdmFyIHByb2MgPSBsaW5rLmFwcGx5KHZvaWQgMCwgbGlua0FyZ3MpXG4gIFRFTVBMQVRFX0NBQ0hFW3Rva2VuXSA9IHByb2NcbiAgcmV0dXJuIHByb2Ncbn1cblxuZnVuY3Rpb24gZ3JhZGllbnQob3V0LCBpbnAsIGJjKSB7XG4gIGlmKEFycmF5LmlzQXJyYXkoYmMpKSB7XG4gICAgaWYoYmMubGVuZ3RoICE9PSBpbnAuZGltZW5zaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25kYXJyYXktZ3JhZGllbnQ6IGludmFsaWQgYm91bmRhcnkgY29uZGl0aW9ucycpXG4gICAgfVxuICB9IGVsc2UgaWYodHlwZW9mIGJjID09PSAnc3RyaW5nJykge1xuICAgIGJjID0gZHVwKGlucC5kaW1lbnNpb24sIGJjKVxuICB9IGVsc2Uge1xuICAgIGJjID0gZHVwKGlucC5kaW1lbnNpb24sICdjbGFtcCcpXG4gIH1cbiAgaWYob3V0LmRpbWVuc2lvbiAhPT0gaW5wLmRpbWVuc2lvbiArIDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ25kYXJyYXktZ3JhZGllbnQ6IG91dHB1dCBkaW1lbnNpb24gbXVzdCBiZSArMSBpbnB1dCBkaW1lbnNpb24nKVxuICB9XG4gIGlmKG91dC5zaGFwZVtpbnAuZGltZW5zaW9uXSAhPT0gaW5wLmRpbWVuc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcignbmRhcnJheS1ncmFkaWVudDogb3V0cHV0IHNoYXBlIG11c3QgbWF0Y2ggaW5wdXQgc2hhcGUnKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPGlucC5kaW1lbnNpb247ICsraSkge1xuICAgIGlmKG91dC5zaGFwZVtpXSAhPT0gaW5wLnNoYXBlW2ldKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25kYXJyYXktZ3JhZGllbnQ6IHNoYXBlIG1pc21hdGNoJylcbiAgICB9XG4gIH1cbiAgaWYoaW5wLnNpemUgPT09IDApIHtcbiAgICByZXR1cm4gb3V0XG4gIH1cbiAgaWYoaW5wLmRpbWVuc2lvbiA8PSAwKSB7XG4gICAgb3V0LnNldCgwKVxuICAgIHJldHVybiBvdXRcbiAgfVxuICB2YXIgY2FjaGVkID0gZ2VuZXJhdGVHcmFkaWVudChiYylcbiAgcmV0dXJuIGNhY2hlZChvdXQsIGlucClcbn0iLCIndXNlIHN0cmljdCdcblxudmFyIHdhcnAgPSByZXF1aXJlKCduZGFycmF5LXdhcnAnKVxudmFyIGludmVydCA9IHJlcXVpcmUoJ2dsLW1hdHJpeC1pbnZlcnQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFwcGx5SG9tb2dyYXBoeVxuXG5mdW5jdGlvbiBhcHBseUhvbW9ncmFwaHkoZGVzdCwgc3JjLCBYaSkge1xuICB2YXIgbiA9IHNyYy5kaW1lbnNpb25cbiAgdmFyIFggPSBpbnZlcnQoW10sIFhpKVxuICB3YXJwKGRlc3QsIHNyYywgZnVuY3Rpb24ob3V0X2MsIGlucF9jKSB7XG4gICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICBvdXRfY1tpXSA9IFhbKG4rMSkqbiArIGldXG4gICAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgICAgb3V0X2NbaV0gKz0gWFsobisxKSpqK2ldICogaW5wX2Nbal1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHcgPSBYWyhuKzEpKihuKzEpLTFdXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICB3ICs9IFhbKG4rMSkqaituXSAqIGlucF9jW2pdXG4gICAgfVxuICAgIHZhciB3ciA9IDEuMCAvIHdcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIG91dF9jW2ldICo9IHdyXG4gICAgfVxuICAgIHJldHVybiBvdXRfY1xuICB9KVxuICByZXR1cm4gZGVzdFxufSIsIlwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGludGVycDFkKGFyciwgeCkge1xuICB2YXIgaXggPSBNYXRoLmZsb29yKHgpXG4gICAgLCBmeCA9IHggLSBpeFxuICAgICwgczAgPSAwIDw9IGl4ICAgJiYgaXggICA8IGFyci5zaGFwZVswXVxuICAgICwgczEgPSAwIDw9IGl4KzEgJiYgaXgrMSA8IGFyci5zaGFwZVswXVxuICAgICwgdzAgPSBzMCA/ICthcnIuZ2V0KGl4KSAgIDogMC4wXG4gICAgLCB3MSA9IHMxID8gK2Fyci5nZXQoaXgrMSkgOiAwLjBcbiAgcmV0dXJuICgxLjAtZngpKncwICsgZngqdzFcbn1cblxuZnVuY3Rpb24gaW50ZXJwMmQoYXJyLCB4LCB5KSB7XG4gIHZhciBpeCA9IE1hdGguZmxvb3IoeClcbiAgICAsIGZ4ID0geCAtIGl4XG4gICAgLCBzMCA9IDAgPD0gaXggICAmJiBpeCAgIDwgYXJyLnNoYXBlWzBdXG4gICAgLCBzMSA9IDAgPD0gaXgrMSAmJiBpeCsxIDwgYXJyLnNoYXBlWzBdXG4gICAgLCBpeSA9IE1hdGguZmxvb3IoeSlcbiAgICAsIGZ5ID0geSAtIGl5XG4gICAgLCB0MCA9IDAgPD0gaXkgICAmJiBpeSAgIDwgYXJyLnNoYXBlWzFdXG4gICAgLCB0MSA9IDAgPD0gaXkrMSAmJiBpeSsxIDwgYXJyLnNoYXBlWzFdXG4gICAgLCB3MDAgPSBzMCYmdDAgPyBhcnIuZ2V0KGl4ICAsaXkgICkgOiAwLjBcbiAgICAsIHcwMSA9IHMwJiZ0MSA/IGFyci5nZXQoaXggICxpeSsxKSA6IDAuMFxuICAgICwgdzEwID0gczEmJnQwID8gYXJyLmdldChpeCsxLGl5ICApIDogMC4wXG4gICAgLCB3MTEgPSBzMSYmdDEgPyBhcnIuZ2V0KGl4KzEsaXkrMSkgOiAwLjBcbiAgcmV0dXJuICgxLjAtZnkpICogKCgxLjAtZngpKncwMCArIGZ4KncxMCkgKyBmeSAqICgoMS4wLWZ4KSp3MDEgKyBmeCp3MTEpXG59XG5cbmZ1bmN0aW9uIGludGVycDNkKGFyciwgeCwgeSwgeikge1xuICB2YXIgaXggPSBNYXRoLmZsb29yKHgpXG4gICAgLCBmeCA9IHggLSBpeFxuICAgICwgczAgPSAwIDw9IGl4ICAgJiYgaXggICA8IGFyci5zaGFwZVswXVxuICAgICwgczEgPSAwIDw9IGl4KzEgJiYgaXgrMSA8IGFyci5zaGFwZVswXVxuICAgICwgaXkgPSBNYXRoLmZsb29yKHkpXG4gICAgLCBmeSA9IHkgLSBpeVxuICAgICwgdDAgPSAwIDw9IGl5ICAgJiYgaXkgICA8IGFyci5zaGFwZVsxXVxuICAgICwgdDEgPSAwIDw9IGl5KzEgJiYgaXkrMSA8IGFyci5zaGFwZVsxXVxuICAgICwgaXogPSBNYXRoLmZsb29yKHopXG4gICAgLCBmeiA9IHogLSBpelxuICAgICwgdTAgPSAwIDw9IGl6ICAgJiYgaXogICA8IGFyci5zaGFwZVsyXVxuICAgICwgdTEgPSAwIDw9IGl6KzEgJiYgaXorMSA8IGFyci5zaGFwZVsyXVxuICAgICwgdzAwMCA9IHMwJiZ0MCYmdTAgPyBhcnIuZ2V0KGl4LGl5LGl6KSAgICAgICA6IDAuMFxuICAgICwgdzAxMCA9IHMwJiZ0MSYmdTAgPyBhcnIuZ2V0KGl4LGl5KzEsaXopICAgICA6IDAuMFxuICAgICwgdzEwMCA9IHMxJiZ0MCYmdTAgPyBhcnIuZ2V0KGl4KzEsaXksaXopICAgICA6IDAuMFxuICAgICwgdzExMCA9IHMxJiZ0MSYmdTAgPyBhcnIuZ2V0KGl4KzEsaXkrMSxpeikgICA6IDAuMFxuICAgICwgdzAwMSA9IHMwJiZ0MCYmdTEgPyBhcnIuZ2V0KGl4LGl5LGl6KzEpICAgICA6IDAuMFxuICAgICwgdzAxMSA9IHMwJiZ0MSYmdTEgPyBhcnIuZ2V0KGl4LGl5KzEsaXorMSkgICA6IDAuMFxuICAgICwgdzEwMSA9IHMxJiZ0MCYmdTEgPyBhcnIuZ2V0KGl4KzEsaXksaXorMSkgICA6IDAuMFxuICAgICwgdzExMSA9IHMxJiZ0MSYmdTEgPyBhcnIuZ2V0KGl4KzEsaXkrMSxpeisxKSA6IDAuMFxuICByZXR1cm4gKDEuMC1meikgKiAoKDEuMC1meSkgKiAoKDEuMC1meCkqdzAwMCArIGZ4KncxMDApICsgZnkgKiAoKDEuMC1meCkqdzAxMCArIGZ4KncxMTApKSArIGZ6ICogKCgxLjAtZnkpICogKCgxLjAtZngpKncwMDEgKyBmeCp3MTAxKSArIGZ5ICogKCgxLjAtZngpKncwMTEgKyBmeCp3MTExKSlcbn1cblxuZnVuY3Rpb24gaW50ZXJwTmQoYXJyKSB7XG4gIHZhciBkID0gYXJyLnNoYXBlLmxlbmd0aHwwXG4gICAgLCBpeCA9IG5ldyBBcnJheShkKVxuICAgICwgZnggPSBuZXcgQXJyYXkoZClcbiAgICAsIHMwID0gbmV3IEFycmF5KGQpXG4gICAgLCBzMSA9IG5ldyBBcnJheShkKVxuICAgICwgaSwgdFxuICBmb3IoaT0wOyBpPGQ7ICsraSkge1xuICAgIHQgPSArYXJndW1lbnRzW2krMV1cbiAgICBpeFtpXSA9IE1hdGguZmxvb3IodClcbiAgICBmeFtpXSA9IHQgLSBpeFtpXVxuICAgIHMwW2ldID0gKDAgPD0gaXhbaV0gICAmJiBpeFtpXSAgIDwgYXJyLnNoYXBlW2ldKVxuICAgIHMxW2ldID0gKDAgPD0gaXhbaV0rMSAmJiBpeFtpXSsxIDwgYXJyLnNoYXBlW2ldKVxuICB9XG4gIHZhciByID0gMC4wLCBqLCB3LCBpZHhcbmlfbG9vcDpcbiAgZm9yKGk9MDsgaTwoMTw8ZCk7ICsraSkge1xuICAgIHcgPSAxLjBcbiAgICBpZHggPSBhcnIub2Zmc2V0XG4gICAgZm9yKGo9MDsgajxkOyArK2opIHtcbiAgICAgIGlmKGkgJiAoMTw8aikpIHtcbiAgICAgICAgaWYoIXMxW2pdKSB7XG4gICAgICAgICAgY29udGludWUgaV9sb29wXG4gICAgICAgIH1cbiAgICAgICAgdyAqPSBmeFtqXVxuICAgICAgICBpZHggKz0gYXJyLnN0cmlkZVtqXSAqIChpeFtqXSArIDEpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZighczBbal0pIHtcbiAgICAgICAgICBjb250aW51ZSBpX2xvb3BcbiAgICAgICAgfVxuICAgICAgICB3ICo9IDEuMCAtIGZ4W2pdXG4gICAgICAgIGlkeCArPSBhcnIuc3RyaWRlW2pdICogaXhbal1cbiAgICAgIH1cbiAgICB9XG4gICAgciArPSB3ICogYXJyLmRhdGFbaWR4XVxuICB9XG4gIHJldHVybiByXG59XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKGFyciwgeCwgeSwgeikge1xuICBzd2l0Y2goYXJyLnNoYXBlLmxlbmd0aCkge1xuICAgIGNhc2UgMDpcbiAgICAgIHJldHVybiAwLjBcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gaW50ZXJwMWQoYXJyLCB4KVxuICAgIGNhc2UgMjpcbiAgICAgIHJldHVybiBpbnRlcnAyZChhcnIsIHgsIHkpXG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuIGludGVycDNkKGFyciwgeCwgeSwgeilcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGludGVycE5kLmFwcGx5KHVuZGVmaW5lZCwgYXJndW1lbnRzKVxuICB9XG59XG5tb2R1bGUuZXhwb3J0cyA9IGludGVycG9sYXRlXG5tb2R1bGUuZXhwb3J0cy5kMSA9IGludGVycDFkXG5tb2R1bGUuZXhwb3J0cy5kMiA9IGludGVycDJkXG5tb2R1bGUuZXhwb3J0cy5kMyA9IGludGVycDNkXG4iLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgY29tcGlsZSA9IHJlcXVpcmUoXCJjd2lzZS1jb21waWxlclwiKVxuXG52YXIgRW1wdHlQcm9jID0ge1xuICBib2R5OiBcIlwiLFxuICBhcmdzOiBbXSxcbiAgdGhpc1ZhcnM6IFtdLFxuICBsb2NhbFZhcnM6IFtdXG59XG5cbmZ1bmN0aW9uIGZpeHVwKHgpIHtcbiAgaWYoIXgpIHtcbiAgICByZXR1cm4gRW1wdHlQcm9jXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8eC5hcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGEgPSB4LmFyZ3NbaV1cbiAgICBpZihpID09PSAwKSB7XG4gICAgICB4LmFyZ3NbaV0gPSB7bmFtZTogYSwgbHZhbHVlOnRydWUsIHJ2YWx1ZTogISF4LnJ2YWx1ZSwgY291bnQ6eC5jb3VudHx8MSB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHguYXJnc1tpXSA9IHtuYW1lOiBhLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDogMX1cbiAgICB9XG4gIH1cbiAgaWYoIXgudGhpc1ZhcnMpIHtcbiAgICB4LnRoaXNWYXJzID0gW11cbiAgfVxuICBpZigheC5sb2NhbFZhcnMpIHtcbiAgICB4LmxvY2FsVmFycyA9IFtdXG4gIH1cbiAgcmV0dXJuIHhcbn1cblxuZnVuY3Rpb24gcGNvbXBpbGUodXNlcl9hcmdzKSB7XG4gIHJldHVybiBjb21waWxlKHtcbiAgICBhcmdzOiAgICAgdXNlcl9hcmdzLmFyZ3MsXG4gICAgcHJlOiAgICAgIGZpeHVwKHVzZXJfYXJncy5wcmUpLFxuICAgIGJvZHk6ICAgICBmaXh1cCh1c2VyX2FyZ3MuYm9keSksXG4gICAgcG9zdDogICAgIGZpeHVwKHVzZXJfYXJncy5wcm9jKSxcbiAgICBmdW5jTmFtZTogdXNlcl9hcmdzLmZ1bmNOYW1lXG4gIH0pXG59XG5cbmZ1bmN0aW9uIG1ha2VPcCh1c2VyX2FyZ3MpIHtcbiAgdmFyIGFyZ3MgPSBbXVxuICBmb3IodmFyIGk9MDsgaTx1c2VyX2FyZ3MuYXJncy5sZW5ndGg7ICsraSkge1xuICAgIGFyZ3MucHVzaChcImFcIitpKVxuICB9XG4gIHZhciB3cmFwcGVyID0gbmV3IEZ1bmN0aW9uKFwiUFwiLCBbXG4gICAgXCJyZXR1cm4gZnVuY3Rpb24gXCIsIHVzZXJfYXJncy5mdW5jTmFtZSwgXCJfbmRhcnJheW9wcyhcIiwgYXJncy5qb2luKFwiLFwiKSwgXCIpIHtQKFwiLCBhcmdzLmpvaW4oXCIsXCIpLCBcIik7cmV0dXJuIGEwfVwiXG4gIF0uam9pbihcIlwiKSlcbiAgcmV0dXJuIHdyYXBwZXIocGNvbXBpbGUodXNlcl9hcmdzKSlcbn1cblxudmFyIGFzc2lnbl9vcHMgPSB7XG4gIGFkZDogIFwiK1wiLFxuICBzdWI6ICBcIi1cIixcbiAgbXVsOiAgXCIqXCIsXG4gIGRpdjogIFwiL1wiLFxuICBtb2Q6ICBcIiVcIixcbiAgYmFuZDogXCImXCIsXG4gIGJvcjogIFwifFwiLFxuICBieG9yOiBcIl5cIixcbiAgbHNoaWZ0OiBcIjw8XCIsXG4gIHJzaGlmdDogXCI+PlwiLFxuICBycnNoaWZ0OiBcIj4+PlwiXG59XG47KGZ1bmN0aW9uKCl7XG4gIGZvcih2YXIgaWQgaW4gYXNzaWduX29wcykge1xuICAgIHZhciBvcCA9IGFzc2lnbl9vcHNbaWRdXG4gICAgZXhwb3J0c1tpZF0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIixcImFycmF5XCIsXCJhcnJheVwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcImNcIl0sXG4gICAgICAgICAgICAgYm9keTogXCJhPWJcIitvcCtcImNcIn0sXG4gICAgICBmdW5jTmFtZTogaWRcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJlcVwiXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLFwiYXJyYXlcIl0sXG4gICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhXCIrb3ArXCI9YlwifSxcbiAgICAgIHJ2YWx1ZTogdHJ1ZSxcbiAgICAgIGZ1bmNOYW1lOiBpZCtcImVxXCJcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJzXCJdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCIsIFwiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCIsXCJzXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPWJcIitvcCtcInNcIn0sXG4gICAgICBmdW5jTmFtZTogaWQrXCJzXCJcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJzZXFcIl0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIixcInNjYWxhclwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIixcInNcIl0sXG4gICAgICAgICAgICAgYm9keTpcImFcIitvcCtcIj1zXCJ9LFxuICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgZnVuY05hbWU6IGlkK1wic2VxXCJcbiAgICB9KVxuICB9XG59KSgpO1xuXG52YXIgdW5hcnlfb3BzID0ge1xuICBub3Q6IFwiIVwiLFxuICBibm90OiBcIn5cIixcbiAgbmVnOiBcIi1cIixcbiAgcmVjaXA6IFwiMS4wL1wiXG59XG47KGZ1bmN0aW9uKCl7XG4gIGZvcih2YXIgaWQgaW4gdW5hcnlfb3BzKSB7XG4gICAgdmFyIG9wID0gdW5hcnlfb3BzW2lkXVxuICAgIGV4cG9ydHNbaWRdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPVwiK29wK1wiYlwifSxcbiAgICAgIGZ1bmNOYW1lOiBpZFxuICAgIH0pXG4gICAgZXhwb3J0c1tpZCtcImVxXCJdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiXSxcbiAgICAgICAgICAgICBib2R5OlwiYT1cIitvcCtcImFcIn0sXG4gICAgICBydmFsdWU6IHRydWUsXG4gICAgICBjb3VudDogMixcbiAgICAgIGZ1bmNOYW1lOiBpZCtcImVxXCJcbiAgICB9KVxuICB9XG59KSgpO1xuXG52YXIgYmluYXJ5X29wcyA9IHtcbiAgYW5kOiBcIiYmXCIsXG4gIG9yOiBcInx8XCIsXG4gIGVxOiBcIj09PVwiLFxuICBuZXE6IFwiIT09XCIsXG4gIGx0OiBcIjxcIixcbiAgZ3Q6IFwiPlwiLFxuICBsZXE6IFwiPD1cIixcbiAgZ2VxOiBcIj49XCJcbn1cbjsoZnVuY3Rpb24oKSB7XG4gIGZvcih2YXIgaWQgaW4gYmluYXJ5X29wcykge1xuICAgIHZhciBvcCA9IGJpbmFyeV9vcHNbaWRdXG4gICAgZXhwb3J0c1tpZF0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIixcImFycmF5XCIsXCJhcnJheVwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIiwgXCJiXCIsIFwiY1wiXSxcbiAgICAgICAgICAgICBib2R5OlwiYT1iXCIrb3ArXCJjXCJ9LFxuICAgICAgZnVuY05hbWU6IGlkXG4gICAgfSlcbiAgICBleHBvcnRzW2lkK1wic1wiXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLFwiYXJyYXlcIixcInNjYWxhclwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIiwgXCJiXCIsIFwic1wiXSxcbiAgICAgICAgICAgICBib2R5OlwiYT1iXCIrb3ArXCJzXCJ9LFxuICAgICAgZnVuY05hbWU6IGlkK1wic1wiXG4gICAgfSlcbiAgICBleHBvcnRzW2lkK1wiZXFcIl0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIiwgXCJhcnJheVwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIiwgXCJiXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPWFcIitvcCtcImJcIn0sXG4gICAgICBydmFsdWU6dHJ1ZSxcbiAgICAgIGNvdW50OjIsXG4gICAgICBmdW5jTmFtZTogaWQrXCJlcVwiXG4gICAgfSlcbiAgICBleHBvcnRzW2lkK1wic2VxXCJdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCIsIFwic2NhbGFyXCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwic1wiXSxcbiAgICAgICAgICAgICBib2R5OlwiYT1hXCIrb3ArXCJzXCJ9LFxuICAgICAgcnZhbHVlOnRydWUsXG4gICAgICBjb3VudDoyLFxuICAgICAgZnVuY05hbWU6IGlkK1wic2VxXCJcbiAgICB9KVxuICB9XG59KSgpO1xuXG52YXIgbWF0aF91bmFyeSA9IFtcbiAgXCJhYnNcIixcbiAgXCJhY29zXCIsXG4gIFwiYXNpblwiLFxuICBcImF0YW5cIixcbiAgXCJjZWlsXCIsXG4gIFwiY29zXCIsXG4gIFwiZXhwXCIsXG4gIFwiZmxvb3JcIixcbiAgXCJsb2dcIixcbiAgXCJyb3VuZFwiLFxuICBcInNpblwiLFxuICBcInNxcnRcIixcbiAgXCJ0YW5cIlxuXVxuOyhmdW5jdGlvbigpIHtcbiAgZm9yKHZhciBpPTA7IGk8bWF0aF91bmFyeS5sZW5ndGg7ICsraSkge1xuICAgIHZhciBmID0gbWF0aF91bmFyeVtpXVxuICAgIGV4cG9ydHNbZl0gPSBtYWtlT3Aoe1xuICAgICAgICAgICAgICAgICAgICBhcmdzOiBbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICAgICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiXSwgYm9keTpcImE9dGhpc19mKGIpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmXG4gICAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcImVxXCJdID0gbWFrZU9wKHtcbiAgICAgICAgICAgICAgICAgICAgICBhcmdzOiBbXCJhcnJheVwiXSxcbiAgICAgICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczogW1wiYVwiXSwgYm9keTpcImE9dGhpc19mKGEpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiAyLFxuICAgICAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmK1wiZXFcIlxuICAgICAgICAgICAgICAgICAgICB9KVxuICB9XG59KSgpO1xuXG52YXIgbWF0aF9jb21tID0gW1xuICBcIm1heFwiLFxuICBcIm1pblwiLFxuICBcImF0YW4yXCIsXG4gIFwicG93XCJcbl1cbjsoZnVuY3Rpb24oKXtcbiAgZm9yKHZhciBpPTA7IGk8bWF0aF9jb21tLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGY9IG1hdGhfY29tbVtpXVxuICAgIGV4cG9ydHNbZl0gPSBtYWtlT3Aoe1xuICAgICAgICAgICAgICAgICAgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcImNcIl0sIGJvZHk6XCJhPXRoaXNfZihiLGMpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZlxuICAgICAgICAgICAgICAgIH0pXG4gICAgZXhwb3J0c1tmK1wic1wiXSA9IG1ha2VPcCh7XG4gICAgICAgICAgICAgICAgICBhcmdzOltcImFycmF5XCIsIFwiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcImNcIl0sIGJvZHk6XCJhPXRoaXNfZihiLGMpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcInNcIlxuICAgICAgICAgICAgICAgICAgfSlcbiAgICBleHBvcnRzW2YrXCJlcVwiXSA9IG1ha2VPcCh7IGFyZ3M6W1wiYXJyYXlcIiwgXCJhcnJheVwiXSxcbiAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiXSwgYm9keTpcImE9dGhpc19mKGEsYilcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIHJ2YWx1ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIGNvdW50OiAyLFxuICAgICAgICAgICAgICAgICAgZnVuY05hbWU6IGYrXCJlcVwiXG4gICAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcInNlcVwiXSA9IG1ha2VPcCh7IGFyZ3M6W1wiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIl0sIGJvZHk6XCJhPXRoaXNfZihhLGIpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBydmFsdWU6dHJ1ZSxcbiAgICAgICAgICAgICAgICAgIGNvdW50OjIsXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcInNlcVwiXG4gICAgICAgICAgICAgICAgICB9KVxuICB9XG59KSgpO1xuXG52YXIgbWF0aF9ub25jb21tID0gW1xuICBcImF0YW4yXCIsXG4gIFwicG93XCJcbl1cbjsoZnVuY3Rpb24oKXtcbiAgZm9yKHZhciBpPTA7IGk8bWF0aF9ub25jb21tLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGY9IG1hdGhfbm9uY29tbVtpXVxuICAgIGV4cG9ydHNbZitcIm9wXCJdID0gbWFrZU9wKHtcbiAgICAgICAgICAgICAgICAgIGFyZ3M6W1wiYXJyYXlcIiwgXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICAgICAgICAgICAgICAgICAgcHJlOiB7YXJnczpbXSwgYm9keTpcInRoaXNfZj1NYXRoLlwiK2YsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCIsXCJjXCJdLCBib2R5OlwiYT10aGlzX2YoYyxiKVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgZnVuY05hbWU6IGYrXCJvcFwiXG4gICAgICAgICAgICAgICAgfSlcbiAgICBleHBvcnRzW2YrXCJvcHNcIl0gPSBtYWtlT3Aoe1xuICAgICAgICAgICAgICAgICAgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCIsIFwic2NhbGFyXCJdLFxuICAgICAgICAgICAgICAgICAgcHJlOiB7YXJnczpbXSwgYm9keTpcInRoaXNfZj1NYXRoLlwiK2YsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCIsXCJjXCJdLCBib2R5OlwiYT10aGlzX2YoYyxiKVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgZnVuY05hbWU6IGYrXCJvcHNcIlxuICAgICAgICAgICAgICAgICAgfSlcbiAgICBleHBvcnRzW2YrXCJvcGVxXCJdID0gbWFrZU9wKHsgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICAgICAgICAgICAgICAgICAgcHJlOiB7YXJnczpbXSwgYm9keTpcInRoaXNfZj1NYXRoLlwiK2YsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCJdLCBib2R5OlwiYT10aGlzX2YoYixhKVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgY291bnQ6IDIsXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcIm9wZXFcIlxuICAgICAgICAgICAgICAgICAgfSlcbiAgICBleHBvcnRzW2YrXCJvcHNlcVwiXSA9IG1ha2VPcCh7IGFyZ3M6W1wiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIl0sIGJvZHk6XCJhPXRoaXNfZihiLGEpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBydmFsdWU6dHJ1ZSxcbiAgICAgICAgICAgICAgICAgIGNvdW50OjIsXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcIm9wc2VxXCJcbiAgICAgICAgICAgICAgICAgIH0pXG4gIH1cbn0pKCk7XG5cbmV4cG9ydHMuYW55ID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZTogRW1wdHlQcm9jLFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJhXCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjF9XSwgYm9keTogXCJpZihhKXtyZXR1cm4gdHJ1ZX1cIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W10sIGJvZHk6XCJyZXR1cm4gZmFsc2VcIn0sXG4gIGZ1bmNOYW1lOiBcImFueVwiXG59KVxuXG5leHBvcnRzLmFsbCA9IGNvbXBpbGUoe1xuICBhcmdzOltcImFycmF5XCJdLFxuICBwcmU6IEVtcHR5UHJvYyxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwieFwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoxfV0sIGJvZHk6IFwiaWYoIXgpe3JldHVybiBmYWxzZX1cIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W10sIGJvZHk6XCJyZXR1cm4gdHJ1ZVwifSxcbiAgZnVuY05hbWU6IFwiYWxsXCJcbn0pXG5cbmV4cG9ydHMuc3VtID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZToge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwidGhpc19zPTBcIn0sXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcImFcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6MX1dLCBib2R5OiBcInRoaXNfcys9YVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIHRoaXNfc1wifSxcbiAgZnVuY05hbWU6IFwic3VtXCJcbn0pXG5cbmV4cG9ydHMucHJvZCA9IGNvbXBpbGUoe1xuICBhcmdzOltcImFycmF5XCJdLFxuICBwcmU6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInRoaXNfcz0xXCJ9LFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJhXCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjF9XSwgYm9keTogXCJ0aGlzX3MqPWFcIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtcInRoaXNfc1wiXX0sXG4gIHBvc3Q6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInJldHVybiB0aGlzX3NcIn0sXG4gIGZ1bmNOYW1lOiBcInByb2RcIlxufSlcblxuZXhwb3J0cy5ub3JtMnNxdWFyZWQgPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiXSxcbiAgcHJlOiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJ0aGlzX3M9MFwifSxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwiYVwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoyfV0sIGJvZHk6IFwidGhpc19zKz1hKmFcIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtcInRoaXNfc1wiXX0sXG4gIHBvc3Q6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInJldHVybiB0aGlzX3NcIn0sXG4gIGZ1bmNOYW1lOiBcIm5vcm0yc3F1YXJlZFwiXG59KVxuICBcbmV4cG9ydHMubm9ybTIgPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiXSxcbiAgcHJlOiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJ0aGlzX3M9MFwifSxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwiYVwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoyfV0sIGJvZHk6IFwidGhpc19zKz1hKmFcIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtcInRoaXNfc1wiXX0sXG4gIHBvc3Q6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInJldHVybiBNYXRoLnNxcnQodGhpc19zKVwifSxcbiAgZnVuY05hbWU6IFwibm9ybTJcIlxufSlcbiAgXG5cbmV4cG9ydHMubm9ybWluZiA9IGNvbXBpbGUoe1xuICBhcmdzOltcImFycmF5XCJdLFxuICBwcmU6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInRoaXNfcz0wXCJ9LFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJhXCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjR9XSwgYm9keTpcImlmKC1hPnRoaXNfcyl7dGhpc19zPS1hfWVsc2UgaWYoYT50aGlzX3Mpe3RoaXNfcz1hfVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIHRoaXNfc1wifSxcbiAgZnVuY05hbWU6IFwibm9ybWluZlwiXG59KVxuXG5leHBvcnRzLm5vcm0xID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZToge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwidGhpc19zPTBcIn0sXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcImFcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6M31dLCBib2R5OiBcInRoaXNfcys9YTwwPy1hOmFcIiwgbG9jYWxWYXJzOiBbXSwgdGhpc1ZhcnM6IFtcInRoaXNfc1wiXX0sXG4gIHBvc3Q6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInJldHVybiB0aGlzX3NcIn0sXG4gIGZ1bmNOYW1lOiBcIm5vcm0xXCJcbn0pXG5cbmV4cG9ydHMuc3VwID0gY29tcGlsZSh7XG4gIGFyZ3M6IFsgXCJhcnJheVwiIF0sXG4gIHByZTpcbiAgIHsgYm9keTogXCJ0aGlzX2g9LUluZmluaXR5XCIsXG4gICAgIGFyZ3M6IFtdLFxuICAgICB0aGlzVmFyczogWyBcInRoaXNfaFwiIF0sXG4gICAgIGxvY2FsVmFyczogW10gfSxcbiAgYm9keTpcbiAgIHsgYm9keTogXCJpZihfaW5saW5lXzFfYXJnMF8+dGhpc19oKXRoaXNfaD1faW5saW5lXzFfYXJnMF9cIixcbiAgICAgYXJnczogW3tcIm5hbWVcIjpcIl9pbmxpbmVfMV9hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoyfSBdLFxuICAgICB0aGlzVmFyczogWyBcInRoaXNfaFwiIF0sXG4gICAgIGxvY2FsVmFyczogW10gfSxcbiAgcG9zdDpcbiAgIHsgYm9keTogXCJyZXR1cm4gdGhpc19oXCIsXG4gICAgIGFyZ3M6IFtdLFxuICAgICB0aGlzVmFyczogWyBcInRoaXNfaFwiIF0sXG4gICAgIGxvY2FsVmFyczogW10gfVxuIH0pXG5cbmV4cG9ydHMuaW5mID0gY29tcGlsZSh7XG4gIGFyZ3M6IFsgXCJhcnJheVwiIF0sXG4gIHByZTpcbiAgIHsgYm9keTogXCJ0aGlzX2g9SW5maW5pdHlcIixcbiAgICAgYXJnczogW10sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9LFxuICBib2R5OlxuICAgeyBib2R5OiBcImlmKF9pbmxpbmVfMV9hcmcwXzx0aGlzX2gpdGhpc19oPV9pbmxpbmVfMV9hcmcwX1wiLFxuICAgICBhcmdzOiBbe1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjJ9IF0sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9LFxuICBwb3N0OlxuICAgeyBib2R5OiBcInJldHVybiB0aGlzX2hcIixcbiAgICAgYXJnczogW10sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9XG4gfSlcblxuZXhwb3J0cy5hcmdtaW4gPSBjb21waWxlKHtcbiAgYXJnczpbXCJpbmRleFwiLFwiYXJyYXlcIixcInNoYXBlXCJdLFxuICBwcmU6e1xuICAgIGJvZHk6XCJ7dGhpc192PUluZmluaXR5O3RoaXNfaT1faW5saW5lXzBfYXJnMl8uc2xpY2UoMCl9XCIsXG4gICAgYXJnczpbXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcwX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6ZmFsc2UsY291bnQ6MH0sXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcxX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6ZmFsc2UsY291bnQ6MH0sXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcyX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6dHJ1ZSxjb3VudDoxfVxuICAgICAgXSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIixcInRoaXNfdlwiXSxcbiAgICBsb2NhbFZhcnM6W119LFxuICBib2R5OntcbiAgICBib2R5Olwie2lmKF9pbmxpbmVfMV9hcmcxXzx0aGlzX3Ype3RoaXNfdj1faW5saW5lXzFfYXJnMV87Zm9yKHZhciBfaW5saW5lXzFfaz0wO19pbmxpbmVfMV9rPF9pbmxpbmVfMV9hcmcwXy5sZW5ndGg7KytfaW5saW5lXzFfayl7dGhpc19pW19pbmxpbmVfMV9rXT1faW5saW5lXzFfYXJnMF9bX2lubGluZV8xX2tdfX19XCIsXG4gICAgYXJnczpbXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMV9hcmcwX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6dHJ1ZSxjb3VudDoyfSxcbiAgICAgIHtuYW1lOlwiX2lubGluZV8xX2FyZzFfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTp0cnVlLGNvdW50OjJ9XSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIixcInRoaXNfdlwiXSxcbiAgICBsb2NhbFZhcnM6W1wiX2lubGluZV8xX2tcIl19LFxuICBwb3N0OntcbiAgICBib2R5Olwie3JldHVybiB0aGlzX2l9XCIsXG4gICAgYXJnczpbXSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIl0sXG4gICAgbG9jYWxWYXJzOltdfVxufSlcblxuZXhwb3J0cy5hcmdtYXggPSBjb21waWxlKHtcbiAgYXJnczpbXCJpbmRleFwiLFwiYXJyYXlcIixcInNoYXBlXCJdLFxuICBwcmU6e1xuICAgIGJvZHk6XCJ7dGhpc192PS1JbmZpbml0eTt0aGlzX2k9X2lubGluZV8wX2FyZzJfLnNsaWNlKDApfVwiLFxuICAgIGFyZ3M6W1xuICAgICAge25hbWU6XCJfaW5saW5lXzBfYXJnMF9cIixsdmFsdWU6ZmFsc2UscnZhbHVlOmZhbHNlLGNvdW50OjB9LFxuICAgICAge25hbWU6XCJfaW5saW5lXzBfYXJnMV9cIixsdmFsdWU6ZmFsc2UscnZhbHVlOmZhbHNlLGNvdW50OjB9LFxuICAgICAge25hbWU6XCJfaW5saW5lXzBfYXJnMl9cIixsdmFsdWU6ZmFsc2UscnZhbHVlOnRydWUsY291bnQ6MX1cbiAgICAgIF0sXG4gICAgdGhpc1ZhcnM6W1widGhpc19pXCIsXCJ0aGlzX3ZcIl0sXG4gICAgbG9jYWxWYXJzOltdfSxcbiAgYm9keTp7XG4gICAgYm9keTpcIntpZihfaW5saW5lXzFfYXJnMV8+dGhpc192KXt0aGlzX3Y9X2lubGluZV8xX2FyZzFfO2Zvcih2YXIgX2lubGluZV8xX2s9MDtfaW5saW5lXzFfazxfaW5saW5lXzFfYXJnMF8ubGVuZ3RoOysrX2lubGluZV8xX2spe3RoaXNfaVtfaW5saW5lXzFfa109X2lubGluZV8xX2FyZzBfW19pbmxpbmVfMV9rXX19fVwiLFxuICAgIGFyZ3M6W1xuICAgICAge25hbWU6XCJfaW5saW5lXzFfYXJnMF9cIixsdmFsdWU6ZmFsc2UscnZhbHVlOnRydWUsY291bnQ6Mn0sXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMV9hcmcxX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6dHJ1ZSxjb3VudDoyfV0sXG4gICAgdGhpc1ZhcnM6W1widGhpc19pXCIsXCJ0aGlzX3ZcIl0sXG4gICAgbG9jYWxWYXJzOltcIl9pbmxpbmVfMV9rXCJdfSxcbiAgcG9zdDp7XG4gICAgYm9keTpcIntyZXR1cm4gdGhpc19pfVwiLFxuICAgIGFyZ3M6W10sXG4gICAgdGhpc1ZhcnM6W1widGhpc19pXCJdLFxuICAgIGxvY2FsVmFyczpbXX1cbn0pICBcblxuZXhwb3J0cy5yYW5kb20gPSBtYWtlT3Aoe1xuICBhcmdzOiBbXCJhcnJheVwiXSxcbiAgcHJlOiB7YXJnczpbXSwgYm9keTpcInRoaXNfZj1NYXRoLnJhbmRvbVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICBib2R5OiB7YXJnczogW1wiYVwiXSwgYm9keTpcImE9dGhpc19mKClcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgZnVuY05hbWU6IFwicmFuZG9tXCJcbn0pXG5cbmV4cG9ydHMuYXNzaWduID0gbWFrZU9wKHtcbiAgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICBib2R5OiB7YXJnczpbXCJhXCIsIFwiYlwiXSwgYm9keTpcImE9YlwifSxcbiAgZnVuY05hbWU6IFwiYXNzaWduXCIgfSlcblxuZXhwb3J0cy5hc3NpZ25zID0gbWFrZU9wKHtcbiAgYXJnczpbXCJhcnJheVwiLCBcInNjYWxhclwiXSxcbiAgYm9keToge2FyZ3M6W1wiYVwiLCBcImJcIl0sIGJvZHk6XCJhPWJcIn0sXG4gIGZ1bmNOYW1lOiBcImFzc2lnbnNcIiB9KVxuXG5cbmV4cG9ydHMuZXF1YWxzID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIiwgXCJhcnJheVwiXSxcbiAgcHJlOiBFbXB0eVByb2MsXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcInhcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6MX0sXG4gICAgICAgICAgICAgICB7bmFtZTpcInlcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6MX1dLCBcbiAgICAgICAgYm9keTogXCJpZih4IT09eSl7cmV0dXJuIGZhbHNlfVwiLCBcbiAgICAgICAgbG9jYWxWYXJzOiBbXSwgXG4gICAgICAgIHRoaXNWYXJzOiBbXX0sXG4gIHBvc3Q6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltdLCBib2R5OlwicmV0dXJuIHRydWVcIn0sXG4gIGZ1bmNOYW1lOiBcImVxdWFsc1wiXG59KVxuXG5cbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBuZGFycmF5ID0gcmVxdWlyZShcIm5kYXJyYXlcIilcbnZhciBkb19jb252ZXJ0ID0gcmVxdWlyZShcIi4vZG9Db252ZXJ0LmpzXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChhcnIsIHJlc3VsdCkge1xuICB2YXIgc2hhcGUgPSBbXSwgYyA9IGFyciwgc3ogPSAxXG4gIHdoaWxlKEFycmF5LmlzQXJyYXkoYykpIHtcbiAgICBzaGFwZS5wdXNoKGMubGVuZ3RoKVxuICAgIHN6ICo9IGMubGVuZ3RoXG4gICAgYyA9IGNbMF1cbiAgfVxuICBpZihzaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmRhcnJheSgpXG4gIH1cbiAgaWYoIXJlc3VsdCkge1xuICAgIHJlc3VsdCA9IG5kYXJyYXkobmV3IEZsb2F0NjRBcnJheShzeiksIHNoYXBlKVxuICB9XG4gIGRvX2NvbnZlcnQocmVzdWx0LCBhcnIpXG4gIHJldHVybiByZXN1bHRcbn1cbiIsIm1vZHVsZS5leHBvcnRzPXJlcXVpcmUoJ2N3aXNlLWNvbXBpbGVyJykoe1wiYXJnc1wiOltcImFycmF5XCIsXCJzY2FsYXJcIixcImluZGV4XCJdLFwicHJlXCI6e1wiYm9keVwiOlwie31cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXX0sXCJib2R5XCI6e1wiYm9keVwiOlwie1xcbnZhciBfaW5saW5lXzFfdj1faW5saW5lXzFfYXJnMV8sX2lubGluZV8xX2lcXG5mb3IoX2lubGluZV8xX2k9MDtfaW5saW5lXzFfaTxfaW5saW5lXzFfYXJnMl8ubGVuZ3RoLTE7KytfaW5saW5lXzFfaSkge1xcbl9pbmxpbmVfMV92PV9pbmxpbmVfMV92W19pbmxpbmVfMV9hcmcyX1tfaW5saW5lXzFfaV1dXFxufVxcbl9pbmxpbmVfMV9hcmcwXz1faW5saW5lXzFfdltfaW5saW5lXzFfYXJnMl9bX2lubGluZV8xX2FyZzJfLmxlbmd0aC0xXV1cXG59XCIsXCJhcmdzXCI6W3tcIm5hbWVcIjpcIl9pbmxpbmVfMV9hcmcwX1wiLFwibHZhbHVlXCI6dHJ1ZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzFfYXJnMV9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzJfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjR9XSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXCJfaW5saW5lXzFfaVwiLFwiX2lubGluZV8xX3ZcIl19LFwicG9zdFwiOntcImJvZHlcIjpcInt9XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltdLFwibG9jYWxWYXJzXCI6W119LFwiZnVuY05hbWVcIjpcImNvbnZlcnRcIixcImJsb2NrU2l6ZVwiOjY0fSlcbiIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBwb29sID0gcmVxdWlyZShcInR5cGVkYXJyYXktcG9vbFwiKVxuXG52YXIgSU5TRVJUSU9OX1NPUlRfVEhSRVNIT0xEID0gMzJcblxuZnVuY3Rpb24gZ2V0TWFsbG9jRnJlZShkdHlwZSkge1xuICBzd2l0Y2goZHR5cGUpIHtcbiAgICBjYXNlIFwidWludDhcIjpcbiAgICAgIHJldHVybiBbcG9vbC5tYWxsb2NVaW50OCwgcG9vbC5mcmVlVWludDhdXG4gICAgY2FzZSBcInVpbnQxNlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY1VpbnQxNiwgcG9vbC5mcmVlVWludDE2XVxuICAgIGNhc2UgXCJ1aW50MzJcIjpcbiAgICAgIHJldHVybiBbcG9vbC5tYWxsb2NVaW50MzIsIHBvb2wuZnJlZVVpbnQzMl1cbiAgICBjYXNlIFwiaW50OFwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0ludDgsIHBvb2wuZnJlZUludDhdXG4gICAgY2FzZSBcImludDE2XCI6XG4gICAgICByZXR1cm4gW3Bvb2wubWFsbG9jSW50MTYsIHBvb2wuZnJlZUludDE2XVxuICAgIGNhc2UgXCJpbnQzMlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0ludDMyLCBwb29sLmZyZWVJbnQzMl1cbiAgICBjYXNlIFwiZmxvYXQzMlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0Zsb2F0LCBwb29sLmZyZWVGbG9hdF1cbiAgICBjYXNlIFwiZmxvYXQ2NFwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0RvdWJsZSwgcG9vbC5mcmVlRG91YmxlXVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbFxuICB9XG59XG5cbmZ1bmN0aW9uIHNoYXBlQXJncyhkaW1lbnNpb24pIHtcbiAgdmFyIGFyZ3MgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGFyZ3MucHVzaChcInNcIitpKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiblwiK2kpXG4gIH1cbiAgZm9yKHZhciBpPTE7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBhcmdzLnB1c2goXCJkXCIraSlcbiAgfVxuICBmb3IodmFyIGk9MTsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGFyZ3MucHVzaChcImVcIitpKVxuICB9XG4gIGZvcih2YXIgaT0xOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiZlwiK2kpXG4gIH1cbiAgcmV0dXJuIGFyZ3Ncbn1cblxuZnVuY3Rpb24gY3JlYXRlSW5zZXJ0aW9uU29ydChvcmRlciwgZHR5cGUpIHtcblxuICB2YXIgY29kZSA9IFtcIid1c2Ugc3RyaWN0J1wiXVxuICB2YXIgZnVuY05hbWUgPSBbXCJuZGFycmF5SW5zZXJ0aW9uU29ydFwiLCBvcmRlci5qb2luKFwiZFwiKSwgZHR5cGVdLmpvaW4oXCJcIilcbiAgdmFyIGZ1bmNBcmdzID0gW1wibGVmdFwiLCBcInJpZ2h0XCIsIFwiZGF0YVwiLCBcIm9mZnNldFwiIF0uY29uY2F0KHNoYXBlQXJncyhvcmRlci5sZW5ndGgpKVxuICB2YXIgYWxsb2NhdG9yID0gZ2V0TWFsbG9jRnJlZShkdHlwZSlcbiAgXG4gIHZhciB2YXJzID0gWyBcImksaixjcHRyLHB0cj1sZWZ0KnMwK29mZnNldFwiIF1cbiAgXG4gIGlmKG9yZGVyLmxlbmd0aCA+IDEpIHtcbiAgICB2YXIgc2NyYXRjaF9zaGFwZSA9IFtdXG4gICAgZm9yKHZhciBpPTE7IGk8b3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhcnMucHVzaChcImlcIitpKVxuICAgICAgc2NyYXRjaF9zaGFwZS5wdXNoKFwiblwiK2kpXG4gICAgfVxuICAgIGlmKGFsbG9jYXRvcikge1xuICAgICAgdmFycy5wdXNoKFwic2NyYXRjaD1tYWxsb2MoXCIgKyBzY3JhdGNoX3NoYXBlLmpvaW4oXCIqXCIpICsgXCIpXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhcnMucHVzaChcInNjcmF0Y2g9bmV3IEFycmF5KFwiK3NjcmF0Y2hfc2hhcGUuam9pbihcIipcIikgKyBcIilcIilcbiAgICB9XG4gICAgdmFycy5wdXNoKFwiZHB0clwiLFwic3B0clwiLFwiYVwiLFwiYlwiKVxuICB9IGVsc2Uge1xuICAgIHZhcnMucHVzaChcInNjcmF0Y2hcIilcbiAgfVxuICBcbiAgZnVuY3Rpb24gZGF0YVJlYWQocHRyKSB7XG4gICAgaWYoZHR5cGUgPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICByZXR1cm4gW1wiZGF0YS5nZXQoXCIsIHB0ciwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXVwiXS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGRhdGFXcml0ZShwdHIsIHYpIHtcbiAgICBpZihkdHlwZSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgIHJldHVybiBbXCJkYXRhLnNldChcIiwgcHRyLCBcIixcIiwgdiwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXT1cIix2XS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIC8vQ3JlYXRlIGZ1bmN0aW9uIGhlYWRlclxuICBjb2RlLnB1c2goXG4gICAgW1wiZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihcIiwgZnVuY0FyZ3Muam9pbihcIixcIiksIFwiKXt2YXIgXCIsIHZhcnMuam9pbihcIixcIildLmpvaW4oXCJcIiksXG4gICAgICBcImZvcihpPWxlZnQrMTtpPD1yaWdodDsrK2kpe1wiLFxuICAgICAgICBcImo9aTtwdHIrPXMwXCIsXG4gICAgICAgIFwiY3B0cj1wdHJcIilcbiAgXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gIFxuICAgIC8vQ29weSBkYXRhIGludG8gc2NyYXRjaFxuICAgIGNvZGUucHVzaChcImRwdHI9MDtzcHRyPXB0clwiKVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixqLFwiPTA7aVwiLGosXCI8blwiLGosXCI7KytpXCIsaixcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChcInNjcmF0Y2hbZHB0cisrXT1cIixkYXRhUmVhZChcInNwdHJcIikpXG4gICAgZm9yKHZhciBpPTA7IGk8b3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBqID0gb3JkZXJbaV1cbiAgICAgIGlmKGogPT09IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcInNwdHIrPWRcIitqLFwifVwiKVxuICAgIH1cblxuICAgIFxuICAgIC8vQ29tcGFyZSBpdGVtcyBpbiBvdXRlciBsb29wXG4gICAgY29kZS5wdXNoKFwiX19nOndoaWxlKGotLT5sZWZ0KXtcIixcbiAgICAgICAgICAgICAgXCJkcHRyPTBcIixcbiAgICAgICAgICAgICAgXCJzcHRyPWNwdHItczBcIilcbiAgICBmb3IodmFyIGk9MTsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgICAgaWYoaSA9PT0gMSkge1xuICAgICAgICBjb2RlLnB1c2goXCJfX2w6XCIpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixpLFwiPTA7aVwiLGksXCI8blwiLGksXCI7KytpXCIsaSxcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChbXCJhPVwiLCBkYXRhUmVhZChcInNwdHJcIiksXCJcXG5iPXNjcmF0Y2hbZHB0cl1cXG5pZihhPGIpe2JyZWFrIF9fZ31cXG5pZihhPmIpe2JyZWFrIF9fbH1cIl0uam9pbihcIlwiKSlcbiAgICBmb3IodmFyIGk9b3JkZXIubGVuZ3RoLTE7IGk+PTE7IC0taSkge1xuICAgICAgY29kZS5wdXNoKFxuICAgICAgICBcInNwdHIrPWVcIitpLFxuICAgICAgICBcImRwdHIrPWZcIitpLFxuICAgICAgICBcIn1cIilcbiAgICB9XG4gICAgXG4gICAgLy9Db3B5IGRhdGEgYmFja1xuICAgIGNvZGUucHVzaChcImRwdHI9Y3B0cjtzcHRyPWNwdHItczBcIilcbiAgICBmb3IodmFyIGk9b3JkZXIubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgICAgdmFyIGogPSBvcmRlcltpXVxuICAgICAgaWYoaiA9PT0gMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKFtcImZvcihpXCIsaixcIj0wO2lcIixqLFwiPG5cIixqLFwiOysraVwiLGosXCIpe1wiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICBjb2RlLnB1c2goZGF0YVdyaXRlKFwiZHB0clwiLCBkYXRhUmVhZChcInNwdHJcIikpKVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZHB0cis9ZFwiLGosXCI7c3B0cis9ZFwiLGpdLmpvaW4oXCJcIiksXCJ9XCIpXG4gICAgfVxuICAgIFxuICAgIC8vQ2xvc2Ugd2hpbGUgbG9vcFxuICAgIGNvZGUucHVzaChcImNwdHItPXMwXFxufVwiKVxuXG4gICAgLy9Db3B5IHNjcmF0Y2ggaW50byBjcHRyXG4gICAgY29kZS5wdXNoKFwiZHB0cj1jcHRyO3NwdHI9MFwiKVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixqLFwiPTA7aVwiLGosXCI8blwiLGosXCI7KytpXCIsaixcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChkYXRhV3JpdGUoXCJkcHRyXCIsIFwic2NyYXRjaFtzcHRyKytdXCIpKVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goXCJkcHRyKz1kXCIraixcIn1cIilcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwic2NyYXRjaD1cIiArIGRhdGFSZWFkKFwicHRyXCIpLFxuICAgICAgICAgICAgICBcIndoaWxlKChqLS0+bGVmdCkmJihcIitkYXRhUmVhZChcImNwdHItczBcIikrXCI+c2NyYXRjaCkpe1wiLFxuICAgICAgICAgICAgICAgIGRhdGFXcml0ZShcImNwdHJcIiwgZGF0YVJlYWQoXCJjcHRyLXMwXCIpKSxcbiAgICAgICAgICAgICAgICBcImNwdHItPXMwXCIsXG4gICAgICAgICAgICAgIFwifVwiLFxuICAgICAgICAgICAgICBkYXRhV3JpdGUoXCJjcHRyXCIsIFwic2NyYXRjaFwiKSlcbiAgfVxuICBcbiAgLy9DbG9zZSBvdXRlciBsb29wIGJvZHlcbiAgY29kZS5wdXNoKFwifVwiKVxuICBpZihvcmRlci5sZW5ndGggPiAxICYmIGFsbG9jYXRvcikge1xuICAgIGNvZGUucHVzaChcImZyZWUoc2NyYXRjaClcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9IHJldHVybiBcIiArIGZ1bmNOYW1lKVxuICBcbiAgLy9Db21waWxlIGFuZCBsaW5rIGZ1bmN0aW9uXG4gIGlmKGFsbG9jYXRvcikge1xuICAgIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oXCJtYWxsb2NcIiwgXCJmcmVlXCIsIGNvZGUuam9pbihcIlxcblwiKSlcbiAgICByZXR1cm4gcmVzdWx0KGFsbG9jYXRvclswXSwgYWxsb2NhdG9yWzFdKVxuICB9IGVsc2Uge1xuICAgIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oY29kZS5qb2luKFwiXFxuXCIpKVxuICAgIHJldHVybiByZXN1bHQoKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVF1aWNrU29ydChvcmRlciwgZHR5cGUsIGluc2VydGlvblNvcnQpIHtcbiAgdmFyIGNvZGUgPSBbIFwiJ3VzZSBzdHJpY3QnXCIgXVxuICB2YXIgZnVuY05hbWUgPSBbXCJuZGFycmF5UXVpY2tTb3J0XCIsIG9yZGVyLmpvaW4oXCJkXCIpLCBkdHlwZV0uam9pbihcIlwiKVxuICB2YXIgZnVuY0FyZ3MgPSBbXCJsZWZ0XCIsIFwicmlnaHRcIiwgXCJkYXRhXCIsIFwib2Zmc2V0XCIgXS5jb25jYXQoc2hhcGVBcmdzKG9yZGVyLmxlbmd0aCkpXG4gIHZhciBhbGxvY2F0b3IgPSBnZXRNYWxsb2NGcmVlKGR0eXBlKVxuICB2YXIgbGFiZWxDb3VudGVyPTBcbiAgXG4gIGNvZGUucHVzaChbXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKFwiLCBmdW5jQXJncy5qb2luKFwiLFwiKSwgXCIpe1wiXS5qb2luKFwiXCIpKVxuICBcbiAgdmFyIHZhcnMgPSBbXG4gICAgXCJzaXh0aD0oKHJpZ2h0LWxlZnQrMSkvNil8MFwiLFxuICAgIFwiaW5kZXgxPWxlZnQrc2l4dGhcIixcbiAgICBcImluZGV4NT1yaWdodC1zaXh0aFwiLFxuICAgIFwiaW5kZXgzPShsZWZ0K3JpZ2h0KT4+MVwiLFxuICAgIFwiaW5kZXgyPWluZGV4My1zaXh0aFwiLFxuICAgIFwiaW5kZXg0PWluZGV4MytzaXh0aFwiLFxuICAgIFwiZWwxPWluZGV4MVwiLFxuICAgIFwiZWwyPWluZGV4MlwiLFxuICAgIFwiZWwzPWluZGV4M1wiLFxuICAgIFwiZWw0PWluZGV4NFwiLFxuICAgIFwiZWw1PWluZGV4NVwiLFxuICAgIFwibGVzcz1sZWZ0KzFcIixcbiAgICBcImdyZWF0PXJpZ2h0LTFcIixcbiAgICBcInBpdm90c19hcmVfZXF1YWw9dHJ1ZVwiLFxuICAgIFwidG1wXCIsXG4gICAgXCJ0bXAwXCIsXG4gICAgXCJ4XCIsXG4gICAgXCJ5XCIsXG4gICAgXCJ6XCIsXG4gICAgXCJrXCIsXG4gICAgXCJwdHIwXCIsXG4gICAgXCJwdHIxXCIsXG4gICAgXCJwdHIyXCIsXG4gICAgXCJjb21wX3Bpdm90MT0wXCIsXG4gICAgXCJjb21wX3Bpdm90Mj0wXCIsXG4gICAgXCJjb21wPTBcIlxuICBdXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgdmFyIGVsZV9zaXplID0gW11cbiAgICBmb3IodmFyIGk9MTsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgICAgZWxlX3NpemUucHVzaChcIm5cIitpKVxuICAgICAgdmFycy5wdXNoKFwiaVwiK2kpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPDg7ICsraSkge1xuICAgICAgdmFycy5wdXNoKFwiYl9wdHJcIitpKVxuICAgIH1cbiAgICB2YXJzLnB1c2goXG4gICAgICBcInB0cjNcIixcbiAgICAgIFwicHRyNFwiLFxuICAgICAgXCJwdHI1XCIsXG4gICAgICBcInB0cjZcIixcbiAgICAgIFwicHRyN1wiLFxuICAgICAgXCJwaXZvdF9wdHJcIixcbiAgICAgIFwicHRyX3NoaWZ0XCIsXG4gICAgICBcImVsZW1lbnRTaXplPVwiK2VsZV9zaXplLmpvaW4oXCIqXCIpKVxuICAgIGlmKGFsbG9jYXRvcikge1xuICAgICAgdmFycy5wdXNoKFwicGl2b3QxPW1hbGxvYyhlbGVtZW50U2l6ZSlcIixcbiAgICAgICAgICAgICAgICBcInBpdm90Mj1tYWxsb2MoZWxlbWVudFNpemUpXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhcnMucHVzaChcInBpdm90MT1uZXcgQXJyYXkoZWxlbWVudFNpemUpLHBpdm90Mj1uZXcgQXJyYXkoZWxlbWVudFNpemUpXCIpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhcnMucHVzaChcInBpdm90MVwiLCBcInBpdm90MlwiKVxuICB9XG4gIFxuICAvL0luaXRpYWxpemUgbG9jYWwgdmFyaWFibGVzXG4gIGNvZGUucHVzaChcInZhciBcIiArIHZhcnMuam9pbihcIixcIikpXG4gIFxuICBmdW5jdGlvbiB0b1BvaW50ZXIodikge1xuICAgIHJldHVybiBbXCIob2Zmc2V0K1wiLHYsXCIqczApXCJdLmpvaW4oXCJcIilcbiAgfVxuICBcbiAgZnVuY3Rpb24gZGF0YVJlYWQocHRyKSB7XG4gICAgaWYoZHR5cGUgPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICByZXR1cm4gW1wiZGF0YS5nZXQoXCIsIHB0ciwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXVwiXS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGRhdGFXcml0ZShwdHIsIHYpIHtcbiAgICBpZihkdHlwZSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgIHJldHVybiBbXCJkYXRhLnNldChcIiwgcHRyLCBcIixcIiwgdiwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXT1cIix2XS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGNhY2hlTG9vcChwdHJzLCB1c2VQaXZvdCwgYm9keSkge1xuICAgIGlmKHB0cnMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb2RlLnB1c2goXCJwdHIwPVwiK3RvUG9pbnRlcihwdHJzWzBdKSlcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yKHZhciBpPTA7IGk8cHRycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb2RlLnB1c2goW1wiYl9wdHJcIixpLFwiPXMwKlwiLHB0cnNbaV1dLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICAgIGlmKHVzZVBpdm90KSB7XG4gICAgICBjb2RlLnB1c2goXCJwaXZvdF9wdHI9MFwiKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJwdHJfc2hpZnQ9b2Zmc2V0XCIpXG4gICAgZm9yKHZhciBpPW9yZGVyLmxlbmd0aC0xOyBpPj0wOyAtLWkpIHtcbiAgICAgIHZhciBqID0gb3JkZXJbaV1cbiAgICAgIGlmKGogPT09IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChbXCJmb3IoaVwiLGosXCI9MDtpXCIsaixcIjxuXCIsaixcIjsrK2lcIixqLFwiKXtcIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgaWYocHRycy5sZW5ndGggPiAxKSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxwdHJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvZGUucHVzaChbXCJwdHJcIixpLFwiPWJfcHRyXCIsaSxcIitwdHJfc2hpZnRcIl0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICB9XG4gICAgY29kZS5wdXNoKGJvZHkpXG4gICAgaWYodXNlUGl2b3QpIHtcbiAgICAgIGNvZGUucHVzaChcIisrcGl2b3RfcHRyXCIpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBpZihwdHJzLmxlbmd0aD4xKSB7XG4gICAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdCs9ZFwiK2opXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlLnB1c2goXCJwdHIwKz1kXCIrailcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGxleGljb0xvb3AobGFiZWwsIHB0cnMsIHVzZVBpdm90LCBib2R5KSB7XG4gICAgaWYocHRycy5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvZGUucHVzaChcInB0cjA9XCIrdG9Qb2ludGVyKHB0cnNbMF0pKVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxwdHJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvZGUucHVzaChbXCJiX3B0clwiLGksXCI9czAqXCIscHRyc1tpXV0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdD1vZmZzZXRcIilcbiAgICB9XG4gICAgaWYodXNlUGl2b3QpIHtcbiAgICAgIGNvZGUucHVzaChcInBpdm90X3B0cj0wXCIpXG4gICAgfVxuICAgIGlmKGxhYmVsKSB7XG4gICAgICBjb2RlLnB1c2gobGFiZWwrXCI6XCIpXG4gICAgfVxuICAgIGZvcih2YXIgaT0xOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixpLFwiPTA7aVwiLGksXCI8blwiLGksXCI7KytpXCIsaSxcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGlmKHB0cnMubGVuZ3RoID4gMSkge1xuICAgICAgZm9yKHZhciBpPTA7IGk8cHRycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb2RlLnB1c2goW1wicHRyXCIsaSxcIj1iX3B0clwiLGksXCIrcHRyX3NoaWZ0XCJdLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICAgIGNvZGUucHVzaChib2R5KVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MTsgLS1pKSB7XG4gICAgICBpZih1c2VQaXZvdCkge1xuICAgICAgICBjb2RlLnB1c2goXCJwaXZvdF9wdHIrPWZcIitpKVxuICAgICAgfVxuICAgICAgaWYocHRycy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdCs9ZVwiK2kpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlLnB1c2goXCJwdHIwKz1lXCIraSlcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGNsZWFuVXAoKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSAmJiBhbGxvY2F0b3IpIHtcbiAgICAgIGNvZGUucHVzaChcImZyZWUocGl2b3QxKVwiLCBcImZyZWUocGl2b3QyKVwiKVxuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gY29tcGFyZVN3YXAoYV9pZCwgYl9pZCkge1xuICAgIHZhciBhID0gXCJlbFwiK2FfaWRcbiAgICB2YXIgYiA9IFwiZWxcIitiX2lkXG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgdmFyIGxibCA9IFwiX19sXCIgKyAoKytsYWJlbENvdW50ZXIpXG4gICAgICBsZXhpY29Mb29wKGxibCwgW2EsIGJdLCBmYWxzZSwgW1xuICAgICAgICBcImNvbXA9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiLVwiLGRhdGFSZWFkKFwicHRyMVwiKSxcIlxcblwiLFxuICAgICAgICBcImlmKGNvbXA+MCl7dG1wMD1cIiwgYSwgXCI7XCIsYSxcIj1cIixiLFwiO1wiLCBiLFwiPXRtcDA7YnJlYWsgXCIsIGxibCxcIn1cXG5cIixcbiAgICAgICAgXCJpZihjb21wPDApe2JyZWFrIFwiLCBsYmwsIFwifVwiXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChbXCJpZihcIiwgZGF0YVJlYWQodG9Qb2ludGVyKGEpKSwgXCI+XCIsIGRhdGFSZWFkKHRvUG9pbnRlcihiKSksIFwiKXt0bXAwPVwiLCBhLCBcIjtcIixhLFwiPVwiLGIsXCI7XCIsIGIsXCI9dG1wMH1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGNvbXBhcmVTd2FwKDEsIDIpXG4gIGNvbXBhcmVTd2FwKDQsIDUpXG4gIGNvbXBhcmVTd2FwKDEsIDMpXG4gIGNvbXBhcmVTd2FwKDIsIDMpXG4gIGNvbXBhcmVTd2FwKDEsIDQpXG4gIGNvbXBhcmVTd2FwKDMsIDQpXG4gIGNvbXBhcmVTd2FwKDIsIDUpXG4gIGNvbXBhcmVTd2FwKDIsIDMpXG4gIGNvbXBhcmVTd2FwKDQsIDUpXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgY2FjaGVMb29wKFtcImVsMVwiLCBcImVsMlwiLCBcImVsM1wiLCBcImVsNFwiLCBcImVsNVwiLCBcImluZGV4MVwiLCBcImluZGV4M1wiLCBcImluZGV4NVwiXSwgdHJ1ZSwgW1xuICAgICAgXCJwaXZvdDFbcGl2b3RfcHRyXT1cIixkYXRhUmVhZChcInB0cjFcIiksXCJcXG5cIixcbiAgICAgIFwicGl2b3QyW3Bpdm90X3B0cl09XCIsZGF0YVJlYWQoXCJwdHIzXCIpLFwiXFxuXCIsXG4gICAgICBcInBpdm90c19hcmVfZXF1YWw9cGl2b3RzX2FyZV9lcXVhbCYmKHBpdm90MVtwaXZvdF9wdHJdPT09cGl2b3QyW3Bpdm90X3B0cl0pXFxuXCIsXG4gICAgICBcIng9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiXFxuXCIsXG4gICAgICBcInk9XCIsZGF0YVJlYWQoXCJwdHIyXCIpLFwiXFxuXCIsXG4gICAgICBcIno9XCIsZGF0YVJlYWQoXCJwdHI0XCIpLFwiXFxuXCIsXG4gICAgICBkYXRhV3JpdGUoXCJwdHI1XCIsIFwieFwiKSxcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKFwicHRyNlwiLCBcInlcIiksXCJcXG5cIixcbiAgICAgIGRhdGFXcml0ZShcInB0cjdcIiwgXCJ6XCIpXG4gICAgXS5qb2luKFwiXCIpKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChbXG4gICAgICBcInBpdm90MT1cIiwgZGF0YVJlYWQodG9Qb2ludGVyKFwiZWwyXCIpKSwgXCJcXG5cIixcbiAgICAgIFwicGl2b3QyPVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDRcIikpLCBcIlxcblwiLFxuICAgICAgXCJwaXZvdHNfYXJlX2VxdWFsPXBpdm90MT09PXBpdm90MlxcblwiLFxuICAgICAgXCJ4PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDFcIikpLCBcIlxcblwiLFxuICAgICAgXCJ5PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDNcIikpLCBcIlxcblwiLFxuICAgICAgXCJ6PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDVcIikpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4MVwiKSwgXCJ4XCIpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4M1wiKSwgXCJ5XCIpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4NVwiKSwgXCJ6XCIpXG4gICAgXS5qb2luKFwiXCIpKVxuICB9XG4gIFxuXG4gIGZ1bmN0aW9uIG1vdmVFbGVtZW50KGRzdCwgc3JjKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgY2FjaGVMb29wKFtkc3QsIHNyY10sIGZhbHNlLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIwXCIsIGRhdGFSZWFkKFwicHRyMVwiKSlcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKGRhdGFXcml0ZSh0b1BvaW50ZXIoZHN0KSwgZGF0YVJlYWQodG9Qb2ludGVyKHNyYykpKSlcbiAgICB9XG4gIH1cbiAgXG4gIG1vdmVFbGVtZW50KFwiaW5kZXgyXCIsIFwibGVmdFwiKVxuICBtb3ZlRWxlbWVudChcImluZGV4NFwiLCBcInJpZ2h0XCIpXG4gIFxuICBmdW5jdGlvbiBjb21wYXJlUGl2b3QocmVzdWx0LCBwdHIsIG4pIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICB2YXIgbGJsID0gXCJfX2xcIiArICgrK2xhYmVsQ291bnRlcilcbiAgICAgIGxleGljb0xvb3AobGJsLCBbcHRyXSwgdHJ1ZSwgW1xuICAgICAgICByZXN1bHQsXCI9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiLXBpdm90XCIsbixcIltwaXZvdF9wdHJdXFxuXCIsXG4gICAgICAgIFwiaWYoXCIscmVzdWx0LFwiIT09MCl7YnJlYWsgXCIsIGxibCwgXCJ9XCJcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKFtyZXN1bHQsXCI9XCIsIGRhdGFSZWFkKHRvUG9pbnRlcihwdHIpKSwgXCItcGl2b3RcIiwgbl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHN3YXBFbGVtZW50cyhhLCBiKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgY2FjaGVMb29wKFthLGJdLGZhbHNlLFtcbiAgICAgICAgXCJ0bXA9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjBcIiwgZGF0YVJlYWQoXCJwdHIxXCIpKSxcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIxXCIsIFwidG1wXCIpXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChbXG4gICAgICAgIFwicHRyMD1cIix0b1BvaW50ZXIoYSksXCJcXG5cIixcbiAgICAgICAgXCJwdHIxPVwiLHRvUG9pbnRlcihiKSxcIlxcblwiLFxuICAgICAgICBcInRtcD1cIixkYXRhUmVhZChcInB0cjBcIiksXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMFwiLCBkYXRhUmVhZChcInB0cjFcIikpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjFcIiwgXCJ0bXBcIilcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHRyaXBsZVN3YXAoaywgbGVzcywgZ3JlYXQpIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICBjYWNoZUxvb3AoW2ssbGVzcyxncmVhdF0sIGZhbHNlLCBbXG4gICAgICAgIFwidG1wPVwiLGRhdGFSZWFkKFwicHRyMFwiKSxcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIwXCIsIGRhdGFSZWFkKFwicHRyMVwiKSksXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMVwiLCBkYXRhUmVhZChcInB0cjJcIikpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjJcIiwgXCJ0bXBcIilcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICAgIGNvZGUucHVzaChcIisrXCIrbGVzcywgXCItLVwiK2dyZWF0KVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goW1xuICAgICAgICBcInB0cjA9XCIsdG9Qb2ludGVyKGspLFwiXFxuXCIsXG4gICAgICAgIFwicHRyMT1cIix0b1BvaW50ZXIobGVzcyksXCJcXG5cIixcbiAgICAgICAgXCJwdHIyPVwiLHRvUG9pbnRlcihncmVhdCksXCJcXG5cIixcbiAgICAgICAgXCIrK1wiLGxlc3MsXCJcXG5cIixcbiAgICAgICAgXCItLVwiLGdyZWF0LFwiXFxuXCIsXG4gICAgICAgIFwidG1wPVwiLCBkYXRhUmVhZChcInB0cjBcIiksIFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjBcIiwgZGF0YVJlYWQoXCJwdHIxXCIpKSwgXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMVwiLCBkYXRhUmVhZChcInB0cjJcIikpLCBcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIyXCIsIFwidG1wXCIpXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBzd2FwQW5kRGVjcmVtZW50KGssIGdyZWF0KSB7XG4gICAgc3dhcEVsZW1lbnRzKGssIGdyZWF0KVxuICAgIGNvZGUucHVzaChcIi0tXCIrZ3JlYXQpXG4gIH1cbiAgICBcbiAgY29kZS5wdXNoKFwiaWYocGl2b3RzX2FyZV9lcXVhbCl7XCIpXG4gICAgLy9QaXZvdHMgYXJlIGVxdWFsIGNhc2VcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wXCIsIFwia1wiLCAxKVxuICAgICAgY29kZS5wdXNoKFwiaWYoY29tcD09PTApe2NvbnRpbnVlfVwiKVxuICAgICAgY29kZS5wdXNoKFwiaWYoY29tcDwwKXtcIilcbiAgICAgICAgY29kZS5wdXNoKFwiaWYoayE9PWxlc3Mpe1wiKVxuICAgICAgICAgIHN3YXBFbGVtZW50cyhcImtcIiwgXCJsZXNzXCIpXG4gICAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICAgICAgY29kZS5wdXNoKFwiKytsZXNzXCIpXG4gICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgY29kZS5wdXNoKFwid2hpbGUodHJ1ZSl7XCIpXG4gICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgY29kZS5wdXNoKFwiaWYoY29tcD4wKXtcIilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImdyZWF0LS1cIilcbiAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZSBpZihjb21wPDApe1wiKVxuICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICBzd2FwQW5kRGVjcmVtZW50KFwia1wiLCBcImdyZWF0XCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJicmVha1wiKVxuICAgICAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgIGNvZGUucHVzaChcIn1cIilcbiAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgLy9QaXZvdHMgbm90IGVxdWFsIGNhc2VcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MVwiLCBcImtcIiwgMSlcbiAgICAgIGNvZGUucHVzaChcImlmKGNvbXBfcGl2b3QxPDApe1wiKVxuICAgICAgICBjb2RlLnB1c2goXCJpZihrIT09bGVzcyl7XCIpXG4gICAgICAgICAgc3dhcEVsZW1lbnRzKFwia1wiLCBcImxlc3NcIilcbiAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCIrK2xlc3NcIilcbiAgICAgIGNvZGUucHVzaChcIn1lbHNle1wiKVxuICAgICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MlwiLCBcImtcIiwgMilcbiAgICAgICAgY29kZS5wdXNoKFwiaWYoY29tcF9waXZvdDI+MCl7XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwid2hpbGUodHJ1ZSl7XCIpXG4gICAgICAgICAgICBjb21wYXJlUGl2b3QoXCJjb21wXCIsIFwiZ3JlYXRcIiwgMilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA+MCl7XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKC0tZ3JlYXQ8ayl7YnJlYWt9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImNvbnRpbnVlXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA8MCl7XCIpXG4gICAgICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICAgICAgc3dhcEFuZERlY3JlbWVudChcImtcIiwgXCJncmVhdFwiKVxuICAgICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICBjb2RlLnB1c2goXCJ9XCIpXG4gIFxuICAvL01vdmUgcGl2b3RzIHRvIGNvcnJlY3QgcGxhY2VcbiAgZnVuY3Rpb24gc3RvcmVQaXZvdChtZW1fZGVzdCwgcGl2b3RfZGVzdCwgcGl2b3QpIHtcbiAgICBpZihvcmRlci5sZW5ndGg+MSkge1xuICAgICAgY2FjaGVMb29wKFttZW1fZGVzdCwgcGl2b3RfZGVzdF0sIHRydWUsIFtcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMFwiLCBkYXRhUmVhZChcInB0cjFcIikpLCBcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIxXCIsIFtcInBpdm90XCIscGl2b3QsXCJbcGl2b3RfcHRyXVwiXS5qb2luKFwiXCIpKVxuICAgICAgXS5qb2luKFwiXCIpKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goXG4gICAgICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihtZW1fZGVzdCksIGRhdGFSZWFkKHRvUG9pbnRlcihwaXZvdF9kZXN0KSkpLFxuICAgICAgICAgIGRhdGFXcml0ZSh0b1BvaW50ZXIocGl2b3RfZGVzdCksIFwicGl2b3RcIitwaXZvdCkpXG4gICAgfVxuICB9XG4gIFxuICBzdG9yZVBpdm90KFwibGVmdFwiLCBcIihsZXNzLTEpXCIsIDEpXG4gIHN0b3JlUGl2b3QoXCJyaWdodFwiLCBcIihncmVhdCsxKVwiLCAyKVxuXG4gIC8vUmVjdXJzaXZlIHNvcnQgY2FsbFxuICBmdW5jdGlvbiBkb1NvcnQobGVmdCwgcmlnaHQpIHtcbiAgICBjb2RlLnB1c2goW1xuICAgICAgXCJpZigoXCIscmlnaHQsXCItXCIsbGVmdCxcIik8PVwiLElOU0VSVElPTl9TT1JUX1RIUkVTSE9MRCxcIil7XFxuXCIsXG4gICAgICAgIFwiaW5zZXJ0aW9uU29ydChcIiwgbGVmdCwgXCIsXCIsIHJpZ2h0LCBcIixkYXRhLG9mZnNldCxcIiwgc2hhcGVBcmdzKG9yZGVyLmxlbmd0aCkuam9pbihcIixcIiksIFwiKVxcblwiLFxuICAgICAgXCJ9ZWxzZXtcXG5cIixcbiAgICAgICAgZnVuY05hbWUsIFwiKFwiLCBsZWZ0LCBcIixcIiwgcmlnaHQsIFwiLGRhdGEsb2Zmc2V0LFwiLCBzaGFwZUFyZ3Mob3JkZXIubGVuZ3RoKS5qb2luKFwiLFwiKSwgXCIpXFxuXCIsXG4gICAgICBcIn1cIlxuICAgIF0uam9pbihcIlwiKSlcbiAgfVxuICBkb1NvcnQoXCJsZWZ0XCIsIFwiKGxlc3MtMilcIilcbiAgZG9Tb3J0KFwiKGdyZWF0KzIpXCIsIFwicmlnaHRcIilcbiAgXG4gIC8vSWYgcGl2b3RzIGFyZSBlcXVhbCwgdGhlbiBlYXJseSBvdXRcbiAgY29kZS5wdXNoKFwiaWYocGl2b3RzX2FyZV9lcXVhbCl7XCIpXG4gICAgY2xlYW5VcCgpXG4gICAgY29kZS5wdXNoKFwicmV0dXJuXCIpXG4gIGNvZGUucHVzaChcIn1cIilcbiAgXG4gIGZ1bmN0aW9uIHdhbGtQb2ludGVyKHB0ciwgcGl2b3QsIGJvZHkpIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICBjb2RlLnB1c2goW1wiX19sXCIsKytsYWJlbENvdW50ZXIsXCI6d2hpbGUodHJ1ZSl7XCJdLmpvaW4oXCJcIikpXG4gICAgICBjYWNoZUxvb3AoW3B0cl0sIHRydWUsIFtcbiAgICAgICAgXCJpZihcIiwgZGF0YVJlYWQoXCJwdHIwXCIpLCBcIiE9PXBpdm90XCIsIHBpdm90LCBcIltwaXZvdF9wdHJdKXticmVhayBfX2xcIiwgbGFiZWxDb3VudGVyLCBcIn1cIlxuICAgICAgXS5qb2luKFwiXCIpKVxuICAgICAgY29kZS5wdXNoKGJvZHksIFwifVwiKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goW1wid2hpbGUoXCIsIGRhdGFSZWFkKHRvUG9pbnRlcihwdHIpKSwgXCI9PT1waXZvdFwiLCBwaXZvdCwgXCIpe1wiLCBib2R5LCBcIn1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIC8vQ2hlY2sgYm91bmRzXG4gIGNvZGUucHVzaChcImlmKGxlc3M8aW5kZXgxJiZncmVhdD5pbmRleDUpe1wiKVxuICBcbiAgICB3YWxrUG9pbnRlcihcImxlc3NcIiwgMSwgXCIrK2xlc3NcIilcbiAgICB3YWxrUG9pbnRlcihcImdyZWF0XCIsIDIsIFwiLS1ncmVhdFwiKVxuICBcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MVwiLCBcImtcIiwgMSlcbiAgICAgIGNvZGUucHVzaChcImlmKGNvbXBfcGl2b3QxPT09MCl7XCIpXG4gICAgICAgIGNvZGUucHVzaChcImlmKGshPT1sZXNzKXtcIilcbiAgICAgICAgICBzd2FwRWxlbWVudHMoXCJrXCIsIFwibGVzc1wiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgIGNvZGUucHVzaChcIisrbGVzc1wiKVxuICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgIGNvbXBhcmVQaXZvdChcImNvbXBfcGl2b3QyXCIsIFwia1wiLCAyKVxuICAgICAgICBjb2RlLnB1c2goXCJpZihjb21wX3Bpdm90Mj09PTApe1wiKVxuICAgICAgICAgIGNvZGUucHVzaChcIndoaWxlKHRydWUpe1wiKVxuICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJpZihjb21wPT09MCl7XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKC0tZ3JlYXQ8ayl7YnJlYWt9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImNvbnRpbnVlXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA8MCl7XCIpXG4gICAgICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICAgICAgc3dhcEFuZERlY3JlbWVudChcImtcIiwgXCJncmVhdFwiKVxuICAgICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICBjb2RlLnB1c2goXCJ9XCIpXG4gIFxuICAvL0NsZWFuIHVwIGFuZCBkbyBhIGZpbmFsIHNvcnRpbmcgcGFzc1xuICBjbGVhblVwKClcbiAgZG9Tb3J0KFwibGVzc1wiLCBcImdyZWF0XCIpXG4gXG4gIC8vQ2xvc2Ugb2ZmIG1haW4gbG9vcFxuICBjb2RlLnB1c2goXCJ9cmV0dXJuIFwiICsgZnVuY05hbWUpXG4gIFxuICAvL0NvbXBpbGUgYW5kIGxpbmtcbiAgaWYob3JkZXIubGVuZ3RoID4gMSAmJiBhbGxvY2F0b3IpIHtcbiAgICB2YXIgY29tcGlsZWQgPSBuZXcgRnVuY3Rpb24oXCJpbnNlcnRpb25Tb3J0XCIsIFwibWFsbG9jXCIsIFwiZnJlZVwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gICAgcmV0dXJuIGNvbXBpbGVkKGluc2VydGlvblNvcnQsIGFsbG9jYXRvclswXSwgYWxsb2NhdG9yWzFdKVxuICB9XG4gIHZhciBjb21waWxlZCA9IG5ldyBGdW5jdGlvbihcImluc2VydGlvblNvcnRcIiwgY29kZS5qb2luKFwiXFxuXCIpKVxuICByZXR1cm4gY29tcGlsZWQoaW5zZXJ0aW9uU29ydClcbn1cblxuZnVuY3Rpb24gY29tcGlsZVNvcnQob3JkZXIsIGR0eXBlKSB7XG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnXCJdXG4gIHZhciBmdW5jTmFtZSA9IFtcIm5kYXJyYXlTb3J0V3JhcHBlclwiLCBvcmRlci5qb2luKFwiZFwiKSwgZHR5cGVdLmpvaW4oXCJcIilcbiAgdmFyIGZ1bmNBcmdzID0gWyBcImFycmF5XCIgXVxuICBcbiAgY29kZS5wdXNoKFtcImZ1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoXCIsIGZ1bmNBcmdzLmpvaW4oXCIsXCIpLCBcIil7XCJdLmpvaW4oXCJcIikpXG4gIFxuICAvL1VucGFjayBsb2NhbCB2YXJpYWJsZXMgZnJvbSBhcnJheVxuICB2YXIgdmFycyA9IFtcImRhdGE9YXJyYXkuZGF0YSxvZmZzZXQ9YXJyYXkub2Zmc2V0fDAsc2hhcGU9YXJyYXkuc2hhcGUsc3RyaWRlPWFycmF5LnN0cmlkZVwiXVxuICBmb3IodmFyIGk9MDsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgIHZhcnMucHVzaChbXCJzXCIsaSxcIj1zdHJpZGVbXCIsaSxcIl18MCxuXCIsaSxcIj1zaGFwZVtcIixpLFwiXXwwXCJdLmpvaW4oXCJcIikpXG4gIH1cbiAgXG4gIHZhciBzY3JhdGNoX3N0cmlkZSA9IG5ldyBBcnJheShvcmRlci5sZW5ndGgpXG4gIHZhciBucHJvZCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGsgPSBvcmRlcltpXVxuICAgIGlmKGsgPT09IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKG5wcm9kLmxlbmd0aCA9PT0gMCkge1xuICAgICAgc2NyYXRjaF9zdHJpZGVba10gPSBcIjFcIlxuICAgIH0gZWxzZSB7XG4gICAgICBzY3JhdGNoX3N0cmlkZVtrXSA9IG5wcm9kLmpvaW4oXCIqXCIpXG4gICAgfVxuICAgIG5wcm9kLnB1c2goXCJuXCIraylcbiAgfVxuICBcbiAgdmFyIHAgPSAtMSwgcSA9IC0xXG4gIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGogPSBvcmRlcltpXVxuICAgIGlmKGogIT09IDApIHtcbiAgICAgIGlmKHAgPiAwKSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJkXCIsaixcIj1zXCIsaixcIi1kXCIscCxcIipuXCIscF0uam9pbihcIlwiKSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJkXCIsaixcIj1zXCIsal0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICAgIHAgPSBqXG4gICAgfVxuICAgIHZhciBrID0gb3JkZXIubGVuZ3RoLTEtaVxuICAgIGlmKGsgIT09IDApIHtcbiAgICAgIGlmKHEgPiAwKSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJlXCIsayxcIj1zXCIsayxcIi1lXCIscSxcIipuXCIscSxcbiAgICAgICAgICAgICAgICAgIFwiLGZcIixrLFwiPVwiLHNjcmF0Y2hfc3RyaWRlW2tdLFwiLWZcIixxLFwiKm5cIixxXS5qb2luKFwiXCIpKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFycy5wdXNoKFtcImVcIixrLFwiPXNcIixrLFwiLGZcIixrLFwiPVwiLHNjcmF0Y2hfc3RyaWRlW2tdXS5qb2luKFwiXCIpKVxuICAgICAgfVxuICAgICAgcSA9IGtcbiAgICB9XG4gIH1cbiAgXG4gIC8vRGVjbGFyZSBsb2NhbCB2YXJpYWJsZXNcbiAgY29kZS5wdXNoKFwidmFyIFwiICsgdmFycy5qb2luKFwiLFwiKSlcbiAgXG4gIC8vQ3JlYXRlIGFyZ3VtZW50cyBmb3Igc3Vicm91dGluZVxuICB2YXIgc29ydEFyZ3MgPSBbXCIwXCIsIFwibjAtMVwiLCBcImRhdGFcIiwgXCJvZmZzZXRcIl0uY29uY2F0KHNoYXBlQXJncyhvcmRlci5sZW5ndGgpKVxuICBcbiAgLy9DYWxsIG1haW4gc29ydGluZyByb3V0aW5lXG4gIGNvZGUucHVzaChbXG4gICAgXCJpZihuMDw9XCIsSU5TRVJUSU9OX1NPUlRfVEhSRVNIT0xELFwiKXtcIixcbiAgICAgIFwiaW5zZXJ0aW9uU29ydChcIiwgc29ydEFyZ3Muam9pbihcIixcIiksIFwiKX1lbHNle1wiLFxuICAgICAgXCJxdWlja1NvcnQoXCIsIHNvcnRBcmdzLmpvaW4oXCIsXCIpLFxuICAgIFwiKX1cIlxuICBdLmpvaW4oXCJcIikpXG4gIFxuICAvL1JldHVyblxuICBjb2RlLnB1c2goXCJ9cmV0dXJuIFwiICsgZnVuY05hbWUpXG4gIFxuICAvL0xpbmsgZXZlcnl0aGluZyB0b2dldGhlclxuICB2YXIgcmVzdWx0ID0gbmV3IEZ1bmN0aW9uKFwiaW5zZXJ0aW9uU29ydFwiLCBcInF1aWNrU29ydFwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gIHZhciBpbnNlcnRpb25Tb3J0ID0gY3JlYXRlSW5zZXJ0aW9uU29ydChvcmRlciwgZHR5cGUpXG4gIHZhciBxdWlja1NvcnQgPSBjcmVhdGVRdWlja1NvcnQob3JkZXIsIGR0eXBlLCBpbnNlcnRpb25Tb3J0KVxuICByZXR1cm4gcmVzdWx0KGluc2VydGlvblNvcnQsIHF1aWNrU29ydClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb21waWxlU29ydCIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBjb21waWxlID0gcmVxdWlyZShcIi4vbGliL2NvbXBpbGVfc29ydC5qc1wiKVxudmFyIENBQ0hFID0ge31cblxuZnVuY3Rpb24gc29ydChhcnJheSkge1xuICB2YXIgb3JkZXIgPSBhcnJheS5vcmRlclxuICB2YXIgZHR5cGUgPSBhcnJheS5kdHlwZVxuICB2YXIgdHlwZVNpZyA9IFtvcmRlciwgZHR5cGUgXVxuICB2YXIgdHlwZU5hbWUgPSB0eXBlU2lnLmpvaW4oXCI6XCIpXG4gIHZhciBjb21waWxlZCA9IENBQ0hFW3R5cGVOYW1lXVxuICBpZighY29tcGlsZWQpIHtcbiAgICBDQUNIRVt0eXBlTmFtZV0gPSBjb21waWxlZCA9IGNvbXBpbGUob3JkZXIsIGR0eXBlKVxuICB9XG4gIGNvbXBpbGVkKGFycmF5KVxuICByZXR1cm4gYXJyYXlcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzb3J0IiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBpbnRlcnAgID0gcmVxdWlyZSgnbmRhcnJheS1saW5lYXItaW50ZXJwb2xhdGUnKVxuXG5cbnZhciBkb193YXJwID0gcmVxdWlyZSgnY3dpc2UvbGliL3dyYXBwZXInKSh7XCJhcmdzXCI6W1wiaW5kZXhcIixcImFycmF5XCIsXCJzY2FsYXJcIixcInNjYWxhclwiLFwic2NhbGFyXCJdLFwicHJlXCI6e1wiYm9keVwiOlwie3RoaXNfd2FycGVkPW5ldyBBcnJheShfaW5saW5lXzNfYXJnNF8pfVwiLFwiYXJnc1wiOlt7XCJuYW1lXCI6XCJfaW5saW5lXzNfYXJnMF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjB9LHtcIm5hbWVcIjpcIl9pbmxpbmVfM19hcmcxX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MH0se1wibmFtZVwiOlwiX2lubGluZV8zX2FyZzJfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjowfSx7XCJuYW1lXCI6XCJfaW5saW5lXzNfYXJnM19cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjB9LHtcIm5hbWVcIjpcIl9pbmxpbmVfM19hcmc0X1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfV0sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwiYm9keVwiOntcImJvZHlcIjpcIntfaW5saW5lXzRfYXJnMl8odGhpc193YXJwZWQsX2lubGluZV80X2FyZzBfKSxfaW5saW5lXzRfYXJnMV89X2lubGluZV80X2FyZzNfLmFwcGx5KHZvaWQgMCx0aGlzX3dhcnBlZCl9XCIsXCJhcmdzXCI6W3tcIm5hbWVcIjpcIl9pbmxpbmVfNF9hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzRfYXJnMV9cIixcImx2YWx1ZVwiOnRydWUsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV80X2FyZzJfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfNF9hcmczX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzRfYXJnNF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjB9XSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJwb3N0XCI6e1wiYm9keVwiOlwie31cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXX0sXCJkZWJ1Z1wiOmZhbHNlLFwiZnVuY05hbWVcIjpcIndhcnBORFwiLFwiYmxvY2tTaXplXCI6NjR9KVxuXG52YXIgZG9fd2FycF8xID0gcmVxdWlyZSgnY3dpc2UvbGliL3dyYXBwZXInKSh7XCJhcmdzXCI6W1wiaW5kZXhcIixcImFycmF5XCIsXCJzY2FsYXJcIixcInNjYWxhclwiLFwic2NhbGFyXCJdLFwicHJlXCI6e1wiYm9keVwiOlwie3RoaXNfd2FycGVkPVswXX1cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJib2R5XCI6e1wiYm9keVwiOlwie19pbmxpbmVfN19hcmcyXyh0aGlzX3dhcnBlZCxfaW5saW5lXzdfYXJnMF8pLF9pbmxpbmVfN19hcmcxXz1faW5saW5lXzdfYXJnM18oX2lubGluZV83X2FyZzRfLHRoaXNfd2FycGVkWzBdKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV83X2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfN19hcmcxX1wiLFwibHZhbHVlXCI6dHJ1ZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzdfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV83X2FyZzNfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfN19hcmc0X1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfV0sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwicG9zdFwiOntcImJvZHlcIjpcInt9XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltdLFwibG9jYWxWYXJzXCI6W119LFwiZGVidWdcIjpmYWxzZSxcImZ1bmNOYW1lXCI6XCJ3YXJwMURcIixcImJsb2NrU2l6ZVwiOjY0fSlcblxudmFyIGRvX3dhcnBfMiA9IHJlcXVpcmUoJ2N3aXNlL2xpYi93cmFwcGVyJykoe1wiYXJnc1wiOltcImluZGV4XCIsXCJhcnJheVwiLFwic2NhbGFyXCIsXCJzY2FsYXJcIixcInNjYWxhclwiXSxcInByZVwiOntcImJvZHlcIjpcInt0aGlzX3dhcnBlZD1bMCwwXX1cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJib2R5XCI6e1wiYm9keVwiOlwie19pbmxpbmVfMTBfYXJnMl8odGhpc193YXJwZWQsX2lubGluZV8xMF9hcmcwXyksX2lubGluZV8xMF9hcmcxXz1faW5saW5lXzEwX2FyZzNfKF9pbmxpbmVfMTBfYXJnNF8sdGhpc193YXJwZWRbMF0sdGhpc193YXJwZWRbMV0pfVwiLFwiYXJnc1wiOlt7XCJuYW1lXCI6XCJfaW5saW5lXzEwX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTBfYXJnMV9cIixcImx2YWx1ZVwiOnRydWUsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xMF9hcmcyX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEwX2FyZzNfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTBfYXJnNF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX3dhcnBlZFwiXSxcImxvY2FsVmFyc1wiOltdfSxcInBvc3RcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwid2FycDJEXCIsXCJibG9ja1NpemVcIjo2NH0pXG5cbnZhciBkb193YXJwXzMgPSByZXF1aXJlKCdjd2lzZS9saWIvd3JhcHBlcicpKHtcImFyZ3NcIjpbXCJpbmRleFwiLFwiYXJyYXlcIixcInNjYWxhclwiLFwic2NhbGFyXCIsXCJzY2FsYXJcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7dGhpc193YXJwZWQ9WzAsMCwwXX1cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJib2R5XCI6e1wiYm9keVwiOlwie19pbmxpbmVfMTNfYXJnMl8odGhpc193YXJwZWQsX2lubGluZV8xM19hcmcwXyksX2lubGluZV8xM19hcmcxXz1faW5saW5lXzEzX2FyZzNfKF9pbmxpbmVfMTNfYXJnNF8sdGhpc193YXJwZWRbMF0sdGhpc193YXJwZWRbMV0sdGhpc193YXJwZWRbMl0pfVwiLFwiYXJnc1wiOlt7XCJuYW1lXCI6XCJfaW5saW5lXzEzX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTNfYXJnMV9cIixcImx2YWx1ZVwiOnRydWUsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xM19hcmcyX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEzX2FyZzNfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTNfYXJnNF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX3dhcnBlZFwiXSxcImxvY2FsVmFyc1wiOltdfSxcInBvc3RcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwid2FycDNEXCIsXCJibG9ja1NpemVcIjo2NH0pXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd2FycChkZXN0LCBzcmMsIGZ1bmMpIHtcbiAgc3dpdGNoKHNyYy5zaGFwZS5sZW5ndGgpIHtcbiAgICBjYXNlIDE6XG4gICAgICBkb193YXJwXzEoZGVzdCwgZnVuYywgaW50ZXJwLmQxLCBzcmMpXG4gICAgICBicmVha1xuICAgIGNhc2UgMjpcbiAgICAgIGRvX3dhcnBfMihkZXN0LCBmdW5jLCBpbnRlcnAuZDIsIHNyYylcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAzOlxuICAgICAgZG9fd2FycF8zKGRlc3QsIGZ1bmMsIGludGVycC5kMywgc3JjKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgZG9fd2FycChkZXN0LCBmdW5jLCBpbnRlcnAuYmluZCh1bmRlZmluZWQsIHNyYyksIHNyYy5zaGFwZS5sZW5ndGgpXG4gICAgICBicmVha1xuICB9XG4gIHJldHVybiBkZXN0XG59XG4iLCJ2YXIgaW90YSA9IHJlcXVpcmUoXCJpb3RhLWFycmF5XCIpXG52YXIgaXNCdWZmZXIgPSByZXF1aXJlKFwiaXMtYnVmZmVyXCIpXG5cbnZhciBoYXNUeXBlZEFycmF5cyAgPSAoKHR5cGVvZiBGbG9hdDY0QXJyYXkpICE9PSBcInVuZGVmaW5lZFwiKVxuXG5mdW5jdGlvbiBjb21wYXJlMXN0KGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gLSBiWzBdXG59XG5cbmZ1bmN0aW9uIG9yZGVyKCkge1xuICB2YXIgc3RyaWRlID0gdGhpcy5zdHJpZGVcbiAgdmFyIHRlcm1zID0gbmV3IEFycmF5KHN0cmlkZS5sZW5ndGgpXG4gIHZhciBpXG4gIGZvcihpPTA7IGk8dGVybXMubGVuZ3RoOyArK2kpIHtcbiAgICB0ZXJtc1tpXSA9IFtNYXRoLmFicyhzdHJpZGVbaV0pLCBpXVxuICB9XG4gIHRlcm1zLnNvcnQoY29tcGFyZTFzdClcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh0ZXJtcy5sZW5ndGgpXG4gIGZvcihpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gdGVybXNbaV1bMV1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgZGltZW5zaW9uKSB7XG4gIHZhciBjbGFzc05hbWUgPSBbXCJWaWV3XCIsIGRpbWVuc2lvbiwgXCJkXCIsIGR0eXBlXS5qb2luKFwiXCIpXG4gIGlmKGRpbWVuc2lvbiA8IDApIHtcbiAgICBjbGFzc05hbWUgPSBcIlZpZXdfTmlsXCIgKyBkdHlwZVxuICB9XG4gIHZhciB1c2VHZXR0ZXJzID0gKGR0eXBlID09PSBcImdlbmVyaWNcIilcblxuICBpZihkaW1lbnNpb24gPT09IC0xKSB7XG4gICAgLy9TcGVjaWFsIGNhc2UgZm9yIHRyaXZpYWwgYXJyYXlzXG4gICAgdmFyIGNvZGUgPVxuICAgICAgXCJmdW5jdGlvbiBcIitjbGFzc05hbWUrXCIoYSl7dGhpcy5kYXRhPWE7fTtcXFxudmFyIHByb3RvPVwiK2NsYXNzTmFtZStcIi5wcm90b3R5cGU7XFxcbnByb3RvLmR0eXBlPSdcIitkdHlwZStcIic7XFxcbnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIC0xfTtcXFxucHJvdG8uc2l6ZT0wO1xcXG5wcm90by5kaW1lbnNpb249LTE7XFxcbnByb3RvLnNoYXBlPXByb3RvLnN0cmlkZT1wcm90by5vcmRlcj1bXTtcXFxucHJvdG8ubG89cHJvdG8uaGk9cHJvdG8udHJhbnNwb3NlPXByb3RvLnN0ZXA9XFxcbmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhKTt9O1xcXG5wcm90by5nZXQ9cHJvdG8uc2V0PWZ1bmN0aW9uKCl7fTtcXFxucHJvdG8ucGljaz1mdW5jdGlvbigpe3JldHVybiBudWxsfTtcXFxucmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoYSl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIoYSk7fVwiXG4gICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbihjb2RlKVxuICAgIHJldHVybiBwcm9jZWR1cmUoKVxuICB9IGVsc2UgaWYoZGltZW5zaW9uID09PSAwKSB7XG4gICAgLy9TcGVjaWFsIGNhc2UgZm9yIDBkIGFycmF5c1xuICAgIHZhciBjb2RlID1cbiAgICAgIFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiKGEsZCkge1xcXG50aGlzLmRhdGEgPSBhO1xcXG50aGlzLm9mZnNldCA9IGRcXFxufTtcXFxudmFyIHByb3RvPVwiK2NsYXNzTmFtZStcIi5wcm90b3R5cGU7XFxcbnByb3RvLmR0eXBlPSdcIitkdHlwZStcIic7XFxcbnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMub2Zmc2V0fTtcXFxucHJvdG8uZGltZW5zaW9uPTA7XFxcbnByb3RvLnNpemU9MTtcXFxucHJvdG8uc2hhcGU9XFxcbnByb3RvLnN0cmlkZT1cXFxucHJvdG8ub3JkZXI9W107XFxcbnByb3RvLmxvPVxcXG5wcm90by5oaT1cXFxucHJvdG8udHJhbnNwb3NlPVxcXG5wcm90by5zdGVwPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9jb3B5KCkge1xcXG5yZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsdGhpcy5vZmZzZXQpXFxcbn07XFxcbnByb3RvLnBpY2s9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3BpY2soKXtcXFxucmV0dXJuIFRyaXZpYWxBcnJheSh0aGlzLmRhdGEpO1xcXG59O1xcXG5wcm90by52YWx1ZU9mPXByb3RvLmdldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfZ2V0KCl7XFxcbnJldHVybiBcIisodXNlR2V0dGVycyA/IFwidGhpcy5kYXRhLmdldCh0aGlzLm9mZnNldClcIiA6IFwidGhpcy5kYXRhW3RoaXMub2Zmc2V0XVwiKStcblwifTtcXFxucHJvdG8uc2V0PWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zZXQodil7XFxcbnJldHVybiBcIisodXNlR2V0dGVycyA/IFwidGhpcy5kYXRhLnNldCh0aGlzLm9mZnNldCx2KVwiIDogXCJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdPXZcIikrXCJcXFxufTtcXFxucmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoYSxiLGMsZCl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIoYSxkKX1cIlxuICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oXCJUcml2aWFsQXJyYXlcIiwgY29kZSlcbiAgICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdWzBdKVxuICB9XG5cbiAgdmFyIGNvZGUgPSBbXCIndXNlIHN0cmljdCdcIl1cblxuICAvL0NyZWF0ZSBjb25zdHJ1Y3RvciBmb3Igdmlld1xuICB2YXIgaW5kaWNlcyA9IGlvdGEoZGltZW5zaW9uKVxuICB2YXIgYXJncyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwiaVwiK2kgfSlcbiAgdmFyIGluZGV4X3N0ciA9IFwidGhpcy5vZmZzZXQrXCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICAgIHJldHVybiBcInRoaXMuc3RyaWRlW1wiICsgaSArIFwiXSppXCIgKyBpXG4gICAgICB9KS5qb2luKFwiK1wiKVxuICB2YXIgc2hhcGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpXG4gIHZhciBzdHJpZGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJjXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpXG4gIGNvZGUucHVzaChcbiAgICBcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIihhLFwiICsgc2hhcGVBcmcgKyBcIixcIiArIHN0cmlkZUFyZyArIFwiLGQpe3RoaXMuZGF0YT1hXCIsXG4gICAgICBcInRoaXMuc2hhcGU9W1wiICsgc2hhcGVBcmcgKyBcIl1cIixcbiAgICAgIFwidGhpcy5zdHJpZGU9W1wiICsgc3RyaWRlQXJnICsgXCJdXCIsXG4gICAgICBcInRoaXMub2Zmc2V0PWR8MH1cIixcbiAgICBcInZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlXCIsXG4gICAgXCJwcm90by5kdHlwZT0nXCIrZHR5cGUrXCInXCIsXG4gICAgXCJwcm90by5kaW1lbnNpb249XCIrZGltZW5zaW9uKVxuXG4gIC8vdmlldy5zaXplOlxuICBjb2RlLnB1c2goXCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ3NpemUnLHtnZXQ6ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3NpemUoKXtcXFxucmV0dXJuIFwiK2luZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwidGhpcy5zaGFwZVtcIitpK1wiXVwiIH0pLmpvaW4oXCIqXCIpLFxuXCJ9fSlcIilcblxuICAvL3ZpZXcub3JkZXI6XG4gIGlmKGRpbWVuc2lvbiA9PT0gMSkge1xuICAgIGNvZGUucHVzaChcInByb3RvLm9yZGVyPVswXVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnb3JkZXInLHtnZXQ6XCIpXG4gICAgaWYoZGltZW5zaW9uIDwgNCkge1xuICAgICAgY29kZS5wdXNoKFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX29yZGVyKCl7XCIpXG4gICAgICBpZihkaW1lbnNpb24gPT09IDIpIHtcbiAgICAgICAgY29kZS5wdXNoKFwicmV0dXJuIChNYXRoLmFicyh0aGlzLnN0cmlkZVswXSk+TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pKT9bMSwwXTpbMCwxXX19KVwiKVxuICAgICAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMykge1xuICAgICAgICBjb2RlLnB1c2goXG5cInZhciBzMD1NYXRoLmFicyh0aGlzLnN0cmlkZVswXSksczE9TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pLHMyPU1hdGguYWJzKHRoaXMuc3RyaWRlWzJdKTtcXFxuaWYoczA+czEpe1xcXG5pZihzMT5zMil7XFxcbnJldHVybiBbMiwxLDBdO1xcXG59ZWxzZSBpZihzMD5zMil7XFxcbnJldHVybiBbMSwyLDBdO1xcXG59ZWxzZXtcXFxucmV0dXJuIFsxLDAsMl07XFxcbn1cXFxufWVsc2UgaWYoczA+czIpe1xcXG5yZXR1cm4gWzIsMCwxXTtcXFxufWVsc2UgaWYoczI+czEpe1xcXG5yZXR1cm4gWzAsMSwyXTtcXFxufWVsc2V7XFxcbnJldHVybiBbMCwyLDFdO1xcXG59fX0pXCIpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChcIk9SREVSfSlcIilcbiAgICB9XG4gIH1cblxuICAvL3ZpZXcuc2V0KGkwLCAuLi4sIHYpOlxuICBjb2RlLnB1c2goXG5cInByb3RvLnNldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfc2V0KFwiK2FyZ3Muam9pbihcIixcIikrXCIsdil7XCIpXG4gIGlmKHVzZUdldHRlcnMpIHtcbiAgICBjb2RlLnB1c2goXCJyZXR1cm4gdGhpcy5kYXRhLnNldChcIitpbmRleF9zdHIrXCIsdil9XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YVtcIitpbmRleF9zdHIrXCJdPXZ9XCIpXG4gIH1cblxuICAvL3ZpZXcuZ2V0KGkwLCAuLi4pOlxuICBjb2RlLnB1c2goXCJwcm90by5nZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2dldChcIithcmdzLmpvaW4oXCIsXCIpK1wiKXtcIilcbiAgaWYodXNlR2V0dGVycykge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGEuZ2V0KFwiK2luZGV4X3N0citcIil9XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YVtcIitpbmRleF9zdHIrXCJdfVwiKVxuICB9XG5cbiAgLy92aWV3LmluZGV4OlxuICBjb2RlLnB1c2goXG4gICAgXCJwcm90by5pbmRleD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfaW5kZXgoXCIsIGFyZ3Muam9pbigpLCBcIil7cmV0dXJuIFwiK2luZGV4X3N0citcIn1cIilcblxuICAvL3ZpZXcuaGkoKTpcbiAgY29kZS5wdXNoKFwicHJvdG8uaGk9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2hpKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSxcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gW1wiKHR5cGVvZiBpXCIsaSxcIiE9PSdudW1iZXInfHxpXCIsaSxcIjwwKT90aGlzLnNoYXBlW1wiLCBpLCBcIl06aVwiLCBpLFwifDBcIl0uam9pbihcIlwiKVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInRoaXMuc3RyaWRlW1wiK2kgKyBcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLHRoaXMub2Zmc2V0KX1cIilcblxuICAvL3ZpZXcubG8oKTpcbiAgdmFyIGFfdmFycyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwiYVwiK2krXCI9dGhpcy5zaGFwZVtcIitpK1wiXVwiIH0pXG4gIHZhciBjX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImNcIitpK1wiPXRoaXMuc3RyaWRlW1wiK2krXCJdXCIgfSlcbiAgY29kZS5wdXNoKFwicHJvdG8ubG89ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2xvKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3ZhciBiPXRoaXMub2Zmc2V0LGQ9MCxcIithX3ZhcnMuam9pbihcIixcIikrXCIsXCIrY192YXJzLmpvaW4oXCIsXCIpKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcblwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicmJmlcIitpK1wiPj0wKXtcXFxuZD1pXCIraStcInwwO1xcXG5iKz1jXCIraStcIipkO1xcXG5hXCIraStcIi09ZH1cIilcbiAgfVxuICBjb2RlLnB1c2goXCJyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYVwiK2lcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJjXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLGIpfVwiKVxuXG4gIC8vdmlldy5zdGVwKCk6XG4gIGNvZGUucHVzaChcInByb3RvLnN0ZXA9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3N0ZXAoXCIrYXJncy5qb2luKFwiLFwiKStcIil7dmFyIFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIitpK1wiPXRoaXMuc2hhcGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImJcIitpK1wiPXRoaXMuc3RyaWRlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixjPXRoaXMub2Zmc2V0LGQ9MCxjZWlsPU1hdGguY2VpbFwiKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcblwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicpe1xcXG5kPWlcIitpK1wifDA7XFxcbmlmKGQ8MCl7XFxcbmMrPWJcIitpK1wiKihhXCIraStcIi0xKTtcXFxuYVwiK2krXCI9Y2VpbCgtYVwiK2krXCIvZClcXFxufWVsc2V7XFxcbmFcIitpK1wiPWNlaWwoYVwiK2krXCIvZClcXFxufVxcXG5iXCIraStcIio9ZFxcXG59XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwicmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIiArIGlcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIgKyBpXG4gICAgfSkuam9pbihcIixcIikrXCIsYyl9XCIpXG5cbiAgLy92aWV3LnRyYW5zcG9zZSgpOlxuICB2YXIgdFNoYXBlID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgdmFyIHRTdHJpZGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIHRTaGFwZVtpXSA9IFwiYVtpXCIraStcIl1cIlxuICAgIHRTdHJpZGVbaV0gPSBcImJbaVwiK2krXCJdXCJcbiAgfVxuICBjb2RlLnB1c2goXCJwcm90by50cmFuc3Bvc2U9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3RyYW5zcG9zZShcIithcmdzK1wiKXtcIitcbiAgICBhcmdzLm1hcChmdW5jdGlvbihuLGlkeCkgeyByZXR1cm4gbiArIFwiPShcIiArIG4gKyBcIj09PXVuZGVmaW5lZD9cIiArIGlkeCArIFwiOlwiICsgbiArIFwifDApXCJ9KS5qb2luKFwiO1wiKSxcbiAgICBcInZhciBhPXRoaXMuc2hhcGUsYj10aGlzLnN0cmlkZTtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrdFNoYXBlLmpvaW4oXCIsXCIpK1wiLFwiK3RTdHJpZGUuam9pbihcIixcIikrXCIsdGhpcy5vZmZzZXQpfVwiKVxuXG4gIC8vdmlldy5waWNrKCk6XG4gIGNvZGUucHVzaChcInByb3RvLnBpY2s9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3BpY2soXCIrYXJncytcIil7dmFyIGE9W10sYj1bXSxjPXRoaXMub2Zmc2V0XCIpXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgY29kZS5wdXNoKFwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicmJmlcIitpK1wiPj0wKXtjPShjK3RoaXMuc3RyaWRlW1wiK2krXCJdKmlcIitpK1wiKXwwfWVsc2V7YS5wdXNoKHRoaXMuc2hhcGVbXCIraStcIl0pO2IucHVzaCh0aGlzLnN0cmlkZVtcIitpK1wiXSl9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwidmFyIGN0b3I9Q1RPUl9MSVNUW2EubGVuZ3RoKzFdO3JldHVybiBjdG9yKHRoaXMuZGF0YSxhLGIsYyl9XCIpXG5cbiAgLy9BZGQgcmV0dXJuIHN0YXRlbWVudFxuICBjb2RlLnB1c2goXCJyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0X1wiK2NsYXNzTmFtZStcIihkYXRhLHNoYXBlLHN0cmlkZSxvZmZzZXQpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwic2hhcGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInN0cmlkZVtcIitpK1wiXVwiXG4gICAgfSkuam9pbihcIixcIikrXCIsb2Zmc2V0KX1cIilcblxuICAvL0NvbXBpbGUgcHJvY2VkdXJlXG4gIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oXCJDVE9SX0xJU1RcIiwgXCJPUkRFUlwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV0sIG9yZGVyKVxufVxuXG5mdW5jdGlvbiBhcnJheURUeXBlKGRhdGEpIHtcbiAgaWYoaXNCdWZmZXIoZGF0YSkpIHtcbiAgICByZXR1cm4gXCJidWZmZXJcIlxuICB9XG4gIGlmKGhhc1R5cGVkQXJyYXlzKSB7XG4gICAgc3dpdGNoKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSkge1xuICAgICAgY2FzZSBcIltvYmplY3QgRmxvYXQ2NEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJmbG9hdDY0XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEZsb2F0MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiZmxvYXQzMlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBJbnQ4QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDhcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50MTZBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiaW50MTZcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiaW50MzJcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDhBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDhcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDE2QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQxNlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBVaW50MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDMyXCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJ1aW50OF9jbGFtcGVkXCJcbiAgICB9XG4gIH1cbiAgaWYoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgIHJldHVybiBcImFycmF5XCJcbiAgfVxuICByZXR1cm4gXCJnZW5lcmljXCJcbn1cblxudmFyIENBQ0hFRF9DT05TVFJVQ1RPUlMgPSB7XG4gIFwiZmxvYXQzMlwiOltdLFxuICBcImZsb2F0NjRcIjpbXSxcbiAgXCJpbnQ4XCI6W10sXG4gIFwiaW50MTZcIjpbXSxcbiAgXCJpbnQzMlwiOltdLFxuICBcInVpbnQ4XCI6W10sXG4gIFwidWludDE2XCI6W10sXG4gIFwidWludDMyXCI6W10sXG4gIFwiYXJyYXlcIjpbXSxcbiAgXCJ1aW50OF9jbGFtcGVkXCI6W10sXG4gIFwiYnVmZmVyXCI6W10sXG4gIFwiZ2VuZXJpY1wiOltdXG59XG5cbjsoZnVuY3Rpb24oKSB7XG4gIGZvcih2YXIgaWQgaW4gQ0FDSEVEX0NPTlNUUlVDVE9SUykge1xuICAgIENBQ0hFRF9DT05TVFJVQ1RPUlNbaWRdLnB1c2goY29tcGlsZUNvbnN0cnVjdG9yKGlkLCAtMSkpXG4gIH1cbn0pO1xuXG5mdW5jdGlvbiB3cmFwcGVkTkRBcnJheUN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KSB7XG4gIGlmKGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBjdG9yID0gQ0FDSEVEX0NPTlNUUlVDVE9SUy5hcnJheVswXVxuICAgIHJldHVybiBjdG9yKFtdKVxuICB9IGVsc2UgaWYodHlwZW9mIGRhdGEgPT09IFwibnVtYmVyXCIpIHtcbiAgICBkYXRhID0gW2RhdGFdXG4gIH1cbiAgaWYoc2hhcGUgPT09IHVuZGVmaW5lZCkge1xuICAgIHNoYXBlID0gWyBkYXRhLmxlbmd0aCBdXG4gIH1cbiAgdmFyIGQgPSBzaGFwZS5sZW5ndGhcbiAgaWYoc3RyaWRlID09PSB1bmRlZmluZWQpIHtcbiAgICBzdHJpZGUgPSBuZXcgQXJyYXkoZClcbiAgICBmb3IodmFyIGk9ZC0xLCBzej0xOyBpPj0wOyAtLWkpIHtcbiAgICAgIHN0cmlkZVtpXSA9IHN6XG4gICAgICBzeiAqPSBzaGFwZVtpXVxuICAgIH1cbiAgfVxuICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIG9mZnNldCA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgIGlmKHN0cmlkZVtpXSA8IDApIHtcbiAgICAgICAgb2Zmc2V0IC09IChzaGFwZVtpXS0xKSpzdHJpZGVbaV1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIGR0eXBlID0gYXJyYXlEVHlwZShkYXRhKVxuICB2YXIgY3Rvcl9saXN0ID0gQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV1cbiAgd2hpbGUoY3Rvcl9saXN0Lmxlbmd0aCA8PSBkKzEpIHtcbiAgICBjdG9yX2xpc3QucHVzaChjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGN0b3JfbGlzdC5sZW5ndGgtMSkpXG4gIH1cbiAgdmFyIGN0b3IgPSBjdG9yX2xpc3RbZCsxXVxuICByZXR1cm4gY3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gd3JhcHBlZE5EQXJyYXlDdG9yXG4iLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgZG91YmxlQml0cyA9IHJlcXVpcmUoXCJkb3VibGUtYml0c1wiKVxuXG52YXIgU01BTExFU1RfREVOT1JNID0gTWF0aC5wb3coMiwgLTEwNzQpXG52YXIgVUlOVF9NQVggPSAoLTEpPj4+MFxuXG5tb2R1bGUuZXhwb3J0cyA9IG5leHRhZnRlclxuXG5mdW5jdGlvbiBuZXh0YWZ0ZXIoeCwgeSkge1xuICBpZihpc05hTih4KSB8fCBpc05hTih5KSkge1xuICAgIHJldHVybiBOYU5cbiAgfVxuICBpZih4ID09PSB5KSB7XG4gICAgcmV0dXJuIHhcbiAgfVxuICBpZih4ID09PSAwKSB7XG4gICAgaWYoeSA8IDApIHtcbiAgICAgIHJldHVybiAtU01BTExFU1RfREVOT1JNXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBTTUFMTEVTVF9ERU5PUk1cbiAgICB9XG4gIH1cbiAgdmFyIGhpID0gZG91YmxlQml0cy5oaSh4KVxuICB2YXIgbG8gPSBkb3VibGVCaXRzLmxvKHgpXG4gIGlmKCh5ID4geCkgPT09ICh4ID4gMCkpIHtcbiAgICBpZihsbyA9PT0gVUlOVF9NQVgpIHtcbiAgICAgIGhpICs9IDFcbiAgICAgIGxvID0gMFxuICAgIH0gZWxzZSB7XG4gICAgICBsbyArPSAxXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmKGxvID09PSAwKSB7XG4gICAgICBsbyA9IFVJTlRfTUFYXG4gICAgICBoaSAtPSAxXG4gICAgfSBlbHNlIHtcbiAgICAgIGxvIC09IDFcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRvdWJsZUJpdHMucGFjayhsbywgaGkpXG59IiwiXG52YXIgz4AgPSBNYXRoLlBJXG52YXIgXzEyMCA9IHJhZGlhbnMoMTIwKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5vcm1hbGl6ZVxuXG4vKipcbiAqIGRlc2NyaWJlIGBwYXRoYCBpbiB0ZXJtcyBvZiBjdWJpYyBiw6l6aWVyIFxuICogY3VydmVzIGFuZCBtb3ZlIGNvbW1hbmRzXG4gKlxuICogQHBhcmFtIHtBcnJheX0gcGF0aFxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cblxuZnVuY3Rpb24gbm9ybWFsaXplKHBhdGgpe1xuXHQvLyBpbml0IHN0YXRlXG5cdHZhciBwcmV2XG5cdHZhciByZXN1bHQgPSBbXVxuXHR2YXIgYmV6aWVyWCA9IDBcblx0dmFyIGJlemllclkgPSAwXG5cdHZhciBzdGFydFggPSAwXG5cdHZhciBzdGFydFkgPSAwXG5cdHZhciBxdWFkWCA9IG51bGxcblx0dmFyIHF1YWRZID0gbnVsbFxuXHR2YXIgeCA9IDBcblx0dmFyIHkgPSAwXG5cblx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHBhdGgubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHR2YXIgc2VnID0gcGF0aFtpXVxuXHRcdHZhciBjb21tYW5kID0gc2VnWzBdXG5cdFx0c3dpdGNoIChjb21tYW5kKSB7XG5cdFx0XHRjYXNlICdNJzpcblx0XHRcdFx0c3RhcnRYID0gc2VnWzFdXG5cdFx0XHRcdHN0YXJ0WSA9IHNlZ1syXVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnQSc6XG5cdFx0XHRcdHNlZyA9IGFyYyh4LCB5LHNlZ1sxXSxzZWdbMl0scmFkaWFucyhzZWdbM10pLHNlZ1s0XSxzZWdbNV0sc2VnWzZdLHNlZ1s3XSlcblx0XHRcdFx0Ly8gc3BsaXQgbXVsdGkgcGFydFxuXHRcdFx0XHRzZWcudW5zaGlmdCgnQycpXG5cdFx0XHRcdGlmIChzZWcubGVuZ3RoID4gNykge1xuXHRcdFx0XHRcdHJlc3VsdC5wdXNoKHNlZy5zcGxpY2UoMCwgNykpXG5cdFx0XHRcdFx0c2VnLnVuc2hpZnQoJ0MnKVxuXHRcdFx0XHR9XG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdTJzpcblx0XHRcdFx0Ly8gZGVmYXVsdCBjb250cm9sIHBvaW50XG5cdFx0XHRcdHZhciBjeCA9IHhcblx0XHRcdFx0dmFyIGN5ID0geVxuXHRcdFx0XHRpZiAocHJldiA9PSAnQycgfHwgcHJldiA9PSAnUycpIHtcblx0XHRcdFx0XHRjeCArPSBjeCAtIGJlemllclggLy8gcmVmbGVjdCB0aGUgcHJldmlvdXMgY29tbWFuZCdzIGNvbnRyb2xcblx0XHRcdFx0XHRjeSArPSBjeSAtIGJlemllclkgLy8gcG9pbnQgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgcG9pbnRcblx0XHRcdFx0fVxuXHRcdFx0XHRzZWcgPSBbJ0MnLCBjeCwgY3ksIHNlZ1sxXSwgc2VnWzJdLCBzZWdbM10sIHNlZ1s0XV1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ1QnOlxuXHRcdFx0XHRpZiAocHJldiA9PSAnUScgfHwgcHJldiA9PSAnVCcpIHtcblx0XHRcdFx0XHRxdWFkWCA9IHggKiAyIC0gcXVhZFggLy8gYXMgd2l0aCAnUycgcmVmbGVjdCBwcmV2aW91cyBjb250cm9sIHBvaW50XG5cdFx0XHRcdFx0cXVhZFkgPSB5ICogMiAtIHF1YWRZXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cXVhZFggPSB4XG5cdFx0XHRcdFx0cXVhZFkgPSB5XG5cdFx0XHRcdH1cblx0XHRcdFx0c2VnID0gcXVhZHJhdGljKHgsIHksIHF1YWRYLCBxdWFkWSwgc2VnWzFdLCBzZWdbMl0pXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdRJzpcblx0XHRcdFx0cXVhZFggPSBzZWdbMV1cblx0XHRcdFx0cXVhZFkgPSBzZWdbMl1cblx0XHRcdFx0c2VnID0gcXVhZHJhdGljKHgsIHksIHNlZ1sxXSwgc2VnWzJdLCBzZWdbM10sIHNlZ1s0XSlcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ0wnOlxuXHRcdFx0XHRzZWcgPSBsaW5lKHgsIHksIHNlZ1sxXSwgc2VnWzJdKVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnSCc6XG5cdFx0XHRcdHNlZyA9IGxpbmUoeCwgeSwgc2VnWzFdLCB5KVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnVic6XG5cdFx0XHRcdHNlZyA9IGxpbmUoeCwgeSwgeCwgc2VnWzFdKVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnWic6XG5cdFx0XHRcdHNlZyA9IGxpbmUoeCwgeSwgc3RhcnRYLCBzdGFydFkpXG5cdFx0XHRcdGJyZWFrXG5cdFx0fVxuXG5cdFx0Ly8gdXBkYXRlIHN0YXRlXG5cdFx0cHJldiA9IGNvbW1hbmRcblx0XHR4ID0gc2VnW3NlZy5sZW5ndGggLSAyXVxuXHRcdHkgPSBzZWdbc2VnLmxlbmd0aCAtIDFdXG5cdFx0aWYgKHNlZy5sZW5ndGggPiA0KSB7XG5cdFx0XHRiZXppZXJYID0gc2VnW3NlZy5sZW5ndGggLSA0XVxuXHRcdFx0YmV6aWVyWSA9IHNlZ1tzZWcubGVuZ3RoIC0gM11cblx0XHR9IGVsc2Uge1xuXHRcdFx0YmV6aWVyWCA9IHhcblx0XHRcdGJlemllclkgPSB5XG5cdFx0fVxuXHRcdHJlc3VsdC5wdXNoKHNlZylcblx0fVxuXG5cdHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gbGluZSh4MSwgeTEsIHgyLCB5Mil7XG5cdHJldHVybiBbJ0MnLCB4MSwgeTEsIHgyLCB5MiwgeDIsIHkyXVxufVxuXG5mdW5jdGlvbiBxdWFkcmF0aWMoeDEsIHkxLCBjeCwgY3ksIHgyLCB5Mil7XG5cdHJldHVybiBbXG5cdFx0J0MnLFxuXHRcdHgxLzMgKyAoMi8zKSAqIGN4LFxuXHRcdHkxLzMgKyAoMi8zKSAqIGN5LFxuXHRcdHgyLzMgKyAoMi8zKSAqIGN4LFxuXHRcdHkyLzMgKyAoMi8zKSAqIGN5LFxuXHRcdHgyLFxuXHRcdHkyXG5cdF1cbn1cblxuLy8gVGhpcyBmdW5jdGlvbiBpcyByaXBwZWQgZnJvbSBcbi8vIGdpdGh1Yi5jb20vRG1pdHJ5QmFyYW5vdnNraXkvcmFwaGFlbC9ibG9iLzRkOTdkNC9yYXBoYWVsLmpzI0wyMjE2LUwyMzA0IFxuLy8gd2hpY2ggcmVmZXJlbmNlcyB3My5vcmcvVFIvU1ZHMTEvaW1wbG5vdGUuaHRtbCNBcmNJbXBsZW1lbnRhdGlvbk5vdGVzXG4vLyBUT0RPOiBtYWtlIGl0IGh1bWFuIHJlYWRhYmxlXG5cbmZ1bmN0aW9uIGFyYyh4MSwgeTEsIHJ4LCByeSwgYW5nbGUsIGxhcmdlX2FyY19mbGFnLCBzd2VlcF9mbGFnLCB4MiwgeTIsIHJlY3Vyc2l2ZSkge1xuXHRpZiAoIXJlY3Vyc2l2ZSkge1xuXHRcdHZhciB4eSA9IHJvdGF0ZSh4MSwgeTEsIC1hbmdsZSlcblx0XHR4MSA9IHh5Lnhcblx0XHR5MSA9IHh5Lnlcblx0XHR4eSA9IHJvdGF0ZSh4MiwgeTIsIC1hbmdsZSlcblx0XHR4MiA9IHh5Lnhcblx0XHR5MiA9IHh5Lnlcblx0XHR2YXIgeCA9ICh4MSAtIHgyKSAvIDJcblx0XHR2YXIgeSA9ICh5MSAtIHkyKSAvIDJcblx0XHR2YXIgaCA9ICh4ICogeCkgLyAocnggKiByeCkgKyAoeSAqIHkpIC8gKHJ5ICogcnkpXG5cdFx0aWYgKGggPiAxKSB7XG5cdFx0XHRoID0gTWF0aC5zcXJ0KGgpXG5cdFx0XHRyeCA9IGggKiByeFxuXHRcdFx0cnkgPSBoICogcnlcblx0XHR9XG5cdFx0dmFyIHJ4MiA9IHJ4ICogcnhcblx0XHR2YXIgcnkyID0gcnkgKiByeVxuXHRcdHZhciBrID0gKGxhcmdlX2FyY19mbGFnID09IHN3ZWVwX2ZsYWcgPyAtMSA6IDEpXG5cdFx0XHQqIE1hdGguc3FydChNYXRoLmFicygocngyICogcnkyIC0gcngyICogeSAqIHkgLSByeTIgKiB4ICogeCkgLyAocngyICogeSAqIHkgKyByeTIgKiB4ICogeCkpKVxuXHRcdGlmIChrID09IEluZmluaXR5KSBrID0gMSAvLyBuZXV0cmFsaXplXG5cdFx0dmFyIGN4ID0gayAqIHJ4ICogeSAvIHJ5ICsgKHgxICsgeDIpIC8gMlxuXHRcdHZhciBjeSA9IGsgKiAtcnkgKiB4IC8gcnggKyAoeTEgKyB5MikgLyAyXG5cdFx0dmFyIGYxID0gTWF0aC5hc2luKCgoeTEgLSBjeSkgLyByeSkudG9GaXhlZCg5KSlcblx0XHR2YXIgZjIgPSBNYXRoLmFzaW4oKCh5MiAtIGN5KSAvIHJ5KS50b0ZpeGVkKDkpKVxuXG5cdFx0ZjEgPSB4MSA8IGN4ID8gz4AgLSBmMSA6IGYxXG5cdFx0ZjIgPSB4MiA8IGN4ID8gz4AgLSBmMiA6IGYyXG5cdFx0aWYgKGYxIDwgMCkgZjEgPSDPgCAqIDIgKyBmMVxuXHRcdGlmIChmMiA8IDApIGYyID0gz4AgKiAyICsgZjJcblx0XHRpZiAoc3dlZXBfZmxhZyAmJiBmMSA+IGYyKSBmMSA9IGYxIC0gz4AgKiAyXG5cdFx0aWYgKCFzd2VlcF9mbGFnICYmIGYyID4gZjEpIGYyID0gZjIgLSDPgCAqIDJcblx0fSBlbHNlIHtcblx0XHRmMSA9IHJlY3Vyc2l2ZVswXVxuXHRcdGYyID0gcmVjdXJzaXZlWzFdXG5cdFx0Y3ggPSByZWN1cnNpdmVbMl1cblx0XHRjeSA9IHJlY3Vyc2l2ZVszXVxuXHR9XG5cdC8vIGdyZWF0ZXIgdGhhbiAxMjAgZGVncmVlcyByZXF1aXJlcyBtdWx0aXBsZSBzZWdtZW50c1xuXHRpZiAoTWF0aC5hYnMoZjIgLSBmMSkgPiBfMTIwKSB7XG5cdFx0dmFyIGYyb2xkID0gZjJcblx0XHR2YXIgeDJvbGQgPSB4MlxuXHRcdHZhciB5Mm9sZCA9IHkyXG5cdFx0ZjIgPSBmMSArIF8xMjAgKiAoc3dlZXBfZmxhZyAmJiBmMiA+IGYxID8gMSA6IC0xKVxuXHRcdHgyID0gY3ggKyByeCAqIE1hdGguY29zKGYyKVxuXHRcdHkyID0gY3kgKyByeSAqIE1hdGguc2luKGYyKVxuXHRcdHZhciByZXMgPSBhcmMoeDIsIHkyLCByeCwgcnksIGFuZ2xlLCAwLCBzd2VlcF9mbGFnLCB4Mm9sZCwgeTJvbGQsIFtmMiwgZjJvbGQsIGN4LCBjeV0pXG5cdH1cblx0dmFyIHQgPSBNYXRoLnRhbigoZjIgLSBmMSkgLyA0KVxuXHR2YXIgaHggPSA0IC8gMyAqIHJ4ICogdFxuXHR2YXIgaHkgPSA0IC8gMyAqIHJ5ICogdFxuXHR2YXIgY3VydmUgPSBbXG5cdFx0MiAqIHgxIC0gKHgxICsgaHggKiBNYXRoLnNpbihmMSkpLFxuXHRcdDIgKiB5MSAtICh5MSAtIGh5ICogTWF0aC5jb3MoZjEpKSxcblx0XHR4MiArIGh4ICogTWF0aC5zaW4oZjIpLFxuXHRcdHkyIC0gaHkgKiBNYXRoLmNvcyhmMiksXG5cdFx0eDIsXG5cdFx0eTJcblx0XVxuXHRpZiAocmVjdXJzaXZlKSByZXR1cm4gY3VydmVcblx0aWYgKHJlcykgY3VydmUgPSBjdXJ2ZS5jb25jYXQocmVzKVxuXHRmb3IgKHZhciBpID0gMDsgaSA8IGN1cnZlLmxlbmd0aDspIHtcblx0XHR2YXIgcm90ID0gcm90YXRlKGN1cnZlW2ldLCBjdXJ2ZVtpKzFdLCBhbmdsZSlcblx0XHRjdXJ2ZVtpKytdID0gcm90Lnhcblx0XHRjdXJ2ZVtpKytdID0gcm90Lnlcblx0fVxuXHRyZXR1cm4gY3VydmVcbn1cblxuZnVuY3Rpb24gcm90YXRlKHgsIHksIHJhZCl7XG5cdHJldHVybiB7XG5cdFx0eDogeCAqIE1hdGguY29zKHJhZCkgLSB5ICogTWF0aC5zaW4ocmFkKSxcblx0XHR5OiB4ICogTWF0aC5zaW4ocmFkKSArIHkgKiBNYXRoLmNvcyhyYWQpXG5cdH1cbn1cblxuZnVuY3Rpb24gcmFkaWFucyhkZWdyZXNzKXtcblx0cmV0dXJuIGRlZ3Jlc3MgKiAoz4AgLyAxODApXG59XG4iLCJ2YXIgREVGQVVMVF9OT1JNQUxTX0VQU0lMT04gPSAxZS02O1xudmFyIERFRkFVTFRfRkFDRV9FUFNJTE9OID0gMWUtNjtcblxuLy9Fc3RpbWF0ZSB0aGUgdmVydGV4IG5vcm1hbHMgb2YgYSBtZXNoXG5leHBvcnRzLnZlcnRleE5vcm1hbHMgPSBmdW5jdGlvbihmYWNlcywgcG9zaXRpb25zLCBzcGVjaWZpZWRFcHNpbG9uKSB7XG5cbiAgdmFyIE4gICAgICAgICA9IHBvc2l0aW9ucy5sZW5ndGg7XG4gIHZhciBub3JtYWxzICAgPSBuZXcgQXJyYXkoTik7XG4gIHZhciBlcHNpbG9uICAgPSBzcGVjaWZpZWRFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9OT1JNQUxTX0VQU0lMT04gOiBzcGVjaWZpZWRFcHNpbG9uO1xuXG4gIC8vSW5pdGlhbGl6ZSBub3JtYWwgYXJyYXlcbiAgZm9yKHZhciBpPTA7IGk8TjsgKytpKSB7XG4gICAgbm9ybWFsc1tpXSA9IFswLjAsIDAuMCwgMC4wXTtcbiAgfVxuXG4gIC8vV2FsayBvdmVyIGFsbCB0aGUgZmFjZXMgYW5kIGFkZCBwZXItdmVydGV4IGNvbnRyaWJ1dGlvbiB0byBub3JtYWwgd2VpZ2h0c1xuICBmb3IodmFyIGk9MDsgaTxmYWNlcy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBmID0gZmFjZXNbaV07XG4gICAgdmFyIHAgPSAwO1xuICAgIHZhciBjID0gZltmLmxlbmd0aC0xXTtcbiAgICB2YXIgbiA9IGZbMF07XG4gICAgZm9yKHZhciBqPTA7IGo8Zi5sZW5ndGg7ICsraikge1xuXG4gICAgICAvL1NoaWZ0IGluZGljZXMgYmFja1xuICAgICAgcCA9IGM7XG4gICAgICBjID0gbjtcbiAgICAgIG4gPSBmWyhqKzEpICUgZi5sZW5ndGhdO1xuXG4gICAgICB2YXIgdjAgPSBwb3NpdGlvbnNbcF07XG4gICAgICB2YXIgdjEgPSBwb3NpdGlvbnNbY107XG4gICAgICB2YXIgdjIgPSBwb3NpdGlvbnNbbl07XG5cbiAgICAgIC8vQ29tcHV0ZSBpbmZpbmV0ZWlzbWFsIGFyY3NcbiAgICAgIHZhciBkMDEgPSBuZXcgQXJyYXkoMyk7XG4gICAgICB2YXIgbTAxID0gMC4wO1xuICAgICAgdmFyIGQyMSA9IG5ldyBBcnJheSgzKTtcbiAgICAgIHZhciBtMjEgPSAwLjA7XG4gICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgZDAxW2tdID0gdjBba10gIC0gdjFba107XG4gICAgICAgIG0wMSAgICs9IGQwMVtrXSAqIGQwMVtrXTtcbiAgICAgICAgZDIxW2tdID0gdjJba10gIC0gdjFba107XG4gICAgICAgIG0yMSAgICs9IGQyMVtrXSAqIGQyMVtrXTtcbiAgICAgIH1cblxuICAgICAgLy9BY2N1bXVsYXRlIHZhbHVlcyBpbiBub3JtYWxcbiAgICAgIGlmKG0wMSAqIG0yMSA+IGVwc2lsb24pIHtcbiAgICAgICAgdmFyIG5vcm0gPSBub3JtYWxzW2NdO1xuICAgICAgICB2YXIgdyA9IDEuMCAvIE1hdGguc3FydChtMDEgKiBtMjEpO1xuICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgICB2YXIgdSA9IChrKzEpJTM7XG4gICAgICAgICAgdmFyIHYgPSAoaysyKSUzO1xuICAgICAgICAgIG5vcm1ba10gKz0gdyAqIChkMjFbdV0gKiBkMDFbdl0gLSBkMjFbdl0gKiBkMDFbdV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9TY2FsZSBhbGwgbm9ybWFscyB0byB1bml0IGxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxOOyArK2kpIHtcbiAgICB2YXIgbm9ybSA9IG5vcm1hbHNbaV07XG4gICAgdmFyIG0gPSAwLjA7XG4gICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XG4gICAgICBtICs9IG5vcm1ba10gKiBub3JtW2tdO1xuICAgIH1cbiAgICBpZihtID4gZXBzaWxvbikge1xuICAgICAgdmFyIHcgPSAxLjAgLyBNYXRoLnNxcnQobSk7XG4gICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgbm9ybVtrXSAqPSB3O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgbm9ybVtrXSA9IDAuMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL1JldHVybiB0aGUgcmVzdWx0aW5nIHNldCBvZiBwYXRjaGVzXG4gIHJldHVybiBub3JtYWxzO1xufVxuXG4vL0NvbXB1dGUgZmFjZSBub3JtYWxzIG9mIGEgbWVzaFxuZXhwb3J0cy5mYWNlTm9ybWFscyA9IGZ1bmN0aW9uKGZhY2VzLCBwb3NpdGlvbnMsIHNwZWNpZmllZEVwc2lsb24pIHtcblxuICB2YXIgTiAgICAgICAgID0gZmFjZXMubGVuZ3RoO1xuICB2YXIgbm9ybWFscyAgID0gbmV3IEFycmF5KE4pO1xuICB2YXIgZXBzaWxvbiAgID0gc3BlY2lmaWVkRXBzaWxvbiA9PT0gdm9pZCgwKSA/IERFRkFVTFRfRkFDRV9FUFNJTE9OIDogc3BlY2lmaWVkRXBzaWxvbjtcblxuICBmb3IodmFyIGk9MDsgaTxOOyArK2kpIHtcbiAgICB2YXIgZiA9IGZhY2VzW2ldO1xuICAgIHZhciBwb3MgPSBuZXcgQXJyYXkoMyk7XG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICBwb3Nbal0gPSBwb3NpdGlvbnNbZltqXV07XG4gICAgfVxuXG4gICAgdmFyIGQwMSA9IG5ldyBBcnJheSgzKTtcbiAgICB2YXIgZDIxID0gbmV3IEFycmF5KDMpO1xuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgZDAxW2pdID0gcG9zWzFdW2pdIC0gcG9zWzBdW2pdO1xuICAgICAgZDIxW2pdID0gcG9zWzJdW2pdIC0gcG9zWzBdW2pdO1xuICAgIH1cblxuICAgIHZhciBuID0gbmV3IEFycmF5KDMpO1xuICAgIHZhciBsID0gMC4wO1xuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgdmFyIHUgPSAoaisxKSUzO1xuICAgICAgdmFyIHYgPSAoaisyKSUzO1xuICAgICAgbltqXSA9IGQwMVt1XSAqIGQyMVt2XSAtIGQwMVt2XSAqIGQyMVt1XTtcbiAgICAgIGwgKz0gbltqXSAqIG5bal07XG4gICAgfVxuICAgIGlmKGwgPiBlcHNpbG9uKSB7XG4gICAgICBsID0gMS4wIC8gTWF0aC5zcXJ0KGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsID0gMC4wO1xuICAgIH1cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIG5bal0gKj0gbDtcbiAgICB9XG4gICAgbm9ybWFsc1tpXSA9IG47XG4gIH1cbiAgcmV0dXJuIG5vcm1hbHM7XG59XG5cblxuIiwiLypcbm9iamVjdC1hc3NpZ25cbihjKSBTaW5kcmUgU29yaHVzXG5AbGljZW5zZSBNSVRcbiovXG5cbid1c2Ugc3RyaWN0Jztcbi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG52YXIgZ2V0T3duUHJvcGVydHlTeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcbnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG52YXIgcHJvcElzRW51bWVyYWJsZSA9IE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGU7XG5cbmZ1bmN0aW9uIHRvT2JqZWN0KHZhbCkge1xuXHRpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0dGhyb3cgbmV3IFR5cGVFcnJvcignT2JqZWN0LmFzc2lnbiBjYW5ub3QgYmUgY2FsbGVkIHdpdGggbnVsbCBvciB1bmRlZmluZWQnKTtcblx0fVxuXG5cdHJldHVybiBPYmplY3QodmFsKTtcbn1cblxuZnVuY3Rpb24gc2hvdWxkVXNlTmF0aXZlKCkge1xuXHR0cnkge1xuXHRcdGlmICghT2JqZWN0LmFzc2lnbikge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIERldGVjdCBidWdneSBwcm9wZXJ0eSBlbnVtZXJhdGlvbiBvcmRlciBpbiBvbGRlciBWOCB2ZXJzaW9ucy5cblxuXHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTQxMThcblx0XHR2YXIgdGVzdDEgPSBuZXcgU3RyaW5nKCdhYmMnKTsgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tbmV3LXdyYXBwZXJzXG5cdFx0dGVzdDFbNV0gPSAnZGUnO1xuXHRcdGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0ZXN0MSlbMF0gPT09ICc1Jykge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMwNTZcblx0XHR2YXIgdGVzdDIgPSB7fTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IDEwOyBpKyspIHtcblx0XHRcdHRlc3QyWydfJyArIFN0cmluZy5mcm9tQ2hhckNvZGUoaSldID0gaTtcblx0XHR9XG5cdFx0dmFyIG9yZGVyMiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRlc3QyKS5tYXAoZnVuY3Rpb24gKG4pIHtcblx0XHRcdHJldHVybiB0ZXN0MltuXTtcblx0XHR9KTtcblx0XHRpZiAob3JkZXIyLmpvaW4oJycpICE9PSAnMDEyMzQ1Njc4OScpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0zMDU2XG5cdFx0dmFyIHRlc3QzID0ge307XG5cdFx0J2FiY2RlZmdoaWprbG1ub3BxcnN0Jy5zcGxpdCgnJykuZm9yRWFjaChmdW5jdGlvbiAobGV0dGVyKSB7XG5cdFx0XHR0ZXN0M1tsZXR0ZXJdID0gbGV0dGVyO1xuXHRcdH0pO1xuXHRcdGlmIChPYmplY3Qua2V5cyhPYmplY3QuYXNzaWduKHt9LCB0ZXN0MykpLmpvaW4oJycpICE9PVxuXHRcdFx0XHQnYWJjZGVmZ2hpamtsbW5vcHFyc3QnKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH0gY2F0Y2ggKGVycikge1xuXHRcdC8vIFdlIGRvbid0IGV4cGVjdCBhbnkgb2YgdGhlIGFib3ZlIHRvIHRocm93LCBidXQgYmV0dGVyIHRvIGJlIHNhZmUuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2hvdWxkVXNlTmF0aXZlKCkgPyBPYmplY3QuYXNzaWduIDogZnVuY3Rpb24gKHRhcmdldCwgc291cmNlKSB7XG5cdHZhciBmcm9tO1xuXHR2YXIgdG8gPSB0b09iamVjdCh0YXJnZXQpO1xuXHR2YXIgc3ltYm9scztcblxuXHRmb3IgKHZhciBzID0gMTsgcyA8IGFyZ3VtZW50cy5sZW5ndGg7IHMrKykge1xuXHRcdGZyb20gPSBPYmplY3QoYXJndW1lbnRzW3NdKTtcblxuXHRcdGZvciAodmFyIGtleSBpbiBmcm9tKSB7XG5cdFx0XHRpZiAoaGFzT3duUHJvcGVydHkuY2FsbChmcm9tLCBrZXkpKSB7XG5cdFx0XHRcdHRvW2tleV0gPSBmcm9tW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGdldE93blByb3BlcnR5U3ltYm9scykge1xuXHRcdFx0c3ltYm9scyA9IGdldE93blByb3BlcnR5U3ltYm9scyhmcm9tKTtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgc3ltYm9scy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRpZiAocHJvcElzRW51bWVyYWJsZS5jYWxsKGZyb20sIHN5bWJvbHNbaV0pKSB7XG5cdFx0XHRcdFx0dG9bc3ltYm9sc1tpXV0gPSBmcm9tW3N5bWJvbHNbaV1dO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHRvO1xufTtcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHF1YXRGcm9tRnJhbWVcblxuZnVuY3Rpb24gcXVhdEZyb21GcmFtZShcbiAgb3V0LFxuICByeCwgcnksIHJ6LFxuICB1eCwgdXksIHV6LFxuICBmeCwgZnksIGZ6KSB7XG4gIHZhciB0ciA9IHJ4ICsgdXkgKyBmelxuICBpZihsID4gMCkge1xuICAgIHZhciBsID0gTWF0aC5zcXJ0KHRyICsgMS4wKVxuICAgIG91dFswXSA9IDAuNSAqICh1eiAtIGZ5KSAvIGxcbiAgICBvdXRbMV0gPSAwLjUgKiAoZnggLSByeikgLyBsXG4gICAgb3V0WzJdID0gMC41ICogKHJ5IC0gdXkpIC8gbFxuICAgIG91dFszXSA9IDAuNSAqIGxcbiAgfSBlbHNlIHtcbiAgICB2YXIgdGYgPSBNYXRoLm1heChyeCwgdXksIGZ6KVxuICAgIHZhciBsID0gTWF0aC5zcXJ0KDIgKiB0ZiAtIHRyICsgMS4wKVxuICAgIGlmKHJ4ID49IHRmKSB7XG4gICAgICAvL3ggeSB6ICBvcmRlclxuICAgICAgb3V0WzBdID0gMC41ICogbFxuICAgICAgb3V0WzFdID0gMC41ICogKHV4ICsgcnkpIC8gbFxuICAgICAgb3V0WzJdID0gMC41ICogKGZ4ICsgcnopIC8gbFxuICAgICAgb3V0WzNdID0gMC41ICogKHV6IC0gZnkpIC8gbFxuICAgIH0gZWxzZSBpZih1eSA+PSB0Zikge1xuICAgICAgLy95IHogeCAgb3JkZXJcbiAgICAgIG91dFswXSA9IDAuNSAqIChyeSArIHV4KSAvIGxcbiAgICAgIG91dFsxXSA9IDAuNSAqIGxcbiAgICAgIG91dFsyXSA9IDAuNSAqIChmeSArIHV6KSAvIGxcbiAgICAgIG91dFszXSA9IDAuNSAqIChmeCAtIHJ6KSAvIGxcbiAgICB9IGVsc2Uge1xuICAgICAgLy96IHggeSAgb3JkZXJcbiAgICAgIG91dFswXSA9IDAuNSAqIChyeiArIGZ4KSAvIGxcbiAgICAgIG91dFsxXSA9IDAuNSAqICh1eiArIGZ5KSAvIGxcbiAgICAgIG91dFsyXSA9IDAuNSAqIGxcbiAgICAgIG91dFszXSA9IDAuNSAqIChyeSAtIHV4KSAvIGxcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dFxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZU9yYml0Q29udHJvbGxlclxuXG52YXIgZmlsdGVyVmVjdG9yICA9IHJlcXVpcmUoJ2ZpbHRlcmVkLXZlY3RvcicpXG52YXIgbG9va0F0ICAgICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvbG9va0F0JylcbnZhciBtYXQ0RnJvbVF1YXQgID0gcmVxdWlyZSgnZ2wtbWF0NC9mcm9tUXVhdCcpXG52YXIgaW52ZXJ0NDQgICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvaW52ZXJ0JylcbnZhciBxdWF0RnJvbUZyYW1lID0gcmVxdWlyZSgnLi9saWIvcXVhdEZyb21GcmFtZScpXG5cbmZ1bmN0aW9uIGxlbjMoeCx5LHopIHtcbiAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyh4LDIpICsgTWF0aC5wb3coeSwyKSArIE1hdGgucG93KHosMikpXG59XG5cbmZ1bmN0aW9uIGxlbjQodyx4LHkseikge1xuICByZXR1cm4gTWF0aC5zcXJ0KE1hdGgucG93KHcsMikgKyBNYXRoLnBvdyh4LDIpICsgTWF0aC5wb3coeSwyKSArIE1hdGgucG93KHosMikpXG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZTQob3V0LCBhKSB7XG4gIHZhciBheCA9IGFbMF1cbiAgdmFyIGF5ID0gYVsxXVxuICB2YXIgYXogPSBhWzJdXG4gIHZhciBhdyA9IGFbM11cbiAgdmFyIGFsID0gbGVuNChheCwgYXksIGF6LCBhdylcbiAgaWYoYWwgPiAxZS02KSB7XG4gICAgb3V0WzBdID0gYXgvYWxcbiAgICBvdXRbMV0gPSBheS9hbFxuICAgIG91dFsyXSA9IGF6L2FsXG4gICAgb3V0WzNdID0gYXcvYWxcbiAgfSBlbHNlIHtcbiAgICBvdXRbMF0gPSBvdXRbMV0gPSBvdXRbMl0gPSAwLjBcbiAgICBvdXRbM10gPSAxLjBcbiAgfVxufVxuXG5mdW5jdGlvbiBPcmJpdENhbWVyYUNvbnRyb2xsZXIoaW5pdFF1YXQsIGluaXRDZW50ZXIsIGluaXRSYWRpdXMpIHtcbiAgdGhpcy5yYWRpdXMgICAgPSBmaWx0ZXJWZWN0b3IoW2luaXRSYWRpdXNdKVxuICB0aGlzLmNlbnRlciAgICA9IGZpbHRlclZlY3Rvcihpbml0Q2VudGVyKVxuICB0aGlzLnJvdGF0aW9uICA9IGZpbHRlclZlY3Rvcihpbml0UXVhdClcblxuICB0aGlzLmNvbXB1dGVkUmFkaXVzICAgPSB0aGlzLnJhZGl1cy5jdXJ2ZSgwKVxuICB0aGlzLmNvbXB1dGVkQ2VudGVyICAgPSB0aGlzLmNlbnRlci5jdXJ2ZSgwKVxuICB0aGlzLmNvbXB1dGVkUm90YXRpb24gPSB0aGlzLnJvdGF0aW9uLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRVcCAgICAgICA9IFswLjEsMCwwXVxuICB0aGlzLmNvbXB1dGVkRXllICAgICAgPSBbMC4xLDAsMF1cbiAgdGhpcy5jb21wdXRlZE1hdHJpeCAgID0gWzAuMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1cblxuICB0aGlzLnJlY2FsY01hdHJpeCgwKVxufVxuXG52YXIgcHJvdG8gPSBPcmJpdENhbWVyYUNvbnRyb2xsZXIucHJvdG90eXBlXG5cbnByb3RvLmxhc3RUID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLm1heChcbiAgICB0aGlzLnJhZGl1cy5sYXN0VCgpLFxuICAgIHRoaXMuY2VudGVyLmxhc3RUKCksXG4gICAgdGhpcy5yb3RhdGlvbi5sYXN0VCgpKVxufVxuXG5wcm90by5yZWNhbGNNYXRyaXggPSBmdW5jdGlvbih0KSB7XG4gIHRoaXMucmFkaXVzLmN1cnZlKHQpXG4gIHRoaXMuY2VudGVyLmN1cnZlKHQpXG4gIHRoaXMucm90YXRpb24uY3VydmUodClcblxuICB2YXIgcXVhdCA9IHRoaXMuY29tcHV0ZWRSb3RhdGlvblxuICBub3JtYWxpemU0KHF1YXQsIHF1YXQpXG5cbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgbWF0NEZyb21RdWF0KG1hdCwgcXVhdClcblxuICB2YXIgY2VudGVyID0gdGhpcy5jb21wdXRlZENlbnRlclxuICB2YXIgZXllICAgID0gdGhpcy5jb21wdXRlZEV5ZVxuICB2YXIgdXAgICAgID0gdGhpcy5jb21wdXRlZFVwXG4gIHZhciByYWRpdXMgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxuXG4gIGV5ZVswXSA9IGNlbnRlclswXSArIHJhZGl1cyAqIG1hdFsyXVxuICBleWVbMV0gPSBjZW50ZXJbMV0gKyByYWRpdXMgKiBtYXRbNl1cbiAgZXllWzJdID0gY2VudGVyWzJdICsgcmFkaXVzICogbWF0WzEwXVxuICB1cFswXSA9IG1hdFsxXVxuICB1cFsxXSA9IG1hdFs1XVxuICB1cFsyXSA9IG1hdFs5XVxuXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciByciA9IDAuMFxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcnIgKz0gbWF0W2krNCpqXSAqIGV5ZVtqXVxuICAgIH1cbiAgICBtYXRbMTIraV0gPSAtcnJcbiAgfVxufVxuXG5wcm90by5nZXRNYXRyaXggPSBmdW5jdGlvbih0LCByZXN1bHQpIHtcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcbiAgdmFyIG0gPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIGlmKHJlc3VsdCkge1xuICAgIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcbiAgICAgIHJlc3VsdFtpXSA9IG1baV1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG4gIHJldHVybiBtXG59XG5cbnByb3RvLmlkbGUgPSBmdW5jdGlvbih0KSB7XG4gIHRoaXMuY2VudGVyLmlkbGUodClcbiAgdGhpcy5yYWRpdXMuaWRsZSh0KVxuICB0aGlzLnJvdGF0aW9uLmlkbGUodClcbn1cblxucHJvdG8uZmx1c2ggPSBmdW5jdGlvbih0KSB7XG4gIHRoaXMuY2VudGVyLmZsdXNoKHQpXG4gIHRoaXMucmFkaXVzLmZsdXNoKHQpXG4gIHRoaXMucm90YXRpb24uZmx1c2godClcbn1cblxucHJvdG8ucGFuID0gZnVuY3Rpb24odCwgZHgsIGR5LCBkeikge1xuICBkeCA9IGR4IHx8IDAuMFxuICBkeSA9IGR5IHx8IDAuMFxuICBkeiA9IGR6IHx8IDAuMFxuXG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG5cbiAgdmFyIHV4ID0gbWF0WzFdXG4gIHZhciB1eSA9IG1hdFs1XVxuICB2YXIgdXogPSBtYXRbOV1cbiAgdmFyIHVsID0gbGVuMyh1eCwgdXksIHV6KVxuICB1eCAvPSB1bFxuICB1eSAvPSB1bFxuICB1eiAvPSB1bFxuXG4gIHZhciByeCA9IG1hdFswXVxuICB2YXIgcnkgPSBtYXRbNF1cbiAgdmFyIHJ6ID0gbWF0WzhdXG4gIHZhciBydSA9IHJ4ICogdXggKyByeSAqIHV5ICsgcnogKiB1elxuICByeCAtPSB1eCAqIHJ1XG4gIHJ5IC09IHV5ICogcnVcbiAgcnogLT0gdXogKiBydVxuICB2YXIgcmwgPSBsZW4zKHJ4LCByeSwgcnopXG4gIHJ4IC89IHJsXG4gIHJ5IC89IHJsXG4gIHJ6IC89IHJsXG5cbiAgdmFyIGZ4ID0gbWF0WzJdXG4gIHZhciBmeSA9IG1hdFs2XVxuICB2YXIgZnogPSBtYXRbMTBdXG4gIHZhciBmdSA9IGZ4ICogdXggKyBmeSAqIHV5ICsgZnogKiB1elxuICB2YXIgZnIgPSBmeCAqIHJ4ICsgZnkgKiByeSArIGZ6ICogcnpcbiAgZnggLT0gZnUgKiB1eCArIGZyICogcnhcbiAgZnkgLT0gZnUgKiB1eSArIGZyICogcnlcbiAgZnogLT0gZnUgKiB1eiArIGZyICogcnpcbiAgdmFyIGZsID0gbGVuMyhmeCwgZnksIGZ6KVxuICBmeCAvPSBmbFxuICBmeSAvPSBmbFxuICBmeiAvPSBmbFxuXG4gIHZhciB2eCA9IHJ4ICogZHggKyB1eCAqIGR5XG4gIHZhciB2eSA9IHJ5ICogZHggKyB1eSAqIGR5XG4gIHZhciB2eiA9IHJ6ICogZHggKyB1eiAqIGR5XG5cbiAgdGhpcy5jZW50ZXIubW92ZSh0LCB2eCwgdnksIHZ6KVxuXG4gIC8vVXBkYXRlIHotY29tcG9uZW50IG9mIHJhZGl1c1xuICB2YXIgcmFkaXVzID0gTWF0aC5leHAodGhpcy5jb21wdXRlZFJhZGl1c1swXSlcbiAgcmFkaXVzID0gTWF0aC5tYXgoMWUtNCwgcmFkaXVzICsgZHopXG4gIHRoaXMucmFkaXVzLnNldCh0LCBNYXRoLmxvZyhyYWRpdXMpKVxufVxuXG5wcm90by5yb3RhdGUgPSBmdW5jdGlvbih0LCBkeCwgZHksIGR6KSB7XG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG5cbiAgZHggPSBkeHx8MC4wXG4gIGR5ID0gZHl8fDAuMFxuXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG5cbiAgdmFyIHJ4ID0gbWF0WzBdXG4gIHZhciByeSA9IG1hdFs0XVxuICB2YXIgcnogPSBtYXRbOF1cblxuICB2YXIgdXggPSBtYXRbMV1cbiAgdmFyIHV5ID0gbWF0WzVdXG4gIHZhciB1eiA9IG1hdFs5XVxuXG4gIHZhciBmeCA9IG1hdFsyXVxuICB2YXIgZnkgPSBtYXRbNl1cbiAgdmFyIGZ6ID0gbWF0WzEwXVxuXG4gIHZhciBxeCA9IGR4ICogcnggKyBkeSAqIHV4XG4gIHZhciBxeSA9IGR4ICogcnkgKyBkeSAqIHV5XG4gIHZhciBxeiA9IGR4ICogcnogKyBkeSAqIHV6XG5cbiAgdmFyIGJ4ID0gLShmeSAqIHF6IC0gZnogKiBxeSlcbiAgdmFyIGJ5ID0gLShmeiAqIHF4IC0gZnggKiBxeilcbiAgdmFyIGJ6ID0gLShmeCAqIHF5IC0gZnkgKiBxeCkgIFxuICB2YXIgYncgPSBNYXRoLnNxcnQoTWF0aC5tYXgoMC4wLCAxLjAgLSBNYXRoLnBvdyhieCwyKSAtIE1hdGgucG93KGJ5LDIpIC0gTWF0aC5wb3coYnosMikpKVxuICB2YXIgYmwgPSBsZW40KGJ4LCBieSwgYnosIGJ3KVxuICBpZihibCA+IDFlLTYpIHtcbiAgICBieCAvPSBibFxuICAgIGJ5IC89IGJsXG4gICAgYnogLz0gYmxcbiAgICBidyAvPSBibFxuICB9IGVsc2Uge1xuICAgIGJ4ID0gYnkgPSBieiA9IDAuMFxuICAgIGJ3ID0gMS4wXG4gIH1cblxuICB2YXIgcm90YXRpb24gPSB0aGlzLmNvbXB1dGVkUm90YXRpb25cbiAgdmFyIGF4ID0gcm90YXRpb25bMF1cbiAgdmFyIGF5ID0gcm90YXRpb25bMV1cbiAgdmFyIGF6ID0gcm90YXRpb25bMl1cbiAgdmFyIGF3ID0gcm90YXRpb25bM11cblxuICB2YXIgY3ggPSBheCpidyArIGF3KmJ4ICsgYXkqYnogLSBheipieVxuICB2YXIgY3kgPSBheSpidyArIGF3KmJ5ICsgYXoqYnggLSBheCpielxuICB2YXIgY3ogPSBheipidyArIGF3KmJ6ICsgYXgqYnkgLSBheSpieFxuICB2YXIgY3cgPSBhdypidyAtIGF4KmJ4IC0gYXkqYnkgLSBheipielxuICBcbiAgLy9BcHBseSByb2xsXG4gIGlmKGR6KSB7XG4gICAgYnggPSBmeFxuICAgIGJ5ID0gZnlcbiAgICBieiA9IGZ6XG4gICAgdmFyIHMgPSBNYXRoLnNpbihkeikgLyBsZW4zKGJ4LCBieSwgYnopXG4gICAgYnggKj0gc1xuICAgIGJ5ICo9IHNcbiAgICBieiAqPSBzXG4gICAgYncgPSBNYXRoLmNvcyhkeClcbiAgICBjeCA9IGN4KmJ3ICsgY3cqYnggKyBjeSpieiAtIGN6KmJ5XG4gICAgY3kgPSBjeSpidyArIGN3KmJ5ICsgY3oqYnggLSBjeCpielxuICAgIGN6ID0gY3oqYncgKyBjdypieiArIGN4KmJ5IC0gY3kqYnhcbiAgICBjdyA9IGN3KmJ3IC0gY3gqYnggLSBjeSpieSAtIGN6KmJ6XG4gIH1cblxuICB2YXIgY2wgPSBsZW40KGN4LCBjeSwgY3osIGN3KVxuICBpZihjbCA+IDFlLTYpIHtcbiAgICBjeCAvPSBjbFxuICAgIGN5IC89IGNsXG4gICAgY3ogLz0gY2xcbiAgICBjdyAvPSBjbFxuICB9IGVsc2Uge1xuICAgIGN4ID0gY3kgPSBjeiA9IDAuMFxuICAgIGN3ID0gMS4wXG4gIH1cblxuICB0aGlzLnJvdGF0aW9uLnNldCh0LCBjeCwgY3ksIGN6LCBjdylcbn1cblxucHJvdG8ubG9va0F0ID0gZnVuY3Rpb24odCwgZXllLCBjZW50ZXIsIHVwKSB7XG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG5cbiAgY2VudGVyID0gY2VudGVyIHx8IHRoaXMuY29tcHV0ZWRDZW50ZXJcbiAgZXllICAgID0gZXllICAgIHx8IHRoaXMuY29tcHV0ZWRFeWVcbiAgdXAgICAgID0gdXAgICAgIHx8IHRoaXMuY29tcHV0ZWRVcFxuXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIGxvb2tBdChtYXQsIGV5ZSwgY2VudGVyLCB1cClcblxuICB2YXIgcm90YXRpb24gPSB0aGlzLmNvbXB1dGVkUm90YXRpb25cbiAgcXVhdEZyb21GcmFtZShyb3RhdGlvbixcbiAgICBtYXRbMF0sIG1hdFsxXSwgbWF0WzJdLFxuICAgIG1hdFs0XSwgbWF0WzVdLCBtYXRbNl0sXG4gICAgbWF0WzhdLCBtYXRbOV0sIG1hdFsxMF0pXG4gIG5vcm1hbGl6ZTQocm90YXRpb24sIHJvdGF0aW9uKVxuICB0aGlzLnJvdGF0aW9uLnNldCh0LCByb3RhdGlvblswXSwgcm90YXRpb25bMV0sIHJvdGF0aW9uWzJdLCByb3RhdGlvblszXSlcblxuICB2YXIgZmwgPSAwLjBcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgZmwgKz0gTWF0aC5wb3coY2VudGVyW2ldIC0gZXllW2ldLCAyKVxuICB9XG4gIHRoaXMucmFkaXVzLnNldCh0LCAwLjUgKiBNYXRoLmxvZyhNYXRoLm1heChmbCwgMWUtNikpKVxuXG4gIHRoaXMuY2VudGVyLnNldCh0LCBjZW50ZXJbMF0sIGNlbnRlclsxXSwgY2VudGVyWzJdKVxufVxuXG5wcm90by50cmFuc2xhdGUgPSBmdW5jdGlvbih0LCBkeCwgZHksIGR6KSB7XG4gIHRoaXMuY2VudGVyLm1vdmUodCxcbiAgICBkeHx8MC4wLFxuICAgIGR5fHwwLjAsXG4gICAgZHp8fDAuMClcbn1cblxucHJvdG8uc2V0TWF0cml4ID0gZnVuY3Rpb24odCwgbWF0cml4KSB7XG5cbiAgdmFyIHJvdGF0aW9uID0gdGhpcy5jb21wdXRlZFJvdGF0aW9uXG4gIHF1YXRGcm9tRnJhbWUocm90YXRpb24sXG4gICAgbWF0cml4WzBdLCBtYXRyaXhbMV0sIG1hdHJpeFsyXSxcbiAgICBtYXRyaXhbNF0sIG1hdHJpeFs1XSwgbWF0cml4WzZdLFxuICAgIG1hdHJpeFs4XSwgbWF0cml4WzldLCBtYXRyaXhbMTBdKVxuICBub3JtYWxpemU0KHJvdGF0aW9uLCByb3RhdGlvbilcbiAgdGhpcy5yb3RhdGlvbi5zZXQodCwgcm90YXRpb25bMF0sIHJvdGF0aW9uWzFdLCByb3RhdGlvblsyXSwgcm90YXRpb25bM10pXG5cbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgaW52ZXJ0NDQobWF0LCBtYXRyaXgpXG4gIHZhciB3ID0gbWF0WzE1XVxuICBpZihNYXRoLmFicyh3KSA+IDFlLTYpIHtcbiAgICB2YXIgY3ggPSBtYXRbMTJdL3dcbiAgICB2YXIgY3kgPSBtYXRbMTNdL3dcbiAgICB2YXIgY3ogPSBtYXRbMTRdL3dcblxuICAgIHRoaXMucmVjYWxjTWF0cml4KHQpICBcbiAgICB2YXIgciA9IE1hdGguZXhwKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pXG4gICAgdGhpcy5jZW50ZXIuc2V0KHQsIGN4LW1hdFsyXSpyLCBjeS1tYXRbNl0qciwgY3otbWF0WzEwXSpyKVxuICAgIHRoaXMucmFkaXVzLmlkbGUodClcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmNlbnRlci5pZGxlKHQpXG4gICAgdGhpcy5yYWRpdXMuaWRsZSh0KVxuICB9XG59XG5cbnByb3RvLnNldERpc3RhbmNlID0gZnVuY3Rpb24odCwgZCkge1xuICBpZihkID4gMCkge1xuICAgIHRoaXMucmFkaXVzLnNldCh0LCBNYXRoLmxvZyhkKSlcbiAgfVxufVxuXG5wcm90by5zZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKGxvLCBoaSkge1xuICBpZihsbyA+IDApIHtcbiAgICBsbyA9IE1hdGgubG9nKGxvKVxuICB9IGVsc2Uge1xuICAgIGxvID0gLUluZmluaXR5ICAgIFxuICB9XG4gIGlmKGhpID4gMCkge1xuICAgIGhpID0gTWF0aC5sb2coaGkpXG4gIH0gZWxzZSB7XG4gICAgaGkgPSBJbmZpbml0eVxuICB9XG4gIGhpID0gTWF0aC5tYXgoaGksIGxvKVxuICB0aGlzLnJhZGl1cy5ib3VuZHNbMF1bMF0gPSBsb1xuICB0aGlzLnJhZGl1cy5ib3VuZHNbMV1bMF0gPSBoaVxufVxuXG5wcm90by5nZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKG91dCkge1xuICB2YXIgYm91bmRzID0gdGhpcy5yYWRpdXMuYm91bmRzXG4gIGlmKG91dCkge1xuICAgIG91dFswXSA9IE1hdGguZXhwKGJvdW5kc1swXVswXSlcbiAgICBvdXRbMV0gPSBNYXRoLmV4cChib3VuZHNbMV1bMF0pXG4gICAgcmV0dXJuIG91dFxuICB9XG4gIHJldHVybiBbIE1hdGguZXhwKGJvdW5kc1swXVswXSksIE1hdGguZXhwKGJvdW5kc1sxXVswXSkgXVxufVxuXG5wcm90by50b0pTT04gPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5yZWNhbGNNYXRyaXgodGhpcy5sYXN0VCgpKVxuICByZXR1cm4ge1xuICAgIGNlbnRlcjogICB0aGlzLmNvbXB1dGVkQ2VudGVyLnNsaWNlKCksXG4gICAgcm90YXRpb246IHRoaXMuY29tcHV0ZWRSb3RhdGlvbi5zbGljZSgpLFxuICAgIGRpc3RhbmNlOiBNYXRoLmxvZyh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKSxcbiAgICB6b29tTWluOiAgdGhpcy5yYWRpdXMuYm91bmRzWzBdWzBdLFxuICAgIHpvb21NYXg6ICB0aGlzLnJhZGl1cy5ib3VuZHNbMV1bMF1cbiAgfVxufVxuXG5wcm90by5mcm9tSlNPTiA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgdmFyIHQgPSB0aGlzLmxhc3RUKClcbiAgdmFyIGMgPSBvcHRpb25zLmNlbnRlclxuICBpZihjKSB7XG4gICAgdGhpcy5jZW50ZXIuc2V0KHQsIGNbMF0sIGNbMV0sIGNbMl0pXG4gIH1cbiAgdmFyIHIgPSBvcHRpb25zLnJvdGF0aW9uXG4gIGlmKHIpIHtcbiAgICB0aGlzLnJvdGF0aW9uLnNldCh0LCByWzBdLCByWzFdLCByWzJdLCByWzNdKVxuICB9XG4gIHZhciBkID0gb3B0aW9ucy5kaXN0YW5jZVxuICBpZihkICYmIGQgPiAwKSB7XG4gICAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKGQpKVxuICB9XG4gIHRoaXMuc2V0RGlzdGFuY2VMaW1pdHMob3B0aW9ucy56b29tTWluLCBvcHRpb25zLnpvb21NYXgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU9yYml0Q29udHJvbGxlcihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIHZhciBjZW50ZXIgICA9IG9wdGlvbnMuY2VudGVyICAgfHwgWzAsMCwwXVxuICB2YXIgcm90YXRpb24gPSBvcHRpb25zLnJvdGF0aW9uIHx8IFswLDAsMCwxXVxuICB2YXIgcmFkaXVzICAgPSBvcHRpb25zLnJhZGl1cyAgIHx8IDEuMFxuXG4gIGNlbnRlciA9IFtdLnNsaWNlLmNhbGwoY2VudGVyLCAwLCAzKVxuICByb3RhdGlvbiA9IFtdLnNsaWNlLmNhbGwocm90YXRpb24sIDAsIDQpXG4gIG5vcm1hbGl6ZTQocm90YXRpb24sIHJvdGF0aW9uKVxuXG4gIHZhciByZXN1bHQgPSBuZXcgT3JiaXRDYW1lcmFDb250cm9sbGVyKFxuICAgIHJvdGF0aW9uLFxuICAgIGNlbnRlcixcbiAgICBNYXRoLmxvZyhyYWRpdXMpKVxuXG4gIHJlc3VsdC5zZXREaXN0YW5jZUxpbWl0cyhvcHRpb25zLnpvb21NaW4sIG9wdGlvbnMuem9vbU1heClcblxuICBpZignZXllJyBpbiBvcHRpb25zIHx8ICd1cCcgaW4gb3B0aW9ucykge1xuICAgIHJlc3VsdC5sb29rQXQoMCwgb3B0aW9ucy5leWUsIG9wdGlvbnMuY2VudGVyLCBvcHRpb25zLnVwKVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufSIsIi8qIVxuICogcGFkLWxlZnQgPGh0dHBzOi8vZ2l0aHViLmNvbS9qb25zY2hsaW5rZXJ0L3BhZC1sZWZ0PlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNC0yMDE1LCBKb24gU2NobGlua2VydC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciByZXBlYXQgPSByZXF1aXJlKCdyZXBlYXQtc3RyaW5nJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFkTGVmdChzdHIsIG51bSwgY2gpIHtcbiAgY2ggPSB0eXBlb2YgY2ggIT09ICd1bmRlZmluZWQnID8gKGNoICsgJycpIDogJyAnO1xuICByZXR1cm4gcmVwZWF0KGNoLCBudW0pICsgc3RyO1xufTsiLCIndXNlIHN0cmljdCdcclxuXHJcbi8qKlxyXG4gKiBAbW9kdWxlIHBhcmVudGhlc2lzXHJcbiAqL1xyXG5cclxuZnVuY3Rpb24gcGFyc2UgKHN0ciwgb3B0cykge1xyXG5cdC8vIHByZXRlbmQgbm9uLXN0cmluZyBwYXJzZWQgcGVyLXNlXHJcblx0aWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKSByZXR1cm4gW3N0cl1cclxuXHJcblx0dmFyIHJlcyA9IFtzdHJdXHJcblxyXG5cdGlmICh0eXBlb2Ygb3B0cyA9PT0gJ3N0cmluZycgfHwgQXJyYXkuaXNBcnJheShvcHRzKSkge1xyXG5cdFx0b3B0cyA9IHticmFja2V0czogb3B0c31cclxuXHR9XHJcblx0ZWxzZSBpZiAoIW9wdHMpIG9wdHMgPSB7fVxyXG5cclxuXHR2YXIgYnJhY2tldHMgPSBvcHRzLmJyYWNrZXRzID8gKEFycmF5LmlzQXJyYXkob3B0cy5icmFja2V0cykgPyBvcHRzLmJyYWNrZXRzIDogW29wdHMuYnJhY2tldHNdKSA6IFsne30nLCAnW10nLCAnKCknXVxyXG5cclxuXHR2YXIgZXNjYXBlID0gb3B0cy5lc2NhcGUgfHwgJ19fXydcclxuXHJcblx0dmFyIGZsYXQgPSAhIW9wdHMuZmxhdFxyXG5cclxuXHRicmFja2V0cy5mb3JFYWNoKGZ1bmN0aW9uIChicmFja2V0KSB7XHJcblx0XHQvLyBjcmVhdGUgcGFyZW50aGVzaXMgcmVnZXhcclxuXHRcdHZhciBwUkUgPSBuZXcgUmVnRXhwKFsnXFxcXCcsIGJyYWNrZXRbMF0sICdbXlxcXFwnLCBicmFja2V0WzBdLCAnXFxcXCcsIGJyYWNrZXRbMV0sICddKlxcXFwnLCBicmFja2V0WzFdXS5qb2luKCcnKSlcclxuXHJcblx0XHR2YXIgaWRzID0gW11cclxuXHJcblx0XHRmdW5jdGlvbiByZXBsYWNlVG9rZW4odG9rZW4sIGlkeCwgc3RyKXtcclxuXHRcdFx0Ly8gc2F2ZSB0b2tlbiB0byByZXNcclxuXHRcdFx0dmFyIHJlZklkID0gcmVzLnB1c2godG9rZW4uc2xpY2UoYnJhY2tldFswXS5sZW5ndGgsIC1icmFja2V0WzFdLmxlbmd0aCkpIC0gMVxyXG5cclxuXHRcdFx0aWRzLnB1c2gocmVmSWQpXHJcblxyXG5cdFx0XHRyZXR1cm4gZXNjYXBlICsgcmVmSWRcclxuXHRcdH1cclxuXHJcblx0XHRyZXMuZm9yRWFjaChmdW5jdGlvbiAoc3RyLCBpKSB7XHJcblx0XHRcdHZhciBwcmV2U3RyXHJcblxyXG5cdFx0XHQvLyByZXBsYWNlIHBhcmVuIHRva2VucyB0aWxsIHRoZXJl4oCZcyBub25lXHJcblx0XHRcdHZhciBhID0gMFxyXG5cdFx0XHR3aGlsZSAoc3RyICE9IHByZXZTdHIpIHtcclxuXHRcdFx0XHRwcmV2U3RyID0gc3RyXHJcblx0XHRcdFx0c3RyID0gc3RyLnJlcGxhY2UocFJFLCByZXBsYWNlVG9rZW4pXHJcblx0XHRcdFx0aWYgKGErKyA+IDEwZTMpIHRocm93IEVycm9yKCdSZWZlcmVuY2VzIGhhdmUgY2lyY3VsYXIgZGVwZW5kZW5jeS4gUGxlYXNlLCBjaGVjayB0aGVtLicpXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHJlc1tpXSA9IHN0clxyXG5cdFx0fSlcclxuXHJcblx0XHQvLyB3cmFwIGZvdW5kIHJlZnMgdG8gYnJhY2tldHNcclxuXHRcdGlkcyA9IGlkcy5yZXZlcnNlKClcclxuXHRcdHJlcyA9IHJlcy5tYXAoZnVuY3Rpb24gKHN0cikge1xyXG5cdFx0XHRpZHMuZm9yRWFjaChmdW5jdGlvbiAoaWQpIHtcclxuXHRcdFx0XHRzdHIgPSBzdHIucmVwbGFjZShuZXcgUmVnRXhwKCcoXFxcXCcgKyBlc2NhcGUgKyBpZCArICcoPyFbMC05XSkpJywgJ2cnKSwgYnJhY2tldFswXSArICckMScgKyBicmFja2V0WzFdKVxyXG5cdFx0XHR9KVxyXG5cdFx0XHRyZXR1cm4gc3RyXHJcblx0XHR9KVxyXG5cdH0pXHJcblxyXG5cdHZhciByZSA9IG5ldyBSZWdFeHAoJ1xcXFwnICsgZXNjYXBlICsgJyhbMC05XSspJylcclxuXHJcblx0Ly8gdHJhbnNmb3JtIHJlZmVyZW5jZXMgdG8gdHJlZVxyXG5cdGZ1bmN0aW9uIG5lc3QgKHN0ciwgcmVmcywgZXNjYXBlKSB7XHJcblx0XHR2YXIgcmVzID0gW10sIG1hdGNoXHJcblxyXG5cdFx0dmFyIGEgPSAwXHJcblx0XHR3aGlsZSAobWF0Y2ggPSByZS5leGVjKHN0cikpIHtcclxuXHRcdFx0aWYgKGErKyA+IDEwZTMpIHRocm93IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2VzIGluIHBhcmVudGhlc2lzJylcclxuXHJcblx0XHRcdHJlcy5wdXNoKHN0ci5zbGljZSgwLCBtYXRjaC5pbmRleCkpXHJcblxyXG5cdFx0XHRyZXMucHVzaChuZXN0KHJlZnNbbWF0Y2hbMV1dLCByZWZzKSlcclxuXHJcblx0XHRcdHN0ciA9IHN0ci5zbGljZShtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aClcclxuXHRcdH1cclxuXHJcblx0XHRyZXMucHVzaChzdHIpXHJcblxyXG5cdFx0cmV0dXJuIHJlc1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIGZsYXQgPyByZXMgOiBuZXN0KHJlc1swXSwgcmVzKVxyXG59XHJcblxyXG5mdW5jdGlvbiBzdHJpbmdpZnkgKGFyZywgb3B0cykge1xyXG5cdGlmIChvcHRzICYmIG9wdHMuZmxhdCkge1xyXG5cdFx0dmFyIGVzY2FwZSA9IG9wdHMgJiYgb3B0cy5lc2NhcGUgfHwgJ19fXydcclxuXHJcblx0XHR2YXIgc3RyID0gYXJnWzBdLCBwcmV2U3RyXHJcblxyXG5cdFx0Ly8gcHJldGVuZCBiYWQgc3RyaW5nIHN0cmluZ2lmaWVkIHdpdGggbm8gcGFyZW50aGVzZXNcclxuXHRcdGlmICghc3RyKSByZXR1cm4gJydcclxuXHJcblxyXG5cdFx0dmFyIHJlID0gbmV3IFJlZ0V4cCgnXFxcXCcgKyBlc2NhcGUgKyAnKFswLTldKyknKVxyXG5cclxuXHRcdHZhciBhID0gMFxyXG5cdFx0d2hpbGUgKHN0ciAhPSBwcmV2U3RyKSB7XHJcblx0XHRcdGlmIChhKysgPiAxMGUzKSB0aHJvdyBFcnJvcignQ2lyY3VsYXIgcmVmZXJlbmNlcyBpbiAnICsgYXJnKVxyXG5cdFx0XHRwcmV2U3RyID0gc3RyXHJcblx0XHRcdHN0ciA9IHN0ci5yZXBsYWNlKHJlLCByZXBsYWNlUmVmKVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBzdHJcclxuXHR9XHJcblxyXG5cdHJldHVybiBhcmcucmVkdWNlKGZ1bmN0aW9uIGYgKHByZXYsIGN1cnIpIHtcclxuXHRcdGlmIChBcnJheS5pc0FycmF5KGN1cnIpKSB7XHJcblx0XHRcdGN1cnIgPSBjdXJyLnJlZHVjZShmLCAnJylcclxuXHRcdH1cclxuXHRcdHJldHVybiBwcmV2ICsgY3VyclxyXG5cdH0sICcnKVxyXG5cclxuXHRmdW5jdGlvbiByZXBsYWNlUmVmKG1hdGNoLCBpZHgpe1xyXG5cdFx0aWYgKGFyZ1tpZHhdID09IG51bGwpIHRocm93IEVycm9yKCdSZWZlcmVuY2UgJyArIGlkeCArICdpcyB1bmRlZmluZWQnKVxyXG5cdFx0cmV0dXJuIGFyZ1tpZHhdXHJcblx0fVxyXG59XHJcblxyXG5mdW5jdGlvbiBwYXJlbnRoZXNpcyAoYXJnLCBvcHRzKSB7XHJcblx0aWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xyXG5cdFx0cmV0dXJuIHN0cmluZ2lmeShhcmcsIG9wdHMpXHJcblx0fVxyXG5cdGVsc2Uge1xyXG5cdFx0cmV0dXJuIHBhcnNlKGFyZywgb3B0cylcclxuXHR9XHJcbn1cclxuXHJcbnBhcmVudGhlc2lzLnBhcnNlID0gcGFyc2VcclxucGFyZW50aGVzaXMuc3RyaW5naWZ5ID0gc3RyaW5naWZ5XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHBhcmVudGhlc2lzXHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHBpY2sgPSByZXF1aXJlKCdwaWNrLWJ5LWFsaWFzJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcGFyc2VSZWN0XHJcblxyXG5mdW5jdGlvbiBwYXJzZVJlY3QgKGFyZykge1xyXG4gIHZhciByZWN0XHJcblxyXG4gIC8vIGRpcmVjdCBhcmd1bWVudHMgc2VxdWVuY2VcclxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcclxuICAgIGFyZyA9IGFyZ3VtZW50c1xyXG4gIH1cclxuXHJcbiAgLy8gc3ZnIHZpZXdib3hcclxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcclxuICAgIGFyZyA9IGFyZy5zcGxpdCgvXFxzLykubWFwKHBhcnNlRmxvYXQpXHJcbiAgfVxyXG4gIGVsc2UgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XHJcbiAgICBhcmcgPSBbYXJnXVxyXG4gIH1cclxuXHJcbiAgLy8gMCwgMCwgMTAwLCAxMDAgLSBhcnJheS1saWtlXHJcbiAgaWYgKGFyZy5sZW5ndGggJiYgdHlwZW9mIGFyZ1swXSA9PT0gJ251bWJlcicpIHtcclxuICAgIC8vIFt3LCB3XVxyXG4gICAgaWYgKGFyZy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgcmVjdCA9IHtcclxuICAgICAgICB3aWR0aDogYXJnWzBdLFxyXG4gICAgICAgIGhlaWdodDogYXJnWzBdLFxyXG4gICAgICAgIHg6IDAsIHk6IDBcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gW3csIGhdXHJcbiAgICBlbHNlIGlmIChhcmcubGVuZ3RoID09PSAyKSB7XHJcbiAgICAgIHJlY3QgPSB7XHJcbiAgICAgICAgd2lkdGg6IGFyZ1swXSxcclxuICAgICAgICBoZWlnaHQ6IGFyZ1sxXSxcclxuICAgICAgICB4OiAwLCB5OiAwXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIFtsLCB0LCByLCBiXVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHJlY3QgPSB7XHJcbiAgICAgICAgeDogYXJnWzBdLFxyXG4gICAgICAgIHk6IGFyZ1sxXSxcclxuICAgICAgICB3aWR0aDogKGFyZ1syXSAtIGFyZ1swXSkgfHwgMCxcclxuICAgICAgICBoZWlnaHQ6IChhcmdbM10gLSBhcmdbMV0pIHx8IDBcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICAvLyB7eCwgeSwgdywgaH0gb3Ige2wsIHQsIGIsIHJ9XHJcbiAgZWxzZSBpZiAoYXJnKSB7XHJcbiAgICBhcmcgPSBwaWNrKGFyZywge1xyXG4gICAgICBsZWZ0OiAneCBsIGxlZnQgTGVmdCcsXHJcbiAgICAgIHRvcDogJ3kgdCB0b3AgVG9wJyxcclxuICAgICAgd2lkdGg6ICd3IHdpZHRoIFcgV2lkdGgnLFxyXG4gICAgICBoZWlnaHQ6ICdoIGhlaWdodCBXIFdpZHRoJyxcclxuICAgICAgYm90dG9tOiAnYiBib3R0b20gQm90dG9tJyxcclxuICAgICAgcmlnaHQ6ICdyIHJpZ2h0IFJpZ2h0J1xyXG4gICAgfSlcclxuXHJcbiAgICByZWN0ID0ge1xyXG4gICAgICB4OiBhcmcubGVmdCB8fCAwLFxyXG4gICAgICB5OiBhcmcudG9wIHx8IDBcclxuICAgIH1cclxuXHJcbiAgICBpZiAoYXJnLndpZHRoID09IG51bGwpIHtcclxuICAgICAgaWYgKGFyZy5yaWdodCkgcmVjdC53aWR0aCA9IGFyZy5yaWdodCAtIHJlY3QueFxyXG4gICAgICBlbHNlIHJlY3Qud2lkdGggPSAwXHJcbiAgICB9XHJcbiAgICBlbHNlIHtcclxuICAgICAgcmVjdC53aWR0aCA9IGFyZy53aWR0aFxyXG4gICAgfVxyXG5cclxuICAgIGlmIChhcmcuaGVpZ2h0ID09IG51bGwpIHtcclxuICAgICAgaWYgKGFyZy5ib3R0b20pIHJlY3QuaGVpZ2h0ID0gYXJnLmJvdHRvbSAtIHJlY3QueVxyXG4gICAgICBlbHNlIHJlY3QuaGVpZ2h0ID0gMFxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHJlY3QuaGVpZ2h0ID0gYXJnLmhlaWdodFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlY3RcclxufVxyXG4iLCJcbm1vZHVsZS5leHBvcnRzID0gcGFyc2VcblxuLyoqXG4gKiBleHBlY3RlZCBhcmd1bWVudCBsZW5ndGhzXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5cbnZhciBsZW5ndGggPSB7YTogNywgYzogNiwgaDogMSwgbDogMiwgbTogMiwgcTogNCwgczogNCwgdDogMiwgdjogMSwgejogMH1cblxuLyoqXG4gKiBzZWdtZW50IHBhdHRlcm5cbiAqIEB0eXBlIHtSZWdFeHB9XG4gKi9cblxudmFyIHNlZ21lbnQgPSAvKFthc3R2enFtaGxjXSkoW15hc3R2enFtaGxjXSopL2lnXG5cbi8qKlxuICogcGFyc2UgYW4gc3ZnIHBhdGggZGF0YSBzdHJpbmcuIEdlbmVyYXRlcyBhbiBBcnJheVxuICogb2YgY29tbWFuZHMgd2hlcmUgZWFjaCBjb21tYW5kIGlzIGFuIEFycmF5IG9mIHRoZVxuICogZm9ybSBgW2NvbW1hbmQsIGFyZzEsIGFyZzIsIC4uLl1gXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGhcbiAqIEByZXR1cm4ge0FycmF5fVxuICovXG5cbmZ1bmN0aW9uIHBhcnNlKHBhdGgpIHtcblx0dmFyIGRhdGEgPSBbXVxuXHRwYXRoLnJlcGxhY2Uoc2VnbWVudCwgZnVuY3Rpb24oXywgY29tbWFuZCwgYXJncyl7XG5cdFx0dmFyIHR5cGUgPSBjb21tYW5kLnRvTG93ZXJDYXNlKClcblx0XHRhcmdzID0gcGFyc2VWYWx1ZXMoYXJncylcblxuXHRcdC8vIG92ZXJsb2FkZWQgbW92ZVRvXG5cdFx0aWYgKHR5cGUgPT0gJ20nICYmIGFyZ3MubGVuZ3RoID4gMikge1xuXHRcdFx0ZGF0YS5wdXNoKFtjb21tYW5kXS5jb25jYXQoYXJncy5zcGxpY2UoMCwgMikpKVxuXHRcdFx0dHlwZSA9ICdsJ1xuXHRcdFx0Y29tbWFuZCA9IGNvbW1hbmQgPT0gJ20nID8gJ2wnIDogJ0wnXG5cdFx0fVxuXG5cdFx0d2hpbGUgKHRydWUpIHtcblx0XHRcdGlmIChhcmdzLmxlbmd0aCA9PSBsZW5ndGhbdHlwZV0pIHtcblx0XHRcdFx0YXJncy51bnNoaWZ0KGNvbW1hbmQpXG5cdFx0XHRcdHJldHVybiBkYXRhLnB1c2goYXJncylcblx0XHRcdH1cblx0XHRcdGlmIChhcmdzLmxlbmd0aCA8IGxlbmd0aFt0eXBlXSkgdGhyb3cgbmV3IEVycm9yKCdtYWxmb3JtZWQgcGF0aCBkYXRhJylcblx0XHRcdGRhdGEucHVzaChbY29tbWFuZF0uY29uY2F0KGFyZ3Muc3BsaWNlKDAsIGxlbmd0aFt0eXBlXSkpKVxuXHRcdH1cblx0fSlcblx0cmV0dXJuIGRhdGFcbn1cblxudmFyIG51bWJlciA9IC8tP1swLTldKlxcLj9bMC05XSsoPzplWy0rXT9cXGQrKT8vaWdcblxuZnVuY3Rpb24gcGFyc2VWYWx1ZXMoYXJncykge1xuXHR2YXIgbnVtYmVycyA9IGFyZ3MubWF0Y2gobnVtYmVyKVxuXHRyZXR1cm4gbnVtYmVycyA/IG51bWJlcnMubWFwKE51bWJlcikgOiBbXVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYXJzZVVuaXQoc3RyLCBvdXQpIHtcbiAgICBpZiAoIW91dClcbiAgICAgICAgb3V0ID0gWyAwLCAnJyBdXG5cbiAgICBzdHIgPSBTdHJpbmcoc3RyKVxuICAgIHZhciBudW0gPSBwYXJzZUZsb2F0KHN0ciwgMTApXG4gICAgb3V0WzBdID0gbnVtXG4gICAgb3V0WzFdID0gc3RyLm1hdGNoKC9bXFxkLlxcLVxcK10qXFxzKiguKikvKVsxXSB8fCAnJ1xuICAgIHJldHVybiBvdXRcbn0iLCIvLyBHZW5lcmF0ZWQgYnkgQ29mZmVlU2NyaXB0IDEuMTIuMlxuKGZ1bmN0aW9uKCkge1xuICB2YXIgZ2V0TmFub1NlY29uZHMsIGhydGltZSwgbG9hZFRpbWUsIG1vZHVsZUxvYWRUaW1lLCBub2RlTG9hZFRpbWUsIHVwVGltZTtcblxuICBpZiAoKHR5cGVvZiBwZXJmb3JtYW5jZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwZXJmb3JtYW5jZSAhPT0gbnVsbCkgJiYgcGVyZm9ybWFuY2Uubm93KSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICB9O1xuICB9IGVsc2UgaWYgKCh0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzICE9PSBudWxsKSAmJiBwcm9jZXNzLmhydGltZSkge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gKGdldE5hbm9TZWNvbmRzKCkgLSBub2RlTG9hZFRpbWUpIC8gMWU2O1xuICAgIH07XG4gICAgaHJ0aW1lID0gcHJvY2Vzcy5ocnRpbWU7XG4gICAgZ2V0TmFub1NlY29uZHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBocjtcbiAgICAgIGhyID0gaHJ0aW1lKCk7XG4gICAgICByZXR1cm4gaHJbMF0gKiAxZTkgKyBoclsxXTtcbiAgICB9O1xuICAgIG1vZHVsZUxvYWRUaW1lID0gZ2V0TmFub1NlY29uZHMoKTtcbiAgICB1cFRpbWUgPSBwcm9jZXNzLnVwdGltZSgpICogMWU5O1xuICAgIG5vZGVMb2FkVGltZSA9IG1vZHVsZUxvYWRUaW1lIC0gdXBUaW1lO1xuICB9IGVsc2UgaWYgKERhdGUubm93KSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBEYXRlLm5vdygpIC0gbG9hZFRpbWU7XG4gICAgfTtcbiAgICBsb2FkVGltZSA9IERhdGUubm93KCk7XG4gIH0gZWxzZSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIGxvYWRUaW1lO1xuICAgIH07XG4gICAgbG9hZFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgfVxuXG59KS5jYWxsKHRoaXMpO1xuXG4vLyMgc291cmNlTWFwcGluZ1VSTD1wZXJmb3JtYW5jZS1ub3cuanMubWFwXG4iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHBlcm11dGF0aW9uU2lnblxuXG52YXIgQlJVVEVfRk9SQ0VfQ1VUT0ZGID0gMzJcblxudmFyIHBvb2wgPSByZXF1aXJlKFwidHlwZWRhcnJheS1wb29sXCIpXG5cbmZ1bmN0aW9uIHBlcm11dGF0aW9uU2lnbihwKSB7XG4gIHZhciBuID0gcC5sZW5ndGhcbiAgaWYobiA8IEJSVVRFX0ZPUkNFX0NVVE9GRikge1xuICAgIC8vVXNlIHF1YWRyYXRpYyBhbGdvcml0aG0gZm9yIHNtYWxsIG5cbiAgICB2YXIgc2duID0gMVxuICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgZm9yKHZhciBqPTA7IGo8aTsgKytqKSB7XG4gICAgICAgIGlmKHBbaV0gPCBwW2pdKSB7XG4gICAgICAgICAgc2duID0gLXNnblxuICAgICAgICB9IGVsc2UgaWYocFtpXSA9PT0gcFtqXSkge1xuICAgICAgICAgIHJldHVybiAwXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNnblxuICB9IGVsc2Uge1xuICAgIC8vT3RoZXJ3aXNlIHVzZSBsaW5lYXIgdGltZSBhbGdvcml0aG1cbiAgICB2YXIgdmlzaXRlZCA9IHBvb2wubWFsbG9jVWludDgobilcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIHZpc2l0ZWRbaV0gPSAwXG4gICAgfVxuICAgIHZhciBzZ24gPSAxXG4gICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICBpZighdmlzaXRlZFtpXSkge1xuICAgICAgICB2YXIgY291bnQgPSAxXG4gICAgICAgIHZpc2l0ZWRbaV0gPSAxXG4gICAgICAgIGZvcih2YXIgaj1wW2ldOyBqIT09aTsgaj1wW2pdKSB7XG4gICAgICAgICAgaWYodmlzaXRlZFtqXSkge1xuICAgICAgICAgICAgcG9vbC5mcmVlVWludDgodmlzaXRlZClcbiAgICAgICAgICAgIHJldHVybiAwXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvdW50ICs9IDFcbiAgICAgICAgICB2aXNpdGVkW2pdID0gMVxuICAgICAgICB9XG4gICAgICAgIGlmKCEoY291bnQgJiAxKSkge1xuICAgICAgICAgIHNnbiA9IC1zZ25cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBwb29sLmZyZWVVaW50OCh2aXNpdGVkKVxuICAgIHJldHVybiBzZ25cbiAgfVxufSIsIlwidXNlIHN0cmljdFwiXG5cbnZhciBwb29sID0gcmVxdWlyZShcInR5cGVkYXJyYXktcG9vbFwiKVxudmFyIGludmVyc2UgPSByZXF1aXJlKFwiaW52ZXJ0LXBlcm11dGF0aW9uXCIpXG5cbmZ1bmN0aW9uIHJhbmsocGVybXV0YXRpb24pIHtcbiAgdmFyIG4gPSBwZXJtdXRhdGlvbi5sZW5ndGhcbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIDBcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gcGVybXV0YXRpb25bMV1cbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWtcbiAgfVxuICB2YXIgcCA9IHBvb2wubWFsbG9jVWludDMyKG4pXG4gIHZhciBwaW52ID0gcG9vbC5tYWxsb2NVaW50MzIobilcbiAgdmFyIHIgPSAwLCBzLCB0LCBpXG4gIGludmVyc2UocGVybXV0YXRpb24sIHBpbnYpXG4gIGZvcihpPTA7IGk8bjsgKytpKSB7XG4gICAgcFtpXSA9IHBlcm11dGF0aW9uW2ldXG4gIH1cbiAgZm9yKGk9bi0xOyBpPjA7IC0taSkge1xuICAgIHQgPSBwaW52W2ldXG4gICAgcyA9IHBbaV1cbiAgICBwW2ldID0gcFt0XVxuICAgIHBbdF0gPSBzXG4gICAgcGludltpXSA9IHBpbnZbc11cbiAgICBwaW52W3NdID0gdFxuICAgIHIgPSAociArIHMpICogaVxuICB9XG4gIHBvb2wuZnJlZVVpbnQzMihwaW52KVxuICBwb29sLmZyZWVVaW50MzIocClcbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gdW5yYW5rKG4sIHIsIHApIHtcbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgICBpZihwKSB7IHJldHVybiBwIH1cbiAgICAgIHJldHVybiBbXVxuICAgIGNhc2UgMTpcbiAgICAgIGlmKHApIHtcbiAgICAgICAgcFswXSA9IDBcbiAgICAgICAgcmV0dXJuIHBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbMF1cbiAgICAgIH1cbiAgICBjYXNlIDI6XG4gICAgICBpZihwKSB7XG4gICAgICAgIGlmKHIpIHtcbiAgICAgICAgICBwWzBdID0gMFxuICAgICAgICAgIHBbMV0gPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcFswXSA9IDFcbiAgICAgICAgICBwWzFdID0gMFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gciA/IFswLDFdIDogWzEsMF1cbiAgICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWtcbiAgfVxuICBwID0gcCB8fCBuZXcgQXJyYXkobilcbiAgdmFyIHMsIHQsIGksIG5mPTFcbiAgcFswXSA9IDBcbiAgZm9yKGk9MTsgaTxuOyArK2kpIHtcbiAgICBwW2ldID0gaVxuICAgIG5mID0gKG5mKmkpfDBcbiAgfVxuICBmb3IoaT1uLTE7IGk+MDsgLS1pKSB7XG4gICAgcyA9IChyIC8gbmYpfDBcbiAgICByID0gKHIgLSBzICogbmYpfDBcbiAgICBuZiA9IChuZiAvIGkpfDBcbiAgICB0ID0gcFtpXXwwXG4gICAgcFtpXSA9IHBbc118MFxuICAgIHBbc10gPSB0fDBcbiAgfVxuICByZXR1cm4gcFxufVxuXG5leHBvcnRzLnJhbmsgPSByYW5rXG5leHBvcnRzLnVucmFuayA9IHVucmFua1xuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwaWNrIChzcmMsIHByb3BzLCBrZWVwUmVzdCkge1xyXG5cdHZhciByZXN1bHQgPSB7fSwgcHJvcCwgaVxyXG5cclxuXHRpZiAodHlwZW9mIHByb3BzID09PSAnc3RyaW5nJykgcHJvcHMgPSB0b0xpc3QocHJvcHMpXHJcblx0aWYgKEFycmF5LmlzQXJyYXkocHJvcHMpKSB7XHJcblx0XHR2YXIgcmVzID0ge31cclxuXHRcdGZvciAoaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRyZXNbcHJvcHNbaV1dID0gdHJ1ZVxyXG5cdFx0fVxyXG5cdFx0cHJvcHMgPSByZXNcclxuXHR9XHJcblxyXG5cdC8vIGNvbnZlcnQgc3RyaW5ncyB0byBsaXN0c1xyXG5cdGZvciAocHJvcCBpbiBwcm9wcykge1xyXG5cdFx0cHJvcHNbcHJvcF0gPSB0b0xpc3QocHJvcHNbcHJvcF0pXHJcblx0fVxyXG5cclxuXHQvLyBrZWVwLXJlc3Qgc3RyYXRlZ3kgcmVxdWlyZXMgdW5tYXRjaGVkIHByb3BzIHRvIGJlIHByZXNlcnZlZFxyXG5cdHZhciBvY2N1cGllZCA9IHt9XHJcblxyXG5cdGZvciAocHJvcCBpbiBwcm9wcykge1xyXG5cdFx0dmFyIGFsaWFzZXMgPSBwcm9wc1twcm9wXVxyXG5cclxuXHRcdGlmIChBcnJheS5pc0FycmF5KGFsaWFzZXMpKSB7XHJcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBhbGlhc2VzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0dmFyIGFsaWFzID0gYWxpYXNlc1tpXVxyXG5cclxuXHRcdFx0XHRpZiAoa2VlcFJlc3QpIHtcclxuXHRcdFx0XHRcdG9jY3VwaWVkW2FsaWFzXSA9IHRydWVcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGlmIChhbGlhcyBpbiBzcmMpIHtcclxuXHRcdFx0XHRcdHJlc3VsdFtwcm9wXSA9IHNyY1thbGlhc11cclxuXHJcblx0XHRcdFx0XHRpZiAoa2VlcFJlc3QpIHtcclxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgaiA9IGk7IGogPCBhbGlhc2VzLmxlbmd0aDsgaisrKSB7XHJcblx0XHRcdFx0XHRcdFx0b2NjdXBpZWRbYWxpYXNlc1tqXV0gPSB0cnVlXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRicmVha1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSBpZiAocHJvcCBpbiBzcmMpIHtcclxuXHRcdFx0aWYgKHByb3BzW3Byb3BdKSB7XHJcblx0XHRcdFx0cmVzdWx0W3Byb3BdID0gc3JjW3Byb3BdXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmIChrZWVwUmVzdCkge1xyXG5cdFx0XHRcdG9jY3VwaWVkW3Byb3BdID0gdHJ1ZVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRpZiAoa2VlcFJlc3QpIHtcclxuXHRcdGZvciAocHJvcCBpbiBzcmMpIHtcclxuXHRcdFx0aWYgKG9jY3VwaWVkW3Byb3BdKSBjb250aW51ZVxyXG5cdFx0XHRyZXN1bHRbcHJvcF0gPSBzcmNbcHJvcF1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiByZXN1bHRcclxufVxyXG5cclxudmFyIENBQ0hFID0ge31cclxuXHJcbmZ1bmN0aW9uIHRvTGlzdChhcmcpIHtcclxuXHRpZiAoQ0FDSEVbYXJnXSkgcmV0dXJuIENBQ0hFW2FyZ11cclxuXHRpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcclxuXHRcdGFyZyA9IENBQ0hFW2FyZ10gPSBhcmcuc3BsaXQoL1xccyosXFxzKnxcXHMrLylcclxuXHR9XHJcblx0cmV0dXJuIGFyZ1xyXG59XHJcbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gcGxhbmFyRHVhbFxuXG52YXIgY29tcGFyZUFuZ2xlID0gcmVxdWlyZShcImNvbXBhcmUtYW5nbGVcIilcblxuZnVuY3Rpb24gcGxhbmFyRHVhbChjZWxscywgcG9zaXRpb25zKSB7XG5cbiAgdmFyIG51bVZlcnRpY2VzID0gcG9zaXRpb25zLmxlbmd0aHwwXG4gIHZhciBudW1FZGdlcyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgYWRqID0gW25ldyBBcnJheShudW1WZXJ0aWNlcyksIG5ldyBBcnJheShudW1WZXJ0aWNlcyldXG4gIGZvcih2YXIgaT0wOyBpPG51bVZlcnRpY2VzOyArK2kpIHtcbiAgICBhZGpbMF1baV0gPSBbXVxuICAgIGFkalsxXVtpXSA9IFtdXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8bnVtRWRnZXM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBhZGpbMF1bY1swXV0ucHVzaChjKVxuICAgIGFkalsxXVtjWzFdXS5wdXNoKGMpXG4gIH1cblxuICB2YXIgY3ljbGVzID0gW11cblxuICAvL0FkZCBpc29sYXRlZCB2ZXJ0aWNlcyBhcyB0cml2aWFsIGNhc2VcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGlmKGFkalswXVtpXS5sZW5ndGggKyBhZGpbMV1baV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICBjeWNsZXMucHVzaCggW2ldIClcbiAgICB9XG4gIH1cblxuICAvL1JlbW92ZSBhIGhhbGYgZWRnZVxuICBmdW5jdGlvbiBjdXQoYywgaSkge1xuICAgIHZhciBhID0gYWRqW2ldW2NbaV1dXG4gICAgYS5zcGxpY2UoYS5pbmRleE9mKGMpLCAxKVxuICB9XG5cbiAgLy9GaW5kIG5leHQgdmVydGV4IGFuZCBjdXQgZWRnZVxuICBmdW5jdGlvbiBuZXh0KGEsIGIsIG5vQ3V0KSB7XG4gICAgdmFyIG5leHRDZWxsLCBuZXh0VmVydGV4LCBuZXh0RGlyXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XG4gICAgICBpZihhZGpbaV1bYl0ubGVuZ3RoID4gMCkge1xuICAgICAgICBuZXh0Q2VsbCA9IGFkaltpXVtiXVswXVxuICAgICAgICBuZXh0RGlyID0gaVxuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgICBuZXh0VmVydGV4ID0gbmV4dENlbGxbbmV4dERpcl4xXVxuXG4gICAgZm9yKHZhciBkaXI9MDsgZGlyPDI7ICsrZGlyKSB7XG4gICAgICB2YXIgbmJoZCA9IGFkaltkaXJdW2JdXG4gICAgICBmb3IodmFyIGs9MDsgazxuYmhkLmxlbmd0aDsgKytrKSB7XG4gICAgICAgIHZhciBlID0gbmJoZFtrXVxuICAgICAgICB2YXIgcCA9IGVbZGlyXjFdXG4gICAgICAgIHZhciBjbXAgPSBjb21wYXJlQW5nbGUoXG4gICAgICAgICAgICBwb3NpdGlvbnNbYV0sIFxuICAgICAgICAgICAgcG9zaXRpb25zW2JdLCBcbiAgICAgICAgICAgIHBvc2l0aW9uc1tuZXh0VmVydGV4XSxcbiAgICAgICAgICAgIHBvc2l0aW9uc1twXSlcbiAgICAgICAgaWYoY21wID4gMCkge1xuICAgICAgICAgIG5leHRDZWxsID0gZVxuICAgICAgICAgIG5leHRWZXJ0ZXggPSBwXG4gICAgICAgICAgbmV4dERpciA9IGRpclxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmKG5vQ3V0KSB7XG4gICAgICByZXR1cm4gbmV4dFZlcnRleFxuICAgIH1cbiAgICBpZihuZXh0Q2VsbCkge1xuICAgICAgY3V0KG5leHRDZWxsLCBuZXh0RGlyKVxuICAgIH1cbiAgICByZXR1cm4gbmV4dFZlcnRleFxuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdEN5Y2xlKHYsIGRpcikge1xuICAgIHZhciBlMCA9IGFkaltkaXJdW3ZdWzBdXG4gICAgdmFyIGN5Y2xlID0gW3ZdXG4gICAgY3V0KGUwLCBkaXIpXG4gICAgdmFyIHUgPSBlMFtkaXJeMV1cbiAgICB2YXIgZDAgPSBkaXJcbiAgICB3aGlsZSh0cnVlKSB7XG4gICAgICB3aGlsZSh1ICE9PSB2KSB7XG4gICAgICAgIGN5Y2xlLnB1c2godSlcbiAgICAgICAgdSA9IG5leHQoY3ljbGVbY3ljbGUubGVuZ3RoLTJdLCB1LCBmYWxzZSlcbiAgICAgIH1cbiAgICAgIGlmKGFkalswXVt2XS5sZW5ndGggKyBhZGpbMV1bdl0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICB2YXIgYSA9IGN5Y2xlW2N5Y2xlLmxlbmd0aC0xXVxuICAgICAgdmFyIGIgPSB2XG4gICAgICB2YXIgYyA9IGN5Y2xlWzFdXG4gICAgICB2YXIgZCA9IG5leHQoYSwgYiwgdHJ1ZSlcbiAgICAgIGlmKGNvbXBhcmVBbmdsZShwb3NpdGlvbnNbYV0sIHBvc2l0aW9uc1tiXSwgcG9zaXRpb25zW2NdLCBwb3NpdGlvbnNbZF0pIDwgMCkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgY3ljbGUucHVzaCh2KVxuICAgICAgdSA9IG5leHQoYSwgYilcbiAgICB9XG4gICAgcmV0dXJuIGN5Y2xlXG4gIH1cblxuICBmdW5jdGlvbiBzaG91bGRHbHVlKHBjeWNsZSwgbmN5Y2xlKSB7XG4gICAgcmV0dXJuIChuY3ljbGVbMV0gPT09IG5jeWNsZVtuY3ljbGUubGVuZ3RoLTFdKVxuICB9XG5cbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgdmFyIHBjeWNsZSA9IFtdXG4gICAgICB3aGlsZShhZGpbal1baV0ubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgbmkgPSBhZGpbMF1baV0ubGVuZ3RoXG4gICAgICAgIHZhciBuY3ljbGUgPSBleHRyYWN0Q3ljbGUoaSxqKVxuICAgICAgICBpZihzaG91bGRHbHVlKHBjeWNsZSwgbmN5Y2xlKSkge1xuICAgICAgICAgIC8vR2x1ZSB0b2dldGhlciB0cml2aWFsIGN5Y2xlc1xuICAgICAgICAgIHBjeWNsZS5wdXNoLmFwcGx5KHBjeWNsZSwgbmN5Y2xlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmKHBjeWNsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjeWNsZXMucHVzaChwY3ljbGUpXG4gICAgICAgICAgfVxuICAgICAgICAgIHBjeWNsZSA9IG5jeWNsZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZihwY3ljbGUubGVuZ3RoID4gMCkge1xuICAgICAgICBjeWNsZXMucHVzaChwY3ljbGUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9Db21iaW5lIHBhdGhzIGFuZCBsb29wcyB0b2dldGhlclxuICByZXR1cm4gY3ljbGVzXG59IiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gdHJpbUxlYXZlc1xuXG52YXIgZTJhID0gcmVxdWlyZSgnZWRnZXMtdG8tYWRqYWNlbmN5LWxpc3QnKVxuXG5mdW5jdGlvbiB0cmltTGVhdmVzKGVkZ2VzLCBwb3NpdGlvbnMpIHtcbiAgdmFyIGFkaiA9IGUyYShlZGdlcywgcG9zaXRpb25zLmxlbmd0aClcbiAgdmFyIGxpdmUgPSBuZXcgQXJyYXkocG9zaXRpb25zLmxlbmd0aClcbiAgdmFyIG5iaGQgPSBuZXcgQXJyYXkocG9zaXRpb25zLmxlbmd0aClcblxuICB2YXIgZGVhZCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjb3VudCA9IGFkaltpXS5sZW5ndGhcbiAgICBuYmhkW2ldID0gY291bnRcbiAgICBsaXZlW2ldID0gdHJ1ZVxuICAgIGlmKGNvdW50IDw9IDEpIHtcbiAgICAgIGRlYWQucHVzaChpKVxuICAgIH1cbiAgfVxuXG4gIHdoaWxlKGRlYWQubGVuZ3RoID4gMCkge1xuICAgIHZhciB2ID0gZGVhZC5wb3AoKVxuICAgIGxpdmVbdl0gPSBmYWxzZVxuICAgIHZhciBuID0gYWRqW3ZdXG4gICAgZm9yKHZhciBpPTA7IGk8bi5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHUgPSBuW2ldXG4gICAgICBpZigtLW5iaGRbdV0gPT09IDApIHtcbiAgICAgICAgZGVhZC5wdXNoKHUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIG5ld0luZGV4ID0gbmV3IEFycmF5KHBvc2l0aW9ucy5sZW5ndGgpXG4gIHZhciBucG9zaXRpb25zID0gW11cbiAgZm9yKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgaWYobGl2ZVtpXSkge1xuICAgICAgdmFyIHYgPSBucG9zaXRpb25zLmxlbmd0aFxuICAgICAgbmV3SW5kZXhbaV0gPSB2XG4gICAgICBucG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2ldKVxuICAgIH0gZWxzZSB7XG4gICAgICBuZXdJbmRleFtpXSA9IC0xXG4gICAgfVxuICB9XG5cbiAgdmFyIG5lZGdlcyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgIGlmKGxpdmVbZVswXV0gJiYgbGl2ZVtlWzFdXSkge1xuICAgICAgbmVkZ2VzLnB1c2goWyBuZXdJbmRleFtlWzBdXSwgbmV3SW5kZXhbZVsxXV0gXSlcbiAgICB9XG4gIH1cbiAgXG4gIHJldHVybiBbIG5lZGdlcywgbnBvc2l0aW9ucyBdXG59IiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gcGxhbmFyR3JhcGhUb1BvbHlsaW5lXG5cbnZhciBlMmEgPSByZXF1aXJlKCdlZGdlcy10by1hZGphY2VuY3ktbGlzdCcpXG52YXIgcGxhbmFyRHVhbCA9IHJlcXVpcmUoJ3BsYW5hci1kdWFsJylcbnZhciBwcmVwcm9jZXNzUG9seWdvbiA9IHJlcXVpcmUoJ3BvaW50LWluLWJpZy1wb2x5Z29uJylcbnZhciB0d29Qcm9kdWN0ID0gcmVxdWlyZSgndHdvLXByb2R1Y3QnKVxudmFyIHJvYnVzdFN1bSA9IHJlcXVpcmUoJ3JvYnVzdC1zdW0nKVxudmFyIHVuaXEgPSByZXF1aXJlKCd1bmlxJylcbnZhciB0cmltTGVhdmVzID0gcmVxdWlyZSgnLi9saWIvdHJpbS1sZWF2ZXMnKVxuXG5mdW5jdGlvbiBtYWtlQXJyYXkobGVuZ3RoLCBmaWxsKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxsZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IGZpbGxcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1ha2VBcnJheU9mQXJyYXlzKGxlbmd0aCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8bGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBbXVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuXG5mdW5jdGlvbiBwbGFuYXJHcmFwaFRvUG9seWxpbmUoZWRnZXMsIHBvc2l0aW9ucykge1xuXG4gIC8vVHJpbSBsZWF2ZXNcbiAgdmFyIHJlc3VsdCA9IHRyaW1MZWF2ZXMoZWRnZXMsIHBvc2l0aW9ucylcbiAgZWRnZXMgPSByZXN1bHRbMF1cbiAgcG9zaXRpb25zID0gcmVzdWx0WzFdXG5cbiAgdmFyIG51bVZlcnRpY2VzID0gcG9zaXRpb25zLmxlbmd0aFxuICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5sZW5ndGhcblxuICAvL0NhbGN1bGF0ZSBhZGphY2VuY3kgbGlzdCwgY2hlY2sgbWFuaWZvbGRcbiAgdmFyIGFkaiA9IGUyYShlZGdlcywgcG9zaXRpb25zLmxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGlmKGFkaltpXS5sZW5ndGggJSAyID09PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BsYW5hci1ncmFwaC10by1wb2x5bGluZTogZ3JhcGggbXVzdCBiZSBtYW5pZm9sZCcpXG4gICAgfVxuICB9XG5cbiAgLy9HZXQgZmFjZXNcbiAgdmFyIGZhY2VzID0gcGxhbmFyRHVhbChlZGdlcywgcG9zaXRpb25zKVxuXG4gIC8vQ2hlY2sgb3JpZW50YXRpb24gb2YgYSBwb2x5Z29uIHVzaW5nIGV4YWN0IGFyaXRobWV0aWNcbiAgZnVuY3Rpb24gY2N3KGMpIHtcbiAgICB2YXIgbiA9IGMubGVuZ3RoXG4gICAgdmFyIGFyZWEgPSBbMF1cbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHZhciBhID0gcG9zaXRpb25zW2Nbal1dXG4gICAgICB2YXIgYiA9IHBvc2l0aW9uc1tjWyhqKzEpJW5dXVxuICAgICAgdmFyIHQwMCA9IHR3b1Byb2R1Y3QoLWFbMF0sIGFbMV0pXG4gICAgICB2YXIgdDAxID0gdHdvUHJvZHVjdCgtYVswXSwgYlsxXSlcbiAgICAgIHZhciB0MTAgPSB0d29Qcm9kdWN0KCBiWzBdLCBhWzFdKVxuICAgICAgdmFyIHQxMSA9IHR3b1Byb2R1Y3QoIGJbMF0sIGJbMV0pXG4gICAgICBhcmVhID0gcm9idXN0U3VtKGFyZWEsIHJvYnVzdFN1bShyb2J1c3RTdW0odDAwLCB0MDEpLCByb2J1c3RTdW0odDEwLCB0MTEpKSlcbiAgICB9XG4gICAgcmV0dXJuIGFyZWFbYXJlYS5sZW5ndGgtMV0gPiAwXG4gIH1cblxuICAvL0V4dHJhY3QgYWxsIGNsb2Nrd2lzZSBmYWNlc1xuICBmYWNlcyA9IGZhY2VzLmZpbHRlcihjY3cpXG5cbiAgLy9EZXRlY3Qgd2hpY2ggbG9vcHMgYXJlIGNvbnRhaW5lZCBpbiBvbmUgYW5vdGhlciB0byBoYW5kbGUgcGFyZW50LW9mIHJlbGF0aW9uXG4gIHZhciBudW1GYWNlcyA9IGZhY2VzLmxlbmd0aFxuICB2YXIgcGFyZW50ID0gbmV3IEFycmF5KG51bUZhY2VzKVxuICB2YXIgY29udGFpbm1lbnQgPSBuZXcgQXJyYXkobnVtRmFjZXMpXG4gIGZvcih2YXIgaT0wOyBpPG51bUZhY2VzOyArK2kpIHtcbiAgICBwYXJlbnRbaV0gPSBpXG4gICAgdmFyIHJvdyA9IG5ldyBBcnJheShudW1GYWNlcylcbiAgICB2YXIgbG9vcFZlcnRpY2VzID0gZmFjZXNbaV0ubWFwKGZ1bmN0aW9uKHYpIHtcbiAgICAgIHJldHVybiBwb3NpdGlvbnNbdl1cbiAgICB9KVxuICAgIHZhciBwbWMgPSBwcmVwcm9jZXNzUG9seWdvbihbbG9vcFZlcnRpY2VzXSlcbiAgICB2YXIgY291bnQgPSAwXG4gICAgb3V0ZXI6XG4gICAgZm9yKHZhciBqPTA7IGo8bnVtRmFjZXM7ICsraikge1xuICAgICAgcm93W2pdID0gMFxuICAgICAgaWYoaSA9PT0gaikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgdmFyIGMgPSBmYWNlc1tqXVxuICAgICAgdmFyIG4gPSBjLmxlbmd0aFxuICAgICAgZm9yKHZhciBrPTA7IGs8bjsgKytrKSB7XG4gICAgICAgIHZhciBkID0gcG1jKHBvc2l0aW9uc1tjW2tdXSlcbiAgICAgICAgaWYoZCAhPT0gMCkge1xuICAgICAgICAgIGlmKGQgPCAwKSB7XG4gICAgICAgICAgICByb3dbal0gPSAxXG4gICAgICAgICAgICBjb3VudCArPSAxXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlIG91dGVyXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJvd1tqXSA9IDFcbiAgICAgIGNvdW50ICs9IDFcbiAgICB9XG4gICAgY29udGFpbm1lbnRbaV0gPSBbY291bnQsIGksIHJvd11cbiAgfVxuICBjb250YWlubWVudC5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgIHJldHVybiBiWzBdIC0gYVswXVxuICB9KVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgdmFyIHJvdyA9IGNvbnRhaW5tZW50W2ldXG4gICAgdmFyIGlkeCA9IHJvd1sxXVxuICAgIHZhciBjaGlsZHJlbiA9IHJvd1syXVxuICAgIGZvcih2YXIgaj0wOyBqPG51bUZhY2VzOyArK2opIHtcbiAgICAgIGlmKGNoaWxkcmVuW2pdKSB7XG4gICAgICAgIHBhcmVudFtqXSA9IGlkeFxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vSW5pdGlhbGl6ZSBmYWNlIGFkamFjZW5jeSBsaXN0XG4gIHZhciBmYWRqID0gbWFrZUFycmF5T2ZBcnJheXMobnVtRmFjZXMpXG4gIGZvcih2YXIgaT0wOyBpPG51bUZhY2VzOyArK2kpIHtcbiAgICBmYWRqW2ldLnB1c2gocGFyZW50W2ldKVxuICAgIGZhZGpbcGFyZW50W2ldXS5wdXNoKGkpXG4gIH1cblxuICAvL0J1aWxkIGFkamFjZW5jeSBtYXRyaXggZm9yIGVkZ2VzXG4gIHZhciBlZGdlQWRqYWNlbmN5ID0ge31cbiAgdmFyIGludGVybmFsVmVydGljZXMgPSBtYWtlQXJyYXkobnVtVmVydGljZXMsIGZhbHNlKVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgdmFyIGMgPSBmYWNlc1tpXVxuICAgIHZhciBuID0gYy5sZW5ndGhcbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHZhciBhID0gY1tqXVxuICAgICAgdmFyIGIgPSBjWyhqKzEpJW5dXG4gICAgICB2YXIga2V5ID0gTWF0aC5taW4oYSxiKSArIFwiOlwiICsgTWF0aC5tYXgoYSxiKVxuICAgICAgaWYoa2V5IGluIGVkZ2VBZGphY2VuY3kpIHtcbiAgICAgICAgdmFyIG5laWdoYm9yID0gZWRnZUFkamFjZW5jeVtrZXldXG4gICAgICAgIGZhZGpbbmVpZ2hib3JdLnB1c2goaSlcbiAgICAgICAgZmFkaltpXS5wdXNoKG5laWdoYm9yKVxuICAgICAgICBpbnRlcm5hbFZlcnRpY2VzW2FdID0gaW50ZXJuYWxWZXJ0aWNlc1tiXSA9IHRydWVcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVkZ2VBZGphY2VuY3lba2V5XSA9IGlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzaGFyZWRCb3VuZGFyeShjKSB7XG4gICAgdmFyIG4gPSBjLmxlbmd0aFxuICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgaWYoIWludGVybmFsVmVydGljZXNbY1tpXV0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICB2YXIgdG9WaXNpdCA9IFtdXG4gIHZhciBwYXJpdHkgPSBtYWtlQXJyYXkobnVtRmFjZXMsIC0xKVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgaWYocGFyZW50W2ldID09PSBpICYmICFzaGFyZWRCb3VuZGFyeShmYWNlc1tpXSkpIHtcbiAgICAgIHRvVmlzaXQucHVzaChpKVxuICAgICAgcGFyaXR5W2ldID0gMFxuICAgIH0gZWxzZSB7XG4gICAgICBwYXJpdHlbaV0gPSAtMVxuICAgIH1cbiAgfVxuXG4gIC8vVXNpbmcgZmFjZSBhZGphY2VuY3ksIGNsYXNzaWZ5IGZhY2VzIGFzIGluL291dFxuICB2YXIgcmVzdWx0ID0gW11cbiAgd2hpbGUodG9WaXNpdC5sZW5ndGggPiAwKSB7XG4gICAgdmFyIHRvcCA9IHRvVmlzaXQucG9wKClcbiAgICB2YXIgbmJoZCA9IGZhZGpbdG9wXVxuICAgIHVuaXEobmJoZCwgZnVuY3Rpb24oYSxiKSB7XG4gICAgICByZXR1cm4gYS1iXG4gICAgfSlcbiAgICB2YXIgbm5iaHIgPSBuYmhkLmxlbmd0aFxuICAgIHZhciBwID0gcGFyaXR5W3RvcF1cbiAgICB2YXIgcG9seWxpbmVcbiAgICBpZihwID09PSAwKSB7XG4gICAgICB2YXIgYyA9IGZhY2VzW3RvcF1cbiAgICAgIHBvbHlsaW5lID0gW2NdXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPG5uYmhyOyArK2kpIHtcbiAgICAgIHZhciBmID0gbmJoZFtpXVxuICAgICAgaWYocGFyaXR5W2ZdID49IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHBhcml0eVtmXSA9IHBeMVxuICAgICAgdG9WaXNpdC5wdXNoKGYpXG4gICAgICBpZihwID09PSAwKSB7XG4gICAgICAgIHZhciBjID0gZmFjZXNbZl1cbiAgICAgICAgaWYoIXNoYXJlZEJvdW5kYXJ5KGMpKSB7XG4gICAgICAgICAgYy5yZXZlcnNlKClcbiAgICAgICAgICBwb2x5bGluZS5wdXNoKGMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYocCA9PT0gMCkge1xuICAgICAgcmVzdWx0LnB1c2gocG9seWxpbmUpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufSIsIid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3F1YWQnKVxyXG4iLCIvKipcclxuICogQG1vZHVsZSAgcG9pbnQtY2x1c3Rlci9xdWFkXHJcbiAqXHJcbiAqIEJ1Y2tldCBiYXNlZCBxdWFkIHRyZWUgY2x1c3RlcmluZ1xyXG4gKi9cclxuXHJcbid1c2Ugc3RyaWN0J1xyXG5cclxuY29uc3Qgc2VhcmNoID0gcmVxdWlyZSgnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxyXG5jb25zdCBjbGFtcCA9IHJlcXVpcmUoJ2NsYW1wJylcclxuY29uc3QgcmVjdCA9IHJlcXVpcmUoJ3BhcnNlLXJlY3QnKVxyXG5jb25zdCBnZXRCb3VuZHMgPSByZXF1aXJlKCdhcnJheS1ib3VuZHMnKVxyXG5jb25zdCBwaWNrID0gcmVxdWlyZSgncGljay1ieS1hbGlhcycpXHJcbmNvbnN0IGRlZmluZWQgPSByZXF1aXJlKCdkZWZpbmVkJylcclxuY29uc3QgZmxhdHRlbiA9IHJlcXVpcmUoJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKVxyXG5jb25zdCBpc09iaiA9IHJlcXVpcmUoJ2lzLW9iaicpXHJcbmNvbnN0IGR0eXBlID0gcmVxdWlyZSgnZHR5cGUnKVxyXG5jb25zdCBsb2cyID0gcmVxdWlyZSgnbWF0aC1sb2cyJylcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsdXN0ZXIgKHNyY1BvaW50cywgb3B0aW9ucykge1xyXG5cdGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9XHJcblxyXG5cdHNyY1BvaW50cyA9IGZsYXR0ZW4oc3JjUG9pbnRzLCAnZmxvYXQ2NCcpXHJcblxyXG5cdG9wdGlvbnMgPSBwaWNrKG9wdGlvbnMsIHtcclxuXHRcdGJvdW5kczogJ3JhbmdlIGJvdW5kcyBkYXRhQm94IGRhdGFib3gnLFxyXG5cdFx0bWF4RGVwdGg6ICdkZXB0aCBtYXhEZXB0aCBtYXhkZXB0aCBsZXZlbCBtYXhMZXZlbCBtYXhsZXZlbCBsZXZlbHMnLFxyXG5cdFx0ZHR5cGU6ICd0eXBlIGR0eXBlIGZvcm1hdCBvdXQgZHN0IG91dHB1dCBkZXN0aW5hdGlvbidcclxuXHRcdC8vIHNvcnQ6ICdzb3J0Qnkgc29ydGJ5IHNvcnQnLFxyXG5cdFx0Ly8gcGljazogJ3BpY2sgbGV2ZWxQb2ludCcsXHJcblx0XHQvLyBub2RlU2l6ZTogJ25vZGUgbm9kZVNpemUgbWluTm9kZVNpemUgbWluU2l6ZSBzaXplJ1xyXG5cdH0pXHJcblxyXG5cdC8vIGxldCBub2RlU2l6ZSA9IGRlZmluZWQob3B0aW9ucy5ub2RlU2l6ZSwgMSlcclxuXHRsZXQgbWF4RGVwdGggPSBkZWZpbmVkKG9wdGlvbnMubWF4RGVwdGgsIDI1NSlcclxuXHRsZXQgYm91bmRzID0gZGVmaW5lZChvcHRpb25zLmJvdW5kcywgZ2V0Qm91bmRzKHNyY1BvaW50cywgMikpXHJcblx0aWYgKGJvdW5kc1swXSA9PT0gYm91bmRzWzJdKSBib3VuZHNbMl0rK1xyXG5cdGlmIChib3VuZHNbMV0gPT09IGJvdW5kc1szXSkgYm91bmRzWzNdKytcclxuXHJcblx0bGV0IHBvaW50cyA9IG5vcm1hbGl6ZShzcmNQb2ludHMsIGJvdW5kcylcclxuXHJcblx0Ly8gaW5pdCB2YXJpYWJsZXNcclxuXHRsZXQgbiA9IHNyY1BvaW50cy5sZW5ndGggPj4+IDFcclxuXHRsZXQgaWRzXHJcblx0aWYgKCFvcHRpb25zLmR0eXBlKSBvcHRpb25zLmR0eXBlID0gJ2FycmF5J1xyXG5cclxuXHRpZiAodHlwZW9mIG9wdGlvbnMuZHR5cGUgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRpZHMgPSBuZXcgKGR0eXBlKG9wdGlvbnMuZHR5cGUpKShuKVxyXG5cdH1cclxuXHRlbHNlIGlmIChvcHRpb25zLmR0eXBlKSB7XHJcblx0XHRpZHMgPSBvcHRpb25zLmR0eXBlXHJcblx0XHRpZiAoQXJyYXkuaXNBcnJheShpZHMpKSBpZHMubGVuZ3RoID0gblxyXG5cdH1cclxuXHRmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkge1xyXG5cdFx0aWRzW2ldID0gaVxyXG5cdH1cclxuXHJcblx0Ly8gcG9pbnQgaW5kZXhlcyBmb3IgbGV2ZWxzIFswOiBbYSxiLGMsZF0sIDE6IFthLGIsYyxkLGUsZiwuLi5dLCAuLi5dXHJcblx0bGV0IGxldmVscyA9IFtdXHJcblxyXG5cdC8vIHN0YXJ0aW5nIGluZGV4ZXMgb2Ygc3VicmFuZ2VzIGluIHN1YiBsZXZlbHMsIGxldmVscy5sZW5ndGggKiA0XHJcblx0bGV0IHN1YmxldmVscyA9IFtdXHJcblxyXG5cdC8vIHVuaXF1ZSBncm91cCBpZHMsIHNvcnRlZCBpbiB6LWN1cnZlIGZhc2hpb24gd2l0aGluIGxldmVsc1xyXG5cdGxldCBncm91cHMgPSBbXVxyXG5cclxuXHQvLyBsZXZlbCBvZmZzZXRzIGluIGBpZHNgXHJcblx0bGV0IG9mZnNldHMgPSBbXVxyXG5cclxuXHJcblx0Ly8gc29ydCBwb2ludHNcclxuXHRzb3J0KDAsIDAsIDEsIGlkcywgMCwgMSlcclxuXHJcblxyXG5cdC8vIHJldHVybiByZW9yZGVyZWQgaWRzIHdpdGggcHJvdmlkZWQgbWV0aG9kc1xyXG5cdC8vIHNhdmUgbGV2ZWwgb2Zmc2V0cyBpbiBvdXRwdXQgYnVmZmVyXHJcblx0bGV0IG9mZnNldCA9IDBcclxuXHRmb3IgKGxldCBsZXZlbCA9IDA7IGxldmVsIDwgbGV2ZWxzLmxlbmd0aDsgbGV2ZWwrKykge1xyXG5cdFx0bGV0IGxldmVsSXRlbXMgPSBsZXZlbHNbbGV2ZWxdXHJcblx0XHRpZiAoaWRzLnNldCkgaWRzLnNldChsZXZlbEl0ZW1zLCBvZmZzZXQpXHJcblx0XHRlbHNlIHtcclxuXHRcdFx0Zm9yIChsZXQgaSA9IDAsIGwgPSBsZXZlbEl0ZW1zLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG5cdFx0XHRcdGlkc1tpICsgb2Zmc2V0XSA9IGxldmVsSXRlbXNbaV1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0bGV0IG5leHRPZmZzZXQgPSBvZmZzZXQgKyBsZXZlbHNbbGV2ZWxdLmxlbmd0aFxyXG5cdFx0b2Zmc2V0c1tsZXZlbF0gPSBbb2Zmc2V0LCBuZXh0T2Zmc2V0XVxyXG5cdFx0b2Zmc2V0ID0gbmV4dE9mZnNldFxyXG5cdH1cclxuXHJcblx0aWRzLnJhbmdlID0gcmFuZ2VcclxuXHJcblx0cmV0dXJuIGlkc1xyXG5cclxuXHJcblxyXG5cdC8vIEZJWE1FOiBpdCBpcyBwb3NzaWJsZSB0byBjcmVhdGUgb25lIHR5cGVkIGFycmF5IGhlYXAgYW5kIHJldXNlIHRoYXQgdG8gYXZvaWQgbWVtb3J5IGJsb3dcclxuXHRmdW5jdGlvbiBzb3J0ICh4LCB5LCBkaWFtLCBpZHMsIGxldmVsLCBncm91cCkge1xyXG5cdFx0aWYgKCFpZHMubGVuZ3RoKSByZXR1cm4gbnVsbFxyXG5cclxuXHRcdC8vIHNhdmUgZmlyc3QgcG9pbnQgYXMgbGV2ZWwgcmVwcmVzZW50YXRpdmVcclxuXHRcdGxldCBsZXZlbEl0ZW1zID0gbGV2ZWxzW2xldmVsXSB8fCAobGV2ZWxzW2xldmVsXSA9IFtdKVxyXG5cdFx0bGV0IGxldmVsR3JvdXBzID0gZ3JvdXBzW2xldmVsXSB8fCAoZ3JvdXBzW2xldmVsXSA9IFtdKVxyXG5cdFx0bGV0IHN1YmxldmVsID0gc3VibGV2ZWxzW2xldmVsXSB8fCAoc3VibGV2ZWxzW2xldmVsXSA9IFtdKVxyXG5cdFx0bGV0IG9mZnNldCA9IGxldmVsSXRlbXMubGVuZ3RoXHJcblxyXG5cdFx0bGV2ZWwrK1xyXG5cclxuXHRcdC8vIG1heCBkZXB0aCByZWFjaGVkIC0gcHV0IGFsbCBpdGVtcyBpbnRvIGEgZmlyc3QgZ3JvdXBcclxuXHRcdGlmIChsZXZlbCA+IG1heERlcHRoKSB7XHJcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaWRzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0bGV2ZWxJdGVtcy5wdXNoKGlkc1tpXSlcclxuXHRcdFx0XHRsZXZlbEdyb3Vwcy5wdXNoKGdyb3VwKVxyXG5cdFx0XHRcdHN1YmxldmVsLnB1c2gobnVsbCwgbnVsbCwgbnVsbCwgbnVsbClcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0cmV0dXJuIG9mZnNldFxyXG5cdFx0fVxyXG5cclxuXHRcdGxldmVsSXRlbXMucHVzaChpZHNbMF0pXHJcblx0XHRsZXZlbEdyb3Vwcy5wdXNoKGdyb3VwKVxyXG5cclxuXHRcdGlmIChpZHMubGVuZ3RoIDw9IDEpIHtcclxuXHRcdFx0c3VibGV2ZWwucHVzaChudWxsLCBudWxsLCBudWxsLCBudWxsKVxyXG5cdFx0XHRyZXR1cm4gb2Zmc2V0XHJcblx0XHR9XHJcblxyXG5cclxuXHRcdGxldCBkMiA9IGRpYW0gKiAuNVxyXG5cdFx0bGV0IGN4ID0geCArIGQyLCBjeSA9IHkgKyBkMlxyXG5cclxuXHRcdC8vIGRpc3RyaWJ1dGUgcG9pbnRzIGJ5IDQgYnVja2V0c1xyXG5cdFx0bGV0IGxvbG8gPSBbXSwgbG9oaSA9IFtdLCBoaWxvID0gW10sIGhpaGkgPSBbXVxyXG5cclxuXHRcdGZvciAobGV0IGkgPSAxLCBsID0gaWRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG5cdFx0XHRsZXQgaWR4ID0gaWRzW2ldLFxyXG5cdFx0XHRcdHggPSBwb2ludHNbaWR4ICogMl0sXHJcblx0XHRcdFx0eSA9IHBvaW50c1tpZHggKiAyICsgMV1cclxuXHRcdFx0eCA8IGN4ID8gKHkgPCBjeSA/IGxvbG8ucHVzaChpZHgpIDogbG9oaS5wdXNoKGlkeCkpIDogKHkgPCBjeSA/IGhpbG8ucHVzaChpZHgpIDogaGloaS5wdXNoKGlkeCkpXHJcblx0XHR9XHJcblxyXG5cdFx0Z3JvdXAgPDw9IDJcclxuXHRcdHN1YmxldmVsLnB1c2goXHJcblx0XHRcdHNvcnQoeCwgeSwgZDIsIGxvbG8sIGxldmVsLCBncm91cCksXHJcblx0XHRcdHNvcnQoeCwgY3ksIGQyLCBsb2hpLCBsZXZlbCwgZ3JvdXAgKyAxKSxcclxuXHRcdFx0c29ydChjeCwgeSwgZDIsIGhpbG8sIGxldmVsLCBncm91cCArIDIpLFxyXG5cdFx0XHRzb3J0KGN4LCBjeSwgZDIsIGhpaGksIGxldmVsLCBncm91cCArIDMpXHJcblx0XHQpXHJcblxyXG5cdFx0cmV0dXJuIG9mZnNldFxyXG5cdH1cclxuXHJcblx0Ly8gZ2V0IGFsbCBwb2ludHMgd2l0aGluIHRoZSBwYXNzZWQgcmFuZ2VcclxuXHRmdW5jdGlvbiByYW5nZSAoIC4uLmFyZ3MgKSB7XHJcblx0XHRsZXQgb3B0aW9uc1xyXG5cclxuXHRcdGlmIChpc09iaihhcmdzW2FyZ3MubGVuZ3RoIC0gMV0pKSB7XHJcblx0XHRcdGxldCBhcmcgPSBhcmdzLnBvcCgpXHJcblxyXG5cdFx0XHQvLyBkZXRlY3QgaWYgdGhhdCB3YXMgYSByZWN0IG9iamVjdFxyXG5cdFx0XHRpZiAoIWFyZ3MubGVuZ3RoICYmIChhcmcueCAhPSBudWxsIHx8IGFyZy5sICE9IG51bGwgfHwgYXJnLmxlZnQgIT0gbnVsbCkpIHtcclxuXHRcdFx0XHRhcmdzID0gW2FyZ11cclxuXHRcdFx0XHRvcHRpb25zID0ge31cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0b3B0aW9ucyA9IHBpY2soYXJnLCB7XHJcblx0XHRcdFx0bGV2ZWw6ICdsZXZlbCBtYXhMZXZlbCcsXHJcblx0XHRcdFx0ZDogJ2QgZGlhbSBkaWFtZXRlciByIHJhZGl1cyBweCBweFNpemUgcGl4ZWwgcGl4ZWxTaXplIG1heEQgc2l6ZSBtaW5TaXplJyxcclxuXHRcdFx0XHRsb2Q6ICdsb2QgZGV0YWlscyByYW5nZXMgb2Zmc2V0cydcclxuXHRcdFx0fSlcclxuXHRcdH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRvcHRpb25zID0ge31cclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWFyZ3MubGVuZ3RoKSBhcmdzID0gYm91bmRzXHJcblxyXG5cdFx0bGV0IGJveCA9IHJlY3QoIC4uLmFyZ3MgKVxyXG5cclxuXHRcdGxldCBbbWluWCwgbWluWSwgbWF4WCwgbWF4WV0gPSBbXHJcblx0XHRcdE1hdGgubWluKGJveC54LCBib3gueCArIGJveC53aWR0aCksXHJcblx0XHRcdE1hdGgubWluKGJveC55LCBib3gueSArIGJveC5oZWlnaHQpLFxyXG5cdFx0XHRNYXRoLm1heChib3gueCwgYm94LnggKyBib3gud2lkdGgpLFxyXG5cdFx0XHRNYXRoLm1heChib3gueSwgYm94LnkgKyBib3guaGVpZ2h0KVxyXG5cdFx0XVxyXG5cclxuXHRcdGxldCBbbm1pblgsIG5taW5ZLCBubWF4WCwgbm1heFldID0gbm9ybWFsaXplKFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXSwgYm91bmRzIClcclxuXHJcblx0XHRsZXQgbWF4TGV2ZWwgPSBkZWZpbmVkKG9wdGlvbnMubGV2ZWwsIGxldmVscy5sZW5ndGgpXHJcblxyXG5cdFx0Ly8gbGltaXQgbWF4TGV2ZWwgYnkgcHggc2l6ZVxyXG5cdFx0aWYgKG9wdGlvbnMuZCAhPSBudWxsKSB7XHJcblx0XHRcdGxldCBkXHJcblx0XHRcdGlmICh0eXBlb2Ygb3B0aW9ucy5kID09PSAnbnVtYmVyJykgZCA9IFtvcHRpb25zLmQsIG9wdGlvbnMuZF1cclxuXHRcdFx0ZWxzZSBpZiAob3B0aW9ucy5kLmxlbmd0aCkgZCA9IG9wdGlvbnMuZFxyXG5cclxuXHRcdFx0bWF4TGV2ZWwgPSBNYXRoLm1pbihcclxuXHRcdFx0XHRNYXRoLm1heChcclxuXHRcdFx0XHRcdE1hdGguY2VpbCgtbG9nMihNYXRoLmFicyhkWzBdKSAvIChib3VuZHNbMl0gLSBib3VuZHNbMF0pKSksXHJcblx0XHRcdFx0XHRNYXRoLmNlaWwoLWxvZzIoTWF0aC5hYnMoZFsxXSkgLyAoYm91bmRzWzNdIC0gYm91bmRzWzFdKSkpXHJcblx0XHRcdFx0KSxcclxuXHRcdFx0XHRtYXhMZXZlbFxyXG5cdFx0XHQpXHJcblx0XHR9XHJcblx0XHRtYXhMZXZlbCA9IE1hdGgubWluKG1heExldmVsLCBsZXZlbHMubGVuZ3RoKVxyXG5cclxuXHRcdC8vIHJldHVybiBsZXZlbHMgb2YgZGV0YWlsc1xyXG5cdFx0aWYgKG9wdGlvbnMubG9kKSB7XHJcblx0XHRcdHJldHVybiBsb2Qobm1pblgsIG5taW5ZLCBubWF4WCwgbm1heFksIG1heExldmVsKVxyXG5cdFx0fVxyXG5cclxuXHJcblxyXG5cdFx0Ly8gZG8gc2VsZWN0aW9uIGlkc1xyXG5cdFx0bGV0IHNlbGVjdGlvbiA9IFtdXHJcblxyXG5cdFx0Ly8gRklYTUU6IHByb2JhYmx5IHdlIGNhbiBkbyBMT0QgaGVyZSBiZWZvcmVoZWFkXHJcblx0XHRzZWxlY3QoIDAsIDAsIDEsIDAsIDAsIDEpXHJcblxyXG5cdFx0ZnVuY3Rpb24gc2VsZWN0ICggbG94LCBsb3ksIGQsIGxldmVsLCBmcm9tLCB0byApIHtcclxuXHRcdFx0aWYgKGZyb20gPT09IG51bGwgfHwgdG8gPT09IG51bGwpIHJldHVyblxyXG5cclxuXHRcdFx0bGV0IGhpeCA9IGxveCArIGRcclxuXHRcdFx0bGV0IGhpeSA9IGxveSArIGRcclxuXHJcblx0XHRcdC8vIGlmIGJveCBkb2VzIG5vdCBpbnRlcnNlY3QgbGV2ZWwgLSBpZ25vcmVcclxuXHRcdFx0aWYgKCBubWluWCA+IGhpeCB8fCBubWluWSA+IGhpeSB8fCBubWF4WCA8IGxveCB8fCBubWF4WSA8IGxveSApIHJldHVyblxyXG5cdFx0XHRpZiAoIGxldmVsID49IG1heExldmVsICkgcmV0dXJuXHJcblx0XHRcdGlmICggZnJvbSA9PT0gdG8gKSByZXR1cm5cclxuXHJcblx0XHRcdC8vIGlmIHBvaW50cyBmYWxsIGludG8gYm94IHJhbmdlIC0gdGFrZSBpdFxyXG5cdFx0XHRsZXQgbGV2ZWxJdGVtcyA9IGxldmVsc1tsZXZlbF1cclxuXHJcblx0XHRcdGlmICh0byA9PT0gdW5kZWZpbmVkKSB0byA9IGxldmVsSXRlbXMubGVuZ3RoXHJcblxyXG5cdFx0XHRmb3IgKGxldCBpID0gZnJvbTsgaSA8IHRvOyBpKyspIHtcclxuXHRcdFx0XHRsZXQgaWQgPSBsZXZlbEl0ZW1zW2ldXHJcblxyXG5cdFx0XHRcdGxldCBweCA9IHNyY1BvaW50c1sgaWQgKiAyIF1cclxuXHRcdFx0XHRsZXQgcHkgPSBzcmNQb2ludHNbIGlkICogMiArIDEgXVxyXG5cclxuXHRcdFx0XHRpZiAoIHB4ID49IG1pblggJiYgcHggPD0gbWF4WCAmJiBweSA+PSBtaW5ZICYmIHB5IDw9IG1heFkgKSB7c2VsZWN0aW9uLnB1c2goaWQpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBmb3IgZXZlcnkgc3Vic2VjdGlvbiBkbyBzZWxlY3RcclxuXHRcdFx0bGV0IG9mZnNldHMgPSBzdWJsZXZlbHNbIGxldmVsIF1cclxuXHRcdFx0bGV0IG9mZjAgPSBvZmZzZXRzWyBmcm9tICogNCArIDAgXVxyXG5cdFx0XHRsZXQgb2ZmMSA9IG9mZnNldHNbIGZyb20gKiA0ICsgMSBdXHJcblx0XHRcdGxldCBvZmYyID0gb2Zmc2V0c1sgZnJvbSAqIDQgKyAyIF1cclxuXHRcdFx0bGV0IG9mZjMgPSBvZmZzZXRzWyBmcm9tICogNCArIDMgXVxyXG5cdFx0XHRsZXQgZW5kID0gbmV4dE9mZnNldChvZmZzZXRzLCBmcm9tICsgMSlcclxuXHJcblx0XHRcdGxldCBkMiA9IGQgKiAuNVxyXG5cdFx0XHRsZXQgbmV4dExldmVsID0gbGV2ZWwgKyAxXHJcblx0XHRcdHNlbGVjdCggbG94LCBsb3ksIGQyLCBuZXh0TGV2ZWwsIG9mZjAsIG9mZjEgfHwgb2ZmMiB8fCBvZmYzIHx8IGVuZClcclxuXHRcdFx0c2VsZWN0KCBsb3gsIGxveSArIGQyLCBkMiwgbmV4dExldmVsLCBvZmYxLCBvZmYyIHx8IG9mZjMgfHwgZW5kKVxyXG5cdFx0XHRzZWxlY3QoIGxveCArIGQyLCBsb3ksIGQyLCBuZXh0TGV2ZWwsIG9mZjIsIG9mZjMgfHwgZW5kKVxyXG5cdFx0XHRzZWxlY3QoIGxveCArIGQyLCBsb3kgKyBkMiwgZDIsIG5leHRMZXZlbCwgb2ZmMywgZW5kKVxyXG5cdFx0fVxyXG5cclxuXHRcdGZ1bmN0aW9uIG5leHRPZmZzZXQob2Zmc2V0cywgZnJvbSkge1xyXG5cdFx0XHRsZXQgb2Zmc2V0ID0gbnVsbCwgaSA9IDBcclxuXHRcdFx0d2hpbGUob2Zmc2V0ID09PSBudWxsKSB7XHJcblx0XHRcdFx0b2Zmc2V0ID0gb2Zmc2V0c1sgZnJvbSAqIDQgKyBpIF1cclxuXHRcdFx0XHRpKytcclxuXHRcdFx0XHRpZiAoaSA+IG9mZnNldHMubGVuZ3RoKSByZXR1cm4gbnVsbFxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBvZmZzZXRcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gc2VsZWN0aW9uXHJcblx0fVxyXG5cclxuXHQvLyBnZXQgcmFuZ2Ugb2Zmc2V0cyB3aXRoaW4gbGV2ZWxzIHRvIHJlbmRlciBsb2RzIGFwcHJvcHJpYXRlIGZvciB6b29tIGxldmVsXHJcblx0Ly8gVE9ETzogaXQgaXMgcG9zc2libGUgdG8gc3RvcmUgbWluU2l6ZSBvZiBhIHBvaW50IHRvIG9wdGltaXplIG5lZWRlIGxldmVsIGNhbGNcclxuXHRmdW5jdGlvbiBsb2QgKGxveCwgbG95LCBoaXgsIGhpeSwgbWF4TGV2ZWwpIHtcclxuXHRcdGxldCByYW5nZXMgPSBbXVxyXG5cclxuXHRcdGZvciAobGV0IGxldmVsID0gMDsgbGV2ZWwgPCBtYXhMZXZlbDsgbGV2ZWwrKykge1xyXG5cdFx0XHRsZXQgbGV2ZWxHcm91cHMgPSBncm91cHNbbGV2ZWxdXHJcblx0XHRcdGxldCBmcm9tID0gb2Zmc2V0c1tsZXZlbF1bMF1cclxuXHJcblx0XHRcdGxldCBsZXZlbEdyb3VwU3RhcnQgPSBncm91cChsb3gsIGxveSwgbGV2ZWwpXHJcblx0XHRcdGxldCBsZXZlbEdyb3VwRW5kID0gZ3JvdXAoaGl4LCBoaXksIGxldmVsKVxyXG5cclxuXHRcdFx0Ly8gRklYTUU6IHV0aWxpemUgc3VibGV2ZWxzIHRvIHNwZWVkIHVwIHNlYXJjaCByYW5nZSBoZXJlXHJcblx0XHRcdGxldCBzdGFydE9mZnNldCA9IHNlYXJjaC5nZShsZXZlbEdyb3VwcywgbGV2ZWxHcm91cFN0YXJ0KVxyXG5cdFx0XHRsZXQgZW5kT2Zmc2V0ID0gc2VhcmNoLmd0KGxldmVsR3JvdXBzLCBsZXZlbEdyb3VwRW5kLCBzdGFydE9mZnNldCwgbGV2ZWxHcm91cHMubGVuZ3RoIC0gMSlcclxuXHJcblx0XHRcdHJhbmdlc1tsZXZlbF0gPSBbc3RhcnRPZmZzZXQgKyBmcm9tLCBlbmRPZmZzZXQgKyBmcm9tXVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiByYW5nZXNcclxuXHR9XHJcblxyXG5cdC8vIGdldCBncm91cCBpZCBjbG9zZXN0IHRvIHRoZSB4LHkgY29vcmRpbmF0ZSwgY29ycmVzcG9uZGluZyB0byBhIGxldmVsXHJcblx0ZnVuY3Rpb24gZ3JvdXAgKHgsIHksIGxldmVsKSB7XHJcblx0XHRsZXQgZ3JvdXAgPSAxXHJcblxyXG5cdFx0bGV0IGN4ID0gLjUsIGN5ID0gLjVcclxuXHRcdGxldCBkaWFtID0gLjVcclxuXHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxldmVsOyBpKyspIHtcclxuXHRcdFx0Z3JvdXAgPDw9IDJcclxuXHJcblx0XHRcdGdyb3VwICs9IHggPCBjeCA/ICh5IDwgY3kgPyAwIDogMSkgOiAoeSA8IGN5ID8gMiA6IDMpXHJcblxyXG5cdFx0XHRkaWFtICo9IC41XHJcblxyXG5cdFx0XHRjeCArPSB4IDwgY3ggPyAtZGlhbSA6IGRpYW1cclxuXHRcdFx0Y3kgKz0geSA8IGN5ID8gLWRpYW0gOiBkaWFtXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGdyb3VwXHJcblx0fVxyXG59XHJcblxyXG5cclxuLy8gbm9ybWFsaXplIHBvaW50cyBieSBib3VuZHNcclxuZnVuY3Rpb24gbm9ybWFsaXplIChwdHMsIGJvdW5kcykge1xyXG5cdGxldCBbbG94LCBsb3ksIGhpeCwgaGl5XSA9IGJvdW5kc1xyXG5cdGxldCBzY2FsZVggPSAxLjAgLyAoaGl4IC0gbG94KVxyXG5cdGxldCBzY2FsZVkgPSAxLjAgLyAoaGl5IC0gbG95KVxyXG5cdGxldCByZXN1bHQgPSBuZXcgQXJyYXkocHRzLmxlbmd0aClcclxuXHJcblx0Zm9yIChsZXQgaSA9IDAsIG4gPSBwdHMubGVuZ3RoIC8gMjsgaSA8IG47IGkrKykge1xyXG5cdFx0cmVzdWx0WzIqaV0gPSBjbGFtcCgocHRzWzIqaV0gLSBsb3gpICogc2NhbGVYLCAwLCAxKVxyXG5cdFx0cmVzdWx0WzIqaSsxXSA9IGNsYW1wKChwdHNbMippKzFdIC0gbG95KSAqIHNjYWxlWSwgMCwgMSlcclxuXHR9XHJcblxyXG5cdHJldHVybiByZXN1bHRcclxufVxyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHByZXByb2Nlc3NQb2x5Z29uXG5cbnZhciBvcmllbnQgPSByZXF1aXJlKCdyb2J1c3Qtb3JpZW50YXRpb24nKVszXVxudmFyIG1ha2VTbGFicyA9IHJlcXVpcmUoJ3NsYWItZGVjb21wb3NpdGlvbicpXG52YXIgbWFrZUludGVydmFsVHJlZSA9IHJlcXVpcmUoJ2ludGVydmFsLXRyZWUtMWQnKVxudmFyIGJzZWFyY2ggPSByZXF1aXJlKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXG5cbmZ1bmN0aW9uIHZpc2l0SW50ZXJ2YWwoKSB7XG4gIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIGludGVydmFsU2VhcmNoKHRhYmxlKSB7XG4gIHJldHVybiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIHRyZWUgPSB0YWJsZVt4XVxuICAgIGlmKHRyZWUpIHtcbiAgICAgIHJldHVybiAhIXRyZWUucXVlcnlQb2ludCh5LCB2aXNpdEludGVydmFsKVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5mdW5jdGlvbiBidWlsZFZlcnRpY2FsSW5kZXgoc2VnbWVudHMpIHtcbiAgdmFyIHRhYmxlID0ge31cbiAgZm9yKHZhciBpPTA7IGk8c2VnbWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcyA9IHNlZ21lbnRzW2ldXG4gICAgdmFyIHggPSBzWzBdWzBdXG4gICAgdmFyIHkwID0gc1swXVsxXVxuICAgIHZhciB5MSA9IHNbMV1bMV1cbiAgICB2YXIgcCA9IFsgTWF0aC5taW4oeTAsIHkxKSwgTWF0aC5tYXgoeTAsIHkxKSBdXG4gICAgaWYoeCBpbiB0YWJsZSkge1xuICAgICAgdGFibGVbeF0ucHVzaChwKVxuICAgIH0gZWxzZSB7XG4gICAgICB0YWJsZVt4XSA9IFsgcCBdXG4gICAgfVxuICB9XG4gIHZhciBpbnRlcnZhbFRhYmxlID0ge31cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh0YWJsZSlcbiAgZm9yKHZhciBpPTA7IGk8a2V5cy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBzZWdzID0gdGFibGVba2V5c1tpXV1cbiAgICBpbnRlcnZhbFRhYmxlW2tleXNbaV1dID0gbWFrZUludGVydmFsVHJlZShzZWdzKVxuICB9XG4gIHJldHVybiBpbnRlcnZhbFNlYXJjaChpbnRlcnZhbFRhYmxlKVxufVxuXG5mdW5jdGlvbiBidWlsZFNsYWJTZWFyY2goc2xhYnMsIGNvb3JkaW5hdGVzKSB7XG4gIHJldHVybiBmdW5jdGlvbihwKSB7XG4gICAgdmFyIGJ1Y2tldCA9IGJzZWFyY2gubGUoY29vcmRpbmF0ZXMsIHBbMF0pXG4gICAgaWYoYnVja2V0IDwgMCkge1xuICAgICAgcmV0dXJuIDFcbiAgICB9XG4gICAgdmFyIHJvb3QgPSBzbGFic1tidWNrZXRdXG4gICAgaWYoIXJvb3QpIHtcbiAgICAgIGlmKGJ1Y2tldCA+IDAgJiYgY29vcmRpbmF0ZXNbYnVja2V0XSA9PT0gcFswXSkge1xuICAgICAgICByb290ID0gc2xhYnNbYnVja2V0LTFdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMVxuICAgICAgfVxuICAgIH1cbiAgICB2YXIgbGFzdE9yaWVudGF0aW9uID0gMVxuICAgIHdoaWxlKHJvb3QpIHtcbiAgICAgIHZhciBzID0gcm9vdC5rZXlcbiAgICAgIHZhciBvID0gb3JpZW50KHAsIHNbMF0sIHNbMV0pXG4gICAgICBpZihzWzBdWzBdIDwgc1sxXVswXSkge1xuICAgICAgICBpZihvIDwgMCkge1xuICAgICAgICAgIHJvb3QgPSByb290LmxlZnRcbiAgICAgICAgfSBlbHNlIGlmKG8gPiAwKSB7XG4gICAgICAgICAgbGFzdE9yaWVudGF0aW9uID0gLTFcbiAgICAgICAgICByb290ID0gcm9vdC5yaWdodFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiAwXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKG8gPiAwKSB7XG4gICAgICAgICAgcm9vdCA9IHJvb3QubGVmdFxuICAgICAgICB9IGVsc2UgaWYobyA8IDApIHtcbiAgICAgICAgICBsYXN0T3JpZW50YXRpb24gPSAxXG4gICAgICAgICAgcm9vdCA9IHJvb3QucmlnaHRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gMFxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBsYXN0T3JpZW50YXRpb25cbiAgfVxufVxuXG5mdW5jdGlvbiBjbGFzc2lmeUVtcHR5KHApIHtcbiAgcmV0dXJuIDFcbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2xhc3NpZnlWZXJ0aWNhbCh0ZXN0VmVydGljYWwpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGNsYXNzaWZ5KHApIHtcbiAgICBpZih0ZXN0VmVydGljYWwocFswXSwgcFsxXSkpIHtcbiAgICAgIHJldHVybiAwXG4gICAgfVxuICAgIHJldHVybiAxXG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2xhc3NpZnlQb2ludERlZ2VuKHRlc3RWZXJ0aWNhbCwgdGVzdE5vcm1hbCkge1xuICByZXR1cm4gZnVuY3Rpb24gY2xhc3NpZnkocCkge1xuICAgIGlmKHRlc3RWZXJ0aWNhbChwWzBdLCBwWzFdKSkge1xuICAgICAgcmV0dXJuIDBcbiAgICB9XG4gICAgcmV0dXJuIHRlc3ROb3JtYWwocClcbiAgfVxufVxuXG5mdW5jdGlvbiBwcmVwcm9jZXNzUG9seWdvbihsb29wcykge1xuICAvL0NvbXB1dGUgbnVtYmVyIG9mIGxvb3BzXG4gIHZhciBudW1Mb29wcyA9IGxvb3BzLmxlbmd0aFxuXG4gIC8vVW5wYWNrIHNlZ21lbnRzXG4gIHZhciBzZWdtZW50cyA9IFtdXG4gIHZhciB2c2VnbWVudHMgPSBbXVxuICB2YXIgcHRyID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1Mb29wczsgKytpKSB7XG4gICAgdmFyIGxvb3AgPSBsb29wc1tpXVxuICAgIHZhciBudW1WZXJ0aWNlcyA9IGxvb3AubGVuZ3RoXG4gICAgZm9yKHZhciBzPW51bVZlcnRpY2VzLTEsdD0wOyB0PG51bVZlcnRpY2VzOyBzPSh0KyspKSB7XG4gICAgICB2YXIgYSA9IGxvb3Bbc11cbiAgICAgIHZhciBiID0gbG9vcFt0XVxuICAgICAgaWYoYVswXSA9PT0gYlswXSkge1xuICAgICAgICB2c2VnbWVudHMucHVzaChbYSxiXSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlZ21lbnRzLnB1c2goW2EsYl0pXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9EZWdlbmVyYXRlIGNhc2U6IEFsbCBsb29wcyBhcmUgZW1wdHlcbiAgaWYoc2VnbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYodnNlZ21lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGNsYXNzaWZ5RW1wdHlcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNyZWF0ZUNsYXNzaWZ5VmVydGljYWwoYnVpbGRWZXJ0aWNhbEluZGV4KHZzZWdtZW50cykpXG4gICAgfVxuICB9XG5cbiAgLy9CdWlsZCBzbGFiIGRlY29tcG9zaXRpb25cbiAgdmFyIHNsYWJzID0gbWFrZVNsYWJzKHNlZ21lbnRzKVxuICB2YXIgdGVzdFNsYWIgPSBidWlsZFNsYWJTZWFyY2goc2xhYnMuc2xhYnMsIHNsYWJzLmNvb3JkaW5hdGVzKVxuXG4gIGlmKHZzZWdtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdGVzdFNsYWJcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY3JlYXRlQ2xhc3NpZnlQb2ludERlZ2VuKFxuICAgICAgYnVpbGRWZXJ0aWNhbEluZGV4KHZzZWdtZW50cyksXG4gICAgICB0ZXN0U2xhYilcbiAgfVxufSIsIi8qXG4gKiBAY29weXJpZ2h0IDIwMTYgU2VhbiBDb25uZWxseSAoQHZvaWRxayksIGh0dHA6Ly9zeW50aGV0aS5jY1xuICogQGxpY2Vuc2UgTUlUXG4gKiBAcHJlc2VydmUgUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcbiAqL1xuXG52YXIgQnVpbGRMb2cgPSByZXF1aXJlKCcuL2xpYi9idWlsZC1sb2cnKTtcbnZhciBFcHNpbG9uID0gcmVxdWlyZSgnLi9saWIvZXBzaWxvbicpO1xudmFyIEludGVyc2VjdGVyID0gcmVxdWlyZSgnLi9saWIvaW50ZXJzZWN0ZXInKTtcbnZhciBTZWdtZW50Q2hhaW5lciA9IHJlcXVpcmUoJy4vbGliL3NlZ21lbnQtY2hhaW5lcicpO1xudmFyIFNlZ21lbnRTZWxlY3RvciA9IHJlcXVpcmUoJy4vbGliL3NlZ21lbnQtc2VsZWN0b3InKTtcbnZhciBHZW9KU09OID0gcmVxdWlyZSgnLi9saWIvZ2VvanNvbicpO1xuXG52YXIgYnVpbGRMb2cgPSBmYWxzZTtcbnZhciBlcHNpbG9uID0gRXBzaWxvbigpO1xuXG52YXIgUG9seUJvb2w7XG5Qb2x5Qm9vbCA9IHtcblx0Ly8gZ2V0dGVyL3NldHRlciBmb3IgYnVpbGRMb2dcblx0YnVpbGRMb2c6IGZ1bmN0aW9uKGJsKXtcblx0XHRpZiAoYmwgPT09IHRydWUpXG5cdFx0XHRidWlsZExvZyA9IEJ1aWxkTG9nKCk7XG5cdFx0ZWxzZSBpZiAoYmwgPT09IGZhbHNlKVxuXHRcdFx0YnVpbGRMb2cgPSBmYWxzZTtcblx0XHRyZXR1cm4gYnVpbGRMb2cgPT09IGZhbHNlID8gZmFsc2UgOiBidWlsZExvZy5saXN0O1xuXHR9LFxuXHQvLyBnZXR0ZXIvc2V0dGVyIGZvciBlcHNpbG9uXG5cdGVwc2lsb246IGZ1bmN0aW9uKHYpe1xuXHRcdHJldHVybiBlcHNpbG9uLmVwc2lsb24odik7XG5cdH0sXG5cblx0Ly8gY29yZSBBUElcblx0c2VnbWVudHM6IGZ1bmN0aW9uKHBvbHkpe1xuXHRcdHZhciBpID0gSW50ZXJzZWN0ZXIodHJ1ZSwgZXBzaWxvbiwgYnVpbGRMb2cpO1xuXHRcdHBvbHkucmVnaW9ucy5mb3JFYWNoKGkuYWRkUmVnaW9uKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IGkuY2FsY3VsYXRlKHBvbHkuaW52ZXJ0ZWQpLFxuXHRcdFx0aW52ZXJ0ZWQ6IHBvbHkuaW52ZXJ0ZWRcblx0XHR9O1xuXHR9LFxuXHRjb21iaW5lOiBmdW5jdGlvbihzZWdtZW50czEsIHNlZ21lbnRzMil7XG5cdFx0dmFyIGkzID0gSW50ZXJzZWN0ZXIoZmFsc2UsIGVwc2lsb24sIGJ1aWxkTG9nKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29tYmluZWQ6IGkzLmNhbGN1bGF0ZShcblx0XHRcdFx0c2VnbWVudHMxLnNlZ21lbnRzLCBzZWdtZW50czEuaW52ZXJ0ZWQsXG5cdFx0XHRcdHNlZ21lbnRzMi5zZWdtZW50cywgc2VnbWVudHMyLmludmVydGVkXG5cdFx0XHQpLFxuXHRcdFx0aW52ZXJ0ZWQxOiBzZWdtZW50czEuaW52ZXJ0ZWQsXG5cdFx0XHRpbnZlcnRlZDI6IHNlZ21lbnRzMi5pbnZlcnRlZFxuXHRcdH07XG5cdH0sXG5cdHNlbGVjdFVuaW9uOiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IudW5pb24oY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgfHwgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3RJbnRlcnNlY3Q6IGZ1bmN0aW9uKGNvbWJpbmVkKXtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IFNlZ21lbnRTZWxlY3Rvci5pbnRlcnNlY3QoY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgJiYgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3REaWZmZXJlbmNlOiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IuZGlmZmVyZW5jZShjb21iaW5lZC5jb21iaW5lZCwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6IGNvbWJpbmVkLmludmVydGVkMSAmJiAhY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3REaWZmZXJlbmNlUmV2OiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IuZGlmZmVyZW5jZVJldihjb21iaW5lZC5jb21iaW5lZCwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6ICFjb21iaW5lZC5pbnZlcnRlZDEgJiYgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3RYb3I6IGZ1bmN0aW9uKGNvbWJpbmVkKXtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IFNlZ21lbnRTZWxlY3Rvci54b3IoY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgIT09IGNvbWJpbmVkLmludmVydGVkMlxuXHRcdH1cblx0fSxcblx0cG9seWdvbjogZnVuY3Rpb24oc2VnbWVudHMpe1xuXHRcdHJldHVybiB7XG5cdFx0XHRyZWdpb25zOiBTZWdtZW50Q2hhaW5lcihzZWdtZW50cy5zZWdtZW50cywgZXBzaWxvbiwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6IHNlZ21lbnRzLmludmVydGVkXG5cdFx0fTtcblx0fSxcblxuXHQvLyBHZW9KU09OIGNvbnZlcnRlcnNcblx0cG9seWdvbkZyb21HZW9KU09OOiBmdW5jdGlvbihnZW9qc29uKXtcblx0XHRyZXR1cm4gR2VvSlNPTi50b1BvbHlnb24oUG9seUJvb2wsIGdlb2pzb24pO1xuXHR9LFxuXHRwb2x5Z29uVG9HZW9KU09OOiBmdW5jdGlvbihwb2x5KXtcblx0XHRyZXR1cm4gR2VvSlNPTi5mcm9tUG9seWdvbihQb2x5Qm9vbCwgZXBzaWxvbiwgcG9seSk7XG5cdH0sXG5cblx0Ly8gaGVscGVyIGZ1bmN0aW9ucyBmb3IgY29tbW9uIG9wZXJhdGlvbnNcblx0dW5pb246IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3RVbmlvbik7XG5cdH0sXG5cdGludGVyc2VjdDogZnVuY3Rpb24ocG9seTEsIHBvbHkyKXtcblx0XHRyZXR1cm4gb3BlcmF0ZShwb2x5MSwgcG9seTIsIFBvbHlCb29sLnNlbGVjdEludGVyc2VjdCk7XG5cdH0sXG5cdGRpZmZlcmVuY2U6IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3REaWZmZXJlbmNlKTtcblx0fSxcblx0ZGlmZmVyZW5jZVJldjogZnVuY3Rpb24ocG9seTEsIHBvbHkyKXtcblx0XHRyZXR1cm4gb3BlcmF0ZShwb2x5MSwgcG9seTIsIFBvbHlCb29sLnNlbGVjdERpZmZlcmVuY2VSZXYpO1xuXHR9LFxuXHR4b3I6IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3RYb3IpO1xuXHR9XG59O1xuXG5mdW5jdGlvbiBvcGVyYXRlKHBvbHkxLCBwb2x5Miwgc2VsZWN0b3Ipe1xuXHR2YXIgc2VnMSA9IFBvbHlCb29sLnNlZ21lbnRzKHBvbHkxKTtcblx0dmFyIHNlZzIgPSBQb2x5Qm9vbC5zZWdtZW50cyhwb2x5Mik7XG5cdHZhciBjb21iID0gUG9seUJvb2wuY29tYmluZShzZWcxLCBzZWcyKTtcblx0dmFyIHNlZzMgPSBzZWxlY3Rvcihjb21iKTtcblx0cmV0dXJuIFBvbHlCb29sLnBvbHlnb24oc2VnMyk7XG59XG5cbmlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0Jylcblx0d2luZG93LlBvbHlCb29sID0gUG9seUJvb2w7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9seUJvb2w7XG4iLCIvLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gdXNlZCBzdHJpY3RseSBmb3IgbG9nZ2luZyB0aGUgcHJvY2Vzc2luZyBvZiB0aGUgYWxnb3JpdGhtLi4uIG9ubHkgdXNlZnVsIGlmIHlvdSBpbnRlbmQgb25cbi8vIGxvb2tpbmcgdW5kZXIgdGhlIGNvdmVycyAoZm9yIHByZXR0eSBVSSdzIG9yIGRlYnVnZ2luZylcbi8vXG5cbmZ1bmN0aW9uIEJ1aWxkTG9nKCl7XG5cdHZhciBteTtcblx0dmFyIG5leHRTZWdtZW50SWQgPSAwO1xuXHR2YXIgY3VyVmVydCA9IGZhbHNlO1xuXG5cdGZ1bmN0aW9uIHB1c2godHlwZSwgZGF0YSl7XG5cdFx0bXkubGlzdC5wdXNoKHtcblx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhOiBkYXRhID8gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShkYXRhKSkgOiB2b2lkIDBcblx0XHR9KTtcblx0XHRyZXR1cm4gbXk7XG5cdH1cblxuXHRteSA9IHtcblx0XHRsaXN0OiBbXSxcblx0XHRzZWdtZW50SWQ6IGZ1bmN0aW9uKCl7XG5cdFx0XHRyZXR1cm4gbmV4dFNlZ21lbnRJZCsrO1xuXHRcdH0sXG5cdFx0Y2hlY2tJbnRlcnNlY3Rpb246IGZ1bmN0aW9uKHNlZzEsIHNlZzIpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoZWNrJywgeyBzZWcxOiBzZWcxLCBzZWcyOiBzZWcyIH0pO1xuXHRcdH0sXG5cdFx0c2VnbWVudENob3A6IGZ1bmN0aW9uKHNlZywgZW5kKXtcblx0XHRcdHB1c2goJ2Rpdl9zZWcnLCB7IHNlZzogc2VnLCBwdDogZW5kIH0pO1xuXHRcdFx0cmV0dXJuIHB1c2goJ2Nob3AnLCB7IHNlZzogc2VnLCBwdDogZW5kIH0pO1xuXHRcdH0sXG5cdFx0c3RhdHVzUmVtb3ZlOiBmdW5jdGlvbihzZWcpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3BvcF9zZWcnLCB7IHNlZzogc2VnIH0pO1xuXHRcdH0sXG5cdFx0c2VnbWVudFVwZGF0ZTogZnVuY3Rpb24oc2VnKXtcblx0XHRcdHJldHVybiBwdXNoKCdzZWdfdXBkYXRlJywgeyBzZWc6IHNlZyB9KTtcblx0XHR9LFxuXHRcdHNlZ21lbnROZXc6IGZ1bmN0aW9uKHNlZywgcHJpbWFyeSl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnbmV3X3NlZycsIHsgc2VnOiBzZWcsIHByaW1hcnk6IHByaW1hcnkgfSk7XG5cdFx0fSxcblx0XHRzZWdtZW50UmVtb3ZlOiBmdW5jdGlvbihzZWcpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3JlbV9zZWcnLCB7IHNlZzogc2VnIH0pO1xuXHRcdH0sXG5cdFx0dGVtcFN0YXR1czogZnVuY3Rpb24oc2VnLCBhYm92ZSwgYmVsb3cpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3RlbXBfc3RhdHVzJywgeyBzZWc6IHNlZywgYWJvdmU6IGFib3ZlLCBiZWxvdzogYmVsb3cgfSk7XG5cdFx0fSxcblx0XHRyZXdpbmQ6IGZ1bmN0aW9uKHNlZyl7XG5cdFx0XHRyZXR1cm4gcHVzaCgncmV3aW5kJywgeyBzZWc6IHNlZyB9KTtcblx0XHR9LFxuXHRcdHN0YXR1czogZnVuY3Rpb24oc2VnLCBhYm92ZSwgYmVsb3cpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3N0YXR1cycsIHsgc2VnOiBzZWcsIGFib3ZlOiBhYm92ZSwgYmVsb3c6IGJlbG93IH0pO1xuXHRcdH0sXG5cdFx0dmVydDogZnVuY3Rpb24oeCl7XG5cdFx0XHRpZiAoeCA9PT0gY3VyVmVydClcblx0XHRcdFx0cmV0dXJuIG15O1xuXHRcdFx0Y3VyVmVydCA9IHg7XG5cdFx0XHRyZXR1cm4gcHVzaCgndmVydCcsIHsgeDogeCB9KTtcblx0XHR9LFxuXHRcdGxvZzogZnVuY3Rpb24oZGF0YSl7XG5cdFx0XHRpZiAodHlwZW9mIGRhdGEgIT09ICdzdHJpbmcnKVxuXHRcdFx0XHRkYXRhID0gSlNPTi5zdHJpbmdpZnkoZGF0YSwgZmFsc2UsICcgICcpO1xuXHRcdFx0cmV0dXJuIHB1c2goJ2xvZycsIHsgdHh0OiBkYXRhIH0pO1xuXHRcdH0sXG5cdFx0cmVzZXQ6IGZ1bmN0aW9uKCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgncmVzZXQnKTtcblx0XHR9LFxuXHRcdHNlbGVjdGVkOiBmdW5jdGlvbihzZWdzKXtcblx0XHRcdHJldHVybiBwdXNoKCdzZWxlY3RlZCcsIHsgc2Vnczogc2VncyB9KTtcblx0XHR9LFxuXHRcdGNoYWluU3RhcnQ6IGZ1bmN0aW9uKHNlZyl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fc3RhcnQnLCB7IHNlZzogc2VnIH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5SZW1vdmVIZWFkOiBmdW5jdGlvbihpbmRleCwgcHQpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX3JlbV9oZWFkJywgeyBpbmRleDogaW5kZXgsIHB0OiBwdCB9KTtcblx0XHR9LFxuXHRcdGNoYWluUmVtb3ZlVGFpbDogZnVuY3Rpb24oaW5kZXgsIHB0KXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9yZW1fdGFpbCcsIHsgaW5kZXg6IGluZGV4LCBwdDogcHQgfSk7XG5cdFx0fSxcblx0XHRjaGFpbk5ldzogZnVuY3Rpb24ocHQxLCBwdDIpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX25ldycsIHsgcHQxOiBwdDEsIHB0MjogcHQyIH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5NYXRjaDogZnVuY3Rpb24oaW5kZXgpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX21hdGNoJywgeyBpbmRleDogaW5kZXggfSk7XG5cdFx0fSxcblx0XHRjaGFpbkNsb3NlOiBmdW5jdGlvbihpbmRleCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fY2xvc2UnLCB7IGluZGV4OiBpbmRleCB9KTtcblx0XHR9LFxuXHRcdGNoYWluQWRkSGVhZDogZnVuY3Rpb24oaW5kZXgsIHB0KXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9hZGRfaGVhZCcsIHsgaW5kZXg6IGluZGV4LCBwdDogcHQgfSk7XG5cdFx0fSxcblx0XHRjaGFpbkFkZFRhaWw6IGZ1bmN0aW9uKGluZGV4LCBwdCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fYWRkX3RhaWwnLCB7IGluZGV4OiBpbmRleCwgcHQ6IHB0LCB9KTtcblx0XHR9LFxuXHRcdGNoYWluQ29ubmVjdDogZnVuY3Rpb24oaW5kZXgxLCBpbmRleDIpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX2NvbicsIHsgaW5kZXgxOiBpbmRleDEsIGluZGV4MjogaW5kZXgyIH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5SZXZlcnNlOiBmdW5jdGlvbihpbmRleCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fcmV2JywgeyBpbmRleDogaW5kZXggfSk7XG5cdFx0fSxcblx0XHRjaGFpbkpvaW46IGZ1bmN0aW9uKGluZGV4MSwgaW5kZXgyKXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9qb2luJywgeyBpbmRleDE6IGluZGV4MSwgaW5kZXgyOiBpbmRleDIgfSk7XG5cdFx0fSxcblx0XHRkb25lOiBmdW5jdGlvbigpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2RvbmUnKTtcblx0XHR9XG5cdH07XG5cdHJldHVybiBteTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBCdWlsZExvZztcbiIsIi8vIChjKSBDb3B5cmlnaHQgMjAxNiwgU2VhbiBDb25uZWxseSAoQHZvaWRxayksIGh0dHA6Ly9zeW50aGV0aS5jY1xuLy8gTUlUIExpY2Vuc2Vcbi8vIFByb2plY3QgSG9tZTogaHR0cHM6Ly9naXRodWIuY29tL3ZvaWRxay9wb2x5Ym9vbGpzXG5cbi8vXG4vLyBwcm92aWRlcyB0aGUgcmF3IGNvbXB1dGF0aW9uIGZ1bmN0aW9ucyB0aGF0IHRha2VzIGVwc2lsb24gaW50byBhY2NvdW50XG4vL1xuLy8gemVybyBpcyBkZWZpbmVkIHRvIGJlIGJldHdlZW4gKC1lcHNpbG9uLCBlcHNpbG9uKSBleGNsdXNpdmVcbi8vXG5cbmZ1bmN0aW9uIEVwc2lsb24oZXBzKXtcblx0aWYgKHR5cGVvZiBlcHMgIT09ICdudW1iZXInKVxuXHRcdGVwcyA9IDAuMDAwMDAwMDAwMTsgLy8gc2FuZSBkZWZhdWx0PyBzdXJlIHdoeSBub3Rcblx0dmFyIG15ID0ge1xuXHRcdGVwc2lsb246IGZ1bmN0aW9uKHYpe1xuXHRcdFx0aWYgKHR5cGVvZiB2ID09PSAnbnVtYmVyJylcblx0XHRcdFx0ZXBzID0gdjtcblx0XHRcdHJldHVybiBlcHM7XG5cdFx0fSxcblx0XHRwb2ludEFib3ZlT3JPbkxpbmU6IGZ1bmN0aW9uKHB0LCBsZWZ0LCByaWdodCl7XG5cdFx0XHR2YXIgQXggPSBsZWZ0WzBdO1xuXHRcdFx0dmFyIEF5ID0gbGVmdFsxXTtcblx0XHRcdHZhciBCeCA9IHJpZ2h0WzBdO1xuXHRcdFx0dmFyIEJ5ID0gcmlnaHRbMV07XG5cdFx0XHR2YXIgQ3ggPSBwdFswXTtcblx0XHRcdHZhciBDeSA9IHB0WzFdO1xuXHRcdFx0cmV0dXJuIChCeCAtIEF4KSAqIChDeSAtIEF5KSAtIChCeSAtIEF5KSAqIChDeCAtIEF4KSA+PSAtZXBzO1xuXHRcdH0sXG5cdFx0cG9pbnRCZXR3ZWVuOiBmdW5jdGlvbihwLCBsZWZ0LCByaWdodCl7XG5cdFx0XHQvLyBwIG11c3QgYmUgY29sbGluZWFyIHdpdGggbGVmdC0+cmlnaHRcblx0XHRcdC8vIHJldHVybnMgZmFsc2UgaWYgcCA9PSBsZWZ0LCBwID09IHJpZ2h0LCBvciBsZWZ0ID09IHJpZ2h0XG5cdFx0XHR2YXIgZF9weV9seSA9IHBbMV0gLSBsZWZ0WzFdO1xuXHRcdFx0dmFyIGRfcnhfbHggPSByaWdodFswXSAtIGxlZnRbMF07XG5cdFx0XHR2YXIgZF9weF9seCA9IHBbMF0gLSBsZWZ0WzBdO1xuXHRcdFx0dmFyIGRfcnlfbHkgPSByaWdodFsxXSAtIGxlZnRbMV07XG5cblx0XHRcdHZhciBkb3QgPSBkX3B4X2x4ICogZF9yeF9seCArIGRfcHlfbHkgKiBkX3J5X2x5O1xuXHRcdFx0Ly8gaWYgYGRvdGAgaXMgMCwgdGhlbiBgcGAgPT0gYGxlZnRgIG9yIGBsZWZ0YCA9PSBgcmlnaHRgIChyZWplY3QpXG5cdFx0XHQvLyBpZiBgZG90YCBpcyBsZXNzIHRoYW4gMCwgdGhlbiBgcGAgaXMgdG8gdGhlIGxlZnQgb2YgYGxlZnRgIChyZWplY3QpXG5cdFx0XHRpZiAoZG90IDwgZXBzKVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHRcdHZhciBzcWxlbiA9IGRfcnhfbHggKiBkX3J4X2x4ICsgZF9yeV9seSAqIGRfcnlfbHk7XG5cdFx0XHQvLyBpZiBgZG90YCA+IGBzcWxlbmAsIHRoZW4gYHBgIGlzIHRvIHRoZSByaWdodCBvZiBgcmlnaHRgIChyZWplY3QpXG5cdFx0XHQvLyB0aGVyZWZvcmUsIGlmIGBkb3QgLSBzcWxlbmAgaXMgZ3JlYXRlciB0aGFuIDAsIHRoZW4gYHBgIGlzIHRvIHRoZSByaWdodCBvZiBgcmlnaHRgIChyZWplY3QpXG5cdFx0XHRpZiAoZG90IC0gc3FsZW4gPiAtZXBzKVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0sXG5cdFx0cG9pbnRzU2FtZVg6IGZ1bmN0aW9uKHAxLCBwMil7XG5cdFx0XHRyZXR1cm4gTWF0aC5hYnMocDFbMF0gLSBwMlswXSkgPCBlcHM7XG5cdFx0fSxcblx0XHRwb2ludHNTYW1lWTogZnVuY3Rpb24ocDEsIHAyKXtcblx0XHRcdHJldHVybiBNYXRoLmFicyhwMVsxXSAtIHAyWzFdKSA8IGVwcztcblx0XHR9LFxuXHRcdHBvaW50c1NhbWU6IGZ1bmN0aW9uKHAxLCBwMil7XG5cdFx0XHRyZXR1cm4gbXkucG9pbnRzU2FtZVgocDEsIHAyKSAmJiBteS5wb2ludHNTYW1lWShwMSwgcDIpO1xuXHRcdH0sXG5cdFx0cG9pbnRzQ29tcGFyZTogZnVuY3Rpb24ocDEsIHAyKXtcblx0XHRcdC8vIHJldHVybnMgLTEgaWYgcDEgaXMgc21hbGxlciwgMSBpZiBwMiBpcyBzbWFsbGVyLCAwIGlmIGVxdWFsXG5cdFx0XHRpZiAobXkucG9pbnRzU2FtZVgocDEsIHAyKSlcblx0XHRcdFx0cmV0dXJuIG15LnBvaW50c1NhbWVZKHAxLCBwMikgPyAwIDogKHAxWzFdIDwgcDJbMV0gPyAtMSA6IDEpO1xuXHRcdFx0cmV0dXJuIHAxWzBdIDwgcDJbMF0gPyAtMSA6IDE7XG5cdFx0fSxcblx0XHRwb2ludHNDb2xsaW5lYXI6IGZ1bmN0aW9uKHB0MSwgcHQyLCBwdDMpe1xuXHRcdFx0Ly8gZG9lcyBwdDEtPnB0Mi0+cHQzIG1ha2UgYSBzdHJhaWdodCBsaW5lP1xuXHRcdFx0Ly8gZXNzZW50aWFsbHkgdGhpcyBpcyBqdXN0IGNoZWNraW5nIHRvIHNlZSBpZiB0aGUgc2xvcGUocHQxLT5wdDIpID09PSBzbG9wZShwdDItPnB0Mylcblx0XHRcdC8vIGlmIHNsb3BlcyBhcmUgZXF1YWwsIHRoZW4gdGhleSBtdXN0IGJlIGNvbGxpbmVhciwgYmVjYXVzZSB0aGV5IHNoYXJlIHB0MlxuXHRcdFx0dmFyIGR4MSA9IHB0MVswXSAtIHB0MlswXTtcblx0XHRcdHZhciBkeTEgPSBwdDFbMV0gLSBwdDJbMV07XG5cdFx0XHR2YXIgZHgyID0gcHQyWzBdIC0gcHQzWzBdO1xuXHRcdFx0dmFyIGR5MiA9IHB0MlsxXSAtIHB0M1sxXTtcblx0XHRcdHJldHVybiBNYXRoLmFicyhkeDEgKiBkeTIgLSBkeDIgKiBkeTEpIDwgZXBzO1xuXHRcdH0sXG5cdFx0bGluZXNJbnRlcnNlY3Q6IGZ1bmN0aW9uKGEwLCBhMSwgYjAsIGIxKXtcblx0XHRcdC8vIHJldHVybnMgZmFsc2UgaWYgdGhlIGxpbmVzIGFyZSBjb2luY2lkZW50IChlLmcuLCBwYXJhbGxlbCBvciBvbiB0b3Agb2YgZWFjaCBvdGhlcilcblx0XHRcdC8vXG5cdFx0XHQvLyByZXR1cm5zIGFuIG9iamVjdCBpZiB0aGUgbGluZXMgaW50ZXJzZWN0OlxuXHRcdFx0Ly8gICB7XG5cdFx0XHQvLyAgICAgcHQ6IFt4LCB5XSwgICAgd2hlcmUgdGhlIGludGVyc2VjdGlvbiBwb2ludCBpcyBhdFxuXHRcdFx0Ly8gICAgIGFsb25nQTogd2hlcmUgaW50ZXJzZWN0aW9uIHBvaW50IGlzIGFsb25nIEEsXG5cdFx0XHQvLyAgICAgYWxvbmdCOiB3aGVyZSBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgYWxvbmcgQlxuXHRcdFx0Ly8gICB9XG5cdFx0XHQvL1xuXHRcdFx0Ly8gIGFsb25nQSBhbmQgYWxvbmdCIHdpbGwgZWFjaCBiZSBvbmUgb2Y6IC0yLCAtMSwgMCwgMSwgMlxuXHRcdFx0Ly9cblx0XHRcdC8vICB3aXRoIHRoZSBmb2xsb3dpbmcgbWVhbmluZzpcblx0XHRcdC8vXG5cdFx0XHQvLyAgICAtMiAgIGludGVyc2VjdGlvbiBwb2ludCBpcyBiZWZvcmUgc2VnbWVudCdzIGZpcnN0IHBvaW50XG5cdFx0XHQvLyAgICAtMSAgIGludGVyc2VjdGlvbiBwb2ludCBpcyBkaXJlY3RseSBvbiBzZWdtZW50J3MgZmlyc3QgcG9pbnRcblx0XHRcdC8vICAgICAwICAgaW50ZXJzZWN0aW9uIHBvaW50IGlzIGJldHdlZW4gc2VnbWVudCdzIGZpcnN0IGFuZCBzZWNvbmQgcG9pbnRzIChleGNsdXNpdmUpXG5cdFx0XHQvLyAgICAgMSAgIGludGVyc2VjdGlvbiBwb2ludCBpcyBkaXJlY3RseSBvbiBzZWdtZW50J3Mgc2Vjb25kIHBvaW50XG5cdFx0XHQvLyAgICAgMiAgIGludGVyc2VjdGlvbiBwb2ludCBpcyBhZnRlciBzZWdtZW50J3Mgc2Vjb25kIHBvaW50XG5cdFx0XHR2YXIgYWR4ID0gYTFbMF0gLSBhMFswXTtcblx0XHRcdHZhciBhZHkgPSBhMVsxXSAtIGEwWzFdO1xuXHRcdFx0dmFyIGJkeCA9IGIxWzBdIC0gYjBbMF07XG5cdFx0XHR2YXIgYmR5ID0gYjFbMV0gLSBiMFsxXTtcblxuXHRcdFx0dmFyIGF4YiA9IGFkeCAqIGJkeSAtIGFkeSAqIGJkeDtcblx0XHRcdGlmIChNYXRoLmFicyhheGIpIDwgZXBzKVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7IC8vIGxpbmVzIGFyZSBjb2luY2lkZW50XG5cblx0XHRcdHZhciBkeCA9IGEwWzBdIC0gYjBbMF07XG5cdFx0XHR2YXIgZHkgPSBhMFsxXSAtIGIwWzFdO1xuXG5cdFx0XHR2YXIgQSA9IChiZHggKiBkeSAtIGJkeSAqIGR4KSAvIGF4Yjtcblx0XHRcdHZhciBCID0gKGFkeCAqIGR5IC0gYWR5ICogZHgpIC8gYXhiO1xuXG5cdFx0XHR2YXIgcmV0ID0ge1xuXHRcdFx0XHRhbG9uZ0E6IDAsXG5cdFx0XHRcdGFsb25nQjogMCxcblx0XHRcdFx0cHQ6IFtcblx0XHRcdFx0XHRhMFswXSArIEEgKiBhZHgsXG5cdFx0XHRcdFx0YTBbMV0gKyBBICogYWR5XG5cdFx0XHRcdF1cblx0XHRcdH07XG5cblx0XHRcdC8vIGNhdGVnb3JpemUgd2hlcmUgaW50ZXJzZWN0aW9uIHBvaW50IGlzIGFsb25nIEEgYW5kIEJcblxuXHRcdFx0aWYgKEEgPD0gLWVwcylcblx0XHRcdFx0cmV0LmFsb25nQSA9IC0yO1xuXHRcdFx0ZWxzZSBpZiAoQSA8IGVwcylcblx0XHRcdFx0cmV0LmFsb25nQSA9IC0xO1xuXHRcdFx0ZWxzZSBpZiAoQSAtIDEgPD0gLWVwcylcblx0XHRcdFx0cmV0LmFsb25nQSA9IDA7XG5cdFx0XHRlbHNlIGlmIChBIC0gMSA8IGVwcylcblx0XHRcdFx0cmV0LmFsb25nQSA9IDE7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJldC5hbG9uZ0EgPSAyO1xuXG5cdFx0XHRpZiAoQiA8PSAtZXBzKVxuXHRcdFx0XHRyZXQuYWxvbmdCID0gLTI7XG5cdFx0XHRlbHNlIGlmIChCIDwgZXBzKVxuXHRcdFx0XHRyZXQuYWxvbmdCID0gLTE7XG5cdFx0XHRlbHNlIGlmIChCIC0gMSA8PSAtZXBzKVxuXHRcdFx0XHRyZXQuYWxvbmdCID0gMDtcblx0XHRcdGVsc2UgaWYgKEIgLSAxIDwgZXBzKVxuXHRcdFx0XHRyZXQuYWxvbmdCID0gMTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0cmV0LmFsb25nQiA9IDI7XG5cblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fSxcblx0XHRwb2ludEluc2lkZVJlZ2lvbjogZnVuY3Rpb24ocHQsIHJlZ2lvbil7XG5cdFx0XHR2YXIgeCA9IHB0WzBdO1xuXHRcdFx0dmFyIHkgPSBwdFsxXTtcblx0XHRcdHZhciBsYXN0X3ggPSByZWdpb25bcmVnaW9uLmxlbmd0aCAtIDFdWzBdO1xuXHRcdFx0dmFyIGxhc3RfeSA9IHJlZ2lvbltyZWdpb24ubGVuZ3RoIC0gMV1bMV07XG5cdFx0XHR2YXIgaW5zaWRlID0gZmFsc2U7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lvbi5sZW5ndGg7IGkrKyl7XG5cdFx0XHRcdHZhciBjdXJyX3ggPSByZWdpb25baV1bMF07XG5cdFx0XHRcdHZhciBjdXJyX3kgPSByZWdpb25baV1bMV07XG5cblx0XHRcdFx0Ly8gaWYgeSBpcyBiZXR3ZWVuIGN1cnJfeSBhbmQgbGFzdF95LCBhbmRcblx0XHRcdFx0Ly8geCBpcyB0byB0aGUgcmlnaHQgb2YgdGhlIGJvdW5kYXJ5IGNyZWF0ZWQgYnkgdGhlIGxpbmVcblx0XHRcdFx0aWYgKChjdXJyX3kgLSB5ID4gZXBzKSAhPSAobGFzdF95IC0geSA+IGVwcykgJiZcblx0XHRcdFx0XHQobGFzdF94IC0gY3Vycl94KSAqICh5IC0gY3Vycl95KSAvIChsYXN0X3kgLSBjdXJyX3kpICsgY3Vycl94IC0geCA+IGVwcylcblx0XHRcdFx0XHRpbnNpZGUgPSAhaW5zaWRlXG5cblx0XHRcdFx0bGFzdF94ID0gY3Vycl94O1xuXHRcdFx0XHRsYXN0X3kgPSBjdXJyX3k7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gaW5zaWRlO1xuXHRcdH1cblx0fTtcblx0cmV0dXJuIG15O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEVwc2lsb247XG4iLCIvLyAoYykgQ29weXJpZ2h0IDIwMTcsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gY29udmVydCBiZXR3ZWVuIFBvbHlCb29sIHBvbHlnb24gZm9ybWF0IGFuZCBHZW9KU09OIGZvcm1hdHMgKFBvbHlnb24gYW5kIE11bHRpUG9seWdvbilcbi8vXG5cbnZhciBHZW9KU09OID0ge1xuXHQvLyBjb252ZXJ0IGEgR2VvSlNPTiBvYmplY3QgdG8gYSBQb2x5Qm9vbCBwb2x5Z29uXG5cdHRvUG9seWdvbjogZnVuY3Rpb24oUG9seUJvb2wsIGdlb2pzb24pe1xuXG5cdFx0Ly8gY29udmVydHMgbGlzdCBvZiBMaW5lU3RyaW5nJ3MgdG8gc2VnbWVudHNcblx0XHRmdW5jdGlvbiBHZW9Qb2x5KGNvb3Jkcyl7XG5cdFx0XHQvLyBjaGVjayBmb3IgZW1wdHkgY29vcmRzXG5cdFx0XHRpZiAoY29vcmRzLmxlbmd0aCA8PSAwKVxuXHRcdFx0XHRyZXR1cm4gUG9seUJvb2wuc2VnbWVudHMoeyBpbnZlcnRlZDogZmFsc2UsIHJlZ2lvbnM6IFtdIH0pO1xuXG5cdFx0XHQvLyBjb252ZXJ0IExpbmVTdHJpbmcgdG8gc2VnbWVudHNcblx0XHRcdGZ1bmN0aW9uIExpbmVTdHJpbmcobHMpe1xuXHRcdFx0XHQvLyByZW1vdmUgdGFpbCB3aGljaCBzaG91bGQgYmUgdGhlIHNhbWUgYXMgaGVhZFxuXHRcdFx0XHR2YXIgcmVnID0gbHMuc2xpY2UoMCwgbHMubGVuZ3RoIC0gMSk7XG5cdFx0XHRcdHJldHVybiBQb2x5Qm9vbC5zZWdtZW50cyh7IGludmVydGVkOiBmYWxzZSwgcmVnaW9uczogW3JlZ10gfSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIHRoZSBmaXJzdCBMaW5lU3RyaW5nIGlzIGNvbnNpZGVyZWQgdGhlIG91dHNpZGVcblx0XHRcdHZhciBvdXQgPSBMaW5lU3RyaW5nKGNvb3Jkc1swXSk7XG5cblx0XHRcdC8vIHRoZSByZXN0IG9mIHRoZSBMaW5lU3RyaW5ncyBhcmUgY29uc2lkZXJlZCBpbnRlcmlvciBob2xlcywgc28gc3VidHJhY3QgdGhlbSBmcm9tIHRoZVxuXHRcdFx0Ly8gY3VycmVudCByZXN1bHRcblx0XHRcdGZvciAodmFyIGkgPSAxOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKVxuXHRcdFx0XHRvdXQgPSBQb2x5Qm9vbC5zZWxlY3REaWZmZXJlbmNlKFBvbHlCb29sLmNvbWJpbmUob3V0LCBMaW5lU3RyaW5nKGNvb3Jkc1tpXSkpKTtcblxuXHRcdFx0cmV0dXJuIG91dDtcblx0XHR9XG5cblx0XHRpZiAoZ2VvanNvbi50eXBlID09PSAnUG9seWdvbicpe1xuXHRcdFx0Ly8gc2luZ2xlIHBvbHlnb24sIHNvIGp1c3QgY29udmVydCBpdCBhbmQgd2UncmUgZG9uZVxuXHRcdFx0cmV0dXJuIFBvbHlCb29sLnBvbHlnb24oR2VvUG9seShnZW9qc29uLmNvb3JkaW5hdGVzKSk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKGdlb2pzb24udHlwZSA9PT0gJ011bHRpUG9seWdvbicpe1xuXHRcdFx0Ly8gbXVsdGlwbGUgcG9seWdvbnMsIHNvIHVuaW9uIGFsbCB0aGUgcG9seWdvbnMgdG9nZXRoZXJcblx0XHRcdHZhciBvdXQgPSBQb2x5Qm9vbC5zZWdtZW50cyh7IGludmVydGVkOiBmYWxzZSwgcmVnaW9uczogW10gfSk7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGdlb2pzb24uY29vcmRpbmF0ZXMubGVuZ3RoOyBpKyspXG5cdFx0XHRcdG91dCA9IFBvbHlCb29sLnNlbGVjdFVuaW9uKFBvbHlCb29sLmNvbWJpbmUob3V0LCBHZW9Qb2x5KGdlb2pzb24uY29vcmRpbmF0ZXNbaV0pKSk7XG5cdFx0XHRyZXR1cm4gUG9seUJvb2wucG9seWdvbihvdXQpO1xuXHRcdH1cblx0XHR0aHJvdyBuZXcgRXJyb3IoJ1BvbHlCb29sOiBDYW5ub3QgY29udmVydCBHZW9KU09OIG9iamVjdCB0byBQb2x5Qm9vbCBwb2x5Z29uJyk7XG5cdH0sXG5cblx0Ly8gY29udmVydCBhIFBvbHlCb29sIHBvbHlnb24gdG8gYSBHZW9KU09OIG9iamVjdFxuXHRmcm9tUG9seWdvbjogZnVuY3Rpb24oUG9seUJvb2wsIGVwcywgcG9seSl7XG5cdFx0Ly8gbWFrZSBzdXJlIG91dCBwb2x5Z29uIGlzIGNsZWFuXG5cdFx0cG9seSA9IFBvbHlCb29sLnBvbHlnb24oUG9seUJvb2wuc2VnbWVudHMocG9seSkpO1xuXG5cdFx0Ly8gdGVzdCBpZiByMSBpcyBpbnNpZGUgcjJcblx0XHRmdW5jdGlvbiByZWdpb25JbnNpZGVSZWdpb24ocjEsIHIyKXtcblx0XHRcdC8vIHdlJ3JlIGd1YXJhbnRlZWQgbm8gbGluZXMgaW50ZXJzZWN0IChiZWNhdXNlIHRoZSBwb2x5Z29uIGlzIGNsZWFuKSwgYnV0IGEgdmVydGV4XG5cdFx0XHQvLyBjb3VsZCBiZSBvbiB0aGUgZWRnZSAtLSBzbyB3ZSBqdXN0IGF2ZXJhZ2UgcHRbMF0gYW5kIHB0WzFdIHRvIHByb2R1Y2UgYSBwb2ludCBvbiB0aGVcblx0XHRcdC8vIGVkZ2Ugb2YgdGhlIGZpcnN0IGxpbmUsIHdoaWNoIGNhbm5vdCBiZSBvbiBhbiBlZGdlXG5cdFx0XHRyZXR1cm4gZXBzLnBvaW50SW5zaWRlUmVnaW9uKFtcblx0XHRcdFx0KHIxWzBdWzBdICsgcjFbMV1bMF0pICogMC41LFxuXHRcdFx0XHQocjFbMF1bMV0gKyByMVsxXVsxXSkgKiAwLjVcblx0XHRcdF0sIHIyKTtcblx0XHR9XG5cblx0XHQvLyBjYWxjdWxhdGUgaW5zaWRlIGhlaXJhcmNoeVxuXHRcdC8vXG5cdFx0Ly8gIF9fX19fX19fX19fX19fX19fX19fXyAgIF9fX19fX18gICAgcm9vdHMgLT4gQSAgICAgICAtPiBGXG5cdFx0Ly8gfCAgICAgICAgICBBICAgICAgICAgIHwgfCAgIEYgICB8ICAgICAgICAgICAgfCAgICAgICAgICB8XG5cdFx0Ly8gfCAgX19fX19fXyAgIF9fX19fX18gIHwgfCAgX19fICB8ICAgICAgICAgICAgKy0tIEIgICAgICArLS0gR1xuXHRcdC8vIHwgfCAgIEIgICB8IHwgICBDICAgfCB8IHwgfCAgIHwgfCAgICAgICAgICAgIHwgICB8XG5cdFx0Ly8gfCB8ICBfX18gIHwgfCAgX19fICB8IHwgfCB8ICAgfCB8ICAgICAgICAgICAgfCAgICstLSBEXG5cdFx0Ly8gfCB8IHwgRCB8IHwgfCB8IEUgfCB8IHwgfCB8IEcgfCB8ICAgICAgICAgICAgfFxuXHRcdC8vIHwgfCB8X19ffCB8IHwgfF9fX3wgfCB8IHwgfCAgIHwgfCAgICAgICAgICAgICstLSBDXG5cdFx0Ly8gfCB8X19fX19fX3wgfF9fX19fX198IHwgfCB8X19ffCB8ICAgICAgICAgICAgICAgIHxcblx0XHQvLyB8X19fX19fX19fX19fX19fX19fX19ffCB8X19fX19fX3wgICAgICAgICAgICAgICAgKy0tIEVcblxuXHRcdGZ1bmN0aW9uIG5ld05vZGUocmVnaW9uKXtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdHJlZ2lvbjogcmVnaW9uLFxuXHRcdFx0XHRjaGlsZHJlbjogW11cblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0dmFyIHJvb3RzID0gbmV3Tm9kZShudWxsKTtcblxuXHRcdGZ1bmN0aW9uIGFkZENoaWxkKHJvb3QsIHJlZ2lvbil7XG5cdFx0XHQvLyBmaXJzdCBjaGVjayBpZiB3ZSdyZSBpbnNpZGUgYW55IGNoaWxkcmVuXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJvb3QuY2hpbGRyZW4ubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHR2YXIgY2hpbGQgPSByb290LmNoaWxkcmVuW2ldO1xuXHRcdFx0XHRpZiAocmVnaW9uSW5zaWRlUmVnaW9uKHJlZ2lvbiwgY2hpbGQucmVnaW9uKSl7XG5cdFx0XHRcdFx0Ly8gd2UgYXJlLCBzbyBpbnNlcnQgaW5zaWRlIHRoZW0gaW5zdGVhZFxuXHRcdFx0XHRcdGFkZENoaWxkKGNoaWxkLCByZWdpb24pO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBub3QgaW5zaWRlIGFueSBjaGlsZHJlbiwgc28gY2hlY2sgdG8gc2VlIGlmIGFueSBjaGlsZHJlbiBhcmUgaW5zaWRlIHVzXG5cdFx0XHR2YXIgbm9kZSA9IG5ld05vZGUocmVnaW9uKTtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcm9vdC5jaGlsZHJlbi5sZW5ndGg7IGkrKyl7XG5cdFx0XHRcdHZhciBjaGlsZCA9IHJvb3QuY2hpbGRyZW5baV07XG5cdFx0XHRcdGlmIChyZWdpb25JbnNpZGVSZWdpb24oY2hpbGQucmVnaW9uLCByZWdpb24pKXtcblx0XHRcdFx0XHQvLyBvb3BzLi4uIG1vdmUgdGhlIGNoaWxkIGJlbmVhdGggdXMsIGFuZCByZW1vdmUgdGhlbSBmcm9tIHJvb3Rcblx0XHRcdFx0XHRub2RlLmNoaWxkcmVuLnB1c2goY2hpbGQpO1xuXHRcdFx0XHRcdHJvb3QuY2hpbGRyZW4uc3BsaWNlKGksIDEpO1xuXHRcdFx0XHRcdGktLTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBub3cgd2UgY2FuIGFkZCBvdXJzZWx2ZXNcblx0XHRcdHJvb3QuY2hpbGRyZW4ucHVzaChub2RlKTtcblx0XHR9XG5cblx0XHQvLyBhZGQgYWxsIHJlZ2lvbnMgdG8gdGhlIHJvb3Rcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHBvbHkucmVnaW9ucy5sZW5ndGg7IGkrKyl7XG5cdFx0XHR2YXIgcmVnaW9uID0gcG9seS5yZWdpb25zW2ldO1xuXHRcdFx0aWYgKHJlZ2lvbi5sZW5ndGggPCAzKSAvLyByZWdpb25zIG11c3QgaGF2ZSBhdCBsZWFzdCAzIHBvaW50cyAoc2FuaXR5IGNoZWNrKVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdGFkZENoaWxkKHJvb3RzLCByZWdpb24pO1xuXHRcdH1cblxuXHRcdC8vIHdpdGggb3VyIGhlaXJhcmNoeSwgd2UgY2FuIGRpc3Rpbmd1aXNoIGJldHdlZW4gZXh0ZXJpb3IgYm9yZGVycywgYW5kIGludGVyaW9yIGhvbGVzXG5cdFx0Ly8gdGhlIHJvb3Qgbm9kZXMgYXJlIGV4dGVyaW9yLCBjaGlsZHJlbiBhcmUgaW50ZXJpb3IsIGNoaWxkcmVuJ3MgY2hpbGRyZW4gYXJlIGV4dGVyaW9yLFxuXHRcdC8vIGNoaWxkcmVuJ3MgY2hpbGRyZW4ncyBjaGlsZHJlbiBhcmUgaW50ZXJpb3IsIGV0Y1xuXG5cdFx0Ly8gd2hpbGUgd2UncmUgYXQgaXQsIGV4dGVyaW9ycyBhcmUgY291bnRlci1jbG9ja3dpc2UsIGFuZCBpbnRlcmlvcnMgYXJlIGNsb2Nrd2lzZVxuXG5cdFx0ZnVuY3Rpb24gZm9yY2VXaW5kaW5nKHJlZ2lvbiwgY2xvY2t3aXNlKXtcblx0XHRcdC8vIGZpcnN0LCBzZWUgaWYgd2UncmUgY2xvY2t3aXNlIG9yIGNvdW50ZXItY2xvY2t3aXNlXG5cdFx0XHQvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TaG9lbGFjZV9mb3JtdWxhXG5cdFx0XHR2YXIgd2luZGluZyA9IDA7XG5cdFx0XHR2YXIgbGFzdF94ID0gcmVnaW9uW3JlZ2lvbi5sZW5ndGggLSAxXVswXTtcblx0XHRcdHZhciBsYXN0X3kgPSByZWdpb25bcmVnaW9uLmxlbmd0aCAtIDFdWzFdO1xuXHRcdFx0dmFyIGNvcHkgPSBbXTtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcmVnaW9uLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0dmFyIGN1cnJfeCA9IHJlZ2lvbltpXVswXTtcblx0XHRcdFx0dmFyIGN1cnJfeSA9IHJlZ2lvbltpXVsxXTtcblx0XHRcdFx0Y29weS5wdXNoKFtjdXJyX3gsIGN1cnJfeV0pOyAvLyBjcmVhdGUgYSBjb3B5IHdoaWxlIHdlJ3JlIGF0IGl0XG5cdFx0XHRcdHdpbmRpbmcgKz0gY3Vycl95ICogbGFzdF94IC0gY3Vycl94ICogbGFzdF95O1xuXHRcdFx0XHRsYXN0X3ggPSBjdXJyX3g7XG5cdFx0XHRcdGxhc3RfeSA9IGN1cnJfeTtcblx0XHRcdH1cblx0XHRcdC8vIHRoaXMgYXNzdW1lcyBDYXJ0ZXNpYW4gY29vcmRpbmF0ZXMgKFkgaXMgcG9zaXRpdmUgZ29pbmcgdXApXG5cdFx0XHR2YXIgaXNjbG9ja3dpc2UgPSB3aW5kaW5nIDwgMDtcblx0XHRcdGlmIChpc2Nsb2Nrd2lzZSAhPT0gY2xvY2t3aXNlKVxuXHRcdFx0XHRjb3B5LnJldmVyc2UoKTtcblx0XHRcdC8vIHdoaWxlIHdlJ3JlIGhlcmUsIHRoZSBsYXN0IHBvaW50IG11c3QgYmUgdGhlIGZpcnN0IHBvaW50Li4uXG5cdFx0XHRjb3B5LnB1c2goW2NvcHlbMF1bMF0sIGNvcHlbMF1bMV1dKTtcblx0XHRcdHJldHVybiBjb3B5O1xuXHRcdH1cblxuXHRcdHZhciBnZW9wb2x5cyA9IFtdO1xuXG5cdFx0ZnVuY3Rpb24gYWRkRXh0ZXJpb3Iobm9kZSl7XG5cdFx0XHR2YXIgcG9seSA9IFtmb3JjZVdpbmRpbmcobm9kZS5yZWdpb24sIGZhbHNlKV07XG5cdFx0XHRnZW9wb2x5cy5wdXNoKHBvbHkpO1xuXHRcdFx0Ly8gY2hpbGRyZW4gb2YgZXh0ZXJpb3JzIGFyZSBpbnRlcmlvclxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKVxuXHRcdFx0XHRwb2x5LnB1c2goZ2V0SW50ZXJpb3Iobm9kZS5jaGlsZHJlbltpXSkpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGdldEludGVyaW9yKG5vZGUpe1xuXHRcdFx0Ly8gY2hpbGRyZW4gb2YgaW50ZXJpb3JzIGFyZSBleHRlcmlvclxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKVxuXHRcdFx0XHRhZGRFeHRlcmlvcihub2RlLmNoaWxkcmVuW2ldKTtcblx0XHRcdC8vIHJldHVybiB0aGUgY2xvY2t3aXNlIGludGVyaW9yXG5cdFx0XHRyZXR1cm4gZm9yY2VXaW5kaW5nKG5vZGUucmVnaW9uLCB0cnVlKTtcblx0XHR9XG5cblx0XHQvLyByb290IG5vZGVzIGFyZSBleHRlcmlvclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcm9vdHMuY2hpbGRyZW4ubGVuZ3RoOyBpKyspXG5cdFx0XHRhZGRFeHRlcmlvcihyb290cy5jaGlsZHJlbltpXSk7XG5cblx0XHQvLyBsYXN0bHksIGNvbnN0cnVjdCB0aGUgYXBwcm9ycHJpYXRlIEdlb0pTT04gb2JqZWN0XG5cblx0XHRpZiAoZ2VvcG9seXMubGVuZ3RoIDw9IDApIC8vIGVtcHR5IEdlb0pTT04gUG9seWdvblxuXHRcdFx0cmV0dXJuIHsgdHlwZTogJ1BvbHlnb24nLCBjb29yZGluYXRlczogW10gfTtcblx0XHRpZiAoZ2VvcG9seXMubGVuZ3RoID09IDEpIC8vIHVzZSBhIEdlb0pTT04gUG9seWdvblxuXHRcdFx0cmV0dXJuIHsgdHlwZTogJ1BvbHlnb24nLCBjb29yZGluYXRlczogZ2VvcG9seXNbMF0gfTtcblx0XHRyZXR1cm4geyAvLyBvdGhlcndpc2UsIHVzZSBhIEdlb0pTT04gTXVsdGlQb2x5Z29uXG5cdFx0XHR0eXBlOiAnTXVsdGlQb2x5Z29uJyxcblx0XHRcdGNvb3JkaW5hdGVzOiBnZW9wb2x5c1xuXHRcdH07XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gR2VvSlNPTjtcbiIsIi8vIChjKSBDb3B5cmlnaHQgMjAxNiwgU2VhbiBDb25uZWxseSAoQHZvaWRxayksIGh0dHA6Ly9zeW50aGV0aS5jY1xuLy8gTUlUIExpY2Vuc2Vcbi8vIFByb2plY3QgSG9tZTogaHR0cHM6Ly9naXRodWIuY29tL3ZvaWRxay9wb2x5Ym9vbGpzXG5cbi8vXG4vLyB0aGlzIGlzIHRoZSBjb3JlIHdvcmstaG9yc2Vcbi8vXG5cbnZhciBMaW5rZWRMaXN0ID0gcmVxdWlyZSgnLi9saW5rZWQtbGlzdCcpO1xuXG5mdW5jdGlvbiBJbnRlcnNlY3RlcihzZWxmSW50ZXJzZWN0aW9uLCBlcHMsIGJ1aWxkTG9nKXtcblx0Ly8gc2VsZkludGVyc2VjdGlvbiBpcyB0cnVlL2ZhbHNlIGRlcGVuZGluZyBvbiB0aGUgcGhhc2Ugb2YgdGhlIG92ZXJhbGwgYWxnb3JpdGhtXG5cblx0Ly9cblx0Ly8gc2VnbWVudCBjcmVhdGlvblxuXHQvL1xuXG5cdGZ1bmN0aW9uIHNlZ21lbnROZXcoc3RhcnQsIGVuZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGlkOiBidWlsZExvZyA/IGJ1aWxkTG9nLnNlZ21lbnRJZCgpIDogLTEsXG5cdFx0XHRzdGFydDogc3RhcnQsXG5cdFx0XHRlbmQ6IGVuZCxcblx0XHRcdG15RmlsbDoge1xuXHRcdFx0XHRhYm92ZTogbnVsbCwgLy8gaXMgdGhlcmUgZmlsbCBhYm92ZSB1cz9cblx0XHRcdFx0YmVsb3c6IG51bGwgIC8vIGlzIHRoZXJlIGZpbGwgYmVsb3cgdXM/XG5cdFx0XHR9LFxuXHRcdFx0b3RoZXJGaWxsOiBudWxsXG5cdFx0fTtcblx0fVxuXG5cdGZ1bmN0aW9uIHNlZ21lbnRDb3B5KHN0YXJ0LCBlbmQsIHNlZyl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGlkOiBidWlsZExvZyA/IGJ1aWxkTG9nLnNlZ21lbnRJZCgpIDogLTEsXG5cdFx0XHRzdGFydDogc3RhcnQsXG5cdFx0XHRlbmQ6IGVuZCxcblx0XHRcdG15RmlsbDoge1xuXHRcdFx0XHRhYm92ZTogc2VnLm15RmlsbC5hYm92ZSxcblx0XHRcdFx0YmVsb3c6IHNlZy5teUZpbGwuYmVsb3dcblx0XHRcdH0sXG5cdFx0XHRvdGhlckZpbGw6IG51bGxcblx0XHR9O1xuXHR9XG5cblx0Ly9cblx0Ly8gZXZlbnQgbG9naWNcblx0Ly9cblxuXHR2YXIgZXZlbnRfcm9vdCA9IExpbmtlZExpc3QuY3JlYXRlKCk7XG5cblx0ZnVuY3Rpb24gZXZlbnRDb21wYXJlKHAxX2lzU3RhcnQsIHAxXzEsIHAxXzIsIHAyX2lzU3RhcnQsIHAyXzEsIHAyXzIpe1xuXHRcdC8vIGNvbXBhcmUgdGhlIHNlbGVjdGVkIHBvaW50cyBmaXJzdFxuXHRcdHZhciBjb21wID0gZXBzLnBvaW50c0NvbXBhcmUocDFfMSwgcDJfMSk7XG5cdFx0aWYgKGNvbXAgIT09IDApXG5cdFx0XHRyZXR1cm4gY29tcDtcblx0XHQvLyB0aGUgc2VsZWN0ZWQgcG9pbnRzIGFyZSB0aGUgc2FtZVxuXG5cdFx0aWYgKGVwcy5wb2ludHNTYW1lKHAxXzIsIHAyXzIpKSAvLyBpZiB0aGUgbm9uLXNlbGVjdGVkIHBvaW50cyBhcmUgdGhlIHNhbWUgdG9vLi4uXG5cdFx0XHRyZXR1cm4gMDsgLy8gdGhlbiB0aGUgc2VnbWVudHMgYXJlIGVxdWFsXG5cblx0XHRpZiAocDFfaXNTdGFydCAhPT0gcDJfaXNTdGFydCkgLy8gaWYgb25lIGlzIGEgc3RhcnQgYW5kIHRoZSBvdGhlciBpc24ndC4uLlxuXHRcdFx0cmV0dXJuIHAxX2lzU3RhcnQgPyAxIDogLTE7IC8vIGZhdm9yIHRoZSBvbmUgdGhhdCBpc24ndCB0aGUgc3RhcnRcblxuXHRcdC8vIG90aGVyd2lzZSwgd2UnbGwgaGF2ZSB0byBjYWxjdWxhdGUgd2hpY2ggb25lIGlzIGJlbG93IHRoZSBvdGhlciBtYW51YWxseVxuXHRcdHJldHVybiBlcHMucG9pbnRBYm92ZU9yT25MaW5lKHAxXzIsXG5cdFx0XHRwMl9pc1N0YXJ0ID8gcDJfMSA6IHAyXzIsIC8vIG9yZGVyIG1hdHRlcnNcblx0XHRcdHAyX2lzU3RhcnQgPyBwMl8yIDogcDJfMVxuXHRcdCkgPyAxIDogLTE7XG5cdH1cblxuXHRmdW5jdGlvbiBldmVudEFkZChldiwgb3RoZXJfcHQpe1xuXHRcdGV2ZW50X3Jvb3QuaW5zZXJ0QmVmb3JlKGV2LCBmdW5jdGlvbihoZXJlKXtcblx0XHRcdC8vIHNob3VsZCBldiBiZSBpbnNlcnRlZCBiZWZvcmUgaGVyZT9cblx0XHRcdHZhciBjb21wID0gZXZlbnRDb21wYXJlKFxuXHRcdFx0XHRldiAgLmlzU3RhcnQsIGV2ICAucHQsICAgICAgb3RoZXJfcHQsXG5cdFx0XHRcdGhlcmUuaXNTdGFydCwgaGVyZS5wdCwgaGVyZS5vdGhlci5wdFxuXHRcdFx0KTtcblx0XHRcdHJldHVybiBjb21wIDwgMDtcblx0XHR9KTtcblx0fVxuXG5cdGZ1bmN0aW9uIGV2ZW50QWRkU2VnbWVudFN0YXJ0KHNlZywgcHJpbWFyeSl7XG5cdFx0dmFyIGV2X3N0YXJ0ID0gTGlua2VkTGlzdC5ub2RlKHtcblx0XHRcdGlzU3RhcnQ6IHRydWUsXG5cdFx0XHRwdDogc2VnLnN0YXJ0LFxuXHRcdFx0c2VnOiBzZWcsXG5cdFx0XHRwcmltYXJ5OiBwcmltYXJ5LFxuXHRcdFx0b3RoZXI6IG51bGwsXG5cdFx0XHRzdGF0dXM6IG51bGxcblx0XHR9KTtcblx0XHRldmVudEFkZChldl9zdGFydCwgc2VnLmVuZCk7XG5cdFx0cmV0dXJuIGV2X3N0YXJ0O1xuXHR9XG5cblx0ZnVuY3Rpb24gZXZlbnRBZGRTZWdtZW50RW5kKGV2X3N0YXJ0LCBzZWcsIHByaW1hcnkpe1xuXHRcdHZhciBldl9lbmQgPSBMaW5rZWRMaXN0Lm5vZGUoe1xuXHRcdFx0aXNTdGFydDogZmFsc2UsXG5cdFx0XHRwdDogc2VnLmVuZCxcblx0XHRcdHNlZzogc2VnLFxuXHRcdFx0cHJpbWFyeTogcHJpbWFyeSxcblx0XHRcdG90aGVyOiBldl9zdGFydCxcblx0XHRcdHN0YXR1czogbnVsbFxuXHRcdH0pO1xuXHRcdGV2X3N0YXJ0Lm90aGVyID0gZXZfZW5kO1xuXHRcdGV2ZW50QWRkKGV2X2VuZCwgZXZfc3RhcnQucHQpO1xuXHR9XG5cblx0ZnVuY3Rpb24gZXZlbnRBZGRTZWdtZW50KHNlZywgcHJpbWFyeSl7XG5cdFx0dmFyIGV2X3N0YXJ0ID0gZXZlbnRBZGRTZWdtZW50U3RhcnQoc2VnLCBwcmltYXJ5KTtcblx0XHRldmVudEFkZFNlZ21lbnRFbmQoZXZfc3RhcnQsIHNlZywgcHJpbWFyeSk7XG5cdFx0cmV0dXJuIGV2X3N0YXJ0O1xuXHR9XG5cblx0ZnVuY3Rpb24gZXZlbnRVcGRhdGVFbmQoZXYsIGVuZCl7XG5cdFx0Ly8gc2xpZGVzIGFuIGVuZCBiYWNrd2FyZHNcblx0XHQvLyAgIChzdGFydCktLS0tLS0tLS0tLS0oZW5kKSAgICB0bzpcblx0XHQvLyAgIChzdGFydCktLS0oZW5kKVxuXG5cdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0YnVpbGRMb2cuc2VnbWVudENob3AoZXYuc2VnLCBlbmQpO1xuXG5cdFx0ZXYub3RoZXIucmVtb3ZlKCk7XG5cdFx0ZXYuc2VnLmVuZCA9IGVuZDtcblx0XHRldi5vdGhlci5wdCA9IGVuZDtcblx0XHRldmVudEFkZChldi5vdGhlciwgZXYucHQpO1xuXHR9XG5cblx0ZnVuY3Rpb24gZXZlbnREaXZpZGUoZXYsIHB0KXtcblx0XHR2YXIgbnMgPSBzZWdtZW50Q29weShwdCwgZXYuc2VnLmVuZCwgZXYuc2VnKTtcblx0XHRldmVudFVwZGF0ZUVuZChldiwgcHQpO1xuXHRcdHJldHVybiBldmVudEFkZFNlZ21lbnQobnMsIGV2LnByaW1hcnkpO1xuXHR9XG5cblx0ZnVuY3Rpb24gY2FsY3VsYXRlKHByaW1hcnlQb2x5SW52ZXJ0ZWQsIHNlY29uZGFyeVBvbHlJbnZlcnRlZCl7XG5cdFx0Ly8gaWYgc2VsZkludGVyc2VjdGlvbiBpcyB0cnVlIHRoZW4gdGhlcmUgaXMgbm8gc2Vjb25kYXJ5IHBvbHlnb24sIHNvIHRoYXQgaXNuJ3QgdXNlZFxuXG5cdFx0Ly9cblx0XHQvLyBzdGF0dXMgbG9naWNcblx0XHQvL1xuXG5cdFx0dmFyIHN0YXR1c19yb290ID0gTGlua2VkTGlzdC5jcmVhdGUoKTtcblxuXHRcdGZ1bmN0aW9uIHN0YXR1c0NvbXBhcmUoZXYxLCBldjIpe1xuXHRcdFx0dmFyIGExID0gZXYxLnNlZy5zdGFydDtcblx0XHRcdHZhciBhMiA9IGV2MS5zZWcuZW5kO1xuXHRcdFx0dmFyIGIxID0gZXYyLnNlZy5zdGFydDtcblx0XHRcdHZhciBiMiA9IGV2Mi5zZWcuZW5kO1xuXG5cdFx0XHRpZiAoZXBzLnBvaW50c0NvbGxpbmVhcihhMSwgYjEsIGIyKSl7XG5cdFx0XHRcdGlmIChlcHMucG9pbnRzQ29sbGluZWFyKGEyLCBiMSwgYjIpKVxuXHRcdFx0XHRcdHJldHVybiAxOy8vZXZlbnRDb21wYXJlKHRydWUsIGExLCBhMiwgdHJ1ZSwgYjEsIGIyKTtcblx0XHRcdFx0cmV0dXJuIGVwcy5wb2ludEFib3ZlT3JPbkxpbmUoYTIsIGIxLCBiMikgPyAxIDogLTE7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZXBzLnBvaW50QWJvdmVPck9uTGluZShhMSwgYjEsIGIyKSA/IDEgOiAtMTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBzdGF0dXNGaW5kU3Vycm91bmRpbmcoZXYpe1xuXHRcdFx0cmV0dXJuIHN0YXR1c19yb290LmZpbmRUcmFuc2l0aW9uKGZ1bmN0aW9uKGhlcmUpe1xuXHRcdFx0XHR2YXIgY29tcCA9IHN0YXR1c0NvbXBhcmUoZXYsIGhlcmUuZXYpO1xuXHRcdFx0XHRyZXR1cm4gY29tcCA+IDA7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBjaGVja0ludGVyc2VjdGlvbihldjEsIGV2Mil7XG5cdFx0XHQvLyByZXR1cm5zIHRoZSBzZWdtZW50IGVxdWFsIHRvIGV2MSwgb3IgZmFsc2UgaWYgbm90aGluZyBlcXVhbFxuXG5cdFx0XHR2YXIgc2VnMSA9IGV2MS5zZWc7XG5cdFx0XHR2YXIgc2VnMiA9IGV2Mi5zZWc7XG5cdFx0XHR2YXIgYTEgPSBzZWcxLnN0YXJ0O1xuXHRcdFx0dmFyIGEyID0gc2VnMS5lbmQ7XG5cdFx0XHR2YXIgYjEgPSBzZWcyLnN0YXJ0O1xuXHRcdFx0dmFyIGIyID0gc2VnMi5lbmQ7XG5cblx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0YnVpbGRMb2cuY2hlY2tJbnRlcnNlY3Rpb24oc2VnMSwgc2VnMik7XG5cblx0XHRcdHZhciBpID0gZXBzLmxpbmVzSW50ZXJzZWN0KGExLCBhMiwgYjEsIGIyKTtcblxuXHRcdFx0aWYgKGkgPT09IGZhbHNlKXtcblx0XHRcdFx0Ly8gc2VnbWVudHMgYXJlIHBhcmFsbGVsIG9yIGNvaW5jaWRlbnRcblxuXHRcdFx0XHQvLyBpZiBwb2ludHMgYXJlbid0IGNvbGxpbmVhciwgdGhlbiB0aGUgc2VnbWVudHMgYXJlIHBhcmFsbGVsLCBzbyBubyBpbnRlcnNlY3Rpb25zXG5cdFx0XHRcdGlmICghZXBzLnBvaW50c0NvbGxpbmVhcihhMSwgYTIsIGIxKSlcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdC8vIG90aGVyd2lzZSwgc2VnbWVudHMgYXJlIG9uIHRvcCBvZiBlYWNoIG90aGVyIHNvbWVob3cgKGFrYSBjb2luY2lkZW50KVxuXG5cdFx0XHRcdGlmIChlcHMucG9pbnRzU2FtZShhMSwgYjIpIHx8IGVwcy5wb2ludHNTYW1lKGEyLCBiMSkpXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlOyAvLyBzZWdtZW50cyB0b3VjaCBhdCBlbmRwb2ludHMuLi4gbm8gaW50ZXJzZWN0aW9uXG5cblx0XHRcdFx0dmFyIGExX2VxdV9iMSA9IGVwcy5wb2ludHNTYW1lKGExLCBiMSk7XG5cdFx0XHRcdHZhciBhMl9lcXVfYjIgPSBlcHMucG9pbnRzU2FtZShhMiwgYjIpO1xuXG5cdFx0XHRcdGlmIChhMV9lcXVfYjEgJiYgYTJfZXF1X2IyKVxuXHRcdFx0XHRcdHJldHVybiBldjI7IC8vIHNlZ21lbnRzIGFyZSBleGFjdGx5IGVxdWFsXG5cblx0XHRcdFx0dmFyIGExX2JldHdlZW4gPSAhYTFfZXF1X2IxICYmIGVwcy5wb2ludEJldHdlZW4oYTEsIGIxLCBiMik7XG5cdFx0XHRcdHZhciBhMl9iZXR3ZWVuID0gIWEyX2VxdV9iMiAmJiBlcHMucG9pbnRCZXR3ZWVuKGEyLCBiMSwgYjIpO1xuXG5cdFx0XHRcdC8vIGhhbmR5IGZvciBkZWJ1Z2dpbmc6XG5cdFx0XHRcdC8vIGJ1aWxkTG9nLmxvZyh7XG5cdFx0XHRcdC8vXHRhMV9lcXVfYjE6IGExX2VxdV9iMSxcblx0XHRcdFx0Ly9cdGEyX2VxdV9iMjogYTJfZXF1X2IyLFxuXHRcdFx0XHQvL1x0YTFfYmV0d2VlbjogYTFfYmV0d2Vlbixcblx0XHRcdFx0Ly9cdGEyX2JldHdlZW46IGEyX2JldHdlZW5cblx0XHRcdFx0Ly8gfSk7XG5cblx0XHRcdFx0aWYgKGExX2VxdV9iMSl7XG5cdFx0XHRcdFx0aWYgKGEyX2JldHdlZW4pe1xuXHRcdFx0XHRcdFx0Ly8gIChhMSktLS0oYTIpXG5cdFx0XHRcdFx0XHQvLyAgKGIxKS0tLS0tLS0tLS0oYjIpXG5cdFx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGEyKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRcdC8vICAoYTEpLS0tLS0tLS0tLShhMilcblx0XHRcdFx0XHRcdC8vICAoYjEpLS0tKGIyKVxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYxLCBiMik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiBldjI7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAoYTFfYmV0d2Vlbil7XG5cdFx0XHRcdFx0aWYgKCFhMl9lcXVfYjIpe1xuXHRcdFx0XHRcdFx0Ly8gbWFrZSBhMiBlcXVhbCB0byBiMlxuXHRcdFx0XHRcdFx0aWYgKGEyX2JldHdlZW4pe1xuXHRcdFx0XHRcdFx0XHQvLyAgICAgICAgIChhMSktLS0oYTIpXG5cdFx0XHRcdFx0XHRcdC8vICAoYjEpLS0tLS0tLS0tLS0tLS0tLS0oYjIpXG5cdFx0XHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MiwgYTIpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRcdFx0Ly8gICAgICAgICAoYTEpLS0tLS0tLS0tLShhMilcblx0XHRcdFx0XHRcdFx0Ly8gIChiMSktLS0tLS0tLS0tKGIyKVxuXHRcdFx0XHRcdFx0XHRldmVudERpdmlkZShldjEsIGIyKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyAgICAgICAgIChhMSktLS0oYTIpXG5cdFx0XHRcdFx0Ly8gIChiMSktLS0tLS0tLS0tKGIyKVxuXHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MiwgYTEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNle1xuXHRcdFx0XHQvLyBvdGhlcndpc2UsIGxpbmVzIGludGVyc2VjdCBhdCBpLnB0LCB3aGljaCBtYXkgb3IgbWF5IG5vdCBiZSBiZXR3ZWVuIHRoZSBlbmRwb2ludHNcblxuXHRcdFx0XHQvLyBpcyBBIGRpdmlkZWQgYmV0d2VlbiBpdHMgZW5kcG9pbnRzPyAoZXhjbHVzaXZlKVxuXHRcdFx0XHRpZiAoaS5hbG9uZ0EgPT09IDApe1xuXHRcdFx0XHRcdGlmIChpLmFsb25nQiA9PT0gLTEpIC8vIHllcywgYXQgZXhhY3RseSBiMVxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYxLCBiMSk7XG5cdFx0XHRcdFx0ZWxzZSBpZiAoaS5hbG9uZ0IgPT09IDApIC8vIHllcywgc29tZXdoZXJlIGJldHdlZW4gQidzIGVuZHBvaW50c1xuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYxLCBpLnB0KTtcblx0XHRcdFx0XHRlbHNlIGlmIChpLmFsb25nQiA9PT0gMSkgLy8geWVzLCBhdCBleGFjdGx5IGIyXG5cdFx0XHRcdFx0XHRldmVudERpdmlkZShldjEsIGIyKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlzIEIgZGl2aWRlZCBiZXR3ZWVuIGl0cyBlbmRwb2ludHM/IChleGNsdXNpdmUpXG5cdFx0XHRcdGlmIChpLmFsb25nQiA9PT0gMCl7XG5cdFx0XHRcdFx0aWYgKGkuYWxvbmdBID09PSAtMSkgLy8geWVzLCBhdCBleGFjdGx5IGExXG5cdFx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGExKTtcblx0XHRcdFx0XHRlbHNlIGlmIChpLmFsb25nQSA9PT0gMCkgLy8geWVzLCBzb21ld2hlcmUgYmV0d2VlbiBBJ3MgZW5kcG9pbnRzIChleGNsdXNpdmUpXG5cdFx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGkucHQpO1xuXHRcdFx0XHRcdGVsc2UgaWYgKGkuYWxvbmdBID09PSAxKSAvLyB5ZXMsIGF0IGV4YWN0bHkgYTJcblx0XHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MiwgYTIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly9cblx0XHQvLyBtYWluIGV2ZW50IGxvb3Bcblx0XHQvL1xuXHRcdHZhciBzZWdtZW50cyA9IFtdO1xuXHRcdHdoaWxlICghZXZlbnRfcm9vdC5pc0VtcHR5KCkpe1xuXHRcdFx0dmFyIGV2ID0gZXZlbnRfcm9vdC5nZXRIZWFkKCk7XG5cblx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0YnVpbGRMb2cudmVydChldi5wdFswXSk7XG5cblx0XHRcdGlmIChldi5pc1N0YXJ0KXtcblxuXHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0YnVpbGRMb2cuc2VnbWVudE5ldyhldi5zZWcsIGV2LnByaW1hcnkpO1xuXG5cdFx0XHRcdHZhciBzdXJyb3VuZGluZyA9IHN0YXR1c0ZpbmRTdXJyb3VuZGluZyhldik7XG5cdFx0XHRcdHZhciBhYm92ZSA9IHN1cnJvdW5kaW5nLmJlZm9yZSA/IHN1cnJvdW5kaW5nLmJlZm9yZS5ldiA6IG51bGw7XG5cdFx0XHRcdHZhciBiZWxvdyA9IHN1cnJvdW5kaW5nLmFmdGVyID8gc3Vycm91bmRpbmcuYWZ0ZXIuZXYgOiBudWxsO1xuXG5cdFx0XHRcdGlmIChidWlsZExvZyl7XG5cdFx0XHRcdFx0YnVpbGRMb2cudGVtcFN0YXR1cyhcblx0XHRcdFx0XHRcdGV2LnNlZyxcblx0XHRcdFx0XHRcdGFib3ZlID8gYWJvdmUuc2VnIDogZmFsc2UsXG5cdFx0XHRcdFx0XHRiZWxvdyA/IGJlbG93LnNlZyA6IGZhbHNlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGZ1bmN0aW9uIGNoZWNrQm90aEludGVyc2VjdGlvbnMoKXtcblx0XHRcdFx0XHRpZiAoYWJvdmUpe1xuXHRcdFx0XHRcdFx0dmFyIGV2ZSA9IGNoZWNrSW50ZXJzZWN0aW9uKGV2LCBhYm92ZSk7XG5cdFx0XHRcdFx0XHRpZiAoZXZlKVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZXZlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoYmVsb3cpXG5cdFx0XHRcdFx0XHRyZXR1cm4gY2hlY2tJbnRlcnNlY3Rpb24oZXYsIGJlbG93KTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgZXZlID0gY2hlY2tCb3RoSW50ZXJzZWN0aW9ucygpO1xuXHRcdFx0XHRpZiAoZXZlKXtcblx0XHRcdFx0XHQvLyBldiBhbmQgZXZlIGFyZSBlcXVhbFxuXHRcdFx0XHRcdC8vIHdlJ2xsIGtlZXAgZXZlIGFuZCB0aHJvdyBhd2F5IGV2XG5cblx0XHRcdFx0XHQvLyBtZXJnZSBldi5zZWcncyBmaWxsIGluZm9ybWF0aW9uIGludG8gZXZlLnNlZ1xuXG5cdFx0XHRcdFx0aWYgKHNlbGZJbnRlcnNlY3Rpb24pe1xuXHRcdFx0XHRcdFx0dmFyIHRvZ2dsZTsgLy8gYXJlIHdlIGEgdG9nZ2xpbmcgZWRnZT9cblx0XHRcdFx0XHRcdGlmIChldi5zZWcubXlGaWxsLmJlbG93ID09PSBudWxsKVxuXHRcdFx0XHRcdFx0XHR0b2dnbGUgPSB0cnVlO1xuXHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0XHR0b2dnbGUgPSBldi5zZWcubXlGaWxsLmFib3ZlICE9PSBldi5zZWcubXlGaWxsLmJlbG93O1xuXG5cdFx0XHRcdFx0XHQvLyBtZXJnZSB0d28gc2VnbWVudHMgdGhhdCBiZWxvbmcgdG8gdGhlIHNhbWUgcG9seWdvblxuXHRcdFx0XHRcdFx0Ly8gdGhpbmsgb2YgdGhpcyBhcyBzYW5kd2ljaGluZyB0d28gc2VnbWVudHMgdG9nZXRoZXIsIHdoZXJlIGBldmUuc2VnYCBpc1xuXHRcdFx0XHRcdFx0Ly8gdGhlIGJvdHRvbSAtLSB0aGlzIHdpbGwgY2F1c2UgdGhlIGFib3ZlIGZpbGwgZmxhZyB0byB0b2dnbGVcblx0XHRcdFx0XHRcdGlmICh0b2dnbGUpXG5cdFx0XHRcdFx0XHRcdGV2ZS5zZWcubXlGaWxsLmFib3ZlID0gIWV2ZS5zZWcubXlGaWxsLmFib3ZlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdFx0Ly8gbWVyZ2UgdHdvIHNlZ21lbnRzIHRoYXQgYmVsb25nIHRvIGRpZmZlcmVudCBwb2x5Z29uc1xuXHRcdFx0XHRcdFx0Ly8gZWFjaCBzZWdtZW50IGhhcyBkaXN0aW5jdCBrbm93bGVkZ2UsIHNvIG5vIHNwZWNpYWwgbG9naWMgaXMgbmVlZGVkXG5cdFx0XHRcdFx0XHQvLyBub3RlIHRoYXQgdGhpcyBjYW4gb25seSBoYXBwZW4gb25jZSBwZXIgc2VnbWVudCBpbiB0aGlzIHBoYXNlLCBiZWNhdXNlIHdlXG5cdFx0XHRcdFx0XHQvLyBhcmUgZ3VhcmFudGVlZCB0aGF0IGFsbCBzZWxmLWludGVyc2VjdGlvbnMgYXJlIGdvbmVcblx0XHRcdFx0XHRcdGV2ZS5zZWcub3RoZXJGaWxsID0gZXYuc2VnLm15RmlsbDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0XHRidWlsZExvZy5zZWdtZW50VXBkYXRlKGV2ZS5zZWcpO1xuXG5cdFx0XHRcdFx0ZXYub3RoZXIucmVtb3ZlKCk7XG5cdFx0XHRcdFx0ZXYucmVtb3ZlKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoZXZlbnRfcm9vdC5nZXRIZWFkKCkgIT09IGV2KXtcblx0XHRcdFx0XHQvLyBzb21ldGhpbmcgd2FzIGluc2VydGVkIGJlZm9yZSB1cyBpbiB0aGUgZXZlbnQgcXVldWUsIHNvIGxvb3AgYmFjayBhcm91bmQgYW5kXG5cdFx0XHRcdFx0Ly8gcHJvY2VzcyBpdCBiZWZvcmUgY29udGludWluZ1xuXHRcdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRcdGJ1aWxkTG9nLnJld2luZChldi5zZWcpO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly9cblx0XHRcdFx0Ly8gY2FsY3VsYXRlIGZpbGwgZmxhZ3Ncblx0XHRcdFx0Ly9cblx0XHRcdFx0aWYgKHNlbGZJbnRlcnNlY3Rpb24pe1xuXHRcdFx0XHRcdHZhciB0b2dnbGU7IC8vIGFyZSB3ZSBhIHRvZ2dsaW5nIGVkZ2U/XG5cdFx0XHRcdFx0aWYgKGV2LnNlZy5teUZpbGwuYmVsb3cgPT09IG51bGwpIC8vIGlmIHdlIGFyZSBhIG5ldyBzZWdtZW50Li4uXG5cdFx0XHRcdFx0XHR0b2dnbGUgPSB0cnVlOyAvLyB0aGVuIHdlIHRvZ2dsZVxuXHRcdFx0XHRcdGVsc2UgLy8gd2UgYXJlIGEgc2VnbWVudCB0aGF0IGhhcyBwcmV2aW91cyBrbm93bGVkZ2UgZnJvbSBhIGRpdmlzaW9uXG5cdFx0XHRcdFx0XHR0b2dnbGUgPSBldi5zZWcubXlGaWxsLmFib3ZlICE9PSBldi5zZWcubXlGaWxsLmJlbG93OyAvLyBjYWxjdWxhdGUgdG9nZ2xlXG5cblx0XHRcdFx0XHQvLyBuZXh0LCBjYWxjdWxhdGUgd2hldGhlciB3ZSBhcmUgZmlsbGVkIGJlbG93IHVzXG5cdFx0XHRcdFx0aWYgKCFiZWxvdyl7IC8vIGlmIG5vdGhpbmcgaXMgYmVsb3cgdXMuLi5cblx0XHRcdFx0XHRcdC8vIHdlIGFyZSBmaWxsZWQgYmVsb3cgdXMgaWYgdGhlIHBvbHlnb24gaXMgaW52ZXJ0ZWRcblx0XHRcdFx0XHRcdGV2LnNlZy5teUZpbGwuYmVsb3cgPSBwcmltYXJ5UG9seUludmVydGVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdFx0Ly8gb3RoZXJ3aXNlLCB3ZSBrbm93IHRoZSBhbnN3ZXIgLS0gaXQncyB0aGUgc2FtZSBpZiB3aGF0ZXZlciBpcyBiZWxvd1xuXHRcdFx0XHRcdFx0Ly8gdXMgaXMgZmlsbGVkIGFib3ZlIGl0XG5cdFx0XHRcdFx0XHRldi5zZWcubXlGaWxsLmJlbG93ID0gYmVsb3cuc2VnLm15RmlsbC5hYm92ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBzaW5jZSBub3cgd2Uga25vdyBpZiB3ZSdyZSBmaWxsZWQgYmVsb3cgdXMsIHdlIGNhbiBjYWxjdWxhdGUgd2hldGhlclxuXHRcdFx0XHRcdC8vIHdlJ3JlIGZpbGxlZCBhYm92ZSB1cyBieSBhcHBseWluZyB0b2dnbGUgdG8gd2hhdGV2ZXIgaXMgYmVsb3cgdXNcblx0XHRcdFx0XHRpZiAodG9nZ2xlKVxuXHRcdFx0XHRcdFx0ZXYuc2VnLm15RmlsbC5hYm92ZSA9ICFldi5zZWcubXlGaWxsLmJlbG93O1xuXHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdGV2LnNlZy5teUZpbGwuYWJvdmUgPSBldi5zZWcubXlGaWxsLmJlbG93O1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2V7XG5cdFx0XHRcdFx0Ly8gbm93IHdlIGZpbGwgaW4gYW55IG1pc3NpbmcgdHJhbnNpdGlvbiBpbmZvcm1hdGlvbiwgc2luY2Ugd2UgYXJlIGFsbC1rbm93aW5nXG5cdFx0XHRcdFx0Ly8gYXQgdGhpcyBwb2ludFxuXG5cdFx0XHRcdFx0aWYgKGV2LnNlZy5vdGhlckZpbGwgPT09IG51bGwpe1xuXHRcdFx0XHRcdFx0Ly8gaWYgd2UgZG9uJ3QgaGF2ZSBvdGhlciBpbmZvcm1hdGlvbiwgdGhlbiB3ZSBuZWVkIHRvIGZpZ3VyZSBvdXQgaWYgd2UncmVcblx0XHRcdFx0XHRcdC8vIGluc2lkZSB0aGUgb3RoZXIgcG9seWdvblxuXHRcdFx0XHRcdFx0dmFyIGluc2lkZTtcblx0XHRcdFx0XHRcdGlmICghYmVsb3cpe1xuXHRcdFx0XHRcdFx0XHQvLyBpZiBub3RoaW5nIGlzIGJlbG93IHVzLCB0aGVuIHdlJ3JlIGluc2lkZSBpZiB0aGUgb3RoZXIgcG9seWdvbiBpc1xuXHRcdFx0XHRcdFx0XHQvLyBpbnZlcnRlZFxuXHRcdFx0XHRcdFx0XHRpbnNpZGUgPVxuXHRcdFx0XHRcdFx0XHRcdGV2LnByaW1hcnkgPyBzZWNvbmRhcnlQb2x5SW52ZXJ0ZWQgOiBwcmltYXJ5UG9seUludmVydGVkO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZXsgLy8gb3RoZXJ3aXNlLCBzb21ldGhpbmcgaXMgYmVsb3cgdXNcblx0XHRcdFx0XHRcdFx0Ly8gc28gY29weSB0aGUgYmVsb3cgc2VnbWVudCdzIG90aGVyIHBvbHlnb24ncyBhYm92ZVxuXHRcdFx0XHRcdFx0XHRpZiAoZXYucHJpbWFyeSA9PT0gYmVsb3cucHJpbWFyeSlcblx0XHRcdFx0XHRcdFx0XHRpbnNpZGUgPSBiZWxvdy5zZWcub3RoZXJGaWxsLmFib3ZlO1xuXHRcdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdFx0aW5zaWRlID0gYmVsb3cuc2VnLm15RmlsbC5hYm92ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGV2LnNlZy5vdGhlckZpbGwgPSB7XG5cdFx0XHRcdFx0XHRcdGFib3ZlOiBpbnNpZGUsXG5cdFx0XHRcdFx0XHRcdGJlbG93OiBpbnNpZGVcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGJ1aWxkTG9nKXtcblx0XHRcdFx0XHRidWlsZExvZy5zdGF0dXMoXG5cdFx0XHRcdFx0XHRldi5zZWcsXG5cdFx0XHRcdFx0XHRhYm92ZSA/IGFib3ZlLnNlZyA6IGZhbHNlLFxuXHRcdFx0XHRcdFx0YmVsb3cgPyBiZWxvdy5zZWcgOiBmYWxzZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpbnNlcnQgdGhlIHN0YXR1cyBhbmQgcmVtZW1iZXIgaXQgZm9yIGxhdGVyIHJlbW92YWxcblx0XHRcdFx0ZXYub3RoZXIuc3RhdHVzID0gc3Vycm91bmRpbmcuaW5zZXJ0KExpbmtlZExpc3Qubm9kZSh7IGV2OiBldiB9KSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNle1xuXHRcdFx0XHR2YXIgc3QgPSBldi5zdGF0dXM7XG5cblx0XHRcdFx0aWYgKHN0ID09PSBudWxsKXtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1BvbHlCb29sOiBaZXJvLWxlbmd0aCBzZWdtZW50IGRldGVjdGVkOyB5b3VyIGVwc2lsb24gaXMgJyArXG5cdFx0XHRcdFx0XHQncHJvYmFibHkgdG9vIHNtYWxsIG9yIHRvbyBsYXJnZScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gcmVtb3ZpbmcgdGhlIHN0YXR1cyB3aWxsIGNyZWF0ZSB0d28gbmV3IGFkamFjZW50IGVkZ2VzLCBzbyB3ZSdsbCBuZWVkIHRvIGNoZWNrXG5cdFx0XHRcdC8vIGZvciB0aG9zZVxuXHRcdFx0XHRpZiAoc3RhdHVzX3Jvb3QuZXhpc3RzKHN0LnByZXYpICYmIHN0YXR1c19yb290LmV4aXN0cyhzdC5uZXh0KSlcblx0XHRcdFx0XHRjaGVja0ludGVyc2VjdGlvbihzdC5wcmV2LmV2LCBzdC5uZXh0LmV2KTtcblxuXHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0YnVpbGRMb2cuc3RhdHVzUmVtb3ZlKHN0LmV2LnNlZyk7XG5cblx0XHRcdFx0Ly8gcmVtb3ZlIHRoZSBzdGF0dXNcblx0XHRcdFx0c3QucmVtb3ZlKCk7XG5cblx0XHRcdFx0Ly8gaWYgd2UndmUgcmVhY2hlZCB0aGlzIHBvaW50LCB3ZSd2ZSBjYWxjdWxhdGVkIGV2ZXJ5dGhpbmcgdGhlcmUgaXMgdG8ga25vdywgc29cblx0XHRcdFx0Ly8gc2F2ZSB0aGUgc2VnbWVudCBmb3IgcmVwb3J0aW5nXG5cdFx0XHRcdGlmICghZXYucHJpbWFyeSl7XG5cdFx0XHRcdFx0Ly8gbWFrZSBzdXJlIGBzZWcubXlGaWxsYCBhY3R1YWxseSBwb2ludHMgdG8gdGhlIHByaW1hcnkgcG9seWdvbiB0aG91Z2hcblx0XHRcdFx0XHR2YXIgcyA9IGV2LnNlZy5teUZpbGw7XG5cdFx0XHRcdFx0ZXYuc2VnLm15RmlsbCA9IGV2LnNlZy5vdGhlckZpbGw7XG5cdFx0XHRcdFx0ZXYuc2VnLm90aGVyRmlsbCA9IHM7XG5cdFx0XHRcdH1cblx0XHRcdFx0c2VnbWVudHMucHVzaChldi5zZWcpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyByZW1vdmUgdGhlIGV2ZW50IGFuZCBjb250aW51ZVxuXHRcdFx0ZXZlbnRfcm9vdC5nZXRIZWFkKCkucmVtb3ZlKCk7XG5cdFx0fVxuXG5cdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0YnVpbGRMb2cuZG9uZSgpO1xuXG5cdFx0cmV0dXJuIHNlZ21lbnRzO1xuXHR9XG5cblx0Ly8gcmV0dXJuIHRoZSBhcHByb3ByaWF0ZSBBUEkgZGVwZW5kaW5nIG9uIHdoYXQgd2UncmUgZG9pbmdcblx0aWYgKCFzZWxmSW50ZXJzZWN0aW9uKXtcblx0XHQvLyBwZXJmb3JtaW5nIGNvbWJpbmF0aW9uIG9mIHBvbHlnb25zLCBzbyBvbmx5IGRlYWwgd2l0aCBhbHJlYWR5LXByb2Nlc3NlZCBzZWdtZW50c1xuXHRcdHJldHVybiB7XG5cdFx0XHRjYWxjdWxhdGU6IGZ1bmN0aW9uKHNlZ21lbnRzMSwgaW52ZXJ0ZWQxLCBzZWdtZW50czIsIGludmVydGVkMil7XG5cdFx0XHRcdC8vIHNlZ21lbnRzWCBjb21lIGZyb20gdGhlIHNlbGYtaW50ZXJzZWN0aW9uIEFQSSwgb3IgdGhpcyBBUElcblx0XHRcdFx0Ly8gaW52ZXJ0ZWRYIGlzIHdoZXRoZXIgd2UgdHJlYXQgdGhhdCBsaXN0IG9mIHNlZ21lbnRzIGFzIGFuIGludmVydGVkIHBvbHlnb24gb3Igbm90XG5cdFx0XHRcdC8vIHJldHVybnMgc2VnbWVudHMgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZnVydGhlciBvcGVyYXRpb25zXG5cdFx0XHRcdHNlZ21lbnRzMS5mb3JFYWNoKGZ1bmN0aW9uKHNlZyl7XG5cdFx0XHRcdFx0ZXZlbnRBZGRTZWdtZW50KHNlZ21lbnRDb3B5KHNlZy5zdGFydCwgc2VnLmVuZCwgc2VnKSwgdHJ1ZSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzZWdtZW50czIuZm9yRWFjaChmdW5jdGlvbihzZWcpe1xuXHRcdFx0XHRcdGV2ZW50QWRkU2VnbWVudChzZWdtZW50Q29weShzZWcuc3RhcnQsIHNlZy5lbmQsIHNlZyksIGZhbHNlKTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybiBjYWxjdWxhdGUoaW52ZXJ0ZWQxLCBpbnZlcnRlZDIpO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvLyBvdGhlcndpc2UsIHBlcmZvcm1pbmcgc2VsZi1pbnRlcnNlY3Rpb24sIHNvIGRlYWwgd2l0aCByZWdpb25zXG5cdHJldHVybiB7XG5cdFx0YWRkUmVnaW9uOiBmdW5jdGlvbihyZWdpb24pe1xuXHRcdFx0Ly8gcmVnaW9ucyBhcmUgYSBsaXN0IG9mIHBvaW50czpcblx0XHRcdC8vICBbIFswLCAwXSwgWzEwMCwgMF0sIFs1MCwgMTAwXSBdXG5cdFx0XHQvLyB5b3UgY2FuIGFkZCBtdWx0aXBsZSByZWdpb25zIGJlZm9yZSBydW5uaW5nIGNhbGN1bGF0ZVxuXHRcdFx0dmFyIHB0MTtcblx0XHRcdHZhciBwdDIgPSByZWdpb25bcmVnaW9uLmxlbmd0aCAtIDFdO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCByZWdpb24ubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHRwdDEgPSBwdDI7XG5cdFx0XHRcdHB0MiA9IHJlZ2lvbltpXTtcblxuXHRcdFx0XHR2YXIgZm9yd2FyZCA9IGVwcy5wb2ludHNDb21wYXJlKHB0MSwgcHQyKTtcblx0XHRcdFx0aWYgKGZvcndhcmQgPT09IDApIC8vIHBvaW50cyBhcmUgZXF1YWwsIHNvIHdlIGhhdmUgYSB6ZXJvLWxlbmd0aCBzZWdtZW50XG5cdFx0XHRcdFx0Y29udGludWU7IC8vIGp1c3Qgc2tpcCBpdFxuXG5cdFx0XHRcdGV2ZW50QWRkU2VnbWVudChcblx0XHRcdFx0XHRzZWdtZW50TmV3KFxuXHRcdFx0XHRcdFx0Zm9yd2FyZCA8IDAgPyBwdDEgOiBwdDIsXG5cdFx0XHRcdFx0XHRmb3J3YXJkIDwgMCA/IHB0MiA6IHB0MVxuXHRcdFx0XHRcdCksXG5cdFx0XHRcdFx0dHJ1ZVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Y2FsY3VsYXRlOiBmdW5jdGlvbihpbnZlcnRlZCl7XG5cdFx0XHQvLyBpcyB0aGUgcG9seWdvbiBpbnZlcnRlZD9cblx0XHRcdC8vIHJldHVybnMgc2VnbWVudHNcblx0XHRcdHJldHVybiBjYWxjdWxhdGUoaW52ZXJ0ZWQsIGZhbHNlKTtcblx0XHR9XG5cdH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gSW50ZXJzZWN0ZXI7XG4iLCIvLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gc2ltcGxlIGxpbmtlZCBsaXN0IGltcGxlbWVudGF0aW9uIHRoYXQgYWxsb3dzIHlvdSB0byB0cmF2ZXJzZSBkb3duIG5vZGVzIGFuZCBzYXZlIHBvc2l0aW9uc1xuLy9cblxudmFyIExpbmtlZExpc3QgPSB7XG5cdGNyZWF0ZTogZnVuY3Rpb24oKXtcblx0XHR2YXIgbXkgPSB7XG5cdFx0XHRyb290OiB7IHJvb3Q6IHRydWUsIG5leHQ6IG51bGwgfSxcblx0XHRcdGV4aXN0czogZnVuY3Rpb24obm9kZSl7XG5cdFx0XHRcdGlmIChub2RlID09PSBudWxsIHx8IG5vZGUgPT09IG15LnJvb3QpXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH0sXG5cdFx0XHRpc0VtcHR5OiBmdW5jdGlvbigpe1xuXHRcdFx0XHRyZXR1cm4gbXkucm9vdC5uZXh0ID09PSBudWxsO1xuXHRcdFx0fSxcblx0XHRcdGdldEhlYWQ6IGZ1bmN0aW9uKCl7XG5cdFx0XHRcdHJldHVybiBteS5yb290Lm5leHQ7XG5cdFx0XHR9LFxuXHRcdFx0aW5zZXJ0QmVmb3JlOiBmdW5jdGlvbihub2RlLCBjaGVjayl7XG5cdFx0XHRcdHZhciBsYXN0ID0gbXkucm9vdDtcblx0XHRcdFx0dmFyIGhlcmUgPSBteS5yb290Lm5leHQ7XG5cdFx0XHRcdHdoaWxlIChoZXJlICE9PSBudWxsKXtcblx0XHRcdFx0XHRpZiAoY2hlY2soaGVyZSkpe1xuXHRcdFx0XHRcdFx0bm9kZS5wcmV2ID0gaGVyZS5wcmV2O1xuXHRcdFx0XHRcdFx0bm9kZS5uZXh0ID0gaGVyZTtcblx0XHRcdFx0XHRcdGhlcmUucHJldi5uZXh0ID0gbm9kZTtcblx0XHRcdFx0XHRcdGhlcmUucHJldiA9IG5vZGU7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGxhc3QgPSBoZXJlO1xuXHRcdFx0XHRcdGhlcmUgPSBoZXJlLm5leHQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0bGFzdC5uZXh0ID0gbm9kZTtcblx0XHRcdFx0bm9kZS5wcmV2ID0gbGFzdDtcblx0XHRcdFx0bm9kZS5uZXh0ID0gbnVsbDtcblx0XHRcdH0sXG5cdFx0XHRmaW5kVHJhbnNpdGlvbjogZnVuY3Rpb24oY2hlY2spe1xuXHRcdFx0XHR2YXIgcHJldiA9IG15LnJvb3Q7XG5cdFx0XHRcdHZhciBoZXJlID0gbXkucm9vdC5uZXh0O1xuXHRcdFx0XHR3aGlsZSAoaGVyZSAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0aWYgKGNoZWNrKGhlcmUpKVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0cHJldiA9IGhlcmU7XG5cdFx0XHRcdFx0aGVyZSA9IGhlcmUubmV4dDtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdGJlZm9yZTogcHJldiA9PT0gbXkucm9vdCA/IG51bGwgOiBwcmV2LFxuXHRcdFx0XHRcdGFmdGVyOiBoZXJlLFxuXHRcdFx0XHRcdGluc2VydDogZnVuY3Rpb24obm9kZSl7XG5cdFx0XHRcdFx0XHRub2RlLnByZXYgPSBwcmV2O1xuXHRcdFx0XHRcdFx0bm9kZS5uZXh0ID0gaGVyZTtcblx0XHRcdFx0XHRcdHByZXYubmV4dCA9IG5vZGU7XG5cdFx0XHRcdFx0XHRpZiAoaGVyZSAhPT0gbnVsbClcblx0XHRcdFx0XHRcdFx0aGVyZS5wcmV2ID0gbm9kZTtcblx0XHRcdFx0XHRcdHJldHVybiBub2RlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdHJldHVybiBteTtcblx0fSxcblx0bm9kZTogZnVuY3Rpb24oZGF0YSl7XG5cdFx0ZGF0YS5wcmV2ID0gbnVsbDtcblx0XHRkYXRhLm5leHQgPSBudWxsO1xuXHRcdGRhdGEucmVtb3ZlID0gZnVuY3Rpb24oKXtcblx0XHRcdGRhdGEucHJldi5uZXh0ID0gZGF0YS5uZXh0O1xuXHRcdFx0aWYgKGRhdGEubmV4dClcblx0XHRcdFx0ZGF0YS5uZXh0LnByZXYgPSBkYXRhLnByZXY7XG5cdFx0XHRkYXRhLnByZXYgPSBudWxsO1xuXHRcdFx0ZGF0YS5uZXh0ID0gbnVsbDtcblx0XHR9O1xuXHRcdHJldHVybiBkYXRhO1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmtlZExpc3Q7XG4iLCIvLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gY29udmVydHMgYSBsaXN0IG9mIHNlZ21lbnRzIGludG8gYSBsaXN0IG9mIHJlZ2lvbnMsIHdoaWxlIGFsc28gcmVtb3ZpbmcgdW5uZWNlc3NhcnkgdmVydGljaWVzXG4vL1xuXG5mdW5jdGlvbiBTZWdtZW50Q2hhaW5lcihzZWdtZW50cywgZXBzLCBidWlsZExvZyl7XG5cdHZhciBjaGFpbnMgPSBbXTtcblx0dmFyIHJlZ2lvbnMgPSBbXTtcblxuXHRzZWdtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKHNlZyl7XG5cdFx0dmFyIHB0MSA9IHNlZy5zdGFydDtcblx0XHR2YXIgcHQyID0gc2VnLmVuZDtcblx0XHRpZiAoZXBzLnBvaW50c1NhbWUocHQxLCBwdDIpKXtcblx0XHRcdGNvbnNvbGUud2FybignUG9seUJvb2w6IFdhcm5pbmc6IFplcm8tbGVuZ3RoIHNlZ21lbnQgZGV0ZWN0ZWQ7IHlvdXIgZXBzaWxvbiBpcyAnICtcblx0XHRcdFx0J3Byb2JhYmx5IHRvbyBzbWFsbCBvciB0b28gbGFyZ2UnKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRidWlsZExvZy5jaGFpblN0YXJ0KHNlZyk7XG5cblx0XHQvLyBzZWFyY2ggZm9yIHR3byBjaGFpbnMgdGhhdCB0aGlzIHNlZ21lbnQgbWF0Y2hlc1xuXHRcdHZhciBmaXJzdF9tYXRjaCA9IHtcblx0XHRcdGluZGV4OiAwLFxuXHRcdFx0bWF0Y2hlc19oZWFkOiBmYWxzZSxcblx0XHRcdG1hdGNoZXNfcHQxOiBmYWxzZVxuXHRcdH07XG5cdFx0dmFyIHNlY29uZF9tYXRjaCA9IHtcblx0XHRcdGluZGV4OiAwLFxuXHRcdFx0bWF0Y2hlc19oZWFkOiBmYWxzZSxcblx0XHRcdG1hdGNoZXNfcHQxOiBmYWxzZVxuXHRcdH07XG5cdFx0dmFyIG5leHRfbWF0Y2ggPSBmaXJzdF9tYXRjaDtcblx0XHRmdW5jdGlvbiBzZXRNYXRjaChpbmRleCwgbWF0Y2hlc19oZWFkLCBtYXRjaGVzX3B0MSl7XG5cdFx0XHQvLyByZXR1cm4gdHJ1ZSBpZiB3ZSd2ZSBtYXRjaGVkIHR3aWNlXG5cdFx0XHRuZXh0X21hdGNoLmluZGV4ID0gaW5kZXg7XG5cdFx0XHRuZXh0X21hdGNoLm1hdGNoZXNfaGVhZCA9IG1hdGNoZXNfaGVhZDtcblx0XHRcdG5leHRfbWF0Y2gubWF0Y2hlc19wdDEgPSBtYXRjaGVzX3B0MTtcblx0XHRcdGlmIChuZXh0X21hdGNoID09PSBmaXJzdF9tYXRjaCl7XG5cdFx0XHRcdG5leHRfbWF0Y2ggPSBzZWNvbmRfbWF0Y2g7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdG5leHRfbWF0Y2ggPSBudWxsO1xuXHRcdFx0cmV0dXJuIHRydWU7IC8vIHdlJ3ZlIG1hdGNoZWQgdHdpY2UsIHdlJ3JlIGRvbmUgaGVyZVxuXHRcdH1cblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGNoYWlucy5sZW5ndGg7IGkrKyl7XG5cdFx0XHR2YXIgY2hhaW4gPSBjaGFpbnNbaV07XG5cdFx0XHR2YXIgaGVhZCAgPSBjaGFpblswXTtcblx0XHRcdHZhciBoZWFkMiA9IGNoYWluWzFdO1xuXHRcdFx0dmFyIHRhaWwgID0gY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMV07XG5cdFx0XHR2YXIgdGFpbDIgPSBjaGFpbltjaGFpbi5sZW5ndGggLSAyXTtcblx0XHRcdGlmIChlcHMucG9pbnRzU2FtZShoZWFkLCBwdDEpKXtcblx0XHRcdFx0aWYgKHNldE1hdGNoKGksIHRydWUsIHRydWUpKVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoZXBzLnBvaW50c1NhbWUoaGVhZCwgcHQyKSl7XG5cdFx0XHRcdGlmIChzZXRNYXRjaChpLCB0cnVlLCBmYWxzZSkpXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmIChlcHMucG9pbnRzU2FtZSh0YWlsLCBwdDEpKXtcblx0XHRcdFx0aWYgKHNldE1hdGNoKGksIGZhbHNlLCB0cnVlKSlcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKGVwcy5wb2ludHNTYW1lKHRhaWwsIHB0Mikpe1xuXHRcdFx0XHRpZiAoc2V0TWF0Y2goaSwgZmFsc2UsIGZhbHNlKSlcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAobmV4dF9tYXRjaCA9PT0gZmlyc3RfbWF0Y2gpe1xuXHRcdFx0Ly8gd2UgZGlkbid0IG1hdGNoIGFueXRoaW5nLCBzbyBjcmVhdGUgYSBuZXcgY2hhaW5cblx0XHRcdGNoYWlucy5wdXNoKFsgcHQxLCBwdDIgXSk7XG5cdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdGJ1aWxkTG9nLmNoYWluTmV3KHB0MSwgcHQyKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAobmV4dF9tYXRjaCA9PT0gc2Vjb25kX21hdGNoKXtcblx0XHRcdC8vIHdlIG1hdGNoZWQgYSBzaW5nbGUgY2hhaW5cblxuXHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRidWlsZExvZy5jaGFpbk1hdGNoKGZpcnN0X21hdGNoLmluZGV4KTtcblxuXHRcdFx0Ly8gYWRkIHRoZSBvdGhlciBwb2ludCB0byB0aGUgYXBwb3JwcmlhdGUgZW5kLCBhbmQgY2hlY2sgdG8gc2VlIGlmIHdlJ3ZlIGNsb3NlZCB0aGVcblx0XHRcdC8vIGNoYWluIGludG8gYSBsb29wXG5cblx0XHRcdHZhciBpbmRleCA9IGZpcnN0X21hdGNoLmluZGV4O1xuXHRcdFx0dmFyIHB0ID0gZmlyc3RfbWF0Y2gubWF0Y2hlc19wdDEgPyBwdDIgOiBwdDE7IC8vIGlmIHdlIG1hdGNoZWQgcHQxLCB0aGVuIHdlIGFkZCBwdDIsIGV0Y1xuXHRcdFx0dmFyIGFkZFRvSGVhZCA9IGZpcnN0X21hdGNoLm1hdGNoZXNfaGVhZDsgLy8gaWYgd2UgbWF0Y2hlZCBhdCBoZWFkLCB0aGVuIGFkZCB0byB0aGUgaGVhZFxuXG5cdFx0XHR2YXIgY2hhaW4gPSBjaGFpbnNbaW5kZXhdO1xuXHRcdFx0dmFyIGdyb3cgID0gYWRkVG9IZWFkID8gY2hhaW5bMF0gOiBjaGFpbltjaGFpbi5sZW5ndGggLSAxXTtcblx0XHRcdHZhciBncm93MiA9IGFkZFRvSGVhZCA/IGNoYWluWzFdIDogY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMl07XG5cdFx0XHR2YXIgb3BwbyAgPSBhZGRUb0hlYWQgPyBjaGFpbltjaGFpbi5sZW5ndGggLSAxXSA6IGNoYWluWzBdO1xuXHRcdFx0dmFyIG9wcG8yID0gYWRkVG9IZWFkID8gY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMl0gOiBjaGFpblsxXTtcblxuXHRcdFx0aWYgKGVwcy5wb2ludHNDb2xsaW5lYXIoZ3JvdzIsIGdyb3csIHB0KSl7XG5cdFx0XHRcdC8vIGdyb3cgaXNuJ3QgbmVlZGVkIGJlY2F1c2UgaXQncyBkaXJlY3RseSBiZXR3ZWVuIGdyb3cyIGFuZCBwdDpcblx0XHRcdFx0Ly8gZ3JvdzIgLS0tZ3Jvdy0tLT4gcHRcblx0XHRcdFx0aWYgKGFkZFRvSGVhZCl7XG5cdFx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdFx0YnVpbGRMb2cuY2hhaW5SZW1vdmVIZWFkKGZpcnN0X21hdGNoLmluZGV4LCBwdCk7XG5cdFx0XHRcdFx0Y2hhaW4uc2hpZnQoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluUmVtb3ZlVGFpbChmaXJzdF9tYXRjaC5pbmRleCwgcHQpO1xuXHRcdFx0XHRcdGNoYWluLnBvcCgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGdyb3cgPSBncm93MjsgLy8gb2xkIGdyb3cgaXMgZ29uZS4uLiBuZXcgZ3JvdyBpcyB3aGF0IGdyb3cyIHdhc1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZXBzLnBvaW50c1NhbWUob3BwbywgcHQpKXtcblx0XHRcdFx0Ly8gd2UncmUgY2xvc2luZyB0aGUgbG9vcCwgc28gcmVtb3ZlIGNoYWluIGZyb20gY2hhaW5zXG5cdFx0XHRcdGNoYWlucy5zcGxpY2UoaW5kZXgsIDEpO1xuXG5cdFx0XHRcdGlmIChlcHMucG9pbnRzQ29sbGluZWFyKG9wcG8yLCBvcHBvLCBncm93KSl7XG5cdFx0XHRcdFx0Ly8gb3BwbyBpc24ndCBuZWVkZWQgYmVjYXVzZSBpdCdzIGRpcmVjdGx5IGJldHdlZW4gb3BwbzIgYW5kIGdyb3c6XG5cdFx0XHRcdFx0Ly8gb3BwbzIgLS0tb3Bwby0tLT5ncm93XG5cdFx0XHRcdFx0aWYgKGFkZFRvSGVhZCl7XG5cdFx0XHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluUmVtb3ZlVGFpbChmaXJzdF9tYXRjaC5pbmRleCwgZ3Jvdyk7XG5cdFx0XHRcdFx0XHRjaGFpbi5wb3AoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRcdFx0YnVpbGRMb2cuY2hhaW5SZW1vdmVIZWFkKGZpcnN0X21hdGNoLmluZGV4LCBncm93KTtcblx0XHRcdFx0XHRcdGNoYWluLnNoaWZ0KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluQ2xvc2UoZmlyc3RfbWF0Y2guaW5kZXgpO1xuXG5cdFx0XHRcdC8vIHdlIGhhdmUgYSBjbG9zZWQgY2hhaW4hXG5cdFx0XHRcdHJlZ2lvbnMucHVzaChjaGFpbik7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gbm90IGNsb3NpbmcgYSBsb29wLCBzbyBqdXN0IGFkZCBpdCB0byB0aGUgYXBwb3JwcmlhdGUgc2lkZVxuXHRcdFx0aWYgKGFkZFRvSGVhZCl7XG5cdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRidWlsZExvZy5jaGFpbkFkZEhlYWQoZmlyc3RfbWF0Y2guaW5kZXgsIHB0KTtcblx0XHRcdFx0Y2hhaW4udW5zaGlmdChwdCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNle1xuXHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0YnVpbGRMb2cuY2hhaW5BZGRUYWlsKGZpcnN0X21hdGNoLmluZGV4LCBwdCk7XG5cdFx0XHRcdGNoYWluLnB1c2gocHQpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIG90aGVyd2lzZSwgd2UgbWF0Y2hlZCB0d28gY2hhaW5zLCBzbyB3ZSBuZWVkIHRvIGNvbWJpbmUgdGhvc2UgY2hhaW5zIHRvZ2V0aGVyXG5cblx0XHRmdW5jdGlvbiByZXZlcnNlQ2hhaW4oaW5kZXgpe1xuXHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRidWlsZExvZy5jaGFpblJldmVyc2UoaW5kZXgpO1xuXHRcdFx0Y2hhaW5zW2luZGV4XS5yZXZlcnNlKCk7IC8vIGdlZSwgdGhhdCdzIGVhc3lcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBhcHBlbmRDaGFpbihpbmRleDEsIGluZGV4Mil7XG5cdFx0XHQvLyBpbmRleDEgZ2V0cyBpbmRleDIgYXBwZW5kZWQgdG8gaXQsIGFuZCBpbmRleDIgaXMgcmVtb3ZlZFxuXHRcdFx0dmFyIGNoYWluMSA9IGNoYWluc1tpbmRleDFdO1xuXHRcdFx0dmFyIGNoYWluMiA9IGNoYWluc1tpbmRleDJdO1xuXHRcdFx0dmFyIHRhaWwgID0gY2hhaW4xW2NoYWluMS5sZW5ndGggLSAxXTtcblx0XHRcdHZhciB0YWlsMiA9IGNoYWluMVtjaGFpbjEubGVuZ3RoIC0gMl07XG5cdFx0XHR2YXIgaGVhZCAgPSBjaGFpbjJbMF07XG5cdFx0XHR2YXIgaGVhZDIgPSBjaGFpbjJbMV07XG5cblx0XHRcdGlmIChlcHMucG9pbnRzQ29sbGluZWFyKHRhaWwyLCB0YWlsLCBoZWFkKSl7XG5cdFx0XHRcdC8vIHRhaWwgaXNuJ3QgbmVlZGVkIGJlY2F1c2UgaXQncyBkaXJlY3RseSBiZXR3ZWVuIHRhaWwyIGFuZCBoZWFkXG5cdFx0XHRcdC8vIHRhaWwyIC0tLXRhaWwtLS0+IGhlYWRcblx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluUmVtb3ZlVGFpbChpbmRleDEsIHRhaWwpO1xuXHRcdFx0XHRjaGFpbjEucG9wKCk7XG5cdFx0XHRcdHRhaWwgPSB0YWlsMjsgLy8gb2xkIHRhaWwgaXMgZ29uZS4uLiBuZXcgdGFpbCBpcyB3aGF0IHRhaWwyIHdhc1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZXBzLnBvaW50c0NvbGxpbmVhcih0YWlsLCBoZWFkLCBoZWFkMikpe1xuXHRcdFx0XHQvLyBoZWFkIGlzbid0IG5lZWRlZCBiZWNhdXNlIGl0J3MgZGlyZWN0bHkgYmV0d2VlbiB0YWlsIGFuZCBoZWFkMlxuXHRcdFx0XHQvLyB0YWlsIC0tLWhlYWQtLS0+IGhlYWQyXG5cdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRidWlsZExvZy5jaGFpblJlbW92ZUhlYWQoaW5kZXgyLCBoZWFkKTtcblx0XHRcdFx0Y2hhaW4yLnNoaWZ0KCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0YnVpbGRMb2cuY2hhaW5Kb2luKGluZGV4MSwgaW5kZXgyKTtcblx0XHRcdGNoYWluc1tpbmRleDFdID0gY2hhaW4xLmNvbmNhdChjaGFpbjIpO1xuXHRcdFx0Y2hhaW5zLnNwbGljZShpbmRleDIsIDEpO1xuXHRcdH1cblxuXHRcdHZhciBGID0gZmlyc3RfbWF0Y2guaW5kZXg7XG5cdFx0dmFyIFMgPSBzZWNvbmRfbWF0Y2guaW5kZXg7XG5cblx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRidWlsZExvZy5jaGFpbkNvbm5lY3QoRiwgUyk7XG5cblx0XHR2YXIgcmV2ZXJzZUYgPSBjaGFpbnNbRl0ubGVuZ3RoIDwgY2hhaW5zW1NdLmxlbmd0aDsgLy8gcmV2ZXJzZSB0aGUgc2hvcnRlciBjaGFpbiwgaWYgbmVlZGVkXG5cdFx0aWYgKGZpcnN0X21hdGNoLm1hdGNoZXNfaGVhZCl7XG5cdFx0XHRpZiAoc2Vjb25kX21hdGNoLm1hdGNoZXNfaGVhZCl7XG5cdFx0XHRcdGlmIChyZXZlcnNlRil7XG5cdFx0XHRcdFx0Ly8gPDw8PCBGIDw8PDwgLS0tID4+Pj4gUyA+Pj4+XG5cdFx0XHRcdFx0cmV2ZXJzZUNoYWluKEYpO1xuXHRcdFx0XHRcdC8vID4+Pj4gRiA+Pj4+IC0tLSA+Pj4+IFMgPj4+PlxuXHRcdFx0XHRcdGFwcGVuZENoYWluKEYsIFMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2V7XG5cdFx0XHRcdFx0Ly8gPDw8PCBGIDw8PDwgLS0tID4+Pj4gUyA+Pj4+XG5cdFx0XHRcdFx0cmV2ZXJzZUNoYWluKFMpO1xuXHRcdFx0XHRcdC8vIDw8PDwgRiA8PDw8IC0tLSA8PDw8IFMgPDw8PCAgIGxvZ2ljYWxseSBzYW1lIGFzOlxuXHRcdFx0XHRcdC8vID4+Pj4gUyA+Pj4+IC0tLSA+Pj4+IEYgPj4+PlxuXHRcdFx0XHRcdGFwcGVuZENoYWluKFMsIEYpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNle1xuXHRcdFx0XHQvLyA8PDw8IEYgPDw8PCAtLS0gPDw8PCBTIDw8PDwgICBsb2dpY2FsbHkgc2FtZSBhczpcblx0XHRcdFx0Ly8gPj4+PiBTID4+Pj4gLS0tID4+Pj4gRiA+Pj4+XG5cdFx0XHRcdGFwcGVuZENoYWluKFMsIEYpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNle1xuXHRcdFx0aWYgKHNlY29uZF9tYXRjaC5tYXRjaGVzX2hlYWQpe1xuXHRcdFx0XHQvLyA+Pj4+IEYgPj4+PiAtLS0gPj4+PiBTID4+Pj5cblx0XHRcdFx0YXBwZW5kQ2hhaW4oRiwgUyk7XG5cdFx0XHR9XG5cdFx0XHRlbHNle1xuXHRcdFx0XHRpZiAocmV2ZXJzZUYpe1xuXHRcdFx0XHRcdC8vID4+Pj4gRiA+Pj4+IC0tLSA8PDw8IFMgPDw8PFxuXHRcdFx0XHRcdHJldmVyc2VDaGFpbihGKTtcblx0XHRcdFx0XHQvLyA8PDw8IEYgPDw8PCAtLS0gPDw8PCBTIDw8PDwgICBsb2dpY2FsbHkgc2FtZSBhczpcblx0XHRcdFx0XHQvLyA+Pj4+IFMgPj4+PiAtLS0gPj4+PiBGID4+Pj5cblx0XHRcdFx0XHRhcHBlbmRDaGFpbihTLCBGKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdC8vID4+Pj4gRiA+Pj4+IC0tLSA8PDw8IFMgPDw8PFxuXHRcdFx0XHRcdHJldmVyc2VDaGFpbihTKTtcblx0XHRcdFx0XHQvLyA+Pj4+IEYgPj4+PiAtLS0gPj4+PiBTID4+Pj5cblx0XHRcdFx0XHRhcHBlbmRDaGFpbihGLCBTKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0cmV0dXJuIHJlZ2lvbnM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2VnbWVudENoYWluZXI7XG4iLCIvLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gZmlsdGVyIGEgbGlzdCBvZiBzZWdtZW50cyBiYXNlZCBvbiBib29sZWFuIG9wZXJhdGlvbnNcbi8vXG5cbmZ1bmN0aW9uIHNlbGVjdChzZWdtZW50cywgc2VsZWN0aW9uLCBidWlsZExvZyl7XG5cdHZhciByZXN1bHQgPSBbXTtcblx0c2VnbWVudHMuZm9yRWFjaChmdW5jdGlvbihzZWcpe1xuXHRcdHZhciBpbmRleCA9XG5cdFx0XHQoc2VnLm15RmlsbC5hYm92ZSA/IDggOiAwKSArXG5cdFx0XHQoc2VnLm15RmlsbC5iZWxvdyA/IDQgOiAwKSArXG5cdFx0XHQoKHNlZy5vdGhlckZpbGwgJiYgc2VnLm90aGVyRmlsbC5hYm92ZSkgPyAyIDogMCkgK1xuXHRcdFx0KChzZWcub3RoZXJGaWxsICYmIHNlZy5vdGhlckZpbGwuYmVsb3cpID8gMSA6IDApO1xuXHRcdGlmIChzZWxlY3Rpb25baW5kZXhdICE9PSAwKXtcblx0XHRcdC8vIGNvcHkgdGhlIHNlZ21lbnQgdG8gdGhlIHJlc3VsdHMsIHdoaWxlIGFsc28gY2FsY3VsYXRpbmcgdGhlIGZpbGwgc3RhdHVzXG5cdFx0XHRyZXN1bHQucHVzaCh7XG5cdFx0XHRcdGlkOiBidWlsZExvZyA/IGJ1aWxkTG9nLnNlZ21lbnRJZCgpIDogLTEsXG5cdFx0XHRcdHN0YXJ0OiBzZWcuc3RhcnQsXG5cdFx0XHRcdGVuZDogc2VnLmVuZCxcblx0XHRcdFx0bXlGaWxsOiB7XG5cdFx0XHRcdFx0YWJvdmU6IHNlbGVjdGlvbltpbmRleF0gPT09IDEsIC8vIDEgaWYgZmlsbGVkIGFib3ZlXG5cdFx0XHRcdFx0YmVsb3c6IHNlbGVjdGlvbltpbmRleF0gPT09IDIgIC8vIDIgaWYgZmlsbGVkIGJlbG93XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG90aGVyRmlsbDogbnVsbFxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblxuXHRpZiAoYnVpbGRMb2cpXG5cdFx0YnVpbGRMb2cuc2VsZWN0ZWQocmVzdWx0KTtcblxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG52YXIgU2VnbWVudFNlbGVjdG9yID0ge1xuXHR1bmlvbjogZnVuY3Rpb24oc2VnbWVudHMsIGJ1aWxkTG9nKXsgLy8gcHJpbWFyeSB8IHNlY29uZGFyeVxuXHRcdC8vIGFib3ZlMSBiZWxvdzEgYWJvdmUyIGJlbG93MiAgICBLZWVwPyAgICAgICAgICAgICAgIFZhbHVlXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0cmV0dXJuIHNlbGVjdChzZWdtZW50cywgW1xuXHRcdFx0MCwgMiwgMSwgMCxcblx0XHRcdDIsIDIsIDAsIDAsXG5cdFx0XHQxLCAwLCAxLCAwLFxuXHRcdFx0MCwgMCwgMCwgMFxuXHRcdF0sIGJ1aWxkTG9nKTtcblx0fSxcblx0aW50ZXJzZWN0OiBmdW5jdGlvbihzZWdtZW50cywgYnVpbGRMb2cpeyAvLyBwcmltYXJ5ICYgc2Vjb25kYXJ5XG5cdFx0Ly8gYWJvdmUxIGJlbG93MSBhYm92ZTIgYmVsb3cyICAgIEtlZXA/ICAgICAgICAgICAgICAgVmFsdWVcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHRyZXR1cm4gc2VsZWN0KHNlZ21lbnRzLCBbXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MCwgMiwgMCwgMixcblx0XHRcdDAsIDAsIDEsIDEsXG5cdFx0XHQwLCAyLCAxLCAwXG5cdFx0XSwgYnVpbGRMb2cpO1xuXHR9LFxuXHRkaWZmZXJlbmNlOiBmdW5jdGlvbihzZWdtZW50cywgYnVpbGRMb2cpeyAvLyBwcmltYXJ5IC0gc2Vjb25kYXJ5XG5cdFx0Ly8gYWJvdmUxIGJlbG93MSBhYm92ZTIgYmVsb3cyICAgIEtlZXA/ICAgICAgICAgICAgICAgVmFsdWVcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHRyZXR1cm4gc2VsZWN0KHNlZ21lbnRzLCBbXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MiwgMCwgMiwgMCxcblx0XHRcdDEsIDEsIDAsIDAsXG5cdFx0XHQwLCAxLCAyLCAwXG5cdFx0XSwgYnVpbGRMb2cpO1xuXHR9LFxuXHRkaWZmZXJlbmNlUmV2OiBmdW5jdGlvbihzZWdtZW50cywgYnVpbGRMb2cpeyAvLyBzZWNvbmRhcnkgLSBwcmltYXJ5XG5cdFx0Ly8gYWJvdmUxIGJlbG93MSBhYm92ZTIgYmVsb3cyICAgIEtlZXA/ICAgICAgICAgICAgICAgVmFsdWVcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHRyZXR1cm4gc2VsZWN0KHNlZ21lbnRzLCBbXG5cdFx0XHQwLCAyLCAxLCAwLFxuXHRcdFx0MCwgMCwgMSwgMSxcblx0XHRcdDAsIDIsIDAsIDIsXG5cdFx0XHQwLCAwLCAwLCAwXG5cdFx0XSwgYnVpbGRMb2cpO1xuXHR9LFxuXHR4b3I6IGZ1bmN0aW9uKHNlZ21lbnRzLCBidWlsZExvZyl7IC8vIHByaW1hcnkgXiBzZWNvbmRhcnlcblx0XHQvLyBhYm92ZTEgYmVsb3cxIGFib3ZlMiBiZWxvdzIgICAgS2VlcD8gICAgICAgICAgICAgICBWYWx1ZVxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMCAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMCAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMSAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMCAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMCAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMSAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMSAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMCAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMCAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMSAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMSAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMCAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMCAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMSAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdHJldHVybiBzZWxlY3Qoc2VnbWVudHMsIFtcblx0XHRcdDAsIDIsIDEsIDAsXG5cdFx0XHQyLCAwLCAwLCAxLFxuXHRcdFx0MSwgMCwgMCwgMixcblx0XHRcdDAsIDEsIDIsIDBcblx0XHRdLCBidWlsZExvZyk7XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU2VnbWVudFNlbGVjdG9yO1xuIiwiLy9PcHRpbWl6ZWQgdmVyc2lvbiBmb3IgdHJpYW5nbGUgY2xvc2VzdCBwb2ludFxuLy8gQmFzZWQgb24gRWJlcmx5J3MgV2lsZE1hZ2ljayBjb2Rlc1xuLy8gaHR0cDovL3d3dy5nZW9tZXRyaWN0b29scy5jb20vTGliTWF0aGVtYXRpY3MvRGlzdGFuY2UvRGlzdGFuY2UuaHRtbFxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBkaWZmID0gbmV3IEZsb2F0NjRBcnJheSg0KTtcbnZhciBlZGdlMCA9IG5ldyBGbG9hdDY0QXJyYXkoNCk7XG52YXIgZWRnZTEgPSBuZXcgRmxvYXQ2NEFycmF5KDQpO1xuXG5mdW5jdGlvbiBjbG9zZXN0UG9pbnQyZChWMCwgVjEsIFYyLCBwb2ludCwgcmVzdWx0KSB7XG4gIC8vUmVhbGxvY2F0ZSBidWZmZXJzIGlmIG5lY2Vzc2FyeVxuICBpZihkaWZmLmxlbmd0aCA8IHBvaW50Lmxlbmd0aCkge1xuICAgIGRpZmYgPSBuZXcgRmxvYXQ2NEFycmF5KHBvaW50Lmxlbmd0aCk7XG4gICAgZWRnZTAgPSBuZXcgRmxvYXQ2NEFycmF5KHBvaW50Lmxlbmd0aCk7XG4gICAgZWRnZTEgPSBuZXcgRmxvYXQ2NEFycmF5KHBvaW50Lmxlbmd0aCk7XG4gIH1cbiAgLy9Db21wdXRlIGVkZ2VzXG4gIGZvcih2YXIgaT0wOyBpPHBvaW50Lmxlbmd0aDsgKytpKSB7XG4gICAgZGlmZltpXSAgPSBWMFtpXSAtIHBvaW50W2ldO1xuICAgIGVkZ2UwW2ldID0gVjFbaV0gLSBWMFtpXTtcbiAgICBlZGdlMVtpXSA9IFYyW2ldIC0gVjBbaV07XG4gIH1cbiAgLy9Db21wdXRlIGNvZWZmaWNpZW50cyBmb3IgcXVhZHJhdGljIGZ1bmNcbiAgdmFyIGEwMCA9IDAuMFxuICAgICwgYTAxID0gMC4wXG4gICAgLCBhMTEgPSAwLjBcbiAgICAsIGIwICA9IDAuMFxuICAgICwgYjEgID0gMC4wXG4gICAgLCBjICAgPSAwLjA7XG4gIGZvcih2YXIgaT0wOyBpPHBvaW50Lmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGUwID0gZWRnZTBbaV1cbiAgICAgICwgZTEgPSBlZGdlMVtpXVxuICAgICAgLCBkICA9IGRpZmZbaV07XG4gICAgYTAwICs9IGUwICogZTA7XG4gICAgYTAxICs9IGUwICogZTE7XG4gICAgYTExICs9IGUxICogZTE7XG4gICAgYjAgICs9IGQgKiBlMDtcbiAgICBiMSAgKz0gZCAqIGUxO1xuICAgIGMgICArPSBkICogZDtcbiAgfVxuICAvL0NvbXB1dGUgZGV0ZXJtaW5hbnQvY29lZmZzXG4gIHZhciBkZXQgPSBNYXRoLmFicyhhMDAqYTExIC0gYTAxKmEwMSk7XG4gIHZhciBzICAgPSBhMDEqYjEgLSBhMTEqYjA7XG4gIHZhciB0ICAgPSBhMDEqYjAgLSBhMDAqYjE7XG4gIHZhciBzcXJEaXN0YW5jZTtcbiAgLy9IYXJkY29kZWQgVm9yb25vaSBkaWFncmFtIGNsYXNzaWZpY2F0aW9uXG4gIGlmIChzICsgdCA8PSBkZXQpIHtcbiAgICBpZiAocyA8IDApIHtcbiAgICAgIGlmICh0IDwgMCkgeyAvLyByZWdpb24gNFxuICAgICAgICBpZiAoYjAgPCAwKSB7XG4gICAgICAgICAgdCA9IDA7XG4gICAgICAgICAgaWYgKC1iMCA+PSBhMDApIHtcbiAgICAgICAgICAgIHMgPSAxLjA7XG4gICAgICAgICAgICBzcXJEaXN0YW5jZSA9IGEwMCArIDIuMCpiMCArIGM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMgPSAtYjAvYTAwO1xuICAgICAgICAgICAgc3FyRGlzdGFuY2UgPSBiMCpzICsgYztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcyA9IDA7XG4gICAgICAgICAgaWYgKGIxID49IDApIHtcbiAgICAgICAgICAgIHQgPSAwO1xuICAgICAgICAgICAgc3FyRGlzdGFuY2UgPSBjO1xuICAgICAgICAgIH0gZWxzZSBpZiAoLWIxID49IGExMSkge1xuICAgICAgICAgICAgdCA9IDE7XG4gICAgICAgICAgICBzcXJEaXN0YW5jZSA9IGExMSArIDIuMCpiMSArIGM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHQgPSAtYjEvYTExO1xuICAgICAgICAgICAgc3FyRGlzdGFuY2UgPSBiMSp0ICsgYztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7ICAvLyByZWdpb24gM1xuICAgICAgICBzID0gMDtcbiAgICAgICAgaWYgKGIxID49IDApIHtcbiAgICAgICAgICB0ID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGM7XG4gICAgICAgIH0gZWxzZSBpZiAoLWIxID49IGExMSkge1xuICAgICAgICAgIHQgPSAxO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYTExICsgMi4wKmIxICsgYztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0ID0gLWIxL2ExMTtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGIxKnQgKyBjO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0IDwgMCkgeyAvLyByZWdpb24gNVxuICAgICAgdCA9IDA7XG4gICAgICBpZiAoYjAgPj0gMCkge1xuICAgICAgICBzID0gMDtcbiAgICAgICAgc3FyRGlzdGFuY2UgPSBjO1xuICAgICAgfSBlbHNlIGlmICgtYjAgPj0gYTAwKSB7XG4gICAgICAgIHMgPSAxO1xuICAgICAgICBzcXJEaXN0YW5jZSA9IGEwMCArIDIuMCpiMCArIGM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzID0gLWIwL2EwMDtcbiAgICAgICAgc3FyRGlzdGFuY2UgPSBiMCpzICsgYztcbiAgICAgIH1cbiAgICB9IGVsc2UgeyAgLy8gcmVnaW9uIDBcbiAgICAgIC8vIG1pbmltdW0gYXQgaW50ZXJpb3IgcG9pbnRcbiAgICAgIHZhciBpbnZEZXQgPSAxLjAgLyBkZXQ7XG4gICAgICBzICo9IGludkRldDtcbiAgICAgIHQgKj0gaW52RGV0O1xuICAgICAgc3FyRGlzdGFuY2UgPSBzKihhMDAqcyArIGEwMSp0ICsgMi4wKmIwKSArIHQqKGEwMSpzICsgYTExKnQgKyAyLjAqYjEpICsgYztcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIHRtcDAsIHRtcDEsIG51bWVyLCBkZW5vbTtcbiAgICBcbiAgICBpZiAocyA8IDApIHsgIC8vIHJlZ2lvbiAyXG4gICAgICB0bXAwID0gYTAxICsgYjA7XG4gICAgICB0bXAxID0gYTExICsgYjE7XG4gICAgICBpZiAodG1wMSA+IHRtcDApIHtcbiAgICAgICAgbnVtZXIgPSB0bXAxIC0gdG1wMDtcbiAgICAgICAgZGVub20gPSBhMDAgLSAyLjAqYTAxICsgYTExO1xuICAgICAgICBpZiAobnVtZXIgPj0gZGVub20pIHtcbiAgICAgICAgICBzID0gMTtcbiAgICAgICAgICB0ID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGEwMCArIDIuMCpiMCArIGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcyA9IG51bWVyL2Rlbm9tO1xuICAgICAgICAgIHQgPSAxIC0gcztcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IHMqKGEwMCpzICsgYTAxKnQgKyAyLjAqYjApICtcbiAgICAgICAgICB0KihhMDEqcyArIGExMSp0ICsgMi4wKmIxKSArIGM7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMgPSAwO1xuICAgICAgICBpZiAodG1wMSA8PSAwKSB7XG4gICAgICAgICAgdCA9IDE7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMTEgKyAyLjAqYjEgKyBjO1xuICAgICAgICB9IGVsc2UgaWYgKGIxID49IDApIHtcbiAgICAgICAgICB0ID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdCA9IC1iMS9hMTE7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBiMSp0ICsgYztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodCA8IDApIHsgIC8vIHJlZ2lvbiA2XG4gICAgICB0bXAwID0gYTAxICsgYjE7XG4gICAgICB0bXAxID0gYTAwICsgYjA7XG4gICAgICBpZiAodG1wMSA+IHRtcDApIHtcbiAgICAgICAgbnVtZXIgPSB0bXAxIC0gdG1wMDtcbiAgICAgICAgZGVub20gPSBhMDAgLSAyLjAqYTAxICsgYTExO1xuICAgICAgICBpZiAobnVtZXIgPj0gZGVub20pIHtcbiAgICAgICAgICB0ID0gMTtcbiAgICAgICAgICBzID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGExMSArIDIuMCpiMSArIGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdCA9IG51bWVyL2Rlbm9tO1xuICAgICAgICAgIHMgPSAxIC0gdDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IHMqKGEwMCpzICsgYTAxKnQgKyAyLjAqYjApICtcbiAgICAgICAgICB0KihhMDEqcyArIGExMSp0ICsgMi4wKmIxKSArIGM7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHQgPSAwO1xuICAgICAgICBpZiAodG1wMSA8PSAwKSB7XG4gICAgICAgICAgcyA9IDE7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMDAgKyAyLjAqYjAgKyBjO1xuICAgICAgICB9IGVsc2UgaWYgKGIwID49IDApIHtcbiAgICAgICAgICBzID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcyA9IC1iMC9hMDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBiMCpzICsgYztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7ICAvLyByZWdpb24gMVxuICAgICAgbnVtZXIgPSBhMTEgKyBiMSAtIGEwMSAtIGIwO1xuICAgICAgaWYgKG51bWVyIDw9IDApIHtcbiAgICAgICAgcyA9IDA7XG4gICAgICAgIHQgPSAxO1xuICAgICAgICBzcXJEaXN0YW5jZSA9IGExMSArIDIuMCpiMSArIGM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZW5vbSA9IGEwMCAtIDIuMCphMDEgKyBhMTE7XG4gICAgICAgIGlmIChudW1lciA+PSBkZW5vbSkge1xuICAgICAgICAgIHMgPSAxO1xuICAgICAgICAgIHQgPSAwO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYTAwICsgMi4wKmIwICsgYztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzID0gbnVtZXIvZGVub207XG4gICAgICAgICAgdCA9IDEgLSBzO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gcyooYTAwKnMgKyBhMDEqdCArIDIuMCpiMCkgK1xuICAgICAgICAgIHQqKGEwMSpzICsgYTExKnQgKyAyLjAqYjEpICsgYztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgdSA9IDEuMCAtIHMgLSB0O1xuICBmb3IodmFyIGk9MDsgaTxwb2ludC5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IHUgKiBWMFtpXSArIHMgKiBWMVtpXSArIHQgKiBWMltpXTtcbiAgfVxuICBpZihzcXJEaXN0YW5jZSA8IDApIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuICByZXR1cm4gc3FyRGlzdGFuY2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvc2VzdFBvaW50MmQ7XG4iLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCdnbC1xdWF0L3NsZXJwJykiLCJ2YXIgbm93ID0gcmVxdWlyZSgncGVyZm9ybWFuY2Utbm93JylcbiAgLCByb290ID0gdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3dcbiAgLCB2ZW5kb3JzID0gWydtb3onLCAnd2Via2l0J11cbiAgLCBzdWZmaXggPSAnQW5pbWF0aW9uRnJhbWUnXG4gICwgcmFmID0gcm9vdFsncmVxdWVzdCcgKyBzdWZmaXhdXG4gICwgY2FmID0gcm9vdFsnY2FuY2VsJyArIHN1ZmZpeF0gfHwgcm9vdFsnY2FuY2VsUmVxdWVzdCcgKyBzdWZmaXhdXG5cbmZvcih2YXIgaSA9IDA7ICFyYWYgJiYgaSA8IHZlbmRvcnMubGVuZ3RoOyBpKyspIHtcbiAgcmFmID0gcm9vdFt2ZW5kb3JzW2ldICsgJ1JlcXVlc3QnICsgc3VmZml4XVxuICBjYWYgPSByb290W3ZlbmRvcnNbaV0gKyAnQ2FuY2VsJyArIHN1ZmZpeF1cbiAgICAgIHx8IHJvb3RbdmVuZG9yc1tpXSArICdDYW5jZWxSZXF1ZXN0JyArIHN1ZmZpeF1cbn1cblxuLy8gU29tZSB2ZXJzaW9ucyBvZiBGRiBoYXZlIHJBRiBidXQgbm90IGNBRlxuaWYoIXJhZiB8fCAhY2FmKSB7XG4gIHZhciBsYXN0ID0gMFxuICAgICwgaWQgPSAwXG4gICAgLCBxdWV1ZSA9IFtdXG4gICAgLCBmcmFtZUR1cmF0aW9uID0gMTAwMCAvIDYwXG5cbiAgcmFmID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICBpZihxdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHZhciBfbm93ID0gbm93KClcbiAgICAgICAgLCBuZXh0ID0gTWF0aC5tYXgoMCwgZnJhbWVEdXJhdGlvbiAtIChfbm93IC0gbGFzdCkpXG4gICAgICBsYXN0ID0gbmV4dCArIF9ub3dcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBjcCA9IHF1ZXVlLnNsaWNlKDApXG4gICAgICAgIC8vIENsZWFyIHF1ZXVlIGhlcmUgdG8gcHJldmVudFxuICAgICAgICAvLyBjYWxsYmFja3MgZnJvbSBhcHBlbmRpbmcgbGlzdGVuZXJzXG4gICAgICAgIC8vIHRvIHRoZSBjdXJyZW50IGZyYW1lJ3MgcXVldWVcbiAgICAgICAgcXVldWUubGVuZ3RoID0gMFxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY3AubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZighY3BbaV0uY2FuY2VsbGVkKSB7XG4gICAgICAgICAgICB0cnl7XG4gICAgICAgICAgICAgIGNwW2ldLmNhbGxiYWNrKGxhc3QpXG4gICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgdGhyb3cgZSB9LCAwKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgTWF0aC5yb3VuZChuZXh0KSlcbiAgICB9XG4gICAgcXVldWUucHVzaCh7XG4gICAgICBoYW5kbGU6ICsraWQsXG4gICAgICBjYWxsYmFjazogY2FsbGJhY2ssXG4gICAgICBjYW5jZWxsZWQ6IGZhbHNlXG4gICAgfSlcbiAgICByZXR1cm4gaWRcbiAgfVxuXG4gIGNhZiA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYocXVldWVbaV0uaGFuZGxlID09PSBoYW5kbGUpIHtcbiAgICAgICAgcXVldWVbaV0uY2FuY2VsbGVkID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGZuKSB7XG4gIC8vIFdyYXAgaW4gYSBuZXcgZnVuY3Rpb24gdG8gcHJldmVudFxuICAvLyBgY2FuY2VsYCBwb3RlbnRpYWxseSBiZWluZyBhc3NpZ25lZFxuICAvLyB0byB0aGUgbmF0aXZlIHJBRiBmdW5jdGlvblxuICByZXR1cm4gcmFmLmNhbGwocm9vdCwgZm4pXG59XG5tb2R1bGUuZXhwb3J0cy5jYW5jZWwgPSBmdW5jdGlvbigpIHtcbiAgY2FmLmFwcGx5KHJvb3QsIGFyZ3VtZW50cylcbn1cbm1vZHVsZS5leHBvcnRzLnBvbHlmaWxsID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gIGlmICghb2JqZWN0KSB7XG4gICAgb2JqZWN0ID0gcm9vdDtcbiAgfVxuICBvYmplY3QucmVxdWVzdEFuaW1hdGlvbkZyYW1lID0gcmFmXG4gIG9iamVjdC5jYW5jZWxBbmltYXRpb25GcmFtZSA9IGNhZlxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBibmFkZCA9IHJlcXVpcmUoJ2JpZy1yYXQvYWRkJylcblxubW9kdWxlLmV4cG9ydHMgPSBhZGRcblxuZnVuY3Rpb24gYWRkIChhLCBiKSB7XG4gIHZhciBuID0gYS5sZW5ndGhcbiAgdmFyIHIgPSBuZXcgQXJyYXkobilcbiAgZm9yICh2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHJbaV0gPSBibmFkZChhW2ldLCBiW2ldKVxuICB9XG4gIHJldHVybiByXG59XG4iLCIndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBmbG9hdDJyYXRcblxudmFyIHJhdCA9IHJlcXVpcmUoJ2JpZy1yYXQnKVxuXG5mdW5jdGlvbiBmbG9hdDJyYXQodikge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KHYubGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTx2Lmxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gcmF0KHZbaV0pXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciByYXQgPSByZXF1aXJlKCdiaWctcmF0JylcbnZhciBtdWwgPSByZXF1aXJlKCdiaWctcmF0L211bCcpXG5cbm1vZHVsZS5leHBvcnRzID0gbXVsc1xuXG5mdW5jdGlvbiBtdWxzKGEsIHgpIHtcbiAgdmFyIHMgPSByYXQoeClcbiAgdmFyIG4gPSBhLmxlbmd0aFxuICB2YXIgciA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByW2ldID0gbXVsKGFbaV0sIHMpXG4gIH1cbiAgcmV0dXJuIHJcbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgYm5zdWIgPSByZXF1aXJlKCdiaWctcmF0L3N1YicpXG5cbm1vZHVsZS5leHBvcnRzID0gc3ViXG5cbmZ1bmN0aW9uIHN1YihhLCBiKSB7XG4gIHZhciBuID0gYS5sZW5ndGhcbiAgdmFyIHIgPSBuZXcgQXJyYXkobilcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByW2ldID0gYm5zdWIoYVtpXSwgYltpXSlcbiAgfVxuICByZXR1cm4gclxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBjb21wYXJlQ2VsbCA9IHJlcXVpcmUoJ2NvbXBhcmUtY2VsbCcpXG52YXIgY29tcGFyZU9yaWVudGVkQ2VsbCA9IHJlcXVpcmUoJ2NvbXBhcmUtb3JpZW50ZWQtY2VsbCcpXG52YXIgb3JpZW50YXRpb24gPSByZXF1aXJlKCdjZWxsLW9yaWVudGF0aW9uJylcblxubW9kdWxlLmV4cG9ydHMgPSByZWR1Y2VDZWxsQ29tcGxleFxuXG5mdW5jdGlvbiByZWR1Y2VDZWxsQ29tcGxleChjZWxscykge1xuICBjZWxscy5zb3J0KGNvbXBhcmVPcmllbnRlZENlbGwpXG4gIHZhciBuID0gY2VsbHMubGVuZ3RoXG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICB2YXIgbyA9IG9yaWVudGF0aW9uKGMpXG4gICAgaWYobyA9PT0gMCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYocHRyID4gMCkge1xuICAgICAgdmFyIGYgPSBjZWxsc1twdHItMV1cbiAgICAgIGlmKGNvbXBhcmVDZWxsKGMsIGYpID09PSAwICYmXG4gICAgICAgICBvcmllbnRhdGlvbihmKSAgICAhPT0gbykge1xuICAgICAgICBwdHIgLT0gMVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgIH1cbiAgICBjZWxsc1twdHIrK10gPSBjXG4gIH1cbiAgY2VsbHMubGVuZ3RoID0gcHRyXG4gIHJldHVybiBjZWxsc1xufVxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5jb25zdCBnZXRCb3VuZHMgPSByZXF1aXJlKCdhcnJheS1ib3VuZHMnKVxyXG5jb25zdCByZ2JhID0gcmVxdWlyZSgnY29sb3Itbm9ybWFsaXplJylcclxuY29uc3QgdXBkYXRlRGlmZiA9IHJlcXVpcmUoJ3VwZGF0ZS1kaWZmJylcclxuY29uc3QgcGljayA9IHJlcXVpcmUoJ3BpY2stYnktYWxpYXMnKVxyXG5jb25zdCBleHRlbmQgPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJylcclxuY29uc3QgZmxhdHRlbiA9IHJlcXVpcmUoJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKVxyXG5jb25zdCB7ZmxvYXQzMiwgZnJhY3QzMn0gPSByZXF1aXJlKCd0by1mbG9hdDMyJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gRXJyb3IyRFxyXG5cclxuY29uc3QgV0VJR0hUUyA9IFtcclxuXHQvL2RpcmVjdGlvbiwgbGluZVdpZHRoIHNoaWZ0LCBjYXBTaXplIHNoaWZ0XHJcblxyXG5cdC8vIHgtZXJyb3IgYmFyXHJcblx0WzEsIDAsIDAsIDEsIDAsIDBdLFxyXG5cdFsxLCAwLCAwLCAtMSwgMCwgMF0sXHJcblx0Wy0xLCAwLCAwLCAtMSwgMCwgMF0sXHJcblxyXG5cdFstMSwgMCwgMCwgLTEsIDAsIDBdLFxyXG5cdFstMSwgMCwgMCwgMSwgMCwgMF0sXHJcblx0WzEsIDAsIDAsIDEsIDAsIDBdLFxyXG5cclxuXHQvLyB4LWVycm9yIHJpZ2h0IGNhcFxyXG5cdFsxLCAwLCAtMSwgMCwgMCwgMV0sXHJcblx0WzEsIDAsIC0xLCAwLCAwLCAtMV0sXHJcblx0WzEsIDAsIDEsIDAsIDAsIC0xXSxcclxuXHJcblx0WzEsIDAsIDEsIDAsIDAsIC0xXSxcclxuXHRbMSwgMCwgMSwgMCwgMCwgMV0sXHJcblx0WzEsIDAsIC0xLCAwLCAwLCAxXSxcclxuXHJcblx0Ly8geC1lcnJvciBsZWZ0IGNhcFxyXG5cdFstMSwgMCwgLTEsIDAsIDAsIDFdLFxyXG5cdFstMSwgMCwgLTEsIDAsIDAsIC0xXSxcclxuXHRbLTEsIDAsIDEsIDAsIDAsIC0xXSxcclxuXHJcblx0Wy0xLCAwLCAxLCAwLCAwLCAtMV0sXHJcblx0Wy0xLCAwLCAxLCAwLCAwLCAxXSxcclxuXHRbLTEsIDAsIC0xLCAwLCAwLCAxXSxcclxuXHJcblx0Ly8geS1lcnJvciBiYXJcclxuXHRbMCwgMSwgMSwgMCwgMCwgMF0sXHJcblx0WzAsIDEsIC0xLCAwLCAwLCAwXSxcclxuXHRbMCwgLTEsIC0xLCAwLCAwLCAwXSxcclxuXHJcblx0WzAsIC0xLCAtMSwgMCwgMCwgMF0sXHJcblx0WzAsIDEsIDEsIDAsIDAsIDBdLFxyXG5cdFswLCAtMSwgMSwgMCwgMCwgMF0sXHJcblxyXG5cdC8vIHktZXJyb3IgdG9wIGNhcFxyXG5cdFswLCAxLCAwLCAtMSwgMSwgMF0sXHJcblx0WzAsIDEsIDAsIC0xLCAtMSwgMF0sXHJcblx0WzAsIDEsIDAsIDEsIC0xLCAwXSxcclxuXHJcblx0WzAsIDEsIDAsIDEsIDEsIDBdLFxyXG5cdFswLCAxLCAwLCAtMSwgMSwgMF0sXHJcblx0WzAsIDEsIDAsIDEsIC0xLCAwXSxcclxuXHJcblx0Ly8geS1lcnJvciBib3R0b20gY2FwXHJcblx0WzAsIC0xLCAwLCAtMSwgMSwgMF0sXHJcblx0WzAsIC0xLCAwLCAtMSwgLTEsIDBdLFxyXG5cdFswLCAtMSwgMCwgMSwgLTEsIDBdLFxyXG5cclxuXHRbMCwgLTEsIDAsIDEsIDEsIDBdLFxyXG5cdFswLCAtMSwgMCwgLTEsIDEsIDBdLFxyXG5cdFswLCAtMSwgMCwgMSwgLTEsIDBdXHJcbl1cclxuXHJcblxyXG5mdW5jdGlvbiBFcnJvcjJEIChyZWdsLCBvcHRpb25zKSB7XHJcblx0aWYgKHR5cGVvZiByZWdsID09PSAnZnVuY3Rpb24nKSB7XHJcblx0XHRpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fVxyXG5cdFx0b3B0aW9ucy5yZWdsID0gcmVnbFxyXG5cdH1cclxuXHRlbHNlIHtcclxuXHRcdG9wdGlvbnMgPSByZWdsXHJcblx0fVxyXG5cdGlmIChvcHRpb25zLmxlbmd0aCkgb3B0aW9ucy5wb3NpdGlvbnMgPSBvcHRpb25zXHJcblx0cmVnbCA9IG9wdGlvbnMucmVnbFxyXG5cclxuXHRpZiAoIXJlZ2wuaGFzRXh0ZW5zaW9uKCdBTkdMRV9pbnN0YW5jZWRfYXJyYXlzJykpIHtcclxuXHRcdHRocm93IEVycm9yKCdyZWdsLWVycm9yMmQ6IGBBTkdMRV9pbnN0YW5jZWRfYXJyYXlzYCBleHRlbnNpb24gc2hvdWxkIGJlIGVuYWJsZWQnKTtcclxuXHR9XHJcblxyXG5cdC8vIHBlcnNpc3RlbnQgdmFyaWFibGVzXHJcblx0bGV0IGdsID0gcmVnbC5fZ2wsIGRyYXdFcnJvcnMsIHBvc2l0aW9uQnVmZmVyLCBwb3NpdGlvbkZyYWN0QnVmZmVyLCBjb2xvckJ1ZmZlciwgZXJyb3JCdWZmZXIsIG1lc2hCdWZmZXIsXHJcblx0XHRcdGRlZmF1bHRzID0ge1xyXG5cdFx0XHRcdGNvbG9yOiAnYmxhY2snLFxyXG5cdFx0XHRcdGNhcFNpemU6IDUsXHJcblx0XHRcdFx0bGluZVdpZHRoOiAxLFxyXG5cdFx0XHRcdG9wYWNpdHk6IDEsXHJcblx0XHRcdFx0dmlld3BvcnQ6IG51bGwsXHJcblx0XHRcdFx0cmFuZ2U6IG51bGwsXHJcblx0XHRcdFx0b2Zmc2V0OiAwLFxyXG5cdFx0XHRcdGNvdW50OiAwLFxyXG5cdFx0XHRcdGJvdW5kczogbnVsbCxcclxuXHRcdFx0XHRwb3NpdGlvbnM6IFtdLFxyXG5cdFx0XHRcdGVycm9yczogW11cclxuXHRcdFx0fSwgZ3JvdXBzID0gW11cclxuXHJcblx0Ly9jb2xvciBwZXItcG9pbnRcclxuXHRjb2xvckJ1ZmZlciA9IHJlZ2wuYnVmZmVyKHtcclxuXHRcdHVzYWdlOiAnZHluYW1pYycsXHJcblx0XHR0eXBlOiAndWludDgnLFxyXG5cdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoMClcclxuXHR9KVxyXG5cdC8veHktcG9zaXRpb24gcGVyLXBvaW50XHJcblx0cG9zaXRpb25CdWZmZXIgPSByZWdsLmJ1ZmZlcih7XHJcblx0XHR1c2FnZTogJ2R5bmFtaWMnLFxyXG5cdFx0dHlwZTogJ2Zsb2F0JyxcclxuXHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KDApXHJcblx0fSlcclxuXHQvL3h5LXBvc2l0aW9uIGZsb2F0MzItZnJhY3Rpb25cclxuXHRwb3NpdGlvbkZyYWN0QnVmZmVyID0gcmVnbC5idWZmZXIoe1xyXG5cdFx0dXNhZ2U6ICdkeW5hbWljJyxcclxuXHRcdHR5cGU6ICdmbG9hdCcsXHJcblx0XHRkYXRhOiBuZXcgVWludDhBcnJheSgwKVxyXG5cdH0pXHJcblx0Ly80IGVycm9ycyBwZXItcG9pbnRcclxuXHRlcnJvckJ1ZmZlciA9IHJlZ2wuYnVmZmVyKHtcclxuXHRcdHVzYWdlOiAnZHluYW1pYycsXHJcblx0XHR0eXBlOiAnZmxvYXQnLFxyXG5cdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoMClcclxuXHR9KVxyXG5cdC8vZXJyb3IgYmFyIG1lc2hcclxuXHRtZXNoQnVmZmVyID0gcmVnbC5idWZmZXIoe1xyXG5cdFx0dXNhZ2U6ICdzdGF0aWMnLFxyXG5cdFx0dHlwZTogJ2Zsb2F0JyxcclxuXHRcdGRhdGE6IFdFSUdIVFNcclxuXHR9KVxyXG5cclxuXHR1cGRhdGUob3B0aW9ucylcclxuXHJcblx0Ly9kcmF3aW5nIG1ldGhvZFxyXG5cdGRyYXdFcnJvcnMgPSByZWdsKHtcclxuXHRcdHZlcnQ6IGBcclxuXHRcdHByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcblx0XHRhdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbiwgcG9zaXRpb25GcmFjdDtcclxuXHRcdGF0dHJpYnV0ZSB2ZWM0IGVycm9yO1xyXG5cdFx0YXR0cmlidXRlIHZlYzQgY29sb3I7XHJcblxyXG5cdFx0YXR0cmlidXRlIHZlYzIgZGlyZWN0aW9uLCBsaW5lT2Zmc2V0LCBjYXBPZmZzZXQ7XHJcblxyXG5cdFx0dW5pZm9ybSB2ZWM0IHZpZXdwb3J0O1xyXG5cdFx0dW5pZm9ybSBmbG9hdCBsaW5lV2lkdGgsIGNhcFNpemU7XHJcblx0XHR1bmlmb3JtIHZlYzIgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3Q7XHJcblxyXG5cdFx0dmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcclxuXHJcblx0XHR2b2lkIG1haW4oKSB7XHJcblx0XHRcdGZyYWdDb2xvciA9IGNvbG9yIC8gMjU1LjtcclxuXHJcblx0XHRcdHZlYzIgcGl4ZWxPZmZzZXQgPSBsaW5lV2lkdGggKiBsaW5lT2Zmc2V0ICsgKGNhcFNpemUgKyBsaW5lV2lkdGgpICogY2FwT2Zmc2V0O1xyXG5cclxuXHRcdFx0dmVjMiBkeHkgPSAtc3RlcCguNSwgZGlyZWN0aW9uLnh5KSAqIGVycm9yLnh6ICsgc3RlcChkaXJlY3Rpb24ueHksIHZlYzIoLS41KSkgKiBlcnJvci55dztcclxuXHJcblx0XHRcdHZlYzIgcG9zaXRpb24gPSBwb3NpdGlvbiArIGR4eTtcclxuXHJcblx0XHRcdHZlYzIgcG9zID0gKHBvc2l0aW9uICsgdHJhbnNsYXRlKSAqIHNjYWxlXHJcblx0XHRcdFx0KyAocG9zaXRpb25GcmFjdCArIHRyYW5zbGF0ZUZyYWN0KSAqIHNjYWxlXHJcblx0XHRcdFx0KyAocG9zaXRpb24gKyB0cmFuc2xhdGUpICogc2NhbGVGcmFjdFxyXG5cdFx0XHRcdCsgKHBvc2l0aW9uRnJhY3QgKyB0cmFuc2xhdGVGcmFjdCkgKiBzY2FsZUZyYWN0O1xyXG5cclxuXHRcdFx0cG9zICs9IHBpeGVsT2Zmc2V0IC8gdmlld3BvcnQuenc7XHJcblxyXG5cdFx0XHRnbF9Qb3NpdGlvbiA9IHZlYzQocG9zICogMi4gLSAxLiwgMCwgMSk7XHJcblx0XHR9XHJcblx0XHRgLFxyXG5cclxuXHRcdGZyYWc6IGBcclxuXHRcdHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xyXG5cclxuXHRcdHZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XHJcblxyXG5cdFx0dW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xyXG5cclxuXHRcdHZvaWQgbWFpbigpIHtcclxuXHRcdFx0Z2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xyXG5cdFx0XHRnbF9GcmFnQ29sb3IuYSAqPSBvcGFjaXR5O1xyXG5cdFx0fVxyXG5cdFx0YCxcclxuXHJcblx0XHR1bmlmb3Jtczoge1xyXG5cdFx0XHRyYW5nZTogcmVnbC5wcm9wKCdyYW5nZScpLFxyXG5cdFx0XHRsaW5lV2lkdGg6IHJlZ2wucHJvcCgnbGluZVdpZHRoJyksXHJcblx0XHRcdGNhcFNpemU6IHJlZ2wucHJvcCgnY2FwU2l6ZScpLFxyXG5cdFx0XHRvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcclxuXHRcdFx0c2NhbGU6IHJlZ2wucHJvcCgnc2NhbGUnKSxcclxuXHRcdFx0dHJhbnNsYXRlOiByZWdsLnByb3AoJ3RyYW5zbGF0ZScpLFxyXG5cdFx0XHRzY2FsZUZyYWN0OiByZWdsLnByb3AoJ3NjYWxlRnJhY3QnKSxcclxuXHRcdFx0dHJhbnNsYXRlRnJhY3Q6IHJlZ2wucHJvcCgndHJhbnNsYXRlRnJhY3QnKSxcclxuXHRcdFx0dmlld3BvcnQ6IChjdHgsIHByb3ApID0+IFtwcm9wLnZpZXdwb3J0LngsIHByb3Audmlld3BvcnQueSwgY3R4LnZpZXdwb3J0V2lkdGgsIGN0eC52aWV3cG9ydEhlaWdodF1cclxuXHRcdH0sXHJcblxyXG5cdFx0YXR0cmlidXRlczoge1xyXG5cdFx0XHQvL2R5bmFtaWMgYXR0cmlidXRlc1xyXG5cdFx0XHRjb2xvcjoge1xyXG5cdFx0XHRcdGJ1ZmZlcjogY29sb3JCdWZmZXIsXHJcblx0XHRcdFx0b2Zmc2V0OiAoY3R4LCBwcm9wKSA9PiBwcm9wLm9mZnNldCAqIDQsXHJcblx0XHRcdFx0ZGl2aXNvcjogMSxcclxuXHRcdFx0fSxcclxuXHRcdFx0cG9zaXRpb246IHtcclxuXHRcdFx0XHRidWZmZXI6IHBvc2l0aW9uQnVmZmVyLFxyXG5cdFx0XHRcdG9mZnNldDogKGN0eCwgcHJvcCkgPT4gcHJvcC5vZmZzZXQgKiA4LFxyXG5cdFx0XHRcdGRpdmlzb3I6IDFcclxuXHRcdFx0fSxcclxuXHRcdFx0cG9zaXRpb25GcmFjdDoge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcG9zaXRpb25GcmFjdEJ1ZmZlcixcclxuXHRcdFx0XHRvZmZzZXQ6IChjdHgsIHByb3ApID0+IHByb3Aub2Zmc2V0ICogOCxcclxuXHRcdFx0XHRkaXZpc29yOiAxXHJcblx0XHRcdH0sXHJcblx0XHRcdGVycm9yOiB7XHJcblx0XHRcdFx0YnVmZmVyOiBlcnJvckJ1ZmZlcixcclxuXHRcdFx0XHRvZmZzZXQ6IChjdHgsIHByb3ApID0+IHByb3Aub2Zmc2V0ICogMTYsXHJcblx0XHRcdFx0ZGl2aXNvcjogMVxyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0Ly9zdGF0aWMgYXR0cmlidXRlc1xyXG5cdFx0XHRkaXJlY3Rpb246IHtcclxuXHRcdFx0XHRidWZmZXI6IG1lc2hCdWZmZXIsXHJcblx0XHRcdFx0c3RyaWRlOiAyNCxcclxuXHRcdFx0XHRvZmZzZXQ6IDBcclxuXHRcdFx0fSxcclxuXHRcdFx0bGluZU9mZnNldDoge1xyXG5cdFx0XHRcdGJ1ZmZlcjogbWVzaEJ1ZmZlcixcclxuXHRcdFx0XHRzdHJpZGU6IDI0LFxyXG5cdFx0XHRcdG9mZnNldDogOFxyXG5cdFx0XHR9LFxyXG5cdFx0XHRjYXBPZmZzZXQ6IHtcclxuXHRcdFx0XHRidWZmZXI6IG1lc2hCdWZmZXIsXHJcblx0XHRcdFx0c3RyaWRlOiAyNCxcclxuXHRcdFx0XHRvZmZzZXQ6IDE2XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblxyXG5cdFx0cHJpbWl0aXZlOiAndHJpYW5nbGVzJyxcclxuXHJcblx0XHRibGVuZDoge1xyXG5cdFx0XHRlbmFibGU6IHRydWUsXHJcblx0XHRcdGNvbG9yOiBbMCwwLDAsMF0sXHJcblx0XHRcdGVxdWF0aW9uOiB7XHJcblx0XHRcdFx0cmdiOiAnYWRkJyxcclxuXHRcdFx0XHRhbHBoYTogJ2FkZCdcclxuXHRcdFx0fSxcclxuXHRcdFx0ZnVuYzoge1xyXG5cdFx0XHRcdHNyY1JHQjogJ3NyYyBhbHBoYScsXHJcblx0XHRcdFx0ZHN0UkdCOiAnb25lIG1pbnVzIHNyYyBhbHBoYScsXHJcblx0XHRcdFx0c3JjQWxwaGE6ICdvbmUgbWludXMgZHN0IGFscGhhJyxcclxuXHRcdFx0XHRkc3RBbHBoYTogJ29uZSdcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHJcblx0XHRkZXB0aDoge1xyXG5cdFx0XHRlbmFibGU6IGZhbHNlXHJcblx0XHR9LFxyXG5cclxuXHRcdHNjaXNzb3I6IHtcclxuXHRcdFx0ZW5hYmxlOiB0cnVlLFxyXG5cdFx0XHRib3g6IHJlZ2wucHJvcCgndmlld3BvcnQnKVxyXG5cdFx0fSxcclxuXHRcdHZpZXdwb3J0OiByZWdsLnByb3AoJ3ZpZXdwb3J0JyksXHJcblx0XHRzdGVuY2lsOiBmYWxzZSxcclxuXHJcblx0XHRpbnN0YW5jZXM6IHJlZ2wucHJvcCgnY291bnQnKSxcclxuXHRcdGNvdW50OiBXRUlHSFRTLmxlbmd0aFxyXG5cdH0pXHJcblxyXG5cdC8vZXhwb3NlIEFQSVxyXG5cdGV4dGVuZChlcnJvcjJkLCB7XHJcblx0XHR1cGRhdGU6IHVwZGF0ZSxcclxuXHRcdGRyYXc6IGRyYXcsXHJcblx0XHRkZXN0cm95OiBkZXN0cm95LFxyXG5cdFx0cmVnbDogcmVnbCxcclxuXHRcdGdsOiBnbCxcclxuXHRcdGNhbnZhczogZ2wuY2FudmFzLFxyXG5cdFx0Z3JvdXBzOiBncm91cHNcclxuXHR9KVxyXG5cclxuXHRyZXR1cm4gZXJyb3IyZFxyXG5cclxuXHRmdW5jdGlvbiBlcnJvcjJkIChvcHRzKSB7XHJcblx0XHQvL3VwZGF0ZVxyXG5cdFx0aWYgKG9wdHMpIHtcclxuXHRcdFx0dXBkYXRlKG9wdHMpXHJcblx0XHR9XHJcblxyXG5cdFx0Ly9kZXN0cm95XHJcblx0XHRlbHNlIGlmIChvcHRzID09PSBudWxsKSB7XHJcblx0XHRcdGRlc3Ryb3koKVxyXG5cdFx0fVxyXG5cclxuXHRcdGRyYXcoKVxyXG5cdH1cclxuXHJcblxyXG5cdC8vbWFpbiBkcmF3IG1ldGhvZFxyXG5cdGZ1bmN0aW9uIGRyYXcgKG9wdGlvbnMpIHtcclxuXHRcdGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ251bWJlcicpIHJldHVybiBkcmF3R3JvdXAob3B0aW9ucylcclxuXHJcblx0XHQvL21ha2Ugb3B0aW9ucyBhIGJhdGNoXHJcblx0XHRpZiAob3B0aW9ucyAmJiAhQXJyYXkuaXNBcnJheShvcHRpb25zKSkgb3B0aW9ucyA9IFtvcHRpb25zXVxyXG5cclxuXHJcblx0XHRyZWdsLl9yZWZyZXNoKClcclxuXHJcblx0XHQvL3JlbmRlciBtdWx0aXBsZSBwb2x5bGluZXMgdmlhIHJlZ2wgYmF0Y2hcclxuXHRcdGdyb3Vwcy5mb3JFYWNoKChzLCBpKSA9PiB7XHJcblx0XHRcdGlmICghcykgcmV0dXJuXHJcblxyXG5cdFx0XHRpZiAob3B0aW9ucykge1xyXG5cdFx0XHRcdGlmICghb3B0aW9uc1tpXSkgcy5kcmF3ID0gZmFsc2VcclxuXHRcdFx0XHRlbHNlIHMuZHJhdyA9IHRydWVcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly9pZ25vcmUgZHJhdyBmbGFnIGZvciBvbmUgcGFzc1xyXG5cdFx0XHRpZiAoIXMuZHJhdykge1xyXG5cdFx0XHRcdHMuZHJhdyA9IHRydWU7XHJcblx0XHRcdFx0cmV0dXJuXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGRyYXdHcm91cChpKVxyXG5cdFx0fSlcclxuXHR9XHJcblxyXG5cdC8vZHJhdyBzaW5nbGUgZXJyb3IgZ3JvdXAgYnkgaWRcclxuXHRmdW5jdGlvbiBkcmF3R3JvdXAgKHMpIHtcclxuXHRcdGlmICh0eXBlb2YgcyA9PT0gJ251bWJlcicpIHMgPSBncm91cHNbc11cclxuXHRcdGlmIChzID09IG51bGwpIHJldHVyblxyXG5cclxuXHRcdGlmICghKHMgJiYgcy5jb3VudCAmJiBzLmNvbG9yICYmIHMub3BhY2l0eSAmJiBzLnBvc2l0aW9ucyAmJiBzLnBvc2l0aW9ucy5sZW5ndGggPiAxKSkgcmV0dXJuXHJcblxyXG5cdFx0cy5zY2FsZVJhdGlvID0gW1xyXG5cdFx0XHRzLnNjYWxlWzBdICogcy52aWV3cG9ydC53aWR0aCxcclxuXHRcdFx0cy5zY2FsZVsxXSAqIHMudmlld3BvcnQuaGVpZ2h0XHJcblx0XHRdXHJcblxyXG5cdFx0ZHJhd0Vycm9ycyhzKVxyXG5cclxuXHRcdGlmIChzLmFmdGVyKSBzLmFmdGVyKHMpXHJcblx0fVxyXG5cclxuXHRmdW5jdGlvbiB1cGRhdGUgKG9wdGlvbnMpIHtcclxuXHRcdGlmICghb3B0aW9ucykgcmV0dXJuXHJcblxyXG5cdFx0Ly9kaXJlY3QgcG9pbnRzIGFyZ3VtZW50XHJcblx0XHRpZiAob3B0aW9ucy5sZW5ndGggIT0gbnVsbCkge1xyXG5cdFx0XHRpZiAodHlwZW9mIG9wdGlvbnNbMF0gPT09ICdudW1iZXInKSBvcHRpb25zID0gW3twb3NpdGlvbnM6IG9wdGlvbnN9XVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vbWFrZSBvcHRpb25zIGEgYmF0Y2hcclxuXHRcdGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG9wdGlvbnMpKSBvcHRpb25zID0gW29wdGlvbnNdXHJcblxyXG5cdFx0Ly9nbG9iYWwgY291bnQgb2YgcG9pbnRzXHJcblx0XHRsZXQgcG9pbnRDb3VudCA9IDAsIGVycm9yQ291bnQgPSAwXHJcblxyXG5cdFx0ZXJyb3IyZC5ncm91cHMgPSBncm91cHMgPSBvcHRpb25zLm1hcCgob3B0aW9ucywgaSkgPT4ge1xyXG5cdFx0XHRsZXQgZ3JvdXAgPSBncm91cHNbaV1cclxuXHJcblx0XHRcdGlmICghb3B0aW9ucykgcmV0dXJuIGdyb3VwXHJcblx0XHRcdGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSBvcHRpb25zID0ge2FmdGVyOiBvcHRpb25zfVxyXG5cdFx0XHRlbHNlIGlmICh0eXBlb2Ygb3B0aW9uc1swXSA9PT0gJ251bWJlcicpIG9wdGlvbnMgPSB7cG9zaXRpb25zOiBvcHRpb25zfVxyXG5cclxuXHRcdFx0Ly9jb3B5IG9wdGlvbnMgdG8gYXZvaWQgbXV0YXRpb24gJiBoYW5kbGUgYWxpYXNlc1xyXG5cdFx0XHRvcHRpb25zID0gcGljayhvcHRpb25zLCB7XHJcblx0XHRcdFx0Y29sb3I6ICdjb2xvciBjb2xvcnMgZmlsbCcsXHJcblx0XHRcdFx0Y2FwU2l6ZTogJ2NhcFNpemUgY2FwIGNhcHNpemUgY2FwLXNpemUnLFxyXG5cdFx0XHRcdGxpbmVXaWR0aDogJ2xpbmVXaWR0aCBsaW5lLXdpZHRoIHdpZHRoIGxpbmUgdGhpY2tuZXNzJyxcclxuXHRcdFx0XHRvcGFjaXR5OiAnb3BhY2l0eSBhbHBoYScsXHJcblx0XHRcdFx0cmFuZ2U6ICdyYW5nZSBkYXRhQm94JyxcclxuXHRcdFx0XHR2aWV3cG9ydDogJ3ZpZXdwb3J0IHZpZXdCb3gnLFxyXG5cdFx0XHRcdGVycm9yczogJ2Vycm9ycyBlcnJvcicsXHJcblx0XHRcdFx0cG9zaXRpb25zOiAncG9zaXRpb25zIHBvc2l0aW9uIGRhdGEgcG9pbnRzJ1xyXG5cdFx0XHR9KVxyXG5cclxuXHRcdFx0aWYgKCFncm91cCkge1xyXG5cdFx0XHRcdGdyb3Vwc1tpXSA9IGdyb3VwID0ge1xyXG5cdFx0XHRcdFx0aWQ6IGksXHJcblx0XHRcdFx0XHRzY2FsZTogbnVsbCxcclxuXHRcdFx0XHRcdHRyYW5zbGF0ZTogbnVsbCxcclxuXHRcdFx0XHRcdHNjYWxlRnJhY3Q6IG51bGwsXHJcblx0XHRcdFx0XHR0cmFuc2xhdGVGcmFjdDogbnVsbCxcclxuXHRcdFx0XHRcdGRyYXc6IHRydWVcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0b3B0aW9ucyA9IGV4dGVuZCh7fSwgZGVmYXVsdHMsIG9wdGlvbnMpXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHVwZGF0ZURpZmYoZ3JvdXAsIG9wdGlvbnMsIFt7XHJcblx0XHRcdFx0bGluZVdpZHRoOiB2ID0+ICt2ICogLjUsXHJcblx0XHRcdFx0Y2FwU2l6ZTogdiA9PiArdiAqIC41LFxyXG5cdFx0XHRcdG9wYWNpdHk6IHBhcnNlRmxvYXQsXHJcblx0XHRcdFx0ZXJyb3JzOiBlcnJvcnMgPT4ge1xyXG5cdFx0XHRcdFx0ZXJyb3JzID0gZmxhdHRlbihlcnJvcnMpXHJcblxyXG5cdFx0XHRcdFx0ZXJyb3JDb3VudCArPSBlcnJvcnMubGVuZ3RoXHJcblx0XHRcdFx0XHRyZXR1cm4gZXJyb3JzXHJcblx0XHRcdFx0fSxcclxuXHRcdFx0XHRwb3NpdGlvbnM6IChwb3NpdGlvbnMsIHN0YXRlKSA9PiB7XHJcblx0XHRcdFx0XHRwb3NpdGlvbnMgPSBmbGF0dGVuKHBvc2l0aW9ucywgJ2Zsb2F0NjQnKVxyXG5cdFx0XHRcdFx0c3RhdGUuY291bnQgPSBNYXRoLmZsb29yKHBvc2l0aW9ucy5sZW5ndGggLyAyKVxyXG5cdFx0XHRcdFx0c3RhdGUuYm91bmRzID0gZ2V0Qm91bmRzKHBvc2l0aW9ucywgMilcclxuXHRcdFx0XHRcdHN0YXRlLm9mZnNldCA9IHBvaW50Q291bnRcclxuXHJcblx0XHRcdFx0XHRwb2ludENvdW50ICs9IHN0YXRlLmNvdW50XHJcblxyXG5cdFx0XHRcdFx0cmV0dXJuIHBvc2l0aW9uc1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSwge1xyXG5cdFx0XHRcdGNvbG9yOiAoY29sb3JzLCBzdGF0ZSkgPT4ge1xyXG5cdFx0XHRcdFx0bGV0IGNvdW50ID0gc3RhdGUuY291bnRcclxuXHJcblx0XHRcdFx0XHRpZiAoIWNvbG9ycykgY29sb3JzID0gJ3RyYW5zcGFyZW50J1xyXG5cclxuXHRcdFx0XHRcdC8vICdibGFjaycgb3IgWzAsMCwwLDBdIGNhc2VcclxuXHRcdFx0XHRcdGlmICghQXJyYXkuaXNBcnJheShjb2xvcnMpIHx8IHR5cGVvZiBjb2xvcnNbMF0gPT09ICdudW1iZXInKSB7XHJcblx0XHRcdFx0XHRcdGxldCBjb2xvciA9IGNvbG9yc1xyXG5cdFx0XHRcdFx0XHRjb2xvcnMgPSBBcnJheShjb3VudClcclxuXHRcdFx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0Y29sb3JzW2ldID0gY29sb3JcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdGlmIChjb2xvcnMubGVuZ3RoIDwgY291bnQpIHRocm93IEVycm9yKCdOb3QgZW5vdWdoIGNvbG9ycycpXHJcblxyXG5cdFx0XHRcdFx0bGV0IGNvbG9yRGF0YSA9IG5ldyBVaW50OEFycmF5KGNvdW50ICogNClcclxuXHJcblx0XHRcdFx0XHQvL2NvbnZlcnQgY29sb3JzIHRvIGZsb2F0IGFycmF5c1xyXG5cdFx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdGxldCBjID0gcmdiYShjb2xvcnNbaV0sICd1aW50OCcpXHJcblx0XHRcdFx0XHRcdGNvbG9yRGF0YS5zZXQoYywgaSAqIDQpXHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0cmV0dXJuIGNvbG9yRGF0YVxyXG5cdFx0XHRcdH0sXHJcblxyXG5cdFx0XHRcdHJhbmdlOiAocmFuZ2UsIHN0YXRlLCBvcHRpb25zKSA9PiB7XHJcblx0XHRcdFx0XHRsZXQgYm91bmRzID0gc3RhdGUuYm91bmRzXHJcblx0XHRcdFx0XHRpZiAoIXJhbmdlKSByYW5nZSA9IGJvdW5kc1xyXG5cclxuXHRcdFx0XHRcdHN0YXRlLnNjYWxlID0gWzEgLyAocmFuZ2VbMl0gLSByYW5nZVswXSksIDEgLyAocmFuZ2VbM10gLSByYW5nZVsxXSldXHJcblx0XHRcdFx0XHRzdGF0ZS50cmFuc2xhdGUgPSBbLXJhbmdlWzBdLCAtcmFuZ2VbMV1dXHJcblxyXG5cdFx0XHRcdFx0c3RhdGUuc2NhbGVGcmFjdCA9IGZyYWN0MzIoc3RhdGUuc2NhbGUpXHJcblx0XHRcdFx0XHRzdGF0ZS50cmFuc2xhdGVGcmFjdCA9IGZyYWN0MzIoc3RhdGUudHJhbnNsYXRlKVxyXG5cclxuXHRcdFx0XHRcdHJldHVybiByYW5nZVxyXG5cdFx0XHRcdH0sXHJcblxyXG5cdFx0XHRcdHZpZXdwb3J0OiB2cCA9PiB7XHJcblx0XHRcdFx0XHRsZXQgdmlld3BvcnRcclxuXHJcblx0XHRcdFx0XHRpZiAoQXJyYXkuaXNBcnJheSh2cCkpIHtcclxuXHRcdFx0XHRcdFx0dmlld3BvcnQgPSB7XHJcblx0XHRcdFx0XHRcdFx0eDogdnBbMF0sXHJcblx0XHRcdFx0XHRcdFx0eTogdnBbMV0sXHJcblx0XHRcdFx0XHRcdFx0d2lkdGg6IHZwWzJdIC0gdnBbMF0sXHJcblx0XHRcdFx0XHRcdFx0aGVpZ2h0OiB2cFszXSAtIHZwWzFdXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2UgaWYgKHZwKSB7XHJcblx0XHRcdFx0XHRcdHZpZXdwb3J0ID0ge1xyXG5cdFx0XHRcdFx0XHRcdHg6IHZwLnggfHwgdnAubGVmdCB8fCAwLFxyXG5cdFx0XHRcdFx0XHRcdHk6IHZwLnkgfHwgdnAudG9wIHx8IDBcclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0aWYgKHZwLnJpZ2h0KSB2aWV3cG9ydC53aWR0aCA9IHZwLnJpZ2h0IC0gdmlld3BvcnQueFxyXG5cdFx0XHRcdFx0XHRlbHNlIHZpZXdwb3J0LndpZHRoID0gdnAudyB8fCB2cC53aWR0aCB8fCAwXHJcblxyXG5cdFx0XHRcdFx0XHRpZiAodnAuYm90dG9tKSB2aWV3cG9ydC5oZWlnaHQgPSB2cC5ib3R0b20gLSB2aWV3cG9ydC55XHJcblx0XHRcdFx0XHRcdGVsc2Ugdmlld3BvcnQuaGVpZ2h0ID0gdnAuaCB8fCB2cC5oZWlnaHQgfHwgMFxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdHZpZXdwb3J0ID0ge1xyXG5cdFx0XHRcdFx0XHRcdHg6IDAsIHk6IDAsXHJcblx0XHRcdFx0XHRcdFx0d2lkdGg6IGdsLmRyYXdpbmdCdWZmZXJXaWR0aCxcclxuXHRcdFx0XHRcdFx0XHRoZWlnaHQ6IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdHJldHVybiB2aWV3cG9ydFxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fV0pXHJcblxyXG5cdFx0XHRyZXR1cm4gZ3JvdXBcclxuXHRcdH0pXHJcblxyXG5cdFx0aWYgKHBvaW50Q291bnQgfHwgZXJyb3JDb3VudCkge1xyXG5cdFx0XHRsZXQgbGVuID0gZ3JvdXBzLnJlZHVjZSgoYWNjLCBncm91cCwgaSkgPT4ge1xyXG5cdFx0XHRcdHJldHVybiBhY2MgKyAoZ3JvdXAgPyBncm91cC5jb3VudCA6IDApXHJcblx0XHRcdH0sIDApXHJcblxyXG5cdFx0XHRsZXQgcG9zaXRpb25EYXRhID0gbmV3IEZsb2F0NjRBcnJheShsZW4gKiAyKVxyXG5cdFx0XHRsZXQgY29sb3JEYXRhID0gbmV3IFVpbnQ4QXJyYXkobGVuICogNClcclxuXHRcdFx0bGV0IGVycm9yRGF0YSA9IG5ldyBGbG9hdDMyQXJyYXkobGVuICogNClcclxuXHJcblx0XHRcdGdyb3Vwcy5mb3JFYWNoKChncm91cCwgaSkgPT4ge1xyXG5cdFx0XHRcdGlmICghZ3JvdXApIHJldHVyblxyXG5cdFx0XHRcdGxldCB7cG9zaXRpb25zLCBjb3VudCwgb2Zmc2V0LCBjb2xvciwgZXJyb3JzfSA9IGdyb3VwXHJcblx0XHRcdFx0aWYgKCFjb3VudCkgcmV0dXJuXHJcblxyXG5cdFx0XHRcdGNvbG9yRGF0YS5zZXQoY29sb3IsIG9mZnNldCAqIDQpXHJcblx0XHRcdFx0ZXJyb3JEYXRhLnNldChlcnJvcnMsIG9mZnNldCAqIDQpXHJcblx0XHRcdFx0cG9zaXRpb25EYXRhLnNldChwb3NpdGlvbnMsIG9mZnNldCAqIDIpXHJcblx0XHRcdH0pXHJcblxyXG5cdFx0XHRwb3NpdGlvbkJ1ZmZlcihmbG9hdDMyKHBvc2l0aW9uRGF0YSkpXHJcblx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXIoZnJhY3QzMihwb3NpdGlvbkRhdGEpKVxyXG5cdFx0XHRjb2xvckJ1ZmZlcihjb2xvckRhdGEpXHJcblx0XHRcdGVycm9yQnVmZmVyKGVycm9yRGF0YSlcclxuXHRcdH1cclxuXHJcblx0fVxyXG5cclxuXHRmdW5jdGlvbiBkZXN0cm95ICgpIHtcclxuXHRcdHBvc2l0aW9uQnVmZmVyLmRlc3Ryb3koKVxyXG5cdFx0cG9zaXRpb25GcmFjdEJ1ZmZlci5kZXN0cm95KClcclxuXHRcdGNvbG9yQnVmZmVyLmRlc3Ryb3koKVxyXG5cdFx0ZXJyb3JCdWZmZXIuZGVzdHJveSgpXHJcblx0XHRtZXNoQnVmZmVyLmRlc3Ryb3koKVxyXG5cdH1cclxufVxyXG4iLCIndXNlIHN0cmljdCdcblxuXG5jb25zdCByZ2JhID0gcmVxdWlyZSgnY29sb3Itbm9ybWFsaXplJylcbmNvbnN0IGdldEJvdW5kcyA9IHJlcXVpcmUoJ2FycmF5LWJvdW5kcycpXG5jb25zdCBleHRlbmQgPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJylcbmNvbnN0IGdsc2xpZnkgPSByZXF1aXJlKCdnbHNsaWZ5JylcbmNvbnN0IHBpY2sgPSByZXF1aXJlKCdwaWNrLWJ5LWFsaWFzJylcbmNvbnN0IGZsYXR0ZW4gPSByZXF1aXJlKCdmbGF0dGVuLXZlcnRleC1kYXRhJylcbmNvbnN0IHRyaWFuZ3VsYXRlID0gcmVxdWlyZSgnZWFyY3V0JylcbmNvbnN0IG5vcm1hbGl6ZSA9IHJlcXVpcmUoJ2FycmF5LW5vcm1hbGl6ZScpXG5jb25zdCB7IGZsb2F0MzIsIGZyYWN0MzIgfSA9IHJlcXVpcmUoJ3RvLWZsb2F0MzInKVxuY29uc3QgV2Vha01hcCA9IHJlcXVpcmUoJ2VzNi13ZWFrLW1hcCcpXG5jb25zdCBwYXJzZVJlY3QgPSByZXF1aXJlKCdwYXJzZS1yZWN0JylcblxuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmUyRFxuXG5cbi8qKiBAY29uc3RydWN0b3IgKi9cbmZ1bmN0aW9uIExpbmUyRCAocmVnbCwgb3B0aW9ucykge1xuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgTGluZTJEKSkgcmV0dXJuIG5ldyBMaW5lMkQocmVnbCwgb3B0aW9ucylcblxuXHRpZiAodHlwZW9mIHJlZ2wgPT09ICdmdW5jdGlvbicpIHtcblx0XHRpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fVxuXHRcdG9wdGlvbnMucmVnbCA9IHJlZ2xcblx0fVxuXHRlbHNlIHtcblx0XHRvcHRpb25zID0gcmVnbFxuXHR9XG5cdGlmIChvcHRpb25zLmxlbmd0aCkgb3B0aW9ucy5wb3NpdGlvbnMgPSBvcHRpb25zXG5cdHJlZ2wgPSBvcHRpb25zLnJlZ2xcblxuXHRpZiAoIXJlZ2wuaGFzRXh0ZW5zaW9uKCdBTkdMRV9pbnN0YW5jZWRfYXJyYXlzJykpIHtcblx0XHR0aHJvdyBFcnJvcigncmVnbC1lcnJvcjJkOiBgQU5HTEVfaW5zdGFuY2VkX2FycmF5c2AgZXh0ZW5zaW9uIHNob3VsZCBiZSBlbmFibGVkJyk7XG5cdH1cblxuXHQvLyBwZXJzaXN0ZW50IHZhcmlhYmxlc1xuXHR0aGlzLmdsID0gcmVnbC5fZ2xcblx0dGhpcy5yZWdsID0gcmVnbFxuXG5cdC8vIGxpc3Qgb2Ygb3B0aW9ucyBmb3IgbGluZXNcblx0dGhpcy5wYXNzZXMgPSBbXVxuXG5cdC8vIGNhY2hlZCBzaGFkZXJzIGluc3RhbmNlXG5cdHRoaXMuc2hhZGVycyA9IExpbmUyRC5zaGFkZXJzLmhhcyhyZWdsKSA/IExpbmUyRC5zaGFkZXJzLmdldChyZWdsKSA6IExpbmUyRC5zaGFkZXJzLnNldChyZWdsLCBMaW5lMkQuY3JlYXRlU2hhZGVycyhyZWdsKSkuZ2V0KHJlZ2wpXG5cblxuXHQvLyBpbml0IGRlZmF1bHRzXG5cdHRoaXMudXBkYXRlKG9wdGlvbnMpXG59XG5cblxuTGluZTJELmRhc2hNdWx0ID0gMlxuTGluZTJELm1heFBhdHRlcm5MZW5ndGggPSAyNTZcbkxpbmUyRC5wcmVjaXNpb25UaHJlc2hvbGQgPSAzZTZcbkxpbmUyRC5tYXhQb2ludHMgPSAxZTRcbkxpbmUyRC5tYXhMaW5lcyA9IDIwNDhcblxuXG4vLyBjYWNoZSBvZiBjcmVhdGVkIGRyYXcgY2FsbHMgcGVyLXJlZ2wgaW5zdGFuY2VcbkxpbmUyRC5zaGFkZXJzID0gbmV3IFdlYWtNYXAoKVxuXG5cbi8vIGNyZWF0ZSBzdGF0aWMgc2hhZGVycyBvbmNlXG5MaW5lMkQuY3JlYXRlU2hhZGVycyA9IGZ1bmN0aW9uIChyZWdsKSB7XG5cdGxldCBvZmZzZXRCdWZmZXIgPSByZWdsLmJ1ZmZlcih7XG5cdFx0dXNhZ2U6ICdzdGF0aWMnLFxuXHRcdHR5cGU6ICdmbG9hdCcsXG5cdFx0ZGF0YTogWzAsMSwgMCwwLCAxLDEsIDEsMF1cblx0fSlcblxuXHRsZXQgc2hhZGVyT3B0aW9ucyA9IHtcblx0XHRwcmltaXRpdmU6ICd0cmlhbmdsZSBzdHJpcCcsXG5cdFx0aW5zdGFuY2VzOiByZWdsLnByb3AoJ2NvdW50JyksXG5cdFx0Y291bnQ6IDQsXG5cdFx0b2Zmc2V0OiAwLFxuXG5cdFx0dW5pZm9ybXM6IHtcblx0XHRcdG1pdGVyTW9kZTogKGN0eCwgcHJvcCkgPT4gcHJvcC5qb2luID09PSAncm91bmQnID8gMiA6IDEsXG5cdFx0XHRtaXRlckxpbWl0OiByZWdsLnByb3AoJ21pdGVyTGltaXQnKSxcblx0XHRcdHNjYWxlOiByZWdsLnByb3AoJ3NjYWxlJyksXG5cdFx0XHRzY2FsZUZyYWN0OiByZWdsLnByb3AoJ3NjYWxlRnJhY3QnKSxcblx0XHRcdHRyYW5zbGF0ZUZyYWN0OiByZWdsLnByb3AoJ3RyYW5zbGF0ZUZyYWN0JyksXG5cdFx0XHR0cmFuc2xhdGU6IHJlZ2wucHJvcCgndHJhbnNsYXRlJyksXG5cdFx0XHR0aGlja25lc3M6IHJlZ2wucHJvcCgndGhpY2tuZXNzJyksXG5cdFx0XHRkYXNoUGF0dGVybjogcmVnbC5wcm9wKCdkYXNoVGV4dHVyZScpLFxuXHRcdFx0b3BhY2l0eTogcmVnbC5wcm9wKCdvcGFjaXR5JyksXG5cdFx0XHRwaXhlbFJhdGlvOiByZWdsLmNvbnRleHQoJ3BpeGVsUmF0aW8nKSxcblx0XHRcdGlkOiByZWdsLnByb3AoJ2lkJyksXG5cdFx0XHRkYXNoU2l6ZTogcmVnbC5wcm9wKCdkYXNoTGVuZ3RoJyksXG5cdFx0XHR2aWV3cG9ydDogKGMsIHApID0+IFtwLnZpZXdwb3J0LngsIHAudmlld3BvcnQueSwgYy52aWV3cG9ydFdpZHRoLCBjLnZpZXdwb3J0SGVpZ2h0XSxcblx0XHRcdGRlcHRoOiByZWdsLnByb3AoJ2RlcHRoJylcblx0XHR9LFxuXG5cdFx0YmxlbmQ6IHtcblx0XHRcdGVuYWJsZTogdHJ1ZSxcblx0XHRcdGNvbG9yOiBbMCwwLDAsMF0sXG5cdFx0XHRlcXVhdGlvbjoge1xuXHRcdFx0XHRyZ2I6ICdhZGQnLFxuXHRcdFx0XHRhbHBoYTogJ2FkZCdcblx0XHRcdH0sXG5cdFx0XHRmdW5jOiB7XG5cdFx0XHRcdHNyY1JHQjogJ3NyYyBhbHBoYScsXG5cdFx0XHRcdGRzdFJHQjogJ29uZSBtaW51cyBzcmMgYWxwaGEnLFxuXHRcdFx0XHRzcmNBbHBoYTogJ29uZSBtaW51cyBkc3QgYWxwaGEnLFxuXHRcdFx0XHRkc3RBbHBoYTogJ29uZSdcblx0XHRcdH1cblx0XHR9LFxuXHRcdGRlcHRoOiB7XG5cdFx0XHRlbmFibGU6IChjLCBwKSA9PiB7XG5cdFx0XHRcdHJldHVybiAhcC5vdmVybGF5XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzdGVuY2lsOiB7ZW5hYmxlOiBmYWxzZX0sXG5cdFx0c2Npc3Nvcjoge1xuXHRcdFx0ZW5hYmxlOiB0cnVlLFxuXHRcdFx0Ym94OiByZWdsLnByb3AoJ3ZpZXdwb3J0Jylcblx0XHR9LFxuXHRcdHZpZXdwb3J0OiByZWdsLnByb3AoJ3ZpZXdwb3J0Jylcblx0fVxuXG5cblx0Ly8gc2ltcGxpZmllZCByZWN0YW5ndWxhciBsaW5lIHNoYWRlclxuXHRsZXQgZHJhd1JlY3RMaW5lID0gcmVnbChleHRlbmQoe1xuXHRcdHZlcnQ6IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgYUNvb3JkLCBiQ29vcmQsIGFDb29yZEZyYWN0LCBiQ29vcmRGcmFjdDtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5hdHRyaWJ1dGUgZmxvYXQgbGluZUVuZCwgbGluZVRvcDtcXG5cXG51bmlmb3JtIHZlYzIgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3Q7XFxudW5pZm9ybSBmbG9hdCB0aGlja25lc3MsIHBpeGVsUmF0aW8sIGlkLCBkZXB0aDtcXG51bmlmb3JtIHZlYzQgdmlld3BvcnQ7XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG52YXJ5aW5nIHZlYzIgdGFuZ2VudDtcXG5cXG52ZWMyIHByb2plY3QodmVjMiBwb3NpdGlvbiwgdmVjMiBwb3NpdGlvbkZyYWN0LCB2ZWMyIHNjYWxlLCB2ZWMyIHNjYWxlRnJhY3QsIHZlYzIgdHJhbnNsYXRlLCB2ZWMyIHRyYW5zbGF0ZUZyYWN0KSB7XFxuXFx0Ly8gdGhlIG9yZGVyIGlzIGltcG9ydGFudFxcblxcdHJldHVybiBwb3NpdGlvbiAqIHNjYWxlICsgdHJhbnNsYXRlXFxuICAgICAgICsgcG9zaXRpb25GcmFjdCAqIHNjYWxlICsgdHJhbnNsYXRlRnJhY3RcXG4gICAgICAgKyBwb3NpdGlvbiAqIHNjYWxlRnJhY3RcXG4gICAgICAgKyBwb3NpdGlvbkZyYWN0ICogc2NhbGVGcmFjdDtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcblxcdGZsb2F0IGxpbmVTdGFydCA9IDEuIC0gbGluZUVuZDtcXG5cXHRmbG9hdCBsaW5lT2Zmc2V0ID0gbGluZVRvcCAqIDIuIC0gMS47XFxuXFxuXFx0dmVjMiBkaWZmID0gKGJDb29yZCArIGJDb29yZEZyYWN0IC0gYUNvb3JkIC0gYUNvb3JkRnJhY3QpO1xcblxcdHRhbmdlbnQgPSBub3JtYWxpemUoZGlmZiAqIHNjYWxlICogdmlld3BvcnQuencpO1xcblxcdHZlYzIgbm9ybWFsID0gdmVjMigtdGFuZ2VudC55LCB0YW5nZW50LngpO1xcblxcblxcdHZlYzIgcG9zaXRpb24gPSBwcm9qZWN0KGFDb29yZCwgYUNvb3JkRnJhY3QsIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0KSAqIGxpbmVTdGFydFxcblxcdFxcdCsgcHJvamVjdChiQ29vcmQsIGJDb29yZEZyYWN0LCBzY2FsZSwgc2NhbGVGcmFjdCwgdHJhbnNsYXRlLCB0cmFuc2xhdGVGcmFjdCkgKiBsaW5lRW5kXFxuXFxuXFx0XFx0KyB0aGlja25lc3MgKiBub3JtYWwgKiAuNSAqIGxpbmVPZmZzZXQgLyB2aWV3cG9ydC56dztcXG5cXG5cXHRnbF9Qb3NpdGlvbiA9IHZlYzQocG9zaXRpb24gKiAyLjAgLSAxLjAsIGRlcHRoLCAxKTtcXG5cXG5cXHRmcmFnQ29sb3IgPSBjb2xvciAvIDI1NS47XFxufVxcblwiXSksXG5cdFx0ZnJhZzogZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG51bmlmb3JtIHNhbXBsZXIyRCBkYXNoUGF0dGVybjtcXG5cXG51bmlmb3JtIGZsb2F0IGRhc2hTaXplLCBwaXhlbFJhdGlvLCB0aGlja25lc3MsIG9wYWNpdHksIGlkO1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxudmFyeWluZyB2ZWMyIHRhbmdlbnQ7XFxuXFxudm9pZCBtYWluKCkge1xcblxcdGZsb2F0IGFscGhhID0gMS47XFxuXFxuXFx0ZmxvYXQgdCA9IGZyYWN0KGRvdCh0YW5nZW50LCBnbF9GcmFnQ29vcmQueHkpIC8gZGFzaFNpemUpICogLjUgKyAuMjU7XFxuXFx0ZmxvYXQgZGFzaCA9IHRleHR1cmUyRChkYXNoUGF0dGVybiwgdmVjMih0LCAuNSkpLnI7XFxuXFxuXFx0Z2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcblxcdGdsX0ZyYWdDb2xvci5hICo9IGFscGhhICogb3BhY2l0eSAqIGRhc2g7XFxufVxcblwiXSksXG5cblx0XHRhdHRyaWJ1dGVzOiB7XG5cdFx0XHQvLyBpZiBwb2ludCBpcyBhdCB0aGUgZW5kIG9mIHNlZ21lbnRcblx0XHRcdGxpbmVFbmQ6IHtcblx0XHRcdFx0YnVmZmVyOiBvZmZzZXRCdWZmZXIsXG5cdFx0XHRcdGRpdmlzb3I6IDAsXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiAwXG5cdFx0XHR9LFxuXHRcdFx0Ly8gaWYgcG9pbnQgaXMgYXQgdGhlIHRvcCBvZiBzZWdtZW50XG5cdFx0XHRsaW5lVG9wOiB7XG5cdFx0XHRcdGJ1ZmZlcjogb2Zmc2V0QnVmZmVyLFxuXHRcdFx0XHRkaXZpc29yOiAwLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogNFxuXHRcdFx0fSxcblx0XHRcdC8vIGJlZ2lubmluZyBvZiBsaW5lIGNvb3JkaW5hdGVcblx0XHRcdGFDb29yZDoge1xuXHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgncG9zaXRpb25CdWZmZXInKSxcblx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRvZmZzZXQ6IDgsXG5cdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdH0sXG5cdFx0XHQvLyBlbmQgb2YgbGluZSBjb29yZGluYXRlXG5cdFx0XHRiQ29vcmQ6IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiAxNixcblx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0fSxcblx0XHRcdGFDb29yZEZyYWN0OiB7XG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkZyYWN0QnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiA4LFxuXHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHR9LFxuXHRcdFx0YkNvb3JkRnJhY3Q6IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uRnJhY3RCdWZmZXInKSxcblx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRvZmZzZXQ6IDE2LFxuXHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHR9LFxuXHRcdFx0Y29sb3I6IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ2NvbG9yQnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogNCxcblx0XHRcdFx0b2Zmc2V0OiAwLFxuXHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHR9XG5cdFx0fVxuXHR9LCBzaGFkZXJPcHRpb25zKSlcblxuXHQvLyBjcmVhdGUgcmVnbCBkcmF3XG5cdGxldCBkcmF3TWl0ZXJMaW5lXG5cblx0dHJ5IHtcblx0XHRkcmF3TWl0ZXJMaW5lID0gcmVnbChleHRlbmQoe1xuXHRcdFx0Ly8gY3VsbGluZyByZW1vdmVzIHBvbHlnb24gY3JlYXNpbmdcblx0XHRcdGN1bGw6IHtcblx0XHRcdFx0ZW5hYmxlOiB0cnVlLFxuXHRcdFx0XHRmYWNlOiAnYmFjaydcblx0XHRcdH0sXG5cblx0XHRcdHZlcnQ6IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgYUNvb3JkLCBiQ29vcmQsIG5leHRDb29yZCwgcHJldkNvb3JkO1xcbmF0dHJpYnV0ZSB2ZWM0IGFDb2xvciwgYkNvbG9yO1xcbmF0dHJpYnV0ZSBmbG9hdCBsaW5lRW5kLCBsaW5lVG9wO1xcblxcbnVuaWZvcm0gdmVjMiBzY2FsZSwgdHJhbnNsYXRlO1xcbnVuaWZvcm0gZmxvYXQgdGhpY2tuZXNzLCBwaXhlbFJhdGlvLCBpZCwgZGVwdGg7XFxudW5pZm9ybSB2ZWM0IHZpZXdwb3J0O1xcbnVuaWZvcm0gZmxvYXQgbWl0ZXJMaW1pdCwgbWl0ZXJNb2RlO1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxudmFyeWluZyB2ZWM0IHN0YXJ0Q3V0b2ZmLCBlbmRDdXRvZmY7XFxudmFyeWluZyB2ZWMyIHRhbmdlbnQ7XFxudmFyeWluZyB2ZWMyIHN0YXJ0Q29vcmQsIGVuZENvb3JkO1xcbnZhcnlpbmcgZmxvYXQgZW5hYmxlU3RhcnRNaXRlciwgZW5hYmxlRW5kTWl0ZXI7XFxuXFxuY29uc3QgZmxvYXQgUkVWRVJTRV9USFJFU0hPTEQgPSAtLjg3NTtcXG5jb25zdCBmbG9hdCBNSU5fRElGRiA9IDFlLTY7XFxuXFxuLy8gVE9ETzogcG9zc2libGUgb3B0aW1pemF0aW9uczogYXZvaWQgb3ZlcmNhbGN1bGF0aW5nIGFsbCBmb3IgdmVydGljZXMgYW5kIGNhbGMganVzdCBvbmUgaW5zdGVhZFxcbi8vIFRPRE86IHByZWNhbGN1bGF0ZSBkb3QgcHJvZHVjdHMsIG5vcm1hbGl6ZSB0aGluZ3MgYmVmb3JlaGVhZCBldGMuXFxuLy8gVE9ETzogcmVmYWN0b3IgdG8gcmVjdGFuZ3VsYXIgYWxnb3JpdGhtXFxuXFxuZmxvYXQgZGlzdFRvTGluZSh2ZWMyIHAsIHZlYzIgYSwgdmVjMiBiKSB7XFxuXFx0dmVjMiBkaWZmID0gYiAtIGE7XFxuXFx0dmVjMiBwZXJwID0gbm9ybWFsaXplKHZlYzIoLWRpZmYueSwgZGlmZi54KSk7XFxuXFx0cmV0dXJuIGRvdChwIC0gYSwgcGVycCk7XFxufVxcblxcbmJvb2wgaXNOYU4oIGZsb2F0IHZhbCApe1xcbiAgcmV0dXJuICggdmFsIDwgMC4wIHx8IDAuMCA8IHZhbCB8fCB2YWwgPT0gMC4wICkgPyBmYWxzZSA6IHRydWU7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG5cXHR2ZWMyIGFDb29yZCA9IGFDb29yZCwgYkNvb3JkID0gYkNvb3JkLCBwcmV2Q29vcmQgPSBwcmV2Q29vcmQsIG5leHRDb29yZCA9IG5leHRDb29yZDtcXG5cXG4gIHZlYzIgYWRqdXN0ZWRTY2FsZTtcXG4gIGFkanVzdGVkU2NhbGUueCA9IChhYnMoc2NhbGUueCkgPCBNSU5fRElGRikgPyBNSU5fRElGRiA6IHNjYWxlLng7XFxuICBhZGp1c3RlZFNjYWxlLnkgPSAoYWJzKHNjYWxlLnkpIDwgTUlOX0RJRkYpID8gTUlOX0RJRkYgOiBzY2FsZS55O1xcblxcbiAgdmVjMiBzY2FsZVJhdGlvID0gYWRqdXN0ZWRTY2FsZSAqIHZpZXdwb3J0Lnp3O1xcblxcdHZlYzIgbm9ybWFsV2lkdGggPSB0aGlja25lc3MgLyBzY2FsZVJhdGlvO1xcblxcblxcdGZsb2F0IGxpbmVTdGFydCA9IDEuIC0gbGluZUVuZDtcXG5cXHRmbG9hdCBsaW5lQm90ID0gMS4gLSBsaW5lVG9wO1xcblxcblxcdGZyYWdDb2xvciA9IChsaW5lU3RhcnQgKiBhQ29sb3IgKyBsaW5lRW5kICogYkNvbG9yKSAvIDI1NS47XFxuXFxuXFx0aWYgKGlzTmFOKGFDb29yZC54KSB8fCBpc05hTihhQ29vcmQueSkgfHwgaXNOYU4oYkNvb3JkLngpIHx8IGlzTmFOKGJDb29yZC55KSkgcmV0dXJuO1xcblxcblxcdGlmIChhQ29vcmQgPT0gcHJldkNvb3JkKSBwcmV2Q29vcmQgPSBhQ29vcmQgKyBub3JtYWxpemUoYkNvb3JkIC0gYUNvb3JkKTtcXG5cXHRpZiAoYkNvb3JkID09IG5leHRDb29yZCkgbmV4dENvb3JkID0gYkNvb3JkIC0gbm9ybWFsaXplKGJDb29yZCAtIGFDb29yZCk7XFxuXFxuXFx0dmVjMiBwcmV2RGlmZiA9IGFDb29yZCAtIHByZXZDb29yZDtcXG5cXHR2ZWMyIGN1cnJEaWZmID0gYkNvb3JkIC0gYUNvb3JkO1xcblxcdHZlYzIgbmV4dERpZmYgPSBuZXh0Q29vcmQgLSBiQ29vcmQ7XFxuXFxuXFx0dmVjMiBwcmV2VGFuZ2VudCA9IG5vcm1hbGl6ZShwcmV2RGlmZiAqIHNjYWxlUmF0aW8pO1xcblxcdHZlYzIgY3VyclRhbmdlbnQgPSBub3JtYWxpemUoY3VyckRpZmYgKiBzY2FsZVJhdGlvKTtcXG5cXHR2ZWMyIG5leHRUYW5nZW50ID0gbm9ybWFsaXplKG5leHREaWZmICogc2NhbGVSYXRpbyk7XFxuXFxuXFx0dmVjMiBwcmV2Tm9ybWFsID0gdmVjMigtcHJldlRhbmdlbnQueSwgcHJldlRhbmdlbnQueCk7XFxuXFx0dmVjMiBjdXJyTm9ybWFsID0gdmVjMigtY3VyclRhbmdlbnQueSwgY3VyclRhbmdlbnQueCk7XFxuXFx0dmVjMiBuZXh0Tm9ybWFsID0gdmVjMigtbmV4dFRhbmdlbnQueSwgbmV4dFRhbmdlbnQueCk7XFxuXFxuXFx0dmVjMiBzdGFydEpvaW5EaXJlY3Rpb24gPSBub3JtYWxpemUocHJldlRhbmdlbnQgLSBjdXJyVGFuZ2VudCk7XFxuXFx0dmVjMiBlbmRKb2luRGlyZWN0aW9uID0gbm9ybWFsaXplKGN1cnJUYW5nZW50IC0gbmV4dFRhbmdlbnQpO1xcblxcblxcdC8vIGNvbGxhcHNlZC91bmlkaXJlY3Rpb25hbCBzZWdtZW50IGNhc2VzXFxuXFx0Ly8gRklYTUU6IHRoZXJlIHNob3VsZCBiZSBtb3JlIGVsZWdhbnQgc29sdXRpb25cXG5cXHR2ZWMyIHByZXZUYW5EaWZmID0gYWJzKHByZXZUYW5nZW50IC0gY3VyclRhbmdlbnQpO1xcblxcdHZlYzIgbmV4dFRhbkRpZmYgPSBhYnMobmV4dFRhbmdlbnQgLSBjdXJyVGFuZ2VudCk7XFxuXFx0aWYgKG1heChwcmV2VGFuRGlmZi54LCBwcmV2VGFuRGlmZi55KSA8IE1JTl9ESUZGKSB7XFxuXFx0XFx0c3RhcnRKb2luRGlyZWN0aW9uID0gY3Vyck5vcm1hbDtcXG5cXHR9XFxuXFx0aWYgKG1heChuZXh0VGFuRGlmZi54LCBuZXh0VGFuRGlmZi55KSA8IE1JTl9ESUZGKSB7XFxuXFx0XFx0ZW5kSm9pbkRpcmVjdGlvbiA9IGN1cnJOb3JtYWw7XFxuXFx0fVxcblxcdGlmIChhQ29vcmQgPT0gYkNvb3JkKSB7XFxuXFx0XFx0ZW5kSm9pbkRpcmVjdGlvbiA9IHN0YXJ0Sm9pbkRpcmVjdGlvbjtcXG5cXHRcXHRjdXJyTm9ybWFsID0gcHJldk5vcm1hbDtcXG5cXHRcXHRjdXJyVGFuZ2VudCA9IHByZXZUYW5nZW50O1xcblxcdH1cXG5cXG5cXHR0YW5nZW50ID0gY3VyclRhbmdlbnQ7XFxuXFxuXFx0Ly9jYWxjdWxhdGUgam9pbiBzaGlmdHMgcmVsYXRpdmUgdG8gbm9ybWFsc1xcblxcdGZsb2F0IHN0YXJ0Sm9pblNoaWZ0ID0gZG90KGN1cnJOb3JtYWwsIHN0YXJ0Sm9pbkRpcmVjdGlvbik7XFxuXFx0ZmxvYXQgZW5kSm9pblNoaWZ0ID0gZG90KGN1cnJOb3JtYWwsIGVuZEpvaW5EaXJlY3Rpb24pO1xcblxcblxcdGZsb2F0IHN0YXJ0TWl0ZXJSYXRpbyA9IGFicygxLiAvIHN0YXJ0Sm9pblNoaWZ0KTtcXG5cXHRmbG9hdCBlbmRNaXRlclJhdGlvID0gYWJzKDEuIC8gZW5kSm9pblNoaWZ0KTtcXG5cXG5cXHR2ZWMyIHN0YXJ0Sm9pbiA9IHN0YXJ0Sm9pbkRpcmVjdGlvbiAqIHN0YXJ0TWl0ZXJSYXRpbztcXG5cXHR2ZWMyIGVuZEpvaW4gPSBlbmRKb2luRGlyZWN0aW9uICogZW5kTWl0ZXJSYXRpbztcXG5cXG5cXHR2ZWMyIHN0YXJ0VG9wSm9pbiwgc3RhcnRCb3RKb2luLCBlbmRUb3BKb2luLCBlbmRCb3RKb2luO1xcblxcdHN0YXJ0VG9wSm9pbiA9IHNpZ24oc3RhcnRKb2luU2hpZnQpICogc3RhcnRKb2luICogLjU7XFxuXFx0c3RhcnRCb3RKb2luID0gLXN0YXJ0VG9wSm9pbjtcXG5cXG5cXHRlbmRUb3BKb2luID0gc2lnbihlbmRKb2luU2hpZnQpICogZW5kSm9pbiAqIC41O1xcblxcdGVuZEJvdEpvaW4gPSAtZW5kVG9wSm9pbjtcXG5cXG5cXHR2ZWMyIGFUb3BDb29yZCA9IGFDb29yZCArIG5vcm1hbFdpZHRoICogc3RhcnRUb3BKb2luO1xcblxcdHZlYzIgYlRvcENvb3JkID0gYkNvb3JkICsgbm9ybWFsV2lkdGggKiBlbmRUb3BKb2luO1xcblxcdHZlYzIgYUJvdENvb3JkID0gYUNvb3JkICsgbm9ybWFsV2lkdGggKiBzdGFydEJvdEpvaW47XFxuXFx0dmVjMiBiQm90Q29vcmQgPSBiQ29vcmQgKyBub3JtYWxXaWR0aCAqIGVuZEJvdEpvaW47XFxuXFxuXFx0Ly9taXRlciBhbnRpLWNsaXBwaW5nXFxuXFx0ZmxvYXQgYmFDbGlwcGluZyA9IGRpc3RUb0xpbmUoYkNvb3JkLCBhQ29vcmQsIGFCb3RDb29yZCkgLyBkb3Qobm9ybWFsaXplKG5vcm1hbFdpZHRoICogZW5kQm90Sm9pbiksIG5vcm1hbGl6ZShub3JtYWxXaWR0aC55eCAqIHZlYzIoLXN0YXJ0Qm90Sm9pbi55LCBzdGFydEJvdEpvaW4ueCkpKTtcXG5cXHRmbG9hdCBhYkNsaXBwaW5nID0gZGlzdFRvTGluZShhQ29vcmQsIGJDb29yZCwgYlRvcENvb3JkKSAvIGRvdChub3JtYWxpemUobm9ybWFsV2lkdGggKiBzdGFydEJvdEpvaW4pLCBub3JtYWxpemUobm9ybWFsV2lkdGgueXggKiB2ZWMyKC1lbmRCb3RKb2luLnksIGVuZEJvdEpvaW4ueCkpKTtcXG5cXG5cXHQvL3ByZXZlbnQgY2xvc2UgdG8gcmV2ZXJzZSBkaXJlY3Rpb24gc3dpdGNoXFxuXFx0Ym9vbCBwcmV2UmV2ZXJzZSA9IGRvdChjdXJyVGFuZ2VudCwgcHJldlRhbmdlbnQpIDw9IFJFVkVSU0VfVEhSRVNIT0xEICYmIGFicyhkb3QoY3VyclRhbmdlbnQsIHByZXZOb3JtYWwpKSAqIG1pbihsZW5ndGgocHJldkRpZmYpLCBsZW5ndGgoY3VyckRpZmYpKSA8ICBsZW5ndGgobm9ybWFsV2lkdGggKiBjdXJyTm9ybWFsKTtcXG5cXHRib29sIG5leHRSZXZlcnNlID0gZG90KGN1cnJUYW5nZW50LCBuZXh0VGFuZ2VudCkgPD0gUkVWRVJTRV9USFJFU0hPTEQgJiYgYWJzKGRvdChjdXJyVGFuZ2VudCwgbmV4dE5vcm1hbCkpICogbWluKGxlbmd0aChuZXh0RGlmZiksIGxlbmd0aChjdXJyRGlmZikpIDwgIGxlbmd0aChub3JtYWxXaWR0aCAqIGN1cnJOb3JtYWwpO1xcblxcblxcdGlmIChwcmV2UmV2ZXJzZSkge1xcblxcdFxcdC8vbWFrZSBqb2luIHJlY3Rhbmd1bGFyXFxuXFx0XFx0dmVjMiBtaXRlclNoaWZ0ID0gbm9ybWFsV2lkdGggKiBzdGFydEpvaW5EaXJlY3Rpb24gKiBtaXRlckxpbWl0ICogLjU7XFxuXFx0XFx0ZmxvYXQgbm9ybWFsQWRqdXN0ID0gMS4gLSBtaW4obWl0ZXJMaW1pdCAvIHN0YXJ0TWl0ZXJSYXRpbywgMS4pO1xcblxcdFxcdGFCb3RDb29yZCA9IGFDb29yZCArIG1pdGVyU2hpZnQgLSBub3JtYWxBZGp1c3QgKiBub3JtYWxXaWR0aCAqIGN1cnJOb3JtYWwgKiAuNTtcXG5cXHRcXHRhVG9wQ29vcmQgPSBhQ29vcmQgKyBtaXRlclNoaWZ0ICsgbm9ybWFsQWRqdXN0ICogbm9ybWFsV2lkdGggKiBjdXJyTm9ybWFsICogLjU7XFxuXFx0fVxcblxcdGVsc2UgaWYgKCFuZXh0UmV2ZXJzZSAmJiBiYUNsaXBwaW5nID4gMC4gJiYgYmFDbGlwcGluZyA8IGxlbmd0aChub3JtYWxXaWR0aCAqIGVuZEJvdEpvaW4pKSB7XFxuXFx0XFx0Ly9oYW5kbGUgbWl0ZXIgY2xpcHBpbmdcXG5cXHRcXHRiVG9wQ29vcmQgLT0gbm9ybWFsV2lkdGggKiBlbmRUb3BKb2luO1xcblxcdFxcdGJUb3BDb29yZCArPSBub3JtYWxpemUoZW5kVG9wSm9pbiAqIG5vcm1hbFdpZHRoKSAqIGJhQ2xpcHBpbmc7XFxuXFx0fVxcblxcblxcdGlmIChuZXh0UmV2ZXJzZSkge1xcblxcdFxcdC8vbWFrZSBqb2luIHJlY3Rhbmd1bGFyXFxuXFx0XFx0dmVjMiBtaXRlclNoaWZ0ID0gbm9ybWFsV2lkdGggKiBlbmRKb2luRGlyZWN0aW9uICogbWl0ZXJMaW1pdCAqIC41O1xcblxcdFxcdGZsb2F0IG5vcm1hbEFkanVzdCA9IDEuIC0gbWluKG1pdGVyTGltaXQgLyBlbmRNaXRlclJhdGlvLCAxLik7XFxuXFx0XFx0YkJvdENvb3JkID0gYkNvb3JkICsgbWl0ZXJTaGlmdCAtIG5vcm1hbEFkanVzdCAqIG5vcm1hbFdpZHRoICogY3Vyck5vcm1hbCAqIC41O1xcblxcdFxcdGJUb3BDb29yZCA9IGJDb29yZCArIG1pdGVyU2hpZnQgKyBub3JtYWxBZGp1c3QgKiBub3JtYWxXaWR0aCAqIGN1cnJOb3JtYWwgKiAuNTtcXG5cXHR9XFxuXFx0ZWxzZSBpZiAoIXByZXZSZXZlcnNlICYmIGFiQ2xpcHBpbmcgPiAwLiAmJiBhYkNsaXBwaW5nIDwgbGVuZ3RoKG5vcm1hbFdpZHRoICogc3RhcnRCb3RKb2luKSkge1xcblxcdFxcdC8vaGFuZGxlIG1pdGVyIGNsaXBwaW5nXFxuXFx0XFx0YUJvdENvb3JkIC09IG5vcm1hbFdpZHRoICogc3RhcnRCb3RKb2luO1xcblxcdFxcdGFCb3RDb29yZCArPSBub3JtYWxpemUoc3RhcnRCb3RKb2luICogbm9ybWFsV2lkdGgpICogYWJDbGlwcGluZztcXG5cXHR9XFxuXFxuXFx0dmVjMiBhVG9wUG9zaXRpb24gPSAoYVRvcENvb3JkKSAqIGFkanVzdGVkU2NhbGUgKyB0cmFuc2xhdGU7XFxuXFx0dmVjMiBhQm90UG9zaXRpb24gPSAoYUJvdENvb3JkKSAqIGFkanVzdGVkU2NhbGUgKyB0cmFuc2xhdGU7XFxuXFxuXFx0dmVjMiBiVG9wUG9zaXRpb24gPSAoYlRvcENvb3JkKSAqIGFkanVzdGVkU2NhbGUgKyB0cmFuc2xhdGU7XFxuXFx0dmVjMiBiQm90UG9zaXRpb24gPSAoYkJvdENvb3JkKSAqIGFkanVzdGVkU2NhbGUgKyB0cmFuc2xhdGU7XFxuXFxuXFx0Ly9wb3NpdGlvbiBpcyBub3JtYWxpemVkIDAuLjEgY29vcmQgb24gdGhlIHNjcmVlblxcblxcdHZlYzIgcG9zaXRpb24gPSAoYVRvcFBvc2l0aW9uICogbGluZVRvcCArIGFCb3RQb3NpdGlvbiAqIGxpbmVCb3QpICogbGluZVN0YXJ0ICsgKGJUb3BQb3NpdGlvbiAqIGxpbmVUb3AgKyBiQm90UG9zaXRpb24gKiBsaW5lQm90KSAqIGxpbmVFbmQ7XFxuXFxuXFx0c3RhcnRDb29yZCA9IGFDb29yZCAqIHNjYWxlUmF0aW8gKyB0cmFuc2xhdGUgKiB2aWV3cG9ydC56dyArIHZpZXdwb3J0Lnh5O1xcblxcdGVuZENvb3JkID0gYkNvb3JkICogc2NhbGVSYXRpbyArIHRyYW5zbGF0ZSAqIHZpZXdwb3J0Lnp3ICsgdmlld3BvcnQueHk7XFxuXFxuXFx0Z2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uICAqIDIuMCAtIDEuMCwgZGVwdGgsIDEpO1xcblxcblxcdGVuYWJsZVN0YXJ0TWl0ZXIgPSBzdGVwKGRvdChjdXJyVGFuZ2VudCwgcHJldlRhbmdlbnQpLCAuNSk7XFxuXFx0ZW5hYmxlRW5kTWl0ZXIgPSBzdGVwKGRvdChjdXJyVGFuZ2VudCwgbmV4dFRhbmdlbnQpLCAuNSk7XFxuXFxuXFx0Ly9iZXZlbCBtaXRlciBjdXRvZmZzXFxuXFx0aWYgKG1pdGVyTW9kZSA9PSAxLikge1xcblxcdFxcdGlmIChlbmFibGVTdGFydE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0dmVjMiBzdGFydE1pdGVyV2lkdGggPSB2ZWMyKHN0YXJ0Sm9pbkRpcmVjdGlvbikgKiB0aGlja25lc3MgKiBtaXRlckxpbWl0ICogLjU7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgPSB2ZWM0KGFDb29yZCwgYUNvb3JkKTtcXG5cXHRcXHRcXHRzdGFydEN1dG9mZi56dyArPSB2ZWMyKC1zdGFydEpvaW5EaXJlY3Rpb24ueSwgc3RhcnRKb2luRGlyZWN0aW9uLngpIC8gc2NhbGVSYXRpbztcXG5cXHRcXHRcXHRzdGFydEN1dG9mZiA9IHN0YXJ0Q3V0b2ZmICogc2NhbGVSYXRpby54eXh5ICsgdHJhbnNsYXRlLnh5eHkgKiB2aWV3cG9ydC56d3p3O1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmICs9IHZpZXdwb3J0Lnh5eHk7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgKz0gc3RhcnRNaXRlcldpZHRoLnh5eHk7XFxuXFx0XFx0fVxcblxcblxcdFxcdGlmIChlbmFibGVFbmRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdHZlYzIgZW5kTWl0ZXJXaWR0aCA9IHZlYzIoZW5kSm9pbkRpcmVjdGlvbikgKiB0aGlja25lc3MgKiBtaXRlckxpbWl0ICogLjU7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmID0gdmVjNChiQ29vcmQsIGJDb29yZCk7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmLnp3ICs9IHZlYzIoLWVuZEpvaW5EaXJlY3Rpb24ueSwgZW5kSm9pbkRpcmVjdGlvbi54KSAgLyBzY2FsZVJhdGlvO1xcblxcdFxcdFxcdGVuZEN1dG9mZiA9IGVuZEN1dG9mZiAqIHNjYWxlUmF0aW8ueHl4eSArIHRyYW5zbGF0ZS54eXh5ICogdmlld3BvcnQuend6dztcXG5cXHRcXHRcXHRlbmRDdXRvZmYgKz0gdmlld3BvcnQueHl4eTtcXG5cXHRcXHRcXHRlbmRDdXRvZmYgKz0gZW5kTWl0ZXJXaWR0aC54eXh5O1xcblxcdFxcdH1cXG5cXHR9XFxuXFxuXFx0Ly9yb3VuZCBtaXRlciBjdXRvZmZzXFxuXFx0ZWxzZSBpZiAobWl0ZXJNb2RlID09IDIuKSB7XFxuXFx0XFx0aWYgKGVuYWJsZVN0YXJ0TWl0ZXIgPT0gMS4pIHtcXG5cXHRcXHRcXHR2ZWMyIHN0YXJ0TWl0ZXJXaWR0aCA9IHZlYzIoc3RhcnRKb2luRGlyZWN0aW9uKSAqIHRoaWNrbmVzcyAqIGFicyhkb3Qoc3RhcnRKb2luRGlyZWN0aW9uLCBjdXJyTm9ybWFsKSkgKiAuNTtcXG5cXHRcXHRcXHRzdGFydEN1dG9mZiA9IHZlYzQoYUNvb3JkLCBhQ29vcmQpO1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmLnp3ICs9IHZlYzIoLXN0YXJ0Sm9pbkRpcmVjdGlvbi55LCBzdGFydEpvaW5EaXJlY3Rpb24ueCkgLyBzY2FsZVJhdGlvO1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmID0gc3RhcnRDdXRvZmYgKiBzY2FsZVJhdGlvLnh5eHkgKyB0cmFuc2xhdGUueHl4eSAqIHZpZXdwb3J0Lnp3enc7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgKz0gdmlld3BvcnQueHl4eTtcXG5cXHRcXHRcXHRzdGFydEN1dG9mZiArPSBzdGFydE1pdGVyV2lkdGgueHl4eTtcXG5cXHRcXHR9XFxuXFxuXFx0XFx0aWYgKGVuYWJsZUVuZE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0dmVjMiBlbmRNaXRlcldpZHRoID0gdmVjMihlbmRKb2luRGlyZWN0aW9uKSAqIHRoaWNrbmVzcyAqIGFicyhkb3QoZW5kSm9pbkRpcmVjdGlvbiwgY3Vyck5vcm1hbCkpICogLjU7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmID0gdmVjNChiQ29vcmQsIGJDb29yZCk7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmLnp3ICs9IHZlYzIoLWVuZEpvaW5EaXJlY3Rpb24ueSwgZW5kSm9pbkRpcmVjdGlvbi54KSAgLyBzY2FsZVJhdGlvO1xcblxcdFxcdFxcdGVuZEN1dG9mZiA9IGVuZEN1dG9mZiAqIHNjYWxlUmF0aW8ueHl4eSArIHRyYW5zbGF0ZS54eXh5ICogdmlld3BvcnQuend6dztcXG5cXHRcXHRcXHRlbmRDdXRvZmYgKz0gdmlld3BvcnQueHl4eTtcXG5cXHRcXHRcXHRlbmRDdXRvZmYgKz0gZW5kTWl0ZXJXaWR0aC54eXh5O1xcblxcdFxcdH1cXG5cXHR9XFxufVxcblwiXSksXG5cdFx0XHRmcmFnOiBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gc2FtcGxlcjJEIGRhc2hQYXR0ZXJuO1xcbnVuaWZvcm0gZmxvYXQgZGFzaFNpemUsIHBpeGVsUmF0aW8sIHRoaWNrbmVzcywgb3BhY2l0eSwgaWQsIG1pdGVyTW9kZTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcbnZhcnlpbmcgdmVjMiB0YW5nZW50O1xcbnZhcnlpbmcgdmVjNCBzdGFydEN1dG9mZiwgZW5kQ3V0b2ZmO1xcbnZhcnlpbmcgdmVjMiBzdGFydENvb3JkLCBlbmRDb29yZDtcXG52YXJ5aW5nIGZsb2F0IGVuYWJsZVN0YXJ0TWl0ZXIsIGVuYWJsZUVuZE1pdGVyO1xcblxcbmZsb2F0IGRpc3RUb0xpbmUodmVjMiBwLCB2ZWMyIGEsIHZlYzIgYikge1xcblxcdHZlYzIgZGlmZiA9IGIgLSBhO1xcblxcdHZlYzIgcGVycCA9IG5vcm1hbGl6ZSh2ZWMyKC1kaWZmLnksIGRpZmYueCkpO1xcblxcdHJldHVybiBkb3QocCAtIGEsIHBlcnApO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuXFx0ZmxvYXQgYWxwaGEgPSAxLiwgZGlzdFRvU3RhcnQsIGRpc3RUb0VuZDtcXG5cXHRmbG9hdCBjdXRvZmYgPSB0aGlja25lc3MgKiAuNTtcXG5cXG5cXHQvL2JldmVsIG1pdGVyXFxuXFx0aWYgKG1pdGVyTW9kZSA9PSAxLikge1xcblxcdFxcdGlmIChlbmFibGVTdGFydE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0ZGlzdFRvU3RhcnQgPSBkaXN0VG9MaW5lKGdsX0ZyYWdDb29yZC54eSwgc3RhcnRDdXRvZmYueHksIHN0YXJ0Q3V0b2ZmLnp3KTtcXG5cXHRcXHRcXHRpZiAoZGlzdFRvU3RhcnQgPCAtMS4pIHtcXG5cXHRcXHRcXHRcXHRkaXNjYXJkO1xcblxcdFxcdFxcdFxcdHJldHVybjtcXG5cXHRcXHRcXHR9XFxuXFx0XFx0XFx0YWxwaGEgKj0gbWluKG1heChkaXN0VG9TdGFydCArIDEuLCAwLiksIDEuKTtcXG5cXHRcXHR9XFxuXFxuXFx0XFx0aWYgKGVuYWJsZUVuZE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0ZGlzdFRvRW5kID0gZGlzdFRvTGluZShnbF9GcmFnQ29vcmQueHksIGVuZEN1dG9mZi54eSwgZW5kQ3V0b2ZmLnp3KTtcXG5cXHRcXHRcXHRpZiAoZGlzdFRvRW5kIDwgLTEuKSB7XFxuXFx0XFx0XFx0XFx0ZGlzY2FyZDtcXG5cXHRcXHRcXHRcXHRyZXR1cm47XFxuXFx0XFx0XFx0fVxcblxcdFxcdFxcdGFscGhhICo9IG1pbihtYXgoZGlzdFRvRW5kICsgMS4sIDAuKSwgMS4pO1xcblxcdFxcdH1cXG5cXHR9XFxuXFxuXFx0Ly8gcm91bmQgbWl0ZXJcXG5cXHRlbHNlIGlmIChtaXRlck1vZGUgPT0gMi4pIHtcXG5cXHRcXHRpZiAoZW5hYmxlU3RhcnRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdGRpc3RUb1N0YXJ0ID0gZGlzdFRvTGluZShnbF9GcmFnQ29vcmQueHksIHN0YXJ0Q3V0b2ZmLnh5LCBzdGFydEN1dG9mZi56dyk7XFxuXFx0XFx0XFx0aWYgKGRpc3RUb1N0YXJ0IDwgMC4pIHtcXG5cXHRcXHRcXHRcXHRmbG9hdCByYWRpdXMgPSBsZW5ndGgoZ2xfRnJhZ0Nvb3JkLnh5IC0gc3RhcnRDb29yZCk7XFxuXFxuXFx0XFx0XFx0XFx0aWYocmFkaXVzID4gY3V0b2ZmICsgLjUpIHtcXG5cXHRcXHRcXHRcXHRcXHRkaXNjYXJkO1xcblxcdFxcdFxcdFxcdFxcdHJldHVybjtcXG5cXHRcXHRcXHRcXHR9XFxuXFxuXFx0XFx0XFx0XFx0YWxwaGEgLT0gc21vb3Roc3RlcChjdXRvZmYgLSAuNSwgY3V0b2ZmICsgLjUsIHJhZGl1cyk7XFxuXFx0XFx0XFx0fVxcblxcdFxcdH1cXG5cXG5cXHRcXHRpZiAoZW5hYmxlRW5kTWl0ZXIgPT0gMS4pIHtcXG5cXHRcXHRcXHRkaXN0VG9FbmQgPSBkaXN0VG9MaW5lKGdsX0ZyYWdDb29yZC54eSwgZW5kQ3V0b2ZmLnh5LCBlbmRDdXRvZmYuencpO1xcblxcdFxcdFxcdGlmIChkaXN0VG9FbmQgPCAwLikge1xcblxcdFxcdFxcdFxcdGZsb2F0IHJhZGl1cyA9IGxlbmd0aChnbF9GcmFnQ29vcmQueHkgLSBlbmRDb29yZCk7XFxuXFxuXFx0XFx0XFx0XFx0aWYocmFkaXVzID4gY3V0b2ZmICsgLjUpIHtcXG5cXHRcXHRcXHRcXHRcXHRkaXNjYXJkO1xcblxcdFxcdFxcdFxcdFxcdHJldHVybjtcXG5cXHRcXHRcXHRcXHR9XFxuXFxuXFx0XFx0XFx0XFx0YWxwaGEgLT0gc21vb3Roc3RlcChjdXRvZmYgLSAuNSwgY3V0b2ZmICsgLjUsIHJhZGl1cyk7XFxuXFx0XFx0XFx0fVxcblxcdFxcdH1cXG5cXHR9XFxuXFxuXFx0ZmxvYXQgdCA9IGZyYWN0KGRvdCh0YW5nZW50LCBnbF9GcmFnQ29vcmQueHkpIC8gZGFzaFNpemUpICogLjUgKyAuMjU7XFxuXFx0ZmxvYXQgZGFzaCA9IHRleHR1cmUyRChkYXNoUGF0dGVybiwgdmVjMih0LCAuNSkpLnI7XFxuXFxuXFx0Z2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcblxcdGdsX0ZyYWdDb2xvci5hICo9IGFscGhhICogb3BhY2l0eSAqIGRhc2g7XFxufVxcblwiXSksXG5cblx0XHRcdGF0dHJpYnV0ZXM6IHtcblx0XHRcdFx0Ly8gaXMgbGluZSBlbmRcblx0XHRcdFx0bGluZUVuZDoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogb2Zmc2V0QnVmZmVyLFxuXHRcdFx0XHRcdGRpdmlzb3I6IDAsXG5cdFx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRcdG9mZnNldDogMFxuXHRcdFx0XHR9LFxuXHRcdFx0XHQvLyBpcyBsaW5lIHRvcFxuXHRcdFx0XHRsaW5lVG9wOiB7XG5cdFx0XHRcdFx0YnVmZmVyOiBvZmZzZXRCdWZmZXIsXG5cdFx0XHRcdFx0ZGl2aXNvcjogMCxcblx0XHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdFx0b2Zmc2V0OiA0XG5cdFx0XHRcdH0sXG5cdFx0XHRcdC8vIGxlZnQgY29sb3Jcblx0XHRcdFx0YUNvbG9yOiB7XG5cdFx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ2NvbG9yQnVmZmVyJyksXG5cdFx0XHRcdFx0c3RyaWRlOiA0LFxuXHRcdFx0XHRcdG9mZnNldDogMCxcblx0XHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHRcdH0sXG5cdFx0XHRcdC8vIHJpZ2h0IGNvbG9yXG5cdFx0XHRcdGJDb2xvcjoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdjb2xvckJ1ZmZlcicpLFxuXHRcdFx0XHRcdHN0cmlkZTogNCxcblx0XHRcdFx0XHRvZmZzZXQ6IDQsXG5cdFx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRwcmV2Q29vcmQ6IHtcblx0XHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgncG9zaXRpb25CdWZmZXInKSxcblx0XHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdFx0b2Zmc2V0OiAwLFxuXHRcdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdFx0fSxcblx0XHRcdFx0YUNvb3JkOiB7XG5cdFx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRcdG9mZnNldDogOCxcblx0XHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGJDb29yZDoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkJ1ZmZlcicpLFxuXHRcdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0XHRvZmZzZXQ6IDE2LFxuXHRcdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdFx0fSxcblx0XHRcdFx0bmV4dENvb3JkOiB7XG5cdFx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRcdG9mZnNldDogMjQsXG5cdFx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSwgc2hhZGVyT3B0aW9ucykpXG5cdH0gY2F0Y2ggKGUpIHtcblx0XHQvLyBJRS9iYWQgV2Via2l0IGZhbGxiYWNrXG5cdFx0ZHJhd01pdGVyTGluZSA9IGRyYXdSZWN0TGluZVxuXHR9XG5cblx0Ly8gZmlsbCBzaGFkZXJcblx0bGV0IGRyYXdGaWxsID0gcmVnbCh7XG5cdFx0cHJpbWl0aXZlOiAndHJpYW5nbGUnLFxuXHRcdGVsZW1lbnRzOiAoY3R4LCBwcm9wKSA9PiBwcm9wLnRyaWFuZ2xlcyxcblx0XHRvZmZzZXQ6IDAsXG5cblx0XHR2ZXJ0OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uLCBwb3NpdGlvbkZyYWN0O1xcblxcbnVuaWZvcm0gdmVjNCBjb2xvcjtcXG51bmlmb3JtIHZlYzIgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3Q7XFxudW5pZm9ybSBmbG9hdCBwaXhlbFJhdGlvLCBpZDtcXG51bmlmb3JtIHZlYzQgdmlld3BvcnQ7XFxudW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxuY29uc3QgZmxvYXQgTUFYX0xJTkVTID0gMjU2LjtcXG5cXG52b2lkIG1haW4oKSB7XFxuXFx0ZmxvYXQgZGVwdGggPSAoTUFYX0xJTkVTIC0gNC4gLSBpZCkgLyAoTUFYX0xJTkVTKTtcXG5cXG5cXHR2ZWMyIHBvc2l0aW9uID0gcG9zaXRpb24gKiBzY2FsZSArIHRyYW5zbGF0ZVxcbiAgICAgICArIHBvc2l0aW9uRnJhY3QgKiBzY2FsZSArIHRyYW5zbGF0ZUZyYWN0XFxuICAgICAgICsgcG9zaXRpb24gKiBzY2FsZUZyYWN0XFxuICAgICAgICsgcG9zaXRpb25GcmFjdCAqIHNjYWxlRnJhY3Q7XFxuXFxuXFx0Z2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uICogMi4wIC0gMS4wLCBkZXB0aCwgMSk7XFxuXFxuXFx0ZnJhZ0NvbG9yID0gY29sb3IgLyAyNTUuO1xcblxcdGZyYWdDb2xvci5hICo9IG9wYWNpdHk7XFxufVxcblwiXSksXG5cdFx0ZnJhZzogZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG5cXHRnbF9GcmFnQ29sb3IgPSBmcmFnQ29sb3I7XFxufVxcblwiXSksXG5cblx0XHR1bmlmb3Jtczoge1xuXHRcdFx0c2NhbGU6IHJlZ2wucHJvcCgnc2NhbGUnKSxcblx0XHRcdGNvbG9yOiByZWdsLnByb3AoJ2ZpbGwnKSxcblx0XHRcdHNjYWxlRnJhY3Q6IHJlZ2wucHJvcCgnc2NhbGVGcmFjdCcpLFxuXHRcdFx0dHJhbnNsYXRlRnJhY3Q6IHJlZ2wucHJvcCgndHJhbnNsYXRlRnJhY3QnKSxcblx0XHRcdHRyYW5zbGF0ZTogcmVnbC5wcm9wKCd0cmFuc2xhdGUnKSxcblx0XHRcdG9wYWNpdHk6IHJlZ2wucHJvcCgnb3BhY2l0eScpLFxuXHRcdFx0cGl4ZWxSYXRpbzogcmVnbC5jb250ZXh0KCdwaXhlbFJhdGlvJyksXG5cdFx0XHRpZDogcmVnbC5wcm9wKCdpZCcpLFxuXHRcdFx0dmlld3BvcnQ6IChjdHgsIHByb3ApID0+IFtwcm9wLnZpZXdwb3J0LngsIHByb3Audmlld3BvcnQueSwgY3R4LnZpZXdwb3J0V2lkdGgsIGN0eC52aWV3cG9ydEhlaWdodF1cblx0XHR9LFxuXG5cdFx0YXR0cmlidXRlczoge1xuXHRcdFx0cG9zaXRpb246IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiA4XG5cdFx0XHR9LFxuXHRcdFx0cG9zaXRpb25GcmFjdDoge1xuXHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgncG9zaXRpb25GcmFjdEJ1ZmZlcicpLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogOFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRibGVuZDogc2hhZGVyT3B0aW9ucy5ibGVuZCxcblxuXHRcdGRlcHRoOiB7IGVuYWJsZTogZmFsc2UgfSxcblx0XHRzY2lzc29yOiBzaGFkZXJPcHRpb25zLnNjaXNzb3IsXG5cdFx0c3RlbmNpbDogc2hhZGVyT3B0aW9ucy5zdGVuY2lsLFxuXHRcdHZpZXdwb3J0OiBzaGFkZXJPcHRpb25zLnZpZXdwb3J0XG5cdH0pXG5cblx0cmV0dXJuIHtcblx0XHRmaWxsOiBkcmF3RmlsbCwgcmVjdDogZHJhd1JlY3RMaW5lLCBtaXRlcjogZHJhd01pdGVyTGluZVxuXHR9XG59XG5cblxuLy8gdXNlZCB0byBmb3IgbmV3IGxpbmVzIGluc3RhbmNlc1xuTGluZTJELmRlZmF1bHRzID0ge1xuXHRkYXNoZXM6IG51bGwsXG5cdGpvaW46ICdtaXRlcicsXG5cdG1pdGVyTGltaXQ6IDEsXG5cdHRoaWNrbmVzczogMTAsXG5cdGNhcDogJ3NxdWFyZScsXG5cdGNvbG9yOiAnYmxhY2snLFxuXHRvcGFjaXR5OiAxLFxuXHRvdmVybGF5OiBmYWxzZSxcblx0dmlld3BvcnQ6IG51bGwsXG5cdHJhbmdlOiBudWxsLFxuXHRjbG9zZTogZmFsc2UsXG5cdGZpbGw6IG51bGxcbn1cblxuXG5MaW5lMkQucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG5cdGlmIChhcmdzLmxlbmd0aCkge1xuXHRcdHRoaXMudXBkYXRlKC4uLmFyZ3MpXG5cdH1cblxuXHR0aGlzLmRyYXcoKVxufVxuXG5cbkxpbmUyRC5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG5cdC8vIHJlbmRlciBtdWx0aXBsZSBwb2x5bGluZXMgdmlhIHJlZ2wgYmF0Y2hcblx0KGFyZ3MubGVuZ3RoID8gYXJncyA6IHRoaXMucGFzc2VzKS5mb3JFYWNoKChzLCBpKSA9PiB7XG5cdFx0Ly8gcmVuZGVyIGFycmF5IHBhc3MgYXMgYSBsaXN0IG9mIHBhc3Nlc1xuXHRcdGlmIChzICYmIEFycmF5LmlzQXJyYXkocykpIHJldHVybiB0aGlzLmRyYXcoLi4ucylcblxuXHRcdGlmICh0eXBlb2YgcyA9PT0gJ251bWJlcicpIHMgPSB0aGlzLnBhc3Nlc1tzXVxuXG5cdFx0aWYgKCEocyAmJiBzLmNvdW50ID4gMSAmJiBzLm9wYWNpdHkpKSByZXR1cm5cblxuXHRcdHRoaXMucmVnbC5fcmVmcmVzaCgpXG5cblx0XHRpZiAocy5maWxsICYmIHMudHJpYW5nbGVzICYmIHMudHJpYW5nbGVzLmxlbmd0aCA+IDIpIHtcblx0XHRcdHRoaXMuc2hhZGVycy5maWxsKHMpXG5cdFx0fVxuXG5cdFx0aWYgKCFzLnRoaWNrbmVzcykgcmV0dXJuXG5cblx0XHQvLyBoaWdoIHNjYWxlIGlzIG9ubHkgYXZhaWxhYmxlIGZvciByZWN0IG1vZGUgd2l0aCBwcmVjaXNpb25cblx0XHRpZiAocy5zY2FsZVswXSAqIHMudmlld3BvcnQud2lkdGggPiBMaW5lMkQucHJlY2lzaW9uVGhyZXNob2xkIHx8IHMuc2NhbGVbMV0gKiBzLnZpZXdwb3J0LmhlaWdodCA+IExpbmUyRC5wcmVjaXNpb25UaHJlc2hvbGQpIHtcblx0XHRcdHRoaXMuc2hhZGVycy5yZWN0KHMpXG5cdFx0fVxuXG5cdFx0Ly8gdGhpbiB0aGlzLnBhc3NlcyBvciB0b28gbWFueSBwb2ludHMgYXJlIHJlbmRlcmVkIGFzIHNpbXBsaWZpZWQgcmVjdCBzaGFkZXJcblx0XHRlbHNlIGlmIChzLmpvaW4gPT09ICdyZWN0JyB8fCAoIXMuam9pbiAmJiAocy50aGlja25lc3MgPD0gMiB8fCBzLmNvdW50ID49IExpbmUyRC5tYXhQb2ludHMpKSkge1xuXHRcdFx0dGhpcy5zaGFkZXJzLnJlY3Qocylcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHR0aGlzLnNoYWRlcnMubWl0ZXIocylcblx0XHR9XG5cdH0pXG5cblx0cmV0dXJuIHRoaXNcbn1cblxuTGluZTJELnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuXHRpZiAoIW9wdGlvbnMpIHJldHVyblxuXG5cdGlmIChvcHRpb25zLmxlbmd0aCAhPSBudWxsKSB7XG5cdFx0aWYgKHR5cGVvZiBvcHRpb25zWzBdID09PSAnbnVtYmVyJykgb3B0aW9ucyA9IFt7cG9zaXRpb25zOiBvcHRpb25zfV1cblx0fVxuXG5cdC8vIG1ha2Ugb3B0aW9ucyBhIGJhdGNoXG5cdGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG9wdGlvbnMpKSBvcHRpb25zID0gW29wdGlvbnNdXG5cblx0bGV0IHsgcmVnbCwgZ2wgfSA9IHRoaXNcblxuXHQvLyBwcm9jZXNzIHBlci1saW5lIHNldHRpbmdzXG5cdG9wdGlvbnMuZm9yRWFjaCgobywgaSkgPT4ge1xuXHRcdGxldCBzdGF0ZSA9IHRoaXMucGFzc2VzW2ldXG5cblx0XHRpZiAobyA9PT0gdW5kZWZpbmVkKSByZXR1cm5cblxuXHRcdC8vIG51bGwtYXJndW1lbnQgcmVtb3ZlcyBwYXNzXG5cdFx0aWYgKG8gPT09IG51bGwpIHtcblx0XHRcdHRoaXMucGFzc2VzW2ldID0gbnVsbFxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXG5cdFx0aWYgKHR5cGVvZiBvWzBdID09PSAnbnVtYmVyJykgbyA9IHtwb3NpdGlvbnM6IG99XG5cblx0XHQvLyBoYW5kbGUgYWxpYXNlc1xuXHRcdG8gPSBwaWNrKG8sIHtcblx0XHRcdHBvc2l0aW9uczogJ3Bvc2l0aW9ucyBwb2ludHMgZGF0YSBjb29yZHMnLFxuXHRcdFx0dGhpY2tuZXNzOiAndGhpY2tuZXNzIGxpbmVXaWR0aCBsaW5lV2lkdGhzIGxpbmUtd2lkdGggbGluZXdpZHRoIHdpZHRoIHN0cm9rZS13aWR0aCBzdHJva2V3aWR0aCBzdHJva2VXaWR0aCcsXG5cdFx0XHRqb2luOiAnbGluZUpvaW4gbGluZWpvaW4gam9pbiB0eXBlIG1vZGUnLFxuXHRcdFx0bWl0ZXJMaW1pdDogJ21pdGVybGltaXQgbWl0ZXJMaW1pdCcsXG5cdFx0XHRkYXNoZXM6ICdkYXNoIGRhc2hlcyBkYXNoYXJyYXkgZGFzaC1hcnJheSBkYXNoQXJyYXknLFxuXHRcdFx0Y29sb3I6ICdjb2xvciBjb2xvdXIgc3Ryb2tlIGNvbG9ycyBjb2xvdXJzIHN0cm9rZS1jb2xvciBzdHJva2VDb2xvcicsXG5cdFx0XHRmaWxsOiAnZmlsbCBmaWxsLWNvbG9yIGZpbGxDb2xvcicsXG5cdFx0XHRvcGFjaXR5OiAnYWxwaGEgb3BhY2l0eScsXG5cdFx0XHRvdmVybGF5OiAnb3ZlcmxheSBjcmVhc2Ugb3ZlcmxhcCBpbnRlcnNlY3QnLFxuXHRcdFx0Y2xvc2U6ICdjbG9zZWQgY2xvc2UgY2xvc2VkLXBhdGggY2xvc2VQYXRoJyxcblx0XHRcdHJhbmdlOiAncmFuZ2UgZGF0YUJveCcsXG5cdFx0XHR2aWV3cG9ydDogJ3ZpZXdwb3J0IHZpZXdCb3gnLFxuXHRcdFx0aG9sZTogJ2hvbGVzIGhvbGUgaG9sbG93J1xuXHRcdH0pXG5cblx0XHQvLyBpbml0IHN0YXRlXG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0dGhpcy5wYXNzZXNbaV0gPSBzdGF0ZSA9IHtcblx0XHRcdFx0aWQ6IGksXG5cdFx0XHRcdHNjYWxlOiBudWxsLFxuXHRcdFx0XHRzY2FsZUZyYWN0OiBudWxsLFxuXHRcdFx0XHR0cmFuc2xhdGU6IG51bGwsXG5cdFx0XHRcdHRyYW5zbGF0ZUZyYWN0OiBudWxsLFxuXHRcdFx0XHRjb3VudDogMCxcblx0XHRcdFx0aG9sZTogW10sXG5cdFx0XHRcdGRlcHRoOiAwLFxuXG5cdFx0XHRcdGRhc2hMZW5ndGg6IDEsXG5cdFx0XHRcdGRhc2hUZXh0dXJlOiByZWdsLnRleHR1cmUoe1xuXHRcdFx0XHRcdGNoYW5uZWxzOiAxLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KFsyNTVdKSxcblx0XHRcdFx0XHR3aWR0aDogMSxcblx0XHRcdFx0XHRoZWlnaHQ6IDEsXG5cdFx0XHRcdFx0bWFnOiAnbGluZWFyJyxcblx0XHRcdFx0XHRtaW46ICdsaW5lYXInXG5cdFx0XHRcdH0pLFxuXG5cdFx0XHRcdGNvbG9yQnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHRcdFx0XHR0eXBlOiAndWludDgnLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHRcdFx0fSksXG5cdFx0XHRcdHBvc2l0aW9uQnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHRcdFx0XHR0eXBlOiAnZmxvYXQnLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHRcdFx0fSksXG5cdFx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXI6IHJlZ2wuYnVmZmVyKHtcblx0XHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCcsXG5cdFx0XHRcdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoKVxuXHRcdFx0XHR9KVxuXHRcdFx0fVxuXG5cdFx0XHRvID0gZXh0ZW5kKHt9LCBMaW5lMkQuZGVmYXVsdHMsIG8pXG5cdFx0fVxuXHRcdGlmIChvLnRoaWNrbmVzcyAhPSBudWxsKSBzdGF0ZS50aGlja25lc3MgPSBwYXJzZUZsb2F0KG8udGhpY2tuZXNzKVxuXHRcdGlmIChvLm9wYWNpdHkgIT0gbnVsbCkgc3RhdGUub3BhY2l0eSA9IHBhcnNlRmxvYXQoby5vcGFjaXR5KVxuXHRcdGlmIChvLm1pdGVyTGltaXQgIT0gbnVsbCkgc3RhdGUubWl0ZXJMaW1pdCA9IHBhcnNlRmxvYXQoby5taXRlckxpbWl0KVxuXHRcdGlmIChvLm92ZXJsYXkgIT0gbnVsbCkge1xuXHRcdFx0c3RhdGUub3ZlcmxheSA9ICEhby5vdmVybGF5XG5cdFx0XHRpZiAoaSA8IExpbmUyRC5tYXhMaW5lcykge1xuXHRcdFx0XHRzdGF0ZS5kZXB0aCA9IDIgKiAoTGluZTJELm1heExpbmVzIC0gMSAtIGkgJSBMaW5lMkQubWF4TGluZXMpIC8gTGluZTJELm1heExpbmVzIC0gMS47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChvLmpvaW4gIT0gbnVsbCkgc3RhdGUuam9pbiA9IG8uam9pblxuXHRcdGlmIChvLmhvbGUgIT0gbnVsbCkgc3RhdGUuaG9sZSA9IG8uaG9sZVxuXHRcdGlmIChvLmZpbGwgIT0gbnVsbCkgc3RhdGUuZmlsbCA9ICFvLmZpbGwgPyBudWxsIDogcmdiYShvLmZpbGwsICd1aW50OCcpXG5cdFx0aWYgKG8udmlld3BvcnQgIT0gbnVsbCkgc3RhdGUudmlld3BvcnQgPSBwYXJzZVJlY3Qoby52aWV3cG9ydClcblxuXHRcdGlmICghc3RhdGUudmlld3BvcnQpIHtcblx0XHRcdHN0YXRlLnZpZXdwb3J0ID0gcGFyc2VSZWN0KFtcblx0XHRcdFx0Z2wuZHJhd2luZ0J1ZmZlcldpZHRoLFxuXHRcdFx0XHRnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG5cdFx0XHRdKVxuXHRcdH1cblxuXHRcdGlmIChvLmNsb3NlICE9IG51bGwpIHN0YXRlLmNsb3NlID0gby5jbG9zZVxuXG5cdFx0Ly8gcmVzZXQgcG9zaXRpb25zXG5cdFx0aWYgKG8ucG9zaXRpb25zID09PSBudWxsKSBvLnBvc2l0aW9ucyA9IFtdXG5cdFx0aWYgKG8ucG9zaXRpb25zKSB7XG5cdFx0XHRsZXQgcG9zaXRpb25zLCBjb3VudFxuXG5cdFx0XHQvLyBpZiBwb3NpdGlvbnMgYXJlIGFuIG9iamVjdCB3aXRoIHgveVxuXHRcdFx0aWYgKG8ucG9zaXRpb25zLnggJiYgby5wb3NpdGlvbnMueSkge1xuXHRcdFx0XHRsZXQgeFBvcyA9IG8ucG9zaXRpb25zLnhcblx0XHRcdFx0bGV0IHlQb3MgPSBvLnBvc2l0aW9ucy55XG5cdFx0XHRcdGNvdW50ID0gc3RhdGUuY291bnQgPSBNYXRoLm1heChcblx0XHRcdFx0XHR4UG9zLmxlbmd0aCxcblx0XHRcdFx0XHR5UG9zLmxlbmd0aFxuXHRcdFx0XHQpXG5cdFx0XHRcdHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoY291bnQgKiAyKVxuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcblx0XHRcdFx0XHRwb3NpdGlvbnNbaSAqIDJdID0geFBvc1tpXVxuXHRcdFx0XHRcdHBvc2l0aW9uc1tpICogMiArIDFdID0geVBvc1tpXVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0cG9zaXRpb25zID0gZmxhdHRlbihvLnBvc2l0aW9ucywgJ2Zsb2F0NjQnKVxuXHRcdFx0XHRjb3VudCA9IHN0YXRlLmNvdW50ID0gTWF0aC5mbG9vcihwb3NpdGlvbnMubGVuZ3RoIC8gMilcblx0XHRcdH1cblxuXHRcdFx0bGV0IGJvdW5kcyA9IHN0YXRlLmJvdW5kcyA9IGdldEJvdW5kcyhwb3NpdGlvbnMsIDIpXG5cblx0XHRcdC8vIGNyZWF0ZSBmaWxsIHBvc2l0aW9uc1xuXHRcdFx0Ly8gRklYTUU6IGZpbGwgcG9zaXRpb25zIGNhbiBiZSBzZXQgb25seSBhbG9uZyB3aXRoIHBvc2l0aW9uc1xuXHRcdFx0aWYgKHN0YXRlLmZpbGwpIHtcblx0XHRcdFx0bGV0IHBvcyA9IFtdXG5cblx0XHRcdFx0Ly8gZmlsdGVyIGJhZCB2ZXJ0aWNlcyBhbmQgcmVtYXAgdHJpYW5nbGVzIHRvIGVuc3VyZSBzaGFwZVxuXHRcdFx0XHRsZXQgaWRzID0ge31cblx0XHRcdFx0bGV0IGxhc3RJZCA9IDBcblxuXHRcdFx0XHRmb3IgKGxldCBpID0gMCwgcHRyID0gMCwgbCA9IHN0YXRlLmNvdW50OyBpIDwgbDsgaSsrKSB7XG5cdFx0XHRcdFx0bGV0IHggPSBwb3NpdGlvbnNbaSoyXVxuXHRcdFx0XHRcdGxldCB5ID0gcG9zaXRpb25zW2kqMiArIDFdXG5cdFx0XHRcdFx0aWYgKGlzTmFOKHgpIHx8IGlzTmFOKHkpIHx8IHggPT0gbnVsbCB8fCB5ID09IG51bGwpIHtcblx0XHRcdFx0XHRcdHggPSBwb3NpdGlvbnNbbGFzdElkKjJdXG5cdFx0XHRcdFx0XHR5ID0gcG9zaXRpb25zW2xhc3RJZCoyICsgMV1cblx0XHRcdFx0XHRcdGlkc1tpXSA9IGxhc3RJZFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdGxhc3RJZCA9IGlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cG9zW3B0cisrXSA9IHhcblx0XHRcdFx0XHRwb3NbcHRyKytdID0geVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0bGV0IHRyaWFuZ2xlcyA9IHRyaWFuZ3VsYXRlKHBvcywgc3RhdGUuaG9sZSB8fCBbXSlcblxuXHRcdFx0XHRmb3IgKGxldCBpID0gMCwgbCA9IHRyaWFuZ2xlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcblx0XHRcdFx0XHRpZiAoaWRzW3RyaWFuZ2xlc1tpXV0gIT0gbnVsbCkgdHJpYW5nbGVzW2ldID0gaWRzW3RyaWFuZ2xlc1tpXV1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHN0YXRlLnRyaWFuZ2xlcyA9IHRyaWFuZ2xlc1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB1cGRhdGUgcG9zaXRpb24gYnVmZmVyc1xuXHRcdFx0bGV0IG5wb3MgPSBuZXcgRmxvYXQ2NEFycmF5KHBvc2l0aW9ucylcblx0XHRcdG5vcm1hbGl6ZShucG9zLCAyLCBib3VuZHMpXG5cblx0XHRcdGxldCBwb3NpdGlvbkRhdGEgPSBuZXcgRmxvYXQ2NEFycmF5KGNvdW50ICogMiArIDYpXG5cblx0XHRcdC8vIHJvdGF0ZSBmaXJzdCBzZWdtZW50IGpvaW5cblx0XHRcdGlmIChzdGF0ZS5jbG9zZSkge1xuXHRcdFx0XHRpZiAocG9zaXRpb25zWzBdID09PSBwb3NpdGlvbnNbY291bnQqMiAtIDJdICYmXG5cdFx0XHRcdFx0cG9zaXRpb25zWzFdID09PSBwb3NpdGlvbnNbY291bnQqMiAtIDFdKSB7XG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhWzBdID0gbnBvc1tjb3VudCoyIC0gNF1cblx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbMV0gPSBucG9zW2NvdW50KjIgLSAzXVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVswXSA9IG5wb3NbY291bnQqMiAtIDJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhWzFdID0gbnBvc1tjb3VudCoyIC0gMV1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHBvc2l0aW9uRGF0YVswXSA9IG5wb3NbMF1cblx0XHRcdFx0cG9zaXRpb25EYXRhWzFdID0gbnBvc1sxXVxuXHRcdFx0fVxuXG5cdFx0XHRwb3NpdGlvbkRhdGEuc2V0KG5wb3MsIDIpXG5cblx0XHRcdC8vIGFkZCBsYXN0IHNlZ21lbnRcblx0XHRcdGlmIChzdGF0ZS5jbG9zZSkge1xuXHRcdFx0XHQvLyBpZ25vcmUgY29pbmNpZGluZyBzdGFydC9lbmRcblx0XHRcdFx0aWYgKHBvc2l0aW9uc1swXSA9PT0gcG9zaXRpb25zW2NvdW50KjIgLSAyXSAmJlxuXHRcdFx0XHRcdHBvc2l0aW9uc1sxXSA9PT0gcG9zaXRpb25zW2NvdW50KjIgLSAxXSkge1xuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgMl0gPSBucG9zWzJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAzXSA9IG5wb3NbM11cblx0XHRcdFx0XHRzdGF0ZS5jb3VudCAtPSAxXG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAyXSA9IG5wb3NbMF1cblx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDNdID0gbnBvc1sxXVxuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgNF0gPSBucG9zWzJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyA1XSA9IG5wb3NbM11cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly8gYWRkIHN0dWJcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDJdID0gbnBvc1tjb3VudCoyIC0gMl1cblx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAzXSA9IG5wb3NbY291bnQqMiAtIDFdXG5cdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgNF0gPSBucG9zW2NvdW50KjIgLSAyXVxuXHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDVdID0gbnBvc1tjb3VudCoyIC0gMV1cblx0XHRcdH1cblxuXHRcdFx0c3RhdGUucG9zaXRpb25CdWZmZXIoZmxvYXQzMihwb3NpdGlvbkRhdGEpKVxuXHRcdFx0c3RhdGUucG9zaXRpb25GcmFjdEJ1ZmZlcihmcmFjdDMyKHBvc2l0aW9uRGF0YSkpXG5cdFx0fVxuXG5cdFx0aWYgKG8ucmFuZ2UpIHtcblx0XHRcdHN0YXRlLnJhbmdlID0gby5yYW5nZVxuXHRcdH0gZWxzZSBpZiAoIXN0YXRlLnJhbmdlKSB7XG5cdFx0XHRzdGF0ZS5yYW5nZSA9IHN0YXRlLmJvdW5kc1xuXHRcdH1cblxuXHRcdGlmICgoby5yYW5nZSB8fCBvLnBvc2l0aW9ucykgJiYgc3RhdGUuY291bnQpIHtcblx0XHRcdGxldCBib3VuZHMgPSBzdGF0ZS5ib3VuZHNcblxuXHRcdFx0bGV0IGJvdW5kc1cgPSBib3VuZHNbMl0gLSBib3VuZHNbMF0sXG5cdFx0XHRcdGJvdW5kc0ggPSBib3VuZHNbM10gLSBib3VuZHNbMV1cblxuXHRcdFx0bGV0IHJhbmdlVyA9IHN0YXRlLnJhbmdlWzJdIC0gc3RhdGUucmFuZ2VbMF0sXG5cdFx0XHRcdHJhbmdlSCA9IHN0YXRlLnJhbmdlWzNdIC0gc3RhdGUucmFuZ2VbMV1cblxuXHRcdFx0c3RhdGUuc2NhbGUgPSBbXG5cdFx0XHRcdGJvdW5kc1cgLyByYW5nZVcsXG5cdFx0XHRcdGJvdW5kc0ggLyByYW5nZUhcblx0XHRcdF1cblx0XHRcdHN0YXRlLnRyYW5zbGF0ZSA9IFtcblx0XHRcdFx0LXN0YXRlLnJhbmdlWzBdIC8gcmFuZ2VXICsgYm91bmRzWzBdIC8gcmFuZ2VXIHx8IDAsXG5cdFx0XHRcdC1zdGF0ZS5yYW5nZVsxXSAvIHJhbmdlSCArIGJvdW5kc1sxXSAvIHJhbmdlSCB8fCAwXG5cdFx0XHRdXG5cblx0XHRcdHN0YXRlLnNjYWxlRnJhY3QgPSBmcmFjdDMyKHN0YXRlLnNjYWxlKVxuXHRcdFx0c3RhdGUudHJhbnNsYXRlRnJhY3QgPSBmcmFjdDMyKHN0YXRlLnRyYW5zbGF0ZSlcblx0XHR9XG5cblx0XHRpZiAoby5kYXNoZXMpIHtcblx0XHRcdGxldCBkYXNoTGVuZ3RoID0gMC4sIGRhc2hEYXRhXG5cblx0XHRcdGlmICghby5kYXNoZXMgfHwgby5kYXNoZXMubGVuZ3RoIDwgMikge1xuXHRcdFx0XHRkYXNoTGVuZ3RoID0gMS5cblx0XHRcdFx0ZGFzaERhdGEgPSBuZXcgVWludDhBcnJheShbMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTVdKVxuXHRcdFx0fVxuXG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0ZGFzaExlbmd0aCA9IDAuO1xuXHRcdFx0XHRmb3IobGV0IGkgPSAwOyBpIDwgby5kYXNoZXMubGVuZ3RoOyArK2kpIHtcblx0XHRcdFx0XHRkYXNoTGVuZ3RoICs9IG8uZGFzaGVzW2ldXG5cdFx0XHRcdH1cblx0XHRcdFx0ZGFzaERhdGEgPSBuZXcgVWludDhBcnJheShkYXNoTGVuZ3RoICogTGluZTJELmRhc2hNdWx0KVxuXHRcdFx0XHRsZXQgcHRyID0gMFxuXHRcdFx0XHRsZXQgZmlsbENvbG9yID0gMjU1XG5cblx0XHRcdFx0Ly8gcmVwZWF0IHRleHR1cmUgdHdvIHRpbWVzIHRvIHByb3ZpZGUgc21vb3RoIDAtc3RlcFxuXHRcdFx0XHRmb3IgKGxldCBrID0gMDsgayA8IDI7IGsrKykge1xuXHRcdFx0XHRcdGZvcihsZXQgaSA9IDA7IGkgPCBvLmRhc2hlcy5sZW5ndGg7ICsraSkge1xuXHRcdFx0XHRcdFx0Zm9yKGxldCBqID0gMCwgbCA9IG8uZGFzaGVzW2ldICogTGluZTJELmRhc2hNdWx0ICogLjU7IGogPCBsOyArK2opIHtcblx0XHRcdFx0XHRcdFx0ZGFzaERhdGFbcHRyKytdID0gZmlsbENvbG9yXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRmaWxsQ29sb3IgXj0gMjU1XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHN0YXRlLmRhc2hMZW5ndGggPSBkYXNoTGVuZ3RoXG5cdFx0XHRzdGF0ZS5kYXNoVGV4dHVyZSh7XG5cdFx0XHRcdGNoYW5uZWxzOiAxLFxuXHRcdFx0XHRkYXRhOiBkYXNoRGF0YSxcblx0XHRcdFx0d2lkdGg6IGRhc2hEYXRhLmxlbmd0aCxcblx0XHRcdFx0aGVpZ2h0OiAxLFxuXHRcdFx0XHRtYWc6ICdsaW5lYXInLFxuXHRcdFx0XHRtaW46ICdsaW5lYXInXG5cdFx0XHR9LCAwLCAwKVxuXHRcdH1cblxuXHRcdGlmIChvLmNvbG9yKSB7XG5cdFx0XHRsZXQgY291bnQgPSBzdGF0ZS5jb3VudFxuXHRcdFx0bGV0IGNvbG9ycyA9IG8uY29sb3JcblxuXHRcdFx0aWYgKCFjb2xvcnMpIGNvbG9ycyA9ICd0cmFuc3BhcmVudCdcblxuXHRcdFx0bGV0IGNvbG9yRGF0YSA9IG5ldyBVaW50OEFycmF5KGNvdW50ICogNCArIDQpXG5cblx0XHRcdC8vIGNvbnZlcnQgY29sb3JzIHRvIHR5cGVkIGFycmF5c1xuXHRcdFx0aWYgKCFBcnJheS5pc0FycmF5KGNvbG9ycykgfHwgdHlwZW9mIGNvbG9yc1swXSA9PT0gJ251bWJlcicpIHtcblx0XHRcdFx0bGV0IGMgPSByZ2JhKGNvbG9ycywgJ3VpbnQ4JylcblxuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50ICsgMTsgaSsrKSB7XG5cdFx0XHRcdFx0Y29sb3JEYXRhLnNldChjLCBpICogNClcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG5cdFx0XHRcdFx0bGV0IGMgPSByZ2JhKGNvbG9yc1tpXSwgJ3VpbnQ4Jylcblx0XHRcdFx0XHRjb2xvckRhdGEuc2V0KGMsIGkgKiA0KVxuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbG9yRGF0YS5zZXQocmdiYShjb2xvcnNbMF0sICd1aW50OCcpLCBjb3VudCAqIDQpXG5cdFx0XHR9XG5cblx0XHRcdHN0YXRlLmNvbG9yQnVmZmVyKHtcblx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHRcdFx0dHlwZTogJ3VpbnQ4Jyxcblx0XHRcdFx0ZGF0YTogY29sb3JEYXRhXG5cdFx0XHR9KVxuXHRcdH1cblx0fSlcblxuXHQvLyByZW1vdmUgdW5tZW50aW9uZWQgcGFzc2VzXG5cdGlmIChvcHRpb25zLmxlbmd0aCA8IHRoaXMucGFzc2VzLmxlbmd0aCkge1xuXHRcdGZvciAobGV0IGkgPSBvcHRpb25zLmxlbmd0aDsgaSA8IHRoaXMucGFzc2VzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRsZXQgcGFzcyA9IHRoaXMucGFzc2VzW2ldXG5cdFx0XHRpZiAoIXBhc3MpIGNvbnRpbnVlXG5cdFx0XHRwYXNzLmNvbG9yQnVmZmVyLmRlc3Ryb3koKVxuXHRcdFx0cGFzcy5wb3NpdGlvbkJ1ZmZlci5kZXN0cm95KClcblx0XHRcdHBhc3MuZGFzaFRleHR1cmUuZGVzdHJveSgpXG5cdFx0fVxuXHRcdHRoaXMucGFzc2VzLmxlbmd0aCA9IG9wdGlvbnMubGVuZ3RoXG5cdH1cblxuXHQvLyByZW1vdmUgbnVsbCBpdGVtc1xuXHRsZXQgcGFzc2VzID0gW11cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnBhc3Nlcy5sZW5ndGg7IGkrKykge1xuXHRcdGlmICh0aGlzLnBhc3Nlc1tpXSAhPT0gbnVsbCkgcGFzc2VzLnB1c2godGhpcy5wYXNzZXNbaV0pXG5cdH1cblx0dGhpcy5wYXNzZXMgPSBwYXNzZXNcblxuXHRyZXR1cm4gdGhpc1xufVxuXG5MaW5lMkQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG5cdHRoaXMucGFzc2VzLmZvckVhY2gocGFzcyA9PiB7XG5cdFx0cGFzcy5jb2xvckJ1ZmZlci5kZXN0cm95KClcblx0XHRwYXNzLnBvc2l0aW9uQnVmZmVyLmRlc3Ryb3koKVxuXHRcdHBhc3MuZGFzaFRleHR1cmUuZGVzdHJveSgpXG5cdH0pXG5cblx0dGhpcy5wYXNzZXMubGVuZ3RoID0gMFxuXG5cdHJldHVybiB0aGlzXG59XG5cbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxubGV0IFNjYXR0ZXIgPSByZXF1aXJlKCcuL3NjYXR0ZXInKVxyXG5sZXQgZXh0ZW5kID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyZWdsLCBvcHRpb25zKSB7XHJcblx0bGV0IHNjYXR0ZXIgPSBuZXcgU2NhdHRlcihyZWdsLCBvcHRpb25zKVxyXG5cclxuXHRsZXQgcmVuZGVyID0gc2NhdHRlci5yZW5kZXIuYmluZChzY2F0dGVyKVxyXG5cclxuXHQvLyBleHBvc2UgQVBJXHJcblx0ZXh0ZW5kKHJlbmRlciwge1xyXG5cdFx0cmVuZGVyOiByZW5kZXIsXHJcblx0XHR1cGRhdGU6IHNjYXR0ZXIudXBkYXRlLmJpbmQoc2NhdHRlciksXHJcblx0XHRkcmF3OiBzY2F0dGVyLmRyYXcuYmluZChzY2F0dGVyKSxcclxuXHRcdGRlc3Ryb3k6IHNjYXR0ZXIuZGVzdHJveS5iaW5kKHNjYXR0ZXIpLFxyXG5cdFx0cmVnbDogc2NhdHRlci5yZWdsLFxyXG5cdFx0Z2w6IHNjYXR0ZXIuZ2wsXHJcblx0XHRjYW52YXM6IHNjYXR0ZXIuZ2wuY2FudmFzLFxyXG5cdFx0Z3JvdXBzOiBzY2F0dGVyLmdyb3VwcyxcclxuXHRcdG1hcmtlcnM6IHNjYXR0ZXIubWFya2VyQ2FjaGUsXHJcblx0XHRwYWxldHRlOiBzY2F0dGVyLnBhbGV0dGVcclxuXHR9KVxyXG5cclxuXHRyZXR1cm4gcmVuZGVyXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG5jb25zdCByZ2JhID0gcmVxdWlyZSgnY29sb3Itbm9ybWFsaXplJylcclxuY29uc3QgZ2V0Qm91bmRzID0gcmVxdWlyZSgnYXJyYXktYm91bmRzJylcclxuY29uc3QgY29sb3JJZCA9IHJlcXVpcmUoJ2NvbG9yLWlkJylcclxuY29uc3QgY2x1c3RlciA9IHJlcXVpcmUoJ3BvaW50LWNsdXN0ZXInKVxyXG5jb25zdCBleHRlbmQgPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJylcclxuY29uc3QgZ2xzbGlmeSA9IHJlcXVpcmUoJ2dsc2xpZnknKVxyXG5jb25zdCBwaWNrID0gcmVxdWlyZSgncGljay1ieS1hbGlhcycpXHJcbmNvbnN0IHVwZGF0ZURpZmYgPSByZXF1aXJlKCd1cGRhdGUtZGlmZicpXHJcbmNvbnN0IGZsYXR0ZW4gPSByZXF1aXJlKCdmbGF0dGVuLXZlcnRleC1kYXRhJylcclxuY29uc3QgaWUgPSByZXF1aXJlKCdpcy1pZXhwbG9yZXInKVxyXG5jb25zdCBmMzIgPSByZXF1aXJlKCd0by1mbG9hdDMyJylcclxuY29uc3QgcGFyc2VSZWN0ID0gcmVxdWlyZSgncGFyc2UtcmVjdCcpXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBTY2F0dGVyXHJcblxyXG5cclxuZnVuY3Rpb24gU2NhdHRlciAocmVnbCwgb3B0aW9ucykge1xyXG5cdGlmICghKHRoaXMgaW5zdGFuY2VvZiBTY2F0dGVyKSkgcmV0dXJuIG5ldyBTY2F0dGVyKHJlZ2wsIG9wdGlvbnMpXHJcblxyXG5cdGlmICh0eXBlb2YgcmVnbCA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdFx0aWYgKCFvcHRpb25zKSBvcHRpb25zID0ge31cclxuXHRcdG9wdGlvbnMucmVnbCA9IHJlZ2xcclxuXHR9XHJcblx0ZWxzZSB7XHJcblx0XHRvcHRpb25zID0gcmVnbFxyXG5cdFx0cmVnbCA9IG51bGxcclxuXHR9XHJcblxyXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMubGVuZ3RoKSBvcHRpb25zLnBvc2l0aW9ucyA9IG9wdGlvbnNcclxuXHJcblx0cmVnbCA9IG9wdGlvbnMucmVnbFxyXG5cclxuXHQvLyBwZXJzaXN0ZW50IHZhcmlhYmxlc1xyXG5cdGxldCBnbCA9IHJlZ2wuX2dsLCBwYWxldHRlVGV4dHVyZSwgcGFsZXR0ZSA9IFtdLCBwYWxldHRlSWRzID0ge30sXHJcblxyXG5cdFx0Ly8gc3RhdGVcclxuXHRcdGdyb3VwcyA9IFtdLFxyXG5cclxuXHRcdC8vIHRleHR1cmVzIGZvciBtYXJrZXIga2V5c1xyXG5cdFx0bWFya2VyVGV4dHVyZXMgPSBbbnVsbF0sXHJcblx0XHRtYXJrZXJDYWNoZSA9IFtudWxsXVxyXG5cclxuXHRjb25zdCBtYXhDb2xvcnMgPSAyNTUsIG1heFNpemUgPSAxMDBcclxuXHJcblx0Ly8gZGlyZWN0IGNvbG9yIGJ1ZmZlciBtb2RlXHJcblx0Ly8gSUUgZG9lcyBub3Qgc3VwcG9ydCBwYWxldHRlIGFueXdheXNcclxuXHR0aGlzLnRvb01hbnlDb2xvcnMgPSBpZVxyXG5cclxuXHQvLyB0ZXh0dXJlIHdpdGggY29sb3IgcGFsZXR0ZVxyXG5cdHBhbGV0dGVUZXh0dXJlID0gcmVnbC50ZXh0dXJlKHtcclxuXHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KG1heENvbG9ycyAqIDQpLFxyXG5cdFx0d2lkdGg6IG1heENvbG9ycyxcclxuXHRcdGhlaWdodDogMSxcclxuXHRcdHR5cGU6ICd1aW50OCcsXHJcblx0XHRmb3JtYXQ6ICdyZ2JhJyxcclxuXHRcdHdyYXBTOiAnY2xhbXAnLFxyXG5cdFx0d3JhcFQ6ICdjbGFtcCcsXHJcblx0XHRtYWc6ICduZWFyZXN0JyxcclxuXHRcdG1pbjogJ25lYXJlc3QnXHJcblx0fSlcclxuXHJcblx0ZXh0ZW5kKHRoaXMsIHtcclxuXHRcdHJlZ2wsXHJcblx0XHRnbCxcclxuXHRcdGdyb3VwcyxcclxuXHRcdG1hcmtlckNhY2hlLFxyXG5cdFx0bWFya2VyVGV4dHVyZXMsXHJcblx0XHRwYWxldHRlLFxyXG5cdFx0cGFsZXR0ZUlkcyxcclxuXHRcdHBhbGV0dGVUZXh0dXJlLFxyXG5cdFx0bWF4Q29sb3JzLFxyXG5cdFx0bWF4U2l6ZSxcclxuXHRcdGNhbnZhczogZ2wuY2FudmFzXHJcblx0fSlcclxuXHJcblx0dGhpcy51cGRhdGUob3B0aW9ucylcclxuXHJcblx0Ly8gY29tbW9uIHNoYWRlciBvcHRpb25zXHJcblx0bGV0IHNoYWRlck9wdGlvbnMgPSB7XHJcblx0XHR1bmlmb3Jtczoge1xyXG5cdFx0XHRwaXhlbFJhdGlvOiByZWdsLmNvbnRleHQoJ3BpeGVsUmF0aW8nKSxcclxuXHRcdFx0cGFsZXR0ZTogcGFsZXR0ZVRleHR1cmUsXHJcblx0XHRcdHBhbGV0dGVTaXplOiAoY3R4LCBwcm9wKSA9PiBbdGhpcy50b29NYW55Q29sb3JzID8gMCA6IG1heENvbG9ycywgcGFsZXR0ZVRleHR1cmUuaGVpZ2h0XSxcclxuXHRcdFx0c2NhbGU6IHJlZ2wucHJvcCgnc2NhbGUnKSxcclxuXHRcdFx0c2NhbGVGcmFjdDogcmVnbC5wcm9wKCdzY2FsZUZyYWN0JyksXHJcblx0XHRcdHRyYW5zbGF0ZTogcmVnbC5wcm9wKCd0cmFuc2xhdGUnKSxcclxuXHRcdFx0dHJhbnNsYXRlRnJhY3Q6IHJlZ2wucHJvcCgndHJhbnNsYXRlRnJhY3QnKSxcclxuXHRcdFx0b3BhY2l0eTogcmVnbC5wcm9wKCdvcGFjaXR5JyksXHJcblx0XHRcdG1hcmtlcjogcmVnbC5wcm9wKCdtYXJrZXJUZXh0dXJlJyksXHJcblx0XHR9LFxyXG5cclxuXHRcdGF0dHJpYnV0ZXM6IHtcclxuXHRcdFx0Ly8gRklYTUU6IG9wdGltaXplIHRoZXNlIHBhcnRzXHJcblx0XHRcdHg6IChjdHgsIHByb3ApID0+IHByb3AueEF0dHIgfHwge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5wb3NpdGlvbkJ1ZmZlcixcclxuXHRcdFx0XHRzdHJpZGU6IDgsXHJcblx0XHRcdFx0b2Zmc2V0OiAwXHJcblx0XHRcdH0sXHJcblx0XHRcdHk6IChjdHgsIHByb3ApID0+IHByb3AueUF0dHIgfHwge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5wb3NpdGlvbkJ1ZmZlcixcclxuXHRcdFx0XHRzdHJpZGU6IDgsXHJcblx0XHRcdFx0b2Zmc2V0OiA0XHJcblx0XHRcdH0sXHJcblx0XHRcdHhGcmFjdDogKGN0eCwgcHJvcCkgPT4gcHJvcC54QXR0ciA/IHsgY29uc3RhbnQ6IFswLCAwXSB9IDoge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5wb3NpdGlvbkZyYWN0QnVmZmVyLFxyXG5cdFx0XHRcdHN0cmlkZTogOCxcclxuXHRcdFx0XHRvZmZzZXQ6IDBcclxuXHRcdFx0fSxcclxuXHRcdFx0eUZyYWN0OiAoY3R4LCBwcm9wKSA9PiBwcm9wLnlBdHRyID8geyBjb25zdGFudDogWzAsIDBdIH0gOiB7XHJcblx0XHRcdFx0YnVmZmVyOiBwcm9wLnBvc2l0aW9uRnJhY3RCdWZmZXIsXHJcblx0XHRcdFx0c3RyaWRlOiA4LFxyXG5cdFx0XHRcdG9mZnNldDogNFxyXG5cdFx0XHR9LFxyXG5cdFx0XHRzaXplOiAoY3R4LCBwcm9wKSA9PiBwcm9wLnNpemUubGVuZ3RoID8ge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5zaXplQnVmZmVyLFxyXG5cdFx0XHRcdHN0cmlkZTogMixcclxuXHRcdFx0XHRvZmZzZXQ6IDBcclxuXHRcdFx0fSA6IHtcclxuXHRcdFx0XHRjb25zdGFudDogWyBNYXRoLnJvdW5kKHByb3Auc2l6ZSAqIDI1NSAvIHRoaXMubWF4U2l6ZSkgXVxyXG5cdFx0XHR9LFxyXG5cdFx0XHRib3JkZXJTaXplOiAoY3R4LCBwcm9wKSA9PiBwcm9wLmJvcmRlclNpemUubGVuZ3RoID8ge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5zaXplQnVmZmVyLFxyXG5cdFx0XHRcdHN0cmlkZTogMixcclxuXHRcdFx0XHRvZmZzZXQ6IDFcclxuXHRcdFx0fSA6IHtcclxuXHRcdFx0XHRjb25zdGFudDogWyBNYXRoLnJvdW5kKHByb3AuYm9yZGVyU2l6ZSAqIDI1NSAvIHRoaXMubWF4U2l6ZSkgXVxyXG5cdFx0XHR9LFxyXG5cdFx0XHRjb2xvcklkOiAoY3R4LCBwcm9wKSA9PiBwcm9wLmNvbG9yLmxlbmd0aCA/IHtcclxuXHRcdFx0XHRidWZmZXI6IHByb3AuY29sb3JCdWZmZXIsXHJcblx0XHRcdFx0c3RyaWRlOiB0aGlzLnRvb01hbnlDb2xvcnMgPyA4IDogNCxcclxuXHRcdFx0XHRvZmZzZXQ6IDBcclxuXHRcdFx0fSA6IHtcclxuXHRcdFx0XHRjb25zdGFudDogdGhpcy50b29NYW55Q29sb3JzID8gcGFsZXR0ZS5zbGljZShwcm9wLmNvbG9yICogNCwgcHJvcC5jb2xvciAqIDQgKyA0KSA6IFsgcHJvcC5jb2xvciBdXHJcblx0XHRcdH0sXHJcblx0XHRcdGJvcmRlckNvbG9ySWQ6IChjdHgsIHByb3ApID0+IHByb3AuYm9yZGVyQ29sb3IubGVuZ3RoID8ge1xyXG5cdFx0XHRcdGJ1ZmZlcjogcHJvcC5jb2xvckJ1ZmZlcixcclxuXHRcdFx0XHRzdHJpZGU6IHRoaXMudG9vTWFueUNvbG9ycyA/IDggOiA0LFxyXG5cdFx0XHRcdG9mZnNldDogdGhpcy50b29NYW55Q29sb3JzID8gNCA6IDJcclxuXHRcdFx0fSA6IHtcclxuXHRcdFx0XHRjb25zdGFudDogdGhpcy50b29NYW55Q29sb3JzID8gcGFsZXR0ZS5zbGljZShwcm9wLmJvcmRlckNvbG9yICogNCwgcHJvcC5ib3JkZXJDb2xvciAqIDQgKyA0KSA6IFsgcHJvcC5ib3JkZXJDb2xvciBdXHJcblx0XHRcdH0sXHJcblx0XHRcdGlzQWN0aXZlOiAoY3R4LCBwcm9wKSA9PiBwcm9wLmFjdGl2YXRpb24gPT09IHRydWUgPyB7IGNvbnN0YW50OiBbMV0gfSA6IHByb3AuYWN0aXZhdGlvbiA/IHByb3AuYWN0aXZhdGlvbiA6IHsgY29uc3RhbnQ6IFswXSB9XHJcblx0XHR9LFxyXG5cclxuXHRcdGJsZW5kOiB7XHJcblx0XHRcdGVuYWJsZTogdHJ1ZSxcclxuXHRcdFx0Y29sb3I6IFswLDAsMCwxXSxcclxuXHJcblx0XHRcdC8vIHBob3Rvc2hvcCBibGVuZGluZ1xyXG5cdFx0XHRmdW5jOiB7XHJcblx0XHRcdFx0c3JjUkdCOiAnc3JjIGFscGhhJyxcclxuXHRcdFx0XHRkc3RSR0I6ICdvbmUgbWludXMgc3JjIGFscGhhJyxcclxuXHRcdFx0XHRzcmNBbHBoYTogJ29uZSBtaW51cyBkc3QgYWxwaGEnLFxyXG5cdFx0XHRcdGRzdEFscGhhOiAnb25lJ1xyXG5cdFx0XHR9XHJcblx0XHR9LFxyXG5cclxuXHRcdHNjaXNzb3I6IHtcclxuXHRcdFx0ZW5hYmxlOiB0cnVlLFxyXG5cdFx0XHRib3g6IHJlZ2wucHJvcCgndmlld3BvcnQnKVxyXG5cdFx0fSxcclxuXHRcdHZpZXdwb3J0OiByZWdsLnByb3AoJ3ZpZXdwb3J0JyksXHJcblxyXG5cdFx0c3RlbmNpbDoge2VuYWJsZTogZmFsc2V9LFxyXG5cdFx0ZGVwdGg6IHtlbmFibGU6IGZhbHNlfSxcclxuXHJcblx0XHRlbGVtZW50czogcmVnbC5wcm9wKCdlbGVtZW50cycpLFxyXG5cdFx0Y291bnQ6IHJlZ2wucHJvcCgnY291bnQnKSxcclxuXHRcdG9mZnNldDogcmVnbC5wcm9wKCdvZmZzZXQnKSxcclxuXHJcblx0XHRwcmltaXRpdmU6ICdwb2ludHMnXHJcblx0fVxyXG5cclxuXHQvLyBkcmF3IHNkZi1tYXJrZXJcclxuXHRsZXQgbWFya2VyT3B0aW9ucyA9IGV4dGVuZCh7fSwgc2hhZGVyT3B0aW9ucylcclxuXHRtYXJrZXJPcHRpb25zLmZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvciwgZnJhZ0JvcmRlckNvbG9yO1xcbnZhcnlpbmcgZmxvYXQgZnJhZ1dpZHRoLCBmcmFnQm9yZGVyQ29sb3JMZXZlbCwgZnJhZ0NvbG9yTGV2ZWw7XFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgbWFya2VyO1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbywgb3BhY2l0eTtcXG5cXG5mbG9hdCBzbW9vdGhTdGVwKGZsb2F0IHgsIGZsb2F0IHkpIHtcXG4gIHJldHVybiAxLjAgLyAoMS4wICsgZXhwKDUwLjAqKHggLSB5KSkpO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICBmbG9hdCBkaXN0ID0gdGV4dHVyZTJEKG1hcmtlciwgZ2xfUG9pbnRDb29yZCkuciwgZGVsdGEgPSBmcmFnV2lkdGg7XFxuXFxuICAvLyBtYXgtZGlzdGFuY2UgYWxwaGFcXG4gIGlmIChkaXN0IDwgMC4wMDMpIGRpc2NhcmQ7XFxuXFxuICAvLyBudWxsLWJvcmRlciBjYXNlXFxuICBpZiAoZnJhZ0JvcmRlckNvbG9yTGV2ZWwgPT0gZnJhZ0NvbG9yTGV2ZWwgfHwgZnJhZ0JvcmRlckNvbG9yLmEgPT0gMC4pIHtcXG4gICAgZmxvYXQgY29sb3JBbXQgPSBzbW9vdGhzdGVwKC41IC0gZGVsdGEsIC41ICsgZGVsdGEsIGRpc3QpO1xcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGZyYWdDb2xvci5yZ2IsIGNvbG9yQW10ICogZnJhZ0NvbG9yLmEgKiBvcGFjaXR5KTtcXG4gIH1cXG4gIGVsc2Uge1xcbiAgICBmbG9hdCBib3JkZXJDb2xvckFtdCA9IHNtb290aHN0ZXAoZnJhZ0JvcmRlckNvbG9yTGV2ZWwgLSBkZWx0YSwgZnJhZ0JvcmRlckNvbG9yTGV2ZWwgKyBkZWx0YSwgZGlzdCk7XFxuICAgIGZsb2F0IGNvbG9yQW10ID0gc21vb3Roc3RlcChmcmFnQ29sb3JMZXZlbCAtIGRlbHRhLCBmcmFnQ29sb3JMZXZlbCArIGRlbHRhLCBkaXN0KTtcXG5cXG4gICAgdmVjNCBjb2xvciA9IGZyYWdCb3JkZXJDb2xvcjtcXG4gICAgY29sb3IuYSAqPSBib3JkZXJDb2xvckFtdDtcXG4gICAgY29sb3IgPSBtaXgoY29sb3IsIGZyYWdDb2xvciwgY29sb3JBbXQpO1xcbiAgICBjb2xvci5hICo9IG9wYWNpdHk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbiAgfVxcblxcbn1cXG5cIl0pXHJcblx0bWFya2VyT3B0aW9ucy52ZXJ0ID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSBmbG9hdCB4LCB5LCB4RnJhY3QsIHlGcmFjdDtcXG5hdHRyaWJ1dGUgZmxvYXQgc2l6ZSwgYm9yZGVyU2l6ZTtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcklkLCBib3JkZXJDb2xvcklkO1xcbmF0dHJpYnV0ZSBmbG9hdCBpc0FjdGl2ZTtcXG5cXG51bmlmb3JtIHZlYzIgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3QsIHBhbGV0dGVTaXplO1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbztcXG51bmlmb3JtIHNhbXBsZXIyRCBwYWxldHRlO1xcblxcbmNvbnN0IGZsb2F0IG1heFNpemUgPSAxMDAuO1xcbmNvbnN0IGZsb2F0IGJvcmRlckxldmVsID0gLjU7XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvciwgZnJhZ0JvcmRlckNvbG9yO1xcbnZhcnlpbmcgZmxvYXQgZnJhZ1BvaW50U2l6ZSwgZnJhZ0JvcmRlclJhZGl1cyxcXG4gICAgZnJhZ1dpZHRoLCBmcmFnQm9yZGVyQ29sb3JMZXZlbCwgZnJhZ0NvbG9yTGV2ZWw7XFxuXFxudmVjMiBwYWxldHRlQ29vcmQoZmxvYXQgaWQpIHtcXG4gIHJldHVybiB2ZWMyKFxcbiAgICAobW9kKGlkLCBwYWxldHRlU2l6ZS54KSArIC41KSAvIHBhbGV0dGVTaXplLngsXFxuICAgIChmbG9vcihpZCAvIHBhbGV0dGVTaXplLngpICsgLjUpIC8gcGFsZXR0ZVNpemUueVxcbiAgKTtcXG59XFxudmVjMiBwYWxldHRlQ29vcmQodmVjMiBpZCkge1xcbiAgcmV0dXJuIHZlYzIoXFxuICAgIChpZC54ICsgLjUpIC8gcGFsZXR0ZVNpemUueCxcXG4gICAgKGlkLnkgKyAuNSkgLyBwYWxldHRlU2l6ZS55XFxuICApO1xcbn1cXG52ZWM0IGdldENvbG9yKHZlYzQgaWQpIHtcXG4gIC8vIHplcm8tcGFsZXR0ZSBtZWFucyB3ZSBkZWFsIHdpdGggZGlyZWN0IGJ1ZmZlclxcbiAgaWYgKHBhbGV0dGVTaXplLnggPT0gMC4pIHJldHVybiBpZCAvIDI1NS47XFxuICByZXR1cm4gdGV4dHVyZTJEKHBhbGV0dGUsIHBhbGV0dGVDb29yZChpZC54eSkpO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAoaXNBY3RpdmUgPT0gMC4pIHJldHVybjtcXG5cXG4gIHZlYzIgcG9zaXRpb24gPSB2ZWMyKHgsIHkpO1xcbiAgdmVjMiBwb3NpdGlvbkZyYWN0ID0gdmVjMih4RnJhY3QsIHlGcmFjdCk7XFxuXFxuICB2ZWM0IGNvbG9yID0gZ2V0Q29sb3IoY29sb3JJZCk7XFxuICB2ZWM0IGJvcmRlckNvbG9yID0gZ2V0Q29sb3IoYm9yZGVyQ29sb3JJZCk7XFxuXFxuICBmbG9hdCBzaXplID0gc2l6ZSAqIG1heFNpemUgLyAyNTUuO1xcbiAgZmxvYXQgYm9yZGVyU2l6ZSA9IGJvcmRlclNpemUgKiBtYXhTaXplIC8gMjU1LjtcXG5cXG4gIGdsX1BvaW50U2l6ZSA9IDIuICogc2l6ZSAqIHBpeGVsUmF0aW87XFxuICBmcmFnUG9pbnRTaXplID0gc2l6ZSAqIHBpeGVsUmF0aW87XFxuXFxuICB2ZWMyIHBvcyA9IChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZVxcbiAgICAgICsgKHBvc2l0aW9uRnJhY3QgKyB0cmFuc2xhdGVGcmFjdCkgKiBzY2FsZVxcbiAgICAgICsgKHBvc2l0aW9uICsgdHJhbnNsYXRlKSAqIHNjYWxlRnJhY3RcXG4gICAgICArIChwb3NpdGlvbkZyYWN0ICsgdHJhbnNsYXRlRnJhY3QpICogc2NhbGVGcmFjdDtcXG5cXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChwb3MgKiAyLiAtIDEuLCAwLCAxKTtcXG5cXG4gIGZyYWdDb2xvciA9IGNvbG9yO1xcbiAgZnJhZ0JvcmRlckNvbG9yID0gYm9yZGVyQ29sb3I7XFxuICBmcmFnV2lkdGggPSAxLiAvIGdsX1BvaW50U2l6ZTtcXG5cXG4gIGZyYWdCb3JkZXJDb2xvckxldmVsID0gY2xhbXAoYm9yZGVyTGV2ZWwgLSBib3JkZXJMZXZlbCAqIGJvcmRlclNpemUgLyBzaXplLCAwLiwgMS4pO1xcbiAgZnJhZ0NvbG9yTGV2ZWwgPSBjbGFtcChib3JkZXJMZXZlbCArICgxLiAtIGJvcmRlckxldmVsKSAqIGJvcmRlclNpemUgLyBzaXplLCAwLiwgMS4pO1xcbn1cXG5cIl0pXHJcblxyXG5cdHRoaXMuZHJhd01hcmtlciA9IHJlZ2wobWFya2VyT3B0aW9ucylcclxuXHJcblx0Ly8gZHJhdyBjaXJjbGVcclxuXHRsZXQgY2lyY2xlT3B0aW9ucyA9IGV4dGVuZCh7fSwgc2hhZGVyT3B0aW9ucylcclxuXHRjaXJjbGVPcHRpb25zLmZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3IsIGZyYWdCb3JkZXJDb2xvcjtcXG5cXG51bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxudmFyeWluZyBmbG9hdCBmcmFnQm9yZGVyUmFkaXVzLCBmcmFnV2lkdGg7XFxuXFxuZmxvYXQgc21vb3RoU3RlcChmbG9hdCBlZGdlMCwgZmxvYXQgZWRnZTEsIGZsb2F0IHgpIHtcXG5cXHRmbG9hdCB0O1xcblxcdHQgPSBjbGFtcCgoeCAtIGVkZ2UwKSAvIChlZGdlMSAtIGVkZ2UwKSwgMC4wLCAxLjApO1xcblxcdHJldHVybiB0ICogdCAqICgzLjAgLSAyLjAgKiB0KTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcblxcdGZsb2F0IHJhZGl1cywgYWxwaGEgPSAxLjAsIGRlbHRhID0gZnJhZ1dpZHRoO1xcblxcblxcdHJhZGl1cyA9IGxlbmd0aCgyLjAgKiBnbF9Qb2ludENvb3JkLnh5IC0gMS4wKTtcXG5cXG5cXHRpZiAocmFkaXVzID4gMS4wICsgZGVsdGEpIHtcXG5cXHRcXHRkaXNjYXJkO1xcblxcdH1cXG5cXG5cXHRhbHBoYSAtPSBzbW9vdGhzdGVwKDEuMCAtIGRlbHRhLCAxLjAgKyBkZWx0YSwgcmFkaXVzKTtcXG5cXG5cXHRmbG9hdCBib3JkZXJSYWRpdXMgPSBmcmFnQm9yZGVyUmFkaXVzO1xcblxcdGZsb2F0IHJhdGlvID0gc21vb3Roc3RlcChib3JkZXJSYWRpdXMgLSBkZWx0YSwgYm9yZGVyUmFkaXVzICsgZGVsdGEsIHJhZGl1cyk7XFxuXFx0dmVjNCBjb2xvciA9IG1peChmcmFnQ29sb3IsIGZyYWdCb3JkZXJDb2xvciwgcmF0aW8pO1xcblxcdGNvbG9yLmEgKj0gYWxwaGEgKiBvcGFjaXR5O1xcblxcdGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbn1cXG5cIl0pXHJcblx0Y2lyY2xlT3B0aW9ucy52ZXJ0ID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgZmxvYXQgeCwgeSwgeEZyYWN0LCB5RnJhY3Q7XFxuYXR0cmlidXRlIGZsb2F0IHNpemUsIGJvcmRlclNpemU7XFxuYXR0cmlidXRlIHZlYzQgY29sb3JJZCwgYm9yZGVyQ29sb3JJZDtcXG5hdHRyaWJ1dGUgZmxvYXQgaXNBY3RpdmU7XFxuXFxudW5pZm9ybSB2ZWMyIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0O1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbztcXG51bmlmb3JtIHNhbXBsZXIyRCBwYWxldHRlO1xcbnVuaWZvcm0gdmVjMiBwYWxldHRlU2l6ZTtcXG5cXG5jb25zdCBmbG9hdCBtYXhTaXplID0gMTAwLjtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yLCBmcmFnQm9yZGVyQ29sb3I7XFxudmFyeWluZyBmbG9hdCBmcmFnQm9yZGVyUmFkaXVzLCBmcmFnV2lkdGg7XFxuXFxudmVjMiBwYWxldHRlQ29vcmQoZmxvYXQgaWQpIHtcXG4gIHJldHVybiB2ZWMyKFxcbiAgICAobW9kKGlkLCBwYWxldHRlU2l6ZS54KSArIC41KSAvIHBhbGV0dGVTaXplLngsXFxuICAgIChmbG9vcihpZCAvIHBhbGV0dGVTaXplLngpICsgLjUpIC8gcGFsZXR0ZVNpemUueVxcbiAgKTtcXG59XFxudmVjMiBwYWxldHRlQ29vcmQodmVjMiBpZCkge1xcbiAgcmV0dXJuIHZlYzIoXFxuICAgIChpZC54ICsgLjUpIC8gcGFsZXR0ZVNpemUueCxcXG4gICAgKGlkLnkgKyAuNSkgLyBwYWxldHRlU2l6ZS55XFxuICApO1xcbn1cXG5cXG52ZWM0IGdldENvbG9yKHZlYzQgaWQpIHtcXG4gIC8vIHplcm8tcGFsZXR0ZSBtZWFucyB3ZSBkZWFsIHdpdGggZGlyZWN0IGJ1ZmZlclxcbiAgaWYgKHBhbGV0dGVTaXplLnggPT0gMC4pIHJldHVybiBpZCAvIDI1NS47XFxuICByZXR1cm4gdGV4dHVyZTJEKHBhbGV0dGUsIHBhbGV0dGVDb29yZChpZC54eSkpO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICAvLyBpZ25vcmUgaW5hY3RpdmUgcG9pbnRzXFxuICBpZiAoaXNBY3RpdmUgPT0gMC4pIHJldHVybjtcXG5cXG4gIHZlYzIgcG9zaXRpb24gPSB2ZWMyKHgsIHkpO1xcbiAgdmVjMiBwb3NpdGlvbkZyYWN0ID0gdmVjMih4RnJhY3QsIHlGcmFjdCk7XFxuXFxuICB2ZWM0IGNvbG9yID0gZ2V0Q29sb3IoY29sb3JJZCk7XFxuICB2ZWM0IGJvcmRlckNvbG9yID0gZ2V0Q29sb3IoYm9yZGVyQ29sb3JJZCk7XFxuXFxuICBmbG9hdCBzaXplID0gc2l6ZSAqIG1heFNpemUgLyAyNTUuO1xcbiAgZmxvYXQgYm9yZGVyU2l6ZSA9IGJvcmRlclNpemUgKiBtYXhTaXplIC8gMjU1LjtcXG5cXG4gIGdsX1BvaW50U2l6ZSA9IChzaXplICsgYm9yZGVyU2l6ZSkgKiBwaXhlbFJhdGlvO1xcblxcbiAgdmVjMiBwb3MgPSAocG9zaXRpb24gKyB0cmFuc2xhdGUpICogc2NhbGVcXG4gICAgICArIChwb3NpdGlvbkZyYWN0ICsgdHJhbnNsYXRlRnJhY3QpICogc2NhbGVcXG4gICAgICArIChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZUZyYWN0XFxuICAgICAgKyAocG9zaXRpb25GcmFjdCArIHRyYW5zbGF0ZUZyYWN0KSAqIHNjYWxlRnJhY3Q7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zICogMi4gLSAxLiwgMCwgMSk7XFxuXFxuICBmcmFnQm9yZGVyUmFkaXVzID0gMS4gLSAyLiAqIGJvcmRlclNpemUgLyAoc2l6ZSArIGJvcmRlclNpemUpO1xcbiAgZnJhZ0NvbG9yID0gY29sb3I7XFxuICBmcmFnQm9yZGVyQ29sb3IgPSBib3JkZXJDb2xvci5hID09IDAuIHx8IGJvcmRlclNpemUgPT0gMC4gPyB2ZWM0KGNvbG9yLnJnYiwgMC4pIDogYm9yZGVyQ29sb3I7XFxuICBmcmFnV2lkdGggPSAxLiAvIGdsX1BvaW50U2l6ZTtcXG59XFxuXCJdKVxyXG5cclxuXHQvLyBwb2x5ZmlsbCBJRVxyXG5cdGlmIChpZSkge1xyXG5cdFx0Y2lyY2xlT3B0aW9ucy5mcmFnID0gY2lyY2xlT3B0aW9ucy5mcmFnLnJlcGxhY2UoJ3Ntb290aHN0ZXAnLCAnc21vb3RoU3RlcCcpXHJcblx0XHRtYXJrZXJPcHRpb25zLmZyYWcgPSBtYXJrZXJPcHRpb25zLmZyYWcucmVwbGFjZSgnc21vb3Roc3RlcCcsICdzbW9vdGhTdGVwJylcclxuXHR9XHJcblxyXG5cdHRoaXMuZHJhd0NpcmNsZSA9IHJlZ2woY2lyY2xlT3B0aW9ucylcclxufVxyXG5cclxuLy8gc2luZ2xlIHBhc3MgZGVmYXVsdHNcclxuU2NhdHRlci5kZWZhdWx0cyA9IHtcclxuXHRjb2xvcjogJ2JsYWNrJyxcclxuXHRib3JkZXJDb2xvcjogJ3RyYW5zcGFyZW50JyxcclxuXHRib3JkZXJTaXplOiAwLFxyXG5cdHNpemU6IDEyLFxyXG5cdG9wYWNpdHk6IDEsXHJcblx0bWFya2VyOiB1bmRlZmluZWQsXHJcblx0dmlld3BvcnQ6IG51bGwsXHJcblx0cmFuZ2U6IG51bGwsXHJcblx0cGl4ZWxTaXplOiBudWxsLFxyXG5cdGNvdW50OiAwLFxyXG5cdG9mZnNldDogMCxcclxuXHRib3VuZHM6IG51bGwsXHJcblx0cG9zaXRpb25zOiBbXSxcclxuXHRzbmFwOiAxZTRcclxufVxyXG5cclxuXHJcbi8vIHVwZGF0ZSAmIHJlZHJhd1xyXG5TY2F0dGVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoLi4uYXJncykge1xyXG5cdGlmIChhcmdzLmxlbmd0aCkge1xyXG5cdFx0dGhpcy51cGRhdGUoLi4uYXJncylcclxuXHR9XHJcblxyXG5cdHRoaXMuZHJhdygpXHJcblxyXG5cdHJldHVybiB0aGlzXHJcbn1cclxuXHJcblxyXG4vLyBkcmF3IGFsbCBncm91cHMgb3Igb25seSBpbmRpY2F0ZWQgb25lc1xyXG5TY2F0dGVyLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcclxuXHRsZXQgeyBncm91cHMgfSA9IHRoaXNcclxuXHJcblx0Ly8gaWYgZGlyZWN0bHkgYXJyYXkgcGFzc2VkIC0gdHJlYXQgYXMgcGFzc2VzXHJcblx0aWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIEFycmF5LmlzQXJyYXkoYXJnc1swXSkgICYmIChhcmdzWzBdWzBdID09PSBudWxsIHx8IEFycmF5LmlzQXJyYXkoYXJnc1swXVswXSkpKSB7XHJcblx0XHRhcmdzID0gYXJnc1swXVxyXG5cdH1cclxuXHJcblx0Ly8gRklYTUU6IHJlbW92ZSBvbmNlIGh0dHBzOi8vZ2l0aHViLmNvbS9yZWdsLXByb2plY3QvcmVnbC9pc3N1ZXMvNDc0IHJlc29sdmVkXHJcblx0dGhpcy5yZWdsLl9yZWZyZXNoKClcclxuXHJcblx0aWYgKGFyZ3MubGVuZ3RoKSB7XHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dGhpcy5kcmF3SXRlbShpLCBhcmdzW2ldKVxyXG5cdFx0fVxyXG5cdH1cclxuXHQvLyBkcmF3IGFsbCBwYXNzZXNcclxuXHRlbHNlIHtcclxuXHRcdGdyb3Vwcy5mb3JFYWNoKChncm91cCwgaSkgPT4ge1xyXG5cdFx0XHR0aGlzLmRyYXdJdGVtKGkpXHJcblx0XHR9KVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRoaXNcclxufVxyXG5cclxuLy8gZHJhdyBzcGVjaWZpYyBzY2F0dGVyIGdyb3VwXHJcblNjYXR0ZXIucHJvdG90eXBlLmRyYXdJdGVtID0gZnVuY3Rpb24gKGlkLCBlbHMpIHtcclxuXHRsZXQgeyBncm91cHMgfSA9IHRoaXNcclxuXHRsZXQgZ3JvdXAgPSBncm91cHNbaWRdXHJcblxyXG5cdC8vIGRlYnVnIHZpZXdwb3J0XHJcblx0Ly8gbGV0IHsgdmlld3BvcnQgfSA9IGdyb3VwXHJcblx0Ly8gZ2wuZW5hYmxlKGdsLlNDSVNTT1JfVEVTVCk7XHJcblx0Ly8gZ2wuc2Npc3Nvcih2aWV3cG9ydC54LCB2aWV3cG9ydC55LCB2aWV3cG9ydC53aWR0aCwgdmlld3BvcnQuaGVpZ2h0KTtcclxuXHQvLyBnbC5jbGVhckNvbG9yKDAsIDAsIDAsIC41KTtcclxuXHQvLyBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKTtcclxuXHJcblx0aWYgKHR5cGVvZiBlbHMgPT09ICdudW1iZXInKSB7XHJcblx0XHRpZCA9IGVsc1xyXG5cdFx0Z3JvdXAgPSBncm91cHNbZWxzXVxyXG5cdFx0ZWxzID0gbnVsbFxyXG5cdH1cclxuXHJcblx0aWYgKCEoZ3JvdXAgJiYgZ3JvdXAuY291bnQgJiYgZ3JvdXAub3BhY2l0eSkpIHJldHVyblxyXG5cclxuXHQvLyBkcmF3IGNpcmNsZXNcclxuXHRpZiAoZ3JvdXAuYWN0aXZhdGlvblswXSkge1xyXG5cdFx0Ly8gVE9ETzogb3B0aW1pemUgdGhpcyBwZXJmb3JtYW5jZSBieSBtYWtpbmcgZ3JvdXBzIGFuZCByZWdsLnRoaXMgcHJvcHNcclxuXHRcdHRoaXMuZHJhd0NpcmNsZSh0aGlzLmdldE1hcmtlckRyYXdPcHRpb25zKDAsIGdyb3VwLCBlbHMpKVxyXG5cdH1cclxuXHJcblx0Ly8gZHJhdyBhbGwgb3RoZXIgYXZhaWxhYmxlIG1hcmtlcnNcclxuXHRsZXQgYmF0Y2ggPSBbXVxyXG5cclxuXHRmb3IgKGxldCBpID0gMTsgaSA8IGdyb3VwLmFjdGl2YXRpb24ubGVuZ3RoOyBpKyspIHtcclxuXHRcdGlmICghZ3JvdXAuYWN0aXZhdGlvbltpXSB8fCAoZ3JvdXAuYWN0aXZhdGlvbltpXSAhPT0gdHJ1ZSAmJiAhZ3JvdXAuYWN0aXZhdGlvbltpXS5kYXRhLmxlbmd0aCkpIGNvbnRpbnVlXHJcblxyXG5cdFx0YmF0Y2gucHVzaCguLi50aGlzLmdldE1hcmtlckRyYXdPcHRpb25zKGksIGdyb3VwLCBlbHMpKVxyXG5cdH1cclxuXHJcblx0aWYgKGJhdGNoLmxlbmd0aCkge1xyXG5cdFx0dGhpcy5kcmF3TWFya2VyKGJhdGNoKVxyXG5cdH1cclxufVxyXG5cclxuLy8gZ2V0IG9wdGlvbnMgZm9yIHRoZSBtYXJrZXIgaWRzXHJcblNjYXR0ZXIucHJvdG90eXBlLmdldE1hcmtlckRyYXdPcHRpb25zID0gZnVuY3Rpb24obWFya2VySWQsIGdyb3VwLCBlbGVtZW50cykge1xyXG5cdGxldCB7IHJhbmdlLCB0cmVlLCB2aWV3cG9ydCwgYWN0aXZhdGlvbiwgc2VsZWN0aW9uQnVmZmVyLCBjb3VudCB9ID0gZ3JvdXBcclxuXHRsZXQgeyByZWdsIH0gPSB0aGlzXHJcblxyXG5cdC8vIGRpcmVjdCBwb2ludHNcclxuXHRpZiAoIXRyZWUpIHtcclxuXHRcdC8vIGlmIGVsZW1lbnRzIGFycmF5IC0gZHJhdyB1bmNsdXN0ZXJlZCBwb2ludHNcclxuXHRcdGlmIChlbGVtZW50cykge1xyXG5cdFx0XHRyZXR1cm4gW2V4dGVuZCh7fSwgZ3JvdXAsIHtcclxuXHRcdFx0XHRtYXJrZXJUZXh0dXJlOiB0aGlzLm1hcmtlclRleHR1cmVzW21hcmtlcklkXSxcclxuXHRcdFx0XHRhY3RpdmF0aW9uOiBhY3RpdmF0aW9uW21hcmtlcklkXSxcclxuXHRcdFx0XHRjb3VudDogZWxlbWVudHMubGVuZ3RoLFxyXG5cdFx0XHRcdGVsZW1lbnRzLFxyXG5cdFx0XHRcdG9mZnNldDogMFxyXG5cdFx0XHR9KV1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gWyBleHRlbmQoe30sIGdyb3VwLCB7XHJcblx0XHRcdG1hcmtlclRleHR1cmU6IHRoaXMubWFya2VyVGV4dHVyZXNbbWFya2VySWRdLFxyXG5cdFx0XHRhY3RpdmF0aW9uOiBhY3RpdmF0aW9uW21hcmtlcklkXSxcclxuXHRcdFx0b2Zmc2V0OiAwXHJcblx0XHR9KSBdXHJcblx0fVxyXG5cclxuXHQvLyBjbHVzdGVyZWQgcG9pbnRzXHJcblx0bGV0IGJhdGNoID0gW11cclxuXHJcblx0bGV0IGxvZCA9IHRyZWUucmFuZ2UocmFuZ2UsIHsgbG9kOiB0cnVlLCBweDogW1xyXG5cdFx0KHJhbmdlWzJdIC0gcmFuZ2VbMF0pIC8gdmlld3BvcnQud2lkdGgsXHJcblx0XHQocmFuZ2VbM10gLSByYW5nZVsxXSkgLyB2aWV3cG9ydC5oZWlnaHRcclxuXHRdfSlcclxuXHJcblx0Ly8gZW5hYmxlIGVsZW1lbnRzIGJ5IHVzaW5nIHNlbGVjdGlvbiBidWZmZXJcclxuXHRpZiAoZWxlbWVudHMpIHtcclxuXHRcdGxldCBtYXJrZXJBY3RpdmF0aW9uID0gYWN0aXZhdGlvblttYXJrZXJJZF1cclxuXHRcdGxldCBtYXNrID0gbWFya2VyQWN0aXZhdGlvbi5kYXRhXHJcblx0XHRsZXQgZGF0YSA9IG5ldyBVaW50OEFycmF5KGNvdW50KVxyXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRsZXQgaWQgPSBlbGVtZW50c1tpXVxyXG5cdFx0XHRkYXRhW2lkXSA9IG1hc2sgPyBtYXNrW2lkXSA6IDFcclxuXHRcdH1cclxuXHRcdHNlbGVjdGlvbkJ1ZmZlci5zdWJkYXRhKGRhdGEpXHJcblx0fVxyXG5cclxuXHRmb3IgKGxldCBsID0gbG9kLmxlbmd0aDsgbC0tOykge1xyXG5cdFx0bGV0IFtmcm9tLCB0b10gPSBsb2RbbF1cclxuXHJcblx0XHRiYXRjaC5wdXNoKGV4dGVuZCh7fSwgZ3JvdXAsIHtcclxuXHRcdFx0bWFya2VyVGV4dHVyZTogdGhpcy5tYXJrZXJUZXh0dXJlc1ttYXJrZXJJZF0sXHJcblx0XHRcdGFjdGl2YXRpb246IGVsZW1lbnRzID8gc2VsZWN0aW9uQnVmZmVyIDogYWN0aXZhdGlvblttYXJrZXJJZF0sXHJcblx0XHRcdG9mZnNldDogZnJvbSxcclxuXHRcdFx0Y291bnQ6IHRvIC0gZnJvbVxyXG5cdFx0fSkpXHJcblx0fVxyXG5cclxuXHRyZXR1cm4gYmF0Y2hcclxufVxyXG5cclxuLy8gdXBkYXRlIGdyb3VwcyBvcHRpb25zXHJcblNjYXR0ZXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XHJcblx0aWYgKCFhcmdzLmxlbmd0aCkgcmV0dXJuXHJcblxyXG5cdC8vIHBhc3NlcyBhcmUgYXMgc2luZ2xlIGFycmF5XHJcblx0aWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIEFycmF5LmlzQXJyYXkoYXJnc1swXSkpIGFyZ3MgPSBhcmdzWzBdXHJcblxyXG5cdGxldCB7IGdyb3VwcywgZ2wsIHJlZ2wsIG1heFNpemUsIG1heENvbG9ycywgcGFsZXR0ZSB9ID0gdGhpc1xyXG5cclxuXHR0aGlzLmdyb3VwcyA9IGdyb3VwcyA9IGFyZ3MubWFwKChvcHRpb25zLCBpKSA9PiB7XHJcblx0XHRsZXQgZ3JvdXAgPSBncm91cHNbaV1cclxuXHJcblx0XHRpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZ3JvdXBcclxuXHJcblx0XHRpZiAob3B0aW9ucyA9PT0gbnVsbCkgb3B0aW9ucyA9IHsgcG9zaXRpb25zOiBudWxsIH1cclxuXHRcdGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSBvcHRpb25zID0geyBvbmRyYXc6IG9wdGlvbnMgfVxyXG5cdFx0ZWxzZSBpZiAodHlwZW9mIG9wdGlvbnNbMF0gPT09ICdudW1iZXInKSBvcHRpb25zID0geyBwb3NpdGlvbnM6IG9wdGlvbnMgfVxyXG5cclxuXHRcdC8vIGNvcHkgb3B0aW9ucyB0byBhdm9pZCBtdXRhdGlvbiAmIGhhbmRsZSBhbGlhc2VzXHJcblx0XHRvcHRpb25zID0gcGljayhvcHRpb25zLCB7XHJcblx0XHRcdHBvc2l0aW9uczogJ3Bvc2l0aW9ucyBkYXRhIHBvaW50cycsXHJcblx0XHRcdHNuYXA6ICdzbmFwIGNsdXN0ZXIgbG9kIHRyZWUnLFxyXG5cdFx0XHRzaXplOiAnc2l6ZXMgc2l6ZSByYWRpdXMnLFxyXG5cdFx0XHRib3JkZXJTaXplOiAnYm9yZGVyU2l6ZXMgYm9yZGVyU2l6ZSBib3JkZXItc2l6ZSBib3JkZXJzaXplIGJvcmRlcldpZHRoIGJvcmRlcldpZHRocyBib3JkZXItd2lkdGggYm9yZGVyd2lkdGggc3Ryb2tlLXdpZHRoIHN0cm9rZVdpZHRoIHN0cm9rZXdpZHRoIG91dGxpbmUnLFxyXG5cdFx0XHRjb2xvcjogJ2NvbG9ycyBjb2xvciBmaWxsIGZpbGwtY29sb3IgZmlsbENvbG9yJyxcclxuXHRcdFx0Ym9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcnMgYm9yZGVyQ29sb3Igc3Ryb2tlIHN0cm9rZS1jb2xvciBzdHJva2VDb2xvcicsXHJcblx0XHRcdG1hcmtlcjogJ21hcmtlcnMgbWFya2VyIHNoYXBlJyxcclxuXHRcdFx0cmFuZ2U6ICdyYW5nZSBkYXRhQm94IGRhdGFib3gnLFxyXG5cdFx0XHR2aWV3cG9ydDogJ3ZpZXdwb3J0IHZpZXdQb3J0IHZpZXdCb3ggdmlld2JveCcsXHJcblx0XHRcdG9wYWNpdHk6ICdvcGFjaXR5IGFscGhhIHRyYW5zcGFyZW5jeScsXHJcblx0XHRcdGJvdW5kczogJ2JvdW5kIGJvdW5kcyBib3VuZGFyaWVzIGxpbWl0cydcclxuXHRcdH0pXHJcblxyXG5cdFx0aWYgKG9wdGlvbnMucG9zaXRpb25zID09PSBudWxsKSBvcHRpb25zLnBvc2l0aW9ucyA9IFtdXHJcblxyXG5cdFx0aWYgKCFncm91cCkge1xyXG5cdFx0XHRncm91cHNbaV0gPSBncm91cCA9IHtcclxuXHRcdFx0XHRpZDogaSxcclxuXHRcdFx0XHRzY2FsZTogbnVsbCxcclxuXHRcdFx0XHR0cmFuc2xhdGU6IG51bGwsXHJcblx0XHRcdFx0c2NhbGVGcmFjdDogbnVsbCxcclxuXHRcdFx0XHR0cmFuc2xhdGVGcmFjdDogbnVsbCxcclxuXHJcblx0XHRcdFx0Ly8gYnVmZmVycyBmb3IgYWN0aXZlIG1hcmtlcnNcclxuXHRcdFx0XHRhY3RpdmF0aW9uOiBbXSxcclxuXHJcblx0XHRcdFx0Ly8gYnVmZmVyIGZvciBmaWx0ZXJlZCBtYXJrZXJzXHJcblx0XHRcdFx0c2VsZWN0aW9uQnVmZmVyOiByZWdsLmJ1ZmZlcih7XHJcblx0XHRcdFx0XHRkYXRhOiBuZXcgVWludDhBcnJheSgwKSxcclxuXHRcdFx0XHRcdHVzYWdlOiAnc3RyZWFtJyxcclxuXHRcdFx0XHRcdHR5cGU6ICd1aW50OCdcclxuXHRcdFx0XHR9KSxcclxuXHJcblx0XHRcdFx0Ly8gYnVmZmVycyB3aXRoIGRhdGE6IGl0IGlzIGZhc3RlciB0byBzd2l0Y2ggdGhlbSBwZXItcGFzc1xyXG5cdFx0XHRcdC8vIHRoYW4gcHJvdmlkZSBvbmUgY29uZ3JlZ2F0ZSBidWZmZXJcclxuXHRcdFx0XHRzaXplQnVmZmVyOiByZWdsLmJ1ZmZlcih7XHJcblx0XHRcdFx0XHRkYXRhOiBuZXcgVWludDhBcnJheSgwKSxcclxuXHRcdFx0XHRcdHVzYWdlOiAnZHluYW1pYycsXHJcblx0XHRcdFx0XHR0eXBlOiAndWludDgnXHJcblx0XHRcdFx0fSksXHJcblx0XHRcdFx0Y29sb3JCdWZmZXI6IHJlZ2wuYnVmZmVyKHtcclxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KDApLFxyXG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcclxuXHRcdFx0XHRcdHR5cGU6ICd1aW50OCdcclxuXHRcdFx0XHR9KSxcclxuXHRcdFx0XHRwb3NpdGlvbkJ1ZmZlcjogcmVnbC5idWZmZXIoe1xyXG5cdFx0XHRcdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoMCksXHJcblx0XHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxyXG5cdFx0XHRcdFx0dHlwZTogJ2Zsb2F0J1xyXG5cdFx0XHRcdH0pLFxyXG5cdFx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXI6IHJlZ2wuYnVmZmVyKHtcclxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KDApLFxyXG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcclxuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCdcclxuXHRcdFx0XHR9KVxyXG5cdFx0XHR9XHJcblx0XHRcdG9wdGlvbnMgPSBleHRlbmQoe30sIFNjYXR0ZXIuZGVmYXVsdHMsIG9wdGlvbnMpXHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gZm9yY2UgdXBkYXRlIHRyaWdnZXJzXHJcblx0XHRpZiAob3B0aW9ucy5wb3NpdGlvbnMgJiYgISgnbWFya2VyJyBpbiBvcHRpb25zKSkge1xyXG5cdFx0XHRvcHRpb25zLm1hcmtlciA9IGdyb3VwLm1hcmtlclxyXG5cdFx0XHRkZWxldGUgZ3JvdXAubWFya2VyXHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gdXBkYXRpbmcgbWFya2VycyBjYXVzZSByZWNhbGN1bGF0aW5nIHNuYXBwaW5nXHJcblx0XHRpZiAob3B0aW9ucy5tYXJrZXIgJiYgISgncG9zaXRpb25zJyBpbiBvcHRpb25zKSkge1xyXG5cdFx0XHRvcHRpb25zLnBvc2l0aW9ucyA9IGdyb3VwLnBvc2l0aW9uc1xyXG5cdFx0XHRkZWxldGUgZ3JvdXAucG9zaXRpb25zXHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gZ2xvYmFsIGNvdW50IG9mIHBvaW50c1xyXG5cdFx0bGV0IGhhc1NpemUgPSAwLCBoYXNDb2xvciA9IDBcclxuXHJcblx0XHR1cGRhdGVEaWZmKGdyb3VwLCBvcHRpb25zLCBbe1xyXG5cdFx0XHRzbmFwOiB0cnVlLFxyXG5cdFx0XHRzaXplOiAocywgZ3JvdXApID0+IHtcclxuXHRcdFx0XHRpZiAocyA9PSBudWxsKSBzID0gU2NhdHRlci5kZWZhdWx0cy5zaXplXHJcblx0XHRcdFx0aGFzU2l6ZSArPSBzICYmIHMubGVuZ3RoID8gMSA6IDBcclxuXHRcdFx0XHRyZXR1cm4gc1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRib3JkZXJTaXplOiAocywgZ3JvdXApID0+IHtcclxuXHRcdFx0XHRpZiAocyA9PSBudWxsKSBzID0gU2NhdHRlci5kZWZhdWx0cy5ib3JkZXJTaXplXHJcblx0XHRcdFx0aGFzU2l6ZSArPSBzICYmIHMubGVuZ3RoID8gMSA6IDBcclxuXHRcdFx0XHRyZXR1cm4gc1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRvcGFjaXR5OiBwYXJzZUZsb2F0LFxyXG5cclxuXHRcdFx0Ly8gYWRkIGNvbG9ycyB0byBwYWxldHRlLCBzYXZlIHJlZmVyZW5jZXNcclxuXHRcdFx0Y29sb3I6IChjLCBncm91cCkgPT4ge1xyXG5cdFx0XHRcdGlmIChjID09IG51bGwpIGMgPSBTY2F0dGVyLmRlZmF1bHRzLmNvbG9yXHJcblx0XHRcdFx0YyA9IHRoaXMudXBkYXRlQ29sb3IoYylcclxuXHRcdFx0XHRoYXNDb2xvcisrXHJcblx0XHRcdFx0cmV0dXJuIGNcclxuXHRcdFx0fSxcclxuXHRcdFx0Ym9yZGVyQ29sb3I6IChjLCBncm91cCkgPT4ge1xyXG5cdFx0XHRcdGlmIChjID09IG51bGwpIGMgPSBTY2F0dGVyLmRlZmF1bHRzLmJvcmRlckNvbG9yXHJcblx0XHRcdFx0YyA9IHRoaXMudXBkYXRlQ29sb3IoYylcclxuXHRcdFx0XHRoYXNDb2xvcisrXHJcblx0XHRcdFx0cmV0dXJuIGNcclxuXHRcdFx0fSxcclxuXHJcblx0XHRcdGJvdW5kczogKGJvdW5kcywgZ3JvdXAsIG9wdGlvbnMpID0+IHtcclxuXHRcdFx0XHRpZiAoISgncmFuZ2UnIGluIG9wdGlvbnMpKSBvcHRpb25zLnJhbmdlID0gbnVsbFxyXG5cdFx0XHRcdHJldHVybiBib3VuZHNcclxuXHRcdFx0fSxcclxuXHJcblx0XHRcdHBvc2l0aW9uczogKHBvc2l0aW9ucywgZ3JvdXAsIG9wdGlvbnMpID0+IHtcclxuXHRcdFx0XHRsZXQgeyBzbmFwIH0gPSBncm91cFxyXG5cdFx0XHRcdGxldCB7IHBvc2l0aW9uQnVmZmVyLCBwb3NpdGlvbkZyYWN0QnVmZmVyLCBzZWxlY3Rpb25CdWZmZXIgfSA9IGdyb3VwXHJcblxyXG5cdFx0XHRcdC8vIHNlcGFyYXRlIGJ1ZmZlcnMgZm9yIHgveSBjb29yZGluYXRlc1xyXG5cdFx0XHRcdGlmIChwb3NpdGlvbnMueCB8fCBwb3NpdGlvbnMueSkge1xyXG5cdFx0XHRcdFx0aWYgKHBvc2l0aW9ucy54Lmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRncm91cC54QXR0ciA9IHtcclxuXHRcdFx0XHRcdFx0XHRidWZmZXI6IHJlZ2wuYnVmZmVyKHBvc2l0aW9ucy54KSxcclxuXHRcdFx0XHRcdFx0XHRvZmZzZXQ6IDAsXHJcblx0XHRcdFx0XHRcdFx0c3RyaWRlOiA0LFxyXG5cdFx0XHRcdFx0XHRcdGNvdW50OiBwb3NpdGlvbnMueC5sZW5ndGhcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdGdyb3VwLnhBdHRyID0ge1xyXG5cdFx0XHRcdFx0XHRcdGJ1ZmZlcjogcG9zaXRpb25zLnguYnVmZmVyLFxyXG5cdFx0XHRcdFx0XHRcdG9mZnNldDogcG9zaXRpb25zLngub2Zmc2V0ICogNCB8fCAwLFxyXG5cdFx0XHRcdFx0XHRcdHN0cmlkZTogKHBvc2l0aW9ucy54LnN0cmlkZSB8fCAxKSAqIDQsXHJcblx0XHRcdFx0XHRcdFx0Y291bnQ6IHBvc2l0aW9ucy54LmNvdW50XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmIChwb3NpdGlvbnMueS5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0Z3JvdXAueUF0dHIgPSB7XHJcblx0XHRcdFx0XHRcdFx0YnVmZmVyOiByZWdsLmJ1ZmZlcihwb3NpdGlvbnMueSksXHJcblx0XHRcdFx0XHRcdFx0b2Zmc2V0OiAwLFxyXG5cdFx0XHRcdFx0XHRcdHN0cmlkZTogNCxcclxuXHRcdFx0XHRcdFx0XHRjb3VudDogcG9zaXRpb25zLnkubGVuZ3RoXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRncm91cC55QXR0ciA9IHtcclxuXHRcdFx0XHRcdFx0XHRidWZmZXI6IHBvc2l0aW9ucy55LmJ1ZmZlcixcclxuXHRcdFx0XHRcdFx0XHRvZmZzZXQ6IHBvc2l0aW9ucy55Lm9mZnNldCAqIDQgfHwgMCxcclxuXHRcdFx0XHRcdFx0XHRzdHJpZGU6IChwb3NpdGlvbnMueS5zdHJpZGUgfHwgMSkgKiA0LFxyXG5cdFx0XHRcdFx0XHRcdGNvdW50OiBwb3NpdGlvbnMueS5jb3VudFxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRncm91cC5jb3VudCA9IE1hdGgubWF4KGdyb3VwLnhBdHRyLmNvdW50LCBncm91cC55QXR0ci5jb3VudClcclxuXHJcblx0XHRcdFx0XHRyZXR1cm4gcG9zaXRpb25zXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRwb3NpdGlvbnMgPSBmbGF0dGVuKHBvc2l0aW9ucywgJ2Zsb2F0NjQnKVxyXG5cclxuXHRcdFx0XHRsZXQgY291bnQgPSBncm91cC5jb3VudCA9IE1hdGguZmxvb3IocG9zaXRpb25zLmxlbmd0aCAvIDIpXHJcblx0XHRcdFx0bGV0IGJvdW5kcyA9IGdyb3VwLmJvdW5kcyA9IGNvdW50ID8gZ2V0Qm91bmRzKHBvc2l0aW9ucywgMikgOiBudWxsXHJcblxyXG5cdFx0XHRcdC8vIGlmIHJhbmdlIGlzIG5vdCBwcm92aWRlZCB1cGRhdGVkIC0gcmVjYWxjIGl0XHJcblx0XHRcdFx0aWYgKCFvcHRpb25zLnJhbmdlICYmICFncm91cC5yYW5nZSkge1xyXG5cdFx0XHRcdFx0ZGVsZXRlIGdyb3VwLnJhbmdlXHJcblx0XHRcdFx0XHRvcHRpb25zLnJhbmdlID0gYm91bmRzXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyByZXNldCBtYXJrZXJcclxuXHRcdFx0XHRpZiAoIW9wdGlvbnMubWFya2VyICYmICFncm91cC5tYXJrZXIpIHtcclxuXHRcdFx0XHRcdGRlbGV0ZSBncm91cC5tYXJrZXI7XHJcblx0XHRcdFx0XHRvcHRpb25zLm1hcmtlciA9IG51bGw7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBidWlsZCBjbHVzdGVyIHRyZWUgaWYgcmVxdWlyZWRcclxuXHRcdFx0XHRpZiAoc25hcCAmJiAoc25hcCA9PT0gdHJ1ZSB8fCBjb3VudCA+IHNuYXApKSB7XHJcblx0XHRcdFx0XHRncm91cC50cmVlID0gY2x1c3Rlcihwb3NpdGlvbnMsIHsgYm91bmRzIH0pXHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdC8vIGV4aXN0aW5nIHRyZWUgaW5zdGFuY2VcclxuXHRcdFx0XHRlbHNlIGlmIChzbmFwICYmIHNuYXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRncm91cC50cmVlID0gc25hcFxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKGdyb3VwLnRyZWUpIHtcclxuXHRcdFx0XHRcdGxldCBvcHRzID0ge1xyXG5cdFx0XHRcdFx0XHRwcmltaXRpdmU6ICdwb2ludHMnLFxyXG5cdFx0XHRcdFx0XHR1c2FnZTogJ3N0YXRpYycsXHJcblx0XHRcdFx0XHRcdGRhdGE6IGdyb3VwLnRyZWUsXHJcblx0XHRcdFx0XHRcdHR5cGU6ICd1aW50MzInXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRpZiAoZ3JvdXAuZWxlbWVudHMpIGdyb3VwLmVsZW1lbnRzKG9wdHMpXHJcblx0XHRcdFx0XHRlbHNlIGdyb3VwLmVsZW1lbnRzID0gcmVnbC5lbGVtZW50cyhvcHRzKVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Ly8gdXBkYXRlIHBvc2l0aW9uIGJ1ZmZlcnNcclxuXHRcdFx0XHRwb3NpdGlvbkJ1ZmZlcih7XHJcblx0XHRcdFx0XHRkYXRhOiBmMzIuZmxvYXQocG9zaXRpb25zKSxcclxuXHRcdFx0XHRcdHVzYWdlOiAnZHluYW1pYydcclxuXHRcdFx0XHR9KVxyXG5cdFx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXIoe1xyXG5cdFx0XHRcdFx0ZGF0YTogZjMyLmZyYWN0KHBvc2l0aW9ucyksXHJcblx0XHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnXHJcblx0XHRcdFx0fSlcclxuXHJcblx0XHRcdFx0Ly8gZXhwYW5kIHNlbGVjdGlvbkJ1ZmZlclxyXG5cdFx0XHRcdHNlbGVjdGlvbkJ1ZmZlcih7XHJcblx0XHRcdFx0XHRkYXRhOiBuZXcgVWludDhBcnJheShjb3VudCksXHJcblx0XHRcdFx0XHR0eXBlOiAndWludDgnLFxyXG5cdFx0XHRcdFx0dXNhZ2U6ICdzdHJlYW0nXHJcblx0XHRcdFx0fSlcclxuXHJcblx0XHRcdFx0cmV0dXJuIHBvc2l0aW9uc1xyXG5cdFx0XHR9XHJcblx0XHR9LCB7XHJcblx0XHRcdC8vIGNyZWF0ZSBtYXJrZXIgaWRzIGNvcnJlc3BvbmRpbmcgdG8ga25vd24gbWFya2VyIHRleHR1cmVzXHJcblx0XHRcdG1hcmtlcjogKG1hcmtlcnMsIGdyb3VwLCBvcHRpb25zKSA9PiB7XHJcblx0XHRcdFx0bGV0IHsgYWN0aXZhdGlvbiB9ID0gZ3JvdXBcclxuXHJcblx0XHRcdFx0Ly8gcmVzZXQgbWFya2VyIGVsZW1lbnRzXHJcblx0XHRcdFx0YWN0aXZhdGlvbi5mb3JFYWNoKGJ1ZmZlciA9PiBidWZmZXIgJiYgYnVmZmVyLmRlc3Ryb3kgJiYgYnVmZmVyLmRlc3Ryb3koKSlcclxuXHRcdFx0XHRhY3RpdmF0aW9uLmxlbmd0aCA9IDBcclxuXHJcblx0XHRcdFx0Ly8gc2luZ2xlIHNkZiBtYXJrZXJcclxuXHRcdFx0XHRpZiAoIW1hcmtlcnMgfHwgdHlwZW9mIG1hcmtlcnNbMF0gPT09ICdudW1iZXInKSB7XHJcblx0XHRcdFx0XHRsZXQgaWQgPSB0aGlzLmFkZE1hcmtlcihtYXJrZXJzKVxyXG5cdFx0XHRcdFx0YWN0aXZhdGlvbltpZF0gPSB0cnVlXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBwZXItcG9pbnQgbWFya2VycyB1c2UgbWFzayBidWZmZXJzIHRvIGVuYWJsZSBtYXJrZXJzIGluIHZlcnQgc2hhZGVyXHJcblx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRsZXQgbWFya2VyTWFza3MgPSBbXVxyXG5cclxuXHRcdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsID0gTWF0aC5taW4obWFya2Vycy5sZW5ndGgsIGdyb3VwLmNvdW50KTsgaSA8IGw7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRsZXQgaWQgPSB0aGlzLmFkZE1hcmtlcihtYXJrZXJzW2ldKVxyXG5cclxuXHRcdFx0XHRcdFx0aWYgKCFtYXJrZXJNYXNrc1tpZF0pIG1hcmtlck1hc2tzW2lkXSA9IG5ldyBVaW50OEFycmF5KGdyb3VwLmNvdW50KVxyXG5cclxuXHRcdFx0XHRcdFx0Ly8gZW5hYmxlIG1hcmtlciBieSBkZWZhdWx0XHJcblx0XHRcdFx0XHRcdG1hcmtlck1hc2tzW2lkXVtpXSA9IDFcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRmb3IgKGxldCBpZCA9IDA7IGlkIDwgbWFya2VyTWFza3MubGVuZ3RoOyBpZCsrKSB7XHJcblx0XHRcdFx0XHRcdGlmICghbWFya2VyTWFza3NbaWRdKSBjb250aW51ZVxyXG5cclxuXHRcdFx0XHRcdFx0bGV0IG9wdHMgPSB7XHJcblx0XHRcdFx0XHRcdFx0ZGF0YTogbWFya2VyTWFza3NbaWRdLFxyXG5cdFx0XHRcdFx0XHRcdHR5cGU6ICd1aW50OCcsXHJcblx0XHRcdFx0XHRcdFx0dXNhZ2U6ICdzdGF0aWMnXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYgKCFhY3RpdmF0aW9uW2lkXSkge1xyXG5cdFx0XHRcdFx0XHRcdGFjdGl2YXRpb25baWRdID0gcmVnbC5idWZmZXIob3B0cylcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRhY3RpdmF0aW9uW2lkXShvcHRzKVxyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0XHRhY3RpdmF0aW9uW2lkXS5kYXRhID0gbWFya2VyTWFza3NbaWRdXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRyZXR1cm4gbWFya2Vyc1xyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0cmFuZ2U6IChyYW5nZSwgZ3JvdXAsIG9wdGlvbnMpID0+IHtcclxuXHRcdFx0XHRsZXQgYm91bmRzID0gZ3JvdXAuYm91bmRzXHJcblxyXG5cdFx0XHRcdC8vIEZJWE1FOiB3aHkgZG8gd2UgbmVlZCB0aGlzP1xyXG5cdFx0XHRcdGlmICghYm91bmRzKSByZXR1cm5cclxuXHRcdFx0XHRpZiAoIXJhbmdlKSByYW5nZSA9IGJvdW5kc1xyXG5cclxuXHRcdFx0XHRncm91cC5zY2FsZSA9IFsxIC8gKHJhbmdlWzJdIC0gcmFuZ2VbMF0pLCAxIC8gKHJhbmdlWzNdIC0gcmFuZ2VbMV0pXVxyXG5cdFx0XHRcdGdyb3VwLnRyYW5zbGF0ZSA9IFstcmFuZ2VbMF0sIC1yYW5nZVsxXV1cclxuXHJcblx0XHRcdFx0Z3JvdXAuc2NhbGVGcmFjdCA9IGYzMi5mcmFjdChncm91cC5zY2FsZSlcclxuXHRcdFx0XHRncm91cC50cmFuc2xhdGVGcmFjdCA9IGYzMi5mcmFjdChncm91cC50cmFuc2xhdGUpXHJcblxyXG5cdFx0XHRcdHJldHVybiByYW5nZVxyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0dmlld3BvcnQ6IHZwID0+IHtcclxuXHRcdFx0XHRsZXQgcmVjdCA9IHBhcnNlUmVjdCh2cCB8fCBbXHJcblx0XHRcdFx0XHRnbC5kcmF3aW5nQnVmZmVyV2lkdGgsXHJcblx0XHRcdFx0XHRnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XHJcblx0XHRcdFx0XSlcclxuXHJcblx0XHRcdFx0Ly8gbm9ybWFsaXplIHZpZXdwb3J0IHRvIHRoZSBjYW52YXMgY29vcmRpbmF0ZXNcclxuXHRcdFx0XHQvLyByZWN0LnkgPSBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0IC0gcmVjdC5oZWlnaHQgLSByZWN0LnlcclxuXHJcblx0XHRcdFx0cmV0dXJuIHJlY3RcclxuXHRcdFx0fVxyXG5cdFx0fV0pXHJcblxyXG5cdFx0Ly8gdXBkYXRlIHNpemUgYnVmZmVyLCBpZiBuZWVkZWRcclxuXHRcdGlmIChoYXNTaXplKSB7XHJcblx0XHRcdGxldCB7IGNvdW50LCBzaXplLCBib3JkZXJTaXplLCBzaXplQnVmZmVyIH0gPSBncm91cFxyXG5cclxuXHRcdFx0bGV0IHNpemVzID0gbmV3IFVpbnQ4QXJyYXkoY291bnQqMilcclxuXHRcdFx0aWYgKHNpemUubGVuZ3RoIHx8IGJvcmRlclNpemUubGVuZ3RoKSB7XHJcblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XHJcblx0XHRcdFx0XHQvLyB3ZSBkb3duc2NhbGUgc2l6ZSB0byBhbGxvdyBmb3IgZnJhY3Rpb25zXHJcblx0XHRcdFx0XHRzaXplc1tpKjJdID0gTWF0aC5yb3VuZCgoc2l6ZVtpXSA9PSBudWxsID8gc2l6ZSA6IHNpemVbaV0pICogMjU1IC8gbWF4U2l6ZSlcclxuXHRcdFx0XHRcdHNpemVzW2kqMiArIDFdID0gTWF0aC5yb3VuZCgoYm9yZGVyU2l6ZVtpXSA9PSBudWxsID8gYm9yZGVyU2l6ZSA6IGJvcmRlclNpemVbaV0pICogMjU1IC8gbWF4U2l6ZSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0c2l6ZUJ1ZmZlcih7XHJcblx0XHRcdFx0ZGF0YTogc2l6ZXMsXHJcblx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJ1xyXG5cdFx0XHR9KVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIHVwZGF0ZSBjb2xvciBidWZmZXIgaWYgbmVlZGVkXHJcblx0XHRpZiAoaGFzQ29sb3IpIHtcclxuXHRcdFx0bGV0IHtjb3VudCwgY29sb3IsIGJvcmRlckNvbG9yLCBjb2xvckJ1ZmZlciB9ID0gZ3JvdXBcclxuXHRcdFx0bGV0IGNvbG9yc1xyXG5cclxuXHRcdFx0Ly8gaWYgdG9vIG1hbnkgY29sb3JzIC0gcHV0IGNvbG9ycyB0byBidWZmZXIgZGlyZWN0bHlcclxuXHRcdFx0aWYgKHRoaXMudG9vTWFueUNvbG9ycykge1xyXG5cdFx0XHRcdGlmIChjb2xvci5sZW5ndGggfHwgYm9yZGVyQ29sb3IubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRjb2xvcnMgPSBuZXcgVWludDhBcnJheShjb3VudCAqIDgpXHJcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcclxuXHRcdFx0XHRcdFx0bGV0IGNvbG9ySWQgPSBjb2xvcltpXVxyXG5cdFx0XHRcdFx0XHRjb2xvcnNbaSo4XSA9IHBhbGV0dGVbY29sb3JJZCo0XVxyXG5cdFx0XHRcdFx0XHRjb2xvcnNbaSo4ICsgMV0gPSBwYWxldHRlW2NvbG9ySWQqNCArIDFdXHJcblx0XHRcdFx0XHRcdGNvbG9yc1tpKjggKyAyXSA9IHBhbGV0dGVbY29sb3JJZCo0ICsgMl1cclxuXHRcdFx0XHRcdFx0Y29sb3JzW2kqOCArIDNdID0gcGFsZXR0ZVtjb2xvcklkKjQgKyAzXVxyXG5cclxuXHRcdFx0XHRcdFx0bGV0IGJvcmRlckNvbG9ySWQgPSBib3JkZXJDb2xvcltpXVxyXG5cdFx0XHRcdFx0XHRjb2xvcnNbaSo4ICsgNF0gPSBwYWxldHRlW2JvcmRlckNvbG9ySWQqNF1cclxuXHRcdFx0XHRcdFx0Y29sb3JzW2kqOCArIDVdID0gcGFsZXR0ZVtib3JkZXJDb2xvcklkKjQgKyAxXVxyXG5cdFx0XHRcdFx0XHRjb2xvcnNbaSo4ICsgNl0gPSBwYWxldHRlW2JvcmRlckNvbG9ySWQqNCArIDJdXHJcblx0XHRcdFx0XHRcdGNvbG9yc1tpKjggKyA3XSA9IHBhbGV0dGVbYm9yZGVyQ29sb3JJZCo0ICsgM11cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIGlmIGxpbWl0ZWQgYW1vdW50IG9mIGNvbG9ycyAtIGtlZXAgcGFsZXR0ZSBjb2xvciBwaWNraW5nXHJcblx0XHRcdC8vIHRoYXQgc2F2ZXMgc2lnbmlmaWNhbnQgbWVtb3J5XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGlmIChjb2xvci5sZW5ndGggfHwgYm9yZGVyQ29sb3IubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHQvLyB3ZSBuZWVkIHNsaWdodCBkYXRhIGluY3JlYXNlIGJ5IDIgZHVlIHRvIHZlYzQgYm9yZGVySWQgaW4gc2hhZGVyXHJcblx0XHRcdFx0XHRjb2xvcnMgPSBuZXcgVWludDhBcnJheShjb3VudCAqIDQgKyAyKVxyXG5cdFx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdC8vIHB1dCBjb2xvciBjb29yZHMgaW4gcGFsZXR0ZSB0ZXh0dXJlXHJcblx0XHRcdFx0XHRcdGlmIChjb2xvcltpXSAhPSBudWxsKSB7XHJcblx0XHRcdFx0XHRcdFx0Y29sb3JzW2kqNF0gPSBjb2xvcltpXSAlIG1heENvbG9yc1xyXG5cdFx0XHRcdFx0XHRcdGNvbG9yc1tpKjQgKyAxXSA9IE1hdGguZmxvb3IoY29sb3JbaV0gLyBtYXhDb2xvcnMpXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYgKGJvcmRlckNvbG9yW2ldICE9IG51bGwpIHtcclxuXHRcdFx0XHRcdFx0XHRjb2xvcnNbaSo0ICsgMl0gPSBib3JkZXJDb2xvcltpXSAlIG1heENvbG9yc1xyXG5cdFx0XHRcdFx0XHRcdGNvbG9yc1tpKjQgKyAzXSA9IE1hdGguZmxvb3IoYm9yZGVyQ29sb3JbaV0gLyBtYXhDb2xvcnMpXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGNvbG9yQnVmZmVyKHtcclxuXHRcdFx0XHRkYXRhOiBjb2xvcnMgfHwgbmV3IFVpbnQ4QXJyYXkoMCksXHJcblx0XHRcdFx0dHlwZTogJ3VpbnQ4JyxcclxuXHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnXHJcblx0XHRcdH0pXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGdyb3VwXHJcblx0fSlcclxufVxyXG5cclxuXHJcbi8vIGdldCAoYW5kIGNyZWF0ZSkgbWFya2VyIHRleHR1cmUgaWRcclxuU2NhdHRlci5wcm90b3R5cGUuYWRkTWFya2VyID0gZnVuY3Rpb24gKHNkZikge1xyXG5cdGxldCB7IG1hcmtlclRleHR1cmVzLCByZWdsLCBtYXJrZXJDYWNoZSB9ID0gdGhpc1xyXG5cclxuXHRsZXQgcG9zID0gc2RmID09IG51bGwgPyAwIDogbWFya2VyQ2FjaGUuaW5kZXhPZihzZGYpXHJcblxyXG5cdGlmIChwb3MgPj0gMCkgcmV0dXJuIHBvc1xyXG5cclxuXHQvLyBjb252ZXJ0IHNkZiB0byAwLi4yNTUgcmFuZ2VcclxuXHRsZXQgZGlzdEFyclxyXG5cdGlmIChzZGYgaW5zdGFuY2VvZiBVaW50OEFycmF5IHx8IHNkZiBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KSB7XHJcblx0XHRkaXN0QXJyID0gc2RmXHJcblx0fVxyXG5cdGVsc2Uge1xyXG5cdFx0ZGlzdEFyciA9IG5ldyBVaW50OEFycmF5KHNkZi5sZW5ndGgpXHJcblx0XHRmb3IgKGxldCBpID0gMCwgbCA9IHNkZi5sZW5ndGg7IGkgPCBsOyBpKyspIHtcclxuXHRcdFx0ZGlzdEFycltpXSA9IHNkZltpXSAqIDI1NVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0bGV0IHJhZGl1cyA9IE1hdGguZmxvb3IoTWF0aC5zcXJ0KGRpc3RBcnIubGVuZ3RoKSlcclxuXHJcblx0cG9zID0gbWFya2VyVGV4dHVyZXMubGVuZ3RoXHJcblxyXG5cdG1hcmtlckNhY2hlLnB1c2goc2RmKVxyXG5cdG1hcmtlclRleHR1cmVzLnB1c2gocmVnbC50ZXh0dXJlKHtcclxuXHRcdGNoYW5uZWxzOiAxLFxyXG5cdFx0ZGF0YTogZGlzdEFycixcclxuXHRcdHJhZGl1czogcmFkaXVzLFxyXG5cdFx0bWFnOiAnbGluZWFyJyxcclxuXHRcdG1pbjogJ2xpbmVhcidcclxuXHR9KSlcclxuXHJcblx0cmV0dXJuIHBvc1xyXG59XHJcblxyXG4vLyByZWdpc3RlciBjb2xvciB0byBwYWxldHRlLCByZXR1cm4gaXQncyBpbmRleCBvciBsaXN0IG9mIGluZGV4ZXNcclxuU2NhdHRlci5wcm90b3R5cGUudXBkYXRlQ29sb3IgPSBmdW5jdGlvbiAoY29sb3JzKSB7XHJcblx0bGV0IHsgcGFsZXR0ZUlkcywgcGFsZXR0ZSwgbWF4Q29sb3JzIH0gPSB0aGlzXHJcblxyXG5cdGlmICghQXJyYXkuaXNBcnJheShjb2xvcnMpKSB7XHJcblx0XHRjb2xvcnMgPSBbY29sb3JzXVxyXG5cdH1cclxuXHJcblx0bGV0IGlkeCA9IFtdXHJcblxyXG5cdC8vIGlmIGNvbG9yIGdyb3VwcyAtIGZsYXR0ZW4gdGhlbVxyXG5cdGlmICh0eXBlb2YgY29sb3JzWzBdID09PSAnbnVtYmVyJykge1xyXG5cdFx0bGV0IGdyb3VwZWQgPSBbXVxyXG5cclxuXHRcdGlmIChBcnJheS5pc0FycmF5KGNvbG9ycykpIHtcclxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyBpKz00KSB7XHJcblx0XHRcdFx0Z3JvdXBlZC5wdXNoKGNvbG9ycy5zbGljZShpLCBpKzQpKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyBpKz00KSB7XHJcblx0XHRcdFx0Z3JvdXBlZC5wdXNoKGNvbG9ycy5zdWJhcnJheShpLCBpKzQpKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Y29sb3JzID0gZ3JvdXBlZFxyXG5cdH1cclxuXHJcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdGxldCBjb2xvciA9IGNvbG9yc1tpXVxyXG5cclxuXHRcdGNvbG9yID0gcmdiYShjb2xvciwgJ3VpbnQ4JylcclxuXHJcblx0XHRsZXQgaWQgPSBjb2xvcklkKGNvbG9yLCBmYWxzZSlcclxuXHJcblx0XHQvLyBpZiBuZXcgY29sb3IgLSBzYXZlIGl0XHJcblx0XHRpZiAocGFsZXR0ZUlkc1tpZF0gPT0gbnVsbCkge1xyXG5cdFx0XHRsZXQgcG9zID0gcGFsZXR0ZS5sZW5ndGhcclxuXHRcdFx0cGFsZXR0ZUlkc1tpZF0gPSBNYXRoLmZsb29yKHBvcyAvIDQpXHJcblx0XHRcdHBhbGV0dGVbcG9zXSA9IGNvbG9yWzBdXHJcblx0XHRcdHBhbGV0dGVbcG9zKzFdID0gY29sb3JbMV1cclxuXHRcdFx0cGFsZXR0ZVtwb3MrMl0gPSBjb2xvclsyXVxyXG5cdFx0XHRwYWxldHRlW3BvcyszXSA9IGNvbG9yWzNdXHJcblx0XHR9XHJcblxyXG5cdFx0aWR4W2ldID0gcGFsZXR0ZUlkc1tpZF1cclxuXHR9XHJcblxyXG5cdC8vIGRldGVjdCBpZiB0b28gbWFueSBjb2xvcnMgaW4gcGFsZXR0ZVxyXG5cdGlmICghdGhpcy50b29NYW55Q29sb3JzICYmIHBhbGV0dGUubGVuZ3RoID4gbWF4Q29sb3JzICogbWF4Q29sb3JzICogNCkgdGhpcy50b29NYW55Q29sb3JzID0gdHJ1ZVxyXG5cclxuXHQvLyBsaW1pdCBtYXggY29sb3JcclxuXHR0aGlzLnVwZGF0ZVBhbGV0dGUocGFsZXR0ZSlcclxuXHJcblx0Ly8ga2VlcCBzdGF0aWMgaW5kZXggZm9yIHNpbmdsZS1jb2xvciBwcm9wZXJ0eVxyXG5cdHJldHVybiBpZHgubGVuZ3RoID09PSAxID8gaWR4WzBdIDogaWR4XHJcbn1cclxuXHJcblNjYXR0ZXIucHJvdG90eXBlLnVwZGF0ZVBhbGV0dGUgPSBmdW5jdGlvbiAocGFsZXR0ZSkge1xyXG5cdGlmICh0aGlzLnRvb01hbnlDb2xvcnMpIHJldHVyblxyXG5cclxuXHRsZXQgeyBtYXhDb2xvcnMsIHBhbGV0dGVUZXh0dXJlIH0gPSB0aGlzXHJcblxyXG5cdGxldCByZXF1aXJlZEhlaWdodCA9IE1hdGguY2VpbChwYWxldHRlLmxlbmd0aCAqIC4yNSAvIG1heENvbG9ycylcclxuXHJcblx0Ly8gcGFkIGRhdGFcclxuXHRpZiAocmVxdWlyZWRIZWlnaHQgPiAxKSB7XHJcblx0XHRwYWxldHRlID0gcGFsZXR0ZS5zbGljZSgpXHJcblx0XHRmb3IgKGxldCBpID0gKHBhbGV0dGUubGVuZ3RoICogLjI1KSAlIG1heENvbG9yczsgaSA8IHJlcXVpcmVkSGVpZ2h0ICogbWF4Q29sb3JzOyBpKyspIHtcclxuXHRcdFx0cGFsZXR0ZS5wdXNoKDAsIDAsIDAsIDApXHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBlbnN1cmUgaGVpZ2h0XHJcblx0aWYgKHBhbGV0dGVUZXh0dXJlLmhlaWdodCA8IHJlcXVpcmVkSGVpZ2h0KSB7XHJcblx0XHRwYWxldHRlVGV4dHVyZS5yZXNpemUobWF4Q29sb3JzLCByZXF1aXJlZEhlaWdodClcclxuXHR9XHJcblxyXG5cdC8vIHVwZGF0ZSBmdWxsIGRhdGFcclxuXHRwYWxldHRlVGV4dHVyZS5zdWJpbWFnZSh7XHJcblx0XHR3aWR0aDogTWF0aC5taW4ocGFsZXR0ZS5sZW5ndGggKiAuMjUsIG1heENvbG9ycyksXHJcblx0XHRoZWlnaHQ6IHJlcXVpcmVkSGVpZ2h0LFxyXG5cdFx0ZGF0YTogcGFsZXR0ZVxyXG5cdH0sIDAsIDApXHJcbn1cclxuXHJcbi8vIHJlbW92ZSB1bnVzZWQgc3R1ZmZcclxuU2NhdHRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcclxuXHR0aGlzLmdyb3Vwcy5mb3JFYWNoKGdyb3VwID0+IHtcclxuXHRcdGdyb3VwLnNpemVCdWZmZXIuZGVzdHJveSgpXHJcblx0XHRncm91cC5wb3NpdGlvbkJ1ZmZlci5kZXN0cm95KClcclxuXHRcdGdyb3VwLnBvc2l0aW9uRnJhY3RCdWZmZXIuZGVzdHJveSgpXHJcblx0XHRncm91cC5jb2xvckJ1ZmZlci5kZXN0cm95KClcclxuXHRcdGdyb3VwLmFjdGl2YXRpb24uZm9yRWFjaChiID0+IGIgJiYgYi5kZXN0cm95ICYmIGIuZGVzdHJveSgpKVxyXG5cdFx0Z3JvdXAuc2VsZWN0aW9uQnVmZmVyLmRlc3Ryb3koKVxyXG5cclxuXHRcdGlmIChncm91cC5lbGVtZW50cykgZ3JvdXAuZWxlbWVudHMuZGVzdHJveSgpXHJcblx0fSlcclxuXHR0aGlzLmdyb3Vwcy5sZW5ndGggPSAwXHJcblxyXG5cdHRoaXMucGFsZXR0ZVRleHR1cmUuZGVzdHJveSgpXHJcblxyXG5cdHRoaXMubWFya2VyVGV4dHVyZXMuZm9yRWFjaCh0eHQgPT4gdHh0ICYmIHR4dC5kZXN0cm95ICYmIHR4dC5kZXN0cm95KCkpXHJcblxyXG5cdHJldHVybiB0aGlzXHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnXG5cblxuY29uc3QgY3JlYXRlU2NhdHRlciA9IHJlcXVpcmUoJ3JlZ2wtc2NhdHRlcjJkL3NjYXR0ZXInKVxuY29uc3QgcGljayA9IHJlcXVpcmUoJ3BpY2stYnktYWxpYXMnKVxuY29uc3QgZ2V0Qm91bmRzID0gcmVxdWlyZSgnYXJyYXktYm91bmRzJylcbmNvbnN0IHJhZiA9IHJlcXVpcmUoJ3JhZicpXG5jb25zdCBhcnJSYW5nZSA9IHJlcXVpcmUoJ2FycmF5LXJhbmdlJylcbmNvbnN0IHJlY3QgPSByZXF1aXJlKCdwYXJzZS1yZWN0JylcbmNvbnN0IGZsYXR0ZW4gPSByZXF1aXJlKCdmbGF0dGVuLXZlcnRleC1kYXRhJylcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFNQTE9NXG5cblxuLy8gQGNvbnN0cnVjdG9yXG5mdW5jdGlvbiBTUExPTSAocmVnbCwgb3B0aW9ucykge1xuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgU1BMT00pKSByZXR1cm4gbmV3IFNQTE9NKHJlZ2wsIG9wdGlvbnMpXG5cblx0Ly8gcmVuZGVyIHBhc3Nlc1xuXHR0aGlzLnRyYWNlcyA9IFtdXG5cblx0Ly8gcGFzc2VzIGZvciBzY2F0dGVyLCBjb21iaW5lZCBhY3Jvc3MgdHJhY2VzXG5cdHRoaXMucGFzc2VzID0ge31cblxuXHR0aGlzLnJlZ2wgPSByZWdsXG5cblx0Ly8gbWFpbiBzY2F0dGVyIGRyYXdpbmcgaW5zdGFuY2Vcblx0dGhpcy5zY2F0dGVyID0gY3JlYXRlU2NhdHRlcihyZWdsKVxuXG5cdHRoaXMuY2FudmFzID0gdGhpcy5zY2F0dGVyLmNhbnZhc1xufVxuXG5cbi8vIHVwZGF0ZSAmIGRyYXcgcGFzc2VzIG9uY2UgcGVyIGZyYW1lXG5TUExPTS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0aWYgKGFyZ3MubGVuZ3RoKSB7XG5cdFx0dGhpcy51cGRhdGUoLi4uYXJncylcblx0fVxuXG5cdGlmICh0aGlzLnJlZ2wuYXR0cmlidXRlcy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXIpIHJldHVybiB0aGlzLmRyYXcoKVxuXG5cdC8vIG1ha2Ugc3VyZSBkcmF3IGlzIG5vdCBjYWxsZWQgbW9yZSBvZnRlbiB0aGFuIG9uY2UgYSBmcmFtZVxuXHRpZiAodGhpcy5kaXJ0eSkge1xuXHRcdGlmICh0aGlzLnBsYW5uZWQgPT0gbnVsbCkge1xuXHRcdFx0dGhpcy5wbGFubmVkID0gcmFmKCgpID0+IHtcblx0XHRcdFx0dGhpcy5kcmF3KClcblx0XHRcdFx0dGhpcy5kaXJ0eSA9IHRydWVcblx0XHRcdFx0dGhpcy5wbGFubmVkID0gbnVsbFxuXHRcdFx0fSlcblx0XHR9XG5cdH1cblx0ZWxzZSB7XG5cdFx0dGhpcy5kcmF3KClcblx0XHR0aGlzLmRpcnR5ID0gdHJ1ZVxuXHRcdHJhZigoKSA9PiB7XG5cdFx0XHR0aGlzLmRpcnR5ID0gZmFsc2Vcblx0XHR9KVxuXHR9XG5cblx0cmV0dXJuIHRoaXNcbn1cblxuXG4vLyB1cGRhdGUgcGFzc2VzXG5TUExPTS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0aWYgKCFhcmdzLmxlbmd0aCkgcmV0dXJuXG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0dGhpcy51cGRhdGVJdGVtKGksIGFyZ3NbaV0pXG5cdH1cblxuXHQvLyByZW1vdmUgbnVsbGVkIHBhc3Nlc1xuXHR0aGlzLnRyYWNlcyA9IHRoaXMudHJhY2VzLmZpbHRlcihCb29sZWFuKVxuXG5cdC8vIEZJWE1FOiB1cGRhdGUgcGFzc2VzIGluZGVwZW5kZW50bHlcblx0bGV0IHBhc3NlcyA9IFtdXG5cdGxldCBvZmZzZXQgPSAwXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy50cmFjZXMubGVuZ3RoOyBpKyspIHtcblx0XHRsZXQgdHJhY2UgPSB0aGlzLnRyYWNlc1tpXVxuXHRcdGxldCB0cmFjZVBhc3NlcyA9IHRoaXMudHJhY2VzW2ldLnBhc3Nlc1xuXHRcdGZvciAobGV0IGogPSAwOyBqIDwgdHJhY2VQYXNzZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdHBhc3Nlcy5wdXNoKHRoaXMucGFzc2VzW3RyYWNlUGFzc2VzW2pdXSlcblx0XHR9XG5cdFx0Ly8gc2F2ZSBvZmZzZXQgb2YgcGFzc2VzXG5cdFx0dHJhY2UucGFzc09mZnNldCA9IG9mZnNldFxuXHRcdG9mZnNldCArPSB0cmFjZS5wYXNzZXMubGVuZ3RoXG5cdH1cblxuXHR0aGlzLnNjYXR0ZXIudXBkYXRlKC4uLnBhc3NlcylcblxuXHRyZXR1cm4gdGhpc1xufVxuXG5cbi8vIHVwZGF0ZSB0cmFjZSBieSBpbmRleCwgbm90IHN1cHBvc2VkIHRvIGJlIGNhbGxlZCBkaXJlY3RseVxuU1BMT00ucHJvdG90eXBlLnVwZGF0ZUl0ZW0gPSBmdW5jdGlvbiAoaSwgb3B0aW9ucykge1xuXHRsZXQgeyByZWdsIH0gPSB0aGlzXG5cblx0Ly8gcmVtb3ZlIHBhc3MgaWYgbnVsbFxuXHRpZiAob3B0aW9ucyA9PT0gbnVsbCkge1xuXHRcdHRoaXMudHJhY2VzW2ldID0gbnVsbFxuXHRcdHJldHVybiB0aGlzXG5cdH1cblxuXHRpZiAoIW9wdGlvbnMpIHJldHVybiB0aGlzXG5cblx0bGV0IG8gPSBwaWNrKG9wdGlvbnMsIHtcblx0XHRkYXRhOiAnZGF0YSBpdGVtcyBjb2x1bW5zIHJvd3MgdmFsdWVzIGRpbWVuc2lvbnMgc2FtcGxlcyB4Jyxcblx0XHRzbmFwOiAnc25hcCBjbHVzdGVyJyxcblx0XHRzaXplOiAnc2l6ZXMgc2l6ZSByYWRpdXMnLFxuXHRcdGNvbG9yOiAnY29sb3JzIGNvbG9yIGZpbGwgZmlsbC1jb2xvciBmaWxsQ29sb3InLFxuXHRcdG9wYWNpdHk6ICdvcGFjaXR5IGFscGhhIHRyYW5zcGFyZW5jeSBvcGFxdWUnLFxuXHRcdGJvcmRlclNpemU6ICdib3JkZXJTaXplcyBib3JkZXJTaXplIGJvcmRlci1zaXplIGJvcmRlcnNpemUgYm9yZGVyV2lkdGggYm9yZGVyV2lkdGhzIGJvcmRlci13aWR0aCBib3JkZXJ3aWR0aCBzdHJva2Utd2lkdGggc3Ryb2tlV2lkdGggc3Ryb2tld2lkdGggb3V0bGluZScsXG5cdFx0Ym9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcnMgYm9yZGVyQ29sb3IgYm9yZGVyY29sb3Igc3Ryb2tlIHN0cm9rZS1jb2xvciBzdHJva2VDb2xvcicsXG5cdFx0bWFya2VyOiAnbWFya2VycyBtYXJrZXIgc2hhcGUnLFxuXHRcdHJhbmdlOiAncmFuZ2UgcmFuZ2VzIGRhdGFib3ggZGF0YUJveCcsXG5cdFx0dmlld3BvcnQ6ICd2aWV3cG9ydCB2aWV3Qm94IHZpZXdib3gnLFxuXHRcdGRvbWFpbjogJ2RvbWFpbiBkb21haW5zIGFyZWEgYXJlYXMnLFxuXHRcdHBhZGRpbmc6ICdwYWQgcGFkZGluZyBwYWRkaW5ncyBwYWRzIG1hcmdpbiBtYXJnaW5zJyxcblx0XHR0cmFuc3Bvc2U6ICd0cmFuc3Bvc2UgdHJhbnNwb3NlZCcsXG5cdFx0ZGlhZ29uYWw6ICdkaWFnb25hbCBkaWFnIHNob3dEaWFnb25hbCcsXG5cdFx0dXBwZXI6ICd1cHBlciB1cCB0b3AgdXBwZXJoYWxmIHVwcGVySGFsZiBzaG93dXBwZXJoYWxmIHNob3dVcHBlciBzaG93VXBwZXJIYWxmJyxcblx0XHRsb3dlcjogJ2xvd2VyIGxvdyBib3R0b20gbG93ZXJoYWxmIGxvd2VySGFsZiBzaG93bG93ZXJoYWxmIHNob3dMb3dlckhhbGYgc2hvd0xvd2VyJ1xuXHR9KVxuXG5cdC8vIHdlIHByb3ZpZGUgcmVnbCBidWZmZXIgcGVyLXRyYWNlLCBzaW5jZSB0cmFjZSBkYXRhIGNhbiBiZSBjaGFuZ2VkXG5cdGxldCB0cmFjZSA9ICh0aGlzLnRyYWNlc1tpXSB8fCAodGhpcy50cmFjZXNbaV0gPSB7XG5cdFx0aWQ6IGksXG5cdFx0YnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdFx0dHlwZTogJ2Zsb2F0Jyxcblx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHR9KSxcblx0XHRjb2xvcjogJ2JsYWNrJyxcblx0XHRtYXJrZXI6IG51bGwsXG5cdFx0c2l6ZTogMTIsXG5cdFx0Ym9yZGVyQ29sb3I6ICd0cmFuc3BhcmVudCcsXG5cdFx0Ym9yZGVyU2l6ZTogMSxcblx0XHR2aWV3cG9ydDogIHJlY3QoW3JlZ2wuX2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgcmVnbC5fZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0pLFxuXHRcdHBhZGRpbmc6IFswLCAwLCAwLCAwXSxcblx0XHRvcGFjaXR5OiAxLFxuXHRcdGRpYWdvbmFsOiB0cnVlLFxuXHRcdHVwcGVyOiB0cnVlLFxuXHRcdGxvd2VyOiB0cnVlXG5cdH0pKVxuXG5cblx0Ly8gc2F2ZSBzdHlsZXNcblx0aWYgKG8uY29sb3IgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmNvbG9yID0gby5jb2xvclxuXHR9XG5cdGlmIChvLnNpemUgIT0gbnVsbCkge1xuXHRcdHRyYWNlLnNpemUgPSBvLnNpemVcblx0fVxuXHRpZiAoby5tYXJrZXIgIT0gbnVsbCkge1xuXHRcdHRyYWNlLm1hcmtlciA9IG8ubWFya2VyXG5cdH1cblx0aWYgKG8uYm9yZGVyQ29sb3IgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmJvcmRlckNvbG9yID0gby5ib3JkZXJDb2xvclxuXHR9XG5cdGlmIChvLmJvcmRlclNpemUgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmJvcmRlclNpemUgPSBvLmJvcmRlclNpemVcblx0fVxuXHRpZiAoby5vcGFjaXR5ICE9IG51bGwpIHtcblx0XHR0cmFjZS5vcGFjaXR5ID0gby5vcGFjaXR5XG5cdH1cblx0aWYgKG8udmlld3BvcnQpIHtcblx0XHR0cmFjZS52aWV3cG9ydCA9IHJlY3Qoby52aWV3cG9ydClcblx0fVxuXHRpZiAoby5kaWFnb25hbCAhPSBudWxsKSB0cmFjZS5kaWFnb25hbCA9IG8uZGlhZ29uYWxcblx0aWYgKG8udXBwZXIgIT0gbnVsbCkgdHJhY2UudXBwZXIgPSBvLnVwcGVyXG5cdGlmIChvLmxvd2VyICE9IG51bGwpIHRyYWNlLmxvd2VyID0gby5sb3dlclxuXG5cdC8vIHB1dCBmbGF0dGVuZWQgZGF0YSBpbnRvIGJ1ZmZlclxuXHRpZiAoby5kYXRhKSB7XG5cdFx0dHJhY2UuYnVmZmVyKGZsYXR0ZW4oby5kYXRhKSlcblx0XHR0cmFjZS5jb2x1bW5zID0gby5kYXRhLmxlbmd0aFxuXHRcdHRyYWNlLmNvdW50ID0gby5kYXRhWzBdLmxlbmd0aFxuXG5cdFx0Ly8gZGV0ZWN0IGJvdW5kcyBwZXItY29sdW1uXG5cdFx0dHJhY2UuYm91bmRzID0gW11cblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdHJhY2UuY29sdW1uczsgaSsrKSB7XG5cdFx0XHR0cmFjZS5ib3VuZHNbaV0gPSBnZXRCb3VuZHMoby5kYXRhW2ldLCAxKVxuXHRcdH1cblx0fVxuXG5cdC8vIGFkZCBwcm9wZXIgcmFuZ2UgdXBkYXRpbmcgbWFya2Vyc1xuXHRsZXQgbXVsdGlyYW5nZVxuXHRpZiAoby5yYW5nZSkge1xuXHRcdHRyYWNlLnJhbmdlID0gby5yYW5nZVxuXHRcdG11bHRpcmFuZ2UgPSB0cmFjZS5yYW5nZSAmJiB0eXBlb2YgdHJhY2UucmFuZ2VbMF0gIT09ICdudW1iZXInXG5cdH1cblxuXHRpZiAoby5kb21haW4pIHtcblx0XHR0cmFjZS5kb21haW4gPSBvLmRvbWFpblxuXHR9XG5cdGxldCBtdWx0aXBhZGRpbmcgPSBmYWxzZVxuXHRpZiAoby5wYWRkaW5nICE9IG51bGwpIHtcblx0XHQvLyBtdWx0aXBsZSBwYWRkaW5nc1xuXHRcdGlmIChBcnJheS5pc0FycmF5KG8ucGFkZGluZykgJiYgby5wYWRkaW5nLmxlbmd0aCA9PT0gdHJhY2UuY29sdW1ucyAmJiB0eXBlb2Ygby5wYWRkaW5nW28ucGFkZGluZy5sZW5ndGggLSAxXSA9PT0gJ251bWJlcicpIHtcblx0XHRcdHRyYWNlLnBhZGRpbmcgPSBvLnBhZGRpbmcubWFwKGdldFBhZClcblx0XHRcdG11bHRpcGFkZGluZyA9IHRydWVcblx0XHR9XG5cdFx0Ly8gc2luZ2xlIHBhZGRpbmdcblx0XHRlbHNlIHtcblx0XHRcdHRyYWNlLnBhZGRpbmcgPSBnZXRQYWQoby5wYWRkaW5nKVxuXHRcdH1cblx0fVxuXG5cdC8vIGNyZWF0ZSBwYXNzZXNcblx0bGV0IG0gPSB0cmFjZS5jb2x1bW5zXG5cdGxldCBuID0gdHJhY2UuY291bnRcblxuXHRsZXQgdyA9IHRyYWNlLnZpZXdwb3J0LndpZHRoXG5cdGxldCBoID0gdHJhY2Uudmlld3BvcnQuaGVpZ2h0XG5cdGxldCBsZWZ0ID0gdHJhY2Uudmlld3BvcnQueFxuXHRsZXQgdG9wID0gdHJhY2Uudmlld3BvcnQueVxuXHRsZXQgaXcgPSB3IC8gbVxuXHRsZXQgaWggPSBoIC8gbVxuXG5cdHRyYWNlLnBhc3NlcyA9IFtdXG5cblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBtOyBpKyspIHtcblx0XHRmb3IgKGxldCBqID0gMDsgaiA8IG07IGorKykge1xuXHRcdFx0aWYgKCF0cmFjZS5kaWFnb25hbCAmJiBqID09PSBpKSBjb250aW51ZVxuXHRcdFx0aWYgKCF0cmFjZS51cHBlciAmJiBpID4gaikgY29udGludWVcblx0XHRcdGlmICghdHJhY2UubG93ZXIgJiYgaSA8IGopIGNvbnRpbnVlXG5cblx0XHRcdGxldCBrZXkgPSBwYXNzSWQodHJhY2UuaWQsIGksIGopXG5cblx0XHRcdGxldCBwYXNzID0gdGhpcy5wYXNzZXNba2V5XSB8fCAodGhpcy5wYXNzZXNba2V5XSA9IHt9KVxuXG5cdFx0XHRpZiAoby5kYXRhKSB7XG5cdFx0XHRcdGlmIChvLnRyYW5zcG9zZSkge1xuXHRcdFx0XHRcdHBhc3MucG9zaXRpb25zID0ge1xuXHRcdFx0XHRcdFx0eDoge2J1ZmZlcjogdHJhY2UuYnVmZmVyLCBvZmZzZXQ6IGosIGNvdW50OiBuLCBzdHJpZGU6IG19LFxuXHRcdFx0XHRcdFx0eToge2J1ZmZlcjogdHJhY2UuYnVmZmVyLCBvZmZzZXQ6IGksIGNvdW50OiBuLCBzdHJpZGU6IG19XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHBhc3MucG9zaXRpb25zID0ge1xuXHRcdFx0XHRcdFx0eDoge2J1ZmZlcjogdHJhY2UuYnVmZmVyLCBvZmZzZXQ6IGogKiBuLCBjb3VudDogbn0sXG5cdFx0XHRcdFx0XHR5OiB7YnVmZmVyOiB0cmFjZS5idWZmZXIsIG9mZnNldDogaSAqIG4sIGNvdW50OiBufVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHBhc3MuYm91bmRzID0gZ2V0Qm94KHRyYWNlLmJvdW5kcywgaSwgailcblx0XHRcdH1cblxuXHRcdFx0aWYgKG8uZG9tYWluIHx8IG8udmlld3BvcnQgfHwgby5kYXRhKSB7XG5cdFx0XHRcdGxldCBwYWQgPSBtdWx0aXBhZGRpbmcgPyBnZXRCb3godHJhY2UucGFkZGluZywgaSwgaikgOiB0cmFjZS5wYWRkaW5nXG5cdFx0XHRcdGlmICh0cmFjZS5kb21haW4pIHtcblx0XHRcdFx0XHRsZXQgW2xveCwgbG95LCBoaXgsIGhpeV0gPSBnZXRCb3godHJhY2UuZG9tYWluLCBpLCBqKVxuXG5cdFx0XHRcdFx0cGFzcy52aWV3cG9ydCA9IFtcblx0XHRcdFx0XHRcdGxlZnQgKyBsb3ggKiB3ICsgcGFkWzBdLFxuXHRcdFx0XHRcdFx0dG9wICsgbG95ICogaCArIHBhZFsxXSxcblx0XHRcdFx0XHRcdGxlZnQgKyBoaXggKiB3IC0gcGFkWzJdLFxuXHRcdFx0XHRcdFx0dG9wICsgaGl5ICogaCAtIHBhZFszXVxuXHRcdFx0XHRcdF1cblx0XHRcdFx0fVxuXHRcdFx0XHQvLyBjb25zaWRlciBhdXRvLWRvbWFpbiBlcXVpcGFydGlhbFxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRwYXNzLnZpZXdwb3J0ID0gW1xuXHRcdFx0XHRcdFx0bGVmdCArIGogKiBpdyArIGl3ICogcGFkWzBdLFxuXHRcdFx0XHRcdFx0dG9wICsgaSAqIGloICsgaWggKiBwYWRbMV0sXG5cdFx0XHRcdFx0XHRsZWZ0ICsgKGogKyAxKSAqIGl3IC0gaXcgKiBwYWRbMl0sXG5cdFx0XHRcdFx0XHR0b3AgKyAoaSArIDEpICogaWggLSBpaCAqIHBhZFszXVxuXHRcdFx0XHRcdF1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoby5jb2xvcikgcGFzcy5jb2xvciA9IHRyYWNlLmNvbG9yXG5cdFx0XHRpZiAoby5zaXplKSBwYXNzLnNpemUgPSB0cmFjZS5zaXplXG5cdFx0XHRpZiAoby5tYXJrZXIpIHBhc3MubWFya2VyID0gdHJhY2UubWFya2VyXG5cdFx0XHRpZiAoby5ib3JkZXJTaXplKSBwYXNzLmJvcmRlclNpemUgPSB0cmFjZS5ib3JkZXJTaXplXG5cdFx0XHRpZiAoby5ib3JkZXJDb2xvcikgcGFzcy5ib3JkZXJDb2xvciA9IHRyYWNlLmJvcmRlckNvbG9yXG5cdFx0XHRpZiAoby5vcGFjaXR5KSBwYXNzLm9wYWNpdHkgPSB0cmFjZS5vcGFjaXR5XG5cblx0XHRcdGlmIChvLnJhbmdlKSB7XG5cdFx0XHRcdHBhc3MucmFuZ2UgPSBtdWx0aXJhbmdlID8gZ2V0Qm94KHRyYWNlLnJhbmdlLCBpLCBqKSA6IHRyYWNlLnJhbmdlIHx8IHBhc3MuYm91bmRzXG5cdFx0XHR9XG5cblx0XHRcdHRyYWNlLnBhc3Nlcy5wdXNoKGtleSlcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdGhpc1xufVxuXG5cbi8vIGRyYXcgYWxsIG9yIHBhc3NlZCBwYXNzZXNcblNQTE9NLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0aWYgKCFhcmdzLmxlbmd0aCkge1xuXHRcdHRoaXMuc2NhdHRlci5kcmF3KClcblx0fVxuXHRlbHNlIHtcblx0XHRsZXQgaWR4ID0gW11cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdC8vIGRyYXcoMCwgMiwgNSkgLSBkcmF3IHRyYWNlc1xuXHRcdFx0aWYgKHR5cGVvZiBhcmdzW2ldID09PSAnbnVtYmVyJyApIHtcblx0XHRcdFx0bGV0IHsgcGFzc2VzLCBwYXNzT2Zmc2V0IH0gPSB0aGlzLnRyYWNlc1thcmdzW2ldXVxuXHRcdFx0XHRpZHgucHVzaCguLi5hcnJSYW5nZShwYXNzT2Zmc2V0LCBwYXNzT2Zmc2V0ICsgcGFzc2VzLmxlbmd0aCkpXG5cdFx0XHR9XG5cdFx0XHQvLyBkcmF3KFswLCAxLCAyIC4uLl0sIFszLCA0LCA1XSkgLSBkcmF3IHBvaW50c1xuXHRcdFx0ZWxzZSBpZiAoYXJnc1tpXS5sZW5ndGgpIHtcblx0XHRcdFx0bGV0IGVscyA9IGFyZ3NbaV1cblx0XHRcdFx0bGV0IHsgcGFzc2VzLCBwYXNzT2Zmc2V0IH0gPSB0aGlzLnRyYWNlc1tpXVxuXHRcdFx0XHRwYXNzZXMgPSBwYXNzZXMubWFwKChwYXNzSWQsIGkpID0+IHtcblx0XHRcdFx0XHRpZHhbcGFzc09mZnNldCArIGldID0gZWxzXG5cdFx0XHRcdH0pXG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuc2NhdHRlci5kcmF3KC4uLmlkeClcblx0fVxuXG5cdHJldHVybiB0aGlzXG59XG5cblxuLy8gZGlzcG9zZSByZXNvdXJjZXNcblNQTE9NLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuXHR0aGlzLnRyYWNlcy5mb3JFYWNoKHRyYWNlID0+IHtcblx0XHRpZiAodHJhY2UuYnVmZmVyICYmIHRyYWNlLmJ1ZmZlci5kZXN0cm95KSB0cmFjZS5idWZmZXIuZGVzdHJveSgpXG5cdH0pXG5cdHRoaXMudHJhY2VzID0gbnVsbFxuXHR0aGlzLnBhc3NlcyA9IG51bGxcblxuXHR0aGlzLnNjYXR0ZXIuZGVzdHJveSgpXG5cblx0cmV0dXJuIHRoaXNcbn1cblxuXG4vLyByZXR1cm4gcGFzcyBjb3JyZXNwb25kaW5nIHRvIHRyYWNlIGktIGotIHNxdWFyZVxuZnVuY3Rpb24gcGFzc0lkICh0cmFjZSwgaSwgaikge1xuXHRsZXQgaWQgPSAodHJhY2UuaWQgIT0gbnVsbCA/IHRyYWNlLmlkIDogdHJhY2UpXG5cdGxldCBuID0gaVxuXHRsZXQgbSA9IGpcblx0bGV0IGtleSA9IGlkIDw8IDE2IHwgKG4gJiAweGZmKSA8PCA4IHwgbSAmIDB4ZmZcblxuXHRyZXR1cm4ga2V5XG59XG5cblxuLy8gcmV0dXJuIGJvdW5kaW5nIGJveCBjb3JyZXNwb25kaW5nIHRvIGEgcGFzc1xuZnVuY3Rpb24gZ2V0Qm94IChpdGVtcywgaSwgaikge1xuXHRsZXQgaWxveCwgaWxveSwgaWhpeCwgaWhpeSwgamxveCwgamxveSwgamhpeCwgamhpeVxuXHRsZXQgaWl0ZW0gPSBpdGVtc1tpXSwgaml0ZW0gPSBpdGVtc1tqXVxuXG5cdGlmIChpaXRlbS5sZW5ndGggPiAyKSB7XG5cdFx0aWxveCA9IGlpdGVtWzBdXG5cdFx0aWhpeCA9IGlpdGVtWzJdXG5cdFx0aWxveSA9IGlpdGVtWzFdXG5cdFx0aWhpeSA9IGlpdGVtWzNdXG5cdH1cblx0ZWxzZSBpZiAoaWl0ZW0ubGVuZ3RoKSB7XG5cdFx0aWxveCA9IGlsb3kgPSBpaXRlbVswXVxuXHRcdGloaXggPSBpaGl5ID0gaWl0ZW1bMV1cblx0fVxuXHRlbHNlIHtcblx0XHRpbG94ID0gaWl0ZW0ueFxuXHRcdGlsb3kgPSBpaXRlbS55XG5cdFx0aWhpeCA9IGlpdGVtLnggKyBpaXRlbS53aWR0aFxuXHRcdGloaXkgPSBpaXRlbS55ICsgaWl0ZW0uaGVpZ2h0XG5cdH1cblxuXHRpZiAoaml0ZW0ubGVuZ3RoID4gMikge1xuXHRcdGpsb3ggPSBqaXRlbVswXVxuXHRcdGpoaXggPSBqaXRlbVsyXVxuXHRcdGpsb3kgPSBqaXRlbVsxXVxuXHRcdGpoaXkgPSBqaXRlbVszXVxuXHR9XG5cdGVsc2UgaWYgKGppdGVtLmxlbmd0aCkge1xuXHRcdGpsb3ggPSBqbG95ID0gaml0ZW1bMF1cblx0XHRqaGl4ID0gamhpeSA9IGppdGVtWzFdXG5cdH1cblx0ZWxzZSB7XG5cdFx0amxveCA9IGppdGVtLnhcblx0XHRqbG95ID0gaml0ZW0ueVxuXHRcdGpoaXggPSBqaXRlbS54ICsgaml0ZW0ud2lkdGhcblx0XHRqaGl5ID0gaml0ZW0ueSArIGppdGVtLmhlaWdodFxuXHR9XG5cblx0cmV0dXJuIFsgamxveCwgaWxveSwgamhpeCwgaWhpeSBdXG59XG5cblxuZnVuY3Rpb24gZ2V0UGFkIChhcmcpIHtcblx0aWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSByZXR1cm4gW2FyZywgYXJnLCBhcmcsIGFyZ11cblx0ZWxzZSBpZiAoYXJnLmxlbmd0aCA9PT0gMikgcmV0dXJuIFthcmdbMF0sIGFyZ1sxXSwgYXJnWzBdLCBhcmdbMV1dXG5cdGVsc2Uge1xuXHRcdGxldCBib3ggPSByZWN0KGFyZylcblx0XHRyZXR1cm4gW2JveC54LCBib3gueSwgYm94LnggKyBib3gud2lkdGgsIGJveC55ICsgYm94LmhlaWdodF1cblx0fVxufVxuIiwiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuXHQoZ2xvYmFsLmNyZWF0ZVJFR0wgPSBmYWN0b3J5KCkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbnZhciBpc1R5cGVkQXJyYXkgPSBmdW5jdGlvbiAoeCkge1xuICByZXR1cm4gKFxuICAgIHggaW5zdGFuY2VvZiBVaW50OEFycmF5IHx8XG4gICAgeCBpbnN0YW5jZW9mIFVpbnQxNkFycmF5IHx8XG4gICAgeCBpbnN0YW5jZW9mIFVpbnQzMkFycmF5IHx8XG4gICAgeCBpbnN0YW5jZW9mIEludDhBcnJheSB8fFxuICAgIHggaW5zdGFuY2VvZiBJbnQxNkFycmF5IHx8XG4gICAgeCBpbnN0YW5jZW9mIEludDMyQXJyYXkgfHxcbiAgICB4IGluc3RhbmNlb2YgRmxvYXQzMkFycmF5IHx8XG4gICAgeCBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSB8fFxuICAgIHggaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheVxuICApXG59O1xuXG52YXIgZXh0ZW5kID0gZnVuY3Rpb24gKGJhc2UsIG9wdHMpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvcHRzKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgYmFzZVtrZXlzW2ldXSA9IG9wdHNba2V5c1tpXV07XG4gIH1cbiAgcmV0dXJuIGJhc2Vcbn07XG5cbi8vIEVycm9yIGNoZWNraW5nIGFuZCBwYXJhbWV0ZXIgdmFsaWRhdGlvbi5cbi8vXG4vLyBTdGF0ZW1lbnRzIGZvciB0aGUgZm9ybSBgY2hlY2suc29tZVByb2NlZHVyZSguLi4pYCBnZXQgcmVtb3ZlZCBieVxuLy8gYSBicm93c2VyaWZ5IHRyYW5zZm9ybSBmb3Igb3B0aW1pemVkL21pbmlmaWVkIGJ1bmRsZXMuXG4vL1xuLyogZ2xvYmFscyBhdG9iICovXG52YXIgZW5kbCA9ICdcXG4nO1xuXG4vLyBvbmx5IHVzZWQgZm9yIGV4dHJhY3Rpbmcgc2hhZGVyIG5hbWVzLiAgaWYgYXRvYiBub3QgcHJlc2VudCwgdGhlbiBlcnJvcnNcbi8vIHdpbGwgYmUgc2xpZ2h0bHkgY3JhcHBpZXJcbmZ1bmN0aW9uIGRlY29kZUI2NCAoc3RyKSB7XG4gIGlmICh0eXBlb2YgYXRvYiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gYXRvYihzdHIpXG4gIH1cbiAgcmV0dXJuICdiYXNlNjQ6JyArIHN0clxufVxuXG5mdW5jdGlvbiByYWlzZSAobWVzc2FnZSkge1xuICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJyhyZWdsKSAnICsgbWVzc2FnZSk7XG4gIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICB0aHJvdyBlcnJvclxufVxuXG5mdW5jdGlvbiBjaGVjayAocHJlZCwgbWVzc2FnZSkge1xuICBpZiAoIXByZWQpIHtcbiAgICByYWlzZShtZXNzYWdlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBlbmNvbG9uIChtZXNzYWdlKSB7XG4gIGlmIChtZXNzYWdlKSB7XG4gICAgcmV0dXJuICc6ICcgKyBtZXNzYWdlXG4gIH1cbiAgcmV0dXJuICcnXG59XG5cbmZ1bmN0aW9uIGNoZWNrUGFyYW1ldGVyIChwYXJhbSwgcG9zc2liaWxpdGllcywgbWVzc2FnZSkge1xuICBpZiAoIShwYXJhbSBpbiBwb3NzaWJpbGl0aWVzKSkge1xuICAgIHJhaXNlKCd1bmtub3duIHBhcmFtZXRlciAoJyArIHBhcmFtICsgJyknICsgZW5jb2xvbihtZXNzYWdlKSArXG4gICAgICAgICAgJy4gcG9zc2libGUgdmFsdWVzOiAnICsgT2JqZWN0LmtleXMocG9zc2liaWxpdGllcykuam9pbigpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0lzVHlwZWRBcnJheSAoZGF0YSwgbWVzc2FnZSkge1xuICBpZiAoIWlzVHlwZWRBcnJheShkYXRhKSkge1xuICAgIHJhaXNlKFxuICAgICAgJ2ludmFsaWQgcGFyYW1ldGVyIHR5cGUnICsgZW5jb2xvbihtZXNzYWdlKSArXG4gICAgICAnLiBtdXN0IGJlIGEgdHlwZWQgYXJyYXknKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja1R5cGVPZiAodmFsdWUsIHR5cGUsIG1lc3NhZ2UpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gdHlwZSkge1xuICAgIHJhaXNlKFxuICAgICAgJ2ludmFsaWQgcGFyYW1ldGVyIHR5cGUnICsgZW5jb2xvbihtZXNzYWdlKSArXG4gICAgICAnLiBleHBlY3RlZCAnICsgdHlwZSArICcsIGdvdCAnICsgKHR5cGVvZiB2YWx1ZSkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrTm9uTmVnYXRpdmVJbnQgKHZhbHVlLCBtZXNzYWdlKSB7XG4gIGlmICghKCh2YWx1ZSA+PSAwKSAmJlxuICAgICAgICAoKHZhbHVlIHwgMCkgPT09IHZhbHVlKSkpIHtcbiAgICByYWlzZSgnaW52YWxpZCBwYXJhbWV0ZXIgdHlwZSwgKCcgKyB2YWx1ZSArICcpJyArIGVuY29sb24obWVzc2FnZSkgK1xuICAgICAgICAgICcuIG11c3QgYmUgYSBub25uZWdhdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2hlY2tPbmVPZiAodmFsdWUsIGxpc3QsIG1lc3NhZ2UpIHtcbiAgaWYgKGxpc3QuaW5kZXhPZih2YWx1ZSkgPCAwKSB7XG4gICAgcmFpc2UoJ2ludmFsaWQgdmFsdWUnICsgZW5jb2xvbihtZXNzYWdlKSArICcuIG11c3QgYmUgb25lIG9mOiAnICsgbGlzdCk7XG4gIH1cbn1cblxudmFyIGNvbnN0cnVjdG9yS2V5cyA9IFtcbiAgJ2dsJyxcbiAgJ2NhbnZhcycsXG4gICdjb250YWluZXInLFxuICAnYXR0cmlidXRlcycsXG4gICdwaXhlbFJhdGlvJyxcbiAgJ2V4dGVuc2lvbnMnLFxuICAnb3B0aW9uYWxFeHRlbnNpb25zJyxcbiAgJ3Byb2ZpbGUnLFxuICAnb25Eb25lJ1xuXTtcblxuZnVuY3Rpb24gY2hlY2tDb25zdHJ1Y3RvciAob2JqKSB7XG4gIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKGNvbnN0cnVjdG9yS2V5cy5pbmRleE9mKGtleSkgPCAwKSB7XG4gICAgICByYWlzZSgnaW52YWxpZCByZWdsIGNvbnN0cnVjdG9yIGFyZ3VtZW50IFwiJyArIGtleSArICdcIi4gbXVzdCBiZSBvbmUgb2YgJyArIGNvbnN0cnVjdG9yS2V5cyk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gbGVmdFBhZCAoc3RyLCBuKSB7XG4gIHN0ciA9IHN0ciArICcnO1xuICB3aGlsZSAoc3RyLmxlbmd0aCA8IG4pIHtcbiAgICBzdHIgPSAnICcgKyBzdHI7XG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiBTaGFkZXJGaWxlICgpIHtcbiAgdGhpcy5uYW1lID0gJ3Vua25vd24nO1xuICB0aGlzLmxpbmVzID0gW107XG4gIHRoaXMuaW5kZXggPSB7fTtcbiAgdGhpcy5oYXNFcnJvcnMgPSBmYWxzZTtcbn1cblxuZnVuY3Rpb24gU2hhZGVyTGluZSAobnVtYmVyLCBsaW5lKSB7XG4gIHRoaXMubnVtYmVyID0gbnVtYmVyO1xuICB0aGlzLmxpbmUgPSBsaW5lO1xuICB0aGlzLmVycm9ycyA9IFtdO1xufVxuXG5mdW5jdGlvbiBTaGFkZXJFcnJvciAoZmlsZU51bWJlciwgbGluZU51bWJlciwgbWVzc2FnZSkge1xuICB0aGlzLmZpbGUgPSBmaWxlTnVtYmVyO1xuICB0aGlzLmxpbmUgPSBsaW5lTnVtYmVyO1xuICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xufVxuXG5mdW5jdGlvbiBndWVzc0NvbW1hbmQgKCkge1xuICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgdmFyIHN0YWNrID0gKGVycm9yLnN0YWNrIHx8IGVycm9yKS50b1N0cmluZygpO1xuICB2YXIgcGF0ID0gL2NvbXBpbGVQcm9jZWR1cmUuKlxcblxccyphdC4qXFwoKC4qKVxcKS8uZXhlYyhzdGFjayk7XG4gIGlmIChwYXQpIHtcbiAgICByZXR1cm4gcGF0WzFdXG4gIH1cbiAgdmFyIHBhdDIgPSAvY29tcGlsZVByb2NlZHVyZS4qXFxuXFxzKmF0XFxzKyguKikoXFxufCQpLy5leGVjKHN0YWNrKTtcbiAgaWYgKHBhdDIpIHtcbiAgICByZXR1cm4gcGF0MlsxXVxuICB9XG4gIHJldHVybiAndW5rbm93bidcbn1cblxuZnVuY3Rpb24gZ3Vlc3NDYWxsU2l0ZSAoKSB7XG4gIHZhciBlcnJvciA9IG5ldyBFcnJvcigpO1xuICB2YXIgc3RhY2sgPSAoZXJyb3Iuc3RhY2sgfHwgZXJyb3IpLnRvU3RyaW5nKCk7XG4gIHZhciBwYXQgPSAvYXQgUkVHTENvbW1hbmQuKlxcblxccythdC4qXFwoKC4qKVxcKS8uZXhlYyhzdGFjayk7XG4gIGlmIChwYXQpIHtcbiAgICByZXR1cm4gcGF0WzFdXG4gIH1cbiAgdmFyIHBhdDIgPSAvYXQgUkVHTENvbW1hbmQuKlxcblxccythdFxccysoLiopXFxuLy5leGVjKHN0YWNrKTtcbiAgaWYgKHBhdDIpIHtcbiAgICByZXR1cm4gcGF0MlsxXVxuICB9XG4gIHJldHVybiAndW5rbm93bidcbn1cblxuZnVuY3Rpb24gcGFyc2VTb3VyY2UgKHNvdXJjZSwgY29tbWFuZCkge1xuICB2YXIgbGluZXMgPSBzb3VyY2Uuc3BsaXQoJ1xcbicpO1xuICB2YXIgbGluZU51bWJlciA9IDE7XG4gIHZhciBmaWxlTnVtYmVyID0gMDtcbiAgdmFyIGZpbGVzID0ge1xuICAgIHVua25vd246IG5ldyBTaGFkZXJGaWxlKCksXG4gICAgMDogbmV3IFNoYWRlckZpbGUoKVxuICB9O1xuICBmaWxlcy51bmtub3duLm5hbWUgPSBmaWxlc1swXS5uYW1lID0gY29tbWFuZCB8fCBndWVzc0NvbW1hbmQoKTtcbiAgZmlsZXMudW5rbm93bi5saW5lcy5wdXNoKG5ldyBTaGFkZXJMaW5lKDAsICcnKSk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuICAgIHZhciBwYXJ0cyA9IC9eXFxzKlxcI1xccyooXFx3KylcXHMrKC4rKVxccyokLy5leGVjKGxpbmUpO1xuICAgIGlmIChwYXJ0cykge1xuICAgICAgc3dpdGNoIChwYXJ0c1sxXSkge1xuICAgICAgICBjYXNlICdsaW5lJzpcbiAgICAgICAgICB2YXIgbGluZU51bWJlckluZm8gPSAvKFxcZCspKFxccytcXGQrKT8vLmV4ZWMocGFydHNbMl0pO1xuICAgICAgICAgIGlmIChsaW5lTnVtYmVySW5mbykge1xuICAgICAgICAgICAgbGluZU51bWJlciA9IGxpbmVOdW1iZXJJbmZvWzFdIHwgMDtcbiAgICAgICAgICAgIGlmIChsaW5lTnVtYmVySW5mb1syXSkge1xuICAgICAgICAgICAgICBmaWxlTnVtYmVyID0gbGluZU51bWJlckluZm9bMl0gfCAwO1xuICAgICAgICAgICAgICBpZiAoIShmaWxlTnVtYmVyIGluIGZpbGVzKSkge1xuICAgICAgICAgICAgICAgIGZpbGVzW2ZpbGVOdW1iZXJdID0gbmV3IFNoYWRlckZpbGUoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlICdkZWZpbmUnOlxuICAgICAgICAgIHZhciBuYW1lSW5mbyA9IC9TSEFERVJfTkFNRShfQjY0KT9cXHMrKC4qKSQvLmV4ZWMocGFydHNbMl0pO1xuICAgICAgICAgIGlmIChuYW1lSW5mbykge1xuICAgICAgICAgICAgZmlsZXNbZmlsZU51bWJlcl0ubmFtZSA9IChuYW1lSW5mb1sxXVxuICAgICAgICAgICAgICAgID8gZGVjb2RlQjY0KG5hbWVJbmZvWzJdKVxuICAgICAgICAgICAgICAgIDogbmFtZUluZm9bMl0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgICBmaWxlc1tmaWxlTnVtYmVyXS5saW5lcy5wdXNoKG5ldyBTaGFkZXJMaW5lKGxpbmVOdW1iZXIrKywgbGluZSkpO1xuICB9XG4gIE9iamVjdC5rZXlzKGZpbGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlTnVtYmVyKSB7XG4gICAgdmFyIGZpbGUgPSBmaWxlc1tmaWxlTnVtYmVyXTtcbiAgICBmaWxlLmxpbmVzLmZvckVhY2goZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgIGZpbGUuaW5kZXhbbGluZS5udW1iZXJdID0gbGluZTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBmaWxlc1xufVxuXG5mdW5jdGlvbiBwYXJzZUVycm9yTG9nIChlcnJMb2cpIHtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICBlcnJMb2cuc3BsaXQoJ1xcbicpLmZvckVhY2goZnVuY3Rpb24gKGVyck1zZykge1xuICAgIGlmIChlcnJNc2cubGVuZ3RoIDwgNSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIHZhciBwYXJ0cyA9IC9eRVJST1JcXDpcXHMrKFxcZCspXFw6KFxcZCspXFw6XFxzKiguKikkLy5leGVjKGVyck1zZyk7XG4gICAgaWYgKHBhcnRzKSB7XG4gICAgICByZXN1bHQucHVzaChuZXcgU2hhZGVyRXJyb3IoXG4gICAgICAgIHBhcnRzWzFdIHwgMCxcbiAgICAgICAgcGFydHNbMl0gfCAwLFxuICAgICAgICBwYXJ0c1szXS50cmltKCkpKTtcbiAgICB9IGVsc2UgaWYgKGVyck1zZy5sZW5ndGggPiAwKSB7XG4gICAgICByZXN1bHQucHVzaChuZXcgU2hhZGVyRXJyb3IoJ3Vua25vd24nLCAwLCBlcnJNc2cpKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGFubm90YXRlRmlsZXMgKGZpbGVzLCBlcnJvcnMpIHtcbiAgZXJyb3JzLmZvckVhY2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgdmFyIGZpbGUgPSBmaWxlc1tlcnJvci5maWxlXTtcbiAgICBpZiAoZmlsZSkge1xuICAgICAgdmFyIGxpbmUgPSBmaWxlLmluZGV4W2Vycm9yLmxpbmVdO1xuICAgICAgaWYgKGxpbmUpIHtcbiAgICAgICAgbGluZS5lcnJvcnMucHVzaChlcnJvcik7XG4gICAgICAgIGZpbGUuaGFzRXJyb3JzID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuICAgIGZpbGVzLnVua25vd24uaGFzRXJyb3JzID0gdHJ1ZTtcbiAgICBmaWxlcy51bmtub3duLmxpbmVzWzBdLmVycm9ycy5wdXNoKGVycm9yKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2hhZGVyRXJyb3IgKGdsLCBzaGFkZXIsIHNvdXJjZSwgdHlwZSwgY29tbWFuZCkge1xuICBpZiAoIWdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIGdsLkNPTVBJTEVfU1RBVFVTKSkge1xuICAgIHZhciBlcnJMb2cgPSBnbC5nZXRTaGFkZXJJbmZvTG9nKHNoYWRlcik7XG4gICAgdmFyIHR5cGVOYW1lID0gdHlwZSA9PT0gZ2wuRlJBR01FTlRfU0hBREVSID8gJ2ZyYWdtZW50JyA6ICd2ZXJ0ZXgnO1xuICAgIGNoZWNrQ29tbWFuZFR5cGUoc291cmNlLCAnc3RyaW5nJywgdHlwZU5hbWUgKyAnIHNoYWRlciBzb3VyY2UgbXVzdCBiZSBhIHN0cmluZycsIGNvbW1hbmQpO1xuICAgIHZhciBmaWxlcyA9IHBhcnNlU291cmNlKHNvdXJjZSwgY29tbWFuZCk7XG4gICAgdmFyIGVycm9ycyA9IHBhcnNlRXJyb3JMb2coZXJyTG9nKTtcbiAgICBhbm5vdGF0ZUZpbGVzKGZpbGVzLCBlcnJvcnMpO1xuXG4gICAgT2JqZWN0LmtleXMoZmlsZXMpLmZvckVhY2goZnVuY3Rpb24gKGZpbGVOdW1iZXIpIHtcbiAgICAgIHZhciBmaWxlID0gZmlsZXNbZmlsZU51bWJlcl07XG4gICAgICBpZiAoIWZpbGUuaGFzRXJyb3JzKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICB2YXIgc3RyaW5ncyA9IFsnJ107XG4gICAgICB2YXIgc3R5bGVzID0gWycnXTtcblxuICAgICAgZnVuY3Rpb24gcHVzaCAoc3RyLCBzdHlsZSkge1xuICAgICAgICBzdHJpbmdzLnB1c2goc3RyKTtcbiAgICAgICAgc3R5bGVzLnB1c2goc3R5bGUgfHwgJycpO1xuICAgICAgfVxuXG4gICAgICBwdXNoKCdmaWxlIG51bWJlciAnICsgZmlsZU51bWJlciArICc6ICcgKyBmaWxlLm5hbWUgKyAnXFxuJywgJ2NvbG9yOnJlZDt0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO2ZvbnQtd2VpZ2h0OmJvbGQnKTtcblxuICAgICAgZmlsZS5saW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIGlmIChsaW5lLmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcHVzaChsZWZ0UGFkKGxpbmUubnVtYmVyLCA0KSArICd8ICAnLCAnYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IGZvbnQtd2VpZ2h0OmJvbGQnKTtcbiAgICAgICAgICBwdXNoKGxpbmUubGluZSArIGVuZGwsICdjb2xvcjpyZWQ7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyBmb250LXdlaWdodDpib2xkJyk7XG5cbiAgICAgICAgICAvLyB0cnkgdG8gZ3Vlc3MgdG9rZW5cbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICBsaW5lLmVycm9ycy5mb3JFYWNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgdmFyIHRva2VuID0gL15cXHMqXFwnKC4qKVxcJ1xccypcXDpcXHMqKC4qKSQvLmV4ZWMobWVzc2FnZSk7XG4gICAgICAgICAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgICAgICAgdmFyIHRva2VuUGF0ID0gdG9rZW5bMV07XG4gICAgICAgICAgICAgIG1lc3NhZ2UgPSB0b2tlblsyXTtcbiAgICAgICAgICAgICAgc3dpdGNoICh0b2tlblBhdCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Fzc2lnbic6XG4gICAgICAgICAgICAgICAgICB0b2tlblBhdCA9ICc9JztcbiAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgb2Zmc2V0ID0gTWF0aC5tYXgobGluZS5saW5lLmluZGV4T2YodG9rZW5QYXQsIG9mZnNldCksIDApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHVzaChsZWZ0UGFkKCd8ICcsIDYpKTtcbiAgICAgICAgICAgIHB1c2gobGVmdFBhZCgnXl5eJywgb2Zmc2V0ICsgMykgKyBlbmRsLCAnZm9udC13ZWlnaHQ6Ym9sZCcpO1xuICAgICAgICAgICAgcHVzaChsZWZ0UGFkKCd8ICcsIDYpKTtcbiAgICAgICAgICAgIHB1c2gobWVzc2FnZSArIGVuZGwsICdmb250LXdlaWdodDpib2xkJyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcHVzaChsZWZ0UGFkKCd8ICcsIDYpICsgZW5kbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcHVzaChsZWZ0UGFkKGxpbmUubnVtYmVyLCA0KSArICd8ICAnKTtcbiAgICAgICAgICBwdXNoKGxpbmUubGluZSArIGVuZGwsICdjb2xvcjpyZWQnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiAhd2luZG93LmNocm9tZSkge1xuICAgICAgICBzdHlsZXNbMF0gPSBzdHJpbmdzLmpvaW4oJyVjJyk7XG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIHN0eWxlcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZyhzdHJpbmdzLmpvaW4oJycpKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNoZWNrLnJhaXNlKCdFcnJvciBjb21waWxpbmcgJyArIHR5cGVOYW1lICsgJyBzaGFkZXIsICcgKyBmaWxlc1swXS5uYW1lKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0xpbmtFcnJvciAoZ2wsIHByb2dyYW0sIGZyYWdTaGFkZXIsIHZlcnRTaGFkZXIsIGNvbW1hbmQpIHtcbiAgaWYgKCFnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkxJTktfU1RBVFVTKSkge1xuICAgIHZhciBlcnJMb2cgPSBnbC5nZXRQcm9ncmFtSW5mb0xvZyhwcm9ncmFtKTtcbiAgICB2YXIgZnJhZ1BhcnNlID0gcGFyc2VTb3VyY2UoZnJhZ1NoYWRlciwgY29tbWFuZCk7XG4gICAgdmFyIHZlcnRQYXJzZSA9IHBhcnNlU291cmNlKHZlcnRTaGFkZXIsIGNvbW1hbmQpO1xuXG4gICAgdmFyIGhlYWRlciA9ICdFcnJvciBsaW5raW5nIHByb2dyYW0gd2l0aCB2ZXJ0ZXggc2hhZGVyLCBcIicgK1xuICAgICAgdmVydFBhcnNlWzBdLm5hbWUgKyAnXCIsIGFuZCBmcmFnbWVudCBzaGFkZXIgXCInICsgZnJhZ1BhcnNlWzBdLm5hbWUgKyAnXCInO1xuXG4gICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNvbnNvbGUubG9nKCclYycgKyBoZWFkZXIgKyBlbmRsICsgJyVjJyArIGVyckxvZyxcbiAgICAgICAgJ2NvbG9yOnJlZDt0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO2ZvbnQtd2VpZ2h0OmJvbGQnLFxuICAgICAgICAnY29sb3I6cmVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUubG9nKGhlYWRlciArIGVuZGwgKyBlcnJMb2cpO1xuICAgIH1cbiAgICBjaGVjay5yYWlzZShoZWFkZXIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHNhdmVDb21tYW5kUmVmIChvYmplY3QpIHtcbiAgb2JqZWN0Ll9jb21tYW5kUmVmID0gZ3Vlc3NDb21tYW5kKCk7XG59XG5cbmZ1bmN0aW9uIHNhdmVEcmF3Q29tbWFuZEluZm8gKG9wdHMsIHVuaWZvcm1zLCBhdHRyaWJ1dGVzLCBzdHJpbmdTdG9yZSkge1xuICBzYXZlQ29tbWFuZFJlZihvcHRzKTtcblxuICBmdW5jdGlvbiBpZCAoc3RyKSB7XG4gICAgaWYgKHN0cikge1xuICAgICAgcmV0dXJuIHN0cmluZ1N0b3JlLmlkKHN0cilcbiAgICB9XG4gICAgcmV0dXJuIDBcbiAgfVxuICBvcHRzLl9mcmFnSWQgPSBpZChvcHRzLnN0YXRpYy5mcmFnKTtcbiAgb3B0cy5fdmVydElkID0gaWQob3B0cy5zdGF0aWMudmVydCk7XG5cbiAgZnVuY3Rpb24gYWRkUHJvcHMgKGRpY3QsIHNldCkge1xuICAgIE9iamVjdC5rZXlzKHNldCkuZm9yRWFjaChmdW5jdGlvbiAodSkge1xuICAgICAgZGljdFtzdHJpbmdTdG9yZS5pZCh1KV0gPSB0cnVlO1xuICAgIH0pO1xuICB9XG5cbiAgdmFyIHVuaWZvcm1TZXQgPSBvcHRzLl91bmlmb3JtU2V0ID0ge307XG4gIGFkZFByb3BzKHVuaWZvcm1TZXQsIHVuaWZvcm1zLnN0YXRpYyk7XG4gIGFkZFByb3BzKHVuaWZvcm1TZXQsIHVuaWZvcm1zLmR5bmFtaWMpO1xuXG4gIHZhciBhdHRyaWJ1dGVTZXQgPSBvcHRzLl9hdHRyaWJ1dGVTZXQgPSB7fTtcbiAgYWRkUHJvcHMoYXR0cmlidXRlU2V0LCBhdHRyaWJ1dGVzLnN0YXRpYyk7XG4gIGFkZFByb3BzKGF0dHJpYnV0ZVNldCwgYXR0cmlidXRlcy5keW5hbWljKTtcblxuICBvcHRzLl9oYXNDb3VudCA9IChcbiAgICAnY291bnQnIGluIG9wdHMuc3RhdGljIHx8XG4gICAgJ2NvdW50JyBpbiBvcHRzLmR5bmFtaWMgfHxcbiAgICAnZWxlbWVudHMnIGluIG9wdHMuc3RhdGljIHx8XG4gICAgJ2VsZW1lbnRzJyBpbiBvcHRzLmR5bmFtaWMpO1xufVxuXG5mdW5jdGlvbiBjb21tYW5kUmFpc2UgKG1lc3NhZ2UsIGNvbW1hbmQpIHtcbiAgdmFyIGNhbGxTaXRlID0gZ3Vlc3NDYWxsU2l0ZSgpO1xuICByYWlzZShtZXNzYWdlICtcbiAgICAnIGluIGNvbW1hbmQgJyArIChjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpKSArXG4gICAgKGNhbGxTaXRlID09PSAndW5rbm93bicgPyAnJyA6ICcgY2FsbGVkIGZyb20gJyArIGNhbGxTaXRlKSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrQ29tbWFuZCAocHJlZCwgbWVzc2FnZSwgY29tbWFuZCkge1xuICBpZiAoIXByZWQpIHtcbiAgICBjb21tYW5kUmFpc2UobWVzc2FnZSwgY29tbWFuZCB8fCBndWVzc0NvbW1hbmQoKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2hlY2tQYXJhbWV0ZXJDb21tYW5kIChwYXJhbSwgcG9zc2liaWxpdGllcywgbWVzc2FnZSwgY29tbWFuZCkge1xuICBpZiAoIShwYXJhbSBpbiBwb3NzaWJpbGl0aWVzKSkge1xuICAgIGNvbW1hbmRSYWlzZShcbiAgICAgICd1bmtub3duIHBhcmFtZXRlciAoJyArIHBhcmFtICsgJyknICsgZW5jb2xvbihtZXNzYWdlKSArXG4gICAgICAnLiBwb3NzaWJsZSB2YWx1ZXM6ICcgKyBPYmplY3Qua2V5cyhwb3NzaWJpbGl0aWVzKS5qb2luKCksXG4gICAgICBjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0NvbW1hbmRUeXBlICh2YWx1ZSwgdHlwZSwgbWVzc2FnZSwgY29tbWFuZCkge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSB0eXBlKSB7XG4gICAgY29tbWFuZFJhaXNlKFxuICAgICAgJ2ludmFsaWQgcGFyYW1ldGVyIHR5cGUnICsgZW5jb2xvbihtZXNzYWdlKSArXG4gICAgICAnLiBleHBlY3RlZCAnICsgdHlwZSArICcsIGdvdCAnICsgKHR5cGVvZiB2YWx1ZSksXG4gICAgICBjb21tYW5kIHx8IGd1ZXNzQ29tbWFuZCgpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja09wdGlvbmFsIChibG9jaykge1xuICBibG9jaygpO1xufVxuXG5mdW5jdGlvbiBjaGVja0ZyYW1lYnVmZmVyRm9ybWF0IChhdHRhY2htZW50LCB0ZXhGb3JtYXRzLCByYkZvcm1hdHMpIHtcbiAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgIGNoZWNrT25lT2YoXG4gICAgICBhdHRhY2htZW50LnRleHR1cmUuX3RleHR1cmUuaW50ZXJuYWxmb3JtYXQsXG4gICAgICB0ZXhGb3JtYXRzLFxuICAgICAgJ3Vuc3VwcG9ydGVkIHRleHR1cmUgZm9ybWF0IGZvciBhdHRhY2htZW50Jyk7XG4gIH0gZWxzZSB7XG4gICAgY2hlY2tPbmVPZihcbiAgICAgIGF0dGFjaG1lbnQucmVuZGVyYnVmZmVyLl9yZW5kZXJidWZmZXIuZm9ybWF0LFxuICAgICAgcmJGb3JtYXRzLFxuICAgICAgJ3Vuc3VwcG9ydGVkIHJlbmRlcmJ1ZmZlciBmb3JtYXQgZm9yIGF0dGFjaG1lbnQnKTtcbiAgfVxufVxuXG52YXIgR0xfQ0xBTVBfVE9fRURHRSA9IDB4ODEyRjtcblxudmFyIEdMX05FQVJFU1QgPSAweDI2MDA7XG52YXIgR0xfTkVBUkVTVF9NSVBNQVBfTkVBUkVTVCA9IDB4MjcwMDtcbnZhciBHTF9MSU5FQVJfTUlQTUFQX05FQVJFU1QgPSAweDI3MDE7XG52YXIgR0xfTkVBUkVTVF9NSVBNQVBfTElORUFSID0gMHgyNzAyO1xudmFyIEdMX0xJTkVBUl9NSVBNQVBfTElORUFSID0gMHgyNzAzO1xuXG52YXIgR0xfQllURSA9IDUxMjA7XG52YXIgR0xfVU5TSUdORURfQllURSA9IDUxMjE7XG52YXIgR0xfU0hPUlQgPSA1MTIyO1xudmFyIEdMX1VOU0lHTkVEX1NIT1JUID0gNTEyMztcbnZhciBHTF9JTlQgPSA1MTI0O1xudmFyIEdMX1VOU0lHTkVEX0lOVCA9IDUxMjU7XG52YXIgR0xfRkxPQVQgPSA1MTI2O1xuXG52YXIgR0xfVU5TSUdORURfU0hPUlRfNF80XzRfNCA9IDB4ODAzMztcbnZhciBHTF9VTlNJR05FRF9TSE9SVF81XzVfNV8xID0gMHg4MDM0O1xudmFyIEdMX1VOU0lHTkVEX1NIT1JUXzVfNl81ID0gMHg4MzYzO1xudmFyIEdMX1VOU0lHTkVEX0lOVF8yNF84X1dFQkdMID0gMHg4NEZBO1xuXG52YXIgR0xfSEFMRl9GTE9BVF9PRVMgPSAweDhENjE7XG5cbnZhciBUWVBFX1NJWkUgPSB7fTtcblxuVFlQRV9TSVpFW0dMX0JZVEVdID1cblRZUEVfU0laRVtHTF9VTlNJR05FRF9CWVRFXSA9IDE7XG5cblRZUEVfU0laRVtHTF9TSE9SVF0gPVxuVFlQRV9TSVpFW0dMX1VOU0lHTkVEX1NIT1JUXSA9XG5UWVBFX1NJWkVbR0xfSEFMRl9GTE9BVF9PRVNdID1cblRZUEVfU0laRVtHTF9VTlNJR05FRF9TSE9SVF81XzZfNV0gPVxuVFlQRV9TSVpFW0dMX1VOU0lHTkVEX1NIT1JUXzRfNF80XzRdID1cblRZUEVfU0laRVtHTF9VTlNJR05FRF9TSE9SVF81XzVfNV8xXSA9IDI7XG5cblRZUEVfU0laRVtHTF9JTlRdID1cblRZUEVfU0laRVtHTF9VTlNJR05FRF9JTlRdID1cblRZUEVfU0laRVtHTF9GTE9BVF0gPVxuVFlQRV9TSVpFW0dMX1VOU0lHTkVEX0lOVF8yNF84X1dFQkdMXSA9IDQ7XG5cbmZ1bmN0aW9uIHBpeGVsU2l6ZSAodHlwZSwgY2hhbm5lbHMpIHtcbiAgaWYgKHR5cGUgPT09IEdMX1VOU0lHTkVEX1NIT1JUXzVfNV81XzEgfHxcbiAgICAgIHR5cGUgPT09IEdMX1VOU0lHTkVEX1NIT1JUXzRfNF80XzQgfHxcbiAgICAgIHR5cGUgPT09IEdMX1VOU0lHTkVEX1NIT1JUXzVfNl81KSB7XG4gICAgcmV0dXJuIDJcbiAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9VTlNJR05FRF9JTlRfMjRfOF9XRUJHTCkge1xuICAgIHJldHVybiA0XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFRZUEVfU0laRVt0eXBlXSAqIGNoYW5uZWxzXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNQb3cyICh2KSB7XG4gIHJldHVybiAhKHYgJiAodiAtIDEpKSAmJiAoISF2KVxufVxuXG5mdW5jdGlvbiBjaGVja1RleHR1cmUyRCAoaW5mbywgbWlwRGF0YSwgbGltaXRzKSB7XG4gIHZhciBpO1xuICB2YXIgdyA9IG1pcERhdGEud2lkdGg7XG4gIHZhciBoID0gbWlwRGF0YS5oZWlnaHQ7XG4gIHZhciBjID0gbWlwRGF0YS5jaGFubmVscztcblxuICAvLyBDaGVjayB0ZXh0dXJlIHNoYXBlXG4gIGNoZWNrKHcgPiAwICYmIHcgPD0gbGltaXRzLm1heFRleHR1cmVTaXplICYmXG4gICAgICAgIGggPiAwICYmIGggPD0gbGltaXRzLm1heFRleHR1cmVTaXplLFxuICAgICAgICAnaW52YWxpZCB0ZXh0dXJlIHNoYXBlJyk7XG5cbiAgLy8gY2hlY2sgd3JhcCBtb2RlXG4gIGlmIChpbmZvLndyYXBTICE9PSBHTF9DTEFNUF9UT19FREdFIHx8IGluZm8ud3JhcFQgIT09IEdMX0NMQU1QX1RPX0VER0UpIHtcbiAgICBjaGVjayhpc1BvdzIodykgJiYgaXNQb3cyKGgpLFxuICAgICAgJ2luY29tcGF0aWJsZSB3cmFwIG1vZGUgZm9yIHRleHR1cmUsIGJvdGggd2lkdGggYW5kIGhlaWdodCBtdXN0IGJlIHBvd2VyIG9mIDInKTtcbiAgfVxuXG4gIGlmIChtaXBEYXRhLm1pcG1hc2sgPT09IDEpIHtcbiAgICBpZiAodyAhPT0gMSAmJiBoICE9PSAxKSB7XG4gICAgICBjaGVjayhcbiAgICAgICAgaW5mby5taW5GaWx0ZXIgIT09IEdMX05FQVJFU1RfTUlQTUFQX05FQVJFU1QgJiZcbiAgICAgICAgaW5mby5taW5GaWx0ZXIgIT09IEdMX05FQVJFU1RfTUlQTUFQX0xJTkVBUiAmJlxuICAgICAgICBpbmZvLm1pbkZpbHRlciAhPT0gR0xfTElORUFSX01JUE1BUF9ORUFSRVNUICYmXG4gICAgICAgIGluZm8ubWluRmlsdGVyICE9PSBHTF9MSU5FQVJfTUlQTUFQX0xJTkVBUixcbiAgICAgICAgJ21pbiBmaWx0ZXIgcmVxdWlyZXMgbWlwbWFwJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIHRleHR1cmUgbXVzdCBiZSBwb3dlciBvZiAyXG4gICAgY2hlY2soaXNQb3cyKHcpICYmIGlzUG93MihoKSxcbiAgICAgICd0ZXh0dXJlIG11c3QgYmUgYSBzcXVhcmUgcG93ZXIgb2YgMiB0byBzdXBwb3J0IG1pcG1hcHBpbmcnKTtcbiAgICBjaGVjayhtaXBEYXRhLm1pcG1hc2sgPT09ICh3IDw8IDEpIC0gMSxcbiAgICAgICdtaXNzaW5nIG9yIGluY29tcGxldGUgbWlwbWFwIGRhdGEnKTtcbiAgfVxuXG4gIGlmIChtaXBEYXRhLnR5cGUgPT09IEdMX0ZMT0FUKSB7XG4gICAgaWYgKGxpbWl0cy5leHRlbnNpb25zLmluZGV4T2YoJ29lc190ZXh0dXJlX2Zsb2F0X2xpbmVhcicpIDwgMCkge1xuICAgICAgY2hlY2soaW5mby5taW5GaWx0ZXIgPT09IEdMX05FQVJFU1QgJiYgaW5mby5tYWdGaWx0ZXIgPT09IEdMX05FQVJFU1QsXG4gICAgICAgICdmaWx0ZXIgbm90IHN1cHBvcnRlZCwgbXVzdCBlbmFibGUgb2VzX3RleHR1cmVfZmxvYXRfbGluZWFyJyk7XG4gICAgfVxuICAgIGNoZWNrKCFpbmZvLmdlbk1pcG1hcHMsXG4gICAgICAnbWlwbWFwIGdlbmVyYXRpb24gbm90IHN1cHBvcnRlZCB3aXRoIGZsb2F0IHRleHR1cmVzJyk7XG4gIH1cblxuICAvLyBjaGVjayBpbWFnZSBjb21wbGV0ZVxuICB2YXIgbWlwaW1hZ2VzID0gbWlwRGF0YS5pbWFnZXM7XG4gIGZvciAoaSA9IDA7IGkgPCAxNjsgKytpKSB7XG4gICAgaWYgKG1pcGltYWdlc1tpXSkge1xuICAgICAgdmFyIG13ID0gdyA+PiBpO1xuICAgICAgdmFyIG1oID0gaCA+PiBpO1xuICAgICAgY2hlY2sobWlwRGF0YS5taXBtYXNrICYgKDEgPDwgaSksICdtaXNzaW5nIG1pcG1hcCBkYXRhJyk7XG5cbiAgICAgIHZhciBpbWcgPSBtaXBpbWFnZXNbaV07XG5cbiAgICAgIGNoZWNrKFxuICAgICAgICBpbWcud2lkdGggPT09IG13ICYmXG4gICAgICAgIGltZy5oZWlnaHQgPT09IG1oLFxuICAgICAgICAnaW52YWxpZCBzaGFwZSBmb3IgbWlwIGltYWdlcycpO1xuXG4gICAgICBjaGVjayhcbiAgICAgICAgaW1nLmZvcm1hdCA9PT0gbWlwRGF0YS5mb3JtYXQgJiZcbiAgICAgICAgaW1nLmludGVybmFsZm9ybWF0ID09PSBtaXBEYXRhLmludGVybmFsZm9ybWF0ICYmXG4gICAgICAgIGltZy50eXBlID09PSBtaXBEYXRhLnR5cGUsXG4gICAgICAgICdpbmNvbXBhdGlibGUgdHlwZSBmb3IgbWlwIGltYWdlJyk7XG5cbiAgICAgIGlmIChpbWcuY29tcHJlc3NlZCkge1xuICAgICAgICAvLyBUT0RPOiBjaGVjayBzaXplIGZvciBjb21wcmVzc2VkIGltYWdlc1xuICAgICAgfSBlbHNlIGlmIChpbWcuZGF0YSkge1xuICAgICAgICAvLyBjaGVjayhpbWcuZGF0YS5ieXRlTGVuZ3RoID09PSBtdyAqIG1oICpcbiAgICAgICAgLy8gTWF0aC5tYXgocGl4ZWxTaXplKGltZy50eXBlLCBjKSwgaW1nLnVucGFja0FsaWdubWVudCksXG4gICAgICAgIHZhciByb3dTaXplID0gTWF0aC5jZWlsKHBpeGVsU2l6ZShpbWcudHlwZSwgYykgKiBtdyAvIGltZy51bnBhY2tBbGlnbm1lbnQpICogaW1nLnVucGFja0FsaWdubWVudDtcbiAgICAgICAgY2hlY2soaW1nLmRhdGEuYnl0ZUxlbmd0aCA9PT0gcm93U2l6ZSAqIG1oLFxuICAgICAgICAgICdpbnZhbGlkIGRhdGEgZm9yIGltYWdlLCBidWZmZXIgc2l6ZSBpcyBpbmNvbnNpc3RlbnQgd2l0aCBpbWFnZSBmb3JtYXQnKTtcbiAgICAgIH0gZWxzZSBpZiAoaW1nLmVsZW1lbnQpIHtcbiAgICAgICAgLy8gVE9ETzogY2hlY2sgZWxlbWVudCBjYW4gYmUgbG9hZGVkXG4gICAgICB9IGVsc2UgaWYgKGltZy5jb3B5KSB7XG4gICAgICAgIC8vIFRPRE86IGNoZWNrIGNvbXBhdGlibGUgZm9ybWF0IGFuZCB0eXBlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghaW5mby5nZW5NaXBtYXBzKSB7XG4gICAgICBjaGVjaygobWlwRGF0YS5taXBtYXNrICYgKDEgPDwgaSkpID09PSAwLCAnZXh0cmEgbWlwbWFwIGRhdGEnKTtcbiAgICB9XG4gIH1cblxuICBpZiAobWlwRGF0YS5jb21wcmVzc2VkKSB7XG4gICAgY2hlY2soIWluZm8uZ2VuTWlwbWFwcyxcbiAgICAgICdtaXBtYXAgZ2VuZXJhdGlvbiBmb3IgY29tcHJlc3NlZCBpbWFnZXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrVGV4dHVyZUN1YmUgKHRleHR1cmUsIGluZm8sIGZhY2VzLCBsaW1pdHMpIHtcbiAgdmFyIHcgPSB0ZXh0dXJlLndpZHRoO1xuICB2YXIgaCA9IHRleHR1cmUuaGVpZ2h0O1xuICB2YXIgYyA9IHRleHR1cmUuY2hhbm5lbHM7XG5cbiAgLy8gQ2hlY2sgdGV4dHVyZSBzaGFwZVxuICBjaGVjayhcbiAgICB3ID4gMCAmJiB3IDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSAmJiBoID4gMCAmJiBoIDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSxcbiAgICAnaW52YWxpZCB0ZXh0dXJlIHNoYXBlJyk7XG4gIGNoZWNrKFxuICAgIHcgPT09IGgsXG4gICAgJ2N1YmUgbWFwIG11c3QgYmUgc3F1YXJlJyk7XG4gIGNoZWNrKFxuICAgIGluZm8ud3JhcFMgPT09IEdMX0NMQU1QX1RPX0VER0UgJiYgaW5mby53cmFwVCA9PT0gR0xfQ0xBTVBfVE9fRURHRSxcbiAgICAnd3JhcCBtb2RlIG5vdCBzdXBwb3J0ZWQgYnkgY3ViZSBtYXAnKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGZhY2VzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGZhY2UgPSBmYWNlc1tpXTtcbiAgICBjaGVjayhcbiAgICAgIGZhY2Uud2lkdGggPT09IHcgJiYgZmFjZS5oZWlnaHQgPT09IGgsXG4gICAgICAnaW5jb25zaXN0ZW50IGN1YmUgbWFwIGZhY2Ugc2hhcGUnKTtcblxuICAgIGlmIChpbmZvLmdlbk1pcG1hcHMpIHtcbiAgICAgIGNoZWNrKCFmYWNlLmNvbXByZXNzZWQsXG4gICAgICAgICdjYW4gbm90IGdlbmVyYXRlIG1pcG1hcCBmb3IgY29tcHJlc3NlZCB0ZXh0dXJlcycpO1xuICAgICAgY2hlY2soZmFjZS5taXBtYXNrID09PSAxLFxuICAgICAgICAnY2FuIG5vdCBzcGVjaWZ5IG1pcG1hcHMgYW5kIGdlbmVyYXRlIG1pcG1hcHMnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVE9ETzogY2hlY2sgbWlwIGFuZCBmaWx0ZXIgbW9kZVxuICAgIH1cblxuICAgIHZhciBtaXBtYXBzID0gZmFjZS5pbWFnZXM7XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAxNjsgKytqKSB7XG4gICAgICB2YXIgaW1nID0gbWlwbWFwc1tqXTtcbiAgICAgIGlmIChpbWcpIHtcbiAgICAgICAgdmFyIG13ID0gdyA+PiBqO1xuICAgICAgICB2YXIgbWggPSBoID4+IGo7XG4gICAgICAgIGNoZWNrKGZhY2UubWlwbWFzayAmICgxIDw8IGopLCAnbWlzc2luZyBtaXBtYXAgZGF0YScpO1xuICAgICAgICBjaGVjayhcbiAgICAgICAgICBpbWcud2lkdGggPT09IG13ICYmXG4gICAgICAgICAgaW1nLmhlaWdodCA9PT0gbWgsXG4gICAgICAgICAgJ2ludmFsaWQgc2hhcGUgZm9yIG1pcCBpbWFnZXMnKTtcbiAgICAgICAgY2hlY2soXG4gICAgICAgICAgaW1nLmZvcm1hdCA9PT0gdGV4dHVyZS5mb3JtYXQgJiZcbiAgICAgICAgICBpbWcuaW50ZXJuYWxmb3JtYXQgPT09IHRleHR1cmUuaW50ZXJuYWxmb3JtYXQgJiZcbiAgICAgICAgICBpbWcudHlwZSA9PT0gdGV4dHVyZS50eXBlLFxuICAgICAgICAgICdpbmNvbXBhdGlibGUgdHlwZSBmb3IgbWlwIGltYWdlJyk7XG5cbiAgICAgICAgaWYgKGltZy5jb21wcmVzc2VkKSB7XG4gICAgICAgICAgLy8gVE9ETzogY2hlY2sgc2l6ZSBmb3IgY29tcHJlc3NlZCBpbWFnZXNcbiAgICAgICAgfSBlbHNlIGlmIChpbWcuZGF0YSkge1xuICAgICAgICAgIGNoZWNrKGltZy5kYXRhLmJ5dGVMZW5ndGggPT09IG13ICogbWggKlxuICAgICAgICAgICAgTWF0aC5tYXgocGl4ZWxTaXplKGltZy50eXBlLCBjKSwgaW1nLnVucGFja0FsaWdubWVudCksXG4gICAgICAgICAgICAnaW52YWxpZCBkYXRhIGZvciBpbWFnZSwgYnVmZmVyIHNpemUgaXMgaW5jb25zaXN0ZW50IHdpdGggaW1hZ2UgZm9ybWF0Jyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaW1nLmVsZW1lbnQpIHtcbiAgICAgICAgICAvLyBUT0RPOiBjaGVjayBlbGVtZW50IGNhbiBiZSBsb2FkZWRcbiAgICAgICAgfSBlbHNlIGlmIChpbWcuY29weSkge1xuICAgICAgICAgIC8vIFRPRE86IGNoZWNrIGNvbXBhdGlibGUgZm9ybWF0IGFuZCB0eXBlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxudmFyIGNoZWNrJDEgPSBleHRlbmQoY2hlY2ssIHtcbiAgb3B0aW9uYWw6IGNoZWNrT3B0aW9uYWwsXG4gIHJhaXNlOiByYWlzZSxcbiAgY29tbWFuZFJhaXNlOiBjb21tYW5kUmFpc2UsXG4gIGNvbW1hbmQ6IGNoZWNrQ29tbWFuZCxcbiAgcGFyYW1ldGVyOiBjaGVja1BhcmFtZXRlcixcbiAgY29tbWFuZFBhcmFtZXRlcjogY2hlY2tQYXJhbWV0ZXJDb21tYW5kLFxuICBjb25zdHJ1Y3RvcjogY2hlY2tDb25zdHJ1Y3RvcixcbiAgdHlwZTogY2hlY2tUeXBlT2YsXG4gIGNvbW1hbmRUeXBlOiBjaGVja0NvbW1hbmRUeXBlLFxuICBpc1R5cGVkQXJyYXk6IGNoZWNrSXNUeXBlZEFycmF5LFxuICBubmk6IGNoZWNrTm9uTmVnYXRpdmVJbnQsXG4gIG9uZU9mOiBjaGVja09uZU9mLFxuICBzaGFkZXJFcnJvcjogY2hlY2tTaGFkZXJFcnJvcixcbiAgbGlua0Vycm9yOiBjaGVja0xpbmtFcnJvcixcbiAgY2FsbFNpdGU6IGd1ZXNzQ2FsbFNpdGUsXG4gIHNhdmVDb21tYW5kUmVmOiBzYXZlQ29tbWFuZFJlZixcbiAgc2F2ZURyYXdJbmZvOiBzYXZlRHJhd0NvbW1hbmRJbmZvLFxuICBmcmFtZWJ1ZmZlckZvcm1hdDogY2hlY2tGcmFtZWJ1ZmZlckZvcm1hdCxcbiAgZ3Vlc3NDb21tYW5kOiBndWVzc0NvbW1hbmQsXG4gIHRleHR1cmUyRDogY2hlY2tUZXh0dXJlMkQsXG4gIHRleHR1cmVDdWJlOiBjaGVja1RleHR1cmVDdWJlXG59KTtcblxudmFyIFZBUklBQkxFX0NPVU5URVIgPSAwO1xuXG52YXIgRFlOX0ZVTkMgPSAwO1xuXG5mdW5jdGlvbiBEeW5hbWljVmFyaWFibGUgKHR5cGUsIGRhdGEpIHtcbiAgdGhpcy5pZCA9IChWQVJJQUJMRV9DT1VOVEVSKyspO1xuICB0aGlzLnR5cGUgPSB0eXBlO1xuICB0aGlzLmRhdGEgPSBkYXRhO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVTdHIgKHN0cikge1xuICByZXR1cm4gc3RyLnJlcGxhY2UoL1xcXFwvZywgJ1xcXFxcXFxcJykucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpXG59XG5cbmZ1bmN0aW9uIHNwbGl0UGFydHMgKHN0cikge1xuICBpZiAoc3RyLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG5cbiAgdmFyIGZpcnN0Q2hhciA9IHN0ci5jaGFyQXQoMCk7XG4gIHZhciBsYXN0Q2hhciA9IHN0ci5jaGFyQXQoc3RyLmxlbmd0aCAtIDEpO1xuXG4gIGlmIChzdHIubGVuZ3RoID4gMSAmJlxuICAgICAgZmlyc3RDaGFyID09PSBsYXN0Q2hhciAmJlxuICAgICAgKGZpcnN0Q2hhciA9PT0gJ1wiJyB8fCBmaXJzdENoYXIgPT09IFwiJ1wiKSkge1xuICAgIHJldHVybiBbJ1wiJyArIGVzY2FwZVN0cihzdHIuc3Vic3RyKDEsIHN0ci5sZW5ndGggLSAyKSkgKyAnXCInXVxuICB9XG5cbiAgdmFyIHBhcnRzID0gL1xcWyhmYWxzZXx0cnVlfG51bGx8XFxkK3wnW14nXSonfFwiW15cIl0qXCIpXFxdLy5leGVjKHN0cik7XG4gIGlmIChwYXJ0cykge1xuICAgIHJldHVybiAoXG4gICAgICBzcGxpdFBhcnRzKHN0ci5zdWJzdHIoMCwgcGFydHMuaW5kZXgpKVxuICAgICAgLmNvbmNhdChzcGxpdFBhcnRzKHBhcnRzWzFdKSlcbiAgICAgIC5jb25jYXQoc3BsaXRQYXJ0cyhzdHIuc3Vic3RyKHBhcnRzLmluZGV4ICsgcGFydHNbMF0ubGVuZ3RoKSkpXG4gICAgKVxuICB9XG5cbiAgdmFyIHN1YnBhcnRzID0gc3RyLnNwbGl0KCcuJyk7XG4gIGlmIChzdWJwYXJ0cy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gWydcIicgKyBlc2NhcGVTdHIoc3RyKSArICdcIiddXG4gIH1cblxuICB2YXIgcmVzdWx0ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3VicGFydHMubGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHNwbGl0UGFydHMoc3VicGFydHNbaV0pKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHRvQWNjZXNzb3JTdHJpbmcgKHN0cikge1xuICByZXR1cm4gJ1snICsgc3BsaXRQYXJ0cyhzdHIpLmpvaW4oJ11bJykgKyAnXSdcbn1cblxuZnVuY3Rpb24gZGVmaW5lRHluYW1pYyAodHlwZSwgZGF0YSkge1xuICByZXR1cm4gbmV3IER5bmFtaWNWYXJpYWJsZSh0eXBlLCB0b0FjY2Vzc29yU3RyaW5nKGRhdGEgKyAnJykpXG59XG5cbmZ1bmN0aW9uIGlzRHluYW1pYyAoeCkge1xuICByZXR1cm4gKHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nICYmICF4Ll9yZWdsVHlwZSkgfHxcbiAgICAgICAgIHggaW5zdGFuY2VvZiBEeW5hbWljVmFyaWFibGVcbn1cblxuZnVuY3Rpb24gdW5ib3ggKHgsIHBhdGgpIHtcbiAgaWYgKHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIG5ldyBEeW5hbWljVmFyaWFibGUoRFlOX0ZVTkMsIHgpXG4gIH1cbiAgcmV0dXJuIHhcbn1cblxudmFyIGR5bmFtaWMgPSB7XG4gIER5bmFtaWNWYXJpYWJsZTogRHluYW1pY1ZhcmlhYmxlLFxuICBkZWZpbmU6IGRlZmluZUR5bmFtaWMsXG4gIGlzRHluYW1pYzogaXNEeW5hbWljLFxuICB1bmJveDogdW5ib3gsXG4gIGFjY2Vzc29yOiB0b0FjY2Vzc29yU3RyaW5nXG59O1xuXG4vKiBnbG9iYWxzIHJlcXVlc3RBbmltYXRpb25GcmFtZSwgY2FuY2VsQW5pbWF0aW9uRnJhbWUgKi9cbnZhciByYWYgPSB7XG4gIG5leHQ6IHR5cGVvZiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPT09ICdmdW5jdGlvbidcbiAgICA/IGZ1bmN0aW9uIChjYikgeyByZXR1cm4gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGNiKSB9XG4gICAgOiBmdW5jdGlvbiAoY2IpIHsgcmV0dXJuIHNldFRpbWVvdXQoY2IsIDE2KSB9LFxuICBjYW5jZWw6IHR5cGVvZiBjYW5jZWxBbmltYXRpb25GcmFtZSA9PT0gJ2Z1bmN0aW9uJ1xuICAgID8gZnVuY3Rpb24gKHJhZikgeyByZXR1cm4gY2FuY2VsQW5pbWF0aW9uRnJhbWUocmFmKSB9XG4gICAgOiBjbGVhclRpbWVvdXRcbn07XG5cbi8qIGdsb2JhbHMgcGVyZm9ybWFuY2UgKi9cbnZhciBjbG9jayA9ICh0eXBlb2YgcGVyZm9ybWFuY2UgIT09ICd1bmRlZmluZWQnICYmIHBlcmZvcm1hbmNlLm5vdylcbiAgPyBmdW5jdGlvbiAoKSB7IHJldHVybiBwZXJmb3JtYW5jZS5ub3coKSB9XG4gIDogZnVuY3Rpb24gKCkgeyByZXR1cm4gKyhuZXcgRGF0ZSgpKSB9O1xuXG5mdW5jdGlvbiBjcmVhdGVTdHJpbmdTdG9yZSAoKSB7XG4gIHZhciBzdHJpbmdJZHMgPSB7Jyc6IDB9O1xuICB2YXIgc3RyaW5nVmFsdWVzID0gWycnXTtcbiAgcmV0dXJuIHtcbiAgICBpZDogZnVuY3Rpb24gKHN0cikge1xuICAgICAgdmFyIHJlc3VsdCA9IHN0cmluZ0lkc1tzdHJdO1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICB9XG4gICAgICByZXN1bHQgPSBzdHJpbmdJZHNbc3RyXSA9IHN0cmluZ1ZhbHVlcy5sZW5ndGg7XG4gICAgICBzdHJpbmdWYWx1ZXMucHVzaChzdHIpO1xuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH0sXG5cbiAgICBzdHI6IGZ1bmN0aW9uIChpZCkge1xuICAgICAgcmV0dXJuIHN0cmluZ1ZhbHVlc1tpZF1cbiAgICB9XG4gIH1cbn1cblxuLy8gQ29udGV4dCBhbmQgY2FudmFzIGNyZWF0aW9uIGhlbHBlciBmdW5jdGlvbnNcbmZ1bmN0aW9uIGNyZWF0ZUNhbnZhcyAoZWxlbWVudCwgb25Eb25lLCBwaXhlbFJhdGlvKSB7XG4gIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgZXh0ZW5kKGNhbnZhcy5zdHlsZSwge1xuICAgIGJvcmRlcjogMCxcbiAgICBtYXJnaW46IDAsXG4gICAgcGFkZGluZzogMCxcbiAgICB0b3A6IDAsXG4gICAgbGVmdDogMFxuICB9KTtcbiAgZWxlbWVudC5hcHBlbmRDaGlsZChjYW52YXMpO1xuXG4gIGlmIChlbGVtZW50ID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgY2FudmFzLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBleHRlbmQoZWxlbWVudC5zdHlsZSwge1xuICAgICAgbWFyZ2luOiAwLFxuICAgICAgcGFkZGluZzogMFxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzaXplICgpIHtcbiAgICB2YXIgdyA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgIHZhciBoID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgIGlmIChlbGVtZW50ICE9PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICB2YXIgYm91bmRzID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHcgPSBib3VuZHMucmlnaHQgLSBib3VuZHMubGVmdDtcbiAgICAgIGggPSBib3VuZHMuYm90dG9tIC0gYm91bmRzLnRvcDtcbiAgICB9XG4gICAgY2FudmFzLndpZHRoID0gcGl4ZWxSYXRpbyAqIHc7XG4gICAgY2FudmFzLmhlaWdodCA9IHBpeGVsUmF0aW8gKiBoO1xuICAgIGV4dGVuZChjYW52YXMuc3R5bGUsIHtcbiAgICAgIHdpZHRoOiB3ICsgJ3B4JyxcbiAgICAgIGhlaWdodDogaCArICdweCdcbiAgICB9KTtcbiAgfVxuXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUsIGZhbHNlKTtcblxuICBmdW5jdGlvbiBvbkRlc3Ryb3kgKCkge1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUpO1xuICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQoY2FudmFzKTtcbiAgfVxuXG4gIHJlc2l6ZSgpO1xuXG4gIHJldHVybiB7XG4gICAgY2FudmFzOiBjYW52YXMsXG4gICAgb25EZXN0cm95OiBvbkRlc3Ryb3lcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVDb250ZXh0IChjYW52YXMsIGNvbnRleHRBdHRyaWJ1dGVzKSB7XG4gIGZ1bmN0aW9uIGdldCAobmFtZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gY2FudmFzLmdldENvbnRleHQobmFtZSwgY29udGV4dEF0dHJpYnV0ZXMpXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gIH1cbiAgcmV0dXJuIChcbiAgICBnZXQoJ3dlYmdsJykgfHxcbiAgICBnZXQoJ2V4cGVyaW1lbnRhbC13ZWJnbCcpIHx8XG4gICAgZ2V0KCd3ZWJnbC1leHBlcmltZW50YWwnKVxuICApXG59XG5cbmZ1bmN0aW9uIGlzSFRNTEVsZW1lbnQgKG9iaikge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvYmoubm9kZU5hbWUgPT09ICdzdHJpbmcnICYmXG4gICAgdHlwZW9mIG9iai5hcHBlbmRDaGlsZCA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgIHR5cGVvZiBvYmouZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID09PSAnZnVuY3Rpb24nXG4gIClcbn1cblxuZnVuY3Rpb24gaXNXZWJHTENvbnRleHQgKG9iaikge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvYmouZHJhd0FycmF5cyA9PT0gJ2Z1bmN0aW9uJyB8fFxuICAgIHR5cGVvZiBvYmouZHJhd0VsZW1lbnRzID09PSAnZnVuY3Rpb24nXG4gIClcbn1cblxuZnVuY3Rpb24gcGFyc2VFeHRlbnNpb25zIChpbnB1dCkge1xuICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBpbnB1dC5zcGxpdCgpXG4gIH1cbiAgY2hlY2skMShBcnJheS5pc0FycmF5KGlucHV0KSwgJ2ludmFsaWQgZXh0ZW5zaW9uIGFycmF5Jyk7XG4gIHJldHVybiBpbnB1dFxufVxuXG5mdW5jdGlvbiBnZXRFbGVtZW50IChkZXNjKSB7XG4gIGlmICh0eXBlb2YgZGVzYyA9PT0gJ3N0cmluZycpIHtcbiAgICBjaGVjayQxKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcsICdub3Qgc3VwcG9ydGVkIG91dHNpZGUgb2YgRE9NJyk7XG4gICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZGVzYylcbiAgfVxuICByZXR1cm4gZGVzY1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MgKGFyZ3NfKSB7XG4gIHZhciBhcmdzID0gYXJnc18gfHwge307XG4gIHZhciBlbGVtZW50LCBjb250YWluZXIsIGNhbnZhcywgZ2w7XG4gIHZhciBjb250ZXh0QXR0cmlidXRlcyA9IHt9O1xuICB2YXIgZXh0ZW5zaW9ucyA9IFtdO1xuICB2YXIgb3B0aW9uYWxFeHRlbnNpb25zID0gW107XG4gIHZhciBwaXhlbFJhdGlvID0gKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnID8gMSA6IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvKTtcbiAgdmFyIHByb2ZpbGUgPSBmYWxzZTtcbiAgdmFyIG9uRG9uZSA9IGZ1bmN0aW9uIChlcnIpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICBjaGVjayQxLnJhaXNlKGVycik7XG4gICAgfVxuICB9O1xuICB2YXIgb25EZXN0cm95ID0gZnVuY3Rpb24gKCkge307XG4gIGlmICh0eXBlb2YgYXJncyA9PT0gJ3N0cmluZycpIHtcbiAgICBjaGVjayQxKFxuICAgICAgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyxcbiAgICAgICdzZWxlY3RvciBxdWVyaWVzIG9ubHkgc3VwcG9ydGVkIGluIERPTSBlbnZpcm9tZW50cycpO1xuICAgIGVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZ3MpO1xuICAgIGNoZWNrJDEoZWxlbWVudCwgJ2ludmFsaWQgcXVlcnkgc3RyaW5nIGZvciBlbGVtZW50Jyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGFyZ3MgPT09ICdvYmplY3QnKSB7XG4gICAgaWYgKGlzSFRNTEVsZW1lbnQoYXJncykpIHtcbiAgICAgIGVsZW1lbnQgPSBhcmdzO1xuICAgIH0gZWxzZSBpZiAoaXNXZWJHTENvbnRleHQoYXJncykpIHtcbiAgICAgIGdsID0gYXJncztcbiAgICAgIGNhbnZhcyA9IGdsLmNhbnZhcztcbiAgICB9IGVsc2Uge1xuICAgICAgY2hlY2skMS5jb25zdHJ1Y3RvcihhcmdzKTtcbiAgICAgIGlmICgnZ2wnIGluIGFyZ3MpIHtcbiAgICAgICAgZ2wgPSBhcmdzLmdsO1xuICAgICAgfSBlbHNlIGlmICgnY2FudmFzJyBpbiBhcmdzKSB7XG4gICAgICAgIGNhbnZhcyA9IGdldEVsZW1lbnQoYXJncy5jYW52YXMpO1xuICAgICAgfSBlbHNlIGlmICgnY29udGFpbmVyJyBpbiBhcmdzKSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGdldEVsZW1lbnQoYXJncy5jb250YWluZXIpO1xuICAgICAgfVxuICAgICAgaWYgKCdhdHRyaWJ1dGVzJyBpbiBhcmdzKSB7XG4gICAgICAgIGNvbnRleHRBdHRyaWJ1dGVzID0gYXJncy5hdHRyaWJ1dGVzO1xuICAgICAgICBjaGVjayQxLnR5cGUoY29udGV4dEF0dHJpYnV0ZXMsICdvYmplY3QnLCAnaW52YWxpZCBjb250ZXh0IGF0dHJpYnV0ZXMnKTtcbiAgICAgIH1cbiAgICAgIGlmICgnZXh0ZW5zaW9ucycgaW4gYXJncykge1xuICAgICAgICBleHRlbnNpb25zID0gcGFyc2VFeHRlbnNpb25zKGFyZ3MuZXh0ZW5zaW9ucyk7XG4gICAgICB9XG4gICAgICBpZiAoJ29wdGlvbmFsRXh0ZW5zaW9ucycgaW4gYXJncykge1xuICAgICAgICBvcHRpb25hbEV4dGVuc2lvbnMgPSBwYXJzZUV4dGVuc2lvbnMoYXJncy5vcHRpb25hbEV4dGVuc2lvbnMpO1xuICAgICAgfVxuICAgICAgaWYgKCdvbkRvbmUnIGluIGFyZ3MpIHtcbiAgICAgICAgY2hlY2skMS50eXBlKFxuICAgICAgICAgIGFyZ3Mub25Eb25lLCAnZnVuY3Rpb24nLFxuICAgICAgICAgICdpbnZhbGlkIG9yIG1pc3Npbmcgb25Eb25lIGNhbGxiYWNrJyk7XG4gICAgICAgIG9uRG9uZSA9IGFyZ3Mub25Eb25lO1xuICAgICAgfVxuICAgICAgaWYgKCdwcm9maWxlJyBpbiBhcmdzKSB7XG4gICAgICAgIHByb2ZpbGUgPSAhIWFyZ3MucHJvZmlsZTtcbiAgICAgIH1cbiAgICAgIGlmICgncGl4ZWxSYXRpbycgaW4gYXJncykge1xuICAgICAgICBwaXhlbFJhdGlvID0gK2FyZ3MucGl4ZWxSYXRpbztcbiAgICAgICAgY2hlY2skMShwaXhlbFJhdGlvID4gMCwgJ2ludmFsaWQgcGl4ZWwgcmF0aW8nKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBhcmd1bWVudHMgdG8gcmVnbCcpO1xuICB9XG5cbiAgaWYgKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnY2FudmFzJykge1xuICAgICAgY2FudmFzID0gZWxlbWVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGFpbmVyID0gZWxlbWVudDtcbiAgICB9XG4gIH1cblxuICBpZiAoIWdsKSB7XG4gICAgaWYgKCFjYW52YXMpIHtcbiAgICAgIGNoZWNrJDEoXG4gICAgICAgIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICdtdXN0IG1hbnVhbGx5IHNwZWNpZnkgd2ViZ2wgY29udGV4dCBvdXRzaWRlIG9mIERPTSBlbnZpcm9ubWVudHMnKTtcbiAgICAgIHZhciByZXN1bHQgPSBjcmVhdGVDYW52YXMoY29udGFpbmVyIHx8IGRvY3VtZW50LmJvZHksIG9uRG9uZSwgcGl4ZWxSYXRpbyk7XG4gICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuICAgICAgY2FudmFzID0gcmVzdWx0LmNhbnZhcztcbiAgICAgIG9uRGVzdHJveSA9IHJlc3VsdC5vbkRlc3Ryb3k7XG4gICAgfVxuICAgIGdsID0gY3JlYXRlQ29udGV4dChjYW52YXMsIGNvbnRleHRBdHRyaWJ1dGVzKTtcbiAgfVxuXG4gIGlmICghZ2wpIHtcbiAgICBvbkRlc3Ryb3koKTtcbiAgICBvbkRvbmUoJ3dlYmdsIG5vdCBzdXBwb3J0ZWQsIHRyeSB1cGdyYWRpbmcgeW91ciBicm93c2VyIG9yIGdyYXBoaWNzIGRyaXZlcnMgaHR0cDovL2dldC53ZWJnbC5vcmcnKTtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBnbDogZ2wsXG4gICAgY2FudmFzOiBjYW52YXMsXG4gICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgZXh0ZW5zaW9uczogZXh0ZW5zaW9ucyxcbiAgICBvcHRpb25hbEV4dGVuc2lvbnM6IG9wdGlvbmFsRXh0ZW5zaW9ucyxcbiAgICBwaXhlbFJhdGlvOiBwaXhlbFJhdGlvLFxuICAgIHByb2ZpbGU6IHByb2ZpbGUsXG4gICAgb25Eb25lOiBvbkRvbmUsXG4gICAgb25EZXN0cm95OiBvbkRlc3Ryb3lcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVFeHRlbnNpb25DYWNoZSAoZ2wsIGNvbmZpZykge1xuICB2YXIgZXh0ZW5zaW9ucyA9IHt9O1xuXG4gIGZ1bmN0aW9uIHRyeUxvYWRFeHRlbnNpb24gKG5hbWVfKSB7XG4gICAgY2hlY2skMS50eXBlKG5hbWVfLCAnc3RyaW5nJywgJ2V4dGVuc2lvbiBuYW1lIG11c3QgYmUgc3RyaW5nJyk7XG4gICAgdmFyIG5hbWUgPSBuYW1lXy50b0xvd2VyQ2FzZSgpO1xuICAgIHZhciBleHQ7XG4gICAgdHJ5IHtcbiAgICAgIGV4dCA9IGV4dGVuc2lvbnNbbmFtZV0gPSBnbC5nZXRFeHRlbnNpb24obmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge31cbiAgICByZXR1cm4gISFleHRcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY29uZmlnLmV4dGVuc2lvbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgbmFtZSA9IGNvbmZpZy5leHRlbnNpb25zW2ldO1xuICAgIGlmICghdHJ5TG9hZEV4dGVuc2lvbihuYW1lKSkge1xuICAgICAgY29uZmlnLm9uRGVzdHJveSgpO1xuICAgICAgY29uZmlnLm9uRG9uZSgnXCInICsgbmFtZSArICdcIiBleHRlbnNpb24gaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY3VycmVudCBXZWJHTCBjb250ZXh0LCB0cnkgdXBncmFkaW5nIHlvdXIgc3lzdGVtIG9yIGEgZGlmZmVyZW50IGJyb3dzZXInKTtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICB9XG5cbiAgY29uZmlnLm9wdGlvbmFsRXh0ZW5zaW9ucy5mb3JFYWNoKHRyeUxvYWRFeHRlbnNpb24pO1xuXG4gIHJldHVybiB7XG4gICAgZXh0ZW5zaW9uczogZXh0ZW5zaW9ucyxcbiAgICByZXN0b3JlOiBmdW5jdGlvbiAoKSB7XG4gICAgICBPYmplY3Qua2V5cyhleHRlbnNpb25zKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGlmICghdHJ5TG9hZEV4dGVuc2lvbihuYW1lKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignKHJlZ2wpOiBlcnJvciByZXN0b3JpbmcgZXh0ZW5zaW9uICcgKyBuYW1lKVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gbG9vcCAobiwgZikge1xuICB2YXIgcmVzdWx0ID0gQXJyYXkobik7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gZihpKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbnZhciBHTF9CWVRFJDEgPSA1MTIwO1xudmFyIEdMX1VOU0lHTkVEX0JZVEUkMiA9IDUxMjE7XG52YXIgR0xfU0hPUlQkMSA9IDUxMjI7XG52YXIgR0xfVU5TSUdORURfU0hPUlQkMSA9IDUxMjM7XG52YXIgR0xfSU5UJDEgPSA1MTI0O1xudmFyIEdMX1VOU0lHTkVEX0lOVCQxID0gNTEyNTtcbnZhciBHTF9GTE9BVCQyID0gNTEyNjtcblxuZnVuY3Rpb24gbmV4dFBvdzE2ICh2KSB7XG4gIGZvciAodmFyIGkgPSAxNjsgaSA8PSAoMSA8PCAyOCk7IGkgKj0gMTYpIHtcbiAgICBpZiAodiA8PSBpKSB7XG4gICAgICByZXR1cm4gaVxuICAgIH1cbiAgfVxuICByZXR1cm4gMFxufVxuXG5mdW5jdGlvbiBsb2cyICh2KSB7XG4gIHZhciByLCBzaGlmdDtcbiAgciA9ICh2ID4gMHhGRkZGKSA8PCA0O1xuICB2ID4+Pj0gcjtcbiAgc2hpZnQgPSAodiA+IDB4RkYpIDw8IDM7XG4gIHYgPj4+PSBzaGlmdDsgciB8PSBzaGlmdDtcbiAgc2hpZnQgPSAodiA+IDB4RikgPDwgMjtcbiAgdiA+Pj49IHNoaWZ0OyByIHw9IHNoaWZ0O1xuICBzaGlmdCA9ICh2ID4gMHgzKSA8PCAxO1xuICB2ID4+Pj0gc2hpZnQ7IHIgfD0gc2hpZnQ7XG4gIHJldHVybiByIHwgKHYgPj4gMSlcbn1cblxuZnVuY3Rpb24gY3JlYXRlUG9vbCAoKSB7XG4gIHZhciBidWZmZXJQb29sID0gbG9vcCg4LCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFtdXG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGFsbG9jIChuKSB7XG4gICAgdmFyIHN6ID0gbmV4dFBvdzE2KG4pO1xuICAgIHZhciBiaW4gPSBidWZmZXJQb29sW2xvZzIoc3opID4+IDJdO1xuICAgIGlmIChiaW4ubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIGJpbi5wb3AoKVxuICAgIH1cbiAgICByZXR1cm4gbmV3IEFycmF5QnVmZmVyKHN6KVxuICB9XG5cbiAgZnVuY3Rpb24gZnJlZSAoYnVmKSB7XG4gICAgYnVmZmVyUG9vbFtsb2cyKGJ1Zi5ieXRlTGVuZ3RoKSA+PiAyXS5wdXNoKGJ1Zik7XG4gIH1cblxuICBmdW5jdGlvbiBhbGxvY1R5cGUgKHR5cGUsIG4pIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVsbDtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgR0xfQllURSQxOlxuICAgICAgICByZXN1bHQgPSBuZXcgSW50OEFycmF5KGFsbG9jKG4pLCAwLCBuKTtcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgR0xfVU5TSUdORURfQllURSQyOlxuICAgICAgICByZXN1bHQgPSBuZXcgVWludDhBcnJheShhbGxvYyhuKSwgMCwgbik7XG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIEdMX1NIT1JUJDE6XG4gICAgICAgIHJlc3VsdCA9IG5ldyBJbnQxNkFycmF5KGFsbG9jKDIgKiBuKSwgMCwgbik7XG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIEdMX1VOU0lHTkVEX1NIT1JUJDE6XG4gICAgICAgIHJlc3VsdCA9IG5ldyBVaW50MTZBcnJheShhbGxvYygyICogbiksIDAsIG4pO1xuICAgICAgICBicmVha1xuICAgICAgY2FzZSBHTF9JTlQkMTpcbiAgICAgICAgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkoYWxsb2MoNCAqIG4pLCAwLCBuKTtcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgR0xfVU5TSUdORURfSU5UJDE6XG4gICAgICAgIHJlc3VsdCA9IG5ldyBVaW50MzJBcnJheShhbGxvYyg0ICogbiksIDAsIG4pO1xuICAgICAgICBicmVha1xuICAgICAgY2FzZSBHTF9GTE9BVCQyOlxuICAgICAgICByZXN1bHQgPSBuZXcgRmxvYXQzMkFycmF5KGFsbG9jKDQgKiBuKSwgMCwgbik7XG4gICAgICAgIGJyZWFrXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gbikge1xuICAgICAgcmV0dXJuIHJlc3VsdC5zdWJhcnJheSgwLCBuKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBmdW5jdGlvbiBmcmVlVHlwZSAoYXJyYXkpIHtcbiAgICBmcmVlKGFycmF5LmJ1ZmZlcik7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFsbG9jOiBhbGxvYyxcbiAgICBmcmVlOiBmcmVlLFxuICAgIGFsbG9jVHlwZTogYWxsb2NUeXBlLFxuICAgIGZyZWVUeXBlOiBmcmVlVHlwZVxuICB9XG59XG5cbnZhciBwb29sID0gY3JlYXRlUG9vbCgpO1xuXG4vLyB6ZXJvIHBvb2wgZm9yIGluaXRpYWwgemVybyBkYXRhXG5wb29sLnplcm8gPSBjcmVhdGVQb29sKCk7XG5cbnZhciBHTF9TVUJQSVhFTF9CSVRTID0gMHgwRDUwO1xudmFyIEdMX1JFRF9CSVRTID0gMHgwRDUyO1xudmFyIEdMX0dSRUVOX0JJVFMgPSAweDBENTM7XG52YXIgR0xfQkxVRV9CSVRTID0gMHgwRDU0O1xudmFyIEdMX0FMUEhBX0JJVFMgPSAweDBENTU7XG52YXIgR0xfREVQVEhfQklUUyA9IDB4MEQ1NjtcbnZhciBHTF9TVEVOQ0lMX0JJVFMgPSAweDBENTc7XG5cbnZhciBHTF9BTElBU0VEX1BPSU5UX1NJWkVfUkFOR0UgPSAweDg0NkQ7XG52YXIgR0xfQUxJQVNFRF9MSU5FX1dJRFRIX1JBTkdFID0gMHg4NDZFO1xuXG52YXIgR0xfTUFYX1RFWFRVUkVfU0laRSA9IDB4MEQzMztcbnZhciBHTF9NQVhfVklFV1BPUlRfRElNUyA9IDB4MEQzQTtcbnZhciBHTF9NQVhfVkVSVEVYX0FUVFJJQlMgPSAweDg4Njk7XG52YXIgR0xfTUFYX1ZFUlRFWF9VTklGT1JNX1ZFQ1RPUlMgPSAweDhERkI7XG52YXIgR0xfTUFYX1ZBUllJTkdfVkVDVE9SUyA9IDB4OERGQztcbnZhciBHTF9NQVhfQ09NQklORURfVEVYVFVSRV9JTUFHRV9VTklUUyA9IDB4OEI0RDtcbnZhciBHTF9NQVhfVkVSVEVYX1RFWFRVUkVfSU1BR0VfVU5JVFMgPSAweDhCNEM7XG52YXIgR0xfTUFYX1RFWFRVUkVfSU1BR0VfVU5JVFMgPSAweDg4NzI7XG52YXIgR0xfTUFYX0ZSQUdNRU5UX1VOSUZPUk1fVkVDVE9SUyA9IDB4OERGRDtcbnZhciBHTF9NQVhfQ1VCRV9NQVBfVEVYVFVSRV9TSVpFID0gMHg4NTFDO1xudmFyIEdMX01BWF9SRU5ERVJCVUZGRVJfU0laRSA9IDB4ODRFODtcblxudmFyIEdMX1ZFTkRPUiA9IDB4MUYwMDtcbnZhciBHTF9SRU5ERVJFUiA9IDB4MUYwMTtcbnZhciBHTF9WRVJTSU9OID0gMHgxRjAyO1xudmFyIEdMX1NIQURJTkdfTEFOR1VBR0VfVkVSU0lPTiA9IDB4OEI4QztcblxudmFyIEdMX01BWF9URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCA9IDB4ODRGRjtcblxudmFyIEdMX01BWF9DT0xPUl9BVFRBQ0hNRU5UU19XRUJHTCA9IDB4OENERjtcbnZhciBHTF9NQVhfRFJBV19CVUZGRVJTX1dFQkdMID0gMHg4ODI0O1xuXG52YXIgR0xfVEVYVFVSRV8yRCA9IDB4MERFMTtcbnZhciBHTF9URVhUVVJFX0NVQkVfTUFQID0gMHg4NTEzO1xudmFyIEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCA9IDB4ODUxNTtcbnZhciBHTF9URVhUVVJFMCA9IDB4ODRDMDtcbnZhciBHTF9SR0JBID0gMHgxOTA4O1xudmFyIEdMX0ZMT0FUJDEgPSAweDE0MDY7XG52YXIgR0xfVU5TSUdORURfQllURSQxID0gMHgxNDAxO1xudmFyIEdMX0ZSQU1FQlVGRkVSID0gMHg4RDQwO1xudmFyIEdMX0ZSQU1FQlVGRkVSX0NPTVBMRVRFID0gMHg4Q0Q1O1xudmFyIEdMX0NPTE9SX0FUVEFDSE1FTlQwID0gMHg4Q0UwO1xudmFyIEdMX0NPTE9SX0JVRkZFUl9CSVQkMSA9IDB4NDAwMDtcblxudmFyIHdyYXBMaW1pdHMgPSBmdW5jdGlvbiAoZ2wsIGV4dGVuc2lvbnMpIHtcbiAgdmFyIG1heEFuaXNvdHJvcGljID0gMTtcbiAgaWYgKGV4dGVuc2lvbnMuZXh0X3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljKSB7XG4gICAgbWF4QW5pc290cm9waWMgPSBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1RFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhUKTtcbiAgfVxuXG4gIHZhciBtYXhEcmF3YnVmZmVycyA9IDE7XG4gIHZhciBtYXhDb2xvckF0dGFjaG1lbnRzID0gMTtcbiAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfZHJhd19idWZmZXJzKSB7XG4gICAgbWF4RHJhd2J1ZmZlcnMgPSBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0RSQVdfQlVGRkVSU19XRUJHTCk7XG4gICAgbWF4Q29sb3JBdHRhY2htZW50cyA9IGdsLmdldFBhcmFtZXRlcihHTF9NQVhfQ09MT1JfQVRUQUNITUVOVFNfV0VCR0wpO1xuICB9XG5cbiAgLy8gZGV0ZWN0IGlmIHJlYWRpbmcgZmxvYXQgdGV4dHVyZXMgaXMgYXZhaWxhYmxlIChTYWZhcmkgZG9lc24ndCBzdXBwb3J0KVxuICB2YXIgcmVhZEZsb2F0ID0gISFleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0O1xuICBpZiAocmVhZEZsb2F0KSB7XG4gICAgdmFyIHJlYWRGbG9hdFRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV8yRCwgcmVhZEZsb2F0VGV4dHVyZSk7XG4gICAgZ2wudGV4SW1hZ2UyRChHTF9URVhUVVJFXzJELCAwLCBHTF9SR0JBLCAxLCAxLCAwLCBHTF9SR0JBLCBHTF9GTE9BVCQxLCBudWxsKTtcblxuICAgIHZhciBmYm8gPSBnbC5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihHTF9GUkFNRUJVRkZFUiwgZmJvKTtcbiAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChHTF9GUkFNRUJVRkZFUiwgR0xfQ09MT1JfQVRUQUNITUVOVDAsIEdMX1RFWFRVUkVfMkQsIHJlYWRGbG9hdFRleHR1cmUsIDApO1xuICAgIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfMkQsIG51bGwpO1xuXG4gICAgaWYgKGdsLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoR0xfRlJBTUVCVUZGRVIpICE9PSBHTF9GUkFNRUJVRkZFUl9DT01QTEVURSkgcmVhZEZsb2F0ID0gZmFsc2U7XG5cbiAgICBlbHNlIHtcbiAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIDEsIDEpO1xuICAgICAgZ2wuY2xlYXJDb2xvcigxLjAsIDAuMCwgMC4wLCAxLjApO1xuICAgICAgZ2wuY2xlYXIoR0xfQ09MT1JfQlVGRkVSX0JJVCQxKTtcbiAgICAgIHZhciBwaXhlbHMgPSBwb29sLmFsbG9jVHlwZShHTF9GTE9BVCQxLCA0KTtcbiAgICAgIGdsLnJlYWRQaXhlbHMoMCwgMCwgMSwgMSwgR0xfUkdCQSwgR0xfRkxPQVQkMSwgcGl4ZWxzKTtcblxuICAgICAgaWYgKGdsLmdldEVycm9yKCkpIHJlYWRGbG9hdCA9IGZhbHNlO1xuICAgICAgZWxzZSB7XG4gICAgICAgIGdsLmRlbGV0ZUZyYW1lYnVmZmVyKGZibyk7XG4gICAgICAgIGdsLmRlbGV0ZVRleHR1cmUocmVhZEZsb2F0VGV4dHVyZSk7XG5cbiAgICAgICAgcmVhZEZsb2F0ID0gcGl4ZWxzWzBdID09PSAxLjA7XG4gICAgICB9XG5cbiAgICAgIHBvb2wuZnJlZVR5cGUocGl4ZWxzKTtcbiAgICB9XG4gIH1cblxuICAvLyBkZXRlY3Qgbm9uIHBvd2VyIG9mIHR3byBjdWJlIHRleHR1cmVzIHN1cHBvcnQgKElFIGRvZXNuJ3Qgc3VwcG9ydClcbiAgdmFyIG5wb3RUZXh0dXJlQ3ViZSA9IHRydWU7XG4gIHZhciBjdWJlVGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgdmFyIGRhdGEgPSBwb29sLmFsbG9jVHlwZShHTF9VTlNJR05FRF9CWVRFJDEsIDM2KTtcbiAgZ2wuYWN0aXZlVGV4dHVyZShHTF9URVhUVVJFMCk7XG4gIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfQ1VCRV9NQVAsIGN1YmVUZXh0dXJlKTtcbiAgZ2wudGV4SW1hZ2UyRChHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gsIDAsIEdMX1JHQkEsIDMsIDMsIDAsIEdMX1JHQkEsIEdMX1VOU0lHTkVEX0JZVEUkMSwgZGF0YSk7XG4gIHBvb2wuZnJlZVR5cGUoZGF0YSk7XG4gIGdsLmJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfQ1VCRV9NQVAsIG51bGwpO1xuICBnbC5kZWxldGVUZXh0dXJlKGN1YmVUZXh0dXJlKTtcbiAgbnBvdFRleHR1cmVDdWJlID0gIWdsLmdldEVycm9yKCk7XG5cbiAgcmV0dXJuIHtcbiAgICAvLyBkcmF3aW5nIGJ1ZmZlciBiaXQgZGVwdGhcbiAgICBjb2xvckJpdHM6IFtcbiAgICAgIGdsLmdldFBhcmFtZXRlcihHTF9SRURfQklUUyksXG4gICAgICBnbC5nZXRQYXJhbWV0ZXIoR0xfR1JFRU5fQklUUyksXG4gICAgICBnbC5nZXRQYXJhbWV0ZXIoR0xfQkxVRV9CSVRTKSxcbiAgICAgIGdsLmdldFBhcmFtZXRlcihHTF9BTFBIQV9CSVRTKVxuICAgIF0sXG4gICAgZGVwdGhCaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfREVQVEhfQklUUyksXG4gICAgc3RlbmNpbEJpdHM6IGdsLmdldFBhcmFtZXRlcihHTF9TVEVOQ0lMX0JJVFMpLFxuICAgIHN1YnBpeGVsQml0czogZ2wuZ2V0UGFyYW1ldGVyKEdMX1NVQlBJWEVMX0JJVFMpLFxuXG4gICAgLy8gc3VwcG9ydGVkIGV4dGVuc2lvbnNcbiAgICBleHRlbnNpb25zOiBPYmplY3Qua2V5cyhleHRlbnNpb25zKS5maWx0ZXIoZnVuY3Rpb24gKGV4dCkge1xuICAgICAgcmV0dXJuICEhZXh0ZW5zaW9uc1tleHRdXG4gICAgfSksXG5cbiAgICAvLyBtYXggYW5pc28gc2FtcGxlc1xuICAgIG1heEFuaXNvdHJvcGljOiBtYXhBbmlzb3Ryb3BpYyxcblxuICAgIC8vIG1heCBkcmF3IGJ1ZmZlcnNcbiAgICBtYXhEcmF3YnVmZmVyczogbWF4RHJhd2J1ZmZlcnMsXG4gICAgbWF4Q29sb3JBdHRhY2htZW50czogbWF4Q29sb3JBdHRhY2htZW50cyxcblxuICAgIC8vIHBvaW50IGFuZCBsaW5lIHNpemUgcmFuZ2VzXG4gICAgcG9pbnRTaXplRGltczogZ2wuZ2V0UGFyYW1ldGVyKEdMX0FMSUFTRURfUE9JTlRfU0laRV9SQU5HRSksXG4gICAgbGluZVdpZHRoRGltczogZ2wuZ2V0UGFyYW1ldGVyKEdMX0FMSUFTRURfTElORV9XSURUSF9SQU5HRSksXG4gICAgbWF4Vmlld3BvcnREaW1zOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZJRVdQT1JUX0RJTVMpLFxuICAgIG1heENvbWJpbmVkVGV4dHVyZVVuaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0NPTUJJTkVEX1RFWFRVUkVfSU1BR0VfVU5JVFMpLFxuICAgIG1heEN1YmVNYXBTaXplOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX0NVQkVfTUFQX1RFWFRVUkVfU0laRSksXG4gICAgbWF4UmVuZGVyYnVmZmVyU2l6ZTogZ2wuZ2V0UGFyYW1ldGVyKEdMX01BWF9SRU5ERVJCVUZGRVJfU0laRSksXG4gICAgbWF4VGV4dHVyZVVuaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1RFWFRVUkVfSU1BR0VfVU5JVFMpLFxuICAgIG1heFRleHR1cmVTaXplOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1RFWFRVUkVfU0laRSksXG4gICAgbWF4QXR0cmlidXRlczogZ2wuZ2V0UGFyYW1ldGVyKEdMX01BWF9WRVJURVhfQVRUUklCUyksXG4gICAgbWF4VmVydGV4VW5pZm9ybXM6IGdsLmdldFBhcmFtZXRlcihHTF9NQVhfVkVSVEVYX1VOSUZPUk1fVkVDVE9SUyksXG4gICAgbWF4VmVydGV4VGV4dHVyZVVuaXRzOiBnbC5nZXRQYXJhbWV0ZXIoR0xfTUFYX1ZFUlRFWF9URVhUVVJFX0lNQUdFX1VOSVRTKSxcbiAgICBtYXhWYXJ5aW5nVmVjdG9yczogZ2wuZ2V0UGFyYW1ldGVyKEdMX01BWF9WQVJZSU5HX1ZFQ1RPUlMpLFxuICAgIG1heEZyYWdtZW50VW5pZm9ybXM6IGdsLmdldFBhcmFtZXRlcihHTF9NQVhfRlJBR01FTlRfVU5JRk9STV9WRUNUT1JTKSxcblxuICAgIC8vIHZlbmRvciBpbmZvXG4gICAgZ2xzbDogZ2wuZ2V0UGFyYW1ldGVyKEdMX1NIQURJTkdfTEFOR1VBR0VfVkVSU0lPTiksXG4gICAgcmVuZGVyZXI6IGdsLmdldFBhcmFtZXRlcihHTF9SRU5ERVJFUiksXG4gICAgdmVuZG9yOiBnbC5nZXRQYXJhbWV0ZXIoR0xfVkVORE9SKSxcbiAgICB2ZXJzaW9uOiBnbC5nZXRQYXJhbWV0ZXIoR0xfVkVSU0lPTiksXG5cbiAgICAvLyBxdWlya3NcbiAgICByZWFkRmxvYXQ6IHJlYWRGbG9hdCxcbiAgICBucG90VGV4dHVyZUN1YmU6IG5wb3RUZXh0dXJlQ3ViZVxuICB9XG59O1xuXG5mdW5jdGlvbiBpc05EQXJyYXlMaWtlIChvYmopIHtcbiAgcmV0dXJuIChcbiAgICAhIW9iaiAmJlxuICAgIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmXG4gICAgQXJyYXkuaXNBcnJheShvYmouc2hhcGUpICYmXG4gICAgQXJyYXkuaXNBcnJheShvYmouc3RyaWRlKSAmJlxuICAgIHR5cGVvZiBvYmoub2Zmc2V0ID09PSAnbnVtYmVyJyAmJlxuICAgIG9iai5zaGFwZS5sZW5ndGggPT09IG9iai5zdHJpZGUubGVuZ3RoICYmXG4gICAgKEFycmF5LmlzQXJyYXkob2JqLmRhdGEpIHx8XG4gICAgICBpc1R5cGVkQXJyYXkob2JqLmRhdGEpKSlcbn1cblxudmFyIHZhbHVlcyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubWFwKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIG9ialtrZXldIH0pXG59O1xuXG52YXIgZmxhdHRlblV0aWxzID0ge1xuICBzaGFwZTogYXJyYXlTaGFwZSQxLFxuICBmbGF0dGVuOiBmbGF0dGVuQXJyYXlcbn07XG5cbmZ1bmN0aW9uIGZsYXR0ZW4xRCAoYXJyYXksIG54LCBvdXQpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBueDsgKytpKSB7XG4gICAgb3V0W2ldID0gYXJyYXlbaV07XG4gIH1cbn1cblxuZnVuY3Rpb24gZmxhdHRlbjJEIChhcnJheSwgbngsIG55LCBvdXQpIHtcbiAgdmFyIHB0ciA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbng7ICsraSkge1xuICAgIHZhciByb3cgPSBhcnJheVtpXTtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG55OyArK2opIHtcbiAgICAgIG91dFtwdHIrK10gPSByb3dbal07XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4zRCAoYXJyYXksIG54LCBueSwgbnosIG91dCwgcHRyXykge1xuICB2YXIgcHRyID0gcHRyXztcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBueDsgKytpKSB7XG4gICAgdmFyIHJvdyA9IGFycmF5W2ldO1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbnk7ICsraikge1xuICAgICAgdmFyIGNvbCA9IHJvd1tqXTtcbiAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgbno7ICsraykge1xuICAgICAgICBvdXRbcHRyKytdID0gY29sW2tdO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBmbGF0dGVuUmVjIChhcnJheSwgc2hhcGUsIGxldmVsLCBvdXQsIHB0cikge1xuICB2YXIgc3RyaWRlID0gMTtcbiAgZm9yICh2YXIgaSA9IGxldmVsICsgMTsgaSA8IHNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgc3RyaWRlICo9IHNoYXBlW2ldO1xuICB9XG4gIHZhciBuID0gc2hhcGVbbGV2ZWxdO1xuICBpZiAoc2hhcGUubGVuZ3RoIC0gbGV2ZWwgPT09IDQpIHtcbiAgICB2YXIgbnggPSBzaGFwZVtsZXZlbCArIDFdO1xuICAgIHZhciBueSA9IHNoYXBlW2xldmVsICsgMl07XG4gICAgdmFyIG56ID0gc2hhcGVbbGV2ZWwgKyAzXTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBmbGF0dGVuM0QoYXJyYXlbaV0sIG54LCBueSwgbnosIG91dCwgcHRyKTtcbiAgICAgIHB0ciArPSBzdHJpZGU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGZsYXR0ZW5SZWMoYXJyYXlbaV0sIHNoYXBlLCBsZXZlbCArIDEsIG91dCwgcHRyKTtcbiAgICAgIHB0ciArPSBzdHJpZGU7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW5BcnJheSAoYXJyYXksIHNoYXBlLCB0eXBlLCBvdXRfKSB7XG4gIHZhciBzeiA9IDE7XG4gIGlmIChzaGFwZS5sZW5ndGgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgICBzeiAqPSBzaGFwZVtpXTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgc3ogPSAwO1xuICB9XG4gIHZhciBvdXQgPSBvdXRfIHx8IHBvb2wuYWxsb2NUeXBlKHR5cGUsIHN6KTtcbiAgc3dpdGNoIChzaGFwZS5sZW5ndGgpIHtcbiAgICBjYXNlIDA6XG4gICAgICBicmVha1xuICAgIGNhc2UgMTpcbiAgICAgIGZsYXR0ZW4xRChhcnJheSwgc2hhcGVbMF0sIG91dCk7XG4gICAgICBicmVha1xuICAgIGNhc2UgMjpcbiAgICAgIGZsYXR0ZW4yRChhcnJheSwgc2hhcGVbMF0sIHNoYXBlWzFdLCBvdXQpO1xuICAgICAgYnJlYWtcbiAgICBjYXNlIDM6XG4gICAgICBmbGF0dGVuM0QoYXJyYXksIHNoYXBlWzBdLCBzaGFwZVsxXSwgc2hhcGVbMl0sIG91dCwgMCk7XG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICBmbGF0dGVuUmVjKGFycmF5LCBzaGFwZSwgMCwgb3V0LCAwKTtcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIGFycmF5U2hhcGUkMSAoYXJyYXlfKSB7XG4gIHZhciBzaGFwZSA9IFtdO1xuICBmb3IgKHZhciBhcnJheSA9IGFycmF5XzsgYXJyYXkubGVuZ3RoOyBhcnJheSA9IGFycmF5WzBdKSB7XG4gICAgc2hhcGUucHVzaChhcnJheS5sZW5ndGgpO1xuICB9XG4gIHJldHVybiBzaGFwZVxufVxuXG52YXIgYXJyYXlUeXBlcyA9IHtcblx0XCJbb2JqZWN0IEludDhBcnJheV1cIjogNTEyMCxcblx0XCJbb2JqZWN0IEludDE2QXJyYXldXCI6IDUxMjIsXG5cdFwiW29iamVjdCBJbnQzMkFycmF5XVwiOiA1MTI0LFxuXHRcIltvYmplY3QgVWludDhBcnJheV1cIjogNTEyMSxcblx0XCJbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XVwiOiA1MTIxLFxuXHRcIltvYmplY3QgVWludDE2QXJyYXldXCI6IDUxMjMsXG5cdFwiW29iamVjdCBVaW50MzJBcnJheV1cIjogNTEyNSxcblx0XCJbb2JqZWN0IEZsb2F0MzJBcnJheV1cIjogNTEyNixcblx0XCJbb2JqZWN0IEZsb2F0NjRBcnJheV1cIjogNTEyMSxcblx0XCJbb2JqZWN0IEFycmF5QnVmZmVyXVwiOiA1MTIxXG59O1xuXG52YXIgaW50OCA9IDUxMjA7XG52YXIgaW50MTYgPSA1MTIyO1xudmFyIGludDMyID0gNTEyNDtcbnZhciB1aW50OCA9IDUxMjE7XG52YXIgdWludDE2ID0gNTEyMztcbnZhciB1aW50MzIgPSA1MTI1O1xudmFyIGZsb2F0ID0gNTEyNjtcbnZhciBmbG9hdDMyID0gNTEyNjtcbnZhciBnbFR5cGVzID0ge1xuXHRpbnQ4OiBpbnQ4LFxuXHRpbnQxNjogaW50MTYsXG5cdGludDMyOiBpbnQzMixcblx0dWludDg6IHVpbnQ4LFxuXHR1aW50MTY6IHVpbnQxNixcblx0dWludDMyOiB1aW50MzIsXG5cdGZsb2F0OiBmbG9hdCxcblx0ZmxvYXQzMjogZmxvYXQzMlxufTtcblxudmFyIGR5bmFtaWMkMSA9IDM1MDQ4O1xudmFyIHN0cmVhbSA9IDM1MDQwO1xudmFyIHVzYWdlVHlwZXMgPSB7XG5cdGR5bmFtaWM6IGR5bmFtaWMkMSxcblx0c3RyZWFtOiBzdHJlYW0sXG5cdFwic3RhdGljXCI6IDM1MDQ0XG59O1xuXG52YXIgYXJyYXlGbGF0dGVuID0gZmxhdHRlblV0aWxzLmZsYXR0ZW47XG52YXIgYXJyYXlTaGFwZSA9IGZsYXR0ZW5VdGlscy5zaGFwZTtcblxudmFyIEdMX1NUQVRJQ19EUkFXID0gMHg4OEU0O1xudmFyIEdMX1NUUkVBTV9EUkFXID0gMHg4OEUwO1xuXG52YXIgR0xfVU5TSUdORURfQllURSQzID0gNTEyMTtcbnZhciBHTF9GTE9BVCQzID0gNTEyNjtcblxudmFyIERUWVBFU19TSVpFUyA9IFtdO1xuRFRZUEVTX1NJWkVTWzUxMjBdID0gMTsgLy8gaW50OFxuRFRZUEVTX1NJWkVTWzUxMjJdID0gMjsgLy8gaW50MTZcbkRUWVBFU19TSVpFU1s1MTI0XSA9IDQ7IC8vIGludDMyXG5EVFlQRVNfU0laRVNbNTEyMV0gPSAxOyAvLyB1aW50OFxuRFRZUEVTX1NJWkVTWzUxMjNdID0gMjsgLy8gdWludDE2XG5EVFlQRVNfU0laRVNbNTEyNV0gPSA0OyAvLyB1aW50MzJcbkRUWVBFU19TSVpFU1s1MTI2XSA9IDQ7IC8vIGZsb2F0MzJcblxuZnVuY3Rpb24gdHlwZWRBcnJheUNvZGUgKGRhdGEpIHtcbiAgcmV0dXJuIGFycmF5VHlwZXNbT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGEpXSB8IDBcbn1cblxuZnVuY3Rpb24gY29weUFycmF5IChvdXQsIGlucCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGlucC5sZW5ndGg7ICsraSkge1xuICAgIG91dFtpXSA9IGlucFtpXTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0cmFuc3Bvc2UgKFxuICByZXN1bHQsIGRhdGEsIHNoYXBlWCwgc2hhcGVZLCBzdHJpZGVYLCBzdHJpZGVZLCBvZmZzZXQpIHtcbiAgdmFyIHB0ciA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc2hhcGVYOyArK2kpIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHNoYXBlWTsgKytqKSB7XG4gICAgICByZXN1bHRbcHRyKytdID0gZGF0YVtzdHJpZGVYICogaSArIHN0cmlkZVkgKiBqICsgb2Zmc2V0XTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gd3JhcEJ1ZmZlclN0YXRlIChnbCwgc3RhdHMsIGNvbmZpZywgYXR0cmlidXRlU3RhdGUpIHtcbiAgdmFyIGJ1ZmZlckNvdW50ID0gMDtcbiAgdmFyIGJ1ZmZlclNldCA9IHt9O1xuXG4gIGZ1bmN0aW9uIFJFR0xCdWZmZXIgKHR5cGUpIHtcbiAgICB0aGlzLmlkID0gYnVmZmVyQ291bnQrKztcbiAgICB0aGlzLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy51c2FnZSA9IEdMX1NUQVRJQ19EUkFXO1xuICAgIHRoaXMuYnl0ZUxlbmd0aCA9IDA7XG4gICAgdGhpcy5kaW1lbnNpb24gPSAxO1xuICAgIHRoaXMuZHR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDM7XG5cbiAgICB0aGlzLnBlcnNpc3RlbnREYXRhID0gbnVsbDtcblxuICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgdGhpcy5zdGF0cyA9IHtzaXplOiAwfTtcbiAgICB9XG4gIH1cblxuICBSRUdMQnVmZmVyLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKCkge1xuICAgIGdsLmJpbmRCdWZmZXIodGhpcy50eXBlLCB0aGlzLmJ1ZmZlcik7XG4gIH07XG5cbiAgUkVHTEJ1ZmZlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICBkZXN0cm95KHRoaXMpO1xuICB9O1xuXG4gIHZhciBzdHJlYW1Qb29sID0gW107XG5cbiAgZnVuY3Rpb24gY3JlYXRlU3RyZWFtICh0eXBlLCBkYXRhKSB7XG4gICAgdmFyIGJ1ZmZlciA9IHN0cmVhbVBvb2wucG9wKCk7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgIGJ1ZmZlciA9IG5ldyBSRUdMQnVmZmVyKHR5cGUpO1xuICAgIH1cbiAgICBidWZmZXIuYmluZCgpO1xuICAgIGluaXRCdWZmZXJGcm9tRGF0YShidWZmZXIsIGRhdGEsIEdMX1NUUkVBTV9EUkFXLCAwLCAxLCBmYWxzZSk7XG4gICAgcmV0dXJuIGJ1ZmZlclxuICB9XG5cbiAgZnVuY3Rpb24gZGVzdHJveVN0cmVhbSAoc3RyZWFtJCQxKSB7XG4gICAgc3RyZWFtUG9vbC5wdXNoKHN0cmVhbSQkMSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbml0QnVmZmVyRnJvbVR5cGVkQXJyYXkgKGJ1ZmZlciwgZGF0YSwgdXNhZ2UpIHtcbiAgICBidWZmZXIuYnl0ZUxlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDtcbiAgICBnbC5idWZmZXJEYXRhKGJ1ZmZlci50eXBlLCBkYXRhLCB1c2FnZSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbml0QnVmZmVyRnJvbURhdGEgKGJ1ZmZlciwgZGF0YSwgdXNhZ2UsIGR0eXBlLCBkaW1lbnNpb24sIHBlcnNpc3QpIHtcbiAgICB2YXIgc2hhcGU7XG4gICAgYnVmZmVyLnVzYWdlID0gdXNhZ2U7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIGJ1ZmZlci5kdHlwZSA9IGR0eXBlIHx8IEdMX0ZMT0FUJDM7XG4gICAgICBpZiAoZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBmbGF0RGF0YTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YVswXSkpIHtcbiAgICAgICAgICBzaGFwZSA9IGFycmF5U2hhcGUoZGF0YSk7XG4gICAgICAgICAgdmFyIGRpbSA9IDE7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBzaGFwZS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgZGltICo9IHNoYXBlW2ldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBidWZmZXIuZGltZW5zaW9uID0gZGltO1xuICAgICAgICAgIGZsYXREYXRhID0gYXJyYXlGbGF0dGVuKGRhdGEsIHNoYXBlLCBidWZmZXIuZHR5cGUpO1xuICAgICAgICAgIGluaXRCdWZmZXJGcm9tVHlwZWRBcnJheShidWZmZXIsIGZsYXREYXRhLCB1c2FnZSk7XG4gICAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICAgIGJ1ZmZlci5wZXJzaXN0ZW50RGF0YSA9IGZsYXREYXRhO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb29sLmZyZWVUeXBlKGZsYXREYXRhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGFbMF0gPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgYnVmZmVyLmRpbWVuc2lvbiA9IGRpbWVuc2lvbjtcbiAgICAgICAgICB2YXIgdHlwZWREYXRhID0gcG9vbC5hbGxvY1R5cGUoYnVmZmVyLmR0eXBlLCBkYXRhLmxlbmd0aCk7XG4gICAgICAgICAgY29weUFycmF5KHR5cGVkRGF0YSwgZGF0YSk7XG4gICAgICAgICAgaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgdHlwZWREYXRhLCB1c2FnZSk7XG4gICAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICAgIGJ1ZmZlci5wZXJzaXN0ZW50RGF0YSA9IHR5cGVkRGF0YTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9vbC5mcmVlVHlwZSh0eXBlZERhdGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChpc1R5cGVkQXJyYXkoZGF0YVswXSkpIHtcbiAgICAgICAgICBidWZmZXIuZGltZW5zaW9uID0gZGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgYnVmZmVyLmR0eXBlID0gZHR5cGUgfHwgdHlwZWRBcnJheUNvZGUoZGF0YVswXSkgfHwgR0xfRkxPQVQkMztcbiAgICAgICAgICBmbGF0RGF0YSA9IGFycmF5RmxhdHRlbihcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICBbZGF0YS5sZW5ndGgsIGRhdGFbMF0ubGVuZ3RoXSxcbiAgICAgICAgICAgIGJ1ZmZlci5kdHlwZSk7XG4gICAgICAgICAgaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgZmxhdERhdGEsIHVzYWdlKTtcbiAgICAgICAgICBpZiAocGVyc2lzdCkge1xuICAgICAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gZmxhdERhdGE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBvb2wuZnJlZVR5cGUoZmxhdERhdGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIGJ1ZmZlciBkYXRhJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVHlwZWRBcnJheShkYXRhKSkge1xuICAgICAgYnVmZmVyLmR0eXBlID0gZHR5cGUgfHwgdHlwZWRBcnJheUNvZGUoZGF0YSk7XG4gICAgICBidWZmZXIuZGltZW5zaW9uID0gZGltZW5zaW9uO1xuICAgICAgaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgZGF0YSwgdXNhZ2UpO1xuICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gbmV3IFVpbnQ4QXJyYXkobmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIpKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzTkRBcnJheUxpa2UoZGF0YSkpIHtcbiAgICAgIHNoYXBlID0gZGF0YS5zaGFwZTtcbiAgICAgIHZhciBzdHJpZGUgPSBkYXRhLnN0cmlkZTtcbiAgICAgIHZhciBvZmZzZXQgPSBkYXRhLm9mZnNldDtcblxuICAgICAgdmFyIHNoYXBlWCA9IDA7XG4gICAgICB2YXIgc2hhcGVZID0gMDtcbiAgICAgIHZhciBzdHJpZGVYID0gMDtcbiAgICAgIHZhciBzdHJpZGVZID0gMDtcbiAgICAgIGlmIChzaGFwZS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgc2hhcGVYID0gc2hhcGVbMF07XG4gICAgICAgIHNoYXBlWSA9IDE7XG4gICAgICAgIHN0cmlkZVggPSBzdHJpZGVbMF07XG4gICAgICAgIHN0cmlkZVkgPSAwO1xuICAgICAgfSBlbHNlIGlmIChzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgc2hhcGVYID0gc2hhcGVbMF07XG4gICAgICAgIHNoYXBlWSA9IHNoYXBlWzFdO1xuICAgICAgICBzdHJpZGVYID0gc3RyaWRlWzBdO1xuICAgICAgICBzdHJpZGVZID0gc3RyaWRlWzFdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBzaGFwZScpO1xuICAgICAgfVxuXG4gICAgICBidWZmZXIuZHR5cGUgPSBkdHlwZSB8fCB0eXBlZEFycmF5Q29kZShkYXRhLmRhdGEpIHx8IEdMX0ZMT0FUJDM7XG4gICAgICBidWZmZXIuZGltZW5zaW9uID0gc2hhcGVZO1xuXG4gICAgICB2YXIgdHJhbnNwb3NlRGF0YSA9IHBvb2wuYWxsb2NUeXBlKGJ1ZmZlci5kdHlwZSwgc2hhcGVYICogc2hhcGVZKTtcbiAgICAgIHRyYW5zcG9zZSh0cmFuc3Bvc2VEYXRhLFxuICAgICAgICBkYXRhLmRhdGEsXG4gICAgICAgIHNoYXBlWCwgc2hhcGVZLFxuICAgICAgICBzdHJpZGVYLCBzdHJpZGVZLFxuICAgICAgICBvZmZzZXQpO1xuICAgICAgaW5pdEJ1ZmZlckZyb21UeXBlZEFycmF5KGJ1ZmZlciwgdHJhbnNwb3NlRGF0YSwgdXNhZ2UpO1xuICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgYnVmZmVyLnBlcnNpc3RlbnREYXRhID0gdHJhbnNwb3NlRGF0YTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBvb2wuZnJlZVR5cGUodHJhbnNwb3NlRGF0YSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgYnVmZmVyIGRhdGEnKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkZXN0cm95IChidWZmZXIpIHtcbiAgICBzdGF0cy5idWZmZXJDb3VudC0tO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVTdGF0ZS5zdGF0ZS5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHJlY29yZCA9IGF0dHJpYnV0ZVN0YXRlLnN0YXRlW2ldO1xuICAgICAgaWYgKHJlY29yZC5idWZmZXIgPT09IGJ1ZmZlcikge1xuICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSk7XG4gICAgICAgIHJlY29yZC5idWZmZXIgPSBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBoYW5kbGUgPSBidWZmZXIuYnVmZmVyO1xuICAgIGNoZWNrJDEoaGFuZGxlLCAnYnVmZmVyIG11c3Qgbm90IGJlIGRlbGV0ZWQgYWxyZWFkeScpO1xuICAgIGdsLmRlbGV0ZUJ1ZmZlcihoYW5kbGUpO1xuICAgIGJ1ZmZlci5idWZmZXIgPSBudWxsO1xuICAgIGRlbGV0ZSBidWZmZXJTZXRbYnVmZmVyLmlkXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAob3B0aW9ucywgdHlwZSwgZGVmZXJJbml0LCBwZXJzaXN0ZW50KSB7XG4gICAgc3RhdHMuYnVmZmVyQ291bnQrKztcblxuICAgIHZhciBidWZmZXIgPSBuZXcgUkVHTEJ1ZmZlcih0eXBlKTtcbiAgICBidWZmZXJTZXRbYnVmZmVyLmlkXSA9IGJ1ZmZlcjtcblxuICAgIGZ1bmN0aW9uIHJlZ2xCdWZmZXIgKG9wdGlvbnMpIHtcbiAgICAgIHZhciB1c2FnZSA9IEdMX1NUQVRJQ19EUkFXO1xuICAgICAgdmFyIGRhdGEgPSBudWxsO1xuICAgICAgdmFyIGJ5dGVMZW5ndGggPSAwO1xuICAgICAgdmFyIGR0eXBlID0gMDtcbiAgICAgIHZhciBkaW1lbnNpb24gPSAxO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykgfHxcbiAgICAgICAgICBpc1R5cGVkQXJyYXkob3B0aW9ucykgfHxcbiAgICAgICAgICBpc05EQXJyYXlMaWtlKG9wdGlvbnMpKSB7XG4gICAgICAgIGRhdGEgPSBvcHRpb25zO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYnl0ZUxlbmd0aCA9IG9wdGlvbnMgfCAwO1xuICAgICAgfSBlbHNlIGlmIChvcHRpb25zKSB7XG4gICAgICAgIGNoZWNrJDEudHlwZShcbiAgICAgICAgICBvcHRpb25zLCAnb2JqZWN0JyxcbiAgICAgICAgICAnYnVmZmVyIGFyZ3VtZW50cyBtdXN0IGJlIGFuIG9iamVjdCwgYSBudW1iZXIgb3IgYW4gYXJyYXknKTtcblxuICAgICAgICBpZiAoJ2RhdGEnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBjaGVjayQxKFxuICAgICAgICAgICAgZGF0YSA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheShkYXRhKSB8fFxuICAgICAgICAgICAgaXNUeXBlZEFycmF5KGRhdGEpIHx8XG4gICAgICAgICAgICBpc05EQXJyYXlMaWtlKGRhdGEpLFxuICAgICAgICAgICAgJ2ludmFsaWQgZGF0YSBmb3IgYnVmZmVyJyk7XG4gICAgICAgICAgZGF0YSA9IG9wdGlvbnMuZGF0YTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgndXNhZ2UnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnVzYWdlLCB1c2FnZVR5cGVzLCAnaW52YWxpZCBidWZmZXIgdXNhZ2UnKTtcbiAgICAgICAgICB1c2FnZSA9IHVzYWdlVHlwZXNbb3B0aW9ucy51c2FnZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3R5cGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLnR5cGUsIGdsVHlwZXMsICdpbnZhbGlkIGJ1ZmZlciB0eXBlJyk7XG4gICAgICAgICAgZHR5cGUgPSBnbFR5cGVzW29wdGlvbnMudHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2RpbWVuc2lvbicgaW4gb3B0aW9ucykge1xuICAgICAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLmRpbWVuc2lvbiwgJ251bWJlcicsICdpbnZhbGlkIGRpbWVuc2lvbicpO1xuICAgICAgICAgIGRpbWVuc2lvbiA9IG9wdGlvbnMuZGltZW5zaW9uIHwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnbGVuZ3RoJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgY2hlY2skMS5ubmkoYnl0ZUxlbmd0aCwgJ2J1ZmZlciBsZW5ndGggbXVzdCBiZSBhIG5vbm5lZ2F0aXZlIGludGVnZXInKTtcbiAgICAgICAgICBieXRlTGVuZ3RoID0gb3B0aW9ucy5sZW5ndGggfCAwO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGJ1ZmZlci5iaW5kKCk7XG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgLy8gIzQ3NVxuICAgICAgICBpZiAoYnl0ZUxlbmd0aCkgZ2wuYnVmZmVyRGF0YShidWZmZXIudHlwZSwgYnl0ZUxlbmd0aCwgdXNhZ2UpO1xuICAgICAgICBidWZmZXIuZHR5cGUgPSBkdHlwZSB8fCBHTF9VTlNJR05FRF9CWVRFJDM7XG4gICAgICAgIGJ1ZmZlci51c2FnZSA9IHVzYWdlO1xuICAgICAgICBidWZmZXIuZGltZW5zaW9uID0gZGltZW5zaW9uO1xuICAgICAgICBidWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0QnVmZmVyRnJvbURhdGEoYnVmZmVyLCBkYXRhLCB1c2FnZSwgZHR5cGUsIGRpbWVuc2lvbiwgcGVyc2lzdGVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICBidWZmZXIuc3RhdHMuc2l6ZSA9IGJ1ZmZlci5ieXRlTGVuZ3RoICogRFRZUEVTX1NJWkVTW2J1ZmZlci5kdHlwZV07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWdsQnVmZmVyXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0U3ViRGF0YSAoZGF0YSwgb2Zmc2V0KSB7XG4gICAgICBjaGVjayQxKG9mZnNldCArIGRhdGEuYnl0ZUxlbmd0aCA8PSBidWZmZXIuYnl0ZUxlbmd0aCxcbiAgICAgICAgJ2ludmFsaWQgYnVmZmVyIHN1YmRhdGEgY2FsbCwgYnVmZmVyIGlzIHRvbyBzbWFsbC4gJyArICcgQ2FuXFwndCB3cml0ZSBkYXRhIG9mIHNpemUgJyArIGRhdGEuYnl0ZUxlbmd0aCArICcgc3RhcnRpbmcgZnJvbSBvZmZzZXQgJyArIG9mZnNldCArICcgdG8gYSBidWZmZXIgb2Ygc2l6ZSAnICsgYnVmZmVyLmJ5dGVMZW5ndGgpO1xuXG4gICAgICBnbC5idWZmZXJTdWJEYXRhKGJ1ZmZlci50eXBlLCBvZmZzZXQsIGRhdGEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN1YmRhdGEgKGRhdGEsIG9mZnNldF8pIHtcbiAgICAgIHZhciBvZmZzZXQgPSAob2Zmc2V0XyB8fCAwKSB8IDA7XG4gICAgICB2YXIgc2hhcGU7XG4gICAgICBidWZmZXIuYmluZCgpO1xuICAgICAgaWYgKGlzVHlwZWRBcnJheShkYXRhKSkge1xuICAgICAgICBzZXRTdWJEYXRhKGRhdGEsIG9mZnNldCk7XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVswXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHZhciBjb252ZXJ0ZWQgPSBwb29sLmFsbG9jVHlwZShidWZmZXIuZHR5cGUsIGRhdGEubGVuZ3RoKTtcbiAgICAgICAgICAgIGNvcHlBcnJheShjb252ZXJ0ZWQsIGRhdGEpO1xuICAgICAgICAgICAgc2V0U3ViRGF0YShjb252ZXJ0ZWQsIG9mZnNldCk7XG4gICAgICAgICAgICBwb29sLmZyZWVUeXBlKGNvbnZlcnRlZCk7XG4gICAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGRhdGFbMF0pIHx8IGlzVHlwZWRBcnJheShkYXRhWzBdKSkge1xuICAgICAgICAgICAgc2hhcGUgPSBhcnJheVNoYXBlKGRhdGEpO1xuICAgICAgICAgICAgdmFyIGZsYXREYXRhID0gYXJyYXlGbGF0dGVuKGRhdGEsIHNoYXBlLCBidWZmZXIuZHR5cGUpO1xuICAgICAgICAgICAgc2V0U3ViRGF0YShmbGF0RGF0YSwgb2Zmc2V0KTtcbiAgICAgICAgICAgIHBvb2wuZnJlZVR5cGUoZmxhdERhdGEpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIGJ1ZmZlciBkYXRhJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGlzTkRBcnJheUxpa2UoZGF0YSkpIHtcbiAgICAgICAgc2hhcGUgPSBkYXRhLnNoYXBlO1xuICAgICAgICB2YXIgc3RyaWRlID0gZGF0YS5zdHJpZGU7XG5cbiAgICAgICAgdmFyIHNoYXBlWCA9IDA7XG4gICAgICAgIHZhciBzaGFwZVkgPSAwO1xuICAgICAgICB2YXIgc3RyaWRlWCA9IDA7XG4gICAgICAgIHZhciBzdHJpZGVZID0gMDtcbiAgICAgICAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIHNoYXBlWCA9IHNoYXBlWzBdO1xuICAgICAgICAgIHNoYXBlWSA9IDE7XG4gICAgICAgICAgc3RyaWRlWCA9IHN0cmlkZVswXTtcbiAgICAgICAgICBzdHJpZGVZID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICBzaGFwZVggPSBzaGFwZVswXTtcbiAgICAgICAgICBzaGFwZVkgPSBzaGFwZVsxXTtcbiAgICAgICAgICBzdHJpZGVYID0gc3RyaWRlWzBdO1xuICAgICAgICAgIHN0cmlkZVkgPSBzdHJpZGVbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBzaGFwZScpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkdHlwZSA9IEFycmF5LmlzQXJyYXkoZGF0YS5kYXRhKVxuICAgICAgICAgID8gYnVmZmVyLmR0eXBlXG4gICAgICAgICAgOiB0eXBlZEFycmF5Q29kZShkYXRhLmRhdGEpO1xuXG4gICAgICAgIHZhciB0cmFuc3Bvc2VEYXRhID0gcG9vbC5hbGxvY1R5cGUoZHR5cGUsIHNoYXBlWCAqIHNoYXBlWSk7XG4gICAgICAgIHRyYW5zcG9zZSh0cmFuc3Bvc2VEYXRhLFxuICAgICAgICAgIGRhdGEuZGF0YSxcbiAgICAgICAgICBzaGFwZVgsIHNoYXBlWSxcbiAgICAgICAgICBzdHJpZGVYLCBzdHJpZGVZLFxuICAgICAgICAgIGRhdGEub2Zmc2V0KTtcbiAgICAgICAgc2V0U3ViRGF0YSh0cmFuc3Bvc2VEYXRhLCBvZmZzZXQpO1xuICAgICAgICBwb29sLmZyZWVUeXBlKHRyYW5zcG9zZURhdGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBkYXRhIGZvciBidWZmZXIgc3ViZGF0YScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlZ2xCdWZmZXJcbiAgICB9XG5cbiAgICBpZiAoIWRlZmVySW5pdCkge1xuICAgICAgcmVnbEJ1ZmZlcihvcHRpb25zKTtcbiAgICB9XG5cbiAgICByZWdsQnVmZmVyLl9yZWdsVHlwZSA9ICdidWZmZXInO1xuICAgIHJlZ2xCdWZmZXIuX2J1ZmZlciA9IGJ1ZmZlcjtcbiAgICByZWdsQnVmZmVyLnN1YmRhdGEgPSBzdWJkYXRhO1xuICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgcmVnbEJ1ZmZlci5zdGF0cyA9IGJ1ZmZlci5zdGF0cztcbiAgICB9XG4gICAgcmVnbEJ1ZmZlci5kZXN0cm95ID0gZnVuY3Rpb24gKCkgeyBkZXN0cm95KGJ1ZmZlcik7IH07XG5cbiAgICByZXR1cm4gcmVnbEJ1ZmZlclxuICB9XG5cbiAgZnVuY3Rpb24gcmVzdG9yZUJ1ZmZlcnMgKCkge1xuICAgIHZhbHVlcyhidWZmZXJTZXQpLmZvckVhY2goZnVuY3Rpb24gKGJ1ZmZlcikge1xuICAgICAgYnVmZmVyLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgZ2wuYmluZEJ1ZmZlcihidWZmZXIudHlwZSwgYnVmZmVyLmJ1ZmZlcik7XG4gICAgICBnbC5idWZmZXJEYXRhKFxuICAgICAgICBidWZmZXIudHlwZSwgYnVmZmVyLnBlcnNpc3RlbnREYXRhIHx8IGJ1ZmZlci5ieXRlTGVuZ3RoLCBidWZmZXIudXNhZ2UpO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgc3RhdHMuZ2V0VG90YWxCdWZmZXJTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgIC8vIFRPRE86IFJpZ2h0IG5vdywgdGhlIHN0cmVhbXMgYXJlIG5vdCBwYXJ0IG9mIHRoZSB0b3RhbCBjb3VudC5cbiAgICAgIE9iamVjdC5rZXlzKGJ1ZmZlclNldCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHRvdGFsICs9IGJ1ZmZlclNldFtrZXldLnN0YXRzLnNpemU7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0b3RhbFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNyZWF0ZTogY3JlYXRlQnVmZmVyLFxuXG4gICAgY3JlYXRlU3RyZWFtOiBjcmVhdGVTdHJlYW0sXG4gICAgZGVzdHJveVN0cmVhbTogZGVzdHJveVN0cmVhbSxcblxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YWx1ZXMoYnVmZmVyU2V0KS5mb3JFYWNoKGRlc3Ryb3kpO1xuICAgICAgc3RyZWFtUG9vbC5mb3JFYWNoKGRlc3Ryb3kpO1xuICAgIH0sXG5cbiAgICBnZXRCdWZmZXI6IGZ1bmN0aW9uICh3cmFwcGVyKSB7XG4gICAgICBpZiAod3JhcHBlciAmJiB3cmFwcGVyLl9idWZmZXIgaW5zdGFuY2VvZiBSRUdMQnVmZmVyKSB7XG4gICAgICAgIHJldHVybiB3cmFwcGVyLl9idWZmZXJcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfSxcblxuICAgIHJlc3RvcmU6IHJlc3RvcmVCdWZmZXJzLFxuXG4gICAgX2luaXRCdWZmZXI6IGluaXRCdWZmZXJGcm9tRGF0YVxuICB9XG59XG5cbnZhciBwb2ludHMgPSAwO1xudmFyIHBvaW50ID0gMDtcbnZhciBsaW5lcyA9IDE7XG52YXIgbGluZSA9IDE7XG52YXIgdHJpYW5nbGVzID0gNDtcbnZhciB0cmlhbmdsZSA9IDQ7XG52YXIgcHJpbVR5cGVzID0ge1xuXHRwb2ludHM6IHBvaW50cyxcblx0cG9pbnQ6IHBvaW50LFxuXHRsaW5lczogbGluZXMsXG5cdGxpbmU6IGxpbmUsXG5cdHRyaWFuZ2xlczogdHJpYW5nbGVzLFxuXHR0cmlhbmdsZTogdHJpYW5nbGUsXG5cdFwibGluZSBsb29wXCI6IDIsXG5cdFwibGluZSBzdHJpcFwiOiAzLFxuXHRcInRyaWFuZ2xlIHN0cmlwXCI6IDUsXG5cdFwidHJpYW5nbGUgZmFuXCI6IDZcbn07XG5cbnZhciBHTF9QT0lOVFMgPSAwO1xudmFyIEdMX0xJTkVTID0gMTtcbnZhciBHTF9UUklBTkdMRVMgPSA0O1xuXG52YXIgR0xfQllURSQyID0gNTEyMDtcbnZhciBHTF9VTlNJR05FRF9CWVRFJDQgPSA1MTIxO1xudmFyIEdMX1NIT1JUJDIgPSA1MTIyO1xudmFyIEdMX1VOU0lHTkVEX1NIT1JUJDIgPSA1MTIzO1xudmFyIEdMX0lOVCQyID0gNTEyNDtcbnZhciBHTF9VTlNJR05FRF9JTlQkMiA9IDUxMjU7XG5cbnZhciBHTF9FTEVNRU5UX0FSUkFZX0JVRkZFUiA9IDM0OTYzO1xuXG52YXIgR0xfU1RSRUFNX0RSQVckMSA9IDB4ODhFMDtcbnZhciBHTF9TVEFUSUNfRFJBVyQxID0gMHg4OEU0O1xuXG5mdW5jdGlvbiB3cmFwRWxlbWVudHNTdGF0ZSAoZ2wsIGV4dGVuc2lvbnMsIGJ1ZmZlclN0YXRlLCBzdGF0cykge1xuICB2YXIgZWxlbWVudFNldCA9IHt9O1xuICB2YXIgZWxlbWVudENvdW50ID0gMDtcblxuICB2YXIgZWxlbWVudFR5cGVzID0ge1xuICAgICd1aW50OCc6IEdMX1VOU0lHTkVEX0JZVEUkNCxcbiAgICAndWludDE2JzogR0xfVU5TSUdORURfU0hPUlQkMlxuICB9O1xuXG4gIGlmIChleHRlbnNpb25zLm9lc19lbGVtZW50X2luZGV4X3VpbnQpIHtcbiAgICBlbGVtZW50VHlwZXMudWludDMyID0gR0xfVU5TSUdORURfSU5UJDI7XG4gIH1cblxuICBmdW5jdGlvbiBSRUdMRWxlbWVudEJ1ZmZlciAoYnVmZmVyKSB7XG4gICAgdGhpcy5pZCA9IGVsZW1lbnRDb3VudCsrO1xuICAgIGVsZW1lbnRTZXRbdGhpcy5pZF0gPSB0aGlzO1xuICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyO1xuICAgIHRoaXMucHJpbVR5cGUgPSBHTF9UUklBTkdMRVM7XG4gICAgdGhpcy52ZXJ0Q291bnQgPSAwO1xuICAgIHRoaXMudHlwZSA9IDA7XG4gIH1cblxuICBSRUdMRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmJ1ZmZlci5iaW5kKCk7XG4gIH07XG5cbiAgdmFyIGJ1ZmZlclBvb2wgPSBbXTtcblxuICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50U3RyZWFtIChkYXRhKSB7XG4gICAgdmFyIHJlc3VsdCA9IGJ1ZmZlclBvb2wucG9wKCk7XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHJlc3VsdCA9IG5ldyBSRUdMRWxlbWVudEJ1ZmZlcihidWZmZXJTdGF0ZS5jcmVhdGUoXG4gICAgICAgIG51bGwsXG4gICAgICAgIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSLFxuICAgICAgICB0cnVlLFxuICAgICAgICBmYWxzZSkuX2J1ZmZlcik7XG4gICAgfVxuICAgIGluaXRFbGVtZW50cyhyZXN1bHQsIGRhdGEsIEdMX1NUUkVBTV9EUkFXJDEsIC0xLCAtMSwgMCwgMCk7XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gZGVzdHJveUVsZW1lbnRTdHJlYW0gKGVsZW1lbnRzKSB7XG4gICAgYnVmZmVyUG9vbC5wdXNoKGVsZW1lbnRzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRFbGVtZW50cyAoXG4gICAgZWxlbWVudHMsXG4gICAgZGF0YSxcbiAgICB1c2FnZSxcbiAgICBwcmltLFxuICAgIGNvdW50LFxuICAgIGJ5dGVMZW5ndGgsXG4gICAgdHlwZSkge1xuICAgIGVsZW1lbnRzLmJ1ZmZlci5iaW5kKCk7XG4gICAgaWYgKGRhdGEpIHtcbiAgICAgIHZhciBwcmVkaWN0ZWRUeXBlID0gdHlwZTtcbiAgICAgIGlmICghdHlwZSAmJiAoXG4gICAgICAgICAgIWlzVHlwZWRBcnJheShkYXRhKSB8fFxuICAgICAgICAgKGlzTkRBcnJheUxpa2UoZGF0YSkgJiYgIWlzVHlwZWRBcnJheShkYXRhLmRhdGEpKSkpIHtcbiAgICAgICAgcHJlZGljdGVkVHlwZSA9IGV4dGVuc2lvbnMub2VzX2VsZW1lbnRfaW5kZXhfdWludFxuICAgICAgICAgID8gR0xfVU5TSUdORURfSU5UJDJcbiAgICAgICAgICA6IEdMX1VOU0lHTkVEX1NIT1JUJDI7XG4gICAgICB9XG4gICAgICBidWZmZXJTdGF0ZS5faW5pdEJ1ZmZlcihcbiAgICAgICAgZWxlbWVudHMuYnVmZmVyLFxuICAgICAgICBkYXRhLFxuICAgICAgICB1c2FnZSxcbiAgICAgICAgcHJlZGljdGVkVHlwZSxcbiAgICAgICAgMyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdsLmJ1ZmZlckRhdGEoR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIsIGJ5dGVMZW5ndGgsIHVzYWdlKTtcbiAgICAgIGVsZW1lbnRzLmJ1ZmZlci5kdHlwZSA9IGR0eXBlIHx8IEdMX1VOU0lHTkVEX0JZVEUkNDtcbiAgICAgIGVsZW1lbnRzLmJ1ZmZlci51c2FnZSA9IHVzYWdlO1xuICAgICAgZWxlbWVudHMuYnVmZmVyLmRpbWVuc2lvbiA9IDM7XG4gICAgICBlbGVtZW50cy5idWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIGR0eXBlID0gdHlwZTtcbiAgICBpZiAoIXR5cGUpIHtcbiAgICAgIHN3aXRjaCAoZWxlbWVudHMuYnVmZmVyLmR0eXBlKSB7XG4gICAgICAgIGNhc2UgR0xfVU5TSUdORURfQllURSQ0OlxuICAgICAgICBjYXNlIEdMX0JZVEUkMjpcbiAgICAgICAgICBkdHlwZSA9IEdMX1VOU0lHTkVEX0JZVEUkNDtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfVU5TSUdORURfU0hPUlQkMjpcbiAgICAgICAgY2FzZSBHTF9TSE9SVCQyOlxuICAgICAgICAgIGR0eXBlID0gR0xfVU5TSUdORURfU0hPUlQkMjtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfVU5TSUdORURfSU5UJDI6XG4gICAgICAgIGNhc2UgR0xfSU5UJDI6XG4gICAgICAgICAgZHR5cGUgPSBHTF9VTlNJR05FRF9JTlQkMjtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgY2hlY2skMS5yYWlzZSgndW5zdXBwb3J0ZWQgdHlwZSBmb3IgZWxlbWVudCBhcnJheScpO1xuICAgICAgfVxuICAgICAgZWxlbWVudHMuYnVmZmVyLmR0eXBlID0gZHR5cGU7XG4gICAgfVxuICAgIGVsZW1lbnRzLnR5cGUgPSBkdHlwZTtcblxuICAgIC8vIENoZWNrIG9lc19lbGVtZW50X2luZGV4X3VpbnQgZXh0ZW5zaW9uXG4gICAgY2hlY2skMShcbiAgICAgIGR0eXBlICE9PSBHTF9VTlNJR05FRF9JTlQkMiB8fFxuICAgICAgISFleHRlbnNpb25zLm9lc19lbGVtZW50X2luZGV4X3VpbnQsXG4gICAgICAnMzIgYml0IGVsZW1lbnQgYnVmZmVycyBub3Qgc3VwcG9ydGVkLCBlbmFibGUgb2VzX2VsZW1lbnRfaW5kZXhfdWludCBmaXJzdCcpO1xuXG4gICAgLy8gdHJ5IHRvIGd1ZXNzIGRlZmF1bHQgcHJpbWl0aXZlIHR5cGUgYW5kIGFyZ3VtZW50c1xuICAgIHZhciB2ZXJ0Q291bnQgPSBjb3VudDtcbiAgICBpZiAodmVydENvdW50IDwgMCkge1xuICAgICAgdmVydENvdW50ID0gZWxlbWVudHMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICBpZiAoZHR5cGUgPT09IEdMX1VOU0lHTkVEX1NIT1JUJDIpIHtcbiAgICAgICAgdmVydENvdW50ID4+PSAxO1xuICAgICAgfSBlbHNlIGlmIChkdHlwZSA9PT0gR0xfVU5TSUdORURfSU5UJDIpIHtcbiAgICAgICAgdmVydENvdW50ID4+PSAyO1xuICAgICAgfVxuICAgIH1cbiAgICBlbGVtZW50cy52ZXJ0Q291bnQgPSB2ZXJ0Q291bnQ7XG5cbiAgICAvLyB0cnkgdG8gZ3Vlc3MgcHJpbWl0aXZlIHR5cGUgZnJvbSBjZWxsIGRpbWVuc2lvblxuICAgIHZhciBwcmltVHlwZSA9IHByaW07XG4gICAgaWYgKHByaW0gPCAwKSB7XG4gICAgICBwcmltVHlwZSA9IEdMX1RSSUFOR0xFUztcbiAgICAgIHZhciBkaW1lbnNpb24gPSBlbGVtZW50cy5idWZmZXIuZGltZW5zaW9uO1xuICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gMSkgcHJpbVR5cGUgPSBHTF9QT0lOVFM7XG4gICAgICBpZiAoZGltZW5zaW9uID09PSAyKSBwcmltVHlwZSA9IEdMX0xJTkVTO1xuICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gMykgcHJpbVR5cGUgPSBHTF9UUklBTkdMRVM7XG4gICAgfVxuICAgIGVsZW1lbnRzLnByaW1UeXBlID0gcHJpbVR5cGU7XG4gIH1cblxuICBmdW5jdGlvbiBkZXN0cm95RWxlbWVudHMgKGVsZW1lbnRzKSB7XG4gICAgc3RhdHMuZWxlbWVudHNDb3VudC0tO1xuXG4gICAgY2hlY2skMShlbGVtZW50cy5idWZmZXIgIT09IG51bGwsICdtdXN0IG5vdCBkb3VibGUgZGVzdHJveSBlbGVtZW50cycpO1xuICAgIGRlbGV0ZSBlbGVtZW50U2V0W2VsZW1lbnRzLmlkXTtcbiAgICBlbGVtZW50cy5idWZmZXIuZGVzdHJveSgpO1xuICAgIGVsZW1lbnRzLmJ1ZmZlciA9IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50cyAob3B0aW9ucywgcGVyc2lzdGVudCkge1xuICAgIHZhciBidWZmZXIgPSBidWZmZXJTdGF0ZS5jcmVhdGUobnVsbCwgR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIsIHRydWUpO1xuICAgIHZhciBlbGVtZW50cyA9IG5ldyBSRUdMRWxlbWVudEJ1ZmZlcihidWZmZXIuX2J1ZmZlcik7XG4gICAgc3RhdHMuZWxlbWVudHNDb3VudCsrO1xuXG4gICAgZnVuY3Rpb24gcmVnbEVsZW1lbnRzIChvcHRpb25zKSB7XG4gICAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgICAgYnVmZmVyKCk7XG4gICAgICAgIGVsZW1lbnRzLnByaW1UeXBlID0gR0xfVFJJQU5HTEVTO1xuICAgICAgICBlbGVtZW50cy52ZXJ0Q291bnQgPSAwO1xuICAgICAgICBlbGVtZW50cy50eXBlID0gR0xfVU5TSUdORURfQllURSQ0O1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYnVmZmVyKG9wdGlvbnMpO1xuICAgICAgICBlbGVtZW50cy5wcmltVHlwZSA9IEdMX1RSSUFOR0xFUztcbiAgICAgICAgZWxlbWVudHMudmVydENvdW50ID0gb3B0aW9ucyB8IDA7XG4gICAgICAgIGVsZW1lbnRzLnR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgZGF0YSA9IG51bGw7XG4gICAgICAgIHZhciB1c2FnZSA9IEdMX1NUQVRJQ19EUkFXJDE7XG4gICAgICAgIHZhciBwcmltVHlwZSA9IC0xO1xuICAgICAgICB2YXIgdmVydENvdW50ID0gLTE7XG4gICAgICAgIHZhciBieXRlTGVuZ3RoID0gMDtcbiAgICAgICAgdmFyIGR0eXBlID0gMDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykgfHxcbiAgICAgICAgICAgIGlzVHlwZWRBcnJheShvcHRpb25zKSB8fFxuICAgICAgICAgICAgaXNOREFycmF5TGlrZShvcHRpb25zKSkge1xuICAgICAgICAgIGRhdGEgPSBvcHRpb25zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoZWNrJDEudHlwZShvcHRpb25zLCAnb2JqZWN0JywgJ2ludmFsaWQgYXJndW1lbnRzIGZvciBlbGVtZW50cycpO1xuICAgICAgICAgIGlmICgnZGF0YScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgZGF0YSA9IG9wdGlvbnMuZGF0YTtcbiAgICAgICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShkYXRhKSB8fFxuICAgICAgICAgICAgICAgIGlzVHlwZWRBcnJheShkYXRhKSB8fFxuICAgICAgICAgICAgICAgIGlzTkRBcnJheUxpa2UoZGF0YSksXG4gICAgICAgICAgICAgICAgJ2ludmFsaWQgZGF0YSBmb3IgZWxlbWVudCBidWZmZXInKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCd1c2FnZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIoXG4gICAgICAgICAgICAgIG9wdGlvbnMudXNhZ2UsXG4gICAgICAgICAgICAgIHVzYWdlVHlwZXMsXG4gICAgICAgICAgICAgICdpbnZhbGlkIGVsZW1lbnQgYnVmZmVyIHVzYWdlJyk7XG4gICAgICAgICAgICB1c2FnZSA9IHVzYWdlVHlwZXNbb3B0aW9ucy51c2FnZV07XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgncHJpbWl0aXZlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihcbiAgICAgICAgICAgICAgb3B0aW9ucy5wcmltaXRpdmUsXG4gICAgICAgICAgICAgIHByaW1UeXBlcyxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgZWxlbWVudCBidWZmZXIgcHJpbWl0aXZlJyk7XG4gICAgICAgICAgICBwcmltVHlwZSA9IHByaW1UeXBlc1tvcHRpb25zLnByaW1pdGl2ZV07XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnY291bnQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgICAgIHR5cGVvZiBvcHRpb25zLmNvdW50ID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLmNvdW50ID49IDAsXG4gICAgICAgICAgICAgICdpbnZhbGlkIHZlcnRleCBjb3VudCBmb3IgZWxlbWVudHMnKTtcbiAgICAgICAgICAgIHZlcnRDb3VudCA9IG9wdGlvbnMuY291bnQgfCAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ3R5cGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNoZWNrJDEucGFyYW1ldGVyKFxuICAgICAgICAgICAgICBvcHRpb25zLnR5cGUsXG4gICAgICAgICAgICAgIGVsZW1lbnRUeXBlcyxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgYnVmZmVyIHR5cGUnKTtcbiAgICAgICAgICAgIGR0eXBlID0gZWxlbWVudFR5cGVzW29wdGlvbnMudHlwZV07XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnbGVuZ3RoJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBieXRlTGVuZ3RoID0gb3B0aW9ucy5sZW5ndGggfCAwO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBieXRlTGVuZ3RoID0gdmVydENvdW50O1xuICAgICAgICAgICAgaWYgKGR0eXBlID09PSBHTF9VTlNJR05FRF9TSE9SVCQyIHx8IGR0eXBlID09PSBHTF9TSE9SVCQyKSB7XG4gICAgICAgICAgICAgIGJ5dGVMZW5ndGggKj0gMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZHR5cGUgPT09IEdMX1VOU0lHTkVEX0lOVCQyIHx8IGR0eXBlID09PSBHTF9JTlQkMikge1xuICAgICAgICAgICAgICBieXRlTGVuZ3RoICo9IDQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGluaXRFbGVtZW50cyhcbiAgICAgICAgICBlbGVtZW50cyxcbiAgICAgICAgICBkYXRhLFxuICAgICAgICAgIHVzYWdlLFxuICAgICAgICAgIHByaW1UeXBlLFxuICAgICAgICAgIHZlcnRDb3VudCxcbiAgICAgICAgICBieXRlTGVuZ3RoLFxuICAgICAgICAgIGR0eXBlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlZ2xFbGVtZW50c1xuICAgIH1cblxuICAgIHJlZ2xFbGVtZW50cyhvcHRpb25zKTtcblxuICAgIHJlZ2xFbGVtZW50cy5fcmVnbFR5cGUgPSAnZWxlbWVudHMnO1xuICAgIHJlZ2xFbGVtZW50cy5fZWxlbWVudHMgPSBlbGVtZW50cztcbiAgICByZWdsRWxlbWVudHMuc3ViZGF0YSA9IGZ1bmN0aW9uIChkYXRhLCBvZmZzZXQpIHtcbiAgICAgIGJ1ZmZlci5zdWJkYXRhKGRhdGEsIG9mZnNldCk7XG4gICAgICByZXR1cm4gcmVnbEVsZW1lbnRzXG4gICAgfTtcbiAgICByZWdsRWxlbWVudHMuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGRlc3Ryb3lFbGVtZW50cyhlbGVtZW50cyk7XG4gICAgfTtcblxuICAgIHJldHVybiByZWdsRWxlbWVudHNcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY3JlYXRlOiBjcmVhdGVFbGVtZW50cyxcbiAgICBjcmVhdGVTdHJlYW06IGNyZWF0ZUVsZW1lbnRTdHJlYW0sXG4gICAgZGVzdHJveVN0cmVhbTogZGVzdHJveUVsZW1lbnRTdHJlYW0sXG4gICAgZ2V0RWxlbWVudHM6IGZ1bmN0aW9uIChlbGVtZW50cykge1xuICAgICAgaWYgKHR5cGVvZiBlbGVtZW50cyA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgICAgIGVsZW1lbnRzLl9lbGVtZW50cyBpbnN0YW5jZW9mIFJFR0xFbGVtZW50QnVmZmVyKSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50cy5fZWxlbWVudHNcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfSxcbiAgICBjbGVhcjogZnVuY3Rpb24gKCkge1xuICAgICAgdmFsdWVzKGVsZW1lbnRTZXQpLmZvckVhY2goZGVzdHJveUVsZW1lbnRzKTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEZMT0FUID0gbmV3IEZsb2F0MzJBcnJheSgxKTtcbnZhciBJTlQgPSBuZXcgVWludDMyQXJyYXkoRkxPQVQuYnVmZmVyKTtcblxudmFyIEdMX1VOU0lHTkVEX1NIT1JUJDQgPSA1MTIzO1xuXG5mdW5jdGlvbiBjb252ZXJ0VG9IYWxmRmxvYXQgKGFycmF5KSB7XG4gIHZhciB1c2hvcnRzID0gcG9vbC5hbGxvY1R5cGUoR0xfVU5TSUdORURfU0hPUlQkNCwgYXJyYXkubGVuZ3RoKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGlzTmFOKGFycmF5W2ldKSkge1xuICAgICAgdXNob3J0c1tpXSA9IDB4ZmZmZjtcbiAgICB9IGVsc2UgaWYgKGFycmF5W2ldID09PSBJbmZpbml0eSkge1xuICAgICAgdXNob3J0c1tpXSA9IDB4N2MwMDtcbiAgICB9IGVsc2UgaWYgKGFycmF5W2ldID09PSAtSW5maW5pdHkpIHtcbiAgICAgIHVzaG9ydHNbaV0gPSAweGZjMDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIEZMT0FUWzBdID0gYXJyYXlbaV07XG4gICAgICB2YXIgeCA9IElOVFswXTtcblxuICAgICAgdmFyIHNnbiA9ICh4ID4+PiAzMSkgPDwgMTU7XG4gICAgICB2YXIgZXhwID0gKCh4IDw8IDEpID4+PiAyNCkgLSAxMjc7XG4gICAgICB2YXIgZnJhYyA9ICh4ID4+IDEzKSAmICgoMSA8PCAxMCkgLSAxKTtcblxuICAgICAgaWYgKGV4cCA8IC0yNCkge1xuICAgICAgICAvLyByb3VuZCBub24tcmVwcmVzZW50YWJsZSBkZW5vcm1hbHMgdG8gMFxuICAgICAgICB1c2hvcnRzW2ldID0gc2duO1xuICAgICAgfSBlbHNlIGlmIChleHAgPCAtMTQpIHtcbiAgICAgICAgLy8gaGFuZGxlIGRlbm9ybWFsc1xuICAgICAgICB2YXIgcyA9IC0xNCAtIGV4cDtcbiAgICAgICAgdXNob3J0c1tpXSA9IHNnbiArICgoZnJhYyArICgxIDw8IDEwKSkgPj4gcyk7XG4gICAgICB9IGVsc2UgaWYgKGV4cCA+IDE1KSB7XG4gICAgICAgIC8vIHJvdW5kIG92ZXJmbG93IHRvICsvLSBJbmZpbml0eVxuICAgICAgICB1c2hvcnRzW2ldID0gc2duICsgMHg3YzAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlIGNvbnZlcnQgZGlyZWN0bHlcbiAgICAgICAgdXNob3J0c1tpXSA9IHNnbiArICgoZXhwICsgMTUpIDw8IDEwKSArIGZyYWM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVzaG9ydHNcbn1cblxuZnVuY3Rpb24gaXNBcnJheUxpa2UgKHMpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkocykgfHwgaXNUeXBlZEFycmF5KHMpXG59XG5cbnZhciBpc1BvdzIkMSA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiAhKHYgJiAodiAtIDEpKSAmJiAoISF2KVxufTtcblxudmFyIEdMX0NPTVBSRVNTRURfVEVYVFVSRV9GT1JNQVRTID0gMHg4NkEzO1xuXG52YXIgR0xfVEVYVFVSRV8yRCQxID0gMHgwREUxO1xudmFyIEdMX1RFWFRVUkVfQ1VCRV9NQVAkMSA9IDB4ODUxMztcbnZhciBHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gkMSA9IDB4ODUxNTtcblxudmFyIEdMX1JHQkEkMSA9IDB4MTkwODtcbnZhciBHTF9BTFBIQSA9IDB4MTkwNjtcbnZhciBHTF9SR0IgPSAweDE5MDc7XG52YXIgR0xfTFVNSU5BTkNFID0gMHgxOTA5O1xudmFyIEdMX0xVTUlOQU5DRV9BTFBIQSA9IDB4MTkwQTtcblxudmFyIEdMX1JHQkE0ID0gMHg4MDU2O1xudmFyIEdMX1JHQjVfQTEgPSAweDgwNTc7XG52YXIgR0xfUkdCNTY1ID0gMHg4RDYyO1xuXG52YXIgR0xfVU5TSUdORURfU0hPUlRfNF80XzRfNCQxID0gMHg4MDMzO1xudmFyIEdMX1VOU0lHTkVEX1NIT1JUXzVfNV81XzEkMSA9IDB4ODAzNDtcbnZhciBHTF9VTlNJR05FRF9TSE9SVF81XzZfNSQxID0gMHg4MzYzO1xudmFyIEdMX1VOU0lHTkVEX0lOVF8yNF84X1dFQkdMJDEgPSAweDg0RkE7XG5cbnZhciBHTF9ERVBUSF9DT01QT05FTlQgPSAweDE5MDI7XG52YXIgR0xfREVQVEhfU1RFTkNJTCA9IDB4ODRGOTtcblxudmFyIEdMX1NSR0JfRVhUID0gMHg4QzQwO1xudmFyIEdMX1NSR0JfQUxQSEFfRVhUID0gMHg4QzQyO1xuXG52YXIgR0xfSEFMRl9GTE9BVF9PRVMkMSA9IDB4OEQ2MTtcblxudmFyIEdMX0NPTVBSRVNTRURfUkdCX1MzVENfRFhUMV9FWFQgPSAweDgzRjA7XG52YXIgR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUMV9FWFQgPSAweDgzRjE7XG52YXIgR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUM19FWFQgPSAweDgzRjI7XG52YXIgR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUNV9FWFQgPSAweDgzRjM7XG5cbnZhciBHTF9DT01QUkVTU0VEX1JHQl9BVENfV0VCR0wgPSAweDhDOTI7XG52YXIgR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19FWFBMSUNJVF9BTFBIQV9XRUJHTCA9IDB4OEM5MztcbnZhciBHTF9DT01QUkVTU0VEX1JHQkFfQVRDX0lOVEVSUE9MQVRFRF9BTFBIQV9XRUJHTCA9IDB4ODdFRTtcblxudmFyIEdMX0NPTVBSRVNTRURfUkdCX1BWUlRDXzRCUFBWMV9JTUcgPSAweDhDMDA7XG52YXIgR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfMkJQUFYxX0lNRyA9IDB4OEMwMTtcbnZhciBHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfNEJQUFYxX0lNRyA9IDB4OEMwMjtcbnZhciBHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfMkJQUFYxX0lNRyA9IDB4OEMwMztcblxudmFyIEdMX0NPTVBSRVNTRURfUkdCX0VUQzFfV0VCR0wgPSAweDhENjQ7XG5cbnZhciBHTF9VTlNJR05FRF9CWVRFJDUgPSAweDE0MDE7XG52YXIgR0xfVU5TSUdORURfU0hPUlQkMyA9IDB4MTQwMztcbnZhciBHTF9VTlNJR05FRF9JTlQkMyA9IDB4MTQwNTtcbnZhciBHTF9GTE9BVCQ0ID0gMHgxNDA2O1xuXG52YXIgR0xfVEVYVFVSRV9XUkFQX1MgPSAweDI4MDI7XG52YXIgR0xfVEVYVFVSRV9XUkFQX1QgPSAweDI4MDM7XG5cbnZhciBHTF9SRVBFQVQgPSAweDI5MDE7XG52YXIgR0xfQ0xBTVBfVE9fRURHRSQxID0gMHg4MTJGO1xudmFyIEdMX01JUlJPUkVEX1JFUEVBVCA9IDB4ODM3MDtcblxudmFyIEdMX1RFWFRVUkVfTUFHX0ZJTFRFUiA9IDB4MjgwMDtcbnZhciBHTF9URVhUVVJFX01JTl9GSUxURVIgPSAweDI4MDE7XG5cbnZhciBHTF9ORUFSRVNUJDEgPSAweDI2MDA7XG52YXIgR0xfTElORUFSID0gMHgyNjAxO1xudmFyIEdMX05FQVJFU1RfTUlQTUFQX05FQVJFU1QkMSA9IDB4MjcwMDtcbnZhciBHTF9MSU5FQVJfTUlQTUFQX05FQVJFU1QkMSA9IDB4MjcwMTtcbnZhciBHTF9ORUFSRVNUX01JUE1BUF9MSU5FQVIkMSA9IDB4MjcwMjtcbnZhciBHTF9MSU5FQVJfTUlQTUFQX0xJTkVBUiQxID0gMHgyNzAzO1xuXG52YXIgR0xfR0VORVJBVEVfTUlQTUFQX0hJTlQgPSAweDgxOTI7XG52YXIgR0xfRE9OVF9DQVJFID0gMHgxMTAwO1xudmFyIEdMX0ZBU1RFU1QgPSAweDExMDE7XG52YXIgR0xfTklDRVNUID0gMHgxMTAyO1xuXG52YXIgR0xfVEVYVFVSRV9NQVhfQU5JU09UUk9QWV9FWFQgPSAweDg0RkU7XG5cbnZhciBHTF9VTlBBQ0tfQUxJR05NRU5UID0gMHgwQ0Y1O1xudmFyIEdMX1VOUEFDS19GTElQX1lfV0VCR0wgPSAweDkyNDA7XG52YXIgR0xfVU5QQUNLX1BSRU1VTFRJUExZX0FMUEhBX1dFQkdMID0gMHg5MjQxO1xudmFyIEdMX1VOUEFDS19DT0xPUlNQQUNFX0NPTlZFUlNJT05fV0VCR0wgPSAweDkyNDM7XG5cbnZhciBHTF9CUk9XU0VSX0RFRkFVTFRfV0VCR0wgPSAweDkyNDQ7XG5cbnZhciBHTF9URVhUVVJFMCQxID0gMHg4NEMwO1xuXG52YXIgTUlQTUFQX0ZJTFRFUlMgPSBbXG4gIEdMX05FQVJFU1RfTUlQTUFQX05FQVJFU1QkMSxcbiAgR0xfTkVBUkVTVF9NSVBNQVBfTElORUFSJDEsXG4gIEdMX0xJTkVBUl9NSVBNQVBfTkVBUkVTVCQxLFxuICBHTF9MSU5FQVJfTUlQTUFQX0xJTkVBUiQxXG5dO1xuXG52YXIgQ0hBTk5FTFNfRk9STUFUID0gW1xuICAwLFxuICBHTF9MVU1JTkFOQ0UsXG4gIEdMX0xVTUlOQU5DRV9BTFBIQSxcbiAgR0xfUkdCLFxuICBHTF9SR0JBJDFcbl07XG5cbnZhciBGT1JNQVRfQ0hBTk5FTFMgPSB7fTtcbkZPUk1BVF9DSEFOTkVMU1tHTF9MVU1JTkFOQ0VdID1cbkZPUk1BVF9DSEFOTkVMU1tHTF9BTFBIQV0gPVxuRk9STUFUX0NIQU5ORUxTW0dMX0RFUFRIX0NPTVBPTkVOVF0gPSAxO1xuRk9STUFUX0NIQU5ORUxTW0dMX0RFUFRIX1NURU5DSUxdID1cbkZPUk1BVF9DSEFOTkVMU1tHTF9MVU1JTkFOQ0VfQUxQSEFdID0gMjtcbkZPUk1BVF9DSEFOTkVMU1tHTF9SR0JdID1cbkZPUk1BVF9DSEFOTkVMU1tHTF9TUkdCX0VYVF0gPSAzO1xuRk9STUFUX0NIQU5ORUxTW0dMX1JHQkEkMV0gPVxuRk9STUFUX0NIQU5ORUxTW0dMX1NSR0JfQUxQSEFfRVhUXSA9IDQ7XG5cbmZ1bmN0aW9uIG9iamVjdE5hbWUgKHN0cikge1xuICByZXR1cm4gJ1tvYmplY3QgJyArIHN0ciArICddJ1xufVxuXG52YXIgQ0FOVkFTX0NMQVNTID0gb2JqZWN0TmFtZSgnSFRNTENhbnZhc0VsZW1lbnQnKTtcbnZhciBDT05URVhUMkRfQ0xBU1MgPSBvYmplY3ROYW1lKCdDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQnKTtcbnZhciBCSVRNQVBfQ0xBU1MgPSBvYmplY3ROYW1lKCdJbWFnZUJpdG1hcCcpO1xudmFyIElNQUdFX0NMQVNTID0gb2JqZWN0TmFtZSgnSFRNTEltYWdlRWxlbWVudCcpO1xudmFyIFZJREVPX0NMQVNTID0gb2JqZWN0TmFtZSgnSFRNTFZpZGVvRWxlbWVudCcpO1xuXG52YXIgUElYRUxfQ0xBU1NFUyA9IE9iamVjdC5rZXlzKGFycmF5VHlwZXMpLmNvbmNhdChbXG4gIENBTlZBU19DTEFTUyxcbiAgQ09OVEVYVDJEX0NMQVNTLFxuICBCSVRNQVBfQ0xBU1MsXG4gIElNQUdFX0NMQVNTLFxuICBWSURFT19DTEFTU1xuXSk7XG5cbi8vIGZvciBldmVyeSB0ZXh0dXJlIHR5cGUsIHN0b3JlXG4vLyB0aGUgc2l6ZSBpbiBieXRlcy5cbnZhciBUWVBFX1NJWkVTID0gW107XG5UWVBFX1NJWkVTW0dMX1VOU0lHTkVEX0JZVEUkNV0gPSAxO1xuVFlQRV9TSVpFU1tHTF9GTE9BVCQ0XSA9IDQ7XG5UWVBFX1NJWkVTW0dMX0hBTEZfRkxPQVRfT0VTJDFdID0gMjtcblxuVFlQRV9TSVpFU1tHTF9VTlNJR05FRF9TSE9SVCQzXSA9IDI7XG5UWVBFX1NJWkVTW0dMX1VOU0lHTkVEX0lOVCQzXSA9IDQ7XG5cbnZhciBGT1JNQVRfU0laRVNfU1BFQ0lBTCA9IFtdO1xuRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfUkdCQTRdID0gMjtcbkZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX1JHQjVfQTFdID0gMjtcbkZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX1JHQjU2NV0gPSAyO1xuRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfREVQVEhfU1RFTkNJTF0gPSA0O1xuXG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQl9TM1RDX0RYVDFfRVhUXSA9IDAuNTtcbkZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDFfRVhUXSA9IDAuNTtcbkZPUk1BVF9TSVpFU19TUEVDSUFMW0dMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDNfRVhUXSA9IDE7XG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQ1X0VYVF0gPSAxO1xuXG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQl9BVENfV0VCR0xdID0gMC41O1xuRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19FWFBMSUNJVF9BTFBIQV9XRUJHTF0gPSAxO1xuRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19JTlRFUlBPTEFURURfQUxQSEFfV0VCR0xdID0gMTtcblxuRk9STUFUX1NJWkVTX1NQRUNJQUxbR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfNEJQUFYxX0lNR10gPSAwLjU7XG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQl9QVlJUQ18yQlBQVjFfSU1HXSA9IDAuMjU7XG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfNEJQUFYxX0lNR10gPSAwLjU7XG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQkFfUFZSVENfMkJQUFYxX0lNR10gPSAwLjI1O1xuXG5GT1JNQVRfU0laRVNfU1BFQ0lBTFtHTF9DT01QUkVTU0VEX1JHQl9FVEMxX1dFQkdMXSA9IDAuNTtcblxuZnVuY3Rpb24gaXNOdW1lcmljQXJyYXkgKGFycikge1xuICByZXR1cm4gKFxuICAgIEFycmF5LmlzQXJyYXkoYXJyKSAmJlxuICAgIChhcnIubGVuZ3RoID09PSAwIHx8XG4gICAgdHlwZW9mIGFyclswXSA9PT0gJ251bWJlcicpKVxufVxuXG5mdW5jdGlvbiBpc1JlY3RBcnJheSAoYXJyKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShhcnIpKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgdmFyIHdpZHRoID0gYXJyLmxlbmd0aDtcbiAgaWYgKHdpZHRoID09PSAwIHx8ICFpc0FycmF5TGlrZShhcnJbMF0pKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgcmV0dXJuIHRydWVcbn1cblxuZnVuY3Rpb24gY2xhc3NTdHJpbmcgKHgpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KVxufVxuXG5mdW5jdGlvbiBpc0NhbnZhc0VsZW1lbnQgKG9iamVjdCkge1xuICByZXR1cm4gY2xhc3NTdHJpbmcob2JqZWN0KSA9PT0gQ0FOVkFTX0NMQVNTXG59XG5cbmZ1bmN0aW9uIGlzQ29udGV4dDJEIChvYmplY3QpIHtcbiAgcmV0dXJuIGNsYXNzU3RyaW5nKG9iamVjdCkgPT09IENPTlRFWFQyRF9DTEFTU1xufVxuXG5mdW5jdGlvbiBpc0JpdG1hcCAob2JqZWN0KSB7XG4gIHJldHVybiBjbGFzc1N0cmluZyhvYmplY3QpID09PSBCSVRNQVBfQ0xBU1Ncbn1cblxuZnVuY3Rpb24gaXNJbWFnZUVsZW1lbnQgKG9iamVjdCkge1xuICByZXR1cm4gY2xhc3NTdHJpbmcob2JqZWN0KSA9PT0gSU1BR0VfQ0xBU1Ncbn1cblxuZnVuY3Rpb24gaXNWaWRlb0VsZW1lbnQgKG9iamVjdCkge1xuICByZXR1cm4gY2xhc3NTdHJpbmcob2JqZWN0KSA9PT0gVklERU9fQ0xBU1Ncbn1cblxuZnVuY3Rpb24gaXNQaXhlbERhdGEgKG9iamVjdCkge1xuICBpZiAoIW9iamVjdCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIHZhciBjbGFzc05hbWUgPSBjbGFzc1N0cmluZyhvYmplY3QpO1xuICBpZiAoUElYRUxfQ0xBU1NFUy5pbmRleE9mKGNsYXNzTmFtZSkgPj0gMCkge1xuICAgIHJldHVybiB0cnVlXG4gIH1cbiAgcmV0dXJuIChcbiAgICBpc051bWVyaWNBcnJheShvYmplY3QpIHx8XG4gICAgaXNSZWN0QXJyYXkob2JqZWN0KSB8fFxuICAgIGlzTkRBcnJheUxpa2Uob2JqZWN0KSlcbn1cblxuZnVuY3Rpb24gdHlwZWRBcnJheUNvZGUkMSAoZGF0YSkge1xuICByZXR1cm4gYXJyYXlUeXBlc1tPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSldIHwgMFxufVxuXG5mdW5jdGlvbiBjb252ZXJ0RGF0YSAocmVzdWx0LCBkYXRhKSB7XG4gIHZhciBuID0gZGF0YS5sZW5ndGg7XG4gIHN3aXRjaCAocmVzdWx0LnR5cGUpIHtcbiAgICBjYXNlIEdMX1VOU0lHTkVEX0JZVEUkNTpcbiAgICBjYXNlIEdMX1VOU0lHTkVEX1NIT1JUJDM6XG4gICAgY2FzZSBHTF9VTlNJR05FRF9JTlQkMzpcbiAgICBjYXNlIEdMX0ZMT0FUJDQ6XG4gICAgICB2YXIgY29udmVydGVkID0gcG9vbC5hbGxvY1R5cGUocmVzdWx0LnR5cGUsIG4pO1xuICAgICAgY29udmVydGVkLnNldChkYXRhKTtcbiAgICAgIHJlc3VsdC5kYXRhID0gY29udmVydGVkO1xuICAgICAgYnJlYWtcblxuICAgIGNhc2UgR0xfSEFMRl9GTE9BVF9PRVMkMTpcbiAgICAgIHJlc3VsdC5kYXRhID0gY29udmVydFRvSGFsZkZsb2F0KGRhdGEpO1xuICAgICAgYnJlYWtcblxuICAgIGRlZmF1bHQ6XG4gICAgICBjaGVjayQxLnJhaXNlKCd1bnN1cHBvcnRlZCB0ZXh0dXJlIHR5cGUsIG11c3Qgc3BlY2lmeSBhIHR5cGVkIGFycmF5Jyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcHJlQ29udmVydCAoaW1hZ2UsIG4pIHtcbiAgcmV0dXJuIHBvb2wuYWxsb2NUeXBlKFxuICAgIGltYWdlLnR5cGUgPT09IEdMX0hBTEZfRkxPQVRfT0VTJDFcbiAgICAgID8gR0xfRkxPQVQkNFxuICAgICAgOiBpbWFnZS50eXBlLCBuKVxufVxuXG5mdW5jdGlvbiBwb3N0Q29udmVydCAoaW1hZ2UsIGRhdGEpIHtcbiAgaWYgKGltYWdlLnR5cGUgPT09IEdMX0hBTEZfRkxPQVRfT0VTJDEpIHtcbiAgICBpbWFnZS5kYXRhID0gY29udmVydFRvSGFsZkZsb2F0KGRhdGEpO1xuICAgIHBvb2wuZnJlZVR5cGUoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgaW1hZ2UuZGF0YSA9IGRhdGE7XG4gIH1cbn1cblxuZnVuY3Rpb24gdHJhbnNwb3NlRGF0YSAoaW1hZ2UsIGFycmF5LCBzdHJpZGVYLCBzdHJpZGVZLCBzdHJpZGVDLCBvZmZzZXQpIHtcbiAgdmFyIHcgPSBpbWFnZS53aWR0aDtcbiAgdmFyIGggPSBpbWFnZS5oZWlnaHQ7XG4gIHZhciBjID0gaW1hZ2UuY2hhbm5lbHM7XG4gIHZhciBuID0gdyAqIGggKiBjO1xuICB2YXIgZGF0YSA9IHByZUNvbnZlcnQoaW1hZ2UsIG4pO1xuXG4gIHZhciBwID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoOyArK2kpIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHc7ICsraikge1xuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBjOyArK2spIHtcbiAgICAgICAgZGF0YVtwKytdID0gYXJyYXlbc3RyaWRlWCAqIGogKyBzdHJpZGVZICogaSArIHN0cmlkZUMgKiBrICsgb2Zmc2V0XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwb3N0Q29udmVydChpbWFnZSwgZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGdldFRleHR1cmVTaXplIChmb3JtYXQsIHR5cGUsIHdpZHRoLCBoZWlnaHQsIGlzTWlwbWFwLCBpc0N1YmUpIHtcbiAgdmFyIHM7XG4gIGlmICh0eXBlb2YgRk9STUFUX1NJWkVTX1NQRUNJQUxbZm9ybWF0XSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAvLyB3ZSBoYXZlIGEgc3BlY2lhbCBhcnJheSBmb3IgZGVhbGluZyB3aXRoIHdlaXJkIGNvbG9yIGZvcm1hdHMgc3VjaCBhcyBSR0I1QTFcbiAgICBzID0gRk9STUFUX1NJWkVTX1NQRUNJQUxbZm9ybWF0XTtcbiAgfSBlbHNlIHtcbiAgICBzID0gRk9STUFUX0NIQU5ORUxTW2Zvcm1hdF0gKiBUWVBFX1NJWkVTW3R5cGVdO1xuICB9XG5cbiAgaWYgKGlzQ3ViZSkge1xuICAgIHMgKj0gNjtcbiAgfVxuXG4gIGlmIChpc01pcG1hcCkge1xuICAgIC8vIGNvbXB1dGUgdGhlIHRvdGFsIHNpemUgb2YgYWxsIHRoZSBtaXBtYXBzLlxuICAgIHZhciB0b3RhbCA9IDA7XG5cbiAgICB2YXIgdyA9IHdpZHRoO1xuICAgIHdoaWxlICh3ID49IDEpIHtcbiAgICAgIC8vIHdlIGNhbiBvbmx5IHVzZSBtaXBtYXBzIG9uIGEgc3F1YXJlIGltYWdlLFxuICAgICAgLy8gc28gd2UgY2FuIHNpbXBseSB1c2UgdGhlIHdpZHRoIGFuZCBpZ25vcmUgdGhlIGhlaWdodDpcbiAgICAgIHRvdGFsICs9IHMgKiB3ICogdztcbiAgICAgIHcgLz0gMjtcbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHMgKiB3aWR0aCAqIGhlaWdodFxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVTZXQgKFxuICBnbCwgZXh0ZW5zaW9ucywgbGltaXRzLCByZWdsUG9sbCwgY29udGV4dFN0YXRlLCBzdGF0cywgY29uZmlnKSB7XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gSW5pdGlhbGl6ZSBjb25zdGFudHMgYW5kIHBhcmFtZXRlciB0YWJsZXMgaGVyZVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIHZhciBtaXBtYXBIaW50ID0ge1xuICAgIFwiZG9uJ3QgY2FyZVwiOiBHTF9ET05UX0NBUkUsXG4gICAgJ2RvbnQgY2FyZSc6IEdMX0RPTlRfQ0FSRSxcbiAgICAnbmljZSc6IEdMX05JQ0VTVCxcbiAgICAnZmFzdCc6IEdMX0ZBU1RFU1RcbiAgfTtcblxuICB2YXIgd3JhcE1vZGVzID0ge1xuICAgICdyZXBlYXQnOiBHTF9SRVBFQVQsXG4gICAgJ2NsYW1wJzogR0xfQ0xBTVBfVE9fRURHRSQxLFxuICAgICdtaXJyb3InOiBHTF9NSVJST1JFRF9SRVBFQVRcbiAgfTtcblxuICB2YXIgbWFnRmlsdGVycyA9IHtcbiAgICAnbmVhcmVzdCc6IEdMX05FQVJFU1QkMSxcbiAgICAnbGluZWFyJzogR0xfTElORUFSXG4gIH07XG5cbiAgdmFyIG1pbkZpbHRlcnMgPSBleHRlbmQoe1xuICAgICdtaXBtYXAnOiBHTF9MSU5FQVJfTUlQTUFQX0xJTkVBUiQxLFxuICAgICduZWFyZXN0IG1pcG1hcCBuZWFyZXN0JzogR0xfTkVBUkVTVF9NSVBNQVBfTkVBUkVTVCQxLFxuICAgICdsaW5lYXIgbWlwbWFwIG5lYXJlc3QnOiBHTF9MSU5FQVJfTUlQTUFQX05FQVJFU1QkMSxcbiAgICAnbmVhcmVzdCBtaXBtYXAgbGluZWFyJzogR0xfTkVBUkVTVF9NSVBNQVBfTElORUFSJDEsXG4gICAgJ2xpbmVhciBtaXBtYXAgbGluZWFyJzogR0xfTElORUFSX01JUE1BUF9MSU5FQVIkMVxuICB9LCBtYWdGaWx0ZXJzKTtcblxuICB2YXIgY29sb3JTcGFjZSA9IHtcbiAgICAnbm9uZSc6IDAsXG4gICAgJ2Jyb3dzZXInOiBHTF9CUk9XU0VSX0RFRkFVTFRfV0VCR0xcbiAgfTtcblxuICB2YXIgdGV4dHVyZVR5cGVzID0ge1xuICAgICd1aW50OCc6IEdMX1VOU0lHTkVEX0JZVEUkNSxcbiAgICAncmdiYTQnOiBHTF9VTlNJR05FRF9TSE9SVF80XzRfNF80JDEsXG4gICAgJ3JnYjU2NSc6IEdMX1VOU0lHTkVEX1NIT1JUXzVfNl81JDEsXG4gICAgJ3JnYjUgYTEnOiBHTF9VTlNJR05FRF9TSE9SVF81XzVfNV8xJDFcbiAgfTtcblxuICB2YXIgdGV4dHVyZUZvcm1hdHMgPSB7XG4gICAgJ2FscGhhJzogR0xfQUxQSEEsXG4gICAgJ2x1bWluYW5jZSc6IEdMX0xVTUlOQU5DRSxcbiAgICAnbHVtaW5hbmNlIGFscGhhJzogR0xfTFVNSU5BTkNFX0FMUEhBLFxuICAgICdyZ2InOiBHTF9SR0IsXG4gICAgJ3JnYmEnOiBHTF9SR0JBJDEsXG4gICAgJ3JnYmE0JzogR0xfUkdCQTQsXG4gICAgJ3JnYjUgYTEnOiBHTF9SR0I1X0ExLFxuICAgICdyZ2I1NjUnOiBHTF9SR0I1NjVcbiAgfTtcblxuICB2YXIgY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzID0ge307XG5cbiAgaWYgKGV4dGVuc2lvbnMuZXh0X3NyZ2IpIHtcbiAgICB0ZXh0dXJlRm9ybWF0cy5zcmdiID0gR0xfU1JHQl9FWFQ7XG4gICAgdGV4dHVyZUZvcm1hdHMuc3JnYmEgPSBHTF9TUkdCX0FMUEhBX0VYVDtcbiAgfVxuXG4gIGlmIChleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0KSB7XG4gICAgdGV4dHVyZVR5cGVzLmZsb2F0MzIgPSB0ZXh0dXJlVHlwZXMuZmxvYXQgPSBHTF9GTE9BVCQ0O1xuICB9XG5cbiAgaWYgKGV4dGVuc2lvbnMub2VzX3RleHR1cmVfaGFsZl9mbG9hdCkge1xuICAgIHRleHR1cmVUeXBlc1snZmxvYXQxNiddID0gdGV4dHVyZVR5cGVzWydoYWxmIGZsb2F0J10gPSBHTF9IQUxGX0ZMT0FUX09FUyQxO1xuICB9XG5cbiAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfZGVwdGhfdGV4dHVyZSkge1xuICAgIGV4dGVuZCh0ZXh0dXJlRm9ybWF0cywge1xuICAgICAgJ2RlcHRoJzogR0xfREVQVEhfQ09NUE9ORU5ULFxuICAgICAgJ2RlcHRoIHN0ZW5jaWwnOiBHTF9ERVBUSF9TVEVOQ0lMXG4gICAgfSk7XG5cbiAgICBleHRlbmQodGV4dHVyZVR5cGVzLCB7XG4gICAgICAndWludDE2JzogR0xfVU5TSUdORURfU0hPUlQkMyxcbiAgICAgICd1aW50MzInOiBHTF9VTlNJR05FRF9JTlQkMyxcbiAgICAgICdkZXB0aCBzdGVuY2lsJzogR0xfVU5TSUdORURfSU5UXzI0XzhfV0VCR0wkMVxuICAgIH0pO1xuICB9XG5cbiAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfY29tcHJlc3NlZF90ZXh0dXJlX3MzdGMpIHtcbiAgICBleHRlbmQoY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzLCB7XG4gICAgICAncmdiIHMzdGMgZHh0MSc6IEdMX0NPTVBSRVNTRURfUkdCX1MzVENfRFhUMV9FWFQsXG4gICAgICAncmdiYSBzM3RjIGR4dDEnOiBHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQxX0VYVCxcbiAgICAgICdyZ2JhIHMzdGMgZHh0Myc6IEdMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDNfRVhULFxuICAgICAgJ3JnYmEgczN0YyBkeHQ1JzogR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUNV9FWFRcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChleHRlbnNpb25zLndlYmdsX2NvbXByZXNzZWRfdGV4dHVyZV9hdGMpIHtcbiAgICBleHRlbmQoY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzLCB7XG4gICAgICAncmdiIGF0Yyc6IEdMX0NPTVBSRVNTRURfUkdCX0FUQ19XRUJHTCxcbiAgICAgICdyZ2JhIGF0YyBleHBsaWNpdCBhbHBoYSc6IEdMX0NPTVBSRVNTRURfUkdCQV9BVENfRVhQTElDSVRfQUxQSEFfV0VCR0wsXG4gICAgICAncmdiYSBhdGMgaW50ZXJwb2xhdGVkIGFscGhhJzogR0xfQ09NUFJFU1NFRF9SR0JBX0FUQ19JTlRFUlBPTEFURURfQUxQSEFfV0VCR0xcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChleHRlbnNpb25zLndlYmdsX2NvbXByZXNzZWRfdGV4dHVyZV9wdnJ0Yykge1xuICAgIGV4dGVuZChjb21wcmVzc2VkVGV4dHVyZUZvcm1hdHMsIHtcbiAgICAgICdyZ2IgcHZydGMgNGJwcHYxJzogR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfNEJQUFYxX0lNRyxcbiAgICAgICdyZ2IgcHZydGMgMmJwcHYxJzogR0xfQ09NUFJFU1NFRF9SR0JfUFZSVENfMkJQUFYxX0lNRyxcbiAgICAgICdyZ2JhIHB2cnRjIDRicHB2MSc6IEdMX0NPTVBSRVNTRURfUkdCQV9QVlJUQ180QlBQVjFfSU1HLFxuICAgICAgJ3JnYmEgcHZydGMgMmJwcHYxJzogR0xfQ09NUFJFU1NFRF9SR0JBX1BWUlRDXzJCUFBWMV9JTUdcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChleHRlbnNpb25zLndlYmdsX2NvbXByZXNzZWRfdGV4dHVyZV9ldGMxKSB7XG4gICAgY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzWydyZ2IgZXRjMSddID0gR0xfQ09NUFJFU1NFRF9SR0JfRVRDMV9XRUJHTDtcbiAgfVxuXG4gIC8vIENvcHkgb3ZlciBhbGwgdGV4dHVyZSBmb3JtYXRzXG4gIHZhciBzdXBwb3J0ZWRDb21wcmVzc2VkRm9ybWF0cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKFxuICAgIGdsLmdldFBhcmFtZXRlcihHTF9DT01QUkVTU0VEX1RFWFRVUkVfRk9STUFUUykpO1xuICBPYmplY3Qua2V5cyhjb21wcmVzc2VkVGV4dHVyZUZvcm1hdHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB2YXIgZm9ybWF0ID0gY29tcHJlc3NlZFRleHR1cmVGb3JtYXRzW25hbWVdO1xuICAgIGlmIChzdXBwb3J0ZWRDb21wcmVzc2VkRm9ybWF0cy5pbmRleE9mKGZvcm1hdCkgPj0gMCkge1xuICAgICAgdGV4dHVyZUZvcm1hdHNbbmFtZV0gPSBmb3JtYXQ7XG4gICAgfVxuICB9KTtcblxuICB2YXIgc3VwcG9ydGVkRm9ybWF0cyA9IE9iamVjdC5rZXlzKHRleHR1cmVGb3JtYXRzKTtcbiAgbGltaXRzLnRleHR1cmVGb3JtYXRzID0gc3VwcG9ydGVkRm9ybWF0cztcblxuICAvLyBhc3NvY2lhdGUgd2l0aCBldmVyeSBmb3JtYXQgc3RyaW5nIGl0c1xuICAvLyBjb3JyZXNwb25kaW5nIEdMLXZhbHVlLlxuICB2YXIgdGV4dHVyZUZvcm1hdHNJbnZlcnQgPSBbXTtcbiAgT2JqZWN0LmtleXModGV4dHVyZUZvcm1hdHMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciB2YWwgPSB0ZXh0dXJlRm9ybWF0c1trZXldO1xuICAgIHRleHR1cmVGb3JtYXRzSW52ZXJ0W3ZhbF0gPSBrZXk7XG4gIH0pO1xuXG4gIC8vIGFzc29jaWF0ZSB3aXRoIGV2ZXJ5IHR5cGUgc3RyaW5nIGl0c1xuICAvLyBjb3JyZXNwb25kaW5nIEdMLXZhbHVlLlxuICB2YXIgdGV4dHVyZVR5cGVzSW52ZXJ0ID0gW107XG4gIE9iamVjdC5rZXlzKHRleHR1cmVUeXBlcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIHZhbCA9IHRleHR1cmVUeXBlc1trZXldO1xuICAgIHRleHR1cmVUeXBlc0ludmVydFt2YWxdID0ga2V5O1xuICB9KTtcblxuICB2YXIgbWFnRmlsdGVyc0ludmVydCA9IFtdO1xuICBPYmplY3Qua2V5cyhtYWdGaWx0ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgdmFsID0gbWFnRmlsdGVyc1trZXldO1xuICAgIG1hZ0ZpbHRlcnNJbnZlcnRbdmFsXSA9IGtleTtcbiAgfSk7XG5cbiAgdmFyIG1pbkZpbHRlcnNJbnZlcnQgPSBbXTtcbiAgT2JqZWN0LmtleXMobWluRmlsdGVycykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIHZhbCA9IG1pbkZpbHRlcnNba2V5XTtcbiAgICBtaW5GaWx0ZXJzSW52ZXJ0W3ZhbF0gPSBrZXk7XG4gIH0pO1xuXG4gIHZhciB3cmFwTW9kZXNJbnZlcnQgPSBbXTtcbiAgT2JqZWN0LmtleXMod3JhcE1vZGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgdmFsID0gd3JhcE1vZGVzW2tleV07XG4gICAgd3JhcE1vZGVzSW52ZXJ0W3ZhbF0gPSBrZXk7XG4gIH0pO1xuXG4gIC8vIGNvbG9yRm9ybWF0c1tdIGdpdmVzIHRoZSBmb3JtYXQgKGNoYW5uZWxzKSBhc3NvY2lhdGVkIHRvIGFuXG4gIC8vIGludGVybmFsZm9ybWF0XG4gIHZhciBjb2xvckZvcm1hdHMgPSBzdXBwb3J0ZWRGb3JtYXRzLnJlZHVjZShmdW5jdGlvbiAoY29sb3IsIGtleSkge1xuICAgIHZhciBnbGVudW0gPSB0ZXh0dXJlRm9ybWF0c1trZXldO1xuICAgIGlmIChnbGVudW0gPT09IEdMX0xVTUlOQU5DRSB8fFxuICAgICAgICBnbGVudW0gPT09IEdMX0FMUEhBIHx8XG4gICAgICAgIGdsZW51bSA9PT0gR0xfTFVNSU5BTkNFIHx8XG4gICAgICAgIGdsZW51bSA9PT0gR0xfTFVNSU5BTkNFX0FMUEhBIHx8XG4gICAgICAgIGdsZW51bSA9PT0gR0xfREVQVEhfQ09NUE9ORU5UIHx8XG4gICAgICAgIGdsZW51bSA9PT0gR0xfREVQVEhfU1RFTkNJTCkge1xuICAgICAgY29sb3JbZ2xlbnVtXSA9IGdsZW51bTtcbiAgICB9IGVsc2UgaWYgKGdsZW51bSA9PT0gR0xfUkdCNV9BMSB8fCBrZXkuaW5kZXhPZigncmdiYScpID49IDApIHtcbiAgICAgIGNvbG9yW2dsZW51bV0gPSBHTF9SR0JBJDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbG9yW2dsZW51bV0gPSBHTF9SR0I7XG4gICAgfVxuICAgIHJldHVybiBjb2xvclxuICB9LCB7fSk7XG5cbiAgZnVuY3Rpb24gVGV4RmxhZ3MgKCkge1xuICAgIC8vIGZvcm1hdCBpbmZvXG4gICAgdGhpcy5pbnRlcm5hbGZvcm1hdCA9IEdMX1JHQkEkMTtcbiAgICB0aGlzLmZvcm1hdCA9IEdMX1JHQkEkMTtcbiAgICB0aGlzLnR5cGUgPSBHTF9VTlNJR05FRF9CWVRFJDU7XG4gICAgdGhpcy5jb21wcmVzc2VkID0gZmFsc2U7XG5cbiAgICAvLyBwaXhlbCBzdG9yYWdlXG4gICAgdGhpcy5wcmVtdWx0aXBseUFscGhhID0gZmFsc2U7XG4gICAgdGhpcy5mbGlwWSA9IGZhbHNlO1xuICAgIHRoaXMudW5wYWNrQWxpZ25tZW50ID0gMTtcbiAgICB0aGlzLmNvbG9yU3BhY2UgPSBHTF9CUk9XU0VSX0RFRkFVTFRfV0VCR0w7XG5cbiAgICAvLyBzaGFwZSBpbmZvXG4gICAgdGhpcy53aWR0aCA9IDA7XG4gICAgdGhpcy5oZWlnaHQgPSAwO1xuICAgIHRoaXMuY2hhbm5lbHMgPSAwO1xuICB9XG5cbiAgZnVuY3Rpb24gY29weUZsYWdzIChyZXN1bHQsIG90aGVyKSB7XG4gICAgcmVzdWx0LmludGVybmFsZm9ybWF0ID0gb3RoZXIuaW50ZXJuYWxmb3JtYXQ7XG4gICAgcmVzdWx0LmZvcm1hdCA9IG90aGVyLmZvcm1hdDtcbiAgICByZXN1bHQudHlwZSA9IG90aGVyLnR5cGU7XG4gICAgcmVzdWx0LmNvbXByZXNzZWQgPSBvdGhlci5jb21wcmVzc2VkO1xuXG4gICAgcmVzdWx0LnByZW11bHRpcGx5QWxwaGEgPSBvdGhlci5wcmVtdWx0aXBseUFscGhhO1xuICAgIHJlc3VsdC5mbGlwWSA9IG90aGVyLmZsaXBZO1xuICAgIHJlc3VsdC51bnBhY2tBbGlnbm1lbnQgPSBvdGhlci51bnBhY2tBbGlnbm1lbnQ7XG4gICAgcmVzdWx0LmNvbG9yU3BhY2UgPSBvdGhlci5jb2xvclNwYWNlO1xuXG4gICAgcmVzdWx0LndpZHRoID0gb3RoZXIud2lkdGg7XG4gICAgcmVzdWx0LmhlaWdodCA9IG90aGVyLmhlaWdodDtcbiAgICByZXN1bHQuY2hhbm5lbHMgPSBvdGhlci5jaGFubmVscztcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlRmxhZ3MgKGZsYWdzLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zICE9PSAnb2JqZWN0JyB8fCAhb3B0aW9ucykge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCdwcmVtdWx0aXBseUFscGhhJyBpbiBvcHRpb25zKSB7XG4gICAgICBjaGVjayQxLnR5cGUob3B0aW9ucy5wcmVtdWx0aXBseUFscGhhLCAnYm9vbGVhbicsXG4gICAgICAgICdpbnZhbGlkIHByZW11bHRpcGx5QWxwaGEnKTtcbiAgICAgIGZsYWdzLnByZW11bHRpcGx5QWxwaGEgPSBvcHRpb25zLnByZW11bHRpcGx5QWxwaGE7XG4gICAgfVxuXG4gICAgaWYgKCdmbGlwWScgaW4gb3B0aW9ucykge1xuICAgICAgY2hlY2skMS50eXBlKG9wdGlvbnMuZmxpcFksICdib29sZWFuJyxcbiAgICAgICAgJ2ludmFsaWQgdGV4dHVyZSBmbGlwJyk7XG4gICAgICBmbGFncy5mbGlwWSA9IG9wdGlvbnMuZmxpcFk7XG4gICAgfVxuXG4gICAgaWYgKCdhbGlnbm1lbnQnIGluIG9wdGlvbnMpIHtcbiAgICAgIGNoZWNrJDEub25lT2Yob3B0aW9ucy5hbGlnbm1lbnQsIFsxLCAyLCA0LCA4XSxcbiAgICAgICAgJ2ludmFsaWQgdGV4dHVyZSB1bnBhY2sgYWxpZ25tZW50Jyk7XG4gICAgICBmbGFncy51bnBhY2tBbGlnbm1lbnQgPSBvcHRpb25zLmFsaWdubWVudDtcbiAgICB9XG5cbiAgICBpZiAoJ2NvbG9yU3BhY2UnIGluIG9wdGlvbnMpIHtcbiAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG9wdGlvbnMuY29sb3JTcGFjZSwgY29sb3JTcGFjZSxcbiAgICAgICAgJ2ludmFsaWQgY29sb3JTcGFjZScpO1xuICAgICAgZmxhZ3MuY29sb3JTcGFjZSA9IGNvbG9yU3BhY2Vbb3B0aW9ucy5jb2xvclNwYWNlXTtcbiAgICB9XG5cbiAgICBpZiAoJ3R5cGUnIGluIG9wdGlvbnMpIHtcbiAgICAgIHZhciB0eXBlID0gb3B0aW9ucy50eXBlO1xuICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0IHx8XG4gICAgICAgICEodHlwZSA9PT0gJ2Zsb2F0JyB8fCB0eXBlID09PSAnZmxvYXQzMicpLFxuICAgICAgICAneW91IG11c3QgZW5hYmxlIHRoZSBPRVNfdGV4dHVyZV9mbG9hdCBleHRlbnNpb24gaW4gb3JkZXIgdG8gdXNlIGZsb2F0aW5nIHBvaW50IHRleHR1cmVzLicpO1xuICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2hhbGZfZmxvYXQgfHxcbiAgICAgICAgISh0eXBlID09PSAnaGFsZiBmbG9hdCcgfHwgdHlwZSA9PT0gJ2Zsb2F0MTYnKSxcbiAgICAgICAgJ3lvdSBtdXN0IGVuYWJsZSB0aGUgT0VTX3RleHR1cmVfaGFsZl9mbG9hdCBleHRlbnNpb24gaW4gb3JkZXIgdG8gdXNlIDE2LWJpdCBmbG9hdGluZyBwb2ludCB0ZXh0dXJlcy4nKTtcbiAgICAgIGNoZWNrJDEoZXh0ZW5zaW9ucy53ZWJnbF9kZXB0aF90ZXh0dXJlIHx8XG4gICAgICAgICEodHlwZSA9PT0gJ3VpbnQxNicgfHwgdHlwZSA9PT0gJ3VpbnQzMicgfHwgdHlwZSA9PT0gJ2RlcHRoIHN0ZW5jaWwnKSxcbiAgICAgICAgJ3lvdSBtdXN0IGVuYWJsZSB0aGUgV0VCR0xfZGVwdGhfdGV4dHVyZSBleHRlbnNpb24gaW4gb3JkZXIgdG8gdXNlIGRlcHRoL3N0ZW5jaWwgdGV4dHVyZXMuJyk7XG4gICAgICBjaGVjayQxLnBhcmFtZXRlcih0eXBlLCB0ZXh0dXJlVHlwZXMsXG4gICAgICAgICdpbnZhbGlkIHRleHR1cmUgdHlwZScpO1xuICAgICAgZmxhZ3MudHlwZSA9IHRleHR1cmVUeXBlc1t0eXBlXTtcbiAgICB9XG5cbiAgICB2YXIgdyA9IGZsYWdzLndpZHRoO1xuICAgIHZhciBoID0gZmxhZ3MuaGVpZ2h0O1xuICAgIHZhciBjID0gZmxhZ3MuY2hhbm5lbHM7XG4gICAgdmFyIGhhc0NoYW5uZWxzID0gZmFsc2U7XG4gICAgaWYgKCdzaGFwZScgaW4gb3B0aW9ucykge1xuICAgICAgY2hlY2skMShBcnJheS5pc0FycmF5KG9wdGlvbnMuc2hhcGUpICYmIG9wdGlvbnMuc2hhcGUubGVuZ3RoID49IDIsXG4gICAgICAgICdzaGFwZSBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgICB3ID0gb3B0aW9ucy5zaGFwZVswXTtcbiAgICAgIGggPSBvcHRpb25zLnNoYXBlWzFdO1xuICAgICAgaWYgKG9wdGlvbnMuc2hhcGUubGVuZ3RoID09PSAzKSB7XG4gICAgICAgIGMgPSBvcHRpb25zLnNoYXBlWzJdO1xuICAgICAgICBjaGVjayQxKGMgPiAwICYmIGMgPD0gNCwgJ2ludmFsaWQgbnVtYmVyIG9mIGNoYW5uZWxzJyk7XG4gICAgICAgIGhhc0NoYW5uZWxzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGNoZWNrJDEodyA+PSAwICYmIHcgPD0gbGltaXRzLm1heFRleHR1cmVTaXplLCAnaW52YWxpZCB3aWR0aCcpO1xuICAgICAgY2hlY2skMShoID49IDAgJiYgaCA8PSBsaW1pdHMubWF4VGV4dHVyZVNpemUsICdpbnZhbGlkIGhlaWdodCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoJ3JhZGl1cycgaW4gb3B0aW9ucykge1xuICAgICAgICB3ID0gaCA9IG9wdGlvbnMucmFkaXVzO1xuICAgICAgICBjaGVjayQxKHcgPj0gMCAmJiB3IDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgcmFkaXVzJyk7XG4gICAgICB9XG4gICAgICBpZiAoJ3dpZHRoJyBpbiBvcHRpb25zKSB7XG4gICAgICAgIHcgPSBvcHRpb25zLndpZHRoO1xuICAgICAgICBjaGVjayQxKHcgPj0gMCAmJiB3IDw9IGxpbWl0cy5tYXhUZXh0dXJlU2l6ZSwgJ2ludmFsaWQgd2lkdGgnKTtcbiAgICAgIH1cbiAgICAgIGlmICgnaGVpZ2h0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgIGggPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgY2hlY2skMShoID49IDAgJiYgaCA8PSBsaW1pdHMubWF4VGV4dHVyZVNpemUsICdpbnZhbGlkIGhlaWdodCcpO1xuICAgICAgfVxuICAgICAgaWYgKCdjaGFubmVscycgaW4gb3B0aW9ucykge1xuICAgICAgICBjID0gb3B0aW9ucy5jaGFubmVscztcbiAgICAgICAgY2hlY2skMShjID4gMCAmJiBjIDw9IDQsICdpbnZhbGlkIG51bWJlciBvZiBjaGFubmVscycpO1xuICAgICAgICBoYXNDaGFubmVscyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIGZsYWdzLndpZHRoID0gdyB8IDA7XG4gICAgZmxhZ3MuaGVpZ2h0ID0gaCB8IDA7XG4gICAgZmxhZ3MuY2hhbm5lbHMgPSBjIHwgMDtcblxuICAgIHZhciBoYXNGb3JtYXQgPSBmYWxzZTtcbiAgICBpZiAoJ2Zvcm1hdCcgaW4gb3B0aW9ucykge1xuICAgICAgdmFyIGZvcm1hdFN0ciA9IG9wdGlvbnMuZm9ybWF0O1xuICAgICAgY2hlY2skMShleHRlbnNpb25zLndlYmdsX2RlcHRoX3RleHR1cmUgfHxcbiAgICAgICAgIShmb3JtYXRTdHIgPT09ICdkZXB0aCcgfHwgZm9ybWF0U3RyID09PSAnZGVwdGggc3RlbmNpbCcpLFxuICAgICAgICAneW91IG11c3QgZW5hYmxlIHRoZSBXRUJHTF9kZXB0aF90ZXh0dXJlIGV4dGVuc2lvbiBpbiBvcmRlciB0byB1c2UgZGVwdGgvc3RlbmNpbCB0ZXh0dXJlcy4nKTtcbiAgICAgIGNoZWNrJDEucGFyYW1ldGVyKGZvcm1hdFN0ciwgdGV4dHVyZUZvcm1hdHMsXG4gICAgICAgICdpbnZhbGlkIHRleHR1cmUgZm9ybWF0Jyk7XG4gICAgICB2YXIgaW50ZXJuYWxmb3JtYXQgPSBmbGFncy5pbnRlcm5hbGZvcm1hdCA9IHRleHR1cmVGb3JtYXRzW2Zvcm1hdFN0cl07XG4gICAgICBmbGFncy5mb3JtYXQgPSBjb2xvckZvcm1hdHNbaW50ZXJuYWxmb3JtYXRdO1xuICAgICAgaWYgKGZvcm1hdFN0ciBpbiB0ZXh0dXJlVHlwZXMpIHtcbiAgICAgICAgaWYgKCEoJ3R5cGUnIGluIG9wdGlvbnMpKSB7XG4gICAgICAgICAgZmxhZ3MudHlwZSA9IHRleHR1cmVUeXBlc1tmb3JtYXRTdHJdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZm9ybWF0U3RyIGluIGNvbXByZXNzZWRUZXh0dXJlRm9ybWF0cykge1xuICAgICAgICBmbGFncy5jb21wcmVzc2VkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGhhc0Zvcm1hdCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gUmVjb25jaWxlIGNoYW5uZWxzIGFuZCBmb3JtYXRcbiAgICBpZiAoIWhhc0NoYW5uZWxzICYmIGhhc0Zvcm1hdCkge1xuICAgICAgZmxhZ3MuY2hhbm5lbHMgPSBGT1JNQVRfQ0hBTk5FTFNbZmxhZ3MuZm9ybWF0XTtcbiAgICB9IGVsc2UgaWYgKGhhc0NoYW5uZWxzICYmICFoYXNGb3JtYXQpIHtcbiAgICAgIGlmIChmbGFncy5jaGFubmVscyAhPT0gQ0hBTk5FTFNfRk9STUFUW2ZsYWdzLmZvcm1hdF0pIHtcbiAgICAgICAgZmxhZ3MuZm9ybWF0ID0gZmxhZ3MuaW50ZXJuYWxmb3JtYXQgPSBDSEFOTkVMU19GT1JNQVRbZmxhZ3MuY2hhbm5lbHNdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoaGFzRm9ybWF0ICYmIGhhc0NoYW5uZWxzKSB7XG4gICAgICBjaGVjayQxKFxuICAgICAgICBmbGFncy5jaGFubmVscyA9PT0gRk9STUFUX0NIQU5ORUxTW2ZsYWdzLmZvcm1hdF0sXG4gICAgICAgICdudW1iZXIgb2YgY2hhbm5lbHMgaW5jb25zaXN0ZW50IHdpdGggc3BlY2lmaWVkIGZvcm1hdCcpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldEZsYWdzIChmbGFncykge1xuICAgIGdsLnBpeGVsU3RvcmVpKEdMX1VOUEFDS19GTElQX1lfV0VCR0wsIGZsYWdzLmZsaXBZKTtcbiAgICBnbC5waXhlbFN0b3JlaShHTF9VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsIGZsYWdzLnByZW11bHRpcGx5QWxwaGEpO1xuICAgIGdsLnBpeGVsU3RvcmVpKEdMX1VOUEFDS19DT0xPUlNQQUNFX0NPTlZFUlNJT05fV0VCR0wsIGZsYWdzLmNvbG9yU3BhY2UpO1xuICAgIGdsLnBpeGVsU3RvcmVpKEdMX1VOUEFDS19BTElHTk1FTlQsIGZsYWdzLnVucGFja0FsaWdubWVudCk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFRleCBpbWFnZSBkYXRhXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZnVuY3Rpb24gVGV4SW1hZ2UgKCkge1xuICAgIFRleEZsYWdzLmNhbGwodGhpcyk7XG5cbiAgICB0aGlzLnhPZmZzZXQgPSAwO1xuICAgIHRoaXMueU9mZnNldCA9IDA7XG5cbiAgICAvLyBkYXRhXG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbiAgICB0aGlzLm5lZWRzRnJlZSA9IGZhbHNlO1xuXG4gICAgLy8gaHRtbCBlbGVtZW50XG4gICAgdGhpcy5lbGVtZW50ID0gbnVsbDtcblxuICAgIC8vIGNvcHlUZXhJbWFnZSBpbmZvXG4gICAgdGhpcy5uZWVkc0NvcHkgPSBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlSW1hZ2UgKGltYWdlLCBvcHRpb25zKSB7XG4gICAgdmFyIGRhdGEgPSBudWxsO1xuICAgIGlmIChpc1BpeGVsRGF0YShvcHRpb25zKSkge1xuICAgICAgZGF0YSA9IG9wdGlvbnM7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zKSB7XG4gICAgICBjaGVjayQxLnR5cGUob3B0aW9ucywgJ29iamVjdCcsICdpbnZhbGlkIHBpeGVsIGRhdGEgdHlwZScpO1xuICAgICAgcGFyc2VGbGFncyhpbWFnZSwgb3B0aW9ucyk7XG4gICAgICBpZiAoJ3gnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgaW1hZ2UueE9mZnNldCA9IG9wdGlvbnMueCB8IDA7XG4gICAgICB9XG4gICAgICBpZiAoJ3knIGluIG9wdGlvbnMpIHtcbiAgICAgICAgaW1hZ2UueU9mZnNldCA9IG9wdGlvbnMueSB8IDA7XG4gICAgICB9XG4gICAgICBpZiAoaXNQaXhlbERhdGEob3B0aW9ucy5kYXRhKSkge1xuICAgICAgICBkYXRhID0gb3B0aW9ucy5kYXRhO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNoZWNrJDEoXG4gICAgICAhaW1hZ2UuY29tcHJlc3NlZCB8fFxuICAgICAgZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXksXG4gICAgICAnY29tcHJlc3NlZCB0ZXh0dXJlIGRhdGEgbXVzdCBiZSBzdG9yZWQgaW4gYSB1aW50OGFycmF5Jyk7XG5cbiAgICBpZiAob3B0aW9ucy5jb3B5KSB7XG4gICAgICBjaGVjayQxKCFkYXRhLCAnY2FuIG5vdCBzcGVjaWZ5IGNvcHkgYW5kIGRhdGEgZmllbGQgZm9yIHRoZSBzYW1lIHRleHR1cmUnKTtcbiAgICAgIHZhciB2aWV3VyA9IGNvbnRleHRTdGF0ZS52aWV3cG9ydFdpZHRoO1xuICAgICAgdmFyIHZpZXdIID0gY29udGV4dFN0YXRlLnZpZXdwb3J0SGVpZ2h0O1xuICAgICAgaW1hZ2Uud2lkdGggPSBpbWFnZS53aWR0aCB8fCAodmlld1cgLSBpbWFnZS54T2Zmc2V0KTtcbiAgICAgIGltYWdlLmhlaWdodCA9IGltYWdlLmhlaWdodCB8fCAodmlld0ggLSBpbWFnZS55T2Zmc2V0KTtcbiAgICAgIGltYWdlLm5lZWRzQ29weSA9IHRydWU7XG4gICAgICBjaGVjayQxKGltYWdlLnhPZmZzZXQgPj0gMCAmJiBpbWFnZS54T2Zmc2V0IDwgdmlld1cgJiZcbiAgICAgICAgICAgIGltYWdlLnlPZmZzZXQgPj0gMCAmJiBpbWFnZS55T2Zmc2V0IDwgdmlld0ggJiZcbiAgICAgICAgICAgIGltYWdlLndpZHRoID4gMCAmJiBpbWFnZS53aWR0aCA8PSB2aWV3VyAmJlxuICAgICAgICAgICAgaW1hZ2UuaGVpZ2h0ID4gMCAmJiBpbWFnZS5oZWlnaHQgPD0gdmlld0gsXG4gICAgICAgICAgICAnY29weSB0ZXh0dXJlIHJlYWQgb3V0IG9mIGJvdW5kcycpO1xuICAgIH0gZWxzZSBpZiAoIWRhdGEpIHtcbiAgICAgIGltYWdlLndpZHRoID0gaW1hZ2Uud2lkdGggfHwgMTtcbiAgICAgIGltYWdlLmhlaWdodCA9IGltYWdlLmhlaWdodCB8fCAxO1xuICAgICAgaW1hZ2UuY2hhbm5lbHMgPSBpbWFnZS5jaGFubmVscyB8fCA0O1xuICAgIH0gZWxzZSBpZiAoaXNUeXBlZEFycmF5KGRhdGEpKSB7XG4gICAgICBpbWFnZS5jaGFubmVscyA9IGltYWdlLmNoYW5uZWxzIHx8IDQ7XG4gICAgICBpbWFnZS5kYXRhID0gZGF0YTtcbiAgICAgIGlmICghKCd0eXBlJyBpbiBvcHRpb25zKSAmJiBpbWFnZS50eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDUpIHtcbiAgICAgICAgaW1hZ2UudHlwZSA9IHR5cGVkQXJyYXlDb2RlJDEoZGF0YSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChpc051bWVyaWNBcnJheShkYXRhKSkge1xuICAgICAgaW1hZ2UuY2hhbm5lbHMgPSBpbWFnZS5jaGFubmVscyB8fCA0O1xuICAgICAgY29udmVydERhdGEoaW1hZ2UsIGRhdGEpO1xuICAgICAgaW1hZ2UuYWxpZ25tZW50ID0gMTtcbiAgICAgIGltYWdlLm5lZWRzRnJlZSA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChpc05EQXJyYXlMaWtlKGRhdGEpKSB7XG4gICAgICB2YXIgYXJyYXkgPSBkYXRhLmRhdGE7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyYXkpICYmIGltYWdlLnR5cGUgPT09IEdMX1VOU0lHTkVEX0JZVEUkNSkge1xuICAgICAgICBpbWFnZS50eXBlID0gdHlwZWRBcnJheUNvZGUkMShhcnJheSk7XG4gICAgICB9XG4gICAgICB2YXIgc2hhcGUgPSBkYXRhLnNoYXBlO1xuICAgICAgdmFyIHN0cmlkZSA9IGRhdGEuc3RyaWRlO1xuICAgICAgdmFyIHNoYXBlWCwgc2hhcGVZLCBzaGFwZUMsIHN0cmlkZVgsIHN0cmlkZVksIHN0cmlkZUM7XG4gICAgICBpZiAoc2hhcGUubGVuZ3RoID09PSAzKSB7XG4gICAgICAgIHNoYXBlQyA9IHNoYXBlWzJdO1xuICAgICAgICBzdHJpZGVDID0gc3RyaWRlWzJdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMShzaGFwZS5sZW5ndGggPT09IDIsICdpbnZhbGlkIG5kYXJyYXkgcGl4ZWwgZGF0YSwgbXVzdCBiZSAyIG9yIDNEJyk7XG4gICAgICAgIHNoYXBlQyA9IDE7XG4gICAgICAgIHN0cmlkZUMgPSAxO1xuICAgICAgfVxuICAgICAgc2hhcGVYID0gc2hhcGVbMF07XG4gICAgICBzaGFwZVkgPSBzaGFwZVsxXTtcbiAgICAgIHN0cmlkZVggPSBzdHJpZGVbMF07XG4gICAgICBzdHJpZGVZID0gc3RyaWRlWzFdO1xuICAgICAgaW1hZ2UuYWxpZ25tZW50ID0gMTtcbiAgICAgIGltYWdlLndpZHRoID0gc2hhcGVYO1xuICAgICAgaW1hZ2UuaGVpZ2h0ID0gc2hhcGVZO1xuICAgICAgaW1hZ2UuY2hhbm5lbHMgPSBzaGFwZUM7XG4gICAgICBpbWFnZS5mb3JtYXQgPSBpbWFnZS5pbnRlcm5hbGZvcm1hdCA9IENIQU5ORUxTX0ZPUk1BVFtzaGFwZUNdO1xuICAgICAgaW1hZ2UubmVlZHNGcmVlID0gdHJ1ZTtcbiAgICAgIHRyYW5zcG9zZURhdGEoaW1hZ2UsIGFycmF5LCBzdHJpZGVYLCBzdHJpZGVZLCBzdHJpZGVDLCBkYXRhLm9mZnNldCk7XG4gICAgfSBlbHNlIGlmIChpc0NhbnZhc0VsZW1lbnQoZGF0YSkgfHwgaXNDb250ZXh0MkQoZGF0YSkpIHtcbiAgICAgIGlmIChpc0NhbnZhc0VsZW1lbnQoZGF0YSkpIHtcbiAgICAgICAgaW1hZ2UuZWxlbWVudCA9IGRhdGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbWFnZS5lbGVtZW50ID0gZGF0YS5jYW52YXM7XG4gICAgICB9XG4gICAgICBpbWFnZS53aWR0aCA9IGltYWdlLmVsZW1lbnQud2lkdGg7XG4gICAgICBpbWFnZS5oZWlnaHQgPSBpbWFnZS5lbGVtZW50LmhlaWdodDtcbiAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICB9IGVsc2UgaWYgKGlzQml0bWFwKGRhdGEpKSB7XG4gICAgICBpbWFnZS5lbGVtZW50ID0gZGF0YTtcbiAgICAgIGltYWdlLndpZHRoID0gZGF0YS53aWR0aDtcbiAgICAgIGltYWdlLmhlaWdodCA9IGRhdGEuaGVpZ2h0O1xuICAgICAgaW1hZ2UuY2hhbm5lbHMgPSA0O1xuICAgIH0gZWxzZSBpZiAoaXNJbWFnZUVsZW1lbnQoZGF0YSkpIHtcbiAgICAgIGltYWdlLmVsZW1lbnQgPSBkYXRhO1xuICAgICAgaW1hZ2Uud2lkdGggPSBkYXRhLm5hdHVyYWxXaWR0aDtcbiAgICAgIGltYWdlLmhlaWdodCA9IGRhdGEubmF0dXJhbEhlaWdodDtcbiAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICB9IGVsc2UgaWYgKGlzVmlkZW9FbGVtZW50KGRhdGEpKSB7XG4gICAgICBpbWFnZS5lbGVtZW50ID0gZGF0YTtcbiAgICAgIGltYWdlLndpZHRoID0gZGF0YS52aWRlb1dpZHRoO1xuICAgICAgaW1hZ2UuaGVpZ2h0ID0gZGF0YS52aWRlb0hlaWdodDtcbiAgICAgIGltYWdlLmNoYW5uZWxzID0gNDtcbiAgICB9IGVsc2UgaWYgKGlzUmVjdEFycmF5KGRhdGEpKSB7XG4gICAgICB2YXIgdyA9IGltYWdlLndpZHRoIHx8IGRhdGFbMF0ubGVuZ3RoO1xuICAgICAgdmFyIGggPSBpbWFnZS5oZWlnaHQgfHwgZGF0YS5sZW5ndGg7XG4gICAgICB2YXIgYyA9IGltYWdlLmNoYW5uZWxzO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlKGRhdGFbMF1bMF0pKSB7XG4gICAgICAgIGMgPSBjIHx8IGRhdGFbMF1bMF0ubGVuZ3RoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYyA9IGMgfHwgMTtcbiAgICAgIH1cbiAgICAgIHZhciBhcnJheVNoYXBlID0gZmxhdHRlblV0aWxzLnNoYXBlKGRhdGEpO1xuICAgICAgdmFyIG4gPSAxO1xuICAgICAgZm9yICh2YXIgZGQgPSAwOyBkZCA8IGFycmF5U2hhcGUubGVuZ3RoOyArK2RkKSB7XG4gICAgICAgIG4gKj0gYXJyYXlTaGFwZVtkZF07XG4gICAgICB9XG4gICAgICB2YXIgYWxsb2NEYXRhID0gcHJlQ29udmVydChpbWFnZSwgbik7XG4gICAgICBmbGF0dGVuVXRpbHMuZmxhdHRlbihkYXRhLCBhcnJheVNoYXBlLCAnJywgYWxsb2NEYXRhKTtcbiAgICAgIHBvc3RDb252ZXJ0KGltYWdlLCBhbGxvY0RhdGEpO1xuICAgICAgaW1hZ2UuYWxpZ25tZW50ID0gMTtcbiAgICAgIGltYWdlLndpZHRoID0gdztcbiAgICAgIGltYWdlLmhlaWdodCA9IGg7XG4gICAgICBpbWFnZS5jaGFubmVscyA9IGM7XG4gICAgICBpbWFnZS5mb3JtYXQgPSBpbWFnZS5pbnRlcm5hbGZvcm1hdCA9IENIQU5ORUxTX0ZPUk1BVFtjXTtcbiAgICAgIGltYWdlLm5lZWRzRnJlZSA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGltYWdlLnR5cGUgPT09IEdMX0ZMT0FUJDQpIHtcbiAgICAgIGNoZWNrJDEobGltaXRzLmV4dGVuc2lvbnMuaW5kZXhPZignb2VzX3RleHR1cmVfZmxvYXQnKSA+PSAwLFxuICAgICAgICAnb2VzX3RleHR1cmVfZmxvYXQgZXh0ZW5zaW9uIG5vdCBlbmFibGVkJyk7XG4gICAgfSBlbHNlIGlmIChpbWFnZS50eXBlID09PSBHTF9IQUxGX0ZMT0FUX09FUyQxKSB7XG4gICAgICBjaGVjayQxKGxpbWl0cy5leHRlbnNpb25zLmluZGV4T2YoJ29lc190ZXh0dXJlX2hhbGZfZmxvYXQnKSA+PSAwLFxuICAgICAgICAnb2VzX3RleHR1cmVfaGFsZl9mbG9hdCBleHRlbnNpb24gbm90IGVuYWJsZWQnKTtcbiAgICB9XG5cbiAgICAvLyBkbyBjb21wcmVzc2VkIHRleHR1cmUgIHZhbGlkYXRpb24gaGVyZS5cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldEltYWdlIChpbmZvLCB0YXJnZXQsIG1pcGxldmVsKSB7XG4gICAgdmFyIGVsZW1lbnQgPSBpbmZvLmVsZW1lbnQ7XG4gICAgdmFyIGRhdGEgPSBpbmZvLmRhdGE7XG4gICAgdmFyIGludGVybmFsZm9ybWF0ID0gaW5mby5pbnRlcm5hbGZvcm1hdDtcbiAgICB2YXIgZm9ybWF0ID0gaW5mby5mb3JtYXQ7XG4gICAgdmFyIHR5cGUgPSBpbmZvLnR5cGU7XG4gICAgdmFyIHdpZHRoID0gaW5mby53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gaW5mby5oZWlnaHQ7XG4gICAgdmFyIGNoYW5uZWxzID0gaW5mby5jaGFubmVscztcblxuICAgIHNldEZsYWdzKGluZm8pO1xuXG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIGdsLnRleEltYWdlMkQodGFyZ2V0LCBtaXBsZXZlbCwgZm9ybWF0LCBmb3JtYXQsIHR5cGUsIGVsZW1lbnQpO1xuICAgIH0gZWxzZSBpZiAoaW5mby5jb21wcmVzc2VkKSB7XG4gICAgICBnbC5jb21wcmVzc2VkVGV4SW1hZ2UyRCh0YXJnZXQsIG1pcGxldmVsLCBpbnRlcm5hbGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgMCwgZGF0YSk7XG4gICAgfSBlbHNlIGlmIChpbmZvLm5lZWRzQ29weSkge1xuICAgICAgcmVnbFBvbGwoKTtcbiAgICAgIGdsLmNvcHlUZXhJbWFnZTJEKFxuICAgICAgICB0YXJnZXQsIG1pcGxldmVsLCBmb3JtYXQsIGluZm8ueE9mZnNldCwgaW5mby55T2Zmc2V0LCB3aWR0aCwgaGVpZ2h0LCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG51bGxEYXRhID0gIWRhdGE7XG4gICAgICBpZiAobnVsbERhdGEpIHtcbiAgICAgICAgZGF0YSA9IHBvb2wuemVyby5hbGxvY1R5cGUodHlwZSwgd2lkdGggKiBoZWlnaHQgKiBjaGFubmVscyk7XG4gICAgICB9XG5cbiAgICAgIGdsLnRleEltYWdlMkQodGFyZ2V0LCBtaXBsZXZlbCwgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCAwLCBmb3JtYXQsIHR5cGUsIGRhdGEpO1xuXG4gICAgICBpZiAobnVsbERhdGEgJiYgZGF0YSkge1xuICAgICAgICBwb29sLnplcm8uZnJlZVR5cGUoZGF0YSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2V0U3ViSW1hZ2UgKGluZm8sIHRhcmdldCwgeCwgeSwgbWlwbGV2ZWwpIHtcbiAgICB2YXIgZWxlbWVudCA9IGluZm8uZWxlbWVudDtcbiAgICB2YXIgZGF0YSA9IGluZm8uZGF0YTtcbiAgICB2YXIgaW50ZXJuYWxmb3JtYXQgPSBpbmZvLmludGVybmFsZm9ybWF0O1xuICAgIHZhciBmb3JtYXQgPSBpbmZvLmZvcm1hdDtcbiAgICB2YXIgdHlwZSA9IGluZm8udHlwZTtcbiAgICB2YXIgd2lkdGggPSBpbmZvLndpZHRoO1xuICAgIHZhciBoZWlnaHQgPSBpbmZvLmhlaWdodDtcblxuICAgIHNldEZsYWdzKGluZm8pO1xuXG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIGdsLnRleFN1YkltYWdlMkQoXG4gICAgICAgIHRhcmdldCwgbWlwbGV2ZWwsIHgsIHksIGZvcm1hdCwgdHlwZSwgZWxlbWVudCk7XG4gICAgfSBlbHNlIGlmIChpbmZvLmNvbXByZXNzZWQpIHtcbiAgICAgIGdsLmNvbXByZXNzZWRUZXhTdWJJbWFnZTJEKFxuICAgICAgICB0YXJnZXQsIG1pcGxldmVsLCB4LCB5LCBpbnRlcm5hbGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgZGF0YSk7XG4gICAgfSBlbHNlIGlmIChpbmZvLm5lZWRzQ29weSkge1xuICAgICAgcmVnbFBvbGwoKTtcbiAgICAgIGdsLmNvcHlUZXhTdWJJbWFnZTJEKFxuICAgICAgICB0YXJnZXQsIG1pcGxldmVsLCB4LCB5LCBpbmZvLnhPZmZzZXQsIGluZm8ueU9mZnNldCwgd2lkdGgsIGhlaWdodCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdsLnRleFN1YkltYWdlMkQoXG4gICAgICAgIHRhcmdldCwgbWlwbGV2ZWwsIHgsIHksIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSwgZGF0YSk7XG4gICAgfVxuICB9XG5cbiAgLy8gdGV4SW1hZ2UgcG9vbFxuICB2YXIgaW1hZ2VQb29sID0gW107XG5cbiAgZnVuY3Rpb24gYWxsb2NJbWFnZSAoKSB7XG4gICAgcmV0dXJuIGltYWdlUG9vbC5wb3AoKSB8fCBuZXcgVGV4SW1hZ2UoKVxuICB9XG5cbiAgZnVuY3Rpb24gZnJlZUltYWdlIChpbWFnZSkge1xuICAgIGlmIChpbWFnZS5uZWVkc0ZyZWUpIHtcbiAgICAgIHBvb2wuZnJlZVR5cGUoaW1hZ2UuZGF0YSk7XG4gICAgfVxuICAgIFRleEltYWdlLmNhbGwoaW1hZ2UpO1xuICAgIGltYWdlUG9vbC5wdXNoKGltYWdlKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTWlwIG1hcFxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGZ1bmN0aW9uIE1pcE1hcCAoKSB7XG4gICAgVGV4RmxhZ3MuY2FsbCh0aGlzKTtcblxuICAgIHRoaXMuZ2VuTWlwbWFwcyA9IGZhbHNlO1xuICAgIHRoaXMubWlwbWFwSGludCA9IEdMX0RPTlRfQ0FSRTtcbiAgICB0aGlzLm1pcG1hc2sgPSAwO1xuICAgIHRoaXMuaW1hZ2VzID0gQXJyYXkoMTYpO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VNaXBNYXBGcm9tU2hhcGUgKG1pcG1hcCwgd2lkdGgsIGhlaWdodCkge1xuICAgIHZhciBpbWcgPSBtaXBtYXAuaW1hZ2VzWzBdID0gYWxsb2NJbWFnZSgpO1xuICAgIG1pcG1hcC5taXBtYXNrID0gMTtcbiAgICBpbWcud2lkdGggPSBtaXBtYXAud2lkdGggPSB3aWR0aDtcbiAgICBpbWcuaGVpZ2h0ID0gbWlwbWFwLmhlaWdodCA9IGhlaWdodDtcbiAgICBpbWcuY2hhbm5lbHMgPSBtaXBtYXAuY2hhbm5lbHMgPSA0O1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VNaXBNYXBGcm9tT2JqZWN0IChtaXBtYXAsIG9wdGlvbnMpIHtcbiAgICB2YXIgaW1nRGF0YSA9IG51bGw7XG4gICAgaWYgKGlzUGl4ZWxEYXRhKG9wdGlvbnMpKSB7XG4gICAgICBpbWdEYXRhID0gbWlwbWFwLmltYWdlc1swXSA9IGFsbG9jSW1hZ2UoKTtcbiAgICAgIGNvcHlGbGFncyhpbWdEYXRhLCBtaXBtYXApO1xuICAgICAgcGFyc2VJbWFnZShpbWdEYXRhLCBvcHRpb25zKTtcbiAgICAgIG1pcG1hcC5taXBtYXNrID0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFyc2VGbGFncyhtaXBtYXAsIG9wdGlvbnMpO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5taXBtYXApKSB7XG4gICAgICAgIHZhciBtaXBEYXRhID0gb3B0aW9ucy5taXBtYXA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWlwRGF0YS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGltZ0RhdGEgPSBtaXBtYXAuaW1hZ2VzW2ldID0gYWxsb2NJbWFnZSgpO1xuICAgICAgICAgIGNvcHlGbGFncyhpbWdEYXRhLCBtaXBtYXApO1xuICAgICAgICAgIGltZ0RhdGEud2lkdGggPj49IGk7XG4gICAgICAgICAgaW1nRGF0YS5oZWlnaHQgPj49IGk7XG4gICAgICAgICAgcGFyc2VJbWFnZShpbWdEYXRhLCBtaXBEYXRhW2ldKTtcbiAgICAgICAgICBtaXBtYXAubWlwbWFzayB8PSAoMSA8PCBpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW1nRGF0YSA9IG1pcG1hcC5pbWFnZXNbMF0gPSBhbGxvY0ltYWdlKCk7XG4gICAgICAgIGNvcHlGbGFncyhpbWdEYXRhLCBtaXBtYXApO1xuICAgICAgICBwYXJzZUltYWdlKGltZ0RhdGEsIG9wdGlvbnMpO1xuICAgICAgICBtaXBtYXAubWlwbWFzayA9IDE7XG4gICAgICB9XG4gICAgfVxuICAgIGNvcHlGbGFncyhtaXBtYXAsIG1pcG1hcC5pbWFnZXNbMF0pO1xuXG4gICAgLy8gRm9yIHRleHR1cmVzIG9mIHRoZSBjb21wcmVzc2VkIGZvcm1hdCBXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Y1xuICAgIC8vIHdlIG11c3QgaGF2ZSB0aGF0XG4gICAgLy9cbiAgICAvLyBcIldoZW4gbGV2ZWwgZXF1YWxzIHplcm8gd2lkdGggYW5kIGhlaWdodCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNC5cbiAgICAvLyBXaGVuIGxldmVsIGlzIGdyZWF0ZXIgdGhhbiAwIHdpZHRoIGFuZCBoZWlnaHQgbXVzdCBiZSAwLCAxLCAyIG9yIGEgbXVsdGlwbGUgb2YgNC4gXCJcbiAgICAvL1xuICAgIC8vIGJ1dCB3ZSBkbyBub3QgeWV0IHN1cHBvcnQgaGF2aW5nIG11bHRpcGxlIG1pcG1hcCBsZXZlbHMgZm9yIGNvbXByZXNzZWQgdGV4dHVyZXMsXG4gICAgLy8gc28gd2Ugb25seSB0ZXN0IGZvciBsZXZlbCB6ZXJvLlxuXG4gICAgaWYgKG1pcG1hcC5jb21wcmVzc2VkICYmXG4gICAgICAgIChtaXBtYXAuaW50ZXJuYWxmb3JtYXQgPT09IEdMX0NPTVBSRVNTRURfUkdCX1MzVENfRFhUMV9FWFQpIHx8XG4gICAgICAgIChtaXBtYXAuaW50ZXJuYWxmb3JtYXQgPT09IEdMX0NPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDFfRVhUKSB8fFxuICAgICAgICAobWlwbWFwLmludGVybmFsZm9ybWF0ID09PSBHTF9DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQzX0VYVCkgfHxcbiAgICAgICAgKG1pcG1hcC5pbnRlcm5hbGZvcm1hdCA9PT0gR0xfQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUNV9FWFQpKSB7XG4gICAgICBjaGVjayQxKG1pcG1hcC53aWR0aCAlIDQgPT09IDAgJiZcbiAgICAgICAgICAgIG1pcG1hcC5oZWlnaHQgJSA0ID09PSAwLFxuICAgICAgICAgICAgJ2ZvciBjb21wcmVzc2VkIHRleHR1cmUgZm9ybWF0cywgbWlwbWFwIGxldmVsIDAgbXVzdCBoYXZlIHdpZHRoIGFuZCBoZWlnaHQgdGhhdCBhcmUgYSBtdWx0aXBsZSBvZiA0Jyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2V0TWlwTWFwIChtaXBtYXAsIHRhcmdldCkge1xuICAgIHZhciBpbWFnZXMgPSBtaXBtYXAuaW1hZ2VzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW1hZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoIWltYWdlc1tpXSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIHNldEltYWdlKGltYWdlc1tpXSwgdGFyZ2V0LCBpKTtcbiAgICB9XG4gIH1cblxuICB2YXIgbWlwUG9vbCA9IFtdO1xuXG4gIGZ1bmN0aW9uIGFsbG9jTWlwTWFwICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gbWlwUG9vbC5wb3AoKSB8fCBuZXcgTWlwTWFwKCk7XG4gICAgVGV4RmxhZ3MuY2FsbChyZXN1bHQpO1xuICAgIHJlc3VsdC5taXBtYXNrID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyArK2kpIHtcbiAgICAgIHJlc3VsdC5pbWFnZXNbaV0gPSBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBmdW5jdGlvbiBmcmVlTWlwTWFwIChtaXBtYXApIHtcbiAgICB2YXIgaW1hZ2VzID0gbWlwbWFwLmltYWdlcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGltYWdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKGltYWdlc1tpXSkge1xuICAgICAgICBmcmVlSW1hZ2UoaW1hZ2VzW2ldKTtcbiAgICAgIH1cbiAgICAgIGltYWdlc1tpXSA9IG51bGw7XG4gICAgfVxuICAgIG1pcFBvb2wucHVzaChtaXBtYXApO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBUZXggaW5mb1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGZ1bmN0aW9uIFRleEluZm8gKCkge1xuICAgIHRoaXMubWluRmlsdGVyID0gR0xfTkVBUkVTVCQxO1xuICAgIHRoaXMubWFnRmlsdGVyID0gR0xfTkVBUkVTVCQxO1xuXG4gICAgdGhpcy53cmFwUyA9IEdMX0NMQU1QX1RPX0VER0UkMTtcbiAgICB0aGlzLndyYXBUID0gR0xfQ0xBTVBfVE9fRURHRSQxO1xuXG4gICAgdGhpcy5hbmlzb3Ryb3BpYyA9IDE7XG5cbiAgICB0aGlzLmdlbk1pcG1hcHMgPSBmYWxzZTtcbiAgICB0aGlzLm1pcG1hcEhpbnQgPSBHTF9ET05UX0NBUkU7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVRleEluZm8gKGluZm8sIG9wdGlvbnMpIHtcbiAgICBpZiAoJ21pbicgaW4gb3B0aW9ucykge1xuICAgICAgdmFyIG1pbkZpbHRlciA9IG9wdGlvbnMubWluO1xuICAgICAgY2hlY2skMS5wYXJhbWV0ZXIobWluRmlsdGVyLCBtaW5GaWx0ZXJzKTtcbiAgICAgIGluZm8ubWluRmlsdGVyID0gbWluRmlsdGVyc1ttaW5GaWx0ZXJdO1xuICAgICAgaWYgKE1JUE1BUF9GSUxURVJTLmluZGV4T2YoaW5mby5taW5GaWx0ZXIpID49IDAgJiYgISgnZmFjZXMnIGluIG9wdGlvbnMpKSB7XG4gICAgICAgIGluZm8uZ2VuTWlwbWFwcyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCdtYWcnIGluIG9wdGlvbnMpIHtcbiAgICAgIHZhciBtYWdGaWx0ZXIgPSBvcHRpb25zLm1hZztcbiAgICAgIGNoZWNrJDEucGFyYW1ldGVyKG1hZ0ZpbHRlciwgbWFnRmlsdGVycyk7XG4gICAgICBpbmZvLm1hZ0ZpbHRlciA9IG1hZ0ZpbHRlcnNbbWFnRmlsdGVyXTtcbiAgICB9XG5cbiAgICB2YXIgd3JhcFMgPSBpbmZvLndyYXBTO1xuICAgIHZhciB3cmFwVCA9IGluZm8ud3JhcFQ7XG4gICAgaWYgKCd3cmFwJyBpbiBvcHRpb25zKSB7XG4gICAgICB2YXIgd3JhcCA9IG9wdGlvbnMud3JhcDtcbiAgICAgIGlmICh0eXBlb2Ygd3JhcCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIod3JhcCwgd3JhcE1vZGVzKTtcbiAgICAgICAgd3JhcFMgPSB3cmFwVCA9IHdyYXBNb2Rlc1t3cmFwXTtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh3cmFwKSkge1xuICAgICAgICBjaGVjayQxLnBhcmFtZXRlcih3cmFwWzBdLCB3cmFwTW9kZXMpO1xuICAgICAgICBjaGVjayQxLnBhcmFtZXRlcih3cmFwWzFdLCB3cmFwTW9kZXMpO1xuICAgICAgICB3cmFwUyA9IHdyYXBNb2Rlc1t3cmFwWzBdXTtcbiAgICAgICAgd3JhcFQgPSB3cmFwTW9kZXNbd3JhcFsxXV07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICgnd3JhcFMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIG9wdFdyYXBTID0gb3B0aW9ucy53cmFwUztcbiAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIob3B0V3JhcFMsIHdyYXBNb2Rlcyk7XG4gICAgICAgIHdyYXBTID0gd3JhcE1vZGVzW29wdFdyYXBTXTtcbiAgICAgIH1cbiAgICAgIGlmICgnd3JhcFQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIG9wdFdyYXBUID0gb3B0aW9ucy53cmFwVDtcbiAgICAgICAgY2hlY2skMS5wYXJhbWV0ZXIob3B0V3JhcFQsIHdyYXBNb2Rlcyk7XG4gICAgICAgIHdyYXBUID0gd3JhcE1vZGVzW29wdFdyYXBUXTtcbiAgICAgIH1cbiAgICB9XG4gICAgaW5mby53cmFwUyA9IHdyYXBTO1xuICAgIGluZm8ud3JhcFQgPSB3cmFwVDtcblxuICAgIGlmICgnYW5pc290cm9waWMnIGluIG9wdGlvbnMpIHtcbiAgICAgIHZhciBhbmlzb3Ryb3BpYyA9IG9wdGlvbnMuYW5pc290cm9waWM7XG4gICAgICBjaGVjayQxKHR5cGVvZiBhbmlzb3Ryb3BpYyA9PT0gJ251bWJlcicgJiZcbiAgICAgICAgIGFuaXNvdHJvcGljID49IDEgJiYgYW5pc290cm9waWMgPD0gbGltaXRzLm1heEFuaXNvdHJvcGljLFxuICAgICAgICAnYW5pc28gc2FtcGxlcyBtdXN0IGJlIGJldHdlZW4gMSBhbmQgJyk7XG4gICAgICBpbmZvLmFuaXNvdHJvcGljID0gb3B0aW9ucy5hbmlzb3Ryb3BpYztcbiAgICB9XG5cbiAgICBpZiAoJ21pcG1hcCcgaW4gb3B0aW9ucykge1xuICAgICAgdmFyIGhhc01pcE1hcCA9IGZhbHNlO1xuICAgICAgc3dpdGNoICh0eXBlb2Ygb3B0aW9ucy5taXBtYXApIHtcbiAgICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLm1pcG1hcCwgbWlwbWFwSGludCxcbiAgICAgICAgICAgICdpbnZhbGlkIG1pcG1hcCBoaW50Jyk7XG4gICAgICAgICAgaW5mby5taXBtYXBIaW50ID0gbWlwbWFwSGludFtvcHRpb25zLm1pcG1hcF07XG4gICAgICAgICAgaW5mby5nZW5NaXBtYXBzID0gdHJ1ZTtcbiAgICAgICAgICBoYXNNaXBNYXAgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICAgICAgaGFzTWlwTWFwID0gaW5mby5nZW5NaXBtYXBzID0gb3B0aW9ucy5taXBtYXA7XG4gICAgICAgICAgYnJlYWtcblxuICAgICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShvcHRpb25zLm1pcG1hcCksICdpbnZhbGlkIG1pcG1hcCB0eXBlJyk7XG4gICAgICAgICAgaW5mby5nZW5NaXBtYXBzID0gZmFsc2U7XG4gICAgICAgICAgaGFzTWlwTWFwID0gdHJ1ZTtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBtaXBtYXAgdHlwZScpO1xuICAgICAgfVxuICAgICAgaWYgKGhhc01pcE1hcCAmJiAhKCdtaW4nIGluIG9wdGlvbnMpKSB7XG4gICAgICAgIGluZm8ubWluRmlsdGVyID0gR0xfTkVBUkVTVF9NSVBNQVBfTkVBUkVTVCQxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldFRleEluZm8gKGluZm8sIHRhcmdldCkge1xuICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTF9URVhUVVJFX01JTl9GSUxURVIsIGluZm8ubWluRmlsdGVyKTtcbiAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0xfVEVYVFVSRV9NQUdfRklMVEVSLCBpbmZvLm1hZ0ZpbHRlcik7XG4gICAgZ2wudGV4UGFyYW1ldGVyaSh0YXJnZXQsIEdMX1RFWFRVUkVfV1JBUF9TLCBpbmZvLndyYXBTKTtcbiAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0xfVEVYVFVSRV9XUkFQX1QsIGluZm8ud3JhcFQpO1xuICAgIGlmIChleHRlbnNpb25zLmV4dF90ZXh0dXJlX2ZpbHRlcl9hbmlzb3Ryb3BpYykge1xuICAgICAgZ2wudGV4UGFyYW1ldGVyaSh0YXJnZXQsIEdMX1RFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhULCBpbmZvLmFuaXNvdHJvcGljKTtcbiAgICB9XG4gICAgaWYgKGluZm8uZ2VuTWlwbWFwcykge1xuICAgICAgZ2wuaGludChHTF9HRU5FUkFURV9NSVBNQVBfSElOVCwgaW5mby5taXBtYXBIaW50KTtcbiAgICAgIGdsLmdlbmVyYXRlTWlwbWFwKHRhcmdldCk7XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBGdWxsIHRleHR1cmUgb2JqZWN0XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgdmFyIHRleHR1cmVDb3VudCA9IDA7XG4gIHZhciB0ZXh0dXJlU2V0ID0ge307XG4gIHZhciBudW1UZXhVbml0cyA9IGxpbWl0cy5tYXhUZXh0dXJlVW5pdHM7XG4gIHZhciB0ZXh0dXJlVW5pdHMgPSBBcnJheShudW1UZXhVbml0cykubWFwKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9KTtcblxuICBmdW5jdGlvbiBSRUdMVGV4dHVyZSAodGFyZ2V0KSB7XG4gICAgVGV4RmxhZ3MuY2FsbCh0aGlzKTtcbiAgICB0aGlzLm1pcG1hc2sgPSAwO1xuICAgIHRoaXMuaW50ZXJuYWxmb3JtYXQgPSBHTF9SR0JBJDE7XG5cbiAgICB0aGlzLmlkID0gdGV4dHVyZUNvdW50Kys7XG5cbiAgICB0aGlzLnJlZkNvdW50ID0gMTtcblxuICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcblxuICAgIHRoaXMudW5pdCA9IC0xO1xuICAgIHRoaXMuYmluZENvdW50ID0gMDtcblxuICAgIHRoaXMudGV4SW5mbyA9IG5ldyBUZXhJbmZvKCk7XG5cbiAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgIHRoaXMuc3RhdHMgPSB7c2l6ZTogMH07XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdGVtcEJpbmQgKHRleHR1cmUpIHtcbiAgICBnbC5hY3RpdmVUZXh0dXJlKEdMX1RFWFRVUkUwJDEpO1xuICAgIGdsLmJpbmRUZXh0dXJlKHRleHR1cmUudGFyZ2V0LCB0ZXh0dXJlLnRleHR1cmUpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGVtcFJlc3RvcmUgKCkge1xuICAgIHZhciBwcmV2ID0gdGV4dHVyZVVuaXRzWzBdO1xuICAgIGlmIChwcmV2KSB7XG4gICAgICBnbC5iaW5kVGV4dHVyZShwcmV2LnRhcmdldCwgcHJldi50ZXh0dXJlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV8yRCQxLCBudWxsKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkZXN0cm95ICh0ZXh0dXJlKSB7XG4gICAgdmFyIGhhbmRsZSA9IHRleHR1cmUudGV4dHVyZTtcbiAgICBjaGVjayQxKGhhbmRsZSwgJ211c3Qgbm90IGRvdWJsZSBkZXN0cm95IHRleHR1cmUnKTtcbiAgICB2YXIgdW5pdCA9IHRleHR1cmUudW5pdDtcbiAgICB2YXIgdGFyZ2V0ID0gdGV4dHVyZS50YXJnZXQ7XG4gICAgaWYgKHVuaXQgPj0gMCkge1xuICAgICAgZ2wuYWN0aXZlVGV4dHVyZShHTF9URVhUVVJFMCQxICsgdW5pdCk7XG4gICAgICBnbC5iaW5kVGV4dHVyZSh0YXJnZXQsIG51bGwpO1xuICAgICAgdGV4dHVyZVVuaXRzW3VuaXRdID0gbnVsbDtcbiAgICB9XG4gICAgZ2wuZGVsZXRlVGV4dHVyZShoYW5kbGUpO1xuICAgIHRleHR1cmUudGV4dHVyZSA9IG51bGw7XG4gICAgdGV4dHVyZS5wYXJhbXMgPSBudWxsO1xuICAgIHRleHR1cmUucGl4ZWxzID0gbnVsbDtcbiAgICB0ZXh0dXJlLnJlZkNvdW50ID0gMDtcbiAgICBkZWxldGUgdGV4dHVyZVNldFt0ZXh0dXJlLmlkXTtcbiAgICBzdGF0cy50ZXh0dXJlQ291bnQtLTtcbiAgfVxuXG4gIGV4dGVuZChSRUdMVGV4dHVyZS5wcm90b3R5cGUsIHtcbiAgICBiaW5kOiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdGV4dHVyZSA9IHRoaXM7XG4gICAgICB0ZXh0dXJlLmJpbmRDb3VudCArPSAxO1xuICAgICAgdmFyIHVuaXQgPSB0ZXh0dXJlLnVuaXQ7XG4gICAgICBpZiAodW5pdCA8IDApIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1UZXhVbml0czsgKytpKSB7XG4gICAgICAgICAgdmFyIG90aGVyID0gdGV4dHVyZVVuaXRzW2ldO1xuICAgICAgICAgIGlmIChvdGhlcikge1xuICAgICAgICAgICAgaWYgKG90aGVyLmJpbmRDb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG90aGVyLnVuaXQgPSAtMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGV4dHVyZVVuaXRzW2ldID0gdGV4dHVyZTtcbiAgICAgICAgICB1bml0ID0gaTtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICAgIGlmICh1bml0ID49IG51bVRleFVuaXRzKSB7XG4gICAgICAgICAgY2hlY2skMS5yYWlzZSgnaW5zdWZmaWNpZW50IG51bWJlciBvZiB0ZXh0dXJlIHVuaXRzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZy5wcm9maWxlICYmIHN0YXRzLm1heFRleHR1cmVVbml0cyA8ICh1bml0ICsgMSkpIHtcbiAgICAgICAgICBzdGF0cy5tYXhUZXh0dXJlVW5pdHMgPSB1bml0ICsgMTsgLy8gKzEsIHNpbmNlIHRoZSB1bml0cyBhcmUgemVyby1iYXNlZFxuICAgICAgICB9XG4gICAgICAgIHRleHR1cmUudW5pdCA9IHVuaXQ7XG4gICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoR0xfVEVYVFVSRTAkMSArIHVuaXQpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZSh0ZXh0dXJlLnRhcmdldCwgdGV4dHVyZS50ZXh0dXJlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bml0XG4gICAgfSxcblxuICAgIHVuYmluZDogZnVuY3Rpb24gKCkge1xuICAgICAgdGhpcy5iaW5kQ291bnQgLT0gMTtcbiAgICB9LFxuXG4gICAgZGVjUmVmOiBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoLS10aGlzLnJlZkNvdW50IDw9IDApIHtcbiAgICAgICAgZGVzdHJveSh0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZVRleHR1cmUyRCAoYSwgYikge1xuICAgIHZhciB0ZXh0dXJlID0gbmV3IFJFR0xUZXh0dXJlKEdMX1RFWFRVUkVfMkQkMSk7XG4gICAgdGV4dHVyZVNldFt0ZXh0dXJlLmlkXSA9IHRleHR1cmU7XG4gICAgc3RhdHMudGV4dHVyZUNvdW50Kys7XG5cbiAgICBmdW5jdGlvbiByZWdsVGV4dHVyZTJEIChhLCBiKSB7XG4gICAgICB2YXIgdGV4SW5mbyA9IHRleHR1cmUudGV4SW5mbztcbiAgICAgIFRleEluZm8uY2FsbCh0ZXhJbmZvKTtcbiAgICAgIHZhciBtaXBEYXRhID0gYWxsb2NNaXBNYXAoKTtcblxuICAgICAgaWYgKHR5cGVvZiBhID09PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAodHlwZW9mIGIgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tU2hhcGUobWlwRGF0YSwgYSB8IDAsIGIgfCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXJzZU1pcE1hcEZyb21TaGFwZShtaXBEYXRhLCBhIHwgMCwgYSB8IDApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGEpIHtcbiAgICAgICAgY2hlY2skMS50eXBlKGEsICdvYmplY3QnLCAnaW52YWxpZCBhcmd1bWVudHMgdG8gcmVnbC50ZXh0dXJlJyk7XG4gICAgICAgIHBhcnNlVGV4SW5mbyh0ZXhJbmZvLCBhKTtcbiAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KG1pcERhdGEsIGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZW1wdHkgdGV4dHVyZXMgZ2V0IGFzc2lnbmVkIGEgZGVmYXVsdCBzaGFwZSBvZiAxeDFcbiAgICAgICAgcGFyc2VNaXBNYXBGcm9tU2hhcGUobWlwRGF0YSwgMSwgMSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0ZXhJbmZvLmdlbk1pcG1hcHMpIHtcbiAgICAgICAgbWlwRGF0YS5taXBtYXNrID0gKG1pcERhdGEud2lkdGggPDwgMSkgLSAxO1xuICAgICAgfVxuICAgICAgdGV4dHVyZS5taXBtYXNrID0gbWlwRGF0YS5taXBtYXNrO1xuXG4gICAgICBjb3B5RmxhZ3ModGV4dHVyZSwgbWlwRGF0YSk7XG5cbiAgICAgIGNoZWNrJDEudGV4dHVyZTJEKHRleEluZm8sIG1pcERhdGEsIGxpbWl0cyk7XG4gICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0ID0gbWlwRGF0YS5pbnRlcm5hbGZvcm1hdDtcblxuICAgICAgcmVnbFRleHR1cmUyRC53aWR0aCA9IG1pcERhdGEud2lkdGg7XG4gICAgICByZWdsVGV4dHVyZTJELmhlaWdodCA9IG1pcERhdGEuaGVpZ2h0O1xuXG4gICAgICB0ZW1wQmluZCh0ZXh0dXJlKTtcbiAgICAgIHNldE1pcE1hcChtaXBEYXRhLCBHTF9URVhUVVJFXzJEJDEpO1xuICAgICAgc2V0VGV4SW5mbyh0ZXhJbmZvLCBHTF9URVhUVVJFXzJEJDEpO1xuICAgICAgdGVtcFJlc3RvcmUoKTtcblxuICAgICAgZnJlZU1pcE1hcChtaXBEYXRhKTtcblxuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHRleHR1cmUuc3RhdHMuc2l6ZSA9IGdldFRleHR1cmVTaXplKFxuICAgICAgICAgIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsXG4gICAgICAgICAgdGV4dHVyZS50eXBlLFxuICAgICAgICAgIG1pcERhdGEud2lkdGgsXG4gICAgICAgICAgbWlwRGF0YS5oZWlnaHQsXG4gICAgICAgICAgdGV4SW5mby5nZW5NaXBtYXBzLFxuICAgICAgICAgIGZhbHNlKTtcbiAgICAgIH1cbiAgICAgIHJlZ2xUZXh0dXJlMkQuZm9ybWF0ID0gdGV4dHVyZUZvcm1hdHNJbnZlcnRbdGV4dHVyZS5pbnRlcm5hbGZvcm1hdF07XG4gICAgICByZWdsVGV4dHVyZTJELnR5cGUgPSB0ZXh0dXJlVHlwZXNJbnZlcnRbdGV4dHVyZS50eXBlXTtcblxuICAgICAgcmVnbFRleHR1cmUyRC5tYWcgPSBtYWdGaWx0ZXJzSW52ZXJ0W3RleEluZm8ubWFnRmlsdGVyXTtcbiAgICAgIHJlZ2xUZXh0dXJlMkQubWluID0gbWluRmlsdGVyc0ludmVydFt0ZXhJbmZvLm1pbkZpbHRlcl07XG5cbiAgICAgIHJlZ2xUZXh0dXJlMkQud3JhcFMgPSB3cmFwTW9kZXNJbnZlcnRbdGV4SW5mby53cmFwU107XG4gICAgICByZWdsVGV4dHVyZTJELndyYXBUID0gd3JhcE1vZGVzSW52ZXJ0W3RleEluZm8ud3JhcFRdO1xuXG4gICAgICByZXR1cm4gcmVnbFRleHR1cmUyRFxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN1YmltYWdlIChpbWFnZSwgeF8sIHlfLCBsZXZlbF8pIHtcbiAgICAgIGNoZWNrJDEoISFpbWFnZSwgJ211c3Qgc3BlY2lmeSBpbWFnZSBkYXRhJyk7XG5cbiAgICAgIHZhciB4ID0geF8gfCAwO1xuICAgICAgdmFyIHkgPSB5XyB8IDA7XG4gICAgICB2YXIgbGV2ZWwgPSBsZXZlbF8gfCAwO1xuXG4gICAgICB2YXIgaW1hZ2VEYXRhID0gYWxsb2NJbWFnZSgpO1xuICAgICAgY29weUZsYWdzKGltYWdlRGF0YSwgdGV4dHVyZSk7XG4gICAgICBpbWFnZURhdGEud2lkdGggPSAwO1xuICAgICAgaW1hZ2VEYXRhLmhlaWdodCA9IDA7XG4gICAgICBwYXJzZUltYWdlKGltYWdlRGF0YSwgaW1hZ2UpO1xuICAgICAgaW1hZ2VEYXRhLndpZHRoID0gaW1hZ2VEYXRhLndpZHRoIHx8ICgodGV4dHVyZS53aWR0aCA+PiBsZXZlbCkgLSB4KTtcbiAgICAgIGltYWdlRGF0YS5oZWlnaHQgPSBpbWFnZURhdGEuaGVpZ2h0IHx8ICgodGV4dHVyZS5oZWlnaHQgPj4gbGV2ZWwpIC0geSk7XG5cbiAgICAgIGNoZWNrJDEoXG4gICAgICAgIHRleHR1cmUudHlwZSA9PT0gaW1hZ2VEYXRhLnR5cGUgJiZcbiAgICAgICAgdGV4dHVyZS5mb3JtYXQgPT09IGltYWdlRGF0YS5mb3JtYXQgJiZcbiAgICAgICAgdGV4dHVyZS5pbnRlcm5hbGZvcm1hdCA9PT0gaW1hZ2VEYXRhLmludGVybmFsZm9ybWF0LFxuICAgICAgICAnaW5jb21wYXRpYmxlIGZvcm1hdCBmb3IgdGV4dHVyZS5zdWJpbWFnZScpO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgeCA+PSAwICYmIHkgPj0gMCAmJlxuICAgICAgICB4ICsgaW1hZ2VEYXRhLndpZHRoIDw9IHRleHR1cmUud2lkdGggJiZcbiAgICAgICAgeSArIGltYWdlRGF0YS5oZWlnaHQgPD0gdGV4dHVyZS5oZWlnaHQsXG4gICAgICAgICd0ZXh0dXJlLnN1YmltYWdlIHdyaXRlIG91dCBvZiBib3VuZHMnKTtcbiAgICAgIGNoZWNrJDEoXG4gICAgICAgIHRleHR1cmUubWlwbWFzayAmICgxIDw8IGxldmVsKSxcbiAgICAgICAgJ21pc3NpbmcgbWlwbWFwIGRhdGEnKTtcbiAgICAgIGNoZWNrJDEoXG4gICAgICAgIGltYWdlRGF0YS5kYXRhIHx8IGltYWdlRGF0YS5lbGVtZW50IHx8IGltYWdlRGF0YS5uZWVkc0NvcHksXG4gICAgICAgICdtaXNzaW5nIGltYWdlIGRhdGEnKTtcblxuICAgICAgdGVtcEJpbmQodGV4dHVyZSk7XG4gICAgICBzZXRTdWJJbWFnZShpbWFnZURhdGEsIEdMX1RFWFRVUkVfMkQkMSwgeCwgeSwgbGV2ZWwpO1xuICAgICAgdGVtcFJlc3RvcmUoKTtcblxuICAgICAgZnJlZUltYWdlKGltYWdlRGF0YSk7XG5cbiAgICAgIHJldHVybiByZWdsVGV4dHVyZTJEXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzaXplICh3XywgaF8pIHtcbiAgICAgIHZhciB3ID0gd18gfCAwO1xuICAgICAgdmFyIGggPSAoaF8gfCAwKSB8fCB3O1xuICAgICAgaWYgKHcgPT09IHRleHR1cmUud2lkdGggJiYgaCA9PT0gdGV4dHVyZS5oZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlMkRcbiAgICAgIH1cblxuICAgICAgcmVnbFRleHR1cmUyRC53aWR0aCA9IHRleHR1cmUud2lkdGggPSB3O1xuICAgICAgcmVnbFRleHR1cmUyRC5oZWlnaHQgPSB0ZXh0dXJlLmhlaWdodCA9IGg7XG5cbiAgICAgIHRlbXBCaW5kKHRleHR1cmUpO1xuXG4gICAgICB2YXIgZGF0YTtcbiAgICAgIHZhciBjaGFubmVscyA9IHRleHR1cmUuY2hhbm5lbHM7XG4gICAgICB2YXIgdHlwZSA9IHRleHR1cmUudHlwZTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IHRleHR1cmUubWlwbWFzayA+PiBpOyArK2kpIHtcbiAgICAgICAgdmFyIF93ID0gdyA+PiBpO1xuICAgICAgICB2YXIgX2ggPSBoID4+IGk7XG4gICAgICAgIGlmICghX3cgfHwgIV9oKSBicmVha1xuICAgICAgICBkYXRhID0gcG9vbC56ZXJvLmFsbG9jVHlwZSh0eXBlLCBfdyAqIF9oICogY2hhbm5lbHMpO1xuICAgICAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICAgIEdMX1RFWFRVUkVfMkQkMSxcbiAgICAgICAgICBpLFxuICAgICAgICAgIHRleHR1cmUuZm9ybWF0LFxuICAgICAgICAgIF93LFxuICAgICAgICAgIF9oLFxuICAgICAgICAgIDAsXG4gICAgICAgICAgdGV4dHVyZS5mb3JtYXQsXG4gICAgICAgICAgdGV4dHVyZS50eXBlLFxuICAgICAgICAgIGRhdGEpO1xuICAgICAgICBpZiAoZGF0YSkgcG9vbC56ZXJvLmZyZWVUeXBlKGRhdGEpO1xuICAgICAgfVxuICAgICAgdGVtcFJlc3RvcmUoKTtcblxuICAgICAgLy8gYWxzbywgcmVjb21wdXRlIHRoZSB0ZXh0dXJlIHNpemUuXG4gICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgICAgdGV4dHVyZS5zdGF0cy5zaXplID0gZ2V0VGV4dHVyZVNpemUoXG4gICAgICAgICAgdGV4dHVyZS5pbnRlcm5hbGZvcm1hdCxcbiAgICAgICAgICB0ZXh0dXJlLnR5cGUsXG4gICAgICAgICAgdyxcbiAgICAgICAgICBoLFxuICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlMkRcbiAgICB9XG5cbiAgICByZWdsVGV4dHVyZTJEKGEsIGIpO1xuXG4gICAgcmVnbFRleHR1cmUyRC5zdWJpbWFnZSA9IHN1YmltYWdlO1xuICAgIHJlZ2xUZXh0dXJlMkQucmVzaXplID0gcmVzaXplO1xuICAgIHJlZ2xUZXh0dXJlMkQuX3JlZ2xUeXBlID0gJ3RleHR1cmUyZCc7XG4gICAgcmVnbFRleHR1cmUyRC5fdGV4dHVyZSA9IHRleHR1cmU7XG4gICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICByZWdsVGV4dHVyZTJELnN0YXRzID0gdGV4dHVyZS5zdGF0cztcbiAgICB9XG4gICAgcmVnbFRleHR1cmUyRC5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgdGV4dHVyZS5kZWNSZWYoKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlZ2xUZXh0dXJlMkRcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVDdWJlIChhMCwgYTEsIGEyLCBhMywgYTQsIGE1KSB7XG4gICAgdmFyIHRleHR1cmUgPSBuZXcgUkVHTFRleHR1cmUoR0xfVEVYVFVSRV9DVUJFX01BUCQxKTtcbiAgICB0ZXh0dXJlU2V0W3RleHR1cmUuaWRdID0gdGV4dHVyZTtcbiAgICBzdGF0cy5jdWJlQ291bnQrKztcblxuICAgIHZhciBmYWNlcyA9IG5ldyBBcnJheSg2KTtcblxuICAgIGZ1bmN0aW9uIHJlZ2xUZXh0dXJlQ3ViZSAoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSkge1xuICAgICAgdmFyIGk7XG4gICAgICB2YXIgdGV4SW5mbyA9IHRleHR1cmUudGV4SW5mbztcbiAgICAgIFRleEluZm8uY2FsbCh0ZXhJbmZvKTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgZmFjZXNbaV0gPSBhbGxvY01pcE1hcCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGEwID09PSAnbnVtYmVyJyB8fCAhYTApIHtcbiAgICAgICAgdmFyIHMgPSAoYTAgfCAwKSB8fCAxO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tU2hhcGUoZmFjZXNbaV0sIHMsIHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhMCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgaWYgKGExKSB7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzBdLCBhMCk7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzFdLCBhMSk7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzJdLCBhMik7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzNdLCBhMyk7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzRdLCBhNCk7XG4gICAgICAgICAgcGFyc2VNaXBNYXBGcm9tT2JqZWN0KGZhY2VzWzVdLCBhNSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyc2VUZXhJbmZvKHRleEluZm8sIGEwKTtcbiAgICAgICAgICBwYXJzZUZsYWdzKHRleHR1cmUsIGEwKTtcbiAgICAgICAgICBpZiAoJ2ZhY2VzJyBpbiBhMCkge1xuICAgICAgICAgICAgdmFyIGZhY2VfaW5wdXQgPSBhMC5mYWNlcztcbiAgICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShmYWNlX2lucHV0KSAmJiBmYWNlX2lucHV0Lmxlbmd0aCA9PT0gNixcbiAgICAgICAgICAgICAgJ2N1YmUgZmFjZXMgbXVzdCBiZSBhIGxlbmd0aCA2IGFycmF5Jyk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEodHlwZW9mIGZhY2VfaW5wdXRbaV0gPT09ICdvYmplY3QnICYmICEhZmFjZV9pbnB1dFtpXSxcbiAgICAgICAgICAgICAgICAnaW52YWxpZCBpbnB1dCBmb3IgY3ViZSBtYXAgZmFjZScpO1xuICAgICAgICAgICAgICBjb3B5RmxhZ3MoZmFjZXNbaV0sIHRleHR1cmUpO1xuICAgICAgICAgICAgICBwYXJzZU1pcE1hcEZyb21PYmplY3QoZmFjZXNbaV0sIGZhY2VfaW5wdXRbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgICAgICAgIHBhcnNlTWlwTWFwRnJvbU9iamVjdChmYWNlc1tpXSwgYTApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBhcmd1bWVudHMgdG8gY3ViZSBtYXAnKTtcbiAgICAgIH1cblxuICAgICAgY29weUZsYWdzKHRleHR1cmUsIGZhY2VzWzBdKTtcblxuICAgICAgaWYgKCFsaW1pdHMubnBvdFRleHR1cmVDdWJlKSB7XG4gICAgICAgIGNoZWNrJDEoaXNQb3cyJDEodGV4dHVyZS53aWR0aCkgJiYgaXNQb3cyJDEodGV4dHVyZS5oZWlnaHQpLCAneW91ciBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgbm9uIHBvd2VyIG9yIHR3byB0ZXh0dXJlIGRpbWVuc2lvbnMnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRleEluZm8uZ2VuTWlwbWFwcykge1xuICAgICAgICB0ZXh0dXJlLm1pcG1hc2sgPSAoZmFjZXNbMF0ud2lkdGggPDwgMSkgLSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHVyZS5taXBtYXNrID0gZmFjZXNbMF0ubWlwbWFzaztcbiAgICAgIH1cblxuICAgICAgY2hlY2skMS50ZXh0dXJlQ3ViZSh0ZXh0dXJlLCB0ZXhJbmZvLCBmYWNlcywgbGltaXRzKTtcbiAgICAgIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQgPSBmYWNlc1swXS5pbnRlcm5hbGZvcm1hdDtcblxuICAgICAgcmVnbFRleHR1cmVDdWJlLndpZHRoID0gZmFjZXNbMF0ud2lkdGg7XG4gICAgICByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0ID0gZmFjZXNbMF0uaGVpZ2h0O1xuXG4gICAgICB0ZW1wQmluZCh0ZXh0dXJlKTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgc2V0TWlwTWFwKGZhY2VzW2ldLCBHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gkMSArIGkpO1xuICAgICAgfVxuICAgICAgc2V0VGV4SW5mbyh0ZXhJbmZvLCBHTF9URVhUVVJFX0NVQkVfTUFQJDEpO1xuICAgICAgdGVtcFJlc3RvcmUoKTtcblxuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHRleHR1cmUuc3RhdHMuc2l6ZSA9IGdldFRleHR1cmVTaXplKFxuICAgICAgICAgIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsXG4gICAgICAgICAgdGV4dHVyZS50eXBlLFxuICAgICAgICAgIHJlZ2xUZXh0dXJlQ3ViZS53aWR0aCxcbiAgICAgICAgICByZWdsVGV4dHVyZUN1YmUuaGVpZ2h0LFxuICAgICAgICAgIHRleEluZm8uZ2VuTWlwbWFwcyxcbiAgICAgICAgICB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmVnbFRleHR1cmVDdWJlLmZvcm1hdCA9IHRleHR1cmVGb3JtYXRzSW52ZXJ0W3RleHR1cmUuaW50ZXJuYWxmb3JtYXRdO1xuICAgICAgcmVnbFRleHR1cmVDdWJlLnR5cGUgPSB0ZXh0dXJlVHlwZXNJbnZlcnRbdGV4dHVyZS50eXBlXTtcblxuICAgICAgcmVnbFRleHR1cmVDdWJlLm1hZyA9IG1hZ0ZpbHRlcnNJbnZlcnRbdGV4SW5mby5tYWdGaWx0ZXJdO1xuICAgICAgcmVnbFRleHR1cmVDdWJlLm1pbiA9IG1pbkZpbHRlcnNJbnZlcnRbdGV4SW5mby5taW5GaWx0ZXJdO1xuXG4gICAgICByZWdsVGV4dHVyZUN1YmUud3JhcFMgPSB3cmFwTW9kZXNJbnZlcnRbdGV4SW5mby53cmFwU107XG4gICAgICByZWdsVGV4dHVyZUN1YmUud3JhcFQgPSB3cmFwTW9kZXNJbnZlcnRbdGV4SW5mby53cmFwVF07XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgZnJlZU1pcE1hcChmYWNlc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWdsVGV4dHVyZUN1YmVcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdWJpbWFnZSAoZmFjZSwgaW1hZ2UsIHhfLCB5XywgbGV2ZWxfKSB7XG4gICAgICBjaGVjayQxKCEhaW1hZ2UsICdtdXN0IHNwZWNpZnkgaW1hZ2UgZGF0YScpO1xuICAgICAgY2hlY2skMSh0eXBlb2YgZmFjZSA9PT0gJ251bWJlcicgJiYgZmFjZSA9PT0gKGZhY2UgfCAwKSAmJlxuICAgICAgICBmYWNlID49IDAgJiYgZmFjZSA8IDYsICdpbnZhbGlkIGZhY2UnKTtcblxuICAgICAgdmFyIHggPSB4XyB8IDA7XG4gICAgICB2YXIgeSA9IHlfIHwgMDtcbiAgICAgIHZhciBsZXZlbCA9IGxldmVsXyB8IDA7XG5cbiAgICAgIHZhciBpbWFnZURhdGEgPSBhbGxvY0ltYWdlKCk7XG4gICAgICBjb3B5RmxhZ3MoaW1hZ2VEYXRhLCB0ZXh0dXJlKTtcbiAgICAgIGltYWdlRGF0YS53aWR0aCA9IDA7XG4gICAgICBpbWFnZURhdGEuaGVpZ2h0ID0gMDtcbiAgICAgIHBhcnNlSW1hZ2UoaW1hZ2VEYXRhLCBpbWFnZSk7XG4gICAgICBpbWFnZURhdGEud2lkdGggPSBpbWFnZURhdGEud2lkdGggfHwgKCh0ZXh0dXJlLndpZHRoID4+IGxldmVsKSAtIHgpO1xuICAgICAgaW1hZ2VEYXRhLmhlaWdodCA9IGltYWdlRGF0YS5oZWlnaHQgfHwgKCh0ZXh0dXJlLmhlaWdodCA+PiBsZXZlbCkgLSB5KTtcblxuICAgICAgY2hlY2skMShcbiAgICAgICAgdGV4dHVyZS50eXBlID09PSBpbWFnZURhdGEudHlwZSAmJlxuICAgICAgICB0ZXh0dXJlLmZvcm1hdCA9PT0gaW1hZ2VEYXRhLmZvcm1hdCAmJlxuICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0ID09PSBpbWFnZURhdGEuaW50ZXJuYWxmb3JtYXQsXG4gICAgICAgICdpbmNvbXBhdGlibGUgZm9ybWF0IGZvciB0ZXh0dXJlLnN1YmltYWdlJyk7XG4gICAgICBjaGVjayQxKFxuICAgICAgICB4ID49IDAgJiYgeSA+PSAwICYmXG4gICAgICAgIHggKyBpbWFnZURhdGEud2lkdGggPD0gdGV4dHVyZS53aWR0aCAmJlxuICAgICAgICB5ICsgaW1hZ2VEYXRhLmhlaWdodCA8PSB0ZXh0dXJlLmhlaWdodCxcbiAgICAgICAgJ3RleHR1cmUuc3ViaW1hZ2Ugd3JpdGUgb3V0IG9mIGJvdW5kcycpO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgdGV4dHVyZS5taXBtYXNrICYgKDEgPDwgbGV2ZWwpLFxuICAgICAgICAnbWlzc2luZyBtaXBtYXAgZGF0YScpO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgaW1hZ2VEYXRhLmRhdGEgfHwgaW1hZ2VEYXRhLmVsZW1lbnQgfHwgaW1hZ2VEYXRhLm5lZWRzQ29weSxcbiAgICAgICAgJ21pc3NpbmcgaW1hZ2UgZGF0YScpO1xuXG4gICAgICB0ZW1wQmluZCh0ZXh0dXJlKTtcbiAgICAgIHNldFN1YkltYWdlKGltYWdlRGF0YSwgR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDEgKyBmYWNlLCB4LCB5LCBsZXZlbCk7XG4gICAgICB0ZW1wUmVzdG9yZSgpO1xuXG4gICAgICBmcmVlSW1hZ2UoaW1hZ2VEYXRhKTtcblxuICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlc2l6ZSAocmFkaXVzXykge1xuICAgICAgdmFyIHJhZGl1cyA9IHJhZGl1c18gfCAwO1xuICAgICAgaWYgKHJhZGl1cyA9PT0gdGV4dHVyZS53aWR0aCkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgcmVnbFRleHR1cmVDdWJlLndpZHRoID0gdGV4dHVyZS53aWR0aCA9IHJhZGl1cztcbiAgICAgIHJlZ2xUZXh0dXJlQ3ViZS5oZWlnaHQgPSB0ZXh0dXJlLmhlaWdodCA9IHJhZGl1cztcblxuICAgICAgdGVtcEJpbmQodGV4dHVyZSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgdGV4dHVyZS5taXBtYXNrID4+IGo7ICsraikge1xuICAgICAgICAgIGdsLnRleEltYWdlMkQoXG4gICAgICAgICAgICBHTF9URVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1gkMSArIGksXG4gICAgICAgICAgICBqLFxuICAgICAgICAgICAgdGV4dHVyZS5mb3JtYXQsXG4gICAgICAgICAgICByYWRpdXMgPj4gaixcbiAgICAgICAgICAgIHJhZGl1cyA+PiBqLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIHRleHR1cmUuZm9ybWF0LFxuICAgICAgICAgICAgdGV4dHVyZS50eXBlLFxuICAgICAgICAgICAgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRlbXBSZXN0b3JlKCk7XG5cbiAgICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgICB0ZXh0dXJlLnN0YXRzLnNpemUgPSBnZXRUZXh0dXJlU2l6ZShcbiAgICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0LFxuICAgICAgICAgIHRleHR1cmUudHlwZSxcbiAgICAgICAgICByZWdsVGV4dHVyZUN1YmUud2lkdGgsXG4gICAgICAgICAgcmVnbFRleHR1cmVDdWJlLmhlaWdodCxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZVxuICAgIH1cblxuICAgIHJlZ2xUZXh0dXJlQ3ViZShhMCwgYTEsIGEyLCBhMywgYTQsIGE1KTtcblxuICAgIHJlZ2xUZXh0dXJlQ3ViZS5zdWJpbWFnZSA9IHN1YmltYWdlO1xuICAgIHJlZ2xUZXh0dXJlQ3ViZS5yZXNpemUgPSByZXNpemU7XG4gICAgcmVnbFRleHR1cmVDdWJlLl9yZWdsVHlwZSA9ICd0ZXh0dXJlQ3ViZSc7XG4gICAgcmVnbFRleHR1cmVDdWJlLl90ZXh0dXJlID0gdGV4dHVyZTtcbiAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgIHJlZ2xUZXh0dXJlQ3ViZS5zdGF0cyA9IHRleHR1cmUuc3RhdHM7XG4gICAgfVxuICAgIHJlZ2xUZXh0dXJlQ3ViZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgdGV4dHVyZS5kZWNSZWYoKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlZ2xUZXh0dXJlQ3ViZVxuICB9XG5cbiAgLy8gQ2FsbGVkIHdoZW4gcmVnbCBpcyBkZXN0cm95ZWRcbiAgZnVuY3Rpb24gZGVzdHJveVRleHR1cmVzICgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bVRleFVuaXRzOyArK2kpIHtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoR0xfVEVYVFVSRTAkMSArIGkpO1xuICAgICAgZ2wuYmluZFRleHR1cmUoR0xfVEVYVFVSRV8yRCQxLCBudWxsKTtcbiAgICAgIHRleHR1cmVVbml0c1tpXSA9IG51bGw7XG4gICAgfVxuICAgIHZhbHVlcyh0ZXh0dXJlU2V0KS5mb3JFYWNoKGRlc3Ryb3kpO1xuXG4gICAgc3RhdHMuY3ViZUNvdW50ID0gMDtcbiAgICBzdGF0cy50ZXh0dXJlQ291bnQgPSAwO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgc3RhdHMuZ2V0VG90YWxUZXh0dXJlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICBPYmplY3Qua2V5cyh0ZXh0dXJlU2V0KS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdG90YWwgKz0gdGV4dHVyZVNldFtrZXldLnN0YXRzLnNpemU7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0b3RhbFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiByZXN0b3JlVGV4dHVyZXMgKCkge1xuICAgIHZhbHVlcyh0ZXh0dXJlU2V0KS5mb3JFYWNoKGZ1bmN0aW9uICh0ZXh0dXJlKSB7XG4gICAgICB0ZXh0dXJlLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICBnbC5iaW5kVGV4dHVyZSh0ZXh0dXJlLnRhcmdldCwgdGV4dHVyZS50ZXh0dXJlKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMzI7ICsraSkge1xuICAgICAgICBpZiAoKHRleHR1cmUubWlwbWFzayAmICgxIDw8IGkpKSA9PT0gMCkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRleHR1cmUudGFyZ2V0ID09PSBHTF9URVhUVVJFXzJEJDEpIHtcbiAgICAgICAgICBnbC50ZXhJbWFnZTJEKEdMX1RFWFRVUkVfMkQkMSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0LFxuICAgICAgICAgICAgdGV4dHVyZS53aWR0aCA+PiBpLFxuICAgICAgICAgICAgdGV4dHVyZS5oZWlnaHQgPj4gaSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0LFxuICAgICAgICAgICAgdGV4dHVyZS50eXBlLFxuICAgICAgICAgICAgbnVsbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCA2OyArK2opIHtcbiAgICAgICAgICAgIGdsLnRleEltYWdlMkQoR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDEgKyBqLFxuICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICB0ZXh0dXJlLmludGVybmFsZm9ybWF0LFxuICAgICAgICAgICAgICB0ZXh0dXJlLndpZHRoID4+IGksXG4gICAgICAgICAgICAgIHRleHR1cmUuaGVpZ2h0ID4+IGksXG4gICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgIHRleHR1cmUuaW50ZXJuYWxmb3JtYXQsXG4gICAgICAgICAgICAgIHRleHR1cmUudHlwZSxcbiAgICAgICAgICAgICAgbnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzZXRUZXhJbmZvKHRleHR1cmUudGV4SW5mbywgdGV4dHVyZS50YXJnZXQpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjcmVhdGUyRDogY3JlYXRlVGV4dHVyZTJELFxuICAgIGNyZWF0ZUN1YmU6IGNyZWF0ZVRleHR1cmVDdWJlLFxuICAgIGNsZWFyOiBkZXN0cm95VGV4dHVyZXMsXG4gICAgZ2V0VGV4dHVyZTogZnVuY3Rpb24gKHdyYXBwZXIpIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfSxcbiAgICByZXN0b3JlOiByZXN0b3JlVGV4dHVyZXNcbiAgfVxufVxuXG52YXIgR0xfUkVOREVSQlVGRkVSID0gMHg4RDQxO1xuXG52YXIgR0xfUkdCQTQkMSA9IDB4ODA1NjtcbnZhciBHTF9SR0I1X0ExJDEgPSAweDgwNTc7XG52YXIgR0xfUkdCNTY1JDEgPSAweDhENjI7XG52YXIgR0xfREVQVEhfQ09NUE9ORU5UMTYgPSAweDgxQTU7XG52YXIgR0xfU1RFTkNJTF9JTkRFWDggPSAweDhENDg7XG52YXIgR0xfREVQVEhfU1RFTkNJTCQxID0gMHg4NEY5O1xuXG52YXIgR0xfU1JHQjhfQUxQSEE4X0VYVCA9IDB4OEM0MztcblxudmFyIEdMX1JHQkEzMkZfRVhUID0gMHg4ODE0O1xuXG52YXIgR0xfUkdCQTE2Rl9FWFQgPSAweDg4MUE7XG52YXIgR0xfUkdCMTZGX0VYVCA9IDB4ODgxQjtcblxudmFyIEZPUk1BVF9TSVpFUyA9IFtdO1xuXG5GT1JNQVRfU0laRVNbR0xfUkdCQTQkMV0gPSAyO1xuRk9STUFUX1NJWkVTW0dMX1JHQjVfQTEkMV0gPSAyO1xuRk9STUFUX1NJWkVTW0dMX1JHQjU2NSQxXSA9IDI7XG5cbkZPUk1BVF9TSVpFU1tHTF9ERVBUSF9DT01QT05FTlQxNl0gPSAyO1xuRk9STUFUX1NJWkVTW0dMX1NURU5DSUxfSU5ERVg4XSA9IDE7XG5GT1JNQVRfU0laRVNbR0xfREVQVEhfU1RFTkNJTCQxXSA9IDQ7XG5cbkZPUk1BVF9TSVpFU1tHTF9TUkdCOF9BTFBIQThfRVhUXSA9IDQ7XG5GT1JNQVRfU0laRVNbR0xfUkdCQTMyRl9FWFRdID0gMTY7XG5GT1JNQVRfU0laRVNbR0xfUkdCQTE2Rl9FWFRdID0gODtcbkZPUk1BVF9TSVpFU1tHTF9SR0IxNkZfRVhUXSA9IDY7XG5cbmZ1bmN0aW9uIGdldFJlbmRlcmJ1ZmZlclNpemUgKGZvcm1hdCwgd2lkdGgsIGhlaWdodCkge1xuICByZXR1cm4gRk9STUFUX1NJWkVTW2Zvcm1hdF0gKiB3aWR0aCAqIGhlaWdodFxufVxuXG52YXIgd3JhcFJlbmRlcmJ1ZmZlcnMgPSBmdW5jdGlvbiAoZ2wsIGV4dGVuc2lvbnMsIGxpbWl0cywgc3RhdHMsIGNvbmZpZykge1xuICB2YXIgZm9ybWF0VHlwZXMgPSB7XG4gICAgJ3JnYmE0JzogR0xfUkdCQTQkMSxcbiAgICAncmdiNTY1JzogR0xfUkdCNTY1JDEsXG4gICAgJ3JnYjUgYTEnOiBHTF9SR0I1X0ExJDEsXG4gICAgJ2RlcHRoJzogR0xfREVQVEhfQ09NUE9ORU5UMTYsXG4gICAgJ3N0ZW5jaWwnOiBHTF9TVEVOQ0lMX0lOREVYOCxcbiAgICAnZGVwdGggc3RlbmNpbCc6IEdMX0RFUFRIX1NURU5DSUwkMVxuICB9O1xuXG4gIGlmIChleHRlbnNpb25zLmV4dF9zcmdiKSB7XG4gICAgZm9ybWF0VHlwZXNbJ3NyZ2JhJ10gPSBHTF9TUkdCOF9BTFBIQThfRVhUO1xuICB9XG5cbiAgaWYgKGV4dGVuc2lvbnMuZXh0X2NvbG9yX2J1ZmZlcl9oYWxmX2Zsb2F0KSB7XG4gICAgZm9ybWF0VHlwZXNbJ3JnYmExNmYnXSA9IEdMX1JHQkExNkZfRVhUO1xuICAgIGZvcm1hdFR5cGVzWydyZ2IxNmYnXSA9IEdMX1JHQjE2Rl9FWFQ7XG4gIH1cblxuICBpZiAoZXh0ZW5zaW9ucy53ZWJnbF9jb2xvcl9idWZmZXJfZmxvYXQpIHtcbiAgICBmb3JtYXRUeXBlc1sncmdiYTMyZiddID0gR0xfUkdCQTMyRl9FWFQ7XG4gIH1cblxuICB2YXIgZm9ybWF0VHlwZXNJbnZlcnQgPSBbXTtcbiAgT2JqZWN0LmtleXMoZm9ybWF0VHlwZXMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciB2YWwgPSBmb3JtYXRUeXBlc1trZXldO1xuICAgIGZvcm1hdFR5cGVzSW52ZXJ0W3ZhbF0gPSBrZXk7XG4gIH0pO1xuXG4gIHZhciByZW5kZXJidWZmZXJDb3VudCA9IDA7XG4gIHZhciByZW5kZXJidWZmZXJTZXQgPSB7fTtcblxuICBmdW5jdGlvbiBSRUdMUmVuZGVyYnVmZmVyIChyZW5kZXJidWZmZXIpIHtcbiAgICB0aGlzLmlkID0gcmVuZGVyYnVmZmVyQ291bnQrKztcbiAgICB0aGlzLnJlZkNvdW50ID0gMTtcblxuICAgIHRoaXMucmVuZGVyYnVmZmVyID0gcmVuZGVyYnVmZmVyO1xuXG4gICAgdGhpcy5mb3JtYXQgPSBHTF9SR0JBNCQxO1xuICAgIHRoaXMud2lkdGggPSAwO1xuICAgIHRoaXMuaGVpZ2h0ID0gMDtcblxuICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgdGhpcy5zdGF0cyA9IHtzaXplOiAwfTtcbiAgICB9XG4gIH1cblxuICBSRUdMUmVuZGVyYnVmZmVyLnByb3RvdHlwZS5kZWNSZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKC0tdGhpcy5yZWZDb3VudCA8PSAwKSB7XG4gICAgICBkZXN0cm95KHRoaXMpO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBkZXN0cm95IChyYikge1xuICAgIHZhciBoYW5kbGUgPSByYi5yZW5kZXJidWZmZXI7XG4gICAgY2hlY2skMShoYW5kbGUsICdtdXN0IG5vdCBkb3VibGUgZGVzdHJveSByZW5kZXJidWZmZXInKTtcbiAgICBnbC5iaW5kUmVuZGVyYnVmZmVyKEdMX1JFTkRFUkJVRkZFUiwgbnVsbCk7XG4gICAgZ2wuZGVsZXRlUmVuZGVyYnVmZmVyKGhhbmRsZSk7XG4gICAgcmIucmVuZGVyYnVmZmVyID0gbnVsbDtcbiAgICByYi5yZWZDb3VudCA9IDA7XG4gICAgZGVsZXRlIHJlbmRlcmJ1ZmZlclNldFtyYi5pZF07XG4gICAgc3RhdHMucmVuZGVyYnVmZmVyQ291bnQtLTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVJlbmRlcmJ1ZmZlciAoYSwgYikge1xuICAgIHZhciByZW5kZXJidWZmZXIgPSBuZXcgUkVHTFJlbmRlcmJ1ZmZlcihnbC5jcmVhdGVSZW5kZXJidWZmZXIoKSk7XG4gICAgcmVuZGVyYnVmZmVyU2V0W3JlbmRlcmJ1ZmZlci5pZF0gPSByZW5kZXJidWZmZXI7XG4gICAgc3RhdHMucmVuZGVyYnVmZmVyQ291bnQrKztcblxuICAgIGZ1bmN0aW9uIHJlZ2xSZW5kZXJidWZmZXIgKGEsIGIpIHtcbiAgICAgIHZhciB3ID0gMDtcbiAgICAgIHZhciBoID0gMDtcbiAgICAgIHZhciBmb3JtYXQgPSBHTF9SR0JBNCQxO1xuXG4gICAgICBpZiAodHlwZW9mIGEgPT09ICdvYmplY3QnICYmIGEpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBhO1xuICAgICAgICBpZiAoJ3NoYXBlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgdmFyIHNoYXBlID0gb3B0aW9ucy5zaGFwZTtcbiAgICAgICAgICBjaGVjayQxKEFycmF5LmlzQXJyYXkoc2hhcGUpICYmIHNoYXBlLmxlbmd0aCA+PSAyLFxuICAgICAgICAgICAgJ2ludmFsaWQgcmVuZGVyYnVmZmVyIHNoYXBlJyk7XG4gICAgICAgICAgdyA9IHNoYXBlWzBdIHwgMDtcbiAgICAgICAgICBoID0gc2hhcGVbMV0gfCAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICgncmFkaXVzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB3ID0gaCA9IG9wdGlvbnMucmFkaXVzIHwgMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCd3aWR0aCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgdyA9IG9wdGlvbnMud2lkdGggfCAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ2hlaWdodCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgaCA9IG9wdGlvbnMuaGVpZ2h0IHwgMDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdmb3JtYXQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBjaGVjayQxLnBhcmFtZXRlcihvcHRpb25zLmZvcm1hdCwgZm9ybWF0VHlwZXMsXG4gICAgICAgICAgICAnaW52YWxpZCByZW5kZXJidWZmZXIgZm9ybWF0Jyk7XG4gICAgICAgICAgZm9ybWF0ID0gZm9ybWF0VHlwZXNbb3B0aW9ucy5mb3JtYXRdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhID09PSAnbnVtYmVyJykge1xuICAgICAgICB3ID0gYSB8IDA7XG4gICAgICAgIGlmICh0eXBlb2YgYiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBoID0gYiB8IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaCA9IHc7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWEpIHtcbiAgICAgICAgdyA9IGggPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5yYWlzZSgnaW52YWxpZCBhcmd1bWVudHMgdG8gcmVuZGVyYnVmZmVyIGNvbnN0cnVjdG9yJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIGNoZWNrIHNoYXBlXG4gICAgICBjaGVjayQxKFxuICAgICAgICB3ID4gMCAmJiBoID4gMCAmJlxuICAgICAgICB3IDw9IGxpbWl0cy5tYXhSZW5kZXJidWZmZXJTaXplICYmIGggPD0gbGltaXRzLm1heFJlbmRlcmJ1ZmZlclNpemUsXG4gICAgICAgICdpbnZhbGlkIHJlbmRlcmJ1ZmZlciBzaXplJyk7XG5cbiAgICAgIGlmICh3ID09PSByZW5kZXJidWZmZXIud2lkdGggJiZcbiAgICAgICAgICBoID09PSByZW5kZXJidWZmZXIuaGVpZ2h0ICYmXG4gICAgICAgICAgZm9ybWF0ID09PSByZW5kZXJidWZmZXIuZm9ybWF0KSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICByZWdsUmVuZGVyYnVmZmVyLndpZHRoID0gcmVuZGVyYnVmZmVyLndpZHRoID0gdztcbiAgICAgIHJlZ2xSZW5kZXJidWZmZXIuaGVpZ2h0ID0gcmVuZGVyYnVmZmVyLmhlaWdodCA9IGg7XG4gICAgICByZW5kZXJidWZmZXIuZm9ybWF0ID0gZm9ybWF0O1xuXG4gICAgICBnbC5iaW5kUmVuZGVyYnVmZmVyKEdMX1JFTkRFUkJVRkZFUiwgcmVuZGVyYnVmZmVyLnJlbmRlcmJ1ZmZlcik7XG4gICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKEdMX1JFTkRFUkJVRkZFUiwgZm9ybWF0LCB3LCBoKTtcblxuICAgICAgY2hlY2skMShcbiAgICAgICAgZ2wuZ2V0RXJyb3IoKSA9PT0gMCxcbiAgICAgICAgJ2ludmFsaWQgcmVuZGVyIGJ1ZmZlciBmb3JtYXQnKTtcblxuICAgICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICAgIHJlbmRlcmJ1ZmZlci5zdGF0cy5zaXplID0gZ2V0UmVuZGVyYnVmZmVyU2l6ZShyZW5kZXJidWZmZXIuZm9ybWF0LCByZW5kZXJidWZmZXIud2lkdGgsIHJlbmRlcmJ1ZmZlci5oZWlnaHQpO1xuICAgICAgfVxuICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5mb3JtYXQgPSBmb3JtYXRUeXBlc0ludmVydFtyZW5kZXJidWZmZXIuZm9ybWF0XTtcblxuICAgICAgcmV0dXJuIHJlZ2xSZW5kZXJidWZmZXJcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUgKHdfLCBoXykge1xuICAgICAgdmFyIHcgPSB3XyB8IDA7XG4gICAgICB2YXIgaCA9IChoXyB8IDApIHx8IHc7XG5cbiAgICAgIGlmICh3ID09PSByZW5kZXJidWZmZXIud2lkdGggJiYgaCA9PT0gcmVuZGVyYnVmZmVyLmhlaWdodCkge1xuICAgICAgICByZXR1cm4gcmVnbFJlbmRlcmJ1ZmZlclxuICAgICAgfVxuXG4gICAgICAvLyBjaGVjayBzaGFwZVxuICAgICAgY2hlY2skMShcbiAgICAgICAgdyA+IDAgJiYgaCA+IDAgJiZcbiAgICAgICAgdyA8PSBsaW1pdHMubWF4UmVuZGVyYnVmZmVyU2l6ZSAmJiBoIDw9IGxpbWl0cy5tYXhSZW5kZXJidWZmZXJTaXplLFxuICAgICAgICAnaW52YWxpZCByZW5kZXJidWZmZXIgc2l6ZScpO1xuXG4gICAgICByZWdsUmVuZGVyYnVmZmVyLndpZHRoID0gcmVuZGVyYnVmZmVyLndpZHRoID0gdztcbiAgICAgIHJlZ2xSZW5kZXJidWZmZXIuaGVpZ2h0ID0gcmVuZGVyYnVmZmVyLmhlaWdodCA9IGg7XG5cbiAgICAgIGdsLmJpbmRSZW5kZXJidWZmZXIoR0xfUkVOREVSQlVGRkVSLCByZW5kZXJidWZmZXIucmVuZGVyYnVmZmVyKTtcbiAgICAgIGdsLnJlbmRlcmJ1ZmZlclN0b3JhZ2UoR0xfUkVOREVSQlVGRkVSLCByZW5kZXJidWZmZXIuZm9ybWF0LCB3LCBoKTtcblxuICAgICAgY2hlY2skMShcbiAgICAgICAgZ2wuZ2V0RXJyb3IoKSA9PT0gMCxcbiAgICAgICAgJ2ludmFsaWQgcmVuZGVyIGJ1ZmZlciBmb3JtYXQnKTtcblxuICAgICAgLy8gYWxzbywgcmVjb21wdXRlIHNpemUuXG4gICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgICAgcmVuZGVyYnVmZmVyLnN0YXRzLnNpemUgPSBnZXRSZW5kZXJidWZmZXJTaXplKFxuICAgICAgICAgIHJlbmRlcmJ1ZmZlci5mb3JtYXQsIHJlbmRlcmJ1ZmZlci53aWR0aCwgcmVuZGVyYnVmZmVyLmhlaWdodCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWdsUmVuZGVyYnVmZmVyXG4gICAgfVxuXG4gICAgcmVnbFJlbmRlcmJ1ZmZlcihhLCBiKTtcblxuICAgIHJlZ2xSZW5kZXJidWZmZXIucmVzaXplID0gcmVzaXplO1xuICAgIHJlZ2xSZW5kZXJidWZmZXIuX3JlZ2xUeXBlID0gJ3JlbmRlcmJ1ZmZlcic7XG4gICAgcmVnbFJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyID0gcmVuZGVyYnVmZmVyO1xuICAgIGlmIChjb25maWcucHJvZmlsZSkge1xuICAgICAgcmVnbFJlbmRlcmJ1ZmZlci5zdGF0cyA9IHJlbmRlcmJ1ZmZlci5zdGF0cztcbiAgICB9XG4gICAgcmVnbFJlbmRlcmJ1ZmZlci5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmVuZGVyYnVmZmVyLmRlY1JlZigpO1xuICAgIH07XG5cbiAgICByZXR1cm4gcmVnbFJlbmRlcmJ1ZmZlclxuICB9XG5cbiAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgc3RhdHMuZ2V0VG90YWxSZW5kZXJidWZmZXJTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgIE9iamVjdC5rZXlzKHJlbmRlcmJ1ZmZlclNldCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHRvdGFsICs9IHJlbmRlcmJ1ZmZlclNldFtrZXldLnN0YXRzLnNpemU7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0b3RhbFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiByZXN0b3JlUmVuZGVyYnVmZmVycyAoKSB7XG4gICAgdmFsdWVzKHJlbmRlcmJ1ZmZlclNldCkuZm9yRWFjaChmdW5jdGlvbiAocmIpIHtcbiAgICAgIHJiLnJlbmRlcmJ1ZmZlciA9IGdsLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpO1xuICAgICAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihHTF9SRU5ERVJCVUZGRVIsIHJiLnJlbmRlcmJ1ZmZlcik7XG4gICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKEdMX1JFTkRFUkJVRkZFUiwgcmIuZm9ybWF0LCByYi53aWR0aCwgcmIuaGVpZ2h0KTtcbiAgICB9KTtcbiAgICBnbC5iaW5kUmVuZGVyYnVmZmVyKEdMX1JFTkRFUkJVRkZFUiwgbnVsbCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNyZWF0ZTogY3JlYXRlUmVuZGVyYnVmZmVyLFxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YWx1ZXMocmVuZGVyYnVmZmVyU2V0KS5mb3JFYWNoKGRlc3Ryb3kpO1xuICAgIH0sXG4gICAgcmVzdG9yZTogcmVzdG9yZVJlbmRlcmJ1ZmZlcnNcbiAgfVxufTtcblxuLy8gV2Ugc3RvcmUgdGhlc2UgY29uc3RhbnRzIHNvIHRoYXQgdGhlIG1pbmlmaWVyIGNhbiBpbmxpbmUgdGhlbVxudmFyIEdMX0ZSQU1FQlVGRkVSJDEgPSAweDhENDA7XG52YXIgR0xfUkVOREVSQlVGRkVSJDEgPSAweDhENDE7XG5cbnZhciBHTF9URVhUVVJFXzJEJDIgPSAweDBERTE7XG52YXIgR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIgPSAweDg1MTU7XG5cbnZhciBHTF9DT0xPUl9BVFRBQ0hNRU5UMCQxID0gMHg4Q0UwO1xudmFyIEdMX0RFUFRIX0FUVEFDSE1FTlQgPSAweDhEMDA7XG52YXIgR0xfU1RFTkNJTF9BVFRBQ0hNRU5UID0gMHg4RDIwO1xudmFyIEdMX0RFUFRIX1NURU5DSUxfQVRUQUNITUVOVCA9IDB4ODIxQTtcblxudmFyIEdMX0ZSQU1FQlVGRkVSX0NPTVBMRVRFJDEgPSAweDhDRDU7XG52YXIgR0xfRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UID0gMHg4Q0Q2O1xudmFyIEdMX0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfTUlTU0lOR19BVFRBQ0hNRU5UID0gMHg4Q0Q3O1xudmFyIEdMX0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OUyA9IDB4OENEOTtcbnZhciBHTF9GUkFNRUJVRkZFUl9VTlNVUFBPUlRFRCA9IDB4OENERDtcblxudmFyIEdMX0hBTEZfRkxPQVRfT0VTJDIgPSAweDhENjE7XG52YXIgR0xfVU5TSUdORURfQllURSQ2ID0gMHgxNDAxO1xudmFyIEdMX0ZMT0FUJDUgPSAweDE0MDY7XG5cbnZhciBHTF9SR0IkMSA9IDB4MTkwNztcbnZhciBHTF9SR0JBJDIgPSAweDE5MDg7XG5cbnZhciBHTF9ERVBUSF9DT01QT05FTlQkMSA9IDB4MTkwMjtcblxudmFyIGNvbG9yVGV4dHVyZUZvcm1hdEVudW1zID0gW1xuICBHTF9SR0IkMSxcbiAgR0xfUkdCQSQyXG5dO1xuXG4vLyBmb3IgZXZlcnkgdGV4dHVyZSBmb3JtYXQsIHN0b3JlXG4vLyB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzXG52YXIgdGV4dHVyZUZvcm1hdENoYW5uZWxzID0gW107XG50ZXh0dXJlRm9ybWF0Q2hhbm5lbHNbR0xfUkdCQSQyXSA9IDQ7XG50ZXh0dXJlRm9ybWF0Q2hhbm5lbHNbR0xfUkdCJDFdID0gMztcblxuLy8gZm9yIGV2ZXJ5IHRleHR1cmUgdHlwZSwgc3RvcmVcbi8vIHRoZSBzaXplIGluIGJ5dGVzLlxudmFyIHRleHR1cmVUeXBlU2l6ZXMgPSBbXTtcbnRleHR1cmVUeXBlU2l6ZXNbR0xfVU5TSUdORURfQllURSQ2XSA9IDE7XG50ZXh0dXJlVHlwZVNpemVzW0dMX0ZMT0FUJDVdID0gNDtcbnRleHR1cmVUeXBlU2l6ZXNbR0xfSEFMRl9GTE9BVF9PRVMkMl0gPSAyO1xuXG52YXIgR0xfUkdCQTQkMiA9IDB4ODA1NjtcbnZhciBHTF9SR0I1X0ExJDIgPSAweDgwNTc7XG52YXIgR0xfUkdCNTY1JDIgPSAweDhENjI7XG52YXIgR0xfREVQVEhfQ09NUE9ORU5UMTYkMSA9IDB4ODFBNTtcbnZhciBHTF9TVEVOQ0lMX0lOREVYOCQxID0gMHg4RDQ4O1xudmFyIEdMX0RFUFRIX1NURU5DSUwkMiA9IDB4ODRGOTtcblxudmFyIEdMX1NSR0I4X0FMUEhBOF9FWFQkMSA9IDB4OEM0MztcblxudmFyIEdMX1JHQkEzMkZfRVhUJDEgPSAweDg4MTQ7XG5cbnZhciBHTF9SR0JBMTZGX0VYVCQxID0gMHg4ODFBO1xudmFyIEdMX1JHQjE2Rl9FWFQkMSA9IDB4ODgxQjtcblxudmFyIGNvbG9yUmVuZGVyYnVmZmVyRm9ybWF0RW51bXMgPSBbXG4gIEdMX1JHQkE0JDIsXG4gIEdMX1JHQjVfQTEkMixcbiAgR0xfUkdCNTY1JDIsXG4gIEdMX1NSR0I4X0FMUEhBOF9FWFQkMSxcbiAgR0xfUkdCQTE2Rl9FWFQkMSxcbiAgR0xfUkdCMTZGX0VYVCQxLFxuICBHTF9SR0JBMzJGX0VYVCQxXG5dO1xuXG52YXIgc3RhdHVzQ29kZSA9IHt9O1xuc3RhdHVzQ29kZVtHTF9GUkFNRUJVRkZFUl9DT01QTEVURSQxXSA9ICdjb21wbGV0ZSc7XG5zdGF0dXNDb2RlW0dMX0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVF0gPSAnaW5jb21wbGV0ZSBhdHRhY2htZW50JztcbnN0YXR1c0NvZGVbR0xfRlJBTUVCVUZGRVJfSU5DT01QTEVURV9ESU1FTlNJT05TXSA9ICdpbmNvbXBsZXRlIGRpbWVuc2lvbnMnO1xuc3RhdHVzQ29kZVtHTF9GUkFNRUJVRkZFUl9JTkNPTVBMRVRFX01JU1NJTkdfQVRUQUNITUVOVF0gPSAnaW5jb21wbGV0ZSwgbWlzc2luZyBhdHRhY2htZW50JztcbnN0YXR1c0NvZGVbR0xfRlJBTUVCVUZGRVJfVU5TVVBQT1JURURdID0gJ3Vuc3VwcG9ydGVkJztcblxuZnVuY3Rpb24gd3JhcEZCT1N0YXRlIChcbiAgZ2wsXG4gIGV4dGVuc2lvbnMsXG4gIGxpbWl0cyxcbiAgdGV4dHVyZVN0YXRlLFxuICByZW5kZXJidWZmZXJTdGF0ZSxcbiAgc3RhdHMpIHtcbiAgdmFyIGZyYW1lYnVmZmVyU3RhdGUgPSB7XG4gICAgY3VyOiBudWxsLFxuICAgIG5leHQ6IG51bGwsXG4gICAgZGlydHk6IGZhbHNlLFxuICAgIHNldEZCTzogbnVsbFxuICB9O1xuXG4gIHZhciBjb2xvclRleHR1cmVGb3JtYXRzID0gWydyZ2JhJ107XG4gIHZhciBjb2xvclJlbmRlcmJ1ZmZlckZvcm1hdHMgPSBbJ3JnYmE0JywgJ3JnYjU2NScsICdyZ2I1IGExJ107XG5cbiAgaWYgKGV4dGVuc2lvbnMuZXh0X3NyZ2IpIHtcbiAgICBjb2xvclJlbmRlcmJ1ZmZlckZvcm1hdHMucHVzaCgnc3JnYmEnKTtcbiAgfVxuXG4gIGlmIChleHRlbnNpb25zLmV4dF9jb2xvcl9idWZmZXJfaGFsZl9mbG9hdCkge1xuICAgIGNvbG9yUmVuZGVyYnVmZmVyRm9ybWF0cy5wdXNoKCdyZ2JhMTZmJywgJ3JnYjE2ZicpO1xuICB9XG5cbiAgaWYgKGV4dGVuc2lvbnMud2ViZ2xfY29sb3JfYnVmZmVyX2Zsb2F0KSB7XG4gICAgY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLnB1c2goJ3JnYmEzMmYnKTtcbiAgfVxuXG4gIHZhciBjb2xvclR5cGVzID0gWyd1aW50OCddO1xuICBpZiAoZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9oYWxmX2Zsb2F0KSB7XG4gICAgY29sb3JUeXBlcy5wdXNoKCdoYWxmIGZsb2F0JywgJ2Zsb2F0MTYnKTtcbiAgfVxuICBpZiAoZXh0ZW5zaW9ucy5vZXNfdGV4dHVyZV9mbG9hdCkge1xuICAgIGNvbG9yVHlwZXMucHVzaCgnZmxvYXQnLCAnZmxvYXQzMicpO1xuICB9XG5cbiAgZnVuY3Rpb24gRnJhbWVidWZmZXJBdHRhY2htZW50ICh0YXJnZXQsIHRleHR1cmUsIHJlbmRlcmJ1ZmZlcikge1xuICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgIHRoaXMudGV4dHVyZSA9IHRleHR1cmU7XG4gICAgdGhpcy5yZW5kZXJidWZmZXIgPSByZW5kZXJidWZmZXI7XG5cbiAgICB2YXIgdyA9IDA7XG4gICAgdmFyIGggPSAwO1xuICAgIGlmICh0ZXh0dXJlKSB7XG4gICAgICB3ID0gdGV4dHVyZS53aWR0aDtcbiAgICAgIGggPSB0ZXh0dXJlLmhlaWdodDtcbiAgICB9IGVsc2UgaWYgKHJlbmRlcmJ1ZmZlcikge1xuICAgICAgdyA9IHJlbmRlcmJ1ZmZlci53aWR0aDtcbiAgICAgIGggPSByZW5kZXJidWZmZXIuaGVpZ2h0O1xuICAgIH1cbiAgICB0aGlzLndpZHRoID0gdztcbiAgICB0aGlzLmhlaWdodCA9IGg7XG4gIH1cblxuICBmdW5jdGlvbiBkZWNSZWYgKGF0dGFjaG1lbnQpIHtcbiAgICBpZiAoYXR0YWNobWVudCkge1xuICAgICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgICBhdHRhY2htZW50LnRleHR1cmUuX3RleHR1cmUuZGVjUmVmKCk7XG4gICAgICB9XG4gICAgICBpZiAoYXR0YWNobWVudC5yZW5kZXJidWZmZXIpIHtcbiAgICAgICAgYXR0YWNobWVudC5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5kZWNSZWYoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbmNSZWZBbmRDaGVja1NoYXBlIChhdHRhY2htZW50LCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgaWYgKCFhdHRhY2htZW50KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgdmFyIHRleHR1cmUgPSBhdHRhY2htZW50LnRleHR1cmUuX3RleHR1cmU7XG4gICAgICB2YXIgdHcgPSBNYXRoLm1heCgxLCB0ZXh0dXJlLndpZHRoKTtcbiAgICAgIHZhciB0aCA9IE1hdGgubWF4KDEsIHRleHR1cmUuaGVpZ2h0KTtcbiAgICAgIGNoZWNrJDEodHcgPT09IHdpZHRoICYmIHRoID09PSBoZWlnaHQsXG4gICAgICAgICdpbmNvbnNpc3RlbnQgd2lkdGgvaGVpZ2h0IGZvciBzdXBwbGllZCB0ZXh0dXJlJyk7XG4gICAgICB0ZXh0dXJlLnJlZkNvdW50ICs9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciByZW5kZXJidWZmZXIgPSBhdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgcmVuZGVyYnVmZmVyLndpZHRoID09PSB3aWR0aCAmJiByZW5kZXJidWZmZXIuaGVpZ2h0ID09PSBoZWlnaHQsXG4gICAgICAgICdpbmNvbnNpc3RlbnQgd2lkdGgvaGVpZ2h0IGZvciByZW5kZXJidWZmZXInKTtcbiAgICAgIHJlbmRlcmJ1ZmZlci5yZWZDb3VudCArPSAxO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGF0dGFjaCAobG9jYXRpb24sIGF0dGFjaG1lbnQpIHtcbiAgICBpZiAoYXR0YWNobWVudCkge1xuICAgICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChcbiAgICAgICAgICBHTF9GUkFNRUJVRkZFUiQxLFxuICAgICAgICAgIGxvY2F0aW9uLFxuICAgICAgICAgIGF0dGFjaG1lbnQudGFyZ2V0LFxuICAgICAgICAgIGF0dGFjaG1lbnQudGV4dHVyZS5fdGV4dHVyZS50ZXh0dXJlLFxuICAgICAgICAgIDApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZ2wuZnJhbWVidWZmZXJSZW5kZXJidWZmZXIoXG4gICAgICAgICAgR0xfRlJBTUVCVUZGRVIkMSxcbiAgICAgICAgICBsb2NhdGlvbixcbiAgICAgICAgICBHTF9SRU5ERVJCVUZGRVIkMSxcbiAgICAgICAgICBhdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLnJlbmRlcmJ1ZmZlcik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VBdHRhY2htZW50IChhdHRhY2htZW50KSB7XG4gICAgdmFyIHRhcmdldCA9IEdMX1RFWFRVUkVfMkQkMjtcbiAgICB2YXIgdGV4dHVyZSA9IG51bGw7XG4gICAgdmFyIHJlbmRlcmJ1ZmZlciA9IG51bGw7XG5cbiAgICB2YXIgZGF0YSA9IGF0dGFjaG1lbnQ7XG4gICAgaWYgKHR5cGVvZiBhdHRhY2htZW50ID09PSAnb2JqZWN0Jykge1xuICAgICAgZGF0YSA9IGF0dGFjaG1lbnQuZGF0YTtcbiAgICAgIGlmICgndGFyZ2V0JyBpbiBhdHRhY2htZW50KSB7XG4gICAgICAgIHRhcmdldCA9IGF0dGFjaG1lbnQudGFyZ2V0IHwgMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjaGVjayQxLnR5cGUoZGF0YSwgJ2Z1bmN0aW9uJywgJ2ludmFsaWQgYXR0YWNobWVudCBkYXRhJyk7XG5cbiAgICB2YXIgdHlwZSA9IGRhdGEuX3JlZ2xUeXBlO1xuICAgIGlmICh0eXBlID09PSAndGV4dHVyZTJkJykge1xuICAgICAgdGV4dHVyZSA9IGRhdGE7XG4gICAgICBjaGVjayQxKHRhcmdldCA9PT0gR0xfVEVYVFVSRV8yRCQyKTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICd0ZXh0dXJlQ3ViZScpIHtcbiAgICAgIHRleHR1cmUgPSBkYXRhO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgdGFyZ2V0ID49IEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQyICYmXG4gICAgICAgIHRhcmdldCA8IEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQyICsgNixcbiAgICAgICAgJ2ludmFsaWQgY3ViZSBtYXAgdGFyZ2V0Jyk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAncmVuZGVyYnVmZmVyJykge1xuICAgICAgcmVuZGVyYnVmZmVyID0gZGF0YTtcbiAgICAgIHRhcmdldCA9IEdMX1JFTkRFUkJVRkZFUiQxO1xuICAgIH0gZWxzZSB7XG4gICAgICBjaGVjayQxLnJhaXNlKCdpbnZhbGlkIHJlZ2wgb2JqZWN0IGZvciBhdHRhY2htZW50Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBGcmFtZWJ1ZmZlckF0dGFjaG1lbnQodGFyZ2V0LCB0ZXh0dXJlLCByZW5kZXJidWZmZXIpXG4gIH1cblxuICBmdW5jdGlvbiBhbGxvY0F0dGFjaG1lbnQgKFxuICAgIHdpZHRoLFxuICAgIGhlaWdodCxcbiAgICBpc1RleHR1cmUsXG4gICAgZm9ybWF0LFxuICAgIHR5cGUpIHtcbiAgICBpZiAoaXNUZXh0dXJlKSB7XG4gICAgICB2YXIgdGV4dHVyZSA9IHRleHR1cmVTdGF0ZS5jcmVhdGUyRCh7XG4gICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgIGZvcm1hdDogZm9ybWF0LFxuICAgICAgICB0eXBlOiB0eXBlXG4gICAgICB9KTtcbiAgICAgIHRleHR1cmUuX3RleHR1cmUucmVmQ291bnQgPSAwO1xuICAgICAgcmV0dXJuIG5ldyBGcmFtZWJ1ZmZlckF0dGFjaG1lbnQoR0xfVEVYVFVSRV8yRCQyLCB0ZXh0dXJlLCBudWxsKVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgcmIgPSByZW5kZXJidWZmZXJTdGF0ZS5jcmVhdGUoe1xuICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICBmb3JtYXQ6IGZvcm1hdFxuICAgICAgfSk7XG4gICAgICByYi5fcmVuZGVyYnVmZmVyLnJlZkNvdW50ID0gMDtcbiAgICAgIHJldHVybiBuZXcgRnJhbWVidWZmZXJBdHRhY2htZW50KEdMX1JFTkRFUkJVRkZFUiQxLCBudWxsLCByYilcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB1bndyYXBBdHRhY2htZW50IChhdHRhY2htZW50KSB7XG4gICAgcmV0dXJuIGF0dGFjaG1lbnQgJiYgKGF0dGFjaG1lbnQudGV4dHVyZSB8fCBhdHRhY2htZW50LnJlbmRlcmJ1ZmZlcilcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlc2l6ZUF0dGFjaG1lbnQgKGF0dGFjaG1lbnQsIHcsIGgpIHtcbiAgICBpZiAoYXR0YWNobWVudCkge1xuICAgICAgaWYgKGF0dGFjaG1lbnQudGV4dHVyZSkge1xuICAgICAgICBhdHRhY2htZW50LnRleHR1cmUucmVzaXplKHcsIGgpO1xuICAgICAgfSBlbHNlIGlmIChhdHRhY2htZW50LnJlbmRlcmJ1ZmZlcikge1xuICAgICAgICBhdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5yZXNpemUodywgaCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIGZyYW1lYnVmZmVyQ291bnQgPSAwO1xuICB2YXIgZnJhbWVidWZmZXJTZXQgPSB7fTtcblxuICBmdW5jdGlvbiBSRUdMRnJhbWVidWZmZXIgKCkge1xuICAgIHRoaXMuaWQgPSBmcmFtZWJ1ZmZlckNvdW50Kys7XG4gICAgZnJhbWVidWZmZXJTZXRbdGhpcy5pZF0gPSB0aGlzO1xuXG4gICAgdGhpcy5mcmFtZWJ1ZmZlciA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgdGhpcy53aWR0aCA9IDA7XG4gICAgdGhpcy5oZWlnaHQgPSAwO1xuXG4gICAgdGhpcy5jb2xvckF0dGFjaG1lbnRzID0gW107XG4gICAgdGhpcy5kZXB0aEF0dGFjaG1lbnQgPSBudWxsO1xuICAgIHRoaXMuc3RlbmNpbEF0dGFjaG1lbnQgPSBudWxsO1xuICAgIHRoaXMuZGVwdGhTdGVuY2lsQXR0YWNobWVudCA9IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBkZWNGQk9SZWZzIChmcmFtZWJ1ZmZlcikge1xuICAgIGZyYW1lYnVmZmVyLmNvbG9yQXR0YWNobWVudHMuZm9yRWFjaChkZWNSZWYpO1xuICAgIGRlY1JlZihmcmFtZWJ1ZmZlci5kZXB0aEF0dGFjaG1lbnQpO1xuICAgIGRlY1JlZihmcmFtZWJ1ZmZlci5zdGVuY2lsQXR0YWNobWVudCk7XG4gICAgZGVjUmVmKGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVzdHJveSAoZnJhbWVidWZmZXIpIHtcbiAgICB2YXIgaGFuZGxlID0gZnJhbWVidWZmZXIuZnJhbWVidWZmZXI7XG4gICAgY2hlY2skMShoYW5kbGUsICdtdXN0IG5vdCBkb3VibGUgZGVzdHJveSBmcmFtZWJ1ZmZlcicpO1xuICAgIGdsLmRlbGV0ZUZyYW1lYnVmZmVyKGhhbmRsZSk7XG4gICAgZnJhbWVidWZmZXIuZnJhbWVidWZmZXIgPSBudWxsO1xuICAgIHN0YXRzLmZyYW1lYnVmZmVyQ291bnQtLTtcbiAgICBkZWxldGUgZnJhbWVidWZmZXJTZXRbZnJhbWVidWZmZXIuaWRdO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlRnJhbWVidWZmZXIgKGZyYW1lYnVmZmVyKSB7XG4gICAgdmFyIGk7XG5cbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoR0xfRlJBTUVCVUZGRVIkMSwgZnJhbWVidWZmZXIuZnJhbWVidWZmZXIpO1xuICAgIHZhciBjb2xvckF0dGFjaG1lbnRzID0gZnJhbWVidWZmZXIuY29sb3JBdHRhY2htZW50cztcbiAgICBmb3IgKGkgPSAwOyBpIDwgY29sb3JBdHRhY2htZW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgYXR0YWNoKEdMX0NPTE9SX0FUVEFDSE1FTlQwJDEgKyBpLCBjb2xvckF0dGFjaG1lbnRzW2ldKTtcbiAgICB9XG4gICAgZm9yIChpID0gY29sb3JBdHRhY2htZW50cy5sZW5ndGg7IGkgPCBsaW1pdHMubWF4Q29sb3JBdHRhY2htZW50czsgKytpKSB7XG4gICAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChcbiAgICAgICAgR0xfRlJBTUVCVUZGRVIkMSxcbiAgICAgICAgR0xfQ09MT1JfQVRUQUNITUVOVDAkMSArIGksXG4gICAgICAgIEdMX1RFWFRVUkVfMkQkMixcbiAgICAgICAgbnVsbCxcbiAgICAgICAgMCk7XG4gICAgfVxuXG4gICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoXG4gICAgICBHTF9GUkFNRUJVRkZFUiQxLFxuICAgICAgR0xfREVQVEhfU1RFTkNJTF9BVFRBQ0hNRU5ULFxuICAgICAgR0xfVEVYVFVSRV8yRCQyLFxuICAgICAgbnVsbCxcbiAgICAgIDApO1xuICAgIGdsLmZyYW1lYnVmZmVyVGV4dHVyZTJEKFxuICAgICAgR0xfRlJBTUVCVUZGRVIkMSxcbiAgICAgIEdMX0RFUFRIX0FUVEFDSE1FTlQsXG4gICAgICBHTF9URVhUVVJFXzJEJDIsXG4gICAgICBudWxsLFxuICAgICAgMCk7XG4gICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoXG4gICAgICBHTF9GUkFNRUJVRkZFUiQxLFxuICAgICAgR0xfU1RFTkNJTF9BVFRBQ0hNRU5ULFxuICAgICAgR0xfVEVYVFVSRV8yRCQyLFxuICAgICAgbnVsbCxcbiAgICAgIDApO1xuXG4gICAgYXR0YWNoKEdMX0RFUFRIX0FUVEFDSE1FTlQsIGZyYW1lYnVmZmVyLmRlcHRoQXR0YWNobWVudCk7XG4gICAgYXR0YWNoKEdMX1NURU5DSUxfQVRUQUNITUVOVCwgZnJhbWVidWZmZXIuc3RlbmNpbEF0dGFjaG1lbnQpO1xuICAgIGF0dGFjaChHTF9ERVBUSF9TVEVOQ0lMX0FUVEFDSE1FTlQsIGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQpO1xuXG4gICAgLy8gQ2hlY2sgc3RhdHVzIGNvZGVcbiAgICB2YXIgc3RhdHVzID0gZ2wuY2hlY2tGcmFtZWJ1ZmZlclN0YXR1cyhHTF9GUkFNRUJVRkZFUiQxKTtcbiAgICBpZiAoc3RhdHVzICE9PSBHTF9GUkFNRUJVRkZFUl9DT01QTEVURSQxKSB7XG4gICAgICBjaGVjayQxLnJhaXNlKCdmcmFtZWJ1ZmZlciBjb25maWd1cmF0aW9uIG5vdCBzdXBwb3J0ZWQsIHN0YXR1cyA9ICcgK1xuICAgICAgICBzdGF0dXNDb2RlW3N0YXR1c10pO1xuICAgIH1cblxuXG4gICAgZ2wuYmluZEZyYW1lYnVmZmVyKEdMX0ZSQU1FQlVGRkVSJDEsIGZyYW1lYnVmZmVyU3RhdGUubmV4dCA/IGZyYW1lYnVmZmVyU3RhdGUubmV4dC5mcmFtZWJ1ZmZlciA6IG51bGwpO1xuICAgIGZyYW1lYnVmZmVyU3RhdGUuY3VyID0gZnJhbWVidWZmZXJTdGF0ZS5uZXh0O1xuXG4gICAgLy8gRklYTUU6IENsZWFyIGVycm9yIGNvZGUgaGVyZS4gIFRoaXMgaXMgYSB3b3JrIGFyb3VuZCBmb3IgYSBidWcgaW5cbiAgICAvLyBoZWFkbGVzcy1nbFxuICAgIGdsLmdldEVycm9yKCk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVGQk8gKGEwLCBhMSkge1xuICAgIHZhciBmcmFtZWJ1ZmZlciA9IG5ldyBSRUdMRnJhbWVidWZmZXIoKTtcbiAgICBzdGF0cy5mcmFtZWJ1ZmZlckNvdW50Kys7XG5cbiAgICBmdW5jdGlvbiByZWdsRnJhbWVidWZmZXIgKGEsIGIpIHtcbiAgICAgIHZhciBpO1xuXG4gICAgICBjaGVjayQxKGZyYW1lYnVmZmVyU3RhdGUubmV4dCAhPT0gZnJhbWVidWZmZXIsXG4gICAgICAgICdjYW4gbm90IHVwZGF0ZSBmcmFtZWJ1ZmZlciB3aGljaCBpcyBjdXJyZW50bHkgaW4gdXNlJyk7XG5cbiAgICAgIHZhciBleHREcmF3QnVmZmVycyA9IGV4dGVuc2lvbnMud2ViZ2xfZHJhd19idWZmZXJzO1xuXG4gICAgICB2YXIgd2lkdGggPSAwO1xuICAgICAgdmFyIGhlaWdodCA9IDA7XG5cbiAgICAgIHZhciBuZWVkc0RlcHRoID0gdHJ1ZTtcbiAgICAgIHZhciBuZWVkc1N0ZW5jaWwgPSB0cnVlO1xuXG4gICAgICB2YXIgY29sb3JCdWZmZXIgPSBudWxsO1xuICAgICAgdmFyIGNvbG9yVGV4dHVyZSA9IHRydWU7XG4gICAgICB2YXIgY29sb3JGb3JtYXQgPSAncmdiYSc7XG4gICAgICB2YXIgY29sb3JUeXBlID0gJ3VpbnQ4JztcbiAgICAgIHZhciBjb2xvckNvdW50ID0gMTtcblxuICAgICAgdmFyIGRlcHRoQnVmZmVyID0gbnVsbDtcbiAgICAgIHZhciBzdGVuY2lsQnVmZmVyID0gbnVsbDtcbiAgICAgIHZhciBkZXB0aFN0ZW5jaWxCdWZmZXIgPSBudWxsO1xuICAgICAgdmFyIGRlcHRoU3RlbmNpbFRleHR1cmUgPSBmYWxzZTtcblxuICAgICAgaWYgKHR5cGVvZiBhID09PSAnbnVtYmVyJykge1xuICAgICAgICB3aWR0aCA9IGEgfCAwO1xuICAgICAgICBoZWlnaHQgPSAoYiB8IDApIHx8IHdpZHRoO1xuICAgICAgfSBlbHNlIGlmICghYSkge1xuICAgICAgICB3aWR0aCA9IGhlaWdodCA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVjayQxLnR5cGUoYSwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyBmb3IgZnJhbWVidWZmZXInKTtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBhO1xuXG4gICAgICAgIGlmICgnc2hhcGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgc2hhcGUgPSBvcHRpb25zLnNoYXBlO1xuICAgICAgICAgIGNoZWNrJDEoQXJyYXkuaXNBcnJheShzaGFwZSkgJiYgc2hhcGUubGVuZ3RoID49IDIsXG4gICAgICAgICAgICAnaW52YWxpZCBzaGFwZSBmb3IgZnJhbWVidWZmZXInKTtcbiAgICAgICAgICB3aWR0aCA9IHNoYXBlWzBdO1xuICAgICAgICAgIGhlaWdodCA9IHNoYXBlWzFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICgncmFkaXVzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB3aWR0aCA9IGhlaWdodCA9IG9wdGlvbnMucmFkaXVzO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoJ3dpZHRoJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB3aWR0aCA9IG9wdGlvbnMud2lkdGg7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnaGVpZ2h0JyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBoZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2NvbG9yJyBpbiBvcHRpb25zIHx8XG4gICAgICAgICAgICAnY29sb3JzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgY29sb3JCdWZmZXIgPVxuICAgICAgICAgICAgb3B0aW9ucy5jb2xvciB8fFxuICAgICAgICAgICAgb3B0aW9ucy5jb2xvcnM7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3JCdWZmZXIpKSB7XG4gICAgICAgICAgICBjaGVjayQxKFxuICAgICAgICAgICAgICBjb2xvckJ1ZmZlci5sZW5ndGggPT09IDEgfHwgZXh0RHJhd0J1ZmZlcnMsXG4gICAgICAgICAgICAgICdtdWx0aXBsZSByZW5kZXIgdGFyZ2V0cyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjb2xvckJ1ZmZlcikge1xuICAgICAgICAgIGlmICgnY29sb3JDb3VudCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY29sb3JDb3VudCA9IG9wdGlvbnMuY29sb3JDb3VudCB8IDA7XG4gICAgICAgICAgICBjaGVjayQxKGNvbG9yQ291bnQgPiAwLCAnaW52YWxpZCBjb2xvciBidWZmZXIgY291bnQnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJ2NvbG9yVGV4dHVyZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY29sb3JUZXh0dXJlID0gISFvcHRpb25zLmNvbG9yVGV4dHVyZTtcbiAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gJ3JnYmE0JztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJ2NvbG9yVHlwZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY29sb3JUeXBlID0gb3B0aW9ucy5jb2xvclR5cGU7XG4gICAgICAgICAgICBpZiAoIWNvbG9yVGV4dHVyZSkge1xuICAgICAgICAgICAgICBpZiAoY29sb3JUeXBlID09PSAnaGFsZiBmbG9hdCcgfHwgY29sb3JUeXBlID09PSAnZmxvYXQxNicpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxKGV4dGVuc2lvbnMuZXh0X2NvbG9yX2J1ZmZlcl9oYWxmX2Zsb2F0LFxuICAgICAgICAgICAgICAgICAgJ3lvdSBtdXN0IGVuYWJsZSBFWFRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQgdG8gdXNlIDE2LWJpdCByZW5kZXIgYnVmZmVycycpO1xuICAgICAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gJ3JnYmExNmYnO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvbG9yVHlwZSA9PT0gJ2Zsb2F0JyB8fCBjb2xvclR5cGUgPT09ICdmbG9hdDMyJykge1xuICAgICAgICAgICAgICAgIGNoZWNrJDEoZXh0ZW5zaW9ucy53ZWJnbF9jb2xvcl9idWZmZXJfZmxvYXQsXG4gICAgICAgICAgICAgICAgICAneW91IG11c3QgZW5hYmxlIFdFQkdMX2NvbG9yX2J1ZmZlcl9mbG9hdCBpbiBvcmRlciB0byB1c2UgMzItYml0IGZsb2F0aW5nIHBvaW50IHJlbmRlcmJ1ZmZlcnMnKTtcbiAgICAgICAgICAgICAgICBjb2xvckZvcm1hdCA9ICdyZ2JhMzJmJztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0IHx8XG4gICAgICAgICAgICAgICAgIShjb2xvclR5cGUgPT09ICdmbG9hdCcgfHwgY29sb3JUeXBlID09PSAnZmxvYXQzMicpLFxuICAgICAgICAgICAgICAgICd5b3UgbXVzdCBlbmFibGUgT0VTX3RleHR1cmVfZmxvYXQgaW4gb3JkZXIgdG8gdXNlIGZsb2F0aW5nIHBvaW50IGZyYW1lYnVmZmVyIG9iamVjdHMnKTtcbiAgICAgICAgICAgICAgY2hlY2skMShleHRlbnNpb25zLm9lc190ZXh0dXJlX2hhbGZfZmxvYXQgfHxcbiAgICAgICAgICAgICAgICAhKGNvbG9yVHlwZSA9PT0gJ2hhbGYgZmxvYXQnIHx8IGNvbG9yVHlwZSA9PT0gJ2Zsb2F0MTYnKSxcbiAgICAgICAgICAgICAgICAneW91IG11c3QgZW5hYmxlIE9FU190ZXh0dXJlX2hhbGZfZmxvYXQgaW4gb3JkZXIgdG8gdXNlIDE2LWJpdCBmbG9hdGluZyBwb2ludCBmcmFtZWJ1ZmZlciBvYmplY3RzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGVjayQxLm9uZU9mKGNvbG9yVHlwZSwgY29sb3JUeXBlcywgJ2ludmFsaWQgY29sb3IgdHlwZScpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICgnY29sb3JGb3JtYXQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gb3B0aW9ucy5jb2xvckZvcm1hdDtcbiAgICAgICAgICAgIGlmIChjb2xvclRleHR1cmVGb3JtYXRzLmluZGV4T2YoY29sb3JGb3JtYXQpID49IDApIHtcbiAgICAgICAgICAgICAgY29sb3JUZXh0dXJlID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLmluZGV4T2YoY29sb3JGb3JtYXQpID49IDApIHtcbiAgICAgICAgICAgICAgY29sb3JUZXh0dXJlID0gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoY29sb3JUZXh0dXJlKSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5vbmVPZihcbiAgICAgICAgICAgICAgICAgIG9wdGlvbnMuY29sb3JGb3JtYXQsIGNvbG9yVGV4dHVyZUZvcm1hdHMsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCBjb2xvciBmb3JtYXQgZm9yIHRleHR1cmUnKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLm9uZU9mKFxuICAgICAgICAgICAgICAgICAgb3B0aW9ucy5jb2xvckZvcm1hdCwgY29sb3JSZW5kZXJidWZmZXJGb3JtYXRzLFxuICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgY29sb3IgZm9ybWF0IGZvciByZW5kZXJidWZmZXInKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnZGVwdGhUZXh0dXJlJyBpbiBvcHRpb25zIHx8ICdkZXB0aFN0ZW5jaWxUZXh0dXJlJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgZGVwdGhTdGVuY2lsVGV4dHVyZSA9ICEhKG9wdGlvbnMuZGVwdGhUZXh0dXJlIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRlcHRoU3RlbmNpbFRleHR1cmUpO1xuICAgICAgICAgIGNoZWNrJDEoIWRlcHRoU3RlbmNpbFRleHR1cmUgfHwgZXh0ZW5zaW9ucy53ZWJnbF9kZXB0aF90ZXh0dXJlLFxuICAgICAgICAgICAgJ3dlYmdsX2RlcHRoX3RleHR1cmUgZXh0ZW5zaW9uIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnZGVwdGgnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuZGVwdGggPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgbmVlZHNEZXB0aCA9IG9wdGlvbnMuZGVwdGg7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlcHRoQnVmZmVyID0gb3B0aW9ucy5kZXB0aDtcbiAgICAgICAgICAgIG5lZWRzU3RlbmNpbCA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnc3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zdGVuY2lsID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIG5lZWRzU3RlbmNpbCA9IG9wdGlvbnMuc3RlbmNpbDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RlbmNpbEJ1ZmZlciA9IG9wdGlvbnMuc3RlbmNpbDtcbiAgICAgICAgICAgIG5lZWRzRGVwdGggPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2RlcHRoU3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kZXB0aFN0ZW5jaWwgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgbmVlZHNEZXB0aCA9IG5lZWRzU3RlbmNpbCA9IG9wdGlvbnMuZGVwdGhTdGVuY2lsO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZXB0aFN0ZW5jaWxCdWZmZXIgPSBvcHRpb25zLmRlcHRoU3RlbmNpbDtcbiAgICAgICAgICAgIG5lZWRzRGVwdGggPSBmYWxzZTtcbiAgICAgICAgICAgIG5lZWRzU3RlbmNpbCA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBwYXJzZSBhdHRhY2htZW50c1xuICAgICAgdmFyIGNvbG9yQXR0YWNobWVudHMgPSBudWxsO1xuICAgICAgdmFyIGRlcHRoQXR0YWNobWVudCA9IG51bGw7XG4gICAgICB2YXIgc3RlbmNpbEF0dGFjaG1lbnQgPSBudWxsO1xuICAgICAgdmFyIGRlcHRoU3RlbmNpbEF0dGFjaG1lbnQgPSBudWxsO1xuXG4gICAgICAvLyBTZXQgdXAgY29sb3IgYXR0YWNobWVudHNcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9yQnVmZmVyKSkge1xuICAgICAgICBjb2xvckF0dGFjaG1lbnRzID0gY29sb3JCdWZmZXIubWFwKHBhcnNlQXR0YWNobWVudCk7XG4gICAgICB9IGVsc2UgaWYgKGNvbG9yQnVmZmVyKSB7XG4gICAgICAgIGNvbG9yQXR0YWNobWVudHMgPSBbcGFyc2VBdHRhY2htZW50KGNvbG9yQnVmZmVyKV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2xvckF0dGFjaG1lbnRzID0gbmV3IEFycmF5KGNvbG9yQ291bnQpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29sb3JDb3VudDsgKytpKSB7XG4gICAgICAgICAgY29sb3JBdHRhY2htZW50c1tpXSA9IGFsbG9jQXR0YWNobWVudChcbiAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgICAgY29sb3JUZXh0dXJlLFxuICAgICAgICAgICAgY29sb3JGb3JtYXQsXG4gICAgICAgICAgICBjb2xvclR5cGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNoZWNrJDEoZXh0ZW5zaW9ucy53ZWJnbF9kcmF3X2J1ZmZlcnMgfHwgY29sb3JBdHRhY2htZW50cy5sZW5ndGggPD0gMSxcbiAgICAgICAgJ3lvdSBtdXN0IGVuYWJsZSB0aGUgV0VCR0xfZHJhd19idWZmZXJzIGV4dGVuc2lvbiBpbiBvcmRlciB0byB1c2UgbXVsdGlwbGUgY29sb3IgYnVmZmVycy4nKTtcbiAgICAgIGNoZWNrJDEoY29sb3JBdHRhY2htZW50cy5sZW5ndGggPD0gbGltaXRzLm1heENvbG9yQXR0YWNobWVudHMsXG4gICAgICAgICd0b28gbWFueSBjb2xvciBhdHRhY2htZW50cywgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgICB3aWR0aCA9IHdpZHRoIHx8IGNvbG9yQXR0YWNobWVudHNbMF0ud2lkdGg7XG4gICAgICBoZWlnaHQgPSBoZWlnaHQgfHwgY29sb3JBdHRhY2htZW50c1swXS5oZWlnaHQ7XG5cbiAgICAgIGlmIChkZXB0aEJ1ZmZlcikge1xuICAgICAgICBkZXB0aEF0dGFjaG1lbnQgPSBwYXJzZUF0dGFjaG1lbnQoZGVwdGhCdWZmZXIpO1xuICAgICAgfSBlbHNlIGlmIChuZWVkc0RlcHRoICYmICFuZWVkc1N0ZW5jaWwpIHtcbiAgICAgICAgZGVwdGhBdHRhY2htZW50ID0gYWxsb2NBdHRhY2htZW50KFxuICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICBkZXB0aFN0ZW5jaWxUZXh0dXJlLFxuICAgICAgICAgICdkZXB0aCcsXG4gICAgICAgICAgJ3VpbnQzMicpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3RlbmNpbEJ1ZmZlcikge1xuICAgICAgICBzdGVuY2lsQXR0YWNobWVudCA9IHBhcnNlQXR0YWNobWVudChzdGVuY2lsQnVmZmVyKTtcbiAgICAgIH0gZWxzZSBpZiAobmVlZHNTdGVuY2lsICYmICFuZWVkc0RlcHRoKSB7XG4gICAgICAgIHN0ZW5jaWxBdHRhY2htZW50ID0gYWxsb2NBdHRhY2htZW50KFxuICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAnc3RlbmNpbCcsXG4gICAgICAgICAgJ3VpbnQ4Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChkZXB0aFN0ZW5jaWxCdWZmZXIpIHtcbiAgICAgICAgZGVwdGhTdGVuY2lsQXR0YWNobWVudCA9IHBhcnNlQXR0YWNobWVudChkZXB0aFN0ZW5jaWxCdWZmZXIpO1xuICAgICAgfSBlbHNlIGlmICghZGVwdGhCdWZmZXIgJiYgIXN0ZW5jaWxCdWZmZXIgJiYgbmVlZHNTdGVuY2lsICYmIG5lZWRzRGVwdGgpIHtcbiAgICAgICAgZGVwdGhTdGVuY2lsQXR0YWNobWVudCA9IGFsbG9jQXR0YWNobWVudChcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgZGVwdGhTdGVuY2lsVGV4dHVyZSxcbiAgICAgICAgICAnZGVwdGggc3RlbmNpbCcsXG4gICAgICAgICAgJ2RlcHRoIHN0ZW5jaWwnKTtcbiAgICAgIH1cblxuICAgICAgY2hlY2skMShcbiAgICAgICAgKCEhZGVwdGhCdWZmZXIpICsgKCEhc3RlbmNpbEJ1ZmZlcikgKyAoISFkZXB0aFN0ZW5jaWxCdWZmZXIpIDw9IDEsXG4gICAgICAgICdpbnZhbGlkIGZyYW1lYnVmZmVyIGNvbmZpZ3VyYXRpb24sIGNhbiBzcGVjaWZ5IGV4YWN0bHkgb25lIGRlcHRoL3N0ZW5jaWwgYXR0YWNobWVudCcpO1xuXG4gICAgICB2YXIgY29tbW9uQ29sb3JBdHRhY2htZW50U2l6ZSA9IG51bGw7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2xvckF0dGFjaG1lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGluY1JlZkFuZENoZWNrU2hhcGUoY29sb3JBdHRhY2htZW50c1tpXSwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGNoZWNrJDEoIWNvbG9yQXR0YWNobWVudHNbaV0gfHxcbiAgICAgICAgICAoY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlICYmXG4gICAgICAgICAgICBjb2xvclRleHR1cmVGb3JtYXRFbnVtcy5pbmRleE9mKGNvbG9yQXR0YWNobWVudHNbaV0udGV4dHVyZS5fdGV4dHVyZS5mb3JtYXQpID49IDApIHx8XG4gICAgICAgICAgKGNvbG9yQXR0YWNobWVudHNbaV0ucmVuZGVyYnVmZmVyICYmXG4gICAgICAgICAgICBjb2xvclJlbmRlcmJ1ZmZlckZvcm1hdEVudW1zLmluZGV4T2YoY29sb3JBdHRhY2htZW50c1tpXS5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5mb3JtYXQpID49IDApLFxuICAgICAgICAgICdmcmFtZWJ1ZmZlciBjb2xvciBhdHRhY2htZW50ICcgKyBpICsgJyBpcyBpbnZhbGlkJyk7XG5cbiAgICAgICAgaWYgKGNvbG9yQXR0YWNobWVudHNbaV0gJiYgY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlKSB7XG4gICAgICAgICAgdmFyIGNvbG9yQXR0YWNobWVudFNpemUgPVxuICAgICAgICAgICAgICB0ZXh0dXJlRm9ybWF0Q2hhbm5lbHNbY29sb3JBdHRhY2htZW50c1tpXS50ZXh0dXJlLl90ZXh0dXJlLmZvcm1hdF0gKlxuICAgICAgICAgICAgICB0ZXh0dXJlVHlwZVNpemVzW2NvbG9yQXR0YWNobWVudHNbaV0udGV4dHVyZS5fdGV4dHVyZS50eXBlXTtcblxuICAgICAgICAgIGlmIChjb21tb25Db2xvckF0dGFjaG1lbnRTaXplID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb21tb25Db2xvckF0dGFjaG1lbnRTaXplID0gY29sb3JBdHRhY2htZW50U2l6ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBtYWtlIHN1cmUgdGhhdCBhbGwgY29sb3IgYXR0YWNobWVudHMgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgYml0cGxhbmVzXG4gICAgICAgICAgICAvLyAodGhhdCBpcywgdGhlIHNhbWUgbnVtZXIgb2YgYml0cyBwZXIgcGl4ZWwpXG4gICAgICAgICAgICAvLyBUaGlzIGlzIHJlcXVpcmVkIGJ5IHRoZSBHTEVTMi4wIHN0YW5kYXJkLiBTZWUgdGhlIGJlZ2lubmluZyBvZiBDaGFwdGVyIDQgaW4gdGhhdCBkb2N1bWVudC5cbiAgICAgICAgICAgIGNoZWNrJDEoY29tbW9uQ29sb3JBdHRhY2htZW50U2l6ZSA9PT0gY29sb3JBdHRhY2htZW50U2l6ZSxcbiAgICAgICAgICAgICAgICAgICdhbGwgY29sb3IgYXR0YWNobWVudHMgbXVjaCBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBiaXRzIHBlciBwaXhlbC4nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGluY1JlZkFuZENoZWNrU2hhcGUoZGVwdGhBdHRhY2htZW50LCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIGNoZWNrJDEoIWRlcHRoQXR0YWNobWVudCB8fFxuICAgICAgICAoZGVwdGhBdHRhY2htZW50LnRleHR1cmUgJiZcbiAgICAgICAgICBkZXB0aEF0dGFjaG1lbnQudGV4dHVyZS5fdGV4dHVyZS5mb3JtYXQgPT09IEdMX0RFUFRIX0NPTVBPTkVOVCQxKSB8fFxuICAgICAgICAoZGVwdGhBdHRhY2htZW50LnJlbmRlcmJ1ZmZlciAmJlxuICAgICAgICAgIGRlcHRoQXR0YWNobWVudC5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5mb3JtYXQgPT09IEdMX0RFUFRIX0NPTVBPTkVOVDE2JDEpLFxuICAgICAgICAnaW52YWxpZCBkZXB0aCBhdHRhY2htZW50IGZvciBmcmFtZWJ1ZmZlciBvYmplY3QnKTtcbiAgICAgIGluY1JlZkFuZENoZWNrU2hhcGUoc3RlbmNpbEF0dGFjaG1lbnQsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgY2hlY2skMSghc3RlbmNpbEF0dGFjaG1lbnQgfHxcbiAgICAgICAgKHN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlciAmJlxuICAgICAgICAgIHN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLmZvcm1hdCA9PT0gR0xfU1RFTkNJTF9JTkRFWDgkMSksXG4gICAgICAgICdpbnZhbGlkIHN0ZW5jaWwgYXR0YWNobWVudCBmb3IgZnJhbWVidWZmZXIgb2JqZWN0Jyk7XG4gICAgICBpbmNSZWZBbmRDaGVja1NoYXBlKGRlcHRoU3RlbmNpbEF0dGFjaG1lbnQsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgY2hlY2skMSghZGVwdGhTdGVuY2lsQXR0YWNobWVudCB8fFxuICAgICAgICAoZGVwdGhTdGVuY2lsQXR0YWNobWVudC50ZXh0dXJlICYmXG4gICAgICAgICAgZGVwdGhTdGVuY2lsQXR0YWNobWVudC50ZXh0dXJlLl90ZXh0dXJlLmZvcm1hdCA9PT0gR0xfREVQVEhfU1RFTkNJTCQyKSB8fFxuICAgICAgICAoZGVwdGhTdGVuY2lsQXR0YWNobWVudC5yZW5kZXJidWZmZXIgJiZcbiAgICAgICAgICBkZXB0aFN0ZW5jaWxBdHRhY2htZW50LnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLmZvcm1hdCA9PT0gR0xfREVQVEhfU1RFTkNJTCQyKSxcbiAgICAgICAgJ2ludmFsaWQgZGVwdGgtc3RlbmNpbCBhdHRhY2htZW50IGZvciBmcmFtZWJ1ZmZlciBvYmplY3QnKTtcblxuICAgICAgLy8gZGVjcmVtZW50IHJlZmVyZW5jZXNcbiAgICAgIGRlY0ZCT1JlZnMoZnJhbWVidWZmZXIpO1xuXG4gICAgICBmcmFtZWJ1ZmZlci53aWR0aCA9IHdpZHRoO1xuICAgICAgZnJhbWVidWZmZXIuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICBmcmFtZWJ1ZmZlci5jb2xvckF0dGFjaG1lbnRzID0gY29sb3JBdHRhY2htZW50cztcbiAgICAgIGZyYW1lYnVmZmVyLmRlcHRoQXR0YWNobWVudCA9IGRlcHRoQXR0YWNobWVudDtcbiAgICAgIGZyYW1lYnVmZmVyLnN0ZW5jaWxBdHRhY2htZW50ID0gc3RlbmNpbEF0dGFjaG1lbnQ7XG4gICAgICBmcmFtZWJ1ZmZlci5kZXB0aFN0ZW5jaWxBdHRhY2htZW50ID0gZGVwdGhTdGVuY2lsQXR0YWNobWVudDtcblxuICAgICAgcmVnbEZyYW1lYnVmZmVyLmNvbG9yID0gY29sb3JBdHRhY2htZW50cy5tYXAodW53cmFwQXR0YWNobWVudCk7XG4gICAgICByZWdsRnJhbWVidWZmZXIuZGVwdGggPSB1bndyYXBBdHRhY2htZW50KGRlcHRoQXR0YWNobWVudCk7XG4gICAgICByZWdsRnJhbWVidWZmZXIuc3RlbmNpbCA9IHVud3JhcEF0dGFjaG1lbnQoc3RlbmNpbEF0dGFjaG1lbnQpO1xuICAgICAgcmVnbEZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbCA9IHVud3JhcEF0dGFjaG1lbnQoZGVwdGhTdGVuY2lsQXR0YWNobWVudCk7XG5cbiAgICAgIHJlZ2xGcmFtZWJ1ZmZlci53aWR0aCA9IGZyYW1lYnVmZmVyLndpZHRoO1xuICAgICAgcmVnbEZyYW1lYnVmZmVyLmhlaWdodCA9IGZyYW1lYnVmZmVyLmhlaWdodDtcblxuICAgICAgdXBkYXRlRnJhbWVidWZmZXIoZnJhbWVidWZmZXIpO1xuXG4gICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzaXplICh3XywgaF8pIHtcbiAgICAgIGNoZWNrJDEoZnJhbWVidWZmZXJTdGF0ZS5uZXh0ICE9PSBmcmFtZWJ1ZmZlcixcbiAgICAgICAgJ2NhbiBub3QgcmVzaXplIGEgZnJhbWVidWZmZXIgd2hpY2ggaXMgY3VycmVudGx5IGluIHVzZScpO1xuXG4gICAgICB2YXIgdyA9IHdfIHwgMDtcbiAgICAgIHZhciBoID0gKGhfIHwgMCkgfHwgdztcbiAgICAgIGlmICh3ID09PSBmcmFtZWJ1ZmZlci53aWR0aCAmJiBoID09PSBmcmFtZWJ1ZmZlci5oZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2xGcmFtZWJ1ZmZlclxuICAgICAgfVxuXG4gICAgICAvLyByZXNpemUgYWxsIGJ1ZmZlcnNcbiAgICAgIHZhciBjb2xvckF0dGFjaG1lbnRzID0gZnJhbWVidWZmZXIuY29sb3JBdHRhY2htZW50cztcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29sb3JBdHRhY2htZW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgICByZXNpemVBdHRhY2htZW50KGNvbG9yQXR0YWNobWVudHNbaV0sIHcsIGgpO1xuICAgICAgfVxuICAgICAgcmVzaXplQXR0YWNobWVudChmcmFtZWJ1ZmZlci5kZXB0aEF0dGFjaG1lbnQsIHcsIGgpO1xuICAgICAgcmVzaXplQXR0YWNobWVudChmcmFtZWJ1ZmZlci5zdGVuY2lsQXR0YWNobWVudCwgdywgaCk7XG4gICAgICByZXNpemVBdHRhY2htZW50KGZyYW1lYnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQsIHcsIGgpO1xuXG4gICAgICBmcmFtZWJ1ZmZlci53aWR0aCA9IHJlZ2xGcmFtZWJ1ZmZlci53aWR0aCA9IHc7XG4gICAgICBmcmFtZWJ1ZmZlci5oZWlnaHQgPSByZWdsRnJhbWVidWZmZXIuaGVpZ2h0ID0gaDtcblxuICAgICAgdXBkYXRlRnJhbWVidWZmZXIoZnJhbWVidWZmZXIpO1xuXG4gICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyXG4gICAgfVxuXG4gICAgcmVnbEZyYW1lYnVmZmVyKGEwLCBhMSk7XG5cbiAgICByZXR1cm4gZXh0ZW5kKHJlZ2xGcmFtZWJ1ZmZlciwge1xuICAgICAgcmVzaXplOiByZXNpemUsXG4gICAgICBfcmVnbFR5cGU6ICdmcmFtZWJ1ZmZlcicsXG4gICAgICBfZnJhbWVidWZmZXI6IGZyYW1lYnVmZmVyLFxuICAgICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xuICAgICAgICBkZXN0cm95KGZyYW1lYnVmZmVyKTtcbiAgICAgICAgZGVjRkJPUmVmcyhmcmFtZWJ1ZmZlcik7XG4gICAgICB9LFxuICAgICAgdXNlOiBmdW5jdGlvbiAoYmxvY2spIHtcbiAgICAgICAgZnJhbWVidWZmZXJTdGF0ZS5zZXRGQk8oe1xuICAgICAgICAgIGZyYW1lYnVmZmVyOiByZWdsRnJhbWVidWZmZXJcbiAgICAgICAgfSwgYmxvY2spO1xuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVDdWJlRkJPIChvcHRpb25zKSB7XG4gICAgdmFyIGZhY2VzID0gQXJyYXkoNik7XG5cbiAgICBmdW5jdGlvbiByZWdsRnJhbWVidWZmZXJDdWJlIChhKSB7XG4gICAgICB2YXIgaTtcblxuICAgICAgY2hlY2skMShmYWNlcy5pbmRleE9mKGZyYW1lYnVmZmVyU3RhdGUubmV4dCkgPCAwLFxuICAgICAgICAnY2FuIG5vdCB1cGRhdGUgZnJhbWVidWZmZXIgd2hpY2ggaXMgY3VycmVudGx5IGluIHVzZScpO1xuXG4gICAgICB2YXIgZXh0RHJhd0J1ZmZlcnMgPSBleHRlbnNpb25zLndlYmdsX2RyYXdfYnVmZmVycztcblxuICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgY29sb3I6IG51bGxcbiAgICAgIH07XG5cbiAgICAgIHZhciByYWRpdXMgPSAwO1xuXG4gICAgICB2YXIgY29sb3JCdWZmZXIgPSBudWxsO1xuICAgICAgdmFyIGNvbG9yRm9ybWF0ID0gJ3JnYmEnO1xuICAgICAgdmFyIGNvbG9yVHlwZSA9ICd1aW50OCc7XG4gICAgICB2YXIgY29sb3JDb3VudCA9IDE7XG5cbiAgICAgIGlmICh0eXBlb2YgYSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmFkaXVzID0gYSB8IDA7XG4gICAgICB9IGVsc2UgaWYgKCFhKSB7XG4gICAgICAgIHJhZGl1cyA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVjayQxLnR5cGUoYSwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyBmb3IgZnJhbWVidWZmZXInKTtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBhO1xuXG4gICAgICAgIGlmICgnc2hhcGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgc2hhcGUgPSBvcHRpb25zLnNoYXBlO1xuICAgICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgICBBcnJheS5pc0FycmF5KHNoYXBlKSAmJiBzaGFwZS5sZW5ndGggPj0gMixcbiAgICAgICAgICAgICdpbnZhbGlkIHNoYXBlIGZvciBmcmFtZWJ1ZmZlcicpO1xuICAgICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgICBzaGFwZVswXSA9PT0gc2hhcGVbMV0sXG4gICAgICAgICAgICAnY3ViZSBmcmFtZWJ1ZmZlciBtdXN0IGJlIHNxdWFyZScpO1xuICAgICAgICAgIHJhZGl1cyA9IHNoYXBlWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICgncmFkaXVzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICByYWRpdXMgPSBvcHRpb25zLnJhZGl1cyB8IDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgnd2lkdGgnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJhZGl1cyA9IG9wdGlvbnMud2lkdGggfCAwO1xuICAgICAgICAgICAgaWYgKCdoZWlnaHQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgY2hlY2skMShvcHRpb25zLmhlaWdodCA9PT0gcmFkaXVzLCAnbXVzdCBiZSBzcXVhcmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKCdoZWlnaHQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJhZGl1cyA9IG9wdGlvbnMuaGVpZ2h0IHwgMDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2NvbG9yJyBpbiBvcHRpb25zIHx8XG4gICAgICAgICAgICAnY29sb3JzJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgY29sb3JCdWZmZXIgPVxuICAgICAgICAgICAgb3B0aW9ucy5jb2xvciB8fFxuICAgICAgICAgICAgb3B0aW9ucy5jb2xvcnM7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3JCdWZmZXIpKSB7XG4gICAgICAgICAgICBjaGVjayQxKFxuICAgICAgICAgICAgICBjb2xvckJ1ZmZlci5sZW5ndGggPT09IDEgfHwgZXh0RHJhd0J1ZmZlcnMsXG4gICAgICAgICAgICAgICdtdWx0aXBsZSByZW5kZXIgdGFyZ2V0cyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjb2xvckJ1ZmZlcikge1xuICAgICAgICAgIGlmICgnY29sb3JDb3VudCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY29sb3JDb3VudCA9IG9wdGlvbnMuY29sb3JDb3VudCB8IDA7XG4gICAgICAgICAgICBjaGVjayQxKGNvbG9yQ291bnQgPiAwLCAnaW52YWxpZCBjb2xvciBidWZmZXIgY291bnQnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJ2NvbG9yVHlwZScgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgY2hlY2skMS5vbmVPZihcbiAgICAgICAgICAgICAgb3B0aW9ucy5jb2xvclR5cGUsIGNvbG9yVHlwZXMsXG4gICAgICAgICAgICAgICdpbnZhbGlkIGNvbG9yIHR5cGUnKTtcbiAgICAgICAgICAgIGNvbG9yVHlwZSA9IG9wdGlvbnMuY29sb3JUeXBlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICgnY29sb3JGb3JtYXQnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbG9yRm9ybWF0ID0gb3B0aW9ucy5jb2xvckZvcm1hdDtcbiAgICAgICAgICAgIGNoZWNrJDEub25lT2YoXG4gICAgICAgICAgICAgIG9wdGlvbnMuY29sb3JGb3JtYXQsIGNvbG9yVGV4dHVyZUZvcm1hdHMsXG4gICAgICAgICAgICAgICdpbnZhbGlkIGNvbG9yIGZvcm1hdCBmb3IgdGV4dHVyZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnZGVwdGgnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICBwYXJhbXMuZGVwdGggPSBvcHRpb25zLmRlcHRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCdzdGVuY2lsJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgcGFyYW1zLnN0ZW5jaWwgPSBvcHRpb25zLnN0ZW5jaWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2RlcHRoU3RlbmNpbCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgIHBhcmFtcy5kZXB0aFN0ZW5jaWwgPSBvcHRpb25zLmRlcHRoU3RlbmNpbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgY29sb3JDdWJlcztcbiAgICAgIGlmIChjb2xvckJ1ZmZlcikge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xvckJ1ZmZlcikpIHtcbiAgICAgICAgICBjb2xvckN1YmVzID0gW107XG4gICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQnVmZmVyLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBjb2xvckN1YmVzW2ldID0gY29sb3JCdWZmZXJbaV07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbG9yQ3ViZXMgPSBbIGNvbG9yQnVmZmVyIF07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbG9yQ3ViZXMgPSBBcnJheShjb2xvckNvdW50KTtcbiAgICAgICAgdmFyIGN1YmVNYXBQYXJhbXMgPSB7XG4gICAgICAgICAgcmFkaXVzOiByYWRpdXMsXG4gICAgICAgICAgZm9ybWF0OiBjb2xvckZvcm1hdCxcbiAgICAgICAgICB0eXBlOiBjb2xvclR5cGVcbiAgICAgICAgfTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQ291bnQ7ICsraSkge1xuICAgICAgICAgIGNvbG9yQ3ViZXNbaV0gPSB0ZXh0dXJlU3RhdGUuY3JlYXRlQ3ViZShjdWJlTWFwUGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBjb2xvciBjdWJlc1xuICAgICAgcGFyYW1zLmNvbG9yID0gQXJyYXkoY29sb3JDdWJlcy5sZW5ndGgpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yQ3ViZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGN1YmUgPSBjb2xvckN1YmVzW2ldO1xuICAgICAgICBjaGVjayQxKFxuICAgICAgICAgIHR5cGVvZiBjdWJlID09PSAnZnVuY3Rpb24nICYmIGN1YmUuX3JlZ2xUeXBlID09PSAndGV4dHVyZUN1YmUnLFxuICAgICAgICAgICdpbnZhbGlkIGN1YmUgbWFwJyk7XG4gICAgICAgIHJhZGl1cyA9IHJhZGl1cyB8fCBjdWJlLndpZHRoO1xuICAgICAgICBjaGVjayQxKFxuICAgICAgICAgIGN1YmUud2lkdGggPT09IHJhZGl1cyAmJiBjdWJlLmhlaWdodCA9PT0gcmFkaXVzLFxuICAgICAgICAgICdpbnZhbGlkIGN1YmUgbWFwIHNoYXBlJyk7XG4gICAgICAgIHBhcmFtcy5jb2xvcltpXSA9IHtcbiAgICAgICAgICB0YXJnZXQ6IEdMX1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCQyLFxuICAgICAgICAgIGRhdGE6IGNvbG9yQ3ViZXNbaV1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgZm9yIChpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNvbG9yQ3ViZXMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICBwYXJhbXMuY29sb3Jbal0udGFyZ2V0ID0gR0xfVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9YJDIgKyBpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJldXNlIGRlcHRoLXN0ZW5jaWwgYXR0YWNobWVudHMgYWNyb3NzIGFsbCBjdWJlIG1hcHNcbiAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgcGFyYW1zLmRlcHRoID0gZmFjZXNbMF0uZGVwdGg7XG4gICAgICAgICAgcGFyYW1zLnN0ZW5jaWwgPSBmYWNlc1swXS5zdGVuY2lsO1xuICAgICAgICAgIHBhcmFtcy5kZXB0aFN0ZW5jaWwgPSBmYWNlc1swXS5kZXB0aFN0ZW5jaWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZhY2VzW2ldKSB7XG4gICAgICAgICAgKGZhY2VzW2ldKShwYXJhbXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZhY2VzW2ldID0gY3JlYXRlRkJPKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGV4dGVuZChyZWdsRnJhbWVidWZmZXJDdWJlLCB7XG4gICAgICAgIHdpZHRoOiByYWRpdXMsXG4gICAgICAgIGhlaWdodDogcmFkaXVzLFxuICAgICAgICBjb2xvcjogY29sb3JDdWJlc1xuICAgICAgfSlcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUgKHJhZGl1c18pIHtcbiAgICAgIHZhciBpO1xuICAgICAgdmFyIHJhZGl1cyA9IHJhZGl1c18gfCAwO1xuICAgICAgY2hlY2skMShyYWRpdXMgPiAwICYmIHJhZGl1cyA8PSBsaW1pdHMubWF4Q3ViZU1hcFNpemUsXG4gICAgICAgICdpbnZhbGlkIHJhZGl1cyBmb3IgY3ViZSBmYm8nKTtcblxuICAgICAgaWYgKHJhZGl1cyA9PT0gcmVnbEZyYW1lYnVmZmVyQ3ViZS53aWR0aCkge1xuICAgICAgICByZXR1cm4gcmVnbEZyYW1lYnVmZmVyQ3ViZVxuICAgICAgfVxuXG4gICAgICB2YXIgY29sb3JzID0gcmVnbEZyYW1lYnVmZmVyQ3ViZS5jb2xvcjtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgY29sb3JzW2ldLnJlc2l6ZShyYWRpdXMpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgNjsgKytpKSB7XG4gICAgICAgIGZhY2VzW2ldLnJlc2l6ZShyYWRpdXMpO1xuICAgICAgfVxuXG4gICAgICByZWdsRnJhbWVidWZmZXJDdWJlLndpZHRoID0gcmVnbEZyYW1lYnVmZmVyQ3ViZS5oZWlnaHQgPSByYWRpdXM7XG5cbiAgICAgIHJldHVybiByZWdsRnJhbWVidWZmZXJDdWJlXG4gICAgfVxuXG4gICAgcmVnbEZyYW1lYnVmZmVyQ3ViZShvcHRpb25zKTtcblxuICAgIHJldHVybiBleHRlbmQocmVnbEZyYW1lYnVmZmVyQ3ViZSwge1xuICAgICAgZmFjZXM6IGZhY2VzLFxuICAgICAgcmVzaXplOiByZXNpemUsXG4gICAgICBfcmVnbFR5cGU6ICdmcmFtZWJ1ZmZlckN1YmUnLFxuICAgICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xuICAgICAgICBmYWNlcy5mb3JFYWNoKGZ1bmN0aW9uIChmKSB7XG4gICAgICAgICAgZi5kZXN0cm95KCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiByZXN0b3JlRnJhbWVidWZmZXJzICgpIHtcbiAgICB2YWx1ZXMoZnJhbWVidWZmZXJTZXQpLmZvckVhY2goZnVuY3Rpb24gKGZiKSB7XG4gICAgICBmYi5mcmFtZWJ1ZmZlciA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgICB1cGRhdGVGcmFtZWJ1ZmZlcihmYik7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gZXh0ZW5kKGZyYW1lYnVmZmVyU3RhdGUsIHtcbiAgICBnZXRGcmFtZWJ1ZmZlcjogZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiBvYmplY3QgPT09ICdmdW5jdGlvbicgJiYgb2JqZWN0Ll9yZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyJykge1xuICAgICAgICB2YXIgZmJvID0gb2JqZWN0Ll9mcmFtZWJ1ZmZlcjtcbiAgICAgICAgaWYgKGZibyBpbnN0YW5jZW9mIFJFR0xGcmFtZWJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBmYm9cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGxcbiAgICB9LFxuICAgIGNyZWF0ZTogY3JlYXRlRkJPLFxuICAgIGNyZWF0ZUN1YmU6IGNyZWF0ZUN1YmVGQk8sXG4gICAgY2xlYXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhbHVlcyhmcmFtZWJ1ZmZlclNldCkuZm9yRWFjaChkZXN0cm95KTtcbiAgICB9LFxuICAgIHJlc3RvcmU6IHJlc3RvcmVGcmFtZWJ1ZmZlcnNcbiAgfSlcbn1cblxudmFyIEdMX0ZMT0FUJDYgPSA1MTI2O1xuXG5mdW5jdGlvbiBBdHRyaWJ1dGVSZWNvcmQgKCkge1xuICB0aGlzLnN0YXRlID0gMDtcblxuICB0aGlzLnggPSAwLjA7XG4gIHRoaXMueSA9IDAuMDtcbiAgdGhpcy56ID0gMC4wO1xuICB0aGlzLncgPSAwLjA7XG5cbiAgdGhpcy5idWZmZXIgPSBudWxsO1xuICB0aGlzLnNpemUgPSAwO1xuICB0aGlzLm5vcm1hbGl6ZWQgPSBmYWxzZTtcbiAgdGhpcy50eXBlID0gR0xfRkxPQVQkNjtcbiAgdGhpcy5vZmZzZXQgPSAwO1xuICB0aGlzLnN0cmlkZSA9IDA7XG4gIHRoaXMuZGl2aXNvciA9IDA7XG59XG5cbmZ1bmN0aW9uIHdyYXBBdHRyaWJ1dGVTdGF0ZSAoXG4gIGdsLFxuICBleHRlbnNpb25zLFxuICBsaW1pdHMsXG4gIHN0cmluZ1N0b3JlKSB7XG4gIHZhciBOVU1fQVRUUklCVVRFUyA9IGxpbWl0cy5tYXhBdHRyaWJ1dGVzO1xuICB2YXIgYXR0cmlidXRlQmluZGluZ3MgPSBuZXcgQXJyYXkoTlVNX0FUVFJJQlVURVMpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IE5VTV9BVFRSSUJVVEVTOyArK2kpIHtcbiAgICBhdHRyaWJ1dGVCaW5kaW5nc1tpXSA9IG5ldyBBdHRyaWJ1dGVSZWNvcmQoKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgUmVjb3JkOiBBdHRyaWJ1dGVSZWNvcmQsXG4gICAgc2NvcGU6IHt9LFxuICAgIHN0YXRlOiBhdHRyaWJ1dGVCaW5kaW5nc1xuICB9XG59XG5cbnZhciBHTF9GUkFHTUVOVF9TSEFERVIgPSAzNTYzMjtcbnZhciBHTF9WRVJURVhfU0hBREVSID0gMzU2MzM7XG5cbnZhciBHTF9BQ1RJVkVfVU5JRk9STVMgPSAweDhCODY7XG52YXIgR0xfQUNUSVZFX0FUVFJJQlVURVMgPSAweDhCODk7XG5cbmZ1bmN0aW9uIHdyYXBTaGFkZXJTdGF0ZSAoZ2wsIHN0cmluZ1N0b3JlLCBzdGF0cywgY29uZmlnKSB7XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBnbHNsIGNvbXBpbGF0aW9uIGFuZCBsaW5raW5nXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICB2YXIgZnJhZ1NoYWRlcnMgPSB7fTtcbiAgdmFyIHZlcnRTaGFkZXJzID0ge307XG5cbiAgZnVuY3Rpb24gQWN0aXZlSW5mbyAobmFtZSwgaWQsIGxvY2F0aW9uLCBpbmZvKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICB0aGlzLmlkID0gaWQ7XG4gICAgdGhpcy5sb2NhdGlvbiA9IGxvY2F0aW9uO1xuICAgIHRoaXMuaW5mbyA9IGluZm87XG4gIH1cblxuICBmdW5jdGlvbiBpbnNlcnRBY3RpdmVJbmZvIChsaXN0LCBpbmZvKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAobGlzdFtpXS5pZCA9PT0gaW5mby5pZCkge1xuICAgICAgICBsaXN0W2ldLmxvY2F0aW9uID0gaW5mby5sb2NhdGlvbjtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuICAgIGxpc3QucHVzaChpbmZvKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFNoYWRlciAodHlwZSwgaWQsIGNvbW1hbmQpIHtcbiAgICB2YXIgY2FjaGUgPSB0eXBlID09PSBHTF9GUkFHTUVOVF9TSEFERVIgPyBmcmFnU2hhZGVycyA6IHZlcnRTaGFkZXJzO1xuICAgIHZhciBzaGFkZXIgPSBjYWNoZVtpZF07XG5cbiAgICBpZiAoIXNoYWRlcikge1xuICAgICAgdmFyIHNvdXJjZSA9IHN0cmluZ1N0b3JlLnN0cihpZCk7XG4gICAgICBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICBnbC5zaGFkZXJTb3VyY2Uoc2hhZGVyLCBzb3VyY2UpO1xuICAgICAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgY2hlY2skMS5zaGFkZXJFcnJvcihnbCwgc2hhZGVyLCBzb3VyY2UsIHR5cGUsIGNvbW1hbmQpO1xuICAgICAgY2FjaGVbaWRdID0gc2hhZGVyO1xuICAgIH1cblxuICAgIHJldHVybiBzaGFkZXJcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBwcm9ncmFtIGxpbmtpbmdcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIHZhciBwcm9ncmFtQ2FjaGUgPSB7fTtcbiAgdmFyIHByb2dyYW1MaXN0ID0gW107XG5cbiAgdmFyIFBST0dSQU1fQ09VTlRFUiA9IDA7XG5cbiAgZnVuY3Rpb24gUkVHTFByb2dyYW0gKGZyYWdJZCwgdmVydElkKSB7XG4gICAgdGhpcy5pZCA9IFBST0dSQU1fQ09VTlRFUisrO1xuICAgIHRoaXMuZnJhZ0lkID0gZnJhZ0lkO1xuICAgIHRoaXMudmVydElkID0gdmVydElkO1xuICAgIHRoaXMucHJvZ3JhbSA9IG51bGw7XG4gICAgdGhpcy51bmlmb3JtcyA9IFtdO1xuICAgIHRoaXMuYXR0cmlidXRlcyA9IFtdO1xuXG4gICAgaWYgKGNvbmZpZy5wcm9maWxlKSB7XG4gICAgICB0aGlzLnN0YXRzID0ge1xuICAgICAgICB1bmlmb3Jtc0NvdW50OiAwLFxuICAgICAgICBhdHRyaWJ1dGVzQ291bnQ6IDBcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gbGlua1Byb2dyYW0gKGRlc2MsIGNvbW1hbmQpIHtcbiAgICB2YXIgaSwgaW5mbztcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBjb21waWxlICYgbGlua1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB2YXIgZnJhZ1NoYWRlciA9IGdldFNoYWRlcihHTF9GUkFHTUVOVF9TSEFERVIsIGRlc2MuZnJhZ0lkKTtcbiAgICB2YXIgdmVydFNoYWRlciA9IGdldFNoYWRlcihHTF9WRVJURVhfU0hBREVSLCBkZXNjLnZlcnRJZCk7XG5cbiAgICB2YXIgcHJvZ3JhbSA9IGRlc2MucHJvZ3JhbSA9IGdsLmNyZWF0ZVByb2dyYW0oKTtcbiAgICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnJhZ1NoYWRlcik7XG4gICAgZ2wuYXR0YWNoU2hhZGVyKHByb2dyYW0sIHZlcnRTaGFkZXIpO1xuICAgIGdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuICAgIGNoZWNrJDEubGlua0Vycm9yKFxuICAgICAgZ2wsXG4gICAgICBwcm9ncmFtLFxuICAgICAgc3RyaW5nU3RvcmUuc3RyKGRlc2MuZnJhZ0lkKSxcbiAgICAgIHN0cmluZ1N0b3JlLnN0cihkZXNjLnZlcnRJZCksXG4gICAgICBjb21tYW5kKTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBncmFiIHVuaWZvcm1zXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciBudW1Vbmlmb3JtcyA9IGdsLmdldFByb2dyYW1QYXJhbWV0ZXIocHJvZ3JhbSwgR0xfQUNUSVZFX1VOSUZPUk1TKTtcbiAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgIGRlc2Muc3RhdHMudW5pZm9ybXNDb3VudCA9IG51bVVuaWZvcm1zO1xuICAgIH1cbiAgICB2YXIgdW5pZm9ybXMgPSBkZXNjLnVuaWZvcm1zO1xuICAgIGZvciAoaSA9IDA7IGkgPCBudW1Vbmlmb3JtczsgKytpKSB7XG4gICAgICBpbmZvID0gZ2wuZ2V0QWN0aXZlVW5pZm9ybShwcm9ncmFtLCBpKTtcbiAgICAgIGlmIChpbmZvKSB7XG4gICAgICAgIGlmIChpbmZvLnNpemUgPiAxKSB7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBpbmZvLnNpemU7ICsraikge1xuICAgICAgICAgICAgdmFyIG5hbWUgPSBpbmZvLm5hbWUucmVwbGFjZSgnWzBdJywgJ1snICsgaiArICddJyk7XG4gICAgICAgICAgICBpbnNlcnRBY3RpdmVJbmZvKHVuaWZvcm1zLCBuZXcgQWN0aXZlSW5mbyhcbiAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgc3RyaW5nU3RvcmUuaWQobmFtZSksXG4gICAgICAgICAgICAgIGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBuYW1lKSxcbiAgICAgICAgICAgICAgaW5mbykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnNlcnRBY3RpdmVJbmZvKHVuaWZvcm1zLCBuZXcgQWN0aXZlSW5mbyhcbiAgICAgICAgICAgIGluZm8ubmFtZSxcbiAgICAgICAgICAgIHN0cmluZ1N0b3JlLmlkKGluZm8ubmFtZSksXG4gICAgICAgICAgICBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgaW5mby5uYW1lKSxcbiAgICAgICAgICAgIGluZm8pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBncmFiIGF0dHJpYnV0ZXNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIG51bUF0dHJpYnV0ZXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIEdMX0FDVElWRV9BVFRSSUJVVEVTKTtcbiAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICAgIGRlc2Muc3RhdHMuYXR0cmlidXRlc0NvdW50ID0gbnVtQXR0cmlidXRlcztcbiAgICB9XG5cbiAgICB2YXIgYXR0cmlidXRlcyA9IGRlc2MuYXR0cmlidXRlcztcbiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQXR0cmlidXRlczsgKytpKSB7XG4gICAgICBpbmZvID0gZ2wuZ2V0QWN0aXZlQXR0cmliKHByb2dyYW0sIGkpO1xuICAgICAgaWYgKGluZm8pIHtcbiAgICAgICAgaW5zZXJ0QWN0aXZlSW5mbyhhdHRyaWJ1dGVzLCBuZXcgQWN0aXZlSW5mbyhcbiAgICAgICAgICBpbmZvLm5hbWUsXG4gICAgICAgICAgc3RyaW5nU3RvcmUuaWQoaW5mby5uYW1lKSxcbiAgICAgICAgICBnbC5nZXRBdHRyaWJMb2NhdGlvbihwcm9ncmFtLCBpbmZvLm5hbWUpLFxuICAgICAgICAgIGluZm8pKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcbiAgICBzdGF0cy5nZXRNYXhVbmlmb3Jtc0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG0gPSAwO1xuICAgICAgcHJvZ3JhbUxpc3QuZm9yRWFjaChmdW5jdGlvbiAoZGVzYykge1xuICAgICAgICBpZiAoZGVzYy5zdGF0cy51bmlmb3Jtc0NvdW50ID4gbSkge1xuICAgICAgICAgIG0gPSBkZXNjLnN0YXRzLnVuaWZvcm1zQ291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG1cbiAgICB9O1xuXG4gICAgc3RhdHMuZ2V0TWF4QXR0cmlidXRlc0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG0gPSAwO1xuICAgICAgcHJvZ3JhbUxpc3QuZm9yRWFjaChmdW5jdGlvbiAoZGVzYykge1xuICAgICAgICBpZiAoZGVzYy5zdGF0cy5hdHRyaWJ1dGVzQ291bnQgPiBtKSB7XG4gICAgICAgICAgbSA9IGRlc2Muc3RhdHMuYXR0cmlidXRlc0NvdW50O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBtXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlc3RvcmVTaGFkZXJzICgpIHtcbiAgICBmcmFnU2hhZGVycyA9IHt9O1xuICAgIHZlcnRTaGFkZXJzID0ge307XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9ncmFtTGlzdC5sZW5ndGg7ICsraSkge1xuICAgICAgbGlua1Byb2dyYW0ocHJvZ3JhbUxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY2xlYXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBkZWxldGVTaGFkZXIgPSBnbC5kZWxldGVTaGFkZXIuYmluZChnbCk7XG4gICAgICB2YWx1ZXMoZnJhZ1NoYWRlcnMpLmZvckVhY2goZGVsZXRlU2hhZGVyKTtcbiAgICAgIGZyYWdTaGFkZXJzID0ge307XG4gICAgICB2YWx1ZXModmVydFNoYWRlcnMpLmZvckVhY2goZGVsZXRlU2hhZGVyKTtcbiAgICAgIHZlcnRTaGFkZXJzID0ge307XG5cbiAgICAgIHByb2dyYW1MaXN0LmZvckVhY2goZnVuY3Rpb24gKGRlc2MpIHtcbiAgICAgICAgZ2wuZGVsZXRlUHJvZ3JhbShkZXNjLnByb2dyYW0pO1xuICAgICAgfSk7XG4gICAgICBwcm9ncmFtTGlzdC5sZW5ndGggPSAwO1xuICAgICAgcHJvZ3JhbUNhY2hlID0ge307XG5cbiAgICAgIHN0YXRzLnNoYWRlckNvdW50ID0gMDtcbiAgICB9LFxuXG4gICAgcHJvZ3JhbTogZnVuY3Rpb24gKHZlcnRJZCwgZnJhZ0lkLCBjb21tYW5kKSB7XG4gICAgICBjaGVjayQxLmNvbW1hbmQodmVydElkID49IDAsICdtaXNzaW5nIHZlcnRleCBzaGFkZXInLCBjb21tYW5kKTtcbiAgICAgIGNoZWNrJDEuY29tbWFuZChmcmFnSWQgPj0gMCwgJ21pc3NpbmcgZnJhZ21lbnQgc2hhZGVyJywgY29tbWFuZCk7XG5cbiAgICAgIHZhciBjYWNoZSA9IHByb2dyYW1DYWNoZVtmcmFnSWRdO1xuICAgICAgaWYgKCFjYWNoZSkge1xuICAgICAgICBjYWNoZSA9IHByb2dyYW1DYWNoZVtmcmFnSWRdID0ge307XG4gICAgICB9XG4gICAgICB2YXIgcHJvZ3JhbSA9IGNhY2hlW3ZlcnRJZF07XG4gICAgICBpZiAoIXByb2dyYW0pIHtcbiAgICAgICAgcHJvZ3JhbSA9IG5ldyBSRUdMUHJvZ3JhbShmcmFnSWQsIHZlcnRJZCk7XG4gICAgICAgIHN0YXRzLnNoYWRlckNvdW50Kys7XG5cbiAgICAgICAgbGlua1Byb2dyYW0ocHJvZ3JhbSwgY29tbWFuZCk7XG4gICAgICAgIGNhY2hlW3ZlcnRJZF0gPSBwcm9ncmFtO1xuICAgICAgICBwcm9ncmFtTGlzdC5wdXNoKHByb2dyYW0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb2dyYW1cbiAgICB9LFxuXG4gICAgcmVzdG9yZTogcmVzdG9yZVNoYWRlcnMsXG5cbiAgICBzaGFkZXI6IGdldFNoYWRlcixcblxuICAgIGZyYWc6IC0xLFxuICAgIHZlcnQ6IC0xXG4gIH1cbn1cblxudmFyIEdMX1JHQkEkMyA9IDY0MDg7XG52YXIgR0xfVU5TSUdORURfQllURSQ3ID0gNTEyMTtcbnZhciBHTF9QQUNLX0FMSUdOTUVOVCA9IDB4MEQwNTtcbnZhciBHTF9GTE9BVCQ3ID0gMHgxNDA2OyAvLyA1MTI2XG5cbmZ1bmN0aW9uIHdyYXBSZWFkUGl4ZWxzIChcbiAgZ2wsXG4gIGZyYW1lYnVmZmVyU3RhdGUsXG4gIHJlZ2xQb2xsLFxuICBjb250ZXh0LFxuICBnbEF0dHJpYnV0ZXMsXG4gIGV4dGVuc2lvbnMsXG4gIGxpbWl0cykge1xuICBmdW5jdGlvbiByZWFkUGl4ZWxzSW1wbCAoaW5wdXQpIHtcbiAgICB2YXIgdHlwZTtcbiAgICBpZiAoZnJhbWVidWZmZXJTdGF0ZS5uZXh0ID09PSBudWxsKSB7XG4gICAgICBjaGVjayQxKFxuICAgICAgICBnbEF0dHJpYnV0ZXMucHJlc2VydmVEcmF3aW5nQnVmZmVyLFxuICAgICAgICAneW91IG11c3QgY3JlYXRlIGEgd2ViZ2wgY29udGV4dCB3aXRoIFwicHJlc2VydmVEcmF3aW5nQnVmZmVyXCI6dHJ1ZSBpbiBvcmRlciB0byByZWFkIHBpeGVscyBmcm9tIHRoZSBkcmF3aW5nIGJ1ZmZlcicpO1xuICAgICAgdHlwZSA9IEdMX1VOU0lHTkVEX0JZVEUkNztcbiAgICB9IGVsc2Uge1xuICAgICAgY2hlY2skMShcbiAgICAgICAgZnJhbWVidWZmZXJTdGF0ZS5uZXh0LmNvbG9yQXR0YWNobWVudHNbMF0udGV4dHVyZSAhPT0gbnVsbCxcbiAgICAgICAgICAnWW91IGNhbm5vdCByZWFkIGZyb20gYSByZW5kZXJidWZmZXInKTtcbiAgICAgIHR5cGUgPSBmcmFtZWJ1ZmZlclN0YXRlLm5leHQuY29sb3JBdHRhY2htZW50c1swXS50ZXh0dXJlLl90ZXh0dXJlLnR5cGU7XG5cbiAgICAgIGlmIChleHRlbnNpb25zLm9lc190ZXh0dXJlX2Zsb2F0KSB7XG4gICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgdHlwZSA9PT0gR0xfVU5TSUdORURfQllURSQ3IHx8IHR5cGUgPT09IEdMX0ZMT0FUJDcsXG4gICAgICAgICAgJ1JlYWRpbmcgZnJvbSBhIGZyYW1lYnVmZmVyIGlzIG9ubHkgYWxsb3dlZCBmb3IgdGhlIHR5cGVzIFxcJ3VpbnQ4XFwnIGFuZCBcXCdmbG9hdFxcJycpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSBHTF9GTE9BVCQ3KSB7XG4gICAgICAgICAgY2hlY2skMShsaW1pdHMucmVhZEZsb2F0LCAnUmVhZGluZyBcXCdmbG9hdFxcJyB2YWx1ZXMgaXMgbm90IHBlcm1pdHRlZCBpbiB5b3VyIGJyb3dzZXIuIEZvciBhIGZhbGxiYWNrLCBwbGVhc2Ugc2VlOiBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9nbHNsLXJlYWQtZmxvYXQnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMShcbiAgICAgICAgICB0eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDcsXG4gICAgICAgICAgJ1JlYWRpbmcgZnJvbSBhIGZyYW1lYnVmZmVyIGlzIG9ubHkgYWxsb3dlZCBmb3IgdGhlIHR5cGUgXFwndWludDhcXCcnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgeCA9IDA7XG4gICAgdmFyIHkgPSAwO1xuICAgIHZhciB3aWR0aCA9IGNvbnRleHQuZnJhbWVidWZmZXJXaWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gY29udGV4dC5mcmFtZWJ1ZmZlckhlaWdodDtcbiAgICB2YXIgZGF0YSA9IG51bGw7XG5cbiAgICBpZiAoaXNUeXBlZEFycmF5KGlucHV0KSkge1xuICAgICAgZGF0YSA9IGlucHV0O1xuICAgIH0gZWxzZSBpZiAoaW5wdXQpIHtcbiAgICAgIGNoZWNrJDEudHlwZShpbnB1dCwgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3VtZW50cyB0byByZWdsLnJlYWQoKScpO1xuICAgICAgeCA9IGlucHV0LnggfCAwO1xuICAgICAgeSA9IGlucHV0LnkgfCAwO1xuICAgICAgY2hlY2skMShcbiAgICAgICAgeCA+PSAwICYmIHggPCBjb250ZXh0LmZyYW1lYnVmZmVyV2lkdGgsXG4gICAgICAgICdpbnZhbGlkIHggb2Zmc2V0IGZvciByZWdsLnJlYWQnKTtcbiAgICAgIGNoZWNrJDEoXG4gICAgICAgIHkgPj0gMCAmJiB5IDwgY29udGV4dC5mcmFtZWJ1ZmZlckhlaWdodCxcbiAgICAgICAgJ2ludmFsaWQgeSBvZmZzZXQgZm9yIHJlZ2wucmVhZCcpO1xuICAgICAgd2lkdGggPSAoaW5wdXQud2lkdGggfHwgKGNvbnRleHQuZnJhbWVidWZmZXJXaWR0aCAtIHgpKSB8IDA7XG4gICAgICBoZWlnaHQgPSAoaW5wdXQuaGVpZ2h0IHx8IChjb250ZXh0LmZyYW1lYnVmZmVySGVpZ2h0IC0geSkpIHwgMDtcbiAgICAgIGRhdGEgPSBpbnB1dC5kYXRhIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLy8gc2FuaXR5IGNoZWNrIGlucHV0LmRhdGFcbiAgICBpZiAoZGF0YSkge1xuICAgICAgaWYgKHR5cGUgPT09IEdMX1VOU0lHTkVEX0JZVEUkNykge1xuICAgICAgICBjaGVjayQxKFxuICAgICAgICAgIGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5LFxuICAgICAgICAgICdidWZmZXIgbXVzdCBiZSBcXCdVaW50OEFycmF5XFwnIHdoZW4gcmVhZGluZyBmcm9tIGEgZnJhbWVidWZmZXIgb2YgdHlwZSBcXCd1aW50OFxcJycpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9GTE9BVCQ3KSB7XG4gICAgICAgIGNoZWNrJDEoXG4gICAgICAgICAgZGF0YSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSxcbiAgICAgICAgICAnYnVmZmVyIG11c3QgYmUgXFwnRmxvYXQzMkFycmF5XFwnIHdoZW4gcmVhZGluZyBmcm9tIGEgZnJhbWVidWZmZXIgb2YgdHlwZSBcXCdmbG9hdFxcJycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNoZWNrJDEoXG4gICAgICB3aWR0aCA+IDAgJiYgd2lkdGggKyB4IDw9IGNvbnRleHQuZnJhbWVidWZmZXJXaWR0aCxcbiAgICAgICdpbnZhbGlkIHdpZHRoIGZvciByZWFkIHBpeGVscycpO1xuICAgIGNoZWNrJDEoXG4gICAgICBoZWlnaHQgPiAwICYmIGhlaWdodCArIHkgPD0gY29udGV4dC5mcmFtZWJ1ZmZlckhlaWdodCxcbiAgICAgICdpbnZhbGlkIGhlaWdodCBmb3IgcmVhZCBwaXhlbHMnKTtcblxuICAgIC8vIFVwZGF0ZSBXZWJHTCBzdGF0ZVxuICAgIHJlZ2xQb2xsKCk7XG5cbiAgICAvLyBDb21wdXRlIHNpemVcbiAgICB2YXIgc2l6ZSA9IHdpZHRoICogaGVpZ2h0ICogNDtcblxuICAgIC8vIEFsbG9jYXRlIGRhdGFcbiAgICBpZiAoIWRhdGEpIHtcbiAgICAgIGlmICh0eXBlID09PSBHTF9VTlNJR05FRF9CWVRFJDcpIHtcbiAgICAgICAgZGF0YSA9IG5ldyBVaW50OEFycmF5KHNpemUpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBHTF9GTE9BVCQ3KSB7XG4gICAgICAgIGRhdGEgPSBkYXRhIHx8IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVHlwZSBjaGVja1xuICAgIGNoZWNrJDEuaXNUeXBlZEFycmF5KGRhdGEsICdkYXRhIGJ1ZmZlciBmb3IgcmVnbC5yZWFkKCkgbXVzdCBiZSBhIHR5cGVkYXJyYXknKTtcbiAgICBjaGVjayQxKGRhdGEuYnl0ZUxlbmd0aCA+PSBzaXplLCAnZGF0YSBidWZmZXIgZm9yIHJlZ2wucmVhZCgpIHRvbyBzbWFsbCcpO1xuXG4gICAgLy8gUnVuIHJlYWQgcGl4ZWxzXG4gICAgZ2wucGl4ZWxTdG9yZWkoR0xfUEFDS19BTElHTk1FTlQsIDQpO1xuICAgIGdsLnJlYWRQaXhlbHMoeCwgeSwgd2lkdGgsIGhlaWdodCwgR0xfUkdCQSQzLFxuICAgICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICAgIGRhdGEpO1xuXG4gICAgcmV0dXJuIGRhdGFcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRQaXhlbHNGQk8gKG9wdGlvbnMpIHtcbiAgICB2YXIgcmVzdWx0O1xuICAgIGZyYW1lYnVmZmVyU3RhdGUuc2V0RkJPKHtcbiAgICAgIGZyYW1lYnVmZmVyOiBvcHRpb25zLmZyYW1lYnVmZmVyXG4gICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgcmVzdWx0ID0gcmVhZFBpeGVsc0ltcGwob3B0aW9ucyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZFBpeGVscyAob3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucyB8fCAhKCdmcmFtZWJ1ZmZlcicgaW4gb3B0aW9ucykpIHtcbiAgICAgIHJldHVybiByZWFkUGl4ZWxzSW1wbChvcHRpb25zKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVhZFBpeGVsc0ZCTyhvcHRpb25zKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZWFkUGl4ZWxzXG59XG5cbmZ1bmN0aW9uIHNsaWNlICh4KSB7XG4gIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh4KVxufVxuXG5mdW5jdGlvbiBqb2luICh4KSB7XG4gIHJldHVybiBzbGljZSh4KS5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVFbnZpcm9ubWVudCAoKSB7XG4gIC8vIFVuaXF1ZSB2YXJpYWJsZSBpZCBjb3VudGVyXG4gIHZhciB2YXJDb3VudGVyID0gMDtcblxuICAvLyBMaW5rZWQgdmFsdWVzIGFyZSBwYXNzZWQgZnJvbSB0aGlzIHNjb3BlIGludG8gdGhlIGdlbmVyYXRlZCBjb2RlIGJsb2NrXG4gIC8vIENhbGxpbmcgbGluaygpIHBhc3NlcyBhIHZhbHVlIGludG8gdGhlIGdlbmVyYXRlZCBzY29wZSBhbmQgcmV0dXJuc1xuICAvLyB0aGUgdmFyaWFibGUgbmFtZSB3aGljaCBpdCBpcyBib3VuZCB0b1xuICB2YXIgbGlua2VkTmFtZXMgPSBbXTtcbiAgdmFyIGxpbmtlZFZhbHVlcyA9IFtdO1xuICBmdW5jdGlvbiBsaW5rICh2YWx1ZSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlua2VkVmFsdWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAobGlua2VkVmFsdWVzW2ldID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gbGlua2VkTmFtZXNbaV1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbmFtZSA9ICdnJyArICh2YXJDb3VudGVyKyspO1xuICAgIGxpbmtlZE5hbWVzLnB1c2gobmFtZSk7XG4gICAgbGlua2VkVmFsdWVzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiBuYW1lXG4gIH1cblxuICAvLyBjcmVhdGUgYSBjb2RlIGJsb2NrXG4gIGZ1bmN0aW9uIGJsb2NrICgpIHtcbiAgICB2YXIgY29kZSA9IFtdO1xuICAgIGZ1bmN0aW9uIHB1c2ggKCkge1xuICAgICAgY29kZS5wdXNoLmFwcGx5KGNvZGUsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgIH1cblxuICAgIHZhciB2YXJzID0gW107XG4gICAgZnVuY3Rpb24gZGVmICgpIHtcbiAgICAgIHZhciBuYW1lID0gJ3YnICsgKHZhckNvdW50ZXIrKyk7XG4gICAgICB2YXJzLnB1c2gobmFtZSk7XG5cbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb2RlLnB1c2gobmFtZSwgJz0nKTtcbiAgICAgICAgY29kZS5wdXNoLmFwcGx5KGNvZGUsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICBjb2RlLnB1c2goJzsnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5hbWVcbiAgICB9XG5cbiAgICByZXR1cm4gZXh0ZW5kKHB1c2gsIHtcbiAgICAgIGRlZjogZGVmLFxuICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGpvaW4oW1xuICAgICAgICAgICh2YXJzLmxlbmd0aCA+IDAgPyAndmFyICcgKyB2YXJzICsgJzsnIDogJycpLFxuICAgICAgICAgIGpvaW4oY29kZSlcbiAgICAgICAgXSlcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gc2NvcGUgKCkge1xuICAgIHZhciBlbnRyeSA9IGJsb2NrKCk7XG4gICAgdmFyIGV4aXQgPSBibG9jaygpO1xuXG4gICAgdmFyIGVudHJ5VG9TdHJpbmcgPSBlbnRyeS50b1N0cmluZztcbiAgICB2YXIgZXhpdFRvU3RyaW5nID0gZXhpdC50b1N0cmluZztcblxuICAgIGZ1bmN0aW9uIHNhdmUgKG9iamVjdCwgcHJvcCkge1xuICAgICAgZXhpdChvYmplY3QsIHByb3AsICc9JywgZW50cnkuZGVmKG9iamVjdCwgcHJvcCksICc7Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbiAoKSB7XG4gICAgICBlbnRyeS5hcHBseShlbnRyeSwgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgfSwge1xuICAgICAgZGVmOiBlbnRyeS5kZWYsXG4gICAgICBlbnRyeTogZW50cnksXG4gICAgICBleGl0OiBleGl0LFxuICAgICAgc2F2ZTogc2F2ZSxcbiAgICAgIHNldDogZnVuY3Rpb24gKG9iamVjdCwgcHJvcCwgdmFsdWUpIHtcbiAgICAgICAgc2F2ZShvYmplY3QsIHByb3ApO1xuICAgICAgICBlbnRyeShvYmplY3QsIHByb3AsICc9JywgdmFsdWUsICc7Jyk7XG4gICAgICB9LFxuICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGVudHJ5VG9TdHJpbmcoKSArIGV4aXRUb1N0cmluZygpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbmRpdGlvbmFsICgpIHtcbiAgICB2YXIgcHJlZCA9IGpvaW4oYXJndW1lbnRzKTtcbiAgICB2YXIgdGhlbkJsb2NrID0gc2NvcGUoKTtcbiAgICB2YXIgZWxzZUJsb2NrID0gc2NvcGUoKTtcblxuICAgIHZhciB0aGVuVG9TdHJpbmcgPSB0aGVuQmxvY2sudG9TdHJpbmc7XG4gICAgdmFyIGVsc2VUb1N0cmluZyA9IGVsc2VCbG9jay50b1N0cmluZztcblxuICAgIHJldHVybiBleHRlbmQodGhlbkJsb2NrLCB7XG4gICAgICB0aGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoZW5CbG9jay5hcHBseSh0aGVuQmxvY2ssIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICByZXR1cm4gdGhpc1xuICAgICAgfSxcbiAgICAgIGVsc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZWxzZUJsb2NrLmFwcGx5KGVsc2VCbG9jaywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgIHJldHVybiB0aGlzXG4gICAgICB9LFxuICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVsc2VDbGF1c2UgPSBlbHNlVG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKGVsc2VDbGF1c2UpIHtcbiAgICAgICAgICBlbHNlQ2xhdXNlID0gJ2Vsc2V7JyArIGVsc2VDbGF1c2UgKyAnfSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGpvaW4oW1xuICAgICAgICAgICdpZignLCBwcmVkLCAnKXsnLFxuICAgICAgICAgIHRoZW5Ub1N0cmluZygpLFxuICAgICAgICAgICd9JywgZWxzZUNsYXVzZVxuICAgICAgICBdKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvLyBwcm9jZWR1cmUgbGlzdFxuICB2YXIgZ2xvYmFsQmxvY2sgPSBibG9jaygpO1xuICB2YXIgcHJvY2VkdXJlcyA9IHt9O1xuICBmdW5jdGlvbiBwcm9jIChuYW1lLCBjb3VudCkge1xuICAgIHZhciBhcmdzID0gW107XG4gICAgZnVuY3Rpb24gYXJnICgpIHtcbiAgICAgIHZhciBuYW1lID0gJ2EnICsgYXJncy5sZW5ndGg7XG4gICAgICBhcmdzLnB1c2gobmFtZSk7XG4gICAgICByZXR1cm4gbmFtZVxuICAgIH1cblxuICAgIGNvdW50ID0gY291bnQgfHwgMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyArK2kpIHtcbiAgICAgIGFyZygpO1xuICAgIH1cblxuICAgIHZhciBib2R5ID0gc2NvcGUoKTtcbiAgICB2YXIgYm9keVRvU3RyaW5nID0gYm9keS50b1N0cmluZztcblxuICAgIHZhciByZXN1bHQgPSBwcm9jZWR1cmVzW25hbWVdID0gZXh0ZW5kKGJvZHksIHtcbiAgICAgIGFyZzogYXJnLFxuICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGpvaW4oW1xuICAgICAgICAgICdmdW5jdGlvbignLCBhcmdzLmpvaW4oKSwgJyl7JyxcbiAgICAgICAgICBib2R5VG9TdHJpbmcoKSxcbiAgICAgICAgICAnfSdcbiAgICAgICAgXSlcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbXBpbGUgKCkge1xuICAgIHZhciBjb2RlID0gWydcInVzZSBzdHJpY3RcIjsnLFxuICAgICAgZ2xvYmFsQmxvY2ssXG4gICAgICAncmV0dXJuIHsnXTtcbiAgICBPYmplY3Qua2V5cyhwcm9jZWR1cmVzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICBjb2RlLnB1c2goJ1wiJywgbmFtZSwgJ1wiOicsIHByb2NlZHVyZXNbbmFtZV0udG9TdHJpbmcoKSwgJywnKTtcbiAgICB9KTtcbiAgICBjb2RlLnB1c2goJ30nKTtcbiAgICB2YXIgc3JjID0gam9pbihjb2RlKVxuICAgICAgLnJlcGxhY2UoLzsvZywgJztcXG4nKVxuICAgICAgLnJlcGxhY2UoL30vZywgJ31cXG4nKVxuICAgICAgLnJlcGxhY2UoL3svZywgJ3tcXG4nKTtcbiAgICB2YXIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KG51bGwsIGxpbmtlZE5hbWVzLmNvbmNhdChzcmMpKTtcbiAgICByZXR1cm4gcHJvYy5hcHBseShudWxsLCBsaW5rZWRWYWx1ZXMpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdsb2JhbDogZ2xvYmFsQmxvY2ssXG4gICAgbGluazogbGluayxcbiAgICBibG9jazogYmxvY2ssXG4gICAgcHJvYzogcHJvYyxcbiAgICBzY29wZTogc2NvcGUsXG4gICAgY29uZDogY29uZGl0aW9uYWwsXG4gICAgY29tcGlsZTogY29tcGlsZVxuICB9XG59XG5cbi8vIFwiY3V0ZVwiIG5hbWVzIGZvciB2ZWN0b3IgY29tcG9uZW50c1xudmFyIENVVEVfQ09NUE9ORU5UUyA9ICd4eXp3Jy5zcGxpdCgnJyk7XG5cbnZhciBHTF9VTlNJR05FRF9CWVRFJDggPSA1MTIxO1xuXG52YXIgQVRUUklCX1NUQVRFX1BPSU5URVIgPSAxO1xudmFyIEFUVFJJQl9TVEFURV9DT05TVEFOVCA9IDI7XG5cbnZhciBEWU5fRlVOQyQxID0gMDtcbnZhciBEWU5fUFJPUCQxID0gMTtcbnZhciBEWU5fQ09OVEVYVCQxID0gMjtcbnZhciBEWU5fU1RBVEUkMSA9IDM7XG52YXIgRFlOX1RIVU5LID0gNDtcblxudmFyIFNfRElUSEVSID0gJ2RpdGhlcic7XG52YXIgU19CTEVORF9FTkFCTEUgPSAnYmxlbmQuZW5hYmxlJztcbnZhciBTX0JMRU5EX0NPTE9SID0gJ2JsZW5kLmNvbG9yJztcbnZhciBTX0JMRU5EX0VRVUFUSU9OID0gJ2JsZW5kLmVxdWF0aW9uJztcbnZhciBTX0JMRU5EX0ZVTkMgPSAnYmxlbmQuZnVuYyc7XG52YXIgU19ERVBUSF9FTkFCTEUgPSAnZGVwdGguZW5hYmxlJztcbnZhciBTX0RFUFRIX0ZVTkMgPSAnZGVwdGguZnVuYyc7XG52YXIgU19ERVBUSF9SQU5HRSA9ICdkZXB0aC5yYW5nZSc7XG52YXIgU19ERVBUSF9NQVNLID0gJ2RlcHRoLm1hc2snO1xudmFyIFNfQ09MT1JfTUFTSyA9ICdjb2xvck1hc2snO1xudmFyIFNfQ1VMTF9FTkFCTEUgPSAnY3VsbC5lbmFibGUnO1xudmFyIFNfQ1VMTF9GQUNFID0gJ2N1bGwuZmFjZSc7XG52YXIgU19GUk9OVF9GQUNFID0gJ2Zyb250RmFjZSc7XG52YXIgU19MSU5FX1dJRFRIID0gJ2xpbmVXaWR0aCc7XG52YXIgU19QT0xZR09OX09GRlNFVF9FTkFCTEUgPSAncG9seWdvbk9mZnNldC5lbmFibGUnO1xudmFyIFNfUE9MWUdPTl9PRkZTRVRfT0ZGU0VUID0gJ3BvbHlnb25PZmZzZXQub2Zmc2V0JztcbnZhciBTX1NBTVBMRV9BTFBIQSA9ICdzYW1wbGUuYWxwaGEnO1xudmFyIFNfU0FNUExFX0VOQUJMRSA9ICdzYW1wbGUuZW5hYmxlJztcbnZhciBTX1NBTVBMRV9DT1ZFUkFHRSA9ICdzYW1wbGUuY292ZXJhZ2UnO1xudmFyIFNfU1RFTkNJTF9FTkFCTEUgPSAnc3RlbmNpbC5lbmFibGUnO1xudmFyIFNfU1RFTkNJTF9NQVNLID0gJ3N0ZW5jaWwubWFzayc7XG52YXIgU19TVEVOQ0lMX0ZVTkMgPSAnc3RlbmNpbC5mdW5jJztcbnZhciBTX1NURU5DSUxfT1BGUk9OVCA9ICdzdGVuY2lsLm9wRnJvbnQnO1xudmFyIFNfU1RFTkNJTF9PUEJBQ0sgPSAnc3RlbmNpbC5vcEJhY2snO1xudmFyIFNfU0NJU1NPUl9FTkFCTEUgPSAnc2Npc3Nvci5lbmFibGUnO1xudmFyIFNfU0NJU1NPUl9CT1ggPSAnc2Npc3Nvci5ib3gnO1xudmFyIFNfVklFV1BPUlQgPSAndmlld3BvcnQnO1xuXG52YXIgU19QUk9GSUxFID0gJ3Byb2ZpbGUnO1xuXG52YXIgU19GUkFNRUJVRkZFUiA9ICdmcmFtZWJ1ZmZlcic7XG52YXIgU19WRVJUID0gJ3ZlcnQnO1xudmFyIFNfRlJBRyA9ICdmcmFnJztcbnZhciBTX0VMRU1FTlRTID0gJ2VsZW1lbnRzJztcbnZhciBTX1BSSU1JVElWRSA9ICdwcmltaXRpdmUnO1xudmFyIFNfQ09VTlQgPSAnY291bnQnO1xudmFyIFNfT0ZGU0VUID0gJ29mZnNldCc7XG52YXIgU19JTlNUQU5DRVMgPSAnaW5zdGFuY2VzJztcblxudmFyIFNVRkZJWF9XSURUSCA9ICdXaWR0aCc7XG52YXIgU1VGRklYX0hFSUdIVCA9ICdIZWlnaHQnO1xuXG52YXIgU19GUkFNRUJVRkZFUl9XSURUSCA9IFNfRlJBTUVCVUZGRVIgKyBTVUZGSVhfV0lEVEg7XG52YXIgU19GUkFNRUJVRkZFUl9IRUlHSFQgPSBTX0ZSQU1FQlVGRkVSICsgU1VGRklYX0hFSUdIVDtcbnZhciBTX1ZJRVdQT1JUX1dJRFRIID0gU19WSUVXUE9SVCArIFNVRkZJWF9XSURUSDtcbnZhciBTX1ZJRVdQT1JUX0hFSUdIVCA9IFNfVklFV1BPUlQgKyBTVUZGSVhfSEVJR0hUO1xudmFyIFNfRFJBV0lOR0JVRkZFUiA9ICdkcmF3aW5nQnVmZmVyJztcbnZhciBTX0RSQVdJTkdCVUZGRVJfV0lEVEggPSBTX0RSQVdJTkdCVUZGRVIgKyBTVUZGSVhfV0lEVEg7XG52YXIgU19EUkFXSU5HQlVGRkVSX0hFSUdIVCA9IFNfRFJBV0lOR0JVRkZFUiArIFNVRkZJWF9IRUlHSFQ7XG5cbnZhciBORVNURURfT1BUSU9OUyA9IFtcbiAgU19CTEVORF9GVU5DLFxuICBTX0JMRU5EX0VRVUFUSU9OLFxuICBTX1NURU5DSUxfRlVOQyxcbiAgU19TVEVOQ0lMX09QRlJPTlQsXG4gIFNfU1RFTkNJTF9PUEJBQ0ssXG4gIFNfU0FNUExFX0NPVkVSQUdFLFxuICBTX1ZJRVdQT1JULFxuICBTX1NDSVNTT1JfQk9YLFxuICBTX1BPTFlHT05fT0ZGU0VUX09GRlNFVFxuXTtcblxudmFyIEdMX0FSUkFZX0JVRkZFUiQxID0gMzQ5NjI7XG52YXIgR0xfRUxFTUVOVF9BUlJBWV9CVUZGRVIkMSA9IDM0OTYzO1xuXG52YXIgR0xfRlJBR01FTlRfU0hBREVSJDEgPSAzNTYzMjtcbnZhciBHTF9WRVJURVhfU0hBREVSJDEgPSAzNTYzMztcblxudmFyIEdMX1RFWFRVUkVfMkQkMyA9IDB4MERFMTtcbnZhciBHTF9URVhUVVJFX0NVQkVfTUFQJDIgPSAweDg1MTM7XG5cbnZhciBHTF9DVUxMX0ZBQ0UgPSAweDBCNDQ7XG52YXIgR0xfQkxFTkQgPSAweDBCRTI7XG52YXIgR0xfRElUSEVSID0gMHgwQkQwO1xudmFyIEdMX1NURU5DSUxfVEVTVCA9IDB4MEI5MDtcbnZhciBHTF9ERVBUSF9URVNUID0gMHgwQjcxO1xudmFyIEdMX1NDSVNTT1JfVEVTVCA9IDB4MEMxMTtcbnZhciBHTF9QT0xZR09OX09GRlNFVF9GSUxMID0gMHg4MDM3O1xudmFyIEdMX1NBTVBMRV9BTFBIQV9UT19DT1ZFUkFHRSA9IDB4ODA5RTtcbnZhciBHTF9TQU1QTEVfQ09WRVJBR0UgPSAweDgwQTA7XG5cbnZhciBHTF9GTE9BVCQ4ID0gNTEyNjtcbnZhciBHTF9GTE9BVF9WRUMyID0gMzU2NjQ7XG52YXIgR0xfRkxPQVRfVkVDMyA9IDM1NjY1O1xudmFyIEdMX0ZMT0FUX1ZFQzQgPSAzNTY2NjtcbnZhciBHTF9JTlQkMyA9IDUxMjQ7XG52YXIgR0xfSU5UX1ZFQzIgPSAzNTY2NztcbnZhciBHTF9JTlRfVkVDMyA9IDM1NjY4O1xudmFyIEdMX0lOVF9WRUM0ID0gMzU2Njk7XG52YXIgR0xfQk9PTCA9IDM1NjcwO1xudmFyIEdMX0JPT0xfVkVDMiA9IDM1NjcxO1xudmFyIEdMX0JPT0xfVkVDMyA9IDM1NjcyO1xudmFyIEdMX0JPT0xfVkVDNCA9IDM1NjczO1xudmFyIEdMX0ZMT0FUX01BVDIgPSAzNTY3NDtcbnZhciBHTF9GTE9BVF9NQVQzID0gMzU2NzU7XG52YXIgR0xfRkxPQVRfTUFUNCA9IDM1Njc2O1xudmFyIEdMX1NBTVBMRVJfMkQgPSAzNTY3ODtcbnZhciBHTF9TQU1QTEVSX0NVQkUgPSAzNTY4MDtcblxudmFyIEdMX1RSSUFOR0xFUyQxID0gNDtcblxudmFyIEdMX0ZST05UID0gMTAyODtcbnZhciBHTF9CQUNLID0gMTAyOTtcbnZhciBHTF9DVyA9IDB4MDkwMDtcbnZhciBHTF9DQ1cgPSAweDA5MDE7XG52YXIgR0xfTUlOX0VYVCA9IDB4ODAwNztcbnZhciBHTF9NQVhfRVhUID0gMHg4MDA4O1xudmFyIEdMX0FMV0FZUyA9IDUxOTtcbnZhciBHTF9LRUVQID0gNzY4MDtcbnZhciBHTF9aRVJPID0gMDtcbnZhciBHTF9PTkUgPSAxO1xudmFyIEdMX0ZVTkNfQUREID0gMHg4MDA2O1xudmFyIEdMX0xFU1MgPSA1MTM7XG5cbnZhciBHTF9GUkFNRUJVRkZFUiQyID0gMHg4RDQwO1xudmFyIEdMX0NPTE9SX0FUVEFDSE1FTlQwJDIgPSAweDhDRTA7XG5cbnZhciBibGVuZEZ1bmNzID0ge1xuICAnMCc6IDAsXG4gICcxJzogMSxcbiAgJ3plcm8nOiAwLFxuICAnb25lJzogMSxcbiAgJ3NyYyBjb2xvcic6IDc2OCxcbiAgJ29uZSBtaW51cyBzcmMgY29sb3InOiA3NjksXG4gICdzcmMgYWxwaGEnOiA3NzAsXG4gICdvbmUgbWludXMgc3JjIGFscGhhJzogNzcxLFxuICAnZHN0IGNvbG9yJzogNzc0LFxuICAnb25lIG1pbnVzIGRzdCBjb2xvcic6IDc3NSxcbiAgJ2RzdCBhbHBoYSc6IDc3MixcbiAgJ29uZSBtaW51cyBkc3QgYWxwaGEnOiA3NzMsXG4gICdjb25zdGFudCBjb2xvcic6IDMyNzY5LFxuICAnb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yJzogMzI3NzAsXG4gICdjb25zdGFudCBhbHBoYSc6IDMyNzcxLFxuICAnb25lIG1pbnVzIGNvbnN0YW50IGFscGhhJzogMzI3NzIsXG4gICdzcmMgYWxwaGEgc2F0dXJhdGUnOiA3NzZcbn07XG5cbi8vIFRoZXJlIGFyZSBpbnZhbGlkIHZhbHVlcyBmb3Igc3JjUkdCIGFuZCBkc3RSR0IuIFNlZTpcbi8vIGh0dHBzOi8vd3d3Lmtocm9ub3Mub3JnL3JlZ2lzdHJ5L3dlYmdsL3NwZWNzLzEuMC8jNi4xM1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9XZWJHTC9ibG9iLzBkMzIwMWY1ZjdlYzNjMDA2MGJjMWYwNDA3NzQ2MTU0MWYxOTg3YjkvY29uZm9ybWFuY2Utc3VpdGVzLzEuMC4zL2NvbmZvcm1hbmNlL21pc2Mvd2ViZ2wtc3BlY2lmaWMuaHRtbCNMNTZcbnZhciBpbnZhbGlkQmxlbmRDb21iaW5hdGlvbnMgPSBbXG4gICdjb25zdGFudCBjb2xvciwgY29uc3RhbnQgYWxwaGEnLFxuICAnb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yLCBjb25zdGFudCBhbHBoYScsXG4gICdjb25zdGFudCBjb2xvciwgb25lIG1pbnVzIGNvbnN0YW50IGFscGhhJyxcbiAgJ29uZSBtaW51cyBjb25zdGFudCBjb2xvciwgb25lIG1pbnVzIGNvbnN0YW50IGFscGhhJyxcbiAgJ2NvbnN0YW50IGFscGhhLCBjb25zdGFudCBjb2xvcicsXG4gICdjb25zdGFudCBhbHBoYSwgb25lIG1pbnVzIGNvbnN0YW50IGNvbG9yJyxcbiAgJ29uZSBtaW51cyBjb25zdGFudCBhbHBoYSwgY29uc3RhbnQgY29sb3InLFxuICAnb25lIG1pbnVzIGNvbnN0YW50IGFscGhhLCBvbmUgbWludXMgY29uc3RhbnQgY29sb3InXG5dO1xuXG52YXIgY29tcGFyZUZ1bmNzID0ge1xuICAnbmV2ZXInOiA1MTIsXG4gICdsZXNzJzogNTEzLFxuICAnPCc6IDUxMyxcbiAgJ2VxdWFsJzogNTE0LFxuICAnPSc6IDUxNCxcbiAgJz09JzogNTE0LFxuICAnPT09JzogNTE0LFxuICAnbGVxdWFsJzogNTE1LFxuICAnPD0nOiA1MTUsXG4gICdncmVhdGVyJzogNTE2LFxuICAnPic6IDUxNixcbiAgJ25vdGVxdWFsJzogNTE3LFxuICAnIT0nOiA1MTcsXG4gICchPT0nOiA1MTcsXG4gICdnZXF1YWwnOiA1MTgsXG4gICc+PSc6IDUxOCxcbiAgJ2Fsd2F5cyc6IDUxOVxufTtcblxudmFyIHN0ZW5jaWxPcHMgPSB7XG4gICcwJzogMCxcbiAgJ3plcm8nOiAwLFxuICAna2VlcCc6IDc2ODAsXG4gICdyZXBsYWNlJzogNzY4MSxcbiAgJ2luY3JlbWVudCc6IDc2ODIsXG4gICdkZWNyZW1lbnQnOiA3NjgzLFxuICAnaW5jcmVtZW50IHdyYXAnOiAzNDA1NSxcbiAgJ2RlY3JlbWVudCB3cmFwJzogMzQwNTYsXG4gICdpbnZlcnQnOiA1Mzg2XG59O1xuXG52YXIgc2hhZGVyVHlwZSA9IHtcbiAgJ2ZyYWcnOiBHTF9GUkFHTUVOVF9TSEFERVIkMSxcbiAgJ3ZlcnQnOiBHTF9WRVJURVhfU0hBREVSJDFcbn07XG5cbnZhciBvcmllbnRhdGlvblR5cGUgPSB7XG4gICdjdyc6IEdMX0NXLFxuICAnY2N3JzogR0xfQ0NXXG59O1xuXG5mdW5jdGlvbiBpc0J1ZmZlckFyZ3MgKHgpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoeCkgfHxcbiAgICBpc1R5cGVkQXJyYXkoeCkgfHxcbiAgICBpc05EQXJyYXlMaWtlKHgpXG59XG5cbi8vIE1ha2Ugc3VyZSB2aWV3cG9ydCBpcyBwcm9jZXNzZWQgZmlyc3RcbmZ1bmN0aW9uIHNvcnRTdGF0ZSAoc3RhdGUpIHtcbiAgcmV0dXJuIHN0YXRlLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAoYSA9PT0gU19WSUVXUE9SVCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfSBlbHNlIGlmIChiID09PSBTX1ZJRVdQT1JUKSB7XG4gICAgICByZXR1cm4gMVxuICAgIH1cbiAgICByZXR1cm4gKGEgPCBiKSA/IC0xIDogMVxuICB9KVxufVxuXG5mdW5jdGlvbiBEZWNsYXJhdGlvbiAodGhpc0RlcCwgY29udGV4dERlcCwgcHJvcERlcCwgYXBwZW5kKSB7XG4gIHRoaXMudGhpc0RlcCA9IHRoaXNEZXA7XG4gIHRoaXMuY29udGV4dERlcCA9IGNvbnRleHREZXA7XG4gIHRoaXMucHJvcERlcCA9IHByb3BEZXA7XG4gIHRoaXMuYXBwZW5kID0gYXBwZW5kO1xufVxuXG5mdW5jdGlvbiBpc1N0YXRpYyAoZGVjbCkge1xuICByZXR1cm4gZGVjbCAmJiAhKGRlY2wudGhpc0RlcCB8fCBkZWNsLmNvbnRleHREZXAgfHwgZGVjbC5wcm9wRGVwKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVTdGF0aWNEZWNsIChhcHBlbmQpIHtcbiAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihmYWxzZSwgZmFsc2UsIGZhbHNlLCBhcHBlbmQpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUR5bmFtaWNEZWNsIChkeW4sIGFwcGVuZCkge1xuICB2YXIgdHlwZSA9IGR5bi50eXBlO1xuICBpZiAodHlwZSA9PT0gRFlOX0ZVTkMkMSkge1xuICAgIHZhciBudW1BcmdzID0gZHluLmRhdGEubGVuZ3RoO1xuICAgIHJldHVybiBuZXcgRGVjbGFyYXRpb24oXG4gICAgICB0cnVlLFxuICAgICAgbnVtQXJncyA+PSAxLFxuICAgICAgbnVtQXJncyA+PSAyLFxuICAgICAgYXBwZW5kKVxuICB9IGVsc2UgaWYgKHR5cGUgPT09IERZTl9USFVOSykge1xuICAgIHZhciBkYXRhID0gZHluLmRhdGE7XG4gICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihcbiAgICAgIGRhdGEudGhpc0RlcCxcbiAgICAgIGRhdGEuY29udGV4dERlcCxcbiAgICAgIGRhdGEucHJvcERlcCxcbiAgICAgIGFwcGVuZClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKFxuICAgICAgdHlwZSA9PT0gRFlOX1NUQVRFJDEsXG4gICAgICB0eXBlID09PSBEWU5fQ09OVEVYVCQxLFxuICAgICAgdHlwZSA9PT0gRFlOX1BST1AkMSxcbiAgICAgIGFwcGVuZClcbiAgfVxufVxuXG52YXIgU0NPUEVfREVDTCA9IG5ldyBEZWNsYXJhdGlvbihmYWxzZSwgZmFsc2UsIGZhbHNlLCBmdW5jdGlvbiAoKSB7fSk7XG5cbmZ1bmN0aW9uIHJlZ2xDb3JlIChcbiAgZ2wsXG4gIHN0cmluZ1N0b3JlLFxuICBleHRlbnNpb25zLFxuICBsaW1pdHMsXG4gIGJ1ZmZlclN0YXRlLFxuICBlbGVtZW50U3RhdGUsXG4gIHRleHR1cmVTdGF0ZSxcbiAgZnJhbWVidWZmZXJTdGF0ZSxcbiAgdW5pZm9ybVN0YXRlLFxuICBhdHRyaWJ1dGVTdGF0ZSxcbiAgc2hhZGVyU3RhdGUsXG4gIGRyYXdTdGF0ZSxcbiAgY29udGV4dFN0YXRlLFxuICB0aW1lcixcbiAgY29uZmlnKSB7XG4gIHZhciBBdHRyaWJ1dGVSZWNvcmQgPSBhdHRyaWJ1dGVTdGF0ZS5SZWNvcmQ7XG5cbiAgdmFyIGJsZW5kRXF1YXRpb25zID0ge1xuICAgICdhZGQnOiAzMjc3NCxcbiAgICAnc3VidHJhY3QnOiAzMjc3OCxcbiAgICAncmV2ZXJzZSBzdWJ0cmFjdCc6IDMyNzc5XG4gIH07XG4gIGlmIChleHRlbnNpb25zLmV4dF9ibGVuZF9taW5tYXgpIHtcbiAgICBibGVuZEVxdWF0aW9ucy5taW4gPSBHTF9NSU5fRVhUO1xuICAgIGJsZW5kRXF1YXRpb25zLm1heCA9IEdMX01BWF9FWFQ7XG4gIH1cblxuICB2YXIgZXh0SW5zdGFuY2luZyA9IGV4dGVuc2lvbnMuYW5nbGVfaW5zdGFuY2VkX2FycmF5cztcbiAgdmFyIGV4dERyYXdCdWZmZXJzID0gZXh0ZW5zaW9ucy53ZWJnbF9kcmF3X2J1ZmZlcnM7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBXRUJHTCBTVEFURVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIHZhciBjdXJyZW50U3RhdGUgPSB7XG4gICAgZGlydHk6IHRydWUsXG4gICAgcHJvZmlsZTogY29uZmlnLnByb2ZpbGVcbiAgfTtcbiAgdmFyIG5leHRTdGF0ZSA9IHt9O1xuICB2YXIgR0xfU1RBVEVfTkFNRVMgPSBbXTtcbiAgdmFyIEdMX0ZMQUdTID0ge307XG4gIHZhciBHTF9WQVJJQUJMRVMgPSB7fTtcblxuICBmdW5jdGlvbiBwcm9wTmFtZSAobmFtZSkge1xuICAgIHJldHVybiBuYW1lLnJlcGxhY2UoJy4nLCAnXycpXG4gIH1cblxuICBmdW5jdGlvbiBzdGF0ZUZsYWcgKHNuYW1lLCBjYXAsIGluaXQpIHtcbiAgICB2YXIgbmFtZSA9IHByb3BOYW1lKHNuYW1lKTtcbiAgICBHTF9TVEFURV9OQU1FUy5wdXNoKHNuYW1lKTtcbiAgICBuZXh0U3RhdGVbbmFtZV0gPSBjdXJyZW50U3RhdGVbbmFtZV0gPSAhIWluaXQ7XG4gICAgR0xfRkxBR1NbbmFtZV0gPSBjYXA7XG4gIH1cblxuICBmdW5jdGlvbiBzdGF0ZVZhcmlhYmxlIChzbmFtZSwgZnVuYywgaW5pdCkge1xuICAgIHZhciBuYW1lID0gcHJvcE5hbWUoc25hbWUpO1xuICAgIEdMX1NUQVRFX05BTUVTLnB1c2goc25hbWUpO1xuICAgIGlmIChBcnJheS5pc0FycmF5KGluaXQpKSB7XG4gICAgICBjdXJyZW50U3RhdGVbbmFtZV0gPSBpbml0LnNsaWNlKCk7XG4gICAgICBuZXh0U3RhdGVbbmFtZV0gPSBpbml0LnNsaWNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN1cnJlbnRTdGF0ZVtuYW1lXSA9IG5leHRTdGF0ZVtuYW1lXSA9IGluaXQ7XG4gICAgfVxuICAgIEdMX1ZBUklBQkxFU1tuYW1lXSA9IGZ1bmM7XG4gIH1cblxuICAvLyBEaXRoZXJpbmdcbiAgc3RhdGVGbGFnKFNfRElUSEVSLCBHTF9ESVRIRVIpO1xuXG4gIC8vIEJsZW5kaW5nXG4gIHN0YXRlRmxhZyhTX0JMRU5EX0VOQUJMRSwgR0xfQkxFTkQpO1xuICBzdGF0ZVZhcmlhYmxlKFNfQkxFTkRfQ09MT1IsICdibGVuZENvbG9yJywgWzAsIDAsIDAsIDBdKTtcbiAgc3RhdGVWYXJpYWJsZShTX0JMRU5EX0VRVUFUSU9OLCAnYmxlbmRFcXVhdGlvblNlcGFyYXRlJyxcbiAgICBbR0xfRlVOQ19BREQsIEdMX0ZVTkNfQUREXSk7XG4gIHN0YXRlVmFyaWFibGUoU19CTEVORF9GVU5DLCAnYmxlbmRGdW5jU2VwYXJhdGUnLFxuICAgIFtHTF9PTkUsIEdMX1pFUk8sIEdMX09ORSwgR0xfWkVST10pO1xuXG4gIC8vIERlcHRoXG4gIHN0YXRlRmxhZyhTX0RFUFRIX0VOQUJMRSwgR0xfREVQVEhfVEVTVCwgdHJ1ZSk7XG4gIHN0YXRlVmFyaWFibGUoU19ERVBUSF9GVU5DLCAnZGVwdGhGdW5jJywgR0xfTEVTUyk7XG4gIHN0YXRlVmFyaWFibGUoU19ERVBUSF9SQU5HRSwgJ2RlcHRoUmFuZ2UnLCBbMCwgMV0pO1xuICBzdGF0ZVZhcmlhYmxlKFNfREVQVEhfTUFTSywgJ2RlcHRoTWFzaycsIHRydWUpO1xuXG4gIC8vIENvbG9yIG1hc2tcbiAgc3RhdGVWYXJpYWJsZShTX0NPTE9SX01BU0ssIFNfQ09MT1JfTUFTSywgW3RydWUsIHRydWUsIHRydWUsIHRydWVdKTtcblxuICAvLyBGYWNlIGN1bGxpbmdcbiAgc3RhdGVGbGFnKFNfQ1VMTF9FTkFCTEUsIEdMX0NVTExfRkFDRSk7XG4gIHN0YXRlVmFyaWFibGUoU19DVUxMX0ZBQ0UsICdjdWxsRmFjZScsIEdMX0JBQ0spO1xuXG4gIC8vIEZyb250IGZhY2Ugb3JpZW50YXRpb25cbiAgc3RhdGVWYXJpYWJsZShTX0ZST05UX0ZBQ0UsIFNfRlJPTlRfRkFDRSwgR0xfQ0NXKTtcblxuICAvLyBMaW5lIHdpZHRoXG4gIHN0YXRlVmFyaWFibGUoU19MSU5FX1dJRFRILCBTX0xJTkVfV0lEVEgsIDEpO1xuXG4gIC8vIFBvbHlnb24gb2Zmc2V0XG4gIHN0YXRlRmxhZyhTX1BPTFlHT05fT0ZGU0VUX0VOQUJMRSwgR0xfUE9MWUdPTl9PRkZTRVRfRklMTCk7XG4gIHN0YXRlVmFyaWFibGUoU19QT0xZR09OX09GRlNFVF9PRkZTRVQsICdwb2x5Z29uT2Zmc2V0JywgWzAsIDBdKTtcblxuICAvLyBTYW1wbGUgY292ZXJhZ2VcbiAgc3RhdGVGbGFnKFNfU0FNUExFX0FMUEhBLCBHTF9TQU1QTEVfQUxQSEFfVE9fQ09WRVJBR0UpO1xuICBzdGF0ZUZsYWcoU19TQU1QTEVfRU5BQkxFLCBHTF9TQU1QTEVfQ09WRVJBR0UpO1xuICBzdGF0ZVZhcmlhYmxlKFNfU0FNUExFX0NPVkVSQUdFLCAnc2FtcGxlQ292ZXJhZ2UnLCBbMSwgZmFsc2VdKTtcblxuICAvLyBTdGVuY2lsXG4gIHN0YXRlRmxhZyhTX1NURU5DSUxfRU5BQkxFLCBHTF9TVEVOQ0lMX1RFU1QpO1xuICBzdGF0ZVZhcmlhYmxlKFNfU1RFTkNJTF9NQVNLLCAnc3RlbmNpbE1hc2snLCAtMSk7XG4gIHN0YXRlVmFyaWFibGUoU19TVEVOQ0lMX0ZVTkMsICdzdGVuY2lsRnVuYycsIFtHTF9BTFdBWVMsIDAsIC0xXSk7XG4gIHN0YXRlVmFyaWFibGUoU19TVEVOQ0lMX09QRlJPTlQsICdzdGVuY2lsT3BTZXBhcmF0ZScsXG4gICAgW0dMX0ZST05ULCBHTF9LRUVQLCBHTF9LRUVQLCBHTF9LRUVQXSk7XG4gIHN0YXRlVmFyaWFibGUoU19TVEVOQ0lMX09QQkFDSywgJ3N0ZW5jaWxPcFNlcGFyYXRlJyxcbiAgICBbR0xfQkFDSywgR0xfS0VFUCwgR0xfS0VFUCwgR0xfS0VFUF0pO1xuXG4gIC8vIFNjaXNzb3JcbiAgc3RhdGVGbGFnKFNfU0NJU1NPUl9FTkFCTEUsIEdMX1NDSVNTT1JfVEVTVCk7XG4gIHN0YXRlVmFyaWFibGUoU19TQ0lTU09SX0JPWCwgJ3NjaXNzb3InLFxuICAgIFswLCAwLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdKTtcblxuICAvLyBWaWV3cG9ydFxuICBzdGF0ZVZhcmlhYmxlKFNfVklFV1BPUlQsIFNfVklFV1BPUlQsXG4gICAgWzAsIDAsIGdsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0pO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gRU5WSVJPTk1FTlRcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICB2YXIgc2hhcmVkU3RhdGUgPSB7XG4gICAgZ2w6IGdsLFxuICAgIGNvbnRleHQ6IGNvbnRleHRTdGF0ZSxcbiAgICBzdHJpbmdzOiBzdHJpbmdTdG9yZSxcbiAgICBuZXh0OiBuZXh0U3RhdGUsXG4gICAgY3VycmVudDogY3VycmVudFN0YXRlLFxuICAgIGRyYXc6IGRyYXdTdGF0ZSxcbiAgICBlbGVtZW50czogZWxlbWVudFN0YXRlLFxuICAgIGJ1ZmZlcjogYnVmZmVyU3RhdGUsXG4gICAgc2hhZGVyOiBzaGFkZXJTdGF0ZSxcbiAgICBhdHRyaWJ1dGVzOiBhdHRyaWJ1dGVTdGF0ZS5zdGF0ZSxcbiAgICB1bmlmb3JtczogdW5pZm9ybVN0YXRlLFxuICAgIGZyYW1lYnVmZmVyOiBmcmFtZWJ1ZmZlclN0YXRlLFxuICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnMsXG5cbiAgICB0aW1lcjogdGltZXIsXG4gICAgaXNCdWZmZXJBcmdzOiBpc0J1ZmZlckFyZ3NcbiAgfTtcblxuICB2YXIgc2hhcmVkQ29uc3RhbnRzID0ge1xuICAgIHByaW1UeXBlczogcHJpbVR5cGVzLFxuICAgIGNvbXBhcmVGdW5jczogY29tcGFyZUZ1bmNzLFxuICAgIGJsZW5kRnVuY3M6IGJsZW5kRnVuY3MsXG4gICAgYmxlbmRFcXVhdGlvbnM6IGJsZW5kRXF1YXRpb25zLFxuICAgIHN0ZW5jaWxPcHM6IHN0ZW5jaWxPcHMsXG4gICAgZ2xUeXBlczogZ2xUeXBlcyxcbiAgICBvcmllbnRhdGlvblR5cGU6IG9yaWVudGF0aW9uVHlwZVxuICB9O1xuXG4gIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgIHNoYXJlZFN0YXRlLmlzQXJyYXlMaWtlID0gaXNBcnJheUxpa2U7XG4gIH0pO1xuXG4gIGlmIChleHREcmF3QnVmZmVycykge1xuICAgIHNoYXJlZENvbnN0YW50cy5iYWNrQnVmZmVyID0gW0dMX0JBQ0tdO1xuICAgIHNoYXJlZENvbnN0YW50cy5kcmF3QnVmZmVyID0gbG9vcChsaW1pdHMubWF4RHJhd2J1ZmZlcnMsIGZ1bmN0aW9uIChpKSB7XG4gICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICByZXR1cm4gWzBdXG4gICAgICB9XG4gICAgICByZXR1cm4gbG9vcChpLCBmdW5jdGlvbiAoaikge1xuICAgICAgICByZXR1cm4gR0xfQ09MT1JfQVRUQUNITUVOVDAkMiArIGpcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cblxuICB2YXIgZHJhd0NhbGxDb3VudGVyID0gMDtcbiAgZnVuY3Rpb24gY3JlYXRlUkVHTEVudmlyb25tZW50ICgpIHtcbiAgICB2YXIgZW52ID0gY3JlYXRlRW52aXJvbm1lbnQoKTtcbiAgICB2YXIgbGluayA9IGVudi5saW5rO1xuICAgIHZhciBnbG9iYWwgPSBlbnYuZ2xvYmFsO1xuICAgIGVudi5pZCA9IGRyYXdDYWxsQ291bnRlcisrO1xuXG4gICAgZW52LmJhdGNoSWQgPSAnMCc7XG5cbiAgICAvLyBsaW5rIHNoYXJlZCBzdGF0ZVxuICAgIHZhciBTSEFSRUQgPSBsaW5rKHNoYXJlZFN0YXRlKTtcbiAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZCA9IHtcbiAgICAgIHByb3BzOiAnYTAnXG4gICAgfTtcbiAgICBPYmplY3Qua2V5cyhzaGFyZWRTdGF0ZSkuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgc2hhcmVkW3Byb3BdID0gZ2xvYmFsLmRlZihTSEFSRUQsICcuJywgcHJvcCk7XG4gICAgfSk7XG5cbiAgICAvLyBJbmplY3QgcnVudGltZSBhc3NlcnRpb24gc3R1ZmYgZm9yIGRlYnVnIGJ1aWxkc1xuICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgZW52LkNIRUNLID0gbGluayhjaGVjayQxKTtcbiAgICAgIGVudi5jb21tYW5kU3RyID0gY2hlY2skMS5ndWVzc0NvbW1hbmQoKTtcbiAgICAgIGVudi5jb21tYW5kID0gbGluayhlbnYuY29tbWFuZFN0cik7XG4gICAgICBlbnYuYXNzZXJ0ID0gZnVuY3Rpb24gKGJsb2NrLCBwcmVkLCBtZXNzYWdlKSB7XG4gICAgICAgIGJsb2NrKFxuICAgICAgICAgICdpZighKCcsIHByZWQsICcpKScsXG4gICAgICAgICAgdGhpcy5DSEVDSywgJy5jb21tYW5kUmFpc2UoJywgbGluayhtZXNzYWdlKSwgJywnLCB0aGlzLmNvbW1hbmQsICcpOycpO1xuICAgICAgfTtcblxuICAgICAgc2hhcmVkQ29uc3RhbnRzLmludmFsaWRCbGVuZENvbWJpbmF0aW9ucyA9IGludmFsaWRCbGVuZENvbWJpbmF0aW9ucztcbiAgICB9KTtcblxuICAgIC8vIENvcHkgR0wgc3RhdGUgdmFyaWFibGVzIG92ZXJcbiAgICB2YXIgbmV4dFZhcnMgPSBlbnYubmV4dCA9IHt9O1xuICAgIHZhciBjdXJyZW50VmFycyA9IGVudi5jdXJyZW50ID0ge307XG4gICAgT2JqZWN0LmtleXMoR0xfVkFSSUFCTEVTKS5mb3JFYWNoKGZ1bmN0aW9uICh2YXJpYWJsZSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY3VycmVudFN0YXRlW3ZhcmlhYmxlXSkpIHtcbiAgICAgICAgbmV4dFZhcnNbdmFyaWFibGVdID0gZ2xvYmFsLmRlZihzaGFyZWQubmV4dCwgJy4nLCB2YXJpYWJsZSk7XG4gICAgICAgIGN1cnJlbnRWYXJzW3ZhcmlhYmxlXSA9IGdsb2JhbC5kZWYoc2hhcmVkLmN1cnJlbnQsICcuJywgdmFyaWFibGUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFyZWQgY29uc3RhbnRzXG4gICAgdmFyIGNvbnN0YW50cyA9IGVudi5jb25zdGFudHMgPSB7fTtcbiAgICBPYmplY3Qua2V5cyhzaGFyZWRDb25zdGFudHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgIGNvbnN0YW50c1tuYW1lXSA9IGdsb2JhbC5kZWYoSlNPTi5zdHJpbmdpZnkoc2hhcmVkQ29uc3RhbnRzW25hbWVdKSk7XG4gICAgfSk7XG5cbiAgICAvLyBIZWxwZXIgZnVuY3Rpb24gZm9yIGNhbGxpbmcgYSBibG9ja1xuICAgIGVudi5pbnZva2UgPSBmdW5jdGlvbiAoYmxvY2ssIHgpIHtcbiAgICAgIHN3aXRjaCAoeC50eXBlKSB7XG4gICAgICAgIGNhc2UgRFlOX0ZVTkMkMTpcbiAgICAgICAgICB2YXIgYXJnTGlzdCA9IFtcbiAgICAgICAgICAgICd0aGlzJyxcbiAgICAgICAgICAgIHNoYXJlZC5jb250ZXh0LFxuICAgICAgICAgICAgc2hhcmVkLnByb3BzLFxuICAgICAgICAgICAgZW52LmJhdGNoSWRcbiAgICAgICAgICBdO1xuICAgICAgICAgIHJldHVybiBibG9jay5kZWYoXG4gICAgICAgICAgICBsaW5rKHguZGF0YSksICcuY2FsbCgnLFxuICAgICAgICAgICAgICBhcmdMaXN0LnNsaWNlKDAsIE1hdGgubWF4KHguZGF0YS5sZW5ndGggKyAxLCA0KSksXG4gICAgICAgICAgICAgJyknKVxuICAgICAgICBjYXNlIERZTl9QUk9QJDE6XG4gICAgICAgICAgcmV0dXJuIGJsb2NrLmRlZihzaGFyZWQucHJvcHMsIHguZGF0YSlcbiAgICAgICAgY2FzZSBEWU5fQ09OVEVYVCQxOlxuICAgICAgICAgIHJldHVybiBibG9jay5kZWYoc2hhcmVkLmNvbnRleHQsIHguZGF0YSlcbiAgICAgICAgY2FzZSBEWU5fU1RBVEUkMTpcbiAgICAgICAgICByZXR1cm4gYmxvY2suZGVmKCd0aGlzJywgeC5kYXRhKVxuICAgICAgICBjYXNlIERZTl9USFVOSzpcbiAgICAgICAgICB4LmRhdGEuYXBwZW5kKGVudiwgYmxvY2spO1xuICAgICAgICAgIHJldHVybiB4LmRhdGEucmVmXG4gICAgICB9XG4gICAgfTtcblxuICAgIGVudi5hdHRyaWJDYWNoZSA9IHt9O1xuXG4gICAgdmFyIHNjb3BlQXR0cmlicyA9IHt9O1xuICAgIGVudi5zY29wZUF0dHJpYiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICB2YXIgaWQgPSBzdHJpbmdTdG9yZS5pZChuYW1lKTtcbiAgICAgIGlmIChpZCBpbiBzY29wZUF0dHJpYnMpIHtcbiAgICAgICAgcmV0dXJuIHNjb3BlQXR0cmlic1tpZF1cbiAgICAgIH1cbiAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlU3RhdGUuc2NvcGVbaWRdO1xuICAgICAgaWYgKCFiaW5kaW5nKSB7XG4gICAgICAgIGJpbmRpbmcgPSBhdHRyaWJ1dGVTdGF0ZS5zY29wZVtpZF0gPSBuZXcgQXR0cmlidXRlUmVjb3JkKCk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gc2NvcGVBdHRyaWJzW2lkXSA9IGxpbmsoYmluZGluZyk7XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfTtcblxuICAgIHJldHVybiBlbnZcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUEFSU0lOR1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGZ1bmN0aW9uIHBhcnNlUHJvZmlsZSAob3B0aW9ucykge1xuICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuXG4gICAgdmFyIHByb2ZpbGVFbmFibGU7XG4gICAgaWYgKFNfUFJPRklMRSBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICB2YXIgdmFsdWUgPSAhIXN0YXRpY09wdGlvbnNbU19QUk9GSUxFXTtcbiAgICAgIHByb2ZpbGVFbmFibGUgPSBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgfSk7XG4gICAgICBwcm9maWxlRW5hYmxlLmVuYWJsZSA9IHZhbHVlO1xuICAgIH0gZWxzZSBpZiAoU19QUk9GSUxFIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICB2YXIgZHluID0gZHluYW1pY09wdGlvbnNbU19QUk9GSUxFXTtcbiAgICAgIHByb2ZpbGVFbmFibGUgPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgIHJldHVybiBlbnYuaW52b2tlKHNjb3BlLCBkeW4pXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvZmlsZUVuYWJsZVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VGcmFtZWJ1ZmZlciAob3B0aW9ucywgZW52KSB7XG4gICAgdmFyIHN0YXRpY09wdGlvbnMgPSBvcHRpb25zLnN0YXRpYztcbiAgICB2YXIgZHluYW1pY09wdGlvbnMgPSBvcHRpb25zLmR5bmFtaWM7XG5cbiAgICBpZiAoU19GUkFNRUJVRkZFUiBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICB2YXIgZnJhbWVidWZmZXIgPSBzdGF0aWNPcHRpb25zW1NfRlJBTUVCVUZGRVJdO1xuICAgICAgaWYgKGZyYW1lYnVmZmVyKSB7XG4gICAgICAgIGZyYW1lYnVmZmVyID0gZnJhbWVidWZmZXJTdGF0ZS5nZXRGcmFtZWJ1ZmZlcihmcmFtZWJ1ZmZlcik7XG4gICAgICAgIGNoZWNrJDEuY29tbWFuZChmcmFtZWJ1ZmZlciwgJ2ludmFsaWQgZnJhbWVidWZmZXIgb2JqZWN0Jyk7XG4gICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIGJsb2NrKSB7XG4gICAgICAgICAgdmFyIEZSQU1FQlVGRkVSID0gZW52LmxpbmsoZnJhbWVidWZmZXIpO1xuICAgICAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgICAgIGJsb2NrLnNldChcbiAgICAgICAgICAgIHNoYXJlZC5mcmFtZWJ1ZmZlcixcbiAgICAgICAgICAgICcubmV4dCcsXG4gICAgICAgICAgICBGUkFNRUJVRkZFUik7XG4gICAgICAgICAgdmFyIENPTlRFWFQgPSBzaGFyZWQuY29udGV4dDtcbiAgICAgICAgICBibG9jay5zZXQoXG4gICAgICAgICAgICBDT05URVhULFxuICAgICAgICAgICAgJy4nICsgU19GUkFNRUJVRkZFUl9XSURUSCxcbiAgICAgICAgICAgIEZSQU1FQlVGRkVSICsgJy53aWR0aCcpO1xuICAgICAgICAgIGJsb2NrLnNldChcbiAgICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgICAnLicgKyBTX0ZSQU1FQlVGRkVSX0hFSUdIVCxcbiAgICAgICAgICAgIEZSQU1FQlVGRkVSICsgJy5oZWlnaHQnKTtcbiAgICAgICAgICByZXR1cm4gRlJBTUVCVUZGRVJcbiAgICAgICAgfSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgICAgICAgc2NvcGUuc2V0KFxuICAgICAgICAgICAgc2hhcmVkLmZyYW1lYnVmZmVyLFxuICAgICAgICAgICAgJy5uZXh0JyxcbiAgICAgICAgICAgICdudWxsJyk7XG4gICAgICAgICAgdmFyIENPTlRFWFQgPSBzaGFyZWQuY29udGV4dDtcbiAgICAgICAgICBzY29wZS5zZXQoXG4gICAgICAgICAgICBDT05URVhULFxuICAgICAgICAgICAgJy4nICsgU19GUkFNRUJVRkZFUl9XSURUSCxcbiAgICAgICAgICAgIENPTlRFWFQgKyAnLicgKyBTX0RSQVdJTkdCVUZGRVJfV0lEVEgpO1xuICAgICAgICAgIHNjb3BlLnNldChcbiAgICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgICAnLicgKyBTX0ZSQU1FQlVGRkVSX0hFSUdIVCxcbiAgICAgICAgICAgIENPTlRFWFQgKyAnLicgKyBTX0RSQVdJTkdCVUZGRVJfSEVJR0hUKTtcbiAgICAgICAgICByZXR1cm4gJ251bGwnXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChTX0ZSQU1FQlVGRkVSIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICB2YXIgZHluID0gZHluYW1pY09wdGlvbnNbU19GUkFNRUJVRkZFUl07XG4gICAgICByZXR1cm4gY3JlYXRlRHluYW1pY0RlY2woZHluLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICB2YXIgRlJBTUVCVUZGRVJfRlVOQyA9IGVudi5pbnZva2Uoc2NvcGUsIGR5bik7XG4gICAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgICB2YXIgRlJBTUVCVUZGRVJfU1RBVEUgPSBzaGFyZWQuZnJhbWVidWZmZXI7XG4gICAgICAgIHZhciBGUkFNRUJVRkZFUiA9IHNjb3BlLmRlZihcbiAgICAgICAgICBGUkFNRUJVRkZFUl9TVEFURSwgJy5nZXRGcmFtZWJ1ZmZlcignLCBGUkFNRUJVRkZFUl9GVU5DLCAnKScpO1xuXG4gICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAnIScgKyBGUkFNRUJVRkZFUl9GVU5DICsgJ3x8JyArIEZSQU1FQlVGRkVSLFxuICAgICAgICAgICAgJ2ludmFsaWQgZnJhbWVidWZmZXIgb2JqZWN0Jyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNjb3BlLnNldChcbiAgICAgICAgICBGUkFNRUJVRkZFUl9TVEFURSxcbiAgICAgICAgICAnLm5leHQnLFxuICAgICAgICAgIEZSQU1FQlVGRkVSKTtcbiAgICAgICAgdmFyIENPTlRFWFQgPSBzaGFyZWQuY29udGV4dDtcbiAgICAgICAgc2NvcGUuc2V0KFxuICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgJy4nICsgU19GUkFNRUJVRkZFUl9XSURUSCxcbiAgICAgICAgICBGUkFNRUJVRkZFUiArICc/JyArIEZSQU1FQlVGRkVSICsgJy53aWR0aDonICtcbiAgICAgICAgICBDT05URVhUICsgJy4nICsgU19EUkFXSU5HQlVGRkVSX1dJRFRIKTtcbiAgICAgICAgc2NvcGUuc2V0KFxuICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgJy4nICsgU19GUkFNRUJVRkZFUl9IRUlHSFQsXG4gICAgICAgICAgRlJBTUVCVUZGRVIgK1xuICAgICAgICAgICc/JyArIEZSQU1FQlVGRkVSICsgJy5oZWlnaHQ6JyArXG4gICAgICAgICAgQ09OVEVYVCArICcuJyArIFNfRFJBV0lOR0JVRkZFUl9IRUlHSFQpO1xuICAgICAgICByZXR1cm4gRlJBTUVCVUZGRVJcbiAgICAgIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VWaWV3cG9ydFNjaXNzb3IgKG9wdGlvbnMsIGZyYW1lYnVmZmVyLCBlbnYpIHtcbiAgICB2YXIgc3RhdGljT3B0aW9ucyA9IG9wdGlvbnMuc3RhdGljO1xuICAgIHZhciBkeW5hbWljT3B0aW9ucyA9IG9wdGlvbnMuZHluYW1pYztcblxuICAgIGZ1bmN0aW9uIHBhcnNlQm94IChwYXJhbSkge1xuICAgICAgaWYgKHBhcmFtIGluIHN0YXRpY09wdGlvbnMpIHtcbiAgICAgICAgdmFyIGJveCA9IHN0YXRpY09wdGlvbnNbcGFyYW1dO1xuICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKGJveCwgJ29iamVjdCcsICdpbnZhbGlkICcgKyBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuXG4gICAgICAgIHZhciBpc1N0YXRpYyA9IHRydWU7XG4gICAgICAgIHZhciB4ID0gYm94LnggfCAwO1xuICAgICAgICB2YXIgeSA9IGJveC55IHwgMDtcbiAgICAgICAgdmFyIHcsIGg7XG4gICAgICAgIGlmICgnd2lkdGgnIGluIGJveCkge1xuICAgICAgICAgIHcgPSBib3gud2lkdGggfCAwO1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh3ID49IDAsICdpbnZhbGlkICcgKyBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlzU3RhdGljID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdoZWlnaHQnIGluIGJveCkge1xuICAgICAgICAgIGggPSBib3guaGVpZ2h0IHwgMDtcbiAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoaCA+PSAwLCAnaW52YWxpZCAnICsgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpc1N0YXRpYyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihcbiAgICAgICAgICAhaXNTdGF0aWMgJiYgZnJhbWVidWZmZXIgJiYgZnJhbWVidWZmZXIudGhpc0RlcCxcbiAgICAgICAgICAhaXNTdGF0aWMgJiYgZnJhbWVidWZmZXIgJiYgZnJhbWVidWZmZXIuY29udGV4dERlcCxcbiAgICAgICAgICAhaXNTdGF0aWMgJiYgZnJhbWVidWZmZXIgJiYgZnJhbWVidWZmZXIucHJvcERlcCxcbiAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIENPTlRFWFQgPSBlbnYuc2hhcmVkLmNvbnRleHQ7XG4gICAgICAgICAgICB2YXIgQk9YX1cgPSB3O1xuICAgICAgICAgICAgaWYgKCEoJ3dpZHRoJyBpbiBib3gpKSB7XG4gICAgICAgICAgICAgIEJPWF9XID0gc2NvcGUuZGVmKENPTlRFWFQsICcuJywgU19GUkFNRUJVRkZFUl9XSURUSCwgJy0nLCB4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBCT1hfSCA9IGg7XG4gICAgICAgICAgICBpZiAoISgnaGVpZ2h0JyBpbiBib3gpKSB7XG4gICAgICAgICAgICAgIEJPWF9IID0gc2NvcGUuZGVmKENPTlRFWFQsICcuJywgU19GUkFNRUJVRkZFUl9IRUlHSFQsICctJywgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW3gsIHksIEJPWF9XLCBCT1hfSF1cbiAgICAgICAgICB9KVxuICAgICAgfSBlbHNlIGlmIChwYXJhbSBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICB2YXIgZHluQm94ID0gZHluYW1pY09wdGlvbnNbcGFyYW1dO1xuICAgICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlRHluYW1pY0RlY2woZHluQm94LCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgIHZhciBCT1ggPSBlbnYuaW52b2tlKHNjb3BlLCBkeW5Cb3gpO1xuXG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICBCT1ggKyAnJiZ0eXBlb2YgJyArIEJPWCArICc9PT1cIm9iamVjdFwiJyxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgJyArIHBhcmFtKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHZhciBDT05URVhUID0gZW52LnNoYXJlZC5jb250ZXh0O1xuICAgICAgICAgIHZhciBCT1hfWCA9IHNjb3BlLmRlZihCT1gsICcueHwwJyk7XG4gICAgICAgICAgdmFyIEJPWF9ZID0gc2NvcGUuZGVmKEJPWCwgJy55fDAnKTtcbiAgICAgICAgICB2YXIgQk9YX1cgPSBzY29wZS5kZWYoXG4gICAgICAgICAgICAnXCJ3aWR0aFwiIGluICcsIEJPWCwgJz8nLCBCT1gsICcud2lkdGh8MDonLFxuICAgICAgICAgICAgJygnLCBDT05URVhULCAnLicsIFNfRlJBTUVCVUZGRVJfV0lEVEgsICctJywgQk9YX1gsICcpJyk7XG4gICAgICAgICAgdmFyIEJPWF9IID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgJ1wiaGVpZ2h0XCIgaW4gJywgQk9YLCAnPycsIEJPWCwgJy5oZWlnaHR8MDonLFxuICAgICAgICAgICAgJygnLCBDT05URVhULCAnLicsIFNfRlJBTUVCVUZGRVJfSEVJR0hULCAnLScsIEJPWF9ZLCAnKScpO1xuXG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICBCT1hfVyArICc+PTAmJicgK1xuICAgICAgICAgICAgICBCT1hfSCArICc+PTAnLFxuICAgICAgICAgICAgICAnaW52YWxpZCAnICsgcGFyYW0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuIFtCT1hfWCwgQk9YX1ksIEJPWF9XLCBCT1hfSF1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChmcmFtZWJ1ZmZlcikge1xuICAgICAgICAgIHJlc3VsdC50aGlzRGVwID0gcmVzdWx0LnRoaXNEZXAgfHwgZnJhbWVidWZmZXIudGhpc0RlcDtcbiAgICAgICAgICByZXN1bHQuY29udGV4dERlcCA9IHJlc3VsdC5jb250ZXh0RGVwIHx8IGZyYW1lYnVmZmVyLmNvbnRleHREZXA7XG4gICAgICAgICAgcmVzdWx0LnByb3BEZXAgPSByZXN1bHQucHJvcERlcCB8fCBmcmFtZWJ1ZmZlci5wcm9wRGVwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgIH0gZWxzZSBpZiAoZnJhbWVidWZmZXIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihcbiAgICAgICAgICBmcmFtZWJ1ZmZlci50aGlzRGVwLFxuICAgICAgICAgIGZyYW1lYnVmZmVyLmNvbnRleHREZXAsXG4gICAgICAgICAgZnJhbWVidWZmZXIucHJvcERlcCxcbiAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgdmFyIENPTlRFWFQgPSBlbnYuc2hhcmVkLmNvbnRleHQ7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAwLCAwLFxuICAgICAgICAgICAgICBzY29wZS5kZWYoQ09OVEVYVCwgJy4nLCBTX0ZSQU1FQlVGRkVSX1dJRFRIKSxcbiAgICAgICAgICAgICAgc2NvcGUuZGVmKENPTlRFWFQsICcuJywgU19GUkFNRUJVRkZFUl9IRUlHSFQpXVxuICAgICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciB2aWV3cG9ydCA9IHBhcnNlQm94KFNfVklFV1BPUlQpO1xuXG4gICAgaWYgKHZpZXdwb3J0KSB7XG4gICAgICB2YXIgcHJldlZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgICB2aWV3cG9ydCA9IG5ldyBEZWNsYXJhdGlvbihcbiAgICAgICAgdmlld3BvcnQudGhpc0RlcCxcbiAgICAgICAgdmlld3BvcnQuY29udGV4dERlcCxcbiAgICAgICAgdmlld3BvcnQucHJvcERlcCxcbiAgICAgICAgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2YXIgVklFV1BPUlQgPSBwcmV2Vmlld3BvcnQuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgICAgIHZhciBDT05URVhUID0gZW52LnNoYXJlZC5jb250ZXh0O1xuICAgICAgICAgIHNjb3BlLnNldChcbiAgICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgICAnLicgKyBTX1ZJRVdQT1JUX1dJRFRILFxuICAgICAgICAgICAgVklFV1BPUlRbMl0pO1xuICAgICAgICAgIHNjb3BlLnNldChcbiAgICAgICAgICAgIENPTlRFWFQsXG4gICAgICAgICAgICAnLicgKyBTX1ZJRVdQT1JUX0hFSUdIVCxcbiAgICAgICAgICAgIFZJRVdQT1JUWzNdKTtcbiAgICAgICAgICByZXR1cm4gVklFV1BPUlRcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZpZXdwb3J0OiB2aWV3cG9ydCxcbiAgICAgIHNjaXNzb3JfYm94OiBwYXJzZUJveChTX1NDSVNTT1JfQk9YKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlUHJvZ3JhbSAob3B0aW9ucykge1xuICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuXG4gICAgZnVuY3Rpb24gcGFyc2VTaGFkZXIgKG5hbWUpIHtcbiAgICAgIGlmIChuYW1lIGluIHN0YXRpY09wdGlvbnMpIHtcbiAgICAgICAgdmFyIGlkID0gc3RyaW5nU3RvcmUuaWQoc3RhdGljT3B0aW9uc1tuYW1lXSk7XG4gICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHNoYWRlclN0YXRlLnNoYWRlcihzaGFkZXJUeXBlW25hbWVdLCBpZCwgY2hlY2skMS5ndWVzc0NvbW1hbmQoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGlkXG4gICAgICAgIH0pO1xuICAgICAgICByZXN1bHQuaWQgPSBpZDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgfSBlbHNlIGlmIChuYW1lIGluIGR5bmFtaWNPcHRpb25zKSB7XG4gICAgICAgIHZhciBkeW4gPSBkeW5hbWljT3B0aW9uc1tuYW1lXTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR5bmFtaWNEZWNsKGR5biwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2YXIgc3RyID0gZW52Lmludm9rZShzY29wZSwgZHluKTtcbiAgICAgICAgICB2YXIgaWQgPSBzY29wZS5kZWYoZW52LnNoYXJlZC5zdHJpbmdzLCAnLmlkKCcsIHN0ciwgJyknKTtcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNjb3BlKFxuICAgICAgICAgICAgICBlbnYuc2hhcmVkLnNoYWRlciwgJy5zaGFkZXIoJyxcbiAgICAgICAgICAgICAgc2hhZGVyVHlwZVtuYW1lXSwgJywnLFxuICAgICAgICAgICAgICBpZCwgJywnLFxuICAgICAgICAgICAgICBlbnYuY29tbWFuZCwgJyk7Jyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIGlkXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cblxuICAgIHZhciBmcmFnID0gcGFyc2VTaGFkZXIoU19GUkFHKTtcbiAgICB2YXIgdmVydCA9IHBhcnNlU2hhZGVyKFNfVkVSVCk7XG5cbiAgICB2YXIgcHJvZ3JhbSA9IG51bGw7XG4gICAgdmFyIHByb2dWYXI7XG4gICAgaWYgKGlzU3RhdGljKGZyYWcpICYmIGlzU3RhdGljKHZlcnQpKSB7XG4gICAgICBwcm9ncmFtID0gc2hhZGVyU3RhdGUucHJvZ3JhbSh2ZXJ0LmlkLCBmcmFnLmlkKTtcbiAgICAgIHByb2dWYXIgPSBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgIHJldHVybiBlbnYubGluayhwcm9ncmFtKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2dWYXIgPSBuZXcgRGVjbGFyYXRpb24oXG4gICAgICAgIChmcmFnICYmIGZyYWcudGhpc0RlcCkgfHwgKHZlcnQgJiYgdmVydC50aGlzRGVwKSxcbiAgICAgICAgKGZyYWcgJiYgZnJhZy5jb250ZXh0RGVwKSB8fCAodmVydCAmJiB2ZXJ0LmNvbnRleHREZXApLFxuICAgICAgICAoZnJhZyAmJiBmcmFnLnByb3BEZXApIHx8ICh2ZXJ0ICYmIHZlcnQucHJvcERlcCksXG4gICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgdmFyIFNIQURFUl9TVEFURSA9IGVudi5zaGFyZWQuc2hhZGVyO1xuICAgICAgICAgIHZhciBmcmFnSWQ7XG4gICAgICAgICAgaWYgKGZyYWcpIHtcbiAgICAgICAgICAgIGZyYWdJZCA9IGZyYWcuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcmFnSWQgPSBzY29wZS5kZWYoU0hBREVSX1NUQVRFLCAnLicsIFNfRlJBRyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciB2ZXJ0SWQ7XG4gICAgICAgICAgaWYgKHZlcnQpIHtcbiAgICAgICAgICAgIHZlcnRJZCA9IHZlcnQuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2ZXJ0SWQgPSBzY29wZS5kZWYoU0hBREVSX1NUQVRFLCAnLicsIFNfVkVSVCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBwcm9nRGVmID0gU0hBREVSX1NUQVRFICsgJy5wcm9ncmFtKCcgKyB2ZXJ0SWQgKyAnLCcgKyBmcmFnSWQ7XG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwcm9nRGVmICs9ICcsJyArIGVudi5jb21tYW5kO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBzY29wZS5kZWYocHJvZ0RlZiArICcpJylcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZyYWc6IGZyYWcsXG4gICAgICB2ZXJ0OiB2ZXJ0LFxuICAgICAgcHJvZ1ZhcjogcHJvZ1ZhcixcbiAgICAgIHByb2dyYW06IHByb2dyYW1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZURyYXcgKG9wdGlvbnMsIGVudikge1xuICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuXG4gICAgZnVuY3Rpb24gcGFyc2VFbGVtZW50cyAoKSB7XG4gICAgICBpZiAoU19FTEVNRU5UUyBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgIHZhciBlbGVtZW50cyA9IHN0YXRpY09wdGlvbnNbU19FTEVNRU5UU107XG4gICAgICAgIGlmIChpc0J1ZmZlckFyZ3MoZWxlbWVudHMpKSB7XG4gICAgICAgICAgZWxlbWVudHMgPSBlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHMoZWxlbWVudFN0YXRlLmNyZWF0ZShlbGVtZW50cywgdHJ1ZSkpO1xuICAgICAgICB9IGVsc2UgaWYgKGVsZW1lbnRzKSB7XG4gICAgICAgICAgZWxlbWVudHMgPSBlbGVtZW50U3RhdGUuZ2V0RWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChlbGVtZW50cywgJ2ludmFsaWQgZWxlbWVudHMnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICBpZiAoZWxlbWVudHMpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBlbnYubGluayhlbGVtZW50cyk7XG4gICAgICAgICAgICBlbnYuRUxFTUVOVFMgPSByZXN1bHQ7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICAgICAgfVxuICAgICAgICAgIGVudi5FTEVNRU5UUyA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC52YWx1ZSA9IGVsZW1lbnRzO1xuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICB9IGVsc2UgaWYgKFNfRUxFTUVOVFMgaW4gZHluYW1pY09wdGlvbnMpIHtcbiAgICAgICAgdmFyIGR5biA9IGR5bmFtaWNPcHRpb25zW1NfRUxFTUVOVFNdO1xuICAgICAgICByZXR1cm4gY3JlYXRlRHluYW1pY0RlY2woZHluLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuXG4gICAgICAgICAgdmFyIElTX0JVRkZFUl9BUkdTID0gc2hhcmVkLmlzQnVmZmVyQXJncztcbiAgICAgICAgICB2YXIgRUxFTUVOVF9TVEFURSA9IHNoYXJlZC5lbGVtZW50cztcblxuICAgICAgICAgIHZhciBlbGVtZW50RGVmbiA9IGVudi5pbnZva2Uoc2NvcGUsIGR5bik7XG4gICAgICAgICAgdmFyIGVsZW1lbnRzID0gc2NvcGUuZGVmKCdudWxsJyk7XG4gICAgICAgICAgdmFyIGVsZW1lbnRTdHJlYW0gPSBzY29wZS5kZWYoSVNfQlVGRkVSX0FSR1MsICcoJywgZWxlbWVudERlZm4sICcpJyk7XG5cbiAgICAgICAgICB2YXIgaWZ0ZSA9IGVudi5jb25kKGVsZW1lbnRTdHJlYW0pXG4gICAgICAgICAgICAudGhlbihlbGVtZW50cywgJz0nLCBFTEVNRU5UX1NUQVRFLCAnLmNyZWF0ZVN0cmVhbSgnLCBlbGVtZW50RGVmbiwgJyk7JylcbiAgICAgICAgICAgIC5lbHNlKGVsZW1lbnRzLCAnPScsIEVMRU1FTlRfU1RBVEUsICcuZ2V0RWxlbWVudHMoJywgZWxlbWVudERlZm4sICcpOycpO1xuXG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBlbnYuYXNzZXJ0KGlmdGUuZWxzZSxcbiAgICAgICAgICAgICAgJyEnICsgZWxlbWVudERlZm4gKyAnfHwnICsgZWxlbWVudHMsXG4gICAgICAgICAgICAgICdpbnZhbGlkIGVsZW1lbnRzJyk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBzY29wZS5lbnRyeShpZnRlKTtcbiAgICAgICAgICBzY29wZS5leGl0KFxuICAgICAgICAgICAgZW52LmNvbmQoZWxlbWVudFN0cmVhbSlcbiAgICAgICAgICAgICAgLnRoZW4oRUxFTUVOVF9TVEFURSwgJy5kZXN0cm95U3RyZWFtKCcsIGVsZW1lbnRzLCAnKTsnKSk7XG5cbiAgICAgICAgICBlbnYuRUxFTUVOVFMgPSBlbGVtZW50cztcblxuICAgICAgICAgIHJldHVybiBlbGVtZW50c1xuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cblxuICAgIHZhciBlbGVtZW50cyA9IHBhcnNlRWxlbWVudHMoKTtcblxuICAgIGZ1bmN0aW9uIHBhcnNlUHJpbWl0aXZlICgpIHtcbiAgICAgIGlmIChTX1BSSU1JVElWRSBpbiBzdGF0aWNPcHRpb25zKSB7XG4gICAgICAgIHZhciBwcmltaXRpdmUgPSBzdGF0aWNPcHRpb25zW1NfUFJJTUlUSVZFXTtcbiAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHByaW1pdGl2ZSwgcHJpbVR5cGVzLCAnaW52YWxpZCBwcmltaXR2ZScsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICByZXR1cm4gcHJpbVR5cGVzW3ByaW1pdGl2ZV1cbiAgICAgICAgfSlcbiAgICAgIH0gZWxzZSBpZiAoU19QUklNSVRJVkUgaW4gZHluYW1pY09wdGlvbnMpIHtcbiAgICAgICAgdmFyIGR5blByaW1pdGl2ZSA9IGR5bmFtaWNPcHRpb25zW1NfUFJJTUlUSVZFXTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR5bmFtaWNEZWNsKGR5blByaW1pdGl2ZSwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2YXIgUFJJTV9UWVBFUyA9IGVudi5jb25zdGFudHMucHJpbVR5cGVzO1xuICAgICAgICAgIHZhciBwcmltID0gZW52Lmludm9rZShzY29wZSwgZHluUHJpbWl0aXZlKTtcbiAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAgIHByaW0gKyAnIGluICcgKyBQUklNX1RZUEVTLFxuICAgICAgICAgICAgICAnaW52YWxpZCBwcmltaXRpdmUsIG11c3QgYmUgb25lIG9mICcgKyBPYmplY3Qua2V5cyhwcmltVHlwZXMpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKFBSSU1fVFlQRVMsICdbJywgcHJpbSwgJ10nKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIGlmIChlbGVtZW50cykge1xuICAgICAgICBpZiAoaXNTdGF0aWMoZWxlbWVudHMpKSB7XG4gICAgICAgICAgaWYgKGVsZW1lbnRzLnZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVudi5FTEVNRU5UUywgJy5wcmltVHlwZScpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHJldHVybiBHTF9UUklBTkdMRVMkMVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBEZWNsYXJhdGlvbihcbiAgICAgICAgICAgIGVsZW1lbnRzLnRoaXNEZXAsXG4gICAgICAgICAgICBlbGVtZW50cy5jb250ZXh0RGVwLFxuICAgICAgICAgICAgZWxlbWVudHMucHJvcERlcCxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgIHZhciBlbGVtZW50cyA9IGVudi5FTEVNRU5UUztcbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbGVtZW50cywgJz8nLCBlbGVtZW50cywgJy5wcmltVHlwZTonLCBHTF9UUklBTkdMRVMkMSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VQYXJhbSAocGFyYW0sIGlzT2Zmc2V0KSB7XG4gICAgICBpZiAocGFyYW0gaW4gc3RhdGljT3B0aW9ucykge1xuICAgICAgICB2YXIgdmFsdWUgPSBzdGF0aWNPcHRpb25zW3BhcmFtXSB8IDA7XG4gICAgICAgIGNoZWNrJDEuY29tbWFuZCghaXNPZmZzZXQgfHwgdmFsdWUgPj0gMCwgJ2ludmFsaWQgJyArIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgIHJldHVybiBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgaWYgKGlzT2Zmc2V0KSB7XG4gICAgICAgICAgICBlbnYuT0ZGU0VUID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIGlmIChwYXJhbSBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICB2YXIgZHluVmFsdWUgPSBkeW5hbWljT3B0aW9uc1twYXJhbV07XG4gICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW5WYWx1ZSwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gZW52Lmludm9rZShzY29wZSwgZHluVmFsdWUpO1xuICAgICAgICAgIGlmIChpc09mZnNldCkge1xuICAgICAgICAgICAgZW52Lk9GRlNFVCA9IHJlc3VsdDtcbiAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgIHJlc3VsdCArICc+PTAnLFxuICAgICAgICAgICAgICAgICdpbnZhbGlkICcgKyBwYXJhbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIGlmIChpc09mZnNldCAmJiBlbGVtZW50cykge1xuICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICAgIGVudi5PRkZTRVQgPSAnMCc7XG4gICAgICAgICAgcmV0dXJuIDBcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgdmFyIE9GRlNFVCA9IHBhcnNlUGFyYW0oU19PRkZTRVQsIHRydWUpO1xuXG4gICAgZnVuY3Rpb24gcGFyc2VWZXJ0Q291bnQgKCkge1xuICAgICAgaWYgKFNfQ09VTlQgaW4gc3RhdGljT3B0aW9ucykge1xuICAgICAgICB2YXIgY291bnQgPSBzdGF0aWNPcHRpb25zW1NfQ09VTlRdIHwgMDtcbiAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgIHR5cGVvZiBjb3VudCA9PT0gJ251bWJlcicgJiYgY291bnQgPj0gMCwgJ2ludmFsaWQgdmVydGV4IGNvdW50JywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICByZXR1cm4gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGNvdW50XG4gICAgICAgIH0pXG4gICAgICB9IGVsc2UgaWYgKFNfQ09VTlQgaW4gZHluYW1pY09wdGlvbnMpIHtcbiAgICAgICAgdmFyIGR5bkNvdW50ID0gZHluYW1pY09wdGlvbnNbU19DT1VOVF07XG4gICAgICAgIHJldHVybiBjcmVhdGVEeW5hbWljRGVjbChkeW5Db3VudCwgZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gZW52Lmludm9rZShzY29wZSwgZHluQ291bnQpO1xuICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgJ3R5cGVvZiAnICsgcmVzdWx0ICsgJz09PVwibnVtYmVyXCImJicgK1xuICAgICAgICAgICAgICByZXN1bHQgKyAnPj0wJiYnICtcbiAgICAgICAgICAgICAgcmVzdWx0ICsgJz09PSgnICsgcmVzdWx0ICsgJ3wwKScsXG4gICAgICAgICAgICAgICdpbnZhbGlkIHZlcnRleCBjb3VudCcpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgfSlcbiAgICAgIH0gZWxzZSBpZiAoZWxlbWVudHMpIHtcbiAgICAgICAgaWYgKGlzU3RhdGljKGVsZW1lbnRzKSkge1xuICAgICAgICAgIGlmIChlbGVtZW50cykge1xuICAgICAgICAgICAgaWYgKE9GRlNFVCkge1xuICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY2xhcmF0aW9uKFxuICAgICAgICAgICAgICAgIE9GRlNFVC50aGlzRGVwLFxuICAgICAgICAgICAgICAgIE9GRlNFVC5jb250ZXh0RGVwLFxuICAgICAgICAgICAgICAgIE9GRlNFVC5wcm9wRGVwLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgICAgICAgICBlbnYuRUxFTUVOVFMsICcudmVydENvdW50LScsIGVudi5PRkZTRVQpO1xuXG4gICAgICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKyAnPj0wJyxcbiAgICAgICAgICAgICAgICAgICAgICAnaW52YWxpZCB2ZXJ0ZXggb2Zmc2V0L2VsZW1lbnQgYnVmZmVyIHRvbyBzbWFsbCcpO1xuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVudi5FTEVNRU5UUywgJy52ZXJ0Q291bnQnKVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHJldHVybiAtMVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Lk1JU1NJTkcgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB2YXJpYWJsZSA9IG5ldyBEZWNsYXJhdGlvbihcbiAgICAgICAgICAgIGVsZW1lbnRzLnRoaXNEZXAgfHwgT0ZGU0VULnRoaXNEZXAsXG4gICAgICAgICAgICBlbGVtZW50cy5jb250ZXh0RGVwIHx8IE9GRlNFVC5jb250ZXh0RGVwLFxuICAgICAgICAgICAgZWxlbWVudHMucHJvcERlcCB8fCBPRkZTRVQucHJvcERlcCxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICAgIHZhciBlbGVtZW50cyA9IGVudi5FTEVNRU5UUztcbiAgICAgICAgICAgICAgaWYgKGVudi5PRkZTRVQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKGVsZW1lbnRzLCAnPycsIGVsZW1lbnRzLCAnLnZlcnRDb3VudC0nLFxuICAgICAgICAgICAgICAgICAgZW52Lk9GRlNFVCwgJzotMScpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihlbGVtZW50cywgJz8nLCBlbGVtZW50cywgJy52ZXJ0Q291bnQ6LTEnKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXJpYWJsZS5EWU5BTUlDID0gdHJ1ZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gdmFyaWFibGVcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZWxlbWVudHM6IGVsZW1lbnRzLFxuICAgICAgcHJpbWl0aXZlOiBwYXJzZVByaW1pdGl2ZSgpLFxuICAgICAgY291bnQ6IHBhcnNlVmVydENvdW50KCksXG4gICAgICBpbnN0YW5jZXM6IHBhcnNlUGFyYW0oU19JTlNUQU5DRVMsIGZhbHNlKSxcbiAgICAgIG9mZnNldDogT0ZGU0VUXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VHTFN0YXRlIChvcHRpb25zLCBlbnYpIHtcbiAgICB2YXIgc3RhdGljT3B0aW9ucyA9IG9wdGlvbnMuc3RhdGljO1xuICAgIHZhciBkeW5hbWljT3B0aW9ucyA9IG9wdGlvbnMuZHluYW1pYztcblxuICAgIHZhciBTVEFURSA9IHt9O1xuXG4gICAgR0xfU1RBVEVfTkFNRVMuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgdmFyIHBhcmFtID0gcHJvcE5hbWUocHJvcCk7XG5cbiAgICAgIGZ1bmN0aW9uIHBhcnNlUGFyYW0gKHBhcnNlU3RhdGljLCBwYXJzZUR5bmFtaWMpIHtcbiAgICAgICAgaWYgKHByb3AgaW4gc3RhdGljT3B0aW9ucykge1xuICAgICAgICAgIHZhciB2YWx1ZSA9IHBhcnNlU3RhdGljKHN0YXRpY09wdGlvbnNbcHJvcF0pO1xuICAgICAgICAgIFNUQVRFW3BhcmFtXSA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAocHJvcCBpbiBkeW5hbWljT3B0aW9ucykge1xuICAgICAgICAgIHZhciBkeW4gPSBkeW5hbWljT3B0aW9uc1twcm9wXTtcbiAgICAgICAgICBTVEFURVtwYXJhbV0gPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VEeW5hbWljKGVudiwgc2NvcGUsIGVudi5pbnZva2Uoc2NvcGUsIGR5bikpXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc3dpdGNoIChwcm9wKSB7XG4gICAgICAgIGNhc2UgU19DVUxMX0VOQUJMRTpcbiAgICAgICAgY2FzZSBTX0JMRU5EX0VOQUJMRTpcbiAgICAgICAgY2FzZSBTX0RJVEhFUjpcbiAgICAgICAgY2FzZSBTX1NURU5DSUxfRU5BQkxFOlxuICAgICAgICBjYXNlIFNfREVQVEhfRU5BQkxFOlxuICAgICAgICBjYXNlIFNfU0NJU1NPUl9FTkFCTEU6XG4gICAgICAgIGNhc2UgU19QT0xZR09OX09GRlNFVF9FTkFCTEU6XG4gICAgICAgIGNhc2UgU19TQU1QTEVfQUxQSEE6XG4gICAgICAgIGNhc2UgU19TQU1QTEVfRU5BQkxFOlxuICAgICAgICBjYXNlIFNfREVQVEhfTUFTSzpcbiAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShcbiAgICAgICAgICAgIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnYm9vbGVhbicsIHByb3AsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAgICAgICAndHlwZW9mICcgKyB2YWx1ZSArICc9PT1cImJvb2xlYW5cIicsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCBmbGFnICcgKyBwcm9wLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgY2FzZSBTX0RFUFRIX0ZVTkM6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHZhbHVlLCBjb21wYXJlRnVuY3MsICdpbnZhbGlkICcgKyBwcm9wLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiBjb21wYXJlRnVuY3NbdmFsdWVdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIHZhciBDT01QQVJFX0ZVTkNTID0gZW52LmNvbnN0YW50cy5jb21wYXJlRnVuY3M7XG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAgICAgICB2YWx1ZSArICcgaW4gJyArIENPTVBBUkVfRlVOQ1MsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCAnICsgcHJvcCArICcsIG11c3QgYmUgb25lIG9mICcgKyBPYmplY3Qua2V5cyhjb21wYXJlRnVuY3MpKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYoQ09NUEFSRV9GVU5DUywgJ1snLCB2YWx1ZSwgJ10nKVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfREVQVEhfUkFOR0U6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgIGlzQXJyYXlMaWtlKHZhbHVlKSAmJlxuICAgICAgICAgICAgICAgIHZhbHVlLmxlbmd0aCA9PT0gMiAmJlxuICAgICAgICAgICAgICAgIHR5cGVvZiB2YWx1ZVswXSA9PT0gJ251bWJlcicgJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgdmFsdWVbMV0gPT09ICdudW1iZXInICYmXG4gICAgICAgICAgICAgICAgdmFsdWVbMF0gPD0gdmFsdWVbMV0sXG4gICAgICAgICAgICAgICAgJ2RlcHRoIHJhbmdlIGlzIDJkIGFycmF5JyxcbiAgICAgICAgICAgICAgICBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgZW52LnNoYXJlZC5pc0FycmF5TGlrZSArICcoJyArIHZhbHVlICsgJykmJicgK1xuICAgICAgICAgICAgICAgICAgdmFsdWUgKyAnLmxlbmd0aD09PTImJicgK1xuICAgICAgICAgICAgICAgICAgJ3R5cGVvZiAnICsgdmFsdWUgKyAnWzBdPT09XCJudW1iZXJcIiYmJyArXG4gICAgICAgICAgICAgICAgICAndHlwZW9mICcgKyB2YWx1ZSArICdbMV09PT1cIm51bWJlclwiJiYnICtcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJ1swXTw9JyArIHZhbHVlICsgJ1sxXScsXG4gICAgICAgICAgICAgICAgICAnZGVwdGggcmFuZ2UgbXVzdCBiZSBhIDJkIGFycmF5Jyk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIHZhciBaX05FQVIgPSBzY29wZS5kZWYoJysnLCB2YWx1ZSwgJ1swXScpO1xuICAgICAgICAgICAgICB2YXIgWl9GQVIgPSBzY29wZS5kZWYoJysnLCB2YWx1ZSwgJ1sxXScpO1xuICAgICAgICAgICAgICByZXR1cm4gW1pfTkVBUiwgWl9GQVJdXG4gICAgICAgICAgICB9KVxuXG4gICAgICAgIGNhc2UgU19CTEVORF9GVU5DOlxuICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKFxuICAgICAgICAgICAgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdvYmplY3QnLCAnYmxlbmQuZnVuYycsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgdmFyIHNyY1JHQiA9ICgnc3JjUkdCJyBpbiB2YWx1ZSA/IHZhbHVlLnNyY1JHQiA6IHZhbHVlLnNyYyk7XG4gICAgICAgICAgICAgIHZhciBzcmNBbHBoYSA9ICgnc3JjQWxwaGEnIGluIHZhbHVlID8gdmFsdWUuc3JjQWxwaGEgOiB2YWx1ZS5zcmMpO1xuICAgICAgICAgICAgICB2YXIgZHN0UkdCID0gKCdkc3RSR0InIGluIHZhbHVlID8gdmFsdWUuZHN0UkdCIDogdmFsdWUuZHN0KTtcbiAgICAgICAgICAgICAgdmFyIGRzdEFscGhhID0gKCdkc3RBbHBoYScgaW4gdmFsdWUgPyB2YWx1ZS5kc3RBbHBoYSA6IHZhbHVlLmRzdCk7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcihzcmNSR0IsIGJsZW5kRnVuY3MsIHBhcmFtICsgJy5zcmNSR0InLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcihzcmNBbHBoYSwgYmxlbmRGdW5jcywgcGFyYW0gKyAnLnNyY0FscGhhJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoZHN0UkdCLCBibGVuZEZ1bmNzLCBwYXJhbSArICcuZHN0UkdCJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoZHN0QWxwaGEsIGJsZW5kRnVuY3MsIHBhcmFtICsgJy5kc3RBbHBoYScsIGVudi5jb21tYW5kU3RyKTtcblxuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgICAgKGludmFsaWRCbGVuZENvbWJpbmF0aW9ucy5pbmRleE9mKHNyY1JHQiArICcsICcgKyBkc3RSR0IpID09PSAtMSksXG4gICAgICAgICAgICAgICAgJ3VuYWxsb3dlZCBibGVuZGluZyBjb21iaW5hdGlvbiAoc3JjUkdCLCBkc3RSR0IpID0gKCcgKyBzcmNSR0IgKyAnLCAnICsgZHN0UkdCICsgJyknLCBlbnYuY29tbWFuZFN0cik7XG5cbiAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBibGVuZEZ1bmNzW3NyY1JHQl0sXG4gICAgICAgICAgICAgICAgYmxlbmRGdW5jc1tkc3RSR0JdLFxuICAgICAgICAgICAgICAgIGJsZW5kRnVuY3Nbc3JjQWxwaGFdLFxuICAgICAgICAgICAgICAgIGJsZW5kRnVuY3NbZHN0QWxwaGFdXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgdmFyIEJMRU5EX0ZVTkNTID0gZW52LmNvbnN0YW50cy5ibGVuZEZ1bmNzO1xuXG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAgICAgICB2YWx1ZSArICcmJnR5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJvYmplY3RcIicsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCBibGVuZCBmdW5jLCBtdXN0IGJlIGFuIG9iamVjdCcpO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBmdW5jdGlvbiByZWFkIChwcmVmaXgsIHN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgICAgICAgJ1wiJywgcHJlZml4LCBzdWZmaXgsICdcIiBpbiAnLCB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICc/JywgdmFsdWUsICcuJywgcHJlZml4LCBzdWZmaXgsXG4gICAgICAgICAgICAgICAgICAnOicsIHZhbHVlLCAnLicsIHByZWZpeCk7XG5cbiAgICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmMgKyAnIGluICcgKyBCTEVORF9GVU5DUyxcbiAgICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgJyArIHByb3AgKyAnLicgKyBwcmVmaXggKyBzdWZmaXggKyAnLCBtdXN0IGJlIG9uZSBvZiAnICsgT2JqZWN0LmtleXMoYmxlbmRGdW5jcykpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmNcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHZhciBzcmNSR0IgPSByZWFkKCdzcmMnLCAnUkdCJyk7XG4gICAgICAgICAgICAgIHZhciBkc3RSR0IgPSByZWFkKCdkc3QnLCAnUkdCJyk7XG5cbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIElOVkFMSURfQkxFTkRfQ09NQklOQVRJT05TID0gZW52LmNvbnN0YW50cy5pbnZhbGlkQmxlbmRDb21iaW5hdGlvbnM7XG5cbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgSU5WQUxJRF9CTEVORF9DT01CSU5BVElPTlMgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgJy5pbmRleE9mKCcgKyBzcmNSR0IgKyAnK1wiLCBcIisnICsgZHN0UkdCICsgJykgPT09IC0xICcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAndW5hbGxvd2VkIGJsZW5kaW5nIGNvbWJpbmF0aW9uIGZvciAoc3JjUkdCLCBkc3RSR0IpJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICB2YXIgU1JDX1JHQiA9IHNjb3BlLmRlZihCTEVORF9GVU5DUywgJ1snLCBzcmNSR0IsICddJyk7XG4gICAgICAgICAgICAgIHZhciBTUkNfQUxQSEEgPSBzY29wZS5kZWYoQkxFTkRfRlVOQ1MsICdbJywgcmVhZCgnc3JjJywgJ0FscGhhJyksICddJyk7XG4gICAgICAgICAgICAgIHZhciBEU1RfUkdCID0gc2NvcGUuZGVmKEJMRU5EX0ZVTkNTLCAnWycsIGRzdFJHQiwgJ10nKTtcbiAgICAgICAgICAgICAgdmFyIERTVF9BTFBIQSA9IHNjb3BlLmRlZihCTEVORF9GVU5DUywgJ1snLCByZWFkKCdkc3QnLCAnQWxwaGEnKSwgJ10nKTtcblxuICAgICAgICAgICAgICByZXR1cm4gW1NSQ19SR0IsIERTVF9SR0IsIFNSQ19BTFBIQSwgRFNUX0FMUEhBXVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfQkxFTkRfRVFVQVRJT046XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUsIGJsZW5kRXF1YXRpb25zLCAnaW52YWxpZCAnICsgcHJvcCwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICBibGVuZEVxdWF0aW9uc1t2YWx1ZV0sXG4gICAgICAgICAgICAgICAgICBibGVuZEVxdWF0aW9uc1t2YWx1ZV1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFBhcmFtZXRlcihcbiAgICAgICAgICAgICAgICAgIHZhbHVlLnJnYiwgYmxlbmRFcXVhdGlvbnMsIHByb3AgKyAnLnJnYicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoXG4gICAgICAgICAgICAgICAgICB2YWx1ZS5hbHBoYSwgYmxlbmRFcXVhdGlvbnMsIHByb3AgKyAnLmFscGhhJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICBibGVuZEVxdWF0aW9uc1t2YWx1ZS5yZ2JdLFxuICAgICAgICAgICAgICAgICAgYmxlbmRFcXVhdGlvbnNbdmFsdWUuYWxwaGFdXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFJhaXNlKCdpbnZhbGlkIGJsZW5kLmVxdWF0aW9uJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24gKGVudiwgc2NvcGUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgIHZhciBCTEVORF9FUVVBVElPTlMgPSBlbnYuY29uc3RhbnRzLmJsZW5kRXF1YXRpb25zO1xuXG4gICAgICAgICAgICAgIHZhciBSR0IgPSBzY29wZS5kZWYoKTtcbiAgICAgICAgICAgICAgdmFyIEFMUEhBID0gc2NvcGUuZGVmKCk7XG5cbiAgICAgICAgICAgICAgdmFyIGlmdGUgPSBlbnYuY29uZCgndHlwZW9mICcsIHZhbHVlLCAnPT09XCJzdHJpbmdcIicpO1xuXG4gICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNoZWNrUHJvcCAoYmxvY2ssIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KGJsb2NrLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSArICcgaW4gJyArIEJMRU5EX0VRVUFUSU9OUyxcbiAgICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgJyArIG5hbWUgKyAnLCBtdXN0IGJlIG9uZSBvZiAnICsgT2JqZWN0LmtleXMoYmxlbmRFcXVhdGlvbnMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2hlY2tQcm9wKGlmdGUudGhlbiwgcHJvcCwgdmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChpZnRlLmVsc2UsXG4gICAgICAgICAgICAgICAgICB2YWx1ZSArICcmJnR5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJvYmplY3RcIicsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCAnICsgcHJvcCk7XG4gICAgICAgICAgICAgICAgY2hlY2tQcm9wKGlmdGUuZWxzZSwgcHJvcCArICcucmdiJywgdmFsdWUgKyAnLnJnYicpO1xuICAgICAgICAgICAgICAgIGNoZWNrUHJvcChpZnRlLmVsc2UsIHByb3AgKyAnLmFscGhhJywgdmFsdWUgKyAnLmFscGhhJyk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGlmdGUudGhlbihcbiAgICAgICAgICAgICAgICBSR0IsICc9JywgQUxQSEEsICc9JywgQkxFTkRfRVFVQVRJT05TLCAnWycsIHZhbHVlLCAnXTsnKTtcbiAgICAgICAgICAgICAgaWZ0ZS5lbHNlKFxuICAgICAgICAgICAgICAgIFJHQiwgJz0nLCBCTEVORF9FUVVBVElPTlMsICdbJywgdmFsdWUsICcucmdiXTsnLFxuICAgICAgICAgICAgICAgIEFMUEhBLCAnPScsIEJMRU5EX0VRVUFUSU9OUywgJ1snLCB2YWx1ZSwgJy5hbHBoYV07Jyk7XG5cbiAgICAgICAgICAgICAgc2NvcGUoaWZ0ZSk7XG5cbiAgICAgICAgICAgICAgcmV0dXJuIFtSR0IsIEFMUEhBXVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfQkxFTkRfQ09MT1I6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgIGlzQXJyYXlMaWtlKHZhbHVlKSAmJlxuICAgICAgICAgICAgICAgIHZhbHVlLmxlbmd0aCA9PT0gNCxcbiAgICAgICAgICAgICAgICAnYmxlbmQuY29sb3IgbXVzdCBiZSBhIDRkIGFycmF5JywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gbG9vcCg0LCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiArdmFsdWVbaV1cbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgIGVudi5zaGFyZWQuaXNBcnJheUxpa2UgKyAnKCcgKyB2YWx1ZSArICcpJiYnICtcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJy5sZW5ndGg9PT00JyxcbiAgICAgICAgICAgICAgICAgICdibGVuZC5jb2xvciBtdXN0IGJlIGEgNGQgYXJyYXknKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBsb29wKDQsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZignKycsIHZhbHVlLCAnWycsIGksICddJylcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgY2FzZSBTX1NURU5DSUxfTUFTSzpcbiAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShcbiAgICAgICAgICAgIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnbnVtYmVyJywgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlIHwgMFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgJ3R5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJudW1iZXJcIicsXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCBzdGVuY2lsLm1hc2snKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBzY29wZS5kZWYodmFsdWUsICd8MCcpXG4gICAgICAgICAgICB9KVxuXG4gICAgICAgIGNhc2UgU19TVEVOQ0lMX0ZVTkM6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ29iamVjdCcsIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBjbXAgPSB2YWx1ZS5jbXAgfHwgJ2tlZXAnO1xuICAgICAgICAgICAgICB2YXIgcmVmID0gdmFsdWUucmVmIHx8IDA7XG4gICAgICAgICAgICAgIHZhciBtYXNrID0gJ21hc2snIGluIHZhbHVlID8gdmFsdWUubWFzayA6IC0xO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoY21wLCBjb21wYXJlRnVuY3MsIHByb3AgKyAnLmNtcCcsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZShyZWYsICdudW1iZXInLCBwcm9wICsgJy5yZWYnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUobWFzaywgJ251bWJlcicsIHByb3AgKyAnLm1hc2snLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgY29tcGFyZUZ1bmNzW2NtcF0sXG4gICAgICAgICAgICAgICAgcmVmLFxuICAgICAgICAgICAgICAgIG1hc2tcbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICB2YXIgQ09NUEFSRV9GVU5DUyA9IGVudi5jb25zdGFudHMuY29tcGFyZUZ1bmNzO1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBhc3NlcnQgKCkge1xuICAgICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmpvaW4uY2FsbChhcmd1bWVudHMsICcnKSxcbiAgICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgc3RlbmNpbC5mdW5jJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFzc2VydCh2YWx1ZSArICcmJnR5cGVvZiAnLCB2YWx1ZSwgJz09PVwib2JqZWN0XCInKTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoJyEoXCJjbXBcIiBpbiAnLCB2YWx1ZSwgJyl8fCgnLFxuICAgICAgICAgICAgICAgICAgdmFsdWUsICcuY21wIGluICcsIENPTVBBUkVfRlVOQ1MsICcpJyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB2YXIgY21wID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgICAgICdcImNtcFwiIGluICcsIHZhbHVlLFxuICAgICAgICAgICAgICAgICc/JywgQ09NUEFSRV9GVU5DUywgJ1snLCB2YWx1ZSwgJy5jbXBdJyxcbiAgICAgICAgICAgICAgICAnOicsIEdMX0tFRVApO1xuICAgICAgICAgICAgICB2YXIgcmVmID0gc2NvcGUuZGVmKHZhbHVlLCAnLnJlZnwwJyk7XG4gICAgICAgICAgICAgIHZhciBtYXNrID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgICAgICdcIm1hc2tcIiBpbiAnLCB2YWx1ZSxcbiAgICAgICAgICAgICAgICAnPycsIHZhbHVlLCAnLm1hc2t8MDotMScpO1xuICAgICAgICAgICAgICByZXR1cm4gW2NtcCwgcmVmLCBtYXNrXVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfU1RFTkNJTF9PUEZST05UOlxuICAgICAgICBjYXNlIFNfU1RFTkNJTF9PUEJBQ0s6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ29iamVjdCcsIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBmYWlsID0gdmFsdWUuZmFpbCB8fCAna2VlcCc7XG4gICAgICAgICAgICAgIHZhciB6ZmFpbCA9IHZhbHVlLnpmYWlsIHx8ICdrZWVwJztcbiAgICAgICAgICAgICAgdmFyIHpwYXNzID0gdmFsdWUuenBhc3MgfHwgJ2tlZXAnO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoZmFpbCwgc3RlbmNpbE9wcywgcHJvcCArICcuZmFpbCcsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHpmYWlsLCBzdGVuY2lsT3BzLCBwcm9wICsgJy56ZmFpbCcsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kUGFyYW1ldGVyKHpwYXNzLCBzdGVuY2lsT3BzLCBwcm9wICsgJy56cGFzcycsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBwcm9wID09PSBTX1NURU5DSUxfT1BCQUNLID8gR0xfQkFDSyA6IEdMX0ZST05ULFxuICAgICAgICAgICAgICAgIHN0ZW5jaWxPcHNbZmFpbF0sXG4gICAgICAgICAgICAgICAgc3RlbmNpbE9wc1t6ZmFpbF0sXG4gICAgICAgICAgICAgICAgc3RlbmNpbE9wc1t6cGFzc11cbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICB2YXIgU1RFTkNJTF9PUFMgPSBlbnYuY29uc3RhbnRzLnN0ZW5jaWxPcHM7XG5cbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJyxcbiAgICAgICAgICAgICAgICAgICdpbnZhbGlkICcgKyBwcm9wKTtcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgZnVuY3Rpb24gcmVhZCAobmFtZSkge1xuICAgICAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgICAgJyEoXCInICsgbmFtZSArICdcIiBpbiAnICsgdmFsdWUgKyAnKXx8JyArXG4gICAgICAgICAgICAgICAgICAgICcoJyArIHZhbHVlICsgJy4nICsgbmFtZSArICcgaW4gJyArIFNURU5DSUxfT1BTICsgJyknLFxuICAgICAgICAgICAgICAgICAgICAnaW52YWxpZCAnICsgcHJvcCArICcuJyArIG5hbWUgKyAnLCBtdXN0IGJlIG9uZSBvZiAnICsgT2JqZWN0LmtleXMoc3RlbmNpbE9wcykpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZihcbiAgICAgICAgICAgICAgICAgICdcIicsIG5hbWUsICdcIiBpbiAnLCB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICc/JywgU1RFTkNJTF9PUFMsICdbJywgdmFsdWUsICcuJywgbmFtZSwgJ106JyxcbiAgICAgICAgICAgICAgICAgIEdMX0tFRVApXG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIHByb3AgPT09IFNfU1RFTkNJTF9PUEJBQ0sgPyBHTF9CQUNLIDogR0xfRlJPTlQsXG4gICAgICAgICAgICAgICAgcmVhZCgnZmFpbCcpLFxuICAgICAgICAgICAgICAgIHJlYWQoJ3pmYWlsJyksXG4gICAgICAgICAgICAgICAgcmVhZCgnenBhc3MnKVxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KVxuXG4gICAgICAgIGNhc2UgU19QT0xZR09OX09GRlNFVF9PRkZTRVQ6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlUGFyYW0oXG4gICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh2YWx1ZSwgJ29iamVjdCcsIHBhcmFtLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHZhciBmYWN0b3IgPSB2YWx1ZS5mYWN0b3IgfCAwO1xuICAgICAgICAgICAgICB2YXIgdW5pdHMgPSB2YWx1ZS51bml0cyB8IDA7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUoZmFjdG9yLCAnbnVtYmVyJywgcGFyYW0gKyAnLmZhY3RvcicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kVHlwZSh1bml0cywgJ251bWJlcicsIHBhcmFtICsgJy51bml0cycsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtmYWN0b3IsIHVuaXRzXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgdmFsdWUgKyAnJiZ0eXBlb2YgJyArIHZhbHVlICsgJz09PVwib2JqZWN0XCInLFxuICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgJyArIHByb3ApO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICB2YXIgRkFDVE9SID0gc2NvcGUuZGVmKHZhbHVlLCAnLmZhY3RvcnwwJyk7XG4gICAgICAgICAgICAgIHZhciBVTklUUyA9IHNjb3BlLmRlZih2YWx1ZSwgJy51bml0c3wwJyk7XG5cbiAgICAgICAgICAgICAgcmV0dXJuIFtGQUNUT1IsIFVOSVRTXVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfQ1VMTF9GQUNFOlxuICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKFxuICAgICAgICAgICAgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIHZhciBmYWNlID0gMDtcbiAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSAnZnJvbnQnKSB7XG4gICAgICAgICAgICAgICAgZmFjZSA9IEdMX0ZST05UO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAnYmFjaycpIHtcbiAgICAgICAgICAgICAgICBmYWNlID0gR0xfQkFDSztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoISFmYWNlLCBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gZmFjZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgdmFsdWUgKyAnPT09XCJmcm9udFwifHwnICtcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJz09PVwiYmFja1wiJyxcbiAgICAgICAgICAgICAgICAgICdpbnZhbGlkIGN1bGwuZmFjZScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLmRlZih2YWx1ZSwgJz09PVwiZnJvbnRcIj8nLCBHTF9GUk9OVCwgJzonLCBHTF9CQUNLKVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfTElORV9XSURUSDpcbiAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShcbiAgICAgICAgICAgIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJlxuICAgICAgICAgICAgICAgIHZhbHVlID49IGxpbWl0cy5saW5lV2lkdGhEaW1zWzBdICYmXG4gICAgICAgICAgICAgICAgdmFsdWUgPD0gbGltaXRzLmxpbmVXaWR0aERpbXNbMV0sXG4gICAgICAgICAgICAgICAgJ2ludmFsaWQgbGluZSB3aWR0aCwgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlciBiZXR3ZWVuICcgK1xuICAgICAgICAgICAgICAgIGxpbWl0cy5saW5lV2lkdGhEaW1zWzBdICsgJyBhbmQgJyArIGxpbWl0cy5saW5lV2lkdGhEaW1zWzFdLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgJ3R5cGVvZiAnICsgdmFsdWUgKyAnPT09XCJudW1iZXJcIiYmJyArXG4gICAgICAgICAgICAgICAgICB2YWx1ZSArICc+PScgKyBsaW1pdHMubGluZVdpZHRoRGltc1swXSArICcmJicgK1xuICAgICAgICAgICAgICAgICAgdmFsdWUgKyAnPD0nICsgbGltaXRzLmxpbmVXaWR0aERpbXNbMV0sXG4gICAgICAgICAgICAgICAgICAnaW52YWxpZCBsaW5lIHdpZHRoJyk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfRlJPTlRfRkFDRTpcbiAgICAgICAgICByZXR1cm4gcGFyc2VQYXJhbShcbiAgICAgICAgICAgIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIodmFsdWUsIG9yaWVudGF0aW9uVHlwZSwgcGFyYW0sIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIG9yaWVudGF0aW9uVHlwZVt2YWx1ZV1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJz09PVwiY3dcInx8JyArXG4gICAgICAgICAgICAgICAgICB2YWx1ZSArICc9PT1cImNjd1wiJyxcbiAgICAgICAgICAgICAgICAgICdpbnZhbGlkIGZyb250RmFjZSwgbXVzdCBiZSBvbmUgb2YgY3csY2N3Jyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gc2NvcGUuZGVmKHZhbHVlICsgJz09PVwiY3dcIj8nICsgR0xfQ1cgKyAnOicgKyBHTF9DQ1cpXG4gICAgICAgICAgICB9KVxuXG4gICAgICAgIGNhc2UgU19DT0xPUl9NQVNLOlxuICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKFxuICAgICAgICAgICAgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICBpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LFxuICAgICAgICAgICAgICAgICdjb2xvci5tYXNrIG11c3QgYmUgbGVuZ3RoIDQgYXJyYXknLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5tYXAoZnVuY3Rpb24gKHYpIHsgcmV0dXJuICEhdiB9KVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlbnYsIHNjb3BlLCB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlbnYuYXNzZXJ0KHNjb3BlLFxuICAgICAgICAgICAgICAgICAgZW52LnNoYXJlZC5pc0FycmF5TGlrZSArICcoJyArIHZhbHVlICsgJykmJicgK1xuICAgICAgICAgICAgICAgICAgdmFsdWUgKyAnLmxlbmd0aD09PTQnLFxuICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgY29sb3IubWFzaycpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIGxvb3AoNCwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyEhJyArIHZhbHVlICsgJ1snICsgaSArICddJ1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBjYXNlIFNfU0FNUExFX0NPVkVSQUdFOlxuICAgICAgICAgIHJldHVybiBwYXJzZVBhcmFtKFxuICAgICAgICAgICAgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlLCBwYXJhbSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB2YXIgc2FtcGxlVmFsdWUgPSAndmFsdWUnIGluIHZhbHVlID8gdmFsdWUudmFsdWUgOiAxO1xuICAgICAgICAgICAgICB2YXIgc2FtcGxlSW52ZXJ0ID0gISF2YWx1ZS5pbnZlcnQ7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICB0eXBlb2Ygc2FtcGxlVmFsdWUgPT09ICdudW1iZXInICYmXG4gICAgICAgICAgICAgICAgc2FtcGxlVmFsdWUgPj0gMCAmJiBzYW1wbGVWYWx1ZSA8PSAxLFxuICAgICAgICAgICAgICAgICdzYW1wbGUuY292ZXJhZ2UudmFsdWUgbXVzdCBiZSBhIG51bWJlciBiZXR3ZWVuIDAgYW5kIDEnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIHJldHVybiBbc2FtcGxlVmFsdWUsIHNhbXBsZUludmVydF1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmdW5jdGlvbiAoZW52LCBzY29wZSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgICAgICAgIHZhbHVlICsgJyYmdHlwZW9mICcgKyB2YWx1ZSArICc9PT1cIm9iamVjdFwiJyxcbiAgICAgICAgICAgICAgICAgICdpbnZhbGlkIHNhbXBsZS5jb3ZlcmFnZScpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdmFyIFZBTFVFID0gc2NvcGUuZGVmKFxuICAgICAgICAgICAgICAgICdcInZhbHVlXCIgaW4gJywgdmFsdWUsICc/KycsIHZhbHVlLCAnLnZhbHVlOjEnKTtcbiAgICAgICAgICAgICAgdmFyIElOVkVSVCA9IHNjb3BlLmRlZignISEnLCB2YWx1ZSwgJy5pbnZlcnQnKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtWQUxVRSwgSU5WRVJUXVxuICAgICAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBTVEFURVxuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VVbmlmb3JtcyAodW5pZm9ybXMsIGVudikge1xuICAgIHZhciBzdGF0aWNVbmlmb3JtcyA9IHVuaWZvcm1zLnN0YXRpYztcbiAgICB2YXIgZHluYW1pY1VuaWZvcm1zID0gdW5pZm9ybXMuZHluYW1pYztcblxuICAgIHZhciBVTklGT1JNUyA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoc3RhdGljVW5pZm9ybXMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgIHZhciB2YWx1ZSA9IHN0YXRpY1VuaWZvcm1zW25hbWVdO1xuICAgICAgdmFyIHJlc3VsdDtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8XG4gICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgcmVzdWx0ID0gY3JlYXRlU3RhdGljRGVjbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIHJlZ2xUeXBlID0gdmFsdWUuX3JlZ2xUeXBlO1xuICAgICAgICBpZiAocmVnbFR5cGUgPT09ICd0ZXh0dXJlMmQnIHx8XG4gICAgICAgICAgICByZWdsVHlwZSA9PT0gJ3RleHR1cmVDdWJlJykge1xuICAgICAgICAgIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudikge1xuICAgICAgICAgICAgcmV0dXJuIGVudi5saW5rKHZhbHVlKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHJlZ2xUeXBlID09PSAnZnJhbWVidWZmZXInIHx8XG4gICAgICAgICAgICAgICAgICAgcmVnbFR5cGUgPT09ICdmcmFtZWJ1ZmZlckN1YmUnKSB7XG4gICAgICAgICAgY2hlY2skMS5jb21tYW5kKHZhbHVlLmNvbG9yLmxlbmd0aCA+IDAsXG4gICAgICAgICAgICAnbWlzc2luZyBjb2xvciBhdHRhY2htZW50IGZvciBmcmFtZWJ1ZmZlciBzZW50IHRvIHVuaWZvcm0gXCInICsgbmFtZSArICdcIicsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICByZXN1bHQgPSBjcmVhdGVTdGF0aWNEZWNsKGZ1bmN0aW9uIChlbnYpIHtcbiAgICAgICAgICAgIHJldHVybiBlbnYubGluayh2YWx1ZS5jb2xvclswXSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVjayQxLmNvbW1hbmRSYWlzZSgnaW52YWxpZCBkYXRhIGZvciB1bmlmb3JtIFwiJyArIG5hbWUgKyAnXCInLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoaXNBcnJheUxpa2UodmFsdWUpKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudikge1xuICAgICAgICAgIHZhciBJVEVNID0gZW52Lmdsb2JhbC5kZWYoJ1snLFxuICAgICAgICAgICAgbG9vcCh2YWx1ZS5sZW5ndGgsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICB0eXBlb2YgdmFsdWVbaV0gPT09ICdudW1iZXInIHx8XG4gICAgICAgICAgICAgICAgdHlwZW9mIHZhbHVlW2ldID09PSAnYm9vbGVhbicsXG4gICAgICAgICAgICAgICAgJ2ludmFsaWQgdW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWVbaV1cbiAgICAgICAgICAgIH0pLCAnXScpO1xuICAgICAgICAgIHJldHVybiBJVEVNXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hlY2skMS5jb21tYW5kUmFpc2UoJ2ludmFsaWQgb3IgbWlzc2luZyBkYXRhIGZvciB1bmlmb3JtIFwiJyArIG5hbWUgKyAnXCInLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICB9XG4gICAgICByZXN1bHQudmFsdWUgPSB2YWx1ZTtcbiAgICAgIFVOSUZPUk1TW25hbWVdID0gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgT2JqZWN0LmtleXMoZHluYW1pY1VuaWZvcm1zKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHZhciBkeW4gPSBkeW5hbWljVW5pZm9ybXNba2V5XTtcbiAgICAgIFVOSUZPUk1TW2tleV0gPSBjcmVhdGVEeW5hbWljRGVjbChkeW4sIGZ1bmN0aW9uIChlbnYsIHNjb3BlKSB7XG4gICAgICAgIHJldHVybiBlbnYuaW52b2tlKHNjb3BlLCBkeW4pXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiBVTklGT1JNU1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VBdHRyaWJ1dGVzIChhdHRyaWJ1dGVzLCBlbnYpIHtcbiAgICB2YXIgc3RhdGljQXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMuc3RhdGljO1xuICAgIHZhciBkeW5hbWljQXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMuZHluYW1pYztcblxuICAgIHZhciBhdHRyaWJ1dGVEZWZzID0ge307XG5cbiAgICBPYmplY3Qua2V5cyhzdGF0aWNBdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChhdHRyaWJ1dGUpIHtcbiAgICAgIHZhciB2YWx1ZSA9IHN0YXRpY0F0dHJpYnV0ZXNbYXR0cmlidXRlXTtcbiAgICAgIHZhciBpZCA9IHN0cmluZ1N0b3JlLmlkKGF0dHJpYnV0ZSk7XG5cbiAgICAgIHZhciByZWNvcmQgPSBuZXcgQXR0cmlidXRlUmVjb3JkKCk7XG4gICAgICBpZiAoaXNCdWZmZXJBcmdzKHZhbHVlKSkge1xuICAgICAgICByZWNvcmQuc3RhdGUgPSBBVFRSSUJfU1RBVEVfUE9JTlRFUjtcbiAgICAgICAgcmVjb3JkLmJ1ZmZlciA9IGJ1ZmZlclN0YXRlLmdldEJ1ZmZlcihcbiAgICAgICAgICBidWZmZXJTdGF0ZS5jcmVhdGUodmFsdWUsIEdMX0FSUkFZX0JVRkZFUiQxLCBmYWxzZSwgdHJ1ZSkpO1xuICAgICAgICByZWNvcmQudHlwZSA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYnVmZmVyID0gYnVmZmVyU3RhdGUuZ2V0QnVmZmVyKHZhbHVlKTtcbiAgICAgICAgaWYgKGJ1ZmZlcikge1xuICAgICAgICAgIHJlY29yZC5zdGF0ZSA9IEFUVFJJQl9TVEFURV9QT0lOVEVSO1xuICAgICAgICAgIHJlY29yZC5idWZmZXIgPSBidWZmZXI7XG4gICAgICAgICAgcmVjb3JkLnR5cGUgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlLFxuICAgICAgICAgICAgJ2ludmFsaWQgZGF0YSBmb3IgYXR0cmlidXRlICcgKyBhdHRyaWJ1dGUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICBpZiAoJ2NvbnN0YW50JyBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIGNvbnN0YW50ID0gdmFsdWUuY29uc3RhbnQ7XG4gICAgICAgICAgICByZWNvcmQuYnVmZmVyID0gJ251bGwnO1xuICAgICAgICAgICAgcmVjb3JkLnN0YXRlID0gQVRUUklCX1NUQVRFX0NPTlNUQU5UO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb25zdGFudCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgcmVjb3JkLnggPSBjb25zdGFudDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICBpc0FycmF5TGlrZShjb25zdGFudCkgJiZcbiAgICAgICAgICAgICAgICBjb25zdGFudC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgICAgY29uc3RhbnQubGVuZ3RoIDw9IDQsXG4gICAgICAgICAgICAgICAgJ2ludmFsaWQgY29uc3RhbnQgZm9yIGF0dHJpYnV0ZSAnICsgYXR0cmlidXRlLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIENVVEVfQ09NUE9ORU5UUy5mb3JFYWNoKGZ1bmN0aW9uIChjLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPCBjb25zdGFudC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgIHJlY29yZFtjXSA9IGNvbnN0YW50W2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChpc0J1ZmZlckFyZ3ModmFsdWUuYnVmZmVyKSkge1xuICAgICAgICAgICAgICBidWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIoXG4gICAgICAgICAgICAgICAgYnVmZmVyU3RhdGUuY3JlYXRlKHZhbHVlLmJ1ZmZlciwgR0xfQVJSQVlfQlVGRkVSJDEsIGZhbHNlLCB0cnVlKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBidWZmZXIgPSBidWZmZXJTdGF0ZS5nZXRCdWZmZXIodmFsdWUuYnVmZmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZCghIWJ1ZmZlciwgJ21pc3NpbmcgYnVmZmVyIGZvciBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiJywgZW52LmNvbW1hbmRTdHIpO1xuXG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gdmFsdWUub2Zmc2V0IHwgMDtcbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChvZmZzZXQgPj0gMCxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgb2Zmc2V0IGZvciBhdHRyaWJ1dGUgXCInICsgYXR0cmlidXRlICsgJ1wiJywgZW52LmNvbW1hbmRTdHIpO1xuXG4gICAgICAgICAgICB2YXIgc3RyaWRlID0gdmFsdWUuc3RyaWRlIHwgMDtcbiAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChzdHJpZGUgPj0gMCAmJiBzdHJpZGUgPCAyNTYsXG4gICAgICAgICAgICAgICdpbnZhbGlkIHN0cmlkZSBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIiwgbXVzdCBiZSBpbnRlZ2VyIGJldHdlZWVuIFswLCAyNTVdJywgZW52LmNvbW1hbmRTdHIpO1xuXG4gICAgICAgICAgICB2YXIgc2l6ZSA9IHZhbHVlLnNpemUgfCAwO1xuICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKCEoJ3NpemUnIGluIHZhbHVlKSB8fCAoc2l6ZSA+IDAgJiYgc2l6ZSA8PSA0KSxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgc2l6ZSBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIiwgbXVzdCBiZSAxLDIsMyw0JywgZW52LmNvbW1hbmRTdHIpO1xuXG4gICAgICAgICAgICB2YXIgbm9ybWFsaXplZCA9ICEhdmFsdWUubm9ybWFsaXplZDtcblxuICAgICAgICAgICAgdmFyIHR5cGUgPSAwO1xuICAgICAgICAgICAgaWYgKCd0eXBlJyBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRQYXJhbWV0ZXIoXG4gICAgICAgICAgICAgICAgdmFsdWUudHlwZSwgZ2xUeXBlcyxcbiAgICAgICAgICAgICAgICAnaW52YWxpZCB0eXBlIGZvciBhdHRyaWJ1dGUgJyArIGF0dHJpYnV0ZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICB0eXBlID0gZ2xUeXBlc1t2YWx1ZS50eXBlXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGRpdmlzb3IgPSB2YWx1ZS5kaXZpc29yIHwgMDtcbiAgICAgICAgICAgIGlmICgnZGl2aXNvcicgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKGRpdmlzb3IgPT09IDAgfHwgZXh0SW5zdGFuY2luZyxcbiAgICAgICAgICAgICAgICAnY2Fubm90IHNwZWNpZnkgZGl2aXNvciBmb3IgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIiwgaW5zdGFuY2luZyBub3Qgc3VwcG9ydGVkJywgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoZGl2aXNvciA+PSAwLFxuICAgICAgICAgICAgICAgICdpbnZhbGlkIGRpdmlzb3IgZm9yIGF0dHJpYnV0ZSBcIicgKyBhdHRyaWJ1dGUgKyAnXCInLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICB2YXIgY29tbWFuZCA9IGVudi5jb21tYW5kU3RyO1xuXG4gICAgICAgICAgICAgIHZhciBWQUxJRF9LRVlTID0gW1xuICAgICAgICAgICAgICAgICdidWZmZXInLFxuICAgICAgICAgICAgICAgICdvZmZzZXQnLFxuICAgICAgICAgICAgICAgICdkaXZpc29yJyxcbiAgICAgICAgICAgICAgICAnbm9ybWFsaXplZCcsXG4gICAgICAgICAgICAgICAgJ3R5cGUnLFxuICAgICAgICAgICAgICAgICdzaXplJyxcbiAgICAgICAgICAgICAgICAnc3RyaWRlJ1xuICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgIE9iamVjdC5rZXlzKHZhbHVlKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgICAgVkFMSURfS0VZUy5pbmRleE9mKHByb3ApID49IDAsXG4gICAgICAgICAgICAgICAgICAndW5rbm93biBwYXJhbWV0ZXIgXCInICsgcHJvcCArICdcIiBmb3IgYXR0cmlidXRlIHBvaW50ZXIgXCInICsgYXR0cmlidXRlICsgJ1wiICh2YWxpZCBwYXJhbWV0ZXJzIGFyZSAnICsgVkFMSURfS0VZUyArICcpJyxcbiAgICAgICAgICAgICAgICAgIGNvbW1hbmQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZWNvcmQuYnVmZmVyID0gYnVmZmVyO1xuICAgICAgICAgICAgcmVjb3JkLnN0YXRlID0gQVRUUklCX1NUQVRFX1BPSU5URVI7XG4gICAgICAgICAgICByZWNvcmQuc2l6ZSA9IHNpemU7XG4gICAgICAgICAgICByZWNvcmQubm9ybWFsaXplZCA9IG5vcm1hbGl6ZWQ7XG4gICAgICAgICAgICByZWNvcmQudHlwZSA9IHR5cGUgfHwgYnVmZmVyLmR0eXBlO1xuICAgICAgICAgICAgcmVjb3JkLm9mZnNldCA9IG9mZnNldDtcbiAgICAgICAgICAgIHJlY29yZC5zdHJpZGUgPSBzdHJpZGU7XG4gICAgICAgICAgICByZWNvcmQuZGl2aXNvciA9IGRpdmlzb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGF0dHJpYnV0ZURlZnNbYXR0cmlidXRlXSA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgdmFyIGNhY2hlID0gZW52LmF0dHJpYkNhY2hlO1xuICAgICAgICBpZiAoaWQgaW4gY2FjaGUpIHtcbiAgICAgICAgICByZXR1cm4gY2FjaGVbaWRdXG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgICBpc1N0cmVhbTogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgT2JqZWN0LmtleXMocmVjb3JkKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9IHJlY29yZFtrZXldO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlY29yZC5idWZmZXIpIHtcbiAgICAgICAgICByZXN1bHQuYnVmZmVyID0gZW52LmxpbmsocmVjb3JkLmJ1ZmZlcik7XG4gICAgICAgICAgcmVzdWx0LnR5cGUgPSByZXN1bHQudHlwZSB8fCAocmVzdWx0LmJ1ZmZlciArICcuZHR5cGUnKTtcbiAgICAgICAgfVxuICAgICAgICBjYWNoZVtpZF0gPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgT2JqZWN0LmtleXMoZHluYW1pY0F0dHJpYnV0ZXMpLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgdmFyIGR5biA9IGR5bmFtaWNBdHRyaWJ1dGVzW2F0dHJpYnV0ZV07XG5cbiAgICAgIGZ1bmN0aW9uIGFwcGVuZEF0dHJpYnV0ZUNvZGUgKGVudiwgYmxvY2spIHtcbiAgICAgICAgdmFyIFZBTFVFID0gZW52Lmludm9rZShibG9jaywgZHluKTtcblxuICAgICAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcblxuICAgICAgICB2YXIgSVNfQlVGRkVSX0FSR1MgPSBzaGFyZWQuaXNCdWZmZXJBcmdzO1xuICAgICAgICB2YXIgQlVGRkVSX1NUQVRFID0gc2hhcmVkLmJ1ZmZlcjtcblxuICAgICAgICAvLyBQZXJmb3JtIHZhbGlkYXRpb24gb24gYXR0cmlidXRlXG4gICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGVudi5hc3NlcnQoYmxvY2ssXG4gICAgICAgICAgICBWQUxVRSArICcmJih0eXBlb2YgJyArIFZBTFVFICsgJz09PVwib2JqZWN0XCJ8fHR5cGVvZiAnICtcbiAgICAgICAgICAgIFZBTFVFICsgJz09PVwiZnVuY3Rpb25cIikmJignICtcbiAgICAgICAgICAgIElTX0JVRkZFUl9BUkdTICsgJygnICsgVkFMVUUgKyAnKXx8JyArXG4gICAgICAgICAgICBCVUZGRVJfU1RBVEUgKyAnLmdldEJ1ZmZlcignICsgVkFMVUUgKyAnKXx8JyArXG4gICAgICAgICAgICBCVUZGRVJfU1RBVEUgKyAnLmdldEJ1ZmZlcignICsgVkFMVUUgKyAnLmJ1ZmZlcil8fCcgK1xuICAgICAgICAgICAgSVNfQlVGRkVSX0FSR1MgKyAnKCcgKyBWQUxVRSArICcuYnVmZmVyKXx8JyArXG4gICAgICAgICAgICAnKFwiY29uc3RhbnRcIiBpbiAnICsgVkFMVUUgK1xuICAgICAgICAgICAgJyYmKHR5cGVvZiAnICsgVkFMVUUgKyAnLmNvbnN0YW50PT09XCJudW1iZXJcInx8JyArXG4gICAgICAgICAgICBzaGFyZWQuaXNBcnJheUxpa2UgKyAnKCcgKyBWQUxVRSArICcuY29uc3RhbnQpKSkpJyxcbiAgICAgICAgICAgICdpbnZhbGlkIGR5bmFtaWMgYXR0cmlidXRlIFwiJyArIGF0dHJpYnV0ZSArICdcIicpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBhbGxvY2F0ZSBuYW1lcyBmb3IgcmVzdWx0XG4gICAgICAgIHZhciByZXN1bHQgPSB7XG4gICAgICAgICAgaXNTdHJlYW06IGJsb2NrLmRlZihmYWxzZSlcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGRlZmF1bHRSZWNvcmQgPSBuZXcgQXR0cmlidXRlUmVjb3JkKCk7XG4gICAgICAgIGRlZmF1bHRSZWNvcmQuc3RhdGUgPSBBVFRSSUJfU1RBVEVfUE9JTlRFUjtcbiAgICAgICAgT2JqZWN0LmtleXMoZGVmYXVsdFJlY29yZCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSBibG9jay5kZWYoJycgKyBkZWZhdWx0UmVjb3JkW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgQlVGRkVSID0gcmVzdWx0LmJ1ZmZlcjtcbiAgICAgICAgdmFyIFRZUEUgPSByZXN1bHQudHlwZTtcbiAgICAgICAgYmxvY2soXG4gICAgICAgICAgJ2lmKCcsIElTX0JVRkZFUl9BUkdTLCAnKCcsIFZBTFVFLCAnKSl7JyxcbiAgICAgICAgICByZXN1bHQuaXNTdHJlYW0sICc9dHJ1ZTsnLFxuICAgICAgICAgIEJVRkZFUiwgJz0nLCBCVUZGRVJfU1RBVEUsICcuY3JlYXRlU3RyZWFtKCcsIEdMX0FSUkFZX0JVRkZFUiQxLCAnLCcsIFZBTFVFLCAnKTsnLFxuICAgICAgICAgIFRZUEUsICc9JywgQlVGRkVSLCAnLmR0eXBlOycsXG4gICAgICAgICAgJ31lbHNleycsXG4gICAgICAgICAgQlVGRkVSLCAnPScsIEJVRkZFUl9TVEFURSwgJy5nZXRCdWZmZXIoJywgVkFMVUUsICcpOycsXG4gICAgICAgICAgJ2lmKCcsIEJVRkZFUiwgJyl7JyxcbiAgICAgICAgICBUWVBFLCAnPScsIEJVRkZFUiwgJy5kdHlwZTsnLFxuICAgICAgICAgICd9ZWxzZSBpZihcImNvbnN0YW50XCIgaW4gJywgVkFMVUUsICcpeycsXG4gICAgICAgICAgcmVzdWx0LnN0YXRlLCAnPScsIEFUVFJJQl9TVEFURV9DT05TVEFOVCwgJzsnLFxuICAgICAgICAgICdpZih0eXBlb2YgJyArIFZBTFVFICsgJy5jb25zdGFudCA9PT0gXCJudW1iZXJcIil7JyxcbiAgICAgICAgICByZXN1bHRbQ1VURV9DT01QT05FTlRTWzBdXSwgJz0nLCBWQUxVRSwgJy5jb25zdGFudDsnLFxuICAgICAgICAgIENVVEVfQ09NUE9ORU5UUy5zbGljZSgxKS5tYXAoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRbbl1cbiAgICAgICAgICB9KS5qb2luKCc9JyksICc9MDsnLFxuICAgICAgICAgICd9ZWxzZXsnLFxuICAgICAgICAgIENVVEVfQ09NUE9ORU5UUy5tYXAoZnVuY3Rpb24gKG5hbWUsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIHJlc3VsdFtuYW1lXSArICc9JyArIFZBTFVFICsgJy5jb25zdGFudC5sZW5ndGg+JyArIGkgK1xuICAgICAgICAgICAgICAnPycgKyBWQUxVRSArICcuY29uc3RhbnRbJyArIGkgKyAnXTowOydcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9KS5qb2luKCcnKSxcbiAgICAgICAgICAnfX1lbHNleycsXG4gICAgICAgICAgJ2lmKCcsIElTX0JVRkZFUl9BUkdTLCAnKCcsIFZBTFVFLCAnLmJ1ZmZlcikpeycsXG4gICAgICAgICAgQlVGRkVSLCAnPScsIEJVRkZFUl9TVEFURSwgJy5jcmVhdGVTdHJlYW0oJywgR0xfQVJSQVlfQlVGRkVSJDEsICcsJywgVkFMVUUsICcuYnVmZmVyKTsnLFxuICAgICAgICAgICd9ZWxzZXsnLFxuICAgICAgICAgIEJVRkZFUiwgJz0nLCBCVUZGRVJfU1RBVEUsICcuZ2V0QnVmZmVyKCcsIFZBTFVFLCAnLmJ1ZmZlcik7JyxcbiAgICAgICAgICAnfScsXG4gICAgICAgICAgVFlQRSwgJz1cInR5cGVcIiBpbiAnLCBWQUxVRSwgJz8nLFxuICAgICAgICAgIHNoYXJlZC5nbFR5cGVzLCAnWycsIFZBTFVFLCAnLnR5cGVdOicsIEJVRkZFUiwgJy5kdHlwZTsnLFxuICAgICAgICAgIHJlc3VsdC5ub3JtYWxpemVkLCAnPSEhJywgVkFMVUUsICcubm9ybWFsaXplZDsnKTtcbiAgICAgICAgZnVuY3Rpb24gZW1pdFJlYWRSZWNvcmQgKG5hbWUpIHtcbiAgICAgICAgICBibG9jayhyZXN1bHRbbmFtZV0sICc9JywgVkFMVUUsICcuJywgbmFtZSwgJ3wwOycpO1xuICAgICAgICB9XG4gICAgICAgIGVtaXRSZWFkUmVjb3JkKCdzaXplJyk7XG4gICAgICAgIGVtaXRSZWFkUmVjb3JkKCdvZmZzZXQnKTtcbiAgICAgICAgZW1pdFJlYWRSZWNvcmQoJ3N0cmlkZScpO1xuICAgICAgICBlbWl0UmVhZFJlY29yZCgnZGl2aXNvcicpO1xuXG4gICAgICAgIGJsb2NrKCd9fScpO1xuXG4gICAgICAgIGJsb2NrLmV4aXQoXG4gICAgICAgICAgJ2lmKCcsIHJlc3VsdC5pc1N0cmVhbSwgJyl7JyxcbiAgICAgICAgICBCVUZGRVJfU1RBVEUsICcuZGVzdHJveVN0cmVhbSgnLCBCVUZGRVIsICcpOycsXG4gICAgICAgICAgJ30nKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICB9XG5cbiAgICAgIGF0dHJpYnV0ZURlZnNbYXR0cmlidXRlXSA9IGNyZWF0ZUR5bmFtaWNEZWNsKGR5biwgYXBwZW5kQXR0cmlidXRlQ29kZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXR0cmlidXRlRGVmc1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VDb250ZXh0IChjb250ZXh0KSB7XG4gICAgdmFyIHN0YXRpY0NvbnRleHQgPSBjb250ZXh0LnN0YXRpYztcbiAgICB2YXIgZHluYW1pY0NvbnRleHQgPSBjb250ZXh0LmR5bmFtaWM7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoc3RhdGljQ29udGV4dCkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIHZhbHVlID0gc3RhdGljQ29udGV4dFtuYW1lXTtcbiAgICAgIHJlc3VsdFtuYW1lXSA9IGNyZWF0ZVN0YXRpY0RlY2woZnVuY3Rpb24gKGVudiwgc2NvcGUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICByZXR1cm4gJycgKyB2YWx1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBlbnYubGluayh2YWx1ZSlcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBPYmplY3Qua2V5cyhkeW5hbWljQ29udGV4dCkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIGR5biA9IGR5bmFtaWNDb250ZXh0W25hbWVdO1xuICAgICAgcmVzdWx0W25hbWVdID0gY3JlYXRlRHluYW1pY0RlY2woZHluLCBmdW5jdGlvbiAoZW52LCBzY29wZSkge1xuICAgICAgICByZXR1cm4gZW52Lmludm9rZShzY29wZSwgZHluKVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUFyZ3VtZW50cyAob3B0aW9ucywgYXR0cmlidXRlcywgdW5pZm9ybXMsIGNvbnRleHQsIGVudikge1xuICAgIHZhciBzdGF0aWNPcHRpb25zID0gb3B0aW9ucy5zdGF0aWM7XG4gICAgdmFyIGR5bmFtaWNPcHRpb25zID0gb3B0aW9ucy5keW5hbWljO1xuXG4gICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgS0VZX05BTUVTID0gW1xuICAgICAgICBTX0ZSQU1FQlVGRkVSLFxuICAgICAgICBTX1ZFUlQsXG4gICAgICAgIFNfRlJBRyxcbiAgICAgICAgU19FTEVNRU5UUyxcbiAgICAgICAgU19QUklNSVRJVkUsXG4gICAgICAgIFNfT0ZGU0VULFxuICAgICAgICBTX0NPVU5ULFxuICAgICAgICBTX0lOU1RBTkNFUyxcbiAgICAgICAgU19QUk9GSUxFXG4gICAgICBdLmNvbmNhdChHTF9TVEFURV9OQU1FUyk7XG5cbiAgICAgIGZ1bmN0aW9uIGNoZWNrS2V5cyAoZGljdCkge1xuICAgICAgICBPYmplY3Qua2V5cyhkaWN0KS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICBLRVlfTkFNRVMuaW5kZXhPZihrZXkpID49IDAsXG4gICAgICAgICAgICAndW5rbm93biBwYXJhbWV0ZXIgXCInICsga2V5ICsgJ1wiJyxcbiAgICAgICAgICAgIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNoZWNrS2V5cyhzdGF0aWNPcHRpb25zKTtcbiAgICAgIGNoZWNrS2V5cyhkeW5hbWljT3B0aW9ucyk7XG4gICAgfSk7XG5cbiAgICB2YXIgZnJhbWVidWZmZXIgPSBwYXJzZUZyYW1lYnVmZmVyKG9wdGlvbnMsIGVudik7XG4gICAgdmFyIHZpZXdwb3J0QW5kU2Npc3NvciA9IHBhcnNlVmlld3BvcnRTY2lzc29yKG9wdGlvbnMsIGZyYW1lYnVmZmVyLCBlbnYpO1xuICAgIHZhciBkcmF3ID0gcGFyc2VEcmF3KG9wdGlvbnMsIGVudik7XG4gICAgdmFyIHN0YXRlID0gcGFyc2VHTFN0YXRlKG9wdGlvbnMsIGVudik7XG4gICAgdmFyIHNoYWRlciA9IHBhcnNlUHJvZ3JhbShvcHRpb25zLCBlbnYpO1xuXG4gICAgZnVuY3Rpb24gY29weUJveCAobmFtZSkge1xuICAgICAgdmFyIGRlZm4gPSB2aWV3cG9ydEFuZFNjaXNzb3JbbmFtZV07XG4gICAgICBpZiAoZGVmbikge1xuICAgICAgICBzdGF0ZVtuYW1lXSA9IGRlZm47XG4gICAgICB9XG4gICAgfVxuICAgIGNvcHlCb3goU19WSUVXUE9SVCk7XG4gICAgY29weUJveChwcm9wTmFtZShTX1NDSVNTT1JfQk9YKSk7XG5cbiAgICB2YXIgZGlydHkgPSBPYmplY3Qua2V5cyhzdGF0ZSkubGVuZ3RoID4gMDtcblxuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICBmcmFtZWJ1ZmZlcjogZnJhbWVidWZmZXIsXG4gICAgICBkcmF3OiBkcmF3LFxuICAgICAgc2hhZGVyOiBzaGFkZXIsXG4gICAgICBzdGF0ZTogc3RhdGUsXG4gICAgICBkaXJ0eTogZGlydHlcbiAgICB9O1xuXG4gICAgcmVzdWx0LnByb2ZpbGUgPSBwYXJzZVByb2ZpbGUob3B0aW9ucywgZW52KTtcbiAgICByZXN1bHQudW5pZm9ybXMgPSBwYXJzZVVuaWZvcm1zKHVuaWZvcm1zLCBlbnYpO1xuICAgIHJlc3VsdC5hdHRyaWJ1dGVzID0gcGFyc2VBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGVudik7XG4gICAgcmVzdWx0LmNvbnRleHQgPSBwYXJzZUNvbnRleHQoY29udGV4dCwgZW52KTtcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIENPTU1PTiBVUERBVEUgRlVOQ1RJT05TXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgZnVuY3Rpb24gZW1pdENvbnRleHQgKGVudiwgc2NvcGUsIGNvbnRleHQpIHtcbiAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcbiAgICB2YXIgQ09OVEVYVCA9IHNoYXJlZC5jb250ZXh0O1xuXG4gICAgdmFyIGNvbnRleHRFbnRlciA9IGVudi5zY29wZSgpO1xuXG4gICAgT2JqZWN0LmtleXMoY29udGV4dCkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgc2NvcGUuc2F2ZShDT05URVhULCAnLicgKyBuYW1lKTtcbiAgICAgIHZhciBkZWZuID0gY29udGV4dFtuYW1lXTtcbiAgICAgIGNvbnRleHRFbnRlcihDT05URVhULCAnLicsIG5hbWUsICc9JywgZGVmbi5hcHBlbmQoZW52LCBzY29wZSksICc7Jyk7XG4gICAgfSk7XG5cbiAgICBzY29wZShjb250ZXh0RW50ZXIpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBDT01NT04gRFJBV0lORyBGVU5DVElPTlNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBmdW5jdGlvbiBlbWl0UG9sbEZyYW1lYnVmZmVyIChlbnYsIHNjb3BlLCBmcmFtZWJ1ZmZlciwgc2tpcENoZWNrKSB7XG4gICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG5cbiAgICB2YXIgR0wgPSBzaGFyZWQuZ2w7XG4gICAgdmFyIEZSQU1FQlVGRkVSX1NUQVRFID0gc2hhcmVkLmZyYW1lYnVmZmVyO1xuICAgIHZhciBFWFRfRFJBV19CVUZGRVJTO1xuICAgIGlmIChleHREcmF3QnVmZmVycykge1xuICAgICAgRVhUX0RSQVdfQlVGRkVSUyA9IHNjb3BlLmRlZihzaGFyZWQuZXh0ZW5zaW9ucywgJy53ZWJnbF9kcmF3X2J1ZmZlcnMnKTtcbiAgICB9XG5cbiAgICB2YXIgY29uc3RhbnRzID0gZW52LmNvbnN0YW50cztcblxuICAgIHZhciBEUkFXX0JVRkZFUlMgPSBjb25zdGFudHMuZHJhd0J1ZmZlcjtcbiAgICB2YXIgQkFDS19CVUZGRVIgPSBjb25zdGFudHMuYmFja0J1ZmZlcjtcblxuICAgIHZhciBORVhUO1xuICAgIGlmIChmcmFtZWJ1ZmZlcikge1xuICAgICAgTkVYVCA9IGZyYW1lYnVmZmVyLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgTkVYVCA9IHNjb3BlLmRlZihGUkFNRUJVRkZFUl9TVEFURSwgJy5uZXh0Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFza2lwQ2hlY2spIHtcbiAgICAgIHNjb3BlKCdpZignLCBORVhULCAnIT09JywgRlJBTUVCVUZGRVJfU1RBVEUsICcuY3VyKXsnKTtcbiAgICB9XG4gICAgc2NvcGUoXG4gICAgICAnaWYoJywgTkVYVCwgJyl7JyxcbiAgICAgIEdMLCAnLmJpbmRGcmFtZWJ1ZmZlcignLCBHTF9GUkFNRUJVRkZFUiQyLCAnLCcsIE5FWFQsICcuZnJhbWVidWZmZXIpOycpO1xuICAgIGlmIChleHREcmF3QnVmZmVycykge1xuICAgICAgc2NvcGUoRVhUX0RSQVdfQlVGRkVSUywgJy5kcmF3QnVmZmVyc1dFQkdMKCcsXG4gICAgICAgIERSQVdfQlVGRkVSUywgJ1snLCBORVhULCAnLmNvbG9yQXR0YWNobWVudHMubGVuZ3RoXSk7Jyk7XG4gICAgfVxuICAgIHNjb3BlKCd9ZWxzZXsnLFxuICAgICAgR0wsICcuYmluZEZyYW1lYnVmZmVyKCcsIEdMX0ZSQU1FQlVGRkVSJDIsICcsbnVsbCk7Jyk7XG4gICAgaWYgKGV4dERyYXdCdWZmZXJzKSB7XG4gICAgICBzY29wZShFWFRfRFJBV19CVUZGRVJTLCAnLmRyYXdCdWZmZXJzV0VCR0woJywgQkFDS19CVUZGRVIsICcpOycpO1xuICAgIH1cbiAgICBzY29wZShcbiAgICAgICd9JyxcbiAgICAgIEZSQU1FQlVGRkVSX1NUQVRFLCAnLmN1cj0nLCBORVhULCAnOycpO1xuICAgIGlmICghc2tpcENoZWNrKSB7XG4gICAgICBzY29wZSgnfScpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVtaXRQb2xsU3RhdGUgKGVudiwgc2NvcGUsIGFyZ3MpIHtcbiAgICB2YXIgc2hhcmVkID0gZW52LnNoYXJlZDtcblxuICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcblxuICAgIHZhciBDVVJSRU5UX1ZBUlMgPSBlbnYuY3VycmVudDtcbiAgICB2YXIgTkVYVF9WQVJTID0gZW52Lm5leHQ7XG4gICAgdmFyIENVUlJFTlRfU1RBVEUgPSBzaGFyZWQuY3VycmVudDtcbiAgICB2YXIgTkVYVF9TVEFURSA9IHNoYXJlZC5uZXh0O1xuXG4gICAgdmFyIGJsb2NrID0gZW52LmNvbmQoQ1VSUkVOVF9TVEFURSwgJy5kaXJ0eScpO1xuXG4gICAgR0xfU1RBVEVfTkFNRVMuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgdmFyIHBhcmFtID0gcHJvcE5hbWUocHJvcCk7XG4gICAgICBpZiAocGFyYW0gaW4gYXJncy5zdGF0ZSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdmFyIE5FWFQsIENVUlJFTlQ7XG4gICAgICBpZiAocGFyYW0gaW4gTkVYVF9WQVJTKSB7XG4gICAgICAgIE5FWFQgPSBORVhUX1ZBUlNbcGFyYW1dO1xuICAgICAgICBDVVJSRU5UID0gQ1VSUkVOVF9WQVJTW3BhcmFtXTtcbiAgICAgICAgdmFyIHBhcnRzID0gbG9vcChjdXJyZW50U3RhdGVbcGFyYW1dLmxlbmd0aCwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICByZXR1cm4gYmxvY2suZGVmKE5FWFQsICdbJywgaSwgJ10nKVxuICAgICAgICB9KTtcbiAgICAgICAgYmxvY2soZW52LmNvbmQocGFydHMubWFwKGZ1bmN0aW9uIChwLCBpKSB7XG4gICAgICAgICAgcmV0dXJuIHAgKyAnIT09JyArIENVUlJFTlQgKyAnWycgKyBpICsgJ10nXG4gICAgICAgIH0pLmpvaW4oJ3x8JykpXG4gICAgICAgICAgLnRoZW4oXG4gICAgICAgICAgICBHTCwgJy4nLCBHTF9WQVJJQUJMRVNbcGFyYW1dLCAnKCcsIHBhcnRzLCAnKTsnLFxuICAgICAgICAgICAgcGFydHMubWFwKGZ1bmN0aW9uIChwLCBpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBDVVJSRU5UICsgJ1snICsgaSArICddPScgKyBwXG4gICAgICAgICAgICB9KS5qb2luKCc7JyksICc7JykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgTkVYVCA9IGJsb2NrLmRlZihORVhUX1NUQVRFLCAnLicsIHBhcmFtKTtcbiAgICAgICAgdmFyIGlmdGUgPSBlbnYuY29uZChORVhULCAnIT09JywgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSk7XG4gICAgICAgIGJsb2NrKGlmdGUpO1xuICAgICAgICBpZiAocGFyYW0gaW4gR0xfRkxBR1MpIHtcbiAgICAgICAgICBpZnRlKFxuICAgICAgICAgICAgZW52LmNvbmQoTkVYVClcbiAgICAgICAgICAgICAgICAudGhlbihHTCwgJy5lbmFibGUoJywgR0xfRkxBR1NbcGFyYW1dLCAnKTsnKVxuICAgICAgICAgICAgICAgIC5lbHNlKEdMLCAnLmRpc2FibGUoJywgR0xfRkxBR1NbcGFyYW1dLCAnKTsnKSxcbiAgICAgICAgICAgIENVUlJFTlRfU1RBVEUsICcuJywgcGFyYW0sICc9JywgTkVYVCwgJzsnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZnRlKFxuICAgICAgICAgICAgR0wsICcuJywgR0xfVkFSSUFCTEVTW3BhcmFtXSwgJygnLCBORVhULCAnKTsnLFxuICAgICAgICAgICAgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCBORVhULCAnOycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKE9iamVjdC5rZXlzKGFyZ3Muc3RhdGUpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYmxvY2soQ1VSUkVOVF9TVEFURSwgJy5kaXJ0eT1mYWxzZTsnKTtcbiAgICB9XG4gICAgc2NvcGUoYmxvY2spO1xuICB9XG5cbiAgZnVuY3Rpb24gZW1pdFNldE9wdGlvbnMgKGVudiwgc2NvcGUsIG9wdGlvbnMsIGZpbHRlcikge1xuICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgIHZhciBDVVJSRU5UX1ZBUlMgPSBlbnYuY3VycmVudDtcbiAgICB2YXIgQ1VSUkVOVF9TVEFURSA9IHNoYXJlZC5jdXJyZW50O1xuICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICBzb3J0U3RhdGUoT2JqZWN0LmtleXMob3B0aW9ucykpLmZvckVhY2goZnVuY3Rpb24gKHBhcmFtKSB7XG4gICAgICB2YXIgZGVmbiA9IG9wdGlvbnNbcGFyYW1dO1xuICAgICAgaWYgKGZpbHRlciAmJiAhZmlsdGVyKGRlZm4pKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgdmFyIHZhcmlhYmxlID0gZGVmbi5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICBpZiAoR0xfRkxBR1NbcGFyYW1dKSB7XG4gICAgICAgIHZhciBmbGFnID0gR0xfRkxBR1NbcGFyYW1dO1xuICAgICAgICBpZiAoaXNTdGF0aWMoZGVmbikpIHtcbiAgICAgICAgICBpZiAodmFyaWFibGUpIHtcbiAgICAgICAgICAgIHNjb3BlKEdMLCAnLmVuYWJsZSgnLCBmbGFnLCAnKTsnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2NvcGUoR0wsICcuZGlzYWJsZSgnLCBmbGFnLCAnKTsnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2NvcGUoZW52LmNvbmQodmFyaWFibGUpXG4gICAgICAgICAgICAudGhlbihHTCwgJy5lbmFibGUoJywgZmxhZywgJyk7JylcbiAgICAgICAgICAgIC5lbHNlKEdMLCAnLmRpc2FibGUoJywgZmxhZywgJyk7JykpO1xuICAgICAgICB9XG4gICAgICAgIHNjb3BlKENVUlJFTlRfU1RBVEUsICcuJywgcGFyYW0sICc9JywgdmFyaWFibGUsICc7Jyk7XG4gICAgICB9IGVsc2UgaWYgKGlzQXJyYXlMaWtlKHZhcmlhYmxlKSkge1xuICAgICAgICB2YXIgQ1VSUkVOVCA9IENVUlJFTlRfVkFSU1twYXJhbV07XG4gICAgICAgIHNjb3BlKFxuICAgICAgICAgIEdMLCAnLicsIEdMX1ZBUklBQkxFU1twYXJhbV0sICcoJywgdmFyaWFibGUsICcpOycsXG4gICAgICAgICAgdmFyaWFibGUubWFwKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gQ1VSUkVOVCArICdbJyArIGkgKyAnXT0nICsgdlxuICAgICAgICAgIH0pLmpvaW4oJzsnKSwgJzsnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNjb3BlKFxuICAgICAgICAgIEdMLCAnLicsIEdMX1ZBUklBQkxFU1twYXJhbV0sICcoJywgdmFyaWFibGUsICcpOycsXG4gICAgICAgICAgQ1VSUkVOVF9TVEFURSwgJy4nLCBwYXJhbSwgJz0nLCB2YXJpYWJsZSwgJzsnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluamVjdEV4dGVuc2lvbnMgKGVudiwgc2NvcGUpIHtcbiAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgZW52Lmluc3RhbmNpbmcgPSBzY29wZS5kZWYoXG4gICAgICAgIGVudi5zaGFyZWQuZXh0ZW5zaW9ucywgJy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzJyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW1pdFByb2ZpbGUgKGVudiwgc2NvcGUsIGFyZ3MsIHVzZVNjb3BlLCBpbmNyZW1lbnRDb3VudGVyKSB7XG4gICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG4gICAgdmFyIFNUQVRTID0gZW52LnN0YXRzO1xuICAgIHZhciBDVVJSRU5UX1NUQVRFID0gc2hhcmVkLmN1cnJlbnQ7XG4gICAgdmFyIFRJTUVSID0gc2hhcmVkLnRpbWVyO1xuICAgIHZhciBwcm9maWxlQXJnID0gYXJncy5wcm9maWxlO1xuXG4gICAgZnVuY3Rpb24gcGVyZkNvdW50ZXIgKCkge1xuICAgICAgaWYgKHR5cGVvZiBwZXJmb3JtYW5jZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuICdEYXRlLm5vdygpJ1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuICdwZXJmb3JtYW5jZS5ub3coKSdcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgQ1BVX1NUQVJULCBRVUVSWV9DT1VOVEVSO1xuICAgIGZ1bmN0aW9uIGVtaXRQcm9maWxlU3RhcnQgKGJsb2NrKSB7XG4gICAgICBDUFVfU1RBUlQgPSBzY29wZS5kZWYoKTtcbiAgICAgIGJsb2NrKENQVV9TVEFSVCwgJz0nLCBwZXJmQ291bnRlcigpLCAnOycpO1xuICAgICAgaWYgKHR5cGVvZiBpbmNyZW1lbnRDb3VudGVyID09PSAnc3RyaW5nJykge1xuICAgICAgICBibG9jayhTVEFUUywgJy5jb3VudCs9JywgaW5jcmVtZW50Q291bnRlciwgJzsnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJsb2NrKFNUQVRTLCAnLmNvdW50Kys7Jyk7XG4gICAgICB9XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgaWYgKHVzZVNjb3BlKSB7XG4gICAgICAgICAgUVVFUllfQ09VTlRFUiA9IHNjb3BlLmRlZigpO1xuICAgICAgICAgIGJsb2NrKFFVRVJZX0NPVU5URVIsICc9JywgVElNRVIsICcuZ2V0TnVtUGVuZGluZ1F1ZXJpZXMoKTsnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBibG9jayhUSU1FUiwgJy5iZWdpblF1ZXJ5KCcsIFNUQVRTLCAnKTsnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRQcm9maWxlRW5kIChibG9jaykge1xuICAgICAgYmxvY2soU1RBVFMsICcuY3B1VGltZSs9JywgcGVyZkNvdW50ZXIoKSwgJy0nLCBDUFVfU1RBUlQsICc7Jyk7XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgaWYgKHVzZVNjb3BlKSB7XG4gICAgICAgICAgYmxvY2soVElNRVIsICcucHVzaFNjb3BlU3RhdHMoJyxcbiAgICAgICAgICAgIFFVRVJZX0NPVU5URVIsICcsJyxcbiAgICAgICAgICAgIFRJTUVSLCAnLmdldE51bVBlbmRpbmdRdWVyaWVzKCksJyxcbiAgICAgICAgICAgIFNUQVRTLCAnKTsnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBibG9jayhUSU1FUiwgJy5lbmRRdWVyeSgpOycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2NvcGVQcm9maWxlICh2YWx1ZSkge1xuICAgICAgdmFyIHByZXYgPSBzY29wZS5kZWYoQ1VSUkVOVF9TVEFURSwgJy5wcm9maWxlJyk7XG4gICAgICBzY29wZShDVVJSRU5UX1NUQVRFLCAnLnByb2ZpbGU9JywgdmFsdWUsICc7Jyk7XG4gICAgICBzY29wZS5leGl0KENVUlJFTlRfU1RBVEUsICcucHJvZmlsZT0nLCBwcmV2LCAnOycpO1xuICAgIH1cblxuICAgIHZhciBVU0VfUFJPRklMRTtcbiAgICBpZiAocHJvZmlsZUFyZykge1xuICAgICAgaWYgKGlzU3RhdGljKHByb2ZpbGVBcmcpKSB7XG4gICAgICAgIGlmIChwcm9maWxlQXJnLmVuYWJsZSkge1xuICAgICAgICAgIGVtaXRQcm9maWxlU3RhcnQoc2NvcGUpO1xuICAgICAgICAgIGVtaXRQcm9maWxlRW5kKHNjb3BlLmV4aXQpO1xuICAgICAgICAgIHNjb3BlUHJvZmlsZSgndHJ1ZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNjb3BlUHJvZmlsZSgnZmFsc2UnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIFVTRV9QUk9GSUxFID0gcHJvZmlsZUFyZy5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICBzY29wZVByb2ZpbGUoVVNFX1BST0ZJTEUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBVU0VfUFJPRklMRSA9IHNjb3BlLmRlZihDVVJSRU5UX1NUQVRFLCAnLnByb2ZpbGUnKTtcbiAgICB9XG5cbiAgICB2YXIgc3RhcnQgPSBlbnYuYmxvY2soKTtcbiAgICBlbWl0UHJvZmlsZVN0YXJ0KHN0YXJ0KTtcbiAgICBzY29wZSgnaWYoJywgVVNFX1BST0ZJTEUsICcpeycsIHN0YXJ0LCAnfScpO1xuICAgIHZhciBlbmQgPSBlbnYuYmxvY2soKTtcbiAgICBlbWl0UHJvZmlsZUVuZChlbmQpO1xuICAgIHNjb3BlLmV4aXQoJ2lmKCcsIFVTRV9QUk9GSUxFLCAnKXsnLCBlbmQsICd9Jyk7XG4gIH1cblxuICBmdW5jdGlvbiBlbWl0QXR0cmlidXRlcyAoZW52LCBzY29wZSwgYXJncywgYXR0cmlidXRlcywgZmlsdGVyKSB7XG4gICAgdmFyIHNoYXJlZCA9IGVudi5zaGFyZWQ7XG5cbiAgICBmdW5jdGlvbiB0eXBlTGVuZ3RoICh4KSB7XG4gICAgICBzd2l0Y2ggKHgpIHtcbiAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICBjYXNlIEdMX0lOVF9WRUMyOlxuICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMjpcbiAgICAgICAgICByZXR1cm4gMlxuICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzM6XG4gICAgICAgIGNhc2UgR0xfSU5UX1ZFQzM6XG4gICAgICAgIGNhc2UgR0xfQk9PTF9WRUMzOlxuICAgICAgICAgIHJldHVybiAzXG4gICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDNDpcbiAgICAgICAgY2FzZSBHTF9JTlRfVkVDNDpcbiAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzQ6XG4gICAgICAgICAgcmV0dXJuIDRcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gMVxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRCaW5kQXR0cmlidXRlIChBVFRSSUJVVEUsIHNpemUsIHJlY29yZCkge1xuICAgICAgdmFyIEdMID0gc2hhcmVkLmdsO1xuXG4gICAgICB2YXIgTE9DQVRJT04gPSBzY29wZS5kZWYoQVRUUklCVVRFLCAnLmxvY2F0aW9uJyk7XG4gICAgICB2YXIgQklORElORyA9IHNjb3BlLmRlZihzaGFyZWQuYXR0cmlidXRlcywgJ1snLCBMT0NBVElPTiwgJ10nKTtcblxuICAgICAgdmFyIFNUQVRFID0gcmVjb3JkLnN0YXRlO1xuICAgICAgdmFyIEJVRkZFUiA9IHJlY29yZC5idWZmZXI7XG4gICAgICB2YXIgQ09OU1RfQ09NUE9ORU5UUyA9IFtcbiAgICAgICAgcmVjb3JkLngsXG4gICAgICAgIHJlY29yZC55LFxuICAgICAgICByZWNvcmQueixcbiAgICAgICAgcmVjb3JkLndcbiAgICAgIF07XG5cbiAgICAgIHZhciBDT01NT05fS0VZUyA9IFtcbiAgICAgICAgJ2J1ZmZlcicsXG4gICAgICAgICdub3JtYWxpemVkJyxcbiAgICAgICAgJ29mZnNldCcsXG4gICAgICAgICdzdHJpZGUnXG4gICAgICBdO1xuXG4gICAgICBmdW5jdGlvbiBlbWl0QnVmZmVyICgpIHtcbiAgICAgICAgc2NvcGUoXG4gICAgICAgICAgJ2lmKCEnLCBCSU5ESU5HLCAnLmJ1ZmZlcil7JyxcbiAgICAgICAgICBHTCwgJy5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSgnLCBMT0NBVElPTiwgJyk7fScpO1xuXG4gICAgICAgIHZhciBUWVBFID0gcmVjb3JkLnR5cGU7XG4gICAgICAgIHZhciBTSVpFO1xuICAgICAgICBpZiAoIXJlY29yZC5zaXplKSB7XG4gICAgICAgICAgU0laRSA9IHNpemU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgU0laRSA9IHNjb3BlLmRlZihyZWNvcmQuc2l6ZSwgJ3x8Jywgc2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBzY29wZSgnaWYoJyxcbiAgICAgICAgICBCSU5ESU5HLCAnLnR5cGUhPT0nLCBUWVBFLCAnfHwnLFxuICAgICAgICAgIEJJTkRJTkcsICcuc2l6ZSE9PScsIFNJWkUsICd8fCcsXG4gICAgICAgICAgQ09NTU9OX0tFWVMubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBCSU5ESU5HICsgJy4nICsga2V5ICsgJyE9PScgKyByZWNvcmRba2V5XVxuICAgICAgICAgIH0pLmpvaW4oJ3x8JyksXG4gICAgICAgICAgJyl7JyxcbiAgICAgICAgICBHTCwgJy5iaW5kQnVmZmVyKCcsIEdMX0FSUkFZX0JVRkZFUiQxLCAnLCcsIEJVRkZFUiwgJy5idWZmZXIpOycsXG4gICAgICAgICAgR0wsICcudmVydGV4QXR0cmliUG9pbnRlcignLCBbXG4gICAgICAgICAgICBMT0NBVElPTixcbiAgICAgICAgICAgIFNJWkUsXG4gICAgICAgICAgICBUWVBFLFxuICAgICAgICAgICAgcmVjb3JkLm5vcm1hbGl6ZWQsXG4gICAgICAgICAgICByZWNvcmQuc3RyaWRlLFxuICAgICAgICAgICAgcmVjb3JkLm9mZnNldFxuICAgICAgICAgIF0sICcpOycsXG4gICAgICAgICAgQklORElORywgJy50eXBlPScsIFRZUEUsICc7JyxcbiAgICAgICAgICBCSU5ESU5HLCAnLnNpemU9JywgU0laRSwgJzsnLFxuICAgICAgICAgIENPTU1PTl9LRVlTLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gQklORElORyArICcuJyArIGtleSArICc9JyArIHJlY29yZFtrZXldICsgJzsnXG4gICAgICAgICAgfSkuam9pbignJyksXG4gICAgICAgICAgJ30nKTtcblxuICAgICAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgICAgIHZhciBESVZJU09SID0gcmVjb3JkLmRpdmlzb3I7XG4gICAgICAgICAgc2NvcGUoXG4gICAgICAgICAgICAnaWYoJywgQklORElORywgJy5kaXZpc29yIT09JywgRElWSVNPUiwgJyl7JyxcbiAgICAgICAgICAgIGVudi5pbnN0YW5jaW5nLCAnLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRSgnLCBbTE9DQVRJT04sIERJVklTT1JdLCAnKTsnLFxuICAgICAgICAgICAgQklORElORywgJy5kaXZpc29yPScsIERJVklTT1IsICc7fScpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGVtaXRDb25zdGFudCAoKSB7XG4gICAgICAgIHNjb3BlKFxuICAgICAgICAgICdpZignLCBCSU5ESU5HLCAnLmJ1ZmZlcil7JyxcbiAgICAgICAgICBHTCwgJy5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoJywgTE9DQVRJT04sICcpOycsXG4gICAgICAgICAgJ31pZignLCBDVVRFX0NPTVBPTkVOVFMubWFwKGZ1bmN0aW9uIChjLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gQklORElORyArICcuJyArIGMgKyAnIT09JyArIENPTlNUX0NPTVBPTkVOVFNbaV1cbiAgICAgICAgICB9KS5qb2luKCd8fCcpLCAnKXsnLFxuICAgICAgICAgIEdMLCAnLnZlcnRleEF0dHJpYjRmKCcsIExPQ0FUSU9OLCAnLCcsIENPTlNUX0NPTVBPTkVOVFMsICcpOycsXG4gICAgICAgICAgQ1VURV9DT01QT05FTlRTLm1hcChmdW5jdGlvbiAoYywgaSkge1xuICAgICAgICAgICAgcmV0dXJuIEJJTkRJTkcgKyAnLicgKyBjICsgJz0nICsgQ09OU1RfQ09NUE9ORU5UU1tpXSArICc7J1xuICAgICAgICAgIH0pLmpvaW4oJycpLFxuICAgICAgICAgICd9Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChTVEFURSA9PT0gQVRUUklCX1NUQVRFX1BPSU5URVIpIHtcbiAgICAgICAgZW1pdEJ1ZmZlcigpO1xuICAgICAgfSBlbHNlIGlmIChTVEFURSA9PT0gQVRUUklCX1NUQVRFX0NPTlNUQU5UKSB7XG4gICAgICAgIGVtaXRDb25zdGFudCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2NvcGUoJ2lmKCcsIFNUQVRFLCAnPT09JywgQVRUUklCX1NUQVRFX1BPSU5URVIsICcpeycpO1xuICAgICAgICBlbWl0QnVmZmVyKCk7XG4gICAgICAgIHNjb3BlKCd9ZWxzZXsnKTtcbiAgICAgICAgZW1pdENvbnN0YW50KCk7XG4gICAgICAgIHNjb3BlKCd9Jyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXR0cmlidXRlcy5mb3JFYWNoKGZ1bmN0aW9uIChhdHRyaWJ1dGUpIHtcbiAgICAgIHZhciBuYW1lID0gYXR0cmlidXRlLm5hbWU7XG4gICAgICB2YXIgYXJnID0gYXJncy5hdHRyaWJ1dGVzW25hbWVdO1xuICAgICAgdmFyIHJlY29yZDtcbiAgICAgIGlmIChhcmcpIHtcbiAgICAgICAgaWYgKCFmaWx0ZXIoYXJnKSkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIHJlY29yZCA9IGFyZy5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIWZpbHRlcihTQ09QRV9ERUNMKSkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIHZhciBzY29wZUF0dHJpYiA9IGVudi5zY29wZUF0dHJpYihuYW1lKTtcbiAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZW52LmFzc2VydChzY29wZSxcbiAgICAgICAgICAgIHNjb3BlQXR0cmliICsgJy5zdGF0ZScsXG4gICAgICAgICAgICAnbWlzc2luZyBhdHRyaWJ1dGUgJyArIG5hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVjb3JkID0ge307XG4gICAgICAgIE9iamVjdC5rZXlzKG5ldyBBdHRyaWJ1dGVSZWNvcmQoKSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgcmVjb3JkW2tleV0gPSBzY29wZS5kZWYoc2NvcGVBdHRyaWIsICcuJywga2V5KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBlbWl0QmluZEF0dHJpYnV0ZShcbiAgICAgICAgZW52LmxpbmsoYXR0cmlidXRlKSwgdHlwZUxlbmd0aChhdHRyaWJ1dGUuaW5mby50eXBlKSwgcmVjb3JkKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVtaXRVbmlmb3JtcyAoZW52LCBzY29wZSwgYXJncywgdW5pZm9ybXMsIGZpbHRlcikge1xuICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcblxuICAgIHZhciBpbmZpeDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVuaWZvcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgdW5pZm9ybSA9IHVuaWZvcm1zW2ldO1xuICAgICAgdmFyIG5hbWUgPSB1bmlmb3JtLm5hbWU7XG4gICAgICB2YXIgdHlwZSA9IHVuaWZvcm0uaW5mby50eXBlO1xuICAgICAgdmFyIGFyZyA9IGFyZ3MudW5pZm9ybXNbbmFtZV07XG4gICAgICB2YXIgVU5JRk9STSA9IGVudi5saW5rKHVuaWZvcm0pO1xuICAgICAgdmFyIExPQ0FUSU9OID0gVU5JRk9STSArICcubG9jYXRpb24nO1xuXG4gICAgICB2YXIgVkFMVUU7XG4gICAgICBpZiAoYXJnKSB7XG4gICAgICAgIGlmICghZmlsdGVyKGFyZykpIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc1N0YXRpYyhhcmcpKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gYXJnLnZhbHVlO1xuICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgIHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICAgICAnbWlzc2luZyB1bmlmb3JtIFwiJyArIG5hbWUgKyAnXCInLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgaWYgKHR5cGUgPT09IEdMX1NBTVBMRVJfMkQgfHwgdHlwZSA9PT0gR0xfU0FNUExFUl9DVUJFKSB7XG4gICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgICAgICAgICAoKHR5cGUgPT09IEdMX1NBTVBMRVJfMkQgJiZcbiAgICAgICAgICAgICAgICAodmFsdWUuX3JlZ2xUeXBlID09PSAndGV4dHVyZTJkJyB8fFxuICAgICAgICAgICAgICAgIHZhbHVlLl9yZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyJykpIHx8XG4gICAgICAgICAgICAgICh0eXBlID09PSBHTF9TQU1QTEVSX0NVQkUgJiZcbiAgICAgICAgICAgICAgICAodmFsdWUuX3JlZ2xUeXBlID09PSAndGV4dHVyZUN1YmUnIHx8XG4gICAgICAgICAgICAgICAgdmFsdWUuX3JlZ2xUeXBlID09PSAnZnJhbWVidWZmZXJDdWJlJykpKSxcbiAgICAgICAgICAgICAgJ2ludmFsaWQgdGV4dHVyZSBmb3IgdW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgdmFyIFRFWF9WQUxVRSA9IGVudi5saW5rKHZhbHVlLl90ZXh0dXJlIHx8IHZhbHVlLmNvbG9yWzBdLl90ZXh0dXJlKTtcbiAgICAgICAgICAgIHNjb3BlKEdMLCAnLnVuaWZvcm0xaSgnLCBMT0NBVElPTiwgJywnLCBURVhfVkFMVUUgKyAnLmJpbmQoKSk7Jyk7XG4gICAgICAgICAgICBzY29wZS5leGl0KFRFWF9WQUxVRSwgJy51bmJpbmQoKTsnKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgdHlwZSA9PT0gR0xfRkxPQVRfTUFUMiB8fFxuICAgICAgICAgICAgdHlwZSA9PT0gR0xfRkxPQVRfTUFUMyB8fFxuICAgICAgICAgICAgdHlwZSA9PT0gR0xfRkxPQVRfTUFUNCkge1xuICAgICAgICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChpc0FycmF5TGlrZSh2YWx1ZSksXG4gICAgICAgICAgICAgICAgJ2ludmFsaWQgbWF0cml4IGZvciB1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICAodHlwZSA9PT0gR0xfRkxPQVRfTUFUMiAmJiB2YWx1ZS5sZW5ndGggPT09IDQpIHx8XG4gICAgICAgICAgICAgICAgKHR5cGUgPT09IEdMX0ZMT0FUX01BVDMgJiYgdmFsdWUubGVuZ3RoID09PSA5KSB8fFxuICAgICAgICAgICAgICAgICh0eXBlID09PSBHTF9GTE9BVF9NQVQ0ICYmIHZhbHVlLmxlbmd0aCA9PT0gMTYpLFxuICAgICAgICAgICAgICAgICdpbnZhbGlkIGxlbmd0aCBmb3IgbWF0cml4IHVuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIE1BVF9WQUxVRSA9IGVudi5nbG9iYWwuZGVmKCduZXcgRmxvYXQzMkFycmF5KFsnICtcbiAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodmFsdWUpICsgJ10pJyk7XG4gICAgICAgICAgICB2YXIgZGltID0gMjtcbiAgICAgICAgICAgIGlmICh0eXBlID09PSBHTF9GTE9BVF9NQVQzKSB7XG4gICAgICAgICAgICAgIGRpbSA9IDM7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IEdMX0ZMT0FUX01BVDQpIHtcbiAgICAgICAgICAgICAgZGltID0gNDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNjb3BlKFxuICAgICAgICAgICAgICBHTCwgJy51bmlmb3JtTWF0cml4JywgZGltLCAnZnYoJyxcbiAgICAgICAgICAgICAgTE9DQVRJT04sICcsZmFsc2UsJywgTUFUX1ZBTFVFLCAnKTsnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgIGNhc2UgR0xfRkxPQVQkODpcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnbnVtYmVyJywgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICcxZic7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICAgIGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDIsXG4gICAgICAgICAgICAgICAgICAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIGluZml4ID0gJzJmJztcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzM6XG4gICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgICAgaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMyxcbiAgICAgICAgICAgICAgICAgICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgaW5maXggPSAnM2YnO1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDNDpcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgICAgICBpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LFxuICAgICAgICAgICAgICAgICAgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICc0Zic7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgY2FzZSBHTF9CT09MOlxuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZFR5cGUodmFsdWUsICdib29sZWFuJywgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICcxaSc7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgY2FzZSBHTF9JTlQkMzpcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmRUeXBlKHZhbHVlLCAnbnVtYmVyJywgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICcxaSc7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzI6XG4gICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgICAgaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMixcbiAgICAgICAgICAgICAgICAgICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgaW5maXggPSAnMmknO1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGNhc2UgR0xfSU5UX1ZFQzI6XG4gICAgICAgICAgICAgICAgY2hlY2skMS5jb21tYW5kKFxuICAgICAgICAgICAgICAgICAgaXNBcnJheUxpa2UodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMixcbiAgICAgICAgICAgICAgICAgICd1bmlmb3JtICcgKyBuYW1lLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgICAgICAgICAgaW5maXggPSAnMmknO1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGNhc2UgR0xfQk9PTF9WRUMzOlxuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICAgIGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDMsXG4gICAgICAgICAgICAgICAgICAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIGluZml4ID0gJzNpJztcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBjYXNlIEdMX0lOVF9WRUMzOlxuICAgICAgICAgICAgICAgIGNoZWNrJDEuY29tbWFuZChcbiAgICAgICAgICAgICAgICAgIGlzQXJyYXlMaWtlKHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDMsXG4gICAgICAgICAgICAgICAgICAndW5pZm9ybSAnICsgbmFtZSwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICAgICAgICAgIGluZml4ID0gJzNpJztcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDNDpcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgICAgICBpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LFxuICAgICAgICAgICAgICAgICAgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICc0aSc7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgY2FzZSBHTF9JTlRfVkVDNDpcbiAgICAgICAgICAgICAgICBjaGVjayQxLmNvbW1hbmQoXG4gICAgICAgICAgICAgICAgICBpc0FycmF5TGlrZSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSA0LFxuICAgICAgICAgICAgICAgICAgJ3VuaWZvcm0gJyArIG5hbWUsIGVudi5jb21tYW5kU3RyKTtcbiAgICAgICAgICAgICAgICBpbmZpeCA9ICc0aSc7XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNjb3BlKEdMLCAnLnVuaWZvcm0nLCBpbmZpeCwgJygnLCBMT0NBVElPTiwgJywnLFxuICAgICAgICAgICAgICBpc0FycmF5TGlrZSh2YWx1ZSkgPyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh2YWx1ZSkgOiB2YWx1ZSxcbiAgICAgICAgICAgICAgJyk7Jyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgVkFMVUUgPSBhcmcuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIWZpbHRlcihTQ09QRV9ERUNMKSkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgVkFMVUUgPSBzY29wZS5kZWYoc2hhcmVkLnVuaWZvcm1zLCAnWycsIHN0cmluZ1N0b3JlLmlkKG5hbWUpLCAnXScpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZSA9PT0gR0xfU0FNUExFUl8yRCkge1xuICAgICAgICBzY29wZShcbiAgICAgICAgICAnaWYoJywgVkFMVUUsICcmJicsIFZBTFVFLCAnLl9yZWdsVHlwZT09PVwiZnJhbWVidWZmZXJcIil7JyxcbiAgICAgICAgICBWQUxVRSwgJz0nLCBWQUxVRSwgJy5jb2xvclswXTsnLFxuICAgICAgICAgICd9Jyk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IEdMX1NBTVBMRVJfQ1VCRSkge1xuICAgICAgICBzY29wZShcbiAgICAgICAgICAnaWYoJywgVkFMVUUsICcmJicsIFZBTFVFLCAnLl9yZWdsVHlwZT09PVwiZnJhbWVidWZmZXJDdWJlXCIpeycsXG4gICAgICAgICAgVkFMVUUsICc9JywgVkFMVUUsICcuY29sb3JbMF07JyxcbiAgICAgICAgICAnfScpO1xuICAgICAgfVxuXG4gICAgICAvLyBwZXJmb3JtIHR5cGUgdmFsaWRhdGlvblxuICAgICAgY2hlY2skMS5vcHRpb25hbChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIGNoZWNrIChwcmVkLCBtZXNzYWdlKSB7XG4gICAgICAgICAgZW52LmFzc2VydChzY29wZSwgcHJlZCxcbiAgICAgICAgICAgICdiYWQgZGF0YSBvciBtaXNzaW5nIGZvciB1bmlmb3JtIFwiJyArIG5hbWUgKyAnXCIuICAnICsgbWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBjaGVja1R5cGUgKHR5cGUpIHtcbiAgICAgICAgICBjaGVjayhcbiAgICAgICAgICAgICd0eXBlb2YgJyArIFZBTFVFICsgJz09PVwiJyArIHR5cGUgKyAnXCInLFxuICAgICAgICAgICAgJ2ludmFsaWQgdHlwZSwgZXhwZWN0ZWQgJyArIHR5cGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tWZWN0b3IgKG4sIHR5cGUpIHtcbiAgICAgICAgICBjaGVjayhcbiAgICAgICAgICAgIHNoYXJlZC5pc0FycmF5TGlrZSArICcoJyArIFZBTFVFICsgJykmJicgKyBWQUxVRSArICcubGVuZ3RoPT09JyArIG4sXG4gICAgICAgICAgICAnaW52YWxpZCB2ZWN0b3IsIHNob3VsZCBoYXZlIGxlbmd0aCAnICsgbiwgZW52LmNvbW1hbmRTdHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tUZXh0dXJlICh0YXJnZXQpIHtcbiAgICAgICAgICBjaGVjayhcbiAgICAgICAgICAgICd0eXBlb2YgJyArIFZBTFVFICsgJz09PVwiZnVuY3Rpb25cIiYmJyArXG4gICAgICAgICAgICBWQUxVRSArICcuX3JlZ2xUeXBlPT09XCJ0ZXh0dXJlJyArXG4gICAgICAgICAgICAodGFyZ2V0ID09PSBHTF9URVhUVVJFXzJEJDMgPyAnMmQnIDogJ0N1YmUnKSArICdcIicsXG4gICAgICAgICAgICAnaW52YWxpZCB0ZXh0dXJlIHR5cGUnLCBlbnYuY29tbWFuZFN0cik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICBjYXNlIEdMX0lOVCQzOlxuICAgICAgICAgICAgY2hlY2tUeXBlKCdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9JTlRfVkVDMjpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDIsICdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9JTlRfVkVDMzpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDMsICdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9JTlRfVkVDNDpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9GTE9BVCQ4OlxuICAgICAgICAgICAgY2hlY2tUeXBlKCdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9GTE9BVF9WRUMyOlxuICAgICAgICAgICAgY2hlY2tWZWN0b3IoMiwgJ251bWJlcicpO1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlIEdMX0ZMT0FUX1ZFQzM6XG4gICAgICAgICAgICBjaGVja1ZlY3RvcigzLCAnbnVtYmVyJyk7XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDNDpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9CT09MOlxuICAgICAgICAgICAgY2hlY2tUeXBlKCdib29sZWFuJyk7XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgR0xfQk9PTF9WRUMyOlxuICAgICAgICAgICAgY2hlY2tWZWN0b3IoMiwgJ2Jvb2xlYW4nKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzM6XG4gICAgICAgICAgICBjaGVja1ZlY3RvcigzLCAnYm9vbGVhbicpO1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlIEdMX0JPT0xfVkVDNDpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdib29sZWFuJyk7XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgR0xfRkxPQVRfTUFUMjpcbiAgICAgICAgICAgIGNoZWNrVmVjdG9yKDQsICdudW1iZXInKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9GTE9BVF9NQVQzOlxuICAgICAgICAgICAgY2hlY2tWZWN0b3IoOSwgJ251bWJlcicpO1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDQ6XG4gICAgICAgICAgICBjaGVja1ZlY3RvcigxNiwgJ251bWJlcicpO1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlIEdMX1NBTVBMRVJfMkQ6XG4gICAgICAgICAgICBjaGVja1RleHR1cmUoR0xfVEVYVFVSRV8yRCQzKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBHTF9TQU1QTEVSX0NVQkU6XG4gICAgICAgICAgICBjaGVja1RleHR1cmUoR0xfVEVYVFVSRV9DVUJFX01BUCQyKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB2YXIgdW5yb2xsID0gMTtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIEdMX1NBTVBMRVJfMkQ6XG4gICAgICAgIGNhc2UgR0xfU0FNUExFUl9DVUJFOlxuICAgICAgICAgIHZhciBURVggPSBzY29wZS5kZWYoVkFMVUUsICcuX3RleHR1cmUnKTtcbiAgICAgICAgICBzY29wZShHTCwgJy51bmlmb3JtMWkoJywgTE9DQVRJT04sICcsJywgVEVYLCAnLmJpbmQoKSk7Jyk7XG4gICAgICAgICAgc2NvcGUuZXhpdChURVgsICcudW5iaW5kKCk7Jyk7XG4gICAgICAgICAgY29udGludWVcblxuICAgICAgICBjYXNlIEdMX0lOVCQzOlxuICAgICAgICBjYXNlIEdMX0JPT0w6XG4gICAgICAgICAgaW5maXggPSAnMWknO1xuICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSBHTF9JTlRfVkVDMjpcbiAgICAgICAgY2FzZSBHTF9CT09MX1ZFQzI6XG4gICAgICAgICAgaW5maXggPSAnMmknO1xuICAgICAgICAgIHVucm9sbCA9IDI7XG4gICAgICAgICAgYnJlYWtcblxuICAgICAgICBjYXNlIEdMX0lOVF9WRUMzOlxuICAgICAgICBjYXNlIEdMX0JPT0xfVkVDMzpcbiAgICAgICAgICBpbmZpeCA9ICczaSc7XG4gICAgICAgICAgdW5yb2xsID0gMztcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfSU5UX1ZFQzQ6XG4gICAgICAgIGNhc2UgR0xfQk9PTF9WRUM0OlxuICAgICAgICAgIGluZml4ID0gJzRpJztcbiAgICAgICAgICB1bnJvbGwgPSA0O1xuICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSBHTF9GTE9BVCQ4OlxuICAgICAgICAgIGluZml4ID0gJzFmJztcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDMjpcbiAgICAgICAgICBpbmZpeCA9ICcyZic7XG4gICAgICAgICAgdW5yb2xsID0gMjtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDMzpcbiAgICAgICAgICBpbmZpeCA9ICczZic7XG4gICAgICAgICAgdW5yb2xsID0gMztcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfRkxPQVRfVkVDNDpcbiAgICAgICAgICBpbmZpeCA9ICc0Zic7XG4gICAgICAgICAgdW5yb2xsID0gNDtcbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgR0xfRkxPQVRfTUFUMjpcbiAgICAgICAgICBpbmZpeCA9ICdNYXRyaXgyZnYnO1xuICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgY2FzZSBHTF9GTE9BVF9NQVQzOlxuICAgICAgICAgIGluZml4ID0gJ01hdHJpeDNmdic7XG4gICAgICAgICAgYnJlYWtcblxuICAgICAgICBjYXNlIEdMX0ZMT0FUX01BVDQ6XG4gICAgICAgICAgaW5maXggPSAnTWF0cml4NGZ2JztcbiAgICAgICAgICBicmVha1xuICAgICAgfVxuXG4gICAgICBzY29wZShHTCwgJy51bmlmb3JtJywgaW5maXgsICcoJywgTE9DQVRJT04sICcsJyk7XG4gICAgICBpZiAoaW5maXguY2hhckF0KDApID09PSAnTScpIHtcbiAgICAgICAgdmFyIG1hdFNpemUgPSBNYXRoLnBvdyh0eXBlIC0gR0xfRkxPQVRfTUFUMiArIDIsIDIpO1xuICAgICAgICB2YXIgU1RPUkFHRSA9IGVudi5nbG9iYWwuZGVmKCduZXcgRmxvYXQzMkFycmF5KCcsIG1hdFNpemUsICcpJyk7XG4gICAgICAgIHNjb3BlKFxuICAgICAgICAgICdmYWxzZSwoQXJyYXkuaXNBcnJheSgnLCBWQUxVRSwgJyl8fCcsIFZBTFVFLCAnIGluc3RhbmNlb2YgRmxvYXQzMkFycmF5KT8nLCBWQUxVRSwgJzooJyxcbiAgICAgICAgICBsb29wKG1hdFNpemUsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICByZXR1cm4gU1RPUkFHRSArICdbJyArIGkgKyAnXT0nICsgVkFMVUUgKyAnWycgKyBpICsgJ10nXG4gICAgICAgICAgfSksICcsJywgU1RPUkFHRSwgJyknKTtcbiAgICAgIH0gZWxzZSBpZiAodW5yb2xsID4gMSkge1xuICAgICAgICBzY29wZShsb29wKHVucm9sbCwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICByZXR1cm4gVkFMVUUgKyAnWycgKyBpICsgJ10nXG4gICAgICAgIH0pKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNjb3BlKFZBTFVFKTtcbiAgICAgIH1cbiAgICAgIHNjb3BlKCcpOycpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVtaXREcmF3IChlbnYsIG91dGVyLCBpbm5lciwgYXJncykge1xuICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgIHZhciBHTCA9IHNoYXJlZC5nbDtcbiAgICB2YXIgRFJBV19TVEFURSA9IHNoYXJlZC5kcmF3O1xuXG4gICAgdmFyIGRyYXdPcHRpb25zID0gYXJncy5kcmF3O1xuXG4gICAgZnVuY3Rpb24gZW1pdEVsZW1lbnRzICgpIHtcbiAgICAgIHZhciBkZWZuID0gZHJhd09wdGlvbnMuZWxlbWVudHM7XG4gICAgICB2YXIgRUxFTUVOVFM7XG4gICAgICB2YXIgc2NvcGUgPSBvdXRlcjtcbiAgICAgIGlmIChkZWZuKSB7XG4gICAgICAgIGlmICgoZGVmbi5jb250ZXh0RGVwICYmIGFyZ3MuY29udGV4dER5bmFtaWMpIHx8IGRlZm4ucHJvcERlcCkge1xuICAgICAgICAgIHNjb3BlID0gaW5uZXI7XG4gICAgICAgIH1cbiAgICAgICAgRUxFTUVOVFMgPSBkZWZuLmFwcGVuZChlbnYsIHNjb3BlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEVMRU1FTlRTID0gc2NvcGUuZGVmKERSQVdfU1RBVEUsICcuJywgU19FTEVNRU5UUyk7XG4gICAgICB9XG4gICAgICBpZiAoRUxFTUVOVFMpIHtcbiAgICAgICAgc2NvcGUoXG4gICAgICAgICAgJ2lmKCcgKyBFTEVNRU5UUyArICcpJyArXG4gICAgICAgICAgR0wgKyAnLmJpbmRCdWZmZXIoJyArIEdMX0VMRU1FTlRfQVJSQVlfQlVGRkVSJDEgKyAnLCcgKyBFTEVNRU5UUyArICcuYnVmZmVyLmJ1ZmZlcik7Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gRUxFTUVOVFNcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0Q291bnQgKCkge1xuICAgICAgdmFyIGRlZm4gPSBkcmF3T3B0aW9ucy5jb3VudDtcbiAgICAgIHZhciBDT1VOVDtcbiAgICAgIHZhciBzY29wZSA9IG91dGVyO1xuICAgICAgaWYgKGRlZm4pIHtcbiAgICAgICAgaWYgKChkZWZuLmNvbnRleHREZXAgJiYgYXJncy5jb250ZXh0RHluYW1pYykgfHwgZGVmbi5wcm9wRGVwKSB7XG4gICAgICAgICAgc2NvcGUgPSBpbm5lcjtcbiAgICAgICAgfVxuICAgICAgICBDT1VOVCA9IGRlZm4uYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgICAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoZGVmbi5NSVNTSU5HKSB7XG4gICAgICAgICAgICBlbnYuYXNzZXJ0KG91dGVyLCAnZmFsc2UnLCAnbWlzc2luZyB2ZXJ0ZXggY291bnQnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGRlZm4uRFlOQU1JQykge1xuICAgICAgICAgICAgZW52LmFzc2VydChzY29wZSwgQ09VTlQgKyAnPj0wJywgJ21pc3NpbmcgdmVydGV4IGNvdW50Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIENPVU5UID0gc2NvcGUuZGVmKERSQVdfU1RBVEUsICcuJywgU19DT1VOVCk7XG4gICAgICAgIGNoZWNrJDEub3B0aW9uYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGVudi5hc3NlcnQoc2NvcGUsIENPVU5UICsgJz49MCcsICdtaXNzaW5nIHZlcnRleCBjb3VudCcpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBDT1VOVFxuICAgIH1cblxuICAgIHZhciBFTEVNRU5UUyA9IGVtaXRFbGVtZW50cygpO1xuICAgIGZ1bmN0aW9uIGVtaXRWYWx1ZSAobmFtZSkge1xuICAgICAgdmFyIGRlZm4gPSBkcmF3T3B0aW9uc1tuYW1lXTtcbiAgICAgIGlmIChkZWZuKSB7XG4gICAgICAgIGlmICgoZGVmbi5jb250ZXh0RGVwICYmIGFyZ3MuY29udGV4dER5bmFtaWMpIHx8IGRlZm4ucHJvcERlcCkge1xuICAgICAgICAgIHJldHVybiBkZWZuLmFwcGVuZChlbnYsIGlubmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBkZWZuLmFwcGVuZChlbnYsIG91dGVyKVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gb3V0ZXIuZGVmKERSQVdfU1RBVEUsICcuJywgbmFtZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgUFJJTUlUSVZFID0gZW1pdFZhbHVlKFNfUFJJTUlUSVZFKTtcbiAgICB2YXIgT0ZGU0VUID0gZW1pdFZhbHVlKFNfT0ZGU0VUKTtcblxuICAgIHZhciBDT1VOVCA9IGVtaXRDb3VudCgpO1xuICAgIGlmICh0eXBlb2YgQ09VTlQgPT09ICdudW1iZXInKSB7XG4gICAgICBpZiAoQ09VTlQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlubmVyKCdpZignLCBDT1VOVCwgJyl7Jyk7XG4gICAgICBpbm5lci5leGl0KCd9Jyk7XG4gICAgfVxuXG4gICAgdmFyIElOU1RBTkNFUywgRVhUX0lOU1RBTkNJTkc7XG4gICAgaWYgKGV4dEluc3RhbmNpbmcpIHtcbiAgICAgIElOU1RBTkNFUyA9IGVtaXRWYWx1ZShTX0lOU1RBTkNFUyk7XG4gICAgICBFWFRfSU5TVEFOQ0lORyA9IGVudi5pbnN0YW5jaW5nO1xuICAgIH1cblxuICAgIHZhciBFTEVNRU5UX1RZUEUgPSBFTEVNRU5UUyArICcudHlwZSc7XG5cbiAgICB2YXIgZWxlbWVudHNTdGF0aWMgPSBkcmF3T3B0aW9ucy5lbGVtZW50cyAmJiBpc1N0YXRpYyhkcmF3T3B0aW9ucy5lbGVtZW50cyk7XG5cbiAgICBmdW5jdGlvbiBlbWl0SW5zdGFuY2luZyAoKSB7XG4gICAgICBmdW5jdGlvbiBkcmF3RWxlbWVudHMgKCkge1xuICAgICAgICBpbm5lcihFWFRfSU5TVEFOQ0lORywgJy5kcmF3RWxlbWVudHNJbnN0YW5jZWRBTkdMRSgnLCBbXG4gICAgICAgICAgUFJJTUlUSVZFLFxuICAgICAgICAgIENPVU5ULFxuICAgICAgICAgIEVMRU1FTlRfVFlQRSxcbiAgICAgICAgICBPRkZTRVQgKyAnPDwoKCcgKyBFTEVNRU5UX1RZUEUgKyAnLScgKyBHTF9VTlNJR05FRF9CWVRFJDggKyAnKT4+MSknLFxuICAgICAgICAgIElOU1RBTkNFU1xuICAgICAgICBdLCAnKTsnKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZHJhd0FycmF5cyAoKSB7XG4gICAgICAgIGlubmVyKEVYVF9JTlNUQU5DSU5HLCAnLmRyYXdBcnJheXNJbnN0YW5jZWRBTkdMRSgnLFxuICAgICAgICAgIFtQUklNSVRJVkUsIE9GRlNFVCwgQ09VTlQsIElOU1RBTkNFU10sICcpOycpO1xuICAgICAgfVxuXG4gICAgICBpZiAoRUxFTUVOVFMpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50c1N0YXRpYykge1xuICAgICAgICAgIGlubmVyKCdpZignLCBFTEVNRU5UUywgJyl7Jyk7XG4gICAgICAgICAgZHJhd0VsZW1lbnRzKCk7XG4gICAgICAgICAgaW5uZXIoJ31lbHNleycpO1xuICAgICAgICAgIGRyYXdBcnJheXMoKTtcbiAgICAgICAgICBpbm5lcignfScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRyYXdFbGVtZW50cygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkcmF3QXJyYXlzKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdFJlZ3VsYXIgKCkge1xuICAgICAgZnVuY3Rpb24gZHJhd0VsZW1lbnRzICgpIHtcbiAgICAgICAgaW5uZXIoR0wgKyAnLmRyYXdFbGVtZW50cygnICsgW1xuICAgICAgICAgIFBSSU1JVElWRSxcbiAgICAgICAgICBDT1VOVCxcbiAgICAgICAgICBFTEVNRU5UX1RZUEUsXG4gICAgICAgICAgT0ZGU0VUICsgJzw8KCgnICsgRUxFTUVOVF9UWVBFICsgJy0nICsgR0xfVU5TSUdORURfQllURSQ4ICsgJyk+PjEpJ1xuICAgICAgICBdICsgJyk7Jyk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRyYXdBcnJheXMgKCkge1xuICAgICAgICBpbm5lcihHTCArICcuZHJhd0FycmF5cygnICsgW1BSSU1JVElWRSwgT0ZGU0VULCBDT1VOVF0gKyAnKTsnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKEVMRU1FTlRTKSB7XG4gICAgICAgIGlmICghZWxlbWVudHNTdGF0aWMpIHtcbiAgICAgICAgICBpbm5lcignaWYoJywgRUxFTUVOVFMsICcpeycpO1xuICAgICAgICAgIGRyYXdFbGVtZW50cygpO1xuICAgICAgICAgIGlubmVyKCd9ZWxzZXsnKTtcbiAgICAgICAgICBkcmF3QXJyYXlzKCk7XG4gICAgICAgICAgaW5uZXIoJ30nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkcmF3RWxlbWVudHMoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZHJhd0FycmF5cygpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHRJbnN0YW5jaW5nICYmICh0eXBlb2YgSU5TVEFOQ0VTICE9PSAnbnVtYmVyJyB8fCBJTlNUQU5DRVMgPj0gMCkpIHtcbiAgICAgIGlmICh0eXBlb2YgSU5TVEFOQ0VTID09PSAnc3RyaW5nJykge1xuICAgICAgICBpbm5lcignaWYoJywgSU5TVEFOQ0VTLCAnPjApeycpO1xuICAgICAgICBlbWl0SW5zdGFuY2luZygpO1xuICAgICAgICBpbm5lcignfWVsc2UgaWYoJywgSU5TVEFOQ0VTLCAnPDApeycpO1xuICAgICAgICBlbWl0UmVndWxhcigpO1xuICAgICAgICBpbm5lcignfScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW1pdEluc3RhbmNpbmcoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZW1pdFJlZ3VsYXIoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVCb2R5IChlbWl0Qm9keSwgcGFyZW50RW52LCBhcmdzLCBwcm9ncmFtLCBjb3VudCkge1xuICAgIHZhciBlbnYgPSBjcmVhdGVSRUdMRW52aXJvbm1lbnQoKTtcbiAgICB2YXIgc2NvcGUgPSBlbnYucHJvYygnYm9keScsIGNvdW50KTtcbiAgICBjaGVjayQxLm9wdGlvbmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgIGVudi5jb21tYW5kU3RyID0gcGFyZW50RW52LmNvbW1hbmRTdHI7XG4gICAgICBlbnYuY29tbWFuZCA9IGVudi5saW5rKHBhcmVudEVudi5jb21tYW5kU3RyKTtcbiAgICB9KTtcbiAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgZW52Lmluc3RhbmNpbmcgPSBzY29wZS5kZWYoXG4gICAgICAgIGVudi5zaGFyZWQuZXh0ZW5zaW9ucywgJy5hbmdsZV9pbnN0YW5jZWRfYXJyYXlzJyk7XG4gICAgfVxuICAgIGVtaXRCb2R5KGVudiwgc2NvcGUsIGFyZ3MsIHByb2dyYW0pO1xuICAgIHJldHVybiBlbnYuY29tcGlsZSgpLmJvZHlcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gRFJBVyBQUk9DXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgZnVuY3Rpb24gZW1pdERyYXdCb2R5IChlbnYsIGRyYXcsIGFyZ3MsIHByb2dyYW0pIHtcbiAgICBpbmplY3RFeHRlbnNpb25zKGVudiwgZHJhdyk7XG4gICAgZW1pdEF0dHJpYnV0ZXMoZW52LCBkcmF3LCBhcmdzLCBwcm9ncmFtLmF0dHJpYnV0ZXMsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSk7XG4gICAgZW1pdFVuaWZvcm1zKGVudiwgZHJhdywgYXJncywgcHJvZ3JhbS51bmlmb3JtcywgZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KTtcbiAgICBlbWl0RHJhdyhlbnYsIGRyYXcsIGRyYXcsIGFyZ3MpO1xuICB9XG5cbiAgZnVuY3Rpb24gZW1pdERyYXdQcm9jIChlbnYsIGFyZ3MpIHtcbiAgICB2YXIgZHJhdyA9IGVudi5wcm9jKCdkcmF3JywgMSk7XG5cbiAgICBpbmplY3RFeHRlbnNpb25zKGVudiwgZHJhdyk7XG5cbiAgICBlbWl0Q29udGV4dChlbnYsIGRyYXcsIGFyZ3MuY29udGV4dCk7XG4gICAgZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIGRyYXcsIGFyZ3MuZnJhbWVidWZmZXIpO1xuXG4gICAgZW1pdFBvbGxTdGF0ZShlbnYsIGRyYXcsIGFyZ3MpO1xuICAgIGVtaXRTZXRPcHRpb25zKGVudiwgZHJhdywgYXJncy5zdGF0ZSk7XG5cbiAgICBlbWl0UHJvZmlsZShlbnYsIGRyYXcsIGFyZ3MsIGZhbHNlLCB0cnVlKTtcblxuICAgIHZhciBwcm9ncmFtID0gYXJncy5zaGFkZXIucHJvZ1Zhci5hcHBlbmQoZW52LCBkcmF3KTtcbiAgICBkcmF3KGVudi5zaGFyZWQuZ2wsICcudXNlUHJvZ3JhbSgnLCBwcm9ncmFtLCAnLnByb2dyYW0pOycpO1xuXG4gICAgaWYgKGFyZ3Muc2hhZGVyLnByb2dyYW0pIHtcbiAgICAgIGVtaXREcmF3Qm9keShlbnYsIGRyYXcsIGFyZ3MsIGFyZ3Muc2hhZGVyLnByb2dyYW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZHJhd0NhY2hlID0gZW52Lmdsb2JhbC5kZWYoJ3t9Jyk7XG4gICAgICB2YXIgUFJPR19JRCA9IGRyYXcuZGVmKHByb2dyYW0sICcuaWQnKTtcbiAgICAgIHZhciBDQUNIRURfUFJPQyA9IGRyYXcuZGVmKGRyYXdDYWNoZSwgJ1snLCBQUk9HX0lELCAnXScpO1xuICAgICAgZHJhdyhcbiAgICAgICAgZW52LmNvbmQoQ0FDSEVEX1BST0MpXG4gICAgICAgICAgLnRoZW4oQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwKTsnKVxuICAgICAgICAgIC5lbHNlKFxuICAgICAgICAgICAgQ0FDSEVEX1BST0MsICc9JywgZHJhd0NhY2hlLCAnWycsIFBST0dfSUQsICddPScsXG4gICAgICAgICAgICBlbnYubGluayhmdW5jdGlvbiAocHJvZ3JhbSkge1xuICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlQm9keShlbWl0RHJhd0JvZHksIGVudiwgYXJncywgcHJvZ3JhbSwgMSlcbiAgICAgICAgICAgIH0pLCAnKCcsIHByb2dyYW0sICcpOycsXG4gICAgICAgICAgICBDQUNIRURfUFJPQywgJy5jYWxsKHRoaXMsYTApOycpKTtcbiAgICB9XG5cbiAgICBpZiAoT2JqZWN0LmtleXMoYXJncy5zdGF0ZSkubGVuZ3RoID4gMCkge1xuICAgICAgZHJhdyhlbnYuc2hhcmVkLmN1cnJlbnQsICcuZGlydHk9dHJ1ZTsnKTtcbiAgICB9XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEJBVENIIFBST0NcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIGVtaXRCYXRjaER5bmFtaWNTaGFkZXJCb2R5IChlbnYsIHNjb3BlLCBhcmdzLCBwcm9ncmFtKSB7XG4gICAgZW52LmJhdGNoSWQgPSAnYTEnO1xuXG4gICAgaW5qZWN0RXh0ZW5zaW9ucyhlbnYsIHNjb3BlKTtcblxuICAgIGZ1bmN0aW9uIGFsbCAoKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cblxuICAgIGVtaXRBdHRyaWJ1dGVzKGVudiwgc2NvcGUsIGFyZ3MsIHByb2dyYW0uYXR0cmlidXRlcywgYWxsKTtcbiAgICBlbWl0VW5pZm9ybXMoZW52LCBzY29wZSwgYXJncywgcHJvZ3JhbS51bmlmb3JtcywgYWxsKTtcbiAgICBlbWl0RHJhdyhlbnYsIHNjb3BlLCBzY29wZSwgYXJncyk7XG4gIH1cblxuICBmdW5jdGlvbiBlbWl0QmF0Y2hCb2R5IChlbnYsIHNjb3BlLCBhcmdzLCBwcm9ncmFtKSB7XG4gICAgaW5qZWN0RXh0ZW5zaW9ucyhlbnYsIHNjb3BlKTtcblxuICAgIHZhciBjb250ZXh0RHluYW1pYyA9IGFyZ3MuY29udGV4dERlcDtcblxuICAgIHZhciBCQVRDSF9JRCA9IHNjb3BlLmRlZigpO1xuICAgIHZhciBQUk9QX0xJU1QgPSAnYTAnO1xuICAgIHZhciBOVU1fUFJPUFMgPSAnYTEnO1xuICAgIHZhciBQUk9QUyA9IHNjb3BlLmRlZigpO1xuICAgIGVudi5zaGFyZWQucHJvcHMgPSBQUk9QUztcbiAgICBlbnYuYmF0Y2hJZCA9IEJBVENIX0lEO1xuXG4gICAgdmFyIG91dGVyID0gZW52LnNjb3BlKCk7XG4gICAgdmFyIGlubmVyID0gZW52LnNjb3BlKCk7XG5cbiAgICBzY29wZShcbiAgICAgIG91dGVyLmVudHJ5LFxuICAgICAgJ2ZvcignLCBCQVRDSF9JRCwgJz0wOycsIEJBVENIX0lELCAnPCcsIE5VTV9QUk9QUywgJzsrKycsIEJBVENIX0lELCAnKXsnLFxuICAgICAgUFJPUFMsICc9JywgUFJPUF9MSVNULCAnWycsIEJBVENIX0lELCAnXTsnLFxuICAgICAgaW5uZXIsXG4gICAgICAnfScsXG4gICAgICBvdXRlci5leGl0KTtcblxuICAgIGZ1bmN0aW9uIGlzSW5uZXJEZWZuIChkZWZuKSB7XG4gICAgICByZXR1cm4gKChkZWZuLmNvbnRleHREZXAgJiYgY29udGV4dER5bmFtaWMpIHx8IGRlZm4ucHJvcERlcClcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc091dGVyRGVmbiAoZGVmbikge1xuICAgICAgcmV0dXJuICFpc0lubmVyRGVmbihkZWZuKVxuICAgIH1cblxuICAgIGlmIChhcmdzLm5lZWRzQ29udGV4dCkge1xuICAgICAgZW1pdENvbnRleHQoZW52LCBpbm5lciwgYXJncy5jb250ZXh0KTtcbiAgICB9XG4gICAgaWYgKGFyZ3MubmVlZHNGcmFtZWJ1ZmZlcikge1xuICAgICAgZW1pdFBvbGxGcmFtZWJ1ZmZlcihlbnYsIGlubmVyLCBhcmdzLmZyYW1lYnVmZmVyKTtcbiAgICB9XG4gICAgZW1pdFNldE9wdGlvbnMoZW52LCBpbm5lciwgYXJncy5zdGF0ZSwgaXNJbm5lckRlZm4pO1xuXG4gICAgaWYgKGFyZ3MucHJvZmlsZSAmJiBpc0lubmVyRGVmbihhcmdzLnByb2ZpbGUpKSB7XG4gICAgICBlbWl0UHJvZmlsZShlbnYsIGlubmVyLCBhcmdzLCBmYWxzZSwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgaWYgKCFwcm9ncmFtKSB7XG4gICAgICB2YXIgcHJvZ0NhY2hlID0gZW52Lmdsb2JhbC5kZWYoJ3t9Jyk7XG4gICAgICB2YXIgUFJPR1JBTSA9IGFyZ3Muc2hhZGVyLnByb2dWYXIuYXBwZW5kKGVudiwgaW5uZXIpO1xuICAgICAgdmFyIFBST0dfSUQgPSBpbm5lci5kZWYoUFJPR1JBTSwgJy5pZCcpO1xuICAgICAgdmFyIENBQ0hFRF9QUk9DID0gaW5uZXIuZGVmKHByb2dDYWNoZSwgJ1snLCBQUk9HX0lELCAnXScpO1xuICAgICAgaW5uZXIoXG4gICAgICAgIGVudi5zaGFyZWQuZ2wsICcudXNlUHJvZ3JhbSgnLCBQUk9HUkFNLCAnLnByb2dyYW0pOycsXG4gICAgICAgICdpZighJywgQ0FDSEVEX1BST0MsICcpeycsXG4gICAgICAgIENBQ0hFRF9QUk9DLCAnPScsIHByb2dDYWNoZSwgJ1snLCBQUk9HX0lELCAnXT0nLFxuICAgICAgICBlbnYubGluayhmdW5jdGlvbiAocHJvZ3JhbSkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVCb2R5KFxuICAgICAgICAgICAgZW1pdEJhdGNoRHluYW1pY1NoYWRlckJvZHksIGVudiwgYXJncywgcHJvZ3JhbSwgMilcbiAgICAgICAgfSksICcoJywgUFJPR1JBTSwgJyk7fScsXG4gICAgICAgIENBQ0hFRF9QUk9DLCAnLmNhbGwodGhpcyxhMFsnLCBCQVRDSF9JRCwgJ10sJywgQkFUQ0hfSUQsICcpOycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbWl0QXR0cmlidXRlcyhlbnYsIG91dGVyLCBhcmdzLCBwcm9ncmFtLmF0dHJpYnV0ZXMsIGlzT3V0ZXJEZWZuKTtcbiAgICAgIGVtaXRBdHRyaWJ1dGVzKGVudiwgaW5uZXIsIGFyZ3MsIHByb2dyYW0uYXR0cmlidXRlcywgaXNJbm5lckRlZm4pO1xuICAgICAgZW1pdFVuaWZvcm1zKGVudiwgb3V0ZXIsIGFyZ3MsIHByb2dyYW0udW5pZm9ybXMsIGlzT3V0ZXJEZWZuKTtcbiAgICAgIGVtaXRVbmlmb3JtcyhlbnYsIGlubmVyLCBhcmdzLCBwcm9ncmFtLnVuaWZvcm1zLCBpc0lubmVyRGVmbik7XG4gICAgICBlbWl0RHJhdyhlbnYsIG91dGVyLCBpbm5lciwgYXJncyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZW1pdEJhdGNoUHJvYyAoZW52LCBhcmdzKSB7XG4gICAgdmFyIGJhdGNoID0gZW52LnByb2MoJ2JhdGNoJywgMik7XG4gICAgZW52LmJhdGNoSWQgPSAnMCc7XG5cbiAgICBpbmplY3RFeHRlbnNpb25zKGVudiwgYmF0Y2gpO1xuXG4gICAgLy8gQ2hlY2sgaWYgYW55IGNvbnRleHQgdmFyaWFibGVzIGRlcGVuZCBvbiBwcm9wc1xuICAgIHZhciBjb250ZXh0RHluYW1pYyA9IGZhbHNlO1xuICAgIHZhciBuZWVkc0NvbnRleHQgPSB0cnVlO1xuICAgIE9iamVjdC5rZXlzKGFyZ3MuY29udGV4dCkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgY29udGV4dER5bmFtaWMgPSBjb250ZXh0RHluYW1pYyB8fCBhcmdzLmNvbnRleHRbbmFtZV0ucHJvcERlcDtcbiAgICB9KTtcbiAgICBpZiAoIWNvbnRleHREeW5hbWljKSB7XG4gICAgICBlbWl0Q29udGV4dChlbnYsIGJhdGNoLCBhcmdzLmNvbnRleHQpO1xuICAgICAgbmVlZHNDb250ZXh0ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gZnJhbWVidWZmZXIgc3RhdGUgYWZmZWN0cyBmcmFtZWJ1ZmZlcldpZHRoL2hlaWdodCBjb250ZXh0IHZhcnNcbiAgICB2YXIgZnJhbWVidWZmZXIgPSBhcmdzLmZyYW1lYnVmZmVyO1xuICAgIHZhciBuZWVkc0ZyYW1lYnVmZmVyID0gZmFsc2U7XG4gICAgaWYgKGZyYW1lYnVmZmVyKSB7XG4gICAgICBpZiAoZnJhbWVidWZmZXIucHJvcERlcCkge1xuICAgICAgICBjb250ZXh0RHluYW1pYyA9IG5lZWRzRnJhbWVidWZmZXIgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmcmFtZWJ1ZmZlci5jb250ZXh0RGVwICYmIGNvbnRleHREeW5hbWljKSB7XG4gICAgICAgIG5lZWRzRnJhbWVidWZmZXIgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKCFuZWVkc0ZyYW1lYnVmZmVyKSB7XG4gICAgICAgIGVtaXRQb2xsRnJhbWVidWZmZXIoZW52LCBiYXRjaCwgZnJhbWVidWZmZXIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBlbWl0UG9sbEZyYW1lYnVmZmVyKGVudiwgYmF0Y2gsIG51bGwpO1xuICAgIH1cblxuICAgIC8vIHZpZXdwb3J0IGlzIHdlaXJkIGJlY2F1c2UgaXQgY2FuIGFmZmVjdCBjb250ZXh0IHZhcnNcbiAgICBpZiAoYXJncy5zdGF0ZS52aWV3cG9ydCAmJiBhcmdzLnN0YXRlLnZpZXdwb3J0LnByb3BEZXApIHtcbiAgICAgIGNvbnRleHREeW5hbWljID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0lubmVyRGVmbiAoZGVmbikge1xuICAgICAgcmV0dXJuIChkZWZuLmNvbnRleHREZXAgJiYgY29udGV4dER5bmFtaWMpIHx8IGRlZm4ucHJvcERlcFxuICAgIH1cblxuICAgIC8vIHNldCB3ZWJnbCBvcHRpb25zXG4gICAgZW1pdFBvbGxTdGF0ZShlbnYsIGJhdGNoLCBhcmdzKTtcbiAgICBlbWl0U2V0T3B0aW9ucyhlbnYsIGJhdGNoLCBhcmdzLnN0YXRlLCBmdW5jdGlvbiAoZGVmbikge1xuICAgICAgcmV0dXJuICFpc0lubmVyRGVmbihkZWZuKVxuICAgIH0pO1xuXG4gICAgaWYgKCFhcmdzLnByb2ZpbGUgfHwgIWlzSW5uZXJEZWZuKGFyZ3MucHJvZmlsZSkpIHtcbiAgICAgIGVtaXRQcm9maWxlKGVudiwgYmF0Y2gsIGFyZ3MsIGZhbHNlLCAnYTEnKTtcbiAgICB9XG5cbiAgICAvLyBTYXZlIHRoZXNlIHZhbHVlcyB0byBhcmdzIHNvIHRoYXQgdGhlIGJhdGNoIGJvZHkgcm91dGluZSBjYW4gdXNlIHRoZW1cbiAgICBhcmdzLmNvbnRleHREZXAgPSBjb250ZXh0RHluYW1pYztcbiAgICBhcmdzLm5lZWRzQ29udGV4dCA9IG5lZWRzQ29udGV4dDtcbiAgICBhcmdzLm5lZWRzRnJhbWVidWZmZXIgPSBuZWVkc0ZyYW1lYnVmZmVyO1xuXG4gICAgLy8gZGV0ZXJtaW5lIGlmIHNoYWRlciBpcyBkeW5hbWljXG4gICAgdmFyIHByb2dEZWZuID0gYXJncy5zaGFkZXIucHJvZ1ZhcjtcbiAgICBpZiAoKHByb2dEZWZuLmNvbnRleHREZXAgJiYgY29udGV4dER5bmFtaWMpIHx8IHByb2dEZWZuLnByb3BEZXApIHtcbiAgICAgIGVtaXRCYXRjaEJvZHkoXG4gICAgICAgIGVudixcbiAgICAgICAgYmF0Y2gsXG4gICAgICAgIGFyZ3MsXG4gICAgICAgIG51bGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgUFJPR1JBTSA9IHByb2dEZWZuLmFwcGVuZChlbnYsIGJhdGNoKTtcbiAgICAgIGJhdGNoKGVudi5zaGFyZWQuZ2wsICcudXNlUHJvZ3JhbSgnLCBQUk9HUkFNLCAnLnByb2dyYW0pOycpO1xuICAgICAgaWYgKGFyZ3Muc2hhZGVyLnByb2dyYW0pIHtcbiAgICAgICAgZW1pdEJhdGNoQm9keShcbiAgICAgICAgICBlbnYsXG4gICAgICAgICAgYmF0Y2gsXG4gICAgICAgICAgYXJncyxcbiAgICAgICAgICBhcmdzLnNoYWRlci5wcm9ncmFtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBiYXRjaENhY2hlID0gZW52Lmdsb2JhbC5kZWYoJ3t9Jyk7XG4gICAgICAgIHZhciBQUk9HX0lEID0gYmF0Y2guZGVmKFBST0dSQU0sICcuaWQnKTtcbiAgICAgICAgdmFyIENBQ0hFRF9QUk9DID0gYmF0Y2guZGVmKGJhdGNoQ2FjaGUsICdbJywgUFJPR19JRCwgJ10nKTtcbiAgICAgICAgYmF0Y2goXG4gICAgICAgICAgZW52LmNvbmQoQ0FDSEVEX1BST0MpXG4gICAgICAgICAgICAudGhlbihDQUNIRURfUFJPQywgJy5jYWxsKHRoaXMsYTAsYTEpOycpXG4gICAgICAgICAgICAuZWxzZShcbiAgICAgICAgICAgICAgQ0FDSEVEX1BST0MsICc9JywgYmF0Y2hDYWNoZSwgJ1snLCBQUk9HX0lELCAnXT0nLFxuICAgICAgICAgICAgICBlbnYubGluayhmdW5jdGlvbiAocHJvZ3JhbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVCb2R5KGVtaXRCYXRjaEJvZHksIGVudiwgYXJncywgcHJvZ3JhbSwgMilcbiAgICAgICAgICAgICAgfSksICcoJywgUFJPR1JBTSwgJyk7JyxcbiAgICAgICAgICAgICAgQ0FDSEVEX1BST0MsICcuY2FsbCh0aGlzLGEwLGExKTsnKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKE9iamVjdC5rZXlzKGFyZ3Muc3RhdGUpLmxlbmd0aCA+IDApIHtcbiAgICAgIGJhdGNoKGVudi5zaGFyZWQuY3VycmVudCwgJy5kaXJ0eT10cnVlOycpO1xuICAgIH1cbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gU0NPUEUgQ09NTUFORFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGZ1bmN0aW9uIGVtaXRTY29wZVByb2MgKGVudiwgYXJncykge1xuICAgIHZhciBzY29wZSA9IGVudi5wcm9jKCdzY29wZScsIDMpO1xuICAgIGVudi5iYXRjaElkID0gJ2EyJztcblxuICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgIHZhciBDVVJSRU5UX1NUQVRFID0gc2hhcmVkLmN1cnJlbnQ7XG5cbiAgICBlbWl0Q29udGV4dChlbnYsIHNjb3BlLCBhcmdzLmNvbnRleHQpO1xuXG4gICAgaWYgKGFyZ3MuZnJhbWVidWZmZXIpIHtcbiAgICAgIGFyZ3MuZnJhbWVidWZmZXIuYXBwZW5kKGVudiwgc2NvcGUpO1xuICAgIH1cblxuICAgIHNvcnRTdGF0ZShPYmplY3Qua2V5cyhhcmdzLnN0YXRlKSkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIGRlZm4gPSBhcmdzLnN0YXRlW25hbWVdO1xuICAgICAgdmFyIHZhbHVlID0gZGVmbi5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICBpZiAoaXNBcnJheUxpa2UodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgICAgICBzY29wZS5zZXQoZW52Lm5leHRbbmFtZV0sICdbJyArIGkgKyAnXScsIHYpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNjb3BlLnNldChzaGFyZWQubmV4dCwgJy4nICsgbmFtZSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZW1pdFByb2ZpbGUoZW52LCBzY29wZSwgYXJncywgdHJ1ZSwgdHJ1ZSlcblxuICAgIDtbU19FTEVNRU5UUywgU19PRkZTRVQsIFNfQ09VTlQsIFNfSU5TVEFOQ0VTLCBTX1BSSU1JVElWRV0uZm9yRWFjaChcbiAgICAgIGZ1bmN0aW9uIChvcHQpIHtcbiAgICAgICAgdmFyIHZhcmlhYmxlID0gYXJncy5kcmF3W29wdF07XG4gICAgICAgIGlmICghdmFyaWFibGUpIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBzY29wZS5zZXQoc2hhcmVkLmRyYXcsICcuJyArIG9wdCwgJycgKyB2YXJpYWJsZS5hcHBlbmQoZW52LCBzY29wZSkpO1xuICAgICAgfSk7XG5cbiAgICBPYmplY3Qua2V5cyhhcmdzLnVuaWZvcm1zKS5mb3JFYWNoKGZ1bmN0aW9uIChvcHQpIHtcbiAgICAgIHNjb3BlLnNldChcbiAgICAgICAgc2hhcmVkLnVuaWZvcm1zLFxuICAgICAgICAnWycgKyBzdHJpbmdTdG9yZS5pZChvcHQpICsgJ10nLFxuICAgICAgICBhcmdzLnVuaWZvcm1zW29wdF0uYXBwZW5kKGVudiwgc2NvcGUpKTtcbiAgICB9KTtcblxuICAgIE9iamVjdC5rZXlzKGFyZ3MuYXR0cmlidXRlcykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdmFyIHJlY29yZCA9IGFyZ3MuYXR0cmlidXRlc1tuYW1lXS5hcHBlbmQoZW52LCBzY29wZSk7XG4gICAgICB2YXIgc2NvcGVBdHRyaWIgPSBlbnYuc2NvcGVBdHRyaWIobmFtZSk7XG4gICAgICBPYmplY3Qua2V5cyhuZXcgQXR0cmlidXRlUmVjb3JkKCkpLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHtcbiAgICAgICAgc2NvcGUuc2V0KHNjb3BlQXR0cmliLCAnLicgKyBwcm9wLCByZWNvcmRbcHJvcF0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBzYXZlU2hhZGVyIChuYW1lKSB7XG4gICAgICB2YXIgc2hhZGVyID0gYXJncy5zaGFkZXJbbmFtZV07XG4gICAgICBpZiAoc2hhZGVyKSB7XG4gICAgICAgIHNjb3BlLnNldChzaGFyZWQuc2hhZGVyLCAnLicgKyBuYW1lLCBzaGFkZXIuYXBwZW5kKGVudiwgc2NvcGUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgc2F2ZVNoYWRlcihTX1ZFUlQpO1xuICAgIHNhdmVTaGFkZXIoU19GUkFHKTtcblxuICAgIGlmIChPYmplY3Qua2V5cyhhcmdzLnN0YXRlKS5sZW5ndGggPiAwKSB7XG4gICAgICBzY29wZShDVVJSRU5UX1NUQVRFLCAnLmRpcnR5PXRydWU7Jyk7XG4gICAgICBzY29wZS5leGl0KENVUlJFTlRfU1RBVEUsICcuZGlydHk9dHJ1ZTsnKTtcbiAgICB9XG5cbiAgICBzY29wZSgnYTEoJywgZW52LnNoYXJlZC5jb250ZXh0LCAnLGEwLCcsIGVudi5iYXRjaElkLCAnKTsnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRHluYW1pY09iamVjdCAob2JqZWN0KSB7XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8IGlzQXJyYXlMaWtlKG9iamVjdCkpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB2YXIgcHJvcHMgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChkeW5hbWljLmlzRHluYW1pYyhvYmplY3RbcHJvcHNbaV1dKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIGZ1bmN0aW9uIHNwbGF0T2JqZWN0IChlbnYsIG9wdGlvbnMsIG5hbWUpIHtcbiAgICB2YXIgb2JqZWN0ID0gb3B0aW9ucy5zdGF0aWNbbmFtZV07XG4gICAgaWYgKCFvYmplY3QgfHwgIWlzRHluYW1pY09iamVjdChvYmplY3QpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB2YXIgZ2xvYmFscyA9IGVudi5nbG9iYWw7XG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuICAgIHZhciB0aGlzRGVwID0gZmFsc2U7XG4gICAgdmFyIGNvbnRleHREZXAgPSBmYWxzZTtcbiAgICB2YXIgcHJvcERlcCA9IGZhbHNlO1xuICAgIHZhciBvYmplY3RSZWYgPSBlbnYuZ2xvYmFsLmRlZigne30nKTtcbiAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgICBpZiAoZHluYW1pYy5pc0R5bmFtaWModmFsdWUpKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICB2YWx1ZSA9IG9iamVjdFtrZXldID0gZHluYW1pYy51bmJveCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRlcHMgPSBjcmVhdGVEeW5hbWljRGVjbCh2YWx1ZSwgbnVsbCk7XG4gICAgICAgIHRoaXNEZXAgPSB0aGlzRGVwIHx8IGRlcHMudGhpc0RlcDtcbiAgICAgICAgcHJvcERlcCA9IHByb3BEZXAgfHwgZGVwcy5wcm9wRGVwO1xuICAgICAgICBjb250ZXh0RGVwID0gY29udGV4dERlcCB8fCBkZXBzLmNvbnRleHREZXA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbG9iYWxzKG9iamVjdFJlZiwgJy4nLCBrZXksICc9Jyk7XG4gICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7XG4gICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgIGdsb2JhbHModmFsdWUpO1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgZ2xvYmFscygnXCInLCB2YWx1ZSwgJ1wiJyk7XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgJ29iamVjdCc6XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgZ2xvYmFscygnWycsIHZhbHVlLmpvaW4oKSwgJ10nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGdsb2JhbHMoZW52LmxpbmsodmFsdWUpKTtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgICAgZ2xvYmFscygnOycpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gYXBwZW5kQmxvY2sgKGVudiwgYmxvY2spIHtcbiAgICAgIGtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdFtrZXldO1xuICAgICAgICBpZiAoIWR5bmFtaWMuaXNEeW5hbWljKHZhbHVlKSkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIHZhciByZWYgPSBlbnYuaW52b2tlKGJsb2NrLCB2YWx1ZSk7XG4gICAgICAgIGJsb2NrKG9iamVjdFJlZiwgJy4nLCBrZXksICc9JywgcmVmLCAnOycpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5keW5hbWljW25hbWVdID0gbmV3IGR5bmFtaWMuRHluYW1pY1ZhcmlhYmxlKERZTl9USFVOSywge1xuICAgICAgdGhpc0RlcDogdGhpc0RlcCxcbiAgICAgIGNvbnRleHREZXA6IGNvbnRleHREZXAsXG4gICAgICBwcm9wRGVwOiBwcm9wRGVwLFxuICAgICAgcmVmOiBvYmplY3RSZWYsXG4gICAgICBhcHBlbmQ6IGFwcGVuZEJsb2NrXG4gICAgfSk7XG4gICAgZGVsZXRlIG9wdGlvbnMuc3RhdGljW25hbWVdO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBNQUlOIERSQVcgQ09NTUFORFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGZ1bmN0aW9uIGNvbXBpbGVDb21tYW5kIChvcHRpb25zLCBhdHRyaWJ1dGVzLCB1bmlmb3JtcywgY29udGV4dCwgc3RhdHMpIHtcbiAgICB2YXIgZW52ID0gY3JlYXRlUkVHTEVudmlyb25tZW50KCk7XG5cbiAgICAvLyBsaW5rIHN0YXRzLCBzbyB0aGF0IHdlIGNhbiBlYXNpbHkgYWNjZXNzIGl0IGluIHRoZSBwcm9ncmFtLlxuICAgIGVudi5zdGF0cyA9IGVudi5saW5rKHN0YXRzKTtcblxuICAgIC8vIHNwbGF0IG9wdGlvbnMgYW5kIGF0dHJpYnV0ZXMgdG8gYWxsb3cgZm9yIGR5bmFtaWMgbmVzdGVkIHByb3BlcnRpZXNcbiAgICBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzLnN0YXRpYykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICBzcGxhdE9iamVjdChlbnYsIGF0dHJpYnV0ZXMsIGtleSk7XG4gICAgfSk7XG4gICAgTkVTVEVEX09QVElPTlMuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgc3BsYXRPYmplY3QoZW52LCBvcHRpb25zLCBuYW1lKTtcbiAgICB9KTtcblxuICAgIHZhciBhcmdzID0gcGFyc2VBcmd1bWVudHMob3B0aW9ucywgYXR0cmlidXRlcywgdW5pZm9ybXMsIGNvbnRleHQsIGVudik7XG5cbiAgICBlbWl0RHJhd1Byb2MoZW52LCBhcmdzKTtcbiAgICBlbWl0U2NvcGVQcm9jKGVudiwgYXJncyk7XG4gICAgZW1pdEJhdGNoUHJvYyhlbnYsIGFyZ3MpO1xuXG4gICAgcmV0dXJuIGVudi5jb21waWxlKClcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUE9MTCAvIFJFRlJFU0hcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICByZXR1cm4ge1xuICAgIG5leHQ6IG5leHRTdGF0ZSxcbiAgICBjdXJyZW50OiBjdXJyZW50U3RhdGUsXG4gICAgcHJvY3M6IChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgZW52ID0gY3JlYXRlUkVHTEVudmlyb25tZW50KCk7XG4gICAgICB2YXIgcG9sbCA9IGVudi5wcm9jKCdwb2xsJyk7XG4gICAgICB2YXIgcmVmcmVzaCA9IGVudi5wcm9jKCdyZWZyZXNoJyk7XG4gICAgICB2YXIgY29tbW9uID0gZW52LmJsb2NrKCk7XG4gICAgICBwb2xsKGNvbW1vbik7XG4gICAgICByZWZyZXNoKGNvbW1vbik7XG5cbiAgICAgIHZhciBzaGFyZWQgPSBlbnYuc2hhcmVkO1xuICAgICAgdmFyIEdMID0gc2hhcmVkLmdsO1xuICAgICAgdmFyIE5FWFRfU1RBVEUgPSBzaGFyZWQubmV4dDtcbiAgICAgIHZhciBDVVJSRU5UX1NUQVRFID0gc2hhcmVkLmN1cnJlbnQ7XG5cbiAgICAgIGNvbW1vbihDVVJSRU5UX1NUQVRFLCAnLmRpcnR5PWZhbHNlOycpO1xuXG4gICAgICBlbWl0UG9sbEZyYW1lYnVmZmVyKGVudiwgcG9sbCk7XG4gICAgICBlbWl0UG9sbEZyYW1lYnVmZmVyKGVudiwgcmVmcmVzaCwgbnVsbCwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJlZnJlc2ggdXBkYXRlcyBhbGwgYXR0cmlidXRlIHN0YXRlIGNoYW5nZXNcbiAgICAgIHZhciBJTlNUQU5DSU5HO1xuICAgICAgaWYgKGV4dEluc3RhbmNpbmcpIHtcbiAgICAgICAgSU5TVEFOQ0lORyA9IGVudi5saW5rKGV4dEluc3RhbmNpbmcpO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW1pdHMubWF4QXR0cmlidXRlczsgKytpKSB7XG4gICAgICAgIHZhciBCSU5ESU5HID0gcmVmcmVzaC5kZWYoc2hhcmVkLmF0dHJpYnV0ZXMsICdbJywgaSwgJ10nKTtcbiAgICAgICAgdmFyIGlmdGUgPSBlbnYuY29uZChCSU5ESU5HLCAnLmJ1ZmZlcicpO1xuICAgICAgICBpZnRlLnRoZW4oXG4gICAgICAgICAgR0wsICcuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoJywgaSwgJyk7JyxcbiAgICAgICAgICBHTCwgJy5iaW5kQnVmZmVyKCcsXG4gICAgICAgICAgICBHTF9BUlJBWV9CVUZGRVIkMSwgJywnLFxuICAgICAgICAgICAgQklORElORywgJy5idWZmZXIuYnVmZmVyKTsnLFxuICAgICAgICAgIEdMLCAnLnZlcnRleEF0dHJpYlBvaW50ZXIoJyxcbiAgICAgICAgICAgIGksICcsJyxcbiAgICAgICAgICAgIEJJTkRJTkcsICcuc2l6ZSwnLFxuICAgICAgICAgICAgQklORElORywgJy50eXBlLCcsXG4gICAgICAgICAgICBCSU5ESU5HLCAnLm5vcm1hbGl6ZWQsJyxcbiAgICAgICAgICAgIEJJTkRJTkcsICcuc3RyaWRlLCcsXG4gICAgICAgICAgICBCSU5ESU5HLCAnLm9mZnNldCk7J1xuICAgICAgICApLmVsc2UoXG4gICAgICAgICAgR0wsICcuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KCcsIGksICcpOycsXG4gICAgICAgICAgR0wsICcudmVydGV4QXR0cmliNGYoJyxcbiAgICAgICAgICAgIGksICcsJyxcbiAgICAgICAgICAgIEJJTkRJTkcsICcueCwnLFxuICAgICAgICAgICAgQklORElORywgJy55LCcsXG4gICAgICAgICAgICBCSU5ESU5HLCAnLnosJyxcbiAgICAgICAgICAgIEJJTkRJTkcsICcudyk7JyxcbiAgICAgICAgICBCSU5ESU5HLCAnLmJ1ZmZlcj1udWxsOycpO1xuICAgICAgICByZWZyZXNoKGlmdGUpO1xuICAgICAgICBpZiAoZXh0SW5zdGFuY2luZykge1xuICAgICAgICAgIHJlZnJlc2goXG4gICAgICAgICAgICBJTlNUQU5DSU5HLCAnLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRSgnLFxuICAgICAgICAgICAgaSwgJywnLFxuICAgICAgICAgICAgQklORElORywgJy5kaXZpc29yKTsnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBPYmplY3Qua2V5cyhHTF9GTEFHUykuZm9yRWFjaChmdW5jdGlvbiAoZmxhZykge1xuICAgICAgICB2YXIgY2FwID0gR0xfRkxBR1NbZmxhZ107XG4gICAgICAgIHZhciBORVhUID0gY29tbW9uLmRlZihORVhUX1NUQVRFLCAnLicsIGZsYWcpO1xuICAgICAgICB2YXIgYmxvY2sgPSBlbnYuYmxvY2soKTtcbiAgICAgICAgYmxvY2soJ2lmKCcsIE5FWFQsICcpeycsXG4gICAgICAgICAgR0wsICcuZW5hYmxlKCcsIGNhcCwgJyl9ZWxzZXsnLFxuICAgICAgICAgIEdMLCAnLmRpc2FibGUoJywgY2FwLCAnKX0nLFxuICAgICAgICAgIENVUlJFTlRfU1RBVEUsICcuJywgZmxhZywgJz0nLCBORVhULCAnOycpO1xuICAgICAgICByZWZyZXNoKGJsb2NrKTtcbiAgICAgICAgcG9sbChcbiAgICAgICAgICAnaWYoJywgTkVYVCwgJyE9PScsIENVUlJFTlRfU1RBVEUsICcuJywgZmxhZywgJyl7JyxcbiAgICAgICAgICBibG9jayxcbiAgICAgICAgICAnfScpO1xuICAgICAgfSk7XG5cbiAgICAgIE9iamVjdC5rZXlzKEdMX1ZBUklBQkxFUykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgZnVuYyA9IEdMX1ZBUklBQkxFU1tuYW1lXTtcbiAgICAgICAgdmFyIGluaXQgPSBjdXJyZW50U3RhdGVbbmFtZV07XG4gICAgICAgIHZhciBORVhULCBDVVJSRU5UO1xuICAgICAgICB2YXIgYmxvY2sgPSBlbnYuYmxvY2soKTtcbiAgICAgICAgYmxvY2soR0wsICcuJywgZnVuYywgJygnKTtcbiAgICAgICAgaWYgKGlzQXJyYXlMaWtlKGluaXQpKSB7XG4gICAgICAgICAgdmFyIG4gPSBpbml0Lmxlbmd0aDtcbiAgICAgICAgICBORVhUID0gZW52Lmdsb2JhbC5kZWYoTkVYVF9TVEFURSwgJy4nLCBuYW1lKTtcbiAgICAgICAgICBDVVJSRU5UID0gZW52Lmdsb2JhbC5kZWYoQ1VSUkVOVF9TVEFURSwgJy4nLCBuYW1lKTtcbiAgICAgICAgICBibG9jayhcbiAgICAgICAgICAgIGxvb3AobiwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIE5FWFQgKyAnWycgKyBpICsgJ10nXG4gICAgICAgICAgICB9KSwgJyk7JyxcbiAgICAgICAgICAgIGxvb3AobiwgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIENVUlJFTlQgKyAnWycgKyBpICsgJ109JyArIE5FWFQgKyAnWycgKyBpICsgJ107J1xuICAgICAgICAgICAgfSkuam9pbignJykpO1xuICAgICAgICAgIHBvbGwoXG4gICAgICAgICAgICAnaWYoJywgbG9vcChuLCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICByZXR1cm4gTkVYVCArICdbJyArIGkgKyAnXSE9PScgKyBDVVJSRU5UICsgJ1snICsgaSArICddJ1xuICAgICAgICAgICAgfSkuam9pbignfHwnKSwgJyl7JyxcbiAgICAgICAgICAgIGJsb2NrLFxuICAgICAgICAgICAgJ30nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBORVhUID0gY29tbW9uLmRlZihORVhUX1NUQVRFLCAnLicsIG5hbWUpO1xuICAgICAgICAgIENVUlJFTlQgPSBjb21tb24uZGVmKENVUlJFTlRfU1RBVEUsICcuJywgbmFtZSk7XG4gICAgICAgICAgYmxvY2soXG4gICAgICAgICAgICBORVhULCAnKTsnLFxuICAgICAgICAgICAgQ1VSUkVOVF9TVEFURSwgJy4nLCBuYW1lLCAnPScsIE5FWFQsICc7Jyk7XG4gICAgICAgICAgcG9sbChcbiAgICAgICAgICAgICdpZignLCBORVhULCAnIT09JywgQ1VSUkVOVCwgJyl7JyxcbiAgICAgICAgICAgIGJsb2NrLFxuICAgICAgICAgICAgJ30nKTtcbiAgICAgICAgfVxuICAgICAgICByZWZyZXNoKGJsb2NrKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gZW52LmNvbXBpbGUoKVxuICAgIH0pKCksXG4gICAgY29tcGlsZTogY29tcGlsZUNvbW1hbmRcbiAgfVxufVxuXG5mdW5jdGlvbiBzdGF0cyAoKSB7XG4gIHJldHVybiB7XG4gICAgYnVmZmVyQ291bnQ6IDAsXG4gICAgZWxlbWVudHNDb3VudDogMCxcbiAgICBmcmFtZWJ1ZmZlckNvdW50OiAwLFxuICAgIHNoYWRlckNvdW50OiAwLFxuICAgIHRleHR1cmVDb3VudDogMCxcbiAgICBjdWJlQ291bnQ6IDAsXG4gICAgcmVuZGVyYnVmZmVyQ291bnQ6IDAsXG4gICAgbWF4VGV4dHVyZVVuaXRzOiAwXG4gIH1cbn1cblxudmFyIEdMX1FVRVJZX1JFU1VMVF9FWFQgPSAweDg4NjY7XG52YXIgR0xfUVVFUllfUkVTVUxUX0FWQUlMQUJMRV9FWFQgPSAweDg4Njc7XG52YXIgR0xfVElNRV9FTEFQU0VEX0VYVCA9IDB4ODhCRjtcblxudmFyIGNyZWF0ZVRpbWVyID0gZnVuY3Rpb24gKGdsLCBleHRlbnNpb25zKSB7XG4gIHZhciBleHRUaW1lciA9IGV4dGVuc2lvbnMuZXh0X2Rpc2pvaW50X3RpbWVyX3F1ZXJ5O1xuXG4gIGlmICghZXh0VGltZXIpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgLy8gUVVFUlkgUE9PTCBCRUdJTlxuICB2YXIgcXVlcnlQb29sID0gW107XG4gIGZ1bmN0aW9uIGFsbG9jUXVlcnkgKCkge1xuICAgIHJldHVybiBxdWVyeVBvb2wucG9wKCkgfHwgZXh0VGltZXIuY3JlYXRlUXVlcnlFWFQoKVxuICB9XG4gIGZ1bmN0aW9uIGZyZWVRdWVyeSAocXVlcnkpIHtcbiAgICBxdWVyeVBvb2wucHVzaChxdWVyeSk7XG4gIH1cbiAgLy8gUVVFUlkgUE9PTCBFTkRcblxuICB2YXIgcGVuZGluZ1F1ZXJpZXMgPSBbXTtcbiAgZnVuY3Rpb24gYmVnaW5RdWVyeSAoc3RhdHMpIHtcbiAgICB2YXIgcXVlcnkgPSBhbGxvY1F1ZXJ5KCk7XG4gICAgZXh0VGltZXIuYmVnaW5RdWVyeUVYVChHTF9USU1FX0VMQVBTRURfRVhULCBxdWVyeSk7XG4gICAgcGVuZGluZ1F1ZXJpZXMucHVzaChxdWVyeSk7XG4gICAgcHVzaFNjb3BlU3RhdHMocGVuZGluZ1F1ZXJpZXMubGVuZ3RoIC0gMSwgcGVuZGluZ1F1ZXJpZXMubGVuZ3RoLCBzdGF0cyk7XG4gIH1cblxuICBmdW5jdGlvbiBlbmRRdWVyeSAoKSB7XG4gICAgZXh0VGltZXIuZW5kUXVlcnlFWFQoR0xfVElNRV9FTEFQU0VEX0VYVCk7XG4gIH1cblxuICAvL1xuICAvLyBQZW5kaW5nIHN0YXRzIHBvb2wuXG4gIC8vXG4gIGZ1bmN0aW9uIFBlbmRpbmdTdGF0cyAoKSB7XG4gICAgdGhpcy5zdGFydFF1ZXJ5SW5kZXggPSAtMTtcbiAgICB0aGlzLmVuZFF1ZXJ5SW5kZXggPSAtMTtcbiAgICB0aGlzLnN1bSA9IDA7XG4gICAgdGhpcy5zdGF0cyA9IG51bGw7XG4gIH1cbiAgdmFyIHBlbmRpbmdTdGF0c1Bvb2wgPSBbXTtcbiAgZnVuY3Rpb24gYWxsb2NQZW5kaW5nU3RhdHMgKCkge1xuICAgIHJldHVybiBwZW5kaW5nU3RhdHNQb29sLnBvcCgpIHx8IG5ldyBQZW5kaW5nU3RhdHMoKVxuICB9XG4gIGZ1bmN0aW9uIGZyZWVQZW5kaW5nU3RhdHMgKHBlbmRpbmdTdGF0cykge1xuICAgIHBlbmRpbmdTdGF0c1Bvb2wucHVzaChwZW5kaW5nU3RhdHMpO1xuICB9XG4gIC8vIFBlbmRpbmcgc3RhdHMgcG9vbCBlbmRcblxuICB2YXIgcGVuZGluZ1N0YXRzID0gW107XG4gIGZ1bmN0aW9uIHB1c2hTY29wZVN0YXRzIChzdGFydCwgZW5kLCBzdGF0cykge1xuICAgIHZhciBwcyA9IGFsbG9jUGVuZGluZ1N0YXRzKCk7XG4gICAgcHMuc3RhcnRRdWVyeUluZGV4ID0gc3RhcnQ7XG4gICAgcHMuZW5kUXVlcnlJbmRleCA9IGVuZDtcbiAgICBwcy5zdW0gPSAwO1xuICAgIHBzLnN0YXRzID0gc3RhdHM7XG4gICAgcGVuZGluZ1N0YXRzLnB1c2gocHMpO1xuICB9XG5cbiAgLy8gd2Ugc2hvdWxkIGNhbGwgdGhpcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBmcmFtZSxcbiAgLy8gaW4gb3JkZXIgdG8gdXBkYXRlIGdwdVRpbWVcbiAgdmFyIHRpbWVTdW0gPSBbXTtcbiAgdmFyIHF1ZXJ5UHRyID0gW107XG4gIGZ1bmN0aW9uIHVwZGF0ZSAoKSB7XG4gICAgdmFyIHB0ciwgaTtcblxuICAgIHZhciBuID0gcGVuZGluZ1F1ZXJpZXMubGVuZ3RoO1xuICAgIGlmIChuID09PSAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBSZXNlcnZlIHNwYWNlXG4gICAgcXVlcnlQdHIubGVuZ3RoID0gTWF0aC5tYXgocXVlcnlQdHIubGVuZ3RoLCBuICsgMSk7XG4gICAgdGltZVN1bS5sZW5ndGggPSBNYXRoLm1heCh0aW1lU3VtLmxlbmd0aCwgbiArIDEpO1xuICAgIHRpbWVTdW1bMF0gPSAwO1xuICAgIHF1ZXJ5UHRyWzBdID0gMDtcblxuICAgIC8vIFVwZGF0ZSBhbGwgcGVuZGluZyB0aW1lciBxdWVyaWVzXG4gICAgdmFyIHF1ZXJ5VGltZSA9IDA7XG4gICAgcHRyID0gMDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgcGVuZGluZ1F1ZXJpZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBxdWVyeSA9IHBlbmRpbmdRdWVyaWVzW2ldO1xuICAgICAgaWYgKGV4dFRpbWVyLmdldFF1ZXJ5T2JqZWN0RVhUKHF1ZXJ5LCBHTF9RVUVSWV9SRVNVTFRfQVZBSUxBQkxFX0VYVCkpIHtcbiAgICAgICAgcXVlcnlUaW1lICs9IGV4dFRpbWVyLmdldFF1ZXJ5T2JqZWN0RVhUKHF1ZXJ5LCBHTF9RVUVSWV9SRVNVTFRfRVhUKTtcbiAgICAgICAgZnJlZVF1ZXJ5KHF1ZXJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlbmRpbmdRdWVyaWVzW3B0cisrXSA9IHF1ZXJ5O1xuICAgICAgfVxuICAgICAgdGltZVN1bVtpICsgMV0gPSBxdWVyeVRpbWU7XG4gICAgICBxdWVyeVB0cltpICsgMV0gPSBwdHI7XG4gICAgfVxuICAgIHBlbmRpbmdRdWVyaWVzLmxlbmd0aCA9IHB0cjtcblxuICAgIC8vIFVwZGF0ZSBhbGwgcGVuZGluZyBzdGF0IHF1ZXJpZXNcbiAgICBwdHIgPSAwO1xuICAgIGZvciAoaSA9IDA7IGkgPCBwZW5kaW5nU3RhdHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBzdGF0cyA9IHBlbmRpbmdTdGF0c1tpXTtcbiAgICAgIHZhciBzdGFydCA9IHN0YXRzLnN0YXJ0UXVlcnlJbmRleDtcbiAgICAgIHZhciBlbmQgPSBzdGF0cy5lbmRRdWVyeUluZGV4O1xuICAgICAgc3RhdHMuc3VtICs9IHRpbWVTdW1bZW5kXSAtIHRpbWVTdW1bc3RhcnRdO1xuICAgICAgdmFyIHN0YXJ0UHRyID0gcXVlcnlQdHJbc3RhcnRdO1xuICAgICAgdmFyIGVuZFB0ciA9IHF1ZXJ5UHRyW2VuZF07XG4gICAgICBpZiAoZW5kUHRyID09PSBzdGFydFB0cikge1xuICAgICAgICBzdGF0cy5zdGF0cy5ncHVUaW1lICs9IHN0YXRzLnN1bSAvIDFlNjtcbiAgICAgICAgZnJlZVBlbmRpbmdTdGF0cyhzdGF0cyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGF0cy5zdGFydFF1ZXJ5SW5kZXggPSBzdGFydFB0cjtcbiAgICAgICAgc3RhdHMuZW5kUXVlcnlJbmRleCA9IGVuZFB0cjtcbiAgICAgICAgcGVuZGluZ1N0YXRzW3B0cisrXSA9IHN0YXRzO1xuICAgICAgfVxuICAgIH1cbiAgICBwZW5kaW5nU3RhdHMubGVuZ3RoID0gcHRyO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBiZWdpblF1ZXJ5OiBiZWdpblF1ZXJ5LFxuICAgIGVuZFF1ZXJ5OiBlbmRRdWVyeSxcbiAgICBwdXNoU2NvcGVTdGF0czogcHVzaFNjb3BlU3RhdHMsXG4gICAgdXBkYXRlOiB1cGRhdGUsXG4gICAgZ2V0TnVtUGVuZGluZ1F1ZXJpZXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBwZW5kaW5nUXVlcmllcy5sZW5ndGhcbiAgICB9LFxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICBxdWVyeVBvb2wucHVzaC5hcHBseShxdWVyeVBvb2wsIHBlbmRpbmdRdWVyaWVzKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXVlcnlQb29sLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGV4dFRpbWVyLmRlbGV0ZVF1ZXJ5RVhUKHF1ZXJ5UG9vbFtpXSk7XG4gICAgICB9XG4gICAgICBwZW5kaW5nUXVlcmllcy5sZW5ndGggPSAwO1xuICAgICAgcXVlcnlQb29sLmxlbmd0aCA9IDA7XG4gICAgfSxcbiAgICByZXN0b3JlOiBmdW5jdGlvbiAoKSB7XG4gICAgICBwZW5kaW5nUXVlcmllcy5sZW5ndGggPSAwO1xuICAgICAgcXVlcnlQb29sLmxlbmd0aCA9IDA7XG4gICAgfVxuICB9XG59O1xuXG52YXIgR0xfQ09MT1JfQlVGRkVSX0JJVCA9IDE2Mzg0O1xudmFyIEdMX0RFUFRIX0JVRkZFUl9CSVQgPSAyNTY7XG52YXIgR0xfU1RFTkNJTF9CVUZGRVJfQklUID0gMTAyNDtcblxudmFyIEdMX0FSUkFZX0JVRkZFUiA9IDM0OTYyO1xuXG52YXIgQ09OVEVYVF9MT1NUX0VWRU5UID0gJ3dlYmdsY29udGV4dGxvc3QnO1xudmFyIENPTlRFWFRfUkVTVE9SRURfRVZFTlQgPSAnd2ViZ2xjb250ZXh0cmVzdG9yZWQnO1xuXG52YXIgRFlOX1BST1AgPSAxO1xudmFyIERZTl9DT05URVhUID0gMjtcbnZhciBEWU5fU1RBVEUgPSAzO1xuXG5mdW5jdGlvbiBmaW5kIChoYXlzdGFjaywgbmVlZGxlKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGF5c3RhY2subGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoaGF5c3RhY2tbaV0gPT09IG5lZWRsZSkge1xuICAgICAgcmV0dXJuIGlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIC0xXG59XG5cbmZ1bmN0aW9uIHdyYXBSRUdMIChhcmdzKSB7XG4gIHZhciBjb25maWcgPSBwYXJzZUFyZ3MoYXJncyk7XG4gIGlmICghY29uZmlnKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBnbCA9IGNvbmZpZy5nbDtcbiAgdmFyIGdsQXR0cmlidXRlcyA9IGdsLmdldENvbnRleHRBdHRyaWJ1dGVzKCk7XG4gIHZhciBjb250ZXh0TG9zdCA9IGdsLmlzQ29udGV4dExvc3QoKTtcblxuICB2YXIgZXh0ZW5zaW9uU3RhdGUgPSBjcmVhdGVFeHRlbnNpb25DYWNoZShnbCwgY29uZmlnKTtcbiAgaWYgKCFleHRlbnNpb25TdGF0ZSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgc3RyaW5nU3RvcmUgPSBjcmVhdGVTdHJpbmdTdG9yZSgpO1xuICB2YXIgc3RhdHMkJDEgPSBzdGF0cygpO1xuICB2YXIgZXh0ZW5zaW9ucyA9IGV4dGVuc2lvblN0YXRlLmV4dGVuc2lvbnM7XG4gIHZhciB0aW1lciA9IGNyZWF0ZVRpbWVyKGdsLCBleHRlbnNpb25zKTtcblxuICB2YXIgU1RBUlRfVElNRSA9IGNsb2NrKCk7XG4gIHZhciBXSURUSCA9IGdsLmRyYXdpbmdCdWZmZXJXaWR0aDtcbiAgdmFyIEhFSUdIVCA9IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQ7XG5cbiAgdmFyIGNvbnRleHRTdGF0ZSA9IHtcbiAgICB0aWNrOiAwLFxuICAgIHRpbWU6IDAsXG4gICAgdmlld3BvcnRXaWR0aDogV0lEVEgsXG4gICAgdmlld3BvcnRIZWlnaHQ6IEhFSUdIVCxcbiAgICBmcmFtZWJ1ZmZlcldpZHRoOiBXSURUSCxcbiAgICBmcmFtZWJ1ZmZlckhlaWdodDogSEVJR0hULFxuICAgIGRyYXdpbmdCdWZmZXJXaWR0aDogV0lEVEgsXG4gICAgZHJhd2luZ0J1ZmZlckhlaWdodDogSEVJR0hULFxuICAgIHBpeGVsUmF0aW86IGNvbmZpZy5waXhlbFJhdGlvXG4gIH07XG4gIHZhciB1bmlmb3JtU3RhdGUgPSB7fTtcbiAgdmFyIGRyYXdTdGF0ZSA9IHtcbiAgICBlbGVtZW50czogbnVsbCxcbiAgICBwcmltaXRpdmU6IDQsIC8vIEdMX1RSSUFOR0xFU1xuICAgIGNvdW50OiAtMSxcbiAgICBvZmZzZXQ6IDAsXG4gICAgaW5zdGFuY2VzOiAtMVxuICB9O1xuXG4gIHZhciBsaW1pdHMgPSB3cmFwTGltaXRzKGdsLCBleHRlbnNpb25zKTtcbiAgdmFyIGF0dHJpYnV0ZVN0YXRlID0gd3JhcEF0dHJpYnV0ZVN0YXRlKFxuICAgIGdsLFxuICAgIGV4dGVuc2lvbnMsXG4gICAgbGltaXRzLFxuICAgIHN0cmluZ1N0b3JlKTtcbiAgdmFyIGJ1ZmZlclN0YXRlID0gd3JhcEJ1ZmZlclN0YXRlKFxuICAgIGdsLFxuICAgIHN0YXRzJCQxLFxuICAgIGNvbmZpZyxcbiAgICBhdHRyaWJ1dGVTdGF0ZSk7XG4gIHZhciBlbGVtZW50U3RhdGUgPSB3cmFwRWxlbWVudHNTdGF0ZShnbCwgZXh0ZW5zaW9ucywgYnVmZmVyU3RhdGUsIHN0YXRzJCQxKTtcbiAgdmFyIHNoYWRlclN0YXRlID0gd3JhcFNoYWRlclN0YXRlKGdsLCBzdHJpbmdTdG9yZSwgc3RhdHMkJDEsIGNvbmZpZyk7XG4gIHZhciB0ZXh0dXJlU3RhdGUgPSBjcmVhdGVUZXh0dXJlU2V0KFxuICAgIGdsLFxuICAgIGV4dGVuc2lvbnMsXG4gICAgbGltaXRzLFxuICAgIGZ1bmN0aW9uICgpIHsgY29yZS5wcm9jcy5wb2xsKCk7IH0sXG4gICAgY29udGV4dFN0YXRlLFxuICAgIHN0YXRzJCQxLFxuICAgIGNvbmZpZyk7XG4gIHZhciByZW5kZXJidWZmZXJTdGF0ZSA9IHdyYXBSZW5kZXJidWZmZXJzKGdsLCBleHRlbnNpb25zLCBsaW1pdHMsIHN0YXRzJCQxLCBjb25maWcpO1xuICB2YXIgZnJhbWVidWZmZXJTdGF0ZSA9IHdyYXBGQk9TdGF0ZShcbiAgICBnbCxcbiAgICBleHRlbnNpb25zLFxuICAgIGxpbWl0cyxcbiAgICB0ZXh0dXJlU3RhdGUsXG4gICAgcmVuZGVyYnVmZmVyU3RhdGUsXG4gICAgc3RhdHMkJDEpO1xuICB2YXIgY29yZSA9IHJlZ2xDb3JlKFxuICAgIGdsLFxuICAgIHN0cmluZ1N0b3JlLFxuICAgIGV4dGVuc2lvbnMsXG4gICAgbGltaXRzLFxuICAgIGJ1ZmZlclN0YXRlLFxuICAgIGVsZW1lbnRTdGF0ZSxcbiAgICB0ZXh0dXJlU3RhdGUsXG4gICAgZnJhbWVidWZmZXJTdGF0ZSxcbiAgICB1bmlmb3JtU3RhdGUsXG4gICAgYXR0cmlidXRlU3RhdGUsXG4gICAgc2hhZGVyU3RhdGUsXG4gICAgZHJhd1N0YXRlLFxuICAgIGNvbnRleHRTdGF0ZSxcbiAgICB0aW1lcixcbiAgICBjb25maWcpO1xuICB2YXIgcmVhZFBpeGVscyA9IHdyYXBSZWFkUGl4ZWxzKFxuICAgIGdsLFxuICAgIGZyYW1lYnVmZmVyU3RhdGUsXG4gICAgY29yZS5wcm9jcy5wb2xsLFxuICAgIGNvbnRleHRTdGF0ZSxcbiAgICBnbEF0dHJpYnV0ZXMsIGV4dGVuc2lvbnMsIGxpbWl0cyk7XG5cbiAgdmFyIG5leHRTdGF0ZSA9IGNvcmUubmV4dDtcbiAgdmFyIGNhbnZhcyA9IGdsLmNhbnZhcztcblxuICB2YXIgcmFmQ2FsbGJhY2tzID0gW107XG4gIHZhciBsb3NzQ2FsbGJhY2tzID0gW107XG4gIHZhciByZXN0b3JlQ2FsbGJhY2tzID0gW107XG4gIHZhciBkZXN0cm95Q2FsbGJhY2tzID0gW2NvbmZpZy5vbkRlc3Ryb3ldO1xuXG4gIHZhciBhY3RpdmVSQUYgPSBudWxsO1xuICBmdW5jdGlvbiBoYW5kbGVSQUYgKCkge1xuICAgIGlmIChyYWZDYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgdGltZXIudXBkYXRlKCk7XG4gICAgICB9XG4gICAgICBhY3RpdmVSQUYgPSBudWxsO1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gc2NoZWR1bGUgbmV4dCBhbmltYXRpb24gZnJhbWVcbiAgICBhY3RpdmVSQUYgPSByYWYubmV4dChoYW5kbGVSQUYpO1xuXG4gICAgLy8gcG9sbCBmb3IgY2hhbmdlc1xuICAgIHBvbGwoKTtcblxuICAgIC8vIGZpcmUgYSBjYWxsYmFjayBmb3IgYWxsIHBlbmRpbmcgcmFmc1xuICAgIGZvciAodmFyIGkgPSByYWZDYWxsYmFja3MubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHZhciBjYiA9IHJhZkNhbGxiYWNrc1tpXTtcbiAgICAgIGlmIChjYikge1xuICAgICAgICBjYihjb250ZXh0U3RhdGUsIG51bGwsIDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZsdXNoIGFsbCBwZW5kaW5nIHdlYmdsIGNhbGxzXG4gICAgZ2wuZmx1c2goKTtcblxuICAgIC8vIHBvbGwgR1BVIHRpbWVycyAqYWZ0ZXIqIGdsLmZsdXNoIHNvIHdlIGRvbid0IGRlbGF5IGNvbW1hbmQgZGlzcGF0Y2hcbiAgICBpZiAodGltZXIpIHtcbiAgICAgIHRpbWVyLnVwZGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0YXJ0UkFGICgpIHtcbiAgICBpZiAoIWFjdGl2ZVJBRiAmJiByYWZDYWxsYmFja3MubGVuZ3RoID4gMCkge1xuICAgICAgYWN0aXZlUkFGID0gcmFmLm5leHQoaGFuZGxlUkFGKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzdG9wUkFGICgpIHtcbiAgICBpZiAoYWN0aXZlUkFGKSB7XG4gICAgICByYWYuY2FuY2VsKGhhbmRsZVJBRik7XG4gICAgICBhY3RpdmVSQUYgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUNvbnRleHRMb3NzIChldmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAvLyBzZXQgY29udGV4dCBsb3N0IGZsYWdcbiAgICBjb250ZXh0TG9zdCA9IHRydWU7XG5cbiAgICAvLyBwYXVzZSByZXF1ZXN0IGFuaW1hdGlvbiBmcmFtZVxuICAgIHN0b3BSQUYoKTtcblxuICAgIC8vIGxvc2UgY29udGV4dFxuICAgIGxvc3NDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgIGNiKCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVDb250ZXh0UmVzdG9yZWQgKGV2ZW50KSB7XG4gICAgLy8gY2xlYXIgZXJyb3IgY29kZVxuICAgIGdsLmdldEVycm9yKCk7XG5cbiAgICAvLyBjbGVhciBjb250ZXh0IGxvc3QgZmxhZ1xuICAgIGNvbnRleHRMb3N0ID0gZmFsc2U7XG5cbiAgICAvLyByZWZyZXNoIHN0YXRlXG4gICAgZXh0ZW5zaW9uU3RhdGUucmVzdG9yZSgpO1xuICAgIHNoYWRlclN0YXRlLnJlc3RvcmUoKTtcbiAgICBidWZmZXJTdGF0ZS5yZXN0b3JlKCk7XG4gICAgdGV4dHVyZVN0YXRlLnJlc3RvcmUoKTtcbiAgICByZW5kZXJidWZmZXJTdGF0ZS5yZXN0b3JlKCk7XG4gICAgZnJhbWVidWZmZXJTdGF0ZS5yZXN0b3JlKCk7XG4gICAgaWYgKHRpbWVyKSB7XG4gICAgICB0aW1lci5yZXN0b3JlKCk7XG4gICAgfVxuXG4gICAgLy8gcmVmcmVzaCBzdGF0ZVxuICAgIGNvcmUucHJvY3MucmVmcmVzaCgpO1xuXG4gICAgLy8gcmVzdGFydCBSQUZcbiAgICBzdGFydFJBRigpO1xuXG4gICAgLy8gcmVzdG9yZSBjb250ZXh0XG4gICAgcmVzdG9yZUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgY2IoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChjYW52YXMpIHtcbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcihDT05URVhUX0xPU1RfRVZFTlQsIGhhbmRsZUNvbnRleHRMb3NzLCBmYWxzZSk7XG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoQ09OVEVYVF9SRVNUT1JFRF9FVkVOVCwgaGFuZGxlQ29udGV4dFJlc3RvcmVkLCBmYWxzZSk7XG4gIH1cblxuICBmdW5jdGlvbiBkZXN0cm95ICgpIHtcbiAgICByYWZDYWxsYmFja3MubGVuZ3RoID0gMDtcbiAgICBzdG9wUkFGKCk7XG5cbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBjYW52YXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihDT05URVhUX0xPU1RfRVZFTlQsIGhhbmRsZUNvbnRleHRMb3NzKTtcbiAgICAgIGNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKENPTlRFWFRfUkVTVE9SRURfRVZFTlQsIGhhbmRsZUNvbnRleHRSZXN0b3JlZCk7XG4gICAgfVxuXG4gICAgc2hhZGVyU3RhdGUuY2xlYXIoKTtcbiAgICBmcmFtZWJ1ZmZlclN0YXRlLmNsZWFyKCk7XG4gICAgcmVuZGVyYnVmZmVyU3RhdGUuY2xlYXIoKTtcbiAgICB0ZXh0dXJlU3RhdGUuY2xlYXIoKTtcbiAgICBlbGVtZW50U3RhdGUuY2xlYXIoKTtcbiAgICBidWZmZXJTdGF0ZS5jbGVhcigpO1xuXG4gICAgaWYgKHRpbWVyKSB7XG4gICAgICB0aW1lci5jbGVhcigpO1xuICAgIH1cblxuICAgIGRlc3Ryb3lDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgIGNiKCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBjb21waWxlUHJvY2VkdXJlIChvcHRpb25zKSB7XG4gICAgY2hlY2skMSghIW9wdGlvbnMsICdpbnZhbGlkIGFyZ3MgdG8gcmVnbCh7Li4ufSknKTtcbiAgICBjaGVjayQxLnR5cGUob3B0aW9ucywgJ29iamVjdCcsICdpbnZhbGlkIGFyZ3MgdG8gcmVnbCh7Li4ufSknKTtcblxuICAgIGZ1bmN0aW9uIGZsYXR0ZW5OZXN0ZWRPcHRpb25zIChvcHRpb25zKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gZXh0ZW5kKHt9LCBvcHRpb25zKTtcbiAgICAgIGRlbGV0ZSByZXN1bHQudW5pZm9ybXM7XG4gICAgICBkZWxldGUgcmVzdWx0LmF0dHJpYnV0ZXM7XG4gICAgICBkZWxldGUgcmVzdWx0LmNvbnRleHQ7XG5cbiAgICAgIGlmICgnc3RlbmNpbCcgaW4gcmVzdWx0ICYmIHJlc3VsdC5zdGVuY2lsLm9wKSB7XG4gICAgICAgIHJlc3VsdC5zdGVuY2lsLm9wQmFjayA9IHJlc3VsdC5zdGVuY2lsLm9wRnJvbnQgPSByZXN1bHQuc3RlbmNpbC5vcDtcbiAgICAgICAgZGVsZXRlIHJlc3VsdC5zdGVuY2lsLm9wO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBtZXJnZSAobmFtZSkge1xuICAgICAgICBpZiAobmFtZSBpbiByZXN1bHQpIHtcbiAgICAgICAgICB2YXIgY2hpbGQgPSByZXN1bHRbbmFtZV07XG4gICAgICAgICAgZGVsZXRlIHJlc3VsdFtuYW1lXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhjaGlsZCkuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgICAgICAgcmVzdWx0W25hbWUgKyAnLicgKyBwcm9wXSA9IGNoaWxkW3Byb3BdO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBtZXJnZSgnYmxlbmQnKTtcbiAgICAgIG1lcmdlKCdkZXB0aCcpO1xuICAgICAgbWVyZ2UoJ2N1bGwnKTtcbiAgICAgIG1lcmdlKCdzdGVuY2lsJyk7XG4gICAgICBtZXJnZSgncG9seWdvbk9mZnNldCcpO1xuICAgICAgbWVyZ2UoJ3NjaXNzb3InKTtcbiAgICAgIG1lcmdlKCdzYW1wbGUnKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNlcGFyYXRlRHluYW1pYyAob2JqZWN0KSB7XG4gICAgICB2YXIgc3RhdGljSXRlbXMgPSB7fTtcbiAgICAgIHZhciBkeW5hbWljSXRlbXMgPSB7fTtcbiAgICAgIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdFtvcHRpb25dO1xuICAgICAgICBpZiAoZHluYW1pYy5pc0R5bmFtaWModmFsdWUpKSB7XG4gICAgICAgICAgZHluYW1pY0l0ZW1zW29wdGlvbl0gPSBkeW5hbWljLnVuYm94KHZhbHVlLCBvcHRpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YXRpY0l0ZW1zW29wdGlvbl0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkeW5hbWljOiBkeW5hbWljSXRlbXMsXG4gICAgICAgIHN0YXRpYzogc3RhdGljSXRlbXNcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUcmVhdCBjb250ZXh0IHZhcmlhYmxlcyBzZXBhcmF0ZSBmcm9tIG90aGVyIGR5bmFtaWMgdmFyaWFibGVzXG4gICAgdmFyIGNvbnRleHQgPSBzZXBhcmF0ZUR5bmFtaWMob3B0aW9ucy5jb250ZXh0IHx8IHt9KTtcbiAgICB2YXIgdW5pZm9ybXMgPSBzZXBhcmF0ZUR5bmFtaWMob3B0aW9ucy51bmlmb3JtcyB8fCB7fSk7XG4gICAgdmFyIGF0dHJpYnV0ZXMgPSBzZXBhcmF0ZUR5bmFtaWMob3B0aW9ucy5hdHRyaWJ1dGVzIHx8IHt9KTtcbiAgICB2YXIgb3B0cyA9IHNlcGFyYXRlRHluYW1pYyhmbGF0dGVuTmVzdGVkT3B0aW9ucyhvcHRpb25zKSk7XG5cbiAgICB2YXIgc3RhdHMkJDEgPSB7XG4gICAgICBncHVUaW1lOiAwLjAsXG4gICAgICBjcHVUaW1lOiAwLjAsXG4gICAgICBjb3VudDogMFxuICAgIH07XG5cbiAgICB2YXIgY29tcGlsZWQgPSBjb3JlLmNvbXBpbGUob3B0cywgYXR0cmlidXRlcywgdW5pZm9ybXMsIGNvbnRleHQsIHN0YXRzJCQxKTtcblxuICAgIHZhciBkcmF3ID0gY29tcGlsZWQuZHJhdztcbiAgICB2YXIgYmF0Y2ggPSBjb21waWxlZC5iYXRjaDtcbiAgICB2YXIgc2NvcGUgPSBjb21waWxlZC5zY29wZTtcblxuICAgIC8vIEZJWE1FOiB3ZSBzaG91bGQgbW9kaWZ5IGNvZGUgZ2VuZXJhdGlvbiBmb3IgYmF0Y2ggY29tbWFuZHMgc28gdGhpc1xuICAgIC8vIGlzbid0IG5lY2Vzc2FyeVxuICAgIHZhciBFTVBUWV9BUlJBWSA9IFtdO1xuICAgIGZ1bmN0aW9uIHJlc2VydmUgKGNvdW50KSB7XG4gICAgICB3aGlsZSAoRU1QVFlfQVJSQVkubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgICAgRU1QVFlfQVJSQVkucHVzaChudWxsKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBFTVBUWV9BUlJBWVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIFJFR0xDb21tYW5kIChhcmdzLCBib2R5KSB7XG4gICAgICB2YXIgaTtcbiAgICAgIGlmIChjb250ZXh0TG9zdCkge1xuICAgICAgICBjaGVjayQxLnJhaXNlKCdjb250ZXh0IGxvc3QnKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgYXJncyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gc2NvcGUuY2FsbCh0aGlzLCBudWxsLCBhcmdzLCAwKVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYm9keSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBpZiAodHlwZW9mIGFyZ3MgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyZ3M7ICsraSkge1xuICAgICAgICAgICAgc2NvcGUuY2FsbCh0aGlzLCBudWxsLCBib2R5LCBpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmdzKSkge1xuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBzY29wZS5jYWxsKHRoaXMsIGFyZ3NbaV0sIGJvZHksIGkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gc2NvcGUuY2FsbCh0aGlzLCBhcmdzLCBib2R5LCAwKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmdzID09PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAoYXJncyA+IDApIHtcbiAgICAgICAgICByZXR1cm4gYmF0Y2guY2FsbCh0aGlzLCByZXNlcnZlKGFyZ3MgfCAwKSwgYXJncyB8IDApXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmdzKSkge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4gYmF0Y2guY2FsbCh0aGlzLCBhcmdzLCBhcmdzLmxlbmd0aClcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRyYXcuY2FsbCh0aGlzLCBhcmdzKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBleHRlbmQoUkVHTENvbW1hbmQsIHtcbiAgICAgIHN0YXRzOiBzdGF0cyQkMVxuICAgIH0pXG4gIH1cblxuICB2YXIgc2V0RkJPID0gZnJhbWVidWZmZXJTdGF0ZS5zZXRGQk8gPSBjb21waWxlUHJvY2VkdXJlKHtcbiAgICBmcmFtZWJ1ZmZlcjogZHluYW1pYy5kZWZpbmUuY2FsbChudWxsLCBEWU5fUFJPUCwgJ2ZyYW1lYnVmZmVyJylcbiAgfSk7XG5cbiAgZnVuY3Rpb24gY2xlYXJJbXBsIChfLCBvcHRpb25zKSB7XG4gICAgdmFyIGNsZWFyRmxhZ3MgPSAwO1xuICAgIGNvcmUucHJvY3MucG9sbCgpO1xuXG4gICAgdmFyIGMgPSBvcHRpb25zLmNvbG9yO1xuICAgIGlmIChjKSB7XG4gICAgICBnbC5jbGVhckNvbG9yKCtjWzBdIHx8IDAsICtjWzFdIHx8IDAsICtjWzJdIHx8IDAsICtjWzNdIHx8IDApO1xuICAgICAgY2xlYXJGbGFncyB8PSBHTF9DT0xPUl9CVUZGRVJfQklUO1xuICAgIH1cbiAgICBpZiAoJ2RlcHRoJyBpbiBvcHRpb25zKSB7XG4gICAgICBnbC5jbGVhckRlcHRoKCtvcHRpb25zLmRlcHRoKTtcbiAgICAgIGNsZWFyRmxhZ3MgfD0gR0xfREVQVEhfQlVGRkVSX0JJVDtcbiAgICB9XG4gICAgaWYgKCdzdGVuY2lsJyBpbiBvcHRpb25zKSB7XG4gICAgICBnbC5jbGVhclN0ZW5jaWwob3B0aW9ucy5zdGVuY2lsIHwgMCk7XG4gICAgICBjbGVhckZsYWdzIHw9IEdMX1NURU5DSUxfQlVGRkVSX0JJVDtcbiAgICB9XG5cbiAgICBjaGVjayQxKCEhY2xlYXJGbGFncywgJ2NhbGxlZCByZWdsLmNsZWFyIHdpdGggbm8gYnVmZmVyIHNwZWNpZmllZCcpO1xuICAgIGdsLmNsZWFyKGNsZWFyRmxhZ3MpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXIgKG9wdGlvbnMpIHtcbiAgICBjaGVjayQxKFxuICAgICAgdHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnICYmIG9wdGlvbnMsXG4gICAgICAncmVnbC5jbGVhcigpIHRha2VzIGFuIG9iamVjdCBhcyBpbnB1dCcpO1xuICAgIGlmICgnZnJhbWVidWZmZXInIGluIG9wdGlvbnMpIHtcbiAgICAgIGlmIChvcHRpb25zLmZyYW1lYnVmZmVyICYmXG4gICAgICAgICAgb3B0aW9ucy5mcmFtZWJ1ZmZlcl9yZWdsVHlwZSA9PT0gJ2ZyYW1lYnVmZmVyQ3ViZScpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgICBzZXRGQk8oZXh0ZW5kKHtcbiAgICAgICAgICAgIGZyYW1lYnVmZmVyOiBvcHRpb25zLmZyYW1lYnVmZmVyLmZhY2VzW2ldXG4gICAgICAgICAgfSwgb3B0aW9ucyksIGNsZWFySW1wbCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNldEZCTyhvcHRpb25zLCBjbGVhckltcGwpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjbGVhckltcGwobnVsbCwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZnJhbWUgKGNiKSB7XG4gICAgY2hlY2skMS50eXBlKGNiLCAnZnVuY3Rpb24nLCAncmVnbC5mcmFtZSgpIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgIHJhZkNhbGxiYWNrcy5wdXNoKGNiKTtcblxuICAgIGZ1bmN0aW9uIGNhbmNlbCAoKSB7XG4gICAgICAvLyBGSVhNRTogIHNob3VsZCB3ZSBjaGVjayBzb21ldGhpbmcgb3RoZXIgdGhhbiBlcXVhbHMgY2IgaGVyZT9cbiAgICAgIC8vIHdoYXQgaWYgYSB1c2VyIGNhbGxzIGZyYW1lIHR3aWNlIHdpdGggdGhlIHNhbWUgY2FsbGJhY2suLi5cbiAgICAgIC8vXG4gICAgICB2YXIgaSA9IGZpbmQocmFmQ2FsbGJhY2tzLCBjYik7XG4gICAgICBjaGVjayQxKGkgPj0gMCwgJ2Nhbm5vdCBjYW5jZWwgYSBmcmFtZSB0d2ljZScpO1xuICAgICAgZnVuY3Rpb24gcGVuZGluZ0NhbmNlbCAoKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGZpbmQocmFmQ2FsbGJhY2tzLCBwZW5kaW5nQ2FuY2VsKTtcbiAgICAgICAgcmFmQ2FsbGJhY2tzW2luZGV4XSA9IHJhZkNhbGxiYWNrc1tyYWZDYWxsYmFja3MubGVuZ3RoIC0gMV07XG4gICAgICAgIHJhZkNhbGxiYWNrcy5sZW5ndGggLT0gMTtcbiAgICAgICAgaWYgKHJhZkNhbGxiYWNrcy5sZW5ndGggPD0gMCkge1xuICAgICAgICAgIHN0b3BSQUYoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmFmQ2FsbGJhY2tzW2ldID0gcGVuZGluZ0NhbmNlbDtcbiAgICB9XG5cbiAgICBzdGFydFJBRigpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNhbmNlbDogY2FuY2VsXG4gICAgfVxuICB9XG5cbiAgLy8gcG9sbCB2aWV3cG9ydFxuICBmdW5jdGlvbiBwb2xsVmlld3BvcnQgKCkge1xuICAgIHZhciB2aWV3cG9ydCA9IG5leHRTdGF0ZS52aWV3cG9ydDtcbiAgICB2YXIgc2Npc3NvckJveCA9IG5leHRTdGF0ZS5zY2lzc29yX2JveDtcbiAgICB2aWV3cG9ydFswXSA9IHZpZXdwb3J0WzFdID0gc2Npc3NvckJveFswXSA9IHNjaXNzb3JCb3hbMV0gPSAwO1xuICAgIGNvbnRleHRTdGF0ZS52aWV3cG9ydFdpZHRoID1cbiAgICAgIGNvbnRleHRTdGF0ZS5mcmFtZWJ1ZmZlcldpZHRoID1cbiAgICAgIGNvbnRleHRTdGF0ZS5kcmF3aW5nQnVmZmVyV2lkdGggPVxuICAgICAgdmlld3BvcnRbMl0gPVxuICAgICAgc2Npc3NvckJveFsyXSA9IGdsLmRyYXdpbmdCdWZmZXJXaWR0aDtcbiAgICBjb250ZXh0U3RhdGUudmlld3BvcnRIZWlnaHQgPVxuICAgICAgY29udGV4dFN0YXRlLmZyYW1lYnVmZmVySGVpZ2h0ID1cbiAgICAgIGNvbnRleHRTdGF0ZS5kcmF3aW5nQnVmZmVySGVpZ2h0ID1cbiAgICAgIHZpZXdwb3J0WzNdID1cbiAgICAgIHNjaXNzb3JCb3hbM10gPSBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0O1xuICB9XG5cbiAgZnVuY3Rpb24gcG9sbCAoKSB7XG4gICAgY29udGV4dFN0YXRlLnRpY2sgKz0gMTtcbiAgICBjb250ZXh0U3RhdGUudGltZSA9IG5vdygpO1xuICAgIHBvbGxWaWV3cG9ydCgpO1xuICAgIGNvcmUucHJvY3MucG9sbCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVmcmVzaCAoKSB7XG4gICAgcG9sbFZpZXdwb3J0KCk7XG4gICAgY29yZS5wcm9jcy5yZWZyZXNoKCk7XG4gICAgaWYgKHRpbWVyKSB7XG4gICAgICB0aW1lci51cGRhdGUoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBub3cgKCkge1xuICAgIHJldHVybiAoY2xvY2soKSAtIFNUQVJUX1RJTUUpIC8gMTAwMC4wXG4gIH1cblxuICByZWZyZXNoKCk7XG5cbiAgZnVuY3Rpb24gYWRkTGlzdGVuZXIgKGV2ZW50LCBjYWxsYmFjaykge1xuICAgIGNoZWNrJDEudHlwZShjYWxsYmFjaywgJ2Z1bmN0aW9uJywgJ2xpc3RlbmVyIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gICAgdmFyIGNhbGxiYWNrcztcbiAgICBzd2l0Y2ggKGV2ZW50KSB7XG4gICAgICBjYXNlICdmcmFtZSc6XG4gICAgICAgIHJldHVybiBmcmFtZShjYWxsYmFjaylcbiAgICAgIGNhc2UgJ2xvc3QnOlxuICAgICAgICBjYWxsYmFja3MgPSBsb3NzQ2FsbGJhY2tzO1xuICAgICAgICBicmVha1xuICAgICAgY2FzZSAncmVzdG9yZSc6XG4gICAgICAgIGNhbGxiYWNrcyA9IHJlc3RvcmVDYWxsYmFja3M7XG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdkZXN0cm95JzpcbiAgICAgICAgY2FsbGJhY2tzID0gZGVzdHJveUNhbGxiYWNrcztcbiAgICAgICAgYnJlYWtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNoZWNrJDEucmFpc2UoJ2ludmFsaWQgZXZlbnQsIG11c3QgYmUgb25lIG9mIGZyYW1lLGxvc3QscmVzdG9yZSxkZXN0cm95Jyk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgIHJldHVybiB7XG4gICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2tzW2ldID09PSBjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2tzW2ldID0gY2FsbGJhY2tzW2NhbGxiYWNrcy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGNhbGxiYWNrcy5wb3AoKTtcbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciByZWdsID0gZXh0ZW5kKGNvbXBpbGVQcm9jZWR1cmUsIHtcbiAgICAvLyBDbGVhciBjdXJyZW50IEZCT1xuICAgIGNsZWFyOiBjbGVhcixcblxuICAgIC8vIFNob3J0IGN1dHMgZm9yIGR5bmFtaWMgdmFyaWFibGVzXG4gICAgcHJvcDogZHluYW1pYy5kZWZpbmUuYmluZChudWxsLCBEWU5fUFJPUCksXG4gICAgY29udGV4dDogZHluYW1pYy5kZWZpbmUuYmluZChudWxsLCBEWU5fQ09OVEVYVCksXG4gICAgdGhpczogZHluYW1pYy5kZWZpbmUuYmluZChudWxsLCBEWU5fU1RBVEUpLFxuXG4gICAgLy8gZXhlY3V0ZXMgYW4gZW1wdHkgZHJhdyBjb21tYW5kXG4gICAgZHJhdzogY29tcGlsZVByb2NlZHVyZSh7fSksXG5cbiAgICAvLyBSZXNvdXJjZXNcbiAgICBidWZmZXI6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICByZXR1cm4gYnVmZmVyU3RhdGUuY3JlYXRlKG9wdGlvbnMsIEdMX0FSUkFZX0JVRkZFUiwgZmFsc2UsIGZhbHNlKVxuICAgIH0sXG4gICAgZWxlbWVudHM6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICByZXR1cm4gZWxlbWVudFN0YXRlLmNyZWF0ZShvcHRpb25zLCBmYWxzZSlcbiAgICB9LFxuICAgIHRleHR1cmU6IHRleHR1cmVTdGF0ZS5jcmVhdGUyRCxcbiAgICBjdWJlOiB0ZXh0dXJlU3RhdGUuY3JlYXRlQ3ViZSxcbiAgICByZW5kZXJidWZmZXI6IHJlbmRlcmJ1ZmZlclN0YXRlLmNyZWF0ZSxcbiAgICBmcmFtZWJ1ZmZlcjogZnJhbWVidWZmZXJTdGF0ZS5jcmVhdGUsXG4gICAgZnJhbWVidWZmZXJDdWJlOiBmcmFtZWJ1ZmZlclN0YXRlLmNyZWF0ZUN1YmUsXG5cbiAgICAvLyBFeHBvc2UgY29udGV4dCBhdHRyaWJ1dGVzXG4gICAgYXR0cmlidXRlczogZ2xBdHRyaWJ1dGVzLFxuXG4gICAgLy8gRnJhbWUgcmVuZGVyaW5nXG4gICAgZnJhbWU6IGZyYW1lLFxuICAgIG9uOiBhZGRMaXN0ZW5lcixcblxuICAgIC8vIFN5c3RlbSBsaW1pdHNcbiAgICBsaW1pdHM6IGxpbWl0cyxcbiAgICBoYXNFeHRlbnNpb246IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICByZXR1cm4gbGltaXRzLmV4dGVuc2lvbnMuaW5kZXhPZihuYW1lLnRvTG93ZXJDYXNlKCkpID49IDBcbiAgICB9LFxuXG4gICAgLy8gUmVhZCBwaXhlbHNcbiAgICByZWFkOiByZWFkUGl4ZWxzLFxuXG4gICAgLy8gRGVzdHJveSByZWdsIGFuZCBhbGwgYXNzb2NpYXRlZCByZXNvdXJjZXNcbiAgICBkZXN0cm95OiBkZXN0cm95LFxuXG4gICAgLy8gRGlyZWN0IEdMIHN0YXRlIG1hbmlwdWxhdGlvblxuICAgIF9nbDogZ2wsXG4gICAgX3JlZnJlc2g6IHJlZnJlc2gsXG5cbiAgICBwb2xsOiBmdW5jdGlvbiAoKSB7XG4gICAgICBwb2xsKCk7XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgdGltZXIudXBkYXRlKCk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8vIEN1cnJlbnQgdGltZVxuICAgIG5vdzogbm93LFxuXG4gICAgLy8gcmVnbCBTdGF0aXN0aWNzIEluZm9ybWF0aW9uXG4gICAgc3RhdHM6IHN0YXRzJCQxXG4gIH0pO1xuXG4gIGNvbmZpZy5vbkRvbmUobnVsbCwgcmVnbCk7XG5cbiAgcmV0dXJuIHJlZ2xcbn1cblxucmV0dXJuIHdyYXBSRUdMO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmVnbC5qcy5tYXBcbiIsIi8qIVxuICogcmVwZWF0LXN0cmluZyA8aHR0cHM6Ly9naXRodWIuY29tL2pvbnNjaGxpbmtlcnQvcmVwZWF0LXN0cmluZz5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNSwgSm9uIFNjaGxpbmtlcnQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFJlc3VsdHMgY2FjaGVcbiAqL1xuXG52YXIgcmVzID0gJyc7XG52YXIgY2FjaGU7XG5cbi8qKlxuICogRXhwb3NlIGByZXBlYXRgXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSByZXBlYXQ7XG5cbi8qKlxuICogUmVwZWF0IHRoZSBnaXZlbiBgc3RyaW5nYCB0aGUgc3BlY2lmaWVkIGBudW1iZXJgXG4gKiBvZiB0aW1lcy5cbiAqXG4gKiAqKkV4YW1wbGU6KipcbiAqXG4gKiBgYGBqc1xuICogdmFyIHJlcGVhdCA9IHJlcXVpcmUoJ3JlcGVhdC1zdHJpbmcnKTtcbiAqIHJlcGVhdCgnQScsIDUpO1xuICogLy89PiBBQUFBQVxuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGBzdHJpbmdgIFRoZSBzdHJpbmcgdG8gcmVwZWF0XG4gKiBAcGFyYW0ge051bWJlcn0gYG51bWJlcmAgVGhlIG51bWJlciBvZiB0aW1lcyB0byByZXBlYXQgdGhlIHN0cmluZ1xuICogQHJldHVybiB7U3RyaW5nfSBSZXBlYXRlZCBzdHJpbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gcmVwZWF0KHN0ciwgbnVtKSB7XG4gIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4cGVjdGVkIGEgc3RyaW5nJyk7XG4gIH1cblxuICAvLyBjb3ZlciBjb21tb24sIHF1aWNrIHVzZSBjYXNlc1xuICBpZiAobnVtID09PSAxKSByZXR1cm4gc3RyO1xuICBpZiAobnVtID09PSAyKSByZXR1cm4gc3RyICsgc3RyO1xuXG4gIHZhciBtYXggPSBzdHIubGVuZ3RoICogbnVtO1xuICBpZiAoY2FjaGUgIT09IHN0ciB8fCB0eXBlb2YgY2FjaGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgY2FjaGUgPSBzdHI7XG4gICAgcmVzID0gJyc7XG4gIH0gZWxzZSBpZiAocmVzLmxlbmd0aCA+PSBtYXgpIHtcbiAgICByZXR1cm4gcmVzLnN1YnN0cigwLCBtYXgpO1xuICB9XG5cbiAgd2hpbGUgKG1heCA+IHJlcy5sZW5ndGggJiYgbnVtID4gMSkge1xuICAgIGlmIChudW0gJiAxKSB7XG4gICAgICByZXMgKz0gc3RyO1xuICAgIH1cblxuICAgIG51bSA+Pj0gMTtcbiAgICBzdHIgKz0gc3RyO1xuICB9XG5cbiAgcmVzICs9IHN0cjtcbiAgcmVzID0gcmVzLnN1YnN0cigwLCBtYXgpO1xuICByZXR1cm4gcmVzO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPVxuICBnbG9iYWwucGVyZm9ybWFuY2UgJiZcbiAgZ2xvYmFsLnBlcmZvcm1hbmNlLm5vdyA/IGZ1bmN0aW9uIG5vdygpIHtcbiAgICByZXR1cm4gcGVyZm9ybWFuY2Uubm93KClcbiAgfSA6IERhdGUubm93IHx8IGZ1bmN0aW9uIG5vdygpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlXG4gIH1cbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gY29tcHJlc3NFeHBhbnNpb25cblxuZnVuY3Rpb24gY29tcHJlc3NFeHBhbnNpb24oZSkge1xuICB2YXIgbSA9IGUubGVuZ3RoXG4gIHZhciBRID0gZVtlLmxlbmd0aC0xXVxuICB2YXIgYm90dG9tID0gbVxuICBmb3IodmFyIGk9bS0yOyBpPj0wOyAtLWkpIHtcbiAgICB2YXIgYSA9IFFcbiAgICB2YXIgYiA9IGVbaV1cbiAgICBRID0gYSArIGJcbiAgICB2YXIgYnYgPSBRIC0gYVxuICAgIHZhciBxID0gYiAtIGJ2XG4gICAgaWYocSkge1xuICAgICAgZVstLWJvdHRvbV0gPSBRXG4gICAgICBRID0gcVxuICAgIH1cbiAgfVxuICB2YXIgdG9wID0gMFxuICBmb3IodmFyIGk9Ym90dG9tOyBpPG07ICsraSkge1xuICAgIHZhciBhID0gZVtpXVxuICAgIHZhciBiID0gUVxuICAgIFEgPSBhICsgYlxuICAgIHZhciBidiA9IFEgLSBhXG4gICAgdmFyIHEgPSBiIC0gYnZcbiAgICBpZihxKSB7XG4gICAgICBlW3RvcCsrXSA9IHFcbiAgICB9XG4gIH1cbiAgZVt0b3ArK10gPSBRXG4gIGUubGVuZ3RoID0gdG9wXG4gIHJldHVybiBlXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSByZXF1aXJlKFwidHdvLXByb2R1Y3RcIilcbnZhciByb2J1c3RTdW0gPSByZXF1aXJlKFwicm9idXN0LXN1bVwiKVxudmFyIHJvYnVzdFNjYWxlID0gcmVxdWlyZShcInJvYnVzdC1zY2FsZVwiKVxudmFyIGNvbXByZXNzID0gcmVxdWlyZShcInJvYnVzdC1jb21wcmVzc1wiKVxuXG52YXIgTlVNX0VYUEFOREVEID0gNlxuXG5mdW5jdGlvbiBjb2ZhY3RvcihtLCBjKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgZm9yKHZhciBpPTE7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gcmVzdWx0W2ktMV0gPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgICBmb3IodmFyIGo9MCxrPTA7IGo8bS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoaiA9PT0gYykge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgcltrKytdID0gbVtpXVtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1hdHJpeChuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gbmV3IEFycmF5KG4pXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICByZXN1bHRbaV1bal0gPSBbXCJtW1wiLCBpLCBcIl1bXCIsIGosIFwiXVwiXS5qb2luKFwiXCIpXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gc2lnbihuKSB7XG4gIGlmKG4gJiAxKSB7XG4gICAgcmV0dXJuIFwiLVwiXG4gIH1cbiAgcmV0dXJuIFwiXCJcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVTdW0oZXhwcikge1xuICBpZihleHByLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBleHByWzBdXG4gIH0gZWxzZSBpZihleHByLmxlbmd0aCA9PT0gMikge1xuICAgIHJldHVybiBbXCJzdW0oXCIsIGV4cHJbMF0sIFwiLFwiLCBleHByWzFdLCBcIilcIl0uam9pbihcIlwiKVxuICB9IGVsc2Uge1xuICAgIHZhciBtID0gZXhwci5sZW5ndGg+PjFcbiAgICByZXR1cm4gW1wic3VtKFwiLCBnZW5lcmF0ZVN1bShleHByLnNsaWNlKDAsIG0pKSwgXCIsXCIsIGdlbmVyYXRlU3VtKGV4cHIuc2xpY2UobSkpLCBcIilcIl0uam9pbihcIlwiKVxuICB9XG59XG5cbmZ1bmN0aW9uIGRldGVybWluYW50KG0pIHtcbiAgaWYobS5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1wic3VtKHByb2QoXCIsIG1bMF1bMF0sIFwiLFwiLCBtWzFdWzFdLCBcIikscHJvZCgtXCIsIG1bMF1bMV0sIFwiLFwiLCBtWzFdWzBdLCBcIikpXCJdLmpvaW4oXCJcIilcbiAgfSBlbHNlIHtcbiAgICB2YXIgZXhwciA9IFtdXG4gICAgZm9yKHZhciBpPTA7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgICAgZXhwci5wdXNoKFtcInNjYWxlKFwiLCBkZXRlcm1pbmFudChjb2ZhY3RvcihtLCBpKSksIFwiLFwiLCBzaWduKGkpLCBtWzBdW2ldLCBcIilcIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgcmV0dXJuIGdlbmVyYXRlU3VtKGV4cHIpXG4gIH1cbn1cblxuZnVuY3Rpb24gY29tcGlsZURldGVybWluYW50KG4pIHtcbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oXCJzdW1cIiwgXCJzY2FsZVwiLCBcInByb2RcIiwgXCJjb21wcmVzc1wiLCBbXG4gICAgXCJmdW5jdGlvbiByb2J1c3REZXRlcm1pbmFudFwiLG4sIFwiKG0pe3JldHVybiBjb21wcmVzcyhcIiwgXG4gICAgICBkZXRlcm1pbmFudChtYXRyaXgobikpLFxuICAgIFwiKX07cmV0dXJuIHJvYnVzdERldGVybWluYW50XCIsIG5dLmpvaW4oXCJcIikpXG4gIHJldHVybiBwcm9jKHJvYnVzdFN1bSwgcm9idXN0U2NhbGUsIHR3b1Byb2R1Y3QsIGNvbXByZXNzKVxufVxuXG52YXIgQ0FDSEUgPSBbXG4gIGZ1bmN0aW9uIHJvYnVzdERldGVybWluYW50MCgpIHsgcmV0dXJuIFswXSB9LFxuICBmdW5jdGlvbiByb2J1c3REZXRlcm1pbmFudDEobSkgeyByZXR1cm4gW21bMF1bMF1dIH1cbl1cblxuZnVuY3Rpb24gZ2VuZXJhdGVEaXNwYXRjaCgpIHtcbiAgd2hpbGUoQ0FDSEUubGVuZ3RoIDwgTlVNX0VYUEFOREVEKSB7XG4gICAgQ0FDSEUucHVzaChjb21waWxlRGV0ZXJtaW5hbnQoQ0FDSEUubGVuZ3RoKSlcbiAgfVxuICB2YXIgcHJvY0FyZ3MgPSBbXVxuICB2YXIgY29kZSA9IFtcImZ1bmN0aW9uIHJvYnVzdERldGVybWluYW50KG0pe3N3aXRjaChtLmxlbmd0aCl7XCJdXG4gIGZvcih2YXIgaT0wOyBpPE5VTV9FWFBBTkRFRDsgKytpKSB7XG4gICAgcHJvY0FyZ3MucHVzaChcImRldFwiICsgaSlcbiAgICBjb2RlLnB1c2goXCJjYXNlIFwiLCBpLCBcIjpyZXR1cm4gZGV0XCIsIGksIFwiKG0pO1wiKVxuICB9XG4gIGNvZGUucHVzaChcIn1cXFxudmFyIGRldD1DQUNIRVttLmxlbmd0aF07XFxcbmlmKCFkZXQpXFxcbmRldD1DQUNIRVttLmxlbmd0aF09Z2VuKG0ubGVuZ3RoKTtcXFxucmV0dXJuIGRldChtKTtcXFxufVxcXG5yZXR1cm4gcm9idXN0RGV0ZXJtaW5hbnRcIilcbiAgcHJvY0FyZ3MucHVzaChcIkNBQ0hFXCIsIFwiZ2VuXCIsIGNvZGUuam9pbihcIlwiKSlcbiAgdmFyIHByb2MgPSBGdW5jdGlvbi5hcHBseSh1bmRlZmluZWQsIHByb2NBcmdzKVxuICBtb2R1bGUuZXhwb3J0cyA9IHByb2MuYXBwbHkodW5kZWZpbmVkLCBDQUNIRS5jb25jYXQoW0NBQ0hFLCBjb21waWxlRGV0ZXJtaW5hbnRdKSlcbiAgZm9yKHZhciBpPTA7IGk8Q0FDSEUubGVuZ3RoOyArK2kpIHtcbiAgICBtb2R1bGUuZXhwb3J0c1tpXSA9IENBQ0hFW2ldXG4gIH1cbn1cblxuZ2VuZXJhdGVEaXNwYXRjaCgpIiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSByZXF1aXJlKFwidHdvLXByb2R1Y3RcIilcbnZhciByb2J1c3RTdW0gPSByZXF1aXJlKFwicm9idXN0LXN1bVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJvYnVzdERvdFByb2R1Y3RcblxuZnVuY3Rpb24gcm9idXN0RG90UHJvZHVjdChhLCBiKSB7XG4gIHZhciByID0gdHdvUHJvZHVjdChhWzBdLCBiWzBdKVxuICBmb3IodmFyIGk9MTsgaTxhLmxlbmd0aDsgKytpKSB7XG4gICAgciA9IHJvYnVzdFN1bShyLCB0d29Qcm9kdWN0KGFbaV0sIGJbaV0pKVxuICB9XG4gIHJldHVybiByXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSByZXF1aXJlKFwidHdvLXByb2R1Y3RcIilcbnZhciByb2J1c3RTdW0gPSByZXF1aXJlKFwicm9idXN0LXN1bVwiKVxudmFyIHJvYnVzdERpZmYgPSByZXF1aXJlKFwicm9idXN0LXN1YnRyYWN0XCIpXG52YXIgcm9idXN0U2NhbGUgPSByZXF1aXJlKFwicm9idXN0LXNjYWxlXCIpXG5cbnZhciBOVU1fRVhQQU5EID0gNlxuXG5mdW5jdGlvbiBjb2ZhY3RvcihtLCBjKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgZm9yKHZhciBpPTE7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gcmVzdWx0W2ktMV0gPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgICBmb3IodmFyIGo9MCxrPTA7IGo8bS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoaiA9PT0gYykge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgcltrKytdID0gbVtpXVtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1hdHJpeChuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gbmV3IEFycmF5KG4pXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICByZXN1bHRbaV1bal0gPSBbXCJtXCIsIGosIFwiW1wiLCAobi1pLTIpLCBcIl1cIl0uam9pbihcIlwiKVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlU3VtKGV4cHIpIHtcbiAgaWYoZXhwci5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZXhwclswXVxuICB9IGVsc2UgaWYoZXhwci5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1wic3VtKFwiLCBleHByWzBdLCBcIixcIiwgZXhwclsxXSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfSBlbHNlIHtcbiAgICB2YXIgbSA9IGV4cHIubGVuZ3RoPj4xXG4gICAgcmV0dXJuIFtcInN1bShcIiwgZ2VuZXJhdGVTdW0oZXhwci5zbGljZSgwLCBtKSksIFwiLFwiLCBnZW5lcmF0ZVN1bShleHByLnNsaWNlKG0pKSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlUHJvZHVjdChhLCBiKSB7XG4gIGlmKGEuY2hhckF0KDApID09PSBcIm1cIikge1xuICAgIGlmKGIuY2hhckF0KDApID09PSBcIndcIikge1xuICAgICAgdmFyIHRva3MgPSBhLnNwbGl0KFwiW1wiKVxuICAgICAgcmV0dXJuIFtcIndcIiwgYi5zdWJzdHIoMSksIFwibVwiLCB0b2tzWzBdLnN1YnN0cigxKV0uam9pbihcIlwiKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW1wicHJvZChcIiwgYSwgXCIsXCIsIGIsIFwiKVwiXS5qb2luKFwiXCIpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBtYWtlUHJvZHVjdChiLCBhKVxuICB9XG59XG5cbmZ1bmN0aW9uIHNpZ24ocykge1xuICBpZihzICYgMSAhPT0gMCkge1xuICAgIHJldHVybiBcIi1cIlxuICB9XG4gIHJldHVybiBcIlwiXG59XG5cbmZ1bmN0aW9uIGRldGVybWluYW50KG0pIHtcbiAgaWYobS5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1tcImRpZmYoXCIsIG1ha2VQcm9kdWN0KG1bMF1bMF0sIG1bMV1bMV0pLCBcIixcIiwgbWFrZVByb2R1Y3QobVsxXVswXSwgbVswXVsxXSksIFwiKVwiXS5qb2luKFwiXCIpXVxuICB9IGVsc2Uge1xuICAgIHZhciBleHByID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxtLmxlbmd0aDsgKytpKSB7XG4gICAgICBleHByLnB1c2goW1wic2NhbGUoXCIsIGdlbmVyYXRlU3VtKGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSksIFwiLFwiLCBzaWduKGkpLCBtWzBdW2ldLCBcIilcIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgcmV0dXJuIGV4cHJcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlU3F1YXJlKGQsIG4pIHtcbiAgdmFyIHRlcm1zID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bi0yOyArK2kpIHtcbiAgICB0ZXJtcy5wdXNoKFtcInByb2QobVwiLCBkLCBcIltcIiwgaSwgXCJdLG1cIiwgZCwgXCJbXCIsIGksIFwiXSlcIl0uam9pbihcIlwiKSlcbiAgfVxuICByZXR1cm4gZ2VuZXJhdGVTdW0odGVybXMpXG59XG5cbmZ1bmN0aW9uIG9yaWVudGF0aW9uKG4pIHtcbiAgdmFyIHBvcyA9IFtdXG4gIHZhciBuZWcgPSBbXVxuICB2YXIgbSA9IG1hdHJpeChuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICBtWzBdW2ldID0gXCIxXCJcbiAgICBtW24tMV1baV0gPSBcIndcIitpXG4gIH0gXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGlmKChpJjEpPT09MCkge1xuICAgICAgcG9zLnB1c2guYXBwbHkocG9zLGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSlcbiAgICB9IGVsc2Uge1xuICAgICAgbmVnLnB1c2guYXBwbHkobmVnLGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSlcbiAgICB9XG4gIH1cbiAgdmFyIHBvc0V4cHIgPSBnZW5lcmF0ZVN1bShwb3MpXG4gIHZhciBuZWdFeHByID0gZ2VuZXJhdGVTdW0obmVnKVxuICB2YXIgZnVuY05hbWUgPSBcImV4YWN0SW5TcGhlcmVcIiArIG5cbiAgdmFyIGZ1bmNBcmdzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgZnVuY0FyZ3MucHVzaChcIm1cIiArIGkpXG4gIH1cbiAgdmFyIGNvZGUgPSBbXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKFwiLCBmdW5jQXJncy5qb2luKCksIFwiKXtcIl1cbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgY29kZS5wdXNoKFwidmFyIHdcIixpLFwiPVwiLG1ha2VTcXVhcmUoaSxuKSxcIjtcIilcbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIGlmKGogIT09IGkpIHtcbiAgICAgICAgY29kZS5wdXNoKFwidmFyIHdcIixpLFwibVwiLGosXCI9c2NhbGUod1wiLGksXCIsbVwiLGosXCJbMF0pO1wiKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBjb2RlLnB1c2goXCJ2YXIgcD1cIiwgcG9zRXhwciwgXCIsbj1cIiwgbmVnRXhwciwgXCIsZD1kaWZmKHAsbik7cmV0dXJuIGRbZC5sZW5ndGgtMV07fXJldHVybiBcIiwgZnVuY05hbWUpXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwic3VtXCIsIFwiZGlmZlwiLCBcInByb2RcIiwgXCJzY2FsZVwiLCBjb2RlLmpvaW4oXCJcIikpXG4gIHJldHVybiBwcm9jKHJvYnVzdFN1bSwgcm9idXN0RGlmZiwgdHdvUHJvZHVjdCwgcm9idXN0U2NhbGUpXG59XG5cbmZ1bmN0aW9uIGluU3BoZXJlMCgpIHsgcmV0dXJuIDAgfVxuZnVuY3Rpb24gaW5TcGhlcmUxKCkgeyByZXR1cm4gMCB9XG5mdW5jdGlvbiBpblNwaGVyZTIoKSB7IHJldHVybiAwIH1cblxudmFyIENBQ0hFRCA9IFtcbiAgaW5TcGhlcmUwLFxuICBpblNwaGVyZTEsXG4gIGluU3BoZXJlMlxuXVxuXG5mdW5jdGlvbiBzbG93SW5TcGhlcmUoYXJncykge1xuICB2YXIgcHJvYyA9IENBQ0hFRFthcmdzLmxlbmd0aF1cbiAgaWYoIXByb2MpIHtcbiAgICBwcm9jID0gQ0FDSEVEW2FyZ3MubGVuZ3RoXSA9IG9yaWVudGF0aW9uKGFyZ3MubGVuZ3RoKVxuICB9XG4gIHJldHVybiBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgYXJncylcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVJblNwaGVyZVRlc3QoKSB7XG4gIHdoaWxlKENBQ0hFRC5sZW5ndGggPD0gTlVNX0VYUEFORCkge1xuICAgIENBQ0hFRC5wdXNoKG9yaWVudGF0aW9uKENBQ0hFRC5sZW5ndGgpKVxuICB9XG4gIHZhciBhcmdzID0gW11cbiAgdmFyIHByb2NBcmdzID0gW1wic2xvd1wiXVxuICBmb3IodmFyIGk9MDsgaTw9TlVNX0VYUEFORDsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiYVwiICsgaSlcbiAgICBwcm9jQXJncy5wdXNoKFwib1wiICsgaSlcbiAgfVxuICB2YXIgY29kZSA9IFtcbiAgICBcImZ1bmN0aW9uIHRlc3RJblNwaGVyZShcIiwgYXJncy5qb2luKCksIFwiKXtzd2l0Y2goYXJndW1lbnRzLmxlbmd0aCl7Y2FzZSAwOmNhc2UgMTpyZXR1cm4gMDtcIlxuICBdXG4gIGZvcih2YXIgaT0yOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXCJjYXNlIFwiLCBpLCBcIjpyZXR1cm4gb1wiLCBpLCBcIihcIiwgYXJncy5zbGljZSgwLCBpKS5qb2luKCksIFwiKTtcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9dmFyIHM9bmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO2Zvcih2YXIgaT0wO2k8YXJndW1lbnRzLmxlbmd0aDsrK2kpe3NbaV09YXJndW1lbnRzW2ldfTtyZXR1cm4gc2xvdyhzKTt9cmV0dXJuIHRlc3RJblNwaGVyZVwiKVxuICBwcm9jQXJncy5wdXNoKGNvZGUuam9pbihcIlwiKSlcblxuICB2YXIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgcHJvY0FyZ3MpXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgW3Nsb3dJblNwaGVyZV0uY29uY2F0KENBQ0hFRCkpXG4gIGZvcih2YXIgaT0wOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBtb2R1bGUuZXhwb3J0c1tpXSA9IENBQ0hFRFtpXVxuICB9XG59XG5cbmdlbmVyYXRlSW5TcGhlcmVUZXN0KCkiLCJcInVzZSBzdHJpY3RcIlxuXG52YXIgZGV0ZXJtaW5hbnQgPSByZXF1aXJlKFwicm9idXN0LWRldGVybWluYW50XCIpXG5cbnZhciBOVU1fRVhQQU5EID0gNlxuXG5mdW5jdGlvbiBnZW5lcmF0ZVNvbHZlcihuKSB7XG4gIHZhciBmdW5jTmFtZSA9IFwicm9idXN0TGluZWFyU29sdmVcIiArIG4gKyBcImRcIlxuICB2YXIgY29kZSA9IFtcImZ1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoQSxiKXtyZXR1cm4gW1wiXVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXCJkZXQoW1wiKVxuICAgIGZvcih2YXIgaj0wOyBqPG47ICsraikge1xuICAgICAgaWYoaiA+IDApIHtcbiAgICAgICAgY29kZS5wdXNoKFwiLFwiKVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKFwiW1wiKVxuICAgICAgZm9yKHZhciBrPTA7IGs8bjsgKytrKSB7XG4gICAgICAgIGlmKGsgPiAwKSB7XG4gICAgICAgICAgY29kZS5wdXNoKFwiLFwiKVxuICAgICAgICB9XG4gICAgICAgIGlmKGsgPT09IGkpIHtcbiAgICAgICAgICBjb2RlLnB1c2goXCIrYltcIiwgaiwgXCJdXCIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29kZS5wdXNoKFwiK0FbXCIsIGosIFwiXVtcIiwgaywgXCJdXCIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcIl1cIilcbiAgICB9XG4gICAgY29kZS5wdXNoKFwiXSksXCIpXG4gIH1cbiAgY29kZS5wdXNoKFwiZGV0KEEpXX1yZXR1cm4gXCIsIGZ1bmNOYW1lKVxuICB2YXIgcHJvYyA9IG5ldyBGdW5jdGlvbihcImRldFwiLCBjb2RlLmpvaW4oXCJcIikpXG4gIGlmKG4gPCA2KSB7XG4gICAgcmV0dXJuIHByb2MoZGV0ZXJtaW5hbnRbbl0pXG4gIH1cbiAgcmV0dXJuIHByb2MoZGV0ZXJtaW5hbnQpXG59XG5cbmZ1bmN0aW9uIHJvYnVzdExpbmVhclNvbHZlMGQoKSB7XG4gIHJldHVybiBbIDAgXVxufVxuXG5mdW5jdGlvbiByb2J1c3RMaW5lYXJTb2x2ZTFkKEEsIGIpIHtcbiAgcmV0dXJuIFsgWyBiWzBdIF0sIFsgQVswXVswXSBdIF1cbn1cblxudmFyIENBQ0hFID0gW1xuICByb2J1c3RMaW5lYXJTb2x2ZTBkLFxuICByb2J1c3RMaW5lYXJTb2x2ZTFkXG5dXG5cbmZ1bmN0aW9uIGdlbmVyYXRlRGlzcGF0Y2goKSB7XG4gIHdoaWxlKENBQ0hFLmxlbmd0aCA8IE5VTV9FWFBBTkQpIHtcbiAgICBDQUNIRS5wdXNoKGdlbmVyYXRlU29sdmVyKENBQ0hFLmxlbmd0aCkpXG4gIH1cbiAgdmFyIHByb2NBcmdzID0gW11cbiAgdmFyIGNvZGUgPSBbXCJmdW5jdGlvbiBkaXNwYXRjaExpbmVhclNvbHZlKEEsYil7c3dpdGNoKEEubGVuZ3RoKXtcIl1cbiAgZm9yKHZhciBpPTA7IGk8TlVNX0VYUEFORDsgKytpKSB7XG4gICAgcHJvY0FyZ3MucHVzaChcInNcIiArIGkpXG4gICAgY29kZS5wdXNoKFwiY2FzZSBcIiwgaSwgXCI6cmV0dXJuIHNcIiwgaSwgXCIoQSxiKTtcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9dmFyIHM9Q0FDSEVbQS5sZW5ndGhdO2lmKCFzKXM9Q0FDSEVbQS5sZW5ndGhdPWcoQS5sZW5ndGgpO3JldHVybiBzKEEsYil9cmV0dXJuIGRpc3BhdGNoTGluZWFyU29sdmVcIilcbiAgcHJvY0FyZ3MucHVzaChcIkNBQ0hFXCIsIFwiZ1wiLCBjb2RlLmpvaW4oXCJcIikpXG4gIHZhciBwcm9jID0gRnVuY3Rpb24uYXBwbHkodW5kZWZpbmVkLCBwcm9jQXJncylcbiAgbW9kdWxlLmV4cG9ydHMgPSBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgQ0FDSEUuY29uY2F0KFtDQUNIRSwgZ2VuZXJhdGVTb2x2ZXJdKSlcbiAgZm9yKHZhciBpPTA7IGk8TlVNX0VYUEFORDsgKytpKSB7XG4gICAgbW9kdWxlLmV4cG9ydHNbaV0gPSBDQUNIRVtpXVxuICB9XG59XG5cbmdlbmVyYXRlRGlzcGF0Y2goKSIsIlwidXNlIHN0cmljdFwiXG5cbnZhciB0d29Qcm9kdWN0ID0gcmVxdWlyZShcInR3by1wcm9kdWN0XCIpXG52YXIgcm9idXN0U3VtID0gcmVxdWlyZShcInJvYnVzdC1zdW1cIilcbnZhciByb2J1c3RTY2FsZSA9IHJlcXVpcmUoXCJyb2J1c3Qtc2NhbGVcIilcbnZhciByb2J1c3RTdWJ0cmFjdCA9IHJlcXVpcmUoXCJyb2J1c3Qtc3VidHJhY3RcIilcblxudmFyIE5VTV9FWFBBTkQgPSA1XG5cbnZhciBFUFNJTE9OICAgICA9IDEuMTEwMjIzMDI0NjI1MTU2NWUtMTZcbnZhciBFUlJCT1VORDMgICA9ICgzLjAgKyAxNi4wICogRVBTSUxPTikgKiBFUFNJTE9OXG52YXIgRVJSQk9VTkQ0ICAgPSAoNy4wICsgNTYuMCAqIEVQU0lMT04pICogRVBTSUxPTlxuXG5mdW5jdGlvbiBjb2ZhY3RvcihtLCBjKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgZm9yKHZhciBpPTE7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gcmVzdWx0W2ktMV0gPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgICBmb3IodmFyIGo9MCxrPTA7IGo8bS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoaiA9PT0gYykge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgcltrKytdID0gbVtpXVtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1hdHJpeChuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gbmV3IEFycmF5KG4pXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICByZXN1bHRbaV1bal0gPSBbXCJtXCIsIGosIFwiW1wiLCAobi1pLTEpLCBcIl1cIl0uam9pbihcIlwiKVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHNpZ24obikge1xuICBpZihuICYgMSkge1xuICAgIHJldHVybiBcIi1cIlxuICB9XG4gIHJldHVybiBcIlwiXG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlU3VtKGV4cHIpIHtcbiAgaWYoZXhwci5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZXhwclswXVxuICB9IGVsc2UgaWYoZXhwci5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1wic3VtKFwiLCBleHByWzBdLCBcIixcIiwgZXhwclsxXSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfSBlbHNlIHtcbiAgICB2YXIgbSA9IGV4cHIubGVuZ3RoPj4xXG4gICAgcmV0dXJuIFtcInN1bShcIiwgZ2VuZXJhdGVTdW0oZXhwci5zbGljZSgwLCBtKSksIFwiLFwiLCBnZW5lcmF0ZVN1bShleHByLnNsaWNlKG0pKSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfVxufVxuXG5mdW5jdGlvbiBkZXRlcm1pbmFudChtKSB7XG4gIGlmKG0ubGVuZ3RoID09PSAyKSB7XG4gICAgcmV0dXJuIFtbXCJzdW0ocHJvZChcIiwgbVswXVswXSwgXCIsXCIsIG1bMV1bMV0sIFwiKSxwcm9kKC1cIiwgbVswXVsxXSwgXCIsXCIsIG1bMV1bMF0sIFwiKSlcIl0uam9pbihcIlwiKV1cbiAgfSBlbHNlIHtcbiAgICB2YXIgZXhwciA9IFtdXG4gICAgZm9yKHZhciBpPTA7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgICAgZXhwci5wdXNoKFtcInNjYWxlKFwiLCBnZW5lcmF0ZVN1bShkZXRlcm1pbmFudChjb2ZhY3RvcihtLCBpKSkpLCBcIixcIiwgc2lnbihpKSwgbVswXVtpXSwgXCIpXCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIHJldHVybiBleHByXG4gIH1cbn1cblxuZnVuY3Rpb24gb3JpZW50YXRpb24obikge1xuICB2YXIgcG9zID0gW11cbiAgdmFyIG5lZyA9IFtdXG4gIHZhciBtID0gbWF0cml4KG4pXG4gIHZhciBhcmdzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgaWYoKGkmMSk9PT0wKSB7XG4gICAgICBwb3MucHVzaC5hcHBseShwb3MsIGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSlcbiAgICB9IGVsc2Uge1xuICAgICAgbmVnLnB1c2guYXBwbHkobmVnLCBkZXRlcm1pbmFudChjb2ZhY3RvcihtLCBpKSkpXG4gICAgfVxuICAgIGFyZ3MucHVzaChcIm1cIiArIGkpXG4gIH1cbiAgdmFyIHBvc0V4cHIgPSBnZW5lcmF0ZVN1bShwb3MpXG4gIHZhciBuZWdFeHByID0gZ2VuZXJhdGVTdW0obmVnKVxuICB2YXIgZnVuY05hbWUgPSBcIm9yaWVudGF0aW9uXCIgKyBuICsgXCJFeGFjdFwiXG4gIHZhciBjb2RlID0gW1wiZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihcIiwgYXJncy5qb2luKCksIFwiKXt2YXIgcD1cIiwgcG9zRXhwciwgXCIsbj1cIiwgbmVnRXhwciwgXCIsZD1zdWIocCxuKTtcXFxucmV0dXJuIGRbZC5sZW5ndGgtMV07fTtyZXR1cm4gXCIsIGZ1bmNOYW1lXS5qb2luKFwiXCIpXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwic3VtXCIsIFwicHJvZFwiLCBcInNjYWxlXCIsIFwic3ViXCIsIGNvZGUpXG4gIHJldHVybiBwcm9jKHJvYnVzdFN1bSwgdHdvUHJvZHVjdCwgcm9idXN0U2NhbGUsIHJvYnVzdFN1YnRyYWN0KVxufVxuXG52YXIgb3JpZW50YXRpb24zRXhhY3QgPSBvcmllbnRhdGlvbigzKVxudmFyIG9yaWVudGF0aW9uNEV4YWN0ID0gb3JpZW50YXRpb24oNClcblxudmFyIENBQ0hFRCA9IFtcbiAgZnVuY3Rpb24gb3JpZW50YXRpb24wKCkgeyByZXR1cm4gMCB9LFxuICBmdW5jdGlvbiBvcmllbnRhdGlvbjEoKSB7IHJldHVybiAwIH0sXG4gIGZ1bmN0aW9uIG9yaWVudGF0aW9uMihhLCBiKSB7IFxuICAgIHJldHVybiBiWzBdIC0gYVswXVxuICB9LFxuICBmdW5jdGlvbiBvcmllbnRhdGlvbjMoYSwgYiwgYykge1xuICAgIHZhciBsID0gKGFbMV0gLSBjWzFdKSAqIChiWzBdIC0gY1swXSlcbiAgICB2YXIgciA9IChhWzBdIC0gY1swXSkgKiAoYlsxXSAtIGNbMV0pXG4gICAgdmFyIGRldCA9IGwgLSByXG4gICAgdmFyIHNcbiAgICBpZihsID4gMCkge1xuICAgICAgaWYociA8PSAwKSB7XG4gICAgICAgIHJldHVybiBkZXRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMgPSBsICsgclxuICAgICAgfVxuICAgIH0gZWxzZSBpZihsIDwgMCkge1xuICAgICAgaWYociA+PSAwKSB7XG4gICAgICAgIHJldHVybiBkZXRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMgPSAtKGwgKyByKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZGV0XG4gICAgfVxuICAgIHZhciB0b2wgPSBFUlJCT1VORDMgKiBzXG4gICAgaWYoZGV0ID49IHRvbCB8fCBkZXQgPD0gLXRvbCkge1xuICAgICAgcmV0dXJuIGRldFxuICAgIH1cbiAgICByZXR1cm4gb3JpZW50YXRpb24zRXhhY3QoYSwgYiwgYylcbiAgfSxcbiAgZnVuY3Rpb24gb3JpZW50YXRpb240KGEsYixjLGQpIHtcbiAgICB2YXIgYWR4ID0gYVswXSAtIGRbMF1cbiAgICB2YXIgYmR4ID0gYlswXSAtIGRbMF1cbiAgICB2YXIgY2R4ID0gY1swXSAtIGRbMF1cbiAgICB2YXIgYWR5ID0gYVsxXSAtIGRbMV1cbiAgICB2YXIgYmR5ID0gYlsxXSAtIGRbMV1cbiAgICB2YXIgY2R5ID0gY1sxXSAtIGRbMV1cbiAgICB2YXIgYWR6ID0gYVsyXSAtIGRbMl1cbiAgICB2YXIgYmR6ID0gYlsyXSAtIGRbMl1cbiAgICB2YXIgY2R6ID0gY1syXSAtIGRbMl1cbiAgICB2YXIgYmR4Y2R5ID0gYmR4ICogY2R5XG4gICAgdmFyIGNkeGJkeSA9IGNkeCAqIGJkeVxuICAgIHZhciBjZHhhZHkgPSBjZHggKiBhZHlcbiAgICB2YXIgYWR4Y2R5ID0gYWR4ICogY2R5XG4gICAgdmFyIGFkeGJkeSA9IGFkeCAqIGJkeVxuICAgIHZhciBiZHhhZHkgPSBiZHggKiBhZHlcbiAgICB2YXIgZGV0ID0gYWR6ICogKGJkeGNkeSAtIGNkeGJkeSkgXG4gICAgICAgICAgICArIGJkeiAqIChjZHhhZHkgLSBhZHhjZHkpXG4gICAgICAgICAgICArIGNkeiAqIChhZHhiZHkgLSBiZHhhZHkpXG4gICAgdmFyIHBlcm1hbmVudCA9IChNYXRoLmFicyhiZHhjZHkpICsgTWF0aC5hYnMoY2R4YmR5KSkgKiBNYXRoLmFicyhhZHopXG4gICAgICAgICAgICAgICAgICArIChNYXRoLmFicyhjZHhhZHkpICsgTWF0aC5hYnMoYWR4Y2R5KSkgKiBNYXRoLmFicyhiZHopXG4gICAgICAgICAgICAgICAgICArIChNYXRoLmFicyhhZHhiZHkpICsgTWF0aC5hYnMoYmR4YWR5KSkgKiBNYXRoLmFicyhjZHopXG4gICAgdmFyIHRvbCA9IEVSUkJPVU5ENCAqIHBlcm1hbmVudFxuICAgIGlmICgoZGV0ID4gdG9sKSB8fCAoLWRldCA+IHRvbCkpIHtcbiAgICAgIHJldHVybiBkZXRcbiAgICB9XG4gICAgcmV0dXJuIG9yaWVudGF0aW9uNEV4YWN0KGEsYixjLGQpXG4gIH1cbl1cblxuZnVuY3Rpb24gc2xvd09yaWVudChhcmdzKSB7XG4gIHZhciBwcm9jID0gQ0FDSEVEW2FyZ3MubGVuZ3RoXVxuICBpZighcHJvYykge1xuICAgIHByb2MgPSBDQUNIRURbYXJncy5sZW5ndGhdID0gb3JpZW50YXRpb24oYXJncy5sZW5ndGgpXG4gIH1cbiAgcmV0dXJuIHByb2MuYXBwbHkodW5kZWZpbmVkLCBhcmdzKVxufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZU9yaWVudGF0aW9uUHJvYygpIHtcbiAgd2hpbGUoQ0FDSEVELmxlbmd0aCA8PSBOVU1fRVhQQU5EKSB7XG4gICAgQ0FDSEVELnB1c2gob3JpZW50YXRpb24oQ0FDSEVELmxlbmd0aCkpXG4gIH1cbiAgdmFyIGFyZ3MgPSBbXVxuICB2YXIgcHJvY0FyZ3MgPSBbXCJzbG93XCJdXG4gIGZvcih2YXIgaT0wOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBhcmdzLnB1c2goXCJhXCIgKyBpKVxuICAgIHByb2NBcmdzLnB1c2goXCJvXCIgKyBpKVxuICB9XG4gIHZhciBjb2RlID0gW1xuICAgIFwiZnVuY3Rpb24gZ2V0T3JpZW50YXRpb24oXCIsIGFyZ3Muam9pbigpLCBcIil7c3dpdGNoKGFyZ3VtZW50cy5sZW5ndGgpe2Nhc2UgMDpjYXNlIDE6cmV0dXJuIDA7XCJcbiAgXVxuICBmb3IodmFyIGk9MjsgaTw9TlVNX0VYUEFORDsgKytpKSB7XG4gICAgY29kZS5wdXNoKFwiY2FzZSBcIiwgaSwgXCI6cmV0dXJuIG9cIiwgaSwgXCIoXCIsIGFyZ3Muc2xpY2UoMCwgaSkuam9pbigpLCBcIik7XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifXZhciBzPW5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtmb3IodmFyIGk9MDtpPGFyZ3VtZW50cy5sZW5ndGg7KytpKXtzW2ldPWFyZ3VtZW50c1tpXX07cmV0dXJuIHNsb3cocyk7fXJldHVybiBnZXRPcmllbnRhdGlvblwiKVxuICBwcm9jQXJncy5wdXNoKGNvZGUuam9pbihcIlwiKSlcblxuICB2YXIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgcHJvY0FyZ3MpXG4gIG1vZHVsZS5leHBvcnRzID0gcHJvYy5hcHBseSh1bmRlZmluZWQsIFtzbG93T3JpZW50XS5jb25jYXQoQ0FDSEVEKSlcbiAgZm9yKHZhciBpPTA7IGk8PU5VTV9FWFBBTkQ7ICsraSkge1xuICAgIG1vZHVsZS5leHBvcnRzW2ldID0gQ0FDSEVEW2ldXG4gIH1cbn1cblxuZ2VuZXJhdGVPcmllbnRhdGlvblByb2MoKSIsIlwidXNlIHN0cmljdFwiXG5cbnZhciByb2J1c3RTdW0gPSByZXF1aXJlKFwicm9idXN0LXN1bVwiKVxudmFyIHJvYnVzdFNjYWxlID0gcmVxdWlyZShcInJvYnVzdC1zY2FsZVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJvYnVzdFByb2R1Y3RcblxuZnVuY3Rpb24gcm9idXN0UHJvZHVjdChhLCBiKSB7XG4gIGlmKGEubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIHJvYnVzdFNjYWxlKGIsIGFbMF0pXG4gIH1cbiAgaWYoYi5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gcm9idXN0U2NhbGUoYSwgYlswXSlcbiAgfVxuICBpZihhLmxlbmd0aCA9PT0gMCB8fCBiLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbMF1cbiAgfVxuICB2YXIgciA9IFswXVxuICBpZihhLmxlbmd0aCA8IGIubGVuZ3RoKSB7XG4gICAgZm9yKHZhciBpPTA7IGk8YS5sZW5ndGg7ICsraSkge1xuICAgICAgciA9IHJvYnVzdFN1bShyLCByb2J1c3RTY2FsZShiLCBhW2ldKSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZm9yKHZhciBpPTA7IGk8Yi5sZW5ndGg7ICsraSkge1xuICAgICAgciA9IHJvYnVzdFN1bShyLCByb2J1c3RTY2FsZShhLCBiW2ldKSlcbiAgICB9ICAgIFxuICB9XG4gIHJldHVybiByXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSByZXF1aXJlKFwidHdvLXByb2R1Y3RcIilcbnZhciB0d29TdW0gPSByZXF1aXJlKFwidHdvLXN1bVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNjYWxlTGluZWFyRXhwYW5zaW9uXG5cbmZ1bmN0aW9uIHNjYWxlTGluZWFyRXhwYW5zaW9uKGUsIHNjYWxlKSB7XG4gIHZhciBuID0gZS5sZW5ndGhcbiAgaWYobiA9PT0gMSkge1xuICAgIHZhciB0cyA9IHR3b1Byb2R1Y3QoZVswXSwgc2NhbGUpXG4gICAgaWYodHNbMF0pIHtcbiAgICAgIHJldHVybiB0c1xuICAgIH1cbiAgICByZXR1cm4gWyB0c1sxXSBdXG4gIH1cbiAgdmFyIGcgPSBuZXcgQXJyYXkoMiAqIG4pXG4gIHZhciBxID0gWzAuMSwgMC4xXVxuICB2YXIgdCA9IFswLjEsIDAuMV1cbiAgdmFyIGNvdW50ID0gMFxuICB0d29Qcm9kdWN0KGVbMF0sIHNjYWxlLCBxKVxuICBpZihxWzBdKSB7XG4gICAgZ1tjb3VudCsrXSA9IHFbMF1cbiAgfVxuICBmb3IodmFyIGk9MTsgaTxuOyArK2kpIHtcbiAgICB0d29Qcm9kdWN0KGVbaV0sIHNjYWxlLCB0KVxuICAgIHZhciBwcSA9IHFbMV1cbiAgICB0d29TdW0ocHEsIHRbMF0sIHEpXG4gICAgaWYocVswXSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHFbMF1cbiAgICB9XG4gICAgdmFyIGEgPSB0WzFdXG4gICAgdmFyIGIgPSBxWzFdXG4gICAgdmFyIHggPSBhICsgYlxuICAgIHZhciBidiA9IHggLSBhXG4gICAgdmFyIHkgPSBiIC0gYnZcbiAgICBxWzFdID0geFxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfVxuICB9XG4gIGlmKHFbMV0pIHtcbiAgICBnW2NvdW50KytdID0gcVsxXVxuICB9XG4gIGlmKGNvdW50ID09PSAwKSB7XG4gICAgZ1tjb3VudCsrXSA9IDAuMFxuICB9XG4gIGcubGVuZ3RoID0gY291bnRcbiAgcmV0dXJuIGdcbn0iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHNlZ21lbnRzSW50ZXJzZWN0XG5cbnZhciBvcmllbnQgPSByZXF1aXJlKFwicm9idXN0LW9yaWVudGF0aW9uXCIpWzNdXG5cbmZ1bmN0aW9uIGNoZWNrQ29sbGluZWFyKGEwLCBhMSwgYjAsIGIxKSB7XG5cbiAgZm9yKHZhciBkPTA7IGQ8MjsgKytkKSB7XG4gICAgdmFyIHgwID0gYTBbZF1cbiAgICB2YXIgeTAgPSBhMVtkXVxuICAgIHZhciBsMCA9IE1hdGgubWluKHgwLCB5MClcbiAgICB2YXIgaDAgPSBNYXRoLm1heCh4MCwgeTApICAgIFxuXG4gICAgdmFyIHgxID0gYjBbZF1cbiAgICB2YXIgeTEgPSBiMVtkXVxuICAgIHZhciBsMSA9IE1hdGgubWluKHgxLCB5MSlcbiAgICB2YXIgaDEgPSBNYXRoLm1heCh4MSwgeTEpICAgIFxuXG4gICAgaWYoaDEgPCBsMCB8fCBoMCA8IGwxKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBzZWdtZW50c0ludGVyc2VjdChhMCwgYTEsIGIwLCBiMSkge1xuICB2YXIgeDAgPSBvcmllbnQoYTAsIGIwLCBiMSlcbiAgdmFyIHkwID0gb3JpZW50KGExLCBiMCwgYjEpXG4gIGlmKCh4MCA+IDAgJiYgeTAgPiAwKSB8fCAoeDAgPCAwICYmIHkwIDwgMCkpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHZhciB4MSA9IG9yaWVudChiMCwgYTAsIGExKVxuICB2YXIgeTEgPSBvcmllbnQoYjEsIGEwLCBhMSlcbiAgaWYoKHgxID4gMCAmJiB5MSA+IDApIHx8ICh4MSA8IDAgJiYgeTEgPCAwKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgLy9DaGVjayBmb3IgZGVnZW5lcmF0ZSBjb2xsaW5lYXIgY2FzZVxuICBpZih4MCA9PT0gMCAmJiB5MCA9PT0gMCAmJiB4MSA9PT0gMCAmJiB5MSA9PT0gMCkge1xuICAgIHJldHVybiBjaGVja0NvbGxpbmVhcihhMCwgYTEsIGIwLCBiMSlcbiAgfVxuXG4gIHJldHVybiB0cnVlXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSByb2J1c3RTdWJ0cmFjdFxuXG4vL0Vhc3kgY2FzZTogQWRkIHR3byBzY2FsYXJzXG5mdW5jdGlvbiBzY2FsYXJTY2FsYXIoYSwgYikge1xuICB2YXIgeCA9IGEgKyBiXG4gIHZhciBidiA9IHggLSBhXG4gIHZhciBhdiA9IHggLSBidlxuICB2YXIgYnIgPSBiIC0gYnZcbiAgdmFyIGFyID0gYSAtIGF2XG4gIHZhciB5ID0gYXIgKyBiclxuICBpZih5KSB7XG4gICAgcmV0dXJuIFt5LCB4XVxuICB9XG4gIHJldHVybiBbeF1cbn1cblxuZnVuY3Rpb24gcm9idXN0U3VidHJhY3QoZSwgZikge1xuICB2YXIgbmUgPSBlLmxlbmd0aHwwXG4gIHZhciBuZiA9IGYubGVuZ3RofDBcbiAgaWYobmUgPT09IDEgJiYgbmYgPT09IDEpIHtcbiAgICByZXR1cm4gc2NhbGFyU2NhbGFyKGVbMF0sIC1mWzBdKVxuICB9XG4gIHZhciBuID0gbmUgKyBuZlxuICB2YXIgZyA9IG5ldyBBcnJheShuKVxuICB2YXIgY291bnQgPSAwXG4gIHZhciBlcHRyID0gMFxuICB2YXIgZnB0ciA9IDBcbiAgdmFyIGFicyA9IE1hdGguYWJzXG4gIHZhciBlaSA9IGVbZXB0cl1cbiAgdmFyIGVhID0gYWJzKGVpKVxuICB2YXIgZmkgPSAtZltmcHRyXVxuICB2YXIgZmEgPSBhYnMoZmkpXG4gIHZhciBhLCBiXG4gIGlmKGVhIDwgZmEpIHtcbiAgICBiID0gZWlcbiAgICBlcHRyICs9IDFcbiAgICBpZihlcHRyIDwgbmUpIHtcbiAgICAgIGVpID0gZVtlcHRyXVxuICAgICAgZWEgPSBhYnMoZWkpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGIgPSBmaVxuICAgIGZwdHIgKz0gMVxuICAgIGlmKGZwdHIgPCBuZikge1xuICAgICAgZmkgPSAtZltmcHRyXVxuICAgICAgZmEgPSBhYnMoZmkpXG4gICAgfVxuICB9XG4gIGlmKChlcHRyIDwgbmUgJiYgZWEgPCBmYSkgfHwgKGZwdHIgPj0gbmYpKSB7XG4gICAgYSA9IGVpXG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICAgIGVhID0gYWJzKGVpKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhID0gZmlcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gLWZbZnB0cl1cbiAgICAgIGZhID0gYWJzKGZpKVxuICAgIH1cbiAgfVxuICB2YXIgeCA9IGEgKyBiXG4gIHZhciBidiA9IHggLSBhXG4gIHZhciB5ID0gYiAtIGJ2XG4gIHZhciBxMCA9IHlcbiAgdmFyIHExID0geFxuICB2YXIgX3gsIF9idiwgX2F2LCBfYnIsIF9hclxuICB3aGlsZShlcHRyIDwgbmUgJiYgZnB0ciA8IG5mKSB7XG4gICAgaWYoZWEgPCBmYSkge1xuICAgICAgYSA9IGVpXG4gICAgICBlcHRyICs9IDFcbiAgICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgICBlaSA9IGVbZXB0cl1cbiAgICAgICAgZWEgPSBhYnMoZWkpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGEgPSBmaVxuICAgICAgZnB0ciArPSAxXG4gICAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgICAgZmkgPSAtZltmcHRyXVxuICAgICAgICBmYSA9IGFicyhmaSlcbiAgICAgIH1cbiAgICB9XG4gICAgYiA9IHEwXG4gICAgeCA9IGEgKyBiXG4gICAgYnYgPSB4IC0gYVxuICAgIHkgPSBiIC0gYnZcbiAgICBpZih5KSB7XG4gICAgICBnW2NvdW50KytdID0geVxuICAgIH1cbiAgICBfeCA9IHExICsgeFxuICAgIF9idiA9IF94IC0gcTFcbiAgICBfYXYgPSBfeCAtIF9idlxuICAgIF9iciA9IHggLSBfYnZcbiAgICBfYXIgPSBxMSAtIF9hdlxuICAgIHEwID0gX2FyICsgX2JyXG4gICAgcTEgPSBfeFxuICB9XG4gIHdoaWxlKGVwdHIgPCBuZSkge1xuICAgIGEgPSBlaVxuICAgIGIgPSBxMFxuICAgIHggPSBhICsgYlxuICAgIGJ2ID0geCAtIGFcbiAgICB5ID0gYiAtIGJ2XG4gICAgaWYoeSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHlcbiAgICB9XG4gICAgX3ggPSBxMSArIHhcbiAgICBfYnYgPSBfeCAtIHExXG4gICAgX2F2ID0gX3ggLSBfYnZcbiAgICBfYnIgPSB4IC0gX2J2XG4gICAgX2FyID0gcTEgLSBfYXZcbiAgICBxMCA9IF9hciArIF9iclxuICAgIHExID0gX3hcbiAgICBlcHRyICs9IDFcbiAgICBpZihlcHRyIDwgbmUpIHtcbiAgICAgIGVpID0gZVtlcHRyXVxuICAgIH1cbiAgfVxuICB3aGlsZShmcHRyIDwgbmYpIHtcbiAgICBhID0gZmlcbiAgICBiID0gcTBcbiAgICB4ID0gYSArIGJcbiAgICBidiA9IHggLSBhXG4gICAgeSA9IGIgLSBidlxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfSBcbiAgICBfeCA9IHExICsgeFxuICAgIF9idiA9IF94IC0gcTFcbiAgICBfYXYgPSBfeCAtIF9idlxuICAgIF9iciA9IHggLSBfYnZcbiAgICBfYXIgPSBxMSAtIF9hdlxuICAgIHEwID0gX2FyICsgX2JyXG4gICAgcTEgPSBfeFxuICAgIGZwdHIgKz0gMVxuICAgIGlmKGZwdHIgPCBuZikge1xuICAgICAgZmkgPSAtZltmcHRyXVxuICAgIH1cbiAgfVxuICBpZihxMCkge1xuICAgIGdbY291bnQrK10gPSBxMFxuICB9XG4gIGlmKHExKSB7XG4gICAgZ1tjb3VudCsrXSA9IHExXG4gIH1cbiAgaWYoIWNvdW50KSB7XG4gICAgZ1tjb3VudCsrXSA9IDAuMCAgXG4gIH1cbiAgZy5sZW5ndGggPSBjb3VudFxuICByZXR1cm4gZ1xufSIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gbGluZWFyRXhwYW5zaW9uU3VtXG5cbi8vRWFzeSBjYXNlOiBBZGQgdHdvIHNjYWxhcnNcbmZ1bmN0aW9uIHNjYWxhclNjYWxhcihhLCBiKSB7XG4gIHZhciB4ID0gYSArIGJcbiAgdmFyIGJ2ID0geCAtIGFcbiAgdmFyIGF2ID0geCAtIGJ2XG4gIHZhciBiciA9IGIgLSBidlxuICB2YXIgYXIgPSBhIC0gYXZcbiAgdmFyIHkgPSBhciArIGJyXG4gIGlmKHkpIHtcbiAgICByZXR1cm4gW3ksIHhdXG4gIH1cbiAgcmV0dXJuIFt4XVxufVxuXG5mdW5jdGlvbiBsaW5lYXJFeHBhbnNpb25TdW0oZSwgZikge1xuICB2YXIgbmUgPSBlLmxlbmd0aHwwXG4gIHZhciBuZiA9IGYubGVuZ3RofDBcbiAgaWYobmUgPT09IDEgJiYgbmYgPT09IDEpIHtcbiAgICByZXR1cm4gc2NhbGFyU2NhbGFyKGVbMF0sIGZbMF0pXG4gIH1cbiAgdmFyIG4gPSBuZSArIG5mXG4gIHZhciBnID0gbmV3IEFycmF5KG4pXG4gIHZhciBjb3VudCA9IDBcbiAgdmFyIGVwdHIgPSAwXG4gIHZhciBmcHRyID0gMFxuICB2YXIgYWJzID0gTWF0aC5hYnNcbiAgdmFyIGVpID0gZVtlcHRyXVxuICB2YXIgZWEgPSBhYnMoZWkpXG4gIHZhciBmaSA9IGZbZnB0cl1cbiAgdmFyIGZhID0gYWJzKGZpKVxuICB2YXIgYSwgYlxuICBpZihlYSA8IGZhKSB7XG4gICAgYiA9IGVpXG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICAgIGVhID0gYWJzKGVpKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBiID0gZmlcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gZltmcHRyXVxuICAgICAgZmEgPSBhYnMoZmkpXG4gICAgfVxuICB9XG4gIGlmKChlcHRyIDwgbmUgJiYgZWEgPCBmYSkgfHwgKGZwdHIgPj0gbmYpKSB7XG4gICAgYSA9IGVpXG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICAgIGVhID0gYWJzKGVpKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhID0gZmlcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gZltmcHRyXVxuICAgICAgZmEgPSBhYnMoZmkpXG4gICAgfVxuICB9XG4gIHZhciB4ID0gYSArIGJcbiAgdmFyIGJ2ID0geCAtIGFcbiAgdmFyIHkgPSBiIC0gYnZcbiAgdmFyIHEwID0geVxuICB2YXIgcTEgPSB4XG4gIHZhciBfeCwgX2J2LCBfYXYsIF9iciwgX2FyXG4gIHdoaWxlKGVwdHIgPCBuZSAmJiBmcHRyIDwgbmYpIHtcbiAgICBpZihlYSA8IGZhKSB7XG4gICAgICBhID0gZWlcbiAgICAgIGVwdHIgKz0gMVxuICAgICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICAgIGVpID0gZVtlcHRyXVxuICAgICAgICBlYSA9IGFicyhlaSlcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IGZpXG4gICAgICBmcHRyICs9IDFcbiAgICAgIGlmKGZwdHIgPCBuZikge1xuICAgICAgICBmaSA9IGZbZnB0cl1cbiAgICAgICAgZmEgPSBhYnMoZmkpXG4gICAgICB9XG4gICAgfVxuICAgIGIgPSBxMFxuICAgIHggPSBhICsgYlxuICAgIGJ2ID0geCAtIGFcbiAgICB5ID0gYiAtIGJ2XG4gICAgaWYoeSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHlcbiAgICB9XG4gICAgX3ggPSBxMSArIHhcbiAgICBfYnYgPSBfeCAtIHExXG4gICAgX2F2ID0gX3ggLSBfYnZcbiAgICBfYnIgPSB4IC0gX2J2XG4gICAgX2FyID0gcTEgLSBfYXZcbiAgICBxMCA9IF9hciArIF9iclxuICAgIHExID0gX3hcbiAgfVxuICB3aGlsZShlcHRyIDwgbmUpIHtcbiAgICBhID0gZWlcbiAgICBiID0gcTBcbiAgICB4ID0gYSArIGJcbiAgICBidiA9IHggLSBhXG4gICAgeSA9IGIgLSBidlxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfVxuICAgIF94ID0gcTEgKyB4XG4gICAgX2J2ID0gX3ggLSBxMVxuICAgIF9hdiA9IF94IC0gX2J2XG4gICAgX2JyID0geCAtIF9idlxuICAgIF9hciA9IHExIC0gX2F2XG4gICAgcTAgPSBfYXIgKyBfYnJcbiAgICBxMSA9IF94XG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICB9XG4gIH1cbiAgd2hpbGUoZnB0ciA8IG5mKSB7XG4gICAgYSA9IGZpXG4gICAgYiA9IHEwXG4gICAgeCA9IGEgKyBiXG4gICAgYnYgPSB4IC0gYVxuICAgIHkgPSBiIC0gYnZcbiAgICBpZih5KSB7XG4gICAgICBnW2NvdW50KytdID0geVxuICAgIH0gXG4gICAgX3ggPSBxMSArIHhcbiAgICBfYnYgPSBfeCAtIHExXG4gICAgX2F2ID0gX3ggLSBfYnZcbiAgICBfYnIgPSB4IC0gX2J2XG4gICAgX2FyID0gcTEgLSBfYXZcbiAgICBxMCA9IF9hciArIF9iclxuICAgIHExID0gX3hcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gZltmcHRyXVxuICAgIH1cbiAgfVxuICBpZihxMCkge1xuICAgIGdbY291bnQrK10gPSBxMFxuICB9XG4gIGlmKHExKSB7XG4gICAgZ1tjb3VudCsrXSA9IHExXG4gIH1cbiAgaWYoIWNvdW50KSB7XG4gICAgZ1tjb3VudCsrXSA9IDAuMCAgXG4gIH1cbiAgZy5sZW5ndGggPSBjb3VudFxuICByZXR1cm4gZ1xufSIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2lnbnVtKHgpIHtcbiAgaWYoeCA8IDApIHsgcmV0dXJuIC0xIH1cbiAgaWYoeCA+IDApIHsgcmV0dXJuIDEgfVxuICByZXR1cm4gMC4wXG59IiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gYm91bmRhcnlcblxudmFyIGJuZCA9IHJlcXVpcmUoJ2JvdW5kYXJ5LWNlbGxzJylcbnZhciByZWR1Y2UgPSByZXF1aXJlKCdyZWR1Y2Utc2ltcGxpY2lhbC1jb21wbGV4JylcblxuZnVuY3Rpb24gYm91bmRhcnkoY2VsbHMpIHtcbiAgcmV0dXJuIHJlZHVjZShibmQoY2VsbHMpKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gZXh0cmFjdENvbnRvdXJcblxudmFyIG5kYXJyYXkgPSByZXF1aXJlKCduZGFycmF5JylcbnZhciBwb29sICAgID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcbnZhciBuZHNvcnQgID0gcmVxdWlyZSgnbmRhcnJheS1zb3J0JylcblxudmFyIGNvbnRvdXJBbGdvcml0aG0gPSByZXF1aXJlKCcuL2xpYi9jb2RlZ2VuJylcblxuZnVuY3Rpb24gZ2V0RGltZW5zaW9uKGNlbGxzKSB7XG4gIHZhciBudW1DZWxscyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgZCA9IDBcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xuICAgIGQgPSBNYXRoLm1heChkLCBjZWxsc1tpXS5sZW5ndGgpfDBcbiAgfVxuICByZXR1cm4gZC0xXG59XG5cbmZ1bmN0aW9uIGdldFNpZ25zKHZhbHVlcywgbGV2ZWwpIHtcbiAgdmFyIG51bVZlcnRzICAgID0gdmFsdWVzLmxlbmd0aFxuICB2YXIgdmVydGV4U2lnbnMgPSBwb29sLm1hbGxvY1VpbnQ4KG51bVZlcnRzKVxuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0czsgKytpKSB7XG4gICAgdmVydGV4U2lnbnNbaV0gPSAodmFsdWVzW2ldIDwgbGV2ZWwpfDBcbiAgfVxuICByZXR1cm4gdmVydGV4U2lnbnNcbn1cblxuZnVuY3Rpb24gZ2V0RWRnZXMoY2VsbHMsIGQpIHtcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXG4gIHZhciBtYXhFZGdlcyA9ICgoZCAqIChkKzEpLzIpICogbnVtQ2VsbHMpfDBcbiAgdmFyIGVkZ2VzICAgID0gcG9vbC5tYWxsb2NVaW50MzIobWF4RWRnZXMqMilcbiAgdmFyIGVQdHIgICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIHZhciBkID0gYy5sZW5ndGhcbiAgICBmb3IodmFyIGo9MDsgajxkOyArK2opIHtcbiAgICAgIGZvcih2YXIgaz0wOyBrPGo7ICsraykge1xuICAgICAgICB2YXIgYSA9IGNba11cbiAgICAgICAgdmFyIGIgPSBjW2pdXG4gICAgICAgIGVkZ2VzW2VQdHIrK10gPSBNYXRoLm1pbihhLGIpfDBcbiAgICAgICAgZWRnZXNbZVB0cisrXSA9IE1hdGgubWF4KGEsYil8MFxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgbmVkZ2VzID0gKGVQdHIvMil8MFxuICBuZHNvcnQobmRhcnJheShlZGdlcywgW25lZGdlcywyXSkpIFxuICB2YXIgcHRyID0gMlxuICBmb3IodmFyIGk9MjsgaTxlUHRyOyBpKz0yKSB7XG4gICAgaWYoZWRnZXNbaS0yXSA9PT0gZWRnZXNbaV0gJiZcbiAgICAgICBlZGdlc1tpLTFdID09PSBlZGdlc1tpKzFdKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBlZGdlc1twdHIrK10gPSBlZGdlc1tpXVxuICAgIGVkZ2VzW3B0cisrXSA9IGVkZ2VzW2krMV1cbiAgfVxuXG4gIHJldHVybiBuZGFycmF5KGVkZ2VzLCBbKHB0ci8yKXwwLCAyXSlcbn1cblxuZnVuY3Rpb24gZ2V0Q3Jvc3NpbmdXZWlnaHRzKGVkZ2VzLCB2YWx1ZXMsIHNpZ25zLCBsZXZlbCkge1xuICB2YXIgZWRhdGEgICAgID0gZWRnZXMuZGF0YVxuICB2YXIgbnVtRWRnZXMgID0gZWRnZXMuc2hhcGVbMF1cbiAgdmFyIHdlaWdodHMgICA9IHBvb2wubWFsbG9jRG91YmxlKG51bUVkZ2VzKVxuICB2YXIgcHRyICAgICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgdmFyIGEgID0gZWRhdGFbMippXVxuICAgIHZhciBiICA9IGVkYXRhWzIqaSsxXVxuICAgIGlmKHNpZ25zW2FdID09PSBzaWduc1tiXSkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIHZhID0gdmFsdWVzW2FdXG4gICAgdmFyIHZiID0gdmFsdWVzW2JdXG4gICAgZWRhdGFbMipwdHJdICAgICA9IGFcbiAgICBlZGF0YVsyKnB0cisxXSAgID0gYlxuICAgIHdlaWdodHNbcHRyKytdICAgPSAodmIgLSBsZXZlbCkgLyAodmIgLSB2YSlcbiAgfVxuICBlZGdlcy5zaGFwZVswXSA9IHB0clxuICByZXR1cm4gbmRhcnJheSh3ZWlnaHRzLCBbcHRyXSlcbn1cblxuZnVuY3Rpb24gZ2V0Q2FzY2FkZShlZGdlcywgbnVtVmVydHMpIHtcbiAgdmFyIHJlc3VsdCAgID0gcG9vbC5tYWxsb2NJbnQzMihudW1WZXJ0cyoyKVxuICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5zaGFwZVswXVxuICB2YXIgZWRhdGEgICAgPSBlZGdlcy5kYXRhXG4gIHJlc3VsdFswXSAgICA9IDBcbiAgdmFyIGxhc3RWICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgdmFyIGEgPSBlZGF0YVsyKmldXG4gICAgaWYoYSAhPT0gbGFzdFYpIHtcbiAgICAgIHJlc3VsdFsyKmxhc3RWKzFdID0gaVxuICAgICAgd2hpbGUoKytsYXN0ViA8IGEpIHtcbiAgICAgICAgcmVzdWx0WzIqbGFzdFZdID0gaVxuICAgICAgICByZXN1bHRbMipsYXN0VisxXSA9IGlcbiAgICAgIH1cbiAgICAgIHJlc3VsdFsyKmxhc3RWXSA9IGlcbiAgICB9XG4gIH1cbiAgcmVzdWx0WzIqbGFzdFYrMV0gPSBudW1FZGdlc1xuICB3aGlsZSgrK2xhc3RWIDwgbnVtVmVydHMpIHtcbiAgICByZXN1bHRbMipsYXN0Vl0gPSByZXN1bHRbMipsYXN0VisxXSA9IG51bUVkZ2VzXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiB1bnBhY2tFZGdlcyhlZGdlcykge1xuICB2YXIgbmUgPSBlZGdlcy5zaGFwZVswXXwwXG4gIHZhciBlZGF0YSA9IGVkZ2VzLmRhdGFcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuZSlcbiAgZm9yKHZhciBpPTA7IGk8bmU7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IFtlZGF0YVsyKmldLCBlZGF0YVsyKmkrMV1dXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBleHRyYWN0Q29udG91cihjZWxscywgdmFsdWVzLCBsZXZlbCwgZCkge1xuICBsZXZlbCA9IGxldmVsfHwwLjBcblxuICAvL0lmIHVzZXIgZGlkbid0IHNwZWNpZnkgYGRgLCB1c2UgYnJ1dGUgZm9yY2Ugc2NhblxuICBpZih0eXBlb2YgZCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBkID0gZ2V0RGltZW5zaW9uKGNlbGxzKVxuICB9XG5cbiAgLy9Db3VudCBudW1iZXIgb2YgY2VsbHNcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXG4gIGlmKG51bUNlbGxzID09PSAwIHx8IGQgPCAxKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbGxzOiAgICAgICAgIFtdLFxuICAgICAgdmVydGV4SWRzOiAgICAgW10sXG4gICAgICB2ZXJ0ZXhXZWlnaHRzOiBbXVxuICAgIH1cbiAgfVxuXG4gIC8vUmVhZCBpbiB2ZXJ0ZXggc2lnbnNcbiAgdmFyIHZlcnRleFNpZ25zID0gZ2V0U2lnbnModmFsdWVzLCArbGV2ZWwpXG5cbiAgLy9GaXJzdCBnZXQgMS1za2VsZXRvbiwgZmluZCBhbGwgY3Jvc3NpbmdzXG4gIHZhciBlZGdlcyAgID0gZ2V0RWRnZXMoY2VsbHMsIGQpXG4gIHZhciB3ZWlnaHRzID0gZ2V0Q3Jvc3NpbmdXZWlnaHRzKGVkZ2VzLCB2YWx1ZXMsIHZlcnRleFNpZ25zLCArbGV2ZWwpXG5cbiAgLy9CdWlsZCB2ZXJ0ZXggY2FzY2FkZSB0byBzcGVlZCB1cCBiaW5hcnkgc2VhcmNoXG4gIHZhciB2Y2FzY2FkZSA9IGdldENhc2NhZGUoZWRnZXMsIHZhbHVlcy5sZW5ndGh8MClcblxuICAvL1RoZW4gY29uc3RydWN0IGNlbGxzXG4gIHZhciBmYWNlcyA9IGNvbnRvdXJBbGdvcml0aG0oZCkoY2VsbHMsIGVkZ2VzLmRhdGEsIHZjYXNjYWRlLCB2ZXJ0ZXhTaWducylcblxuICAvL1VucGFjayBkYXRhIGludG8gcHJldHR5IGZvcm1hdFxuICB2YXIgdWVkZ2VzICAgPSB1bnBhY2tFZGdlcyhlZGdlcylcbiAgdmFyIHV3ZWlnaHRzID0gW10uc2xpY2UuY2FsbCh3ZWlnaHRzLmRhdGEsIDAsIHdlaWdodHMuc2hhcGVbMF0pXG5cbiAgLy9SZWxlYXNlIGRhdGFcbiAgcG9vbC5mcmVlKHZlcnRleFNpZ25zKVxuICBwb29sLmZyZWUoZWRnZXMuZGF0YSlcbiAgcG9vbC5mcmVlKHdlaWdodHMuZGF0YSlcbiAgcG9vbC5mcmVlKHZjYXNjYWRlKVxuICBcbiAgcmV0dXJuIHtcbiAgICBjZWxsczogICAgICAgICBmYWNlcyxcbiAgICB2ZXJ0ZXhJZHM6ICAgICB1ZWRnZXMsXG4gICAgdmVydGV4V2VpZ2h0czogdXdlaWdodHNcbiAgfVxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFBvbHlnb25pemVyXG5cbnZhciBwb29sID0gcmVxdWlyZSgndHlwZWRhcnJheS1wb29sJylcbnZhciBjcmVhdGVNU1RhYmxlID0gcmVxdWlyZSgnbWFyY2hpbmctc2ltcGxleC10YWJsZScpXG5cbnZhciBDQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIGNyZWF0ZUNlbGxQb2x5Z29uaXplcihkKSB7XG4gIHZhciBtYXhDZWxsU2l6ZSA9IDBcbiAgdmFyIHRhYmxlcyA9IG5ldyBBcnJheShkKzEpXG4gIHRhYmxlc1swXSA9IFsgW10gXVxuICBmb3IodmFyIGk9MTsgaTw9ZDsgKytpKSB7XG4gICAgdmFyIHRhYiA9IHRhYmxlc1tpXSA9IGNyZWF0ZU1TVGFibGUoaSlcbiAgICBmb3IodmFyIGo9MDsgajx0YWIubGVuZ3RoOyArK2opIHtcbiAgICAgIG1heENlbGxTaXplID0gTWF0aC5tYXgobWF4Q2VsbFNpemUsIHRhYltpXS5sZW5ndGgpXG4gICAgfVxuICB9XG5cbiAgdmFyIGNvZGUgID0gW1xuICAnZnVuY3Rpb24gQihDLEUsaSxqKXsnLFxuICAgICd2YXIgYT1NYXRoLm1pbihpLGopfDAsYj1NYXRoLm1heChpLGopfDAsbD1DWzIqYV0saD1DWzIqYSsxXTsnLFxuICAgICd3aGlsZShsPGgpeycsXG4gICAgICAndmFyIG09KGwraCk+PjEsdj1FWzIqbSsxXTsnLFxuICAgICAgJ2lmKHY9PT1iKXtyZXR1cm4gbX0nLFxuICAgICAgJ2lmKGI8dil7aD1tfWVsc2V7bD1tKzF9JyxcbiAgICAnfScsXG4gICAgJ3JldHVybiBsOycsXG4gICd9OycsXG4gICdmdW5jdGlvbiBnZXRDb250b3VyJywgZCwgJ2QoRixFLEMsUyl7JyxcbiAgICAndmFyIG49Ri5sZW5ndGgsUj1bXTsnLFxuICAgICdmb3IodmFyIGk9MDtpPG47KytpKXt2YXIgYz1GW2ldLGw9Yy5sZW5ndGg7J1xuICBdXG5cbiAgZnVuY3Rpb24gZ2VuZXJhdGVDYXNlKGZhY2V0cykge1xuICAgIGlmKGZhY2V0cy5sZW5ndGggPD0gMCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvZGUucHVzaCgnUi5wdXNoKCcpXG4gICAgZm9yKHZhciBpPTA7IGk8ZmFjZXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZmFjZXQgPSBmYWNldHNbaV1cbiAgICAgIGlmKGkgPiAwKSB7XG4gICAgICAgIGNvZGUucHVzaCgnLCcpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goJ1snKVxuICAgICAgZm9yKHZhciBqPTA7IGo8ZmFjZXQubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGYgPSBmYWNldFtqXVxuICAgICAgICBpZihqID4gMCkge1xuICAgICAgICAgIGNvZGUucHVzaCgnLCcpXG4gICAgICAgIH1cbiAgICAgICAgY29kZS5wdXNoKCdCKEMsRSxjWycsIGZbMF0sICddLGNbJywgZlsxXSwgJ10pJylcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaCgnXScpXG4gICAgfVxuICAgIGNvZGUucHVzaCgnKTsnKVxuICB9XG5cbiAgZm9yKHZhciBpPWQrMTsgaT4xOyAtLWkpIHtcbiAgICBpZihpIDwgZCsxKSB7XG4gICAgICBjb2RlLnB1c2goJ2Vsc2UgJylcbiAgICB9XG4gICAgY29kZS5wdXNoKCdpZihsPT09JywgaSwgJyl7JylcblxuICAgIC8vR2VuZXJhdGUgbWFza1xuICAgIHZhciBtYXNrU3RyID0gW11cbiAgICBmb3IodmFyIGo9MDsgajxpOyArK2opIHtcbiAgICAgIG1hc2tTdHIucHVzaCgnKFNbY1snK2orJ11dPDwnK2orJyknKVxuICAgIH1cblxuICAgIC8vUGVyZm9ybSB0YWJsZSBsb29rIHVwXG4gICAgY29kZS5wdXNoKCd2YXIgTT0nLCBtYXNrU3RyLmpvaW4oJysnKSwgXG4gICAgICAnO2lmKE09PT0wfHxNPT09JywgKDE8PGkpLTEsIFxuICAgICAgICAnKXtjb250aW51ZX1zd2l0Y2goTSl7JylcblxuICAgIHZhciB0YWIgPSB0YWJsZXNbaS0xXVxuICAgIGZvcih2YXIgaj0wOyBqPHRhYi5sZW5ndGg7ICsraikge1xuICAgICAgY29kZS5wdXNoKCdjYXNlICcsIGosICc6JylcbiAgICAgIGdlbmVyYXRlQ2FzZSh0YWJbal0pXG4gICAgICBjb2RlLnB1c2goJ2JyZWFrOycpXG4gICAgfVxuICAgIGNvZGUucHVzaCgnfX0nKVxuICB9XG4gIGNvZGUucHVzaCgnfXJldHVybiBSO307cmV0dXJuIGdldENvbnRvdXInLCBkLCAnZCcpXG5cbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oJ3Bvb2wnLCBjb2RlLmpvaW4oJycpKVxuICByZXR1cm4gcHJvYyhwb29sKVxufVxuXG5mdW5jdGlvbiBnZXRQb2x5Z29uaXplcihkKSB7XG4gIHZhciBhbGcgPSBDQUNIRVtkXVxuICBpZighYWxnKSB7XG4gICAgYWxnID0gQ0FDSEVbZF0gPSBjcmVhdGVDZWxsUG9seWdvbml6ZXIoZCkgXG4gIH1cbiAgcmV0dXJuIGFsZ1xufSIsIlwidXNlIHN0cmljdFwiOyBcInVzZSByZXN0cmljdFwiO1xuXG52YXIgYml0cyAgICAgID0gcmVxdWlyZShcImJpdC10d2lkZGxlXCIpXG4gICwgVW5pb25GaW5kID0gcmVxdWlyZShcInVuaW9uLWZpbmRcIilcblxuLy9SZXR1cm5zIHRoZSBkaW1lbnNpb24gb2YgYSBjZWxsIGNvbXBsZXhcbmZ1bmN0aW9uIGRpbWVuc2lvbihjZWxscykge1xuICB2YXIgZCA9IDBcbiAgICAsIG1heCA9IE1hdGgubWF4XG4gIGZvcih2YXIgaT0wLCBpbD1jZWxscy5sZW5ndGg7IGk8aWw7ICsraSkge1xuICAgIGQgPSBtYXgoZCwgY2VsbHNbaV0ubGVuZ3RoKVxuICB9XG4gIHJldHVybiBkLTFcbn1cbmV4cG9ydHMuZGltZW5zaW9uID0gZGltZW5zaW9uXG5cbi8vQ291bnRzIHRoZSBudW1iZXIgb2YgdmVydGljZXMgaW4gZmFjZXNcbmZ1bmN0aW9uIGNvdW50VmVydGljZXMoY2VsbHMpIHtcbiAgdmFyIHZjID0gLTFcbiAgICAsIG1heCA9IE1hdGgubWF4XG4gIGZvcih2YXIgaT0wLCBpbD1jZWxscy5sZW5ndGg7IGk8aWw7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MCwgamw9Yy5sZW5ndGg7IGo8amw7ICsraikge1xuICAgICAgdmMgPSBtYXgodmMsIGNbal0pXG4gICAgfVxuICB9XG4gIHJldHVybiB2YysxXG59XG5leHBvcnRzLmNvdW50VmVydGljZXMgPSBjb3VudFZlcnRpY2VzXG5cbi8vUmV0dXJucyBhIGRlZXAgY29weSBvZiBjZWxsc1xuZnVuY3Rpb24gY2xvbmVDZWxscyhjZWxscykge1xuICB2YXIgbmNlbGxzID0gbmV3IEFycmF5KGNlbGxzLmxlbmd0aClcbiAgZm9yKHZhciBpPTAsIGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgbmNlbGxzW2ldID0gY2VsbHNbaV0uc2xpY2UoMClcbiAgfVxuICByZXR1cm4gbmNlbGxzXG59XG5leHBvcnRzLmNsb25lQ2VsbHMgPSBjbG9uZUNlbGxzXG5cbi8vUmFua3MgYSBwYWlyIG9mIGNlbGxzIHVwIHRvIHBlcm11dGF0aW9uXG5mdW5jdGlvbiBjb21wYXJlQ2VsbHMoYSwgYikge1xuICB2YXIgbiA9IGEubGVuZ3RoXG4gICAgLCB0ID0gYS5sZW5ndGggLSBiLmxlbmd0aFxuICAgICwgbWluID0gTWF0aC5taW5cbiAgaWYodCkge1xuICAgIHJldHVybiB0XG4gIH1cbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gYVswXSAtIGJbMF07XG4gICAgY2FzZSAyOlxuICAgICAgdmFyIGQgPSBhWzBdK2FbMV0tYlswXS1iWzFdXG4gICAgICBpZihkKSB7XG4gICAgICAgIHJldHVybiBkXG4gICAgICB9XG4gICAgICByZXR1cm4gbWluKGFbMF0sYVsxXSkgLSBtaW4oYlswXSxiWzFdKVxuICAgIGNhc2UgMzpcbiAgICAgIHZhciBsMSA9IGFbMF0rYVsxXVxuICAgICAgICAsIG0xID0gYlswXStiWzFdXG4gICAgICBkID0gbDErYVsyXSAtIChtMStiWzJdKVxuICAgICAgaWYoZCkge1xuICAgICAgICByZXR1cm4gZFxuICAgICAgfVxuICAgICAgdmFyIGwwID0gbWluKGFbMF0sIGFbMV0pXG4gICAgICAgICwgbTAgPSBtaW4oYlswXSwgYlsxXSlcbiAgICAgICAgLCBkICA9IG1pbihsMCwgYVsyXSkgLSBtaW4obTAsIGJbMl0pXG4gICAgICBpZihkKSB7XG4gICAgICAgIHJldHVybiBkXG4gICAgICB9XG4gICAgICByZXR1cm4gbWluKGwwK2FbMl0sIGwxKSAtIG1pbihtMCtiWzJdLCBtMSlcbiAgICBcbiAgICAvL1RPRE86IE1heWJlIG9wdGltaXplIG49NCBhcyB3ZWxsP1xuICAgIFxuICAgIGRlZmF1bHQ6XG4gICAgICB2YXIgYXMgPSBhLnNsaWNlKDApXG4gICAgICBhcy5zb3J0KClcbiAgICAgIHZhciBicyA9IGIuc2xpY2UoMClcbiAgICAgIGJzLnNvcnQoKVxuICAgICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICAgIHQgPSBhc1tpXSAtIGJzW2ldXG4gICAgICAgIGlmKHQpIHtcbiAgICAgICAgICByZXR1cm4gdFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gMFxuICB9XG59XG5leHBvcnRzLmNvbXBhcmVDZWxscyA9IGNvbXBhcmVDZWxsc1xuXG5mdW5jdGlvbiBjb21wYXJlWmlwcGVkKGEsIGIpIHtcbiAgcmV0dXJuIGNvbXBhcmVDZWxscyhhWzBdLCBiWzBdKVxufVxuXG4vL1B1dHMgYSBjZWxsIGNvbXBsZXggaW50byBub3JtYWwgb3JkZXIgZm9yIHRoZSBwdXJwb3NlcyBvZiBmaW5kQ2VsbCBxdWVyaWVzXG5mdW5jdGlvbiBub3JtYWxpemUoY2VsbHMsIGF0dHIpIHtcbiAgaWYoYXR0cikge1xuICAgIHZhciBsZW4gPSBjZWxscy5sZW5ndGhcbiAgICB2YXIgemlwcGVkID0gbmV3IEFycmF5KGxlbilcbiAgICBmb3IodmFyIGk9MDsgaTxsZW47ICsraSkge1xuICAgICAgemlwcGVkW2ldID0gW2NlbGxzW2ldLCBhdHRyW2ldXVxuICAgIH1cbiAgICB6aXBwZWQuc29ydChjb21wYXJlWmlwcGVkKVxuICAgIGZvcih2YXIgaT0wOyBpPGxlbjsgKytpKSB7XG4gICAgICBjZWxsc1tpXSA9IHppcHBlZFtpXVswXVxuICAgICAgYXR0cltpXSA9IHppcHBlZFtpXVsxXVxuICAgIH1cbiAgICByZXR1cm4gY2VsbHNcbiAgfSBlbHNlIHtcbiAgICBjZWxscy5zb3J0KGNvbXBhcmVDZWxscylcbiAgICByZXR1cm4gY2VsbHNcbiAgfVxufVxuZXhwb3J0cy5ub3JtYWxpemUgPSBub3JtYWxpemVcblxuLy9SZW1vdmVzIGFsbCBkdXBsaWNhdGUgY2VsbHMgaW4gdGhlIGNvbXBsZXhcbmZ1bmN0aW9uIHVuaXF1ZShjZWxscykge1xuICBpZihjZWxscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICB2YXIgcHRyID0gMVxuICAgICwgbGVuID0gY2VsbHMubGVuZ3RoXG4gIGZvcih2YXIgaT0xOyBpPGxlbjsgKytpKSB7XG4gICAgdmFyIGEgPSBjZWxsc1tpXVxuICAgIGlmKGNvbXBhcmVDZWxscyhhLCBjZWxsc1tpLTFdKSkge1xuICAgICAgaWYoaSA9PT0gcHRyKSB7XG4gICAgICAgIHB0cisrXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjZWxsc1twdHIrK10gPSBhXG4gICAgfVxuICB9XG4gIGNlbGxzLmxlbmd0aCA9IHB0clxuICByZXR1cm4gY2VsbHNcbn1cbmV4cG9ydHMudW5pcXVlID0gdW5pcXVlO1xuXG4vL0ZpbmRzIGEgY2VsbCBpbiBhIG5vcm1hbGl6ZWQgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBmaW5kQ2VsbChjZWxscywgYykge1xuICB2YXIgbG8gPSAwXG4gICAgLCBoaSA9IGNlbGxzLmxlbmd0aC0xXG4gICAgLCByICA9IC0xXG4gIHdoaWxlIChsbyA8PSBoaSkge1xuICAgIHZhciBtaWQgPSAobG8gKyBoaSkgPj4gMVxuICAgICAgLCBzICAgPSBjb21wYXJlQ2VsbHMoY2VsbHNbbWlkXSwgYylcbiAgICBpZihzIDw9IDApIHtcbiAgICAgIGlmKHMgPT09IDApIHtcbiAgICAgICAgciA9IG1pZFxuICAgICAgfVxuICAgICAgbG8gPSBtaWQgKyAxXG4gICAgfSBlbHNlIGlmKHMgPiAwKSB7XG4gICAgICBoaSA9IG1pZCAtIDFcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJcbn1cbmV4cG9ydHMuZmluZENlbGwgPSBmaW5kQ2VsbDtcblxuLy9CdWlsZHMgYW4gaW5kZXggZm9yIGFuIG4tY2VsbC4gIFRoaXMgaXMgbW9yZSBnZW5lcmFsIHRoYW4gZHVhbCwgYnV0IGxlc3MgZWZmaWNpZW50XG5mdW5jdGlvbiBpbmNpZGVuY2UoZnJvbV9jZWxscywgdG9fY2VsbHMpIHtcbiAgdmFyIGluZGV4ID0gbmV3IEFycmF5KGZyb21fY2VsbHMubGVuZ3RoKVxuICBmb3IodmFyIGk9MCwgaWw9aW5kZXgubGVuZ3RoOyBpPGlsOyArK2kpIHtcbiAgICBpbmRleFtpXSA9IFtdXG4gIH1cbiAgdmFyIGIgPSBbXVxuICBmb3IodmFyIGk9MCwgbj10b19jZWxscy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgdmFyIGMgPSB0b19jZWxsc1tpXVxuICAgIHZhciBjbCA9IGMubGVuZ3RoXG4gICAgZm9yKHZhciBrPTEsIGtuPSgxPDxjbCk7IGs8a247ICsraykge1xuICAgICAgYi5sZW5ndGggPSBiaXRzLnBvcENvdW50KGspXG4gICAgICB2YXIgbCA9IDBcbiAgICAgIGZvcih2YXIgaj0wOyBqPGNsOyArK2opIHtcbiAgICAgICAgaWYoayAmICgxPDxqKSkge1xuICAgICAgICAgIGJbbCsrXSA9IGNbal1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIGlkeD1maW5kQ2VsbChmcm9tX2NlbGxzLCBiKVxuICAgICAgaWYoaWR4IDwgMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgd2hpbGUodHJ1ZSkge1xuICAgICAgICBpbmRleFtpZHgrK10ucHVzaChpKVxuICAgICAgICBpZihpZHggPj0gZnJvbV9jZWxscy5sZW5ndGggfHwgY29tcGFyZUNlbGxzKGZyb21fY2VsbHNbaWR4XSwgYikgIT09IDApIHtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBpbmRleFxufVxuZXhwb3J0cy5pbmNpZGVuY2UgPSBpbmNpZGVuY2VcblxuLy9Db21wdXRlcyB0aGUgZHVhbCBvZiB0aGUgbWVzaC4gIFRoaXMgaXMgYmFzaWNhbGx5IGFuIG9wdGltaXplZCB2ZXJzaW9uIG9mIGJ1aWxkSW5kZXggZm9yIHRoZSBzaXR1YXRpb24gd2hlcmUgZnJvbV9jZWxscyBpcyBqdXN0IHRoZSBsaXN0IG9mIHZlcnRpY2VzXG5mdW5jdGlvbiBkdWFsKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgaWYoIXZlcnRleF9jb3VudCkge1xuICAgIHJldHVybiBpbmNpZGVuY2UodW5pcXVlKHNrZWxldG9uKGNlbGxzLCAwKSksIGNlbGxzLCAwKVxuICB9XG4gIHZhciByZXMgPSBuZXcgQXJyYXkodmVydGV4X2NvdW50KVxuICBmb3IodmFyIGk9MDsgaTx2ZXJ0ZXhfY291bnQ7ICsraSkge1xuICAgIHJlc1tpXSA9IFtdXG4gIH1cbiAgZm9yKHZhciBpPTAsIGxlbj1jZWxscy5sZW5ndGg7IGk8bGVuOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBqPTAsIGNsPWMubGVuZ3RoOyBqPGNsOyArK2opIHtcbiAgICAgIHJlc1tjW2pdXS5wdXNoKGkpXG4gICAgfVxuICB9XG4gIHJldHVybiByZXNcbn1cbmV4cG9ydHMuZHVhbCA9IGR1YWxcblxuLy9FbnVtZXJhdGVzIGFsbCBjZWxscyBpbiB0aGUgY29tcGxleFxuZnVuY3Rpb24gZXhwbG9kZShjZWxscykge1xuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTAsIGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgICAgLCBjbCA9IGMubGVuZ3RofDBcbiAgICBmb3IodmFyIGo9MSwgamw9KDE8PGNsKTsgajxqbDsgKytqKSB7XG4gICAgICB2YXIgYiA9IFtdXG4gICAgICBmb3IodmFyIGs9MDsgazxjbDsgKytrKSB7XG4gICAgICAgIGlmKChqID4+PiBrKSAmIDEpIHtcbiAgICAgICAgICBiLnB1c2goY1trXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmVzdWx0LnB1c2goYilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZShyZXN1bHQpXG59XG5leHBvcnRzLmV4cGxvZGUgPSBleHBsb2RlXG5cbi8vRW51bWVyYXRlcyBhbGwgb2YgdGhlIG4tY2VsbHMgb2YgYSBjZWxsIGNvbXBsZXhcbmZ1bmN0aW9uIHNrZWxldG9uKGNlbGxzLCBuKSB7XG4gIGlmKG4gPCAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIHJlc3VsdCA9IFtdXG4gICAgLCBrMCAgICAgPSAoMTw8KG4rMSkpLTFcbiAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBrPWswOyBrPCgxPDxjLmxlbmd0aCk7IGs9Yml0cy5uZXh0Q29tYmluYXRpb24oaykpIHtcbiAgICAgIHZhciBiID0gbmV3IEFycmF5KG4rMSlcbiAgICAgICAgLCBsID0gMFxuICAgICAgZm9yKHZhciBqPTA7IGo8Yy5sZW5ndGg7ICsraikge1xuICAgICAgICBpZihrICYgKDE8PGopKSB7XG4gICAgICAgICAgYltsKytdID0gY1tqXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXN1bHQucHVzaChiKVxuICAgIH1cbiAgfVxuICByZXR1cm4gbm9ybWFsaXplKHJlc3VsdClcbn1cbmV4cG9ydHMuc2tlbGV0b24gPSBza2VsZXRvbjtcblxuLy9Db21wdXRlcyB0aGUgYm91bmRhcnkgb2YgYWxsIGNlbGxzLCBkb2VzIG5vdCByZW1vdmUgZHVwbGljYXRlc1xuZnVuY3Rpb24gYm91bmRhcnkoY2VsbHMpIHtcbiAgdmFyIHJlcyA9IFtdXG4gIGZvcih2YXIgaT0wLGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wLGNsPWMubGVuZ3RoOyBqPGNsOyArK2opIHtcbiAgICAgIHZhciBiID0gbmV3IEFycmF5KGMubGVuZ3RoLTEpXG4gICAgICBmb3IodmFyIGs9MCwgbD0wOyBrPGNsOyArK2spIHtcbiAgICAgICAgaWYoayAhPT0gaikge1xuICAgICAgICAgIGJbbCsrXSA9IGNba11cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmVzLnB1c2goYilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZShyZXMpXG59XG5leHBvcnRzLmJvdW5kYXJ5ID0gYm91bmRhcnk7XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgZGVuc2UgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzX2RlbnNlKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgdmFyIGxhYmVscyA9IG5ldyBVbmlvbkZpbmQodmVydGV4X2NvdW50KVxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XG4gICAgICBmb3IodmFyIGs9aisxOyBrPGMubGVuZ3RoOyArK2spIHtcbiAgICAgICAgbGFiZWxzLmxpbmsoY1tqXSwgY1trXSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIGNvbXBvbmVudHMgPSBbXVxuICAgICwgY29tcG9uZW50X2xhYmVscyA9IGxhYmVscy5yYW5rc1xuICBmb3IodmFyIGk9MDsgaTxjb21wb25lbnRfbGFiZWxzLmxlbmd0aDsgKytpKSB7XG4gICAgY29tcG9uZW50X2xhYmVsc1tpXSA9IC0xXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgbCA9IGxhYmVscy5maW5kKGNlbGxzW2ldWzBdKVxuICAgIGlmKGNvbXBvbmVudF9sYWJlbHNbbF0gPCAwKSB7XG4gICAgICBjb21wb25lbnRfbGFiZWxzW2xdID0gY29tcG9uZW50cy5sZW5ndGhcbiAgICAgIGNvbXBvbmVudHMucHVzaChbY2VsbHNbaV0uc2xpY2UoMCldKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudF9sYWJlbHNbbF1dLnB1c2goY2VsbHNbaV0uc2xpY2UoMCkpXG4gICAgfVxuICB9XG4gIHJldHVybiBjb21wb25lbnRzXG59XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgc3BhcnNlIGdyYXBoXG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzX3NwYXJzZShjZWxscykge1xuICB2YXIgdmVydGljZXMgID0gdW5pcXVlKG5vcm1hbGl6ZShza2VsZXRvbihjZWxscywgMCkpKVxuICAgICwgbGFiZWxzICAgID0gbmV3IFVuaW9uRmluZCh2ZXJ0aWNlcy5sZW5ndGgpXG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPGMubGVuZ3RoOyArK2opIHtcbiAgICAgIHZhciB2aiA9IGZpbmRDZWxsKHZlcnRpY2VzLCBbY1tqXV0pXG4gICAgICBmb3IodmFyIGs9aisxOyBrPGMubGVuZ3RoOyArK2spIHtcbiAgICAgICAgbGFiZWxzLmxpbmsodmosIGZpbmRDZWxsKHZlcnRpY2VzLCBbY1trXV0pKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgY29tcG9uZW50cyAgICAgICAgPSBbXVxuICAgICwgY29tcG9uZW50X2xhYmVscyAgPSBsYWJlbHMucmFua3NcbiAgZm9yKHZhciBpPTA7IGk8Y29tcG9uZW50X2xhYmVscy5sZW5ndGg7ICsraSkge1xuICAgIGNvbXBvbmVudF9sYWJlbHNbaV0gPSAtMVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGwgPSBsYWJlbHMuZmluZChmaW5kQ2VsbCh2ZXJ0aWNlcywgW2NlbGxzW2ldWzBdXSkpO1xuICAgIGlmKGNvbXBvbmVudF9sYWJlbHNbbF0gPCAwKSB7XG4gICAgICBjb21wb25lbnRfbGFiZWxzW2xdID0gY29tcG9uZW50cy5sZW5ndGhcbiAgICAgIGNvbXBvbmVudHMucHVzaChbY2VsbHNbaV0uc2xpY2UoMCldKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudF9sYWJlbHNbbF1dLnB1c2goY2VsbHNbaV0uc2xpY2UoMCkpXG4gICAgfVxuICB9XG4gIHJldHVybiBjb21wb25lbnRzXG59XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgaWYodmVydGV4X2NvdW50KSB7XG4gICAgcmV0dXJuIGNvbm5lY3RlZENvbXBvbmVudHNfZGVuc2UoY2VsbHMsIHZlcnRleF9jb3VudClcbiAgfVxuICByZXR1cm4gY29ubmVjdGVkQ29tcG9uZW50c19zcGFyc2UoY2VsbHMpXG59XG5leHBvcnRzLmNvbm5lY3RlZENvbXBvbmVudHMgPSBjb25uZWN0ZWRDb21wb25lbnRzXG4iLCJcInVzZSBzdHJpY3RcIjsgXCJ1c2UgcmVzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBVbmlvbkZpbmQ7XG5cbmZ1bmN0aW9uIFVuaW9uRmluZChjb3VudCkge1xuICB0aGlzLnJvb3RzID0gbmV3IEFycmF5KGNvdW50KTtcbiAgdGhpcy5yYW5rcyA9IG5ldyBBcnJheShjb3VudCk7XG4gIFxuICBmb3IodmFyIGk9MDsgaTxjb3VudDsgKytpKSB7XG4gICAgdGhpcy5yb290c1tpXSA9IGk7XG4gICAgdGhpcy5yYW5rc1tpXSA9IDA7XG4gIH1cbn1cblxuVW5pb25GaW5kLnByb3RvdHlwZS5sZW5ndGggPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMucm9vdHMubGVuZ3RoO1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLm1ha2VTZXQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG4gPSB0aGlzLnJvb3RzLmxlbmd0aDtcbiAgdGhpcy5yb290cy5wdXNoKG4pO1xuICB0aGlzLnJhbmtzLnB1c2goMCk7XG4gIHJldHVybiBuO1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLmZpbmQgPSBmdW5jdGlvbih4KSB7XG4gIHZhciByb290cyA9IHRoaXMucm9vdHM7XG4gIHdoaWxlKHJvb3RzW3hdICE9PSB4KSB7XG4gICAgdmFyIHkgPSByb290c1t4XTtcbiAgICByb290c1t4XSA9IHJvb3RzW3ldO1xuICAgIHggPSB5O1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLmxpbmsgPSBmdW5jdGlvbih4LCB5KSB7XG4gIHZhciB4ciA9IHRoaXMuZmluZCh4KVxuICAgICwgeXIgPSB0aGlzLmZpbmQoeSk7XG4gIGlmKHhyID09PSB5cikge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgcmFua3MgPSB0aGlzLnJhbmtzXG4gICAgLCByb290cyA9IHRoaXMucm9vdHNcbiAgICAsIHhkICAgID0gcmFua3NbeHJdXG4gICAgLCB5ZCAgICA9IHJhbmtzW3lyXTtcbiAgaWYoeGQgPCB5ZCkge1xuICAgIHJvb3RzW3hyXSA9IHlyO1xuICB9IGVsc2UgaWYoeWQgPCB4ZCkge1xuICAgIHJvb3RzW3lyXSA9IHhyO1xuICB9IGVsc2Uge1xuICAgIHJvb3RzW3lyXSA9IHhyO1xuICAgICsrcmFua3NbeHJdO1xuICB9XG59XG5cbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gc2ltcGxpZnlQb2x5Z29uXG5cbnZhciBvcmllbnQgPSByZXF1aXJlKFwicm9idXN0LW9yaWVudGF0aW9uXCIpXG52YXIgc2MgPSByZXF1aXJlKFwic2ltcGxpY2lhbC1jb21wbGV4XCIpXG5cbmZ1bmN0aW9uIGVycm9yV2VpZ2h0KGJhc2UsIGEsIGIpIHtcbiAgdmFyIGFyZWEgPSBNYXRoLmFicyhvcmllbnQoYmFzZSwgYSwgYikpXG4gIHZhciBwZXJpbSA9IE1hdGguc3FydChNYXRoLnBvdyhhWzBdIC0gYlswXSwgMikgKyBNYXRoLnBvdyhhWzFdLWJbMV0sIDIpKVxuICByZXR1cm4gYXJlYSAvIHBlcmltXG59XG5cbmZ1bmN0aW9uIHNpbXBsaWZ5UG9seWdvbihjZWxscywgcG9zaXRpb25zLCBtaW5BcmVhKSB7XG5cbiAgdmFyIG4gPSBwb3NpdGlvbnMubGVuZ3RoXG4gIHZhciBuYyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgaW52ID0gbmV3IEFycmF5KG4pXG4gIHZhciBvdXR2ID0gbmV3IEFycmF5KG4pXG4gIHZhciB3ZWlnaHRzID0gbmV3IEFycmF5KG4pXG4gIHZhciBkZWFkID0gbmV3IEFycmF5KG4pXG4gIFxuICAvL0luaXRpYWxpemUgdGFibGVzXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGludltpXSA9IG91dHZbaV0gPSAtMVxuICAgIHdlaWdodHNbaV0gPSBJbmZpbml0eVxuICAgIGRlYWRbaV0gPSBmYWxzZVxuICB9XG5cbiAgLy9Db21wdXRlIG5laWdoYm9yc1xuICBmb3IodmFyIGk9MDsgaTxuYzsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGlmKGMubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnB1dCBtdXN0IGJlIGEgZ3JhcGhcIilcbiAgICB9XG4gICAgdmFyIHMgPSBjWzFdXG4gICAgdmFyIHQgPSBjWzBdXG4gICAgaWYob3V0dlt0XSAhPT0gLTEpIHtcbiAgICAgIG91dHZbdF0gPSAtMlxuICAgIH0gZWxzZSB7XG4gICAgICBvdXR2W3RdID0gc1xuICAgIH1cbiAgICBpZihpbnZbc10gIT09IC0xKSB7XG4gICAgICBpbnZbc10gPSAtMlxuICAgIH0gZWxzZSB7XG4gICAgICBpbnZbc10gPSB0XG4gICAgfVxuICB9XG5cbiAgLy9VcGRhdGVzIHRoZSB3ZWlnaHQgZm9yIHZlcnRleCBpXG4gIGZ1bmN0aW9uIGNvbXB1dGVXZWlnaHQoaSkge1xuICAgIGlmKGRlYWRbaV0pIHtcbiAgICAgIHJldHVybiBJbmZpbml0eVxuICAgIH1cbiAgICAvL1RPRE86IENoZWNrIHRoYXQgdGhlIGxpbmUgc2VnbWVudCBkb2Vzbid0IGNyb3NzIG9uY2Ugc2ltcGxpZmllZFxuICAgIHZhciBzID0gaW52W2ldXG4gICAgdmFyIHQgPSBvdXR2W2ldXG4gICAgaWYoKHM8MCkgfHwgKHQ8MCkpIHtcbiAgICAgIHJldHVybiBJbmZpbml0eVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZXJyb3JXZWlnaHQocG9zaXRpb25zW2ldLCBwb3NpdGlvbnNbc10sIHBvc2l0aW9uc1t0XSlcbiAgICB9XG4gIH1cblxuICAvL1N3YXBzIHR3byBub2RlcyBvbiB0aGUgaGVhcCAoaSxqKSBhcmUgdGhlIGluZGV4IG9mIHRoZSBub2Rlc1xuICBmdW5jdGlvbiBoZWFwU3dhcChpLGopIHtcbiAgICB2YXIgYSA9IGhlYXBbaV1cbiAgICB2YXIgYiA9IGhlYXBbal1cbiAgICBoZWFwW2ldID0gYlxuICAgIGhlYXBbal0gPSBhXG4gICAgaW5kZXhbYV0gPSBqXG4gICAgaW5kZXhbYl0gPSBpXG4gIH1cblxuICAvL1JldHVybnMgdGhlIHdlaWdodCBvZiBub2RlIGkgb24gdGhlIGhlYXBcbiAgZnVuY3Rpb24gaGVhcFdlaWdodChpKSB7XG4gICAgcmV0dXJuIHdlaWdodHNbaGVhcFtpXV1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhlYXBQYXJlbnQoaSkge1xuICAgIGlmKGkgJiAxKSB7XG4gICAgICByZXR1cm4gKGkgLSAxKSA+PiAxXG4gICAgfVxuICAgIHJldHVybiAoaSA+PiAxKSAtIDFcbiAgfVxuXG4gIC8vQnViYmxlIGVsZW1lbnQgaSBkb3duIHRoZSBoZWFwXG4gIGZ1bmN0aW9uIGhlYXBEb3duKGkpIHtcbiAgICB2YXIgdyA9IGhlYXBXZWlnaHQoaSlcbiAgICB3aGlsZSh0cnVlKSB7XG4gICAgICB2YXIgdHcgPSB3XG4gICAgICB2YXIgbGVmdCAgPSAyKmkgKyAxXG4gICAgICB2YXIgcmlnaHQgPSAyKihpICsgMSlcbiAgICAgIHZhciBuZXh0ID0gaVxuICAgICAgaWYobGVmdCA8IGhlYXBDb3VudCkge1xuICAgICAgICB2YXIgbHcgPSBoZWFwV2VpZ2h0KGxlZnQpXG4gICAgICAgIGlmKGx3IDwgdHcpIHtcbiAgICAgICAgICBuZXh0ID0gbGVmdFxuICAgICAgICAgIHR3ID0gbHdcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYocmlnaHQgPCBoZWFwQ291bnQpIHtcbiAgICAgICAgdmFyIHJ3ID0gaGVhcFdlaWdodChyaWdodClcbiAgICAgICAgaWYocncgPCB0dykge1xuICAgICAgICAgIG5leHQgPSByaWdodFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZihuZXh0ID09PSBpKSB7XG4gICAgICAgIHJldHVybiBpXG4gICAgICB9XG4gICAgICBoZWFwU3dhcChpLCBuZXh0KVxuICAgICAgaSA9IG5leHQgICAgICBcbiAgICB9XG4gIH1cblxuICAvL0J1YmJsZXMgZWxlbWVudCBpIHVwIHRoZSBoZWFwXG4gIGZ1bmN0aW9uIGhlYXBVcChpKSB7XG4gICAgdmFyIHcgPSBoZWFwV2VpZ2h0KGkpXG4gICAgd2hpbGUoaSA+IDApIHtcbiAgICAgIHZhciBwYXJlbnQgPSBoZWFwUGFyZW50KGkpXG4gICAgICBpZihwYXJlbnQgPj0gMCkge1xuICAgICAgICB2YXIgcHcgPSBoZWFwV2VpZ2h0KHBhcmVudClcbiAgICAgICAgaWYodyA8IHB3KSB7XG4gICAgICAgICAgaGVhcFN3YXAoaSwgcGFyZW50KVxuICAgICAgICAgIGkgPSBwYXJlbnRcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIC8vUG9wIG1pbmltdW0gZWxlbWVudFxuICBmdW5jdGlvbiBoZWFwUG9wKCkge1xuICAgIGlmKGhlYXBDb3VudCA+IDApIHtcbiAgICAgIHZhciBoZWFkID0gaGVhcFswXVxuICAgICAgaGVhcFN3YXAoMCwgaGVhcENvdW50LTEpXG4gICAgICBoZWFwQ291bnQgLT0gMVxuICAgICAgaGVhcERvd24oMClcbiAgICAgIHJldHVybiBoZWFkXG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgLy9VcGRhdGUgaGVhcCBpdGVtIGlcbiAgZnVuY3Rpb24gaGVhcFVwZGF0ZShpLCB3KSB7XG4gICAgdmFyIGEgPSBoZWFwW2ldXG4gICAgaWYod2VpZ2h0c1thXSA9PT0gdykge1xuICAgICAgcmV0dXJuIGlcbiAgICB9XG4gICAgd2VpZ2h0c1thXSA9IC1JbmZpbml0eVxuICAgIGhlYXBVcChpKVxuICAgIGhlYXBQb3AoKVxuICAgIHdlaWdodHNbYV0gPSB3XG4gICAgaGVhcENvdW50ICs9IDFcbiAgICByZXR1cm4gaGVhcFVwKGhlYXBDb3VudC0xKVxuICB9XG5cbiAgLy9LaWxscyBhIHZlcnRleCAoYXNzdW1lIHZlcnRleCBhbHJlYWR5IHJlbW92ZWQgZnJvbSBoZWFwKVxuICBmdW5jdGlvbiBraWxsKGkpIHtcbiAgICBpZihkZWFkW2ldKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgLy9LaWxsIHZlcnRleFxuICAgIGRlYWRbaV0gPSB0cnVlXG4gICAgLy9GaXh1cCB0b3BvbG9neVxuICAgIHZhciBzID0gaW52W2ldXG4gICAgdmFyIHQgPSBvdXR2W2ldXG4gICAgaWYoaW52W3RdID49IDApIHtcbiAgICAgIGludlt0XSA9IHNcbiAgICB9XG4gICAgaWYob3V0dltzXSA+PSAwKSB7XG4gICAgICBvdXR2W3NdID0gdFxuICAgIH1cblxuICAgIC8vVXBkYXRlIHdlaWdodHMgb24gcyBhbmQgdFxuICAgIGlmKGluZGV4W3NdID49IDApIHtcbiAgICAgIGhlYXBVcGRhdGUoaW5kZXhbc10sIGNvbXB1dGVXZWlnaHQocykpXG4gICAgfVxuICAgIGlmKGluZGV4W3RdID49IDApIHtcbiAgICAgIGhlYXBVcGRhdGUoaW5kZXhbdF0sIGNvbXB1dGVXZWlnaHQodCkpXG4gICAgfVxuICB9XG5cbiAgLy9Jbml0aWFsaXplIHdlaWdodHMgYW5kIGhlYXBcbiAgdmFyIGhlYXAgPSBbXVxuICB2YXIgaW5kZXggPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgdmFyIHcgPSB3ZWlnaHRzW2ldID0gY29tcHV0ZVdlaWdodChpKVxuICAgIGlmKHcgPCBJbmZpbml0eSkge1xuICAgICAgaW5kZXhbaV0gPSBoZWFwLmxlbmd0aFxuICAgICAgaGVhcC5wdXNoKGkpXG4gICAgfSBlbHNlIHtcbiAgICAgIGluZGV4W2ldID0gLTFcbiAgICB9XG4gIH1cbiAgdmFyIGhlYXBDb3VudCA9IGhlYXAubGVuZ3RoXG4gIGZvcih2YXIgaT1oZWFwQ291bnQ+PjE7IGk+PTA7IC0taSkge1xuICAgIGhlYXBEb3duKGkpXG4gIH1cbiAgXG4gIC8vS2lsbCB2ZXJ0aWNlc1xuICB3aGlsZSh0cnVlKSB7XG4gICAgdmFyIGhtaW4gPSBoZWFwUG9wKClcbiAgICBpZigoaG1pbiA8IDApIHx8ICh3ZWlnaHRzW2htaW5dID4gbWluQXJlYSkpIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIGtpbGwoaG1pbilcbiAgfVxuXG4gIC8vQnVpbGQgY29sbGFwc2VkIHZlcnRleCB0YWJsZVxuICB2YXIgbnBvc2l0aW9ucyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGlmKCFkZWFkW2ldKSB7XG4gICAgICBpbmRleFtpXSA9IG5wb3NpdGlvbnMubGVuZ3RoXG4gICAgICBucG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2ldLnNsaWNlKCkpXG4gICAgfVxuICB9XG4gIHZhciBudiA9IG5wb3NpdGlvbnMubGVuZ3RoXG5cbiAgZnVuY3Rpb24gdG9ydG9pc2VIYXJlKHNlcSwgc3RhcnQpIHtcbiAgICBpZihzZXFbc3RhcnRdIDwgMCkge1xuICAgICAgcmV0dXJuIHN0YXJ0XG4gICAgfVxuICAgIHZhciB0ID0gc3RhcnRcbiAgICB2YXIgaCA9IHN0YXJ0XG4gICAgZG8ge1xuICAgICAgLy9XYWxrIHR3byBzdGVwcyB3aXRoIGhcbiAgICAgIHZhciBuaCA9IHNlcVtoXVxuICAgICAgaWYoIWRlYWRbaF0gfHwgbmggPCAwIHx8IG5oID09PSBoKSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBoID0gbmhcbiAgICAgIG5oID0gc2VxW2hdXG4gICAgICBpZighZGVhZFtoXSB8fCBuaCA8IDAgfHwgbmggPT09IGgpIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGggPSBuaFxuXG4gICAgICAvL1dhbGsgb25lIHN0ZXAgd2l0aCB0XG4gICAgICB0ID0gc2VxW3RdXG4gICAgfSB3aGlsZSh0ICE9PSBoKVxuICAgIC8vQ29tcHJlc3MgY3ljbGVzXG4gICAgZm9yKHZhciB2PXN0YXJ0OyB2IT09aDsgdiA9IHNlcVt2XSkge1xuICAgICAgc2VxW3ZdID0gaFxuICAgIH1cbiAgICByZXR1cm4gaFxuICB9XG5cbiAgdmFyIG5jZWxscyA9IFtdXG4gIGNlbGxzLmZvckVhY2goZnVuY3Rpb24oYykge1xuICAgIHZhciB0aW4gPSB0b3J0b2lzZUhhcmUoaW52LCBjWzBdKVxuICAgIHZhciB0b3V0ID0gdG9ydG9pc2VIYXJlKG91dHYsIGNbMV0pXG4gICAgaWYodGluID49IDAgJiYgdG91dCA+PSAwICYmIHRpbiAhPT0gdG91dCkge1xuICAgICAgdmFyIGNpbiA9IGluZGV4W3Rpbl1cbiAgICAgIHZhciBjb3V0ID0gaW5kZXhbdG91dF1cbiAgICAgIGlmKGNpbiAhPT0gY291dCkge1xuICAgICAgICBuY2VsbHMucHVzaChbIGNpbiwgY291dCBdKVxuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvL05vcm1hbGl6ZSByZXN1bHRcbiAgc2MudW5pcXVlKHNjLm5vcm1hbGl6ZShuY2VsbHMpKVxuXG4gIC8vUmV0dXJuIGZpbmFsIGxpc3Qgb2YgY2VsbHNcbiAgcmV0dXJuIHtcbiAgICBwb3NpdGlvbnM6IG5wb3NpdGlvbnMsXG4gICAgZWRnZXM6IG5jZWxsc1xuICB9XG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBvcmRlclNlZ21lbnRzXG5cbnZhciBvcmllbnQgPSByZXF1aXJlKFwicm9idXN0LW9yaWVudGF0aW9uXCIpXG5cbmZ1bmN0aW9uIGhvcml6b250YWxPcmRlcihhLCBiKSB7XG4gIHZhciBibCwgYnJcbiAgaWYoYlswXVswXSA8IGJbMV1bMF0pIHtcbiAgICBibCA9IGJbMF1cbiAgICBiciA9IGJbMV1cbiAgfSBlbHNlIGlmKGJbMF1bMF0gPiBiWzFdWzBdKSB7XG4gICAgYmwgPSBiWzFdXG4gICAgYnIgPSBiWzBdXG4gIH0gZWxzZSB7XG4gICAgdmFyIGFsbyA9IE1hdGgubWluKGFbMF1bMV0sIGFbMV1bMV0pXG4gICAgdmFyIGFoaSA9IE1hdGgubWF4KGFbMF1bMV0sIGFbMV1bMV0pXG4gICAgdmFyIGJsbyA9IE1hdGgubWluKGJbMF1bMV0sIGJbMV1bMV0pXG4gICAgdmFyIGJoaSA9IE1hdGgubWF4KGJbMF1bMV0sIGJbMV1bMV0pXG4gICAgaWYoYWhpIDwgYmxvKSB7XG4gICAgICByZXR1cm4gYWhpIC0gYmxvXG4gICAgfVxuICAgIGlmKGFsbyA+IGJoaSkge1xuICAgICAgcmV0dXJuIGFsbyAtIGJoaVxuICAgIH1cbiAgICByZXR1cm4gYWhpIC0gYmhpXG4gIH1cbiAgdmFyIGFsLCBhclxuICBpZihhWzBdWzFdIDwgYVsxXVsxXSkge1xuICAgIGFsID0gYVswXVxuICAgIGFyID0gYVsxXVxuICB9IGVsc2Uge1xuICAgIGFsID0gYVsxXVxuICAgIGFyID0gYVswXVxuICB9XG4gIHZhciBkID0gb3JpZW50KGJyLCBibCwgYWwpXG4gIGlmKGQpIHtcbiAgICByZXR1cm4gZFxuICB9XG4gIGQgPSBvcmllbnQoYnIsIGJsLCBhcilcbiAgaWYoZCkge1xuICAgIHJldHVybiBkXG4gIH1cbiAgcmV0dXJuIGFyIC0gYnJcbn1cblxuZnVuY3Rpb24gb3JkZXJTZWdtZW50cyhiLCBhKSB7XG4gIHZhciBhbCwgYXJcbiAgaWYoYVswXVswXSA8IGFbMV1bMF0pIHtcbiAgICBhbCA9IGFbMF1cbiAgICBhciA9IGFbMV1cbiAgfSBlbHNlIGlmKGFbMF1bMF0gPiBhWzFdWzBdKSB7XG4gICAgYWwgPSBhWzFdXG4gICAgYXIgPSBhWzBdXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGhvcml6b250YWxPcmRlcihhLCBiKVxuICB9XG4gIHZhciBibCwgYnJcbiAgaWYoYlswXVswXSA8IGJbMV1bMF0pIHtcbiAgICBibCA9IGJbMF1cbiAgICBiciA9IGJbMV1cbiAgfSBlbHNlIGlmKGJbMF1bMF0gPiBiWzFdWzBdKSB7XG4gICAgYmwgPSBiWzFdXG4gICAgYnIgPSBiWzBdXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIC1ob3Jpem9udGFsT3JkZXIoYiwgYSlcbiAgfVxuICB2YXIgZDEgPSBvcmllbnQoYWwsIGFyLCBicilcbiAgdmFyIGQyID0gb3JpZW50KGFsLCBhciwgYmwpXG4gIGlmKGQxIDwgMCkge1xuICAgIGlmKGQyIDw9IDApIHtcbiAgICAgIHJldHVybiBkMVxuICAgIH1cbiAgfSBlbHNlIGlmKGQxID4gMCkge1xuICAgIGlmKGQyID49IDApIHtcbiAgICAgIHJldHVybiBkMVxuICAgIH1cbiAgfSBlbHNlIGlmKGQyKSB7XG4gICAgcmV0dXJuIGQyXG4gIH1cbiAgZDEgPSBvcmllbnQoYnIsIGJsLCBhcilcbiAgZDIgPSBvcmllbnQoYnIsIGJsLCBhbClcbiAgaWYoZDEgPCAwKSB7XG4gICAgaWYoZDIgPD0gMCkge1xuICAgICAgcmV0dXJuIGQxXG4gICAgfVxuICB9IGVsc2UgaWYoZDEgPiAwKSB7XG4gICAgaWYoZDIgPj0gMCkge1xuICAgICAgcmV0dXJuIGQxXG4gICAgfVxuICB9IGVsc2UgaWYoZDIpIHtcbiAgICByZXR1cm4gZDJcbiAgfVxuICByZXR1cm4gYXJbMF0gLSBiclswXVxufSIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2xhYkRlY29tcG9zaXRpb25cblxudmFyIGJvdW5kcyA9IHJlcXVpcmUoXCJiaW5hcnktc2VhcmNoLWJvdW5kc1wiKVxudmFyIGNyZWF0ZVJCVHJlZSA9IHJlcXVpcmUoXCJmdW5jdGlvbmFsLXJlZC1ibGFjay10cmVlXCIpXG52YXIgb3JpZW50ID0gcmVxdWlyZShcInJvYnVzdC1vcmllbnRhdGlvblwiKVxudmFyIG9yZGVyU2VnbWVudHMgPSByZXF1aXJlKFwiLi9saWIvb3JkZXItc2VnbWVudHNcIilcblxuZnVuY3Rpb24gU2xhYkRlY29tcG9zaXRpb24oc2xhYnMsIGNvb3JkaW5hdGVzLCBob3Jpem9udGFsKSB7XG4gIHRoaXMuc2xhYnMgPSBzbGFic1xuICB0aGlzLmNvb3JkaW5hdGVzID0gY29vcmRpbmF0ZXNcbiAgdGhpcy5ob3Jpem9udGFsID0gaG9yaXpvbnRhbFxufVxuXG52YXIgcHJvdG8gPSBTbGFiRGVjb21wb3NpdGlvbi5wcm90b3R5cGVcblxuZnVuY3Rpb24gY29tcGFyZUhvcml6b250YWwoZSwgeSkge1xuICByZXR1cm4gZS55IC0geVxufVxuXG5mdW5jdGlvbiBzZWFyY2hCdWNrZXQocm9vdCwgcCkge1xuICB2YXIgbGFzdE5vZGUgPSBudWxsXG4gIHdoaWxlKHJvb3QpIHtcbiAgICB2YXIgc2VnID0gcm9vdC5rZXlcbiAgICB2YXIgbCwgclxuICAgIGlmKHNlZ1swXVswXSA8IHNlZ1sxXVswXSkge1xuICAgICAgbCA9IHNlZ1swXVxuICAgICAgciA9IHNlZ1sxXVxuICAgIH0gZWxzZSB7XG4gICAgICBsID0gc2VnWzFdXG4gICAgICByID0gc2VnWzBdXG4gICAgfVxuICAgIHZhciBvID0gb3JpZW50KGwsIHIsIHApXG4gICAgaWYobyA8IDApIHtcbiAgICAgIHJvb3QgPSByb290LmxlZnRcbiAgICB9IGVsc2UgaWYobyA+IDApIHtcbiAgICAgIGlmKHBbMF0gIT09IHNlZ1sxXVswXSkge1xuICAgICAgICBsYXN0Tm9kZSA9IHJvb3RcbiAgICAgICAgcm9vdCA9IHJvb3QucmlnaHRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB2YWwgPSBzZWFyY2hCdWNrZXQocm9vdC5yaWdodCwgcClcbiAgICAgICAgaWYodmFsKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbFxuICAgICAgICB9XG4gICAgICAgIHJvb3QgPSByb290LmxlZnRcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYocFswXSAhPT0gc2VnWzFdWzBdKSB7XG4gICAgICAgIHJldHVybiByb290XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdmFsID0gc2VhcmNoQnVja2V0KHJvb3QucmlnaHQsIHApXG4gICAgICAgIGlmKHZhbCkge1xuICAgICAgICAgIHJldHVybiB2YWxcbiAgICAgICAgfVxuICAgICAgICByb290ID0gcm9vdC5sZWZ0XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBsYXN0Tm9kZVxufVxuXG5wcm90by5jYXN0VXAgPSBmdW5jdGlvbihwKSB7XG4gIHZhciBidWNrZXQgPSBib3VuZHMubGUodGhpcy5jb29yZGluYXRlcywgcFswXSlcbiAgaWYoYnVja2V0IDwgMCkge1xuICAgIHJldHVybiAtMVxuICB9XG4gIHZhciByb290ID0gdGhpcy5zbGFic1tidWNrZXRdXG4gIHZhciBoaXROb2RlID0gc2VhcmNoQnVja2V0KHRoaXMuc2xhYnNbYnVja2V0XSwgcClcbiAgdmFyIGxhc3RIaXQgPSAtMVxuICBpZihoaXROb2RlKSB7XG4gICAgbGFzdEhpdCA9IGhpdE5vZGUudmFsdWVcbiAgfVxuICAvL0VkZ2UgY2FzZTogbmVlZCB0byBoYW5kbGUgaG9yaXpvbnRhbCBzZWdtZW50cyAoc3Vja3MpXG4gIGlmKHRoaXMuY29vcmRpbmF0ZXNbYnVja2V0XSA9PT0gcFswXSkge1xuICAgIHZhciBsYXN0U2VnbWVudCA9IG51bGxcbiAgICBpZihoaXROb2RlKSB7XG4gICAgICBsYXN0U2VnbWVudCA9IGhpdE5vZGUua2V5XG4gICAgfVxuICAgIGlmKGJ1Y2tldCA+IDApIHtcbiAgICAgIHZhciBvdGhlckhpdE5vZGUgPSBzZWFyY2hCdWNrZXQodGhpcy5zbGFic1tidWNrZXQtMV0sIHApXG4gICAgICBpZihvdGhlckhpdE5vZGUpIHtcbiAgICAgICAgaWYobGFzdFNlZ21lbnQpIHtcbiAgICAgICAgICBpZihvcmRlclNlZ21lbnRzKG90aGVySGl0Tm9kZS5rZXksIGxhc3RTZWdtZW50KSA+IDApIHtcbiAgICAgICAgICAgIGxhc3RTZWdtZW50ID0gb3RoZXJIaXROb2RlLmtleVxuICAgICAgICAgICAgbGFzdEhpdCA9IG90aGVySGl0Tm9kZS52YWx1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsYXN0SGl0ID0gb3RoZXJIaXROb2RlLnZhbHVlXG4gICAgICAgICAgbGFzdFNlZ21lbnQgPSBvdGhlckhpdE5vZGUua2V5XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGhvcml6ID0gdGhpcy5ob3Jpem9udGFsW2J1Y2tldF1cbiAgICBpZihob3Jpei5sZW5ndGggPiAwKSB7XG4gICAgICB2YXIgaGJ1Y2tldCA9IGJvdW5kcy5nZShob3JpeiwgcFsxXSwgY29tcGFyZUhvcml6b250YWwpXG4gICAgICBpZihoYnVja2V0IDwgaG9yaXoubGVuZ3RoKSB7XG4gICAgICAgIHZhciBlID0gaG9yaXpbaGJ1Y2tldF1cbiAgICAgICAgaWYocFsxXSA9PT0gZS55KSB7XG4gICAgICAgICAgaWYoZS5jbG9zZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBlLmluZGV4XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdoaWxlKGhidWNrZXQgPCBob3Jpei5sZW5ndGgtMSAmJiBob3JpeltoYnVja2V0KzFdLnkgPT09IHBbMV0pIHtcbiAgICAgICAgICAgICAgaGJ1Y2tldCA9IGhidWNrZXQrMVxuICAgICAgICAgICAgICBlID0gaG9yaXpbaGJ1Y2tldF1cbiAgICAgICAgICAgICAgaWYoZS5jbG9zZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZS5pbmRleFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihlLnkgPT09IHBbMV0gJiYgIWUuc3RhcnQpIHtcbiAgICAgICAgICAgICAgaGJ1Y2tldCA9IGhidWNrZXQrMVxuICAgICAgICAgICAgICBpZihoYnVja2V0ID49IGhvcml6Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYXN0SGl0XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZSA9IGhvcml6W2hidWNrZXRdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vQ2hlY2sgaWYgZSBpcyBhYm92ZS9iZWxvdyBsYXN0IHNlZ21lbnRcbiAgICAgICAgaWYoZS5zdGFydCkge1xuICAgICAgICAgIGlmKGxhc3RTZWdtZW50KSB7XG4gICAgICAgICAgICB2YXIgbyA9IG9yaWVudChsYXN0U2VnbWVudFswXSwgbGFzdFNlZ21lbnRbMV0sIFtwWzBdLCBlLnldKVxuICAgICAgICAgICAgaWYobGFzdFNlZ21lbnRbMF1bMF0gPiBsYXN0U2VnbWVudFsxXVswXSkge1xuICAgICAgICAgICAgICBvID0gLW9cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKG8gPiAwKSB7XG4gICAgICAgICAgICAgIGxhc3RIaXQgPSBlLmluZGV4XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxhc3RIaXQgPSBlLmluZGV4XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoZS55ICE9PSBwWzFdKSB7XG4gICAgICAgICAgbGFzdEhpdCA9IGUuaW5kZXhcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbGFzdEhpdFxufVxuXG5mdW5jdGlvbiBJbnRlcnZhbFNlZ21lbnQoeSwgaW5kZXgsIHN0YXJ0LCBjbG9zZWQpIHtcbiAgdGhpcy55ID0geVxuICB0aGlzLmluZGV4ID0gaW5kZXhcbiAgdGhpcy5zdGFydCA9IHN0YXJ0XG4gIHRoaXMuY2xvc2VkID0gY2xvc2VkXG59XG5cbmZ1bmN0aW9uIEV2ZW50KHgsIHNlZ21lbnQsIGNyZWF0ZSwgaW5kZXgpIHtcbiAgdGhpcy54ID0geFxuICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50XG4gIHRoaXMuY3JlYXRlID0gY3JlYXRlXG4gIHRoaXMuaW5kZXggPSBpbmRleFxufVxuXG5cbmZ1bmN0aW9uIGNyZWF0ZVNsYWJEZWNvbXBvc2l0aW9uKHNlZ21lbnRzKSB7XG4gIHZhciBudW1TZWdtZW50cyA9IHNlZ21lbnRzLmxlbmd0aFxuICB2YXIgbnVtRXZlbnRzID0gMiAqIG51bVNlZ21lbnRzXG4gIHZhciBldmVudHMgPSBuZXcgQXJyYXkobnVtRXZlbnRzKVxuICBmb3IodmFyIGk9MDsgaTxudW1TZWdtZW50czsgKytpKSB7XG4gICAgdmFyIHMgPSBzZWdtZW50c1tpXVxuICAgIHZhciBmID0gc1swXVswXSA8IHNbMV1bMF1cbiAgICBldmVudHNbMippXSA9IG5ldyBFdmVudChzWzBdWzBdLCBzLCBmLCBpKVxuICAgIGV2ZW50c1syKmkrMV0gPSBuZXcgRXZlbnQoc1sxXVswXSwgcywgIWYsIGkpXG4gIH1cbiAgZXZlbnRzLnNvcnQoZnVuY3Rpb24oYSxiKSB7XG4gICAgdmFyIGQgPSBhLnggLSBiLnhcbiAgICBpZihkKSB7XG4gICAgICByZXR1cm4gZFxuICAgIH1cbiAgICBkID0gYS5jcmVhdGUgLSBiLmNyZWF0ZVxuICAgIGlmKGQpIHtcbiAgICAgIHJldHVybiBkXG4gICAgfVxuICAgIHJldHVybiBNYXRoLm1pbihhLnNlZ21lbnRbMF1bMV0sIGEuc2VnbWVudFsxXVsxXSkgLSBNYXRoLm1pbihiLnNlZ21lbnRbMF1bMV0sIGIuc2VnbWVudFsxXVsxXSlcbiAgfSlcbiAgdmFyIHRyZWUgPSBjcmVhdGVSQlRyZWUob3JkZXJTZWdtZW50cylcbiAgdmFyIHNsYWJzID0gW11cbiAgdmFyIGxpbmVzID0gW11cbiAgdmFyIGhvcml6b250YWwgPSBbXVxuICB2YXIgbGFzdFggPSAtSW5maW5pdHlcbiAgZm9yKHZhciBpPTA7IGk8bnVtRXZlbnRzOyApIHtcbiAgICB2YXIgeCA9IGV2ZW50c1tpXS54XG4gICAgdmFyIGhvcml6ID0gW11cbiAgICB3aGlsZShpIDwgbnVtRXZlbnRzKSB7XG4gICAgICB2YXIgZSA9IGV2ZW50c1tpXVxuICAgICAgaWYoZS54ICE9PSB4KSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBpICs9IDFcbiAgICAgIGlmKGUuc2VnbWVudFswXVswXSA9PT0gZS54ICYmIGUuc2VnbWVudFsxXVswXSA9PT0gZS54KSB7XG4gICAgICAgIGlmKGUuY3JlYXRlKSB7XG4gICAgICAgICAgaWYoZS5zZWdtZW50WzBdWzFdIDwgZS5zZWdtZW50WzFdWzFdKSB7XG4gICAgICAgICAgICBob3Jpei5wdXNoKG5ldyBJbnRlcnZhbFNlZ21lbnQoXG4gICAgICAgICAgICAgICAgZS5zZWdtZW50WzBdWzFdLFxuICAgICAgICAgICAgICAgIGUuaW5kZXgsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB0cnVlKSlcbiAgICAgICAgICAgIGhvcml6LnB1c2gobmV3IEludGVydmFsU2VnbWVudChcbiAgICAgICAgICAgICAgICBlLnNlZ21lbnRbMV1bMV0sXG4gICAgICAgICAgICAgICAgZS5pbmRleCxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICBmYWxzZSkpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhvcml6LnB1c2gobmV3IEludGVydmFsU2VnbWVudChcbiAgICAgICAgICAgICAgICBlLnNlZ21lbnRbMV1bMV0sXG4gICAgICAgICAgICAgICAgZS5pbmRleCxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIGZhbHNlKSlcbiAgICAgICAgICAgIGhvcml6LnB1c2gobmV3IEludGVydmFsU2VnbWVudChcbiAgICAgICAgICAgICAgICBlLnNlZ21lbnRbMF1bMV0sXG4gICAgICAgICAgICAgICAgZS5pbmRleCxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICB0cnVlKSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKGUuY3JlYXRlKSB7XG4gICAgICAgICAgdHJlZSA9IHRyZWUuaW5zZXJ0KGUuc2VnbWVudCwgZS5pbmRleClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0cmVlID0gdHJlZS5yZW1vdmUoZS5zZWdtZW50KVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHNsYWJzLnB1c2godHJlZS5yb290KVxuICAgIGxpbmVzLnB1c2goeClcbiAgICBob3Jpem9udGFsLnB1c2goaG9yaXopXG4gIH1cbiAgcmV0dXJuIG5ldyBTbGFiRGVjb21wb3NpdGlvbihzbGFicywgbGluZXMsIGhvcml6b250YWwpXG59IiwiXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHJvYnVzdERvdCA9IHJlcXVpcmUoXCJyb2J1c3QtZG90LXByb2R1Y3RcIilcbnZhciByb2J1c3RTdW0gPSByZXF1aXJlKFwicm9idXN0LXN1bVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNwbGl0UG9seWdvblxubW9kdWxlLmV4cG9ydHMucG9zaXRpdmUgPSBwb3NpdGl2ZVxubW9kdWxlLmV4cG9ydHMubmVnYXRpdmUgPSBuZWdhdGl2ZVxuXG5mdW5jdGlvbiBwbGFuZVQocCwgcGxhbmUpIHtcbiAgdmFyIHIgPSByb2J1c3RTdW0ocm9idXN0RG90KHAsIHBsYW5lKSwgW3BsYW5lW3BsYW5lLmxlbmd0aC0xXV0pXG4gIHJldHVybiByW3IubGVuZ3RoLTFdXG59XG5cblxuLy9DYW4ndCBkbyB0aGlzIGV4YWN0bHkgYW5kIGVtaXQgYSBmbG9hdGluZyBwb2ludCByZXN1bHRcbmZ1bmN0aW9uIGxlcnBXKGEsIHdhLCBiLCB3Yikge1xuICB2YXIgZCA9IHdiIC0gd2FcbiAgdmFyIHQgPSAtd2EgLyBkXG4gIGlmKHQgPCAwLjApIHtcbiAgICB0ID0gMC4wXG4gIH0gZWxzZSBpZih0ID4gMS4wKSB7XG4gICAgdCA9IDEuMFxuICB9XG4gIHZhciB0aSA9IDEuMCAtIHRcbiAgdmFyIG4gPSBhLmxlbmd0aFxuICB2YXIgciA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByW2ldID0gdCAqIGFbaV0gKyB0aSAqIGJbaV1cbiAgfVxuICByZXR1cm4gclxufVxuXG5mdW5jdGlvbiBzcGxpdFBvbHlnb24ocG9pbnRzLCBwbGFuZSkge1xuICB2YXIgcG9zID0gW11cbiAgdmFyIG5lZyA9IFtdXG4gIHZhciBhID0gcGxhbmVUKHBvaW50c1twb2ludHMubGVuZ3RoLTFdLCBwbGFuZSlcbiAgZm9yKHZhciBzPXBvaW50c1twb2ludHMubGVuZ3RoLTFdLCB0PXBvaW50c1swXSwgaT0wOyBpPHBvaW50cy5sZW5ndGg7ICsraSwgcz10KSB7XG4gICAgdCA9IHBvaW50c1tpXVxuICAgIHZhciBiID0gcGxhbmVUKHQsIHBsYW5lKVxuICAgIGlmKChhIDwgMCAmJiBiID4gMCkgfHwgKGEgPiAwICYmIGIgPCAwKSkge1xuICAgICAgdmFyIHAgPSBsZXJwVyhzLCBiLCB0LCBhKVxuICAgICAgcG9zLnB1c2gocClcbiAgICAgIG5lZy5wdXNoKHAuc2xpY2UoKSlcbiAgICB9XG4gICAgaWYoYiA8IDApIHtcbiAgICAgIG5lZy5wdXNoKHQuc2xpY2UoKSlcbiAgICB9IGVsc2UgaWYoYiA+IDApIHtcbiAgICAgIHBvcy5wdXNoKHQuc2xpY2UoKSlcbiAgICB9IGVsc2Uge1xuICAgICAgcG9zLnB1c2godC5zbGljZSgpKVxuICAgICAgbmVnLnB1c2godC5zbGljZSgpKVxuICAgIH1cbiAgICBhID0gYlxuICB9XG4gIHJldHVybiB7IHBvc2l0aXZlOiBwb3MsIG5lZ2F0aXZlOiBuZWcgfVxufVxuXG5mdW5jdGlvbiBwb3NpdGl2ZShwb2ludHMsIHBsYW5lKSB7XG4gIHZhciBwb3MgPSBbXVxuICB2YXIgYSA9IHBsYW5lVChwb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgcGxhbmUpXG4gIGZvcih2YXIgcz1wb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgdD1wb2ludHNbMF0sIGk9MDsgaTxwb2ludHMubGVuZ3RoOyArK2ksIHM9dCkge1xuICAgIHQgPSBwb2ludHNbaV1cbiAgICB2YXIgYiA9IHBsYW5lVCh0LCBwbGFuZSlcbiAgICBpZigoYSA8IDAgJiYgYiA+IDApIHx8IChhID4gMCAmJiBiIDwgMCkpIHtcbiAgICAgIHBvcy5wdXNoKGxlcnBXKHMsIGIsIHQsIGEpKVxuICAgIH1cbiAgICBpZihiID49IDApIHtcbiAgICAgIHBvcy5wdXNoKHQuc2xpY2UoKSlcbiAgICB9XG4gICAgYSA9IGJcbiAgfVxuICByZXR1cm4gcG9zXG59XG5cbmZ1bmN0aW9uIG5lZ2F0aXZlKHBvaW50cywgcGxhbmUpIHtcbiAgdmFyIG5lZyA9IFtdXG4gIHZhciBhID0gcGxhbmVUKHBvaW50c1twb2ludHMubGVuZ3RoLTFdLCBwbGFuZSlcbiAgZm9yKHZhciBzPXBvaW50c1twb2ludHMubGVuZ3RoLTFdLCB0PXBvaW50c1swXSwgaT0wOyBpPHBvaW50cy5sZW5ndGg7ICsraSwgcz10KSB7XG4gICAgdCA9IHBvaW50c1tpXVxuICAgIHZhciBiID0gcGxhbmVUKHQsIHBsYW5lKVxuICAgIGlmKChhIDwgMCAmJiBiID4gMCkgfHwgKGEgPiAwICYmIGIgPCAwKSkge1xuICAgICAgbmVnLnB1c2gobGVycFcocywgYiwgdCwgYSkpXG4gICAgfVxuICAgIGlmKGIgPD0gMCkge1xuICAgICAgbmVnLnB1c2godC5zbGljZSgpKVxuICAgIH1cbiAgICBhID0gYlxuICB9XG4gIHJldHVybiBuZWdcbn0iLCIvKiBnbG9iYWwgd2luZG93LCBleHBvcnRzLCBkZWZpbmUgKi9cblxuIWZ1bmN0aW9uKCkge1xuICAgICd1c2Ugc3RyaWN0J1xuXG4gICAgdmFyIHJlID0ge1xuICAgICAgICBub3Rfc3RyaW5nOiAvW15zXS8sXG4gICAgICAgIG5vdF9ib29sOiAvW150XS8sXG4gICAgICAgIG5vdF90eXBlOiAvW15UXS8sXG4gICAgICAgIG5vdF9wcmltaXRpdmU6IC9bXnZdLyxcbiAgICAgICAgbnVtYmVyOiAvW2RpZWZnXS8sXG4gICAgICAgIG51bWVyaWNfYXJnOiAvW2JjZGllZmd1eFhdLyxcbiAgICAgICAganNvbjogL1tqXS8sXG4gICAgICAgIG5vdF9qc29uOiAvW15qXS8sXG4gICAgICAgIHRleHQ6IC9eW15cXHgyNV0rLyxcbiAgICAgICAgbW9kdWxvOiAvXlxceDI1ezJ9LyxcbiAgICAgICAgcGxhY2Vob2xkZXI6IC9eXFx4MjUoPzooWzEtOV1cXGQqKVxcJHxcXCgoW15cXCldKylcXCkpPyhcXCspPygwfCdbXiRdKT8oLSk/KFxcZCspPyg/OlxcLihcXGQrKSk/KFtiLWdpam9zdFR1dnhYXSkvLFxuICAgICAgICBrZXk6IC9eKFthLXpfXVthLXpfXFxkXSopL2ksXG4gICAgICAgIGtleV9hY2Nlc3M6IC9eXFwuKFthLXpfXVthLXpfXFxkXSopL2ksXG4gICAgICAgIGluZGV4X2FjY2VzczogL15cXFsoXFxkKylcXF0vLFxuICAgICAgICBzaWduOiAvXltcXCtcXC1dL1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNwcmludGYoa2V5KSB7XG4gICAgICAgIC8vIGBhcmd1bWVudHNgIGlzIG5vdCBhbiBhcnJheSwgYnV0IHNob3VsZCBiZSBmaW5lIGZvciB0aGlzIGNhbGxcbiAgICAgICAgcmV0dXJuIHNwcmludGZfZm9ybWF0KHNwcmludGZfcGFyc2Uoa2V5KSwgYXJndW1lbnRzKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZzcHJpbnRmKGZtdCwgYXJndikge1xuICAgICAgICByZXR1cm4gc3ByaW50Zi5hcHBseShudWxsLCBbZm10XS5jb25jYXQoYXJndiB8fCBbXSkpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3ByaW50Zl9mb3JtYXQocGFyc2VfdHJlZSwgYXJndikge1xuICAgICAgICB2YXIgY3Vyc29yID0gMSwgdHJlZV9sZW5ndGggPSBwYXJzZV90cmVlLmxlbmd0aCwgYXJnLCBvdXRwdXQgPSAnJywgaSwgaywgbWF0Y2gsIHBhZCwgcGFkX2NoYXJhY3RlciwgcGFkX2xlbmd0aCwgaXNfcG9zaXRpdmUsIHNpZ25cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRyZWVfbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyc2VfdHJlZVtpXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgKz0gcGFyc2VfdHJlZVtpXVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwYXJzZV90cmVlW2ldKSkge1xuICAgICAgICAgICAgICAgIG1hdGNoID0gcGFyc2VfdHJlZVtpXSAvLyBjb252ZW5pZW5jZSBwdXJwb3NlcyBvbmx5XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoWzJdKSB7IC8vIGtleXdvcmQgYXJndW1lbnRcbiAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndltjdXJzb3JdXG4gICAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBtYXRjaFsyXS5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhcmcuaGFzT3duUHJvcGVydHkobWF0Y2hbMl1ba10pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHNwcmludGYoJ1tzcHJpbnRmXSBwcm9wZXJ0eSBcIiVzXCIgZG9lcyBub3QgZXhpc3QnLCBtYXRjaFsyXVtrXSkpXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmdbbWF0Y2hbMl1ba11dXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAobWF0Y2hbMV0pIHsgLy8gcG9zaXRpb25hbCBhcmd1bWVudCAoZXhwbGljaXQpXG4gICAgICAgICAgICAgICAgICAgIGFyZyA9IGFyZ3ZbbWF0Y2hbMV1dXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBwb3NpdGlvbmFsIGFyZ3VtZW50IChpbXBsaWNpdClcbiAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndltjdXJzb3IrK11cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocmUubm90X3R5cGUudGVzdChtYXRjaFs4XSkgJiYgcmUubm90X3ByaW1pdGl2ZS50ZXN0KG1hdGNoWzhdKSAmJiBhcmcgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcoKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChyZS5udW1lcmljX2FyZy50ZXN0KG1hdGNoWzhdKSAmJiAodHlwZW9mIGFyZyAhPT0gJ251bWJlcicgJiYgaXNOYU4oYXJnKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzcHJpbnRmKCdbc3ByaW50Zl0gZXhwZWN0aW5nIG51bWJlciBidXQgZm91bmQgJVQnLCBhcmcpKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChyZS5udW1iZXIudGVzdChtYXRjaFs4XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNfcG9zaXRpdmUgPSBhcmcgPj0gMFxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHN3aXRjaCAobWF0Y2hbOF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYic6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBwYXJzZUludChhcmcsIDEwKS50b1N0cmluZygyKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhcnNlSW50KGFyZywgMTApKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2knOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gcGFyc2VJbnQoYXJnLCAxMClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2onOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gSlNPTi5zdHJpbmdpZnkoYXJnLCBudWxsLCBtYXRjaFs2XSA/IHBhcnNlSW50KG1hdGNoWzZdKSA6IDApXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IG1hdGNoWzddID8gcGFyc2VGbG9hdChhcmcpLnRvRXhwb25lbnRpYWwobWF0Y2hbN10pIDogcGFyc2VGbG9hdChhcmcpLnRvRXhwb25lbnRpYWwoKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZic6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBtYXRjaFs3XSA/IHBhcnNlRmxvYXQoYXJnKS50b0ZpeGVkKG1hdGNoWzddKSA6IHBhcnNlRmxvYXQoYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBtYXRjaFs3XSA/IFN0cmluZyhOdW1iZXIoYXJnLnRvUHJlY2lzaW9uKG1hdGNoWzddKSkpIDogcGFyc2VGbG9hdChhcmcpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdvJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChwYXJzZUludChhcmcsIDEwKSA+Pj4gMCkudG9TdHJpbmcoOClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gU3RyaW5nKGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChtYXRjaFs3XSA/IGFyZy5zdWJzdHJpbmcoMCwgbWF0Y2hbN10pIDogYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBTdHJpbmcoISFhcmcpXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSAobWF0Y2hbN10gPyBhcmcuc3Vic3RyaW5nKDAsIG1hdGNoWzddKSA6IGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ1QnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFyZykuc2xpY2UoOCwgLTEpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChtYXRjaFs3XSA/IGFyZy5zdWJzdHJpbmcoMCwgbWF0Y2hbN10pIDogYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBwYXJzZUludChhcmcsIDEwKSA+Pj4gMFxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndic6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcudmFsdWVPZigpXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSAobWF0Y2hbN10gPyBhcmcuc3Vic3RyaW5nKDAsIG1hdGNoWzddKSA6IGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3gnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gKHBhcnNlSW50KGFyZywgMTApID4+PiAwKS50b1N0cmluZygxNilcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ1gnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gKHBhcnNlSW50KGFyZywgMTApID4+PiAwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlLmpzb24udGVzdChtYXRjaFs4XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IGFyZ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlLm51bWJlci50ZXN0KG1hdGNoWzhdKSAmJiAoIWlzX3Bvc2l0aXZlIHx8IG1hdGNoWzNdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lnbiA9IGlzX3Bvc2l0aXZlID8gJysnIDogJy0nXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcudG9TdHJpbmcoKS5yZXBsYWNlKHJlLnNpZ24sICcnKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lnbiA9ICcnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcGFkX2NoYXJhY3RlciA9IG1hdGNoWzRdID8gbWF0Y2hbNF0gPT09ICcwJyA/ICcwJyA6IG1hdGNoWzRdLmNoYXJBdCgxKSA6ICcgJ1xuICAgICAgICAgICAgICAgICAgICBwYWRfbGVuZ3RoID0gbWF0Y2hbNl0gLSAoc2lnbiArIGFyZykubGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgIHBhZCA9IG1hdGNoWzZdID8gKHBhZF9sZW5ndGggPiAwID8gcGFkX2NoYXJhY3Rlci5yZXBlYXQocGFkX2xlbmd0aCkgOiAnJykgOiAnJ1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gbWF0Y2hbNV0gPyBzaWduICsgYXJnICsgcGFkIDogKHBhZF9jaGFyYWN0ZXIgPT09ICcwJyA/IHNpZ24gKyBwYWQgKyBhcmcgOiBwYWQgKyBzaWduICsgYXJnKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0cHV0XG4gICAgfVxuXG4gICAgdmFyIHNwcmludGZfY2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpXG5cbiAgICBmdW5jdGlvbiBzcHJpbnRmX3BhcnNlKGZtdCkge1xuICAgICAgICBpZiAoc3ByaW50Zl9jYWNoZVtmbXRdKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ByaW50Zl9jYWNoZVtmbXRdXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgX2ZtdCA9IGZtdCwgbWF0Y2gsIHBhcnNlX3RyZWUgPSBbXSwgYXJnX25hbWVzID0gMFxuICAgICAgICB3aGlsZSAoX2ZtdCkge1xuICAgICAgICAgICAgaWYgKChtYXRjaCA9IHJlLnRleHQuZXhlYyhfZm10KSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBwYXJzZV90cmVlLnB1c2gobWF0Y2hbMF0pXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICgobWF0Y2ggPSByZS5tb2R1bG8uZXhlYyhfZm10KSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBwYXJzZV90cmVlLnB1c2goJyUnKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoKG1hdGNoID0gcmUucGxhY2Vob2xkZXIuZXhlYyhfZm10KSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hbMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnX25hbWVzIHw9IDFcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpZWxkX2xpc3QgPSBbXSwgcmVwbGFjZW1lbnRfZmllbGQgPSBtYXRjaFsyXSwgZmllbGRfbWF0Y2ggPSBbXVxuICAgICAgICAgICAgICAgICAgICBpZiAoKGZpZWxkX21hdGNoID0gcmUua2V5LmV4ZWMocmVwbGFjZW1lbnRfZmllbGQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmllbGRfbGlzdC5wdXNoKGZpZWxkX21hdGNoWzFdKVxuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKChyZXBsYWNlbWVudF9maWVsZCA9IHJlcGxhY2VtZW50X2ZpZWxkLnN1YnN0cmluZyhmaWVsZF9tYXRjaFswXS5sZW5ndGgpKSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGZpZWxkX21hdGNoID0gcmUua2V5X2FjY2Vzcy5leGVjKHJlcGxhY2VtZW50X2ZpZWxkKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmllbGRfbGlzdC5wdXNoKGZpZWxkX21hdGNoWzFdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgoZmllbGRfbWF0Y2ggPSByZS5pbmRleF9hY2Nlc3MuZXhlYyhyZXBsYWNlbWVudF9maWVsZCkpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkX2xpc3QucHVzaChmaWVsZF9tYXRjaFsxXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignW3NwcmludGZdIGZhaWxlZCB0byBwYXJzZSBuYW1lZCBhcmd1bWVudCBrZXknKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignW3NwcmludGZdIGZhaWxlZCB0byBwYXJzZSBuYW1lZCBhcmd1bWVudCBrZXknKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoWzJdID0gZmllbGRfbGlzdFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnX25hbWVzIHw9IDJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGFyZ19uYW1lcyA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tzcHJpbnRmXSBtaXhpbmcgcG9zaXRpb25hbCBhbmQgbmFtZWQgcGxhY2Vob2xkZXJzIGlzIG5vdCAoeWV0KSBzdXBwb3J0ZWQnKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJzZV90cmVlLnB1c2gobWF0Y2gpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1tzcHJpbnRmXSB1bmV4cGVjdGVkIHBsYWNlaG9sZGVyJylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF9mbXQgPSBfZm10LnN1YnN0cmluZyhtYXRjaFswXS5sZW5ndGgpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNwcmludGZfY2FjaGVbZm10XSA9IHBhcnNlX3RyZWVcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBleHBvcnQgdG8gZWl0aGVyIGJyb3dzZXIgb3Igbm9kZS5qc1xuICAgICAqL1xuICAgIC8qIGVzbGludC1kaXNhYmxlIHF1b3RlLXByb3BzICovXG4gICAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBleHBvcnRzWydzcHJpbnRmJ10gPSBzcHJpbnRmXG4gICAgICAgIGV4cG9ydHNbJ3ZzcHJpbnRmJ10gPSB2c3ByaW50ZlxuICAgIH1cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgd2luZG93WydzcHJpbnRmJ10gPSBzcHJpbnRmXG4gICAgICAgIHdpbmRvd1sndnNwcmludGYnXSA9IHZzcHJpbnRmXG5cbiAgICAgICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lWydhbWQnXSkge1xuICAgICAgICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICdzcHJpbnRmJzogc3ByaW50ZixcbiAgICAgICAgICAgICAgICAgICAgJ3ZzcHJpbnRmJzogdnNwcmludGZcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qIGVzbGludC1lbmFibGUgcXVvdGUtcHJvcHMgKi9cbn0oKVxuIiwiJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgcGFyZW4gPSByZXF1aXJlKCdwYXJlbnRoZXNpcycpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0QnkgKHN0cmluZywgc2VwYXJhdG9yLCBvKSB7XHJcblx0aWYgKHN0cmluZyA9PSBudWxsKSB0aHJvdyBFcnJvcignRmlyc3QgYXJndW1lbnQgc2hvdWxkIGJlIGEgc3RyaW5nJylcclxuXHRpZiAoc2VwYXJhdG9yID09IG51bGwpIHRocm93IEVycm9yKCdTZXBhcmF0b3Igc2hvdWxkIGJlIGEgc3RyaW5nIG9yIGEgUmVnRXhwJylcclxuXHJcblx0aWYgKCFvKSBvID0ge31cclxuXHRlbHNlIGlmICh0eXBlb2YgbyA9PT0gJ3N0cmluZycgfHwgQXJyYXkuaXNBcnJheShvKSkge1xyXG5cdFx0byA9IHtpZ25vcmU6IG99XHJcblx0fVxyXG5cclxuXHRpZiAoby5lc2NhcGUgPT0gbnVsbCkgby5lc2NhcGUgPSB0cnVlXHJcblx0aWYgKG8uaWdub3JlID09IG51bGwpIG8uaWdub3JlID0gWydbXScsICcoKScsICd7fScsICc8PicsICdcIlwiJywgXCInJ1wiLCAnYGAnLCAn4oCc4oCdJywgJ8KrwrsnXVxyXG5cdGVsc2Uge1xyXG5cdFx0aWYgKHR5cGVvZiBvLmlnbm9yZSA9PT0gJ3N0cmluZycpIHtvLmlnbm9yZSA9IFtvLmlnbm9yZV19XHJcblxyXG5cdFx0by5pZ25vcmUgPSBvLmlnbm9yZS5tYXAoZnVuY3Rpb24gKHBhaXIpIHtcclxuXHRcdFx0Ly8gJ1wiJyDihpIgJ1wiXCInXHJcblx0XHRcdGlmIChwYWlyLmxlbmd0aCA9PT0gMSkgcGFpciA9IHBhaXIgKyBwYWlyXHJcblx0XHRcdHJldHVybiBwYWlyXHJcblx0XHR9KVxyXG5cdH1cclxuXHJcblx0dmFyIHRva2VucyA9IHBhcmVuLnBhcnNlKHN0cmluZywge2ZsYXQ6IHRydWUsIGJyYWNrZXRzOiBvLmlnbm9yZX0pXHJcblx0dmFyIHN0ciA9IHRva2Vuc1swXVxyXG5cclxuXHR2YXIgcGFydHMgPSBzdHIuc3BsaXQoc2VwYXJhdG9yKVxyXG5cclxuXHQvLyBqb2luIHBhcnRzIHNlcGFyYXRlZCBieSBlc2NhcGVcclxuXHRpZiAoby5lc2NhcGUpIHtcclxuXHRcdHZhciBjbGVhblBhcnRzID0gW11cclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dmFyIHByZXYgPSBwYXJ0c1tpXVxyXG5cdFx0XHR2YXIgcGFydCA9IHBhcnRzW2kgKyAxXVxyXG5cclxuXHRcdFx0aWYgKHByZXZbcHJldi5sZW5ndGggLSAxXSA9PT0gJ1xcXFwnICYmIHByZXZbcHJldi5sZW5ndGggLSAyXSAhPT0gJ1xcXFwnKSB7XHJcblx0XHRcdFx0Y2xlYW5QYXJ0cy5wdXNoKHByZXYgKyBzZXBhcmF0b3IgKyBwYXJ0KVxyXG5cdFx0XHRcdGkrK1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGNsZWFuUGFydHMucHVzaChwcmV2KVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRwYXJ0cyA9IGNsZWFuUGFydHNcclxuXHR9XHJcblxyXG5cdC8vIG9wZW4gcGFyZW5zIHBhY2sgJiBhcHBseSB1bnF1b3RlcywgaWYgYW55XHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xyXG5cdFx0dG9rZW5zWzBdID0gcGFydHNbaV1cclxuXHRcdHBhcnRzW2ldID0gcGFyZW4uc3RyaW5naWZ5KHRva2Vucywge2ZsYXQ6IHRydWV9KVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHBhcnRzXHJcbn1cclxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBzdHJvbmdseUNvbm5lY3RlZENvbXBvbmVudHNcblxuZnVuY3Rpb24gc3Ryb25nbHlDb25uZWN0ZWRDb21wb25lbnRzKGFkakxpc3QpIHtcbiAgdmFyIG51bVZlcnRpY2VzID0gYWRqTGlzdC5sZW5ndGg7XG4gIHZhciBpbmRleCA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgdmFyIGxvd1ZhbHVlID0gbmV3IEFycmF5KG51bVZlcnRpY2VzKVxuICB2YXIgYWN0aXZlID0gbmV3IEFycmF5KG51bVZlcnRpY2VzKVxuICB2YXIgY2hpbGQgPSBuZXcgQXJyYXkobnVtVmVydGljZXMpXG4gIHZhciBzY2MgPSBuZXcgQXJyYXkobnVtVmVydGljZXMpXG4gIHZhciBzY2NMaW5rcyA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgXG4gIC8vSW5pdGlhbGl6ZSB0YWJsZXNcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGluZGV4W2ldID0gLTFcbiAgICBsb3dWYWx1ZVtpXSA9IDBcbiAgICBhY3RpdmVbaV0gPSBmYWxzZVxuICAgIGNoaWxkW2ldID0gMFxuICAgIHNjY1tpXSA9IC0xXG4gICAgc2NjTGlua3NbaV0gPSBbXVxuICB9XG5cbiAgLy8gVGhlIHN0cm9uZ0Nvbm5lY3QgZnVuY3Rpb25cbiAgdmFyIGNvdW50ID0gMFxuICB2YXIgY29tcG9uZW50cyA9IFtdXG4gIHZhciBzY2NBZGpMaXN0ID0gW11cblxuICBmdW5jdGlvbiBzdHJvbmdDb25uZWN0KHYpIHtcbiAgICAvLyBUbyBhdm9pZCBydW5uaW5nIG91dCBvZiBzdGFjayBzcGFjZSwgdGhpcyBlbXVsYXRlcyB0aGUgcmVjdXJzaXZlIGJlaGF2aW91ciBvZiB0aGUgbm9ybWFsIGFsZ29yaXRobSwgZWZmZWN0aXZlbHkgdXNpbmcgVCBhcyB0aGUgY2FsbCBzdGFjay5cbiAgICB2YXIgUyA9IFt2XSwgVCA9IFt2XVxuICAgIGluZGV4W3ZdID0gbG93VmFsdWVbdl0gPSBjb3VudFxuICAgIGFjdGl2ZVt2XSA9IHRydWVcbiAgICBjb3VudCArPSAxXG4gICAgd2hpbGUoVC5sZW5ndGggPiAwKSB7XG4gICAgICB2ID0gVFtULmxlbmd0aC0xXVxuICAgICAgdmFyIGUgPSBhZGpMaXN0W3ZdXG4gICAgICBpZiAoY2hpbGRbdl0gPCBlLmxlbmd0aCkgeyAvLyBJZiB3ZSdyZSBub3QgZG9uZSBpdGVyYXRpbmcgb3ZlciB0aGUgY2hpbGRyZW4sIGZpcnN0IHRyeSBmaW5pc2hpbmcgdGhhdC5cbiAgICAgICAgZm9yKHZhciBpPWNoaWxkW3ZdOyBpPGUubGVuZ3RoOyArK2kpIHsgLy8gU3RhcnQgd2hlcmUgd2UgbGVmdCBvZmYuXG4gICAgICAgICAgdmFyIHUgPSBlW2ldXG4gICAgICAgICAgaWYoaW5kZXhbdV0gPCAwKSB7XG4gICAgICAgICAgICBpbmRleFt1XSA9IGxvd1ZhbHVlW3VdID0gY291bnRcbiAgICAgICAgICAgIGFjdGl2ZVt1XSA9IHRydWVcbiAgICAgICAgICAgIGNvdW50ICs9IDFcbiAgICAgICAgICAgIFMucHVzaCh1KVxuICAgICAgICAgICAgVC5wdXNoKHUpXG4gICAgICAgICAgICBicmVhayAvLyBGaXJzdCByZWN1cnNlLCB0aGVuIGNvbnRpbnVlIGhlcmUgKHdpdGggdGhlIHNhbWUgY2hpbGQhKS5cbiAgICAgICAgICAgIC8vIFRoZXJlIGlzIGEgc2xpZ2h0IGNoYW5nZSB0byBUYXJqYW4ncyBhbGdvcml0aG0gaGVyZS5cbiAgICAgICAgICAgIC8vIE5vcm1hbGx5LCBhZnRlciBoYXZpbmcgcmVjdXJzZWQsIHdlIHNldCBsb3dWYWx1ZSBsaWtlIHdlIGRvIGZvciBhbiBhY3RpdmUgY2hpbGQgKGFsdGhvdWdoIHNvbWUgdmFyaWFudHMgb2YgdGhlIGFsZ29yaXRobSBkbyBpdCBzbGlnaHRseSBkaWZmZXJlbnRseSkuXG4gICAgICAgICAgICAvLyBIZXJlLCB3ZSBvbmx5IGRvIHNvIGlmIHRoZSBjaGlsZCB3ZSByZWN1cnNlZCBvbiBpcyBzdGlsbCBhY3RpdmUuXG4gICAgICAgICAgICAvLyBUaGUgcmVhc29uaW5nIGlzIHRoYXQgaWYgaXQgaXMgbm8gbG9uZ2VyIGFjdGl2ZSwgaXQgbXVzdCBoYXZlIGhhZCBhIGxvd1ZhbHVlIGVxdWFsIHRvIGl0cyBvd24gaW5kZXgsIHdoaWNoIG1lYW5zIHRoYXQgaXQgaXMgbmVjZXNzYXJpbHkgaGlnaGVyIHRoYW4gb3VyIGxvd1ZhbHVlLlxuICAgICAgICAgIH0gZWxzZSBpZiAoYWN0aXZlW3VdKSB7XG4gICAgICAgICAgICBsb3dWYWx1ZVt2XSA9IE1hdGgubWluKGxvd1ZhbHVlW3ZdLCBsb3dWYWx1ZVt1XSl8MFxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2NjW3VdID49IDApIHtcbiAgICAgICAgICAgIC8vIE5vZGUgdiBpcyBub3QgeWV0IGFzc2lnbmVkIGFuIHNjYywgYnV0IG9uY2UgaXQgaXMgdGhhdCBzY2MgY2FuIGFwcGFyZW50bHkgcmVhY2ggc2NjW3VdLlxuICAgICAgICAgICAgc2NjTGlua3Nbdl0ucHVzaChzY2NbdV0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNoaWxkW3ZdID0gaSAvLyBSZW1lbWJlciB3aGVyZSB3ZSBsZWZ0IG9mZi5cbiAgICAgIH0gZWxzZSB7IC8vIElmIHdlJ3JlIGRvbmUgaXRlcmF0aW5nIG92ZXIgdGhlIGNoaWxkcmVuLCBjaGVjayB3aGV0aGVyIHdlIGhhdmUgYW4gc2NjLlxuICAgICAgICBpZihsb3dWYWx1ZVt2XSA9PT0gaW5kZXhbdl0pIHsgLy8gVE9ETzogSXQgL21pZ2h0LyBiZSB0cnVlIHRoYXQgVCBpcyBhbHdheXMgYSBwcmVmaXggb2YgUyAoYXQgdGhpcyBwb2ludCEhISksIGFuZCBpZiBzbywgdGhpcyBjb3VsZCBiZSB1c2VkIGhlcmUuXG4gICAgICAgICAgdmFyIGNvbXBvbmVudCA9IFtdXG4gICAgICAgICAgdmFyIGxpbmtzID0gW10sIGxpbmtDb3VudCA9IDBcbiAgICAgICAgICBmb3IodmFyIGk9Uy5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICAgICAgICB2YXIgdyA9IFNbaV1cbiAgICAgICAgICAgIGFjdGl2ZVt3XSA9IGZhbHNlXG4gICAgICAgICAgICBjb21wb25lbnQucHVzaCh3KVxuICAgICAgICAgICAgbGlua3MucHVzaChzY2NMaW5rc1t3XSlcbiAgICAgICAgICAgIGxpbmtDb3VudCArPSBzY2NMaW5rc1t3XS5sZW5ndGhcbiAgICAgICAgICAgIHNjY1t3XSA9IGNvbXBvbmVudHMubGVuZ3RoXG4gICAgICAgICAgICBpZih3ID09PSB2KSB7XG4gICAgICAgICAgICAgIFMubGVuZ3RoID0gaVxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb21wb25lbnRzLnB1c2goY29tcG9uZW50KVxuICAgICAgICAgIHZhciBhbGxMaW5rcyA9IG5ldyBBcnJheShsaW5rQ291bnQpXG4gICAgICAgICAgZm9yKHZhciBpPTA7IGk8bGlua3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvcih2YXIgaj0wOyBqPGxpbmtzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgIGFsbExpbmtzWy0tbGlua0NvdW50XSA9IGxpbmtzW2ldW2pdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHNjY0Fkakxpc3QucHVzaChhbGxMaW5rcylcbiAgICAgICAgfVxuICAgICAgICBULnBvcCgpIC8vIE5vdyB3ZSdyZSBmaW5pc2hlZCBleHBsb3JpbmcgdGhpcyBwYXJ0aWN1bGFyIG5vZGUgKG5vcm1hbGx5IGNvcnJlc3BvbmRzIHRvIHRoZSByZXR1cm4gc3RhdGVtZW50KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vUnVuIHN0cm9uZyBjb25uZWN0IHN0YXJ0aW5nIGZyb20gZWFjaCB2ZXJ0ZXhcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGlmKGluZGV4W2ldIDwgMCkge1xuICAgICAgc3Ryb25nQ29ubmVjdChpKVxuICAgIH1cbiAgfVxuICBcbiAgLy8gQ29tcGFjdCBzY2NBZGpMaXN0XG4gIHZhciBuZXdFXG4gIGZvcih2YXIgaT0wOyBpPHNjY0Fkakxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZSA9IHNjY0Fkakxpc3RbaV1cbiAgICBpZiAoZS5sZW5ndGggPT09IDApIGNvbnRpbnVlXG4gICAgZS5zb3J0KGZ1bmN0aW9uIChhLGIpIHsgcmV0dXJuIGEtYjsgfSlcbiAgICBuZXdFID0gW2VbMF1dXG4gICAgZm9yKHZhciBqPTE7IGo8ZS5sZW5ndGg7IGorKykge1xuICAgICAgaWYgKGVbal0gIT09IGVbai0xXSkge1xuICAgICAgICBuZXdFLnB1c2goZVtqXSlcbiAgICAgIH1cbiAgICB9XG4gICAgc2NjQWRqTGlzdFtpXSA9IG5ld0VcbiAgfSAgXG5cbiAgcmV0dXJuIHtjb21wb25lbnRzOiBjb21wb25lbnRzLCBhZGphY2VuY3lMaXN0OiBzY2NBZGpMaXN0fVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gdG9TdXBlclNjcmlwdFxuXG52YXIgU1VQRVJTQ1JJUFRTID0ge1xuICAnICc6ICcgJyxcbiAgJzAnOiAn4oGwJyxcbiAgJzEnOiAnwrknLFxuICAnMic6ICfCsicsXG4gICczJzogJ8KzJyxcbiAgJzQnOiAn4oG0JyxcbiAgJzUnOiAn4oG1JyxcbiAgJzYnOiAn4oG2JyxcbiAgJzcnOiAn4oG3JyxcbiAgJzgnOiAn4oG4JyxcbiAgJzknOiAn4oG5JyxcbiAgJysnOiAn4oG6JyxcbiAgJy0nOiAn4oG7JyxcbiAgJ2EnOiAn4bWDJyxcbiAgJ2InOiAn4bWHJyxcbiAgJ2MnOiAn4bacJyxcbiAgJ2QnOiAn4bWIJyxcbiAgJ2UnOiAn4bWJJyxcbiAgJ2YnOiAn4bagJyxcbiAgJ2cnOiAn4bWNJyxcbiAgJ2gnOiAnyrAnLFxuICAnaSc6ICfigbEnLFxuICAnaic6ICfKsicsXG4gICdrJzogJ+G1jycsXG4gICdsJzogJ8uhJyxcbiAgJ20nOiAn4bWQJyxcbiAgJ24nOiAn4oG/JyxcbiAgJ28nOiAn4bWSJyxcbiAgJ3AnOiAn4bWWJyxcbiAgJ3InOiAnyrMnLFxuICAncyc6ICfLoicsXG4gICd0JzogJ+G1lycsXG4gICd1JzogJ+G1mCcsXG4gICd2JzogJ+G1mycsXG4gICd3JzogJ8q3JyxcbiAgJ3gnOiAny6MnLFxuICAneSc6ICfKuCcsXG4gICd6JzogJ+G2uydcbn1cblxuZnVuY3Rpb24gdG9TdXBlclNjcmlwdCh4KSB7XG4gIHJldHVybiB4LnNwbGl0KCcnKS5tYXAoZnVuY3Rpb24oYykge1xuICAgIGlmKGMgaW4gU1VQRVJTQ1JJUFRTKSB7XG4gICAgICByZXR1cm4gU1VQRVJTQ1JJUFRTW2NdXG4gICAgfVxuICAgIHJldHVybiAnJ1xuICB9KS5qb2luKCcnKVxufVxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBzdXJmYWNlTmV0c1xuXG52YXIgZ2VuZXJhdGVDb250b3VyRXh0cmFjdG9yID0gcmVxdWlyZShcIm5kYXJyYXktZXh0cmFjdC1jb250b3VyXCIpXG52YXIgdHJpYW5ndWxhdGVDdWJlID0gcmVxdWlyZShcInRyaWFuZ3VsYXRlLWh5cGVyY3ViZVwiKVxudmFyIHplcm9Dcm9zc2luZ3MgPSByZXF1aXJlKFwiemVyby1jcm9zc2luZ3NcIilcblxuZnVuY3Rpb24gYnVpbGRTdXJmYWNlTmV0cyhvcmRlciwgZHR5cGUpIHtcbiAgdmFyIGRpbWVuc2lvbiA9IG9yZGVyLmxlbmd0aFxuICB2YXIgY29kZSA9IFtcIid1c2Ugc3RyaWN0JztcIl1cbiAgdmFyIGZ1bmNOYW1lID0gXCJzdXJmYWNlTmV0c1wiICsgb3JkZXIuam9pbihcIl9cIikgKyBcImRcIiArIGR0eXBlXG5cbiAgLy9Db250b3VyIGV4dHJhY3Rpb24gZnVuY3Rpb25cbiAgY29kZS5wdXNoKFxuICAgIFwidmFyIGNvbnRvdXI9Z2VuQ29udG91cih7XCIsXG4gICAgICBcIm9yZGVyOltcIiwgb3JkZXIuam9pbigpLCBcIl0sXCIsXG4gICAgICBcInNjYWxhckFyZ3VtZW50czogMyxcIixcbiAgICAgIFwicGhhc2U6ZnVuY3Rpb24gcGhhc2VGdW5jKHAsYSxiLGMpIHsgcmV0dXJuIChwID4gYyl8MCB9LFwiKVxuICBpZihkdHlwZSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICBjb2RlLnB1c2goXCJnZXR0ZXJzOlswXSxcIilcbiAgfVxuXG4gIC8vR2VuZXJhdGUgdmVydGV4IGZ1bmN0aW9uXG4gIHZhciBjdWJlQXJncyA9IFtdXG4gIHZhciBleHRyYUFyZ3MgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGN1YmVBcmdzLnB1c2goXCJkXCIgKyBpKVxuICAgIGV4dHJhQXJncy5wdXNoKFwiZFwiICsgaSlcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwoMTw8ZGltZW5zaW9uKTsgKytpKSB7XG4gICAgY3ViZUFyZ3MucHVzaChcInZcIiArIGkpXG4gICAgZXh0cmFBcmdzLnB1c2goXCJ2XCIgKyBpKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPCgxPDxkaW1lbnNpb24pOyArK2kpIHtcbiAgICBjdWJlQXJncy5wdXNoKFwicFwiICsgaSlcbiAgICBleHRyYUFyZ3MucHVzaChcInBcIiArIGkpXG4gIH1cbiAgY3ViZUFyZ3MucHVzaChcImFcIiwgXCJiXCIsIFwiY1wiKVxuICBleHRyYUFyZ3MucHVzaChcImFcIiwgXCJjXCIpXG4gIGNvZGUucHVzaChcInZlcnRleDpmdW5jdGlvbiB2ZXJ0ZXhGdW5jKFwiLCBjdWJlQXJncy5qb2luKCksIFwiKXtcIilcbiAgLy9NYXNrIGFyZ3MgdG9nZXRoZXJcbiAgdmFyIG1hc2tTdHIgPSBbXVxuICBmb3IodmFyIGk9MDsgaTwoMTw8ZGltZW5zaW9uKTsgKytpKSB7XG4gICAgbWFza1N0ci5wdXNoKFwiKHBcIiArIGkgKyBcIjw8XCIgKyBpICsgXCIpXCIpXG4gIH1cbiAgLy9HZW5lcmF0ZSB2YXJpYWJsZXMgYW5kIGdpZ2FudG8gc3dpdGNoIHN0YXRlbWVudFxuICBjb2RlLnB1c2goXCJ2YXIgbT0oXCIsIG1hc2tTdHIuam9pbihcIitcIiksIFwiKXwwO2lmKG09PT0wfHxtPT09XCIsICgxPDwoMTw8ZGltZW5zaW9uKSktMSwgXCIpe3JldHVybn1cIilcbiAgdmFyIGV4dHJhRnVuY3MgPSBbXVxuICB2YXIgY3VycmVudEZ1bmMgPSBbXVxuICBpZigxPDwoMTw8ZGltZW5zaW9uKSA8PSAxMjgpIHtcbiAgICBjb2RlLnB1c2goXCJzd2l0Y2gobSl7XCIpXG4gICAgY3VycmVudEZ1bmMgPSBjb2RlXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwic3dpdGNoKG0+Pj43KXtcIilcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwxPDwoMTw8ZGltZW5zaW9uKTsgKytpKSB7XG4gICAgaWYoMTw8KDE8PGRpbWVuc2lvbikgPiAxMjgpIHtcbiAgICAgIGlmKChpJTEyOCk9PT0wKSB7XG4gICAgICAgIGlmKGV4dHJhRnVuY3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGN1cnJlbnRGdW5jLnB1c2goXCJ9fVwiKVxuICAgICAgICB9XG4gICAgICAgIHZhciBlZk5hbWUgPSBcInZFeHRyYVwiICsgZXh0cmFGdW5jcy5sZW5ndGhcbiAgICAgICAgY29kZS5wdXNoKFwiY2FzZSBcIiwgKGk+Pj43KSwgXCI6XCIsIGVmTmFtZSwgXCIobSYweDdmLFwiLCBleHRyYUFyZ3Muam9pbigpLCBcIik7YnJlYWs7XCIpXG4gICAgICAgIGN1cnJlbnRGdW5jID0gW1xuICAgICAgICAgIFwiZnVuY3Rpb24gXCIsIGVmTmFtZSwgXCIobSxcIiwgZXh0cmFBcmdzLmpvaW4oKSwgXCIpe3N3aXRjaChtKXtcIlxuICAgICAgICBdXG4gICAgICAgIGV4dHJhRnVuY3MucHVzaChjdXJyZW50RnVuYylcbiAgICAgIH0gIFxuICAgIH1cbiAgICBjdXJyZW50RnVuYy5wdXNoKFwiY2FzZSBcIiwgKGkmMHg3ZiksIFwiOlwiKVxuICAgIHZhciBjcm9zc2luZ3MgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICAgIHZhciBkZW5vbXMgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICAgIHZhciBjcm9zc2luZ0NvdW50ID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgICB2YXIgYmlhcyA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gICAgdmFyIHRvdGFsQ3Jvc3NpbmdzID0gMFxuICAgIGZvcih2YXIgaj0wOyBqPGRpbWVuc2lvbjsgKytqKSB7XG4gICAgICBjcm9zc2luZ3Nbal0gPSBbXVxuICAgICAgZGVub21zW2pdID0gW11cbiAgICAgIGNyb3NzaW5nQ291bnRbal0gPSAwXG4gICAgICBiaWFzW2pdID0gMFxuICAgIH1cbiAgICBmb3IodmFyIGo9MDsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgICBmb3IodmFyIGs9MDsgazxkaW1lbnNpb247ICsraykge1xuICAgICAgICB2YXIgdSA9IGogXiAoMTw8aylcbiAgICAgICAgaWYodSA+IGopIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGlmKCEoaSYoMTw8dSkpICE9PSAhKGkmKDE8PGopKSkge1xuICAgICAgICAgIHZhciBzaWduID0gMVxuICAgICAgICAgIGlmKGkmKDE8PHUpKSB7XG4gICAgICAgICAgICBkZW5vbXNba10ucHVzaChcInZcIiArIHUgKyBcIi12XCIgKyBqKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZW5vbXNba10ucHVzaChcInZcIiArIGogKyBcIi12XCIgKyB1KVxuICAgICAgICAgICAgc2lnbiA9IC1zaWduXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHNpZ24gPCAwKSB7XG4gICAgICAgICAgICBjcm9zc2luZ3Nba10ucHVzaChcIi12XCIgKyBqICsgXCItdlwiICsgdSlcbiAgICAgICAgICAgIGNyb3NzaW5nQ291bnRba10gKz0gMlxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjcm9zc2luZ3Nba10ucHVzaChcInZcIiArIGogKyBcIit2XCIgKyB1KVxuICAgICAgICAgICAgY3Jvc3NpbmdDb3VudFtrXSAtPSAyICAgICAgICAgICAgXG4gICAgICAgICAgfVxuICAgICAgICAgIHRvdGFsQ3Jvc3NpbmdzICs9IDFcbiAgICAgICAgICBmb3IodmFyIGw9MDsgbDxkaW1lbnNpb247ICsrbCkge1xuICAgICAgICAgICAgaWYobCA9PT0gaykge1xuICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodSYoMTw8bCkpIHtcbiAgICAgICAgICAgICAgYmlhc1tsXSArPSAxXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBiaWFzW2xdIC09IDFcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHZlcnRleFN0ciA9IFtdXG4gICAgZm9yKHZhciBrPTA7IGs8ZGltZW5zaW9uOyArK2spIHtcbiAgICAgIGlmKGNyb3NzaW5nc1trXS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmVydGV4U3RyLnB1c2goXCJkXCIgKyBrICsgXCItMC41XCIpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgY1N0ciA9IFwiXCJcbiAgICAgICAgaWYoY3Jvc3NpbmdDb3VudFtrXSA8IDApIHtcbiAgICAgICAgICBjU3RyID0gY3Jvc3NpbmdDb3VudFtrXSArIFwiKmNcIlxuICAgICAgICB9IGVsc2UgaWYoY3Jvc3NpbmdDb3VudFtrXSA+IDApIHtcbiAgICAgICAgICBjU3RyID0gXCIrXCIgKyBjcm9zc2luZ0NvdW50W2tdICsgXCIqY1wiXG4gICAgICAgIH1cbiAgICAgICAgdmFyIHdlaWdodCA9IDAuNSAqIChjcm9zc2luZ3Nba10ubGVuZ3RoIC8gdG90YWxDcm9zc2luZ3MpXG4gICAgICAgIHZhciBzaGlmdCA9IDAuNSArIDAuNSAqIChiaWFzW2tdIC8gdG90YWxDcm9zc2luZ3MpXG4gICAgICAgIHZlcnRleFN0ci5wdXNoKFwiZFwiICsgayArIFwiLVwiICsgc2hpZnQgKyBcIi1cIiArIHdlaWdodCArIFwiKihcIiArIGNyb3NzaW5nc1trXS5qb2luKFwiK1wiKSArIGNTdHIgKyBcIikvKFwiICsgZGVub21zW2tdLmpvaW4oXCIrXCIpICsgXCIpXCIpXG4gICAgICAgIFxuICAgICAgfVxuICAgIH1cbiAgICBjdXJyZW50RnVuYy5wdXNoKFwiYS5wdXNoKFtcIiwgdmVydGV4U3RyLmpvaW4oKSwgXCJdKTtcIixcbiAgICAgIFwiYnJlYWs7XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifX0sXCIpXG4gIGlmKGV4dHJhRnVuY3MubGVuZ3RoID4gMCkge1xuICAgIGN1cnJlbnRGdW5jLnB1c2goXCJ9fVwiKVxuICB9XG5cbiAgLy9DcmVhdGUgZmFjZSBmdW5jdGlvblxuICB2YXIgZmFjZUFyZ3MgPSBbXVxuICBmb3IodmFyIGk9MDsgaTwoMTw8KGRpbWVuc2lvbi0xKSk7ICsraSkge1xuICAgIGZhY2VBcmdzLnB1c2goXCJ2XCIgKyBpKVxuICB9XG4gIGZhY2VBcmdzLnB1c2goXCJjMFwiLCBcImMxXCIsIFwicDBcIiwgXCJwMVwiLCBcImFcIiwgXCJiXCIsIFwiY1wiKVxuICBjb2RlLnB1c2goXCJjZWxsOmZ1bmN0aW9uIGNlbGxGdW5jKFwiLCBmYWNlQXJncy5qb2luKCksIFwiKXtcIilcblxuICB2YXIgZmFjZXRzID0gdHJpYW5ndWxhdGVDdWJlKGRpbWVuc2lvbi0xKVxuICBjb2RlLnB1c2goXCJpZihwMCl7Yi5wdXNoKFwiLFxuICAgIGZhY2V0cy5tYXAoZnVuY3Rpb24oZikge1xuICAgICAgcmV0dXJuIFwiW1wiICsgZi5tYXAoZnVuY3Rpb24odikge1xuICAgICAgICByZXR1cm4gXCJ2XCIgKyB2XG4gICAgICB9KSArIFwiXVwiXG4gICAgfSkuam9pbigpLCBcIil9ZWxzZXtiLnB1c2goXCIsXG4gICAgZmFjZXRzLm1hcChmdW5jdGlvbihmKSB7XG4gICAgICB2YXIgZSA9IGYuc2xpY2UoKVxuICAgICAgZS5yZXZlcnNlKClcbiAgICAgIHJldHVybiBcIltcIiArIGUubWFwKGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIFwidlwiICsgdlxuICAgICAgfSkgKyBcIl1cIlxuICAgIH0pLmpvaW4oKSxcbiAgICBcIil9fX0pO2Z1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoYXJyYXksbGV2ZWwpe3ZhciB2ZXJ0cz1bXSxjZWxscz1bXTtjb250b3VyKGFycmF5LHZlcnRzLGNlbGxzLGxldmVsKTtyZXR1cm4ge3Bvc2l0aW9uczp2ZXJ0cyxjZWxsczpjZWxsc307fSByZXR1cm4gXCIsIGZ1bmNOYW1lLCBcIjtcIilcblxuICBmb3IodmFyIGk9MDsgaTxleHRyYUZ1bmNzLmxlbmd0aDsgKytpKSB7XG4gICAgY29kZS5wdXNoKGV4dHJhRnVuY3NbaV0uam9pbihcIlwiKSlcbiAgfVxuXG4gIC8vQ29tcGlsZSBhbmQgbGlua1xuICB2YXIgcHJvYyA9IG5ldyBGdW5jdGlvbihcImdlbkNvbnRvdXJcIiwgY29kZS5qb2luKFwiXCIpKVxuICByZXR1cm4gcHJvYyhnZW5lcmF0ZUNvbnRvdXJFeHRyYWN0b3IpXG59XG5cbi8vMUQgY2FzZTogTmVlZCB0byBoYW5kbGUgc3BlY2lhbGx5XG5mdW5jdGlvbiBtZXNoMUQoYXJyYXksIGxldmVsKSB7XG4gIHZhciB6YyA9IHplcm9Dcm9zc2luZ3MoYXJyYXksIGxldmVsKVxuICB2YXIgbiA9IHpjLmxlbmd0aFxuICB2YXIgbnBvcyA9IG5ldyBBcnJheShuKVxuICB2YXIgbmNlbCA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICBucG9zW2ldID0gWyB6Y1tpXSBdXG4gICAgbmNlbFtpXSA9IFsgaSBdXG4gIH1cbiAgcmV0dXJuIHtcbiAgICBwb3NpdGlvbnM6IG5wb3MsXG4gICAgY2VsbHM6IG5jZWxcbiAgfVxufVxuXG52YXIgQ0FDSEUgPSB7fVxuXG5mdW5jdGlvbiBzdXJmYWNlTmV0cyhhcnJheSxsZXZlbCkge1xuICBpZihhcnJheS5kaW1lbnNpb24gPD0gMCkge1xuICAgIHJldHVybiB7IHBvc2l0aW9uczogW10sIGNlbGxzOiBbXSB9XG4gIH0gZWxzZSBpZihhcnJheS5kaW1lbnNpb24gPT09IDEpIHtcbiAgICByZXR1cm4gbWVzaDFEKGFycmF5LCBsZXZlbClcbiAgfVxuICB2YXIgdHlwZXNpZyA9IGFycmF5Lm9yZGVyLmpvaW4oKSArIFwiLVwiICsgYXJyYXkuZHR5cGVcbiAgdmFyIHByb2MgPSBDQUNIRVt0eXBlc2lnXVxuICB2YXIgbGV2ZWwgPSAoK2xldmVsKSB8fCAwLjBcbiAgaWYoIXByb2MpIHtcbiAgICBwcm9jID0gQ0FDSEVbdHlwZXNpZ10gPSBidWlsZFN1cmZhY2VOZXRzKGFycmF5Lm9yZGVyLCBhcnJheS5kdHlwZSlcbiAgfVxuICByZXR1cm4gcHJvYyhhcnJheSxsZXZlbClcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9zbGljZWRUb0FycmF5ID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBzbGljZUl0ZXJhdG9yKGFyciwgaSkgeyB2YXIgX2FyciA9IFtdOyB2YXIgX24gPSB0cnVlOyB2YXIgX2QgPSBmYWxzZTsgdmFyIF9lID0gdW5kZWZpbmVkOyB0cnkgeyBmb3IgKHZhciBfaSA9IGFycltTeW1ib2wuaXRlcmF0b3JdKCksIF9zOyAhKF9uID0gKF9zID0gX2kubmV4dCgpKS5kb25lKTsgX24gPSB0cnVlKSB7IF9hcnIucHVzaChfcy52YWx1ZSk7IGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhazsgfSB9IGNhdGNoIChlcnIpIHsgX2QgPSB0cnVlOyBfZSA9IGVycjsgfSBmaW5hbGx5IHsgdHJ5IHsgaWYgKCFfbiAmJiBfaVtcInJldHVyblwiXSkgX2lbXCJyZXR1cm5cIl0oKTsgfSBmaW5hbGx5IHsgaWYgKF9kKSB0aHJvdyBfZTsgfSB9IHJldHVybiBfYXJyOyB9IHJldHVybiBmdW5jdGlvbiAoYXJyLCBpKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHsgcmV0dXJuIGFycjsgfSBlbHNlIGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGFycikpIHsgcmV0dXJuIHNsaWNlSXRlcmF0b3IoYXJyLCBpKTsgfSBlbHNlIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2VcIik7IH0gfTsgfSgpO1xuXG52YXIgVEFVID0gTWF0aC5QSSAqIDI7XG5cbnZhciBtYXBUb0VsbGlwc2UgPSBmdW5jdGlvbiBtYXBUb0VsbGlwc2UoX3JlZiwgcngsIHJ5LCBjb3NwaGksIHNpbnBoaSwgY2VudGVyeCwgY2VudGVyeSkge1xuICB2YXIgeCA9IF9yZWYueCxcbiAgICAgIHkgPSBfcmVmLnk7XG5cbiAgeCAqPSByeDtcbiAgeSAqPSByeTtcblxuICB2YXIgeHAgPSBjb3NwaGkgKiB4IC0gc2lucGhpICogeTtcbiAgdmFyIHlwID0gc2lucGhpICogeCArIGNvc3BoaSAqIHk7XG5cbiAgcmV0dXJuIHtcbiAgICB4OiB4cCArIGNlbnRlcngsXG4gICAgeTogeXAgKyBjZW50ZXJ5XG4gIH07XG59O1xuXG52YXIgYXBwcm94VW5pdEFyYyA9IGZ1bmN0aW9uIGFwcHJveFVuaXRBcmMoYW5nMSwgYW5nMikge1xuICAvLyBTZWUgaHR0cDovL3NwZW5jZXJtb3J0ZW5zZW4uY29tL2FydGljbGVzL2Jlemllci1jaXJjbGUvIGZvciB0aGUgZGVyaXZhdGlvblxuICAvLyBvZiB0aGlzIGNvbnN0YW50LlxuICB2YXIgYyA9IDAuNTUxOTE1MDI0NDk0O1xuXG4gIHZhciB4MSA9IE1hdGguY29zKGFuZzEpO1xuICB2YXIgeTEgPSBNYXRoLnNpbihhbmcxKTtcbiAgdmFyIHgyID0gTWF0aC5jb3MoYW5nMSArIGFuZzIpO1xuICB2YXIgeTIgPSBNYXRoLnNpbihhbmcxICsgYW5nMik7XG5cbiAgcmV0dXJuIFt7XG4gICAgeDogeDEgLSB5MSAqIGMsXG4gICAgeTogeTEgKyB4MSAqIGNcbiAgfSwge1xuICAgIHg6IHgyICsgeTIgKiBjLFxuICAgIHk6IHkyIC0geDIgKiBjXG4gIH0sIHtcbiAgICB4OiB4MixcbiAgICB5OiB5MlxuICB9XTtcbn07XG5cbnZhciB2ZWN0b3JBbmdsZSA9IGZ1bmN0aW9uIHZlY3RvckFuZ2xlKHV4LCB1eSwgdngsIHZ5KSB7XG4gIHZhciBzaWduID0gdXggKiB2eSAtIHV5ICogdnggPCAwID8gLTEgOiAxO1xuICB2YXIgdW1hZyA9IE1hdGguc3FydCh1eCAqIHV4ICsgdXkgKiB1eSk7XG4gIHZhciB2bWFnID0gTWF0aC5zcXJ0KHV4ICogdXggKyB1eSAqIHV5KTtcbiAgdmFyIGRvdCA9IHV4ICogdnggKyB1eSAqIHZ5O1xuXG4gIHZhciBkaXYgPSBkb3QgLyAodW1hZyAqIHZtYWcpO1xuXG4gIGlmIChkaXYgPiAxKSB7XG4gICAgZGl2ID0gMTtcbiAgfVxuXG4gIGlmIChkaXYgPCAtMSkge1xuICAgIGRpdiA9IC0xO1xuICB9XG5cbiAgcmV0dXJuIHNpZ24gKiBNYXRoLmFjb3MoZGl2KTtcbn07XG5cbnZhciBnZXRBcmNDZW50ZXIgPSBmdW5jdGlvbiBnZXRBcmNDZW50ZXIocHgsIHB5LCBjeCwgY3ksIHJ4LCByeSwgbGFyZ2VBcmNGbGFnLCBzd2VlcEZsYWcsIHNpbnBoaSwgY29zcGhpLCBweHAsIHB5cCkge1xuICB2YXIgcnhzcSA9IE1hdGgucG93KHJ4LCAyKTtcbiAgdmFyIHJ5c3EgPSBNYXRoLnBvdyhyeSwgMik7XG4gIHZhciBweHBzcSA9IE1hdGgucG93KHB4cCwgMik7XG4gIHZhciBweXBzcSA9IE1hdGgucG93KHB5cCwgMik7XG5cbiAgdmFyIHJhZGljYW50ID0gcnhzcSAqIHJ5c3EgLSByeHNxICogcHlwc3EgLSByeXNxICogcHhwc3E7XG5cbiAgaWYgKHJhZGljYW50IDwgMCkge1xuICAgIHJhZGljYW50ID0gMDtcbiAgfVxuXG4gIHJhZGljYW50IC89IHJ4c3EgKiBweXBzcSArIHJ5c3EgKiBweHBzcTtcbiAgcmFkaWNhbnQgPSBNYXRoLnNxcnQocmFkaWNhbnQpICogKGxhcmdlQXJjRmxhZyA9PT0gc3dlZXBGbGFnID8gLTEgOiAxKTtcblxuICB2YXIgY2VudGVyeHAgPSByYWRpY2FudCAqIHJ4IC8gcnkgKiBweXA7XG4gIHZhciBjZW50ZXJ5cCA9IHJhZGljYW50ICogLXJ5IC8gcnggKiBweHA7XG5cbiAgdmFyIGNlbnRlcnggPSBjb3NwaGkgKiBjZW50ZXJ4cCAtIHNpbnBoaSAqIGNlbnRlcnlwICsgKHB4ICsgY3gpIC8gMjtcbiAgdmFyIGNlbnRlcnkgPSBzaW5waGkgKiBjZW50ZXJ4cCArIGNvc3BoaSAqIGNlbnRlcnlwICsgKHB5ICsgY3kpIC8gMjtcblxuICB2YXIgdngxID0gKHB4cCAtIGNlbnRlcnhwKSAvIHJ4O1xuICB2YXIgdnkxID0gKHB5cCAtIGNlbnRlcnlwKSAvIHJ5O1xuICB2YXIgdngyID0gKC1weHAgLSBjZW50ZXJ4cCkgLyByeDtcbiAgdmFyIHZ5MiA9ICgtcHlwIC0gY2VudGVyeXApIC8gcnk7XG5cbiAgdmFyIGFuZzEgPSB2ZWN0b3JBbmdsZSgxLCAwLCB2eDEsIHZ5MSk7XG4gIHZhciBhbmcyID0gdmVjdG9yQW5nbGUodngxLCB2eTEsIHZ4MiwgdnkyKTtcblxuICBpZiAoc3dlZXBGbGFnID09PSAwICYmIGFuZzIgPiAwKSB7XG4gICAgYW5nMiAtPSBUQVU7XG4gIH1cblxuICBpZiAoc3dlZXBGbGFnID09PSAxICYmIGFuZzIgPCAwKSB7XG4gICAgYW5nMiArPSBUQVU7XG4gIH1cblxuICByZXR1cm4gW2NlbnRlcngsIGNlbnRlcnksIGFuZzEsIGFuZzJdO1xufTtcblxudmFyIGFyY1RvQmV6aWVyID0gZnVuY3Rpb24gYXJjVG9CZXppZXIoX3JlZjIpIHtcbiAgdmFyIHB4ID0gX3JlZjIucHgsXG4gICAgICBweSA9IF9yZWYyLnB5LFxuICAgICAgY3ggPSBfcmVmMi5jeCxcbiAgICAgIGN5ID0gX3JlZjIuY3ksXG4gICAgICByeCA9IF9yZWYyLnJ4LFxuICAgICAgcnkgPSBfcmVmMi5yeSxcbiAgICAgIF9yZWYyJHhBeGlzUm90YXRpb24gPSBfcmVmMi54QXhpc1JvdGF0aW9uLFxuICAgICAgeEF4aXNSb3RhdGlvbiA9IF9yZWYyJHhBeGlzUm90YXRpb24gPT09IHVuZGVmaW5lZCA/IDAgOiBfcmVmMiR4QXhpc1JvdGF0aW9uLFxuICAgICAgX3JlZjIkbGFyZ2VBcmNGbGFnID0gX3JlZjIubGFyZ2VBcmNGbGFnLFxuICAgICAgbGFyZ2VBcmNGbGFnID0gX3JlZjIkbGFyZ2VBcmNGbGFnID09PSB1bmRlZmluZWQgPyAwIDogX3JlZjIkbGFyZ2VBcmNGbGFnLFxuICAgICAgX3JlZjIkc3dlZXBGbGFnID0gX3JlZjIuc3dlZXBGbGFnLFxuICAgICAgc3dlZXBGbGFnID0gX3JlZjIkc3dlZXBGbGFnID09PSB1bmRlZmluZWQgPyAwIDogX3JlZjIkc3dlZXBGbGFnO1xuXG4gIHZhciBjdXJ2ZXMgPSBbXTtcblxuICBpZiAocnggPT09IDAgfHwgcnkgPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICB2YXIgc2lucGhpID0gTWF0aC5zaW4oeEF4aXNSb3RhdGlvbiAqIFRBVSAvIDM2MCk7XG4gIHZhciBjb3NwaGkgPSBNYXRoLmNvcyh4QXhpc1JvdGF0aW9uICogVEFVIC8gMzYwKTtcblxuICB2YXIgcHhwID0gY29zcGhpICogKHB4IC0gY3gpIC8gMiArIHNpbnBoaSAqIChweSAtIGN5KSAvIDI7XG4gIHZhciBweXAgPSAtc2lucGhpICogKHB4IC0gY3gpIC8gMiArIGNvc3BoaSAqIChweSAtIGN5KSAvIDI7XG5cbiAgaWYgKHB4cCA9PT0gMCAmJiBweXAgPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICByeCA9IE1hdGguYWJzKHJ4KTtcbiAgcnkgPSBNYXRoLmFicyhyeSk7XG5cbiAgdmFyIGxhbWJkYSA9IE1hdGgucG93KHB4cCwgMikgLyBNYXRoLnBvdyhyeCwgMikgKyBNYXRoLnBvdyhweXAsIDIpIC8gTWF0aC5wb3cocnksIDIpO1xuXG4gIGlmIChsYW1iZGEgPiAxKSB7XG4gICAgcnggKj0gTWF0aC5zcXJ0KGxhbWJkYSk7XG4gICAgcnkgKj0gTWF0aC5zcXJ0KGxhbWJkYSk7XG4gIH1cblxuICB2YXIgX2dldEFyY0NlbnRlciA9IGdldEFyY0NlbnRlcihweCwgcHksIGN4LCBjeSwgcngsIHJ5LCBsYXJnZUFyY0ZsYWcsIHN3ZWVwRmxhZywgc2lucGhpLCBjb3NwaGksIHB4cCwgcHlwKSxcbiAgICAgIF9nZXRBcmNDZW50ZXIyID0gX3NsaWNlZFRvQXJyYXkoX2dldEFyY0NlbnRlciwgNCksXG4gICAgICBjZW50ZXJ4ID0gX2dldEFyY0NlbnRlcjJbMF0sXG4gICAgICBjZW50ZXJ5ID0gX2dldEFyY0NlbnRlcjJbMV0sXG4gICAgICBhbmcxID0gX2dldEFyY0NlbnRlcjJbMl0sXG4gICAgICBhbmcyID0gX2dldEFyY0NlbnRlcjJbM107XG5cbiAgLy8gSWYgJ2FuZzInID09IDkwLjAwMDAwMDAwMDEsIHRoZW4gYHJhdGlvYCB3aWxsIGV2YWx1YXRlIHRvXG4gIC8vIDEuMDAwMDAwMDAwMS4gVGhpcyBjYXVzZXMgYHNlZ21lbnRzYCB0byBiZSBncmVhdGVyIHRoYW4gb25lLCB3aGljaCBpcyBhblxuICAvLyB1bmVjZXNzYXJ5IHNwbGl0LCBhbmQgYWRkcyBleHRyYSBwb2ludHMgdG8gdGhlIGJlemllciBjdXJ2ZS4gVG8gYWxsZXZpYXRlXG4gIC8vIHRoaXMgaXNzdWUsIHdlIHJvdW5kIHRvIDEuMCB3aGVuIHRoZSByYXRpbyBpcyBjbG9zZSB0byAxLjAuXG5cblxuICB2YXIgcmF0aW8gPSBNYXRoLmFicyhhbmcyKSAvIChUQVUgLyA0KTtcbiAgaWYgKE1hdGguYWJzKDEuMCAtIHJhdGlvKSA8IDAuMDAwMDAwMSkge1xuICAgIHJhdGlvID0gMS4wO1xuICB9XG5cbiAgdmFyIHNlZ21lbnRzID0gTWF0aC5tYXgoTWF0aC5jZWlsKHJhdGlvKSwgMSk7XG5cbiAgYW5nMiAvPSBzZWdtZW50cztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHNlZ21lbnRzOyBpKyspIHtcbiAgICBjdXJ2ZXMucHVzaChhcHByb3hVbml0QXJjKGFuZzEsIGFuZzIpKTtcbiAgICBhbmcxICs9IGFuZzI7XG4gIH1cblxuICByZXR1cm4gY3VydmVzLm1hcChmdW5jdGlvbiAoY3VydmUpIHtcbiAgICB2YXIgX21hcFRvRWxsaXBzZSA9IG1hcFRvRWxsaXBzZShjdXJ2ZVswXSwgcngsIHJ5LCBjb3NwaGksIHNpbnBoaSwgY2VudGVyeCwgY2VudGVyeSksXG4gICAgICAgIHgxID0gX21hcFRvRWxsaXBzZS54LFxuICAgICAgICB5MSA9IF9tYXBUb0VsbGlwc2UueTtcblxuICAgIHZhciBfbWFwVG9FbGxpcHNlMiA9IG1hcFRvRWxsaXBzZShjdXJ2ZVsxXSwgcngsIHJ5LCBjb3NwaGksIHNpbnBoaSwgY2VudGVyeCwgY2VudGVyeSksXG4gICAgICAgIHgyID0gX21hcFRvRWxsaXBzZTIueCxcbiAgICAgICAgeTIgPSBfbWFwVG9FbGxpcHNlMi55O1xuXG4gICAgdmFyIF9tYXBUb0VsbGlwc2UzID0gbWFwVG9FbGxpcHNlKGN1cnZlWzJdLCByeCwgcnksIGNvc3BoaSwgc2lucGhpLCBjZW50ZXJ4LCBjZW50ZXJ5KSxcbiAgICAgICAgeCA9IF9tYXBUb0VsbGlwc2UzLngsXG4gICAgICAgIHkgPSBfbWFwVG9FbGxpcHNlMy55O1xuXG4gICAgcmV0dXJuIHsgeDE6IHgxLCB5MTogeTEsIHgyOiB4MiwgeTI6IHkyLCB4OiB4LCB5OiB5IH07XG4gIH0pO1xufTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gYXJjVG9CZXppZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMuZGVmYXVsdDsiLCIndXNlIHN0cmljdCdcclxuXHJcbnZhciBwYXJzZSA9IHJlcXVpcmUoJ3BhcnNlLXN2Zy1wYXRoJylcclxudmFyIGFicyA9IHJlcXVpcmUoJ2Ficy1zdmctcGF0aCcpXHJcbnZhciBub3JtYWxpemUgPSByZXF1aXJlKCdub3JtYWxpemUtc3ZnLXBhdGgnKVxyXG52YXIgaXNTdmdQYXRoID0gcmVxdWlyZSgnaXMtc3ZnLXBhdGgnKVxyXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0JylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcGF0aEJvdW5kc1xyXG5cclxuXHJcbmZ1bmN0aW9uIHBhdGhCb3VuZHMocGF0aCkge1xyXG4gIC8vIEVTNiBzdHJpbmcgdHBsIGNhbGxcclxuICBpZiAoQXJyYXkuaXNBcnJheShwYXRoKSAmJiBwYXRoLmxlbmd0aCA9PT0gMSAmJiB0eXBlb2YgcGF0aFswXSA9PT0gJ3N0cmluZycpIHBhdGggPSBwYXRoWzBdXHJcblxyXG4gIC8vIHN2ZyBwYXRoIHN0cmluZ1xyXG4gIGlmICh0eXBlb2YgcGF0aCA9PT0gJ3N0cmluZycpIHtcclxuICAgIGFzc2VydChpc1N2Z1BhdGgocGF0aCksICdTdHJpbmcgaXMgbm90IGFuIFNWRyBwYXRoLicpXHJcbiAgICBwYXRoID0gcGFyc2UocGF0aClcclxuICB9XHJcblxyXG4gIGFzc2VydChBcnJheS5pc0FycmF5KHBhdGgpLCAnQXJndW1lbnQgc2hvdWxkIGJlIGEgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHBhdGggc2VnbWVudHMuJylcclxuXHJcbiAgcGF0aCA9IGFicyhwYXRoKVxyXG4gIHBhdGggPSBub3JtYWxpemUocGF0aClcclxuXHJcbiAgaWYgKCFwYXRoLmxlbmd0aCkgcmV0dXJuIFswLCAwLCAwLCAwXVxyXG5cclxuICB2YXIgYm91bmRzID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXHJcblxyXG4gIGZvciAodmFyIGkgPSAwLCBsID0gcGF0aC5sZW5ndGg7IGkgPCBsOyBpKyspIHtcclxuICAgIHZhciBwb2ludHMgPSBwYXRoW2ldLnNsaWNlKDEpXHJcblxyXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwb2ludHMubGVuZ3RoOyBqICs9IDIpIHtcclxuICAgICAgaWYgKHBvaW50c1tqICsgMF0gPCBib3VuZHNbMF0pIGJvdW5kc1swXSA9IHBvaW50c1tqICsgMF1cclxuICAgICAgaWYgKHBvaW50c1tqICsgMV0gPCBib3VuZHNbMV0pIGJvdW5kc1sxXSA9IHBvaW50c1tqICsgMV1cclxuICAgICAgaWYgKHBvaW50c1tqICsgMF0gPiBib3VuZHNbMl0pIGJvdW5kc1syXSA9IHBvaW50c1tqICsgMF1cclxuICAgICAgaWYgKHBvaW50c1tqICsgMV0gPiBib3VuZHNbM10pIGJvdW5kc1szXSA9IHBvaW50c1tqICsgMV1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiBib3VuZHNcclxufVxyXG4iLCIndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gbm9ybWFsaXplXHJcblxyXG52YXIgYXJjVG9DdXJ2ZSA9IHJlcXVpcmUoJ3N2Zy1hcmMtdG8tY3ViaWMtYmV6aWVyJylcclxuXHJcbmZ1bmN0aW9uIG5vcm1hbGl6ZShwYXRoKXtcclxuICAvLyBpbml0IHN0YXRlXHJcbiAgdmFyIHByZXZcclxuICB2YXIgcmVzdWx0ID0gW11cclxuICB2YXIgYmV6aWVyWCA9IDBcclxuICB2YXIgYmV6aWVyWSA9IDBcclxuICB2YXIgc3RhcnRYID0gMFxyXG4gIHZhciBzdGFydFkgPSAwXHJcbiAgdmFyIHF1YWRYID0gbnVsbFxyXG4gIHZhciBxdWFkWSA9IG51bGxcclxuICB2YXIgeCA9IDBcclxuICB2YXIgeSA9IDBcclxuXHJcbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHBhdGgubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuICAgIHZhciBzZWcgPSBwYXRoW2ldXHJcbiAgICB2YXIgY29tbWFuZCA9IHNlZ1swXVxyXG5cclxuICAgIHN3aXRjaCAoY29tbWFuZCkge1xyXG4gICAgICBjYXNlICdNJzpcclxuICAgICAgICBzdGFydFggPSBzZWdbMV1cclxuICAgICAgICBzdGFydFkgPSBzZWdbMl1cclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlICdBJzpcclxuICAgICAgICB2YXIgY3VydmVzID0gYXJjVG9DdXJ2ZSh7XHJcbiAgICAgICAgICBweDogeCxcclxuICAgICAgICAgIHB5OiB5LFxyXG4gICAgICAgICAgY3g6IHNlZ1s2XSxcclxuICAgICAgICAgIGN5OiAgc2VnWzddLFxyXG4gICAgICAgICAgcng6IHNlZ1sxXSxcclxuICAgICAgICAgIHJ5OiBzZWdbMl0sXHJcbiAgICAgICAgICB4QXhpc1JvdGF0aW9uOiBzZWdbM10sXHJcbiAgICAgICAgICBsYXJnZUFyY0ZsYWc6IHNlZ1s0XSxcclxuICAgICAgICAgIHN3ZWVwRmxhZzogc2VnWzVdXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgLy8gbnVsbC1jdXJ2ZXNcclxuICAgICAgICBpZiAoIWN1cnZlcy5sZW5ndGgpIGNvbnRpbnVlXHJcblxyXG4gICAgICAgIGZvciAodmFyIGogPSAwLCBjOyBqIDwgY3VydmVzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICBjID0gY3VydmVzW2pdXHJcbiAgICAgICAgICBzZWcgPSBbJ0MnLCBjLngxLCBjLnkxLCBjLngyLCBjLnkyLCBjLngsIGMueV1cclxuICAgICAgICAgIGlmIChqIDwgY3VydmVzLmxlbmd0aCAtIDEpIHJlc3VsdC5wdXNoKHNlZylcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ1MnOlxyXG4gICAgICAgIC8vIGRlZmF1bHQgY29udHJvbCBwb2ludFxyXG4gICAgICAgIHZhciBjeCA9IHhcclxuICAgICAgICB2YXIgY3kgPSB5XHJcbiAgICAgICAgaWYgKHByZXYgPT0gJ0MnIHx8IHByZXYgPT0gJ1MnKSB7XHJcbiAgICAgICAgICBjeCArPSBjeCAtIGJlemllclggLy8gcmVmbGVjdCB0aGUgcHJldmlvdXMgY29tbWFuZCdzIGNvbnRyb2xcclxuICAgICAgICAgIGN5ICs9IGN5IC0gYmV6aWVyWSAvLyBwb2ludCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBwb2ludFxyXG4gICAgICAgIH1cclxuICAgICAgICBzZWcgPSBbJ0MnLCBjeCwgY3ksIHNlZ1sxXSwgc2VnWzJdLCBzZWdbM10sIHNlZ1s0XV1cclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlICdUJzpcclxuICAgICAgICBpZiAocHJldiA9PSAnUScgfHwgcHJldiA9PSAnVCcpIHtcclxuICAgICAgICAgIHF1YWRYID0geCAqIDIgLSBxdWFkWCAvLyBhcyB3aXRoICdTJyByZWZsZWN0IHByZXZpb3VzIGNvbnRyb2wgcG9pbnRcclxuICAgICAgICAgIHF1YWRZID0geSAqIDIgLSBxdWFkWVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBxdWFkWCA9IHhcclxuICAgICAgICAgIHF1YWRZID0geVxyXG4gICAgICAgIH1cclxuICAgICAgICBzZWcgPSBxdWFkcmF0aWMoeCwgeSwgcXVhZFgsIHF1YWRZLCBzZWdbMV0sIHNlZ1syXSlcclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlICdRJzpcclxuICAgICAgICBxdWFkWCA9IHNlZ1sxXVxyXG4gICAgICAgIHF1YWRZID0gc2VnWzJdXHJcbiAgICAgICAgc2VnID0gcXVhZHJhdGljKHgsIHksIHNlZ1sxXSwgc2VnWzJdLCBzZWdbM10sIHNlZ1s0XSlcclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlICdMJzpcclxuICAgICAgICBzZWcgPSBsaW5lKHgsIHksIHNlZ1sxXSwgc2VnWzJdKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ0gnOlxyXG4gICAgICAgIHNlZyA9IGxpbmUoeCwgeSwgc2VnWzFdLCB5KVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ1YnOlxyXG4gICAgICAgIHNlZyA9IGxpbmUoeCwgeSwgeCwgc2VnWzFdKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ1onOlxyXG4gICAgICAgIHNlZyA9IGxpbmUoeCwgeSwgc3RhcnRYLCBzdGFydFkpXHJcbiAgICAgICAgYnJlYWtcclxuICAgIH1cclxuXHJcbiAgICAvLyB1cGRhdGUgc3RhdGVcclxuICAgIHByZXYgPSBjb21tYW5kXHJcbiAgICB4ID0gc2VnW3NlZy5sZW5ndGggLSAyXVxyXG4gICAgeSA9IHNlZ1tzZWcubGVuZ3RoIC0gMV1cclxuICAgIGlmIChzZWcubGVuZ3RoID4gNCkge1xyXG4gICAgICBiZXppZXJYID0gc2VnW3NlZy5sZW5ndGggLSA0XVxyXG4gICAgICBiZXppZXJZID0gc2VnW3NlZy5sZW5ndGggLSAzXVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYmV6aWVyWCA9IHhcclxuICAgICAgYmV6aWVyWSA9IHlcclxuICAgIH1cclxuICAgIHJlc3VsdC5wdXNoKHNlZylcclxuICB9XHJcblxyXG4gIHJldHVybiByZXN1bHRcclxufVxyXG5cclxuZnVuY3Rpb24gbGluZSh4MSwgeTEsIHgyLCB5Mil7XHJcbiAgcmV0dXJuIFsnQycsIHgxLCB5MSwgeDIsIHkyLCB4MiwgeTJdXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHF1YWRyYXRpYyh4MSwgeTEsIGN4LCBjeSwgeDIsIHkyKXtcclxuICByZXR1cm4gW1xyXG4gICAgJ0MnLFxyXG4gICAgeDEvMyArICgyLzMpICogY3gsXHJcbiAgICB5MS8zICsgKDIvMykgKiBjeSxcclxuICAgIHgyLzMgKyAoMi8zKSAqIGN4LFxyXG4gICAgeTIvMyArICgyLzMpICogY3ksXHJcbiAgICB4MixcclxuICAgIHkyXHJcbiAgXVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHBhdGhCb3VuZHMgPSByZXF1aXJlKCdzdmctcGF0aC1ib3VuZHMnKVxyXG52YXIgcGFyc2VQYXRoID0gcmVxdWlyZSgncGFyc2Utc3ZnLXBhdGgnKVxyXG52YXIgZHJhd1BhdGggPSByZXF1aXJlKCdkcmF3LXN2Zy1wYXRoJylcclxudmFyIGlzU3ZnUGF0aCA9IHJlcXVpcmUoJ2lzLXN2Zy1wYXRoJylcclxudmFyIGJpdG1hcFNkZiA9IHJlcXVpcmUoJ2JpdG1hcC1zZGYnKVxyXG5cclxudmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbnZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcGF0aFNkZlxyXG5cclxuXHJcbmZ1bmN0aW9uIHBhdGhTZGYgKHBhdGgsIG9wdGlvbnMpIHtcclxuXHRpZiAoIWlzU3ZnUGF0aChwYXRoKSkgdGhyb3cgRXJyb3IoJ0FyZ3VtZW50IHNob3VsZCBiZSB2YWxpZCBzdmcgcGF0aCBzdHJpbmcnKVxyXG5cclxuXHRpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fVxyXG5cclxuXHR2YXIgdywgaFxyXG5cdGlmIChvcHRpb25zLnNoYXBlKSB7XHJcblx0XHR3ID0gb3B0aW9ucy5zaGFwZVswXVxyXG5cdFx0aCA9IG9wdGlvbnMuc2hhcGVbMV1cclxuXHR9XHJcblx0ZWxzZSB7XHJcblx0XHR3ID0gY2FudmFzLndpZHRoID0gb3B0aW9ucy53IHx8IG9wdGlvbnMud2lkdGggfHwgMjAwXHJcblx0XHRoID0gY2FudmFzLmhlaWdodCA9IG9wdGlvbnMuaCB8fCBvcHRpb25zLmhlaWdodCB8fCAyMDBcclxuXHR9XHJcblx0dmFyIHNpemUgPSBNYXRoLm1pbih3LCBoKVxyXG5cclxuXHR2YXIgc3Ryb2tlID0gb3B0aW9ucy5zdHJva2UgfHwgMFxyXG5cclxuXHR2YXIgdmlld2JveCA9IG9wdGlvbnMudmlld2JveCB8fCBvcHRpb25zLnZpZXdCb3ggfHwgcGF0aEJvdW5kcyhwYXRoKVxyXG5cdHZhciBzY2FsZSA9IFt3IC8gKHZpZXdib3hbMl0gLSB2aWV3Ym94WzBdKSwgaCAvICh2aWV3Ym94WzNdIC0gdmlld2JveFsxXSldXHJcblx0dmFyIG1heFNjYWxlID0gTWF0aC5taW4oc2NhbGVbMF0gfHwgMCwgc2NhbGVbMV0gfHwgMCkgLyAyXHJcblxyXG5cdC8vY2xlYXIgY3R4XHJcblx0Y3R4LmZpbGxTdHlsZSA9ICdibGFjaydcclxuXHRjdHguZmlsbFJlY3QoMCwgMCwgdywgaClcclxuXHJcblx0Y3R4LmZpbGxTdHlsZSA9ICd3aGl0ZSdcclxuXHJcblx0aWYgKHN0cm9rZSlcdHtcclxuXHRcdGlmICh0eXBlb2Ygc3Ryb2tlICE9ICdudW1iZXInKSBzdHJva2UgPSAxXHJcblx0XHRpZiAoc3Ryb2tlID4gMCkge1xyXG5cdFx0XHRjdHguc3Ryb2tlU3R5bGUgPSAnd2hpdGUnXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0Y3R4LnN0cm9rZVN0eWxlID0gJ2JsYWNrJ1xyXG5cdFx0fVxyXG5cclxuXHRcdGN0eC5saW5lV2lkdGggPSBNYXRoLmFicyhzdHJva2UpXHJcblx0fVxyXG5cclxuXHRjdHgudHJhbnNsYXRlKHcgKiAuNSwgaCAqIC41KVxyXG5cdGN0eC5zY2FsZShtYXhTY2FsZSwgbWF4U2NhbGUpXHJcblxyXG5cdC8vaWYgY2FudmFzIHN2ZyBwYXRocyBhcGkgaXMgYXZhaWxhYmxlXHJcblx0aWYgKGlzUGF0aDJEU3VwcG9ydGVkKCkpIHtcclxuXHRcdHZhciBwYXRoMmQgPSBuZXcgUGF0aDJEKHBhdGgpXHJcblx0XHRjdHguZmlsbChwYXRoMmQpXHJcblx0XHRzdHJva2UgJiYgY3R4LnN0cm9rZShwYXRoMmQpXHJcblx0fVxyXG5cdC8vZmFsbGJhY2sgdG8gYmV6aWVyLWN1cnZlc1xyXG5cdGVsc2Uge1xyXG5cdFx0dmFyIHNlZ21lbnRzID0gcGFyc2VQYXRoKHBhdGgpXHJcblx0XHRkcmF3UGF0aChjdHgsIHNlZ21lbnRzKVxyXG5cdFx0Y3R4LmZpbGwoKVxyXG5cdFx0c3Ryb2tlICYmIGN0eC5zdHJva2UoKVxyXG5cdH1cclxuXHJcblx0Y3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcclxuXHJcblx0dmFyIGRhdGEgPSBiaXRtYXBTZGYoY3R4LCB7XHJcblx0XHRjdXRvZmY6IG9wdGlvbnMuY3V0b2ZmICE9IG51bGwgPyBvcHRpb25zLmN1dG9mZiA6IC41LFxyXG5cdFx0cmFkaXVzOiBvcHRpb25zLnJhZGl1cyAhPSBudWxsID8gb3B0aW9ucy5yYWRpdXMgOiBzaXplICogLjVcclxuXHR9KVxyXG5cclxuXHRyZXR1cm4gZGF0YVxyXG59XHJcblxyXG5mdW5jdGlvbiBpc1BhdGgyRFN1cHBvcnRlZCAoKSB7XHJcblx0dmFyIGN0eCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpLmdldENvbnRleHQoJzJkJylcclxuXHRjdHguY2FudmFzLndpZHRoID0gY3R4LmNhbnZhcy5oZWlnaHQgPSAxXHJcblxyXG5cdHZhciBwYXRoID0gbmV3IFBhdGgyRCgnTTAsMGgxdjFoLTF2LTFaJylcclxuXHJcblx0Y3R4LmZpbGxTdHlsZSA9ICdibGFjaydcclxuXHRjdHguZmlsbChwYXRoKVxyXG5cclxuXHR2YXIgaWRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsMCwxLDEpXHJcblxyXG5cdHJldHVybiBpZGF0YSAmJiBpZGF0YS5kYXRhICYmIGlkYXRhLmRhdGFbM10gPT09IDI1NVxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHRleHRHZXRcblxudmFyIHZlY3Rvcml6ZVRleHQgPSByZXF1aXJlKCd2ZWN0b3JpemUtdGV4dCcpXG5cbnZhciBnbG9iYWxzID0gd2luZG93IHx8IHByb2Nlc3MuZ2xvYmFsIHx8IHt9XG52YXIgX19URVhUX0NBQ0hFICA9IGdsb2JhbHMuX19URVhUX0NBQ0hFIHx8IHt9XG5nbG9iYWxzLl9fVEVYVF9DQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIHVud3JhcChtZXNoKSB7XG4gIHZhciBjZWxscyAgICAgPSBtZXNoLmNlbGxzXG4gIHZhciBwb3NpdGlvbnMgPSBtZXNoLnBvc2l0aW9uc1xuICB2YXIgZGF0YSAgICAgID0gbmV3IEZsb2F0MzJBcnJheShjZWxscy5sZW5ndGggKiA2KVxuICB2YXIgcHRyICAgICAgID0gMFxuICB2YXIgc2hhcGVYICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciB0cmkgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgdmFyIHBvaW50ID0gcG9zaXRpb25zW3RyaVtqXV1cbiAgICAgIGRhdGFbcHRyKytdID0gcG9pbnRbMF1cbiAgICAgIGRhdGFbcHRyKytdID0gcG9pbnRbMV0gKyAxLjRcbiAgICAgIHNoYXBlWCAgICAgID0gTWF0aC5tYXgocG9pbnRbMF0sIHNoYXBlWClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBkYXRhOiAgZGF0YSxcbiAgICBzaGFwZTogc2hhcGVYXG4gIH1cbn1cblxuZnVuY3Rpb24gdGV4dEdldChmb250LCB0ZXh0LCBvcHRzKSB7XG4gIHZhciBvcHRzID0gb3B0cyB8fCB7fVxuICB2YXIgZm9udGNhY2hlID0gX19URVhUX0NBQ0hFW2ZvbnRdXG4gICBpZighZm9udGNhY2hlKSB7XG4gICAgIGZvbnRjYWNoZSA9IF9fVEVYVF9DQUNIRVtmb250XSA9IHtcbiAgICAgICAnICc6IHtcbiAgICAgICAgIGRhdGE6ICAgbmV3IEZsb2F0MzJBcnJheSgwKSxcbiAgICAgICAgIHNoYXBlOiAwLjJcbiAgICAgICB9XG4gICAgIH1cbiAgIH1cbiAgIHZhciBtZXNoID0gZm9udGNhY2hlW3RleHRdXG4gICBpZighbWVzaCkge1xuICAgICBpZih0ZXh0Lmxlbmd0aCA8PSAxIHx8ICEvXFxkLy50ZXN0KHRleHQpKSB7XG4gICAgICAgbWVzaCA9IGZvbnRjYWNoZVt0ZXh0XSA9IHVud3JhcCh2ZWN0b3JpemVUZXh0KHRleHQsIHtcbiAgICAgICAgIHRyaWFuZ2xlczogICAgIHRydWUsXG4gICAgICAgICBmb250OiAgICAgICAgICBmb250LFxuICAgICAgICAgdGV4dEFsaWduOiAgICAgb3B0cy50ZXh0QWxpZ24gfHwgJ2xlZnQnLFxuICAgICAgICAgdGV4dEJhc2VsaW5lOiAgJ2FscGhhYmV0aWMnXG4gICAgICAgfSkpXG4gICAgIH0gZWxzZSB7XG4gICAgICAgdmFyIHBhcnRzID0gdGV4dC5zcGxpdCgvKFxcZHxcXHMpLylcbiAgICAgICB2YXIgYnVmZmVyID0gbmV3IEFycmF5KHBhcnRzLmxlbmd0aClcbiAgICAgICB2YXIgYnVmZmVyU2l6ZSA9IDBcbiAgICAgICB2YXIgc2hhcGVYID0gMFxuICAgICAgIGZvcih2YXIgaT0wOyBpPHBhcnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICBidWZmZXJbaV0gPSB0ZXh0R2V0KGZvbnQsIHBhcnRzW2ldKVxuICAgICAgICAgYnVmZmVyU2l6ZSArPSBidWZmZXJbaV0uZGF0YS5sZW5ndGhcbiAgICAgICAgIHNoYXBlWCArPSBidWZmZXJbaV0uc2hhcGVcbiAgICAgICAgIGlmKGk+MCkge1xuICAgICAgICAgICBzaGFwZVggKz0gMC4wMlxuICAgICAgICAgfVxuICAgICAgIH1cblxuICAgICAgIHZhciBkYXRhID0gbmV3IEZsb2F0MzJBcnJheShidWZmZXJTaXplKVxuICAgICAgIHZhciBwdHIgICAgID0gMFxuICAgICAgIHZhciB4T2Zmc2V0ID0gLTAuNSAqIHNoYXBlWFxuICAgICAgIGZvcih2YXIgaT0wOyBpPGJ1ZmZlci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgdmFyIGJkYXRhID0gYnVmZmVyW2ldLmRhdGFcbiAgICAgICAgIGZvcih2YXIgaj0wOyBqPGJkYXRhLmxlbmd0aDsgais9Mikge1xuICAgICAgICAgICBkYXRhW3B0cisrXSA9IGJkYXRhW2pdICsgeE9mZnNldFxuICAgICAgICAgICBkYXRhW3B0cisrXSA9IGJkYXRhW2orMV1cbiAgICAgICAgIH1cbiAgICAgICAgIHhPZmZzZXQgKz0gYnVmZmVyW2ldLnNoYXBlICsgMC4wMlxuICAgICAgIH1cblxuICAgICAgIG1lc2ggPSBmb250Y2FjaGVbdGV4dF0gPSB7XG4gICAgICAgICBkYXRhOiAgZGF0YSxcbiAgICAgICAgIHNoYXBlOiBzaGFwZVhcbiAgICAgICB9XG4gICAgIH1cbiAgIH1cblxuICAgcmV0dXJuIG1lc2hcbn1cbiIsIi8vIFRpbnlDb2xvciB2MS40LjFcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iZ3JpbnMvVGlueUNvbG9yXG4vLyBCcmlhbiBHcmluc3RlYWQsIE1JVCBMaWNlbnNlXG5cbihmdW5jdGlvbihNYXRoKSB7XG5cbnZhciB0cmltTGVmdCA9IC9eXFxzKy8sXG4gICAgdHJpbVJpZ2h0ID0gL1xccyskLyxcbiAgICB0aW55Q291bnRlciA9IDAsXG4gICAgbWF0aFJvdW5kID0gTWF0aC5yb3VuZCxcbiAgICBtYXRoTWluID0gTWF0aC5taW4sXG4gICAgbWF0aE1heCA9IE1hdGgubWF4LFxuICAgIG1hdGhSYW5kb20gPSBNYXRoLnJhbmRvbTtcblxuZnVuY3Rpb24gdGlueWNvbG9yIChjb2xvciwgb3B0cykge1xuXG4gICAgY29sb3IgPSAoY29sb3IpID8gY29sb3IgOiAnJztcbiAgICBvcHRzID0gb3B0cyB8fCB7IH07XG5cbiAgICAvLyBJZiBpbnB1dCBpcyBhbHJlYWR5IGEgdGlueWNvbG9yLCByZXR1cm4gaXRzZWxmXG4gICAgaWYgKGNvbG9yIGluc3RhbmNlb2YgdGlueWNvbG9yKSB7XG4gICAgICAgcmV0dXJuIGNvbG9yO1xuICAgIH1cbiAgICAvLyBJZiB3ZSBhcmUgY2FsbGVkIGFzIGEgZnVuY3Rpb24sIGNhbGwgdXNpbmcgbmV3IGluc3RlYWRcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgdGlueWNvbG9yKSkge1xuICAgICAgICByZXR1cm4gbmV3IHRpbnljb2xvcihjb2xvciwgb3B0cyk7XG4gICAgfVxuXG4gICAgdmFyIHJnYiA9IGlucHV0VG9SR0IoY29sb3IpO1xuICAgIHRoaXMuX29yaWdpbmFsSW5wdXQgPSBjb2xvcixcbiAgICB0aGlzLl9yID0gcmdiLnIsXG4gICAgdGhpcy5fZyA9IHJnYi5nLFxuICAgIHRoaXMuX2IgPSByZ2IuYixcbiAgICB0aGlzLl9hID0gcmdiLmEsXG4gICAgdGhpcy5fcm91bmRBID0gbWF0aFJvdW5kKDEwMCp0aGlzLl9hKSAvIDEwMCxcbiAgICB0aGlzLl9mb3JtYXQgPSBvcHRzLmZvcm1hdCB8fCByZ2IuZm9ybWF0O1xuICAgIHRoaXMuX2dyYWRpZW50VHlwZSA9IG9wdHMuZ3JhZGllbnRUeXBlO1xuXG4gICAgLy8gRG9uJ3QgbGV0IHRoZSByYW5nZSBvZiBbMCwyNTVdIGNvbWUgYmFjayBpbiBbMCwxXS5cbiAgICAvLyBQb3RlbnRpYWxseSBsb3NlIGEgbGl0dGxlIGJpdCBvZiBwcmVjaXNpb24gaGVyZSwgYnV0IHdpbGwgZml4IGlzc3VlcyB3aGVyZVxuICAgIC8vIC41IGdldHMgaW50ZXJwcmV0ZWQgYXMgaGFsZiBvZiB0aGUgdG90YWwsIGluc3RlYWQgb2YgaGFsZiBvZiAxXG4gICAgLy8gSWYgaXQgd2FzIHN1cHBvc2VkIHRvIGJlIDEyOCwgdGhpcyB3YXMgYWxyZWFkeSB0YWtlbiBjYXJlIG9mIGJ5IGBpbnB1dFRvUmdiYFxuICAgIGlmICh0aGlzLl9yIDwgMSkgeyB0aGlzLl9yID0gbWF0aFJvdW5kKHRoaXMuX3IpOyB9XG4gICAgaWYgKHRoaXMuX2cgPCAxKSB7IHRoaXMuX2cgPSBtYXRoUm91bmQodGhpcy5fZyk7IH1cbiAgICBpZiAodGhpcy5fYiA8IDEpIHsgdGhpcy5fYiA9IG1hdGhSb3VuZCh0aGlzLl9iKTsgfVxuXG4gICAgdGhpcy5fb2sgPSByZ2Iub2s7XG4gICAgdGhpcy5fdGNfaWQgPSB0aW55Q291bnRlcisrO1xufVxuXG50aW55Y29sb3IucHJvdG90eXBlID0ge1xuICAgIGlzRGFyazogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEJyaWdodG5lc3MoKSA8IDEyODtcbiAgICB9LFxuICAgIGlzTGlnaHQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gIXRoaXMuaXNEYXJrKCk7XG4gICAgfSxcbiAgICBpc1ZhbGlkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29rO1xuICAgIH0sXG4gICAgZ2V0T3JpZ2luYWxJbnB1dDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3JpZ2luYWxJbnB1dDtcbiAgICB9LFxuICAgIGdldEZvcm1hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9mb3JtYXQ7XG4gICAgfSxcbiAgICBnZXRBbHBoYTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hO1xuICAgIH0sXG4gICAgZ2V0QnJpZ2h0bmVzczogZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vaHR0cDovL3d3dy53My5vcmcvVFIvQUVSVCNjb2xvci1jb250cmFzdFxuICAgICAgICB2YXIgcmdiID0gdGhpcy50b1JnYigpO1xuICAgICAgICByZXR1cm4gKHJnYi5yICogMjk5ICsgcmdiLmcgKiA1ODcgKyByZ2IuYiAqIDExNCkgLyAxMDAwO1xuICAgIH0sXG4gICAgZ2V0THVtaW5hbmNlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy9odHRwOi8vd3d3LnczLm9yZy9UUi8yMDA4L1JFQy1XQ0FHMjAtMjAwODEyMTEvI3JlbGF0aXZlbHVtaW5hbmNlZGVmXG4gICAgICAgIHZhciByZ2IgPSB0aGlzLnRvUmdiKCk7XG4gICAgICAgIHZhciBSc1JHQiwgR3NSR0IsIEJzUkdCLCBSLCBHLCBCO1xuICAgICAgICBSc1JHQiA9IHJnYi5yLzI1NTtcbiAgICAgICAgR3NSR0IgPSByZ2IuZy8yNTU7XG4gICAgICAgIEJzUkdCID0gcmdiLmIvMjU1O1xuXG4gICAgICAgIGlmIChSc1JHQiA8PSAwLjAzOTI4KSB7UiA9IFJzUkdCIC8gMTIuOTI7fSBlbHNlIHtSID0gTWF0aC5wb3coKChSc1JHQiArIDAuMDU1KSAvIDEuMDU1KSwgMi40KTt9XG4gICAgICAgIGlmIChHc1JHQiA8PSAwLjAzOTI4KSB7RyA9IEdzUkdCIC8gMTIuOTI7fSBlbHNlIHtHID0gTWF0aC5wb3coKChHc1JHQiArIDAuMDU1KSAvIDEuMDU1KSwgMi40KTt9XG4gICAgICAgIGlmIChCc1JHQiA8PSAwLjAzOTI4KSB7QiA9IEJzUkdCIC8gMTIuOTI7fSBlbHNlIHtCID0gTWF0aC5wb3coKChCc1JHQiArIDAuMDU1KSAvIDEuMDU1KSwgMi40KTt9XG4gICAgICAgIHJldHVybiAoMC4yMTI2ICogUikgKyAoMC43MTUyICogRykgKyAoMC4wNzIyICogQik7XG4gICAgfSxcbiAgICBzZXRBbHBoYTogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgdGhpcy5fYSA9IGJvdW5kQWxwaGEodmFsdWUpO1xuICAgICAgICB0aGlzLl9yb3VuZEEgPSBtYXRoUm91bmQoMTAwKnRoaXMuX2EpIC8gMTAwO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIHRvSHN2OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGhzdiA9IHJnYlRvSHN2KHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IpO1xuICAgICAgICByZXR1cm4geyBoOiBoc3YuaCAqIDM2MCwgczogaHN2LnMsIHY6IGhzdi52LCBhOiB0aGlzLl9hIH07XG4gICAgfSxcbiAgICB0b0hzdlN0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBoc3YgPSByZ2JUb0hzdih0aGlzLl9yLCB0aGlzLl9nLCB0aGlzLl9iKTtcbiAgICAgICAgdmFyIGggPSBtYXRoUm91bmQoaHN2LmggKiAzNjApLCBzID0gbWF0aFJvdW5kKGhzdi5zICogMTAwKSwgdiA9IG1hdGhSb3VuZChoc3YudiAqIDEwMCk7XG4gICAgICAgIHJldHVybiAodGhpcy5fYSA9PSAxKSA/XG4gICAgICAgICAgXCJoc3YoXCIgICsgaCArIFwiLCBcIiArIHMgKyBcIiUsIFwiICsgdiArIFwiJSlcIiA6XG4gICAgICAgICAgXCJoc3ZhKFwiICsgaCArIFwiLCBcIiArIHMgKyBcIiUsIFwiICsgdiArIFwiJSwgXCIrIHRoaXMuX3JvdW5kQSArIFwiKVwiO1xuICAgIH0sXG4gICAgdG9Ic2w6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgaHNsID0gcmdiVG9Ic2wodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYik7XG4gICAgICAgIHJldHVybiB7IGg6IGhzbC5oICogMzYwLCBzOiBoc2wucywgbDogaHNsLmwsIGE6IHRoaXMuX2EgfTtcbiAgICB9LFxuICAgIHRvSHNsU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGhzbCA9IHJnYlRvSHNsKHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IpO1xuICAgICAgICB2YXIgaCA9IG1hdGhSb3VuZChoc2wuaCAqIDM2MCksIHMgPSBtYXRoUm91bmQoaHNsLnMgKiAxMDApLCBsID0gbWF0aFJvdW5kKGhzbC5sICogMTAwKTtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9hID09IDEpID9cbiAgICAgICAgICBcImhzbChcIiAgKyBoICsgXCIsIFwiICsgcyArIFwiJSwgXCIgKyBsICsgXCIlKVwiIDpcbiAgICAgICAgICBcImhzbGEoXCIgKyBoICsgXCIsIFwiICsgcyArIFwiJSwgXCIgKyBsICsgXCIlLCBcIisgdGhpcy5fcm91bmRBICsgXCIpXCI7XG4gICAgfSxcbiAgICB0b0hleDogZnVuY3Rpb24oYWxsb3czQ2hhcikge1xuICAgICAgICByZXR1cm4gcmdiVG9IZXgodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYiwgYWxsb3czQ2hhcik7XG4gICAgfSxcbiAgICB0b0hleFN0cmluZzogZnVuY3Rpb24oYWxsb3czQ2hhcikge1xuICAgICAgICByZXR1cm4gJyMnICsgdGhpcy50b0hleChhbGxvdzNDaGFyKTtcbiAgICB9LFxuICAgIHRvSGV4ODogZnVuY3Rpb24oYWxsb3c0Q2hhcikge1xuICAgICAgICByZXR1cm4gcmdiYVRvSGV4KHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IsIHRoaXMuX2EsIGFsbG93NENoYXIpO1xuICAgIH0sXG4gICAgdG9IZXg4U3RyaW5nOiBmdW5jdGlvbihhbGxvdzRDaGFyKSB7XG4gICAgICAgIHJldHVybiAnIycgKyB0aGlzLnRvSGV4OChhbGxvdzRDaGFyKTtcbiAgICB9LFxuICAgIHRvUmdiOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHsgcjogbWF0aFJvdW5kKHRoaXMuX3IpLCBnOiBtYXRoUm91bmQodGhpcy5fZyksIGI6IG1hdGhSb3VuZCh0aGlzLl9iKSwgYTogdGhpcy5fYSB9O1xuICAgIH0sXG4gICAgdG9SZ2JTdHJpbmc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gKHRoaXMuX2EgPT0gMSkgP1xuICAgICAgICAgIFwicmdiKFwiICArIG1hdGhSb3VuZCh0aGlzLl9yKSArIFwiLCBcIiArIG1hdGhSb3VuZCh0aGlzLl9nKSArIFwiLCBcIiArIG1hdGhSb3VuZCh0aGlzLl9iKSArIFwiKVwiIDpcbiAgICAgICAgICBcInJnYmEoXCIgKyBtYXRoUm91bmQodGhpcy5fcikgKyBcIiwgXCIgKyBtYXRoUm91bmQodGhpcy5fZykgKyBcIiwgXCIgKyBtYXRoUm91bmQodGhpcy5fYikgKyBcIiwgXCIgKyB0aGlzLl9yb3VuZEEgKyBcIilcIjtcbiAgICB9LFxuICAgIHRvUGVyY2VudGFnZVJnYjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB7IHI6IG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX3IsIDI1NSkgKiAxMDApICsgXCIlXCIsIGc6IG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX2csIDI1NSkgKiAxMDApICsgXCIlXCIsIGI6IG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX2IsIDI1NSkgKiAxMDApICsgXCIlXCIsIGE6IHRoaXMuX2EgfTtcbiAgICB9LFxuICAgIHRvUGVyY2VudGFnZVJnYlN0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5fYSA9PSAxKSA/XG4gICAgICAgICAgXCJyZ2IoXCIgICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fciwgMjU1KSAqIDEwMCkgKyBcIiUsIFwiICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fZywgMjU1KSAqIDEwMCkgKyBcIiUsIFwiICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fYiwgMjU1KSAqIDEwMCkgKyBcIiUpXCIgOlxuICAgICAgICAgIFwicmdiYShcIiArIG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX3IsIDI1NSkgKiAxMDApICsgXCIlLCBcIiArIG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX2csIDI1NSkgKiAxMDApICsgXCIlLCBcIiArIG1hdGhSb3VuZChib3VuZDAxKHRoaXMuX2IsIDI1NSkgKiAxMDApICsgXCIlLCBcIiArIHRoaXMuX3JvdW5kQSArIFwiKVwiO1xuICAgIH0sXG4gICAgdG9OYW1lOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX2EgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBcInRyYW5zcGFyZW50XCI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fYSA8IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBoZXhOYW1lc1tyZ2JUb0hleCh0aGlzLl9yLCB0aGlzLl9nLCB0aGlzLl9iLCB0cnVlKV0gfHwgZmFsc2U7XG4gICAgfSxcbiAgICB0b0ZpbHRlcjogZnVuY3Rpb24oc2Vjb25kQ29sb3IpIHtcbiAgICAgICAgdmFyIGhleDhTdHJpbmcgPSAnIycgKyByZ2JhVG9BcmdiSGV4KHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IsIHRoaXMuX2EpO1xuICAgICAgICB2YXIgc2Vjb25kSGV4OFN0cmluZyA9IGhleDhTdHJpbmc7XG4gICAgICAgIHZhciBncmFkaWVudFR5cGUgPSB0aGlzLl9ncmFkaWVudFR5cGUgPyBcIkdyYWRpZW50VHlwZSA9IDEsIFwiIDogXCJcIjtcblxuICAgICAgICBpZiAoc2Vjb25kQ29sb3IpIHtcbiAgICAgICAgICAgIHZhciBzID0gdGlueWNvbG9yKHNlY29uZENvbG9yKTtcbiAgICAgICAgICAgIHNlY29uZEhleDhTdHJpbmcgPSAnIycgKyByZ2JhVG9BcmdiSGV4KHMuX3IsIHMuX2csIHMuX2IsIHMuX2EpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFwicHJvZ2lkOkRYSW1hZ2VUcmFuc2Zvcm0uTWljcm9zb2Z0LmdyYWRpZW50KFwiK2dyYWRpZW50VHlwZStcInN0YXJ0Q29sb3JzdHI9XCIraGV4OFN0cmluZytcIixlbmRDb2xvcnN0cj1cIitzZWNvbmRIZXg4U3RyaW5nK1wiKVwiO1xuICAgIH0sXG4gICAgdG9TdHJpbmc6IGZ1bmN0aW9uKGZvcm1hdCkge1xuICAgICAgICB2YXIgZm9ybWF0U2V0ID0gISFmb3JtYXQ7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdCB8fCB0aGlzLl9mb3JtYXQ7XG5cbiAgICAgICAgdmFyIGZvcm1hdHRlZFN0cmluZyA9IGZhbHNlO1xuICAgICAgICB2YXIgaGFzQWxwaGEgPSB0aGlzLl9hIDwgMSAmJiB0aGlzLl9hID49IDA7XG4gICAgICAgIHZhciBuZWVkc0FscGhhRm9ybWF0ID0gIWZvcm1hdFNldCAmJiBoYXNBbHBoYSAmJiAoZm9ybWF0ID09PSBcImhleFwiIHx8IGZvcm1hdCA9PT0gXCJoZXg2XCIgfHwgZm9ybWF0ID09PSBcImhleDNcIiB8fCBmb3JtYXQgPT09IFwiaGV4NFwiIHx8IGZvcm1hdCA9PT0gXCJoZXg4XCIgfHwgZm9ybWF0ID09PSBcIm5hbWVcIik7XG5cbiAgICAgICAgaWYgKG5lZWRzQWxwaGFGb3JtYXQpIHtcbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgXCJ0cmFuc3BhcmVudFwiLCBhbGwgb3RoZXIgbm9uLWFscGhhIGZvcm1hdHNcbiAgICAgICAgICAgIC8vIHdpbGwgcmV0dXJuIHJnYmEgd2hlbiB0aGVyZSBpcyB0cmFuc3BhcmVuY3kuXG4gICAgICAgICAgICBpZiAoZm9ybWF0ID09PSBcIm5hbWVcIiAmJiB0aGlzLl9hID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9OYW1lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b1JnYlN0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwicmdiXCIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0cmluZyA9IHRoaXMudG9SZ2JTdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcInByZ2JcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b1BlcmNlbnRhZ2VSZ2JTdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcImhleFwiIHx8IGZvcm1hdCA9PT0gXCJoZXg2XCIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0cmluZyA9IHRoaXMudG9IZXhTdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcImhleDNcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hleFN0cmluZyh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcImhleDRcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hleDhTdHJpbmcodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gXCJoZXg4XCIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0cmluZyA9IHRoaXMudG9IZXg4U3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gXCJuYW1lXCIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0cmluZyA9IHRoaXMudG9OYW1lKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gXCJoc2xcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hzbFN0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwiaHN2XCIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0cmluZyA9IHRoaXMudG9Ic3ZTdHJpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXR0ZWRTdHJpbmcgfHwgdGhpcy50b0hleFN0cmluZygpO1xuICAgIH0sXG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGlueWNvbG9yKHRoaXMudG9TdHJpbmcoKSk7XG4gICAgfSxcblxuICAgIF9hcHBseU1vZGlmaWNhdGlvbjogZnVuY3Rpb24oZm4sIGFyZ3MpIHtcbiAgICAgICAgdmFyIGNvbG9yID0gZm4uYXBwbHkobnVsbCwgW3RoaXNdLmNvbmNhdChbXS5zbGljZS5jYWxsKGFyZ3MpKSk7XG4gICAgICAgIHRoaXMuX3IgPSBjb2xvci5fcjtcbiAgICAgICAgdGhpcy5fZyA9IGNvbG9yLl9nO1xuICAgICAgICB0aGlzLl9iID0gY29sb3IuX2I7XG4gICAgICAgIHRoaXMuc2V0QWxwaGEoY29sb3IuX2EpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGxpZ2h0ZW46IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24obGlnaHRlbiwgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIGJyaWdodGVuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5TW9kaWZpY2F0aW9uKGJyaWdodGVuLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgZGFya2VuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5TW9kaWZpY2F0aW9uKGRhcmtlbiwgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIGRlc2F0dXJhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oZGVzYXR1cmF0ZSwgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNhdHVyYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5TW9kaWZpY2F0aW9uKHNhdHVyYXRlLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgZ3JleXNjYWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5TW9kaWZpY2F0aW9uKGdyZXlzY2FsZSwgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNwaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oc3BpbiwgYXJndW1lbnRzKTtcbiAgICB9LFxuXG4gICAgX2FwcGx5Q29tYmluYXRpb246IGZ1bmN0aW9uKGZuLCBhcmdzKSB7XG4gICAgICAgIHJldHVybiBmbi5hcHBseShudWxsLCBbdGhpc10uY29uY2F0KFtdLnNsaWNlLmNhbGwoYXJncykpKTtcbiAgICB9LFxuICAgIGFuYWxvZ291czogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUNvbWJpbmF0aW9uKGFuYWxvZ291cywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIGNvbXBsZW1lbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlDb21iaW5hdGlvbihjb21wbGVtZW50LCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgbW9ub2Nocm9tYXRpYzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUNvbWJpbmF0aW9uKG1vbm9jaHJvbWF0aWMsIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBzcGxpdGNvbXBsZW1lbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlDb21iaW5hdGlvbihzcGxpdGNvbXBsZW1lbnQsIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICB0cmlhZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUNvbWJpbmF0aW9uKHRyaWFkLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgdGV0cmFkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5Q29tYmluYXRpb24odGV0cmFkLCBhcmd1bWVudHMpO1xuICAgIH1cbn07XG5cbi8vIElmIGlucHV0IGlzIGFuIG9iamVjdCwgZm9yY2UgMSBpbnRvIFwiMS4wXCIgdG8gaGFuZGxlIHJhdGlvcyBwcm9wZXJseVxuLy8gU3RyaW5nIGlucHV0IHJlcXVpcmVzIFwiMS4wXCIgYXMgaW5wdXQsIHNvIDEgd2lsbCBiZSB0cmVhdGVkIGFzIDFcbnRpbnljb2xvci5mcm9tUmF0aW8gPSBmdW5jdGlvbihjb2xvciwgb3B0cykge1xuICAgIGlmICh0eXBlb2YgY29sb3IgPT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgbmV3Q29sb3IgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSBpbiBjb2xvcikge1xuICAgICAgICAgICAgaWYgKGNvbG9yLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbG9yW2ldID0gY29sb3JbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdDb2xvcltpXSA9IGNvbnZlcnRUb1BlcmNlbnRhZ2UoY29sb3JbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb2xvciA9IG5ld0NvbG9yO1xuICAgIH1cblxuICAgIHJldHVybiB0aW55Y29sb3IoY29sb3IsIG9wdHMpO1xufTtcblxuLy8gR2l2ZW4gYSBzdHJpbmcgb3Igb2JqZWN0LCBjb252ZXJ0IHRoYXQgaW5wdXQgdG8gUkdCXG4vLyBQb3NzaWJsZSBzdHJpbmcgaW5wdXRzOlxuLy9cbi8vICAgICBcInJlZFwiXG4vLyAgICAgXCIjZjAwXCIgb3IgXCJmMDBcIlxuLy8gICAgIFwiI2ZmMDAwMFwiIG9yIFwiZmYwMDAwXCJcbi8vICAgICBcIiNmZjAwMDAwMFwiIG9yIFwiZmYwMDAwMDBcIlxuLy8gICAgIFwicmdiIDI1NSAwIDBcIiBvciBcInJnYiAoMjU1LCAwLCAwKVwiXG4vLyAgICAgXCJyZ2IgMS4wIDAgMFwiIG9yIFwicmdiICgxLCAwLCAwKVwiXG4vLyAgICAgXCJyZ2JhICgyNTUsIDAsIDAsIDEpXCIgb3IgXCJyZ2JhIDI1NSwgMCwgMCwgMVwiXG4vLyAgICAgXCJyZ2JhICgxLjAsIDAsIDAsIDEpXCIgb3IgXCJyZ2JhIDEuMCwgMCwgMCwgMVwiXG4vLyAgICAgXCJoc2woMCwgMTAwJSwgNTAlKVwiIG9yIFwiaHNsIDAgMTAwJSA1MCVcIlxuLy8gICAgIFwiaHNsYSgwLCAxMDAlLCA1MCUsIDEpXCIgb3IgXCJoc2xhIDAgMTAwJSA1MCUsIDFcIlxuLy8gICAgIFwiaHN2KDAsIDEwMCUsIDEwMCUpXCIgb3IgXCJoc3YgMCAxMDAlIDEwMCVcIlxuLy9cbmZ1bmN0aW9uIGlucHV0VG9SR0IoY29sb3IpIHtcblxuICAgIHZhciByZ2IgPSB7IHI6IDAsIGc6IDAsIGI6IDAgfTtcbiAgICB2YXIgYSA9IDE7XG4gICAgdmFyIHMgPSBudWxsO1xuICAgIHZhciB2ID0gbnVsbDtcbiAgICB2YXIgbCA9IG51bGw7XG4gICAgdmFyIG9rID0gZmFsc2U7XG4gICAgdmFyIGZvcm1hdCA9IGZhbHNlO1xuXG4gICAgaWYgKHR5cGVvZiBjb2xvciA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGNvbG9yID0gc3RyaW5nSW5wdXRUb09iamVjdChjb2xvcik7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjb2xvciA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIGlmIChpc1ZhbGlkQ1NTVW5pdChjb2xvci5yKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci5nKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci5iKSkge1xuICAgICAgICAgICAgcmdiID0gcmdiVG9SZ2IoY29sb3IuciwgY29sb3IuZywgY29sb3IuYik7XG4gICAgICAgICAgICBvayA9IHRydWU7XG4gICAgICAgICAgICBmb3JtYXQgPSBTdHJpbmcoY29sb3Iucikuc3Vic3RyKC0xKSA9PT0gXCIlXCIgPyBcInByZ2JcIiA6IFwicmdiXCI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNWYWxpZENTU1VuaXQoY29sb3IuaCkgJiYgaXNWYWxpZENTU1VuaXQoY29sb3IucykgJiYgaXNWYWxpZENTU1VuaXQoY29sb3IudikpIHtcbiAgICAgICAgICAgIHMgPSBjb252ZXJ0VG9QZXJjZW50YWdlKGNvbG9yLnMpO1xuICAgICAgICAgICAgdiA9IGNvbnZlcnRUb1BlcmNlbnRhZ2UoY29sb3Iudik7XG4gICAgICAgICAgICByZ2IgPSBoc3ZUb1JnYihjb2xvci5oLCBzLCB2KTtcbiAgICAgICAgICAgIG9rID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcm1hdCA9IFwiaHN2XCI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNWYWxpZENTU1VuaXQoY29sb3IuaCkgJiYgaXNWYWxpZENTU1VuaXQoY29sb3IucykgJiYgaXNWYWxpZENTU1VuaXQoY29sb3IubCkpIHtcbiAgICAgICAgICAgIHMgPSBjb252ZXJ0VG9QZXJjZW50YWdlKGNvbG9yLnMpO1xuICAgICAgICAgICAgbCA9IGNvbnZlcnRUb1BlcmNlbnRhZ2UoY29sb3IubCk7XG4gICAgICAgICAgICByZ2IgPSBoc2xUb1JnYihjb2xvci5oLCBzLCBsKTtcbiAgICAgICAgICAgIG9rID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcm1hdCA9IFwiaHNsXCI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29sb3IuaGFzT3duUHJvcGVydHkoXCJhXCIpKSB7XG4gICAgICAgICAgICBhID0gY29sb3IuYTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGEgPSBib3VuZEFscGhhKGEpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgb2s6IG9rLFxuICAgICAgICBmb3JtYXQ6IGNvbG9yLmZvcm1hdCB8fCBmb3JtYXQsXG4gICAgICAgIHI6IG1hdGhNaW4oMjU1LCBtYXRoTWF4KHJnYi5yLCAwKSksXG4gICAgICAgIGc6IG1hdGhNaW4oMjU1LCBtYXRoTWF4KHJnYi5nLCAwKSksXG4gICAgICAgIGI6IG1hdGhNaW4oMjU1LCBtYXRoTWF4KHJnYi5iLCAwKSksXG4gICAgICAgIGE6IGFcbiAgICB9O1xufVxuXG5cbi8vIENvbnZlcnNpb24gRnVuY3Rpb25zXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBgcmdiVG9Ic2xgLCBgcmdiVG9Ic3ZgLCBgaHNsVG9SZ2JgLCBgaHN2VG9SZ2JgIG1vZGlmaWVkIGZyb206XG4vLyA8aHR0cDovL21qaWphY2tzb24uY29tLzIwMDgvMDIvcmdiLXRvLWhzbC1hbmQtcmdiLXRvLWhzdi1jb2xvci1tb2RlbC1jb252ZXJzaW9uLWFsZ29yaXRobXMtaW4tamF2YXNjcmlwdD5cblxuLy8gYHJnYlRvUmdiYFxuLy8gSGFuZGxlIGJvdW5kcyAvIHBlcmNlbnRhZ2UgY2hlY2tpbmcgdG8gY29uZm9ybSB0byBDU1MgY29sb3Igc3BlY1xuLy8gPGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtY29sb3IvPlxuLy8gKkFzc3VtZXM6KiByLCBnLCBiIGluIFswLCAyNTVdIG9yIFswLCAxXVxuLy8gKlJldHVybnM6KiB7IHIsIGcsIGIgfSBpbiBbMCwgMjU1XVxuZnVuY3Rpb24gcmdiVG9SZ2IociwgZywgYil7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcjogYm91bmQwMShyLCAyNTUpICogMjU1LFxuICAgICAgICBnOiBib3VuZDAxKGcsIDI1NSkgKiAyNTUsXG4gICAgICAgIGI6IGJvdW5kMDEoYiwgMjU1KSAqIDI1NVxuICAgIH07XG59XG5cbi8vIGByZ2JUb0hzbGBcbi8vIENvbnZlcnRzIGFuIFJHQiBjb2xvciB2YWx1ZSB0byBIU0wuXG4vLyAqQXNzdW1lczoqIHIsIGcsIGFuZCBiIGFyZSBjb250YWluZWQgaW4gWzAsIDI1NV0gb3IgWzAsIDFdXG4vLyAqUmV0dXJuczoqIHsgaCwgcywgbCB9IGluIFswLDFdXG5mdW5jdGlvbiByZ2JUb0hzbChyLCBnLCBiKSB7XG5cbiAgICByID0gYm91bmQwMShyLCAyNTUpO1xuICAgIGcgPSBib3VuZDAxKGcsIDI1NSk7XG4gICAgYiA9IGJvdW5kMDEoYiwgMjU1KTtcblxuICAgIHZhciBtYXggPSBtYXRoTWF4KHIsIGcsIGIpLCBtaW4gPSBtYXRoTWluKHIsIGcsIGIpO1xuICAgIHZhciBoLCBzLCBsID0gKG1heCArIG1pbikgLyAyO1xuXG4gICAgaWYobWF4ID09IG1pbikge1xuICAgICAgICBoID0gcyA9IDA7IC8vIGFjaHJvbWF0aWNcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBkID0gbWF4IC0gbWluO1xuICAgICAgICBzID0gbCA+IDAuNSA/IGQgLyAoMiAtIG1heCAtIG1pbikgOiBkIC8gKG1heCArIG1pbik7XG4gICAgICAgIHN3aXRjaChtYXgpIHtcbiAgICAgICAgICAgIGNhc2UgcjogaCA9IChnIC0gYikgLyBkICsgKGcgPCBiID8gNiA6IDApOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgZzogaCA9IChiIC0gcikgLyBkICsgMjsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGI6IGggPSAociAtIGcpIC8gZCArIDQ7IGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgaCAvPSA2O1xuICAgIH1cblxuICAgIHJldHVybiB7IGg6IGgsIHM6IHMsIGw6IGwgfTtcbn1cblxuLy8gYGhzbFRvUmdiYFxuLy8gQ29udmVydHMgYW4gSFNMIGNvbG9yIHZhbHVlIHRvIFJHQi5cbi8vICpBc3N1bWVzOiogaCBpcyBjb250YWluZWQgaW4gWzAsIDFdIG9yIFswLCAzNjBdIGFuZCBzIGFuZCBsIGFyZSBjb250YWluZWQgWzAsIDFdIG9yIFswLCAxMDBdXG4vLyAqUmV0dXJuczoqIHsgciwgZywgYiB9IGluIHRoZSBzZXQgWzAsIDI1NV1cbmZ1bmN0aW9uIGhzbFRvUmdiKGgsIHMsIGwpIHtcbiAgICB2YXIgciwgZywgYjtcblxuICAgIGggPSBib3VuZDAxKGgsIDM2MCk7XG4gICAgcyA9IGJvdW5kMDEocywgMTAwKTtcbiAgICBsID0gYm91bmQwMShsLCAxMDApO1xuXG4gICAgZnVuY3Rpb24gaHVlMnJnYihwLCBxLCB0KSB7XG4gICAgICAgIGlmKHQgPCAwKSB0ICs9IDE7XG4gICAgICAgIGlmKHQgPiAxKSB0IC09IDE7XG4gICAgICAgIGlmKHQgPCAxLzYpIHJldHVybiBwICsgKHEgLSBwKSAqIDYgKiB0O1xuICAgICAgICBpZih0IDwgMS8yKSByZXR1cm4gcTtcbiAgICAgICAgaWYodCA8IDIvMykgcmV0dXJuIHAgKyAocSAtIHApICogKDIvMyAtIHQpICogNjtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgaWYocyA9PT0gMCkge1xuICAgICAgICByID0gZyA9IGIgPSBsOyAvLyBhY2hyb21hdGljXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgcSA9IGwgPCAwLjUgPyBsICogKDEgKyBzKSA6IGwgKyBzIC0gbCAqIHM7XG4gICAgICAgIHZhciBwID0gMiAqIGwgLSBxO1xuICAgICAgICByID0gaHVlMnJnYihwLCBxLCBoICsgMS8zKTtcbiAgICAgICAgZyA9IGh1ZTJyZ2IocCwgcSwgaCk7XG4gICAgICAgIGIgPSBodWUycmdiKHAsIHEsIGggLSAxLzMpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHI6IHIgKiAyNTUsIGc6IGcgKiAyNTUsIGI6IGIgKiAyNTUgfTtcbn1cblxuLy8gYHJnYlRvSHN2YFxuLy8gQ29udmVydHMgYW4gUkdCIGNvbG9yIHZhbHVlIHRvIEhTVlxuLy8gKkFzc3VtZXM6KiByLCBnLCBhbmQgYiBhcmUgY29udGFpbmVkIGluIHRoZSBzZXQgWzAsIDI1NV0gb3IgWzAsIDFdXG4vLyAqUmV0dXJuczoqIHsgaCwgcywgdiB9IGluIFswLDFdXG5mdW5jdGlvbiByZ2JUb0hzdihyLCBnLCBiKSB7XG5cbiAgICByID0gYm91bmQwMShyLCAyNTUpO1xuICAgIGcgPSBib3VuZDAxKGcsIDI1NSk7XG4gICAgYiA9IGJvdW5kMDEoYiwgMjU1KTtcblxuICAgIHZhciBtYXggPSBtYXRoTWF4KHIsIGcsIGIpLCBtaW4gPSBtYXRoTWluKHIsIGcsIGIpO1xuICAgIHZhciBoLCBzLCB2ID0gbWF4O1xuXG4gICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgcyA9IG1heCA9PT0gMCA/IDAgOiBkIC8gbWF4O1xuXG4gICAgaWYobWF4ID09IG1pbikge1xuICAgICAgICBoID0gMDsgLy8gYWNocm9tYXRpY1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc3dpdGNoKG1heCkge1xuICAgICAgICAgICAgY2FzZSByOiBoID0gKGcgLSBiKSAvIGQgKyAoZyA8IGIgPyA2IDogMCk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBnOiBoID0gKGIgLSByKSAvIGQgKyAyOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgYjogaCA9IChyIC0gZykgLyBkICsgNDsgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaCAvPSA2O1xuICAgIH1cbiAgICByZXR1cm4geyBoOiBoLCBzOiBzLCB2OiB2IH07XG59XG5cbi8vIGBoc3ZUb1JnYmBcbi8vIENvbnZlcnRzIGFuIEhTViBjb2xvciB2YWx1ZSB0byBSR0IuXG4vLyAqQXNzdW1lczoqIGggaXMgY29udGFpbmVkIGluIFswLCAxXSBvciBbMCwgMzYwXSBhbmQgcyBhbmQgdiBhcmUgY29udGFpbmVkIGluIFswLCAxXSBvciBbMCwgMTAwXVxuLy8gKlJldHVybnM6KiB7IHIsIGcsIGIgfSBpbiB0aGUgc2V0IFswLCAyNTVdXG4gZnVuY3Rpb24gaHN2VG9SZ2IoaCwgcywgdikge1xuXG4gICAgaCA9IGJvdW5kMDEoaCwgMzYwKSAqIDY7XG4gICAgcyA9IGJvdW5kMDEocywgMTAwKTtcbiAgICB2ID0gYm91bmQwMSh2LCAxMDApO1xuXG4gICAgdmFyIGkgPSBNYXRoLmZsb29yKGgpLFxuICAgICAgICBmID0gaCAtIGksXG4gICAgICAgIHAgPSB2ICogKDEgLSBzKSxcbiAgICAgICAgcSA9IHYgKiAoMSAtIGYgKiBzKSxcbiAgICAgICAgdCA9IHYgKiAoMSAtICgxIC0gZikgKiBzKSxcbiAgICAgICAgbW9kID0gaSAlIDYsXG4gICAgICAgIHIgPSBbdiwgcSwgcCwgcCwgdCwgdl1bbW9kXSxcbiAgICAgICAgZyA9IFt0LCB2LCB2LCBxLCBwLCBwXVttb2RdLFxuICAgICAgICBiID0gW3AsIHAsIHQsIHYsIHYsIHFdW21vZF07XG5cbiAgICByZXR1cm4geyByOiByICogMjU1LCBnOiBnICogMjU1LCBiOiBiICogMjU1IH07XG59XG5cbi8vIGByZ2JUb0hleGBcbi8vIENvbnZlcnRzIGFuIFJHQiBjb2xvciB0byBoZXhcbi8vIEFzc3VtZXMgciwgZywgYW5kIGIgYXJlIGNvbnRhaW5lZCBpbiB0aGUgc2V0IFswLCAyNTVdXG4vLyBSZXR1cm5zIGEgMyBvciA2IGNoYXJhY3RlciBoZXhcbmZ1bmN0aW9uIHJnYlRvSGV4KHIsIGcsIGIsIGFsbG93M0NoYXIpIHtcblxuICAgIHZhciBoZXggPSBbXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKHIpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGcpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGIpLnRvU3RyaW5nKDE2KSlcbiAgICBdO1xuXG4gICAgLy8gUmV0dXJuIGEgMyBjaGFyYWN0ZXIgaGV4IGlmIHBvc3NpYmxlXG4gICAgaWYgKGFsbG93M0NoYXIgJiYgaGV4WzBdLmNoYXJBdCgwKSA9PSBoZXhbMF0uY2hhckF0KDEpICYmIGhleFsxXS5jaGFyQXQoMCkgPT0gaGV4WzFdLmNoYXJBdCgxKSAmJiBoZXhbMl0uY2hhckF0KDApID09IGhleFsyXS5jaGFyQXQoMSkpIHtcbiAgICAgICAgcmV0dXJuIGhleFswXS5jaGFyQXQoMCkgKyBoZXhbMV0uY2hhckF0KDApICsgaGV4WzJdLmNoYXJBdCgwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaGV4LmpvaW4oXCJcIik7XG59XG5cbi8vIGByZ2JhVG9IZXhgXG4vLyBDb252ZXJ0cyBhbiBSR0JBIGNvbG9yIHBsdXMgYWxwaGEgdHJhbnNwYXJlbmN5IHRvIGhleFxuLy8gQXNzdW1lcyByLCBnLCBiIGFyZSBjb250YWluZWQgaW4gdGhlIHNldCBbMCwgMjU1XSBhbmRcbi8vIGEgaW4gWzAsIDFdLiBSZXR1cm5zIGEgNCBvciA4IGNoYXJhY3RlciByZ2JhIGhleFxuZnVuY3Rpb24gcmdiYVRvSGV4KHIsIGcsIGIsIGEsIGFsbG93NENoYXIpIHtcblxuICAgIHZhciBoZXggPSBbXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKHIpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGcpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGIpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIoY29udmVydERlY2ltYWxUb0hleChhKSlcbiAgICBdO1xuXG4gICAgLy8gUmV0dXJuIGEgNCBjaGFyYWN0ZXIgaGV4IGlmIHBvc3NpYmxlXG4gICAgaWYgKGFsbG93NENoYXIgJiYgaGV4WzBdLmNoYXJBdCgwKSA9PSBoZXhbMF0uY2hhckF0KDEpICYmIGhleFsxXS5jaGFyQXQoMCkgPT0gaGV4WzFdLmNoYXJBdCgxKSAmJiBoZXhbMl0uY2hhckF0KDApID09IGhleFsyXS5jaGFyQXQoMSkgJiYgaGV4WzNdLmNoYXJBdCgwKSA9PSBoZXhbM10uY2hhckF0KDEpKSB7XG4gICAgICAgIHJldHVybiBoZXhbMF0uY2hhckF0KDApICsgaGV4WzFdLmNoYXJBdCgwKSArIGhleFsyXS5jaGFyQXQoMCkgKyBoZXhbM10uY2hhckF0KDApO1xuICAgIH1cblxuICAgIHJldHVybiBoZXguam9pbihcIlwiKTtcbn1cblxuLy8gYHJnYmFUb0FyZ2JIZXhgXG4vLyBDb252ZXJ0cyBhbiBSR0JBIGNvbG9yIHRvIGFuIEFSR0IgSGV4OCBzdHJpbmdcbi8vIFJhcmVseSB1c2VkLCBidXQgcmVxdWlyZWQgZm9yIFwidG9GaWx0ZXIoKVwiXG5mdW5jdGlvbiByZ2JhVG9BcmdiSGV4KHIsIGcsIGIsIGEpIHtcblxuICAgIHZhciBoZXggPSBbXG4gICAgICAgIHBhZDIoY29udmVydERlY2ltYWxUb0hleChhKSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKHIpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGcpLnRvU3RyaW5nKDE2KSksXG4gICAgICAgIHBhZDIobWF0aFJvdW5kKGIpLnRvU3RyaW5nKDE2KSlcbiAgICBdO1xuXG4gICAgcmV0dXJuIGhleC5qb2luKFwiXCIpO1xufVxuXG4vLyBgZXF1YWxzYFxuLy8gQ2FuIGJlIGNhbGxlZCB3aXRoIGFueSB0aW55Y29sb3IgaW5wdXRcbnRpbnljb2xvci5lcXVhbHMgPSBmdW5jdGlvbiAoY29sb3IxLCBjb2xvcjIpIHtcbiAgICBpZiAoIWNvbG9yMSB8fCAhY29sb3IyKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIHJldHVybiB0aW55Y29sb3IoY29sb3IxKS50b1JnYlN0cmluZygpID09IHRpbnljb2xvcihjb2xvcjIpLnRvUmdiU3RyaW5nKCk7XG59O1xuXG50aW55Y29sb3IucmFuZG9tID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRpbnljb2xvci5mcm9tUmF0aW8oe1xuICAgICAgICByOiBtYXRoUmFuZG9tKCksXG4gICAgICAgIGc6IG1hdGhSYW5kb20oKSxcbiAgICAgICAgYjogbWF0aFJhbmRvbSgpXG4gICAgfSk7XG59O1xuXG5cbi8vIE1vZGlmaWNhdGlvbiBGdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRoYW5rcyB0byBsZXNzLmpzIGZvciBzb21lIG9mIHRoZSBiYXNpY3MgaGVyZVxuLy8gPGh0dHBzOi8vZ2l0aHViLmNvbS9jbG91ZGhlYWQvbGVzcy5qcy9ibG9iL21hc3Rlci9saWIvbGVzcy9mdW5jdGlvbnMuanM+XG5cbmZ1bmN0aW9uIGRlc2F0dXJhdGUoY29sb3IsIGFtb3VudCkge1xuICAgIGFtb3VudCA9IChhbW91bnQgPT09IDApID8gMCA6IChhbW91bnQgfHwgMTApO1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgaHNsLnMgLT0gYW1vdW50IC8gMTAwO1xuICAgIGhzbC5zID0gY2xhbXAwMShoc2wucyk7XG4gICAgcmV0dXJuIHRpbnljb2xvcihoc2wpO1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0ZShjb2xvciwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCAxMCk7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICBoc2wucyArPSBhbW91bnQgLyAxMDA7XG4gICAgaHNsLnMgPSBjbGFtcDAxKGhzbC5zKTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbmZ1bmN0aW9uIGdyZXlzY2FsZShjb2xvcikge1xuICAgIHJldHVybiB0aW55Y29sb3IoY29sb3IpLmRlc2F0dXJhdGUoMTAwKTtcbn1cblxuZnVuY3Rpb24gbGlnaHRlbiAoY29sb3IsIGFtb3VudCkge1xuICAgIGFtb3VudCA9IChhbW91bnQgPT09IDApID8gMCA6IChhbW91bnQgfHwgMTApO1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgaHNsLmwgKz0gYW1vdW50IC8gMTAwO1xuICAgIGhzbC5sID0gY2xhbXAwMShoc2wubCk7XG4gICAgcmV0dXJuIHRpbnljb2xvcihoc2wpO1xufVxuXG5mdW5jdGlvbiBicmlnaHRlbihjb2xvciwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCAxMCk7XG4gICAgdmFyIHJnYiA9IHRpbnljb2xvcihjb2xvcikudG9SZ2IoKTtcbiAgICByZ2IuciA9IG1hdGhNYXgoMCwgbWF0aE1pbigyNTUsIHJnYi5yIC0gbWF0aFJvdW5kKDI1NSAqIC0gKGFtb3VudCAvIDEwMCkpKSk7XG4gICAgcmdiLmcgPSBtYXRoTWF4KDAsIG1hdGhNaW4oMjU1LCByZ2IuZyAtIG1hdGhSb3VuZCgyNTUgKiAtIChhbW91bnQgLyAxMDApKSkpO1xuICAgIHJnYi5iID0gbWF0aE1heCgwLCBtYXRoTWluKDI1NSwgcmdiLmIgLSBtYXRoUm91bmQoMjU1ICogLSAoYW1vdW50IC8gMTAwKSkpKTtcbiAgICByZXR1cm4gdGlueWNvbG9yKHJnYik7XG59XG5cbmZ1bmN0aW9uIGRhcmtlbiAoY29sb3IsIGFtb3VudCkge1xuICAgIGFtb3VudCA9IChhbW91bnQgPT09IDApID8gMCA6IChhbW91bnQgfHwgMTApO1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgaHNsLmwgLT0gYW1vdW50IC8gMTAwO1xuICAgIGhzbC5sID0gY2xhbXAwMShoc2wubCk7XG4gICAgcmV0dXJuIHRpbnljb2xvcihoc2wpO1xufVxuXG4vLyBTcGluIHRha2VzIGEgcG9zaXRpdmUgb3IgbmVnYXRpdmUgYW1vdW50IHdpdGhpbiBbLTM2MCwgMzYwXSBpbmRpY2F0aW5nIHRoZSBjaGFuZ2Ugb2YgaHVlLlxuLy8gVmFsdWVzIG91dHNpZGUgb2YgdGhpcyByYW5nZSB3aWxsIGJlIHdyYXBwZWQgaW50byB0aGlzIHJhbmdlLlxuZnVuY3Rpb24gc3Bpbihjb2xvciwgYW1vdW50KSB7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICB2YXIgaHVlID0gKGhzbC5oICsgYW1vdW50KSAlIDM2MDtcbiAgICBoc2wuaCA9IGh1ZSA8IDAgPyAzNjAgKyBodWUgOiBodWU7XG4gICAgcmV0dXJuIHRpbnljb2xvcihoc2wpO1xufVxuXG4vLyBDb21iaW5hdGlvbiBGdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVGhhbmtzIHRvIGpRdWVyeSB4Q29sb3IgZm9yIHNvbWUgb2YgdGhlIGlkZWFzIGJlaGluZCB0aGVzZVxuLy8gPGh0dHBzOi8vZ2l0aHViLmNvbS9pbmZ1c2lvbi9qUXVlcnkteGNvbG9yL2Jsb2IvbWFzdGVyL2pxdWVyeS54Y29sb3IuanM+XG5cbmZ1bmN0aW9uIGNvbXBsZW1lbnQoY29sb3IpIHtcbiAgICB2YXIgaHNsID0gdGlueWNvbG9yKGNvbG9yKS50b0hzbCgpO1xuICAgIGhzbC5oID0gKGhzbC5oICsgMTgwKSAlIDM2MDtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbmZ1bmN0aW9uIHRyaWFkKGNvbG9yKSB7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICB2YXIgaCA9IGhzbC5oO1xuICAgIHJldHVybiBbXG4gICAgICAgIHRpbnljb2xvcihjb2xvciksXG4gICAgICAgIHRpbnljb2xvcih7IGg6IChoICsgMTIwKSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sIH0pLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDI0MCkgJSAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubCB9KVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIHRldHJhZChjb2xvcikge1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgdmFyIGggPSBoc2wuaDtcbiAgICByZXR1cm4gW1xuICAgICAgICB0aW55Y29sb3IoY29sb3IpLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDkwKSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sIH0pLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDE4MCkgJSAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubCB9KSxcbiAgICAgICAgdGlueWNvbG9yKHsgaDogKGggKyAyNzApICUgMzYwLCBzOiBoc2wucywgbDogaHNsLmwgfSlcbiAgICBdO1xufVxuXG5mdW5jdGlvbiBzcGxpdGNvbXBsZW1lbnQoY29sb3IpIHtcbiAgICB2YXIgaHNsID0gdGlueWNvbG9yKGNvbG9yKS50b0hzbCgpO1xuICAgIHZhciBoID0gaHNsLmg7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgdGlueWNvbG9yKGNvbG9yKSxcbiAgICAgICAgdGlueWNvbG9yKHsgaDogKGggKyA3MikgJSAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubH0pLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDIxNikgJSAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubH0pXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gYW5hbG9nb3VzKGNvbG9yLCByZXN1bHRzLCBzbGljZXMpIHtcbiAgICByZXN1bHRzID0gcmVzdWx0cyB8fCA2O1xuICAgIHNsaWNlcyA9IHNsaWNlcyB8fCAzMDtcblxuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgdmFyIHBhcnQgPSAzNjAgLyBzbGljZXM7XG4gICAgdmFyIHJldCA9IFt0aW55Y29sb3IoY29sb3IpXTtcblxuICAgIGZvciAoaHNsLmggPSAoKGhzbC5oIC0gKHBhcnQgKiByZXN1bHRzID4+IDEpKSArIDcyMCkgJSAzNjA7IC0tcmVzdWx0czsgKSB7XG4gICAgICAgIGhzbC5oID0gKGhzbC5oICsgcGFydCkgJSAzNjA7XG4gICAgICAgIHJldC5wdXNoKHRpbnljb2xvcihoc2wpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gbW9ub2Nocm9tYXRpYyhjb2xvciwgcmVzdWx0cykge1xuICAgIHJlc3VsdHMgPSByZXN1bHRzIHx8IDY7XG4gICAgdmFyIGhzdiA9IHRpbnljb2xvcihjb2xvcikudG9Ic3YoKTtcbiAgICB2YXIgaCA9IGhzdi5oLCBzID0gaHN2LnMsIHYgPSBoc3YudjtcbiAgICB2YXIgcmV0ID0gW107XG4gICAgdmFyIG1vZGlmaWNhdGlvbiA9IDEgLyByZXN1bHRzO1xuXG4gICAgd2hpbGUgKHJlc3VsdHMtLSkge1xuICAgICAgICByZXQucHVzaCh0aW55Y29sb3IoeyBoOiBoLCBzOiBzLCB2OiB2fSkpO1xuICAgICAgICB2ID0gKHYgKyBtb2RpZmljYXRpb24pICUgMTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xufVxuXG4vLyBVdGlsaXR5IEZ1bmN0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbnRpbnljb2xvci5taXggPSBmdW5jdGlvbihjb2xvcjEsIGNvbG9yMiwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCA1MCk7XG5cbiAgICB2YXIgcmdiMSA9IHRpbnljb2xvcihjb2xvcjEpLnRvUmdiKCk7XG4gICAgdmFyIHJnYjIgPSB0aW55Y29sb3IoY29sb3IyKS50b1JnYigpO1xuXG4gICAgdmFyIHAgPSBhbW91bnQgLyAxMDA7XG5cbiAgICB2YXIgcmdiYSA9IHtcbiAgICAgICAgcjogKChyZ2IyLnIgLSByZ2IxLnIpICogcCkgKyByZ2IxLnIsXG4gICAgICAgIGc6ICgocmdiMi5nIC0gcmdiMS5nKSAqIHApICsgcmdiMS5nLFxuICAgICAgICBiOiAoKHJnYjIuYiAtIHJnYjEuYikgKiBwKSArIHJnYjEuYixcbiAgICAgICAgYTogKChyZ2IyLmEgLSByZ2IxLmEpICogcCkgKyByZ2IxLmFcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRpbnljb2xvcihyZ2JhKTtcbn07XG5cblxuLy8gUmVhZGFiaWxpdHkgRnVuY3Rpb25zXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIDxodHRwOi8vd3d3LnczLm9yZy9UUi8yMDA4L1JFQy1XQ0FHMjAtMjAwODEyMTEvI2NvbnRyYXN0LXJhdGlvZGVmIChXQ0FHIFZlcnNpb24gMilcblxuLy8gYGNvbnRyYXN0YFxuLy8gQW5hbHl6ZSB0aGUgMiBjb2xvcnMgYW5kIHJldHVybnMgdGhlIGNvbG9yIGNvbnRyYXN0IGRlZmluZWQgYnkgKFdDQUcgVmVyc2lvbiAyKVxudGlueWNvbG9yLnJlYWRhYmlsaXR5ID0gZnVuY3Rpb24oY29sb3IxLCBjb2xvcjIpIHtcbiAgICB2YXIgYzEgPSB0aW55Y29sb3IoY29sb3IxKTtcbiAgICB2YXIgYzIgPSB0aW55Y29sb3IoY29sb3IyKTtcbiAgICByZXR1cm4gKE1hdGgubWF4KGMxLmdldEx1bWluYW5jZSgpLGMyLmdldEx1bWluYW5jZSgpKSswLjA1KSAvIChNYXRoLm1pbihjMS5nZXRMdW1pbmFuY2UoKSxjMi5nZXRMdW1pbmFuY2UoKSkrMC4wNSk7XG59O1xuXG4vLyBgaXNSZWFkYWJsZWBcbi8vIEVuc3VyZSB0aGF0IGZvcmVncm91bmQgYW5kIGJhY2tncm91bmQgY29sb3IgY29tYmluYXRpb25zIG1lZXQgV0NBRzIgZ3VpZGVsaW5lcy5cbi8vIFRoZSB0aGlyZCBhcmd1bWVudCBpcyBhbiBvcHRpb25hbCBPYmplY3QuXG4vLyAgICAgIHRoZSAnbGV2ZWwnIHByb3BlcnR5IHN0YXRlcyAnQUEnIG9yICdBQUEnIC0gaWYgbWlzc2luZyBvciBpbnZhbGlkLCBpdCBkZWZhdWx0cyB0byAnQUEnO1xuLy8gICAgICB0aGUgJ3NpemUnIHByb3BlcnR5IHN0YXRlcyAnbGFyZ2UnIG9yICdzbWFsbCcgLSBpZiBtaXNzaW5nIG9yIGludmFsaWQsIGl0IGRlZmF1bHRzIHRvICdzbWFsbCcuXG4vLyBJZiB0aGUgZW50aXJlIG9iamVjdCBpcyBhYnNlbnQsIGlzUmVhZGFibGUgZGVmYXVsdHMgdG8ge2xldmVsOlwiQUFcIixzaXplOlwic21hbGxcIn0uXG5cbi8vICpFeGFtcGxlKlxuLy8gICAgdGlueWNvbG9yLmlzUmVhZGFibGUoXCIjMDAwXCIsIFwiIzExMVwiKSA9PiBmYWxzZVxuLy8gICAgdGlueWNvbG9yLmlzUmVhZGFibGUoXCIjMDAwXCIsIFwiIzExMVwiLHtsZXZlbDpcIkFBXCIsc2l6ZTpcImxhcmdlXCJ9KSA9PiBmYWxzZVxudGlueWNvbG9yLmlzUmVhZGFibGUgPSBmdW5jdGlvbihjb2xvcjEsIGNvbG9yMiwgd2NhZzIpIHtcbiAgICB2YXIgcmVhZGFiaWxpdHkgPSB0aW55Y29sb3IucmVhZGFiaWxpdHkoY29sb3IxLCBjb2xvcjIpO1xuICAgIHZhciB3Y2FnMlBhcm1zLCBvdXQ7XG5cbiAgICBvdXQgPSBmYWxzZTtcblxuICAgIHdjYWcyUGFybXMgPSB2YWxpZGF0ZVdDQUcyUGFybXMod2NhZzIpO1xuICAgIHN3aXRjaCAod2NhZzJQYXJtcy5sZXZlbCArIHdjYWcyUGFybXMuc2l6ZSkge1xuICAgICAgICBjYXNlIFwiQUFzbWFsbFwiOlxuICAgICAgICBjYXNlIFwiQUFBbGFyZ2VcIjpcbiAgICAgICAgICAgIG91dCA9IHJlYWRhYmlsaXR5ID49IDQuNTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQUFsYXJnZVwiOlxuICAgICAgICAgICAgb3V0ID0gcmVhZGFiaWxpdHkgPj0gMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQUFBc21hbGxcIjpcbiAgICAgICAgICAgIG91dCA9IHJlYWRhYmlsaXR5ID49IDc7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcblxufTtcblxuLy8gYG1vc3RSZWFkYWJsZWBcbi8vIEdpdmVuIGEgYmFzZSBjb2xvciBhbmQgYSBsaXN0IG9mIHBvc3NpYmxlIGZvcmVncm91bmQgb3IgYmFja2dyb3VuZFxuLy8gY29sb3JzIGZvciB0aGF0IGJhc2UsIHJldHVybnMgdGhlIG1vc3QgcmVhZGFibGUgY29sb3IuXG4vLyBPcHRpb25hbGx5IHJldHVybnMgQmxhY2sgb3IgV2hpdGUgaWYgdGhlIG1vc3QgcmVhZGFibGUgY29sb3IgaXMgdW5yZWFkYWJsZS5cbi8vICpFeGFtcGxlKlxuLy8gICAgdGlueWNvbG9yLm1vc3RSZWFkYWJsZSh0aW55Y29sb3IubW9zdFJlYWRhYmxlKFwiIzEyM1wiLCBbXCIjMTI0XCIsIFwiIzEyNVwiXSx7aW5jbHVkZUZhbGxiYWNrQ29sb3JzOmZhbHNlfSkudG9IZXhTdHJpbmcoKTsgLy8gXCIjMTEyMjU1XCJcbi8vICAgIHRpbnljb2xvci5tb3N0UmVhZGFibGUodGlueWNvbG9yLm1vc3RSZWFkYWJsZShcIiMxMjNcIiwgW1wiIzEyNFwiLCBcIiMxMjVcIl0se2luY2x1ZGVGYWxsYmFja0NvbG9yczp0cnVlfSkudG9IZXhTdHJpbmcoKTsgIC8vIFwiI2ZmZmZmZlwiXG4vLyAgICB0aW55Y29sb3IubW9zdFJlYWRhYmxlKFwiI2E4MDE1YVwiLCBbXCIjZmFmM2YzXCJdLHtpbmNsdWRlRmFsbGJhY2tDb2xvcnM6dHJ1ZSxsZXZlbDpcIkFBQVwiLHNpemU6XCJsYXJnZVwifSkudG9IZXhTdHJpbmcoKTsgLy8gXCIjZmFmM2YzXCJcbi8vICAgIHRpbnljb2xvci5tb3N0UmVhZGFibGUoXCIjYTgwMTVhXCIsIFtcIiNmYWYzZjNcIl0se2luY2x1ZGVGYWxsYmFja0NvbG9yczp0cnVlLGxldmVsOlwiQUFBXCIsc2l6ZTpcInNtYWxsXCJ9KS50b0hleFN0cmluZygpOyAvLyBcIiNmZmZmZmZcIlxudGlueWNvbG9yLm1vc3RSZWFkYWJsZSA9IGZ1bmN0aW9uKGJhc2VDb2xvciwgY29sb3JMaXN0LCBhcmdzKSB7XG4gICAgdmFyIGJlc3RDb2xvciA9IG51bGw7XG4gICAgdmFyIGJlc3RTY29yZSA9IDA7XG4gICAgdmFyIHJlYWRhYmlsaXR5O1xuICAgIHZhciBpbmNsdWRlRmFsbGJhY2tDb2xvcnMsIGxldmVsLCBzaXplIDtcbiAgICBhcmdzID0gYXJncyB8fCB7fTtcbiAgICBpbmNsdWRlRmFsbGJhY2tDb2xvcnMgPSBhcmdzLmluY2x1ZGVGYWxsYmFja0NvbG9ycyA7XG4gICAgbGV2ZWwgPSBhcmdzLmxldmVsO1xuICAgIHNpemUgPSBhcmdzLnNpemU7XG5cbiAgICBmb3IgKHZhciBpPSAwOyBpIDwgY29sb3JMaXN0Lmxlbmd0aCA7IGkrKykge1xuICAgICAgICByZWFkYWJpbGl0eSA9IHRpbnljb2xvci5yZWFkYWJpbGl0eShiYXNlQ29sb3IsIGNvbG9yTGlzdFtpXSk7XG4gICAgICAgIGlmIChyZWFkYWJpbGl0eSA+IGJlc3RTY29yZSkge1xuICAgICAgICAgICAgYmVzdFNjb3JlID0gcmVhZGFiaWxpdHk7XG4gICAgICAgICAgICBiZXN0Q29sb3IgPSB0aW55Y29sb3IoY29sb3JMaXN0W2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aW55Y29sb3IuaXNSZWFkYWJsZShiYXNlQ29sb3IsIGJlc3RDb2xvciwge1wibGV2ZWxcIjpsZXZlbCxcInNpemVcIjpzaXplfSkgfHwgIWluY2x1ZGVGYWxsYmFja0NvbG9ycykge1xuICAgICAgICByZXR1cm4gYmVzdENvbG9yO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYXJncy5pbmNsdWRlRmFsbGJhY2tDb2xvcnM9ZmFsc2U7XG4gICAgICAgIHJldHVybiB0aW55Y29sb3IubW9zdFJlYWRhYmxlKGJhc2VDb2xvcixbXCIjZmZmXCIsIFwiIzAwMFwiXSxhcmdzKTtcbiAgICB9XG59O1xuXG5cbi8vIEJpZyBMaXN0IG9mIENvbG9yc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyA8aHR0cDovL3d3dy53My5vcmcvVFIvY3NzMy1jb2xvci8jc3ZnLWNvbG9yPlxudmFyIG5hbWVzID0gdGlueWNvbG9yLm5hbWVzID0ge1xuICAgIGFsaWNlYmx1ZTogXCJmMGY4ZmZcIixcbiAgICBhbnRpcXVld2hpdGU6IFwiZmFlYmQ3XCIsXG4gICAgYXF1YTogXCIwZmZcIixcbiAgICBhcXVhbWFyaW5lOiBcIjdmZmZkNFwiLFxuICAgIGF6dXJlOiBcImYwZmZmZlwiLFxuICAgIGJlaWdlOiBcImY1ZjVkY1wiLFxuICAgIGJpc3F1ZTogXCJmZmU0YzRcIixcbiAgICBibGFjazogXCIwMDBcIixcbiAgICBibGFuY2hlZGFsbW9uZDogXCJmZmViY2RcIixcbiAgICBibHVlOiBcIjAwZlwiLFxuICAgIGJsdWV2aW9sZXQ6IFwiOGEyYmUyXCIsXG4gICAgYnJvd246IFwiYTUyYTJhXCIsXG4gICAgYnVybHl3b29kOiBcImRlYjg4N1wiLFxuICAgIGJ1cm50c2llbm5hOiBcImVhN2U1ZFwiLFxuICAgIGNhZGV0Ymx1ZTogXCI1ZjllYTBcIixcbiAgICBjaGFydHJldXNlOiBcIjdmZmYwMFwiLFxuICAgIGNob2NvbGF0ZTogXCJkMjY5MWVcIixcbiAgICBjb3JhbDogXCJmZjdmNTBcIixcbiAgICBjb3JuZmxvd2VyYmx1ZTogXCI2NDk1ZWRcIixcbiAgICBjb3Juc2lsazogXCJmZmY4ZGNcIixcbiAgICBjcmltc29uOiBcImRjMTQzY1wiLFxuICAgIGN5YW46IFwiMGZmXCIsXG4gICAgZGFya2JsdWU6IFwiMDAwMDhiXCIsXG4gICAgZGFya2N5YW46IFwiMDA4YjhiXCIsXG4gICAgZGFya2dvbGRlbnJvZDogXCJiODg2MGJcIixcbiAgICBkYXJrZ3JheTogXCJhOWE5YTlcIixcbiAgICBkYXJrZ3JlZW46IFwiMDA2NDAwXCIsXG4gICAgZGFya2dyZXk6IFwiYTlhOWE5XCIsXG4gICAgZGFya2toYWtpOiBcImJkYjc2YlwiLFxuICAgIGRhcmttYWdlbnRhOiBcIjhiMDA4YlwiLFxuICAgIGRhcmtvbGl2ZWdyZWVuOiBcIjU1NmIyZlwiLFxuICAgIGRhcmtvcmFuZ2U6IFwiZmY4YzAwXCIsXG4gICAgZGFya29yY2hpZDogXCI5OTMyY2NcIixcbiAgICBkYXJrcmVkOiBcIjhiMDAwMFwiLFxuICAgIGRhcmtzYWxtb246IFwiZTk5NjdhXCIsXG4gICAgZGFya3NlYWdyZWVuOiBcIjhmYmM4ZlwiLFxuICAgIGRhcmtzbGF0ZWJsdWU6IFwiNDgzZDhiXCIsXG4gICAgZGFya3NsYXRlZ3JheTogXCIyZjRmNGZcIixcbiAgICBkYXJrc2xhdGVncmV5OiBcIjJmNGY0ZlwiLFxuICAgIGRhcmt0dXJxdW9pc2U6IFwiMDBjZWQxXCIsXG4gICAgZGFya3Zpb2xldDogXCI5NDAwZDNcIixcbiAgICBkZWVwcGluazogXCJmZjE0OTNcIixcbiAgICBkZWVwc2t5Ymx1ZTogXCIwMGJmZmZcIixcbiAgICBkaW1ncmF5OiBcIjY5Njk2OVwiLFxuICAgIGRpbWdyZXk6IFwiNjk2OTY5XCIsXG4gICAgZG9kZ2VyYmx1ZTogXCIxZTkwZmZcIixcbiAgICBmaXJlYnJpY2s6IFwiYjIyMjIyXCIsXG4gICAgZmxvcmFsd2hpdGU6IFwiZmZmYWYwXCIsXG4gICAgZm9yZXN0Z3JlZW46IFwiMjI4YjIyXCIsXG4gICAgZnVjaHNpYTogXCJmMGZcIixcbiAgICBnYWluc2Jvcm86IFwiZGNkY2RjXCIsXG4gICAgZ2hvc3R3aGl0ZTogXCJmOGY4ZmZcIixcbiAgICBnb2xkOiBcImZmZDcwMFwiLFxuICAgIGdvbGRlbnJvZDogXCJkYWE1MjBcIixcbiAgICBncmF5OiBcIjgwODA4MFwiLFxuICAgIGdyZWVuOiBcIjAwODAwMFwiLFxuICAgIGdyZWVueWVsbG93OiBcImFkZmYyZlwiLFxuICAgIGdyZXk6IFwiODA4MDgwXCIsXG4gICAgaG9uZXlkZXc6IFwiZjBmZmYwXCIsXG4gICAgaG90cGluazogXCJmZjY5YjRcIixcbiAgICBpbmRpYW5yZWQ6IFwiY2Q1YzVjXCIsXG4gICAgaW5kaWdvOiBcIjRiMDA4MlwiLFxuICAgIGl2b3J5OiBcImZmZmZmMFwiLFxuICAgIGtoYWtpOiBcImYwZTY4Y1wiLFxuICAgIGxhdmVuZGVyOiBcImU2ZTZmYVwiLFxuICAgIGxhdmVuZGVyYmx1c2g6IFwiZmZmMGY1XCIsXG4gICAgbGF3bmdyZWVuOiBcIjdjZmMwMFwiLFxuICAgIGxlbW9uY2hpZmZvbjogXCJmZmZhY2RcIixcbiAgICBsaWdodGJsdWU6IFwiYWRkOGU2XCIsXG4gICAgbGlnaHRjb3JhbDogXCJmMDgwODBcIixcbiAgICBsaWdodGN5YW46IFwiZTBmZmZmXCIsXG4gICAgbGlnaHRnb2xkZW5yb2R5ZWxsb3c6IFwiZmFmYWQyXCIsXG4gICAgbGlnaHRncmF5OiBcImQzZDNkM1wiLFxuICAgIGxpZ2h0Z3JlZW46IFwiOTBlZTkwXCIsXG4gICAgbGlnaHRncmV5OiBcImQzZDNkM1wiLFxuICAgIGxpZ2h0cGluazogXCJmZmI2YzFcIixcbiAgICBsaWdodHNhbG1vbjogXCJmZmEwN2FcIixcbiAgICBsaWdodHNlYWdyZWVuOiBcIjIwYjJhYVwiLFxuICAgIGxpZ2h0c2t5Ymx1ZTogXCI4N2NlZmFcIixcbiAgICBsaWdodHNsYXRlZ3JheTogXCI3ODlcIixcbiAgICBsaWdodHNsYXRlZ3JleTogXCI3ODlcIixcbiAgICBsaWdodHN0ZWVsYmx1ZTogXCJiMGM0ZGVcIixcbiAgICBsaWdodHllbGxvdzogXCJmZmZmZTBcIixcbiAgICBsaW1lOiBcIjBmMFwiLFxuICAgIGxpbWVncmVlbjogXCIzMmNkMzJcIixcbiAgICBsaW5lbjogXCJmYWYwZTZcIixcbiAgICBtYWdlbnRhOiBcImYwZlwiLFxuICAgIG1hcm9vbjogXCI4MDAwMDBcIixcbiAgICBtZWRpdW1hcXVhbWFyaW5lOiBcIjY2Y2RhYVwiLFxuICAgIG1lZGl1bWJsdWU6IFwiMDAwMGNkXCIsXG4gICAgbWVkaXVtb3JjaGlkOiBcImJhNTVkM1wiLFxuICAgIG1lZGl1bXB1cnBsZTogXCI5MzcwZGJcIixcbiAgICBtZWRpdW1zZWFncmVlbjogXCIzY2IzNzFcIixcbiAgICBtZWRpdW1zbGF0ZWJsdWU6IFwiN2I2OGVlXCIsXG4gICAgbWVkaXVtc3ByaW5nZ3JlZW46IFwiMDBmYTlhXCIsXG4gICAgbWVkaXVtdHVycXVvaXNlOiBcIjQ4ZDFjY1wiLFxuICAgIG1lZGl1bXZpb2xldHJlZDogXCJjNzE1ODVcIixcbiAgICBtaWRuaWdodGJsdWU6IFwiMTkxOTcwXCIsXG4gICAgbWludGNyZWFtOiBcImY1ZmZmYVwiLFxuICAgIG1pc3R5cm9zZTogXCJmZmU0ZTFcIixcbiAgICBtb2NjYXNpbjogXCJmZmU0YjVcIixcbiAgICBuYXZham93aGl0ZTogXCJmZmRlYWRcIixcbiAgICBuYXZ5OiBcIjAwMDA4MFwiLFxuICAgIG9sZGxhY2U6IFwiZmRmNWU2XCIsXG4gICAgb2xpdmU6IFwiODA4MDAwXCIsXG4gICAgb2xpdmVkcmFiOiBcIjZiOGUyM1wiLFxuICAgIG9yYW5nZTogXCJmZmE1MDBcIixcbiAgICBvcmFuZ2VyZWQ6IFwiZmY0NTAwXCIsXG4gICAgb3JjaGlkOiBcImRhNzBkNlwiLFxuICAgIHBhbGVnb2xkZW5yb2Q6IFwiZWVlOGFhXCIsXG4gICAgcGFsZWdyZWVuOiBcIjk4ZmI5OFwiLFxuICAgIHBhbGV0dXJxdW9pc2U6IFwiYWZlZWVlXCIsXG4gICAgcGFsZXZpb2xldHJlZDogXCJkYjcwOTNcIixcbiAgICBwYXBheWF3aGlwOiBcImZmZWZkNVwiLFxuICAgIHBlYWNocHVmZjogXCJmZmRhYjlcIixcbiAgICBwZXJ1OiBcImNkODUzZlwiLFxuICAgIHBpbms6IFwiZmZjMGNiXCIsXG4gICAgcGx1bTogXCJkZGEwZGRcIixcbiAgICBwb3dkZXJibHVlOiBcImIwZTBlNlwiLFxuICAgIHB1cnBsZTogXCI4MDAwODBcIixcbiAgICByZWJlY2NhcHVycGxlOiBcIjY2MzM5OVwiLFxuICAgIHJlZDogXCJmMDBcIixcbiAgICByb3N5YnJvd246IFwiYmM4ZjhmXCIsXG4gICAgcm95YWxibHVlOiBcIjQxNjllMVwiLFxuICAgIHNhZGRsZWJyb3duOiBcIjhiNDUxM1wiLFxuICAgIHNhbG1vbjogXCJmYTgwNzJcIixcbiAgICBzYW5keWJyb3duOiBcImY0YTQ2MFwiLFxuICAgIHNlYWdyZWVuOiBcIjJlOGI1N1wiLFxuICAgIHNlYXNoZWxsOiBcImZmZjVlZVwiLFxuICAgIHNpZW5uYTogXCJhMDUyMmRcIixcbiAgICBzaWx2ZXI6IFwiYzBjMGMwXCIsXG4gICAgc2t5Ymx1ZTogXCI4N2NlZWJcIixcbiAgICBzbGF0ZWJsdWU6IFwiNmE1YWNkXCIsXG4gICAgc2xhdGVncmF5OiBcIjcwODA5MFwiLFxuICAgIHNsYXRlZ3JleTogXCI3MDgwOTBcIixcbiAgICBzbm93OiBcImZmZmFmYVwiLFxuICAgIHNwcmluZ2dyZWVuOiBcIjAwZmY3ZlwiLFxuICAgIHN0ZWVsYmx1ZTogXCI0NjgyYjRcIixcbiAgICB0YW46IFwiZDJiNDhjXCIsXG4gICAgdGVhbDogXCIwMDgwODBcIixcbiAgICB0aGlzdGxlOiBcImQ4YmZkOFwiLFxuICAgIHRvbWF0bzogXCJmZjYzNDdcIixcbiAgICB0dXJxdW9pc2U6IFwiNDBlMGQwXCIsXG4gICAgdmlvbGV0OiBcImVlODJlZVwiLFxuICAgIHdoZWF0OiBcImY1ZGViM1wiLFxuICAgIHdoaXRlOiBcImZmZlwiLFxuICAgIHdoaXRlc21va2U6IFwiZjVmNWY1XCIsXG4gICAgeWVsbG93OiBcImZmMFwiLFxuICAgIHllbGxvd2dyZWVuOiBcIjlhY2QzMlwiXG59O1xuXG4vLyBNYWtlIGl0IGVhc3kgdG8gYWNjZXNzIGNvbG9ycyB2aWEgYGhleE5hbWVzW2hleF1gXG52YXIgaGV4TmFtZXMgPSB0aW55Y29sb3IuaGV4TmFtZXMgPSBmbGlwKG5hbWVzKTtcblxuXG4vLyBVdGlsaXRpZXNcbi8vIC0tLS0tLS0tLVxuXG4vLyBgeyAnbmFtZTEnOiAndmFsMScgfWAgYmVjb21lcyBgeyAndmFsMSc6ICduYW1lMScgfWBcbmZ1bmN0aW9uIGZsaXAobykge1xuICAgIHZhciBmbGlwcGVkID0geyB9O1xuICAgIGZvciAodmFyIGkgaW4gbykge1xuICAgICAgICBpZiAoby5oYXNPd25Qcm9wZXJ0eShpKSkge1xuICAgICAgICAgICAgZmxpcHBlZFtvW2ldXSA9IGk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZsaXBwZWQ7XG59XG5cbi8vIFJldHVybiBhIHZhbGlkIGFscGhhIHZhbHVlIFswLDFdIHdpdGggYWxsIGludmFsaWQgdmFsdWVzIGJlaW5nIHNldCB0byAxXG5mdW5jdGlvbiBib3VuZEFscGhhKGEpIHtcbiAgICBhID0gcGFyc2VGbG9hdChhKTtcblxuICAgIGlmIChpc05hTihhKSB8fCBhIDwgMCB8fCBhID4gMSkge1xuICAgICAgICBhID0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gYTtcbn1cblxuLy8gVGFrZSBpbnB1dCBmcm9tIFswLCBuXSBhbmQgcmV0dXJuIGl0IGFzIFswLCAxXVxuZnVuY3Rpb24gYm91bmQwMShuLCBtYXgpIHtcbiAgICBpZiAoaXNPbmVQb2ludFplcm8obikpIHsgbiA9IFwiMTAwJVwiOyB9XG5cbiAgICB2YXIgcHJvY2Vzc1BlcmNlbnQgPSBpc1BlcmNlbnRhZ2Uobik7XG4gICAgbiA9IG1hdGhNaW4obWF4LCBtYXRoTWF4KDAsIHBhcnNlRmxvYXQobikpKTtcblxuICAgIC8vIEF1dG9tYXRpY2FsbHkgY29udmVydCBwZXJjZW50YWdlIGludG8gbnVtYmVyXG4gICAgaWYgKHByb2Nlc3NQZXJjZW50KSB7XG4gICAgICAgIG4gPSBwYXJzZUludChuICogbWF4LCAxMCkgLyAxMDA7XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIGZsb2F0aW5nIHBvaW50IHJvdW5kaW5nIGVycm9yc1xuICAgIGlmICgoTWF0aC5hYnMobiAtIG1heCkgPCAwLjAwMDAwMSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgLy8gQ29udmVydCBpbnRvIFswLCAxXSByYW5nZSBpZiBpdCBpc24ndCBhbHJlYWR5XG4gICAgcmV0dXJuIChuICUgbWF4KSAvIHBhcnNlRmxvYXQobWF4KTtcbn1cblxuLy8gRm9yY2UgYSBudW1iZXIgYmV0d2VlbiAwIGFuZCAxXG5mdW5jdGlvbiBjbGFtcDAxKHZhbCkge1xuICAgIHJldHVybiBtYXRoTWluKDEsIG1hdGhNYXgoMCwgdmFsKSk7XG59XG5cbi8vIFBhcnNlIGEgYmFzZS0xNiBoZXggdmFsdWUgaW50byBhIGJhc2UtMTAgaW50ZWdlclxuZnVuY3Rpb24gcGFyc2VJbnRGcm9tSGV4KHZhbCkge1xuICAgIHJldHVybiBwYXJzZUludCh2YWwsIDE2KTtcbn1cblxuLy8gTmVlZCB0byBoYW5kbGUgMS4wIGFzIDEwMCUsIHNpbmNlIG9uY2UgaXQgaXMgYSBudW1iZXIsIHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiBpdCBhbmQgMVxuLy8gPGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNzQyMjA3Mi9qYXZhc2NyaXB0LWhvdy10by1kZXRlY3QtbnVtYmVyLWFzLWEtZGVjaW1hbC1pbmNsdWRpbmctMS0wPlxuZnVuY3Rpb24gaXNPbmVQb2ludFplcm8obikge1xuICAgIHJldHVybiB0eXBlb2YgbiA9PSBcInN0cmluZ1wiICYmIG4uaW5kZXhPZignLicpICE9IC0xICYmIHBhcnNlRmxvYXQobikgPT09IDE7XG59XG5cbi8vIENoZWNrIHRvIHNlZSBpZiBzdHJpbmcgcGFzc2VkIGluIGlzIGEgcGVyY2VudGFnZVxuZnVuY3Rpb24gaXNQZXJjZW50YWdlKG4pIHtcbiAgICByZXR1cm4gdHlwZW9mIG4gPT09IFwic3RyaW5nXCIgJiYgbi5pbmRleE9mKCclJykgIT0gLTE7XG59XG5cbi8vIEZvcmNlIGEgaGV4IHZhbHVlIHRvIGhhdmUgMiBjaGFyYWN0ZXJzXG5mdW5jdGlvbiBwYWQyKGMpIHtcbiAgICByZXR1cm4gYy5sZW5ndGggPT0gMSA/ICcwJyArIGMgOiAnJyArIGM7XG59XG5cbi8vIFJlcGxhY2UgYSBkZWNpbWFsIHdpdGggaXQncyBwZXJjZW50YWdlIHZhbHVlXG5mdW5jdGlvbiBjb252ZXJ0VG9QZXJjZW50YWdlKG4pIHtcbiAgICBpZiAobiA8PSAxKSB7XG4gICAgICAgIG4gPSAobiAqIDEwMCkgKyBcIiVcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gbjtcbn1cblxuLy8gQ29udmVydHMgYSBkZWNpbWFsIHRvIGEgaGV4IHZhbHVlXG5mdW5jdGlvbiBjb252ZXJ0RGVjaW1hbFRvSGV4KGQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChwYXJzZUZsb2F0KGQpICogMjU1KS50b1N0cmluZygxNik7XG59XG4vLyBDb252ZXJ0cyBhIGhleCB2YWx1ZSB0byBhIGRlY2ltYWxcbmZ1bmN0aW9uIGNvbnZlcnRIZXhUb0RlY2ltYWwoaCkge1xuICAgIHJldHVybiAocGFyc2VJbnRGcm9tSGV4KGgpIC8gMjU1KTtcbn1cblxudmFyIG1hdGNoZXJzID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgLy8gPGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtdmFsdWVzLyNpbnRlZ2Vycz5cbiAgICB2YXIgQ1NTX0lOVEVHRVIgPSBcIlstXFxcXCtdP1xcXFxkKyU/XCI7XG5cbiAgICAvLyA8aHR0cDovL3d3dy53My5vcmcvVFIvY3NzMy12YWx1ZXMvI251bWJlci12YWx1ZT5cbiAgICB2YXIgQ1NTX05VTUJFUiA9IFwiWy1cXFxcK10/XFxcXGQqXFxcXC5cXFxcZCslP1wiO1xuXG4gICAgLy8gQWxsb3cgcG9zaXRpdmUvbmVnYXRpdmUgaW50ZWdlci9udW1iZXIuICBEb24ndCBjYXB0dXJlIHRoZSBlaXRoZXIvb3IsIGp1c3QgdGhlIGVudGlyZSBvdXRjb21lLlxuICAgIHZhciBDU1NfVU5JVCA9IFwiKD86XCIgKyBDU1NfTlVNQkVSICsgXCIpfCg/OlwiICsgQ1NTX0lOVEVHRVIgKyBcIilcIjtcblxuICAgIC8vIEFjdHVhbCBtYXRjaGluZy5cbiAgICAvLyBQYXJlbnRoZXNlcyBhbmQgY29tbWFzIGFyZSBvcHRpb25hbCwgYnV0IG5vdCByZXF1aXJlZC5cbiAgICAvLyBXaGl0ZXNwYWNlIGNhbiB0YWtlIHRoZSBwbGFjZSBvZiBjb21tYXMgb3Igb3BlbmluZyBwYXJlblxuICAgIHZhciBQRVJNSVNTSVZFX01BVENIMyA9IFwiW1xcXFxzfFxcXFwoXSsoXCIgKyBDU1NfVU5JVCArIFwiKVssfFxcXFxzXSsoXCIgKyBDU1NfVU5JVCArIFwiKVssfFxcXFxzXSsoXCIgKyBDU1NfVU5JVCArIFwiKVxcXFxzKlxcXFwpP1wiO1xuICAgIHZhciBQRVJNSVNTSVZFX01BVENINCA9IFwiW1xcXFxzfFxcXFwoXSsoXCIgKyBDU1NfVU5JVCArIFwiKVssfFxcXFxzXSsoXCIgKyBDU1NfVU5JVCArIFwiKVssfFxcXFxzXSsoXCIgKyBDU1NfVU5JVCArIFwiKVssfFxcXFxzXSsoXCIgKyBDU1NfVU5JVCArIFwiKVxcXFxzKlxcXFwpP1wiO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgQ1NTX1VOSVQ6IG5ldyBSZWdFeHAoQ1NTX1VOSVQpLFxuICAgICAgICByZ2I6IG5ldyBSZWdFeHAoXCJyZ2JcIiArIFBFUk1JU1NJVkVfTUFUQ0gzKSxcbiAgICAgICAgcmdiYTogbmV3IFJlZ0V4cChcInJnYmFcIiArIFBFUk1JU1NJVkVfTUFUQ0g0KSxcbiAgICAgICAgaHNsOiBuZXcgUmVnRXhwKFwiaHNsXCIgKyBQRVJNSVNTSVZFX01BVENIMyksXG4gICAgICAgIGhzbGE6IG5ldyBSZWdFeHAoXCJoc2xhXCIgKyBQRVJNSVNTSVZFX01BVENINCksXG4gICAgICAgIGhzdjogbmV3IFJlZ0V4cChcImhzdlwiICsgUEVSTUlTU0lWRV9NQVRDSDMpLFxuICAgICAgICBoc3ZhOiBuZXcgUmVnRXhwKFwiaHN2YVwiICsgUEVSTUlTU0lWRV9NQVRDSDQpLFxuICAgICAgICBoZXgzOiAvXiM/KFswLTlhLWZBLUZdezF9KShbMC05YS1mQS1GXXsxfSkoWzAtOWEtZkEtRl17MX0pJC8sXG4gICAgICAgIGhleDY6IC9eIz8oWzAtOWEtZkEtRl17Mn0pKFswLTlhLWZBLUZdezJ9KShbMC05YS1mQS1GXXsyfSkkLyxcbiAgICAgICAgaGV4NDogL14jPyhbMC05YS1mQS1GXXsxfSkoWzAtOWEtZkEtRl17MX0pKFswLTlhLWZBLUZdezF9KShbMC05YS1mQS1GXXsxfSkkLyxcbiAgICAgICAgaGV4ODogL14jPyhbMC05YS1mQS1GXXsyfSkoWzAtOWEtZkEtRl17Mn0pKFswLTlhLWZBLUZdezJ9KShbMC05YS1mQS1GXXsyfSkkL1xuICAgIH07XG59KSgpO1xuXG4vLyBgaXNWYWxpZENTU1VuaXRgXG4vLyBUYWtlIGluIGEgc2luZ2xlIHN0cmluZyAvIG51bWJlciBhbmQgY2hlY2sgdG8gc2VlIGlmIGl0IGxvb2tzIGxpa2UgYSBDU1MgdW5pdFxuLy8gKHNlZSBgbWF0Y2hlcnNgIGFib3ZlIGZvciBkZWZpbml0aW9uKS5cbmZ1bmN0aW9uIGlzVmFsaWRDU1NVbml0KGNvbG9yKSB7XG4gICAgcmV0dXJuICEhbWF0Y2hlcnMuQ1NTX1VOSVQuZXhlYyhjb2xvcik7XG59XG5cbi8vIGBzdHJpbmdJbnB1dFRvT2JqZWN0YFxuLy8gUGVybWlzc2l2ZSBzdHJpbmcgcGFyc2luZy4gIFRha2UgaW4gYSBudW1iZXIgb2YgZm9ybWF0cywgYW5kIG91dHB1dCBhbiBvYmplY3Rcbi8vIGJhc2VkIG9uIGRldGVjdGVkIGZvcm1hdC4gIFJldHVybnMgYHsgciwgZywgYiB9YCBvciBgeyBoLCBzLCBsIH1gIG9yIGB7IGgsIHMsIHZ9YFxuZnVuY3Rpb24gc3RyaW5nSW5wdXRUb09iamVjdChjb2xvcikge1xuXG4gICAgY29sb3IgPSBjb2xvci5yZXBsYWNlKHRyaW1MZWZ0LCcnKS5yZXBsYWNlKHRyaW1SaWdodCwgJycpLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFyIG5hbWVkID0gZmFsc2U7XG4gICAgaWYgKG5hbWVzW2NvbG9yXSkge1xuICAgICAgICBjb2xvciA9IG5hbWVzW2NvbG9yXTtcbiAgICAgICAgbmFtZWQgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIGlmIChjb2xvciA9PSAndHJhbnNwYXJlbnQnKSB7XG4gICAgICAgIHJldHVybiB7IHI6IDAsIGc6IDAsIGI6IDAsIGE6IDAsIGZvcm1hdDogXCJuYW1lXCIgfTtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gbWF0Y2ggc3RyaW5nIGlucHV0IHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnMuXG4gICAgLy8gS2VlcCBtb3N0IG9mIHRoZSBudW1iZXIgYm91bmRpbmcgb3V0IG9mIHRoaXMgZnVuY3Rpb24gLSBkb24ndCB3b3JyeSBhYm91dCBbMCwxXSBvciBbMCwxMDBdIG9yIFswLDM2MF1cbiAgICAvLyBKdXN0IHJldHVybiBhbiBvYmplY3QgYW5kIGxldCB0aGUgY29udmVyc2lvbiBmdW5jdGlvbnMgaGFuZGxlIHRoYXQuXG4gICAgLy8gVGhpcyB3YXkgdGhlIHJlc3VsdCB3aWxsIGJlIHRoZSBzYW1lIHdoZXRoZXIgdGhlIHRpbnljb2xvciBpcyBpbml0aWFsaXplZCB3aXRoIHN0cmluZyBvciBvYmplY3QuXG4gICAgdmFyIG1hdGNoO1xuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5yZ2IuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IHI6IG1hdGNoWzFdLCBnOiBtYXRjaFsyXSwgYjogbWF0Y2hbM10gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLnJnYmEuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IHI6IG1hdGNoWzFdLCBnOiBtYXRjaFsyXSwgYjogbWF0Y2hbM10sIGE6IG1hdGNoWzRdIH07XG4gICAgfVxuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5oc2wuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IGg6IG1hdGNoWzFdLCBzOiBtYXRjaFsyXSwgbDogbWF0Y2hbM10gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhzbGEuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IGg6IG1hdGNoWzFdLCBzOiBtYXRjaFsyXSwgbDogbWF0Y2hbM10sIGE6IG1hdGNoWzRdIH07XG4gICAgfVxuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5oc3YuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IGg6IG1hdGNoWzFdLCBzOiBtYXRjaFsyXSwgdjogbWF0Y2hbM10gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhzdmEuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7IGg6IG1hdGNoWzFdLCBzOiBtYXRjaFsyXSwgdjogbWF0Y2hbM10sIGE6IG1hdGNoWzRdIH07XG4gICAgfVxuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5oZXg4LmV4ZWMoY29sb3IpKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcjogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzFdKSxcbiAgICAgICAgICAgIGc6IHBhcnNlSW50RnJvbUhleChtYXRjaFsyXSksXG4gICAgICAgICAgICBiOiBwYXJzZUludEZyb21IZXgobWF0Y2hbM10pLFxuICAgICAgICAgICAgYTogY29udmVydEhleFRvRGVjaW1hbChtYXRjaFs0XSksXG4gICAgICAgICAgICBmb3JtYXQ6IG5hbWVkID8gXCJuYW1lXCIgOiBcImhleDhcIlxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMuaGV4Ni5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHI6IHBhcnNlSW50RnJvbUhleChtYXRjaFsxXSksXG4gICAgICAgICAgICBnOiBwYXJzZUludEZyb21IZXgobWF0Y2hbMl0pLFxuICAgICAgICAgICAgYjogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzNdKSxcbiAgICAgICAgICAgIGZvcm1hdDogbmFtZWQgPyBcIm5hbWVcIiA6IFwiaGV4XCJcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhleDQuZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByOiBwYXJzZUludEZyb21IZXgobWF0Y2hbMV0gKyAnJyArIG1hdGNoWzFdKSxcbiAgICAgICAgICAgIGc6IHBhcnNlSW50RnJvbUhleChtYXRjaFsyXSArICcnICsgbWF0Y2hbMl0pLFxuICAgICAgICAgICAgYjogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzNdICsgJycgKyBtYXRjaFszXSksXG4gICAgICAgICAgICBhOiBjb252ZXJ0SGV4VG9EZWNpbWFsKG1hdGNoWzRdICsgJycgKyBtYXRjaFs0XSksXG4gICAgICAgICAgICBmb3JtYXQ6IG5hbWVkID8gXCJuYW1lXCIgOiBcImhleDhcIlxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMuaGV4My5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHI6IHBhcnNlSW50RnJvbUhleChtYXRjaFsxXSArICcnICsgbWF0Y2hbMV0pLFxuICAgICAgICAgICAgZzogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzJdICsgJycgKyBtYXRjaFsyXSksXG4gICAgICAgICAgICBiOiBwYXJzZUludEZyb21IZXgobWF0Y2hbM10gKyAnJyArIG1hdGNoWzNdKSxcbiAgICAgICAgICAgIGZvcm1hdDogbmFtZWQgPyBcIm5hbWVcIiA6IFwiaGV4XCJcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlV0NBRzJQYXJtcyhwYXJtcykge1xuICAgIC8vIHJldHVybiB2YWxpZCBXQ0FHMiBwYXJtcyBmb3IgaXNSZWFkYWJsZS5cbiAgICAvLyBJZiBpbnB1dCBwYXJtcyBhcmUgaW52YWxpZCwgcmV0dXJuIHtcImxldmVsXCI6XCJBQVwiLCBcInNpemVcIjpcInNtYWxsXCJ9XG4gICAgdmFyIGxldmVsLCBzaXplO1xuICAgIHBhcm1zID0gcGFybXMgfHwge1wibGV2ZWxcIjpcIkFBXCIsIFwic2l6ZVwiOlwic21hbGxcIn07XG4gICAgbGV2ZWwgPSAocGFybXMubGV2ZWwgfHwgXCJBQVwiKS50b1VwcGVyQ2FzZSgpO1xuICAgIHNpemUgPSAocGFybXMuc2l6ZSB8fCBcInNtYWxsXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKGxldmVsICE9PSBcIkFBXCIgJiYgbGV2ZWwgIT09IFwiQUFBXCIpIHtcbiAgICAgICAgbGV2ZWwgPSBcIkFBXCI7XG4gICAgfVxuICAgIGlmIChzaXplICE9PSBcInNtYWxsXCIgJiYgc2l6ZSAhPT0gXCJsYXJnZVwiKSB7XG4gICAgICAgIHNpemUgPSBcInNtYWxsXCI7XG4gICAgfVxuICAgIHJldHVybiB7XCJsZXZlbFwiOmxldmVsLCBcInNpemVcIjpzaXplfTtcbn1cblxuLy8gTm9kZTogRXhwb3J0IGZ1bmN0aW9uXG5pZiAodHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gdGlueWNvbG9yO1xufVxuLy8gQU1EL3JlcXVpcmVqczogRGVmaW5lIHRoZSBtb2R1bGVcbmVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZShmdW5jdGlvbiAoKSB7cmV0dXJuIHRpbnljb2xvcjt9KTtcbn1cbi8vIEJyb3dzZXI6IEV4cG9zZSB0byB3aW5kb3dcbmVsc2Uge1xuICAgIHdpbmRvdy50aW55Y29sb3IgPSB0aW55Y29sb3I7XG59XG5cbn0pKE1hdGgpO1xuIiwiLyogQG1vZHVsZSB0by1mbG9hdDMyICovXHJcblxyXG4ndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZmxvYXQzMlxyXG5tb2R1bGUuZXhwb3J0cy5mbG9hdDMyID1cclxubW9kdWxlLmV4cG9ydHMuZmxvYXQgPSBmbG9hdDMyXHJcbm1vZHVsZS5leHBvcnRzLmZyYWN0MzIgPVxyXG5tb2R1bGUuZXhwb3J0cy5mcmFjdCA9IGZyYWN0MzJcclxuXHJcbi8vIHJldHVybiBmcmFjdGlvbmFsIHBhcnQgb2YgZmxvYXQzMiBhcnJheVxyXG5mdW5jdGlvbiBmcmFjdDMyIChhcnIpIHtcclxuXHRpZiAodHlwZW9mIGFyciA9PT0gJ251bWJlcicpIHtcclxuXHRcdHJldHVybiBmbG9hdDMyKGFyciAtIGZsb2F0MzIoYXJyKSlcclxuXHR9XHJcblxyXG5cdHZhciBmcmFjdCA9IGZsb2F0MzIoYXJyKVxyXG5cdGZvciAodmFyIGkgPSAwLCBsID0gZnJhY3QubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcblx0XHRmcmFjdFtpXSA9IGFycltpXSAtIGZyYWN0W2ldXHJcblx0fVxyXG5cdHJldHVybiBmcmFjdFxyXG59XHJcblxyXG4vLyBtYWtlIHN1cmUgZGF0YSBpcyBmbG9hdDMyIGFycmF5XHJcbmZ1bmN0aW9uIGZsb2F0MzIgKGFycikge1xyXG5cdGlmIChhcnIgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpIHJldHVybiBhcnJcclxuXHRpZiAodHlwZW9mIGFyciA9PT0gJ251bWJlcicpIHtcclxuXHRcdHJldHVybiAobmV3IEZsb2F0MzJBcnJheShbYXJyXSkpWzBdXHJcblx0fVxyXG5cclxuXHR2YXIgZmxvYXQgPSBuZXcgRmxvYXQzMkFycmF5KGFycilcclxuXHRmbG9hdC5zZXQoYXJyKVxyXG5cdHJldHVybiBmbG9hdFxyXG59XHJcbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgcGFyc2VVbml0ID0gcmVxdWlyZSgncGFyc2UtdW5pdCcpXG5cbm1vZHVsZS5leHBvcnRzID0gdG9QWFxuXG52YXIgUElYRUxTX1BFUl9JTkNIID0gOTZcblxuZnVuY3Rpb24gZ2V0UHJvcGVydHlJblBYKGVsZW1lbnQsIHByb3ApIHtcbiAgdmFyIHBhcnRzID0gcGFyc2VVbml0KGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZShwcm9wKSlcbiAgcmV0dXJuIHBhcnRzWzBdICogdG9QWChwYXJ0c1sxXSwgZWxlbWVudClcbn1cblxuLy9UaGlzIGJydXRhbCBoYWNrIGlzIG5lZWRlZFxuZnVuY3Rpb24gZ2V0U2l6ZUJydXRhbCh1bml0LCBlbGVtZW50KSB7XG4gIHZhciB0ZXN0RElWID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgdGVzdERJVi5zdHlsZVsnZm9udC1zaXplJ10gPSAnMTI4JyArIHVuaXRcbiAgZWxlbWVudC5hcHBlbmRDaGlsZCh0ZXN0RElWKVxuICB2YXIgc2l6ZSA9IGdldFByb3BlcnR5SW5QWCh0ZXN0RElWLCAnZm9udC1zaXplJykgLyAxMjhcbiAgZWxlbWVudC5yZW1vdmVDaGlsZCh0ZXN0RElWKVxuICByZXR1cm4gc2l6ZVxufVxuXG5mdW5jdGlvbiB0b1BYKHN0ciwgZWxlbWVudCkge1xuICBlbGVtZW50ID0gZWxlbWVudCB8fCBkb2N1bWVudC5ib2R5XG4gIHN0ciA9IChzdHIgfHwgJ3B4JykudHJpbSgpLnRvTG93ZXJDYXNlKClcbiAgaWYoZWxlbWVudCA9PT0gd2luZG93IHx8IGVsZW1lbnQgPT09IGRvY3VtZW50KSB7XG4gICAgZWxlbWVudCA9IGRvY3VtZW50LmJvZHkgXG4gIH1cbiAgc3dpdGNoKHN0cikge1xuICAgIGNhc2UgJyUnOiAgLy9BbWJpZ3VvdXMsIG5vdCBzdXJlIGlmIHdlIHNob3VsZCB1c2Ugd2lkdGggb3IgaGVpZ2h0XG4gICAgICByZXR1cm4gZWxlbWVudC5jbGllbnRIZWlnaHQgLyAxMDAuMFxuICAgIGNhc2UgJ2NoJzpcbiAgICBjYXNlICdleCc6XG4gICAgICByZXR1cm4gZ2V0U2l6ZUJydXRhbChzdHIsIGVsZW1lbnQpXG4gICAgY2FzZSAnZW0nOlxuICAgICAgcmV0dXJuIGdldFByb3BlcnR5SW5QWChlbGVtZW50LCAnZm9udC1zaXplJylcbiAgICBjYXNlICdyZW0nOlxuICAgICAgcmV0dXJuIGdldFByb3BlcnR5SW5QWChkb2N1bWVudC5ib2R5LCAnZm9udC1zaXplJylcbiAgICBjYXNlICd2dyc6XG4gICAgICByZXR1cm4gd2luZG93LmlubmVyV2lkdGgvMTAwXG4gICAgY2FzZSAndmgnOlxuICAgICAgcmV0dXJuIHdpbmRvdy5pbm5lckhlaWdodC8xMDBcbiAgICBjYXNlICd2bWluJzpcbiAgICAgIHJldHVybiBNYXRoLm1pbih3aW5kb3cuaW5uZXJXaWR0aCwgd2luZG93LmlubmVySGVpZ2h0KSAvIDEwMFxuICAgIGNhc2UgJ3ZtYXgnOlxuICAgICAgcmV0dXJuIE1hdGgubWF4KHdpbmRvdy5pbm5lcldpZHRoLCB3aW5kb3cuaW5uZXJIZWlnaHQpIC8gMTAwXG4gICAgY2FzZSAnaW4nOlxuICAgICAgcmV0dXJuIFBJWEVMU19QRVJfSU5DSFxuICAgIGNhc2UgJ2NtJzpcbiAgICAgIHJldHVybiBQSVhFTFNfUEVSX0lOQ0ggLyAyLjU0XG4gICAgY2FzZSAnbW0nOlxuICAgICAgcmV0dXJuIFBJWEVMU19QRVJfSU5DSCAvIDI1LjRcbiAgICBjYXNlICdwdCc6XG4gICAgICByZXR1cm4gUElYRUxTX1BFUl9JTkNIIC8gNzJcbiAgICBjYXNlICdwYyc6XG4gICAgICByZXR1cm4gUElYRUxTX1BFUl9JTkNIIC8gNlxuICB9XG4gIHJldHVybiAxXG59IiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL3RvcG9qc29uL3RvcG9qc29uLWNsaWVudCBWZXJzaW9uIDIuMS4wLiBDb3B5cmlnaHQgMjAxNiBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG4gIChmYWN0b3J5KChnbG9iYWwudG9wb2pzb24gPSBnbG9iYWwudG9wb2pzb24gfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBpZGVudGl0eSA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHg7XG59O1xuXG52YXIgdHJhbnNmb3JtID0gZnVuY3Rpb24odG9wb2xvZ3kpIHtcbiAgaWYgKCh0cmFuc2Zvcm0gPSB0b3BvbG9neS50cmFuc2Zvcm0pID09IG51bGwpIHJldHVybiBpZGVudGl0eTtcbiAgdmFyIHRyYW5zZm9ybSxcbiAgICAgIHgwLFxuICAgICAgeTAsXG4gICAgICBreCA9IHRyYW5zZm9ybS5zY2FsZVswXSxcbiAgICAgIGt5ID0gdHJhbnNmb3JtLnNjYWxlWzFdLFxuICAgICAgZHggPSB0cmFuc2Zvcm0udHJhbnNsYXRlWzBdLFxuICAgICAgZHkgPSB0cmFuc2Zvcm0udHJhbnNsYXRlWzFdO1xuICByZXR1cm4gZnVuY3Rpb24ocG9pbnQsIGkpIHtcbiAgICBpZiAoIWkpIHgwID0geTAgPSAwO1xuICAgIHBvaW50WzBdID0gKHgwICs9IHBvaW50WzBdKSAqIGt4ICsgZHg7XG4gICAgcG9pbnRbMV0gPSAoeTAgKz0gcG9pbnRbMV0pICoga3kgKyBkeTtcbiAgICByZXR1cm4gcG9pbnQ7XG4gIH07XG59O1xuXG52YXIgYmJveCA9IGZ1bmN0aW9uKHRvcG9sb2d5KSB7XG4gIHZhciBiYm94ID0gdG9wb2xvZ3kuYmJveDtcblxuICBmdW5jdGlvbiBiYm94UG9pbnQocDApIHtcbiAgICBwMVswXSA9IHAwWzBdLCBwMVsxXSA9IHAwWzFdLCB0KHAxKTtcbiAgICBpZiAocDFbMF0gPCB4MCkgeDAgPSBwMVswXTtcbiAgICBpZiAocDFbMF0gPiB4MSkgeDEgPSBwMVswXTtcbiAgICBpZiAocDFbMV0gPCB5MCkgeTAgPSBwMVsxXTtcbiAgICBpZiAocDFbMV0gPiB5MSkgeTEgPSBwMVsxXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJib3hHZW9tZXRyeShvKSB7XG4gICAgc3dpdGNoIChvLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJHZW9tZXRyeUNvbGxlY3Rpb25cIjogby5nZW9tZXRyaWVzLmZvckVhY2goYmJveEdlb21ldHJ5KTsgYnJlYWs7XG4gICAgICBjYXNlIFwiUG9pbnRcIjogYmJveFBvaW50KG8uY29vcmRpbmF0ZXMpOyBicmVhaztcbiAgICAgIGNhc2UgXCJNdWx0aVBvaW50XCI6IG8uY29vcmRpbmF0ZXMuZm9yRWFjaChiYm94UG9pbnQpOyBicmVhaztcbiAgICB9XG4gIH1cblxuICBpZiAoIWJib3gpIHtcbiAgICB2YXIgdCA9IHRyYW5zZm9ybSh0b3BvbG9neSksIHAwLCBwMSA9IG5ldyBBcnJheSgyKSwgbmFtZSxcbiAgICAgICAgeDAgPSBJbmZpbml0eSwgeTAgPSB4MCwgeDEgPSAteDAsIHkxID0gLXgwO1xuXG4gICAgdG9wb2xvZ3kuYXJjcy5mb3JFYWNoKGZ1bmN0aW9uKGFyYykge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGFyYy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBwMCA9IGFyY1tpXSwgcDFbMF0gPSBwMFswXSwgcDFbMV0gPSBwMFsxXSwgdChwMSwgaSk7XG4gICAgICAgIGlmIChwMVswXSA8IHgwKSB4MCA9IHAxWzBdO1xuICAgICAgICBpZiAocDFbMF0gPiB4MSkgeDEgPSBwMVswXTtcbiAgICAgICAgaWYgKHAxWzFdIDwgeTApIHkwID0gcDFbMV07XG4gICAgICAgIGlmIChwMVsxXSA+IHkxKSB5MSA9IHAxWzFdO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZm9yIChuYW1lIGluIHRvcG9sb2d5Lm9iamVjdHMpIHtcbiAgICAgIGJib3hHZW9tZXRyeSh0b3BvbG9neS5vYmplY3RzW25hbWVdKTtcbiAgICB9XG5cbiAgICBiYm94ID0gdG9wb2xvZ3kuYmJveCA9IFt4MCwgeTAsIHgxLCB5MV07XG4gIH1cblxuICByZXR1cm4gYmJveDtcbn07XG5cbnZhciByZXZlcnNlID0gZnVuY3Rpb24oYXJyYXksIG4pIHtcbiAgdmFyIHQsIGogPSBhcnJheS5sZW5ndGgsIGkgPSBqIC0gbjtcbiAgd2hpbGUgKGkgPCAtLWopIHQgPSBhcnJheVtpXSwgYXJyYXlbaSsrXSA9IGFycmF5W2pdLCBhcnJheVtqXSA9IHQ7XG59O1xuXG52YXIgZmVhdHVyZSA9IGZ1bmN0aW9uKHRvcG9sb2d5LCBvKSB7XG4gIHJldHVybiBvLnR5cGUgPT09IFwiR2VvbWV0cnlDb2xsZWN0aW9uXCJcbiAgICAgID8ge3R5cGU6IFwiRmVhdHVyZUNvbGxlY3Rpb25cIiwgZmVhdHVyZXM6IG8uZ2VvbWV0cmllcy5tYXAoZnVuY3Rpb24obykgeyByZXR1cm4gZmVhdHVyZSQxKHRvcG9sb2d5LCBvKTsgfSl9XG4gICAgICA6IGZlYXR1cmUkMSh0b3BvbG9neSwgbyk7XG59O1xuXG5mdW5jdGlvbiBmZWF0dXJlJDEodG9wb2xvZ3ksIG8pIHtcbiAgdmFyIGlkID0gby5pZCxcbiAgICAgIGJib3ggPSBvLmJib3gsXG4gICAgICBwcm9wZXJ0aWVzID0gby5wcm9wZXJ0aWVzID09IG51bGwgPyB7fSA6IG8ucHJvcGVydGllcyxcbiAgICAgIGdlb21ldHJ5ID0gb2JqZWN0KHRvcG9sb2d5LCBvKTtcbiAgcmV0dXJuIGlkID09IG51bGwgJiYgYmJveCA9PSBudWxsID8ge3R5cGU6IFwiRmVhdHVyZVwiLCBwcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBnZW9tZXRyeTogZ2VvbWV0cnl9XG4gICAgICA6IGJib3ggPT0gbnVsbCA/IHt0eXBlOiBcIkZlYXR1cmVcIiwgaWQ6IGlkLCBwcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBnZW9tZXRyeTogZ2VvbWV0cnl9XG4gICAgICA6IHt0eXBlOiBcIkZlYXR1cmVcIiwgaWQ6IGlkLCBiYm94OiBiYm94LCBwcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBnZW9tZXRyeTogZ2VvbWV0cnl9O1xufVxuXG5mdW5jdGlvbiBvYmplY3QodG9wb2xvZ3ksIG8pIHtcbiAgdmFyIHRyYW5zZm9ybVBvaW50ID0gdHJhbnNmb3JtKHRvcG9sb2d5KSxcbiAgICAgIGFyY3MgPSB0b3BvbG9neS5hcmNzO1xuXG4gIGZ1bmN0aW9uIGFyYyhpLCBwb2ludHMpIHtcbiAgICBpZiAocG9pbnRzLmxlbmd0aCkgcG9pbnRzLnBvcCgpO1xuICAgIGZvciAodmFyIGEgPSBhcmNzW2kgPCAwID8gfmkgOiBpXSwgayA9IDAsIG4gPSBhLmxlbmd0aDsgayA8IG47ICsraykge1xuICAgICAgcG9pbnRzLnB1c2godHJhbnNmb3JtUG9pbnQoYVtrXS5zbGljZSgpLCBrKSk7XG4gICAgfVxuICAgIGlmIChpIDwgMCkgcmV2ZXJzZShwb2ludHMsIG4pO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9pbnQocCkge1xuICAgIHJldHVybiB0cmFuc2Zvcm1Qb2ludChwLnNsaWNlKCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gbGluZShhcmNzKSB7XG4gICAgdmFyIHBvaW50cyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gYXJjcy5sZW5ndGg7IGkgPCBuOyArK2kpIGFyYyhhcmNzW2ldLCBwb2ludHMpO1xuICAgIGlmIChwb2ludHMubGVuZ3RoIDwgMikgcG9pbnRzLnB1c2gocG9pbnRzWzBdLnNsaWNlKCkpO1xuICAgIHJldHVybiBwb2ludHM7XG4gIH1cblxuICBmdW5jdGlvbiByaW5nKGFyY3MpIHtcbiAgICB2YXIgcG9pbnRzID0gbGluZShhcmNzKTtcbiAgICB3aGlsZSAocG9pbnRzLmxlbmd0aCA8IDQpIHBvaW50cy5wdXNoKHBvaW50c1swXS5zbGljZSgpKTtcbiAgICByZXR1cm4gcG9pbnRzO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9seWdvbihhcmNzKSB7XG4gICAgcmV0dXJuIGFyY3MubWFwKHJpbmcpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2VvbWV0cnkobykge1xuICAgIHZhciB0eXBlID0gby50eXBlLCBjb29yZGluYXRlcztcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgXCJHZW9tZXRyeUNvbGxlY3Rpb25cIjogcmV0dXJuIHt0eXBlOiB0eXBlLCBnZW9tZXRyaWVzOiBvLmdlb21ldHJpZXMubWFwKGdlb21ldHJ5KX07XG4gICAgICBjYXNlIFwiUG9pbnRcIjogY29vcmRpbmF0ZXMgPSBwb2ludChvLmNvb3JkaW5hdGVzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlQb2ludFwiOiBjb29yZGluYXRlcyA9IG8uY29vcmRpbmF0ZXMubWFwKHBvaW50KTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTGluZVN0cmluZ1wiOiBjb29yZGluYXRlcyA9IGxpbmUoby5hcmNzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlMaW5lU3RyaW5nXCI6IGNvb3JkaW5hdGVzID0gby5hcmNzLm1hcChsaW5lKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiUG9seWdvblwiOiBjb29yZGluYXRlcyA9IHBvbHlnb24oby5hcmNzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlQb2x5Z29uXCI6IGNvb3JkaW5hdGVzID0gby5hcmNzLm1hcChwb2x5Z29uKTsgYnJlYWs7XG4gICAgICBkZWZhdWx0OiByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHt0eXBlOiB0eXBlLCBjb29yZGluYXRlczogY29vcmRpbmF0ZXN9O1xuICB9XG5cbiAgcmV0dXJuIGdlb21ldHJ5KG8pO1xufVxuXG52YXIgc3RpdGNoID0gZnVuY3Rpb24odG9wb2xvZ3ksIGFyY3MpIHtcbiAgdmFyIHN0aXRjaGVkQXJjcyA9IHt9LFxuICAgICAgZnJhZ21lbnRCeVN0YXJ0ID0ge30sXG4gICAgICBmcmFnbWVudEJ5RW5kID0ge30sXG4gICAgICBmcmFnbWVudHMgPSBbXSxcbiAgICAgIGVtcHR5SW5kZXggPSAtMTtcblxuICAvLyBTdGl0Y2ggZW1wdHkgYXJjcyBmaXJzdCwgc2luY2UgdGhleSBtYXkgYmUgc3Vic3VtZWQgYnkgb3RoZXIgYXJjcy5cbiAgYXJjcy5mb3JFYWNoKGZ1bmN0aW9uKGksIGopIHtcbiAgICB2YXIgYXJjID0gdG9wb2xvZ3kuYXJjc1tpIDwgMCA/IH5pIDogaV0sIHQ7XG4gICAgaWYgKGFyYy5sZW5ndGggPCAzICYmICFhcmNbMV1bMF0gJiYgIWFyY1sxXVsxXSkge1xuICAgICAgdCA9IGFyY3NbKytlbXB0eUluZGV4XSwgYXJjc1tlbXB0eUluZGV4XSA9IGksIGFyY3Nbal0gPSB0O1xuICAgIH1cbiAgfSk7XG5cbiAgYXJjcy5mb3JFYWNoKGZ1bmN0aW9uKGkpIHtcbiAgICB2YXIgZSA9IGVuZHMoaSksXG4gICAgICAgIHN0YXJ0ID0gZVswXSxcbiAgICAgICAgZW5kID0gZVsxXSxcbiAgICAgICAgZiwgZztcblxuICAgIGlmIChmID0gZnJhZ21lbnRCeUVuZFtzdGFydF0pIHtcbiAgICAgIGRlbGV0ZSBmcmFnbWVudEJ5RW5kW2YuZW5kXTtcbiAgICAgIGYucHVzaChpKTtcbiAgICAgIGYuZW5kID0gZW5kO1xuICAgICAgaWYgKGcgPSBmcmFnbWVudEJ5U3RhcnRbZW5kXSkge1xuICAgICAgICBkZWxldGUgZnJhZ21lbnRCeVN0YXJ0W2cuc3RhcnRdO1xuICAgICAgICB2YXIgZmcgPSBnID09PSBmID8gZiA6IGYuY29uY2F0KGcpO1xuICAgICAgICBmcmFnbWVudEJ5U3RhcnRbZmcuc3RhcnQgPSBmLnN0YXJ0XSA9IGZyYWdtZW50QnlFbmRbZmcuZW5kID0gZy5lbmRdID0gZmc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmcmFnbWVudEJ5U3RhcnRbZi5zdGFydF0gPSBmcmFnbWVudEJ5RW5kW2YuZW5kXSA9IGY7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChmID0gZnJhZ21lbnRCeVN0YXJ0W2VuZF0pIHtcbiAgICAgIGRlbGV0ZSBmcmFnbWVudEJ5U3RhcnRbZi5zdGFydF07XG4gICAgICBmLnVuc2hpZnQoaSk7XG4gICAgICBmLnN0YXJ0ID0gc3RhcnQ7XG4gICAgICBpZiAoZyA9IGZyYWdtZW50QnlFbmRbc3RhcnRdKSB7XG4gICAgICAgIGRlbGV0ZSBmcmFnbWVudEJ5RW5kW2cuZW5kXTtcbiAgICAgICAgdmFyIGdmID0gZyA9PT0gZiA/IGYgOiBnLmNvbmNhdChmKTtcbiAgICAgICAgZnJhZ21lbnRCeVN0YXJ0W2dmLnN0YXJ0ID0gZy5zdGFydF0gPSBmcmFnbWVudEJ5RW5kW2dmLmVuZCA9IGYuZW5kXSA9IGdmO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnJhZ21lbnRCeVN0YXJ0W2Yuc3RhcnRdID0gZnJhZ21lbnRCeUVuZFtmLmVuZF0gPSBmO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmID0gW2ldO1xuICAgICAgZnJhZ21lbnRCeVN0YXJ0W2Yuc3RhcnQgPSBzdGFydF0gPSBmcmFnbWVudEJ5RW5kW2YuZW5kID0gZW5kXSA9IGY7XG4gICAgfVxuICB9KTtcblxuICBmdW5jdGlvbiBlbmRzKGkpIHtcbiAgICB2YXIgYXJjID0gdG9wb2xvZ3kuYXJjc1tpIDwgMCA/IH5pIDogaV0sIHAwID0gYXJjWzBdLCBwMTtcbiAgICBpZiAodG9wb2xvZ3kudHJhbnNmb3JtKSBwMSA9IFswLCAwXSwgYXJjLmZvckVhY2goZnVuY3Rpb24oZHApIHsgcDFbMF0gKz0gZHBbMF0sIHAxWzFdICs9IGRwWzFdOyB9KTtcbiAgICBlbHNlIHAxID0gYXJjW2FyYy5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gaSA8IDAgPyBbcDEsIHAwXSA6IFtwMCwgcDFdO1xuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goZnJhZ21lbnRCeUVuZCwgZnJhZ21lbnRCeVN0YXJ0KSB7XG4gICAgZm9yICh2YXIgayBpbiBmcmFnbWVudEJ5RW5kKSB7XG4gICAgICB2YXIgZiA9IGZyYWdtZW50QnlFbmRba107XG4gICAgICBkZWxldGUgZnJhZ21lbnRCeVN0YXJ0W2Yuc3RhcnRdO1xuICAgICAgZGVsZXRlIGYuc3RhcnQ7XG4gICAgICBkZWxldGUgZi5lbmQ7XG4gICAgICBmLmZvckVhY2goZnVuY3Rpb24oaSkgeyBzdGl0Y2hlZEFyY3NbaSA8IDAgPyB+aSA6IGldID0gMTsgfSk7XG4gICAgICBmcmFnbWVudHMucHVzaChmKTtcbiAgICB9XG4gIH1cblxuICBmbHVzaChmcmFnbWVudEJ5RW5kLCBmcmFnbWVudEJ5U3RhcnQpO1xuICBmbHVzaChmcmFnbWVudEJ5U3RhcnQsIGZyYWdtZW50QnlFbmQpO1xuICBhcmNzLmZvckVhY2goZnVuY3Rpb24oaSkgeyBpZiAoIXN0aXRjaGVkQXJjc1tpIDwgMCA/IH5pIDogaV0pIGZyYWdtZW50cy5wdXNoKFtpXSk7IH0pO1xuXG4gIHJldHVybiBmcmFnbWVudHM7XG59O1xuXG52YXIgbWVzaCA9IGZ1bmN0aW9uKHRvcG9sb2d5KSB7XG4gIHJldHVybiBvYmplY3QodG9wb2xvZ3ksIG1lc2hBcmNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xufTtcblxuZnVuY3Rpb24gbWVzaEFyY3ModG9wb2xvZ3ksIG9iamVjdCQkMSwgZmlsdGVyKSB7XG4gIHZhciBhcmNzLCBpLCBuO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIGFyY3MgPSBleHRyYWN0QXJjcyh0b3BvbG9neSwgb2JqZWN0JCQxLCBmaWx0ZXIpO1xuICBlbHNlIGZvciAoaSA9IDAsIGFyY3MgPSBuZXcgQXJyYXkobiA9IHRvcG9sb2d5LmFyY3MubGVuZ3RoKTsgaSA8IG47ICsraSkgYXJjc1tpXSA9IGk7XG4gIHJldHVybiB7dHlwZTogXCJNdWx0aUxpbmVTdHJpbmdcIiwgYXJjczogc3RpdGNoKHRvcG9sb2d5LCBhcmNzKX07XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RBcmNzKHRvcG9sb2d5LCBvYmplY3QkJDEsIGZpbHRlcikge1xuICB2YXIgYXJjcyA9IFtdLFxuICAgICAgZ2VvbXNCeUFyYyA9IFtdLFxuICAgICAgZ2VvbTtcblxuICBmdW5jdGlvbiBleHRyYWN0MChpKSB7XG4gICAgdmFyIGogPSBpIDwgMCA/IH5pIDogaTtcbiAgICAoZ2VvbXNCeUFyY1tqXSB8fCAoZ2VvbXNCeUFyY1tqXSA9IFtdKSkucHVzaCh7aTogaSwgZzogZ2VvbX0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdDEoYXJjcykge1xuICAgIGFyY3MuZm9yRWFjaChleHRyYWN0MCk7XG4gIH1cblxuICBmdW5jdGlvbiBleHRyYWN0MihhcmNzKSB7XG4gICAgYXJjcy5mb3JFYWNoKGV4dHJhY3QxKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGV4dHJhY3QzKGFyY3MpIHtcbiAgICBhcmNzLmZvckVhY2goZXh0cmFjdDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2VvbWV0cnkobykge1xuICAgIHN3aXRjaCAoZ2VvbSA9IG8sIG8udHlwZSkge1xuICAgICAgY2FzZSBcIkdlb21ldHJ5Q29sbGVjdGlvblwiOiBvLmdlb21ldHJpZXMuZm9yRWFjaChnZW9tZXRyeSk7IGJyZWFrO1xuICAgICAgY2FzZSBcIkxpbmVTdHJpbmdcIjogZXh0cmFjdDEoby5hcmNzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlMaW5lU3RyaW5nXCI6IGNhc2UgXCJQb2x5Z29uXCI6IGV4dHJhY3QyKG8uYXJjcyk7IGJyZWFrO1xuICAgICAgY2FzZSBcIk11bHRpUG9seWdvblwiOiBleHRyYWN0MyhvLmFyY3MpOyBicmVhaztcbiAgICB9XG4gIH1cblxuICBnZW9tZXRyeShvYmplY3QkJDEpO1xuXG4gIGdlb21zQnlBcmMuZm9yRWFjaChmaWx0ZXIgPT0gbnVsbFxuICAgICAgPyBmdW5jdGlvbihnZW9tcykgeyBhcmNzLnB1c2goZ2VvbXNbMF0uaSk7IH1cbiAgICAgIDogZnVuY3Rpb24oZ2VvbXMpIHsgaWYgKGZpbHRlcihnZW9tc1swXS5nLCBnZW9tc1tnZW9tcy5sZW5ndGggLSAxXS5nKSkgYXJjcy5wdXNoKGdlb21zWzBdLmkpOyB9KTtcblxuICByZXR1cm4gYXJjcztcbn1cblxuZnVuY3Rpb24gcGxhbmFyUmluZ0FyZWEocmluZykge1xuICB2YXIgaSA9IC0xLCBuID0gcmluZy5sZW5ndGgsIGEsIGIgPSByaW5nW24gLSAxXSwgYXJlYSA9IDA7XG4gIHdoaWxlICgrK2kgPCBuKSBhID0gYiwgYiA9IHJpbmdbaV0sIGFyZWEgKz0gYVswXSAqIGJbMV0gLSBhWzFdICogYlswXTtcbiAgcmV0dXJuIE1hdGguYWJzKGFyZWEpOyAvLyBOb3RlOiBkb3VibGVkIGFyZWEhXG59XG5cbnZhciBtZXJnZSA9IGZ1bmN0aW9uKHRvcG9sb2d5KSB7XG4gIHJldHVybiBvYmplY3QodG9wb2xvZ3ksIG1lcmdlQXJjcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbn07XG5cbmZ1bmN0aW9uIG1lcmdlQXJjcyh0b3BvbG9neSwgb2JqZWN0cykge1xuICB2YXIgcG9seWdvbnNCeUFyYyA9IHt9LFxuICAgICAgcG9seWdvbnMgPSBbXSxcbiAgICAgIGdyb3VwcyA9IFtdO1xuXG4gIG9iamVjdHMuZm9yRWFjaChnZW9tZXRyeSk7XG5cbiAgZnVuY3Rpb24gZ2VvbWV0cnkobykge1xuICAgIHN3aXRjaCAoby50eXBlKSB7XG4gICAgICBjYXNlIFwiR2VvbWV0cnlDb2xsZWN0aW9uXCI6IG8uZ2VvbWV0cmllcy5mb3JFYWNoKGdlb21ldHJ5KTsgYnJlYWs7XG4gICAgICBjYXNlIFwiUG9seWdvblwiOiBleHRyYWN0KG8uYXJjcyk7IGJyZWFrO1xuICAgICAgY2FzZSBcIk11bHRpUG9seWdvblwiOiBvLmFyY3MuZm9yRWFjaChleHRyYWN0KTsgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdChwb2x5Z29uKSB7XG4gICAgcG9seWdvbi5mb3JFYWNoKGZ1bmN0aW9uKHJpbmcpIHtcbiAgICAgIHJpbmcuZm9yRWFjaChmdW5jdGlvbihhcmMpIHtcbiAgICAgICAgKHBvbHlnb25zQnlBcmNbYXJjID0gYXJjIDwgMCA/IH5hcmMgOiBhcmNdIHx8IChwb2x5Z29uc0J5QXJjW2FyY10gPSBbXSkpLnB1c2gocG9seWdvbik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBwb2x5Z29ucy5wdXNoKHBvbHlnb24pO1xuICB9XG5cbiAgZnVuY3Rpb24gYXJlYShyaW5nKSB7XG4gICAgcmV0dXJuIHBsYW5hclJpbmdBcmVhKG9iamVjdCh0b3BvbG9neSwge3R5cGU6IFwiUG9seWdvblwiLCBhcmNzOiBbcmluZ119KS5jb29yZGluYXRlc1swXSk7XG4gIH1cblxuICBwb2x5Z29ucy5mb3JFYWNoKGZ1bmN0aW9uKHBvbHlnb24pIHtcbiAgICBpZiAoIXBvbHlnb24uXykge1xuICAgICAgdmFyIGdyb3VwID0gW10sXG4gICAgICAgICAgbmVpZ2hib3JzID0gW3BvbHlnb25dO1xuICAgICAgcG9seWdvbi5fID0gMTtcbiAgICAgIGdyb3Vwcy5wdXNoKGdyb3VwKTtcbiAgICAgIHdoaWxlIChwb2x5Z29uID0gbmVpZ2hib3JzLnBvcCgpKSB7XG4gICAgICAgIGdyb3VwLnB1c2gocG9seWdvbik7XG4gICAgICAgIHBvbHlnb24uZm9yRWFjaChmdW5jdGlvbihyaW5nKSB7XG4gICAgICAgICAgcmluZy5mb3JFYWNoKGZ1bmN0aW9uKGFyYykge1xuICAgICAgICAgICAgcG9seWdvbnNCeUFyY1thcmMgPCAwID8gfmFyYyA6IGFyY10uZm9yRWFjaChmdW5jdGlvbihwb2x5Z29uKSB7XG4gICAgICAgICAgICAgIGlmICghcG9seWdvbi5fKSB7XG4gICAgICAgICAgICAgICAgcG9seWdvbi5fID0gMTtcbiAgICAgICAgICAgICAgICBuZWlnaGJvcnMucHVzaChwb2x5Z29uKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgcG9seWdvbnMuZm9yRWFjaChmdW5jdGlvbihwb2x5Z29uKSB7XG4gICAgZGVsZXRlIHBvbHlnb24uXztcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBcIk11bHRpUG9seWdvblwiLFxuICAgIGFyY3M6IGdyb3Vwcy5tYXAoZnVuY3Rpb24ocG9seWdvbnMpIHtcbiAgICAgIHZhciBhcmNzID0gW10sIG47XG5cbiAgICAgIC8vIEV4dHJhY3QgdGhlIGV4dGVyaW9yICh1bmlxdWUpIGFyY3MuXG4gICAgICBwb2x5Z29ucy5mb3JFYWNoKGZ1bmN0aW9uKHBvbHlnb24pIHtcbiAgICAgICAgcG9seWdvbi5mb3JFYWNoKGZ1bmN0aW9uKHJpbmcpIHtcbiAgICAgICAgICByaW5nLmZvckVhY2goZnVuY3Rpb24oYXJjKSB7XG4gICAgICAgICAgICBpZiAocG9seWdvbnNCeUFyY1thcmMgPCAwID8gfmFyYyA6IGFyY10ubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgICBhcmNzLnB1c2goYXJjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gU3RpdGNoIHRoZSBhcmNzIGludG8gb25lIG9yIG1vcmUgcmluZ3MuXG4gICAgICBhcmNzID0gc3RpdGNoKHRvcG9sb2d5LCBhcmNzKTtcblxuICAgICAgLy8gSWYgbW9yZSB0aGFuIG9uZSByaW5nIGlzIHJldHVybmVkLFxuICAgICAgLy8gYXQgbW9zdCBvbmUgb2YgdGhlc2UgcmluZ3MgY2FuIGJlIHRoZSBleHRlcmlvcjtcbiAgICAgIC8vIGNob29zZSB0aGUgb25lIHdpdGggdGhlIGdyZWF0ZXN0IGFic29sdXRlIGFyZWEuXG4gICAgICBpZiAoKG4gPSBhcmNzLmxlbmd0aCkgPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxLCBrID0gYXJlYShhcmNzWzBdKSwga2ksIHQ7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBpZiAoKGtpID0gYXJlYShhcmNzW2ldKSkgPiBrKSB7XG4gICAgICAgICAgICB0ID0gYXJjc1swXSwgYXJjc1swXSA9IGFyY3NbaV0sIGFyY3NbaV0gPSB0LCBrID0ga2k7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhcmNzO1xuICAgIH0pXG4gIH07XG59XG5cbnZhciBiaXNlY3QgPSBmdW5jdGlvbihhLCB4KSB7XG4gIHZhciBsbyA9IDAsIGhpID0gYS5sZW5ndGg7XG4gIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgdmFyIG1pZCA9IGxvICsgaGkgPj4+IDE7XG4gICAgaWYgKGFbbWlkXSA8IHgpIGxvID0gbWlkICsgMTtcbiAgICBlbHNlIGhpID0gbWlkO1xuICB9XG4gIHJldHVybiBsbztcbn07XG5cbnZhciBuZWlnaGJvcnMgPSBmdW5jdGlvbihvYmplY3RzKSB7XG4gIHZhciBpbmRleGVzQnlBcmMgPSB7fSwgLy8gYXJjIGluZGV4IC0+IGFycmF5IG9mIG9iamVjdCBpbmRleGVzXG4gICAgICBuZWlnaGJvcnMgPSBvYmplY3RzLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIFtdOyB9KTtcblxuICBmdW5jdGlvbiBsaW5lKGFyY3MsIGkpIHtcbiAgICBhcmNzLmZvckVhY2goZnVuY3Rpb24oYSkge1xuICAgICAgaWYgKGEgPCAwKSBhID0gfmE7XG4gICAgICB2YXIgbyA9IGluZGV4ZXNCeUFyY1thXTtcbiAgICAgIGlmIChvKSBvLnB1c2goaSk7XG4gICAgICBlbHNlIGluZGV4ZXNCeUFyY1thXSA9IFtpXTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvbHlnb24oYXJjcywgaSkge1xuICAgIGFyY3MuZm9yRWFjaChmdW5jdGlvbihhcmMpIHsgbGluZShhcmMsIGkpOyB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdlb21ldHJ5KG8sIGkpIHtcbiAgICBpZiAoby50eXBlID09PSBcIkdlb21ldHJ5Q29sbGVjdGlvblwiKSBvLmdlb21ldHJpZXMuZm9yRWFjaChmdW5jdGlvbihvKSB7IGdlb21ldHJ5KG8sIGkpOyB9KTtcbiAgICBlbHNlIGlmIChvLnR5cGUgaW4gZ2VvbWV0cnlUeXBlKSBnZW9tZXRyeVR5cGVbby50eXBlXShvLmFyY3MsIGkpO1xuICB9XG5cbiAgdmFyIGdlb21ldHJ5VHlwZSA9IHtcbiAgICBMaW5lU3RyaW5nOiBsaW5lLFxuICAgIE11bHRpTGluZVN0cmluZzogcG9seWdvbixcbiAgICBQb2x5Z29uOiBwb2x5Z29uLFxuICAgIE11bHRpUG9seWdvbjogZnVuY3Rpb24oYXJjcywgaSkgeyBhcmNzLmZvckVhY2goZnVuY3Rpb24oYXJjKSB7IHBvbHlnb24oYXJjLCBpKTsgfSk7IH1cbiAgfTtcblxuICBvYmplY3RzLmZvckVhY2goZ2VvbWV0cnkpO1xuXG4gIGZvciAodmFyIGkgaW4gaW5kZXhlc0J5QXJjKSB7XG4gICAgZm9yICh2YXIgaW5kZXhlcyA9IGluZGV4ZXNCeUFyY1tpXSwgbSA9IGluZGV4ZXMubGVuZ3RoLCBqID0gMDsgaiA8IG07ICsraikge1xuICAgICAgZm9yICh2YXIgayA9IGogKyAxOyBrIDwgbTsgKytrKSB7XG4gICAgICAgIHZhciBpaiA9IGluZGV4ZXNbal0sIGlrID0gaW5kZXhlc1trXSwgbjtcbiAgICAgICAgaWYgKChuID0gbmVpZ2hib3JzW2lqXSlbaSA9IGJpc2VjdChuLCBpayldICE9PSBpaykgbi5zcGxpY2UoaSwgMCwgaWspO1xuICAgICAgICBpZiAoKG4gPSBuZWlnaGJvcnNbaWtdKVtpID0gYmlzZWN0KG4sIGlqKV0gIT09IGlqKSBuLnNwbGljZShpLCAwLCBpaik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5laWdoYm9ycztcbn07XG5cbnZhciBxdWFudGl6ZSA9IGZ1bmN0aW9uKHRvcG9sb2d5LCBuKSB7XG4gIGlmICghKChuID0gTWF0aC5mbG9vcihuKSkgPj0gMikpIHRocm93IG5ldyBFcnJvcihcIm4gbXVzdCBiZSDiiaUyXCIpO1xuICBpZiAodG9wb2xvZ3kudHJhbnNmb3JtKSB0aHJvdyBuZXcgRXJyb3IoXCJhbHJlYWR5IHF1YW50aXplZFwiKTtcbiAgdmFyIGJiID0gYmJveCh0b3BvbG9neSksIG5hbWUsXG4gICAgICBkeCA9IGJiWzBdLCBreCA9IChiYlsyXSAtIGR4KSAvIChuIC0gMSkgfHwgMSxcbiAgICAgIGR5ID0gYmJbMV0sIGt5ID0gKGJiWzNdIC0gZHkpIC8gKG4gLSAxKSB8fCAxO1xuXG4gIGZ1bmN0aW9uIHF1YW50aXplUG9pbnQocCkge1xuICAgIHBbMF0gPSBNYXRoLnJvdW5kKChwWzBdIC0gZHgpIC8ga3gpO1xuICAgIHBbMV0gPSBNYXRoLnJvdW5kKChwWzFdIC0gZHkpIC8ga3kpO1xuICB9XG5cbiAgZnVuY3Rpb24gcXVhbnRpemVHZW9tZXRyeShvKSB7XG4gICAgc3dpdGNoIChvLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJHZW9tZXRyeUNvbGxlY3Rpb25cIjogby5nZW9tZXRyaWVzLmZvckVhY2gocXVhbnRpemVHZW9tZXRyeSk7IGJyZWFrO1xuICAgICAgY2FzZSBcIlBvaW50XCI6IHF1YW50aXplUG9pbnQoby5jb29yZGluYXRlcyk7IGJyZWFrO1xuICAgICAgY2FzZSBcIk11bHRpUG9pbnRcIjogby5jb29yZGluYXRlcy5mb3JFYWNoKHF1YW50aXplUG9pbnQpOyBicmVhaztcbiAgICB9XG4gIH1cblxuICB0b3BvbG9neS5hcmNzLmZvckVhY2goZnVuY3Rpb24oYXJjKSB7XG4gICAgdmFyIGkgPSAxLFxuICAgICAgICBqID0gMSxcbiAgICAgICAgbiA9IGFyYy5sZW5ndGgsXG4gICAgICAgIHBpID0gYXJjWzBdLFxuICAgICAgICB4MCA9IHBpWzBdID0gTWF0aC5yb3VuZCgocGlbMF0gLSBkeCkgLyBreCksXG4gICAgICAgIHkwID0gcGlbMV0gPSBNYXRoLnJvdW5kKChwaVsxXSAtIGR5KSAvIGt5KSxcbiAgICAgICAgcGosXG4gICAgICAgIHgxLFxuICAgICAgICB5MTtcblxuICAgIGZvciAoOyBpIDwgbjsgKytpKSB7XG4gICAgICBwaSA9IGFyY1tpXTtcbiAgICAgIHgxID0gTWF0aC5yb3VuZCgocGlbMF0gLSBkeCkgLyBreCk7XG4gICAgICB5MSA9IE1hdGgucm91bmQoKHBpWzFdIC0gZHkpIC8ga3kpO1xuICAgICAgaWYgKHgxICE9PSB4MCB8fCB5MSAhPT0geTApIHtcbiAgICAgICAgcGogPSBhcmNbaisrXTtcbiAgICAgICAgcGpbMF0gPSB4MSAtIHgwLCB4MCA9IHgxO1xuICAgICAgICBwalsxXSA9IHkxIC0geTAsIHkwID0geTE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGogPCAyKSB7XG4gICAgICBwaiA9IGFyY1tqKytdO1xuICAgICAgcGpbMF0gPSAwO1xuICAgICAgcGpbMV0gPSAwO1xuICAgIH1cblxuICAgIGFyYy5sZW5ndGggPSBqO1xuICB9KTtcblxuICBmb3IgKG5hbWUgaW4gdG9wb2xvZ3kub2JqZWN0cykge1xuICAgIHF1YW50aXplR2VvbWV0cnkodG9wb2xvZ3kub2JqZWN0c1tuYW1lXSk7XG4gIH1cblxuICB0b3BvbG9neS50cmFuc2Zvcm0gPSB7XG4gICAgc2NhbGU6IFtreCwga3ldLFxuICAgIHRyYW5zbGF0ZTogW2R4LCBkeV1cbiAgfTtcblxuICByZXR1cm4gdG9wb2xvZ3k7XG59O1xuXG52YXIgdW50cmFuc2Zvcm0gPSBmdW5jdGlvbih0b3BvbG9neSkge1xuICBpZiAoKHRyYW5zZm9ybSA9IHRvcG9sb2d5LnRyYW5zZm9ybSkgPT0gbnVsbCkgcmV0dXJuIGlkZW50aXR5O1xuICB2YXIgdHJhbnNmb3JtLFxuICAgICAgeDAsXG4gICAgICB5MCxcbiAgICAgIGt4ID0gdHJhbnNmb3JtLnNjYWxlWzBdLFxuICAgICAga3kgPSB0cmFuc2Zvcm0uc2NhbGVbMV0sXG4gICAgICBkeCA9IHRyYW5zZm9ybS50cmFuc2xhdGVbMF0sXG4gICAgICBkeSA9IHRyYW5zZm9ybS50cmFuc2xhdGVbMV07XG4gIHJldHVybiBmdW5jdGlvbihwb2ludCwgaSkge1xuICAgIGlmICghaSkgeDAgPSB5MCA9IDA7XG4gICAgdmFyIHgxID0gTWF0aC5yb3VuZCgocG9pbnRbMF0gLSBkeCkgLyBreCksXG4gICAgICAgIHkxID0gTWF0aC5yb3VuZCgocG9pbnRbMV0gLSBkeSkgLyBreSk7XG4gICAgcG9pbnRbMF0gPSB4MSAtIHgwLCB4MCA9IHgxO1xuICAgIHBvaW50WzFdID0geTEgLSB5MCwgeTAgPSB5MTtcbiAgICByZXR1cm4gcG9pbnQ7XG4gIH07XG59O1xuXG5leHBvcnRzLmJib3ggPSBiYm94O1xuZXhwb3J0cy5mZWF0dXJlID0gZmVhdHVyZTtcbmV4cG9ydHMubWVzaCA9IG1lc2g7XG5leHBvcnRzLm1lc2hBcmNzID0gbWVzaEFyY3M7XG5leHBvcnRzLm1lcmdlID0gbWVyZ2U7XG5leHBvcnRzLm1lcmdlQXJjcyA9IG1lcmdlQXJjcztcbmV4cG9ydHMubmVpZ2hib3JzID0gbmVpZ2hib3JzO1xuZXhwb3J0cy5xdWFudGl6ZSA9IHF1YW50aXplO1xuZXhwb3J0cy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5leHBvcnRzLnVudHJhbnNmb3JtID0gdW50cmFuc2Zvcm07XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHRyaWFuZ3VsYXRlQ3ViZVxuXG52YXIgcGVybSA9IHJlcXVpcmUoXCJwZXJtdXRhdGlvbi1yYW5rXCIpXG52YXIgc2duID0gcmVxdWlyZShcInBlcm11dGF0aW9uLXBhcml0eVwiKVxudmFyIGdhbW1hID0gcmVxdWlyZShcImdhbW1hXCIpXG5cbmZ1bmN0aW9uIHRyaWFuZ3VsYXRlQ3ViZShkaW1lbnNpb24pIHtcbiAgaWYoZGltZW5zaW9uIDwgMCkge1xuICAgIHJldHVybiBbIF1cbiAgfVxuICBpZihkaW1lbnNpb24gPT09IDApIHtcbiAgICByZXR1cm4gWyBbMF0gXVxuICB9XG4gIHZhciBkZmFjdG9yaWFsID0gTWF0aC5yb3VuZChnYW1tYShkaW1lbnNpb24rMSkpfDBcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGRmYWN0b3JpYWw7ICsraSkge1xuICAgIHZhciBwID0gcGVybS51bnJhbmsoZGltZW5zaW9uLCBpKVxuICAgIHZhciBjZWxsID0gWyAwIF1cbiAgICB2YXIgdiA9IDBcbiAgICBmb3IodmFyIGo9MDsgajxwLmxlbmd0aDsgKytqKSB7XG4gICAgICB2ICs9ICgxPDxwW2pdKVxuICAgICAgY2VsbC5wdXNoKHYpXG4gICAgfVxuICAgIGlmKHNnbihwKSA8IDEpIHtcbiAgICAgIGNlbGxbMF0gPSB2XG4gICAgICBjZWxsW2RpbWVuc2lvbl0gPSAwXG4gICAgfVxuICAgIHJlc3VsdC5wdXNoKGNlbGwpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufSIsIid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVR1cm50YWJsZUNvbnRyb2xsZXJcblxudmFyIGZpbHRlclZlY3RvciA9IHJlcXVpcmUoJ2ZpbHRlcmVkLXZlY3RvcicpXG52YXIgaW52ZXJ0NDQgICAgID0gcmVxdWlyZSgnZ2wtbWF0NC9pbnZlcnQnKVxudmFyIHJvdGF0ZU0gICAgICA9IHJlcXVpcmUoJ2dsLW1hdDQvcm90YXRlJylcbnZhciBjcm9zcyAgICAgICAgPSByZXF1aXJlKCdnbC12ZWMzL2Nyb3NzJylcbnZhciBub3JtYWxpemUzICAgPSByZXF1aXJlKCdnbC12ZWMzL25vcm1hbGl6ZScpXG52YXIgZG90MyAgICAgICAgID0gcmVxdWlyZSgnZ2wtdmVjMy9kb3QnKVxuXG5mdW5jdGlvbiBsZW4zKHgsIHksIHopIHtcbiAgcmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyh4LCAyKSArIE1hdGgucG93KHksIDIpICsgTWF0aC5wb3coeiwgMikpXG59XG5cbmZ1bmN0aW9uIGNsYW1wMSh4KSB7XG4gIHJldHVybiBNYXRoLm1pbigxLjAsIE1hdGgubWF4KC0xLjAsIHgpKVxufVxuXG5mdW5jdGlvbiBmaW5kT3J0aG9QYWlyKHYpIHtcbiAgdmFyIHZ4ID0gTWF0aC5hYnModlswXSlcbiAgdmFyIHZ5ID0gTWF0aC5hYnModlsxXSlcbiAgdmFyIHZ6ID0gTWF0aC5hYnModlsyXSlcblxuICB2YXIgdSA9IFswLDAsMF1cbiAgaWYodnggPiBNYXRoLm1heCh2eSwgdnopKSB7XG4gICAgdVsyXSA9IDFcbiAgfSBlbHNlIGlmKHZ5ID4gTWF0aC5tYXgodngsIHZ6KSkge1xuICAgIHVbMF0gPSAxXG4gIH0gZWxzZSB7XG4gICAgdVsxXSA9IDFcbiAgfVxuXG4gIHZhciB2diA9IDBcbiAgdmFyIHV2ID0gMFxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kgKSB7XG4gICAgdnYgKz0gdltpXSAqIHZbaV1cbiAgICB1diArPSB1W2ldICogdltpXVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHVbaV0gLT0gKHV2IC8gdnYpICogIHZbaV1cbiAgfVxuICBub3JtYWxpemUzKHUsIHUpXG4gIHJldHVybiB1XG59XG5cbmZ1bmN0aW9uIFR1cm50YWJsZUNvbnRyb2xsZXIoem9vbU1pbiwgem9vbU1heCwgY2VudGVyLCB1cCwgcmlnaHQsIHJhZGl1cywgdGhldGEsIHBoaSkge1xuICB0aGlzLmNlbnRlciA9IGZpbHRlclZlY3RvcihjZW50ZXIpXG4gIHRoaXMudXAgICAgID0gZmlsdGVyVmVjdG9yKHVwKVxuICB0aGlzLnJpZ2h0ICA9IGZpbHRlclZlY3RvcihyaWdodClcbiAgdGhpcy5yYWRpdXMgPSBmaWx0ZXJWZWN0b3IoW3JhZGl1c10pXG4gIHRoaXMuYW5nbGUgID0gZmlsdGVyVmVjdG9yKFt0aGV0YSwgcGhpXSlcbiAgdGhpcy5hbmdsZS5ib3VuZHMgPSBbWy1JbmZpbml0eSwtTWF0aC5QSS8yXSwgW0luZmluaXR5LE1hdGguUEkvMl1dXG4gIHRoaXMuc2V0RGlzdGFuY2VMaW1pdHMoem9vbU1pbiwgem9vbU1heClcblxuICB0aGlzLmNvbXB1dGVkQ2VudGVyID0gdGhpcy5jZW50ZXIuY3VydmUoMClcbiAgdGhpcy5jb21wdXRlZFVwICAgICA9IHRoaXMudXAuY3VydmUoMClcbiAgdGhpcy5jb21wdXRlZFJpZ2h0ICA9IHRoaXMucmlnaHQuY3VydmUoMClcbiAgdGhpcy5jb21wdXRlZFJhZGl1cyA9IHRoaXMucmFkaXVzLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRBbmdsZSAgPSB0aGlzLmFuZ2xlLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRUb3dhcmQgPSBbMCwwLDBdXG4gIHRoaXMuY29tcHV0ZWRFeWUgICAgPSBbMCwwLDBdXG4gIHRoaXMuY29tcHV0ZWRNYXRyaXggPSBuZXcgQXJyYXkoMTYpXG4gIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcbiAgICB0aGlzLmNvbXB1dGVkTWF0cml4W2ldID0gMC41XG4gIH1cblxuICB0aGlzLnJlY2FsY01hdHJpeCgwKVxufVxuXG52YXIgcHJvdG8gPSBUdXJudGFibGVDb250cm9sbGVyLnByb3RvdHlwZVxuXG5wcm90by5zZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKG1pbkRpc3QsIG1heERpc3QpIHtcbiAgaWYobWluRGlzdCA+IDApIHtcbiAgICBtaW5EaXN0ID0gTWF0aC5sb2cobWluRGlzdClcbiAgfSBlbHNlIHtcbiAgICBtaW5EaXN0ID0gLUluZmluaXR5XG4gIH1cbiAgaWYobWF4RGlzdCA+IDApIHtcbiAgICBtYXhEaXN0ID0gTWF0aC5sb2cobWF4RGlzdClcbiAgfSBlbHNlIHtcbiAgICBtYXhEaXN0ID0gSW5maW5pdHlcbiAgfVxuICBtYXhEaXN0ID0gTWF0aC5tYXgobWF4RGlzdCwgbWluRGlzdClcbiAgdGhpcy5yYWRpdXMuYm91bmRzWzBdWzBdID0gbWluRGlzdFxuICB0aGlzLnJhZGl1cy5ib3VuZHNbMV1bMF0gPSBtYXhEaXN0XG59XG5cbnByb3RvLmdldERpc3RhbmNlTGltaXRzID0gZnVuY3Rpb24ob3V0KSB7XG4gIHZhciBib3VuZHMgPSB0aGlzLnJhZGl1cy5ib3VuZHNbMF1cbiAgaWYob3V0KSB7XG4gICAgb3V0WzBdID0gTWF0aC5leHAoYm91bmRzWzBdWzBdKVxuICAgIG91dFsxXSA9IE1hdGguZXhwKGJvdW5kc1sxXVswXSlcbiAgICByZXR1cm4gb3V0XG4gIH1cbiAgcmV0dXJuIFsgTWF0aC5leHAoYm91bmRzWzBdWzBdKSwgTWF0aC5leHAoYm91bmRzWzFdWzBdKSBdXG59XG5cbnByb3RvLnJlY2FsY01hdHJpeCA9IGZ1bmN0aW9uKHQpIHtcbiAgLy9SZWNvbXB1dGUgY3VydmVzXG4gIHRoaXMuY2VudGVyLmN1cnZlKHQpXG4gIHRoaXMudXAuY3VydmUodClcbiAgdGhpcy5yaWdodC5jdXJ2ZSh0KVxuICB0aGlzLnJhZGl1cy5jdXJ2ZSh0KVxuICB0aGlzLmFuZ2xlLmN1cnZlKHQpXG5cbiAgLy9Db21wdXRlIGZyYW1lIGZvciBjYW1lcmEgbWF0cml4XG4gIHZhciB1cCAgICAgPSB0aGlzLmNvbXB1dGVkVXBcbiAgdmFyIHJpZ2h0ICA9IHRoaXMuY29tcHV0ZWRSaWdodFxuICB2YXIgdXUgPSAwLjBcbiAgdmFyIHVyID0gMC4wXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHVyICs9IHVwW2ldICogcmlnaHRbaV1cbiAgICB1dSArPSB1cFtpXSAqIHVwW2ldXG4gIH1cbiAgdmFyIHVsID0gTWF0aC5zcXJ0KHV1KVxuICB2YXIgcnIgPSAwLjBcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgcmlnaHRbaV0gLT0gdXBbaV0gKiB1ciAvIHV1XG4gICAgcnIgICAgICAgKz0gcmlnaHRbaV0gKiByaWdodFtpXVxuICAgIHVwW2ldICAgIC89IHVsXG4gIH1cbiAgdmFyIHJsID0gTWF0aC5zcXJ0KHJyKVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICByaWdodFtpXSAvPSBybFxuICB9XG5cbiAgLy9Db21wdXRlIHRvd2FyZCB2ZWN0b3JcbiAgdmFyIHRvd2FyZCA9IHRoaXMuY29tcHV0ZWRUb3dhcmRcbiAgY3Jvc3ModG93YXJkLCB1cCwgcmlnaHQpXG4gIG5vcm1hbGl6ZTModG93YXJkLCB0b3dhcmQpXG5cbiAgLy9Db21wdXRlIGFuZ3VsYXIgcGFyYW1ldGVyc1xuICB2YXIgcmFkaXVzID0gTWF0aC5leHAodGhpcy5jb21wdXRlZFJhZGl1c1swXSlcbiAgdmFyIHRoZXRhICA9IHRoaXMuY29tcHV0ZWRBbmdsZVswXVxuICB2YXIgcGhpICAgID0gdGhpcy5jb21wdXRlZEFuZ2xlWzFdXG5cbiAgdmFyIGN0aGV0YSA9IE1hdGguY29zKHRoZXRhKVxuICB2YXIgc3RoZXRhID0gTWF0aC5zaW4odGhldGEpXG4gIHZhciBjcGhpICAgPSBNYXRoLmNvcyhwaGkpXG4gIHZhciBzcGhpICAgPSBNYXRoLnNpbihwaGkpXG5cbiAgdmFyIGNlbnRlciA9IHRoaXMuY29tcHV0ZWRDZW50ZXJcblxuICB2YXIgd3ggPSBjdGhldGEgKiBjcGhpIFxuICB2YXIgd3kgPSBzdGhldGEgKiBjcGhpXG4gIHZhciB3eiA9IHNwaGlcblxuICB2YXIgc3ggPSAtY3RoZXRhICogc3BoaVxuICB2YXIgc3kgPSAtc3RoZXRhICogc3BoaVxuICB2YXIgc3ogPSBjcGhpXG5cbiAgdmFyIGV5ZSA9IHRoaXMuY29tcHV0ZWRFeWVcbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdmFyIHggICAgICA9IHd4ICogcmlnaHRbaV0gKyB3eSAqIHRvd2FyZFtpXSArIHd6ICogdXBbaV1cbiAgICBtYXRbNCppKzFdID0gc3ggKiByaWdodFtpXSArIHN5ICogdG93YXJkW2ldICsgc3ogKiB1cFtpXVxuICAgIG1hdFs0KmkrMl0gPSB4XG4gICAgbWF0WzQqaSszXSA9IDAuMFxuICB9XG5cbiAgdmFyIGF4ID0gbWF0WzFdXG4gIHZhciBheSA9IG1hdFs1XVxuICB2YXIgYXogPSBtYXRbOV1cbiAgdmFyIGJ4ID0gbWF0WzJdXG4gIHZhciBieSA9IG1hdFs2XVxuICB2YXIgYnogPSBtYXRbMTBdXG4gIHZhciBjeCA9IGF5ICogYnogLSBheiAqIGJ5XG4gIHZhciBjeSA9IGF6ICogYnggLSBheCAqIGJ6XG4gIHZhciBjeiA9IGF4ICogYnkgLSBheSAqIGJ4XG4gIHZhciBjbCA9IGxlbjMoY3gsIGN5LCBjeilcbiAgY3ggLz0gY2xcbiAgY3kgLz0gY2xcbiAgY3ogLz0gY2xcbiAgbWF0WzBdID0gY3hcbiAgbWF0WzRdID0gY3lcbiAgbWF0WzhdID0gY3pcblxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBleWVbaV0gPSBjZW50ZXJbaV0gKyBtYXRbMis0KmldKnJhZGl1c1xuICB9XG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdmFyIHJyID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICByciArPSBtYXRbaSs0KmpdICogZXllW2pdXG4gICAgfVxuICAgIG1hdFsxMitpXSA9IC1yclxuICB9XG4gIG1hdFsxNV0gPSAxLjBcbn1cblxucHJvdG8uZ2V0TWF0cml4ID0gZnVuY3Rpb24odCwgcmVzdWx0KSB7XG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIGlmKHJlc3VsdCkge1xuICAgIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcbiAgICAgIHJlc3VsdFtpXSA9IG1hdFtpXVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbiAgcmV0dXJuIG1hdFxufVxuXG52YXIgekF4aXMgPSBbMCwwLDBdXG5wcm90by5yb3RhdGUgPSBmdW5jdGlvbih0LCBkdGhldGEsIGRwaGksIGRyb2xsKSB7XG4gIHRoaXMuYW5nbGUubW92ZSh0LCBkdGhldGEsIGRwaGkpXG4gIGlmKGRyb2xsKSB7XG4gICAgdGhpcy5yZWNhbGNNYXRyaXgodClcblxuICAgIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gICAgekF4aXNbMF0gPSBtYXRbMl1cbiAgICB6QXhpc1sxXSA9IG1hdFs2XVxuICAgIHpBeGlzWzJdID0gbWF0WzEwXVxuXG4gICAgdmFyIHVwICAgICA9IHRoaXMuY29tcHV0ZWRVcFxuICAgIHZhciByaWdodCAgPSB0aGlzLmNvbXB1dGVkUmlnaHRcbiAgICB2YXIgdG93YXJkID0gdGhpcy5jb21wdXRlZFRvd2FyZFxuXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgICBtYXRbNCppXSAgID0gdXBbaV1cbiAgICAgIG1hdFs0KmkrMV0gPSByaWdodFtpXVxuICAgICAgbWF0WzQqaSsyXSA9IHRvd2FyZFtpXVxuICAgIH1cbiAgICByb3RhdGVNKG1hdCwgbWF0LCBkcm9sbCwgekF4aXMpXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgICB1cFtpXSA9ICAgIG1hdFs0KmldXG4gICAgICByaWdodFtpXSA9IG1hdFs0KmkrMV1cbiAgICB9XG5cbiAgICB0aGlzLnVwLnNldCh0LCB1cFswXSwgdXBbMV0sIHVwWzJdKVxuICAgIHRoaXMucmlnaHQuc2V0KHQsIHJpZ2h0WzBdLCByaWdodFsxXSwgcmlnaHRbMl0pXG4gIH1cbn1cblxucHJvdG8ucGFuID0gZnVuY3Rpb24odCwgZHgsIGR5LCBkeikge1xuICBkeCA9IGR4IHx8IDAuMFxuICBkeSA9IGR5IHx8IDAuMFxuICBkeiA9IGR6IHx8IDAuMFxuXG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG5cbiAgdmFyIGRpc3QgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxuXG4gIHZhciB1eCA9IG1hdFsxXVxuICB2YXIgdXkgPSBtYXRbNV1cbiAgdmFyIHV6ID0gbWF0WzldXG4gIHZhciB1bCA9IGxlbjModXgsIHV5LCB1eilcbiAgdXggLz0gdWxcbiAgdXkgLz0gdWxcbiAgdXogLz0gdWxcblxuICB2YXIgcnggPSBtYXRbMF1cbiAgdmFyIHJ5ID0gbWF0WzRdXG4gIHZhciByeiA9IG1hdFs4XVxuICB2YXIgcnUgPSByeCAqIHV4ICsgcnkgKiB1eSArIHJ6ICogdXpcbiAgcnggLT0gdXggKiBydVxuICByeSAtPSB1eSAqIHJ1XG4gIHJ6IC09IHV6ICogcnVcbiAgdmFyIHJsID0gbGVuMyhyeCwgcnksIHJ6KVxuICByeCAvPSBybFxuICByeSAvPSBybFxuICByeiAvPSBybFxuXG4gIHZhciB2eCA9IHJ4ICogZHggKyB1eCAqIGR5XG4gIHZhciB2eSA9IHJ5ICogZHggKyB1eSAqIGR5XG4gIHZhciB2eiA9IHJ6ICogZHggKyB1eiAqIGR5XG4gIHRoaXMuY2VudGVyLm1vdmUodCwgdngsIHZ5LCB2eilcblxuICAvL1VwZGF0ZSB6LWNvbXBvbmVudCBvZiByYWRpdXNcbiAgdmFyIHJhZGl1cyA9IE1hdGguZXhwKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pXG4gIHJhZGl1cyA9IE1hdGgubWF4KDFlLTQsIHJhZGl1cyArIGR6KVxuICB0aGlzLnJhZGl1cy5zZXQodCwgTWF0aC5sb2cocmFkaXVzKSlcbn1cblxucHJvdG8udHJhbnNsYXRlID0gZnVuY3Rpb24odCwgZHgsIGR5LCBkeikge1xuICB0aGlzLmNlbnRlci5tb3ZlKHQsXG4gICAgZHh8fDAuMCxcbiAgICBkeXx8MC4wLFxuICAgIGR6fHwwLjApXG59XG5cbi8vUmVjZW50ZXJzIHRoZSBjb29yZGluYXRlIGF4ZXNcbnByb3RvLnNldE1hdHJpeCA9IGZ1bmN0aW9uKHQsIG1hdCwgYXhlcywgbm9TbmFwKSB7XG4gIFxuICAvL0dldCB0aGUgYXhlcyBmb3IgdGFyZVxuICB2YXIgdXNoaWZ0ID0gMVxuICBpZih0eXBlb2YgYXhlcyA9PT0gJ251bWJlcicpIHtcbiAgICB1c2hpZnQgPSAoYXhlcyl8MFxuICB9IFxuICBpZih1c2hpZnQgPCAwIHx8IHVzaGlmdCA+IDMpIHtcbiAgICB1c2hpZnQgPSAxXG4gIH1cbiAgdmFyIHZzaGlmdCA9ICh1c2hpZnQgKyAyKSAlIDNcbiAgdmFyIGZzaGlmdCA9ICh1c2hpZnQgKyAxKSAlIDNcblxuICAvL1JlY29tcHV0ZSBzdGF0ZSBmb3IgbmV3IHQgdmFsdWVcbiAgaWYoIW1hdCkgeyBcbiAgICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuICAgIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgfVxuXG4gIC8vR2V0IHJpZ2h0IGFuZCB1cCB2ZWN0b3JzXG4gIHZhciB1eCA9IG1hdFt1c2hpZnRdXG4gIHZhciB1eSA9IG1hdFt1c2hpZnQrNF1cbiAgdmFyIHV6ID0gbWF0W3VzaGlmdCs4XVxuICBpZighbm9TbmFwKSB7XG4gICAgdmFyIHVsID0gbGVuMyh1eCwgdXksIHV6KVxuICAgIHV4IC89IHVsXG4gICAgdXkgLz0gdWxcbiAgICB1eiAvPSB1bFxuICB9IGVsc2Uge1xuICAgIHZhciBheCA9IE1hdGguYWJzKHV4KVxuICAgIHZhciBheSA9IE1hdGguYWJzKHV5KVxuICAgIHZhciBheiA9IE1hdGguYWJzKHV6KVxuICAgIHZhciBhbSA9IE1hdGgubWF4KGF4LGF5LGF6KVxuICAgIGlmKGF4ID09PSBhbSkge1xuICAgICAgdXggPSAodXggPCAwKSA/IC0xIDogMVxuICAgICAgdXkgPSB1eiA9IDBcbiAgICB9IGVsc2UgaWYoYXogPT09IGFtKSB7XG4gICAgICB1eiA9ICh1eiA8IDApID8gLTEgOiAxXG4gICAgICB1eCA9IHV5ID0gMFxuICAgIH0gZWxzZSB7XG4gICAgICB1eSA9ICh1eSA8IDApID8gLTEgOiAxXG4gICAgICB1eCA9IHV6ID0gMFxuICAgIH1cbiAgfVxuXG4gIHZhciByeCA9IG1hdFt2c2hpZnRdXG4gIHZhciByeSA9IG1hdFt2c2hpZnQrNF1cbiAgdmFyIHJ6ID0gbWF0W3ZzaGlmdCs4XVxuICB2YXIgcnUgPSByeCAqIHV4ICsgcnkgKiB1eSArIHJ6ICogdXpcbiAgcnggLT0gdXggKiBydVxuICByeSAtPSB1eSAqIHJ1XG4gIHJ6IC09IHV6ICogcnVcbiAgdmFyIHJsID0gbGVuMyhyeCwgcnksIHJ6KVxuICByeCAvPSBybFxuICByeSAvPSBybFxuICByeiAvPSBybFxuICBcbiAgdmFyIGZ4ID0gdXkgKiByeiAtIHV6ICogcnlcbiAgdmFyIGZ5ID0gdXogKiByeCAtIHV4ICogcnpcbiAgdmFyIGZ6ID0gdXggKiByeSAtIHV5ICogcnhcbiAgdmFyIGZsID0gbGVuMyhmeCwgZnksIGZ6KVxuICBmeCAvPSBmbFxuICBmeSAvPSBmbFxuICBmeiAvPSBmbFxuXG4gIHRoaXMuY2VudGVyLmp1bXAodCwgZXgsIGV5LCBleilcbiAgdGhpcy5yYWRpdXMuaWRsZSh0KVxuICB0aGlzLnVwLmp1bXAodCwgdXgsIHV5LCB1eilcbiAgdGhpcy5yaWdodC5qdW1wKHQsIHJ4LCByeSwgcnopXG5cbiAgdmFyIHBoaSwgdGhldGFcbiAgaWYodXNoaWZ0ID09PSAyKSB7XG4gICAgdmFyIGN4ID0gbWF0WzFdXG4gICAgdmFyIGN5ID0gbWF0WzVdXG4gICAgdmFyIGN6ID0gbWF0WzldXG4gICAgdmFyIGNyID0gY3ggKiByeCArIGN5ICogcnkgKyBjeiAqIHJ6XG4gICAgdmFyIGNmID0gY3ggKiBmeCArIGN5ICogZnkgKyBjeiAqIGZ6XG4gICAgaWYodHUgPCAwKSB7XG4gICAgICBwaGkgPSAtTWF0aC5QSS8yXG4gICAgfSBlbHNlIHtcbiAgICAgIHBoaSA9IE1hdGguUEkvMlxuICAgIH1cbiAgICB0aGV0YSA9IE1hdGguYXRhbjIoY2YsIGNyKVxuICB9IGVsc2Uge1xuICAgIHZhciB0eCA9IG1hdFsyXVxuICAgIHZhciB0eSA9IG1hdFs2XVxuICAgIHZhciB0eiA9IG1hdFsxMF1cbiAgICB2YXIgdHUgPSB0eCAqIHV4ICsgdHkgKiB1eSArIHR6ICogdXpcbiAgICB2YXIgdHIgPSB0eCAqIHJ4ICsgdHkgKiByeSArIHR6ICogcnpcbiAgICB2YXIgdGYgPSB0eCAqIGZ4ICsgdHkgKiBmeSArIHR6ICogZnpcblxuICAgIHBoaSA9IE1hdGguYXNpbihjbGFtcDEodHUpKVxuICAgIHRoZXRhID0gTWF0aC5hdGFuMih0ZiwgdHIpXG4gIH1cblxuICB0aGlzLmFuZ2xlLmp1bXAodCwgdGhldGEsIHBoaSlcblxuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuICB2YXIgZHggPSBtYXRbMl1cbiAgdmFyIGR5ID0gbWF0WzZdXG4gIHZhciBkeiA9IG1hdFsxMF1cblxuICB2YXIgaW1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgaW52ZXJ0NDQoaW1hdCwgbWF0KVxuICB2YXIgdyAgPSBpbWF0WzE1XVxuICB2YXIgZXggPSBpbWF0WzEyXSAvIHdcbiAgdmFyIGV5ID0gaW1hdFsxM10gLyB3XG4gIHZhciBleiA9IGltYXRbMTRdIC8gd1xuXG4gIHZhciBncyA9IE1hdGguZXhwKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pXG4gIHRoaXMuY2VudGVyLmp1bXAodCwgZXgtZHgqZ3MsIGV5LWR5KmdzLCBlei1keipncylcbn1cblxucHJvdG8ubGFzdFQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIE1hdGgubWF4KFxuICAgIHRoaXMuY2VudGVyLmxhc3RUKCksXG4gICAgdGhpcy51cC5sYXN0VCgpLFxuICAgIHRoaXMucmlnaHQubGFzdFQoKSxcbiAgICB0aGlzLnJhZGl1cy5sYXN0VCgpLFxuICAgIHRoaXMuYW5nbGUubGFzdFQoKSlcbn1cblxucHJvdG8uaWRsZSA9IGZ1bmN0aW9uKHQpIHtcbiAgdGhpcy5jZW50ZXIuaWRsZSh0KVxuICB0aGlzLnVwLmlkbGUodClcbiAgdGhpcy5yaWdodC5pZGxlKHQpXG4gIHRoaXMucmFkaXVzLmlkbGUodClcbiAgdGhpcy5hbmdsZS5pZGxlKHQpXG59XG5cbnByb3RvLmZsdXNoID0gZnVuY3Rpb24odCkge1xuICB0aGlzLmNlbnRlci5mbHVzaCh0KVxuICB0aGlzLnVwLmZsdXNoKHQpXG4gIHRoaXMucmlnaHQuZmx1c2godClcbiAgdGhpcy5yYWRpdXMuZmx1c2godClcbiAgdGhpcy5hbmdsZS5mbHVzaCh0KVxufVxuXG5wcm90by5zZXREaXN0YW5jZSA9IGZ1bmN0aW9uKHQsIGQpIHtcbiAgaWYoZCA+IDApIHtcbiAgICB0aGlzLnJhZGl1cy5zZXQodCwgTWF0aC5sb2coZCkpXG4gIH1cbn1cblxucHJvdG8ubG9va0F0ID0gZnVuY3Rpb24odCwgZXllLCBjZW50ZXIsIHVwKSB7XG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXG5cbiAgZXllICAgID0gZXllICAgIHx8IHRoaXMuY29tcHV0ZWRFeWVcbiAgY2VudGVyID0gY2VudGVyIHx8IHRoaXMuY29tcHV0ZWRDZW50ZXJcbiAgdXAgICAgID0gdXAgICAgIHx8IHRoaXMuY29tcHV0ZWRVcFxuXG4gIHZhciB1eCA9IHVwWzBdXG4gIHZhciB1eSA9IHVwWzFdXG4gIHZhciB1eiA9IHVwWzJdXG4gIHZhciB1bCA9IGxlbjModXgsIHV5LCB1eilcbiAgaWYodWwgPCAxZS02KSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdXggLz0gdWxcbiAgdXkgLz0gdWxcbiAgdXogLz0gdWxcblxuICB2YXIgdHggPSBleWVbMF0gLSBjZW50ZXJbMF1cbiAgdmFyIHR5ID0gZXllWzFdIC0gY2VudGVyWzFdXG4gIHZhciB0eiA9IGV5ZVsyXSAtIGNlbnRlclsyXVxuICB2YXIgdGwgPSBsZW4zKHR4LCB0eSwgdHopXG4gIGlmKHRsIDwgMWUtNikge1xuICAgIHJldHVyblxuICB9XG4gIHR4IC89IHRsXG4gIHR5IC89IHRsXG4gIHR6IC89IHRsXG5cbiAgdmFyIHJpZ2h0ID0gdGhpcy5jb21wdXRlZFJpZ2h0XG4gIHZhciByeCA9IHJpZ2h0WzBdXG4gIHZhciByeSA9IHJpZ2h0WzFdXG4gIHZhciByeiA9IHJpZ2h0WzJdXG4gIHZhciBydSA9IHV4KnJ4ICsgdXkqcnkgKyB1eipyelxuICByeCAtPSBydSAqIHV4XG4gIHJ5IC09IHJ1ICogdXlcbiAgcnogLT0gcnUgKiB1elxuICB2YXIgcmwgPSBsZW4zKHJ4LCByeSwgcnopXG5cbiAgaWYocmwgPCAwLjAxKSB7XG4gICAgcnggPSB1eSAqIHR6IC0gdXogKiB0eVxuICAgIHJ5ID0gdXogKiB0eCAtIHV4ICogdHpcbiAgICByeiA9IHV4ICogdHkgLSB1eSAqIHR4XG4gICAgcmwgPSBsZW4zKHJ4LCByeSwgcnopXG4gICAgaWYocmwgPCAxZS02KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gIH1cbiAgcnggLz0gcmxcbiAgcnkgLz0gcmxcbiAgcnogLz0gcmxcblxuICB0aGlzLnVwLnNldCh0LCB1eCwgdXksIHV6KVxuICB0aGlzLnJpZ2h0LnNldCh0LCByeCwgcnksIHJ6KVxuICB0aGlzLmNlbnRlci5zZXQodCwgY2VudGVyWzBdLCBjZW50ZXJbMV0sIGNlbnRlclsyXSlcbiAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKHRsKSlcblxuICB2YXIgZnggPSB1eSAqIHJ6IC0gdXogKiByeVxuICB2YXIgZnkgPSB1eiAqIHJ4IC0gdXggKiByelxuICB2YXIgZnogPSB1eCAqIHJ5IC0gdXkgKiByeFxuICB2YXIgZmwgPSBsZW4zKGZ4LCBmeSwgZnopXG4gIGZ4IC89IGZsXG4gIGZ5IC89IGZsXG4gIGZ6IC89IGZsXG5cbiAgdmFyIHR1ID0gdXgqdHggKyB1eSp0eSArIHV6KnR6XG4gIHZhciB0ciA9IHJ4KnR4ICsgcnkqdHkgKyByeip0elxuICB2YXIgdGYgPSBmeCp0eCArIGZ5KnR5ICsgZnoqdHpcblxuICB2YXIgcGhpICAgPSBNYXRoLmFzaW4oY2xhbXAxKHR1KSlcbiAgdmFyIHRoZXRhID0gTWF0aC5hdGFuMih0ZiwgdHIpXG5cbiAgdmFyIGFuZ2xlU3RhdGUgPSB0aGlzLmFuZ2xlLl9zdGF0ZVxuICB2YXIgbGFzdFRoZXRhICA9IGFuZ2xlU3RhdGVbYW5nbGVTdGF0ZS5sZW5ndGgtMV1cbiAgdmFyIGxhc3RQaGkgICAgPSBhbmdsZVN0YXRlW2FuZ2xlU3RhdGUubGVuZ3RoLTJdXG4gIGxhc3RUaGV0YSAgICAgID0gbGFzdFRoZXRhICUgKDIuMCAqIE1hdGguUEkpXG4gIHZhciBkcCA9IE1hdGguYWJzKGxhc3RUaGV0YSArIDIuMCAqIE1hdGguUEkgLSB0aGV0YSlcbiAgdmFyIGQwID0gTWF0aC5hYnMobGFzdFRoZXRhIC0gdGhldGEpXG4gIHZhciBkbiA9IE1hdGguYWJzKGxhc3RUaGV0YSAtIDIuMCAqIE1hdGguUEkgLSB0aGV0YSlcbiAgaWYoZHAgPCBkMCkge1xuICAgIGxhc3RUaGV0YSArPSAyLjAgKiBNYXRoLlBJXG4gIH1cbiAgaWYoZG4gPCBkMCkge1xuICAgIGxhc3RUaGV0YSAtPSAyLjAgKiBNYXRoLlBJXG4gIH1cblxuICB0aGlzLmFuZ2xlLmp1bXAodGhpcy5hbmdsZS5sYXN0VCgpLCBsYXN0VGhldGEsIGxhc3RQaGkpXG4gIHRoaXMuYW5nbGUuc2V0KHQsIHRoZXRhLCBwaGkpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR1cm50YWJsZUNvbnRyb2xsZXIob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIHZhciBjZW50ZXIgPSBvcHRpb25zLmNlbnRlciB8fCBbMCwwLDBdXG4gIHZhciB1cCAgICAgPSBvcHRpb25zLnVwICAgICB8fCBbMCwxLDBdXG4gIHZhciByaWdodCAgPSBvcHRpb25zLnJpZ2h0ICB8fCBmaW5kT3J0aG9QYWlyKHVwKVxuICB2YXIgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXMgfHwgMS4wXG4gIHZhciB0aGV0YSAgPSBvcHRpb25zLnRoZXRhICB8fCAwLjBcbiAgdmFyIHBoaSAgICA9IG9wdGlvbnMucGhpICAgIHx8IDAuMFxuXG4gIGNlbnRlciA9IFtdLnNsaWNlLmNhbGwoY2VudGVyLCAwLCAzKVxuXG4gIHVwID0gW10uc2xpY2UuY2FsbCh1cCwgMCwgMylcbiAgbm9ybWFsaXplMyh1cCwgdXApXG5cbiAgcmlnaHQgPSBbXS5zbGljZS5jYWxsKHJpZ2h0LCAwLCAzKVxuICBub3JtYWxpemUzKHJpZ2h0LCByaWdodClcblxuICBpZignZXllJyBpbiBvcHRpb25zKSB7XG4gICAgdmFyIGV5ZSA9IG9wdGlvbnMuZXllXG4gICAgdmFyIHRvd2FyZCA9IFtcbiAgICAgIGV5ZVswXS1jZW50ZXJbMF0sXG4gICAgICBleWVbMV0tY2VudGVyWzFdLFxuICAgICAgZXllWzJdLWNlbnRlclsyXVxuICAgIF1cbiAgICBjcm9zcyhyaWdodCwgdG93YXJkLCB1cClcbiAgICBpZihsZW4zKHJpZ2h0WzBdLCByaWdodFsxXSwgcmlnaHRbMl0pIDwgMWUtNikge1xuICAgICAgcmlnaHQgPSBmaW5kT3J0aG9QYWlyKHVwKVxuICAgIH0gZWxzZSB7XG4gICAgICBub3JtYWxpemUzKHJpZ2h0LCByaWdodClcbiAgICB9XG5cbiAgICByYWRpdXMgPSBsZW4zKHRvd2FyZFswXSwgdG93YXJkWzFdLCB0b3dhcmRbMl0pXG5cbiAgICB2YXIgdXQgPSBkb3QzKHVwLCB0b3dhcmQpIC8gcmFkaXVzXG4gICAgdmFyIHJ0ID0gZG90MyhyaWdodCwgdG93YXJkKSAvIHJhZGl1c1xuICAgIHBoaSAgICA9IE1hdGguYWNvcyh1dClcbiAgICB0aGV0YSAgPSBNYXRoLmFjb3MocnQpXG4gIH1cblxuICAvL1VzZSBsb2dhcml0aG1pYyBjb29yZGluYXRlcyBmb3IgcmFkaXVzXG4gIHJhZGl1cyA9IE1hdGgubG9nKHJhZGl1cylcblxuICAvL1JldHVybiB0aGUgY29udHJvbGxlclxuICByZXR1cm4gbmV3IFR1cm50YWJsZUNvbnRyb2xsZXIoXG4gICAgb3B0aW9ucy56b29tTWluLFxuICAgIG9wdGlvbnMuem9vbU1heCxcbiAgICBjZW50ZXIsXG4gICAgdXAsXG4gICAgcmlnaHQsXG4gICAgcmFkaXVzLFxuICAgIHRoZXRhLFxuICAgIHBoaSlcbn0iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHR3b1Byb2R1Y3RcblxudmFyIFNQTElUVEVSID0gKyhNYXRoLnBvdygyLCAyNykgKyAxLjApXG5cbmZ1bmN0aW9uIHR3b1Byb2R1Y3QoYSwgYiwgcmVzdWx0KSB7XG4gIHZhciB4ID0gYSAqIGJcblxuICB2YXIgYyA9IFNQTElUVEVSICogYVxuICB2YXIgYWJpZyA9IGMgLSBhXG4gIHZhciBhaGkgPSBjIC0gYWJpZ1xuICB2YXIgYWxvID0gYSAtIGFoaVxuXG4gIHZhciBkID0gU1BMSVRURVIgKiBiXG4gIHZhciBiYmlnID0gZCAtIGJcbiAgdmFyIGJoaSA9IGQgLSBiYmlnXG4gIHZhciBibG8gPSBiIC0gYmhpXG5cbiAgdmFyIGVycjEgPSB4IC0gKGFoaSAqIGJoaSlcbiAgdmFyIGVycjIgPSBlcnIxIC0gKGFsbyAqIGJoaSlcbiAgdmFyIGVycjMgPSBlcnIyIC0gKGFoaSAqIGJsbylcblxuICB2YXIgeSA9IGFsbyAqIGJsbyAtIGVycjNcblxuICBpZihyZXN1bHQpIHtcbiAgICByZXN1bHRbMF0gPSB5XG4gICAgcmVzdWx0WzFdID0geFxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIHJldHVybiBbIHksIHggXVxufSIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZmFzdFR3b1N1bVxuXG5mdW5jdGlvbiBmYXN0VHdvU3VtKGEsIGIsIHJlc3VsdCkge1xuXHR2YXIgeCA9IGEgKyBiXG5cdHZhciBidiA9IHggLSBhXG5cdHZhciBhdiA9IHggLSBidlxuXHR2YXIgYnIgPSBiIC0gYnZcblx0dmFyIGFyID0gYSAtIGF2XG5cdGlmKHJlc3VsdCkge1xuXHRcdHJlc3VsdFswXSA9IGFyICsgYnJcblx0XHRyZXN1bHRbMV0gPSB4XG5cdFx0cmV0dXJuIHJlc3VsdFxuXHR9XG5cdHJldHVybiBbYXIrYnIsIHhdXG59IiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBiaXRzID0gcmVxdWlyZSgnYml0LXR3aWRkbGUnKVxudmFyIGR1cCA9IHJlcXVpcmUoJ2R1cCcpXG5cbi8vTGVnYWN5IHBvb2wgc3VwcG9ydFxuaWYoIWdsb2JhbC5fX1RZUEVEQVJSQVlfUE9PTCkge1xuICBnbG9iYWwuX19UWVBFREFSUkFZX1BPT0wgPSB7XG4gICAgICBVSU5UOCAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBVSU5UMTYgIDogZHVwKFszMiwgMF0pXG4gICAgLCBVSU5UMzIgIDogZHVwKFszMiwgMF0pXG4gICAgLCBJTlQ4ICAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBJTlQxNiAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBJTlQzMiAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBGTE9BVCAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBET1VCTEUgIDogZHVwKFszMiwgMF0pXG4gICAgLCBEQVRBICAgIDogZHVwKFszMiwgMF0pXG4gICAgLCBVSU5UOEMgIDogZHVwKFszMiwgMF0pXG4gICAgLCBCVUZGRVIgIDogZHVwKFszMiwgMF0pXG4gIH1cbn1cblxudmFyIGhhc1VpbnQ4QyA9ICh0eXBlb2YgVWludDhDbGFtcGVkQXJyYXkpICE9PSAndW5kZWZpbmVkJ1xudmFyIFBPT0wgPSBnbG9iYWwuX19UWVBFREFSUkFZX1BPT0xcblxuLy9VcGdyYWRlIHBvb2xcbmlmKCFQT09MLlVJTlQ4Qykge1xuICBQT09MLlVJTlQ4QyA9IGR1cChbMzIsIDBdKVxufVxuaWYoIVBPT0wuQlVGRkVSKSB7XG4gIFBPT0wuQlVGRkVSID0gZHVwKFszMiwgMF0pXG59XG5cbi8vTmV3IHRlY2huaXF1ZTogT25seSBhbGxvY2F0ZSBmcm9tIEFycmF5QnVmZmVyVmlldyBhbmQgQnVmZmVyXG52YXIgREFUQSAgICA9IFBPT0wuREFUQVxuICAsIEJVRkZFUiAgPSBQT09MLkJVRkZFUlxuXG5leHBvcnRzLmZyZWUgPSBmdW5jdGlvbiBmcmVlKGFycmF5KSB7XG4gIGlmKEJ1ZmZlci5pc0J1ZmZlcihhcnJheSkpIHtcbiAgICBCVUZGRVJbYml0cy5sb2cyKGFycmF5Lmxlbmd0aCldLnB1c2goYXJyYXkpXG4gIH0gZWxzZSB7XG4gICAgaWYoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFycmF5KSAhPT0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJykge1xuICAgICAgYXJyYXkgPSBhcnJheS5idWZmZXJcbiAgICB9XG4gICAgaWYoIWFycmF5KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdmFyIG4gPSBhcnJheS5sZW5ndGggfHwgYXJyYXkuYnl0ZUxlbmd0aFxuICAgIHZhciBsb2dfbiA9IGJpdHMubG9nMihuKXwwXG4gICAgREFUQVtsb2dfbl0ucHVzaChhcnJheSlcbiAgfVxufVxuXG5mdW5jdGlvbiBmcmVlQXJyYXlCdWZmZXIoYnVmZmVyKSB7XG4gIGlmKCFidWZmZXIpIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgbiA9IGJ1ZmZlci5sZW5ndGggfHwgYnVmZmVyLmJ5dGVMZW5ndGhcbiAgdmFyIGxvZ19uID0gYml0cy5sb2cyKG4pXG4gIERBVEFbbG9nX25dLnB1c2goYnVmZmVyKVxufVxuXG5mdW5jdGlvbiBmcmVlVHlwZWRBcnJheShhcnJheSkge1xuICBmcmVlQXJyYXlCdWZmZXIoYXJyYXkuYnVmZmVyKVxufVxuXG5leHBvcnRzLmZyZWVVaW50OCA9XG5leHBvcnRzLmZyZWVVaW50MTYgPVxuZXhwb3J0cy5mcmVlVWludDMyID1cbmV4cG9ydHMuZnJlZUludDggPVxuZXhwb3J0cy5mcmVlSW50MTYgPVxuZXhwb3J0cy5mcmVlSW50MzIgPVxuZXhwb3J0cy5mcmVlRmxvYXQzMiA9IFxuZXhwb3J0cy5mcmVlRmxvYXQgPVxuZXhwb3J0cy5mcmVlRmxvYXQ2NCA9IFxuZXhwb3J0cy5mcmVlRG91YmxlID0gXG5leHBvcnRzLmZyZWVVaW50OENsYW1wZWQgPSBcbmV4cG9ydHMuZnJlZURhdGFWaWV3ID0gZnJlZVR5cGVkQXJyYXlcblxuZXhwb3J0cy5mcmVlQXJyYXlCdWZmZXIgPSBmcmVlQXJyYXlCdWZmZXJcblxuZXhwb3J0cy5mcmVlQnVmZmVyID0gZnVuY3Rpb24gZnJlZUJ1ZmZlcihhcnJheSkge1xuICBCVUZGRVJbYml0cy5sb2cyKGFycmF5Lmxlbmd0aCldLnB1c2goYXJyYXkpXG59XG5cbmV4cG9ydHMubWFsbG9jID0gZnVuY3Rpb24gbWFsbG9jKG4sIGR0eXBlKSB7XG4gIGlmKGR0eXBlID09PSB1bmRlZmluZWQgfHwgZHR5cGUgPT09ICdhcnJheWJ1ZmZlcicpIHtcbiAgICByZXR1cm4gbWFsbG9jQXJyYXlCdWZmZXIobilcbiAgfSBlbHNlIHtcbiAgICBzd2l0Y2goZHR5cGUpIHtcbiAgICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY1VpbnQ4KG4pXG4gICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgICByZXR1cm4gbWFsbG9jVWludDE2KG4pXG4gICAgICBjYXNlICd1aW50MzInOlxuICAgICAgICByZXR1cm4gbWFsbG9jVWludDMyKG4pXG4gICAgICBjYXNlICdpbnQ4JzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY0ludDgobilcbiAgICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY0ludDE2KG4pXG4gICAgICBjYXNlICdpbnQzMic6XG4gICAgICAgIHJldHVybiBtYWxsb2NJbnQzMihuKVxuICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICAgIHJldHVybiBtYWxsb2NGbG9hdChuKVxuICAgICAgY2FzZSAnZG91YmxlJzpcbiAgICAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgICAgICByZXR1cm4gbWFsbG9jRG91YmxlKG4pXG4gICAgICBjYXNlICd1aW50OF9jbGFtcGVkJzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY1VpbnQ4Q2xhbXBlZChuKVxuICAgICAgY2FzZSAnYnVmZmVyJzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY0J1ZmZlcihuKVxuICAgICAgY2FzZSAnZGF0YSc6XG4gICAgICBjYXNlICdkYXRhdmlldyc6XG4gICAgICAgIHJldHVybiBtYWxsb2NEYXRhVmlldyhuKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbFxufVxuXG5mdW5jdGlvbiBtYWxsb2NBcnJheUJ1ZmZlcihuKSB7XG4gIHZhciBuID0gYml0cy5uZXh0UG93MihuKVxuICB2YXIgbG9nX24gPSBiaXRzLmxvZzIobilcbiAgdmFyIGQgPSBEQVRBW2xvZ19uXVxuICBpZihkLmxlbmd0aCA+IDApIHtcbiAgICByZXR1cm4gZC5wb3AoKVxuICB9XG4gIHJldHVybiBuZXcgQXJyYXlCdWZmZXIobilcbn1cbmV4cG9ydHMubWFsbG9jQXJyYXlCdWZmZXIgPSBtYWxsb2NBcnJheUJ1ZmZlclxuXG5mdW5jdGlvbiBtYWxsb2NVaW50OChuKSB7XG4gIHJldHVybiBuZXcgVWludDhBcnJheShtYWxsb2NBcnJheUJ1ZmZlcihuKSwgMCwgbilcbn1cbmV4cG9ydHMubWFsbG9jVWludDggPSBtYWxsb2NVaW50OFxuXG5mdW5jdGlvbiBtYWxsb2NVaW50MTYobikge1xuICByZXR1cm4gbmV3IFVpbnQxNkFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDIqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY1VpbnQxNiA9IG1hbGxvY1VpbnQxNlxuXG5mdW5jdGlvbiBtYWxsb2NVaW50MzIobikge1xuICByZXR1cm4gbmV3IFVpbnQzMkFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDQqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY1VpbnQzMiA9IG1hbGxvY1VpbnQzMlxuXG5mdW5jdGlvbiBtYWxsb2NJbnQ4KG4pIHtcbiAgcmV0dXJuIG5ldyBJbnQ4QXJyYXkobWFsbG9jQXJyYXlCdWZmZXIobiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0ludDggPSBtYWxsb2NJbnQ4XG5cbmZ1bmN0aW9uIG1hbGxvY0ludDE2KG4pIHtcbiAgcmV0dXJuIG5ldyBJbnQxNkFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDIqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0ludDE2ID0gbWFsbG9jSW50MTZcblxuZnVuY3Rpb24gbWFsbG9jSW50MzIobikge1xuICByZXR1cm4gbmV3IEludDMyQXJyYXkobWFsbG9jQXJyYXlCdWZmZXIoNCpuKSwgMCwgbilcbn1cbmV4cG9ydHMubWFsbG9jSW50MzIgPSBtYWxsb2NJbnQzMlxuXG5mdW5jdGlvbiBtYWxsb2NGbG9hdChuKSB7XG4gIHJldHVybiBuZXcgRmxvYXQzMkFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDQqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0Zsb2F0MzIgPSBleHBvcnRzLm1hbGxvY0Zsb2F0ID0gbWFsbG9jRmxvYXRcblxuZnVuY3Rpb24gbWFsbG9jRG91YmxlKG4pIHtcbiAgcmV0dXJuIG5ldyBGbG9hdDY0QXJyYXkobWFsbG9jQXJyYXlCdWZmZXIoOCpuKSwgMCwgbilcbn1cbmV4cG9ydHMubWFsbG9jRmxvYXQ2NCA9IGV4cG9ydHMubWFsbG9jRG91YmxlID0gbWFsbG9jRG91YmxlXG5cbmZ1bmN0aW9uIG1hbGxvY1VpbnQ4Q2xhbXBlZChuKSB7XG4gIGlmKGhhc1VpbnQ4Qykge1xuICAgIHJldHVybiBuZXcgVWludDhDbGFtcGVkQXJyYXkobWFsbG9jQXJyYXlCdWZmZXIobiksIDAsIG4pXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG1hbGxvY1VpbnQ4KG4pXG4gIH1cbn1cbmV4cG9ydHMubWFsbG9jVWludDhDbGFtcGVkID0gbWFsbG9jVWludDhDbGFtcGVkXG5cbmZ1bmN0aW9uIG1hbGxvY0RhdGFWaWV3KG4pIHtcbiAgcmV0dXJuIG5ldyBEYXRhVmlldyhtYWxsb2NBcnJheUJ1ZmZlcihuKSwgMCwgbilcbn1cbmV4cG9ydHMubWFsbG9jRGF0YVZpZXcgPSBtYWxsb2NEYXRhVmlld1xuXG5mdW5jdGlvbiBtYWxsb2NCdWZmZXIobikge1xuICBuID0gYml0cy5uZXh0UG93MihuKVxuICB2YXIgbG9nX24gPSBiaXRzLmxvZzIobilcbiAgdmFyIGNhY2hlID0gQlVGRkVSW2xvZ19uXVxuICBpZihjYWNoZS5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGNhY2hlLnBvcCgpXG4gIH1cbiAgcmV0dXJuIG5ldyBCdWZmZXIobilcbn1cbmV4cG9ydHMubWFsbG9jQnVmZmVyID0gbWFsbG9jQnVmZmVyXG5cbmV4cG9ydHMuY2xlYXJDYWNoZSA9IGZ1bmN0aW9uIGNsZWFyQ2FjaGUoKSB7XG4gIGZvcih2YXIgaT0wOyBpPDMyOyArK2kpIHtcbiAgICBQT09MLlVJTlQ4W2ldLmxlbmd0aCA9IDBcbiAgICBQT09MLlVJTlQxNltpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5VSU5UMzJbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuSU5UOFtpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5JTlQxNltpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5JTlQzMltpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5GTE9BVFtpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5ET1VCTEVbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuVUlOVDhDW2ldLmxlbmd0aCA9IDBcbiAgICBEQVRBW2ldLmxlbmd0aCA9IDBcbiAgICBCVUZGRVJbaV0ubGVuZ3RoID0gMFxuICB9XG59IiwiXCJ1c2Ugc3RyaWN0XCI7IFwidXNlIHJlc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gVW5pb25GaW5kO1xuXG5mdW5jdGlvbiBVbmlvbkZpbmQoY291bnQpIHtcbiAgdGhpcy5yb290cyA9IG5ldyBBcnJheShjb3VudCk7XG4gIHRoaXMucmFua3MgPSBuZXcgQXJyYXkoY291bnQpO1xuICBcbiAgZm9yKHZhciBpPTA7IGk8Y291bnQ7ICsraSkge1xuICAgIHRoaXMucm9vdHNbaV0gPSBpO1xuICAgIHRoaXMucmFua3NbaV0gPSAwO1xuICB9XG59XG5cbnZhciBwcm90byA9IFVuaW9uRmluZC5wcm90b3R5cGVcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBcImxlbmd0aFwiLCB7XG4gIFwiZ2V0XCI6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJvb3RzLmxlbmd0aFxuICB9XG59KVxuXG5wcm90by5tYWtlU2V0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBuID0gdGhpcy5yb290cy5sZW5ndGg7XG4gIHRoaXMucm9vdHMucHVzaChuKTtcbiAgdGhpcy5yYW5rcy5wdXNoKDApO1xuICByZXR1cm4gbjtcbn1cblxucHJvdG8uZmluZCA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIHgwID0geFxuICB2YXIgcm9vdHMgPSB0aGlzLnJvb3RzO1xuICB3aGlsZShyb290c1t4XSAhPT0geCkge1xuICAgIHggPSByb290c1t4XVxuICB9XG4gIHdoaWxlKHJvb3RzW3gwXSAhPT0geCkge1xuICAgIHZhciB5ID0gcm9vdHNbeDBdXG4gICAgcm9vdHNbeDBdID0geFxuICAgIHgwID0geVxuICB9XG4gIHJldHVybiB4O1xufVxuXG5wcm90by5saW5rID0gZnVuY3Rpb24oeCwgeSkge1xuICB2YXIgeHIgPSB0aGlzLmZpbmQoeClcbiAgICAsIHlyID0gdGhpcy5maW5kKHkpO1xuICBpZih4ciA9PT0geXIpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIHJhbmtzID0gdGhpcy5yYW5rc1xuICAgICwgcm9vdHMgPSB0aGlzLnJvb3RzXG4gICAgLCB4ZCAgICA9IHJhbmtzW3hyXVxuICAgICwgeWQgICAgPSByYW5rc1t5cl07XG4gIGlmKHhkIDwgeWQpIHtcbiAgICByb290c1t4cl0gPSB5cjtcbiAgfSBlbHNlIGlmKHlkIDwgeGQpIHtcbiAgICByb290c1t5cl0gPSB4cjtcbiAgfSBlbHNlIHtcbiAgICByb290c1t5cl0gPSB4cjtcbiAgICArK3JhbmtzW3hyXTtcbiAgfVxufSIsIlwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIHVuaXF1ZV9wcmVkKGxpc3QsIGNvbXBhcmUpIHtcbiAgdmFyIHB0ciA9IDFcbiAgICAsIGxlbiA9IGxpc3QubGVuZ3RoXG4gICAgLCBhPWxpc3RbMF0sIGI9bGlzdFswXVxuICBmb3IodmFyIGk9MTsgaTxsZW47ICsraSkge1xuICAgIGIgPSBhXG4gICAgYSA9IGxpc3RbaV1cbiAgICBpZihjb21wYXJlKGEsIGIpKSB7XG4gICAgICBpZihpID09PSBwdHIpIHtcbiAgICAgICAgcHRyKytcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGxpc3RbcHRyKytdID0gYVxuICAgIH1cbiAgfVxuICBsaXN0Lmxlbmd0aCA9IHB0clxuICByZXR1cm4gbGlzdFxufVxuXG5mdW5jdGlvbiB1bmlxdWVfZXEobGlzdCkge1xuICB2YXIgcHRyID0gMVxuICAgICwgbGVuID0gbGlzdC5sZW5ndGhcbiAgICAsIGE9bGlzdFswXSwgYiA9IGxpc3RbMF1cbiAgZm9yKHZhciBpPTE7IGk8bGVuOyArK2ksIGI9YSkge1xuICAgIGIgPSBhXG4gICAgYSA9IGxpc3RbaV1cbiAgICBpZihhICE9PSBiKSB7XG4gICAgICBpZihpID09PSBwdHIpIHtcbiAgICAgICAgcHRyKytcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGxpc3RbcHRyKytdID0gYVxuICAgIH1cbiAgfVxuICBsaXN0Lmxlbmd0aCA9IHB0clxuICByZXR1cm4gbGlzdFxufVxuXG5mdW5jdGlvbiB1bmlxdWUobGlzdCwgY29tcGFyZSwgc29ydGVkKSB7XG4gIGlmKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGxpc3RcbiAgfVxuICBpZihjb21wYXJlKSB7XG4gICAgaWYoIXNvcnRlZCkge1xuICAgICAgbGlzdC5zb3J0KGNvbXBhcmUpXG4gICAgfVxuICAgIHJldHVybiB1bmlxdWVfcHJlZChsaXN0LCBjb21wYXJlKVxuICB9XG4gIGlmKCFzb3J0ZWQpIHtcbiAgICBsaXN0LnNvcnQoKVxuICB9XG4gIHJldHVybiB1bmlxdWVfZXEobGlzdClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB1bmlxdWVcbiIsInZhciByZWcgPSAvW1xcJ1xcXCJdL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHVucXVvdGUoc3RyKSB7XG4gIGlmICghc3RyKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cbiAgaWYgKHJlZy50ZXN0KHN0ci5jaGFyQXQoMCkpKSB7XG4gICAgc3RyID0gc3RyLnN1YnN0cigxKVxuICB9XG4gIGlmIChyZWcudGVzdChzdHIuY2hhckF0KHN0ci5sZW5ndGggLSAxKSkpIHtcbiAgICBzdHIgPSBzdHIuc3Vic3RyKDAsIHN0ci5sZW5ndGggLSAxKVxuICB9XG4gIHJldHVybiBzdHJcbn1cbiIsIi8qKlxyXG4gKiBAbW9kdWxlIHVwZGF0ZS1kaWZmXHJcbiAqL1xyXG5cclxuJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHVwZGF0ZURpZmYgKG9iaiwgZGlmZiwgbWFwcGVycykge1xyXG5cdGlmICghQXJyYXkuaXNBcnJheShtYXBwZXJzKSkgbWFwcGVycyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKVxyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbCA9IG1hcHBlcnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcblx0XHR2YXIgZGljdCA9IG1hcHBlcnNbaV1cclxuXHRcdGZvciAodmFyIHByb3AgaW4gZGljdCkge1xyXG5cdFx0XHRpZiAoZGlmZltwcm9wXSAhPT0gdW5kZWZpbmVkICYmICFBcnJheS5pc0FycmF5KGRpZmZbcHJvcF0pICYmIG9ialtwcm9wXSA9PT0gZGlmZltwcm9wXSkgY29udGludWVcclxuXHJcblx0XHRcdGlmIChwcm9wIGluIGRpZmYpIHtcclxuXHRcdFx0XHR2YXIgcmVzdWx0XHJcblxyXG5cdFx0XHRcdGlmIChkaWN0W3Byb3BdID09PSB0cnVlKSByZXN1bHQgPSBkaWZmW3Byb3BdXHJcblx0XHRcdFx0ZWxzZSBpZiAoZGljdFtwcm9wXSA9PT0gZmFsc2UpIGNvbnRpbnVlXHJcblx0XHRcdFx0ZWxzZSBpZiAodHlwZW9mIGRpY3RbcHJvcF0gPT09ICdmdW5jdGlvbicpIHtcclxuXHRcdFx0XHRcdHJlc3VsdCA9IGRpY3RbcHJvcF0oZGlmZltwcm9wXSwgb2JqLCBkaWZmKVxyXG5cdFx0XHRcdFx0aWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkKSBjb250aW51ZVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0b2JqW3Byb3BdID0gcmVzdWx0XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBvYmpcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVRleHRcblxudmFyIHZlY3Rvcml6ZVRleHQgPSByZXF1aXJlKFwiLi9saWIvdnRleHRcIilcbnZhciBkZWZhdWx0Q2FudmFzID0gbnVsbFxudmFyIGRlZmF1bHRDb250ZXh0ID0gbnVsbFxuXG5pZih0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gIGRlZmF1bHRDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICBkZWZhdWx0Q2FudmFzLndpZHRoID0gODE5MlxuICBkZWZhdWx0Q2FudmFzLmhlaWdodCA9IDEwMjRcbiAgZGVmYXVsdENvbnRleHQgPSBkZWZhdWx0Q2FudmFzLmdldENvbnRleHQoXCIyZFwiKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUZXh0KHN0ciwgb3B0aW9ucykge1xuICBpZigodHlwZW9mIG9wdGlvbnMgIT09IFwib2JqZWN0XCIpIHx8IChvcHRpb25zID09PSBudWxsKSkge1xuICAgIG9wdGlvbnMgPSB7fVxuICB9XG4gIHJldHVybiB2ZWN0b3JpemVUZXh0KFxuICAgIHN0cixcbiAgICBvcHRpb25zLmNhbnZhcyB8fCBkZWZhdWx0Q2FudmFzLFxuICAgIG9wdGlvbnMuY29udGV4dCB8fCBkZWZhdWx0Q29udGV4dCxcbiAgICBvcHRpb25zKVxufVxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSB2ZWN0b3JpemVUZXh0XG5tb2R1bGUuZXhwb3J0cy5wcm9jZXNzUGl4ZWxzID0gcHJvY2Vzc1BpeGVsc1xuXG52YXIgc3VyZmFjZU5ldHMgPSByZXF1aXJlKCdzdXJmYWNlLW5ldHMnKVxudmFyIG5kYXJyYXkgPSByZXF1aXJlKCduZGFycmF5JylcbnZhciBzaW1wbGlmeSA9IHJlcXVpcmUoJ3NpbXBsaWZ5LXBsYW5hci1ncmFwaCcpXG52YXIgY2xlYW5QU0xHID0gcmVxdWlyZSgnY2xlYW4tcHNsZycpXG52YXIgY2R0MmQgPSByZXF1aXJlKCdjZHQyZCcpXG52YXIgdG9Qb2x5Z29uQ3JhcHB5ID0gcmVxdWlyZSgncGxhbmFyLWdyYXBoLXRvLXBvbHlsaW5lJylcblxuZnVuY3Rpb24gdHJhbnNmb3JtUG9zaXRpb25zKHBvc2l0aW9ucywgb3B0aW9ucywgc2l6ZSkge1xuICB2YXIgYWxpZ24gPSBvcHRpb25zLnRleHRBbGlnbiB8fCBcInN0YXJ0XCJcbiAgdmFyIGJhc2VsaW5lID0gb3B0aW9ucy50ZXh0QmFzZWxpbmUgfHwgXCJhbHBoYWJldGljXCJcblxuICB2YXIgbG8gPSBbMTw8MzAsIDE8PDMwXVxuICB2YXIgaGkgPSBbMCwwXVxuICB2YXIgbiA9IHBvc2l0aW9ucy5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgdmFyIHAgPSBwb3NpdGlvbnNbaV1cbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgIGxvW2pdID0gTWF0aC5taW4obG9bal0sIHBbal0pfDBcbiAgICAgIGhpW2pdID0gTWF0aC5tYXgoaGlbal0sIHBbal0pfDBcbiAgICB9XG4gIH1cblxuICB2YXIgeFNoaWZ0ID0gMFxuICBzd2l0Y2goYWxpZ24pIHtcbiAgICBjYXNlIFwiY2VudGVyXCI6XG4gICAgICB4U2hpZnQgPSAtMC41ICogKGxvWzBdICsgaGlbMF0pXG4gICAgYnJlYWtcblxuICAgIGNhc2UgXCJyaWdodFwiOlxuICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgIHhTaGlmdCA9IC1oaVswXVxuICAgIGJyZWFrXG5cbiAgICBjYXNlIFwibGVmdFwiOlxuICAgIGNhc2UgXCJzdGFydFwiOlxuICAgICAgeFNoaWZ0ID0gLWxvWzBdXG4gICAgYnJlYWtcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ2ZWN0b3JpemUtdGV4dDogVW5yZWNvZ25pemVkIHRleHRBbGlnbjogJ1wiICsgYWxpZ24gKyBcIidcIilcbiAgfVxuXG4gIHZhciB5U2hpZnQgPSAwXG4gIHN3aXRjaChiYXNlbGluZSkge1xuICAgIGNhc2UgXCJoYW5naW5nXCI6XG4gICAgY2FzZSBcInRvcFwiOlxuICAgICAgeVNoaWZ0ID0gLWxvWzFdXG4gICAgYnJlYWtcblxuICAgIGNhc2UgXCJtaWRkbGVcIjpcbiAgICAgIHlTaGlmdCA9IC0wLjUgKiAobG9bMV0gKyBoaVsxXSlcbiAgICBicmVha1xuXG4gICAgY2FzZSBcImFscGhhYmV0aWNcIjpcbiAgICBjYXNlIFwiaWRlb2dyYXBoaWNcIjpcbiAgICAgIHlTaGlmdCA9IC0zICogc2l6ZVxuICAgIGJyZWFrXG5cbiAgICBjYXNlIFwiYm90dG9tXCI6XG4gICAgICB5U2hpZnQgPSAtaGlbMV1cbiAgICBicmVha1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInZlY3Rvcml6ZS10ZXh0OiBVbnJlY29naW5pemVkIHRleHRCYXNlbGluZTogJ1wiICsgYmFzZWxpbmUgKyBcIidcIilcbiAgfVxuXG4gIHZhciBzY2FsZSA9IDEuMCAvIHNpemVcbiAgaWYoXCJsaW5lSGVpZ2h0XCIgaW4gb3B0aW9ucykge1xuICAgIHNjYWxlICo9ICtvcHRpb25zLmxpbmVIZWlnaHRcbiAgfSBlbHNlIGlmKFwid2lkdGhcIiBpbiBvcHRpb25zKSB7XG4gICAgc2NhbGUgPSBvcHRpb25zLndpZHRoIC8gKGhpWzBdIC0gbG9bMF0pXG4gIH0gZWxzZSBpZihcImhlaWdodFwiIGluIG9wdGlvbnMpIHtcbiAgICBzY2FsZSA9IG9wdGlvbnMuaGVpZ2h0IC8gKGhpWzFdIC0gbG9bMV0pXG4gIH1cblxuICByZXR1cm4gcG9zaXRpb25zLm1hcChmdW5jdGlvbihwKSB7XG4gICAgcmV0dXJuIFsgc2NhbGUgKiAocFswXSArIHhTaGlmdCksIHNjYWxlICogKHBbMV0gKyB5U2hpZnQpIF1cbiAgfSlcbn1cblxuZnVuY3Rpb24gZ2V0UGl4ZWxzKGNhbnZhcywgY29udGV4dCwgc3RyLCBzaXplKSB7XG4gIHZhciB3aWR0aCA9IE1hdGguY2VpbChjb250ZXh0Lm1lYXN1cmVUZXh0KHN0cikud2lkdGggKyAyKnNpemUpfDBcbiAgaWYod2lkdGggPiA4MTkyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidmVjdG9yaXplLXRleHQ6IFN0cmluZyB0b28gbG9uZyAoc29ycnksIHRoaXMgd2lsbCBnZXQgZml4ZWQgbGF0ZXIpXCIpXG4gIH1cbiAgdmFyIGhlaWdodCA9IDMgKiBzaXplXG4gIGlmKGNhbnZhcy5oZWlnaHQgPCBoZWlnaHQpIHtcbiAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0XG4gIH1cblxuICBjb250ZXh0LmZpbGxTdHlsZSA9IFwiIzAwMFwiXG4gIGNvbnRleHQuZmlsbFJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KVxuXG4gIGNvbnRleHQuZmlsbFN0eWxlID0gXCIjZmZmXCJcbiAgY29udGV4dC5maWxsVGV4dChzdHIsIHNpemUsIDIqc2l6ZSlcblxuICAvL0N1dCBwaXhlbHMgZnJvbSBpbWFnZVxuICB2YXIgcGl4ZWxEYXRhID0gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgd2lkdGgsIGhlaWdodClcbiAgdmFyIHBpeGVscyA9IG5kYXJyYXkocGl4ZWxEYXRhLmRhdGEsIFtoZWlnaHQsIHdpZHRoLCA0XSlcblxuICByZXR1cm4gcGl4ZWxzLnBpY2soLTEsLTEsMCkudHJhbnNwb3NlKDEsMClcbn1cblxuZnVuY3Rpb24gZ2V0Q29udG91cihwaXhlbHMsIGRvU2ltcGxpZnkpIHtcbiAgdmFyIGNvbnRvdXIgPSBzdXJmYWNlTmV0cyhwaXhlbHMsIDEyOClcbiAgaWYoZG9TaW1wbGlmeSkge1xuICAgIHJldHVybiBzaW1wbGlmeShjb250b3VyLmNlbGxzLCBjb250b3VyLnBvc2l0aW9ucywgMC4yNSlcbiAgfVxuICByZXR1cm4ge1xuICAgIGVkZ2VzOiBjb250b3VyLmNlbGxzLFxuICAgIHBvc2l0aW9uczogY29udG91ci5wb3NpdGlvbnNcbiAgfVxufVxuXG5mdW5jdGlvbiBwcm9jZXNzUGl4ZWxzSW1wbChwaXhlbHMsIG9wdGlvbnMsIHNpemUsIHNpbXBsaWZ5KSB7XG4gIC8vRXh0cmFjdCBjb250b3VyXG4gIHZhciBjb250b3VyID0gZ2V0Q29udG91cihwaXhlbHMsIHNpbXBsaWZ5KVxuXG4gIC8vQXBwbHkgd2FycCB0byBwb3NpdGlvbnNcbiAgdmFyIHBvc2l0aW9ucyA9IHRyYW5zZm9ybVBvc2l0aW9ucyhjb250b3VyLnBvc2l0aW9ucywgb3B0aW9ucywgc2l6ZSlcbiAgdmFyIGVkZ2VzICAgICA9IGNvbnRvdXIuZWRnZXNcbiAgdmFyIGZsaXAgPSBcImNjd1wiID09PSBvcHRpb25zLm9yaWVudGF0aW9uXG5cbiAgLy9DbGVhbiB1cCB0aGUgUFNMRywgcmVzb2x2ZSBzZWxmIGludGVyc2VjdGlvbnMsIGV0Yy5cbiAgY2xlYW5QU0xHKHBvc2l0aW9ucywgZWRnZXMpXG5cbiAgLy9JZiB0cmlhbmd1bGF0ZSBmbGFnIHBhc3NlZCwgdHJpYW5ndWxhdGUgdGhlIHJlc3VsdFxuICBpZihvcHRpb25zLnBvbHlnb25zIHx8IG9wdGlvbnMucG9seWdvbiB8fCBvcHRpb25zLnBvbHlsaW5lKSB7XG4gICAgdmFyIHJlc3VsdCA9IHRvUG9seWdvbkNyYXBweShlZGdlcywgcG9zaXRpb25zKVxuICAgIHZhciBucmVzdWx0ID0gbmV3IEFycmF5KHJlc3VsdC5sZW5ndGgpXG4gICAgZm9yKHZhciBpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgbG9vcHMgPSByZXN1bHRbaV1cbiAgICAgIHZhciBubG9vcHMgPSBuZXcgQXJyYXkobG9vcHMubGVuZ3RoKVxuICAgICAgZm9yKHZhciBqPTA7IGo8bG9vcHMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGxvb3AgPSBsb29wc1tqXVxuICAgICAgICB2YXIgbmxvb3AgPSBuZXcgQXJyYXkobG9vcC5sZW5ndGgpXG4gICAgICAgIGZvcih2YXIgaz0wOyBrPGxvb3AubGVuZ3RoOyArK2spIHtcbiAgICAgICAgICBubG9vcFtrXSA9IHBvc2l0aW9uc1tsb29wW2tdXS5zbGljZSgpXG4gICAgICAgIH1cbiAgICAgICAgaWYoZmxpcCkge1xuICAgICAgICAgIG5sb29wLnJldmVyc2UoKVxuICAgICAgICB9XG4gICAgICAgIG5sb29wc1tqXSA9IG5sb29wXG4gICAgICB9XG4gICAgICBucmVzdWx0W2ldID0gbmxvb3BzXG4gICAgfVxuICAgIHJldHVybiBucmVzdWx0XG4gIH0gZWxzZSBpZihvcHRpb25zLnRyaWFuZ2xlcyB8fCBvcHRpb25zLnRyaWFuZ3VsYXRlIHx8IG9wdGlvbnMudHJpYW5nbGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2VsbHM6IGNkdDJkKHBvc2l0aW9ucywgZWRnZXMsIHtcbiAgICAgICAgZGVsYXVuYXk6IGZhbHNlLFxuICAgICAgICBleHRlcmlvcjogZmFsc2UsXG4gICAgICAgIGludGVyaW9yOiB0cnVlXG4gICAgICB9KSxcbiAgICAgIHBvc2l0aW9uczogcG9zaXRpb25zXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiB7XG4gICAgICBlZGdlczogICAgIGVkZ2VzLFxuICAgICAgcG9zaXRpb25zOiBwb3NpdGlvbnNcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1BpeGVscyhwaXhlbHMsIG9wdGlvbnMsIHNpemUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gcHJvY2Vzc1BpeGVsc0ltcGwocGl4ZWxzLCBvcHRpb25zLCBzaXplLCB0cnVlKVxuICB9IGNhdGNoKGUpIHt9XG4gIHRyeSB7XG4gICAgcmV0dXJuIHByb2Nlc3NQaXhlbHNJbXBsKHBpeGVscywgb3B0aW9ucywgc2l6ZSwgZmFsc2UpXG4gIH0gY2F0Y2goZSkge31cbiAgaWYob3B0aW9ucy5wb2x5Z29ucyB8fCBvcHRpb25zLnBvbHlsaW5lIHx8IG9wdGlvbnMucG9seWdvbikge1xuICAgIHJldHVybiBbXVxuICB9XG4gIGlmKG9wdGlvbnMudHJpYW5nbGVzIHx8IG9wdGlvbnMudHJpYW5ndWxhdGUgfHwgb3B0aW9ucy50cmlhbmdsZSkge1xuICAgIHJldHVybiB7XG4gICAgICBjZWxsczogW10sXG4gICAgICBwb3NpdGlvbnM6IFtdXG4gICAgfVxuICB9XG4gIHJldHVybiB7XG4gICAgZWRnZXM6IFtdLFxuICAgIHBvc2l0aW9uczogW11cbiAgfVxufVxuXG5mdW5jdGlvbiB2ZWN0b3JpemVUZXh0KHN0ciwgY2FudmFzLCBjb250ZXh0LCBvcHRpb25zKSB7XG4gIHZhciBzaXplID0gb3B0aW9ucy5zaXplIHx8IDY0XG4gIHZhciBmYW1pbHkgPSBvcHRpb25zLmZvbnQgfHwgXCJub3JtYWxcIlxuXG4gIGNvbnRleHQuZm9udCA9IHNpemUgKyBcInB4IFwiICsgZmFtaWx5XG4gIGNvbnRleHQudGV4dEFsaWduID0gXCJzdGFydFwiXG4gIGNvbnRleHQudGV4dEJhc2VsaW5lID0gXCJhbHBoYWJldGljXCJcbiAgY29udGV4dC5kaXJlY3Rpb24gPSBcImx0clwiXG5cbiAgdmFyIHBpeGVscyA9IGdldFBpeGVscyhjYW52YXMsIGNvbnRleHQsIHN0ciwgc2l6ZSlcblxuICByZXR1cm4gcHJvY2Vzc1BpeGVscyhwaXhlbHMsIG9wdGlvbnMsIHNpemUpXG59XG4iLCIvLyBDb3B5cmlnaHQgKEMpIDIwMTEgR29vZ2xlIEluYy5cbi8vXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuLy8gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4vL1xuLy8gaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4vL1xuLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuLy8gZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuLy8gV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4vLyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4vLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IEluc3RhbGwgYSBsZWFreSBXZWFrTWFwIGVtdWxhdGlvbiBvbiBwbGF0Zm9ybXMgdGhhdFxuICogZG9uJ3QgcHJvdmlkZSBhIGJ1aWx0LWluIG9uZS5cbiAqXG4gKiA8cD5Bc3N1bWVzIHRoYXQgYW4gRVM1IHBsYXRmb3JtIHdoZXJlLCBpZiB7QGNvZGUgV2Vha01hcH0gaXNcbiAqIGFscmVhZHkgcHJlc2VudCwgdGhlbiBpdCBjb25mb3JtcyB0byB0aGUgYW50aWNpcGF0ZWQgRVM2XG4gKiBzcGVjaWZpY2F0aW9uLiBUbyBydW4gdGhpcyBmaWxlIG9uIGFuIEVTNSBvciBhbG1vc3QgRVM1XG4gKiBpbXBsZW1lbnRhdGlvbiB3aGVyZSB0aGUge0Bjb2RlIFdlYWtNYXB9IHNwZWNpZmljYXRpb24gZG9lcyBub3RcbiAqIHF1aXRlIGNvbmZvcm0sIHJ1biA8Y29kZT5yZXBhaXJFUzUuanM8L2NvZGU+IGZpcnN0LlxuICpcbiAqIDxwPkV2ZW4gdGhvdWdoIFdlYWtNYXBNb2R1bGUgaXMgbm90IGdsb2JhbCwgdGhlIGxpbnRlciB0aGlua3MgaXRcbiAqIGlzLCB3aGljaCBpcyB3aHkgaXQgaXMgaW4gdGhlIG92ZXJyaWRlcyBsaXN0IGJlbG93LlxuICpcbiAqIDxwPk5PVEU6IEJlZm9yZSB1c2luZyB0aGlzIFdlYWtNYXAgZW11bGF0aW9uIGluIGEgbm9uLVNFU1xuICogZW52aXJvbm1lbnQsIHNlZSB0aGUgbm90ZSBiZWxvdyBhYm91dCBoaWRkZW5SZWNvcmQuXG4gKlxuICogQGF1dGhvciBNYXJrIFMuIE1pbGxlclxuICogQHJlcXVpcmVzIGNyeXB0bywgQXJyYXlCdWZmZXIsIFVpbnQ4QXJyYXksIG5hdmlnYXRvciwgY29uc29sZVxuICogQG92ZXJyaWRlcyBXZWFrTWFwLCBzZXMsIFByb3h5XG4gKiBAb3ZlcnJpZGVzIFdlYWtNYXBNb2R1bGVcbiAqL1xuXG4vKipcbiAqIFRoaXMge0Bjb2RlIFdlYWtNYXB9IGVtdWxhdGlvbiBpcyBvYnNlcnZhYmx5IGVxdWl2YWxlbnQgdG8gdGhlXG4gKiBFUy1IYXJtb255IFdlYWtNYXAsIGJ1dCB3aXRoIGxlYWtpZXIgZ2FyYmFnZSBjb2xsZWN0aW9uIHByb3BlcnRpZXMuXG4gKlxuICogPHA+QXMgd2l0aCB0cnVlIFdlYWtNYXBzLCBpbiB0aGlzIGVtdWxhdGlvbiwgYSBrZXkgZG9lcyBub3RcbiAqIHJldGFpbiBtYXBzIGluZGV4ZWQgYnkgdGhhdCBrZXkgYW5kIChjcnVjaWFsbHkpIGEgbWFwIGRvZXMgbm90XG4gKiByZXRhaW4gdGhlIGtleXMgaXQgaW5kZXhlcy4gQSBtYXAgYnkgaXRzZWxmIGFsc28gZG9lcyBub3QgcmV0YWluXG4gKiB0aGUgdmFsdWVzIGFzc29jaWF0ZWQgd2l0aCB0aGF0IG1hcC5cbiAqXG4gKiA8cD5Ib3dldmVyLCB0aGUgdmFsdWVzIGFzc29jaWF0ZWQgd2l0aCBhIGtleSBpbiBzb21lIG1hcCBhcmVcbiAqIHJldGFpbmVkIHNvIGxvbmcgYXMgdGhhdCBrZXkgaXMgcmV0YWluZWQgYW5kIHRob3NlIGFzc29jaWF0aW9ucyBhcmVcbiAqIG5vdCBvdmVycmlkZGVuLiBGb3IgZXhhbXBsZSwgd2hlbiB1c2VkIHRvIHN1cHBvcnQgbWVtYnJhbmVzLCBhbGxcbiAqIHZhbHVlcyBleHBvcnRlZCBmcm9tIGEgZ2l2ZW4gbWVtYnJhbmUgd2lsbCBsaXZlIGZvciB0aGUgbGlmZXRpbWVcbiAqIHRoZXkgd291bGQgaGF2ZSBoYWQgaW4gdGhlIGFic2VuY2Ugb2YgYW4gaW50ZXJwb3NlZCBtZW1icmFuZS4gRXZlblxuICogd2hlbiB0aGUgbWVtYnJhbmUgaXMgcmV2b2tlZCwgYWxsIG9iamVjdHMgdGhhdCB3b3VsZCBoYXZlIGJlZW5cbiAqIHJlYWNoYWJsZSBpbiB0aGUgYWJzZW5jZSBvZiByZXZvY2F0aW9uIHdpbGwgc3RpbGwgYmUgcmVhY2hhYmxlLCBhc1xuICogZmFyIGFzIHRoZSBHQyBjYW4gdGVsbCwgZXZlbiB0aG91Z2ggdGhleSB3aWxsIG5vIGxvbmdlciBiZSByZWxldmFudFxuICogdG8gb25nb2luZyBjb21wdXRhdGlvbi5cbiAqXG4gKiA8cD5UaGUgQVBJIGltcGxlbWVudGVkIGhlcmUgaXMgYXBwcm94aW1hdGVseSB0aGUgQVBJIGFzIGltcGxlbWVudGVkXG4gKiBpbiBGRjYuMGExIGFuZCBhZ3JlZWQgdG8gYnkgTWFya00sIEFuZHJlYXMgR2FsLCBhbmQgRGF2ZSBIZXJtYW4sXG4gKiByYXRoZXIgdGhhbiB0aGUgb2ZmaWFsbHkgYXBwcm92ZWQgcHJvcG9zYWwgcGFnZS4gVE9ETyhlcmlnaHRzKTpcbiAqIHVwZ3JhZGUgdGhlIGVjbWFzY3JpcHQgV2Vha01hcCBwcm9wb3NhbCBwYWdlIHRvIGV4cGxhaW4gdGhpcyBBUElcbiAqIGNoYW5nZSBhbmQgcHJlc2VudCB0byBFY21hU2NyaXB0IGNvbW1pdHRlZSBmb3IgdGhlaXIgYXBwcm92YWwuXG4gKlxuICogPHA+VGhlIGZpcnN0IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZW11bGF0aW9uIGhlcmUgYW5kIHRoYXQgaW5cbiAqIEZGNi4wYTEgaXMgdGhlIHByZXNlbmNlIG9mIG5vbiBlbnVtZXJhYmxlIHtAY29kZSBnZXRfX18sIGhhc19fXyxcbiAqIHNldF9fXywgYW5kIGRlbGV0ZV9fX30gbWV0aG9kcyBvbiBXZWFrTWFwIGluc3RhbmNlcyB0byByZXByZXNlbnRcbiAqIHdoYXQgd291bGQgYmUgdGhlIGhpZGRlbiBpbnRlcm5hbCBwcm9wZXJ0aWVzIG9mIGEgcHJpbWl0aXZlXG4gKiBpbXBsZW1lbnRhdGlvbi4gV2hlcmVhcyB0aGUgRkY2LjBhMSBXZWFrTWFwLnByb3RvdHlwZSBtZXRob2RzXG4gKiByZXF1aXJlIHRoZWlyIHtAY29kZSB0aGlzfSB0byBiZSBhIGdlbnVpbmUgV2Vha01hcCBpbnN0YW5jZSAoaS5lLixcbiAqIGFuIG9iamVjdCBvZiB7QGNvZGUgW1tDbGFzc11dfSBcIldlYWtNYXB9KSwgc2luY2UgdGhlcmUgaXMgbm90aGluZ1xuICogdW5mb3JnZWFibGUgYWJvdXQgdGhlIHBzZXVkby1pbnRlcm5hbCBtZXRob2QgbmFtZXMgdXNlZCBoZXJlLFxuICogbm90aGluZyBwcmV2ZW50cyB0aGVzZSBlbXVsYXRlZCBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIGJlaW5nXG4gKiBhcHBsaWVkIHRvIG5vbi1XZWFrTWFwcyB3aXRoIHBzZXVkby1pbnRlcm5hbCBtZXRob2RzIG9mIHRoZSBzYW1lXG4gKiBuYW1lcy5cbiAqXG4gKiA8cD5Bbm90aGVyIGRpZmZlcmVuY2UgaXMgdGhhdCBvdXIgZW11bGF0ZWQge0Bjb2RlXG4gKiBXZWFrTWFwLnByb3RvdHlwZX0gaXMgbm90IGl0c2VsZiBhIFdlYWtNYXAuIEEgcHJvYmxlbSB3aXRoIHRoZVxuICogY3VycmVudCBGRjYuMGExIEFQSSBpcyB0aGF0IFdlYWtNYXAucHJvdG90eXBlIGlzIGl0c2VsZiBhIFdlYWtNYXBcbiAqIHByb3ZpZGluZyBhbWJpZW50IG11dGFiaWxpdHkgYW5kIGFuIGFtYmllbnQgY29tbXVuaWNhdGlvbnNcbiAqIGNoYW5uZWwuIFRodXMsIGlmIGEgV2Vha01hcCBpcyBhbHJlYWR5IHByZXNlbnQgYW5kIGhhcyB0aGlzXG4gKiBwcm9ibGVtLCByZXBhaXJFUzUuanMgd3JhcHMgaXQgaW4gYSBzYWZlIHdyYXBwcGVyIGluIG9yZGVyIHRvXG4gKiBwcmV2ZW50IGFjY2VzcyB0byB0aGlzIGNoYW5uZWwuIChTZWVcbiAqIFBBVENIX01VVEFCTEVfRlJPWkVOX1dFQUtNQVBfUFJPVE8gaW4gcmVwYWlyRVM1LmpzKS5cbiAqL1xuXG4vKipcbiAqIElmIHRoaXMgaXMgYSBmdWxsIDxhIGhyZWY9XG4gKiBcImh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9lcy1sYWIvd2lraS9TZWN1cmVhYmxlRVM1XCJcbiAqID5zZWN1cmVhYmxlIEVTNTwvYT4gcGxhdGZvcm0gYW5kIHRoZSBFUy1IYXJtb255IHtAY29kZSBXZWFrTWFwfSBpc1xuICogYWJzZW50LCBpbnN0YWxsIGFuIGFwcHJveGltYXRlIGVtdWxhdGlvbi5cbiAqXG4gKiA8cD5JZiBXZWFrTWFwIGlzIHByZXNlbnQgYnV0IGNhbm5vdCBzdG9yZSBzb21lIG9iamVjdHMsIHVzZSBvdXIgYXBwcm94aW1hdGVcbiAqIGVtdWxhdGlvbiBhcyBhIHdyYXBwZXIuXG4gKlxuICogPHA+SWYgdGhpcyBpcyBhbG1vc3QgYSBzZWN1cmVhYmxlIEVTNSBwbGF0Zm9ybSwgdGhlbiBXZWFrTWFwLmpzXG4gKiBzaG91bGQgYmUgcnVuIGFmdGVyIHJlcGFpckVTNS5qcy5cbiAqXG4gKiA8cD5TZWUge0Bjb2RlIFdlYWtNYXB9IGZvciBkb2N1bWVudGF0aW9uIG9mIHRoZSBnYXJiYWdlIGNvbGxlY3Rpb25cbiAqIHByb3BlcnRpZXMgb2YgdGhpcyBXZWFrTWFwIGVtdWxhdGlvbi5cbiAqL1xuKGZ1bmN0aW9uIFdlYWtNYXBNb2R1bGUoKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIGlmICh0eXBlb2Ygc2VzICE9PSAndW5kZWZpbmVkJyAmJiBzZXMub2sgJiYgIXNlcy5vaygpKSB7XG4gICAgLy8gYWxyZWFkeSB0b28gYnJva2VuLCBzbyBnaXZlIHVwXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIEluIHNvbWUgY2FzZXMgKGN1cnJlbnQgRmlyZWZveCksIHdlIG11c3QgbWFrZSBhIGNob2ljZSBiZXR3ZWVlbiBhXG4gICAqIFdlYWtNYXAgd2hpY2ggaXMgY2FwYWJsZSBvZiB1c2luZyBhbGwgdmFyaWV0aWVzIG9mIGhvc3Qgb2JqZWN0cyBhc1xuICAgKiBrZXlzIGFuZCBvbmUgd2hpY2ggaXMgY2FwYWJsZSBvZiBzYWZlbHkgdXNpbmcgcHJveGllcyBhcyBrZXlzLiBTZWVcbiAgICogY29tbWVudHMgYmVsb3cgYWJvdXQgSG9zdFdlYWtNYXAgYW5kIERvdWJsZVdlYWtNYXAgZm9yIGRldGFpbHMuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gKHdoaWNoIGlzIGEgZ2xvYmFsLCBub3QgZXhwb3NlZCB0byBndWVzdHMpIG1hcmtzIGFcbiAgICogV2Vha01hcCBhcyBwZXJtaXR0ZWQgdG8gZG8gd2hhdCBpcyBuZWNlc3NhcnkgdG8gaW5kZXggYWxsIGhvc3RcbiAgICogb2JqZWN0cywgYXQgdGhlIGNvc3Qgb2YgbWFraW5nIGl0IHVuc2FmZSBmb3IgcHJveGllcy5cbiAgICpcbiAgICogRG8gbm90IGFwcGx5IHRoaXMgZnVuY3Rpb24gdG8gYW55dGhpbmcgd2hpY2ggaXMgbm90IGEgZ2VudWluZVxuICAgKiBmcmVzaCBXZWFrTWFwLlxuICAgKi9cbiAgZnVuY3Rpb24gd2Vha01hcFBlcm1pdEhvc3RPYmplY3RzKG1hcCkge1xuICAgIC8vIGlkZW50aXR5IG9mIGZ1bmN0aW9uIHVzZWQgYXMgYSBzZWNyZXQgLS0gZ29vZCBlbm91Z2ggYW5kIGNoZWFwXG4gICAgaWYgKG1hcC5wZXJtaXRIb3N0T2JqZWN0c19fXykge1xuICAgICAgbWFwLnBlcm1pdEhvc3RPYmplY3RzX19fKHdlYWtNYXBQZXJtaXRIb3N0T2JqZWN0cyk7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2Ygc2VzICE9PSAndW5kZWZpbmVkJykge1xuICAgIHNlcy53ZWFrTWFwUGVybWl0SG9zdE9iamVjdHMgPSB3ZWFrTWFwUGVybWl0SG9zdE9iamVjdHM7XG4gIH1cblxuICAvLyBJRSAxMSBoYXMgbm8gUHJveHkgYnV0IGhhcyBhIGJyb2tlbiBXZWFrTWFwIHN1Y2ggdGhhdCB3ZSBuZWVkIHRvIHBhdGNoXG4gIC8vIGl0IHVzaW5nIERvdWJsZVdlYWtNYXA7IHRoaXMgZmxhZyB0ZWxscyBEb3VibGVXZWFrTWFwIHNvLlxuICB2YXIgZG91YmxlV2Vha01hcENoZWNrU2lsZW50RmFpbHVyZSA9IGZhbHNlO1xuXG4gIC8vIENoZWNrIGlmIHRoZXJlIGlzIGFscmVhZHkgYSBnb29kLWVub3VnaCBXZWFrTWFwIGltcGxlbWVudGF0aW9uLCBhbmQgaWYgc29cbiAgLy8gZXhpdCB3aXRob3V0IHJlcGxhY2luZyBpdC5cbiAgaWYgKHR5cGVvZiBXZWFrTWFwID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdmFyIEhvc3RXZWFrTWFwID0gV2Vha01hcDtcbiAgICAvLyBUaGVyZSBpcyBhIFdlYWtNYXAgLS0gaXMgaXQgZ29vZCBlbm91Z2g/XG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIC9GaXJlZm94Ly50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICAvLyBXZSdyZSBub3cgKmFzc3VtaW5nIG5vdCosIGJlY2F1c2UgYXMgb2YgdGhpcyB3cml0aW5nICgyMDEzLTA1LTA2KVxuICAgICAgLy8gRmlyZWZveCdzIFdlYWtNYXBzIGhhdmUgYSBtaXNjZWxsYW55IG9mIG9iamVjdHMgdGhleSB3b24ndCBhY2NlcHQsIGFuZFxuICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBtYWtlIGFuIGV4aGF1c3RpdmUgbGlzdCwgYW5kIHRlc3RpbmcgZm9yIGp1c3Qgb25lXG4gICAgICAvLyB3aWxsIGJlIGEgcHJvYmxlbSBpZiB0aGF0IG9uZSBpcyBmaXhlZCBhbG9uZSAoYXMgdGhleSBkaWQgZm9yIEV2ZW50KS5cblxuICAgICAgLy8gSWYgdGhlcmUgaXMgYSBwbGF0Zm9ybSB0aGF0IHdlICpjYW4qIHJlbGlhYmx5IHRlc3Qgb24sIGhlcmUncyBob3cgdG9cbiAgICAgIC8vIGRvIGl0OlxuICAgICAgLy8gIHZhciBwcm9ibGVtYXRpYyA9IC4uLiA7XG4gICAgICAvLyAgdmFyIHRlc3RIb3N0TWFwID0gbmV3IEhvc3RXZWFrTWFwKCk7XG4gICAgICAvLyAgdHJ5IHtcbiAgICAgIC8vICAgIHRlc3RIb3N0TWFwLnNldChwcm9ibGVtYXRpYywgMSk7ICAvLyBGaXJlZm94IDIwIHdpbGwgdGhyb3cgaGVyZVxuICAgICAgLy8gICAgaWYgKHRlc3RIb3N0TWFwLmdldChwcm9ibGVtYXRpYykgPT09IDEpIHtcbiAgICAgIC8vICAgICAgcmV0dXJuO1xuICAgICAgLy8gICAgfVxuICAgICAgLy8gIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSUUgMTEgYnVnOiBXZWFrTWFwcyBzaWxlbnRseSBmYWlsIHRvIHN0b3JlIGZyb3plbiBvYmplY3RzLlxuICAgICAgdmFyIHRlc3RNYXAgPSBuZXcgSG9zdFdlYWtNYXAoKTtcbiAgICAgIHZhciB0ZXN0T2JqZWN0ID0gT2JqZWN0LmZyZWV6ZSh7fSk7XG4gICAgICB0ZXN0TWFwLnNldCh0ZXN0T2JqZWN0LCAxKTtcbiAgICAgIGlmICh0ZXN0TWFwLmdldCh0ZXN0T2JqZWN0KSAhPT0gMSkge1xuICAgICAgICBkb3VibGVXZWFrTWFwQ2hlY2tTaWxlbnRGYWlsdXJlID0gdHJ1ZTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoIHRvIGluc3RhbGxpbmcgb3VyIFdlYWtNYXAuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFdlYWtNYXA7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgaG9wID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbiAgdmFyIGdvcG4gPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcztcbiAgdmFyIGRlZlByb3AgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG4gIHZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlO1xuXG4gIC8qKlxuICAgKiBTZWN1cml0eSBkZXBlbmRzIG9uIEhJRERFTl9OQU1FIGJlaW5nIGJvdGggPGk+dW5ndWVzc2FibGU8L2k+IGFuZFxuICAgKiA8aT51bmRpc2NvdmVyYWJsZTwvaT4gYnkgdW50cnVzdGVkIGNvZGUuXG4gICAqXG4gICAqIDxwPkdpdmVuIHRoZSBrbm93biB3ZWFrbmVzc2VzIG9mIE1hdGgucmFuZG9tKCkgb24gZXhpc3RpbmdcbiAgICogYnJvd3NlcnMsIGl0IGRvZXMgbm90IGdlbmVyYXRlIHVuZ3Vlc3NhYmlsaXR5IHdlIGNhbiBiZSBjb25maWRlbnRcbiAgICogb2YuXG4gICAqXG4gICAqIDxwPkl0IGlzIHRoZSBtb25rZXkgcGF0Y2hpbmcgbG9naWMgaW4gdGhpcyBmaWxlIHRoYXQgaXMgaW50ZW5kZWRcbiAgICogdG8gZW5zdXJlIHVuZGlzY292ZXJhYmlsaXR5LiBUaGUgYmFzaWMgaWRlYSBpcyB0aGF0IHRoZXJlIGFyZVxuICAgKiB0aHJlZSBmdW5kYW1lbnRhbCBtZWFucyBvZiBkaXNjb3ZlcmluZyBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdDpcbiAgICogVGhlIGZvci9pbiBsb29wLCBPYmplY3Qua2V5cygpLCBhbmQgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoKSxcbiAgICogYXMgd2VsbCBhcyBzb21lIHByb3Bvc2VkIEVTNiBleHRlbnNpb25zIHRoYXQgYXBwZWFyIG9uIG91clxuICAgKiB3aGl0ZWxpc3QuIFRoZSBmaXJzdCB0d28gb25seSBkaXNjb3ZlciBlbnVtZXJhYmxlIHByb3BlcnRpZXMsIGFuZFxuICAgKiB3ZSBvbmx5IHVzZSBISURERU5fTkFNRSB0byBuYW1lIGEgbm9uLWVudW1lcmFibGUgcHJvcGVydHksIHNvIHRoZVxuICAgKiBvbmx5IHJlbWFpbmluZyB0aHJlYXQgc2hvdWxkIGJlIGdldE93blByb3BlcnR5TmFtZXMgYW5kIHNvbWVcbiAgICogcHJvcG9zZWQgRVM2IGV4dGVuc2lvbnMgdGhhdCBhcHBlYXIgb24gb3VyIHdoaXRlbGlzdC4gV2UgbW9ua2V5XG4gICAqIHBhdGNoIHRoZW0gdG8gcmVtb3ZlIEhJRERFTl9OQU1FIGZyb20gdGhlIGxpc3Qgb2YgcHJvcGVydGllcyB0aGV5XG4gICAqIHJldHVybnMuXG4gICAqXG4gICAqIDxwPlRPRE8oZXJpZ2h0cyk6IE9uIGEgcGxhdGZvcm0gd2l0aCBidWlsdC1pbiBQcm94aWVzLCBwcm94aWVzXG4gICAqIGNvdWxkIGJlIHVzZWQgdG8gdHJhcCBhbmQgdGhlcmVieSBkaXNjb3ZlciB0aGUgSElEREVOX05BTUUsIHNvIHdlXG4gICAqIG5lZWQgdG8gbW9ua2V5IHBhdGNoIFByb3h5LmNyZWF0ZSwgUHJveHkuY3JlYXRlRnVuY3Rpb24sIGV0YywgaW5cbiAgICogb3JkZXIgdG8gd3JhcCB0aGUgcHJvdmlkZWQgaGFuZGxlciB3aXRoIHRoZSByZWFsIGhhbmRsZXIgd2hpY2hcbiAgICogZmlsdGVycyBvdXQgYWxsIHRyYXBzIHVzaW5nIEhJRERFTl9OQU1FLlxuICAgKlxuICAgKiA8cD5UT0RPKGVyaWdodHMpOiBSZXZpc2l0IE1pa2UgU3RheSdzIHN1Z2dlc3Rpb24gdGhhdCB3ZSB1c2UgYW5cbiAgICogZW5jYXBzdWxhdGVkIGZ1bmN0aW9uIGF0IGEgbm90LW5lY2Vzc2FyaWx5LXNlY3JldCBuYW1lLCB3aGljaFxuICAgKiB1c2VzIHRoZSBTdGllZ2xlciBzaGFyZWQtc3RhdGUgcmlnaHRzIGFtcGxpZmljYXRpb24gcGF0dGVybiB0b1xuICAgKiByZXZlYWwgdGhlIGFzc29jaWF0ZWQgdmFsdWUgb25seSB0byB0aGUgV2Vha01hcCBpbiB3aGljaCB0aGlzIGtleVxuICAgKiBpcyBhc3NvY2lhdGVkIHdpdGggdGhhdCB2YWx1ZS4gU2luY2Ugb25seSB0aGUga2V5IHJldGFpbnMgdGhlXG4gICAqIGZ1bmN0aW9uLCB0aGUgZnVuY3Rpb24gY2FuIGFsc28gcmVtZW1iZXIgdGhlIGtleSB3aXRob3V0IGNhdXNpbmdcbiAgICogbGVha2FnZSBvZiB0aGUga2V5LCBzbyB0aGlzIGRvZXNuJ3QgdmlvbGF0ZSBvdXIgZ2VuZXJhbCBnY1xuICAgKiBnb2Fscy4gSW4gYWRkaXRpb24sIGJlY2F1c2UgdGhlIG5hbWUgbmVlZCBub3QgYmUgYSBndWFyZGVkXG4gICAqIHNlY3JldCwgd2UgY291bGQgZWZmaWNpZW50bHkgaGFuZGxlIGNyb3NzLWZyYW1lIGZyb3plbiBrZXlzLlxuICAgKi9cbiAgdmFyIEhJRERFTl9OQU1FX1BSRUZJWCA9ICd3ZWFrbWFwOic7XG4gIHZhciBISURERU5fTkFNRSA9IEhJRERFTl9OQU1FX1BSRUZJWCArICdpZGVudDonICsgTWF0aC5yYW5kb20oKSArICdfX18nO1xuXG4gIGlmICh0eXBlb2YgY3J5cHRvICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgdHlwZW9mIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgIHR5cGVvZiBBcnJheUJ1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgdHlwZW9mIFVpbnQ4QXJyYXkgPT09ICdmdW5jdGlvbicpIHtcbiAgICB2YXIgYWIgPSBuZXcgQXJyYXlCdWZmZXIoMjUpO1xuICAgIHZhciB1OHMgPSBuZXcgVWludDhBcnJheShhYik7XG4gICAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyh1OHMpO1xuICAgIEhJRERFTl9OQU1FID0gSElEREVOX05BTUVfUFJFRklYICsgJ3JhbmQ6JyArXG4gICAgICBBcnJheS5wcm90b3R5cGUubWFwLmNhbGwodThzLCBmdW5jdGlvbih1OCkge1xuICAgICAgICByZXR1cm4gKHU4ICUgMzYpLnRvU3RyaW5nKDM2KTtcbiAgICAgIH0pLmpvaW4oJycpICsgJ19fXyc7XG4gIH1cblxuICBmdW5jdGlvbiBpc05vdEhpZGRlbk5hbWUobmFtZSkge1xuICAgIHJldHVybiAhKFxuICAgICAgICBuYW1lLnN1YnN0cigwLCBISURERU5fTkFNRV9QUkVGSVgubGVuZ3RoKSA9PSBISURERU5fTkFNRV9QUkVGSVggJiZcbiAgICAgICAgbmFtZS5zdWJzdHIobmFtZS5sZW5ndGggLSAzKSA9PT0gJ19fXycpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vbmtleSBwYXRjaCBnZXRPd25Qcm9wZXJ0eU5hbWVzIHRvIGF2b2lkIHJldmVhbGluZyB0aGVcbiAgICogSElEREVOX05BTUUuXG4gICAqXG4gICAqIDxwPlRoZSBFUzUuMSBzcGVjIHJlcXVpcmVzIGVhY2ggbmFtZSB0byBhcHBlYXIgb25seSBvbmNlLCBidXQgYXNcbiAgICogb2YgdGhpcyB3cml0aW5nLCB0aGlzIHJlcXVpcmVtZW50IGlzIGNvbnRyb3ZlcnNpYWwgZm9yIEVTNiwgc28gd2VcbiAgICogbWFkZSB0aGlzIGNvZGUgcm9idXN0IGFnYWluc3QgdGhpcyBjYXNlLiBJZiB0aGUgcmVzdWx0aW5nIGV4dHJhXG4gICAqIHNlYXJjaCB0dXJucyBvdXQgdG8gYmUgZXhwZW5zaXZlLCB3ZSBjYW4gcHJvYmFibHkgcmVsYXggdGhpcyBvbmNlXG4gICAqIEVTNiBpcyBhZGVxdWF0ZWx5IHN1cHBvcnRlZCBvbiBhbGwgbWFqb3IgYnJvd3NlcnMsIGlmZiBubyBicm93c2VyXG4gICAqIHZlcnNpb25zIHdlIHN1cHBvcnQgYXQgdGhhdCB0aW1lIGhhdmUgcmVsYXhlZCB0aGlzIGNvbnN0cmFpbnRcbiAgICogd2l0aG91dCBwcm92aWRpbmcgYnVpbHQtaW4gRVM2IFdlYWtNYXBzLlxuICAgKi9cbiAgZGVmUHJvcChPYmplY3QsICdnZXRPd25Qcm9wZXJ0eU5hbWVzJywge1xuICAgIHZhbHVlOiBmdW5jdGlvbiBmYWtlR2V0T3duUHJvcGVydHlOYW1lcyhvYmopIHtcbiAgICAgIHJldHVybiBnb3BuKG9iaikuZmlsdGVyKGlzTm90SGlkZGVuTmFtZSk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogZ2V0UHJvcGVydHlOYW1lcyBpcyBub3QgaW4gRVM1IGJ1dCBpdCBpcyBwcm9wb3NlZCBmb3IgRVM2IGFuZFxuICAgKiBkb2VzIGFwcGVhciBpbiBvdXIgd2hpdGVsaXN0LCBzbyB3ZSBuZWVkIHRvIGNsZWFuIGl0IHRvby5cbiAgICovXG4gIGlmICgnZ2V0UHJvcGVydHlOYW1lcycgaW4gT2JqZWN0KSB7XG4gICAgdmFyIG9yaWdpbmFsR2V0UHJvcGVydHlOYW1lcyA9IE9iamVjdC5nZXRQcm9wZXJ0eU5hbWVzO1xuICAgIGRlZlByb3AoT2JqZWN0LCAnZ2V0UHJvcGVydHlOYW1lcycsIHtcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBmYWtlR2V0UHJvcGVydHlOYW1lcyhvYmopIHtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsR2V0UHJvcGVydHlOYW1lcyhvYmopLmZpbHRlcihpc05vdEhpZGRlbk5hbWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIDxwPlRvIHRyZWF0IG9iamVjdHMgYXMgaWRlbnRpdHkta2V5cyB3aXRoIHJlYXNvbmFibGUgZWZmaWNpZW5jeVxuICAgKiBvbiBFUzUgYnkgaXRzZWxmIChpLmUuLCB3aXRob3V0IGFueSBvYmplY3Qta2V5ZWQgY29sbGVjdGlvbnMpLCB3ZVxuICAgKiBuZWVkIHRvIGFkZCBhIGhpZGRlbiBwcm9wZXJ0eSB0byBzdWNoIGtleSBvYmplY3RzIHdoZW4gd2VcbiAgICogY2FuLiBUaGlzIHJhaXNlcyBzZXZlcmFsIGlzc3VlczpcbiAgICogPHVsPlxuICAgKiA8bGk+QXJyYW5naW5nIHRvIGFkZCB0aGlzIHByb3BlcnR5IHRvIG9iamVjdHMgYmVmb3JlIHdlIGxvc2UgdGhlXG4gICAqICAgICBjaGFuY2UsIGFuZFxuICAgKiA8bGk+SGlkaW5nIHRoZSBleGlzdGVuY2Ugb2YgdGhpcyBuZXcgcHJvcGVydHkgZnJvbSBtb3N0XG4gICAqICAgICBKYXZhU2NyaXB0IGNvZGUuXG4gICAqIDxsaT5QcmV2ZW50aW5nIDxpPmNlcnRpZmljYXRpb24gdGhlZnQ8L2k+LCB3aGVyZSBvbmUgb2JqZWN0IGlzXG4gICAqICAgICBjcmVhdGVkIGZhbHNlbHkgY2xhaW1pbmcgdG8gYmUgdGhlIGtleSBvZiBhbiBhc3NvY2lhdGlvblxuICAgKiAgICAgYWN0dWFsbHkga2V5ZWQgYnkgYW5vdGhlciBvYmplY3QuXG4gICAqIDxsaT5QcmV2ZW50aW5nIDxpPnZhbHVlIHRoZWZ0PC9pPiwgd2hlcmUgdW50cnVzdGVkIGNvZGUgd2l0aFxuICAgKiAgICAgYWNjZXNzIHRvIGEga2V5IG9iamVjdCBidXQgbm90IGEgd2VhayBtYXAgbmV2ZXJ0aGVsZXNzXG4gICAqICAgICBvYnRhaW5zIGFjY2VzcyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoYXQga2V5IGluIHRoYXRcbiAgICogICAgIHdlYWsgbWFwLlxuICAgKiA8L3VsPlxuICAgKiBXZSBkbyBzbyBieVxuICAgKiA8dWw+XG4gICAqIDxsaT5NYWtpbmcgdGhlIG5hbWUgb2YgdGhlIGhpZGRlbiBwcm9wZXJ0eSB1bmd1ZXNzYWJsZSwgc28gXCJbXVwiXG4gICAqICAgICBpbmRleGluZywgd2hpY2ggd2UgY2Fubm90IGludGVyY2VwdCwgY2Fubm90IGJlIHVzZWQgdG8gYWNjZXNzXG4gICAqICAgICBhIHByb3BlcnR5IHdpdGhvdXQga25vd2luZyB0aGUgbmFtZS5cbiAgICogPGxpPk1ha2luZyB0aGUgaGlkZGVuIHByb3BlcnR5IG5vbi1lbnVtZXJhYmxlLCBzbyB3ZSBuZWVkIG5vdFxuICAgKiAgICAgd29ycnkgYWJvdXQgZm9yLWluIGxvb3BzIG9yIHtAY29kZSBPYmplY3Qua2V5c30sXG4gICAqIDxsaT5tb25rZXkgcGF0Y2hpbmcgdGhvc2UgcmVmbGVjdGl2ZSBtZXRob2RzIHRoYXQgd291bGRcbiAgICogICAgIHByZXZlbnQgZXh0ZW5zaW9ucywgdG8gYWRkIHRoaXMgaGlkZGVuIHByb3BlcnR5IGZpcnN0LFxuICAgKiA8bGk+bW9ua2V5IHBhdGNoaW5nIHRob3NlIG1ldGhvZHMgdGhhdCB3b3VsZCByZXZlYWwgdGhpc1xuICAgKiAgICAgaGlkZGVuIHByb3BlcnR5LlxuICAgKiA8L3VsPlxuICAgKiBVbmZvcnR1bmF0ZWx5LCBiZWNhdXNlIG9mIHNhbWUtb3JpZ2luIGlmcmFtZXMsIHdlIGNhbm5vdCByZWxpYWJseVxuICAgKiBhZGQgdGhpcyBoaWRkZW4gcHJvcGVydHkgYmVmb3JlIGFuIG9iamVjdCBiZWNvbWVzXG4gICAqIG5vbi1leHRlbnNpYmxlLiBJbnN0ZWFkLCBpZiB3ZSBlbmNvdW50ZXIgYSBub24tZXh0ZW5zaWJsZSBvYmplY3RcbiAgICogd2l0aG91dCBhIGhpZGRlbiByZWNvcmQgdGhhdCB3ZSBjYW4gZGV0ZWN0ICh3aGV0aGVyIG9yIG5vdCBpdCBoYXNcbiAgICogYSBoaWRkZW4gcmVjb3JkIHN0b3JlZCB1bmRlciBhIG5hbWUgc2VjcmV0IHRvIHVzKSwgdGhlbiB3ZSBqdXN0XG4gICAqIHVzZSB0aGUga2V5IG9iamVjdCBpdHNlbGYgdG8gcmVwcmVzZW50IGl0cyBpZGVudGl0eSBpbiBhIGJydXRlXG4gICAqIGZvcmNlIGxlYWt5IG1hcCBzdG9yZWQgaW4gdGhlIHdlYWsgbWFwLCBsb3NpbmcgYWxsIHRoZSBhZHZhbnRhZ2VzXG4gICAqIG9mIHdlYWtuZXNzIGZvciB0aGVzZS5cbiAgICovXG4gIGZ1bmN0aW9uIGdldEhpZGRlblJlY29yZChrZXkpIHtcbiAgICBpZiAoa2V5ICE9PSBPYmplY3Qoa2V5KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTm90IGFuIG9iamVjdDogJyArIGtleSk7XG4gICAgfVxuICAgIHZhciBoaWRkZW5SZWNvcmQgPSBrZXlbSElEREVOX05BTUVdO1xuICAgIGlmIChoaWRkZW5SZWNvcmQgJiYgaGlkZGVuUmVjb3JkLmtleSA9PT0ga2V5KSB7IHJldHVybiBoaWRkZW5SZWNvcmQ7IH1cbiAgICBpZiAoIWlzRXh0ZW5zaWJsZShrZXkpKSB7XG4gICAgICAvLyBXZWFrIG1hcCBtdXN0IGJydXRlIGZvcmNlLCBhcyBleHBsYWluZWQgaW4gZG9jLWNvbW1lbnQgYWJvdmUuXG4gICAgICByZXR1cm4gdm9pZCAwO1xuICAgIH1cblxuICAgIC8vIFRoZSBoaWRkZW5SZWNvcmQgYW5kIHRoZSBrZXkgcG9pbnQgZGlyZWN0bHkgYXQgZWFjaCBvdGhlciwgdmlhXG4gICAgLy8gdGhlIFwia2V5XCIgYW5kIEhJRERFTl9OQU1FIHByb3BlcnRpZXMgcmVzcGVjdGl2ZWx5LiBUaGUga2V5XG4gICAgLy8gZmllbGQgaXMgZm9yIHF1aWNrbHkgdmVyaWZ5aW5nIHRoYXQgdGhpcyBoaWRkZW4gcmVjb3JkIGlzIGFuXG4gICAgLy8gb3duIHByb3BlcnR5LCBub3QgYSBoaWRkZW4gcmVjb3JkIGZyb20gdXAgdGhlIHByb3RvdHlwZSBjaGFpbi5cbiAgICAvL1xuICAgIC8vIE5PVEU6IEJlY2F1c2UgdGhpcyBXZWFrTWFwIGVtdWxhdGlvbiBpcyBtZWFudCBvbmx5IGZvciBzeXN0ZW1zIGxpa2VcbiAgICAvLyBTRVMgd2hlcmUgT2JqZWN0LnByb3RvdHlwZSBpcyBmcm96ZW4gd2l0aG91dCBhbnkgbnVtZXJpY1xuICAgIC8vIHByb3BlcnRpZXMsIGl0IGlzIG9rIHRvIHVzZSBhbiBvYmplY3QgbGl0ZXJhbCBmb3IgdGhlIGhpZGRlblJlY29yZC5cbiAgICAvLyBUaGlzIGhhcyB0d28gYWR2YW50YWdlczpcbiAgICAvLyAqIEl0IGlzIG11Y2ggZmFzdGVyIGluIGEgcGVyZm9ybWFuY2UgY3JpdGljYWwgcGxhY2VcbiAgICAvLyAqIEl0IGF2b2lkcyByZWx5aW5nIG9uIE9iamVjdC5jcmVhdGUobnVsbCksIHdoaWNoIGhhZCBiZWVuXG4gICAgLy8gICBwcm9ibGVtYXRpYyBvbiBDaHJvbWUgMjguMC4xNDgwLjAuIFNlZVxuICAgIC8vICAgaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9nb29nbGUtY2FqYS9pc3N1ZXMvZGV0YWlsP2lkPTE2ODdcbiAgICBoaWRkZW5SZWNvcmQgPSB7IGtleToga2V5IH07XG5cbiAgICAvLyBXaGVuIHVzaW5nIHRoaXMgV2Vha01hcCBlbXVsYXRpb24gb24gcGxhdGZvcm1zIHdoZXJlXG4gICAgLy8gT2JqZWN0LnByb3RvdHlwZSBtaWdodCBub3QgYmUgZnJvemVuIGFuZCBPYmplY3QuY3JlYXRlKG51bGwpIGlzXG4gICAgLy8gcmVsaWFibGUsIHVzZSB0aGUgZm9sbG93aW5nIHR3byBjb21tZW50ZWQgb3V0IGxpbmVzIGluc3RlYWQuXG4gICAgLy8gaGlkZGVuUmVjb3JkID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAvLyBoaWRkZW5SZWNvcmQua2V5ID0ga2V5O1xuXG4gICAgLy8gUGxlYXNlIGNvbnRhY3QgdXMgaWYgeW91IG5lZWQgdGhpcyB0byB3b3JrIG9uIHBsYXRmb3JtcyB3aGVyZVxuICAgIC8vIE9iamVjdC5wcm90b3R5cGUgbWlnaHQgbm90IGJlIGZyb3plbiBhbmRcbiAgICAvLyBPYmplY3QuY3JlYXRlKG51bGwpIG1pZ2h0IG5vdCBiZSByZWxpYWJsZS5cblxuICAgIHRyeSB7XG4gICAgICBkZWZQcm9wKGtleSwgSElEREVOX05BTUUsIHtcbiAgICAgICAgdmFsdWU6IGhpZGRlblJlY29yZCxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gaGlkZGVuUmVjb3JkO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBVbmRlciBzb21lIGNpcmN1bXN0YW5jZXMsIGlzRXh0ZW5zaWJsZSBzZWVtcyB0byBtaXNyZXBvcnQgd2hldGhlclxuICAgICAgLy8gdGhlIEhJRERFTl9OQU1FIGNhbiBiZSBkZWZpbmVkLlxuICAgICAgLy8gVGhlIGNpcmN1bXN0YW5jZXMgaGF2ZSBub3QgYmVlbiBpc29sYXRlZCwgYnV0IGF0IGxlYXN0IGFmZmVjdFxuICAgICAgLy8gTm9kZS5qcyB2MC4xMC4yNiBvbiBUcmF2aXNDSSAvIExpbnV4LCBidXQgbm90IHRoZSBzYW1lIHZlcnNpb24gb2ZcbiAgICAgIC8vIE5vZGUuanMgb24gT1MgWC5cbiAgICAgIHJldHVybiB2b2lkIDA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vbmtleSBwYXRjaCBvcGVyYXRpb25zIHRoYXQgd291bGQgbWFrZSB0aGVpciBhcmd1bWVudFxuICAgKiBub24tZXh0ZW5zaWJsZS5cbiAgICpcbiAgICogPHA+VGhlIG1vbmtleSBwYXRjaGVkIHZlcnNpb25zIHRocm93IGEgVHlwZUVycm9yIGlmIHRoZWlyXG4gICAqIGFyZ3VtZW50IGlzIG5vdCBhbiBvYmplY3QsIHNvIGl0IHNob3VsZCBvbmx5IGJlIGRvbmUgdG8gZnVuY3Rpb25zXG4gICAqIHRoYXQgc2hvdWxkIHRocm93IGEgVHlwZUVycm9yIGFueXdheSBpZiB0aGVpciBhcmd1bWVudCBpcyBub3QgYW5cbiAgICogb2JqZWN0LlxuICAgKi9cbiAgKGZ1bmN0aW9uKCl7XG4gICAgdmFyIG9sZEZyZWV6ZSA9IE9iamVjdC5mcmVlemU7XG4gICAgZGVmUHJvcChPYmplY3QsICdmcmVlemUnLCB7XG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaWRlbnRpZnlpbmdGcmVlemUob2JqKSB7XG4gICAgICAgIGdldEhpZGRlblJlY29yZChvYmopO1xuICAgICAgICByZXR1cm4gb2xkRnJlZXplKG9iaik7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdmFyIG9sZFNlYWwgPSBPYmplY3Quc2VhbDtcbiAgICBkZWZQcm9wKE9iamVjdCwgJ3NlYWwnLCB7XG4gICAgICB2YWx1ZTogZnVuY3Rpb24gaWRlbnRpZnlpbmdTZWFsKG9iaikge1xuICAgICAgICBnZXRIaWRkZW5SZWNvcmQob2JqKTtcbiAgICAgICAgcmV0dXJuIG9sZFNlYWwob2JqKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB2YXIgb2xkUHJldmVudEV4dGVuc2lvbnMgPSBPYmplY3QucHJldmVudEV4dGVuc2lvbnM7XG4gICAgZGVmUHJvcChPYmplY3QsICdwcmV2ZW50RXh0ZW5zaW9ucycsIHtcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpZGVudGlmeWluZ1ByZXZlbnRFeHRlbnNpb25zKG9iaikge1xuICAgICAgICBnZXRIaWRkZW5SZWNvcmQob2JqKTtcbiAgICAgICAgcmV0dXJuIG9sZFByZXZlbnRFeHRlbnNpb25zKG9iaik7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pKCk7XG5cbiAgZnVuY3Rpb24gY29uc3RGdW5jKGZ1bmMpIHtcbiAgICBmdW5jLnByb3RvdHlwZSA9IG51bGw7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoZnVuYyk7XG4gIH1cblxuICB2YXIgY2FsbGVkQXNGdW5jdGlvbldhcm5pbmdEb25lID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGNhbGxlZEFzRnVuY3Rpb25XYXJuaW5nKCkge1xuICAgIC8vIEZ1dHVyZSBFUzYgV2Vha01hcCBpcyBjdXJyZW50bHkgKDIwMTMtMDktMTApIGV4cGVjdGVkIHRvIHJlamVjdCBXZWFrTWFwKClcbiAgICAvLyBidXQgd2UgdXNlZCB0byBwZXJtaXQgaXQgYW5kIGRvIGl0IG91cnNlbHZlcywgc28gd2FybiBvbmx5LlxuICAgIGlmICghY2FsbGVkQXNGdW5jdGlvbldhcm5pbmdEb25lICYmIHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgY2FsbGVkQXNGdW5jdGlvbldhcm5pbmdEb25lID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUud2FybignV2Vha01hcCBzaG91bGQgYmUgaW52b2tlZCBhcyBuZXcgV2Vha01hcCgpLCBub3QgJyArXG4gICAgICAgICAgJ1dlYWtNYXAoKS4gVGhpcyB3aWxsIGJlIGFuIGVycm9yIGluIHRoZSBmdXR1cmUuJyk7XG4gICAgfVxuICB9XG5cbiAgdmFyIG5leHRJZCA9IDA7XG5cbiAgdmFyIE91cldlYWtNYXAgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgT3VyV2Vha01hcCkpIHsgIC8vIGFwcHJveGltYXRlIHRlc3QgZm9yIG5ldyAuLi4oKVxuICAgICAgY2FsbGVkQXNGdW5jdGlvbldhcm5pbmcoKTtcbiAgICB9XG5cbiAgICAvLyBXZSBhcmUgY3VycmVudGx5ICgxMi8yNS8yMDEyKSBuZXZlciBlbmNvdW50ZXJpbmcgYW55IHByZW1hdHVyZWx5XG4gICAgLy8gbm9uLWV4dGVuc2libGUga2V5cy5cbiAgICB2YXIga2V5cyA9IFtdOyAvLyBicnV0ZSBmb3JjZSBmb3IgcHJlbWF0dXJlbHkgbm9uLWV4dGVuc2libGUga2V5cy5cbiAgICB2YXIgdmFsdWVzID0gW107IC8vIGJydXRlIGZvcmNlIGZvciBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICB2YXIgaWQgPSBuZXh0SWQrKztcblxuICAgIGZ1bmN0aW9uIGdldF9fXyhrZXksIG9wdF9kZWZhdWx0KSB7XG4gICAgICB2YXIgaW5kZXg7XG4gICAgICB2YXIgaGlkZGVuUmVjb3JkID0gZ2V0SGlkZGVuUmVjb3JkKGtleSk7XG4gICAgICBpZiAoaGlkZGVuUmVjb3JkKSB7XG4gICAgICAgIHJldHVybiBpZCBpbiBoaWRkZW5SZWNvcmQgPyBoaWRkZW5SZWNvcmRbaWRdIDogb3B0X2RlZmF1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleCA9IGtleXMuaW5kZXhPZihrZXkpO1xuICAgICAgICByZXR1cm4gaW5kZXggPj0gMCA/IHZhbHVlc1tpbmRleF0gOiBvcHRfZGVmYXVsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYXNfX18oa2V5KSB7XG4gICAgICB2YXIgaGlkZGVuUmVjb3JkID0gZ2V0SGlkZGVuUmVjb3JkKGtleSk7XG4gICAgICBpZiAoaGlkZGVuUmVjb3JkKSB7XG4gICAgICAgIHJldHVybiBpZCBpbiBoaWRkZW5SZWNvcmQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ga2V5cy5pbmRleE9mKGtleSkgPj0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRfX18oa2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIGluZGV4O1xuICAgICAgdmFyIGhpZGRlblJlY29yZCA9IGdldEhpZGRlblJlY29yZChrZXkpO1xuICAgICAgaWYgKGhpZGRlblJlY29yZCkge1xuICAgICAgICBoaWRkZW5SZWNvcmRbaWRdID0gdmFsdWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleCA9IGtleXMuaW5kZXhPZihrZXkpO1xuICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgICAgIHZhbHVlc1tpbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBTaW5jZSBzb21lIGJyb3dzZXJzIHByZWVtcHRpdmVseSB0ZXJtaW5hdGUgc2xvdyB0dXJucyBidXRcbiAgICAgICAgICAvLyB0aGVuIGNvbnRpbnVlIGNvbXB1dGluZyB3aXRoIHByZXN1bWFibHkgY29ycnVwdGVkIGhlYXBcbiAgICAgICAgICAvLyBzdGF0ZSwgd2UgaGVyZSBkZWZlbnNpdmVseSBnZXQga2V5cy5sZW5ndGggZmlyc3QgYW5kIHRoZW5cbiAgICAgICAgICAvLyB1c2UgaXQgdG8gdXBkYXRlIGJvdGggdGhlIHZhbHVlcyBhbmQga2V5cyBhcnJheXMsIGtlZXBpbmdcbiAgICAgICAgICAvLyB0aGVtIGluIHN5bmMuXG4gICAgICAgICAgaW5kZXggPSBrZXlzLmxlbmd0aDtcbiAgICAgICAgICB2YWx1ZXNbaW5kZXhdID0gdmFsdWU7XG4gICAgICAgICAgLy8gSWYgd2UgY3Jhc2ggaGVyZSwgdmFsdWVzIHdpbGwgYmUgb25lIGxvbmdlciB0aGFuIGtleXMuXG4gICAgICAgICAga2V5c1tpbmRleF0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlbGV0ZV9fXyhrZXkpIHtcbiAgICAgIHZhciBoaWRkZW5SZWNvcmQgPSBnZXRIaWRkZW5SZWNvcmQoa2V5KTtcbiAgICAgIHZhciBpbmRleCwgbGFzdEluZGV4O1xuICAgICAgaWYgKGhpZGRlblJlY29yZCkge1xuICAgICAgICByZXR1cm4gaWQgaW4gaGlkZGVuUmVjb3JkICYmIGRlbGV0ZSBoaWRkZW5SZWNvcmRbaWRdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kZXggPSBrZXlzLmluZGV4T2Yoa2V5KTtcbiAgICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTaW5jZSBzb21lIGJyb3dzZXJzIHByZWVtcHRpdmVseSB0ZXJtaW5hdGUgc2xvdyB0dXJucyBidXRcbiAgICAgICAgLy8gdGhlbiBjb250aW51ZSBjb21wdXRpbmcgd2l0aCBwb3RlbnRpYWxseSBjb3JydXB0ZWQgaGVhcFxuICAgICAgICAvLyBzdGF0ZSwgd2UgaGVyZSBkZWZlbnNpdmVseSBnZXQga2V5cy5sZW5ndGggZmlyc3QgYW5kIHRoZW4gdXNlXG4gICAgICAgIC8vIGl0IHRvIHVwZGF0ZSBib3RoIHRoZSBrZXlzIGFuZCB0aGUgdmFsdWVzIGFycmF5LCBrZWVwaW5nXG4gICAgICAgIC8vIHRoZW0gaW4gc3luYy4gV2UgdXBkYXRlIHRoZSB0d28gd2l0aCBhbiBvcmRlciBvZiBhc3NpZ25tZW50cyxcbiAgICAgICAgLy8gc3VjaCB0aGF0IGFueSBwcmVmaXggb2YgdGhlc2UgYXNzaWdubWVudHMgd2lsbCBwcmVzZXJ2ZSB0aGVcbiAgICAgICAgLy8ga2V5L3ZhbHVlIGNvcnJlc3BvbmRlbmNlLCBlaXRoZXIgYmVmb3JlIG9yIGFmdGVyIHRoZSBkZWxldGUuXG4gICAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIG5lZWRzIHRvIHdvcmsgY29ycmVjdGx5IHdoZW4gaW5kZXggPT09IGxhc3RJbmRleC5cbiAgICAgICAgbGFzdEluZGV4ID0ga2V5cy5sZW5ndGggLSAxO1xuICAgICAgICBrZXlzW2luZGV4XSA9IHZvaWQgMDtcbiAgICAgICAgLy8gSWYgd2UgY3Jhc2ggaGVyZSwgdGhlcmUncyBhIHZvaWQgMCBpbiB0aGUga2V5cyBhcnJheSwgYnV0XG4gICAgICAgIC8vIG5vIG9wZXJhdGlvbiB3aWxsIGNhdXNlIGEgXCJrZXlzLmluZGV4T2Yodm9pZCAwKVwiLCBzaW5jZVxuICAgICAgICAvLyBnZXRIaWRkZW5SZWNvcmQodm9pZCAwKSB3aWxsIGFsd2F5cyB0aHJvdyBhbiBlcnJvciBmaXJzdC5cbiAgICAgICAgdmFsdWVzW2luZGV4XSA9IHZhbHVlc1tsYXN0SW5kZXhdO1xuICAgICAgICAvLyBJZiB3ZSBjcmFzaCBoZXJlLCB2YWx1ZXNbaW5kZXhdIGNhbm5vdCBiZSBmb3VuZCBoZXJlLFxuICAgICAgICAvLyBiZWNhdXNlIGtleXNbaW5kZXhdIGlzIHZvaWQgMC5cbiAgICAgICAga2V5c1tpbmRleF0gPSBrZXlzW2xhc3RJbmRleF07XG4gICAgICAgIC8vIElmIGluZGV4ID09PSBsYXN0SW5kZXggYW5kIHdlIGNyYXNoIGhlcmUsIHRoZW4ga2V5c1tpbmRleF1cbiAgICAgICAgLy8gaXMgc3RpbGwgdm9pZCAwLCBzaW5jZSB0aGUgYWxpYXNpbmcga2lsbGVkIHRoZSBwcmV2aW91cyBrZXkuXG4gICAgICAgIGtleXMubGVuZ3RoID0gbGFzdEluZGV4O1xuICAgICAgICAvLyBJZiB3ZSBjcmFzaCBoZXJlLCBrZXlzIHdpbGwgYmUgb25lIHNob3J0ZXIgdGhhbiB2YWx1ZXMuXG4gICAgICAgIHZhbHVlcy5sZW5ndGggPSBsYXN0SW5kZXg7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuY3JlYXRlKE91cldlYWtNYXAucHJvdG90eXBlLCB7XG4gICAgICBnZXRfX186ICAgIHsgdmFsdWU6IGNvbnN0RnVuYyhnZXRfX18pIH0sXG4gICAgICBoYXNfX186ICAgIHsgdmFsdWU6IGNvbnN0RnVuYyhoYXNfX18pIH0sXG4gICAgICBzZXRfX186ICAgIHsgdmFsdWU6IGNvbnN0RnVuYyhzZXRfX18pIH0sXG4gICAgICBkZWxldGVfX186IHsgdmFsdWU6IGNvbnN0RnVuYyhkZWxldGVfX18pIH1cbiAgICB9KTtcbiAgfTtcblxuICBPdXJXZWFrTWFwLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0LnByb3RvdHlwZSwge1xuICAgIGdldDoge1xuICAgICAgLyoqXG4gICAgICAgKiBSZXR1cm4gdGhlIHZhbHVlIG1vc3QgcmVjZW50bHkgYXNzb2NpYXRlZCB3aXRoIGtleSwgb3JcbiAgICAgICAqIG9wdF9kZWZhdWx0IGlmIG5vbmUuXG4gICAgICAgKi9cbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXQoa2V5LCBvcHRfZGVmYXVsdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRfX18oa2V5LCBvcHRfZGVmYXVsdCk7XG4gICAgICB9LFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9LFxuXG4gICAgaGFzOiB7XG4gICAgICAvKipcbiAgICAgICAqIElzIHRoZXJlIGEgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGtleSBpbiB0aGlzIFdlYWtNYXA/XG4gICAgICAgKi9cbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBoYXMoa2V5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhc19fXyhrZXkpO1xuICAgICAgfSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSxcblxuICAgIHNldDoge1xuICAgICAgLyoqXG4gICAgICAgKiBBc3NvY2lhdGUgdmFsdWUgd2l0aCBrZXkgaW4gdGhpcyBXZWFrTWFwLCBvdmVyd3JpdGluZyBhbnlcbiAgICAgICAqIHByZXZpb3VzIGFzc29jaWF0aW9uIGlmIHByZXNlbnQuXG4gICAgICAgKi9cbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRfX18oa2V5LCB2YWx1ZSk7XG4gICAgICB9LFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9LFxuXG4gICAgJ2RlbGV0ZSc6IHtcbiAgICAgIC8qKlxuICAgICAgICogUmVtb3ZlIGFueSBhc3NvY2lhdGlvbiBmb3Iga2V5IGluIHRoaXMgV2Vha01hcCwgcmV0dXJuaW5nXG4gICAgICAgKiB3aGV0aGVyIHRoZXJlIHdhcyBvbmUuXG4gICAgICAgKlxuICAgICAgICogPHA+Tm90ZSB0aGF0IHRoZSBib29sZWFuIHJldHVybiBoZXJlIGRvZXMgbm90IHdvcmsgbGlrZSB0aGVcbiAgICAgICAqIHtAY29kZSBkZWxldGV9IG9wZXJhdG9yLiBUaGUge0Bjb2RlIGRlbGV0ZX0gb3BlcmF0b3IgcmV0dXJuc1xuICAgICAgICogd2hldGhlciB0aGUgZGVsZXRpb24gc3VjY2VlZHMgYXQgYnJpbmdpbmcgYWJvdXQgYSBzdGF0ZSBpblxuICAgICAgICogd2hpY2ggdGhlIGRlbGV0ZWQgcHJvcGVydHkgaXMgYWJzZW50LiBUaGUge0Bjb2RlIGRlbGV0ZX1cbiAgICAgICAqIG9wZXJhdG9yIHRoZXJlZm9yZSByZXR1cm5zIHRydWUgaWYgdGhlIHByb3BlcnR5IHdhcyBhbHJlYWR5XG4gICAgICAgKiBhYnNlbnQsIHdoZXJlYXMgdGhpcyB7QGNvZGUgZGVsZXRlfSBtZXRob2QgcmV0dXJucyBmYWxzZSBpZlxuICAgICAgICogdGhlIGFzc29jaWF0aW9uIHdhcyBhbHJlYWR5IGFic2VudC5cbiAgICAgICAqL1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlbW92ZShrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVsZXRlX19fKGtleSk7XG4gICAgICB9LFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9XG4gIH0pO1xuXG4gIGlmICh0eXBlb2YgSG9zdFdlYWtNYXAgPT09ICdmdW5jdGlvbicpIHtcbiAgICAoZnVuY3Rpb24oKSB7XG4gICAgICAvLyBJZiB3ZSBnb3QgaGVyZSwgdGhlbiB0aGUgcGxhdGZvcm0gaGFzIGEgV2Vha01hcCBidXQgd2UgYXJlIGNvbmNlcm5lZFxuICAgICAgLy8gdGhhdCBpdCBtYXkgcmVmdXNlIHRvIHN0b3JlIHNvbWUga2V5IHR5cGVzLiBUaGVyZWZvcmUsIG1ha2UgYSBtYXBcbiAgICAgIC8vIGltcGxlbWVudGF0aW9uIHdoaWNoIG1ha2VzIHVzZSBvZiBib3RoIGFzIHBvc3NpYmxlLlxuXG4gICAgICAvLyBJbiB0aGlzIG1vZGUgd2UgYXJlIGFsd2F5cyB1c2luZyBkb3VibGUgbWFwcywgc28gd2UgYXJlIG5vdCBwcm94eS1zYWZlLlxuICAgICAgLy8gVGhpcyBjb21iaW5hdGlvbiBkb2VzIG5vdCBvY2N1ciBpbiBhbnkga25vd24gYnJvd3NlciwgYnV0IHdlIGhhZCBiZXN0XG4gICAgICAvLyBiZSBzYWZlLlxuICAgICAgaWYgKGRvdWJsZVdlYWtNYXBDaGVja1NpbGVudEZhaWx1cmUgJiYgdHlwZW9mIFByb3h5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBQcm94eSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gRG91YmxlV2Vha01hcCgpIHtcbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIE91cldlYWtNYXApKSB7ICAvLyBhcHByb3hpbWF0ZSB0ZXN0IGZvciBuZXcgLi4uKClcbiAgICAgICAgICBjYWxsZWRBc0Z1bmN0aW9uV2FybmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJlZmVyYWJsZSwgdHJ1bHkgd2VhayBtYXAuXG4gICAgICAgIHZhciBobWFwID0gbmV3IEhvc3RXZWFrTWFwKCk7XG5cbiAgICAgICAgLy8gT3VyIGhpZGRlbi1wcm9wZXJ0eS1iYXNlZCBwc2V1ZG8td2Vhay1tYXAuIExhemlseSBpbml0aWFsaXplZCBpbiB0aGVcbiAgICAgICAgLy8gJ3NldCcgaW1wbGVtZW50YXRpb247IHRodXMgd2UgY2FuIGF2b2lkIHBlcmZvcm1pbmcgZXh0cmEgbG9va3VwcyBpZlxuICAgICAgICAvLyB3ZSBrbm93IGFsbCBlbnRyaWVzIGFjdHVhbGx5IHN0b3JlZCBhcmUgZW50ZXJlZCBpbiAnaG1hcCcuXG4gICAgICAgIHZhciBvbWFwID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIEhpZGRlbi1wcm9wZXJ0eSBtYXBzIGFyZSBub3QgY29tcGF0aWJsZSB3aXRoIHByb3hpZXMgYmVjYXVzZSBwcm94aWVzXG4gICAgICAgIC8vIGNhbiBvYnNlcnZlIHRoZSBoaWRkZW4gbmFtZSBhbmQgZWl0aGVyIGFjY2lkZW50YWxseSBleHBvc2UgaXQgb3IgZmFpbFxuICAgICAgICAvLyB0byBhbGxvdyB0aGUgaGlkZGVuIHByb3BlcnR5IHRvIGJlIHNldC4gVGhlcmVmb3JlLCB3ZSBkbyBub3QgYWxsb3dcbiAgICAgICAgLy8gYXJiaXRyYXJ5IFdlYWtNYXBzIHRvIHN3aXRjaCB0byB1c2luZyBoaWRkZW4gcHJvcGVydGllcywgYnV0IG9ubHlcbiAgICAgICAgLy8gdGhvc2Ugd2hpY2ggbmVlZCB0aGUgYWJpbGl0eSwgYW5kIHVucHJpdmlsZWdlZCBjb2RlIGlzIG5vdCBhbGxvd2VkXG4gICAgICAgIC8vIHRvIHNldCB0aGUgZmxhZy5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gKEV4Y2VwdCBpbiBkb3VibGVXZWFrTWFwQ2hlY2tTaWxlbnRGYWlsdXJlIG1vZGUgaW4gd2hpY2ggY2FzZSB3ZVxuICAgICAgICAvLyBkaXNhYmxlIHByb3hpZXMuKVxuICAgICAgICB2YXIgZW5hYmxlU3dpdGNoaW5nID0gZmFsc2U7XG5cbiAgICAgICAgZnVuY3Rpb24gZGdldChrZXksIG9wdF9kZWZhdWx0KSB7XG4gICAgICAgICAgaWYgKG9tYXApIHtcbiAgICAgICAgICAgIHJldHVybiBobWFwLmhhcyhrZXkpID8gaG1hcC5nZXQoa2V5KVxuICAgICAgICAgICAgICAgIDogb21hcC5nZXRfX18oa2V5LCBvcHRfZGVmYXVsdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBobWFwLmdldChrZXksIG9wdF9kZWZhdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBkaGFzKGtleSkge1xuICAgICAgICAgIHJldHVybiBobWFwLmhhcyhrZXkpIHx8IChvbWFwID8gb21hcC5oYXNfX18oa2V5KSA6IGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkc2V0O1xuICAgICAgICBpZiAoZG91YmxlV2Vha01hcENoZWNrU2lsZW50RmFpbHVyZSkge1xuICAgICAgICAgIGRzZXQgPSBmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICBobWFwLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIGlmICghaG1hcC5oYXMoa2V5KSkge1xuICAgICAgICAgICAgICBpZiAoIW9tYXApIHsgb21hcCA9IG5ldyBPdXJXZWFrTWFwKCk7IH1cbiAgICAgICAgICAgICAgb21hcC5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRzZXQgPSBmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAoZW5hYmxlU3dpdGNoaW5nKSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaG1hcC5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW9tYXApIHsgb21hcCA9IG5ldyBPdXJXZWFrTWFwKCk7IH1cbiAgICAgICAgICAgICAgICBvbWFwLnNldF9fXyhrZXksIHZhbHVlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaG1hcC5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZGRlbGV0ZShrZXkpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gISFobWFwWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgIGlmIChvbWFwKSB7IHJldHVybiBvbWFwLmRlbGV0ZV9fXyhrZXkpIHx8IHJlc3VsdDsgfVxuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShPdXJXZWFrTWFwLnByb3RvdHlwZSwge1xuICAgICAgICAgIGdldF9fXzogICAgeyB2YWx1ZTogY29uc3RGdW5jKGRnZXQpIH0sXG4gICAgICAgICAgaGFzX19fOiAgICB7IHZhbHVlOiBjb25zdEZ1bmMoZGhhcykgfSxcbiAgICAgICAgICBzZXRfX186ICAgIHsgdmFsdWU6IGNvbnN0RnVuYyhkc2V0KSB9LFxuICAgICAgICAgIGRlbGV0ZV9fXzogeyB2YWx1ZTogY29uc3RGdW5jKGRkZWxldGUpIH0sXG4gICAgICAgICAgcGVybWl0SG9zdE9iamVjdHNfX186IHsgdmFsdWU6IGNvbnN0RnVuYyhmdW5jdGlvbih0b2tlbikge1xuICAgICAgICAgICAgaWYgKHRva2VuID09PSB3ZWFrTWFwUGVybWl0SG9zdE9iamVjdHMpIHtcbiAgICAgICAgICAgICAgZW5hYmxlU3dpdGNoaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYm9ndXMgY2FsbCB0byBwZXJtaXRIb3N0T2JqZWN0c19fXycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIERvdWJsZVdlYWtNYXAucHJvdG90eXBlID0gT3VyV2Vha01hcC5wcm90b3R5cGU7XG4gICAgICBtb2R1bGUuZXhwb3J0cyA9IERvdWJsZVdlYWtNYXA7XG5cbiAgICAgIC8vIGRlZmluZSAuY29uc3RydWN0b3IgdG8gaGlkZSBPdXJXZWFrTWFwIGN0b3JcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShXZWFrTWFwLnByb3RvdHlwZSwgJ2NvbnN0cnVjdG9yJywge1xuICAgICAgICB2YWx1ZTogV2Vha01hcCxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsICAvLyBhcyBkZWZhdWx0IC5jb25zdHJ1Y3RvciBpc1xuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICB9KTtcbiAgICB9KSgpO1xuICB9IGVsc2Uge1xuICAgIC8vIFRoZXJlIGlzIG5vIGhvc3QgV2Vha01hcCwgc28gd2UgbXVzdCB1c2UgdGhlIGVtdWxhdGlvbi5cblxuICAgIC8vIEVtdWxhdGVkIFdlYWtNYXBzIGFyZSBpbmNvbXBhdGlibGUgd2l0aCBuYXRpdmUgcHJveGllcyAoYmVjYXVzZSBwcm94aWVzXG4gICAgLy8gY2FuIG9ic2VydmUgdGhlIGhpZGRlbiBuYW1lKSwgc28gd2UgbXVzdCBkaXNhYmxlIFByb3h5IHVzYWdlIChpblxuICAgIC8vIEFycmF5TGlrZSBhbmQgRG9tYWRvLCBjdXJyZW50bHkpLlxuICAgIGlmICh0eXBlb2YgUHJveHkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBQcm94eSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBtb2R1bGUuZXhwb3J0cyA9IE91cldlYWtNYXA7XG4gIH1cbn0pKCk7XG4iLCJ2YXIgaGlkZGVuU3RvcmUgPSByZXF1aXJlKCcuL2hpZGRlbi1zdG9yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVN0b3JlO1xuXG5mdW5jdGlvbiBjcmVhdGVTdG9yZSgpIHtcbiAgICB2YXIga2V5ID0ge307XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKG9iaikge1xuICAgICAgICBpZiAoKHR5cGVvZiBvYmogIT09ICdvYmplY3QnIHx8IG9iaiA9PT0gbnVsbCkgJiZcbiAgICAgICAgICAgIHR5cGVvZiBvYmogIT09ICdmdW5jdGlvbidcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYWttYXAtc2hpbTogS2V5IG11c3QgYmUgb2JqZWN0JylcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzdG9yZSA9IG9iai52YWx1ZU9mKGtleSk7XG4gICAgICAgIHJldHVybiBzdG9yZSAmJiBzdG9yZS5pZGVudGl0eSA9PT0ga2V5ID9cbiAgICAgICAgICAgIHN0b3JlIDogaGlkZGVuU3RvcmUob2JqLCBrZXkpO1xuICAgIH07XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGhpZGRlblN0b3JlO1xuXG5mdW5jdGlvbiBoaWRkZW5TdG9yZShvYmosIGtleSkge1xuICAgIHZhciBzdG9yZSA9IHsgaWRlbnRpdHk6IGtleSB9O1xuICAgIHZhciB2YWx1ZU9mID0gb2JqLnZhbHVlT2Y7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBcInZhbHVlT2ZcIiwge1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgIT09IGtleSA/XG4gICAgICAgICAgICAgICAgdmFsdWVPZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogc3RvcmU7XG4gICAgICAgIH0sXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG5cbiAgICByZXR1cm4gc3RvcmU7XG59XG4iLCIvLyBPcmlnaW5hbCAtIEBHb3pvbGEuXG4vLyBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9Hb3phbGEvMTI2OTk5MVxuLy8gVGhpcyBpcyBhIHJlaW1wbGVtZW50ZWQgdmVyc2lvbiAod2l0aCBhIGZldyBidWcgZml4ZXMpLlxuXG52YXIgY3JlYXRlU3RvcmUgPSByZXF1aXJlKCcuL2NyZWF0ZS1zdG9yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHdlYWtNYXA7XG5cbmZ1bmN0aW9uIHdlYWtNYXAoKSB7XG4gICAgdmFyIHByaXZhdGVzID0gY3JlYXRlU3RvcmUoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgICdnZXQnOiBmdW5jdGlvbiAoa2V5LCBmYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHN0b3JlID0gcHJpdmF0ZXMoa2V5KVxuICAgICAgICAgICAgcmV0dXJuIHN0b3JlLmhhc093blByb3BlcnR5KCd2YWx1ZScpID9cbiAgICAgICAgICAgICAgICBzdG9yZS52YWx1ZSA6IGZhbGxiYWNrXG4gICAgICAgIH0sXG4gICAgICAgICdzZXQnOiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgcHJpdmF0ZXMoa2V5KS52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgICdoYXMnOiBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiAndmFsdWUnIGluIHByaXZhdGVzKGtleSk7XG4gICAgICAgIH0sXG4gICAgICAgICdkZWxldGUnOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZGVsZXRlIHByaXZhdGVzKGtleSkudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJ2YXIgZ2V0Q29udGV4dCA9IHJlcXVpcmUoJ2dldC1jYW52YXMtY29udGV4dCcpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0V2ViR0xDb250ZXh0IChvcHQpIHtcbiAgcmV0dXJuIGdldENvbnRleHQoJ3dlYmdsJywgb3B0KVxufVxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBUcmFkaXRpb25hbCBDaGluZXNlIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBOaWNvbGFzIFJpZXNjbyAoZW5xdWlyaWVzQG5pY29sYXNyaWVzY28ubmV0KSBEZWNlbWJlciAyMDE2LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxudmFyIGdyZWdvcmlhbkNhbGVuZGFyID0gbWFpbi5pbnN0YW5jZSgpO1xuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIHRyYWRpdGlvbmFsIENoaW5lc2UgY2FsZW5kYXIuXG4gICAgU291cmNlIG9mIGNhbGVuZGFyIHRhYmxlcyBodHRwczovL2dpdGh1Yi5jb20vaXNlZTE1L0x1bmFyLVNvbGFyLUNhbGVuZGFyLUNvbnZlcnRlciAuXG4gICAgQGNsYXNzIENoaW5lc2VDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBDaGluZXNlQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuQ2hpbmVzZUNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKENoaW5lc2VDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnQ2hpbmVzZScsXG4gICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBHcmVnb3JpYW4gZXBvY2g6IDEgSmFudWFyeSAwMDAxIENFLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxNzIxNDI1LjUsXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBUaGlzIGNhbGVuZGFyIHVzZXMgbW9udGggaW5kaWNlcyB0byBhY2NvdW50IGZvciBpbnRlcmNhbGFyeSBtb250aHMuIFxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDAsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgVGhpcyBjYWxlbmRhciB1c2VzIG1vbnRoIGluZGljZXMgdG8gYWNjb3VudCBmb3IgaW50ZXJjYWxhcnkgbW9udGhzLiBcbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDAsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnQ2hpbmVzZScsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQkVDJywgJ0VDJ10sXG4gICAgICAgICAgICBtb250aE51bWJlcnM6IGZ1bmN0aW9uKGRhdGUsIHBhZGRlZCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gZGF0ZS5tYXRjaChNT05USF9OVU1CRVJfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gJycgKyB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhZGRlZCAmJiBtb250aC5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoID0gXCIwXCIgKyBtb250aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0ludGVyY2FsYXJ5TW9udGgoeWVhciwgbW9udGhJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9udGggKz0gJ2knO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBkYXRlLm1hdGNoKE1PTlRIX05BTUVfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy50b0NoaW5lc2VNb250aCh5ZWFyLCBtb250aEluZGV4KTtcblxuICAgICAgICAgICAgICAgIHZhciBtb250aE5hbWUgPSBbJ+S4gOaciCcsJ+S6jOaciCcsJ+S4ieaciCcsJ+Wbm+aciCcsJ+S6lOaciCcsJ+WFreaciCcsXG4gICAgICAgICAgICAgICAgICAgICfkuIPmnIgnLCflhavmnIgnLCfkuZ3mnIgnLCfljYHmnIgnLCfljYHkuIDmnIgnLCfljYHkuozmnIgnXVttb250aCAtIDFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZSA9ICfpl7AnICsgbW9udGhOYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aE5hbWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBkYXRlLm1hdGNoKE1PTlRIX1NIT1JUX05BTUVfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy50b0NoaW5lc2VNb250aCh5ZWFyLCBtb250aEluZGV4KTtcblxuICAgICAgICAgICAgICAgIHZhciBtb250aE5hbWUgPSBbJ+S4gCcsJ+S6jCcsJ+S4iScsJ+WbmycsJ+S6lCcsJ+WFrScsXG4gICAgICAgICAgICAgICAgICAgICfkuIMnLCflhasnLCfkuZ0nLCfljYEnLCfljYHkuIAnLCfljYHkuownXVttb250aCAtIDFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZSA9ICfpl7AnICsgbW9udGhOYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aE5hbWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFyc2VNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKHllYXIpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aCA9IHBhcnNlSW50KG1vbnRoU3RyaW5nKTtcbiAgICAgICAgICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeTtcblxuICAgICAgICAgICAgICAgIGlmICghaXNOYU4obW9udGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpID0gbW9udGhTdHJpbmdbbW9udGhTdHJpbmcubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgIGlzSW50ZXJjYWxhcnkgPSAoaSA9PT0gJ2knIHx8IGkgPT09ICdJJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vbnRoU3RyaW5nWzBdID09PSAn6ZewJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnRlcmNhbGFyeSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb250aFN0cmluZyA9IG1vbnRoU3RyaW5nLnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9udGhTdHJpbmdbbW9udGhTdHJpbmcubGVuZ3RoIC0gMV0gPT09ICfmnIgnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb250aFN0cmluZyA9IG1vbnRoU3RyaW5nLnN1YnN0cmluZygwLCBtb250aFN0cmluZy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtb250aCA9IDEgK1xuICAgICAgICAgICAgICAgICAgICAgICAgWyfkuIAnLCfkuownLCfkuIknLCflm5snLCfkupQnLCflha0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ+S4gycsJ+WFqycsJ+S5nScsJ+WNgScsJ+WNgeS4gCcsJ+WNgeS6jCddLmluZGV4T2YobW9udGhTdHJpbmcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gdGhpcy50b01vbnRoSW5kZXgoeWVhciwgbW9udGgsIGlzSW50ZXJjYWxhcnkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aEluZGV4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnU3UnLCAnTW8nLCAnVHUnLCAnV2UnLCAnVGgnLCAnRnInLCAnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAxLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIENoZWNrIHRoYXQgYSBjYW5kaWRhdGUgZGF0ZSBpcyBmcm9tIHRoZSBzYW1lIGNhbGVuZGFyIGFuZCBpcyB2YWxpZC5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSBvciB0aGUgeWVhciB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIGVycm9yIHtzdHJpbmd9IEVycm9yIG1lc3NhZ2UgaWYgaW52YWxpZC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiB5ZWFyIG91dCBvZiByYW5nZS4gKi9cbiAgICBfdmFsaWRhdGVZZWFyOiBmdW5jdGlvbih5ZWFyLCBlcnJvcikge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHllYXIgIT09ICdudW1iZXInIHx8IHllYXIgPCAxODg4IHx8IHllYXIgPiAyMTExKSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvci5yZXBsYWNlKC9cXHswXFx9LywgdGhpcy5sb2NhbC5uYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB5ZWFyO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG1vbnRoIGluZGV4IChpLmUuIGFjY291bnRpbmcgZm9yIGludGVyY2FsYXJ5IG1vbnRocykuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggKDEgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHBhcmFtIFtpc0ludGVyY2FsYXJ5PWZhbHNlXSB7Ym9vbGVhbn0gSWYgbW9udGggaXMgaW50ZXJjYWxhcnkuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG1vbnRoIGluZGV4ICgwIGZvciBmaXJzdCBtb250aCkuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9Nb250aEluZGV4OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgaXNJbnRlcmNhbGFyeSkge1xuICAgICAgICAvLyBjb21wdXRlIGludGVyY2FsYXJ5IG1vbnRoIGluIHRoZSB5ZWFyICgwIGlmIG5vbmUpXG4gICAgICAgIHZhciBpbnRlcmNhbGFyeU1vbnRoID0gdGhpcy5pbnRlcmNhbGFyeU1vbnRoKHllYXIpO1xuXG4gICAgICAgIC8vIHZhbGlkYXRlIG1vbnRoXG4gICAgICAgIHZhciBpbnZhbGlkSW50ZXJjYWxhcnlNb250aCA9IFxuICAgICAgICAgICAgKGlzSW50ZXJjYWxhcnkgJiYgbW9udGggIT09IGludGVyY2FsYXJ5TW9udGgpO1xuICAgICAgICBpZiAoaW52YWxpZEludGVyY2FsYXJ5TW9udGggfHwgbW9udGggPCAxIHx8IG1vbnRoID4gMTIpIHtcbiAgICAgICAgICAgIHRocm93IG1haW4ubG9jYWwuaW52YWxpZE1vbnRoXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLmxvY2FsLm5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29tcHV0ZSBtb250aCBpbmRleFxuICAgICAgICB2YXIgbW9udGhJbmRleDtcblxuICAgICAgICBpZiAoIWludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgICAgIG1vbnRoSW5kZXggPSBtb250aCAtIDE7XG4gICAgICAgIH0gZWxzZSBpZighaXNJbnRlcmNhbGFyeSAmJiBtb250aCA8PSBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgICAgICBtb250aEluZGV4ID0gbW9udGggLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9udGhJbmRleCA9IG1vbnRoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1vbnRoSW5kZXg7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbW9udGggKGkuZS4gYWNjb3VudGluZyBmb3IgaW50ZXJjYWxhcnkgbW9udGhzKS5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gbW9udGhJbmRleCB7bnVtYmVyfSBUaGUgbW9udGggaW5kZXggKDAgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbW9udGggKDEgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0NoaW5lc2VNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29tcHV0ZSBpbnRlcmNhbGFyeSBtb250aCBpbiB0aGUgeWVhciAoMCBpZiBub25lKVxuICAgICAgICB2YXIgaW50ZXJjYWxhcnlNb250aCA9IHRoaXMuaW50ZXJjYWxhcnlNb250aCh5ZWFyKTtcblxuICAgICAgICAvLyB2YWxpZGF0ZSBtb250aFxuICAgICAgICB2YXIgbWF4TW9udGhJbmRleCA9IChpbnRlcmNhbGFyeU1vbnRoKSA/IDEyIDogMTE7XG4gICAgICAgIGlmIChtb250aEluZGV4IDwgMCB8fCBtb250aEluZGV4ID4gbWF4TW9udGhJbmRleCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGhcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMubG9jYWwubmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb21wdXRlIENoaW5lc2UgbW9udGhcbiAgICAgICAgdmFyIG1vbnRoO1xuXG4gICAgICAgIGlmICghaW50ZXJjYWxhcnlNb250aCkge1xuICAgICAgICAgICAgbW9udGggPSBtb250aEluZGV4ICsgMTtcbiAgICAgICAgfSBlbHNlIGlmKG1vbnRoSW5kZXggPCBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgICAgICBtb250aCA9IG1vbnRoSW5kZXggKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9udGggPSBtb250aEluZGV4O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1vbnRoO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSBpbnRlcmNhbGFyeSBtb250aCBvZiBhIHllYXIgKGlmIGFueSkuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBpbnRlcmNhbGFyeSBtb250aCBudW1iZXIsIG9yIDAgaWYgbm9uZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBpbnRlcmNhbGFyeU1vbnRoOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHllYXIgPSB0aGlzLl92YWxpZGF0ZVllYXIoeWVhcik7XG5cbiAgICAgICAgdmFyIG1vbnRoRGF5c1RhYmxlID0gTFVOQVJfTU9OVEhfREFZU1t5ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG4gICAgICAgIHZhciBpbnRlcmNhbGFyeU1vbnRoID0gbW9udGhEYXlzVGFibGUgPj4gMTM7XG5cbiAgICAgICAgcmV0dXJuIGludGVyY2FsYXJ5TW9udGg7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYW4gaW50ZXJjYWxhcnkgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGFuIGludGVyY2FsYXJ5IG1vbnRoLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGlzSW50ZXJjYWxhcnlNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSB0aGlzLmludGVyY2FsYXJ5TW9udGgoeWVhcik7XG5cbiAgICAgICAgcmV0dXJuICEhaW50ZXJjYWxhcnlNb250aCAmJiBpbnRlcmNhbGFyeU1vbnRoID09PSBtb250aEluZGV4O1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gKHRoaXMuaW50ZXJjYWxhcnlNb250aCh5ZWFyKSAhPT0gMCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aEluZGV4XSB7bnVtYmVyfSBUaGUgbW9udGggaW5kZXggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aEluZGV4LCBkYXkpIHtcbiAgICAgICAgLy8gY29tcHV0ZSBDaGluZXNlIG5ldyB5ZWFyXG4gICAgICAgIHZhciB2YWxpZGF0ZWRZZWFyID1cbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlWWVhcih5ZWFyLCBtYWluLmxvY2FsLmludmFsaWR5ZWFyKTtcbiAgICAgICAgdmFyIHBhY2tlZERhdGUgPVxuICAgICAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUlt2YWxpZGF0ZWRZZWFyIC0gQ0hJTkVTRV9ORVdfWUVBUlswXV07XG5cbiAgICAgICAgdmFyIHkgPSAocGFja2VkRGF0ZSA+PiA5KSAmIDB4RkZGO1xuICAgICAgICB2YXIgbSA9IChwYWNrZWREYXRlID4+IDUpICYgMHgwRjtcbiAgICAgICAgdmFyIGQgPSBwYWNrZWREYXRlICYgMHgxRjtcbiAgICAgICAgXG4gICAgICAgIC8vIGZpbmQgZmlyc3QgVGhydXNkYXkgb2YgdGhlIHllYXJcbiAgICAgICAgdmFyIGZpcnN0VGh1cnNkYXk7XG4gICAgICAgIGZpcnN0VGh1cnNkYXkgPSBncmVnb3JpYW5DYWxlbmRhci5uZXdEYXRlKHksIG0sIGQpO1xuICAgICAgICBmaXJzdFRodXJzZGF5LmFkZCg0IC0gKGZpcnN0VGh1cnNkYXkuZGF5T2ZXZWVrKCkgfHwgNyksICdkJyk7XG5cbiAgICAgICAgLy8gY29tcHV0ZSBkYXlzIGZyb20gZmlyc3QgVGh1cnNkYXlcbiAgICAgICAgdmFyIG9mZnNldCA9XG4gICAgICAgICAgICB0aGlzLnRvSkQoeWVhciwgbW9udGhJbmRleCwgZGF5KSAtIGZpcnN0VGh1cnNkYXkudG9KRCgpO1xuICAgICAgICByZXR1cm4gMSArIE1hdGguZmxvb3Iob2Zmc2V0IC8gNyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIG1vbnRocyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gKHRoaXMubGVhcFllYXIoeWVhcikpID8gMTMgOiAxMjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICAgICAgeWVhciA9IHllYXIueWVhcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgeWVhciA9IHRoaXMuX3ZhbGlkYXRlWWVhcih5ZWFyKTtcblxuICAgICAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW3llYXIgLSBMVU5BUl9NT05USF9EQVlTWzBdXTtcblxuICAgICAgICB2YXIgaW50ZXJjYWxhcnlNb250aCA9IG1vbnRoRGF5c1RhYmxlID4+IDEzO1xuICAgICAgICB2YXIgbWF4TW9udGhJbmRleCA9IChpbnRlcmNhbGFyeU1vbnRoKSA/IDEyIDogMTE7XG4gICAgICAgIGlmIChtb250aEluZGV4ID4gbWF4TW9udGhJbmRleCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGhcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMubG9jYWwubmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF5c0luTW9udGggPSAobW9udGhEYXlzVGFibGUgJiAoMSA8PCAoMTIgLSBtb250aEluZGV4KSkpID9cbiAgICAgICAgICAgIDMwIDogMjk7XG5cbiAgICAgICAgcmV0dXJuIGRheXNJbk1vbnRoO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoSW5kZXgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoSW5kZXgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoSW5kZXgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgbW9udGhJbmRleCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcblxuICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeSA9IHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuICAgICAgICB2YXIgbW9udGggPSB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgIHZhciBzb2xhciA9IHRvU29sYXIoeWVhciwgbW9udGgsIGRheSwgaXNJbnRlcmNhbGFyeSk7XG5cbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLnRvSkQoc29sYXIueWVhciwgc29sYXIubW9udGgsIHNvbGFyLmRheSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBkYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIGx1bmFyID0gdG9MdW5hcihkYXRlLnllYXIoKSwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICAgICAgdmFyIG1vbnRoSW5kZXggPSB0aGlzLnRvTW9udGhJbmRleChcbiAgICAgICAgICAgIGx1bmFyLnllYXIsIGx1bmFyLm1vbnRoLCBsdW5hci5pc0ludGVyY2FsYXJ5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZShsdW5hci55ZWFyLCBtb250aEluZGV4LCBsdW5hci5kYXkpO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIHN0cmluZy5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZVN0cmluZyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50aW5nIGEgQ2hpbmVzZSBkYXRlXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgbmV3IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIGZyb21TdHJpbmc6IGZ1bmN0aW9uKGRhdGVTdHJpbmcpIHtcbiAgICAgICAgdmFyIG1hdGNoID0gZGF0ZVN0cmluZy5tYXRjaChEQVRFX1JFR0VYUCk7XG5cbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl92YWxpZGF0ZVllYXIoK21hdGNoWzFdKTtcblxuICAgICAgICB2YXIgbW9udGggPSArbWF0Y2hbMl07XG4gICAgICAgIHZhciBpc0ludGVyY2FsYXJ5ID0gISFtYXRjaFszXTtcbiAgICAgICAgdmFyIG1vbnRoSW5kZXggPSB0aGlzLnRvTW9udGhJbmRleCh5ZWFyLCBtb250aCwgaXNJbnRlcmNhbGFyeSk7XG5cbiAgICAgICAgdmFyIGRheSA9ICttYXRjaFs0XTtcblxuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoSW5kZXgsIGRheSk7XG4gICAgfSxcblxuICAgIC8qKiBBZGQgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgQ2F0ZXIgZm9yIG5vIHllYXIgemVyby5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZSB7Q0RhdGV9IFRoZSBzdGFydGluZyBkYXRlLlxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBhZGQ6IGZ1bmN0aW9uKGRhdGUsIG9mZnNldCwgcGVyaW9kKSB7XG4gICAgICAgIHZhciB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeSA9IHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuICAgICAgICB2YXIgbW9udGggPSB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgIHZhciBjZGF0ZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihDaGluZXNlQ2FsZW5kYXIucHJvdG90eXBlKVxuICAgICAgICAgICAgLmFkZC5jYWxsKHRoaXMsIGRhdGUsIG9mZnNldCwgcGVyaW9kKTtcblxuICAgICAgICBpZiAocGVyaW9kID09PSAneScpIHtcbiAgICAgICAgICAgIC8vIFJlc3luYyBtb250aFxuICAgICAgICAgICAgdmFyIHJlc3VsdFllYXIgPSBjZGF0ZS55ZWFyKCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0TW9udGhJbmRleCA9IGNkYXRlLm1vbnRoKCk7XG5cbiAgICAgICAgICAgIC8vIFVzaW5nIHRoZSBmYWN0IHRoZSBtb250aCBpbmRleCBvZiBhbiBpbnRlcmNhbGFyeSBtb250aFxuICAgICAgICAgICAgLy8gZXF1YWxzIGl0cyBtb250aCBudW1iZXI6XG4gICAgICAgICAgICB2YXIgcmVzdWx0Q2FuQmVJbnRlcmNhbGFyeU1vbnRoID1cbiAgICAgICAgICAgICAgICB0aGlzLmlzSW50ZXJjYWxhcnlNb250aChyZXN1bHRZZWFyLCBtb250aCk7XG5cbiAgICAgICAgICAgIHZhciBjb3JyZWN0ZWRNb250aEluZGV4ID1cbiAgICAgICAgICAgICAgICAoaXNJbnRlcmNhbGFyeSAmJiByZXN1bHRDYW5CZUludGVyY2FsYXJ5TW9udGgpID9cbiAgICAgICAgICAgICAgICB0aGlzLnRvTW9udGhJbmRleChyZXN1bHRZZWFyLCBtb250aCwgdHJ1ZSkgOlxuICAgICAgICAgICAgICAgIHRoaXMudG9Nb250aEluZGV4KHJlc3VsdFllYXIsIG1vbnRoLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIGlmIChjb3JyZWN0ZWRNb250aEluZGV4ICE9PSByZXN1bHRNb250aEluZGV4KSB7XG4gICAgICAgICAgICAgICAgY2RhdGUubW9udGgoY29ycmVjdGVkTW9udGhJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2RhdGU7XG4gICAgfSxcbn0pO1xuXG4vLyBVc2VkIGJ5IENoaW5lc2VDYWxlbmRhci5wcm90b3R5cGUuZnJvbVN0cmluZ1xudmFyIERBVEVfUkVHRVhQID0gL15cXHMqKC0/XFxkXFxkXFxkXFxkfFxcZFxcZClbLS9dKFxcZD9cXGQpKFtpSV0/KVstL10oXFxkP1xcZCkvbTtcbnZhciBNT05USF9OVU1CRVJfUkVHRVhQID0gL15cXGQ/XFxkW2lJXT8vbTtcbnZhciBNT05USF9OQU1FX1JFR0VYUCA9IC9e6ZewP+WNgT9b5LiA5LqM5LiJ5Zub5LqU5YWt5LiD5YWr5LmdXT/mnIgvbTtcbnZhciBNT05USF9TSE9SVF9OQU1FX1JFR0VYUCA9IC9e6ZewP+WNgT9b5LiA5LqM5LiJ5Zub5LqU5YWt5LiD5YWr5LmdXT8vbTtcblxuLy8gQ2hpbmVzZSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuY2hpbmVzZSA9IENoaW5lc2VDYWxlbmRhcjtcblxuLy8gQ2hpbmVzZSBjYWxlbmRhciB0YWJsZXMgZnJvbSB5ZWFyIDE4ODggdG8gMjExMVxuLy9cbi8vIFNvdXJjZTpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9pc2VlMTUvTHVuYXItU29sYXItQ2FsZW5kYXItQ29udmVydGVyLmdpdFxuXG4vLyBUYWJsZSBvZiBpbnRlcmNhbGFyeSBtb250aHMgYW5kIGRheXMgcGVyIG1vbnRoIGZyb20geWVhciAxODg4IHRvIDIxMTFcbi8vXG4vLyBiaXQgKDEyIC0gaSk6ICAgICAgICBkYXlzIGluIHRoZSBpXnRoIG1vbnRoXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAwIGlmIGledGggbHVuYXIgbW9udGggaGFzIDI5IGRheXMpXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAxIGlmIGledGggbHVuYXIgbW9udGggaGFzIDMwIGRheXMpXG4vLyAgICAgICAgICAgICAgICAgICAgICAoZmlyc3QgbW9udGggaW4gbHVuYXIgeWVhciBpcyBpID0gMClcbi8vIGJpdHMgKDEzLDE0LDE1LDE2KTogIGludGVyY2FsYXJ5IG1vbnRoXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAwIGlmIGx1bmFyIHllYXIgaGFzIG5vIGludGVyY2FsYXJ5IG1vbnRoKVxudmFyIExVTkFSX01PTlRIX0RBWVMgPSBbMTg4NywgMHgxNjk0LCAweDE2YWEsIDB4NGFkNSxcbiAgICAweGFiNiwgMHhjNGI3LCAweDRhZSwgMHhhNTYsIDB4YjUyYSwgMHgxZDJhLCAweGQ1NCwgMHg3NWFhLCAweDE1NmEsXG4gICAgMHgxMDk2ZCwgMHg5NWMsIDB4MTRhZSwgMHhhYTRkLCAweDFhNGMsIDB4MWIyYSwgMHg4ZDU1LCAweGFkNCxcbiAgICAweDEzNWEsIDB4NDk1ZCwgMHg5NWMsIDB4ZDQ5YiwgMHgxNDlhLCAweDFhNGEsIDB4YmFhNSwgMHgxNmE4LFxuICAgIDB4MWFkNCwgMHg1MmRhLCAweDEyYjYsIDB4ZTkzNywgMHg5MmUsIDB4MTQ5NiwgMHhiNjRiLCAweGQ0YSxcbiAgICAweGRhOCwgMHg5NWI1LCAweDU2YywgMHgxMmFlLCAweDQ5MmYsIDB4OTJlLCAweGNjOTYsIDB4MWE5NCxcbiAgICAweDFkNGEsIDB4YWRhOSwgMHhiNWEsIDB4NTZjLCAweDcyNmUsIDB4MTI1YywgMHhmOTJkLCAweDE5MmEsXG4gICAgMHgxYTk0LCAweGRiNGEsIDB4MTZhYSwgMHhhZDQsIDB4OTU1YiwgMHg0YmEsIDB4MTI1YSwgMHg1OTJiLFxuICAgIDB4MTUyYSwgMHhmNjk1LCAweGQ5NCwgMHgxNmFhLCAweGFhYjUsIDB4OWI0LCAweDE0YjYsIDB4NmE1NyxcbiAgICAweGE1NiwgMHgxMTUyYSwgMHgxZDJhLCAweGQ1NCwgMHhkNWFhLCAweDE1NmEsIDB4OTZjLCAweDk0YWUsXG4gICAgMHgxNGFlLCAweGE0YywgMHg3ZDI2LCAweDFiMmEsIDB4ZWI1NSwgMHhhZDQsIDB4MTJkYSwgMHhhOTVkLFxuICAgIDB4OTVhLCAweDE0OWEsIDB4OWE0ZCwgMHgxYTRhLCAweDExYWE1LCAweDE2YTgsIDB4MTZkNCwgMHhkMmRhLFxuICAgIDB4MTJiNiwgMHg5MzYsIDB4OTQ5NywgMHgxNDk2LCAweDE1NjRiLCAweGQ0YSwgMHhkYTgsIDB4ZDViNCxcbiAgICAweDE1NmMsIDB4MTJhZSwgMHhhOTJmLCAweDkyZSwgMHhjOTYsIDB4NmQ0YSwgMHgxZDRhLCAweDEwZDY1LFxuICAgIDB4YjU4LCAweDE1NmMsIDB4YjI2ZCwgMHgxMjVjLCAweDE5MmMsIDB4OWE5NSwgMHgxYTk0LCAweDFiNGEsXG4gICAgMHg0YjU1LCAweGFkNCwgMHhmNTViLCAweDRiYSwgMHgxMjVhLCAweGI5MmIsIDB4MTUyYSwgMHgxNjk0LFxuICAgIDB4OTZhYSwgMHgxNWFhLCAweDEyYWI1LCAweDk3NCwgMHgxNGI2LCAweGNhNTcsIDB4YTU2LCAweDE1MjYsXG4gICAgMHg4ZTk1LCAweGQ1NCwgMHgxNWFhLCAweDQ5YjUsIDB4OTZjLCAweGQ0YWUsIDB4MTQ5YywgMHgxYTRjLFxuICAgIDB4YmQyNiwgMHgxYWE2LCAweGI1NCwgMHg2ZDZhLCAweDEyZGEsIDB4MTY5NWQsIDB4OTVhLCAweDE0OWEsXG4gICAgMHhkYTRiLCAweDFhNGEsIDB4MWFhNCwgMHhiYjU0LCAweDE2YjQsIDB4YWRhLCAweDQ5NWIsIDB4OTM2LFxuICAgIDB4ZjQ5NywgMHgxNDk2LCAweDE1NGEsIDB4YjZhNSwgMHhkYTQsIDB4MTViNCwgMHg2YWI2LCAweDEyNmUsXG4gICAgMHgxMDkyZiwgMHg5MmUsIDB4Yzk2LCAweGNkNGEsIDB4MWQ0YSwgMHhkNjQsIDB4OTU2YywgMHgxNTVjLFxuICAgIDB4MTI1YywgMHg3OTJlLCAweDE5MmMsIDB4ZmE5NSwgMHgxYTk0LCAweDFiNGEsIDB4YWI1NSwgMHhhZDQsXG4gICAgMHgxNGRhLCAweDhhNWQsIDB4YTVhLCAweDExNTJiLCAweDE1MmEsIDB4MTY5NCwgMHhkNmFhLCAweDE1YWEsXG4gICAgMHhhYjQsIDB4OTRiYSwgMHgxNGI2LCAweGE1NiwgMHg3NTI3LCAweGQyNiwgMHhlZTUzLCAweGQ1NCwgMHgxNWFhLFxuICAgIDB4YTliNSwgMHg5NmMsIDB4MTRhZSwgMHg4YTRlLCAweDFhNGMsIDB4MTFkMjYsIDB4MWFhNCwgMHgxYjU0LFxuICAgIDB4Y2Q2YSwgMHhhZGEsIDB4OTVjLCAweDk0OWQsIDB4MTQ5YSwgMHgxYTJhLCAweDViMjUsIDB4MWFhNCxcbiAgICAweGZiNTIsIDB4MTZiNCwgMHhhYmEsIDB4YTk1YiwgMHg5MzYsIDB4MTQ5NiwgMHg5YTRiLCAweDE1NGEsXG4gICAgMHgxMzZhNSwgMHhkYTQsIDB4MTVhY107XG5cbi8vIFRhYmxlIG9mIENoaW5lc2UgTmV3IFllYXJzIGZyb20geWVhciAxODg4IHRvIDIxMTFcbi8vIFxuLy8gYml0cyAoMCB0byA0KTogICBzb2xhciBkYXlcbi8vIGJpdHMgKDUgdG8gOCk6ICAgc29sYXIgbW9udGhcbi8vIGJpdHMgKDkgdG8gMjApOiAgc29sYXIgeWVhclxudmFyIENISU5FU0VfTkVXX1lFQVIgPSBbMTg4NywgMHhlYzA0YywgMHhlYzIzZiwgMHhlYzQzNSwgMHhlYzY0OSxcbiAgICAweGVjODNlLCAweGVjYTUxLCAweGVjYzQ2LCAweGVjZTNhLCAweGVkMDRkLCAweGVkMjQyLCAweGVkNDM2LFxuICAgIDB4ZWQ2NGEsIDB4ZWQ4M2YsIDB4ZWRhNTMsIDB4ZWRjNDgsIDB4ZWRlM2QsIDB4ZWUwNTAsIDB4ZWUyNDQsXG4gICAgMHhlZTQzOSwgMHhlZTY0ZCwgMHhlZTg0MiwgMHhlZWEzNiwgMHhlZWM0YSwgMHhlZWUzZSwgMHhlZjA1MixcbiAgICAweGVmMjQ2LCAweGVmNDNhLCAweGVmNjRlLCAweGVmODQzLCAweGVmYTM3LCAweGVmYzRiLCAweGVmZTQxLFxuICAgIDB4ZjAwNTQsIDB4ZjAyNDgsIDB4ZjA0M2MsIDB4ZjA2NTAsIDB4ZjA4NDUsIDB4ZjBhMzgsIDB4ZjBjNGQsXG4gICAgMHhmMGU0MiwgMHhmMTAzNywgMHhmMTI0YSwgMHhmMTQzZSwgMHhmMTY1MSwgMHhmMTg0NiwgMHhmMWEzYSxcbiAgICAweGYxYzRlLCAweGYxZTQ0LCAweGYyMDM4LCAweGYyMjRiLCAweGYyNDNmLCAweGYyNjUzLCAweGYyODQ4LFxuICAgIDB4ZjJhM2IsIDB4ZjJjNGYsIDB4ZjJlNDUsIDB4ZjMwMzksIDB4ZjMyNGQsIDB4ZjM0NDIsIDB4ZjM2MzYsXG4gICAgMHhmMzg0YSwgMHhmM2EzZCwgMHhmM2M1MSwgMHhmM2U0NiwgMHhmNDAzYiwgMHhmNDI0ZSwgMHhmNDQ0MyxcbiAgICAweGY0NjM4LCAweGY0ODRjLCAweGY0YTNmLCAweGY0YzUyLCAweGY0ZTQ4LCAweGY1MDNjLCAweGY1MjRmLFxuICAgIDB4ZjU0NDUsIDB4ZjU2MzksIDB4ZjU4NGQsIDB4ZjVhNDIsIDB4ZjVjMzUsIDB4ZjVlNDksIDB4ZjYwM2UsXG4gICAgMHhmNjI1MSwgMHhmNjQ0NiwgMHhmNjYzYiwgMHhmNjg0ZiwgMHhmNmE0MywgMHhmNmMzNywgMHhmNmU0YixcbiAgICAweGY3MDNmLCAweGY3MjUyLCAweGY3NDQ3LCAweGY3NjNjLCAweGY3ODUwLCAweGY3YTQ1LCAweGY3YzM5LFxuICAgIDB4ZjdlNGQsIDB4ZjgwNDIsIDB4ZjgyNTQsIDB4Zjg0NDksIDB4Zjg2M2QsIDB4Zjg4NTEsIDB4ZjhhNDYsXG4gICAgMHhmOGMzYiwgMHhmOGU0ZiwgMHhmOTA0NCwgMHhmOTIzNywgMHhmOTQ0YSwgMHhmOTYzZiwgMHhmOTg1MyxcbiAgICAweGY5YTQ3LCAweGY5YzNjLCAweGY5ZTUwLCAweGZhMDQ1LCAweGZhMjM4LCAweGZhNDRjLCAweGZhNjQxLFxuICAgIDB4ZmE4MzYsIDB4ZmFhNDksIDB4ZmFjM2QsIDB4ZmFlNTIsIDB4ZmIwNDcsIDB4ZmIyM2EsIDB4ZmI0NGUsXG4gICAgMHhmYjY0MywgMHhmYjgzNywgMHhmYmE0YSwgMHhmYmMzZiwgMHhmYmU1MywgMHhmYzA0OCwgMHhmYzIzYyxcbiAgICAweGZjNDUwLCAweGZjNjQ1LCAweGZjODM5LCAweGZjYTRjLCAweGZjYzQxLCAweGZjZTM2LCAweGZkMDRhLFxuICAgIDB4ZmQyM2QsIDB4ZmQ0NTEsIDB4ZmQ2NDYsIDB4ZmQ4M2EsIDB4ZmRhNGQsIDB4ZmRjNDMsIDB4ZmRlMzcsXG4gICAgMHhmZTA0YiwgMHhmZTIzZiwgMHhmZTQ1MywgMHhmZTY0OCwgMHhmZTgzYywgMHhmZWE0ZiwgMHhmZWM0NCxcbiAgICAweGZlZTM4LCAweGZmMDRjLCAweGZmMjQxLCAweGZmNDM2LCAweGZmNjRhLCAweGZmODNlLCAweGZmYTUxLFxuICAgIDB4ZmZjNDYsIDB4ZmZlM2EsIDB4MTAwMDRlLCAweDEwMDI0MiwgMHgxMDA0MzcsIDB4MTAwNjRiLCAweDEwMDg0MSxcbiAgICAweDEwMGE1MywgMHgxMDBjNDgsIDB4MTAwZTNjLCAweDEwMTA0ZiwgMHgxMDEyNDQsIDB4MTAxNDM4LFxuICAgIDB4MTAxNjRjLCAweDEwMTg0MiwgMHgxMDFhMzUsIDB4MTAxYzQ5LCAweDEwMWUzZCwgMHgxMDIwNTEsXG4gICAgMHgxMDIyNDUsIDB4MTAyNDNhLCAweDEwMjY0ZSwgMHgxMDI4NDMsIDB4MTAyYTM3LCAweDEwMmM0YixcbiAgICAweDEwMmUzZiwgMHgxMDMwNTMsIDB4MTAzMjQ3LCAweDEwMzQzYiwgMHgxMDM2NGYsIDB4MTAzODQ1LFxuICAgIDB4MTAzYTM4LCAweDEwM2M0YywgMHgxMDNlNDIsIDB4MTA0MDM2LCAweDEwNDI0OSwgMHgxMDQ0M2QsXG4gICAgMHgxMDQ2NTEsIDB4MTA0ODQ2LCAweDEwNGEzYSwgMHgxMDRjNGUsIDB4MTA0ZTQzLCAweDEwNTAzOCxcbiAgICAweDEwNTI0YSwgMHgxMDU0M2UsIDB4MTA1NjUyLCAweDEwNTg0NywgMHgxMDVhM2IsIDB4MTA1YzRmLFxuICAgIDB4MTA1ZTQ1LCAweDEwNjAzOSwgMHgxMDYyNGMsIDB4MTA2NDQxLCAweDEwNjYzNSwgMHgxMDY4NDksXG4gICAgMHgxMDZhM2QsIDB4MTA2YzUxLCAweDEwNmU0NywgMHgxMDcwM2MsIDB4MTA3MjRmLCAweDEwNzQ0NCxcbiAgICAweDEwNzYzOCwgMHgxMDc4NGMsIDB4MTA3YTNmLCAweDEwN2M1MywgMHgxMDdlNDhdO1xuXG5mdW5jdGlvbiB0b0x1bmFyKHllYXJPckRhdGUsIG1vbnRoT3JSZXN1bHQsIGRheSwgcmVzdWx0KSB7XG4gICAgdmFyIHNvbGFyRGF0ZTtcbiAgICB2YXIgbHVuYXJEYXRlO1xuXG4gICAgaWYodHlwZW9mIHllYXJPckRhdGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHNvbGFyRGF0ZSA9IHllYXJPckRhdGU7XG4gICAgICAgIGx1bmFyRGF0ZSA9IG1vbnRoT3JSZXN1bHQgfHwge307XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaXNWYWxpZFllYXIgPSAodHlwZW9mIHllYXJPckRhdGUgPT09ICdudW1iZXInKSAmJlxuICAgICAgICAgICAgKHllYXJPckRhdGUgPj0gMTg4OCkgJiYgKHllYXJPckRhdGUgPD0gMjExMSk7XG4gICAgICAgIGlmKCFpc1ZhbGlkWWVhcilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbGFyIHllYXIgb3V0c2lkZSByYW5nZSAxODg4LTIxMTFcIik7XG5cbiAgICAgICAgdmFyIGlzVmFsaWRNb250aCA9ICh0eXBlb2YgbW9udGhPclJlc3VsdCA9PT0gJ251bWJlcicpICYmXG4gICAgICAgICAgICAobW9udGhPclJlc3VsdCA+PSAxKSAmJiAobW9udGhPclJlc3VsdCA8PSAxMik7XG4gICAgICAgIGlmKCFpc1ZhbGlkTW9udGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb2xhciBtb250aCBvdXRzaWRlIHJhbmdlIDEgLSAxMlwiKTtcblxuICAgICAgICB2YXIgaXNWYWxpZERheSA9ICh0eXBlb2YgZGF5ID09PSAnbnVtYmVyJykgJiYgKGRheSA+PSAxKSAmJiAoZGF5IDw9IDMxKTtcbiAgICAgICAgaWYoIWlzVmFsaWREYXkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb2xhciBkYXkgb3V0c2lkZSByYW5nZSAxIC0gMzFcIik7XG5cbiAgICAgICAgc29sYXJEYXRlID0ge1xuICAgICAgICAgICAgeWVhcjogeWVhck9yRGF0ZSxcbiAgICAgICAgICAgIG1vbnRoOiBtb250aE9yUmVzdWx0LFxuICAgICAgICAgICAgZGF5OiBkYXksXG4gICAgICAgIH07XG4gICAgICAgIGx1bmFyRGF0ZSA9IHJlc3VsdCB8fCB7fTtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIENoaW5lc2UgbmV3IHllYXIgYW5kIGx1bmFyIHllYXJcbiAgICB2YXIgY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID1cbiAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUltzb2xhckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHBhY2tlZERhdGUgPSAoc29sYXJEYXRlLnllYXIgPDwgOSkgfCAoc29sYXJEYXRlLm1vbnRoIDw8IDUpXG4gICAgICAgIHwgc29sYXJEYXRlLmRheTtcblxuICAgIGx1bmFyRGF0ZS55ZWFyID0gKHBhY2tlZERhdGUgPj0gY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlKSA/XG4gICAgICAgIHNvbGFyRGF0ZS55ZWFyIDpcbiAgICAgICAgc29sYXJEYXRlLnllYXIgLSAxO1xuXG4gICAgY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID1cbiAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUltsdW5hckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHkgPSAoY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID4+IDkpICYgMHhGRkY7XG4gICAgdmFyIG0gPSAoY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID4+IDUpICYgMHgwRjtcbiAgICB2YXIgZCA9IGNoaW5lc2VOZXdZZWFyUGFja2VkRGF0ZSAmIDB4MUY7XG5cbiAgICAvLyBDb21wdXRlIGRheXMgZnJvbSBuZXcgeWVhclxuICAgIHZhciBkYXlzRnJvbU5ld1llYXI7XG5cbiAgICB2YXIgY2hpbmVzZU5ld1llYXJKU0RhdGUgPSBuZXcgRGF0ZSh5LCBtIC0xLCBkKTtcbiAgICB2YXIganNEYXRlID0gbmV3IERhdGUoc29sYXJEYXRlLnllYXIsIHNvbGFyRGF0ZS5tb250aCAtIDEsIHNvbGFyRGF0ZS5kYXkpO1xuXG4gICAgZGF5c0Zyb21OZXdZZWFyID0gTWF0aC5yb3VuZChcbiAgICAgICAgKGpzRGF0ZSAtIGNoaW5lc2VOZXdZZWFySlNEYXRlKSAvICgyNCAqIDM2MDAgKiAxMDAwKSk7XG5cbiAgICAvLyBDb21wdXRlIGx1bmFyIG1vbnRoIGFuZCBkYXlcbiAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW2x1bmFyRGF0ZS55ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG5cbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDA7IGkgPCAxMzsgaSsrKSB7XG4gICAgICAgIHZhciBkYXlzSW5Nb250aCA9IChtb250aERheXNUYWJsZSAmICgxIDw8ICgxMiAtIGkpKSkgPyAzMCA6IDI5O1xuXG4gICAgICAgIGlmIChkYXlzRnJvbU5ld1llYXIgPCBkYXlzSW5Nb250aCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBkYXlzRnJvbU5ld1llYXIgLT0gZGF5c0luTW9udGg7XG4gICAgfVxuXG4gICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSBtb250aERheXNUYWJsZSA+PiAxMztcbiAgICBpZiAoIWludGVyY2FsYXJ5TW9udGggfHwgaSA8IGludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgbHVuYXJEYXRlLmlzSW50ZXJjYWxhcnkgPSBmYWxzZTtcbiAgICAgICAgbHVuYXJEYXRlLm1vbnRoID0gMSArIGk7XG4gICAgfSBlbHNlIGlmIChpID09PSBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgIGx1bmFyRGF0ZS5pc0ludGVyY2FsYXJ5ID0gdHJ1ZTtcbiAgICAgICAgbHVuYXJEYXRlLm1vbnRoID0gaTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsdW5hckRhdGUuaXNJbnRlcmNhbGFyeSA9IGZhbHNlO1xuICAgICAgICBsdW5hckRhdGUubW9udGggPSBpO1xuICAgIH1cblxuICAgIGx1bmFyRGF0ZS5kYXkgPSAxICsgZGF5c0Zyb21OZXdZZWFyO1xuXG4gICAgcmV0dXJuIGx1bmFyRGF0ZTtcbn1cblxuZnVuY3Rpb24gdG9Tb2xhcih5ZWFyT3JEYXRlLCBtb250aE9yUmVzdWx0LCBkYXksIGlzSW50ZXJjYWxhcnlPclJlc3VsdCwgcmVzdWx0KSB7XG4gICAgdmFyIHNvbGFyRGF0ZTtcbiAgICB2YXIgbHVuYXJEYXRlO1xuXG4gICAgaWYodHlwZW9mIHllYXJPckRhdGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGx1bmFyRGF0ZSA9IHllYXJPckRhdGU7XG4gICAgICAgIHNvbGFyRGF0ZSA9IG1vbnRoT3JSZXN1bHQgfHwge307XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaXNWYWxpZFllYXIgPSAodHlwZW9mIHllYXJPckRhdGUgPT09ICdudW1iZXInKSAmJlxuICAgICAgICAgICAgKHllYXJPckRhdGUgPj0gMTg4OCkgJiYgKHllYXJPckRhdGUgPD0gMjExMSk7XG4gICAgICAgIGlmKCFpc1ZhbGlkWWVhcilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkx1bmFyIHllYXIgb3V0c2lkZSByYW5nZSAxODg4LTIxMTFcIik7XG5cbiAgICAgICAgdmFyIGlzVmFsaWRNb250aCA9ICh0eXBlb2YgbW9udGhPclJlc3VsdCA9PT0gJ251bWJlcicpICYmXG4gICAgICAgICAgICAobW9udGhPclJlc3VsdCA+PSAxKSAmJiAobW9udGhPclJlc3VsdCA8PSAxMik7XG4gICAgICAgIGlmKCFpc1ZhbGlkTW9udGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMdW5hciBtb250aCBvdXRzaWRlIHJhbmdlIDEgLSAxMlwiKTtcblxuICAgICAgICB2YXIgaXNWYWxpZERheSA9ICh0eXBlb2YgZGF5ID09PSAnbnVtYmVyJykgJiYgKGRheSA+PSAxKSAmJiAoZGF5IDw9IDMwKTtcbiAgICAgICAgaWYoIWlzVmFsaWREYXkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMdW5hciBkYXkgb3V0c2lkZSByYW5nZSAxIC0gMzBcIik7XG5cbiAgICAgICAgdmFyIGlzSW50ZXJjYWxhcnk7XG4gICAgICAgIGlmKHR5cGVvZiBpc0ludGVyY2FsYXJ5T3JSZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpc0ludGVyY2FsYXJ5ID0gZmFsc2U7XG4gICAgICAgICAgICBzb2xhckRhdGUgPSBpc0ludGVyY2FsYXJ5T3JSZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc0ludGVyY2FsYXJ5ID0gISFpc0ludGVyY2FsYXJ5T3JSZXN1bHQ7XG4gICAgICAgICAgICBzb2xhckRhdGUgPSByZXN1bHQgfHwge307XG4gICAgICAgIH1cblxuICAgICAgICBsdW5hckRhdGUgPSB7XG4gICAgICAgICAgICB5ZWFyOiB5ZWFyT3JEYXRlLFxuICAgICAgICAgICAgbW9udGg6IG1vbnRoT3JSZXN1bHQsXG4gICAgICAgICAgICBkYXk6IGRheSxcbiAgICAgICAgICAgIGlzSW50ZXJjYWxhcnk6IGlzSW50ZXJjYWxhcnksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBkYXlzIGZyb20gbmV3IHllYXJcbiAgICB2YXIgZGF5c0Zyb21OZXdZZWFyO1xuXG4gICAgZGF5c0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLmRheSAtIDE7XG5cbiAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW2x1bmFyRGF0ZS55ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG4gICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSBtb250aERheXNUYWJsZSA+PiAxMztcblxuICAgIHZhciBtb250aHNGcm9tTmV3WWVhcjtcbiAgICBpZiAoIWludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgbW9udGhzRnJvbU5ld1llYXIgPSBsdW5hckRhdGUubW9udGggLSAxO1xuICAgIH0gZWxzZSBpZiAobHVuYXJEYXRlLm1vbnRoID4gaW50ZXJjYWxhcnlNb250aCkge1xuICAgICAgICBtb250aHNGcm9tTmV3WWVhciA9IGx1bmFyRGF0ZS5tb250aDtcbiAgICB9IGVsc2UgaWYgKGx1bmFyRGF0ZS5pc0ludGVyY2FsYXJ5KSB7XG4gICAgICAgIG1vbnRoc0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLm1vbnRoO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1vbnRoc0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLm1vbnRoIC0gMTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbW9udGhzRnJvbU5ld1llYXI7IGkrKykge1xuICAgICAgICB2YXIgZGF5c0luTW9udGggPSAobW9udGhEYXlzVGFibGUgJiAoMSA8PCAoMTIgLSBpKSkpID8gMzAgOiAyOTtcbiAgICAgICAgZGF5c0Zyb21OZXdZZWFyICs9IGRheXNJbk1vbnRoO1xuICAgIH1cblxuICAgIC8vIENvbXB1dGUgQ2hpbmVzZSBuZXcgeWVhclxuICAgIHZhciBwYWNrZWREYXRlID0gQ0hJTkVTRV9ORVdfWUVBUltsdW5hckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHkgPSAocGFja2VkRGF0ZSA+PiA5KSAmIDB4RkZGO1xuICAgIHZhciBtID0gKHBhY2tlZERhdGUgPj4gNSkgJiAweDBGO1xuICAgIHZhciBkID0gcGFja2VkRGF0ZSAmIDB4MUY7XG5cbiAgICAvLyBDb21wdXRlIHNvbGFyIGRhdGVcbiAgICB2YXIganNEYXRlID0gbmV3IERhdGUoeSwgbSAtIDEsIGQgKyBkYXlzRnJvbU5ld1llYXIpO1xuXG4gICAgc29sYXJEYXRlLnllYXIgPSBqc0RhdGUuZ2V0RnVsbFllYXIoKTtcbiAgICBzb2xhckRhdGUubW9udGggPSAxICsganNEYXRlLmdldE1vbnRoKCk7XG4gICAgc29sYXJEYXRlLmRheSA9IGpzRGF0ZS5nZXREYXRlKCk7XG5cbiAgICByZXR1cm4gc29sYXJEYXRlO1xufVxuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIENvcHRpYyBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEZlYnJ1YXJ5IDIwMTAuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gcmVxdWlyZSgnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IHJlcXVpcmUoJ29iamVjdC1hc3NpZ24nKTtcblxuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIENvcHRpYyBjYWxlbmRhci5cbiAgICBTZWUgPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29wdGljX2NhbGVuZGFyXCI+aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db3B0aWNfY2FsZW5kYXI8L2E+LlxuICAgIFNlZSBhbHNvIENhbGVuZHJpY2FsIENhbGN1bGF0aW9uczogVGhlIE1pbGxlbm5pdW0gRWRpdGlvblxuICAgICg8YSBocmVmPVwiaHR0cDovL2Vtci5jcy5paXQuZWR1L2hvbWUvcmVpbmdvbGQvY2FsZW5kYXItYm9vay9pbmRleC5zaHRtbFwiPmh0dHA6Ly9lbXIuY3MuaWl0LmVkdS9ob21lL3JlaW5nb2xkL2NhbGVuZGFyLWJvb2svaW5kZXguc2h0bWw8L2E+KS5cbiAgICBAY2xhc3MgQ29wdGljQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gQ29wdGljQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuQ29wdGljQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IG1haW4uYmFzZUNhbGVuZGFyO1xuXG5hc3NpZ24oQ29wdGljQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnQ29wdGljJyxcbiAgICAvKiogSnVsaWFuIGRhdGUgb2Ygc3RhcnQgb2YgQ29wdGljIGVwb2NoOiAyOSBBdWd1c3QgMjg0IENFIChHcmVnb3JpYW4pLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxODI1MDI5LjUsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDVdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdDb3B0aWMnLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JBTScsICdBTSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydUaG91dCcsICdQYW9waScsICdIYXRob3InLCAnS29pYWsnLCAnVG9iaScsICdNZXNoaXInLFxuICAgICAgICAgICAgJ1BhcmVtaGF0JywgJ1BhcmVtb3VkZScsICdQYXNob25zJywgJ1Bhb25pJywgJ0VwaXAnLCAnTWVzb3JpJywgJ1BpIEtvZ2kgRW5hdm90J10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnVGhvJywgJ1BhbycsICdIYXRoJywgJ0tvaScsICdUb2InLCAnTWVzaCcsXG4gICAgICAgICAgICAnUGF0JywgJ1BhZCcsICdQYXNoJywgJ1BhbycsICdFcGknLCAnTWVzbycsICdQaUsnXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1RreXJpYWthJywgJ1Blc25hdScsICdQc2hvbWVudCcsICdQZWZ0b291JywgJ1B0aW91JywgJ1Bzb291JywgJ1BzYWJiYXRvbiddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydUa3knLCAnUGVzJywgJ1BzaCcsICdQZWYnLCAnUHRpJywgJ1BzbycsICdQc2EnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1RrJywgJ1BlcycsICdQc2gnLCAnUGVmJywgJ1B0JywgJ1BzbycsICdQc2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdkZC9tbS95eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAwLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSBkYXRlLnllYXIoKSArIChkYXRlLnllYXIoKSA8IDAgPyAxIDogMCk7IC8vIE5vIHllYXIgemVyb1xuICAgICAgICByZXR1cm4geWVhciAlIDQgPT09IDMgfHwgeWVhciAlIDQgPT09IC0xO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBtb250aHMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIG1haW4ubG9jYWwuaW52YWxpZFllYXIgfHwgbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIDEzO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXIpIHRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdICtcbiAgICAgICAgICAgIChkYXRlLm1vbnRoKCkgPT09IDEzICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIGRheSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHx8IDcpIDwgNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyKSB0aGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgaWYgKHllYXIgPCAwKSB7IHllYXIrKzsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIGRhdGUuZGF5KCkgKyAoZGF0ZS5tb250aCgpIC0gMSkgKiAzMCArXG4gICAgICAgICAgICAoeWVhciAtIDEpICogMzY1ICsgTWF0aC5mbG9vcih5ZWFyIC8gNCkgKyB0aGlzLmpkRXBvY2ggLSAxO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBjID0gTWF0aC5mbG9vcihqZCkgKyAwLjUgLSB0aGlzLmpkRXBvY2g7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcigoYyAtIE1hdGguZmxvb3IoKGMgKyAzNjYpIC8gMTQ2MSkpIC8gMzY1KSArIDE7XG4gICAgICAgIGlmICh5ZWFyIDw9IDApIHsgeWVhci0tOyB9IC8vIE5vIHllYXIgemVyb1xuICAgICAgICBjID0gTWF0aC5mbG9vcihqZCkgKyAwLjUgLSB0aGlzLm5ld0RhdGUoeWVhciwgMSwgMSkudG9KRCgpO1xuICAgICAgICB2YXIgbW9udGggPSBNYXRoLmZsb29yKGMgLyAzMCkgKyAxO1xuICAgICAgICB2YXIgZGF5ID0gYyAtIChtb250aCAtIDEpICogMzAgKyAxO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH1cbn0pO1xuXG4vLyBDb3B0aWMgY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLmNvcHRpYyA9IENvcHRpY0NhbGVuZGFyO1xuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIERpc2N3b3JsZCBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEphbnVhcnkgMjAxNi5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSByZXF1aXJlKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgRGlzY3dvcmxkIGNhbGVuZGFyIC0gVW5zZWVuIFVuaXZlcnNpdHkgdmVyc2lvbi5cbiAgICBTZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL3dpa2kubHNwYWNlLm9yZy9tZWRpYXdpa2kvRGlzY3dvcmxkX2NhbGVuZGFyXCI+aHR0cDovL3dpa2kubHNwYWNlLm9yZy9tZWRpYXdpa2kvRGlzY3dvcmxkX2NhbGVuZGFyPC9hPlxuICAgIGFuZCA8YSBocmVmPVwiaHR0cDovL2Rpc2N3b3JsZC53aWtpYS5jb20vd2lraS9EaXNjd29ybGRfY2FsZW5kYXJcIj5odHRwOi8vZGlzY3dvcmxkLndpa2lhLmNvbS93aWtpL0Rpc2N3b3JsZF9jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIERpc2N3b3JsZENhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIERpc2N3b3JsZENhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbkRpc2N3b3JsZENhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKERpc2N3b3JsZENhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyICovXG4gICAgbmFtZTogJ0Rpc2N3b3JsZCcsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIERpc2N3b3JsZCBlcG9jaDogMSBKYW51YXJ5IDAwMDEgQ0UuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE3MjE0MjUuNSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyICovXG4gICAgZGF5c1Blck1vbnRoOiBbMTYsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzJdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdEaXNjd29ybGQnLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JVQycsICdVQyddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydJY2snLCAnT2ZmbGUnLCAnRmVicnVhcnknLCAnTWFyY2gnLCAnQXByaWwnLCAnTWF5JywgJ0p1bmUnLFxuICAgICAgICAgICAgJ0dydW5lJywgJ0F1Z3VzdCcsICdTcHVuZScsICdTZWt0b2JlcicsICdFbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0ljaycsICdPZmYnLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdHcnUnLCAnQXVnJywgJ1NwdScsICdTZWsnLCAnRW1iJywgJ0RlYyddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnU3VuZGF5JywgJ09jdGVkYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnT2N0JywgJ01vbicsICdUdWUnLCAnV2VkJywgJ1RodScsICdGcmknLCAnU2F0J10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydTdScsICdPYycsICdNbycsICdUdScsICdXZScsICdUaCcsICdGcicsICdTYSddLFxuICAgICAgICAgICAgZGlnaXRzOiBudWxsLFxuICAgICAgICAgICAgZGF0ZUZvcm1hdDogJ3l5eXkvbW0vZGQnLFxuICAgICAgICAgICAgZmlyc3REYXk6IDIsXG4gICAgICAgICAgICBpc1JUTDogZmFsc2VcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBtb250aHMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxMztcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gNDAwO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDgpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgd2Vlay5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLiAqL1xuICAgIGRheXNJbldlZWs6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gODtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBkYXkgb2YgdGhlIHdlZWsgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGRheSBvZiB0aGUgd2VlazogMCB0byBudW1iZXIgb2YgZGF5cyAtIDEuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5T2ZXZWVrOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiAoZGF0ZS5kYXkoKSArIDEpICUgODtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkb3cgPSB0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgcmV0dXJuIChkb3cgPj0gMiAmJiBkb3cgPD0gNik7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge29iamVjdH0gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiAtIGNvbnRlbnRzIGRlcGVuZHMgb24gY2FsZW5kYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZXh0cmFJbmZvOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiB7Y2VudHVyeTogY2VudHVyaWVzW01hdGguZmxvb3IoKGRhdGUueWVhcigpIC0gMSkgLyAxMDApICsgMV0gfHwgJyd9O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpICsgKGRhdGUueWVhcigpIDwgMCA/IDEgOiAwKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIHJldHVybiBkYXkgKyAobW9udGggPiAxID8gMTYgOiAwKSArIChtb250aCA+IDIgPyAobW9udGggLSAyKSAqIDMyIDogMCkgK1xuICAgICAgICAgICAgKHllYXIgLSAxKSAqIDQwMCArIHRoaXMuamRFcG9jaCAtIDE7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkICsgMC41KSAtIE1hdGguZmxvb3IodGhpcy5qZEVwb2NoKSAtIDE7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcihqZCAvIDQwMCkgKyAxO1xuICAgICAgICBqZCAtPSAoeWVhciAtIDEpICogNDAwO1xuICAgICAgICBqZCArPSAoamQgPiAxNSA/IDE2IDogMCk7XG4gICAgICAgIHZhciBtb250aCA9IE1hdGguZmxvb3IoamQgLyAzMikgKyAxO1xuICAgICAgICB2YXIgZGF5ID0gamQgLSAobW9udGggLSAxKSAqIDMyICsgMTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyIDw9IDAgPyB5ZWFyIC0gMSA6IHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH1cbn0pO1xuXG4vLyBOYW1lcyBvZiB0aGUgY2VudHVyaWVzXG52YXIgY2VudHVyaWVzID0ge1xuICAgIDIwOiAnRnJ1aXRiYXQnLFxuICAgIDIxOiAnQW5jaG92eSdcbn07XG5cbi8vIERpc2N3b3JsZCBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuZGlzY3dvcmxkID0gRGlzY3dvcmxkQ2FsZW5kYXI7XG5cbiIsIi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgRXRoaW9waWFuIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgRmVicnVhcnkgMjAxMC5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSByZXF1aXJlKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgRXRoaW9waWFuIGNhbGVuZGFyLlxuICAgIFNlZSA8YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FdGhpb3BpYW5fY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V0aGlvcGlhbl9jYWxlbmRhcjwvYT4uXG4gICAgU2VlIGFsc28gQ2FsZW5kcmljYWwgQ2FsY3VsYXRpb25zOiBUaGUgTWlsbGVubml1bSBFZGl0aW9uXG4gICAgKDxhIGhyZWY9XCJodHRwOi8vZW1yLmNzLmlpdC5lZHUvaG9tZS9yZWluZ29sZC9jYWxlbmRhci1ib29rL2luZGV4LnNodG1sXCI+aHR0cDovL2Vtci5jcy5paXQuZWR1L2hvbWUvcmVpbmdvbGQvY2FsZW5kYXItYm9vay9pbmRleC5zaHRtbDwvYT4pLlxuICAgIEBjbGFzcyBFdGhpb3BpYW5DYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBFdGhpb3BpYW5DYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5FdGhpb3BpYW5DYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihFdGhpb3BpYW5DYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIG5hbWU6ICdFdGhpb3BpYW4nLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBFdGhpb3BpYW4gZXBvY2g6IDI3IEF1Z3VzdCA4IENFIChHcmVnb3JpYW4pLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxNzI0MjIwLjUsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDVdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdFdGhpb3BpYW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JFRScsICdFRSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydNZXNrZXJlbScsICdUaWtlbWV0JywgJ0hpZGFyJywgJ1RhaGVzYXMnLCAnVGlyJywgJ1lla2F0aXQnLFxuICAgICAgICAgICAgJ01lZ2FiaXQnLCAnTWlhemlhJywgJ0dlbmJvdCcsICdTZW5lJywgJ0hhbWxlJywgJ05laGFzZScsICdQYWd1bWUnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydNZXMnLCAnVGlrJywgJ0hpZCcsICdUYWgnLCAnVGlyJywgJ1llaycsXG4gICAgICAgICAgICAnTWVnJywgJ01pYScsICdHZW4nLCAnU2VuJywgJ0hhbScsICdOZWgnLCAnUGFnJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydFaHVkJywgJ1NlZ25vJywgJ01ha3NlZ25vJywgJ0lyb2InLCAnSGFtdXMnLCAnQXJiJywgJ0tpZGFtZSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydFaHUnLCAnU2VnJywgJ01haycsICdJcm8nLCAnSGFtJywgJ0FyYicsICdLaWQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ0VoJywgJ1NlJywgJ01hJywgJ0lyJywgJ0hhJywgJ0FyJywgJ0tpJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnZGQvbW0veXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHZhciB5ZWFyID0gZGF0ZS55ZWFyKCkgKyAoZGF0ZS55ZWFyKCkgPCAwID8gMSA6IDApOyAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHllYXIgJSA0ID09PSAzIHx8IHllYXIgJSA0ID09PSAtMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIG1vbnRocy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBtb250aHNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBtYWluLmxvY2FsLmludmFsaWRZZWFyIHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxMztcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSBtb250aC5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAxMyAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBpZiAoeWVhciA8IDApIHsgeWVhcisrOyB9IC8vIE5vIHllYXIgemVyb1xuICAgICAgICByZXR1cm4gZGF0ZS5kYXkoKSArIChkYXRlLm1vbnRoKCkgLSAxKSAqIDMwICtcbiAgICAgICAgICAgICh5ZWFyIC0gMSkgKiAzNjUgKyBNYXRoLmZsb29yKHllYXIgLyA0KSArIHRoaXMuamRFcG9jaCAtIDE7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gdGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSB0aGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgdmFyIGMgPSBNYXRoLmZsb29yKGpkKSArIDAuNSAtIHRoaXMuamRFcG9jaDtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKChjIC0gTWF0aC5mbG9vcigoYyArIDM2NikgLyAxNDYxKSkgLyAzNjUpICsgMTtcbiAgICAgICAgaWYgKHllYXIgPD0gMCkgeyB5ZWFyLS07IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIGMgPSBNYXRoLmZsb29yKGpkKSArIDAuNSAtIHRoaXMubmV3RGF0ZSh5ZWFyLCAxLCAxKS50b0pEKCk7XG4gICAgICAgIHZhciBtb250aCA9IE1hdGguZmxvb3IoYyAvIDMwKSArIDE7XG4gICAgICAgIHZhciBkYXkgPSBjIC0gKG1vbnRoIC0gMSkgKiAzMCArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIEV0aGlvcGlhbiBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuZXRoaW9waWFuID0gRXRoaW9waWFuQ2FsZW5kYXI7XG5cbiIsIi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgSGVicmV3IGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgQXVndXN0IDIwMDkuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gcmVxdWlyZSgnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IHJlcXVpcmUoJ29iamVjdC1hc3NpZ24nKTtcblxuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIEhlYnJldyBjaXZpbCBjYWxlbmRhci5cbiAgICBCYXNlZCBvbiBjb2RlIGZyb20gPGEgaHJlZj1cImh0dHA6Ly93d3cuZm91cm1pbGFiLmNoL2RvY3VtZW50cy9jYWxlbmRhci9cIj5odHRwOi8vd3d3LmZvdXJtaWxhYi5jaC9kb2N1bWVudHMvY2FsZW5kYXIvPC9hPi5cbiAgICBTZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9IZWJyZXdfY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0hlYnJld19jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIEhlYnJld0NhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIEhlYnJld0NhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbkhlYnJld0NhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKEhlYnJld0NhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgbmFtZTogJ0hlYnJldycsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIEhlYnJldyBlcG9jaDogNyBPY3RvYmVyIDM3NjEgQkNFLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAzNDc5OTUuNSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgZGF5c1Blck1vbnRoOiBbMzAsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzAsIDI5LCAzMCwgMjksIDMwLCAyOSwgMjldLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiA3LFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdIZWJyZXcnLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JBTScsICdBTSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydOaXNhbicsICdJeWFyJywgJ1NpdmFuJywgJ1RhbW11eicsICdBdicsICdFbHVsJyxcbiAgICAgICAgICAgICdUaXNocmVpJywgJ0NoZXNodmFuJywgJ0tpc2xldicsICdUZXZldCcsICdTaGV2YXQnLCAnQWRhcicsICdBZGFyIElJJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnTmlzJywgJ0l5YScsICdTaXYnLCAnVGFtJywgJ0F2JywgJ0VsdScsICdUaXMnLCAnQ2hlJywgJ0tpcycsICdUZXYnLCAnU2hlJywgJ0FkYScsICdBZDInXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1lvbSBSaXNob24nLCAnWW9tIFNoZW5pJywgJ1lvbSBTaGxpc2hpJywgJ1lvbSBSZXZpXFwnaScsICdZb20gQ2hhbWlzaGknLCAnWW9tIFNoaXNoaScsICdZb20gU2hhYmJhdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydSaXMnLCAnU2hlJywgJ1NobCcsICdSZXYnLCAnQ2hhJywgJ1NoaScsICdTaGEnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1JpJywnU2hlJywnU2hsJywnUmUnLCdDaCcsJ1NoaScsJ1NoYSddLFxuICAgICAgICAgICAgZGlnaXRzOiBudWxsLFxuICAgICAgICAgICAgZGF0ZUZvcm1hdDogJ2RkL21tL3l5eXknLFxuICAgICAgICAgICAgZmlyc3REYXk6IDAsXG4gICAgICAgICAgICBpc1JUTDogZmFsc2VcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbGVhcFllYXIoZGF0ZS55ZWFyKCkpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBfbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgeWVhciA9ICh5ZWFyIDwgMCA/IHllYXIgKyAxIDogeWVhcik7XG4gICAgICAgIHJldHVybiBtb2QoeWVhciAqIDcgKyAxLCAxOSkgPCA3O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBtb250aHMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiB0aGlzLl9sZWFwWWVhcih5ZWFyLnllYXIgPyB5ZWFyLnllYXIoKSA6IHllYXIpID8gMTMgOiAxMjtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIHJldHVybiB0aGlzLnRvSkQoKHllYXIgPT09IC0xID8gKzEgOiB5ZWFyICsgMSksIDcsIDEpIC0gdGhpcy50b0pEKHllYXIsIDcsIDEpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICBtb250aCA9IHllYXIubW9udGgoKTtcbiAgICAgICAgICAgIHllYXIgPSB5ZWFyLnllYXIoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIChtb250aCA9PT0gMTIgJiYgdGhpcy5sZWFwWWVhcih5ZWFyKSA/IDMwIDogLy8gQWRhciBJXG4gICAgICAgICAgICAgICAgKG1vbnRoID09PSA4ICYmIG1vZCh0aGlzLmRheXNJblllYXIoeWVhciksIDEwKSA9PT0gNSA/IDMwIDogLy8gQ2hlc2h2YW4gaW4gc2hsZW1haCB5ZWFyXG4gICAgICAgICAgICAgICAgKG1vbnRoID09PSA5ICYmIG1vZCh0aGlzLmRheXNJblllYXIoeWVhciksIDEwKSA9PT0gMyA/IDI5IDogLy8gS2lzbGV2IGluIGNoYXNlcmFoIHllYXJcbiAgICAgICAgICAgICAgICB0aGlzLmRheXNQZXJNb250aFttb250aCAtIDFdKSkpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpICE9PSA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCBhIGRhdGUgLSB5ZWFyIHR5cGUuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtvYmplY3R9IEFkZGl0aW9uYWwgaW5mb3JtYXRpb24gLSBjb250ZW50cyBkZXBlbmRzIG9uIGNhbGVuZGFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGV4dHJhSW5mbzogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4ge3llYXJUeXBlOiAodGhpcy5sZWFwWWVhcihkYXRlKSA/ICdlbWJvbGlzbWljJyA6ICdjb21tb24nKSArICcgJyArXG4gICAgICAgICAgICBbJ2RlZmljaWVudCcsICdyZWd1bGFyJywgJ2NvbXBsZXRlJ11bdGhpcy5kYXlzSW5ZZWFyKGRhdGUpICUgMTAgLSAzXX07XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZSl8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBtb250aCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcbiAgICAgICAgdmFyIGFkalllYXIgPSAoeWVhciA8PSAwID8geWVhciArIDEgOiB5ZWFyKTtcbiAgICAgICAgdmFyIGpkID0gdGhpcy5qZEVwb2NoICsgdGhpcy5fZGVsYXkxKGFkalllYXIpICtcbiAgICAgICAgICAgIHRoaXMuX2RlbGF5MihhZGpZZWFyKSArIGRheSArIDE7XG4gICAgICAgIGlmIChtb250aCA8IDcpIHtcbiAgICAgICAgICAgIGZvciAodmFyIG0gPSA3OyBtIDw9IHRoaXMubW9udGhzSW5ZZWFyKHllYXIpOyBtKyspIHtcbiAgICAgICAgICAgICAgICBqZCArPSB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgbSA9IDE7IG0gPCBtb250aDsgbSsrKSB7XG4gICAgICAgICAgICAgICAgamQgKz0gdGhpcy5kYXlzSW5Nb250aCh5ZWFyLCBtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvciAodmFyIG0gPSA3OyBtIDwgbW9udGg7IG0rKykge1xuICAgICAgICAgICAgICAgIGpkICs9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGpkO1xuICAgIH0sXG5cbiAgICAvKiogVGVzdCBmb3IgZGVsYXkgb2Ygc3RhcnQgb2YgbmV3IHllYXIgYW5kIHRvIGF2b2lkXG4gICAgICAgIFN1bmRheSwgV2VkbmVzZGF5LCBvciBGcmlkYXkgYXMgc3RhcnQgb2YgdGhlIG5ldyB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5cyB0byBvZmZzZXQgYnkuICovXG4gICAgX2RlbGF5MTogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgbW9udGhzID0gTWF0aC5mbG9vcigoMjM1ICogeWVhciAtIDIzNCkgLyAxOSk7XG4gICAgICAgIHZhciBwYXJ0cyA9IDEyMDg0ICsgMTM3NTMgKiBtb250aHM7XG4gICAgICAgIHZhciBkYXkgPSBtb250aHMgKiAyOSArIE1hdGguZmxvb3IocGFydHMgLyAyNTkyMCk7XG4gICAgICAgIGlmIChtb2QoMyAqIChkYXkgKyAxKSwgNykgPCAzKSB7XG4gICAgICAgICAgICBkYXkrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF5O1xuICAgIH0sXG5cbiAgICAvKiogQ2hlY2sgZm9yIGRlbGF5IGluIHN0YXJ0IG9mIG5ldyB5ZWFyIGR1ZSB0byBsZW5ndGggb2YgYWRqYWNlbnQgeWVhcnMuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkYXlzIHRvIG9mZnNldCBieS4gKi9cbiAgICBfZGVsYXkyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBsYXN0ID0gdGhpcy5fZGVsYXkxKHllYXIgLSAxKTtcbiAgICAgICAgdmFyIHByZXNlbnQgPSB0aGlzLl9kZWxheTEoeWVhcik7XG4gICAgICAgIHZhciBuZXh0ID0gdGhpcy5fZGVsYXkxKHllYXIgKyAxKTtcbiAgICAgICAgcmV0dXJuICgobmV4dCAtIHByZXNlbnQpID09PSAzNTYgPyAyIDogKChwcmVzZW50IC0gbGFzdCkgPT09IDM4MiA/IDEgOiAwKSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkKSArIDAuNTtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKCgoamQgLSB0aGlzLmpkRXBvY2gpICogOTg0OTYuMCkgLyAzNTk3NTM1MS4wKSAtIDE7XG4gICAgICAgIHdoaWxlIChqZCA+PSB0aGlzLnRvSkQoKHllYXIgPT09IC0xID8gKzEgOiB5ZWFyICsgMSksIDcsIDEpKSB7XG4gICAgICAgICAgICB5ZWFyKys7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1vbnRoID0gKGpkIDwgdGhpcy50b0pEKHllYXIsIDEsIDEpKSA/IDcgOiAxO1xuICAgICAgICB3aGlsZSAoamQgPiB0aGlzLnRvSkQoeWVhciwgbW9udGgsIHRoaXMuZGF5c0luTW9udGgoeWVhciwgbW9udGgpKSkge1xuICAgICAgICAgICAgbW9udGgrKztcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5ID0gamQgLSB0aGlzLnRvSkQoeWVhciwgbW9udGgsIDEpICsgMTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gTW9kdWx1cyBmdW5jdGlvbiB3aGljaCB3b3JrcyBmb3Igbm9uLWludGVnZXJzLlxuZnVuY3Rpb24gbW9kKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIChiICogTWF0aC5mbG9vcihhIC8gYikpO1xufVxuXG4vLyBIZWJyZXcgY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLmhlYnJldyA9IEhlYnJld0NhbGVuZGFyO1xuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIElzbGFtaWMgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBBdWd1c3QgMjAwOS5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSByZXF1aXJlKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgSXNsYW1pYyBvciAnMTYgY2l2aWwnIGNhbGVuZGFyLlxuICAgIEJhc2VkIG9uIGNvZGUgZnJvbSA8YSBocmVmPVwiaHR0cDovL3d3dy5pcmFuY2hhbWJlci5jb20vY2FsZW5kYXIvY29udmVydGVyL2lyYW5pYW5fY2FsZW5kYXJfY29udmVydGVyLnBocFwiPmh0dHA6Ly93d3cuaXJhbmNoYW1iZXIuY29tL2NhbGVuZGFyL2NvbnZlcnRlci9pcmFuaWFuX2NhbGVuZGFyX2NvbnZlcnRlci5waHA8L2E+LlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lzbGFtaWNfY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lzbGFtaWNfY2FsZW5kYXI8L2E+LlxuICAgIEBjbGFzcyBJc2xhbWljQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gSXNsYW1pY0NhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbklzbGFtaWNDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihJc2xhbWljQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyICovXG4gICAgbmFtZTogJ0lzbGFtaWMnLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBJc2xhbWljIGVwb2NoOiAxNiBKdWx5IDYyMiBDRS5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE5NDg0MzkuNSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMwLCAyOSwgMzAsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzAsIDI5LCAzMCwgMjldLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ0lzbGFtaWMnLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JIJywgJ0FIJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ011aGFycmFtJywgJ1NhZmFyJywgJ1JhYmlcXCcgYWwtYXd3YWwnLCAnUmFiaVxcJyBhbC10aGFuaScsICdKdW1hZGEgYWwtYXd3YWwnLCAnSnVtYWRhIGFsLXRoYW5pJyxcbiAgICAgICAgICAgICdSYWphYicsICdTaGFcXCdhYmFuJywgJ1JhbWFkYW4nLCAnU2hhd3dhbCcsICdEaHUgYWwtUWlcXCdkYWgnLCAnRGh1IGFsLUhpamphaCddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ011aCcsICdTYWYnLCAnUmFiMScsICdSYWIyJywgJ0p1bTEnLCAnSnVtMicsICdSYWonLCAnU2hhXFwnJywgJ1JhbScsICdTaGF3JywgJ0RodVEnLCAnRGh1SCddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnWWF3bSBhbC1haGFkJywgJ1lhd20gYWwtaXRobmF5bicsICdZYXdtIGF0aC10aHVsYWF0aGFhXFwnJyxcbiAgICAgICAgICAgICdZYXdtIGFsLWFyYmlcXCdhYVxcJycsICdZYXdtIGFsLWtoYW3Eq3MnLCAnWWF3bSBhbC1qdW1cXCdhJywgJ1lhd20gYXMtc2FidCddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydBaGEnLCAnSXRoJywgJ1RodScsICdBcmInLCAnS2hhJywgJ0p1bScsICdTYWInXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ0FoJywnSXQnLCdUaCcsJ0FyJywnS2gnLCdKdScsJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAneXl5eS9tbS9kZCcsXG4gICAgICAgICAgICBmaXJzdERheTogNixcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gKGRhdGUueWVhcigpICogMTEgKyAxNCkgJSAzMCA8IDExO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gKHRoaXMubGVhcFllYXIoeWVhcikgPyAzNTUgOiAzNTQpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdICtcbiAgICAgICAgICAgIChkYXRlLm1vbnRoKCkgPT09IDEyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KSAhPT0gNTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIG1vbnRoID0gZGF0ZS5tb250aCgpO1xuICAgICAgICBkYXkgPSBkYXRlLmRheSgpO1xuICAgICAgICB5ZWFyID0gKHllYXIgPD0gMCA/IHllYXIgKyAxIDogeWVhcik7XG4gICAgICAgIHJldHVybiBkYXkgKyBNYXRoLmNlaWwoMjkuNSAqIChtb250aCAtIDEpKSArICh5ZWFyIC0gMSkgKiAzNTQgK1xuICAgICAgICAgICAgTWF0aC5mbG9vcigoMyArICgxMSAqIHllYXIpKSAvIDMwKSArIHRoaXMuamRFcG9jaCAtIDE7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkID0gTWF0aC5mbG9vcihqZCkgKyAwLjU7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcigoMzAgKiAoamQgLSB0aGlzLmpkRXBvY2gpICsgMTA2NDYpIC8gMTA2MzEpO1xuICAgICAgICB5ZWFyID0gKHllYXIgPD0gMCA/IHllYXIgLSAxIDogeWVhcik7XG4gICAgICAgIHZhciBtb250aCA9IE1hdGgubWluKDEyLCBNYXRoLmNlaWwoKGpkIC0gMjkgLSB0aGlzLnRvSkQoeWVhciwgMSwgMSkpIC8gMjkuNSkgKyAxKTtcbiAgICAgICAgdmFyIGRheSA9IGpkIC0gdGhpcy50b0pEKHllYXIsIG1vbnRoLCAxKSArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIElzbGFtaWMgKDE2IGNpdmlsKSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuaXNsYW1pYyA9IElzbGFtaWNDYWxlbmRhcjtcblxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBKdWxpYW4gY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBBdWd1c3QgMjAwOS5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSByZXF1aXJlKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgSnVsaWFuIGNhbGVuZGFyLlxuICAgIEJhc2VkIG9uIGNvZGUgZnJvbSA8YSBocmVmPVwiaHR0cDovL3d3dy5mb3VybWlsYWIuY2gvZG9jdW1lbnRzL2NhbGVuZGFyL1wiPmh0dHA6Ly93d3cuZm91cm1pbGFiLmNoL2RvY3VtZW50cy9jYWxlbmRhci88L2E+LlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0p1bGlhbl9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSnVsaWFuX2NhbGVuZGFyPC9hPi5cbiAgICBAY2xhc3MgSnVsaWFuQ2FsZW5kYXJcbiAgICBAYXVnbWVudHMgQmFzZUNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIEp1bGlhbkNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbkp1bGlhbkNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKEp1bGlhbkNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbmFtZTogJ0p1bGlhbicsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIEp1bGlhbiBlcG9jaDogMSBKYW51YXJ5IDAwMDEgQUQgPSAzMCBEZWNlbWJlciAwMDAxIEJDRS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTcyMTQyMy41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMjgsIDMxLCAzMCwgMzEsIDMwLCAzMSwgMzEsIDMwLCAzMSwgMzAsIDMxXSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnSnVsaWFuJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQycsICdBRCddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnbW0vZGQveXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHZhciB5ZWFyID0gKGRhdGUueWVhcigpIDwgMCA/IGRhdGUueWVhcigpICsgMSA6IGRhdGUueWVhcigpKTsgLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIHJldHVybiAoeWVhciAlIDQpID09PSAwO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUgLSBJU08gODYwMS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFRodXJzZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBNb25kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCg0IC0gKGNoZWNrRGF0ZS5kYXlPZldlZWsoKSB8fCA3KSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV0gK1xuICAgICAgICAgICAgKGRhdGUubW9udGgoKSA9PT0gMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhIHdlZWsgZGF5LCBmYWxzZSBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHx8IDcpIDwgNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIGlmICh5ZWFyIDwgMCkgeyB5ZWFyKys7IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIC8vIEplYW4gTWVldXMgYWxnb3JpdGhtLCBcIkFzdHJvbm9taWNhbCBBbGdvcml0aG1zXCIsIDE5OTFcbiAgICAgICAgaWYgKG1vbnRoIDw9IDIpIHtcbiAgICAgICAgICAgIHllYXItLTtcbiAgICAgICAgICAgIG1vbnRoICs9IDEyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKDM2NS4yNSAqICh5ZWFyICsgNDcxNikpICtcbiAgICAgICAgICAgIE1hdGguZmxvb3IoMzAuNjAwMSAqIChtb250aCArIDEpKSArIGRheSAtIDE1MjQuNTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICAvLyBKZWFuIE1lZXVzIGFsZ29yaXRobSwgXCJBc3Ryb25vbWljYWwgQWxnb3JpdGhtc1wiLCAxOTkxXG4gICAgICAgIHZhciBhID0gTWF0aC5mbG9vcihqZCArIDAuNSk7XG4gICAgICAgIHZhciBiID0gYSArIDE1MjQ7XG4gICAgICAgIHZhciBjID0gTWF0aC5mbG9vcigoYiAtIDEyMi4xKSAvIDM2NS4yNSk7XG4gICAgICAgIHZhciBkID0gTWF0aC5mbG9vcigzNjUuMjUgKiBjKTtcbiAgICAgICAgdmFyIGUgPSBNYXRoLmZsb29yKChiIC0gZCkgLyAzMC42MDAxKTtcbiAgICAgICAgdmFyIG1vbnRoID0gZSAtIE1hdGguZmxvb3IoZSA8IDE0ID8gMSA6IDEzKTtcbiAgICAgICAgdmFyIHllYXIgPSBjIC0gTWF0aC5mbG9vcihtb250aCA+IDIgPyA0NzE2IDogNDcxNSk7XG4gICAgICAgIHZhciBkYXkgPSBiIC0gZCAtIE1hdGguZmxvb3IoMzAuNjAwMSAqIGUpO1xuICAgICAgICBpZiAoeWVhciA8PSAwKSB7IHllYXItLTsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gSnVsaWFuIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5qdWxpYW4gPSBKdWxpYW5DYWxlbmRhcjtcblxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBNYXlhbiBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEF1Z3VzdCAyMDA5LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBNYXlhbiBMb25nIENvdW50IGNhbGVuZGFyLlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01heWFuX2NhbGVuZGFyXCI+aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NYXlhbl9jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIE1heWFuQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gTWF5YW5DYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5NYXlhbkNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKE1heWFuQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhciAqL1xuICAgIG5hbWU6ICdNYXlhbicsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIE1heWFuIGVwb2NoOiAxMSBBdWd1c3QgMzExNCBCQ0UuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyICovXG4gICAgamRFcG9jaDogNTg0MjgyLjUsXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogdHJ1ZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAwLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMCxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDAsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC5cbiAgICAgICAgQHByb3BlcnR5IGhhYWJNb250aHMge3N0cmluZ1tdfSBUaGUgbmFtZXMgb2YgdGhlIEhhYWIgbW9udGhzLlxuICAgICAgICBAcHJvcGVydHkgdHpvbGtpbk1vbnRocyB7c3RyaW5nW119IFRoZSBuYW1lcyBvZiB0aGUgVHpvbGtpbiBtb250aHMuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdNYXlhbicsXG4gICAgICAgICAgICBlcG9jaHM6IFsnJywgJyddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgICAgICAgICAgICcxMCcsICcxMScsICcxMicsICcxMycsICcxNCcsICcxNScsICcxNicsICcxNyddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLFxuICAgICAgICAgICAgJzEwJywgJzExJywgJzEyJywgJzEzJywgJzE0JywgJzE1JywgJzE2JywgJzE3J10sXG4gICAgICAgICAgICBkYXlOYW1lczogWycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgICAgICAgICAgICcxMCcsICcxMScsICcxMicsICcxMycsICcxNCcsICcxNScsICcxNicsICcxNycsICcxOCcsICcxOSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgICAgICAgICAgICcxMCcsICcxMScsICcxMicsICcxMycsICcxNCcsICcxNScsICcxNicsICcxNycsICcxOCcsICcxOSddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsXG4gICAgICAgICAgICAnMTAnLCAnMTEnLCAnMTInLCAnMTMnLCAnMTQnLCAnMTUnLCAnMTYnLCAnMTcnLCAnMTgnLCAnMTknXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdZWVlZLm0uZCcsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZSxcbiAgICAgICAgICAgIGhhYWJNb250aHM6IFsnUG9wJywgJ1VvJywgJ1ppcCcsICdab3R6JywgJ1R6ZWMnLCAnWHVsJywgJ1lheGtpbicsICdNb2wnLCAnQ2hlbicsICdZYXgnLFxuICAgICAgICAgICAgJ1phYycsICdDZWgnLCAnTWFjJywgJ0thbmtpbicsICdNdWFuJywgJ1BheCcsICdLYXlhYicsICdDdW1rdScsICdVYXllYiddLFxuICAgICAgICAgICAgdHpvbGtpbk1vbnRoczogWydJbWl4JywgJ0lrJywgJ0FrYmFsJywgJ0thbicsICdDaGljY2hhbicsICdDaW1pJywgJ01hbmlrJywgJ0xhbWF0JywgJ011bHVjJywgJ09jJyxcbiAgICAgICAgICAgICdDaHVlbicsICdFYicsICdCZW4nLCAnSXgnLCAnTWVuJywgJ0NpYicsICdDYWJhbicsICdFdHpuYWInLCAnQ2F1YWMnLCAnQWhhdSddXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICAvKiogRm9ybWF0IHRoZSB5ZWFyLCBpZiBub3QgYSBzaW1wbGUgc2VxdWVudGlhbCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGZvcm1hdCBvciB0aGUgeWVhciB0byBmb3JtYXQuXG4gICAgICAgIEByZXR1cm4ge3N0cmluZ30gVGhlIGZvcm1hdHRlZCB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGZvcm1hdFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgdmFyIGJha3R1biA9IE1hdGguZmxvb3IoeWVhciAvIDQwMCk7XG4gICAgICAgIHllYXIgPSB5ZWFyICUgNDAwO1xuICAgICAgICB5ZWFyICs9ICh5ZWFyIDwgMCA/IDQwMCA6IDApO1xuICAgICAgICB2YXIga2F0dW4gPSBNYXRoLmZsb29yKHllYXIgLyAyMCk7XG4gICAgICAgIHJldHVybiBiYWt0dW4gKyAnLicgKyBrYXR1biArICcuJyArICh5ZWFyICUgMjApO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCBmcm9tIHRoZSBmb3JtYXR0ZWQgeWVhciBiYWNrIHRvIGEgc2luZ2xlIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXJzIHtzdHJpbmd9IFRoZSB5ZWFyIGFzIG4ubi5uLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBzZXF1ZW50aWFsIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB2YWx1ZSBpcyBzdXBwbGllZC4gKi9cbiAgICBmb3JZZWFyOiBmdW5jdGlvbih5ZWFycykge1xuICAgICAgICB5ZWFycyA9IHllYXJzLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmICh5ZWFycy5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgICB0aHJvdyAnSW52YWxpZCBNYXlhbiB5ZWFyJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgeWVhciA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgeWVhcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB5ID0gcGFyc2VJbnQoeWVhcnNbaV0sIDEwKTtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyh5KSA+IDE5IHx8IChpID4gMCAmJiB5IDwgMCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyAnSW52YWxpZCBNYXlhbiB5ZWFyJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHllYXIgPSB5ZWFyICogMjAgKyB5O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB5ZWFyO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBtb250aHMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBtb250aHMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbW9udGhzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIDE4O1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gMzYwO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gMjA7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB3ZWVrLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy4gKi9cbiAgICBkYXlzSW5XZWVrOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDU7IC8vIEp1c3QgZm9yIGZvcm1hdHRpbmdcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBkYXkgb2YgdGhlIHdlZWsgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5IG9mIHRoZSB3ZWVrOiAwIHRvIG51bWJlciBvZiBkYXlzIC0gMS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlPZldlZWs6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIGRhdGUuZGF5KCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgYSBkYXRlIC0gSGFhYiBhbmQgVHpvbGtpbiBlcXVpdmFsZW50cy5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7b2JqZWN0fSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIC0gY29udGVudHMgZGVwZW5kcyBvbiBjYWxlbmRhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBleHRyYUluZm86IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgdmFyIGpkID0gZGF0ZS50b0pEKCk7XG4gICAgICAgIHZhciBoYWFiID0gdGhpcy5fdG9IYWFiKGpkKTtcbiAgICAgICAgdmFyIHR6b2xraW4gPSB0aGlzLl90b1R6b2xraW4oamQpO1xuICAgICAgICByZXR1cm4ge2hhYWJNb250aE5hbWU6IHRoaXMubG9jYWwuaGFhYk1vbnRoc1toYWFiWzBdIC0gMV0sXG4gICAgICAgICAgICBoYWFiTW9udGg6IGhhYWJbMF0sIGhhYWJEYXk6IGhhYWJbMV0sXG4gICAgICAgICAgICB0em9sa2luRGF5TmFtZTogdGhpcy5sb2NhbC50em9sa2luTW9udGhzW3R6b2xraW5bMF0gLSAxXSxcbiAgICAgICAgICAgIHR6b2xraW5EYXk6IHR6b2xraW5bMF0sIHR6b2xraW5UcmVjZW5hOiB0em9sa2luWzFdfTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIEhhYWIgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSBqZCAge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJbXX0gQ29ycmVzcG9uZGluZyBIYWFiIG1vbnRoIGFuZCBkYXkuICovXG4gICAgX3RvSGFhYjogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgLT0gdGhpcy5qZEVwb2NoO1xuICAgICAgICB2YXIgZGF5ID0gbW9kKGpkICsgOCArICgoMTggLSAxKSAqIDIwKSwgMzY1KTtcbiAgICAgICAgcmV0dXJuIFtNYXRoLmZsb29yKGRheSAvIDIwKSArIDEsIG1vZChkYXksIDIwKV07XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSBUem9sa2luIGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJbXX0gQ29ycmVzcG9uZGluZyBUem9sa2luIGRheSBhbmQgdHJlY2VuYS4gKi9cbiAgICBfdG9Uem9sa2luOiBmdW5jdGlvbihqZCkge1xuICAgICAgICBqZCAtPSB0aGlzLmpkRXBvY2g7XG4gICAgICAgIHJldHVybiBbYW1vZChqZCArIDIwLCAyMCksIGFtb2QoamQgKyA0LCAxMyldO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4gZGF0ZS5kYXkoKSArIChkYXRlLm1vbnRoKCkgKiAyMCkgKyAoZGF0ZS55ZWFyKCkgKiAzNjApICsgdGhpcy5qZEVwb2NoO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkKSArIDAuNSAtIHRoaXMuamRFcG9jaDtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKGpkIC8gMzYwKTtcbiAgICAgICAgamQgPSBqZCAlIDM2MDtcbiAgICAgICAgamQgKz0gKGpkIDwgMCA/IDM2MCA6IDApO1xuICAgICAgICB2YXIgbW9udGggPSBNYXRoLmZsb29yKGpkIC8gMjApO1xuICAgICAgICB2YXIgZGF5ID0gamQgJSAyMDtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gTW9kdWx1cyBmdW5jdGlvbiB3aGljaCB3b3JrcyBmb3Igbm9uLWludGVnZXJzLlxuZnVuY3Rpb24gbW9kKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIChiICogTWF0aC5mbG9vcihhIC8gYikpO1xufVxuXG4vLyBNb2R1bHVzIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgbnVtZXJhdG9yIGlmIG1vZHVsdXMgaXMgemVyby5cbmZ1bmN0aW9uIGFtb2QoYSwgYikge1xuICAgIHJldHVybiBtb2QoYSAtIDEsIGIpICsgMTtcbn1cblxuLy8gTWF5YW4gY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLm1heWFuID0gTWF5YW5DYWxlbmRhcjtcblxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG4vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBOYW5ha3NoYWhpIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgSmFudWFyeSAyMDE2LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBOYW5ha3NoYWhpIGNhbGVuZGFyLlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9OYW5ha3NoYWhpX2NhbGVuZGFyXCI+aHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTmFuYWtzaGFoaV9jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIE5hbmFrc2hhaGlDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBOYW5ha3NoYWhpQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuTmFuYWtzaGFoaUNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxudmFyIGdyZWdvcmlhbiA9IG1haW4uaW5zdGFuY2UoJ2dyZWdvcmlhbicpO1xuXG5hc3NpZ24oTmFuYWtzaGFoaUNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIG5hbWU6ICdOYW5ha3NoYWhpJyxcbiAgICAvKiogSnVsaWFuIGRhdGUgb2Ygc3RhcnQgb2YgTmFuYWtzaGFoaSBlcG9jaDogMTQgTWFyY2ggMTQ2OSBDRS5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDIyNTc2NzMuNSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAzMSwgMzEsIDMxLCAzMSwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzBdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ05hbmFrc2hhaGknLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JOJywgJ0FOJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0NoZXQnLCAnVmFpc2FraCcsICdKZXRoJywgJ0hhcmgnLCAnU2F3YW4nLCAnQmhhZG9uJyxcbiAgICAgICAgICAgICdBc3N1JywgJ0thdGFrJywgJ01hZ2hhcicsICdQb2gnLCAnTWFnaCcsICdQaGFndW4nXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydDaGUnLCAnVmFpJywgJ0pldCcsICdIYXInLCAnU2F3JywgJ0JoYScsICdBc3MnLCAnS2F0JywgJ01ncicsICdQb2gnLCAnTWdoJywgJ1BoYSddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnU29tdmFhcicsICdNYW5nYWx2YXInLCAnQnVkaHZhYXInLCAnVmVlcnZhYXInLCAnU2h1a2FydmFhcicsICdTYW5pY2hhcnZhYXInLCAnRXR2YWFyJ10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1NvbScsICdNYW5nYWwnLCAnQnVkaCcsICdWZWVyJywgJ1NodWthcicsICdTYW5pY2hhcicsICdFdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnU28nLCAnTWEnLCAnQnUnLCAnVmUnLCAnU2gnLCAnU2EnLCAnRXQnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdkZC1tbS15eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAwLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIG1haW4ubG9jYWwuaW52YWxpZFllYXIgfHwgbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbi5sZWFwWWVhcihkYXRlLnllYXIoKSArIChkYXRlLnllYXIoKSA8IDEgPyAxIDogMCkgKyAxNDY5KTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIE1vbmRheSBvZiB0aGlzIHdlZWsgc3RhcnRpbmcgb24gTW9uZGF5XG4gICAgICAgIHZhciBjaGVja0RhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgIGNoZWNrRGF0ZS5hZGQoMSAtIChjaGVja0RhdGUuZGF5T2ZXZWVrKCkgfHwgNyksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAxMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHx8IDcpIDwgNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgdmFyIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgaWYgKHllYXIgPCAwKSB7IHllYXIrKzsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgdmFyIGRveSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIGZvciAodmFyIG0gPSAxOyBtIDwgZGF0ZS5tb250aCgpOyBtKyspIHtcbiAgICAgICAgICAgIGRveSArPSB0aGlzLmRheXNQZXJNb250aFttIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRveSArIGdyZWdvcmlhbi50b0pEKHllYXIgKyAxNDY4LCAzLCAxMyk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkID0gTWF0aC5mbG9vcihqZCArIDAuNSk7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcigoamQgLSAodGhpcy5qZEVwb2NoIC0gMSkpIC8gMzY2KTtcbiAgICAgICAgd2hpbGUgKGpkID49IHRoaXMudG9KRCh5ZWFyICsgMSwgMSwgMSkpIHtcbiAgICAgICAgICAgIHllYXIrKztcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5ID0gamQgLSBNYXRoLmZsb29yKHRoaXMudG9KRCh5ZWFyLCAxLCAxKSArIDAuNSkgKyAxO1xuICAgICAgICB2YXIgbW9udGggPSAxO1xuICAgICAgICB3aGlsZSAoZGF5ID4gdGhpcy5kYXlzSW5Nb250aCh5ZWFyLCBtb250aCkpIHtcbiAgICAgICAgICAgIGRheSAtPSB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG1vbnRoKTtcbiAgICAgICAgICAgIG1vbnRoKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gTmFuYWtzaGFoaSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMubmFuYWtzaGFoaSA9IE5hbmFrc2hhaGlDYWxlbmRhcjtcblxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBOZXBhbGkgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEFydHVyIE5ldW1hbm4gKGljdC5wcm9qZWN0c3thdH1uZXBhbC5pbmYub3JnKSBBcHJpbCAyMDEzLlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBOZXBhbGkgY2l2aWwgY2FsZW5kYXIuXG4gICAgQmFzZWQgb24gdGhlIGlkZWFzIGZyb20gXG4gICAgPGEgaHJlZj1cImh0dHA6Ly9jb2RlaXNzdWUuY29tL2FydGljbGVzL2EwNGUwNTBkZWE3NDY4Zi9hbGdvcml0aG0tdG8tY29udmVydC1lbmdsaXNoLWRhdGUtdG8tbmVwYWxpLWRhdGUtdXNpbmctYy1uZXRcIj5odHRwOi8vY29kZWlzc3VlLmNvbS9hcnRpY2xlcy9hMDRlMDUwZGVhNzQ2OGYvYWxnb3JpdGhtLXRvLWNvbnZlcnQtZW5nbGlzaC1kYXRlLXRvLW5lcGFsaS1kYXRlLXVzaW5nLWMtbmV0PC9hPlxuICAgIGFuZCA8YSBocmVmPVwiaHR0cDovL2JpcmVuajJlZS5ibG9nc3BvdC5jb20vMjAxMS8wNC9uZXBhbGktY2FsZW5kYXItaW4tamF2YS5odG1sXCI+aHR0cDovL2JpcmVuajJlZS5ibG9nc3BvdC5jb20vMjAxMS8wNC9uZXBhbGktY2FsZW5kYXItaW4tamF2YS5odG1sPC9hPlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05lcGFsaV9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTmVwYWxpX2NhbGVuZGFyPC9hPlxuICAgIGFuZCA8YSBocmVmPVwiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmlrcmFtX1NhbXdhdFwiPmh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jpa3JhbV9TYW13YXQ8L2E+LlxuICAgIEBjbGFzcyBOZXBhbGlDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBOZXBhbGlDYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5OZXBhbGlDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihOZXBhbGlDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhciAqL1xuICAgIG5hbWU6ICdOZXBhbGknLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBOZXBhbGkgZXBvY2g6IDE0IEFwcmlsIDU3IEJDRS5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTcwMDcwOS41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMzEsIDMyLCAzMiwgMzEsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzAsIDMwXSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLCBcbiAgICAvKiogVGhlIG51bWJlciBvZiBkYXlzIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyWWVhcjogMzY1LFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnTmVwYWxpJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQlMnLCAnQUJTJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0JhaXNha2gnLCAnSmVzdGhhJywgJ0FzaGFkaCcsICdTaHJhd2FuJywgJ0JoYWRyYScsICdBc2h3aW4nLFxuICAgICAgICAgICAgJ0thcnRpaycsICdNYW5nc2lyJywgJ1BhdXNoJywgJ01hbmdoJywgJ0ZhbGd1bicsICdDaGFpdHJhJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnQmFpJywgJ0plJywgJ0FzJywgJ1NocmEnLCAnQmhhJywgJ0FzaCcsICdLYXInLCAnTWFuZycsICdQYXUnLCAnTWEnLCAnRmFsJywgJ0NoYWknXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ0FhaXRhYmFhcicsICdTb21iYWFyJywgJ01hbmdsYmFhcicsICdCdWRoYWJhYXInLCAnQmloaWJhYXInLCAnU2h1a3JhYmFhcicsICdTaGFuaWJhYXInXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnQWFpdGEnLCAnU29tJywgJ01hbmdsJywgJ0J1ZGhhJywgJ0JpaGknLCAnU2h1a3JhJywgJ1NoYW5pJ10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydBYWknLCAnU28nLCAnTWFuJywgJ0J1JywgJ0JpJywgJ1NodScsICdTaGEnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdkZC9tbS95eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAxLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzSW5ZZWFyKHllYXIpICE9PSB0aGlzLmRheXNQZXJZZWFyO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW3llYXJdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1BlclllYXI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRheXNQZXJZZWFyID0gMDtcbiAgICAgICAgZm9yICh2YXIgbW9udGhfbnVtYmVyID0gdGhpcy5taW5Nb250aDsgbW9udGhfbnVtYmVyIDw9IDEyOyBtb250aF9udW1iZXIrKykge1xuICAgICAgICAgICAgZGF5c1BlclllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVt5ZWFyXVttb250aF9udW1iZXJdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXlzUGVyWWVhcjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcnwgVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgaWYgKHllYXIueWVhcikge1xuICAgICAgICAgICAgbW9udGggPSB5ZWFyLm1vbnRoKCk7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbeWVhcl0gPT09ICd1bmRlZmluZWQnID9cbiAgICAgICAgICAgIHRoaXMuZGF5c1Blck1vbnRoW21vbnRoIC0gMV0gOiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW3llYXJdW21vbnRoXSk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgIT09IDY7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24obmVwYWxpWWVhciwgbmVwYWxpTW9udGgsIG5lcGFsaURheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKG5lcGFsaVllYXIsIG5lcGFsaU1vbnRoLCBuZXBhbGlEYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICBuZXBhbGlZZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIG5lcGFsaU1vbnRoID0gZGF0ZS5tb250aCgpO1xuICAgICAgICBuZXBhbGlEYXkgPSBkYXRlLmRheSgpO1xuICAgICAgICB2YXIgZ3JlZ29yaWFuQ2FsZW5kYXIgPSBtYWluLmluc3RhbmNlKCk7XG4gICAgICAgIHZhciBncmVnb3JpYW5EYXlPZlllYXIgPSAwOyAvLyBXZSB3aWxsIGFkZCBhbGwgdGhlIGRheXMgdGhhdCB3ZW50IGJ5IHNpbmNlXG4gICAgICAgIC8vIHRoZSAxc3QuIEphbnVhcnkgYW5kIHRoZW4gd2UgY2FuIGdldCB0aGUgR3JlZ29yaWFuIERhdGVcbiAgICAgICAgdmFyIG5lcGFsaU1vbnRoVG9DaGVjayA9IG5lcGFsaU1vbnRoO1xuICAgICAgICB2YXIgbmVwYWxpWWVhclRvQ2hlY2sgPSBuZXBhbGlZZWFyO1xuICAgICAgICB0aGlzLl9jcmVhdGVNaXNzaW5nQ2FsZW5kYXJEYXRhKG5lcGFsaVllYXIpO1xuICAgICAgICAvLyBHZXQgdGhlIGNvcnJlY3QgeWVhclxuICAgICAgICB2YXIgZ3JlZ29yaWFuWWVhciA9IG5lcGFsaVllYXIgLSAobmVwYWxpTW9udGhUb0NoZWNrID4gOSB8fCAobmVwYWxpTW9udGhUb0NoZWNrID09PSA5ICYmXG4gICAgICAgICAgICBuZXBhbGlEYXkgPj0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bMF0pID8gNTYgOiA1Nyk7XG4gICAgICAgIC8vIEZpcnN0IHdlIGFkZCB0aGUgYW1vdW50IG9mIGRheXMgaW4gdGhlIGFjdHVhbCBOZXBhbGkgbW9udGggYXMgdGhlIGRheSBvZiB5ZWFyIGluIHRoZVxuICAgICAgICAvLyBHcmVnb3JpYW4gb25lIGJlY2F1c2UgYXQgbGVhc3QgdGhpcyBkYXlzIGFyZSBnb25lIHNpbmNlIHRoZSAxc3QuIEphbi4gXG4gICAgICAgIGlmIChuZXBhbGlNb250aCAhPT0gOSkge1xuICAgICAgICAgICAgZ3JlZ29yaWFuRGF5T2ZZZWFyID0gbmVwYWxpRGF5O1xuICAgICAgICAgICAgbmVwYWxpTW9udGhUb0NoZWNrLS07XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm93IHdlIGxvb3AgdGhyb3cgYWxsIE5lcGFsaSBtb250aCBhbmQgYWRkIHRoZSBhbW91bnQgb2YgZGF5cyB0byBncmVnb3JpYW5EYXlPZlllYXIgXG4gICAgICAgIC8vIHdlIGRvIHRoaXMgdGlsbCB3ZSByZWFjaCBQYXVzaCAoOXRoIG1vbnRoKS4gMXN0LiBKYW51YXJ5IGFsd2F5cyBmYWxscyBpbiB0aGlzIG1vbnRoICBcbiAgICAgICAgd2hpbGUgKG5lcGFsaU1vbnRoVG9DaGVjayAhPT0gOSkge1xuICAgICAgICAgICAgaWYgKG5lcGFsaU1vbnRoVG9DaGVjayA8PSAwKSB7XG4gICAgICAgICAgICAgICAgbmVwYWxpTW9udGhUb0NoZWNrID0gMTI7XG4gICAgICAgICAgICAgICAgbmVwYWxpWWVhclRvQ2hlY2stLTtcbiAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBncmVnb3JpYW5EYXlPZlllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bbmVwYWxpTW9udGhUb0NoZWNrXTtcbiAgICAgICAgICAgIG5lcGFsaU1vbnRoVG9DaGVjay0tO1xuICAgICAgICB9ICAgICAgICBcbiAgICAgICAgLy8gSWYgdGhlIGRhdGUgdGhhdCBoYXMgdG8gYmUgY29udmVydGVkIGlzIGluIFBhdXNoIChtb250aCBuby4gOSkgd2UgaGF2ZSB0byBkbyBzb21lIG90aGVyIGNhbGN1bGF0aW9uXG4gICAgICAgIGlmIChuZXBhbGlNb250aCA9PT0gOSkge1xuICAgICAgICAgICAgLy8gQWRkIHRoZSBkYXlzIHRoYXQgYXJlIHBhc3NlZCBzaW5jZSB0aGUgZmlyc3QgZGF5IG9mIFBhdXNoIGFuZCBzdWJzdHJhY3QgdGhlXG4gICAgICAgICAgICAvLyBhbW91bnQgb2YgZGF5cyB0aGF0IGxpZSBiZXR3ZWVuIDFzdC4gSmFuIGFuZCAxc3QgUGF1c2hcbiAgICAgICAgICAgIGdyZWdvcmlhbkRheU9mWWVhciArPSBuZXBhbGlEYXkgLSB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW25lcGFsaVllYXJUb0NoZWNrXVswXTtcbiAgICAgICAgICAgIC8vIEZvciB0aGUgZmlyc3QgZGF5cyBvZiBQYXVzaCB3ZSBhcmUgbm93IGluIG5lZ2F0aXZlIHZhbHVlcyxcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgaW4gdGhlIGVuZCBvZiB0aGUgZ3JlZ29yaWFuIHllYXIgd2Ugc3Vic3RyYWN0XG4gICAgICAgICAgICAvLyAzNjUgLyAzNjYgZGF5cyAoUC5TLiByZW1lbWJlciBtYXRoIGluIHNjaG9vbCArIC0gZ2l2ZXMgLSlcbiAgICAgICAgICAgIGlmIChncmVnb3JpYW5EYXlPZlllYXIgPCAwKSB7XG4gICAgICAgICAgICAgICAgZ3JlZ29yaWFuRGF5T2ZZZWFyICs9IGdyZWdvcmlhbkNhbGVuZGFyLmRheXNJblllYXIoZ3JlZ29yaWFuWWVhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBncmVnb3JpYW5EYXlPZlllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bOV0gLVxuICAgICAgICAgICAgICAgIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhclRvQ2hlY2tdWzBdO1xuICAgICAgICB9ICAgICAgICBcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLm5ld0RhdGUoZ3JlZ29yaWFuWWVhciwgMSAsMSkuYWRkKGdyZWdvcmlhbkRheU9mWWVhciwgJ2QnKS50b0pEKCk7XG4gICAgfSxcbiAgICBcbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBncmVnb3JpYW5DYWxlbmRhciA9ICBtYWluLmluc3RhbmNlKCk7XG4gICAgICAgIHZhciBncmVnb3JpYW5EYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIGdyZWdvcmlhblllYXIgPSBncmVnb3JpYW5EYXRlLnllYXIoKTtcbiAgICAgICAgdmFyIGdyZWdvcmlhbkRheU9mWWVhciA9IGdyZWdvcmlhbkRhdGUuZGF5T2ZZZWFyKCk7XG4gICAgICAgIHZhciBuZXBhbGlZZWFyID0gZ3JlZ29yaWFuWWVhciArIDU2OyAvL3RoaXMgaXMgbm90IGZpbmFsLCBpdCBjb3VsZCBiZSBhbHNvICs1NyBidXQgKzU2IGlzIGFsd2F5cyB0cnVlIGZvciAxc3QgSmFuLlxuICAgICAgICB0aGlzLl9jcmVhdGVNaXNzaW5nQ2FsZW5kYXJEYXRhKG5lcGFsaVllYXIpO1xuICAgICAgICB2YXIgbmVwYWxpTW9udGggPSA5OyAvLyBKYW4gMSBhbHdheXMgZmFsbCBpbiBOZXBhbGkgbW9udGggUGF1c2ggd2hpY2ggaXMgdGhlIDl0aCBtb250aCBvZiBOZXBhbGkgY2FsZW5kYXIuXG4gICAgICAgIC8vIEdldCB0aGUgTmVwYWxpIGRheSBpbiBQYXVzaCAobW9udGggOSkgb2YgMXN0IEphbnVhcnkgXG4gICAgICAgIHZhciBkYXlPZkZpcnN0SmFuSW5QYXVzaCA9IHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bMF07XG4gICAgICAgIC8vIENoZWNrIGhvdyBtYW55IGRheXMgYXJlIGxlZnQgb2YgUGF1c2ggLlxuICAgICAgICAvLyBEYXlzIGNhbGN1bGF0ZWQgZnJvbSAxc3QgSmFuIHRpbGwgdGhlIGVuZCBvZiB0aGUgYWN0dWFsIE5lcGFsaSBtb250aCwgXG4gICAgICAgIC8vIHdlIHVzZSB0aGlzIHZhbHVlIHRvIGNoZWNrIGlmIHRoZSBncmVnb3JpYW4gRGF0ZSBpcyBpbiB0aGUgYWN0dWFsIE5lcGFsaSBtb250aC5cbiAgICAgICAgdmFyIGRheXNTaW5jZUphbkZpcnN0VG9FbmRPZk5lcGFsaU1vbnRoID1cbiAgICAgICAgICAgIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bbmVwYWxpTW9udGhdIC0gZGF5T2ZGaXJzdEphbkluUGF1c2ggKyAxO1xuICAgICAgICAvLyBJZiB0aGUgZ3JlZ29yaWFuIGRheS1vZi15ZWFyIGlzIHNtYWxsZXIgbyBlcXVhbCB0aGFuIHRoZSBzdW0gb2YgZGF5cyBiZXR3ZWVuIHRoZSAxc3QgSmFudWFyeSBhbmQgXG4gICAgICAgIC8vIHRoZSBlbmQgb2YgdGhlIGFjdHVhbCBuZXBhbGkgbW9udGggd2UgZm91bmQgdGhlIGNvcnJlY3QgbmVwYWxpIG1vbnRoLlxuICAgICAgICAvLyBFeGFtcGxlOiBcbiAgICAgICAgLy8gVGhlIDR0aCBGZWJydWFyeSAyMDExIGlzIHRoZSBncmVnb3JpYW5EYXlPZlllYXIgMzUgKDMxIGRheXMgb2YgSmFudWFyeSArIDQpXG4gICAgICAgIC8vIDFzdCBKYW51YXJ5IDIwMTEgaXMgaW4gdGhlIG5lcGFsaSB5ZWFyIDIwNjcsIHdoZXJlIDFzdC4gSmFudWFyeSBpcyBpbiB0aGUgMTd0aCBkYXkgb2YgUGF1c2ggKDl0aCBtb250aClcbiAgICAgICAgLy8gSW4gMjA2NyBQYXVzaCBoYXMgMzBkYXlzLCBUaGlzIG1lYW5zICgzMC0xNysxPTE0KSB0aGVyZSBhcmUgMTRkYXlzIGJldHdlZW4gMXN0IEphbnVhcnkgYW5kIGVuZCBvZiBQYXVzaCBcbiAgICAgICAgLy8gKGluY2x1ZGluZyAxN3RoIEphbnVhcnkpXG4gICAgICAgIC8vIFRoZSBncmVnb3JpYW5EYXlPZlllYXIgKDM1KSBpcyBiaWdnZXIgdGhhbiAxNCwgc28gd2UgY2hlY2sgdGhlIG5leHQgbW9udGhcbiAgICAgICAgLy8gVGhlIG5leHQgbmVwYWxpIG1vbnRoIChNYW5naCkgaGFzIDI5IGRheXMgXG4gICAgICAgIC8vIDI5KzE0PTQzLCB0aGlzIGlzIGJpZ2dlciB0aGFuIGdyZWdvcmlhbkRheU9mWWVhcigzNSkgc28sIHdlIGZvdW5kIHRoZSBjb3JyZWN0IG5lcGFsaSBtb250aFxuICAgICAgICB3aGlsZSAoZ3JlZ29yaWFuRGF5T2ZZZWFyID4gZGF5c1NpbmNlSmFuRmlyc3RUb0VuZE9mTmVwYWxpTW9udGgpIHtcbiAgICAgICAgICAgIG5lcGFsaU1vbnRoKys7XG4gICAgICAgICAgICBpZiAobmVwYWxpTW9udGggPiAxMikge1xuICAgICAgICAgICAgICAgIG5lcGFsaU1vbnRoID0gMTtcbiAgICAgICAgICAgICAgICBuZXBhbGlZZWFyKys7XG4gICAgICAgICAgICB9ICAgIFxuICAgICAgICAgICAgZGF5c1NpbmNlSmFuRmlyc3RUb0VuZE9mTmVwYWxpTW9udGggKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyXVtuZXBhbGlNb250aF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIGxhc3Qgc3RlcCBpcyB0byBjYWxjdWxhdGUgdGhlIG5lcGFsaSBkYXktb2YtbW9udGhcbiAgICAgICAgLy8gdG8gY29udGludWUgb3VyIGV4YW1wbGUgZnJvbSBiZWZvcmU6XG4gICAgICAgIC8vIHdlIGNhbGN1bGF0ZWQgdGhlcmUgYXJlIDQzIGRheXMgZnJvbSAxc3QuIEphbnVhcnkgKDE3IFBhdXNoKSB0aWxsIGVuZCBvZiBNYW5naCAoMjkgZGF5cylcbiAgICAgICAgLy8gd2hlbiB3ZSBzdWJ0cmFjdCBmcm9tIHRoaXMgNDMgZGF5cyB0aGUgZGF5LW9mLXllYXIgb2YgdGhlIHRoZSBHcmVnb3JpYW4gZGF0ZSAoMzUpLFxuICAgICAgICAvLyB3ZSBrbm93IGhvdyBmYXIgdGhlIHNlYXJjaGVkIGRheSBpcyBhd2F5IGZyb20gdGhlIGVuZCBvZiB0aGUgTmVwYWxpIG1vbnRoLlxuICAgICAgICAvLyBTbyB3ZSBzaW1wbHkgc3VidHJhY3QgdGhpcyBudW1iZXIgZnJvbSB0aGUgYW1vdW50IG9mIGRheXMgaW4gdGhpcyBtb250aCAoMzApIFxuICAgICAgICB2YXIgbmVwYWxpRGF5T2ZNb250aCA9IHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bbmVwYWxpTW9udGhdIC1cbiAgICAgICAgICAgIChkYXlzU2luY2VKYW5GaXJzdFRvRW5kT2ZOZXBhbGlNb250aCAtIGdyZWdvcmlhbkRheU9mWWVhcik7ICAgICAgICBcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZShuZXBhbGlZZWFyLCBuZXBhbGlNb250aCwgbmVwYWxpRGF5T2ZNb250aCk7XG4gICAgfSxcbiAgICBcbiAgICAvKiogQ3JlYXRlcyBtaXNzaW5nIGRhdGEgaW4gdGhlIE5FUEFMSV9DQUxFTkRBUl9EQVRBIHRhYmxlLlxuICAgICAgICBUaGlzIGRhdGEgd2lsbCBub3QgYmUgY29ycmVjdCBidXQganVzdCBnaXZlIGFuIGVzdGltYXRlZCByZXN1bHQuIE1vc3RseSAtLysgMSBkYXlcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIG5lcGFsaVllYXIge251bWJlcn0gVGhlIG1pc3NpbmcgeWVhciBudW1iZXIuICovXG4gICAgX2NyZWF0ZU1pc3NpbmdDYWxlbmRhckRhdGE6IGZ1bmN0aW9uKG5lcGFsaVllYXIpIHtcbiAgICAgICAgdmFyIHRtcF9jYWxlbmRhcl9kYXRhID0gdGhpcy5kYXlzUGVyTW9udGguc2xpY2UoMCk7XG4gICAgICAgIHRtcF9jYWxlbmRhcl9kYXRhLnVuc2hpZnQoMTcpO1xuICAgICAgICBmb3IgKHZhciBuZXBhbGlZZWFyVG9DcmVhdGUgPSAobmVwYWxpWWVhciAtIDEpOyBuZXBhbGlZZWFyVG9DcmVhdGUgPCAobmVwYWxpWWVhciArIDIpOyBuZXBhbGlZZWFyVG9DcmVhdGUrKykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW25lcGFsaVllYXJUb0NyZWF0ZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DcmVhdGVdID0gdG1wX2NhbGVuZGFyX2RhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIFxuICAgIE5FUEFMSV9DQUxFTkRBUl9EQVRBOiAge1xuICAgICAgICAvLyBUaGVzZSBkYXRhIGFyZSBmcm9tIGh0dHA6Ly93d3cuYXNoZXNoLmNvbS5ucFxuICAgICAgICAxOTcwOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTcxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTcyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTczOiBbMTksIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTc0OiBbMTksIDMxLCAzMSwgMzIsIDMwLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc1OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMCwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTc3OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTc4OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc5OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTgxOiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgyOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgzOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTg1OiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg2OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg3OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg4OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTg5OiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTkwOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTkxOiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLCAgICBcbiAgICAgICAgLy8gVGhlc2UgZGF0YSBhcmUgZnJvbSBodHRwOi8vbmVwYWxpY2FsZW5kYXIucmF0MzIuY29tL2luZGV4LnBocFxuICAgICAgICAxOTkyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTkzOiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk0OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTk3OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk4OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDAwOiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDAxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDAyOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDAzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDA0OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDA1OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDA2OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDA3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDA4OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDA5OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDEwOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDExOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDEyOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDEzOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE0OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDE2OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE3OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE4OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDIwOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDI0OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI1OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDI3OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDI4OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI5OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDMwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzFdLFxuICAgICAgICAyMDMxOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDMxLCAzMSwgMzEsIDMxLCAzMSwgMzFdLFxuICAgICAgICAyMDMyOiBbMTcsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzJdLFxuICAgICAgICAyMDMzOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDM1OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDM2OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM3OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM4OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDM5OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQwOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQxOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDQzOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ0OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ1OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDQ3OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ4OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDUxOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUyOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDU0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDU1OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDMwLCAyOSwgMzBdLFxuICAgICAgICAyMDU2OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDU3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDU4OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDU5OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDYwOiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDYxOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDYyOiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDYzOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY0OiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDY2OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDY3OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY4OiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDcwOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDcxOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDcyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDczOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDc0OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc1OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc2OiBbMTYsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDc4OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc5OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDgwOiBbMTYsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAvLyBUaGVzZSBkYXRhIGFyZSBmcm9tIGh0dHA6Ly93d3cuYXNoZXNoLmNvbS5ucC9uZXBhbGktY2FsZW5kYXIvXG4gICAgICAgIDIwODE6IFsxNywgMzEsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODI6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODM6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODQ6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODU6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODY6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODc6IFsxNiwgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODg6IFsxNiwgMzAsIDMxLCAzMiwgMzIsIDMwLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODk6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTA6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTE6IFsxNiwgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTI6IFsxNiwgMzEsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTM6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTQ6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTU6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDI5LCAzMCwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTY6IFsxNywgMzAsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDI5LCAzMCwgMjksIDMwLCAzMF0sXG4gICAgICAgIDIwOTc6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTg6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMjksIDMwLCAyOSwgMzAsIDMwLCAzMV0sXG4gICAgICAgIDIwOTk6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDI5LCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIxMDA6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMwLCAzMSwgMzAsIDI5LCAzMCwgMjksIDMwLCAzMF0gICAgXG4gICAgfVxufSk7ICAgIFxuXG4vLyBOZXBhbGkgY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLm5lcGFsaSA9IE5lcGFsaUNhbGVuZGFyO1xuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIFBlcnNpYW4gY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBBdWd1c3QgMjAwOS5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSByZXF1aXJlKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgUGVyc2lhbiBvciBKYWxhbGkgY2FsZW5kYXIuXG4gICAgQmFzZWQgb24gY29kZSBmcm9tIDxhIGhyZWY9XCJodHRwOi8vd3d3LmlyYW5jaGFtYmVyLmNvbS9jYWxlbmRhci9jb252ZXJ0ZXIvaXJhbmlhbl9jYWxlbmRhcl9jb252ZXJ0ZXIucGhwXCI+aHR0cDovL3d3dy5pcmFuY2hhbWJlci5jb20vY2FsZW5kYXIvY29udmVydGVyL2lyYW5pYW5fY2FsZW5kYXJfY29udmVydGVyLnBocDwvYT4uXG4gICAgU2VlIGFsc28gPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXJhbmlhbl9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXJhbmlhbl9jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIFBlcnNpYW5DYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBQZXJzaWFuQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuUGVyc2lhbkNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKFBlcnNpYW5DYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnUGVyc2lhbicsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIFBlcnNpYW4gZXBvY2g6IDE5IE1hcmNoIDYyMiBDRS5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE5NDgzMjAuNSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAzMSwgMzEsIDMxLCAzMSwgMzEsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMjldLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ1BlcnNpYW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JQJywgJ0FQJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0ZhcnZhcmRpbicsICdPcmRpYmVoZXNodCcsICdLaG9yZGFkJywgJ1RpcicsICdNb3JkYWQnLCAnU2hhaHJpdmFyJyxcbiAgICAgICAgICAgICdNZWhyJywgJ0FiYW4nLCAnQXphcicsICdEYXknLCAnQmFobWFuJywgJ0VzZmFuZCddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0ZhcicsICdPcmQnLCAnS2hvJywgJ1RpcicsICdNb3InLCAnU2hhJywgJ01laCcsICdBYmEnLCAnQXphJywgJ0RheScsICdCYWgnLCAnRXNmJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydZZWtzaGFtYmUnLCAnRG9zaGFtYmUnLCAnU2VzaGFtYmUnLCAnQ2jDpmhhcnNoYW1iZScsICdQYW5qc2hhbWJlJywgJ0pvbVxcJ2UnLCAnU2hhbWJlJ10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1llaycsICdEbycsICdTZScsICdDaMOmJywgJ1BhbmonLCAnSm9tJywgJ1NoYSddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnWWUnLCdEbycsJ1NlJywnQ2gnLCdQYScsJ0pvJywnU2gnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiA2LFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAoKCgoKGRhdGUueWVhcigpIC0gKGRhdGUueWVhcigpID4gMCA/IDQ3NCA6IDQ3MykpICUgMjgyMCkgK1xuICAgICAgICAgICAgNDc0ICsgMzgpICogNjgyKSAlIDI4MTYpIDwgNjgyO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU2F0dXJkYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFNhdHVyZGF5XG4gICAgICAgIHZhciBjaGVja0RhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgIGNoZWNrRGF0ZS5hZGQoLSgoY2hlY2tEYXRlLmRheU9mV2VlaygpICsgMSkgJSA3KSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdICtcbiAgICAgICAgICAgIChkYXRlLm1vbnRoKCkgPT09IDEyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KSAhPT0gNTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIG1vbnRoID0gZGF0ZS5tb250aCgpO1xuICAgICAgICBkYXkgPSBkYXRlLmRheSgpO1xuICAgICAgICB2YXIgZXBCYXNlID0geWVhciAtICh5ZWFyID49IDAgPyA0NzQgOiA0NzMpO1xuICAgICAgICB2YXIgZXBZZWFyID0gNDc0ICsgbW9kKGVwQmFzZSwgMjgyMCk7XG4gICAgICAgIHJldHVybiBkYXkgKyAobW9udGggPD0gNyA/IChtb250aCAtIDEpICogMzEgOiAobW9udGggLSAxKSAqIDMwICsgNikgK1xuICAgICAgICAgICAgTWF0aC5mbG9vcigoZXBZZWFyICogNjgyIC0gMTEwKSAvIDI4MTYpICsgKGVwWWVhciAtIDEpICogMzY1ICtcbiAgICAgICAgICAgIE1hdGguZmxvb3IoZXBCYXNlIC8gMjgyMCkgKiAxMDI5OTgzICsgdGhpcy5qZEVwb2NoIC0gMTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkKSArIDAuNTtcbiAgICAgICAgdmFyIGRlcG9jaCA9IGpkIC0gdGhpcy50b0pEKDQ3NSwgMSwgMSk7XG4gICAgICAgIHZhciBjeWNsZSA9IE1hdGguZmxvb3IoZGVwb2NoIC8gMTAyOTk4Myk7XG4gICAgICAgIHZhciBjeWVhciA9IG1vZChkZXBvY2gsIDEwMjk5ODMpO1xuICAgICAgICB2YXIgeWN5Y2xlID0gMjgyMDtcbiAgICAgICAgaWYgKGN5ZWFyICE9PSAxMDI5OTgyKSB7XG4gICAgICAgICAgICB2YXIgYXV4MSA9IE1hdGguZmxvb3IoY3llYXIgLyAzNjYpO1xuICAgICAgICAgICAgdmFyIGF1eDIgPSBtb2QoY3llYXIsIDM2Nik7XG4gICAgICAgICAgICB5Y3ljbGUgPSBNYXRoLmZsb29yKCgoMjEzNCAqIGF1eDEpICsgKDI4MTYgKiBhdXgyKSArIDI4MTUpIC8gMTAyODUyMikgKyBhdXgxICsgMTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgeWVhciA9IHljeWNsZSArICgyODIwICogY3ljbGUpICsgNDc0O1xuICAgICAgICB5ZWFyID0gKHllYXIgPD0gMCA/IHllYXIgLSAxIDogeWVhcik7XG4gICAgICAgIHZhciB5ZGF5ID0gamQgLSB0aGlzLnRvSkQoeWVhciwgMSwgMSkgKyAxO1xuICAgICAgICB2YXIgbW9udGggPSAoeWRheSA8PSAxODYgPyBNYXRoLmNlaWwoeWRheSAvIDMxKSA6IE1hdGguY2VpbCgoeWRheSAtIDYpIC8gMzApKTtcbiAgICAgICAgdmFyIGRheSA9IGpkIC0gdGhpcy50b0pEKHllYXIsIG1vbnRoLCAxKSArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIE1vZHVsdXMgZnVuY3Rpb24gd2hpY2ggd29ya3MgZm9yIG5vbi1pbnRlZ2Vycy5cbmZ1bmN0aW9uIG1vZChhLCBiKSB7XG4gICAgcmV0dXJuIGEgLSAoYiAqIE1hdGguZmxvb3IoYSAvIGIpKTtcbn1cblxuLy8gUGVyc2lhbiAoSmFsYWxpKSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMucGVyc2lhbiA9IFBlcnNpYW5DYWxlbmRhcjtcbm1haW4uY2FsZW5kYXJzLmphbGFsaSA9IFBlcnNpYW5DYWxlbmRhcjtcblxuIiwiLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBUYWl3YW5lc2UgKE1pbmd1bykgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBGZWJydWFyeSAyMDEwLlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxudmFyIGdyZWdvcmlhbkNhbGVuZGFyID0gbWFpbi5pbnN0YW5jZSgpO1xuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIFRhaXdhbmVzZSBjYWxlbmRhci5cbiAgICBTZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NaW5ndW9fY2FsZW5kYXIuXG4gICAgQGNsYXNzIFRhaXdhbkNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIFRhaXdhbkNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cblRhaXdhbkNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKFRhaXdhbkNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyICovXG4gICAgbmFtZTogJ1RhaXdhbicsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIFRhaXdhbiBlcG9jaDogMSBKYW51YXJ5IDE5MTIgQ0UgKEdyZWdvcmlhbikuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDI0MTk0MDIuNSxcbiAgICAvKiogRGlmZmVyZW5jZSBpbiB5ZWFycyBiZXR3ZWVuIFRhaXdhbiBhbmQgR3JlZ29yaWFuIGNhbGVuZGFycy5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyICovXG4gICAgeWVhcnNPZmZzZXQ6IDE5MTEsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAyOCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdUYWl3YW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JST0MnLCAnUk9DJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0phbnVhcnknLCAnRmVicnVhcnknLCAnTWFyY2gnLCAnQXByaWwnLCAnTWF5JywgJ0p1bmUnLFxuICAgICAgICAgICAgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLCAnT2N0JywgJ05vdicsICdEZWMnXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnU3UnLCAnTW8nLCAnVHUnLCAnV2UnLCAnVGgnLCAnRnInLCAnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAxLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl90MmdZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLmxlYXBZZWFyKHllYXIpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUgLSBJU08gODYwMS5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl90MmdZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLndlZWtPZlllYXIoeWVhciwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdICtcbiAgICAgICAgICAgIChkYXRlLm1vbnRoKCkgPT09IDIgJiYgdGhpcy5sZWFwWWVhcihkYXRlLnllYXIoKSkgPyAxIDogMCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHx8IDcpIDwgNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdDJnWWVhcihkYXRlLnllYXIoKSk7XG4gICAgICAgIHJldHVybiBncmVnb3JpYW5DYWxlbmRhci50b0pEKHllYXIsIGRhdGUubW9udGgoKSwgZGF0ZS5kYXkoKSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgdmFyIGRhdGUgPSBncmVnb3JpYW5DYWxlbmRhci5mcm9tSkQoamQpO1xuICAgICAgICB2YXIgeWVhciA9IHRoaXMuX2cydFllYXIoZGF0ZS55ZWFyKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIGRhdGUubW9udGgoKSwgZGF0ZS5kYXkoKSk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IFRhaXdhbmVzZSB0byBHcmVnb3JpYW4geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSBUYWl3YW5lc2UgeWVhci5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgY29ycmVzcG9uZGluZyBHcmVnb3JpYW4geWVhci4gKi9cbiAgICBfdDJnWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4geWVhciArIHRoaXMueWVhcnNPZmZzZXQgKyAoeWVhciA+PSAtdGhpcy55ZWFyc09mZnNldCAmJiB5ZWFyIDw9IC0xID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCBHcmVnb3JpYW4gdG8gVGFpd2FuZXNlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgR3JlZ29yaWFuIHllYXIuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGNvcnJlc3BvbmRpbmcgVGFpd2FuZXNlIHllYXIuICovXG4gICAgX2cydFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgcmV0dXJuIHllYXIgLSB0aGlzLnllYXJzT2Zmc2V0IC0gKHllYXIgPj0gMSAmJiB5ZWFyIDw9IHRoaXMueWVhcnNPZmZzZXQgPyAxIDogMCk7XG4gICAgfVxufSk7XG5cbi8vIFRhaXdhbiBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMudGFpd2FuID0gVGFpd2FuQ2FsZW5kYXI7XG5cbiIsIi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgVGhhaSBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEZlYnJ1YXJ5IDIwMTAuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gcmVxdWlyZSgnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IHJlcXVpcmUoJ29iamVjdC1hc3NpZ24nKTtcblxuXG52YXIgZ3JlZ29yaWFuQ2FsZW5kYXIgPSBtYWluLmluc3RhbmNlKCk7XG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVGhhaSBjYWxlbmRhci5cbiAgICBTZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UaGFpX2NhbGVuZGFyLlxuICAgIEBjbGFzcyBUaGFpQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gVGhhaUNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cblRoYWlDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihUaGFpQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyICovXG4gICAgbmFtZTogJ1RoYWknLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBUaGFpIGVwb2NoOiAxIEphbnVhcnkgNTQzIEJDRSAoR3JlZ29yaWFuKS5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE1MjMwOTguNSxcbiAgICAvKiogRGlmZmVyZW5jZSBpbiB5ZWFycyBiZXR3ZWVuIFRoYWkgYW5kIEdyZWdvcmlhbiBjYWxlbmRhcnMuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICB5ZWFyc09mZnNldDogNTQzLCBcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAyOCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ1RoYWknLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JCRScsICdCRSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnZGQvbW0veXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB2YXIgeWVhciA9IHRoaXMuX3QyZ1llYXIoZGF0ZS55ZWFyKCkpO1xuICAgICAgICByZXR1cm4gZ3JlZ29yaWFuQ2FsZW5kYXIubGVhcFllYXIoeWVhcik7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl90MmdZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLndlZWtPZlllYXIoeWVhciwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdDJnWWVhcihkYXRlLnllYXIoKSk7XG4gICAgICAgIHJldHVybiBncmVnb3JpYW5DYWxlbmRhci50b0pEKHllYXIsIGRhdGUubW9udGgoKSwgZGF0ZS5kYXkoKSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBkYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl9nMnRZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBkYXRlLm1vbnRoKCksIGRhdGUuZGF5KCkpO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCBUaGFpIHRvIEdyZWdvcmlhbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSBUaGFpIHllYXIuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGNvcnJlc3BvbmRpbmcgR3JlZ29yaWFuIHllYXIuICovXG4gICAgX3QyZ1llYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgcmV0dXJuIHllYXIgLSB0aGlzLnllYXJzT2Zmc2V0IC0gKHllYXIgPj0gMSAmJiB5ZWFyIDw9IHRoaXMueWVhcnNPZmZzZXQgPyAxIDogMCk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IEdyZWdvcmlhbiB0byBUaGFpIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIEdyZWdvcmlhbiB5ZWFyLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBjb3JyZXNwb25kaW5nIFRoYWkgeWVhci4gKi9cbiAgICBfZzJ0WWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4geWVhciArIHRoaXMueWVhcnNPZmZzZXQgKyAoeWVhciA+PSAtdGhpcy55ZWFyc09mZnNldCAmJiB5ZWFyIDw9IC0xID8gMSA6IDApO1xuICAgIH1cbn0pO1xuXG4vLyBUaGFpIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy50aGFpID0gVGhhaUNhbGVuZGFyO1xuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIFVtbUFsUXVyYSBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgQW1ybyBPc2FtYSBNYXJjaCAyMDEzLlxuICAgTW9kaWZpZWQgYnkgQmlubm9vaC5jb20gJiB3d3cuZWxtLnNhIC0gMjAxNCAtIEFkZGVkIGRhdGVzIGJhY2sgdG8gMTI3NiBIaWpyaSB5ZWFyLlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBVbW1BbFF1cmEgb3IgJ3NhdWRpJyBjYWxlbmRhci5cbiAgICBTZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Jc2xhbWljX2NhbGVuZGFyI1NhdWRpX0FyYWJpYS4yN3NfVW1tX2FsLVF1cmFfY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lzbGFtaWNfY2FsZW5kYXIjU2F1ZGlfQXJhYmlhLjI3c19VbW1fYWwtUXVyYV9jYWxlbmRhcjwvYT4uXG4gICAgPGEgaHJlZj1cImh0dHA6Ly93d3cudW1tdWxxdXJhLm9yZy5zYS9BYm91dC5hc3B4XCI+aHR0cDovL3d3dy51bW11bHF1cmEub3JnLnNhL0Fib3V0LmFzcHg8L2E+XG4gICAgPGEgaHJlZj1cImh0dHA6Ly93d3cuc3RhZmYuc2NpZW5jZS51dS5ubC9+Z2VudDAxMTMvaXNsYW0vdW1tYWxxdXJhLmh0bVwiPmh0dHA6Ly93d3cuc3RhZmYuc2NpZW5jZS51dS5ubC9+Z2VudDAxMTMvaXNsYW0vdW1tYWxxdXJhLmh0bTwvYT5cbiAgICBAY2xhc3MgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gVW1tQWxRdXJhQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuVW1tQWxRdXJhQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IG1haW4uYmFzZUNhbGVuZGFyO1xuXG5hc3NpZ24oVW1tQWxRdXJhQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnVW1tQWxRdXJhJyxcbiAgICAvL2pkRXBvY2g6IDE5NDg0NDAsIC8vIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIFVtbUFsUXVyYSBlcG9jaDogMTQgTWFyY2ggMTkzNyBDRVxuICAgIC8vZGF5c1Blck1vbnRoOiAvLyBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLCByZXBsYWNlZCBieSBhIG1ldGhvZC5cbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnVW1tIGFsLVF1cmEnLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JIJywgJ0FIJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0FsLU11aGFycmFtJywgJ1NhZmFyJywgJ1JhYmlcXCcgYWwtYXd3YWwnLCAnUmFiaVxcJyBBbC1UaGFuaScsICdKdW1hZGEgQWwtQXd3YWwnLCAnSnVtYWRhIEFsLVRoYW5pJyxcbiAgICAgICAgICAgICdSYWphYicsICdTaGFcXCdhYmFuJywgJ1JhbWFkYW4nLCAnU2hhd3dhbCcsICdEaHUgYWwtUWlcXCdkYWgnLCAnRGh1IGFsLUhpamphaCddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ011aCcsICdTYWYnLCAnUmFiMScsICdSYWIyJywgJ0p1bTEnLCAnSnVtMicsICdSYWonLCAnU2hhXFwnJywgJ1JhbScsICdTaGF3JywgJ0RodVEnLCAnRGh1SCddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnWWF3bSBhbC1BaGFkJywgJ1lhd20gYWwtSXRobmFpbicsICdZYXdtIGFsLVRoYWzEgXRoxIHigJknLCAnWWF3bSBhbC1BcmJh4oCYxIHigJknLCAnWWF3bSBhbC1LaGFtxKtzJywgJ1lhd20gYWwtSnVt4oCYYScsICdZYXdtIGFsLVNhYnQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ0FoJywgJ0l0aCcsICdUaCcsICdBcicsICdLaCcsICdKdScsICdTYSddLFxuICAgICAgICAgICAgZGlnaXRzOiBudWxsLFxuICAgICAgICAgICAgZGF0ZUZvcm1hdDogJ3l5eXkvbW0vZGQnLFxuICAgICAgICAgICAgZmlyc3REYXk6IDYsXG4gICAgICAgICAgICBpc1JUTDogdHJ1ZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uICh5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5c0luWWVhcihkYXRlLnllYXIoKSkgPT09IDM1NSk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24gKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uICh5ZWFyKSB7XG4gICAgICAgIHZhciBkYXlzQ291bnQgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSAxMjsgaSsrKSB7XG4gICAgICAgICAgICBkYXlzQ291bnQgKz0gdGhpcy5kYXlzSW5Nb250aCh5ZWFyLCBpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF5c0NvdW50O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbiAoeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgdmFyIG1jamRuID0gZGF0ZS50b0pEKCkgLSAyNDAwMDAwICsgMC41OyAvLyBNb2RpZmllZCBDaHJvbm9sb2dpY2FsIEp1bGlhbiBEYXkgTnVtYmVyIChNQ0pETilcbiAgICAgICAgLy8gdGhlIE1DSkROJ3Mgb2YgdGhlIHN0YXJ0IG9mIHRoZSBsdW5hdGlvbnMgaW4gdGhlIFVtbSBhbC1RdXJhIGNhbGVuZGFyIGFyZSBzdG9yZWQgaW4gdGhlICd1bW1hbHF1cmFfZGF0JyBhcnJheVxuICAgICAgICB2YXIgaW5kZXggPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVtbWFscXVyYV9kYXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh1bW1hbHF1cmFfZGF0W2ldID4gbWNqZG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHVtbWFscXVyYV9kYXRbaW5kZXhdIC0gdW1tYWxxdXJhX2RhdFtpbmRleCAtIDFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDMwOyAvLyBVbmtub3duIG91dHNpZGVcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbiAoeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgIT09IDU7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24gKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgdmFyIGluZGV4ID0gKDEyICogKGRhdGUueWVhcigpIC0gMSkpICsgZGF0ZS5tb250aCgpIC0gMTUyOTI7XG4gICAgICAgIHZhciBtY2pkbiA9IGRhdGUuZGF5KCkgKyB1bW1hbHF1cmFfZGF0W2luZGV4IC0gMV0gLSAxO1xuICAgICAgICByZXR1cm4gbWNqZG4gKyAyNDAwMDAwIC0gMC41OyAvLyBNb2RpZmllZCBDaHJvbm9sb2dpY2FsIEp1bGlhbiBEYXkgTnVtYmVyIChNQ0pETilcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbiAoamQpIHtcbiAgICAgICAgdmFyIG1jamRuID0gamQgLSAyNDAwMDAwICsgMC41OyAvLyBNb2RpZmllZCBDaHJvbm9sb2dpY2FsIEp1bGlhbiBEYXkgTnVtYmVyIChNQ0pETilcbiAgICAgICAgLy8gdGhlIE1DSkROJ3Mgb2YgdGhlIHN0YXJ0IG9mIHRoZSBsdW5hdGlvbnMgaW4gdGhlIFVtbSBhbC1RdXJhIGNhbGVuZGFyIFxuICAgICAgICAvLyBhcmUgc3RvcmVkIGluIHRoZSAndW1tYWxxdXJhX2RhdCcgYXJyYXlcbiAgICAgICAgdmFyIGluZGV4ID0gMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1bW1hbHF1cmFfZGF0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodW1tYWxxdXJhX2RhdFtpXSA+IG1jamRuKSBicmVhaztcbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGx1bmF0aW9uID0gaW5kZXggKyAxNTI5MjsgLy9VbW1BbFF1cmEgTHVuYXRpb24gTnVtYmVyXG4gICAgICAgIHZhciBpaSA9IE1hdGguZmxvb3IoKGx1bmF0aW9uIC0gMSkgLyAxMik7XG4gICAgICAgIHZhciB5ZWFyID0gaWkgKyAxO1xuICAgICAgICB2YXIgbW9udGggPSBsdW5hdGlvbiAtIDEyICogaWk7XG4gICAgICAgIHZhciBkYXkgPSBtY2pkbiAtIHVtbWFscXVyYV9kYXRbaW5kZXggLSAxXSArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciBhIGRhdGUgaXMgdmFsaWQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBkYXkge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHZhbGlkIGRhdGUsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuICovXG4gICAgaXNWYWxpZDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgdmFsaWQgPSBtYWluLmJhc2VDYWxlbmRhci5wcm90b3R5cGUuaXNWYWxpZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgICAgIHllYXIgPSAoeWVhci55ZWFyICE9IG51bGwgPyB5ZWFyLnllYXIgOiB5ZWFyKTtcbiAgICAgICAgICAgIHZhbGlkID0gKHllYXIgPj0gMTI3NiAmJiB5ZWFyIDw9IDE1MDApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWxpZDtcbiAgICB9LFxuXG4gICAgLyoqIENoZWNrIHRoYXQgYSBjYW5kaWRhdGUgZGF0ZSBpcyBmcm9tIHRoZSBzYW1lIGNhbGVuZGFyIGFuZCBpcyB2YWxpZC5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIHZhbGlkYXRlIG9yIHRoZSB5ZWFyIHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gZGF5IHtudW1iZXJ9IFRoZSBkYXkgdG8gdmFsaWRhdGUuXG4gICAgICAgIEBwYXJhbSBlcnJvciB7c3RyaW5nfSBFcnJvciBtZXNzYWdlIGlmIGludmFsaWQuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgZGlmZmVyZW50IGNhbGVuZGFycyB1c2VkIG9yIGludmFsaWQgZGF0ZS4gKi9cbiAgICBfdmFsaWRhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXksIGVycm9yKSB7XG4gICAgICAgIHZhciBkYXRlID0gbWFpbi5iYXNlQ2FsZW5kYXIucHJvdG90eXBlLl92YWxpZGF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICBpZiAoZGF0ZS55ZWFyIDwgMTI3NiB8fCBkYXRlLnllYXIgPiAxNTAwKSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvci5yZXBsYWNlKC9cXHswXFx9LywgdGhpcy5sb2NhbC5uYW1lKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG59KTtcblxuLy8gVW1tQWxRdXJhIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy51bW1hbHF1cmEgPSBVbW1BbFF1cmFDYWxlbmRhcjtcblxudmFyIHVtbWFscXVyYV9kYXQgPSBbXG4gICAgMjAsICAgIDUwLCAgICA3OSwgICAgMTA5LCAgIDEzOCwgICAxNjgsICAgMTk3LCAgIDIyNywgICAyNTYsICAgMjg2LCAgIDMxNSwgICAzNDUsICAgMzc0LCAgIDQwNCwgICA0MzMsICAgNDYzLCAgIDQ5MiwgICA1MjIsICAgNTUxLCAgIDU4MSwgXG4gICAgNjExLCAgIDY0MSwgICA2NzAsICAgNzAwLCAgIDcyOSwgICA3NTksICAgNzg4LCAgIDgxOCwgICA4NDcsICAgODc3LCAgIDkwNiwgICA5MzYsICAgOTY1LCAgIDk5NSwgICAxMDI0LCAgMTA1NCwgIDEwODMsICAxMTEzLCAgMTE0MiwgIDExNzIsXG4gICAgMTIwMSwgIDEyMzEsICAxMjYwLCAgMTI5MCwgIDEzMjAsICAxMzUwLCAgMTM3OSwgIDE0MDksICAxNDM4LCAgMTQ2OCwgIDE0OTcsICAxNTI3LCAgMTU1NiwgIDE1ODYsICAxNjE1LCAgMTY0NSwgIDE2NzQsICAxNzA0LCAgMTczMywgIDE3NjMsXG4gICAgMTc5MiwgIDE4MjIsICAxODUxLCAgMTg4MSwgIDE5MTAsICAxOTQwLCAgMTk2OSwgIDE5OTksICAyMDI4LCAgMjA1OCwgIDIwODcsICAyMTE3LCAgMjE0NiwgIDIxNzYsICAyMjA1LCAgMjIzNSwgIDIyNjQsICAyMjk0LCAgMjMyMywgIDIzNTMsXG4gICAgMjM4MywgIDI0MTMsICAyNDQyLCAgMjQ3MiwgIDI1MDEsICAyNTMxLCAgMjU2MCwgIDI1OTAsICAyNjE5LCAgMjY0OSwgIDI2NzgsICAyNzA4LCAgMjczNywgIDI3NjcsICAyNzk2LCAgMjgyNiwgIDI4NTUsICAyODg1LCAgMjkxNCwgIDI5NDQsXG4gICAgMjk3MywgIDMwMDMsICAzMDMyLCAgMzA2MiwgIDMwOTEsICAzMTIxLCAgMzE1MCwgIDMxODAsICAzMjA5LCAgMzIzOSwgIDMyNjgsICAzMjk4LCAgMzMyNywgIDMzNTcsICAzMzg2LCAgMzQxNiwgIDM0NDYsICAzNDc2LCAgMzUwNSwgIDM1MzUsXG4gICAgMzU2NCwgIDM1OTQsICAzNjIzLCAgMzY1MywgIDM2ODIsICAzNzEyLCAgMzc0MSwgIDM3NzEsICAzODAwLCAgMzgzMCwgIDM4NTksICAzODg5LCAgMzkxOCwgIDM5NDgsICAzOTc3LCAgNDAwNywgIDQwMzYsICA0MDY2LCAgNDA5NSwgIDQxMjUsXG4gICAgNDE1NSwgIDQxODUsICA0MjE0LCAgNDI0NCwgIDQyNzMsICA0MzAzLCAgNDMzMiwgIDQzNjIsICA0MzkxLCAgNDQyMSwgIDQ0NTAsICA0NDgwLCAgNDUwOSwgIDQ1MzksICA0NTY4LCAgNDU5OCwgIDQ2MjcsICA0NjU3LCAgNDY4NiwgIDQ3MTYsXG4gICAgNDc0NSwgIDQ3NzUsICA0ODA0LCAgNDgzNCwgIDQ4NjMsICA0ODkzLCAgNDkyMiwgIDQ5NTIsICA0OTgxLCAgNTAxMSwgIDUwNDAsICA1MDcwLCAgNTA5OSwgIDUxMjksICA1MTU4LCAgNTE4OCwgIDUyMTgsICA1MjQ4LCAgNTI3NywgIDUzMDcsXG4gICAgNTMzNiwgIDUzNjYsICA1Mzk1LCAgNTQyNSwgIDU0NTQsICA1NDg0LCAgNTUxMywgIDU1NDMsICA1NTcyLCAgNTYwMiwgIDU2MzEsICA1NjYxLCAgNTY5MCwgIDU3MjAsICA1NzQ5LCAgNTc3OSwgIDU4MDgsICA1ODM4LCAgNTg2NywgIDU4OTcsXG4gICAgNTkyNiwgIDU5NTYsICA1OTg1LCAgNjAxNSwgIDYwNDQsICA2MDc0LCAgNjEwMywgIDYxMzMsICA2MTYyLCAgNjE5MiwgIDYyMjEsICA2MjUxLCAgNjI4MSwgIDYzMTEsICA2MzQwLCAgNjM3MCwgIDYzOTksICA2NDI5LCAgNjQ1OCwgIDY0ODgsXG4gICAgNjUxNywgIDY1NDcsICA2NTc2LCAgNjYwNiwgIDY2MzUsICA2NjY1LCAgNjY5NCwgIDY3MjQsICA2NzUzLCAgNjc4MywgIDY4MTIsICA2ODQyLCAgNjg3MSwgIDY5MDEsICA2OTMwLCAgNjk2MCwgIDY5ODksICA3MDE5LCAgNzA0OCwgIDcwNzgsXG4gICAgNzEwNywgIDcxMzcsICA3MTY2LCAgNzE5NiwgIDcyMjUsICA3MjU1LCAgNzI4NCwgIDczMTQsICA3MzQ0LCAgNzM3NCwgIDc0MDMsICA3NDMzLCAgNzQ2MiwgIDc0OTIsICA3NTIxLCAgNzU1MSwgIDc1ODAsICA3NjEwLCAgNzYzOSwgIDc2NjksXG4gICAgNzY5OCwgIDc3MjgsICA3NzU3LCAgNzc4NywgIDc4MTYsICA3ODQ2LCAgNzg3NSwgIDc5MDUsICA3OTM0LCAgNzk2NCwgIDc5OTMsICA4MDIzLCAgODA1MywgIDgwODMsICA4MTEyLCAgODE0MiwgIDgxNzEsICA4MjAxLCAgODIzMCwgIDgyNjAsXG4gICAgODI4OSwgIDgzMTksICA4MzQ4LCAgODM3OCwgIDg0MDcsICA4NDM3LCAgODQ2NiwgIDg0OTYsICA4NTI1LCAgODU1NSwgIDg1ODQsICA4NjE0LCAgODY0MywgIDg2NzMsICA4NzAyLCAgODczMiwgIDg3NjEsICA4NzkxLCAgODgyMSwgIDg4NTAsXG4gICAgODg4MCwgIDg5MDksICA4OTM4LCAgODk2OCwgIDg5OTcsICA5MDI3LCAgOTA1NiwgIDkwODYsICA5MTE1LCAgOTE0NSwgIDkxNzUsICA5MjA1LCAgOTIzNCwgIDkyNjQsICA5MjkzLCAgOTMyMiwgIDkzNTIsICA5MzgxLCAgOTQxMCwgIDk0NDAsXG4gICAgOTQ3MCwgIDk0OTksICA5NTI5LCAgOTU1OSwgIDk1ODksICA5NjE4LCAgOTY0OCwgIDk2NzcsICA5NzA2LCAgOTczNiwgIDk3NjUsICA5Nzk0LCAgOTgyNCwgIDk4NTMsICA5ODgzLCAgOTkxMywgIDk5NDMsICA5OTcyLCAgMTAwMDIsIDEwMDMyLFxuICAgIDEwMDYxLCAxMDA5MCwgMTAxMjAsIDEwMTQ5LCAxMDE3OCwgMTAyMDgsIDEwMjM3LCAxMDI2NywgMTAyOTcsIDEwMzI2LCAxMDM1NiwgMTAzODYsIDEwNDE1LCAxMDQ0NSwgMTA0NzQsIDEwNTA0LCAxMDUzMywgMTA1NjIsIDEwNTkyLCAxMDYyMSxcbiAgICAxMDY1MSwgMTA2ODAsIDEwNzEwLCAxMDc0MCwgMTA3NzAsIDEwNzk5LCAxMDgyOSwgMTA4NTgsIDEwODg4LCAxMDkxNywgMTA5NDcsIDEwOTc2LCAxMTAwNSwgMTEwMzUsIDExMDY0LCAxMTA5NCwgMTExMjQsIDExMTUzLCAxMTE4MywgMTEyMTMsXG4gICAgMTEyNDIsIDExMjcyLCAxMTMwMSwgMTEzMzEsIDExMzYwLCAxMTM4OSwgMTE0MTksIDExNDQ4LCAxMTQ3OCwgMTE1MDcsIDExNTM3LCAxMTU2NywgMTE1OTYsIDExNjI2LCAxMTY1NSwgMTE2ODUsIDExNzE1LCAxMTc0NCwgMTE3NzQsIDExODAzLFxuICAgIDExODMyLCAxMTg2MiwgMTE4OTEsIDExOTIxLCAxMTk1MCwgMTE5ODAsIDEyMDEwLCAxMjAzOSwgMTIwNjksIDEyMDk5LCAxMjEyOCwgMTIxNTgsIDEyMTg3LCAxMjIxNiwgMTIyNDYsIDEyMjc1LCAxMjMwNCwgMTIzMzQsIDEyMzY0LCAxMjM5MyxcbiAgICAxMjQyMywgMTI0NTMsIDEyNDgzLCAxMjUxMiwgMTI1NDIsIDEyNTcxLCAxMjYwMCwgMTI2MzAsIDEyNjU5LCAxMjY4OCwgMTI3MTgsIDEyNzQ3LCAxMjc3NywgMTI4MDcsIDEyODM3LCAxMjg2NiwgMTI4OTYsIDEyOTI2LCAxMjk1NSwgMTI5ODQsXG4gICAgMTMwMTQsIDEzMDQzLCAxMzA3MiwgMTMxMDIsIDEzMTMxLCAxMzE2MSwgMTMxOTEsIDEzMjIwLCAxMzI1MCwgMTMyODAsIDEzMzEwLCAxMzMzOSwgMTMzNjgsIDEzMzk4LCAxMzQyNywgMTM0NTYsIDEzNDg2LCAxMzUxNSwgMTM1NDUsIDEzNTc0LFxuICAgIDEzNjA0LCAxMzYzNCwgMTM2NjQsIDEzNjkzLCAxMzcyMywgMTM3NTIsIDEzNzgyLCAxMzgxMSwgMTM4NDAsIDEzODcwLCAxMzg5OSwgMTM5MjksIDEzOTU4LCAxMzk4OCwgMTQwMTgsIDE0MDQ3LCAxNDA3NywgMTQxMDcsIDE0MTM2LCAxNDE2NixcbiAgICAxNDE5NSwgMTQyMjQsIDE0MjU0LCAxNDI4MywgMTQzMTMsIDE0MzQyLCAxNDM3MiwgMTQ0MDEsIDE0NDMxLCAxNDQ2MSwgMTQ0OTAsIDE0NTIwLCAxNDU1MCwgMTQ1NzksIDE0NjA5LCAxNDYzOCwgMTQ2NjcsIDE0Njk3LCAxNDcyNiwgMTQ3NTYsXG4gICAgMTQ3ODUsIDE0ODE1LCAxNDg0NCwgMTQ4NzQsIDE0OTA0LCAxNDkzMywgMTQ5NjMsIDE0OTkzLCAxNTAyMSwgMTUwNTEsIDE1MDgxLCAxNTExMCwgMTUxNDAsIDE1MTY5LCAxNTE5OSwgMTUyMjgsIDE1MjU4LCAxNTI4NywgMTUzMTcsIDE1MzQ3LFxuICAgIDE1Mzc3LCAxNTQwNiwgMTU0MzYsIDE1NDY1LCAxNTQ5NCwgMTU1MjQsIDE1NTUzLCAxNTU4MiwgMTU2MTIsIDE1NjQxLCAxNTY3MSwgMTU3MDEsIDE1NzMxLCAxNTc2MCwgMTU3OTAsIDE1ODIwLCAxNTg0OSwgMTU4NzgsIDE1OTA4LCAxNTkzNyxcbiAgICAxNTk2NiwgMTU5OTYsIDE2MDI1LCAxNjA1NSwgMTYwODUsIDE2MTE0LCAxNjE0NCwgMTYxNzQsIDE2MjA0LCAxNjIzMywgMTYyNjIsIDE2MjkyLCAxNjMyMSwgMTYzNTAsIDE2MzgwLCAxNjQwOSwgMTY0MzksIDE2NDY4LCAxNjQ5OCwgMTY1MjgsXG4gICAgMTY1NTgsIDE2NTg3LCAxNjYxNywgMTY2NDYsIDE2Njc2LCAxNjcwNSwgMTY3MzQsIDE2NzY0LCAxNjc5MywgMTY4MjMsIDE2ODUyLCAxNjg4MiwgMTY5MTIsIDE2OTQxLCAxNjk3MSwgMTcwMDEsIDE3MDMwLCAxNzA2MCwgMTcwODksIDE3MTE4LFxuICAgIDE3MTQ4LCAxNzE3NywgMTcyMDcsIDE3MjM2LCAxNzI2NiwgMTcyOTUsIDE3MzI1LCAxNzM1NSwgMTczODQsIDE3NDE0LCAxNzQ0NCwgMTc0NzMsIDE3NTAyLCAxNzUzMiwgMTc1NjEsIDE3NTkxLCAxNzYyMCwgMTc2NTAsIDE3Njc5LCAxNzcwOSxcbiAgICAxNzczOCwgMTc3NjgsIDE3Nzk4LCAxNzgyNywgMTc4NTcsIDE3ODg2LCAxNzkxNiwgMTc5NDUsIDE3OTc1LCAxODAwNCwgMTgwMzQsIDE4MDYzLCAxODA5MywgMTgxMjIsIDE4MTUyLCAxODE4MSwgMTgyMTEsIDE4MjQxLCAxODI3MCwgMTgzMDAsXG4gICAgMTgzMzAsIDE4MzU5LCAxODM4OCwgMTg0MTgsIDE4NDQ3LCAxODQ3NiwgMTg1MDYsIDE4NTM1LCAxODU2NSwgMTg1OTUsIDE4NjI1LCAxODY1NCwgMTg2ODQsIDE4NzE0LCAxODc0MywgMTg3NzIsIDE4ODAyLCAxODgzMSwgMTg4NjAsIDE4ODkwLFxuICAgIDE4OTE5LCAxODk0OSwgMTg5NzksIDE5MDA4LCAxOTAzOCwgMTkwNjgsIDE5MDk4LCAxOTEyNywgMTkxNTYsIDE5MTg2LCAxOTIxNSwgMTkyNDQsIDE5Mjc0LCAxOTMwMywgMTkzMzMsIDE5MzYyLCAxOTM5MiwgMTk0MjIsIDE5NDUyLCAxOTQ4MSxcbiAgICAxOTUxMSwgMTk1NDAsIDE5NTcwLCAxOTU5OSwgMTk2MjgsIDE5NjU4LCAxOTY4NywgMTk3MTcsIDE5NzQ2LCAxOTc3NiwgMTk4MDYsIDE5ODM2LCAxOTg2NSwgMTk4OTUsIDE5OTI0LCAxOTk1NCwgMTk5ODMsIDIwMDEyLCAyMDA0MiwgMjAwNzEsXG4gICAgMjAxMDEsIDIwMTMwLCAyMDE2MCwgMjAxOTAsIDIwMjE5LCAyMDI0OSwgMjAyNzksIDIwMzA4LCAyMDMzOCwgMjAzNjcsIDIwMzk2LCAyMDQyNiwgMjA0NTUsIDIwNDg1LCAyMDUxNCwgMjA1NDQsIDIwNTczLCAyMDYwMywgMjA2MzMsIDIwNjYyLFxuICAgIDIwNjkyLCAyMDcyMSwgMjA3NTEsIDIwNzgwLCAyMDgxMCwgMjA4MzksIDIwODY5LCAyMDg5OCwgMjA5MjgsIDIwOTU3LCAyMDk4NywgMjEwMTYsIDIxMDQ2LCAyMTA3NiwgMjExMDUsIDIxMTM1LCAyMTE2NCwgMjExOTQsIDIxMjIzLCAyMTI1MyxcbiAgICAyMTI4MiwgMjEzMTIsIDIxMzQxLCAyMTM3MSwgMjE0MDAsIDIxNDMwLCAyMTQ1OSwgMjE0ODksIDIxNTE5LCAyMTU0OCwgMjE1NzgsIDIxNjA3LCAyMTYzNywgMjE2NjYsIDIxNjk2LCAyMTcyNSwgMjE3NTQsIDIxNzg0LCAyMTgxMywgMjE4NDMsXG4gICAgMjE4NzMsIDIxOTAyLCAyMTkzMiwgMjE5NjIsIDIxOTkxLCAyMjAyMSwgMjIwNTAsIDIyMDgwLCAyMjEwOSwgMjIxMzgsIDIyMTY4LCAyMjE5NywgMjIyMjcsIDIyMjU2LCAyMjI4NiwgMjIzMTYsIDIyMzQ2LCAyMjM3NSwgMjI0MDUsIDIyNDM0LFxuICAgIDIyNDY0LCAyMjQ5MywgMjI1MjIsIDIyNTUyLCAyMjU4MSwgMjI2MTEsIDIyNjQwLCAyMjY3MCwgMjI3MDAsIDIyNzMwLCAyMjc1OSwgMjI3ODksIDIyODE4LCAyMjg0OCwgMjI4NzcsIDIyOTA2LCAyMjkzNiwgMjI5NjUsIDIyOTk0LCAyMzAyNCxcbiAgICAyMzA1NCwgMjMwODMsIDIzMTEzLCAyMzE0MywgMjMxNzMsIDIzMjAyLCAyMzIzMiwgMjMyNjEsIDIzMjkwLCAyMzMyMCwgMjMzNDksIDIzMzc5LCAyMzQwOCwgMjM0MzgsIDIzNDY3LCAyMzQ5NywgMjM1MjcsIDIzNTU2LCAyMzU4NiwgMjM2MTYsXG4gICAgMjM2NDUsIDIzNjc0LCAyMzcwNCwgMjM3MzMsIDIzNzYzLCAyMzc5MiwgMjM4MjIsIDIzODUxLCAyMzg4MSwgMjM5MTAsIDIzOTQwLCAyMzk3MCwgMjM5OTksIDI0MDI5LCAyNDA1OCwgMjQwODgsIDI0MTE3LCAyNDE0NywgMjQxNzYsIDI0MjA2LFxuICAgIDI0MjM1LCAyNDI2NSwgMjQyOTQsIDI0MzI0LCAyNDM1MywgMjQzODMsIDI0NDEzLCAyNDQ0MiwgMjQ0NzIsIDI0NTAxLCAyNDUzMSwgMjQ1NjAsIDI0NTkwLCAyNDYxOSwgMjQ2NDgsIDI0Njc4LCAyNDcwNywgMjQ3MzcsIDI0NzY3LCAyNDc5NixcbiAgICAyNDgyNiwgMjQ4NTYsIDI0ODg1LCAyNDkxNSwgMjQ5NDQsIDI0OTc0LCAyNTAwMywgMjUwMzIsIDI1MDYyLCAyNTA5MSwgMjUxMjEsIDI1MTUwLCAyNTE4MCwgMjUyMTAsIDI1MjQwLCAyNTI2OSwgMjUyOTksIDI1MzI4LCAyNTM1OCwgMjUzODcsXG4gICAgMjU0MTYsIDI1NDQ2LCAyNTQ3NSwgMjU1MDUsIDI1NTM0LCAyNTU2NCwgMjU1OTQsIDI1NjI0LCAyNTY1MywgMjU2ODMsIDI1NzEyLCAyNTc0MiwgMjU3NzEsIDI1ODAwLCAyNTgzMCwgMjU4NTksIDI1ODg4LCAyNTkxOCwgMjU5NDgsIDI1OTc3LFxuICAgIDI2MDA3LCAyNjAzNywgMjYwNjcsIDI2MDk2LCAyNjEyNiwgMjYxNTUsIDI2MTg0LCAyNjIxNCwgMjYyNDMsIDI2MjcyLCAyNjMwMiwgMjYzMzIsIDI2MzYxLCAyNjM5MSwgMjY0MjEsIDI2NDUxLCAyNjQ4MCwgMjY1MTAsIDI2NTM5LCAyNjU2OCxcbiAgICAyNjU5OCwgMjY2MjcsIDI2NjU2LCAyNjY4NiwgMjY3MTUsIDI2NzQ1LCAyNjc3NSwgMjY4MDUsIDI2ODM0LCAyNjg2NCwgMjY4OTMsIDI2OTIzLCAyNjk1MiwgMjY5ODIsIDI3MDExLCAyNzA0MSwgMjcwNzAsIDI3MDk5LCAyNzEyOSwgMjcxNTksXG4gICAgMjcxODgsIDI3MjE4LCAyNzI0OCwgMjcyNzcsIDI3MzA3LCAyNzMzNiwgMjczNjYsIDI3Mzk1LCAyNzQyNSwgMjc0NTQsIDI3NDg0LCAyNzUxMywgMjc1NDIsIDI3NTcyLCAyNzYwMiwgMjc2MzEsIDI3NjYxLCAyNzY5MSwgMjc3MjAsIDI3NzUwLFxuICAgIDI3Nzc5LCAyNzgwOSwgMjc4MzgsIDI3ODY4LCAyNzg5NywgMjc5MjYsIDI3OTU2LCAyNzk4NSwgMjgwMTUsIDI4MDQ1LCAyODA3NCwgMjgxMDQsIDI4MTM0LCAyODE2MywgMjgxOTMsIDI4MjIyLCAyODI1MiwgMjgyODEsIDI4MzEwLCAyODM0MCxcbiAgICAyODM2OSwgMjgzOTksIDI4NDI4LCAyODQ1OCwgMjg0ODgsIDI4NTE3LCAyODU0NywgMjg1NzcsXG4gICAgLy8gRnJvbSAxMzU2XG4gICAgMjg2MDcsIDI4NjM2LCAyODY2NSwgMjg2OTUsIDI4NzI0LCAyODc1NCwgMjg3ODMsIDI4ODEzLCAyODg0MywgMjg4NzIsIDI4OTAxLCAyODkzMSwgMjg5NjAsIDI4OTkwLCAyOTAxOSwgMjkwNDksIDI5MDc4LCAyOTEwOCwgMjkxMzcsIDI5MTY3LFxuICAgIDI5MTk2LCAyOTIyNiwgMjkyNTUsIDI5Mjg1LCAyOTMxNSwgMjkzNDUsIDI5Mzc1LCAyOTQwNCwgMjk0MzQsIDI5NDYzLCAyOTQ5MiwgMjk1MjIsIDI5NTUxLCAyOTU4MCwgMjk2MTAsIDI5NjQwLCAyOTY2OSwgMjk2OTksIDI5NzI5LCAyOTc1OSxcbiAgICAyOTc4OCwgMjk4MTgsIDI5ODQ3LCAyOTg3NiwgMjk5MDYsIDI5OTM1LCAyOTk2NCwgMjk5OTQsIDMwMDIzLCAzMDA1MywgMzAwODIsIDMwMTEyLCAzMDE0MSwgMzAxNzEsIDMwMjAwLCAzMDIzMCwgMzAyNTksIDMwMjg5LCAzMDMxOCwgMzAzNDgsXG4gICAgMzAzNzgsIDMwNDA4LCAzMDQzNywgMzA0NjcsIDMwNDk2LCAzMDUyNiwgMzA1NTUsIDMwNTg1LCAzMDYxNCwgMzA2NDQsIDMwNjczLCAzMDcwMywgMzA3MzIsIDMwNzYyLCAzMDc5MSwgMzA4MjEsIDMwODUwLCAzMDg4MCwgMzA5MDksIDMwOTM5LFxuICAgIDMwOTY4LCAzMDk5OCwgMzEwMjcsIDMxMDU3LCAzMTA4NiwgMzExMTYsIDMxMTQ1LCAzMTE3NSwgMzEyMDQsIDMxMjM0LCAzMTI2MywgMzEyOTMsIDMxMzIyLCAzMTM1MiwgMzEzODEsIDMxNDExLCAzMTQ0MSwgMzE0NzEsIDMxNTAwLCAzMTUzMCxcbiAgICAzMTU1OSwgMzE1ODksIDMxNjE4LCAzMTY0OCwgMzE2NzYsIDMxNzA2LCAzMTczNiwgMzE3NjYsIDMxNzk1LCAzMTgyNSwgMzE4NTQsIDMxODg0LCAzMTkxMywgMzE5NDMsIDMxOTcyLCAzMjAwMiwgMzIwMzEsIDMyMDYxLCAzMjA5MCwgMzIxMjAsXG4gICAgMzIxNTAsIDMyMTgwLCAzMjIwOSwgMzIyMzksIDMyMjY4LCAzMjI5OCwgMzIzMjcsIDMyMzU3LCAzMjM4NiwgMzI0MTYsIDMyNDQ1LCAzMjQ3NSwgMzI1MDQsIDMyNTM0LCAzMjU2MywgMzI1OTMsIDMyNjIyLCAzMjY1MiwgMzI2ODEsIDMyNzExLFxuICAgIDMyNzQwLCAzMjc3MCwgMzI3OTksIDMyODI5LCAzMjg1OCwgMzI4ODgsIDMyOTE3LCAzMjk0NywgMzI5NzYsIDMzMDA2LCAzMzAzNSwgMzMwNjUsIDMzMDk0LCAzMzEyNCwgMzMxNTMsIDMzMTgzLCAzMzIxMywgMzMyNDMsIDMzMjcyLCAzMzMwMixcbiAgICAzMzMzMSwgMzMzNjEsIDMzMzkwLCAzMzQyMCwgMzM0NTAsIDMzNDc5LCAzMzUwOSwgMzM1MzksIDMzNTY4LCAzMzU5OCwgMzM2MjcsIDMzNjU3LCAzMzY4NiwgMzM3MTYsIDMzNzQ1LCAzMzc3NSwgMzM4MDQsIDMzODM0LCAzMzg2MywgMzM4OTMsXG4gICAgMzM5MjIsIDMzOTUyLCAzMzk4MSwgMzQwMTEsIDM0MDQwLCAzNDA2OSwgMzQwOTksIDM0MTI4LCAzNDE1OCwgMzQxODcsIDM0MjE3LCAzNDI0NywgMzQyNzcsIDM0MzA2LCAzNDMzNiwgMzQzNjUsIDM0Mzk1LCAzNDQyNCwgMzQ0NTQsIDM0NDgzLFxuICAgIDM0NTEyLCAzNDU0MiwgMzQ1NzEsIDM0NjAxLCAzNDYzMSwgMzQ2NjAsIDM0NjkwLCAzNDcxOSwgMzQ3NDksIDM0Nzc4LCAzNDgwOCwgMzQ4MzcsIDM0ODY3LCAzNDg5NiwgMzQ5MjYsIDM0OTU1LCAzNDk4NSwgMzUwMTUsIDM1MDQ0LCAzNTA3NCxcbiAgICAzNTEwMywgMzUxMzMsIDM1MTYyLCAzNTE5MiwgMzUyMjIsIDM1MjUxLCAzNTI4MCwgMzUzMTAsIDM1MzQwLCAzNTM3MCwgMzUzOTksIDM1NDI5LCAzNTQ1OCwgMzU0ODgsIDM1NTE3LCAzNTU0NywgMzU1NzYsIDM1NjA1LCAzNTYzNSwgMzU2NjUsXG4gICAgMzU2OTQsIDM1NzIzLCAzNTc1MywgMzU3ODIsIDM1ODExLCAzNTg0MSwgMzU4NzEsIDM1OTAxLCAzNTkzMCwgMzU5NjAsIDM1OTg5LCAzNjAxOSwgMzYwNDgsIDM2MDc4LCAzNjEwNywgMzYxMzYsIDM2MTY2LCAzNjE5NSwgMzYyMjUsIDM2MjU0LFxuICAgIDM2Mjg0LCAzNjMxNCwgMzYzNDMsIDM2MzczLCAzNjQwMywgMzY0MzMsIDM2NDYyLCAzNjQ5MiwgMzY1MjEsIDM2NTUxLCAzNjU4MCwgMzY2MTAsIDM2NjM5LCAzNjY2OSwgMzY2OTgsIDM2NzI4LCAzNjc1NywgMzY3ODYsIDM2ODE2LCAzNjg0NSxcbiAgICAzNjg3NSwgMzY5MDQsIDM2OTM0LCAzNjk2MywgMzY5OTMsIDM3MDIyLCAzNzA1MiwgMzcwODEsIDM3MTExLCAzNzE0MSwgMzcxNzAsIDM3MjAwLCAzNzIyOSwgMzcyNTksIDM3Mjg4LCAzNzMxOCwgMzczNDcsIDM3Mzc3LCAzNzQwNiwgMzc0MzYsXG4gICAgMzc0NjUsIDM3NDk1LCAzNzUyNCwgMzc1NTQsIDM3NTg0LCAzNzYxMywgMzc2NDMsIDM3NjcyLCAzNzcwMSwgMzc3MzEsIDM3NzYwLCAzNzc5MCwgMzc4MTksIDM3ODQ5LCAzNzg3OCwgMzc5MDgsIDM3OTM4LCAzNzk2NywgMzc5OTcsIDM4MDI3LFxuICAgIDM4MDU2LCAzODA4NSwgMzgxMTUsIDM4MTQ0LCAzODE3NCwgMzgyMDMsIDM4MjMzLCAzODI2MiwgMzgyOTIsIDM4MzIyLCAzODM1MSwgMzgzODEsIDM4NDEwLCAzODQ0MCwgMzg0NjksIDM4NDk5LCAzODUyOCwgMzg1NTgsIDM4NTg3LCAzODYxNyxcbiAgICAzODY0NiwgMzg2NzYsIDM4NzA1LCAzODczNSwgMzg3NjQsIDM4Nzk0LCAzODgyMywgMzg4NTMsIDM4ODgyLCAzODkxMiwgMzg5NDEsIDM4OTcxLCAzOTAwMSwgMzkwMzAsIDM5MDU5LCAzOTA4OSwgMzkxMTgsIDM5MTQ4LCAzOTE3OCwgMzkyMDgsXG4gICAgMzkyMzcsIDM5MjY3LCAzOTI5NywgMzkzMjYsIDM5MzU1LCAzOTM4NSwgMzk0MTQsIDM5NDQ0LCAzOTQ3MywgMzk1MDMsIDM5NTMyLCAzOTU2MiwgMzk1OTIsIDM5NjIxLCAzOTY1MCwgMzk2ODAsIDM5NzA5LCAzOTczOSwgMzk3NjgsIDM5Nzk4LFxuICAgIDM5ODI3LCAzOTg1NywgMzk4ODYsIDM5OTE2LCAzOTk0NiwgMzk5NzUsIDQwMDA1LCA0MDAzNSwgNDAwNjQsIDQwMDk0LCA0MDEyMywgNDAxNTMsIDQwMTgyLCA0MDIxMiwgNDAyNDEsIDQwMjcxLCA0MDMwMCwgNDAzMzAsIDQwMzU5LCA0MDM4OSxcbiAgICA0MDQxOCwgNDA0NDgsIDQwNDc3LCA0MDUwNywgNDA1MzYsIDQwNTY2LCA0MDU5NSwgNDA2MjUsIDQwNjU1LCA0MDY4NSwgNDA3MTQsIDQwNzQ0LCA0MDc3MywgNDA4MDMsIDQwODMyLCA0MDg2MiwgNDA4OTIsIDQwOTIxLCA0MDk1MSwgNDA5ODAsXG4gICAgNDEwMDksIDQxMDM5LCA0MTA2OCwgNDEwOTgsIDQxMTI3LCA0MTE1NywgNDExODYsIDQxMjE2LCA0MTI0NSwgNDEyNzUsIDQxMzA0LCA0MTMzNCwgNDEzNjQsIDQxMzkzLCA0MTQyMiwgNDE0NTIsIDQxNDgxLCA0MTUxMSwgNDE1NDAsIDQxNTcwLFxuICAgIDQxNTk5LCA0MTYyOSwgNDE2NTgsIDQxNjg4LCA0MTcxOCwgNDE3NDgsIDQxNzc3LCA0MTgwNywgNDE4MzYsIDQxODY1LCA0MTg5NCwgNDE5MjQsIDQxOTUzLCA0MTk4MywgNDIwMTIsIDQyMDQyLCA0MjA3MiwgNDIxMDIsIDQyMTMxLCA0MjE2MSxcbiAgICA0MjE5MCwgNDIyMjAsIDQyMjQ5LCA0MjI3OSwgNDIzMDgsIDQyMzM3LCA0MjM2NywgNDIzOTcsIDQyNDI2LCA0MjQ1NiwgNDI0ODUsIDQyNTE1LCA0MjU0NSwgNDI1NzQsIDQyNjA0LCA0MjYzMywgNDI2NjIsIDQyNjkyLCA0MjcyMSwgNDI3NTEsXG4gICAgNDI3ODAsIDQyODEwLCA0MjgzOSwgNDI4NjksIDQyODk5LCA0MjkyOSwgNDI5NTgsIDQyOTg4LCA0MzAxNywgNDMwNDYsIDQzMDc2LCA0MzEwNSwgNDMxMzUsIDQzMTY0LCA0MzE5NCwgNDMyMjMsIDQzMjUzLCA0MzI4MywgNDMzMTIsIDQzMzQyLFxuICAgIDQzMzcxLCA0MzQwMSwgNDM0MzAsIDQzNDYwLCA0MzQ4OSwgNDM1MTksIDQzNTQ4LCA0MzU3OCwgNDM2MDcsIDQzNjM3LCA0MzY2NiwgNDM2OTYsIDQzNzI2LCA0Mzc1NSwgNDM3ODUsIDQzODE0LCA0Mzg0NCwgNDM4NzMsIDQzOTAzLCA0MzkzMixcbiAgICA0Mzk2MiwgNDM5OTEsIDQ0MDIxLCA0NDA1MCwgNDQwODAsIDQ0MTA5LCA0NDEzOSwgNDQxNjksIDQ0MTk4LCA0NDIyOCwgNDQyNTgsIDQ0Mjg3LCA0NDMxNywgNDQzNDYsIDQ0Mzc1LCA0NDQwNSwgNDQ0MzQsIDQ0NDY0LCA0NDQ5MywgNDQ1MjMsXG4gICAgNDQ1NTMsIDQ0NTgyLCA0NDYxMiwgNDQ2NDEsIDQ0NjcxLCA0NDcwMCwgNDQ3MzAsIDQ0NzU5LCA0NDc4OCwgNDQ4MTgsIDQ0ODQ3LCA0NDg3NywgNDQ5MDYsIDQ0OTM2LCA0NDk2NiwgNDQ5OTYsIDQ1MDI1LCA0NTA1NSwgNDUwODQsIDQ1MTE0LFxuICAgIDQ1MTQzLCA0NTE3MiwgNDUyMDIsIDQ1MjMxLCA0NTI2MSwgNDUyOTAsIDQ1MzIwLCA0NTM1MCwgNDUzODAsIDQ1NDA5LCA0NTQzOSwgNDU0NjgsIDQ1NDk4LCA0NTUyNywgNDU1NTYsIDQ1NTg2LCA0NTYxNSwgNDU2NDQsIDQ1Njc0LCA0NTcwNCxcbiAgICA0NTczMywgNDU3NjMsIDQ1NzkzLCA0NTgyMywgNDU4NTIsIDQ1ODgyLCA0NTkxMSwgNDU5NDAsIDQ1OTcwLCA0NTk5OSwgNDYwMjgsIDQ2MDU4LCA0NjA4OCwgNDYxMTcsIDQ2MTQ3LCA0NjE3NywgNDYyMDYsIDQ2MjM2LCA0NjI2NSwgNDYyOTUsXG4gICAgNDYzMjQsIDQ2MzU0LCA0NjM4MywgNDY0MTMsIDQ2NDQyLCA0NjQ3MiwgNDY1MDEsIDQ2NTMxLCA0NjU2MCwgNDY1OTAsIDQ2NjIwLCA0NjY0OSwgNDY2NzksIDQ2NzA4LCA0NjczOCwgNDY3NjcsIDQ2Nzk3LCA0NjgyNiwgNDY4NTYsIDQ2ODg1LFxuICAgIDQ2OTE1LCA0Njk0NCwgNDY5NzQsIDQ3MDAzLCA0NzAzMywgNDcwNjMsIDQ3MDkyLCA0NzEyMiwgNDcxNTEsIDQ3MTgxLCA0NzIxMCwgNDcyNDAsIDQ3MjY5LCA0NzI5OCwgNDczMjgsIDQ3MzU3LCA0NzM4NywgNDc0MTcsIDQ3NDQ2LCA0NzQ3NixcbiAgICA0NzUwNiwgNDc1MzUsIDQ3NTY1LCA0NzU5NCwgNDc2MjQsIDQ3NjUzLCA0NzY4MiwgNDc3MTIsIDQ3NzQxLCA0Nzc3MSwgNDc4MDAsIDQ3ODMwLCA0Nzg2MCwgNDc4OTAsIDQ3OTE5LCA0Nzk0OSwgNDc5NzgsIDQ4MDA4LCA0ODAzNywgNDgwNjYsXG4gICAgNDgwOTYsIDQ4MTI1LCA0ODE1NSwgNDgxODQsIDQ4MjE0LCA0ODI0NCwgNDgyNzMsIDQ4MzAzLCA0ODMzMywgNDgzNjIsIDQ4MzkyLCA0ODQyMSwgNDg0NTAsIDQ4NDgwLCA0ODUwOSwgNDg1MzgsIDQ4NTY4LCA0ODU5OCwgNDg2MjcsIDQ4NjU3LFxuICAgIDQ4Njg3LCA0ODcxNywgNDg3NDYsIDQ4Nzc2LCA0ODgwNSwgNDg4MzQsIDQ4ODY0LCA0ODg5MywgNDg5MjIsIDQ4OTUyLCA0ODk4MiwgNDkwMTEsIDQ5MDQxLCA0OTA3MSwgNDkxMDAsIDQ5MTMwLCA0OTE2MCwgNDkxODksIDQ5MjE4LCA0OTI0OCxcbiAgICA0OTI3NywgNDkzMDYsIDQ5MzM2LCA0OTM2NSwgNDkzOTUsIDQ5NDI1LCA0OTQ1NSwgNDk0ODQsIDQ5NTE0LCA0OTU0MywgNDk1NzMsIDQ5NjAyLCA0OTYzMiwgNDk2NjEsIDQ5NjkwLCA0OTcyMCwgNDk3NDksIDQ5Nzc5LCA0OTgwOSwgNDk4MzgsXG4gICAgNDk4NjgsIDQ5ODk4LCA0OTkyNywgNDk5NTcsIDQ5OTg2LCA1MDAxNiwgNTAwNDUsIDUwMDc1LCA1MDEwNCwgNTAxMzMsIDUwMTYzLCA1MDE5MiwgNTAyMjIsIDUwMjUyLCA1MDI4MSwgNTAzMTEsIDUwMzQwLCA1MDM3MCwgNTA0MDAsIDUwNDI5LFxuICAgIDUwNDU5LCA1MDQ4OCwgNTA1MTgsIDUwNTQ3LCA1MDU3NiwgNTA2MDYsIDUwNjM1LCA1MDY2NSwgNTA2OTQsIDUwNzI0LCA1MDc1NCwgNTA3ODQsIDUwODEzLCA1MDg0MywgNTA4NzIsIDUwOTAyLCA1MDkzMSwgNTA5NjAsIDUwOTkwLCA1MTAxOSxcbiAgICA1MTA0OSwgNTEwNzgsIDUxMTA4LCA1MTEzOCwgNTExNjcsIDUxMTk3LCA1MTIyNywgNTEyNTYsIDUxMjg2LCA1MTMxNSwgNTEzNDUsIDUxMzc0LCA1MTQwMywgNTE0MzMsIDUxNDYyLCA1MTQ5MiwgNTE1MjIsIDUxNTUyLCA1MTU4MiwgNTE2MTEsXG4gICAgNTE2NDEsIDUxNjcwLCA1MTY5OSwgNTE3MjksIDUxNzU4LCA1MTc4NywgNTE4MTYsIDUxODQ2LCA1MTg3NiwgNTE5MDYsIDUxOTM2LCA1MTk2NSwgNTE5OTUsIDUyMDI1LCA1MjA1NCwgNTIwODMsIDUyMTEzLCA1MjE0MiwgNTIxNzEsIDUyMjAwLFxuICAgIDUyMjMwLCA1MjI2MCwgNTIyOTAsIDUyMzE5LCA1MjM0OSwgNTIzNzksIDUyNDA4LCA1MjQzOCwgNTI0NjcsIDUyNDk3LCA1MjUyNiwgNTI1NTUsIDUyNTg1LCA1MjYxNCwgNTI2NDQsIDUyNjczLCA1MjcwMywgNTI3MzMsIDUyNzYyLCA1Mjc5MixcbiAgICA1MjgyMiwgNTI4NTEsIDUyODgxLCA1MjkxMCwgNTI5MzksIDUyOTY5LCA1Mjk5OCwgNTMwMjgsIDUzMDU3LCA1MzA4NywgNTMxMTYsIDUzMTQ2LCA1MzE3NiwgNTMyMDUsIDUzMjM1LCA1MzI2NCwgNTMyOTQsIDUzMzI0LCA1MzM1MywgNTMzODMsXG4gICAgNTM0MTIsIDUzNDQxLCA1MzQ3MSwgNTM1MDAsIDUzNTMwLCA1MzU1OSwgNTM1ODksIDUzNjE5LCA1MzY0OCwgNTM2NzgsIDUzNzA4LCA1MzczNywgNTM3NjcsIDUzNzk2LCA1MzgyNSwgNTM4NTUsIDUzODg0LCA1MzkxMywgNTM5NDMsIDUzOTczLFxuICAgIDU0MDAzLCA1NDAzMiwgNTQwNjIsIDU0MDkyLCA1NDEyMSwgNTQxNTEsIDU0MTgwLCA1NDIwOSwgNTQyMzksIDU0MjY4LCA1NDI5NywgNTQzMjcsIDU0MzU3LCA1NDM4NywgNTQ0MTYsIDU0NDQ2LCA1NDQ3NiwgNTQ1MDUsIDU0NTM1LCA1NDU2NCxcbiAgICA1NDU5MywgNTQ2MjMsIDU0NjUyLCA1NDY4MSwgNTQ3MTEsIDU0NzQxLCA1NDc3MCwgNTQ4MDAsIDU0ODMwLCA1NDg1OSwgNTQ4ODksIDU0OTE5LCA1NDk0OCwgNTQ5NzcsIDU1MDA3LCA1NTAzNiwgNTUwNjYsIDU1MDk1LCA1NTEyNSwgNTUxNTQsXG4gICAgNTUxODQsIDU1MjEzLCA1NTI0MywgNTUyNzMsIDU1MzAyLCA1NTMzMiwgNTUzNjEsIDU1MzkxLCA1NTQyMCwgNTU0NTAsIDU1NDc5LCA1NTUwOCwgNTU1MzgsIDU1NTY3LCA1NTU5NywgNTU2MjcsIDU1NjU3LCA1NTY4NiwgNTU3MTYsIDU1NzQ1LFxuICAgIDU1Nzc1LCA1NTgwNCwgNTU4MzQsIDU1ODYzLCA1NTg5MiwgNTU5MjIsIDU1OTUxLCA1NTk4MSwgNTYwMTEsIDU2MDQwLCA1NjA3MCwgNTYxMDAsIDU2MTI5LCA1NjE1OSwgNTYxODgsIDU2MjE4LCA1NjI0NywgNTYyNzYsIDU2MzA2LCA1NjMzNSxcbiAgICA1NjM2NSwgNTYzOTQsIDU2NDI0LCA1NjQ1NCwgNTY0ODMsIDU2NTEzLCA1NjU0MywgNTY1NzIsIDU2NjAxLCA1NjYzMSwgNTY2NjAsIDU2NjkwLCA1NjcxOSwgNTY3NDksIDU2Nzc4LCA1NjgwOCwgNTY4MzcsIDU2ODY3LCA1Njg5NywgNTY5MjYsXG4gICAgNTY5NTYsIDU2OTg1LCA1NzAxNSwgNTcwNDQsIDU3MDc0LCA1NzEwMywgNTcxMzMsIDU3MTYyLCA1NzE5MiwgNTcyMjEsIDU3MjUxLCA1NzI4MCwgNTczMTAsIDU3MzQwLCA1NzM2OSwgNTczOTksIDU3NDI5LCA1NzQ1OCwgNTc0ODcsIDU3NTE3LFxuICAgIDU3NTQ2LCA1NzU3NiwgNTc2MDUsIDU3NjM0LCA1NzY2NCwgNTc2OTQsIDU3NzIzLCA1Nzc1MywgNTc3ODMsIDU3ODEzLCA1Nzg0MiwgNTc4NzEsIDU3OTAxLCA1NzkzMCwgNTc5NTksIDU3OTg5LCA1ODAxOCwgNTgwNDgsIDU4MDc3LCA1ODEwNyxcbiAgICA1ODEzNywgNTgxNjcsIDU4MTk2LCA1ODIyNiwgNTgyNTUsIDU4Mjg1LCA1ODMxNCwgNTgzNDMsIDU4MzczLCA1ODQwMiwgNTg0MzIsIDU4NDYxLCA1ODQ5MSwgNTg1MjEsIDU4NTUxLCA1ODU4MCwgNTg2MTAsIDU4NjM5LCA1ODY2OSwgNTg2OTgsXG4gICAgNTg3MjcsIDU4NzU3LCA1ODc4NiwgNTg4MTYsIDU4ODQ1LCA1ODg3NSwgNTg5MDUsIDU4OTM0LCA1ODk2NCwgNTg5OTQsIDU5MDIzLCA1OTA1MywgNTkwODIsIDU5MTExLCA1OTE0MSwgNTkxNzAsIDU5MjAwLCA1OTIyOSwgNTkyNTksIDU5Mjg4LFxuICAgIDU5MzE4LCA1OTM0OCwgNTkzNzcsIDU5NDA3LCA1OTQzNiwgNTk0NjYsIDU5NDk1LCA1OTUyNSwgNTk1NTQsIDU5NTg0LCA1OTYxMywgNTk2NDMsIDU5NjcyLCA1OTcwMiwgNTk3MzEsIDU5NzYxLCA1OTc5MSwgNTk4MjAsIDU5ODUwLCA1OTg3OSxcbiAgICA1OTkwOSwgNTk5MzksIDU5OTY4LCA1OTk5NywgNjAwMjcsIDYwMDU2LCA2MDA4NiwgNjAxMTUsIDYwMTQ1LCA2MDE3NCwgNjAyMDQsIDYwMjM0LCA2MDI2NCwgNjAyOTMsIDYwMzIzLCA2MDM1MiwgNjAzODEsIDYwNDExLCA2MDQ0MCwgNjA0NjksXG4gICAgNjA0OTksIDYwNTI4LCA2MDU1OCwgNjA1ODgsIDYwNjE4LCA2MDY0OCwgNjA2NzcsIDYwNzA3LCA2MDczNiwgNjA3NjUsIDYwNzk1LCA2MDgyNCwgNjA4NTMsIDYwODgzLCA2MDkxMiwgNjA5NDIsIDYwOTcyLCA2MTAwMiwgNjEwMzEsIDYxMDYxLFxuICAgIDYxMDkwLCA2MTEyMCwgNjExNDksIDYxMTc5LCA2MTIwOCwgNjEyMzcsIDYxMjY3LCA2MTI5NiwgNjEzMjYsIDYxMzU2LCA2MTM4NSwgNjE0MTUsIDYxNDQ1LCA2MTQ3NCwgNjE1MDQsIDYxNTMzLCA2MTU2MywgNjE1OTIsIDYxNjIxLCA2MTY1MSxcbiAgICA2MTY4MCwgNjE3MTAsIDYxNzM5LCA2MTc2OSwgNjE3OTksIDYxODI4LCA2MTg1OCwgNjE4ODgsIDYxOTE3LCA2MTk0NywgNjE5NzYsIDYyMDA2LCA2MjAzNSwgNjIwNjQsIDYyMDk0LCA2MjEyMywgNjIxNTMsIDYyMTgyLCA2MjIxMiwgNjIyNDIsXG4gICAgNjIyNzEsIDYyMzAxLCA2MjMzMSwgNjIzNjAsIDYyMzkwLCA2MjQxOSwgNjI0NDgsIDYyNDc4LCA2MjUwNywgNjI1MzcsIDYyNTY2LCA2MjU5NiwgNjI2MjUsIDYyNjU1LCA2MjY4NSwgNjI3MTUsIDYyNzQ0LCA2Mjc3NCwgNjI4MDMsIDYyODMyLFxuICAgIDYyODYyLCA2Mjg5MSwgNjI5MjEsIDYyOTUwLCA2Mjk4MCwgNjMwMDksIDYzMDM5LCA2MzA2OSwgNjMwOTksIDYzMTI4LCA2MzE1NywgNjMxODcsIDYzMjE2LCA2MzI0NiwgNjMyNzUsIDYzMzA1LCA2MzMzNCwgNjMzNjMsIDYzMzkzLCA2MzQyMyxcbiAgICA2MzQ1MywgNjM0ODIsIDYzNTEyLCA2MzU0MSwgNjM1NzEsIDYzNjAwLCA2MzYzMCwgNjM2NTksIDYzNjg5LCA2MzcxOCwgNjM3NDcsIDYzNzc3LCA2MzgwNywgNjM4MzYsIDYzODY2LCA2Mzg5NSwgNjM5MjUsIDYzOTU1LCA2Mzk4NCwgNjQwMTQsXG4gICAgNjQwNDMsIDY0MDczLCA2NDEwMiwgNjQxMzEsIDY0MTYxLCA2NDE5MCwgNjQyMjAsIDY0MjQ5LCA2NDI3OSwgNjQzMDksIDY0MzM5LCA2NDM2OCwgNjQzOTgsIDY0NDI3LCA2NDQ1NywgNjQ0ODYsIDY0NTE1LCA2NDU0NSwgNjQ1NzQsIDY0NjAzLFxuICAgIDY0NjMzLCA2NDY2MywgNjQ2OTIsIDY0NzIyLCA2NDc1MiwgNjQ3ODIsIDY0ODExLCA2NDg0MSwgNjQ4NzAsIDY0ODk5LCA2NDkyOSwgNjQ5NTgsIDY0OTg3LCA2NTAxNywgNjUwNDcsIDY1MDc2LCA2NTEwNiwgNjUxMzYsIDY1MTY2LCA2NTE5NSxcbiAgICA2NTIyNSwgNjUyNTQsIDY1MjgzLCA2NTMxMywgNjUzNDIsIDY1MzcxLCA2NTQwMSwgNjU0MzEsIDY1NDYwLCA2NTQ5MCwgNjU1MjAsIDY1NTQ5LCA2NTU3OSwgNjU2MDgsIDY1NjM4LCA2NTY2NywgNjU2OTcsIDY1NzI2LCA2NTc1NSwgNjU3ODUsXG4gICAgNjU4MTUsIDY1ODQ0LCA2NTg3NCwgNjU5MDMsIDY1OTMzLCA2NTk2MywgNjU5OTIsIDY2MDIyLCA2NjA1MSwgNjYwODEsIDY2MTEwLCA2NjE0MCwgNjYxNjksIDY2MTk5LCA2NjIyOCwgNjYyNTgsIDY2Mjg3LCA2NjMxNywgNjYzNDYsIDY2Mzc2LFxuICAgIDY2NDA1LCA2NjQzNSwgNjY0NjUsIDY2NDk0LCA2NjUyNCwgNjY1NTMsIDY2NTgzLCA2NjYxMiwgNjY2NDEsIDY2NjcxLCA2NjcwMCwgNjY3MzAsIDY2NzYwLCA2Njc4OSwgNjY4MTksIDY2ODQ5LCA2Njg3OCwgNjY5MDgsIDY2OTM3LCA2Njk2NyxcbiAgICA2Njk5NiwgNjcwMjUsIDY3MDU1LCA2NzA4NCwgNjcxMTQsIDY3MTQzLCA2NzE3MywgNjcyMDMsIDY3MjMzLCA2NzI2MiwgNjcyOTIsIDY3MzIxLCA2NzM1MSwgNjczODAsIDY3NDA5LCA2NzQzOSwgNjc0NjgsIDY3NDk3LCA2NzUyNywgNjc1NTcsXG4gICAgNjc1ODcsIDY3NjE3LCA2NzY0NiwgNjc2NzYsIDY3NzA1LCA2NzczNSwgNjc3NjQsIDY3NzkzLCA2NzgyMywgNjc4NTIsIDY3ODgyLCA2NzkxMSwgNjc5NDEsIDY3OTcxLCA2ODAwMCwgNjgwMzAsIDY4MDYwLCA2ODA4OSwgNjgxMTksIDY4MTQ4LFxuICAgIDY4MTc3LCA2ODIwNywgNjgyMzYsIDY4MjY2LCA2ODI5NSwgNjgzMjUsIDY4MzU0LCA2ODM4NCwgNjg0MTQsIDY4NDQzLCA2ODQ3MywgNjg1MDIsIDY4NTMyLCA2ODU2MSwgNjg1OTEsIDY4NjIwLCA2ODY1MCwgNjg2NzksIDY4NzA4LCA2ODczOCxcbiAgICA2ODc2OCwgNjg3OTcsIDY4ODI3LCA2ODg1NywgNjg4ODYsIDY4OTE2LCA2ODk0NiwgNjg5NzUsIDY5MDA0LCA2OTAzNCwgNjkwNjMsIDY5MDkyLCA2OTEyMiwgNjkxNTIsIDY5MTgxLCA2OTIxMSwgNjkyNDAsIDY5MjcwLCA2OTMwMCwgNjkzMzAsXG4gICAgNjkzNTksIDY5Mzg4LCA2OTQxOCwgNjk0NDcsIDY5NDc2LCA2OTUwNiwgNjk1MzUsIDY5NTY1LCA2OTU5NSwgNjk2MjQsIDY5NjU0LCA2OTY4NCwgNjk3MTMsIDY5NzQzLCA2OTc3MiwgNjk4MDIsIDY5ODMxLCA2OTg2MSwgNjk4OTAsIDY5OTE5LFxuICAgIDY5OTQ5LCA2OTk3OCwgNzAwMDgsIDcwMDM4LCA3MDA2NywgNzAwOTcsIDcwMTI2LCA3MDE1NiwgNzAxODYsIDcwMjE1LCA3MDI0NSwgNzAyNzQsIDcwMzAzLCA3MDMzMywgNzAzNjIsIDcwMzkyLCA3MDQyMSwgNzA0NTEsIDcwNDgxLCA3MDUxMCxcbiAgICA3MDU0MCwgNzA1NzAsIDcwNTk5LCA3MDYyOSwgNzA2NTgsIDcwNjg3LCA3MDcxNywgNzA3NDYsIDcwNzc2LCA3MDgwNSwgNzA4MzUsIDcwODY0LCA3MDg5NCwgNzA5MjQsIDcwOTU0LCA3MDk4MywgNzEwMTMsIDcxMDQyLCA3MTA3MSwgNzExMDEsXG4gICAgNzExMzAsIDcxMTU5LCA3MTE4OSwgNzEyMTgsIDcxMjQ4LCA3MTI3OCwgNzEzMDgsIDcxMzM3LCA3MTM2NywgNzEzOTcsIDcxNDI2LCA3MTQ1NSwgNzE0ODUsIDcxNTE0LCA3MTU0MywgNzE1NzMsIDcxNjAyLCA3MTYzMiwgNzE2NjIsIDcxNjkxLFxuICAgIDcxNzIxLCA3MTc1MSwgNzE3ODEsIDcxODEwLCA3MTgzOSwgNzE4NjksIDcxODk4LCA3MTkyNywgNzE5NTcsIDcxOTg2LCA3MjAxNiwgNzIwNDYsIDcyMDc1LCA3MjEwNSwgNzIxMzUsIDcyMTY0LCA3MjE5NCwgNzIyMjMsIDcyMjUzLCA3MjI4MixcbiAgICA3MjMxMSwgNzIzNDEsIDcyMzcwLCA3MjQwMCwgNzI0MjksIDcyNDU5LCA3MjQ4OSwgNzI1MTgsIDcyNTQ4LCA3MjU3NywgNzI2MDcsIDcyNjM3LCA3MjY2NiwgNzI2OTUsIDcyNzI1LCA3Mjc1NCwgNzI3ODQsIDcyODEzLCA3Mjg0MywgNzI4NzIsXG4gICAgNzI5MDIsIDcyOTMxLCA3Mjk2MSwgNzI5OTEsIDczMDIwLCA3MzA1MCwgNzMwODAsIDczMTA5LCA3MzEzOSwgNzMxNjgsIDczMTk3LCA3MzIyNywgNzMyNTYsIDczMjg2LCA3MzMxNSwgNzMzNDUsIDczMzc1LCA3MzQwNCwgNzM0MzQsIDczNDY0LFxuICAgIDczNDkzLCA3MzUyMywgNzM1NTIsIDczNTgxLCA3MzYxMSwgNzM2NDAsIDczNjY5LCA3MzY5OSwgNzM3MjksIDczNzU4LCA3Mzc4OCwgNzM4MTgsIDczODQ4LCA3Mzg3NywgNzM5MDcsIDczOTM2LCA3Mzk2NSwgNzM5OTUsIDc0MDI0LCA3NDA1MyxcbiAgICA3NDA4MywgNzQxMTMsIDc0MTQyLCA3NDE3MiwgNzQyMDIsIDc0MjMxLCA3NDI2MSwgNzQyOTEsIDc0MzIwLCA3NDM0OSwgNzQzNzksIDc0NDA4LCA3NDQzNywgNzQ0NjcsIDc0NDk3LCA3NDUyNiwgNzQ1NTYsIDc0NTg2LCA3NDYxNSwgNzQ2NDUsXG4gICAgNzQ2NzUsIDc0NzA0LCA3NDczMywgNzQ3NjMsIDc0NzkyLCA3NDgyMiwgNzQ4NTEsIDc0ODgxLCA3NDkxMCwgNzQ5NDAsIDc0OTY5LCA3NDk5OSwgNzUwMjksIDc1MDU4LCA3NTA4OCwgNzUxMTcsIDc1MTQ3LCA3NTE3NiwgNzUyMDYsIDc1MjM1LFxuICAgIDc1MjY0LCA3NTI5NCwgNzUzMjMsIDc1MzUzLCA3NTM4MywgNzU0MTIsIDc1NDQyLCA3NTQ3MiwgNzU1MDEsIDc1NTMxLCA3NTU2MCwgNzU1OTAsIDc1NjE5LCA3NTY0OCwgNzU2NzgsIDc1NzA3LCA3NTczNywgNzU3NjYsIDc1Nzk2LCA3NTgyNixcbiAgICA3NTg1NiwgNzU4ODUsIDc1OTE1LCA3NTk0NCwgNzU5NzQsIDc2MDAzLCA3NjAzMiwgNzYwNjIsIDc2MDkxLCA3NjEyMSwgNzYxNTAsIDc2MTgwLCA3NjIxMCwgNzYyMzksIDc2MjY5LCA3NjI5OSwgNzYzMjgsIDc2MzU4LCA3NjM4NywgNzY0MTYsXG4gICAgNzY0NDYsIDc2NDc1LCA3NjUwNSwgNzY1MzQsIDc2NTY0LCA3NjU5MywgNzY2MjMsIDc2NjUzLCA3NjY4MiwgNzY3MTIsIDc2NzQxLCA3Njc3MSwgNzY4MDEsIDc2ODMwLCA3Njg1OSwgNzY4ODksIDc2OTE4LCA3Njk0OCwgNzY5NzcsIDc3MDA3LFxuICAgIDc3MDM2LCA3NzA2NiwgNzcwOTYsIDc3MTI1LCA3NzE1NSwgNzcxODUsIDc3MjE0LCA3NzI0MywgNzcyNzMsIDc3MzAyLCA3NzMzMiwgNzczNjEsIDc3MzkwLCA3NzQyMCwgNzc0NTAsIDc3NDc5LCA3NzUwOSwgNzc1MzksIDc3NTY5LCA3NzU5OCxcbiAgICA3NzYyNywgNzc2NTcsIDc3Njg2LCA3NzcxNSwgNzc3NDUsIDc3Nzc0LCA3NzgwNCwgNzc4MzMsIDc3ODYzLCA3Nzg5MywgNzc5MjMsIDc3OTUyLCA3Nzk4MiwgNzgwMTEsIDc4MDQxLCA3ODA3MCwgNzgwOTksIDc4MTI5LCA3ODE1OCwgNzgxODgsXG4gICAgNzgyMTcsIDc4MjQ3LCA3ODI3NywgNzgzMDcsIDc4MzM2LCA3ODM2NiwgNzgzOTUsIDc4NDI1LCA3ODQ1NCwgNzg0ODMsIDc4NTEzLCA3ODU0MiwgNzg1NzIsIDc4NjAxLCA3ODYzMSwgNzg2NjEsIDc4NjkwLCA3ODcyMCwgNzg3NTAsIDc4Nzc5LFxuICAgIDc4ODA4LCA3ODgzOCwgNzg4NjcsIDc4ODk3LCA3ODkyNiwgNzg5NTYsIDc4OTg1LCA3OTAxNSwgNzkwNDQsIDc5MDc0LCA3OTEwNCwgNzkxMzMsIDc5MTYzLCA3OTE5MiwgNzkyMjIsIDc5MjUxLCA3OTI4MSwgNzkzMTAsIDc5MzQwLCA3OTM2OSxcbiAgICA3OTM5OSwgNzk0MjgsIDc5NDU4LCA3OTQ4NywgNzk1MTcsIDc5NTQ2LCA3OTU3NiwgNzk2MDYsIDc5NjM1LCA3OTY2NSwgNzk2OTUsIDc5NzI0LCA3OTc1MywgNzk3ODMsIDc5ODEyLCA3OTg0MSwgNzk4NzEsIDc5OTAwLCA3OTkzMCwgNzk5NjAsXG4gICAgNzk5OTBdO1xuXG4iLCIvKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIENhbGVuZGFycyBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEF1Z3VzdCAyMDA5LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xuXG5cbmZ1bmN0aW9uIENhbGVuZGFycygpIHtcbiAgICB0aGlzLnJlZ2lvbmFsT3B0aW9ucyA9IFtdO1xuICAgIHRoaXMucmVnaW9uYWxPcHRpb25zWycnXSA9IHtcbiAgICAgICAgaW52YWxpZENhbGVuZGFyOiAnQ2FsZW5kYXIgezB9IG5vdCBmb3VuZCcsXG4gICAgICAgIGludmFsaWREYXRlOiAnSW52YWxpZCB7MH0gZGF0ZScsXG4gICAgICAgIGludmFsaWRNb250aDogJ0ludmFsaWQgezB9IG1vbnRoJyxcbiAgICAgICAgaW52YWxpZFllYXI6ICdJbnZhbGlkIHswfSB5ZWFyJyxcbiAgICAgICAgZGlmZmVyZW50Q2FsZW5kYXJzOiAnQ2Fubm90IG1peCB7MH0gYW5kIHsxfSBkYXRlcydcbiAgICB9O1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG4gICAgdGhpcy5jYWxlbmRhcnMgPSB7fTtcbiAgICB0aGlzLl9sb2NhbENhbHMgPSB7fTtcbn1cblxuLyoqIENyZWF0ZSB0aGUgY2FsZW5kYXJzIHBsdWdpbi5cbiAgICA8cD5Qcm92aWRlcyBzdXBwb3J0IGZvciB2YXJpb3VzIHdvcmxkIGNhbGVuZGFycyBpbiBhIGNvbnNpc3RlbnQgbWFubmVyLjwvcD5cbiAgICAgQGNsYXNzIENhbGVuZGFyc1xuICAgIEBleGFtcGxlIF9leHBvcnRzLmluc3RhbmNlKCdqdWxpYW4nKS5uZXdEYXRlKDIwMTQsIDEyLCAyNSkgKi9cbmFzc2lnbihDYWxlbmRhcnMucHJvdG90eXBlLCB7XG5cbiAgICAvKiogT2J0YWluIGEgY2FsZW5kYXIgaW1wbGVtZW50YXRpb24gYW5kIGxvY2FsaXNhdGlvbi5cbiAgICAgICAgQG1lbWJlcm9mIENhbGVuZGFyc1xuICAgICAgICBAcGFyYW0gW25hbWU9J2dyZWdvcmlhbiddIHtzdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSBjYWxlbmRhciwgZS5nLiAnZ3JlZ29yaWFuJywgJ3BlcnNpYW4nLCAnaXNsYW1pYycuXG4gICAgICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIHRvIHVzZSBmb3IgbG9jYWxpc2F0aW9uIChkZWZhdWx0IGlzIEVuZ2xpc2gpLlxuICAgICAgICBAcmV0dXJuIHtDYWxlbmRhcn0gVGhlIGNhbGVuZGFyIGFuZCBsb2NhbGlzYXRpb24uXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgY2FsZW5kYXIgbm90IGZvdW5kLiAqL1xuICAgIGluc3RhbmNlOiBmdW5jdGlvbihuYW1lLCBsYW5ndWFnZSkge1xuICAgICAgICBuYW1lID0gKG5hbWUgfHwgJ2dyZWdvcmlhbicpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGxhbmd1YWdlID0gbGFuZ3VhZ2UgfHwgJyc7XG4gICAgICAgIHZhciBjYWwgPSB0aGlzLl9sb2NhbENhbHNbbmFtZSArICctJyArIGxhbmd1YWdlXTtcbiAgICAgICAgaWYgKCFjYWwgJiYgdGhpcy5jYWxlbmRhcnNbbmFtZV0pIHtcbiAgICAgICAgICAgIGNhbCA9IG5ldyB0aGlzLmNhbGVuZGFyc1tuYW1lXShsYW5ndWFnZSk7XG4gICAgICAgICAgICB0aGlzLl9sb2NhbENhbHNbbmFtZSArICctJyArIGxhbmd1YWdlXSA9IGNhbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNhbCkge1xuICAgICAgICAgICAgdGhyb3cgKHRoaXMubG9jYWwuaW52YWxpZENhbGVuZGFyIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkQ2FsZW5kYXIpLlxuICAgICAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCBuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FsO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgLSBmb3IgdG9kYXkgaWYgbm8gb3RoZXIgcGFyYW1ldGVycyBnaXZlbi5cbiAgICAgICAgQG1lbWJlcm9mIENhbGVuZGFyc1xuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb3B5IG9yIHRoZSB5ZWFyIGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW2NhbGVuZGFyPSdncmVnb3JpYW4nXSB7QmFzZUNhbGVuZGFyfHN0cmluZ30gVGhlIHVuZGVybHlpbmcgY2FsZW5kYXIgb3IgdGhlIG5hbWUgb2YgdGhlIGNhbGVuZGFyLlxuICAgICAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgdG8gdXNlIGZvciBsb2NhbGlzYXRpb24gKGRlZmF1bHQgRW5nbGlzaCkuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgbmV3IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIG5ld0RhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXksIGNhbGVuZGFyLCBsYW5ndWFnZSkge1xuICAgICAgICBjYWxlbmRhciA9ICh5ZWFyICE9IG51bGwgJiYgeWVhci55ZWFyID8geWVhci5jYWxlbmRhcigpIDogKHR5cGVvZiBjYWxlbmRhciA9PT0gJ3N0cmluZycgP1xuICAgICAgICAgICAgdGhpcy5pbnN0YW5jZShjYWxlbmRhciwgbGFuZ3VhZ2UpIDogY2FsZW5kYXIpKSB8fCB0aGlzLmluc3RhbmNlKCk7XG4gICAgICAgIHJldHVybiBjYWxlbmRhci5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH0sXG4gICAgXG4gICAgLyoqIEEgc2ltcGxlIGRpZ2l0IHN1YnN0aXR1dGlvbiBmdW5jdGlvbiBmb3IgbG9jYWxpc2luZyBudW1iZXJzIHZpYSB0aGUgQ2FsZW5kYXIgZGlnaXRzIG9wdGlvbi5cbiAgICAgICAgQG1lbWJlciBDYWxlbmRhcnNcbiAgICAgICAgQHBhcmFtIGRpZ2l0cyB7c3RyaW5nW119IFRoZSBzdWJzdGl0dXRlIGRpZ2l0cywgZm9yIDAgdGhyb3VnaCA5LlxuICAgICAgICBAcmV0dXJuIHtmdW5jdGlvbn0gVGhlIHN1YnN0aXR1dGlvbiBmdW5jdGlvbi4gKi9cbiAgICBzdWJzdGl0dXRlRGlnaXRzOiBmdW5jdGlvbihkaWdpdHMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gKHZhbHVlICsgJycpLnJlcGxhY2UoL1swLTldL2csIGZ1bmN0aW9uKGRpZ2l0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZ2l0c1tkaWdpdF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgXG4gICAgLyoqIERpZ2l0IHN1YnN0aXR1dGlvbiBmdW5jdGlvbiBmb3IgbG9jYWxpc2luZyBDaGluZXNlIHN0eWxlIG51bWJlcnMgdmlhIHRoZSBDYWxlbmRhciBkaWdpdHMgb3B0aW9uLlxuICAgICAgICBAbWVtYmVyIENhbGVuZGFyc1xuICAgICAgICBAcGFyYW0gZGlnaXRzIHtzdHJpbmdbXX0gVGhlIHN1YnN0aXR1dGUgZGlnaXRzLCBmb3IgMCB0aHJvdWdoIDkuXG4gICAgICAgIEBwYXJhbSBwb3dlcnMge3N0cmluZ1tdfSBUaGUgY2hhcmFjdGVycyBkZW5vdGluZyBwb3dlcnMgb2YgMTAsIGkuZS4gMSwgMTAsIDEwMCwgMTAwMC5cbiAgICAgICAgQHJldHVybiB7ZnVuY3Rpb259IFRoZSBzdWJzdGl0dXRpb24gZnVuY3Rpb24uICovXG4gICAgc3Vic3RpdHV0ZUNoaW5lc2VEaWdpdHM6IGZ1bmN0aW9uKGRpZ2l0cywgcG93ZXJzKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIGxvY2FsTnVtYmVyID0gJyc7XG4gICAgICAgICAgICB2YXIgcG93ZXIgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKHZhbHVlID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciB1bml0cyA9IHZhbHVlICUgMTA7XG4gICAgICAgICAgICAgICAgbG9jYWxOdW1iZXIgPSAodW5pdHMgPT09IDAgPyAnJyA6IGRpZ2l0c1t1bml0c10gKyBwb3dlcnNbcG93ZXJdKSArIGxvY2FsTnVtYmVyO1xuICAgICAgICAgICAgICAgIHBvd2VyKys7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlIC8gMTApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxvY2FsTnVtYmVyLmluZGV4T2YoZGlnaXRzWzFdICsgcG93ZXJzWzFdKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGxvY2FsTnVtYmVyID0gbG9jYWxOdW1iZXIuc3Vic3RyKDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxvY2FsTnVtYmVyIHx8IGRpZ2l0c1swXTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG4vKiogR2VuZXJpYyBkYXRlLCBiYXNlZCBvbiBhIHBhcnRpY3VsYXIgY2FsZW5kYXIuXG4gICAgQGNsYXNzIENEYXRlXG4gICAgQHBhcmFtIGNhbGVuZGFyIHtCYXNlQ2FsZW5kYXJ9IFRoZSB1bmRlcmx5aW5nIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uLlxuICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSB5ZWFyIGZvciB0aGlzIGRhdGUuXG4gICAgQHBhcmFtIG1vbnRoIHtudW1iZXJ9IFRoZSBtb250aCBmb3IgdGhpcyBkYXRlLlxuICAgIEBwYXJhbSBkYXkge251bWJlcn0gVGhlIGRheSBmb3IgdGhpcyBkYXRlLlxuICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZGF0ZSBvYmplY3QuXG4gICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUuICovXG5mdW5jdGlvbiBDRGF0ZShjYWxlbmRhciwgeWVhciwgbW9udGgsIGRheSkge1xuICAgIHRoaXMuX2NhbGVuZGFyID0gY2FsZW5kYXI7XG4gICAgdGhpcy5feWVhciA9IHllYXI7XG4gICAgdGhpcy5fbW9udGggPSBtb250aDtcbiAgICB0aGlzLl9kYXkgPSBkYXk7XG4gICAgaWYgKHRoaXMuX2NhbGVuZGFyLl92YWxpZGF0ZUxldmVsID09PSAwICYmXG4gICAgICAgICAgICAhdGhpcy5fY2FsZW5kYXIuaXNWYWxpZCh0aGlzLl95ZWFyLCB0aGlzLl9tb250aCwgdGhpcy5fZGF5KSkge1xuICAgICAgICB0aHJvdyAoX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSkuXG4gICAgICAgICAgICByZXBsYWNlKC9cXHswXFx9LywgdGhpcy5fY2FsZW5kYXIubG9jYWwubmFtZSk7XG4gICAgfVxufVxuXG4vKiogUGFkIGEgbnVtZXJpYyB2YWx1ZSB3aXRoIGxlYWRpbmcgemVyb2VzLlxuICAgIEBwcml2YXRlXG4gICAgQHBhcmFtIHZhbHVlIHtudW1iZXJ9IFRoZSBudW1iZXIgdG8gZm9ybWF0LlxuICAgIEBwYXJhbSBsZW5ndGgge251bWJlcn0gVGhlIG1pbmltdW0gbGVuZ3RoLlxuICAgIEByZXR1cm4ge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBudW1iZXIuICovXG5mdW5jdGlvbiBwYWQodmFsdWUsIGxlbmd0aCkge1xuICAgIHZhbHVlID0gJycgKyB2YWx1ZTtcbiAgICByZXR1cm4gJzAwMDAwMCcuc3Vic3RyaW5nKDAsIGxlbmd0aCAtIHZhbHVlLmxlbmd0aCkgKyB2YWx1ZTtcbn1cblxuYXNzaWduKENEYXRlLnByb3RvdHlwZSwge1xuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIFt5ZWFyXSB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb3B5IG9yIHRoZSB5ZWFyIGZvciB0aGUgZGF0ZSAoZGVmYXVsdCB0aGlzIGRhdGUpLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgbmV3IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIG5ld0RhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLm5ld0RhdGUoKHllYXIgPT0gbnVsbCA/IHRoaXMgOiB5ZWFyKSwgbW9udGgsIGRheSk7XG4gICAgfSxcblxuICAgIC8qKiBTZXQgb3IgcmV0cmlldmUgdGhlIHllYXIgZm9yIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBbeWVhcl0ge251bWJlcn0gVGhlIHllYXIgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ8Q0RhdGV9IFRoZSBkYXRlJ3MgeWVhciAoaWYgbm8gcGFyYW1ldGVyKSBvciB0aGUgdXBkYXRlZCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZS4gKi9cbiAgICB5ZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHJldHVybiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCA/IHRoaXMuX3llYXIgOiB0aGlzLnNldCh5ZWFyLCAneScpKTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBvciByZXRyaWV2ZSB0aGUgbW9udGggZm9yIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcnxDRGF0ZX0gVGhlIGRhdGUncyBtb250aCAoaWYgbm8gcGFyYW1ldGVyKSBvciB0aGUgdXBkYXRlZCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZS4gKi9cbiAgICBtb250aDogZnVuY3Rpb24obW9udGgpIHtcbiAgICAgICAgcmV0dXJuIChhcmd1bWVudHMubGVuZ3RoID09PSAwID8gdGhpcy5fbW9udGggOiB0aGlzLnNldChtb250aCwgJ20nKSk7XG4gICAgfSxcblxuICAgIC8qKiBTZXQgb3IgcmV0cmlldmUgdGhlIGRheSBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ8Q0RhdGF9IFRoZSBkYXRlJ3MgZGF5IChpZiBubyBwYXJhbWV0ZXIpIG9yIHRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIGRheTogZnVuY3Rpb24oZGF5KSB7XG4gICAgICAgIHJldHVybiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCA/IHRoaXMuX2RheSA6IHRoaXMuc2V0KGRheSwgJ2QnKSk7XG4gICAgfSxcblxuICAgIC8qKiBTZXQgbmV3IHZhbHVlcyBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHBhcmFtIGRheSB7bnVtYmVyfSBUaGUgZGF5IGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIGRhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9jYWxlbmRhci5pc1ZhbGlkKHllYXIsIG1vbnRoLCBkYXkpKSB7XG4gICAgICAgICAgICB0aHJvdyAoX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSkuXG4gICAgICAgICAgICAgICAgcmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMuX2NhbGVuZGFyLmxvY2FsLm5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3llYXIgPSB5ZWFyO1xuICAgICAgICB0aGlzLl9tb250aCA9IG1vbnRoO1xuICAgICAgICB0aGlzLl9kYXkgPSBkYXk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5sZWFwWWVhcih0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBlcG9jaCBkZXNpZ25hdG9yIGZvciB0aGlzIGRhdGUsIGUuZy4gQkNFIG9yIENFLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGUgY3VycmVudCBlcG9jaC4gKi9cbiAgICBlcG9jaDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5lcG9jaCh0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqIEZvcm1hdCB0aGUgeWVhciwgaWYgbm90IGEgc2ltcGxlIHNlcXVlbnRpYWwgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHllYXIuICovXG4gICAgZm9ybWF0WWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5mb3JtYXRZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG1vbnRoIG9mIHRoZSB5ZWFyIGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gdGhlIG1vbnRoJ3MgcG9zaXRpb24gd2l0aGluIGEgbnVtYmVyZWQgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG1vbnRoIG9mIHRoZSB5ZWFyOiA8Y29kZT5taW5Nb250aDwvY29kZT4gdG8gbW9udGhzIHBlciB5ZWFyLiAqL1xuICAgIG1vbnRoT2ZZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLm1vbnRoT2ZZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXI6IDEgdG8gd2Vla3MgcGVyIHllYXIuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci53ZWVrT2ZZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIHRoZSB5ZWFyIGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIHllYXIuICovXG4gICAgZGF5c0luWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5kYXlzSW5ZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGRheSBvZiB0aGUgeWVhciBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5IG9mIHRoZSB5ZWFyOiAxIHRvIGRheXMgcGVyIHllYXIuICovXG4gICAgZGF5T2ZZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmRheU9mWWVhcih0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgbW9udGggZm9yIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmRheXNJbk1vbnRoKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGRheSBvZiB0aGUgd2VlayBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5IG9mIHRoZSB3ZWVrOiAwIHRvIG51bWJlciBvZiBkYXlzIC0gMS4gKi9cbiAgICBkYXlPZldlZWs6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZGF5T2ZXZWVrKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIud2Vla0RheSh0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7b2JqZWN0fSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIC0gY29udGVudHMgZGVwZW5kcyBvbiBjYWxlbmRhci4gKi9cbiAgICBleHRyYUluZm86IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZXh0cmFJbmZvKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogQWRkIHBlcmlvZChzKSB0byBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuICovXG4gICAgYWRkOiBmdW5jdGlvbihvZmZzZXQsIHBlcmlvZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuYWRkKHRoaXMsIG9mZnNldCwgcGVyaW9kKTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBhIHBvcnRpb24gb2YgdGhlIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0gdmFsdWUge251bWJlcn0gVGhlIG5ldyB2YWx1ZSBmb3IgdGhlIHBlcmlvZC5cbiAgICAgICAgQHBhcmFtIHBlcmlvZCB7c3RyaW5nfSBPbmUgb2YgJ3knIGZvciB5ZWFyLCAnbScgZm9yIG1vbnRoLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgbm90IGEgdmFsaWQgZGF0ZS4gKi9cbiAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlLCBwZXJpb2QpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLnNldCh0aGlzLCB2YWx1ZSwgcGVyaW9kKTtcbiAgICB9LFxuXG4gICAgLyoqIENvbXBhcmUgdGhpcyBkYXRlIHRvIGFub3RoZXIgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBkYXRlIHtDRGF0ZX0gVGhlIG90aGVyIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gLTEgaWYgdGhpcyBkYXRlIGlzIGJlZm9yZSB0aGUgb3RoZXIgZGF0ZSxcbiAgICAgICAgICAgICAgICAwIGlmIHRoZXkgYXJlIGVxdWFsLCBvciArMSBpZiB0aGlzIGRhdGUgaXMgYWZ0ZXIgdGhlIG90aGVyIGRhdGUuICovXG4gICAgY29tcGFyZVRvOiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgIGlmICh0aGlzLl9jYWxlbmRhci5uYW1lICE9PSBkYXRlLl9jYWxlbmRhci5uYW1lKSB7XG4gICAgICAgICAgICB0aHJvdyAoX2V4cG9ydHMubG9jYWwuZGlmZmVyZW50Q2FsZW5kYXJzIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uZGlmZmVyZW50Q2FsZW5kYXJzKS5cbiAgICAgICAgICAgICAgICByZXBsYWNlKC9cXHswXFx9LywgdGhpcy5fY2FsZW5kYXIubG9jYWwubmFtZSkucmVwbGFjZSgvXFx7MVxcfS8sIGRhdGUuX2NhbGVuZGFyLmxvY2FsLm5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjID0gKHRoaXMuX3llYXIgIT09IGRhdGUuX3llYXIgPyB0aGlzLl95ZWFyIC0gZGF0ZS5feWVhciA6XG4gICAgICAgICAgICB0aGlzLl9tb250aCAhPT0gZGF0ZS5fbW9udGggPyB0aGlzLm1vbnRoT2ZZZWFyKCkgLSBkYXRlLm1vbnRoT2ZZZWFyKCkgOlxuICAgICAgICAgICAgdGhpcy5fZGF5IC0gZGF0ZS5fZGF5KTtcbiAgICAgICAgcmV0dXJuIChjID09PSAwID8gMCA6IChjIDwgMCA/IC0xIDogKzEpKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBjYWxlbmRhciBiYWNraW5nIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge0Jhc2VDYWxlbmRhcn0gVGhlIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uLiAqL1xuICAgIGNhbGVuZGFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIudG9KRCh0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgdGhpcyBkYXRlIHRvIGEgc3RhbmRhcmQgKEdyZWdvcmlhbikgSmF2YVNjcmlwdCBEYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7RGF0ZX0gVGhlIGVxdWl2YWxlbnQgSmF2YVNjcmlwdCBkYXRlLiAqL1xuICAgIHRvSlNEYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLnRvSlNEYXRlKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIHN0YW5kYXJkIChHcmVnb3JpYW4pIEphdmFTY3JpcHQgRGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBqc2Qge0RhdGV9IFRoZSBKYXZhU2NyaXB0IGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpTRGF0ZTogZnVuY3Rpb24oanNkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5mcm9tSlNEYXRlKGpzZCk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IHRvIGEgc3RyaW5nIGZvciBkaXNwbGF5LlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGlzIGRhdGUgYXMgYSBzdHJpbmcuICovXG4gICAgdG9TdHJpbmc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gKHRoaXMueWVhcigpIDwgMCA/ICctJyA6ICcnKSArIHBhZChNYXRoLmFicyh0aGlzLnllYXIoKSksIDQpICtcbiAgICAgICAgICAgICctJyArIHBhZCh0aGlzLm1vbnRoKCksIDIpICsgJy0nICsgcGFkKHRoaXMuZGF5KCksIDIpO1xuICAgIH1cbn0pO1xuXG4vKiogQmFzaWMgZnVuY3Rpb25hbGl0eSBmb3IgYWxsIGNhbGVuZGFycy5cbiAgICBPdGhlciBjYWxlbmRhcnMgc2hvdWxkIGV4dGVuZCB0aGlzOlxuICAgIDxwcmU+T3RoZXJDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgQmFzZUNhbGVuZGFyOzwvcHJlPlxuICAgIEBjbGFzcyBCYXNlQ2FsZW5kYXIgKi9cbmZ1bmN0aW9uIEJhc2VDYWxlbmRhcigpIHtcbiAgICB0aGlzLnNob3J0WWVhckN1dG9mZiA9ICcrMTAnO1xufVxuXG5hc3NpZ24oQmFzZUNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIF92YWxpZGF0ZUxldmVsOiAwLCAvLyBcIlN0YWNrXCIgdG8gdHVybiB2YWxpZGF0aW9uIG9uL29mZlxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIHdpdGhpbiB0aGlzIGNhbGVuZGFyIC0gdG9kYXkgaWYgbm8gcGFyYW1ldGVycyBnaXZlbi5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBkdXBsaWNhdGUgb3IgdGhlIHllYXIgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgbmV3IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgbm90IGEgdmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG5ld0RhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgaWYgKHllYXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9kYXkoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICAgICAgZGF5ID0geWVhci5kYXkoKTtcbiAgICAgICAgICAgIG1vbnRoID0geWVhci5tb250aCgpO1xuICAgICAgICAgICAgeWVhciA9IHllYXIueWVhcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQ0RhdGUodGhpcywgeWVhciwgbW9udGgsIGRheSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmb3IgdG9kYXkuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRvZGF5J3MgZGF0ZS4gKi9cbiAgICB0b2RheTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyb21KU0RhdGUobmV3IERhdGUoKSk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgZXBvY2ggZGVzaWduYXRvciBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGUgY3VycmVudCBlcG9jaC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBlcG9jaDogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZFllYXIgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAoZGF0ZS55ZWFyKCkgPCAwID8gdGhpcy5sb2NhbC5lcG9jaHNbMF0gOiB0aGlzLmxvY2FsLmVwb2Noc1sxXSk7XG4gICAgfSxcblxuICAgIC8qKiBGb3JtYXQgdGhlIHllYXIsIGlmIG5vdCBhIHNpbXBsZSBzZXF1ZW50aWFsIG51bWJlclxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGZvcm1hdCBvciB0aGUgeWVhciB0byBmb3JtYXQuXG4gICAgICAgIEByZXR1cm4ge3N0cmluZ30gVGhlIGZvcm1hdHRlZCB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGZvcm1hdFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRZZWFyIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gKGRhdGUueWVhcigpIDwgMCA/ICctJyA6ICcnKSArIHBhZChNYXRoLmFicyhkYXRlLnllYXIoKSksIDQpXG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIG1vbnRocyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRZZWFyIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gMTI7XG4gICAgfSxcblxuICAgIC8qKiBDYWxjdWxhdGUgdGhlIG1vbnRoJ3Mgb3JkaW5hbCBwb3NpdGlvbiB3aXRoaW4gdGhlIHllYXIgLVxuICAgICAgICBmb3IgdGhvc2UgY2FsZW5kYXJzIHRoYXQgZG9uJ3Qgc3RhcnQgYXQgbW9udGggMSFcbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgb3JkaW5hbCBwb3NpdGlvbiwgc3RhcnRpbmcgZnJvbSA8Y29kZT5taW5Nb250aDwvY29kZT4uXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyL21vbnRoIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbW9udGhPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZE1vbnRoIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIChkYXRlLm1vbnRoKCkgKyB0aGlzLm1vbnRoc0luWWVhcihkYXRlKSAtIHRoaXMuZmlyc3RNb250aCkgJVxuICAgICAgICAgICAgdGhpcy5tb250aHNJblllYXIoZGF0ZSkgKyB0aGlzLm1pbk1vbnRoO1xuICAgIH0sXG5cbiAgICAvKiogQ2FsY3VsYXRlIGFjdHVhbCBtb250aCBmcm9tIG9yZGluYWwgcG9zaXRpb24sIHN0YXJ0aW5nIGZyb20gbWluTW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIG9yZCB7bnVtYmVyfSBUaGUgbW9udGgncyBvcmRpbmFsIHBvc2l0aW9uLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBtb250aCdzIG51bWJlci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIvbW9udGguICovXG4gICAgZnJvbU1vbnRoT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBvcmQpIHtcbiAgICAgICAgdmFyIG0gPSAob3JkICsgdGhpcy5maXJzdE1vbnRoIC0gMiAqIHRoaXMubWluTW9udGgpICVcbiAgICAgICAgICAgIHRoaXMubW9udGhzSW5ZZWFyKHllYXIpICsgdGhpcy5taW5Nb250aDtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbSwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkTW9udGggfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkWWVhciB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuICh0aGlzLmxlYXBZZWFyKGRhdGUpID8gMzY2IDogMzY1KTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBkYXkgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkYXkgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5T2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4gZGF0ZS50b0pEKCkgLSB0aGlzLm5ld0RhdGUoZGF0ZS55ZWFyKCksXG4gICAgICAgICAgICB0aGlzLmZyb21Nb250aE9mWWVhcihkYXRlLnllYXIoKSwgdGhpcy5taW5Nb250aCksIHRoaXMubWluRGF5KS50b0pEKCkgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgd2Vlay5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy4gKi9cbiAgICBkYXlzSW5XZWVrOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDc7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgZGF5IG9mIHRoZSB3ZWVrIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5IG9mIHRoZSB3ZWVrOiAwIHRvIG51bWJlciBvZiBkYXlzIC0gMS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlPZldlZWs6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiAoTWF0aC5mbG9vcih0aGlzLnRvSkQoZGF0ZSkpICsgMikgJSB0aGlzLmRheXNJbldlZWsoKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge29iamVjdH0gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiAtIGNvbnRlbnRzIGRlcGVuZHMgb24gY2FsZW5kYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZXh0cmFJbmZvOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG5cbiAgICAvKiogQWRkIHBlcmlvZChzKSB0byBhIGRhdGUuXG4gICAgICAgIENhdGVyIGZvciBubyB5ZWFyIHplcm8uXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGRhdGUge0NEYXRlfSBUaGUgc3RhcnRpbmcgZGF0ZS5cbiAgICAgICAgQHBhcmFtIG9mZnNldCB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgdG8gYWRqdXN0IGJ5LlxuICAgICAgICBAcGFyYW0gcGVyaW9kIHtzdHJpbmd9IE9uZSBvZiAneScgZm9yIHllYXIsICdtJyBmb3IgbW9udGgsICd3JyBmb3Igd2VlaywgJ2QnIGZvciBkYXkuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgdXBkYXRlZCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgYWRkOiBmdW5jdGlvbihkYXRlLCBvZmZzZXQsIHBlcmlvZCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZShkYXRlLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4gdGhpcy5fY29ycmVjdEFkZChkYXRlLCB0aGlzLl9hZGQoZGF0ZSwgb2Zmc2V0LCBwZXJpb2QpLCBvZmZzZXQsIHBlcmlvZCk7XG4gICAgfSxcblxuICAgIC8qKiBBZGQgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0gZGF0ZSB7Q0RhdGV9IFRoZSBzdGFydGluZyBkYXRlLlxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuICovXG4gICAgX2FkZDogZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0LCBwZXJpb2QpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVMZXZlbCsrO1xuICAgICAgICBpZiAocGVyaW9kID09PSAnZCcgfHwgcGVyaW9kID09PSAndycpIHtcbiAgICAgICAgICAgIHZhciBqZCA9IGRhdGUudG9KRCgpICsgb2Zmc2V0ICogKHBlcmlvZCA9PT0gJ3cnID8gdGhpcy5kYXlzSW5XZWVrKCkgOiAxKTtcbiAgICAgICAgICAgIHZhciBkID0gZGF0ZS5jYWxlbmRhcigpLmZyb21KRChqZCk7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsLS07XG4gICAgICAgICAgICByZXR1cm4gW2QueWVhcigpLCBkLm1vbnRoKCksIGQuZGF5KCldO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgeSA9IGRhdGUueWVhcigpICsgKHBlcmlvZCA9PT0gJ3knID8gb2Zmc2V0IDogMCk7XG4gICAgICAgICAgICB2YXIgbSA9IGRhdGUubW9udGhPZlllYXIoKSArIChwZXJpb2QgPT09ICdtJyA/IG9mZnNldCA6IDApO1xuICAgICAgICAgICAgdmFyIGQgPSBkYXRlLmRheSgpOy8vICsgKHBlcmlvZCA9PT0gJ2QnID8gb2Zmc2V0IDogMCkgK1xuICAgICAgICAgICAgICAgIC8vKHBlcmlvZCA9PT0gJ3cnID8gb2Zmc2V0ICogdGhpcy5kYXlzSW5XZWVrKCkgOiAwKTtcbiAgICAgICAgICAgIHZhciByZXN5bmNZZWFyTW9udGggPSBmdW5jdGlvbihjYWxlbmRhcikge1xuICAgICAgICAgICAgICAgIHdoaWxlIChtIDwgY2FsZW5kYXIubWluTW9udGgpIHtcbiAgICAgICAgICAgICAgICAgICAgeS0tO1xuICAgICAgICAgICAgICAgICAgICBtICs9IGNhbGVuZGFyLm1vbnRoc0luWWVhcih5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHllYXJNb250aHMgPSBjYWxlbmRhci5tb250aHNJblllYXIoeSk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG0gPiB5ZWFyTW9udGhzIC0gMSArIGNhbGVuZGFyLm1pbk1vbnRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHkrKztcbiAgICAgICAgICAgICAgICAgICAgbSAtPSB5ZWFyTW9udGhzO1xuICAgICAgICAgICAgICAgICAgICB5ZWFyTW9udGhzID0gY2FsZW5kYXIubW9udGhzSW5ZZWFyKHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocGVyaW9kID09PSAneScpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZS5tb250aCgpICE9PSB0aGlzLmZyb21Nb250aE9mWWVhcih5LCBtKSkgeyAvLyBIZWJyZXdcbiAgICAgICAgICAgICAgICAgICAgbSA9IHRoaXMubmV3RGF0ZSh5LCBkYXRlLm1vbnRoKCksIHRoaXMubWluRGF5KS5tb250aE9mWWVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtID0gTWF0aC5taW4obSwgdGhpcy5tb250aHNJblllYXIoeSkpO1xuICAgICAgICAgICAgICAgIGQgPSBNYXRoLm1pbihkLCB0aGlzLmRheXNJbk1vbnRoKHksIHRoaXMuZnJvbU1vbnRoT2ZZZWFyKHksIG0pKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwZXJpb2QgPT09ICdtJykge1xuICAgICAgICAgICAgICAgIHJlc3luY1llYXJNb250aCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkID0gTWF0aC5taW4oZCwgdGhpcy5kYXlzSW5Nb250aCh5LCB0aGlzLmZyb21Nb250aE9mWWVhcih5LCBtKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHltZCA9IFt5LCB0aGlzLmZyb21Nb250aE9mWWVhcih5LCBtKSwgZF07XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsLS07XG4gICAgICAgICAgICByZXR1cm4geW1kO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsLS07XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBDb3JyZWN0IGEgY2FuZGlkYXRlIGRhdGUgYWZ0ZXIgYWRkaW5nIHBlcmlvZChzKSB0byBhIGRhdGUuXG4gICAgICAgIEhhbmRsZSBubyB5ZWFyIHplcm8gaWYgbmVjZXNzYXJ5LlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSBkYXRlIHtDRGF0ZX0gVGhlIHN0YXJ0aW5nIGRhdGUuXG4gICAgICAgIEBwYXJhbSB5bWQge251bWJlcltdfSBUaGUgYWRkZWQgZGF0ZS5cbiAgICAgICAgQHBhcmFtIG9mZnNldCB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHBlcmlvZHMgdG8gYWRqdXN0IGJ5LlxuICAgICAgICBAcGFyYW0gcGVyaW9kIHtzdHJpbmd9IE9uZSBvZiAneScgZm9yIHllYXIsICdtJyBmb3IgbW9udGgsICd3JyBmb3Igd2VlaywgJ2QnIGZvciBkYXkuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgdXBkYXRlZCBkYXRlLiAqL1xuICAgIF9jb3JyZWN0QWRkOiBmdW5jdGlvbihkYXRlLCB5bWQsIG9mZnNldCwgcGVyaW9kKSB7XG4gICAgICAgIGlmICghdGhpcy5oYXNZZWFyWmVybyAmJiAocGVyaW9kID09PSAneScgfHwgcGVyaW9kID09PSAnbScpKSB7XG4gICAgICAgICAgICBpZiAoeW1kWzBdID09PSAwIHx8IC8vIEluIHllYXIgemVyb1xuICAgICAgICAgICAgICAgICAgICAoZGF0ZS55ZWFyKCkgPiAwKSAhPT0gKHltZFswXSA+IDApKSB7IC8vIENyb3NzZWQgeWVhciB6ZXJvXG4gICAgICAgICAgICAgICAgdmFyIGFkaiA9IHt5OiBbMSwgMSwgJ3knXSwgbTogWzEsIHRoaXMubW9udGhzSW5ZZWFyKC0xKSwgJ20nXSxcbiAgICAgICAgICAgICAgICAgICAgdzogW3RoaXMuZGF5c0luV2VlaygpLCB0aGlzLmRheXNJblllYXIoLTEpLCAnZCddLFxuICAgICAgICAgICAgICAgICAgICBkOiBbMSwgdGhpcy5kYXlzSW5ZZWFyKC0xKSwgJ2QnXX1bcGVyaW9kXTtcbiAgICAgICAgICAgICAgICB2YXIgZGlyID0gKG9mZnNldCA8IDAgPyAtMSA6ICsxKTtcbiAgICAgICAgICAgICAgICB5bWQgPSB0aGlzLl9hZGQoZGF0ZSwgb2Zmc2V0ICogYWRqWzBdICsgZGlyICogYWRqWzFdLCBhZGpbMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRlLmRhdGUoeW1kWzBdLCB5bWRbMV0sIHltZFsyXSk7XG4gICAgfSxcblxuICAgIC8qKiBTZXQgYSBwb3J0aW9uIG9mIHRoZSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBkYXRlIHtDRGF0ZX0gVGhlIHN0YXJ0aW5nIGRhdGUuXG4gICAgICAgIEBwYXJhbSB2YWx1ZSB7bnVtYmVyfSBUaGUgbmV3IHZhbHVlIGZvciB0aGUgcGVyaW9kLlxuICAgICAgICBAcGFyYW0gcGVyaW9kIHtzdHJpbmd9IE9uZSBvZiAneScgZm9yIHllYXIsICdtJyBmb3IgbW9udGgsICdkJyBmb3IgZGF5LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIHVwZGF0ZWQgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBzZXQ6IGZ1bmN0aW9uKGRhdGUsIHZhbHVlLCBwZXJpb2QpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoZGF0ZSwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKTtcbiAgICAgICAgdmFyIHkgPSAocGVyaW9kID09PSAneScgPyB2YWx1ZSA6IGRhdGUueWVhcigpKTtcbiAgICAgICAgdmFyIG0gPSAocGVyaW9kID09PSAnbScgPyB2YWx1ZSA6IGRhdGUubW9udGgoKSk7XG4gICAgICAgIHZhciBkID0gKHBlcmlvZCA9PT0gJ2QnID8gdmFsdWUgOiBkYXRlLmRheSgpKTtcbiAgICAgICAgaWYgKHBlcmlvZCA9PT0gJ3knIHx8IHBlcmlvZCA9PT0gJ20nKSB7XG4gICAgICAgICAgICBkID0gTWF0aC5taW4oZCwgdGhpcy5kYXlzSW5Nb250aCh5LCBtKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGUuZGF0ZSh5LCBtLCBkKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIGEgZGF0ZSBpcyB2YWxpZCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBkYXkge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHZhbGlkIGRhdGUsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuICovXG4gICAgaXNWYWxpZDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsKys7XG4gICAgICAgIHZhciB2YWxpZCA9ICh0aGlzLmhhc1llYXJaZXJvIHx8IHllYXIgIT09IDApO1xuICAgICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgICAgIHZhciBkYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSk7XG4gICAgICAgICAgICB2YWxpZCA9IChtb250aCA+PSB0aGlzLm1pbk1vbnRoICYmIG1vbnRoIC0gdGhpcy5taW5Nb250aCA8IHRoaXMubW9udGhzSW5ZZWFyKGRhdGUpKSAmJlxuICAgICAgICAgICAgICAgIChkYXkgPj0gdGhpcy5taW5EYXkgJiYgZGF5IC0gdGhpcy5taW5EYXkgPCB0aGlzLmRheXNJbk1vbnRoKGRhdGUpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsLS07XG4gICAgICAgIHJldHVybiB2YWxpZDtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgdGhlIGRhdGUgdG8gYSBzdGFuZGFyZCAoR3JlZ29yaWFuKSBKYXZhU2NyaXB0IERhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7RGF0ZX0gVGhlIGVxdWl2YWxlbnQgSmF2YVNjcmlwdCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSlNEYXRlOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4gX2V4cG9ydHMuaW5zdGFuY2UoKS5mcm9tSkQodGhpcy50b0pEKGRhdGUpKS50b0pTRGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCB0aGUgZGF0ZSBmcm9tIGEgc3RhbmRhcmQgKEdyZWdvcmlhbikgSmF2YVNjcmlwdCBEYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqc2Qge0RhdGV9IFRoZSBKYXZhU2NyaXB0IGRhdGUuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBjYWxlbmRhciBkYXRlLiAqL1xuICAgIGZyb21KU0RhdGU6IGZ1bmN0aW9uKGpzZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mcm9tSkQoX2V4cG9ydHMuaW5zdGFuY2UoKS5mcm9tSlNEYXRlKGpzZCkudG9KRCgpKTtcbiAgICB9LFxuXG4gICAgLyoqIENoZWNrIHRoYXQgYSBjYW5kaWRhdGUgZGF0ZSBpcyBmcm9tIHRoZSBzYW1lIGNhbGVuZGFyIGFuZCBpcyB2YWxpZC5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byB2YWxpZGF0ZSBvciB0aGUgeWVhciB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIGVycm9yIHtzdHJpbmd9IFJycm9yIG1lc3NhZ2UgaWYgaW52YWxpZC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBkaWZmZXJlbnQgY2FsZW5kYXJzIHVzZWQgb3IgaW52YWxpZCBkYXRlLiAqL1xuICAgIF92YWxpZGF0ZTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSwgZXJyb3IpIHtcbiAgICAgICAgaWYgKHllYXIueWVhcikge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3ZhbGlkYXRlTGV2ZWwgPT09IDAgJiYgdGhpcy5uYW1lICE9PSB5ZWFyLmNhbGVuZGFyKCkubmFtZSkge1xuICAgICAgICAgICAgICAgIHRocm93IChfZXhwb3J0cy5sb2NhbC5kaWZmZXJlbnRDYWxlbmRhcnMgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5kaWZmZXJlbnRDYWxlbmRhcnMpLlxuICAgICAgICAgICAgICAgICAgICByZXBsYWNlKC9cXHswXFx9LywgdGhpcy5sb2NhbC5uYW1lKS5yZXBsYWNlKC9cXHsxXFx9LywgeWVhci5jYWxlbmRhcigpLmxvY2FsLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHllYXI7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwrKztcbiAgICAgICAgICAgIGlmICh0aGlzLl92YWxpZGF0ZUxldmVsID09PSAxICYmICF0aGlzLmlzVmFsaWQoeWVhciwgbW9udGgsIGRheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvci5yZXBsYWNlKC9cXHswXFx9LywgdGhpcy5sb2NhbC5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVMZXZlbC0tO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwtLTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBQcm9sZXB0aWMgR3JlZ29yaWFuIENhbGVuZGFyLlxuICAgIFNlZSA8YSBocmVmPVwiOmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR3JlZ29yaWFuX2NhbGVuZGFyXCI+aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HcmVnb3JpYW5fY2FsZW5kYXI8L2E+XG4gICAgYW5kIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Byb2xlcHRpY19HcmVnb3JpYW5fY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Byb2xlcHRpY19HcmVnb3JpYW5fY2FsZW5kYXI8L2E+LlxuICAgIEBjbGFzcyBHcmVnb3JpYW5DYWxlbmRhclxuICAgIEBhdWdtZW50cyBCYXNlQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gR3JlZ29yaWFuQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2VdIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuR3JlZ29yaWFuQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IEJhc2VDYWxlbmRhcjtcblxuYXNzaWduKEdyZWdvcmlhbkNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyICovXG4gICAgbmFtZTogJ0dyZWdvcmlhbicsXG4gICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBHcmVnb3JpYW4gZXBvY2g6IDEgSmFudWFyeSAwMDAxIENFLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxNzIxNDI1LjUsXG4gICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMjgsIDMxLCAzMCwgMzEsIDMwLCAzMSwgMzEsIDMwLCAzMSwgMzAsIDMxXSxcbiAgICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IGZhbHNlLFxuICAgIC8qKiBUaGUgbWluaW11bSBtb250aCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdHcmVnb3JpYW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JDRScsICdDRSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnbW0vZGQveXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcbiAgICBcbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkWWVhciB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSBkYXRlLnllYXIoKSArIChkYXRlLnllYXIoKSA8IDAgPyAxIDogMCk7IC8vIE5vIHllYXIgemVyb1xuICAgICAgICByZXR1cm4geWVhciAlIDQgPT09IDAgJiYgKHllYXIgJSAxMDAgIT09IDAgfHwgeWVhciAlIDQwMCA9PT0gMCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhciwgc3RhcnRpbmcgZnJvbSAxLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBUaHVyc2RheSBvZiB0aGlzIHdlZWsgc3RhcnRpbmcgb24gTW9uZGF5XG4gICAgICAgIHZhciBjaGVja0RhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgIGNoZWNrRGF0ZS5hZGQoNCAtIChjaGVja0RhdGUuZGF5T2ZXZWVrKCkgfHwgNyksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkTW9udGggfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV0gK1xuICAgICAgICAgICAgKGRhdGUubW9udGgoKSA9PT0gMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIGlmICh5ZWFyIDwgMCkgeyB5ZWFyKys7IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIC8vIEplYW4gTWVldXMgYWxnb3JpdGhtLCBcIkFzdHJvbm9taWNhbCBBbGdvcml0aG1zXCIsIDE5OTFcbiAgICAgICAgaWYgKG1vbnRoIDwgMykge1xuICAgICAgICAgICAgbW9udGggKz0gMTI7XG4gICAgICAgICAgICB5ZWFyLS07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGEgPSBNYXRoLmZsb29yKHllYXIgLyAxMDApO1xuICAgICAgICB2YXIgYiA9IDIgLSBhICsgTWF0aC5mbG9vcihhIC8gNCk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKDM2NS4yNSAqICh5ZWFyICsgNDcxNikpICtcbiAgICAgICAgICAgIE1hdGguZmxvb3IoMzAuNjAwMSAqIChtb250aCArIDEpKSArIGRheSArIGIgLSAxNTI0LjU7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgLy8gSmVhbiBNZWV1cyBhbGdvcml0aG0sIFwiQXN0cm9ub21pY2FsIEFsZ29yaXRobXNcIiwgMTk5MVxuICAgICAgICB2YXIgeiA9IE1hdGguZmxvb3IoamQgKyAwLjUpO1xuICAgICAgICB2YXIgYSA9IE1hdGguZmxvb3IoKHogLSAxODY3MjE2LjI1KSAvIDM2NTI0LjI1KTtcbiAgICAgICAgYSA9IHogKyAxICsgYSAtIE1hdGguZmxvb3IoYSAvIDQpO1xuICAgICAgICB2YXIgYiA9IGEgKyAxNTI0O1xuICAgICAgICB2YXIgYyA9IE1hdGguZmxvb3IoKGIgLSAxMjIuMSkgLyAzNjUuMjUpO1xuICAgICAgICB2YXIgZCA9IE1hdGguZmxvb3IoMzY1LjI1ICogYyk7XG4gICAgICAgIHZhciBlID0gTWF0aC5mbG9vcigoYiAtIGQpIC8gMzAuNjAwMSk7XG4gICAgICAgIHZhciBkYXkgPSBiIC0gZCAtIE1hdGguZmxvb3IoZSAqIDMwLjYwMDEpO1xuICAgICAgICB2YXIgbW9udGggPSBlIC0gKGUgPiAxMy41ID8gMTMgOiAxKTtcbiAgICAgICAgdmFyIHllYXIgPSBjIC0gKG1vbnRoID4gMi41ID8gNDcxNiA6IDQ3MTUpO1xuICAgICAgICBpZiAoeWVhciA8PSAwKSB7IHllYXItLTsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgdGhpcyBkYXRlIHRvIGEgc3RhbmRhcmQgKEdyZWdvcmlhbikgSmF2YVNjcmlwdCBEYXRlLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7RGF0ZX0gVGhlIGVxdWl2YWxlbnQgSmF2YVNjcmlwdCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSlNEYXRlOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICB2YXIganNkID0gbmV3IERhdGUoZGF0ZS55ZWFyKCksIGRhdGUubW9udGgoKSAtIDEsIGRhdGUuZGF5KCkpO1xuICAgICAgICBqc2Quc2V0SG91cnMoMCk7XG4gICAgICAgIGpzZC5zZXRNaW51dGVzKDApO1xuICAgICAgICBqc2Quc2V0U2Vjb25kcygwKTtcbiAgICAgICAganNkLnNldE1pbGxpc2Vjb25kcygwKTtcbiAgICAgICAgLy8gSG91cnMgbWF5IGJlIG5vbi16ZXJvIG9uIGRheWxpZ2h0IHNhdmluZyBjdXQtb3ZlcjpcbiAgICAgICAgLy8gPiAxMiB3aGVuIG1pZG5pZ2h0IGNoYW5nZW92ZXIsIGJ1dCB0aGVuIGNhbm5vdCBnZW5lcmF0ZVxuICAgICAgICAvLyBtaWRuaWdodCBkYXRldGltZSwgc28ganVtcCB0byAxQU0sIG90aGVyd2lzZSByZXNldC5cbiAgICAgICAganNkLnNldEhvdXJzKGpzZC5nZXRIb3VycygpID4gMTIgPyBqc2QuZ2V0SG91cnMoKSArIDIgOiAwKTtcbiAgICAgICAgcmV0dXJuIGpzZDtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBzdGFuZGFyZCAoR3JlZ29yaWFuKSBKYXZhU2NyaXB0IERhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0ganNkIHtEYXRlfSBUaGUgSmF2YVNjcmlwdCBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KU0RhdGU6IGZ1bmN0aW9uKGpzZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKGpzZC5nZXRGdWxsWWVhcigpLCBqc2QuZ2V0TW9udGgoKSArIDEsIGpzZC5nZXREYXRlKCkpO1xuICAgIH1cbn0pO1xuXG4vLyBTaW5nbGV0b24gbWFuYWdlclxudmFyIF9leHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBuZXcgQ2FsZW5kYXJzKCk7XG5cbi8vIERhdGUgdGVtcGxhdGVcbl9leHBvcnRzLmNkYXRlID0gQ0RhdGU7XG5cbi8vIEJhc2UgY2FsZW5kYXIgdGVtcGxhdGVcbl9leHBvcnRzLmJhc2VDYWxlbmRhciA9IEJhc2VDYWxlbmRhcjtcblxuLy8gR3JlZ29yaWFuIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5fZXhwb3J0cy5jYWxlbmRhcnMuZ3JlZ29yaWFuID0gR3JlZ29yaWFuQ2FsZW5kYXI7XG5cbiIsIi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgQ2FsZW5kYXJzIGV4dHJhcyBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEF1Z3VzdCAyMDA5LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgYXNzaWduID0gcmVxdWlyZSgnb2JqZWN0LWFzc2lnbicpO1xudmFyIG1haW4gPSByZXF1aXJlKCcuL21haW4nKTtcblxuXG5hc3NpZ24obWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLCB7XG4gICAgaW52YWxpZEFyZ3VtZW50czogJ0ludmFsaWQgYXJndW1lbnRzJyxcbiAgICBpbnZhbGlkRm9ybWF0OiAnQ2Fubm90IGZvcm1hdCBhIGRhdGUgZnJvbSBhbm90aGVyIGNhbGVuZGFyJyxcbiAgICBtaXNzaW5nTnVtYmVyQXQ6ICdNaXNzaW5nIG51bWJlciBhdCBwb3NpdGlvbiB7MH0nLFxuICAgIHVua25vd25OYW1lQXQ6ICdVbmtub3duIG5hbWUgYXQgcG9zaXRpb24gezB9JyxcbiAgICB1bmV4cGVjdGVkTGl0ZXJhbEF0OiAnVW5leHBlY3RlZCBsaXRlcmFsIGF0IHBvc2l0aW9uIHswfScsXG4gICAgdW5leHBlY3RlZFRleHQ6ICdBZGRpdGlvbmFsIHRleHQgZm91bmQgYXQgZW5kJ1xufSk7XG5tYWluLmxvY2FsID0gbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddO1xuXG5hc3NpZ24obWFpbi5jZGF0ZS5wcm90b3R5cGUsIHtcblxuICAgIC8qKiBGb3JtYXQgdGhpcyBkYXRlLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0gW2Zvcm1hdF0ge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IHRvIHVzZSAoc2VlIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+KS5cbiAgICAgICAgQHBhcmFtIFtzZXR0aW5nc10ge29iamVjdH0gT3B0aW9ucyBmb3IgdGhlIDxjb2RlPmZvcm1hdERhdGU8L2NvZGU+IGZ1bmN0aW9uLlxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgZGF0ZS4gKi9cbiAgICBmb3JtYXREYXRlOiBmdW5jdGlvbihmb3JtYXQsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBmb3JtYXQ7XG4gICAgICAgICAgICBmb3JtYXQgPSAnJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZm9ybWF0RGF0ZShmb3JtYXQgfHwgJycsIHRoaXMsIHNldHRpbmdzKTtcbiAgICB9XG59KTtcblxuYXNzaWduKG1haW4uYmFzZUNhbGVuZGFyLnByb3RvdHlwZSwge1xuXG4gICAgVU5JWF9FUE9DSDogbWFpbi5pbnN0YW5jZSgpLm5ld0RhdGUoMTk3MCwgMSwgMSkudG9KRCgpLFxuICAgIFNFQ1NfUEVSX0RBWTogMjQgKiA2MCAqIDYwLFxuICAgIFRJQ0tTX0VQT0NIOiBtYWluLmluc3RhbmNlKCkuamRFcG9jaCwgLy8gMSBKYW51YXJ5IDAwMDEgQ0VcbiAgICBUSUNLU19QRVJfREFZOiAyNCAqIDYwICogNjAgKiAxMDAwMDAwMCxcblxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIEFUT00gKFJGQyAzMzM5L0lTTyA4NjAxKS5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyICovXG4gICAgQVRPTTogJ3l5eXktbW0tZGQnLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIGNvb2tpZXMuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIENPT0tJRTogJ0QsIGRkIE0geXl5eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgZnVsbCBkYXRlLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBGVUxMOiAnREQsIE1NIGQsIHl5eXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIElTTyA4NjAxLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBJU09fODYwMTogJ3l5eXktbW0tZGQnLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIEp1bGlhbiBkYXRlLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBKVUxJQU46ICdKJyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBSRkMgODIyLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBSRkNfODIyOiAnRCwgZCBNIHl5JyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBSRkMgODUwLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBSRkNfODUwOiAnREQsIGRkLU0teXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFJGQyAxMDM2LlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBSRkNfMTAzNjogJ0QsIGQgTSB5eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgUkZDIDExMjMuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJGQ18xMTIzOiAnRCwgZCBNIHl5eXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFJGQyAyODIyLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBSRkNfMjgyMjogJ0QsIGQgTSB5eXl5JyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBSU1MgKFJGQyA4MjIpLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBSU1M6ICdELCBkIE0geXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFdpbmRvd3MgdGlja3MuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFRJQ0tTOiAnIScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgVW5peCB0aW1lc3RhbXAuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFRJTUVTVEFNUDogJ0AnLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFczYyAoSVNPIDg2MDEpLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBXM0M6ICd5eXl5LW1tLWRkJyxcblxuICAgIC8qKiBGb3JtYXQgYSBkYXRlIG9iamVjdCBpbnRvIGEgc3RyaW5nIHZhbHVlLlxuICAgICAgICBUaGUgZm9ybWF0IGNhbiBiZSBjb21iaW5hdGlvbnMgb2YgdGhlIGZvbGxvd2luZzpcbiAgICAgICAgPHVsPlxuICAgICAgICA8bGk+ZCAgLSBkYXkgb2YgbW9udGggKG5vIGxlYWRpbmcgemVybyk8L2xpPlxuICAgICAgICA8bGk+ZGQgLSBkYXkgb2YgbW9udGggKHR3byBkaWdpdCk8L2xpPlxuICAgICAgICA8bGk+byAgLSBkYXkgb2YgeWVhciAobm8gbGVhZGluZyB6ZXJvcyk8L2xpPlxuICAgICAgICA8bGk+b28gLSBkYXkgb2YgeWVhciAodGhyZWUgZGlnaXQpPC9saT5cbiAgICAgICAgPGxpPkQgIC0gZGF5IG5hbWUgc2hvcnQ8L2xpPlxuICAgICAgICA8bGk+REQgLSBkYXkgbmFtZSBsb25nPC9saT5cbiAgICAgICAgPGxpPncgIC0gd2VlayBvZiB5ZWFyIChubyBsZWFkaW5nIHplcm8pPC9saT5cbiAgICAgICAgPGxpPnd3IC0gd2VlayBvZiB5ZWFyICh0d28gZGlnaXQpPC9saT5cbiAgICAgICAgPGxpPm0gIC0gbW9udGggb2YgeWVhciAobm8gbGVhZGluZyB6ZXJvKTwvbGk+XG4gICAgICAgIDxsaT5tbSAtIG1vbnRoIG9mIHllYXIgKHR3byBkaWdpdCk8L2xpPlxuICAgICAgICA8bGk+TSAgLSBtb250aCBuYW1lIHNob3J0PC9saT5cbiAgICAgICAgPGxpPk1NIC0gbW9udGggbmFtZSBsb25nPC9saT5cbiAgICAgICAgPGxpPnl5IC0geWVhciAodHdvIGRpZ2l0KTwvbGk+XG4gICAgICAgIDxsaT55eXl5IC0geWVhciAoZm91ciBkaWdpdCk8L2xpPlxuICAgICAgICA8bGk+WVlZWSAtIGZvcm1hdHRlZCB5ZWFyPC9saT5cbiAgICAgICAgPGxpPkogIC0gSnVsaWFuIGRhdGUgKGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbik8L2xpPlxuICAgICAgICA8bGk+QCAgLSBVbml4IHRpbWVzdGFtcCAocyBzaW5jZSAwMS8wMS8xOTcwKTwvbGk+XG4gICAgICAgIDxsaT4hICAtIFdpbmRvd3MgdGlja3MgKDEwMG5zIHNpbmNlIDAxLzAxLzAwMDEpPC9saT5cbiAgICAgICAgPGxpPicuLi4nIC0gbGl0ZXJhbCB0ZXh0PC9saT5cbiAgICAgICAgPGxpPicnIC0gc2luZ2xlIHF1b3RlPC9saT5cbiAgICAgICAgPC91bD5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBbZm9ybWF0XSB7c3RyaW5nfSBUaGUgZGVzaXJlZCBmb3JtYXQgb2YgdGhlIGRhdGUgKGRlZmF1bHRzIHRvIGNhbGVuZGFyIGZvcm1hdCkuXG4gICAgICAgIEBwYXJhbSBkYXRlIHtDRGF0ZX0gVGhlIGRhdGUgdmFsdWUgdG8gZm9ybWF0LlxuICAgICAgICBAcGFyYW0gW3NldHRpbmdzXSB7b2JqZWN0fSBBZGRpdGlvbiBvcHRpb25zLCB3aG9zZSBhdHRyaWJ1dGVzIGluY2x1ZGU6XG4gICAgICAgIEBwcm9wZXJ0eSBbZGF5TmFtZXNTaG9ydF0ge3N0cmluZ1tdfSBBYmJyZXZpYXRlZCBuYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFtkYXlOYW1lc10ge3N0cmluZ1tdfSBOYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzU2hvcnRdIHtzdHJpbmdbXX0gQWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIG1vbnRocy5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzXSB7c3RyaW5nW119IE5hbWVzIG9mIHRoZSBtb250aHMuXG4gICAgICAgIEBwcm9wZXJ0eSBbY2FsY3VsYXRlV2Vla10ge0NhbGVuZGFyc1BpY2tlckNhbGN1bGF0ZVdlZWt9IEZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgW2xvY2FsTnVtYmVycz1mYWxzZV0ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IHRvIGxvY2FsaXNlIG51bWJlcnMgKGlmIGF2YWlsYWJsZSksXG4gICAgICAgICAgICAgICAgICA8Y29kZT5mYWxzZTwvY29kZT4gdG8gdXNlIG5vcm1hbCBBcmFiaWMgbnVtZXJhbHMuXG4gICAgICAgIEByZXR1cm4ge3N0cmluZ30gVGhlIGRhdGUgaW4gdGhlIGFib3ZlIGZvcm1hdC5cbiAgICAgICAgQHRocm93cyBFcnJvcnMgaWYgdGhlIGRhdGUgaXMgZnJvbSBhIGRpZmZlcmVudCBjYWxlbmRhci4gKi9cbiAgICBmb3JtYXREYXRlOiBmdW5jdGlvbihmb3JtYXQsIGRhdGUsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBkYXRlO1xuICAgICAgICAgICAgZGF0ZSA9IGZvcm1hdDtcbiAgICAgICAgICAgIGZvcm1hdCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkYXRlLmNhbGVuZGFyKCkgIT09IHRoaXMpIHtcbiAgICAgICAgICAgIHRocm93IG1haW4ubG9jYWwuaW52YWxpZEZvcm1hdCB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZEZvcm1hdDtcbiAgICAgICAgfVxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgdGhpcy5sb2NhbC5kYXRlRm9ybWF0O1xuICAgICAgICBzZXR0aW5ncyA9IHNldHRpbmdzIHx8IHt9O1xuICAgICAgICB2YXIgZGF5TmFtZXNTaG9ydCA9IHNldHRpbmdzLmRheU5hbWVzU2hvcnQgfHwgdGhpcy5sb2NhbC5kYXlOYW1lc1Nob3J0O1xuICAgICAgICB2YXIgZGF5TmFtZXMgPSBzZXR0aW5ncy5kYXlOYW1lcyB8fCB0aGlzLmxvY2FsLmRheU5hbWVzO1xuICAgICAgICB2YXIgbW9udGhOdW1iZXJzID0gc2V0dGluZ3MubW9udGhOdW1iZXJzIHx8IHRoaXMubG9jYWwubW9udGhOdW1iZXJzO1xuICAgICAgICB2YXIgbW9udGhOYW1lc1Nob3J0ID0gc2V0dGluZ3MubW9udGhOYW1lc1Nob3J0IHx8IHRoaXMubG9jYWwubW9udGhOYW1lc1Nob3J0O1xuICAgICAgICB2YXIgbW9udGhOYW1lcyA9IHNldHRpbmdzLm1vbnRoTmFtZXMgfHwgdGhpcy5sb2NhbC5tb250aE5hbWVzO1xuICAgICAgICB2YXIgY2FsY3VsYXRlV2VlayA9IHNldHRpbmdzLmNhbGN1bGF0ZVdlZWsgfHwgdGhpcy5sb2NhbC5jYWxjdWxhdGVXZWVrO1xuICAgICAgICAvLyBDaGVjayB3aGV0aGVyIGEgZm9ybWF0IGNoYXJhY3RlciBpcyBkb3VibGVkXG4gICAgICAgIHZhciBkb3VibGVkID0gZnVuY3Rpb24obWF0Y2gsIHN0ZXApIHtcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gMTtcbiAgICAgICAgICAgIHdoaWxlIChpRm9ybWF0ICsgbWF0Y2hlcyA8IGZvcm1hdC5sZW5ndGggJiYgZm9ybWF0LmNoYXJBdChpRm9ybWF0ICsgbWF0Y2hlcykgPT09IG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hlcysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaUZvcm1hdCArPSBtYXRjaGVzIC0gMTtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG1hdGNoZXMgLyAoc3RlcCB8fCAxKSkgPiAxO1xuICAgICAgICB9O1xuICAgICAgICAvLyBGb3JtYXQgYSBudW1iZXIsIHdpdGggbGVhZGluZyB6ZXJvZXMgaWYgbmVjZXNzYXJ5XG4gICAgICAgIHZhciBmb3JtYXROdW1iZXIgPSBmdW5jdGlvbihtYXRjaCwgdmFsdWUsIGxlbiwgc3RlcCkge1xuICAgICAgICAgICAgdmFyIG51bSA9ICcnICsgdmFsdWU7XG4gICAgICAgICAgICBpZiAoZG91YmxlZChtYXRjaCwgc3RlcCkpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAobnVtLmxlbmd0aCA8IGxlbikge1xuICAgICAgICAgICAgICAgICAgICBudW0gPSAnMCcgKyBudW07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRm9ybWF0IGEgbmFtZSwgc2hvcnQgb3IgbG9uZyBhcyByZXF1ZXN0ZWRcbiAgICAgICAgdmFyIGZvcm1hdE5hbWUgPSBmdW5jdGlvbihtYXRjaCwgdmFsdWUsIHNob3J0TmFtZXMsIGxvbmdOYW1lcykge1xuICAgICAgICAgICAgcmV0dXJuIChkb3VibGVkKG1hdGNoKSA/IGxvbmdOYW1lc1t2YWx1ZV0gOiBzaG9ydE5hbWVzW3ZhbHVlXSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEZvcm1hdCBtb250aCBudW1iZXJcbiAgICAgICAgLy8gKGUuZy4gQ2hpbmVzZSBjYWxlbmRhciBuZWVkcyB0byBhY2NvdW50IGZvciBpbnRlcmNhbGFyeSBtb250aHMpXG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXM7XG4gICAgICAgIHZhciBmb3JtYXRNb250aCA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiAodHlwZW9mIG1vbnRoTnVtYmVycyA9PT0gJ2Z1bmN0aW9uJykgP1xuICAgICAgICAgICAgICAgIG1vbnRoTnVtYmVycy5jYWxsKGNhbGVuZGFyLCBkYXRlLCBkb3VibGVkKCdtJykpIDpcbiAgICAgICAgICAgICAgICBsb2NhbGlzZU51bWJlcnMoZm9ybWF0TnVtYmVyKCdtJywgZGF0ZS5tb250aCgpLCAyKSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEZvcm1hdCBhIG1vbnRoIG5hbWUsIHNob3J0IG9yIGxvbmcgYXMgcmVxdWVzdGVkXG4gICAgICAgIHZhciBmb3JtYXRNb250aE5hbWUgPSBmdW5jdGlvbihkYXRlLCB1c2VMb25nTmFtZSkge1xuICAgICAgICAgICAgaWYgKHVzZUxvbmdOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICh0eXBlb2YgbW9udGhOYW1lcyA9PT0gJ2Z1bmN0aW9uJykgP1xuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzLmNhbGwoY2FsZW5kYXIsIGRhdGUpIDpcbiAgICAgICAgICAgICAgICAgICAgbW9udGhOYW1lc1tkYXRlLm1vbnRoKCkgLSBjYWxlbmRhci5taW5Nb250aF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAodHlwZW9mIG1vbnRoTmFtZXNTaG9ydCA9PT0gJ2Z1bmN0aW9uJykgP1xuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzU2hvcnQuY2FsbChjYWxlbmRhciwgZGF0ZSkgOlxuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzU2hvcnRbZGF0ZS5tb250aCgpIC0gY2FsZW5kYXIubWluTW9udGhdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvLyBMb2NhbGlzZSBudW1iZXJzIGlmIHJlcXVlc3RlZCBhbmQgYXZhaWxhYmxlXG4gICAgICAgIHZhciBkaWdpdHMgPSB0aGlzLmxvY2FsLmRpZ2l0cztcbiAgICAgICAgdmFyIGxvY2FsaXNlTnVtYmVycyA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gKHNldHRpbmdzLmxvY2FsTnVtYmVycyAmJiBkaWdpdHMgPyBkaWdpdHModmFsdWUpIDogdmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgb3V0cHV0ID0gJyc7XG4gICAgICAgIHZhciBsaXRlcmFsID0gZmFsc2U7XG4gICAgICAgIGZvciAodmFyIGlGb3JtYXQgPSAwOyBpRm9ybWF0IDwgZm9ybWF0Lmxlbmd0aDsgaUZvcm1hdCsrKSB7XG4gICAgICAgICAgICBpZiAobGl0ZXJhbCkge1xuICAgICAgICAgICAgICAgIGlmIChmb3JtYXQuY2hhckF0KGlGb3JtYXQpID09PSBcIidcIiAmJiAhZG91YmxlZChcIidcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbGl0ZXJhbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IGZvcm1hdC5jaGFyQXQoaUZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChmb3JtYXQuY2hhckF0KGlGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2QnOiBvdXRwdXQgKz0gbG9jYWxpc2VOdW1iZXJzKGZvcm1hdE51bWJlcignZCcsIGRhdGUuZGF5KCksIDIpKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ0QnOiBvdXRwdXQgKz0gZm9ybWF0TmFtZSgnRCcsIGRhdGUuZGF5T2ZXZWVrKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXlOYW1lc1Nob3J0LCBkYXlOYW1lcyk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdvJzogb3V0cHV0ICs9IGZvcm1hdE51bWJlcignbycsIGRhdGUuZGF5T2ZZZWFyKCksIDMpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndyc6IG91dHB1dCArPSBmb3JtYXROdW1iZXIoJ3cnLCBkYXRlLndlZWtPZlllYXIoKSwgMik7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdtJzogb3V0cHV0ICs9IGZvcm1hdE1vbnRoKGRhdGUpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnTSc6IG91dHB1dCArPSBmb3JtYXRNb250aE5hbWUoZGF0ZSwgZG91YmxlZCgnTScpKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IChkb3VibGVkKCd5JywgMikgPyBkYXRlLnllYXIoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRhdGUueWVhcigpICUgMTAwIDwgMTAgPyAnMCcgOiAnJykgKyBkYXRlLnllYXIoKSAlIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnWSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBkb3VibGVkKCdZJywgMik7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gZGF0ZS5mb3JtYXRZZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnSic6IG91dHB1dCArPSBkYXRlLnRvSkQoKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ0AnOiBvdXRwdXQgKz0gKGRhdGUudG9KRCgpIC0gdGhpcy5VTklYX0VQT0NIKSAqIHRoaXMuU0VDU19QRVJfREFZOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnISc6IG91dHB1dCArPSAoZGF0ZS50b0pEKCkgLSB0aGlzLlRJQ0tTX0VQT0NIKSAqIHRoaXMuVElDS1NfUEVSX0RBWTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCInXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG91YmxlZChcIidcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXRlcmFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IGZvcm1hdC5jaGFyQXQoaUZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfSxcblxuICAgIC8qKiBQYXJzZSBhIHN0cmluZyB2YWx1ZSBpbnRvIGEgZGF0ZSBvYmplY3QuXG4gICAgICAgIFNlZSA8YSBocmVmPVwiI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIHRoZSBwb3NzaWJsZSBmb3JtYXRzLCBwbHVzOlxuICAgICAgICA8dWw+XG4gICAgICAgIDxsaT4qIC0gaWdub3JlIHJlc3Qgb2Ygc3RyaW5nPC9saT5cbiAgICAgICAgPC91bD5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBmb3JtYXQge3N0cmluZ30gVGhlIGV4cGVjdGVkIGZvcm1hdCBvZiB0aGUgZGF0ZSAoJycgZm9yIGRlZmF1bHQgY2FsZW5kYXIgZm9ybWF0KS5cbiAgICAgICAgQHBhcmFtIHZhbHVlIHtzdHJpbmd9IFRoZSBkYXRlIGluIHRoZSBhYm92ZSBmb3JtYXQuXG4gICAgICAgIEBwYXJhbSBbc2V0dGluZ3NdIHtvYmplY3R9IEFkZGl0aW9uYWwgb3B0aW9ucyB3aG9zZSBhdHRyaWJ1dGVzIGluY2x1ZGU6XG4gICAgICAgIEBwcm9wZXJ0eSBbc2hvcnRZZWFyQ3V0b2ZmXSB7bnVtYmVyfSBUaGUgY3V0b2ZmIHllYXIgZm9yIGRldGVybWluaW5nIHRoZSBjZW50dXJ5LlxuICAgICAgICBAcHJvcGVydHkgW2RheU5hbWVzU2hvcnRdIHtzdHJpbmdbXX0gQWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkuXG4gICAgICAgIEBwcm9wZXJ0eSBbZGF5TmFtZXNdIHtzdHJpbmdbXX0gTmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkuXG4gICAgICAgIEBwcm9wZXJ0eSBbbW9udGhOYW1lc1Nob3J0XSB7c3RyaW5nW119IEFiYnJldmlhdGVkIG5hbWVzIG9mIHRoZSBtb250aHMuXG4gICAgICAgIEBwcm9wZXJ0eSBbbW9udGhOYW1lc10ge3N0cmluZ1tdfSBOYW1lcyBvZiB0aGUgbW9udGhzLlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGV4dHJhY3RlZCBkYXRlIHZhbHVlIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHZhbHVlIGlzIGJsYW5rLlxuICAgICAgICBAdGhyb3dzIEVycm9ycyBpZiB0aGUgZm9ybWF0IGFuZC9vciB2YWx1ZSBhcmUgbWlzc2luZyxcbiAgICAgICAgICAgICAgICBpZiB0aGUgdmFsdWUgZG9lc24ndCBtYXRjaCB0aGUgZm9ybWF0LCBvciBpZiB0aGUgZGF0ZSBpcyBpbnZhbGlkLiAqL1xuICAgIHBhcnNlRGF0ZTogZnVuY3Rpb24oZm9ybWF0LCB2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG1haW4ubG9jYWwuaW52YWxpZEFyZ3VtZW50cyB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZEFyZ3VtZW50cztcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9ICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnID8gdmFsdWUudG9TdHJpbmcoKSA6IHZhbHVlICsgJycpO1xuICAgICAgICBpZiAodmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgdGhpcy5sb2NhbC5kYXRlRm9ybWF0O1xuICAgICAgICBzZXR0aW5ncyA9IHNldHRpbmdzIHx8IHt9O1xuICAgICAgICB2YXIgc2hvcnRZZWFyQ3V0b2ZmID0gc2V0dGluZ3Muc2hvcnRZZWFyQ3V0b2ZmIHx8IHRoaXMuc2hvcnRZZWFyQ3V0b2ZmO1xuICAgICAgICBzaG9ydFllYXJDdXRvZmYgPSAodHlwZW9mIHNob3J0WWVhckN1dG9mZiAhPT0gJ3N0cmluZycgPyBzaG9ydFllYXJDdXRvZmYgOlxuICAgICAgICAgICAgdGhpcy50b2RheSgpLnllYXIoKSAlIDEwMCArIHBhcnNlSW50KHNob3J0WWVhckN1dG9mZiwgMTApKTtcbiAgICAgICAgdmFyIGRheU5hbWVzU2hvcnQgPSBzZXR0aW5ncy5kYXlOYW1lc1Nob3J0IHx8IHRoaXMubG9jYWwuZGF5TmFtZXNTaG9ydDtcbiAgICAgICAgdmFyIGRheU5hbWVzID0gc2V0dGluZ3MuZGF5TmFtZXMgfHwgdGhpcy5sb2NhbC5kYXlOYW1lcztcbiAgICAgICAgdmFyIHBhcnNlTW9udGggPSBzZXR0aW5ncy5wYXJzZU1vbnRoIHx8IHRoaXMubG9jYWwucGFyc2VNb250aDtcbiAgICAgICAgdmFyIG1vbnRoTnVtYmVycyA9IHNldHRpbmdzLm1vbnRoTnVtYmVycyB8fCB0aGlzLmxvY2FsLm1vbnRoTnVtYmVycztcbiAgICAgICAgdmFyIG1vbnRoTmFtZXNTaG9ydCA9IHNldHRpbmdzLm1vbnRoTmFtZXNTaG9ydCB8fCB0aGlzLmxvY2FsLm1vbnRoTmFtZXNTaG9ydDtcbiAgICAgICAgdmFyIG1vbnRoTmFtZXMgPSBzZXR0aW5ncy5tb250aE5hbWVzIHx8IHRoaXMubG9jYWwubW9udGhOYW1lcztcbiAgICAgICAgdmFyIGpkID0gLTE7XG4gICAgICAgIHZhciB5ZWFyID0gLTE7XG4gICAgICAgIHZhciBtb250aCA9IC0xO1xuICAgICAgICB2YXIgZGF5ID0gLTE7XG4gICAgICAgIHZhciBkb3kgPSAtMTtcbiAgICAgICAgdmFyIHNob3J0WWVhciA9IGZhbHNlO1xuICAgICAgICB2YXIgbGl0ZXJhbCA9IGZhbHNlO1xuICAgICAgICAvLyBDaGVjayB3aGV0aGVyIGEgZm9ybWF0IGNoYXJhY3RlciBpcyBkb3VibGVkXG4gICAgICAgIHZhciBkb3VibGVkID0gZnVuY3Rpb24obWF0Y2gsIHN0ZXApIHtcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gMTtcbiAgICAgICAgICAgIHdoaWxlIChpRm9ybWF0ICsgbWF0Y2hlcyA8IGZvcm1hdC5sZW5ndGggJiYgZm9ybWF0LmNoYXJBdChpRm9ybWF0ICsgbWF0Y2hlcykgPT09IG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hlcysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaUZvcm1hdCArPSBtYXRjaGVzIC0gMTtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG1hdGNoZXMgLyAoc3RlcCB8fCAxKSkgPiAxO1xuICAgICAgICB9O1xuICAgICAgICAvLyBFeHRyYWN0IGEgbnVtYmVyIGZyb20gdGhlIHN0cmluZyB2YWx1ZVxuICAgICAgICB2YXIgZ2V0TnVtYmVyID0gZnVuY3Rpb24obWF0Y2gsIHN0ZXApIHtcbiAgICAgICAgICAgIHZhciBpc0RvdWJsZWQgPSBkb3VibGVkKG1hdGNoLCBzdGVwKTtcbiAgICAgICAgICAgIHZhciBzaXplID0gWzIsIDMsIGlzRG91YmxlZCA/IDQgOiAyLCBpc0RvdWJsZWQgPyA0IDogMiwgMTAsIDExLCAyMF1bJ295WUpAIScuaW5kZXhPZihtYXRjaCkgKyAxXTtcbiAgICAgICAgICAgIHZhciBkaWdpdHMgPSBuZXcgUmVnRXhwKCdeLT9cXFxcZHsxLCcgKyBzaXplICsgJ30nKTtcbiAgICAgICAgICAgIHZhciBudW0gPSB2YWx1ZS5zdWJzdHJpbmcoaVZhbHVlKS5tYXRjaChkaWdpdHMpO1xuICAgICAgICAgICAgaWYgKCFudW0pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyAobWFpbi5sb2NhbC5taXNzaW5nTnVtYmVyQXQgfHwgbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLm1pc3NpbmdOdW1iZXJBdCkuXG4gICAgICAgICAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCBpVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaVZhbHVlICs9IG51bVswXS5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQobnVtWzBdLCAxMCk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEV4dHJhY3QgYSBtb250aCBudW1iZXIgZnJvbSB0aGUgc3RyaW5nIHZhbHVlXG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXM7XG4gICAgICAgIHZhciBnZXRNb250aE51bWJlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtb250aE51bWJlcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBkb3VibGVkKCdtJyk7ICAvLyB1cGRhdGUgaUZvcm1hdFxuICAgICAgICAgICAgICAgIHZhciBtb250aCA9IG1vbnRoTnVtYmVycy5jYWxsKGNhbGVuZGFyLCB2YWx1ZS5zdWJzdHJpbmcoaVZhbHVlKSk7XG4gICAgICAgICAgICAgICAgaVZhbHVlICs9IG1vbnRoLmxlbmd0aDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBnZXROdW1iZXIoJ20nKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRXh0cmFjdCBhIG5hbWUgZnJvbSB0aGUgc3RyaW5nIHZhbHVlIGFuZCBjb252ZXJ0IHRvIGFuIGluZGV4XG4gICAgICAgIHZhciBnZXROYW1lID0gZnVuY3Rpb24obWF0Y2gsIHNob3J0TmFtZXMsIGxvbmdOYW1lcywgc3RlcCkge1xuICAgICAgICAgICAgdmFyIG5hbWVzID0gKGRvdWJsZWQobWF0Y2gsIHN0ZXApID8gbG9uZ05hbWVzIDogc2hvcnROYW1lcyk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlLnN1YnN0cihpVmFsdWUsIG5hbWVzW2ldLmxlbmd0aCkudG9Mb3dlckNhc2UoKSA9PT0gbmFtZXNbaV0udG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICBpVmFsdWUgKz0gbmFtZXNbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaSArIGNhbGVuZGFyLm1pbk1vbnRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IChtYWluLmxvY2FsLnVua25vd25OYW1lQXQgfHwgbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLnVua25vd25OYW1lQXQpLlxuICAgICAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCBpVmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICAvLyBFeHRyYWN0IGEgbW9udGggbnVtYmVyIGZyb20gdGhlIHN0cmluZyB2YWx1ZVxuICAgICAgICB2YXIgZ2V0TW9udGhOYW1lID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1vbnRoTmFtZXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YXIgbW9udGggPSBkb3VibGVkKCdNJykgP1xuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzLmNhbGwoY2FsZW5kYXIsIHZhbHVlLnN1YnN0cmluZyhpVmFsdWUpKSA6XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydC5jYWxsKGNhbGVuZGFyLCB2YWx1ZS5zdWJzdHJpbmcoaVZhbHVlKSk7XG4gICAgICAgICAgICAgICAgaVZhbHVlICs9IG1vbnRoLmxlbmd0aDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBnZXROYW1lKCdNJywgbW9udGhOYW1lc1Nob3J0LCBtb250aE5hbWVzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gQ29uZmlybSB0aGF0IGEgbGl0ZXJhbCBjaGFyYWN0ZXIgbWF0Y2hlcyB0aGUgc3RyaW5nIHZhbHVlXG4gICAgICAgIHZhciBjaGVja0xpdGVyYWwgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5jaGFyQXQoaVZhbHVlKSAhPT0gZm9ybWF0LmNoYXJBdChpRm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IChtYWluLmxvY2FsLnVuZXhwZWN0ZWRMaXRlcmFsQXQgfHxcbiAgICAgICAgICAgICAgICAgICAgbWFpbi5yZWdpb25hbE9wdGlvbnNbJyddLnVuZXhwZWN0ZWRMaXRlcmFsQXQpLnJlcGxhY2UoL1xcezBcXH0vLCBpVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaVZhbHVlKys7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBpVmFsdWUgPSAwO1xuICAgICAgICBmb3IgKHZhciBpRm9ybWF0ID0gMDsgaUZvcm1hdCA8IGZvcm1hdC5sZW5ndGg7IGlGb3JtYXQrKykge1xuICAgICAgICAgICAgaWYgKGxpdGVyYWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSA9PT0gXCInXCIgJiYgIWRvdWJsZWQoXCInXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpdGVyYWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdkJzogZGF5ID0gZ2V0TnVtYmVyKCdkJyk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdEJzogZ2V0TmFtZSgnRCcsIGRheU5hbWVzU2hvcnQsIGRheU5hbWVzKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ28nOiBkb3kgPSBnZXROdW1iZXIoJ28nKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3cnOiBnZXROdW1iZXIoJ3cnKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ20nOiBtb250aCA9IGdldE1vbnRoTnVtYmVyKCk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdNJzogbW9udGggPSBnZXRNb250aE5hbWUoKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlTYXZlID0gaUZvcm1hdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3J0WWVhciA9ICFkb3VibGVkKCd5JywgMik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpRm9ybWF0ID0gaVNhdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gZ2V0TnVtYmVyKCd5JywgMik7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnWSc6IHllYXIgPSBnZXROdW1iZXIoJ1knLCAyKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ0onOlxuICAgICAgICAgICAgICAgICAgICAgICAgamQgPSBnZXROdW1iZXIoJ0onKSArIDAuNTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5jaGFyQXQoaVZhbHVlKSA9PT0gJy4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaVZhbHVlKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TnVtYmVyKCdKJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnQCc6IGpkID0gZ2V0TnVtYmVyKCdAJykgLyB0aGlzLlNFQ1NfUEVSX0RBWSArIHRoaXMuVU5JWF9FUE9DSDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJyEnOiBqZCA9IGdldE51bWJlcignIScpIC8gdGhpcy5USUNLU19QRVJfREFZICsgdGhpcy5USUNLU19FUE9DSDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJyonOiBpVmFsdWUgPSB2YWx1ZS5sZW5ndGg7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiJ1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvdWJsZWQoXCInXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXRlcmFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiBjaGVja0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlWYWx1ZSA8IHZhbHVlLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC51bmV4cGVjdGVkVGV4dCB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10udW5leHBlY3RlZFRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHllYXIgPT09IC0xKSB7XG4gICAgICAgICAgICB5ZWFyID0gdGhpcy50b2RheSgpLnllYXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh5ZWFyIDwgMTAwICYmIHNob3J0WWVhcikge1xuICAgICAgICAgICAgeWVhciArPSAoc2hvcnRZZWFyQ3V0b2ZmID09PSAtMSA/IDE5MDAgOiB0aGlzLnRvZGF5KCkueWVhcigpIC1cbiAgICAgICAgICAgICAgICB0aGlzLnRvZGF5KCkueWVhcigpICUgMTAwIC0gKHllYXIgPD0gc2hvcnRZZWFyQ3V0b2ZmID8gMCA6IDEwMCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgbW9udGggPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBtb250aCA9IHBhcnNlTW9udGguY2FsbCh0aGlzLCB5ZWFyLCBtb250aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRveSA+IC0xKSB7XG4gICAgICAgICAgICBtb250aCA9IDE7XG4gICAgICAgICAgICBkYXkgPSBkb3k7XG4gICAgICAgICAgICBmb3IgKHZhciBkaW0gPSB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG1vbnRoKTsgZGF5ID4gZGltOyBkaW0gPSB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG1vbnRoKSkge1xuICAgICAgICAgICAgICAgIG1vbnRoKys7XG4gICAgICAgICAgICAgICAgZGF5IC09IGRpbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKGpkID4gLTEgPyB0aGlzLmZyb21KRChqZCkgOiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSkpO1xuICAgIH0sXG5cbiAgICAvKiogQSBkYXRlIG1heSBiZSBzcGVjaWZpZWQgYXMgYW4gZXhhY3QgdmFsdWUgb3IgYSByZWxhdGl2ZSBvbmUuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZVNwZWMge0NEYXRlfG51bWJlcnxzdHJpbmd9IFRoZSBkYXRlIGFzIGFuIG9iamVjdCBvciBzdHJpbmcgaW4gdGhlIGdpdmVuIGZvcm1hdCBvclxuICAgICAgICAgICAgICAgIGFuIG9mZnNldCAtIG51bWVyaWMgZGF5cyBmcm9tIHRvZGF5LCBvciBzdHJpbmcgYW1vdW50cyBhbmQgcGVyaW9kcywgZS5nLiAnKzFtICsydycuXG4gICAgICAgIEBwYXJhbSBkZWZhdWx0RGF0ZSB7Q0RhdGV9IFRoZSBkYXRlIHRvIHVzZSBpZiBubyBvdGhlciBzdXBwbGllZCwgbWF5IGJlIDxjb2RlPm51bGw8L2NvZGU+LlxuICAgICAgICBAcGFyYW0gY3VycmVudERhdGUge0NEYXRlfSBUaGUgY3VycmVudCBkYXRlIGFzIGEgcG9zc2libGUgYmFzaXMgZm9yIHJlbGF0aXZlIGRhdGVzLFxuICAgICAgICAgICAgICAgIGlmIDxjb2RlPm51bGw8L2NvZGU+IHRvZGF5IGlzIHVzZWQgKG9wdGlvbmFsKVxuICAgICAgICBAcGFyYW0gW2RhdGVGb3JtYXRdIHtzdHJpbmd9IFRoZSBleHBlY3RlZCBkYXRlIGZvcm1hdCAtIHNlZSA8YSBocmVmPVwiI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4uXG4gICAgICAgIEBwYXJhbSBbc2V0dGluZ3NdIHtvYmplY3R9IEFkZGl0aW9uYWwgb3B0aW9ucyB3aG9zZSBhdHRyaWJ1dGVzIGluY2x1ZGU6XG4gICAgICAgIEBwcm9wZXJ0eSBbc2hvcnRZZWFyQ3V0b2ZmXSB7bnVtYmVyfSBUaGUgY3V0b2ZmIHllYXIgZm9yIGRldGVybWluaW5nIHRoZSBjZW50dXJ5LlxuICAgICAgICBAcHJvcGVydHkgW2RheU5hbWVzU2hvcnRdIHtzdHJpbmdbXX0gQWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkuXG4gICAgICAgIEBwcm9wZXJ0eSBbZGF5TmFtZXNdIHtzdHJpbmdbXX0gTmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkuXG4gICAgICAgIEBwcm9wZXJ0eSBbbW9udGhOYW1lc1Nob3J0XSB7c3RyaW5nW119IEFiYnJldmlhdGVkIG5hbWVzIG9mIHRoZSBtb250aHMuXG4gICAgICAgIEBwcm9wZXJ0eSBbbW9udGhOYW1lc10ge3N0cmluZ1tdfSBOYW1lcyBvZiB0aGUgbW9udGhzLlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGRlY29kZWQgZGF0ZS4gKi9cbiAgICBkZXRlcm1pbmVEYXRlOiBmdW5jdGlvbihkYXRlU3BlYywgZGVmYXVsdERhdGUsIGN1cnJlbnREYXRlLCBkYXRlRm9ybWF0LCBzZXR0aW5ncykge1xuICAgICAgICBpZiAoY3VycmVudERhdGUgJiYgdHlwZW9mIGN1cnJlbnREYXRlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBkYXRlRm9ybWF0O1xuICAgICAgICAgICAgZGF0ZUZvcm1hdCA9IGN1cnJlbnREYXRlO1xuICAgICAgICAgICAgY3VycmVudERhdGUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgZGF0ZUZvcm1hdCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHNldHRpbmdzID0gZGF0ZUZvcm1hdDtcbiAgICAgICAgICAgIGRhdGVGb3JtYXQgPSAnJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0aGlzO1xuICAgICAgICB2YXIgb2Zmc2V0U3RyaW5nID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYWxlbmRhci5wYXJzZURhdGUoZGF0ZUZvcm1hdCwgb2Zmc2V0LCBzZXR0aW5ncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIElnbm9yZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IChvZmZzZXQubWF0Y2goL15jLykgJiYgY3VycmVudERhdGUgP1xuICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlLm5ld0RhdGUoKSA6IG51bGwpIHx8IGNhbGVuZGFyLnRvZGF5KCk7XG4gICAgICAgICAgICB2YXIgcGF0dGVybiA9IC8oWystXT9bMC05XSspXFxzKihkfHd8bXx5KT8vZztcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gcGF0dGVybi5leGVjKG9mZnNldCk7XG4gICAgICAgICAgICB3aGlsZSAobWF0Y2hlcykge1xuICAgICAgICAgICAgICAgIGRhdGUuYWRkKHBhcnNlSW50KG1hdGNoZXNbMV0sIDEwKSwgbWF0Y2hlc1syXSB8fCAnZCcpO1xuICAgICAgICAgICAgICAgIG1hdGNoZXMgPSBwYXR0ZXJuLmV4ZWMob2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkYXRlO1xuICAgICAgICB9O1xuICAgICAgICBkZWZhdWx0RGF0ZSA9IChkZWZhdWx0RGF0ZSA/IGRlZmF1bHREYXRlLm5ld0RhdGUoKSA6IG51bGwpO1xuICAgICAgICBkYXRlU3BlYyA9IChkYXRlU3BlYyA9PSBudWxsID8gZGVmYXVsdERhdGUgOlxuICAgICAgICAgICAgKHR5cGVvZiBkYXRlU3BlYyA9PT0gJ3N0cmluZycgPyBvZmZzZXRTdHJpbmcoZGF0ZVNwZWMpIDogKHR5cGVvZiBkYXRlU3BlYyA9PT0gJ251bWJlcicgP1xuICAgICAgICAgICAgKGlzTmFOKGRhdGVTcGVjKSB8fCBkYXRlU3BlYyA9PT0gSW5maW5pdHkgfHwgZGF0ZVNwZWMgPT09IC1JbmZpbml0eSA/IGRlZmF1bHREYXRlIDpcbiAgICAgICAgICAgIGNhbGVuZGFyLnRvZGF5KCkuYWRkKGRhdGVTcGVjLCAnZCcpKSA6IGNhbGVuZGFyLm5ld0RhdGUoZGF0ZVNwZWMpKSkpO1xuICAgICAgICByZXR1cm4gZGF0ZVNwZWM7XG4gICAgfVxufSk7XG5cbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnY3dpc2UtY29tcGlsZXInKSh7XG4gICAgYXJnczogWydhcnJheScsIHtcbiAgICAgICAgb2Zmc2V0OiBbMV0sXG4gICAgICAgIGFycmF5OiAwXG4gICAgfSwgJ3NjYWxhcicsICdzY2FsYXInLCAnaW5kZXgnXSxcbiAgICBwcmU6IHtcbiAgICAgICAgXCJib2R5XCI6IFwie31cIixcbiAgICAgICAgXCJhcmdzXCI6IFtdLFxuICAgICAgICBcInRoaXNWYXJzXCI6IFtdLFxuICAgICAgICBcImxvY2FsVmFyc1wiOiBbXVxuICAgIH0sXG4gICAgcG9zdDoge1xuICAgICAgICBcImJvZHlcIjogXCJ7fVwiLFxuICAgICAgICBcImFyZ3NcIjogW10sXG4gICAgICAgIFwidGhpc1ZhcnNcIjogW10sXG4gICAgICAgIFwibG9jYWxWYXJzXCI6IFtdXG4gICAgfSxcbiAgICBib2R5OiB7XG4gICAgICAgIFwiYm9keVwiOiBcIntcXG4gICAgICAgIHZhciBfaW5saW5lXzFfZGEgPSBfaW5saW5lXzFfYXJnMF8gLSBfaW5saW5lXzFfYXJnM19cXG4gICAgICAgIHZhciBfaW5saW5lXzFfZGIgPSBfaW5saW5lXzFfYXJnMV8gLSBfaW5saW5lXzFfYXJnM19cXG4gICAgICAgIGlmKChfaW5saW5lXzFfZGEgPj0gMCkgIT09IChfaW5saW5lXzFfZGIgPj0gMCkpIHtcXG4gICAgICAgICAgX2lubGluZV8xX2FyZzJfLnB1c2goX2lubGluZV8xX2FyZzRfWzBdICsgMC41ICsgMC41ICogKF9pbmxpbmVfMV9kYSArIF9pbmxpbmVfMV9kYikgLyAoX2lubGluZV8xX2RhIC0gX2lubGluZV8xX2RiKSlcXG4gICAgICAgIH1cXG4gICAgICB9XCIsXG4gICAgICAgIFwiYXJnc1wiOiBbe1xuICAgICAgICAgICAgXCJuYW1lXCI6IFwiX2lubGluZV8xX2FyZzBfXCIsXG4gICAgICAgICAgICBcImx2YWx1ZVwiOiBmYWxzZSxcbiAgICAgICAgICAgIFwicnZhbHVlXCI6IHRydWUsXG4gICAgICAgICAgICBcImNvdW50XCI6IDFcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgXCJuYW1lXCI6IFwiX2lubGluZV8xX2FyZzFfXCIsXG4gICAgICAgICAgICBcImx2YWx1ZVwiOiBmYWxzZSxcbiAgICAgICAgICAgIFwicnZhbHVlXCI6IHRydWUsXG4gICAgICAgICAgICBcImNvdW50XCI6IDFcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgXCJuYW1lXCI6IFwiX2lubGluZV8xX2FyZzJfXCIsXG4gICAgICAgICAgICBcImx2YWx1ZVwiOiBmYWxzZSxcbiAgICAgICAgICAgIFwicnZhbHVlXCI6IHRydWUsXG4gICAgICAgICAgICBcImNvdW50XCI6IDFcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgXCJuYW1lXCI6IFwiX2lubGluZV8xX2FyZzNfXCIsXG4gICAgICAgICAgICBcImx2YWx1ZVwiOiBmYWxzZSxcbiAgICAgICAgICAgIFwicnZhbHVlXCI6IHRydWUsXG4gICAgICAgICAgICBcImNvdW50XCI6IDJcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgXCJuYW1lXCI6IFwiX2lubGluZV8xX2FyZzRfXCIsXG4gICAgICAgICAgICBcImx2YWx1ZVwiOiBmYWxzZSxcbiAgICAgICAgICAgIFwicnZhbHVlXCI6IHRydWUsXG4gICAgICAgICAgICBcImNvdW50XCI6IDFcbiAgICAgICAgfV0sXG4gICAgICAgIFwidGhpc1ZhcnNcIjogW10sXG4gICAgICAgIFwibG9jYWxWYXJzXCI6IFtcIl9pbmxpbmVfMV9kYVwiLCBcIl9pbmxpbmVfMV9kYlwiXVxuICAgIH0sXG4gICAgZnVuY05hbWU6ICd6ZXJvQ3Jvc3NpbmdzJ1xufSlcbiIsIlwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZmluZFplcm9Dcm9zc2luZ3NcblxudmFyIGNvcmUgPSByZXF1aXJlKFwiLi9saWIvemMtY29yZVwiKVxuXG5mdW5jdGlvbiBmaW5kWmVyb0Nyb3NzaW5ncyhhcnJheSwgbGV2ZWwpIHtcbiAgdmFyIGNyb3NzID0gW11cbiAgbGV2ZWwgPSArbGV2ZWwgfHwgMC4wXG4gIGNvcmUoYXJyYXkuaGkoYXJyYXkuc2hhcGVbMF0tMSksIGNyb3NzLCBsZXZlbClcbiAgcmV0dXJuIGNyb3NzXG59IiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEFsbCBwYXRocyBhcmUgdHVuZWQgZm9yIG1heGltdW0gc2NhbGFiaWxpdHkgb2YgdGhlIGFycm93aGVhZCxcbiAqIGllIHRocm91Z2hvdXQgYXJyb3d3aWR0aD0wLjMuLjMgdGhlIGhlYWQgaXMgam9pbmVkIHNtb290aGx5XG4gKiB0byB0aGUgbGluZSwgd2l0aCB0aGUgbGluZSBjb21pbmcgZnJvbSB0aGUgbGVmdCBhbmQgZW5kaW5nIGF0ICgwLCAwKS5cbiAqXG4gKiBgYmFja29mZmAgaXMgdGhlIGRpc3RhbmNlIHRvIG1vdmUgdGhlIGFycm93aGVhZCBhbmQgdGhlIGVuZCBvZiB0aGUgbGluZSxcbiAqIGluIG9yZGVyIHRoYXQgdGhlIGFycm93aGVhZCBwb2ludHMgdG8gdGhlIGRlc2lyZWQgcGxhY2UsIGVpdGhlciBhdFxuICogdGhlIHRpcCBvZiB0aGUgYXJyb3cgb3IgKGluIHRoZSBjYXNlIG9mIGNpcmNsZSBvciBzcXVhcmUpXG4gKiB0aGUgY2VudGVyIG9mIHRoZSBzeW1ib2wuXG4gKlxuICogYG5vUm90YXRlYCwgaWYgdHJ1dGh5LCBzYXlzIHRoYXQgdGhpcyBhcnJvd2hlYWQgc2hvdWxkIG5vdCByb3RhdGUgd2l0aCB0aGVcbiAqIGFycm93LiBUaGF0J3MgdGhlIGNhc2UgZm9yIHNxdWFyZXMsIHdoaWNoIHNob3VsZCBhbHdheXMgYmUgc3RyYWlnaHQsIGFuZFxuICogY2lyY2xlcywgZm9yIHdoaWNoIGl0J3MgaXJyZWxldmFudC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAgICAvLyBubyBhcnJvd1xuICAgIHtcbiAgICAgICAgcGF0aDogJycsXG4gICAgICAgIGJhY2tvZmY6IDBcbiAgICB9LFxuICAgIC8vIHdpZGUgd2l0aCBmbGF0IGJhY2tcbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTIuNCwtM1YzTDAuNiwwWicsXG4gICAgICAgIGJhY2tvZmY6IDAuNlxuICAgIH0sXG4gICAgLy8gbmFycm93ZXIgd2l0aCBmbGF0IGJhY2tcbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTMuNywtMi41VjIuNUwxLjMsMFonLFxuICAgICAgICBiYWNrb2ZmOiAxLjNcbiAgICB9LFxuICAgIC8vIGJhcmJlZFxuICAgIHtcbiAgICAgICAgcGF0aDogJ00tNC40NSwtM0wtMS42NSwtMC4yVjAuMkwtNC40NSwzTDEuNTUsMFonLFxuICAgICAgICBiYWNrb2ZmOiAxLjU1XG4gICAgfSxcbiAgICAvLyB3aWRlIGxpbmUtZHJhd25cbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTIuMiwtMi4yTC0wLjIsLTAuMlYwLjJMLTIuMiwyLjJMLTEuNCwzTDEuNiwwTC0xLjQsLTNaJyxcbiAgICAgICAgYmFja29mZjogMS42XG4gICAgfSxcbiAgICAvLyBuYXJyb3dlciBsaW5lLWRyYXduXG4gICAge1xuICAgICAgICBwYXRoOiAnTS00LjQsLTIuMUwtMC42LC0wLjJWMC4yTC00LjQsMi4xTC00LDNMMiwwTC00LC0zWicsXG4gICAgICAgIGJhY2tvZmY6IDJcbiAgICB9LFxuICAgIC8vIGNpcmNsZVxuICAgIHtcbiAgICAgICAgcGF0aDogJ00yLDBBMiwyIDAgMSwxIDAsLTJBMiwyIDAgMCwxIDIsMFonLFxuICAgICAgICBiYWNrb2ZmOiAwLFxuICAgICAgICBub1JvdGF0ZTogdHJ1ZVxuICAgIH0sXG4gICAgLy8gc3F1YXJlXG4gICAge1xuICAgICAgICBwYXRoOiAnTTIsMlYtMkgtMlYyWicsXG4gICAgICAgIGJhY2tvZmY6IDAsXG4gICAgICAgIG5vUm90YXRlOiB0cnVlXG4gICAgfVxuXTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEFSUk9XUEFUSFMgPSByZXF1aXJlKCcuL2Fycm93X3BhdGhzJyk7XG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY2FydGVzaWFuQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gdGVtcGxhdGVkQXJyYXkoJ2Fubm90YXRpb24nLCB7XG4gICAgdmlzaWJsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZXh0YW5nbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBjb2xvckVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhlaWdodDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYWxpZ246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2NlbnRlcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsaWduOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICdtaWRkbGUnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6ICdyZ2JhKDAsMCwwLDApJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJwYWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBhcnJvd1xuICAgIHNob3dhcnJvdzoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJvd2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJyb3doZWFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IEFSUk9XUEFUSFMubGVuZ3RoLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0YXJyb3doZWFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IEFSUk9XUEFUSFMubGVuZ3RoLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycm93c2lkZToge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydlbmQnLCAnc3RhcnQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2VuZCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJyb3dzaXplOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAuMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0YXJyb3dzaXplOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAuMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycm93d2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMC4xLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhbmRvZmY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0c3RhbmRvZmY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGF4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBheHJlZjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIGRmbHQ6ICdwaXhlbCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3BpeGVsJyxcbiAgICAgICAgICAgIGNhcnRlc2lhbkNvbnN0YW50cy5pZFJlZ2V4LngudG9TdHJpbmcoKVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBheXJlZjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIGRmbHQ6ICdwaXhlbCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3BpeGVsJyxcbiAgICAgICAgICAgIGNhcnRlc2lhbkNvbnN0YW50cy5pZFJlZ2V4LnkudG9TdHJpbmcoKVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBwb3NpdGlvbmluZ1xuICAgIHhyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICdsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4c2hpZnQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5cmVmOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAncGFwZXInLFxuICAgICAgICAgICAgY2FydGVzaWFuQ29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeXNoaWZ0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY2xpY2t0b3Nob3c6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtmYWxzZSwgJ29ub2ZmJywgJ29ub3V0J10sXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhjbGljazoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5Y2xpY2s6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVybGFiZWw6IHtcbiAgICAgICAgYmdjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnXG4gICAgfSxcbiAgICBjYXB0dXJlZXZlbnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgcmVmOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfVxufSk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG52YXIgZHJhdyA9IHJlcXVpcmUoJy4vZHJhdycpLmRyYXc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjQXV0b3JhbmdlKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYW5ub3RhdGlvbkxpc3QgPSBMaWIuZmlsdGVyVmlzaWJsZShmdWxsTGF5b3V0LmFubm90YXRpb25zKTtcblxuICAgIGlmKGFubm90YXRpb25MaXN0Lmxlbmd0aCAmJiBnZC5fZnVsbERhdGEubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW2RyYXcsIGFubkF1dG9yYW5nZV0sIGdkKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBhbm5BdXRvcmFuZ2UoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgLy8gZmluZCB0aGUgYm91bmRpbmcgYm94ZXMgZm9yIGVhY2ggb2YgdGhlc2UgYW5ub3RhdGlvbnMnXG4gICAgLy8gcmVsYXRpdmUgdG8gdGhlaXIgYW5jaG9yIHBvaW50c1xuICAgIC8vIHVzZSB0aGUgYXJyb3cgYW5kIHRoZSB0ZXh0IGJnIHJlY3RhbmdsZSxcbiAgICAvLyBhcyB0aGUgd2hvbGUgYW5ubyBtYXkgaW5jbHVkZSBoaWRkZW4gdGV4dCBpbiBpdHMgYmJveFxuICAgIExpYi5maWx0ZXJWaXNpYmxlKGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnMpLmZvckVhY2goZnVuY3Rpb24oYW5uKSB7XG4gICAgICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBhbm4ueHJlZik7XG4gICAgICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBhbm4ueXJlZik7XG5cbiAgICAgICAgYW5uLl9leHRyZW1lcyA9IHt9O1xuICAgICAgICBpZih4YSkgY2FsY0F4aXNFeHBhbnNpb24oYW5uLCB4YSk7XG4gICAgICAgIGlmKHlhKSBjYWxjQXhpc0V4cGFuc2lvbihhbm4sIHlhKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gY2FsY0F4aXNFeHBhbnNpb24oYW5uLCBheCkge1xuICAgIHZhciBheElkID0gYXguX2lkO1xuICAgIHZhciBsZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcbiAgICB2YXIgcG9zID0gYW5uW2xldHRlcl07XG4gICAgdmFyIGFwb3MgPSBhbm5bJ2EnICsgbGV0dGVyXTtcbiAgICB2YXIgcmVmID0gYW5uW2xldHRlciArICdyZWYnXTtcbiAgICB2YXIgYXJlZiA9IGFublsnYScgKyBsZXR0ZXIgKyAncmVmJ107XG4gICAgdmFyIHBhZHBsdXMgPSBhbm5bJ18nICsgbGV0dGVyICsgJ3BhZHBsdXMnXTtcbiAgICB2YXIgcGFkbWludXMgPSBhbm5bJ18nICsgbGV0dGVyICsgJ3BhZG1pbnVzJ107XG4gICAgdmFyIHNoaWZ0ID0ge3g6IDEsIHk6IC0xfVtsZXR0ZXJdICogYW5uW2xldHRlciArICdzaGlmdCddO1xuICAgIHZhciBoZWFkU2l6ZSA9IDMgKiBhbm4uYXJyb3dzaXplICogYW5uLmFycm93d2lkdGggfHwgMDtcbiAgICB2YXIgaGVhZFBsdXMgPSBoZWFkU2l6ZSArIHNoaWZ0O1xuICAgIHZhciBoZWFkTWludXMgPSBoZWFkU2l6ZSAtIHNoaWZ0O1xuICAgIHZhciBzdGFydEhlYWRTaXplID0gMyAqIGFubi5zdGFydGFycm93c2l6ZSAqIGFubi5hcnJvd3dpZHRoIHx8IDA7XG4gICAgdmFyIHN0YXJ0SGVhZFBsdXMgPSBzdGFydEhlYWRTaXplICsgc2hpZnQ7XG4gICAgdmFyIHN0YXJ0SGVhZE1pbnVzID0gc3RhcnRIZWFkU2l6ZSAtIHNoaWZ0O1xuICAgIHZhciBleHRyZW1lcztcblxuICAgIGlmKGFyZWYgPT09IHJlZikge1xuICAgICAgICAvLyBleHBhbmQgZm9yIHRoZSBhcnJvd2hlYWQgKHBhZGRlZCBieSBhcnJvd2hlYWQpXG4gICAgICAgIHZhciBleHRyZW1lQXJyb3dIZWFkID0gQXhlcy5maW5kRXh0cmVtZXMoYXgsIFtheC5yMmMocG9zKV0sIHtcbiAgICAgICAgICAgIHBwYWRwbHVzOiBoZWFkUGx1cyxcbiAgICAgICAgICAgIHBwYWRtaW51czogaGVhZE1pbnVzXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBhZ2FpbiBmb3IgdGhlIHRleHRib3ggKHBhZGRlZCBieSB0ZXh0Ym94KVxuICAgICAgICB2YXIgZXh0cmVtZVRleHQgPSBBeGVzLmZpbmRFeHRyZW1lcyhheCwgW2F4LnIyYyhhcG9zKV0sIHtcbiAgICAgICAgICAgIHBwYWRwbHVzOiBNYXRoLm1heChwYWRwbHVzLCBzdGFydEhlYWRQbHVzKSxcbiAgICAgICAgICAgIHBwYWRtaW51czogTWF0aC5tYXgocGFkbWludXMsIHN0YXJ0SGVhZE1pbnVzKVxuICAgICAgICB9KTtcbiAgICAgICAgZXh0cmVtZXMgPSB7XG4gICAgICAgICAgICBtaW46IFtleHRyZW1lQXJyb3dIZWFkLm1pblswXSwgZXh0cmVtZVRleHQubWluWzBdXSxcbiAgICAgICAgICAgIG1heDogW2V4dHJlbWVBcnJvd0hlYWQubWF4WzBdLCBleHRyZW1lVGV4dC5tYXhbMF1dXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3RhcnRIZWFkUGx1cyA9IGFwb3MgPyBzdGFydEhlYWRQbHVzICsgYXBvcyA6IHN0YXJ0SGVhZFBsdXM7XG4gICAgICAgIHN0YXJ0SGVhZE1pbnVzID0gYXBvcyA/IHN0YXJ0SGVhZE1pbnVzIC0gYXBvcyA6IHN0YXJ0SGVhZE1pbnVzO1xuICAgICAgICBleHRyZW1lcyA9IEF4ZXMuZmluZEV4dHJlbWVzKGF4LCBbYXgucjJjKHBvcyldLCB7XG4gICAgICAgICAgICBwcGFkcGx1czogTWF0aC5tYXgocGFkcGx1cywgaGVhZFBsdXMsIHN0YXJ0SGVhZFBsdXMpLFxuICAgICAgICAgICAgcHBhZG1pbnVzOiBNYXRoLm1heChwYWRtaW51cywgaGVhZE1pbnVzLCBzdGFydEhlYWRNaW51cylcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYW5uLl9leHRyZW1lc1theElkXSA9IGV4dHJlbWVzO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGFycmF5RWRpdG9yID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLmFycmF5RWRpdG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBoYXNDbGlja1RvU2hvdzogaGFzQ2xpY2tUb1Nob3csXG4gICAgb25DbGljazogb25DbGlja1xufTtcblxuLypcbiAqIGhhc0NsaWNrVG9TaG93OiBkb2VzIHRoZSBnaXZlbiBob3ZlckRhdGEgaGF2ZSBBTlkgYW5ub3RhdGlvbnMgd2hpY2ggd2lsbFxuICogdHVybiBPTiBpZiB3ZSBjbGljayBoZXJlPyAodXNlZCBieSBob3ZlciBldmVudHMgdG8gc2V0IGN1cnNvcilcbiAqXG4gKiBnZDogZ3JhcGhEaXZcbiAqIGhvdmVyRGF0YTogYSBob3ZlckRhdGEgYXJyYXksIGFzIGluY2x1ZGVkIHdpdGggdGhlICpwbG90bHlfaG92ZXIqIG9yXG4gKiAgICAgKnBsb3RseV9jbGljayogZXZlbnRzIGluIHRoZSBgcG9pbnRzYCBhdHRyaWJ1dGVcbiAqXG4gKiByZXR1cm5zOiBib29sZWFuXG4gKi9cbmZ1bmN0aW9uIGhhc0NsaWNrVG9TaG93KGdkLCBob3ZlckRhdGEpIHtcbiAgICB2YXIgc2V0cyA9IGdldFRvZ2dsZVNldHMoZ2QsIGhvdmVyRGF0YSk7XG4gICAgcmV0dXJuIHNldHMub24ubGVuZ3RoID4gMCB8fCBzZXRzLmV4cGxpY2l0T2ZmLmxlbmd0aCA+IDA7XG59XG5cbi8qXG4gKiBvbkNsaWNrOiBwZXJmb3JtIHRoZSB0b2dnbGluZyAodmlhIFBsb3RseS51cGRhdGUpIGltcGxpZWQgYnkgY2xpY2tpbmdcbiAqIGF0IHRoaXMgaG92ZXJEYXRhXG4gKlxuICogZ2Q6IGdyYXBoRGl2XG4gKiBob3ZlckRhdGE6IGEgaG92ZXJEYXRhIGFycmF5LCBhcyBpbmNsdWRlZCB3aXRoIHRoZSAqcGxvdGx5X2hvdmVyKiBvclxuICogICAgICpwbG90bHlfY2xpY2sqIGV2ZW50cyBpbiB0aGUgYHBvaW50c2AgYXR0cmlidXRlXG4gKlxuICogcmV0dXJuczogUHJvbWlzZSB0aGF0IHRoZSB1cGRhdGUgaXMgY29tcGxldGVcbiAqL1xuZnVuY3Rpb24gb25DbGljayhnZCwgaG92ZXJEYXRhKSB7XG4gICAgdmFyIHRvZ2dsZVNldHMgPSBnZXRUb2dnbGVTZXRzKGdkLCBob3ZlckRhdGEpO1xuICAgIHZhciBvblNldCA9IHRvZ2dsZVNldHMub247XG4gICAgdmFyIG9mZlNldCA9IHRvZ2dsZVNldHMub2ZmLmNvbmNhdCh0b2dnbGVTZXRzLmV4cGxpY2l0T2ZmKTtcbiAgICB2YXIgdXBkYXRlID0ge307XG4gICAgdmFyIGFubm90YXRpb25zT3V0ID0gZ2QuX2Z1bGxMYXlvdXQuYW5ub3RhdGlvbnM7XG4gICAgdmFyIGksIGVkaXRIZWxwZXJzO1xuXG4gICAgaWYoIShvblNldC5sZW5ndGggfHwgb2ZmU2V0Lmxlbmd0aCkpIHJldHVybjtcblxuICAgIGZvcihpID0gMDsgaSA8IG9uU2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVkaXRIZWxwZXJzID0gYXJyYXlFZGl0b3IoZ2QubGF5b3V0LCAnYW5ub3RhdGlvbnMnLCBhbm5vdGF0aW9uc091dFtvblNldFtpXV0pO1xuICAgICAgICBlZGl0SGVscGVycy5tb2RpZnlJdGVtKCd2aXNpYmxlJywgdHJ1ZSk7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHVwZGF0ZSwgZWRpdEhlbHBlcnMuZ2V0VXBkYXRlT2JqKCkpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IG9mZlNldC5sZW5ndGg7IGkrKykge1xuICAgICAgICBlZGl0SGVscGVycyA9IGFycmF5RWRpdG9yKGdkLmxheW91dCwgJ2Fubm90YXRpb25zJywgYW5ub3RhdGlvbnNPdXRbb2ZmU2V0W2ldXSk7XG4gICAgICAgIGVkaXRIZWxwZXJzLm1vZGlmeUl0ZW0oJ3Zpc2libGUnLCBmYWxzZSk7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHVwZGF0ZSwgZWRpdEhlbHBlcnMuZ2V0VXBkYXRlT2JqKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCd1cGRhdGUnLCBnZCwge30sIHVwZGF0ZSk7XG59XG5cbi8qXG4gKiBnZXRUb2dnbGVTZXRzOiBmaW5kIHRoZSBhbm5vdGF0aW9ucyB3aGljaCB3aWxsIHR1cm4gb24gb3Igb2ZmIGF0IHRoaXNcbiAqIGhvdmVyRGF0YVxuICpcbiAqIGdkOiBncmFwaERpdlxuICogaG92ZXJEYXRhOiBhIGhvdmVyRGF0YSBhcnJheSwgYXMgaW5jbHVkZWQgd2l0aCB0aGUgKnBsb3RseV9ob3Zlciogb3JcbiAqICAgICAqcGxvdGx5X2NsaWNrKiBldmVudHMgaW4gdGhlIGBwb2ludHNgIGF0dHJpYnV0ZVxuICpcbiAqIHJldHVybnM6IHtcbiAqICAgb246IEFycmF5IChpbmRpY2VzIG9mIGFubm90YXRpb25zIHRvIHR1cm4gb24pLFxuICogICBvZmY6IEFycmF5IChpbmRpY2VzIHRvIHR1cm4gb2ZmIGJlY2F1c2UgeW91J3JlIG5vdCBob3ZlcmluZyBvbiB0aGVtKSxcbiAqICAgZXhwbGljaXRPZmY6IEFycmF5IChpbmRpY2VzIHRvIHR1cm4gb2ZmIGJlY2F1c2UgeW91ICphcmUqIGhvdmVyaW5nIG9uIHRoZW0pXG4gKiB9XG4gKi9cbmZ1bmN0aW9uIGdldFRvZ2dsZVNldHMoZ2QsIGhvdmVyRGF0YSkge1xuICAgIHZhciBhbm5vdGF0aW9ucyA9IGdkLl9mdWxsTGF5b3V0LmFubm90YXRpb25zLFxuICAgICAgICBvblNldCA9IFtdLFxuICAgICAgICBvZmZTZXQgPSBbXSxcbiAgICAgICAgZXhwbGljaXRPZmZTZXQgPSBbXSxcbiAgICAgICAgaG92ZXJMZW4gPSAoaG92ZXJEYXRhIHx8IFtdKS5sZW5ndGg7XG5cbiAgICB2YXIgaSwgaiwgYW5uaSwgc2hvd01vZGUsIHBvaW50aiwgeGEsIHlhLCB0b2dnbGVUeXBlO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYW5uaSA9IGFubm90YXRpb25zW2ldO1xuICAgICAgICBzaG93TW9kZSA9IGFubmkuY2xpY2t0b3Nob3c7XG5cbiAgICAgICAgaWYoc2hvd01vZGUpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGhvdmVyTGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwb2ludGogPSBob3ZlckRhdGFbal07XG4gICAgICAgICAgICAgICAgeGEgPSBwb2ludGoueGF4aXM7XG4gICAgICAgICAgICAgICAgeWEgPSBwb2ludGoueWF4aXM7XG5cbiAgICAgICAgICAgICAgICBpZih4YS5faWQgPT09IGFubmkueHJlZiAmJlxuICAgICAgICAgICAgICAgICAgICB5YS5faWQgPT09IGFubmkueXJlZiAmJlxuICAgICAgICAgICAgICAgICAgICB4YS5kMnIocG9pbnRqLngpID09PSBjbGlja0RhdGEycihhbm5pLl94Y2xpY2ssIHhhKSAmJlxuICAgICAgICAgICAgICAgICAgICB5YS5kMnIocG9pbnRqLnkpID09PSBjbGlja0RhdGEycihhbm5pLl95Y2xpY2ssIHlhKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAvLyBtYXRjaCEgdG9nZ2xlIHRoaXMgYW5ub3RhdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyByZWdhcmRsZXNzIG9mIGl0cyBjbGlja3Rvc2hvdyBtb2RlXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBpZiBpdCdzIG9ub3V0IG1vZGUsIG9mZiBpcyBpbXBsaWNpdFxuICAgICAgICAgICAgICAgICAgICBpZihhbm5pLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHNob3dNb2RlID09PSAnb25vdXQnKSB0b2dnbGVUeXBlID0gb2ZmU2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB0b2dnbGVUeXBlID0gZXhwbGljaXRPZmZTZXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b2dnbGVUeXBlID0gb25TZXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlVHlwZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGogPT09IGhvdmVyTGVuKSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gbWF0Y2ggLSBvbmx5IHR1cm4gdGhpcyBhbm5vdGF0aW9uIE9GRiwgYW5kIG9ubHkgaWZcbiAgICAgICAgICAgICAgICAvLyBzaG93bW9kZSBpcyAnb25vdXQnXG4gICAgICAgICAgICAgICAgaWYoYW5uaS52aXNpYmxlICYmIHNob3dNb2RlID09PSAnb25vdXQnKSBvZmZTZXQucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7b246IG9uU2V0LCBvZmY6IG9mZlNldCwgZXhwbGljaXRPZmY6IGV4cGxpY2l0T2ZmU2V0fTtcbn1cblxuLy8gdG8gaGFuZGxlIGxvZyBheGVzIHVudGlsIHYyXG5mdW5jdGlvbiBjbGlja0RhdGEycihkLCBheCkge1xuICAgIHJldHVybiBheC50eXBlID09PSAnbG9nJyA/IGF4LmwycihkKSA6IGF4LmQycihkKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29sb3InKTtcblxuLy8gZGVmYXVsdHMgY29tbW9uIHRvICdhbm5vdGF0aW9ucycgYW5kICdhbm5vdGF0aW9uczNkJ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMoYW5uSW4sIGFubk91dCwgZnVsbExheW91dCwgY29lcmNlKSB7XG4gICAgY29lcmNlKCdvcGFjaXR5Jyk7XG4gICAgdmFyIGJnQ29sb3IgPSBjb2VyY2UoJ2JnY29sb3InKTtcblxuICAgIHZhciBib3JkZXJDb2xvciA9IGNvZXJjZSgnYm9yZGVyY29sb3InKTtcbiAgICB2YXIgYm9yZGVyT3BhY2l0eSA9IENvbG9yLm9wYWNpdHkoYm9yZGVyQ29sb3IpO1xuXG4gICAgY29lcmNlKCdib3JkZXJwYWQnKTtcblxuICAgIHZhciBib3JkZXJXaWR0aCA9IGNvZXJjZSgnYm9yZGVyd2lkdGgnKTtcbiAgICB2YXIgc2hvd0Fycm93ID0gY29lcmNlKCdzaG93YXJyb3cnKTtcblxuICAgIGNvZXJjZSgndGV4dCcsIHNob3dBcnJvdyA/ICcgJyA6IGZ1bGxMYXlvdXQuX2RmbHRUaXRsZS5hbm5vdGF0aW9uKTtcbiAgICBjb2VyY2UoJ3RleHRhbmdsZScpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnLCBmdWxsTGF5b3V0LmZvbnQpO1xuXG4gICAgY29lcmNlKCd3aWR0aCcpO1xuICAgIGNvZXJjZSgnYWxpZ24nKTtcblxuICAgIHZhciBoID0gY29lcmNlKCdoZWlnaHQnKTtcbiAgICBpZihoKSBjb2VyY2UoJ3ZhbGlnbicpO1xuXG4gICAgaWYoc2hvd0Fycm93KSB7XG4gICAgICAgIHZhciBhcnJvd3NpZGUgPSBjb2VyY2UoJ2Fycm93c2lkZScpO1xuICAgICAgICB2YXIgYXJyb3doZWFkO1xuICAgICAgICB2YXIgYXJyb3dzaXplO1xuXG4gICAgICAgIGlmKGFycm93c2lkZS5pbmRleE9mKCdlbmQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGFycm93aGVhZCA9IGNvZXJjZSgnYXJyb3doZWFkJyk7XG4gICAgICAgICAgICBhcnJvd3NpemUgPSBjb2VyY2UoJ2Fycm93c2l6ZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXJyb3dzaWRlLmluZGV4T2YoJ3N0YXJ0JykgIT09IC0xKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ3N0YXJ0YXJyb3doZWFkJywgYXJyb3doZWFkKTtcbiAgICAgICAgICAgIGNvZXJjZSgnc3RhcnRhcnJvd3NpemUnLCBhcnJvd3NpemUpO1xuICAgICAgICB9XG4gICAgICAgIGNvZXJjZSgnYXJyb3djb2xvcicsIGJvcmRlck9wYWNpdHkgPyBhbm5PdXQuYm9yZGVyY29sb3IgOiBDb2xvci5kZWZhdWx0TGluZSk7XG4gICAgICAgIGNvZXJjZSgnYXJyb3d3aWR0aCcsICgoYm9yZGVyT3BhY2l0eSAmJiBib3JkZXJXaWR0aCkgfHwgMSkgKiAyKTtcbiAgICAgICAgY29lcmNlKCdzdGFuZG9mZicpO1xuICAgICAgICBjb2VyY2UoJ3N0YXJ0c3RhbmRvZmYnKTtcblxuICAgIH1cblxuICAgIHZhciBob3ZlclRleHQgPSBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIHZhciBnbG9iYWxIb3ZlckxhYmVsID0gZnVsbExheW91dC5ob3ZlcmxhYmVsIHx8IHt9O1xuXG4gICAgaWYoaG92ZXJUZXh0KSB7XG4gICAgICAgIHZhciBob3ZlckJHID0gY29lcmNlKCdob3ZlcmxhYmVsLmJnY29sb3InLCBnbG9iYWxIb3ZlckxhYmVsLmJnY29sb3IgfHxcbiAgICAgICAgICAgIChDb2xvci5vcGFjaXR5KGJnQ29sb3IpID8gQ29sb3IucmdiKGJnQ29sb3IpIDogQ29sb3IuZGVmYXVsdExpbmUpXG4gICAgICAgICk7XG5cbiAgICAgICAgdmFyIGhvdmVyQm9yZGVyID0gY29lcmNlKCdob3ZlcmxhYmVsLmJvcmRlcmNvbG9yJywgZ2xvYmFsSG92ZXJMYWJlbC5ib3JkZXJjb2xvciB8fFxuICAgICAgICAgICAgQ29sb3IuY29udHJhc3QoaG92ZXJCRylcbiAgICAgICAgKTtcblxuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdob3ZlcmxhYmVsLmZvbnQnLCB7XG4gICAgICAgICAgICBmYW1pbHk6IGdsb2JhbEhvdmVyTGFiZWwuZm9udC5mYW1pbHksXG4gICAgICAgICAgICBzaXplOiBnbG9iYWxIb3ZlckxhYmVsLmZvbnQuc2l6ZSxcbiAgICAgICAgICAgIGNvbG9yOiBnbG9iYWxIb3ZlckxhYmVsLmZvbnQuY29sb3IgfHwgaG92ZXJCb3JkZXJcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdjYXB0dXJlZXZlbnRzJywgISFob3ZlclRleHQpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0b0xvZ1JhbmdlID0gcmVxdWlyZSgnLi4vLi4vbGliL3RvX2xvZ19yYW5nZScpO1xuXG4vKlxuICogY29udmVydENvb3Jkczogd2hlbiBjb252ZXJ0aW5nIGFuIGF4aXMgYmV0d2VlbiBsb2cgYW5kIGxpbmVhclxuICogeW91IG5lZWQgdG8gYWx0ZXIgYW55IGFubm90YXRpb25zIG9uIHRoYXQgYXhpcyB0byBrZWVwIHRoZW1cbiAqIHBvaW50aW5nIGF0IHRoZSBzYW1lIGRhdGEgcG9pbnQuXG4gKiBJbiB2Mi4wIHRoaXMgd2lsbCBiZWNvbWUgb2Jzb2xldGVcbiAqXG4gKiBnZDogdGhlIHBsb3QgZGl2XG4gKiBheDogdGhlIGF4aXMgYmVpbmcgY2hhbmdlZFxuICogbmV3VHlwZTogdGhlIHR5cGUgaXQncyBnZXR0aW5nXG4gKiBkb0V4dHJhOiBmdW5jdGlvbihhdHRyLCB2YWwpIGZyb20gaW5zaWRlIHJlbGF5b3V0IHRoYXQgc2V0cyB0aGUgYXR0cmlidXRlLlxuICogICAgIFVzZSB0aGlzIHRvIG1ha2UgdGhlIGNoYW5nZXMgYXMgaXQncyBhd2FyZSBpZiBhbnkgb3RoZXIgY2hhbmdlcyBpbiB0aGVcbiAqICAgICBzYW1lIHJlbGF5b3V0IGNhbGwgc2hvdWxkIG92ZXJyaWRlIHRoaXMgY29udmVyc2lvbi5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb252ZXJ0Q29vcmRzKGdkLCBheCwgbmV3VHlwZSwgZG9FeHRyYSkge1xuICAgIGF4ID0gYXggfHwge307XG5cbiAgICB2YXIgdG9Mb2cgPSAobmV3VHlwZSA9PT0gJ2xvZycpICYmIChheC50eXBlID09PSAnbGluZWFyJyksXG4gICAgICAgIGZyb21Mb2cgPSAobmV3VHlwZSA9PT0gJ2xpbmVhcicpICYmIChheC50eXBlID09PSAnbG9nJyk7XG5cbiAgICBpZighKHRvTG9nIHx8IGZyb21Mb2cpKSByZXR1cm47XG5cbiAgICB2YXIgYW5ub3RhdGlvbnMgPSBnZC5fZnVsbExheW91dC5hbm5vdGF0aW9ucyxcbiAgICAgICAgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApLFxuICAgICAgICBhbm4sXG4gICAgICAgIGF0dHJQcmVmaXg7XG5cbiAgICBmdW5jdGlvbiBjb252ZXJ0KGF0dHIpIHtcbiAgICAgICAgdmFyIGN1cnJlbnRWYWwgPSBhbm5bYXR0cl0sXG4gICAgICAgICAgICBuZXdWYWwgPSBudWxsO1xuXG4gICAgICAgIGlmKHRvTG9nKSBuZXdWYWwgPSB0b0xvZ1JhbmdlKGN1cnJlbnRWYWwsIGF4LnJhbmdlKTtcbiAgICAgICAgZWxzZSBuZXdWYWwgPSBNYXRoLnBvdygxMCwgY3VycmVudFZhbCk7XG5cbiAgICAgICAgLy8gaWYgY29udmVyc2lvbiBmYWlsZWQsIGRlbGV0ZSB0aGUgdmFsdWUgc28gaXQgZ2V0cyBhIGRlZmF1bHQgdmFsdWVcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhuZXdWYWwpKSBuZXdWYWwgPSBudWxsO1xuXG4gICAgICAgIGRvRXh0cmEoYXR0clByZWZpeCArIGF0dHIsIG5ld1ZhbCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFubm90YXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFubiA9IGFubm90YXRpb25zW2ldO1xuICAgICAgICBhdHRyUHJlZml4ID0gJ2Fubm90YXRpb25zWycgKyBpICsgJ10uJztcblxuICAgICAgICBpZihhbm5bYXhMZXR0ZXIgKyAncmVmJ10gPT09IGF4Ll9pZCkgY29udmVydChheExldHRlcik7XG4gICAgICAgIGlmKGFublsnYScgKyBheExldHRlciArICdyZWYnXSA9PT0gYXguX2lkKSBjb252ZXJ0KCdhJyArIGF4TGV0dGVyKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMgPSByZXF1aXJlKCcuL2NvbW1vbl9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIHtcbiAgICAgICAgbmFtZTogJ2Fubm90YXRpb25zJyxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBoYW5kbGVBbm5vdGF0aW9uRGVmYXVsdHNcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUFubm90YXRpb25EZWZhdWx0cyhhbm5JbiwgYW5uT3V0LCBmdWxsTGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYW5uSW4sIGFubk91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICB2YXIgY2xpY2tUb1Nob3cgPSBjb2VyY2UoJ2NsaWNrdG9zaG93Jyk7XG5cbiAgICBpZighKHZpc2libGUgfHwgY2xpY2tUb1Nob3cpKSByZXR1cm47XG5cbiAgICBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMoYW5uSW4sIGFubk91dCwgZnVsbExheW91dCwgY29lcmNlKTtcblxuICAgIHZhciBzaG93QXJyb3cgPSBhbm5PdXQuc2hvd2Fycm93O1xuXG4gICAgLy8gcG9zaXRpb25pbmdcbiAgICB2YXIgYXhMZXR0ZXJzID0gWyd4JywgJ3knXSxcbiAgICAgICAgYXJyb3dQb3NEZmx0ID0gWy0xMCwgLTMwXSxcbiAgICAgICAgZ2RNb2NrID0ge19mdWxsTGF5b3V0OiBmdWxsTGF5b3V0fTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgIHZhciBheExldHRlciA9IGF4TGV0dGVyc1tpXTtcblxuICAgICAgICAvLyB4cmVmLCB5cmVmXG4gICAgICAgIHZhciBheFJlZiA9IEF4ZXMuY29lcmNlUmVmKGFubkluLCBhbm5PdXQsIGdkTW9jaywgYXhMZXR0ZXIsICcnLCAncGFwZXInKTtcblxuICAgICAgICBpZihheFJlZiAhPT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgdmFyIGF4ID0gQXhlcy5nZXRGcm9tSWQoZ2RNb2NrLCBheFJlZik7XG4gICAgICAgICAgICBheC5fYW5uSW5kaWNlcy5wdXNoKGFubk91dC5faW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8geCwgeVxuICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKGFubk91dCwgZ2RNb2NrLCBjb2VyY2UsIGF4UmVmLCBheExldHRlciwgMC41KTtcblxuICAgICAgICBpZihzaG93QXJyb3cpIHtcbiAgICAgICAgICAgIHZhciBhcnJvd1Bvc0F0dHIgPSAnYScgKyBheExldHRlcixcbiAgICAgICAgICAgICAgICAvLyBheHJlZiwgYXlyZWZcbiAgICAgICAgICAgICAgICBhYXhSZWYgPSBBeGVzLmNvZXJjZVJlZihhbm5JbiwgYW5uT3V0LCBnZE1vY2ssIGFycm93UG9zQXR0ciwgJ3BpeGVsJyk7XG5cbiAgICAgICAgICAgIC8vIGZvciBub3cgdGhlIGFycm93IGNhbiBvbmx5IGJlIG9uIHRoZSBzYW1lIGF4aXMgb3Igc3BlY2lmaWVkIGFzIHBpeGVsc1xuICAgICAgICAgICAgLy8gVE9ETzogc29tZXRpbWUgaXQgbWlnaHQgYmUgaW50ZXJlc3RpbmcgdG8gYWxsb3cgaXQgdG8gYmUgb24gKmFueSogYXhpc1xuICAgICAgICAgICAgLy8gYnV0IHRoYXQgd291bGQgcmVxdWlyZSB1cGRhdGVzIHRvIGRyYXdpbmcgJiBhdXRvcmFuZ2UgY29kZSBhbmQgbWF5YmUgbW9yZVxuICAgICAgICAgICAgaWYoYWF4UmVmICE9PSAncGl4ZWwnICYmIGFheFJlZiAhPT0gYXhSZWYpIHtcbiAgICAgICAgICAgICAgICBhYXhSZWYgPSBhbm5PdXRbYXJyb3dQb3NBdHRyXSA9ICdwaXhlbCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGF4LCBheVxuICAgICAgICAgICAgdmFyIGFEZmx0ID0gKGFheFJlZiA9PT0gJ3BpeGVsJykgPyBhcnJvd1Bvc0RmbHRbaV0gOiAwLjQ7XG4gICAgICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKGFubk91dCwgZ2RNb2NrLCBjb2VyY2UsIGFheFJlZiwgYXJyb3dQb3NBdHRyLCBhRGZsdCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB4YW5jaG9yLCB5YW5jaG9yXG4gICAgICAgIGNvZXJjZShheExldHRlciArICdhbmNob3InKTtcblxuICAgICAgICAvLyB4c2hpZnQsIHlzaGlmdFxuICAgICAgICBjb2VyY2UoYXhMZXR0ZXIgKyAnc2hpZnQnKTtcbiAgICB9XG5cbiAgICAvLyBpZiB5b3UgaGF2ZSBvbmUgY29vcmRpbmF0ZSB5b3Ugc2hvdWxkIGhhdmUgYm90aFxuICAgIExpYi5ub25lT3JBbGwoYW5uSW4sIGFubk91dCwgWyd4JywgJ3knXSk7XG5cbiAgICAvLyBpZiB5b3UgaGF2ZSBvbmUgcGFydCBvZiBhcnJvdyBsZW5ndGggeW91IHNob3VsZCBoYXZlIGJvdGhcbiAgICBpZihzaG93QXJyb3cpIHtcbiAgICAgICAgTGliLm5vbmVPckFsbChhbm5JbiwgYW5uT3V0LCBbJ2F4JywgJ2F5J10pO1xuICAgIH1cblxuICAgIGlmKGNsaWNrVG9TaG93KSB7XG4gICAgICAgIHZhciB4Q2xpY2sgPSBjb2VyY2UoJ3hjbGljaycpO1xuICAgICAgICB2YXIgeUNsaWNrID0gY29lcmNlKCd5Y2xpY2snKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGFjdHVhbCBjbGljayBkYXRhIHRvIGJpbmQgdG8gaW50byBwcml2YXRlIGF0dHJpYnV0ZXNcbiAgICAgICAgLy8gc28gd2UgZG9uJ3QgaGF2ZSB0byBkbyB0aGlzIGxpdHRsZSBiaXQgb2YgbG9naWMgb24gZXZlcnkgaG92ZXIgZXZlbnRcbiAgICAgICAgYW5uT3V0Ll94Y2xpY2sgPSAoeENsaWNrID09PSB1bmRlZmluZWQpID9cbiAgICAgICAgICAgIGFubk91dC54IDpcbiAgICAgICAgICAgIEF4ZXMuY2xlYW5Qb3NpdGlvbih4Q2xpY2ssIGdkTW9jaywgYW5uT3V0LnhyZWYpO1xuICAgICAgICBhbm5PdXQuX3ljbGljayA9ICh5Q2xpY2sgPT09IHVuZGVmaW5lZCkgP1xuICAgICAgICAgICAgYW5uT3V0LnkgOlxuICAgICAgICAgICAgQXhlcy5jbGVhblBvc2l0aW9uKHlDbGljaywgZ2RNb2NrLCBhbm5PdXQueXJlZik7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBGeCA9IHJlcXVpcmUoJy4uL2Z4Jyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgc2V0Q3Vyc29yID0gcmVxdWlyZSgnLi4vLi4vbGliL3NldGN1cnNvcicpO1xudmFyIGRyYWdFbGVtZW50ID0gcmVxdWlyZSgnLi4vZHJhZ2VsZW1lbnQnKTtcbnZhciBhcnJheUVkaXRvciA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS5hcnJheUVkaXRvcjtcblxudmFyIGRyYXdBcnJvd0hlYWQgPSByZXF1aXJlKCcuL2RyYXdfYXJyb3dfaGVhZCcpO1xuXG4vLyBBbm5vdGF0aW9ucyBhcmUgc3RvcmVkIGluIGdkLmxheW91dC5hbm5vdGF0aW9ucywgYW4gYXJyYXkgb2Ygb2JqZWN0c1xuLy8gaW5kZXggY2FuIHBvaW50IHRvIG9uZSBpdGVtIGluIHRoaXMgYXJyYXksXG4vLyAgb3Igbm9uLW51bWVyaWMgdG8gc2ltcGx5IGFkZCBhIG5ldyBvbmVcbi8vICBvciAtMSB0byBtb2RpZnkgYWxsIGV4aXN0aW5nXG4vLyBvcHQgY2FuIGJlIHRoZSBmdWxsIG9wdGlvbnMgb2JqZWN0LCBvciBvbmUga2V5ICh0byBiZSBzZXQgdG8gdmFsdWUpXG4vLyAgb3IgdW5kZWZpbmVkIHRvIHNpbXBseSByZWRyYXdcbi8vIGlmIG9wdCBpcyBibGFuaywgdmFsIGNhbiBiZSAnYWRkJyBvciBhIGZ1bGwgb3B0aW9ucyBvYmplY3QgdG8gYWRkIGEgbmV3XG4vLyAgYW5ub3RhdGlvbiBhdCB0aGF0IHBvaW50IGluIHRoZSBhcnJheSwgb3IgJ3JlbW92ZScgdG8gZGVsZXRlIHRoaXMgb25lXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGRyYXc6IGRyYXcsXG4gICAgZHJhd09uZTogZHJhd09uZSxcbiAgICBkcmF3UmF3OiBkcmF3UmF3XG59O1xuXG4vKlxuICogZHJhdzogZHJhdyBhbGwgYW5ub3RhdGlvbnMgd2l0aG91dCBhbnkgbmV3IG1vZGlmaWNhdGlvbnNcbiAqL1xuZnVuY3Rpb24gZHJhdyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0QWxsKCcuYW5ub3RhdGlvbicpLnJlbW92ZSgpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZnVsbExheW91dC5hbm5vdGF0aW9uc1tpXS52aXNpYmxlKSB7XG4gICAgICAgICAgICBkcmF3T25lKGdkLCBpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbn1cblxuLypcbiAqIGRyYXdPbmU6IGRyYXcgYSBzaW5nbGUgY2FydGVzaWFuIG9yIHBhcGVyLXJlZiBhbm5vdGF0aW9uLCBwb3RlbnRpYWxseSB3aXRoIG1vZGlmaWNhdGlvbnNcbiAqXG4gKiBpbmRleCAoaW50KTogdGhlIGFubm90YXRpb24gdG8gZHJhd1xuICovXG5mdW5jdGlvbiBkcmF3T25lKGdkLCBpbmRleCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG9wdGlvbnMgPSBmdWxsTGF5b3V0LmFubm90YXRpb25zW2luZGV4XSB8fCB7fTtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgb3B0aW9ucy54cmVmKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgb3B0aW9ucy55cmVmKTtcblxuICAgIGRyYXdSYXcoZ2QsIG9wdGlvbnMsIGluZGV4LCBmYWxzZSwgeGEsIHlhKTtcbn1cblxuLyoqXG4gKiBkcmF3UmF3OiBkcmF3IGEgc2luZ2xlIGFubm90YXRpb24sIHBvdGVudGlhbGx5IHdpdGggbW9kaWZpY2F0aW9uc1xuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyA6IHRoaXMgYW5ub3RhdGlvbidzIGZ1bGxMYXlvdXQgb3B0aW9uc1xuICogQHBhcmFtIHtpbnRlZ2VyfSBpbmRleCA6IGluZGV4IGluICdhbm5vdGF0aW9ucycgY29udGFpbmVyIG9mIHRoZSBhbm5vdGF0aW9uIHRvIGRyYXdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJwbG90SWQgOiBpZCBvZiB0aGUgYW5ub3RhdGlvbidzIHN1YnBsb3RcbiAqICAtIHVzZSBmYWxzZSBmb3IgMmQgKGkuZS4gY2FydGVzaWFuIG9yIHBhcGVyLXJlZikgYW5ub3RhdGlvbnNcbiAqIEBwYXJhbSB7b2JqZWN0IHwgdW5kZWZpbmVkfSB4YSA6IGZ1bGwgeC1heGlzIG9iamVjdCB0byBjb21wdXRlIHN1YnBsb3QgcG9zLXRvLXB4XG4gKiBAcGFyYW0ge29iamVjdCB8IHVuZGVmaW5lZH0geWEgOiAuLi4geS1heGlzXG4gKi9cbmZ1bmN0aW9uIGRyYXdSYXcoZ2QsIG9wdGlvbnMsIGluZGV4LCBzdWJwbG90SWQsIHhhLCB5YSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGdzID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGVkaXRzID0gZ2QuX2NvbnRleHQuZWRpdHM7XG5cbiAgICB2YXIgY2xhc3NOYW1lLCBjb250YWluZXJTdHI7XG5cbiAgICBpZihzdWJwbG90SWQpIHtcbiAgICAgICAgY2xhc3NOYW1lID0gJ2Fubm90YXRpb24tJyArIHN1YnBsb3RJZDtcbiAgICAgICAgY29udGFpbmVyU3RyID0gc3VicGxvdElkICsgJy5hbm5vdGF0aW9ucyc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2xhc3NOYW1lID0gJ2Fubm90YXRpb24nO1xuICAgICAgICBjb250YWluZXJTdHIgPSAnYW5ub3RhdGlvbnMnO1xuICAgIH1cblxuICAgIHZhciBlZGl0SGVscGVycyA9IGFycmF5RWRpdG9yKGdkLmxheW91dCwgY29udGFpbmVyU3RyLCBvcHRpb25zKTtcbiAgICB2YXIgbW9kaWZ5QmFzZSA9IGVkaXRIZWxwZXJzLm1vZGlmeUJhc2U7XG4gICAgdmFyIG1vZGlmeUl0ZW0gPSBlZGl0SGVscGVycy5tb2RpZnlJdGVtO1xuICAgIHZhciBnZXRVcGRhdGVPYmogPSBlZGl0SGVscGVycy5nZXRVcGRhdGVPYmo7XG5cbiAgICAvLyByZW1vdmUgdGhlIGV4aXN0aW5nIGFubm90YXRpb24gaWYgdGhlcmUgaXMgb25lXG4gICAgZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY2xhc3NOYW1lICsgJ1tkYXRhLWluZGV4PVwiJyArIGluZGV4ICsgJ1wiXScpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHZhciBhbm5DbGlwSUQgPSAnY2xpcCcgKyBmdWxsTGF5b3V0Ll91aWQgKyAnX2FubicgKyBpbmRleDtcblxuICAgIC8vIHRoaXMgYW5ub3RhdGlvbiBpcyBnb25lIC0gcXVpdCBub3cgYWZ0ZXIgZGVsZXRpbmcgaXRcbiAgICAvLyBUT0RPOiB1c2UgZDMgaWRpb21zIGluc3RlYWQgb2YgZGVsZXRpbmcgYW5kIHJlZHJhd2luZyBldmVyeSB0aW1lXG4gICAgaWYoIW9wdGlvbnMuX2lucHV0IHx8IG9wdGlvbnMudmlzaWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgZDMuc2VsZWN0QWxsKCcjJyArIGFubkNsaXBJRCkucmVtb3ZlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjYWxjdWxhdGVkIHBpeGVsIHBvc2l0aW9uc1xuICAgIC8vIHggJiB5IGVhY2ggd2lsbCBnZXQgdGV4dCwgaGVhZCwgYW5kIHRhaWwgYXMgYXBwcm9wcmlhdGVcbiAgICB2YXIgYW5uUG9zUHggPSB7eDoge30sIHk6IHt9fSxcbiAgICAgICAgdGV4dGFuZ2xlID0gK29wdGlvbnMudGV4dGFuZ2xlIHx8IDA7XG5cbiAgICAvLyBjcmVhdGUgdGhlIGNvbXBvbmVudHNcbiAgICAvLyBtYWRlIGEgc2luZ2xlIGdyb3VwIHRvIGNvbnRhaW4gYWxsLCBzbyBvcGFjaXR5IGNhbiB3b3JrIHJpZ2h0XG4gICAgLy8gd2l0aCBib3JkZXIvYXJyb3cgdG9nZXRoZXIgdGhpcyBjb3VsZCBoYW5kbGUgYSB3aG9sZSBidW5jaCBvZlxuICAgIC8vIGNsZWFudXAgYXQgdGhpcyBwb2ludCwgYnV0IHdvcmtzIGZvciBub3dcbiAgICB2YXIgYW5uR3JvdXAgPSBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY2xhc3NOYW1lLCB0cnVlKVxuICAgICAgICAuYXR0cignZGF0YS1pbmRleCcsIFN0cmluZyhpbmRleCkpXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG5cbiAgICAvLyBhbm90aGVyIGdyb3VwIGZvciB0ZXh0K2JhY2tncm91bmQgc28gdGhhdCB0aGV5IGNhbiByb3RhdGUgdG9nZXRoZXJcbiAgICB2YXIgYW5uVGV4dEdyb3VwID0gYW5uR3JvdXAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2Fubm90YXRpb24tdGV4dC1nJywgdHJ1ZSk7XG5cbiAgICB2YXIgZWRpdFRleHRQb3NpdGlvbiA9IGVkaXRzW29wdGlvbnMuc2hvd2Fycm93ID8gJ2Fubm90YXRpb25UYWlsJyA6ICdhbm5vdGF0aW9uUG9zaXRpb24nXTtcbiAgICB2YXIgdGV4dEV2ZW50cyA9IG9wdGlvbnMuY2FwdHVyZWV2ZW50cyB8fCBlZGl0cy5hbm5vdGF0aW9uVGV4dCB8fCBlZGl0VGV4dFBvc2l0aW9uO1xuXG4gICAgdmFyIGFublRleHRHcm91cElubmVyID0gYW5uVGV4dEdyb3VwLmFwcGVuZCgnZycpXG4gICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCB0ZXh0RXZlbnRzID8gJ2FsbCcgOiBudWxsKVxuICAgICAgICAuY2FsbChzZXRDdXJzb3IsICdwb2ludGVyJylcbiAgICAgICAgLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgZ2QuX2RyYWdnaW5nID0gZmFsc2U7XG5cbiAgICAgICAgICAgIHZhciBldmVudERhdGEgPSB7XG4gICAgICAgICAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICAgICAgICAgIGFubm90YXRpb246IG9wdGlvbnMuX2lucHV0LFxuICAgICAgICAgICAgICAgIGZ1bGxBbm5vdGF0aW9uOiBvcHRpb25zLFxuICAgICAgICAgICAgICAgIGV2ZW50OiBkMy5ldmVudFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYoc3VicGxvdElkKSB7XG4gICAgICAgICAgICAgICAgZXZlbnREYXRhLnN1YnBsb3RJZCA9IHN1YnBsb3RJZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2NsaWNrYW5ub3RhdGlvbicsIGV2ZW50RGF0YSk7XG4gICAgICAgIH0pO1xuXG4gICAgaWYob3B0aW9ucy5ob3ZlcnRleHQpIHtcbiAgICAgICAgYW5uVGV4dEdyb3VwSW5uZXJcbiAgICAgICAgLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBob3Zlck9wdGlvbnMgPSBvcHRpb25zLmhvdmVybGFiZWw7XG4gICAgICAgICAgICB2YXIgaG92ZXJGb250ID0gaG92ZXJPcHRpb25zLmZvbnQ7XG4gICAgICAgICAgICB2YXIgYkJveCA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB2YXIgYkJveFJlZiA9IGdkLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgIHgwOiBiQm94LmxlZnQgLSBiQm94UmVmLmxlZnQsXG4gICAgICAgICAgICAgICAgeDE6IGJCb3gucmlnaHQgLSBiQm94UmVmLmxlZnQsXG4gICAgICAgICAgICAgICAgeTogKGJCb3gudG9wICsgYkJveC5ib3R0b20pIC8gMiAtIGJCb3hSZWYudG9wLFxuICAgICAgICAgICAgICAgIHRleHQ6IG9wdGlvbnMuaG92ZXJ0ZXh0LFxuICAgICAgICAgICAgICAgIGNvbG9yOiBob3Zlck9wdGlvbnMuYmdjb2xvcixcbiAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogaG92ZXJPcHRpb25zLmJvcmRlcmNvbG9yLFxuICAgICAgICAgICAgICAgIGZvbnRGYW1pbHk6IGhvdmVyRm9udC5mYW1pbHksXG4gICAgICAgICAgICAgICAgZm9udFNpemU6IGhvdmVyRm9udC5zaXplLFxuICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogaG92ZXJGb250LmNvbG9yXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgIGdkOiBnZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIEZ4LmxvbmVVbmhvdmVyKGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGJvcmRlcndpZHRoID0gb3B0aW9ucy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgYm9yZGVycGFkID0gb3B0aW9ucy5ib3JkZXJwYWQsXG4gICAgICAgIGJvcmRlcmZ1bGwgPSBib3JkZXJ3aWR0aCArIGJvcmRlcnBhZDtcblxuICAgIHZhciBhbm5UZXh0QkcgPSBhbm5UZXh0R3JvdXBJbm5lci5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYmcnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGJvcmRlcndpZHRoICsgJ3B4JylcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBvcHRpb25zLmJvcmRlcmNvbG9yKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBvcHRpb25zLmJnY29sb3IpO1xuXG4gICAgdmFyIGlzU2l6ZUNvbnN0cmFpbmVkID0gb3B0aW9ucy53aWR0aCB8fCBvcHRpb25zLmhlaWdodDtcblxuICAgIHZhciBhbm5UZXh0Q2xpcCA9IGZ1bGxMYXlvdXQuX3RvcGNsaXBzXG4gICAgICAgIC5zZWxlY3RBbGwoJyMnICsgYW5uQ2xpcElEKVxuICAgICAgICAuZGF0YShpc1NpemVDb25zdHJhaW5lZCA/IFswXSA6IFtdKTtcblxuICAgIGFublRleHRDbGlwLmVudGVyKCkuYXBwZW5kKCdjbGlwUGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKCdhbm5jbGlwJywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgYW5uQ2xpcElEKVxuICAgICAgLmFwcGVuZCgncmVjdCcpO1xuICAgIGFublRleHRDbGlwLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHZhciBmb250ID0gb3B0aW9ucy5mb250O1xuXG4gICAgdmFyIGFublRleHQgPSBhbm5UZXh0R3JvdXBJbm5lci5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuY2xhc3NlZCgnYW5ub3RhdGlvbi10ZXh0JywgdHJ1ZSlcbiAgICAgICAgLnRleHQob3B0aW9ucy50ZXh0KTtcblxuICAgIGZ1bmN0aW9uIHRleHRMYXlvdXQocykge1xuICAgICAgICBzLmNhbGwoRHJhd2luZy5mb250LCBmb250KVxuICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAndGV4dC1hbmNob3InOiB7XG4gICAgICAgICAgICAgICAgbGVmdDogJ3N0YXJ0JyxcbiAgICAgICAgICAgICAgICByaWdodDogJ2VuZCdcbiAgICAgICAgICAgIH1bb3B0aW9ucy5hbGlnbl0gfHwgJ21pZGRsZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucyhzLCBnZCwgZHJhd0dyYXBoaWNhbEVsZW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0dyYXBoaWNhbEVsZW1lbnRzKCkge1xuICAgICAgICAvLyBpZiB0aGUgdGV4dCBoYXMgKm9ubHkqIGEgbGluaywgbWFrZSB0aGUgd2hvbGUgYm94IGludG8gYSBsaW5rXG4gICAgICAgIHZhciBhbmNob3IzID0gYW5uVGV4dC5zZWxlY3RBbGwoJ2EnKTtcbiAgICAgICAgaWYoYW5jaG9yMy5zaXplKCkgPT09IDEgJiYgYW5jaG9yMy50ZXh0KCkgPT09IGFublRleHQudGV4dCgpKSB7XG4gICAgICAgICAgICB2YXIgd2hvbGVMaW5rID0gYW5uVGV4dEdyb3VwSW5uZXIuaW5zZXJ0KCdhJywgJzpmaXJzdC1jaGlsZCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgICd4bGluazp4bGluazpocmVmJzogYW5jaG9yMy5hdHRyKCd4bGluazpocmVmJyksXG4gICAgICAgICAgICAgICAgJ3hsaW5rOnhsaW5rOnNob3cnOiBhbmNob3IzLmF0dHIoJ3hsaW5rOnNob3cnKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5zdHlsZSh7Y3Vyc29yOiAncG9pbnRlcid9KTtcblxuICAgICAgICAgICAgd2hvbGVMaW5rLm5vZGUoKS5hcHBlbmRDaGlsZChhbm5UZXh0Qkcubm9kZSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtYXRoamF4R3JvdXAgPSBhbm5UZXh0R3JvdXBJbm5lci5zZWxlY3QoJy5hbm5vdGF0aW9uLXRleHQtbWF0aC1ncm91cCcpO1xuICAgICAgICB2YXIgaGFzTWF0aGpheCA9ICFtYXRoamF4R3JvdXAuZW1wdHkoKTtcbiAgICAgICAgdmFyIGFubnRleHRCQiA9IERyYXdpbmcuYkJveChcbiAgICAgICAgICAgICAgICAoaGFzTWF0aGpheCA/IG1hdGhqYXhHcm91cCA6IGFublRleHQpLm5vZGUoKSk7XG4gICAgICAgIHZhciB0ZXh0V2lkdGggPSBhbm50ZXh0QkIud2lkdGg7XG4gICAgICAgIHZhciB0ZXh0SGVpZ2h0ID0gYW5udGV4dEJCLmhlaWdodDtcbiAgICAgICAgdmFyIGFubldpZHRoID0gb3B0aW9ucy53aWR0aCB8fCB0ZXh0V2lkdGg7XG4gICAgICAgIHZhciBhbm5IZWlnaHQgPSBvcHRpb25zLmhlaWdodCB8fCB0ZXh0SGVpZ2h0O1xuICAgICAgICB2YXIgb3V0ZXJXaWR0aCA9IE1hdGgucm91bmQoYW5uV2lkdGggKyAyICogYm9yZGVyZnVsbCk7XG4gICAgICAgIHZhciBvdXRlckhlaWdodCA9IE1hdGgucm91bmQoYW5uSGVpZ2h0ICsgMiAqIGJvcmRlcmZ1bGwpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNoaWZ0RnJhY3Rpb24odiwgYW5jaG9yKSB7XG4gICAgICAgICAgICBpZihhbmNob3IgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgICAgIGlmKHYgPCAxIC8gMykgYW5jaG9yID0gJ2xlZnQnO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYodiA+IDIgLyAzKSBhbmNob3IgPSAncmlnaHQnO1xuICAgICAgICAgICAgICAgIGVsc2UgYW5jaG9yID0gJ2NlbnRlcic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNlbnRlcjogMCxcbiAgICAgICAgICAgICAgICBtaWRkbGU6IDAsXG4gICAgICAgICAgICAgICAgbGVmdDogMC41LFxuICAgICAgICAgICAgICAgIGJvdHRvbTogLTAuNSxcbiAgICAgICAgICAgICAgICByaWdodDogLTAuNSxcbiAgICAgICAgICAgICAgICB0b3A6IDAuNVxuICAgICAgICAgICAgfVthbmNob3JdO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFubm90YXRpb25Jc09mZnNjcmVlbiA9IGZhbHNlO1xuICAgICAgICB2YXIgbGV0dGVycyA9IFsneCcsICd5J107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGxldHRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBheExldHRlciA9IGxldHRlcnNbaV0sXG4gICAgICAgICAgICAgICAgYXhSZWYgPSBvcHRpb25zW2F4TGV0dGVyICsgJ3JlZiddIHx8IGF4TGV0dGVyLFxuICAgICAgICAgICAgICAgIHRhaWxSZWYgPSBvcHRpb25zWydhJyArIGF4TGV0dGVyICsgJ3JlZiddLFxuICAgICAgICAgICAgICAgIGF4ID0ge3g6IHhhLCB5OiB5YX1bYXhMZXR0ZXJdLFxuICAgICAgICAgICAgICAgIGRpbUFuZ2xlID0gKHRleHRhbmdsZSArIChheExldHRlciA9PT0gJ3gnID8gMCA6IC05MCkpICogTWF0aC5QSSAvIDE4MCxcbiAgICAgICAgICAgICAgICAvLyBub3RlIHRoYXQgdGhlc2UgdHdvIGNhbiBiZSBlaXRoZXIgcG9zaXRpdmUgb3IgbmVnYXRpdmVcbiAgICAgICAgICAgICAgICBhbm5TaXplRnJvbVdpZHRoID0gb3V0ZXJXaWR0aCAqIE1hdGguY29zKGRpbUFuZ2xlKSxcbiAgICAgICAgICAgICAgICBhbm5TaXplRnJvbUhlaWdodCA9IG91dGVySGVpZ2h0ICogTWF0aC5zaW4oZGltQW5nbGUpLFxuICAgICAgICAgICAgICAgIC8vIGJ1dCB0aGlzIG9uZSBpcyB0aGUgcG9zaXRpdmUgdG90YWwgc2l6ZVxuICAgICAgICAgICAgICAgIGFublNpemUgPSBNYXRoLmFicyhhbm5TaXplRnJvbVdpZHRoKSArIE1hdGguYWJzKGFublNpemVGcm9tSGVpZ2h0KSxcbiAgICAgICAgICAgICAgICBhbmNob3IgPSBvcHRpb25zW2F4TGV0dGVyICsgJ2FuY2hvciddLFxuICAgICAgICAgICAgICAgIG92ZXJhbGxTaGlmdCA9IG9wdGlvbnNbYXhMZXR0ZXIgKyAnc2hpZnQnXSAqIChheExldHRlciA9PT0gJ3gnID8gMSA6IC0xKSxcbiAgICAgICAgICAgICAgICBwb3NQeCA9IGFublBvc1B4W2F4TGV0dGVyXSxcbiAgICAgICAgICAgICAgICBiYXNlUHgsXG4gICAgICAgICAgICAgICAgdGV4dFBhZFNoaWZ0LFxuICAgICAgICAgICAgICAgIGFsaWduUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgYXV0b0FsaWduRnJhY3Rpb24sXG4gICAgICAgICAgICAgICAgdGV4dFNoaWZ0O1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogY2FsY3VsYXRlIHRoZSAqcHJpbWFyeSogcGl4ZWwgcG9zaXRpb25cbiAgICAgICAgICAgICAqIHdoaWNoIGlzIHRoZSBhcnJvd2hlYWQgaWYgdGhlcmUgaXMgb25lLFxuICAgICAgICAgICAgICogb3RoZXJ3aXNlIHRoZSB0ZXh0IGFuY2hvciBwb2ludFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZihheCkge1xuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGFubm90YXRpb24gaXMgb2ZmIHNjcmVlbiwgdG8gYnlwYXNzIERPTSBtYW5pcHVsYXRpb25zXG4gICAgICAgICAgICAgICAgdmFyIHBvc0ZyYWN0aW9uID0gYXgucjJmcmFjdGlvbihvcHRpb25zW2F4TGV0dGVyXSk7XG4gICAgICAgICAgICAgICAgaWYocG9zRnJhY3Rpb24gPCAwIHx8IHBvc0ZyYWN0aW9uID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZih0YWlsUmVmID09PSBheFJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zRnJhY3Rpb24gPSBheC5yMmZyYWN0aW9uKG9wdGlvbnNbJ2EnICsgYXhMZXR0ZXJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHBvc0ZyYWN0aW9uIDwgMCB8fCBwb3NGcmFjdGlvbiA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uSXNPZmZzY3JlZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbklzT2Zmc2NyZWVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBiYXNlUHggPSBheC5fb2Zmc2V0ICsgYXgucjJwKG9wdGlvbnNbYXhMZXR0ZXJdKTtcbiAgICAgICAgICAgICAgICBhdXRvQWxpZ25GcmFjdGlvbiA9IDAuNTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25Qb3NpdGlvbiA9IG9wdGlvbnNbYXhMZXR0ZXJdO1xuICAgICAgICAgICAgICAgICAgICBiYXNlUHggPSBncy5sICsgZ3MudyAqIGFsaWduUG9zaXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhbGlnblBvc2l0aW9uID0gMSAtIG9wdGlvbnNbYXhMZXR0ZXJdO1xuICAgICAgICAgICAgICAgICAgICBiYXNlUHggPSBncy50ICsgZ3MuaCAqIGFsaWduUG9zaXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF1dG9BbGlnbkZyYWN0aW9uID0gb3B0aW9ucy5zaG93YXJyb3cgPyAwLjUgOiBhbGlnblBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBub3cgdHJhbnNsYXRlIHRoaXMgaW50byBwaXhlbCBwb3NpdGlvbnMgb2YgaGVhZCwgdGFpbCwgYW5kIHRleHRcbiAgICAgICAgICAgIC8vIGFzIHdlbGwgYXMgcGFkZGluZ3MgZm9yIGF1dG9yYW5nZVxuICAgICAgICAgICAgaWYob3B0aW9ucy5zaG93YXJyb3cpIHtcbiAgICAgICAgICAgICAgICBwb3NQeC5oZWFkID0gYmFzZVB4O1xuXG4gICAgICAgICAgICAgICAgdmFyIGFycm93TGVuZ3RoID0gb3B0aW9uc1snYScgKyBheExldHRlcl07XG5cbiAgICAgICAgICAgICAgICAvLyB3aXRoIGFuIGFycm93LCB0aGUgdGV4dCByb3RhdGVzIGFyb3VuZCB0aGUgYW5jaG9yIHBvaW50XG4gICAgICAgICAgICAgICAgdGV4dFNoaWZ0ID0gYW5uU2l6ZUZyb21XaWR0aCAqIHNoaWZ0RnJhY3Rpb24oMC41LCBvcHRpb25zLnhhbmNob3IpIC1cbiAgICAgICAgICAgICAgICAgICAgYW5uU2l6ZUZyb21IZWlnaHQgKiBzaGlmdEZyYWN0aW9uKDAuNSwgb3B0aW9ucy55YW5jaG9yKTtcblxuICAgICAgICAgICAgICAgIGlmKHRhaWxSZWYgPT09IGF4UmVmKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc1B4LnRhaWwgPSBheC5fb2Zmc2V0ICsgYXgucjJwKGFycm93TGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGFpbCBpcyBkYXRhLXJlZmVyZW5jZWQ6IGF1dG9yYW5nZSBwYWRzIHRoZSB0ZXh0IGluIHB4IGZyb20gdGhlIHRhaWxcbiAgICAgICAgICAgICAgICAgICAgdGV4dFBhZFNoaWZ0ID0gdGV4dFNoaWZ0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zUHgudGFpbCA9IGJhc2VQeCArIGFycm93TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAvLyB0YWlsIGlzIHNwZWNpZmllZCBpbiBweCBmcm9tIGhlYWQsIHNvIGF1dG9yYW5nZSBhbHNvIHBhZHMgdnMgaGVhZFxuICAgICAgICAgICAgICAgICAgICB0ZXh0UGFkU2hpZnQgPSB0ZXh0U2hpZnQgKyBhcnJvd0xlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwb3NQeC50ZXh0ID0gcG9zUHgudGFpbCArIHRleHRTaGlmdDtcblxuICAgICAgICAgICAgICAgIC8vIGNvbnN0cmFpbiBwaXhlbC9wYXBlciByZWZlcmVuY2VkIHNvIHRoZSBkcmFnZ2VycyBhcmUgYXQgbGVhc3RcbiAgICAgICAgICAgICAgICAvLyBwYXJ0aWFsbHkgdmlzaWJsZVxuICAgICAgICAgICAgICAgIHZhciBtYXhQeCA9IGZ1bGxMYXlvdXRbKGF4TGV0dGVyID09PSAneCcpID8gJ3dpZHRoJyA6ICdoZWlnaHQnXTtcbiAgICAgICAgICAgICAgICBpZihheFJlZiA9PT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgICAgICAgICBwb3NQeC5oZWFkID0gTGliLmNvbnN0cmFpbihwb3NQeC5oZWFkLCAxLCBtYXhQeCAtIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZih0YWlsUmVmID09PSAncGl4ZWwnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzaGlmdFBsdXMgPSAtTWF0aC5tYXgocG9zUHgudGFpbCAtIDMsIHBvc1B4LnRleHQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRNaW51cyA9IE1hdGgubWluKHBvc1B4LnRhaWwgKyAzLCBwb3NQeC50ZXh0KSAtIG1heFB4O1xuICAgICAgICAgICAgICAgICAgICBpZihzaGlmdFBsdXMgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NQeC50YWlsICs9IHNoaWZ0UGx1cztcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc1B4LnRleHQgKz0gc2hpZnRQbHVzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoc2hpZnRNaW51cyA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc1B4LnRhaWwgLT0gc2hpZnRNaW51cztcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc1B4LnRleHQgLT0gc2hpZnRNaW51cztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHBvc1B4LnRhaWwgKz0gb3ZlcmFsbFNoaWZ0O1xuICAgICAgICAgICAgICAgIHBvc1B4LmhlYWQgKz0gb3ZlcmFsbFNoaWZ0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gd2l0aCBubyBhcnJvdywgdGhlIHRleHQgcm90YXRlcyBhbmQgKnRoZW4qIHdlIHB1dCB0aGUgYW5jaG9yXG4gICAgICAgICAgICAgICAgLy8gcmVsYXRpdmUgdG8gdGhlIG5ldyBib3VuZGluZyBib3hcbiAgICAgICAgICAgICAgICB0ZXh0U2hpZnQgPSBhbm5TaXplICogc2hpZnRGcmFjdGlvbihhdXRvQWxpZ25GcmFjdGlvbiwgYW5jaG9yKTtcbiAgICAgICAgICAgICAgICB0ZXh0UGFkU2hpZnQgPSB0ZXh0U2hpZnQ7XG4gICAgICAgICAgICAgICAgcG9zUHgudGV4dCA9IGJhc2VQeCArIHRleHRTaGlmdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcG9zUHgudGV4dCArPSBvdmVyYWxsU2hpZnQ7XG4gICAgICAgICAgICB0ZXh0U2hpZnQgKz0gb3ZlcmFsbFNoaWZ0O1xuICAgICAgICAgICAgdGV4dFBhZFNoaWZ0ICs9IG92ZXJhbGxTaGlmdDtcblxuICAgICAgICAgICAgLy8gcGFkcGx1cy9taW51cyBhcmUgdXNlZCBieSBhdXRvcmFuZ2VcbiAgICAgICAgICAgIG9wdGlvbnNbJ18nICsgYXhMZXR0ZXIgKyAncGFkcGx1cyddID0gKGFublNpemUgLyAyKSArIHRleHRQYWRTaGlmdDtcbiAgICAgICAgICAgIG9wdGlvbnNbJ18nICsgYXhMZXR0ZXIgKyAncGFkbWludXMnXSA9IChhbm5TaXplIC8gMikgLSB0ZXh0UGFkU2hpZnQ7XG5cbiAgICAgICAgICAgIC8vIHNpemUvc2hpZnQgYXJlIHVzZWQgZHVyaW5nIGRyYWdnaW5nXG4gICAgICAgICAgICBvcHRpb25zWydfJyArIGF4TGV0dGVyICsgJ3NpemUnXSA9IGFublNpemU7XG4gICAgICAgICAgICBvcHRpb25zWydfJyArIGF4TGV0dGVyICsgJ3NoaWZ0J10gPSB0ZXh0U2hpZnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBoYXZlIGV2ZXJ5dGhpbmcgd2UgbmVlZCBmb3IgY2FsY0F1dG9yYW5nZSBhdCB0aGlzIHBvaW50LFxuICAgICAgICAvLyB3ZSBjYW4gc2FmZWx5IGV4aXQgLSB1bmxlc3Mgd2UncmUgY3VycmVudGx5IGRyYWdnaW5nIHRoZSBwbG90XG4gICAgICAgIGlmKCFnZC5fZHJhZ2dpbmcgJiYgYW5ub3RhdGlvbklzT2Zmc2NyZWVuKSB7XG4gICAgICAgICAgICBhbm5UZXh0R3JvdXBJbm5lci5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB4U2hpZnQgPSAwO1xuICAgICAgICB2YXIgeVNoaWZ0ID0gMDtcblxuICAgICAgICBpZihvcHRpb25zLmFsaWduICE9PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIHhTaGlmdCA9IChhbm5XaWR0aCAtIHRleHRXaWR0aCkgKiAob3B0aW9ucy5hbGlnbiA9PT0gJ2NlbnRlcicgPyAwLjUgOiAxKTtcbiAgICAgICAgfVxuICAgICAgICBpZihvcHRpb25zLnZhbGlnbiAhPT0gJ3RvcCcpIHtcbiAgICAgICAgICAgIHlTaGlmdCA9IChhbm5IZWlnaHQgLSB0ZXh0SGVpZ2h0KSAqIChvcHRpb25zLnZhbGlnbiA9PT0gJ21pZGRsZScgPyAwLjUgOiAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhhc01hdGhqYXgpIHtcbiAgICAgICAgICAgIG1hdGhqYXhHcm91cC5zZWxlY3QoJ3N2ZycpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHg6IGJvcmRlcmZ1bGwgKyB4U2hpZnQgLSAxLFxuICAgICAgICAgICAgICAgIHk6IGJvcmRlcmZ1bGwgKyB5U2hpZnRcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGlzU2l6ZUNvbnN0cmFpbmVkID8gYW5uQ2xpcElEIDogbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGV4dHkgPSBib3JkZXJmdWxsICsgeVNoaWZ0IC0gYW5udGV4dEJCLnRvcDtcbiAgICAgICAgICAgIHZhciB0ZXh0eCA9IGJvcmRlcmZ1bGwgKyB4U2hpZnQgLSBhbm50ZXh0QkIubGVmdDtcblxuICAgICAgICAgICAgYW5uVGV4dC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIHRleHR4LCB0ZXh0eSlcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGlzU2l6ZUNvbnN0cmFpbmVkID8gYW5uQ2xpcElEIDogbnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICBhbm5UZXh0Q2xpcC5zZWxlY3QoJ3JlY3QnKS5jYWxsKERyYXdpbmcuc2V0UmVjdCwgYm9yZGVyZnVsbCwgYm9yZGVyZnVsbCxcbiAgICAgICAgICAgIGFubldpZHRoLCBhbm5IZWlnaHQpO1xuXG4gICAgICAgIGFublRleHRCRy5jYWxsKERyYXdpbmcuc2V0UmVjdCwgYm9yZGVyd2lkdGggLyAyLCBib3JkZXJ3aWR0aCAvIDIsXG4gICAgICAgICAgICBvdXRlcldpZHRoIC0gYm9yZGVyd2lkdGgsIG91dGVySGVpZ2h0IC0gYm9yZGVyd2lkdGgpO1xuXG4gICAgICAgIGFublRleHRHcm91cElubmVyLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsXG4gICAgICAgICAgICBNYXRoLnJvdW5kKGFublBvc1B4LngudGV4dCAtIG91dGVyV2lkdGggLyAyKSxcbiAgICAgICAgICAgIE1hdGgucm91bmQoYW5uUG9zUHgueS50ZXh0IC0gb3V0ZXJIZWlnaHQgLyAyKSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogcm90YXRlIHRleHQgYW5kIGJhY2tncm91bmRcbiAgICAgICAgICogd2UgYWxyZWFkeSBjYWxjdWxhdGVkIHRoZSB0ZXh0IGNlbnRlciBwb3NpdGlvbiAqYXMgcm90YXRlZCpcbiAgICAgICAgICogYmVjYXVzZSB3ZSBuZWVkZWQgdGhhdCBmb3IgYXV0b3JhbmdpbmcgYW55d2F5LCBzbyBub3cgd2hldGhlclxuICAgICAgICAgKiB3ZSBoYXZlIGFuIGFycm93IG9yIG5vdCwgd2Ugcm90YXRlIGFib3V0IHRoZSB0ZXh0IGNlbnRlci5cbiAgICAgICAgICovXG4gICAgICAgIGFublRleHRHcm91cC5hdHRyKHt0cmFuc2Zvcm06ICdyb3RhdGUoJyArIHRleHRhbmdsZSArICcsJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5uUG9zUHgueC50ZXh0ICsgJywnICsgYW5uUG9zUHgueS50ZXh0ICsgJyknfSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogYWRkIHRoZSBhcnJvd1xuICAgICAgICAgKiB1c2VzIG9wdGlvbnNbYXJyb3d3aWR0aCxhcnJvd2NvbG9yLGFycm93aGVhZF0gZm9yIHN0eWxpbmdcbiAgICAgICAgICogZHggYW5kIGR5IGFyZSBub3JtYWxseSB6ZXJvLCBidXQgd2hlbiB5b3UgYXJlIGRyYWdnaW5nIHRoZSB0ZXh0Ym94XG4gICAgICAgICAqIHdoaWxlIHRoZSBoZWFkIHN0YXlzIHB1dCwgZHggYW5kIGR5IGFyZSB0aGUgcGl4ZWwgb2Zmc2V0c1xuICAgICAgICAgKi9cbiAgICAgICAgdmFyIGRyYXdBcnJvdyA9IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgYW5uR3JvdXBcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCcuYW5ub3RhdGlvbi1hcnJvdy1nJylcbiAgICAgICAgICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIHZhciBoZWFkWCA9IGFublBvc1B4LnguaGVhZCxcbiAgICAgICAgICAgICAgICBoZWFkWSA9IGFublBvc1B4LnkuaGVhZCxcbiAgICAgICAgICAgICAgICB0YWlsWCA9IGFublBvc1B4LngudGFpbCArIGR4LFxuICAgICAgICAgICAgICAgIHRhaWxZID0gYW5uUG9zUHgueS50YWlsICsgZHksXG4gICAgICAgICAgICAgICAgdGV4dFggPSBhbm5Qb3NQeC54LnRleHQgKyBkeCxcbiAgICAgICAgICAgICAgICB0ZXh0WSA9IGFublBvc1B4LnkudGV4dCArIGR5LFxuXG4gICAgICAgICAgICAgICAgLy8gZmluZCB0aGUgZWRnZSBvZiB0aGUgdGV4dCBib3gsIHdoZXJlIHdlJ2xsIHN0YXJ0IHRoZSBhcnJvdzpcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgdHJhbnNmb3JtIG1hdHJpeCB0byByb3RhdGUgdGhlIHRleHQgYm94IGNvcm5lcnNcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBMaWIucm90YXRpb25YWU1hdHJpeCh0ZXh0YW5nbGUsIHRleHRYLCB0ZXh0WSksXG4gICAgICAgICAgICAgICAgYXBwbHlUcmFuc2Zvcm0gPSBMaWIuYXBwbHkyRFRyYW5zZm9ybSh0cmFuc2Zvcm0pLFxuICAgICAgICAgICAgICAgIGFwcGx5VHJhbnNmb3JtMiA9IExpYi5hcHBseTJEVHJhbnNmb3JtMih0cmFuc2Zvcm0pLFxuXG4gICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIGFuZCB0cmFuc2Zvcm0gYm91bmRpbmcgYm94XG4gICAgICAgICAgICAgICAgd2lkdGggPSArYW5uVGV4dEJHLmF0dHIoJ3dpZHRoJyksXG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gK2FublRleHRCRy5hdHRyKCdoZWlnaHQnKSxcbiAgICAgICAgICAgICAgICB4TGVmdCA9IHRleHRYIC0gMC41ICogd2lkdGgsXG4gICAgICAgICAgICAgICAgeFJpZ2h0ID0geExlZnQgKyB3aWR0aCxcbiAgICAgICAgICAgICAgICB5VG9wID0gdGV4dFkgLSAwLjUgKiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgeUJvdHRvbSA9IHlUb3AgKyBoZWlnaHQsXG4gICAgICAgICAgICAgICAgZWRnZXMgPSBbXG4gICAgICAgICAgICAgICAgICAgIFt4TGVmdCwgeVRvcCwgeExlZnQsIHlCb3R0b21dLFxuICAgICAgICAgICAgICAgICAgICBbeExlZnQsIHlCb3R0b20sIHhSaWdodCwgeUJvdHRvbV0sXG4gICAgICAgICAgICAgICAgICAgIFt4UmlnaHQsIHlCb3R0b20sIHhSaWdodCwgeVRvcF0sXG4gICAgICAgICAgICAgICAgICAgIFt4UmlnaHQsIHlUb3AsIHhMZWZ0LCB5VG9wXVxuICAgICAgICAgICAgICAgIF0ubWFwKGFwcGx5VHJhbnNmb3JtMik7XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgbGluZSBpZiBpdCBlbmRzIGluc2lkZSB0aGUgYm94LiAgVXNlIHJheVxuICAgICAgICAgICAgLy8gY2FzdGluZyBmb3Igcm90YXRlZCBib3hlczogc2VlIHdoaWNoIGVkZ2VzIGludGVyc2VjdCBhXG4gICAgICAgICAgICAvLyBsaW5lIGZyb20gdGhlIGFycm93aGVhZCB0byBmYXIgYXdheSBhbmQgcmVkdWNlIHdpdGggeG9yXG4gICAgICAgICAgICAvLyB0byBnZXQgdGhlIHBhcml0eSBvZiB0aGUgbnVtYmVyIG9mIGludGVyc2VjdGlvbnMuXG4gICAgICAgICAgICBpZihlZGdlcy5yZWR1Y2UoZnVuY3Rpb24oYSwgeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhIF5cbiAgICAgICAgICAgICAgICAgICAgISFMaWIuc2VnbWVudHNJbnRlcnNlY3QoaGVhZFgsIGhlYWRZLCBoZWFkWCArIDFlNiwgaGVhZFkgKyAxZTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeFswXSwgeFsxXSwgeFsyXSwgeFszXSk7XG4gICAgICAgICAgICB9LCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBubyBsaW5lIG9yIGFycm93IC0gc28gcXVpdCBkcmF3QXJyb3cgbm93XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlZGdlcy5mb3JFYWNoKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcCA9IExpYi5zZWdtZW50c0ludGVyc2VjdCh0YWlsWCwgdGFpbFksIGhlYWRYLCBoZWFkWSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4WzBdLCB4WzFdLCB4WzJdLCB4WzNdKTtcbiAgICAgICAgICAgICAgICBpZihwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhaWxYID0gcC54O1xuICAgICAgICAgICAgICAgICAgICB0YWlsWSA9IHAueTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHN0cm9rZXdpZHRoID0gb3B0aW9ucy5hcnJvd3dpZHRoLFxuICAgICAgICAgICAgICAgIGFycm93Q29sb3IgPSBvcHRpb25zLmFycm93Y29sb3IsXG4gICAgICAgICAgICAgICAgYXJyb3dTaWRlID0gb3B0aW9ucy5hcnJvd3NpZGU7XG5cbiAgICAgICAgICAgIHZhciBhcnJvd0dyb3VwID0gYW5uR3JvdXAuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAuc3R5bGUoe29wYWNpdHk6IENvbG9yLm9wYWNpdHkoYXJyb3dDb2xvcil9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdhbm5vdGF0aW9uLWFycm93LWcnLCB0cnVlKTtcblxuICAgICAgICAgICAgdmFyIGFycm93ID0gYXJyb3dHcm91cC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJywgJ00nICsgdGFpbFggKyAnLCcgKyB0YWlsWSArICdMJyArIGhlYWRYICsgJywnICsgaGVhZFkpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBzdHJva2V3aWR0aCArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBDb2xvci5yZ2IoYXJyb3dDb2xvcikpO1xuXG4gICAgICAgICAgICBkcmF3QXJyb3dIZWFkKGFycm93LCBhcnJvd1NpZGUsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICAvLyB0aGUgYXJyb3cgZHJhZ2dlciBpcyBhIHNtYWxsIHNxdWFyZSByaWdodCBhdCB0aGUgaGVhZCwgdGhlbiBhIGxpbmUgdG8gdGhlIHRhaWwsXG4gICAgICAgICAgICAvLyBhbGwgZXhwYW5kZWQgYnkgYSBzdHJva2Ugd2lkdGggb2YgNnB4IHBsdXMgdGhlIGFycm93IGxpbmUgd2lkdGhcbiAgICAgICAgICAgIGlmKGVkaXRzLmFubm90YXRpb25Qb3NpdGlvbiAmJiBhcnJvdy5ub2RlKCkucGFyZW50Tm9kZSAmJiAhc3VicGxvdElkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFycm93RHJhZ0hlYWRYID0gaGVhZFg7XG4gICAgICAgICAgICAgICAgdmFyIGFycm93RHJhZ0hlYWRZID0gaGVhZFk7XG4gICAgICAgICAgICAgICAgaWYob3B0aW9ucy5zdGFuZG9mZikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXJyb3dMZW5ndGggPSBNYXRoLnNxcnQoTWF0aC5wb3coaGVhZFggLSB0YWlsWCwgMikgKyBNYXRoLnBvdyhoZWFkWSAtIHRhaWxZLCAyKSk7XG4gICAgICAgICAgICAgICAgICAgIGFycm93RHJhZ0hlYWRYICs9IG9wdGlvbnMuc3RhbmRvZmYgKiAodGFpbFggLSBoZWFkWCkgLyBhcnJvd0xlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgYXJyb3dEcmFnSGVhZFkgKz0gb3B0aW9ucy5zdGFuZG9mZiAqICh0YWlsWSAtIGhlYWRZKSAvIGFycm93TGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgYXJyb3dEcmFnID0gYXJyb3dHcm91cC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgnYW5ub3RhdGlvbi1hcnJvdycsIHRydWUpXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdhbm5kcmFnJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2N1cnNvci1tb3ZlJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZDogJ00zLDNILTNWLTNIM1pNMCwwTCcgKyAodGFpbFggLSBhcnJvd0RyYWdIZWFkWCkgKyAnLCcgKyAodGFpbFkgLSBhcnJvd0RyYWdIZWFkWSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIGFycm93RHJhZ0hlYWRYICsgJywnICsgYXJyb3dEcmFnSGVhZFkgKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCAoc3Ryb2tld2lkdGggKyA2KSArICdweCcpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgJ3JnYmEoMCwwLDAsMCknKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCAncmdiYSgwLDAsMCwwKScpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFubngwLCBhbm55MDtcblxuICAgICAgICAgICAgICAgIC8vIGRyYWdnZXIgZm9yIHRoZSBhcnJvdyAmIGhlYWQ6IHRyYW5zbGF0ZXMgdGhlIHdob2xlIHRoaW5nXG4gICAgICAgICAgICAgICAgLy8gKGhlYWQvdGFpbC90ZXh0KSBhbGwgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogYXJyb3dEcmFnLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKGFublRleHRHcm91cElubmVyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgYW5ueDAgPSBwb3MueDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFubnkwID0gcG9zLnk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih4YSAmJiB4YS5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlCYXNlKHhhLl9uYW1lICsgJy5hdXRvcmFuZ2UnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHlhICYmIHlhLmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUJhc2UoeWEuX25hbWUgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFubnh5MCA9IGFwcGx5VHJhbnNmb3JtKGFubngwLCBhbm55MCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeGNlbnRlciA9IGFubnh5MFswXSArIGR4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHljZW50ZXIgPSBhbm54eTBbMV0gKyBkeTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFublRleHRHcm91cElubmVyLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIHhjZW50ZXIsIHljZW50ZXIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4JywgeGEgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhhLnAycih4YS5yMnAob3B0aW9ucy54KSArIGR4KSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9wdGlvbnMueCArIChkeCAvIGdzLncpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5JywgeWEgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlhLnAycih5YS5yMnAob3B0aW9ucy55KSArIGR5KSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9wdGlvbnMueSAtIChkeSAvIGdzLmgpKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMuYXhyZWYgPT09IG9wdGlvbnMueHJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F4JywgeGEucDJyKHhhLnIycChvcHRpb25zLmF4KSArIGR4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMuYXlyZWYgPT09IG9wdGlvbnMueXJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F5JywgeWEucDJyKHlhLnIycChvcHRpb25zLmF5KSArIGR5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGFycm93R3JvdXAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgZHggKyAnLCcgKyBkeSArICcpJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbm5UZXh0R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAncm90YXRlKCcgKyB0ZXh0YW5nbGUgKyAnLCcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Y2VudGVyICsgJywnICsgeWNlbnRlciArICcpJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGRvbmVGbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBnZXRVcGRhdGVPYmooKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbm90ZXNCb3ggPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuanMtbm90ZXMtYm94LXBhbmVsJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihub3Rlc0JveCkgbm90ZXNCb3gucmVkcmF3KG5vdGVzQm94LnNlbGVjdGVkT2JqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmKG9wdGlvbnMuc2hvd2Fycm93KSBkcmF3QXJyb3coMCwgMCk7XG5cbiAgICAgICAgLy8gdXNlciBkcmFnZ2luZyB0aGUgYW5ub3RhdGlvbiAodGV4dCwgbm90IGFycm93KVxuICAgICAgICBpZihlZGl0VGV4dFBvc2l0aW9uKSB7XG4gICAgICAgICAgICB2YXIgYmFzZVRleHRUcmFuc2Zvcm07XG5cbiAgICAgICAgICAgIC8vIGRyYWdnZXIgZm9yIHRoZSB0ZXh0Ym94OiBpZiB0aGVyZSdzIGFuIGFycm93LCBqdXN0IGRyYWcgdGhlXG4gICAgICAgICAgICAvLyB0ZXh0Ym94IGFuZCB0YWlsLCBsZWF2ZSB0aGUgaGVhZCB1bnRvdWNoZWRcbiAgICAgICAgICAgIGRyYWdFbGVtZW50LmluaXQoe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IGFublRleHRHcm91cElubmVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBnZDogZ2QsXG4gICAgICAgICAgICAgICAgcHJlcEZuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgYmFzZVRleHRUcmFuc2Zvcm0gPSBhbm5UZXh0R3JvdXAuYXR0cigndHJhbnNmb3JtJyk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY3NyID0gJ3BvaW50ZXInO1xuICAgICAgICAgICAgICAgICAgICBpZihvcHRpb25zLnNob3dhcnJvdykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYob3B0aW9ucy5heHJlZiA9PT0gb3B0aW9ucy54cmVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgnYXgnLCB4YS5wMnIoeGEucjJwKG9wdGlvbnMuYXgpICsgZHgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgnYXgnLCBvcHRpb25zLmF4ICsgZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihvcHRpb25zLmF5cmVmID09PSBvcHRpb25zLnlyZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCdheScsIHlhLnAycih5YS5yMnAob3B0aW9ucy5heSkgKyBkeSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCdheScsIG9wdGlvbnMuYXkgKyBkeSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdBcnJvdyhkeCwgZHkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoIXN1YnBsb3RJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHhVcGRhdGUsIHlVcGRhdGU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih4YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhVcGRhdGUgPSB4YS5wMnIoeGEucjJwKG9wdGlvbnMueCkgKyBkeCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHdpZHRoRnJhY3Rpb24gPSBvcHRpb25zLl94c2l6ZSAvIGdzLncsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhMZWZ0ID0gb3B0aW9ucy54ICsgKG9wdGlvbnMuX3hzaGlmdCAtIG9wdGlvbnMueHNoaWZ0KSAvIGdzLncgLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGhGcmFjdGlvbiAvIDI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4VXBkYXRlID0gZHJhZ0VsZW1lbnQuYWxpZ24oeExlZnQgKyBkeCAvIGdzLncsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoRnJhY3Rpb24sIDAsIDEsIG9wdGlvbnMueGFuY2hvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHlhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeVVwZGF0ZSA9IHlhLnAycih5YS5yMnAob3B0aW9ucy55KSArIGR5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhlaWdodEZyYWN0aW9uID0gb3B0aW9ucy5feXNpemUgLyBncy5oLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5Qm90dG9tID0gb3B0aW9ucy55IC0gKG9wdGlvbnMuX3lzaGlmdCArIG9wdGlvbnMueXNoaWZ0KSAvIGdzLmggLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0RnJhY3Rpb24gLyAyO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeVVwZGF0ZSA9IGRyYWdFbGVtZW50LmFsaWduKHlCb3R0b20gLSBkeSAvIGdzLmgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodEZyYWN0aW9uLCAwLCAxLCBvcHRpb25zLnlhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneCcsIHhVcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneScsIHlVcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXhhIHx8ICF5YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNzciA9IGRyYWdFbGVtZW50LmdldEN1cnNvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGEgPyAwLjUgOiB4VXBkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5YSA/IDAuNSA6IHlVcGRhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMueGFuY2hvciwgb3B0aW9ucy55YW5jaG9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHJldHVybjtcblxuICAgICAgICAgICAgICAgICAgICBhbm5UZXh0R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIGR4ICsgJywnICsgZHkgKyAnKScgKyBiYXNlVGV4dFRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBzZXRDdXJzb3IoYW5uVGV4dEdyb3VwSW5uZXIsIGNzcik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkb25lRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBzZXRDdXJzb3IoYW5uVGV4dEdyb3VwSW5uZXIpO1xuICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBnZXRVcGRhdGVPYmooKSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub3Rlc0JveCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5qcy1ub3Rlcy1ib3gtcGFuZWwnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYobm90ZXNCb3gpIG5vdGVzQm94LnJlZHJhdyhub3Rlc0JveC5zZWxlY3RlZE9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihlZGl0cy5hbm5vdGF0aW9uVGV4dCkge1xuICAgICAgICBhbm5UZXh0LmNhbGwoc3ZnVGV4dFV0aWxzLm1ha2VFZGl0YWJsZSwge2RlbGVnYXRlOiBhbm5UZXh0R3JvdXBJbm5lciwgZ2Q6IGdkfSlcbiAgICAgICAgICAgIC5jYWxsKHRleHRMYXlvdXQpXG4gICAgICAgICAgICAub24oJ2VkaXQnLCBmdW5jdGlvbihfdGV4dCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMudGV4dCA9IF90ZXh0O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbCh0ZXh0TGF5b3V0KTtcblxuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3RleHQnLCBfdGV4dCk7XG5cbiAgICAgICAgICAgICAgICBpZih4YSAmJiB4YS5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZ5QmFzZSh4YS5fbmFtZSArICcuYXV0b3JhbmdlJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHlhICYmIHlhLmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBtb2RpZnlCYXNlKHlhLl9uYW1lICsgJy5hdXRvcmFuZ2UnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBnZXRVcGRhdGVPYmooKSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBhbm5UZXh0LmNhbGwodGV4dExheW91dCk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29sb3InKTtcblxudmFyIEFSUk9XUEFUSFMgPSByZXF1aXJlKCcuL2Fycm93X3BhdGhzJyk7XG5cbi8qKlxuICogQWRkIGFycm93aGVhZChzKSB0byBhIHBhdGggb3IgbGluZSBlbGVtZW50XG4gKlxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGVsMzogYSBkMy1zZWxlY3RlZCBsaW5lIG9yIHBhdGggZWxlbWVudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBlbmRzOiAnbm9uZScsICdzdGFydCcsICdlbmQnLCBvciAnc3RhcnQrZW5kJyBmb3Igd2hpY2ggZW5kcyBnZXQgYXJyb3doZWFkc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zOiBzdHlsZSBpbmZvcm1hdGlvbi4gTXVzdCBoYXZlIGFsbCB0aGUgZm9sbG93aW5nOlxuICogQHBhcmFtIHtudW1iZXJ9IG9wdGlvbnMuYXJyb3doZWFkOiBlbmQgaGVhZCBzdHlsZSAtIHNlZSAuL2Fycm93X3BhdGhzXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5zdGFydGFycm93aGVhZDogc3RhcnQgaGVhZCBzdHlsZSAtIHNlZSAuL2Fycm93X3BhdGhzXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5hcnJvd3NpemU6IHJlbGF0aXZlIHNpemUgb2YgdGhlIGVuZCBoZWFkIHZzIGxpbmUgd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnN0YXJ0YXJyb3dzaXplOiByZWxhdGl2ZSBzaXplIG9mIHRoZSBzdGFydCBoZWFkIHZzIGxpbmUgd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnN0YW5kb2ZmOiBkaXN0YW5jZSBpbiBweCB0byBtb3ZlIHRoZSBlbmQgYXJyb3cgcG9pbnQgZnJvbSBpdHMgdGFyZ2V0XG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5zdGFydHN0YW5kb2ZmOiBkaXN0YW5jZSBpbiBweCB0byBtb3ZlIHRoZSBzdGFydCBhcnJvdyBwb2ludCBmcm9tIGl0cyB0YXJnZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLmFycm93d2lkdGg6IHdpZHRoIG9mIHRoZSBhcnJvdyBsaW5lXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5hcnJvd2NvbG9yOiBjb2xvciBvZiB0aGUgYXJyb3cgbGluZSwgZm9yIHRoZSBoZWFkIHRvIG1hdGNoXG4gKiAgICAgTm90ZSB0aGF0IHRoZSBvcGFjaXR5IG9mIHRoaXMgY29sb3IgaXMgaWdub3JlZCwgYXMgaXQncyBhc3N1bWVkIHRoZSBjb250YWluZXJcbiAqICAgICBvZiBib3RoIHRoZSBsaW5lIGFuZCBoZWFkIGhhcyBvcGFjaXR5IGFwcGxpZWQgdG8gaXQgc28gdGhlcmUgaXNuJ3QgZ3JlYXRlciBvcGFjaXR5XG4gKiAgICAgd2hlcmUgdGhleSBvdmVybGFwLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXdBcnJvd0hlYWQoZWwzLCBlbmRzLCBvcHRpb25zKSB7XG4gICAgdmFyIGVsID0gZWwzLm5vZGUoKTtcbiAgICB2YXIgaGVhZFN0eWxlID0gQVJST1dQQVRIU1tvcHRpb25zLmFycm93aGVhZCB8fCAwXTtcbiAgICB2YXIgc3RhcnRIZWFkU3R5bGUgPSBBUlJPV1BBVEhTW29wdGlvbnMuc3RhcnRhcnJvd2hlYWQgfHwgMF07XG4gICAgdmFyIHNjYWxlID0gKG9wdGlvbnMuYXJyb3d3aWR0aCB8fCAxKSAqIChvcHRpb25zLmFycm93c2l6ZSB8fCAxKTtcbiAgICB2YXIgc3RhcnRTY2FsZSA9IChvcHRpb25zLmFycm93d2lkdGggfHwgMSkgKiAob3B0aW9ucy5zdGFydGFycm93c2l6ZSB8fCAxKTtcbiAgICB2YXIgZG9TdGFydCA9IGVuZHMuaW5kZXhPZignc3RhcnQnKSA+PSAwO1xuICAgIHZhciBkb0VuZCA9IGVuZHMuaW5kZXhPZignZW5kJykgPj0gMDtcbiAgICB2YXIgYmFja09mZiA9IGhlYWRTdHlsZS5iYWNrb2ZmICogc2NhbGUgKyBvcHRpb25zLnN0YW5kb2ZmO1xuICAgIHZhciBzdGFydEJhY2tPZmYgPSBzdGFydEhlYWRTdHlsZS5iYWNrb2ZmICogc3RhcnRTY2FsZSArIG9wdGlvbnMuc3RhcnRzdGFuZG9mZjtcblxuICAgIHZhciBzdGFydCwgZW5kLCBzdGFydFJvdCwgZW5kUm90O1xuXG4gICAgaWYoZWwubm9kZU5hbWUgPT09ICdsaW5lJykge1xuICAgICAgICBzdGFydCA9IHt4OiArZWwzLmF0dHIoJ3gxJyksIHk6ICtlbDMuYXR0cigneTEnKX07XG4gICAgICAgIGVuZCA9IHt4OiArZWwzLmF0dHIoJ3gyJyksIHk6ICtlbDMuYXR0cigneTInKX07XG5cbiAgICAgICAgdmFyIGR4ID0gc3RhcnQueCAtIGVuZC54O1xuICAgICAgICB2YXIgZHkgPSBzdGFydC55IC0gZW5kLnk7XG5cbiAgICAgICAgc3RhcnRSb3QgPSBNYXRoLmF0YW4yKGR5LCBkeCk7XG4gICAgICAgIGVuZFJvdCA9IHN0YXJ0Um90ICsgTWF0aC5QSTtcbiAgICAgICAgaWYoYmFja09mZiAmJiBzdGFydEJhY2tPZmYpIHtcbiAgICAgICAgICAgIGlmKGJhY2tPZmYgKyBzdGFydEJhY2tPZmYgPiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpKSB7XG4gICAgICAgICAgICAgICAgaGlkZUxpbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihiYWNrT2ZmKSB7XG4gICAgICAgICAgICBpZihiYWNrT2ZmICogYmFja09mZiA+IGR4ICogZHggKyBkeSAqIGR5KSB7XG4gICAgICAgICAgICAgICAgaGlkZUxpbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYmFja09mZlggPSBiYWNrT2ZmICogTWF0aC5jb3Moc3RhcnRSb3QpLFxuICAgICAgICAgICAgICAgIGJhY2tPZmZZID0gYmFja09mZiAqIE1hdGguc2luKHN0YXJ0Um90KTtcblxuICAgICAgICAgICAgZW5kLnggKz0gYmFja09mZlg7XG4gICAgICAgICAgICBlbmQueSArPSBiYWNrT2ZmWTtcbiAgICAgICAgICAgIGVsMy5hdHRyKHt4MjogZW5kLngsIHkyOiBlbmQueX0pO1xuXG4gICAgICAgIH1cblxuICAgICAgICBpZihzdGFydEJhY2tPZmYpIHtcbiAgICAgICAgICAgIGlmKHN0YXJ0QmFja09mZiAqIHN0YXJ0QmFja09mZiA+IGR4ICogZHggKyBkeSAqIGR5KSB7XG4gICAgICAgICAgICAgICAgaGlkZUxpbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgc3RhcnRCYWNrT2ZmWCA9IHN0YXJ0QmFja09mZiAqIE1hdGguY29zKHN0YXJ0Um90KSxcbiAgICAgICAgICAgICAgICBzdGFydGJhY2tPZmZZID0gc3RhcnRCYWNrT2ZmICogTWF0aC5zaW4oc3RhcnRSb3QpO1xuXG4gICAgICAgICAgICBzdGFydC54IC09IHN0YXJ0QmFja09mZlg7XG4gICAgICAgICAgICBzdGFydC55IC09IHN0YXJ0YmFja09mZlk7XG4gICAgICAgICAgICBlbDMuYXR0cih7eDE6IHN0YXJ0LngsIHkxOiBzdGFydC55fSk7XG5cbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmKGVsLm5vZGVOYW1lID09PSAncGF0aCcpIHtcbiAgICAgICAgdmFyIHBhdGhsZW4gPSBlbC5nZXRUb3RhbExlbmd0aCgpLFxuICAgICAgICAgICAgLy8gdXNpbmcgZGFzaCB0byBoaWRlIHRoZSBiYWNrT2ZmIHJlZ2lvbiBvZiB0aGUgcGF0aC5cbiAgICAgICAgICAgIC8vIGlmIHdlIGV2ZXIgYWxsb3cgZGFzaCBmb3IgdGhlIGFycm93IHdlJ2xsIGhhdmUgdG9cbiAgICAgICAgICAgIC8vIGRvIGJldHRlciB0aGFuIHRoaXMgaGFjay4uLiBtYXliZSBqdXN0IG1hbnVhbGx5XG4gICAgICAgICAgICAvLyBjb21iaW5lIHRoZSB0d29cbiAgICAgICAgICAgIGRhc2hBcnJheSA9ICcnO1xuXG4gICAgICAgIGlmKHBhdGhsZW4gPCBiYWNrT2ZmICsgc3RhcnRCYWNrT2ZmKSB7XG4gICAgICAgICAgICBoaWRlTGluZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cblxuICAgICAgICB2YXIgc3RhcnQwID0gZWwuZ2V0UG9pbnRBdExlbmd0aCgwKTtcbiAgICAgICAgdmFyIGRzdGFydCA9IGVsLmdldFBvaW50QXRMZW5ndGgoMC4xKTtcblxuICAgICAgICBzdGFydFJvdCA9IE1hdGguYXRhbjIoc3RhcnQwLnkgLSBkc3RhcnQueSwgc3RhcnQwLnggLSBkc3RhcnQueCk7XG4gICAgICAgIHN0YXJ0ID0gZWwuZ2V0UG9pbnRBdExlbmd0aChNYXRoLm1pbihzdGFydEJhY2tPZmYsIHBhdGhsZW4pKTtcblxuICAgICAgICBkYXNoQXJyYXkgPSAnMHB4LCcgKyBzdGFydEJhY2tPZmYgKyAncHgsJztcblxuICAgICAgICB2YXIgZW5kMCA9IGVsLmdldFBvaW50QXRMZW5ndGgocGF0aGxlbik7XG4gICAgICAgIHZhciBkZW5kID0gZWwuZ2V0UG9pbnRBdExlbmd0aChwYXRobGVuIC0gMC4xKTtcblxuICAgICAgICBlbmRSb3QgPSBNYXRoLmF0YW4yKGVuZDAueSAtIGRlbmQueSwgZW5kMC54IC0gZGVuZC54KTtcbiAgICAgICAgZW5kID0gZWwuZ2V0UG9pbnRBdExlbmd0aChNYXRoLm1heCgwLCBwYXRobGVuIC0gYmFja09mZikpO1xuXG4gICAgICAgIHZhciBzaG9ydGVuaW5nID0gZGFzaEFycmF5ID8gc3RhcnRCYWNrT2ZmICsgYmFja09mZiA6IGJhY2tPZmY7XG4gICAgICAgIGRhc2hBcnJheSArPSAocGF0aGxlbiAtIHNob3J0ZW5pbmcpICsgJ3B4LCcgKyBwYXRobGVuICsgJ3B4JztcblxuICAgICAgICBlbDMuc3R5bGUoJ3N0cm9rZS1kYXNoYXJyYXknLCBkYXNoQXJyYXkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhpZGVMaW5lKCkgeyBlbDMuc3R5bGUoJ3N0cm9rZS1kYXNoYXJyYXknLCAnMHB4LDEwMHB4Jyk7IH1cblxuICAgIGZ1bmN0aW9uIGRyYXdoZWFkKGFycm93SGVhZFN0eWxlLCBwLCByb3QsIGFycm93U2NhbGUpIHtcbiAgICAgICAgaWYoIWFycm93SGVhZFN0eWxlLnBhdGgpIHJldHVybjtcbiAgICAgICAgaWYoYXJyb3dIZWFkU3R5bGUubm9Sb3RhdGUpIHJvdCA9IDA7XG5cbiAgICAgICAgZDMuc2VsZWN0KGVsLnBhcmVudE5vZGUpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgJ2NsYXNzJzogZWwzLmF0dHIoJ2NsYXNzJyksXG4gICAgICAgICAgICAgICAgZDogYXJyb3dIZWFkU3R5bGUucGF0aCxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06XG4gICAgICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIHAueCArICcsJyArIHAueSArICcpJyArXG4gICAgICAgICAgICAgICAgICAgIChyb3QgPyAncm90YXRlKCcgKyAocm90ICogMTgwIC8gTWF0aC5QSSkgKyAnKScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAnc2NhbGUoJyArIGFycm93U2NhbGUgKyAnKSdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgIGZpbGw6IENvbG9yLnJnYihvcHRpb25zLmFycm93Y29sb3IpLFxuICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiAwXG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihkb1N0YXJ0KSBkcmF3aGVhZChzdGFydEhlYWRTdHlsZSwgc3RhcnQsIHN0YXJ0Um90LCBzdGFydFNjYWxlKTtcbiAgICBpZihkb0VuZCkgZHJhd2hlYWQoaGVhZFN0eWxlLCBlbmQsIGVuZFJvdCwgc2NhbGUpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZHJhd01vZHVsZSA9IHJlcXVpcmUoJy4vZHJhdycpO1xudmFyIGNsaWNrTW9kdWxlID0gcmVxdWlyZSgnLi9jbGljaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnYW5ub3RhdGlvbnMnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMnKSgnYW5ub3RhdGlvbnMnKSxcblxuICAgIGNhbGNBdXRvcmFuZ2U6IHJlcXVpcmUoJy4vY2FsY19hdXRvcmFuZ2UnKSxcbiAgICBkcmF3OiBkcmF3TW9kdWxlLmRyYXcsXG4gICAgZHJhd09uZTogZHJhd01vZHVsZS5kcmF3T25lLFxuICAgIGRyYXdSYXc6IGRyYXdNb2R1bGUuZHJhd1JhdyxcblxuICAgIGhhc0NsaWNrVG9TaG93OiBjbGlja01vZHVsZS5oYXNDbGlja1RvU2hvdyxcbiAgICBvbkNsaWNrOiBjbGlja01vZHVsZS5vbkNsaWNrLFxuXG4gICAgY29udmVydENvb3JkczogcmVxdWlyZSgnLi9jb252ZXJ0X2Nvb3JkcycpXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBhbm5BdHRzID0gcmVxdWlyZSgnLi4vYW5ub3RhdGlvbnMvYXR0cmlidXRlcycpO1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHRlbXBsYXRlZEFycmF5KCdhbm5vdGF0aW9uJywge1xuICAgIHZpc2libGU6IGFubkF0dHMudmlzaWJsZSxcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBheDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeGFuY2hvcjogYW5uQXR0cy54YW5jaG9yLFxuICAgIHhzaGlmdDogYW5uQXR0cy54c2hpZnQsXG4gICAgeWFuY2hvcjogYW5uQXR0cy55YW5jaG9yLFxuICAgIHlzaGlmdDogYW5uQXR0cy55c2hpZnQsXG5cbiAgICB0ZXh0OiBhbm5BdHRzLnRleHQsXG4gICAgdGV4dGFuZ2xlOiBhbm5BdHRzLnRleHRhbmdsZSxcbiAgICBmb250OiBhbm5BdHRzLmZvbnQsXG4gICAgd2lkdGg6IGFubkF0dHMud2lkdGgsXG4gICAgaGVpZ2h0OiBhbm5BdHRzLmhlaWdodCxcbiAgICBvcGFjaXR5OiBhbm5BdHRzLm9wYWNpdHksXG4gICAgYWxpZ246IGFubkF0dHMuYWxpZ24sXG4gICAgdmFsaWduOiBhbm5BdHRzLnZhbGlnbixcbiAgICBiZ2NvbG9yOiBhbm5BdHRzLmJnY29sb3IsXG4gICAgYm9yZGVyY29sb3I6IGFubkF0dHMuYm9yZGVyY29sb3IsXG4gICAgYm9yZGVycGFkOiBhbm5BdHRzLmJvcmRlcnBhZCxcbiAgICBib3JkZXJ3aWR0aDogYW5uQXR0cy5ib3JkZXJ3aWR0aCxcbiAgICBzaG93YXJyb3c6IGFubkF0dHMuc2hvd2Fycm93LFxuICAgIGFycm93Y29sb3I6IGFubkF0dHMuYXJyb3djb2xvcixcbiAgICBhcnJvd2hlYWQ6IGFubkF0dHMuYXJyb3doZWFkLFxuICAgIHN0YXJ0YXJyb3doZWFkOiBhbm5BdHRzLnN0YXJ0YXJyb3doZWFkLFxuICAgIGFycm93c2lkZTogYW5uQXR0cy5hcnJvd3NpZGUsXG4gICAgYXJyb3dzaXplOiBhbm5BdHRzLmFycm93c2l6ZSxcbiAgICBzdGFydGFycm93c2l6ZTogYW5uQXR0cy5zdGFydGFycm93c2l6ZSxcbiAgICBhcnJvd3dpZHRoOiBhbm5BdHRzLmFycm93d2lkdGgsXG4gICAgc3RhbmRvZmY6IGFubkF0dHMuc3RhbmRvZmYsXG4gICAgc3RhcnRzdGFuZG9mZjogYW5uQXR0cy5zdGFydHN0YW5kb2ZmLFxuICAgIGhvdmVydGV4dDogYW5uQXR0cy5ob3ZlcnRleHQsXG4gICAgaG92ZXJsYWJlbDogYW5uQXR0cy5ob3ZlcmxhYmVsLFxuICAgIGNhcHR1cmVldmVudHM6IGFubkF0dHMuY2FwdHVyZWV2ZW50cyxcblxuICAgIC8vIG1heWJlcyBsYXRlcj9cbiAgICAvLyBjbGlja3Rvc2hvdzogYW5uQXR0cy5jbGlja3Rvc2hvdyxcbiAgICAvLyB4Y2xpY2s6IGFubkF0dHMueGNsaWNrLFxuICAgIC8vIHljbGljazogYW5uQXR0cy55Y2xpY2ssXG5cbiAgICAvLyBub3QgbmVlZGVkIVxuICAgIC8vIGF4cmVmOiAncGl4ZWwnXG4gICAgLy8gYXlyZWY6ICdwaXhlbCdcbiAgICAvLyB4cmVmOiAneCdcbiAgICAvLyB5cmVmOiAneVxuICAgIC8vIHpyZWY6ICd6J1xufSksICdjYWxjJywgJ2Zyb20tcm9vdCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChzY2VuZSkge1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGFubnMgPSBmdWxsU2NlbmVMYXlvdXQuYW5ub3RhdGlvbnM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYW5ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtb2NrQW5uQXhlcyhhbm5zW2ldLCBzY2VuZSk7XG4gICAgfVxuXG4gICAgc2NlbmUuZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJy5hbm5vdGF0aW9uLScgKyBzY2VuZS5pZClcbiAgICAgICAgLnJlbW92ZSgpO1xufTtcblxuZnVuY3Rpb24gbW9ja0FubkF4ZXMoYW5uLCBzY2VuZSkge1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRvbWFpbiA9IGZ1bGxTY2VuZUxheW91dC5kb21haW47XG4gICAgdmFyIHNpemUgPSBzY2VuZS5mdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgdmFyIGJhc2UgPSB7XG4gICAgICAgIC8vIHRoaXMgZ2V0cyBmaWxsIGluIG9uIHJlbmRlclxuICAgICAgICBwZGF0YTogbnVsbCxcblxuICAgICAgICAvLyB0byBnZXQgc2V0Q29udmVydCB0byBub3QgZXhlY3V0ZSBjbGVhbmx5XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuXG4gICAgICAgIC8vIGRvbid0IHRyeSB0byB1cGRhdGUgdGhlbSBvbiBgZWRpdGFibGU6IHRydWVgXG4gICAgICAgIGF1dG9yYW5nZTogZmFsc2UsXG5cbiAgICAgICAgLy8gc2V0IGluZmluaXRlIHJhbmdlIHNvIHRoYXQgYW5ub3RhdGlvbiBkcmF3IHJvdXRpbmVcbiAgICAgICAgLy8gZG9lcyBub3QgdHJ5IHRvIHJlbW92ZSAnb3V0c2lkZS1yYW5nZScgYW5ub3RhdGlvbnMsXG4gICAgICAgIC8vIHRoaXMgY2FzZSBpcyBoYW5kbGVkIGluIHRoZSByZW5kZXIgbG9vcFxuICAgICAgICByYW5nZTogWy1JbmZpbml0eSwgSW5maW5pdHldXG4gICAgfTtcblxuICAgIGFubi5feGEgPSB7fTtcbiAgICBMaWIuZXh0ZW5kRmxhdChhbm4uX3hhLCBiYXNlKTtcbiAgICBBeGVzLnNldENvbnZlcnQoYW5uLl94YSk7XG4gICAgYW5uLl94YS5fb2Zmc2V0ID0gc2l6ZS5sICsgZG9tYWluLnhbMF0gKiBzaXplLnc7XG4gICAgYW5uLl94YS5sMnAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDAuNSAqICgxICsgYW5uLl9wZGF0YVswXSAvIGFubi5fcGRhdGFbM10pICogc2l6ZS53ICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pO1xuICAgIH07XG5cbiAgICBhbm4uX3lhID0ge307XG4gICAgTGliLmV4dGVuZEZsYXQoYW5uLl95YSwgYmFzZSk7XG4gICAgQXhlcy5zZXRDb252ZXJ0KGFubi5feWEpO1xuICAgIGFubi5feWEuX29mZnNldCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oO1xuICAgIGFubi5feWEubDJwID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAwLjUgKiAoMSAtIGFubi5fcGRhdGFbMV0gLyBhbm4uX3BkYXRhWzNdKSAqIHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbiAgICB9O1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUFubm90YXRpb25Db21tb25EZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2Fubm90YXRpb25zL2NvbW1vbl9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVEZWZhdWx0cyhzY2VuZUxheW91dEluLCBzY2VuZUxheW91dE91dCwgb3B0cykge1xuICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoc2NlbmVMYXlvdXRJbiwgc2NlbmVMYXlvdXRPdXQsIHtcbiAgICAgICAgbmFtZTogJ2Fubm90YXRpb25zJyxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBoYW5kbGVBbm5vdGF0aW9uRGVmYXVsdHMsXG4gICAgICAgIGZ1bGxMYXlvdXQ6IG9wdHMuZnVsbExheW91dFxuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlQW5ub3RhdGlvbkRlZmF1bHRzKGFubkluLCBhbm5PdXQsIHNjZW5lTGF5b3V0LCBvcHRzKSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYW5uSW4sIGFubk91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlUG9zaXRpb24oYXhMZXR0ZXIpIHtcbiAgICAgICAgdmFyIGF4TmFtZSA9IGF4TGV0dGVyICsgJ2F4aXMnO1xuXG4gICAgICAgIC8vIG1vY2sgaW4gc3VjaCB3YXkgdGhhdCBnZXRGcm9tSWQgZ3JhYnMgY29ycmVjdCAzRCBheGlzXG4gICAgICAgIHZhciBnZE1vY2sgPSB7IF9mdWxsTGF5b3V0OiB7fSB9O1xuICAgICAgICBnZE1vY2suX2Z1bGxMYXlvdXRbYXhOYW1lXSA9IHNjZW5lTGF5b3V0W2F4TmFtZV07XG5cbiAgICAgICAgcmV0dXJuIEF4ZXMuY29lcmNlUG9zaXRpb24oYW5uT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhMZXR0ZXIsIGF4TGV0dGVyLCAwLjUpO1xuICAgIH1cblxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICBpZighdmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgaGFuZGxlQW5ub3RhdGlvbkNvbW1vbkRlZmF1bHRzKGFubkluLCBhbm5PdXQsIG9wdHMuZnVsbExheW91dCwgY29lcmNlKTtcblxuICAgIGNvZXJjZVBvc2l0aW9uKCd4Jyk7XG4gICAgY29lcmNlUG9zaXRpb24oJ3knKTtcbiAgICBjb2VyY2VQb3NpdGlvbigneicpO1xuXG4gICAgLy8gaWYgeW91IGhhdmUgb25lIGNvb3JkaW5hdGUgeW91IHNob3VsZCBhbGwgdGhyZWVcbiAgICBMaWIubm9uZU9yQWxsKGFubkluLCBhbm5PdXQsIFsneCcsICd5JywgJ3onXSk7XG5cbiAgICAvLyBoYXJkLXNldCBoZXJlIGZvciBjb21wbGV0ZW5lc3NcbiAgICBhbm5PdXQueHJlZiA9ICd4JztcbiAgICBhbm5PdXQueXJlZiA9ICd5JztcbiAgICBhbm5PdXQuenJlZiA9ICd6JztcblxuICAgIGNvZXJjZSgneGFuY2hvcicpO1xuICAgIGNvZXJjZSgneWFuY2hvcicpO1xuICAgIGNvZXJjZSgneHNoaWZ0Jyk7XG4gICAgY29lcmNlKCd5c2hpZnQnKTtcblxuICAgIGlmKGFubk91dC5zaG93YXJyb3cpIHtcbiAgICAgICAgYW5uT3V0LmF4cmVmID0gJ3BpeGVsJztcbiAgICAgICAgYW5uT3V0LmF5cmVmID0gJ3BpeGVsJztcblxuICAgICAgICAvLyBUT0RPIG1heWJlIGRlZmF1bHQgdmFsdWVzIHNob3VsZCBiZSBiaWdnZXIgdGhhbiB0aGUgMkQgY2FzZT9cbiAgICAgICAgY29lcmNlKCdheCcsIC0xMCk7XG4gICAgICAgIGNvZXJjZSgnYXknLCAtMzApO1xuXG4gICAgICAgIC8vIGlmIHlvdSBoYXZlIG9uZSBwYXJ0IG9mIGFycm93IGxlbmd0aCB5b3Ugc2hvdWxkIGhhdmUgYm90aFxuICAgICAgICBMaWIubm9uZU9yQWxsKGFubkluLCBhbm5PdXQsIFsnYXgnLCAnYXknXSk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZHJhd1JhdyA9IHJlcXVpcmUoJy4uL2Fubm90YXRpb25zL2RyYXcnKS5kcmF3UmF3O1xudmFyIHByb2plY3QgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nbDNkL3Byb2plY3QnKTtcbnZhciBheExldHRlcnMgPSBbJ3gnLCAneScsICd6J107XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhdyhzY2VuZSkge1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRhdGFTY2FsZSA9IHNjZW5lLmRhdGFTY2FsZTtcbiAgICB2YXIgYW5ucyA9IGZ1bGxTY2VuZUxheW91dC5hbm5vdGF0aW9ucztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbm5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhbm4gPSBhbm5zW2ldO1xuICAgICAgICB2YXIgYW5ub3RhdGlvbklzT2Zmc2NyZWVuID0gZmFsc2U7XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhMZXR0ZXJzW2pdO1xuICAgICAgICAgICAgdmFyIHBvcyA9IGFubltheExldHRlcl07XG4gICAgICAgICAgICB2YXIgYXggPSBmdWxsU2NlbmVMYXlvdXRbYXhMZXR0ZXIgKyAnYXhpcyddO1xuICAgICAgICAgICAgdmFyIHBvc0ZyYWN0aW9uID0gYXgucjJmcmFjdGlvbihwb3MpO1xuXG4gICAgICAgICAgICBpZihwb3NGcmFjdGlvbiA8IDAgfHwgcG9zRnJhY3Rpb24gPiAxKSB7XG4gICAgICAgICAgICAgICAgYW5ub3RhdGlvbklzT2Zmc2NyZWVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGFubm90YXRpb25Jc09mZnNjcmVlbikge1xuICAgICAgICAgICAgc2NlbmUuZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgICAgICAgICAgLnNlbGVjdCgnLmFubm90YXRpb24tJyArIHNjZW5lLmlkICsgJ1tkYXRhLWluZGV4PVwiJyArIGkgKyAnXCJdJylcbiAgICAgICAgICAgICAgICAucmVtb3ZlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbm4uX3BkYXRhID0gcHJvamVjdChzY2VuZS5nbHBsb3QuY2FtZXJhUGFyYW1zLCBbXG4gICAgICAgICAgICAgICAgZnVsbFNjZW5lTGF5b3V0LnhheGlzLnIybChhbm4ueCkgKiBkYXRhU2NhbGVbMF0sXG4gICAgICAgICAgICAgICAgZnVsbFNjZW5lTGF5b3V0LnlheGlzLnIybChhbm4ueSkgKiBkYXRhU2NhbGVbMV0sXG4gICAgICAgICAgICAgICAgZnVsbFNjZW5lTGF5b3V0LnpheGlzLnIybChhbm4ueikgKiBkYXRhU2NhbGVbMl1cbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICBkcmF3UmF3KHNjZW5lLmdyYXBoRGl2LCBhbm4sIGksIHNjZW5lLmlkLCBhbm4uX3hhLCBhbm4uX3lhKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdhbm5vdGF0aW9uczNkJyxcblxuICAgIHNjaGVtYToge1xuICAgICAgICBzdWJwbG90czoge1xuICAgICAgICAgICAgc2NlbmU6IHthbm5vdGF0aW9uczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyl9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgaGFuZGxlRGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IGluY2x1ZGVHTDNELFxuXG4gICAgY29udmVydDogcmVxdWlyZSgnLi9jb252ZXJ0JyksXG4gICAgZHJhdzogcmVxdWlyZSgnLi9kcmF3Jylcbn07XG5cbmZ1bmN0aW9uIGluY2x1ZGVHTDNEKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgR0wzRCA9IFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnkuZ2wzZDtcbiAgICBpZighR0wzRCkgcmV0dXJuO1xuXG4gICAgdmFyIGF0dHJSZWdleCA9IEdMM0QuYXR0clJlZ2V4O1xuXG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhsYXlvdXRJbik7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGsgPSBrZXlzW2ldO1xuICAgICAgICBpZihhdHRyUmVnZXgudGVzdChrKSAmJiAobGF5b3V0SW5ba10uYW5ub3RhdGlvbnMgfHwgW10pLmxlbmd0aCkge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUobGF5b3V0T3V0Ll9iYXNlUGxvdE1vZHVsZXMsIEdMM0QpO1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUobGF5b3V0T3V0Ll9zdWJwbG90cy5nbDNkLCBrKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gYSB0cmltbWVkIGRvd24gdmVyc2lvbiBvZjpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzL2Jsb2IvbWFzdGVyL2Rpc3QvaW5kZXguanNcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9tYWluJyk7XG5cbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L3BsdXMnKTtcblxucmVxdWlyZSgnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2NoaW5lc2UnKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9jb3B0aWMnKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9kaXNjd29ybGQnKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9ldGhpb3BpYW4nKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9oZWJyZXcnKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9pc2xhbWljJyk7XG5yZXF1aXJlKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvanVsaWFuJyk7XG5yZXF1aXJlKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbWF5YW4nKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9uYW5ha3NoYWhpJyk7XG5yZXF1aXJlKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbmVwYWxpJyk7XG5yZXF1aXJlKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvcGVyc2lhbicpO1xucmVxdWlyZSgnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3RhaXdhbicpO1xucmVxdWlyZSgnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3RoYWknKTtcbnJlcXVpcmUoJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy91bW1hbHF1cmEnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNhbGVuZGFycyA9IHJlcXVpcmUoJy4vY2FsZW5kYXJzJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJyk7XG5cbnZhciBFUE9DSEpEID0gY29uc3RhbnRzLkVQT0NISkQ7XG52YXIgT05FREFZID0gY29uc3RhbnRzLk9ORURBWTtcblxudmFyIGF0dHJpYnV0ZXMgPSB7XG4gICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgIHZhbHVlczogT2JqZWN0LmtleXMoY2FsZW5kYXJzLmNhbGVuZGFycyksXG4gICAgXG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBkZmx0OiAnZ3JlZ29yaWFuJ1xufTtcblxudmFyIGhhbmRsZURlZmF1bHRzID0gZnVuY3Rpb24oY29udEluLCBjb250T3V0LCBhdHRyLCBkZmx0KSB7XG4gICAgdmFyIGF0dHJzID0ge307XG4gICAgYXR0cnNbYXR0cl0gPSBhdHRyaWJ1dGVzO1xuXG4gICAgcmV0dXJuIExpYi5jb2VyY2UoY29udEluLCBjb250T3V0LCBhdHRycywgYXR0ciwgZGZsdCk7XG59O1xuXG52YXIgaGFuZGxlVHJhY2VEZWZhdWx0cyA9IGZ1bmN0aW9uKHRyYWNlSW4sIHRyYWNlT3V0LCBjb29yZHMsIGxheW91dCkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGFuZGxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvb3Jkc1tpXSArICdjYWxlbmRhcicsIGxheW91dC5jYWxlbmRhcik7XG4gICAgfVxufTtcblxuLy8gZWFjaCBjYWxlbmRhciBuZWVkcyBpdHMgb3duIGRlZmF1bHQgY2Fub25pY2FsIHRpY2suIEkgd291bGQgbG92ZSB0byB1c2Vcbi8vIDIwMDAtMDEtMDEgKG9yIGV2ZW4gMDAwMC0wMS0wMSkgZm9yIHRoZW0gYWxsIGJ1dCB0aGV5IGRvbid0IG5lY2Vzc2FyaWx5XG4vLyBhbGwgc3VwcG9ydCBlaXRoZXIgb2YgdGhvc2UgZGF0ZXMuIEluc3RlYWQgSSdsbCB1c2UgdGhlIG1vc3Qgc2lnbmlmaWNhbnRcbi8vIG51bWJlciB0aGV5ICpkbyogc3VwcG9ydCwgYmlhc2VkIHRvd2FyZCB0aGUgcHJlc2VudCBkYXkuXG52YXIgQ0FOT05JQ0FMX1RJQ0sgPSB7XG4gICAgY2hpbmVzZTogJzIwMDAtMDEtMDEnLFxuICAgIGNvcHRpYzogJzIwMDAtMDEtMDEnLFxuICAgIGRpc2N3b3JsZDogJzIwMDAtMDEtMDEnLFxuICAgIGV0aGlvcGlhbjogJzIwMDAtMDEtMDEnLFxuICAgIGhlYnJldzogJzUwMDAtMDEtMDEnLFxuICAgIGlzbGFtaWM6ICcxMDAwLTAxLTAxJyxcbiAgICBqdWxpYW46ICcyMDAwLTAxLTAxJyxcbiAgICBtYXlhbjogJzUwMDAtMDEtMDEnLFxuICAgIG5hbmFrc2hhaGk6ICcxMDAwLTAxLTAxJyxcbiAgICBuZXBhbGk6ICcyMDAwLTAxLTAxJyxcbiAgICBwZXJzaWFuOiAnMTAwMC0wMS0wMScsXG4gICAgamFsYWxpOiAnMTAwMC0wMS0wMScsXG4gICAgdGFpd2FuOiAnMTAwMC0wMS0wMScsXG4gICAgdGhhaTogJzIwMDAtMDEtMDEnLFxuICAgIHVtbWFscXVyYTogJzE0MDAtMDEtMDEnXG59O1xuXG4vLyBTdGFydCBvbiBhIFN1bmRheSAtIGZvciB3ZWVrIHRpY2tzXG4vLyBEaXNjd29ybGQgYW5kIE1heWFuIGNhbGVuZGFycyBkb24ndCBoYXZlIDctZGF5IHdlZWtzIGJ1dCB3ZSdyZSBnb2luZyB0byBnaXZlIHRoZW1cbi8vIDctZGF5IHdlZWsgdGlja3Mgc28gc3RhcnQgb24gb3VyIFN1bmRheXMuXG4vLyBJZiBhbnlvbmUgcmVhbGx5IGNhcmVzIHdlIGNhbiBjdXN0b21pemUgdGhlIGF1dG8gdGljayBzcGFjaW5ncyBmb3IgdGhlc2UgY2FsZW5kYXJzLlxudmFyIENBTk9OSUNBTF9TVU5EQVkgPSB7XG4gICAgY2hpbmVzZTogJzIwMDAtMDEtMDInLFxuICAgIGNvcHRpYzogJzIwMDAtMDEtMDMnLFxuICAgIGRpc2N3b3JsZDogJzIwMDAtMDEtMDMnLFxuICAgIGV0aGlvcGlhbjogJzIwMDAtMDEtMDUnLFxuICAgIGhlYnJldzogJzUwMDAtMDEtMDEnLFxuICAgIGlzbGFtaWM6ICcxMDAwLTAxLTAyJyxcbiAgICBqdWxpYW46ICcyMDAwLTAxLTAzJyxcbiAgICBtYXlhbjogJzUwMDAtMDEtMDEnLFxuICAgIG5hbmFrc2hhaGk6ICcxMDAwLTAxLTA1JyxcbiAgICBuZXBhbGk6ICcyMDAwLTAxLTA1JyxcbiAgICBwZXJzaWFuOiAnMTAwMC0wMS0wMScsXG4gICAgamFsYWxpOiAnMTAwMC0wMS0wMScsXG4gICAgdGFpd2FuOiAnMTAwMC0wMS0wNCcsXG4gICAgdGhhaTogJzIwMDAtMDEtMDQnLFxuICAgIHVtbWFscXVyYTogJzE0MDAtMDEtMDYnXG59O1xuXG52YXIgREZMVFJBTkdFID0ge1xuICAgIGNoaW5lc2U6IFsnMjAwMC0wMS0wMScsICcyMDAxLTAxLTAxJ10sXG4gICAgY29wdGljOiBbJzE3MDAtMDEtMDEnLCAnMTcwMS0wMS0wMSddLFxuICAgIGRpc2N3b3JsZDogWycxODAwLTAxLTAxJywgJzE4MDEtMDEtMDEnXSxcbiAgICBldGhpb3BpYW46IFsnMjAwMC0wMS0wMScsICcyMDAxLTAxLTAxJ10sXG4gICAgaGVicmV3OiBbJzU3MDAtMDEtMDEnLCAnNTcwMS0wMS0wMSddLFxuICAgIGlzbGFtaWM6IFsnMTQwMC0wMS0wMScsICcxNDAxLTAxLTAxJ10sXG4gICAganVsaWFuOiBbJzIwMDAtMDEtMDEnLCAnMjAwMS0wMS0wMSddLFxuICAgIG1heWFuOiBbJzUyMDAtMDEtMDEnLCAnNTIwMS0wMS0wMSddLFxuICAgIG5hbmFrc2hhaGk6IFsnMDUwMC0wMS0wMScsICcwNTAxLTAxLTAxJ10sXG4gICAgbmVwYWxpOiBbJzIwMDAtMDEtMDEnLCAnMjAwMS0wMS0wMSddLFxuICAgIHBlcnNpYW46IFsnMTQwMC0wMS0wMScsICcxNDAxLTAxLTAxJ10sXG4gICAgamFsYWxpOiBbJzE0MDAtMDEtMDEnLCAnMTQwMS0wMS0wMSddLFxuICAgIHRhaXdhbjogWycwMTAwLTAxLTAxJywgJzAxMDEtMDEtMDEnXSxcbiAgICB0aGFpOiBbJzI1MDAtMDEtMDEnLCAnMjUwMS0wMS0wMSddLFxuICAgIHVtbWFscXVyYTogWycxNDAwLTAxLTAxJywgJzE0MDEtMDEtMDEnXVxufTtcblxuLypcbiAqIGNvbnZlcnQgZDMgdGVtcGxhdGVzIHRvIHdvcmxkLWNhbGVuZGFycyB0ZW1wbGF0ZXMsIHNvIG91ciB1c2VycyBvbmx5IG5lZWRcbiAqIHRvIGtub3cgZDMncyBzcGVjaWZpZXJzLiBNYXAgc3BhY2UgcGFkZGluZyB0byBubyBwYWRkaW5nLCBhbmQgdW5rbm93biBmaWVsZHNcbiAqIHRvIGFuIHVnbHkgcGxhY2Vob2xkZXJcbiAqL1xudmFyIFVOS05PV04gPSAnIyMnO1xudmFyIGQzVG9Xb3JsZENhbGVuZGFycyA9IHtcbiAgICAnZCc6IHsnMCc6ICdkZCcsICctJzogJ2QnfSwgLy8gMi1kaWdpdCBvciB1bnBhZGRlZCBkYXkgb2YgbW9udGhcbiAgICAnZSc6IHsnMCc6ICdkJywgJy0nOiAnZCd9LCAvLyBhbHRlcm5hdGUsIGFsd2F5cyB1bnBhZGRlZCBkYXkgb2YgbW9udGhcbiAgICAnYSc6IHsnMCc6ICdEJywgJy0nOiAnRCd9LCAvLyBzaG9ydCB3ZWVrZGF5IG5hbWVcbiAgICAnQSc6IHsnMCc6ICdERCcsICctJzogJ0REJ30sIC8vIGZ1bGwgd2Vla2RheSBuYW1lXG4gICAgJ2onOiB7JzAnOiAnb28nLCAnLSc6ICdvJ30sIC8vIDMtZGlnaXQgb3IgdW5wYWRkZWQgZGF5IG9mIHRoZSB5ZWFyXG4gICAgJ1cnOiB7JzAnOiAnd3cnLCAnLSc6ICd3J30sIC8vIDItZGlnaXQgb3IgdW5wYWRkZWQgd2VlayBvZiB0aGUgeWVhciAoTW9uZGF5IGZpcnN0KVxuICAgICdtJzogeycwJzogJ21tJywgJy0nOiAnbSd9LCAvLyAyLWRpZ2l0IG9yIHVucGFkZGVkIG1vbnRoIG51bWJlclxuICAgICdiJzogeycwJzogJ00nLCAnLSc6ICdNJ30sIC8vIHNob3J0IG1vbnRoIG5hbWVcbiAgICAnQic6IHsnMCc6ICdNTScsICctJzogJ01NJ30sIC8vIGZ1bGwgbW9udGggbmFtZVxuICAgICd5JzogeycwJzogJ3l5JywgJy0nOiAneXknfSwgLy8gMi1kaWdpdCB5ZWFyIChtYXAgdW5wYWRkZWQgdG8gemVyby1wYWRkZWQpXG4gICAgJ1knOiB7JzAnOiAneXl5eScsICctJzogJ3l5eXknfSwgLy8gNC1kaWdpdCB5ZWFyIChtYXAgdW5wYWRkZWQgdG8gemVyby1wYWRkZWQpXG4gICAgJ1UnOiBVTktOT1dOLCAvLyBTdW5kYXktZmlyc3Qgd2VlayBvZiB0aGUgeWVhclxuICAgICd3JzogVU5LTk9XTiwgLy8gZGF5IG9mIHRoZSB3ZWVrIFswKHN1bmRheSksNl1cbiAgICAvLyBjb21iaW5lZCBmb3JtYXQsIHdlIHJlcGxhY2UgdGhlIGRhdGUgcGFydCB3aXRoIHRoZSB3b3JsZC1jYWxlbmRhciB2ZXJzaW9uXG4gICAgLy8gYW5kIHRoZSAlWCBzdGF5cyB0aGVyZSBmb3IgZDMgdG8gaGFuZGxlIHdpdGggdGltZSBwYXJ0c1xuICAgICdjJzogeycwJzogJ0QgTSBkICVYIHl5eXknLCAnLSc6ICdEIE0gZCAlWCB5eXl5J30sXG4gICAgJ3gnOiB7JzAnOiAnbW0vZGQveXl5eScsICctJzogJ21tL2RkL3l5eXknfVxufTtcblxuZnVuY3Rpb24gd29ybGRDYWxGbXQoZm10LCB4LCBjYWxlbmRhcikge1xuICAgIHZhciBkYXRlSkQgPSBNYXRoLmZsb29yKCh4ICsgMC4wNSkgLyBPTkVEQVkpICsgRVBPQ0hKRCxcbiAgICAgICAgY0RhdGUgPSBnZXRDYWwoY2FsZW5kYXIpLmZyb21KRChkYXRlSkQpLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbW9kaWZpZXIsIGRpcmVjdGl2ZSwgZGlyZWN0aXZlTGVuLCBkaXJlY3RpdmVPYmosIHJlcGxhY2VtZW50UGFydDtcbiAgICB3aGlsZSgoaSA9IGZtdC5pbmRleE9mKCclJywgaSkpICE9PSAtMSkge1xuICAgICAgICBtb2RpZmllciA9IGZtdC5jaGFyQXQoaSArIDEpO1xuICAgICAgICBpZihtb2RpZmllciA9PT0gJzAnIHx8IG1vZGlmaWVyID09PSAnLScgfHwgbW9kaWZpZXIgPT09ICdfJykge1xuICAgICAgICAgICAgZGlyZWN0aXZlTGVuID0gMztcbiAgICAgICAgICAgIGRpcmVjdGl2ZSA9IGZtdC5jaGFyQXQoaSArIDIpO1xuICAgICAgICAgICAgaWYobW9kaWZpZXIgPT09ICdfJykgbW9kaWZpZXIgPSAnLSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkaXJlY3RpdmUgPSBtb2RpZmllcjtcbiAgICAgICAgICAgIG1vZGlmaWVyID0gJzAnO1xuICAgICAgICAgICAgZGlyZWN0aXZlTGVuID0gMjtcbiAgICAgICAgfVxuICAgICAgICBkaXJlY3RpdmVPYmogPSBkM1RvV29ybGRDYWxlbmRhcnNbZGlyZWN0aXZlXTtcbiAgICAgICAgaWYoIWRpcmVjdGl2ZU9iaikge1xuICAgICAgICAgICAgaSArPSBkaXJlY3RpdmVMZW47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBjb2RlIGlzIHJlY29nbml6ZWQgYXMgYSBkYXRlIHBhcnQgYnV0IHdvcmxkLWNhbGVuZGFycyBkb2Vzbid0IHN1cHBvcnQgaXRcbiAgICAgICAgICAgIGlmKGRpcmVjdGl2ZU9iaiA9PT0gVU5LTk9XTikgcmVwbGFjZW1lbnRQYXJ0ID0gVU5LTk9XTjtcblxuICAgICAgICAgICAgLy8gZm9ybWF0IHRoZSBjRGF0ZSBhY2NvcmRpbmcgdG8gdGhlIHRyYW5zbGF0ZWQgZGlyZWN0aXZlXG4gICAgICAgICAgICBlbHNlIHJlcGxhY2VtZW50UGFydCA9IGNEYXRlLmZvcm1hdERhdGUoZGlyZWN0aXZlT2JqW21vZGlmaWVyXSk7XG5cbiAgICAgICAgICAgIGZtdCA9IGZtdC5zdWJzdHIoMCwgaSkgKyByZXBsYWNlbWVudFBhcnQgKyBmbXQuc3Vic3RyKGkgKyBkaXJlY3RpdmVMZW4pO1xuICAgICAgICAgICAgaSArPSByZXBsYWNlbWVudFBhcnQubGVuZ3RoO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmbXQ7XG59XG5cbi8vIGNhY2hlIHdvcmxkIGNhbGVuZGFycywgc28gd2UgZG9uJ3QgaGF2ZSB0byByZWluc3RhbnRpYXRlXG4vLyBkdXJpbmcgZWFjaCBkYXRlLXRpbWUgY29udmVyc2lvblxudmFyIGFsbENhbHMgPSB7fTtcbmZ1bmN0aW9uIGdldENhbChjYWxlbmRhcikge1xuICAgIHZhciBjYWxlbmRhck9iaiA9IGFsbENhbHNbY2FsZW5kYXJdO1xuICAgIGlmKGNhbGVuZGFyT2JqKSByZXR1cm4gY2FsZW5kYXJPYmo7XG5cbiAgICBjYWxlbmRhck9iaiA9IGFsbENhbHNbY2FsZW5kYXJdID0gY2FsZW5kYXJzLmluc3RhbmNlKGNhbGVuZGFyKTtcbiAgICByZXR1cm4gY2FsZW5kYXJPYmo7XG59XG5cbmZ1bmN0aW9uIG1ha2VBdHRycyhkZXNjcmlwdGlvbikge1xuICAgIHJldHVybiBMaWIuZXh0ZW5kRmxhdCh7fSwgYXR0cmlidXRlcywgeyBkZXNjcmlwdGlvbjogZGVzY3JpcHRpb24gfSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VUcmFjZUF0dHJzRGVzY3JpcHRpb24oY29vcmQpIHtcbiAgICByZXR1cm4gJ1NldHMgdGhlIGNhbGVuZGFyIHN5c3RlbSB0byB1c2Ugd2l0aCBgJyArIGNvb3JkICsgJ2AgZGF0ZSBkYXRhLic7XG59XG5cbnZhciB4QXR0cnMgPSB7XG4gICAgeGNhbGVuZGFyOiBtYWtlQXR0cnMobWFrZVRyYWNlQXR0cnNEZXNjcmlwdGlvbigneCcpKVxufTtcblxudmFyIHh5QXR0cnMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgeEF0dHJzLCB7XG4gICAgeWNhbGVuZGFyOiBtYWtlQXR0cnMobWFrZVRyYWNlQXR0cnNEZXNjcmlwdGlvbigneScpKVxufSk7XG5cbnZhciB4eXpBdHRycyA9IExpYi5leHRlbmRGbGF0KHt9LCB4eUF0dHJzLCB7XG4gICAgemNhbGVuZGFyOiBtYWtlQXR0cnMobWFrZVRyYWNlQXR0cnNEZXNjcmlwdGlvbigneicpKVxufSk7XG5cbnZhciBheGlzQXR0cnMgPSBtYWtlQXR0cnMoW1xuICAgICdTZXRzIHRoZSBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlIGZvciBgcmFuZ2VgIGFuZCBgdGljazBgJyxcbiAgICAnaWYgdGhpcyBpcyBhIGRhdGUgYXhpcy4gVGhpcyBkb2VzIG5vdCBzZXQgdGhlIGNhbGVuZGFyIGZvcicsXG4gICAgJ2ludGVycHJldGluZyBkYXRhIG9uIHRoaXMgYXhpcywgdGhhdFxcJ3Mgc3BlY2lmaWVkIGluIHRoZSB0cmFjZScsXG4gICAgJ29yIHZpYSB0aGUgZ2xvYmFsIGBsYXlvdXQuY2FsZW5kYXJgJ1xuXS5qb2luKCcgJykpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnY2FsZW5kYXJzJyxcblxuICAgIHNjaGVtYToge1xuICAgICAgICB0cmFjZXM6IHtcbiAgICAgICAgICAgIHNjYXR0ZXI6IHh5QXR0cnMsXG4gICAgICAgICAgICBiYXI6IHh5QXR0cnMsXG4gICAgICAgICAgICBib3g6IHh5QXR0cnMsXG4gICAgICAgICAgICBoZWF0bWFwOiB4eUF0dHJzLFxuICAgICAgICAgICAgY29udG91cjogeHlBdHRycyxcbiAgICAgICAgICAgIGhpc3RvZ3JhbTogeHlBdHRycyxcbiAgICAgICAgICAgIGhpc3RvZ3JhbTJkOiB4eUF0dHJzLFxuICAgICAgICAgICAgaGlzdG9ncmFtMmRjb250b3VyOiB4eUF0dHJzLFxuICAgICAgICAgICAgc2NhdHRlcjNkOiB4eXpBdHRycyxcbiAgICAgICAgICAgIHN1cmZhY2U6IHh5ekF0dHJzLFxuICAgICAgICAgICAgbWVzaDNkOiB4eXpBdHRycyxcbiAgICAgICAgICAgIHNjYXR0ZXJnbDogeHlBdHRycyxcbiAgICAgICAgICAgIG9obGM6IHhBdHRycyxcbiAgICAgICAgICAgIGNhbmRsZXN0aWNrOiB4QXR0cnNcbiAgICAgICAgfSxcbiAgICAgICAgbGF5b3V0OiB7XG4gICAgICAgICAgICBjYWxlbmRhcjogbWFrZUF0dHJzKFtcbiAgICAgICAgICAgICAgICAnU2V0cyB0aGUgZGVmYXVsdCBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlIGZvciBpbnRlcnByZXRpbmcgYW5kJyxcbiAgICAgICAgICAgICAgICAnZGlzcGxheWluZyBkYXRlcyB0aHJvdWdob3V0IHRoZSBwbG90LidcbiAgICAgICAgICAgIF0uam9pbignICcpKVxuICAgICAgICB9LFxuICAgICAgICBzdWJwbG90czoge1xuICAgICAgICAgICAgeGF4aXM6IHtjYWxlbmRhcjogYXhpc0F0dHJzfSxcbiAgICAgICAgICAgIHlheGlzOiB7Y2FsZW5kYXI6IGF4aXNBdHRyc30sXG4gICAgICAgICAgICBzY2VuZToge1xuICAgICAgICAgICAgICAgIHhheGlzOiB7Y2FsZW5kYXI6IGF4aXNBdHRyc30sXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogaXQncyBhY3R1YWxseSByZWR1bmRhbnQgdG8gaW5jbHVkZSB5YXhpcyBhbmQgemF4aXMgaGVyZVxuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2UgaW4gdGhlIHNjZW5lIGF0dHJpYnV0ZXMgdGhlc2UgYXJlIHRoZSBzYW1lIG9iamVjdCBzbyBtZXJnaW5nXG4gICAgICAgICAgICAgICAgLy8gaW50byBvbmUgbWVyZ2VzIGludG8gdGhlbSBhbGwuIEhvd2V2ZXIsIEkgbGVmdCB0aGVtIGluIGZvciBwYXJpdHkgd2l0aFxuICAgICAgICAgICAgICAgIC8vIGNhcnRlc2lhbiwgd2hlcmUgeWF4aXMgaXMgdW51c2VkIHVudGlsIHdlIFBsb3RzY2hlbWEuZ2V0KCkgd2hlbiB3ZVxuICAgICAgICAgICAgICAgIC8vIHVzZSBpdHMgcHJlc2VuY2Ugb3IgYWJzZW5jZSB0byBkZXRlcm1pbmUgd2hldGhlciB0byBkZWxldGUgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIC8vIGZyb20geWF4aXMgaWYgdGhleSBvbmx5IGFwcGx5IHRvIHggKHJhbmdlc2VsZWN0b3IvcmFuZ2VzbGlkZXIpXG4gICAgICAgICAgICAgICAgeWF4aXM6IHtjYWxlbmRhcjogYXhpc0F0dHJzfSxcbiAgICAgICAgICAgICAgICB6YXhpczoge2NhbGVuZGFyOiBheGlzQXR0cnN9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcG9sYXI6IHtcbiAgICAgICAgICAgICAgICByYWRpYWxheGlzOiB7Y2FsZW5kYXI6IGF4aXNBdHRyc31cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmb3Jtczoge1xuICAgICAgICAgICAgZmlsdGVyOiB7XG4gICAgICAgICAgICAgICAgdmFsdWVjYWxlbmRhcjogbWFrZUF0dHJzKFtcbiAgICAgICAgICAgICAgICAgICAgJ1NldHMgdGhlIGNhbGVuZGFyIHN5c3RlbSB0byB1c2UgZm9yIGB2YWx1ZWAsIGlmIGl0IGlzIGEgZGF0ZS4nXG4gICAgICAgICAgICAgICAgXS5qb2luKCcgJykpLFxuICAgICAgICAgICAgICAgIHRhcmdldGNhbGVuZGFyOiBtYWtlQXR0cnMoW1xuICAgICAgICAgICAgICAgICAgICAnU2V0cyB0aGUgY2FsZW5kYXIgc3lzdGVtIHRvIHVzZSBmb3IgYHRhcmdldGAsIGlmIGl0IGlzIGFuJyxcbiAgICAgICAgICAgICAgICAgICAgJ2FycmF5IG9mIGRhdGVzLiBJZiBgdGFyZ2V0YCBpcyBhIHN0cmluZyAoZWcgKngqKSB3ZSB1c2UgdGhlJyxcbiAgICAgICAgICAgICAgICAgICAgJ2NvcnJlc3BvbmRpbmcgdHJhY2UgYXR0cmlidXRlIChlZyBgeGNhbGVuZGFyYCkgaWYgaXQgZXhpc3RzLCcsXG4gICAgICAgICAgICAgICAgICAgICdldmVuIGlmIGB0YXJnZXRjYWxlbmRhcmAgaXMgcHJvdmlkZWQuJ1xuICAgICAgICAgICAgICAgIF0uam9pbignICcpKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxheW91dEF0dHJpYnV0ZXM6IGF0dHJpYnV0ZXMsXG5cbiAgICBoYW5kbGVEZWZhdWx0czogaGFuZGxlRGVmYXVsdHMsXG4gICAgaGFuZGxlVHJhY2VEZWZhdWx0czogaGFuZGxlVHJhY2VEZWZhdWx0cyxcblxuICAgIENBTk9OSUNBTF9TVU5EQVk6IENBTk9OSUNBTF9TVU5EQVksXG4gICAgQ0FOT05JQ0FMX1RJQ0s6IENBTk9OSUNBTF9USUNLLFxuICAgIERGTFRSQU5HRTogREZMVFJBTkdFLFxuXG4gICAgZ2V0Q2FsOiBnZXRDYWwsXG4gICAgd29ybGRDYWxGbXQ6IHdvcmxkQ2FsRm10XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbi8vIElNUE9SVEFOVCAtIGRlZmF1bHQgY29sb3JzIHNob3VsZCBiZSBpbiBoZXggZm9yIGNvbXBhdGliaWxpdHlcbmV4cG9ydHMuZGVmYXVsdHMgPSBbXG4gICAgJyMxZjc3YjQnLCAgLy8gbXV0ZWQgYmx1ZVxuICAgICcjZmY3ZjBlJywgIC8vIHNhZmV0eSBvcmFuZ2VcbiAgICAnIzJjYTAyYycsICAvLyBjb29rZWQgYXNwYXJhZ3VzIGdyZWVuXG4gICAgJyNkNjI3MjgnLCAgLy8gYnJpY2sgcmVkXG4gICAgJyM5NDY3YmQnLCAgLy8gbXV0ZWQgcHVycGxlXG4gICAgJyM4YzU2NGInLCAgLy8gY2hlc3RudXQgYnJvd25cbiAgICAnI2UzNzdjMicsICAvLyByYXNwYmVycnkgeW9ndXJ0IHBpbmtcbiAgICAnIzdmN2Y3ZicsICAvLyBtaWRkbGUgZ3JheVxuICAgICcjYmNiZDIyJywgIC8vIGN1cnJ5IHllbGxvdy1ncmVlblxuICAgICcjMTdiZWNmJyAgIC8vIGJsdWUtdGVhbFxuXTtcblxuZXhwb3J0cy5kZWZhdWx0TGluZSA9ICcjNDQ0JztcblxuZXhwb3J0cy5saWdodExpbmUgPSAnI2VlZSc7XG5cbmV4cG9ydHMuYmFja2dyb3VuZCA9ICcjZmZmJztcblxuZXhwb3J0cy5ib3JkZXJMaW5lID0gJyNCRUM4RDknO1xuXG4vLyB3aXRoIGF4aXMuY29sb3IgYW5kIENvbG9yLmludGVycCB3ZSBhcmVuJ3QgdXNpbmcgbGlnaHRMaW5lXG4vLyBpdHNlbGYgYW55bW9yZSwgaW5zdGVhZCBpbnRlcnBvbGF0aW5nIGJldHdlZW4gYXhpcy5jb2xvclxuLy8gYW5kIHRoZSBiYWNrZ3JvdW5kIGNvbG9yIHVzaW5nIHRpbnljb2xvci5taXguIGxpZ2h0RnJhY3Rpb25cbi8vIGdpdmVzIGJhY2sgZXhhY3RseSBsaWdodExpbmUgaWYgdGhlIG90aGVyIGNvbG9ycyBhcmUgZGVmYXVsdHMuXG5leHBvcnRzLmxpZ2h0RnJhY3Rpb24gPSAxMDAgKiAoMHhlIC0gMHg0KSAvICgweGYgLSAweDQpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIGNvbG9yID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxudmFyIGNvbG9yQXR0cnMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbmNvbG9yLmRlZmF1bHRzID0gY29sb3JBdHRycy5kZWZhdWx0cztcbnZhciBkZWZhdWx0TGluZSA9IGNvbG9yLmRlZmF1bHRMaW5lID0gY29sb3JBdHRycy5kZWZhdWx0TGluZTtcbmNvbG9yLmxpZ2h0TGluZSA9IGNvbG9yQXR0cnMubGlnaHRMaW5lO1xudmFyIGJhY2tncm91bmQgPSBjb2xvci5iYWNrZ3JvdW5kID0gY29sb3JBdHRycy5iYWNrZ3JvdW5kO1xuXG4vKlxuICogdGlueVJHQjogdHVybiBhIHRpbnljb2xvciBpbnRvIGFuIHJnYiBzdHJpbmcsIGJ1dFxuICogdW5saWtlIHRoZSBidWlsdC1pbiB0aW55Y29sb3IudG9SZ2JTdHJpbmcgdGhpcyBuZXZlciBpbmNsdWRlcyBhbHBoYVxuICovXG5jb2xvci50aW55UkdCID0gZnVuY3Rpb24odGMpIHtcbiAgICB2YXIgYyA9IHRjLnRvUmdiKCk7XG4gICAgcmV0dXJuICdyZ2IoJyArIE1hdGgucm91bmQoYy5yKSArICcsICcgK1xuICAgICAgICBNYXRoLnJvdW5kKGMuZykgKyAnLCAnICsgTWF0aC5yb3VuZChjLmIpICsgJyknO1xufTtcblxuY29sb3IucmdiID0gZnVuY3Rpb24oY3N0cikgeyByZXR1cm4gY29sb3IudGlueVJHQih0aW55Y29sb3IoY3N0cikpOyB9O1xuXG5jb2xvci5vcGFjaXR5ID0gZnVuY3Rpb24oY3N0cikgeyByZXR1cm4gY3N0ciA/IHRpbnljb2xvcihjc3RyKS5nZXRBbHBoYSgpIDogMDsgfTtcblxuY29sb3IuYWRkT3BhY2l0eSA9IGZ1bmN0aW9uKGNzdHIsIG9wKSB7XG4gICAgdmFyIGMgPSB0aW55Y29sb3IoY3N0cikudG9SZ2IoKTtcbiAgICByZXR1cm4gJ3JnYmEoJyArIE1hdGgucm91bmQoYy5yKSArICcsICcgK1xuICAgICAgICBNYXRoLnJvdW5kKGMuZykgKyAnLCAnICsgTWF0aC5yb3VuZChjLmIpICsgJywgJyArIG9wICsgJyknO1xufTtcblxuLy8gY29tYmluZSB0d28gY29sb3JzIGludG8gb25lIGFwcGFyZW50IGNvbG9yXG4vLyBpZiBiYWNrIGhhcyB0cmFuc3BhcmVuY3kgb3IgaXMgbWlzc2luZyxcbi8vIGNvbG9yLmJhY2tncm91bmQgaXMgYXNzdW1lZCBiZWhpbmQgaXRcbmNvbG9yLmNvbWJpbmUgPSBmdW5jdGlvbihmcm9udCwgYmFjaykge1xuICAgIHZhciBmYyA9IHRpbnljb2xvcihmcm9udCkudG9SZ2IoKTtcbiAgICBpZihmYy5hID09PSAxKSByZXR1cm4gdGlueWNvbG9yKGZyb250KS50b1JnYlN0cmluZygpO1xuXG4gICAgdmFyIGJjID0gdGlueWNvbG9yKGJhY2sgfHwgYmFja2dyb3VuZCkudG9SZ2IoKSxcbiAgICAgICAgYmNmbGF0ID0gYmMuYSA9PT0gMSA/IGJjIDoge1xuICAgICAgICAgICAgcjogMjU1ICogKDEgLSBiYy5hKSArIGJjLnIgKiBiYy5hLFxuICAgICAgICAgICAgZzogMjU1ICogKDEgLSBiYy5hKSArIGJjLmcgKiBiYy5hLFxuICAgICAgICAgICAgYjogMjU1ICogKDEgLSBiYy5hKSArIGJjLmIgKiBiYy5hXG4gICAgICAgIH0sXG4gICAgICAgIGZjZmxhdCA9IHtcbiAgICAgICAgICAgIHI6IGJjZmxhdC5yICogKDEgLSBmYy5hKSArIGZjLnIgKiBmYy5hLFxuICAgICAgICAgICAgZzogYmNmbGF0LmcgKiAoMSAtIGZjLmEpICsgZmMuZyAqIGZjLmEsXG4gICAgICAgICAgICBiOiBiY2ZsYXQuYiAqICgxIC0gZmMuYSkgKyBmYy5iICogZmMuYVxuICAgICAgICB9O1xuICAgIHJldHVybiB0aW55Y29sb3IoZmNmbGF0KS50b1JnYlN0cmluZygpO1xufTtcblxuLypcbiAqIENyZWF0ZSBhIGNvbG9yIHRoYXQgY29udHJhc3RzIHdpdGggY3N0ci5cbiAqXG4gKiBJZiBjc3RyIGlzIGEgZGFyayBjb2xvciwgd2UgbGlnaHRlbiBpdDsgaWYgaXQncyBsaWdodCwgd2UgZGFya2VuLlxuICpcbiAqIElmIGxpZ2h0QW1vdW50IC8gZGFya0Ftb3VudCBhcmUgdXNlZCwgd2UgYWRqdXN0IGJ5IHRoZXNlIHBlcmNlbnRhZ2VzLFxuICogb3RoZXJ3aXNlIHdlIGdvIGFsbCB0aGUgd2F5IHRvIHdoaXRlIG9yIGJsYWNrLlxuICovXG5jb2xvci5jb250cmFzdCA9IGZ1bmN0aW9uKGNzdHIsIGxpZ2h0QW1vdW50LCBkYXJrQW1vdW50KSB7XG4gICAgdmFyIHRjID0gdGlueWNvbG9yKGNzdHIpO1xuXG4gICAgaWYodGMuZ2V0QWxwaGEoKSAhPT0gMSkgdGMgPSB0aW55Y29sb3IoY29sb3IuY29tYmluZShjc3RyLCBiYWNrZ3JvdW5kKSk7XG5cbiAgICB2YXIgbmV3Q29sb3IgPSB0Yy5pc0RhcmsoKSA/XG4gICAgICAgIChsaWdodEFtb3VudCA/IHRjLmxpZ2h0ZW4obGlnaHRBbW91bnQpIDogYmFja2dyb3VuZCkgOlxuICAgICAgICAoZGFya0Ftb3VudCA/IHRjLmRhcmtlbihkYXJrQW1vdW50KSA6IGRlZmF1bHRMaW5lKTtcblxuICAgIHJldHVybiBuZXdDb2xvci50b1N0cmluZygpO1xufTtcblxuY29sb3Iuc3Ryb2tlID0gZnVuY3Rpb24ocywgYykge1xuICAgIHZhciB0YyA9IHRpbnljb2xvcihjKTtcbiAgICBzLnN0eWxlKHsnc3Ryb2tlJzogY29sb3IudGlueVJHQih0YyksICdzdHJva2Utb3BhY2l0eSc6IHRjLmdldEFscGhhKCl9KTtcbn07XG5cbmNvbG9yLmZpbGwgPSBmdW5jdGlvbihzLCBjKSB7XG4gICAgdmFyIHRjID0gdGlueWNvbG9yKGMpO1xuICAgIHMuc3R5bGUoe1xuICAgICAgICAnZmlsbCc6IGNvbG9yLnRpbnlSR0IodGMpLFxuICAgICAgICAnZmlsbC1vcGFjaXR5JzogdGMuZ2V0QWxwaGEoKVxuICAgIH0pO1xufTtcblxuLy8gc2VhcmNoIGNvbnRhaW5lciBmb3IgY29sb3JzIHdpdGggdGhlIGRlcHJlY2F0ZWQgcmdiKGZyYWN0aW9ucykgZm9ybWF0XG4vLyBhbmQgY29udmVydCB0aGVtIHRvIHJnYigwLTI1NSB2YWx1ZXMpXG5jb2xvci5jbGVhbiA9IGZ1bmN0aW9uKGNvbnRhaW5lcikge1xuICAgIGlmKCFjb250YWluZXIgfHwgdHlwZW9mIGNvbnRhaW5lciAhPT0gJ29iamVjdCcpIHJldHVybjtcblxuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMoY29udGFpbmVyKSxcbiAgICAgICAgaSxcbiAgICAgICAgaixcbiAgICAgICAga2V5LFxuICAgICAgICB2YWw7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgIHZhbCA9IGNvbnRhaW5lcltrZXldO1xuXG4gICAgICAgIC8vIG9ubHkgc2FuaXRpemUga2V5cyB0aGF0IGVuZCBpbiBcImNvbG9yXCIgb3IgXCJjb2xvcnNjYWxlXCJcbiAgICAgICAgaWYoa2V5LnN1YnN0cihrZXkubGVuZ3RoIC0gNSkgPT09ICdjb2xvcicpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodmFsKSkge1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHZhbC5sZW5ndGg7IGorKykgdmFsW2pdID0gY2xlYW5PbmUodmFsW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgY29udGFpbmVyW2tleV0gPSBjbGVhbk9uZSh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoa2V5LnN1YnN0cihrZXkubGVuZ3RoIC0gMTApID09PSAnY29sb3JzY2FsZScgJiYgQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgICAgICAvLyBjb2xvcnNjYWxlcyBoYXZlIHRoZSBmb3JtYXQgW1swLCBjb2xvcjFdLCBbZnJhYywgY29sb3IyXSwgLi4uIFsxLCBjb2xvck5dXVxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdmFsLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh2YWxbal0pKSB2YWxbal1bMV0gPSBjbGVhbk9uZSh2YWxbal1bMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHJlY3Vyc2UgaW50byBhcnJheXMgb2Ygb2JqZWN0cywgYW5kIHBsYWluIG9iamVjdHNcbiAgICAgICAgZWxzZSBpZihBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgIHZhciBlbDAgPSB2YWxbMF07XG4gICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheShlbDApICYmIGVsMCAmJiB0eXBlb2YgZWwwID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHZhbC5sZW5ndGg7IGorKykgY29sb3IuY2xlYW4odmFsW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JykgY29sb3IuY2xlYW4odmFsKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjbGVhbk9uZSh2YWwpIHtcbiAgICBpZihpc051bWVyaWModmFsKSB8fCB0eXBlb2YgdmFsICE9PSAnc3RyaW5nJykgcmV0dXJuIHZhbDtcblxuICAgIHZhciB2YWxUcmltID0gdmFsLnRyaW0oKTtcbiAgICBpZih2YWxUcmltLnN1YnN0cigwLCAzKSAhPT0gJ3JnYicpIHJldHVybiB2YWw7XG5cbiAgICB2YXIgbWF0Y2ggPSB2YWxUcmltLm1hdGNoKC9ecmdiYT9cXHMqXFwoKFteKCldKilcXCkkLyk7XG4gICAgaWYoIW1hdGNoKSByZXR1cm4gdmFsO1xuXG4gICAgdmFyIHBhcnRzID0gbWF0Y2hbMV0udHJpbSgpLnNwbGl0KC9cXHMqW1xccyxdXFxzKi8pLFxuICAgICAgICByZ2JhID0gdmFsVHJpbS5jaGFyQXQoMykgPT09ICdhJyAmJiBwYXJ0cy5sZW5ndGggPT09IDQ7XG4gICAgaWYoIXJnYmEgJiYgcGFydHMubGVuZ3RoICE9PSAzKSByZXR1cm4gdmFsO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFwYXJ0c1tpXS5sZW5ndGgpIHJldHVybiB2YWw7XG4gICAgICAgIHBhcnRzW2ldID0gTnVtYmVyKHBhcnRzW2ldKTtcblxuICAgICAgICAvLyBhbGwgcGFydHMgbXVzdCBiZSBub24tbmVnYXRpdmUgbnVtYmVyc1xuICAgICAgICBpZighKHBhcnRzW2ldID49IDApKSByZXR1cm4gdmFsO1xuICAgICAgICAvLyBhbHBoYT4xIGdldHMgY2xpcHBlZCB0byAxXG4gICAgICAgIGlmKGkgPT09IDMpIHtcbiAgICAgICAgICAgIGlmKHBhcnRzW2ldID4gMSkgcGFydHNbaV0gPSAxO1xuICAgICAgICB9XG4gICAgICAgIC8vIHIsIGcsIGIgbXVzdCBiZSA8IDEgKGllIDEgaXRzZWxmIGlzIG5vdCBhbGxvd2VkKVxuICAgICAgICBlbHNlIGlmKHBhcnRzW2ldID49IDEpIHJldHVybiB2YWw7XG4gICAgfVxuXG4gICAgdmFyIHJnYlN0ciA9IE1hdGgucm91bmQocGFydHNbMF0gKiAyNTUpICsgJywgJyArXG4gICAgICAgIE1hdGgucm91bmQocGFydHNbMV0gKiAyNTUpICsgJywgJyArXG4gICAgICAgIE1hdGgucm91bmQocGFydHNbMl0gKiAyNTUpO1xuXG4gICAgaWYocmdiYSkgcmV0dXJuICdyZ2JhKCcgKyByZ2JTdHIgKyAnLCAnICsgcGFydHNbM10gKyAnKSc7XG4gICAgcmV0dXJuICdyZ2IoJyArIHJnYlN0ciArICcpJztcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGF4ZXNBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbi8vIFRPRE86IG9ubHkgcmlnaHQgaXMgc3VwcG9ydGVkIGN1cnJlbnRseVxuLy8gICAgIG9yaWVudDoge1xuLy8gICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4vLyAgICAgICAgIFxuLy8gICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdyaWdodCcsICd0b3AnLCAnYm90dG9tJ10sXG4vLyAgICAgICAgIGRmbHQ6ICdyaWdodCcsXG4vLyAgICAgICAgIFxuLy8gICAgIH0sXG4gICAgdGhpY2tuZXNzbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydmcmFjdGlvbicsICdwaXhlbHMnXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdwaXhlbHMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMzAsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGVubW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydmcmFjdGlvbicsICdwaXhlbHMnXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdmcmFjdGlvbicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGVuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEuMDIsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddLFxuICAgICAgICBkZmx0OiAnbGVmdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHhwYWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAwLjUsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnbWlkZGxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5cGFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBhIHBvc3NpYmxlIGxpbmUgYXJvdW5kIHRoZSBiYXIgaXRzZWxmXG4gICAgb3V0bGluZWNvbG9yOiBheGVzQXR0cnMubGluZWNvbG9yLFxuICAgIG91dGxpbmV3aWR0aDogYXhlc0F0dHJzLmxpbmV3aWR0aCxcbiAgICAvLyBTaG91bGQgb3V0bGluZXdpZHRoIGhhdmUge2RmbHQ6IDB9ID9cbiAgICAvLyBhbm90aGVyIHBvc3NpYmxlIGxpbmUgb3V0c2lkZSB0aGUgcGFkZGluZyBhbmQgdGljayBsYWJlbHNcbiAgICBib3JkZXJjb2xvcjogYXhlc0F0dHJzLmxpbmVjb2xvcixcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAncmdiYSgwLDAsMCwwKScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gdGljayBhbmQgdGl0bGUgcHJvcGVydGllcyBuYW1lZCBhbmQgZnVuY3Rpb24gZXhhY3RseSBhcyBpbiBheGVzXG4gICAgdGlja21vZGU6IGF4ZXNBdHRycy50aWNrbW9kZSxcbiAgICBudGlja3M6IGF4ZXNBdHRycy5udGlja3MsXG4gICAgdGljazA6IGF4ZXNBdHRycy50aWNrMCxcbiAgICBkdGljazogYXhlc0F0dHJzLmR0aWNrLFxuICAgIHRpY2t2YWxzOiBheGVzQXR0cnMudGlja3ZhbHMsXG4gICAgdGlja3RleHQ6IGF4ZXNBdHRycy50aWNrdGV4dCxcbiAgICB0aWNrczogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnRpY2tzLCB7ZGZsdDogJyd9KSxcbiAgICB0aWNrbGVuOiBheGVzQXR0cnMudGlja2xlbixcbiAgICB0aWNrd2lkdGg6IGF4ZXNBdHRycy50aWNrd2lkdGgsXG4gICAgdGlja2NvbG9yOiBheGVzQXR0cnMudGlja2NvbG9yLFxuICAgIHNob3d0aWNrbGFiZWxzOiBheGVzQXR0cnMuc2hvd3RpY2tsYWJlbHMsXG4gICAgdGlja2ZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIHRpY2thbmdsZTogYXhlc0F0dHJzLnRpY2thbmdsZSxcbiAgICB0aWNrZm9ybWF0OiBheGVzQXR0cnMudGlja2Zvcm1hdCxcbiAgICB0aWNrZm9ybWF0c3RvcHM6IGF4ZXNBdHRycy50aWNrZm9ybWF0c3RvcHMsXG4gICAgdGlja3ByZWZpeDogYXhlc0F0dHJzLnRpY2twcmVmaXgsXG4gICAgc2hvd3RpY2twcmVmaXg6IGF4ZXNBdHRycy5zaG93dGlja3ByZWZpeCxcbiAgICB0aWNrc3VmZml4OiBheGVzQXR0cnMudGlja3N1ZmZpeCxcbiAgICBzaG93dGlja3N1ZmZpeDogYXhlc0F0dHJzLnNob3d0aWNrc3VmZml4LFxuICAgIHNlcGFyYXRldGhvdXNhbmRzOiBheGVzQXR0cnMuc2VwYXJhdGV0aG91c2FuZHMsXG4gICAgZXhwb25lbnRmb3JtYXQ6IGF4ZXNBdHRycy5leHBvbmVudGZvcm1hdCxcbiAgICBzaG93ZXhwb25lbnQ6IGF4ZXNBdHRycy5zaG93ZXhwb25lbnQsXG4gICAgdGl0bGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpdGxlZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdGl0bGVzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3JpZ2h0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICd0b3AnLFxuICAgICAgICBcbiAgICB9XG59LCAnY29sb3JiYXJzJywgJ2Zyb20tcm9vdCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkcmF3Q29sb3JiYXIgPSByZXF1aXJlKCcuL2RyYXcnKTtcblxuLyoqXG4gKiBjb25uZWN0Q29sb3JiYXI6IGNyZWF0ZSBhIGNvbG9yYmFyIGZyb20gYSB0cmFjZSwgdXNpbmcgaXRzIG1vZHVsZSB0b1xuICogICBkZXNjcmliZSB0aGUgY29ubmVjdGlvbi5cbiAqXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50fSBnZFxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGNkXG4gKiAgIGNhbGNkYXRhIGVudHJ5IGZvciB0aGlzIHRyYWNlLiBjZFswXS50cmFjZSBpcyB0aGUgdHJhY2UgaXRzZWxmLCBhbmQgdGhlXG4gKiAgIGNvbG9yYmFyIG9iamVjdCB3aWxsIGJlIHN0YXNoZWQgaW4gY2RbMF0udC5jYlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fGZ1bmN0aW9ufSBtb2R1bGVPcHRzXG4gKiAgIG1heSBiZSBhIGZ1bmN0aW9uKGdkLCBjZCkgdG8gb3ZlcnJpZGUgdGhlIHN0YW5kYXJkIGhhbmRsaW5nIGJlbG93LiBJZlxuICogICBhbiBvYmplY3QsIHNob3VsZCBoYXZlIHRoZXNlIGtleXM6XG4gKiBAcGFyYW0ge09wdGlvbmFsKHN0cmluZyl9IG1vZHVsZU9wdHMuY29udGFpbmVyXG4gKiAgIG5hbWUgb2YgdGhlIGNvbnRhaW5lciBpbnNpZGUgdGhlIHRyYWNlIHdoZXJlIHRoZSBjb2xvcmJhciBhbmQgY29sb3JzY2FsZVxuICogICBhdHRyaWJ1dGVzIGxpdmUgKGllICdtYXJrZXInLCAnbGluZScpIC0gb21pdCBpZiB0aGV5J3JlIGF0IHRoZSB0cmFjZSByb290LlxuICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZU9wdHMubWluXG4gKiAgIG5hbWUgb2YgdGhlIGF0dHJpYnV0ZSBob2xkaW5nIHRoZSB2YWx1ZSBvZiB0aGUgbWluaW11bSBjb2xvclxuICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZU9wdHMubWF4XG4gKiAgIG5hbWUgb2YgdGhlIGF0dHJpYnV0ZSBob2xkaW5nIHRoZSB2YWx1ZSBvZiB0aGUgbWF4aW11bSBjb2xvclxuICogQHBhcmFtIHtPcHRpb25hbChzdHJpbmcpfSBtb2R1bGVPcHRzLnZhbHNcbiAqICAgbmFtZSBvZiB0aGUgYXR0cmlidXRlIGhvbGRpbmcgdGhlIChudW1lcmljKSBjb2xvciBkYXRhXG4gKiAgIHVzZWQgb25seSBpZiBtaW4vbWF4IGZhaWwuIE1heSBiZSBvbWl0dGVkIGlmIHRoZXNlIGFyZSBhbHdheXNcbiAqICAgcHJlLWNhbGN1bGF0ZWQuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29ubmVjdENvbG9yYmFyKGdkLCBjZCwgbW9kdWxlT3B0cykge1xuICAgIGlmKHR5cGVvZiBtb2R1bGVPcHRzID09PSAnZnVuY3Rpb24nKSByZXR1cm4gbW9kdWxlT3B0cyhnZCwgY2QpO1xuXG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIGNiSWQgPSAnY2InICsgdHJhY2UudWlkO1xuICAgIHZhciBjb250YWluZXJOYW1lID0gbW9kdWxlT3B0cy5jb250YWluZXI7XG4gICAgdmFyIGNvbnRhaW5lciA9IGNvbnRhaW5lck5hbWUgPyB0cmFjZVtjb250YWluZXJOYW1lXSA6IHRyYWNlO1xuXG4gICAgZ2QuX2Z1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJy4nICsgY2JJZCkucmVtb3ZlKCk7XG4gICAgaWYoIWNvbnRhaW5lciB8fCAhY29udGFpbmVyLnNob3dzY2FsZSkgcmV0dXJuO1xuXG4gICAgdmFyIGNiID0gY2RbMF0udC5jYiA9IGRyYXdDb2xvcmJhcihnZCwgY2JJZCk7XG5cbiAgICBjYi5maWxsZ3JhZGllbnQoY29udGFpbmVyLmNvbG9yc2NhbGUpXG4gICAgICAgIC56cmFuZ2UoW2NvbnRhaW5lclttb2R1bGVPcHRzLm1pbl0sIGNvbnRhaW5lclttb2R1bGVPcHRzLm1heF1dKVxuICAgICAgICAub3B0aW9ucyhjb250YWluZXIuY29sb3JiYXIpKCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjbjoge1xuICAgICAgICBjb2xvcmJhcjogJ2NvbG9yYmFyJyxcbiAgICAgICAgY2JiZzogJ2NiYmcnLFxuICAgICAgICBjYmZpbGw6ICdjYmZpbGwnLFxuICAgICAgICBjYmZpbGxzOiAnY2JmaWxscycsXG4gICAgICAgIGNibGluZTogJ2NibGluZScsXG4gICAgICAgIGNibGluZXM6ICdjYmxpbmVzJyxcbiAgICAgICAgY2JheGlzOiAnY2JheGlzJyxcbiAgICAgICAgY2J0aXRsZXVuc2hpZnQ6ICdjYnRpdGxldW5zaGlmdCcsXG4gICAgICAgIGNidGl0bGU6ICdjYnRpdGxlJyxcbiAgICAgICAgY2JvdXRsaW5lOiAnY2JvdXRsaW5lJyxcbiAgICAgICAgY3Jpc3A6ICdjcmlzcCcsXG4gICAgICAgIGpzUGxhY2Vob2xkZXI6ICdqcy1wbGFjZWhvbGRlcidcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTWFya0RlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbG9yYmFyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgbGF5b3V0KSB7XG4gICAgdmFyIGNvbG9yYmFyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGNvbnRhaW5lck91dCwgJ2NvbG9yYmFyJyksXG4gICAgICAgIGNvbG9yYmFySW4gPSBjb250YWluZXJJbi5jb2xvcmJhciB8fCB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGNvbG9yYmFySW4sIGNvbG9yYmFyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdGhpY2tuZXNzbW9kZSA9IGNvZXJjZSgndGhpY2tuZXNzbW9kZScpO1xuICAgIGNvZXJjZSgndGhpY2tuZXNzJywgKHRoaWNrbmVzc21vZGUgPT09ICdmcmFjdGlvbicpID9cbiAgICAgICAgMzAgLyAobGF5b3V0LndpZHRoIC0gbGF5b3V0Lm1hcmdpbi5sIC0gbGF5b3V0Lm1hcmdpbi5yKSA6XG4gICAgICAgIDMwXG4gICAgKTtcblxuICAgIHZhciBsZW5tb2RlID0gY29lcmNlKCdsZW5tb2RlJyk7XG4gICAgY29lcmNlKCdsZW4nLCAobGVubW9kZSA9PT0gJ2ZyYWN0aW9uJykgP1xuICAgICAgICAxIDpcbiAgICAgICAgbGF5b3V0LmhlaWdodCAtIGxheW91dC5tYXJnaW4udCAtIGxheW91dC5tYXJnaW4uYlxuICAgICk7XG5cbiAgICBjb2VyY2UoJ3gnKTtcbiAgICBjb2VyY2UoJ3hhbmNob3InKTtcbiAgICBjb2VyY2UoJ3hwYWQnKTtcbiAgICBjb2VyY2UoJ3knKTtcbiAgICBjb2VyY2UoJ3lhbmNob3InKTtcbiAgICBjb2VyY2UoJ3lwYWQnKTtcbiAgICBMaWIubm9uZU9yQWxsKGNvbG9yYmFySW4sIGNvbG9yYmFyT3V0LCBbJ3gnLCAneSddKTtcblxuICAgIGNvZXJjZSgnb3V0bGluZWNvbG9yJyk7XG4gICAgY29lcmNlKCdvdXRsaW5ld2lkdGgnKTtcbiAgICBjb2VyY2UoJ2JvcmRlcmNvbG9yJyk7XG4gICAgY29lcmNlKCdib3JkZXJ3aWR0aCcpO1xuICAgIGNvZXJjZSgnYmdjb2xvcicpO1xuXG4gICAgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoY29sb3JiYXJJbiwgY29sb3JiYXJPdXQsIGNvZXJjZSwgJ2xpbmVhcicpO1xuXG4gICAgdmFyIG9wdHMgPSB7b3V0ZXJUaWNrczogZmFsc2UsIGZvbnQ6IGxheW91dC5mb250fTtcbiAgICBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyhjb2xvcmJhckluLCBjb2xvcmJhck91dCwgY29lcmNlLCAnbGluZWFyJywgb3B0cyk7XG4gICAgaGFuZGxlVGlja01hcmtEZWZhdWx0cyhjb2xvcmJhckluLCBjb2xvcmJhck91dCwgY29lcmNlLCAnbGluZWFyJywgb3B0cyk7XG5cbiAgICBjb2VyY2UoJ3RpdGxlJywgbGF5b3V0Ll9kZmx0VGl0bGUuY29sb3JiYXIpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlZm9udCcsIGxheW91dC5mb250KTtcbiAgICBjb2VyY2UoJ3RpdGxlc2lkZScpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIHRpbnljb2xvciA9IHJlcXVpcmUoJ3Rpbnljb2xvcjInKTtcblxudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi9kcmFnZWxlbWVudCcpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBzZXRDdXJzb3IgPSByZXF1aXJlKCcuLi8uLi9saWIvc2V0Y3Vyc29yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG52YXIgVGl0bGVzID0gcmVxdWlyZSgnLi4vdGl0bGVzJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgYWxpZ25tZW50Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpO1xudmFyIExJTkVfU1BBQ0lORyA9IGFsaWdubWVudENvbnN0YW50cy5MSU5FX1NQQUNJTkc7XG52YXIgRlJPTV9UTCA9IGFsaWdubWVudENvbnN0YW50cy5GUk9NX1RMO1xudmFyIEZST01fQlIgPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9CUjtcblxudmFyIGhhbmRsZUF4aXNEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQXhpc1Bvc2l0aW9uRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vcG9zaXRpb25fZGVmYXVsdHMnKTtcbnZhciBheGlzTGF5b3V0QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjbiA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJykuY247XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhdyhnZCwgaWQpIHtcbiAgICAvLyBvcHRzOiBvcHRpb25zIG9iamVjdCwgY29udGFpbmluZyBldmVyeXRoaW5nIGZyb20gYXR0cmlidXRlc1xuICAgIC8vIHBsdXMgYSBmZXcgb3RoZXJzIHRoYXQgYXJlIHRoZSBlcXVpdmFsZW50IG9mIHRoZSBjb2xvcmJhciBcImRhdGFcIlxuICAgIHZhciBvcHRzID0ge307XG4gICAgZm9yKHZhciBrIGluIGF0dHJpYnV0ZXMpIHtcbiAgICAgICAgb3B0c1trXSA9IG51bGw7XG4gICAgfVxuICAgIC8vIGZpbGxjb2xvciBjYW4gYmUgYSBkMyBzY2FsZSwgZG9tYWluIGlzIHogdmFsdWVzLCByYW5nZSBpcyBjb2xvcnNcbiAgICAvLyBvciBsZWF2ZSBpdCBvdXQgZm9yIG5vIGZpbGwsXG4gICAgLy8gb3Igc2V0IHRvIGEgc3RyaW5nIGNvbnN0YW50IGZvciBzaW5nbGUtY29sb3IgZmlsbFxuICAgIG9wdHMuZmlsbGNvbG9yID0gbnVsbDtcbiAgICAvLyBsaW5lLmNvbG9yIGhhcyB0aGUgc2FtZSBvcHRpb25zIGFzIGZpbGxjb2xvclxuICAgIG9wdHMubGluZSA9IHtjb2xvcjogbnVsbCwgd2lkdGg6IG51bGwsIGRhc2g6IG51bGx9O1xuICAgIC8vIGxldmVscyBvZiBsaW5lcyB0byBkcmF3LlxuICAgIC8vIG5vdGUgdGhhdCB0aGlzIERPRVMgTk9UIGRldGVybWluZSB0aGUgZXh0ZW50IG9mIHRoZSBiYXJcbiAgICAvLyB0aGF0J3MgZ2l2ZW4gYnkgdGhlIGRvbWFpbiBvZiBmaWxsY29sb3JcbiAgICAvLyAob3IgbGluZS5jb2xvciBpZiBubyBmaWxsY29sb3IgZG9tYWluKVxuICAgIG9wdHMubGV2ZWxzID0ge3N0YXJ0OiBudWxsLCBlbmQ6IG51bGwsIHNpemU6IG51bGx9O1xuICAgIC8vIHNlcGFyYXRlIGZpbGwgbGV2ZWxzIChmb3IgZXhhbXBsZSwgaGVhdG1hcCBjb2xvcmluZyBvZiBhXG4gICAgLy8gY29udG91ciBtYXApIGlmIHRoaXMgaXMgb21pdHRlZCwgZmlsbGNvbG9ycyB3aWxsIGJlXG4gICAgLy8gZXZhbHVhdGVkIGhhbGZ3YXkgYmV0d2VlbiBsZXZlbHNcbiAgICBvcHRzLmZpbGxsZXZlbHMgPSBudWxsO1xuICAgIC8vIGZvciBjb250aW51b3VzIGNvbG9yc2NhbGVzOiBmaWxsIHdpdGggYSBncmFkaWVudCBpbnN0ZWFkIG9mIGV4cGxpY2l0IGxldmVsc1xuICAgIC8vIHZhbHVlIHNob3VsZCBiZSB0aGUgY29sb3JzY2FsZSBbWzAsIGMwXSwgW3YxLCBjMV0sIC4uLiwgWzEsIGNFbmRdXVxuICAgIG9wdHMuZmlsbGdyYWRpZW50ID0gbnVsbDtcbiAgICAvLyB3aGVuIHVzaW5nIGEgZ3JhZGllbnQsIHdlIG5lZWQgdGhlIGRhdGEgcmFuZ2Ugc3BlY2lmaWVkIHNlcGFyYXRlbHlcbiAgICBvcHRzLnpyYW5nZSA9IG51bGw7XG5cbiAgICBmdW5jdGlvbiBjb21wb25lbnQoKSB7XG4gICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQsXG4gICAgICAgICAgICBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgICAgIGlmKCh0eXBlb2Ygb3B0cy5maWxsY29sb3IgIT09ICdmdW5jdGlvbicpICYmXG4gICAgICAgICAgICAgICAgKHR5cGVvZiBvcHRzLmxpbmUuY29sb3IgIT09ICdmdW5jdGlvbicpICYmXG4gICAgICAgICAgICAgICAgIW9wdHMuZmlsbGdyYWRpZW50KSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0QWxsKCdnLicgKyBpZCkucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHpyYW5nZSA9IG9wdHMuenJhbmdlIHx8IChkMy5leHRlbnQoKCh0eXBlb2Ygb3B0cy5maWxsY29sb3IgPT09ICdmdW5jdGlvbicpID9cbiAgICAgICAgICAgIG9wdHMuZmlsbGNvbG9yIDogb3B0cy5saW5lLmNvbG9yKS5kb21haW4oKSkpO1xuICAgICAgICB2YXIgbGluZWxldmVscyA9IFtdO1xuICAgICAgICB2YXIgZmlsbGxldmVscyA9IFtdO1xuICAgICAgICB2YXIgbGluZWNvbG9ybWFwID0gdHlwZW9mIG9wdHMubGluZS5jb2xvciA9PT0gJ2Z1bmN0aW9uJyA/XG4gICAgICAgICAgICBvcHRzLmxpbmUuY29sb3IgOiBmdW5jdGlvbigpIHsgcmV0dXJuIG9wdHMubGluZS5jb2xvcjsgfTtcbiAgICAgICAgdmFyIGZpbGxjb2xvcm1hcCA9IHR5cGVvZiBvcHRzLmZpbGxjb2xvciA9PT0gJ2Z1bmN0aW9uJyA/XG4gICAgICAgICAgICBvcHRzLmZpbGxjb2xvciA6IGZ1bmN0aW9uKCkgeyByZXR1cm4gb3B0cy5maWxsY29sb3I7IH07XG4gICAgICAgIHZhciBsO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICB2YXIgbDAgPSBvcHRzLmxldmVscy5lbmQgKyBvcHRzLmxldmVscy5zaXplIC8gMTAwLFxuICAgICAgICAgICAgbHMgPSBvcHRzLmxldmVscy5zaXplLFxuICAgICAgICAgICAgenIwID0gKDEuMDAxICogenJhbmdlWzBdIC0gMC4wMDEgKiB6cmFuZ2VbMV0pLFxuICAgICAgICAgICAgenIxID0gKDEuMDAxICogenJhbmdlWzFdIC0gMC4wMDEgKiB6cmFuZ2VbMF0pO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCAxZTU7IGkrKykge1xuICAgICAgICAgICAgbCA9IG9wdHMubGV2ZWxzLnN0YXJ0ICsgaSAqIGxzO1xuICAgICAgICAgICAgaWYobHMgPiAwID8gKGwgPj0gbDApIDogKGwgPD0gbDApKSBicmVhaztcbiAgICAgICAgICAgIGlmKGwgPiB6cjAgJiYgbCA8IHpyMSkgbGluZWxldmVscy5wdXNoKGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob3B0cy5maWxsZ3JhZGllbnQpIHtcbiAgICAgICAgICAgIGZpbGxsZXZlbHMgPSBbMF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih0eXBlb2Ygb3B0cy5maWxsY29sb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGlmKG9wdHMuZmlsbGxldmVscykge1xuICAgICAgICAgICAgICAgIGwwID0gb3B0cy5maWxsbGV2ZWxzLmVuZCArIG9wdHMuZmlsbGxldmVscy5zaXplIC8gMTAwO1xuICAgICAgICAgICAgICAgIGxzID0gb3B0cy5maWxsbGV2ZWxzLnNpemU7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgMWU1OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbCA9IG9wdHMuZmlsbGxldmVscy5zdGFydCArIGkgKiBscztcbiAgICAgICAgICAgICAgICAgICAgaWYobHMgPiAwID8gKGwgPj0gbDApIDogKGwgPD0gbDApKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgaWYobCA+IHpyYW5nZVswXSAmJiBsIDwgenJhbmdlWzFdKSBmaWxsbGV2ZWxzLnB1c2gobCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZmlsbGxldmVscyA9IGxpbmVsZXZlbHMubWFwKGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHYgLSBvcHRzLmxldmVscy5zaXplIC8gMjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmaWxsbGV2ZWxzLnB1c2goZmlsbGxldmVsc1tmaWxsbGV2ZWxzLmxlbmd0aCAtIDFdICtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5sZXZlbHMuc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihvcHRzLmZpbGxjb2xvciAmJiB0eXBlb2Ygb3B0cy5maWxsY29sb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBkb2Vzbid0IG1hdHRlciB3aGF0IHRoaXMgdmFsdWUgaXMsIHdpdGggYSBzaW5nbGUgdmFsdWVcbiAgICAgICAgICAgIC8vIHdlJ2xsIG1ha2UgYSBzaW5nbGUgZmlsbCByZWN0IGNvdmVyaW5nIHRoZSB3aG9sZSBiYXJcbiAgICAgICAgICAgIGZpbGxsZXZlbHMgPSBbMF07XG4gICAgICAgIH1cblxuICAgICAgICBpZihvcHRzLmxldmVscy5zaXplIDwgMCkge1xuICAgICAgICAgICAgbGluZWxldmVscy5yZXZlcnNlKCk7XG4gICAgICAgICAgICBmaWxsbGV2ZWxzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBtYWtlIGEgUGxvdGx5IEF4ZXMgb2JqZWN0IHRvIHNjYWxlIHdpdGggYW5kIGRyYXcgdGlja3NcbiAgICAgICAgLy8gVE9ETzogZG9lcyBub3Qgc3VwcG9ydCBvcmllbnRhdGlvbiBvdGhlciB0aGFuIHJpZ2h0XG5cbiAgICAgICAgLy8gd2UgY2FsY3VsYXRlIHBpeGVsIHNpemVzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgZ3JhcGggc2l6ZSxcbiAgICAgICAgLy8gbm90IHRoZSBhY3R1YWwgKGluIGNhc2Ugc29tZXRoaW5nIHB1c2hlZCB0aGUgbWFyZ2lucyBhcm91bmQpXG4gICAgICAgIC8vIHdoaWNoIGlzIGEgbGl0dGxlIG9kZCBidXQgYXZvaWRzIGFuIG9kZCBpdGVyYXRpdmUgZWZmZWN0XG4gICAgICAgIC8vIHdoZW4gdGhlIGNvbG9yYmFyIGl0c2VsZiBpcyBwdXNoaW5nIHRoZSBtYXJnaW5zLlxuICAgICAgICAvLyBidXQgdGhlbiB0aGUgZnJhY3Rpb25hbCBzaXplIGlzIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlXG4gICAgICAgIC8vIGFjdHVhbCBncmFwaCBzaXplLCBzbyB0aGF0IHRoZSBheGVzIHdpbGwgc2l6ZSBjb3JyZWN0bHkuXG4gICAgICAgIHZhciBwbG90SGVpZ2h0ID0gZ3MuaCxcbiAgICAgICAgICAgIHBsb3RXaWR0aCA9IGdzLncsXG4gICAgICAgICAgICB0aGlja1B4ID0gTWF0aC5yb3VuZChvcHRzLnRoaWNrbmVzcyAqXG4gICAgICAgICAgICAgICAgKG9wdHMudGhpY2tuZXNzbW9kZSA9PT0gJ2ZyYWN0aW9uJyA/IHBsb3RXaWR0aCA6IDEpKSxcbiAgICAgICAgICAgIHRoaWNrRnJhYyA9IHRoaWNrUHggLyBncy53LFxuICAgICAgICAgICAgbGVuUHggPSBNYXRoLnJvdW5kKG9wdHMubGVuICpcbiAgICAgICAgICAgICAgICAob3B0cy5sZW5tb2RlID09PSAnZnJhY3Rpb24nID8gcGxvdEhlaWdodCA6IDEpKSxcbiAgICAgICAgICAgIGxlbkZyYWMgPSBsZW5QeCAvIGdzLmgsXG4gICAgICAgICAgICB4cGFkRnJhYyA9IG9wdHMueHBhZCAvIGdzLncsXG4gICAgICAgICAgICB5RXh0cmFQeCA9IChvcHRzLmJvcmRlcndpZHRoICsgb3B0cy5vdXRsaW5ld2lkdGgpIC8gMixcbiAgICAgICAgICAgIHlwYWRGcmFjID0gb3B0cy55cGFkIC8gZ3MuaCxcblxuICAgICAgICAgICAgLy8geCBwb3NpdGlvbmluZzogZG8gaXQgaW5pdGlhbGx5IGp1c3QgZm9yIGxlZnQgYW5jaG9yLFxuICAgICAgICAgICAgLy8gdGhlbiBmaXggYXQgdGhlIGVuZCAoc2luY2Ugd2UgZG9uJ3Qga25vdyB0aGUgd2lkdGggeWV0KVxuICAgICAgICAgICAgeExlZnQgPSBNYXRoLnJvdW5kKG9wdHMueCAqIGdzLncgKyBvcHRzLnhwYWQpLFxuICAgICAgICAgICAgLy8gZm9yIGRyYWdnaW5nLi4uIHRoaXMgaXMgZ2V0dGluZyBhIGxpdHRsZSBtdWRkbGVkLi4uXG4gICAgICAgICAgICB4TGVmdEZyYWMgPSBvcHRzLnggLSB0aGlja0ZyYWMgKlxuICAgICAgICAgICAgICAgICh7bWlkZGxlOiAwLjUsIHJpZ2h0OiAxfVtvcHRzLnhhbmNob3JdfHwwKSxcblxuICAgICAgICAgICAgLy8geSBwb3NpdGlvbmluZyB3ZSBjYW4gZG8gY29ycmVjdGx5IGZyb20gdGhlIHN0YXJ0XG4gICAgICAgICAgICB5Qm90dG9tRnJhYyA9IG9wdHMueSArIGxlbkZyYWMgKlxuICAgICAgICAgICAgICAgICgoe3RvcDogLTAuNSwgYm90dG9tOiAwLjV9W29wdHMueWFuY2hvcl0gfHwgMCkgLSAwLjUpLFxuICAgICAgICAgICAgeUJvdHRvbVB4ID0gTWF0aC5yb3VuZChncy5oICogKDEgLSB5Qm90dG9tRnJhYykpLFxuICAgICAgICAgICAgeVRvcFB4ID0geUJvdHRvbVB4IC0gbGVuUHgsXG4gICAgICAgICAgICB0aXRsZUVsLFxuICAgICAgICAgICAgY2JBeGlzSW4gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgICAgICAgICAgcmFuZ2U6IHpyYW5nZSxcbiAgICAgICAgICAgICAgICB0aWNrbW9kZTogb3B0cy50aWNrbW9kZSxcbiAgICAgICAgICAgICAgICBudGlja3M6IG9wdHMubnRpY2tzLFxuICAgICAgICAgICAgICAgIHRpY2swOiBvcHRzLnRpY2swLFxuICAgICAgICAgICAgICAgIGR0aWNrOiBvcHRzLmR0aWNrLFxuICAgICAgICAgICAgICAgIHRpY2t2YWxzOiBvcHRzLnRpY2t2YWxzLFxuICAgICAgICAgICAgICAgIHRpY2t0ZXh0OiBvcHRzLnRpY2t0ZXh0LFxuICAgICAgICAgICAgICAgIHRpY2tzOiBvcHRzLnRpY2tzLFxuICAgICAgICAgICAgICAgIHRpY2tsZW46IG9wdHMudGlja2xlbixcbiAgICAgICAgICAgICAgICB0aWNrd2lkdGg6IG9wdHMudGlja3dpZHRoLFxuICAgICAgICAgICAgICAgIHRpY2tjb2xvcjogb3B0cy50aWNrY29sb3IsXG4gICAgICAgICAgICAgICAgc2hvd3RpY2tsYWJlbHM6IG9wdHMuc2hvd3RpY2tsYWJlbHMsXG4gICAgICAgICAgICAgICAgdGlja2ZvbnQ6IG9wdHMudGlja2ZvbnQsXG4gICAgICAgICAgICAgICAgdGlja2FuZ2xlOiBvcHRzLnRpY2thbmdsZSxcbiAgICAgICAgICAgICAgICB0aWNrZm9ybWF0OiBvcHRzLnRpY2tmb3JtYXQsXG4gICAgICAgICAgICAgICAgZXhwb25lbnRmb3JtYXQ6IG9wdHMuZXhwb25lbnRmb3JtYXQsXG4gICAgICAgICAgICAgICAgc2VwYXJhdGV0aG91c2FuZHM6IG9wdHMuc2VwYXJhdGV0aG91c2FuZHMsXG4gICAgICAgICAgICAgICAgc2hvd2V4cG9uZW50OiBvcHRzLnNob3dleHBvbmVudCxcbiAgICAgICAgICAgICAgICBzaG93dGlja3ByZWZpeDogb3B0cy5zaG93dGlja3ByZWZpeCxcbiAgICAgICAgICAgICAgICB0aWNrcHJlZml4OiBvcHRzLnRpY2twcmVmaXgsXG4gICAgICAgICAgICAgICAgc2hvd3RpY2tzdWZmaXg6IG9wdHMuc2hvd3RpY2tzdWZmaXgsXG4gICAgICAgICAgICAgICAgdGlja3N1ZmZpeDogb3B0cy50aWNrc3VmZml4LFxuICAgICAgICAgICAgICAgIHRpdGxlOiBvcHRzLnRpdGxlLFxuICAgICAgICAgICAgICAgIHRpdGxlZm9udDogb3B0cy50aXRsZWZvbnQsXG4gICAgICAgICAgICAgICAgc2hvd2xpbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IDFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjYkF4aXNPdXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgICAgICAgICAgX2lkOiAneScgKyBpZFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGF4aXNPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGxldHRlcjogJ3knLFxuICAgICAgICAgICAgICAgIGZvbnQ6IGZ1bGxMYXlvdXQuZm9udCxcbiAgICAgICAgICAgICAgICBub0hvdmVyOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbGVuZGFyOiBmdWxsTGF5b3V0LmNhbGVuZGFyICAvLyBub3QgcmVhbGx5IG5lY2Vzc2FyeSAoeWV0PylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgLy8gQ29lcmNlIHcuci50LiBBeGVzIGxheW91dEF0dHJpYnV0ZXM6XG4gICAgICAgIC8vIHJlLXVzZSBheGVzLmpzIGxvZ2ljIHdpdGhvdXQgdXBkYXRpbmcgX2Z1bGxEYXRhXG4gICAgICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjYkF4aXNJbiwgY2JBeGlzT3V0LCBheGlzTGF5b3V0QXR0cnMsIGF0dHIsIGRmbHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJlcGFyZSB0aGUgUGxvdGx5IGF4aXMgb2JqZWN0XG4gICAgICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhjYkF4aXNJbiwgY2JBeGlzT3V0LCBjb2VyY2UsIGF4aXNPcHRpb25zLCBmdWxsTGF5b3V0KTtcbiAgICAgICAgaGFuZGxlQXhpc1Bvc2l0aW9uRGVmYXVsdHMoY2JBeGlzSW4sIGNiQXhpc091dCwgY29lcmNlLCBheGlzT3B0aW9ucyk7XG5cbiAgICAgICAgLy8gcG9zaXRpb24gY2FuJ3QgZ28gaW4gdGhyb3VnaCBzdXBwbHlEZWZhdWx0c1xuICAgICAgICAvLyBiZWNhdXNlIHRoYXQgcmVzdHJpY3RzIGl0IHRvIFswLDFdXG4gICAgICAgIGNiQXhpc091dC5wb3NpdGlvbiA9IG9wdHMueCArIHhwYWRGcmFjICsgdGhpY2tGcmFjO1xuXG4gICAgICAgIC8vIHNhdmUgZm9yIG90aGVyIGNhbGxlcnMgdG8gYWNjZXNzIHRoaXMgYXhpc1xuICAgICAgICBjb21wb25lbnQuYXhpcyA9IGNiQXhpc091dDtcblxuICAgICAgICBpZihbJ3RvcCcsICdib3R0b20nXS5pbmRleE9mKG9wdHMudGl0bGVzaWRlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNiQXhpc091dC50aXRsZXNpZGUgPSBvcHRzLnRpdGxlc2lkZTtcbiAgICAgICAgICAgIGNiQXhpc091dC50aXRsZXggPSBvcHRzLnggKyB4cGFkRnJhYztcbiAgICAgICAgICAgIGNiQXhpc091dC50aXRsZXkgPSB5Qm90dG9tRnJhYyArXG4gICAgICAgICAgICAgICAgKG9wdHMudGl0bGVzaWRlID09PSAndG9wJyA/IGxlbkZyYWMgLSB5cGFkRnJhYyA6IHlwYWRGcmFjKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9wdHMubGluZS5jb2xvciAmJiBvcHRzLnRpY2ttb2RlID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIGNiQXhpc091dC50aWNrbW9kZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgY2JBeGlzT3V0LnRpY2swID0gb3B0cy5sZXZlbHMuc3RhcnQ7XG4gICAgICAgICAgICB2YXIgZHRpY2sgPSBvcHRzLmxldmVscy5zaXplO1xuICAgICAgICAgICAgLy8gZXhwYW5kIGlmIHRvbyBtYW55IGNvbnRvdXJzLCBzbyB3ZSBkb24ndCBnZXQgdG9vIG1hbnkgdGlja3NcbiAgICAgICAgICAgIHZhciBhdXRvTnRpY2sgPSBMaWIuY29uc3RyYWluKFxuICAgICAgICAgICAgICAgICAgICAoeUJvdHRvbVB4IC0geVRvcFB4KSAvIDUwLCA0LCAxNSkgKyAxLFxuICAgICAgICAgICAgICAgIGR0RmFjdG9yID0gKHpyYW5nZVsxXSAtIHpyYW5nZVswXSkgL1xuICAgICAgICAgICAgICAgICAgICAoKG9wdHMubnRpY2tzIHx8IGF1dG9OdGljaykgKiBkdGljayk7XG4gICAgICAgICAgICBpZihkdEZhY3RvciA+IDEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZHRleHAgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5sb2coZHRGYWN0b3IpIC8gTWF0aC5MTjEwKSk7XG4gICAgICAgICAgICAgICAgZHRpY2sgKj0gZHRleHAgKiBMaWIucm91bmRVcChkdEZhY3RvciAvIGR0ZXhwLCBbMiwgNSwgMTBdKTtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgY29udG91cnMgYXJlIGF0IHJvdW5kIG11bHRpcGxlcywgcmVzZXQgdGljazBcbiAgICAgICAgICAgICAgICAvLyBzbyB0aGV5J3JlIHN0aWxsIGF0IHJvdW5kIG11bHRpcGxlcy4gT3RoZXJ3aXNlLFxuICAgICAgICAgICAgICAgIC8vIGtlZXAgdGhlIGZpcnN0IGxhYmVsIG9uIHRoZSBmaXJzdCBjb250b3VyIGxldmVsXG4gICAgICAgICAgICAgICAgaWYoKE1hdGguYWJzKG9wdHMubGV2ZWxzLnN0YXJ0KSAvXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmxldmVscy5zaXplICsgMWUtNikgJSAxIDwgMmUtNikge1xuICAgICAgICAgICAgICAgICAgICBjYkF4aXNPdXQudGljazAgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNiQXhpc091dC5kdGljayA9IGR0aWNrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2V0IGRvbWFpbiBhZnRlciBpbml0LCBiZWNhdXNlIHdlIG1heSB3YW50IHRvXG4gICAgICAgIC8vIGFsbG93IGl0IG91dHNpZGUgWzAsMV1cbiAgICAgICAgY2JBeGlzT3V0LmRvbWFpbiA9IFtcbiAgICAgICAgICAgIHlCb3R0b21GcmFjICsgeXBhZEZyYWMsXG4gICAgICAgICAgICB5Qm90dG9tRnJhYyArIGxlbkZyYWMgLSB5cGFkRnJhY1xuICAgICAgICBdO1xuICAgICAgICBjYkF4aXNPdXQuc2V0U2NhbGUoKTtcblxuICAgICAgICAvLyBub3cgZHJhdyB0aGUgZWxlbWVudHNcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IExpYi5lbnN1cmVTaW5nbGUoZnVsbExheW91dC5faW5mb2xheWVyLCAnZycsIGlkLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICBzLmNsYXNzZWQoY24uY29sb3JiYXIsIHRydWUpXG4gICAgICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBzLmFwcGVuZCgncmVjdCcpLmNsYXNzZWQoY24uY2JiZywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdnJykuY2xhc3NlZChjbi5jYmZpbGxzLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgcy5hcHBlbmQoJ2cnKS5jbGFzc2VkKGNuLmNibGluZXMsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzLmFwcGVuZCgnZycpLmNsYXNzZWQoY24uY2JheGlzLCB0cnVlKS5jbGFzc2VkKGNuLmNyaXNwLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgcy5hcHBlbmQoJ2cnKS5jbGFzc2VkKGNuLmNidGl0bGV1bnNoaWZ0LCB0cnVlKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgnZycpLmNsYXNzZWQoY24uY2J0aXRsZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdyZWN0JykuY2xhc3NlZChjbi5jYm91dGxpbmUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzLnNlbGVjdCgnLmNidGl0bGUnKS5kYXR1bSgwKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29udGFpbmVyLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIE1hdGgucm91bmQoZ3MubCkgK1xuICAgICAgICAgICAgJywnICsgTWF0aC5yb3VuZChncy50KSArICcpJyk7XG4gICAgICAgIC8vIFRPRE86IHRoaXMgb3Bwb3NpdGUgdHJhbnNmb3JtIGlzIGEgaGFjayB1bnRpbCB3ZSBtYWtlIGl0XG4gICAgICAgIC8vIG1vcmUgcmF0aW9uYWwgd2hpY2ggaXRlbXMgZ2V0IHRoaXMgb2Zmc2V0XG4gICAgICAgIHZhciB0aXRsZUNvbnQgPSBjb250YWluZXIuc2VsZWN0KCcuY2J0aXRsZXVuc2hpZnQnKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoLScgK1xuICAgICAgICAgICAgICAgIE1hdGgucm91bmQoZ3MubCkgKyAnLC0nICtcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKGdzLnQpICsgJyknKTtcblxuICAgICAgICBjYkF4aXNPdXQuX2F4aXNsYXllciA9IGNvbnRhaW5lci5zZWxlY3QoJy5jYmF4aXMnKTtcbiAgICAgICAgdmFyIHRpdGxlSGVpZ2h0ID0gMDtcbiAgICAgICAgaWYoWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZihvcHRzLnRpdGxlc2lkZSkgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBkcmF3IHRoZSB0aXRsZSBzbyB3ZSBrbm93IGhvdyBtdWNoIHJvb20gaXQgbmVlZHNcbiAgICAgICAgICAgIC8vIHdoZW4gd2Ugc3F1aXNoIHRoZSBheGlzLiBUaGlzIG9uZSBvbmx5IGFwcGxpZXMgdG9cbiAgICAgICAgICAgIC8vIHRvcCBvciBib3R0b20gdGl0bGVzLCBub3QgcmlnaHQgc2lkZS5cbiAgICAgICAgICAgIHZhciB4ID0gZ3MubCArIChvcHRzLnggKyB4cGFkRnJhYykgKiBncy53LFxuICAgICAgICAgICAgICAgIGZvbnRTaXplID0gY2JBeGlzT3V0LnRpdGxlZm9udC5zaXplLFxuICAgICAgICAgICAgICAgIHk7XG5cbiAgICAgICAgICAgIGlmKG9wdHMudGl0bGVzaWRlID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIHkgPSAoMSAtICh5Qm90dG9tRnJhYyArIGxlbkZyYWMgLSB5cGFkRnJhYykpICogZ3MuaCArXG4gICAgICAgICAgICAgICAgICAgIGdzLnQgKyAzICsgZm9udFNpemUgKiAwLjc1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgeSA9ICgxIC0gKHlCb3R0b21GcmFjICsgeXBhZEZyYWMpKSAqIGdzLmggK1xuICAgICAgICAgICAgICAgICAgICBncy50IC0gMyAtIGZvbnRTaXplICogMC4yNTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRyYXdUaXRsZShjYkF4aXNPdXQuX2lkICsgJ3RpdGxlJywge1xuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHt4OiB4LCB5OiB5LCAndGV4dC1hbmNob3InOiAnc3RhcnQnfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBkcmF3QXhpcygpIHtcbiAgICAgICAgICAgIGlmKFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2Yob3B0cy50aXRsZXNpZGUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIC8vIHNxdWlzaCB0aGUgYXhpcyB0b3AgdG8gbWFrZSByb29tIGZvciB0aGUgdGl0bGVcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGVHcm91cCA9IGNvbnRhaW5lci5zZWxlY3QoJy5jYnRpdGxlJyksXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlVGV4dCA9IHRpdGxlR3JvdXAuc2VsZWN0KCd0ZXh0JyksXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlVHJhbnMgPVxuICAgICAgICAgICAgICAgICAgICAgICAgWy1vcHRzLm91dGxpbmV3aWR0aCAvIDIsIG9wdHMub3V0bGluZXdpZHRoIC8gMl0sXG4gICAgICAgICAgICAgICAgICAgIG1hdGhKYXhOb2RlID0gdGl0bGVHcm91cFxuICAgICAgICAgICAgICAgICAgICAgICAgLnNlbGVjdCgnLmgnICsgY2JBeGlzT3V0Ll9pZCArICd0aXRsZS1tYXRoLWdyb3VwJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgIGxpbmVTaXplID0gMTUuNjtcbiAgICAgICAgICAgICAgICBpZih0aXRsZVRleHQubm9kZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmVTaXplID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlSW50KHRpdGxlVGV4dC5ub2RlKCkuc3R5bGUuZm9udFNpemUsIDEwKSAqIExJTkVfU1BBQ0lORztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYobWF0aEpheE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVIZWlnaHQgPSBEcmF3aW5nLmJCb3gobWF0aEpheE5vZGUpLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgaWYodGl0bGVIZWlnaHQgPiBsaW5lU2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90IGVudGlyZWx5IHN1cmUgaG93IG1hdGhqYXggaXMgZG9pbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHZlcnRpY2FsIGFsaWdubWVudCwgYnV0IHRoaXMgc2VlbXMgdG8gd29yay5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlVHJhbnNbMV0gLT0gKHRpdGxlSGVpZ2h0IC0gbGluZVNpemUpIC8gMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKHRpdGxlVGV4dC5ub2RlKCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICF0aXRsZVRleHQuY2xhc3NlZChjbi5qc1BsYWNlaG9sZGVyKSkge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZUhlaWdodCA9IERyYXdpbmcuYkJveCh0aXRsZVRleHQubm9kZSgpKS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHRpdGxlSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1ZmZlciBidHduIGNvbG9yYmFyIGFuZCB0aXRsZVxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBjb25maWd1cmFibGVcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVIZWlnaHQgKz0gNTtcblxuICAgICAgICAgICAgICAgICAgICBpZihvcHRzLnRpdGxlc2lkZSA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNiQXhpc091dC5kb21haW5bMV0gLT0gdGl0bGVIZWlnaHQgLyBncy5oO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGVUcmFuc1sxXSAqPSAtMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNiQXhpc091dC5kb21haW5bMF0gKz0gdGl0bGVIZWlnaHQgLyBncy5oO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5saW5lcyA9IHN2Z1RleHRVdGlscy5saW5lQ291bnQodGl0bGVUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlVHJhbnNbMV0gKz0gKDEgLSBubGluZXMpICogbGluZVNpemU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aXRsZUdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB0aXRsZVRyYW5zICsgJyknKTtcblxuICAgICAgICAgICAgICAgICAgICBjYkF4aXNPdXQuc2V0U2NhbGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJy5jYmZpbGxzLC5jYmxpbmVzJylcbiAgICAgICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcgK1xuICAgICAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKGdzLmggKiAoMSAtIGNiQXhpc091dC5kb21haW5bMV0pKSArICcpJyk7XG5cbiAgICAgICAgICAgIGNiQXhpc091dC5fYXhpc2xheWVyLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwnICtcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKC1ncy50KSArICcpJyk7XG5cbiAgICAgICAgICAgIHZhciBmaWxscyA9IGNvbnRhaW5lci5zZWxlY3QoJy5jYmZpbGxzJylcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCdyZWN0LmNiZmlsbCcpXG4gICAgICAgICAgICAgICAgICAgIC5kYXRhKGZpbGxsZXZlbHMpO1xuICAgICAgICAgICAgZmlsbHMuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKGNuLmNiZmlsbCwgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZScsICdub25lJyk7XG4gICAgICAgICAgICBmaWxscy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIHZhciB6Qm91bmRzID0genJhbmdlXG4gICAgICAgICAgICAgICAgLm1hcChjYkF4aXNPdXQuYzJwKVxuICAgICAgICAgICAgICAgIC5tYXAoTWF0aC5yb3VuZClcbiAgICAgICAgICAgICAgICAuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhIC0gYjsgfSk7XG5cbiAgICAgICAgICAgIGZpbGxzLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciB6ID0gW1xuICAgICAgICAgICAgICAgICAgICAoaSA9PT0gMCkgPyB6cmFuZ2VbMF0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgKGZpbGxsZXZlbHNbaV0gKyBmaWxsbGV2ZWxzW2kgLSAxXSkgLyAyLFxuICAgICAgICAgICAgICAgICAgICAoaSA9PT0gZmlsbGxldmVscy5sZW5ndGggLSAxKSA/IHpyYW5nZVsxXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAoZmlsbGxldmVsc1tpXSArIGZpbGxsZXZlbHNbaSArIDFdKSAvIDJcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgLm1hcChjYkF4aXNPdXQuYzJwKVxuICAgICAgICAgICAgICAgIC5tYXAoTWF0aC5yb3VuZCk7XG5cbiAgICAgICAgICAgICAgICAvLyBvZmZzZXQgdGhlIHNpZGUgYWRqb2luaW5nIHRoZSBuZXh0IHJlY3RhbmdsZSBzbyB0aGV5XG4gICAgICAgICAgICAgICAgLy8gb3ZlcmxhcCwgdG8gcHJldmVudCBhbnRpYWxpYXNpbmcgZ2Fwc1xuICAgICAgICAgICAgICAgIHpbMV0gPSBMaWIuY29uc3RyYWluKHpbMV0gKyAoelsxXSA+IHpbMF0pID8gMSA6IC0xLCB6Qm91bmRzWzBdLCB6Qm91bmRzWzFdKTtcblxuICAgICAgICAgICAgICAgIC8vIENvbG9yYmFyIGNhbm5vdCBjdXJyZW50bHkgc3VwcG9ydCBvcGFjaXRpZXMgc28gd2VcbiAgICAgICAgICAgICAgICAvLyB1c2UgYW4gb3BhcXVlIGZpbGwgZXZlbiB3aGVuIGFscGhhIGNoYW5uZWxzIHByZXNlbnRcbiAgICAgICAgICAgICAgICB2YXIgZmlsbEVsID0gZDMuc2VsZWN0KHRoaXMpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB4OiB4TGVmdCxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IE1hdGgubWF4KHRoaWNrUHgsIDIpLFxuICAgICAgICAgICAgICAgICAgICB5OiBkMy5taW4oeiksXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoZDMubWF4KHopIC0gZDMubWluKHopLCAyKSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmKG9wdHMuZmlsbGdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuZ3JhZGllbnQoZmlsbEVsLCBnZCwgaWQsICd2ZXJ0aWNhbCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmZpbGxncmFkaWVudCwgJ2ZpbGwnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRpbnljb2xvciBjYW4ndCBoYW5kbGUgZXhwb25lbnRzIGFuZFxuICAgICAgICAgICAgICAgICAgICAvLyBhdCB0aGlzIHNjYWxlLCByZW1vdmluZyBpdCBtYWtlcyBubyBkaWZmZXJlbmNlLlxuICAgICAgICAgICAgICAgICAgICB2YXIgY29sb3JTdHJpbmcgPSBmaWxsY29sb3JtYXAoZCkucmVwbGFjZSgnZS0nLCAnJyk7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxFbC5hdHRyKCdmaWxsJywgdGlueWNvbG9yKGNvbG9yU3RyaW5nKS50b0hleFN0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIGxpbmVzID0gY29udGFpbmVyLnNlbGVjdCgnLmNibGluZXMnKVxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJ3BhdGguY2JsaW5lJylcbiAgICAgICAgICAgICAgICAgICAgLmRhdGEob3B0cy5saW5lLmNvbG9yICYmIG9wdHMubGluZS53aWR0aCA/XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lbGV2ZWxzIDogW10pO1xuICAgICAgICAgICAgbGluZXMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKGNuLmNibGluZSwgdHJ1ZSk7XG4gICAgICAgICAgICBsaW5lcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICBsaW5lcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCAnTScgKyB4TGVmdCArICcsJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAoTWF0aC5yb3VuZChjYkF4aXNPdXQuYzJwKGQpKSArIChvcHRzLmxpbmUud2lkdGggLyAyKSAlIDEpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdoJyArIHRoaWNrUHgpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcubGluZUdyb3VwU3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmxpbmUud2lkdGgsIGxpbmVjb2xvcm1hcChkKSwgb3B0cy5saW5lLmRhc2gpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGZvcmNlIGZ1bGwgcmVkcmF3IG9mIGxhYmVscyBhbmQgdGlja3NcbiAgICAgICAgICAgIGNiQXhpc091dC5fYXhpc2xheWVyLnNlbGVjdEFsbCgnZy4nICsgY2JBeGlzT3V0Ll9pZCArICd0aWNrLHBhdGgnKVxuICAgICAgICAgICAgICAgIC5yZW1vdmUoKTtcblxuICAgICAgICAgICAgY2JBeGlzT3V0Ll9wb3MgPSB4TGVmdCArIHRoaWNrUHggK1xuICAgICAgICAgICAgICAgIChvcHRzLm91dGxpbmV3aWR0aHx8MCkgLyAyIC0gKG9wdHMudGlja3MgPT09ICdvdXRzaWRlJyA/IDEgOiAwKTtcbiAgICAgICAgICAgIGNiQXhpc091dC5zaWRlID0gJ3JpZ2h0JztcblxuICAgICAgICAgICAgLy8gc2VwYXJhdGUgb3V0IGF4aXMgYW5kIHRpdGxlIGRyYXdpbmcsXG4gICAgICAgICAgICAvLyBzbyB3ZSBkb24ndCBuZWVkIHN1Y2ggY29tcGxpY2F0ZWQgbG9naWMgaW4gVGl0bGVzLmRyYXdcbiAgICAgICAgICAgIC8vIGlmIHRpdGxlIGlzIG9uIHRoZSB0b3Agb3IgYm90dG9tLCB3ZSd2ZSBhbHJlYWR5IGRyYXduIGl0XG4gICAgICAgICAgICAvLyB0aGlzIHRpdGxlIGNhbGwgb25seSBoYW5kbGVzIHNpZGU9cmlnaHRcbiAgICAgICAgICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gQXhlcy5kb1RpY2tzU2luZ2xlKGdkLCBjYkF4aXNPdXQsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2Yob3B0cy50aXRsZXNpZGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZvbnRTaXplID0gY2JBeGlzT3V0LnRpdGxlZm9udC5zaXplLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBjYkF4aXNPdXQuX29mZnNldCArIGNiQXhpc091dC5fbGVuZ3RoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gZ3MubCArIChjYkF4aXNPdXQucG9zaXRpb24gfHwgMCkgKiBncy53ICsgKChjYkF4aXNPdXQuc2lkZSA9PT0gJ3JpZ2h0JykgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMCArIGZvbnRTaXplICogKChjYkF4aXNPdXQuc2hvd3RpY2tsYWJlbHMgPyAxIDogMC41KSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtMTAgLSBmb250U2l6ZSAqICgoY2JBeGlzT3V0LnNob3d0aWNrbGFiZWxzID8gMC41IDogMCkpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlICdoJyArIGlzIGEgaGFjayB0byBnZXQgYXJvdW5kIHRoZSBmYWN0IHRoYXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnZlcnRUb1RzcGFucyByb3RhdGVzIGFueSAneS4uLicgY2xhc3MgYnkgOTAgZGVncmVlcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGZpbmQgYSBiZXR0ZXIgd2F5IHRvIGNvbnRyb2wgdGhpcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdUaXRsZSgnaCcgKyBjYkF4aXNPdXQuX2lkICsgJ3RpdGxlJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2b2lkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbjogZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cuJyArIGNiQXhpc091dC5faWQgKyAndGljaycpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWRlOiBvcHRzLnRpdGxlc2lkZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0TGVmdDogZ3MubCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0VG9wOiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhTaGlmdDogZnVsbExheW91dC53aWR0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0cmlidXRlczoge3g6IHgsIHk6IHksICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHtyb3RhdGU6ICctOTAnLCBvZmZzZXQ6IDB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGRyYXdUaXRsZSh0aXRsZUNsYXNzLCB0aXRsZU9wdHMpIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGdldFRyYWNlKCk7XG4gICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSAnY29sb3JiYXIudGl0bGUnO1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lck5hbWUgPSB0cmFjZS5fbW9kdWxlLmNvbG9yYmFyLmNvbnRhaW5lcjtcbiAgICAgICAgICAgIGlmKGNvbnRhaW5lck5hbWUpIHByb3BOYW1lID0gY29udGFpbmVyTmFtZSArICcuJyArIHByb3BOYW1lO1xuXG4gICAgICAgICAgICB2YXIgZGZsdFRpdGxlT3B0cyA9IHtcbiAgICAgICAgICAgICAgICBwcm9wQ29udGFpbmVyOiBjYkF4aXNPdXQsXG4gICAgICAgICAgICAgICAgcHJvcE5hbWU6IHByb3BOYW1lLFxuICAgICAgICAgICAgICAgIHRyYWNlSW5kZXg6IHRyYWNlLmluZGV4LFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBmdWxsTGF5b3V0Ll9kZmx0VGl0bGUuY29sb3JiYXIsXG4gICAgICAgICAgICAgICAgY29udGFpbmVyR3JvdXA6IGNvbnRhaW5lci5zZWxlY3QoJy5jYnRpdGxlJylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIHRoaXMgY2xhc3MtdG8tcm90YXRlIHRoaW5nIHdpdGggY29udmVydFRvVHNwYW5zIGlzXG4gICAgICAgICAgICAvLyBnZXR0aW5nIGhhY2tpZXIgYW5kIGhhY2tpZXIuLi4gZGVsZXRlIGdyb3VwcyB3aXRoIHRoZVxuICAgICAgICAgICAgLy8gd3JvbmcgY2xhc3MgKGluIGNhc2UgZWFybGllciB0aGUgY29sb3JiYXIgd2FzIGRyYXduIG9uXG4gICAgICAgICAgICAvLyBhIGRpZmZlcmVudCBzaWRlLCBJIHRoaW5rPylcbiAgICAgICAgICAgIHZhciBvdGhlckNsYXNzID0gdGl0bGVDbGFzcy5jaGFyQXQoMCkgPT09ICdoJyA/XG4gICAgICAgICAgICAgICAgdGl0bGVDbGFzcy5zdWJzdHIoMSkgOiAoJ2gnICsgdGl0bGVDbGFzcyk7XG4gICAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCcuJyArIG90aGVyQ2xhc3MgKyAnLC4nICsgb3RoZXJDbGFzcyArICctbWF0aC1ncm91cCcpXG4gICAgICAgICAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICBUaXRsZXMuZHJhdyhnZCwgdGl0bGVDbGFzcyxcbiAgICAgICAgICAgICAgICBleHRlbmRGbGF0KGRmbHRUaXRsZU9wdHMsIHRpdGxlT3B0cyB8fCB7fSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcG9zaXRpb25DQigpIHtcbiAgICAgICAgICAgIC8vIHdhaXQgZm9yIHRoZSBheGlzICYgdGl0bGUgdG8gZmluaXNoIHJlbmRlcmluZyBiZWZvcmVcbiAgICAgICAgICAgIC8vIGNvbnRpbnVpbmcgcG9zaXRpb25pbmdcbiAgICAgICAgICAgIC8vIFRPRE86IHdoeSBhcmUgd2UgcmVkcmF3aW5nIG11bHRpcGxlIHRpbWVzIG5vdyB3aXRoIHRoaXM/XG4gICAgICAgICAgICAvLyBJIGd1ZXNzIGF1dG9NYXJnaW4gZG9lc24ndCBsaWtlIGJlaW5nIHBvc3QtcHJvbWlzZT9cbiAgICAgICAgICAgIHZhciBpbm5lcldpZHRoID0gdGhpY2tQeCArIG9wdHMub3V0bGluZXdpZHRoIC8gMiArXG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuYkJveChjYkF4aXNPdXQuX2F4aXNsYXllci5ub2RlKCkpLndpZHRoO1xuICAgICAgICAgICAgdGl0bGVFbCA9IHRpdGxlQ29udC5zZWxlY3QoJ3RleHQnKTtcbiAgICAgICAgICAgIGlmKHRpdGxlRWwubm9kZSgpICYmICF0aXRsZUVsLmNsYXNzZWQoY24uanNQbGFjZWhvbGRlcikpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF0aEpheE5vZGUgPSB0aXRsZUNvbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zZWxlY3QoJy5oJyArIGNiQXhpc091dC5faWQgKyAndGl0bGUtbWF0aC1ncm91cCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAubm9kZSgpLFxuICAgICAgICAgICAgICAgICAgICB0aXRsZVdpZHRoO1xuICAgICAgICAgICAgICAgIGlmKG1hdGhKYXhOb2RlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBbJ3RvcCcsICdib3R0b20nXS5pbmRleE9mKG9wdHMudGl0bGVzaWRlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVXaWR0aCA9IERyYXdpbmcuYkJveChtYXRoSmF4Tm9kZSkud2lkdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBub3RlOiB0aGUgZm9ybXVsYSBiZWxvdyB3b3JrcyBmb3IgYWxsIHRpdGxlc2lkZXMsXG4gICAgICAgICAgICAgICAgICAgIC8vIChleGNlcHQgZm9yIHRvcC9ib3R0b20gbWF0aGpheCwgYWJvdmUpXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCB0aGUgd2VpcmQgZ3MubCBpcyBiZWNhdXNlIHRoZSB0aXRsZXVuc2hpZnRcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJhbnNmb3JtIGdldHMgcmVtb3ZlZCBieSBEcmF3aW5nLmJCb3hcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVXaWR0aCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBEcmF3aW5nLmJCb3godGl0bGVDb250Lm5vZGUoKSkucmlnaHQgLVxuICAgICAgICAgICAgICAgICAgICAgICAgeExlZnQgLSBncy5sO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpbm5lcldpZHRoID0gTWF0aC5tYXgoaW5uZXJXaWR0aCwgdGl0bGVXaWR0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBvdXRlcndpZHRoID0gMiAqIG9wdHMueHBhZCArIGlubmVyV2lkdGggK1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmJvcmRlcndpZHRoICsgb3B0cy5vdXRsaW5ld2lkdGggLyAyLFxuICAgICAgICAgICAgICAgIG91dGVyaGVpZ2h0ID0geUJvdHRvbVB4IC0geVRvcFB4O1xuXG4gICAgICAgICAgICBjb250YWluZXIuc2VsZWN0KCcuY2JiZycpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHg6IHhMZWZ0IC0gb3B0cy54cGFkIC1cbiAgICAgICAgICAgICAgICAgICAgKG9wdHMuYm9yZGVyd2lkdGggKyBvcHRzLm91dGxpbmV3aWR0aCkgLyAyLFxuICAgICAgICAgICAgICAgIHk6IHlUb3BQeCAtIHlFeHRyYVB4LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBNYXRoLm1heChvdXRlcndpZHRoLCAyKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KG91dGVyaGVpZ2h0ICsgMiAqIHlFeHRyYVB4LCAyKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIG9wdHMuYmdjb2xvcilcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgb3B0cy5ib3JkZXJjb2xvcilcbiAgICAgICAgICAgIC5zdHlsZSh7J3N0cm9rZS13aWR0aCc6IG9wdHMuYm9yZGVyd2lkdGh9KTtcblxuICAgICAgICAgICAgY29udGFpbmVyLnNlbGVjdEFsbCgnLmNib3V0bGluZScpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHg6IHhMZWZ0LFxuICAgICAgICAgICAgICAgIHk6IHlUb3BQeCArIG9wdHMueXBhZCArXG4gICAgICAgICAgICAgICAgICAgIChvcHRzLnRpdGxlc2lkZSA9PT0gJ3RvcCcgPyB0aXRsZUhlaWdodCA6IDApLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBNYXRoLm1heCh0aGlja1B4LCAyKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KG91dGVyaGVpZ2h0IC0gMiAqIG9wdHMueXBhZCAtIHRpdGxlSGVpZ2h0LCAyKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgb3B0cy5vdXRsaW5lY29sb3IpXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgIGZpbGw6ICdOb25lJyxcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogb3B0cy5vdXRsaW5ld2lkdGhcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBmaXggcG9zaXRpb25pbmcgZm9yIHhhbmNob3IhPSdsZWZ0J1xuICAgICAgICAgICAgdmFyIHhvZmZzZXQgPSAoe2NlbnRlcjogMC41LCByaWdodDogMX1bb3B0cy54YW5jaG9yXSB8fCAwKSAqXG4gICAgICAgICAgICAgICAgb3V0ZXJ3aWR0aDtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIChncy5sIC0geG9mZnNldCkgKyAnLCcgKyBncy50ICsgJyknKTtcblxuICAgICAgICAgICAgLy8gYXV0byBtYXJnaW4gYWRqdXN0bWVudFxuICAgICAgICAgICAgdmFyIG1hcmdpbk9wdHMgPSB7fTtcbiAgICAgICAgICAgIHZhciB0RnJhYyA9IEZST01fVExbb3B0cy55YW5jaG9yXTtcbiAgICAgICAgICAgIHZhciBiRnJhYyA9IEZST01fQlJbb3B0cy55YW5jaG9yXTtcbiAgICAgICAgICAgIGlmKG9wdHMubGVubW9kZSA9PT0gJ3BpeGVscycpIHtcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLnkgPSBvcHRzLnk7XG4gICAgICAgICAgICAgICAgbWFyZ2luT3B0cy50ID0gb3V0ZXJoZWlnaHQgKiB0RnJhYztcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLmIgPSBvdXRlcmhlaWdodCAqIGJGcmFjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbWFyZ2luT3B0cy50ID0gbWFyZ2luT3B0cy5iID0gMDtcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLnl0ID0gb3B0cy55ICsgb3B0cy5sZW4gKiB0RnJhYztcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLnliID0gb3B0cy55IC0gb3B0cy5sZW4gKiBiRnJhYztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGxGcmFjID0gRlJPTV9UTFtvcHRzLnhhbmNob3JdO1xuICAgICAgICAgICAgdmFyIHJGcmFjID0gRlJPTV9CUltvcHRzLnhhbmNob3JdO1xuICAgICAgICAgICAgaWYob3B0cy50aGlja25lc3Ntb2RlID09PSAncGl4ZWxzJykge1xuICAgICAgICAgICAgICAgIG1hcmdpbk9wdHMueCA9IG9wdHMueDtcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLmwgPSBvdXRlcndpZHRoICogbEZyYWM7XG4gICAgICAgICAgICAgICAgbWFyZ2luT3B0cy5yID0gb3V0ZXJ3aWR0aCAqIHJGcmFjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4dHJhVGhpY2tuZXNzID0gb3V0ZXJ3aWR0aCAtIHRoaWNrUHg7XG4gICAgICAgICAgICAgICAgbWFyZ2luT3B0cy5sID0gZXh0cmFUaGlja25lc3MgKiBsRnJhYztcbiAgICAgICAgICAgICAgICBtYXJnaW5PcHRzLnIgPSBleHRyYVRoaWNrbmVzcyAqIHJGcmFjO1xuICAgICAgICAgICAgICAgIG1hcmdpbk9wdHMueGwgPSBvcHRzLnggLSBvcHRzLnRoaWNrbmVzcyAqIGxGcmFjO1xuICAgICAgICAgICAgICAgIG1hcmdpbk9wdHMueHIgPSBvcHRzLnggKyBvcHRzLnRoaWNrbmVzcyAqIHJGcmFjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgUGxvdHMuYXV0b01hcmdpbihnZCwgaWQsIG1hcmdpbk9wdHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNiRG9uZSA9IExpYi5zeW5jT3JBc3luYyhbXG4gICAgICAgICAgICBQbG90cy5wcmV2aW91c1Byb21pc2VzLFxuICAgICAgICAgICAgZHJhd0F4aXMsXG4gICAgICAgICAgICBQbG90cy5wcmV2aW91c1Byb21pc2VzLFxuICAgICAgICAgICAgcG9zaXRpb25DQlxuICAgICAgICBdLCBnZCk7XG5cbiAgICAgICAgaWYoY2JEb25lICYmIGNiRG9uZS50aGVuKSAoZ2QuX3Byb21pc2VzIHx8IFtdKS5wdXNoKGNiRG9uZSk7XG5cbiAgICAgICAgLy8gZHJhZ2dpbmcuLi5cbiAgICAgICAgaWYoZ2QuX2NvbnRleHQuZWRpdHMuY29sb3JiYXJQb3NpdGlvbikge1xuICAgICAgICAgICAgdmFyIHQwLFxuICAgICAgICAgICAgICAgIHhmLFxuICAgICAgICAgICAgICAgIHlmO1xuXG4gICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICBlbGVtZW50OiBjb250YWluZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgIGdkOiBnZCxcbiAgICAgICAgICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0MCA9IGNvbnRhaW5lci5hdHRyKCd0cmFuc2Zvcm0nKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0Q3Vyc29yKGNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuYXR0cigndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHQwICsgJyAnICsgJ3RyYW5zbGF0ZSgnICsgZHggKyAnLCcgKyBkeSArICcpJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgeGYgPSBkcmFnRWxlbWVudC5hbGlnbih4TGVmdEZyYWMgKyAoZHggLyBncy53KSwgdGhpY2tGcmFjLFxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgMSwgb3B0cy54YW5jaG9yKTtcbiAgICAgICAgICAgICAgICAgICAgeWYgPSBkcmFnRWxlbWVudC5hbGlnbih5Qm90dG9tRnJhYyAtIChkeSAvIGdzLmgpLCBsZW5GcmFjLFxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgMSwgb3B0cy55YW5jaG9yKTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgY3NyID0gZHJhZ0VsZW1lbnQuZ2V0Q3Vyc29yKHhmLCB5ZixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMueGFuY2hvciwgb3B0cy55YW5jaG9yKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0Q3Vyc29yKGNvbnRhaW5lciwgY3NyKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRvbmVGbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEN1cnNvcihjb250YWluZXIpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKHhmICE9PSB1bmRlZmluZWQgJiYgeWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVzdHlsZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeydjb2xvcmJhci54JzogeGYsICdjb2xvcmJhci55JzogeWZ9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFRyYWNlKCkuaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2JEb25lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFRyYWNlKCkge1xuICAgICAgICB2YXIgaWROdW0gPSBpZC5zdWJzdHIoMiksXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgdHJhY2U7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdkLl9mdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2UgPSBnZC5fZnVsbERhdGFbaV07XG4gICAgICAgICAgICBpZih0cmFjZS51aWQgPT09IGlkTnVtKSByZXR1cm4gdHJhY2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzZXR0ZXIvZ2V0dGVycyBmb3IgZXZlcnkgaXRlbSBkZWZpbmVkIGluIG9wdHNcbiAgICBPYmplY3Qua2V5cyhvcHRzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgY29tcG9uZW50W25hbWVdID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgLy8gZ2V0dGVyXG4gICAgICAgICAgICBpZighYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG9wdHNbbmFtZV07XG5cbiAgICAgICAgICAgIC8vIHNldHRlciAtIGZvciBtdWx0aS1wYXJ0IHByb3BlcnRpZXMsXG4gICAgICAgICAgICAvLyBzZXQgb25seSB0aGUgcGFydHMgdGhhdCBhcmUgcHJvdmlkZWRcbiAgICAgICAgICAgIG9wdHNbbmFtZV0gPSBMaWIuaXNQbGFpbk9iamVjdChvcHRzW25hbWVdKSA/XG4gICAgICAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KG9wdHNbbmFtZV0sIHYpIDpcbiAgICAgICAgICAgICAgICAgdjtcblxuICAgICAgICAgICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIG9yIHVzZSAub3B0aW9ucyB0byBzZXQgbXVsdGlwbGUgb3B0aW9ucyBhdCBvbmNlIHZpYSBhIGRpY3Rpb25hcnlcbiAgICBjb21wb25lbnQub3B0aW9ucyA9IGZ1bmN0aW9uKG8pIHtcbiAgICAgICAgZm9yKHZhciBuYW1lIGluIG8pIHtcbiAgICAgICAgICAgIC8vIGluIGNhc2Ugc29tZXRoaW5nIHJhbmRvbSBjb21lcyB0aHJvdWdoXG4gICAgICAgICAgICAvLyB0aGF0J3Mgbm90IGFuIG9wdGlvbiwgaWdub3JlIGl0XG4gICAgICAgICAgICBpZih0eXBlb2YgY29tcG9uZW50W25hbWVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY29tcG9uZW50W25hbWVdKG9bbmFtZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb21wb25lbnQ7XG4gICAgfTtcblxuICAgIGNvbXBvbmVudC5fb3B0cyA9IG9wdHM7XG5cbiAgICByZXR1cm4gY29tcG9uZW50O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYXNDb2xvcmJhcihjb250YWluZXIpIHtcbiAgICByZXR1cm4gTGliLmlzUGxhaW5PYmplY3QoY29udGFpbmVyLmNvbG9yYmFyKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwYWxldHRlcyA9IHJlcXVpcmUoJy4vc2NhbGVzLmpzJyk7XG52YXIgcGFsZXR0ZVN0ciA9IE9iamVjdC5rZXlzKHBhbGV0dGVzKTtcblxuZnVuY3Rpb24gY29kZShzKSB7XG4gICAgcmV0dXJuICdgJyArIHMgKyAnYCc7XG59XG5cbi8qKlxuICogTWFrZSBjb2xvcnNjYWxlIGF0dHJpYnV0ZSBkZWNsYXJhdGlvbnMgZm9yXG4gKlxuICogLSBjb2xvcnNjYWxlLFxuICogLSAoY3x6KWF1dG8sIChjfHopbWluLCAoY3x6KW1heCxcbiAqIC0gYXV0b2NvbG9yc2NhbGUsIHJldmVyc2VzY2FsZSxcbiAqIC0gc2hvd3NjYWxlIChvcHRpb25hbGx5KVxuICogLSBjb2xvciAob3B0aW9uYWxseSlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGV4dCAoZGZsdDogJycsIGkuZS4gZnJvbSB0cmFjZSByb290KTpcbiAqICAgICB0aGUgY29udGFpbmVyIHRoaXMgaXMgaW4gKCcnLCAqbWFya2VyKiwgKm1hcmtlci5saW5lKiBldGMpXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHM6XG4gKiAgIC0gY0xldHRlciB7c3RyaW5nfSAoZGZsdDogJ2MnKTpcbiAqICAgICBsZWFkaW5nIGxldHRlciBmb3IgJ21pbicsICdtYXggYW5kICdhdXRvJyBhdHRyaWJ1dGUgKGVpdGhlciAneicgb3IgJ2MnKVxuICpcbiAqICAgLSBjb2xvckF0dHIge3N0cmluZ30gKGRmbHQ6ICd6JyBpZiBgY0xldHRlcjogJ3onYCwgJ2NvbG9yJyBpZiBgY0xldHRlcjogJ2MnYCk6XG4gKiAgICAgKGZvciBkZXNjcmlwdGlvbnMpIHNldHMgdGhlIG5hbWUgb2YgdGhlIGNvbG9yIGF0dHJpYnV0ZSB0aGF0IG1hcHMgdG8gdGhlIGNvbG9yc2NhbGUuXG4gKlxuICogICAgIE4uQi4gaWYgYGNvbG9yQXR0cjogJ2NvbG9yJ2AsIHdlIGluY2x1ZGUgdGhlIGBjb2xvcmAgZGVjbGFyYXRpb24gaGVyZS5cbiAqXG4gKiAgIC0gb25seUlmTnVtZXJpY2FsIHtzdHJpbmd9IChkZmx0OiBmYWxzZScgaWYgYGNMZXR0ZXI6ICd6J2AsIHRydWUgaWYgYGNMZXR0ZXI6ICdjJ2ApOlxuICogICAgIChmb3IgZGVzY3JpcHRpb25zKSBzZXQgdG8gdHJ1ZSBpZiBjb2xvcnNjYWxlIGF0dHJpYnV0ZSBvbmx5XG4gKlxuICogICAtIGNvbG9yc2NhbGVEZmx0IHtzdHJpbmd9OlxuICogICAgIG92ZXJyaWRlcyB0aGUgY29sb3JzY2FsZSBkZmx0XG4gKlxuICogICAtIGF1dG9Db2xvckRmbHQge2Jvb2xlYW59IChkZmx0IHRydWUpOlxuICogICAgIG5vcm1hbGx5IGF1dG9jb2xvcnNjYWxlLmRmbHQgaXMgYHRydWVgLCBidXQgcGFzcyBgZmFsc2VgIHRvIG92ZXJyaWRlXG4gKlxuICogICAtIG5vU2NhbGUge2Jvb2xlYW59IChkZmx0OiB0cnVlIGlmIGBjb250ZXh0OiAnbWFya2VyLmxpbmUnYCwgZmFsc2Ugb3RoZXJ3aXNlKTpcbiAqICAgICBzZXQgdG8gYGZhbHNlYCB0byBub3QgaW5jbHVkZSBzaG93c2NhbGUgYXR0cmlidXRlIChlLmcuIGZvciAnbWFya2VyLmxpbmUnKVxuICpcbiAqICAgLSBzaG93U2NhbGVEZmx0IHtib29sZWFufSAoZGZsdDogdHJ1ZSBpZiBgY0xldHRlcjogJ3onYCwgZmFsc2Ugb3RoZXJ3aXNlKVxuICpcbiAqICAgLSBlZGl0VHlwZU92ZXJyaWRlIHtib29sZWFufSAoZGZsdDogJycpOlxuICogICAgIG1vc3Qgb2YgdGhlc2UgYXR0cmlidXRlcyBhbHJlYWR5IHJlcXVpcmUgYSByZWNhbGMsIGJ1dCB0aGUgb25lcyB0aGF0IGRvIG5vdFxuICogICAgIGhhdmUgZWRpdFR5cGUgKnN0eWxlKiBvciAqcGxvdCogdW5sZXNzIHlvdSBvdmVycmlkZSAocHJlc3VtYWJseSB3aXRoICpjYWxjKilcbiAqXG4gKiAgIC0gYW5pbSB7Ym9vbGVhbikgKGRmbHQ6IHVuZGVmaW5lZCk6IGlzICdjb2xvcicgYW5pbWF0YWJsZT9cbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29sb3JTY2FsZUF0dHJzKGNvbnRleHQsIG9wdHMpIHtcbiAgICBjb250ZXh0ID0gY29udGV4dCB8fCAnJztcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBjTGV0dGVyID0gb3B0cy5jTGV0dGVyIHx8ICdjJztcbiAgICB2YXIgb25seUlmTnVtZXJpY2FsID0gKCdvbmx5SWZOdW1lcmljYWwnIGluIG9wdHMpID8gb3B0cy5vbmx5SWZOdW1lcmljYWwgOiBCb29sZWFuKGNvbnRleHQpO1xuICAgIHZhciBub1NjYWxlID0gKCdub1NjYWxlJyBpbiBvcHRzKSA/IG9wdHMubm9TY2FsZSA6IGNvbnRleHQgPT09ICdtYXJrZXIubGluZSc7XG4gICAgdmFyIHNob3dTY2FsZURmbHQgPSAoJ3Nob3dTY2FsZURmbHQnIGluIG9wdHMpID8gb3B0cy5zaG93U2NhbGVEZmx0IDogY0xldHRlciA9PT0gJ3onO1xuICAgIHZhciBjb2xvcnNjYWxlRGZsdCA9IHR5cGVvZiBvcHRzLmNvbG9yc2NhbGVEZmx0ID09PSAnc3RyaW5nJyA/IHBhbGV0dGVzW29wdHMuY29sb3JzY2FsZURmbHRdIDogbnVsbDtcbiAgICB2YXIgZWRpdFR5cGVPdmVycmlkZSA9IG9wdHMuZWRpdFR5cGVPdmVycmlkZSB8fCAnJztcbiAgICB2YXIgY29udGV4dEhlYWQgPSBjb250ZXh0ID8gKGNvbnRleHQgKyAnLicpIDogJyc7XG5cbiAgICB2YXIgY29sb3JBdHRyLCBjb2xvckF0dHJGdWxsO1xuXG4gICAgaWYoJ2NvbG9yQXR0cicgaW4gb3B0cykge1xuICAgICAgICBjb2xvckF0dHIgPSBvcHRzLmNvbG9yQXR0cjtcbiAgICAgICAgY29sb3JBdHRyRnVsbCA9IG9wdHMuY29sb3JBdHRyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbG9yQXR0ciA9IHt6OiAneicsIGM6ICdjb2xvcid9W2NMZXR0ZXJdO1xuICAgICAgICBjb2xvckF0dHJGdWxsID0gJ2luICcgKyBjb2RlKGNvbnRleHRIZWFkICsgY29sb3JBdHRyKTtcbiAgICB9XG5cbiAgICB2YXIgZWZmZWN0RGVzYyA9IG9ubHlJZk51bWVyaWNhbCA/XG4gICAgICAgICcgSGFzIGFuIGVmZmVjdCBvbmx5IGlmICcgKyBjb2xvckF0dHJGdWxsICsgJ2lzIHNldCB0byBhIG51bWVyaWNhbCBhcnJheS4nIDpcbiAgICAgICAgJyc7XG5cbiAgICB2YXIgYXV0byA9IGNMZXR0ZXIgKyAnYXV0byc7XG4gICAgdmFyIG1pbiA9IGNMZXR0ZXIgKyAnbWluJztcbiAgICB2YXIgbWF4ID0gY0xldHRlciArICdtYXgnO1xuICAgIHZhciBtaW5GdWxsID0gY29kZShjb250ZXh0SGVhZCArIG1pbik7XG4gICAgdmFyIG1heEZ1bGwgPSBjb2RlKGNvbnRleHRIZWFkICsgbWF4KTtcbiAgICB2YXIgbWlubWF4RnVsbCA9IG1pbkZ1bGwgKyAnIGFuZCAnICsgbWF4RnVsbDtcbiAgICB2YXIgYXV0b0ltcGxpZWRFZGl0cyA9IHt9O1xuICAgIGF1dG9JbXBsaWVkRWRpdHNbbWluXSA9IGF1dG9JbXBsaWVkRWRpdHNbbWF4XSA9IHVuZGVmaW5lZDtcbiAgICB2YXIgbWlubWF4SW1wbGllZEVkaXRzID0ge307XG4gICAgbWlubWF4SW1wbGllZEVkaXRzW2F1dG9dID0gZmFsc2U7XG5cbiAgICB2YXIgYXR0cnMgPSB7fTtcblxuICAgIGlmKGNvbG9yQXR0ciA9PT0gJ2NvbG9yJykge1xuICAgICAgICBhdHRycy5jb2xvciA9IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGVPdmVycmlkZSB8fCAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYob3B0cy5hbmltKSB7XG4gICAgICAgICAgICBhdHRycy5jb2xvci5hbmltID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGF0dHJzW2F1dG9dID0ge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IGF1dG9JbXBsaWVkRWRpdHMsXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRyc1ttaW5dID0ge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIGVkaXRUeXBlOiBlZGl0VHlwZU92ZXJyaWRlIHx8ICdwbG90JyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiBtaW5tYXhJbXBsaWVkRWRpdHMsXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRyc1ttYXhdID0ge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIGVkaXRUeXBlOiBlZGl0VHlwZU92ZXJyaWRlIHx8ICdwbG90JyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiBtaW5tYXhJbXBsaWVkRWRpdHMsXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRycy5jb2xvcnNjYWxlID0ge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3JzY2FsZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBkZmx0OiBjb2xvcnNjYWxlRGZsdCxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7YXV0b2NvbG9yc2NhbGU6IGZhbHNlfSxcbiAgICAgICAgXG4gICAgfTtcblxuICAgIGF0dHJzLmF1dG9jb2xvcnNjYWxlID0ge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICAvLyBnZXRzIG92ZXJyb2RlIGluICdoZWF0bWFwJyAmICdzdXJmYWNlJyBmb3IgYmFja3dhcmRzIGNvbXAuXG4gICAgICAgIGRmbHQ6IG9wdHMuYXV0b0NvbG9yRGZsdCA9PT0gZmFsc2UgPyBmYWxzZSA6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge2NvbG9yc2NhbGU6IHVuZGVmaW5lZH0sXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRycy5yZXZlcnNlc2NhbGUgPSB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9O1xuXG4gICAgaWYoIW5vU2NhbGUpIHtcbiAgICAgICAgYXR0cnMuc2hvd3NjYWxlID0ge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBzaG93U2NhbGVEZmx0LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBhdHRycztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgc2NhbGVzID0gcmVxdWlyZSgnLi9zY2FsZXMnKTtcbnZhciBmbGlwU2NhbGUgPSByZXF1aXJlKCcuL2ZsaXBfc2NhbGUnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGModHJhY2UsIHZhbHMsIGNvbnRhaW5lclN0ciwgY0xldHRlcikge1xuICAgIHZhciBjb250YWluZXIgPSB0cmFjZTtcbiAgICB2YXIgaW5wdXRDb250YWluZXIgPSB0cmFjZS5faW5wdXQ7XG4gICAgdmFyIGZ1bGxJbnB1dENvbnRhaW5lciA9IHRyYWNlLl9mdWxsSW5wdXQ7XG5cbiAgICAvLyBzZXQgYnkgdHJhY2VzIHdpdGggZ3JvdXBieSB0cmFuc2Zvcm1zXG4gICAgdmFyIHVwZGF0ZVN0eWxlID0gdHJhY2UudXBkYXRlU3R5bGU7XG5cbiAgICBmdW5jdGlvbiBkb1VwZGF0ZShhdHRyLCBpbnB1dFZhbCwgZnVsbFZhbCkge1xuICAgICAgICBpZihmdWxsVmFsID09PSB1bmRlZmluZWQpIGZ1bGxWYWwgPSBpbnB1dFZhbDtcblxuICAgICAgICBpZih1cGRhdGVTdHlsZSkge1xuICAgICAgICAgICAgdXBkYXRlU3R5bGUodHJhY2UuX2lucHV0LCBjb250YWluZXJTdHIgPyAoY29udGFpbmVyU3RyICsgJy4nICsgYXR0cikgOiBhdHRyLCBpbnB1dFZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpbnB1dENvbnRhaW5lclthdHRyXSA9IGlucHV0VmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGFpbmVyW2F0dHJdID0gZnVsbFZhbDtcbiAgICAgICAgaWYoZnVsbElucHV0Q29udGFpbmVyICYmICh0cmFjZSAhPT0gdHJhY2UuX2Z1bGxJbnB1dCkpIHtcbiAgICAgICAgICAgIGlmKHVwZGF0ZVN0eWxlKSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlU3R5bGUodHJhY2UuX2Z1bGxJbnB1dCwgY29udGFpbmVyU3RyID8gKGNvbnRhaW5lclN0ciArICcuJyArIGF0dHIpIDogYXR0ciwgZnVsbFZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmdWxsSW5wdXRDb250YWluZXJbYXR0cl0gPSBmdWxsVmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoY29udGFpbmVyU3RyKSB7XG4gICAgICAgIGNvbnRhaW5lciA9IExpYi5uZXN0ZWRQcm9wZXJ0eShjb250YWluZXIsIGNvbnRhaW5lclN0cikuZ2V0KCk7XG4gICAgICAgIGlucHV0Q29udGFpbmVyID0gTGliLm5lc3RlZFByb3BlcnR5KGlucHV0Q29udGFpbmVyLCBjb250YWluZXJTdHIpLmdldCgpO1xuICAgICAgICBmdWxsSW5wdXRDb250YWluZXIgPSBMaWIubmVzdGVkUHJvcGVydHkoZnVsbElucHV0Q29udGFpbmVyLCBjb250YWluZXJTdHIpLmdldCgpIHx8IHt9O1xuICAgIH1cblxuICAgIHZhciBhdXRvQXR0ciA9IGNMZXR0ZXIgKyAnYXV0byc7XG4gICAgdmFyIG1pbkF0dHIgPSBjTGV0dGVyICsgJ21pbic7XG4gICAgdmFyIG1heEF0dHIgPSBjTGV0dGVyICsgJ21heCc7XG4gICAgdmFyIGF1dG8gPSBjb250YWluZXJbYXV0b0F0dHJdO1xuICAgIHZhciBtaW4gPSBjb250YWluZXJbbWluQXR0cl07XG4gICAgdmFyIG1heCA9IGNvbnRhaW5lclttYXhBdHRyXTtcbiAgICB2YXIgc2NsID0gY29udGFpbmVyLmNvbG9yc2NhbGU7XG5cbiAgICBpZihhdXRvICE9PSBmYWxzZSB8fCBtaW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBtaW4gPSBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgdmFscyk7XG4gICAgfVxuXG4gICAgaWYoYXV0byAhPT0gZmFsc2UgfHwgbWF4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWF4ID0gTGliLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIHZhbHMpO1xuICAgIH1cblxuICAgIGlmKG1pbiA9PT0gbWF4KSB7XG4gICAgICAgIG1pbiAtPSAwLjU7XG4gICAgICAgIG1heCArPSAwLjU7XG4gICAgfVxuXG4gICAgZG9VcGRhdGUobWluQXR0ciwgbWluKTtcbiAgICBkb1VwZGF0ZShtYXhBdHRyLCBtYXgpO1xuXG4gICAgLypcbiAgICAgKiBJZiBhdXRvIHdhcyBleHBsaWNpdGx5IGZhbHNlIGJ1dCBtaW4gb3IgbWF4IHdhcyBtaXNzaW5nLFxuICAgICAqIHdlIGZpbGxlZCBpbiB0aGUgbWlzc2luZyBwaWVjZSBoZXJlIGJ1dCBsYXRlciB0aGUgdHJhY2UgZG9lc1xuICAgICAqIG5vdCBsb29rIGF1dG8uXG4gICAgICogT3RoZXJ3aXNlIG1ha2Ugc3VyZSB0aGUgdHJhY2Ugc3RpbGwgbG9va3MgYXV0byBhcyBmYXIgYXMgbGF0ZXJcbiAgICAgKiBjaGFuZ2VzIGFyZSBjb25jZXJuZWQuXG4gICAgICovXG4gICAgZG9VcGRhdGUoYXV0b0F0dHIsIChhdXRvICE9PSBmYWxzZSB8fCAobWluID09PSB1bmRlZmluZWQgJiYgbWF4ID09PSB1bmRlZmluZWQpKSk7XG5cbiAgICBpZihjb250YWluZXIuYXV0b2NvbG9yc2NhbGUpIHtcbiAgICAgICAgaWYobWluICogbWF4IDwgMCkgc2NsID0gc2NhbGVzLlJkQnU7XG4gICAgICAgIGVsc2UgaWYobWluID49IDApIHNjbCA9IHNjYWxlcy5SZWRzO1xuICAgICAgICBlbHNlIHNjbCA9IHNjYWxlcy5CbHVlcztcblxuICAgICAgICAvLyByZXZlcnNlc2NhbGUgaXMgaGFuZGxlZCBhdCB0aGUgY29udGFpbmVyT3V0IGxldmVsXG4gICAgICAgIGRvVXBkYXRlKCdjb2xvcnNjYWxlJywgc2NsLCBjb250YWluZXIucmV2ZXJzZXNjYWxlID8gZmxpcFNjYWxlKHNjbCkgOiBzY2wpO1xuXG4gICAgICAgIC8vIFdlIHB1c2hlZCBhIGNvbG9yc2NhbGUgYmFjayB0byBpbnB1dCwgd2hpY2ggd2lsbCBjaGFuZ2UgdGhlIGRlZmF1bHQgYXV0b2NvbG9yc2NhbGUgbmV4dCB0aW1lXG4gICAgICAgIC8vIHRvIGF2b2lkIHNwdXJpb3VzIHJlZHJhd3MgZnJvbSBQbG90bHkucmVhY3QsIHVwZGF0ZSByZXN1bHRpbmcgYXV0b2NvbG9yc2NhbGUgbm93XG4gICAgICAgIC8vIFRoaXMgaXMgYSBjb25zY2lvdXMgZGVjaXNpb24gc28gdGhhdCBjaGFuZ2luZyB0aGUgZGF0YSBsYXRlciBkb2VzIG5vdCB1bmV4cGVjdGVkbHlcbiAgICAgICAgLy8gZ2l2ZSB5b3UgYSBuZXcgY29sb3JzY2FsZVxuICAgICAgICBpZighaW5wdXRDb250YWluZXIuYXV0b2NvbG9yc2NhbGUpIHtcbiAgICAgICAgICAgIGRvVXBkYXRlKCdhdXRvY29sb3JzY2FsZScsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2FsZXMgPSByZXF1aXJlKCcuL3NjYWxlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gc2NhbGVzLlJkQnU7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGhhc0NvbG9yYmFyID0gcmVxdWlyZSgnLi4vY29sb3JiYXIvaGFzX2NvbG9yYmFyJyk7XG52YXIgY29sb3JiYXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NvbG9yYmFyL2RlZmF1bHRzJyk7XG52YXIgaXNWYWxpZFNjYWxlID0gcmVxdWlyZSgnLi9pc192YWxpZF9zY2FsZScpO1xudmFyIGZsaXBTY2FsZSA9IHJlcXVpcmUoJy4vZmxpcF9zY2FsZScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29sb3JTY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIHZhciBwcmVmaXggPSBvcHRzLnByZWZpeCxcbiAgICAgICAgY0xldHRlciA9IG9wdHMuY0xldHRlcixcbiAgICAgICAgY29udGFpbmVyU3RyID0gcHJlZml4LnNsaWNlKDAsIHByZWZpeC5sZW5ndGggLSAxKSxcbiAgICAgICAgY29udGFpbmVySW4gPSBwcmVmaXggP1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlSW4sIGNvbnRhaW5lclN0cikuZ2V0KCkgfHwge30gOlxuICAgICAgICAgICAgdHJhY2VJbixcbiAgICAgICAgY29udGFpbmVyT3V0ID0gcHJlZml4ID9cbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZU91dCwgY29udGFpbmVyU3RyKS5nZXQoKSB8fCB7fSA6XG4gICAgICAgICAgICB0cmFjZU91dCxcbiAgICAgICAgbWluSW4gPSBjb250YWluZXJJbltjTGV0dGVyICsgJ21pbiddLFxuICAgICAgICBtYXhJbiA9IGNvbnRhaW5lckluW2NMZXR0ZXIgKyAnbWF4J10sXG4gICAgICAgIHNjbEluID0gY29udGFpbmVySW4uY29sb3JzY2FsZTtcblxuICAgIHZhciB2YWxpZE1pbk1heCA9IGlzTnVtZXJpYyhtaW5JbikgJiYgaXNOdW1lcmljKG1heEluKSAmJiAobWluSW4gPCBtYXhJbik7XG4gICAgY29lcmNlKHByZWZpeCArIGNMZXR0ZXIgKyAnYXV0bycsICF2YWxpZE1pbk1heCk7XG4gICAgY29lcmNlKHByZWZpeCArIGNMZXR0ZXIgKyAnbWluJyk7XG4gICAgY29lcmNlKHByZWZpeCArIGNMZXR0ZXIgKyAnbWF4Jyk7XG5cbiAgICAvLyBoYW5kbGVzIGJvdGggdGhlIHRyYWNlIGNhc2UgKGF1dG9jb2xvcnNjYWxlIGlzIGZhbHNlIGJ5IGRlZmF1bHQpIGFuZFxuICAgIC8vIHRoZSBtYXJrZXIgYW5kIG1hcmtlci5saW5lIGNhc2UgKGF1dG9jb2xvcnNjYWxlIGlzIHRydWUgYnkgZGVmYXVsdClcbiAgICB2YXIgYXV0b0NvbG9yc2NhbGVEZmx0O1xuICAgIGlmKHNjbEluICE9PSB1bmRlZmluZWQpIGF1dG9Db2xvcnNjYWxlRGZsdCA9ICFpc1ZhbGlkU2NhbGUoc2NsSW4pO1xuICAgIGNvZXJjZShwcmVmaXggKyAnYXV0b2NvbG9yc2NhbGUnLCBhdXRvQ29sb3JzY2FsZURmbHQpO1xuICAgIHZhciBzY2xPdXQgPSBjb2VyY2UocHJlZml4ICsgJ2NvbG9yc2NhbGUnKTtcblxuICAgIC8vIHJldmVyc2VzY2FsZSBpcyBoYW5kbGVkIGF0IHRoZSBjb250YWluZXJPdXQgbGV2ZWxcbiAgICB2YXIgcmV2ZXJzZVNjYWxlID0gY29lcmNlKHByZWZpeCArICdyZXZlcnNlc2NhbGUnKTtcbiAgICBpZihyZXZlcnNlU2NhbGUpIGNvbnRhaW5lck91dC5jb2xvcnNjYWxlID0gZmxpcFNjYWxlKHNjbE91dCk7XG5cbiAgICAvLyAuLi4gdW50aWwgU2NhdHRlci5jb2xvcmJhciBjYW4gaGFuZGxlIG1hcmtlciBsaW5lIGNvbG9yYmFyc1xuICAgIGlmKHByZWZpeCA9PT0gJ21hcmtlci5saW5lLicpIHJldHVybjtcblxuICAgIGlmKCFvcHRzLm5vU2NhbGUpIHtcbiAgICAgICAgLy8gaGFuZGxlcyBib3RoIHRoZSB0cmFjZSBjYXNlIHdoZXJlIHRoZSBkZmx0IGlzIGxpc3RlZCBpbiBhdHRyaWJ1dGVzIGFuZFxuICAgICAgICAvLyB0aGUgbWFya2VyIGNhc2Ugd2hlcmUgdGhlIGRmbHQgaXMgZGV0ZXJtaW5lZCBieSBoYXNDb2xvcmJhclxuICAgICAgICB2YXIgc2hvd1NjYWxlRGZsdDtcbiAgICAgICAgaWYocHJlZml4KSBzaG93U2NhbGVEZmx0ID0gaGFzQ29sb3JiYXIoY29udGFpbmVySW4pO1xuXG4gICAgICAgIHZhciBzaG93U2NhbGUgPSBjb2VyY2UocHJlZml4ICsgJ3Nob3dzY2FsZScsIHNob3dTY2FsZURmbHQpO1xuICAgICAgICBpZihzaG93U2NhbGUpIGNvbG9yYmFyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgbGF5b3V0KTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogRXh0cmFjdCBjb2xvcnNjYWxlIGludG8gbnVtZXJpYyBkb21haW4gYW5kIGNvbG9yIHJhbmdlLlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IHNjbCBjb2xvcnNjYWxlIGFycmF5IG9mIGFycmF5c1xuICogQHBhcmFtIHtudW1iZXJ9IGNtaW4gbWluaW11bSBjb2xvciB2YWx1ZSAodXNlZCB0byBjbGFtcCBzY2FsZSlcbiAqIEBwYXJhbSB7bnVtYmVyfSBjbWF4IG1heGltdW0gY29sb3IgdmFsdWUgKHVzZWQgdG8gY2xhbXAgc2NhbGUpXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXh0cmFjdFNjYWxlKHNjbCwgY21pbiwgY21heCkge1xuICAgIHZhciBOID0gc2NsLmxlbmd0aCxcbiAgICAgICAgZG9tYWluID0gbmV3IEFycmF5KE4pLFxuICAgICAgICByYW5nZSA9IG5ldyBBcnJheShOKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBOOyBpKyspIHtcbiAgICAgICAgdmFyIHNpID0gc2NsW2ldO1xuXG4gICAgICAgIGRvbWFpbltpXSA9IGNtaW4gKyBzaVswXSAqIChjbWF4IC0gY21pbik7XG4gICAgICAgIHJhbmdlW2ldID0gc2lbMV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZG9tYWluOiBkb21haW4sXG4gICAgICAgIHJhbmdlOiByYW5nZVxuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmxpcFNjYWxlKHNjbCkge1xuICAgIHZhciBOID0gc2NsLmxlbmd0aCxcbiAgICAgICAgc2NsTmV3ID0gbmV3IEFycmF5KE4pLFxuICAgICAgICBzaTtcblxuICAgIGZvcih2YXIgaSA9IE4gLSAxLCBqID0gMDsgaSA+PSAwOyBpLS0sIGorKykge1xuICAgICAgICBzaSA9IHNjbFtpXTtcbiAgICAgICAgc2NsTmV3W2pdID0gWzEgLSBzaVswXSwgc2lbMV1dO1xuICAgIH1cblxuICAgIHJldHVybiBzY2xOZXc7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2FsZXMgPSByZXF1aXJlKCcuL3NjYWxlcycpO1xudmFyIGRlZmF1bHRTY2FsZSA9IHJlcXVpcmUoJy4vZGVmYXVsdF9zY2FsZScpO1xudmFyIGlzVmFsaWRTY2FsZUFycmF5ID0gcmVxdWlyZSgnLi9pc192YWxpZF9zY2FsZV9hcnJheScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0U2NhbGUoc2NsLCBkZmx0KSB7XG4gICAgaWYoIWRmbHQpIGRmbHQgPSBkZWZhdWx0U2NhbGU7XG4gICAgaWYoIXNjbCkgcmV0dXJuIGRmbHQ7XG5cbiAgICBmdW5jdGlvbiBwYXJzZVNjYWxlKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2NsID0gc2NhbGVzW3NjbF0gfHwgSlNPTi5wYXJzZShzY2wpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoKGUpIHtcbiAgICAgICAgICAgIHNjbCA9IGRmbHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih0eXBlb2Ygc2NsID09PSAnc3RyaW5nJykge1xuICAgICAgICBwYXJzZVNjYWxlKCk7XG4gICAgICAgIC8vIG9jY2FzaW9uYWxseSBzY2wgaXMgZG91YmxlLUpTT04gZW5jb2RlZC4uLlxuICAgICAgICBpZih0eXBlb2Ygc2NsID09PSAnc3RyaW5nJykgcGFyc2VTY2FsZSgpO1xuICAgIH1cblxuICAgIGlmKCFpc1ZhbGlkU2NhbGVBcnJheShzY2wpKSByZXR1cm4gZGZsdDtcbiAgICByZXR1cm4gc2NsO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgaXNWYWxpZFNjYWxlID0gcmVxdWlyZSgnLi9pc192YWxpZF9zY2FsZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhc0NvbG9yc2NhbGUodHJhY2UsIGNvbnRhaW5lclN0cikge1xuICAgIHZhciBjb250YWluZXIgPSBjb250YWluZXJTdHIgP1xuICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGNvbnRhaW5lclN0cikuZ2V0KCkgfHwge30gOlxuICAgICAgICB0cmFjZTtcbiAgICB2YXIgY29sb3IgPSBjb250YWluZXIuY29sb3I7XG5cbiAgICB2YXIgaXNBcnJheVdpdGhPbmVOdW1iZXIgPSBmYWxzZTtcbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShjb2xvcikpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbG9yLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWMoY29sb3JbaV0pKSB7XG4gICAgICAgICAgICAgICAgaXNBcnJheVdpdGhPbmVOdW1iZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgTGliLmlzUGxhaW5PYmplY3QoY29udGFpbmVyKSAmJiAoXG4gICAgICAgICAgICBpc0FycmF5V2l0aE9uZU51bWJlciB8fFxuICAgICAgICAgICAgY29udGFpbmVyLnNob3dzY2FsZSA9PT0gdHJ1ZSB8fFxuICAgICAgICAgICAgKGlzTnVtZXJpYyhjb250YWluZXIuY21pbikgJiYgaXNOdW1lcmljKGNvbnRhaW5lci5jbWF4KSkgfHxcbiAgICAgICAgICAgIGlzVmFsaWRTY2FsZShjb250YWluZXIuY29sb3JzY2FsZSkgfHxcbiAgICAgICAgICAgIExpYi5pc1BsYWluT2JqZWN0KGNvbnRhaW5lci5jb2xvcmJhcilcbiAgICAgICAgKVxuICAgICk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuc2NhbGVzID0gcmVxdWlyZSgnLi9zY2FsZXMnKTtcblxuZXhwb3J0cy5kZWZhdWx0U2NhbGUgPSByZXF1aXJlKCcuL2RlZmF1bHRfc2NhbGUnKTtcblxuZXhwb3J0cy5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuaGFuZGxlRGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5cbmV4cG9ydHMuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuXG5leHBvcnRzLmhhc0NvbG9yc2NhbGUgPSByZXF1aXJlKCcuL2hhc19jb2xvcnNjYWxlJyk7XG5cbmV4cG9ydHMuaXNWYWxpZFNjYWxlID0gcmVxdWlyZSgnLi9pc192YWxpZF9zY2FsZScpO1xuXG5leHBvcnRzLmdldFNjYWxlID0gcmVxdWlyZSgnLi9nZXRfc2NhbGUnKTtcblxuZXhwb3J0cy5mbGlwU2NhbGUgPSByZXF1aXJlKCcuL2ZsaXBfc2NhbGUnKTtcblxuZXhwb3J0cy5leHRyYWN0U2NhbGUgPSByZXF1aXJlKCcuL2V4dHJhY3Rfc2NhbGUnKTtcblxuZXhwb3J0cy5tYWtlQ29sb3JTY2FsZUZ1bmMgPSByZXF1aXJlKCcuL21ha2VfY29sb3Jfc2NhbGVfZnVuYycpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2FsZXMgPSByZXF1aXJlKCcuL3NjYWxlcycpO1xudmFyIGlzVmFsaWRTY2FsZUFycmF5ID0gcmVxdWlyZSgnLi9pc192YWxpZF9zY2FsZV9hcnJheScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNWYWxpZFNjYWxlKHNjbCkge1xuICAgIGlmKHNjYWxlc1tzY2xdICE9PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgIGVsc2UgcmV0dXJuIGlzVmFsaWRTY2FsZUFycmF5KHNjbCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc1ZhbGlkU2NhbGVBcnJheShzY2wpIHtcbiAgICB2YXIgaGlnaGVzdFZhbCA9IDA7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShzY2wpIHx8IHNjbC5sZW5ndGggPCAyKSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZighc2NsWzBdIHx8ICFzY2xbc2NsLmxlbmd0aCAtIDFdKSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZigrc2NsWzBdWzBdICE9PSAwIHx8ICtzY2xbc2NsLmxlbmd0aCAtIDFdWzBdICE9PSAxKSByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2NsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzaSA9IHNjbFtpXTtcblxuICAgICAgICBpZihzaS5sZW5ndGggIT09IDIgfHwgK3NpWzBdIDwgaGlnaGVzdFZhbCB8fCAhdGlueWNvbG9yKHNpWzFdKS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGhpZ2hlc3RWYWwgPSArc2lbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG5cbi8qKlxuICogR2VuZXJhbCBjb2xvcnNjYWxlIGZ1bmN0aW9uIGdlbmVyYXRvci5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc3BlY3Mgb3V0cHV0IG9mIENvbG9yc2NhbGUuZXh0cmFjdFNjYWxlIG9yIHByZWNvbXB1dGVkIGRvbWFpbiwgcmFuZ2UuXG4gKiAgLSBkb21haW4ge2FycmF5fVxuICogIC0gcmFuZ2Uge2FycmF5fVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiAgLSBub051bWVyaWNDaGVjayB7Ym9vbGVhbn0gaWYgdHJ1ZSwgc2NhbGUgZnVuYyBieXBhc3NlcyBudW1lcmljIGNoZWNrc1xuICogIC0gcmV0dXJuQXJyYXkge2Jvb2xlYW59IGlmIHRydWUsIHNjYWxlIGZ1bmMgcmV0dXJuIDQtaXRlbSBhcnJheSBpbnN0ZWFkIG9mIGNvbG9yIHN0cmluZ3NcbiAqXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQ29sb3JTY2FsZUZ1bmMoc3BlY3MsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBkb21haW4gPSBzcGVjcy5kb21haW4sXG4gICAgICAgIHJhbmdlID0gc3BlY3MucmFuZ2UsXG4gICAgICAgIE4gPSByYW5nZS5sZW5ndGgsXG4gICAgICAgIF9yYW5nZSA9IG5ldyBBcnJheShOKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBOOyBpKyspIHtcbiAgICAgICAgdmFyIHJnYmEgPSB0aW55Y29sb3IocmFuZ2VbaV0pLnRvUmdiKCk7XG4gICAgICAgIF9yYW5nZVtpXSA9IFtyZ2JhLnIsIHJnYmEuZywgcmdiYS5iLCByZ2JhLmFdO1xuICAgIH1cblxuICAgIHZhciBfc2NsRnVuYyA9IGQzLnNjYWxlLmxpbmVhcigpXG4gICAgICAgIC5kb21haW4oZG9tYWluKVxuICAgICAgICAucmFuZ2UoX3JhbmdlKVxuICAgICAgICAuY2xhbXAodHJ1ZSk7XG5cbiAgICB2YXIgbm9OdW1lcmljQ2hlY2sgPSBvcHRzLm5vTnVtZXJpY0NoZWNrLFxuICAgICAgICByZXR1cm5BcnJheSA9IG9wdHMucmV0dXJuQXJyYXksXG4gICAgICAgIHNjbEZ1bmM7XG5cbiAgICBpZihub051bWVyaWNDaGVjayAmJiByZXR1cm5BcnJheSkge1xuICAgICAgICBzY2xGdW5jID0gX3NjbEZ1bmM7XG4gICAgfVxuICAgIGVsc2UgaWYobm9OdW1lcmljQ2hlY2spIHtcbiAgICAgICAgc2NsRnVuYyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2xvckFycmF5MnJiZ2EoX3NjbEZ1bmModikpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBlbHNlIGlmKHJldHVybkFycmF5KSB7XG4gICAgICAgIHNjbEZ1bmMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWModikpIHJldHVybiBfc2NsRnVuYyh2KTtcbiAgICAgICAgICAgIGVsc2UgaWYodGlueWNvbG9yKHYpLmlzVmFsaWQoKSkgcmV0dXJuIHY7XG4gICAgICAgICAgICBlbHNlIHJldHVybiBDb2xvci5kZWZhdWx0TGluZTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNjbEZ1bmMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWModikpIHJldHVybiBjb2xvckFycmF5MnJiZ2EoX3NjbEZ1bmModikpO1xuICAgICAgICAgICAgZWxzZSBpZih0aW55Y29sb3IodikuaXNWYWxpZCgpKSByZXR1cm4gdjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuIENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIGNvbG9yYmFyIGRyYXcgbG9va3MgaW50byB0aGUgZDMgc2NhbGUgY2xvc3VyZSBmb3IgZG9tYWluIGFuZCByYW5nZVxuXG4gICAgc2NsRnVuYy5kb21haW4gPSBfc2NsRnVuYy5kb21haW47XG5cbiAgICBzY2xGdW5jLnJhbmdlID0gZnVuY3Rpb24oKSB7IHJldHVybiByYW5nZTsgfTtcblxuICAgIHJldHVybiBzY2xGdW5jO1xufTtcblxuZnVuY3Rpb24gY29sb3JBcnJheTJyYmdhKGNvbG9yQXJyYXkpIHtcbiAgICB2YXIgY29sb3JPYmogPSB7XG4gICAgICAgIHI6IGNvbG9yQXJyYXlbMF0sXG4gICAgICAgIGc6IGNvbG9yQXJyYXlbMV0sXG4gICAgICAgIGI6IGNvbG9yQXJyYXlbMl0sXG4gICAgICAgIGE6IGNvbG9yQXJyYXlbM11cbiAgICB9O1xuXG4gICAgcmV0dXJuIHRpbnljb2xvcihjb2xvck9iaikudG9SZ2JTdHJpbmcoKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAnR3JleXMnOiBbXG4gICAgICAgIFswLCAncmdiKDAsMCwwKSddLCBbMSwgJ3JnYigyNTUsMjU1LDI1NSknXVxuICAgIF0sXG5cbiAgICAnWWxHbkJ1JzogW1xuICAgICAgICBbMCwgJ3JnYig4LDI5LDg4KSddLCBbMC4xMjUsICdyZ2IoMzcsNTIsMTQ4KSddLFxuICAgICAgICBbMC4yNSwgJ3JnYigzNCw5NCwxNjgpJ10sIFswLjM3NSwgJ3JnYigyOSwxNDUsMTkyKSddLFxuICAgICAgICBbMC41LCAncmdiKDY1LDE4MiwxOTYpJ10sIFswLjYyNSwgJ3JnYigxMjcsMjA1LDE4NyknXSxcbiAgICAgICAgWzAuNzUsICdyZ2IoMTk5LDIzMywxODApJ10sIFswLjg3NSwgJ3JnYigyMzcsMjQ4LDIxNyknXSxcbiAgICAgICAgWzEsICdyZ2IoMjU1LDI1NSwyMTcpJ11cbiAgICBdLFxuXG4gICAgJ0dyZWVucyc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCw2OCwyNyknXSwgWzAuMTI1LCAncmdiKDAsMTA5LDQ0KSddLFxuICAgICAgICBbMC4yNSwgJ3JnYigzNSwxMzksNjkpJ10sIFswLjM3NSwgJ3JnYig2NSwxNzEsOTMpJ10sXG4gICAgICAgIFswLjUsICdyZ2IoMTE2LDE5NiwxMTgpJ10sIFswLjYyNSwgJ3JnYigxNjEsMjE3LDE1NSknXSxcbiAgICAgICAgWzAuNzUsICdyZ2IoMTk5LDIzMywxOTIpJ10sIFswLjg3NSwgJ3JnYigyMjksMjQ1LDIyNCknXSxcbiAgICAgICAgWzEsICdyZ2IoMjQ3LDI1MiwyNDUpJ11cbiAgICBdLFxuXG4gICAgJ1lsT3JSZCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMTI4LDAsMzgpJ10sIFswLjEyNSwgJ3JnYigxODksMCwzOCknXSxcbiAgICAgICAgWzAuMjUsICdyZ2IoMjI3LDI2LDI4KSddLCBbMC4zNzUsICdyZ2IoMjUyLDc4LDQyKSddLFxuICAgICAgICBbMC41LCAncmdiKDI1MywxNDEsNjApJ10sIFswLjYyNSwgJ3JnYigyNTQsMTc4LDc2KSddLFxuICAgICAgICBbMC43NSwgJ3JnYigyNTQsMjE3LDExOCknXSwgWzAuODc1LCAncmdiKDI1NSwyMzcsMTYwKSddLFxuICAgICAgICBbMSwgJ3JnYigyNTUsMjU1LDIwNCknXVxuICAgIF0sXG5cbiAgICAnQmx1ZXJlZCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDI1NSknXSwgWzEsICdyZ2IoMjU1LDAsMCknXVxuICAgIF0sXG5cbiAgICAvLyBtb2RpZmllZCBSZEJ1IGJhc2VkIG9uXG4gICAgLy8gd3d3LnNhbmRpYS5nb3Yvfmttb3JlbC9kb2N1bWVudHMvQ29sb3JNYXBzL0NvbG9yTWFwc0V4cGFuZGVkLnBkZlxuICAgICdSZEJ1JzogW1xuICAgICAgICBbMCwgJ3JnYig1LDEwLDE3MiknXSwgWzAuMzUsICdyZ2IoMTA2LDEzNywyNDcpJ10sXG4gICAgICAgIFswLjUsICdyZ2IoMTkwLDE5MCwxOTApJ10sIFswLjYsICdyZ2IoMjIwLDE3MCwxMzIpJ10sXG4gICAgICAgIFswLjcsICdyZ2IoMjMwLDE0NSw5MCknXSwgWzEsICdyZ2IoMTc4LDEwLDI4KSddXG4gICAgXSxcblxuICAgIC8vIFNjYWxlIGZvciBub24tbmVnYXRpdmUgbnVtZXJpYyB2YWx1ZXNcbiAgICAnUmVkcyc6IFtcbiAgICAgICAgWzAsICdyZ2IoMjIwLDIyMCwyMjApJ10sIFswLjIsICdyZ2IoMjQ1LDE5NSwxNTcpJ10sXG4gICAgICAgIFswLjQsICdyZ2IoMjQ1LDE2MCwxMDUpJ10sIFsxLCAncmdiKDE3OCwxMCwyOCknXVxuICAgIF0sXG5cbiAgICAvLyBTY2FsZSBmb3Igbm9uLXBvc2l0aXZlIG51bWVyaWMgdmFsdWVzXG4gICAgJ0JsdWVzJzogW1xuICAgICAgICBbMCwgJ3JnYig1LDEwLDE3MiknXSwgWzAuMzUsICdyZ2IoNDAsNjAsMTkwKSddLFxuICAgICAgICBbMC41LCAncmdiKDcwLDEwMCwyNDUpJ10sIFswLjYsICdyZ2IoOTAsMTIwLDI0NSknXSxcbiAgICAgICAgWzAuNywgJ3JnYigxMDYsMTM3LDI0NyknXSwgWzEsICdyZ2IoMjIwLDIyMCwyMjApJ11cbiAgICBdLFxuXG4gICAgJ1BpY25pYyc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDI1NSknXSwgWzAuMSwgJ3JnYig1MSwxNTMsMjU1KSddLFxuICAgICAgICBbMC4yLCAncmdiKDEwMiwyMDQsMjU1KSddLCBbMC4zLCAncmdiKDE1MywyMDQsMjU1KSddLFxuICAgICAgICBbMC40LCAncmdiKDIwNCwyMDQsMjU1KSddLCBbMC41LCAncmdiKDI1NSwyNTUsMjU1KSddLFxuICAgICAgICBbMC42LCAncmdiKDI1NSwyMDQsMjU1KSddLCBbMC43LCAncmdiKDI1NSwxNTMsMjU1KSddLFxuICAgICAgICBbMC44LCAncmdiKDI1NSwxMDIsMjA0KSddLCBbMC45LCAncmdiKDI1NSwxMDIsMTAyKSddLFxuICAgICAgICBbMSwgJ3JnYigyNTUsMCwwKSddXG4gICAgXSxcblxuICAgICdSYWluYm93JzogW1xuICAgICAgICBbMCwgJ3JnYigxNTAsMCw5MCknXSwgWzAuMTI1LCAncmdiKDAsMCwyMDApJ10sXG4gICAgICAgIFswLjI1LCAncmdiKDAsMjUsMjU1KSddLCBbMC4zNzUsICdyZ2IoMCwxNTIsMjU1KSddLFxuICAgICAgICBbMC41LCAncmdiKDQ0LDI1NSwxNTApJ10sIFswLjYyNSwgJ3JnYigxNTEsMjU1LDApJ10sXG4gICAgICAgIFswLjc1LCAncmdiKDI1NSwyMzQsMCknXSwgWzAuODc1LCAncmdiKDI1NSwxMTEsMCknXSxcbiAgICAgICAgWzEsICdyZ2IoMjU1LDAsMCknXVxuICAgIF0sXG5cbiAgICAnUG9ydGxhbmQnOiBbXG4gICAgICAgIFswLCAncmdiKDEyLDUxLDEzMSknXSwgWzAuMjUsICdyZ2IoMTAsMTM2LDE4NiknXSxcbiAgICAgICAgWzAuNSwgJ3JnYigyNDIsMjExLDU2KSddLCBbMC43NSwgJ3JnYigyNDIsMTQzLDU2KSddLFxuICAgICAgICBbMSwgJ3JnYigyMTcsMzAsMzApJ11cbiAgICBdLFxuXG4gICAgJ0pldCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDEzMSknXSwgWzAuMTI1LCAncmdiKDAsNjAsMTcwKSddLFxuICAgICAgICBbMC4zNzUsICdyZ2IoNSwyNTUsMjU1KSddLCBbMC42MjUsICdyZ2IoMjU1LDI1NSwwKSddLFxuICAgICAgICBbMC44NzUsICdyZ2IoMjUwLDAsMCknXSwgWzEsICdyZ2IoMTI4LDAsMCknXVxuICAgIF0sXG5cbiAgICAnSG90JzogW1xuICAgICAgICBbMCwgJ3JnYigwLDAsMCknXSwgWzAuMywgJ3JnYigyMzAsMCwwKSddLFxuICAgICAgICBbMC42LCAncmdiKDI1NSwyMTAsMCknXSwgWzEsICdyZ2IoMjU1LDI1NSwyNTUpJ11cbiAgICBdLFxuXG4gICAgJ0JsYWNrYm9keSc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDApJ10sIFswLjIsICdyZ2IoMjMwLDAsMCknXSxcbiAgICAgICAgWzAuNCwgJ3JnYigyMzAsMjEwLDApJ10sIFswLjcsICdyZ2IoMjU1LDI1NSwyNTUpJ10sXG4gICAgICAgIFsxLCAncmdiKDE2MCwyMDAsMjU1KSddXG4gICAgXSxcblxuICAgICdFYXJ0aCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDEzMCknXSwgWzAuMSwgJ3JnYigwLDE4MCwxODApJ10sXG4gICAgICAgIFswLjIsICdyZ2IoNDAsMjEwLDQwKSddLCBbMC40LCAncmdiKDIzMCwyMzAsNTApJ10sXG4gICAgICAgIFswLjYsICdyZ2IoMTIwLDcwLDIwKSddLCBbMSwgJ3JnYigyNTUsMjU1LDI1NSknXVxuICAgIF0sXG5cbiAgICAnRWxlY3RyaWMnOiBbXG4gICAgICAgIFswLCAncmdiKDAsMCwwKSddLCBbMC4xNSwgJ3JnYigzMCwwLDEwMCknXSxcbiAgICAgICAgWzAuNCwgJ3JnYigxMjAsMCwxMDApJ10sIFswLjYsICdyZ2IoMTYwLDkwLDApJ10sXG4gICAgICAgIFswLjgsICdyZ2IoMjMwLDIwMCwwKSddLCBbMSwgJ3JnYigyNTUsMjUwLDIyMCknXVxuICAgIF0sXG5cbiAgICAnVmlyaWRpcyc6IFtcbiAgICAgICAgWzAsICcjNDQwMTU0J10sIFswLjA2Mjc0NTA5ODAzOTIxNTY5LCAnIzQ4MTg2YSddLFxuICAgICAgICBbMC4xMjU0OTAxOTYwNzg0MzEzNywgJyM0NzJkN2InXSwgWzAuMTg4MjM1Mjk0MTE3NjQ3MDYsICcjNDI0MDg2J10sXG4gICAgICAgIFswLjI1MDk4MDM5MjE1Njg2Mjc0LCAnIzNiNTI4YiddLCBbMC4zMTM3MjU0OTAxOTYwNzg0LCAnIzMzNjM4ZCddLFxuICAgICAgICBbMC4zNzY0NzA1ODgyMzUyOTQxLCAnIzJjNzI4ZSddLCBbMC40MzkyMTU2ODYyNzQ1MDk4LCAnIzI2ODI4ZSddLFxuICAgICAgICBbMC41MDE5NjA3ODQzMTM3MjU1LCAnIzIxOTE4YyddLCBbMC41NjQ3MDU4ODIzNTI5NDEyLCAnIzFmYTA4OCddLFxuICAgICAgICBbMC42Mjc0NTA5ODAzOTIxNTY5LCAnIzI4YWU4MCddLCBbMC42OTAxOTYwNzg0MzEzNzI1LCAnIzNmYmM3MyddLFxuICAgICAgICBbMC43NTI5NDExNzY0NzA1ODgyLCAnIzVlYzk2MiddLCBbMC44MTU2ODYyNzQ1MDk4MDM5LCAnIzg0ZDQ0YiddLFxuICAgICAgICBbMC44Nzg0MzEzNzI1NDkwMTk2LCAnI2FkZGMzMCddLCBbMC45NDExNzY0NzA1ODgyMzUzLCAnI2Q4ZTIxOSddLFxuICAgICAgICBbMSwgJyNmZGU3MjUnXVxuICAgIF0sXG5cbiAgICAnQ2l2aWRpcyc6IFtcbiAgICAgICAgWzAuMDAwMDAwLCAncmdiKDAsMzIsNzYpJ10sIFswLjA1ODgyNCwgJ3JnYigwLDQyLDEwMiknXSxcbiAgICAgICAgWzAuMTE3NjQ3LCAncmdiKDAsNTIsMTEwKSddLCBbMC4xNzY0NzEsICdyZ2IoMzksNjMsMTA4KSddLFxuICAgICAgICBbMC4yMzUyOTQsICdyZ2IoNjAsNzQsMTA3KSddLCBbMC4yOTQxMTgsICdyZ2IoNzYsODUsMTA3KSddLFxuICAgICAgICBbMC4zNTI5NDEsICdyZ2IoOTEsOTUsMTA5KSddLCBbMC40MTE3NjUsICdyZ2IoMTA0LDEwNiwxMTIpJ10sXG4gICAgICAgIFswLjQ3MDU4OCwgJ3JnYigxMTcsMTE3LDExNyknXSwgWzAuNTI5NDEyLCAncmdiKDEzMSwxMjksMTIwKSddLFxuICAgICAgICBbMC41ODgyMzUsICdyZ2IoMTQ2LDE0MCwxMjApJ10sIFswLjY0NzA1OSwgJ3JnYigxNjEsMTUyLDExOCknXSxcbiAgICAgICAgWzAuNzA1ODgyLCAncmdiKDE3NiwxNjUsMTE0KSddLCBbMC43NjQ3MDYsICdyZ2IoMTkyLDE3NywxMDkpJ10sXG4gICAgICAgIFswLjgyMzUyOSwgJ3JnYigyMDksMTkxLDEwMiknXSwgWzAuODgyMzUzLCAncmdiKDIyNSwyMDQsOTIpJ10sXG4gICAgICAgIFswLjk0MTE3NiwgJ3JnYigyNDMsMjE5LDc5KSddLCBbMS4wMDAwMDAsICdyZ2IoMjU1LDIzMyw2OSknXVxuICAgIF1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG4vLyBmb3IgYXV0b21hdGljIGFsaWdubWVudCBvbiBkcmFnZ2luZywgPDEvMyBtZWFucyBsZWZ0IGFsaWduLFxuLy8gPjIvMyBtZWFucyByaWdodCwgYW5kIGJldHdlZW4gaXMgY2VudGVyLiBQaWNrIHRoZSByaWdodCBmcmFjdGlvblxuLy8gYmFzZWQgb24gd2hlcmUgeW91IGFyZSwgYW5kIHJldHVybiB0aGUgZnJhY3Rpb24gY29ycmVzcG9uZGluZyB0b1xuLy8gdGhhdCBwb3NpdGlvbiBvbiB0aGUgb2JqZWN0XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFsaWduKHYsIGR2LCB2MCwgdjEsIGFuY2hvcikge1xuICAgIHZhciB2bWluID0gKHYgLSB2MCkgLyAodjEgLSB2MCksXG4gICAgICAgIHZtYXggPSB2bWluICsgZHYgLyAodjEgLSB2MCksXG4gICAgICAgIHZjID0gKHZtaW4gKyB2bWF4KSAvIDI7XG5cbiAgICAvLyBleHBsaWNpdGx5IHNwZWNpZmllZCBhbmNob3JcbiAgICBpZihhbmNob3IgPT09ICdsZWZ0JyB8fCBhbmNob3IgPT09ICdib3R0b20nKSByZXR1cm4gdm1pbjtcbiAgICBpZihhbmNob3IgPT09ICdjZW50ZXInIHx8IGFuY2hvciA9PT0gJ21pZGRsZScpIHJldHVybiB2YztcbiAgICBpZihhbmNob3IgPT09ICdyaWdodCcgfHwgYW5jaG9yID09PSAndG9wJykgcmV0dXJuIHZtYXg7XG5cbiAgICAvLyBhdXRvbWF0aWMgYmFzZWQgb24gcG9zaXRpb25cbiAgICBpZih2bWluIDwgKDIgLyAzKSAtIHZjKSByZXR1cm4gdm1pbjtcbiAgICBpZih2bWF4ID4gKDQgLyAzKSAtIHZjKSByZXR1cm4gdm1heDtcbiAgICByZXR1cm4gdmM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuXG4vLyBzZXQgY3Vyc29ycyBwb2ludGluZyB0b3dhcmQgdGhlIGNsb3Nlc3QgY29ybmVyL3NpZGUsXG4vLyB0byBpbmRpY2F0ZSBhbGlnbm1lbnRcbi8vIHggYW5kIHkgYXJlIDAtMSwgZnJhY3Rpb25zIG9mIHRoZSBwbG90IGFyZWFcbnZhciBjdXJzb3JzZXQgPSBbXG4gICAgWydzdy1yZXNpemUnLCAncy1yZXNpemUnLCAnc2UtcmVzaXplJ10sXG4gICAgWyd3LXJlc2l6ZScsICdtb3ZlJywgJ2UtcmVzaXplJ10sXG4gICAgWydudy1yZXNpemUnLCAnbi1yZXNpemUnLCAnbmUtcmVzaXplJ11cbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0Q3Vyc29yKHgsIHksIHhhbmNob3IsIHlhbmNob3IpIHtcbiAgICBpZih4YW5jaG9yID09PSAnbGVmdCcpIHggPSAwO1xuICAgIGVsc2UgaWYoeGFuY2hvciA9PT0gJ2NlbnRlcicpIHggPSAxO1xuICAgIGVsc2UgaWYoeGFuY2hvciA9PT0gJ3JpZ2h0JykgeCA9IDI7XG4gICAgZWxzZSB4ID0gTGliLmNvbnN0cmFpbihNYXRoLmZsb29yKHggKiAzKSwgMCwgMik7XG5cbiAgICBpZih5YW5jaG9yID09PSAnYm90dG9tJykgeSA9IDA7XG4gICAgZWxzZSBpZih5YW5jaG9yID09PSAnbWlkZGxlJykgeSA9IDE7XG4gICAgZWxzZSBpZih5YW5jaG9yID09PSAndG9wJykgeSA9IDI7XG4gICAgZWxzZSB5ID0gTGliLmNvbnN0cmFpbihNYXRoLmZsb29yKHkgKiAzKSwgMCwgMik7XG5cbiAgICByZXR1cm4gY3Vyc29yc2V0W3ldW3hdO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbW91c2VPZmZzZXQgPSByZXF1aXJlKCdtb3VzZS1ldmVudC1vZmZzZXQnKTtcbnZhciBoYXNIb3ZlciA9IHJlcXVpcmUoJ2hhcy1ob3ZlcicpO1xudmFyIHN1cHBvcnRzUGFzc2l2ZSA9IHJlcXVpcmUoJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIGludGVyYWN0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpO1xuXG52YXIgZHJhZ0VsZW1lbnQgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5kcmFnRWxlbWVudC5hbGlnbiA9IHJlcXVpcmUoJy4vYWxpZ24nKTtcbmRyYWdFbGVtZW50LmdldEN1cnNvciA9IHJlcXVpcmUoJy4vY3Vyc29yJyk7XG5cbnZhciB1bmhvdmVyID0gcmVxdWlyZSgnLi91bmhvdmVyJyk7XG5kcmFnRWxlbWVudC51bmhvdmVyID0gdW5ob3Zlci53cmFwcGVkO1xuZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyA9IHVuaG92ZXIucmF3O1xuXG5cbi8qKlxuICogQWJzdHJhY3RzIGNsaWNrICYgZHJhZyBpbnRlcmFjdGlvbnNcbiAqXG4gKiBEdXJpbmcgdGhlIGludGVyYWN0aW9uLCBhIFwiY292ZXJTbGlwXCIgZWxlbWVudCAtIGEgdHJhbnNwYXJlbnRcbiAqIGRpdiBjb3ZlcmluZyB0aGUgd2hvbGUgcGFnZSAtIGlzIGNyZWF0ZWQsIHdoaWNoIGhhcyB0d28ga2V5IGVmZmVjdHM6XG4gKiAtIExldHMgeW91IGRyYWcgYmV5b25kIHRoZSBib3VuZGFyaWVzIG9mIHRoZSBwbG90IGl0c2VsZiB3aXRob3V0XG4gKiAgIGRyb3BwaW5nIChidXQgaWYgeW91IGRyYWcgYWxsIHRoZSB3YXkgb3V0IG9mIHRoZSBicm93c2VyIHdpbmRvdyB0aGVcbiAqICAgaW50ZXJhY3Rpb24gd2lsbCBlbmQpXG4gKiAtIEZyZWV6ZXMgdGhlIGN1cnNvcjogd2hhdGV2ZXIgbW91c2UgY3Vyc29yIHRoZSBkcmFnIGVsZW1lbnQgaGFkIHdoZW4gdGhlXG4gKiAgIGludGVyYWN0aW9uIHN0YXJ0ZWQgZ2V0cyBjb3BpZWQgdG8gdGhlIGNvdmVyU2xpcCBmb3IgdXNlIHVudGlsIG1vdXNldXBcbiAqXG4gKiBJZiB0aGUgdXNlciBleGVjdXRlcyBhIGRyYWcgYmlnZ2VyIHRoYW4gTUlORFJBRywgY2FsbGJhY2tzIHdpbGwgZmlyZSBhczpcbiAqICAgICAgcHJlcEZuLCBtb3ZlRm4gKDEgb3IgbW9yZSB0aW1lcyksIGRvbmVGblxuICogSWYgdGhlIHVzZXIgZG9lcyBub3QgZHJhZyBlbm91Z2gsIHByZXBGbiBhbmQgY2xpY2tGbiB3aWxsIGZpcmUuXG4gKlxuICogTm90ZTogSWYgeW91IGNhbmNlbCBjb250ZXh0bWVudSwgY2xpY2tGbiB3aWxsIGZpcmUgZXZlbiB3aXRoIGEgcmlnaHQgY2xpY2tcbiAqICh1bmxpa2UgbmF0aXZlIGV2ZW50cykgc28geW91J2xsIGdldCBhIGBwbG90bHlfY2xpY2tgIGV2ZW50LiBDYW5jZWwgY29udGV4dCBlZzpcbiAqICAgIGdkLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZnVuY3Rpb24oZSkgeyBlLnByZXZlbnREZWZhdWx0KCk7IH0pO1xuICogVE9ETzogd2Ugc2hvdWxkIHByb2JhYmx5IHR1cm4gdGhpcyBpbnRvIGEgYGNvbmZpZ2AgcGFyYW1ldGVyLCBzbyB3ZSBjYW4gZml4IGl0XG4gKiBzdWNoIHRoYXQgaWYgeW91ICpkb24ndCogY2FuY2VsIGNvbnRleHRtZW51LCB3ZSBjYW4gcHJldmVudCBwYXJ0aWFsIGRyYWdzLCB3aGljaFxuICogcHV0IHlvdSBpbiBhIHdlaXJkIHN0YXRlLlxuICpcbiAqIElmIHRoZSB1c2VyIGNsaWNrcyBtdWx0aXBsZSB0aW1lcyBxdWlja2x5LCBjbGlja0ZuIHdpbGwgZmlyZSBlYWNoIHRpbWVcbiAqIGJ1dCBudW1DbGlja3Mgd2lsbCBpbmNyZWFzZSB0byBoZWxwIHlvdSByZWNvZ25pemUgZG91YmxlY2xpY2tzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIHdpdGgga2V5czpcbiAqICAgICAgZWxlbWVudCAocmVxdWlyZWQpIHRoZSBET00gZWxlbWVudCB0byBkcmFnXG4gKiAgICAgIHByZXBGbiAob3B0aW9uYWwpIGZ1bmN0aW9uKGV2ZW50LCBzdGFydFgsIHN0YXJ0WSlcbiAqICAgICAgICAgIGV4ZWN1dGVkIG9uIG1vdXNlZG93blxuICogICAgICAgICAgc3RhcnRYIGFuZCBzdGFydFkgYXJlIHRoZSBjbGllbnRYIGFuZCBjbGllbnRZIHBpeGVsIHBvc2l0aW9uXG4gKiAgICAgICAgICBvZiB0aGUgbW91c2Vkb3duIGV2ZW50XG4gKiAgICAgIG1vdmVGbiAob3B0aW9uYWwpIGZ1bmN0aW9uKGR4LCBkeSlcbiAqICAgICAgICAgIGV4ZWN1dGVkIG9uIG1vdmUsIE9OTFkgYWZ0ZXIgd2UndmUgZXhjZWVkZWQgTUlORFJBR1xuICogICAgICAgICAgKHdlIGtlZXAgZXhlY3V0aW5nIG1vdmVGbiBpZiB5b3UgbW92ZSBiYWNrIHRvIHdoZXJlIHlvdSBzdGFydGVkKVxuICogICAgICAgICAgZHggYW5kIGR5IGFyZSB0aGUgbmV0IHBpeGVsIG9mZnNldCBvZiB0aGUgZHJhZyxcbiAqICAgICAgICAgIGRyYWdnZWQgaXMgdHJ1ZS9mYWxzZSwgaGFzIHRoZSBtb3VzZSBtb3ZlZCBlbm91Z2ggdG9cbiAqICAgICAgICAgIGNvbnN0aXR1dGUgYSBkcmFnXG4gKiAgICAgIGRvbmVGbiAob3B0aW9uYWwpIGZ1bmN0aW9uKGUpXG4gKiAgICAgICAgICBleGVjdXRlZCBvbiBtb3VzZXVwLCBPTkxZIGlmIHdlIGV4Y2VlZGVkIE1JTkRSQUcgKHNvIHlvdSBjYW4gYmVcbiAqICAgICAgICAgIHN1cmUgdGhhdCBtb3ZlRm4gaGFzIGJlZW4gY2FsbGVkIGF0IGxlYXN0IG9uY2UpXG4gKiAgICAgICAgICBudW1DbGlja3MgaXMgaG93IG1hbnkgY2xpY2tzIHdlJ3ZlIHJlZ2lzdGVyZWQgd2l0aGluXG4gKiAgICAgICAgICBhIGRvdWJsZWNsaWNrIHRpbWVcbiAqICAgICAgICAgIGUgaXMgdGhlIG9yaWdpbmFsIG1vdXNldXAgZXZlbnRcbiAqICAgICAgY2xpY2tGbiAob3B0aW9uYWwpIGZ1bmN0aW9uKG51bUNsaWNrcywgZSlcbiAqICAgICAgICAgIGV4ZWN1dGVkIG9uIG1vdXNldXAgaWYgd2UgaGF2ZSBOT1QgZXhjZWVkZWQgTUlORFJBRyAoaWUgbW92ZUZuXG4gKiAgICAgICAgICBoYXMgbm90IGJlZW4gY2FsbGVkIGF0IGFsbClcbiAqICAgICAgICAgIG51bUNsaWNrcyBpcyBob3cgbWFueSBjbGlja3Mgd2UndmUgcmVnaXN0ZXJlZCB3aXRoaW5cbiAqICAgICAgICAgIGEgZG91YmxlY2xpY2sgdGltZVxuICogICAgICAgICAgZSBpcyB0aGUgb3JpZ2luYWwgbW91c2Vkb3duIGV2ZW50XG4gKiAgICAgIGNsYW1wRm4gKG9wdGlvbmFsLCBmdW5jdGlvbihkeCwgZHkpIHJldHVybiBbZHgyLCBkeTJdKVxuICogICAgICAgICAgUHJvdmlkZSBjdXN0b20gY2xhbXBpbmcgZnVuY3Rpb24gZm9yIHNtYWxsIGRpc3BsYWNlbWVudHMuXG4gKiAgICAgICAgICBCeSBkZWZhdWx0LCBjbGFtcGluZyBpcyBkb25lIHVzaW5nIGBtaW5EcmFnYCB0byB4IGFuZCB5IGRpc3BsYWNlbWVudHNcbiAqICAgICAgICAgIGluZGVwZW5kZW50bHkuXG4gKi9cbmRyYWdFbGVtZW50LmluaXQgPSBmdW5jdGlvbiBpbml0KG9wdGlvbnMpIHtcbiAgICB2YXIgZ2QgPSBvcHRpb25zLmdkO1xuICAgIHZhciBudW1DbGlja3MgPSAxO1xuICAgIHZhciBEQkxDTElDS0RFTEFZID0gaW50ZXJhY3RDb25zdGFudHMuREJMQ0xJQ0tERUxBWTtcbiAgICB2YXIgZWxlbWVudCA9IG9wdGlvbnMuZWxlbWVudDtcblxuICAgIHZhciBzdGFydFgsXG4gICAgICAgIHN0YXJ0WSxcbiAgICAgICAgbmV3TW91c2VEb3duVGltZSxcbiAgICAgICAgY3Vyc29yLFxuICAgICAgICBkcmFnQ292ZXIsXG4gICAgICAgIGluaXRpYWxFdmVudCxcbiAgICAgICAgaW5pdGlhbFRhcmdldCxcbiAgICAgICAgcmlnaHRDbGljaztcblxuICAgIGlmKCFnZC5fbW91c2VEb3duVGltZSkgZ2QuX21vdXNlRG93blRpbWUgPSAwO1xuXG4gICAgZWxlbWVudC5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ2FsbCc7XG5cbiAgICBlbGVtZW50Lm9ubW91c2Vkb3duID0gb25TdGFydDtcblxuICAgIGlmKCFzdXBwb3J0c1Bhc3NpdmUpIHtcbiAgICAgICAgZWxlbWVudC5vbnRvdWNoc3RhcnQgPSBvblN0YXJ0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYoZWxlbWVudC5fb250b3VjaHN0YXJ0KSB7XG4gICAgICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBlbGVtZW50Ll9vbnRvdWNoc3RhcnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuX29udG91Y2hzdGFydCA9IG9uU3RhcnQ7XG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIG9uU3RhcnQsIHtwYXNzaXZlOiBmYWxzZX0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIF9jbGFtcEZuKGR4LCBkeSwgbWluRHJhZykge1xuICAgICAgICBpZihNYXRoLmFicyhkeCkgPCBtaW5EcmFnKSBkeCA9IDA7XG4gICAgICAgIGlmKE1hdGguYWJzKGR5KSA8IG1pbkRyYWcpIGR5ID0gMDtcbiAgICAgICAgcmV0dXJuIFtkeCwgZHldO1xuICAgIH1cblxuICAgIHZhciBjbGFtcEZuID0gb3B0aW9ucy5jbGFtcEZuIHx8IF9jbGFtcEZuO1xuXG4gICAgZnVuY3Rpb24gb25TdGFydChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAvLyBtYWtlIGRyYWdnaW5nIGFuZCBkcmFnZ2VkIGludG8gcHJvcGVydGllcyBvZiBnZFxuICAgICAgICAvLyBzbyB0aGF0IG90aGVycyBjYW4gbG9vayBhdCBhbmQgbW9kaWZ5IHRoZW1cbiAgICAgICAgZ2QuX2RyYWdnZWQgPSBmYWxzZTtcbiAgICAgICAgZ2QuX2RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgdmFyIG9mZnNldCA9IHBvaW50ZXJPZmZzZXQoZSk7XG4gICAgICAgIHN0YXJ0WCA9IG9mZnNldFswXTtcbiAgICAgICAgc3RhcnRZID0gb2Zmc2V0WzFdO1xuICAgICAgICBpbml0aWFsVGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgIGluaXRpYWxFdmVudCA9IGU7XG4gICAgICAgIHJpZ2h0Q2xpY2sgPSBlLmJ1dHRvbnMgPT09IDIgfHwgZS5jdHJsS2V5O1xuXG4gICAgICAgIC8vIGZpeCBGeC5ob3ZlciBmb3IgdG91Y2ggZXZlbnRzXG4gICAgICAgIGlmKHR5cGVvZiBlLmNsaWVudFggPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBlLmNsaWVudFkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBlLmNsaWVudFggPSBzdGFydFg7XG4gICAgICAgICAgICBlLmNsaWVudFkgPSBzdGFydFk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdNb3VzZURvd25UaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcbiAgICAgICAgaWYobmV3TW91c2VEb3duVGltZSAtIGdkLl9tb3VzZURvd25UaW1lIDwgREJMQ0xJQ0tERUxBWSkge1xuICAgICAgICAgICAgLy8gaW4gYSBjbGljayB0cmFpblxuICAgICAgICAgICAgbnVtQ2xpY2tzICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBuZXcgY2xpY2sgdHJhaW5cbiAgICAgICAgICAgIG51bUNsaWNrcyA9IDE7XG4gICAgICAgICAgICBnZC5fbW91c2VEb3duVGltZSA9IG5ld01vdXNlRG93blRpbWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihvcHRpb25zLnByZXBGbikgb3B0aW9ucy5wcmVwRm4oZSwgc3RhcnRYLCBzdGFydFkpO1xuXG4gICAgICAgIGlmKGhhc0hvdmVyICYmICFyaWdodENsaWNrKSB7XG4gICAgICAgICAgICBkcmFnQ292ZXIgPSBjb3ZlclNsaXAoKTtcbiAgICAgICAgICAgIGRyYWdDb3Zlci5zdHlsZS5jdXJzb3IgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KS5jdXJzb3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZighaGFzSG92ZXIpIHtcbiAgICAgICAgICAgIC8vIGRvY3VtZW50IGFjdHMgYXMgYSBkcmFnY292ZXIgZm9yIG1vYmlsZSwgYmMgd2UgY2FuJ3QgY3JlYXRlIGRyYWdjb3ZlciBkeW5hbWljYWxseVxuICAgICAgICAgICAgZHJhZ0NvdmVyID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICBjdXJzb3IgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmN1cnNvcjtcbiAgICAgICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KS5jdXJzb3I7XG4gICAgICAgIH1cblxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbk1vdmUpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Eb25lKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb25Nb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvbkRvbmUpO1xuXG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbk1vdmUoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IHBvaW50ZXJPZmZzZXQoZSk7XG4gICAgICAgIHZhciBtaW5EcmFnID0gb3B0aW9ucy5taW5EcmFnIHx8IGNvbnN0YW50cy5NSU5EUkFHO1xuICAgICAgICB2YXIgZHhkeSA9IGNsYW1wRm4ob2Zmc2V0WzBdIC0gc3RhcnRYLCBvZmZzZXRbMV0gLSBzdGFydFksIG1pbkRyYWcpO1xuICAgICAgICB2YXIgZHggPSBkeGR5WzBdO1xuICAgICAgICB2YXIgZHkgPSBkeGR5WzFdO1xuXG4gICAgICAgIGlmKGR4IHx8IGR5KSB7XG4gICAgICAgICAgICBnZC5fZHJhZ2dlZCA9IHRydWU7XG4gICAgICAgICAgICBkcmFnRWxlbWVudC51bmhvdmVyKGdkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGdkLl9kcmFnZ2VkICYmIG9wdGlvbnMubW92ZUZuICYmICFyaWdodENsaWNrKSBvcHRpb25zLm1vdmVGbihkeCwgZHkpO1xuXG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbkRvbmUoZSkge1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbk1vdmUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Eb25lKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb25Nb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvbkRvbmUpO1xuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZihoYXNIb3Zlcikge1xuICAgICAgICAgICAgTGliLnJlbW92ZUVsZW1lbnQoZHJhZ0NvdmVyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGN1cnNvcikge1xuICAgICAgICAgICAgZHJhZ0NvdmVyLmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSBjdXJzb3I7XG4gICAgICAgICAgICBjdXJzb3IgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWdkLl9kcmFnZ2luZykge1xuICAgICAgICAgICAgZ2QuX2RyYWdnZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBnZC5fZHJhZ2dpbmcgPSBmYWxzZTtcblxuICAgICAgICAvLyBkb24ndCBjb3VudCBhcyBhIGRibENsaWNrIHVubGVzcyB0aGUgbW91c2VVcCBpcyBhbHNvIHdpdGhpblxuICAgICAgICAvLyB0aGUgZGJsY2xpY2sgZGVsYXlcbiAgICAgICAgaWYoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIGdkLl9tb3VzZURvd25UaW1lID4gREJMQ0xJQ0tERUxBWSkge1xuICAgICAgICAgICAgbnVtQ2xpY2tzID0gTWF0aC5tYXgobnVtQ2xpY2tzIC0gMSwgMSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihnZC5fZHJhZ2dlZCkge1xuICAgICAgICAgICAgaWYob3B0aW9ucy5kb25lRm4pIG9wdGlvbnMuZG9uZUZuKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZihvcHRpb25zLmNsaWNrRm4pIG9wdGlvbnMuY2xpY2tGbihudW1DbGlja3MsIGluaXRpYWxFdmVudCk7XG5cbiAgICAgICAgICAgIC8vIElmIHdlIGhhdmVuJ3QgZHJhZ2dlZCwgdGhpcyBzaG91bGQgYmUgYSBjbGljay4gQnV0IGJlY2F1c2Ugb2YgdGhlXG4gICAgICAgICAgICAvLyBjb3ZlclNsaXAgY2hhbmdpbmcgdGhlIGVsZW1lbnQsIHRoZSBuYXR1cmFsIHN5c3RlbSBtaWdodCBub3QgZ2VuZXJhdGUgb25lLFxuICAgICAgICAgICAgLy8gc28gd2UgbmVlZCB0byBtYWtlIG91ciBvd24uIEJ1dCByaWdodCBjbGlja3MgZG9uJ3Qgbm9ybWFsbHkgZ2VuZXJhdGVcbiAgICAgICAgICAgIC8vIGNsaWNrIGV2ZW50cywgb25seSBjb250ZXh0bWVudSBldmVudHMsIHdoaWNoIGhhcHBlbiBvbiBtb3VzZWRvd24uXG4gICAgICAgICAgICBpZighcmlnaHRDbGljaykge1xuICAgICAgICAgICAgICAgIHZhciBlMjtcblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGUyID0gbmV3IE1vdXNlRXZlbnQoJ2NsaWNrJywgZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoKGVycikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gcG9pbnRlck9mZnNldChlKTtcbiAgICAgICAgICAgICAgICAgICAgZTIgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudHMnKTtcbiAgICAgICAgICAgICAgICAgICAgZTIuaW5pdE1vdXNlRXZlbnQoJ2NsaWNrJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuYnViYmxlcywgZS5jYW5jZWxhYmxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZS52aWV3LCBlLmRldGFpbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuc2NyZWVuWCwgZS5zY3JlZW5ZLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WzBdLCBvZmZzZXRbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBlLmN0cmxLZXksIGUuYWx0S2V5LCBlLnNoaWZ0S2V5LCBlLm1ldGFLZXksXG4gICAgICAgICAgICAgICAgICAgICAgICBlLmJ1dHRvbiwgZS5yZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpbml0aWFsVGFyZ2V0LmRpc3BhdGNoRXZlbnQoZTIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZmluaXNoRHJhZyhnZCk7XG5cbiAgICAgICAgZ2QuX2RyYWdnZWQgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm47XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY292ZXJTbGlwKCkge1xuICAgIHZhciBjb3ZlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgY292ZXIuY2xhc3NOYW1lID0gJ2RyYWdjb3Zlcic7XG4gICAgdmFyIGNTdHlsZSA9IGNvdmVyLnN0eWxlO1xuICAgIGNTdHlsZS5wb3NpdGlvbiA9ICdmaXhlZCc7XG4gICAgY1N0eWxlLmxlZnQgPSAwO1xuICAgIGNTdHlsZS5yaWdodCA9IDA7XG4gICAgY1N0eWxlLnRvcCA9IDA7XG4gICAgY1N0eWxlLmJvdHRvbSA9IDA7XG4gICAgY1N0eWxlLnpJbmRleCA9IDk5OTk5OTk5OTtcbiAgICBjU3R5bGUuYmFja2dyb3VuZCA9ICdub25lJztcblxuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY292ZXIpO1xuXG4gICAgcmV0dXJuIGNvdmVyO1xufVxuXG5kcmFnRWxlbWVudC5jb3ZlclNsaXAgPSBjb3ZlclNsaXA7XG5cbmZ1bmN0aW9uIGZpbmlzaERyYWcoZ2QpIHtcbiAgICBnZC5fZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICBpZihnZC5fcmVwbG90UGVuZGluZykgUmVnaXN0cnkuY2FsbCgncGxvdCcsIGdkKTtcbn1cblxuZnVuY3Rpb24gcG9pbnRlck9mZnNldChlKSB7XG4gICAgcmV0dXJuIG1vdXNlT2Zmc2V0KFxuICAgICAgICBlLmNoYW5nZWRUb3VjaGVzID8gZS5jaGFuZ2VkVG91Y2hlc1swXSA6IGUsXG4gICAgICAgIGRvY3VtZW50LmJvZHlcbiAgICApO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxudmFyIEV2ZW50cyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9ldmVudHMnKTtcbnZhciB0aHJvdHRsZSA9IHJlcXVpcmUoJy4uLy4uL2xpYi90aHJvdHRsZScpO1xudmFyIGdldEdyYXBoRGl2ID0gcmVxdWlyZSgnLi4vLi4vbGliL2dldF9ncmFwaF9kaXYnKTtcblxudmFyIGhvdmVyQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vZngvY29uc3RhbnRzJyk7XG5cbnZhciB1bmhvdmVyID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuXG51bmhvdmVyLndyYXBwZWQgPSBmdW5jdGlvbihnZCwgZXZ0LCBzdWJwbG90KSB7XG4gICAgZ2QgPSBnZXRHcmFwaERpdihnZCk7XG5cbiAgICAvLyBJbXBvcnRhbnQsIGNsZWFyIGFueSBxdWV1ZWQgaG92ZXJzXG4gICAgaWYoZ2QuX2Z1bGxMYXlvdXQpIHtcbiAgICAgICAgdGhyb3R0bGUuY2xlYXIoZ2QuX2Z1bGxMYXlvdXQuX3VpZCArIGhvdmVyQ29uc3RhbnRzLkhPVkVSSUQpO1xuICAgIH1cblxuICAgIHVuaG92ZXIucmF3KGdkLCBldnQsIHN1YnBsb3QpO1xufTtcblxuXG4vLyByZW1vdmUgaG92ZXIgZWZmZWN0cyBvbiBtb3VzZSBvdXQsIGFuZCBlbWl0IHVuaG92ZXIgZXZlbnRcbnVuaG92ZXIucmF3ID0gZnVuY3Rpb24gdW5ob3ZlclJhdyhnZCwgZXZ0KSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgb2xkaG92ZXJkYXRhID0gZ2QuX2hvdmVyZGF0YTtcblxuICAgIGlmKCFldnQpIGV2dCA9IHt9O1xuICAgIGlmKGV2dC50YXJnZXQgJiZcbiAgICAgICBFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfYmVmb3JlaG92ZXInLCBldnQpID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVsbExheW91dC5faG92ZXJsYXllci5zZWxlY3RBbGwoJ2cnKS5yZW1vdmUoKTtcbiAgICBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLnNlbGVjdEFsbCgnbGluZScpLnJlbW92ZSgpO1xuICAgIGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIuc2VsZWN0QWxsKCdjaXJjbGUnKS5yZW1vdmUoKTtcbiAgICBnZC5faG92ZXJkYXRhID0gdW5kZWZpbmVkO1xuXG4gICAgaWYoZXZ0LnRhcmdldCAmJiBvbGRob3ZlcmRhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7XG4gICAgICAgICAgICBldmVudDogZXZ0LFxuICAgICAgICAgICAgcG9pbnRzOiBvbGRob3ZlcmRhdGFcbiAgICAgICAgfSk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmRhc2ggPSB7XG4gICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgLy8gc3RyaW5nIHR5cGUgdXN1YWxseSBkb2Vzbid0IHRha2UgdmFsdWVzLi4uIHRoaXMgb25lIHNob3VsZCByZWFsbHkgYmVcbiAgICAvLyBhIHNwZWNpYWwgdHlwZSBvciBhdCBsZWFzdCBhIHNwZWNpYWwgY29lcmNpb24gZnVuY3Rpb24sIGZyb20gdGhlIEdVSVxuICAgIC8vIHlvdSBvbmx5IGdldCB0aGVzZSB2YWx1ZXMgYnV0IGVsc2V3aGVyZSB0aGUgdXNlciBjYW4gc3VwcGx5IGEgbGlzdCBvZlxuICAgIC8vIGRhc2ggbGVuZ3RocyBpbiBweCwgYW5kIGl0IHdpbGwgYmUgaG9ub3JlZFxuICAgIHZhbHVlczogWydzb2xpZCcsICdkb3QnLCAnZGFzaCcsICdsb25nZGFzaCcsICdkYXNoZG90JywgJ2xvbmdkYXNoZG90J10sXG4gICAgZGZsdDogJ3NvbGlkJyxcbiAgICBcbiAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICBcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIHRpbnljb2xvciA9IHJlcXVpcmUoJ3Rpbnljb2xvcjInKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG52YXIgQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uL2NvbG9yc2NhbGUnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBzdmdUZXh0VXRpbHMgPSByZXF1aXJlKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcblxudmFyIHhtbG5zTmFtZXNwYWNlcyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG52YXIgYWxpZ25tZW50ID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpO1xudmFyIExJTkVfU1BBQ0lORyA9IGFsaWdubWVudC5MSU5FX1NQQUNJTkc7XG52YXIgREVTRUxFQ1RESU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvaW50ZXJhY3Rpb25zJykuREVTRUxFQ1RESU07XG5cbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgbWFrZUJ1YmJsZVNpemVGbiA9IHJlcXVpcmUoJy4uLy4uL3RyYWNlcy9zY2F0dGVyL21ha2VfYnViYmxlX3NpemVfZnVuYycpO1xuXG52YXIgZHJhd2luZyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBzdHlsaW5nIGZ1bmN0aW9ucyBmb3IgcGxvdCBlbGVtZW50c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZHJhd2luZy5mb250ID0gZnVuY3Rpb24ocywgZmFtaWx5LCBzaXplLCBjb2xvcikge1xuICAgIC8vIGFsc28gYWxsb3cgdGhlIGZvcm0gZm9udChzLCB7ZmFtaWx5LCBzaXplLCBjb2xvcn0pXG4gICAgaWYoTGliLmlzUGxhaW5PYmplY3QoZmFtaWx5KSkge1xuICAgICAgICBjb2xvciA9IGZhbWlseS5jb2xvcjtcbiAgICAgICAgc2l6ZSA9IGZhbWlseS5zaXplO1xuICAgICAgICBmYW1pbHkgPSBmYW1pbHkuZmFtaWx5O1xuICAgIH1cbiAgICBpZihmYW1pbHkpIHMuc3R5bGUoJ2ZvbnQtZmFtaWx5JywgZmFtaWx5KTtcbiAgICBpZihzaXplICsgMSkgcy5zdHlsZSgnZm9udC1zaXplJywgc2l6ZSArICdweCcpO1xuICAgIGlmKGNvbG9yKSBzLmNhbGwoQ29sb3IuZmlsbCwgY29sb3IpO1xufTtcblxuLypcbiAqIFBvc2l0aW9uaW5nIGhlbHBlcnNcbiAqIE5vdGU6IGRvIG5vdCB1c2UgYHNldFBvc2l0aW9uYCB3aXRoIDx0ZXh0PiBub2RlcyBtb2RpZmllZCBieVxuICogYHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnNgLiBVc2UgYHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHRgXG4gKiBpbnN0ZWFkLCBzbyB0aGF0IDx0c3Bhbi5saW5lPiBlbGVtZW50cyBnZXQgdXBkYXRlZCB0byBtYXRjaC5cbiAqL1xuZHJhd2luZy5zZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKHMsIHgsIHkpIHsgcy5hdHRyKCd4JywgeCkuYXR0cigneScsIHkpOyB9O1xuZHJhd2luZy5zZXRTaXplID0gZnVuY3Rpb24ocywgdywgaCkgeyBzLmF0dHIoJ3dpZHRoJywgdykuYXR0cignaGVpZ2h0JywgaCk7IH07XG5kcmF3aW5nLnNldFJlY3QgPSBmdW5jdGlvbihzLCB4LCB5LCB3LCBoKSB7XG4gICAgcy5jYWxsKGRyYXdpbmcuc2V0UG9zaXRpb24sIHgsIHkpLmNhbGwoZHJhd2luZy5zZXRTaXplLCB3LCBoKTtcbn07XG5cbi8qKiBUcmFuc2xhdGUgbm9kZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBkIDogY2FsY2RhdGEgcG9pbnQgaXRlbVxuICogQHBhcmFtIHtzZWx9IHNlbCA6IGQzIHNlbGN0aW9uIG9mIG5vZGUgdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge29iamVjdH0geGEgOiBjb3JyZXNwb25kaW5nIGZ1bGwgeGF4aXMgb2JqZWN0XG4gKiBAcGFyYW0ge29iamVjdH0geWEgOiBjb3JyZXNwb25kaW5nIGZ1bGwgeWF4aXMgb2JqZWN0XG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gOlxuICogIHRydWUgaWYgc2VsZWN0aW9uIGdvdCB0cmFuc2xhdGVkXG4gKiAgZmFsc2UgaWYgc2VsZWN0aW9uIGNvdWxkIG5vdCBnZXQgdHJhbnNsYXRlZFxuICovXG5kcmF3aW5nLnRyYW5zbGF0ZVBvaW50ID0gZnVuY3Rpb24oZCwgc2VsLCB4YSwgeWEpIHtcbiAgICB2YXIgeCA9IHhhLmMycChkLngpO1xuICAgIHZhciB5ID0geWEuYzJwKGQueSk7XG5cbiAgICBpZihpc051bWVyaWMoeCkgJiYgaXNOdW1lcmljKHkpICYmIHNlbC5ub2RlKCkpIHtcbiAgICAgICAgLy8gZm9yIG11bHRpbGluZSB0ZXh0IHRoaXMgd29ya3MgYmV0dGVyXG4gICAgICAgIGlmKHNlbC5ub2RlKCkubm9kZU5hbWUgPT09ICd0ZXh0Jykge1xuICAgICAgICAgICAgc2VsLmF0dHIoJ3gnLCB4KS5hdHRyKCd5JywgeSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgeCArICcsJyArIHkgKyAnKScpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuZHJhd2luZy50cmFuc2xhdGVQb2ludHMgPSBmdW5jdGlvbihzLCB4YSwgeWEpIHtcbiAgICBzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICBkcmF3aW5nLnRyYW5zbGF0ZVBvaW50KGQsIHNlbCwgeGEsIHlhKTtcbiAgICB9KTtcbn07XG5cbmRyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50ID0gZnVuY3Rpb24oZCwgc2VsLCB4YSwgeWEsIHhjYWxlbmRhciwgeWNhbGVuZGFyKSB7XG4gICAgc2VsLmF0dHIoXG4gICAgICAgICdkaXNwbGF5JyxcbiAgICAgICAgKHhhLmlzUHRXaXRoaW5SYW5nZShkLCB4Y2FsZW5kYXIpICYmIHlhLmlzUHRXaXRoaW5SYW5nZShkLCB5Y2FsZW5kYXIpKSA/IG51bGwgOiAnbm9uZSdcbiAgICApO1xufTtcblxuZHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnRzID0gZnVuY3Rpb24odHJhY2VHcm91cHMsIHN1YnBsb3QpIHtcbiAgICBpZighc3VicGxvdC5faGFzQ2xpcE9uQXhpc0ZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgeGEgPSBzdWJwbG90LnhheGlzO1xuICAgIHZhciB5YSA9IHN1YnBsb3QueWF4aXM7XG5cbiAgICB0cmFjZUdyb3Vwcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcbiAgICAgICAgdmFyIHhjYWxlbmRhciA9IHRyYWNlLnhjYWxlbmRhcjtcbiAgICAgICAgdmFyIHljYWxlbmRhciA9IHRyYWNlLnljYWxlbmRhcjtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gdHJhY2UudHlwZSA9PT0gJ2JhcicgPyAnLmJhcnRleHQnIDogJy5wb2ludCwudGV4dHBvaW50JztcblxuICAgICAgICB0cmFjZUdyb3Vwcy5zZWxlY3RBbGwoc2VsZWN0b3IpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgZHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnQoZCwgZDMuc2VsZWN0KHRoaXMpLCB4YSwgeWEsIHhjYWxlbmRhciwgeWNhbGVuZGFyKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5kcmF3aW5nLmNyaXNwUm91bmQgPSBmdW5jdGlvbihnZCwgbGluZVdpZHRoLCBkZmx0KSB7XG4gICAgLy8gZm9yIGxpbmVzIHRoYXQgZGlzYWJsZSBhbnRpYWxpYXNpbmcgd2Ugd2FudCB0b1xuICAgIC8vIG1ha2Ugc3VyZSB0aGUgd2lkdGggaXMgYW4gaW50ZWdlciwgYW5kIGF0IGxlYXN0IDEgaWYgaXQncyBub256ZXJvXG5cbiAgICBpZighbGluZVdpZHRoIHx8ICFpc051bWVyaWMobGluZVdpZHRoKSkgcmV0dXJuIGRmbHQgfHwgMDtcblxuICAgIC8vIGJ1dCBub3QgZm9yIHN0YXRpYyBwbG90cyAtIHRoZXNlIGRvbid0IGdldCBhbnRpYWxpYXNlZCBhbnl3YXkuXG4gICAgaWYoZ2QuX2NvbnRleHQuc3RhdGljUGxvdCkgcmV0dXJuIGxpbmVXaWR0aDtcblxuICAgIGlmKGxpbmVXaWR0aCA8IDEpIHJldHVybiAxO1xuICAgIHJldHVybiBNYXRoLnJvdW5kKGxpbmVXaWR0aCk7XG59O1xuXG5kcmF3aW5nLnNpbmdsZUxpbmVTdHlsZSA9IGZ1bmN0aW9uKGQsIHMsIGx3LCBsYywgbGQpIHtcbiAgICBzLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICB2YXIgbGluZSA9ICgoKGQgfHwgW10pWzBdIHx8IHt9KS50cmFjZSB8fCB7fSkubGluZSB8fCB7fSxcbiAgICAgICAgbHcxID0gbHcgfHwgbGluZS53aWR0aHx8MCxcbiAgICAgICAgZGFzaCA9IGxkIHx8IGxpbmUuZGFzaCB8fCAnJztcblxuICAgIENvbG9yLnN0cm9rZShzLCBsYyB8fCBsaW5lLmNvbG9yKTtcbiAgICBkcmF3aW5nLmRhc2hMaW5lKHMsIGRhc2gsIGx3MSk7XG59O1xuXG5kcmF3aW5nLmxpbmVHcm91cFN0eWxlID0gZnVuY3Rpb24ocywgbHcsIGxjLCBsZCkge1xuICAgIHMuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgbGluZSA9ICgoKGQgfHwgW10pWzBdIHx8IHt9KS50cmFjZSB8fCB7fSkubGluZSB8fCB7fSxcbiAgICAgICAgICAgIGx3MSA9IGx3IHx8IGxpbmUud2lkdGh8fDAsXG4gICAgICAgICAgICBkYXNoID0gbGQgfHwgbGluZS5kYXNoIHx8ICcnO1xuXG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBsYyB8fCBsaW5lLmNvbG9yKVxuICAgICAgICAgICAgLmNhbGwoZHJhd2luZy5kYXNoTGluZSwgZGFzaCwgbHcxKTtcbiAgICB9KTtcbn07XG5cbmRyYXdpbmcuZGFzaExpbmUgPSBmdW5jdGlvbihzLCBkYXNoLCBsaW5lV2lkdGgpIHtcbiAgICBsaW5lV2lkdGggPSArbGluZVdpZHRoIHx8IDA7XG5cbiAgICBkYXNoID0gZHJhd2luZy5kYXNoU3R5bGUoZGFzaCwgbGluZVdpZHRoKTtcblxuICAgIHMuc3R5bGUoe1xuICAgICAgICAnc3Ryb2tlLWRhc2hhcnJheSc6IGRhc2gsXG4gICAgICAgICdzdHJva2Utd2lkdGgnOiBsaW5lV2lkdGggKyAncHgnXG4gICAgfSk7XG59O1xuXG5kcmF3aW5nLmRhc2hTdHlsZSA9IGZ1bmN0aW9uKGRhc2gsIGxpbmVXaWR0aCkge1xuICAgIGxpbmVXaWR0aCA9ICtsaW5lV2lkdGggfHwgMTtcbiAgICB2YXIgZGx3ID0gTWF0aC5tYXgobGluZVdpZHRoLCAzKTtcblxuICAgIGlmKGRhc2ggPT09ICdzb2xpZCcpIGRhc2ggPSAnJztcbiAgICBlbHNlIGlmKGRhc2ggPT09ICdkb3QnKSBkYXNoID0gZGx3ICsgJ3B4LCcgKyBkbHcgKyAncHgnO1xuICAgIGVsc2UgaWYoZGFzaCA9PT0gJ2Rhc2gnKSBkYXNoID0gKDMgKiBkbHcpICsgJ3B4LCcgKyAoMyAqIGRsdykgKyAncHgnO1xuICAgIGVsc2UgaWYoZGFzaCA9PT0gJ2xvbmdkYXNoJykgZGFzaCA9ICg1ICogZGx3KSArICdweCwnICsgKDUgKiBkbHcpICsgJ3B4JztcbiAgICBlbHNlIGlmKGRhc2ggPT09ICdkYXNoZG90Jykge1xuICAgICAgICBkYXNoID0gKDMgKiBkbHcpICsgJ3B4LCcgKyBkbHcgKyAncHgsJyArIGRsdyArICdweCwnICsgZGx3ICsgJ3B4JztcbiAgICB9XG4gICAgZWxzZSBpZihkYXNoID09PSAnbG9uZ2Rhc2hkb3QnKSB7XG4gICAgICAgIGRhc2ggPSAoNSAqIGRsdykgKyAncHgsJyArICgyICogZGx3KSArICdweCwnICsgZGx3ICsgJ3B4LCcgKyAoMiAqIGRsdykgKyAncHgnO1xuICAgIH1cbiAgICAvLyBvdGhlcndpc2UgdXNlciB3cm90ZSB0aGUgZGFzaGFycmF5IHRoZW1zZWx2ZXMgLSBsZWF2ZSBpdCBiZVxuXG4gICAgcmV0dXJuIGRhc2g7XG59O1xuXG4vLyBTYW1lIGFzIGZpbGxHcm91cFN0eWxlLCBleGNlcHQgaW4gdGhpcyBjYXNlIHRoZSBzZWxlY3Rpb24gbWF5IGJlIGEgdHJhbnNpdGlvblxuZHJhd2luZy5zaW5nbGVGaWxsU3R5bGUgPSBmdW5jdGlvbihzZWwpIHtcbiAgICB2YXIgbm9kZSA9IGQzLnNlbGVjdChzZWwubm9kZSgpKTtcbiAgICB2YXIgZGF0YSA9IG5vZGUuZGF0YSgpO1xuICAgIHZhciBmaWxsY29sb3IgPSAoKChkYXRhWzBdIHx8IFtdKVswXSB8fCB7fSkudHJhY2UgfHwge30pLmZpbGxjb2xvcjtcbiAgICBpZihmaWxsY29sb3IpIHtcbiAgICAgICAgc2VsLmNhbGwoQ29sb3IuZmlsbCwgZmlsbGNvbG9yKTtcbiAgICB9XG59O1xuXG5kcmF3aW5nLmZpbGxHcm91cFN0eWxlID0gZnVuY3Rpb24ocykge1xuICAgIHMuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIDApXG4gICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2hhcGUgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHNoYXBlLmNhbGwoQ29sb3IuZmlsbCwgZFswXS50cmFjZS5maWxsY29sb3IpO1xuICAgIH0pO1xufTtcblxudmFyIFNZTUJPTERFRlMgPSByZXF1aXJlKCcuL3N5bWJvbF9kZWZzJyk7XG5cbmRyYXdpbmcuc3ltYm9sTmFtZXMgPSBbXTtcbmRyYXdpbmcuc3ltYm9sRnVuY3MgPSBbXTtcbmRyYXdpbmcuc3ltYm9sTmVlZExpbmVzID0ge307XG5kcmF3aW5nLnN5bWJvbE5vRG90ID0ge307XG5kcmF3aW5nLnN5bWJvbE5vRmlsbCA9IHt9O1xuZHJhd2luZy5zeW1ib2xMaXN0ID0gW107XG5cbk9iamVjdC5rZXlzKFNZTUJPTERFRlMpLmZvckVhY2goZnVuY3Rpb24oaykge1xuICAgIHZhciBzeW1EZWYgPSBTWU1CT0xERUZTW2tdO1xuICAgIGRyYXdpbmcuc3ltYm9sTGlzdCA9IGRyYXdpbmcuc3ltYm9sTGlzdC5jb25jYXQoXG4gICAgICAgIFtzeW1EZWYubiwgaywgc3ltRGVmLm4gKyAxMDAsIGsgKyAnLW9wZW4nXSk7XG4gICAgZHJhd2luZy5zeW1ib2xOYW1lc1tzeW1EZWYubl0gPSBrO1xuICAgIGRyYXdpbmcuc3ltYm9sRnVuY3Nbc3ltRGVmLm5dID0gc3ltRGVmLmY7XG4gICAgaWYoc3ltRGVmLm5lZWRMaW5lKSB7XG4gICAgICAgIGRyYXdpbmcuc3ltYm9sTmVlZExpbmVzW3N5bURlZi5uXSA9IHRydWU7XG4gICAgfVxuICAgIGlmKHN5bURlZi5ub0RvdCkge1xuICAgICAgICBkcmF3aW5nLnN5bWJvbE5vRG90W3N5bURlZi5uXSA9IHRydWU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkcmF3aW5nLnN5bWJvbExpc3QgPSBkcmF3aW5nLnN5bWJvbExpc3QuY29uY2F0KFxuICAgICAgICAgICAgW3N5bURlZi5uICsgMjAwLCBrICsgJy1kb3QnLCBzeW1EZWYubiArIDMwMCwgayArICctb3Blbi1kb3QnXSk7XG4gICAgfVxuICAgIGlmKHN5bURlZi5ub0ZpbGwpIHtcbiAgICAgICAgZHJhd2luZy5zeW1ib2xOb0ZpbGxbc3ltRGVmLm5dID0gdHJ1ZTtcbiAgICB9XG59KTtcbnZhciBNQVhTWU1CT0wgPSBkcmF3aW5nLnN5bWJvbE5hbWVzLmxlbmd0aCxcbiAgICAvLyBhZGQgYSBkb3QgaW4gdGhlIG1pZGRsZSBvZiB0aGUgc3ltYm9sXG4gICAgRE9UUEFUSCA9ICdNMCwwLjVMMC41LDBMMCwtMC41TC0wLjUsMFonO1xuXG5kcmF3aW5nLnN5bWJvbE51bWJlciA9IGZ1bmN0aW9uKHYpIHtcbiAgICBpZih0eXBlb2YgdiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIHZiYXNlID0gMDtcbiAgICAgICAgaWYodi5pbmRleE9mKCctb3BlbicpID4gMCkge1xuICAgICAgICAgICAgdmJhc2UgPSAxMDA7XG4gICAgICAgICAgICB2ID0gdi5yZXBsYWNlKCctb3BlbicsICcnKTtcbiAgICAgICAgfVxuICAgICAgICBpZih2LmluZGV4T2YoJy1kb3QnKSA+IDApIHtcbiAgICAgICAgICAgIHZiYXNlICs9IDIwMDtcbiAgICAgICAgICAgIHYgPSB2LnJlcGxhY2UoJy1kb3QnLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgdiA9IGRyYXdpbmcuc3ltYm9sTmFtZXMuaW5kZXhPZih2KTtcbiAgICAgICAgaWYodiA+PSAwKSB7IHYgKz0gdmJhc2U7IH1cbiAgICB9XG4gICAgaWYoKHYgJSAxMDAgPj0gTUFYU1lNQk9MKSB8fCB2ID49IDQwMCkgeyByZXR1cm4gMDsgfVxuICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWF4KHYsIDApKTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VQb2ludFBhdGgoc3ltYm9sTnVtYmVyLCByKSB7XG4gICAgdmFyIGJhc2UgPSBzeW1ib2xOdW1iZXIgJSAxMDA7XG4gICAgcmV0dXJuIGRyYXdpbmcuc3ltYm9sRnVuY3NbYmFzZV0ocikgKyAoc3ltYm9sTnVtYmVyID49IDIwMCA/IERPVFBBVEggOiAnJyk7XG59XG5cbnZhciBIT1JaR1JBRElFTlQgPSB7eDE6IDEsIHgyOiAwLCB5MTogMCwgeTI6IDB9O1xudmFyIFZFUlRHUkFESUVOVCA9IHt4MTogMCwgeDI6IDAsIHkxOiAxLCB5MjogMH07XG52YXIgc3RvcEZvcm1hdHRlciA9IGQzLmZvcm1hdCgnfi4xZicpO1xudmFyIGdyYWRpZW50SW5mbyA9IHtcbiAgICByYWRpYWw6IHtub2RlOiAncmFkaWFsR3JhZGllbnQnfSxcbiAgICByYWRpYWxyZXZlcnNlZDoge25vZGU6ICdyYWRpYWxHcmFkaWVudCcsIHJldmVyc2VkOiB0cnVlfSxcbiAgICBob3Jpem9udGFsOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IEhPUlpHUkFESUVOVH0sXG4gICAgaG9yaXpvbnRhbHJldmVyc2VkOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IEhPUlpHUkFESUVOVCwgcmV2ZXJzZWQ6IHRydWV9LFxuICAgIHZlcnRpY2FsOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IFZFUlRHUkFESUVOVH0sXG4gICAgdmVydGljYWxyZXZlcnNlZDoge25vZGU6ICdsaW5lYXJHcmFkaWVudCcsIGF0dHJzOiBWRVJUR1JBRElFTlQsIHJldmVyc2VkOiB0cnVlfVxufTtcblxuLyoqXG4gKiBncmFkaWVudDogY3JlYXRlIGFuZCBhcHBseSBhIGdyYWRpZW50IGZpbGxcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc2VsOiBkMyBzZWxlY3Rpb24gdG8gYXBwbHkgdGhpcyBncmFkaWVudCB0b1xuICogICAgIFlvdSBjYW4gdXNlIGBzZWxlY3Rpb24uY2FsbChEcmF3aW5nLmdyYWRpZW50LCAuLi4pYFxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2Q6IHRoZSBncmFwaCBkaXYgYHNlbGAgaXMgcGFydCBvZlxuICogQHBhcmFtIHtzdHJpbmd9IGdyYWRpZW50SUQ6IGEgdW5pcXVlICh3aXRoaW4gdGhpcyBwbG90KSBpZGVudGlmaWVyXG4gKiAgICAgZm9yIHRoaXMgZ3JhZGllbnQsIHNvIHRoYXQgd2UgZG9uJ3QgY3JlYXRlIHVubmVjZXNzYXJ5IGRlZmluaXRpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZTogJ3JhZGlhbCcsICdob3Jpem9udGFsJywgb3IgJ3ZlcnRpY2FsJywgb3B0aW9uYWxseSB3aXRoXG4gKiAgICAgJ3JldmVyc2VkJyBhdCB0aGUgZW5kLiBOb3JtYWxseSByYWRpYWwgZ29lcyBjZW50ZXIgdG8gZWRnZSxcbiAqICAgICBob3Jpem9udGFsIGdvZXMgcmlnaHQgdG8gbGVmdCwgYW5kIHZlcnRpY2FsIGdvZXMgYm90dG9tIHRvIHRvcFxuICogQHBhcmFtIHthcnJheX0gY29sb3JzY2FsZTogYXMgaW4gYXR0cmlidXRlIHZhbHVlcywgW1tmcmFjdGlvbiwgY29sb3JdLCAuLi5dXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcDogdGhlIHByb3BlcnR5IHRvIGFwcGx5IHRvLCAnZmlsbCcgb3IgJ3N0cm9rZSdcbiAqL1xuZHJhd2luZy5ncmFkaWVudCA9IGZ1bmN0aW9uKHNlbCwgZ2QsIGdyYWRpZW50SUQsIHR5cGUsIGNvbG9yc2NhbGUsIHByb3ApIHtcbiAgICB2YXIgbGVuID0gY29sb3JzY2FsZS5sZW5ndGg7XG4gICAgdmFyIGluZm8gPSBncmFkaWVudEluZm9bdHlwZV07XG4gICAgdmFyIGNvbG9yU3RvcHMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYoaW5mby5yZXZlcnNlZCkge1xuICAgICAgICAgICAgY29sb3JTdG9wc1tsZW4gLSAxIC0gaV0gPSBbc3RvcEZvcm1hdHRlcigoMSAtIGNvbG9yc2NhbGVbaV1bMF0pICogMTAwKSwgY29sb3JzY2FsZVtpXVsxXV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb2xvclN0b3BzW2ldID0gW3N0b3BGb3JtYXR0ZXIoY29sb3JzY2FsZVtpXVswXSAqIDEwMCksIGNvbG9yc2NhbGVbaV1bMV1dO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGZ1bGxJRCA9ICdnJyArIGdkLl9mdWxsTGF5b3V0Ll91aWQgKyAnLScgKyBncmFkaWVudElEO1xuXG4gICAgdmFyIGdyYWRpZW50ID0gZ2QuX2Z1bGxMYXlvdXQuX2RlZnMuc2VsZWN0KCcuZ3JhZGllbnRzJylcbiAgICAgICAgLnNlbGVjdEFsbCgnIycgKyBmdWxsSUQpXG4gICAgICAgIC5kYXRhKFt0eXBlICsgY29sb3JTdG9wcy5qb2luKCc7JyldLCBMaWIuaWRlbnRpdHkpO1xuXG4gICAgZ3JhZGllbnQuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgZ3JhZGllbnQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKGluZm8ubm9kZSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBpZihpbmZvLmF0dHJzKSBlbC5hdHRyKGluZm8uYXR0cnMpO1xuXG4gICAgICAgICAgICBlbC5hdHRyKCdpZCcsIGZ1bGxJRCk7XG5cbiAgICAgICAgICAgIHZhciBzdG9wcyA9IGVsLnNlbGVjdEFsbCgnc3RvcCcpXG4gICAgICAgICAgICAgICAgLmRhdGEoY29sb3JTdG9wcyk7XG4gICAgICAgICAgICBzdG9wcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICBzdG9wcy5lbnRlcigpLmFwcGVuZCgnc3RvcCcpO1xuXG4gICAgICAgICAgICBzdG9wcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGMgPSB0aW55Y29sb3IoZFsxXSk7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IGRbMF0gKyAnJScsXG4gICAgICAgICAgICAgICAgICAgICdzdG9wLWNvbG9yJzogQ29sb3IudGlueVJHQih0YyksXG4gICAgICAgICAgICAgICAgICAgICdzdG9wLW9wYWNpdHknOiB0Yy5nZXRBbHBoYSgpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICBzZWwuc3R5bGUocHJvcCwgJ3VybCgjJyArIGZ1bGxJRCArICcpJylcbiAgICAgICAgLnN0eWxlKHByb3AgKyAnLW9wYWNpdHknLCBudWxsKTtcbn07XG5cbi8qXG4gKiBNYWtlIHRoZSBncmFkaWVudHMgY29udGFpbmVyIGFuZCBjbGVhciBvdXQgYW55IHByZXZpb3VzIGdyYWRpZW50cy5cbiAqIFdlIG5ldmVyIGNvbGxlY3QgYWxsIHRoZSBncmFkaWVudHMgd2UgbmVlZCBpbiBvbmUgcGxhY2UsXG4gKiBzbyB3ZSBjYW4ndCBldmVyIHJlbW92ZSBncmFkaWVudHMgdGhhdCBoYXZlIHN0b3BwZWQgYmVpbmcgdXNlZnVsLFxuICogZXhjZXB0IGFsbCBhdCBvbmNlIGJlZm9yZSBhIGZ1bGwgcmVkcmF3LlxuICogVGhlIHVwc2lkZSBvZiB0aGlzIGlzIGFyYml0cmFyeSBwb2ludHMgY2FuIHNoYXJlIGdyYWRpZW50IGRlZnNcbiAqL1xuZHJhd2luZy5pbml0R3JhZGllbnRzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZ3JhZGllbnRzR3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKGdkLl9mdWxsTGF5b3V0Ll9kZWZzLCAnZycsICdncmFkaWVudHMnKTtcbiAgICBncmFkaWVudHNHcm91cC5zZWxlY3RBbGwoJ2xpbmVhckdyYWRpZW50LHJhZGlhbEdyYWRpZW50JykucmVtb3ZlKCk7XG59O1xuXG5cbmRyYXdpbmcucG9pbnRTdHlsZSA9IGZ1bmN0aW9uKHMsIHRyYWNlLCBnZCkge1xuICAgIGlmKCFzLnNpemUoKSkgcmV0dXJuO1xuXG4gICAgdmFyIGZucyA9IGRyYXdpbmcubWFrZVBvaW50U3R5bGVGbnModHJhY2UpO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgZHJhd2luZy5zaW5nbGVQb2ludFN0eWxlKGQsIGQzLnNlbGVjdCh0aGlzKSwgdHJhY2UsIGZucywgZ2QpO1xuICAgIH0pO1xufTtcblxuZHJhd2luZy5zaW5nbGVQb2ludFN0eWxlID0gZnVuY3Rpb24oZCwgc2VsLCB0cmFjZSwgZm5zLCBnZCkge1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcblxuICAgIHNlbC5zdHlsZSgnb3BhY2l0eScsXG4gICAgICAgIGZucy5zZWxlY3RlZE9wYWNpdHlGbiA/IGZucy5zZWxlY3RlZE9wYWNpdHlGbihkKSA6XG4gICAgICAgICAgICAoZC5tbyA9PT0gdW5kZWZpbmVkID8gbWFya2VyLm9wYWNpdHkgOiBkLm1vKVxuICAgICk7XG5cbiAgICBpZihmbnMubXMybXJjKSB7XG4gICAgICAgIHZhciByO1xuXG4gICAgICAgIC8vIGhhbmRsZSBtdWx0aS10cmFjZSBncmFwaCBlZGl0IGNhc2VcbiAgICAgICAgaWYoZC5tcyA9PT0gJ3ZhcmlvdXMnIHx8IG1hcmtlci5zaXplID09PSAndmFyaW91cycpIHtcbiAgICAgICAgICAgIHIgPSAzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgciA9IGZucy5tczJtcmMoZC5tcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSB0aGUgY2FsY3VsYXRlZCBzaXplIHNvIGhvdmVyIGNhbiB1c2UgaXRcbiAgICAgICAgZC5tcmMgPSByO1xuXG4gICAgICAgIGlmKGZucy5zZWxlY3RlZFNpemVGbikge1xuICAgICAgICAgICAgciA9IGQubXJjID0gZm5zLnNlbGVjdGVkU2l6ZUZuKGQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHVybiB0aGUgc3ltYm9sIGludG8gYSBzYW5pdGl6ZWQgbnVtYmVyXG4gICAgICAgIHZhciB4ID0gZHJhd2luZy5zeW1ib2xOdW1iZXIoZC5teCB8fCBtYXJrZXIuc3ltYm9sKSB8fCAwO1xuXG4gICAgICAgIC8vIHNhdmUgaWYgdGhpcyBtYXJrZXIgaXMgb3BlblxuICAgICAgICAvLyBiZWNhdXNlIHRoYXQgaW1wYWN0cyBob3cgdG8gaGFuZGxlIGNvbG9yc1xuICAgICAgICBkLm9tID0geCAlIDIwMCA+PSAxMDA7XG5cbiAgICAgICAgc2VsLmF0dHIoJ2QnLCBtYWtlUG9pbnRQYXRoKHgsIHIpKTtcbiAgICB9XG5cbiAgICB2YXIgcGVyUG9pbnRHcmFkaWVudCA9IGZhbHNlO1xuICAgIHZhciBmaWxsQ29sb3IsIGxpbmVDb2xvciwgbGluZVdpZHRoO1xuXG4gICAgLy8gJ3NvJyBpcyBzdXNwZWN0ZWQgb3V0bGllcnMsIGZvciBib3ggcGxvdHNcbiAgICBpZihkLnNvKSB7XG4gICAgICAgIGxpbmVXaWR0aCA9IG1hcmtlckxpbmUub3V0bGllcndpZHRoO1xuICAgICAgICBsaW5lQ29sb3IgPSBtYXJrZXJMaW5lLm91dGxpZXJjb2xvcjtcbiAgICAgICAgZmlsbENvbG9yID0gbWFya2VyLm91dGxpZXJjb2xvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbWFya2VyTGluZVdpZHRoID0gKG1hcmtlckxpbmUgfHwge30pLndpZHRoO1xuXG4gICAgICAgIGxpbmVXaWR0aCA9IChcbiAgICAgICAgICAgIGQubWx3ICsgMSB8fFxuICAgICAgICAgICAgbWFya2VyTGluZVdpZHRoICsgMSB8fFxuICAgICAgICAgICAgLy8gVE9ETzogd2UgbmVlZCB0aGUgbGF0dGVyIGZvciBsZWdlbmRzLi4uIGNhbiB3ZSBnZXQgcmlkIG9mIGl0P1xuICAgICAgICAgICAgKGQudHJhY2UgPyAoZC50cmFjZS5tYXJrZXIubGluZSB8fCB7fSkud2lkdGggOiAwKSArIDFcbiAgICAgICAgKSAtIDEgfHwgMDtcblxuICAgICAgICBpZignbWxjJyBpbiBkKSBsaW5lQ29sb3IgPSBkLm1sY2MgPSBmbnMubGluZVNjYWxlKGQubWxjKTtcbiAgICAgICAgLy8gd2VpcmQgY2FzZTogYXJyYXkgd2Fzbid0IGxvbmcgZW5vdWdoIHRvIGFwcGx5IHRvIGV2ZXJ5IHBvaW50XG4gICAgICAgIGVsc2UgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyTGluZS5jb2xvcikpIGxpbmVDb2xvciA9IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICBlbHNlIGxpbmVDb2xvciA9IG1hcmtlckxpbmUuY29sb3I7XG5cbiAgICAgICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLmNvbG9yKSkge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gQ29sb3IuZGVmYXVsdExpbmU7XG4gICAgICAgICAgICBwZXJQb2ludEdyYWRpZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCdtYycgaW4gZCkge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gZC5tY2MgPSBmbnMubWFya2VyU2NhbGUoZC5tYyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmaWxsQ29sb3IgPSBtYXJrZXIuY29sb3IgfHwgJ3JnYmEoMCwwLDAsMCknO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZm5zLnNlbGVjdGVkQ29sb3JGbikge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gZm5zLnNlbGVjdGVkQ29sb3JGbihkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGQub20pIHtcbiAgICAgICAgLy8gb3BlbiBtYXJrZXJzIGNhbid0IGhhdmUgemVybyBsaW5ld2lkdGgsIGRlZmF1bHQgdG8gMXB4LFxuICAgICAgICAvLyBhbmQgdXNlIGZpbGwgY29sb3IgYXMgc3Ryb2tlIGNvbG9yXG4gICAgICAgIHNlbC5jYWxsKENvbG9yLnN0cm9rZSwgZmlsbENvbG9yKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogKGxpbmVXaWR0aCB8fCAxKSArICdweCcsXG4gICAgICAgICAgICAgICAgZmlsbDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzZWwuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGxpbmVXaWR0aCArICdweCcpO1xuXG4gICAgICAgIHZhciBtYXJrZXJHcmFkaWVudCA9IG1hcmtlci5ncmFkaWVudDtcblxuICAgICAgICB2YXIgZ3JhZGllbnRUeXBlID0gZC5tZ3Q7XG4gICAgICAgIGlmKGdyYWRpZW50VHlwZSkgcGVyUG9pbnRHcmFkaWVudCA9IHRydWU7XG4gICAgICAgIGVsc2UgZ3JhZGllbnRUeXBlID0gbWFya2VyR3JhZGllbnQgJiYgbWFya2VyR3JhZGllbnQudHlwZTtcblxuICAgICAgICAvLyBmb3IgbGVnZW5kIC0gYXJyYXlzIHdpbGwgcHJvcGFnYXRlIHRocm91Z2ggaGVyZSwgYnV0IHdlIGRvbid0IG5lZWRcbiAgICAgICAgLy8gdG8gdHJlYXQgaXQgYXMgcGVyLXBvaW50LlxuICAgICAgICBpZihBcnJheS5pc0FycmF5KGdyYWRpZW50VHlwZSkpIHtcbiAgICAgICAgICAgIGdyYWRpZW50VHlwZSA9IGdyYWRpZW50VHlwZVswXTtcbiAgICAgICAgICAgIGlmKCFncmFkaWVudEluZm9bZ3JhZGllbnRUeXBlXSkgZ3JhZGllbnRUeXBlID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGdyYWRpZW50VHlwZSAmJiBncmFkaWVudFR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgdmFyIGdyYWRpZW50Q29sb3IgPSBkLm1nYztcbiAgICAgICAgICAgIGlmKGdyYWRpZW50Q29sb3IpIHBlclBvaW50R3JhZGllbnQgPSB0cnVlO1xuICAgICAgICAgICAgZWxzZSBncmFkaWVudENvbG9yID0gbWFya2VyR3JhZGllbnQuY29sb3I7XG5cbiAgICAgICAgICAgIHZhciBncmFkaWVudElEID0gdHJhY2UudWlkO1xuICAgICAgICAgICAgaWYocGVyUG9pbnRHcmFkaWVudCkgZ3JhZGllbnRJRCArPSAnLScgKyBkLmk7XG5cbiAgICAgICAgICAgIGRyYXdpbmcuZ3JhZGllbnQoc2VsLCBnZCwgZ3JhZGllbnRJRCwgZ3JhZGllbnRUeXBlLFxuICAgICAgICAgICAgICAgIFtbMCwgZ3JhZGllbnRDb2xvcl0sIFsxLCBmaWxsQ29sb3JdXSwgJ2ZpbGwnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIENvbG9yLmZpbGwoc2VsLCBmaWxsQ29sb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobGluZVdpZHRoKSB7XG4gICAgICAgICAgICBDb2xvci5zdHJva2Uoc2VsLCBsaW5lQ29sb3IpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZHJhd2luZy5tYWtlUG9pbnRTdHlsZUZucyA9IGZ1bmN0aW9uKHRyYWNlKSB7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG5cbiAgICAvLyBhbGxvdyBhcnJheSBtYXJrZXIgYW5kIG1hcmtlciBsaW5lIGNvbG9ycyB0byBiZVxuICAgIC8vIHNjYWxlZCBieSBnaXZlbiBtYXggYW5kIG1pbiB0byBjb2xvcnNjYWxlc1xuICAgIG91dC5tYXJrZXJTY2FsZSA9IGRyYXdpbmcudHJ5Q29sb3JzY2FsZShtYXJrZXIsICcnKTtcbiAgICBvdXQubGluZVNjYWxlID0gZHJhd2luZy50cnlDb2xvcnNjYWxlKG1hcmtlciwgJ2xpbmUnKTtcblxuICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdzeW1ib2xzJykpIHtcbiAgICAgICAgb3V0Lm1zMm1yYyA9IHN1YlR5cGVzLmlzQnViYmxlKHRyYWNlKSA/XG4gICAgICAgICAgICBtYWtlQnViYmxlU2l6ZUZuKHRyYWNlKSA6XG4gICAgICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuIChtYXJrZXIuc2l6ZSB8fCA2KSAvIDI7IH07XG4gICAgfVxuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQob3V0LCBkcmF3aW5nLm1ha2VTZWxlY3RlZFBvaW50U3R5bGVGbnModHJhY2UpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5tYWtlU2VsZWN0ZWRQb2ludFN0eWxlRm5zID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgb3V0ID0ge307XG5cbiAgICB2YXIgc2VsZWN0ZWRBdHRycyA9IHRyYWNlLnNlbGVjdGVkIHx8IHt9O1xuICAgIHZhciB1bnNlbGVjdGVkQXR0cnMgPSB0cmFjZS51bnNlbGVjdGVkIHx8IHt9O1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgc2VsZWN0ZWRNYXJrZXIgPSBzZWxlY3RlZEF0dHJzLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgdW5zZWxlY3RlZE1hcmtlciA9IHVuc2VsZWN0ZWRBdHRycy5tYXJrZXIgfHwge307XG5cbiAgICB2YXIgbW8gPSBtYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgc21vID0gc2VsZWN0ZWRNYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgdXNtbyA9IHVuc2VsZWN0ZWRNYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgc21vSXNEZWZpbmVkID0gc21vICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIHVzbW9Jc0RlZmluZWQgPSB1c21vICE9PSB1bmRlZmluZWQ7XG5cbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtbykgfHwgc21vSXNEZWZpbmVkIHx8IHVzbW9Jc0RlZmluZWQpIHtcbiAgICAgICAgb3V0LnNlbGVjdGVkT3BhY2l0eUZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGJhc2UgPSBkLm1vID09PSB1bmRlZmluZWQgPyBtYXJrZXIub3BhY2l0eSA6IGQubW87XG5cbiAgICAgICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc21vSXNEZWZpbmVkID8gc21vIDogYmFzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVzbW9Jc0RlZmluZWQgPyB1c21vIDogREVTRUxFQ1RESU0gKiBiYXNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBtYyA9IG1hcmtlci5jb2xvcjtcbiAgICB2YXIgc21jID0gc2VsZWN0ZWRNYXJrZXIuY29sb3I7XG4gICAgdmFyIHVzbWMgPSB1bnNlbGVjdGVkTWFya2VyLmNvbG9yO1xuXG4gICAgaWYoc21jIHx8IHVzbWMpIHtcbiAgICAgICAgb3V0LnNlbGVjdGVkQ29sb3JGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBiYXNlID0gZC5tY2MgfHwgbWM7XG5cbiAgICAgICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc21jIHx8IGJhc2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB1c21jIHx8IGJhc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG1zID0gbWFya2VyLnNpemU7XG4gICAgdmFyIHNtcyA9IHNlbGVjdGVkTWFya2VyLnNpemU7XG4gICAgdmFyIHVzbXMgPSB1bnNlbGVjdGVkTWFya2VyLnNpemU7XG4gICAgdmFyIHNtc0lzRGVmaW5lZCA9IHNtcyAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciB1c21zSXNEZWZpbmVkID0gdXNtcyAhPT0gdW5kZWZpbmVkO1xuXG4gICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3N5bWJvbHMnKSAmJiAoc21zSXNEZWZpbmVkIHx8IHVzbXNJc0RlZmluZWQpKSB7XG4gICAgICAgIG91dC5zZWxlY3RlZFNpemVGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBiYXNlID0gZC5tcmMgfHwgbXMgLyAyO1xuXG4gICAgICAgICAgICBpZihkLnNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNtc0lzRGVmaW5lZCA/IHNtcyAvIDIgOiBiYXNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdXNtc0lzRGVmaW5lZCA/IHVzbXMgLyAyIDogYmFzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5tYWtlU2VsZWN0ZWRUZXh0U3R5bGVGbnMgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBvdXQgPSB7fTtcblxuICAgIHZhciBzZWxlY3RlZEF0dHJzID0gdHJhY2Uuc2VsZWN0ZWQgfHwge307XG4gICAgdmFyIHVuc2VsZWN0ZWRBdHRycyA9IHRyYWNlLnVuc2VsZWN0ZWQgfHwge307XG5cbiAgICB2YXIgdGV4dEZvbnQgPSB0cmFjZS50ZXh0Zm9udCB8fCB7fTtcbiAgICB2YXIgc2VsZWN0ZWRUZXh0Rm9udCA9IHNlbGVjdGVkQXR0cnMudGV4dGZvbnQgfHwge307XG4gICAgdmFyIHVuc2VsZWN0ZWRUZXh0Rm9udCA9IHVuc2VsZWN0ZWRBdHRycy50ZXh0Zm9udCB8fCB7fTtcblxuICAgIHZhciB0YyA9IHRleHRGb250LmNvbG9yO1xuICAgIHZhciBzdGMgPSBzZWxlY3RlZFRleHRGb250LmNvbG9yO1xuICAgIHZhciB1dGMgPSB1bnNlbGVjdGVkVGV4dEZvbnQuY29sb3I7XG5cbiAgICBvdXQuc2VsZWN0ZWRUZXh0Q29sb3JGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGJhc2UgPSBkLnRjIHx8IHRjO1xuXG4gICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGMgfHwgYmFzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKHV0YykgcmV0dXJuIHV0YztcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuIHN0YyA/IGJhc2UgOiBDb2xvci5hZGRPcGFjaXR5KGJhc2UsIERFU0VMRUNURElNKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5zZWxlY3RlZFBvaW50U3R5bGUgPSBmdW5jdGlvbihzLCB0cmFjZSkge1xuICAgIGlmKCFzLnNpemUoKSB8fCAhdHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHJldHVybjtcblxuICAgIHZhciBmbnMgPSBkcmF3aW5nLm1ha2VTZWxlY3RlZFBvaW50U3R5bGVGbnModHJhY2UpO1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXIgfHwge307XG4gICAgdmFyIHNlcSA9IFtdO1xuXG4gICAgaWYoZm5zLnNlbGVjdGVkT3BhY2l0eUZuKSB7XG4gICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKHB0LCBkKSB7XG4gICAgICAgICAgICBwdC5zdHlsZSgnb3BhY2l0eScsIGZucy5zZWxlY3RlZE9wYWNpdHlGbihkKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGZucy5zZWxlY3RlZENvbG9yRm4pIHtcbiAgICAgICAgc2VxLnB1c2goZnVuY3Rpb24ocHQsIGQpIHtcbiAgICAgICAgICAgIENvbG9yLmZpbGwocHQsIGZucy5zZWxlY3RlZENvbG9yRm4oZCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihmbnMuc2VsZWN0ZWRTaXplRm4pIHtcbiAgICAgICAgc2VxLnB1c2goZnVuY3Rpb24ocHQsIGQpIHtcbiAgICAgICAgICAgIHZhciBteCA9IGQubXggfHwgbWFya2VyLnN5bWJvbCB8fCAwO1xuICAgICAgICAgICAgdmFyIG1yYzIgPSBmbnMuc2VsZWN0ZWRTaXplRm4oZCk7XG5cbiAgICAgICAgICAgIHB0LmF0dHIoJ2QnLCBtYWtlUG9pbnRQYXRoKGRyYXdpbmcuc3ltYm9sTnVtYmVyKG14KSwgbXJjMikpO1xuXG4gICAgICAgICAgICAvLyBzYXZlIGZvciBEcmF3aW5nLnNlbGVjdGVkVGV4dFN0eWxlXG4gICAgICAgICAgICBkLm1yYzIgPSBtcmMyO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihzZXEubGVuZ3RoKSB7XG4gICAgICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcHQgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VxLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2VxW2ldKHB0LCBkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxuZHJhd2luZy50cnlDb2xvcnNjYWxlID0gZnVuY3Rpb24obWFya2VyLCBwcmVmaXgpIHtcbiAgICB2YXIgY29udCA9IHByZWZpeCA/IExpYi5uZXN0ZWRQcm9wZXJ0eShtYXJrZXIsIHByZWZpeCkuZ2V0KCkgOiBtYXJrZXI7XG5cbiAgICBpZihjb250KSB7XG4gICAgICAgIHZhciBzY2wgPSBjb250LmNvbG9yc2NhbGU7XG4gICAgICAgIHZhciBjb2xvckFycmF5ID0gY29udC5jb2xvcjtcblxuICAgICAgICBpZihzY2wgJiYgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoY29sb3JBcnJheSkpIHtcbiAgICAgICAgICAgIHJldHVybiBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuYyhcbiAgICAgICAgICAgICAgICBDb2xvcnNjYWxlLmV4dHJhY3RTY2FsZShzY2wsIGNvbnQuY21pbiwgY29udC5jbWF4KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gTGliLmlkZW50aXR5O1xufTtcblxudmFyIFRFWFRPRkZTRVRTSUdOID0ge1xuICAgIHN0YXJ0OiAxLCBlbmQ6IC0xLCBtaWRkbGU6IDAsIGJvdHRvbTogMSwgdG9wOiAtMVxufTtcblxuZnVuY3Rpb24gdGV4dFBvaW50UG9zaXRpb24ocywgdGV4dFBvc2l0aW9uLCBmb250U2l6ZSwgbWFya2VyUmFkaXVzKSB7XG4gICAgdmFyIGdyb3VwID0gZDMuc2VsZWN0KHMubm9kZSgpLnBhcmVudE5vZGUpO1xuXG4gICAgdmFyIHYgPSB0ZXh0UG9zaXRpb24uaW5kZXhPZigndG9wJykgIT09IC0xID9cbiAgICAgICAgJ3RvcCcgOlxuICAgICAgICB0ZXh0UG9zaXRpb24uaW5kZXhPZignYm90dG9tJykgIT09IC0xID8gJ2JvdHRvbScgOiAnbWlkZGxlJztcbiAgICB2YXIgaCA9IHRleHRQb3NpdGlvbi5pbmRleE9mKCdsZWZ0JykgIT09IC0xID9cbiAgICAgICAgJ2VuZCcgOlxuICAgICAgICB0ZXh0UG9zaXRpb24uaW5kZXhPZigncmlnaHQnKSAhPT0gLTEgPyAnc3RhcnQnIDogJ21pZGRsZSc7XG5cbiAgICAvLyBpZiBtYXJrZXJzIGFyZSBzaG93biwgb2Zmc2V0IGEgbGl0dGxlIG1vcmUgdGhhblxuICAgIC8vIHRoZSBub21pbmFsIG1hcmtlciBzaXplXG4gICAgLy8gaWUgMi8xLjYgKiBub21pbmFsLCBiY3Mgc29tZSBtYXJrZXJzIGFyZSBhIGJpdCBiaWdnZXJcbiAgICB2YXIgciA9IG1hcmtlclJhZGl1cyA/IG1hcmtlclJhZGl1cyAvIDAuOCArIDEgOiAwO1xuXG4gICAgdmFyIG51bUxpbmVzID0gKHN2Z1RleHRVdGlscy5saW5lQ291bnQocykgLSAxKSAqIExJTkVfU1BBQ0lORyArIDE7XG4gICAgdmFyIGR4ID0gVEVYVE9GRlNFVFNJR05baF0gKiByO1xuICAgIHZhciBkeSA9IGZvbnRTaXplICogMC43NSArIFRFWFRPRkZTRVRTSUdOW3ZdICogciArXG4gICAgICAgIChURVhUT0ZGU0VUU0lHTlt2XSAtIDEpICogbnVtTGluZXMgKiBmb250U2l6ZSAvIDI7XG5cbiAgICAvLyBmaXggdGhlIG92ZXJhbGwgdGV4dCBncm91cCBwb3NpdGlvblxuICAgIHMuYXR0cigndGV4dC1hbmNob3InLCBoKTtcbiAgICBncm91cC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBkeCArICcsJyArIGR5ICsgJyknKTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjVGV4dEZvbnRTaXplKGQsIHRyYWNlKSB7XG4gICAgdmFyIGZvbnRTaXplID0gZC50cyB8fCB0cmFjZS50ZXh0Zm9udC5zaXplO1xuICAgIHJldHVybiAoaXNOdW1lcmljKGZvbnRTaXplKSAmJiBmb250U2l6ZSA+IDApID8gZm9udFNpemUgOiAwO1xufVxuXG4vLyBkcmF3IHRleHQgYXQgcG9pbnRzXG5kcmF3aW5nLnRleHRQb2ludFN0eWxlID0gZnVuY3Rpb24ocywgdHJhY2UsIGdkKSB7XG4gICAgaWYoIXMuc2l6ZSgpKSByZXR1cm47XG5cbiAgICB2YXIgc2VsZWN0ZWRUZXh0Q29sb3JGbjtcblxuICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgIHZhciBmbnMgPSBkcmF3aW5nLm1ha2VTZWxlY3RlZFRleHRTdHlsZUZucyh0cmFjZSk7XG4gICAgICAgIHNlbGVjdGVkVGV4dENvbG9yRm4gPSBmbnMuc2VsZWN0ZWRUZXh0Q29sb3JGbjtcbiAgICB9XG5cbiAgICBzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRleHQgPSBMaWIuZXh0cmFjdE9wdGlvbihkLCB0cmFjZSwgJ3R4JywgJ3RleHQnKTtcblxuICAgICAgICBpZighdGV4dCAmJiB0ZXh0ICE9PSAwKSB7XG4gICAgICAgICAgICBwLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHBvcyA9IGQudHAgfHwgdHJhY2UudGV4dHBvc2l0aW9uO1xuICAgICAgICB2YXIgZm9udFNpemUgPSBleHRyYWNUZXh0Rm9udFNpemUoZCwgdHJhY2UpO1xuICAgICAgICB2YXIgZm9udENvbG9yID0gc2VsZWN0ZWRUZXh0Q29sb3JGbiA/XG4gICAgICAgICAgICBzZWxlY3RlZFRleHRDb2xvckZuKGQpIDpcbiAgICAgICAgICAgIChkLnRjIHx8IHRyYWNlLnRleHRmb250LmNvbG9yKTtcblxuICAgICAgICBwLmNhbGwoZHJhd2luZy5mb250LFxuICAgICAgICAgICAgICAgIGQudGYgfHwgdHJhY2UudGV4dGZvbnQuZmFtaWx5LFxuICAgICAgICAgICAgICAgIGZvbnRTaXplLFxuICAgICAgICAgICAgICAgIGZvbnRDb2xvcilcbiAgICAgICAgICAgIC50ZXh0KHRleHQpXG4gICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZClcbiAgICAgICAgICAgIC5jYWxsKHRleHRQb2ludFBvc2l0aW9uLCBwb3MsIGZvbnRTaXplLCBkLm1yYyk7XG4gICAgfSk7XG59O1xuXG5kcmF3aW5nLnNlbGVjdGVkVGV4dFN0eWxlID0gZnVuY3Rpb24ocywgdHJhY2UpIHtcbiAgICBpZighcy5zaXplKCkgfHwgIXRyYWNlLnNlbGVjdGVkcG9pbnRzKSByZXR1cm47XG5cbiAgICB2YXIgZm5zID0gZHJhd2luZy5tYWtlU2VsZWN0ZWRUZXh0U3R5bGVGbnModHJhY2UpO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHR4ID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdGMgPSBmbnMuc2VsZWN0ZWRUZXh0Q29sb3JGbihkKTtcbiAgICAgICAgdmFyIHRwID0gZC50cCB8fCB0cmFjZS50ZXh0cG9zaXRpb247XG4gICAgICAgIHZhciBmb250U2l6ZSA9IGV4dHJhY1RleHRGb250U2l6ZShkLCB0cmFjZSk7XG5cbiAgICAgICAgQ29sb3IuZmlsbCh0eCwgdGMpO1xuICAgICAgICB0ZXh0UG9pbnRQb3NpdGlvbih0eCwgdHAsIGZvbnRTaXplLCBkLm1yYzIgfHwgZC5tcmMpO1xuICAgIH0pO1xufTtcblxuLy8gZ2VuZXJhbGl6ZWQgQ2F0bXVsbC1Sb20gc3BsaW5lcywgcGVyXG4vLyBodHRwOi8vd3d3LmNlbXl1a3NlbC5jb20vcmVzZWFyY2gvY2F0bXVsbHJvbV9wYXJhbS9jYXRtdWxscm9tLnBkZlxudmFyIENhdG11bGxSb21FeHAgPSAwLjU7XG5kcmF3aW5nLnNtb290aG9wZW4gPSBmdW5jdGlvbihwdHMsIHNtb290aG5lc3MpIHtcbiAgICBpZihwdHMubGVuZ3RoIDwgMykgeyByZXR1cm4gJ00nICsgcHRzLmpvaW4oJ0wnKTt9XG4gICAgdmFyIHBhdGggPSAnTScgKyBwdHNbMF0sXG4gICAgICAgIHRhbmdlbnRzID0gW10sIGk7XG4gICAgZm9yKGkgPSAxOyBpIDwgcHRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICB0YW5nZW50cy5wdXNoKG1ha2VUYW5nZW50KHB0c1tpIC0gMV0sIHB0c1tpXSwgcHRzW2kgKyAxXSwgc21vb3RobmVzcykpO1xuICAgIH1cbiAgICBwYXRoICs9ICdRJyArIHRhbmdlbnRzWzBdWzBdICsgJyAnICsgcHRzWzFdO1xuICAgIGZvcihpID0gMjsgaSA8IHB0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgcGF0aCArPSAnQycgKyB0YW5nZW50c1tpIC0gMl1bMV0gKyAnICcgKyB0YW5nZW50c1tpIC0gMV1bMF0gKyAnICcgKyBwdHNbaV07XG4gICAgfVxuICAgIHBhdGggKz0gJ1EnICsgdGFuZ2VudHNbcHRzLmxlbmd0aCAtIDNdWzFdICsgJyAnICsgcHRzW3B0cy5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gcGF0aDtcbn07XG5cbmRyYXdpbmcuc21vb3RoY2xvc2VkID0gZnVuY3Rpb24ocHRzLCBzbW9vdGhuZXNzKSB7XG4gICAgaWYocHRzLmxlbmd0aCA8IDMpIHsgcmV0dXJuICdNJyArIHB0cy5qb2luKCdMJykgKyAnWic7IH1cbiAgICB2YXIgcGF0aCA9ICdNJyArIHB0c1swXSxcbiAgICAgICAgcExhc3QgPSBwdHMubGVuZ3RoIC0gMSxcbiAgICAgICAgdGFuZ2VudHMgPSBbbWFrZVRhbmdlbnQocHRzW3BMYXN0XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0c1swXSwgcHRzWzFdLCBzbW9vdGhuZXNzKV0sXG4gICAgICAgIGk7XG4gICAgZm9yKGkgPSAxOyBpIDwgcExhc3Q7IGkrKykge1xuICAgICAgICB0YW5nZW50cy5wdXNoKG1ha2VUYW5nZW50KHB0c1tpIC0gMV0sIHB0c1tpXSwgcHRzW2kgKyAxXSwgc21vb3RobmVzcykpO1xuICAgIH1cbiAgICB0YW5nZW50cy5wdXNoKFxuICAgICAgICBtYWtlVGFuZ2VudChwdHNbcExhc3QgLSAxXSwgcHRzW3BMYXN0XSwgcHRzWzBdLCBzbW9vdGhuZXNzKVxuICAgICk7XG5cbiAgICBmb3IoaSA9IDE7IGkgPD0gcExhc3Q7IGkrKykge1xuICAgICAgICBwYXRoICs9ICdDJyArIHRhbmdlbnRzW2kgLSAxXVsxXSArICcgJyArIHRhbmdlbnRzW2ldWzBdICsgJyAnICsgcHRzW2ldO1xuICAgIH1cbiAgICBwYXRoICs9ICdDJyArIHRhbmdlbnRzW3BMYXN0XVsxXSArICcgJyArIHRhbmdlbnRzWzBdWzBdICsgJyAnICsgcHRzWzBdICsgJ1onO1xuICAgIHJldHVybiBwYXRoO1xufTtcblxuZnVuY3Rpb24gbWFrZVRhbmdlbnQocHJldnB0LCB0aGlzcHQsIG5leHRwdCwgc21vb3RobmVzcykge1xuICAgIHZhciBkMXggPSBwcmV2cHRbMF0gLSB0aGlzcHRbMF0sXG4gICAgICAgIGQxeSA9IHByZXZwdFsxXSAtIHRoaXNwdFsxXSxcbiAgICAgICAgZDJ4ID0gbmV4dHB0WzBdIC0gdGhpc3B0WzBdLFxuICAgICAgICBkMnkgPSBuZXh0cHRbMV0gLSB0aGlzcHRbMV0sXG4gICAgICAgIGQxYSA9IE1hdGgucG93KGQxeCAqIGQxeCArIGQxeSAqIGQxeSwgQ2F0bXVsbFJvbUV4cCAvIDIpLFxuICAgICAgICBkMmEgPSBNYXRoLnBvdyhkMnggKiBkMnggKyBkMnkgKiBkMnksIENhdG11bGxSb21FeHAgLyAyKSxcbiAgICAgICAgbnVteCA9IChkMmEgKiBkMmEgKiBkMXggLSBkMWEgKiBkMWEgKiBkMngpICogc21vb3RobmVzcyxcbiAgICAgICAgbnVteSA9IChkMmEgKiBkMmEgKiBkMXkgLSBkMWEgKiBkMWEgKiBkMnkpICogc21vb3RobmVzcyxcbiAgICAgICAgZGVub20xID0gMyAqIGQyYSAqIChkMWEgKyBkMmEpLFxuICAgICAgICBkZW5vbTIgPSAzICogZDFhICogKGQxYSArIGQyYSk7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgW1xuICAgICAgICAgICAgZDMucm91bmQodGhpc3B0WzBdICsgKGRlbm9tMSAmJiBudW14IC8gZGVub20xKSwgMiksXG4gICAgICAgICAgICBkMy5yb3VuZCh0aGlzcHRbMV0gKyAoZGVub20xICYmIG51bXkgLyBkZW5vbTEpLCAyKVxuICAgICAgICBdLCBbXG4gICAgICAgICAgICBkMy5yb3VuZCh0aGlzcHRbMF0gLSAoZGVub20yICYmIG51bXggLyBkZW5vbTIpLCAyKSxcbiAgICAgICAgICAgIGQzLnJvdW5kKHRoaXNwdFsxXSAtIChkZW5vbTIgJiYgbnVteSAvIGRlbm9tMiksIDIpXG4gICAgICAgIF1cbiAgICBdO1xufVxuXG4vLyBzdGVwIHBhdGhzIC0gcmV0dXJucyBhIGdlbmVyYXRvciBmdW5jdGlvbiBmb3IgcGF0aHNcbi8vIHdpdGggdGhlIGdpdmVuIHN0ZXAgc2hhcGVcbnZhciBTVEVQUEFUSCA9IHtcbiAgICBodjogZnVuY3Rpb24ocDAsIHAxKSB7XG4gICAgICAgIHJldHVybiAnSCcgKyBkMy5yb3VuZChwMVswXSwgMikgKyAnVicgKyBkMy5yb3VuZChwMVsxXSwgMik7XG4gICAgfSxcbiAgICB2aDogZnVuY3Rpb24ocDAsIHAxKSB7XG4gICAgICAgIHJldHVybiAnVicgKyBkMy5yb3VuZChwMVsxXSwgMikgKyAnSCcgKyBkMy5yb3VuZChwMVswXSwgMik7XG4gICAgfSxcbiAgICBodmg6IGZ1bmN0aW9uKHAwLCBwMSkge1xuICAgICAgICByZXR1cm4gJ0gnICsgZDMucm91bmQoKHAwWzBdICsgcDFbMF0pIC8gMiwgMikgKyAnVicgK1xuICAgICAgICAgICAgZDMucm91bmQocDFbMV0sIDIpICsgJ0gnICsgZDMucm91bmQocDFbMF0sIDIpO1xuICAgIH0sXG4gICAgdmh2OiBmdW5jdGlvbihwMCwgcDEpIHtcbiAgICAgICAgcmV0dXJuICdWJyArIGQzLnJvdW5kKChwMFsxXSArIHAxWzFdKSAvIDIsIDIpICsgJ0gnICtcbiAgICAgICAgICAgIGQzLnJvdW5kKHAxWzBdLCAyKSArICdWJyArIGQzLnJvdW5kKHAxWzFdLCAyKTtcbiAgICB9XG59O1xudmFyIFNURVBMSU5FQVIgPSBmdW5jdGlvbihwMCwgcDEpIHtcbiAgICByZXR1cm4gJ0wnICsgZDMucm91bmQocDFbMF0sIDIpICsgJywnICsgZDMucm91bmQocDFbMV0sIDIpO1xufTtcbmRyYXdpbmcuc3RlcHMgPSBmdW5jdGlvbihzaGFwZSkge1xuICAgIHZhciBvbmVzdGVwID0gU1RFUFBBVEhbc2hhcGVdIHx8IFNURVBMSU5FQVI7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHB0cykge1xuICAgICAgICB2YXIgcGF0aCA9ICdNJyArIGQzLnJvdW5kKHB0c1swXVswXSwgMikgKyAnLCcgKyBkMy5yb3VuZChwdHNbMF1bMV0sIDIpO1xuICAgICAgICBmb3IodmFyIGkgPSAxOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwYXRoICs9IG9uZXN0ZXAocHRzW2kgLSAxXSwgcHRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGF0aDtcbiAgICB9O1xufTtcblxuLy8gb2ZmLXNjcmVlbiBzdmcgcmVuZGVyIHRlc3RpbmcgZWxlbWVudCwgc2hhcmVkIGJ5IHRoZSB3aG9sZSBwYWdlXG4vLyB1c2VzIHRoZSBpZCAnanMtcGxvdGx5LXRlc3RlcicgYW5kIHN0b3JlcyBpdCBpbiBkcmF3aW5nLnRlc3RlclxuZHJhd2luZy5tYWtlVGVzdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRlc3RlciA9IExpYi5lbnN1cmVTaW5nbGVCeUlkKGQzLnNlbGVjdCgnYm9keScpLCAnc3ZnJywgJ2pzLXBsb3RseS10ZXN0ZXInLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cih4bWxuc05hbWVzcGFjZXMuc3ZnQXR0cnMpXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgICAgIGxlZnQ6ICctMTAwMDBweCcsXG4gICAgICAgICAgICAgICAgdG9wOiAnLTEwMDAwcHgnLFxuICAgICAgICAgICAgICAgIHdpZHRoOiAnOTAwMHB4JyxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6ICc5MDAwcHgnLFxuICAgICAgICAgICAgICAgICd6LWluZGV4JzogJzEnXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIGJyb3dzZXJzIGRpZmZlciBvbiBob3cgdGhleSBkZXNjcmliZSB0aGUgYm91bmRpbmcgcmVjdCBvZlxuICAgIC8vIHRoZSBzdmcgaWYgaXRzIGNvbnRlbnRzIHNwaWxsIG92ZXIuLi4gc28gbWFrZSBhIDF4MXB4XG4gICAgLy8gcmVmZXJlbmNlIHBvaW50IHdlIGNhbiBtZWFzdXJlIG9mZiBvZi5cbiAgICB2YXIgdGVzdHJlZiA9IExpYi5lbnN1cmVTaW5nbGUodGVzdGVyLCAncGF0aCcsICdqcy1yZWZlcmVuY2UtcG9pbnQnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cignZCcsICdNMCwwSDFWMUgwWicpXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiAwLFxuICAgICAgICAgICAgICAgIGZpbGw6ICdibGFjaydcbiAgICAgICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZHJhd2luZy50ZXN0ZXIgPSB0ZXN0ZXI7XG4gICAgZHJhd2luZy50ZXN0cmVmID0gdGVzdHJlZjtcbn07XG5cbi8qXG4gKiB1c2Ugb3VyIG9mZnNjcmVlbiB0ZXN0ZXIgdG8gZ2V0IGEgY2xpZW50UmVjdCBmb3IgYW4gZWxlbWVudCxcbiAqIGluIGEgcmVmZXJlbmNlIGZyYW1lIHdoZXJlIGl0IGlzbid0IHRyYW5zbGF0ZWQgKG9yIHRyYW5zZm9ybWVkKSBhbmRcbiAqIGl0cyBhbmNob3IgcG9pbnQgaXMgYXQgKDAsMClcbiAqIGFsd2F5cyByZXR1cm5zIGEgY29weSBvZiB0aGUgYmJveCwgc28gdGhlIGNhbGxlciBjYW4gbW9kaWZ5IGl0IHNhZmVseVxuICpcbiAqIEBwYXJhbSB7U1ZHRWxlbWVudH0gbm9kZTogdGhlIGVsZW1lbnQgdG8gbWVhc3VyZS4gSWYgcG9zc2libGUgdGhpcyBzaG91bGQgYmVcbiAqICAgYSA8dGV4dD4gb3IgTWF0aEpheCA8Zz4gZWxlbWVudCB0aGF0J3MgYWxyZWFkeSBwYXNzZWQgdGhyb3VnaFxuICogICBgY29udmVydFRvVHNwYW5zYCBiZWNhdXNlIGluIHRoYXQgY2FzZSB3ZSBjYW4gY2FjaGUgdGhlIHJlc3VsdHMsIGJ1dCBpdCdzXG4gKiAgIHBvc3NpYmxlIHRvIHBhc3MgaW4gYW55IHN2ZyBlbGVtZW50LlxuICpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaW5UZXN0ZXI6IGlzIHRoaXMgZWxlbWVudCBhbHJlYWR5IGluIGBkcmF3aW5nLnRlc3RlcmA/XG4gKiAgIElmIHlvdSBhcmUgbWVhc3VyaW5nIGEgZHVtbXkgZWxlbWVudCwgcmF0aGVyIHRoYW4gb25lIHlvdSByZWFsbHkgaW50ZW5kXG4gKiAgIHRvIHVzZSBvbiB0aGUgcGxvdCwgbWFraW5nIGl0IGluIGBkcmF3aW5nLnRlc3RlcmAgaW4gdGhlIGZpcnN0IHBsYWNlXG4gKiAgIGFsbG93cyB1cyB0byB0ZXN0IGZhc3RlciBiZWNhdXNlIGl0IGN1dHMgb3V0IGNsb25pbmcgYW5kIGFwcGVuZGluZyBpdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaDogZm9yIGludGVybmFsIHVzZSBvbmx5LCBpZiB3ZSBhbHJlYWR5IGtub3cgdGhlIGNhY2hlIGtleVxuICogICBmb3IgdGhpcyBlbGVtZW50IGJlZm9yZWhhbmQuXG4gKlxuICogQHJldHVybiB7b2JqZWN0fTogYSBwbGFpbiBvYmplY3QgY29udGFpbmluZyB0aGUgd2lkdGgsIGhlaWdodCwgbGVmdCwgcmlnaHQsXG4gKiAgIHRvcCwgYW5kIGJvdHRvbSBvZiBgbm9kZWBcbiAqL1xuZHJhd2luZy5zYXZlZEJCb3hlcyA9IHt9O1xudmFyIHNhdmVkQkJveGVzQ291bnQgPSAwO1xudmFyIG1heFNhdmVkQkJveGVzID0gMTAwMDA7XG5cbmRyYXdpbmcuYkJveCA9IGZ1bmN0aW9uKG5vZGUsIGluVGVzdGVyLCBoYXNoKSB7XG4gICAgLypcbiAgICAgKiBDYWNoZSBlbGVtZW50cyB3ZSd2ZSBhbHJlYWR5IG1lYXN1cmVkIHNvIHdlIGRvbid0IGhhdmUgdG9cbiAgICAgKiByZW1lYXN1cmUgdGhlIHNhbWUgdGhpbmcgbWFueSB0aW1lc1xuICAgICAqIFdlIGhhdmUgYSBmZXcgYkJveCBjYWxsZXJzIHRob3VnaCB3aG8gcGFzcyBhIG5vZGUgbGFyZ2VyIHRoYW5cbiAgICAgKiBhIDx0ZXh0PiBvciBhIE1hdGhKYXggPGc+LCBzdWNoIGFzIGFuIGF4aXMgZ3JvdXAgY29udGFpbmluZyBtYW55IGxhYmVscy5cbiAgICAgKiBUaGVzZSB3aWxsIG5vdCBnZW5lcmF0ZSBhIGhhc2ggKHVubGVzcyB3ZSBmaWd1cmUgb3V0IGFuIGFwcHJvcHJpYXRlXG4gICAgICogaGFzaCBrZXkgZm9yIHRoZW0pIGFuZCB0aHVzIHdlIHdpbGwgbm90IGhhc2ggdGhlbS5cbiAgICAgKi9cbiAgICBpZighaGFzaCkgaGFzaCA9IG5vZGVIYXNoKG5vZGUpO1xuICAgIHZhciBvdXQ7XG4gICAgaWYoaGFzaCkge1xuICAgICAgICBvdXQgPSBkcmF3aW5nLnNhdmVkQkJveGVzW2hhc2hdO1xuICAgICAgICBpZihvdXQpIHJldHVybiBMaWIuZXh0ZW5kRmxhdCh7fSwgb3V0KTtcbiAgICB9XG4gICAgZWxzZSBpZihub2RlLmNoaWxkTm9kZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8qXG4gICAgICAgICAqIElmIHdlIGhhdmUgb25seSBvbmUgY2hpbGQgZWxlbWVudCwgd2hpY2ggaXMgaXRzZWxmIGhhc2hhYmxlLCBtYWtlXG4gICAgICAgICAqIGEgbmV3IGhhc2ggZnJvbSB0aGlzIGVsZW1lbnQgcGx1cyBpdHMgeCx5LHRyYW5zZm9ybVxuICAgICAgICAgKiBUaGVzZSBib3VuZGluZyBib3hlcyAqaW5jbHVkZSogeCx5LHRyYW5zZm9ybSAtIG1vc3RseSBmb3IgdXNlIGJ5XG4gICAgICAgICAqIGNhbGxlcnMgdHJ5aW5nIHRvIGF2b2lkIG92ZXJsYXBzIChpZSB0aXRsZXMpXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgaW5uZXJOb2RlID0gbm9kZS5jaGlsZE5vZGVzWzBdO1xuXG4gICAgICAgIGhhc2ggPSBub2RlSGFzaChpbm5lck5vZGUpO1xuICAgICAgICBpZihoYXNoKSB7XG4gICAgICAgICAgICB2YXIgeCA9ICtpbm5lck5vZGUuZ2V0QXR0cmlidXRlKCd4JykgfHwgMDtcbiAgICAgICAgICAgIHZhciB5ID0gK2lubmVyTm9kZS5nZXRBdHRyaWJ1dGUoJ3knKSB8fCAwO1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IGlubmVyTm9kZS5nZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScpO1xuXG4gICAgICAgICAgICBpZighdHJhbnNmb3JtKSB7XG4gICAgICAgICAgICAgICAgLy8gaW4gdGhpcyBjYXNlLCBqdXN0IHZhcnlpbmcgeCBhbmQgeSwgZG9uJ3QgYm90aGVyIGNhY2hpbmdcbiAgICAgICAgICAgICAgICAvLyB0aGUgZmluYWwgYkJveCBiZWNhdXNlIHRoZSBhbHRlcmF0aW9uIGlzIHF1aWNrLlxuICAgICAgICAgICAgICAgIHZhciBpbm5lckJCID0gZHJhd2luZy5iQm94KGlubmVyTm9kZSwgZmFsc2UsIGhhc2gpO1xuICAgICAgICAgICAgICAgIGlmKHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5uZXJCQi5sZWZ0ICs9IHg7XG4gICAgICAgICAgICAgICAgICAgIGlubmVyQkIucmlnaHQgKz0geDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoeSkge1xuICAgICAgICAgICAgICAgICAgICBpbm5lckJCLnRvcCArPSB5O1xuICAgICAgICAgICAgICAgICAgICBpbm5lckJCLmJvdHRvbSArPSB5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5uZXJCQjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBlbHNlIHdlIGhhdmUgYSB0cmFuc2Zvcm0gLSByYXRoZXIgdGhhbiBtYWtlIGEgY29tcGxpY2F0ZWRcbiAgICAgICAgICAgICAqIChhbmQgZXJyb3ItcHJvbmUgYW5kIHByb2JhYmx5IHNsb3cpIHRyYW5zZm9ybSBwYXJzZXIvY2FsY3VsYXRvcixcbiAgICAgICAgICAgICAqIGp1c3QgY29udGludWUgb24gY2FsY3VsYXRpbmcgdGhlIGJvdW5kaW5nQ2xpZW50UmVjdCBvZiB0aGUgZ3JvdXBcbiAgICAgICAgICAgICAqIGFuZCB1c2UgdGhlIG5ldyBjb21wb3NpdGUgaGFzaCB0byBjYWNoZSBpdC5cbiAgICAgICAgICAgICAqIFRoYXQgc2FpZCwgYGlubmVyTm9kZS50cmFuc2Zvcm0uYmFzZVZhbGAgaXMgYW4gYXJyYXkgb2ZcbiAgICAgICAgICAgICAqIGBTVkdUcmFuc2Zvcm1gIG9iamVjdHMsIHRoYXQgKmRvKiBzZWVtIHRvIGhhdmUgYSBuaWNlIG1hdHJpeFxuICAgICAgICAgICAgICogbXVsdGlwbGljYXRpb24gaW50ZXJmYWNlIHRoYXQgd2UgY291bGQgdXNlIHRvIGF2b2lkIG1ha2luZ1xuICAgICAgICAgICAgICogYW5vdGhlciBnZXRCb3VuZGluZ0NsaWVudFJlY3QgY2FsbC4uLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBoYXNoICs9ICd+JyArIHggKyAnficgKyB5ICsgJ34nICsgdHJhbnNmb3JtO1xuXG4gICAgICAgICAgICBvdXQgPSBkcmF3aW5nLnNhdmVkQkJveGVzW2hhc2hdO1xuICAgICAgICAgICAgaWYob3V0KSByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIG91dCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIHRlc3ROb2RlLCB0ZXN0ZXI7XG4gICAgaWYoaW5UZXN0ZXIpIHtcbiAgICAgICAgdGVzdE5vZGUgPSBub2RlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGVzdGVyID0gZHJhd2luZy50ZXN0ZXIubm9kZSgpO1xuXG4gICAgICAgIC8vIGNvcHkgdGhlIG5vZGUgdG8gdGVzdCBpbnRvIHRoZSB0ZXN0ZXJcbiAgICAgICAgdGVzdE5vZGUgPSBub2RlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgICAgdGVzdGVyLmFwcGVuZENoaWxkKHRlc3ROb2RlKTtcbiAgICB9XG5cbiAgICAvLyBzdGFuZGFyZGl6ZSBpdHMgcG9zaXRpb24gKGFuZCBuZXdsaW5lIHRzcGFucyBpZiBhbnkpXG4gICAgZDMuc2VsZWN0KHRlc3ROb2RlKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgbnVsbClcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgMCwgMCk7XG5cbiAgICB2YXIgdGVzdFJlY3QgPSB0ZXN0Tm9kZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgcmVmUmVjdCA9IGRyYXdpbmcudGVzdHJlZlxuICAgICAgICAubm9kZSgpXG4gICAgICAgIC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGlmKCFpblRlc3RlcikgdGVzdGVyLnJlbW92ZUNoaWxkKHRlc3ROb2RlKTtcblxuICAgIHZhciBiYiA9IHtcbiAgICAgICAgaGVpZ2h0OiB0ZXN0UmVjdC5oZWlnaHQsXG4gICAgICAgIHdpZHRoOiB0ZXN0UmVjdC53aWR0aCxcbiAgICAgICAgbGVmdDogdGVzdFJlY3QubGVmdCAtIHJlZlJlY3QubGVmdCxcbiAgICAgICAgdG9wOiB0ZXN0UmVjdC50b3AgLSByZWZSZWN0LnRvcCxcbiAgICAgICAgcmlnaHQ6IHRlc3RSZWN0LnJpZ2h0IC0gcmVmUmVjdC5sZWZ0LFxuICAgICAgICBib3R0b206IHRlc3RSZWN0LmJvdHRvbSAtIHJlZlJlY3QudG9wXG4gICAgfTtcblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSBkb24ndCBoYXZlIHRvbyBtYW55IHNhdmVkIGJveGVzLFxuICAgIC8vIG9yIGEgbG9uZyBzZXNzaW9uIGNvdWxkIG92ZXJsb2FkIG9uIG1lbW9yeVxuICAgIC8vIGJ5IHNhdmluZyBib3hlcyBmb3IgbG9uZy1nb25lIGVsZW1lbnRzXG4gICAgaWYoc2F2ZWRCQm94ZXNDb3VudCA+PSBtYXhTYXZlZEJCb3hlcykge1xuICAgICAgICBkcmF3aW5nLnNhdmVkQkJveGVzID0ge307XG4gICAgICAgIHNhdmVkQkJveGVzQ291bnQgPSAwO1xuICAgIH1cblxuICAgIC8vIGNhY2hlIHRoaXMgYmJveFxuICAgIGlmKGhhc2gpIGRyYXdpbmcuc2F2ZWRCQm94ZXNbaGFzaF0gPSBiYjtcbiAgICBzYXZlZEJCb3hlc0NvdW50Kys7XG5cbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIGJiKTtcbn07XG5cbi8vIGNhcHR1cmUgZXZlcnl0aGluZyBhYm91dCBhIG5vZGUgKGF0IGxlYXN0IGluIG91ciB1c2FnZSkgdGhhdFxuLy8gaW1wYWN0cyBpdHMgYm91bmRpbmcgYm94LCBnaXZlbiB0aGF0IGJCb3ggY2xlYXJzIHgsIHksIGFuZCB0cmFuc2Zvcm1cbmZ1bmN0aW9uIG5vZGVIYXNoKG5vZGUpIHtcbiAgICB2YXIgaW5wdXRUZXh0ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtdW5mb3JtYXR0ZWQnKTtcbiAgICBpZihpbnB1dFRleHQgPT09IG51bGwpIHJldHVybjtcbiAgICByZXR1cm4gaW5wdXRUZXh0ICtcbiAgICAgICAgbm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtbWF0aCcpICtcbiAgICAgICAgbm9kZS5nZXRBdHRyaWJ1dGUoJ3RleHQtYW5jaG9yJykgK1xuICAgICAgICBub2RlLmdldEF0dHJpYnV0ZSgnc3R5bGUnKTtcbn1cblxuLypcbiAqIG1ha2UgYSByb2J1c3QgY2xpcFBhdGggdXJsIGZyb20gYSBsb2NhbCBpZFxuICogbm90ZSEgV2UnZCBiZXR0ZXIgbm90IGJlIGV4cG9ydGluZyBmcm9tIGEgcGFnZVxuICogd2l0aCBhIDxiYXNlPiBvciB0aGUgc3ZnIHdpbGwgbm90IGJlIHBvcnRhYmxlIVxuICovXG5kcmF3aW5nLnNldENsaXBVcmwgPSBmdW5jdGlvbihzLCBsb2NhbElkKSB7XG4gICAgaWYoIWxvY2FsSWQpIHtcbiAgICAgICAgcy5hdHRyKCdjbGlwLXBhdGgnLCBudWxsKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKGRyYXdpbmcuYmFzZVVybCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBiYXNlID0gZDMuc2VsZWN0KCdiYXNlJyk7XG5cbiAgICAgICAgLy8gU3Rhc2ggYmFzZSB1cmwgb25jZSBhbmQgZm9yIGFsbCFcbiAgICAgICAgLy8gV2UgbWF5IGhhdmUgdG8gc3Rhc2ggdGhpcyBlbHNld2hlcmUgd2hlblxuICAgICAgICAvLyB3ZSdsbCB0cnkgdG8gc3VwcG9ydCBmb3IgY2hpbGQgd2luZG93c1xuICAgICAgICAvLyBtb3JlIGluZm8gLT4gaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzcwMlxuICAgICAgICBpZihiYXNlLnNpemUoKSAmJiBiYXNlLmF0dHIoJ2hyZWYnKSkge1xuICAgICAgICAgICAgZHJhd2luZy5iYXNlVXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWYuc3BsaXQoJyMnKVswXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRyYXdpbmcuYmFzZVVybCA9ICcnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcy5hdHRyKCdjbGlwLXBhdGgnLCAndXJsKCcgKyBkcmF3aW5nLmJhc2VVcmwgKyAnIycgKyBsb2NhbElkICsgJyknKTtcbn07XG5cbmRyYXdpbmcuZ2V0VHJhbnNsYXRlID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIC8vIE5vdGUgdGhlIHNlcGFyYXRvciBbXlxcZF0gYmV0d2VlbiB4IGFuZCB5IGluIHRoaXMgcmVnZXhcbiAgICAvLyBXZSBnZW5lcmFsbHkgdXNlICcsJyBidXQgSUUgd2lsbCBjb252ZXJ0IGl0IHRvICcgJ1xuICAgIHZhciByZSA9IC8uKlxcYnRyYW5zbGF0ZVxcKCgtP1xcZCpcXC4/XFxkKilbXi1cXGRdKigtP1xcZCpcXC4/XFxkKilbXlxcZF0uKi8sXG4gICAgICAgIGdldHRlciA9IGVsZW1lbnQuYXR0ciA/ICdhdHRyJyA6ICdnZXRBdHRyaWJ1dGUnLFxuICAgICAgICB0cmFuc2Zvcm0gPSBlbGVtZW50W2dldHRlcl0oJ3RyYW5zZm9ybScpIHx8ICcnO1xuXG4gICAgdmFyIHRyYW5zbGF0ZSA9IHRyYW5zZm9ybS5yZXBsYWNlKHJlLCBmdW5jdGlvbihtYXRjaCwgcDEsIHAyKSB7XG4gICAgICAgIHJldHVybiBbcDEsIHAyXS5qb2luKCcgJyk7XG4gICAgfSlcbiAgICAuc3BsaXQoJyAnKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHg6ICt0cmFuc2xhdGVbMF0gfHwgMCxcbiAgICAgICAgeTogK3RyYW5zbGF0ZVsxXSB8fCAwXG4gICAgfTtcbn07XG5cbmRyYXdpbmcuc2V0VHJhbnNsYXRlID0gZnVuY3Rpb24oZWxlbWVudCwgeCwgeSkge1xuXG4gICAgdmFyIHJlID0gLyhcXGJ0cmFuc2xhdGVcXCguKj9cXCk7PykvLFxuICAgICAgICBnZXR0ZXIgPSBlbGVtZW50LmF0dHIgPyAnYXR0cicgOiAnZ2V0QXR0cmlidXRlJyxcbiAgICAgICAgc2V0dGVyID0gZWxlbWVudC5hdHRyID8gJ2F0dHInIDogJ3NldEF0dHJpYnV0ZScsXG4gICAgICAgIHRyYW5zZm9ybSA9IGVsZW1lbnRbZ2V0dGVyXSgndHJhbnNmb3JtJykgfHwgJyc7XG5cbiAgICB4ID0geCB8fCAwO1xuICAgIHkgPSB5IHx8IDA7XG5cbiAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm0ucmVwbGFjZShyZSwgJycpLnRyaW0oKTtcbiAgICB0cmFuc2Zvcm0gKz0gJyB0cmFuc2xhdGUoJyArIHggKyAnLCAnICsgeSArICcpJztcbiAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm0udHJpbSgpO1xuXG4gICAgZWxlbWVudFtzZXR0ZXJdKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xuXG4gICAgcmV0dXJuIHRyYW5zZm9ybTtcbn07XG5cbmRyYXdpbmcuZ2V0U2NhbGUgPSBmdW5jdGlvbihlbGVtZW50KSB7XG5cbiAgICB2YXIgcmUgPSAvLipcXGJzY2FsZVxcKChcXGQqXFwuP1xcZCopW15cXGRdKihcXGQqXFwuP1xcZCopW15cXGRdLiovLFxuICAgICAgICBnZXR0ZXIgPSBlbGVtZW50LmF0dHIgPyAnYXR0cicgOiAnZ2V0QXR0cmlidXRlJyxcbiAgICAgICAgdHJhbnNmb3JtID0gZWxlbWVudFtnZXR0ZXJdKCd0cmFuc2Zvcm0nKSB8fCAnJztcblxuICAgIHZhciB0cmFuc2xhdGUgPSB0cmFuc2Zvcm0ucmVwbGFjZShyZSwgZnVuY3Rpb24obWF0Y2gsIHAxLCBwMikge1xuICAgICAgICByZXR1cm4gW3AxLCBwMl0uam9pbignICcpO1xuICAgIH0pXG4gICAgLnNwbGl0KCcgJyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4OiArdHJhbnNsYXRlWzBdIHx8IDEsXG4gICAgICAgIHk6ICt0cmFuc2xhdGVbMV0gfHwgMVxuICAgIH07XG59O1xuXG5kcmF3aW5nLnNldFNjYWxlID0gZnVuY3Rpb24oZWxlbWVudCwgeCwgeSkge1xuXG4gICAgdmFyIHJlID0gLyhcXGJzY2FsZVxcKC4qP1xcKTs/KS8sXG4gICAgICAgIGdldHRlciA9IGVsZW1lbnQuYXR0ciA/ICdhdHRyJyA6ICdnZXRBdHRyaWJ1dGUnLFxuICAgICAgICBzZXR0ZXIgPSBlbGVtZW50LmF0dHIgPyAnYXR0cicgOiAnc2V0QXR0cmlidXRlJyxcbiAgICAgICAgdHJhbnNmb3JtID0gZWxlbWVudFtnZXR0ZXJdKCd0cmFuc2Zvcm0nKSB8fCAnJztcblxuICAgIHggPSB4IHx8IDE7XG4gICAgeSA9IHkgfHwgMTtcblxuICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybS5yZXBsYWNlKHJlLCAnJykudHJpbSgpO1xuICAgIHRyYW5zZm9ybSArPSAnIHNjYWxlKCcgKyB4ICsgJywgJyArIHkgKyAnKSc7XG4gICAgdHJhbnNmb3JtID0gdHJhbnNmb3JtLnRyaW0oKTtcblxuICAgIGVsZW1lbnRbc2V0dGVyXSgndHJhbnNmb3JtJywgdHJhbnNmb3JtKTtcblxuICAgIHJldHVybiB0cmFuc2Zvcm07XG59O1xuXG52YXIgU0NBTEVfUkUgPSAvXFxzKnNjLiovO1xuXG5kcmF3aW5nLnNldFBvaW50R3JvdXBTY2FsZSA9IGZ1bmN0aW9uKHNlbGVjdGlvbiwgeFNjYWxlLCB5U2NhbGUpIHtcbiAgICB4U2NhbGUgPSB4U2NhbGUgfHwgMTtcbiAgICB5U2NhbGUgPSB5U2NhbGUgfHwgMTtcblxuICAgIGlmKCFzZWxlY3Rpb24pIHJldHVybjtcblxuICAgIC8vIFRoZSBzYW1lIHNjYWxlIHRyYW5zZm9ybSBmb3IgZXZlcnkgcG9pbnQ6XG4gICAgdmFyIHNjYWxlID0gKHhTY2FsZSA9PT0gMSAmJiB5U2NhbGUgPT09IDEpID9cbiAgICAgICAgJycgOlxuICAgICAgICAnIHNjYWxlKCcgKyB4U2NhbGUgKyAnLCcgKyB5U2NhbGUgKyAnKSc7XG5cbiAgICBzZWxlY3Rpb24uZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHQgPSAodGhpcy5nZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScpIHx8ICcnKS5yZXBsYWNlKFNDQUxFX1JFLCAnJyk7XG4gICAgICAgIHQgKz0gc2NhbGU7XG4gICAgICAgIHQgPSB0LnRyaW0oKTtcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsIHQpO1xuICAgIH0pO1xufTtcblxudmFyIFRFWFRfUE9JTlRfTEFTVF9UUkFOU0xBVElPTl9SRSA9IC90cmFuc2xhdGVcXChbXildKlxcKVxccyokLztcblxuZHJhd2luZy5zZXRUZXh0UG9pbnRzU2NhbGUgPSBmdW5jdGlvbihzZWxlY3Rpb24sIHhTY2FsZSwgeVNjYWxlKSB7XG4gICAgaWYoIXNlbGVjdGlvbikgcmV0dXJuO1xuXG4gICAgc2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm1zO1xuICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0ZXh0ID0gZWwuc2VsZWN0KCd0ZXh0Jyk7XG5cbiAgICAgICAgaWYoIXRleHQubm9kZSgpKSByZXR1cm47XG5cbiAgICAgICAgdmFyIHggPSBwYXJzZUZsb2F0KHRleHQuYXR0cigneCcpIHx8IDApO1xuICAgICAgICB2YXIgeSA9IHBhcnNlRmxvYXQodGV4dC5hdHRyKCd5JykgfHwgMCk7XG5cbiAgICAgICAgdmFyIGV4aXN0aW5nVHJhbnNmb3JtID0gKGVsLmF0dHIoJ3RyYW5zZm9ybScpIHx8ICcnKS5tYXRjaChURVhUX1BPSU5UX0xBU1RfVFJBTlNMQVRJT05fUkUpO1xuXG4gICAgICAgIGlmKHhTY2FsZSA9PT0gMSAmJiB5U2NhbGUgPT09IDEpIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybXMgPSBbXG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgeCArICcsJyArIHkgKyAnKScsXG4gICAgICAgICAgICAgICAgJ3NjYWxlKCcgKyB4U2NhbGUgKyAnLCcgKyB5U2NhbGUgKyAnKScsXG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgKC14KSArICcsJyArICgteSkgKyAnKScsXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZXhpc3RpbmdUcmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybXMucHVzaChleGlzdGluZ1RyYW5zZm9ybSk7XG4gICAgICAgIH1cblxuICAgICAgICBlbC5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm1zLmpvaW4oJyAnKSk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbi8qKiBNYXJrZXIgc3ltYm9sIGRlZmluaXRpb25zXG4gKiB1c2VycyBjYW4gc3BlY2lmeSBtYXJrZXJzIGVpdGhlciBieSBudW1iZXIgb3IgbmFtZVxuICogYWRkIDEwMCAob3IgJy1vcGVuJykgYW5kIHlvdSBnZXQgYW4gb3BlbiBtYXJrZXJcbiAqICBvcGVuIG1hcmtlcnMgaGF2ZSBubyBmaWxsIGFuZCB1c2UgbGluZSBjb2xvciBhcyB0aGUgc3Ryb2tlIGNvbG9yXG4gKiBhZGQgMjAwIChvciAnLWRvdCcpIGFuZCB5b3UgZ2V0IGEgZG90IGluIHRoZSBtaWRkbGVcbiAqIGFkZCBib3RoIGFuZCB5b3UgZ2V0IGJvdGhcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjaXJjbGU6IHtcbiAgICAgICAgbjogMCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcnMgKyAnLDBBJyArIHJzICsgJywnICsgcnMgKyAnIDAgMSwxIDAsLScgKyBycyArXG4gICAgICAgICAgICAgICAgJ0EnICsgcnMgKyAnLCcgKyBycyArICcgMCAwLDEgJyArIHJzICsgJywwWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHNxdWFyZToge1xuICAgICAgICBuOiAxLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyBycyArICcsJyArIHJzICsgJ0gtJyArIHJzICsgJ1YtJyArIHJzICsgJ0gnICsgcnMgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRpYW1vbmQ6IHtcbiAgICAgICAgbjogMixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJkID0gZDMucm91bmQociAqIDEuMywgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcmQgKyAnLDBMMCwnICsgcmQgKyAnTC0nICsgcmQgKyAnLDBMMCwtJyArIHJkICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjcm9zczoge1xuICAgICAgICBuOiAzLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogMC40LCAyKSxcbiAgICAgICAgICAgICAgICByYzIgPSBkMy5yb3VuZChyICogMS4yLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByYzIgKyAnLCcgKyByYyArICdIJyArIHJjICsgJ1YnICsgcmMyICsgJ0gtJyArIHJjICtcbiAgICAgICAgICAgICAgICAnVicgKyByYyArICdILScgKyByYzIgKyAnVi0nICsgcmMgKyAnSC0nICsgcmMgKyAnVi0nICsgcmMyICtcbiAgICAgICAgICAgICAgICAnSCcgKyByYyArICdWLScgKyByYyArICdIJyArIHJjMiArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICBuOiA0LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnggPSBkMy5yb3VuZChyICogMC44IC8gTWF0aC5zcXJ0KDIpLCAyKSxcbiAgICAgICAgICAgICAgICBuZSA9ICdsJyArIHJ4ICsgJywnICsgcngsXG4gICAgICAgICAgICAgICAgc2UgPSAnbCcgKyByeCArICcsLScgKyByeCxcbiAgICAgICAgICAgICAgICBzdyA9ICdsLScgKyByeCArICcsLScgKyByeCxcbiAgICAgICAgICAgICAgICBudyA9ICdsLScgKyByeCArICcsJyArIHJ4O1xuICAgICAgICAgICAgcmV0dXJuICdNMCwnICsgcnggKyBuZSArIHNlICsgc3cgKyBzZSArIHN3ICsgbncgKyBzdyArIG53ICsgbmUgKyBudyArIG5lICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtdXAnOiB7XG4gICAgICAgIG46IDUsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBydCA9IGQzLnJvdW5kKHIgKiAyIC8gTWF0aC5zcXJ0KDMpLCAyKSxcbiAgICAgICAgICAgICAgICByMiA9IGQzLnJvdW5kKHIgLyAyLCAyKSxcbiAgICAgICAgICAgICAgICBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyBydCArICcsJyArIHIyICsgJ0gnICsgcnQgKyAnTDAsLScgKyBycyArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLWRvd24nOiB7XG4gICAgICAgIG46IDYsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBydCA9IGQzLnJvdW5kKHIgKiAyIC8gTWF0aC5zcXJ0KDMpLCAyKSxcbiAgICAgICAgICAgICAgICByMiA9IGQzLnJvdW5kKHIgLyAyLCAyKSxcbiAgICAgICAgICAgICAgICBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyBydCArICcsLScgKyByMiArICdIJyArIHJ0ICsgJ0wwLCcgKyBycyArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLWxlZnQnOiB7XG4gICAgICAgIG46IDcsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBydCA9IGQzLnJvdW5kKHIgKiAyIC8gTWF0aC5zcXJ0KDMpLCAyKSxcbiAgICAgICAgICAgICAgICByMiA9IGQzLnJvdW5kKHIgLyAyLCAyKSxcbiAgICAgICAgICAgICAgICBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHIyICsgJywtJyArIHJ0ICsgJ1YnICsgcnQgKyAnTC0nICsgcnMgKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLXJpZ2h0Jzoge1xuICAgICAgICBuOiA4LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnQgPSBkMy5yb3VuZChyICogMiAvIE1hdGguc3FydCgzKSwgMiksXG4gICAgICAgICAgICAgICAgcjIgPSBkMy5yb3VuZChyIC8gMiwgMiksXG4gICAgICAgICAgICAgICAgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgcjIgKyAnLC0nICsgcnQgKyAnVicgKyBydCArICdMJyArIHJzICsgJywwWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICd0cmlhbmdsZS1uZSc6IHtcbiAgICAgICAgbjogOSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHIxID0gZDMucm91bmQociAqIDAuNiwgMiksXG4gICAgICAgICAgICAgICAgcjIgPSBkMy5yb3VuZChyICogMS4yLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgcjIgKyAnLC0nICsgcjEgKyAnSCcgKyByMSArICdWJyArIHIyICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtc2UnOiB7XG4gICAgICAgIG46IDEwLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcjEgPSBkMy5yb3VuZChyICogMC42LCAyKSxcbiAgICAgICAgICAgICAgICByMiA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHIxICsgJywtJyArIHIyICsgJ1YnICsgcjEgKyAnSC0nICsgcjIgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICd0cmlhbmdsZS1zdyc6IHtcbiAgICAgICAgbjogMTEsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByMSA9IGQzLnJvdW5kKHIgKiAwLjYsIDIpLFxuICAgICAgICAgICAgICAgIHIyID0gZDMucm91bmQociAqIDEuMiwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcjIgKyAnLCcgKyByMSArICdILScgKyByMSArICdWLScgKyByMiArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLW53Jzoge1xuICAgICAgICBuOiAxMixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHIxID0gZDMucm91bmQociAqIDAuNiwgMiksXG4gICAgICAgICAgICAgICAgcjIgPSBkMy5yb3VuZChyICogMS4yLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgcjEgKyAnLCcgKyByMiArICdWLScgKyByMSArICdIJyArIHIyICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBwZW50YWdvbjoge1xuICAgICAgICBuOiAxMyxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHgxID0gZDMucm91bmQociAqIDAuOTUxLCAyKSxcbiAgICAgICAgICAgICAgICB4MiA9IGQzLnJvdW5kKHIgKiAwLjU4OCwgMiksXG4gICAgICAgICAgICAgICAgeTAgPSBkMy5yb3VuZCgtciwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyICogLTAuMzA5LCAyKSxcbiAgICAgICAgICAgICAgICB5MiA9IGQzLnJvdW5kKHIgKiAwLjgwOSwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgeDEgKyAnLCcgKyB5MSArICdMJyArIHgyICsgJywnICsgeTIgKyAnSC0nICsgeDIgK1xuICAgICAgICAgICAgICAgICdMLScgKyB4MSArICcsJyArIHkxICsgJ0wwLCcgKyB5MCArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaGV4YWdvbjoge1xuICAgICAgICBuOiAxNCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHkwID0gZDMucm91bmQociwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyIC8gMiwgMiksXG4gICAgICAgICAgICAgICAgeCA9IGQzLnJvdW5kKHIgKiBNYXRoLnNxcnQoMykgLyAyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyB4ICsgJywtJyArIHkxICsgJ1YnICsgeTEgKyAnTDAsJyArIHkwICtcbiAgICAgICAgICAgICAgICAnTC0nICsgeCArICcsJyArIHkxICsgJ1YtJyArIHkxICsgJ0wwLC0nICsgeTAgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGhleGFnb24yOiB7XG4gICAgICAgIG46IDE1LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeDAgPSBkMy5yb3VuZChyLCAyKSxcbiAgICAgICAgICAgICAgICB4MSA9IGQzLnJvdW5kKHIgLyAyLCAyKSxcbiAgICAgICAgICAgICAgICB5ID0gZDMucm91bmQociAqIE1hdGguc3FydCgzKSAvIDIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyB4MSArICcsJyArIHkgKyAnSCcgKyB4MSArICdMJyArIHgwICtcbiAgICAgICAgICAgICAgICAnLDBMJyArIHgxICsgJywtJyArIHkgKyAnSC0nICsgeDEgKyAnTC0nICsgeDAgKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgb2N0YWdvbjoge1xuICAgICAgICBuOiAxNixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIGEgPSBkMy5yb3VuZChyICogMC45MjQsIDIpLFxuICAgICAgICAgICAgICAgIGIgPSBkMy5yb3VuZChyICogMC4zODMsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyBiICsgJywtJyArIGEgKyAnSCcgKyBiICsgJ0wnICsgYSArICcsLScgKyBiICsgJ1YnICsgYiArXG4gICAgICAgICAgICAgICAgJ0wnICsgYiArICcsJyArIGEgKyAnSC0nICsgYiArICdMLScgKyBhICsgJywnICsgYiArICdWLScgKyBiICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBzdGFyOiB7XG4gICAgICAgIG46IDE3LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSByICogMS40LFxuICAgICAgICAgICAgICAgIHgxID0gZDMucm91bmQocnMgKiAwLjIyNSwgMiksXG4gICAgICAgICAgICAgICAgeDIgPSBkMy5yb3VuZChycyAqIDAuOTUxLCAyKSxcbiAgICAgICAgICAgICAgICB4MyA9IGQzLnJvdW5kKHJzICogMC4zNjMsIDIpLFxuICAgICAgICAgICAgICAgIHg0ID0gZDMucm91bmQocnMgKiAwLjU4OCwgMiksXG4gICAgICAgICAgICAgICAgeTAgPSBkMy5yb3VuZCgtcnMsIDIpLFxuICAgICAgICAgICAgICAgIHkxID0gZDMucm91bmQocnMgKiAtMC4zMDksIDIpLFxuICAgICAgICAgICAgICAgIHkzID0gZDMucm91bmQocnMgKiAwLjExOCwgMiksXG4gICAgICAgICAgICAgICAgeTQgPSBkMy5yb3VuZChycyAqIDAuODA5LCAyKSxcbiAgICAgICAgICAgICAgICB5NSA9IGQzLnJvdW5kKHJzICogMC4zODIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHgxICsgJywnICsgeTEgKyAnSCcgKyB4MiArICdMJyArIHgzICsgJywnICsgeTMgK1xuICAgICAgICAgICAgICAgICdMJyArIHg0ICsgJywnICsgeTQgKyAnTDAsJyArIHk1ICsgJ0wtJyArIHg0ICsgJywnICsgeTQgK1xuICAgICAgICAgICAgICAgICdMLScgKyB4MyArICcsJyArIHkzICsgJ0wtJyArIHgyICsgJywnICsgeTEgKyAnSC0nICsgeDEgK1xuICAgICAgICAgICAgICAgICdMMCwnICsgeTAgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGhleGFncmFtOiB7XG4gICAgICAgIG46IDE4LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeSA9IGQzLnJvdW5kKHIgKiAwLjY2LCAyKSxcbiAgICAgICAgICAgICAgICB4MSA9IGQzLnJvdW5kKHIgKiAwLjM4LCAyKSxcbiAgICAgICAgICAgICAgICB4MiA9IGQzLnJvdW5kKHIgKiAwLjc2LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgeDIgKyAnLDBsLScgKyB4MSArICcsLScgKyB5ICsgJ2gnICsgeDIgK1xuICAgICAgICAgICAgICAgICdsJyArIHgxICsgJywtJyArIHkgKyAnbCcgKyB4MSArICcsJyArIHkgKyAnaCcgKyB4MiArXG4gICAgICAgICAgICAgICAgJ2wtJyArIHgxICsgJywnICsgeSArICdsJyArIHgxICsgJywnICsgeSArICdoLScgKyB4MiArXG4gICAgICAgICAgICAgICAgJ2wtJyArIHgxICsgJywnICsgeSArICdsLScgKyB4MSArICcsLScgKyB5ICsgJ2gtJyArIHgyICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAnc3Rhci10cmlhbmdsZS11cCc6IHtcbiAgICAgICAgbjogMTksXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIE1hdGguc3FydCgzKSAqIDAuOCwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyICogMC44LCAyKSxcbiAgICAgICAgICAgICAgICB5MiA9IGQzLnJvdW5kKHIgKiAxLjYsIDIpLFxuICAgICAgICAgICAgICAgIHJjID0gZDMucm91bmQociAqIDQsIDIpLFxuICAgICAgICAgICAgICAgIGFQYXJ0ID0gJ0EgJyArIHJjICsgJywnICsgcmMgKyAnIDAgMCAxICc7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHggKyAnLCcgKyB5MSArIGFQYXJ0ICsgeCArICcsJyArIHkxICtcbiAgICAgICAgICAgICAgICBhUGFydCArICcwLC0nICsgeTIgKyBhUGFydCArICctJyArIHggKyAnLCcgKyB5MSArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3N0YXItdHJpYW5nbGUtZG93bic6IHtcbiAgICAgICAgbjogMjAsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIE1hdGguc3FydCgzKSAqIDAuOCwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyICogMC44LCAyKSxcbiAgICAgICAgICAgICAgICB5MiA9IGQzLnJvdW5kKHIgKiAxLjYsIDIpLFxuICAgICAgICAgICAgICAgIHJjID0gZDMucm91bmQociAqIDQsIDIpLFxuICAgICAgICAgICAgICAgIGFQYXJ0ID0gJ0EgJyArIHJjICsgJywnICsgcmMgKyAnIDAgMCAxICc7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgeCArICcsLScgKyB5MSArIGFQYXJ0ICsgJy0nICsgeCArICcsLScgKyB5MSArXG4gICAgICAgICAgICAgICAgYVBhcnQgKyAnMCwnICsgeTIgKyBhUGFydCArIHggKyAnLC0nICsgeTEgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdzdGFyLXNxdWFyZSc6IHtcbiAgICAgICAgbjogMjEsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycCA9IGQzLnJvdW5kKHIgKiAxLjEsIDIpLFxuICAgICAgICAgICAgICAgIHJjID0gZDMucm91bmQociAqIDIsIDIpLFxuICAgICAgICAgICAgICAgIGFQYXJ0ID0gJ0EgJyArIHJjICsgJywnICsgcmMgKyAnIDAgMCAxICc7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHJwICsgJywtJyArIHJwICsgYVBhcnQgKyAnLScgKyBycCArICcsJyArIHJwICtcbiAgICAgICAgICAgICAgICBhUGFydCArIHJwICsgJywnICsgcnAgKyBhUGFydCArIHJwICsgJywtJyArIHJwICtcbiAgICAgICAgICAgICAgICBhUGFydCArICctJyArIHJwICsgJywtJyArIHJwICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAnc3Rhci1kaWFtb25kJzoge1xuICAgICAgICBuOiAyMixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJwID0gZDMucm91bmQociAqIDEuNCwgMiksXG4gICAgICAgICAgICAgICAgcmMgPSBkMy5yb3VuZChyICogMS45LCAyKSxcbiAgICAgICAgICAgICAgICBhUGFydCA9ICdBICcgKyByYyArICcsJyArIHJjICsgJyAwIDAgMSAnO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyBycCArICcsMCcgKyBhUGFydCArICcwLCcgKyBycCArXG4gICAgICAgICAgICAgICAgYVBhcnQgKyBycCArICcsMCcgKyBhUGFydCArICcwLC0nICsgcnAgK1xuICAgICAgICAgICAgICAgIGFQYXJ0ICsgJy0nICsgcnAgKyAnLDAnICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAnZGlhbW9uZC10YWxsJzoge1xuICAgICAgICBuOiAyMyxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHggPSBkMy5yb3VuZChyICogMC43LCAyKSxcbiAgICAgICAgICAgICAgICB5ID0gZDMucm91bmQociAqIDEuNCwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00wLCcgKyB5ICsgJ0wnICsgeCArICcsMEwwLC0nICsgeSArICdMLScgKyB4ICsgJywwWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdkaWFtb25kLXdpZGUnOiB7XG4gICAgICAgIG46IDI0LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeCA9IGQzLnJvdW5kKHIgKiAxLjQsIDIpLFxuICAgICAgICAgICAgICAgIHkgPSBkMy5yb3VuZChyICogMC43LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHkgKyAnTCcgKyB4ICsgJywwTDAsLScgKyB5ICsgJ0wtJyArIHggKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaG91cmdsYXNzOiB7XG4gICAgICAgIG46IDI1LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyBycyArICcsJyArIHJzICsgJ0gtJyArIHJzICsgJ0wnICsgcnMgKyAnLC0nICsgcnMgKyAnSC0nICsgcnMgKyAnWic7XG4gICAgICAgIH0sXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICBib3d0aWU6IHtcbiAgICAgICAgbjogMjYsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJzICsgJywnICsgcnMgKyAnVi0nICsgcnMgKyAnTC0nICsgcnMgKyAnLCcgKyBycyArICdWLScgKyBycyArICdaJztcbiAgICAgICAgfSxcbiAgICAgICAgbm9Eb3Q6IHRydWVcbiAgICB9LFxuICAgICdjaXJjbGUtY3Jvc3MnOiB7XG4gICAgICAgIG46IDI3LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHJzICsgJ1YtJyArIHJzICsgJ00nICsgcnMgKyAnLDBILScgKyBycyArXG4gICAgICAgICAgICAgICAgJ00nICsgcnMgKyAnLDBBJyArIHJzICsgJywnICsgcnMgKyAnIDAgMSwxIDAsLScgKyBycyArXG4gICAgICAgICAgICAgICAgJ0EnICsgcnMgKyAnLCcgKyBycyArICcgMCAwLDEgJyArIHJzICsgJywwWic7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZVxuICAgIH0sXG4gICAgJ2NpcmNsZS14Jzoge1xuICAgICAgICBuOiAyOCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMiksXG4gICAgICAgICAgICAgICAgcmMgPSBkMy5yb3VuZChyIC8gTWF0aC5zcXJ0KDIpLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByYyArICcsJyArIHJjICsgJ0wtJyArIHJjICsgJywtJyArIHJjICtcbiAgICAgICAgICAgICAgICAnTScgKyByYyArICcsLScgKyByYyArICdMLScgKyByYyArICcsJyArIHJjICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsMEEnICsgcnMgKyAnLCcgKyBycyArICcgMCAxLDEgMCwtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnQScgKyBycyArICcsJyArIHJzICsgJyAwIDAsMSAnICsgcnMgKyAnLDBaJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICAnc3F1YXJlLWNyb3NzJzoge1xuICAgICAgICBuOiAyOSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00wLCcgKyBycyArICdWLScgKyBycyArICdNJyArIHJzICsgJywwSC0nICsgcnMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywnICsgcnMgKyAnSC0nICsgcnMgKyAnVi0nICsgcnMgKyAnSCcgKyBycyArICdaJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICAnc3F1YXJlLXgnOiB7XG4gICAgICAgIG46IDMwLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyBycyArICcsJyArIHJzICsgJ0wtJyArIHJzICsgJywtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsLScgKyBycyArICdMLScgKyBycyArICcsJyArIHJzICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsJyArIHJzICsgJ0gtJyArIHJzICsgJ1YtJyArIHJzICsgJ0gnICsgcnMgKyAnWic7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZVxuICAgIH0sXG4gICAgJ2RpYW1vbmQtY3Jvc3MnOiB7XG4gICAgICAgIG46IDMxLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmQgPSBkMy5yb3VuZChyICogMS4zLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByZCArICcsMEwwLCcgKyByZCArICdMLScgKyByZCArICcsMEwwLC0nICsgcmQgKyAnWicgK1xuICAgICAgICAgICAgICAgICdNMCwtJyArIHJkICsgJ1YnICsgcmQgKyAnTS0nICsgcmQgKyAnLDBIJyArIHJkO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWVcbiAgICB9LFxuICAgICdkaWFtb25kLXgnOiB7XG4gICAgICAgIG46IDMyLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmQgPSBkMy5yb3VuZChyICogMS4zLCAyKSxcbiAgICAgICAgICAgICAgICByMiA9IGQzLnJvdW5kKHIgKiAwLjY1LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByZCArICcsMEwwLCcgKyByZCArICdMLScgKyByZCArICcsMEwwLC0nICsgcmQgKyAnWicgK1xuICAgICAgICAgICAgICAgICdNLScgKyByMiArICcsLScgKyByMiArICdMJyArIHIyICsgJywnICsgcjIgK1xuICAgICAgICAgICAgICAgICdNLScgKyByMiArICcsJyArIHIyICsgJ0wnICsgcjIgKyAnLC0nICsgcjI7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZVxuICAgIH0sXG4gICAgJ2Nyb3NzLXRoaW4nOiB7XG4gICAgICAgIG46IDMzLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogMS40LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHJjICsgJ1YtJyArIHJjICsgJ00nICsgcmMgKyAnLDBILScgKyByYztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICd4LXRoaW4nOiB7XG4gICAgICAgIG46IDM0LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnggPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByeCArICcsJyArIHJ4ICsgJ0wtJyArIHJ4ICsgJywtJyArIHJ4ICtcbiAgICAgICAgICAgICAgICAnTScgKyByeCArICcsLScgKyByeCArICdMLScgKyByeCArICcsJyArIHJ4O1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgYXN0ZXJpc2s6IHtcbiAgICAgICAgbjogMzUsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByYyA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociAqIDAuODUsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNMCwnICsgcmMgKyAnVi0nICsgcmMgKyAnTScgKyByYyArICcsMEgtJyArIHJjICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsJyArIHJzICsgJ0wtJyArIHJzICsgJywtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsLScgKyBycyArICdMLScgKyBycyArICcsJyArIHJzO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgaGFzaDoge1xuICAgICAgICBuOiAzNixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHIxID0gZDMucm91bmQociAvIDIsIDIpLFxuICAgICAgICAgICAgICAgIHIyID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcjEgKyAnLCcgKyByMiArICdWLScgKyByMiArXG4gICAgICAgICAgICAgICAgJ20tJyArIHIyICsgJywwVicgKyByMiArXG4gICAgICAgICAgICAgICAgJ00nICsgcjIgKyAnLCcgKyByMSArICdILScgKyByMiArXG4gICAgICAgICAgICAgICAgJ20wLC0nICsgcjIgKyAnSCcgKyByMjtcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ3ktdXAnOiB7XG4gICAgICAgIG46IDM3LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeCA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpLFxuICAgICAgICAgICAgICAgIHkwID0gZDMucm91bmQociAqIDEuNiwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyICogMC44LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgeCArICcsJyArIHkxICsgJ0wwLDBNJyArIHggKyAnLCcgKyB5MSArICdMMCwwTTAsLScgKyB5MCArICdMMCwwJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICd5LWRvd24nOiB7XG4gICAgICAgIG46IDM4LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeCA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpLFxuICAgICAgICAgICAgICAgIHkwID0gZDMucm91bmQociAqIDEuNiwgMiksXG4gICAgICAgICAgICAgICAgeTEgPSBkMy5yb3VuZChyICogMC44LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgeCArICcsLScgKyB5MSArICdMMCwwTScgKyB4ICsgJywtJyArIHkxICsgJ0wwLDBNMCwnICsgeTAgKyAnTDAsMCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZSxcbiAgICAgICAgbm9GaWxsOiB0cnVlXG4gICAgfSxcbiAgICAneS1sZWZ0Jzoge1xuICAgICAgICBuOiAzOSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHkgPSBkMy5yb3VuZChyICogMS4yLCAyKSxcbiAgICAgICAgICAgICAgICB4MCA9IGQzLnJvdW5kKHIgKiAxLjYsIDIpLFxuICAgICAgICAgICAgICAgIHgxID0gZDMucm91bmQociAqIDAuOCwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgeDEgKyAnLCcgKyB5ICsgJ0wwLDBNJyArIHgxICsgJywtJyArIHkgKyAnTDAsME0tJyArIHgwICsgJywwTDAsMCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZSxcbiAgICAgICAgbm9GaWxsOiB0cnVlXG4gICAgfSxcbiAgICAneS1yaWdodCc6IHtcbiAgICAgICAgbjogNDAsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB5ID0gZDMucm91bmQociAqIDEuMiwgMiksXG4gICAgICAgICAgICAgICAgeDAgPSBkMy5yb3VuZChyICogMS42LCAyKSxcbiAgICAgICAgICAgICAgICB4MSA9IGQzLnJvdW5kKHIgKiAwLjgsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyB4MSArICcsJyArIHkgKyAnTDAsME0tJyArIHgxICsgJywtJyArIHkgKyAnTDAsME0nICsgeDAgKyAnLDBMMCwwJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICdsaW5lLWV3Jzoge1xuICAgICAgICBuOiA0MSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJjID0gZDMucm91bmQociAqIDEuNCwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcmMgKyAnLDBILScgKyByYztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICdsaW5lLW5zJzoge1xuICAgICAgICBuOiA0MixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJjID0gZDMucm91bmQociAqIDEuNCwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00wLCcgKyByYyArICdWLScgKyByYztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICdsaW5lLW5lJzoge1xuICAgICAgICBuOiA0MyxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJ4ID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcnggKyAnLC0nICsgcnggKyAnTC0nICsgcnggKyAnLCcgKyByeDtcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICdsaW5lLW53Jzoge1xuICAgICAgICBuOiA0NCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJ4ID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcnggKyAnLCcgKyByeCArICdMLScgKyByeCArICcsLScgKyByeDtcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3BlcmNlbnQnLCAnY29uc3RhbnQnLCAnc3FydCcsICdkYXRhJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN5bW1ldHJpYzoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycmF5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheW1pbnVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB2YWx1ZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWVtaW51czoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdHJhY2VyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG4gICAgdHJhY2VyZWZtaW51czoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcbiAgICBjb3B5X3lzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBjb3B5X3pzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG4gICAgY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAyLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIG1ha2VDb21wdXRlRXJyb3IgPSByZXF1aXJlKCcuL2NvbXB1dGVfZXJyb3InKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QpIHtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY2RhdGFbaV07XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlICYmIFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdlcnJvckJhcnNPSycpKSB7XG4gICAgICAgICAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMpO1xuICAgICAgICAgICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnlheGlzKTtcbiAgICAgICAgICAgIGNhbGNPbmVBeGlzKGNhbGNUcmFjZSwgdHJhY2UsIHhhLCAneCcpO1xuICAgICAgICAgICAgY2FsY09uZUF4aXMoY2FsY1RyYWNlLCB0cmFjZSwgeWEsICd5Jyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjYWxjT25lQXhpcyhjYWxjVHJhY2UsIHRyYWNlLCBheGlzLCBjb29yZCkge1xuICAgIHZhciBvcHRzID0gdHJhY2VbJ2Vycm9yXycgKyBjb29yZF0gfHwge30sXG4gICAgICAgIGlzVmlzaWJsZSA9IChvcHRzLnZpc2libGUgJiYgWydsaW5lYXInLCAnbG9nJ10uaW5kZXhPZihheGlzLnR5cGUpICE9PSAtMSksXG4gICAgICAgIHZhbHMgPSBbXTtcblxuICAgIGlmKCFpc1Zpc2libGUpIHJldHVybjtcblxuICAgIHZhciBjb21wdXRlRXJyb3IgPSBtYWtlQ29tcHV0ZUVycm9yKG9wdHMpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldO1xuXG4gICAgICAgIHZhciBpSW4gPSBjYWxjUHQuaTtcblxuICAgICAgICAvLyBmb3IgdHlwZXMgdGhhdCBkb24ndCBpbmNsdWRlIGBpYCBpbiBlYWNoIGNhbGNkYXRhIHBvaW50XG4gICAgICAgIGlmKGlJbiA9PT0gdW5kZWZpbmVkKSBpSW4gPSBpO1xuXG4gICAgICAgIC8vIGZvciBzdGFja2VkIGFyZWEgaW5zZXJ0ZWQgcG9pbnRzXG4gICAgICAgIC8vIFRPRE86IGVycm9yYmFycyBoYXZlIGJlZW4gdGVzdGVkIGN1cnNvcmlseSB3aXRoIHN0YWNrZWQgYXJlYSxcbiAgICAgICAgLy8gYnV0IG5vdCB0aG9yb3VnaGx5LiBJdCdzIG5vdCBldmVuIHJlYWxseSBjbGVhciB3aGF0IHlvdSB3YW50IHRvIGRvOlxuICAgICAgICAvLyBTaG91bGQgaXQganVzdCBiZSBjYWxjdWxhdGVkIGJhc2VkIG9uIHRoYXQgdHJhY2UncyBzaXplIGRhdGE/XG4gICAgICAgIC8vIFNob3VsZCB5b3UgYWRkIGVycm9ycyBmcm9tIGJlbG93IGluIHF1YWRyYXR1cmU/XG4gICAgICAgIC8vIEFuZCB3aGF0IGFib3V0IG5vcm1hbGl6YXRpb24sIHdoZXJlIGluIHByaW5jaXBsZSB0aGUgZXJyb3JzIHNocmlua1xuICAgICAgICAvLyBhZ2FpbiB3aGVuIHlvdSBnZXQgdXAgdG8gdGhlIHRvcCBlbmQ/XG4gICAgICAgIC8vIE9uZSBvcHRpb24gd291bGQgYmUgdG8gZm9yYmlkIGVycm9yYmFycyB3aXRoIHN0YWNraW5nIHVudGlsIHdlXG4gICAgICAgIC8vIGRlY2lkZSBob3cgdG8gaGFuZGxlIHRoZXNlIHF1ZXN0aW9ucy5cbiAgICAgICAgZWxzZSBpZihpSW4gPT09IG51bGwpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjYWxjQ29vcmQgPSBjYWxjUHRbY29vcmRdO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMoYXhpcy5jMmwoY2FsY0Nvb3JkKSkpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBlcnJvcnMgPSBjb21wdXRlRXJyb3IoY2FsY0Nvb3JkLCBpSW4pO1xuICAgICAgICBpZihpc051bWVyaWMoZXJyb3JzWzBdKSAmJiBpc051bWVyaWMoZXJyb3JzWzFdKSkge1xuICAgICAgICAgICAgdmFyIHNob2UgPSBjYWxjUHRbY29vcmQgKyAncyddID0gY2FsY0Nvb3JkIC0gZXJyb3JzWzBdLFxuICAgICAgICAgICAgICAgIGhhdCA9IGNhbGNQdFtjb29yZCArICdoJ10gPSBjYWxjQ29vcmQgKyBlcnJvcnNbMV07XG4gICAgICAgICAgICB2YWxzLnB1c2goc2hvZSwgaGF0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBleHRyZW1lcyA9IEF4ZXMuZmluZEV4dHJlbWVzKGF4aXMsIHZhbHMsIHtwYWRkZWQ6IHRydWV9KTtcbiAgICB2YXIgYXhJZCA9IGF4aXMuX2lkO1xuICAgIHRyYWNlLl9leHRyZW1lc1theElkXS5taW4gPSB0cmFjZS5fZXh0cmVtZXNbYXhJZF0ubWluLmNvbmNhdChleHRyZW1lcy5taW4pO1xuICAgIHRyYWNlLl9leHRyZW1lc1theElkXS5tYXggPSB0cmFjZS5fZXh0cmVtZXNbYXhJZF0ubWF4LmNvbmNhdChleHRyZW1lcy5tYXgpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuLyoqXG4gKiBFcnJvciBiYXIgY29tcHV0aW5nIGZ1bmN0aW9uIGdlbmVyYXRvclxuICpcbiAqIE4uQi4gVGhlIGdlbmVyYXRlZCBmdW5jdGlvbiBkb2VzIG5vdCBjbGVhbiB0aGUgZGF0YVB0IGVudHJpZXMuIE5vbi1udW1lcmljXG4gKiBlbnRyaWVzIHJlc3VsdCBpbiB1bmRlZmluZWQgZXJyb3IgbWFnbml0dWRlcy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyBlcnJvciBiYXIgYXR0cmlidXRlc1xuICpcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSA6XG4gKiAgICAgIEBwYXJhbSB7bnVtZXJpY30gZGF0YVB0IGRhdGEgcG9pbnQgZnJvbSB3aGVyZSB0byBjb21wdXRlIHRoZSBlcnJvciBtYWduaXR1ZGVcbiAqICAgICAgQHBhcmFtIHtudW1iZXJ9IGluZGV4IGluZGV4IG9mIGRhdGFQdCBpbiBpdHMgY29ycmVzcG9uZGluZyBkYXRhIGFycmF5XG4gKiAgICAgIEByZXR1cm4ge2FycmF5fVxuICogICAgICAgIC0gZXJyb3JbMF0gOiBlcnJvciBtYWduaXR1ZGUgaW4gdGhlIG5lZ2F0aXZlIGRpcmVjdGlvblxuICogICAgICAgIC0gZXJyb3JbMV0gOiBcIiBcIiBcIiBcIiBwb3NpdGl2ZSBcIlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VDb21wdXRlRXJyb3Iob3B0cykge1xuICAgIHZhciB0eXBlID0gb3B0cy50eXBlLFxuICAgICAgICBzeW1tZXRyaWMgPSBvcHRzLnN5bW1ldHJpYztcblxuICAgIGlmKHR5cGUgPT09ICdkYXRhJykge1xuICAgICAgICB2YXIgYXJyYXkgPSBvcHRzLmFycmF5IHx8IFtdO1xuXG4gICAgICAgIGlmKHN5bW1ldHJpYykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNvbXB1dGVFcnJvcihkYXRhUHQsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9ICsoYXJyYXlbaW5kZXhdKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gW3ZhbCwgdmFsXTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgYXJyYXltaW51cyA9IG9wdHMuYXJyYXltaW51cyB8fCBbXTtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb21wdXRlRXJyb3IoZGF0YVB0LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciB2YWwgPSArYXJyYXlbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciB2YWxNaW51cyA9ICthcnJheW1pbnVzW2luZGV4XTtcbiAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIG9uZSBpcyBwcmVzZW50IGFuZCB0aGUgb3RoZXIgaXMgbWlzc2luZywgZmlsbCBpbiAwXG4gICAgICAgICAgICAgICAgLy8gc28gd2Ugc3RpbGwgc2VlIHRoZSBwcmVzZW50IG9uZS4gTW9zdGx5IHVzZWZ1bCBkdXJpbmcgbWFudWFsXG4gICAgICAgICAgICAgICAgLy8gZGF0YSBlbnRyeS5cbiAgICAgICAgICAgICAgICBpZighaXNOYU4odmFsKSB8fCAhaXNOYU4odmFsTWludXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbdmFsTWludXMgfHwgMCwgdmFsIHx8IDBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gW05hTiwgTmFOXTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBjb21wdXRlRXJyb3JWYWx1ZSA9IG1ha2VDb21wdXRlRXJyb3JWYWx1ZSh0eXBlLCBvcHRzLnZhbHVlKSxcbiAgICAgICAgICAgIGNvbXB1dGVFcnJvclZhbHVlTWludXMgPSBtYWtlQ29tcHV0ZUVycm9yVmFsdWUodHlwZSwgb3B0cy52YWx1ZW1pbnVzKTtcblxuICAgICAgICBpZihzeW1tZXRyaWMgfHwgb3B0cy52YWx1ZW1pbnVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb21wdXRlRXJyb3IoZGF0YVB0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9IGNvbXB1dGVFcnJvclZhbHVlKGRhdGFQdCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFt2YWwsIHZhbF07XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNvbXB1dGVFcnJvcihkYXRhUHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICBjb21wdXRlRXJyb3JWYWx1ZU1pbnVzKGRhdGFQdCksXG4gICAgICAgICAgICAgICAgICAgIGNvbXB1dGVFcnJvclZhbHVlKGRhdGFQdClcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQ29tcHV0ZSBlcnJvciBiYXIgbWFnbml0dWRlIChmb3IgYWxsIHR5cGVzIGV4Y2VwdCBkYXRhKVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIGVycm9yIGJhciB0eXBlXG4gKiBAcGFyYW0ge251bWVyaWN9IHZhbHVlIGVycm9yIGJhciB2YWx1ZVxuICpcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSA6XG4gKiAgICAgIEBwYXJhbSB7bnVtZXJpY30gZGF0YVB0XG4gKi9cbmZ1bmN0aW9uIG1ha2VDb21wdXRlRXJyb3JWYWx1ZSh0eXBlLCB2YWx1ZSkge1xuICAgIGlmKHR5cGUgPT09ICdwZXJjZW50Jykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZGF0YVB0KSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5hYnMoZGF0YVB0ICogdmFsdWUgLyAxMDApO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZih0eXBlID09PSAnY29uc3RhbnQnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyh2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmKHR5cGUgPT09ICdzcXJ0Jykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZGF0YVB0KSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KE1hdGguYWJzKGRhdGFQdCkpO1xuICAgICAgICB9O1xuICAgIH1cbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBvcHRzKSB7XG4gICAgdmFyIG9iak5hbWUgPSAnZXJyb3JfJyArIG9wdHMuYXhpcztcbiAgICB2YXIgY29udGFpbmVyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKHRyYWNlT3V0LCBvYmpOYW1lKTtcbiAgICB2YXIgY29udGFpbmVySW4gPSB0cmFjZUluW29iak5hbWVdIHx8IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGhhc0Vycm9yQmFycyA9IChcbiAgICAgICAgY29udGFpbmVySW4uYXJyYXkgIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBjb250YWluZXJJbi52YWx1ZSAhPT0gdW5kZWZpbmVkIHx8XG4gICAgICAgIGNvbnRhaW5lckluLnR5cGUgPT09ICdzcXJ0J1xuICAgICk7XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScsIGhhc0Vycm9yQmFycyk7XG5cbiAgICBpZih2aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIHR5cGUgPSBjb2VyY2UoJ3R5cGUnLCAnYXJyYXknIGluIGNvbnRhaW5lckluID8gJ2RhdGEnIDogJ3BlcmNlbnQnKSxcbiAgICAgICAgc3ltbWV0cmljID0gdHJ1ZTtcblxuICAgIGlmKHR5cGUgIT09ICdzcXJ0Jykge1xuICAgICAgICBzeW1tZXRyaWMgPSBjb2VyY2UoJ3N5bW1ldHJpYycsXG4gICAgICAgICAgICAhKCh0eXBlID09PSAnZGF0YScgPyAnYXJyYXltaW51cycgOiAndmFsdWVtaW51cycpIGluIGNvbnRhaW5lckluKSk7XG4gICAgfVxuXG4gICAgaWYodHlwZSA9PT0gJ2RhdGEnKSB7XG4gICAgICAgIGNvZXJjZSgnYXJyYXknKTtcbiAgICAgICAgY29lcmNlKCd0cmFjZXJlZicpO1xuICAgICAgICBpZighc3ltbWV0cmljKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ2FycmF5bWludXMnKTtcbiAgICAgICAgICAgIGNvZXJjZSgndHJhY2VyZWZtaW51cycpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYodHlwZSA9PT0gJ3BlcmNlbnQnIHx8IHR5cGUgPT09ICdjb25zdGFudCcpIHtcbiAgICAgICAgY29lcmNlKCd2YWx1ZScpO1xuICAgICAgICBpZighc3ltbWV0cmljKSBjb2VyY2UoJ3ZhbHVlbWludXMnKTtcbiAgICB9XG5cbiAgICB2YXIgY29weUF0dHIgPSAnY29weV8nICsgb3B0cy5pbmhlcml0ICsgJ3N0eWxlJztcbiAgICBpZihvcHRzLmluaGVyaXQpIHtcbiAgICAgICAgdmFyIGluaGVyaXRPYmogPSB0cmFjZU91dFsnZXJyb3JfJyArIG9wdHMuaW5oZXJpdF07XG4gICAgICAgIGlmKChpbmhlcml0T2JqIHx8IHt9KS52aXNpYmxlKSB7XG4gICAgICAgICAgICBjb2VyY2UoY29weUF0dHIsICEoY29udGFpbmVySW4uY29sb3IgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29udGFpbmVySW4udGhpY2tuZXNzKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTnVtZXJpYyhjb250YWluZXJJbi53aWR0aCkpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZighb3B0cy5pbmhlcml0IHx8ICFjb250YWluZXJPdXRbY29weUF0dHJdKSB7XG4gICAgICAgIGNvZXJjZSgnY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuICAgICAgICBjb2VyY2UoJ3RoaWNrbmVzcycpO1xuICAgICAgICBjb2VyY2UoJ3dpZHRoJywgUmVnaXN0cnkudHJhY2VJcyh0cmFjZU91dCwgJ2dsM2QnKSA/IDAgOiA0KTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbnZhciB4eUF0dHJzID0ge1xuICAgIGVycm9yX3g6IExpYi5leHRlbmRGbGF0KHt9LCBhdHRyaWJ1dGVzKSxcbiAgICBlcnJvcl95OiBMaWIuZXh0ZW5kRmxhdCh7fSwgYXR0cmlidXRlcylcbn07XG5kZWxldGUgeHlBdHRycy5lcnJvcl94LmNvcHlfenN0eWxlO1xuZGVsZXRlIHh5QXR0cnMuZXJyb3JfeS5jb3B5X3pzdHlsZTtcbmRlbGV0ZSB4eUF0dHJzLmVycm9yX3kuY29weV95c3R5bGU7XG5cbnZhciB4eXpBdHRycyA9IHtcbiAgICBlcnJvcl94OiBMaWIuZXh0ZW5kRmxhdCh7fSwgYXR0cmlidXRlcyksXG4gICAgZXJyb3JfeTogTGliLmV4dGVuZEZsYXQoe30sIGF0dHJpYnV0ZXMpLFxuICAgIGVycm9yX3o6IExpYi5leHRlbmRGbGF0KHt9LCBhdHRyaWJ1dGVzKVxufTtcbmRlbGV0ZSB4eXpBdHRycy5lcnJvcl94LmNvcHlfeXN0eWxlO1xuZGVsZXRlIHh5ekF0dHJzLmVycm9yX3kuY29weV95c3R5bGU7XG5kZWxldGUgeHl6QXR0cnMuZXJyb3Jfei5jb3B5X3lzdHlsZTtcbmRlbGV0ZSB4eXpBdHRycy5lcnJvcl96LmNvcHlfenN0eWxlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnZXJyb3JiYXJzJyxcblxuICAgIHNjaGVtYToge1xuICAgICAgICB0cmFjZXM6IHtcbiAgICAgICAgICAgIHNjYXR0ZXI6IHh5QXR0cnMsXG4gICAgICAgICAgICBiYXI6IHh5QXR0cnMsXG4gICAgICAgICAgICBoaXN0b2dyYW06IHh5QXR0cnMsXG4gICAgICAgICAgICBzY2F0dGVyM2Q6IG92ZXJyaWRlQWxsKHh5ekF0dHJzLCAnY2FsYycsICduZXN0ZWQnKSxcbiAgICAgICAgICAgIHNjYXR0ZXJnbDogb3ZlcnJpZGVBbGwoeHlBdHRycywgJ2NhbGMnLCAnbmVzdGVkJylcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuXG4gICAgY2FsYzogcmVxdWlyZSgnLi9jYWxjJyksXG4gICAgbWFrZUNvbXB1dGVFcnJvcjogcmVxdWlyZSgnLi9jb21wdXRlX2Vycm9yJyksXG5cbiAgICBwbG90OiByZXF1aXJlKCcuL3Bsb3QnKSxcbiAgICBzdHlsZTogcmVxdWlyZSgnLi9zdHlsZScpLFxuICAgIGhvdmVySW5mbzogaG92ZXJJbmZvXG59O1xuXG5mdW5jdGlvbiBob3ZlckluZm8oY2FsY1BvaW50LCB0cmFjZSwgaG92ZXJQb2ludCkge1xuICAgIGlmKCh0cmFjZS5lcnJvcl95IHx8IHt9KS52aXNpYmxlKSB7XG4gICAgICAgIGhvdmVyUG9pbnQueWVyciA9IGNhbGNQb2ludC55aCAtIGNhbGNQb2ludC55O1xuICAgICAgICBpZighdHJhY2UuZXJyb3JfeS5zeW1tZXRyaWMpIGhvdmVyUG9pbnQueWVycm5lZyA9IGNhbGNQb2ludC55IC0gY2FsY1BvaW50LnlzO1xuICAgIH1cbiAgICBpZigodHJhY2UuZXJyb3JfeCB8fCB7fSkudmlzaWJsZSkge1xuICAgICAgICBob3ZlclBvaW50LnhlcnIgPSBjYWxjUG9pbnQueGggLSBjYWxjUG9pbnQueDtcbiAgICAgICAgaWYoIXRyYWNlLmVycm9yX3guc3ltbWV0cmljKSBob3ZlclBvaW50LnhlcnJuZWcgPSBjYWxjUG9pbnQueCAtIGNhbGNQb2ludC54cztcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdCh0cmFjZXMsIHBsb3RpbmZvLCB0cmFuc2l0aW9uT3B0cykge1xuICAgIHZhciBpc05ldztcblxuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgdmFyIGhhc0FuaW1hdGlvbiA9IHRyYW5zaXRpb25PcHRzICYmIHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uID4gMDtcblxuICAgIHRyYWNlcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZSxcbiAgICAgICAgICAgIC8vIHx8IHt9IGlzIGluIGNhc2UgdGhlIHRyYWNlIChzcGVjaWZpY2FsbHkgc2NhdHRlcnRlcm5hcnkpXG4gICAgICAgICAgICAvLyBkb2Vzbid0IHN1cHBvcnQgZXJyb3IgYmFycyBhdCBhbGwsIGJ1dCBkb2VzIGdvIHRocm91Z2hcbiAgICAgICAgICAgIC8vIHRoZSBzY2F0dGVyLnBsb3QgbWVjaGFuaWNzLCB3aGljaCBjYWxscyBFcnJvckJhcnMucGxvdFxuICAgICAgICAgICAgLy8gaW50ZXJuYWxseVxuICAgICAgICAgICAgeE9iaiA9IHRyYWNlLmVycm9yX3ggfHwge30sXG4gICAgICAgICAgICB5T2JqID0gdHJhY2UuZXJyb3JfeSB8fCB7fTtcblxuICAgICAgICB2YXIga2V5RnVuYztcblxuICAgICAgICBpZih0cmFjZS5pZHMpIHtcbiAgICAgICAgICAgIGtleUZ1bmMgPSBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaWQ7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzcGFyc2UgPSAoXG4gICAgICAgICAgICBzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKSAmJlxuICAgICAgICAgICAgdHJhY2UubWFya2VyLm1heGRpc3BsYXllZCA+IDBcbiAgICAgICAgKTtcblxuICAgICAgICBpZigheU9iai52aXNpYmxlICYmICF4T2JqLnZpc2libGUpIGQgPSBbXTtcblxuICAgICAgICB2YXIgZXJyb3JiYXJzID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgnZy5lcnJvcmJhcicpXG4gICAgICAgICAgICAuZGF0YShkLCBrZXlGdW5jKTtcblxuICAgICAgICBlcnJvcmJhcnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGlmKCFkLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgICAgIGlmKCF4T2JqLnZpc2libGUpIGVycm9yYmFycy5zZWxlY3RBbGwoJ3BhdGgueGVycm9yJykucmVtb3ZlKCk7XG4gICAgICAgIGlmKCF5T2JqLnZpc2libGUpIGVycm9yYmFycy5zZWxlY3RBbGwoJ3BhdGgueWVycm9yJykucmVtb3ZlKCk7XG5cbiAgICAgICAgZXJyb3JiYXJzLnN0eWxlKCdvcGFjaXR5JywgMSk7XG5cbiAgICAgICAgdmFyIGVudGVyID0gZXJyb3JiYXJzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdlcnJvcmJhcicsIHRydWUpO1xuXG4gICAgICAgIGlmKGhhc0FuaW1hdGlvbikge1xuICAgICAgICAgICAgZW50ZXIuc3R5bGUoJ29wYWNpdHknLCAwKS50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSk7XG4gICAgICAgIH1cblxuICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwoZXJyb3JiYXJzLCBwbG90aW5mby5sYXllckNsaXBJZCk7XG5cbiAgICAgICAgZXJyb3JiYXJzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGVycm9yYmFyID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIGNvb3JkcyA9IGVycm9yQ29vcmRzKGQsIHhhLCB5YSk7XG5cbiAgICAgICAgICAgIGlmKHNwYXJzZSAmJiAhZC52aXMpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHBhdGg7XG5cbiAgICAgICAgICAgIHZhciB5ZXJyb3IgPSBlcnJvcmJhci5zZWxlY3QoJ3BhdGgueWVycm9yJyk7XG4gICAgICAgICAgICBpZih5T2JqLnZpc2libGUgJiYgaXNOdW1lcmljKGNvb3Jkcy54KSAmJlxuICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29vcmRzLnloKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29vcmRzLnlzKSkge1xuICAgICAgICAgICAgICAgIHZhciB5dyA9IHlPYmoud2lkdGg7XG5cbiAgICAgICAgICAgICAgICBwYXRoID0gJ00nICsgKGNvb3Jkcy54IC0geXcpICsgJywnICtcbiAgICAgICAgICAgICAgICAgICAgY29vcmRzLnloICsgJ2gnICsgKDIgKiB5dykgKyAvLyBoYXRcbiAgICAgICAgICAgICAgICAgICAgJ20tJyArIHl3ICsgJywwVicgKyBjb29yZHMueXM7IC8vIGJhclxuXG5cbiAgICAgICAgICAgICAgICBpZighY29vcmRzLm5vWVMpIHBhdGggKz0gJ20tJyArIHl3ICsgJywwaCcgKyAoMiAqIHl3KTsgLy8gc2hvZVxuXG4gICAgICAgICAgICAgICAgaXNOZXcgPSAheWVycm9yLnNpemUoKTtcblxuICAgICAgICAgICAgICAgIGlmKGlzTmV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHllcnJvciA9IGVycm9yYmFyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3ZlY3Rvci1lZmZlY3QnLCAnbm9uLXNjYWxpbmctc3Ryb2tlJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCd5ZXJyb3InLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoaGFzQW5pbWF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHllcnJvciA9IHllcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kdXJhdGlvbih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHllcnJvci5hdHRyKCdkJywgcGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHllcnJvci5yZW1vdmUoKTtcblxuICAgICAgICAgICAgdmFyIHhlcnJvciA9IGVycm9yYmFyLnNlbGVjdCgncGF0aC54ZXJyb3InKTtcbiAgICAgICAgICAgIGlmKHhPYmoudmlzaWJsZSAmJiBpc051bWVyaWMoY29vcmRzLnkpICYmXG4gICAgICAgICAgICAgICAgICAgIGlzTnVtZXJpYyhjb29yZHMueGgpICYmXG4gICAgICAgICAgICAgICAgICAgIGlzTnVtZXJpYyhjb29yZHMueHMpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHh3ID0gKHhPYmouY29weV95c3R5bGUgPyB5T2JqIDogeE9iaikud2lkdGg7XG5cbiAgICAgICAgICAgICAgICBwYXRoID0gJ00nICsgY29vcmRzLnhoICsgJywnICtcbiAgICAgICAgICAgICAgICAgICAgKGNvb3Jkcy55IC0geHcpICsgJ3YnICsgKDIgKiB4dykgKyAvLyBoYXRcbiAgICAgICAgICAgICAgICAgICAgJ20wLC0nICsgeHcgKyAnSCcgKyBjb29yZHMueHM7IC8vIGJhclxuXG4gICAgICAgICAgICAgICAgaWYoIWNvb3Jkcy5ub1hTKSBwYXRoICs9ICdtMCwtJyArIHh3ICsgJ3YnICsgKDIgKiB4dyk7IC8vIHNob2VcblxuICAgICAgICAgICAgICAgIGlzTmV3ID0gIXhlcnJvci5zaXplKCk7XG5cbiAgICAgICAgICAgICAgICBpZihpc05ldykge1xuICAgICAgICAgICAgICAgICAgICB4ZXJyb3IgPSBlcnJvcmJhci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgneGVycm9yJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGhhc0FuaW1hdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB4ZXJyb3IgPSB4ZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmVhc2UodHJhbnNpdGlvbk9wdHMuZWFzaW5nKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB4ZXJyb3IuYXR0cignZCcsIHBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB4ZXJyb3IucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuLy8gY29tcHV0ZSB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGVycm9yLWJhciBvYmplY3RzXG5mdW5jdGlvbiBlcnJvckNvb3JkcyhkLCB4YSwgeWEpIHtcbiAgICB2YXIgb3V0ID0ge1xuICAgICAgICB4OiB4YS5jMnAoZC54KSxcbiAgICAgICAgeTogeWEuYzJwKGQueSlcbiAgICB9O1xuXG4gICAgLy8gY2FsY3VsYXRlIHRoZSBlcnJvciBiYXIgc2l6ZSBhbmQgaGF0IGFuZCBzaG9lIGxvY2F0aW9uc1xuICAgIGlmKGQueWggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBvdXQueWggPSB5YS5jMnAoZC55aCk7XG4gICAgICAgIG91dC55cyA9IHlhLmMycChkLnlzKTtcblxuICAgICAgICAvLyBpZiB0aGUgc2hvZXMgZ28gb2ZmLXNjYWxlIChpZSBsb2cgc2NhbGUsIGVycm9yIGJhcnMgcGFzdCB6ZXJvKVxuICAgICAgICAvLyBjbGlwIHRoZSBiYXIgYW5kIGhpZGUgdGhlIHNob2VzXG4gICAgICAgIGlmKCFpc051bWVyaWMob3V0LnlzKSkge1xuICAgICAgICAgICAgb3V0Lm5vWVMgPSB0cnVlO1xuICAgICAgICAgICAgb3V0LnlzID0geWEuYzJwKGQueXMsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZC54aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG91dC54aCA9IHhhLmMycChkLnhoKTtcbiAgICAgICAgb3V0LnhzID0geGEuYzJwKGQueHMpO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMob3V0LnhzKSkge1xuICAgICAgICAgICAgb3V0Lm5vWFMgPSB0cnVlO1xuICAgICAgICAgICAgb3V0LnhzID0geGEuYzJwKGQueHMsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3R5bGUodHJhY2VzKSB7XG4gICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlLFxuICAgICAgICAgICAgeU9iaiA9IHRyYWNlLmVycm9yX3kgfHwge30sXG4gICAgICAgICAgICB4T2JqID0gdHJhY2UuZXJyb3JfeCB8fCB7fTtcblxuICAgICAgICB2YXIgcyA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBzLnNlbGVjdEFsbCgncGF0aC55ZXJyb3InKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB5T2JqLnRoaWNrbmVzcyArICdweCcpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHlPYmouY29sb3IpO1xuXG4gICAgICAgIGlmKHhPYmouY29weV95c3R5bGUpIHhPYmogPSB5T2JqO1xuXG4gICAgICAgIHMuc2VsZWN0QWxsKCdwYXRoLnhlcnJvcicpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHhPYmoudGhpY2tuZXNzICsgJ3B4JylcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgeE9iai5jb2xvcik7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhvdmVybGFiZWw6IHtcbiAgICAgICAgYmdjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgbmFtZWxlbmd0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICAgICAgbWluOiAtMSxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCkge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBmdW5jdGlvbiBtYWtlQ29lcmNlSG92ZXJJbmZvKHRyYWNlKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBMaWIuY29lcmNlSG92ZXJpbmZvKHtob3ZlcmluZm86IHZhbH0sIHtfbW9kdWxlOiB0cmFjZS5fbW9kdWxlfSwgZnVsbExheW91dCk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICAvLyBkb24ndCBpbmNsdWRlIGhvdmVyIGNhbGMgZmllbGRzIGZvciBwaWUgdHJhY2VzXG4gICAgICAgIC8vIGFzIGNhbGNkYXRhIGl0ZW1zIG1pZ2h0IGJlIHNvcnRlZCBieSB2YWx1ZSBhbmRcbiAgICAgICAgLy8gd29uJ3QgbWF0Y2ggdGhlIGRhdGEgYXJyYXkgb3JkZXIuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdwaWUnKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGZpbGxGbiA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICcyZE1hcCcpID8gcGFzdGUgOiBMaWIuZmlsbEFycmF5O1xuXG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmluZm8sIGNkLCAnaGknLCBtYWtlQ29lcmNlSG92ZXJJbmZvKHRyYWNlKSk7XG5cbiAgICAgICAgaWYoIXRyYWNlLmhvdmVybGFiZWwpIGNvbnRpbnVlO1xuXG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmJnY29sb3IsIGNkLCAnaGJnJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmJvcmRlcmNvbG9yLCBjZCwgJ2hiYycpO1xuICAgICAgICBmaWxsRm4odHJhY2UuaG92ZXJsYWJlbC5mb250LnNpemUsIGNkLCAnaHRzJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmZvbnQuY29sb3IsIGNkLCAnaHRjJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmZvbnQuZmFtaWx5LCBjZCwgJ2h0ZicpO1xuICAgICAgICBmaWxsRm4odHJhY2UuaG92ZXJsYWJlbC5uYW1lbGVuZ3RoLCBjZCwgJ2hubCcpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBhc3RlKHRyYWNlQXR0ciwgY2QsIGNkQXR0ciwgZm4pIHtcbiAgICBmbiA9IGZuIHx8IExpYi5pZGVudGl0eTtcblxuICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2VBdHRyKSkge1xuICAgICAgICBjZFswXVtjZEF0dHJdID0gZm4odHJhY2VBdHRyKTtcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgaG92ZXIgPSByZXF1aXJlKCcuL2hvdmVyJykuaG92ZXI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2xpY2soZ2QsIGV2dCwgc3VicGxvdCkge1xuICAgIHZhciBhbm5vdGF0aW9uc0RvbmUgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ29uQ2xpY2snKShnZCwgZ2QuX2hvdmVyZGF0YSk7XG5cbiAgICAvLyBmYWxsYmFjayB0byBmYWlsLXNhZmUgaW4gY2FzZSB0aGUgcGxvdCB0eXBlJ3MgaG92ZXIgbWV0aG9kIGRvZXNuJ3QgcGFzcyB0aGUgc3VicGxvdC5cbiAgICAvLyBUZXJuYXJ5LCBmb3IgZXhhbXBsZSwgZGlkbid0LCBidXQgaXQgd2FzIGNhdWdodCBiZWNhdXNlIHRlc3RlZC5cbiAgICBpZihzdWJwbG90ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gVGhlIHRydWUgZmxhZyBhdCB0aGUgZW5kIGNhdXNlcyBpdCB0byByZS1ydW4gdGhlIGhvdmVyIGNvbXB1dGF0aW9uIHRvIGZpZ3VyZSBvdXQgKndoaWNoKlxuICAgICAgICAvLyBwb2ludCBpcyBiZWluZyBjbGlja2VkLiBXaXRob3V0IHRoaXMsIGNsaWNraW5nIGlzIHNvbWV3aGF0IHVucmVsaWFibGUuXG4gICAgICAgIGhvdmVyKGdkLCBldnQsIHN1YnBsb3QsIHRydWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRDbGljaygpIHsgZ2QuZW1pdCgncGxvdGx5X2NsaWNrJywge3BvaW50czogZ2QuX2hvdmVyZGF0YSwgZXZlbnQ6IGV2dH0pOyB9XG5cbiAgICBpZihnZC5faG92ZXJkYXRhICYmIGV2dCAmJiBldnQudGFyZ2V0KSB7XG4gICAgICAgIGlmKGFubm90YXRpb25zRG9uZSAmJiBhbm5vdGF0aW9uc0RvbmUudGhlbikge1xuICAgICAgICAgICAgYW5ub3RhdGlvbnNEb25lLnRoZW4oZW1pdENsaWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGVtaXRDbGljaygpO1xuXG4gICAgICAgIC8vIHdoeSBkbyB3ZSBnZXQgYSBkb3VibGUgZXZlbnQgd2l0aG91dCB0aGlzPz8/XG4gICAgICAgIGlmKGV2dC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24pIGV2dC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBob3ZlciBsYWJlbHMgZm9yIG11bHRpcGxlIGhvcml6b250YWwgYmFycyBnZXQgdGlsdGVkIGJ5IHRoaXMgYW5nbGVcbiAgICBZQU5HTEU6IDYwLFxuXG4gICAgLy8gc2l6ZSBhbmQgZGlzcGxheSBjb25zdGFudHMgZm9yIGhvdmVyIHRleHRcblxuICAgIC8vIHBpeGVsIHNpemUgb2YgaG92ZXIgYXJyb3dzXG4gICAgSE9WRVJBUlJPV1NJWkU6IDYsXG4gICAgLy8gcGl4ZWxzIHBhZGRpbmcgYXJvdW5kIHRleHRcbiAgICBIT1ZFUlRFWFRQQUQ6IDMsXG4gICAgLy8gaG92ZXIgZm9udFxuICAgIEhPVkVSRk9OVFNJWkU6IDEzLFxuICAgIEhPVkVSRk9OVDogJ0FyaWFsLCBzYW5zLXNlcmlmJyxcblxuICAgIC8vIG1pbmltdW0gdGltZSAobXNlYykgYmV0d2VlbiBob3ZlciBjYWxsc1xuICAgIEhPVkVSTUlOVElNRTogNTAsXG5cbiAgICAvLyBJRCBzdWZmaXggKHdpdGggZnVsbExheW91dC5fdWlkKSBmb3IgaG92ZXIgZXZlbnRzIGluIHRoZSB0aHJvdHRsZSBjYWNoZVxuICAgIEhPVkVSSUQ6ICctaG92ZXInXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZUhvdmVyTGFiZWxEZWZhdWx0cyA9IHJlcXVpcmUoJy4vaG92ZXJsYWJlbF9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LmhvdmVybGFiZWwpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG4vLyBsb29rIGZvciBlaXRoZXIgc3VicGxvdCBvciB4YXhpcyBhbmQgeWF4aXMgYXR0cmlidXRlc1xuLy8gZG9lcyBub3QgaGFuZGxlIHNwbG9tIGNhc2VcbmV4cG9ydHMuZ2V0U3VicGxvdCA9IGZ1bmN0aW9uIGdldFN1YnBsb3QodHJhY2UpIHtcbiAgICByZXR1cm4gdHJhY2Uuc3VicGxvdCB8fCAodHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcykgfHwgdHJhY2UuZ2VvO1xufTtcblxuLy8gaXMgdHJhY2UgaW4gZ2l2ZW4gbGlzdCBvZiBzdWJwbG90cz9cbi8vIGRvZXMgaGFuZGxlIHNwbG9tIGNhc2VcbmV4cG9ydHMuaXNUcmFjZUluU3VicGxvdHMgPSBmdW5jdGlvbiBpc1RyYWNlSW5TdWJwbG90KHRyYWNlLCBzdWJwbG90cykge1xuICAgIGlmKHRyYWNlLnR5cGUgPT09ICdzcGxvbScpIHtcbiAgICAgICAgdmFyIHhheGVzID0gdHJhY2UueGF4ZXMgfHwgW107XG4gICAgICAgIHZhciB5YXhlcyA9IHRyYWNlLnlheGVzIHx8IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgeGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB5YXhlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKHN1YnBsb3RzLmluZGV4T2YoeGF4ZXNbaV0gKyB5YXhlc1tqXSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1YnBsb3RzLmluZGV4T2YoZXhwb3J0cy5nZXRTdWJwbG90KHRyYWNlKSkgIT09IC0xO1xufTtcblxuLy8gY29udmVuaWVuY2UgZnVuY3Rpb25zIGZvciBtYXBwaW5nIGFsbCByZWxldmFudCBheGVzXG5leHBvcnRzLmZsYXQgPSBmdW5jdGlvbiBmbGF0KHN1YnBsb3RzLCB2KSB7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShzdWJwbG90cy5sZW5ndGgpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzdWJwbG90cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdXRbaV0gPSB2O1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZXhwb3J0cy5wMmMgPSBmdW5jdGlvbiBwMmMoYXhBcnJheSwgdikge1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkoYXhBcnJheS5sZW5ndGgpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheEFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IGF4QXJyYXlbaV0ucDJjKHYpO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZXhwb3J0cy5nZXREaXN0YW5jZUZ1bmN0aW9uID0gZnVuY3Rpb24gZ2V0RGlzdGFuY2VGdW5jdGlvbihtb2RlLCBkeCwgZHksIGR4eSkge1xuICAgIGlmKG1vZGUgPT09ICdjbG9zZXN0JykgcmV0dXJuIGR4eSB8fCBleHBvcnRzLnF1YWRyYXR1cmUoZHgsIGR5KTtcbiAgICByZXR1cm4gbW9kZSA9PT0gJ3gnID8gZHggOiBkeTtcbn07XG5cbmV4cG9ydHMuZ2V0Q2xvc2VzdCA9IGZ1bmN0aW9uIGdldENsb3Nlc3QoY2QsIGRpc3RmbiwgcG9pbnREYXRhKSB7XG4gICAgLy8gZG8gd2UgYWxyZWFkeSBoYXZlIGEgcG9pbnQgbnVtYmVyPyAoYXJyYXkgbW9kZSBvbmx5KVxuICAgIGlmKHBvaW50RGF0YS5pbmRleCAhPT0gZmFsc2UpIHtcbiAgICAgICAgaWYocG9pbnREYXRhLmluZGV4ID49IDAgJiYgcG9pbnREYXRhLmluZGV4IDwgY2QubGVuZ3RoKSB7XG4gICAgICAgICAgICBwb2ludERhdGEuZGlzdGFuY2UgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgcG9pbnREYXRhLmluZGV4ID0gZmFsc2U7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyBhcHBseSB0aGUgZGlzdGFuY2UgZnVuY3Rpb24gdG8gZWFjaCBkYXRhIHBvaW50XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGxvbmdlc3QgbG9vcC4uLiBpZiB0aGlzIGJvZ3MgZG93biwgd2UgbWF5IG5lZWRcbiAgICAgICAgLy8gdG8gY3JlYXRlIHByZS1zb3J0ZWQgZGF0YSAoYnkgeCBvciB5KSwgbm90IHN1cmUgaG93IHRvXG4gICAgICAgIC8vIGRvIHRoaXMgZm9yICdjbG9zZXN0J1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBuZXdEaXN0YW5jZSA9IGRpc3RmbihjZFtpXSk7XG4gICAgICAgICAgICBpZihuZXdEaXN0YW5jZSA8PSBwb2ludERhdGEuZGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBwb2ludERhdGEuaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIHBvaW50RGF0YS5kaXN0YW5jZSA9IG5ld0Rpc3RhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwb2ludERhdGE7XG59O1xuXG4vKlxuICogcHNldWRvLWRpc3RhbmNlIGZ1bmN0aW9uIGZvciBob3ZlciBlZmZlY3RzIG9uIGFyZWFzOiBpbnNpZGUgdGhlIHJlZ2lvblxuICogZGlzdGFuY2UgaXMgZmluaXRlIChgcGFzc1ZhbGApLCBvdXRzaWRlIGl0J3MgSW5maW5pdHkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHYwOiBzaWduZWQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjdXJyZW50IHBvc2l0aW9uIGFuZCB0aGUgbGVmdCBlZGdlXG4gKiBAcGFyYW0ge251bWJlcn0gdjE6IHNpZ25lZCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGN1cnJlbnQgcG9zaXRpb24gYW5kIHRoZSByaWdodCBlZGdlXG4gKiBAcGFyYW0ge251bWJlcn0gcGFzc1ZhbDogdGhlIHZhbHVlIHRvIHJldHVybiBvbiBzdWNjZXNzXG4gKi9cbmV4cG9ydHMuaW5ib3ggPSBmdW5jdGlvbiBpbmJveCh2MCwgdjEsIHBhc3NWYWwpIHtcbiAgICByZXR1cm4gKHYwICogdjEgPCAwIHx8IHYwID09PSAwKSA/IHBhc3NWYWwgOiBJbmZpbml0eTtcbn07XG5cbmV4cG9ydHMucXVhZHJhdHVyZSA9IGZ1bmN0aW9uIHF1YWRyYXR1cmUoZHgsIGR5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgIHZhciB4ID0gZHgoZGkpLFxuICAgICAgICAgICAgeSA9IGR5KGRpKTtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcbiAgICB9O1xufTtcblxuLyoqIEZpbGwgZXZlbnQgZGF0YSBwb2ludCBvYmplY3QgZm9yIGhvdmVyIGFuZCBzZWxlY3Rpb24uXG4gKiAgSW52b2tlcyBfbW9kdWxlLmV2ZW50RGF0YSBpZiBwcmVzZW50LlxuICpcbiAqIE4uQi4gbm90ZSB0aGF0IHBvaW50ICdpbmRleCcgY29ycmVzcG9uZHMgdG8gaW5wdXQgZGF0YSBhcnJheSBpbmRleFxuICogIHdoZXJlYXMgJ251bWJlcicgaXMgaXRzIHBvc3QtdHJhbnNmb3JtIHZlcnNpb24uXG4gKlxuICogSWYgdGhlIGhvdmVyZWQvc2VsZWN0ZWQgcHQgY29ycmVzcG9uZHMgdG8gYW4gbXVsdGlwbGUgaW5wdXQgcG9pbnRzXG4gKiAoZS5nLiBmb3IgaGlzdG9ncmFtIGFuZCB0cmFuc2Zvcm1lZCB0cmFjZXMpLCAncG9pbnROdW1iZXJzYCBhbmQgJ3BvaW50SW5kaWNlcydcbiAqIGFyZSBpbmNsdWRlIGluIHRoZSBldmVudCBkYXRhLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwdFxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gY2RcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqL1xuZXhwb3J0cy5tYWtlRXZlbnREYXRhID0gZnVuY3Rpb24gbWFrZUV2ZW50RGF0YShwdCwgdHJhY2UsIGNkKSB7XG4gICAgLy8gaG92ZXIgdXNlcyAnaW5kZXgnLCBzZWxlY3QgdXNlcyAncG9pbnROdW1iZXInXG4gICAgdmFyIHBvaW50TnVtYmVyID0gJ2luZGV4JyBpbiBwdCA/IHB0LmluZGV4IDogcHQucG9pbnROdW1iZXI7XG5cbiAgICB2YXIgb3V0ID0ge1xuICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgIGZ1bGxEYXRhOiB0cmFjZSxcbiAgICAgICAgY3VydmVOdW1iZXI6IHRyYWNlLmluZGV4LFxuICAgICAgICBwb2ludE51bWJlcjogcG9pbnROdW1iZXJcbiAgICB9O1xuXG4gICAgaWYodHJhY2UuX2luZGV4VG9Qb2ludHMpIHtcbiAgICAgICAgdmFyIHBvaW50SW5kaWNlcyA9IHRyYWNlLl9pbmRleFRvUG9pbnRzW3BvaW50TnVtYmVyXTtcblxuICAgICAgICBpZihwb2ludEluZGljZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBvdXQucG9pbnRJbmRleCA9IHBvaW50SW5kaWNlc1swXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dC5wb2ludEluZGljZXMgPSBwb2ludEluZGljZXM7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvdXQucG9pbnRJbmRleCA9IHBvaW50TnVtYmVyO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLl9tb2R1bGUuZXZlbnREYXRhKSB7XG4gICAgICAgIG91dCA9IHRyYWNlLl9tb2R1bGUuZXZlbnREYXRhKG91dCwgcHQsIHRyYWNlLCBjZCwgcG9pbnROdW1iZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKCd4VmFsJyBpbiBwdCkgb3V0LnggPSBwdC54VmFsO1xuICAgICAgICBlbHNlIGlmKCd4JyBpbiBwdCkgb3V0LnggPSBwdC54O1xuXG4gICAgICAgIGlmKCd5VmFsJyBpbiBwdCkgb3V0LnkgPSBwdC55VmFsO1xuICAgICAgICBlbHNlIGlmKCd5JyBpbiBwdCkgb3V0LnkgPSBwdC55O1xuXG4gICAgICAgIGlmKHB0LnhhKSBvdXQueGF4aXMgPSBwdC54YTtcbiAgICAgICAgaWYocHQueWEpIG91dC55YXhpcyA9IHB0LnlhO1xuICAgICAgICBpZihwdC56TGFiZWxWYWwgIT09IHVuZGVmaW5lZCkgb3V0LnogPSBwdC56TGFiZWxWYWw7XG4gICAgfVxuXG4gICAgZXhwb3J0cy5hcHBlbmRBcnJheVBvaW50VmFsdWUob3V0LCB0cmFjZSwgcG9pbnROdW1iZXIpO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKiBBcHBlbmRzIHZhbHVlcyBpbnNpZGUgYXJyYXkgYXR0cmlidXRlcyBjb3JyZXNwb25kaW5nIHRvIGdpdmVuIHBvaW50IG51bWJlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwb2ludERhdGEgOiBwb2ludCBkYXRhIG9iamVjdCAoZ2V0cyBtdXRhdGVkIGhlcmUpXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2UgOiBmdWxsIHRyYWNlIG9iamVjdFxuICogQHBhcmFtIHtudW1iZXJ8QXJyYXkobnVtYmVyKX0gcG9pbnROdW1iZXIgOiBwb2ludCBudW1iZXIuIE1heSBiZSBhIGxlbmd0aC0yIGFycmF5XG4gKiAgICAgW3JvdywgY29sXSB0byBkaWcgaW50byAyRCBhcnJheXNcbiAqL1xuZXhwb3J0cy5hcHBlbmRBcnJheVBvaW50VmFsdWUgPSBmdW5jdGlvbihwb2ludERhdGEsIHRyYWNlLCBwb2ludE51bWJlcikge1xuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG5cbiAgICBpZighYXJyYXlBdHRycykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5QXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFzdHIgPSBhcnJheUF0dHJzW2ldO1xuICAgICAgICB2YXIga2V5ID0gZ2V0UG9pbnRLZXkoYXN0cik7XG5cbiAgICAgICAgaWYocG9pbnREYXRhW2tleV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXN0cikuZ2V0KCk7XG4gICAgICAgICAgICB2YXIgcG9pbnRWYWwgPSBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcik7XG5cbiAgICAgICAgICAgIGlmKHBvaW50VmFsICE9PSB1bmRlZmluZWQpIHBvaW50RGF0YVtrZXldID0gcG9pbnRWYWw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKipcbiAqIEFwcGVuZHMgdmFsdWVzIGluc2lkZSBhcnJheSBhdHRyaWJ1dGVzIGNvcnJlc3BvbmRpbmcgdG8gZ2l2ZW4gcG9pbnQgbnVtYmVyIGFycmF5XG4gKiBGb3IgdXNlIHdoZW4gcG9pbnREYXRhIHJlZmVyZW5jZXMgYSBwbG90IGVudGl0eSB0aGF0IGFyb3NlIChvciBwb3RlbnRpYWxseSBhcm9zZSlcbiAqIGZyb20gbXVsdGlwbGUgcG9pbnRzIGluIHRoZSBpbnB1dCBkYXRhXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHBvaW50RGF0YSA6IHBvaW50IGRhdGEgb2JqZWN0IChnZXRzIG11dGF0ZWQgaGVyZSlcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZSA6IGZ1bGwgdHJhY2Ugb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5KG51bWJlcil8QXJyYXkoQXJyYXkobnVtYmVyKSl9IHBvaW50TnVtYmVycyA6IEFycmF5IG9mIHBvaW50IG51bWJlcnMuXG4gKiAgICAgRWFjaCBlbnRyeSBpbiB0aGUgYXJyYXkgbWF5IGl0c2VsZiBiZSBhIGxlbmd0aC0yIGFycmF5IFtyb3csIGNvbF0gdG8gZGlnIGludG8gMkQgYXJyYXlzXG4gKi9cbmV4cG9ydHMuYXBwZW5kQXJyYXlNdWx0aVBvaW50VmFsdWVzID0gZnVuY3Rpb24ocG9pbnREYXRhLCB0cmFjZSwgcG9pbnROdW1iZXJzKSB7XG4gICAgdmFyIGFycmF5QXR0cnMgPSB0cmFjZS5fYXJyYXlBdHRycztcblxuICAgIGlmKCFhcnJheUF0dHJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyYXlBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXN0ciA9IGFycmF5QXR0cnNbaV07XG4gICAgICAgIHZhciBrZXkgPSBnZXRQb2ludEtleShhc3RyKTtcblxuICAgICAgICBpZihwb2ludERhdGFba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB2YXIgdmFsID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhc3RyKS5nZXQoKTtcbiAgICAgICAgICAgIHZhciBrZXlWYWwgPSBuZXcgQXJyYXkocG9pbnROdW1iZXJzLmxlbmd0aCk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBwb2ludE51bWJlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBrZXlWYWxbal0gPSBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcnNbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnREYXRhW2tleV0gPSBrZXlWYWw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgcG9pbnRLZXlNYXAgPSB7XG4gICAgaWRzOiAnaWQnLFxuICAgIGxvY2F0aW9uczogJ2xvY2F0aW9uJyxcbiAgICBsYWJlbHM6ICdsYWJlbCcsXG4gICAgdmFsdWVzOiAndmFsdWUnLFxuICAgICdtYXJrZXIuY29sb3JzJzogJ2NvbG9yJ1xufTtcblxuZnVuY3Rpb24gZ2V0UG9pbnRLZXkoYXN0cikge1xuICAgIHJldHVybiBwb2ludEtleU1hcFthc3RyXSB8fCBhc3RyO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcikge1xuICAgIGlmKEFycmF5LmlzQXJyYXkocG9pbnROdW1iZXIpKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodmFsKSAmJiBBcnJheS5pc0FycmF5KHZhbFtwb2ludE51bWJlclswXV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsW3BvaW50TnVtYmVyWzBdXVtwb2ludE51bWJlclsxXV07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsW3BvaW50TnVtYmVyXTtcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBFdmVudHMgPSByZXF1aXJlKCcuLi8uLi9saWIvZXZlbnRzJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgb3ZlcnJpZGVDdXJzb3IgPSByZXF1aXJlKCcuLi8uLi9saWIvb3ZlcnJpZGVfY3Vyc29yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi9kcmFnZWxlbWVudCcpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG4vLyBob3ZlciBsYWJlbHMgZm9yIG11bHRpcGxlIGhvcml6b250YWwgYmFycyBnZXQgdGlsdGVkIGJ5IHNvbWUgYW5nbGUsXG4vLyB0aGVuIG5lZWQgdG8gYmUgb2Zmc2V0IGRpZmZlcmVudGx5IGlmIHRoZXkgb3ZlcmxhcFxudmFyIFlBTkdMRSA9IGNvbnN0YW50cy5ZQU5HTEU7XG52YXIgWUFfUkFESUFOUyA9IE1hdGguUEkgKiBZQU5HTEUgLyAxODA7XG5cbi8vIGV4cGFuc2lvbiBvZiBwcm9qZWN0ZWQgaGVpZ2h0XG52YXIgWUZBQ1RPUiA9IDEgLyBNYXRoLnNpbihZQV9SQURJQU5TKTtcblxuLy8gdG8gbWFrZSB0aGUgYXBwcm9wcmlhdGUgcG9zdC1yb3RhdGlvbiB4IG9mZnNldCxcbi8vIHlvdSBuZWVkIGJvdGggeCBhbmQgeSBvZmZzZXRzXG52YXIgWVNISUZUWCA9IE1hdGguY29zKFlBX1JBRElBTlMpO1xudmFyIFlTSElGVFkgPSBNYXRoLnNpbihZQV9SQURJQU5TKTtcblxuLy8gc2l6ZSBhbmQgZGlzcGxheSBjb25zdGFudHMgZm9yIGhvdmVyIHRleHRcbnZhciBIT1ZFUkFSUk9XU0laRSA9IGNvbnN0YW50cy5IT1ZFUkFSUk9XU0laRTtcbnZhciBIT1ZFUlRFWFRQQUQgPSBjb25zdGFudHMuSE9WRVJURVhUUEFEO1xuXG4vLyBmeC5ob3ZlcjogaGlnaGxpZ2h0IGRhdGEgb24gaG92ZXJcbi8vIGV2dCBjYW4gYmUgYSBtb3VzZW1vdmUgZXZlbnQsIG9yIGFuIG9iamVjdCB3aXRoIGRhdGEgYWJvdXQgd2hhdCBwb2ludHNcbi8vICAgdG8gaG92ZXIgb25cbi8vICAgICAge3hweCx5cHhbLGhvdmVybW9kZV19IC0gcGl4ZWwgbG9jYXRpb25zIGZyb20gdG9wIGxlZnRcbi8vICAgICAgICAgICh3aXRoIG9wdGlvbmFsIG92ZXJyaWRpbmcgaG92ZXJtb2RlKVxuLy8gICAgICB7eHZhbCx5dmFsWyxob3Zlcm1vZGVdfSAtIGRhdGEgdmFsdWVzXG4vLyAgICAgIFt7Y3VydmVOdW1iZXIsKHBvaW50TnVtYmVyfHh2YWwgYW5kL29yIHl2YWwpfV0gLVxuLy8gICAgICAgICAgICAgIGFycmF5IG9mIHNwZWNpZmljIHBvaW50cyB0byBoaWdobGlnaHRcbi8vICAgICAgICAgIHBvaW50TnVtYmVyIGlzIGEgc2luZ2xlIGludGVnZXIgaWYgZ2QuZGF0YVtjdXJ2ZU51bWJlcl0gaXMgMUQsXG4vLyAgICAgICAgICAgICAgb3IgYSB0d28tZWxlbWVudCBhcnJheSBpZiBpdCdzIDJEXG4vLyAgICAgICAgICB4dmFsIGFuZCB5dmFsIGFyZSBkYXRhIHZhbHVlcyxcbi8vICAgICAgICAgICAgICAxRCBkYXRhIG1heSBzcGVjaWZ5IGVpdGhlciBvciBib3RoLFxuLy8gICAgICAgICAgICAgIDJEIGRhdGEgbXVzdCBzcGVjaWZ5IGJvdGhcbi8vIHN1YnBsb3QgaXMgYW4gaWQgc3RyaW5nIChkZWZhdWx0IFwieHlcIilcbi8vIG1ha2VzIHVzZSBvZiBnbC5ob3Zlcm1vZGUsIHdoaWNoIGNhbiBiZTpcbi8vICAgICAgeCAoZmluZCB0aGUgcG9pbnRzIHdpdGggdGhlIGNsb3Nlc3QgeCB2YWx1ZXMsIGllIGEgY29sdW1uKSxcbi8vICAgICAgY2xvc2VzdCAoZmluZCB0aGUgc2luZ2xlIGNsb3Nlc3QgcG9pbnQpXG4vLyAgICBpbnRlcm5hbGx5IHRoZXJlIGFyZSB0d28gbW9yZSB0aGF0IG9jY2FzaW9uYWxseSBnZXQgdXNlZDpcbi8vICAgICAgeSAocGljayBvdXQgYSByb3cgLSBvbmx5IHVzZWQgZm9yIG11bHRpcGxlIGhvcml6b250YWwgYmFyIGNoYXJ0cylcbi8vICAgICAgYXJyYXkgKHVzZWQgd2hlbiB0aGUgdXNlciBzcGVjaWZpZXMgYW4gZXhwbGljaXRcbi8vICAgICAgICAgIGFycmF5IG9mIHBvaW50cyB0byBob3ZlciBvbilcbi8vXG4vLyBXZSB3cmFwIHRoZSBob3ZlcnMgaW4gYSB0aW1lciwgdG8gbGltaXQgdGhlaXIgZnJlcXVlbmN5LlxuLy8gVGhlIGFjdHVhbCByZW5kZXJpbmcgaXMgZG9uZSBieSBwcml2YXRlIGZ1bmN0aW9uIF9ob3Zlci5cbmV4cG9ydHMuaG92ZXIgPSBmdW5jdGlvbiBob3ZlcihnZCwgZXZ0LCBzdWJwbG90LCBub0hvdmVyRXZlbnQpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICBMaWIudGhyb3R0bGUoXG4gICAgICAgIGdkLl9mdWxsTGF5b3V0Ll91aWQgKyBjb25zdGFudHMuSE9WRVJJRCxcbiAgICAgICAgY29uc3RhbnRzLkhPVkVSTUlOVElNRSxcbiAgICAgICAgZnVuY3Rpb24oKSB7IF9ob3ZlcihnZCwgZXZ0LCBzdWJwbG90LCBub0hvdmVyRXZlbnQpOyB9XG4gICAgKTtcbn07XG5cbi8qXG4gKiBEcmF3IGEgc2luZ2xlIGhvdmVyIGl0ZW0gaW4gYSBwcmUtZXhpc3Rpbmcgc3ZnIGNvbnRhaW5lciBzb21ld2hlcmVcbiAqIGhvdmVySXRlbSBzaG91bGQgaGF2ZSBrZXlzOlxuICogICAgLSB4IGFuZCB5IChvciB4MCwgeDEsIHkwLCBhbmQgeTEpOlxuICogICAgICB0aGUgcGl4ZWwgcG9zaXRpb24gdG8gbWFyaywgcmVsYXRpdmUgdG8gb3B0cy5jb250YWluZXJcbiAqICAgIC0geExhYmVsLCB5TGFiZWwsIHpMYWJlbCwgdGV4dCwgYW5kIG5hbWU6XG4gKiAgICAgIGluZm8gdG8gZ28gaW4gdGhlIGxhYmVsXG4gKiAgICAtIGNvbG9yOlxuICogICAgICB0aGUgYmFja2dyb3VuZCBjb2xvciBmb3IgdGhlIGxhYmVsLlxuICogICAgLSBpZGVhbEFsaWduIChvcHRpb25hbCk6XG4gKiAgICAgICdsZWZ0JyBvciAncmlnaHQnIGZvciB3aGljaCBzaWRlIG9mIHRoZSB4L3kgYm94IHRvIHRyeSB0byBwdXQgdGhpcyBvbiBmaXJzdFxuICogICAgLSBib3JkZXJDb2xvciAob3B0aW9uYWwpOlxuICogICAgICBjb2xvciBmb3IgdGhlIGJvcmRlciwgZGVmYXVsdHMgdG8gc3Ryb25nZXN0IGNvbnRyYXN0IHdpdGggY29sb3JcbiAqICAgIC0gZm9udEZhbWlseSAob3B0aW9uYWwpOlxuICogICAgICBzdHJpbmcsIHRoZSBmb250IGZvciB0aGlzIGxhYmVsLCBkZWZhdWx0cyB0byBjb25zdGFudHMuSE9WRVJGT05UXG4gKiAgICAtIGZvbnRTaXplIChvcHRpb25hbCk6XG4gKiAgICAgIHRoZSBsYWJlbCBmb250IHNpemUsIGRlZmF1bHRzIHRvIGNvbnN0YW50cy5IT1ZFUkZPTlRTSVpFXG4gKiAgICAtIGZvbnRDb2xvciAob3B0aW9uYWwpOlxuICogICAgICBkZWZhdWx0cyB0byBib3JkZXJDb2xvclxuICogb3B0cyBzaG91bGQgaGF2ZSBrZXlzOlxuICogICAgLSBiZ0NvbG9yOlxuICogICAgICB0aGUgYmFja2dyb3VuZCBjb2xvciB0aGlzIGlzIGFnYWluc3QsIHVzZWQgaWYgdGhlIHRyYWNlIGlzXG4gKiAgICAgIG5vbi1vcGFxdWUsIGFuZCBmb3IgdGhlIG5hbWUsIHdoaWNoIGdvZXMgb3V0c2lkZSB0aGUgYm94XG4gKiAgICAtIGNvbnRhaW5lcjpcbiAqICAgICAgYSA8c3ZnPiBvciA8Zz4gZWxlbWVudCB0byBhZGQgdGhlIGhvdmVyIGxhYmVsIHRvXG4gKiAgICAtIG91dGVyQ29udGFpbmVyOlxuICogICAgICBub3JtYWxseSBhIHBhcmVudCBvZiBgY29udGFpbmVyYCwgc2V0cyB0aGUgYm91bmRpbmcgYm94IHRvIHVzZSB0b1xuICogICAgICBjb25zdHJhaW4gdGhlIGhvdmVyIGxhYmVsIGFuZCBkZXRlcm1pbmUgd2hldGhlciB0byBzaG93IGl0IG9uIHRoZSBsZWZ0IG9yIHJpZ2h0XG4gKi9cbmV4cG9ydHMubG9uZUhvdmVyID0gZnVuY3Rpb24gbG9uZUhvdmVyKGhvdmVySXRlbSwgb3B0cykge1xuICAgIHZhciBwb2ludERhdGEgPSB7XG4gICAgICAgIGNvbG9yOiBob3Zlckl0ZW0uY29sb3IgfHwgQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgIHgwOiBob3Zlckl0ZW0ueDAgfHwgaG92ZXJJdGVtLnggfHwgMCxcbiAgICAgICAgeDE6IGhvdmVySXRlbS54MSB8fCBob3Zlckl0ZW0ueCB8fCAwLFxuICAgICAgICB5MDogaG92ZXJJdGVtLnkwIHx8IGhvdmVySXRlbS55IHx8IDAsXG4gICAgICAgIHkxOiBob3Zlckl0ZW0ueTEgfHwgaG92ZXJJdGVtLnkgfHwgMCxcbiAgICAgICAgeExhYmVsOiBob3Zlckl0ZW0ueExhYmVsLFxuICAgICAgICB5TGFiZWw6IGhvdmVySXRlbS55TGFiZWwsXG4gICAgICAgIHpMYWJlbDogaG92ZXJJdGVtLnpMYWJlbCxcbiAgICAgICAgdGV4dDogaG92ZXJJdGVtLnRleHQsXG4gICAgICAgIG5hbWU6IGhvdmVySXRlbS5uYW1lLFxuICAgICAgICBpZGVhbEFsaWduOiBob3Zlckl0ZW0uaWRlYWxBbGlnbixcblxuICAgICAgICAvLyBvcHRpb25hbCBleHRyYSBiaXRzIG9mIHN0eWxpbmdcbiAgICAgICAgYm9yZGVyQ29sb3I6IGhvdmVySXRlbS5ib3JkZXJDb2xvcixcbiAgICAgICAgZm9udEZhbWlseTogaG92ZXJJdGVtLmZvbnRGYW1pbHksXG4gICAgICAgIGZvbnRTaXplOiBob3Zlckl0ZW0uZm9udFNpemUsXG4gICAgICAgIGZvbnRDb2xvcjogaG92ZXJJdGVtLmZvbnRDb2xvcixcblxuICAgICAgICAvLyBmaWxsZXIgdG8gbWFrZSBjcmVhdGVIb3ZlclRleHQgaGFwcHlcbiAgICAgICAgdHJhY2U6IHtcbiAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgaG92ZXJpbmZvOiAnJ1xuICAgICAgICB9LFxuICAgICAgICB4YToge19vZmZzZXQ6IDB9LFxuICAgICAgICB5YToge19vZmZzZXQ6IDB9LFxuICAgICAgICBpbmRleDogMFxuICAgIH07XG5cbiAgICB2YXIgY29udGFpbmVyMyA9IGQzLnNlbGVjdChvcHRzLmNvbnRhaW5lcik7XG4gICAgdmFyIG91dGVyQ29udGFpbmVyMyA9IG9wdHMub3V0ZXJDb250YWluZXIgP1xuICAgICAgICBkMy5zZWxlY3Qob3B0cy5vdXRlckNvbnRhaW5lcikgOiBjb250YWluZXIzO1xuXG4gICAgdmFyIGZ1bGxPcHRzID0ge1xuICAgICAgICBob3Zlcm1vZGU6ICdjbG9zZXN0JyxcbiAgICAgICAgcm90YXRlTGFiZWxzOiBmYWxzZSxcbiAgICAgICAgYmdDb2xvcjogb3B0cy5iZ0NvbG9yIHx8IENvbG9yLmJhY2tncm91bmQsXG4gICAgICAgIGNvbnRhaW5lcjogY29udGFpbmVyMyxcbiAgICAgICAgb3V0ZXJDb250YWluZXI6IG91dGVyQ29udGFpbmVyM1xuICAgIH07XG5cbiAgICB2YXIgaG92ZXJMYWJlbCA9IGNyZWF0ZUhvdmVyVGV4dChbcG9pbnREYXRhXSwgZnVsbE9wdHMsIG9wdHMuZ2QpO1xuICAgIGFsaWduSG92ZXJUZXh0KGhvdmVyTGFiZWwsIGZ1bGxPcHRzLnJvdGF0ZUxhYmVscyk7XG5cbiAgICByZXR1cm4gaG92ZXJMYWJlbC5ub2RlKCk7XG59O1xuXG5leHBvcnRzLm11bHRpSG92ZXJzID0gZnVuY3Rpb24gbXVsdGlIb3ZlcnMoaG92ZXJJdGVtcywgb3B0cykge1xuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoaG92ZXJJdGVtcykpIHtcbiAgICAgICAgaG92ZXJJdGVtcyA9IFtob3Zlckl0ZW1zXTtcbiAgICB9XG5cbiAgICB2YXIgcG9pbnRzRGF0YSA9IGhvdmVySXRlbXMubWFwKGZ1bmN0aW9uKGhvdmVySXRlbSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29sb3I6IGhvdmVySXRlbS5jb2xvciB8fCBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgIHgwOiBob3Zlckl0ZW0ueDAgfHwgaG92ZXJJdGVtLnggfHwgMCxcbiAgICAgICAgICAgIHgxOiBob3Zlckl0ZW0ueDEgfHwgaG92ZXJJdGVtLnggfHwgMCxcbiAgICAgICAgICAgIHkwOiBob3Zlckl0ZW0ueTAgfHwgaG92ZXJJdGVtLnkgfHwgMCxcbiAgICAgICAgICAgIHkxOiBob3Zlckl0ZW0ueTEgfHwgaG92ZXJJdGVtLnkgfHwgMCxcbiAgICAgICAgICAgIHhMYWJlbDogaG92ZXJJdGVtLnhMYWJlbCxcbiAgICAgICAgICAgIHlMYWJlbDogaG92ZXJJdGVtLnlMYWJlbCxcbiAgICAgICAgICAgIHpMYWJlbDogaG92ZXJJdGVtLnpMYWJlbCxcbiAgICAgICAgICAgIHRleHQ6IGhvdmVySXRlbS50ZXh0LFxuICAgICAgICAgICAgbmFtZTogaG92ZXJJdGVtLm5hbWUsXG4gICAgICAgICAgICBpZGVhbEFsaWduOiBob3Zlckl0ZW0uaWRlYWxBbGlnbixcblxuICAgICAgICAgICAgLy8gb3B0aW9uYWwgZXh0cmEgYml0cyBvZiBzdHlsaW5nXG4gICAgICAgICAgICBib3JkZXJDb2xvcjogaG92ZXJJdGVtLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgZm9udEZhbWlseTogaG92ZXJJdGVtLmZvbnRGYW1pbHksXG4gICAgICAgICAgICBmb250U2l6ZTogaG92ZXJJdGVtLmZvbnRTaXplLFxuICAgICAgICAgICAgZm9udENvbG9yOiBob3Zlckl0ZW0uZm9udENvbG9yLFxuXG4gICAgICAgICAgICAvLyBmaWxsZXIgdG8gbWFrZSBjcmVhdGVIb3ZlclRleHQgaGFwcHlcbiAgICAgICAgICAgIHRyYWNlOiB7XG4gICAgICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICAgICAgaG92ZXJpbmZvOiAnJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHhhOiB7X29mZnNldDogMH0sXG4gICAgICAgICAgICB5YToge19vZmZzZXQ6IDB9LFxuICAgICAgICAgICAgaW5kZXg6IDBcbiAgICAgICAgfTtcbiAgICB9KTtcblxuXG4gICAgdmFyIGNvbnRhaW5lcjMgPSBkMy5zZWxlY3Qob3B0cy5jb250YWluZXIpLFxuICAgICAgICBvdXRlckNvbnRhaW5lcjMgPSBvcHRzLm91dGVyQ29udGFpbmVyID9cbiAgICAgICAgICAgIGQzLnNlbGVjdChvcHRzLm91dGVyQ29udGFpbmVyKSA6IGNvbnRhaW5lcjM7XG5cbiAgICB2YXIgZnVsbE9wdHMgPSB7XG4gICAgICAgIGhvdmVybW9kZTogJ2Nsb3Nlc3QnLFxuICAgICAgICByb3RhdGVMYWJlbHM6IGZhbHNlLFxuICAgICAgICBiZ0NvbG9yOiBvcHRzLmJnQ29sb3IgfHwgQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgY29udGFpbmVyOiBjb250YWluZXIzLFxuICAgICAgICBvdXRlckNvbnRhaW5lcjogb3V0ZXJDb250YWluZXIzXG4gICAgfTtcblxuICAgIHZhciBob3ZlckxhYmVsID0gY3JlYXRlSG92ZXJUZXh0KHBvaW50c0RhdGEsIGZ1bGxPcHRzLCBvcHRzLmdkKTtcblxuICAgIC8vIEZpeCB2ZXJ0aWNhbCBvdmVybGFwXG4gICAgdmFyIHRvb2x0aXBTcGFjaW5nID0gNTtcbiAgICB2YXIgbGFzdEJvdHRvbVkgPSAwO1xuICAgIGhvdmVyTGFiZWxcbiAgICAgICAgLnNvcnQoZnVuY3Rpb24oYSwgYikge3JldHVybiBhLnkwIC0gYi55MDt9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdG9wWSA9IGQueTAgLSBkLmJ5IC8gMjtcblxuICAgICAgICAgICAgaWYoKHRvcFkgLSB0b29sdGlwU3BhY2luZykgPCBsYXN0Qm90dG9tWSkge1xuICAgICAgICAgICAgICAgIGQub2Zmc2V0ID0gKGxhc3RCb3R0b21ZIC0gdG9wWSkgKyB0b29sdGlwU3BhY2luZztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZC5vZmZzZXQgPSAwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsYXN0Qm90dG9tWSA9IHRvcFkgKyBkLmJ5ICsgZC5vZmZzZXQ7XG4gICAgICAgIH0pO1xuXG5cbiAgICBhbGlnbkhvdmVyVGV4dChob3ZlckxhYmVsLCBmdWxsT3B0cy5yb3RhdGVMYWJlbHMpO1xuXG4gICAgcmV0dXJuIGhvdmVyTGFiZWwubm9kZSgpO1xufTtcblxuLy8gVGhlIGFjdHVhbCBpbXBsZW1lbnRhdGlvbiBpcyBoZXJlOlxuZnVuY3Rpb24gX2hvdmVyKGdkLCBldnQsIHN1YnBsb3QsIG5vSG92ZXJFdmVudCkge1xuICAgIGlmKCFzdWJwbG90KSBzdWJwbG90ID0gJ3h5JztcblxuICAgIC8vIGlmIHRoZSB1c2VyIHBhc3NlZCBpbiBhbiBhcnJheSBvZiBzdWJwbG90cyxcbiAgICAvLyB1c2UgdGhvc2UgaW5zdGVhZCBvZiBmaW5kaW5nIG92ZXJsYXllZCBwbG90c1xuICAgIHZhciBzdWJwbG90cyA9IEFycmF5LmlzQXJyYXkoc3VicGxvdCkgPyBzdWJwbG90IDogW3N1YnBsb3RdO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgcGxvdHMgPSBmdWxsTGF5b3V0Ll9wbG90cyB8fCBbXTtcbiAgICB2YXIgcGxvdGluZm8gPSBwbG90c1tzdWJwbG90XTtcbiAgICB2YXIgaGFzQ2FydGVzaWFuID0gZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKTtcblxuICAgIC8vIGxpc3Qgb2YgYWxsIG92ZXJsYWlkIHN1YnBsb3RzIHRvIGxvb2sgYXRcbiAgICBpZihwbG90aW5mbykge1xuICAgICAgICB2YXIgb3ZlcmxheWVkU3VicGxvdHMgPSBwbG90aW5mby5vdmVybGF5cy5tYXAoZnVuY3Rpb24ocGkpIHtcbiAgICAgICAgICAgIHJldHVybiBwaS5pZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3VicGxvdHMgPSBzdWJwbG90cy5jb25jYXQob3ZlcmxheWVkU3VicGxvdHMpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBzdWJwbG90cy5sZW5ndGg7XG4gICAgdmFyIHhhQXJyYXkgPSBuZXcgQXJyYXkobGVuKTtcbiAgICB2YXIgeWFBcnJheSA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBzdXBwb3J0c0NvbXBhcmUgPSBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgc3BJZCA9IHN1YnBsb3RzW2ldO1xuXG4gICAgICAgIC8vICdjYXJ0ZXNpYW4nIGNhc2VcbiAgICAgICAgdmFyIHBsb3RPYmogPSBwbG90c1tzcElkXTtcbiAgICAgICAgaWYocGxvdE9iaikge1xuICAgICAgICAgICAgc3VwcG9ydHNDb21wYXJlID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gVE9ETyBtYWtlIHN1cmUgdGhhdCBmdWxsTGF5b3V0X3Bsb3RzIGF4aXMgcmVmc1xuICAgICAgICAgICAgLy8gZ2V0IHVwZGF0ZWQgcHJvcGVybHkgc28gdGhhdCB3ZSBkb24ndCBoYXZlXG4gICAgICAgICAgICAvLyB0byB1c2UgQXhlcy5nZXRGcm9tSWQgaW4gZ2VuZXJhbC5cblxuICAgICAgICAgICAgeGFBcnJheVtpXSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBwbG90T2JqLnhheGlzLl9pZCk7XG4gICAgICAgICAgICB5YUFycmF5W2ldID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHBsb3RPYmoueWF4aXMuX2lkKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb3RoZXIgc3VicGxvdCB0eXBlc1xuICAgICAgICB2YXIgX3N1YnBsb3QgPSBmdWxsTGF5b3V0W3NwSWRdLl9zdWJwbG90O1xuICAgICAgICB4YUFycmF5W2ldID0gX3N1YnBsb3QueGF4aXM7XG4gICAgICAgIHlhQXJyYXlbaV0gPSBfc3VicGxvdC55YXhpcztcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJtb2RlID0gZXZ0LmhvdmVybW9kZSB8fCBmdWxsTGF5b3V0LmhvdmVybW9kZTtcblxuICAgIGlmKGhvdmVybW9kZSAmJiAhc3VwcG9ydHNDb21wYXJlKSBob3Zlcm1vZGUgPSAnY2xvc2VzdCc7XG5cbiAgICBpZihbJ3gnLCAneScsICdjbG9zZXN0J10uaW5kZXhPZihob3Zlcm1vZGUpID09PSAtMSB8fCAhZ2QuY2FsY2RhdGEgfHxcbiAgICAgICAgICAgIGdkLnF1ZXJ5U2VsZWN0b3IoJy56b29tYm94JykgfHwgZ2QuX2RyYWdnaW5nKSB7XG4gICAgICAgIHJldHVybiBkcmFnRWxlbWVudC51bmhvdmVyUmF3KGdkLCBldnQpO1xuICAgIH1cblxuICAgIHZhciBob3ZlcmRpc3RhbmNlID0gZnVsbExheW91dC5ob3ZlcmRpc3RhbmNlID09PSAtMSA/IEluZmluaXR5IDogZnVsbExheW91dC5ob3ZlcmRpc3RhbmNlO1xuICAgIHZhciBzcGlrZWRpc3RhbmNlID0gZnVsbExheW91dC5zcGlrZWRpc3RhbmNlID09PSAtMSA/IEluZmluaXR5IDogZnVsbExheW91dC5zcGlrZWRpc3RhbmNlO1xuXG4gICAgLy8gaG92ZXJEYXRhOiB0aGUgc2V0IG9mIGNhbmRpZGF0ZSBwb2ludHMgd2UndmUgZm91bmQgdG8gaGlnaGxpZ2h0XG4gICAgdmFyIGhvdmVyRGF0YSA9IFtdO1xuXG4gICAgLy8gc2VhcmNoRGF0YTogdGhlIGRhdGEgdG8gc2VhcmNoIGluLiBNb3N0bHkgdGhpcyBpcyBqdXN0IGEgY29weSBvZlxuICAgIC8vIGdkLmNhbGNkYXRhLCBmaWx0ZXJlZCB0byB0aGUgc3VicGxvdCBhbmQgb3ZlcmxheXMgd2UncmUgb25cbiAgICAvLyBidXQgaWYgYSBwb2ludCBhcnJheSBpcyBzdXBwbGllZCBpdCB3aWxsIGJlIGEgbWFwcGluZ1xuICAgIC8vIG9mIGluZGljYXRlZCBjdXJ2ZXNcbiAgICB2YXIgc2VhcmNoRGF0YSA9IFtdO1xuXG4gICAgLy8gW3h8eV12YWxBcnJheTogdGhlIGF4aXMgdmFsdWVzIG9mIHRoZSBob3ZlciBldmVudFxuICAgIC8vIG1hcHBlZCBvbnRvIGVhY2ggb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvdmVybGFpZCBzdWJwbG90c1xuICAgIHZhciB4dmFsQXJyYXksIHl2YWxBcnJheTtcblxuICAgIHZhciBpdGVtbnVtLCBjdXJ2ZW51bSwgY2QsIHRyYWNlLCBzdWJwbG90SWQsIHN1YnBsb3RpLCBtb2RlLFxuICAgICAgICB4dmFsLCB5dmFsLCBwb2ludERhdGEsIGNsb3NlZGF0YVByZXZpb3VzTGVuZ3RoO1xuXG4gICAgLy8gc3Bpa2VQb2ludHM6IHRoZSBzZXQgb2YgY2FuZGlkYXRlIHBvaW50cyB3ZSd2ZSBmb3VuZCB0byBkcmF3IHNwaWtlcyB0b1xuICAgIHZhciBzcGlrZVBvaW50cyA9IHtcbiAgICAgICAgaExpbmVQb2ludDogbnVsbCxcbiAgICAgICAgdkxpbmVQb2ludDogbnVsbFxuICAgIH07XG5cbiAgICAvLyBkb2VzIHN1YnBsb3QgaGF2ZSBvbmUgKG9yIG1vcmUpIGhvcml6b250YWwgdHJhY2VzP1xuICAgIC8vIFRoaXMgaXMgdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciB3ZSByb3RhdGUgdGhlIGxhYmVscyBvciBub3RcbiAgICB2YXIgaGFzT25lSG9yaXpvbnRhbFRyYWNlID0gZmFsc2U7XG5cbiAgICAvLyBGaWd1cmUgb3V0IHdoYXQgd2UncmUgaG92ZXJpbmcgb246XG4gICAgLy8gbW91c2UgbG9jYXRpb24gb3IgdXNlci1zdXBwbGllZCBkYXRhXG5cbiAgICBpZihBcnJheS5pc0FycmF5KGV2dCkpIHtcbiAgICAgICAgLy8gdXNlciBzcGVjaWZpZWQgYW4gYXJyYXkgb2YgcG9pbnRzIHRvIGhpZ2hsaWdodFxuICAgICAgICBob3Zlcm1vZGUgPSAnYXJyYXknO1xuICAgICAgICBmb3IoaXRlbW51bSA9IDA7IGl0ZW1udW0gPCBldnQubGVuZ3RoOyBpdGVtbnVtKyspIHtcbiAgICAgICAgICAgIGNkID0gZ2QuY2FsY2RhdGFbZXZ0W2l0ZW1udW1dLmN1cnZlTnVtYmVyfHwwXTtcbiAgICAgICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgICAgICBpZihjZFswXS50cmFjZS5ob3ZlcmluZm8gIT09ICdza2lwJykge1xuICAgICAgICAgICAgICAgIHNlYXJjaERhdGEucHVzaChjZCk7XG4gICAgICAgICAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgICAgICAgICBoYXNPbmVIb3Jpem9udGFsVHJhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZm9yKGN1cnZlbnVtID0gMDsgY3VydmVudW0gPCBnZC5jYWxjZGF0YS5sZW5ndGg7IGN1cnZlbnVtKyspIHtcbiAgICAgICAgICAgIGNkID0gZ2QuY2FsY2RhdGFbY3VydmVudW1dO1xuICAgICAgICAgICAgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLmhvdmVyaW5mbyAhPT0gJ3NraXAnICYmIGhlbHBlcnMuaXNUcmFjZUluU3VicGxvdHModHJhY2UsIHN1YnBsb3RzKSkge1xuICAgICAgICAgICAgICAgIHNlYXJjaERhdGEucHVzaChjZCk7XG4gICAgICAgICAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgICAgICAgICBoYXNPbmVIb3Jpem9udGFsVHJhY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFt4fHldcHg6IHRoZSBwaXhlbHMgKGZyb20gdG9wIGxlZnQpIG9mIHRoZSBtb3VzZSBsb2NhdGlvblxuICAgICAgICAvLyBvbiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsb3QgYXJlYVxuICAgICAgICAvLyBhZGQgcG9pbnRlclh8WSBwcm9wZXJ0eSBmb3IgZHJhd2luZyB0aGUgc3Bpa2VzIGluIHNwaWtlc25hcCAnY3Vyc29yJyBzaXR1YXRpb25cbiAgICAgICAgdmFyIGhhc1VzZXJDYWxsZWRIb3ZlciA9ICFldnQudGFyZ2V0O1xuICAgICAgICB2YXIgeHB4LCB5cHg7XG5cbiAgICAgICAgaWYoaGFzVXNlckNhbGxlZEhvdmVyKSB7XG4gICAgICAgICAgICBpZigneHB4JyBpbiBldnQpIHhweCA9IGV2dC54cHg7XG4gICAgICAgICAgICBlbHNlIHhweCA9IHhhQXJyYXlbMF0uX2xlbmd0aCAvIDI7XG5cbiAgICAgICAgICAgIGlmKCd5cHgnIGluIGV2dCkgeXB4ID0gZXZ0LnlweDtcbiAgICAgICAgICAgIGVsc2UgeXB4ID0geWFBcnJheVswXS5fbGVuZ3RoIC8gMjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZpcmUgdGhlIGJlZm9yZWhvdmVyIGV2ZW50IGFuZCBxdWl0IGlmIGl0IHJldHVybnMgZmFsc2VcbiAgICAgICAgICAgIC8vIG5vdGUgdGhhdCB3ZSdyZSBvbmx5IGNhbGxpbmcgdGhpcyBvbiByZWFsIG1vdXNlIGV2ZW50cywgc29cbiAgICAgICAgICAgIC8vIG1hbnVhbCBjYWxscyB0byBmeC5ob3ZlciB3aWxsIGFsd2F5cyBydW4uXG4gICAgICAgICAgICBpZihFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfYmVmb3JlaG92ZXInLCBldnQpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGRiYiA9IGV2dC50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICAgIHhweCA9IGV2dC5jbGllbnRYIC0gZGJiLmxlZnQ7XG4gICAgICAgICAgICB5cHggPSBldnQuY2xpZW50WSAtIGRiYi50b3A7XG5cbiAgICAgICAgICAgIC8vIGluIGNhc2UgaG92ZXIgd2FzIGNhbGxlZCBmcm9tIG1vdXNlb3V0IGludG8gaG92ZXJ0ZXh0LFxuICAgICAgICAgICAgLy8gaXQncyBwb3NzaWJsZSB5b3UncmUgbm90IGFjdHVhbGx5IG92ZXIgdGhlIHBsb3QgYW55bW9yZVxuICAgICAgICAgICAgaWYoeHB4IDwgMCB8fCB4cHggPiB4YUFycmF5WzBdLl9sZW5ndGggfHwgeXB4IDwgMCB8fCB5cHggPiB5YUFycmF5WzBdLl9sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyhnZCwgZXZ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGV2dC5wb2ludGVyWCA9IHhweCArIHhhQXJyYXlbMF0uX29mZnNldDtcbiAgICAgICAgZXZ0LnBvaW50ZXJZID0geXB4ICsgeWFBcnJheVswXS5fb2Zmc2V0O1xuXG4gICAgICAgIGlmKCd4dmFsJyBpbiBldnQpIHh2YWxBcnJheSA9IGhlbHBlcnMuZmxhdChzdWJwbG90cywgZXZ0Lnh2YWwpO1xuICAgICAgICBlbHNlIHh2YWxBcnJheSA9IGhlbHBlcnMucDJjKHhhQXJyYXksIHhweCk7XG5cbiAgICAgICAgaWYoJ3l2YWwnIGluIGV2dCkgeXZhbEFycmF5ID0gaGVscGVycy5mbGF0KHN1YnBsb3RzLCBldnQueXZhbCk7XG4gICAgICAgIGVsc2UgeXZhbEFycmF5ID0gaGVscGVycy5wMmMoeWFBcnJheSwgeXB4KTtcblxuICAgICAgICBpZighaXNOdW1lcmljKHh2YWxBcnJheVswXSkgfHwgIWlzTnVtZXJpYyh5dmFsQXJyYXlbMF0pKSB7XG4gICAgICAgICAgICBMaWIud2FybignRnguaG92ZXIgZmFpbGVkJywgZXZ0LCBnZCk7XG4gICAgICAgICAgICByZXR1cm4gZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyhnZCwgZXZ0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRoZSBwaXhlbCBkaXN0YW5jZSB0byBiZWF0IGFzIGEgbWF0Y2hpbmcgcG9pbnRcbiAgICAvLyBpbiAneCcgb3IgJ3knIG1vZGUgdGhpcyByZXNldHMgZm9yIGVhY2ggdHJhY2VcbiAgICB2YXIgZGlzdGFuY2UgPSBJbmZpbml0eTtcblxuICAgIC8vIGZpbmQgdGhlIGNsb3Nlc3QgcG9pbnQgaW4gZWFjaCB0cmFjZVxuICAgIC8vIHRoaXMgaXMgbWluaW11bSBkeCBhbmQvb3IgZHksIGRlcGVuZGluZyBvbiBtb2RlXG4gICAgLy8gYW5kIHRoZSBwaXhlbCBwb3NpdGlvbiBmb3IgdGhlIGxhYmVsIChsYWJlbFhweCwgbGFiZWxZcHgpXG4gICAgZm9yKGN1cnZlbnVtID0gMDsgY3VydmVudW0gPCBzZWFyY2hEYXRhLmxlbmd0aDsgY3VydmVudW0rKykge1xuICAgICAgICBjZCA9IHNlYXJjaERhdGFbY3VydmVudW1dO1xuXG4gICAgICAgIC8vIGZpbHRlciBvdXQgaW52aXNpYmxlIG9yIGJyb2tlbiBkYXRhXG4gICAgICAgIGlmKCFjZCB8fCAhY2RbMF0gfHwgIWNkWzBdLnRyYWNlIHx8IGNkWzBdLnRyYWNlLnZpc2libGUgIT09IHRydWUpIGNvbnRpbnVlO1xuXG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgLy8gRXhwbGljaXRseSBiYWlsIG91dCBmb3IgdGhlc2UgdHdvLiBJIGRvbid0IGtub3cgaG93IHRvIG90aGVyd2lzZSBwcmV2ZW50XG4gICAgICAgIC8vIHRoZSByZXN0IG9mIHRoaXMgZnVuY3Rpb24gZnJvbSBydW5uaW5nIGFuZCBmYWlsaW5nXG4gICAgICAgIGlmKFsnY2FycGV0JywgJ2NvbnRvdXJjYXJwZXQnXS5pbmRleE9mKHRyYWNlLl9tb2R1bGUubmFtZSkgIT09IC0xKSBjb250aW51ZTtcblxuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnc3Bsb20nKSB7XG4gICAgICAgICAgICAvLyBzcGxvbSB0cmFjZXMgZG8gbm90IGdlbmVyYXRlIG92ZXJsYXkgc3VicGxvdHMsXG4gICAgICAgICAgICAvLyBpdCBpcyBzYWZlIHRvIGFzc3VtZSBoZXJlIHNwbG9tIHRyYWNlcyBjb3JyZXNwb25kIHRvIHRoZSAwdGggc3VicGxvdFxuICAgICAgICAgICAgc3VicGxvdGkgPSAwO1xuICAgICAgICAgICAgc3VicGxvdElkID0gc3VicGxvdHNbc3VicGxvdGldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3VicGxvdElkID0gaGVscGVycy5nZXRTdWJwbG90KHRyYWNlKTtcbiAgICAgICAgICAgIHN1YnBsb3RpID0gc3VicGxvdHMuaW5kZXhPZihzdWJwbG90SWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2l0aGluIG9uZSB0cmFjZSBtb2RlIGNhbiBzb21ldGltZXMgYmUgb3ZlcnJpZGRlblxuICAgICAgICBtb2RlID0gaG92ZXJtb2RlO1xuXG4gICAgICAgIC8vIGNvbnRhaW5lciBmb3IgbmV3IHBvaW50LCBhbHNvIHVzZWQgdG8gcGFzcyBpbmZvIGludG8gbW9kdWxlLmhvdmVyUG9pbnRzXG4gICAgICAgIHBvaW50RGF0YSA9IHtcbiAgICAgICAgICAgIC8vIHRyYWNlIHByb3BlcnRpZXNcbiAgICAgICAgICAgIGNkOiBjZCxcbiAgICAgICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgICAgIHhhOiB4YUFycmF5W3N1YnBsb3RpXSxcbiAgICAgICAgICAgIHlhOiB5YUFycmF5W3N1YnBsb3RpXSxcblxuICAgICAgICAgICAgLy8gbWF4IGRpc3RhbmNlcyBmb3IgaG92ZXIgYW5kIHNwaWtlcyAtIGZvciBwb2ludHMgdGhhdCB3YW50IHRvIHNob3cgYnV0IGRvIG5vdFxuICAgICAgICAgICAgLy8gd2FudCB0byBvdmVycmlkZSBvdGhlciBwb2ludHMsIHNldCBkaXN0YW5jZS9zcGlrZURpc3RhbmNlIGVxdWFsIHRvIG1heCpEaXN0YW5jZVxuICAgICAgICAgICAgLy8gYW5kIGl0IHdpbGwgbm90IGdldCBmaWx0ZXJlZCBvdXQgYnV0IGl0IHdpbGwgYmUgZ3VhcmFudGVlZCB0byBoYXZlIGEgZ3JlYXRlclxuICAgICAgICAgICAgLy8gZGlzdGFuY2UgdGhhbiBhbnkgcG9pbnQgdGhhdCBjYWxjdWxhdGVkIGEgcmVhbCBkaXN0YW5jZS5cbiAgICAgICAgICAgIG1heEhvdmVyRGlzdGFuY2U6IGhvdmVyZGlzdGFuY2UsXG4gICAgICAgICAgICBtYXhTcGlrZURpc3RhbmNlOiBzcGlrZWRpc3RhbmNlLFxuXG4gICAgICAgICAgICAvLyBwb2ludCBwcm9wZXJ0aWVzIC0gb3ZlcnJpZGUgYWxsIG9mIHRoZXNlXG4gICAgICAgICAgICBpbmRleDogZmFsc2UsIC8vIHBvaW50IGluZGV4IGluIHRyYWNlIC0gb25seSB1c2VkIGJ5IHBsb3RseS5qcyBob3ZlcmRhdGEgY29uc3VtZXJzXG4gICAgICAgICAgICBkaXN0YW5jZTogTWF0aC5taW4oZGlzdGFuY2UsIGhvdmVyZGlzdGFuY2UpLCAvLyBwaXhlbCBkaXN0YW5jZSBvciBwc2V1ZG8tZGlzdGFuY2VcblxuICAgICAgICAgICAgLy8gZGlzdGFuY2UvcHNldWRvLWRpc3RhbmNlIGZvciBzcGlrZXMuIFRoaXMgZGlzdGFuY2Ugc2hvdWxkIGFsd2F5cyBiZSBjYWxjdWxhdGVkXG4gICAgICAgICAgICAvLyBhcyBpZiBpbiBcImNsb3Nlc3RcIiBtb2RlLCBhbmQgc2hvdWxkIG9ubHkgYmUgc2V0IGlmIHRoaXMgcG9pbnQgc2hvdWxkXG4gICAgICAgICAgICAvLyBnZW5lcmF0ZSBhIHNwaWtlLlxuICAgICAgICAgICAgc3Bpa2VEaXN0YW5jZTogSW5maW5pdHksXG5cbiAgICAgICAgICAgIC8vIGluIHNvbWUgY2FzZXMgdGhlIHNwaWtlcyBoYXZlIGRpZmZlcmVudCBwb3NpdGlvbmluZyBmcm9tIHRoZSBob3ZlciBsYWJlbFxuICAgICAgICAgICAgLy8gdGhleSBkb24ndCBuZWVkIHgwL3gxLCBqdXN0IG9uZSBwb3NpdGlvblxuICAgICAgICAgICAgeFNwaWtlOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB5U3Bpa2U6IHVuZGVmaW5lZCxcblxuICAgICAgICAgICAgLy8gd2hlcmUgYW5kIGhvdyB0byBkaXNwbGF5IHRoZSBob3ZlciBsYWJlbFxuICAgICAgICAgICAgY29sb3I6IENvbG9yLmRlZmF1bHRMaW5lLCAvLyB0cmFjZSBjb2xvclxuICAgICAgICAgICAgbmFtZTogdHJhY2UubmFtZSxcbiAgICAgICAgICAgIHgwOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB4MTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgeTA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHkxOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB4TGFiZWxWYWw6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHlMYWJlbFZhbDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgekxhYmVsVmFsOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB0ZXh0OiB1bmRlZmluZWRcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBhZGQgcmVmIHRvIHN1YnBsb3Qgb2JqZWN0IChub24tY2FydGVzaWFuIGNhc2UpXG4gICAgICAgIGlmKGZ1bGxMYXlvdXRbc3VicGxvdElkXSkge1xuICAgICAgICAgICAgcG9pbnREYXRhLnN1YnBsb3QgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZF0uX3N1YnBsb3Q7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWRkIHJlZiB0byBzcGxvbSBzY2VuZVxuICAgICAgICBpZihmdWxsTGF5b3V0Ll9zcGxvbVNjZW5lcyAmJiBmdWxsTGF5b3V0Ll9zcGxvbVNjZW5lc1t0cmFjZS51aWRdKSB7XG4gICAgICAgICAgICBwb2ludERhdGEuc2NlbmUgPSBmdWxsTGF5b3V0Ll9zcGxvbVNjZW5lc1t0cmFjZS51aWRdO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvc2VkYXRhUHJldmlvdXNMZW5ndGggPSBob3ZlckRhdGEubGVuZ3RoO1xuXG4gICAgICAgIC8vIGZvciBhIGhpZ2hsaWdodGluZyBhcnJheSwgZmlndXJlIG91dCB3aGF0XG4gICAgICAgIC8vIHdlJ3JlIHNlYXJjaGluZyBmb3Igd2l0aCB0aGlzIGVsZW1lbnRcbiAgICAgICAgaWYobW9kZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IGV2dFtjdXJ2ZW51bV07XG4gICAgICAgICAgICBpZigncG9pbnROdW1iZXInIGluIHNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIHBvaW50RGF0YS5pbmRleCA9IHNlbGVjdGlvbi5wb2ludE51bWJlcjtcbiAgICAgICAgICAgICAgICBtb2RlID0gJ2Nsb3Nlc3QnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZSA9ICcnO1xuICAgICAgICAgICAgICAgIGlmKCd4dmFsJyBpbiBzZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgeHZhbCA9IHNlbGVjdGlvbi54dmFsO1xuICAgICAgICAgICAgICAgICAgICBtb2RlID0gJ3gnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZigneXZhbCcgaW4gc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHl2YWwgPSBzZWxlY3Rpb24ueXZhbDtcbiAgICAgICAgICAgICAgICAgICAgbW9kZSA9IG1vZGUgPyAnY2xvc2VzdCcgOiAneSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgeHZhbCA9IHh2YWxBcnJheVtzdWJwbG90aV07XG4gICAgICAgICAgICB5dmFsID0geXZhbEFycmF5W3N1YnBsb3RpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdyBpZiB0aGVyZSBpcyByYW5nZSB0byBsb29rIGluLCBmaW5kIHRoZSBwb2ludHMgdG8gaG92ZXIuXG4gICAgICAgIGlmKGhvdmVyZGlzdGFuY2UgIT09IDApIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLl9tb2R1bGUgJiYgdHJhY2UuX21vZHVsZS5ob3ZlclBvaW50cykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdQb2ludHMgPSB0cmFjZS5fbW9kdWxlLmhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgbW9kZSwgZnVsbExheW91dC5faG92ZXJsYXllcik7XG4gICAgICAgICAgICAgICAgaWYobmV3UG9pbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBuZXdQb2ludE51bSA9IDA7IG5ld1BvaW50TnVtIDwgbmV3UG9pbnRzLmxlbmd0aDsgbmV3UG9pbnROdW0rKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3UG9pbnQgPSBuZXdQb2ludHNbbmV3UG9pbnROdW1dO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKG5ld1BvaW50LngwKSAmJiBpc051bWVyaWMobmV3UG9pbnQueTApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG92ZXJEYXRhLnB1c2goY2xlYW5Qb2ludChuZXdQb2ludCwgaG92ZXJtb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBMaWIubG9nKCdVbnJlY29nbml6ZWQgdHJhY2UgdHlwZSBpbiBob3ZlcjonLCB0cmFjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbiBjbG9zZXN0IG1vZGUsIHJlbW92ZSBhbnkgZXhpc3RpbmcgKGZhcnRoZXIpIHBvaW50c1xuICAgICAgICAvLyBhbmQgZG9uJ3QgbG9vayBhbnkgZmFydGhlciB0aGFuIHRoaXMgbGF0ZXN0IHBvaW50IChvciBwb2ludHMsIHNvbWVcbiAgICAgICAgLy8gdHJhY2VzIGxpa2UgYm94ICYgdmlvbGluIG1ha2UgbXVsdGlwbGUgaG92ZXIgbGFiZWxzIGF0IG9uY2UpXG4gICAgICAgIGlmKGhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnICYmIGhvdmVyRGF0YS5sZW5ndGggPiBjbG9zZWRhdGFQcmV2aW91c0xlbmd0aCkge1xuICAgICAgICAgICAgaG92ZXJEYXRhLnNwbGljZSgwLCBjbG9zZWRhdGFQcmV2aW91c0xlbmd0aCk7XG4gICAgICAgICAgICBkaXN0YW5jZSA9IGhvdmVyRGF0YVswXS5kaXN0YW5jZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdyBpZiB0aGVyZSBpcyByYW5nZSB0byBsb29rIGluLCBmaW5kIHRoZSBwb2ludHMgdG8gZHJhdyB0aGUgc3Bpa2VsaW5lc1xuICAgICAgICAvLyBEbyBpdCBvbmx5IGlmIHRoZXJlIGlzIG5vIGhvdmVyRGF0YVxuICAgICAgICBpZihoYXNDYXJ0ZXNpYW4gJiYgKHNwaWtlZGlzdGFuY2UgIT09IDApKSB7XG4gICAgICAgICAgICBpZihob3ZlckRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLmRpc3RhbmNlID0gc3Bpa2VkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICBwb2ludERhdGEuaW5kZXggPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgY2xvc2VzdFBvaW50cyA9IHRyYWNlLl9tb2R1bGUuaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCAnY2xvc2VzdCcsIGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIpO1xuICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RQb2ludHMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xvc2VzdFBvaW50cyA9IGNsb3Nlc3RQb2ludHMuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzb21lIGhvdmVyIHBvaW50cywgbGlrZSBzY2F0dGVyIGZpbGxzLCBkbyBub3QgYWxsb3cgc3Bpa2VzLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gd2lsbCBnZW5lcmF0ZSBhIGhvdmVyIHBvaW50IGJ1dCB3aXRob3V0IGEgdmFsaWQgc3Bpa2VEaXN0YW5jZVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnNwaWtlRGlzdGFuY2UgPD0gc3Bpa2VkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RQb2ludHMgJiYgY2xvc2VzdFBvaW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRtcFBvaW50O1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2xvc2VzdFZQb2ludHMgPSBjbG9zZXN0UG9pbnRzLmZpbHRlcihmdW5jdGlvbihwb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnhhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZihjbG9zZXN0VlBvaW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjbG9zZXN0VlB0ID0gY2xvc2VzdFZQb2ludHNbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpc051bWVyaWMoY2xvc2VzdFZQdC54MCkgJiYgaXNOdW1lcmljKGNsb3Nlc3RWUHQueTApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wUG9pbnQgPSBmaWxsU3Bpa2VQb2ludChjbG9zZXN0VlB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighc3Bpa2VQb2ludHMudkxpbmVQb2ludCB8fCAoc3Bpa2VQb2ludHMudkxpbmVQb2ludC5zcGlrZURpc3RhbmNlID4gdG1wUG9pbnQuc3Bpa2VEaXN0YW5jZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Bpa2VQb2ludHMudkxpbmVQb2ludCA9IHRtcFBvaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9zZXN0SFBvaW50cyA9IGNsb3Nlc3RQb2ludHMuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9pbnQueWEuc2hvd3NwaWtlcztcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RIUG9pbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNsb3Nlc3RIUHQgPSBjbG9zZXN0SFBvaW50c1swXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhjbG9zZXN0SFB0LngwKSAmJiBpc051bWVyaWMoY2xvc2VzdEhQdC55MCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBQb2ludCA9IGZpbGxTcGlrZVBvaW50KGNsb3Nlc3RIUHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFzcGlrZVBvaW50cy5oTGluZVBvaW50IHx8IChzcGlrZVBvaW50cy5oTGluZVBvaW50LnNwaWtlRGlzdGFuY2UgPiB0bXBQb2ludC5zcGlrZURpc3RhbmNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGlrZVBvaW50cy5oTGluZVBvaW50ID0gdG1wUG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VsZWN0Q2xvc2VzdFBvaW50KHBvaW50c0RhdGEsIHNwaWtlZGlzdGFuY2UpIHtcbiAgICAgICAgdmFyIHJlc3VsdFBvaW50ID0gbnVsbDtcbiAgICAgICAgdmFyIG1pbkRpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgICAgIHZhciB0aGlzU3Bpa2VEaXN0YW5jZTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHBvaW50c0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXNTcGlrZURpc3RhbmNlID0gcG9pbnRzRGF0YVtpXS5zcGlrZURpc3RhbmNlO1xuICAgICAgICAgICAgaWYodGhpc1NwaWtlRGlzdGFuY2UgPCBtaW5EaXN0YW5jZSAmJiB0aGlzU3Bpa2VEaXN0YW5jZSA8PSBzcGlrZWRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0UG9pbnQgPSBwb2ludHNEYXRhW2ldO1xuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gdGhpc1NwaWtlRGlzdGFuY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdFBvaW50O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbGxTcGlrZVBvaW50KHBvaW50KSB7XG4gICAgICAgIGlmKCFwb2ludCkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4YTogcG9pbnQueGEsXG4gICAgICAgICAgICB5YTogcG9pbnQueWEsXG4gICAgICAgICAgICB4OiBwb2ludC54U3Bpa2UgIT09IHVuZGVmaW5lZCA/IHBvaW50LnhTcGlrZSA6IChwb2ludC54MCArIHBvaW50LngxKSAvIDIsXG4gICAgICAgICAgICB5OiBwb2ludC55U3Bpa2UgIT09IHVuZGVmaW5lZCA/IHBvaW50LnlTcGlrZSA6IChwb2ludC55MCArIHBvaW50LnkxKSAvIDIsXG4gICAgICAgICAgICBkaXN0YW5jZTogcG9pbnQuZGlzdGFuY2UsXG4gICAgICAgICAgICBzcGlrZURpc3RhbmNlOiBwb2ludC5zcGlrZURpc3RhbmNlLFxuICAgICAgICAgICAgY3VydmVOdW1iZXI6IHBvaW50LnRyYWNlLmluZGV4LFxuICAgICAgICAgICAgY29sb3I6IHBvaW50LmNvbG9yLFxuICAgICAgICAgICAgcG9pbnROdW1iZXI6IHBvaW50LmluZGV4XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHNwaWtlbGluZU9wdHMgPSB7XG4gICAgICAgIGZ1bGxMYXlvdXQ6IGZ1bGxMYXlvdXQsXG4gICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllcixcbiAgICAgICAgb3V0ZXJDb250YWluZXI6IGZ1bGxMYXlvdXQuX3BhcGVyZGl2LFxuICAgICAgICBldmVudDogZXZ0XG4gICAgfTtcbiAgICB2YXIgb2xkc3Bpa2Vwb2ludHMgPSBnZC5fc3Bpa2Vwb2ludHMsXG4gICAgICAgIG5ld3NwaWtlcG9pbnRzID0ge1xuICAgICAgICAgICAgdkxpbmVQb2ludDogc3Bpa2VQb2ludHMudkxpbmVQb2ludCxcbiAgICAgICAgICAgIGhMaW5lUG9pbnQ6IHNwaWtlUG9pbnRzLmhMaW5lUG9pbnRcbiAgICAgICAgfTtcbiAgICBnZC5fc3Bpa2Vwb2ludHMgPSBuZXdzcGlrZXBvaW50cztcblxuICAgIC8vIE5vdyBpZiBpdCBpcyBub3QgcmVzdHJpY3RlZCBieSBzcGlrZWRpc3RhbmNlIG9wdGlvbiwgc2V0IHRoZSBwb2ludHMgdG8gZHJhdyB0aGUgc3Bpa2VsaW5lc1xuICAgIGlmKGhhc0NhcnRlc2lhbiAmJiAoc3Bpa2VkaXN0YW5jZSAhPT0gMCkpIHtcbiAgICAgICAgaWYoaG92ZXJEYXRhLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgdmFyIHRtcEhQb2ludERhdGEgPSBob3ZlckRhdGEuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnlhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciB0bXBIUG9pbnQgPSBzZWxlY3RDbG9zZXN0UG9pbnQodG1wSFBvaW50RGF0YSwgc3Bpa2VkaXN0YW5jZSk7XG4gICAgICAgICAgICBzcGlrZVBvaW50cy5oTGluZVBvaW50ID0gZmlsbFNwaWtlUG9pbnQodG1wSFBvaW50KTtcblxuICAgICAgICAgICAgdmFyIHRtcFZQb2ludERhdGEgPSBob3ZlckRhdGEuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnhhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciB0bXBWUG9pbnQgPSBzZWxlY3RDbG9zZXN0UG9pbnQodG1wVlBvaW50RGF0YSwgc3Bpa2VkaXN0YW5jZSk7XG4gICAgICAgICAgICBzcGlrZVBvaW50cy52TGluZVBvaW50ID0gZmlsbFNwaWtlUG9pbnQodG1wVlBvaW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIGhvdmVyRGF0YSBpcyBlbXB0eSBjaGVjayBmb3IgdGhlIHNwaWtlcyB0byBkcmF3IGFuZCBxdWl0IGlmIHRoZXJlIGFyZSBub25lXG4gICAgaWYoaG92ZXJEYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyhnZCwgZXZ0KTtcbiAgICAgICAgaWYoaGFzQ2FydGVzaWFuICYmICgoc3Bpa2VQb2ludHMuaExpbmVQb2ludCAhPT0gbnVsbCkgfHwgKHNwaWtlUG9pbnRzLnZMaW5lUG9pbnQgIT09IG51bGwpKSkge1xuICAgICAgICAgICAgaWYoc3Bpa2VzQ2hhbmdlZChvbGRzcGlrZXBvaW50cykpIHtcbiAgICAgICAgICAgICAgICBjcmVhdGVTcGlrZWxpbmVzKHNwaWtlUG9pbnRzLCBzcGlrZWxpbmVPcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmKGhhc0NhcnRlc2lhbikge1xuICAgICAgICBpZihzcGlrZXNDaGFuZ2VkKG9sZHNwaWtlcG9pbnRzKSkge1xuICAgICAgICAgICAgY3JlYXRlU3Bpa2VsaW5lcyhzcGlrZVBvaW50cywgc3Bpa2VsaW5lT3B0cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob3ZlckRhdGEuc29ydChmdW5jdGlvbihkMSwgZDIpIHsgcmV0dXJuIGQxLmRpc3RhbmNlIC0gZDIuZGlzdGFuY2U7IH0pO1xuXG4gICAgLy8gbGFzdGx5LCBlbWl0IGN1c3RvbSBob3Zlci91bmhvdmVyIGV2ZW50c1xuICAgIHZhciBvbGRob3ZlcmRhdGEgPSBnZC5faG92ZXJkYXRhO1xuICAgIHZhciBuZXdob3ZlcmRhdGEgPSBbXTtcblxuICAgIC8vIHB1bGwgb3V0IGp1c3QgdGhlIGRhdGEgdGhhdCdzIHVzZWZ1bCB0b1xuICAgIC8vIG90aGVyIHBlb3BsZSBhbmQgc2VuZCBpdCB0byB0aGUgZXZlbnRcbiAgICBmb3IoaXRlbW51bSA9IDA7IGl0ZW1udW0gPCBob3ZlckRhdGEubGVuZ3RoOyBpdGVtbnVtKyspIHtcbiAgICAgICAgdmFyIHB0ID0gaG92ZXJEYXRhW2l0ZW1udW1dO1xuICAgICAgICBuZXdob3ZlcmRhdGEucHVzaChoZWxwZXJzLm1ha2VFdmVudERhdGEocHQsIHB0LnRyYWNlLCBwdC5jZCkpO1xuICAgIH1cblxuICAgIGdkLl9ob3ZlcmRhdGEgPSBuZXdob3ZlcmRhdGE7XG5cbiAgICB2YXIgcm90YXRlTGFiZWxzID0gKFxuICAgICAgICAoaG92ZXJtb2RlID09PSAneScgJiYgKHNlYXJjaERhdGEubGVuZ3RoID4gMSB8fCBob3ZlckRhdGEubGVuZ3RoID4gMSkpIHx8XG4gICAgICAgIChob3Zlcm1vZGUgPT09ICdjbG9zZXN0JyAmJiBoYXNPbmVIb3Jpem9udGFsVHJhY2UgJiYgaG92ZXJEYXRhLmxlbmd0aCA+IDEpXG4gICAgKTtcblxuICAgIHZhciBiZ0NvbG9yID0gQ29sb3IuY29tYmluZShcbiAgICAgICAgZnVsbExheW91dC5wbG90X2JnY29sb3IgfHwgQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yXG4gICAgKTtcblxuICAgIHZhciBsYWJlbE9wdHMgPSB7XG4gICAgICAgIGhvdmVybW9kZTogaG92ZXJtb2RlLFxuICAgICAgICByb3RhdGVMYWJlbHM6IHJvdGF0ZUxhYmVscyxcbiAgICAgICAgYmdDb2xvcjogYmdDb2xvcixcbiAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLFxuICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXJkaXYsXG4gICAgICAgIGNvbW1vbkxhYmVsT3B0czogZnVsbExheW91dC5ob3ZlcmxhYmVsLFxuICAgICAgICBob3ZlcmRpc3RhbmNlOiBmdWxsTGF5b3V0LmhvdmVyZGlzdGFuY2VcbiAgICB9O1xuXG4gICAgdmFyIGhvdmVyTGFiZWxzID0gY3JlYXRlSG92ZXJUZXh0KGhvdmVyRGF0YSwgbGFiZWxPcHRzLCBnZCk7XG5cbiAgICBob3ZlckF2b2lkT3ZlcmxhcHMoaG92ZXJEYXRhLCByb3RhdGVMYWJlbHMgPyAneGEnIDogJ3lhJywgZnVsbExheW91dCk7XG5cbiAgICBhbGlnbkhvdmVyVGV4dChob3ZlckxhYmVscywgcm90YXRlTGFiZWxzKTtcblxuICAgIC8vIFRPRE86IHRhZ05hbWUgaGFjayBpcyBuZWVkZWQgdG8gYXBwZWFzZSBnZW8uanMncyBoYWNrIG9mIHVzaW5nIGV2dC50YXJnZXQ9dHJ1ZVxuICAgIC8vIHdlIHNob3VsZCBpbXByb3ZlIHRoZSBcImZ4XCIgQVBJIHNvIG90aGVyIHBsb3RzIGNhbiB1c2UgaXQgd2l0aG91dCB0aGVzZSBoYWNrLlxuICAgIGlmKGV2dC50YXJnZXQgJiYgZXZ0LnRhcmdldC50YWdOYW1lKSB7XG4gICAgICAgIHZhciBoYXNDbGlja1RvU2hvdyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnaGFzQ2xpY2tUb1Nob3cnKShnZCwgbmV3aG92ZXJkYXRhKTtcbiAgICAgICAgb3ZlcnJpZGVDdXJzb3IoZDMuc2VsZWN0KGV2dC50YXJnZXQpLCBoYXNDbGlja1RvU2hvdyA/ICdwb2ludGVyJyA6ICcnKTtcbiAgICB9XG5cbiAgICAvLyBkb24ndCBlbWl0IGV2ZW50cyBpZiBjYWxsZWQgbWFudWFsbHlcbiAgICBpZighZXZ0LnRhcmdldCB8fCBub0hvdmVyRXZlbnQgfHwgIWhvdmVyQ2hhbmdlZChnZCwgZXZ0LCBvbGRob3ZlcmRhdGEpKSByZXR1cm47XG5cbiAgICBpZihvbGRob3ZlcmRhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7XG4gICAgICAgICAgICBldmVudDogZXZ0LFxuICAgICAgICAgICAgcG9pbnRzOiBvbGRob3ZlcmRhdGFcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZ2QuZW1pdCgncGxvdGx5X2hvdmVyJywge1xuICAgICAgICBldmVudDogZXZ0LFxuICAgICAgICBwb2ludHM6IGdkLl9ob3ZlcmRhdGEsXG4gICAgICAgIHhheGVzOiB4YUFycmF5LFxuICAgICAgICB5YXhlczogeWFBcnJheSxcbiAgICAgICAgeHZhbHM6IHh2YWxBcnJheSxcbiAgICAgICAgeXZhbHM6IHl2YWxBcnJheVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVIb3ZlclRleHQoaG92ZXJEYXRhLCBvcHRzLCBnZCkge1xuICAgIHZhciBob3Zlcm1vZGUgPSBvcHRzLmhvdmVybW9kZTtcbiAgICB2YXIgcm90YXRlTGFiZWxzID0gb3B0cy5yb3RhdGVMYWJlbHM7XG4gICAgdmFyIGJnQ29sb3IgPSBvcHRzLmJnQ29sb3I7XG4gICAgdmFyIGNvbnRhaW5lciA9IG9wdHMuY29udGFpbmVyO1xuICAgIHZhciBvdXRlckNvbnRhaW5lciA9IG9wdHMub3V0ZXJDb250YWluZXI7XG4gICAgdmFyIGNvbW1vbkxhYmVsT3B0cyA9IG9wdHMuY29tbW9uTGFiZWxPcHRzIHx8IHt9O1xuXG4gICAgLy8gb3B0cy5mb250RmFtaWx5L1NpemUgYXJlIHVzZWQgZm9yIHRoZSBjb21tb24gbGFiZWxcbiAgICAvLyBhbmQgYXMgZGVmYXVsdHMgZm9yIGVhY2ggaG92ZXIgbGFiZWwsIHRob3VnaCB0aGUgaW5kaXZpZHVhbCBsYWJlbHNcbiAgICAvLyBjYW4gb3ZlcnJpZGUgdGhpcy5cbiAgICB2YXIgZm9udEZhbWlseSA9IG9wdHMuZm9udEZhbWlseSB8fCBjb25zdGFudHMuSE9WRVJGT05UO1xuICAgIHZhciBmb250U2l6ZSA9IG9wdHMuZm9udFNpemUgfHwgY29uc3RhbnRzLkhPVkVSRk9OVFNJWkU7XG5cbiAgICB2YXIgYzAgPSBob3ZlckRhdGFbMF07XG4gICAgdmFyIHhhID0gYzAueGE7XG4gICAgdmFyIHlhID0gYzAueWE7XG4gICAgdmFyIGNvbW1vbkF0dHIgPSBob3Zlcm1vZGUgPT09ICd5JyA/ICd5TGFiZWwnIDogJ3hMYWJlbCc7XG4gICAgdmFyIHQwID0gYzBbY29tbW9uQXR0cl07XG4gICAgdmFyIHQwMCA9IChTdHJpbmcodDApIHx8ICcnKS5zcGxpdCgnICcpWzBdO1xuICAgIHZhciBvdXRlckNvbnRhaW5lckJCID0gb3V0ZXJDb250YWluZXIubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBvdXRlclRvcCA9IG91dGVyQ29udGFpbmVyQkIudG9wO1xuICAgIHZhciBvdXRlcldpZHRoID0gb3V0ZXJDb250YWluZXJCQi53aWR0aDtcbiAgICB2YXIgb3V0ZXJIZWlnaHQgPSBvdXRlckNvbnRhaW5lckJCLmhlaWdodDtcblxuICAgIC8vIHNob3cgdGhlIGNvbW1vbiBsYWJlbCwgaWYgYW55LCBvbiB0aGUgYXhpc1xuICAgIC8vIG5ldmVyIHNob3cgYSBjb21tb24gbGFiZWwgaW4gYXJyYXkgbW9kZSxcbiAgICAvLyBldmVuIGlmIHNvbWV0aW1lcyB0aGVyZSBjb3VsZCBiZSBvbmVcbiAgICB2YXIgc2hvd0NvbW1vbkxhYmVsID0gKFxuICAgICAgICAodDAgIT09IHVuZGVmaW5lZCkgJiZcbiAgICAgICAgKGMwLmRpc3RhbmNlIDw9IG9wdHMuaG92ZXJkaXN0YW5jZSkgJiZcbiAgICAgICAgKGhvdmVybW9kZSA9PT0gJ3gnIHx8IGhvdmVybW9kZSA9PT0gJ3knKVxuICAgICk7XG5cbiAgICAvLyBhbGwgaG92ZXIgdHJhY2VzIGhvdmVyaW5mbyBtdXN0IGNvbnRhaW4gdGhlIGhvdmVybW9kZVxuICAgIC8vIHRvIGhhdmUgY29tbW9uIGxhYmVsc1xuICAgIGlmKHNob3dDb21tb25MYWJlbCkge1xuICAgICAgICB2YXIgYWxsSGF2ZVogPSB0cnVlO1xuICAgICAgICB2YXIgaSwgdHJhY2VIb3ZlcmluZm87XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGhvdmVyRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoYWxsSGF2ZVogJiYgaG92ZXJEYXRhW2ldLnpMYWJlbCA9PT0gdW5kZWZpbmVkKSBhbGxIYXZlWiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB0cmFjZUhvdmVyaW5mbyA9IGhvdmVyRGF0YVtpXS5ob3ZlcmluZm8gfHwgaG92ZXJEYXRhW2ldLnRyYWNlLmhvdmVyaW5mbztcbiAgICAgICAgICAgIHZhciBwYXJ0cyA9IEFycmF5LmlzQXJyYXkodHJhY2VIb3ZlcmluZm8pID8gdHJhY2VIb3ZlcmluZm8gOiB0cmFjZUhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZignYWxsJykgPT09IC0xICYmXG4gICAgICAgICAgICAgICAgcGFydHMuaW5kZXhPZihob3Zlcm1vZGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHNob3dDb21tb25MYWJlbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8geHl6IGxhYmVscyBwdXQgYWxsIGluZm8gaW4gdGhlaXIgbWFpbiBsYWJlbCwgc28gaGF2ZSBubyBuZWVkIG9mIGEgY29tbW9uIGxhYmVsXG4gICAgICAgIGlmKGFsbEhhdmVaKSBzaG93Q29tbW9uTGFiZWwgPSBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgY29tbW9uTGFiZWwgPSBjb250YWluZXIuc2VsZWN0QWxsKCdnLmF4aXN0ZXh0JylcbiAgICAgICAgLmRhdGEoc2hvd0NvbW1vbkxhYmVsID8gWzBdIDogW10pO1xuICAgIGNvbW1vbkxhYmVsLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2F4aXN0ZXh0JywgdHJ1ZSk7XG4gICAgY29tbW9uTGFiZWwuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgY29tbW9uTGFiZWwuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGxhYmVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgbHBhdGggPSBMaWIuZW5zdXJlU2luZ2xlKGxhYmVsLCAncGF0aCcsICcnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICBzLnN0eWxlKHsnc3Ryb2tlLXdpZHRoJzogJzFweCd9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBsdGV4dCA9IExpYi5lbnN1cmVTaW5nbGUobGFiZWwsICd0ZXh0JywgJycsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiB1bnRpbCB3ZSBjYW4gaGFuZGxlXG4gICAgICAgICAgICAvLyB0ZXggYW5kIHJlZ3VsYXIgdGV4dCB0b2dldGhlclxuICAgICAgICAgICAgcy5hdHRyKCdkYXRhLW5vdGV4JywgMSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBjb21tb25CZ0NvbG9yID0gY29tbW9uTGFiZWxPcHRzLmJnY29sb3IgfHwgQ29sb3IuZGVmYXVsdExpbmU7XG4gICAgICAgIHZhciBjb21tb25TdHJva2UgPSBjb21tb25MYWJlbE9wdHMuYm9yZGVyY29sb3IgfHwgQ29sb3IuY29udHJhc3QoY29tbW9uQmdDb2xvcik7XG4gICAgICAgIHZhciBjb250cmFzdENvbG9yID0gQ29sb3IuY29udHJhc3QoY29tbW9uQmdDb2xvcik7XG5cbiAgICAgICAgbHBhdGguc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogY29tbW9uQmdDb2xvcixcbiAgICAgICAgICAgIHN0cm9rZTogY29tbW9uU3Ryb2tlXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGx0ZXh0LnRleHQodDApXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsXG4gICAgICAgICAgICAgICAgY29tbW9uTGFiZWxPcHRzLmZvbnQuZmFtaWx5IHx8IGZvbnRGYW1pbHksXG4gICAgICAgICAgICAgICAgY29tbW9uTGFiZWxPcHRzLmZvbnQuc2l6ZSB8fCBmb250U2l6ZSxcbiAgICAgICAgICAgICAgICBjb21tb25MYWJlbE9wdHMuZm9udC5jb2xvciB8fCBjb250cmFzdENvbG9yXG4gICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgMCwgMClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICBsYWJlbC5hdHRyKCd0cmFuc2Zvcm0nLCAnJyk7XG5cbiAgICAgICAgdmFyIHRiYiA9IGx0ZXh0Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaWYoaG92ZXJtb2RlID09PSAneCcpIHtcbiAgICAgICAgICAgIGx0ZXh0LmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgMCwgKHhhLnNpZGUgPT09ICd0b3AnID9cbiAgICAgICAgICAgICAgICAgICAgKG91dGVyVG9wIC0gdGJiLmJvdHRvbSAtIEhPVkVSQVJST1dTSVpFIC0gSE9WRVJURVhUUEFEKSA6XG4gICAgICAgICAgICAgICAgICAgIChvdXRlclRvcCAtIHRiYi50b3AgKyBIT1ZFUkFSUk9XU0laRSArIEhPVkVSVEVYVFBBRCkpKTtcblxuICAgICAgICAgICAgdmFyIHRvcHNpZ24gPSB4YS5zaWRlID09PSAndG9wJyA/ICctJyA6ICcnO1xuICAgICAgICAgICAgbHBhdGguYXR0cignZCcsICdNMCwwJyArXG4gICAgICAgICAgICAgICAgJ0wnICsgSE9WRVJBUlJPV1NJWkUgKyAnLCcgKyB0b3BzaWduICsgSE9WRVJBUlJPV1NJWkUgK1xuICAgICAgICAgICAgICAgICdIJyArIChIT1ZFUlRFWFRQQUQgKyB0YmIud2lkdGggLyAyKSArXG4gICAgICAgICAgICAgICAgJ3YnICsgdG9wc2lnbiArIChIT1ZFUlRFWFRQQUQgKiAyICsgdGJiLmhlaWdodCkgK1xuICAgICAgICAgICAgICAgICdILScgKyAoSE9WRVJURVhUUEFEICsgdGJiLndpZHRoIC8gMikgK1xuICAgICAgICAgICAgICAgICdWJyArIHRvcHNpZ24gKyBIT1ZFUkFSUk9XU0laRSArICdILScgKyBIT1ZFUkFSUk9XU0laRSArICdaJyk7XG5cbiAgICAgICAgICAgIGxhYmVsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArXG4gICAgICAgICAgICAgICAgKHhhLl9vZmZzZXQgKyAoYzAueDAgKyBjMC54MSkgLyAyKSArICcsJyArXG4gICAgICAgICAgICAgICAgKHlhLl9vZmZzZXQgKyAoeGEuc2lkZSA9PT0gJ3RvcCcgPyAwIDogeWEuX2xlbmd0aCkpICsgJyknKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGx0ZXh0LmF0dHIoJ3RleHQtYW5jaG9yJywgeWEuc2lkZSA9PT0gJ3JpZ2h0JyA/ICdzdGFydCcgOiAnZW5kJylcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0LFxuICAgICAgICAgICAgICAgICAgICAoeWEuc2lkZSA9PT0gJ3JpZ2h0JyA/IDEgOiAtMSkgKiAoSE9WRVJURVhUUEFEICsgSE9WRVJBUlJPV1NJWkUpLFxuICAgICAgICAgICAgICAgICAgICBvdXRlclRvcCAtIHRiYi50b3AgLSB0YmIuaGVpZ2h0IC8gMik7XG5cbiAgICAgICAgICAgIHZhciBsZWZ0c2lnbiA9IHlhLnNpZGUgPT09ICdyaWdodCcgPyAnJyA6ICctJztcbiAgICAgICAgICAgIGxwYXRoLmF0dHIoJ2QnLCAnTTAsMCcgK1xuICAgICAgICAgICAgICAgICdMJyArIGxlZnRzaWduICsgSE9WRVJBUlJPV1NJWkUgKyAnLCcgKyBIT1ZFUkFSUk9XU0laRSArXG4gICAgICAgICAgICAgICAgJ1YnICsgKEhPVkVSVEVYVFBBRCArIHRiYi5oZWlnaHQgLyAyKSArXG4gICAgICAgICAgICAgICAgJ2gnICsgbGVmdHNpZ24gKyAoSE9WRVJURVhUUEFEICogMiArIHRiYi53aWR0aCkgK1xuICAgICAgICAgICAgICAgICdWLScgKyAoSE9WRVJURVhUUEFEICsgdGJiLmhlaWdodCAvIDIpICtcbiAgICAgICAgICAgICAgICAnSCcgKyBsZWZ0c2lnbiArIEhPVkVSQVJST1dTSVpFICsgJ1YtJyArIEhPVkVSQVJST1dTSVpFICsgJ1onKTtcblxuICAgICAgICAgICAgbGFiZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICtcbiAgICAgICAgICAgICAgICAoeGEuX29mZnNldCArICh5YS5zaWRlID09PSAncmlnaHQnID8geGEuX2xlbmd0aCA6IDApKSArICcsJyArXG4gICAgICAgICAgICAgICAgKHlhLl9vZmZzZXQgKyAoYzAueTAgKyBjMC55MSkgLyAyKSArICcpJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVtb3ZlIHRoZSBcImNsb3NlIGJ1dCBub3QgcXVpdGVcIiBwb2ludHNcbiAgICAgICAgLy8gYmVjYXVzZSBvZiBlcnJvciBiYXJzLCBvbmx5IHRha2UgdXAgdG8gYSBzcGFjZVxuICAgICAgICBob3ZlckRhdGEgPSBob3ZlckRhdGEuZmlsdGVyKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAoZC56TGFiZWxWYWwgIT09IHVuZGVmaW5lZCkgfHxcbiAgICAgICAgICAgICAgICAoZFtjb21tb25BdHRyXSB8fCAnJykuc3BsaXQoJyAnKVswXSA9PT0gdDAwO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIHNob3cgYWxsIHRoZSBpbmRpdmlkdWFsIGxhYmVsc1xuXG4gICAgLy8gZmlyc3QgY3JlYXRlIHRoZSBvYmplY3RzXG4gICAgdmFyIGhvdmVyTGFiZWxzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZy5ob3ZlcnRleHQnKVxuICAgICAgICAuZGF0YShob3ZlckRhdGEsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBbZC50cmFjZS5pbmRleCwgZC5pbmRleCwgZC54MCwgZC55MCwgZC5uYW1lLCBkLmF0dHIsIGQueGEsIGQueWEgfHwgJyddLmpvaW4oJywnKTtcbiAgICAgICAgfSk7XG4gICAgaG92ZXJMYWJlbHMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnaG92ZXJ0ZXh0JywgdHJ1ZSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIC8vIHRyYWNlIG5hbWUgbGFiZWwgKHJlY3QgYW5kIHRleHQubmFtZSlcbiAgICAgICAgICAgIGcuYXBwZW5kKCdyZWN0JylcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBDb2xvci5hZGRPcGFjaXR5KGJnQ29sb3IsIDAuOCkpO1xuICAgICAgICAgICAgZy5hcHBlbmQoJ3RleHQnKS5jbGFzc2VkKCduYW1lJywgdHJ1ZSk7XG4gICAgICAgICAgICAvLyB0cmFjZSBkYXRhIGxhYmVsIChwYXRoIGFuZCB0ZXh0Lm51bXMpXG4gICAgICAgICAgICBnLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCAnMXB4Jyk7XG4gICAgICAgICAgICBnLmFwcGVuZCgndGV4dCcpLmNsYXNzZWQoJ251bXMnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgZm9udEZhbWlseSwgZm9udFNpemUpO1xuICAgICAgICB9KTtcbiAgICBob3ZlckxhYmVscy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyB0aGVuIHB1dCB0aGUgdGV4dCBpbiwgcG9zaXRpb24gdGhlIHBvaW50ZXIgdG8gdGhlIGRhdGEsXG4gICAgLy8gYW5kIGZpZ3VyZSBvdXQgc2l6ZXNcbiAgICBob3ZlckxhYmVscy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGcgPSBkMy5zZWxlY3QodGhpcykuYXR0cigndHJhbnNmb3JtJywgJycpO1xuICAgICAgICB2YXIgbmFtZSA9ICcnO1xuICAgICAgICB2YXIgdGV4dCA9ICcnO1xuXG4gICAgICAgIC8vIGNvbWJpbmUgcG9zc2libGUgbm9uLW9wYXF1ZSB0cmFjZSBjb2xvciB3aXRoIGJnQ29sb3JcbiAgICAgICAgdmFyIGNvbG9yMCA9IGQuYmdjb2xvciB8fCBkLmNvbG9yO1xuICAgICAgICAvLyBjb2xvciBmb3IgJ251bXMnIHBhcnQgb2YgdGhlIGxhYmVsXG4gICAgICAgIHZhciBudW1zQ29sb3IgPSBDb2xvci5jb21iaW5lKFxuICAgICAgICAgICAgQ29sb3Iub3BhY2l0eShjb2xvcjApID8gY29sb3IwIDogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICBiZ0NvbG9yXG4gICAgICAgICk7XG4gICAgICAgIC8vIGNvbG9yIGZvciAnbmFtZScgcGFydCBvZiB0aGUgbGFiZWxcbiAgICAgICAgdmFyIG5hbWVDb2xvciA9IENvbG9yLmNvbWJpbmUoXG4gICAgICAgICAgICBDb2xvci5vcGFjaXR5KGQuY29sb3IpID8gZC5jb2xvciA6IENvbG9yLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgYmdDb2xvclxuICAgICAgICApO1xuICAgICAgICAvLyBmaW5kIGEgY29udHJhc3RpbmcgY29sb3IgZm9yIGJvcmRlciBhbmQgdGV4dFxuICAgICAgICB2YXIgY29udHJhc3RDb2xvciA9IGQuYm9yZGVyQ29sb3IgfHwgQ29sb3IuY29udHJhc3QobnVtc0NvbG9yKTtcblxuICAgICAgICAvLyB0byBnZXQgY3VzdG9tICduYW1lJyBsYWJlbHMgcGFzcyBjbGVhblBvaW50XG4gICAgICAgIGlmKGQubmFtZU92ZXJyaWRlICE9PSB1bmRlZmluZWQpIGQubmFtZSA9IGQubmFtZU92ZXJyaWRlO1xuXG4gICAgICAgIGlmKGQubmFtZSkge1xuICAgICAgICAgICAgLy8gc3RyaXAgb3V0IG91ciBwc2V1ZG8taHRtbCBlbGVtZW50cyBmcm9tIGQubmFtZSAoaWYgaXQgZXhpc3RzIGF0IGFsbClcbiAgICAgICAgICAgIG5hbWUgPSBzdmdUZXh0VXRpbHMucGxhaW5UZXh0KGQubmFtZSB8fCAnJyk7XG5cbiAgICAgICAgICAgIHZhciBuYW1lTGVuZ3RoID0gTWF0aC5yb3VuZChkLm5hbWVMZW5ndGgpO1xuXG4gICAgICAgICAgICBpZihuYW1lTGVuZ3RoID4gLTEgJiYgbmFtZS5sZW5ndGggPiBuYW1lTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYobmFtZUxlbmd0aCA+IDMpIG5hbWUgPSBuYW1lLnN1YnN0cigwLCBuYW1lTGVuZ3RoIC0gMykgKyAnLi4uJztcbiAgICAgICAgICAgICAgICBlbHNlIG5hbWUgPSBuYW1lLnN1YnN0cigwLCBuYW1lTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGQuekxhYmVsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKGQueExhYmVsICE9PSB1bmRlZmluZWQpIHRleHQgKz0gJ3g6ICcgKyBkLnhMYWJlbCArICc8YnI+JztcbiAgICAgICAgICAgIGlmKGQueUxhYmVsICE9PSB1bmRlZmluZWQpIHRleHQgKz0gJ3k6ICcgKyBkLnlMYWJlbCArICc8YnI+JztcbiAgICAgICAgICAgIHRleHQgKz0gKHRleHQgPyAnejogJyA6ICcnKSArIGQuekxhYmVsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoc2hvd0NvbW1vbkxhYmVsICYmIGRbaG92ZXJtb2RlICsgJ0xhYmVsJ10gPT09IHQwKSB7XG4gICAgICAgICAgICB0ZXh0ID0gZFsoaG92ZXJtb2RlID09PSAneCcgPyAneScgOiAneCcpICsgJ0xhYmVsJ10gfHwgJyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihkLnhMYWJlbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihkLnlMYWJlbCAhPT0gdW5kZWZpbmVkKSB0ZXh0ID0gZC55TGFiZWw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihkLnlMYWJlbCA9PT0gdW5kZWZpbmVkKSB0ZXh0ID0gZC54TGFiZWw7XG4gICAgICAgIGVsc2UgdGV4dCA9ICcoJyArIGQueExhYmVsICsgJywgJyArIGQueUxhYmVsICsgJyknO1xuXG4gICAgICAgIGlmKChkLnRleHQgfHwgZC50ZXh0ID09PSAwKSAmJiAhQXJyYXkuaXNBcnJheShkLnRleHQpKSB7XG4gICAgICAgICAgICB0ZXh0ICs9ICh0ZXh0ID8gJzxicj4nIDogJycpICsgZC50ZXh0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdXNlZCBieSBvdGhlciBtb2R1bGVzIChpbml0aWFsbHkganVzdCB0ZXJuYXJ5KSB0aGF0XG4gICAgICAgIC8vIG1hbmFnZSB0aGVpciBvd24gaG92ZXJpbmZvIGluZGVwZW5kZW50IG9mIGNsZWFuUG9pbnRcbiAgICAgICAgLy8gdGhlIHJlc3Qgb2YgdGhpcyB3aWxsIHN0aWxsIGFwcGx5LCBzbyBzdWNoIG1vZHVsZXNcbiAgICAgICAgLy8gY2FuIHN0aWxsIHB1dCB0aGluZ3MgaW4gKHh8eXx6KUxhYmVsLCB0ZXh0LCBhbmQgbmFtZVxuICAgICAgICAvLyBhbmQgaG92ZXJpbmZvIHdpbGwgc3RpbGwgZGV0ZXJtaW5lIHRoZWlyIHZpc2liaWxpdHlcbiAgICAgICAgaWYoZC5leHRyYVRleHQgIT09IHVuZGVmaW5lZCkgdGV4dCArPSAodGV4dCA/ICc8YnI+JyA6ICcnKSArIGQuZXh0cmFUZXh0O1xuXG4gICAgICAgIC8vIGlmICd0ZXh0JyBpcyBlbXB0eSBhdCB0aGlzIHBvaW50LFxuICAgICAgICAvLyBwdXQgJ25hbWUnIGluIG1haW4gbGFiZWwgYW5kIGRvbid0IHNob3cgc2Vjb25kYXJ5IGxhYmVsXG4gICAgICAgIGlmKHRleHQgPT09ICcnKSB7XG4gICAgICAgICAgICAvLyBpZiAnbmFtZScgaXMgYWxzbyBlbXB0eSwgcmVtb3ZlIGVudGlyZSBsYWJlbFxuICAgICAgICAgICAgaWYobmFtZSA9PT0gJycpIGcucmVtb3ZlKCk7XG4gICAgICAgICAgICB0ZXh0ID0gbmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1haW4gbGFiZWxcbiAgICAgICAgdmFyIHR4ID0gZy5zZWxlY3QoJ3RleHQubnVtcycpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsXG4gICAgICAgICAgICAgICAgZC5mb250RmFtaWx5IHx8IGZvbnRGYW1pbHksXG4gICAgICAgICAgICAgICAgZC5mb250U2l6ZSB8fCBmb250U2l6ZSxcbiAgICAgICAgICAgICAgICBkLmZvbnRDb2xvciB8fCBjb250cmFzdENvbG9yKVxuICAgICAgICAgICAgLnRleHQodGV4dClcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLW5vdGV4JywgMSlcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIDAsIDApXG4gICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgdmFyIHR4MiA9IGcuc2VsZWN0KCd0ZXh0Lm5hbWUnKTtcbiAgICAgICAgdmFyIHR4MndpZHRoID0gMDtcblxuICAgICAgICAvLyBzZWNvbmRhcnkgbGFiZWwgZm9yIG5vbi1lbXB0eSAnbmFtZSdcbiAgICAgICAgaWYobmFtZSAmJiBuYW1lICE9PSB0ZXh0KSB7XG4gICAgICAgICAgICB0eDIuY2FsbChEcmF3aW5nLmZvbnQsXG4gICAgICAgICAgICAgICAgICAgIGQuZm9udEZhbWlseSB8fCBmb250RmFtaWx5LFxuICAgICAgICAgICAgICAgICAgICBkLmZvbnRTaXplIHx8IGZvbnRTaXplLFxuICAgICAgICAgICAgICAgICAgICBuYW1lQ29sb3IpXG4gICAgICAgICAgICAgICAgLnRleHQobmFtZSlcbiAgICAgICAgICAgICAgICAuYXR0cignZGF0YS1ub3RleCcsIDEpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgMCwgMClcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG4gICAgICAgICAgICB0eDJ3aWR0aCA9IHR4Mi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggKyAyICogSE9WRVJURVhUUEFEO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdHgyLnJlbW92ZSgpO1xuICAgICAgICAgICAgZy5zZWxlY3QoJ3JlY3QnKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGcuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgZmlsbDogbnVtc0NvbG9yLFxuICAgICAgICAgICAgICAgIHN0cm9rZTogY29udHJhc3RDb2xvclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIHZhciB0YmIgPSB0eC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBodHggPSBkLnhhLl9vZmZzZXQgKyAoZC54MCArIGQueDEpIC8gMjtcbiAgICAgICAgdmFyIGh0eSA9IGQueWEuX29mZnNldCArIChkLnkwICsgZC55MSkgLyAyO1xuICAgICAgICB2YXIgZHggPSBNYXRoLmFicyhkLngxIC0gZC54MCk7XG4gICAgICAgIHZhciBkeSA9IE1hdGguYWJzKGQueTEgLSBkLnkwKTtcbiAgICAgICAgdmFyIHR4VG90YWxXaWR0aCA9IHRiYi53aWR0aCArIEhPVkVSQVJST1dTSVpFICsgSE9WRVJURVhUUEFEICsgdHgyd2lkdGg7XG4gICAgICAgIHZhciBhbmNob3JTdGFydE9LLCBhbmNob3JFbmRPSztcblxuICAgICAgICBkLnR5MCA9IG91dGVyVG9wIC0gdGJiLnRvcDtcbiAgICAgICAgZC5ieCA9IHRiYi53aWR0aCArIDIgKiBIT1ZFUlRFWFRQQUQ7XG4gICAgICAgIGQuYnkgPSB0YmIuaGVpZ2h0ICsgMiAqIEhPVkVSVEVYVFBBRDtcbiAgICAgICAgZC5hbmNob3IgPSAnc3RhcnQnO1xuICAgICAgICBkLnR4d2lkdGggPSB0YmIud2lkdGg7XG4gICAgICAgIGQudHgyd2lkdGggPSB0eDJ3aWR0aDtcbiAgICAgICAgZC5vZmZzZXQgPSAwO1xuXG4gICAgICAgIGlmKHJvdGF0ZUxhYmVscykge1xuICAgICAgICAgICAgZC5wb3MgPSBodHg7XG4gICAgICAgICAgICBhbmNob3JTdGFydE9LID0gaHR5ICsgZHkgLyAyICsgdHhUb3RhbFdpZHRoIDw9IG91dGVySGVpZ2h0O1xuICAgICAgICAgICAgYW5jaG9yRW5kT0sgPSBodHkgLSBkeSAvIDIgLSB0eFRvdGFsV2lkdGggPj0gMDtcbiAgICAgICAgICAgIGlmKChkLmlkZWFsQWxpZ24gPT09ICd0b3AnIHx8ICFhbmNob3JTdGFydE9LKSAmJiBhbmNob3JFbmRPSykge1xuICAgICAgICAgICAgICAgIGh0eSAtPSBkeSAvIDI7XG4gICAgICAgICAgICAgICAgZC5hbmNob3IgPSAnZW5kJztcbiAgICAgICAgICAgIH0gZWxzZSBpZihhbmNob3JTdGFydE9LKSB7XG4gICAgICAgICAgICAgICAgaHR5ICs9IGR5IC8gMjtcbiAgICAgICAgICAgICAgICBkLmFuY2hvciA9ICdzdGFydCc7XG4gICAgICAgICAgICB9IGVsc2UgZC5hbmNob3IgPSAnbWlkZGxlJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGQucG9zID0gaHR5O1xuICAgICAgICAgICAgYW5jaG9yU3RhcnRPSyA9IGh0eCArIGR4IC8gMiArIHR4VG90YWxXaWR0aCA8PSBvdXRlcldpZHRoO1xuICAgICAgICAgICAgYW5jaG9yRW5kT0sgPSBodHggLSBkeCAvIDIgLSB0eFRvdGFsV2lkdGggPj0gMDtcbiAgICAgICAgICAgIGlmKChkLmlkZWFsQWxpZ24gPT09ICdsZWZ0JyB8fCAhYW5jaG9yU3RhcnRPSykgJiYgYW5jaG9yRW5kT0spIHtcbiAgICAgICAgICAgICAgICBodHggLT0gZHggLyAyO1xuICAgICAgICAgICAgICAgIGQuYW5jaG9yID0gJ2VuZCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYoYW5jaG9yU3RhcnRPSykge1xuICAgICAgICAgICAgICAgIGh0eCArPSBkeCAvIDI7XG4gICAgICAgICAgICAgICAgZC5hbmNob3IgPSAnc3RhcnQnO1xuICAgICAgICAgICAgfSBlbHNlIGQuYW5jaG9yID0gJ21pZGRsZSc7XG4gICAgICAgIH1cblxuICAgICAgICB0eC5hdHRyKCd0ZXh0LWFuY2hvcicsIGQuYW5jaG9yKTtcbiAgICAgICAgaWYodHgyd2lkdGgpIHR4Mi5hdHRyKCd0ZXh0LWFuY2hvcicsIGQuYW5jaG9yKTtcbiAgICAgICAgZy5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBodHggKyAnLCcgKyBodHkgKyAnKScgK1xuICAgICAgICAgICAgKHJvdGF0ZUxhYmVscyA/ICdyb3RhdGUoJyArIFlBTkdMRSArICcpJyA6ICcnKSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gaG92ZXJMYWJlbHM7XG59XG5cbi8vIE1ha2UgZ3JvdXBzIG9mIHRvdWNoaW5nIHBvaW50cywgYW5kIHdpdGhpbiBlYWNoIGdyb3VwXG4vLyBtb3ZlIGVhY2ggcG9pbnQgc28gdGhhdCBubyBsYWJlbHMgb3ZlcmxhcCwgYnV0IHRoZSBhdmVyYWdlXG4vLyBsYWJlbCBwb3NpdGlvbiBpcyB0aGUgc2FtZSBhcyBpdCB3YXMgYmVmb3JlIG1vdmluZy4gSW5kaWNlbnRhbGx5LFxuLy8gdGhpcyBpcyBlcXVpdmFsZW50IHRvIHNheWluZyBhbGwgdGhlIGxhYmVscyBhcmUgb24gZXF1YWwgbGluZWFyXG4vLyBzcHJpbmdzIGFib3V0IHRoZWlyIGluaXRpYWwgcG9zaXRpb24uIEluaXRpYWxseSwgZWFjaCBwb2ludCBpc1xuLy8gaXRzIG93biBncm91cCwgYnV0IGFzIHdlIGZpbmQgb3ZlcmxhcHMgd2Ugd2lsbCBjbHVtcCB0aGUgcG9pbnRzLlxuLy9cbi8vIEFsc28sIHRoZXJlIGFyZSBoYXJkIGNvbnN0cmFpbnRzIGF0IHRoZSBlZGdlcyBvZiB0aGUgZ3JhcGhzLFxuLy8gdGhhdCBwdXNoIGFsbCBncm91cHMgdG8gdGhlIG1pZGRsZSBzbyB0aGV5IGFyZSB2aXNpYmxlLiBJIGRvbid0XG4vLyBrbm93IHdoYXQgaGFwcGVucyBpZiB0aGUgZ3JvdXAgc3BhbnMgYWxsIHRoZSB3YXkgZnJvbSBvbmUgZWRnZSB0b1xuLy8gdGhlIG90aGVyLCB0aG91Z2ggaXQgaGFyZGx5IG1hdHRlcnMgLSB0aGVyZSdzIGp1c3QgdG9vIG11Y2hcbi8vIGluZm9ybWF0aW9uIHRoZW4uXG5mdW5jdGlvbiBob3ZlckF2b2lkT3ZlcmxhcHMoaG92ZXJEYXRhLCBheCwgZnVsbExheW91dCkge1xuICAgIHZhciBudW1tb3ZlcyA9IDA7XG5cbiAgICB2YXIgYXhTaWduID0gMTtcblxuICAgIC8vIG1ha2UgZ3JvdXBzIG9mIHRvdWNoaW5nIHBvaW50c1xuICAgIHZhciBwb2ludGdyb3VwcyA9IGhvdmVyRGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXIgYXhpcyA9IGRbYXhdO1xuICAgICAgICB2YXIgYXhJc1ggPSBheGlzLl9pZC5jaGFyQXQoMCkgPT09ICd4JztcbiAgICAgICAgdmFyIHJuZyA9IGF4aXMucmFuZ2U7XG4gICAgICAgIGlmKCFpICYmIHJuZyAmJiAoKHJuZ1swXSA+IHJuZ1sxXSkgIT09IGF4SXNYKSkgYXhTaWduID0gLTE7XG4gICAgICAgIHJldHVybiBbe1xuICAgICAgICAgICAgaTogaSxcbiAgICAgICAgICAgIHRyYWNlSW5kZXg6IGQudHJhY2UuaW5kZXgsXG4gICAgICAgICAgICBkcDogMCxcbiAgICAgICAgICAgIHBvczogZC5wb3MsXG4gICAgICAgICAgICBwb3NyZWY6IGQucG9zcmVmLFxuICAgICAgICAgICAgc2l6ZTogZC5ieSAqIChheElzWCA/IFlGQUNUT1IgOiAxKSAvIDIsXG4gICAgICAgICAgICBwbWluOiAwLFxuICAgICAgICAgICAgcG1heDogKGF4SXNYID8gZnVsbExheW91dC53aWR0aCA6IGZ1bGxMYXlvdXQuaGVpZ2h0KVxuICAgICAgICB9XTtcbiAgICB9KVxuICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIChhWzBdLnBvc3JlZiAtIGJbMF0ucG9zcmVmKSB8fFxuICAgICAgICAgICAgLy8gZm9yIGVxdWFsIHBvc2l0aW9ucywgc29ydCB0cmFjZSBpbmRpY2VzIGluY3JlYXNpbmcgb3IgZGVjcmVhc2luZ1xuICAgICAgICAgICAgLy8gZGVwZW5kaW5nIG9uIHdoZXRoZXIgdGhlIGF4aXMgaXMgcmV2ZXJzZWQgb3Igbm90Li4uIHNvIHN0YWNrZWRcbiAgICAgICAgICAgIC8vIHRyYWNlcyB3aWxsIGdlbmVyYWxseSBrZWVwIHRoZWlyIG9yZGVyIGV2ZW4gaWYgb25lIHRyYWNlIGFkZHNcbiAgICAgICAgICAgIC8vIG5vdGhpbmcgdG8gdGhlIHN0YWNrLlxuICAgICAgICAgICAgKGF4U2lnbiAqIChiWzBdLnRyYWNlSW5kZXggLSBhWzBdLnRyYWNlSW5kZXgpKTtcbiAgICB9KTtcblxuICAgIHZhciBkb25lcG9zaXRpb25pbmcsIHRvcE92ZXJsYXAsIGJvdHRvbU92ZXJsYXAsIGksIGosIHB0aSwgc3VtZHA7XG5cbiAgICBmdW5jdGlvbiBjb25zdHJhaW5Hcm91cChncnApIHtcbiAgICAgICAgdmFyIG1pblB0ID0gZ3JwWzBdO1xuICAgICAgICB2YXIgbWF4UHQgPSBncnBbZ3JwLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgIC8vIG92ZXJsYXAgd2l0aCB0aGUgdG9wIC0gcG9zaXRpdmUgdmFscyBhcmUgb3ZlcmxhcHNcbiAgICAgICAgdG9wT3ZlcmxhcCA9IG1pblB0LnBtaW4gLSBtaW5QdC5wb3MgLSBtaW5QdC5kcCArIG1pblB0LnNpemU7XG5cbiAgICAgICAgLy8gb3ZlcmxhcCB3aXRoIHRoZSBib3R0b20gLSBwb3NpdGl2ZSB2YWxzIGFyZSBvdmVybGFwc1xuICAgICAgICBib3R0b21PdmVybGFwID0gbWF4UHQucG9zICsgbWF4UHQuZHAgKyBtYXhQdC5zaXplIC0gbWluUHQucG1heDtcblxuICAgICAgICAvLyBjaGVjayBmb3IgbWluIG92ZXJsYXAgZmlyc3QsIHNvIHRoYXQgd2UgYWx3YXlzXG4gICAgICAgIC8vIHNlZSB0aGUgbGFyZ2VzdCBsYWJlbHNcbiAgICAgICAgLy8gYWxsb3cgZm9yIC4wMXB4IG92ZXJsYXAsIHNvIHdlIGRvbid0IGdldCBhblxuICAgICAgICAvLyBpbmZpbml0ZSBsb29wIGZyb20gcm91bmRpbmcgZXJyb3JzXG4gICAgICAgIGlmKHRvcE92ZXJsYXAgPiAwLjAxKSB7XG4gICAgICAgICAgICBmb3IoaiA9IGdycC5sZW5ndGggLSAxOyBqID49IDA7IGotLSkgZ3JwW2pdLmRwICs9IHRvcE92ZXJsYXA7XG4gICAgICAgICAgICBkb25lcG9zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZihib3R0b21PdmVybGFwIDwgMC4wMSkgcmV0dXJuO1xuICAgICAgICBpZih0b3BPdmVybGFwIDwgLTAuMDEpIHtcbiAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSdyZSBub3QgcHVzaGluZyBiYWNrIGFuZCBmb3J0aFxuICAgICAgICAgICAgZm9yKGogPSBncnAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIGdycFtqXS5kcCAtPSBib3R0b21PdmVybGFwO1xuICAgICAgICAgICAgZG9uZXBvc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYoIWRvbmVwb3NpdGlvbmluZykgcmV0dXJuO1xuXG4gICAgICAgIC8vIG5vIHJvb20gdG8gZml4IHBvc2l0aW9uaW5nLCBkZWxldGUgb2ZmLXNjcmVlbiBwb2ludHNcblxuICAgICAgICAvLyBmaXJzdCBzZWUgaG93IG1hbnkgcG9pbnRzIHdlIG5lZWQgdG8gZGVsZXRlXG4gICAgICAgIHZhciBkZWxldGVDb3VudCA9IDA7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdycC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcHRpID0gZ3JwW2ldO1xuICAgICAgICAgICAgaWYocHRpLnBvcyArIHB0aS5kcCArIHB0aS5zaXplID4gbWluUHQucG1heCkgZGVsZXRlQ291bnQrKztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHN0YXJ0IGJ5IGRlbGV0aW5nIHBvaW50cyB3aG9zZSBkYXRhIGlzIG9mZiBzY3JlZW5cbiAgICAgICAgZm9yKGkgPSBncnAubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGlmKGRlbGV0ZUNvdW50IDw9IDApIGJyZWFrO1xuICAgICAgICAgICAgcHRpID0gZ3JwW2ldO1xuXG4gICAgICAgICAgICAvLyBwb3MgaGFzIGFscmVhZHkgYmVlbiBjb25zdHJhaW5lZCB0byBbcG1pbixwbWF4XVxuICAgICAgICAgICAgLy8gc28gbG9vayBmb3IgcG9pbnRzIGNsb3NlIHRvIHRoYXQgdG8gZGVsZXRlXG4gICAgICAgICAgICBpZihwdGkucG9zID4gbWluUHQucG1heCAtIDEpIHtcbiAgICAgICAgICAgICAgICBwdGkuZGVsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBkZWxldGVDb3VudC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdycC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoZGVsZXRlQ291bnQgPD0gMCkgYnJlYWs7XG4gICAgICAgICAgICBwdGkgPSBncnBbaV07XG5cbiAgICAgICAgICAgIC8vIHBvcyBoYXMgYWxyZWFkeSBiZWVuIGNvbnN0cmFpbmVkIHRvIFtwbWluLHBtYXhdXG4gICAgICAgICAgICAvLyBzbyBsb29rIGZvciBwb2ludHMgY2xvc2UgdG8gdGhhdCB0byBkZWxldGVcbiAgICAgICAgICAgIGlmKHB0aS5wb3MgPCBtaW5QdC5wbWluICsgMSkge1xuICAgICAgICAgICAgICAgIHB0aS5kZWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGRlbGV0ZUNvdW50LS07XG5cbiAgICAgICAgICAgICAgICAvLyBzaGlmdCB0aGUgd2hvbGUgZ3JvdXAgbWludXMgaW50byB0aGlzIG5ldyBzcGFjZVxuICAgICAgICAgICAgICAgIGJvdHRvbU92ZXJsYXAgPSBwdGkuc2l6ZSAqIDI7XG4gICAgICAgICAgICAgICAgZm9yKGogPSBncnAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIGdycFtqXS5kcCAtPSBib3R0b21PdmVybGFwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHRoZW4gZGVsZXRlIHBvaW50cyB0aGF0IGdvIG9mZiB0aGUgYm90dG9tXG4gICAgICAgIGZvcihpID0gZ3JwLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBpZihkZWxldGVDb3VudCA8PSAwKSBicmVhaztcbiAgICAgICAgICAgIHB0aSA9IGdycFtpXTtcbiAgICAgICAgICAgIGlmKHB0aS5wb3MgKyBwdGkuZHAgKyBwdGkuc2l6ZSA+IG1pblB0LnBtYXgpIHtcbiAgICAgICAgICAgICAgICBwdGkuZGVsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBkZWxldGVDb3VudC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbG9vcCB0aHJvdWdoIGdyb3VwcywgY29tYmluaW5nIHRoZW0gaWYgdGhleSBvdmVybGFwLFxuICAgIC8vIHVudGlsIG5vdGhpbmcgbW92ZXNcbiAgICB3aGlsZSghZG9uZXBvc2l0aW9uaW5nICYmIG51bW1vdmVzIDw9IGhvdmVyRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgLy8gdG8gYXZvaWQgaW5maW5pdGUgbG9vcHMsIGRvbid0IG1vdmUgbW9yZSB0aW1lc1xuICAgICAgICAvLyB0aGFuIHRoZXJlIGFyZSB0cmFjZXNcbiAgICAgICAgbnVtbW92ZXMrKztcblxuICAgICAgICAvLyBhc3N1bWUgbm90aGluZyB3aWxsIG1vdmUgaW4gdGhpcyBpdGVyYXRpb24sXG4gICAgICAgIC8vIHJldmVyc2UgdGhpcyBpZiBpdCBkb2VzXG4gICAgICAgIGRvbmVwb3NpdGlvbmluZyA9IHRydWU7XG4gICAgICAgIGkgPSAwO1xuICAgICAgICB3aGlsZShpIDwgcG9pbnRncm91cHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vIHRoZSBoaWdoZXIgKGcwKSBhbmQgbG93ZXIgKGcxKSBwb2ludCBncm91cFxuICAgICAgICAgICAgdmFyIGcwID0gcG9pbnRncm91cHNbaV07XG4gICAgICAgICAgICB2YXIgZzEgPSBwb2ludGdyb3Vwc1tpICsgMV07XG5cbiAgICAgICAgICAgIC8vIHRoZSBsb3dlc3QgcG9pbnQgaW4gdGhlIGhpZ2hlciBncm91cCAocDApXG4gICAgICAgICAgICAvLyB0aGUgaGlnaGVzdCBwb2ludCBpbiB0aGUgbG93ZXIgZ3JvdXAgKHAxKVxuICAgICAgICAgICAgdmFyIHAwID0gZzBbZzAubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB2YXIgcDEgPSBnMVswXTtcbiAgICAgICAgICAgIHRvcE92ZXJsYXAgPSBwMC5wb3MgKyBwMC5kcCArIHAwLnNpemUgLSBwMS5wb3MgLSBwMS5kcCArIHAxLnNpemU7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZ3JvdXAgcG9pbnRzIHRoYXQgbGllIG9uIHRoZSBzYW1lIGF4ZXNcbiAgICAgICAgICAgIGlmKHRvcE92ZXJsYXAgPiAwLjAxICYmIChwMC5wbWluID09PSBwMS5wbWluKSAmJiAocDAucG1heCA9PT0gcDEucG1heCkpIHtcbiAgICAgICAgICAgICAgICAvLyBwdXNoIHRoZSBuZXcgcG9pbnQocykgYWRkZWQgdG8gdGhpcyBncm91cCBvdXQgb2YgdGhlIHdheVxuICAgICAgICAgICAgICAgIGZvcihqID0gZzEubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIGcxW2pdLmRwICs9IHRvcE92ZXJsYXA7XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgdGhlbSB0byB0aGUgZ3JvdXBcbiAgICAgICAgICAgICAgICBnMC5wdXNoLmFwcGx5KGcwLCBnMSk7XG4gICAgICAgICAgICAgICAgcG9pbnRncm91cHMuc3BsaWNlKGkgKyAxLCAxKTtcblxuICAgICAgICAgICAgICAgIC8vIGFkanVzdCBmb3IgbWluaW11bSBhdmVyYWdlIG1vdmVtZW50XG4gICAgICAgICAgICAgICAgc3VtZHAgPSAwO1xuICAgICAgICAgICAgICAgIGZvcihqID0gZzAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHN1bWRwICs9IGcwW2pdLmRwO1xuICAgICAgICAgICAgICAgIGJvdHRvbU92ZXJsYXAgPSBzdW1kcCAvIGcwLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IGcwLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSBnMFtqXS5kcCAtPSBib3R0b21PdmVybGFwO1xuICAgICAgICAgICAgICAgIGRvbmVwb3NpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpKys7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGVjayBpZiB3ZSdyZSBnb2luZyBvZmYgdGhlIHBsb3Qgb24gZWl0aGVyIHNpZGUgYW5kIGZpeFxuICAgICAgICBwb2ludGdyb3Vwcy5mb3JFYWNoKGNvbnN0cmFpbkdyb3VwKTtcbiAgICB9XG5cbiAgICAvLyBub3cgcHV0IHRoZXNlIG9mZnNldHMgaW50byBob3ZlckRhdGFcbiAgICBmb3IoaSA9IHBvaW50Z3JvdXBzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHZhciBncnAgPSBwb2ludGdyb3Vwc1tpXTtcbiAgICAgICAgZm9yKGogPSBncnAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgIHZhciBwdCA9IGdycFtqXTtcbiAgICAgICAgICAgIHZhciBob3ZlclB0ID0gaG92ZXJEYXRhW3B0LmldO1xuICAgICAgICAgICAgaG92ZXJQdC5vZmZzZXQgPSBwdC5kcDtcbiAgICAgICAgICAgIGhvdmVyUHQuZGVsID0gcHQuZGVsO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBhbGlnbkhvdmVyVGV4dChob3ZlckxhYmVscywgcm90YXRlTGFiZWxzKSB7XG4gICAgLy8gZmluYWxseSBzZXQgdGhlIHRleHQgcG9zaXRpb25pbmcgcmVsYXRpdmUgdG8gdGhlIGRhdGEgYW5kIGRyYXcgdGhlXG4gICAgLy8gYm94IGFyb3VuZCBpdFxuICAgIGhvdmVyTGFiZWxzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgZyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgaWYoZC5kZWwpIHtcbiAgICAgICAgICAgIGcucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaG9yelNpZ24gPSBkLmFuY2hvciA9PT0gJ2VuZCcgPyAtMSA6IDE7XG4gICAgICAgIHZhciB0eCA9IGcuc2VsZWN0KCd0ZXh0Lm51bXMnKTtcbiAgICAgICAgdmFyIGFsaWduU2hpZnQgPSB7c3RhcnQ6IDEsIGVuZDogLTEsIG1pZGRsZTogMH1bZC5hbmNob3JdO1xuICAgICAgICB2YXIgdHh4ID0gYWxpZ25TaGlmdCAqIChIT1ZFUkFSUk9XU0laRSArIEhPVkVSVEVYVFBBRCk7XG4gICAgICAgIHZhciB0eDJ4ID0gdHh4ICsgYWxpZ25TaGlmdCAqIChkLnR4d2lkdGggKyBIT1ZFUlRFWFRQQUQpO1xuICAgICAgICB2YXIgb2Zmc2V0WCA9IDA7XG4gICAgICAgIHZhciBvZmZzZXRZID0gZC5vZmZzZXQ7XG5cbiAgICAgICAgaWYoZC5hbmNob3IgPT09ICdtaWRkbGUnKSB7XG4gICAgICAgICAgICB0eHggLT0gZC50eDJ3aWR0aCAvIDI7XG4gICAgICAgICAgICB0eDJ4ICs9IGQudHh3aWR0aCAvIDIgKyBIT1ZFUlRFWFRQQUQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYocm90YXRlTGFiZWxzKSB7XG4gICAgICAgICAgICBvZmZzZXRZICo9IC1ZU0hJRlRZO1xuICAgICAgICAgICAgb2Zmc2V0WCA9IGQub2Zmc2V0ICogWVNISUZUWDtcbiAgICAgICAgfVxuXG4gICAgICAgIGcuc2VsZWN0KCdwYXRoJykuYXR0cignZCcsIGQuYW5jaG9yID09PSAnbWlkZGxlJyA/XG4gICAgICAgICAgICAvLyBtaWRkbGUgYWxpZ25lZDogcmVjdCBjZW50ZXJlZCBvbiBkYXRhXG4gICAgICAgICAgICAoJ00tJyArIChkLmJ4IC8gMiArIGQudHgyd2lkdGggLyAyKSArICcsJyArIChvZmZzZXRZIC0gZC5ieSAvIDIpICtcbiAgICAgICAgICAgICAgJ2gnICsgZC5ieCArICd2JyArIGQuYnkgKyAnaC0nICsgZC5ieCArICdaJykgOlxuICAgICAgICAgICAgLy8gbGVmdCBvciByaWdodCBhbGlnbmVkOiBzaWRlIHJlY3Qgd2l0aCBhcnJvdyB0byBkYXRhXG4gICAgICAgICAgICAoJ00wLDBMJyArIChob3J6U2lnbiAqIEhPVkVSQVJST1dTSVpFICsgb2Zmc2V0WCkgKyAnLCcgKyAoSE9WRVJBUlJPV1NJWkUgKyBvZmZzZXRZKSArXG4gICAgICAgICAgICAgICAgJ3YnICsgKGQuYnkgLyAyIC0gSE9WRVJBUlJPV1NJWkUpICtcbiAgICAgICAgICAgICAgICAnaCcgKyAoaG9yelNpZ24gKiBkLmJ4KSArXG4gICAgICAgICAgICAgICAgJ3YtJyArIGQuYnkgK1xuICAgICAgICAgICAgICAgICdIJyArIChob3J6U2lnbiAqIEhPVkVSQVJST1dTSVpFICsgb2Zmc2V0WCkgK1xuICAgICAgICAgICAgICAgICdWJyArIChvZmZzZXRZIC0gSE9WRVJBUlJPV1NJWkUpICtcbiAgICAgICAgICAgICAgICAnWicpKTtcblxuICAgICAgICB0eC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsXG4gICAgICAgICAgICB0eHggKyBvZmZzZXRYLCBvZmZzZXRZICsgZC50eTAgLSBkLmJ5IC8gMiArIEhPVkVSVEVYVFBBRCk7XG5cbiAgICAgICAgaWYoZC50eDJ3aWR0aCkge1xuICAgICAgICAgICAgZy5zZWxlY3QoJ3RleHQubmFtZScpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgdHgyeCArIGFsaWduU2hpZnQgKiBIT1ZFUlRFWFRQQUQgKyBvZmZzZXRYLFxuICAgICAgICAgICAgICAgICAgICBvZmZzZXRZICsgZC50eTAgLSBkLmJ5IC8gMiArIEhPVkVSVEVYVFBBRCk7XG4gICAgICAgICAgICBnLnNlbGVjdCgncmVjdCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRSZWN0LFxuICAgICAgICAgICAgICAgICAgICB0eDJ4ICsgKGFsaWduU2hpZnQgLSAxKSAqIGQudHgyd2lkdGggLyAyICsgb2Zmc2V0WCxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WSAtIGQuYnkgLyAyIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgZC50eDJ3aWR0aCwgZC5ieSArIDIpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGNsZWFuUG9pbnQoZCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGluZGV4ID0gZC5pbmRleDtcbiAgICB2YXIgdHJhY2UgPSBkLnRyYWNlIHx8IHt9O1xuICAgIHZhciBjZDAgPSBkLmNkWzBdO1xuICAgIHZhciBjZCA9IGQuY2RbaW5kZXhdIHx8IHt9O1xuXG4gICAgdmFyIGdldFZhbCA9IEFycmF5LmlzQXJyYXkoaW5kZXgpID9cbiAgICAgICAgZnVuY3Rpb24oY2FsY0tleSwgdHJhY2VLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBMaWIuY2FzdE9wdGlvbihjZDAsIGluZGV4LCBjYWxjS2V5KSB8fFxuICAgICAgICAgICAgICAgIExpYi5leHRyYWN0T3B0aW9uKHt9LCB0cmFjZSwgJycsIHRyYWNlS2V5KTtcbiAgICAgICAgfSA6XG4gICAgICAgIGZ1bmN0aW9uKGNhbGNLZXksIHRyYWNlS2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLmV4dHJhY3RPcHRpb24oY2QsIHRyYWNlLCBjYWxjS2V5LCB0cmFjZUtleSk7XG4gICAgICAgIH07XG5cbiAgICBmdW5jdGlvbiBmaWxsKGtleSwgY2FsY0tleSwgdHJhY2VLZXkpIHtcbiAgICAgICAgdmFyIHZhbCA9IGdldFZhbChjYWxjS2V5LCB0cmFjZUtleSk7XG4gICAgICAgIGlmKHZhbCkgZFtrZXldID0gdmFsO1xuICAgIH1cblxuICAgIGZpbGwoJ2hvdmVyaW5mbycsICdoaScsICdob3ZlcmluZm8nKTtcbiAgICBmaWxsKCdiZ2NvbG9yJywgJ2hiZycsICdob3ZlcmxhYmVsLmJnY29sb3InKTtcbiAgICBmaWxsKCdib3JkZXJDb2xvcicsICdoYmMnLCAnaG92ZXJsYWJlbC5ib3JkZXJjb2xvcicpO1xuICAgIGZpbGwoJ2ZvbnRGYW1pbHknLCAnaHRmJywgJ2hvdmVybGFiZWwuZm9udC5mYW1pbHknKTtcbiAgICBmaWxsKCdmb250U2l6ZScsICdodHMnLCAnaG92ZXJsYWJlbC5mb250LnNpemUnKTtcbiAgICBmaWxsKCdmb250Q29sb3InLCAnaHRjJywgJ2hvdmVybGFiZWwuZm9udC5jb2xvcicpO1xuICAgIGZpbGwoJ25hbWVMZW5ndGgnLCAnaG5sJywgJ2hvdmVybGFiZWwubmFtZWxlbmd0aCcpO1xuXG4gICAgZC5wb3NyZWYgPSBob3Zlcm1vZGUgPT09ICd5JyA/XG4gICAgICAgIChkLnhhLl9vZmZzZXQgKyAoZC54MCArIGQueDEpIC8gMikgOlxuICAgICAgICAoZC55YS5fb2Zmc2V0ICsgKGQueTAgKyBkLnkxKSAvIDIpO1xuXG4gICAgLy8gdGhlbiBjb25zdHJhaW4gYWxsIHRoZSBwb3NpdGlvbnMgdG8gYmUgb24gdGhlIHBsb3RcbiAgICBkLngwID0gTGliLmNvbnN0cmFpbihkLngwLCAwLCBkLnhhLl9sZW5ndGgpO1xuICAgIGQueDEgPSBMaWIuY29uc3RyYWluKGQueDEsIDAsIGQueGEuX2xlbmd0aCk7XG4gICAgZC55MCA9IExpYi5jb25zdHJhaW4oZC55MCwgMCwgZC55YS5fbGVuZ3RoKTtcbiAgICBkLnkxID0gTGliLmNvbnN0cmFpbihkLnkxLCAwLCBkLnlhLl9sZW5ndGgpO1xuXG4gICAgLy8gYW5kIGNvbnZlcnQgdGhlIHggYW5kIHkgbGFiZWwgdmFsdWVzIGludG8gZm9ybWF0dGVkIHRleHRcbiAgICBpZihkLnhMYWJlbFZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGQueExhYmVsID0gKCd4TGFiZWwnIGluIGQpID8gZC54TGFiZWwgOiBBeGVzLmhvdmVyTGFiZWxUZXh0KGQueGEsIGQueExhYmVsVmFsKTtcbiAgICAgICAgZC54VmFsID0gZC54YS5jMmQoZC54TGFiZWxWYWwpO1xuICAgIH1cbiAgICBpZihkLnlMYWJlbFZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGQueUxhYmVsID0gKCd5TGFiZWwnIGluIGQpID8gZC55TGFiZWwgOiBBeGVzLmhvdmVyTGFiZWxUZXh0KGQueWEsIGQueUxhYmVsVmFsKTtcbiAgICAgICAgZC55VmFsID0gZC55YS5jMmQoZC55TGFiZWxWYWwpO1xuICAgIH1cblxuICAgIC8vIFRyYWNlcyBsaWtlIGhlYXRtYXBzIGdlbmVyYXRlIHRoZSB6TGFiZWwgaW4gdGhlaXIgaG92ZXJQb2ludHMgZnVuY3Rpb25cbiAgICBpZihkLnpMYWJlbFZhbCAhPT0gdW5kZWZpbmVkICYmIGQuekxhYmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZC56TGFiZWwgPSBTdHJpbmcoZC56TGFiZWxWYWwpO1xuICAgIH1cblxuICAgIC8vIGZvciBib3ggbWVhbnMgYW5kIGVycm9yIGJhcnMsIGFkZCB0aGUgcmFuZ2UgdG8gdGhlIGxhYmVsXG4gICAgaWYoIWlzTmFOKGQueGVycikgJiYgIShkLnhhLnR5cGUgPT09ICdsb2cnICYmIGQueGVyciA8PSAwKSkge1xuICAgICAgICB2YXIgeGVUZXh0ID0gQXhlcy50aWNrVGV4dChkLnhhLCBkLnhhLmMybChkLnhlcnIpLCAnaG92ZXInKS50ZXh0O1xuICAgICAgICBpZihkLnhlcnJuZWcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgZC54TGFiZWwgKz0gJyArJyArIHhlVGV4dCArICcgLyAtJyArXG4gICAgICAgICAgICAgICAgQXhlcy50aWNrVGV4dChkLnhhLCBkLnhhLmMybChkLnhlcnJuZWcpLCAnaG92ZXInKS50ZXh0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgZC54TGFiZWwgKz0gJyDCsSAnICsgeGVUZXh0O1xuXG4gICAgICAgIC8vIHNtYWxsIGRpc3RhbmNlIHBlbmFsdHkgZm9yIGVycm9yIGJhcnMsIHNvIHRoYXQgaWYgdGhlcmUgYXJlXG4gICAgICAgIC8vIHRyYWNlcyB3aXRoIGVycm9ycyBhbmQgc29tZSB3aXRob3V0LCB0aGUgZXJyb3IgYmFyIGxhYmVsIHdpbGxcbiAgICAgICAgLy8gaG9pc3QgdXAgdG8gdGhlIHBvaW50XG4gICAgICAgIGlmKGhvdmVybW9kZSA9PT0gJ3gnKSBkLmRpc3RhbmNlICs9IDE7XG4gICAgfVxuICAgIGlmKCFpc05hTihkLnllcnIpICYmICEoZC55YS50eXBlID09PSAnbG9nJyAmJiBkLnllcnIgPD0gMCkpIHtcbiAgICAgICAgdmFyIHllVGV4dCA9IEF4ZXMudGlja1RleHQoZC55YSwgZC55YS5jMmwoZC55ZXJyKSwgJ2hvdmVyJykudGV4dDtcbiAgICAgICAgaWYoZC55ZXJybmVnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGQueUxhYmVsICs9ICcgKycgKyB5ZVRleHQgKyAnIC8gLScgK1xuICAgICAgICAgICAgICAgIEF4ZXMudGlja1RleHQoZC55YSwgZC55YS5jMmwoZC55ZXJybmVnKSwgJ2hvdmVyJykudGV4dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGQueUxhYmVsICs9ICcgwrEgJyArIHllVGV4dDtcblxuICAgICAgICBpZihob3Zlcm1vZGUgPT09ICd5JykgZC5kaXN0YW5jZSArPSAxO1xuICAgIH1cblxuICAgIHZhciBpbmZvbW9kZSA9IGQuaG92ZXJpbmZvIHx8IGQudHJhY2UuaG92ZXJpbmZvO1xuXG4gICAgaWYoaW5mb21vZGUgIT09ICdhbGwnKSB7XG4gICAgICAgIGluZm9tb2RlID0gQXJyYXkuaXNBcnJheShpbmZvbW9kZSkgPyBpbmZvbW9kZSA6IGluZm9tb2RlLnNwbGl0KCcrJyk7XG4gICAgICAgIGlmKGluZm9tb2RlLmluZGV4T2YoJ3gnKSA9PT0gLTEpIGQueExhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICBpZihpbmZvbW9kZS5pbmRleE9mKCd5JykgPT09IC0xKSBkLnlMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYoaW5mb21vZGUuaW5kZXhPZigneicpID09PSAtMSkgZC56TGFiZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmKGluZm9tb2RlLmluZGV4T2YoJ3RleHQnKSA9PT0gLTEpIGQudGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYoaW5mb21vZGUuaW5kZXhPZignbmFtZScpID09PSAtMSkgZC5uYW1lID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBkO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTcGlrZWxpbmVzKGNsb3Nlc3RQb2ludHMsIG9wdHMpIHtcbiAgICB2YXIgY29udGFpbmVyID0gb3B0cy5jb250YWluZXI7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBvcHRzLmZ1bGxMYXlvdXQ7XG4gICAgdmFyIGV2dCA9IG9wdHMuZXZlbnQ7XG4gICAgdmFyIHNob3dZID0gISFjbG9zZXN0UG9pbnRzLmhMaW5lUG9pbnQ7XG4gICAgdmFyIHNob3dYID0gISFjbG9zZXN0UG9pbnRzLnZMaW5lUG9pbnQ7XG5cbiAgICB2YXIgeGEsIHlhO1xuXG4gICAgLy8gUmVtb3ZlIG9sZCBzcGlrZWxpbmUgaXRlbXNcbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCcuc3Bpa2VsaW5lJykucmVtb3ZlKCk7XG5cbiAgICBpZighKHNob3dYIHx8IHNob3dZKSkgcmV0dXJuO1xuXG4gICAgdmFyIGNvbnRyYXN0Q29sb3IgPSBDb2xvci5jb21iaW5lKGZ1bGxMYXlvdXQucGxvdF9iZ2NvbG9yLCBmdWxsTGF5b3V0LnBhcGVyX2JnY29sb3IpO1xuXG4gICAgLy8gSG9yaXpvbnRhbCBsaW5lICh0byB5LWF4aXMpXG4gICAgaWYoc2hvd1kpIHtcbiAgICAgICAgdmFyIGhMaW5lUG9pbnQgPSBjbG9zZXN0UG9pbnRzLmhMaW5lUG9pbnQ7XG4gICAgICAgIHZhciBoTGluZVBvaW50WCwgaExpbmVQb2ludFk7XG5cbiAgICAgICAgeGEgPSBoTGluZVBvaW50ICYmIGhMaW5lUG9pbnQueGE7XG4gICAgICAgIHlhID0gaExpbmVQb2ludCAmJiBoTGluZVBvaW50LnlhO1xuICAgICAgICB2YXIgeVNuYXAgPSB5YS5zcGlrZXNuYXA7XG5cbiAgICAgICAgaWYoeVNuYXAgPT09ICdjdXJzb3InKSB7XG4gICAgICAgICAgICBoTGluZVBvaW50WCA9IGV2dC5wb2ludGVyWDtcbiAgICAgICAgICAgIGhMaW5lUG9pbnRZID0gZXZ0LnBvaW50ZXJZO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaExpbmVQb2ludFggPSB4YS5fb2Zmc2V0ICsgaExpbmVQb2ludC54O1xuICAgICAgICAgICAgaExpbmVQb2ludFkgPSB5YS5fb2Zmc2V0ICsgaExpbmVQb2ludC55O1xuICAgICAgICB9XG4gICAgICAgIHZhciBkZmx0SExpbmVDb2xvciA9IHRpbnljb2xvci5yZWFkYWJpbGl0eShoTGluZVBvaW50LmNvbG9yLCBjb250cmFzdENvbG9yKSA8IDEuNSA/XG4gICAgICAgICAgICBDb2xvci5jb250cmFzdChjb250cmFzdENvbG9yKSA6IGhMaW5lUG9pbnQuY29sb3I7XG4gICAgICAgIHZhciB5TW9kZSA9IHlhLnNwaWtlbW9kZTtcbiAgICAgICAgdmFyIHlUaGlja25lc3MgPSB5YS5zcGlrZXRoaWNrbmVzcztcbiAgICAgICAgdmFyIHlDb2xvciA9IHlhLnNwaWtlY29sb3IgfHwgZGZsdEhMaW5lQ29sb3I7XG4gICAgICAgIHZhciB5QkIgPSB5YS5fYm91bmRpbmdCb3g7XG4gICAgICAgIHZhciB4RWRnZSA9ICgoeUJCLmxlZnQgKyB5QkIucmlnaHQpIC8gMikgPCBoTGluZVBvaW50WCA/IHlCQi5yaWdodCA6IHlCQi5sZWZ0O1xuICAgICAgICB2YXIgeEJhc2UsIHhFbmRTcGlrZTtcblxuICAgICAgICBpZih5TW9kZS5pbmRleE9mKCd0b2F4aXMnKSAhPT0gLTEgfHwgeU1vZGUuaW5kZXhPZignYWNyb3NzJykgIT09IC0xKSB7XG4gICAgICAgICAgICBpZih5TW9kZS5pbmRleE9mKCd0b2F4aXMnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB4QmFzZSA9IHhFZGdlO1xuICAgICAgICAgICAgICAgIHhFbmRTcGlrZSA9IGhMaW5lUG9pbnRYO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoeU1vZGUuaW5kZXhPZignYWNyb3NzJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgeEJhc2UgPSB5YS5fY291bnRlclNwYW5bMF07XG4gICAgICAgICAgICAgICAgeEVuZFNwaWtlID0geWEuX2NvdW50ZXJTcGFuWzFdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGb3JlZ3JvdW5kIGhvcml6b250YWwgbGluZSAodG8geS1heGlzKVxuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydCgnbGluZScsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDE6IHhCYXNlLFxuICAgICAgICAgICAgICAgICAgICB4MjogeEVuZFNwaWtlLFxuICAgICAgICAgICAgICAgICAgICB5MTogaExpbmVQb2ludFksXG4gICAgICAgICAgICAgICAgICAgIHkyOiBoTGluZVBvaW50WSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IHlUaGlja25lc3MsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogeUNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAnc3Ryb2tlLWRhc2hhcnJheSc6IERyYXdpbmcuZGFzaFN0eWxlKHlhLnNwaWtlZGFzaCwgeVRoaWNrbmVzcylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuXG4gICAgICAgICAgICAvLyBCYWNrZ3JvdW5kIGhvcml6b250YWwgTGluZSAodG8geS1heGlzKVxuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydCgnbGluZScsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDE6IHhCYXNlLFxuICAgICAgICAgICAgICAgICAgICB4MjogeEVuZFNwaWtlLFxuICAgICAgICAgICAgICAgICAgICB5MTogaExpbmVQb2ludFksXG4gICAgICAgICAgICAgICAgICAgIHkyOiBoTGluZVBvaW50WSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IHlUaGlja25lc3MgKyAyLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2U6IGNvbnRyYXN0Q29sb3JcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFkgYXhpcyBtYXJrZXJcbiAgICAgICAgaWYoeU1vZGUuaW5kZXhPZignbWFya2VyJykgIT09IC0xKSB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0KCdjaXJjbGUnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGN4OiB4RWRnZSArICh5YS5zaWRlICE9PSAncmlnaHQnID8geVRoaWNrbmVzcyA6IC15VGhpY2tuZXNzKSxcbiAgICAgICAgICAgICAgICAgICAgY3k6IGhMaW5lUG9pbnRZLFxuICAgICAgICAgICAgICAgICAgICByOiB5VGhpY2tuZXNzLFxuICAgICAgICAgICAgICAgICAgICBmaWxsOiB5Q29sb3JcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHNob3dYKSB7XG4gICAgICAgIHZhciB2TGluZVBvaW50ID0gY2xvc2VzdFBvaW50cy52TGluZVBvaW50O1xuICAgICAgICB2YXIgdkxpbmVQb2ludFgsIHZMaW5lUG9pbnRZO1xuXG4gICAgICAgIHhhID0gdkxpbmVQb2ludCAmJiB2TGluZVBvaW50LnhhO1xuICAgICAgICB5YSA9IHZMaW5lUG9pbnQgJiYgdkxpbmVQb2ludC55YTtcbiAgICAgICAgdmFyIHhTbmFwID0geGEuc3Bpa2VzbmFwO1xuXG4gICAgICAgIGlmKHhTbmFwID09PSAnY3Vyc29yJykge1xuICAgICAgICAgICAgdkxpbmVQb2ludFggPSBldnQucG9pbnRlclg7XG4gICAgICAgICAgICB2TGluZVBvaW50WSA9IGV2dC5wb2ludGVyWTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZMaW5lUG9pbnRYID0geGEuX29mZnNldCArIHZMaW5lUG9pbnQueDtcbiAgICAgICAgICAgIHZMaW5lUG9pbnRZID0geWEuX29mZnNldCArIHZMaW5lUG9pbnQueTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGZsdFZMaW5lQ29sb3IgPSB0aW55Y29sb3IucmVhZGFiaWxpdHkodkxpbmVQb2ludC5jb2xvciwgY29udHJhc3RDb2xvcikgPCAxLjUgP1xuICAgICAgICAgICAgQ29sb3IuY29udHJhc3QoY29udHJhc3RDb2xvcikgOiB2TGluZVBvaW50LmNvbG9yO1xuICAgICAgICB2YXIgeE1vZGUgPSB4YS5zcGlrZW1vZGU7XG4gICAgICAgIHZhciB4VGhpY2tuZXNzID0geGEuc3Bpa2V0aGlja25lc3M7XG4gICAgICAgIHZhciB4Q29sb3IgPSB4YS5zcGlrZWNvbG9yIHx8IGRmbHRWTGluZUNvbG9yO1xuICAgICAgICB2YXIgeEJCID0geGEuX2JvdW5kaW5nQm94O1xuICAgICAgICB2YXIgeUVkZ2UgPSAoKHhCQi50b3AgKyB4QkIuYm90dG9tKSAvIDIpIDwgdkxpbmVQb2ludFkgPyB4QkIuYm90dG9tIDogeEJCLnRvcDtcbiAgICAgICAgdmFyIHlCYXNlLCB5RW5kU3Bpa2U7XG5cbiAgICAgICAgaWYoeE1vZGUuaW5kZXhPZigndG9heGlzJykgIT09IC0xIHx8IHhNb2RlLmluZGV4T2YoJ2Fjcm9zcycpICE9PSAtMSkge1xuICAgICAgICAgICAgaWYoeE1vZGUuaW5kZXhPZigndG9heGlzJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgeUJhc2UgPSB5RWRnZTtcbiAgICAgICAgICAgICAgICB5RW5kU3Bpa2UgPSB2TGluZVBvaW50WTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHhNb2RlLmluZGV4T2YoJ2Fjcm9zcycpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHlCYXNlID0geGEuX2NvdW50ZXJTcGFuWzBdO1xuICAgICAgICAgICAgICAgIHlFbmRTcGlrZSA9IHhhLl9jb3VudGVyU3BhblsxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRm9yZWdyb3VuZCB2ZXJ0aWNhbCBsaW5lICh0byB4LWF4aXMpXG4gICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0KCdsaW5lJywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB4MTogdkxpbmVQb2ludFgsXG4gICAgICAgICAgICAgICAgICAgIHgyOiB2TGluZVBvaW50WCxcbiAgICAgICAgICAgICAgICAgICAgeTE6IHlCYXNlLFxuICAgICAgICAgICAgICAgICAgICB5MjogeUVuZFNwaWtlLFxuICAgICAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogeFRoaWNrbmVzcyxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiB4Q29sb3IsXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2UtZGFzaGFycmF5JzogRHJhd2luZy5kYXNoU3R5bGUoeGEuc3Bpa2VkYXNoLCB4VGhpY2tuZXNzKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3NwaWtlbGluZScsIHRydWUpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2NyaXNwJywgdHJ1ZSk7XG5cbiAgICAgICAgICAgIC8vIEJhY2tncm91bmQgdmVydGljYWwgbGluZSAodG8geC1heGlzKVxuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydCgnbGluZScsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDE6IHZMaW5lUG9pbnRYLFxuICAgICAgICAgICAgICAgICAgICB4MjogdkxpbmVQb2ludFgsXG4gICAgICAgICAgICAgICAgICAgIHkxOiB5QmFzZSxcbiAgICAgICAgICAgICAgICAgICAgeTI6IHlFbmRTcGlrZSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IHhUaGlja25lc3MgKyAyLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2U6IGNvbnRyYXN0Q29sb3JcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gWCBheGlzIG1hcmtlclxuICAgICAgICBpZih4TW9kZS5pbmRleE9mKCdtYXJrZXInKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lci5pbnNlcnQoJ2NpcmNsZScsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgY3g6IHZMaW5lUG9pbnRYLFxuICAgICAgICAgICAgICAgICAgICBjeTogeUVkZ2UgLSAoeGEuc2lkZSAhPT0gJ3RvcCcgPyB4VGhpY2tuZXNzIDogLXhUaGlja25lc3MpLFxuICAgICAgICAgICAgICAgICAgICByOiB4VGhpY2tuZXNzLFxuICAgICAgICAgICAgICAgICAgICBmaWxsOiB4Q29sb3JcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gaG92ZXJDaGFuZ2VkKGdkLCBldnQsIG9sZGhvdmVyZGF0YSkge1xuICAgIC8vIGRvbid0IGVtaXQgYW55IGV2ZW50cyBpZiBub3RoaW5nIGNoYW5nZWRcbiAgICBpZighb2xkaG92ZXJkYXRhIHx8IG9sZGhvdmVyZGF0YS5sZW5ndGggIT09IGdkLl9ob3ZlcmRhdGEubGVuZ3RoKSByZXR1cm4gdHJ1ZTtcblxuICAgIGZvcih2YXIgaSA9IG9sZGhvdmVyZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICB2YXIgb2xkUHQgPSBvbGRob3ZlcmRhdGFbaV07XG4gICAgICAgIHZhciBuZXdQdCA9IGdkLl9ob3ZlcmRhdGFbaV07XG4gICAgICAgIGlmKG9sZFB0LmN1cnZlTnVtYmVyICE9PSBuZXdQdC5jdXJ2ZU51bWJlciB8fFxuICAgICAgICAgICAgICAgIFN0cmluZyhvbGRQdC5wb2ludE51bWJlcikgIT09IFN0cmluZyhuZXdQdC5wb2ludE51bWJlcikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gc3Bpa2VzQ2hhbmdlZChnZCwgb2xkc3Bpa2Vwb2ludHMpIHtcbiAgICAvLyBkb24ndCByZWxheW91dCB0aGUgcGxvdCBiZWNhdXNlIG9mIG5ldyBzcGlrZWxpbmVzIGlmIHNwaWtlbGluZXMgcG9pbnRzIGRpZG4ndCBjaGFuZ2VcbiAgICBpZighb2xkc3Bpa2Vwb2ludHMpIHJldHVybiB0cnVlO1xuICAgIGlmKG9sZHNwaWtlcG9pbnRzLnZMaW5lUG9pbnQgIT09IGdkLl9zcGlrZXBvaW50cy52TGluZVBvaW50IHx8XG4gICAgICAgIG9sZHNwaWtlcG9pbnRzLmhMaW5lUG9pbnQgIT09IGdkLl9zcGlrZXBvaW50cy5oTGluZVBvaW50XG4gICAgKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMoY29udEluLCBjb250T3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIGNvZXJjZSgnaG92ZXJsYWJlbC5iZ2NvbG9yJywgb3B0cy5iZ2NvbG9yKTtcbiAgICBjb2VyY2UoJ2hvdmVybGFiZWwuYm9yZGVyY29sb3InLCBvcHRzLmJvcmRlcmNvbG9yKTtcbiAgICBjb2VyY2UoJ2hvdmVybGFiZWwubmFtZWxlbmd0aCcsIG9wdHMubmFtZWxlbmd0aCk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnaG92ZXJsYWJlbC5mb250Jywgb3B0cy5mb250KTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi9kcmFnZWxlbWVudCcpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGhvdmVyTW9kdWxlID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnZngnLFxuXG4gICAgY29uc3RhbnRzOiByZXF1aXJlKCcuL2NvbnN0YW50cycpLFxuICAgIHNjaGVtYToge1xuICAgICAgICBsYXlvdXQ6IGxheW91dEF0dHJpYnV0ZXNcbiAgICB9LFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlcyxcblxuICAgIHN1cHBseUxheW91dEdsb2JhbERlZmF1bHRzOiByZXF1aXJlKCcuL2xheW91dF9nbG9iYWxfZGVmYXVsdHMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiByZXF1aXJlKCcuL2xheW91dF9kZWZhdWx0cycpLFxuXG4gICAgY2FsYzogcmVxdWlyZSgnLi9jYWxjJyksXG5cbiAgICBnZXREaXN0YW5jZUZ1bmN0aW9uOiBoZWxwZXJzLmdldERpc3RhbmNlRnVuY3Rpb24sXG4gICAgZ2V0Q2xvc2VzdDogaGVscGVycy5nZXRDbG9zZXN0LFxuICAgIGluYm94OiBoZWxwZXJzLmluYm94LFxuICAgIHF1YWRyYXR1cmU6IGhlbHBlcnMucXVhZHJhdHVyZSxcbiAgICBhcHBlbmRBcnJheVBvaW50VmFsdWU6IGhlbHBlcnMuYXBwZW5kQXJyYXlQb2ludFZhbHVlLFxuXG4gICAgY2FzdEhvdmVyT3B0aW9uOiBjYXN0SG92ZXJPcHRpb24sXG4gICAgY2FzdEhvdmVyaW5mbzogY2FzdEhvdmVyaW5mbyxcblxuICAgIGhvdmVyOiBob3Zlck1vZHVsZS5ob3ZlcixcbiAgICB1bmhvdmVyOiBkcmFnRWxlbWVudC51bmhvdmVyLFxuXG4gICAgbG9uZUhvdmVyOiBob3Zlck1vZHVsZS5sb25lSG92ZXIsXG4gICAgbXVsdGlIb3ZlcnM6IGhvdmVyTW9kdWxlLm11bHRpSG92ZXJzLFxuICAgIGxvbmVVbmhvdmVyOiBsb25lVW5ob3ZlcixcblxuICAgIGNsaWNrOiByZXF1aXJlKCcuL2NsaWNrJylcbn07XG5cbmZ1bmN0aW9uIGxvbmVVbmhvdmVyKGNvbnRhaW5lck9yU2VsZWN0aW9uKSB7XG4gICAgLy8gZHVjayB0eXBlIHdoZXRoZXIgdGhlIGFyZyBpcyBhIGQzIHNlbGVjdGlvbiBiZWNhdXNlIGllOSBkb2Vzbid0XG4gICAgLy8gaGFuZGxlIGluc3RhbmNlb2YgbGlrZSBtb2Rlcm4gYnJvd3NlcnMgZG8uXG4gICAgdmFyIHNlbGVjdGlvbiA9IExpYi5pc0QzU2VsZWN0aW9uKGNvbnRhaW5lck9yU2VsZWN0aW9uKSA/XG4gICAgICAgICAgICBjb250YWluZXJPclNlbGVjdGlvbiA6XG4gICAgICAgICAgICBkMy5zZWxlY3QoY29udGFpbmVyT3JTZWxlY3Rpb24pO1xuXG4gICAgc2VsZWN0aW9uLnNlbGVjdEFsbCgnZy5ob3ZlcnRleHQnKS5yZW1vdmUoKTtcbiAgICBzZWxlY3Rpb24uc2VsZWN0QWxsKCcuc3Bpa2VsaW5lJykucmVtb3ZlKCk7XG59XG5cbi8vIGhlbHBlcnMgZm9yIHRyYWNlcyB0aGF0IHVzZSBGeC5sb25lSG92ZXJcblxuZnVuY3Rpb24gY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgYXR0cikge1xuICAgIHJldHVybiBMaWIuY2FzdE9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdob3ZlcmxhYmVsLicgKyBhdHRyKTtcbn1cblxuZnVuY3Rpb24gY2FzdEhvdmVyaW5mbyh0cmFjZSwgZnVsbExheW91dCwgcHROdW1iZXIpIHtcbiAgICBmdW5jdGlvbiBfY29lcmNlKHZhbCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZUhvdmVyaW5mbyh7aG92ZXJpbmZvOiB2YWx9LCB7X21vZHVsZTogdHJhY2UuX21vZHVsZX0sIGZ1bGxMYXlvdXQpO1xuICAgIH1cblxuICAgIHJldHVybiBMaWIuY2FzdE9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdob3ZlcmluZm8nLCBfY29lcmNlKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKSh7XG4gICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICBcbn0pO1xuZm9udEF0dHJzLmZhbWlseS5kZmx0ID0gY29uc3RhbnRzLkhPVkVSRk9OVDtcbmZvbnRBdHRycy5zaXplLmRmbHQgPSBjb25zdGFudHMuSE9WRVJGT05UU0laRTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2xpY2ttb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIFxuICAgICAgICBmbGFnczogWydldmVudCcsICdzZWxlY3QnXSxcbiAgICAgICAgZGZsdDogJ2V2ZW50JyxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkcmFnbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnem9vbScsICdwYW4nLCAnc2VsZWN0JywgJ2xhc3NvJywgJ29yYml0JywgJ3R1cm50YWJsZSddLFxuICAgICAgICBkZmx0OiAnem9vbScsXG4gICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyd4JywgJ3knLCAnY2xvc2VzdCcsIGZhbHNlXSxcbiAgICAgICAgZWRpdFR5cGU6ICdtb2RlYmFyJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcmRpc3RhbmNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAtMSxcbiAgICAgICAgZGZsdDogMjAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwaWtlZGlzdGFuY2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICBtaW46IC0xLFxuICAgICAgICBkZmx0OiAyMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJsYWJlbDoge1xuICAgICAgICBiZ2NvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZvbnQ6IGZvbnRBdHRycyxcbiAgICAgICAgbmFtZWxlbmd0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICAgICAgbWluOiAtMSxcbiAgICAgICAgICAgIGRmbHQ6IDE1LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZSdcbiAgICB9LFxuICAgIHNlbGVjdGRpcmVjdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnaCcsICd2JywgJ2QnLCAnYW55J10sXG4gICAgICAgIGRmbHQ6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJ1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGNsaWNrbW9kZSA9IGNvZXJjZSgnY2xpY2ttb2RlJyk7XG5cbiAgICB2YXIgZHJhZ01vZGUgPSBjb2VyY2UoJ2RyYWdtb2RlJyk7XG4gICAgaWYoZHJhZ01vZGUgPT09ICdzZWxlY3QnKSBjb2VyY2UoJ3NlbGVjdGRpcmVjdGlvbicpO1xuXG4gICAgdmFyIGhvdmVybW9kZURmbHQ7XG4gICAgaWYobGF5b3V0T3V0Ll9oYXMoJ2NhcnRlc2lhbicpKSB7XG4gICAgICAgIGlmKGNsaWNrbW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xKSB7XG4gICAgICAgICAgICBob3Zlcm1vZGVEZmx0ID0gJ2Nsb3Nlc3QnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZmxhZyBmb3IgJ2hvcml6b250YWwnIHBsb3RzOlxuICAgICAgICAgICAgLy8gZGV0ZXJtaW5lcyB0aGUgc3RhdGUgb2YgdGhlIG1vZGUgYmFyICdjb21wYXJlJyBob3Zlcm1vZGUgYnV0dG9uXG4gICAgICAgICAgICBsYXlvdXRPdXQuX2lzSG9yaXogPSBpc0hvcml6KGZ1bGxEYXRhKTtcbiAgICAgICAgICAgIGhvdmVybW9kZURmbHQgPSBsYXlvdXRPdXQuX2lzSG9yaXogPyAneScgOiAneCc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBob3Zlcm1vZGVEZmx0ID0gJ2Nsb3Nlc3QnO1xuXG4gICAgdmFyIGhvdmVyTW9kZSA9IGNvZXJjZSgnaG92ZXJtb2RlJywgaG92ZXJtb2RlRGZsdCk7XG4gICAgaWYoaG92ZXJNb2RlKSB7XG4gICAgICAgIGNvZXJjZSgnaG92ZXJkaXN0YW5jZScpO1xuICAgICAgICBjb2VyY2UoJ3NwaWtlZGlzdGFuY2UnKTtcbiAgICB9XG5cbiAgICAvLyBpZiBvbmx5IG1hcGJveCBvciBnZW8gc3VicGxvdHMgaXMgcHJlc2VudCBvbiBncmFwaCxcbiAgICAvLyByZXNldCAnem9vbScgZHJhZ21vZGUgdG8gJ3BhbicgdW50aWwgJ3pvb20nIGlzIGltcGxlbWVudGVkLFxuICAgIC8vIHNvIHRoYXQgdGhlIGNvcnJlY3QgbW9kZWJhciBidXR0b24gaXMgYWN0aXZlXG4gICAgdmFyIGhhc01hcGJveCA9IGxheW91dE91dC5faGFzKCdtYXBib3gnKTtcbiAgICB2YXIgaGFzR2VvID0gbGF5b3V0T3V0Ll9oYXMoJ2dlbycpO1xuICAgIHZhciBsZW4gPSBsYXlvdXRPdXQuX2Jhc2VQbG90TW9kdWxlcy5sZW5ndGg7XG5cbiAgICBpZihsYXlvdXRPdXQuZHJhZ21vZGUgPT09ICd6b29tJyAmJiAoXG4gICAgICAgICgoaGFzTWFwYm94IHx8IGhhc0dlbykgJiYgbGVuID09PSAxKSB8fFxuICAgICAgICAoaGFzTWFwYm94ICYmIGhhc0dlbyAmJiBsZW4gPT09IDIpXG4gICAgKSkge1xuICAgICAgICBsYXlvdXRPdXQuZHJhZ21vZGUgPSAncGFuJztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpc0hvcml6KGZ1bGxEYXRhKSB7XG4gICAgdmFyIG91dCA9IHRydWU7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gIT09ICdoJykge1xuICAgICAgICAgICAgb3V0ID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuL2hvdmVybGFiZWxfZGVmYXVsdHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dEdsb2JhbERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXlvdXRJbiwgbGF5b3V0T3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgY29lcmNlKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBjb3VudGVyUmVnZXggPSByZXF1aXJlKCcuLi8uLi9saWIvcmVnZXgnKS5jb3VudGVyO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBjYXJ0ZXNpYW5JZFJlZ2V4ID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpLmlkUmVnZXg7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbnZhciBncmlkQXR0cnMgPSB7XG4gICAgcm93czoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcm93b3JkZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsndG9wIHRvIGJvdHRvbScsICdib3R0b20gdG8gdG9wJ10sXG4gICAgICAgIGRmbHQ6ICd0b3AgdG8gYm90dG9tJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29sdW1uczoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3VicGxvdHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBkaW1lbnNpb25zOiAyLFxuICAgICAgICBpdGVtczoge3ZhbFR5cGU6ICdlbnVtZXJhdGVkJywgdmFsdWVzOiBbY291bnRlclJlZ2V4KCd4eScpLnRvU3RyaW5nKCksICcnXSwgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhheGVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgZnJlZUxlbmd0aDogdHJ1ZSxcbiAgICAgICAgaXRlbXM6IHt2YWxUeXBlOiAnZW51bWVyYXRlZCcsIHZhbHVlczogW2NhcnRlc2lhbklkUmVnZXgueC50b1N0cmluZygpLCAnJ10sIGVkaXRUeXBlOiAncGxvdCd9LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YXhlczoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIGZyZWVMZW5ndGg6IHRydWUsXG4gICAgICAgIGl0ZW1zOiB7dmFsVHlwZTogJ2VudW1lcmF0ZWQnLCB2YWx1ZXM6IFtjYXJ0ZXNpYW5JZFJlZ2V4LnkudG9TdHJpbmcoKSwgJyddLCBlZGl0VHlwZTogJ3Bsb3QnfSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcGF0dGVybjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydpbmRlcGVuZGVudCcsICdjb3VwbGVkJ10sXG4gICAgICAgIGRmbHQ6ICdjb3VwbGVkJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkb21haW46IGRvbWFpbkF0dHJzKHtuYW1lOiAnZ3JpZCcsIGVkaXRUeXBlOiAncGxvdCcsIG5vR3JpZENlbGw6IHRydWV9LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIHhzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2JvdHRvbScsICdib3R0b20gcGxvdCcsICd0b3AgcGxvdCcsICd0b3AnXSxcbiAgICAgICAgZGZsdDogJ2JvdHRvbSBwbG90JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeXNpZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdsZWZ0IHBsb3QnLCAncmlnaHQgcGxvdCcsICdyaWdodCddLFxuICAgICAgICBkZmx0OiAnbGVmdCBwbG90JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdwbG90J1xufTtcblxuZnVuY3Rpb24gZ2V0QXhlcyhsYXlvdXQsIGdyaWQsIGF4TGV0dGVyKSB7XG4gICAgdmFyIGdyaWRWYWwgPSBncmlkW2F4TGV0dGVyICsgJ2F4ZXMnXTtcbiAgICB2YXIgc3Bsb21WYWwgPSBPYmplY3Qua2V5cygobGF5b3V0Ll9zcGxvbUF4ZXMgfHwge30pW2F4TGV0dGVyXSB8fCB7fSk7XG5cbiAgICBpZihBcnJheS5pc0FycmF5KGdyaWRWYWwpKSByZXR1cm4gZ3JpZFZhbDtcbiAgICBpZihzcGxvbVZhbC5sZW5ndGgpIHJldHVybiBzcGxvbVZhbDtcbn1cblxuLy8gdGhlIHNoYXBlIG9mIHRoZSBncmlkIC0gdGhpcyBuZWVkcyB0byBiZSBkb25lIEJFRk9SRSBzdXBwbHlEYXRhRGVmYXVsdHNcbi8vIHNvIHRoYXQgbm9uLXN1YnBsb3QgdHJhY2VzIGNhbiBwbGFjZSB0aGVtc2VsdmVzIGluIHRoZSBncmlkXG5mdW5jdGlvbiBzaXplRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBncmlkSW4gPSBsYXlvdXRJbi5ncmlkIHx8IHt9O1xuICAgIHZhciB4QXhlcyA9IGdldEF4ZXMobGF5b3V0T3V0LCBncmlkSW4sICd4Jyk7XG4gICAgdmFyIHlBeGVzID0gZ2V0QXhlcyhsYXlvdXRPdXQsIGdyaWRJbiwgJ3knKTtcblxuICAgIGlmKCFsYXlvdXRJbi5ncmlkICYmICF4QXhlcyAmJiAheUF4ZXMpIHJldHVybjtcblxuICAgIHZhciBoYXNTdWJwbG90R3JpZCA9IEFycmF5LmlzQXJyYXkoZ3JpZEluLnN1YnBsb3RzKSAmJiBBcnJheS5pc0FycmF5KGdyaWRJbi5zdWJwbG90c1swXSk7XG4gICAgdmFyIGhhc1hheGVzID0gQXJyYXkuaXNBcnJheSh4QXhlcyk7XG4gICAgdmFyIGhhc1lheGVzID0gQXJyYXkuaXNBcnJheSh5QXhlcyk7XG4gICAgdmFyIGlzU3Bsb21HZW5lcmF0ZWQgPSAoXG4gICAgICAgIGhhc1hheGVzICYmIHhBeGVzICE9PSBncmlkSW4ueGF4ZXMgJiZcbiAgICAgICAgaGFzWWF4ZXMgJiYgeUF4ZXMgIT09IGdyaWRJbi55YXhlc1xuICAgICk7XG5cbiAgICB2YXIgZGZsdFJvd3MsIGRmbHRDb2x1bW5zO1xuXG4gICAgaWYoaGFzU3VicGxvdEdyaWQpIHtcbiAgICAgICAgZGZsdFJvd3MgPSBncmlkSW4uc3VicGxvdHMubGVuZ3RoO1xuICAgICAgICBkZmx0Q29sdW1ucyA9IGdyaWRJbi5zdWJwbG90c1swXS5sZW5ndGg7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZihoYXNZYXhlcykgZGZsdFJvd3MgPSB5QXhlcy5sZW5ndGg7XG4gICAgICAgIGlmKGhhc1hheGVzKSBkZmx0Q29sdW1ucyA9IHhBeGVzLmxlbmd0aDtcbiAgICB9XG5cbiAgICB2YXIgZ3JpZE91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihsYXlvdXRPdXQsICdncmlkJyk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShncmlkSW4sIGdyaWRPdXQsIGdyaWRBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHJvd3MgPSBjb2VyY2UoJ3Jvd3MnLCBkZmx0Um93cyk7XG4gICAgdmFyIGNvbHVtbnMgPSBjb2VyY2UoJ2NvbHVtbnMnLCBkZmx0Q29sdW1ucyk7XG5cbiAgICBpZighKHJvd3MgKiBjb2x1bW5zID4gMSkpIHtcbiAgICAgICAgZGVsZXRlIGxheW91dE91dC5ncmlkO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYoIWhhc1N1YnBsb3RHcmlkICYmICFoYXNYYXhlcyAmJiAhaGFzWWF4ZXMpIHtcbiAgICAgICAgdmFyIHVzZURlZmF1bHRTdWJwbG90cyA9IGNvZXJjZSgncGF0dGVybicpID09PSAnaW5kZXBlbmRlbnQnO1xuICAgICAgICBpZih1c2VEZWZhdWx0U3VicGxvdHMpIGhhc1N1YnBsb3RHcmlkID0gdHJ1ZTtcbiAgICB9XG4gICAgZ3JpZE91dC5faGFzU3VicGxvdEdyaWQgPSBoYXNTdWJwbG90R3JpZDtcblxuICAgIHZhciByb3dPcmRlciA9IGNvZXJjZSgncm93b3JkZXInKTtcbiAgICB2YXIgcmV2ZXJzZWQgPSByb3dPcmRlciA9PT0gJ3RvcCB0byBib3R0b20nO1xuXG4gICAgdmFyIGRmbHRHYXBYID0gaGFzU3VicGxvdEdyaWQgPyAwLjIgOiAwLjE7XG4gICAgdmFyIGRmbHRHYXBZID0gaGFzU3VicGxvdEdyaWQgPyAwLjMgOiAwLjE7XG5cbiAgICB2YXIgZGZsdFNpZGVYLCBkZmx0U2lkZVk7XG4gICAgaWYoaXNTcGxvbUdlbmVyYXRlZCAmJiBsYXlvdXRPdXQuX3NwbG9tR3JpZERmbHQpIHtcbiAgICAgICAgZGZsdFNpZGVYID0gbGF5b3V0T3V0Ll9zcGxvbUdyaWREZmx0LnhzaWRlO1xuICAgICAgICBkZmx0U2lkZVkgPSBsYXlvdXRPdXQuX3NwbG9tR3JpZERmbHQueXNpZGU7XG4gICAgfVxuXG4gICAgZ3JpZE91dC5fZG9tYWlucyA9IHtcbiAgICAgICAgeDogZmlsbEdyaWRQb3NpdGlvbnMoJ3gnLCBjb2VyY2UsIGRmbHRHYXBYLCBkZmx0U2lkZVgsIGNvbHVtbnMpLFxuICAgICAgICB5OiBmaWxsR3JpZFBvc2l0aW9ucygneScsIGNvZXJjZSwgZGZsdEdhcFksIGRmbHRTaWRlWSwgcm93cywgcmV2ZXJzZWQpXG4gICAgfTtcbn1cblxuLy8gY29lcmNlIHggb3IgeSBzaXppbmcgYXR0cmlidXRlcyBhbmQgcmV0dXJuIGFuIGFycmF5IG9mIGRvbWFpbnMgZm9yIHRoaXMgZGlyZWN0aW9uXG5mdW5jdGlvbiBmaWxsR3JpZFBvc2l0aW9ucyhheExldHRlciwgY29lcmNlLCBkZmx0R2FwLCBkZmx0U2lkZSwgbGVuLCByZXZlcnNlZCkge1xuICAgIHZhciBkaXJHYXAgPSBjb2VyY2UoYXhMZXR0ZXIgKyAnZ2FwJywgZGZsdEdhcCk7XG4gICAgdmFyIGRvbWFpbiA9IGNvZXJjZSgnZG9tYWluLicgKyBheExldHRlcik7XG4gICAgY29lcmNlKGF4TGV0dGVyICsgJ3NpZGUnLCBkZmx0U2lkZSk7XG5cbiAgICB2YXIgb3V0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIHN0YXJ0ID0gZG9tYWluWzBdO1xuICAgIHZhciBzdGVwID0gKGRvbWFpblsxXSAtIHN0YXJ0KSAvIChsZW4gLSBkaXJHYXApO1xuICAgIHZhciBjZWxsRG9tYWluID0gc3RlcCAqICgxIC0gZGlyR2FwKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIGNlbGxTdGFydCA9IHN0YXJ0ICsgc3RlcCAqIGk7XG4gICAgICAgIG91dFtyZXZlcnNlZCA/IChsZW4gLSAxIC0gaSkgOiBpXSA9IFtjZWxsU3RhcnQsIGNlbGxTdGFydCArIGNlbGxEb21haW5dO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufVxuXG4vLyB0aGUgKGNhcnRlc2lhbikgY29udGVudHMgb2YgdGhlIGdyaWQgLSB0aGlzIG5lZWRzIHRvIGhhcHBlbiBBRlRFUiBzdXBwbHlEYXRhRGVmYXVsdHNcbi8vIHNvIHRoYXQgd2Uga25vdyB3aGF0IGNhcnRlc2lhbiBzdWJwbG90cyBhcmUgYXZhaWxhYmxlXG5mdW5jdGlvbiBjb250ZW50RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBncmlkT3V0ID0gbGF5b3V0T3V0LmdyaWQ7XG4gICAgLy8gbWFrZSBzdXJlIHdlIGdvdCB0byB0aGUgZW5kIG9mIGhhbmRsZUdyaWRTaXppbmdcbiAgICBpZighZ3JpZE91dCB8fCAhZ3JpZE91dC5fZG9tYWlucykgcmV0dXJuO1xuXG4gICAgdmFyIGdyaWRJbiA9IGxheW91dEluLmdyaWQgfHwge307XG4gICAgdmFyIHN1YnBsb3RzID0gbGF5b3V0T3V0Ll9zdWJwbG90cztcbiAgICB2YXIgaGFzU3VicGxvdEdyaWQgPSBncmlkT3V0Ll9oYXNTdWJwbG90R3JpZDtcbiAgICB2YXIgcm93cyA9IGdyaWRPdXQucm93cztcbiAgICB2YXIgY29sdW1ucyA9IGdyaWRPdXQuY29sdW1ucztcbiAgICB2YXIgdXNlRGVmYXVsdFN1YnBsb3RzID0gZ3JpZE91dC5wYXR0ZXJuID09PSAnaW5kZXBlbmRlbnQnO1xuXG4gICAgdmFyIGksIGosIHhJZCwgeUlkLCBzdWJwbG90SWQsIHN1YnBsb3RzT3V0LCB5UG9zO1xuXG4gICAgdmFyIGF4aXNNYXAgPSBncmlkT3V0Ll9heGlzTWFwID0ge307XG5cbiAgICBpZihoYXNTdWJwbG90R3JpZCkge1xuICAgICAgICB2YXIgc3VicGxvdHNJbiA9IGdyaWRJbi5zdWJwbG90cyB8fCBbXTtcbiAgICAgICAgc3VicGxvdHNPdXQgPSBncmlkT3V0LnN1YnBsb3RzID0gbmV3IEFycmF5KHJvd3MpO1xuICAgICAgICB2YXIgaW5kZXggPSAxO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHJvd3M7IGkrKykge1xuICAgICAgICAgICAgdmFyIHJvd091dCA9IHN1YnBsb3RzT3V0W2ldID0gbmV3IEFycmF5KGNvbHVtbnMpO1xuICAgICAgICAgICAgdmFyIHJvd0luID0gc3VicGxvdHNJbltpXSB8fCBbXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGNvbHVtbnM7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKHVzZURlZmF1bHRTdWJwbG90cykge1xuICAgICAgICAgICAgICAgICAgICBzdWJwbG90SWQgPSAoaW5kZXggPT09IDEpID8gJ3h5JyA6ICgneCcgKyBpbmRleCArICd5JyArIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBzdWJwbG90SWQgPSByb3dJbltqXTtcblxuICAgICAgICAgICAgICAgIHJvd091dFtqXSA9ICcnO1xuXG4gICAgICAgICAgICAgICAgaWYoc3VicGxvdHMuY2FydGVzaWFuLmluZGV4T2Yoc3VicGxvdElkKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgeVBvcyA9IHN1YnBsb3RJZC5pbmRleE9mKCd5Jyk7XG4gICAgICAgICAgICAgICAgICAgIHhJZCA9IHN1YnBsb3RJZC5zbGljZSgwLCB5UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgeUlkID0gc3VicGxvdElkLnNsaWNlKHlQb3MpO1xuICAgICAgICAgICAgICAgICAgICBpZigoYXhpc01hcFt4SWRdICE9PSB1bmRlZmluZWQgJiYgYXhpc01hcFt4SWRdICE9PSBqKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKGF4aXNNYXBbeUlkXSAhPT0gdW5kZWZpbmVkICYmIGF4aXNNYXBbeUlkXSAhPT0gaSlcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvd091dFtqXSA9IHN1YnBsb3RJZDtcbiAgICAgICAgICAgICAgICAgICAgYXhpc01hcFt4SWRdID0gajtcbiAgICAgICAgICAgICAgICAgICAgYXhpc01hcFt5SWRdID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciB4QXhlcyA9IGdldEF4ZXMobGF5b3V0T3V0LCBncmlkSW4sICd4Jyk7XG4gICAgICAgIHZhciB5QXhlcyA9IGdldEF4ZXMobGF5b3V0T3V0LCBncmlkSW4sICd5Jyk7XG4gICAgICAgIGdyaWRPdXQueGF4ZXMgPSBmaWxsR3JpZEF4ZXMoeEF4ZXMsIHN1YnBsb3RzLnhheGlzLCBjb2x1bW5zLCBheGlzTWFwLCAneCcpO1xuICAgICAgICBncmlkT3V0LnlheGVzID0gZmlsbEdyaWRBeGVzKHlBeGVzLCBzdWJwbG90cy55YXhpcywgcm93cywgYXhpc01hcCwgJ3knKTtcbiAgICB9XG5cbiAgICB2YXIgYW5jaG9ycyA9IGdyaWRPdXQuX2FuY2hvcnMgPSB7fTtcbiAgICB2YXIgcmV2ZXJzZWQgPSBncmlkT3V0LnJvd29yZGVyID09PSAndG9wIHRvIGJvdHRvbSc7XG5cbiAgICBmb3IodmFyIGF4aXNJZCBpbiBheGlzTWFwKSB7XG4gICAgICAgIHZhciBheExldHRlciA9IGF4aXNJZC5jaGFyQXQoMCk7XG4gICAgICAgIHZhciBzaWRlID0gZ3JpZE91dFtheExldHRlciArICdzaWRlJ107XG5cbiAgICAgICAgdmFyIGkwLCBpbmMsIGlGaW5hbDtcblxuICAgICAgICBpZihzaWRlLmxlbmd0aCA8IDgpIHtcbiAgICAgICAgICAgIC8vIGdyaWQgZWRnZSAtICBpZSBub3QgXCIqIHBsb3RcIiAtIG1ha2UgdGhlc2UgYXMgZnJlZSBheGVzXG4gICAgICAgICAgICAvLyBzaW5jZSB3ZSdyZSBub3QgZ3VhcmFudGVlZCB0byBoYXZlIGEgc3VicGxvdCB0aGVyZSBhdCBhbGxcbiAgICAgICAgICAgIGFuY2hvcnNbYXhpc0lkXSA9ICdmcmVlJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgIGlmKChzaWRlLmNoYXJBdCgwKSA9PT0gJ3QnKSA9PT0gcmV2ZXJzZWQpIHtcbiAgICAgICAgICAgICAgICBpMCA9IDA7XG4gICAgICAgICAgICAgICAgaW5jID0gMTtcbiAgICAgICAgICAgICAgICBpRmluYWwgPSByb3dzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaTAgPSByb3dzIC0gMTtcbiAgICAgICAgICAgICAgICBpbmMgPSAtMTtcbiAgICAgICAgICAgICAgICBpRmluYWwgPSAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGhhc1N1YnBsb3RHcmlkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IGF4aXNNYXBbYXhpc0lkXTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IGkwOyBpICE9PSBpRmluYWw7IGkgKz0gaW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YnBsb3RJZCA9IHN1YnBsb3RzT3V0W2ldW2NvbHVtbl07XG4gICAgICAgICAgICAgICAgICAgIGlmKCFzdWJwbG90SWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB5UG9zID0gc3VicGxvdElkLmluZGV4T2YoJ3knKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3VicGxvdElkLnNsaWNlKDAsIHlQb3MpID09PSBheGlzSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvcnNbYXhpc0lkXSA9IHN1YnBsb3RJZC5zbGljZSh5UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSBpMDsgaSAhPT0gaUZpbmFsOyBpICs9IGluYykge1xuICAgICAgICAgICAgICAgICAgICB5SWQgPSBncmlkT3V0LnlheGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZihzdWJwbG90cy5jYXJ0ZXNpYW4uaW5kZXhPZihheGlzSWQgKyB5SWQpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yc1theGlzSWRdID0geUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZigoc2lkZS5jaGFyQXQoMCkgPT09ICdsJykpIHtcbiAgICAgICAgICAgICAgICBpMCA9IDA7XG4gICAgICAgICAgICAgICAgaW5jID0gMTtcbiAgICAgICAgICAgICAgICBpRmluYWwgPSBjb2x1bW5zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaTAgPSBjb2x1bW5zIC0gMTtcbiAgICAgICAgICAgICAgICBpbmMgPSAtMTtcbiAgICAgICAgICAgICAgICBpRmluYWwgPSAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGhhc1N1YnBsb3RHcmlkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvdyA9IGF4aXNNYXBbYXhpc0lkXTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IGkwOyBpICE9PSBpRmluYWw7IGkgKz0gaW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YnBsb3RJZCA9IHN1YnBsb3RzT3V0W3Jvd11baV07XG4gICAgICAgICAgICAgICAgICAgIGlmKCFzdWJwbG90SWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB5UG9zID0gc3VicGxvdElkLmluZGV4T2YoJ3knKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3VicGxvdElkLnNsaWNlKHlQb3MpID09PSBheGlzSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvcnNbYXhpc0lkXSA9IHN1YnBsb3RJZC5zbGljZSgwLCB5UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSBpMDsgaSAhPT0gaUZpbmFsOyBpICs9IGluYykge1xuICAgICAgICAgICAgICAgICAgICB4SWQgPSBncmlkT3V0LnhheGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZihzdWJwbG90cy5jYXJ0ZXNpYW4uaW5kZXhPZih4SWQgKyBheGlzSWQpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yc1theGlzSWRdID0geElkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGZpbGxHcmlkQXhlcyhheGVzSW4sIGF4ZXNBbGxvd2VkLCBsZW4sIGF4aXNNYXAsIGF4TGV0dGVyKSB7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBpO1xuXG4gICAgZnVuY3Rpb24gZmlsbE9uZUF4aXMoaSwgYXhpc0lkKSB7XG4gICAgICAgIGlmKGF4ZXNBbGxvd2VkLmluZGV4T2YoYXhpc0lkKSAhPT0gLTEgJiYgYXhpc01hcFtheGlzSWRdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG91dFtpXSA9IGF4aXNJZDtcbiAgICAgICAgICAgIGF4aXNNYXBbYXhpc0lkXSA9IGk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBvdXRbaV0gPSAnJztcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KGF4ZXNJbikpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGZpbGxPbmVBeGlzKGksIGF4ZXNJbltpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIGRlZmF1bHQgYXhpcyBsaXN0IGlzIHRoZSBmaXJzdCBgbGVuYCBheGlzIGlkc1xuICAgICAgICBmaWxsT25lQXhpcygwLCBheExldHRlcik7XG4gICAgICAgIGZvcihpID0gMTsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBmaWxsT25lQXhpcyhpLCBheExldHRlciArIChpICsgMSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2dyaWQnLFxuXG4gICAgc2NoZW1hOiB7XG4gICAgICAgIGxheW91dDoge2dyaWQ6IGdyaWRBdHRyc31cbiAgICB9LFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogZ3JpZEF0dHJzLFxuICAgIHNpemVEZWZhdWx0czogc2l6ZURlZmF1bHRzLFxuICAgIGNvbnRlbnREZWZhdWx0czogY29udGVudERlZmF1bHRzXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FydGVzaWFuQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gdGVtcGxhdGVkQXJyYXkoJ2ltYWdlJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc291cmNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGF5ZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYmVsb3cnLCAnYWJvdmUnXSxcbiAgICAgICAgZGZsdDogJ2Fib3ZlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNpemV4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2l6ZXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzaXppbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZmlsbCcsICdjb250YWluJywgJ3N0cmV0Y2gnXSxcbiAgICAgICAgZGZsdDogJ2NvbnRhaW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBkZmx0OiAndG9wJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogJ3BhcGVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHlyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC55LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogJ3BhcGVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdydcbn0pO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIHRvTG9nUmFuZ2UgPSByZXF1aXJlKCcuLi8uLi9saWIvdG9fbG9nX3JhbmdlJyk7XG5cbi8qXG4gKiBjb252ZXJ0Q29vcmRzOiB3aGVuIGNvbnZlcnRpbmcgYW4gYXhpcyBiZXR3ZWVuIGxvZyBhbmQgbGluZWFyXG4gKiB5b3UgbmVlZCB0byBhbHRlciBhbnkgaW1hZ2VzIG9uIHRoYXQgYXhpcyB0byBrZWVwIHRoZW1cbiAqIHBvaW50aW5nIGF0IHRoZSBzYW1lIGRhdGEgcG9pbnQuXG4gKiBJbiB2Mi4wIHRoaXMgd2lsbCBiZWNvbWUgb2Jzb2xldGUgKG9yIHBlcmhhcHMgc2l6ZSB3aWxsIHN0aWxsIG5lZWQgY29udmVyc2lvbj8pXG4gKiB3ZSBjb252ZXJ0IHNpemUgYnkgZGVjbGFyaW5nIHRoYXQgdGhlIG1heGltdW0gZXh0ZW50ICppbiBkYXRhIHVuaXRzKiBzaG91bGQgYmVcbiAqIHRoZSBzYW1lLCBhc3N1bWluZyB0aGUgaW1hZ2UgaXMgYW5jaG9yZWQgYnkgaXRzIGNlbnRlciAoY291bGQgcmVtb3ZlIHRoYXQgcmVzdHJpY3Rpb25cbiAqIGlmIHdlIHRoaW5rIGl0J3MgaW1wb3J0YW50KSBldmVuIHRob3VnaCB0aGUgYWN0dWFsIGxlZnQgYW5kIHJpZ2h0IHZhbHVlcyB3aWxsIG5vdCBiZVxuICogcXVpdGUgdGhlIHNhbWUgc2luY2UgdGhlIHNjYWxlIGJlY29tZXMgbm9ubGluZWFyIChhbmQgY2VudHJhbCBhbmNob3IgbWVhbnMgdGhlIHBpeGVsXG4gKiBjZW50ZXIgb2YgdGhlIGltYWdlLCBub3QgdGhlIGRhdGEgdW5pdHMgY2VudGVyKVxuICpcbiAqIGdkOiB0aGUgcGxvdCBkaXZcbiAqIGF4OiB0aGUgYXhpcyBiZWluZyBjaGFuZ2VkXG4gKiBuZXdUeXBlOiB0aGUgdHlwZSBpdCdzIGdldHRpbmdcbiAqIGRvRXh0cmE6IGZ1bmN0aW9uKGF0dHIsIHZhbCkgZnJvbSBpbnNpZGUgcmVsYXlvdXQgdGhhdCBzZXRzIHRoZSBhdHRyaWJ1dGUuXG4gKiAgICAgVXNlIHRoaXMgdG8gbWFrZSB0aGUgY2hhbmdlcyBhcyBpdCdzIGF3YXJlIGlmIGFueSBvdGhlciBjaGFuZ2VzIGluIHRoZVxuICogICAgIHNhbWUgcmVsYXlvdXQgY2FsbCBzaG91bGQgb3ZlcnJpZGUgdGhpcyBjb252ZXJzaW9uLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbnZlcnRDb29yZHMoZ2QsIGF4LCBuZXdUeXBlLCBkb0V4dHJhKSB7XG4gICAgYXggPSBheCB8fCB7fTtcblxuICAgIHZhciB0b0xvZyA9IChuZXdUeXBlID09PSAnbG9nJykgJiYgKGF4LnR5cGUgPT09ICdsaW5lYXInKSxcbiAgICAgICAgZnJvbUxvZyA9IChuZXdUeXBlID09PSAnbGluZWFyJykgJiYgKGF4LnR5cGUgPT09ICdsb2cnKTtcblxuICAgIGlmKCEodG9Mb2cgfHwgZnJvbUxvZykpIHJldHVybjtcblxuICAgIHZhciBpbWFnZXMgPSBnZC5fZnVsbExheW91dC5pbWFnZXMsXG4gICAgICAgIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKSxcbiAgICAgICAgaW1hZ2UsXG4gICAgICAgIGF0dHJQcmVmaXg7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGltYWdlID0gaW1hZ2VzW2ldO1xuICAgICAgICBhdHRyUHJlZml4ID0gJ2ltYWdlc1snICsgaSArICddLic7XG5cbiAgICAgICAgaWYoaW1hZ2VbYXhMZXR0ZXIgKyAncmVmJ10gPT09IGF4Ll9pZCkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRQb3MgPSBpbWFnZVtheExldHRlcl0sXG4gICAgICAgICAgICAgICAgY3VycmVudFNpemUgPSBpbWFnZVsnc2l6ZScgKyBheExldHRlcl0sXG4gICAgICAgICAgICAgICAgbmV3UG9zID0gbnVsbCxcbiAgICAgICAgICAgICAgICBuZXdTaXplID0gbnVsbDtcblxuICAgICAgICAgICAgaWYodG9Mb2cpIHtcbiAgICAgICAgICAgICAgICBuZXdQb3MgPSB0b0xvZ1JhbmdlKGN1cnJlbnRQb3MsIGF4LnJhbmdlKTtcblxuICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIGludmVyc2Ugb2YgdGhlIGNvbnZlcnNpb24gd2UgZG8gaW4gZnJvbUxvZyBiZWxvd1xuICAgICAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIGNvbnZlcnNpb24gaXMgcmV2ZXJzaWJsZSAobm90aWNlIHRoZSBmcm9tTG9nIGNvbnZlcnNpb25cbiAgICAgICAgICAgICAgICAvLyBpcyBsaWtlIHNpbmgsIGFuZCB0aGlzIG9uZSBsb29rcyBsaWtlIGFyY3NpbmgpXG4gICAgICAgICAgICAgICAgdmFyIGR4ID0gY3VycmVudFNpemUgLyBNYXRoLnBvdygxMCwgbmV3UG9zKSAvIDI7XG4gICAgICAgICAgICAgICAgbmV3U2l6ZSA9IDIgKiBNYXRoLmxvZyhkeCArIE1hdGguc3FydCgxICsgZHggKiBkeCkpIC8gTWF0aC5MTjEwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zID0gTWF0aC5wb3coMTAsIGN1cnJlbnRQb3MpO1xuICAgICAgICAgICAgICAgIG5ld1NpemUgPSBuZXdQb3MgKiAoTWF0aC5wb3coMTAsIGN1cnJlbnRTaXplIC8gMikgLSBNYXRoLnBvdygxMCwgLWN1cnJlbnRTaXplIC8gMikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiBjb252ZXJzaW9uIGZhaWxlZCwgZGVsZXRlIHRoZSB2YWx1ZSBzbyBpdCBjYW4gZ2V0IGEgZGVmYXVsdCBsYXRlciBvblxuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhuZXdQb3MpKSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zID0gbnVsbDtcbiAgICAgICAgICAgICAgICBuZXdTaXplID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoIWlzTnVtZXJpYyhuZXdTaXplKSkgbmV3U2l6ZSA9IG51bGw7XG5cbiAgICAgICAgICAgIGRvRXh0cmEoYXR0clByZWZpeCArIGF4TGV0dGVyLCBuZXdQb3MpO1xuICAgICAgICAgICAgZG9FeHRyYShhdHRyUHJlZml4ICsgJ3NpemUnICsgYXhMZXR0ZXIsIG5ld1NpemUpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBuYW1lID0gJ2ltYWdlcyc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBvcHRzID0ge1xuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGltYWdlRGVmYXVsdHNcbiAgICB9O1xuXG4gICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBvcHRzKTtcbn07XG5cblxuZnVuY3Rpb24gaW1hZ2VEZWZhdWx0cyhpbWFnZUluLCBpbWFnZU91dCwgZnVsbExheW91dCkge1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoaW1hZ2VJbiwgaW1hZ2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBzb3VyY2UgPSBjb2VyY2UoJ3NvdXJjZScpO1xuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJywgISFzb3VyY2UpO1xuXG4gICAgaWYoIXZpc2libGUpIHJldHVybiBpbWFnZU91dDtcblxuICAgIGNvZXJjZSgnbGF5ZXInKTtcbiAgICBjb2VyY2UoJ3hhbmNob3InKTtcbiAgICBjb2VyY2UoJ3lhbmNob3InKTtcbiAgICBjb2VyY2UoJ3NpemV4Jyk7XG4gICAgY29lcmNlKCdzaXpleScpO1xuICAgIGNvZXJjZSgnc2l6aW5nJyk7XG4gICAgY29lcmNlKCdvcGFjaXR5Jyk7XG5cbiAgICB2YXIgZ2RNb2NrID0geyBfZnVsbExheW91dDogZnVsbExheW91dCB9LFxuICAgICAgICBheExldHRlcnMgPSBbJ3gnLCAneSddO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAvLyAncGFwZXInIGlzIHRoZSBmYWxsYmFjayBheHJlZlxuICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheExldHRlcnNbaV0sXG4gICAgICAgICAgICBheFJlZiA9IEF4ZXMuY29lcmNlUmVmKGltYWdlSW4sIGltYWdlT3V0LCBnZE1vY2ssIGF4TGV0dGVyLCAncGFwZXInKTtcblxuICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKGltYWdlT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF4TGV0dGVyLCAwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW1hZ2VPdXQ7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciB4bWxuc05hbWVzcGFjZXMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBpbWFnZURhdGFBYm92ZSA9IFtdLFxuICAgICAgICBpbWFnZURhdGFTdWJwbG90ID0ge30sXG4gICAgICAgIGltYWdlRGF0YUJlbG93ID0gW10sXG4gICAgICAgIHN1YnBsb3QsXG4gICAgICAgIGk7XG5cbiAgICAvLyBTb3J0IGludG8gdG9wLCBzdWJwbG90LCBhbmQgYm90dG9tIGxheWVyc1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxMYXlvdXQuaW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpbWcgPSBmdWxsTGF5b3V0LmltYWdlc1tpXTtcblxuICAgICAgICBpZihpbWcudmlzaWJsZSkge1xuICAgICAgICAgICAgaWYoaW1nLmxheWVyID09PSAnYmVsb3cnICYmIGltZy54cmVmICE9PSAncGFwZXInICYmIGltZy55cmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICAgICAgc3VicGxvdCA9IGltZy54cmVmICsgaW1nLnlyZWY7XG5cbiAgICAgICAgICAgICAgICB2YXIgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcblxuICAgICAgICAgICAgICAgIGlmKCFwbG90aW5mbykge1xuICAgICAgICAgICAgICAgICAgICAvLyBGYWxsIGJhY2sgdG8gX2ltYWdlTG93ZXJMYXllciBpbiBjYXNlIHRoZSByZXF1ZXN0ZWQgc3VicGxvdCBkb2Vzbid0IGV4aXN0LlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gaWYgeW91IHJlZmVyZW5jZSB0aGUgaW1hZ2UgdG8gYW4geCAvIHkgYXhpcyBjb21iaW5hdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyB0aGF0IGRvZXNuJ3QgaGF2ZSBhbnkgZGF0YSBvbiBpdCAoYW5kIGxheWVyIGlzIGJlbG93KVxuICAgICAgICAgICAgICAgICAgICBpbWFnZURhdGFCZWxvdy5wdXNoKGltZyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHBsb3RpbmZvLm1haW5wbG90KSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YnBsb3QgPSBwbG90aW5mby5tYWlucGxvdC5pZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZighaW1hZ2VEYXRhU3VicGxvdFtzdWJwbG90XSkge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZURhdGFTdWJwbG90W3N1YnBsb3RdID0gW107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGltYWdlRGF0YVN1YnBsb3Rbc3VicGxvdF0ucHVzaChpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGltZy5sYXllciA9PT0gJ2Fib3ZlJykge1xuICAgICAgICAgICAgICAgIGltYWdlRGF0YUFib3ZlLnB1c2goaW1nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhQmVsb3cucHVzaChpbWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICB2YXIgYW5jaG9ycyA9IHtcbiAgICAgICAgeDoge1xuICAgICAgICAgICAgbGVmdDogeyBzaXppbmc6ICd4TWluJywgb2Zmc2V0OiAwIH0sXG4gICAgICAgICAgICBjZW50ZXI6IHsgc2l6aW5nOiAneE1pZCcsIG9mZnNldDogLTEgLyAyIH0sXG4gICAgICAgICAgICByaWdodDogeyBzaXppbmc6ICd4TWF4Jywgb2Zmc2V0OiAtMSB9XG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHRvcDogeyBzaXppbmc6ICdZTWluJywgb2Zmc2V0OiAwIH0sXG4gICAgICAgICAgICBtaWRkbGU6IHsgc2l6aW5nOiAnWU1pZCcsIG9mZnNldDogLTEgLyAyIH0sXG4gICAgICAgICAgICBib3R0b206IHsgc2l6aW5nOiAnWU1heCcsIG9mZnNldDogLTEgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8gSW1hZ2VzIG11c3QgYmUgY29udmVydGVkIHRvIGRhdGFVUkwncyBmb3IgZXhwb3J0aW5nLlxuICAgIGZ1bmN0aW9uIHNldEltYWdlKGQpIHtcbiAgICAgICAgdmFyIHRoaXNJbWFnZSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBpZih0aGlzLmltZyAmJiB0aGlzLmltZy5zcmMgPT09IGQuc291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzSW1hZ2UuYXR0cigneG1sbnMnLCB4bWxuc05hbWVzcGFjZXMuc3ZnKTtcblxuICAgICAgICB2YXIgaW1hZ2VQcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuXG4gICAgICAgICAgICB2YXIgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgICB0aGlzLmltZyA9IGltZztcblxuICAgICAgICAgICAgLy8gSWYgbm90IHNldCwgYSBgdGFpbnRlZCBjYW52YXNgIGVycm9yIGlzIHRocm93blxuICAgICAgICAgICAgaW1nLnNldEF0dHJpYnV0ZSgnY3Jvc3NPcmlnaW4nLCAnYW5vbnltb3VzJyk7XG4gICAgICAgICAgICBpbWcub25lcnJvciA9IGVycm9ySGFuZGxlcjtcbiAgICAgICAgICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgY2FudmFzLndpZHRoID0gdGhpcy53aWR0aDtcbiAgICAgICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZSh0aGlzLCAwLCAwKTtcblxuICAgICAgICAgICAgICAgIHZhciBkYXRhVVJMID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG5cbiAgICAgICAgICAgICAgICB0aGlzSW1hZ2UuYXR0cigneGxpbms6aHJlZicsIGRhdGFVUkwpO1xuXG4gICAgICAgICAgICAgICAgLy8gcmVzb2x2ZSBwcm9taXNlIGluIG9ubG9hZCBoYW5kbGVyIGluc3RlYWQgb2Ygb24gJ2xvYWQnIHRvIHN1cHBvcnQgSUUxMVxuICAgICAgICAgICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTY4NVxuICAgICAgICAgICAgICAgIC8vIGZvciBtb3JlIGRldGFpbHNcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG5cbiAgICAgICAgICAgIHRoaXNJbWFnZS5vbignZXJyb3InLCBlcnJvckhhbmRsZXIpO1xuXG4gICAgICAgICAgICBpbWcuc3JjID0gZC5zb3VyY2U7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9ySGFuZGxlcigpIHtcbiAgICAgICAgICAgICAgICB0aGlzSW1hZ2UucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgICAgIGdkLl9wcm9taXNlcy5wdXNoKGltYWdlUHJvbWlzZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXBwbHlBdHRyaWJ1dGVzKGQpIHtcbiAgICAgICAgdmFyIHRoaXNJbWFnZSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAvLyBBeGVzIGlmIHNwZWNpZmllZFxuICAgICAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgZC54cmVmKSxcbiAgICAgICAgICAgIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIGQueXJlZik7XG5cbiAgICAgICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplLFxuICAgICAgICAgICAgd2lkdGggPSB4YSA/IE1hdGguYWJzKHhhLmwycChkLnNpemV4KSAtIHhhLmwycCgwKSkgOiBkLnNpemV4ICogc2l6ZS53LFxuICAgICAgICAgICAgaGVpZ2h0ID0geWEgPyBNYXRoLmFicyh5YS5sMnAoZC5zaXpleSkgLSB5YS5sMnAoMCkpIDogZC5zaXpleSAqIHNpemUuaDtcblxuICAgICAgICAvLyBPZmZzZXRzIGZvciBhbmNob3IgcG9zaXRpb25pbmdcbiAgICAgICAgdmFyIHhPZmZzZXQgPSB3aWR0aCAqIGFuY2hvcnMueFtkLnhhbmNob3JdLm9mZnNldCxcbiAgICAgICAgICAgIHlPZmZzZXQgPSBoZWlnaHQgKiBhbmNob3JzLnlbZC55YW5jaG9yXS5vZmZzZXQ7XG5cbiAgICAgICAgdmFyIHNpemluZyA9IGFuY2hvcnMueFtkLnhhbmNob3JdLnNpemluZyArIGFuY2hvcnMueVtkLnlhbmNob3JdLnNpemluZztcblxuICAgICAgICAvLyBGaW5hbCBwb3NpdGlvbnNcbiAgICAgICAgdmFyIHhQb3MgPSAoeGEgPyB4YS5yMnAoZC54KSArIHhhLl9vZmZzZXQgOiBkLnggKiBzaXplLncgKyBzaXplLmwpICsgeE9mZnNldCxcbiAgICAgICAgICAgIHlQb3MgPSAoeWEgPyB5YS5yMnAoZC55KSArIHlhLl9vZmZzZXQgOiBzaXplLmggLSBkLnkgKiBzaXplLmggKyBzaXplLnQpICsgeU9mZnNldDtcblxuXG4gICAgICAgIC8vIENvbnN0cnVjdCB0aGUgcHJvcGVyIGFzcGVjdFJhdGlvIGF0dHJpYnV0ZVxuICAgICAgICBzd2l0Y2goZC5zaXppbmcpIHtcbiAgICAgICAgICAgIGNhc2UgJ2ZpbGwnOlxuICAgICAgICAgICAgICAgIHNpemluZyArPSAnIHNsaWNlJztcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAnc3RyZXRjaCc6XG4gICAgICAgICAgICAgICAgc2l6aW5nID0gJ25vbmUnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpc0ltYWdlLmF0dHIoe1xuICAgICAgICAgICAgeDogeFBvcyxcbiAgICAgICAgICAgIHk6IHlQb3MsXG4gICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86IHNpemluZyxcbiAgICAgICAgICAgIG9wYWNpdHk6IGQub3BhY2l0eVxuICAgICAgICB9KTtcblxuXG4gICAgICAgIC8vIFNldCBwcm9wZXIgY2xpcHBpbmcgb24gaW1hZ2VzXG4gICAgICAgIHZhciB4SWQgPSB4YSA/IHhhLl9pZCA6ICcnLFxuICAgICAgICAgICAgeUlkID0geWEgPyB5YS5faWQgOiAnJyxcbiAgICAgICAgICAgIGNsaXBBeGVzID0geElkICsgeUlkO1xuXG4gICAgICAgIHRoaXNJbWFnZS5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgY2xpcEF4ZXMgP1xuICAgICAgICAgICAgKCdjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIGNsaXBBeGVzKSA6XG4gICAgICAgICAgICBudWxsXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdmFyIGltYWdlc0JlbG93ID0gZnVsbExheW91dC5faW1hZ2VMb3dlckxheWVyLnNlbGVjdEFsbCgnaW1hZ2UnKVxuICAgICAgICAgICAgLmRhdGEoaW1hZ2VEYXRhQmVsb3cpLFxuICAgICAgICBpbWFnZXNBYm92ZSA9IGZ1bGxMYXlvdXQuX2ltYWdlVXBwZXJMYXllci5zZWxlY3RBbGwoJ2ltYWdlJylcbiAgICAgICAgICAgIC5kYXRhKGltYWdlRGF0YUFib3ZlKTtcblxuICAgIGltYWdlc0JlbG93LmVudGVyKCkuYXBwZW5kKCdpbWFnZScpO1xuICAgIGltYWdlc0Fib3ZlLmVudGVyKCkuYXBwZW5kKCdpbWFnZScpO1xuXG4gICAgaW1hZ2VzQmVsb3cuZXhpdCgpLnJlbW92ZSgpO1xuICAgIGltYWdlc0Fib3ZlLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGltYWdlc0JlbG93LmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBzZXRJbWFnZS5iaW5kKHRoaXMpKGQpO1xuICAgICAgICBhcHBseUF0dHJpYnV0ZXMuYmluZCh0aGlzKShkKTtcbiAgICB9KTtcbiAgICBpbWFnZXNBYm92ZS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgc2V0SW1hZ2UuYmluZCh0aGlzKShkKTtcbiAgICAgICAgYXBwbHlBdHRyaWJ1dGVzLmJpbmQodGhpcykoZCk7XG4gICAgfSk7XG5cbiAgICB2YXIgYWxsU3VicGxvdHMgPSBPYmplY3Qua2V5cyhmdWxsTGF5b3V0Ll9wbG90cyk7XG4gICAgZm9yKGkgPSAwOyBpIDwgYWxsU3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3VicGxvdCA9IGFsbFN1YnBsb3RzW2ldO1xuICAgICAgICB2YXIgc3VicGxvdE9iaiA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuXG4gICAgICAgIC8vIGZpbHRlciBvdXQgb3ZlcmxhaWQgcGxvdHMgKHdoaWNoIGhhdmQgdGhlaXIgaW1hZ2VzIG9uIHRoZSBtYWluIHBsb3QpXG4gICAgICAgIC8vIGFuZCBnbDJkIHBsb3RzICh3aGljaCBkb24ndCBzdXBwb3J0IGJlbG93IGltYWdlcywgYXQgbGVhc3Qgbm90IHlldClcbiAgICAgICAgaWYoIXN1YnBsb3RPYmouaW1hZ2VsYXllcikgY29udGludWU7XG5cbiAgICAgICAgdmFyIGltYWdlc09uU3VicGxvdCA9IHN1YnBsb3RPYmouaW1hZ2VsYXllci5zZWxlY3RBbGwoJ2ltYWdlJylcbiAgICAgICAgICAgIC8vIGV2ZW4gaWYgdGhlcmUgYXJlIG5vIGltYWdlcyBvbiB0aGlzIHN1YnBsb3QsIHdlIG5lZWQgdG8gcnVuXG4gICAgICAgICAgICAvLyBlbnRlciBhbmQgZXhpdCBpbiBjYXNlIHRoZXJlIHdlcmUgcHJldmlvdXNseVxuICAgICAgICAgICAgLmRhdGEoaW1hZ2VEYXRhU3VicGxvdFtzdWJwbG90XSB8fCBbXSk7XG5cbiAgICAgICAgaW1hZ2VzT25TdWJwbG90LmVudGVyKCkuYXBwZW5kKCdpbWFnZScpO1xuICAgICAgICBpbWFnZXNPblN1YnBsb3QuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGltYWdlc09uU3VicGxvdC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHNldEltYWdlLmJpbmQodGhpcykoZCk7XG4gICAgICAgICAgICBhcHBseUF0dHJpYnV0ZXMuYmluZCh0aGlzKShkKTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2ltYWdlcycsXG5cbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuICAgIGluY2x1ZGVCYXNlUGxvdDogcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2luY2x1ZGVfY29tcG9uZW50cycpKCdpbWFnZXMnKSxcblxuICAgIGRyYXc6IHJlcXVpcmUoJy4vZHJhdycpLFxuXG4gICAgY29udmVydENvb3JkczogcmVxdWlyZSgnLi9jb252ZXJ0X2Nvb3JkcycpXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuLyoqXG4gKiBEZXRlcm1pbmUgdGhlIHBvc2l0aW9uIGFuY2hvciBwcm9wZXJ0eSBvZiB4L3kgeGFuY2hvci95YW5jaG9yIGNvbXBvbmVudHMuXG4gKlxuICogLSB2YWx1ZXMgPCAxLzMgYWxpZ24gdGhlIGxvdyBzaWRlIGF0IHRoYXQgZnJhY3Rpb24sXG4gKiAtIHZhbHVlcyBbMS8zLCAyLzNdIGFsaWduIHRoZSBjZW50ZXIgYXQgdGhhdCBmcmFjdGlvbixcbiAqIC0gdmFsdWVzID4gMi8zIGFsaWduIHRoZSByaWdodCBhdCB0aGF0IGZyYWN0aW9uLlxuICovXG5cbmV4cG9ydHMuaXNSaWdodEFuY2hvciA9IGZ1bmN0aW9uIGlzUmlnaHRBbmNob3Iob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIG9wdHMueGFuY2hvciA9PT0gJ3JpZ2h0JyB8fFxuICAgICAgICAob3B0cy54YW5jaG9yID09PSAnYXV0bycgJiYgb3B0cy54ID49IDIgLyAzKVxuICAgICk7XG59O1xuXG5leHBvcnRzLmlzQ2VudGVyQW5jaG9yID0gZnVuY3Rpb24gaXNDZW50ZXJBbmNob3Iob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIG9wdHMueGFuY2hvciA9PT0gJ2NlbnRlcicgfHxcbiAgICAgICAgKG9wdHMueGFuY2hvciA9PT0gJ2F1dG8nICYmIG9wdHMueCA+IDEgLyAzICYmIG9wdHMueCA8IDIgLyAzKVxuICAgICk7XG59O1xuXG5leHBvcnRzLmlzQm90dG9tQW5jaG9yID0gZnVuY3Rpb24gaXNCb3R0b21BbmNob3Iob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIG9wdHMueWFuY2hvciA9PT0gJ2JvdHRvbScgfHxcbiAgICAgICAgKG9wdHMueWFuY2hvciA9PT0gJ2F1dG8nICYmIG9wdHMueSA8PSAxIC8gMylcbiAgICApO1xufTtcblxuZXhwb3J0cy5pc01pZGRsZUFuY2hvciA9IGZ1bmN0aW9uIGlzTWlkZGxlQW5jaG9yKG9wdHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBvcHRzLnlhbmNob3IgPT09ICdtaWRkbGUnIHx8XG4gICAgICAgIChvcHRzLnlhbmNob3IgPT09ICdhdXRvJyAmJiBvcHRzLnkgPiAxIC8gMyAmJiBvcHRzLnkgPCAyIC8gMylcbiAgICApO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cnMgPSByZXF1aXJlKCcuLi9jb2xvci9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3YnLCAnaCddLFxuICAgICAgICBkZmx0OiAndicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdHJhY2VvcmRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydyZXZlcnNlZCcsICdncm91cGVkJ10sXG4gICAgICAgIGV4dHJhczogWydub3JtYWwnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFjZWdyb3VwZ2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMS4wMixcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnbGVnZW5kJ1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc2Nyb2xsQmFyV2lkdGg6IDYsXG4gICAgc2Nyb2xsQmFyTWluSGVpZ2h0OiAyMCxcbiAgICBzY3JvbGxCYXJDb2xvcjogJyM4MDhCQTQnLFxuICAgIHNjcm9sbEJhck1hcmdpbjogNCxcbiAgICB0ZXh0T2Zmc2V0WDogNDBcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlUGxvdExheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGxlZ2VuZERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgdmFyIGNvbnRhaW5lckluID0gbGF5b3V0SW4ubGVnZW5kIHx8IHt9O1xuXG4gICAgdmFyIGxlZ2VuZFRyYWNlQ291bnQgPSAwO1xuICAgIHZhciBsZWdlbmRSZWFsbHlIYXNBVHJhY2UgPSBmYWxzZTtcbiAgICB2YXIgZGVmYXVsdE9yZGVyID0gJ25vcm1hbCc7XG5cbiAgICB2YXIgZGVmYXVsdFgsIGRlZmF1bHRZLCBkZWZhdWx0WEFuY2hvciwgZGVmYXVsdFlBbmNob3I7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYoIXRyYWNlLnZpc2libGUpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIE5vdGUgdGhhdCB3ZSBleHBsaWNpdGx5IGNvdW50IGFueSB0cmFjZSB0aGF0IGlzIGVpdGhlciBzaG93biBvclxuICAgICAgICAvLyAqd291bGQqIGJlIHNob3duIGJ5IGRlZmF1bHQsIHRvd2FyZCB0aGUgdHdvIHRyYWNlcyB5b3UgbmVlZCB0b1xuICAgICAgICAvLyBlbnN1cmUgdGhlIGxlZ2VuZCBpcyBzaG93biBieSBkZWZhdWx0LCBiZWNhdXNlIHRoaXMgY2FuIHN0aWxsIGhlbHBcbiAgICAgICAgLy8gZGlzYW1iaWd1YXRlLlxuICAgICAgICBpZih0cmFjZS5zaG93bGVnZW5kIHx8IHRyYWNlLl9kZmx0U2hvd0xlZ2VuZCkge1xuICAgICAgICAgICAgbGVnZW5kVHJhY2VDb3VudCsrO1xuICAgICAgICAgICAgaWYodHJhY2Uuc2hvd2xlZ2VuZCkge1xuICAgICAgICAgICAgICAgIGxlZ2VuZFJlYWxseUhhc0FUcmFjZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgLy8gQWx3YXlzIHNob3cgdGhlIGxlZ2VuZCBieSBkZWZhdWx0IGlmIHRoZXJlJ3MgYSBwaWUsXG4gICAgICAgICAgICAgICAgLy8gb3IgaWYgdGhlcmUncyBvbmx5IG9uZSB0cmFjZSBidXQgaXQncyBleHBsaWNpdGx5IHNob3duXG4gICAgICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZScpIHx8XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLl9pbnB1dC5zaG93bGVnZW5kID09PSB0cnVlXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZFRyYWNlQ291bnQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZigoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JhcicpICYmIGxheW91dE91dC5iYXJtb2RlID09PSAnc3RhY2snKSB8fFxuICAgICAgICAgICAgICAgIFsndG9uZXh0eCcsICd0b25leHR5J10uaW5kZXhPZih0cmFjZS5maWxsKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGRlZmF1bHRPcmRlciA9IGhlbHBlcnMuaXNHcm91cGVkKHt0cmFjZW9yZGVyOiBkZWZhdWx0T3JkZXJ9KSA/XG4gICAgICAgICAgICAgICAgJ2dyb3VwZWQrcmV2ZXJzZWQnIDogJ3JldmVyc2VkJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRyYWNlLmxlZ2VuZGdyb3VwICE9PSB1bmRlZmluZWQgJiYgdHJhY2UubGVnZW5kZ3JvdXAgIT09ICcnKSB7XG4gICAgICAgICAgICBkZWZhdWx0T3JkZXIgPSBoZWxwZXJzLmlzUmV2ZXJzZWQoe3RyYWNlb3JkZXI6IGRlZmF1bHRPcmRlcn0pID9cbiAgICAgICAgICAgICAgICAncmV2ZXJzZWQrZ3JvdXBlZCcgOiAnZ3JvdXBlZCc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2hvd0xlZ2VuZCA9IExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCxcbiAgICAgICAgYmFzZVBsb3RMYXlvdXRBdHRyaWJ1dGVzLCAnc2hvd2xlZ2VuZCcsXG4gICAgICAgIGxlZ2VuZFJlYWxseUhhc0FUcmFjZSAmJiBsZWdlbmRUcmFjZUNvdW50ID4gMSk7XG5cbiAgICBpZihzaG93TGVnZW5kID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIGNvbnRhaW5lck91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihsYXlvdXRPdXQsICdsZWdlbmQnKTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnYmdjb2xvcicsIGxheW91dE91dC5wYXBlcl9iZ2NvbG9yKTtcbiAgICBjb2VyY2UoJ2JvcmRlcmNvbG9yJyk7XG4gICAgY29lcmNlKCdib3JkZXJ3aWR0aCcpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnLCBsYXlvdXRPdXQuZm9udCk7XG5cbiAgICBjb2VyY2UoJ29yaWVudGF0aW9uJyk7XG4gICAgaWYoY29udGFpbmVyT3V0Lm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgdmFyIHhheGlzID0gbGF5b3V0SW4ueGF4aXM7XG4gICAgICAgIGlmKHhheGlzICYmIHhheGlzLnJhbmdlc2xpZGVyICYmIHhheGlzLnJhbmdlc2xpZGVyLnZpc2libGUpIHtcbiAgICAgICAgICAgIGRlZmF1bHRYID0gMDtcbiAgICAgICAgICAgIGRlZmF1bHRYQW5jaG9yID0gJ2xlZnQnO1xuICAgICAgICAgICAgZGVmYXVsdFkgPSAxLjE7XG4gICAgICAgICAgICBkZWZhdWx0WUFuY2hvciA9ICdib3R0b20nO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZGVmYXVsdFggPSAwO1xuICAgICAgICAgICAgZGVmYXVsdFhBbmNob3IgPSAnbGVmdCc7XG4gICAgICAgICAgICBkZWZhdWx0WSA9IC0wLjE7XG4gICAgICAgICAgICBkZWZhdWx0WUFuY2hvciA9ICd0b3AnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29lcmNlKCd0cmFjZW9yZGVyJywgZGVmYXVsdE9yZGVyKTtcbiAgICBpZihoZWxwZXJzLmlzR3JvdXBlZChsYXlvdXRPdXQubGVnZW5kKSkgY29lcmNlKCd0cmFjZWdyb3VwZ2FwJyk7XG5cbiAgICBjb2VyY2UoJ3gnLCBkZWZhdWx0WCk7XG4gICAgY29lcmNlKCd4YW5jaG9yJywgZGVmYXVsdFhBbmNob3IpO1xuICAgIGNvZXJjZSgneScsIGRlZmF1bHRZKTtcbiAgICBjb2VyY2UoJ3lhbmNob3InLCBkZWZhdWx0WUFuY2hvcik7XG4gICAgTGliLm5vbmVPckFsbChjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBbJ3gnLCAneSddKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIEV2ZW50cyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9ldmVudHMnKTtcbnZhciBkcmFnRWxlbWVudCA9IHJlcXVpcmUoJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgaGFuZGxlQ2xpY2sgPSByZXF1aXJlKCcuL2hhbmRsZV9jbGljaycpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBpbnRlcmFjdENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnMnKTtcbnZhciBhbGlnbm1lbnRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50Jyk7XG52YXIgTElORV9TUEFDSU5HID0gYWxpZ25tZW50Q29uc3RhbnRzLkxJTkVfU1BBQ0lORztcbnZhciBGUk9NX1RMID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fVEw7XG52YXIgRlJPTV9CUiA9IGFsaWdubWVudENvbnN0YW50cy5GUk9NX0JSO1xuXG52YXIgZ2V0TGVnZW5kRGF0YSA9IHJlcXVpcmUoJy4vZ2V0X2xlZ2VuZF9kYXRhJyk7XG52YXIgc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xudmFyIGFuY2hvclV0aWxzID0gcmVxdWlyZSgnLi9hbmNob3JfdXRpbHMnKTtcblxudmFyIERCTENMSUNLREVMQVkgPSBpbnRlcmFjdENvbnN0YW50cy5EQkxDTElDS0RFTEFZO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjbGlwSWQgPSAnbGVnZW5kJyArIGZ1bGxMYXlvdXQuX3VpZDtcblxuICAgIGlmKCFmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIgfHwgIWdkLmNhbGNkYXRhKSByZXR1cm47XG5cbiAgICBpZighZ2QuX2xlZ2VuZE1vdXNlRG93blRpbWUpIGdkLl9sZWdlbmRNb3VzZURvd25UaW1lID0gMDtcblxuICAgIHZhciBvcHRzID0gZnVsbExheW91dC5sZWdlbmQ7XG4gICAgdmFyIGxlZ2VuZERhdGEgPSBmdWxsTGF5b3V0LnNob3dsZWdlbmQgJiYgZ2V0TGVnZW5kRGF0YShnZC5jYWxjZGF0YSwgb3B0cyk7XG4gICAgdmFyIGhpZGRlblNsaWNlcyA9IGZ1bGxMYXlvdXQuaGlkZGVubGFiZWxzIHx8IFtdO1xuXG4gICAgaWYoIWZ1bGxMYXlvdXQuc2hvd2xlZ2VuZCB8fCAhbGVnZW5kRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgZnVsbExheW91dC5faW5mb2xheWVyLnNlbGVjdEFsbCgnLmxlZ2VuZCcpLnJlbW92ZSgpO1xuICAgICAgICBmdWxsTGF5b3V0Ll90b3BkZWZzLnNlbGVjdCgnIycgKyBjbGlwSWQpLnJlbW92ZSgpO1xuXG4gICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdsZWdlbmQnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBtYXhMZW5ndGggPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZWdlbmREYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBsZWdlbmREYXRhW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IGxlZ2VuZERhdGFbaV1bal1bMF07XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBpdGVtLnRyYWNlO1xuICAgICAgICAgICAgdmFyIGlzUGllID0gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZScpO1xuICAgICAgICAgICAgdmFyIG5hbWUgPSBpc1BpZSA/IGl0ZW0ubGFiZWwgOiB0cmFjZS5uYW1lO1xuICAgICAgICAgICAgbWF4TGVuZ3RoID0gTWF0aC5tYXgobWF4TGVuZ3RoLCBuYW1lICYmIG5hbWUubGVuZ3RoIHx8IDApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGZpcnN0UmVuZGVyID0gZmFsc2U7XG4gICAgdmFyIGxlZ2VuZCA9IExpYi5lbnN1cmVTaW5nbGUoZnVsbExheW91dC5faW5mb2xheWVyLCAnZycsICdsZWdlbmQnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cigncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgICAgIGZpcnN0UmVuZGVyID0gdHJ1ZTtcbiAgICB9KTtcblxuICAgIHZhciBjbGlwUGF0aCA9IExpYi5lbnN1cmVTaW5nbGVCeUlkKGZ1bGxMYXlvdXQuX3RvcGRlZnMsICdjbGlwUGF0aCcsIGNsaXBJZCwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmFwcGVuZCgncmVjdCcpO1xuICAgIH0pO1xuXG4gICAgdmFyIGJnID0gTGliLmVuc3VyZVNpbmdsZShsZWdlbmQsICdyZWN0JywgJ2JnJywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJyk7XG4gICAgfSk7XG5cbiAgICBiZy5jYWxsKENvbG9yLnN0cm9rZSwgb3B0cy5ib3JkZXJjb2xvcilcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgb3B0cy5iZ2NvbG9yKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIG9wdHMuYm9yZGVyd2lkdGggKyAncHgnKTtcblxuICAgIHZhciBzY3JvbGxCb3ggPSBMaWIuZW5zdXJlU2luZ2xlKGxlZ2VuZCwgJ2cnLCAnc2Nyb2xsYm94Jyk7XG5cbiAgICB2YXIgc2Nyb2xsQmFyID0gTGliLmVuc3VyZVNpbmdsZShsZWdlbmQsICdyZWN0JywgJ3Njcm9sbGJhcicsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKHtcbiAgICAgICAgICAgIHJ4OiAyMCxcbiAgICAgICAgICAgIHJ5OiAzLFxuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgfSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgJyM4MDhCQTQnKTtcbiAgICB9KTtcblxuICAgIHZhciBncm91cHMgPSBzY3JvbGxCb3guc2VsZWN0QWxsKCdnLmdyb3VwcycpXG4gICAgICAgIC5kYXRhKGxlZ2VuZERhdGEpO1xuXG4gICAgZ3JvdXBzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyb3VwcycpO1xuXG4gICAgZ3JvdXBzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHZhciB0cmFjZXMgPSBncm91cHMuc2VsZWN0QWxsKCdnLnRyYWNlcycpXG4gICAgICAgIC5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICB0cmFjZXMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5hdHRyKCdjbGFzcycsICd0cmFjZXMnKTtcbiAgICB0cmFjZXMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdHJhY2VzLmNhbGwoc3R5bGUsIGdkKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZScpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhpZGRlblNsaWNlcy5pbmRleE9mKGRbMF0ubGFiZWwpICE9PSAtMSA/IDAuNSA6IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS52aXNpYmxlID09PSAnbGVnZW5kb25seScgPyAwLjUgOiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgIC5jYWxsKGRyYXdUZXh0cywgZ2QsIG1heExlbmd0aClcbiAgICAgICAgICAgICAgICAuY2FsbChzZXR1cFRyYWNlVG9nZ2xlLCBnZCk7XG4gICAgICAgIH0pO1xuXG4gICAgTGliLnN5bmNPckFzeW5jKFtQbG90cy5wcmV2aW91c1Byb21pc2VzLFxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmKGZpcnN0UmVuZGVyKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZUxlZ2VuZERpbWVuc2lvbnMoZ2QsIGdyb3VwcywgdHJhY2VzKTtcbiAgICAgICAgICAgICAgICBleHBhbmRNYXJnaW4oZ2QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQb3NpdGlvbiBhbmQgc2l6ZSB0aGUgbGVnZW5kXG4gICAgICAgICAgICB2YXIgbHhNaW4gPSAwLFxuICAgICAgICAgICAgICAgIGx4TWF4ID0gZnVsbExheW91dC53aWR0aCxcbiAgICAgICAgICAgICAgICBseU1pbiA9IDAsXG4gICAgICAgICAgICAgICAgbHlNYXggPSBmdWxsTGF5b3V0LmhlaWdodDtcblxuICAgICAgICAgICAgY29tcHV0ZUxlZ2VuZERpbWVuc2lvbnMoZ2QsIGdyb3VwcywgdHJhY2VzKTtcblxuICAgICAgICAgICAgaWYob3B0cy5faGVpZ2h0ID4gbHlNYXgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGVnZW5kIGRvZXNuJ3QgZml0IGluIHRoZSBwbG90IGFyZWEsXG4gICAgICAgICAgICAgICAgLy8gZG8gbm90IGV4cGFuZCB0aGUgdmVydGljYWwgbWFyZ2lucy5cbiAgICAgICAgICAgICAgICBleHBhbmRIb3Jpem9udGFsTWFyZ2luKGdkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXhwYW5kTWFyZ2luKGdkKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2Nyb2xsIHNlY3Rpb24gbXVzdCBiZSBleGVjdXRlZCBhZnRlciByZXBvc2l0aW9uTGVnZW5kLlxuICAgICAgICAgICAgLy8gSXQgcmVxdWlyZXMgdGhlIGxlZ2VuZCB3aWR0aCwgaGVpZ2h0LCB4IGFuZCB5IHRvIHBvc2l0aW9uIHRoZSBzY3JvbGxib3hcbiAgICAgICAgICAgIC8vIGFuZCB0aGVzZSB2YWx1ZXMgYXJlIG11dGF0ZWQgaW4gcmVwb3NpdGlvbkxlZ2VuZC5cbiAgICAgICAgICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemUsXG4gICAgICAgICAgICAgICAgbHggPSBncy5sICsgZ3MudyAqIG9wdHMueCxcbiAgICAgICAgICAgICAgICBseSA9IGdzLnQgKyBncy5oICogKDEgLSBvcHRzLnkpO1xuXG4gICAgICAgICAgICBpZihhbmNob3JVdGlscy5pc1JpZ2h0QW5jaG9yKG9wdHMpKSB7XG4gICAgICAgICAgICAgICAgbHggLT0gb3B0cy5fd2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKGFuY2hvclV0aWxzLmlzQ2VudGVyQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgICAgICAgICAgbHggLT0gb3B0cy5fd2lkdGggLyAyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihhbmNob3JVdGlscy5pc0JvdHRvbUFuY2hvcihvcHRzKSkge1xuICAgICAgICAgICAgICAgIGx5IC09IG9wdHMuX2hlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoYW5jaG9yVXRpbHMuaXNNaWRkbGVBbmNob3Iob3B0cykpIHtcbiAgICAgICAgICAgICAgICBseSAtPSBvcHRzLl9oZWlnaHQgLyAyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGxlZ2VuZCBsZWZ0IGFuZCByaWdodCBzaWRlcyBhcmUgdmlzaWJsZVxuICAgICAgICAgICAgdmFyIGxlZ2VuZFdpZHRoID0gb3B0cy5fd2lkdGgsXG4gICAgICAgICAgICAgICAgbGVnZW5kV2lkdGhNYXggPSBncy53O1xuXG4gICAgICAgICAgICBpZihsZWdlbmRXaWR0aCA+IGxlZ2VuZFdpZHRoTWF4KSB7XG4gICAgICAgICAgICAgICAgbHggPSBncy5sO1xuICAgICAgICAgICAgICAgIGxlZ2VuZFdpZHRoID0gbGVnZW5kV2lkdGhNYXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihseCArIGxlZ2VuZFdpZHRoID4gbHhNYXgpIGx4ID0gbHhNYXggLSBsZWdlbmRXaWR0aDtcbiAgICAgICAgICAgICAgICBpZihseCA8IGx4TWluKSBseCA9IGx4TWluO1xuICAgICAgICAgICAgICAgIGxlZ2VuZFdpZHRoID0gTWF0aC5taW4obHhNYXggLSBseCwgb3B0cy5fd2lkdGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGxlZ2VuZCB0b3AgYW5kIGJvdHRvbSBhcmUgdmlzaWJsZVxuICAgICAgICAgICAgLy8gKGxlZ2VuZHMgd2l0aCBhIHNjcm9sbCBiYXIgYXJlIG5vdCBhbGxvd2VkIHRvIHN0cmV0Y2ggYmV5b25kIHRoZSBleHRlbmRlZFxuICAgICAgICAgICAgLy8gbWFyZ2lucylcbiAgICAgICAgICAgIHZhciBsZWdlbmRIZWlnaHQgPSBvcHRzLl9oZWlnaHQsXG4gICAgICAgICAgICAgICAgbGVnZW5kSGVpZ2h0TWF4ID0gZ3MuaDtcblxuICAgICAgICAgICAgaWYobGVnZW5kSGVpZ2h0ID4gbGVnZW5kSGVpZ2h0TWF4KSB7XG4gICAgICAgICAgICAgICAgbHkgPSBncy50O1xuICAgICAgICAgICAgICAgIGxlZ2VuZEhlaWdodCA9IGxlZ2VuZEhlaWdodE1heDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmKGx5ICsgbGVnZW5kSGVpZ2h0ID4gbHlNYXgpIGx5ID0gbHlNYXggLSBsZWdlbmRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgaWYobHkgPCBseU1pbikgbHkgPSBseU1pbjtcbiAgICAgICAgICAgICAgICBsZWdlbmRIZWlnaHQgPSBNYXRoLm1pbihseU1heCAtIGx5LCBvcHRzLl9oZWlnaHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgc2l6ZSBhbmQgcG9zaXRpb24gb2YgYWxsIHRoZSBlbGVtZW50cyB0aGF0IG1ha2UgdXAgYSBsZWdlbmQ6XG4gICAgICAgICAgICAvLyBsZWdlbmQsIGJhY2tncm91bmQgYW5kIGJvcmRlciwgc2Nyb2xsIGJveCBhbmQgc2Nyb2xsIGJhclxuICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUobGVnZW5kLCBseCwgbHkpO1xuXG4gICAgICAgICAgICAvLyB0byBiZSBzYWZlLCByZW1vdmUgcHJldmlvdXMgbGlzdGVuZXJzXG4gICAgICAgICAgICBzY3JvbGxCYXIub24oJy5kcmFnJywgbnVsbCk7XG4gICAgICAgICAgICBsZWdlbmQub24oJ3doZWVsJywgbnVsbCk7XG5cbiAgICAgICAgICAgIGlmKG9wdHMuX2hlaWdodCA8PSBsZWdlbmRIZWlnaHQgfHwgZ2QuX2NvbnRleHQuc3RhdGljUGxvdCkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHNjcm9sbGJhciBzaG91bGQgbm90IGJlIHNob3duLlxuICAgICAgICAgICAgICAgIGJnLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogbGVnZW5kV2lkdGggLSBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGxlZ2VuZEhlaWdodCAtIG9wdHMuYm9yZGVyd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHg6IG9wdHMuYm9yZGVyd2lkdGggLyAyLFxuICAgICAgICAgICAgICAgICAgICB5OiBvcHRzLmJvcmRlcndpZHRoIC8gMlxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoc2Nyb2xsQm94LCAwLCAwKTtcblxuICAgICAgICAgICAgICAgIGNsaXBQYXRoLnNlbGVjdCgncmVjdCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogbGVnZW5kV2lkdGggLSAyICogb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBsZWdlbmRIZWlnaHQgLSAyICogb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeDogb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeTogb3B0cy5ib3JkZXJ3aWR0aFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHNjcm9sbEJveCwgY2xpcElkKTtcblxuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0UmVjdChzY3JvbGxCYXIsIDAsIDAsIDAsIDApO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRzLl9zY3JvbGxZO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbEJhckhlaWdodCA9IE1hdGgubWF4KGNvbnN0YW50cy5zY3JvbGxCYXJNaW5IZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZEhlaWdodCAqIGxlZ2VuZEhlaWdodCAvIG9wdHMuX2hlaWdodCk7XG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbEJhcllNYXggPSBsZWdlbmRIZWlnaHQgLVxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCYXJIZWlnaHQgLVxuICAgICAgICAgICAgICAgICAgICAyICogY29uc3RhbnRzLnNjcm9sbEJhck1hcmdpbjtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQm94WU1heCA9IG9wdHMuX2hlaWdodCAtIGxlZ2VuZEhlaWdodDtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsUmF0aW8gPSBzY3JvbGxCYXJZTWF4IC8gc2Nyb2xsQm94WU1heDtcblxuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxCb3hZID0gTWF0aC5taW4ob3B0cy5fc2Nyb2xsWSB8fCAwLCBzY3JvbGxCb3hZTWF4KTtcblxuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBiYWNrZ3JvdW5kIGFuZCBjbGlwLXBhdGggd2lkdGhcbiAgICAgICAgICAgICAgICAvLyBieSB0aGUgc2Nyb2xsYmFyIHdpZHRoIGFuZCBtYXJnaW5cbiAgICAgICAgICAgICAgICBiZy5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGxlZ2VuZFdpZHRoIC1cbiAgICAgICAgICAgICAgICAgICAgICAgIDIgKiBvcHRzLmJvcmRlcndpZHRoICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0YW50cy5zY3JvbGxCYXJXaWR0aCArXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyTWFyZ2luLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGxlZ2VuZEhlaWdodCAtIG9wdHMuYm9yZGVyd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHg6IG9wdHMuYm9yZGVyd2lkdGggLyAyLFxuICAgICAgICAgICAgICAgICAgICB5OiBvcHRzLmJvcmRlcndpZHRoIC8gMlxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBsZWdlbmRXaWR0aCAtXG4gICAgICAgICAgICAgICAgICAgICAgICAyICogb3B0cy5ib3JkZXJ3aWR0aCArXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyV2lkdGggK1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RhbnRzLnNjcm9sbEJhck1hcmdpbixcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBsZWdlbmRIZWlnaHQgLSAyICogb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeDogb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeTogb3B0cy5ib3JkZXJ3aWR0aCArIHNjcm9sbEJveFlcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0Q2xpcFVybChzY3JvbGxCb3gsIGNsaXBJZCk7XG5cbiAgICAgICAgICAgICAgICBzY3JvbGxIYW5kbGVyKHNjcm9sbEJveFksIHNjcm9sbEJhckhlaWdodCwgc2Nyb2xsUmF0aW8pO1xuXG4gICAgICAgICAgICAgICAgbGVnZW5kLm9uKCd3aGVlbCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCb3hZID0gTGliLmNvbnN0cmFpbihcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuX3Njcm9sbFkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQzLmV2ZW50LmRlbHRhWSAvIHNjcm9sbEJhcllNYXggKiBzY3JvbGxCb3hZTWF4LFxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgc2Nyb2xsQm94WU1heCk7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbEhhbmRsZXIoc2Nyb2xsQm94WSwgc2Nyb2xsQmFySGVpZ2h0LCBzY3JvbGxSYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNjcm9sbEJveFkgIT09IDAgJiYgc2Nyb2xsQm94WSAhPT0gc2Nyb2xsQm94WU1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50WTAsIHNjcm9sbEJveFkwO1xuXG4gICAgICAgICAgICAgICAgdmFyIGRyYWcgPSBkMy5iZWhhdmlvci5kcmFnKClcbiAgICAgICAgICAgICAgICAub24oJ2RyYWdzdGFydCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBldmVudFkwID0gZDMuZXZlbnQuc291cmNlRXZlbnQuY2xpZW50WTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsQm94WTAgPSBzY3JvbGxCb3hZO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm9uKCdkcmFnJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlID0gZDMuZXZlbnQuc291cmNlRXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKGUuYnV0dG9ucyA9PT0gMiB8fCBlLmN0cmxLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCb3hZID0gTGliLmNvbnN0cmFpbihcbiAgICAgICAgICAgICAgICAgICAgICAgIChlLmNsaWVudFkgLSBldmVudFkwKSAvIHNjcm9sbFJhdGlvICsgc2Nyb2xsQm94WTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAwLCBzY3JvbGxCb3hZTWF4KTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsSGFuZGxlcihzY3JvbGxCb3hZLCBzY3JvbGxCYXJIZWlnaHQsIHNjcm9sbFJhdGlvKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHNjcm9sbEJhci5jYWxsKGRyYWcpO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHNjcm9sbEhhbmRsZXIoc2Nyb2xsQm94WSwgc2Nyb2xsQmFySGVpZ2h0LCBzY3JvbGxSYXRpbykge1xuICAgICAgICAgICAgICAgIG9wdHMuX3Njcm9sbFkgPSBnZC5fZnVsbExheW91dC5sZWdlbmQuX3Njcm9sbFkgPSBzY3JvbGxCb3hZO1xuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHNjcm9sbEJveCwgMCwgLXNjcm9sbEJveFkpO1xuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5zZXRSZWN0KFxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCYXIsXG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyTWFyZ2luICsgc2Nyb2xsQm94WSAqIHNjcm9sbFJhdGlvLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbEJhckhlaWdodFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHk6IG9wdHMuYm9yZGVyd2lkdGggKyBzY3JvbGxCb3hZXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGdkLl9jb250ZXh0LmVkaXRzLmxlZ2VuZFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhmLCB5ZiwgeDAsIHkwO1xuXG4gICAgICAgICAgICAgICAgbGVnZW5kLmNsYXNzZWQoJ2N1cnNvci1tb3ZlJywgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogbGVnZW5kLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKGxlZ2VuZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHgwID0gdHJhbnNmb3JtLng7XG4gICAgICAgICAgICAgICAgICAgICAgICB5MCA9IHRyYW5zZm9ybS55O1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1ggPSB4MCArIGR4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1kgPSB5MCArIGR5O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShsZWdlbmQsIG5ld1gsIG5ld1kpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB4ZiA9IGRyYWdFbGVtZW50LmFsaWduKG5ld1gsIDAsIGdzLmwsIGdzLmwgKyBncy53LCBvcHRzLnhhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgeWYgPSBkcmFnRWxlbWVudC5hbGlnbihuZXdZLCAwLCBncy50ICsgZ3MuaCwgZ3MudCwgb3B0cy55YW5jaG9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZG9uZUZuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHhmICE9PSB1bmRlZmluZWQgJiYgeWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIHsnbGVnZW5kLngnOiB4ZiwgJ2xlZ2VuZC55JzogeWZ9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgY2xpY2tGbjogZnVuY3Rpb24obnVtQ2xpY2tzLCBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2xpY2tlZFRyYWNlID0gZnVsbExheW91dC5faW5mb2xheWVyLnNlbGVjdEFsbCgnZy50cmFjZXMnKS5maWx0ZXIoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuY2xpZW50WCA+PSBiYm94LmxlZnQgJiYgZS5jbGllbnRYIDw9IGJib3gucmlnaHQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5jbGllbnRZID49IGJib3gudG9wICYmIGUuY2xpZW50WSA8PSBiYm94LmJvdHRvbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGNsaWNrZWRUcmFjZS5zaXplKCkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpY2tPckRvdWJsZUNsaWNrKGdkLCBsZWdlbmQsIGNsaWNrZWRUcmFjZSwgbnVtQ2xpY2tzLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XSwgZ2QpO1xufTtcblxuZnVuY3Rpb24gY2xpY2tPckRvdWJsZUNsaWNrKGdkLCBsZWdlbmQsIGxlZ2VuZEl0ZW0sIG51bUNsaWNrcywgZXZ0KSB7XG4gICAgdmFyIHRyYWNlID0gbGVnZW5kSXRlbS5kYXRhKClbMF1bMF0udHJhY2U7XG5cbiAgICB2YXIgZXZ0RGF0YSA9IHtcbiAgICAgICAgZXZlbnQ6IGV2dCxcbiAgICAgICAgbm9kZTogbGVnZW5kSXRlbS5ub2RlKCksXG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgZXhwYW5kZWRJbmRleDogdHJhY2UuX2V4cGFuZGVkSW5kZXgsXG4gICAgICAgIGRhdGE6IGdkLmRhdGEsXG4gICAgICAgIGxheW91dDogZ2QubGF5b3V0LFxuICAgICAgICBmcmFtZXM6IGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVzLFxuICAgICAgICBjb25maWc6IGdkLl9jb250ZXh0LFxuICAgICAgICBmdWxsRGF0YTogZ2QuX2Z1bGxEYXRhLFxuICAgICAgICBmdWxsTGF5b3V0OiBnZC5fZnVsbExheW91dFxuICAgIH07XG5cbiAgICBpZih0cmFjZS5fZ3JvdXApIHtcbiAgICAgICAgZXZ0RGF0YS5ncm91cCA9IHRyYWNlLl9ncm91cDtcbiAgICB9XG4gICAgaWYodHJhY2UudHlwZSA9PT0gJ3BpZScpIHtcbiAgICAgICAgZXZ0RGF0YS5sYWJlbCA9IGxlZ2VuZEl0ZW0uZGF0dW0oKVswXS5sYWJlbDtcbiAgICB9XG5cbiAgICB2YXIgY2xpY2tWYWwgPSBFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfbGVnZW5kY2xpY2snLCBldnREYXRhKTtcbiAgICBpZihjbGlja1ZhbCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIGlmKG51bUNsaWNrcyA9PT0gMSkge1xuICAgICAgICBsZWdlbmQuX2NsaWNrVGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBoYW5kbGVDbGljayhsZWdlbmRJdGVtLCBnZCwgbnVtQ2xpY2tzKTtcbiAgICAgICAgfSwgREJMQ0xJQ0tERUxBWSk7XG4gICAgfVxuICAgIGVsc2UgaWYobnVtQ2xpY2tzID09PSAyKSB7XG4gICAgICAgIGlmKGxlZ2VuZC5fY2xpY2tUaW1lb3V0KSBjbGVhclRpbWVvdXQobGVnZW5kLl9jbGlja1RpbWVvdXQpO1xuICAgICAgICBnZC5fbGVnZW5kTW91c2VEb3duVGltZSA9IDA7XG5cbiAgICAgICAgdmFyIGRibENsaWNrVmFsID0gRXZlbnRzLnRyaWdnZXJIYW5kbGVyKGdkLCAncGxvdGx5X2xlZ2VuZGRvdWJsZWNsaWNrJywgZXZ0RGF0YSk7XG4gICAgICAgIGlmKGRibENsaWNrVmFsICE9PSBmYWxzZSkgaGFuZGxlQ2xpY2sobGVnZW5kSXRlbSwgZ2QsIG51bUNsaWNrcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3VGV4dHMoZywgZ2QsIG1heExlbmd0aCkge1xuICAgIHZhciBsZWdlbmRJdGVtID0gZy5kYXRhKClbMF1bMF07XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdHJhY2UgPSBsZWdlbmRJdGVtLnRyYWNlO1xuICAgIHZhciBpc1BpZSA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdwaWUnKTtcbiAgICB2YXIgdHJhY2VJbmRleCA9IHRyYWNlLmluZGV4O1xuICAgIHZhciBuYW1lID0gaXNQaWUgPyBsZWdlbmRJdGVtLmxhYmVsIDogdHJhY2UubmFtZTtcbiAgICB2YXIgaXNFZGl0YWJsZSA9IGdkLl9jb250ZXh0LmVkaXRzLmxlZ2VuZFRleHQgJiYgIWlzUGllO1xuXG4gICAgdmFyIHRleHRFbCA9IExpYi5lbnN1cmVTaW5nbGUoZywgJ3RleHQnLCAnbGVnZW5kdGV4dCcpO1xuXG4gICAgdGV4dEVsLmF0dHIoJ3RleHQtYW5jaG9yJywgJ3N0YXJ0JylcbiAgICAgICAgLmNsYXNzZWQoJ3VzZXItc2VsZWN0LW5vbmUnLCB0cnVlKVxuICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIGZ1bGxMYXlvdXQubGVnZW5kLmZvbnQpXG4gICAgICAgIC50ZXh0KGlzRWRpdGFibGUgPyBlbnN1cmVMZW5ndGgobmFtZSwgbWF4TGVuZ3RoKSA6IG5hbWUpO1xuXG4gICAgc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCh0ZXh0RWwsIGNvbnN0YW50cy50ZXh0T2Zmc2V0WCwgMCk7XG5cbiAgICBmdW5jdGlvbiB0ZXh0TGF5b3V0KHMpIHtcbiAgICAgICAgc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucyhzLCBnZCwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb21wdXRlVGV4dERpbWVuc2lvbnMoZywgZ2QpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihpc0VkaXRhYmxlKSB7XG4gICAgICAgIHRleHRFbC5jYWxsKHN2Z1RleHRVdGlscy5tYWtlRWRpdGFibGUsIHtnZDogZ2QsIHRleHQ6IG5hbWV9KVxuICAgICAgICAgICAgLmNhbGwodGV4dExheW91dClcbiAgICAgICAgICAgIC5vbignZWRpdCcsIGZ1bmN0aW9uKG5ld05hbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQoZW5zdXJlTGVuZ3RoKG5ld05hbWUsIG1heExlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKHRleHRMYXlvdXQpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZ1bGxJbnB1dCA9IGxlZ2VuZEl0ZW0udHJhY2UuX2Z1bGxJbnB1dCB8fCB7fTtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRlID0ge307XG5cbiAgICAgICAgICAgICAgICBpZihSZWdpc3RyeS5oYXNUcmFuc2Zvcm0oZnVsbElucHV0LCAnZ3JvdXBieScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBncm91cGJ5SW5kaWNlcyA9IFJlZ2lzdHJ5LmdldFRyYW5zZm9ybUluZGljZXMoZnVsbElucHV0LCAnZ3JvdXBieScpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBncm91cGJ5SW5kaWNlc1tncm91cGJ5SW5kaWNlcy5sZW5ndGggLSAxXTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIga2NvbnQgPSBMaWIua2V5ZWRDb250YWluZXIoZnVsbElucHV0LCAndHJhbnNmb3Jtc1snICsgaW5kZXggKyAnXS5zdHlsZXMnLCAndGFyZ2V0JywgJ3ZhbHVlLm5hbWUnKTtcblxuICAgICAgICAgICAgICAgICAgICBrY29udC5zZXQobGVnZW5kSXRlbS50cmFjZS5fZ3JvdXAsIG5ld05hbWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZSA9IGtjb250LmNvbnN0cnVjdFVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZS5uYW1lID0gbmV3TmFtZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncmVzdHlsZScsIGdkLCB1cGRhdGUsIHRyYWNlSW5kZXgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dExheW91dCh0ZXh0RWwpO1xuICAgIH1cbn1cblxuLypcbiAqIE1ha2Ugc3VyZSB3ZSBoYXZlIGEgcmVhc29uYWJseSBjbGlja2FibGUgcmVnaW9uLlxuICogSWYgdGhpcyBzdHJpbmcgaXMgbWlzc2luZyBvciB2ZXJ5IHNob3J0LCBwYWQgaXQgd2l0aCBzcGFjZXMgb3V0IHRvIGF0IGxlYXN0XG4gKiA0IGNoYXJhY3RlcnMsIHVwIHRvIHRoZSBtYXggbGVuZ3RoIG9mIG90aGVyIGxhYmVscywgb24gdGhlIGFzc3VtcHRpb24gdGhhdFxuICogbW9zdCBjaGFyYWN0ZXJzIGFyZSB3aWRlciB0aGFuIHNwYWNlcyBzbyBhIHN0cmluZyBvZiBzcGFjZXMgd2lsbCB1c3VhbGx5IGJlXG4gKiBubyB3aWRlciB0aGFuIHRoZSByZWFsIGxhYmVscy5cbiAqL1xuZnVuY3Rpb24gZW5zdXJlTGVuZ3RoKHN0ciwgbWF4TGVuZ3RoKSB7XG4gICAgdmFyIHRhcmdldExlbmd0aCA9IE1hdGgubWF4KDQsIG1heExlbmd0aCk7XG4gICAgaWYoc3RyICYmIHN0ci50cmltKCkubGVuZ3RoID49IHRhcmdldExlbmd0aCAvIDIpIHJldHVybiBzdHI7XG4gICAgc3RyID0gc3RyIHx8ICcnO1xuICAgIGZvcih2YXIgaSA9IHRhcmdldExlbmd0aCAtIHN0ci5sZW5ndGg7IGkgPiAwOyBpLS0pIHN0ciArPSAnICc7XG4gICAgcmV0dXJuIHN0cjtcbn1cblxuZnVuY3Rpb24gc2V0dXBUcmFjZVRvZ2dsZShnLCBnZCkge1xuICAgIHZhciBuZXdNb3VzZURvd25UaW1lLFxuICAgICAgICBudW1DbGlja3MgPSAxO1xuXG4gICAgdmFyIHRyYWNlVG9nZ2xlID0gTGliLmVuc3VyZVNpbmdsZShnLCAncmVjdCcsICdsZWdlbmR0b2dnbGUnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuc3R5bGUoJ2N1cnNvcicsICdwb2ludGVyJylcbiAgICAgICAgICAgIC5hdHRyKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgJ3JnYmEoMCwwLDAsMCknKTtcbiAgICB9KTtcblxuICAgIHRyYWNlVG9nZ2xlLm9uKCdtb3VzZWRvd24nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgbmV3TW91c2VEb3duVGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG4gICAgICAgIGlmKG5ld01vdXNlRG93blRpbWUgLSBnZC5fbGVnZW5kTW91c2VEb3duVGltZSA8IERCTENMSUNLREVMQVkpIHtcbiAgICAgICAgICAgIC8vIGluIGEgY2xpY2sgdHJhaW5cbiAgICAgICAgICAgIG51bUNsaWNrcyArPSAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gbmV3IGNsaWNrIHRyYWluXG4gICAgICAgICAgICBudW1DbGlja3MgPSAxO1xuICAgICAgICAgICAgZ2QuX2xlZ2VuZE1vdXNlRG93blRpbWUgPSBuZXdNb3VzZURvd25UaW1lO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgdHJhY2VUb2dnbGUub24oJ21vdXNldXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYoZ2QuX2RyYWdnZWQgfHwgZ2QuX2VkaXRpbmcpIHJldHVybjtcbiAgICAgICAgdmFyIGxlZ2VuZCA9IGdkLl9mdWxsTGF5b3V0LmxlZ2VuZDtcblxuICAgICAgICBpZigobmV3IERhdGUoKSkuZ2V0VGltZSgpIC0gZ2QuX2xlZ2VuZE1vdXNlRG93blRpbWUgPiBEQkxDTElDS0RFTEFZKSB7XG4gICAgICAgICAgICBudW1DbGlja3MgPSBNYXRoLm1heChudW1DbGlja3MgLSAxLCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsaWNrT3JEb3VibGVDbGljayhnZCwgbGVnZW5kLCBnLCBudW1DbGlja3MsIGQzLmV2ZW50KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZVRleHREaW1lbnNpb25zKGcsIGdkKSB7XG4gICAgdmFyIGxlZ2VuZEl0ZW0gPSBnLmRhdGEoKVswXVswXTtcblxuICAgIGlmKCFsZWdlbmRJdGVtLnRyYWNlLnNob3dsZWdlbmQpIHtcbiAgICAgICAgZy5yZW1vdmUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBtYXRoamF4R3JvdXAgPSBnLnNlbGVjdCgnZ1tjbGFzcyo9bWF0aC1ncm91cF0nKTtcbiAgICB2YXIgbWF0aGpheE5vZGUgPSBtYXRoamF4R3JvdXAubm9kZSgpO1xuICAgIHZhciBvcHRzID0gZ2QuX2Z1bGxMYXlvdXQubGVnZW5kO1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gb3B0cy5mb250LnNpemUgKiBMSU5FX1NQQUNJTkc7XG4gICAgdmFyIGhlaWdodCwgd2lkdGg7XG5cbiAgICBpZihtYXRoamF4Tm9kZSkge1xuICAgICAgICB2YXIgbWF0aGpheEJCID0gRHJhd2luZy5iQm94KG1hdGhqYXhOb2RlKTtcblxuICAgICAgICBoZWlnaHQgPSBtYXRoamF4QkIuaGVpZ2h0O1xuICAgICAgICB3aWR0aCA9IG1hdGhqYXhCQi53aWR0aDtcblxuICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShtYXRoamF4R3JvdXAsIDAsIChoZWlnaHQgLyA0KSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgdGV4dCA9IGcuc2VsZWN0KCcubGVnZW5kdGV4dCcpO1xuICAgICAgICB2YXIgdGV4dExpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0ZXh0KTtcbiAgICAgICAgdmFyIHRleHROb2RlID0gdGV4dC5ub2RlKCk7XG5cbiAgICAgICAgaGVpZ2h0ID0gbGluZUhlaWdodCAqIHRleHRMaW5lcztcbiAgICAgICAgd2lkdGggPSB0ZXh0Tm9kZSA/IERyYXdpbmcuYkJveCh0ZXh0Tm9kZSkud2lkdGggOiAwO1xuXG4gICAgICAgIC8vIGFwcHJveGltYXRpb24gdG8gaGVpZ2h0IG9mZnNldCB0byBjZW50ZXIgdGhlIGZvbnRcbiAgICAgICAgLy8gdG8gYXZvaWQgZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG4gICAgICAgIHZhciB0ZXh0WSA9IGxpbmVIZWlnaHQgKiAoMC4zICsgKDEgLSB0ZXh0TGluZXMpIC8gMik7XG4gICAgICAgIHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQodGV4dCwgY29uc3RhbnRzLnRleHRPZmZzZXRYLCB0ZXh0WSk7XG4gICAgfVxuXG4gICAgaGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCAxNikgKyAzO1xuXG4gICAgbGVnZW5kSXRlbS5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgbGVnZW5kSXRlbS53aWR0aCA9IHdpZHRoO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlTGVnZW5kRGltZW5zaW9ucyhnZCwgZ3JvdXBzLCB0cmFjZXMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBvcHRzID0gZnVsbExheW91dC5sZWdlbmQ7XG4gICAgdmFyIGJvcmRlcndpZHRoID0gb3B0cy5ib3JkZXJ3aWR0aDtcbiAgICB2YXIgaXNHcm91cGVkID0gaGVscGVycy5pc0dyb3VwZWQob3B0cyk7XG5cbiAgICB2YXIgZXh0cmFXaWR0aCA9IDA7XG5cbiAgICBvcHRzLl93aWR0aCA9IDA7XG4gICAgb3B0cy5faGVpZ2h0ID0gMDtcblxuICAgIGlmKGhlbHBlcnMuaXNWZXJ0aWNhbChvcHRzKSkge1xuICAgICAgICBpZihpc0dyb3VwZWQpIHtcbiAgICAgICAgICAgIGdyb3Vwcy5lYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZSh0aGlzLCAwLCBpICogb3B0cy50cmFjZWdyb3VwZ2FwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGxlZ2VuZEl0ZW0gPSBkWzBdLFxuICAgICAgICAgICAgICAgIHRleHRIZWlnaHQgPSBsZWdlbmRJdGVtLmhlaWdodCxcbiAgICAgICAgICAgICAgICB0ZXh0V2lkdGggPSBsZWdlbmRJdGVtLndpZHRoO1xuXG4gICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZSh0aGlzLFxuICAgICAgICAgICAgICAgIGJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICg1ICsgYm9yZGVyd2lkdGggKyBvcHRzLl9oZWlnaHQgKyB0ZXh0SGVpZ2h0IC8gMikpO1xuXG4gICAgICAgICAgICBvcHRzLl9oZWlnaHQgKz0gdGV4dEhlaWdodDtcbiAgICAgICAgICAgIG9wdHMuX3dpZHRoID0gTWF0aC5tYXgob3B0cy5fd2lkdGgsIHRleHRXaWR0aCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG9wdHMuX3dpZHRoICs9IDQ1ICsgYm9yZGVyd2lkdGggKiAyO1xuICAgICAgICBvcHRzLl9oZWlnaHQgKz0gMTAgKyBib3JkZXJ3aWR0aCAqIDI7XG5cbiAgICAgICAgaWYoaXNHcm91cGVkKSB7XG4gICAgICAgICAgICBvcHRzLl9oZWlnaHQgKz0gKG9wdHMuX2xncm91cHNMZW5ndGggLSAxKSAqIG9wdHMudHJhY2Vncm91cGdhcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGV4dHJhV2lkdGggPSA0MDtcbiAgICB9XG4gICAgZWxzZSBpZihpc0dyb3VwZWQpIHtcbiAgICAgICAgdmFyIGdyb3VwWE9mZnNldHMgPSBbb3B0cy5fd2lkdGhdLFxuICAgICAgICAgICAgZ3JvdXBEYXRhID0gZ3JvdXBzLmRhdGEoKTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwLCBuID0gZ3JvdXBEYXRhLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgdmFyIHRleHRXaWR0aHMgPSBncm91cERhdGFbaV0ubWFwKGZ1bmN0aW9uKGxlZ2VuZEl0ZW1BcnJheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWdlbmRJdGVtQXJyYXlbMF0ud2lkdGg7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIGdyb3VwV2lkdGggPSA0MCArIE1hdGgubWF4LmFwcGx5KG51bGwsIHRleHRXaWR0aHMpO1xuXG4gICAgICAgICAgICBvcHRzLl93aWR0aCArPSBvcHRzLnRyYWNlZ3JvdXBnYXAgKyBncm91cFdpZHRoO1xuXG4gICAgICAgICAgICBncm91cFhPZmZzZXRzLnB1c2gob3B0cy5fd2lkdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ3JvdXBzLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUodGhpcywgZ3JvdXBYT2Zmc2V0c1tpXSwgMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdyb3Vwcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgICAgICAgICAgIGdyb3VwVHJhY2VzID0gZ3JvdXAuc2VsZWN0QWxsKCdnLnRyYWNlcycpLFxuICAgICAgICAgICAgICAgIGdyb3VwSGVpZ2h0ID0gMDtcblxuICAgICAgICAgICAgZ3JvdXBUcmFjZXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxlZ2VuZEl0ZW0gPSBkWzBdLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0SGVpZ2h0ID0gbGVnZW5kSXRlbS5oZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZSh0aGlzLFxuICAgICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgICAgICAoNSArIGJvcmRlcndpZHRoICsgZ3JvdXBIZWlnaHQgKyB0ZXh0SGVpZ2h0IC8gMikpO1xuXG4gICAgICAgICAgICAgICAgZ3JvdXBIZWlnaHQgKz0gdGV4dEhlaWdodDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBvcHRzLl9oZWlnaHQgPSBNYXRoLm1heChvcHRzLl9oZWlnaHQsIGdyb3VwSGVpZ2h0KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgb3B0cy5faGVpZ2h0ICs9IDEwICsgYm9yZGVyd2lkdGggKiAyO1xuICAgICAgICBvcHRzLl93aWR0aCArPSBib3JkZXJ3aWR0aCAqIDI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgcm93SGVpZ2h0ID0gMCxcbiAgICAgICAgICAgIG1heFRyYWNlSGVpZ2h0ID0gMCxcbiAgICAgICAgICAgIG1heFRyYWNlV2lkdGggPSAwLFxuICAgICAgICAgICAgb2Zmc2V0WCA9IDAsXG4gICAgICAgICAgICBmdWxsVHJhY2VzV2lkdGggPSAwLFxuICAgICAgICAgICAgdHJhY2VHYXAgPSBvcHRzLnRyYWNlZ3JvdXBnYXAgfHwgNSxcbiAgICAgICAgICAgIG9uZVJvd0xlZ2VuZDtcblxuICAgICAgICAvLyBjYWxjdWxhdGUgbGFyZ2VzdCB3aWR0aCBmb3IgdHJhY2VzIGFuZCB1c2UgZm9yIHdpZHRoIG9mIGFsbCBsZWdlbmQgaXRlbXNcbiAgICAgICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgbWF4VHJhY2VXaWR0aCA9IE1hdGgubWF4KDQwICsgZFswXS53aWR0aCwgbWF4VHJhY2VXaWR0aCk7XG4gICAgICAgICAgICBmdWxsVHJhY2VzV2lkdGggKz0gNDAgKyBkWzBdLndpZHRoICsgdHJhY2VHYXA7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIGxlZ2VuZCBmaXRzIGluIG9uZSByb3dcbiAgICAgICAgb25lUm93TGVnZW5kID0gZnVsbExheW91dC5fc2l6ZS53ID4gYm9yZGVyd2lkdGggKyBmdWxsVHJhY2VzV2lkdGggLSB0cmFjZUdhcDtcbiAgICAgICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGxlZ2VuZEl0ZW0gPSBkWzBdLFxuICAgICAgICAgICAgICAgIHRyYWNlV2lkdGggPSBvbmVSb3dMZWdlbmQgPyA0MCArIGRbMF0ud2lkdGggOiBtYXhUcmFjZVdpZHRoO1xuXG4gICAgICAgICAgICBpZigoYm9yZGVyd2lkdGggKyBvZmZzZXRYICsgdHJhY2VHYXAgKyB0cmFjZVdpZHRoKSA+IGZ1bGxMYXlvdXQuX3NpemUudykge1xuICAgICAgICAgICAgICAgIG9mZnNldFggPSAwO1xuICAgICAgICAgICAgICAgIHJvd0hlaWdodCA9IHJvd0hlaWdodCArIG1heFRyYWNlSGVpZ2h0O1xuICAgICAgICAgICAgICAgIG9wdHMuX2hlaWdodCA9IG9wdHMuX2hlaWdodCArIG1heFRyYWNlSGVpZ2h0O1xuICAgICAgICAgICAgICAgIC8vIHJlc2V0IGZvciBuZXh0IHJvd1xuICAgICAgICAgICAgICAgIG1heFRyYWNlSGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUodGhpcyxcbiAgICAgICAgICAgICAgICAoYm9yZGVyd2lkdGggKyBvZmZzZXRYKSxcbiAgICAgICAgICAgICAgICAoNSArIGJvcmRlcndpZHRoICsgbGVnZW5kSXRlbS5oZWlnaHQgLyAyKSArIHJvd0hlaWdodCk7XG5cbiAgICAgICAgICAgIG9wdHMuX3dpZHRoICs9IHRyYWNlR2FwICsgdHJhY2VXaWR0aDtcbiAgICAgICAgICAgIG9wdHMuX2hlaWdodCA9IE1hdGgubWF4KG9wdHMuX2hlaWdodCwgbGVnZW5kSXRlbS5oZWlnaHQpO1xuXG4gICAgICAgICAgICAvLyBrZWVwIHRyYWNrIG9mIHRhbGxlc3QgdHJhY2UgaW4gZ3JvdXBcbiAgICAgICAgICAgIG9mZnNldFggKz0gdHJhY2VHYXAgKyB0cmFjZVdpZHRoO1xuICAgICAgICAgICAgbWF4VHJhY2VIZWlnaHQgPSBNYXRoLm1heChsZWdlbmRJdGVtLmhlaWdodCwgbWF4VHJhY2VIZWlnaHQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBvcHRzLl93aWR0aCArPSBib3JkZXJ3aWR0aCAqIDI7XG4gICAgICAgIG9wdHMuX2hlaWdodCArPSAxMCArIGJvcmRlcndpZHRoICogMjtcblxuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSdyZSBvbmx5IGdldHRpbmcgZnVsbCBwaXhlbHNcbiAgICBvcHRzLl93aWR0aCA9IE1hdGguY2VpbChvcHRzLl93aWR0aCk7XG4gICAgb3B0cy5faGVpZ2h0ID0gTWF0aC5jZWlsKG9wdHMuX2hlaWdodCk7XG5cbiAgICB2YXIgaXNFZGl0YWJsZSA9IChcbiAgICAgICAgZ2QuX2NvbnRleHQuZWRpdHMubGVnZW5kVGV4dCB8fFxuICAgICAgICBnZC5fY29udGV4dC5lZGl0cy5sZWdlbmRQb3NpdGlvblxuICAgICk7XG5cbiAgICB0cmFjZXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBsZWdlbmRJdGVtID0gZFswXTtcbiAgICAgICAgdmFyIGJnID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnLmxlZ2VuZHRvZ2dsZScpO1xuXG4gICAgICAgIERyYXdpbmcuc2V0UmVjdChiZyxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAtbGVnZW5kSXRlbS5oZWlnaHQgLyAyLFxuICAgICAgICAgICAgKGlzRWRpdGFibGUgPyAwIDogb3B0cy5fd2lkdGgpICsgZXh0cmFXaWR0aCxcbiAgICAgICAgICAgIGxlZ2VuZEl0ZW0uaGVpZ2h0XG4gICAgICAgICk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZE1hcmdpbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQsXG4gICAgICAgIG9wdHMgPSBmdWxsTGF5b3V0LmxlZ2VuZDtcblxuICAgIHZhciB4YW5jaG9yID0gJ2xlZnQnO1xuICAgIGlmKGFuY2hvclV0aWxzLmlzUmlnaHRBbmNob3Iob3B0cykpIHtcbiAgICAgICAgeGFuY2hvciA9ICdyaWdodCc7XG4gICAgfVxuICAgIGVsc2UgaWYoYW5jaG9yVXRpbHMuaXNDZW50ZXJBbmNob3Iob3B0cykpIHtcbiAgICAgICAgeGFuY2hvciA9ICdjZW50ZXInO1xuICAgIH1cblxuICAgIHZhciB5YW5jaG9yID0gJ3RvcCc7XG4gICAgaWYoYW5jaG9yVXRpbHMuaXNCb3R0b21BbmNob3Iob3B0cykpIHtcbiAgICAgICAgeWFuY2hvciA9ICdib3R0b20nO1xuICAgIH1cbiAgICBlbHNlIGlmKGFuY2hvclV0aWxzLmlzTWlkZGxlQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICAvLyBsYXN0bHkgY2hlY2sgaWYgdGhlIG1hcmdpbiBhdXRvLWV4cGFuZCBoYXMgY2hhbmdlZFxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdsZWdlbmQnLCB7XG4gICAgICAgIHg6IG9wdHMueCxcbiAgICAgICAgeTogb3B0cy55LFxuICAgICAgICBsOiBvcHRzLl93aWR0aCAqIChGUk9NX1RMW3hhbmNob3JdKSxcbiAgICAgICAgcjogb3B0cy5fd2lkdGggKiAoRlJPTV9CUlt4YW5jaG9yXSksXG4gICAgICAgIGI6IG9wdHMuX2hlaWdodCAqIChGUk9NX0JSW3lhbmNob3JdKSxcbiAgICAgICAgdDogb3B0cy5faGVpZ2h0ICogKEZST01fVExbeWFuY2hvcl0pXG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZEhvcml6b250YWxNYXJnaW4oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBvcHRzID0gZnVsbExheW91dC5sZWdlbmQ7XG5cbiAgICB2YXIgeGFuY2hvciA9ICdsZWZ0JztcbiAgICBpZihhbmNob3JVdGlscy5pc1JpZ2h0QW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHhhbmNob3IgPSAncmlnaHQnO1xuICAgIH1cbiAgICBlbHNlIGlmKGFuY2hvclV0aWxzLmlzQ2VudGVyQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHhhbmNob3IgPSAnY2VudGVyJztcbiAgICB9XG5cbiAgICAvLyBsYXN0bHkgY2hlY2sgaWYgdGhlIG1hcmdpbiBhdXRvLWV4cGFuZCBoYXMgY2hhbmdlZFxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdsZWdlbmQnLCB7XG4gICAgICAgIHg6IG9wdHMueCxcbiAgICAgICAgeTogMC41LFxuICAgICAgICBsOiBvcHRzLl93aWR0aCAqIChGUk9NX1RMW3hhbmNob3JdKSxcbiAgICAgICAgcjogb3B0cy5fd2lkdGggKiAoRlJPTV9CUlt4YW5jaG9yXSksXG4gICAgICAgIGI6IDAsXG4gICAgICAgIHQ6IDBcbiAgICB9KTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldExlZ2VuZERhdGEoY2FsY2RhdGEsIG9wdHMpIHtcbiAgICB2YXIgbGdyb3VwVG9UcmFjZXMgPSB7fSxcbiAgICAgICAgbGdyb3VwcyA9IFtdLFxuICAgICAgICBoYXNPbmVOb25CbGFua0dyb3VwID0gZmFsc2UsXG4gICAgICAgIHNsaWNlc1Nob3duID0ge30sXG4gICAgICAgIGxncm91cGkgPSAwO1xuXG4gICAgdmFyIGksIGo7XG5cbiAgICBmdW5jdGlvbiBhZGRPbmVJdGVtKGxlZ2VuZEdyb3VwLCBsZWdlbmRJdGVtKSB7XG4gICAgICAgIC8vIGVhY2ggJycgbGVnZW5kIGdyb3VwIGlzIHRyZWF0ZWQgYXMgYSBzZXBhcmF0ZSBncm91cFxuICAgICAgICBpZihsZWdlbmRHcm91cCA9PT0gJycgfHwgIWhlbHBlcnMuaXNHcm91cGVkKG9wdHMpKSB7XG4gICAgICAgICAgICB2YXIgdW5pcXVlR3JvdXAgPSAnfn5pJyArIGxncm91cGk7IC8vIFRPRE86IGNoZWNrIHRoaXMgYWdhaW5zdCBmdWxsRGF0YSBsZWdlbmRncm91cHM/XG5cbiAgICAgICAgICAgIGxncm91cHMucHVzaCh1bmlxdWVHcm91cCk7XG4gICAgICAgICAgICBsZ3JvdXBUb1RyYWNlc1t1bmlxdWVHcm91cF0gPSBbW2xlZ2VuZEl0ZW1dXTtcbiAgICAgICAgICAgIGxncm91cGkrKztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGxncm91cHMuaW5kZXhPZihsZWdlbmRHcm91cCkgPT09IC0xKSB7XG4gICAgICAgICAgICBsZ3JvdXBzLnB1c2gobGVnZW5kR3JvdXApO1xuICAgICAgICAgICAgaGFzT25lTm9uQmxhbmtHcm91cCA9IHRydWU7XG4gICAgICAgICAgICBsZ3JvdXBUb1RyYWNlc1tsZWdlbmRHcm91cF0gPSBbW2xlZ2VuZEl0ZW1dXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGxncm91cFRvVHJhY2VzW2xlZ2VuZEdyb3VwXS5wdXNoKFtsZWdlbmRJdGVtXSk7XG4gICAgfVxuXG4gICAgLy8gYnVpbGQgYW4geyBsZWdlbmRncm91cDogW2NkMCwgY2QwXSwgLi4uIH0gb2JqZWN0XG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbaV07XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgICAgICB2YXIgbGdyb3VwID0gdHJhY2UubGVnZW5kZ3JvdXA7XG5cbiAgICAgICAgaWYoIXRyYWNlLnZpc2libGUgfHwgIXRyYWNlLnNob3dsZWdlbmQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdwaWUnKSkge1xuICAgICAgICAgICAgaWYoIXNsaWNlc1Nob3duW2xncm91cF0pIHNsaWNlc1Nob3duW2xncm91cF0gPSB7fTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFiZWxqID0gY2Rbal0ubGFiZWw7XG5cbiAgICAgICAgICAgICAgICBpZighc2xpY2VzU2hvd25bbGdyb3VwXVtsYWJlbGpdKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZE9uZUl0ZW0obGdyb3VwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogbGFiZWxqLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IGNkW2pdLmNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgaTogY2Rbal0uaSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0czogY2Rbal0ucHRzXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlc1Nob3duW2xncm91cF1bbGFiZWxqXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZWxzZSBhZGRPbmVJdGVtKGxncm91cCwgY2QwKTtcbiAgICB9XG5cbiAgICAvLyB3b24ndCBkcmF3IGEgbGVnZW5kIGluIHRoaXMgY2FzZVxuICAgIGlmKCFsZ3JvdXBzLmxlbmd0aCkgcmV0dXJuIFtdO1xuXG4gICAgLy8gcmVhcnJhbmdlIGxncm91cFRvVHJhY2VzIGludG8gYSBkMy1mcmllbmRseSBhcnJheSBvZiBhcnJheXNcbiAgICB2YXIgbGdyb3Vwc0xlbmd0aCA9IGxncm91cHMubGVuZ3RoLFxuICAgICAgICBsdHJhY2VzLFxuICAgICAgICBsZWdlbmREYXRhO1xuXG4gICAgaWYoaGFzT25lTm9uQmxhbmtHcm91cCAmJiBoZWxwZXJzLmlzR3JvdXBlZChvcHRzKSkge1xuICAgICAgICBsZWdlbmREYXRhID0gbmV3IEFycmF5KGxncm91cHNMZW5ndGgpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxncm91cHNMZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbHRyYWNlcyA9IGxncm91cFRvVHJhY2VzW2xncm91cHNbaV1dO1xuICAgICAgICAgICAgbGVnZW5kRGF0YVtpXSA9IGhlbHBlcnMuaXNSZXZlcnNlZChvcHRzKSA/IGx0cmFjZXMucmV2ZXJzZSgpIDogbHRyYWNlcztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gY29sbGFwc2UgYWxsIGdyb3VwcyBpbnRvIG9uZSBpZiBhbGwgZ3JvdXBzIGFyZSBibGFua1xuICAgICAgICBsZWdlbmREYXRhID0gW25ldyBBcnJheShsZ3JvdXBzTGVuZ3RoKV07XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGdyb3Vwc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsdHJhY2VzID0gbGdyb3VwVG9UcmFjZXNbbGdyb3Vwc1tpXV1bMF07XG4gICAgICAgICAgICBsZWdlbmREYXRhWzBdW2hlbHBlcnMuaXNSZXZlcnNlZChvcHRzKSA/IGxncm91cHNMZW5ndGggLSBpIC0gMSA6IGldID0gbHRyYWNlcztcbiAgICAgICAgfVxuICAgICAgICBsZ3JvdXBzTGVuZ3RoID0gMTtcbiAgICB9XG5cbiAgICAvLyBuZWVkZWQgaW4gcmVwb3NpdGlvbkxlZ2VuZFxuICAgIG9wdHMuX2xncm91cHNMZW5ndGggPSBsZ3JvdXBzTGVuZ3RoO1xuICAgIHJldHVybiBsZWdlbmREYXRhO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIFNIT1dJU09MQVRFVElQID0gdHJ1ZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDbGljayhnLCBnZCwgbnVtQ2xpY2tzKSB7XG4gICAgaWYoZ2QuX2RyYWdnZWQgfHwgZ2QuX2VkaXRpbmcpIHJldHVybjtcblxuICAgIHZhciBoaWRkZW5TbGljZXMgPSBnZC5fZnVsbExheW91dC5oaWRkZW5sYWJlbHMgP1xuICAgICAgICBnZC5fZnVsbExheW91dC5oaWRkZW5sYWJlbHMuc2xpY2UoKSA6XG4gICAgICAgIFtdO1xuXG4gICAgdmFyIGxlZ2VuZEl0ZW0gPSBnLmRhdGEoKVswXVswXTtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIGZ1bGxUcmFjZSA9IGxlZ2VuZEl0ZW0udHJhY2U7XG4gICAgdmFyIGxlZ2VuZGdyb3VwID0gZnVsbFRyYWNlLmxlZ2VuZGdyb3VwO1xuXG4gICAgdmFyIGksIGosIGtjb250LCBrZXksIGtleXMsIHZhbDtcbiAgICB2YXIgYXR0clVwZGF0ZSA9IHt9O1xuICAgIHZhciBhdHRySW5kaWNlcyA9IFtdO1xuICAgIHZhciBjYXJycyA9IFtdO1xuICAgIHZhciBjYXJySWR4ID0gW107XG5cbiAgICBmdW5jdGlvbiBpbnNlcnRVcGRhdGUodHJhY2VJbmRleCwga2V5LCB2YWx1ZSkge1xuICAgICAgICB2YXIgYXR0ckluZGV4ID0gYXR0ckluZGljZXMuaW5kZXhPZih0cmFjZUluZGV4KTtcbiAgICAgICAgdmFyIHZhbHVlQXJyYXkgPSBhdHRyVXBkYXRlW2tleV07XG4gICAgICAgIGlmKCF2YWx1ZUFycmF5KSB7XG4gICAgICAgICAgICB2YWx1ZUFycmF5ID0gYXR0clVwZGF0ZVtrZXldID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZihhdHRySW5kaWNlcy5pbmRleE9mKHRyYWNlSW5kZXgpID09PSAtMSkge1xuICAgICAgICAgICAgYXR0ckluZGljZXMucHVzaCh0cmFjZUluZGV4KTtcbiAgICAgICAgICAgIGF0dHJJbmRleCA9IGF0dHJJbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZUFycmF5W2F0dHJJbmRleF0gPSB2YWx1ZTtcblxuICAgICAgICByZXR1cm4gYXR0ckluZGV4O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldFZpc2liaWxpdHkoZnVsbFRyYWNlLCB2aXNpYmlsaXR5KSB7XG4gICAgICAgIHZhciBmdWxsSW5wdXQgPSBmdWxsVHJhY2UuX2Z1bGxJbnB1dDtcbiAgICAgICAgaWYoUmVnaXN0cnkuaGFzVHJhbnNmb3JtKGZ1bGxJbnB1dCwgJ2dyb3VwYnknKSkge1xuICAgICAgICAgICAgdmFyIGtjb250ID0gY2FycnNbZnVsbElucHV0LmluZGV4XTtcbiAgICAgICAgICAgIGlmKCFrY29udCkge1xuICAgICAgICAgICAgICAgIHZhciBncm91cGJ5SW5kaWNlcyA9IFJlZ2lzdHJ5LmdldFRyYW5zZm9ybUluZGljZXMoZnVsbElucHV0LCAnZ3JvdXBieScpO1xuICAgICAgICAgICAgICAgIHZhciBsYXN0R3JvdXBieUluZGV4ID0gZ3JvdXBieUluZGljZXNbZ3JvdXBieUluZGljZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAga2NvbnQgPSBMaWIua2V5ZWRDb250YWluZXIoZnVsbElucHV0LCAndHJhbnNmb3Jtc1snICsgbGFzdEdyb3VwYnlJbmRleCArICddLnN0eWxlcycsICd0YXJnZXQnLCAndmFsdWUudmlzaWJsZScpO1xuICAgICAgICAgICAgICAgIGNhcnJzW2Z1bGxJbnB1dC5pbmRleF0gPSBrY29udDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGN1clN0YXRlID0ga2NvbnQuZ2V0KGZ1bGxUcmFjZS5fZ3JvdXApO1xuXG4gICAgICAgICAgICAvLyBJZiBub3Qgc3BlY2lmaWVkLCBhc3N1bWUgdmlzaWJsZS4gVGhpcyBoYXBwZW5zIGlmIHRoZXJlIGFyZSBvdGhlciBzdHlsZVxuICAgICAgICAgICAgLy8gcHJvcGVydGllcyBzZXQgZm9yIGEgZ3JvdXAgYnV0IG5vdCB0aGUgdmlzaWJpbGl0eS4gVGhlcmUgYXJlIG1hbnkgc2ltaWxhclxuICAgICAgICAgICAgLy8gd2F5cyB0byBkbyB0aGlzIChlLmcuIHdoeSBub3QganVzdCBgY3VyU3RhdGUgPSBmdWxsVHJhY2UudmlzaWJsZWA/Pz8gVGhlXG4gICAgICAgICAgICAvLyBhbnN3ZXIgaXM6IGJlY2F1c2UgaXQgYnJlYWtzIG90aGVyIHRoaW5ncyBsaWtlIGdyb3VwYnkgdHJhY2UgbmFtZXMgaW5cbiAgICAgICAgICAgIC8vIHN1YnRsZSB3YXlzLilcbiAgICAgICAgICAgIGlmKGN1clN0YXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjdXJTdGF0ZSA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGN1clN0YXRlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIC8vIHRydWUgLT4gbGVnZW5kb25seS4gQWxsIG90aGVycyB0b2dnbGUgdG8gdHJ1ZTpcbiAgICAgICAgICAgICAgICBrY29udC5zZXQoZnVsbFRyYWNlLl9ncm91cCwgdmlzaWJpbGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXJySWR4W2Z1bGxJbnB1dC5pbmRleF0gPSBpbnNlcnRVcGRhdGUoZnVsbElucHV0LmluZGV4LCAndmlzaWJsZScsIGZ1bGxJbnB1dC52aXNpYmxlID09PSBmYWxzZSA/IGZhbHNlIDogdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBmYWxzZSAtPiBmYWxzZSAobm90IHBvc3NpYmxlIHNpbmNlIHdpbGwgbm90IGJlIHZpc2libGUgaW4gbGVnZW5kKVxuICAgICAgICAgICAgLy8gdHJ1ZSAtPiBsZWdlbmRvbmx5XG4gICAgICAgICAgICAvLyBsZWdlbmRvbmx5IC0+IHRydWVcbiAgICAgICAgICAgIHZhciBuZXh0VmlzaWJpbGl0eSA9IGZ1bGxJbnB1dC52aXNpYmxlID09PSBmYWxzZSA/IGZhbHNlIDogdmlzaWJpbGl0eTtcblxuICAgICAgICAgICAgaW5zZXJ0VXBkYXRlKGZ1bGxJbnB1dC5pbmRleCwgJ3Zpc2libGUnLCBuZXh0VmlzaWJpbGl0eSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihudW1DbGlja3MgPT09IDEgJiYgU0hPV0lTT0xBVEVUSVAgJiYgZ2QuZGF0YSAmJiBnZC5fY29udGV4dC5zaG93VGlwcykge1xuICAgICAgICBMaWIubm90aWZpZXIoTGliLl8oZ2QsICdEb3VibGUtY2xpY2sgb24gbGVnZW5kIHRvIGlzb2xhdGUgb25lIHRyYWNlJyksICdsb25nJyk7XG4gICAgICAgIFNIT1dJU09MQVRFVElQID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgU0hPV0lTT0xBVEVUSVAgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZihSZWdpc3RyeS50cmFjZUlzKGZ1bGxUcmFjZSwgJ3BpZScpKSB7XG4gICAgICAgIHZhciB0aGlzTGFiZWwgPSBsZWdlbmRJdGVtLmxhYmVsLFxuICAgICAgICAgICAgdGhpc0xhYmVsSW5kZXggPSBoaWRkZW5TbGljZXMuaW5kZXhPZih0aGlzTGFiZWwpO1xuXG4gICAgICAgIGlmKG51bUNsaWNrcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYodGhpc0xhYmVsSW5kZXggPT09IC0xKSBoaWRkZW5TbGljZXMucHVzaCh0aGlzTGFiZWwpO1xuICAgICAgICAgICAgZWxzZSBoaWRkZW5TbGljZXMuc3BsaWNlKHRoaXNMYWJlbEluZGV4LCAxKTtcbiAgICAgICAgfSBlbHNlIGlmKG51bUNsaWNrcyA9PT0gMikge1xuICAgICAgICAgICAgaGlkZGVuU2xpY2VzID0gW107XG4gICAgICAgICAgICBnZC5jYWxjZGF0YVswXS5mb3JFYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZih0aGlzTGFiZWwgIT09IGQubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgaGlkZGVuU2xpY2VzLnB1c2goZC5sYWJlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZihnZC5fZnVsbExheW91dC5oaWRkZW5sYWJlbHMgJiYgZ2QuX2Z1bGxMYXlvdXQuaGlkZGVubGFiZWxzLmxlbmd0aCA9PT0gaGlkZGVuU2xpY2VzLmxlbmd0aCAmJiB0aGlzTGFiZWxJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBoaWRkZW5TbGljZXMgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsICdoaWRkZW5sYWJlbHMnLCBoaWRkZW5TbGljZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBoYXNMZWdlbmRncm91cCA9IGxlZ2VuZGdyb3VwICYmIGxlZ2VuZGdyb3VwLmxlbmd0aDtcbiAgICAgICAgdmFyIHRyYWNlSW5kaWNlc0luR3JvdXAgPSBbXTtcbiAgICAgICAgdmFyIHRyYWNlaTtcbiAgICAgICAgaWYoaGFzTGVnZW5kZ3JvdXApIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VpID0gZnVsbERhdGFbaV07XG4gICAgICAgICAgICAgICAgaWYoIXRyYWNlaS52aXNpYmxlKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZWkubGVnZW5kZ3JvdXAgPT09IGxlZ2VuZGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlSW5kaWNlc0luR3JvdXAucHVzaChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihudW1DbGlja3MgPT09IDEpIHtcbiAgICAgICAgICAgIHZhciBuZXh0VmlzaWJpbGl0eTtcblxuICAgICAgICAgICAgc3dpdGNoKGZ1bGxUcmFjZS52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSB0cnVlOlxuICAgICAgICAgICAgICAgICAgICBuZXh0VmlzaWJpbGl0eSA9ICdsZWdlbmRvbmx5JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBmYWxzZTpcbiAgICAgICAgICAgICAgICAgICAgbmV4dFZpc2liaWxpdHkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbGVnZW5kb25seSc6XG4gICAgICAgICAgICAgICAgICAgIG5leHRWaXNpYmlsaXR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGhhc0xlZ2VuZGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZnVsbERhdGFbaV0udmlzaWJsZSAhPT0gZmFsc2UgJiYgZnVsbERhdGFbaV0ubGVnZW5kZ3JvdXAgPT09IGxlZ2VuZGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWaXNpYmlsaXR5KGZ1bGxEYXRhW2ldLCBuZXh0VmlzaWJpbGl0eSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFZpc2liaWxpdHkoZnVsbFRyYWNlLCBuZXh0VmlzaWJpbGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGNsaWNrZWQgaW5kZXguIGV4cGFuZGVkSW5kZXggZG9lcyB3aGF0IHdlIHdhbnQgZm9yIGV4cGFuZGVkIHRyYWNlc1xuICAgICAgICAgICAgLy8gYnV0IGFsc28gY3VsbHMgaGlkZGVuIHRyYWNlcy4gVGhhdCBtZWFucyB3ZSBoYXZlIHNvbWUgd29yayB0byBkby5cbiAgICAgICAgICAgIHZhciBpc0NsaWNrZWQsIGlzSW5Hcm91cCwgb3RoZXJTdGF0ZTtcbiAgICAgICAgICAgIHZhciBpc0lzb2xhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaXNDbGlja2VkID0gZnVsbERhdGFbaV0gPT09IGZ1bGxUcmFjZTtcbiAgICAgICAgICAgICAgICBpZihpc0NsaWNrZWQpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgaXNJbkdyb3VwID0gKGhhc0xlZ2VuZGdyb3VwICYmIGZ1bGxEYXRhW2ldLmxlZ2VuZGdyb3VwID09PSBsZWdlbmRncm91cCk7XG5cbiAgICAgICAgICAgICAgICBpZighaXNJbkdyb3VwICYmIGZ1bGxEYXRhW2ldLnZpc2libGUgPT09IHRydWUgJiYgIVJlZ2lzdHJ5LnRyYWNlSXMoZnVsbERhdGFbaV0sICdub3RMZWdlbmRJc29sYXRhYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNJc29sYXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gRmFsc2UgaXMgc3RpY2t5OyB3ZSBkb24ndCBjaGFuZ2UgaXQuXG4gICAgICAgICAgICAgICAgaWYoZnVsbERhdGFbaV0udmlzaWJsZSA9PT0gZmFsc2UpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyhmdWxsRGF0YVtpXSwgJ25vdExlZ2VuZElzb2xhdGFibGUnKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2goZnVsbFRyYWNlLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbGVnZW5kb25seSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWaXNpYmlsaXR5KGZ1bGxEYXRhW2ldLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIHRydWU6XG4gICAgICAgICAgICAgICAgICAgICAgICBvdGhlclN0YXRlID0gaXNJc29sYXRlZCA/IHRydWUgOiAnbGVnZW5kb25seSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsaWNrZWQgPSBmdWxsRGF0YVtpXSA9PT0gZnVsbFRyYWNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbkdyb3VwID0gaXNDbGlja2VkIHx8IChoYXNMZWdlbmRncm91cCAmJiBmdWxsRGF0YVtpXS5sZWdlbmRncm91cCA9PT0gbGVnZW5kZ3JvdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmlzaWJpbGl0eShmdWxsRGF0YVtpXSwgaXNJbkdyb3VwID8gdHJ1ZSA6IG90aGVyU3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2FycnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGtjb250ID0gY2FycnNbaV07XG4gICAgICAgICAgICBpZigha2NvbnQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgdmFyIHVwZGF0ZSA9IGtjb250LmNvbnN0cnVjdFVwZGF0ZSgpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlS2V5cyA9IE9iamVjdC5rZXlzKHVwZGF0ZSk7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB1cGRhdGVLZXlzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAga2V5ID0gdXBkYXRlS2V5c1tqXTtcbiAgICAgICAgICAgICAgICB2YWwgPSBhdHRyVXBkYXRlW2tleV0gPSBhdHRyVXBkYXRlW2tleV0gfHwgW107XG4gICAgICAgICAgICAgICAgdmFsW2NhcnJJZHhbaV1dID0gdXBkYXRlW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgbGVuZ3RoIG9mIHRoZSB2YWx1ZSBhcnJheXMgc2hvdWxkIGJlIGVxdWFsIGFuZCBhbnkgdW5zcGVjaWZpZWRcbiAgICAgICAgLy8gdmFsdWVzIHNob3VsZCBiZSBleHBsaWNpdGx5IHVuZGVmaW5lZCBmb3IgdGhlbSB0byBnZXQgcHJvcGVybHkgY3VsbGVkXG4gICAgICAgIC8vIGFzIHVwZGF0ZXMgYW5kIG5vdCBhY2NpZGVudGFsbHkgcmVzZXQgdG8gdGhlIGRlZmF1bHQgdmFsdWUuIFRoaXMgZmlsbHNcbiAgICAgICAgLy8gb3V0IHNwYXJzZSBhcnJheXMgd2l0aCB0aGUgcmVxdWlyZWQgbnVtYmVyIG9mIHVuZGVmaW5lZCB2YWx1ZXM6XG4gICAgICAgIGtleXMgPSBPYmplY3Qua2V5cyhhdHRyVXBkYXRlKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGF0dHJJbmRpY2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIGhhc093blByb3BldHkgdG8gcHJvdGVjdCBhZ2FpbnN0IGZhbHNleSB2YWx1ZXM6XG4gICAgICAgICAgICAgICAgaWYoIWF0dHJVcGRhdGVba2V5XS5oYXNPd25Qcm9wZXJ0eShqKSkge1xuICAgICAgICAgICAgICAgICAgICBhdHRyVXBkYXRlW2tleV1bal0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVzdHlsZScsIGdkLCBhdHRyVXBkYXRlLCBhdHRySW5kaWNlcyk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmlzR3JvdXBlZCA9IGZ1bmN0aW9uIGlzR3JvdXBlZChsZWdlbmRMYXlvdXQpIHtcbiAgICByZXR1cm4gKGxlZ2VuZExheW91dC50cmFjZW9yZGVyIHx8ICcnKS5pbmRleE9mKCdncm91cGVkJykgIT09IC0xO1xufTtcblxuZXhwb3J0cy5pc1ZlcnRpY2FsID0gZnVuY3Rpb24gaXNWZXJ0aWNhbChsZWdlbmRMYXlvdXQpIHtcbiAgICByZXR1cm4gbGVnZW5kTGF5b3V0Lm9yaWVudGF0aW9uICE9PSAnaCc7XG59O1xuXG5leHBvcnRzLmlzUmV2ZXJzZWQgPSBmdW5jdGlvbiBpc1JldmVyc2VkKGxlZ2VuZExheW91dCkge1xuICAgIHJldHVybiAobGVnZW5kTGF5b3V0LnRyYWNlb3JkZXIgfHwgJycpLmluZGV4T2YoJ3JldmVyc2VkJykgIT09IC0xO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdsZWdlbmQnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcblxuICAgIGRyYXc6IHJlcXVpcmUoJy4vZHJhdycpLFxuICAgIHN0eWxlOiByZXF1aXJlKCcuL3N0eWxlJylcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uL2NvbG9yJyk7XG5cbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgc3R5bGVQaWUgPSByZXF1aXJlKCcuLi8uLi90cmFjZXMvcGllL3N0eWxlX29uZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKHMsIGdkKSB7XG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlR3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgdmFyIGxheWVycyA9IExpYi5lbnN1cmVTaW5nbGUodHJhY2VHcm91cCwgJ2cnLCAnbGF5ZXJzJyk7XG4gICAgICAgIGxheWVycy5zdHlsZSgnb3BhY2l0eScsIGRbMF0udHJhY2Uub3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIGZpbGwgPSBsYXllcnNcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ2cubGVnZW5kZmlsbCcpXG4gICAgICAgICAgICAgICAgLmRhdGEoW2RdKTtcbiAgICAgICAgZmlsbC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnbGVnZW5kZmlsbCcsIHRydWUpO1xuXG4gICAgICAgIHZhciBsaW5lID0gbGF5ZXJzXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdnLmxlZ2VuZGxpbmVzJylcbiAgICAgICAgICAgICAgICAuZGF0YShbZF0pO1xuICAgICAgICBsaW5lLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdsZWdlbmRsaW5lcycsIHRydWUpO1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBsYXllcnNcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ2cubGVnZW5kc3ltYm9scycpXG4gICAgICAgICAgICAgICAgLmRhdGEoW2RdKTtcbiAgICAgICAgc3ltYm9sLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdsZWdlbmRzeW1ib2xzJywgdHJ1ZSk7XG5cbiAgICAgICAgc3ltYm9sLnNlbGVjdEFsbCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgLmRhdGEoW2RdKVxuICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnbGVnZW5kcG9pbnRzJywgdHJ1ZSk7XG4gICAgfSlcbiAgICAuZWFjaChzdHlsZUJhcnMpXG4gICAgLmVhY2goc3R5bGVCb3hlcylcbiAgICAuZWFjaChzdHlsZVBpZXMpXG4gICAgLmVhY2goc3R5bGVMaW5lcylcbiAgICAuZWFjaChzdHlsZVBvaW50cylcbiAgICAuZWFjaChzdHlsZUNhbmRsZXMpXG4gICAgLmVhY2goc3R5bGVPSExDKTtcblxuICAgIGZ1bmN0aW9uIHN0eWxlTGluZXMoZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICB2YXIgc2hvd0ZpbGwgPSB0cmFjZS52aXNpYmxlICYmIHRyYWNlLmZpbGwgJiYgdHJhY2UuZmlsbCAhPT0gJ25vbmUnO1xuICAgICAgICB2YXIgc2hvd0xpbmUgPSBzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSk7XG4gICAgICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgICAgICB2YXIgc2hvd0dyYWRpZW50TGluZSA9IGZhbHNlO1xuICAgICAgICB2YXIgc2hvd0dyYWRpZW50RmlsbCA9IGZhbHNlO1xuXG4gICAgICAgIGlmKGNvbnRvdXJzKSB7XG4gICAgICAgICAgICB2YXIgY29sb3JpbmcgPSBjb250b3Vycy5jb2xvcmluZztcblxuICAgICAgICAgICAgaWYoY29sb3JpbmcgPT09ICdsaW5lcycpIHtcbiAgICAgICAgICAgICAgICBzaG93R3JhZGllbnRMaW5lID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHNob3dMaW5lID0gY29sb3JpbmcgPT09ICdub25lJyB8fCBjb2xvcmluZyA9PT0gJ2hlYXRtYXAnIHx8XG4gICAgICAgICAgICAgICAgICAgIGNvbnRvdXJzLnNob3dsaW5lcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY29udG91cnMudHlwZSA9PT0gJ2NvbnN0cmFpbnQnKSB7XG4gICAgICAgICAgICAgICAgc2hvd0ZpbGwgPSBjb250b3Vycy5fb3BlcmF0aW9uICE9PSAnPSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKGNvbG9yaW5nID09PSAnZmlsbCcgfHwgY29sb3JpbmcgPT09ICdoZWF0bWFwJykge1xuICAgICAgICAgICAgICAgIHNob3dHcmFkaWVudEZpbGwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2l0aCBmaWxsIGFuZCBubyBtYXJrZXJzIG9yIHRleHQsIG1vdmUgdGhlIGxpbmUgYW5kIGZpbGwgdXAgYSBiaXRcbiAgICAgICAgLy8gc28gaXQncyBtb3JlIGNlbnRlcmVkXG4gICAgICAgIHZhciBtYXJrZXJzT3JUZXh0ID0gc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgfHwgc3ViVHlwZXMuaGFzVGV4dCh0cmFjZSk7XG4gICAgICAgIHZhciBhbnlGaWxsID0gc2hvd0ZpbGwgfHwgc2hvd0dyYWRpZW50RmlsbDtcbiAgICAgICAgdmFyIGFueUxpbmUgPSBzaG93TGluZSB8fCBzaG93R3JhZGllbnRMaW5lO1xuICAgICAgICB2YXIgcGF0aFN0YXJ0ID0gKG1hcmtlcnNPclRleHQgfHwgIWFueUZpbGwpID8gJ001LDAnIDpcbiAgICAgICAgICAgIC8vIHdpdGggYSBsaW5lIGxlYXZlIGl0IHNsaWdodGx5IGJlbG93IGNlbnRlciwgdG8gbGVhdmUgcm9vbSBmb3IgdGhlXG4gICAgICAgICAgICAvLyBsaW5lIHRoaWNrbmVzcyBhbmQgYmVjYXVzZSB0aGUgbGluZSBpcyB1c3VhbGx5IG1vcmUgcHJvbWluZW50XG4gICAgICAgICAgICBhbnlMaW5lID8gJ001LC0yJyA6ICdNNSwtMyc7XG5cbiAgICAgICAgdmFyIHRoaXMzID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHZhciBmaWxsID0gdGhpczMuc2VsZWN0KCcubGVnZW5kZmlsbCcpLnNlbGVjdEFsbCgncGF0aCcpXG4gICAgICAgICAgICAuZGF0YShzaG93RmlsbCB8fCBzaG93R3JhZGllbnRGaWxsID8gW2RdIDogW10pO1xuICAgICAgICBmaWxsLmVudGVyKCkuYXBwZW5kKCdwYXRoJykuY2xhc3NlZCgnanMtZmlsbCcsIHRydWUpO1xuICAgICAgICBmaWxsLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgZmlsbC5hdHRyKCdkJywgcGF0aFN0YXJ0ICsgJ2gzMHY2aC0zMHonKVxuICAgICAgICAgICAgLmNhbGwoc2hvd0ZpbGwgPyBEcmF3aW5nLmZpbGxHcm91cFN0eWxlIDogZmlsbEdyYWRpZW50KTtcblxuICAgICAgICB2YXIgbGluZSA9IHRoaXMzLnNlbGVjdCgnLmxlZ2VuZGxpbmVzJykuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgICAgIC5kYXRhKHNob3dMaW5lIHx8IHNob3dHcmFkaWVudExpbmUgPyBbZF0gOiBbXSk7XG4gICAgICAgIGxpbmUuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdqcy1saW5lJywgdHJ1ZSk7XG4gICAgICAgIGxpbmUuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIHRoaXMgaXMgdWdseS4uLiBidXQgeW91IGNhbid0IGFwcGx5IGEgZ3JhZGllbnQgdG8gYSBwZXJmZWN0bHlcbiAgICAgICAgLy8gaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBsaW5lLiBQcmVzdW1hYmx5IGJlY2F1c2UgdGhlblxuICAgICAgICAvLyB0aGUgc3lzdGVtIGRvZXNuJ3Qga25vdyBob3cgdG8gc2NhbGUgdmVydGljYWwgdmFyaWF0aW9uLCBldmVuXG4gICAgICAgIC8vIHRob3VnaCB0aGVyZSAqaXMqIG5vIHZlcnRpY2FsIHZhcmlhdGlvbiBpbiB0aGlzIGNhc2UuXG4gICAgICAgIC8vIHNvIGFkZCBhbiBpbnZpc2libHkgc21hbGwgYW5nbGUgdG8gdGhlIGxpbmVcbiAgICAgICAgLy8gVGhpcyBpc3N1ZSAoYW5kIHdvcmthcm91bmQpIGV4aXN0IGFjcm9zcyAoTWFjKSBDaHJvbWUsIEZGLCBhbmQgU2FmYXJpXG4gICAgICAgIGxpbmUuYXR0cignZCcsIHBhdGhTdGFydCArIChzaG93R3JhZGllbnRMaW5lID8gJ2wzMCwwLjAwMDEnIDogJ2gzMCcpKVxuICAgICAgICAgICAgLmNhbGwoc2hvd0xpbmUgPyBEcmF3aW5nLmxpbmVHcm91cFN0eWxlIDogbGluZUdyYWRpZW50KTtcblxuICAgICAgICBmdW5jdGlvbiBmaWxsR3JhZGllbnQocykge1xuICAgICAgICAgICAgaWYocy5zaXplKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JhZGllbnRJRCA9ICdsZWdlbmRmaWxsLScgKyB0cmFjZS51aWQ7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5ncmFkaWVudChzLCBnZCwgZ3JhZGllbnRJRCwgJ2hvcml6b250YWxyZXZlcnNlZCcsXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLmNvbG9yc2NhbGUsICdmaWxsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBsaW5lR3JhZGllbnQocykge1xuICAgICAgICAgICAgaWYocy5zaXplKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JhZGllbnRJRCA9ICdsZWdlbmRsaW5lLScgKyB0cmFjZS51aWQ7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5saW5lR3JvdXBTdHlsZShzKTtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLmdyYWRpZW50KHMsIGdkLCBncmFkaWVudElELCAnaG9yaXpvbnRhbHJldmVyc2VkJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UuY29sb3JzY2FsZSwgJ3N0cm9rZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdHlsZVBvaW50cyhkKSB7XG4gICAgICAgIHZhciBkMCA9IGRbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGQwLnRyYWNlO1xuICAgICAgICB2YXIgc2hvd01hcmtlcnMgPSBzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKTtcbiAgICAgICAgdmFyIHNob3dUZXh0ID0gc3ViVHlwZXMuaGFzVGV4dCh0cmFjZSk7XG4gICAgICAgIHZhciBzaG93TGluZXMgPSBzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSk7XG4gICAgICAgIHZhciBkTW9kLCB0TW9kO1xuXG4gICAgICAgIC8vICdzY2F0dGVyM2QnIGRvbid0IHVzZSBnZC5jYWxjZGF0YSxcbiAgICAgICAgLy8gdXNlIGQwLnRyYWNlIHRvIGluZmVyIGFycmF5T2sgYXR0cmlidXRlc1xuXG4gICAgICAgIGZ1bmN0aW9uIGJvdW5kVmFsKGF0dHJJbiwgYXJyYXlUb1ZhbEZuLCBib3VuZHMpIHtcbiAgICAgICAgICAgIHZhciB2YWxJbiA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXR0ckluKS5nZXQoKTtcbiAgICAgICAgICAgIHZhciB2YWxUb0JvdW5kID0gKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHZhbEluKSAmJiBhcnJheVRvVmFsRm4pID9cbiAgICAgICAgICAgICAgICBhcnJheVRvVmFsRm4odmFsSW4pIDpcbiAgICAgICAgICAgICAgICB2YWxJbjtcblxuICAgICAgICAgICAgaWYoYm91bmRzKSB7XG4gICAgICAgICAgICAgICAgaWYodmFsVG9Cb3VuZCA8IGJvdW5kc1swXSkgcmV0dXJuIGJvdW5kc1swXTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmKHZhbFRvQm91bmQgPiBib3VuZHNbMV0pIHJldHVybiBib3VuZHNbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsVG9Cb3VuZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHBpY2tGaXJzdChhcnJheSkgeyByZXR1cm4gYXJyYXlbMF07IH1cblxuICAgICAgICAvLyBjb25zdHJhaW4gdGV4dCwgbWFya2VycywgZXRjIHNvIHRoZXknbGwgZml0IG9uIHRoZSBsZWdlbmRcbiAgICAgICAgaWYoc2hvd01hcmtlcnMgfHwgc2hvd1RleHQgfHwgc2hvd0xpbmVzKSB7XG4gICAgICAgICAgICB2YXIgZEVkaXQgPSB7fTtcbiAgICAgICAgICAgIHZhciB0RWRpdCA9IHt9O1xuXG4gICAgICAgICAgICBpZihzaG93TWFya2Vycykge1xuICAgICAgICAgICAgICAgIGRFZGl0Lm1jID0gYm91bmRWYWwoJ21hcmtlci5jb2xvcicsIHBpY2tGaXJzdCk7XG4gICAgICAgICAgICAgICAgZEVkaXQubXggPSBib3VuZFZhbCgnbWFya2VyLnN5bWJvbCcsIHBpY2tGaXJzdCk7XG4gICAgICAgICAgICAgICAgZEVkaXQubW8gPSBib3VuZFZhbCgnbWFya2VyLm9wYWNpdHknLCBMaWIubWVhbiwgWzAuMiwgMV0pO1xuICAgICAgICAgICAgICAgIGRFZGl0Lm1sYyA9IGJvdW5kVmFsKCdtYXJrZXIubGluZS5jb2xvcicsIHBpY2tGaXJzdCk7XG4gICAgICAgICAgICAgICAgZEVkaXQubWx3ID0gYm91bmRWYWwoJ21hcmtlci5saW5lLndpZHRoJywgTGliLm1lYW4sIFswLCA1XSk7XG4gICAgICAgICAgICAgICAgdEVkaXQubWFya2VyID0ge1xuICAgICAgICAgICAgICAgICAgICBzaXplcmVmOiAxLFxuICAgICAgICAgICAgICAgICAgICBzaXplbWluOiAxLFxuICAgICAgICAgICAgICAgICAgICBzaXplbW9kZTogJ2RpYW1ldGVyJ1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICB2YXIgbXMgPSBib3VuZFZhbCgnbWFya2VyLnNpemUnLCBMaWIubWVhbiwgWzIsIDE2XSk7XG4gICAgICAgICAgICAgICAgZEVkaXQubXMgPSBtcztcbiAgICAgICAgICAgICAgICB0RWRpdC5tYXJrZXIuc2l6ZSA9IG1zO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihzaG93TGluZXMpIHtcbiAgICAgICAgICAgICAgICB0RWRpdC5saW5lID0ge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYm91bmRWYWwoJ2xpbmUud2lkdGgnLCBwaWNrRmlyc3QsIFswLCAxMF0pXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoc2hvd1RleHQpIHtcbiAgICAgICAgICAgICAgICBkRWRpdC50eCA9ICdBYSc7XG4gICAgICAgICAgICAgICAgZEVkaXQudHAgPSBib3VuZFZhbCgndGV4dHBvc2l0aW9uJywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgICAgICBkRWRpdC50cyA9IDEwO1xuICAgICAgICAgICAgICAgIGRFZGl0LnRjID0gYm91bmRWYWwoJ3RleHRmb250LmNvbG9yJywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgICAgICBkRWRpdC50ZiA9IGJvdW5kVmFsKCd0ZXh0Zm9udC5mYW1pbHknLCBwaWNrRmlyc3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkTW9kID0gW0xpYi5taW5FeHRlbmQoZDAsIGRFZGl0KV07XG4gICAgICAgICAgICB0TW9kID0gTGliLm1pbkV4dGVuZCh0cmFjZSwgdEVkaXQpO1xuXG4gICAgICAgICAgICAvLyBhbHdheXMgc2hvdyBsZWdlbmQgaXRlbXMgaW4gYmFzZSBzdGF0ZVxuICAgICAgICAgICAgdE1vZC5zZWxlY3RlZHBvaW50cyA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHRncm91cCA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ2cubGVnZW5kcG9pbnRzJyk7XG5cbiAgICAgICAgdmFyIHB0cyA9IHB0Z3JvdXAuc2VsZWN0QWxsKCdwYXRoLnNjYXR0ZXJwdHMnKVxuICAgICAgICAgICAgLmRhdGEoc2hvd01hcmtlcnMgPyBkTW9kIDogW10pO1xuICAgICAgICAvLyBtYWtlIHN1cmUgbWFya2VyIGlzIG9uIHRoZSBib3R0b20sIGluIGNhc2UgaXQgZW50ZXJzIGFmdGVyIHRleHRcbiAgICAgICAgcHRzLmVudGVyKCkuaW5zZXJ0KCdwYXRoJywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgICAgICAuY2xhc3NlZCgnc2NhdHRlcnB0cycsIHRydWUpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpO1xuICAgICAgICBwdHMuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICBwdHMuY2FsbChEcmF3aW5nLnBvaW50U3R5bGUsIHRNb2QsIGdkKTtcblxuICAgICAgICAvLyAnbXJjJyBpcyBzZXQgaW4gcG9pbnRTdHlsZSBhbmQgdXNlZCBpbiB0ZXh0UG9pbnRTdHlsZTpcbiAgICAgICAgLy8gY29uc3RyYWluIGl0IGhlcmVcbiAgICAgICAgaWYoc2hvd01hcmtlcnMpIGRNb2RbMF0ubXJjID0gMztcblxuICAgICAgICB2YXIgdHh0ID0gcHRncm91cC5zZWxlY3RBbGwoJ2cucG9pbnR0ZXh0JylcbiAgICAgICAgICAgIC5kYXRhKHNob3dUZXh0ID8gZE1vZCA6IFtdKTtcbiAgICAgICAgdHh0LmVudGVyKClcbiAgICAgICAgICAgIC5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdwb2ludHRleHQnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5hcHBlbmQoJ3RleHQnKS5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDIwLDApJyk7XG4gICAgICAgIHR4dC5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIHR4dC5zZWxlY3RBbGwoJ3RleHQnKS5jYWxsKERyYXdpbmcudGV4dFBvaW50U3R5bGUsIHRNb2QsIGdkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdHlsZUJhcnMoZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlLFxuICAgICAgICAgICAgbWFya2VyID0gdHJhY2UubWFya2VyIHx8IHt9LFxuICAgICAgICAgICAgbWFya2VyTGluZSA9IG1hcmtlci5saW5lIHx8IHt9LFxuICAgICAgICAgICAgYmFycGF0aCA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ2cubGVnZW5kcG9pbnRzJylcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoLmxlZ2VuZGJhcicpXG4gICAgICAgICAgICAgICAgLmRhdGEoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JhcicpID8gW2RdIDogW10pO1xuICAgICAgICBiYXJwYXRoLmVudGVyKCkuYXBwZW5kKCdwYXRoJykuY2xhc3NlZCgnbGVnZW5kYmFyJywgdHJ1ZSlcbiAgICAgICAgICAgIC5hdHRyKCdkJywgJ002LDZILTZWLTZINlonKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMjAsMCknKTtcbiAgICAgICAgYmFycGF0aC5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGJhcnBhdGguZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgICAgICAgICAgICBkMCA9IGRbMF0sXG4gICAgICAgICAgICAgICAgdyA9IChkMC5tbHcgKyAxIHx8IG1hcmtlckxpbmUud2lkdGggKyAxKSAtIDE7XG5cbiAgICAgICAgICAgIHAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHcgKyAncHgnKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGQwLm1jIHx8IG1hcmtlci5jb2xvcik7XG5cbiAgICAgICAgICAgIGlmKHcpIHtcbiAgICAgICAgICAgICAgICBwLmNhbGwoQ29sb3Iuc3Ryb2tlLCBkMC5tbGMgfHwgbWFya2VyTGluZS5jb2xvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlQm94ZXMoZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlLFxuICAgICAgICAgICAgcHRzID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kYm94JylcbiAgICAgICAgICAgICAgICAuZGF0YShSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnYm94LXZpb2xpbicpICYmIHRyYWNlLnZpc2libGUgPyBbZF0gOiBbXSk7XG4gICAgICAgIHB0cy5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZGJveCcsIHRydWUpXG4gICAgICAgICAgICAvLyBpZiB3ZSB3YW50IHRoZSBtZWRpYW4gYmFyLCBwcmVwZW5kIE02LDBILTZcbiAgICAgICAgICAgIC5hdHRyKCdkJywgJ002LDZILTZWLTZINlonKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMjAsMCknKTtcbiAgICAgICAgcHRzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgcHRzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgdyA9IHRyYWNlLmxpbmUud2lkdGgsXG4gICAgICAgICAgICAgICAgcCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgcC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgdyArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgdHJhY2UuZmlsbGNvbG9yKTtcblxuICAgICAgICAgICAgaWYodykge1xuICAgICAgICAgICAgICAgIENvbG9yLnN0cm9rZShwLCB0cmFjZS5saW5lLmNvbG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVDYW5kbGVzKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZSxcbiAgICAgICAgICAgIHB0cyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ2cubGVnZW5kcG9pbnRzJylcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoLmxlZ2VuZGNhbmRsZScpXG4gICAgICAgICAgICAgICAgLmRhdGEodHJhY2UudHlwZSA9PT0gJ2NhbmRsZXN0aWNrJyAmJiB0cmFjZS52aXNpYmxlID8gW2QsIGRdIDogW10pO1xuICAgICAgICBwdHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdsZWdlbmRjYW5kbGUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihfLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYoaSkgcmV0dXJuICdNLTE1LDBILThNLTgsNlYtNkg4Wic7IC8vIGluY3JlYXNpbmdcbiAgICAgICAgICAgICAgICByZXR1cm4gJ00xNSwwSDhNOCwtNlY2SC04Wic7IC8vIGRlY3JlYXNpbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIHB0cy5lYWNoKGZ1bmN0aW9uKF8sIGkpIHtcbiAgICAgICAgICAgIHZhciBjb250YWluZXIgPSB0cmFjZVtpID8gJ2luY3JlYXNpbmcnIDogJ2RlY3JlYXNpbmcnXTtcbiAgICAgICAgICAgIHZhciB3ID0gY29udGFpbmVyLmxpbmUud2lkdGgsXG4gICAgICAgICAgICAgICAgcCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgcC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgdyArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgY29udGFpbmVyLmZpbGxjb2xvcik7XG5cbiAgICAgICAgICAgIGlmKHcpIHtcbiAgICAgICAgICAgICAgICBDb2xvci5zdHJva2UocCwgY29udGFpbmVyLmxpbmUuY29sb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdHlsZU9ITEMoZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlLFxuICAgICAgICAgICAgcHRzID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kb2hsYycpXG4gICAgICAgICAgICAgICAgLmRhdGEodHJhY2UudHlwZSA9PT0gJ29obGMnICYmIHRyYWNlLnZpc2libGUgPyBbZCwgZF0gOiBbXSk7XG4gICAgICAgIHB0cy5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZG9obGMnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihfLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYoaSkgcmV0dXJuICdNLTE1LDBIME0tOCwtNlYwJzsgLy8gaW5jcmVhc2luZ1xuICAgICAgICAgICAgICAgIHJldHVybiAnTTE1LDBIME04LDZWMCc7IC8vIGRlY3JlYXNpbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIHB0cy5lYWNoKGZ1bmN0aW9uKF8sIGkpIHtcbiAgICAgICAgICAgIHZhciBjb250YWluZXIgPSB0cmFjZVtpID8gJ2luY3JlYXNpbmcnIDogJ2RlY3JlYXNpbmcnXTtcbiAgICAgICAgICAgIHZhciB3ID0gY29udGFpbmVyLmxpbmUud2lkdGgsXG4gICAgICAgICAgICAgICAgcCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgcC5zdHlsZSgnZmlsbCcsICdub25lJylcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCBjb250YWluZXIubGluZS5kYXNoLCB3KTtcblxuICAgICAgICAgICAgaWYodykge1xuICAgICAgICAgICAgICAgIENvbG9yLnN0cm9rZShwLCBjb250YWluZXIubGluZS5jb2xvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlUGllcyhkKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2UsXG4gICAgICAgICAgICBwdHMgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0KCdnLmxlZ2VuZHBvaW50cycpXG4gICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgncGF0aC5sZWdlbmRwaWUnKVxuICAgICAgICAgICAgICAgIC5kYXRhKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdwaWUnKSAmJiB0cmFjZS52aXNpYmxlID8gW2RdIDogW10pO1xuICAgICAgICBwdHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdsZWdlbmRwaWUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCAnTTYsNkgtNlYtNkg2WicpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpO1xuICAgICAgICBwdHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGlmKHB0cy5zaXplKCkpIHB0cy5jYWxsKHN0eWxlUGllLCBkWzBdLCB0cmFjZSk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBheGlzSWRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgSWNvbnMgPSByZXF1aXJlKCcuLi8uLi8uLi9idWlsZC9wbG90aWNvbicpO1xuXG52YXIgXyA9IExpYi5fO1xuXG52YXIgbW9kZUJhckJ1dHRvbnMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIE1vZGVCYXIgYnV0dG9ucyBjb25maWd1cmF0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqICAgICAgbmFtZSAvIGlkIG9mIHRoZSBidXR0b25zIChmb3IgdHJhY2tpbmcpXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcbiAqICAgICAgdGV4dCB0aGF0IGFwcGVhcnMgd2hpbGUgaG92ZXJpbmcgb3ZlciB0aGUgYnV0dG9uLFxuICogICAgICBlbnRlciBudWxsLCBmYWxzZSBvciAnJyBmb3Igbm8gaG92ZXIgdGV4dFxuICogQHBhcmFtIHtzdHJpbmd9IGljb25cbiAqICAgICAgc3ZnIGljb24gb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgYnV0dG9uXG4gKiAgICAgIGNhbiBiZSBsaW5rZWQgdG8gUGxvdGx5Lkljb25zIHRvIHVzZSB0aGUgZGVmYXVsdCBwbG90bHkgaWNvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBbZ3Jhdml0eV1cbiAqICAgICAgaWNvbiBwb3NpdGlvbmluZ1xuICogQHBhcmFtIHtmdW5jdGlvbn0gY2xpY2tcbiAqICAgICAgY2xpY2sgaGFuZGxlciBhc3NvY2lhdGVkIHdpdGggdGhlIGJ1dHRvbiwgYSBmdW5jdGlvbiBvZlxuICogICAgICAnZ2QnICh0aGUgbWFpbiBncmFwaCBvYmplY3QpIGFuZFxuICogICAgICAnZXYnICh0aGUgZXZlbnQgb2JqZWN0KVxuICogQHBhcmFtIHtzdHJpbmd9IFthdHRyXVxuICogICAgICBhdHRyaWJ1dGUgYXNzb2NpYXRlZCB3aXRoIGJ1dHRvbixcbiAqICAgICAgdXNlIHRoaXMgd2l0aCAndmFsJyB0byBrZWVwIHRyYWNrIG9mIHRoZSBzdGF0ZVxuICogQHBhcmFtIHsqfSBbdmFsXVxuICogICAgICBpbml0aWFsICdhdHRyJyB2YWx1ZSwgY2FuIGJlIGEgZnVuY3Rpb24gb2YgZ2RcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3RvZ2dsZV1cbiAqICAgICAgaXMgdGhlIGJ1dHRvbiBhIHRvZ2dsZSBidXR0b24/XG4gKi9cblxubW9kZUJhckJ1dHRvbnMudG9JbWFnZSA9IHtcbiAgICBuYW1lOiAndG9JbWFnZScsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7XG4gICAgICAgIHZhciBvcHRzID0gZ2QuX2NvbnRleHQudG9JbWFnZUJ1dHRvbk9wdGlvbnMgfHwge307XG4gICAgICAgIHZhciBmb3JtYXQgPSBvcHRzLmZvcm1hdCB8fCAncG5nJztcbiAgICAgICAgcmV0dXJuIGZvcm1hdCA9PT0gJ3BuZycgP1xuICAgICAgICAgICAgXyhnZCwgJ0Rvd25sb2FkIHBsb3QgYXMgYSBwbmcnKSA6IC8vIGxlZ2FjeSB0ZXh0XG4gICAgICAgICAgICBfKGdkLCAnRG93bmxvYWQgcGxvdCcpOyAvLyBnZW5lcmljIG5vbi1QTkcgdGV4dFxuICAgIH0sXG4gICAgaWNvbjogSWNvbnMuY2FtZXJhLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCkge1xuICAgICAgICB2YXIgdG9JbWFnZUJ1dHRvbk9wdGlvbnMgPSBnZC5fY29udGV4dC50b0ltYWdlQnV0dG9uT3B0aW9ucztcbiAgICAgICAgdmFyIG9wdHMgPSB7Zm9ybWF0OiB0b0ltYWdlQnV0dG9uT3B0aW9ucy5mb3JtYXQgfHwgJ3BuZyd9O1xuXG4gICAgICAgIExpYi5ub3RpZmllcihfKGdkLCAnVGFraW5nIHNuYXBzaG90IC0gdGhpcyBtYXkgdGFrZSBhIGZldyBzZWNvbmRzJyksICdsb25nJyk7XG5cbiAgICAgICAgaWYob3B0cy5mb3JtYXQgIT09ICdzdmcnICYmIExpYi5pc0lFKCkpIHtcbiAgICAgICAgICAgIExpYi5ub3RpZmllcihfKGdkLCAnSUUgb25seSBzdXBwb3J0cyBzdmcuICBDaGFuZ2luZyBmb3JtYXQgdG8gc3ZnLicpLCAnbG9uZycpO1xuICAgICAgICAgICAgb3B0cy5mb3JtYXQgPSAnc3ZnJztcbiAgICAgICAgfVxuXG4gICAgICAgIFsnZmlsZW5hbWUnLCAnd2lkdGgnLCAnaGVpZ2h0JywgJ3NjYWxlJ10uZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGlmKHRvSW1hZ2VCdXR0b25PcHRpb25zW2tleV0pIHtcbiAgICAgICAgICAgICAgICBvcHRzW2tleV0gPSB0b0ltYWdlQnV0dG9uT3B0aW9uc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBSZWdpc3RyeS5jYWxsKCdkb3dubG9hZEltYWdlJywgZ2QsIG9wdHMpXG4gICAgICAgICAgLnRoZW4oZnVuY3Rpb24oZmlsZW5hbWUpIHtcbiAgICAgICAgICAgICAgTGliLm5vdGlmaWVyKF8oZ2QsICdTbmFwc2hvdCBzdWNjZWVkZWQnKSArICcgLSAnICsgZmlsZW5hbWUsICdsb25nJyk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIExpYi5ub3RpZmllcihfKGdkLCAnU29ycnksIHRoZXJlIHdhcyBhIHByb2JsZW0gZG93bmxvYWRpbmcgeW91ciBzbmFwc2hvdCEnKSwgJ2xvbmcnKTtcbiAgICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5tb2RlQmFyQnV0dG9ucy5zZW5kRGF0YVRvQ2xvdWQgPSB7XG4gICAgbmFtZTogJ3NlbmREYXRhVG9DbG91ZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnRWRpdCBpbiBDaGFydCBTdHVkaW8nKTsgfSxcbiAgICBpY29uOiBJY29ucy5kaXNrLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCkge1xuICAgICAgICBQbG90cy5zZW5kRGF0YVRvQ2xvdWQoZ2QpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLnpvb20yZCA9IHtcbiAgICBuYW1lOiAnem9vbTJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdab29tJyk7IH0sXG4gICAgYXR0cjogJ2RyYWdtb2RlJyxcbiAgICB2YWw6ICd6b29tJyxcbiAgICBpY29uOiBJY29ucy56b29tYm94LFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLnBhbjJkID0ge1xuICAgIG5hbWU6ICdwYW4yZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnUGFuJyk7IH0sXG4gICAgYXR0cjogJ2RyYWdtb2RlJyxcbiAgICB2YWw6ICdwYW4nLFxuICAgIGljb246IEljb25zLnBhbixcbiAgICBjbGljazogaGFuZGxlQ2FydGVzaWFuXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5zZWxlY3QyZCA9IHtcbiAgICBuYW1lOiAnc2VsZWN0MmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ0JveCBTZWxlY3QnKTsgfSxcbiAgICBhdHRyOiAnZHJhZ21vZGUnLFxuICAgIHZhbDogJ3NlbGVjdCcsXG4gICAgaWNvbjogSWNvbnMuc2VsZWN0Ym94LFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLmxhc3NvMmQgPSB7XG4gICAgbmFtZTogJ2xhc3NvMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ0xhc3NvIFNlbGVjdCcpOyB9LFxuICAgIGF0dHI6ICdkcmFnbW9kZScsXG4gICAgdmFsOiAnbGFzc28nLFxuICAgIGljb246IEljb25zLmxhc3NvLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLnpvb21JbjJkID0ge1xuICAgIG5hbWU6ICd6b29tSW4yZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnWm9vbSBpbicpOyB9LFxuICAgIGF0dHI6ICd6b29tJyxcbiAgICB2YWw6ICdpbicsXG4gICAgaWNvbjogSWNvbnMuem9vbV9wbHVzLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLnpvb21PdXQyZCA9IHtcbiAgICBuYW1lOiAnem9vbU91dDJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdab29tIG91dCcpOyB9LFxuICAgIGF0dHI6ICd6b29tJyxcbiAgICB2YWw6ICdvdXQnLFxuICAgIGljb246IEljb25zLnpvb21fbWludXMsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMuYXV0b1NjYWxlMmQgPSB7XG4gICAgbmFtZTogJ2F1dG9TY2FsZTJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdBdXRvc2NhbGUnKTsgfSxcbiAgICBhdHRyOiAnem9vbScsXG4gICAgdmFsOiAnYXV0bycsXG4gICAgaWNvbjogSWNvbnMuYXV0b3NjYWxlLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0U2NhbGUyZCA9IHtcbiAgICBuYW1lOiAncmVzZXRTY2FsZTJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdSZXNldCBheGVzJyk7IH0sXG4gICAgYXR0cjogJ3pvb20nLFxuICAgIHZhbDogJ3Jlc2V0JyxcbiAgICBpY29uOiBJY29ucy5ob21lLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ2xvc2VzdENhcnRlc2lhbiA9IHtcbiAgICBuYW1lOiAnaG92ZXJDbG9zZXN0Q2FydGVzaWFuJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdTaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogJ2Nsb3Nlc3QnLFxuICAgIGljb246IEljb25zLnRvb2x0aXBfYmFzaWMsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogaGFuZGxlQ2FydGVzaWFuXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5ob3ZlckNvbXBhcmVDYXJ0ZXNpYW4gPSB7XG4gICAgbmFtZTogJ2hvdmVyQ29tcGFyZUNhcnRlc2lhbicsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnQ29tcGFyZSBkYXRhIG9uIGhvdmVyJyk7IH0sXG4gICAgYXR0cjogJ2hvdmVybW9kZScsXG4gICAgdmFsOiBmdW5jdGlvbihnZCkge1xuICAgICAgICByZXR1cm4gZ2QuX2Z1bGxMYXlvdXQuX2lzSG9yaXogPyAneScgOiAneCc7XG4gICAgfSxcbiAgICBpY29uOiBJY29ucy50b29sdGlwX2NvbXBhcmUsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogaGFuZGxlQ2FydGVzaWFuXG59O1xuXG5mdW5jdGlvbiBoYW5kbGVDYXJ0ZXNpYW4oZ2QsIGV2KSB7XG4gICAgdmFyIGJ1dHRvbiA9IGV2LmN1cnJlbnRUYXJnZXQ7XG4gICAgdmFyIGFzdHIgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLWF0dHInKTtcbiAgICB2YXIgdmFsID0gYnV0dG9uLmdldEF0dHJpYnV0ZSgnZGF0YS12YWwnKSB8fCB0cnVlO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGFvYmogPSB7fTtcbiAgICB2YXIgYXhMaXN0ID0gYXhpc0lkcy5saXN0KGdkLCBudWxsLCB0cnVlKTtcbiAgICB2YXIgYWxsU3Bpa2VzRW5hYmxlZCA9ICdvbic7XG5cbiAgICB2YXIgYXgsIGk7XG5cbiAgICBpZihhc3RyID09PSAnem9vbScpIHtcbiAgICAgICAgdmFyIG1hZyA9ICh2YWwgPT09ICdpbicpID8gMC41IDogMixcbiAgICAgICAgICAgIHIwID0gKDEgKyBtYWcpIC8gMixcbiAgICAgICAgICAgIHIxID0gKDEgLSBtYWcpIC8gMjtcblxuICAgICAgICB2YXIgYXhOYW1lO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXggPSBheExpc3RbaV07XG5cbiAgICAgICAgICAgIGlmKCFheC5maXhlZHJhbmdlKSB7XG4gICAgICAgICAgICAgICAgYXhOYW1lID0gYXguX25hbWU7XG4gICAgICAgICAgICAgICAgaWYodmFsID09PSAnYXV0bycpIGFvYmpbYXhOYW1lICsgJy5hdXRvcmFuZ2UnXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgZWxzZSBpZih2YWwgPT09ICdyZXNldCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoYXguX3JhbmdlSW5pdGlhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhb2JqW2F4TmFtZSArICcuYXV0b3JhbmdlJ10gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhbmdlSW5pdGlhbCA9IGF4Ll9yYW5nZUluaXRpYWwuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFvYmpbYXhOYW1lICsgJy5yYW5nZVswXSddID0gcmFuZ2VJbml0aWFsWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYW9ialtheE5hbWUgKyAnLnJhbmdlWzFdJ10gPSByYW5nZUluaXRpYWxbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYoYXguX3Nob3dTcGlrZUluaXRpYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW9ialtheE5hbWUgKyAnLnNob3dzcGlrZXMnXSA9IGF4Ll9zaG93U3Bpa2VJbml0aWFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoYWxsU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyAmJiAhYXguX3Nob3dTcGlrZUluaXRpYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxTcGlrZXNFbmFibGVkID0gJ29mZic7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByYW5nZU5vdyA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4LnIybChheC5yYW5nZVswXSksXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5yMmwoYXgucmFuZ2VbMV0pLFxuICAgICAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciByYW5nZU5ldyA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHIwICogcmFuZ2VOb3dbMF0gKyByMSAqIHJhbmdlTm93WzFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgcjAgKiByYW5nZU5vd1sxXSArIHIxICogcmFuZ2VOb3dbMF1cbiAgICAgICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgICAgICBhb2JqW2F4TmFtZSArICcucmFuZ2VbMF0nXSA9IGF4LmwycihyYW5nZU5ld1swXSk7XG4gICAgICAgICAgICAgICAgICAgIGFvYmpbYXhOYW1lICsgJy5yYW5nZVsxXSddID0gYXgubDJyKHJhbmdlTmV3WzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVsbExheW91dC5fY2FydGVzaWFuU3Bpa2VzRW5hYmxlZCA9IGFsbFNwaWtlc0VuYWJsZWQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyBpZiBBTEwgdHJhY2VzIGhhdmUgb3JpZW50YXRpb24gJ2gnLCAnaG92ZXJtb2RlJzogJ3gnIG90aGVyd2lzZTogJ3knXG4gICAgICAgIGlmKGFzdHIgPT09ICdob3Zlcm1vZGUnICYmICh2YWwgPT09ICd4JyB8fCB2YWwgPT09ICd5JykpIHtcbiAgICAgICAgICAgIHZhbCA9IGZ1bGxMYXlvdXQuX2lzSG9yaXogPyAneScgOiAneCc7XG4gICAgICAgICAgICBidXR0b24uc2V0QXR0cmlidXRlKCdkYXRhLXZhbCcsIHZhbCk7XG4gICAgICAgIH0gZWxzZSBpZihhc3RyID09PSAnaG92ZXJtb2RlJyAmJiB2YWwgPT09ICdjbG9zZXN0Jykge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYXggPSBheExpc3RbaV07XG4gICAgICAgICAgICAgICAgaWYoYWxsU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyAmJiAhYXguc2hvd3NwaWtlcykge1xuICAgICAgICAgICAgICAgICAgICBhbGxTcGlrZXNFbmFibGVkID0gJ29mZic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVsbExheW91dC5fY2FydGVzaWFuU3Bpa2VzRW5hYmxlZCA9IGFsbFNwaWtlc0VuYWJsZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBhb2JqW2FzdHJdID0gdmFsO1xuICAgIH1cblxuICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGFvYmopO1xufVxuXG5tb2RlQmFyQnV0dG9ucy56b29tM2QgPSB7XG4gICAgbmFtZTogJ3pvb20zZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnWm9vbScpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAnem9vbScsXG4gICAgaWNvbjogSWNvbnMuem9vbWJveCxcbiAgICBjbGljazogaGFuZGxlRHJhZzNkXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5wYW4zZCA9IHtcbiAgICBuYW1lOiAncGFuM2QnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1BhbicpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAncGFuJyxcbiAgICBpY29uOiBJY29ucy5wYW4sXG4gICAgY2xpY2s6IGhhbmRsZURyYWczZFxufTtcblxubW9kZUJhckJ1dHRvbnMub3JiaXRSb3RhdGlvbiA9IHtcbiAgICBuYW1lOiAnb3JiaXRSb3RhdGlvbicsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnT3JiaXRhbCByb3RhdGlvbicpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAnb3JiaXQnLFxuICAgIGljb246IEljb25zWyczZF9yb3RhdGUnXSxcbiAgICBjbGljazogaGFuZGxlRHJhZzNkXG59O1xuXG5tb2RlQmFyQnV0dG9ucy50YWJsZVJvdGF0aW9uID0ge1xuICAgIG5hbWU6ICd0YWJsZVJvdGF0aW9uJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdUdXJudGFibGUgcm90YXRpb24nKTsgfSxcbiAgICBhdHRyOiAnc2NlbmUuZHJhZ21vZGUnLFxuICAgIHZhbDogJ3R1cm50YWJsZScsXG4gICAgaWNvbjogSWNvbnNbJ3otYXhpcyddLFxuICAgIGNsaWNrOiBoYW5kbGVEcmFnM2Rcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZURyYWczZChnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgYXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgIHZhciB2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWU7XG4gICAgdmFyIHNjZW5lSWRzID0gZ2QuX2Z1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG4gICAgdmFyIGxheW91dFVwZGF0ZSA9IHt9O1xuXG4gICAgdmFyIHBhcnRzID0gYXR0ci5zcGxpdCgnLicpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheW91dFVwZGF0ZVtzY2VuZUlkc1tpXSArICcuJyArIHBhcnRzWzFdXSA9IHZhbDtcbiAgICB9XG5cbiAgICAvLyBmb3IgbXVsdGktdHlwZSBzdWJwbG90c1xuICAgIHZhciB2YWwyZCA9ICh2YWwgPT09ICdwYW4nKSA/IHZhbCA6ICd6b29tJztcbiAgICBsYXlvdXRVcGRhdGUuZHJhZ21vZGUgPSB2YWwyZDtcblxuICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGxheW91dFVwZGF0ZSk7XG59XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0Q2FtZXJhRGVmYXVsdDNkID0ge1xuICAgIG5hbWU6ICdyZXNldENhbWVyYURlZmF1bHQzZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnUmVzZXQgY2FtZXJhIHRvIGRlZmF1bHQnKTsgfSxcbiAgICBhdHRyOiAncmVzZXREZWZhdWx0JyxcbiAgICBpY29uOiBJY29ucy5ob21lLFxuICAgIGNsaWNrOiBoYW5kbGVDYW1lcmEzZFxufTtcblxubW9kZUJhckJ1dHRvbnMucmVzZXRDYW1lcmFMYXN0U2F2ZTNkID0ge1xuICAgIG5hbWU6ICdyZXNldENhbWVyYUxhc3RTYXZlM2QnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IGNhbWVyYSB0byBsYXN0IHNhdmUnKTsgfSxcbiAgICBhdHRyOiAncmVzZXRMYXN0U2F2ZScsXG4gICAgaWNvbjogSWNvbnMubW92aWUsXG4gICAgY2xpY2s6IGhhbmRsZUNhbWVyYTNkXG59O1xuXG5mdW5jdGlvbiBoYW5kbGVDYW1lcmEzZChnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgYXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHNjZW5lSWRzID0gZnVsbExheW91dC5fc3VicGxvdHMuZ2wzZDtcbiAgICB2YXIgYW9iaiA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzY2VuZUlkID0gc2NlbmVJZHNbaV0sXG4gICAgICAgICAgICBrZXkgPSBzY2VuZUlkICsgJy5jYW1lcmEnLFxuICAgICAgICAgICAgc2NlbmUgPSBmdWxsTGF5b3V0W3NjZW5lSWRdLl9zY2VuZTtcblxuICAgICAgICBpZihhdHRyID09PSAncmVzZXREZWZhdWx0Jykge1xuICAgICAgICAgICAgYW9ialtrZXldID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF0dHIgPT09ICdyZXNldExhc3RTYXZlJykge1xuICAgICAgICAgICAgYW9ialtrZXldID0gTGliLmV4dGVuZERlZXAoe30sIHNjZW5lLmNhbWVyYUluaXRpYWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYW9iaik7XG59XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ2xvc2VzdDNkID0ge1xuICAgIG5hbWU6ICdob3ZlckNsb3Nlc3QzZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnVG9nZ2xlIHNob3cgY2xvc2VzdCBkYXRhIG9uIGhvdmVyJyk7IH0sXG4gICAgYXR0cjogJ2hvdmVybW9kZScsXG4gICAgdmFsOiBudWxsLFxuICAgIHRvZ2dsZTogdHJ1ZSxcbiAgICBpY29uOiBJY29ucy50b29sdGlwX2Jhc2ljLFxuICAgIGdyYXZpdHk6ICduZScsXG4gICAgY2xpY2s6IGhhbmRsZUhvdmVyM2Rcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUhvdmVyM2QoZ2QsIGV2KSB7XG4gICAgdmFyIGJ1dHRvbiA9IGV2LmN1cnJlbnRUYXJnZXQ7XG4gICAgdmFyIHZhbCA9IGJ1dHRvbi5fcHJldmlvdXNWYWwgfHwgZmFsc2U7XG4gICAgdmFyIGxheW91dCA9IGdkLmxheW91dDtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG5cbiAgICB2YXIgYXhlcyA9IFsneGF4aXMnLCAneWF4aXMnLCAnemF4aXMnXTtcbiAgICB2YXIgc3Bpa2VBdHRycyA9IFsnc2hvd3NwaWtlcycsICdzcGlrZXNpZGVzJywgJ3NwaWtldGhpY2tuZXNzJywgJ3NwaWtlY29sb3InXTtcblxuICAgIC8vIGluaXRpYWxpemUgJ2N1cnJlbnQgc3Bpa2UnIG9iamVjdCB0byBiZSBzdG9yZWQgaW4gdGhlIERPTVxuICAgIHZhciBjdXJyZW50U3Bpa2VzID0ge307XG4gICAgdmFyIGF4aXNTcGlrZXMgPSB7fTtcbiAgICB2YXIgbGF5b3V0VXBkYXRlID0ge307XG5cbiAgICBpZih2YWwpIHtcbiAgICAgICAgbGF5b3V0VXBkYXRlID0gTGliLmV4dGVuZERlZXAobGF5b3V0LCB2YWwpO1xuICAgICAgICBidXR0b24uX3ByZXZpb3VzVmFsID0gbnVsbDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGxheW91dFVwZGF0ZSA9IHtcbiAgICAgICAgICAgICdhbGxheGVzLnNob3dzcGlrZXMnOiBmYWxzZVxuICAgICAgICB9O1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzY2VuZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNjZW5lSWQgPSBzY2VuZUlkc1tpXSxcbiAgICAgICAgICAgICAgICBzY2VuZUxheW91dCA9IGZ1bGxMYXlvdXRbc2NlbmVJZF0sXG4gICAgICAgICAgICAgICAgc2NlbmVTcGlrZXMgPSBjdXJyZW50U3Bpa2VzW3NjZW5lSWRdID0ge307XG5cbiAgICAgICAgICAgIHNjZW5lU3Bpa2VzLmhvdmVybW9kZSA9IHNjZW5lTGF5b3V0LmhvdmVybW9kZTtcbiAgICAgICAgICAgIGxheW91dFVwZGF0ZVtzY2VuZUlkICsgJy5ob3Zlcm1vZGUnXSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBjb3B5IGFsbCB0aGUgY3VycmVudCBzcGlrZSBhdHRyc1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBheGlzID0gYXhlc1tqXTtcbiAgICAgICAgICAgICAgICBheGlzU3Bpa2VzID0gc2NlbmVTcGlrZXNbYXhpc10gPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCBzcGlrZUF0dHJzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzcGlrZUF0dHIgPSBzcGlrZUF0dHJzW2tdO1xuICAgICAgICAgICAgICAgICAgICBheGlzU3Bpa2VzW3NwaWtlQXR0cl0gPSBzY2VuZUxheW91dFtheGlzXVtzcGlrZUF0dHJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJ1dHRvbi5fcHJldmlvdXNWYWwgPSBMaWIuZXh0ZW5kRGVlcCh7fSwgY3VycmVudFNwaWtlcyk7XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgbGF5b3V0VXBkYXRlKTtcbn1cblxubW9kZUJhckJ1dHRvbnMuem9vbUluR2VvID0ge1xuICAgIG5hbWU6ICd6b29tSW5HZW8nLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1pvb20gaW4nKTsgfSxcbiAgICBhdHRyOiAnem9vbScsXG4gICAgdmFsOiAnaW4nLFxuICAgIGljb246IEljb25zLnpvb21fcGx1cyxcbiAgICBjbGljazogaGFuZGxlR2VvXG59O1xuXG5tb2RlQmFyQnV0dG9ucy56b29tT3V0R2VvID0ge1xuICAgIG5hbWU6ICd6b29tT3V0R2VvJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdab29tIG91dCcpOyB9LFxuICAgIGF0dHI6ICd6b29tJyxcbiAgICB2YWw6ICdvdXQnLFxuICAgIGljb246IEljb25zLnpvb21fbWludXMsXG4gICAgY2xpY2s6IGhhbmRsZUdlb1xufTtcblxubW9kZUJhckJ1dHRvbnMucmVzZXRHZW8gPSB7XG4gICAgbmFtZTogJ3Jlc2V0R2VvJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdSZXNldCcpOyB9LFxuICAgIGF0dHI6ICdyZXNldCcsXG4gICAgdmFsOiBudWxsLFxuICAgIGljb246IEljb25zLmF1dG9zY2FsZSxcbiAgICBjbGljazogaGFuZGxlR2VvXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5ob3ZlckNsb3Nlc3RHZW8gPSB7XG4gICAgbmFtZTogJ2hvdmVyQ2xvc2VzdEdlbycsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnVG9nZ2xlIHNob3cgY2xvc2VzdCBkYXRhIG9uIGhvdmVyJyk7IH0sXG4gICAgYXR0cjogJ2hvdmVybW9kZScsXG4gICAgdmFsOiBudWxsLFxuICAgIHRvZ2dsZTogdHJ1ZSxcbiAgICBpY29uOiBJY29ucy50b29sdGlwX2Jhc2ljLFxuICAgIGdyYXZpdHk6ICduZScsXG4gICAgY2xpY2s6IHRvZ2dsZUhvdmVyXG59O1xuXG5mdW5jdGlvbiBoYW5kbGVHZW8oZ2QsIGV2KSB7XG4gICAgdmFyIGJ1dHRvbiA9IGV2LmN1cnJlbnRUYXJnZXQ7XG4gICAgdmFyIGF0dHIgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLWF0dHInKTtcbiAgICB2YXIgdmFsID0gYnV0dG9uLmdldEF0dHJpYnV0ZSgnZGF0YS12YWwnKSB8fCB0cnVlO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGdlb0lkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdlbztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBnZW9JZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gZ2VvSWRzW2ldO1xuICAgICAgICB2YXIgZ2VvTGF5b3V0ID0gZnVsbExheW91dFtpZF07XG5cbiAgICAgICAgaWYoYXR0ciA9PT0gJ3pvb20nKSB7XG4gICAgICAgICAgICB2YXIgc2NhbGUgPSBnZW9MYXlvdXQucHJvamVjdGlvbi5zY2FsZTtcbiAgICAgICAgICAgIHZhciBuZXdTY2FsZSA9ICh2YWwgPT09ICdpbicpID8gMiAqIHNjYWxlIDogMC41ICogc2NhbGU7XG5cbiAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGlkICsgJy5wcm9qZWN0aW9uLnNjYWxlJywgbmV3U2NhbGUpO1xuICAgICAgICB9IGVsc2UgaWYoYXR0ciA9PT0gJ3Jlc2V0Jykge1xuICAgICAgICAgICAgcmVzZXRWaWV3KGdkLCAnZ2VvJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ2xvc2VzdEdsMmQgPSB7XG4gICAgbmFtZTogJ2hvdmVyQ2xvc2VzdEdsMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogbnVsbCxcbiAgICB0b2dnbGU6IHRydWUsXG4gICAgaWNvbjogSWNvbnMudG9vbHRpcF9iYXNpYyxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiB0b2dnbGVIb3ZlclxufTtcblxubW9kZUJhckJ1dHRvbnMuaG92ZXJDbG9zZXN0UGllID0ge1xuICAgIG5hbWU6ICdob3ZlckNsb3Nlc3RQaWUnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogJ2Nsb3Nlc3QnLFxuICAgIGljb246IEljb25zLnRvb2x0aXBfYmFzaWMsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogdG9nZ2xlSG92ZXJcbn07XG5cbmZ1bmN0aW9uIHRvZ2dsZUhvdmVyKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBvbkhvdmVyVmFsO1xuICAgIGlmKGZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJykpIHtcbiAgICAgICAgb25Ib3ZlclZhbCA9IGZ1bGxMYXlvdXQuX2lzSG9yaXogPyAneScgOiAneCc7XG4gICAgfVxuICAgIGVsc2Ugb25Ib3ZlclZhbCA9ICdjbG9zZXN0JztcblxuICAgIHZhciBuZXdIb3ZlciA9IGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA/IGZhbHNlIDogb25Ib3ZlclZhbDtcblxuICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsICdob3Zlcm1vZGUnLCBuZXdIb3Zlcik7XG59XG5cbi8vIGJ1dHRvbnMgd2hlbiBtb3JlIHRoZW4gb25lIHBsb3QgdHlwZXMgYXJlIHByZXNlbnRcblxubW9kZUJhckJ1dHRvbnMudG9nZ2xlSG92ZXIgPSB7XG4gICAgbmFtZTogJ3RvZ2dsZUhvdmVyJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdUb2dnbGUgc2hvdyBjbG9zZXN0IGRhdGEgb24gaG92ZXInKTsgfSxcbiAgICBhdHRyOiAnaG92ZXJtb2RlJyxcbiAgICB2YWw6IG51bGwsXG4gICAgdG9nZ2xlOiB0cnVlLFxuICAgIGljb246IEljb25zLnRvb2x0aXBfYmFzaWMsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QsIGV2KSB7XG4gICAgICAgIHRvZ2dsZUhvdmVyKGdkKTtcblxuICAgICAgICAvLyB0aGUgM2QgaG92ZXJtb2RlIHVwZGF0ZSBtdXN0IGNvbWVcbiAgICAgICAgLy8gbGFzdCBzbyB0aGF0IGxheW91dC5ob3Zlcm1vZGUgdXBkYXRlIGRvZXMgbm90XG4gICAgICAgIC8vIG92ZXJyaWRlIHNjZW5lPy5ob3Zlcm1vZGU/LmxheW91dC5cbiAgICAgICAgaGFuZGxlSG92ZXIzZChnZCwgZXYpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0Vmlld3MgPSB7XG4gICAgbmFtZTogJ3Jlc2V0Vmlld3MnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IHZpZXdzJyk7IH0sXG4gICAgaWNvbjogSWNvbnMuaG9tZSxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QsIGV2KSB7XG4gICAgICAgIHZhciBidXR0b24gPSBldi5jdXJyZW50VGFyZ2V0O1xuXG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicsICd6b29tJyk7XG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtdmFsJywgJ3Jlc2V0Jyk7XG4gICAgICAgIGhhbmRsZUNhcnRlc2lhbihnZCwgZXYpO1xuXG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicsICdyZXNldExhc3RTYXZlJyk7XG4gICAgICAgIGhhbmRsZUNhbWVyYTNkKGdkLCBldik7XG5cbiAgICAgICAgcmVzZXRWaWV3KGdkLCAnZ2VvJyk7XG4gICAgICAgIHJlc2V0VmlldyhnZCwgJ21hcGJveCcpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLnRvZ2dsZVNwaWtlbGluZXMgPSB7XG4gICAgbmFtZTogJ3RvZ2dsZVNwaWtlbGluZXMnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBTcGlrZSBMaW5lcycpOyB9LFxuICAgIGljb246IEljb25zLnNwaWtlbGluZSxcbiAgICBhdHRyOiAnX2NhcnRlc2lhblNwaWtlc0VuYWJsZWQnLFxuICAgIHZhbDogJ29uJyxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgICAgICBmdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5TcGlrZXNFbmFibGVkID0gZnVsbExheW91dC5fY2FydGVzaWFuU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyA/ICdvZmYnIDogJ29uJztcblxuICAgICAgICB2YXIgYW9iaiA9IHNldFNwaWtlbGluZVZpc2liaWxpdHkoZ2QpO1xuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGFvYmopO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHNldFNwaWtlbGluZVZpc2liaWxpdHkoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBheExpc3QgPSBheGlzSWRzLmxpc3QoZ2QsIG51bGwsIHRydWUpO1xuICAgIHZhciBhb2JqID0ge307XG5cbiAgICB2YXIgYXgsIGF4TmFtZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXggPSBheExpc3RbaV07XG4gICAgICAgIGF4TmFtZSA9IGF4Ll9uYW1lO1xuICAgICAgICBhb2JqW2F4TmFtZSArICcuc2hvd3NwaWtlcyddID0gZnVsbExheW91dC5fY2FydGVzaWFuU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyA/IHRydWUgOiBheC5fc2hvd1NwaWtlSW5pdGlhbDtcbiAgICB9XG5cbiAgICByZXR1cm4gYW9iajtcbn1cblxubW9kZUJhckJ1dHRvbnMucmVzZXRWaWV3TWFwYm94ID0ge1xuICAgIG5hbWU6ICdyZXNldFZpZXdNYXBib3gnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IHZpZXcnKTsgfSxcbiAgICBhdHRyOiAncmVzZXQnLFxuICAgIGljb246IEljb25zLmhvbWUsXG4gICAgY2xpY2s6IGZ1bmN0aW9uKGdkKSB7XG4gICAgICAgIHJlc2V0VmlldyhnZCwgJ21hcGJveCcpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHJlc2V0VmlldyhnZCwgc3VicGxvdFR5cGUpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbc3VicGxvdFR5cGVdO1xuICAgIHZhciBhT2JqID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBzdWJwbG90SWRzW2ldO1xuICAgICAgICB2YXIgc3VicGxvdE9iaiA9IGZ1bGxMYXlvdXRbaWRdLl9zdWJwbG90O1xuICAgICAgICB2YXIgdmlld0luaXRpYWwgPSBzdWJwbG90T2JqLnZpZXdJbml0aWFsO1xuICAgICAgICB2YXIgdmlld0tleXMgPSBPYmplY3Qua2V5cyh2aWV3SW5pdGlhbCk7XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHZpZXdLZXlzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gdmlld0tleXNbal07XG4gICAgICAgICAgICBhT2JqW2lkICsgJy4nICsga2V5XSA9IHZpZXdJbml0aWFsW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBhT2JqKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLm1hbmFnZSA9IHJlcXVpcmUoJy4vbWFuYWdlJyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGF4aXNJZHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcbnZhciBzY2F0dGVyU3ViVHlwZXMgPSByZXF1aXJlKCcuLi8uLi90cmFjZXMvc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGNyZWF0ZU1vZGVCYXIgPSByZXF1aXJlKCcuL21vZGViYXInKTtcbnZhciBtb2RlQmFyQnV0dG9ucyA9IHJlcXVpcmUoJy4vYnV0dG9ucycpO1xuXG4vKipcbiAqIE1vZGVCYXIgd3JhcHBlciBhcm91bmQgJ2NyZWF0ZScgYW5kICd1cGRhdGUnLFxuICogY2hvb3NlcyBidXR0b25zIHRvIHBhc3MgdG8gTW9kZUJhciBjb25zdHJ1Y3RvciBiYXNlZCBvblxuICogcGxvdCB0eXBlIGFuZCBwbG90IGNvbmZpZy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZ2QgbWFpbiBwbG90IG9iamVjdFxuICpcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYW5hZ2VNb2RlQmFyKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCxcbiAgICAgICAgY29udGV4dCA9IGdkLl9jb250ZXh0LFxuICAgICAgICBtb2RlQmFyID0gZnVsbExheW91dC5fbW9kZUJhcjtcblxuICAgIGlmKCFjb250ZXh0LmRpc3BsYXlNb2RlQmFyKSB7XG4gICAgICAgIGlmKG1vZGVCYXIpIHtcbiAgICAgICAgICAgIG1vZGVCYXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgZGVsZXRlIGZ1bGxMYXlvdXQuX21vZGVCYXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGNvbnRleHQubW9kZUJhckJ1dHRvbnNUb1JlbW92ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFtcbiAgICAgICAgICAgICcqbW9kZUJhckJ1dHRvbnNUb1JlbW92ZSogY29uZmlndXJhdGlvbiBvcHRpb25zJyxcbiAgICAgICAgICAgICdtdXN0IGJlIGFuIGFycmF5LidcbiAgICAgICAgXS5qb2luKCcgJykpO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGNvbnRleHQubW9kZUJhckJ1dHRvbnNUb0FkZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFtcbiAgICAgICAgICAgICcqbW9kZUJhckJ1dHRvbnNUb0FkZCogY29uZmlndXJhdGlvbiBvcHRpb25zJyxcbiAgICAgICAgICAgICdtdXN0IGJlIGFuIGFycmF5LidcbiAgICAgICAgXS5qb2luKCcgJykpO1xuICAgIH1cblxuICAgIHZhciBjdXN0b21CdXR0b25zID0gY29udGV4dC5tb2RlQmFyQnV0dG9ucztcbiAgICB2YXIgYnV0dG9uR3JvdXBzO1xuXG4gICAgaWYoQXJyYXkuaXNBcnJheShjdXN0b21CdXR0b25zKSAmJiBjdXN0b21CdXR0b25zLmxlbmd0aCkge1xuICAgICAgICBidXR0b25Hcm91cHMgPSBmaWxsQ3VzdG9tQnV0dG9uKGN1c3RvbUJ1dHRvbnMpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYnV0dG9uR3JvdXBzID0gZ2V0QnV0dG9uR3JvdXBzKFxuICAgICAgICAgICAgZ2QsXG4gICAgICAgICAgICBjb250ZXh0Lm1vZGVCYXJCdXR0b25zVG9SZW1vdmUsXG4gICAgICAgICAgICBjb250ZXh0Lm1vZGVCYXJCdXR0b25zVG9BZGRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBpZihtb2RlQmFyKSBtb2RlQmFyLnVwZGF0ZShnZCwgYnV0dG9uR3JvdXBzKTtcbiAgICBlbHNlIGZ1bGxMYXlvdXQuX21vZGVCYXIgPSBjcmVhdGVNb2RlQmFyKGdkLCBidXR0b25Hcm91cHMpO1xufTtcblxuLy8gbG9naWMgYmVoaW5kIHdoaWNoIGJ1dHRvbnMgYXJlIGRpc3BsYXllZCBieSBkZWZhdWx0XG5mdW5jdGlvbiBnZXRCdXR0b25Hcm91cHMoZ2QsIGJ1dHRvbnNUb1JlbW92ZSwgYnV0dG9uc1RvQWRkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG5cbiAgICB2YXIgaGFzQ2FydGVzaWFuID0gZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKTtcbiAgICB2YXIgaGFzR0wzRCA9IGZ1bGxMYXlvdXQuX2hhcygnZ2wzZCcpO1xuICAgIHZhciBoYXNHZW8gPSBmdWxsTGF5b3V0Ll9oYXMoJ2dlbycpO1xuICAgIHZhciBoYXNQaWUgPSBmdWxsTGF5b3V0Ll9oYXMoJ3BpZScpO1xuICAgIHZhciBoYXNHTDJEID0gZnVsbExheW91dC5faGFzKCdnbDJkJyk7XG4gICAgdmFyIGhhc1Rlcm5hcnkgPSBmdWxsTGF5b3V0Ll9oYXMoJ3Rlcm5hcnknKTtcbiAgICB2YXIgaGFzTWFwYm94ID0gZnVsbExheW91dC5faGFzKCdtYXBib3gnKTtcbiAgICB2YXIgaGFzUG9sYXIgPSBmdWxsTGF5b3V0Ll9oYXMoJ3BvbGFyJyk7XG4gICAgdmFyIGFsbEF4ZXNGaXhlZCA9IGFyZUFsbEF4ZXNGaXhlZChmdWxsTGF5b3V0KTtcblxuICAgIHZhciBncm91cHMgPSBbXTtcblxuICAgIGZ1bmN0aW9uIGFkZEdyb3VwKG5ld0dyb3VwKSB7XG4gICAgICAgIGlmKCFuZXdHcm91cC5sZW5ndGgpIHJldHVybjtcblxuICAgICAgICB2YXIgb3V0ID0gW107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG5ld0dyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gbmV3R3JvdXBbaV07XG4gICAgICAgICAgICBpZihidXR0b25zVG9SZW1vdmUuaW5kZXhPZihidXR0b24pICE9PSAtMSkgY29udGludWU7XG4gICAgICAgICAgICBvdXQucHVzaChtb2RlQmFyQnV0dG9uc1tidXR0b25dKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdyb3Vwcy5wdXNoKG91dCk7XG4gICAgfVxuXG4gICAgLy8gYnV0dG9ucyBjb21tb24gdG8gYWxsIHBsb3QgdHlwZXNcbiAgICBhZGRHcm91cChbJ3RvSW1hZ2UnLCAnc2VuZERhdGFUb0Nsb3VkJ10pO1xuXG4gICAgdmFyIHpvb21Hcm91cCA9IFtdO1xuICAgIHZhciBob3Zlckdyb3VwID0gW107XG4gICAgdmFyIHJlc2V0R3JvdXAgPSBbXTtcbiAgICB2YXIgZHJhZ01vZGVHcm91cCA9IFtdO1xuXG4gICAgaWYoKGhhc0NhcnRlc2lhbiB8fCBoYXNHTDJEIHx8IGhhc1BpZSB8fCBoYXNUZXJuYXJ5KSArIGhhc0dlbyArIGhhc0dMM0QgKyBoYXNNYXBib3ggKyBoYXNQb2xhciA+IDEpIHtcbiAgICAgICAgLy8gZ3JhcGhzIHdpdGggbW9yZSB0aGFuIG9uZSBwbG90IHR5cGVzIGdldCAndW5pb24gYnV0dG9ucydcbiAgICAgICAgLy8gd2hpY2ggcmVzZXQgdGhlIHZpZXcgb3IgdG9nZ2xlIGhvdmVyIGxhYmVscyBhY3Jvc3MgYWxsIHN1YnBsb3RzLlxuICAgICAgICBob3Zlckdyb3VwID0gWyd0b2dnbGVIb3ZlciddO1xuICAgICAgICByZXNldEdyb3VwID0gWydyZXNldFZpZXdzJ107XG4gICAgfVxuICAgIGVsc2UgaWYoaGFzR2VvKSB7XG4gICAgICAgIHpvb21Hcm91cCA9IFsnem9vbUluR2VvJywgJ3pvb21PdXRHZW8nXTtcbiAgICAgICAgaG92ZXJHcm91cCA9IFsnaG92ZXJDbG9zZXN0R2VvJ107XG4gICAgICAgIHJlc2V0R3JvdXAgPSBbJ3Jlc2V0R2VvJ107XG4gICAgfVxuICAgIGVsc2UgaWYoaGFzR0wzRCkge1xuICAgICAgICBob3Zlckdyb3VwID0gWydob3ZlckNsb3Nlc3QzZCddO1xuICAgICAgICByZXNldEdyb3VwID0gWydyZXNldENhbWVyYURlZmF1bHQzZCcsICdyZXNldENhbWVyYUxhc3RTYXZlM2QnXTtcbiAgICB9XG4gICAgZWxzZSBpZihoYXNNYXBib3gpIHtcbiAgICAgICAgaG92ZXJHcm91cCA9IFsndG9nZ2xlSG92ZXInXTtcbiAgICAgICAgcmVzZXRHcm91cCA9IFsncmVzZXRWaWV3TWFwYm94J107XG4gICAgfVxuICAgIGVsc2UgaWYoaGFzR0wyRCkge1xuICAgICAgICBob3Zlckdyb3VwID0gWydob3ZlckNsb3Nlc3RHbDJkJ107XG4gICAgfVxuICAgIGVsc2UgaWYoaGFzUGllKSB7XG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ2hvdmVyQ2xvc2VzdFBpZSddO1xuICAgIH1cbiAgICBlbHNlIHsgLy8gaGFzUG9sYXIsIGhhc1Rlcm5hcnlcbiAgICAgICAgLy8gYWx3YXlzIHNob3cgYXQgbGVhc3Qgb25lIGhvdmVyIGljb24uXG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ3RvZ2dsZUhvdmVyJ107XG4gICAgfVxuICAgIC8vIGlmIHdlIGhhdmUgY2FydGVzaWFuLCBhbGxvdyBzd2l0Y2hpbmcgYmV0d2VlbiBjbG9zZXN0IGFuZCBjb21wYXJlXG4gICAgLy8gcmVnYXJkbGVzcyBvZiB3aGF0IG90aGVyIHR5cGVzIGFyZSBvbiB0aGUgcGxvdCwgc2luY2UgdGhleSdsbCBhbGxcbiAgICAvLyBqdXN0IHRyZWF0IGFueSB0cnV0aHkgaG92ZXJtb2RlIGFzICdjbG9zZXN0J1xuICAgIGlmKGhhc0NhcnRlc2lhbikge1xuICAgICAgICBob3Zlckdyb3VwID0gWyd0b2dnbGVTcGlrZWxpbmVzJywgJ2hvdmVyQ2xvc2VzdENhcnRlc2lhbicsICdob3ZlckNvbXBhcmVDYXJ0ZXNpYW4nXTtcbiAgICB9XG5cbiAgICBpZigoaGFzQ2FydGVzaWFuIHx8IGhhc0dMMkQpICYmICFhbGxBeGVzRml4ZWQpIHtcbiAgICAgICAgem9vbUdyb3VwID0gWyd6b29tSW4yZCcsICd6b29tT3V0MmQnLCAnYXV0b1NjYWxlMmQnXTtcbiAgICAgICAgaWYocmVzZXRHcm91cFswXSAhPT0gJ3Jlc2V0Vmlld3MnKSByZXNldEdyb3VwID0gWydyZXNldFNjYWxlMmQnXTtcbiAgICB9XG5cbiAgICBpZihoYXNHTDNEKSB7XG4gICAgICAgIGRyYWdNb2RlR3JvdXAgPSBbJ3pvb20zZCcsICdwYW4zZCcsICdvcmJpdFJvdGF0aW9uJywgJ3RhYmxlUm90YXRpb24nXTtcbiAgICB9XG4gICAgZWxzZSBpZigoKGhhc0NhcnRlc2lhbiB8fCBoYXNHTDJEKSAmJiAhYWxsQXhlc0ZpeGVkKSB8fCBoYXNUZXJuYXJ5KSB7XG4gICAgICAgIGRyYWdNb2RlR3JvdXAgPSBbJ3pvb20yZCcsICdwYW4yZCddO1xuICAgIH1cbiAgICBlbHNlIGlmKGhhc01hcGJveCB8fCBoYXNHZW8pIHtcbiAgICAgICAgZHJhZ01vZGVHcm91cCA9IFsncGFuMmQnXTtcbiAgICB9XG4gICAgZWxzZSBpZihoYXNQb2xhcikge1xuICAgICAgICBkcmFnTW9kZUdyb3VwID0gWyd6b29tMmQnXTtcbiAgICB9XG4gICAgaWYoaXNTZWxlY3RhYmxlKGZ1bGxEYXRhKSkge1xuICAgICAgICBkcmFnTW9kZUdyb3VwLnB1c2goJ3NlbGVjdDJkJywgJ2xhc3NvMmQnKTtcbiAgICB9XG5cbiAgICBhZGRHcm91cChkcmFnTW9kZUdyb3VwKTtcbiAgICBhZGRHcm91cCh6b29tR3JvdXAuY29uY2F0KHJlc2V0R3JvdXApKTtcbiAgICBhZGRHcm91cChob3Zlckdyb3VwKTtcblxuICAgIHJldHVybiBhcHBlbmRCdXR0b25zVG9Hcm91cHMoZ3JvdXBzLCBidXR0b25zVG9BZGQpO1xufVxuXG5mdW5jdGlvbiBhcmVBbGxBeGVzRml4ZWQoZnVsbExheW91dCkge1xuICAgIHZhciBheExpc3QgPSBheGlzSWRzLmxpc3Qoe19mdWxsTGF5b3V0OiBmdWxsTGF5b3V0fSwgbnVsbCwgdHJ1ZSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFheExpc3RbaV0uZml4ZWRyYW5nZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8vIGxvb2sgZm9yIHRyYWNlcyB0aGF0IHN1cHBvcnQgc2VsZWN0aW9uXG4vLyB0byBiZSB1cGRhdGVkIGFzIHdlIGFkZCBtb3JlIHNlbGVjdFBvaW50cyBoYW5kbGVyc1xuZnVuY3Rpb24gaXNTZWxlY3RhYmxlKGZ1bGxEYXRhKSB7XG4gICAgdmFyIHNlbGVjdGFibGUgPSBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihzZWxlY3RhYmxlKSBicmVhaztcblxuICAgICAgICB2YXIgdHJhY2UgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICBpZighdHJhY2UuX21vZHVsZSB8fCAhdHJhY2UuX21vZHVsZS5zZWxlY3RQb2ludHMpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdzY2F0dGVyLWxpa2UnKSkge1xuICAgICAgICAgICAgaWYoc2NhdHRlclN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpIHx8IHNjYXR0ZXJTdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGFibGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JveC12aW9saW4nKSkge1xuICAgICAgICAgICAgaWYodHJhY2UuYm94cG9pbnRzID09PSAnYWxsJyB8fCB0cmFjZS5wb2ludHMgPT09ICdhbGwnKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gYXNzdW1lIHRoYXQgaW4gZ2VuZXJhbCBpZiB0aGUgdHJhY2UgbW9kdWxlIGhhcyBzZWxlY3RQb2ludHMsXG4gICAgICAgIC8vIHRoZW4gaXQncyBzZWxlY3RhYmxlLiBTY2F0dGVyIGlzIGFuIGV4Y2VwdGlvbiB0byB0aGlzIGJlY2F1c2UgaXQgbXVzdFxuICAgICAgICAvLyBoYXZlIG1hcmtlcnMgb3IgdGV4dCwgbm90IGp1c3QgYmUgYSBzY2F0dGVyIHR5cGUuXG4gICAgICAgIGVsc2Ugc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGFibGU7XG59XG5cbmZ1bmN0aW9uIGFwcGVuZEJ1dHRvbnNUb0dyb3Vwcyhncm91cHMsIGJ1dHRvbnMpIHtcbiAgICBpZihidXR0b25zLmxlbmd0aCkge1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KGJ1dHRvbnNbMF0pKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYnV0dG9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGdyb3Vwcy5wdXNoKGJ1dHRvbnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgZ3JvdXBzLnB1c2goYnV0dG9ucyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdyb3Vwcztcbn1cblxuLy8gZmlsbCBpbiBjdXN0b20gYnV0dG9ucyByZWZlcnJpbmcgdG8gZGVmYXVsdCBtb2RlIGJhciBidXR0b25zXG5mdW5jdGlvbiBmaWxsQ3VzdG9tQnV0dG9uKGN1c3RvbUJ1dHRvbnMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY3VzdG9tQnV0dG9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYnV0dG9uR3JvdXAgPSBjdXN0b21CdXR0b25zW2ldO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBidXR0b25Hcm91cC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGJ1dHRvbiA9IGJ1dHRvbkdyb3VwW2pdO1xuXG4gICAgICAgICAgICBpZih0eXBlb2YgYnV0dG9uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmKG1vZGVCYXJCdXR0b25zW2J1dHRvbl0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjdXN0b21CdXR0b25zW2ldW2pdID0gbW9kZUJhckJ1dHRvbnNbYnV0dG9uXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAnKm1vZGVCYXJCdXR0b25zKiBjb25maWd1cmF0aW9uIG9wdGlvbnMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgYnV0dG9uIG5hbWUnXG4gICAgICAgICAgICAgICAgICAgIF0uam9pbignICcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY3VzdG9tQnV0dG9ucztcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBJY29ucyA9IHJlcXVpcmUoJy4uLy4uLy4uL2J1aWxkL3Bsb3RpY29uJyk7XG52YXIgUGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xuXG4vKipcbiAqIFVJIGNvbnRyb2xsZXIgZm9yIGludGVyYWN0aXZlIHBsb3RzXG4gKiBAQ2xhc3NcbiAqIEBQYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiBAUGFyYW0ge29iamVjdH0gb3B0cy5idXR0b25zICAgIG5lc3RlZCBhcnJheXMgb2YgZ3JvdXBlZCBidXR0b25zIGNvbmZpZyBvYmplY3RzXG4gKiBAUGFyYW0ge29iamVjdH0gb3B0cy5jb250YWluZXIgIGNvbnRhaW5lciBkaXYgdG8gYXBwZW5kIG1vZGVCYXJcbiAqIEBQYXJhbSB7b2JqZWN0fSBvcHRzLmdyYXBoSW5mbyAgcHJpbWFyeSBwbG90IG9iamVjdCBjb250YWluaW5nIGRhdGEgYW5kIGxheW91dFxuICovXG5mdW5jdGlvbiBNb2RlQmFyKG9wdHMpIHtcbiAgICB0aGlzLmNvbnRhaW5lciA9IG9wdHMuY29udGFpbmVyO1xuICAgIHRoaXMuZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgdGhpcy51cGRhdGUob3B0cy5ncmFwaEluZm8sIG9wdHMuYnV0dG9ucyk7XG5cbiAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmVsZW1lbnQpO1xufVxuXG52YXIgcHJvdG8gPSBNb2RlQmFyLnByb3RvdHlwZTtcblxuLyoqXG4gKiBVcGRhdGUgbW9kZUJhciAoYnV0dG9ucyBhbmQgbG9nbylcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZ3JhcGhJbmZvICBwcmltYXJ5IHBsb3Qgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YSBhbmQgbGF5b3V0XG4gKiBAcGFyYW0ge2FycmF5IG9mIGFycmF5c30gYnV0dG9ucyBuZXN0ZWQgYXJyYXlzIG9mIGdyb3VwZWQgYnV0dG9ucyB0byBpbml0aWFsaXplXG4gKlxuICovXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihncmFwaEluZm8sIGJ1dHRvbnMpIHtcbiAgICB0aGlzLmdyYXBoSW5mbyA9IGdyYXBoSW5mbztcblxuICAgIHZhciBjb250ZXh0ID0gdGhpcy5ncmFwaEluZm8uX2NvbnRleHQsXG4gICAgICAgIGZ1bGxMYXlvdXQgPSB0aGlzLmdyYXBoSW5mby5fZnVsbExheW91dCxcbiAgICAgICAgbW9kZUJhcklkID0gJ21vZGViYXItJyArIGZ1bGxMYXlvdXQuX3VpZDtcblxuICAgIHRoaXMuZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2lkJywgbW9kZUJhcklkKTtcbiAgICB0aGlzLl91aWQgPSBtb2RlQmFySWQ7XG5cbiAgICBpZihjb250ZXh0LmRpc3BsYXlNb2RlQmFyID09PSAnaG92ZXInKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5jbGFzc05hbWUgPSAnbW9kZWJhciBtb2RlYmFyLS1ob3Zlcic7XG4gICAgfVxuICAgIGVsc2UgdGhpcy5lbGVtZW50LmNsYXNzTmFtZSA9ICdtb2RlYmFyJztcblxuICAgIGlmKGZ1bGxMYXlvdXQubW9kZWJhci5vcmllbnRhdGlvbiA9PT0gJ3YnKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5jbGFzc05hbWUgKz0gJyB2ZXJ0aWNhbCc7XG4gICAgICAgIGJ1dHRvbnMgPSBidXR0b25zLnJldmVyc2UoKTtcbiAgICB9XG5cbiAgICBMaWIuZGVsZXRlUmVsYXRlZFN0eWxlUnVsZShtb2RlQmFySWQpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgJyMnICsgbW9kZUJhcklkLCAnYmFja2dyb3VuZC1jb2xvcjogJyArIGZ1bGxMYXlvdXQubW9kZWJhci5iZ2NvbG9yKTtcbiAgICBMaWIuYWRkUmVsYXRlZFN0eWxlUnVsZShtb2RlQmFySWQsICcjJyArIG1vZGVCYXJJZCArICcgLm1vZGViYXItYnRuIC5pY29uIHBhdGgnLCAnZmlsbDogJyArIGZ1bGxMYXlvdXQubW9kZWJhci5jb2xvcik7XG4gICAgTGliLmFkZFJlbGF0ZWRTdHlsZVJ1bGUobW9kZUJhcklkLCAnIycgKyBtb2RlQmFySWQgKyAnIC5tb2RlYmFyLWJ0bjpob3ZlciAuaWNvbiBwYXRoJywgJ2ZpbGw6ICcgKyBmdWxsTGF5b3V0Lm1vZGViYXIuYWN0aXZlY29sb3IpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgJyMnICsgbW9kZUJhcklkICsgJyAubW9kZWJhci1idG4uYWN0aXZlIC5pY29uIHBhdGgnLCAnZmlsbDogJyArIGZ1bGxMYXlvdXQubW9kZWJhci5hY3RpdmVjb2xvcik7XG5cbiAgICAvLyBpZiBidXR0b25zIG9yIGxvZ28gaGF2ZSBjaGFuZ2VkLCByZWRyYXcgbW9kZWJhciBpbnRlcmlvclxuICAgIHZhciBuZWVkc05ld0J1dHRvbnMgPSAhdGhpcy5oYXNCdXR0b25zKGJ1dHRvbnMpO1xuICAgIHZhciBuZWVkc05ld0xvZ28gPSAodGhpcy5oYXNMb2dvICE9PSBjb250ZXh0LmRpc3BsYXlsb2dvKTtcbiAgICB2YXIgbmVlZHNOZXdMb2NhbGUgPSAodGhpcy5sb2NhbGUgIT09IGNvbnRleHQubG9jYWxlKTtcblxuICAgIHRoaXMubG9jYWxlID0gY29udGV4dC5sb2NhbGU7XG5cbiAgICBpZihuZWVkc05ld0J1dHRvbnMgfHwgbmVlZHNOZXdMb2dvIHx8IG5lZWRzTmV3TG9jYWxlKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsQnV0dG9ucygpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlQnV0dG9ucyhidXR0b25zKTtcblxuICAgICAgICBpZihjb250ZXh0LmRpc3BsYXlsb2dvKSB7XG4gICAgICAgICAgICBpZihmdWxsTGF5b3V0Lm1vZGViYXIub3JpZW50YXRpb24gPT09ICd2Jykge1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudC5wcmVwZW5kKHRoaXMuZ2V0TG9nbygpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuZ2V0TG9nbygpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5oYXNMb2dvID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudXBkYXRlQWN0aXZlQnV0dG9uKCk7XG59O1xuXG5wcm90by51cGRhdGVCdXR0b25zID0gZnVuY3Rpb24oYnV0dG9ucykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB0aGlzLmJ1dHRvbnMgPSBidXR0b25zO1xuICAgIHRoaXMuYnV0dG9uRWxlbWVudHMgPSBbXTtcbiAgICB0aGlzLmJ1dHRvbnNOYW1lcyA9IFtdO1xuXG4gICAgdGhpcy5idXR0b25zLmZvckVhY2goZnVuY3Rpb24oYnV0dG9uR3JvdXApIHtcbiAgICAgICAgdmFyIGdyb3VwID0gX3RoaXMuY3JlYXRlR3JvdXAoKTtcblxuICAgICAgICBidXR0b25Hcm91cC5mb3JFYWNoKGZ1bmN0aW9uKGJ1dHRvbkNvbmZpZykge1xuICAgICAgICAgICAgdmFyIGJ1dHRvbk5hbWUgPSBidXR0b25Db25maWcubmFtZTtcbiAgICAgICAgICAgIGlmKCFidXR0b25OYW1lKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdXN0IHByb3ZpZGUgYnV0dG9uIFxcJ25hbWVcXCcgaW4gYnV0dG9uIGNvbmZpZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoX3RoaXMuYnV0dG9uc05hbWVzLmluZGV4T2YoYnV0dG9uTmFtZSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdidXR0b24gbmFtZSBcXCcnICsgYnV0dG9uTmFtZSArICdcXCcgaXMgdGFrZW4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmJ1dHRvbnNOYW1lcy5wdXNoKGJ1dHRvbk5hbWUpO1xuXG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gX3RoaXMuY3JlYXRlQnV0dG9uKGJ1dHRvbkNvbmZpZyk7XG4gICAgICAgICAgICBfdGhpcy5idXR0b25FbGVtZW50cy5wdXNoKGJ1dHRvbik7XG4gICAgICAgICAgICBncm91cC5hcHBlbmRDaGlsZChidXR0b24pO1xuICAgICAgICB9KTtcblxuICAgICAgICBfdGhpcy5lbGVtZW50LmFwcGVuZENoaWxkKGdyb3VwKTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogRW1wdHkgZGl2IGZvciBjb250YWluaW5nIGEgZ3JvdXAgb2YgYnV0dG9uc1xuICogQFJldHVybiB7SFRNTGVsZW1lbnR9XG4gKi9cbnByb3RvLmNyZWF0ZUdyb3VwID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdyb3VwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZ3JvdXAuY2xhc3NOYW1lID0gJ21vZGViYXItZ3JvdXAnO1xuXG4gICAgcmV0dXJuIGdyb3VwO1xufTtcblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgYnV0dG9uIGRpdiBhbmQgc2V0IGNvbnN0YW50IGFuZCBjb25maWd1cmFibGUgYXR0cmlidXRlc1xuICogQFBhcmFtIHtvYmplY3R9IGNvbmZpZyAoc2VlIC4vYnV0dG9ucy5qcyBmb3IgbW9yZSBpbmZvKVxuICogQFJldHVybiB7SFRNTGVsZW1lbnR9XG4gKi9cbnByb3RvLmNyZWF0ZUJ1dHRvbiA9IGZ1bmN0aW9uKGNvbmZpZykge1xuICAgIHZhciBfdGhpcyA9IHRoaXMsXG4gICAgICAgIGJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblxuICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ3JlbCcsICd0b29sdGlwJyk7XG4gICAgYnV0dG9uLmNsYXNzTmFtZSA9ICdtb2RlYmFyLWJ0bic7XG5cbiAgICB2YXIgdGl0bGUgPSBjb25maWcudGl0bGU7XG4gICAgaWYodGl0bGUgPT09IHVuZGVmaW5lZCkgdGl0bGUgPSBjb25maWcubmFtZTtcbiAgICAvLyBmb3IgbG9jYWxpemF0aW9uOiBhbGxvdyB0aXRsZSB0byBiZSBhIGNhbGxhYmxlIHRoYXQgdGFrZXMgZ2QgYXMgYXJnXG4gICAgZWxzZSBpZih0eXBlb2YgdGl0bGUgPT09ICdmdW5jdGlvbicpIHRpdGxlID0gdGl0bGUodGhpcy5ncmFwaEluZm8pO1xuXG4gICAgaWYodGl0bGUgfHwgdGl0bGUgPT09IDApIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtdGl0bGUnLCB0aXRsZSk7XG5cbiAgICBpZihjb25maWcuYXR0ciAhPT0gdW5kZWZpbmVkKSBidXR0b24uc2V0QXR0cmlidXRlKCdkYXRhLWF0dHInLCBjb25maWcuYXR0cik7XG5cbiAgICB2YXIgdmFsID0gY29uZmlnLnZhbDtcbiAgICBpZih2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZih0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nKSB2YWwgPSB2YWwodGhpcy5ncmFwaEluZm8pO1xuICAgICAgICBidXR0b24uc2V0QXR0cmlidXRlKCdkYXRhLXZhbCcsIHZhbCk7XG4gICAgfVxuXG4gICAgdmFyIGNsaWNrID0gY29uZmlnLmNsaWNrO1xuICAgIGlmKHR5cGVvZiBjbGljayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ211c3QgcHJvdmlkZSBidXR0b24gXFwnY2xpY2tcXCcgZnVuY3Rpb24gaW4gYnV0dG9uIGNvbmZpZycpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgICAgIGNvbmZpZy5jbGljayhfdGhpcy5ncmFwaEluZm8sIGV2KTtcblxuICAgICAgICAgICAgLy8gb25seSBuZWVkZWQgZm9yICdob3ZlckNsb3Nlc3RHZW8nIHdoaWNoIGRvZXMgbm90IGNhbGwgcmVsYXlvdXRcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUFjdGl2ZUJ1dHRvbihldi5jdXJyZW50VGFyZ2V0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS10b2dnbGUnLCBjb25maWcudG9nZ2xlIHx8IGZhbHNlKTtcbiAgICBpZihjb25maWcudG9nZ2xlKSBkMy5zZWxlY3QoYnV0dG9uKS5jbGFzc2VkKCdhY3RpdmUnLCB0cnVlKTtcblxuICAgIHZhciBpY29uID0gY29uZmlnLmljb247XG4gICAgaWYodHlwZW9mIGljb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgYnV0dG9uLmFwcGVuZENoaWxkKGljb24oKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGhpcy5jcmVhdGVJY29uKGljb24gfHwgSWNvbnMucXVlc3Rpb24pKTtcbiAgICB9XG4gICAgYnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS1ncmF2aXR5JywgY29uZmlnLmdyYXZpdHkgfHwgJ24nKTtcblxuICAgIHJldHVybiBidXR0b247XG59O1xuXG4vKipcbiAqIEFkZCBhbiBpY29uIHRvIGEgYnV0dG9uXG4gKiBAUGFyYW0ge29iamVjdH0gdGhpc0ljb25cbiAqIEBQYXJhbSB7bnVtYmVyfSB0aGlzSWNvbi53aWR0aFxuICogQFBhcmFtIHtzdHJpbmd9IHRoaXNJY29uLnBhdGhcbiAqIEBQYXJhbSB7c3RyaW5nfSB0aGlzSWNvbi5jb2xvclxuICogQFJldHVybiB7SFRNTGVsZW1lbnR9XG4gKi9cbnByb3RvLmNyZWF0ZUljb24gPSBmdW5jdGlvbih0aGlzSWNvbikge1xuICAgIHZhciBpY29uSGVpZ2h0ID0gaXNOdW1lcmljKHRoaXNJY29uLmhlaWdodCkgP1xuICAgICAgICAgICAgTnVtYmVyKHRoaXNJY29uLmhlaWdodCkgOlxuICAgICAgICAgICAgdGhpc0ljb24uYXNjZW50IC0gdGhpc0ljb24uZGVzY2VudCxcbiAgICAgICAgc3ZnTlMgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLFxuICAgICAgICBpY29uO1xuXG4gICAgaWYodGhpc0ljb24ucGF0aCkge1xuICAgICAgICBpY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHN2Z05TLCAnc3ZnJyk7XG4gICAgICAgIGljb24uc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgWzAsIDAsIHRoaXNJY29uLndpZHRoLCBpY29uSGVpZ2h0XS5qb2luKCcgJykpO1xuICAgICAgICBpY29uLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnaWNvbicpO1xuXG4gICAgICAgIHZhciBwYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHN2Z05TLCAncGF0aCcpO1xuICAgICAgICBwYXRoLnNldEF0dHJpYnV0ZSgnZCcsIHRoaXNJY29uLnBhdGgpO1xuXG4gICAgICAgIGlmKHRoaXNJY29uLnRyYW5zZm9ybSkge1xuICAgICAgICAgICAgcGF0aC5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsIHRoaXNJY29uLnRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih0aGlzSWNvbi5hc2NlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gTGVnYWN5IGljb24gdHJhbnNmb3JtIGNhbGN1bGF0aW9uXG4gICAgICAgICAgICBwYXRoLnNldEF0dHJpYnV0ZSgndHJhbnNmb3JtJywgJ21hdHJpeCgxIDAgMCAtMSAwICcgKyB0aGlzSWNvbi5hc2NlbnQgKyAnKScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWNvbi5hcHBlbmRDaGlsZChwYXRoKTtcbiAgICB9XG5cbiAgICBpZih0aGlzSWNvbi5zdmcpIHtcbiAgICAgICAgdmFyIHN2Z0RvYyA9IFBhcnNlci5wYXJzZUZyb21TdHJpbmcodGhpc0ljb24uc3ZnLCAnYXBwbGljYXRpb24veG1sJyk7XG4gICAgICAgIGljb24gPSBzdmdEb2MuY2hpbGROb2Rlc1swXTtcbiAgICB9XG5cbiAgICBpY29uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzFlbScpO1xuICAgIGljb24uc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxZW0nKTtcblxuICAgIHJldHVybiBpY29uO1xufTtcblxuLyoqXG4gKiBVcGRhdGVzIGFjdGl2ZSBidXR0b24gd2l0aCBhdHRyaWJ1dGUgc3BlY2lmaWVkIGluIGxheW91dFxuICogQFBhcmFtIHtvYmplY3R9IGdyYXBoSW5mbyBwbG90IG9iamVjdCBjb250YWluaW5nIGRhdGEgYW5kIGxheW91dFxuICogQFJldHVybiB7SFRNTGVsZW1lbnR9XG4gKi9cbnByb3RvLnVwZGF0ZUFjdGl2ZUJ1dHRvbiA9IGZ1bmN0aW9uKGJ1dHRvbkNsaWNrZWQpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IHRoaXMuZ3JhcGhJbmZvLl9mdWxsTGF5b3V0LFxuICAgICAgICBkYXRhQXR0ckNsaWNrZWQgPSAoYnV0dG9uQ2xpY2tlZCAhPT0gdW5kZWZpbmVkKSA/XG4gICAgICAgICAgICBidXR0b25DbGlja2VkLmdldEF0dHJpYnV0ZSgnZGF0YS1hdHRyJykgOlxuICAgICAgICAgICAgbnVsbDtcblxuICAgIHRoaXMuYnV0dG9uRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihidXR0b24pIHtcbiAgICAgICAgdmFyIHRoaXN2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWUsXG4gICAgICAgICAgICBkYXRhQXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpLFxuICAgICAgICAgICAgaXNUb2dnbGVCdXR0b24gPSAoYnV0dG9uLmdldEF0dHJpYnV0ZSgnZGF0YS10b2dnbGUnKSA9PT0gJ3RydWUnKSxcbiAgICAgICAgICAgIGJ1dHRvbjMgPSBkMy5zZWxlY3QoYnV0dG9uKTtcblxuICAgICAgICAvLyBVc2UgJ2RhdGEtdG9nZ2xlJyBhbmQgJ2J1dHRvbkNsaWNrZWQnIHRvIHRvZ2dsZSBidXR0b25zXG4gICAgICAgIC8vIHRoYXQgaGF2ZSBubyBvbmUtdG8tb25lIGVxdWl2YWxlbnQgaW4gZnVsbExheW91dFxuICAgICAgICBpZihpc1RvZ2dsZUJ1dHRvbikge1xuICAgICAgICAgICAgaWYoZGF0YUF0dHIgPT09IGRhdGFBdHRyQ2xpY2tlZCkge1xuICAgICAgICAgICAgICAgIGJ1dHRvbjMuY2xhc3NlZCgnYWN0aXZlJywgIWJ1dHRvbjMuY2xhc3NlZCgnYWN0aXZlJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHZhbCA9IChkYXRhQXR0ciA9PT0gbnVsbCkgP1xuICAgICAgICAgICAgICAgIGRhdGFBdHRyIDpcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgZGF0YUF0dHIpLmdldCgpO1xuXG4gICAgICAgICAgICBidXR0b24zLmNsYXNzZWQoJ2FjdGl2ZScsIHZhbCA9PT0gdGhpc3ZhbCk7XG4gICAgICAgIH1cblxuICAgIH0pO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiBtb2RlQmFyIGlzIGNvbmZpZ3VyZWQgYXMgYnV0dG9uIGNvbmZpZ3VyYXRpb24gYXJndW1lbnRcbiAqXG4gKiBAUGFyYW0ge29iamVjdH0gYnV0dG9ucyAyZCBhcnJheSBvZiBncm91cGVkIGJ1dHRvbiBjb25maWcgb2JqZWN0c1xuICogQFJldHVybiB7Ym9vbGVhbn1cbiAqL1xucHJvdG8uaGFzQnV0dG9ucyA9IGZ1bmN0aW9uKGJ1dHRvbnMpIHtcbiAgICB2YXIgY3VycmVudEJ1dHRvbnMgPSB0aGlzLmJ1dHRvbnM7XG5cbiAgICBpZighY3VycmVudEJ1dHRvbnMpIHJldHVybiBmYWxzZTtcblxuICAgIGlmKGJ1dHRvbnMubGVuZ3RoICE9PSBjdXJyZW50QnV0dG9ucy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBidXR0b25zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmKGJ1dHRvbnNbaV0ubGVuZ3RoICE9PSBjdXJyZW50QnV0dG9uc1tpXS5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGJ1dHRvbnNbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGJ1dHRvbnNbaV1bal0ubmFtZSAhPT0gY3VycmVudEJ1dHRvbnNbaV1bal0ubmFtZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge0hUTUxEaXZFbGVtZW50fSBUaGUgbG9nbyBpbWFnZSB3cmFwcGVkIGluIGEgZ3JvdXBcbiAqL1xucHJvdG8uZ2V0TG9nbyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBncm91cCA9IHRoaXMuY3JlYXRlR3JvdXAoKSxcbiAgICAgICAgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblxuICAgIGEuaHJlZiA9ICdodHRwczovL3Bsb3QubHkvJztcbiAgICBhLnRhcmdldCA9ICdfYmxhbmsnO1xuICAgIGEuc2V0QXR0cmlidXRlKCdkYXRhLXRpdGxlJywgTGliLl8odGhpcy5ncmFwaEluZm8sICdQcm9kdWNlZCB3aXRoIFBsb3RseScpKTtcbiAgICBhLmNsYXNzTmFtZSA9ICdtb2RlYmFyLWJ0biBwbG90bHlqc2ljb24gbW9kZWJhci1idG4tLWxvZ28nO1xuXG4gICAgYS5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUljb24oSWNvbnMubmV3cGxvdGx5bG9nbykpO1xuXG4gICAgZ3JvdXAuYXBwZW5kQ2hpbGQoYSk7XG4gICAgcmV0dXJuIGdyb3VwO1xufTtcblxucHJvdG8ucmVtb3ZlQWxsQnV0dG9ucyA9IGZ1bmN0aW9uKCkge1xuICAgIHdoaWxlKHRoaXMuZWxlbWVudC5maXJzdENoaWxkKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5yZW1vdmVDaGlsZCh0aGlzLmVsZW1lbnQuZmlyc3RDaGlsZCk7XG4gICAgfVxuXG4gICAgdGhpcy5oYXNMb2dvID0gZmFsc2U7XG59O1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gICAgTGliLnJlbW92ZUVsZW1lbnQodGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvcignLm1vZGViYXInKSk7XG4gICAgTGliLmRlbGV0ZVJlbGF0ZWRTdHlsZVJ1bGUodGhpcy5fdWlkKTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZU1vZGVCYXIoZ2QsIGJ1dHRvbnMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgdmFyIG1vZGVCYXIgPSBuZXcgTW9kZUJhcih7XG4gICAgICAgIGdyYXBoSW5mbzogZ2QsXG4gICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXJkaXYubm9kZSgpLFxuICAgICAgICBidXR0b25zOiBidXR0b25zXG4gICAgfSk7XG5cbiAgICBpZihmdWxsTGF5b3V0Ll9wcml2YXRlcGxvdCkge1xuICAgICAgICBkMy5zZWxlY3QobW9kZUJhci5lbGVtZW50KS5hcHBlbmQoJ3NwYW4nKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ2JhZGdlLXByaXZhdGUgZmxvYXQtLWxlZnQnLCB0cnVlKVxuICAgICAgICAgICAgLnRleHQoJ1BSSVZBVEUnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZUJhcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNb2RlQmFyO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uL2NvbG9yL2F0dHJpYnV0ZXMnKTtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcblxudmFyIGJ1dHRvbkF0dHJzID0gdGVtcGxhdGVkQXJyYXkoJ2J1dHRvbicsIHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RlcDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnbW9udGgnLCAneWVhcicsICdkYXknLCAnaG91cicsICdtaW51dGUnLCAnc2Vjb25kJywgJ2FsbCddLFxuICAgICAgICBkZmx0OiAnbW9udGgnLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0ZXBtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydiYWNrd2FyZCcsICd0b2RhdGUnXSxcbiAgICAgICAgZGZsdDogJ2JhY2t3YXJkJyxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb3VudDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsYWJlbDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICBcbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBidXR0b25zOiBidXR0b25BdHRycyxcblxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgIGRmbHQ6ICdsZWZ0JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAtMixcbiAgICAgICAgbWF4OiAzLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgZGZsdDogJ2JvdHRvbScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMubGlnaHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhY3RpdmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ3Bsb3QnXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gJ3knIHBvc2l0aW9uIHBhZCBhYm92ZSBjb3VudGVyIGF4aXMgZG9tYWluXG4gICAgeVBhZDogMC4wMixcblxuICAgIC8vIG1pbmltdW0gYnV0dG9uIHdpZHRoIChyZWdhcmRsZXNzIG9mIHRleHQgc2l6ZSlcbiAgICBtaW5CdXR0b25XaWR0aDogMzAsXG5cbiAgICAvLyBidXR0b25zIHJlY3QgcmFkaWlcbiAgICByeDogMyxcbiAgICByeTogMyxcblxuICAgIC8vIGxpZ2h0IGZyYWN0aW9uIHVzZWQgdG8gY29tcHV0ZSB0aGUgJ2FjdGl2ZWNvbG9yJyBkZWZhdWx0XG4gICAgbGlnaHRBbW91bnQ6IDI1LFxuICAgIGRhcmtBbW91bnQ6IDEwXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xudmFyIFRlbXBsYXRlID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgbGF5b3V0LCBjb3VudGVyQXhlcywgY2FsZW5kYXIpIHtcbiAgICB2YXIgc2VsZWN0b3JJbiA9IGNvbnRhaW5lckluLnJhbmdlc2VsZWN0b3IgfHwge307XG4gICAgdmFyIHNlbGVjdG9yT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGNvbnRhaW5lck91dCwgJ3Jhbmdlc2VsZWN0b3InKTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHNlbGVjdG9ySW4sIHNlbGVjdG9yT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgYnV0dG9ucyA9IGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoc2VsZWN0b3JJbiwgc2VsZWN0b3JPdXQsIHtcbiAgICAgICAgbmFtZTogJ2J1dHRvbnMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGJ1dHRvbkRlZmF1bHRzLFxuICAgICAgICBjYWxlbmRhcjogY2FsZW5kYXJcbiAgICB9KTtcblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJywgYnV0dG9ucy5sZW5ndGggPiAwKTtcbiAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgIHZhciBwb3NEZmx0ID0gZ2V0UG9zRGZsdChjb250YWluZXJPdXQsIGxheW91dCwgY291bnRlckF4ZXMpO1xuICAgICAgICBjb2VyY2UoJ3gnLCBwb3NEZmx0WzBdKTtcbiAgICAgICAgY29lcmNlKCd5JywgcG9zRGZsdFsxXSk7XG4gICAgICAgIExpYi5ub25lT3JBbGwoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgWyd4JywgJ3knXSk7XG5cbiAgICAgICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgICAgIGNvZXJjZSgneWFuY2hvcicpO1xuXG4gICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnLCBsYXlvdXQuZm9udCk7XG5cbiAgICAgICAgdmFyIGJnQ29sb3IgPSBjb2VyY2UoJ2JnY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdhY3RpdmVjb2xvcicsIENvbG9yLmNvbnRyYXN0KGJnQ29sb3IsIGNvbnN0YW50cy5saWdodEFtb3VudCwgY29uc3RhbnRzLmRhcmtBbW91bnQpKTtcbiAgICAgICAgY29lcmNlKCdib3JkZXJjb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gYnV0dG9uRGVmYXVsdHMoYnV0dG9uSW4sIGJ1dHRvbk91dCwgc2VsZWN0b3JPdXQsIG9wdHMpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBvcHRzLmNhbGVuZGFyO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYnV0dG9uSW4sIGJ1dHRvbk91dCwgYXR0cmlidXRlcy5idXR0b25zLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuXG4gICAgaWYodmlzaWJsZSkge1xuICAgICAgICB2YXIgc3RlcCA9IGNvZXJjZSgnc3RlcCcpO1xuICAgICAgICBpZihzdGVwICE9PSAnYWxsJykge1xuICAgICAgICAgICAgaWYoY2FsZW5kYXIgJiYgY2FsZW5kYXIgIT09ICdncmVnb3JpYW4nICYmIChzdGVwID09PSAnbW9udGgnIHx8IHN0ZXAgPT09ICd5ZWFyJykpIHtcbiAgICAgICAgICAgICAgICBidXR0b25PdXQuc3RlcG1vZGUgPSAnYmFja3dhcmQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29lcmNlKCdzdGVwbW9kZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb2VyY2UoJ2NvdW50Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ2xhYmVsJyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRQb3NEZmx0KGNvbnRhaW5lck91dCwgbGF5b3V0LCBjb3VudGVyQXhlcykge1xuICAgIHZhciBhbmNob3JlZExpc3QgPSBjb3VudGVyQXhlcy5maWx0ZXIoZnVuY3Rpb24oYXgpIHtcbiAgICAgICAgcmV0dXJuIGxheW91dFtheF0uYW5jaG9yID09PSBjb250YWluZXJPdXQuX2lkO1xuICAgIH0pO1xuXG4gICAgdmFyIHBvc1kgPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbmNob3JlZExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGRvbWFpbiA9IGxheW91dFthbmNob3JlZExpc3RbaV1dLmRvbWFpbjtcbiAgICAgICAgaWYoZG9tYWluKSBwb3NZID0gTWF0aC5tYXgoZG9tYWluWzFdLCBwb3NZKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW2NvbnRhaW5lck91dC5kb21haW5bMF0sIHBvc1kgKyBjb25zdGFudHMueVBhZF07XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgUGxvdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9wbG90cycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vZHJhd2luZycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGF4aXNJZHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcbnZhciBhbmNob3JVdGlscyA9IHJlcXVpcmUoJy4uL2xlZ2VuZC9hbmNob3JfdXRpbHMnKTtcblxudmFyIGFsaWdubWVudENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcbnZhciBMSU5FX1NQQUNJTkcgPSBhbGlnbm1lbnRDb25zdGFudHMuTElORV9TUEFDSU5HO1xudmFyIEZST01fVEwgPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9UTDtcbnZhciBGUk9NX0JSID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fQlI7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xudmFyIGdldFVwZGF0ZU9iamVjdCA9IHJlcXVpcmUoJy4vZ2V0X3VwZGF0ZV9vYmplY3QnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgdmFyIHNlbGVjdG9ycyA9IGZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJy5yYW5nZXNlbGVjdG9yJylcbiAgICAgICAgLmRhdGEobWFrZVNlbGVjdG9yRGF0YShnZCksIHNlbGVjdG9yS2V5RnVuYyk7XG5cbiAgICBzZWxlY3RvcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgncmFuZ2VzZWxlY3RvcicsIHRydWUpO1xuXG4gICAgc2VsZWN0b3JzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHNlbGVjdG9ycy5zdHlsZSh7XG4gICAgICAgIGN1cnNvcjogJ3BvaW50ZXInLFxuICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnYWxsJ1xuICAgIH0pO1xuXG4gICAgc2VsZWN0b3JzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBkMy5zZWxlY3QodGhpcyksXG4gICAgICAgICAgICBheGlzTGF5b3V0ID0gZCxcbiAgICAgICAgICAgIHNlbGVjdG9yTGF5b3V0ID0gYXhpc0xheW91dC5yYW5nZXNlbGVjdG9yO1xuXG4gICAgICAgIHZhciBidXR0b25zID0gc2VsZWN0b3Iuc2VsZWN0QWxsKCdnLmJ1dHRvbicpXG4gICAgICAgICAgICAuZGF0YShMaWIuZmlsdGVyVmlzaWJsZShzZWxlY3RvckxheW91dC5idXR0b25zKSk7XG5cbiAgICAgICAgYnV0dG9ucy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnYnV0dG9uJywgdHJ1ZSk7XG5cbiAgICAgICAgYnV0dG9ucy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBidXR0b24gPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgdXBkYXRlID0gZ2V0VXBkYXRlT2JqZWN0KGF4aXNMYXlvdXQsIGQpO1xuXG4gICAgICAgICAgICBkLl9pc0FjdGl2ZSA9IGlzQWN0aXZlKGF4aXNMYXlvdXQsIGQsIHVwZGF0ZSk7XG5cbiAgICAgICAgICAgIGJ1dHRvbi5jYWxsKGRyYXdCdXR0b25SZWN0LCBzZWxlY3RvckxheW91dCwgZCk7XG4gICAgICAgICAgICBidXR0b24uY2FsbChkcmF3QnV0dG9uVGV4dCwgc2VsZWN0b3JMYXlvdXQsIGQsIGdkKTtcblxuICAgICAgICAgICAgYnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGlmKGdkLl9kcmFnZ2VkKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCB1cGRhdGUpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGJ1dHRvbi5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZC5faXNIb3ZlcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBidXR0b24uY2FsbChkcmF3QnV0dG9uUmVjdCwgc2VsZWN0b3JMYXlvdXQsIGQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGJ1dHRvbi5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBkLl9pc0hvdmVyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBidXR0b24uY2FsbChkcmF3QnV0dG9uUmVjdCwgc2VsZWN0b3JMYXlvdXQsIGQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlcG9zaXRpb24oZ2QsIGJ1dHRvbnMsIHNlbGVjdG9yTGF5b3V0LCBheGlzTGF5b3V0Ll9uYW1lLCBzZWxlY3Rvcik7XG4gICAgfSk7XG5cbn07XG5cbmZ1bmN0aW9uIG1ha2VTZWxlY3RvckRhdGEoZ2QpIHtcbiAgICB2YXIgYXhlcyA9IGF4aXNJZHMubGlzdChnZCwgJ3gnLCB0cnVlKTtcbiAgICB2YXIgZGF0YSA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4aXMgPSBheGVzW2ldO1xuXG4gICAgICAgIGlmKGF4aXMucmFuZ2VzZWxlY3RvciAmJiBheGlzLnJhbmdlc2VsZWN0b3IudmlzaWJsZSkge1xuICAgICAgICAgICAgZGF0YS5wdXNoKGF4aXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdG9yS2V5RnVuYyhkKSB7XG4gICAgcmV0dXJuIGQuX2lkO1xufVxuXG5mdW5jdGlvbiBpc0FjdGl2ZShheGlzTGF5b3V0LCBvcHRzLCB1cGRhdGUpIHtcbiAgICBpZihvcHRzLnN0ZXAgPT09ICdhbGwnKSB7XG4gICAgICAgIHJldHVybiBheGlzTGF5b3V0LmF1dG9yYW5nZSA9PT0gdHJ1ZTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXModXBkYXRlKTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgYXhpc0xheW91dC5yYW5nZVswXSA9PT0gdXBkYXRlW2tleXNbMF1dICYmXG4gICAgICAgICAgICBheGlzTGF5b3V0LnJhbmdlWzFdID09PSB1cGRhdGVba2V5c1sxXV1cbiAgICAgICAgKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYXdCdXR0b25SZWN0KGJ1dHRvbiwgc2VsZWN0b3JMYXlvdXQsIGQpIHtcbiAgICB2YXIgcmVjdCA9IExpYi5lbnN1cmVTaW5nbGUoYnV0dG9uLCAncmVjdCcsICdzZWxlY3Rvci1yZWN0JywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJyk7XG4gICAgfSk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICAncngnOiBjb25zdGFudHMucngsXG4gICAgICAgICdyeSc6IGNvbnN0YW50cy5yeVxuICAgIH0pO1xuXG4gICAgcmVjdC5jYWxsKENvbG9yLnN0cm9rZSwgc2VsZWN0b3JMYXlvdXQuYm9yZGVyY29sb3IpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGdldEZpbGxDb2xvcihzZWxlY3RvckxheW91dCwgZCkpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgc2VsZWN0b3JMYXlvdXQuYm9yZGVyd2lkdGggKyAncHgnKTtcbn1cblxuZnVuY3Rpb24gZ2V0RmlsbENvbG9yKHNlbGVjdG9yTGF5b3V0LCBkKSB7XG4gICAgcmV0dXJuIChkLl9pc0FjdGl2ZSB8fCBkLl9pc0hvdmVyZWQpID9cbiAgICAgICAgc2VsZWN0b3JMYXlvdXQuYWN0aXZlY29sb3IgOlxuICAgICAgICBzZWxlY3RvckxheW91dC5iZ2NvbG9yO1xufVxuXG5mdW5jdGlvbiBkcmF3QnV0dG9uVGV4dChidXR0b24sIHNlbGVjdG9yTGF5b3V0LCBkLCBnZCkge1xuICAgIGZ1bmN0aW9uIHRleHRMYXlvdXQocykge1xuICAgICAgICBzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zKHMsIGdkKTtcbiAgICB9XG5cbiAgICB2YXIgdGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoYnV0dG9uLCAndGV4dCcsICdzZWxlY3Rvci10ZXh0JywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmNsYXNzZWQoJ3VzZXItc2VsZWN0LW5vbmUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpO1xuICAgIH0pO1xuXG4gICAgdGV4dC5jYWxsKERyYXdpbmcuZm9udCwgc2VsZWN0b3JMYXlvdXQuZm9udClcbiAgICAgICAgLnRleHQoZ2V0TGFiZWwoZCkpXG4gICAgICAgIC5jYWxsKHRleHRMYXlvdXQpO1xufVxuXG5mdW5jdGlvbiBnZXRMYWJlbChvcHRzKSB7XG4gICAgaWYob3B0cy5sYWJlbCkgcmV0dXJuIG9wdHMubGFiZWw7XG5cbiAgICBpZihvcHRzLnN0ZXAgPT09ICdhbGwnKSByZXR1cm4gJ2FsbCc7XG5cbiAgICByZXR1cm4gb3B0cy5jb3VudCArIG9wdHMuc3RlcC5jaGFyQXQoMCk7XG59XG5cbmZ1bmN0aW9uIHJlcG9zaXRpb24oZ2QsIGJ1dHRvbnMsIG9wdHMsIGF4TmFtZSwgc2VsZWN0b3IpIHtcbiAgICB2YXIgd2lkdGggPSAwO1xuICAgIHZhciBoZWlnaHQgPSAwO1xuXG4gICAgdmFyIGJvcmRlcldpZHRoID0gb3B0cy5ib3JkZXJ3aWR0aDtcblxuICAgIGJ1dHRvbnMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRleHQgPSBidXR0b24uc2VsZWN0KCcuc2VsZWN0b3ItdGV4dCcpO1xuXG4gICAgICAgIHZhciB0SGVpZ2h0ID0gb3B0cy5mb250LnNpemUgKiBMSU5FX1NQQUNJTkc7XG4gICAgICAgIHZhciBoRWZmID0gTWF0aC5tYXgodEhlaWdodCAqIHN2Z1RleHRVdGlscy5saW5lQ291bnQodGV4dCksIDE2KSArIDM7XG5cbiAgICAgICAgaGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCBoRWZmKTtcbiAgICB9KTtcblxuICAgIGJ1dHRvbnMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHJlY3QgPSBidXR0b24uc2VsZWN0KCcuc2VsZWN0b3ItcmVjdCcpO1xuICAgICAgICB2YXIgdGV4dCA9IGJ1dHRvbi5zZWxlY3QoJy5zZWxlY3Rvci10ZXh0Jyk7XG5cbiAgICAgICAgdmFyIHRXaWR0aCA9IHRleHQubm9kZSgpICYmIERyYXdpbmcuYkJveCh0ZXh0Lm5vZGUoKSkud2lkdGg7XG4gICAgICAgIHZhciB0SGVpZ2h0ID0gb3B0cy5mb250LnNpemUgKiBMSU5FX1NQQUNJTkc7XG4gICAgICAgIHZhciB0TGluZXMgPSBzdmdUZXh0VXRpbHMubGluZUNvdW50KHRleHQpO1xuXG4gICAgICAgIHZhciB3RWZmID0gTWF0aC5tYXgodFdpZHRoICsgMTAsIGNvbnN0YW50cy5taW5CdXR0b25XaWR0aCk7XG5cbiAgICAgICAgLy8gVE9ETyBhZGQgTWF0aEpheCBzdXBwb3J0XG5cbiAgICAgICAgLy8gVE9ETyBhZGQgYnV0dG9uZ2FwIGF0dHJpYnV0ZVxuXG4gICAgICAgIGJ1dHRvbi5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgK1xuICAgICAgICAgICAgKGJvcmRlcldpZHRoICsgd2lkdGgpICsgJywnICsgYm9yZGVyV2lkdGggK1xuICAgICAgICAnKScpO1xuXG4gICAgICAgIHJlY3QuYXR0cih7XG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIHdpZHRoOiB3RWZmLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCh0ZXh0LCB3RWZmIC8gMixcbiAgICAgICAgICAgIGhlaWdodCAvIDIgLSAoKHRMaW5lcyAtIDEpICogdEhlaWdodCAvIDIpICsgMyk7XG5cbiAgICAgICAgd2lkdGggKz0gd0VmZiArIDU7XG4gICAgfSk7XG5cbiAgICB2YXIgZ3JhcGhTaXplID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGx4ID0gZ3JhcGhTaXplLmwgKyBncmFwaFNpemUudyAqIG9wdHMueDtcbiAgICB2YXIgbHkgPSBncmFwaFNpemUudCArIGdyYXBoU2l6ZS5oICogKDEgLSBvcHRzLnkpO1xuXG4gICAgdmFyIHhhbmNob3IgPSAnbGVmdCc7XG4gICAgaWYoYW5jaG9yVXRpbHMuaXNSaWdodEFuY2hvcihvcHRzKSkge1xuICAgICAgICBseCAtPSB3aWR0aDtcbiAgICAgICAgeGFuY2hvciA9ICdyaWdodCc7XG4gICAgfVxuICAgIGlmKGFuY2hvclV0aWxzLmlzQ2VudGVyQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIGx4IC09IHdpZHRoIC8gMjtcbiAgICAgICAgeGFuY2hvciA9ICdjZW50ZXInO1xuICAgIH1cblxuICAgIHZhciB5YW5jaG9yID0gJ3RvcCc7XG4gICAgaWYoYW5jaG9yVXRpbHMuaXNCb3R0b21BbmNob3Iob3B0cykpIHtcbiAgICAgICAgbHkgLT0gaGVpZ2h0O1xuICAgICAgICB5YW5jaG9yID0gJ2JvdHRvbSc7XG4gICAgfVxuICAgIGlmKGFuY2hvclV0aWxzLmlzTWlkZGxlQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIGx5IC09IGhlaWdodCAvIDI7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICB3aWR0aCA9IE1hdGguY2VpbCh3aWR0aCk7XG4gICAgaGVpZ2h0ID0gTWF0aC5jZWlsKGhlaWdodCk7XG4gICAgbHggPSBNYXRoLnJvdW5kKGx4KTtcbiAgICBseSA9IE1hdGgucm91bmQobHkpO1xuXG4gICAgUGxvdHMuYXV0b01hcmdpbihnZCwgYXhOYW1lICsgJy1yYW5nZS1zZWxlY3RvcicsIHtcbiAgICAgICAgeDogb3B0cy54LFxuICAgICAgICB5OiBvcHRzLnksXG4gICAgICAgIGw6IHdpZHRoICogRlJPTV9UTFt4YW5jaG9yXSxcbiAgICAgICAgcjogd2lkdGggKiBGUk9NX0JSW3hhbmNob3JdLFxuICAgICAgICBiOiBoZWlnaHQgKiBGUk9NX0JSW3lhbmNob3JdLFxuICAgICAgICB0OiBoZWlnaHQgKiBGUk9NX1RMW3lhbmNob3JdXG4gICAgfSk7XG5cbiAgICBzZWxlY3Rvci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBseCArICcsJyArIGx5ICsgJyknKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFVwZGF0ZU9iamVjdChheGlzTGF5b3V0LCBidXR0b25MYXlvdXQpIHtcbiAgICB2YXIgYXhOYW1lID0gYXhpc0xheW91dC5fbmFtZTtcbiAgICB2YXIgdXBkYXRlID0ge307XG5cbiAgICBpZihidXR0b25MYXlvdXQuc3RlcCA9PT0gJ2FsbCcpIHtcbiAgICAgICAgdXBkYXRlW2F4TmFtZSArICcuYXV0b3JhbmdlJ10gPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHhyYW5nZSA9IGdldFhSYW5nZShheGlzTGF5b3V0LCBidXR0b25MYXlvdXQpO1xuXG4gICAgICAgIHVwZGF0ZVtheE5hbWUgKyAnLnJhbmdlWzBdJ10gPSB4cmFuZ2VbMF07XG4gICAgICAgIHVwZGF0ZVtheE5hbWUgKyAnLnJhbmdlWzFdJ10gPSB4cmFuZ2VbMV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHVwZGF0ZTtcbn07XG5cbmZ1bmN0aW9uIGdldFhSYW5nZShheGlzTGF5b3V0LCBidXR0b25MYXlvdXQpIHtcbiAgICB2YXIgY3VycmVudFJhbmdlID0gYXhpc0xheW91dC5yYW5nZTtcbiAgICB2YXIgYmFzZSA9IG5ldyBEYXRlKGF4aXNMYXlvdXQucjJsKGN1cnJlbnRSYW5nZVsxXSkpO1xuXG4gICAgdmFyIHN0ZXAgPSBidXR0b25MYXlvdXQuc3RlcCxcbiAgICAgICAgY291bnQgPSBidXR0b25MYXlvdXQuY291bnQ7XG5cbiAgICB2YXIgcmFuZ2UwO1xuXG4gICAgc3dpdGNoKGJ1dHRvbkxheW91dC5zdGVwbW9kZSkge1xuICAgICAgICBjYXNlICdiYWNrd2FyZCc6XG4gICAgICAgICAgICByYW5nZTAgPSBheGlzTGF5b3V0LmwycigrZDMudGltZVtzdGVwXS51dGMub2Zmc2V0KGJhc2UsIC1jb3VudCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAndG9kYXRlJzpcbiAgICAgICAgICAgIHZhciBiYXNlMiA9IGQzLnRpbWVbc3RlcF0udXRjLm9mZnNldChiYXNlLCAtY291bnQpO1xuXG4gICAgICAgICAgICByYW5nZTAgPSBheGlzTGF5b3V0LmwycigrZDMudGltZVtzdGVwXS51dGMuY2VpbChiYXNlMikpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlMSA9IGN1cnJlbnRSYW5nZVsxXTtcblxuICAgIHJldHVybiBbcmFuZ2UwLCByYW5nZTFdO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAncmFuZ2VzZWxlY3RvcicsXG5cbiAgICBzY2hlbWE6IHtcbiAgICAgICAgc3VicGxvdHM6IHtcbiAgICAgICAgICAgIHhheGlzOiB7cmFuZ2VzZWxlY3RvcjogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyl9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgaGFuZGxlRGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcblxuICAgIGRyYXc6IHJlcXVpcmUoJy4vZHJhdycpXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vY29sb3IvYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cmlidXRlcy5iYWNrZ3JvdW5kLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJpYnV0ZXMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhdXRvcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7J3JhbmdlWzBdJzogdW5kZWZpbmVkLCAncmFuZ2VbMV0nOiB1bmRlZmluZWR9LFxuICAgICAgICBcbiAgICB9LFxuICAgIHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAnY2FsYycsIGltcGxpZWRFZGl0czogeydeYXV0b3JhbmdlJzogZmFsc2V9fSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdjYWxjJywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX19XG4gICAgICAgIF0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czogeydhdXRvcmFuZ2UnOiBmYWxzZX0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGhpY2tuZXNzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLjE1LFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmlzaWJsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBsaXN0QXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpLmxpc3Q7XG52YXIgZ2V0QXV0b1JhbmdlID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F1dG9yYW5nZScpLmdldEF1dG9SYW5nZTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNBdXRvcmFuZ2UoZ2QpIHtcbiAgICB2YXIgYXhlcyA9IGxpc3RBeGVzKGdkLCAneCcsIHRydWUpO1xuXG4gICAgLy8gQ29tcHV0ZSBuZXcgc2xpZGVyIHJhbmdlIHVzaW5nIGF4aXMgYXV0b3JhbmdlIGlmIG5lY2Vzc2FyeS5cbiAgICAvL1xuICAgIC8vIENvcHkgYmFjayByYW5nZSB0byBpbnB1dCByYW5nZSBzbGlkZXIgY29udGFpbmVyIHRvIHNraXBcbiAgICAvLyB0aGlzIHN0ZXAgaW4gc3Vic2VxdWVudCBkcmF3IGNhbGxzLlxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4ID0gYXhlc1tpXTtcbiAgICAgICAgdmFyIG9wdHMgPSBheFtjb25zdGFudHMubmFtZV07XG5cbiAgICAgICAgaWYob3B0cyAmJiBvcHRzLnZpc2libGUgJiYgb3B0cy5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgIG9wdHMuX2lucHV0LmF1dG9yYW5nZSA9IHRydWU7XG4gICAgICAgICAgICBvcHRzLl9pbnB1dC5yYW5nZSA9IG9wdHMucmFuZ2UgPSBnZXRBdXRvUmFuZ2UoZ2QsIGF4KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gYXR0cmlidXRlIGNvbnRhaW5lciBuYW1lXG4gICAgbmFtZTogJ3Jhbmdlc2xpZGVyJyxcblxuICAgIC8vIGNsYXNzIG5hbWVzXG5cbiAgICBjb250YWluZXJDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1jb250YWluZXInLFxuICAgIGJnQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItYmcnLFxuICAgIHJhbmdlUGxvdENsYXNzTmFtZTogJ3Jhbmdlc2xpZGVyLXJhbmdlcGxvdCcsXG5cbiAgICBtYXNrTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItbWFzay1taW4nLFxuICAgIG1hc2tNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1heCcsXG4gICAgc2xpZGVCb3hDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1zbGlkZWJveCcsXG5cbiAgICBncmFiYmVyTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItZ3JhYmJlci1taW4nLFxuICAgIGdyYWJBcmVhTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItZ3JhYmFyZWEtbWluJyxcbiAgICBoYW5kbGVNaW5DbGFzc05hbWU6ICdyYW5nZXNsaWRlci1oYW5kbGUtbWluJyxcblxuICAgIGdyYWJiZXJNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1ncmFiYmVyLW1heCcsXG4gICAgZ3JhYkFyZWFNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1ncmFiYXJlYS1tYXgnLFxuICAgIGhhbmRsZU1heENsYXNzTmFtZTogJ3Jhbmdlc2xpZGVyLWhhbmRsZS1tYXgnLFxuXG4gICAgbWFza01pbk9wcEF4aXNDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1pbi1vcHAtYXhpcycsXG4gICAgbWFza01heE9wcEF4aXNDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1heC1vcHAtYXhpcycsXG5cbiAgICAvLyBzdHlsZSBjb25zdGFudHNcblxuICAgIG1hc2tDb2xvcjogJ3JnYmEoMCwwLDAsMC40KScsXG4gICAgbWFza09wcEF4aXNDb2xvcjogJ3JnYmEoMCwwLDAsMC4yKScsXG5cbiAgICBzbGlkZUJveEZpbGw6ICd0cmFuc3BhcmVudCcsXG4gICAgc2xpZGVCb3hDdXJzb3I6ICdldy1yZXNpemUnLFxuXG4gICAgZ3JhYkFyZWFGaWxsOiAndHJhbnNwYXJlbnQnLFxuICAgIGdyYWJBcmVhQ3Vyc29yOiAnY29sLXJlc2l6ZScsXG4gICAgZ3JhYkFyZWFXaWR0aDogMTAsXG5cbiAgICBoYW5kbGVXaWR0aDogNCxcbiAgICBoYW5kbGVSYWRpdXM6IDEsXG4gICAgaGFuZGxlU3Ryb2tlV2lkdGg6IDEsXG5cbiAgICBleHRyYVBhZDogMTVcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBheGlzSWRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgb3BwQXhpc0F0dHJzID0gcmVxdWlyZSgnLi9vcHBheGlzX2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBheE5hbWUpIHtcbiAgICB2YXIgYXhJbiA9IGxheW91dEluW2F4TmFtZV07XG4gICAgdmFyIGF4T3V0ID0gbGF5b3V0T3V0W2F4TmFtZV07XG5cbiAgICBpZighKGF4SW4ucmFuZ2VzbGlkZXIgfHwgbGF5b3V0T3V0Ll9yZXF1ZXN0UmFuZ2VzbGlkZXJbYXhPdXQuX2lkXSkpIHJldHVybjtcblxuICAgIC8vIG5vdCBzdXBlciBwcm91ZCBvZiB0aGlzIChtYXliZSBzdG9yZSBfIGluIGF4aXMgb2JqZWN0IGluc3RlYWRcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QoYXhJbi5yYW5nZXNsaWRlcikpIHtcbiAgICAgICAgYXhJbi5yYW5nZXNsaWRlciA9IHt9O1xuICAgIH1cblxuICAgIHZhciBjb250YWluZXJJbiA9IGF4SW4ucmFuZ2VzbGlkZXI7XG4gICAgdmFyIGNvbnRhaW5lck91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihheE91dCwgJ3Jhbmdlc2xpZGVyJyk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgcmFuZ2VDb250YWluZXJJbiwgcmFuZ2VDb250YWluZXJPdXQ7XG4gICAgZnVuY3Rpb24gY29lcmNlUmFuZ2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShyYW5nZUNvbnRhaW5lckluLCByYW5nZUNvbnRhaW5lck91dCwgb3BwQXhpc0F0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuICAgIGlmKCF2aXNpYmxlKSByZXR1cm47XG5cbiAgICBjb2VyY2UoJ2JnY29sb3InLCBsYXlvdXRPdXQucGxvdF9iZ2NvbG9yKTtcbiAgICBjb2VyY2UoJ2JvcmRlcmNvbG9yJyk7XG4gICAgY29lcmNlKCdib3JkZXJ3aWR0aCcpO1xuICAgIGNvZXJjZSgndGhpY2tuZXNzJyk7XG5cbiAgICBjb2VyY2UoJ2F1dG9yYW5nZScsICFheE91dC5pc1ZhbGlkUmFuZ2UoY29udGFpbmVySW4ucmFuZ2UpKTtcbiAgICBjb2VyY2UoJ3JhbmdlJyk7XG5cbiAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXRPdXQuX3N1YnBsb3RzO1xuICAgIGlmKHN1YnBsb3RzKSB7XG4gICAgICAgIHZhciB5SWRzID0gc3VicGxvdHMuY2FydGVzaWFuXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdWJwbG90SWQuc3Vic3RyKDAsIHN1YnBsb3RJZC5pbmRleE9mKCd5JykpID09PSBheGlzSWRzLm5hbWUyaWQoYXhOYW1lKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdWJwbG90SWQuc3Vic3RyKHN1YnBsb3RJZC5pbmRleE9mKCd5JyksIHN1YnBsb3RJZC5sZW5ndGgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIHZhciB5TmFtZXMgPSBMaWIuc2ltcGxlTWFwKHlJZHMsIGF4aXNJZHMuaWQybmFtZSk7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB5TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB5TmFtZSA9IHlOYW1lc1tpXTtcblxuICAgICAgICAgICAgcmFuZ2VDb250YWluZXJJbiA9IGNvbnRhaW5lckluW3lOYW1lXSB8fCB7fTtcbiAgICAgICAgICAgIHJhbmdlQ29udGFpbmVyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGNvbnRhaW5lck91dCwgeU5hbWUsICd5YXhpcycpO1xuXG4gICAgICAgICAgICB2YXIgeUF4T3V0ID0gbGF5b3V0T3V0W3lOYW1lXTtcblxuICAgICAgICAgICAgdmFyIHJhbmdlbW9kZURmbHQ7XG4gICAgICAgICAgICBpZihyYW5nZUNvbnRhaW5lckluLnJhbmdlICYmIHlBeE91dC5pc1ZhbGlkUmFuZ2UocmFuZ2VDb250YWluZXJJbi5yYW5nZSkpIHtcbiAgICAgICAgICAgICAgICByYW5nZW1vZGVEZmx0ID0gJ2ZpeGVkJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHJhbmdlTW9kZSA9IGNvZXJjZVJhbmdlKCdyYW5nZW1vZGUnLCByYW5nZW1vZGVEZmx0KTtcbiAgICAgICAgICAgIGlmKHJhbmdlTW9kZSAhPT0gJ21hdGNoJykge1xuICAgICAgICAgICAgICAgIGNvZXJjZVJhbmdlKCdyYW5nZScsIHlBeE91dC5yYW5nZS5zbGljZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRvIG1hcCBiYWNrIHJhbmdlIHNsaWRlciAoYXV0bykgcmFuZ2VcbiAgICBjb250YWluZXJPdXQuX2lucHV0ID0gY29udGFpbmVySW47XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvcGxvdHMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xudmFyIFRpdGxlcyA9IHJlcXVpcmUoJy4uL3RpdGxlcycpO1xuXG52YXIgQ2FydGVzaWFuID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBkcmFnRWxlbWVudCA9IHJlcXVpcmUoJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgc2V0Q3Vyc29yID0gcmVxdWlyZSgnLi4vLi4vbGliL3NldGN1cnNvcicpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQsXG4gICAgICAgIHJhbmdlU2xpZGVyRGF0YSA9IG1ha2VSYW5nZVNsaWRlckRhdGEoZnVsbExheW91dCk7XG5cbiAgICAvKlxuICAgICAqIDxnIGNvbnRhaW5lciAvPlxuICAgICAqICA8cmVjdCBiZyAvPlxuICAgICAqICA8IC4uLi4gcmFuZ2UgcGxvdCAvPlxuICAgICAqICA8cmVjdCBtYXNrLW1pbiAvPlxuICAgICAqICA8cmVjdCBtYXNrLW1heCAvPlxuICAgICAqICA8cmVjdCBzbGlkZWJveCAvPlxuICAgICAqICA8ZyBncmFiYmVyLW1pbiAvPlxuICAgICAqICAgICAgPHJlY3QgaGFuZGxlLW1pbiAvPlxuICAgICAqICAgICAgPHJlY3QgZ3JhYmFyZS1taW4gLz5cbiAgICAgKiAgPGcgZ3JhYmJlci1tYXggLz5cbiAgICAgKiAgICAgIDxyZWN0IGhhbmRsZS1tYXggLz5cbiAgICAgKiAgICAgIDxyZWN0IGdyYWJhcmUtbWF4IC8+XG4gICAgICpcbiAgICAgKiAgLi4uXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBrZXlGdW5jdGlvbihheGlzT3B0cykge1xuICAgICAgICByZXR1cm4gYXhpc09wdHMuX25hbWU7XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlU2xpZGVycyA9IGZ1bGxMYXlvdXQuX2luZm9sYXllclxuICAgICAgICAuc2VsZWN0QWxsKCdnLicgKyBjb25zdGFudHMuY29udGFpbmVyQ2xhc3NOYW1lKVxuICAgICAgICAuZGF0YShyYW5nZVNsaWRlckRhdGEsIGtleUZ1bmN0aW9uKTtcblxuICAgIHJhbmdlU2xpZGVycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5jb250YWluZXJDbGFzc05hbWUsIHRydWUpXG4gICAgICAgIC5hdHRyKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKTtcblxuICAgIC8vIHJlbW92ZSBleGl0aW5nIHNsaWRlcnMgYW5kIHRoZWlyIGNvcnJlc3BvbmRpbmcgY2xpcCBwYXRoc1xuICAgIHJhbmdlU2xpZGVycy5leGl0KCkuZWFjaChmdW5jdGlvbihheGlzT3B0cykge1xuICAgICAgICB2YXIgb3B0cyA9IGF4aXNPcHRzW2NvbnN0YW50cy5uYW1lXTtcbiAgICAgICAgZnVsbExheW91dC5fdG9wZGVmcy5zZWxlY3QoJyMnICsgb3B0cy5fY2xpcElkKS5yZW1vdmUoKTtcbiAgICB9KS5yZW1vdmUoKTtcblxuICAgIC8vIHJldHVybiBlYXJseSBpZiBubyByYW5nZSBzbGlkZXIgaXMgdmlzaWJsZVxuICAgIGlmKHJhbmdlU2xpZGVyRGF0YS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIC8vIGZvciBhbGwgcHJlc2VudCByYW5nZSBzbGlkZXJzXG4gICAgcmFuZ2VTbGlkZXJzLmVhY2goZnVuY3Rpb24oYXhpc09wdHMpIHtcbiAgICAgICAgdmFyIHJhbmdlU2xpZGVyID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgICAgICAgb3B0cyA9IGF4aXNPcHRzW2NvbnN0YW50cy5uYW1lXSxcbiAgICAgICAgICAgIG9wcEF4aXNPcHRzID0gZnVsbExheW91dFtBeGVzLmlkMm5hbWUoYXhpc09wdHMuYW5jaG9yKV0sXG4gICAgICAgICAgICBvcHBBeGlzUmFuZ2VPcHRzID0gb3B0c1tBeGVzLmlkMm5hbWUoYXhpc09wdHMuYW5jaG9yKV07XG5cbiAgICAgICAgLy8gdXBkYXRlIHJhbmdlXG4gICAgICAgIC8vIEV4cGFuZCBzbGlkZXIgcmFuZ2UgdG8gdGhlIGF4aXMgcmFuZ2VcbiAgICAgICAgLy8gVE9ETzogd2hhdCBpZiB0aGUgcmFuZ2VzIGFyZSByZXZlcnNlZD9cbiAgICAgICAgaWYob3B0cy5yYW5nZSkge1xuICAgICAgICAgICAgdmFyIG91dFJhbmdlID0gb3B0cy5yYW5nZTtcbiAgICAgICAgICAgIHZhciBheFJhbmdlID0gYXhpc09wdHMucmFuZ2U7XG5cbiAgICAgICAgICAgIG91dFJhbmdlWzBdID0gYXhpc09wdHMubDJyKE1hdGgubWluKGF4aXNPcHRzLnIybChvdXRSYW5nZVswXSksIGF4aXNPcHRzLnIybChheFJhbmdlWzBdKSkpO1xuICAgICAgICAgICAgb3V0UmFuZ2VbMV0gPSBheGlzT3B0cy5sMnIoTWF0aC5tYXgoYXhpc09wdHMucjJsKG91dFJhbmdlWzFdKSwgYXhpc09wdHMucjJsKGF4UmFuZ2VbMV0pKSk7XG4gICAgICAgICAgICBvcHRzLl9pbnB1dC5yYW5nZSA9IG91dFJhbmdlLnNsaWNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBheGlzT3B0cy5jbGVhblJhbmdlKCdyYW5nZXNsaWRlci5yYW5nZScpO1xuXG5cbiAgICAgICAgLy8gdXBkYXRlIHJhbmdlIHNsaWRlciBkaW1lbnNpb25zXG5cbiAgICAgICAgdmFyIG1hcmdpbiA9IGZ1bGxMYXlvdXQubWFyZ2luO1xuICAgICAgICB2YXIgZ3JhcGhTaXplID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICAgICAgdmFyIGRvbWFpbiA9IGF4aXNPcHRzLmRvbWFpbjtcbiAgICAgICAgdmFyIHRpY2tIZWlnaHQgPSAoYXhpc09wdHMuX2JvdW5kaW5nQm94IHx8IHt9KS5oZWlnaHQgfHwgMDtcblxuICAgICAgICB2YXIgb3BwQm90dG9tID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBzdWJwbG90RGF0YSA9IEF4ZXMuZ2V0U3VicGxvdHMoZ2QsIGF4aXNPcHRzKTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3REYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb3BwQXhpcyA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBzdWJwbG90RGF0YVtpXS5zdWJzdHIoc3VicGxvdERhdGFbaV0uaW5kZXhPZigneScpKSk7XG4gICAgICAgICAgICBvcHBCb3R0b20gPSBNYXRoLm1pbihvcHBCb3R0b20sIG9wcEF4aXMuZG9tYWluWzBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG9wdHMuX2lkID0gY29uc3RhbnRzLm5hbWUgKyBheGlzT3B0cy5faWQ7XG4gICAgICAgIG9wdHMuX2NsaXBJZCA9IG9wdHMuX2lkICsgJy0nICsgZnVsbExheW91dC5fdWlkO1xuXG4gICAgICAgIG9wdHMuX3dpZHRoID0gZ3JhcGhTaXplLncgKiAoZG9tYWluWzFdIC0gZG9tYWluWzBdKTtcbiAgICAgICAgb3B0cy5faGVpZ2h0ID0gKGZ1bGxMYXlvdXQuaGVpZ2h0IC0gbWFyZ2luLmIgLSBtYXJnaW4udCkgKiBvcHRzLnRoaWNrbmVzcztcbiAgICAgICAgb3B0cy5fb2Zmc2V0U2hpZnQgPSBNYXRoLmZsb29yKG9wdHMuYm9yZGVyd2lkdGggLyAyKTtcblxuICAgICAgICB2YXIgeCA9IE1hdGgucm91bmQobWFyZ2luLmwgKyAoZ3JhcGhTaXplLncgKiBkb21haW5bMF0pKTtcblxuICAgICAgICB2YXIgeSA9IE1hdGgucm91bmQoXG4gICAgICAgICAgICBncmFwaFNpemUudCArIGdyYXBoU2l6ZS5oICogKDEgLSBvcHBCb3R0b20pICtcbiAgICAgICAgICAgIHRpY2tIZWlnaHQgK1xuICAgICAgICAgICAgb3B0cy5fb2Zmc2V0U2hpZnQgKyBjb25zdGFudHMuZXh0cmFQYWRcbiAgICAgICAgKTtcblxuICAgICAgICByYW5nZVNsaWRlci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4ICsgJywnICsgeSArICcpJyk7XG5cbiAgICAgICAgLy8gdXBkYXRlIGRhdGEgPC0tPiBwaXhlbCBjb29yZGluYXRlIGNvbnZlcnNpb24gbWV0aG9kc1xuXG4gICAgICAgIHZhciByYW5nZTAgPSBheGlzT3B0cy5yMmwob3B0cy5yYW5nZVswXSksXG4gICAgICAgICAgICByYW5nZTEgPSBheGlzT3B0cy5yMmwob3B0cy5yYW5nZVsxXSksXG4gICAgICAgICAgICBkaXN0ID0gcmFuZ2UxIC0gcmFuZ2UwO1xuXG4gICAgICAgIG9wdHMucDJkID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuICh2IC8gb3B0cy5fd2lkdGgpICogZGlzdCArIHJhbmdlMDtcbiAgICAgICAgfTtcblxuICAgICAgICBvcHRzLmQycCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiAodiAtIHJhbmdlMCkgLyBkaXN0ICogb3B0cy5fd2lkdGg7XG4gICAgICAgIH07XG5cbiAgICAgICAgb3B0cy5fcmwgPSBbcmFuZ2UwLCByYW5nZTFdO1xuXG4gICAgICAgIGlmKG9wcEF4aXNSYW5nZU9wdHMucmFuZ2Vtb2RlICE9PSAnbWF0Y2gnKSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2UwT3BwQXhpcyA9IG9wcEF4aXNPcHRzLnIybChvcHBBeGlzUmFuZ2VPcHRzLnJhbmdlWzBdKSxcbiAgICAgICAgICAgICAgICByYW5nZTFPcHBBeGlzID0gb3BwQXhpc09wdHMucjJsKG9wcEF4aXNSYW5nZU9wdHMucmFuZ2VbMV0pLFxuICAgICAgICAgICAgICAgIGRpc3RPcHBBeGlzID0gcmFuZ2UxT3BwQXhpcyAtIHJhbmdlME9wcEF4aXM7XG5cbiAgICAgICAgICAgIG9wdHMuZDJwT3BwQXhpcyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHYgLSByYW5nZTBPcHBBeGlzKSAvIGRpc3RPcHBBeGlzICogb3B0cy5faGVpZ2h0O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSBpbm5lciBub2Rlc1xuXG4gICAgICAgIHJhbmdlU2xpZGVyXG4gICAgICAgICAgICAuY2FsbChkcmF3QmcsIGdkLCBheGlzT3B0cywgb3B0cylcbiAgICAgICAgICAgIC5jYWxsKGFkZENsaXBQYXRoLCBnZCwgYXhpc09wdHMsIG9wdHMpXG4gICAgICAgICAgICAuY2FsbChkcmF3UmFuZ2VQbG90LCBnZCwgYXhpc09wdHMsIG9wdHMpXG4gICAgICAgICAgICAuY2FsbChkcmF3TWFza3MsIGdkLCBheGlzT3B0cywgb3B0cywgb3BwQXhpc1JhbmdlT3B0cylcbiAgICAgICAgICAgIC5jYWxsKGRyYXdTbGlkZUJveCwgZ2QsIGF4aXNPcHRzLCBvcHRzKVxuICAgICAgICAgICAgLmNhbGwoZHJhd0dyYWJiZXJzLCBnZCwgYXhpc09wdHMsIG9wdHMpO1xuXG4gICAgICAgIC8vIHNldHVwIGRyYWcgZWxlbWVudFxuICAgICAgICBzZXR1cERyYWdFbGVtZW50KHJhbmdlU2xpZGVyLCBnZCwgYXhpc09wdHMsIG9wdHMpO1xuXG4gICAgICAgIC8vIHVwZGF0ZSBjdXJyZW50IHJhbmdlXG4gICAgICAgIHNldFBpeGVsUmFuZ2UocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cywgb3BwQXhpc09wdHMsIG9wcEF4aXNSYW5nZU9wdHMpO1xuXG4gICAgICAgIC8vIHRpdGxlIGdvZXMgbmV4dCB0byByYW5nZSBzbGlkZXIgaW5zdGVhZCBvZiB0aWNrIGxhYmVscywgc29cbiAgICAgICAgLy8ganVzdCB0YWtlIGl0IG92ZXIgYW5kIGRyYXcgaXQgZnJvbSBoZXJlXG4gICAgICAgIGlmKGF4aXNPcHRzLnNpZGUgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICBUaXRsZXMuZHJhdyhnZCwgYXhpc09wdHMuX2lkICsgJ3RpdGxlJywge1xuICAgICAgICAgICAgICAgIHByb3BDb250YWluZXI6IGF4aXNPcHRzLFxuICAgICAgICAgICAgICAgIHByb3BOYW1lOiBheGlzT3B0cy5fbmFtZSArICcudGl0bGUnLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBmdWxsTGF5b3V0Ll9kZmx0VGl0bGUueCxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHg6IGF4aXNPcHRzLl9vZmZzZXQgKyBheGlzT3B0cy5fbGVuZ3RoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgeTogeSArIG9wdHMuX2hlaWdodCArIG9wdHMuX29mZnNldFNoaWZ0ICsgMTAgKyAxLjUgKiBheGlzT3B0cy50aXRsZWZvbnQuc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSBtYXJnaW5zXG4gICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIG9wdHMuX2lkLCB7XG4gICAgICAgICAgICB4OiBkb21haW5bMF0sXG4gICAgICAgICAgICB5OiBvcHBCb3R0b20sXG4gICAgICAgICAgICBsOiAwLFxuICAgICAgICAgICAgcjogMCxcbiAgICAgICAgICAgIHQ6IDAsXG4gICAgICAgICAgICBiOiBvcHRzLl9oZWlnaHQgKyBtYXJnaW4uYiArIHRpY2tIZWlnaHQsXG4gICAgICAgICAgICBwYWQ6IGNvbnN0YW50cy5leHRyYVBhZCArIG9wdHMuX29mZnNldFNoaWZ0ICogMlxuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VSYW5nZVNsaWRlckRhdGEoZnVsbExheW91dCkge1xuICAgIHZhciBheGVzID0gQXhlcy5saXN0KHsgX2Z1bGxMYXlvdXQ6IGZ1bGxMYXlvdXQgfSwgJ3gnLCB0cnVlKSxcbiAgICAgICAgbmFtZSA9IGNvbnN0YW50cy5uYW1lLFxuICAgICAgICBvdXQgPSBbXTtcblxuICAgIGlmKGZ1bGxMYXlvdXQuX2hhcygnZ2wyZCcpKSByZXR1cm4gb3V0O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4ID0gYXhlc1tpXTtcblxuICAgICAgICBpZihheFtuYW1lXSAmJiBheFtuYW1lXS52aXNpYmxlKSBvdXQucHVzaChheCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gc2V0dXBEcmFnRWxlbWVudChyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKSB7XG4gICAgdmFyIHNsaWRlQm94ID0gcmFuZ2VTbGlkZXIuc2VsZWN0KCdyZWN0LicgKyBjb25zdGFudHMuc2xpZGVCb3hDbGFzc05hbWUpLm5vZGUoKSxcbiAgICAgICAgZ3JhYkFyZWFNaW4gPSByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5ncmFiQXJlYU1pbkNsYXNzTmFtZSkubm9kZSgpLFxuICAgICAgICBncmFiQXJlYU1heCA9IHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLmdyYWJBcmVhTWF4Q2xhc3NOYW1lKS5ub2RlKCk7XG5cbiAgICByYW5nZVNsaWRlci5vbignbW91c2Vkb3duJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBldmVudCA9IGQzLmV2ZW50LFxuICAgICAgICAgICAgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0LFxuICAgICAgICAgICAgc3RhcnRYID0gZXZlbnQuY2xpZW50WCxcbiAgICAgICAgICAgIG9mZnNldFggPSBzdGFydFggLSByYW5nZVNsaWRlci5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCxcbiAgICAgICAgICAgIG1pblZhbCA9IG9wdHMuZDJwKGF4aXNPcHRzLl9ybFswXSksXG4gICAgICAgICAgICBtYXhWYWwgPSBvcHRzLmQycChheGlzT3B0cy5fcmxbMV0pO1xuXG4gICAgICAgIHZhciBkcmFnQ292ZXIgPSBkcmFnRWxlbWVudC5jb3ZlclNsaXAoKTtcblxuICAgICAgICBkcmFnQ292ZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW91c2VNb3ZlKTtcbiAgICAgICAgZHJhZ0NvdmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBtb3VzZVVwKTtcblxuICAgICAgICBmdW5jdGlvbiBtb3VzZU1vdmUoZSkge1xuICAgICAgICAgICAgdmFyIGRlbHRhID0gK2UuY2xpZW50WCAtIHN0YXJ0WDtcbiAgICAgICAgICAgIHZhciBwaXhlbE1pbiwgcGl4ZWxNYXgsIGN1cnNvcjtcblxuICAgICAgICAgICAgc3dpdGNoKHRhcmdldCkge1xuICAgICAgICAgICAgICAgIGNhc2Ugc2xpZGVCb3g6XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvciA9ICdldy1yZXNpemUnO1xuICAgICAgICAgICAgICAgICAgICBwaXhlbE1pbiA9IG1pblZhbCArIGRlbHRhO1xuICAgICAgICAgICAgICAgICAgICBwaXhlbE1heCA9IG1heFZhbCArIGRlbHRhO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgZ3JhYkFyZWFNaW46XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvciA9ICdjb2wtcmVzaXplJztcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNaW4gPSBtaW5WYWwgKyBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNYXggPSBtYXhWYWw7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBncmFiQXJlYU1heDpcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yID0gJ2NvbC1yZXNpemUnO1xuICAgICAgICAgICAgICAgICAgICBwaXhlbE1pbiA9IG1pblZhbDtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNYXggPSBtYXhWYWwgKyBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBjdXJzb3IgPSAnZXctcmVzaXplJztcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNaW4gPSBvZmZzZXRYO1xuICAgICAgICAgICAgICAgICAgICBwaXhlbE1heCA9IG9mZnNldFggKyBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHBpeGVsTWF4IDwgcGl4ZWxNaW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gcGl4ZWxNYXg7XG4gICAgICAgICAgICAgICAgcGl4ZWxNYXggPSBwaXhlbE1pbjtcbiAgICAgICAgICAgICAgICBwaXhlbE1pbiA9IHRtcDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3B0cy5fcGl4ZWxNaW4gPSBwaXhlbE1pbjtcbiAgICAgICAgICAgIG9wdHMuX3BpeGVsTWF4ID0gcGl4ZWxNYXg7XG5cbiAgICAgICAgICAgIHNldEN1cnNvcihkMy5zZWxlY3QoZHJhZ0NvdmVyKSwgY3Vyc29yKTtcbiAgICAgICAgICAgIHNldERhdGFSYW5nZShyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG1vdXNlVXAoKSB7XG4gICAgICAgICAgICBkcmFnQ292ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW91c2VNb3ZlKTtcbiAgICAgICAgICAgIGRyYWdDb3Zlci5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgbW91c2VVcCk7XG4gICAgICAgICAgICBMaWIucmVtb3ZlRWxlbWVudChkcmFnQ292ZXIpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHNldERhdGFSYW5nZShyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKSB7XG5cbiAgICBmdW5jdGlvbiBjbGFtcCh2KSB7XG4gICAgICAgIHJldHVybiBheGlzT3B0cy5sMnIoTGliLmNvbnN0cmFpbih2LCBvcHRzLl9ybFswXSwgb3B0cy5fcmxbMV0pKTtcbiAgICB9XG5cbiAgICB2YXIgZGF0YU1pbiA9IGNsYW1wKG9wdHMucDJkKG9wdHMuX3BpeGVsTWluKSksXG4gICAgICAgIGRhdGFNYXggPSBjbGFtcChvcHRzLnAyZChvcHRzLl9waXhlbE1heCkpO1xuXG4gICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShmdW5jdGlvbigpIHtcbiAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYXhpc09wdHMuX25hbWUgKyAnLnJhbmdlJywgW2RhdGFNaW4sIGRhdGFNYXhdKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0UGl4ZWxSYW5nZShyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzLCBvcHBBeGlzT3B0cywgb3BwQXhpc1JhbmdlT3B0cykge1xuICAgIHZhciBodzIgPSBjb25zdGFudHMuaGFuZGxlV2lkdGggLyAyO1xuXG4gICAgZnVuY3Rpb24gY2xhbXAodikge1xuICAgICAgICByZXR1cm4gTGliLmNvbnN0cmFpbih2LCAwLCBvcHRzLl93aWR0aCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xhbXBPcHBBeGlzKHYpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb25zdHJhaW4odiwgMCwgb3B0cy5faGVpZ2h0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGFtcEhhbmRsZSh2KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKHYsIC1odzIsIG9wdHMuX3dpZHRoICsgaHcyKTtcbiAgICB9XG5cbiAgICB2YXIgcGl4ZWxNaW4gPSBjbGFtcChvcHRzLmQycChheGlzT3B0cy5fcmxbMF0pKSxcbiAgICAgICAgcGl4ZWxNYXggPSBjbGFtcChvcHRzLmQycChheGlzT3B0cy5fcmxbMV0pKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLnNsaWRlQm94Q2xhc3NOYW1lKVxuICAgICAgICAuYXR0cigneCcsIHBpeGVsTWluKVxuICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNaW5DbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIHBpeGVsTWluKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNYXhDbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd4JywgcGl4ZWxNYXgpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIG9wdHMuX3dpZHRoIC0gcGl4ZWxNYXgpO1xuXG4gICAgaWYob3BwQXhpc1JhbmdlT3B0cy5yYW5nZW1vZGUgIT09ICdtYXRjaCcpIHtcbiAgICAgICAgdmFyIHBpeGVsTWluT3BwQXhpcyA9IG9wdHMuX2hlaWdodCAtIGNsYW1wT3BwQXhpcyhvcHRzLmQycE9wcEF4aXMob3BwQXhpc09wdHMuX3JsWzFdKSksXG4gICAgICAgICAgICBwaXhlbE1heE9wcEF4aXMgPSBvcHRzLl9oZWlnaHQgLSBjbGFtcE9wcEF4aXMob3B0cy5kMnBPcHBBeGlzKG9wcEF4aXNPcHRzLl9ybFswXSkpO1xuXG4gICAgICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNaW5PcHBBeGlzQ2xhc3NOYW1lKVxuICAgICAgICAgICAgLmF0dHIoJ3gnLCBwaXhlbE1pbilcbiAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBwaXhlbE1pbk9wcEF4aXMpXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgICAgICByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5tYXNrTWF4T3BwQXhpc0NsYXNzTmFtZSlcbiAgICAgICAgICAgIC5hdHRyKCd4JywgcGl4ZWxNaW4pXG4gICAgICAgICAgICAuYXR0cigneScsIHBpeGVsTWF4T3BwQXhpcylcbiAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBvcHRzLl9oZWlnaHQgLSBwaXhlbE1heE9wcEF4aXMpXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgICAgICByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5zbGlkZUJveENsYXNzTmFtZSlcbiAgICAgICAgICAgIC5hdHRyKCd5JywgcGl4ZWxNaW5PcHBBeGlzKVxuICAgICAgICAgICAgLmF0dHIoJ2hlaWdodCcsIHBpeGVsTWF4T3BwQXhpcyAtIHBpeGVsTWluT3BwQXhpcyk7XG4gICAgfVxuXG4gICAgLy8gYWRkIG9mZnNldCBmb3IgY3Jpc3BpZXIgY29ybmVyc1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvMTQwOVxuICAgIHZhciBvZmZzZXQgPSAwLjU7XG5cbiAgICB2YXIgeE1pbiA9IE1hdGgucm91bmQoY2xhbXBIYW5kbGUocGl4ZWxNaW4gLSBodzIpKSAtIG9mZnNldCxcbiAgICAgICAgeE1heCA9IE1hdGgucm91bmQoY2xhbXBIYW5kbGUocGl4ZWxNYXggLSBodzIpKSArIG9mZnNldDtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgnZy4nICsgY29uc3RhbnRzLmdyYWJiZXJNaW5DbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4TWluICsgJywnICsgb2Zmc2V0ICsgJyknKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgnZy4nICsgY29uc3RhbnRzLmdyYWJiZXJNYXhDbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4TWF4ICsgJywnICsgb2Zmc2V0ICsgJyknKTtcbn1cblxuZnVuY3Rpb24gZHJhd0JnKHJhbmdlU2xpZGVyLCBnZCwgYXhpc09wdHMsIG9wdHMpIHtcbiAgICB2YXIgYmcgPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5iZ0NsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdmFyIGJvcmRlckNvcnJlY3QgPSAob3B0cy5ib3JkZXJ3aWR0aCAlIDIpID09PSAwID9cbiAgICAgICAgICAgIG9wdHMuYm9yZGVyd2lkdGggOlxuICAgICAgICAgICAgb3B0cy5ib3JkZXJ3aWR0aCAtIDE7XG5cbiAgICB2YXIgb2Zmc2V0U2hpZnQgPSAtb3B0cy5fb2Zmc2V0U2hpZnQ7XG4gICAgdmFyIGx3ID0gRHJhd2luZy5jcmlzcFJvdW5kKGdkLCBvcHRzLmJvcmRlcndpZHRoKTtcblxuICAgIGJnLmF0dHIoe1xuICAgICAgICB3aWR0aDogb3B0cy5fd2lkdGggKyBib3JkZXJDb3JyZWN0LFxuICAgICAgICBoZWlnaHQ6IG9wdHMuX2hlaWdodCArIGJvcmRlckNvcnJlY3QsXG4gICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZSgnICsgb2Zmc2V0U2hpZnQgKyAnLCcgKyBvZmZzZXRTaGlmdCArICcpJyxcbiAgICAgICAgZmlsbDogb3B0cy5iZ2NvbG9yLFxuICAgICAgICBzdHJva2U6IG9wdHMuYm9yZGVyY29sb3IsXG4gICAgICAgICdzdHJva2Utd2lkdGgnOiBsd1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhZGRDbGlwUGF0aChyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBjbGlwUGF0aCA9IExpYi5lbnN1cmVTaW5nbGVCeUlkKGZ1bGxMYXlvdXQuX3RvcGRlZnMsICdjbGlwUGF0aCcsIG9wdHMuX2NsaXBJZCwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmFwcGVuZCgncmVjdCcpLmF0dHIoeyB4OiAwLCB5OiAwIH0pO1xuICAgIH0pO1xuXG4gICAgY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgIHdpZHRoOiBvcHRzLl93aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBvcHRzLl9oZWlnaHRcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZHJhd1JhbmdlUGxvdChyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKSB7XG4gICAgdmFyIHN1YnBsb3REYXRhID0gQXhlcy5nZXRTdWJwbG90cyhnZCwgYXhpc09wdHMpLFxuICAgICAgICBjYWxjRGF0YSA9IGdkLmNhbGNkYXRhO1xuXG4gICAgdmFyIHJhbmdlUGxvdHMgPSByYW5nZVNsaWRlci5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5yYW5nZVBsb3RDbGFzc05hbWUpXG4gICAgICAgIC5kYXRhKHN1YnBsb3REYXRhLCBMaWIuaWRlbnRpdHkpO1xuXG4gICAgcmFuZ2VQbG90cy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGlkKSB7IHJldHVybiBjb25zdGFudHMucmFuZ2VQbG90Q2xhc3NOYW1lICsgJyAnICsgaWQ7IH0pXG4gICAgICAgIC5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgb3B0cy5fY2xpcElkKTtcblxuICAgIHJhbmdlUGxvdHMub3JkZXIoKTtcblxuICAgIHJhbmdlUGxvdHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIG1haW5wbG90aW5mbztcblxuICAgIHJhbmdlUGxvdHMuZWFjaChmdW5jdGlvbihpZCwgaSkge1xuICAgICAgICB2YXIgcGxvdGdyb3VwID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgICAgICAgaXNNYWluUGxvdCA9IChpID09PSAwKTtcblxuICAgICAgICB2YXIgb3BwQXhpc09wdHMgPSBBeGVzLmdldEZyb21JZChnZCwgaWQsICd5JyksXG4gICAgICAgICAgICBvcHBBeGlzTmFtZSA9IG9wcEF4aXNPcHRzLl9uYW1lLFxuICAgICAgICAgICAgb3BwQXhpc1JhbmdlT3B0cyA9IG9wdHNbb3BwQXhpc05hbWVdO1xuXG4gICAgICAgIHZhciBtb2NrRmlndXJlID0ge1xuICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICBsYXlvdXQ6IHtcbiAgICAgICAgICAgICAgICB4YXhpczoge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBheGlzT3B0cy50eXBlLFxuICAgICAgICAgICAgICAgICAgICBkb21haW46IFswLCAxXSxcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IG9wdHMucmFuZ2Uuc2xpY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXI6IGF4aXNPcHRzLmNhbGVuZGFyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB3aWR0aDogb3B0cy5fd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBvcHRzLl9oZWlnaHQsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiB7IHQ6IDAsIGI6IDAsIGw6IDAsIHI6IDAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9jb250ZXh0OiBnZC5fY29udGV4dFxuICAgICAgICB9O1xuXG4gICAgICAgIG1vY2tGaWd1cmUubGF5b3V0W29wcEF4aXNOYW1lXSA9IHtcbiAgICAgICAgICAgIHR5cGU6IG9wcEF4aXNPcHRzLnR5cGUsXG4gICAgICAgICAgICBkb21haW46IFswLCAxXSxcbiAgICAgICAgICAgIHJhbmdlOiBvcHBBeGlzUmFuZ2VPcHRzLnJhbmdlbW9kZSAhPT0gJ21hdGNoJyA/IG9wcEF4aXNSYW5nZU9wdHMucmFuZ2Uuc2xpY2UoKSA6IG9wcEF4aXNPcHRzLnJhbmdlLnNsaWNlKCksXG4gICAgICAgICAgICBjYWxlbmRhcjogb3BwQXhpc09wdHMuY2FsZW5kYXJcbiAgICAgICAgfTtcblxuICAgICAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhtb2NrRmlndXJlKTtcblxuICAgICAgICB2YXIgeGEgPSBtb2NrRmlndXJlLl9mdWxsTGF5b3V0LnhheGlzO1xuICAgICAgICB2YXIgeWEgPSBtb2NrRmlndXJlLl9mdWxsTGF5b3V0W29wcEF4aXNOYW1lXTtcblxuICAgICAgICB2YXIgcGxvdGluZm8gPSB7XG4gICAgICAgICAgICBpZDogaWQsXG4gICAgICAgICAgICBwbG90Z3JvdXA6IHBsb3Rncm91cCxcbiAgICAgICAgICAgIHhheGlzOiB4YSxcbiAgICAgICAgICAgIHlheGlzOiB5YSxcbiAgICAgICAgICAgIGlzUmFuZ2VQbG90OiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYoaXNNYWluUGxvdCkgbWFpbnBsb3RpbmZvID0gcGxvdGluZm87XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcGxvdGluZm8ubWFpbnBsb3QgPSAneHknO1xuICAgICAgICAgICAgcGxvdGluZm8ubWFpbnBsb3RpbmZvID0gbWFpbnBsb3RpbmZvO1xuICAgICAgICB9XG5cbiAgICAgICAgQ2FydGVzaWFuLnJhbmdlUGxvdChnZCwgcGxvdGluZm8sIGZpbHRlclJhbmdlUGxvdENhbGNEYXRhKGNhbGNEYXRhLCBpZCkpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJSYW5nZVBsb3RDYWxjRGF0YShjYWxjRGF0YSwgc3VicGxvdElkKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjRGF0YVtpXSxcbiAgICAgICAgICAgIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXMgPT09IHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgb3V0LnB1c2goY2FsY1RyYWNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGRyYXdNYXNrcyhyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzLCBvcHBBeGlzUmFuZ2VPcHRzKSB7XG4gICAgdmFyIG1hc2tNaW4gPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5tYXNrTWluQ2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBtYXNrTWluXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBvcHRzLl9oZWlnaHQpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGNvbnN0YW50cy5tYXNrQ29sb3IpO1xuXG4gICAgdmFyIG1hc2tNYXggPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5tYXNrTWF4Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgJ3NoYXBlLXJlbmRlcmluZyc6ICdjcmlzcEVkZ2VzJ1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIG1hc2tNYXhcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIG9wdHMuX2hlaWdodClcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgY29uc3RhbnRzLm1hc2tDb2xvcik7XG5cbiAgICAvLyBtYXNrcyB1c2VkIGZvciBvcHBBeGlzIHpvb21cbiAgICBpZihvcHBBeGlzUmFuZ2VPcHRzLnJhbmdlbW9kZSAhPT0gJ21hdGNoJykge1xuICAgICAgICB2YXIgbWFza01pbk9wcEF4aXMgPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5tYXNrTWluT3BwQXhpc0NsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcy5hdHRyKHtcbiAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBtYXNrTWluT3BwQXhpc1xuICAgICAgICAgICAgLmF0dHIoJ3dpZHRoJywgb3B0cy5fd2lkdGgpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb25zdGFudHMubWFza09wcEF4aXNDb2xvcik7XG5cbiAgICAgICAgdmFyIG1hc2tNYXhPcHBBeGlzID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ3JlY3QnLCBjb25zdGFudHMubWFza01heE9wcEF4aXNDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbWFza01heE9wcEF4aXNcbiAgICAgICAgICAgIC5hdHRyKCd3aWR0aCcsIG9wdHMuX3dpZHRoKVxuICAgICAgICAgICAgLnN0eWxlKCdib3JkZXItdG9wJywgY29uc3RhbnRzLm1hc2tPcHBCb3JkZXIpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb25zdGFudHMubWFza09wcEF4aXNDb2xvcik7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3U2xpZGVCb3gocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIGlmKGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHJldHVybjtcblxuICAgIHZhciBzbGlkZUJveCA9IExpYi5lbnN1cmVTaW5nbGUocmFuZ2VTbGlkZXIsICdyZWN0JywgY29uc3RhbnRzLnNsaWRlQm94Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgY3Vyc29yOiBjb25zdGFudHMuc2xpZGVCb3hDdXJzb3IsXG4gICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgc2xpZGVCb3guYXR0cih7XG4gICAgICAgIGhlaWdodDogb3B0cy5faGVpZ2h0LFxuICAgICAgICBmaWxsOiBjb25zdGFudHMuc2xpZGVCb3hGaWxsXG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRyYXdHcmFiYmVycyhyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzKSB7XG4gICAgLy8gPGcgZ3JhYmJlciAvPlxuICAgIHZhciBncmFiYmVyTWluID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ2cnLCBjb25zdGFudHMuZ3JhYmJlck1pbkNsYXNzTmFtZSk7XG4gICAgdmFyIGdyYWJiZXJNYXggPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAnZycsIGNvbnN0YW50cy5ncmFiYmVyTWF4Q2xhc3NOYW1lKTtcblxuICAgIC8vIDxnIGhhbmRsZSAvPlxuICAgIHZhciBoYW5kbGVGaXhBdHRycyA9IHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgd2lkdGg6IGNvbnN0YW50cy5oYW5kbGVXaWR0aCxcbiAgICAgICAgcng6IGNvbnN0YW50cy5oYW5kbGVSYWRpdXMsXG4gICAgICAgIGZpbGw6IENvbG9yLmJhY2tncm91bmQsXG4gICAgICAgIHN0cm9rZTogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICdzdHJva2Utd2lkdGgnOiBjb25zdGFudHMuaGFuZGxlU3Ryb2tlV2lkdGgsXG4gICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICB9O1xuICAgIHZhciBoYW5kbGVEeW5hbWljQXR0cnMgPSB7XG4gICAgICAgIHk6IE1hdGgucm91bmQob3B0cy5faGVpZ2h0IC8gNCksXG4gICAgICAgIGhlaWdodDogTWF0aC5yb3VuZChvcHRzLl9oZWlnaHQgLyAyKSxcbiAgICB9O1xuICAgIHZhciBoYW5kbGVNaW4gPSBMaWIuZW5zdXJlU2luZ2xlKGdyYWJiZXJNaW4sICdyZWN0JywgY29uc3RhbnRzLmhhbmRsZU1pbkNsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoaGFuZGxlRml4QXR0cnMpO1xuICAgIH0pO1xuICAgIGhhbmRsZU1pbi5hdHRyKGhhbmRsZUR5bmFtaWNBdHRycyk7XG5cbiAgICB2YXIgaGFuZGxlTWF4ID0gTGliLmVuc3VyZVNpbmdsZShncmFiYmVyTWF4LCAncmVjdCcsIGNvbnN0YW50cy5oYW5kbGVNYXhDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKGhhbmRsZUZpeEF0dHJzKTtcbiAgICB9KTtcbiAgICBoYW5kbGVNYXguYXR0cihoYW5kbGVEeW5hbWljQXR0cnMpO1xuXG4gICAgLy8gPGcgZ3JhYmFyZWEgLz5cbiAgICBpZihnZC5fY29udGV4dC5zdGF0aWNQbG90KSByZXR1cm47XG5cbiAgICB2YXIgZ3JhYkFyZWFGaXhBdHRycyA9IHtcbiAgICAgICAgd2lkdGg6IGNvbnN0YW50cy5ncmFiQXJlYVdpZHRoLFxuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICBmaWxsOiBjb25zdGFudHMuZ3JhYkFyZWFGaWxsLFxuICAgICAgICBjdXJzb3I6IGNvbnN0YW50cy5ncmFiQXJlYUN1cnNvclxuICAgIH07XG5cbiAgICB2YXIgZ3JhYkFyZWFNaW4gPSBMaWIuZW5zdXJlU2luZ2xlKGdyYWJiZXJNaW4sICdyZWN0JywgY29uc3RhbnRzLmdyYWJBcmVhTWluQ2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cihncmFiQXJlYUZpeEF0dHJzKTtcbiAgICB9KTtcbiAgICBncmFiQXJlYU1pbi5hdHRyKCdoZWlnaHQnLCBvcHRzLl9oZWlnaHQpO1xuXG4gICAgdmFyIGdyYWJBcmVhTWF4ID0gTGliLmVuc3VyZVNpbmdsZShncmFiYmVyTWF4LCAncmVjdCcsIGNvbnN0YW50cy5ncmFiQXJlYU1heENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoZ3JhYkFyZWFGaXhBdHRycyk7XG4gICAgfSk7XG4gICAgZ3JhYkFyZWFNYXguYXR0cignaGVpZ2h0Jywgb3B0cy5faGVpZ2h0KTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGF0dHJzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgb3BwQXhpc0F0dHJzID0gcmVxdWlyZSgnLi9vcHBheGlzX2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ3Jhbmdlc2xpZGVyJyxcblxuICAgIHNjaGVtYToge1xuICAgICAgICBzdWJwbG90czoge1xuICAgICAgICAgICAgeGF4aXM6IHtcbiAgICAgICAgICAgICAgICByYW5nZXNsaWRlcjogTGliLmV4dGVuZEZsYXQoe30sIGF0dHJzLCB7XG4gICAgICAgICAgICAgICAgICAgIHlheGlzOiBvcHBBeGlzQXR0cnNcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxheW91dEF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpLFxuICAgIGhhbmRsZURlZmF1bHRzOiByZXF1aXJlKCcuL2RlZmF1bHRzJyksXG4gICAgY2FsY0F1dG9yYW5nZTogcmVxdWlyZSgnLi9jYWxjX2F1dG9yYW5nZScpLFxuICAgIGRyYXc6IHJlcXVpcmUoJy4vZHJhdycpXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBub3QgcmVhbGx5IGEgJ3N1YnBsb3QnIGF0dHJpYnV0ZSBjb250YWluZXIsXG4gICAgLy8gYnV0IHRoaXMgaXMgdGhlIGZsYWcgd2UgdXNlIHRvIGRlbm90ZSBhdHRyaWJ1dGVzIHRoYXRcbiAgICAvLyBzdXBwb3J0IHlheGlzLCB5YXhpczIsIHlheGlzMywgLi4uIGNvdW50ZXJzXG4gICAgX2lzU3VicGxvdE9iajogdHJ1ZSxcblxuICAgIHJhbmdlbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ2ZpeGVkJywgJ21hdGNoJ10sXG4gICAgICAgIGRmbHQ6ICdtYXRjaCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAncGxvdCd9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3Bsb3QnfVxuICAgICAgICBdLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBhbm5BdHRycyA9IHJlcXVpcmUoJy4uL2Fubm90YXRpb25zL2F0dHJpYnV0ZXMnKTtcbnZhciBzY2F0dGVyTGluZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vdHJhY2VzL3NjYXR0ZXIvYXR0cmlidXRlcycpLmxpbmU7XG52YXIgZGFzaCA9IHJlcXVpcmUoJy4uL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHRlbXBsYXRlZEFycmF5KCdzaGFwZScsIHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdHlwZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydjaXJjbGUnLCAncmVjdCcsICdwYXRoJywgJ2xpbmUnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGF5ZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYmVsb3cnLCAnYWJvdmUnXSxcbiAgICAgICAgZGZsdDogJ2Fib3ZlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhyZWY6IGV4dGVuZEZsYXQoe30sIGFubkF0dHJzLnhyZWYsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgeHNpemVtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3NjYWxlZCcsICdwaXhlbCddLFxuICAgICAgICBkZmx0OiAnc2NhbGVkJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4MDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHgxOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB5cmVmOiBleHRlbmRGbGF0KHt9LCBhbm5BdHRycy55cmVmLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIHlzaXplbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzY2FsZWQnLCAncGl4ZWwnXSxcbiAgICAgICAgZGZsdDogJ3NjYWxlZCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeTA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5MToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcGF0aDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGluZToge1xuICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy5jb2xvciwge2VkaXRUeXBlOiAnYXJyYXlkcmF3J30pLFxuICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy53aWR0aCwge2VkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnfSksXG4gICAgICAgIGRhc2g6IGV4dGVuZEZsYXQoe30sIGRhc2gsIHtlZGl0VHlwZTogJ2FycmF5ZHJhdyd9KSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnXG4gICAgfSxcbiAgICBmaWxsY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3J1xufSk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjQXV0b3JhbmdlKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCxcbiAgICAgICAgc2hhcGVMaXN0ID0gTGliLmZpbHRlclZpc2libGUoZnVsbExheW91dC5zaGFwZXMpO1xuXG4gICAgaWYoIXNoYXBlTGlzdC5sZW5ndGggfHwgIWdkLl9mdWxsRGF0YS5sZW5ndGgpIHJldHVybjtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzaGFwZUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNoYXBlID0gc2hhcGVMaXN0W2ldO1xuICAgICAgICBzaGFwZS5fZXh0cmVtZXMgPSB7fTtcblxuICAgICAgICB2YXIgYXgsIGJvdW5kcztcblxuICAgICAgICBpZihzaGFwZS54cmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICB2YXIgdngwID0gc2hhcGUueHNpemVtb2RlID09PSAncGl4ZWwnID8gc2hhcGUueGFuY2hvciA6IHNoYXBlLngwLFxuICAgICAgICAgICAgICAgIHZ4MSA9IHNoYXBlLnhzaXplbW9kZSA9PT0gJ3BpeGVsJyA/IHNoYXBlLnhhbmNob3IgOiBzaGFwZS54MTtcbiAgICAgICAgICAgIGF4ID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHNoYXBlLnhyZWYpO1xuXG4gICAgICAgICAgICBib3VuZHMgPSBzaGFwZUJvdW5kcyhheCwgdngwLCB2eDEsIHNoYXBlLnBhdGgsIGNvbnN0YW50cy5wYXJhbUlzWCk7XG4gICAgICAgICAgICBpZihib3VuZHMpIHtcbiAgICAgICAgICAgICAgICBzaGFwZS5fZXh0cmVtZXNbYXguX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKGF4LCBib3VuZHMsIGNhbGNYUGFkZGluZ09wdGlvbnMoc2hhcGUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNoYXBlLnlyZWYgIT09ICdwYXBlcicpIHtcbiAgICAgICAgICAgIHZhciB2eTAgPSBzaGFwZS55c2l6ZW1vZGUgPT09ICdwaXhlbCcgPyBzaGFwZS55YW5jaG9yIDogc2hhcGUueTAsXG4gICAgICAgICAgICAgICAgdnkxID0gc2hhcGUueXNpemVtb2RlID09PSAncGl4ZWwnID8gc2hhcGUueWFuY2hvciA6IHNoYXBlLnkxO1xuICAgICAgICAgICAgYXggPSBBeGVzLmdldEZyb21JZChnZCwgc2hhcGUueXJlZik7XG5cbiAgICAgICAgICAgIGJvdW5kcyA9IHNoYXBlQm91bmRzKGF4LCB2eTAsIHZ5MSwgc2hhcGUucGF0aCwgY29uc3RhbnRzLnBhcmFtSXNZKTtcbiAgICAgICAgICAgIGlmKGJvdW5kcykge1xuICAgICAgICAgICAgICAgIHNoYXBlLl9leHRyZW1lc1theC5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoYXgsIGJvdW5kcywgY2FsY1lQYWRkaW5nT3B0aW9ucyhzaGFwZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY2FsY1hQYWRkaW5nT3B0aW9ucyhzaGFwZSkge1xuICAgIHJldHVybiBjYWxjUGFkZGluZ09wdGlvbnMoc2hhcGUubGluZS53aWR0aCwgc2hhcGUueHNpemVtb2RlLCBzaGFwZS54MCwgc2hhcGUueDEsIHNoYXBlLnBhdGgsIGZhbHNlKTtcbn1cblxuZnVuY3Rpb24gY2FsY1lQYWRkaW5nT3B0aW9ucyhzaGFwZSkge1xuICAgIHJldHVybiBjYWxjUGFkZGluZ09wdGlvbnMoc2hhcGUubGluZS53aWR0aCwgc2hhcGUueXNpemVtb2RlLCBzaGFwZS55MCwgc2hhcGUueTEsIHNoYXBlLnBhdGgsIHRydWUpO1xufVxuXG5mdW5jdGlvbiBjYWxjUGFkZGluZ09wdGlvbnMobGluZVdpZHRoLCBzaXplTW9kZSwgdjAsIHYxLCBwYXRoLCBpc1lBeGlzKSB7XG4gICAgdmFyIHBwYWQgPSBsaW5lV2lkdGggLyAyLFxuICAgICAgICBheGlzRGlyZWN0aW9uUmV2ZXJ0ZWQgPSBpc1lBeGlzO1xuXG4gICAgaWYoc2l6ZU1vZGUgPT09ICdwaXhlbCcpIHtcbiAgICAgICAgdmFyIGNvb3JkcyA9IHBhdGggP1xuICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdFBhdGhDb29yZHMocGF0aCwgaXNZQXhpcyA/IGNvbnN0YW50cy5wYXJhbUlzWSA6IGNvbnN0YW50cy5wYXJhbUlzWCkgOlxuICAgICAgICAgIFt2MCwgdjFdO1xuICAgICAgICB2YXIgbWF4VmFsdWUgPSBMaWIuYWdnTnVtcyhNYXRoLm1heCwgbnVsbCwgY29vcmRzKSxcbiAgICAgICAgICAgIG1pblZhbHVlID0gTGliLmFnZ051bXMoTWF0aC5taW4sIG51bGwsIGNvb3JkcyksXG4gICAgICAgICAgICBiZWZvcmVQYWQgPSBtaW5WYWx1ZSA8IDAgPyBNYXRoLmFicyhtaW5WYWx1ZSkgKyBwcGFkIDogcHBhZCxcbiAgICAgICAgICAgIGFmdGVyUGFkID0gbWF4VmFsdWUgPiAwID8gbWF4VmFsdWUgKyBwcGFkIDogcHBhZDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcHBhZDogcHBhZCxcbiAgICAgICAgICAgIHBwYWRwbHVzOiBheGlzRGlyZWN0aW9uUmV2ZXJ0ZWQgPyBiZWZvcmVQYWQgOiBhZnRlclBhZCxcbiAgICAgICAgICAgIHBwYWRtaW51czogYXhpc0RpcmVjdGlvblJldmVydGVkID8gYWZ0ZXJQYWQgOiBiZWZvcmVQYWRcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge3BwYWQ6IHBwYWR9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2hhcGVCb3VuZHMoYXgsIHYwLCB2MSwgcGF0aCwgcGFyYW1zVG9Vc2UpIHtcbiAgICB2YXIgY29udmVydFZhbCA9IChheC50eXBlID09PSAnY2F0ZWdvcnknKSA/IGF4LnIyYyA6IGF4LmQyYztcblxuICAgIGlmKHYwICE9PSB1bmRlZmluZWQpIHJldHVybiBbY29udmVydFZhbCh2MCksIGNvbnZlcnRWYWwodjEpXTtcbiAgICBpZighcGF0aCkgcmV0dXJuO1xuXG4gICAgdmFyIG1pbiA9IEluZmluaXR5LFxuICAgICAgICBtYXggPSAtSW5maW5pdHksXG4gICAgICAgIHNlZ21lbnRzID0gcGF0aC5tYXRjaChjb25zdGFudHMuc2VnbWVudFJFKSxcbiAgICAgICAgaSxcbiAgICAgICAgc2VnbWVudCxcbiAgICAgICAgZHJhd25QYXJhbSxcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICB2YWw7XG5cbiAgICBpZihheC50eXBlID09PSAnZGF0ZScpIGNvbnZlcnRWYWwgPSBoZWxwZXJzLmRlY29kZURhdGUoY29udmVydFZhbCk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzZWdtZW50ID0gc2VnbWVudHNbaV07XG4gICAgICAgIGRyYXduUGFyYW0gPSBwYXJhbXNUb1VzZVtzZWdtZW50LmNoYXJBdCgwKV0uZHJhd247XG4gICAgICAgIGlmKGRyYXduUGFyYW0gPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgICAgcGFyYW1zID0gc2VnbWVudHNbaV0uc3Vic3RyKDEpLm1hdGNoKGNvbnN0YW50cy5wYXJhbVJFKTtcbiAgICAgICAgaWYoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoIDwgZHJhd25QYXJhbSkgY29udGludWU7XG5cbiAgICAgICAgdmFsID0gY29udmVydFZhbChwYXJhbXNbZHJhd25QYXJhbV0pO1xuICAgICAgICBpZih2YWwgPCBtaW4pIG1pbiA9IHZhbDtcbiAgICAgICAgaWYodmFsID4gbWF4KSBtYXggPSB2YWw7XG4gICAgfVxuICAgIGlmKG1heCA+PSBtaW4pIHJldHVybiBbbWluLCBtYXhdO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc2VnbWVudFJFOiAvW01MSFZRQ1RTWl1bXk1MSFZRQ1RTWl0qL2csXG4gICAgcGFyYW1SRTogL1teXFxzLF0rL2csXG5cbiAgICAvLyB3aGljaCBudW1iZXJzIGluIGVhY2ggcGF0aCBzZWdtZW50IGFyZSB4IChvciB5KSB2YWx1ZXNcbiAgICAvLyBkcmF3biBpcyB3aGljaCBwYXJhbSBpcyBhIGRyYXduIHBvaW50LCBhcyBvcHBvc2VkIHRvIGFcbiAgICAvLyBjb250cm9sIHBvaW50ICh3aGljaCBkb2Vzbid0IGNvdW50IHRvd2FyZCBhdXRvcmFuZ2UuXG4gICAgLy8gVE9ETzogdGhpcyBtZWFucyBjdXJ2ZWQgcGF0aHMgY291bGQgZXh0ZW5kIGJleW9uZCB0aGVcbiAgICAvLyBhdXRvcmFuZ2UgYm91bmRzLiBUaGlzIGlzIGEgYml0IHRyaWNreSB0byBnZXQgcmlnaHRcbiAgICAvLyB1bmxlc3Mgd2UgcmV2ZXJ0IHRvIGJvdW5kaW5nIGJveGVzLCBidXQgcGVyaGFwcyB0aGVyZSdzXG4gICAgLy8gYSBjYWxjdWxhdGlvbiB3ZSBjb3VsZCBkby4uLilcbiAgICBwYXJhbUlzWDoge1xuICAgICAgICBNOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBMOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBIOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBWOiB7fSxcbiAgICAgICAgUTogezA6IHRydWUsIDI6IHRydWUsIGRyYXduOiAyfSxcbiAgICAgICAgQzogezA6IHRydWUsIDI6IHRydWUsIDQ6IHRydWUsIGRyYXduOiA0fSxcbiAgICAgICAgVDogezA6IHRydWUsIGRyYXduOiAwfSxcbiAgICAgICAgUzogezA6IHRydWUsIDI6IHRydWUsIGRyYXduOiAyfSxcbiAgICAgICAgLy8gQTogezA6IHRydWUsIDU6IHRydWV9LFxuICAgICAgICBaOiB7fVxuICAgIH0sXG5cbiAgICBwYXJhbUlzWToge1xuICAgICAgICBNOiB7MTogdHJ1ZSwgZHJhd246IDF9LFxuICAgICAgICBMOiB7MTogdHJ1ZSwgZHJhd246IDF9LFxuICAgICAgICBIOiB7fSxcbiAgICAgICAgVjogezA6IHRydWUsIGRyYXduOiAwfSxcbiAgICAgICAgUTogezE6IHRydWUsIDM6IHRydWUsIGRyYXduOiAzfSxcbiAgICAgICAgQzogezE6IHRydWUsIDM6IHRydWUsIDU6IHRydWUsIGRyYXduOiA1fSxcbiAgICAgICAgVDogezE6IHRydWUsIGRyYXduOiAxfSxcbiAgICAgICAgUzogezE6IHRydWUsIDM6IHRydWUsIGRyYXduOiA1fSxcbiAgICAgICAgLy8gQTogezE6IHRydWUsIDY6IHRydWV9LFxuICAgICAgICBaOiB7fVxuICAgIH0sXG5cbiAgICBudW1QYXJhbXM6IHtcbiAgICAgICAgTTogMixcbiAgICAgICAgTDogMixcbiAgICAgICAgSDogMSxcbiAgICAgICAgVjogMSxcbiAgICAgICAgUTogNCxcbiAgICAgICAgQzogNixcbiAgICAgICAgVDogMixcbiAgICAgICAgUzogNCxcbiAgICAgICAgLy8gQTogNyxcbiAgICAgICAgWjogMFxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCB7XG4gICAgICAgIG5hbWU6ICdzaGFwZXMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGhhbmRsZVNoYXBlRGVmYXVsdHNcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZVNoYXBlRGVmYXVsdHMoc2hhcGVJbiwgc2hhcGVPdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShzaGFwZUluLCBzaGFwZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcblxuICAgIGlmKCF2aXNpYmxlKSByZXR1cm47XG5cbiAgICBjb2VyY2UoJ2xheWVyJyk7XG4gICAgY29lcmNlKCdvcGFjaXR5Jyk7XG4gICAgY29lcmNlKCdmaWxsY29sb3InKTtcbiAgICBjb2VyY2UoJ2xpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcbiAgICBjb2VyY2UoJ2xpbmUuZGFzaCcpO1xuXG4gICAgdmFyIGRmbHRUeXBlID0gc2hhcGVJbi5wYXRoID8gJ3BhdGgnIDogJ3JlY3QnLFxuICAgICAgICBzaGFwZVR5cGUgPSBjb2VyY2UoJ3R5cGUnLCBkZmx0VHlwZSksXG4gICAgICAgIHhTaXplTW9kZSA9IGNvZXJjZSgneHNpemVtb2RlJyksXG4gICAgICAgIHlTaXplTW9kZSA9IGNvZXJjZSgneXNpemVtb2RlJyk7XG5cbiAgICAvLyBwb3NpdGlvbmluZ1xuICAgIHZhciBheExldHRlcnMgPSBbJ3gnLCAneSddO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhMZXR0ZXJzW2ldLFxuICAgICAgICAgICAgYXR0ckFuY2hvciA9IGF4TGV0dGVyICsgJ2FuY2hvcicsXG4gICAgICAgICAgICBzaXplTW9kZSA9IGF4TGV0dGVyID09PSAneCcgPyB4U2l6ZU1vZGUgOiB5U2l6ZU1vZGUsXG4gICAgICAgICAgICBnZE1vY2sgPSB7X2Z1bGxMYXlvdXQ6IGZ1bGxMYXlvdXR9LFxuICAgICAgICAgICAgYXgsXG4gICAgICAgICAgICBwb3MycixcbiAgICAgICAgICAgIHIycG9zO1xuXG4gICAgICAgIC8vIHhyZWYsIHlyZWZcbiAgICAgICAgdmFyIGF4UmVmID0gQXhlcy5jb2VyY2VSZWYoc2hhcGVJbiwgc2hhcGVPdXQsIGdkTW9jaywgYXhMZXR0ZXIsICcnLCAncGFwZXInKTtcblxuICAgICAgICBpZihheFJlZiAhPT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgYXggPSBBeGVzLmdldEZyb21JZChnZE1vY2ssIGF4UmVmKTtcbiAgICAgICAgICAgIGF4Ll9zaGFwZUluZGljZXMucHVzaChzaGFwZU91dC5faW5kZXgpO1xuICAgICAgICAgICAgcjJwb3MgPSBoZWxwZXJzLnJhbmdlVG9TaGFwZVBvc2l0aW9uKGF4KTtcbiAgICAgICAgICAgIHBvczJyID0gaGVscGVycy5zaGFwZVBvc2l0aW9uVG9SYW5nZShheCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBwb3MyciA9IHIycG9zID0gTGliLmlkZW50aXR5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29lcmNlIHgwLCB4MSwgeTAsIHkxXG4gICAgICAgIGlmKHNoYXBlVHlwZSAhPT0gJ3BhdGgnKSB7XG4gICAgICAgICAgICB2YXIgZGZsdDAgPSAwLjI1LFxuICAgICAgICAgICAgICAgIGRmbHQxID0gMC43NTtcblxuICAgICAgICAgICAgLy8gaGFjayB1bnRpbCBWMi4wIHdoZW4gbG9nIGhhcyByZWd1bGFyIHJhbmdlIGJlaGF2aW9yIC0gbWFrZSBpdCBsb29rIGxpa2Ugb3RoZXJcbiAgICAgICAgICAgIC8vIHJhbmdlcyB0byBzZW5kIHRvIGNvZXJjZSwgdGhlbiBwdXQgaXQgYmFjayBhZnRlclxuICAgICAgICAgICAgLy8gdGhpcyBpcyBhbGwgdG8gZ2l2ZSByZWFzb25hYmxlIGRlZmF1bHQgcG9zaXRpb24gYmVoYXZpb3Igb24gbG9nIGF4ZXMsIHdoaWNoIGlzXG4gICAgICAgICAgICAvLyBhIHByZXR0eSB1bmltcG9ydGFudCBlZGdlIGNhc2Ugc28gd2UgY291bGQganVzdCBpZ25vcmUgdGhpcy5cbiAgICAgICAgICAgIHZhciBhdHRyMCA9IGF4TGV0dGVyICsgJzAnLFxuICAgICAgICAgICAgICAgIGF0dHIxID0gYXhMZXR0ZXIgKyAnMScsXG4gICAgICAgICAgICAgICAgaW4wID0gc2hhcGVJblthdHRyMF0sXG4gICAgICAgICAgICAgICAgaW4xID0gc2hhcGVJblthdHRyMV07XG4gICAgICAgICAgICBzaGFwZUluW2F0dHIwXSA9IHBvczJyKHNoYXBlSW5bYXR0cjBdLCB0cnVlKTtcbiAgICAgICAgICAgIHNoYXBlSW5bYXR0cjFdID0gcG9zMnIoc2hhcGVJblthdHRyMV0sIHRydWUpO1xuXG4gICAgICAgICAgICBpZihzaXplTW9kZSA9PT0gJ3BpeGVsJykge1xuICAgICAgICAgICAgICAgIGNvZXJjZShhdHRyMCwgMCk7XG4gICAgICAgICAgICAgICAgY29lcmNlKGF0dHIxLCAxMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIEF4ZXMuY29lcmNlUG9zaXRpb24oc2hhcGVPdXQsIGdkTW9jaywgY29lcmNlLCBheFJlZiwgYXR0cjAsIGRmbHQwKTtcbiAgICAgICAgICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKHNoYXBlT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF0dHIxLCBkZmx0MSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGhhY2sgcGFydCAyXG4gICAgICAgICAgICBzaGFwZU91dFthdHRyMF0gPSByMnBvcyhzaGFwZU91dFthdHRyMF0pO1xuICAgICAgICAgICAgc2hhcGVPdXRbYXR0cjFdID0gcjJwb3Moc2hhcGVPdXRbYXR0cjFdKTtcbiAgICAgICAgICAgIHNoYXBlSW5bYXR0cjBdID0gaW4wO1xuICAgICAgICAgICAgc2hhcGVJblthdHRyMV0gPSBpbjE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb2VyY2UgeGFuY2hvciBhbmQgeWFuY2hvclxuICAgICAgICBpZihzaXplTW9kZSA9PT0gJ3BpeGVsJykge1xuICAgICAgICAgICAgLy8gSGFjayBmb3IgbG9nIGF4aXMgZGVzY3JpYmVkIGFib3ZlXG4gICAgICAgICAgICB2YXIgaW5BbmNob3IgPSBzaGFwZUluW2F0dHJBbmNob3JdO1xuICAgICAgICAgICAgc2hhcGVJblthdHRyQW5jaG9yXSA9IHBvczJyKHNoYXBlSW5bYXR0ckFuY2hvcl0sIHRydWUpO1xuXG4gICAgICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKHNoYXBlT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF0dHJBbmNob3IsIDAuMjUpO1xuXG4gICAgICAgICAgICAvLyBIYWNrIHBhcnQgMlxuICAgICAgICAgICAgc2hhcGVPdXRbYXR0ckFuY2hvcl0gPSByMnBvcyhzaGFwZU91dFthdHRyQW5jaG9yXSk7XG4gICAgICAgICAgICBzaGFwZUluW2F0dHJBbmNob3JdID0gaW5BbmNob3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzaGFwZVR5cGUgPT09ICdwYXRoJykge1xuICAgICAgICBjb2VyY2UoJ3BhdGgnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIExpYi5ub25lT3JBbGwoc2hhcGVJbiwgc2hhcGVPdXQsIFsneDAnLCAneDEnLCAneTAnLCAneTEnXSk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi9kcmF3aW5nJyk7XG52YXIgYXJyYXlFZGl0b3IgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykuYXJyYXlFZGl0b3I7XG5cbnZhciBkcmFnRWxlbWVudCA9IHJlcXVpcmUoJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgc2V0Q3Vyc29yID0gcmVxdWlyZSgnLi4vLi4vbGliL3NldGN1cnNvcicpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cblxuLy8gU2hhcGVzIGFyZSBzdG9yZWQgaW4gZ2QubGF5b3V0LnNoYXBlcywgYW4gYXJyYXkgb2Ygb2JqZWN0c1xuLy8gaW5kZXggY2FuIHBvaW50IHRvIG9uZSBpdGVtIGluIHRoaXMgYXJyYXksXG4vLyAgb3Igbm9uLW51bWVyaWMgdG8gc2ltcGx5IGFkZCBhIG5ldyBvbmVcbi8vICBvciAtMSB0byBtb2RpZnkgYWxsIGV4aXN0aW5nXG4vLyBvcHQgY2FuIGJlIHRoZSBmdWxsIG9wdGlvbnMgb2JqZWN0LCBvciBvbmUga2V5ICh0byBiZSBzZXQgdG8gdmFsdWUpXG4vLyAgb3IgdW5kZWZpbmVkIHRvIHNpbXBseSByZWRyYXdcbi8vIGlmIG9wdCBpcyBibGFuaywgdmFsIGNhbiBiZSAnYWRkJyBvciBhIGZ1bGwgb3B0aW9ucyBvYmplY3QgdG8gYWRkIGEgbmV3XG4vLyAgYW5ub3RhdGlvbiBhdCB0aGF0IHBvaW50IGluIHRoZSBhcnJheSwgb3IgJ3JlbW92ZScgdG8gZGVsZXRlIHRoaXMgb25lXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGRyYXc6IGRyYXcsXG4gICAgZHJhd09uZTogZHJhd09uZVxufTtcblxuZnVuY3Rpb24gZHJhdyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICAvLyBSZW1vdmUgcHJldmlvdXMgc2hhcGVzIGJlZm9yZSBkcmF3aW5nIG5ldyBpbiBzaGFwZXMgaW4gZnVsbExheW91dC5zaGFwZXNcbiAgICBmdWxsTGF5b3V0Ll9zaGFwZVVwcGVyTGF5ZXIuc2VsZWN0QWxsKCdwYXRoJykucmVtb3ZlKCk7XG4gICAgZnVsbExheW91dC5fc2hhcGVMb3dlckxheWVyLnNlbGVjdEFsbCgncGF0aCcpLnJlbW92ZSgpO1xuXG4gICAgZm9yKHZhciBrIGluIGZ1bGxMYXlvdXQuX3Bsb3RzKSB7XG4gICAgICAgIHZhciBzaGFwZWxheWVyID0gZnVsbExheW91dC5fcGxvdHNba10uc2hhcGVsYXllcjtcbiAgICAgICAgaWYoc2hhcGVsYXllcikgc2hhcGVsYXllci5zZWxlY3RBbGwoJ3BhdGgnKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbExheW91dC5zaGFwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZnVsbExheW91dC5zaGFwZXNbaV0udmlzaWJsZSkge1xuICAgICAgICAgICAgZHJhd09uZShnZCwgaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtYXkgbmVlZCB0byByZXN1cnJlY3QgdGhpcyBpZiB3ZSBwdXQgdGV4dCAoTGFUZVgpIGluIHNoYXBlc1xuICAgIC8vIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbn1cblxuZnVuY3Rpb24gZHJhd09uZShnZCwgaW5kZXgpIHtcbiAgICAvLyByZW1vdmUgdGhlIGV4aXN0aW5nIHNoYXBlIGlmIHRoZXJlIGlzIG9uZS5cbiAgICAvLyBiZWNhdXNlIGluZGljZXMgY2FuIGNoYW5nZSwgd2UgbmVlZCB0byBsb29rIGluIGFsbCBzaGFwZSBsYXllcnNcbiAgICBnZC5fZnVsbExheW91dC5fcGFwZXJkaXZcbiAgICAgICAgLnNlbGVjdEFsbCgnLnNoYXBlbGF5ZXIgW2RhdGEtaW5kZXg9XCInICsgaW5kZXggKyAnXCJdJylcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBnZC5fZnVsbExheW91dC5zaGFwZXNbaW5kZXhdIHx8IHt9O1xuXG4gICAgLy8gdGhpcyBzaGFwZSBpcyBnb25lIC0gcXVpdCBub3cgYWZ0ZXIgZGVsZXRpbmcgaXRcbiAgICAvLyBUT0RPOiB1c2UgZDMgaWRpb21zIGluc3RlYWQgb2YgZGVsZXRpbmcgYW5kIHJlZHJhd2luZyBldmVyeSB0aW1lXG4gICAgaWYoIW9wdGlvbnMuX2lucHV0IHx8IG9wdGlvbnMudmlzaWJsZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIGlmKG9wdGlvbnMubGF5ZXIgIT09ICdiZWxvdycpIHtcbiAgICAgICAgZHJhd1NoYXBlKGdkLl9mdWxsTGF5b3V0Ll9zaGFwZVVwcGVyTGF5ZXIpO1xuICAgIH1cbiAgICBlbHNlIGlmKG9wdGlvbnMueHJlZiA9PT0gJ3BhcGVyJyB8fCBvcHRpb25zLnlyZWYgPT09ICdwYXBlcicpIHtcbiAgICAgICAgZHJhd1NoYXBlKGdkLl9mdWxsTGF5b3V0Ll9zaGFwZUxvd2VyTGF5ZXIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHBsb3RpbmZvID0gZ2QuX2Z1bGxMYXlvdXQuX3Bsb3RzW29wdGlvbnMueHJlZiArIG9wdGlvbnMueXJlZl07XG4gICAgICAgIGlmKHBsb3RpbmZvKSB7XG4gICAgICAgICAgICB2YXIgbWFpblBsb3QgPSBwbG90aW5mby5tYWlucGxvdGluZm8gfHwgcGxvdGluZm87XG4gICAgICAgICAgICBkcmF3U2hhcGUobWFpblBsb3Quc2hhcGVsYXllcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBGYWxsIGJhY2sgdG8gX3NoYXBlTG93ZXJMYXllciBpbiBjYXNlIHRoZSByZXF1ZXN0ZWQgc3VicGxvdCBkb2Vzbid0IGV4aXN0LlxuICAgICAgICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIHlvdSByZWZlcmVuY2UgdGhlIHNoYXBlIHRvIGFuIHggLyB5IGF4aXMgY29tYmluYXRpb25cbiAgICAgICAgICAgIC8vIHRoYXQgZG9lc24ndCBoYXZlIGFueSBkYXRhIG9uIGl0IChhbmQgbGF5ZXIgaXMgYmVsb3cpXG4gICAgICAgICAgICBkcmF3U2hhcGUoZ2QuX2Z1bGxMYXlvdXQuX3NoYXBlTG93ZXJMYXllcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3U2hhcGUoc2hhcGVMYXllcikge1xuICAgICAgICB2YXIgYXR0cnMgPSB7XG4gICAgICAgICAgICAgICAgJ2RhdGEtaW5kZXgnOiBpbmRleCxcbiAgICAgICAgICAgICAgICAnZmlsbC1ydWxlJzogJ2V2ZW5vZGQnLFxuICAgICAgICAgICAgICAgIGQ6IGdldFBhdGhTdHJpbmcoZ2QsIG9wdGlvbnMpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGluZUNvbG9yID0gb3B0aW9ucy5saW5lLndpZHRoID9cbiAgICAgICAgICAgICAgICBvcHRpb25zLmxpbmUuY29sb3IgOiAncmdiYSgwLDAsMCwwKSc7XG5cbiAgICAgICAgdmFyIHBhdGggPSBzaGFwZUxheWVyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuYXR0cihhdHRycylcbiAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSlcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZUNvbG9yKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgb3B0aW9ucy5maWxsY29sb3IpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCBvcHRpb25zLmxpbmUuZGFzaCwgb3B0aW9ucy5saW5lLndpZHRoKTtcblxuICAgICAgICBzZXRDbGlwUGF0aChwYXRoLCBnZCwgb3B0aW9ucyk7XG5cbiAgICAgICAgaWYoZ2QuX2NvbnRleHQuZWRpdHMuc2hhcGVQb3NpdGlvbikgc2V0dXBEcmFnRWxlbWVudChnZCwgcGF0aCwgb3B0aW9ucywgaW5kZXgsIHNoYXBlTGF5ZXIpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0Q2xpcFBhdGgoc2hhcGVQYXRoLCBnZCwgc2hhcGVPcHRpb25zKSB7XG4gICAgLy8gbm90ZSB0aGF0IGZvciBsYXllcj1cImJlbG93XCIgdGhlIGNsaXBBeGVzIGNhbiBiZSBkaWZmZXJlbnQgZnJvbSB0aGVcbiAgICAvLyBzdWJwbG90IHdlJ3JlIGRyYXdpbmcgdGhpcyBpbi4gVGhpcyBjb3VsZCBjYXVzZSBwcm9ibGVtcyBpZiB0aGUgc2hhcGVcbiAgICAvLyBzcGFucyB0d28gc3VicGxvdHMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTQ1MlxuICAgIHZhciBjbGlwQXhlcyA9IChzaGFwZU9wdGlvbnMueHJlZiArIHNoYXBlT3B0aW9ucy55cmVmKS5yZXBsYWNlKC9wYXBlci9nLCAnJyk7XG5cbiAgICBzaGFwZVBhdGguY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGNsaXBBeGVzID9cbiAgICAgICgnY2xpcCcgKyBnZC5fZnVsbExheW91dC5fdWlkICsgY2xpcEF4ZXMpIDpcbiAgICAgIG51bGxcbiAgICApO1xufVxuXG5mdW5jdGlvbiBzZXR1cERyYWdFbGVtZW50KGdkLCBzaGFwZVBhdGgsIHNoYXBlT3B0aW9ucywgaW5kZXgsIHNoYXBlTGF5ZXIpIHtcbiAgICB2YXIgTUlOV0lEVEggPSAxMDtcbiAgICB2YXIgTUlOSEVJR0hUID0gMTA7XG5cbiAgICB2YXIgeFBpeGVsU2l6ZWQgPSBzaGFwZU9wdGlvbnMueHNpemVtb2RlID09PSAncGl4ZWwnO1xuICAgIHZhciB5UGl4ZWxTaXplZCA9IHNoYXBlT3B0aW9ucy55c2l6ZW1vZGUgPT09ICdwaXhlbCc7XG4gICAgdmFyIGlzTGluZSA9IHNoYXBlT3B0aW9ucy50eXBlID09PSAnbGluZSc7XG4gICAgdmFyIGlzUGF0aCA9IHNoYXBlT3B0aW9ucy50eXBlID09PSAncGF0aCc7XG5cbiAgICB2YXIgZWRpdEhlbHBlcnMgPSBhcnJheUVkaXRvcihnZC5sYXlvdXQsICdzaGFwZXMnLCBzaGFwZU9wdGlvbnMpO1xuICAgIHZhciBtb2RpZnlJdGVtID0gZWRpdEhlbHBlcnMubW9kaWZ5SXRlbTtcblxuICAgIHZhciB4MCwgeTAsIHgxLCB5MSwgeEFuY2hvciwgeUFuY2hvcjtcbiAgICB2YXIgbjAsIHMwLCB3MCwgZTAsIG9wdE4sIG9wdFMsIG9wdFcsIG9wdEU7XG4gICAgdmFyIHBhdGhJbjtcblxuICAgIC8vIHNldHVwIGNvbnZlcnNpb24gZnVuY3Rpb25zXG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHNoYXBlT3B0aW9ucy54cmVmKSxcbiAgICAgICAgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgc2hhcGVPcHRpb25zLnlyZWYpLFxuICAgICAgICB4MnAgPSBoZWxwZXJzLmdldERhdGFUb1BpeGVsKGdkLCB4YSksXG4gICAgICAgIHkycCA9IGhlbHBlcnMuZ2V0RGF0YVRvUGl4ZWwoZ2QsIHlhLCB0cnVlKSxcbiAgICAgICAgcDJ4ID0gaGVscGVycy5nZXRQaXhlbFRvRGF0YShnZCwgeGEpLFxuICAgICAgICBwMnkgPSBoZWxwZXJzLmdldFBpeGVsVG9EYXRhKGdkLCB5YSwgdHJ1ZSk7XG5cbiAgICB2YXIgc2Vuc29yeUVsZW1lbnQgPSBvYnRhaW5TZW5zb3J5RWxlbWVudCgpO1xuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGVsZW1lbnQ6IHNlbnNvcnlFbGVtZW50Lm5vZGUoKSxcbiAgICAgICAgICAgIGdkOiBnZCxcbiAgICAgICAgICAgIHByZXBGbjogc3RhcnREcmFnLFxuICAgICAgICAgICAgZG9uZUZuOiBlbmREcmFnLFxuICAgICAgICAgICAgY2xpY2tGbjogYWJvcnREcmFnXG4gICAgICAgIH0sXG4gICAgICAgIGRyYWdNb2RlO1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG5cbiAgICBzZW5zb3J5RWxlbWVudC5ub2RlKCkub25tb3VzZW1vdmUgPSB1cGRhdGVEcmFnTW9kZTtcblxuICAgIGZ1bmN0aW9uIG9idGFpblNlbnNvcnlFbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gaXNMaW5lID8gY3JlYXRlTGluZURyYWdIYW5kbGVzKCkgOiBzaGFwZVBhdGg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlTGluZURyYWdIYW5kbGVzKCkge1xuICAgICAgICB2YXIgbWluU2Vuc29yeVdpZHRoID0gMTAsXG4gICAgICAgICAgICBzZW5zb3J5V2lkdGggPSBNYXRoLm1heChzaGFwZU9wdGlvbnMubGluZS53aWR0aCwgbWluU2Vuc29yeVdpZHRoKTtcblxuICAgICAgICAvLyBIZWxwZXIgc2hhcGVzIGdyb3VwXG4gICAgICAgIC8vIE5vdGUgdGhhdCBieSBzZXR0aW5nIHRoZSBgZGF0YS1pbmRleGAgYXR0ciwgaXQgaXMgZW5zdXJlZCB0aGF0XG4gICAgICAgIC8vIHRoZSBoZWxwZXIgZ3JvdXAgaXMgcHVyZ2VkIGluIHRoaXMgbW9kdWxlcyBgZHJhd2AgZnVuY3Rpb25cbiAgICAgICAgdmFyIGcgPSBzaGFwZUxheWVyLmFwcGVuZCgnZycpXG4gICAgICAgICAgLmF0dHIoJ2RhdGEtaW5kZXgnLCBpbmRleCk7XG5cbiAgICAgICAgLy8gSGVscGVyIHBhdGggZm9yIG1vdmluZ1xuICAgICAgICBnLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgLmF0dHIoJ2QnLCBzaGFwZVBhdGguYXR0cignZCcpKVxuICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICdjdXJzb3InOiAnbW92ZScsXG4gICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBzZW5zb3J5V2lkdGgsXG4gICAgICAgICAgICAgICdzdHJva2Utb3BhY2l0eSc6ICcwJyAvLyBlbnN1cmUgbm90IHZpc2libGVcbiAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBIZWxwZXIgY2lyY2xlcyBmb3IgcmVzaXppbmdcbiAgICAgICAgdmFyIGNpcmNsZVN0eWxlID0ge1xuICAgICAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6ICcwJyAvLyBlbnN1cmUgbm90IHZpc2libGVcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNpcmNsZVJhZGl1cyA9IHNlbnNvcnlXaWR0aCAvIDIgPiBtaW5TZW5zb3J5V2lkdGggPyBzZW5zb3J5V2lkdGggLyAyIDogbWluU2Vuc29yeVdpZHRoO1xuXG4gICAgICAgIGcuYXBwZW5kKCdjaXJjbGUnKVxuICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgJ2RhdGEtbGluZS1wb2ludCc6ICdzdGFydC1wb2ludCcsXG4gICAgICAgICAgICAgICdjeCc6IHhQaXhlbFNpemVkID8geDJwKHNoYXBlT3B0aW9ucy54YW5jaG9yKSArIHNoYXBlT3B0aW9ucy54MCA6IHgycChzaGFwZU9wdGlvbnMueDApLFxuICAgICAgICAgICAgICAnY3knOiB5UGl4ZWxTaXplZCA/IHkycChzaGFwZU9wdGlvbnMueWFuY2hvcikgLSBzaGFwZU9wdGlvbnMueTAgOiB5MnAoc2hhcGVPcHRpb25zLnkwKSxcbiAgICAgICAgICAgICAgJ3InOiBjaXJjbGVSYWRpdXNcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zdHlsZShjaXJjbGVTdHlsZSlcbiAgICAgICAgICAuY2xhc3NlZCgnY3Vyc29yLWdyYWInLCB0cnVlKTtcblxuICAgICAgICBnLmFwcGVuZCgnY2lyY2xlJylcbiAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICdkYXRhLWxpbmUtcG9pbnQnOiAnZW5kLXBvaW50JyxcbiAgICAgICAgICAgICAgJ2N4JzogeFBpeGVsU2l6ZWQgPyB4MnAoc2hhcGVPcHRpb25zLnhhbmNob3IpICsgc2hhcGVPcHRpb25zLngxIDogeDJwKHNoYXBlT3B0aW9ucy54MSksXG4gICAgICAgICAgICAgICdjeSc6IHlQaXhlbFNpemVkID8geTJwKHNoYXBlT3B0aW9ucy55YW5jaG9yKSAtIHNoYXBlT3B0aW9ucy55MSA6IHkycChzaGFwZU9wdGlvbnMueTEpLFxuICAgICAgICAgICAgICAncic6IGNpcmNsZVJhZGl1c1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnN0eWxlKGNpcmNsZVN0eWxlKVxuICAgICAgICAgIC5jbGFzc2VkKCdjdXJzb3ItZ3JhYicsIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZURyYWdNb2RlKGV2dCkge1xuICAgICAgICBpZihpc0xpbmUpIHtcbiAgICAgICAgICAgIGlmKGV2dC50YXJnZXQudGFnTmFtZSA9PT0gJ3BhdGgnKSB7XG4gICAgICAgICAgICAgICAgZHJhZ01vZGUgPSAnbW92ZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRyYWdNb2RlID0gZXZ0LnRhcmdldC5hdHRyaWJ1dGVzWydkYXRhLWxpbmUtcG9pbnQnXS52YWx1ZSA9PT0gJ3N0YXJ0LXBvaW50JyA/XG4gICAgICAgICAgICAgICAgICAncmVzaXplLW92ZXItc3RhcnQtcG9pbnQnIDogJ3Jlc2l6ZS1vdmVyLWVuZC1wb2ludCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBlbGVtZW50IG1pZ2h0IG5vdCBiZSBvbiBzY3JlZW4gYXQgdGltZSBvZiBzZXR1cCxcbiAgICAgICAgICAgIC8vIHNvIG9idGFpbiBib3VuZGluZyBib3ggaGVyZVxuICAgICAgICAgICAgdmFyIGRyYWdCQm94ID0gZHJhZ09wdGlvbnMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgLy8gY2hvb3NlICdtb3ZlJyBvciAncmVzaXplJ1xuICAgICAgICAgICAgLy8gYmFzZWQgb24gaW5pdGlhbCBwb3NpdGlvbiBvZiBjdXJzb3Igd2l0aGluIHRoZSBkcmFnIGVsZW1lbnRcbiAgICAgICAgICAgIHZhciB3ID0gZHJhZ0JCb3gucmlnaHQgLSBkcmFnQkJveC5sZWZ0LFxuICAgICAgICAgICAgICAgIGggPSBkcmFnQkJveC5ib3R0b20gLSBkcmFnQkJveC50b3AsXG4gICAgICAgICAgICAgICAgeCA9IGV2dC5jbGllbnRYIC0gZHJhZ0JCb3gubGVmdCxcbiAgICAgICAgICAgICAgICB5ID0gZXZ0LmNsaWVudFkgLSBkcmFnQkJveC50b3AsXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gKCFpc1BhdGggJiYgdyA+IE1JTldJRFRIICYmIGggPiBNSU5IRUlHSFQgJiYgIWV2dC5zaGlmdEtleSkgP1xuICAgICAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC5nZXRDdXJzb3IoeCAvIHcsIDEgLSB5IC8gaCkgOlxuICAgICAgICAgICAgICAgICAgICAnbW92ZSc7XG5cbiAgICAgICAgICAgIHNldEN1cnNvcihzaGFwZVBhdGgsIGN1cnNvcik7XG5cbiAgICAgICAgICAgIC8vIHBvc3NpYmxlIHZhbHVlcyAnbW92ZScsICdzdycsICd3JywgJ3NlJywgJ2UnLCAnbmUnLCAnbicsICdudycgYW5kICd3J1xuICAgICAgICAgICAgZHJhZ01vZGUgPSBjdXJzb3Iuc3BsaXQoJy0nKVswXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0YXJ0RHJhZyhldnQpIHtcbiAgICAgICAgLy8gc2V0dXAgdXBkYXRlIHN0cmluZ3MgYW5kIGluaXRpYWwgdmFsdWVzXG4gICAgICAgIGlmKHhQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICB4QW5jaG9yID0geDJwKHNoYXBlT3B0aW9ucy54YW5jaG9yKTtcbiAgICAgICAgfVxuICAgICAgICBpZih5UGl4ZWxTaXplZCkge1xuICAgICAgICAgICAgeUFuY2hvciA9IHkycChzaGFwZU9wdGlvbnMueWFuY2hvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihzaGFwZU9wdGlvbnMudHlwZSA9PT0gJ3BhdGgnKSB7XG4gICAgICAgICAgICBwYXRoSW4gPSBzaGFwZU9wdGlvbnMucGF0aDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHgwID0geFBpeGVsU2l6ZWQgPyBzaGFwZU9wdGlvbnMueDAgOiB4MnAoc2hhcGVPcHRpb25zLngwKTtcbiAgICAgICAgICAgIHkwID0geVBpeGVsU2l6ZWQgPyBzaGFwZU9wdGlvbnMueTAgOiB5MnAoc2hhcGVPcHRpb25zLnkwKTtcbiAgICAgICAgICAgIHgxID0geFBpeGVsU2l6ZWQgPyBzaGFwZU9wdGlvbnMueDEgOiB4MnAoc2hhcGVPcHRpb25zLngxKTtcbiAgICAgICAgICAgIHkxID0geVBpeGVsU2l6ZWQgPyBzaGFwZU9wdGlvbnMueTEgOiB5MnAoc2hhcGVPcHRpb25zLnkxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHgwIDwgeDEpIHtcbiAgICAgICAgICAgIHcwID0geDA7XG4gICAgICAgICAgICBvcHRXID0gJ3gwJztcbiAgICAgICAgICAgIGUwID0geDE7XG4gICAgICAgICAgICBvcHRFID0gJ3gxJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHcwID0geDE7XG4gICAgICAgICAgICBvcHRXID0gJ3gxJztcbiAgICAgICAgICAgIGUwID0geDA7XG4gICAgICAgICAgICBvcHRFID0gJ3gwJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvciBmaXhlZCBzaXplIHNoYXBlcyB0YWtlIG9wcG9zaW5nIGRpcmVjdGlvbiBvZiB5LWF4aXMgaW50byBhY2NvdW50LlxuICAgICAgICAvLyBIaW50OiBGb3IgZGF0YSBzaXplZCBzaGFwZXMgdGhpcyBpcyBkb25lIGJ5IHRoZSB5MnAgZnVuY3Rpb24uXG4gICAgICAgIGlmKCgheVBpeGVsU2l6ZWQgJiYgeTAgPCB5MSkgfHwgKHlQaXhlbFNpemVkICYmIHkwID4geTEpKSB7XG4gICAgICAgICAgICBuMCA9IHkwO1xuICAgICAgICAgICAgb3B0TiA9ICd5MCc7XG4gICAgICAgICAgICBzMCA9IHkxO1xuICAgICAgICAgICAgb3B0UyA9ICd5MSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuMCA9IHkxO1xuICAgICAgICAgICAgb3B0TiA9ICd5MSc7XG4gICAgICAgICAgICBzMCA9IHkwO1xuICAgICAgICAgICAgb3B0UyA9ICd5MCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzZXR1cCBkcmFnTW9kZSBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgaGFuZGxlclxuICAgICAgICB1cGRhdGVEcmFnTW9kZShldnQpO1xuICAgICAgICByZW5kZXJWaXN1YWxDdWVzKHNoYXBlTGF5ZXIsIHNoYXBlT3B0aW9ucyk7XG4gICAgICAgIGRlYWN0aXZhdGVDbGlwUGF0aFRlbXBvcmFyaWx5KHNoYXBlUGF0aCwgc2hhcGVPcHRpb25zLCBnZCk7XG4gICAgICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IChkcmFnTW9kZSA9PT0gJ21vdmUnKSA/IG1vdmVTaGFwZSA6IHJlc2l6ZVNoYXBlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgICAgIHNldEN1cnNvcihzaGFwZVBhdGgpO1xuICAgICAgICByZW1vdmVWaXN1YWxDdWVzKHNoYXBlTGF5ZXIpO1xuXG4gICAgICAgIC8vIERvbid0IHJlbHkgb24gY2xpcFBhdGggYmVpbmcgYWN0aXZhdGVkIGR1cmluZyByZS1sYXlvdXRcbiAgICAgICAgc2V0Q2xpcFBhdGgoc2hhcGVQYXRoLCBnZCwgc2hhcGVPcHRpb25zKTtcbiAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgZWRpdEhlbHBlcnMuZ2V0VXBkYXRlT2JqKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFib3J0RHJhZygpIHtcbiAgICAgICAgcmVtb3ZlVmlzdWFsQ3VlcyhzaGFwZUxheWVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3ZlU2hhcGUoZHgsIGR5KSB7XG4gICAgICAgIGlmKHNoYXBlT3B0aW9ucy50eXBlID09PSAncGF0aCcpIHtcbiAgICAgICAgICAgIHZhciBub09wID0gZnVuY3Rpb24oY29vcmQpIHsgcmV0dXJuIGNvb3JkOyB9LFxuICAgICAgICAgICAgICAgIG1vdmVYID0gbm9PcCxcbiAgICAgICAgICAgICAgICBtb3ZlWSA9IG5vT3A7XG5cbiAgICAgICAgICAgIGlmKHhQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneGFuY2hvcicsIHNoYXBlT3B0aW9ucy54YW5jaG9yID0gcDJ4KHhBbmNob3IgKyBkeCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb3ZlWCA9IGZ1bmN0aW9uIG1vdmVYKHgpIHsgcmV0dXJuIHAyeCh4MnAoeCkgKyBkeCk7IH07XG4gICAgICAgICAgICAgICAgaWYoeGEgJiYgeGEudHlwZSA9PT0gJ2RhdGUnKSBtb3ZlWCA9IGhlbHBlcnMuZW5jb2RlRGF0ZShtb3ZlWCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHlQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneWFuY2hvcicsIHNoYXBlT3B0aW9ucy55YW5jaG9yID0gcDJ5KHlBbmNob3IgKyBkeSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb3ZlWSA9IGZ1bmN0aW9uIG1vdmVZKHkpIHsgcmV0dXJuIHAyeSh5MnAoeSkgKyBkeSk7IH07XG4gICAgICAgICAgICAgICAgaWYoeWEgJiYgeWEudHlwZSA9PT0gJ2RhdGUnKSBtb3ZlWSA9IGhlbHBlcnMuZW5jb2RlRGF0ZShtb3ZlWSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3BhdGgnLCBzaGFwZU9wdGlvbnMucGF0aCA9IG1vdmVQYXRoKHBhdGhJbiwgbW92ZVgsIG1vdmVZKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZih4UGl4ZWxTaXplZCkge1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3hhbmNob3InLCBzaGFwZU9wdGlvbnMueGFuY2hvciA9IHAyeCh4QW5jaG9yICsgZHgpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneDAnLCBzaGFwZU9wdGlvbnMueDAgPSBwMngoeDAgKyBkeCkpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3gxJywgc2hhcGVPcHRpb25zLngxID0gcDJ4KHgxICsgZHgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoeVBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5YW5jaG9yJywgc2hhcGVPcHRpb25zLnlhbmNob3IgPSBwMnkoeUFuY2hvciArIGR5KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3kwJywgc2hhcGVPcHRpb25zLnkwID0gcDJ5KHkwICsgZHkpKTtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5MScsIHNoYXBlT3B0aW9ucy55MSA9IHAyeSh5MSArIGR5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzaGFwZVBhdGguYXR0cignZCcsIGdldFBhdGhTdHJpbmcoZ2QsIHNoYXBlT3B0aW9ucykpO1xuICAgICAgICByZW5kZXJWaXN1YWxDdWVzKHNoYXBlTGF5ZXIsIHNoYXBlT3B0aW9ucyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzaXplU2hhcGUoZHgsIGR5KSB7XG4gICAgICAgIGlmKGlzUGF0aCkge1xuICAgICAgICAgICAgLy8gVE9ETzogaW1wbGVtZW50IHBhdGggcmVzaXplLCBkb24ndCBmb3JnZXQgdG8gdXBkYXRlIGRyYWdNb2RlIGNvZGVcbiAgICAgICAgICAgIHZhciBub09wID0gZnVuY3Rpb24oY29vcmQpIHsgcmV0dXJuIGNvb3JkOyB9LFxuICAgICAgICAgICAgICAgIG1vdmVYID0gbm9PcCxcbiAgICAgICAgICAgICAgICBtb3ZlWSA9IG5vT3A7XG5cbiAgICAgICAgICAgIGlmKHhQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneGFuY2hvcicsIHNoYXBlT3B0aW9ucy54YW5jaG9yID0gcDJ4KHhBbmNob3IgKyBkeCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb3ZlWCA9IGZ1bmN0aW9uIG1vdmVYKHgpIHsgcmV0dXJuIHAyeCh4MnAoeCkgKyBkeCk7IH07XG4gICAgICAgICAgICAgICAgaWYoeGEgJiYgeGEudHlwZSA9PT0gJ2RhdGUnKSBtb3ZlWCA9IGhlbHBlcnMuZW5jb2RlRGF0ZShtb3ZlWCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHlQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneWFuY2hvcicsIHNoYXBlT3B0aW9ucy55YW5jaG9yID0gcDJ5KHlBbmNob3IgKyBkeSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb3ZlWSA9IGZ1bmN0aW9uIG1vdmVZKHkpIHsgcmV0dXJuIHAyeSh5MnAoeSkgKyBkeSk7IH07XG4gICAgICAgICAgICAgICAgaWYoeWEgJiYgeWEudHlwZSA9PT0gJ2RhdGUnKSBtb3ZlWSA9IGhlbHBlcnMuZW5jb2RlRGF0ZShtb3ZlWSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3BhdGgnLCBzaGFwZU9wdGlvbnMucGF0aCA9IG1vdmVQYXRoKHBhdGhJbiwgbW92ZVgsIG1vdmVZKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihpc0xpbmUpIHtcbiAgICAgICAgICAgIGlmKGRyYWdNb2RlID09PSAncmVzaXplLW92ZXItc3RhcnQtcG9pbnQnKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1gwID0geDAgKyBkeDtcbiAgICAgICAgICAgICAgICB2YXIgbmV3WTAgPSB5UGl4ZWxTaXplZCA/IHkwIC0gZHkgOiB5MCArIGR5O1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3gwJywgc2hhcGVPcHRpb25zLngwID0geFBpeGVsU2l6ZWQgPyBuZXdYMCA6IHAyeChuZXdYMCkpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3kwJywgc2hhcGVPcHRpb25zLnkwID0geVBpeGVsU2l6ZWQgPyBuZXdZMCA6IHAyeShuZXdZMCkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGRyYWdNb2RlID09PSAncmVzaXplLW92ZXItZW5kLXBvaW50Jykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdYMSA9IHgxICsgZHg7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1kxID0geVBpeGVsU2l6ZWQgPyB5MSAtIGR5IDogeTEgKyBkeTtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4MScsIHNoYXBlT3B0aW9ucy54MSA9IHhQaXhlbFNpemVkID8gbmV3WDEgOiBwMngobmV3WDEpKTtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5MScsIHNoYXBlT3B0aW9ucy55MSA9IHlQaXhlbFNpemVkID8gbmV3WTEgOiBwMnkobmV3WTEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBuZXdOID0gKH5kcmFnTW9kZS5pbmRleE9mKCduJykpID8gbjAgKyBkeSA6IG4wLFxuICAgICAgICAgICAgICAgIG5ld1MgPSAofmRyYWdNb2RlLmluZGV4T2YoJ3MnKSkgPyBzMCArIGR5IDogczAsXG4gICAgICAgICAgICAgICAgbmV3VyA9ICh+ZHJhZ01vZGUuaW5kZXhPZigndycpKSA/IHcwICsgZHggOiB3MCxcbiAgICAgICAgICAgICAgICBuZXdFID0gKH5kcmFnTW9kZS5pbmRleE9mKCdlJykpID8gZTAgKyBkeCA6IGUwO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGluZ3MgaW4gb3Bwb3NpbmcgZGlyZWN0aW9uIGZvciB5LWF4aXMuXG4gICAgICAgICAgICAvLyBIaW50OiBmb3IgZGF0YS1zaXplZCBzaGFwZXMgdGhlIHJldmVyc2FsIG9mIGF4aXMgZGlyZWN0aW9uIGlzIGRvbmUgaW4gcDJ5LlxuICAgICAgICAgICAgaWYofmRyYWdNb2RlLmluZGV4T2YoJ24nKSAmJiB5UGl4ZWxTaXplZCkgbmV3TiA9IG4wIC0gZHk7XG4gICAgICAgICAgICBpZih+ZHJhZ01vZGUuaW5kZXhPZigncycpICYmIHlQaXhlbFNpemVkKSBuZXdTID0gczAgLSBkeTtcblxuICAgICAgICAgICAgLy8gVXBkYXRlIHNoYXBlIGV2ZW50dWFsbHkuIEFnYWluLCBiZSBhd2FyZSBvZiB0aGVcbiAgICAgICAgICAgIC8vIG9wcG9zaW5nIGRpcmVjdGlvbiBvZiB0aGUgeS1heGlzIG9mIGZpeGVkIHNpemUgc2hhcGVzLlxuICAgICAgICAgICAgaWYoKCF5UGl4ZWxTaXplZCAmJiBuZXdTIC0gbmV3TiA+IE1JTkhFSUdIVCkgfHxcbiAgICAgICAgICAgICAgKHlQaXhlbFNpemVkICYmIG5ld04gLSBuZXdTID4gTUlOSEVJR0hUKSkge1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0ob3B0Tiwgc2hhcGVPcHRpb25zW29wdE5dID0geVBpeGVsU2l6ZWQgPyBuZXdOIDogcDJ5KG5ld04pKTtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKG9wdFMsIHNoYXBlT3B0aW9uc1tvcHRTXSA9IHlQaXhlbFNpemVkID8gbmV3UyA6IHAyeShuZXdTKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihuZXdFIC0gbmV3VyA+IE1JTldJRFRIKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbShvcHRXLCBzaGFwZU9wdGlvbnNbb3B0V10gPSB4UGl4ZWxTaXplZCA/IG5ld1cgOiBwMngobmV3VykpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0ob3B0RSwgc2hhcGVPcHRpb25zW29wdEVdID0geFBpeGVsU2l6ZWQgPyBuZXdFIDogcDJ4KG5ld0UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNoYXBlUGF0aC5hdHRyKCdkJywgZ2V0UGF0aFN0cmluZyhnZCwgc2hhcGVPcHRpb25zKSk7XG4gICAgICAgIHJlbmRlclZpc3VhbEN1ZXMoc2hhcGVMYXllciwgc2hhcGVPcHRpb25zKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW5kZXJWaXN1YWxDdWVzKHNoYXBlTGF5ZXIsIHNoYXBlT3B0aW9ucykge1xuICAgICAgICBpZih4UGl4ZWxTaXplZCB8fCB5UGl4ZWxTaXplZCkge1xuICAgICAgICAgICAgcmVuZGVyQW5jaG9yKCk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiByZW5kZXJBbmNob3IoKSB7XG4gICAgICAgICAgICB2YXIgaXNOb3RQYXRoID0gc2hhcGVPcHRpb25zLnR5cGUgIT09ICdwYXRoJztcblxuICAgICAgICAgICAgLy8gZDMgam9pbiB3aXRoIGR1bW15IGRhdGEgdG8gc2F0aXNmeSBkMyBkYXRhLWJpbmRpbmdcbiAgICAgICAgICAgIHZhciB2aXN1YWxDdWVzID0gc2hhcGVMYXllci5zZWxlY3RBbGwoJy52aXN1YWwtY3VlJykuZGF0YShbMF0pO1xuXG4gICAgICAgICAgICAvLyBFbnRlclxuICAgICAgICAgICAgdmFyIHN0cm9rZVdpZHRoID0gMTtcbiAgICAgICAgICAgIHZpc3VhbEN1ZXMuZW50ZXIoKVxuICAgICAgICAgICAgICAuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgJ2ZpbGwnOiAnI2ZmZicsXG4gICAgICAgICAgICAgICAgICAnZmlsbC1ydWxlJzogJ2V2ZW5vZGQnLFxuICAgICAgICAgICAgICAgICAgJ3N0cm9rZSc6ICcjMDAwJyxcbiAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBzdHJva2VXaWR0aFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2xhc3NlZCgndmlzdWFsLWN1ZScsIHRydWUpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGVcbiAgICAgICAgICAgIHZhciBwb3NYID0geDJwKFxuICAgICAgICAgICAgICB4UGl4ZWxTaXplZCA/XG4gICAgICAgICAgICAgICAgc2hhcGVPcHRpb25zLnhhbmNob3IgOlxuICAgICAgICAgICAgICAgIExpYi5taWRSYW5nZShcbiAgICAgICAgICAgICAgICAgIGlzTm90UGF0aCA/XG4gICAgICAgICAgICAgICAgICAgIFtzaGFwZU9wdGlvbnMueDAsIHNoYXBlT3B0aW9ucy54MV0gOlxuICAgICAgICAgICAgICAgICAgICBoZWxwZXJzLmV4dHJhY3RQYXRoQ29vcmRzKHNoYXBlT3B0aW9ucy5wYXRoLCBjb25zdGFudHMucGFyYW1Jc1gpKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHZhciBwb3NZID0geTJwKFxuICAgICAgICAgICAgICB5UGl4ZWxTaXplZCA/XG4gICAgICAgICAgICAgICAgc2hhcGVPcHRpb25zLnlhbmNob3IgOlxuICAgICAgICAgICAgICAgIExpYi5taWRSYW5nZShcbiAgICAgICAgICAgICAgICAgIGlzTm90UGF0aCA/XG4gICAgICAgICAgICAgICAgICAgIFtzaGFwZU9wdGlvbnMueTAsIHNoYXBlT3B0aW9ucy55MV0gOlxuICAgICAgICAgICAgICAgICAgICBoZWxwZXJzLmV4dHJhY3RQYXRoQ29vcmRzKHNoYXBlT3B0aW9ucy5wYXRoLCBjb25zdGFudHMucGFyYW1Jc1kpKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcG9zWCA9IGhlbHBlcnMucm91bmRQb3NpdGlvbkZvclNoYXJwU3Ryb2tlUmVuZGVyaW5nKHBvc1gsIHN0cm9rZVdpZHRoKTtcbiAgICAgICAgICAgIHBvc1kgPSBoZWxwZXJzLnJvdW5kUG9zaXRpb25Gb3JTaGFycFN0cm9rZVJlbmRlcmluZyhwb3NZLCBzdHJva2VXaWR0aCk7XG5cbiAgICAgICAgICAgIGlmKHhQaXhlbFNpemVkICYmIHlQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNyb3NzUGF0aCA9ICdNJyArIChwb3NYIC0gMSAtIHN0cm9rZVdpZHRoKSArICcsJyArIChwb3NZIC0gMSAtIHN0cm9rZVdpZHRoKSArXG4gICAgICAgICAgICAgICAgICAnaC04djJoOCB2OGgydi04IGg4di0yaC04IHYtOGgtMiBaJztcbiAgICAgICAgICAgICAgICB2aXN1YWxDdWVzLmF0dHIoJ2QnLCBjcm9zc1BhdGgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHhQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZCYXJQYXRoID0gJ00nICsgKHBvc1ggLSAxIC0gc3Ryb2tlV2lkdGgpICsgJywnICsgKHBvc1kgLSA5IC0gc3Ryb2tlV2lkdGgpICtcbiAgICAgICAgICAgICAgICAgICd2MTggaDIgdi0xOCBaJztcbiAgICAgICAgICAgICAgICB2aXN1YWxDdWVzLmF0dHIoJ2QnLCB2QmFyUGF0aCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBoQmFyUGF0aCA9ICdNJyArIChwb3NYIC0gOSAtIHN0cm9rZVdpZHRoKSArICcsJyArIChwb3NZIC0gMSAtIHN0cm9rZVdpZHRoKSArXG4gICAgICAgICAgICAgICAgICAnaDE4IHYyIGgtMTggWic7XG4gICAgICAgICAgICAgICAgdmlzdWFsQ3Vlcy5hdHRyKCdkJywgaEJhclBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlVmlzdWFsQ3VlcyhzaGFwZUxheWVyKSB7XG4gICAgICAgIHNoYXBlTGF5ZXIuc2VsZWN0QWxsKCcudmlzdWFsLWN1ZScpLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlYWN0aXZhdGVDbGlwUGF0aFRlbXBvcmFyaWx5KHNoYXBlUGF0aCwgc2hhcGVPcHRpb25zLCBnZCkge1xuICAgICAgICB2YXIgeHJlZiA9IHNoYXBlT3B0aW9ucy54cmVmLFxuICAgICAgICAgICAgeXJlZiA9IHNoYXBlT3B0aW9ucy55cmVmLFxuICAgICAgICAgICAgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgeHJlZiksXG4gICAgICAgICAgICB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB5cmVmKTtcblxuICAgICAgICB2YXIgY2xpcEF4ZXMgPSAnJztcbiAgICAgICAgaWYoeHJlZiAhPT0gJ3BhcGVyJyAmJiAheGEuYXV0b3JhbmdlKSBjbGlwQXhlcyArPSB4cmVmO1xuICAgICAgICBpZih5cmVmICE9PSAncGFwZXInICYmICF5YS5hdXRvcmFuZ2UpIGNsaXBBeGVzICs9IHlyZWY7XG5cbiAgICAgICAgc2hhcGVQYXRoLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBjbGlwQXhlcyA/XG4gICAgICAgICAgJ2NsaXAnICsgZ2QuX2Z1bGxMYXlvdXQuX3VpZCArIGNsaXBBeGVzIDpcbiAgICAgICAgICBudWxsXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRQYXRoU3RyaW5nKGdkLCBvcHRpb25zKSB7XG4gICAgdmFyIHR5cGUgPSBvcHRpb25zLnR5cGUsXG4gICAgICAgIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIG9wdGlvbnMueHJlZiksXG4gICAgICAgIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIG9wdGlvbnMueXJlZiksXG4gICAgICAgIGdzID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemUsXG4gICAgICAgIHgyciwgeDJwLCB5MnIsIHkycCxcbiAgICAgICAgeDAsIHgxLCB5MCwgeTE7XG5cbiAgICBpZih4YSkge1xuICAgICAgICB4MnIgPSBoZWxwZXJzLnNoYXBlUG9zaXRpb25Ub1JhbmdlKHhhKTtcbiAgICAgICAgeDJwID0gZnVuY3Rpb24odikgeyByZXR1cm4geGEuX29mZnNldCArIHhhLnIycCh4MnIodiwgdHJ1ZSkpOyB9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgeDJwID0gZnVuY3Rpb24odikgeyByZXR1cm4gZ3MubCArIGdzLncgKiB2OyB9O1xuICAgIH1cblxuICAgIGlmKHlhKSB7XG4gICAgICAgIHkyciA9IGhlbHBlcnMuc2hhcGVQb3NpdGlvblRvUmFuZ2UoeWEpO1xuICAgICAgICB5MnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiB5YS5fb2Zmc2V0ICsgeWEucjJwKHkycih2LCB0cnVlKSk7IH07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB5MnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBncy50ICsgZ3MuaCAqICgxIC0gdik7IH07XG4gICAgfVxuXG4gICAgaWYodHlwZSA9PT0gJ3BhdGgnKSB7XG4gICAgICAgIGlmKHhhICYmIHhhLnR5cGUgPT09ICdkYXRlJykgeDJwID0gaGVscGVycy5kZWNvZGVEYXRlKHgycCk7XG4gICAgICAgIGlmKHlhICYmIHlhLnR5cGUgPT09ICdkYXRlJykgeTJwID0gaGVscGVycy5kZWNvZGVEYXRlKHkycCk7XG4gICAgICAgIHJldHVybiBjb252ZXJ0UGF0aChvcHRpb25zLCB4MnAsIHkycCk7XG4gICAgfVxuXG4gICAgaWYob3B0aW9ucy54c2l6ZW1vZGUgPT09ICdwaXhlbCcpIHtcbiAgICAgICAgdmFyIHhBbmNob3JQb3MgPSB4MnAob3B0aW9ucy54YW5jaG9yKTtcbiAgICAgICAgeDAgPSB4QW5jaG9yUG9zICsgb3B0aW9ucy54MDtcbiAgICAgICAgeDEgPSB4QW5jaG9yUG9zICsgb3B0aW9ucy54MTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHgwID0geDJwKG9wdGlvbnMueDApO1xuICAgICAgICB4MSA9IHgycChvcHRpb25zLngxKTtcbiAgICB9XG5cbiAgICBpZihvcHRpb25zLnlzaXplbW9kZSA9PT0gJ3BpeGVsJykge1xuICAgICAgICB2YXIgeUFuY2hvclBvcyA9IHkycChvcHRpb25zLnlhbmNob3IpO1xuICAgICAgICB5MCA9IHlBbmNob3JQb3MgLSBvcHRpb25zLnkwO1xuICAgICAgICB5MSA9IHlBbmNob3JQb3MgLSBvcHRpb25zLnkxO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgeTAgPSB5MnAob3B0aW9ucy55MCk7XG4gICAgICAgIHkxID0geTJwKG9wdGlvbnMueTEpO1xuICAgIH1cblxuICAgIGlmKHR5cGUgPT09ICdsaW5lJykgcmV0dXJuICdNJyArIHgwICsgJywnICsgeTAgKyAnTCcgKyB4MSArICcsJyArIHkxO1xuICAgIGlmKHR5cGUgPT09ICdyZWN0JykgcmV0dXJuICdNJyArIHgwICsgJywnICsgeTAgKyAnSCcgKyB4MSArICdWJyArIHkxICsgJ0gnICsgeDAgKyAnWic7XG4gICAgLy8gY2lyY2xlXG4gICAgdmFyIGN4ID0gKHgwICsgeDEpIC8gMixcbiAgICAgICAgY3kgPSAoeTAgKyB5MSkgLyAyLFxuICAgICAgICByeCA9IE1hdGguYWJzKGN4IC0geDApLFxuICAgICAgICByeSA9IE1hdGguYWJzKGN5IC0geTApLFxuICAgICAgICByQXJjID0gJ0EnICsgcnggKyAnLCcgKyByeSxcbiAgICAgICAgcmlnaHRQdCA9IChjeCArIHJ4KSArICcsJyArIGN5LFxuICAgICAgICB0b3BQdCA9IGN4ICsgJywnICsgKGN5IC0gcnkpO1xuICAgIHJldHVybiAnTScgKyByaWdodFB0ICsgckFyYyArICcgMCAxLDEgJyArIHRvcFB0ICtcbiAgICAgICAgckFyYyArICcgMCAwLDEgJyArIHJpZ2h0UHQgKyAnWic7XG59XG5cblxuZnVuY3Rpb24gY29udmVydFBhdGgob3B0aW9ucywgeDJwLCB5MnApIHtcbiAgICB2YXIgcGF0aEluID0gb3B0aW9ucy5wYXRoLFxuICAgICAgICB4U2l6ZW1vZGUgPSBvcHRpb25zLnhzaXplbW9kZSxcbiAgICAgICAgeVNpemVtb2RlID0gb3B0aW9ucy55c2l6ZW1vZGUsXG4gICAgICAgIHhBbmNob3IgPSBvcHRpb25zLnhhbmNob3IsXG4gICAgICAgIHlBbmNob3IgPSBvcHRpb25zLnlhbmNob3I7XG5cblxuICAgIHJldHVybiBwYXRoSW4ucmVwbGFjZShjb25zdGFudHMuc2VnbWVudFJFLCBmdW5jdGlvbihzZWdtZW50KSB7XG4gICAgICAgIHZhciBwYXJhbU51bWJlciA9IDAsXG4gICAgICAgICAgICBzZWdtZW50VHlwZSA9IHNlZ21lbnQuY2hhckF0KDApLFxuICAgICAgICAgICAgeFBhcmFtcyA9IGNvbnN0YW50cy5wYXJhbUlzWFtzZWdtZW50VHlwZV0sXG4gICAgICAgICAgICB5UGFyYW1zID0gY29uc3RhbnRzLnBhcmFtSXNZW3NlZ21lbnRUeXBlXSxcbiAgICAgICAgICAgIG5QYXJhbXMgPSBjb25zdGFudHMubnVtUGFyYW1zW3NlZ21lbnRUeXBlXTtcblxuICAgICAgICB2YXIgcGFyYW1TdHJpbmcgPSBzZWdtZW50LnN1YnN0cigxKS5yZXBsYWNlKGNvbnN0YW50cy5wYXJhbVJFLCBmdW5jdGlvbihwYXJhbSkge1xuICAgICAgICAgICAgaWYoeFBhcmFtc1twYXJhbU51bWJlcl0pIHtcbiAgICAgICAgICAgICAgICBpZih4U2l6ZW1vZGUgPT09ICdwaXhlbCcpIHBhcmFtID0geDJwKHhBbmNob3IpICsgTnVtYmVyKHBhcmFtKTtcbiAgICAgICAgICAgICAgICBlbHNlIHBhcmFtID0geDJwKHBhcmFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoeVBhcmFtc1twYXJhbU51bWJlcl0pIHtcbiAgICAgICAgICAgICAgICBpZih5U2l6ZW1vZGUgPT09ICdwaXhlbCcpIHBhcmFtID0geTJwKHlBbmNob3IpIC0gTnVtYmVyKHBhcmFtKTtcbiAgICAgICAgICAgICAgICBlbHNlIHBhcmFtID0geTJwKHBhcmFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmFtTnVtYmVyKys7XG5cbiAgICAgICAgICAgIGlmKHBhcmFtTnVtYmVyID4gblBhcmFtcykgcGFyYW0gPSAnWCc7XG4gICAgICAgICAgICByZXR1cm4gcGFyYW07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKHBhcmFtTnVtYmVyID4gblBhcmFtcykge1xuICAgICAgICAgICAgcGFyYW1TdHJpbmcgPSBwYXJhbVN0cmluZy5yZXBsYWNlKC9bXFxzLF0qWC4qLywgJycpO1xuICAgICAgICAgICAgTGliLmxvZygnSWdub3JpbmcgZXh0cmEgcGFyYW1zIGluIHNlZ21lbnQgJyArIHNlZ21lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNlZ21lbnRUeXBlICsgcGFyYW1TdHJpbmc7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIG1vdmVQYXRoKHBhdGhJbiwgbW92ZVgsIG1vdmVZKSB7XG4gICAgcmV0dXJuIHBhdGhJbi5yZXBsYWNlKGNvbnN0YW50cy5zZWdtZW50UkUsIGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgICAgdmFyIHBhcmFtTnVtYmVyID0gMCxcbiAgICAgICAgICAgIHNlZ21lbnRUeXBlID0gc2VnbWVudC5jaGFyQXQoMCksXG4gICAgICAgICAgICB4UGFyYW1zID0gY29uc3RhbnRzLnBhcmFtSXNYW3NlZ21lbnRUeXBlXSxcbiAgICAgICAgICAgIHlQYXJhbXMgPSBjb25zdGFudHMucGFyYW1Jc1lbc2VnbWVudFR5cGVdLFxuICAgICAgICAgICAgblBhcmFtcyA9IGNvbnN0YW50cy5udW1QYXJhbXNbc2VnbWVudFR5cGVdO1xuXG4gICAgICAgIHZhciBwYXJhbVN0cmluZyA9IHNlZ21lbnQuc3Vic3RyKDEpLnJlcGxhY2UoY29uc3RhbnRzLnBhcmFtUkUsIGZ1bmN0aW9uKHBhcmFtKSB7XG4gICAgICAgICAgICBpZihwYXJhbU51bWJlciA+PSBuUGFyYW1zKSByZXR1cm4gcGFyYW07XG5cbiAgICAgICAgICAgIGlmKHhQYXJhbXNbcGFyYW1OdW1iZXJdKSBwYXJhbSA9IG1vdmVYKHBhcmFtKTtcbiAgICAgICAgICAgIGVsc2UgaWYoeVBhcmFtc1twYXJhbU51bWJlcl0pIHBhcmFtID0gbW92ZVkocGFyYW0pO1xuXG4gICAgICAgICAgICBwYXJhbU51bWJlcisrO1xuXG4gICAgICAgICAgICByZXR1cm4gcGFyYW07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzZWdtZW50VHlwZSArIHBhcmFtU3RyaW5nO1xuICAgIH0pO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbi8vIHNwZWNpYWwgcG9zaXRpb24gY29udmVyc2lvbiBmdW5jdGlvbnMuLi4gY2F0ZWdvcnkgYXhpcyBwb3NpdGlvbnMgY2FuJ3QgYmVcbi8vIHNwZWNpZmllZCBieSB0aGVpciBkYXRhIHZhbHVlcywgYmVjYXVzZSB0aGV5IGRvbid0IG1ha2UgYSBjb250aW51b3VzIG1hcHBpbmcuXG4vLyBzbyB0aGVzZSBoYXZlIHRvIGJlIHNwZWNpZmllZCBpbiB0ZXJtcyBvZiB0aGUgY2F0ZWdvcnkgc2VyaWFsIG51bWJlcnMsXG4vLyBidXQgY2FuIHRha2UgZnJhY3Rpb25hbCB2YWx1ZXMuIE90aGVyIGF4aXMgdHlwZXMgd2Ugc3BlY2lmeSBwb3NpdGlvbiBiYXNlZCBvblxuLy8gdGhlIGFjdHVhbCBkYXRhIHZhbHVlcy5cbi8vIFRPRE86IGluIFYyLjAgKHdoZW4gbG9nIGF4aXMgcmFuZ2VzIGFyZSBpbiBkYXRhIHVuaXRzKSByYW5nZSBhbmQgc2hhcGUgcG9zaXRpb25cbi8vIHdpbGwgYmUgaWRlbnRpY2FsLCBzbyByYW5nZVRvU2hhcGVQb3NpdGlvbiBhbmQgc2hhcGVQb3NpdGlvblRvUmFuZ2UgY2FuIGJlXG4vLyByZW1vdmVkIGVudGlyZWx5LlxuXG5leHBvcnRzLnJhbmdlVG9TaGFwZVBvc2l0aW9uID0gZnVuY3Rpb24oYXgpIHtcbiAgICByZXR1cm4gKGF4LnR5cGUgPT09ICdsb2cnKSA/IGF4LnIyZCA6IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHY7IH07XG59O1xuXG5leHBvcnRzLnNoYXBlUG9zaXRpb25Ub1JhbmdlID0gZnVuY3Rpb24oYXgpIHtcbiAgICByZXR1cm4gKGF4LnR5cGUgPT09ICdsb2cnKSA/IGF4LmQyciA6IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHY7IH07XG59O1xuXG5leHBvcnRzLmRlY29kZURhdGUgPSBmdW5jdGlvbihjb252ZXJ0VG9QeCkge1xuICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgIGlmKHYucmVwbGFjZSkgdiA9IHYucmVwbGFjZSgnXycsICcgJyk7XG4gICAgICAgIHJldHVybiBjb252ZXJ0VG9QeCh2KTtcbiAgICB9O1xufTtcblxuZXhwb3J0cy5lbmNvZGVEYXRlID0gZnVuY3Rpb24oY29udmVydFRvRGF0ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbih2KSB7IHJldHVybiBjb252ZXJ0VG9EYXRlKHYpLnJlcGxhY2UoJyAnLCAnXycpOyB9O1xufTtcblxuZXhwb3J0cy5leHRyYWN0UGF0aENvb3JkcyA9IGZ1bmN0aW9uKHBhdGgsIHBhcmFtc1RvVXNlKSB7XG4gICAgdmFyIGV4dHJhY3RlZENvb3JkaW5hdGVzID0gW107XG5cbiAgICB2YXIgc2VnbWVudHMgPSBwYXRoLm1hdGNoKGNvbnN0YW50cy5zZWdtZW50UkUpO1xuICAgIHNlZ21lbnRzLmZvckVhY2goZnVuY3Rpb24oc2VnbWVudCkge1xuICAgICAgICB2YXIgcmVsZXZhbnRQYXJhbUlkeCA9IHBhcmFtc1RvVXNlW3NlZ21lbnQuY2hhckF0KDApXS5kcmF3bjtcbiAgICAgICAgaWYocmVsZXZhbnRQYXJhbUlkeCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHNlZ21lbnQuc3Vic3RyKDEpLm1hdGNoKGNvbnN0YW50cy5wYXJhbVJFKTtcbiAgICAgICAgaWYoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoIDwgcmVsZXZhbnRQYXJhbUlkeCkgcmV0dXJuO1xuXG4gICAgICAgIGV4dHJhY3RlZENvb3JkaW5hdGVzLnB1c2goTGliLmNsZWFuTnVtYmVyKHBhcmFtc1tyZWxldmFudFBhcmFtSWR4XSkpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGV4dHJhY3RlZENvb3JkaW5hdGVzO1xufTtcblxuZXhwb3J0cy5nZXREYXRhVG9QaXhlbCA9IGZ1bmN0aW9uKGdkLCBheGlzLCBpc1ZlcnRpY2FsKSB7XG4gICAgdmFyIGdzID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemUsXG4gICAgICAgIGRhdGFUb1BpeGVsO1xuXG4gICAgaWYoYXhpcykge1xuICAgICAgICB2YXIgZDJyID0gZXhwb3J0cy5zaGFwZVBvc2l0aW9uVG9SYW5nZShheGlzKTtcblxuICAgICAgICBkYXRhVG9QaXhlbCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiBheGlzLl9vZmZzZXQgKyBheGlzLnIycChkMnIodiwgdHJ1ZSkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmKGF4aXMudHlwZSA9PT0gJ2RhdGUnKSBkYXRhVG9QaXhlbCA9IGV4cG9ydHMuZGVjb2RlRGF0ZShkYXRhVG9QaXhlbCk7XG4gICAgfVxuICAgIGVsc2UgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICBkYXRhVG9QaXhlbCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGdzLnQgKyBncy5oICogKDEgLSB2KTsgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGRhdGFUb1BpeGVsID0gZnVuY3Rpb24odikgeyByZXR1cm4gZ3MubCArIGdzLncgKiB2OyB9O1xuICAgIH1cblxuICAgIHJldHVybiBkYXRhVG9QaXhlbDtcbn07XG5cbmV4cG9ydHMuZ2V0UGl4ZWxUb0RhdGEgPSBmdW5jdGlvbihnZCwgYXhpcywgaXNWZXJ0aWNhbCkge1xuICAgIHZhciBncyA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplLFxuICAgICAgICBwaXhlbFRvRGF0YTtcblxuICAgIGlmKGF4aXMpIHtcbiAgICAgICAgdmFyIHIyZCA9IGV4cG9ydHMucmFuZ2VUb1NoYXBlUG9zaXRpb24oYXhpcyk7XG4gICAgICAgIHBpeGVsVG9EYXRhID0gZnVuY3Rpb24ocCkgeyByZXR1cm4gcjJkKGF4aXMucDJyKHAgLSBheGlzLl9vZmZzZXQpKTsgfTtcbiAgICB9XG4gICAgZWxzZSBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHBpeGVsVG9EYXRhID0gZnVuY3Rpb24ocCkgeyByZXR1cm4gMSAtIChwIC0gZ3MudCkgLyBncy5oOyB9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcGl4ZWxUb0RhdGEgPSBmdW5jdGlvbihwKSB7IHJldHVybiAocCAtIGdzLmwpIC8gZ3MudzsgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGl4ZWxUb0RhdGE7XG59O1xuXG4vKipcbiAqIEJhc2VkIG9uIHRoZSBnaXZlbiBzdHJva2Ugd2lkdGgsIHJvdW5kcyB0aGUgcGFzc2VkXG4gKiBwb3NpdGlvbiB2YWx1ZSB0byByZXByZXNlbnQgZWl0aGVyIGEgZnVsbCBvciBoYWxmIHBpeGVsLlxuICpcbiAqIEluIGNhc2Ugb2YgYW4gb2RkIHN0cm9rZSB3aWR0aCAoZS5nLiAxKSwgdGhpcyBtZWFzdXJlIGVuc3VyZXNcbiAqIHRoYXQgYSBzdHJva2UgcG9zaXRpb25lZCBhdCB0aGUgcmV0dXJuZWQgcG9zaXRpb24gaXNuJ3QgcmVuZGVyZWRcbiAqIGJsdXJyeSBkdWUgdG8gYW50aS1hbGlhc2luZy5cbiAqXG4gKiBJbiBjYXNlIG9mIGFuIGV2ZW4gc3Ryb2tlIHdpZHRoIChlLmcuIDIpLCB0aGlzIG1lYXN1cmUgZW5zdXJlc1xuICogdGhhdCB0aGUgcG9zaXRpb24gdmFsdWUgaXMgdHJhbnNmb3JtZWQgdG8gYSBmdWxsIHBpeGVsIHZhbHVlXG4gKiBzbyB0aGF0IGFudGktYWxpYXNpbmcgZG9lc24ndCB0YWtlIGVmZmVjdCBlaXRoZXIuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHBvcyBUaGUgcmF3IHBvc2l0aW9uIHZhbHVlIHRvIGJlIHRyYW5zZm9ybWVkXG4gKiBAcGFyYW0ge251bWJlcn0gc3Ryb2tlV2lkdGggVGhlIHN0cm9rZSB3aWR0aFxuICogQHJldHVybnMge251bWJlcn0gZWl0aGVyIGFuIGludGVnZXIgb3IgYSAuNSBkZWNpbWFsIG51bWJlclxuICovXG5leHBvcnRzLnJvdW5kUG9zaXRpb25Gb3JTaGFycFN0cm9rZVJlbmRlcmluZyA9IGZ1bmN0aW9uKHBvcywgc3Ryb2tlV2lkdGgpIHtcbiAgICB2YXIgc3Ryb2tlV2lkdGhJc09kZCA9IE1hdGgucm91bmQoc3Ryb2tlV2lkdGggJSAyKSA9PT0gMTtcbiAgICB2YXIgcG9zVmFsQXNJbnQgPSBNYXRoLnJvdW5kKHBvcyk7XG5cbiAgICByZXR1cm4gc3Ryb2tlV2lkdGhJc09kZCA/IHBvc1ZhbEFzSW50ICsgMC41IDogcG9zVmFsQXNJbnQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkcmF3TW9kdWxlID0gcmVxdWlyZSgnLi9kcmF3Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdzaGFwZXMnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMnKSgnc2hhcGVzJyksXG5cbiAgICBjYWxjQXV0b3JhbmdlOiByZXF1aXJlKCcuL2NhbGNfYXV0b3JhbmdlJyksXG4gICAgZHJhdzogZHJhd01vZHVsZS5kcmF3LFxuICAgIGRyYXdPbmU6IGRyYXdNb2R1bGUuZHJhd09uZVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIHBhZEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvcGFkX2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmREZWVwQWxsID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZERlZXBBbGw7XG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG52YXIgYW5pbWF0aW9uQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hbmltYXRpb25fYXR0cmlidXRlcycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbnZhciBzdGVwc0F0dHJzID0gdGVtcGxhdGVkQXJyYXkoJ3N0ZXAnLCB7XG4gICAgdmlzaWJsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1ldGhvZDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydyZXN0eWxlJywgJ3JlbGF5b3V0JywgJ2FuaW1hdGUnLCAndXBkYXRlJywgJ3NraXAnXSxcbiAgICAgICAgZGZsdDogJ3Jlc3R5bGUnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcmdzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGZyZWVMZW5ndGg6IHRydWUsXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7IHZhbFR5cGU6ICdhbnknIH0sXG4gICAgICAgICAgICB7IHZhbFR5cGU6ICdhbnknIH0sXG4gICAgICAgICAgICB7IHZhbFR5cGU6ICdhbnknIH1cbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsYWJlbDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGV4ZWN1dGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwodGVtcGxhdGVkQXJyYXkoJ3NsaWRlcicsIHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBhY3RpdmU6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzdGVwczogc3RlcHNBdHRycyxcblxuICAgIGxlbm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZnJhY3Rpb24nLCAncGl4ZWxzJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnZnJhY3Rpb24nLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxlbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDMsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHBhZDogZXh0ZW5kRGVlcEFsbCh7fSwgcGFkQXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSwge3Q6IHtkZmx0OiAyMH19KSxcbiAgICB4YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDMsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHlhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBkZmx0OiAndG9wJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0cmFuc2l0aW9uOiB7XG4gICAgICAgIGR1cmF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMTUwLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVhc2luZzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBhbmltYXRpb25BdHRycy50cmFuc2l0aW9uLmVhc2luZy52YWx1ZXMsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6ICdjdWJpYy1pbi1vdXQnLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgY3VycmVudHZhbHVlOiB7XG4gICAgICAgIHZpc2libGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHhhbmNob3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddLFxuICAgICAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBvZmZzZXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogMTAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHByZWZpeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHN1ZmZpeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBcbiAgICAgICAgfSlcbiAgICB9LFxuXG4gICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBhY3RpdmViZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMuZ3JpcEJnQWN0aXZlQ29sb3IsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLnJhaWxCZ0NvbG9yLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy5yYWlsQm9yZGVyQ29sb3IsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy5yYWlsQm9yZGVyV2lkdGgsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tsZW46IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLnRpY2tMZW5ndGgsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb25zdGFudHMudGlja0NvbG9yLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgbWlub3J0aWNrbGVuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy5taW5vclRpY2tMZW5ndGgsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59KSwgJ2FycmF5ZHJhdycsICdmcm9tLXJvb3QnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gbGF5b3V0IGF0dHJpYnV0ZSBuYW1lXG4gICAgbmFtZTogJ3NsaWRlcnMnLFxuXG4gICAgLy8gY2xhc3MgbmFtZXNcbiAgICBjb250YWluZXJDbGFzc05hbWU6ICdzbGlkZXItY29udGFpbmVyJyxcbiAgICBncm91cENsYXNzTmFtZTogJ3NsaWRlci1ncm91cCcsXG4gICAgaW5wdXRBcmVhQ2xhc3M6ICdzbGlkZXItaW5wdXQtYXJlYScsXG4gICAgcmFpbFJlY3RDbGFzczogJ3NsaWRlci1yYWlsLXJlY3QnLFxuICAgIHJhaWxUb3VjaFJlY3RDbGFzczogJ3NsaWRlci1yYWlsLXRvdWNoLXJlY3QnLFxuICAgIGdyaXBSZWN0Q2xhc3M6ICdzbGlkZXItZ3JpcC1yZWN0JyxcbiAgICB0aWNrUmVjdENsYXNzOiAnc2xpZGVyLXRpY2stcmVjdCcsXG4gICAgaW5wdXRQcm94eUNsYXNzOiAnc2xpZGVyLWlucHV0LXByb3h5JyxcbiAgICBsYWJlbHNDbGFzczogJ3NsaWRlci1sYWJlbHMnLFxuICAgIGxhYmVsR3JvdXBDbGFzczogJ3NsaWRlci1sYWJlbC1ncm91cCcsXG4gICAgbGFiZWxDbGFzczogJ3NsaWRlci1sYWJlbCcsXG4gICAgY3VycmVudFZhbHVlQ2xhc3M6ICdzbGlkZXItY3VycmVudC12YWx1ZScsXG5cbiAgICByYWlsSGVpZ2h0OiA1LFxuXG4gICAgLy8gRE9NIGF0dHJpYnV0ZSBuYW1lIGluIGJ1dHRvbiBncm91cCBrZWVwaW5nIHRyYWNrXG4gICAgLy8gb2YgYWN0aXZlIHVwZGF0ZSBtZW51XG4gICAgbWVudUluZGV4QXR0ck5hbWU6ICdzbGlkZXItYWN0aXZlLWluZGV4JyxcblxuICAgIC8vIGlkIHJvb3QgcGFzcyB0byBQbG90cy5hdXRvTWFyZ2luXG4gICAgYXV0b01hcmdpbklkUm9vdDogJ3NsaWRlci0nLFxuXG4gICAgLy8gbWluIGl0ZW0gd2lkdGggLyBoZWlnaHRcbiAgICBtaW5XaWR0aDogMzAsXG4gICAgbWluSGVpZ2h0OiAzMCxcblxuICAgIC8vIHBhZGRpbmcgYXJvdW5kIGl0ZW0gdGV4dFxuICAgIHRleHRQYWRYOiA0MCxcblxuICAgIC8vIGFycm93IG9mZnNldCBvZmYgcmlnaHQgZWRnZVxuICAgIGFycm93T2Zmc2V0WDogNCxcblxuICAgIHJhaWxSYWRpdXM6IDIsXG4gICAgcmFpbFdpZHRoOiA1LFxuICAgIHJhaWxCb3JkZXI6IDQsXG4gICAgcmFpbEJvcmRlcldpZHRoOiAxLFxuICAgIHJhaWxCb3JkZXJDb2xvcjogJyNiZWM4ZDknLFxuICAgIHJhaWxCZ0NvbG9yOiAnI2Y4ZmFmYycsXG5cbiAgICAvLyBUaGUgZGlzdGFuY2Ugb2YgdGhlIHJhaWwgZnJvbSB0aGUgZWRnZSBvZiB0aGUgdG91Y2hhYmxlIGFyZWFcbiAgICAvLyBTbGlnaHRseSBsZXNzIHRoYW4gdGhlIHN0ZXAgaW5zZXQgYmVjYXVzZSBvZiB0aGUgY3VydmVkIGVkZ2VzXG4gICAgLy8gb2YgdGhlIHJhaWxcbiAgICByYWlsSW5zZXQ6IDgsXG5cbiAgICAvLyBUaGUgZGlzdGFuY2UgZnJvbSB0aGUgZXh0cmVtYWwgdGljayBtYXJrcyB0byB0aGUgZWRnZSBvZiB0aGVcbiAgICAvLyB0b3VjaGFibGUgYXJlYS4gVGhpcyBpcyBiYXNpY2FsbHkgdGhlIHNhbWUgYXMgdGhlIGdyaXAgcmFkaXVzLFxuICAgIC8vIGJ1dCBmb3Igb3RoZXIgc3R5bGVzIGl0IHdvdWxkbid0IHJlYWxseSBuZWVkIHRvIGJlLlxuICAgIHN0ZXBJbnNldDogMTAsXG5cbiAgICBncmlwUmFkaXVzOiAxMCxcbiAgICBncmlwV2lkdGg6IDIwLFxuICAgIGdyaXBIZWlnaHQ6IDIwLFxuICAgIGdyaXBCb3JkZXI6IDIwLFxuICAgIGdyaXBCb3JkZXJXaWR0aDogMSxcbiAgICBncmlwQm9yZGVyQ29sb3I6ICcjYmVjOGQ5JyxcbiAgICBncmlwQmdDb2xvcjogJyNmNmY4ZmEnLFxuICAgIGdyaXBCZ0FjdGl2ZUNvbG9yOiAnI2RiZGRlMCcsXG5cbiAgICBsYWJlbFBhZGRpbmc6IDgsXG4gICAgbGFiZWxPZmZzZXQ6IDAsXG5cbiAgICB0aWNrV2lkdGg6IDEsXG4gICAgdGlja0NvbG9yOiAnIzMzMycsXG4gICAgdGlja09mZnNldDogMjUsXG4gICAgdGlja0xlbmd0aDogNyxcblxuICAgIG1pbm9yVGlja09mZnNldDogMjUsXG4gICAgbWlub3JUaWNrQ29sb3I6ICcjMzMzJyxcbiAgICBtaW5vclRpY2tMZW5ndGg6IDQsXG5cbiAgICAvLyBFeHRyYSBzcGFjZSBiZWxvdyB0aGUgY3VycmVudCB2YWx1ZSBsYWJlbDpcbiAgICBjdXJyZW50VmFsdWVQYWRkaW5nOiA4LFxuICAgIGN1cnJlbnRWYWx1ZUluc2V0OiAwLFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG52YXIgbmFtZSA9IGNvbnN0YW50cy5uYW1lO1xudmFyIHN0ZXBBdHRycyA9IGF0dHJpYnV0ZXMuc3RlcHM7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzbGlkZXJzRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwge1xuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IHNsaWRlckRlZmF1bHRzXG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBzbGlkZXJEZWZhdWx0cyhzbGlkZXJJbiwgc2xpZGVyT3V0LCBsYXlvdXRPdXQpIHtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHNsaWRlckluLCBzbGlkZXJPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBzdGVwcyA9IGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoc2xpZGVySW4sIHNsaWRlck91dCwge1xuICAgICAgICBuYW1lOiAnc3RlcHMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IHN0ZXBEZWZhdWx0c1xuICAgIH0pO1xuXG4gICAgdmFyIHN0ZXBDb3VudCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN0ZXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKHN0ZXBzW2ldLnZpc2libGUpIHN0ZXBDb3VudCsrO1xuICAgIH1cblxuICAgIHZhciB2aXNpYmxlO1xuICAgIC8vIElmIGl0IGhhcyBmZXdlciB0aGFuIHR3byBvcHRpb25zLCBpdCdzIG5vdCByZWFsbHkgYSBzbGlkZXJcbiAgICBpZihzdGVwQ291bnQgPCAyKSB2aXNpYmxlID0gc2xpZGVyT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICBlbHNlIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICBpZighdmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgc2xpZGVyT3V0Ll9zdGVwQ291bnQgPSBzdGVwQ291bnQ7XG4gICAgdmFyIHZpc1N0ZXBzID0gc2xpZGVyT3V0Ll92aXNpYmxlU3RlcHMgPSBMaWIuZmlsdGVyVmlzaWJsZShzdGVwcyk7XG5cbiAgICB2YXIgYWN0aXZlID0gY29lcmNlKCdhY3RpdmUnKTtcbiAgICBpZighKHN0ZXBzW2FjdGl2ZV0gfHwge30pLnZpc2libGUpIHNsaWRlck91dC5hY3RpdmUgPSB2aXNTdGVwc1swXS5faW5kZXg7XG5cbiAgICBjb2VyY2UoJ3gnKTtcbiAgICBjb2VyY2UoJ3knKTtcbiAgICBMaWIubm9uZU9yQWxsKHNsaWRlckluLCBzbGlkZXJPdXQsIFsneCcsICd5J10pO1xuXG4gICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgY29lcmNlKCd5YW5jaG9yJyk7XG5cbiAgICBjb2VyY2UoJ2xlbicpO1xuICAgIGNvZXJjZSgnbGVubW9kZScpO1xuXG4gICAgY29lcmNlKCdwYWQudCcpO1xuICAgIGNvZXJjZSgncGFkLnInKTtcbiAgICBjb2VyY2UoJ3BhZC5iJyk7XG4gICAgY29lcmNlKCdwYWQubCcpO1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnZm9udCcsIGxheW91dE91dC5mb250KTtcblxuICAgIHZhciBjdXJyZW50VmFsdWVJc1Zpc2libGUgPSBjb2VyY2UoJ2N1cnJlbnR2YWx1ZS52aXNpYmxlJyk7XG5cbiAgICBpZihjdXJyZW50VmFsdWVJc1Zpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdjdXJyZW50dmFsdWUueGFuY2hvcicpO1xuICAgICAgICBjb2VyY2UoJ2N1cnJlbnR2YWx1ZS5wcmVmaXgnKTtcbiAgICAgICAgY29lcmNlKCdjdXJyZW50dmFsdWUuc3VmZml4Jyk7XG4gICAgICAgIGNvZXJjZSgnY3VycmVudHZhbHVlLm9mZnNldCcpO1xuXG4gICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2N1cnJlbnR2YWx1ZS5mb250Jywgc2xpZGVyT3V0LmZvbnQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgndHJhbnNpdGlvbi5kdXJhdGlvbicpO1xuICAgIGNvZXJjZSgndHJhbnNpdGlvbi5lYXNpbmcnKTtcblxuICAgIGNvZXJjZSgnYmdjb2xvcicpO1xuICAgIGNvZXJjZSgnYWN0aXZlYmdjb2xvcicpO1xuICAgIGNvZXJjZSgnYm9yZGVyY29sb3InKTtcbiAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG4gICAgY29lcmNlKCd0aWNrbGVuJyk7XG4gICAgY29lcmNlKCd0aWNrd2lkdGgnKTtcbiAgICBjb2VyY2UoJ3RpY2tjb2xvcicpO1xuICAgIGNvZXJjZSgnbWlub3J0aWNrbGVuJyk7XG59XG5cbmZ1bmN0aW9uIHN0ZXBEZWZhdWx0cyh2YWx1ZUluLCB2YWx1ZU91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHZhbHVlSW4sIHZhbHVlT3V0LCBzdGVwQXR0cnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB2aXNpYmxlO1xuICAgIGlmKHZhbHVlSW4ubWV0aG9kICE9PSAnc2tpcCcgJiYgIUFycmF5LmlzQXJyYXkodmFsdWVJbi5hcmdzKSkge1xuICAgICAgICB2aXNpYmxlID0gdmFsdWVPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcblxuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdtZXRob2QnKTtcbiAgICAgICAgY29lcmNlKCdhcmdzJyk7XG4gICAgICAgIHZhciBsYWJlbCA9IGNvZXJjZSgnbGFiZWwnLCAnc3RlcC0nICsgdmFsdWVPdXQuX2luZGV4KTtcbiAgICAgICAgY29lcmNlKCd2YWx1ZScsIGxhYmVsKTtcbiAgICAgICAgY29lcmNlKCdleGVjdXRlJyk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgUGxvdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9wbG90cycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vZHJhd2luZycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGFuY2hvclV0aWxzID0gcmVxdWlyZSgnLi4vbGVnZW5kL2FuY2hvcl91dGlscycpO1xudmFyIGFycmF5RWRpdG9yID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLmFycmF5RWRpdG9yO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBhbGlnbm1lbnRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50Jyk7XG52YXIgTElORV9TUEFDSU5HID0gYWxpZ25tZW50Q29uc3RhbnRzLkxJTkVfU1BBQ0lORztcbnZhciBGUk9NX1RMID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fVEw7XG52YXIgRlJPTV9CUiA9IGFsaWdubWVudENvbnN0YW50cy5GUk9NX0JSO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBzbGlkZXJEYXRhID0gbWFrZVNsaWRlckRhdGEoZnVsbExheW91dCwgZ2QpO1xuXG4gICAgLy8gZHJhdyBhIGNvbnRhaW5lciBmb3IgKmFsbCogc2xpZGVyczpcbiAgICB2YXIgc2xpZGVycyA9IGZ1bGxMYXlvdXQuX2luZm9sYXllclxuICAgICAgICAuc2VsZWN0QWxsKCdnLicgKyBjb25zdGFudHMuY29udGFpbmVyQ2xhc3NOYW1lKVxuICAgICAgICAuZGF0YShzbGlkZXJEYXRhLmxlbmd0aCA+IDAgPyBbMF0gOiBbXSk7XG5cbiAgICBzbGlkZXJzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmNvbnRhaW5lckNsYXNzTmFtZSwgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCAnZXctcmVzaXplJyk7XG5cbiAgICBmdW5jdGlvbiBjbGVhclNsaWRlcihzbGlkZXJPcHRzKSB7XG4gICAgICAgIGlmKHNsaWRlck9wdHMuX2NvbW1hbmRPYnNlcnZlcikge1xuICAgICAgICAgICAgc2xpZGVyT3B0cy5fY29tbWFuZE9ic2VydmVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgZGVsZXRlIHNsaWRlck9wdHMuX2NvbW1hbmRPYnNlcnZlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1vc3QgY29tcG9uZW50cyBkb24ndCBuZWVkIHRvIGV4cGxpY2l0bHkgcmVtb3ZlIGF1dG9NYXJnaW4sIGJlY2F1c2VcbiAgICAgICAgLy8gbWFyZ2luUHVzaGVycyBkb2VzIHRoaXMgLSBidXQgc2xpZGVyIHVwZGF0ZXMgZG9uJ3QgZ28gdGhyb3VnaFxuICAgICAgICAvLyBhIGZ1bGwgcmVwbG90IHNvIHdlIG5lZWQgdG8gZXhwbGljaXRseSByZW1vdmUgaXQuXG4gICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIGF1dG9NYXJnaW5JZChzbGlkZXJPcHRzKSk7XG4gICAgfVxuXG4gICAgc2xpZGVycy5leGl0KCkuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmdyb3VwQ2xhc3NOYW1lKVxuICAgICAgICAgICAgLmVhY2goY2xlYXJTbGlkZXIpO1xuICAgIH0pXG4gICAgLnJlbW92ZSgpO1xuXG4gICAgLy8gUmV0dXJuIGVhcmx5IGlmIG5vIG1lbnVzIHZpc2libGU6XG4gICAgaWYoc2xpZGVyRGF0YS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIHZhciBzbGlkZXJHcm91cHMgPSBzbGlkZXJzLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmdyb3VwQ2xhc3NOYW1lKVxuICAgICAgICAuZGF0YShzbGlkZXJEYXRhLCBrZXlGdW5jdGlvbik7XG5cbiAgICBzbGlkZXJHcm91cHMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjb25zdGFudHMuZ3JvdXBDbGFzc05hbWUsIHRydWUpO1xuXG4gICAgc2xpZGVyR3JvdXBzLmV4aXQoKVxuICAgICAgICAuZWFjaChjbGVhclNsaWRlcilcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgLy8gRmluZCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgc2xpZGVyczpcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2xpZGVyRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2xpZGVyT3B0cyA9IHNsaWRlckRhdGFbaV07XG4gICAgICAgIGZpbmREaW1lbnNpb25zKGdkLCBzbGlkZXJPcHRzKTtcbiAgICB9XG5cbiAgICBzbGlkZXJHcm91cHMuZWFjaChmdW5jdGlvbihzbGlkZXJPcHRzKSB7XG4gICAgICAgIHZhciBnU2xpZGVyID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGNvbXB1dGVMYWJlbFN0ZXBzKHNsaWRlck9wdHMpO1xuXG4gICAgICAgIFBsb3RzLm1hbmFnZUNvbW1hbmRPYnNlcnZlcihnZCwgc2xpZGVyT3B0cywgc2xpZGVyT3B0cy5fdmlzaWJsZVN0ZXBzLCBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAvLyBOQjogU2FtZSBhcyBiZWxvdy4gVGhpcyBpcyAqbm90KiBhbHdheXMgdGhlIHNhbWUgYXMgc2xpZGVyT3B0cyBzaW5jZVxuICAgICAgICAgICAgLy8gaWYgYSBuZXcgc2V0IG9mIHN0ZXBzIGNvbWVzIGluLCB0aGUgcmVmZXJlbmNlIGluIHRoaXMgY2FsbGJhY2sgd291bGRcbiAgICAgICAgICAgIC8vIGJlIGludmFsaWQuIFdlIG5lZWQgdG8gcmVmZXRjaCBpdCBmcm9tIHRoZSBzbGlkZXIgZ3JvdXAsIHdoaWNoIGlzXG4gICAgICAgICAgICAvLyB0aGUgam9pbiBkYXRhIHRoYXQgY3JlYXRlcyB0aGlzIHNsaWRlci4gU28gaWYgdGhpcyBzbGlkZXIgc3RpbGwgZXhpc3RzLFxuICAgICAgICAgICAgLy8gdGhlIGdyb3VwIHNob3VsZCBiZSB2YWxpZCwgKnRvIHRoZSBiZXN0IG9mIG15IGtub3dsZWRnZS4qIElmIG5vdCxcbiAgICAgICAgICAgIC8vIHdlJ2QgaGF2ZSB0byBsb29rIGl0IHVwIGJ5IGQzIGRhdGEgam9pbiBpbmRleC9rZXkuXG4gICAgICAgICAgICB2YXIgb3B0cyA9IGdTbGlkZXIuZGF0YSgpWzBdO1xuXG4gICAgICAgICAgICBpZihvcHRzLmFjdGl2ZSA9PT0gZGF0YS5pbmRleCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYob3B0cy5fZHJhZ2dpbmcpIHJldHVybjtcblxuICAgICAgICAgICAgc2V0QWN0aXZlKGdkLCBnU2xpZGVyLCBvcHRzLCBkYXRhLmluZGV4LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRyYXdTbGlkZXIoZ2QsIGQzLnNlbGVjdCh0aGlzKSwgc2xpZGVyT3B0cyk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBhdXRvTWFyZ2luSWQoc2xpZGVyT3B0cykge1xuICAgIHJldHVybiBjb25zdGFudHMuYXV0b01hcmdpbklkUm9vdCArIHNsaWRlck9wdHMuX2luZGV4O1xufVxuXG4vLyBUaGlzIHJlYWxseSBvbmx5IGp1c3QgZmlsdGVycyBieSB2aXNpYmlsaXR5OlxuZnVuY3Rpb24gbWFrZVNsaWRlckRhdGEoZnVsbExheW91dCwgZ2QpIHtcbiAgICB2YXIgY29udE9wdHMgPSBmdWxsTGF5b3V0W2NvbnN0YW50cy5uYW1lXSxcbiAgICAgICAgc2xpZGVyRGF0YSA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbnRPcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gY29udE9wdHNbaV07XG4gICAgICAgIGlmKCFpdGVtLnZpc2libGUpIGNvbnRpbnVlO1xuICAgICAgICBpdGVtLl9nZCA9IGdkO1xuICAgICAgICBzbGlkZXJEYXRhLnB1c2goaXRlbSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWRlckRhdGE7XG59XG5cbi8vIFRoaXMgaXMgc2V0IGluIHRoZSBkZWZhdWx0cyBzdGVwOlxuZnVuY3Rpb24ga2V5RnVuY3Rpb24ob3B0cykge1xuICAgIHJldHVybiBvcHRzLl9pbmRleDtcbn1cblxuLy8gQ29tcHV0ZSB0aGUgZGltZW5zaW9ucyAobXV0YXRlcyBzbGlkZXJPcHRzKTpcbmZ1bmN0aW9uIGZpbmREaW1lbnNpb25zKGdkLCBzbGlkZXJPcHRzKSB7XG4gICAgdmFyIHNsaWRlckxhYmVscyA9IERyYXdpbmcudGVzdGVyLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmxhYmVsR3JvdXBDbGFzcylcbiAgICAgICAgLmRhdGEoc2xpZGVyT3B0cy5fdmlzaWJsZVN0ZXBzKTtcblxuICAgIHNsaWRlckxhYmVscy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5sYWJlbEdyb3VwQ2xhc3MsIHRydWUpO1xuXG4gICAgLy8gbG9vcCBvdmVyIGZha2UgYnV0dG9ucyB0byBmaW5kIHdpZHRoIC8gaGVpZ2h0XG4gICAgdmFyIG1heExhYmVsV2lkdGggPSAwO1xuICAgIHZhciBsYWJlbEhlaWdodCA9IDA7XG4gICAgc2xpZGVyTGFiZWxzLmVhY2goZnVuY3Rpb24oc3RlcE9wdHMpIHtcbiAgICAgICAgdmFyIGxhYmVsR3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgdmFyIHRleHQgPSBkcmF3TGFiZWwobGFiZWxHcm91cCwge3N0ZXA6IHN0ZXBPcHRzfSwgc2xpZGVyT3B0cyk7XG5cbiAgICAgICAgdmFyIHRleHROb2RlID0gdGV4dC5ub2RlKCk7XG4gICAgICAgIGlmKHRleHROb2RlKSB7XG4gICAgICAgICAgICB2YXIgYkJveCA9IERyYXdpbmcuYkJveCh0ZXh0Tm9kZSk7XG4gICAgICAgICAgICBsYWJlbEhlaWdodCA9IE1hdGgubWF4KGxhYmVsSGVpZ2h0LCBiQm94LmhlaWdodCk7XG4gICAgICAgICAgICBtYXhMYWJlbFdpZHRoID0gTWF0aC5tYXgobWF4TGFiZWxXaWR0aCwgYkJveC53aWR0aCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHNsaWRlckxhYmVscy5yZW1vdmUoKTtcblxuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcyA9IHt9O1xuXG4gICAgZGltcy5pbnB1dEFyZWFXaWR0aCA9IE1hdGgubWF4KFxuICAgICAgICBjb25zdGFudHMucmFpbFdpZHRoLFxuICAgICAgICBjb25zdGFudHMuZ3JpcEhlaWdodFxuICAgICk7XG5cbiAgICAvLyBjYWxjdWxhdGUgc29tZSBvdmVyYWxsIGRpbWVuc2lvbnMgLSBzb21lIG9mIHRoZXNlIGFyZSBuZWVkZWQgZm9yXG4gICAgLy8gY2FsY3VsYXRpbmcgdGhlIGN1cnJlbnRWYWx1ZSBkaW1lbnNpb25zXG4gICAgdmFyIGdyYXBoU2l6ZSA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgIGRpbXMubHggPSBncmFwaFNpemUubCArIGdyYXBoU2l6ZS53ICogc2xpZGVyT3B0cy54O1xuICAgIGRpbXMubHkgPSBncmFwaFNpemUudCArIGdyYXBoU2l6ZS5oICogKDEgLSBzbGlkZXJPcHRzLnkpO1xuXG4gICAgaWYoc2xpZGVyT3B0cy5sZW5tb2RlID09PSAnZnJhY3Rpb24nKSB7XG4gICAgICAgIC8vIGZyYWN0aW9uOlxuICAgICAgICBkaW1zLm91dGVyTGVuZ3RoID0gTWF0aC5yb3VuZChncmFwaFNpemUudyAqIHNsaWRlck9wdHMubGVuKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBwaXhlbHM6XG4gICAgICAgIGRpbXMub3V0ZXJMZW5ndGggPSBzbGlkZXJPcHRzLmxlbjtcbiAgICB9XG5cbiAgICAvLyBUaGUgbGVuZ3RoIG9mIHRoZSByYWlsLCAqZXhjbHVkaW5nKiBwYWRkaW5nIG9uIGVpdGhlciBlbmQ6XG4gICAgZGltcy5pbnB1dEFyZWFTdGFydCA9IDA7XG4gICAgZGltcy5pbnB1dEFyZWFMZW5ndGggPSBNYXRoLnJvdW5kKGRpbXMub3V0ZXJMZW5ndGggLSBzbGlkZXJPcHRzLnBhZC5sIC0gc2xpZGVyT3B0cy5wYWQucik7XG5cbiAgICB2YXIgdGV4dGFibGVJbnB1dExlbmd0aCA9IGRpbXMuaW5wdXRBcmVhTGVuZ3RoIC0gMiAqIGNvbnN0YW50cy5zdGVwSW5zZXQ7XG4gICAgdmFyIGF2YWlsYWJsZVNwYWNlUGVyTGFiZWwgPSB0ZXh0YWJsZUlucHV0TGVuZ3RoIC8gKHNsaWRlck9wdHMuX3N0ZXBDb3VudCAtIDEpO1xuICAgIHZhciBjb21wdXRlZFNwYWNlUGVyTGFiZWwgPSBtYXhMYWJlbFdpZHRoICsgY29uc3RhbnRzLmxhYmVsUGFkZGluZztcbiAgICBkaW1zLmxhYmVsU3RyaWRlID0gTWF0aC5tYXgoMSwgTWF0aC5jZWlsKGNvbXB1dGVkU3BhY2VQZXJMYWJlbCAvIGF2YWlsYWJsZVNwYWNlUGVyTGFiZWwpKTtcbiAgICBkaW1zLmxhYmVsSGVpZ2h0ID0gbGFiZWxIZWlnaHQ7XG5cbiAgICAvLyBsb29wIG92ZXIgYWxsIHBvc3NpYmxlIHZhbHVlcyBmb3IgY3VycmVudFZhbHVlIHRvIGZpbmQgdGhlXG4gICAgLy8gYXJlYSB3ZSBuZWVkIGZvciBpdFxuICAgIGRpbXMuY3VycmVudFZhbHVlTWF4V2lkdGggPSAwO1xuICAgIGRpbXMuY3VycmVudFZhbHVlSGVpZ2h0ID0gMDtcbiAgICBkaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0ID0gMDtcbiAgICBkaW1zLmN1cnJlbnRWYWx1ZU1heExpbmVzID0gMTtcblxuICAgIGlmKHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnZpc2libGUpIHtcbiAgICAgICAgLy8gR2V0IHRoZSBkaW1lbnNpb25zIG9mIHRoZSBjdXJyZW50IHZhbHVlIGxhYmVsOlxuICAgICAgICB2YXIgZHVtbXlHcm91cCA9IERyYXdpbmcudGVzdGVyLmFwcGVuZCgnZycpO1xuXG4gICAgICAgIHNsaWRlckxhYmVscy5lYWNoKGZ1bmN0aW9uKHN0ZXBPcHRzKSB7XG4gICAgICAgICAgICB2YXIgY3VyVmFsUHJlZml4ID0gZHJhd0N1cnJlbnRWYWx1ZShkdW1teUdyb3VwLCBzbGlkZXJPcHRzLCBzdGVwT3B0cy5sYWJlbCk7XG4gICAgICAgICAgICB2YXIgY3VyVmFsU2l6ZSA9IChjdXJWYWxQcmVmaXgubm9kZSgpICYmIERyYXdpbmcuYkJveChjdXJWYWxQcmVmaXgubm9kZSgpKSkgfHwge3dpZHRoOiAwLCBoZWlnaHQ6IDB9O1xuICAgICAgICAgICAgdmFyIGxpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudChjdXJWYWxQcmVmaXgpO1xuICAgICAgICAgICAgZGltcy5jdXJyZW50VmFsdWVNYXhXaWR0aCA9IE1hdGgubWF4KGRpbXMuY3VycmVudFZhbHVlTWF4V2lkdGgsIE1hdGguY2VpbChjdXJWYWxTaXplLndpZHRoKSk7XG4gICAgICAgICAgICBkaW1zLmN1cnJlbnRWYWx1ZUhlaWdodCA9IE1hdGgubWF4KGRpbXMuY3VycmVudFZhbHVlSGVpZ2h0LCBNYXRoLmNlaWwoY3VyVmFsU2l6ZS5oZWlnaHQpKTtcbiAgICAgICAgICAgIGRpbXMuY3VycmVudFZhbHVlTWF4TGluZXMgPSBNYXRoLm1heChkaW1zLmN1cnJlbnRWYWx1ZU1heExpbmVzLCBsaW5lcyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRpbXMuY3VycmVudFZhbHVlVG90YWxIZWlnaHQgPSBkaW1zLmN1cnJlbnRWYWx1ZUhlaWdodCArIHNsaWRlck9wdHMuY3VycmVudHZhbHVlLm9mZnNldDtcblxuICAgICAgICBkdW1teUdyb3VwLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIGRpbXMuaGVpZ2h0ID0gZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodCArIGNvbnN0YW50cy50aWNrT2Zmc2V0ICsgc2xpZGVyT3B0cy50aWNrbGVuICsgY29uc3RhbnRzLmxhYmVsT2Zmc2V0ICsgZGltcy5sYWJlbEhlaWdodCArIHNsaWRlck9wdHMucGFkLnQgKyBzbGlkZXJPcHRzLnBhZC5iO1xuXG4gICAgdmFyIHhhbmNob3IgPSAnbGVmdCc7XG4gICAgaWYoYW5jaG9yVXRpbHMuaXNSaWdodEFuY2hvcihzbGlkZXJPcHRzKSkge1xuICAgICAgICBkaW1zLmx4IC09IGRpbXMub3V0ZXJMZW5ndGg7XG4gICAgICAgIHhhbmNob3IgPSAncmlnaHQnO1xuICAgIH1cbiAgICBpZihhbmNob3JVdGlscy5pc0NlbnRlckFuY2hvcihzbGlkZXJPcHRzKSkge1xuICAgICAgICBkaW1zLmx4IC09IGRpbXMub3V0ZXJMZW5ndGggLyAyO1xuICAgICAgICB4YW5jaG9yID0gJ2NlbnRlcic7XG4gICAgfVxuXG4gICAgdmFyIHlhbmNob3IgPSAndG9wJztcbiAgICBpZihhbmNob3JVdGlscy5pc0JvdHRvbUFuY2hvcihzbGlkZXJPcHRzKSkge1xuICAgICAgICBkaW1zLmx5IC09IGRpbXMuaGVpZ2h0O1xuICAgICAgICB5YW5jaG9yID0gJ2JvdHRvbSc7XG4gICAgfVxuICAgIGlmKGFuY2hvclV0aWxzLmlzTWlkZGxlQW5jaG9yKHNsaWRlck9wdHMpKSB7XG4gICAgICAgIGRpbXMubHkgLT0gZGltcy5oZWlnaHQgLyAyO1xuICAgICAgICB5YW5jaG9yID0gJ21pZGRsZSc7XG4gICAgfVxuXG4gICAgZGltcy5vdXRlckxlbmd0aCA9IE1hdGguY2VpbChkaW1zLm91dGVyTGVuZ3RoKTtcbiAgICBkaW1zLmhlaWdodCA9IE1hdGguY2VpbChkaW1zLmhlaWdodCk7XG4gICAgZGltcy5seCA9IE1hdGgucm91bmQoZGltcy5seCk7XG4gICAgZGltcy5seSA9IE1hdGgucm91bmQoZGltcy5seSk7XG5cbiAgICB2YXIgbWFyZ2luT3B0cyA9IHtcbiAgICAgICAgeTogc2xpZGVyT3B0cy55LFxuICAgICAgICBiOiBkaW1zLmhlaWdodCAqIEZST01fQlJbeWFuY2hvcl0sXG4gICAgICAgIHQ6IGRpbXMuaGVpZ2h0ICogRlJPTV9UTFt5YW5jaG9yXVxuICAgIH07XG5cbiAgICBpZihzbGlkZXJPcHRzLmxlbm1vZGUgPT09ICdmcmFjdGlvbicpIHtcbiAgICAgICAgbWFyZ2luT3B0cy5sID0gMDtcbiAgICAgICAgbWFyZ2luT3B0cy54bCA9IHNsaWRlck9wdHMueCAtIHNsaWRlck9wdHMubGVuICogRlJPTV9UTFt4YW5jaG9yXTtcbiAgICAgICAgbWFyZ2luT3B0cy5yID0gMDtcbiAgICAgICAgbWFyZ2luT3B0cy54ciA9IHNsaWRlck9wdHMueCArIHNsaWRlck9wdHMubGVuICogRlJPTV9CUlt4YW5jaG9yXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIG1hcmdpbk9wdHMueCA9IHNsaWRlck9wdHMueDtcbiAgICAgICAgbWFyZ2luT3B0cy5sID0gZGltcy5vdXRlckxlbmd0aCAqIEZST01fVExbeGFuY2hvcl07XG4gICAgICAgIG1hcmdpbk9wdHMuciA9IGRpbXMub3V0ZXJMZW5ndGggKiBGUk9NX0JSW3hhbmNob3JdO1xuICAgIH1cblxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIGF1dG9NYXJnaW5JZChzbGlkZXJPcHRzKSwgbWFyZ2luT3B0cyk7XG59XG5cbmZ1bmN0aW9uIGRyYXdTbGlkZXIoZ2QsIHNsaWRlckdyb3VwLCBzbGlkZXJPcHRzKSB7XG4gICAgLy8gVGhpcyBpcyByZWxhdGVkIHRvIHRoZSBvdGhlciBsb25nIG5vdGVzIGluIHRoaXMgZmlsZSByZWdhcmRpbmcgd2hhdCBoYXBwZW5zXG4gICAgLy8gd2hlbiBzbGlkZXIgc3RlcHMgZGlzYXBwZWFyLiBUaGlzIHBhcnRpY3VsYXIgZml4IGhhbmRsZXMgd2hhdCBoYXBwZW5zIHdoZW5cbiAgICAvLyB0aGUgKmN1cnJlbnQqIHNsaWRlciBzdGVwIGlzIHJlbW92ZWQuIFRoZSBkcmF3aW5nIGZ1bmN0aW9ucyB3aWxsIGVycm9yIG91dFxuICAgIC8vIHdoZW4gdGhleSBmYWlsIHRvIGZpbmQgaXQsIHNvIHRoZSBmaXggZm9yIG5vdyBpcyB0aGF0IGl0IHdpbGwganVzdCBkcmF3IHRoZVxuICAgIC8vIHNsaWRlciBpbiB0aGUgZmlyc3QgcG9zaXRpb24gYnV0IHdpbGwgbm90IGV4ZWN1dGUgdGhlIGNvbW1hbmQuXG4gICAgaWYoISgoc2xpZGVyT3B0cy5zdGVwc1tzbGlkZXJPcHRzLmFjdGl2ZV0gfHwge30pLnZpc2libGUpKSB7XG4gICAgICAgIHNsaWRlck9wdHMuYWN0aXZlID0gc2xpZGVyT3B0cy5fdmlzaWJsZVN0ZXBzWzBdLl9pbmRleDtcbiAgICB9XG5cbiAgICAvLyBUaGVzZSBhcmUgY2FyZWZ1bGx5IG9yZGVyZWQgZm9yIHByb3BlciB6LW9yZGVyaW5nOlxuICAgIHNsaWRlckdyb3VwXG4gICAgICAgIC5jYWxsKGRyYXdDdXJyZW50VmFsdWUsIHNsaWRlck9wdHMpXG4gICAgICAgIC5jYWxsKGRyYXdSYWlsLCBzbGlkZXJPcHRzKVxuICAgICAgICAuY2FsbChkcmF3TGFiZWxHcm91cCwgc2xpZGVyT3B0cylcbiAgICAgICAgLmNhbGwoZHJhd1RpY2tzLCBzbGlkZXJPcHRzKVxuICAgICAgICAuY2FsbChkcmF3VG91Y2hSZWN0LCBnZCwgc2xpZGVyT3B0cylcbiAgICAgICAgLmNhbGwoZHJhd0dyaXAsIGdkLCBzbGlkZXJPcHRzKTtcblxuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcblxuICAgIC8vIFBvc2l0aW9uIHRoZSByZWN0YW5nbGU6XG4gICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoc2xpZGVyR3JvdXAsIGRpbXMubHggKyBzbGlkZXJPcHRzLnBhZC5sLCBkaW1zLmx5ICsgc2xpZGVyT3B0cy5wYWQudCk7XG5cbiAgICBzbGlkZXJHcm91cC5jYWxsKHNldEdyaXBQb3NpdGlvbiwgc2xpZGVyT3B0cywgZmFsc2UpO1xuICAgIHNsaWRlckdyb3VwLmNhbGwoZHJhd0N1cnJlbnRWYWx1ZSwgc2xpZGVyT3B0cyk7XG5cbn1cblxuZnVuY3Rpb24gZHJhd0N1cnJlbnRWYWx1ZShzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgdmFsdWVPdmVycmlkZSkge1xuICAgIGlmKCFzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS52aXNpYmxlKSByZXR1cm47XG5cbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgdmFyIHgwLCB0ZXh0QW5jaG9yO1xuXG4gICAgc3dpdGNoKHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnhhbmNob3IpIHtcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgLy8gVGhpcyBpcyBhbmNob3JlZCBsZWZ0IGFuZCBhZGp1c3RlZCBieSB0aGUgd2lkdGggb2YgdGhlIGxvbmdlc3QgbGFiZWxcbiAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIHByZWZpeCBkb2Vzbid0IG1vdmUuIFRoZSBnb2FsIG9mIHRoaXMgaXMgdG8gZW1waGFzaXplXG4gICAgICAgICAgICAvLyB3aGF0J3MgYWN0dWFsbHkgY2hhbmdpbmcgYW5kIG1ha2UgdGhlIHVwZGF0ZSBsZXNzIGRpc3RyYWN0aW5nLlxuICAgICAgICAgICAgeDAgPSBkaW1zLmlucHV0QXJlYUxlbmd0aCAtIGNvbnN0YW50cy5jdXJyZW50VmFsdWVJbnNldCAtIGRpbXMuY3VycmVudFZhbHVlTWF4V2lkdGg7XG4gICAgICAgICAgICB0ZXh0QW5jaG9yID0gJ2xlZnQnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgICAgICB4MCA9IGRpbXMuaW5wdXRBcmVhTGVuZ3RoICogMC41O1xuICAgICAgICAgICAgdGV4dEFuY2hvciA9ICdtaWRkbGUnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB4MCA9IGNvbnN0YW50cy5jdXJyZW50VmFsdWVJbnNldDtcbiAgICAgICAgICAgIHRleHRBbmNob3IgPSAnbGVmdCc7XG4gICAgfVxuXG4gICAgdmFyIHRleHQgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWRlckdyb3VwLCAndGV4dCcsIGNvbnN0YW50cy5sYWJlbENsYXNzLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2xhc3NlZCgndXNlci1zZWxlY3Qtbm9uZScsIHRydWUpXG4gICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogdGV4dEFuY2hvcixcbiAgICAgICAgICAgICAgICAnZGF0YS1ub3RleCc6IDFcbiAgICAgICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdmFyIHN0ciA9IHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnByZWZpeCA/IHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnByZWZpeCA6ICcnO1xuXG4gICAgaWYodHlwZW9mIHZhbHVlT3ZlcnJpZGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHN0ciArPSB2YWx1ZU92ZXJyaWRlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBjdXJWYWwgPSBzbGlkZXJPcHRzLnN0ZXBzW3NsaWRlck9wdHMuYWN0aXZlXS5sYWJlbDtcbiAgICAgICAgc3RyICs9IGN1clZhbDtcbiAgICB9XG5cbiAgICBpZihzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5zdWZmaXgpIHtcbiAgICAgICAgc3RyICs9IHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnN1ZmZpeDtcbiAgICB9XG5cbiAgICB0ZXh0LmNhbGwoRHJhd2luZy5mb250LCBzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5mb250KVxuICAgICAgICAudGV4dChzdHIpXG4gICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIHNsaWRlck9wdHMuX2dkKTtcblxuICAgIHZhciBsaW5lcyA9IHN2Z1RleHRVdGlscy5saW5lQ291bnQodGV4dCk7XG5cbiAgICB2YXIgeTAgPSAoZGltcy5jdXJyZW50VmFsdWVNYXhMaW5lcyArIDEgLSBsaW5lcykgKlxuICAgICAgICBzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5mb250LnNpemUgKiBMSU5FX1NQQUNJTkc7XG5cbiAgICBzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0KHRleHQsIHgwLCB5MCk7XG5cbiAgICByZXR1cm4gdGV4dDtcbn1cblxuZnVuY3Rpb24gZHJhd0dyaXAoc2xpZGVyR3JvdXAsIGdkLCBzbGlkZXJPcHRzKSB7XG4gICAgdmFyIGdyaXAgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWRlckdyb3VwLCAncmVjdCcsIGNvbnN0YW50cy5ncmlwUmVjdENsYXNzLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2FsbChhdHRhY2hHcmlwRXZlbnRzLCBnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMpXG4gICAgICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgIH0pO1xuXG4gICAgZ3JpcC5hdHRyKHtcbiAgICAgICAgd2lkdGg6IGNvbnN0YW50cy5ncmlwV2lkdGgsXG4gICAgICAgIGhlaWdodDogY29uc3RhbnRzLmdyaXBIZWlnaHQsXG4gICAgICAgIHJ4OiBjb25zdGFudHMuZ3JpcFJhZGl1cyxcbiAgICAgICAgcnk6IGNvbnN0YW50cy5ncmlwUmFkaXVzLFxuICAgIH0pXG4gICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBzbGlkZXJPcHRzLmJvcmRlcmNvbG9yKVxuICAgIC5jYWxsKENvbG9yLmZpbGwsIHNsaWRlck9wdHMuYmdjb2xvcilcbiAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHNsaWRlck9wdHMuYm9yZGVyd2lkdGggKyAncHgnKTtcbn1cblxuZnVuY3Rpb24gZHJhd0xhYmVsKGl0ZW0sIGRhdGEsIHNsaWRlck9wdHMpIHtcbiAgICB2YXIgdGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoaXRlbSwgJ3RleHQnLCBjb25zdGFudHMubGFiZWxDbGFzcywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmNsYXNzZWQoJ3VzZXItc2VsZWN0LW5vbmUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnLFxuICAgICAgICAgICAgICAgICdkYXRhLW5vdGV4JzogMVxuICAgICAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXh0LmNhbGwoRHJhd2luZy5mb250LCBzbGlkZXJPcHRzLmZvbnQpXG4gICAgICAgIC50ZXh0KGRhdGEuc3RlcC5sYWJlbClcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgc2xpZGVyT3B0cy5fZ2QpO1xuXG4gICAgcmV0dXJuIHRleHQ7XG59XG5cbmZ1bmN0aW9uIGRyYXdMYWJlbEdyb3VwKHNsaWRlckdyb3VwLCBzbGlkZXJPcHRzKSB7XG4gICAgdmFyIGxhYmVscyA9IExpYi5lbnN1cmVTaW5nbGUoc2xpZGVyR3JvdXAsICdnJywgY29uc3RhbnRzLmxhYmVsc0NsYXNzKTtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG5cbiAgICB2YXIgbGFiZWxJdGVtcyA9IGxhYmVscy5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5sYWJlbEdyb3VwQ2xhc3MpXG4gICAgICAgIC5kYXRhKGRpbXMubGFiZWxTdGVwcyk7XG5cbiAgICBsYWJlbEl0ZW1zLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmxhYmVsR3JvdXBDbGFzcywgdHJ1ZSk7XG5cbiAgICBsYWJlbEl0ZW1zLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGxhYmVsSXRlbXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBpdGVtID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGl0ZW0uY2FsbChkcmF3TGFiZWwsIGQsIHNsaWRlck9wdHMpO1xuXG4gICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKGl0ZW0sXG4gICAgICAgICAgICBub3JtYWxpemVkVmFsdWVUb1Bvc2l0aW9uKHNsaWRlck9wdHMsIGQuZnJhY3Rpb24pLFxuICAgICAgICAgICAgY29uc3RhbnRzLnRpY2tPZmZzZXQgK1xuICAgICAgICAgICAgICAgIHNsaWRlck9wdHMudGlja2xlbiArXG4gICAgICAgICAgICAgICAgLy8gcG9zaXRpb24gaXMgdGhlIGJhc2VsaW5lIG9mIHRoZSB0b3AgbGluZSBvZiB0ZXh0IG9ubHksIGV2ZW5cbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbGFiZWwgc3BhbnMgbXVsdGlwbGUgbGluZXNcbiAgICAgICAgICAgICAgICBzbGlkZXJPcHRzLmZvbnQuc2l6ZSAqIExJTkVfU1BBQ0lORyArXG4gICAgICAgICAgICAgICAgY29uc3RhbnRzLmxhYmVsT2Zmc2V0ICtcbiAgICAgICAgICAgICAgICBkaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0XG4gICAgICAgICk7XG4gICAgfSk7XG5cbn1cblxuZnVuY3Rpb24gaGFuZGxlSW5wdXQoZ2QsIHNsaWRlckdyb3VwLCBzbGlkZXJPcHRzLCBub3JtYWxpemVkUG9zaXRpb24sIGRvVHJhbnNpdGlvbikge1xuICAgIHZhciBxdWFudGl6ZWRQb3NpdGlvbiA9IE1hdGgucm91bmQobm9ybWFsaXplZFBvc2l0aW9uICogKHNsaWRlck9wdHMuX3N0ZXBDb3VudCAtIDEpKTtcbiAgICB2YXIgcXVhbnRpemVkSW5kZXggPSBzbGlkZXJPcHRzLl92aXNpYmxlU3RlcHNbcXVhbnRpemVkUG9zaXRpb25dLl9pbmRleDtcblxuICAgIGlmKHF1YW50aXplZEluZGV4ICE9PSBzbGlkZXJPcHRzLmFjdGl2ZSkge1xuICAgICAgICBzZXRBY3RpdmUoZ2QsIHNsaWRlckdyb3VwLCBzbGlkZXJPcHRzLCBxdWFudGl6ZWRJbmRleCwgdHJ1ZSwgZG9UcmFuc2l0aW9uKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldEFjdGl2ZShnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIGluZGV4LCBkb0NhbGxiYWNrLCBkb1RyYW5zaXRpb24pIHtcbiAgICB2YXIgcHJldmlvdXNBY3RpdmUgPSBzbGlkZXJPcHRzLmFjdGl2ZTtcbiAgICBzbGlkZXJPcHRzLmFjdGl2ZSA9IGluZGV4O1xuXG4gICAgLy8gZHVlIHRvIHRlbXBsYXRpbmcsIGl0J3MgcG9zc2libGUgdGhpcyBzbGlkZXIgZG9lc24ndCBldmVuIGV4aXN0IHlldFxuICAgIGFycmF5RWRpdG9yKGdkLmxheW91dCwgY29uc3RhbnRzLm5hbWUsIHNsaWRlck9wdHMpXG4gICAgICAgIC5hcHBseVVwZGF0ZSgnYWN0aXZlJywgaW5kZXgpO1xuXG4gICAgdmFyIHN0ZXAgPSBzbGlkZXJPcHRzLnN0ZXBzW3NsaWRlck9wdHMuYWN0aXZlXTtcblxuICAgIHNsaWRlckdyb3VwLmNhbGwoc2V0R3JpcFBvc2l0aW9uLCBzbGlkZXJPcHRzLCBkb1RyYW5zaXRpb24pO1xuICAgIHNsaWRlckdyb3VwLmNhbGwoZHJhd0N1cnJlbnRWYWx1ZSwgc2xpZGVyT3B0cyk7XG5cbiAgICBnZC5lbWl0KCdwbG90bHlfc2xpZGVyY2hhbmdlJywge1xuICAgICAgICBzbGlkZXI6IHNsaWRlck9wdHMsXG4gICAgICAgIHN0ZXA6IHNsaWRlck9wdHMuc3RlcHNbc2xpZGVyT3B0cy5hY3RpdmVdLFxuICAgICAgICBpbnRlcmFjdGlvbjogZG9DYWxsYmFjayxcbiAgICAgICAgcHJldmlvdXNBY3RpdmU6IHByZXZpb3VzQWN0aXZlXG4gICAgfSk7XG5cbiAgICBpZihzdGVwICYmIHN0ZXAubWV0aG9kICYmIGRvQ2FsbGJhY2spIHtcbiAgICAgICAgaWYoc2xpZGVyR3JvdXAuX25leHRNZXRob2QpIHtcbiAgICAgICAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgcXVldWVkIHVwIGFuIHVwZGF0ZSwganVzdCBvdmVyd3JpdGUgaXQgd2l0aCB0aGUgbW9zdCByZWNlbnQ6XG4gICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZC5zdGVwID0gc3RlcDtcbiAgICAgICAgICAgIHNsaWRlckdyb3VwLl9uZXh0TWV0aG9kLmRvQ2FsbGJhY2sgPSBkb0NhbGxiYWNrO1xuICAgICAgICAgICAgc2xpZGVyR3JvdXAuX25leHRNZXRob2QuZG9UcmFuc2l0aW9uID0gZG9UcmFuc2l0aW9uO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2xpZGVyR3JvdXAuX25leHRNZXRob2QgPSB7c3RlcDogc3RlcCwgZG9DYWxsYmFjazogZG9DYWxsYmFjaywgZG9UcmFuc2l0aW9uOiBkb1RyYW5zaXRpb259O1xuICAgICAgICAgICAgc2xpZGVyR3JvdXAuX25leHRNZXRob2RSYWYgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciBfc3RlcCA9IHNsaWRlckdyb3VwLl9uZXh0TWV0aG9kLnN0ZXA7XG4gICAgICAgICAgICAgICAgaWYoIV9zdGVwLm1ldGhvZCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgaWYoX3N0ZXAuZXhlY3V0ZSkge1xuICAgICAgICAgICAgICAgICAgICBQbG90cy5leGVjdXRlQVBJQ29tbWFuZChnZCwgX3N0ZXAubWV0aG9kLCBfc3RlcC5hcmdzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgc2xpZGVyR3JvdXAuX25leHRNZXRob2RSYWYgPSBudWxsO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGF0dGFjaEdyaXBFdmVudHMoaXRlbSwgZ2QsIHNsaWRlckdyb3VwKSB7XG4gICAgdmFyIG5vZGUgPSBzbGlkZXJHcm91cC5ub2RlKCk7XG4gICAgdmFyICRnZCA9IGQzLnNlbGVjdChnZCk7XG5cbiAgICAvLyBOQjogVGhpcyBpcyAqbm90KiB0aGUgc2FtZSBhcyBzbGlkZXJPcHRzIGl0c2VsZiEgVGhlc2UgY2FsbGJhY2tzXG4gICAgLy8gYXJlIGluIGEgY2xvc3VyZSBzbyB0aGlzIGFycmF5IHdvbid0IGFjdHVhbGx5IGJlIGNvcnJlY3QgaWYgdGhlXG4gICAgLy8gc3RlcHMgaGF2ZSBjaGFuZ2VkIHNpbmNlIHRoaXMgd2FzIGluaXRpYWxpemVkLiBUaGUgc2xpZGVyR3JvdXAsXG4gICAgLy8gaG93ZXZlciwgaGFzIG5vdCBjaGFuZ2VkIHNpbmNlIHRoYXQgKmlzKiB0aGUgc2xpZGVyLCBzbyBpdCBtdXN0XG4gICAgLy8gYmUgcHJlc2VudCB0byByZWNlaXZlIG1vdXNlIGV2ZW50cy5cbiAgICBmdW5jdGlvbiBnZXRTbGlkZXJPcHRzKCkge1xuICAgICAgICByZXR1cm4gc2xpZGVyR3JvdXAuZGF0YSgpWzBdO1xuICAgIH1cblxuICAgIGl0ZW0ub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgc2xpZGVyT3B0cyA9IGdldFNsaWRlck9wdHMoKTtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3NsaWRlcnN0YXJ0Jywge3NsaWRlcjogc2xpZGVyT3B0c30pO1xuXG4gICAgICAgIHZhciBncmlwID0gc2xpZGVyR3JvdXAuc2VsZWN0KCcuJyArIGNvbnN0YW50cy5ncmlwUmVjdENsYXNzKTtcblxuICAgICAgICBkMy5ldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZ3JpcC5jYWxsKENvbG9yLmZpbGwsIHNsaWRlck9wdHMuYWN0aXZlYmdjb2xvcik7XG5cbiAgICAgICAgdmFyIG5vcm1hbGl6ZWRQb3NpdGlvbiA9IHBvc2l0aW9uVG9Ob3JtYWxpemVkVmFsdWUoc2xpZGVyT3B0cywgZDMubW91c2Uobm9kZSlbMF0pO1xuICAgICAgICBoYW5kbGVJbnB1dChnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIG5vcm1hbGl6ZWRQb3NpdGlvbiwgdHJ1ZSk7XG4gICAgICAgIHNsaWRlck9wdHMuX2RyYWdnaW5nID0gdHJ1ZTtcblxuICAgICAgICAkZ2Qub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHNsaWRlck9wdHMgPSBnZXRTbGlkZXJPcHRzKCk7XG4gICAgICAgICAgICB2YXIgbm9ybWFsaXplZFBvc2l0aW9uID0gcG9zaXRpb25Ub05vcm1hbGl6ZWRWYWx1ZShzbGlkZXJPcHRzLCBkMy5tb3VzZShub2RlKVswXSk7XG4gICAgICAgICAgICBoYW5kbGVJbnB1dChnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIG5vcm1hbGl6ZWRQb3NpdGlvbiwgZmFsc2UpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkZ2Qub24oJ21vdXNldXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzbGlkZXJPcHRzID0gZ2V0U2xpZGVyT3B0cygpO1xuICAgICAgICAgICAgc2xpZGVyT3B0cy5fZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGdyaXAuY2FsbChDb2xvci5maWxsLCBzbGlkZXJPcHRzLmJnY29sb3IpO1xuICAgICAgICAgICAgJGdkLm9uKCdtb3VzZXVwJywgbnVsbCk7XG4gICAgICAgICAgICAkZ2Qub24oJ21vdXNlbW92ZScsIG51bGwpO1xuXG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfc2xpZGVyZW5kJywge1xuICAgICAgICAgICAgICAgIHNsaWRlcjogc2xpZGVyT3B0cyxcbiAgICAgICAgICAgICAgICBzdGVwOiBzbGlkZXJPcHRzLnN0ZXBzW3NsaWRlck9wdHMuYWN0aXZlXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBkcmF3VGlja3Moc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMpIHtcbiAgICB2YXIgdGljayA9IHNsaWRlckdyb3VwLnNlbGVjdEFsbCgncmVjdC4nICsgY29uc3RhbnRzLnRpY2tSZWN0Q2xhc3MpXG4gICAgICAgIC5kYXRhKHNsaWRlck9wdHMuX3Zpc2libGVTdGVwcyk7XG4gICAgdmFyIGRpbXMgPSBzbGlkZXJPcHRzLl9kaW1zO1xuXG4gICAgdGljay5lbnRlcigpLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy50aWNrUmVjdENsYXNzLCB0cnVlKTtcblxuICAgIHRpY2suZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdGljay5hdHRyKHtcbiAgICAgICAgd2lkdGg6IHNsaWRlck9wdHMudGlja3dpZHRoICsgJ3B4JyxcbiAgICAgICAgJ3NoYXBlLXJlbmRlcmluZyc6ICdjcmlzcEVkZ2VzJ1xuICAgIH0pO1xuXG4gICAgdGljay5lYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgdmFyIGlzTWFqb3IgPSBpICUgZGltcy5sYWJlbFN0cmlkZSA9PT0gMDtcbiAgICAgICAgdmFyIGl0ZW0gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgaXRlbVxuICAgICAgICAgICAgLmF0dHIoe2hlaWdodDogaXNNYWpvciA/IHNsaWRlck9wdHMudGlja2xlbiA6IHNsaWRlck9wdHMubWlub3J0aWNrbGVufSlcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGlzTWFqb3IgPyBzbGlkZXJPcHRzLnRpY2tjb2xvciA6IHNsaWRlck9wdHMudGlja2NvbG9yKTtcblxuICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShpdGVtLFxuICAgICAgICAgICAgbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBpIC8gKHNsaWRlck9wdHMuX3N0ZXBDb3VudCAtIDEpKSAtIDAuNSAqIHNsaWRlck9wdHMudGlja3dpZHRoLFxuICAgICAgICAgICAgKGlzTWFqb3IgPyBjb25zdGFudHMudGlja09mZnNldCA6IGNvbnN0YW50cy5taW5vclRpY2tPZmZzZXQpICsgZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodFxuICAgICAgICApO1xuICAgIH0pO1xuXG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVMYWJlbFN0ZXBzKHNsaWRlck9wdHMpIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgZGltcy5sYWJlbFN0ZXBzID0gW107XG4gICAgdmFyIG5zdGVwcyA9IHNsaWRlck9wdHMuX3N0ZXBDb3VudDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuc3RlcHM7IGkgKz0gZGltcy5sYWJlbFN0cmlkZSkge1xuICAgICAgICBkaW1zLmxhYmVsU3RlcHMucHVzaCh7XG4gICAgICAgICAgICBmcmFjdGlvbjogaSAvIChuc3RlcHMgLSAxKSxcbiAgICAgICAgICAgIHN0ZXA6IHNsaWRlck9wdHMuX3Zpc2libGVTdGVwc1tpXVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldEdyaXBQb3NpdGlvbihzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgZG9UcmFuc2l0aW9uKSB7XG4gICAgdmFyIGdyaXAgPSBzbGlkZXJHcm91cC5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5ncmlwUmVjdENsYXNzKTtcblxuICAgIHZhciBxdWFudGl6ZWRJbmRleCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNsaWRlck9wdHMuX3N0ZXBDb3VudDsgaSsrKSB7XG4gICAgICAgIGlmKHNsaWRlck9wdHMuX3Zpc2libGVTdGVwc1tpXS5faW5kZXggPT09IHNsaWRlck9wdHMuYWN0aXZlKSB7XG4gICAgICAgICAgICBxdWFudGl6ZWRJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB4ID0gbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBxdWFudGl6ZWRJbmRleCAvIChzbGlkZXJPcHRzLl9zdGVwQ291bnQgLSAxKSk7XG5cbiAgICAvLyBJZiB0aGlzIGlzIHRydWUsIHRoZW4gKnRoaXMgY29tcG9uZW50KiBpcyBhbHJlYWR5IGludm9raW5nIGl0cyBvd24gY29tbWFuZFxuICAgIC8vIGFuZCBoYXMgdHJpZ2dlcmVkIGl0cyBvd24gYW5pbWF0aW9uLlxuICAgIGlmKHNsaWRlck9wdHMuX2ludm9raW5nQ29tbWFuZCkgcmV0dXJuO1xuXG4gICAgdmFyIGVsID0gZ3JpcDtcbiAgICBpZihkb1RyYW5zaXRpb24gJiYgc2xpZGVyT3B0cy50cmFuc2l0aW9uLmR1cmF0aW9uID4gMCkge1xuICAgICAgICBlbCA9IGVsLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmR1cmF0aW9uKHNsaWRlck9wdHMudHJhbnNpdGlvbi5kdXJhdGlvbilcbiAgICAgICAgICAgIC5lYXNlKHNsaWRlck9wdHMudHJhbnNpdGlvbi5lYXNpbmcpO1xuICAgIH1cblxuICAgIC8vIERyYXdpbmcuc2V0VHJhbnNsYXRlIGRvZXNuJ3Qgd29yayBoZXJlIGJlY2FzdWUgb2YgdGhlIHRyYW5zaXRpb24gZHVjay10eXBpbmcuXG4gICAgLy8gSXQncyBhbHNvIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSB0aGVyZSBhcmUgbm8gb3RoZXIgdHJhbnNpdGlvbnMgdG8gcHJlc2VydmUuXG4gICAgZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgKHggLSBjb25zdGFudHMuZ3JpcFdpZHRoICogMC41KSArICcsJyArIChzbGlkZXJPcHRzLl9kaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0KSArICcpJyk7XG59XG5cbi8vIENvbnZlcnQgYSBudW1iZXIgZnJvbSBbMC0xXSB0byBhIHBpeGVsIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBzbGlkZXIgZ3JvdXAgY29udGFpbmVyOlxuZnVuY3Rpb24gbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBub3JtYWxpemVkUG9zaXRpb24pIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgcmV0dXJuIGRpbXMuaW5wdXRBcmVhU3RhcnQgKyBjb25zdGFudHMuc3RlcEluc2V0ICtcbiAgICAgICAgKGRpbXMuaW5wdXRBcmVhTGVuZ3RoIC0gMiAqIGNvbnN0YW50cy5zdGVwSW5zZXQpICogTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgbm9ybWFsaXplZFBvc2l0aW9uKSk7XG59XG5cbi8vIENvbnZlcnQgYSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgc2xpZGVyIGdyb3VwIHRvIGEgbnVibWVyIGluIFswLCAxXVxuZnVuY3Rpb24gcG9zaXRpb25Ub05vcm1hbGl6ZWRWYWx1ZShzbGlkZXJPcHRzLCBwb3NpdGlvbikge1xuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcbiAgICByZXR1cm4gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgKHBvc2l0aW9uIC0gY29uc3RhbnRzLnN0ZXBJbnNldCAtIGRpbXMuaW5wdXRBcmVhU3RhcnQpIC8gKGRpbXMuaW5wdXRBcmVhTGVuZ3RoIC0gMiAqIGNvbnN0YW50cy5zdGVwSW5zZXQgLSAyICogZGltcy5pbnB1dEFyZWFTdGFydCkpKTtcbn1cblxuZnVuY3Rpb24gZHJhd1RvdWNoUmVjdChzbGlkZXJHcm91cCwgZ2QsIHNsaWRlck9wdHMpIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgdmFyIHJlY3QgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWRlckdyb3VwLCAncmVjdCcsIGNvbnN0YW50cy5yYWlsVG91Y2hSZWN0Q2xhc3MsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jYWxsKGF0dGFjaEdyaXBFdmVudHMsIGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cylcbiAgICAgICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfSk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICB3aWR0aDogZGltcy5pbnB1dEFyZWFMZW5ndGgsXG4gICAgICAgIGhlaWdodDogTWF0aC5tYXgoZGltcy5pbnB1dEFyZWFXaWR0aCwgY29uc3RhbnRzLnRpY2tPZmZzZXQgKyBzbGlkZXJPcHRzLnRpY2tsZW4gKyBkaW1zLmxhYmVsSGVpZ2h0KVxuICAgIH0pXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIHNsaWRlck9wdHMuYmdjb2xvcilcbiAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAwKTtcblxuICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHJlY3QsIDAsIGRpbXMuY3VycmVudFZhbHVlVG90YWxIZWlnaHQpO1xufVxuXG5mdW5jdGlvbiBkcmF3UmFpbChzbGlkZXJHcm91cCwgc2xpZGVyT3B0cykge1xuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcbiAgICB2YXIgY29tcHV0ZWRMZW5ndGggPSBkaW1zLmlucHV0QXJlYUxlbmd0aCAtIGNvbnN0YW50cy5yYWlsSW5zZXQgKiAyO1xuICAgIHZhciByZWN0ID0gTGliLmVuc3VyZVNpbmdsZShzbGlkZXJHcm91cCwgJ3JlY3QnLCBjb25zdGFudHMucmFpbFJlY3RDbGFzcyk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICB3aWR0aDogY29tcHV0ZWRMZW5ndGgsXG4gICAgICAgIGhlaWdodDogY29uc3RhbnRzLnJhaWxXaWR0aCxcbiAgICAgICAgcng6IGNvbnN0YW50cy5yYWlsUmFkaXVzLFxuICAgICAgICByeTogY29uc3RhbnRzLnJhaWxSYWRpdXMsXG4gICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICB9KVxuICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgc2xpZGVyT3B0cy5ib3JkZXJjb2xvcilcbiAgICAuY2FsbChDb2xvci5maWxsLCBzbGlkZXJPcHRzLmJnY29sb3IpXG4gICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBzbGlkZXJPcHRzLmJvcmRlcndpZHRoICsgJ3B4Jyk7XG5cbiAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShyZWN0LFxuICAgICAgICBjb25zdGFudHMucmFpbEluc2V0LFxuICAgICAgICAoZGltcy5pbnB1dEFyZWFXaWR0aCAtIGNvbnN0YW50cy5yYWlsV2lkdGgpICogMC41ICsgZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodFxuICAgICk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiBjb25zdGFudHMubmFtZSxcblxuICAgIGxheW91dEF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiByZXF1aXJlKCcuL2RlZmF1bHRzJyksXG5cbiAgICBkcmF3OiByZXF1aXJlKCcuL2RyYXcnKVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGludGVyYWN0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBkcmF3OiBkcmF3XG59O1xuXG52YXIgbnVtU3RyaXBSRSA9IC8gW1hZXVswLTldKiAvO1xuXG4vKipcbiAqIFRpdGxlcyAtIChyZSlkcmF3IHRpdGxlcyBvbiB0aGUgYXhlcyBhbmQgcGxvdDpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkIC0gdGhlIGdyYXBoRGl2XG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVDbGFzcyAtIHRoZSBjc3MgY2xhc3Mgb2YgdGhpcyB0aXRsZVxuICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBob3cgYW5kIHdoYXQgdG8gZHJhd1xuICogICAgICBwcm9wQ29udGFpbmVyIC0gdGhlIGxheW91dCBvYmplY3QgY29udGFpbmluZyBgdGl0bGVgIGFuZCBgdGl0bGVmb250YFxuICogICAgICAgICAgYXR0cmlidXRlcyB0aGF0IGFwcGx5IHRvIHRoaXMgdGl0bGVcbiAqICAgICAgcHJvcE5hbWUgLSB0aGUgZnVsbCBuYW1lIG9mIHRoZSB0aXRsZSBwcm9wZXJ0eSAoZm9yIFBsb3RseS5yZWxheW91dClcbiAqICAgICAgW3RyYWNlSW5kZXhdIC0gaW5jbHVkZSBvbmx5IGlmIHRoaXMgcHJvcGVydHkgYXBwbGllcyB0byBvbmUgdHJhY2VcbiAqICAgICAgICAgIChzdWNoIGFzIGEgY29sb3JiYXIgdGl0bGUpIC0gdGhlbiBlZGl0aW5nIHBpcGVzIHRvIFBsb3RseS5yZXN0eWxlXG4gKiAgICAgICAgICBpbnN0ZWFkIG9mIFBsb3RseS5yZWxheW91dFxuICogICAgICBwbGFjZWhvbGRlciAtIHBsYWNlaG9sZGVyIHRleHQgZm9yIGFuIGVtcHR5IGVkaXRhYmxlIHRpdGxlXG4gKiAgICAgIFthdm9pZF0ge29iamVjdH0gLSBpbmNsdWRlIGlmIHRoaXMgdGl0bGUgc2hvdWxkIG1vdmUgdG8gYXZvaWQgb3RoZXIgZWxlbWVudHNcbiAqICAgICAgICAgIHNlbGVjdGlvbiAtIGQzIHNlbGVjdGlvbiBvZiBlbGVtZW50cyB0byBhdm9pZFxuICogICAgICAgICAgc2lkZSAtIHdoaWNoIGRpcmVjdGlvbiB0byBtb3ZlIGlmIHRoZXJlIGlzIGEgY29uZmxpY3RcbiAqICAgICAgICAgIFtvZmZzZXRMZWZ0XSAtIGlmIHRoZXNlIGVsZW1lbnRzIGFyZSBzdWJqZWN0IHRvIGEgdHJhbnNsYXRpb25cbiAqICAgICAgICAgICAgICB3cnQgdGhlIHRpdGxlIGVsZW1lbnRcbiAqICAgICAgICAgIFtvZmZzZXRUb3BdXG4gKiAgICAgIGF0dHJpYnV0ZXMge29iamVjdH0gLSBwb3NpdGlvbiBhbmQgYWxpZ25tZW50IGF0dHJpYnV0ZXNcbiAqICAgICAgICAgIHggLSBwaXhlbHNcbiAqICAgICAgICAgIHkgLSBwaXhlbHNcbiAqICAgICAgICAgIHRleHQtYW5jaG9yIC0gc3RhcnR8bWlkZGxlfGVuZFxuICogICAgICB0cmFuc2Zvcm0ge29iamVjdH0gLSBob3cgdG8gdHJhbnNmb3JtIHRoZSB0aXRsZSBhZnRlciBwb3NpdGlvbmluZ1xuICogICAgICAgICAgcm90YXRlIC0gZGVncmVlc1xuICogICAgICAgICAgb2Zmc2V0IC0gc2hpZnQgdXAvZG93biBpbiB0aGUgcm90YXRlZCBmcmFtZSAodW51c2VkPylcbiAqICAgICAgY29udGFpbmVyR3JvdXAgLSBpZiBhbiBzdmcgPGc+IGVsZW1lbnQgYWxyZWFkeSBleGlzdHMgdG8gaG9sZCB0aGlzXG4gKiAgICAgICAgICB0aXRsZSwgaW5jbHVkZSBoZXJlLiBPdGhlcndpc2UgaXQgd2lsbCBnbyBpbiBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXJcbiAqXG4gKiAgQHJldHVybiB7c2VsZWN0aW9ufSBkMyBzZWxlY3Rpb24gb2YgdGl0bGUgY29udGFpbmVyIGdyb3VwXG4gKi9cbmZ1bmN0aW9uIGRyYXcoZ2QsIHRpdGxlQ2xhc3MsIG9wdGlvbnMpIHtcbiAgICB2YXIgY29udCA9IG9wdGlvbnMucHJvcENvbnRhaW5lcjtcbiAgICB2YXIgcHJvcCA9IG9wdGlvbnMucHJvcE5hbWU7XG4gICAgdmFyIHBsYWNlaG9sZGVyID0gb3B0aW9ucy5wbGFjZWhvbGRlcjtcbiAgICB2YXIgdHJhY2VJbmRleCA9IG9wdGlvbnMudHJhY2VJbmRleDtcbiAgICB2YXIgYXZvaWQgPSBvcHRpb25zLmF2b2lkIHx8IHt9O1xuICAgIHZhciBhdHRyaWJ1dGVzID0gb3B0aW9ucy5hdHRyaWJ1dGVzO1xuICAgIHZhciB0cmFuc2Zvcm0gPSBvcHRpb25zLnRyYW5zZm9ybTtcbiAgICB2YXIgZ3JvdXAgPSBvcHRpb25zLmNvbnRhaW5lckdyb3VwO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdGl0bGVmb250ID0gY29udC50aXRsZWZvbnQgfHwge307XG4gICAgdmFyIGZvbnQgPSB0aXRsZWZvbnQuZmFtaWx5O1xuICAgIHZhciBmb250U2l6ZSA9IHRpdGxlZm9udC5zaXplO1xuICAgIHZhciBmb250Q29sb3IgPSB0aXRsZWZvbnQuY29sb3I7XG5cbiAgICB2YXIgb3BhY2l0eSA9IDE7XG4gICAgdmFyIGlzcGxhY2Vob2xkZXIgPSBmYWxzZTtcbiAgICB2YXIgdHh0ID0gKGNvbnQudGl0bGUgfHwgJycpLnRyaW0oKTtcblxuICAgIC8vIG9ubHkgbWFrZSB0aGlzIHRpdGxlIGVkaXRhYmxlIGlmIHdlIHBvc2l0aXZlbHkgaWRlbnRpZnkgaXRzIHByb3BlcnR5XG4gICAgLy8gYXMgb25lIHRoYXQgaGFzIGVkaXRpbmcgZW5hYmxlZC5cbiAgICB2YXIgZWRpdEF0dHI7XG4gICAgaWYocHJvcCA9PT0gJ3RpdGxlJykgZWRpdEF0dHIgPSAndGl0bGVUZXh0JztcbiAgICBlbHNlIGlmKHByb3AuaW5kZXhPZignYXhpcycpICE9PSAtMSkgZWRpdEF0dHIgPSAnYXhpc1RpdGxlVGV4dCc7XG4gICAgZWxzZSBpZihwcm9wLmluZGV4T2YoJ2NvbG9yYmFyJyAhPT0gLTEpKSBlZGl0QXR0ciA9ICdjb2xvcmJhclRpdGxlVGV4dCc7XG4gICAgdmFyIGVkaXRhYmxlID0gZ2QuX2NvbnRleHQuZWRpdHNbZWRpdEF0dHJdO1xuXG4gICAgaWYodHh0ID09PSAnJykgb3BhY2l0eSA9IDA7XG4gICAgLy8gbG9vayBmb3IgcGxhY2Vob2xkZXIgdGV4dCB3aGlsZSBzdHJpcHBpbmcgb3V0IG51bWJlcnMgZnJvbSBlZyBYMiwgWTNcbiAgICAvLyB0aGlzIGlzIGp1c3QgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCB0aGUgb2xkIHZlcnNpb24gdGhhdCBoYWRcbiAgICAvLyBcIkNsaWNrIHRvIGVudGVyIFgyIHRpdGxlXCIgYW5kIG1heSBoYXZlIGdvdHRlbiBzYXZlZCBpbiBzb21lIG9sZCBwbG90cyxcbiAgICAvLyB3ZSBkb24ndCB3YW50IHRoaXMgdG8gc2hvdyB1cCB3aGVuIHRoZXNlIGFyZSBkaXNwbGF5ZWQuXG4gICAgZWxzZSBpZih0eHQucmVwbGFjZShudW1TdHJpcFJFLCAnICUgJykgPT09IHBsYWNlaG9sZGVyLnJlcGxhY2UobnVtU3RyaXBSRSwgJyAlICcpKSB7XG4gICAgICAgIG9wYWNpdHkgPSAwLjI7XG4gICAgICAgIGlzcGxhY2Vob2xkZXIgPSB0cnVlO1xuICAgICAgICBpZighZWRpdGFibGUpIHR4dCA9ICcnO1xuICAgIH1cblxuICAgIHZhciBlbFNob3VsZEV4aXN0ID0gdHh0IHx8IGVkaXRhYmxlO1xuXG4gICAgaWYoIWdyb3VwKSB7XG4gICAgICAgIGdyb3VwID0gTGliLmVuc3VyZVNpbmdsZShmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIsICdnJywgJ2ctJyArIHRpdGxlQ2xhc3MpO1xuICAgIH1cblxuICAgIHZhciBlbCA9IGdyb3VwLnNlbGVjdEFsbCgndGV4dCcpXG4gICAgICAgIC5kYXRhKGVsU2hvdWxkRXhpc3QgPyBbMF0gOiBbXSk7XG4gICAgZWwuZW50ZXIoKS5hcHBlbmQoJ3RleHQnKTtcbiAgICBlbC50ZXh0KHR4dClcbiAgICAgICAgLy8gdGhpcyBpcyBoYWNreSwgYnV0IGNvbnZlcnRUb1RzcGFucyB1c2VzIHRoZSBjbGFzc1xuICAgICAgICAvLyB0byBkZXRlcm1pbmUgd2hldGhlciB0byByb3RhdGUgbWF0aEpheC4uLlxuICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIGNsZWFyIG91dCBhbnkgb2xkIGNsYXNzIGFuZCBwdXQgdGhlXG4gICAgICAgIC8vIGNvcnJlY3Qgb25lIChvbmx5IHJlbGV2YW50IGZvciBjb2xvcmJhcnMsIGF0IGxlYXN0XG4gICAgICAgIC8vIGZvciBub3cpIC0gaWUgZG9uJ3QgdXNlIC5jbGFzc2VkXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIHRpdGxlQ2xhc3MpO1xuICAgIGVsLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGlmKCFlbFNob3VsZEV4aXN0KSByZXR1cm4gZ3JvdXA7XG5cbiAgICBmdW5jdGlvbiB0aXRsZUxheW91dCh0aXRsZUVsKSB7XG4gICAgICAgIExpYi5zeW5jT3JBc3luYyhbZHJhd1RpdGxlLCBzY29vdFRpdGxlXSwgdGl0bGVFbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1RpdGxlKHRpdGxlRWwpIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybVZhbDtcblxuICAgICAgICBpZih0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybVZhbCA9ICcnO1xuICAgICAgICAgICAgaWYodHJhbnNmb3JtLnJvdGF0ZSkge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVZhbCArPSAncm90YXRlKCcgKyBbdHJhbnNmb3JtLnJvdGF0ZSwgYXR0cmlidXRlcy54LCBhdHRyaWJ1dGVzLnldICsgJyknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodHJhbnNmb3JtLm9mZnNldCkge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVZhbCArPSAndHJhbnNsYXRlKDAsICcgKyB0cmFuc2Zvcm0ub2Zmc2V0ICsgJyknO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhbnNmb3JtVmFsID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpdGxlRWwuYXR0cigndHJhbnNmb3JtJywgdHJhbnNmb3JtVmFsKTtcblxuICAgICAgICB0aXRsZUVsLnN0eWxlKHtcbiAgICAgICAgICAgICdmb250LWZhbWlseSc6IGZvbnQsXG4gICAgICAgICAgICAnZm9udC1zaXplJzogZDMucm91bmQoZm9udFNpemUsIDIpICsgJ3B4JyxcbiAgICAgICAgICAgIGZpbGw6IENvbG9yLnJnYihmb250Q29sb3IpLFxuICAgICAgICAgICAgb3BhY2l0eTogb3BhY2l0eSAqIENvbG9yLm9wYWNpdHkoZm9udENvbG9yKSxcbiAgICAgICAgICAgICdmb250LXdlaWdodCc6IFBsb3RzLmZvbnRXZWlnaHRcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoYXR0cmlidXRlcylcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzY29vdFRpdGxlKHRpdGxlRWxJbikge1xuICAgICAgICB2YXIgdGl0bGVHcm91cCA9IGQzLnNlbGVjdCh0aXRsZUVsSW4ubm9kZSgpLnBhcmVudE5vZGUpO1xuXG4gICAgICAgIGlmKGF2b2lkICYmIGF2b2lkLnNlbGVjdGlvbiAmJiBhdm9pZC5zaWRlICYmIHR4dCkge1xuICAgICAgICAgICAgdGl0bGVHcm91cC5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgICAgICAgICAgLy8gbW92ZSB0b3dhcmQgYXZvaWQuc2lkZSAoPSBsZWZ0LCByaWdodCwgdG9wLCBib3R0b20pIGlmIG5lZWRlZFxuICAgICAgICAgICAgLy8gY2FuIGluY2x1ZGUgcGFkIChwaXhlbHMsIGRlZmF1bHQgMilcbiAgICAgICAgICAgIHZhciBzaGlmdCA9IDA7XG4gICAgICAgICAgICB2YXIgYmFja3NpZGUgPSB7XG4gICAgICAgICAgICAgICAgbGVmdDogJ3JpZ2h0JyxcbiAgICAgICAgICAgICAgICByaWdodDogJ2xlZnQnLFxuICAgICAgICAgICAgICAgIHRvcDogJ2JvdHRvbScsXG4gICAgICAgICAgICAgICAgYm90dG9tOiAndG9wJ1xuICAgICAgICAgICAgfVthdm9pZC5zaWRlXTtcbiAgICAgICAgICAgIHZhciBzaGlmdFNpZ24gPSAoWydsZWZ0JywgJ3RvcCddLmluZGV4T2YoYXZvaWQuc2lkZSkgIT09IC0xKSA/XG4gICAgICAgICAgICAgICAgICAgIC0xIDogMTtcbiAgICAgICAgICAgIHZhciBwYWQgPSBpc051bWVyaWMoYXZvaWQucGFkKSA/IGF2b2lkLnBhZCA6IDI7XG4gICAgICAgICAgICB2YXIgdGl0bGViYiA9IERyYXdpbmcuYkJveCh0aXRsZUdyb3VwLm5vZGUoKSk7XG4gICAgICAgICAgICB2YXIgcGFwZXJiYiA9IHtcbiAgICAgICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgICAgICByaWdodDogZnVsbExheW91dC53aWR0aCxcbiAgICAgICAgICAgICAgICBib3R0b206IGZ1bGxMYXlvdXQuaGVpZ2h0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIG1heHNoaWZ0ID0gYXZvaWQubWF4U2hpZnQgfHwgKFxuICAgICAgICAgICAgICAgIChwYXBlcmJiW2F2b2lkLnNpZGVdIC0gdGl0bGViYlthdm9pZC5zaWRlXSkgKlxuICAgICAgICAgICAgICAgICgoYXZvaWQuc2lkZSA9PT0gJ2xlZnQnIHx8IGF2b2lkLnNpZGUgPT09ICd0b3AnKSA/IC0xIDogMSkpO1xuICAgICAgICAgICAgLy8gUHJldmVudCB0aGUgdGl0bGUgZ29pbmcgb2ZmIHRoZSBwYXBlclxuICAgICAgICAgICAgaWYobWF4c2hpZnQgPCAwKSBzaGlmdCA9IG1heHNoaWZ0O1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gc28gd2UgZG9uJ3QgaGF2ZSB0byBvZmZzZXQgZWFjaCBhdm9pZGVkIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgLy8gZ2l2ZSB0aGUgdGl0bGUgdGhlIG9wcG9zaXRlIG9mZnNldFxuICAgICAgICAgICAgICAgIHZhciBvZmZzZXRMZWZ0ID0gYXZvaWQub2Zmc2V0TGVmdCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBvZmZzZXRUb3AgPSBhdm9pZC5vZmZzZXRUb3AgfHwgMDtcbiAgICAgICAgICAgICAgICB0aXRsZWJiLmxlZnQgLT0gb2Zmc2V0TGVmdDtcbiAgICAgICAgICAgICAgICB0aXRsZWJiLnJpZ2h0IC09IG9mZnNldExlZnQ7XG4gICAgICAgICAgICAgICAgdGl0bGViYi50b3AgLT0gb2Zmc2V0VG9wO1xuICAgICAgICAgICAgICAgIHRpdGxlYmIuYm90dG9tIC09IG9mZnNldFRvcDtcblxuICAgICAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciBhIHNldCBvZiBlbGVtZW50cyAoYXZvaWQuc2VsZWN0aW9uKVxuICAgICAgICAgICAgICAgIC8vIHRvIGF2b2lkIGNvbGxpc2lvbnMgd2l0aFxuICAgICAgICAgICAgICAgIGF2b2lkLnNlbGVjdGlvbi5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXZvaWRiYiA9IERyYXdpbmcuYkJveCh0aGlzKTtcblxuICAgICAgICAgICAgICAgICAgICBpZihMaWIuYkJveEludGVyc2VjdCh0aXRsZWJiLCBhdm9pZGJiLCBwYWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGlmdCA9IE1hdGgubWF4KHNoaWZ0LCBzaGlmdFNpZ24gKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZvaWRiYlthdm9pZC5zaWRlXSAtIHRpdGxlYmJbYmFja3NpZGVdKSArIHBhZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzaGlmdCA9IE1hdGgubWluKG1heHNoaWZ0LCBzaGlmdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihzaGlmdCA+IDAgfHwgbWF4c2hpZnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNoaWZ0VGVtcGxhdGUgPSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IFstc2hpZnQsIDBdLFxuICAgICAgICAgICAgICAgICAgICByaWdodDogW3NoaWZ0LCAwXSxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiBbMCwgLXNoaWZ0XSxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiBbMCwgc2hpZnRdXG4gICAgICAgICAgICAgICAgfVthdm9pZC5zaWRlXTtcbiAgICAgICAgICAgICAgICB0aXRsZUdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIHNoaWZ0VGVtcGxhdGUgKyAnKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZWwuY2FsbCh0aXRsZUxheW91dCk7XG5cbiAgICBmdW5jdGlvbiBzZXRQbGFjZWhvbGRlcigpIHtcbiAgICAgICAgb3BhY2l0eSA9IDA7XG4gICAgICAgIGlzcGxhY2Vob2xkZXIgPSB0cnVlO1xuICAgICAgICBlbC50ZXh0KHBsYWNlaG9sZGVyKVxuICAgICAgICAgICAgLm9uKCdtb3VzZW92ZXIub3BhY2l0eScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAgICAgLmR1cmF0aW9uKGludGVyYWN0Q29uc3RhbnRzLlNIT1dfUExBQ0VIT0xERVIpLnN0eWxlKCdvcGFjaXR5JywgMSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdtb3VzZW91dC5vcGFjaXR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAuZHVyYXRpb24oaW50ZXJhY3RDb25zdGFudHMuSElERV9QTEFDRUhPTERFUikuc3R5bGUoJ29wYWNpdHknLCAwKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGVkaXRhYmxlKSB7XG4gICAgICAgIGlmKCF0eHQpIHNldFBsYWNlaG9sZGVyKCk7XG4gICAgICAgIGVsc2UgZWwub24oJy5vcGFjaXR5JywgbnVsbCk7XG5cbiAgICAgICAgZWwuY2FsbChzdmdUZXh0VXRpbHMubWFrZUVkaXRhYmxlLCB7Z2Q6IGdkfSlcbiAgICAgICAgICAgIC5vbignZWRpdCcsIGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgICAgICAgICBpZih0cmFjZUluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVzdHlsZScsIGdkLCBwcm9wLCB0ZXh0LCB0cmFjZUluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBwcm9wLCB0ZXh0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdjYW5jZWwnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQodGhpcy5hdHRyKCdkYXRhLXVuZm9ybWF0dGVkJykpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKHRpdGxlTGF5b3V0KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2lucHV0JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dChkIHx8ICcgJylcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgYXR0cmlidXRlcy54LCBhdHRyaWJ1dGVzLnkpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsLmNsYXNzZWQoJ2pzLXBsYWNlaG9sZGVyJywgaXNwbGFjZWhvbGRlcik7XG5cbiAgICByZXR1cm4gZ3JvdXA7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciBwYWRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3BhZF9hdHRyaWJ1dGVzJyk7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG5cbnZhciBidXR0b25zQXR0cnMgPSB0ZW1wbGF0ZWRBcnJheSgnYnV0dG9uJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBtZXRob2Q6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsncmVzdHlsZScsICdyZWxheW91dCcsICdhbmltYXRlJywgJ3VwZGF0ZScsICdza2lwJ10sXG4gICAgICAgIGRmbHQ6ICdyZXN0eWxlJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJnczoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknfSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55J30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueSd9XG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFiZWw6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleGVjdXRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHRlbXBsYXRlZEFycmF5KCd1cGRhdGVtZW51Jywge1xuICAgIF9hcnJheUF0dHJSZWdleHBzOiBbL151cGRhdGVtZW51c1xcWygwfFsxLTldWzAtOV0rKVxcXVxcLmJ1dHRvbnMvXSxcblxuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZHJvcGRvd24nLCAnYnV0dG9ucyddLFxuICAgICAgICBkZmx0OiAnZHJvcGRvd24nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGRpcmVjdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsZWZ0JywgJ3JpZ2h0JywgJ3VwJywgJ2Rvd24nXSxcbiAgICAgICAgZGZsdDogJ2Rvd24nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGFjdGl2ZToge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IC0xLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2hvd2FjdGl2ZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYnV0dG9uczogYnV0dG9uc0F0dHJzLFxuXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAtMixcbiAgICAgICAgbWF4OiAzLFxuICAgICAgICBkZmx0OiAtMC4wNSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgIGRmbHQ6ICdyaWdodCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICd0b3AnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHBhZDogZXh0ZW5kRmxhdCh7fSwgcGFkQXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5ib3JkZXJMaW5lLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9XG59KSwgJ2FycmF5ZHJhdycsICdmcm9tLXJvb3QnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gbGF5b3V0IGF0dHJpYnV0ZSBuYW1lXG4gICAgbmFtZTogJ3VwZGF0ZW1lbnVzJyxcblxuICAgIC8vIGNsYXNzIG5hbWVzXG4gICAgY29udGFpbmVyQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1jb250YWluZXInLFxuICAgIGhlYWRlckdyb3VwQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1oZWFkZXItZ3JvdXAnLFxuICAgIGhlYWRlckNsYXNzTmFtZTogJ3VwZGF0ZW1lbnUtaGVhZGVyJyxcbiAgICBoZWFkZXJBcnJvd0NsYXNzTmFtZTogJ3VwZGF0ZW1lbnUtaGVhZGVyLWFycm93JyxcbiAgICBkcm9wZG93bkJ1dHRvbkdyb3VwQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1kcm9wZG93bi1idXR0b24tZ3JvdXAnLFxuICAgIGRyb3Bkb3duQnV0dG9uQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1kcm9wZG93bi1idXR0b24nLFxuICAgIGJ1dHRvbkNsYXNzTmFtZTogJ3VwZGF0ZW1lbnUtYnV0dG9uJyxcbiAgICBpdGVtUmVjdENsYXNzTmFtZTogJ3VwZGF0ZW1lbnUtaXRlbS1yZWN0JyxcbiAgICBpdGVtVGV4dENsYXNzTmFtZTogJ3VwZGF0ZW1lbnUtaXRlbS10ZXh0JyxcblxuICAgIC8vIERPTSBhdHRyaWJ1dGUgbmFtZSBpbiBidXR0b24gZ3JvdXAga2VlcGluZyB0cmFja1xuICAgIC8vIG9mIGFjdGl2ZSB1cGRhdGUgbWVudVxuICAgIG1lbnVJbmRleEF0dHJOYW1lOiAndXBkYXRlbWVudS1hY3RpdmUtaW5kZXgnLFxuXG4gICAgLy8gaWQgcm9vdCBwYXNzIHRvIFBsb3RzLmF1dG9NYXJnaW5cbiAgICBhdXRvTWFyZ2luSWRSb290OiAndXBkYXRlbWVudS0nLFxuXG4gICAgLy8gb3B0aW9ucyB3aGVuICdhY3RpdmU6IC0xJ1xuICAgIGJsYW5rSGVhZGVyT3B0czogeyBsYWJlbDogJyAgJyB9LFxuXG4gICAgLy8gbWluIGl0ZW0gd2lkdGggLyBoZWlnaHRcbiAgICBtaW5XaWR0aDogMzAsXG4gICAgbWluSGVpZ2h0OiAzMCxcblxuICAgIC8vIHBhZGRpbmcgYXJvdW5kIGl0ZW0gdGV4dFxuICAgIHRleHRQYWRYOiAyNCxcbiAgICBhcnJvd1BhZFg6IDE2LFxuXG4gICAgLy8gaXRlbSByZWN0IHJhZGlpXG4gICAgcng6IDIsXG4gICAgcnk6IDIsXG5cbiAgICAvLyBpdGVtICB0ZXh0IHggb2Zmc2V0IG9mZiBsZWZ0IGVkZ2VcbiAgICB0ZXh0T2Zmc2V0WDogMTIsXG5cbiAgICAvLyBpdGVtICB0ZXh0IHkgb2Zmc2V0ICh3LnIudC4gbWlkZGxlKVxuICAgIHRleHRPZmZzZXRZOiAzLFxuXG4gICAgLy8gYXJyb3cgb2Zmc2V0IG9mZiByaWdodCBlZGdlXG4gICAgYXJyb3dPZmZzZXRYOiA0LFxuXG4gICAgLy8gZ2FwIGJldHdlZW4gaGVhZGVyIGFuZCBidXR0b25zXG4gICAgZ2FwQnV0dG9uSGVhZGVyOiA1LFxuXG4gICAgLy8gZ2FwIGJldHdlZW4gYmV0d2VlbiBidXR0b25zXG4gICAgZ2FwQnV0dG9uOiAyLFxuXG4gICAgLy8gY29sb3IgZ2l2ZW4gdG8gYWN0aXZlIGJ1dHRvbnNcbiAgICBhY3RpdmVDb2xvcjogJyNGNEZBRkYnLFxuXG4gICAgLy8gY29sb3IgZ2l2ZW4gdG8gaG92ZXJlZCBidXR0b25zXG4gICAgaG92ZXJDb2xvcjogJyNGNEZBRkYnLFxuXG4gICAgLy8gc3ltYm9sIGZvciBtZW51IG9wZW4gYXJyb3dcbiAgICBhcnJvd1N5bWJvbDoge1xuICAgICAgICBsZWZ0OiAn4peEJyxcbiAgICAgICAgcmlnaHQ6ICfilronLFxuICAgICAgICB1cDogJ+KWsicsXG4gICAgICAgIGRvd246ICfilrwnXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG52YXIgbmFtZSA9IGNvbnN0YW50cy5uYW1lO1xudmFyIGJ1dHRvbkF0dHJzID0gYXR0cmlidXRlcy5idXR0b25zO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gdXBkYXRlTWVudXNEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgdmFyIG9wdHMgPSB7XG4gICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogbWVudURlZmF1bHRzXG4gICAgfTtcblxuICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgb3B0cyk7XG59O1xuXG5mdW5jdGlvbiBtZW51RGVmYXVsdHMobWVudUluLCBtZW51T3V0LCBsYXlvdXRPdXQpIHtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKG1lbnVJbiwgbWVudU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGJ1dHRvbnMgPSBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKG1lbnVJbiwgbWVudU91dCwge1xuICAgICAgICBuYW1lOiAnYnV0dG9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogYnV0dG9uRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJywgYnV0dG9ucy5sZW5ndGggPiAwKTtcbiAgICBpZighdmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKCdhY3RpdmUnKTtcbiAgICBjb2VyY2UoJ2RpcmVjdGlvbicpO1xuICAgIGNvZXJjZSgndHlwZScpO1xuICAgIGNvZXJjZSgnc2hvd2FjdGl2ZScpO1xuXG4gICAgY29lcmNlKCd4Jyk7XG4gICAgY29lcmNlKCd5Jyk7XG4gICAgTGliLm5vbmVPckFsbChtZW51SW4sIG1lbnVPdXQsIFsneCcsICd5J10pO1xuXG4gICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgY29lcmNlKCd5YW5jaG9yJyk7XG5cbiAgICBjb2VyY2UoJ3BhZC50Jyk7XG4gICAgY29lcmNlKCdwYWQucicpO1xuICAgIGNvZXJjZSgncGFkLmInKTtcbiAgICBjb2VyY2UoJ3BhZC5sJyk7XG5cbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdmb250JywgbGF5b3V0T3V0LmZvbnQpO1xuXG4gICAgY29lcmNlKCdiZ2NvbG9yJywgbGF5b3V0T3V0LnBhcGVyX2JnY29sb3IpO1xuICAgIGNvZXJjZSgnYm9yZGVyY29sb3InKTtcbiAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG59XG5cbmZ1bmN0aW9uIGJ1dHRvbkRlZmF1bHRzKGJ1dHRvbkluLCBidXR0b25PdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShidXR0b25JbiwgYnV0dG9uT3V0LCBidXR0b25BdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnLFxuICAgICAgICAoYnV0dG9uSW4ubWV0aG9kID09PSAnc2tpcCcgfHwgQXJyYXkuaXNBcnJheShidXR0b25Jbi5hcmdzKSkpO1xuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdtZXRob2QnKTtcbiAgICAgICAgY29lcmNlKCdhcmdzJyk7XG4gICAgICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICAgICAgY29lcmNlKCdleGVjdXRlJyk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi9kcmF3aW5nJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgYW5jaG9yVXRpbHMgPSByZXF1aXJlKCcuLi9sZWdlbmQvYW5jaG9yX3V0aWxzJyk7XG52YXIgYXJyYXlFZGl0b3IgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykuYXJyYXlFZGl0b3I7XG5cbnZhciBMSU5FX1NQQUNJTkcgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuTElORV9TUEFDSU5HO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBTY3JvbGxCb3ggPSByZXF1aXJlKCcuL3Njcm9sbGJveCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBtZW51RGF0YSA9IExpYi5maWx0ZXJWaXNpYmxlKGZ1bGxMYXlvdXRbY29uc3RhbnRzLm5hbWVdKTtcblxuICAgIC8qIFVwZGF0ZSBtZW51IGRhdGEgaXMgYm91bmQgdG8gdGhlIGhlYWRlci1ncm91cC5cbiAgICAgKiBUaGUgaXRlbXMgaW4gdGhlIGhlYWRlciBncm91cCBhcmUgYWx3YXlzIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBVcG9uIGNsaWNraW5nIG9uIGEgaGVhZGVyIGl0cyBjb3JyZXNwb25kaW5nIGJ1dHRvblxuICAgICAqIGRhdGEgaXMgYm91bmQgdG8gdGhlIGJ1dHRvbi1ncm91cC5cbiAgICAgKlxuICAgICAqIFdlIGRyYXcgYWxsIGhlYWRlcnMgaW4gb25lIGdyb3VwIGJlZm9yZSBhbGwgYnV0dG9uc1xuICAgICAqIHNvIHRoYXQgdGhlIGJ1dHRvbnMgKmFsd2F5cyogYXBwZWFyIGFib3ZlIHRoZSBoZWFkZXJzLlxuICAgICAqXG4gICAgICogTm90ZSB0aGF0IG9ubHkgb25lIHNldCBvZiBidXR0b25zIGFyZSB2aXNpYmxlIGF0IG9uY2UuXG4gICAgICpcbiAgICAgKiA8ZyBjb250YWluZXIgLz5cbiAgICAgKlxuICAgICAqICAgICA8ZyBoZWFkZXItZ3JvdXAgLz5cbiAgICAgKiAgICAgICAgIDxnIGl0ZW0gaGVhZGVyIC8+XG4gICAgICogICAgICAgICA8dGV4dCBpdGVtIGhlYWRlci1hcnJvdyAvPlxuICAgICAqICAgICA8ZyBoZWFkZXItZ3JvdXAgLz5cbiAgICAgKiAgICAgICAgIDxnIGl0ZW0gaGVhZGVyIC8+XG4gICAgICogICAgICAgICA8dGV4dCBpdGVtIGhlYWRlci1hcnJvdyAvPlxuICAgICAqICAgICAuLi5cbiAgICAgKlxuICAgICAqICAgICA8ZyBidXR0b24tZ3JvdXAgLz5cbiAgICAgKiAgICAgICAgIDxnIGl0ZW0gYnV0dG9uIC8+XG4gICAgICogICAgICAgICA8ZyBpdGVtIGJ1dHRvbiAvPlxuICAgICAqICAgICAgICAgLi4uXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBjbGVhckF1dG9NYXJnaW4obWVudU9wdHMpIHtcbiAgICAgICAgUGxvdHMuYXV0b01hcmdpbihnZCwgYXV0b01hcmdpbklkKG1lbnVPcHRzKSk7XG4gICAgfVxuXG4gICAgLy8gZHJhdyB1cGRhdGUgbWVudSBjb250YWluZXJcbiAgICB2YXIgbWVudXMgPSBmdWxsTGF5b3V0Ll9tZW51bGF5ZXJcbiAgICAgICAgLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmNvbnRhaW5lckNsYXNzTmFtZSlcbiAgICAgICAgLmRhdGEobWVudURhdGEubGVuZ3RoID4gMCA/IFswXSA6IFtdKTtcblxuICAgIG1lbnVzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmNvbnRhaW5lckNsYXNzTmFtZSwgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCAncG9pbnRlcicpO1xuXG4gICAgbWVudXMuZXhpdCgpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIE1vc3QgY29tcG9uZW50cyBkb24ndCBuZWVkIHRvIGV4cGxpY2l0bHkgcmVtb3ZlIGF1dG9NYXJnaW4sIGJlY2F1c2VcbiAgICAgICAgLy8gbWFyZ2luUHVzaGVycyBkb2VzIHRoaXMgLSBidXQgdXBkYXRlbWVudSB1cGRhdGVzIGRvbid0IGdvIHRocm91Z2hcbiAgICAgICAgLy8gYSBmdWxsIHJlcGxvdCBzbyB3ZSBuZWVkIHRvIGV4cGxpY2l0bHkgcmVtb3ZlIGl0LlxuICAgICAgICAvLyBUaGlzIGlzIGZvciByZW1vdmluZyAqYWxsKiB1cGRhdGVtZW51cywgcmVtb3ZpbmcgaW5kaXZpZHVhbHMgaXNcbiAgICAgICAgLy8gaGFuZGxlZCBiZWxvdywgaW4gaGVhZGVyR3JvdXBzLmV4aXRcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmhlYWRlckdyb3VwQ2xhc3NOYW1lKVxuICAgICAgICAgICAgLmVhY2goY2xlYXJBdXRvTWFyZ2luKTtcbiAgICB9KS5yZW1vdmUoKTtcblxuICAgIC8vIHJldHVybiBlYXJseSBpZiBubyB1cGRhdGUgbWVudXMgYXJlIHZpc2libGVcbiAgICBpZihtZW51RGF0YS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIC8vIGpvaW4gaGVhZGVyIGdyb3VwXG4gICAgdmFyIGhlYWRlckdyb3VwcyA9IG1lbnVzLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmhlYWRlckdyb3VwQ2xhc3NOYW1lKVxuICAgICAgICAuZGF0YShtZW51RGF0YSwga2V5RnVuY3Rpb24pO1xuXG4gICAgaGVhZGVyR3JvdXBzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmhlYWRlckdyb3VwQ2xhc3NOYW1lLCB0cnVlKTtcblxuICAgIC8vIGRyYXcgZHJvcGRvd24gYnV0dG9uIGNvbnRhaW5lclxuICAgIHZhciBnQnV0dG9uID0gTGliLmVuc3VyZVNpbmdsZShtZW51cywgJ2cnLCBjb25zdGFudHMuZHJvcGRvd25CdXR0b25Hcm91cENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKTtcbiAgICB9KTtcblxuICAgIC8vIGZpbmQgZGltZW5zaW9ucyBiZWZvcmUgcGxvdHRpbmcgYW55dGhpbmcgKHRoaXMgbXV0YXRlcyBtZW51T3B0cylcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWVudURhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG1lbnVPcHRzID0gbWVudURhdGFbaV07XG4gICAgICAgIGZpbmREaW1lbnNpb25zKGdkLCBtZW51T3B0cyk7XG4gICAgfVxuXG4gICAgLy8gc2V0dXAgc2Nyb2xsYm94XG4gICAgdmFyIHNjcm9sbEJveElkID0gJ3VwZGF0ZW1lbnVzJyArIGZ1bGxMYXlvdXQuX3VpZCxcbiAgICAgICAgc2Nyb2xsQm94ID0gbmV3IFNjcm9sbEJveChnZCwgZ0J1dHRvbiwgc2Nyb2xsQm94SWQpO1xuXG4gICAgLy8gcmVtb3ZlIGV4aXRpbmcgaGVhZGVyLCByZW1vdmUgZHJvcHBlZCBidXR0b25zIGFuZCByZXNldCBtYXJnaW5zXG4gICAgaWYoaGVhZGVyR3JvdXBzLmVudGVyKCkuc2l6ZSgpKSB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSBnQnV0dG9uIGlzIG9uIHRvcCBvZiBhbGwgaGVhZGVyc1xuICAgICAgICBnQnV0dG9uLm5vZGUoKS5wYXJlbnROb2RlLmFwcGVuZENoaWxkKGdCdXR0b24ubm9kZSgpKTtcbiAgICAgICAgZ0J1dHRvbi5jYWxsKHJlbW92ZUFsbEJ1dHRvbnMpO1xuICAgIH1cblxuICAgIGhlYWRlckdyb3Vwcy5leGl0KCkuZWFjaChmdW5jdGlvbihtZW51T3B0cykge1xuICAgICAgICBnQnV0dG9uLmNhbGwocmVtb3ZlQWxsQnV0dG9ucyk7XG4gICAgICAgIGNsZWFyQXV0b01hcmdpbihtZW51T3B0cyk7XG4gICAgfSkucmVtb3ZlKCk7XG5cbiAgICAvLyBkcmF3IGhlYWRlcnMhXG4gICAgaGVhZGVyR3JvdXBzLmVhY2goZnVuY3Rpb24obWVudU9wdHMpIHtcbiAgICAgICAgdmFyIGdIZWFkZXIgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgdmFyIF9nQnV0dG9uID0gbWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJyA/IGdCdXR0b24gOiBudWxsO1xuICAgICAgICBQbG90cy5tYW5hZ2VDb21tYW5kT2JzZXJ2ZXIoZ2QsIG1lbnVPcHRzLCBtZW51T3B0cy5idXR0b25zLCBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICBzZXRBY3RpdmUoZ2QsIG1lbnVPcHRzLCBtZW51T3B0cy5idXR0b25zW2RhdGEuaW5kZXhdLCBnSGVhZGVyLCBfZ0J1dHRvbiwgc2Nyb2xsQm94LCBkYXRhLmluZGV4LCB0cnVlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJykge1xuICAgICAgICAgICAgZHJhd0hlYWRlcihnZCwgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBtZW51T3B0cyk7XG5cbiAgICAgICAgICAgIC8vIGlmIHRoaXMgbWVudSBpcyBhY3RpdmUsIHVwZGF0ZSB0aGUgZHJvcGRvd24gY29udGFpbmVyXG4gICAgICAgICAgICBpZihpc0FjdGl2ZShnQnV0dG9uLCBtZW51T3B0cykpIHtcbiAgICAgICAgICAgICAgICBkcmF3QnV0dG9ucyhnZCwgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBtZW51T3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkcmF3QnV0dG9ucyhnZCwgZ0hlYWRlciwgbnVsbCwgbnVsbCwgbWVudU9wdHMpO1xuICAgICAgICB9XG5cbiAgICB9KTtcbn07XG5cbi8vIE5vdGUgdGhhdCAnX2luZGV4JyBpcyBzZXQgYXQgdGhlIGRlZmF1bHQgc3RlcCxcbi8vIGl0IGNvcnJlc3BvbmRzIHRvIHRoZSBtZW51IGluZGV4IGluIHRoZSB1c2VyIGxheW91dCB1cGRhdGUgbWVudSBjb250YWluZXIuXG4vLyBCZWNhdXNlIGEgbWVudSBjYW4gYmUgc2V0IGludmlzaWJsZSxcbi8vIHRoaXMgaXMgYSBtb3JlICdjb25zaXN0ZW50JyBmaWVsZCB0aGFuIHRoZSBpbmRleCBpbiB0aGUgbWVudURhdGEuXG5mdW5jdGlvbiBrZXlGdW5jdGlvbihtZW51T3B0cykge1xuICAgIHJldHVybiBtZW51T3B0cy5faW5kZXg7XG59XG5cbmZ1bmN0aW9uIGlzRm9sZGVkKGdCdXR0b24pIHtcbiAgICByZXR1cm4gK2dCdXR0b24uYXR0cihjb25zdGFudHMubWVudUluZGV4QXR0ck5hbWUpID09PSAtMTtcbn1cblxuZnVuY3Rpb24gaXNBY3RpdmUoZ0J1dHRvbiwgbWVudU9wdHMpIHtcbiAgICByZXR1cm4gK2dCdXR0b24uYXR0cihjb25zdGFudHMubWVudUluZGV4QXR0ck5hbWUpID09PSBtZW51T3B0cy5faW5kZXg7XG59XG5cbmZ1bmN0aW9uIHNldEFjdGl2ZShnZCwgbWVudU9wdHMsIGJ1dHRvbk9wdHMsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgYnV0dG9uSW5kZXgsIGlzU2lsZW50VXBkYXRlKSB7XG4gICAgLy8gdXBkYXRlICdhY3RpdmUnIGF0dHJpYnV0ZSBpbiBtZW51T3B0c1xuICAgIG1lbnVPcHRzLmFjdGl2ZSA9IGJ1dHRvbkluZGV4O1xuXG4gICAgLy8gZHVlIHRvIHRlbXBsYXRpbmcsIGl0J3MgcG9zc2libGUgdGhpcyBzbGlkZXIgZG9lc24ndCBldmVuIGV4aXN0IHlldFxuICAgIGFycmF5RWRpdG9yKGdkLmxheW91dCwgY29uc3RhbnRzLm5hbWUsIG1lbnVPcHRzKVxuICAgICAgICAuYXBwbHlVcGRhdGUoJ2FjdGl2ZScsIGJ1dHRvbkluZGV4KTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdidXR0b25zJykge1xuICAgICAgICBkcmF3QnV0dG9ucyhnZCwgZ0hlYWRlciwgbnVsbCwgbnVsbCwgbWVudU9wdHMpO1xuICAgIH1cbiAgICBlbHNlIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgLy8gZm9sZCB1cCBidXR0b25zIGFuZCByZWRyYXcgaGVhZGVyXG4gICAgICAgIGdCdXR0b24uYXR0cihjb25zdGFudHMubWVudUluZGV4QXR0ck5hbWUsICctMScpO1xuXG4gICAgICAgIGRyYXdIZWFkZXIoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuXG4gICAgICAgIGlmKCFpc1NpbGVudFVwZGF0ZSkge1xuICAgICAgICAgICAgZHJhd0J1dHRvbnMoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3SGVhZGVyKGdkLCBnSGVhZGVyLCBnQnV0dG9uLCBzY3JvbGxCb3gsIG1lbnVPcHRzKSB7XG4gICAgdmFyIGhlYWRlciA9IExpYi5lbnN1cmVTaW5nbGUoZ0hlYWRlciwgJ2cnLCBjb25zdGFudHMuaGVhZGVyQ2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgIH0pO1xuXG4gICAgdmFyIGRpbXMgPSBtZW51T3B0cy5fZGltcztcbiAgICB2YXIgYWN0aXZlID0gbWVudU9wdHMuYWN0aXZlO1xuICAgIHZhciBoZWFkZXJPcHRzID0gbWVudU9wdHMuYnV0dG9uc1thY3RpdmVdIHx8IGNvbnN0YW50cy5ibGFua0hlYWRlck9wdHM7XG4gICAgdmFyIHBvc09wdHMgPSB7IHk6IG1lbnVPcHRzLnBhZC50LCB5UGFkOiAwLCB4OiBtZW51T3B0cy5wYWQubCwgeFBhZDogMCwgaW5kZXg6IDAgfTtcbiAgICB2YXIgcG9zaXRpb25PdmVycmlkZXMgPSB7XG4gICAgICAgIHdpZHRoOiBkaW1zLmhlYWRlcldpZHRoLFxuICAgICAgICBoZWlnaHQ6IGRpbXMuaGVhZGVySGVpZ2h0XG4gICAgfTtcblxuICAgIGhlYWRlclxuICAgICAgICAuY2FsbChkcmF3SXRlbSwgbWVudU9wdHMsIGhlYWRlck9wdHMsIGdkKVxuICAgICAgICAuY2FsbChzZXRJdGVtUG9zaXRpb24sIG1lbnVPcHRzLCBwb3NPcHRzLCBwb3NpdGlvbk92ZXJyaWRlcyk7XG5cbiAgICAvLyBkcmF3IGRyb3AgYXJyb3cgYXQgdGhlIHJpZ2h0IGVkZ2VcbiAgICB2YXIgYXJyb3cgPSBMaWIuZW5zdXJlU2luZ2xlKGdIZWFkZXIsICd0ZXh0JywgY29uc3RhbnRzLmhlYWRlckFycm93Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2xhc3NlZCgndXNlci1zZWxlY3Qtbm9uZScsIHRydWUpXG4gICAgICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCAnZW5kJylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgbWVudU9wdHMuZm9udClcbiAgICAgICAgICAgIC50ZXh0KGNvbnN0YW50cy5hcnJvd1N5bWJvbFttZW51T3B0cy5kaXJlY3Rpb25dKTtcbiAgICB9KTtcblxuICAgIGFycm93LmF0dHIoe1xuICAgICAgICB4OiBkaW1zLmhlYWRlcldpZHRoIC0gY29uc3RhbnRzLmFycm93T2Zmc2V0WCArIG1lbnVPcHRzLnBhZC5sLFxuICAgICAgICB5OiBkaW1zLmhlYWRlckhlaWdodCAvIDIgKyBjb25zdGFudHMudGV4dE9mZnNldFkgKyBtZW51T3B0cy5wYWQudFxuICAgIH0pO1xuXG4gICAgaGVhZGVyLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICBnQnV0dG9uLmNhbGwocmVtb3ZlQWxsQnV0dG9ucyxcbiAgICAgICAgICAgIFN0cmluZyhpc0FjdGl2ZShnQnV0dG9uLCBtZW51T3B0cykgPyAtMSA6IG1lbnVPcHRzLl9pbmRleClcbiAgICAgICAgKTtcblxuICAgICAgICBkcmF3QnV0dG9ucyhnZCwgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBtZW51T3B0cyk7XG4gICAgfSk7XG5cbiAgICBoZWFkZXIub24oJ21vdXNlb3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICBoZWFkZXIuY2FsbChzdHlsZU9uTW91c2VPdmVyKTtcbiAgICB9KTtcblxuICAgIGhlYWRlci5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaGVhZGVyLmNhbGwoc3R5bGVPbk1vdXNlT3V0LCBtZW51T3B0cyk7XG4gICAgfSk7XG5cbiAgICAvLyB0cmFuc2xhdGUgaGVhZGVyIGdyb3VwXG4gICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoZ0hlYWRlciwgZGltcy5seCwgZGltcy5seSk7XG59XG5cbmZ1bmN0aW9uIGRyYXdCdXR0b25zKGdkLCBnSGVhZGVyLCBnQnV0dG9uLCBzY3JvbGxCb3gsIG1lbnVPcHRzKSB7XG4gICAgLy8gSWYgdGhpcyBpcyBhIHNldCBvZiBidXR0b25zLCBzZXQgcG9pbnRlciBldmVudHMgPSBhbGwgc2luY2Ugd2UgcGxheVxuICAgIC8vIHNvbWUgbWlub3IgZ2FtZXMgd2l0aCB3aGljaCBjb250YWluZXIgaXMgd2hpY2ggaW4gb3JkZXIgdG8gc2ltcGxpZnlcbiAgICAvLyB0aGUgZHJhd2luZyBvZiAqZWl0aGVyKiBidXR0b25zIG9yIG1lbnVzXG4gICAgaWYoIWdCdXR0b24pIHtcbiAgICAgICAgZ0J1dHRvbiA9IGdIZWFkZXI7XG4gICAgICAgIGdCdXR0b24uYXR0cigncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfVxuXG4gICAgdmFyIGJ1dHRvbkRhdGEgPSAoIWlzRm9sZGVkKGdCdXR0b24pIHx8IG1lbnVPcHRzLnR5cGUgPT09ICdidXR0b25zJykgP1xuICAgICAgICBtZW51T3B0cy5idXR0b25zIDpcbiAgICAgICAgW107XG5cbiAgICB2YXIga2xhc3MgPSBtZW51T3B0cy50eXBlID09PSAnZHJvcGRvd24nID8gY29uc3RhbnRzLmRyb3Bkb3duQnV0dG9uQ2xhc3NOYW1lIDogY29uc3RhbnRzLmJ1dHRvbkNsYXNzTmFtZTtcblxuICAgIHZhciBidXR0b25zID0gZ0J1dHRvbi5zZWxlY3RBbGwoJ2cuJyArIGtsYXNzKVxuICAgICAgICAuZGF0YShMaWIuZmlsdGVyVmlzaWJsZShidXR0b25EYXRhKSk7XG5cbiAgICB2YXIgZW50ZXIgPSBidXR0b25zLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoa2xhc3MsIHRydWUpO1xuXG4gICAgdmFyIGV4aXQgPSBidXR0b25zLmV4aXQoKTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgZW50ZXIuYXR0cignb3BhY2l0eScsICcwJylcbiAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5hdHRyKCdvcGFjaXR5JywgJzEnKTtcblxuICAgICAgICBleGl0LnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAucmVtb3ZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZXhpdC5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICB2YXIgeDAgPSAwO1xuICAgIHZhciB5MCA9IDA7XG4gICAgdmFyIGRpbXMgPSBtZW51T3B0cy5fZGltcztcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd1cCcsICdkb3duJ10uaW5kZXhPZihtZW51T3B0cy5kaXJlY3Rpb24pICE9PSAtMTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgeTAgPSBkaW1zLmhlYWRlckhlaWdodCArIGNvbnN0YW50cy5nYXBCdXR0b25IZWFkZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4MCA9IGRpbXMuaGVhZGVyV2lkdGggKyBjb25zdGFudHMuZ2FwQnV0dG9uSGVhZGVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJyAmJiBtZW51T3B0cy5kaXJlY3Rpb24gPT09ICd1cCcpIHtcbiAgICAgICAgeTAgPSAtY29uc3RhbnRzLmdhcEJ1dHRvbkhlYWRlciArIGNvbnN0YW50cy5nYXBCdXR0b24gLSBkaW1zLm9wZW5IZWlnaHQ7XG4gICAgfVxuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJyAmJiBtZW51T3B0cy5kaXJlY3Rpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICB4MCA9IC1jb25zdGFudHMuZ2FwQnV0dG9uSGVhZGVyICsgY29uc3RhbnRzLmdhcEJ1dHRvbiAtIGRpbXMub3BlbldpZHRoO1xuICAgIH1cblxuICAgIHZhciBwb3NPcHRzID0ge1xuICAgICAgICB4OiBkaW1zLmx4ICsgeDAgKyBtZW51T3B0cy5wYWQubCxcbiAgICAgICAgeTogZGltcy5seSArIHkwICsgbWVudU9wdHMucGFkLnQsXG4gICAgICAgIHlQYWQ6IGNvbnN0YW50cy5nYXBCdXR0b24sXG4gICAgICAgIHhQYWQ6IGNvbnN0YW50cy5nYXBCdXR0b24sXG4gICAgICAgIGluZGV4OiAwLFxuICAgIH07XG5cbiAgICB2YXIgc2Nyb2xsQm94UG9zaXRpb24gPSB7XG4gICAgICAgIGw6IHBvc09wdHMueCArIG1lbnVPcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICB0OiBwb3NPcHRzLnkgKyBtZW51T3B0cy5ib3JkZXJ3aWR0aFxuICAgIH07XG5cbiAgICBidXR0b25zLmVhY2goZnVuY3Rpb24oYnV0dG9uT3B0cywgYnV0dG9uSW5kZXgpIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBidXR0b25cbiAgICAgICAgICAgIC5jYWxsKGRyYXdJdGVtLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ2QpXG4gICAgICAgICAgICAuY2FsbChzZXRJdGVtUG9zaXRpb24sIG1lbnVPcHRzLCBwb3NPcHRzKTtcblxuICAgICAgICBidXR0b24ub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBza2lwIGBkcmFnZW5kYCBldmVudHNcbiAgICAgICAgICAgIGlmKGQzLmV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHJldHVybjtcblxuICAgICAgICAgICAgc2V0QWN0aXZlKGdkLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBidXR0b25JbmRleCk7XG5cbiAgICAgICAgICAgIGlmKGJ1dHRvbk9wdHMuZXhlY3V0ZSkge1xuICAgICAgICAgICAgICAgIFBsb3RzLmV4ZWN1dGVBUElDb21tYW5kKGdkLCBidXR0b25PcHRzLm1ldGhvZCwgYnV0dG9uT3B0cy5hcmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2J1dHRvbmNsaWNrZWQnLCB7bWVudTogbWVudU9wdHMsIGJ1dHRvbjogYnV0dG9uT3B0cywgYWN0aXZlOiBtZW51T3B0cy5hY3RpdmV9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYnV0dG9uLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGJ1dHRvbi5jYWxsKHN0eWxlT25Nb3VzZU92ZXIpO1xuICAgICAgICB9KTtcblxuICAgICAgICBidXR0b24ub24oJ21vdXNlb3V0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBidXR0b24uY2FsbChzdHlsZU9uTW91c2VPdXQsIG1lbnVPcHRzKTtcbiAgICAgICAgICAgIGJ1dHRvbnMuY2FsbChzdHlsZUJ1dHRvbnMsIG1lbnVPcHRzKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBidXR0b25zLmNhbGwoc3R5bGVCdXR0b25zLCBtZW51T3B0cyk7XG5cbiAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLncgPSBNYXRoLm1heChkaW1zLm9wZW5XaWR0aCwgZGltcy5oZWFkZXJXaWR0aCk7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLmggPSBwb3NPcHRzLnkgLSBzY3JvbGxCb3hQb3NpdGlvbi50O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2Nyb2xsQm94UG9zaXRpb24udyA9IHBvc09wdHMueCAtIHNjcm9sbEJveFBvc2l0aW9uLmw7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLmggPSBNYXRoLm1heChkaW1zLm9wZW5IZWlnaHQsIGRpbXMuaGVhZGVySGVpZ2h0KTtcbiAgICB9XG5cbiAgICBzY3JvbGxCb3hQb3NpdGlvbi5kaXJlY3Rpb24gPSBtZW51T3B0cy5kaXJlY3Rpb247XG5cbiAgICBpZihzY3JvbGxCb3gpIHtcbiAgICAgICAgaWYoYnV0dG9ucy5zaXplKCkpIHtcbiAgICAgICAgICAgIGRyYXdTY3JvbGxCb3goZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMsIHNjcm9sbEJveFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGhpZGVTY3JvbGxCb3goc2Nyb2xsQm94KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhd1Njcm9sbEJveChnZCwgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBtZW51T3B0cywgcG9zaXRpb24pIHtcbiAgICAvLyBlbmFibGUgdGhlIHNjcm9sbGJveFxuICAgIHZhciBkaXJlY3Rpb24gPSBtZW51T3B0cy5kaXJlY3Rpb247XG4gICAgdmFyIGlzVmVydGljYWwgPSAoZGlyZWN0aW9uID09PSAndXAnIHx8IGRpcmVjdGlvbiA9PT0gJ2Rvd24nKTtcbiAgICB2YXIgZGltcyA9IG1lbnVPcHRzLl9kaW1zO1xuXG4gICAgdmFyIGFjdGl2ZSA9IG1lbnVPcHRzLmFjdGl2ZSxcbiAgICAgICAgdHJhbnNsYXRlWCwgdHJhbnNsYXRlWSxcbiAgICAgICAgaTtcbiAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHRyYW5zbGF0ZVkgPSAwO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBhY3RpdmU7IGkrKykge1xuICAgICAgICAgICAgdHJhbnNsYXRlWSArPSBkaW1zLmhlaWdodHNbaV0gKyBjb25zdGFudHMuZ2FwQnV0dG9uO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0cmFuc2xhdGVYID0gMDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWN0aXZlOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVggKz0gZGltcy53aWR0aHNbaV0gKyBjb25zdGFudHMuZ2FwQnV0dG9uO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2Nyb2xsQm94LmVuYWJsZShwb3NpdGlvbiwgdHJhbnNsYXRlWCwgdHJhbnNsYXRlWSk7XG5cbiAgICBpZihzY3JvbGxCb3guaGJhcikge1xuICAgICAgICBzY3JvbGxCb3guaGJhclxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuYXR0cignb3BhY2l0eScsICcxJyk7XG4gICAgfVxuXG4gICAgaWYoc2Nyb2xsQm94LnZiYXIpIHtcbiAgICAgICAgc2Nyb2xsQm94LnZiYXJcbiAgICAgICAgICAgIC5hdHRyKCdvcGFjaXR5JywgJzAnKVxuICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMScpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaGlkZVNjcm9sbEJveChzY3JvbGxCb3gpIHtcbiAgICB2YXIgaGFzSEJhciA9ICEhc2Nyb2xsQm94LmhiYXIsXG4gICAgICAgIGhhc1ZCYXIgPSAhIXNjcm9sbEJveC52YmFyO1xuXG4gICAgaWYoaGFzSEJhcikge1xuICAgICAgICBzY3JvbGxCb3guaGJhclxuICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaGFzSEJhciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmKCFoYXNWQmFyKSBzY3JvbGxCb3guZGlzYWJsZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYoaGFzVkJhcikge1xuICAgICAgICBzY3JvbGxCb3gudmJhclxuICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaGFzVkJhciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmKCFoYXNIQmFyKSBzY3JvbGxCb3guZGlzYWJsZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3SXRlbShpdGVtLCBtZW51T3B0cywgaXRlbU9wdHMsIGdkKSB7XG4gICAgaXRlbS5jYWxsKGRyYXdJdGVtUmVjdCwgbWVudU9wdHMpXG4gICAgICAgIC5jYWxsKGRyYXdJdGVtVGV4dCwgbWVudU9wdHMsIGl0ZW1PcHRzLCBnZCk7XG59XG5cbmZ1bmN0aW9uIGRyYXdJdGVtUmVjdChpdGVtLCBtZW51T3B0cykge1xuICAgIHZhciByZWN0ID0gTGliLmVuc3VyZVNpbmdsZShpdGVtLCAncmVjdCcsIGNvbnN0YW50cy5pdGVtUmVjdENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgcng6IGNvbnN0YW50cy5yeCxcbiAgICAgICAgICAgIHJ5OiBjb25zdGFudHMucnksXG4gICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcmVjdC5jYWxsKENvbG9yLnN0cm9rZSwgbWVudU9wdHMuYm9yZGVyY29sb3IpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIG1lbnVPcHRzLmJnY29sb3IpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgbWVudU9wdHMuYm9yZGVyd2lkdGggKyAncHgnKTtcbn1cblxuZnVuY3Rpb24gZHJhd0l0ZW1UZXh0KGl0ZW0sIG1lbnVPcHRzLCBpdGVtT3B0cywgZ2QpIHtcbiAgICB2YXIgdGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoaXRlbSwgJ3RleHQnLCBjb25zdGFudHMuaXRlbVRleHRDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jbGFzc2VkKCd1c2VyLXNlbGVjdC1ub25lJywgdHJ1ZSlcbiAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiAnc3RhcnQnLFxuICAgICAgICAgICAgICAgICdkYXRhLW5vdGV4JzogMVxuICAgICAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXh0LmNhbGwoRHJhd2luZy5mb250LCBtZW51T3B0cy5mb250KVxuICAgICAgICAudGV4dChpdGVtT3B0cy5sYWJlbClcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xufVxuXG5mdW5jdGlvbiBzdHlsZUJ1dHRvbnMoYnV0dG9ucywgbWVudU9wdHMpIHtcbiAgICB2YXIgYWN0aXZlID0gbWVudU9wdHMuYWN0aXZlO1xuXG4gICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKGJ1dHRvbk9wdHMsIGkpIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBpZihpID09PSBhY3RpdmUgJiYgbWVudU9wdHMuc2hvd2FjdGl2ZSkge1xuICAgICAgICAgICAgYnV0dG9uLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLml0ZW1SZWN0Q2xhc3NOYW1lKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGNvbnN0YW50cy5hY3RpdmVDb2xvcik7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc3R5bGVPbk1vdXNlT3ZlcihpdGVtKSB7XG4gICAgaXRlbS5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5pdGVtUmVjdENsYXNzTmFtZSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgY29uc3RhbnRzLmhvdmVyQ29sb3IpO1xufVxuXG5mdW5jdGlvbiBzdHlsZU9uTW91c2VPdXQoaXRlbSwgbWVudU9wdHMpIHtcbiAgICBpdGVtLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLml0ZW1SZWN0Q2xhc3NOYW1lKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBtZW51T3B0cy5iZ2NvbG9yKTtcbn1cblxuLy8gZmluZCBpdGVtIGRpbWVuc2lvbnMgKHRoaXMgbXV0YXRlcyBtZW51T3B0cylcbmZ1bmN0aW9uIGZpbmREaW1lbnNpb25zKGdkLCBtZW51T3B0cykge1xuICAgIHZhciBkaW1zID0gbWVudU9wdHMuX2RpbXMgPSB7XG4gICAgICAgIHdpZHRoMTogMCxcbiAgICAgICAgaGVpZ2h0MTogMCxcbiAgICAgICAgaGVpZ2h0czogW10sXG4gICAgICAgIHdpZHRoczogW10sXG4gICAgICAgIHRvdGFsV2lkdGg6IDAsXG4gICAgICAgIHRvdGFsSGVpZ2h0OiAwLFxuICAgICAgICBvcGVuV2lkdGg6IDAsXG4gICAgICAgIG9wZW5IZWlnaHQ6IDAsXG4gICAgICAgIGx4OiAwLFxuICAgICAgICBseTogMFxuICAgIH07XG5cbiAgICB2YXIgZmFrZUJ1dHRvbnMgPSBEcmF3aW5nLnRlc3Rlci5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5kcm9wZG93bkJ1dHRvbkNsYXNzTmFtZSlcbiAgICAgICAgLmRhdGEoTGliLmZpbHRlclZpc2libGUobWVudU9wdHMuYnV0dG9ucykpO1xuXG4gICAgZmFrZUJ1dHRvbnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjb25zdGFudHMuZHJvcGRvd25CdXR0b25DbGFzc05hbWUsIHRydWUpO1xuXG4gICAgdmFyIGlzVmVydGljYWwgPSBbJ3VwJywgJ2Rvd24nXS5pbmRleE9mKG1lbnVPcHRzLmRpcmVjdGlvbikgIT09IC0xO1xuXG4gICAgLy8gbG9vcCBvdmVyIGZha2UgYnV0dG9ucyB0byBmaW5kIHdpZHRoIC8gaGVpZ2h0XG4gICAgZmFrZUJ1dHRvbnMuZWFjaChmdW5jdGlvbihidXR0b25PcHRzLCBpKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgYnV0dG9uLmNhbGwoZHJhd0l0ZW0sIG1lbnVPcHRzLCBidXR0b25PcHRzLCBnZCk7XG5cbiAgICAgICAgdmFyIHRleHQgPSBidXR0b24uc2VsZWN0KCcuJyArIGNvbnN0YW50cy5pdGVtVGV4dENsYXNzTmFtZSk7XG5cbiAgICAgICAgLy8gd2lkdGggaXMgZ2l2ZW4gYnkgbWF4IHdpZHRoIG9mIGFsbCBidXR0b25zXG4gICAgICAgIHZhciB0V2lkdGggPSB0ZXh0Lm5vZGUoKSAmJiBEcmF3aW5nLmJCb3godGV4dC5ub2RlKCkpLndpZHRoO1xuICAgICAgICB2YXIgd0VmZiA9IE1hdGgubWF4KHRXaWR0aCArIGNvbnN0YW50cy50ZXh0UGFkWCwgY29uc3RhbnRzLm1pbldpZHRoKTtcblxuICAgICAgICAvLyBoZWlnaHQgaXMgZGV0ZXJtaW5lZCBieSBpdGVtIHRleHRcbiAgICAgICAgdmFyIHRIZWlnaHQgPSBtZW51T3B0cy5mb250LnNpemUgKiBMSU5FX1NQQUNJTkc7XG4gICAgICAgIHZhciB0TGluZXMgPSBzdmdUZXh0VXRpbHMubGluZUNvdW50KHRleHQpO1xuICAgICAgICB2YXIgaEVmZiA9IE1hdGgubWF4KHRIZWlnaHQgKiB0TGluZXMsIGNvbnN0YW50cy5taW5IZWlnaHQpICsgY29uc3RhbnRzLnRleHRPZmZzZXRZO1xuXG4gICAgICAgIGhFZmYgPSBNYXRoLmNlaWwoaEVmZik7XG4gICAgICAgIHdFZmYgPSBNYXRoLmNlaWwod0VmZik7XG5cbiAgICAgICAgLy8gU3RvcmUgcGVyLWl0ZW0gc2l6ZXMgc2luY2UgYSByb3cgb2YgaG9yaXpvbnRhbCBidXR0b25zLCBmb3IgZXhhbXBsZSxcbiAgICAgICAgLy8gZG9uJ3QgYWxsIG5lZWQgdG8gYmUgdGhlIHNhbWUgd2lkdGg6XG4gICAgICAgIGRpbXMud2lkdGhzW2ldID0gd0VmZjtcbiAgICAgICAgZGltcy5oZWlnaHRzW2ldID0gaEVmZjtcblxuICAgICAgICAvLyBIZWlnaHQgYW5kIHdpZHRoIG9mIGluZGl2aWR1YWwgZWxlbWVudDpcbiAgICAgICAgZGltcy5oZWlnaHQxID0gTWF0aC5tYXgoZGltcy5oZWlnaHQxLCBoRWZmKTtcbiAgICAgICAgZGltcy53aWR0aDEgPSBNYXRoLm1heChkaW1zLndpZHRoMSwgd0VmZik7XG5cbiAgICAgICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgZGltcy50b3RhbFdpZHRoID0gTWF0aC5tYXgoZGltcy50b3RhbFdpZHRoLCB3RWZmKTtcbiAgICAgICAgICAgIGRpbXMub3BlbldpZHRoID0gZGltcy50b3RhbFdpZHRoO1xuICAgICAgICAgICAgZGltcy50b3RhbEhlaWdodCArPSBoRWZmICsgY29uc3RhbnRzLmdhcEJ1dHRvbjtcbiAgICAgICAgICAgIGRpbXMub3BlbkhlaWdodCArPSBoRWZmICsgY29uc3RhbnRzLmdhcEJ1dHRvbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRpbXMudG90YWxXaWR0aCArPSB3RWZmICsgY29uc3RhbnRzLmdhcEJ1dHRvbjtcbiAgICAgICAgICAgIGRpbXMub3BlbldpZHRoICs9IHdFZmYgKyBjb25zdGFudHMuZ2FwQnV0dG9uO1xuICAgICAgICAgICAgZGltcy50b3RhbEhlaWdodCA9IE1hdGgubWF4KGRpbXMudG90YWxIZWlnaHQsIGhFZmYpO1xuICAgICAgICAgICAgZGltcy5vcGVuSGVpZ2h0ID0gZGltcy50b3RhbEhlaWdodDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICBkaW1zLnRvdGFsSGVpZ2h0IC09IGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGltcy50b3RhbFdpZHRoIC09IGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgfVxuXG5cbiAgICBkaW1zLmhlYWRlcldpZHRoID0gZGltcy53aWR0aDEgKyBjb25zdGFudHMuYXJyb3dQYWRYO1xuICAgIGRpbXMuaGVhZGVySGVpZ2h0ID0gZGltcy5oZWlnaHQxO1xuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJykge1xuICAgICAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgICAgICBkaW1zLndpZHRoMSArPSBjb25zdGFudHMuYXJyb3dQYWRYO1xuICAgICAgICAgICAgZGltcy50b3RhbEhlaWdodCA9IGRpbXMuaGVpZ2h0MTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRpbXMudG90YWxXaWR0aCA9IGRpbXMud2lkdGgxO1xuICAgICAgICB9XG4gICAgICAgIGRpbXMudG90YWxXaWR0aCArPSBjb25zdGFudHMuYXJyb3dQYWRYO1xuICAgIH1cblxuICAgIGZha2VCdXR0b25zLnJlbW92ZSgpO1xuXG4gICAgdmFyIHBhZGRlZFdpZHRoID0gZGltcy50b3RhbFdpZHRoICsgbWVudU9wdHMucGFkLmwgKyBtZW51T3B0cy5wYWQucjtcbiAgICB2YXIgcGFkZGVkSGVpZ2h0ID0gZGltcy50b3RhbEhlaWdodCArIG1lbnVPcHRzLnBhZC50ICsgbWVudU9wdHMucGFkLmI7XG5cbiAgICB2YXIgZ3JhcGhTaXplID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemU7XG4gICAgZGltcy5seCA9IGdyYXBoU2l6ZS5sICsgZ3JhcGhTaXplLncgKiBtZW51T3B0cy54O1xuICAgIGRpbXMubHkgPSBncmFwaFNpemUudCArIGdyYXBoU2l6ZS5oICogKDEgLSBtZW51T3B0cy55KTtcblxuICAgIHZhciB4YW5jaG9yID0gJ2xlZnQnO1xuICAgIGlmKGFuY2hvclV0aWxzLmlzUmlnaHRBbmNob3IobWVudU9wdHMpKSB7XG4gICAgICAgIGRpbXMubHggLT0gcGFkZGVkV2lkdGg7XG4gICAgICAgIHhhbmNob3IgPSAncmlnaHQnO1xuICAgIH1cbiAgICBpZihhbmNob3JVdGlscy5pc0NlbnRlckFuY2hvcihtZW51T3B0cykpIHtcbiAgICAgICAgZGltcy5seCAtPSBwYWRkZWRXaWR0aCAvIDI7XG4gICAgICAgIHhhbmNob3IgPSAnY2VudGVyJztcbiAgICB9XG5cbiAgICB2YXIgeWFuY2hvciA9ICd0b3AnO1xuICAgIGlmKGFuY2hvclV0aWxzLmlzQm90dG9tQW5jaG9yKG1lbnVPcHRzKSkge1xuICAgICAgICBkaW1zLmx5IC09IHBhZGRlZEhlaWdodDtcbiAgICAgICAgeWFuY2hvciA9ICdib3R0b20nO1xuICAgIH1cbiAgICBpZihhbmNob3JVdGlscy5pc01pZGRsZUFuY2hvcihtZW51T3B0cykpIHtcbiAgICAgICAgZGltcy5seSAtPSBwYWRkZWRIZWlnaHQgLyAyO1xuICAgICAgICB5YW5jaG9yID0gJ21pZGRsZSc7XG4gICAgfVxuXG4gICAgZGltcy50b3RhbFdpZHRoID0gTWF0aC5jZWlsKGRpbXMudG90YWxXaWR0aCk7XG4gICAgZGltcy50b3RhbEhlaWdodCA9IE1hdGguY2VpbChkaW1zLnRvdGFsSGVpZ2h0KTtcbiAgICBkaW1zLmx4ID0gTWF0aC5yb3VuZChkaW1zLmx4KTtcbiAgICBkaW1zLmx5ID0gTWF0aC5yb3VuZChkaW1zLmx5KTtcblxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIGF1dG9NYXJnaW5JZChtZW51T3B0cyksIHtcbiAgICAgICAgeDogbWVudU9wdHMueCxcbiAgICAgICAgeTogbWVudU9wdHMueSxcbiAgICAgICAgbDogcGFkZGVkV2lkdGggKiAoe3JpZ2h0OiAxLCBjZW50ZXI6IDAuNX1beGFuY2hvcl0gfHwgMCksXG4gICAgICAgIHI6IHBhZGRlZFdpZHRoICogKHtsZWZ0OiAxLCBjZW50ZXI6IDAuNX1beGFuY2hvcl0gfHwgMCksXG4gICAgICAgIGI6IHBhZGRlZEhlaWdodCAqICh7dG9wOiAxLCBtaWRkbGU6IDAuNX1beWFuY2hvcl0gfHwgMCksXG4gICAgICAgIHQ6IHBhZGRlZEhlaWdodCAqICh7Ym90dG9tOiAxLCBtaWRkbGU6IDAuNX1beWFuY2hvcl0gfHwgMClcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYXV0b01hcmdpbklkKG1lbnVPcHRzKSB7XG4gICAgcmV0dXJuIGNvbnN0YW50cy5hdXRvTWFyZ2luSWRSb290ICsgbWVudU9wdHMuX2luZGV4O1xufVxuXG4vLyBzZXQgaXRlbSBwb3NpdGlvbnMgKG11dGF0ZXMgcG9zT3B0cylcbmZ1bmN0aW9uIHNldEl0ZW1Qb3NpdGlvbihpdGVtLCBtZW51T3B0cywgcG9zT3B0cywgb3ZlcnJpZGVPcHRzKSB7XG4gICAgb3ZlcnJpZGVPcHRzID0gb3ZlcnJpZGVPcHRzIHx8IHt9O1xuICAgIHZhciByZWN0ID0gaXRlbS5zZWxlY3QoJy4nICsgY29uc3RhbnRzLml0ZW1SZWN0Q2xhc3NOYW1lKTtcbiAgICB2YXIgdGV4dCA9IGl0ZW0uc2VsZWN0KCcuJyArIGNvbnN0YW50cy5pdGVtVGV4dENsYXNzTmFtZSk7XG4gICAgdmFyIGJvcmRlcldpZHRoID0gbWVudU9wdHMuYm9yZGVyd2lkdGg7XG4gICAgdmFyIGluZGV4ID0gcG9zT3B0cy5pbmRleDtcbiAgICB2YXIgZGltcyA9IG1lbnVPcHRzLl9kaW1zO1xuXG4gICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoaXRlbSwgYm9yZGVyV2lkdGggKyBwb3NPcHRzLngsIGJvcmRlcldpZHRoICsgcG9zT3B0cy55KTtcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd1cCcsICdkb3duJ10uaW5kZXhPZihtZW51T3B0cy5kaXJlY3Rpb24pICE9PSAtMTtcbiAgICB2YXIgZmluYWxIZWlnaHQgPSBvdmVycmlkZU9wdHMuaGVpZ2h0IHx8IChpc1ZlcnRpY2FsID8gZGltcy5oZWlnaHRzW2luZGV4XSA6IGRpbXMuaGVpZ2h0MSk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICB3aWR0aDogb3ZlcnJpZGVPcHRzLndpZHRoIHx8IChpc1ZlcnRpY2FsID8gZGltcy53aWR0aDEgOiBkaW1zLndpZHRoc1tpbmRleF0pLFxuICAgICAgICBoZWlnaHQ6IGZpbmFsSGVpZ2h0XG4gICAgfSk7XG5cbiAgICB2YXIgdEhlaWdodCA9IG1lbnVPcHRzLmZvbnQuc2l6ZSAqIExJTkVfU1BBQ0lORztcbiAgICB2YXIgdExpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0ZXh0KTtcbiAgICB2YXIgc3Bhbk9mZnNldCA9ICgodExpbmVzIC0gMSkgKiB0SGVpZ2h0IC8gMik7XG5cbiAgICBzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0KHRleHQsIGNvbnN0YW50cy50ZXh0T2Zmc2V0WCxcbiAgICAgICAgZmluYWxIZWlnaHQgLyAyIC0gc3Bhbk9mZnNldCArIGNvbnN0YW50cy50ZXh0T2Zmc2V0WSk7XG5cbiAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHBvc09wdHMueSArPSBkaW1zLmhlaWdodHNbaW5kZXhdICsgcG9zT3B0cy55UGFkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBvc09wdHMueCArPSBkaW1zLndpZHRoc1tpbmRleF0gKyBwb3NPcHRzLnhQYWQ7XG4gICAgfVxuXG4gICAgcG9zT3B0cy5pbmRleCsrO1xufVxuXG5mdW5jdGlvbiByZW1vdmVBbGxCdXR0b25zKGdCdXR0b24sIG5ld01lbnVJbmRleEF0dHIpIHtcbiAgICBnQnV0dG9uXG4gICAgICAgIC5hdHRyKGNvbnN0YW50cy5tZW51SW5kZXhBdHRyTmFtZSwgbmV3TWVudUluZGV4QXR0ciB8fCAnLTEnKVxuICAgICAgICAuc2VsZWN0QWxsKCdnLicgKyBjb25zdGFudHMuZHJvcGRvd25CdXR0b25DbGFzc05hbWUpLnJlbW92ZSgpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNjcm9sbEJveDtcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vZHJhd2luZycpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbi8qKlxuICogSGVscGVyIGNsYXNzIHRvIHNldHVwIGEgc2Nyb2xsIGJveFxuICpcbiAqIEBjbGFzc1xuICogQHBhcmFtICAgICAgICAgICBnZCAgICAgICAgICBQbG90bHkncyBncmFwaCBkaXZcbiAqIEBwYXJhbSAgICAgICAgICAgY29udGFpbmVyICAgQ29udGFpbmVyIHRvIGJlIHNjcm9sbC1ib3hlZCAoYXMgYSBEMyBzZWxlY3Rpb24pXG4gKiBAcGFyYW0ge3N0cmluZ30gIGlkICAgICAgICAgIElkIGZvciB0aGUgY2xpcCBwYXRoIHRvIGltcGxlbWVudCB0aGUgc2Nyb2xsIGJveFxuICovXG5mdW5jdGlvbiBTY3JvbGxCb3goZ2QsIGNvbnRhaW5lciwgaWQpIHtcbiAgICB0aGlzLmdkID0gZ2Q7XG4gICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgdGhpcy5pZCA9IGlkO1xuXG4gICAgLy8gU2VlIFNjcm9sbEJveC5wcm90b3R5cGUuZW5hYmxlIGZvciBmdXJ0aGVyIGRlZmluaXRpb25cbiAgICB0aGlzLnBvc2l0aW9uID0gbnVsbDsgIC8vIHNjcm9sbGJveCBwb3NpdGlvblxuICAgIHRoaXMudHJhbnNsYXRlWCA9IG51bGw7ICAvLyBzY3JvbGxib3ggaG9yaXpvbnRhbCB0cmFuc2xhdGlvblxuICAgIHRoaXMudHJhbnNsYXRlWSA9IG51bGw7ICAvLyBzY3JvbGxib3ggdmVydGljYWwgdHJhbnNsYXRpb25cbiAgICB0aGlzLmhiYXIgPSBudWxsOyAgLy8gaG9yaXpvbnRhbCBzY3JvbGxiYXIgRDMgc2VsZWN0aW9uXG4gICAgdGhpcy52YmFyID0gbnVsbDsgIC8vIHZlcnRpY2FsIHNjcm9sbGJhciBEMyBzZWxlY3Rpb25cblxuICAgIC8vIDxyZWN0PiBlbGVtZW50IHRvIGNhcHR1cmUgcG9pbnRlciBldmVudHNcbiAgICB0aGlzLmJnID0gdGhpcy5jb250YWluZXIuc2VsZWN0QWxsKCdyZWN0LnNjcm9sbGJveC1iZycpLmRhdGEoWzBdKTtcblxuICAgIHRoaXMuYmcuZXhpdCgpXG4gICAgICAgIC5vbignLmRyYWcnLCBudWxsKVxuICAgICAgICAub24oJ3doZWVsJywgbnVsbClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgdGhpcy5iZy5lbnRlcigpLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKCdzY3JvbGxib3gtYmcnLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpXG4gICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIHdpZHRoOiAwLFxuICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgIH0pO1xufVxuXG4vLyBzY3JvbGwgYmFyIGRpbWVuc2lvbnNcblNjcm9sbEJveC5iYXJXaWR0aCA9IDI7XG5TY3JvbGxCb3guYmFyTGVuZ3RoID0gMjA7XG5TY3JvbGxCb3guYmFyUmFkaXVzID0gMjtcblNjcm9sbEJveC5iYXJQYWQgPSAxO1xuU2Nyb2xsQm94LmJhckNvbG9yID0gJyM4MDhCQTQnO1xuXG4vKipcbiAqIElmIG5lZWRlZCwgc2V0dXAgYSBjbGlwIHBhdGggYW5kIHNjcm9sbGJhcnNcbiAqXG4gKiBAbWV0aG9kXG4gKiBAcGFyYW0ge09iamVjdH0gIHBvc2l0aW9uXG4gKiBAcGFyYW0ge251bWJlcn0gIHBvc2l0aW9uLmwgIExlZnQgc2lkZSBwb3NpdGlvbiAoaW4gcGl4ZWxzKVxuICogQHBhcmFtIHtudW1iZXJ9ICBwb3NpdGlvbi50ICBUb3Agc2lkZSAoaW4gcGl4ZWxzKVxuICogQHBhcmFtIHtudW1iZXJ9ICBwb3NpdGlvbi53ICBXaWR0aCAoaW4gcGl4ZWxzKVxuICogQHBhcmFtIHtudW1iZXJ9ICBwb3NpdGlvbi5oICBIZWlnaHQgKGluIHBpeGVscylcbiAqIEBwYXJhbSB7c3RyaW5nfSAgW3Bvc2l0aW9uLmRpcmVjdGlvbj0nZG93biddXG4gKiAgICAgICAgICAgICAgICAgIEVpdGhlciAnZG93bicsICdsZWZ0JywgJ3JpZ2h0JyBvciAndXAnXG4gKiBAcGFyYW0ge251bWJlcn0gIFt0cmFuc2xhdGVYPTBdICBIb3Jpem9udGFsIG9mZnNldCAoaW4gcGl4ZWxzKVxuICogQHBhcmFtIHtudW1iZXJ9ICBbdHJhbnNsYXRlWT0wXSAgVmVydGljYWwgb2Zmc2V0IChpbiBwaXhlbHMpXG4gKi9cblNjcm9sbEJveC5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gZW5hYmxlKHBvc2l0aW9uLCB0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSB0aGlzLmdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBmdWxsV2lkdGggPSBmdWxsTGF5b3V0LndpZHRoLFxuICAgICAgICBmdWxsSGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG5cbiAgICAvLyBjb21wdXRlIHBvc2l0aW9uIG9mIHNjcm9sbGJveFxuICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcblxuICAgIHZhciBsID0gdGhpcy5wb3NpdGlvbi5sLFxuICAgICAgICB3ID0gdGhpcy5wb3NpdGlvbi53LFxuICAgICAgICB0ID0gdGhpcy5wb3NpdGlvbi50LFxuICAgICAgICBoID0gdGhpcy5wb3NpdGlvbi5oLFxuICAgICAgICBkaXJlY3Rpb24gPSB0aGlzLnBvc2l0aW9uLmRpcmVjdGlvbixcbiAgICAgICAgaXNEb3duID0gKGRpcmVjdGlvbiA9PT0gJ2Rvd24nKSxcbiAgICAgICAgaXNMZWZ0ID0gKGRpcmVjdGlvbiA9PT0gJ2xlZnQnKSxcbiAgICAgICAgaXNSaWdodCA9IChkaXJlY3Rpb24gPT09ICdyaWdodCcpLFxuICAgICAgICBpc1VwID0gKGRpcmVjdGlvbiA9PT0gJ3VwJyksXG4gICAgICAgIGJveFcgPSB3LFxuICAgICAgICBib3hIID0gaCxcbiAgICAgICAgYm94TCwgYm94UixcbiAgICAgICAgYm94VCwgYm94QjtcblxuICAgIGlmKCFpc0Rvd24gJiYgIWlzTGVmdCAmJiAhaXNSaWdodCAmJiAhaXNVcCkge1xuICAgICAgICB0aGlzLnBvc2l0aW9uLmRpcmVjdGlvbiA9ICdkb3duJztcbiAgICAgICAgaXNEb3duID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgaXNWZXJ0aWNhbCA9IGlzRG93biB8fCBpc1VwO1xuICAgIGlmKGlzVmVydGljYWwpIHtcbiAgICAgICAgYm94TCA9IGw7XG4gICAgICAgIGJveFIgPSBib3hMICsgYm94VztcblxuICAgICAgICBpZihpc0Rvd24pIHtcbiAgICAgICAgICAgIC8vIGFuY2hvciB0byB0b3Agc2lkZVxuICAgICAgICAgICAgYm94VCA9IHQ7XG4gICAgICAgICAgICBib3hCID0gTWF0aC5taW4oYm94VCArIGJveEgsIGZ1bGxIZWlnaHQpO1xuICAgICAgICAgICAgYm94SCA9IGJveEIgLSBib3hUO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gYW5jaG9yIHRvIGJvdHRvbSBzaWRlXG4gICAgICAgICAgICBib3hCID0gdCArIGJveEg7XG4gICAgICAgICAgICBib3hUID0gTWF0aC5tYXgoYm94QiAtIGJveEgsIDApO1xuICAgICAgICAgICAgYm94SCA9IGJveEIgLSBib3hUO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBib3hUID0gdDtcbiAgICAgICAgYm94QiA9IGJveFQgKyBib3hIO1xuXG4gICAgICAgIGlmKGlzTGVmdCkge1xuICAgICAgICAgICAgLy8gYW5jaG9yIHRvIHJpZ2h0IHNpZGVcbiAgICAgICAgICAgIGJveFIgPSBsICsgYm94VztcbiAgICAgICAgICAgIGJveEwgPSBNYXRoLm1heChib3hSIC0gYm94VywgMCk7XG4gICAgICAgICAgICBib3hXID0gYm94UiAtIGJveEw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBhbmNob3IgdG8gbGVmdCBzaWRlXG4gICAgICAgICAgICBib3hMID0gbDtcbiAgICAgICAgICAgIGJveFIgPSBNYXRoLm1pbihib3hMICsgYm94VywgZnVsbFdpZHRoKTtcbiAgICAgICAgICAgIGJveFcgPSBib3hSIC0gYm94TDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX2JveCA9IHtcbiAgICAgICAgbDogYm94TCxcbiAgICAgICAgdDogYm94VCxcbiAgICAgICAgdzogYm94VyxcbiAgICAgICAgaDogYm94SFxuICAgIH07XG5cbiAgICAvLyBjb21wdXRlIHBvc2l0aW9uIG9mIGhvcml6b250YWwgc2Nyb2xsIGJhclxuICAgIHZhciBuZWVkc0hvcml6b250YWxTY3JvbGxCYXIgPSAodyA+IGJveFcpLFxuICAgICAgICBoYmFyVyA9IFNjcm9sbEJveC5iYXJMZW5ndGggKyAyICogU2Nyb2xsQm94LmJhclBhZCxcbiAgICAgICAgaGJhckggPSBTY3JvbGxCb3guYmFyV2lkdGggKyAyICogU2Nyb2xsQm94LmJhclBhZCxcbiAgICAgICAgLy8gZHJhdyBob3Jpem9udGFsIHNjcm9sbGJhciBvbiB0aGUgYm90dG9tIHNpZGVcbiAgICAgICAgaGJhckwgPSBsLFxuICAgICAgICBoYmFyVCA9IHQgKyBoO1xuXG4gICAgaWYoaGJhclQgKyBoYmFySCA+IGZ1bGxIZWlnaHQpIGhiYXJUID0gZnVsbEhlaWdodCAtIGhiYXJIO1xuXG4gICAgdmFyIGhiYXIgPSB0aGlzLmNvbnRhaW5lci5zZWxlY3RBbGwoJ3JlY3Quc2Nyb2xsYmFyLWhvcml6b250YWwnKS5kYXRhKFxuICAgICAgICAgICAgKG5lZWRzSG9yaXpvbnRhbFNjcm9sbEJhcikgPyBbMF0gOiBbXSk7XG5cbiAgICBoYmFyLmV4aXQoKVxuICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgaGJhci5lbnRlcigpLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKCdzY3JvbGxiYXItaG9yaXpvbnRhbCcsIHRydWUpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIFNjcm9sbEJveC5iYXJDb2xvcik7XG5cbiAgICBpZihuZWVkc0hvcml6b250YWxTY3JvbGxCYXIpIHtcbiAgICAgICAgdGhpcy5oYmFyID0gaGJhci5hdHRyKHtcbiAgICAgICAgICAgICdyeCc6IFNjcm9sbEJveC5iYXJSYWRpdXMsXG4gICAgICAgICAgICAncnknOiBTY3JvbGxCb3guYmFyUmFkaXVzLFxuICAgICAgICAgICAgJ3gnOiBoYmFyTCxcbiAgICAgICAgICAgICd5JzogaGJhclQsXG4gICAgICAgICAgICAnd2lkdGgnOiBoYmFyVyxcbiAgICAgICAgICAgICdoZWlnaHQnOiBoYmFySFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBoYmFyIGNlbnRlciBtb3ZlcyBiZXR3ZWVuIGhiYXJYTWluIGFuZCBoYmFyWE1pbiArIGhiYXJUcmFuc2xhdGVNYXhcbiAgICAgICAgdGhpcy5faGJhclhNaW4gPSBoYmFyTCArIGhiYXJXIC8gMjtcbiAgICAgICAgdGhpcy5faGJhclRyYW5zbGF0ZU1heCA9IGJveFcgLSBoYmFyVztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmhiYXI7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9oYmFyWE1pbjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXg7XG4gICAgfVxuXG4gICAgLy8gY29tcHV0ZSBwb3NpdGlvbiBvZiB2ZXJ0aWNhbCBzY3JvbGwgYmFyXG4gICAgdmFyIG5lZWRzVmVydGljYWxTY3JvbGxCYXIgPSAoaCA+IGJveEgpLFxuICAgICAgICB2YmFyVyA9IFNjcm9sbEJveC5iYXJXaWR0aCArIDIgKiBTY3JvbGxCb3guYmFyUGFkLFxuICAgICAgICB2YmFySCA9IFNjcm9sbEJveC5iYXJMZW5ndGggKyAyICogU2Nyb2xsQm94LmJhclBhZCxcbiAgICAgICAgLy8gZHJhdyB2ZXJ0aWNhbCBzY3JvbGxiYXIgb24gdGhlIHJpZ2h0IHNpZGVcbiAgICAgICAgdmJhckwgPSBsICsgdyxcbiAgICAgICAgdmJhclQgPSB0O1xuXG4gICAgaWYodmJhckwgKyB2YmFyVyA+IGZ1bGxXaWR0aCkgdmJhckwgPSBmdWxsV2lkdGggLSB2YmFyVztcblxuICAgIHZhciB2YmFyID0gdGhpcy5jb250YWluZXIuc2VsZWN0QWxsKCdyZWN0LnNjcm9sbGJhci12ZXJ0aWNhbCcpLmRhdGEoXG4gICAgICAgICAgICAobmVlZHNWZXJ0aWNhbFNjcm9sbEJhcikgPyBbMF0gOiBbXSk7XG5cbiAgICB2YmFyLmV4aXQoKVxuICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgdmJhci5lbnRlcigpLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKCdzY3JvbGxiYXItdmVydGljYWwnLCB0cnVlKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBTY3JvbGxCb3guYmFyQ29sb3IpO1xuXG4gICAgaWYobmVlZHNWZXJ0aWNhbFNjcm9sbEJhcikge1xuICAgICAgICB0aGlzLnZiYXIgPSB2YmFyLmF0dHIoe1xuICAgICAgICAgICAgJ3J4JzogU2Nyb2xsQm94LmJhclJhZGl1cyxcbiAgICAgICAgICAgICdyeSc6IFNjcm9sbEJveC5iYXJSYWRpdXMsXG4gICAgICAgICAgICAneCc6IHZiYXJMLFxuICAgICAgICAgICAgJ3knOiB2YmFyVCxcbiAgICAgICAgICAgICd3aWR0aCc6IHZiYXJXLFxuICAgICAgICAgICAgJ2hlaWdodCc6IHZiYXJIXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHZiYXIgY2VudGVyIG1vdmVzIGJldHdlZW4gdmJhcllNaW4gYW5kIHZiYXJZTWluICsgdmJhclRyYW5zbGF0ZU1heFxuICAgICAgICB0aGlzLl92YmFyWU1pbiA9IHZiYXJUICsgdmJhckggLyAyO1xuICAgICAgICB0aGlzLl92YmFyVHJhbnNsYXRlTWF4ID0gYm94SCAtIHZiYXJIO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGVsZXRlIHRoaXMudmJhcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX3ZiYXJZTWluO1xuICAgICAgICBkZWxldGUgdGhpcy5fdmJhclRyYW5zbGF0ZU1heDtcbiAgICB9XG5cbiAgICAvLyBzZXR1cCBhIGNsaXAgcGF0aCAoaWYgc2Nyb2xsIGJhcnMgYXJlIG5lZWRlZClcbiAgICB2YXIgY2xpcElkID0gdGhpcy5pZCxcbiAgICAgICAgY2xpcEwgPSBib3hMIC0gMC41LFxuICAgICAgICBjbGlwUiA9IChuZWVkc1ZlcnRpY2FsU2Nyb2xsQmFyKSA/IGJveFIgKyB2YmFyVyArIDAuNSA6IGJveFIgKyAwLjUsXG4gICAgICAgIGNsaXBUID0gYm94VCAtIDAuNSxcbiAgICAgICAgY2xpcEIgPSAobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyKSA/IGJveEIgKyBoYmFySCArIDAuNSA6IGJveEIgKyAwLjU7XG5cbiAgICB2YXIgY2xpcFBhdGggPSBmdWxsTGF5b3V0Ll90b3BkZWZzLnNlbGVjdEFsbCgnIycgKyBjbGlwSWQpXG4gICAgICAgIC5kYXRhKChuZWVkc0hvcml6b250YWxTY3JvbGxCYXIgfHwgbmVlZHNWZXJ0aWNhbFNjcm9sbEJhcikgPyBbMF0gOiBbXSk7XG5cbiAgICBjbGlwUGF0aC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBjbGlwUGF0aC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2NsaXBQYXRoJykuYXR0cignaWQnLCBjbGlwSWQpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKTtcblxuICAgIGlmKG5lZWRzSG9yaXpvbnRhbFNjcm9sbEJhciB8fCBuZWVkc1ZlcnRpY2FsU2Nyb2xsQmFyKSB7XG4gICAgICAgIHRoaXMuX2NsaXBSZWN0ID0gY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICB4OiBNYXRoLmZsb29yKGNsaXBMKSxcbiAgICAgICAgICAgIHk6IE1hdGguZmxvb3IoY2xpcFQpLFxuICAgICAgICAgICAgd2lkdGg6IE1hdGguY2VpbChjbGlwUikgLSBNYXRoLmZsb29yKGNsaXBMKSxcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5jZWlsKGNsaXBCKSAtIE1hdGguZmxvb3IoY2xpcFQpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuY29udGFpbmVyLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBjbGlwSWQpO1xuXG4gICAgICAgIHRoaXMuYmcuYXR0cih7XG4gICAgICAgICAgICB4OiBsLFxuICAgICAgICAgICAgeTogdCxcbiAgICAgICAgICAgIHdpZHRoOiB3LFxuICAgICAgICAgICAgaGVpZ2h0OiBoXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5iZy5hdHRyKHtcbiAgICAgICAgICAgIHdpZHRoOiAwLFxuICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNvbnRhaW5lclxuICAgICAgICAgICAgLm9uKCd3aGVlbCcsIG51bGwpXG4gICAgICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgbnVsbCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9jbGlwUmVjdDtcbiAgICB9XG5cbiAgICAvLyBzZXQgdXAgZHJhZyBsaXN0ZW5lcnMgKGlmIHNjcm9sbCBiYXJzIGFyZSBuZWVkZWQpXG4gICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyIHx8IG5lZWRzVmVydGljYWxTY3JvbGxCYXIpIHtcbiAgICAgICAgdmFyIG9uQm94RHJhZyA9IGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBkMy5ldmVudC5zb3VyY2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignZHJhZycsIHRoaXMuX29uQm94RHJhZy5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLmNvbnRhaW5lclxuICAgICAgICAgICAgLm9uKCd3aGVlbCcsIG51bGwpXG4gICAgICAgICAgICAub24oJ3doZWVsJywgdGhpcy5fb25Cb3hXaGVlbC5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAuY2FsbChvbkJveERyYWcpO1xuXG4gICAgICAgIHZhciBvbkJhckRyYWcgPSBkMy5iZWhhdmlvci5kcmFnKClcbiAgICAgICAgICAgIC5vbignZHJhZ3N0YXJ0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc291cmNlRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBkMy5ldmVudC5zb3VyY2VFdmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2RyYWcnLCB0aGlzLl9vbkJhckRyYWcuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyKSB7XG4gICAgICAgICAgICB0aGlzLmhiYXJcbiAgICAgICAgICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgICAgICAgICAuY2FsbChvbkJhckRyYWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobmVlZHNWZXJ0aWNhbFNjcm9sbEJhcikge1xuICAgICAgICAgICAgdGhpcy52YmFyXG4gICAgICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAgICAgLmNhbGwob25CYXJEcmFnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNldCBzY3JvbGxib3ggdHJhbnNsYXRpb25cbiAgICB0aGlzLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKTtcbn07XG5cbi8qKlxuICogSWYgcHJlc2VudCwgcmVtb3ZlIGNsaXAtcGF0aCBhbmQgc2Nyb2xsYmFyc1xuICpcbiAqIEBtZXRob2RcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICBpZih0aGlzLmhiYXIgfHwgdGhpcy52YmFyKSB7XG4gICAgICAgIHRoaXMuYmcuYXR0cih7XG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jb250YWluZXJcbiAgICAgICAgICAgIC5vbignd2hlZWwnLCBudWxsKVxuICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIG51bGwpO1xuICAgICAgICBkZWxldGUgdGhpcy5fY2xpcFJlY3Q7XG4gICAgfVxuXG4gICAgaWYodGhpcy5oYmFyKSB7XG4gICAgICAgIHRoaXMuaGJhci5vbignLmRyYWcnLCBudWxsKTtcbiAgICAgICAgdGhpcy5oYmFyLnJlbW92ZSgpO1xuICAgICAgICBkZWxldGUgdGhpcy5oYmFyO1xuICAgICAgICBkZWxldGUgdGhpcy5faGJhclhNaW47XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9oYmFyVHJhbnNsYXRlTWF4O1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB0aGlzLnZiYXIub24oJy5kcmFnJywgbnVsbCk7XG4gICAgICAgIHRoaXMudmJhci5yZW1vdmUoKTtcbiAgICAgICAgZGVsZXRlIHRoaXMudmJhcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX3ZiYXJZTWluO1xuICAgICAgICBkZWxldGUgdGhpcy5fdmJhclRyYW5zbGF0ZU1heDtcbiAgICB9XG59O1xuXG4vKipcbiAqIEhhbmRsZXMgc2Nyb2xsIGJveCBkcmFnIGV2ZW50c1xuICpcbiAqIEBtZXRob2RcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5fb25Cb3hEcmFnID0gZnVuY3Rpb24gb25CYXJEcmFnKCkge1xuICAgIHZhciB0cmFuc2xhdGVYID0gdGhpcy50cmFuc2xhdGVYLFxuICAgICAgICB0cmFuc2xhdGVZID0gdGhpcy50cmFuc2xhdGVZO1xuXG4gICAgaWYodGhpcy5oYmFyKSB7XG4gICAgICAgIHRyYW5zbGF0ZVggLT0gZDMuZXZlbnQuZHg7XG4gICAgfVxuXG4gICAgaWYodGhpcy52YmFyKSB7XG4gICAgICAgIHRyYW5zbGF0ZVkgLT0gZDMuZXZlbnQuZHk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSk7XG59O1xuXG4vKipcbiAqIEhhbmRsZXMgc2Nyb2xsIGJveCB3aGVlbCBldmVudHNcbiAqXG4gKiBAbWV0aG9kXG4gKi9cblNjcm9sbEJveC5wcm90b3R5cGUuX29uQm94V2hlZWwgPSBmdW5jdGlvbiBvbkJhcldoZWVsKCkge1xuICAgIHZhciB0cmFuc2xhdGVYID0gdGhpcy50cmFuc2xhdGVYLFxuICAgICAgICB0cmFuc2xhdGVZID0gdGhpcy50cmFuc2xhdGVZO1xuXG4gICAgaWYodGhpcy5oYmFyKSB7XG4gICAgICAgIHRyYW5zbGF0ZVggKz0gZDMuZXZlbnQuZGVsdGFZO1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB0cmFuc2xhdGVZICs9IGQzLmV2ZW50LmRlbHRhWTtcbiAgICB9XG5cbiAgICB0aGlzLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKTtcbn07XG5cbi8qKlxuICogSGFuZGxlcyBzY3JvbGwgYmFyIGRyYWcgZXZlbnRzXG4gKlxuICogQG1ldGhvZFxuICovXG5TY3JvbGxCb3gucHJvdG90eXBlLl9vbkJhckRyYWcgPSBmdW5jdGlvbiBvbkJhckRyYWcoKSB7XG4gICAgdmFyIHRyYW5zbGF0ZVggPSB0aGlzLnRyYW5zbGF0ZVgsXG4gICAgICAgIHRyYW5zbGF0ZVkgPSB0aGlzLnRyYW5zbGF0ZVk7XG5cbiAgICBpZih0aGlzLmhiYXIpIHtcbiAgICAgICAgdmFyIHhNaW4gPSB0cmFuc2xhdGVYICsgdGhpcy5faGJhclhNaW4sXG4gICAgICAgICAgICB4TWF4ID0geE1pbiArIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXgsXG4gICAgICAgICAgICB4ID0gTGliLmNvbnN0cmFpbihkMy5ldmVudC54LCB4TWluLCB4TWF4KSxcbiAgICAgICAgICAgIHhmID0gKHggLSB4TWluKSAvICh4TWF4IC0geE1pbik7XG5cbiAgICAgICAgdmFyIHRyYW5zbGF0ZVhNYXggPSB0aGlzLnBvc2l0aW9uLncgLSB0aGlzLl9ib3gudztcblxuICAgICAgICB0cmFuc2xhdGVYID0geGYgKiB0cmFuc2xhdGVYTWF4O1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB2YXIgeU1pbiA9IHRyYW5zbGF0ZVkgKyB0aGlzLl92YmFyWU1pbixcbiAgICAgICAgICAgIHlNYXggPSB5TWluICsgdGhpcy5fdmJhclRyYW5zbGF0ZU1heCxcbiAgICAgICAgICAgIHkgPSBMaWIuY29uc3RyYWluKGQzLmV2ZW50LnksIHlNaW4sIHlNYXgpLFxuICAgICAgICAgICAgeWYgPSAoeSAtIHlNaW4pIC8gKHlNYXggLSB5TWluKTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlWU1heCA9IHRoaXMucG9zaXRpb24uaCAtIHRoaXMuX2JveC5oO1xuXG4gICAgICAgIHRyYW5zbGF0ZVkgPSB5ZiAqIHRyYW5zbGF0ZVlNYXg7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSk7XG59O1xuXG4vKipcbiAqIFNldCBjbGlwIHBhdGggYW5kIHNjcm9sbCBiYXIgdHJhbnNsYXRlIHRyYW5zZm9ybVxuICpcbiAqIEBtZXRob2RcbiAqIEBwYXJhbSB7bnVtYmVyfSAgW3RyYW5zbGF0ZVg9MF0gIEhvcml6b250YWwgb2Zmc2V0IChpbiBwaXhlbHMpXG4gKiBAcGFyYW0ge251bWJlcn0gIFt0cmFuc2xhdGVZPTBdICBWZXJ0aWNhbCBvZmZzZXQgKGluIHBpeGVscylcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5zZXRUcmFuc2xhdGUgPSBmdW5jdGlvbiBzZXRUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSkge1xuICAgIC8vIHN0b3JlIHRyYW5zbGF0ZVggYW5kIHRyYW5zbGF0ZVkgKG5lZWRlZCBieSBtb3VzZSBldmVudCBoYW5kbGVycylcbiAgICB2YXIgdHJhbnNsYXRlWE1heCA9IHRoaXMucG9zaXRpb24udyAtIHRoaXMuX2JveC53LFxuICAgICAgICB0cmFuc2xhdGVZTWF4ID0gdGhpcy5wb3NpdGlvbi5oIC0gdGhpcy5fYm94Lmg7XG5cbiAgICB0cmFuc2xhdGVYID0gTGliLmNvbnN0cmFpbih0cmFuc2xhdGVYIHx8IDAsIDAsIHRyYW5zbGF0ZVhNYXgpO1xuICAgIHRyYW5zbGF0ZVkgPSBMaWIuY29uc3RyYWluKHRyYW5zbGF0ZVkgfHwgMCwgMCwgdHJhbnNsYXRlWU1heCk7XG5cbiAgICB0aGlzLnRyYW5zbGF0ZVggPSB0cmFuc2xhdGVYO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IHRyYW5zbGF0ZVk7XG5cbiAgICB0aGlzLmNvbnRhaW5lci5jYWxsKERyYXdpbmcuc2V0VHJhbnNsYXRlLFxuICAgICAgICB0aGlzLl9ib3gubCAtIHRoaXMucG9zaXRpb24ubCAtIHRyYW5zbGF0ZVgsXG4gICAgICAgIHRoaXMuX2JveC50IC0gdGhpcy5wb3NpdGlvbi50IC0gdHJhbnNsYXRlWSk7XG5cbiAgICBpZih0aGlzLl9jbGlwUmVjdCkge1xuICAgICAgICB0aGlzLl9jbGlwUmVjdC5hdHRyKHtcbiAgICAgICAgICAgIHg6IE1hdGguZmxvb3IodGhpcy5wb3NpdGlvbi5sICsgdHJhbnNsYXRlWCAtIDAuNSksXG4gICAgICAgICAgICB5OiBNYXRoLmZsb29yKHRoaXMucG9zaXRpb24udCArIHRyYW5zbGF0ZVkgLSAwLjUpXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKHRoaXMuaGJhcikge1xuICAgICAgICB2YXIgeGYgPSB0cmFuc2xhdGVYIC8gdHJhbnNsYXRlWE1heDtcblxuICAgICAgICB0aGlzLmhiYXIuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSxcbiAgICAgICAgICAgIHRyYW5zbGF0ZVggKyB4ZiAqIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXgsXG4gICAgICAgICAgICB0cmFuc2xhdGVZKTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnZiYXIpIHtcbiAgICAgICAgdmFyIHlmID0gdHJhbnNsYXRlWSAvIHRyYW5zbGF0ZVlNYXg7XG5cbiAgICAgICAgdGhpcy52YmFyLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsXG4gICAgICAgICAgICB0cmFuc2xhdGVYLFxuICAgICAgICAgICAgdHJhbnNsYXRlWSArIHlmICogdGhpcy5fdmJhclRyYW5zbGF0ZU1heCk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gZnJhY3Rpb24gb2Ygc29tZSBzaXplIHRvIGdldCB0byBhIG5hbWVkIHBvc2l0aW9uXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBmcm9tIGJvdHRvbSBsZWZ0OiB0aGlzIGlzIHRoZSBvcmlnaW4gb2Ygb3VyIHBhcGVyLXJlZmVyZW5jZVxuICAgIC8vIHBvc2l0aW9uaW5nIHN5c3RlbVxuICAgIEZST01fQkw6IHtcbiAgICAgICAgbGVmdDogMCxcbiAgICAgICAgY2VudGVyOiAwLjUsXG4gICAgICAgIHJpZ2h0OiAxLFxuICAgICAgICBib3R0b206IDAsXG4gICAgICAgIG1pZGRsZTogMC41LFxuICAgICAgICB0b3A6IDFcbiAgICB9LFxuICAgIC8vIGZyb20gdG9wIGxlZnQ6IHRoaXMgaXMgdGhlIHNjcmVlbiBwaXhlbCBwb3NpdGlvbmluZyBvcmlnaW5cbiAgICBGUk9NX1RMOiB7XG4gICAgICAgIGxlZnQ6IDAsXG4gICAgICAgIGNlbnRlcjogMC41LFxuICAgICAgICByaWdodDogMSxcbiAgICAgICAgYm90dG9tOiAxLFxuICAgICAgICBtaWRkbGU6IDAuNSxcbiAgICAgICAgdG9wOiAwXG4gICAgfSxcbiAgICAvLyBmcm9tIGJvdHRvbSByaWdodDogc29tZXRpbWVzIHlvdSBqdXN0IG5lZWQgdGhlIG9wcG9zaXRlIG9mIF5eXG4gICAgRlJPTV9CUjoge1xuICAgICAgICBsZWZ0OiAxLFxuICAgICAgICBjZW50ZXI6IDAuNSxcbiAgICAgICAgcmlnaHQ6IDAsXG4gICAgICAgIGJvdHRvbTogMCxcbiAgICAgICAgbWlkZGxlOiAwLjUsXG4gICAgICAgIHRvcDogMVxuICAgIH0sXG4gICAgLy8gbXVsdGlwbGUgb2YgZm9udFNpemUgdG8gZ2V0IHRoZSB2ZXJ0aWNhbCBvZmZzZXQgYmV0d2VlbiBsaW5lc1xuICAgIExJTkVfU1BBQ0lORzogMS4zLFxuXG4gICAgLy8gbXVsdGlwbGUgb2YgZm9udFNpemUgdG8gc2hpZnQgZnJvbSB0aGUgYmFzZWxpbmUgdG8gdGhlIG1pZGxpbmVcbiAgICAvLyAodG8gdXNlIHdoZW4gd2UgZG9uJ3QgY2FsY3VsYXRlIHRoaXMgc2hpZnQgZnJvbSBEcmF3aW5nLmJCb3gpXG4gICAgLy8gVG8gYmUgcHJlY2lzZSB0aGlzIHNob3VsZCBiZSBoYWxmIHRoZSBjYXAgaGVpZ2h0IChjYXBpdGFsIGxldHRlcilcbiAgICAvLyBvZiB0aGUgZm9udCwgYW5kIGFjY29yZGluZyB0byB3aWtpcGVkaWE6XG4gICAgLy8gICBhbiBcImF2ZXJhZ2VcIiBmb250IG1pZ2h0IGhhdmUgYSBjYXAgaGVpZ2h0IG9mIDcwJSBvZiB0aGUgZW1cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FbV8odHlwb2dyYXBoeSkjSGlzdG9yeVxuICAgIE1JRF9TSElGVDogMC4zNSxcblxuICAgIE9QUE9TSVRFX1NJREU6IHtcbiAgICAgICAgbGVmdDogJ3JpZ2h0JyxcbiAgICAgICAgcmlnaHQ6ICdsZWZ0JyxcbiAgICAgICAgdG9wOiAnYm90dG9tJyxcbiAgICAgICAgYm90dG9tOiAndG9wJ1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIENPTVBBUklTT05fT1BTOiBbJz0nLCAnIT0nLCAnPCcsICc+PScsICc+JywgJzw9J10sXG4gICAgQ09NUEFSSVNPTl9PUFMyOiBbJz0nLCAnPCcsICc+PScsICc+JywgJzw9J10sXG4gICAgSU5URVJWQUxfT1BTOiBbJ1tdJywgJygpJywgJ1spJywgJyhdJywgJ11bJywgJykoJywgJ10oJywgJylbJ10sXG4gICAgU0VUX09QUzogWyd7fScsICd9eyddLFxuICAgIENPTlNUUkFJTlRfUkVEVUNUSU9OOiB7XG4gICAgICAgIC8vIGZvciBjb250b3VyIGNvbnN0cmFpbnRzLCBvcGVuL2Nsb3NlZCBlbmRwb2ludHMgYXJlIGVxdWl2YWxlbnRcbiAgICAgICAgJz0nOiAnPScsXG5cbiAgICAgICAgJzwnOiAnPCcsXG4gICAgICAgICc8PSc6ICc8JyxcblxuICAgICAgICAnPic6ICc+JyxcbiAgICAgICAgJz49JzogJz4nLFxuXG4gICAgICAgICdbXSc6ICdbXScsXG4gICAgICAgICcoKSc6ICdbXScsXG4gICAgICAgICdbKSc6ICdbXScsXG4gICAgICAgICcoXSc6ICdbXScsXG5cbiAgICAgICAgJ11bJzogJ11bJyxcbiAgICAgICAgJykoJzogJ11bJyxcbiAgICAgICAgJ10oJzogJ11bJyxcbiAgICAgICAgJylbJzogJ11bJ1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc29saWQ6IFtbXSwgMF0sXG4gICAgZG90OiBbWzAuNSwgMV0sIDIwMF0sXG4gICAgZGFzaDogW1swLjUsIDFdLCA1MF0sXG4gICAgbG9uZ2Rhc2g6IFtbMC41LCAxXSwgMTBdLFxuICAgIGRhc2hkb3Q6IFtbMC41LCAwLjYyNSwgMC44NzUsIDFdLCA1MF0sXG4gICAgbG9uZ2Rhc2hkb3Q6IFtbMC41LCAwLjcsIDAuOCwgMV0sIDEwXVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjaXJjbGU6ICfil48nLFxuICAgICdjaXJjbGUtb3Blbic6ICfil4snLFxuICAgIHNxdWFyZTogJ+KWoCcsXG4gICAgJ3NxdWFyZS1vcGVuJzogJ+KWoScsXG4gICAgZGlhbW9uZDogJ+KXhicsXG4gICAgJ2RpYW1vbmQtb3Blbic6ICfil4cnLFxuICAgIGNyb3NzOiAnKycsXG4gICAgeDogJ+KdjCdcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgLyoqXG4gICAgICogVGltaW5nIGluZm9ybWF0aW9uIGZvciBpbnRlcmFjdGl2ZSBlbGVtZW50c1xuICAgICAqL1xuICAgIFNIT1dfUExBQ0VIT0xERVI6IDEwMCxcbiAgICBISURFX1BMQUNFSE9MREVSOiAxMDAwLFxuXG4gICAgLy8gbXMgYmV0d2VlbiBmaXJzdCBtb3VzZWRvd24gYW5kIDJuZCBtb3VzZXVwIHRvIGNvbnN0aXR1dGUgZGJsY2xpY2suLi5cbiAgICAvLyB3ZSBkb24ndCBzZWVtIHRvIGhhdmUgYWNjZXNzIHRvIHRoZSBzeXN0ZW0gc2V0dGluZ1xuICAgIERCTENMSUNLREVMQVk6IDMwMCxcblxuICAgIC8vIG9wYWNpdHkgZGltbWluZyBmcmFjdGlvbiBmb3IgcG9pbnRzIHRoYXQgYXJlIG5vdCBpbiBzZWxlY3Rpb25cbiAgICBERVNFTEVDVERJTTogMC4yXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIFN0YW5kYXJkaXplIGFsbCBtaXNzaW5nIGRhdGEgaW4gY2FsY2RhdGEgdG8gdXNlIHVuZGVmaW5lZFxuICAgICAqIG5ldmVyIG51bGwgb3IgTmFOLlxuICAgICAqIFRoYXQgd2F5IHdlIGNhbiB1c2UgIT09dW5kZWZpbmVkLCBvciAhPT0gQkFETlVNLFxuICAgICAqIHRvIHRlc3QgZm9yIHJlYWwgZGF0YVxuICAgICAqL1xuICAgIEJBRE5VTTogdW5kZWZpbmVkLFxuXG4gICAgLypcbiAgICAgKiBMaW1pdCBjZXJ0YWluIG9wZXJhdGlvbnMgdG8gd2VsbCBiZWxvdyBmbG9hdGluZyBwb2ludCBtYXggdmFsdWVcbiAgICAgKiB0byBhdm9pZCBnbGl0Y2hlczogTWFrZSBzdXJlIHRoYXQgZXZlbiB3aGVuIHlvdSBtdWx0aXBseSBpdCBieSB0aGVcbiAgICAgKiBudW1iZXIgb2YgcGl4ZWxzIG9uIGEgZ2lhbnQgc2NyZWVuIGl0IHN0aWxsIHdvcmtzXG4gICAgICovXG4gICAgRlBfU0FGRTogTnVtYmVyLk1BWF9WQUxVRSAvIDEwMDAwLFxuXG4gICAgLypcbiAgICAgKiBjb252ZXJzaW9uIG9mIGRhdGUgdW5pdHMgdG8gbWlsbGlzZWNvbmRzXG4gICAgICogeWVhciBhbmQgbW9udGggY29uc3RhbnRzIGFyZSBtYXJrZWQgXCJBVkdcIlxuICAgICAqIHRvIHJlbWluZCB1cyB0aGF0IG5vdCBhbGwgeWVhcnMgYW5kIG1vbnRoc1xuICAgICAqIGhhdmUgdGhlIHNhbWUgbGVuZ3RoXG4gICAgICovXG4gICAgT05FQVZHWUVBUjogMzE1NTc2MDAwMDAsIC8vIDM2NS4yNSBkYXlzXG4gICAgT05FQVZHTU9OVEg6IDI2Mjk4MDAwMDAsIC8vIDEvMTIgb2YgT05FQVZHWUVBUlxuICAgIE9ORURBWTogODY0MDAwMDAsXG4gICAgT05FSE9VUjogMzYwMDAwMCxcbiAgICBPTkVNSU46IDYwMDAwLFxuICAgIE9ORVNFQzogMTAwMCxcblxuICAgIC8qXG4gICAgICogRm9yIGZhc3QgY29udmVyc2lvbiBidHduIHdvcmxkIGNhbGVuZGFycyBhbmQgZXBvY2ggbXMsIHRoZSBKdWxpYW4gRGF5IE51bWJlclxuICAgICAqIG9mIHRoZSB1bml4IGVwb2NoLiBGcm9tIGNhbGVuZGFycy5pbnN0YW5jZSgpLm5ld0RhdGUoMTk3MCwgMSwgMSkudG9KRCgpXG4gICAgICovXG4gICAgRVBPQ0hKRDogMjQ0MDU4Ny41LFxuXG4gICAgLypcbiAgICAgKiBBcmUgdHdvIHZhbHVlcyBuZWFybHkgZXF1YWw/IENvbXBhcmUgdG8gMVBQTVxuICAgICAqL1xuICAgIEFMTU9TVF9FUVVBTDogMSAtIDFlLTYsXG5cbiAgICAvKlxuICAgICAqIElmIHdlJ3JlIGFza2VkIHRvIGNsaXAgYSBub24tcG9zaXRpdmUgbG9nIHZhbHVlLCBob3cgZmFyIG9mZi1zY3JlZW5cbiAgICAgKiBkbyB3ZSBwdXQgaXQ/XG4gICAgICovXG4gICAgTE9HX0NMSVA6IDEwLFxuXG4gICAgLypcbiAgICAgKiBub3QgYSBudW1iZXIsIGJ1dCBmb3IgZGlzcGxheWluZyBudW1iZXJzOiB0aGUgXCJtaW51cyBzaWduXCIgc3ltYm9sIGlzXG4gICAgICogd2lkZXIgdGhhbiB0aGUgcmVndWxhciBhc2NpaSBkYXNoIFwiLVwiXG4gICAgICovXG4gICAgTUlOVVNfU0lHTjogJ1xcdTIyMTInXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuZXhwb3J0cy54bWxucyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3htbG5zLyc7XG5leHBvcnRzLnN2ZyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG5leHBvcnRzLnhsaW5rID0gJ2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnO1xuXG4vLyB0aGUgJ29sZCcgZDMgcXVpcmsgZ290IGZpeCBpbiB2My41Ljdcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYm9zdG9jay9kMy9jb21taXQvYTZmNjZlOWRkMzdmNzY0NDAzZmM3YzFmMjZiZTA5YWI0YWYyNGZlZFxuZXhwb3J0cy5zdmdBdHRycyA9IHtcbiAgICB4bWxuczogZXhwb3J0cy5zdmcsXG4gICAgJ3htbG5zOnhsaW5rJzogZXhwb3J0cy54bGlua1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gcGFja2FnZSB2ZXJzaW9uIGluamVjdGVkIGJ5IGBucG0gcnVuIHByZXByb2Nlc3NgXG5leHBvcnRzLnZlcnNpb24gPSAnMS40Mi4yJztcblxuLy8gaW5qZWN0IHByb21pc2UgcG9seWZpbGxcbnJlcXVpcmUoJ2VzNi1wcm9taXNlJykucG9seWZpbGwoKTtcblxuLy8gaW5qZWN0IHBsb3QgY3NzXG5yZXF1aXJlKCcuLi9idWlsZC9wbG90Y3NzJyk7XG5cbi8vIGluamVjdCBkZWZhdWx0IE1hdGhKYXggY29uZmlnXG5yZXF1aXJlKCcuL2ZvbnRzL21hdGhqYXhfY29uZmlnJyk7XG5cbi8vIGluY2x1ZGUgcmVnaXN0cnkgbW9kdWxlIGFuZCBleHBvc2UgcmVnaXN0ZXIgbWV0aG9kXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuL3JlZ2lzdHJ5Jyk7XG52YXIgcmVnaXN0ZXIgPSBleHBvcnRzLnJlZ2lzdGVyID0gUmVnaXN0cnkucmVnaXN0ZXI7XG5cbi8vIGV4cG9zZSBwbG90IGFwaSBtZXRob2RzXG52YXIgcGxvdEFwaSA9IHJlcXVpcmUoJy4vcGxvdF9hcGknKTtcbnZhciBtZXRob2ROYW1lcyA9IE9iamVjdC5rZXlzKHBsb3RBcGkpO1xuZm9yKHZhciBpID0gMDsgaSA8IG1ldGhvZE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIG5hbWUgPSBtZXRob2ROYW1lc1tpXTtcbiAgICBleHBvcnRzW25hbWVdID0gcGxvdEFwaVtuYW1lXTtcbiAgICByZWdpc3Rlcih7XG4gICAgICAgIG1vZHVsZVR5cGU6ICdhcGlNZXRob2QnLFxuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBmbjogcGxvdEFwaVtuYW1lXVxuICAgIH0pO1xufVxuXG4vLyBzY2F0dGVyIGlzIHRoZSBvbmx5IHRyYWNlIGluY2x1ZGVkIGJ5IGRlZmF1bHRcbnJlZ2lzdGVyKHJlcXVpcmUoJy4vdHJhY2VzL3NjYXR0ZXInKSk7XG5cbi8vIHJlZ2lzdGVyIGFsbCByZWdpc3RyYWJsZSBjb21wb25lbnRzIG1vZHVsZXNcbnJlZ2lzdGVyKFtcbiAgICByZXF1aXJlKCcuL2NvbXBvbmVudHMvZngnKSxcbiAgICByZXF1aXJlKCcuL2NvbXBvbmVudHMvbGVnZW5kJyksXG4gICAgcmVxdWlyZSgnLi9jb21wb25lbnRzL2Fubm90YXRpb25zJyksXG4gICAgcmVxdWlyZSgnLi9jb21wb25lbnRzL2Fubm90YXRpb25zM2QnKSxcbiAgICByZXF1aXJlKCcuL2NvbXBvbmVudHMvc2hhcGVzJyksXG4gICAgcmVxdWlyZSgnLi9jb21wb25lbnRzL2ltYWdlcycpLFxuICAgIHJlcXVpcmUoJy4vY29tcG9uZW50cy91cGRhdGVtZW51cycpLFxuICAgIHJlcXVpcmUoJy4vY29tcG9uZW50cy9zbGlkZXJzJyksXG4gICAgcmVxdWlyZSgnLi9jb21wb25lbnRzL3Jhbmdlc2xpZGVyJyksXG4gICAgcmVxdWlyZSgnLi9jb21wb25lbnRzL3Jhbmdlc2VsZWN0b3InKSxcbiAgICByZXF1aXJlKCcuL2NvbXBvbmVudHMvZ3JpZCcpLFxuICAgIHJlcXVpcmUoJy4vY29tcG9uZW50cy9lcnJvcmJhcnMnKVxuXSk7XG5cbi8vIGxvY2FsZXMgZW4gYW5kIGVuLVVTIGFyZSByZXF1aXJlZCBmb3IgZGVmYXVsdCBiZWhhdmlvclxucmVnaXN0ZXIoW1xuICAgIHJlcXVpcmUoJy4vbG9jYWxlLWVuJyksXG4gICAgcmVxdWlyZSgnLi9sb2NhbGUtZW4tdXMnKVxuXSk7XG5cbi8vIHBsb3QgaWNvbnNcbmV4cG9ydHMuSWNvbnMgPSByZXF1aXJlKCcuLi9idWlsZC9wbG90aWNvbicpO1xuXG4vLyB1bm9mZmljaWFsICdiZXRhJyBwbG90IG1ldGhvZHMsIHVzZSBhdCB5b3VyIG93biByaXNrXG5leHBvcnRzLlBsb3RzID0gcmVxdWlyZSgnLi9wbG90cy9wbG90cycpO1xuZXhwb3J0cy5GeCA9IHJlcXVpcmUoJy4vY29tcG9uZW50cy9meCcpO1xuZXhwb3J0cy5TbmFwc2hvdCA9IHJlcXVpcmUoJy4vc25hcHNob3QnKTtcbmV4cG9ydHMuUGxvdFNjaGVtYSA9IHJlcXVpcmUoJy4vcGxvdF9hcGkvcGxvdF9zY2hlbWEnKTtcbmV4cG9ydHMuUXVldWUgPSByZXF1aXJlKCcuL2xpYi9xdWV1ZScpO1xuXG4vLyBleHBvcnQgZDMgdXNlZCBpbiB0aGUgYnVuZGxlXG5leHBvcnRzLmQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyogZ2xvYmFsIE1hdGhKYXg6ZmFsc2UgKi9cblxuLyoqXG4gKiBDaGVjayBhbmQgY29uZmlndXJlIE1hdGhKYXhcbiAqL1xuaWYodHlwZW9mIE1hdGhKYXggIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZXhwb3J0cy5NYXRoSmF4ID0gdHJ1ZTtcblxuICAgIHZhciBnbG9iYWxDb25maWcgPSAod2luZG93LlBsb3RseUNvbmZpZyB8fCB7fSkuTWF0aEpheENvbmZpZyAhPT0gJ2xvY2FsJztcblxuICAgIGlmKGdsb2JhbENvbmZpZykge1xuICAgICAgICBNYXRoSmF4Lkh1Yi5Db25maWcoe1xuICAgICAgICAgICAgbWVzc2FnZVN0eWxlOiAnbm9uZScsXG4gICAgICAgICAgICBza2lwU3RhcnR1cFR5cGVzZXQ6IHRydWUsXG4gICAgICAgICAgICBkaXNwbGF5QWxpZ246ICdsZWZ0JyxcbiAgICAgICAgICAgIHRleDJqYXg6IHtcbiAgICAgICAgICAgICAgICBpbmxpbmVNYXRoOiBbWyckJywgJyQnXSwgWydcXFxcKCcsICdcXFxcKSddXVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgTWF0aEpheC5IdWIuQ29uZmlndXJlZCgpO1xuICAgIH1cblxufSBlbHNlIHtcbiAgICBleHBvcnRzLk1hdGhKYXggPSBmYWxzZTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG1vZE1vZHVsZSA9IHJlcXVpcmUoJy4vbW9kJyk7XG52YXIgbW9kID0gbW9kTW9kdWxlLm1vZDtcbnZhciBtb2RIYWxmID0gbW9kTW9kdWxlLm1vZEhhbGY7XG5cbnZhciBQSSA9IE1hdGguUEk7XG52YXIgdHdvUEkgPSAyICogUEk7XG5cbmZ1bmN0aW9uIGRlZzJyYWQoZGVnKSB7IHJldHVybiBkZWcgLyAxODAgKiBQSTsgfVxuXG5mdW5jdGlvbiByYWQyZGVnKHJhZCkgeyByZXR1cm4gcmFkIC8gUEkgKiAxODA7IH1cblxuLyoqXG4gKiBpcyBzZWN0b3IgYSBmdWxsIGNpcmNsZT9cbiAqIC4uLiB0aGlzIGNvbWVzIHVwIGEgbG90IGluIFNWRyBwYXRoLWRyYXdpbmcgcm91dGluZXNcbiAqXG4gKiBOLkIuIHdlIGNvbnNpZGVyIGFsbCBzZWN0b3JzIHRoYXQgc3BhbiBtb3JlIHRoYXQgMnBpICdmdWxsJyBjaXJjbGVzXG4gKlxuICogQHBhcmFtIHsyLWl0ZW0gYXJyYXl9IGFCbmRzIDogYW5ndWxhciBib3VuZHMgaW4gKnJhZGlhbnMqXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc0Z1bGxDaXJjbGUoYUJuZHMpIHtcbiAgICByZXR1cm4gTWF0aC5hYnMoYUJuZHNbMV0gLSBhQm5kc1swXSkgPiB0d29QSSAtIDFlLTE1O1xufVxuXG4vKipcbiAqIGFuZ3VsYXIgZGVsdGEgYmV0d2VlbiBhbmdsZSAnYScgYW5kICdiJ1xuICogc29sdXRpb24gdGFrZW4gZnJvbTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIwMDcyNzlcbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYSA6IGZpcnN0IGFuZ2xlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXJ9IGIgOiBzZWNvbmQgYW5nbGUgaW4gKnJhZGlhbnMqXG4gKiBAcmV0dXJuIHtudW1iZXJ9IGFuZ3VsYXIgZGVsdGEgaW4gKnJhZGlhbnMqXG4gKi9cbmZ1bmN0aW9uIGFuZ2xlRGVsdGEoYSwgYikge1xuICAgIHJldHVybiBtb2RIYWxmKGIgLSBhLCB0d29QSSk7XG59XG5cbi8qKlxuICogYW5ndWxhciBkaXN0YW5jZSBiZXR3ZWVuIGFuZ2xlICdhJyBhbmQgJ2InXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGEgOiBmaXJzdCBhbmdsZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIDogc2Vjb25kIGFuZ2xlIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7bnVtYmVyfSBhbmd1bGFyIGRpc3RhbmNlIGluICpyYWRpYW5zKlxuICovXG5mdW5jdGlvbiBhbmdsZURpc3QoYSwgYikge1xuICAgIHJldHVybiBNYXRoLmFicyhhbmdsZURlbHRhKGEsIGIpKTtcbn1cblxuLyoqXG4gKiBpcyBhbmdsZSBpbnNpZGUgc2VjdG9yP1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIDogYW5nbGUgdG8gdGVzdCBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSBhQm5kcyA6IHNlY3RvcidzIGFuZ3VsYXIgYm91bmRzIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc0FuZ2xlSW5zaWRlU2VjdG9yKGEsIGFCbmRzKSB7XG4gICAgaWYoaXNGdWxsQ2lyY2xlKGFCbmRzKSkgcmV0dXJuIHRydWU7XG5cbiAgICB2YXIgczAsIHMxO1xuXG4gICAgaWYoYUJuZHNbMF0gPCBhQm5kc1sxXSkge1xuICAgICAgICBzMCA9IGFCbmRzWzBdO1xuICAgICAgICBzMSA9IGFCbmRzWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHMwID0gYUJuZHNbMV07XG4gICAgICAgIHMxID0gYUJuZHNbMF07XG4gICAgfVxuXG4gICAgczAgPSBtb2QoczAsIHR3b1BJKTtcbiAgICBzMSA9IG1vZChzMSwgdHdvUEkpO1xuICAgIGlmKHMwID4gczEpIHMxICs9IHR3b1BJO1xuXG4gICAgdmFyIGEwID0gbW9kKGEsIHR3b1BJKTtcbiAgICB2YXIgYTEgPSBhMCArIHR3b1BJO1xuXG4gICAgcmV0dXJuIChhMCA+PSBzMCAmJiBhMCA8PSBzMSkgfHwgKGExID49IHMwICYmIGExIDw9IHMxKTtcbn1cblxuLyoqXG4gKiBpcyBwdCAocixhKSBpbnNpZGUgc2VjdG9yP1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSByIDogcHQncyByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEgOiBwdCdzIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSByQm5kcyA6IHNlY3RvcidzIHJhZGlhbCBib3VuZHNcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSBhQm5kcyA6IHNlY3RvcidzIGFuZ3VsYXIgYm91bmRzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNQdEluc2lkZVNlY3RvcihyLCBhLCByQm5kcywgYUJuZHMpIHtcbiAgICBpZighaXNBbmdsZUluc2lkZVNlY3RvcihhLCBhQm5kcykpIHJldHVybiBmYWxzZTtcblxuICAgIHZhciByMCwgcjE7XG5cbiAgICBpZihyQm5kc1swXSA8IHJCbmRzWzFdKSB7XG4gICAgICAgIHIwID0gckJuZHNbMF07XG4gICAgICAgIHIxID0gckJuZHNbMV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcjAgPSByQm5kc1sxXTtcbiAgICAgICAgcjEgPSByQm5kc1swXTtcbiAgICB9XG5cbiAgICByZXR1cm4gciA+PSByMCAmJiByIDw9IHIxO1xufVxuXG4vLyBjb21tb24gdG8gcGF0aEFyYywgcGF0aFNlY3RvciBhbmQgcGF0aEFubnVsdXNcbmZ1bmN0aW9uIF9wYXRoKHIwLCByMSwgYTAsIGExLCBjeCwgY3ksIGlzQ2xvc2VkKSB7XG4gICAgY3ggPSBjeCB8fCAwO1xuICAgIGN5ID0gY3kgfHwgMDtcblxuICAgIHZhciBpc0NpcmNsZSA9IGlzRnVsbENpcmNsZShbYTAsIGExXSk7XG4gICAgdmFyIGFTdGFydCwgYU1pZCwgYUVuZDtcbiAgICB2YXIgclN0YXJ0LCByRW5kO1xuXG4gICAgaWYoaXNDaXJjbGUpIHtcbiAgICAgICAgYVN0YXJ0ID0gMDtcbiAgICAgICAgYU1pZCA9IFBJO1xuICAgICAgICBhRW5kID0gdHdvUEk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoYTAgPCBhMSkge1xuICAgICAgICAgICAgYVN0YXJ0ID0gYTA7XG4gICAgICAgICAgICBhRW5kID0gYTE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhU3RhcnQgPSBhMTtcbiAgICAgICAgICAgIGFFbmQgPSBhMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHIwIDwgcjEpIHtcbiAgICAgICAgclN0YXJ0ID0gcjA7XG4gICAgICAgIHJFbmQgPSByMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByU3RhcnQgPSByMTtcbiAgICAgICAgckVuZCA9IHIwO1xuICAgIH1cblxuICAgIC8vIE4uQi4gc3ZnIGNvb3JkaW5hdGVzIGhlcmUsIHdoZXJlIHkgaW5jcmVhc2VzIGRvd253YXJkXG4gICAgZnVuY3Rpb24gcHQociwgYSkge1xuICAgICAgICByZXR1cm4gW3IgKiBNYXRoLmNvcyhhKSArIGN4LCBjeSAtIHIgKiBNYXRoLnNpbihhKV07XG4gICAgfVxuXG4gICAgdmFyIGxhcmdlQXJjID0gTWF0aC5hYnMoYUVuZCAtIGFTdGFydCkgPD0gUEkgPyAwIDogMTtcbiAgICBmdW5jdGlvbiBhcmMociwgYSwgY3cpIHtcbiAgICAgICAgcmV0dXJuICdBJyArIFtyLCByXSArICcgJyArIFswLCBsYXJnZUFyYywgY3ddICsgJyAnICsgcHQociwgYSk7XG4gICAgfVxuXG4gICAgdmFyIHA7XG5cbiAgICBpZihpc0NpcmNsZSkge1xuICAgICAgICBpZihyU3RhcnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHAgPSAnTScgKyBwdChyRW5kLCBhU3RhcnQpICtcbiAgICAgICAgICAgICAgICBhcmMockVuZCwgYU1pZCwgMCkgK1xuICAgICAgICAgICAgICAgIGFyYyhyRW5kLCBhRW5kLCAwKSArICdaJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHAgPSAnTScgKyBwdChyU3RhcnQsIGFTdGFydCkgK1xuICAgICAgICAgICAgICAgIGFyYyhyU3RhcnQsIGFNaWQsIDApICtcbiAgICAgICAgICAgICAgICBhcmMoclN0YXJ0LCBhRW5kLCAwKSArICdaJyArXG4gICAgICAgICAgICAgICAgJ00nICsgcHQockVuZCwgYVN0YXJ0KSArXG4gICAgICAgICAgICAgICAgYXJjKHJFbmQsIGFNaWQsIDEpICtcbiAgICAgICAgICAgICAgICBhcmMockVuZCwgYUVuZCwgMSkgKyAnWic7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihyU3RhcnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHAgPSAnTScgKyBwdChyRW5kLCBhU3RhcnQpICsgYXJjKHJFbmQsIGFFbmQsIDApO1xuICAgICAgICAgICAgaWYoaXNDbG9zZWQpIHAgKz0gJ0wwLDBaJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHAgPSAnTScgKyBwdChyU3RhcnQsIGFTdGFydCkgK1xuICAgICAgICAgICAgICAgICdMJyArIHB0KHJFbmQsIGFTdGFydCkgK1xuICAgICAgICAgICAgICAgIGFyYyhyRW5kLCBhRW5kLCAwKSArXG4gICAgICAgICAgICAgICAgJ0wnICsgcHQoclN0YXJ0LCBhRW5kKSArXG4gICAgICAgICAgICAgICAgYXJjKHJTdGFydCwgYVN0YXJ0LCAxKSArICdaJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwO1xufVxuXG4vKipcbiAqIHBhdGggYW4gYXJjXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHIgOiByYWRpdXNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMCA6IGZpcnN0IGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMSA6IHNlY29uZCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeCA6IHggY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN5IDogeSBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHJldHVybiB7c3RyaW5nfSBzdmcgcGF0aFxuICovXG5mdW5jdGlvbiBwYXRoQXJjKHIsIGEwLCBhMSwgY3gsIGN5KSB7XG4gICAgcmV0dXJuIF9wYXRoKG51bGwsIHIsIGEwLCBhMSwgY3gsIGN5LCAwKTtcbn1cblxuLyoqXG4gKiBwYXRoIGEgc2VjdG9yXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHIgOiByYWRpdXNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMCA6IGZpcnN0IGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMSA6IHNlY29uZCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeCA6IHggY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN5IDogeSBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHJldHVybiB7c3RyaW5nfSBzdmcgcGF0aFxuICovXG5mdW5jdGlvbiBwYXRoU2VjdG9yKHIsIGEwLCBhMSwgY3gsIGN5KSB7XG4gICAgcmV0dXJuIF9wYXRoKG51bGwsIHIsIGEwLCBhMSwgY3gsIGN5LCAxKTtcbn1cblxuLyoqXG4gKiBwYXRoIGFuIGFubnVsdXNcbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gcjAgOiBmaXJzdCByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHIxIDogc2Vjb25kIHJhZGlhbCBjb29yZGluYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gYTAgOiBmaXJzdCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlcn0gYTEgOiBzZWNvbmQgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3ggOiB4IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeSA6IHkgY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEByZXR1cm4ge3N0cmluZ30gc3ZnIHBhdGhcbiAqL1xuZnVuY3Rpb24gcGF0aEFubnVsdXMocjAsIHIxLCBhMCwgYTEsIGN4LCBjeSkge1xuICAgIHJldHVybiBfcGF0aChyMCwgcjEsIGEwLCBhMSwgY3gsIGN5LCAxKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZGVnMnJhZDogZGVnMnJhZCxcbiAgICByYWQyZGVnOiByYWQyZGVnLFxuICAgIGFuZ2xlRGVsdGE6IGFuZ2xlRGVsdGEsXG4gICAgYW5nbGVEaXN0OiBhbmdsZURpc3QsXG4gICAgaXNGdWxsQ2lyY2xlOiBpc0Z1bGxDaXJjbGUsXG4gICAgaXNBbmdsZUluc2lkZVNlY3RvcjogaXNBbmdsZUluc2lkZVNlY3RvcixcbiAgICBpc1B0SW5zaWRlU2VjdG9yOiBpc1B0SW5zaWRlU2VjdG9yLFxuICAgIHBhdGhBcmM6IHBhdGhBcmMsXG4gICAgcGF0aFNlY3RvcjogcGF0aFNlY3RvcixcbiAgICBwYXRoQW5udWx1czogcGF0aEFubnVsdXNcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxuLy8gSUU5IGZhbGxiYWNrc1xuXG52YXIgYWIgPSAodHlwZW9mIEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJyB8fCAhQXJyYXlCdWZmZXIuaXNWaWV3KSA/XG4gICAge2lzVmlldzogZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZTsgfX0gOlxuICAgIEFycmF5QnVmZmVyO1xuXG52YXIgZHYgPSAodHlwZW9mIERhdGFWaWV3ID09PSAndW5kZWZpbmVkJykgP1xuICAgIGZ1bmN0aW9uKCkge30gOlxuICAgIERhdGFWaWV3O1xuXG5mdW5jdGlvbiBpc1R5cGVkQXJyYXkoYSkge1xuICAgIHJldHVybiBhYi5pc1ZpZXcoYSkgJiYgIShhIGluc3RhbmNlb2YgZHYpO1xufVxuZXhwb3J0cy5pc1R5cGVkQXJyYXkgPSBpc1R5cGVkQXJyYXk7XG5cbmZ1bmN0aW9uIGlzQXJyYXlPclR5cGVkQXJyYXkoYSkge1xuICAgIHJldHVybiBpc0FycmF5KGEpIHx8IGlzVHlwZWRBcnJheShhKTtcbn1cbmV4cG9ydHMuaXNBcnJheU9yVHlwZWRBcnJheSA9IGlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbi8qXG4gKiBUZXN0IHdoZXRoZXIgYW4gaW5wdXQgb2JqZWN0IGlzIDFELlxuICpcbiAqIEFzc3VtZXMgd2UgYWxyZWFkeSBrbm93IHRoZSBvYmplY3QgaXMgYW4gYXJyYXkuXG4gKlxuICogTG9va3Mgb25seSBhdCB0aGUgZmlyc3QgZWxlbWVudCwgaWYgdGhlIGRpbWVuc2lvbmFsaXR5IGlzXG4gKiBub3QgY29uc2lzdGVudCB3ZSB3b24ndCBmaWd1cmUgdGhhdCBvdXQgaGVyZS5cbiAqL1xuZnVuY3Rpb24gaXNBcnJheTFEKGEpIHtcbiAgICByZXR1cm4gIWlzQXJyYXlPclR5cGVkQXJyYXkoYVswXSk7XG59XG5leHBvcnRzLmlzQXJyYXkxRCA9IGlzQXJyYXkxRDtcblxuLypcbiAqIEVuc3VyZXMgYW4gYXJyYXkgaGFzIHRoZSByaWdodCBhbW91bnQgb2Ygc3RvcmFnZSBzcGFjZS4gSWYgaXQgZG9lc24ndFxuICogZXhpc3QsIGl0IGNyZWF0ZXMgYW4gYXJyYXkuIElmIGl0IGRvZXMgZXhpc3QsIGl0IHJldHVybnMgaXQgaWYgdG9vXG4gKiBzaG9ydCBvciB0cnVuY2F0ZXMgaXQgaW4tcGxhY2UuXG4gKlxuICogVGhlIGdvYWwgaXMgdG8ganVzdCByZXVzZSBtZW1vcnkgdG8gYXZvaWQgYSBiaXQgb2YgZXhjZXNzaXZlIGdhcmJhZ2VcbiAqIGNvbGxlY3Rpb24uXG4gKi9cbmV4cG9ydHMuZW5zdXJlQXJyYXkgPSBmdW5jdGlvbihvdXQsIG4pIHtcbiAgICAvLyBUT0RPOiB0eXBlZCBhcnJheSBzdXBwb3J0IGhlcmU/IFRoaXMgaXMgb25seSB1c2VkIGluXG4gICAgLy8gdHJhY2VzL2NhcnBldC9jb21wdXRlX2NvbnRyb2xfcG9pbnRzXG4gICAgaWYoIWlzQXJyYXkob3V0KSkgb3V0ID0gW107XG5cbiAgICAvLyBJZiB0b28gbG9uZywgdHJ1bmNhdGUuIChJZiB0b28gc2hvcnQsIGl0IHdpbGwgZ3Jvd1xuICAgIC8vIGF1dG9tYXRpY2FsbHkgc28gd2UgZG9uJ3QgY2FyZSBhYm91dCB0aGF0IGNhc2UpXG4gICAgb3V0Lmxlbmd0aCA9IG47XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLypcbiAqIFR5cGVkQXJyYXktY29tcGF0aWJsZSBjb25jYXRlbmF0aW9uIG9mIG4gYXJyYXlzXG4gKiBpZiBhbGwgYXJyYXlzIGFyZSB0aGUgc2FtZSB0eXBlIGl0IHdpbGwgcHJlc2VydmUgdGhhdCB0eXBlLFxuICogb3RoZXJ3aXNlIGl0IGZhbGxzIGJhY2sgb24gQXJyYXkuXG4gKiBBbHNvIHRyaWVzIHRvIGF2b2lkIGNvcHlpbmcsIGluIGNhc2Ugb25lIGFycmF5IGhhcyB6ZXJvIGxlbmd0aFxuICogQnV0IG5ldmVyIG11dGF0ZXMgYW4gZXhpc3RpbmcgYXJyYXlcbiAqL1xuZXhwb3J0cy5jb25jYXQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYXJncyA9IFtdO1xuICAgIHZhciBhbGxBcnJheSA9IHRydWU7XG4gICAgdmFyIHRvdGFsTGVuID0gMDtcblxuICAgIHZhciBfY29uc3RydWN0b3IsIGFyZzAsIGksIGFyZ2ksIHBvc2ksIGxlbmksIG91dCwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcmdpID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBsZW5pID0gYXJnaS5sZW5ndGg7XG4gICAgICAgIGlmKGxlbmkpIHtcbiAgICAgICAgICAgIGlmKGFyZzApIGFyZ3MucHVzaChhcmdpKTtcbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGFyZzAgPSBhcmdpO1xuICAgICAgICAgICAgICAgIHBvc2kgPSBsZW5pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc0FycmF5KGFyZ2kpKSB7XG4gICAgICAgICAgICAgICAgX2NvbnN0cnVjdG9yID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbGxBcnJheSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmKCF0b3RhbExlbikge1xuICAgICAgICAgICAgICAgICAgICBfY29uc3RydWN0b3IgPSBhcmdpLmNvbnN0cnVjdG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKF9jb25zdHJ1Y3RvciAhPT0gYXJnaS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBpbiBwcmluY2lwbGUgd2UgY291bGQgdXBncmFkZSBoZXJlLFxuICAgICAgICAgICAgICAgICAgICAvLyBpZSBrZWVwIHR5cGVkIGFycmF5IGJ1dCBjb252ZXJ0IGFsbCB0byBGbG9hdDY0QXJyYXk/XG4gICAgICAgICAgICAgICAgICAgIF9jb25zdHJ1Y3RvciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdG90YWxMZW4gKz0gbGVuaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCF0b3RhbExlbikgcmV0dXJuIFtdO1xuICAgIGlmKCFhcmdzLmxlbmd0aCkgcmV0dXJuIGFyZzA7XG5cbiAgICBpZihhbGxBcnJheSkgcmV0dXJuIGFyZzAuY29uY2F0LmFwcGx5KGFyZzAsIGFyZ3MpO1xuICAgIGlmKF9jb25zdHJ1Y3Rvcikge1xuICAgICAgICAvLyBtYXRjaGluZyB0eXBlZCBhcnJheXNcbiAgICAgICAgb3V0ID0gbmV3IF9jb25zdHJ1Y3Rvcih0b3RhbExlbik7XG4gICAgICAgIG91dC5zZXQoYXJnMCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ2kgPSBhcmdzW2ldO1xuICAgICAgICAgICAgb3V0LnNldChhcmdpLCBwb3NpKTtcbiAgICAgICAgICAgIHBvc2kgKz0gYXJnaS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyBtaXNtYXRjaGVkIHR5cGVzIG9yIEFycmF5ICsgdHlwZWRcbiAgICBvdXQgPSBuZXcgQXJyYXkodG90YWxMZW4pO1xuICAgIGZvcihqID0gMDsgaiA8IGFyZzAubGVuZ3RoOyBqKyspIG91dFtqXSA9IGFyZzBbal07XG4gICAgZm9yKGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcmdpID0gYXJnc1tpXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgYXJnaS5sZW5ndGg7IGorKykgb3V0W3Bvc2kgKyBqXSA9IGFyZ2lbal07XG4gICAgICAgIHBvc2kgKz0gajtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG4vLyBwcmVjb21waWxlIGZvciBzcGVlZFxudmFyIEpVTksgPSAvXlsnXCIlLCQjXFxzJ10rfFssIF18WydcIiUsJCNcXHMnXSskL2c7XG5cbi8qKlxuICogY2xlYW5OdW1iZXI6IHJlbW92ZSBjb21tb24gbGVhZGluZyBhbmQgdHJhaWxpbmcgY3J1ZnRcbiAqIEFsd2F5cyByZXR1cm5zIGVpdGhlciBhIG51bWJlciBvciBCQUROVU0uXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2xlYW5OdW1iZXIodikge1xuICAgIGlmKHR5cGVvZiB2ID09PSAnc3RyaW5nJykge1xuICAgICAgICB2ID0gdi5yZXBsYWNlKEpVTkssICcnKTtcbiAgICB9XG5cbiAgICBpZihpc051bWVyaWModikpIHJldHVybiBOdW1iZXIodik7XG5cbiAgICByZXR1cm4gQkFETlVNO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBDbGVhciBnbCBmcmFtZSAoaWYgYW55KS4gVGhpcyBpcyBhIGNvbW1vbiBwYXR0ZXJuIGFzXG4gKiB3ZSB1c3VhbGx5IHNldCBgcHJlc2VydmVEcmF3aW5nQnVmZmVyOiB0cnVlYCBkdXJpbmdcbiAqIGdsIGNvbnRleHQgY3JlYXRpb24gKGUuZy4gdmlhIGByZWdsVXRpbHMucHJlcGFyZWApLlxuICpcbiAqIEBwYXJhbSB7RE9NIG5vZGUgb3Igb2JqZWN0fSBnZCA6IGdyYXBoIGRpdiBvYmplY3RcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjbGVhckdsQ2FudmFzZXMoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoZnVsbExheW91dC5fZ2xjYW52YXMgJiYgZnVsbExheW91dC5fZ2xjYW52YXMuc2l6ZSgpKSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX2dsY2FudmFzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoZC5yZWdsKSBkLnJlZ2wuY2xlYXIoe2NvbG9yOiB0cnVlLCBkZXB0aDogdHJ1ZX0pO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIENsZWFyIHJlc3BvbnNpdmUgaGFuZGxlcnMgKGlmIGFueSkuXG4gKlxuICogQHBhcmFtIHtET00gbm9kZSBvciBvYmplY3R9IGdkIDogZ3JhcGggZGl2IG9iamVjdFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsZWFyUmVzcG9uc2l2ZShnZCkge1xuICAgIGlmKGdkLl9yZXNwb25zaXZlQ2hhcnRIYW5kbGVyKSB7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCBnZC5fcmVzcG9uc2l2ZUNoYXJ0SGFuZGxlcik7XG4gICAgICAgIGRlbGV0ZSBnZC5fcmVzcG9uc2l2ZUNoYXJ0SGFuZGxlcjtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIHRpbnljb2xvciA9IHJlcXVpcmUoJ3Rpbnljb2xvcjInKTtcblxudmFyIGJhc2VUcmFjZUF0dHJzID0gcmVxdWlyZSgnLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGdldENvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZ2V0X3NjYWxlJyk7XG52YXIgY29sb3JzY2FsZU5hbWVzID0gT2JqZWN0LmtleXMocmVxdWlyZSgnLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL3NjYWxlcycpKTtcbnZhciBuZXN0ZWRQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vbmVzdGVkX3Byb3BlcnR5Jyk7XG52YXIgY291bnRlclJlZ2V4ID0gcmVxdWlyZSgnLi9yZWdleCcpLmNvdW50ZXI7XG52YXIgREVTRUxFQ1RESU0gPSByZXF1aXJlKCcuLi9jb25zdGFudHMvaW50ZXJhY3Rpb25zJykuREVTRUxFQ1RESU07XG52YXIgbW9kSGFsZiA9IHJlcXVpcmUoJy4vbW9kJykubW9kSGFsZjtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi9hcnJheScpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbmV4cG9ydHMudmFsT2JqZWN0TWV0YSA9IHtcbiAgICBkYXRhX2FycmF5OiB7XG4gICAgICAgIC8vIFlvdSBjYW4gdXNlICpkZmx0PVtdIHRvIGZvcmNlIHNhaWQgYXJyYXkgdG8gZXhpc3QgdGhvdWdoLlxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgLy8gVE9ETyBtYXliZSBgdjoge3R5cGU6ICdmbG9hdDMyJywgdmFsczogWy8qIC4uLiAqL119YCBhbHNvXG4gICAgICAgICAgICBpZihpc0FycmF5T3JUeXBlZEFycmF5KHYpKSBwcm9wT3V0LnNldCh2KTtcbiAgICAgICAgICAgIGVsc2UgaWYoZGZsdCAhPT0gdW5kZWZpbmVkKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZW51bWVyYXRlZDoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgaWYob3B0cy5jb2VyY2VOdW1iZXIpIHYgPSArdjtcbiAgICAgICAgICAgIGlmKG9wdHMudmFsdWVzLmluZGV4T2YodikgPT09IC0xKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQodik7XG4gICAgICAgIH0sXG4gICAgICAgIHZhbGlkYXRlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmKG9wdHMuY29lcmNlTnVtYmVyKSB2ID0gK3Y7XG5cbiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBvcHRzLnZhbHVlcztcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgayA9IFN0cmluZyh2YWx1ZXNbaV0pO1xuXG4gICAgICAgICAgICAgICAgaWYoKGsuY2hhckF0KDApID09PSAnLycgJiYgay5jaGFyQXQoay5sZW5ndGggLSAxKSA9PT0gJy8nKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKGsuc3Vic3RyKDEsIGsubGVuZ3RoIC0gMikpO1xuICAgICAgICAgICAgICAgICAgICBpZihyZWdleC50ZXN0KHYpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodiA9PT0gdmFsdWVzW2ldKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ2Jvb2xlYW4nOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0KSB7XG4gICAgICAgICAgICBpZih2ID09PSB0cnVlIHx8IHYgPT09IGZhbHNlKSBwcm9wT3V0LnNldCh2KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG51bWJlcjoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyh2KSB8fFxuICAgICAgICAgICAgICAgICAgICAob3B0cy5taW4gIT09IHVuZGVmaW5lZCAmJiB2IDwgb3B0cy5taW4pIHx8XG4gICAgICAgICAgICAgICAgICAgIChvcHRzLm1heCAhPT0gdW5kZWZpbmVkICYmIHYgPiBvcHRzLm1heCkpIHtcbiAgICAgICAgICAgICAgICBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQoK3YpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBpbnRlZ2VyOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0LCBvcHRzKSB7XG4gICAgICAgICAgICBpZih2ICUgMSB8fCAhaXNOdW1lcmljKHYpIHx8XG4gICAgICAgICAgICAgICAgICAgIChvcHRzLm1pbiAhPT0gdW5kZWZpbmVkICYmIHYgPCBvcHRzLm1pbikgfHxcbiAgICAgICAgICAgICAgICAgICAgKG9wdHMubWF4ICE9PSB1bmRlZmluZWQgJiYgdiA+IG9wdHMubWF4KSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBwcm9wT3V0LnNldCgrdik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHN0cmluZzoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIC8vIFRPRE8gJ3ZhbHVlcyBzaG91bGRuJ3QgYmUgaW4gdGhlcmUgKGVkZ2UgY2FzZTogJ2Rhc2gnIGluIFNjYXR0ZXIpXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgaWYodHlwZW9mIHYgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9rVG9Db2VyY2UgPSAodHlwZW9mIHYgPT09ICdudW1iZXInKTtcblxuICAgICAgICAgICAgICAgIGlmKG9wdHMuc3RyaWN0ID09PSB0cnVlIHx8ICFva1RvQ29lcmNlKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KFN0cmluZyh2KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKG9wdHMubm9CbGFuayAmJiAhdikgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjb2xvcjoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgaWYodGlueWNvbG9yKHYpLmlzVmFsaWQoKSkgcHJvcE91dC5zZXQodik7XG4gICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjb2xvcmxpc3Q6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ29sb3IoY29sb3IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGlueWNvbG9yKGNvbG9yKS5pc1ZhbGlkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheSh2KSB8fCAhdi5sZW5ndGgpIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgZWxzZSBpZih2LmV2ZXJ5KGlzQ29sb3IpKSBwcm9wT3V0LnNldCh2KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNvbG9yc2NhbGU6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQpIHtcbiAgICAgICAgICAgIHByb3BPdXQuc2V0KGdldENvbG9yc2NhbGUodiwgZGZsdCkpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhbmdsZToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgaWYodiA9PT0gJ2F1dG8nKSBwcm9wT3V0LnNldCgnYXV0bycpO1xuICAgICAgICAgICAgZWxzZSBpZighaXNOdW1lcmljKHYpKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQobW9kSGFsZigrdiwgMzYwKSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHN1YnBsb3RpZDoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgdmFyIHJlZ2V4ID0gb3B0cy5yZWdleCB8fCBjb3VudGVyUmVnZXgoZGZsdCk7XG4gICAgICAgICAgICBpZih0eXBlb2YgdiA9PT0gJ3N0cmluZycgJiYgcmVnZXgudGVzdCh2KSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICB9LFxuICAgICAgICB2YWxpZGF0ZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgZGZsdCA9IG9wdHMuZGZsdDtcblxuICAgICAgICAgICAgaWYodiA9PT0gZGZsdCkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBpZih0eXBlb2YgdiAhPT0gJ3N0cmluZycpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIGlmKGNvdW50ZXJSZWdleChkZmx0KS50ZXN0KHYpKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBmbGFnbGlzdDoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgaWYodHlwZW9mIHYgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoKG9wdHMuZXh0cmFzIHx8IFtdKS5pbmRleE9mKHYpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB2UGFydHMgPSB2LnNwbGl0KCcrJyksXG4gICAgICAgICAgICAgICAgaSA9IDA7XG4gICAgICAgICAgICB3aGlsZShpIDwgdlBhcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciB2aSA9IHZQYXJ0c1tpXTtcbiAgICAgICAgICAgICAgICBpZihvcHRzLmZsYWdzLmluZGV4T2YodmkpID09PSAtMSB8fCB2UGFydHMuaW5kZXhPZih2aSkgPCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZQYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIXZQYXJ0cy5sZW5ndGgpIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgZWxzZSBwcm9wT3V0LnNldCh2UGFydHMuam9pbignKycpKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYW55OiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0KSB7XG4gICAgICAgICAgICBpZih2ID09PSB1bmRlZmluZWQpIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgZWxzZSBwcm9wT3V0LnNldCh2KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaW5mb19hcnJheToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIC8vIHNldCBgZGltZW5zaW9ucz0yYCBmb3IgYSAyRCBhcnJheSBvciAnMS0yJyBmb3IgZWl0aGVyXG4gICAgICAgIC8vIGBpdGVtc2AgbWF5IGJlIGEgc2luZ2xlIG9iamVjdCBpbnN0ZWFkIG9mIGFuIGFycmF5LCBpbiB3aGljaCBjYXNlXG4gICAgICAgIC8vIGBmcmVlTGVuZ3RoYCBtdXN0IGJlIHRydWUuXG4gICAgICAgIC8vIGlmIGBkaW1lbnNpb25zPScxLTInYCBhbmQgaXRlbXMgaXMgYSAxRCBhcnJheSwgdGhlbiB0aGUgdmFsdWUgY2FuXG4gICAgICAgIC8vIGVpdGhlciBiZSBhIG1hdGNoaW5nIDFEIGFycmF5IG9yIGFuIGFycmF5IG9mIHN1Y2ggbWF0Y2hpbmcgMUQgYXJyYXlzXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuXG4gICAgICAgICAgICAvLyBzaW1wbGlmaWVkIGNvZXJjZSBmdW5jdGlvbiBqdXN0IGZvciBhcnJheSBpdGVtc1xuICAgICAgICAgICAgZnVuY3Rpb24gY29lcmNlUGFydCh2LCBvcHRzLCBkZmx0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dDtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcFBhcnQgPSB7c2V0OiBmdW5jdGlvbih2KSB7IG91dCA9IHY7IH19O1xuXG4gICAgICAgICAgICAgICAgaWYoZGZsdCA9PT0gdW5kZWZpbmVkKSBkZmx0ID0gb3B0cy5kZmx0O1xuXG4gICAgICAgICAgICAgICAgZXhwb3J0cy52YWxPYmplY3RNZXRhW29wdHMudmFsVHlwZV0uY29lcmNlRnVuY3Rpb24odiwgcHJvcFBhcnQsIGRmbHQsIG9wdHMpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHR3b0QgPSBvcHRzLmRpbWVuc2lvbnMgPT09IDIgfHwgKG9wdHMuZGltZW5zaW9ucyA9PT0gJzEtMicgJiYgQXJyYXkuaXNBcnJheSh2KSAmJiBBcnJheS5pc0FycmF5KHZbMF0pKTtcblxuICAgICAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodikpIHtcbiAgICAgICAgICAgICAgICBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBpdGVtcyA9IG9wdHMuaXRlbXM7XG4gICAgICAgICAgICB2YXIgdk91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGFycmF5SXRlbXMgPSBBcnJheS5pc0FycmF5KGl0ZW1zKTtcbiAgICAgICAgICAgIHZhciBhcnJheUl0ZW1zMkQgPSBhcnJheUl0ZW1zICYmIHR3b0QgJiYgQXJyYXkuaXNBcnJheShpdGVtc1swXSk7XG4gICAgICAgICAgICB2YXIgaW5uZXJJdGVtc09ubHkgPSB0d29EICYmIGFycmF5SXRlbXMgJiYgIWFycmF5SXRlbXMyRDtcbiAgICAgICAgICAgIHZhciBsZW4gPSAoYXJyYXlJdGVtcyAmJiAhaW5uZXJJdGVtc09ubHkpID8gaXRlbXMubGVuZ3RoIDogdi5sZW5ndGg7XG5cbiAgICAgICAgICAgIHZhciBpLCBqLCByb3csIGl0ZW0sIGxlbjIsIHZOZXc7XG5cbiAgICAgICAgICAgIGRmbHQgPSBBcnJheS5pc0FycmF5KGRmbHQpID8gZGZsdCA6IFtdO1xuXG4gICAgICAgICAgICBpZih0d29EKSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdk91dFtpXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICByb3cgPSBBcnJheS5pc0FycmF5KHZbaV0pID8gdltpXSA6IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZihpbm5lckl0ZW1zT25seSkgbGVuMiA9IGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZihhcnJheUl0ZW1zKSBsZW4yID0gaXRlbXNbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGxlbjIgPSByb3cubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGxlbjI7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaW5uZXJJdGVtc09ubHkpIGl0ZW0gPSBpdGVtc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoYXJyYXlJdGVtcykgaXRlbSA9IGl0ZW1zW2ldW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpdGVtID0gaXRlbXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZOZXcgPSBjb2VyY2VQYXJ0KHJvd1tqXSwgaXRlbSwgKGRmbHRbaV0gfHwgW10pW2pdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHZOZXcgIT09IHVuZGVmaW5lZCkgdk91dFtpXVtqXSA9IHZOZXc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2TmV3ID0gY29lcmNlUGFydCh2W2ldLCBhcnJheUl0ZW1zID8gaXRlbXNbaV0gOiBpdGVtcywgZGZsdFtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZOZXcgIT09IHVuZGVmaW5lZCkgdk91dFtpXSA9IHZOZXc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwcm9wT3V0LnNldCh2T3V0KTtcbiAgICAgICAgfSxcbiAgICAgICAgdmFsaWRhdGVGdW5jdGlvbjogZnVuY3Rpb24odiwgb3B0cykge1xuICAgICAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodikpIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgICAgdmFyIGl0ZW1zID0gb3B0cy5pdGVtcztcbiAgICAgICAgICAgIHZhciBhcnJheUl0ZW1zID0gQXJyYXkuaXNBcnJheShpdGVtcyk7XG4gICAgICAgICAgICB2YXIgdHdvRCA9IG9wdHMuZGltZW5zaW9ucyA9PT0gMjtcblxuICAgICAgICAgICAgLy8gd2hlbiBmcmVlIGxlbmd0aCBpcyBvZmYsIGlucHV0IGFuZCBkZWNsYXJlZCBsZW5ndGhzIG11c3QgbWF0Y2hcbiAgICAgICAgICAgIGlmKCFvcHRzLmZyZWVMZW5ndGggJiYgdi5sZW5ndGggIT09IGl0ZW1zLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgICAgICAvLyB2YWxpZCB3aGVuIGFsbCBpbnB1dCBpdGVtcyBhcmUgdmFsaWRcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYodHdvRCkge1xuICAgICAgICAgICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheSh2W2ldKSB8fCAoIW9wdHMuZnJlZUxlbmd0aCAmJiB2W2ldLmxlbmd0aCAhPT0gaXRlbXNbaV0ubGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB2W2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZighdmFsaWRhdGUodltpXVtqXSwgYXJyYXlJdGVtcyA/IGl0ZW1zW2ldW2pdIDogaXRlbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYoIXZhbGlkYXRlKHZbaV0sIGFycmF5SXRlbXMgPyBpdGVtc1tpXSA6IGl0ZW1zKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogRW5zdXJlcyB0aGF0IGNvbnRhaW5lclthdHRyaWJ1dGVdIGhhcyBhIHZhbGlkIHZhbHVlLlxuICpcbiAqIGF0dHJpYnV0ZXNbYXR0cmlidXRlXSBpcyBhbiBvYmplY3Qgd2l0aCBwb3NzaWJsZSBrZXlzOlxuICogLSB2YWxUeXBlOiBkYXRhX2FycmF5LCBlbnVtZXJhdGVkLCBib29sZWFuLCAuLi4gYXMgaW4gdmFsT2JqZWN0TWV0YVxuICogLSB2YWx1ZXM6IChlbnVtZXJhdGVkIG9ubHkpIGFycmF5IG9mIGFsbG93ZWQgdmFsc1xuICogLSBtaW4sIG1heDogKG51bWJlciwgaW50ZWdlciBvbmx5KSBpbmNsdXNpdmUgYm91bmRzIG9uIGFsbG93ZWQgdmFsc1xuICogICAgICBlaXRoZXIgb3IgYm90aCBtYXkgYmUgb21pdHRlZFxuICogLSBkZmx0OiBpZiBhdHRyaWJ1dGUgaXMgaW52YWxpZCBvciBtaXNzaW5nLCB1c2UgdGhpcyBkZWZhdWx0XG4gKiAgICAgIGlmIGRmbHQgaXMgcHJvdmlkZWQgYXMgYW4gYXJndW1lbnQgdG8gbGliLmNvZXJjZSBpdCB0YWtlcyBwcmVjZWRlbmNlXG4gKiAgICAgIGFzIGEgY29udmVuaWVuY2UsIHJldHVybnMgdGhlIHZhbHVlIGl0IGZpbmFsbHkgc2V0XG4gKi9cbmV4cG9ydHMuY29lcmNlID0gZnVuY3Rpb24oY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0cmlidXRlLCBkZmx0KSB7XG4gICAgdmFyIG9wdHMgPSBuZXN0ZWRQcm9wZXJ0eShhdHRyaWJ1dGVzLCBhdHRyaWJ1dGUpLmdldCgpO1xuICAgIHZhciBwcm9wSW4gPSBuZXN0ZWRQcm9wZXJ0eShjb250YWluZXJJbiwgYXR0cmlidXRlKTtcbiAgICB2YXIgcHJvcE91dCA9IG5lc3RlZFByb3BlcnR5KGNvbnRhaW5lck91dCwgYXR0cmlidXRlKTtcbiAgICB2YXIgdiA9IHByb3BJbi5nZXQoKTtcblxuICAgIHZhciB0ZW1wbGF0ZSA9IGNvbnRhaW5lck91dC5fdGVtcGxhdGU7XG4gICAgaWYodiA9PT0gdW5kZWZpbmVkICYmIHRlbXBsYXRlKSB7XG4gICAgICAgIHYgPSBuZXN0ZWRQcm9wZXJ0eSh0ZW1wbGF0ZSwgYXR0cmlidXRlKS5nZXQoKTtcbiAgICAgICAgLy8gYWxyZWFkeSB1c2VkIHRoZSB0ZW1wbGF0ZSB2YWx1ZSwgc28gc2hvcnQtY2lyY3VpdCB0aGUgc2Vjb25kIGNoZWNrXG4gICAgICAgIHRlbXBsYXRlID0gMDtcbiAgICB9XG5cbiAgICBpZihkZmx0ID09PSB1bmRlZmluZWQpIGRmbHQgPSBvcHRzLmRmbHQ7XG5cbiAgICAvKipcbiAgICAgKiBhcnJheU9rOiB2YWx1ZSBNQVkgYmUgYW4gYXJyYXksIHRoZW4gd2UgZG8gbm8gdmFsdWUgY2hlY2tpbmdcbiAgICAgKiBhdCB0aGlzIHBvaW50LCBiZWNhdXNlIGl0IGNhbiBiZSBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gdGhlXG4gICAgICogaW5kaXZpZHVhbCBmb3JtIChlZy4gc29tZSBhcnJheSB2YWxzIGNhbiBiZSBudW1iZXJzLCBldmVuIGlmIHRoZVxuICAgICAqIHNpbmdsZSB2YWx1ZXMgbXVzdCBiZSBjb2xvciBzdHJpbmdzKVxuICAgICAqL1xuICAgIGlmKG9wdHMuYXJyYXlPayAmJiBpc0FycmF5T3JUeXBlZEFycmF5KHYpKSB7XG4gICAgICAgIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICByZXR1cm4gdjtcbiAgICB9XG5cbiAgICB2YXIgY29lcmNlRnVuY3Rpb24gPSBleHBvcnRzLnZhbE9iamVjdE1ldGFbb3B0cy52YWxUeXBlXS5jb2VyY2VGdW5jdGlvbjtcbiAgICBjb2VyY2VGdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0LCBvcHRzKTtcblxuICAgIHZhciBvdXQgPSBwcm9wT3V0LmdldCgpO1xuICAgIC8vIGluIGNhc2UgdiB3YXMgcHJvdmlkZWQgYnV0IGludmFsaWQsIHRyeSB0aGUgdGVtcGxhdGUgYWdhaW4gc28gaXQgc3RpbGxcbiAgICAvLyBvdmVycmlkZXMgdGhlIHJlZ3VsYXIgZGVmYXVsdFxuICAgIGlmKHRlbXBsYXRlICYmIG91dCA9PT0gZGZsdCAmJiAhdmFsaWRhdGUodiwgb3B0cykpIHtcbiAgICAgICAgdiA9IG5lc3RlZFByb3BlcnR5KHRlbXBsYXRlLCBhdHRyaWJ1dGUpLmdldCgpO1xuICAgICAgICBjb2VyY2VGdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0LCBvcHRzKTtcbiAgICAgICAgb3V0ID0gcHJvcE91dC5nZXQoKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVmFyaWF0aW9uIG9uIGNvZXJjZVxuICpcbiAqIFVzZXMgY29lcmNlIHRvIGdldCBhdHRyaWJ1dGUgdmFsdWUgaWYgdXNlciBpbnB1dCBpcyB2YWxpZCxcbiAqIHJldHVybnMgYXR0cmlidXRlIGRlZmF1bHQgaWYgdXNlciBpbnB1dCBpdCBub3QgdmFsaWQgb3JcbiAqIHJldHVybnMgZmFsc2UgaWYgdGhlcmUgaXMgbm8gdXNlciBpbnB1dC5cbiAqL1xuZXhwb3J0cy5jb2VyY2UyID0gZnVuY3Rpb24oY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0cmlidXRlLCBkZmx0KSB7XG4gICAgdmFyIHByb3BJbiA9IG5lc3RlZFByb3BlcnR5KGNvbnRhaW5lckluLCBhdHRyaWJ1dGUpLFxuICAgICAgICBwcm9wT3V0ID0gZXhwb3J0cy5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0cmlidXRlLCBkZmx0KSxcbiAgICAgICAgdmFsSW4gPSBwcm9wSW4uZ2V0KCk7XG5cbiAgICByZXR1cm4gKHZhbEluICE9PSB1bmRlZmluZWQgJiYgdmFsSW4gIT09IG51bGwpID8gcHJvcE91dCA6IGZhbHNlO1xufTtcblxuLypcbiAqIFNob3J0Y3V0IHRvIGNvZXJjZSB0aGUgdGhyZWUgZm9udCBhdHRyaWJ1dGVzXG4gKlxuICogJ2NvZXJjZScgaXMgYSBsaWIuY29lcmNlIHdyYXBwZXIgd2l0aCBpbXBsaWVkIGZpcnN0IHRocmVlIGFyZ3VtZW50c1xuICovXG5leHBvcnRzLmNvZXJjZUZvbnQgPSBmdW5jdGlvbihjb2VyY2UsIGF0dHIsIGRmbHRPYmopIHtcbiAgICB2YXIgb3V0ID0ge307XG5cbiAgICBkZmx0T2JqID0gZGZsdE9iaiB8fCB7fTtcblxuICAgIG91dC5mYW1pbHkgPSBjb2VyY2UoYXR0ciArICcuZmFtaWx5JywgZGZsdE9iai5mYW1pbHkpO1xuICAgIG91dC5zaXplID0gY29lcmNlKGF0dHIgKyAnLnNpemUnLCBkZmx0T2JqLnNpemUpO1xuICAgIG91dC5jb2xvciA9IGNvZXJjZShhdHRyICsgJy5jb2xvcicsIGRmbHRPYmouY29sb3IpO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKiBDb2VyY2Ugc2hvcnRjdXQgZm9yICdob3ZlcmluZm8nXG4gKiBoYW5kbGluZyAxLXZzLW11bHRpLXRyYWNlIGRmbHQgbG9naWNcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VJbiA6IHVzZXIgdHJhY2Ugb2JqZWN0XG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VPdXQgOiBmdWxsIHRyYWNlIG9iamVjdCAocmVxdWlyZXMgX21vZHVsZSByZWYpXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0T3V0IDogZnVsbCBsYXlvdXQgb2JqZWN0IChyZXF1aXJlIF9kYXRhTGVuZ3RoIHJlZilcbiAqIEByZXR1cm4ge2FueX0gOiB0aGUgY29lcmNlZCB2YWx1ZVxuICovXG5leHBvcnRzLmNvZXJjZUhvdmVyaW5mbyA9IGZ1bmN0aW9uKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgbW9kdWxlQXR0cnMgPSB0cmFjZU91dC5fbW9kdWxlLmF0dHJpYnV0ZXM7XG4gICAgdmFyIGF0dHJzID0gbW9kdWxlQXR0cnMuaG92ZXJpbmZvID8gbW9kdWxlQXR0cnMgOiBiYXNlVHJhY2VBdHRycztcblxuICAgIHZhciB2YWxPYmogPSBhdHRycy5ob3ZlcmluZm87XG4gICAgdmFyIGRmbHQ7XG5cbiAgICBpZihsYXlvdXRPdXQuX2RhdGFMZW5ndGggPT09IDEpIHtcbiAgICAgICAgdmFyIGZsYWdzID0gdmFsT2JqLmRmbHQgPT09ICdhbGwnID9cbiAgICAgICAgICAgIHZhbE9iai5mbGFncy5zbGljZSgpIDpcbiAgICAgICAgICAgIHZhbE9iai5kZmx0LnNwbGl0KCcrJyk7XG5cbiAgICAgICAgZmxhZ3Muc3BsaWNlKGZsYWdzLmluZGV4T2YoJ25hbWUnKSwgMSk7XG4gICAgICAgIGRmbHQgPSBmbGFncy5qb2luKCcrJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4cG9ydHMuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRycywgJ2hvdmVyaW5mbycsIGRmbHQpO1xufTtcblxuLyoqIENvZXJjZSBzaG9ydGN1dCBmb3IgW3VuXXNlbGVjdGVkLm1hcmtlci5vcGFjaXR5LFxuICogIHdoaWNoIGhhcyBzcGVjaWFsIGRlZmF1bHQgbG9naWMsIHRvIGVuc3VyZSB0aGF0IGl0IGNvcnJlc3BvbmRzIHRvIHRoZVxuICogIGRlZmF1bHQgc2VsZWN0aW9uIGJlaGF2aW9yIHdoaWxlIGFsbG93aW5nIHRvIGJlIG92ZXJ0YWtlbiBieSBhbnkgb3RoZXJcbiAqICBbdW5dc2VsZWN0ZWQgYXR0cmlidXRlLlxuICpcbiAqICBOLkIuIFRoaXMgbXVzdCBiZSBjYWxsZWQgKmFmdGVyKiBjb2VyY2luZyBhbGwgdGhlIG90aGVyIFt1bl1zZWxlY3RlZCBhdHRycyxcbiAqICB0byBnaXZlIHRoZSBpbnRlbmRlZCByZXN1bHQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlT3V0IDogZnVsbERhdGEgaXRlbVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY29lcmNlIDogbGliLmNvZXJjZSB3cmFwcGVyIHdpdGggaW1wbGllZCBmaXJzdCB0aHJlZSBhcmd1bWVudHNcbiAqL1xuZXhwb3J0cy5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5ID0gZnVuY3Rpb24odHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIGlmKCF0cmFjZU91dC5tYXJrZXIpIHJldHVybjtcblxuICAgIHZhciBtbyA9IHRyYWNlT3V0Lm1hcmtlci5vcGFjaXR5O1xuICAgIC8vIHlvdSBjYW4gc3RpbGwgaGF2ZSBhIGBtYXJrZXJgIGNvbnRhaW5lciB3aXRoIG5vIG1hcmtlcnMgaWYgdGhlcmUncyB0ZXh0XG4gICAgaWYobW8gPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgdmFyIHNtb0RmbHQ7XG4gICAgdmFyIHVzbW9EZmx0O1xuXG4gICAgLy8gRG9uJ3QgZ2l2ZSBbdW5dc2VsZWN0ZWQubWFya2VyLm9wYWNpdHkgYSBkZWZhdWx0IHZhbHVlIGlmXG4gICAgLy8gbWFya2VyLm9wYWNpdHkgaXMgYW4gYXJyYXk6IGhhbmRsZSB0aGlzIGR1cmluZyBzdHlsZSBzdGVwLlxuICAgIC8vXG4gICAgLy8gT25seSBnaXZlIFt1bl1zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSBhIGRlZmF1bHQgdmFsdWUgaWYgeW91IGRvbid0XG4gICAgLy8gc2V0IGFueSBvdGhlciBbdW5dc2VsZWN0ZWQgYXR0cmlidXRlcy5cbiAgICBpZighaXNBcnJheU9yVHlwZWRBcnJheShtbykgJiYgIXRyYWNlT3V0LnNlbGVjdGVkICYmICF0cmFjZU91dC51bnNlbGVjdGVkKSB7XG4gICAgICAgIHNtb0RmbHQgPSBtbztcbiAgICAgICAgdXNtb0RmbHQgPSBERVNFTEVDVERJTSAqIG1vO1xuICAgIH1cblxuICAgIGNvZXJjZSgnc2VsZWN0ZWQubWFya2VyLm9wYWNpdHknLCBzbW9EZmx0KTtcbiAgICBjb2VyY2UoJ3Vuc2VsZWN0ZWQubWFya2VyLm9wYWNpdHknLCB1c21vRGZsdCk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZSh2YWx1ZSwgb3B0cykge1xuICAgIHZhciB2YWxPYmplY3REZWYgPSBleHBvcnRzLnZhbE9iamVjdE1ldGFbb3B0cy52YWxUeXBlXTtcblxuICAgIGlmKG9wdHMuYXJyYXlPayAmJiBpc0FycmF5T3JUeXBlZEFycmF5KHZhbHVlKSkgcmV0dXJuIHRydWU7XG5cbiAgICBpZih2YWxPYmplY3REZWYudmFsaWRhdGVGdW5jdGlvbikge1xuICAgICAgICByZXR1cm4gdmFsT2JqZWN0RGVmLnZhbGlkYXRlRnVuY3Rpb24odmFsdWUsIG9wdHMpO1xuICAgIH1cblxuICAgIHZhciBmYWlsZWQgPSB7fSxcbiAgICAgICAgb3V0ID0gZmFpbGVkLFxuICAgICAgICBwcm9wTW9jayA9IHsgc2V0OiBmdW5jdGlvbih2KSB7IG91dCA9IHY7IH0gfTtcblxuICAgIC8vICdmYWlsZWQnIGp1c3Qgc29tZXRoaW5nIG11dGFibGUgdGhhdCB3b24ndCBiZSA9PT0gYW55dGhpbmcgZWxzZVxuXG4gICAgdmFsT2JqZWN0RGVmLmNvZXJjZUZ1bmN0aW9uKHZhbHVlLCBwcm9wTW9jaywgZmFpbGVkLCBvcHRzKTtcbiAgICByZXR1cm4gb3V0ICE9PSBmYWlsZWQ7XG59XG5leHBvcnRzLnZhbGlkYXRlID0gdmFsaWRhdGU7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTG9nZ2VycyA9IHJlcXVpcmUoJy4vbG9nZ2VycycpO1xudmFyIG1vZCA9IHJlcXVpcmUoJy4vbW9kJykubW9kO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL251bWVyaWNhbCcpO1xudmFyIEJBRE5VTSA9IGNvbnN0YW50cy5CQUROVU07XG52YXIgT05FREFZID0gY29uc3RhbnRzLk9ORURBWTtcbnZhciBPTkVIT1VSID0gY29uc3RhbnRzLk9ORUhPVVI7XG52YXIgT05FTUlOID0gY29uc3RhbnRzLk9ORU1JTjtcbnZhciBPTkVTRUMgPSBjb25zdGFudHMuT05FU0VDO1xudmFyIEVQT0NISkQgPSBjb25zdGFudHMuRVBPQ0hKRDtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vcmVnaXN0cnknKTtcblxudmFyIHV0Y0Zvcm1hdCA9IGQzLnRpbWUuZm9ybWF0LnV0YztcblxudmFyIERBVEVUSU1FX1JFR0VYUCA9IC9eXFxzKigtP1xcZFxcZFxcZFxcZHxcXGRcXGQpKC0oXFxkP1xcZCkoLShcXGQ/XFxkKShbIFR0XShbMDFdP1xcZHwyWzAtM10pKDooWzAtNV1cXGQpKDooWzAtNV1cXGQoXFwuXFxkKyk/KSk/KFp8enxbK1xcLV1cXGRcXGQ6P1xcZFxcZCk/KT8pPyk/KT9cXHMqJC9tO1xuLy8gc3BlY2lhbCByZWdleCBmb3IgY2hpbmVzZSBjYWxlbmRhcnMgdG8gc3VwcG9ydCB5eXl5LW1taS1kZCBldGMgZm9yIGludGVyY2FsYXJ5IG1vbnRoc1xudmFyIERBVEVUSU1FX1JFR0VYUF9DTiA9IC9eXFxzKigtP1xcZFxcZFxcZFxcZHxcXGRcXGQpKC0oXFxkP1xcZGk/KSgtKFxcZD9cXGQpKFsgVHRdKFswMV0/XFxkfDJbMC0zXSkoOihbMC01XVxcZCkoOihbMC01XVxcZChcXC5cXGQrKT8pKT8oWnx6fFsrXFwtXVxcZFxcZDo/XFxkXFxkKT8pPyk/KT8pP1xccyokL207XG5cbi8vIGZvciAyLWRpZ2l0IHllYXJzLCB0aGUgZmlyc3QgeWVhciB3ZSBtYXAgdGhlbSBvbnRvXG52YXIgWUZJUlNUID0gbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpIC0gNzA7XG5cbmZ1bmN0aW9uIGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikge1xuICAgIHJldHVybiAoXG4gICAgICAgIGNhbGVuZGFyICYmXG4gICAgICAgIFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeS5jYWxlbmRhcnMgJiZcbiAgICAgICAgdHlwZW9mIGNhbGVuZGFyID09PSAnc3RyaW5nJyAmJiBjYWxlbmRhciAhPT0gJ2dyZWdvcmlhbidcbiAgICApO1xufVxuXG4vKlxuICogZGF0ZVRpY2swOiBnZXQgdGhlIGNhbm9uaWNhbCB0aWNrIGZvciB0aGlzIGNhbGVuZGFyXG4gKlxuICogYm9vbCBzdW5kYXkgaXMgZm9yIHdlZWsgdGlja3MsIHNoaWZ0IGl0IHRvIGEgU3VuZGF5LlxuICovXG5leHBvcnRzLmRhdGVUaWNrMCA9IGZ1bmN0aW9uKGNhbGVuZGFyLCBzdW5kYXkpIHtcbiAgICBpZihpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiBzdW5kYXkgP1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnQ0FOT05JQ0FMX1NVTkRBWScpW2NhbGVuZGFyXSA6XG4gICAgICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdDQU5PTklDQUxfVElDSycpW2NhbGVuZGFyXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBzdW5kYXkgPyAnMjAwMC0wMS0wMicgOiAnMjAwMC0wMS0wMSc7XG4gICAgfVxufTtcblxuLypcbiAqIGRmbHRSYW5nZTogZm9yIGVhY2ggY2FsZW5kYXIsIGdpdmUgYSB2YWxpZCBkZWZhdWx0IHJhbmdlXG4gKi9cbmV4cG9ydHMuZGZsdFJhbmdlID0gZnVuY3Rpb24oY2FsZW5kYXIpIHtcbiAgICBpZihpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpKSB7XG4gICAgICAgIHJldHVybiBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdERkxUUkFOR0UnKVtjYWxlbmRhcl07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gWycyMDAwLTAxLTAxJywgJzIwMDEtMDEtMDEnXTtcbiAgICB9XG59O1xuXG4vLyBpcyBhbiBvYmplY3QgYSBqYXZhc2NyaXB0IGRhdGU/XG5leHBvcnRzLmlzSlNEYXRlID0gZnVuY3Rpb24odikge1xuICAgIHJldHVybiB0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgdiAhPT0gbnVsbCAmJiB0eXBlb2Ygdi5nZXRUaW1lID09PSAnZnVuY3Rpb24nO1xufTtcblxuLy8gVGhlIGFic29sdXRlIGxpbWl0cyBvZiBvdXIgZGF0ZS10aW1lIHN5c3RlbVxuLy8gVGhpcyBpcyBhIGxpdHRsZSB3ZWlyZDogd2UgdXNlIE1JTl9NUyBhbmQgTUFYX01TIGluIGRhdGVUaW1lMm1zXG4vLyBidXQgd2UgdXNlIGRhdGVUaW1lMm1zIHRvIGNhbGN1bGF0ZSB0aGVtIChhZnRlciBkZWZpbmluZyBpdCEpXG52YXIgTUlOX01TLCBNQVhfTVM7XG5cbi8qKlxuICogZGF0ZVRpbWUybXMgLSB0dXJuIGEgZGF0ZSBvYmplY3Qgb3Igc3RyaW5nIHMgaW50byBtaWxsaXNlY29uZHNcbiAqIChyZWxhdGl2ZSB0byAxOTcwLTAxLTAxLCBwZXIgamF2YXNjcmlwdCBzdGFuZGFyZClcbiAqIG9wdGlvbmFsIGNhbGVuZGFyIChzdHJpbmcpIHRvIHVzZSBhIG5vbi1ncmVnb3JpYW4gY2FsZW5kYXJcbiAqXG4gKiBSZXR1cm5zIEJBRE5VTSBpZiBpdCBkb2Vzbid0IGZpbmQgYSBkYXRlXG4gKlxuICogc3RyaW5ncyBzaG91bGQgaGF2ZSB0aGUgZm9ybTpcbiAqXG4gKiAgICAtP1lZWVktbW0tZGQ8c2VwPkhIOk1NOlNTLnNzczx0ekluZm8+P1xuICpcbiAqIDxzZXA+OiBzcGFjZSAob3VyIG5vcm1hbCBzdGFuZGFyZCkgb3IgVCBvciB0IChJU08tODYwMSlcbiAqIDx0ekluZm8+OiBaLCB6LCBvciBbK1xcLV1ISDo/TU0gYW5kIHdlIFRIUk9XIElUIEFXQVlcbiAqIHRoaXMgZm9ybWF0IGNvbWVzIGZyb20gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzMzMzkjc2VjdGlvbi01LjZcbiAqIGJ1dCB3ZSBhbGxvdyBpdCBldmVuIHdpdGggYSBzcGFjZSBhcyB0aGUgc2VwYXJhdG9yXG4gKlxuICogTWF5IHRydW5jYXRlIGFmdGVyIGFueSBmdWxsIGZpZWxkLCBhbmQgc3NzIGNhbiBiZSBhbnkgbGVuZ3RoXG4gKiBldmVuID4zIGRpZ2l0cywgdGhvdWdoIGphdmFzY3JpcHQgZGF0ZXMgdHJ1bmNhdGUgdG8gbWlsbGlzZWNvbmRzLFxuICogd2Uga2VlcCBhcyBtdWNoIGFzIGphdmFzY3JpcHQgbnVtZXJpYyBwcmVjaXNpb24gY2FuIGhvbGQsIGJ1dCB3ZSBvbmx5XG4gKiByZXBvcnQgYmFjayB1cCB0byAxMDAgbWljcm9zZWNvbmQgcHJlY2lzaW9uLCBiZWNhdXNlIG1vc3QgZGF0ZXMgc3VwcG9ydFxuICogdGhpcyBwcmVjaXNpb24gKGNsb3NlIHRvIDE5NzAgc3VwcG9ydCBtb3JlLCB2ZXJ5IGZhciBhd2F5IHN1cHBvcnQgbGVzcylcbiAqXG4gKiBFeHBhbmRlZCB0byBzdXBwb3J0IG5lZ2F0aXZlIHllYXJzIHRvIC05OTk5IGJ1dCB5b3UgbXVzdCBhbHdheXNcbiAqIGdpdmUgNCBkaWdpdHMsIGV4Y2VwdCBmb3IgMi1kaWdpdCBwb3NpdGl2ZSB5ZWFycyB3aGljaCB3ZSBhc3N1bWUgYXJlXG4gKiBuZWFyIHRoZSBwcmVzZW50IHRpbWUuXG4gKiBOb3RlIHRoYXQgd2UgZm9sbG93IElTTyA4NjAxOjIwMDQ6IHRoZXJlICppcyogYSB5ZWFyIDAsIHdoaWNoXG4gKiBpcyAxQkMvQkNFLCBhbmQgLTE9PT0yQkMgZXRjLlxuICpcbiAqIFdvcmxkIGNhbGVuZGFyczogbm90IGFsbCBvZiB0aGVzZSAqaGF2ZSogYWdyZWVkIGV4dGVuc2lvbnMgdG8gdGhpcyBmdWxsIHJhbmdlLFxuICogaWYgeW91IGhhdmUgYW5vdGhlciBjYWxlbmRhciBzeXN0ZW0gYnV0IHdhbnQgYSBkYXRlIHJhbmdlIG91dHNpZGUgaXRzIHZhbGlkaXR5LFxuICogeW91IGNhbiB1c2UgYSBncmVnb3JpYW4gZGF0ZSBzdHJpbmcgcHJlZml4ZWQgd2l0aCAnRycgb3IgJ2cnLlxuICpcbiAqIFdoZXJlIHRvIGN1dCBvZmYgMi1kaWdpdCB5ZWFycyBiZXR3ZWVuIDE5MDBzIGFuZCAyMDAwcz9cbiAqIGZyb20gaHR0cDovL3N1cHBvcnQubWljcm9zb2Z0LmNvbS9rYi8yNDQ2NjQ6XG4gKiAgIDE5MzAtMjAyOSAodGhlIG1vc3QgcmV0cm8gb2YgYWxsLi4uKVxuICogYnV0IGluIG15IG1hYyBjaHJvbWUgZnJvbSBlZy4gZD1uZXcgRGF0ZShEYXRlLnBhcnNlKCc4LzE5LzUwJykpOlxuICogICAxOTUwLTIwNDlcbiAqIGJ5IEphdmEsIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDI0MjczLzpcbiAqICAgbm93LTgwIC0gbm93KzE5XG4gKiBvciBGaWxlTWFrZXIgUHJvLCBmcm9tXG4gKiAgICAgIGh0dHA6Ly93d3cuZmlsZW1ha2VyLmNvbS8xMmhlbHAvaHRtbC9hZGRfdmlld19kYXRhLjQuMjEuaHRtbDpcbiAqICAgbm93LTcwIC0gbm93KzI5XG4gKiBidXQgcHl0aG9uIHN0cnB0aW1lIGV0YywgdmlhXG4gKiAgICAgIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvcHkzay9saWJyYXJ5L3RpbWUuaHRtbDpcbiAqICAgMTk2OS0yMDY4IChzdXBlciBmb3J3YXJkLWxvb2tpbmcsIGJ1dCBzdGF0aWMsIG5vdCBzbGlkaW5nISlcbiAqXG4gKiBsZXRzIGdvIHdpdGggbm93LTcwIHRvIG5vdysyOSwgYW5kIGlmIGFueW9uZSBydW5zIGludG8gdGhpcyBwcm9ibGVtXG4gKiB0aGV5IGNhbiBsZWFybiB0aGUgaGFyZCB3YXkgbm90IHRvIHVzZSAyLWRpZ2l0IHllYXJzLCBhcyBubyBjaG9pY2Ugd2VcbiAqIG1ha2Ugbm93IHdpbGwgY292ZXIgYWxsIHBvc3NpYmlsaXRpZXMuIG1vc3RseSB0aGlzIHdpbGwgYWxsIGJlIHRha2VuXG4gKiBjYXJlIG9mIGluIGluaXRpYWwgcGFyc2luZywgc2hvdWxkIG9ubHkgYmUgYW4gaXNzdWUgZm9yIGhhbmQtZW50ZXJlZCBkYXRhXG4gKiBjdXJyZW50bHkgKDIwMTYpIHRoaXMgcmFuZ2UgaXM6XG4gKiAgIDE5NDYtMjA0NVxuICovXG5leHBvcnRzLmRhdGVUaW1lMm1zID0gZnVuY3Rpb24ocywgY2FsZW5kYXIpIHtcbiAgICAvLyBmaXJzdCBjaGVjayBpZiBzIGlzIGEgZGF0ZSBvYmplY3RcbiAgICBpZihleHBvcnRzLmlzSlNEYXRlKHMpKSB7XG4gICAgICAgIC8vIENvbnZlcnQgdG8gdGhlIFVUQyBtaWxsaXNlY29uZHMgdGhhdCBnaXZlIHRoZSBzYW1lXG4gICAgICAgIC8vIGhvdXJzIGFzIHRoaXMgZGF0ZSBoYXMgaW4gdGhlIGxvY2FsIHRpbWV6b25lXG4gICAgICAgIHZhciB0ek9mZnNldCA9IHMuZ2V0VGltZXpvbmVPZmZzZXQoKSAqIE9ORU1JTjtcbiAgICAgICAgdmFyIG9mZnNldFR3ZWFrID0gKHMuZ2V0VVRDTWludXRlcygpIC0gcy5nZXRNaW51dGVzKCkpICogT05FTUlOICtcbiAgICAgICAgICAgIChzLmdldFVUQ1NlY29uZHMoKSAtIHMuZ2V0U2Vjb25kcygpKSAqIE9ORVNFQyArXG4gICAgICAgICAgICAocy5nZXRVVENNaWxsaXNlY29uZHMoKSAtIHMuZ2V0TWlsbGlzZWNvbmRzKCkpO1xuXG4gICAgICAgIGlmKG9mZnNldFR3ZWFrKSB7XG4gICAgICAgICAgICB2YXIgY29tYiA9IDMgKiBPTkVNSU47XG4gICAgICAgICAgICB0ek9mZnNldCA9IHR6T2Zmc2V0IC0gY29tYiAvIDIgKyBtb2Qob2Zmc2V0VHdlYWsgLSB0ek9mZnNldCArIGNvbWIgLyAyLCBjb21iKTtcbiAgICAgICAgfVxuICAgICAgICBzID0gTnVtYmVyKHMpIC0gdHpPZmZzZXQ7XG4gICAgICAgIGlmKHMgPj0gTUlOX01TICYmIHMgPD0gTUFYX01TKSByZXR1cm4gcztcbiAgICAgICAgcmV0dXJuIEJBRE5VTTtcbiAgICB9XG4gICAgLy8gb3RoZXJ3aXNlIG9ubHkgYWNjZXB0IHN0cmluZ3MgYW5kIG51bWJlcnNcbiAgICBpZih0eXBlb2YgcyAhPT0gJ3N0cmluZycgJiYgdHlwZW9mIHMgIT09ICdudW1iZXInKSByZXR1cm4gQkFETlVNO1xuXG4gICAgcyA9IFN0cmluZyhzKTtcblxuICAgIHZhciBpc1dvcmxkID0gaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKTtcblxuICAgIC8vIHRvIGhhbmRsZSBvdXQtb2YtcmFuZ2UgZGF0ZXMgaW4gaW50ZXJuYXRpb25hbCBjYWxlbmRhcnMsIGFjY2VwdFxuICAgIC8vICdHJyBhcyBhIHByZWZpeCB0byBmb3JjZSB0aGUgYnVpbHQtaW4gZ3JlZ29yaWFuIGNhbGVuZGFyLlxuICAgIHZhciBzMCA9IHMuY2hhckF0KDApO1xuICAgIGlmKGlzV29ybGQgJiYgKHMwID09PSAnRycgfHwgczAgPT09ICdnJykpIHtcbiAgICAgICAgcyA9IHMuc3Vic3RyKDEpO1xuICAgICAgICBjYWxlbmRhciA9ICcnO1xuICAgIH1cblxuICAgIHZhciBpc0NoaW5lc2UgPSBpc1dvcmxkICYmIGNhbGVuZGFyLnN1YnN0cigwLCA3KSA9PT0gJ2NoaW5lc2UnO1xuXG4gICAgdmFyIG1hdGNoID0gcy5tYXRjaChpc0NoaW5lc2UgPyBEQVRFVElNRV9SRUdFWFBfQ04gOiBEQVRFVElNRV9SRUdFWFApO1xuICAgIGlmKCFtYXRjaCkgcmV0dXJuIEJBRE5VTTtcbiAgICB2YXIgeSA9IG1hdGNoWzFdLFxuICAgICAgICBtID0gbWF0Y2hbM10gfHwgJzEnLFxuICAgICAgICBkID0gTnVtYmVyKG1hdGNoWzVdIHx8IDEpLFxuICAgICAgICBIID0gTnVtYmVyKG1hdGNoWzddIHx8IDApLFxuICAgICAgICBNID0gTnVtYmVyKG1hdGNoWzldIHx8IDApLFxuICAgICAgICBTID0gTnVtYmVyKG1hdGNoWzExXSB8fCAwKTtcblxuICAgIGlmKGlzV29ybGQpIHtcbiAgICAgICAgLy8gZGlzYWxsb3cgMi1kaWdpdCB5ZWFycyBmb3Igd29ybGQgY2FsZW5kYXJzXG4gICAgICAgIGlmKHkubGVuZ3RoID09PSAyKSByZXR1cm4gQkFETlVNO1xuICAgICAgICB5ID0gTnVtYmVyKHkpO1xuXG4gICAgICAgIHZhciBjRGF0ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBjYWxJbnN0YW5jZSA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2dldENhbCcpKGNhbGVuZGFyKTtcbiAgICAgICAgICAgIGlmKGlzQ2hpbmVzZSkge1xuICAgICAgICAgICAgICAgIHZhciBpc0ludGVyY2FsYXJ5ID0gbS5jaGFyQXQobS5sZW5ndGggLSAxKSA9PT0gJ2knO1xuICAgICAgICAgICAgICAgIG0gPSBwYXJzZUludChtLCAxMCk7XG4gICAgICAgICAgICAgICAgY0RhdGUgPSBjYWxJbnN0YW5jZS5uZXdEYXRlKHksIGNhbEluc3RhbmNlLnRvTW9udGhJbmRleCh5LCBtLCBpc0ludGVyY2FsYXJ5KSwgZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjRGF0ZSA9IGNhbEluc3RhbmNlLm5ld0RhdGUoeSwgTnVtYmVyKG0pLCBkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaChlKSB7IHJldHVybiBCQUROVU07IH0gLy8gSW52YWxpZCAuLi4gZGF0ZVxuXG4gICAgICAgIGlmKCFjRGF0ZSkgcmV0dXJuIEJBRE5VTTtcblxuICAgICAgICByZXR1cm4gKChjRGF0ZS50b0pEKCkgLSBFUE9DSEpEKSAqIE9ORURBWSkgK1xuICAgICAgICAgICAgKEggKiBPTkVIT1VSKSArIChNICogT05FTUlOKSArIChTICogT05FU0VDKTtcbiAgICB9XG5cbiAgICBpZih5Lmxlbmd0aCA9PT0gMikge1xuICAgICAgICB5ID0gKE51bWJlcih5KSArIDIwMDAgLSBZRklSU1QpICUgMTAwICsgWUZJUlNUO1xuICAgIH1cbiAgICBlbHNlIHkgPSBOdW1iZXIoeSk7XG5cbiAgICAvLyBuZXcgRGF0ZSB1c2VzIG1vbnRocyBmcm9tIDA7IHN1YnRyYWN0IDEgaGVyZSBqdXN0IHNvIHdlXG4gICAgLy8gZG9uJ3QgaGF2ZSB0byBkbyBpdCBhZ2FpbiBkdXJpbmcgdGhlIHZhbGlkaXR5IHRlc3QgYmVsb3dcbiAgICBtIC09IDE7XG5cbiAgICAvLyBqYXZhc2NyaXB0IHRha2VzIG5ldyBEYXRlKDAuLjk5LG0sZCkgdG8gbWVhbiAxOTAwLTE5OTksIHNvXG4gICAgLy8gdG8gc3VwcG9ydCB5ZWFycyAwLTk5IHdlIG5lZWQgdG8gdXNlIHNldEZ1bGxZZWFyIGV4cGxpY2l0bHlcbiAgICAvLyBOb3RlIHRoYXQgMjAwMCBpcyBhIGxlYXAgeWVhci5cbiAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKDIwMDAsIG0sIGQsIEgsIE0pKTtcbiAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKHkpO1xuXG4gICAgaWYoZGF0ZS5nZXRVVENNb250aCgpICE9PSBtKSByZXR1cm4gQkFETlVNO1xuICAgIGlmKGRhdGUuZ2V0VVRDRGF0ZSgpICE9PSBkKSByZXR1cm4gQkFETlVNO1xuXG4gICAgcmV0dXJuIGRhdGUuZ2V0VGltZSgpICsgUyAqIE9ORVNFQztcbn07XG5cbk1JTl9NUyA9IGV4cG9ydHMuTUlOX01TID0gZXhwb3J0cy5kYXRlVGltZTJtcygnLTk5OTknKTtcbk1BWF9NUyA9IGV4cG9ydHMuTUFYX01TID0gZXhwb3J0cy5kYXRlVGltZTJtcygnOTk5OS0xMi0zMSAyMzo1OTo1OS45OTk5Jyk7XG5cbi8vIGlzIHN0cmluZyBzIGEgZGF0ZT8gKHNlZSBhYm92ZSlcbmV4cG9ydHMuaXNEYXRlVGltZSA9IGZ1bmN0aW9uKHMsIGNhbGVuZGFyKSB7XG4gICAgcmV0dXJuIChleHBvcnRzLmRhdGVUaW1lMm1zKHMsIGNhbGVuZGFyKSAhPT0gQkFETlVNKTtcbn07XG5cbi8vIHBhZCBhIG51bWJlciB3aXRoIHplcm9lcywgdG8gZ2l2ZW4gIyBvZiBkaWdpdHMgYmVmb3JlIHRoZSBkZWNpbWFsIHBvaW50XG5mdW5jdGlvbiBscGFkKHZhbCwgZGlnaXRzKSB7XG4gICAgcmV0dXJuIFN0cmluZyh2YWwgKyBNYXRoLnBvdygxMCwgZGlnaXRzKSkuc3Vic3RyKDEpO1xufVxuXG4vKipcbiAqIFR1cm4gbXMgaW50byBzdHJpbmcgb2YgdGhlIGZvcm0gWVlZWS1tbS1kZCBISDpNTTpTUy5zc3NzXG4gKiBDcm9wIGFueSB0cmFpbGluZyB6ZXJvcyBpbiB0aW1lLCBleGNlcHQgbmV2ZXIgc3RvcCByaWdodCBhZnRlciBob3Vyc1xuICogKHdlIGNvdWxkIGNob29zZSB0byBjcm9wICctMDEnIGZyb20gZGF0ZSB0b28gYnV0IGZvciBub3cgd2UgYWx3YXlzXG4gKiBzaG93IHRoZSB3aG9sZSBkYXRlKVxuICogT3B0aW9uYWwgcmFuZ2UgciBpcyB0aGUgZGF0YSByYW5nZSB0aGF0IGFwcGxpZXMsIGFsc28gaW4gbXMuXG4gKiBJZiBybmcgaXMgYmlnLCB0aGUgbGF0ZXIgcGFydHMgb2YgdGltZSB3aWxsIGJlIG9taXR0ZWRcbiAqL1xudmFyIE5JTkVUWURBWVMgPSA5MCAqIE9ORURBWTtcbnZhciBUSFJFRUhPVVJTID0gMyAqIE9ORUhPVVI7XG52YXIgRklWRU1JTiA9IDUgKiBPTkVNSU47XG5leHBvcnRzLm1zMkRhdGVUaW1lID0gZnVuY3Rpb24obXMsIHIsIGNhbGVuZGFyKSB7XG4gICAgaWYodHlwZW9mIG1zICE9PSAnbnVtYmVyJyB8fCAhKG1zID49IE1JTl9NUyAmJiBtcyA8PSBNQVhfTVMpKSByZXR1cm4gQkFETlVNO1xuXG4gICAgaWYoIXIpIHIgPSAwO1xuXG4gICAgdmFyIG1zZWNUZW50aHMgPSBNYXRoLmZsb29yKG1vZChtcyArIDAuMDUsIDEpICogMTApLFxuICAgICAgICBtc1JvdW5kZWQgPSBNYXRoLnJvdW5kKG1zIC0gbXNlY1RlbnRocyAvIDEwKSxcbiAgICAgICAgZGF0ZVN0ciwgaCwgbSwgcywgbXNlYzEwLCBkO1xuXG4gICAgaWYoaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKSkge1xuICAgICAgICB2YXIgZGF0ZUpEID0gTWF0aC5mbG9vcihtc1JvdW5kZWQgLyBPTkVEQVkpICsgRVBPQ0hKRCxcbiAgICAgICAgICAgIHRpbWVNcyA9IE1hdGguZmxvb3IobW9kKG1zLCBPTkVEQVkpKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGRhdGVTdHIgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdnZXRDYWwnKShjYWxlbmRhcilcbiAgICAgICAgICAgICAgICAuZnJvbUpEKGRhdGVKRCkuZm9ybWF0RGF0ZSgneXl5eS1tbS1kZCcpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoKGUpIHtcbiAgICAgICAgICAgIC8vIGludmFsaWQgZGF0ZSBpbiB0aGlzIGNhbGVuZGFyIC0gZmFsbCBiYWNrIHRvIEd5eXl5LW1tLWRkXG4gICAgICAgICAgICBkYXRlU3RyID0gdXRjRm9ybWF0KCdHJVktJW0tJWQnKShuZXcgRGF0ZShtc1JvdW5kZWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHl5eXkgZG9lcyBOT1QgZ3VhcmFudGVlIDQtZGlnaXQgeWVhcnMuIFlZWVkgbW9zdGx5IGRvZXMsIGJ1dCBkb2VzXG4gICAgICAgIC8vIG90aGVyIHRoaW5ncyBmb3IgYSBmZXcgY2FsZW5kYXJzLCBzbyB3ZSBjYW4ndCB0cnVzdCBpdC4gSnVzdCBwYWRcbiAgICAgICAgLy8gaXQgbWFudWFsbHkgKGFmdGVyIHRoZSAnLScgaWYgdGhlcmUgaXMgb25lKVxuICAgICAgICBpZihkYXRlU3RyLmNoYXJBdCgwKSA9PT0gJy0nKSB7XG4gICAgICAgICAgICB3aGlsZShkYXRlU3RyLmxlbmd0aCA8IDExKSBkYXRlU3RyID0gJy0wJyArIGRhdGVTdHIuc3Vic3RyKDEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgd2hpbGUoZGF0ZVN0ci5sZW5ndGggPCAxMCkgZGF0ZVN0ciA9ICcwJyArIGRhdGVTdHI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiBpZiB0aGlzIGlzIGZhc3Rlciwgd2UgY291bGQgdXNlIHRoaXMgYmxvY2sgZm9yIGV4dHJhY3RpbmdcbiAgICAgICAgLy8gdGhlIHRpbWUgY29tcG9uZW50cyBvZiByZWd1bGFyIGdyZWdvcmlhbiB0b29cbiAgICAgICAgaCA9IChyIDwgTklORVRZREFZUykgPyBNYXRoLmZsb29yKHRpbWVNcyAvIE9ORUhPVVIpIDogMDtcbiAgICAgICAgbSA9IChyIDwgTklORVRZREFZUykgPyBNYXRoLmZsb29yKCh0aW1lTXMgJSBPTkVIT1VSKSAvIE9ORU1JTikgOiAwO1xuICAgICAgICBzID0gKHIgPCBUSFJFRUhPVVJTKSA/IE1hdGguZmxvb3IoKHRpbWVNcyAlIE9ORU1JTikgLyBPTkVTRUMpIDogMDtcbiAgICAgICAgbXNlYzEwID0gKHIgPCBGSVZFTUlOKSA/ICh0aW1lTXMgJSBPTkVTRUMpICogMTAgKyBtc2VjVGVudGhzIDogMDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGQgPSBuZXcgRGF0ZShtc1JvdW5kZWQpO1xuXG4gICAgICAgIGRhdGVTdHIgPSB1dGNGb3JtYXQoJyVZLSVtLSVkJykoZCk7XG5cbiAgICAgICAgLy8gPDkwIGRheXM6IGFkZCBob3VycyBhbmQgbWludXRlcyAtIG5ldmVyICpvbmx5KiBhZGQgaG91cnNcbiAgICAgICAgaCA9IChyIDwgTklORVRZREFZUykgPyBkLmdldFVUQ0hvdXJzKCkgOiAwO1xuICAgICAgICBtID0gKHIgPCBOSU5FVFlEQVlTKSA/IGQuZ2V0VVRDTWludXRlcygpIDogMDtcbiAgICAgICAgLy8gPDMgaG91cnM6IGFkZCBzZWNvbmRzXG4gICAgICAgIHMgPSAociA8IFRIUkVFSE9VUlMpID8gZC5nZXRVVENTZWNvbmRzKCkgOiAwO1xuICAgICAgICAvLyA8NSBtaW51dGVzOiBhZGQgbXMgKHBsdXMgb25lIGV4dHJhIGRpZ2l0LCB0aGlzIGlzIG1zZWMqMTApXG4gICAgICAgIG1zZWMxMCA9IChyIDwgRklWRU1JTikgPyBkLmdldFVUQ01pbGxpc2Vjb25kcygpICogMTAgKyBtc2VjVGVudGhzIDogMDtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5jbHVkZVRpbWUoZGF0ZVN0ciwgaCwgbSwgcywgbXNlYzEwKTtcbn07XG5cbi8vIEZvciBjb252ZXJ0aW5nIG9sZC1zdHlsZSBtaWxsaXNlY29uZHMgdG8gZGF0ZSBzdHJpbmdzLFxuLy8gd2UgdXNlIHRoZSBsb2NhbCB0aW1lem9uZSByYXRoZXIgdGhhbiBVVEMgbGlrZSB3ZSB1c2Vcbi8vIGV2ZXJ5d2hlcmUgZWxzZSwgYm90aCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBhbmRcbi8vIGJlY2F1c2UgdGhhdCdzIGhvdyBwZW9wbGUgbW9zdGx5IHVzZSBqYXZhc3JpcHQgZGF0ZSBvYmplY3RzLlxuLy8gQ2xpcCBvbmUgZXh0cmEgZGF5IG9mZiBvdXIgZGF0ZSByYW5nZSB0aG91Z2ggc28gd2UgY2FuJ3QgZ2V0XG4vLyB0aHJvd24gYmV5b25kIHRoZSByYW5nZSBieSB0aGUgdGltZXpvbmUgc2hpZnQuXG5leHBvcnRzLm1zMkRhdGVUaW1lTG9jYWwgPSBmdW5jdGlvbihtcykge1xuICAgIGlmKCEobXMgPj0gTUlOX01TICsgT05FREFZICYmIG1zIDw9IE1BWF9NUyAtIE9ORURBWSkpIHJldHVybiBCQUROVU07XG5cbiAgICB2YXIgbXNlY1RlbnRocyA9IE1hdGguZmxvb3IobW9kKG1zICsgMC4wNSwgMSkgKiAxMCksXG4gICAgICAgIGQgPSBuZXcgRGF0ZShNYXRoLnJvdW5kKG1zIC0gbXNlY1RlbnRocyAvIDEwKSksXG4gICAgICAgIGRhdGVTdHIgPSBkMy50aW1lLmZvcm1hdCgnJVktJW0tJWQnKShkKSxcbiAgICAgICAgaCA9IGQuZ2V0SG91cnMoKSxcbiAgICAgICAgbSA9IGQuZ2V0TWludXRlcygpLFxuICAgICAgICBzID0gZC5nZXRTZWNvbmRzKCksXG4gICAgICAgIG1zZWMxMCA9IGQuZ2V0VVRDTWlsbGlzZWNvbmRzKCkgKiAxMCArIG1zZWNUZW50aHM7XG5cbiAgICByZXR1cm4gaW5jbHVkZVRpbWUoZGF0ZVN0ciwgaCwgbSwgcywgbXNlYzEwKTtcbn07XG5cbmZ1bmN0aW9uIGluY2x1ZGVUaW1lKGRhdGVTdHIsIGgsIG0sIHMsIG1zZWMxMCkge1xuICAgIC8vIGluY2x1ZGUgZWFjaCBwYXJ0IHRoYXQgaGFzIG5vbnplcm8gZGF0YSBpbiBvciBhZnRlciBpdFxuICAgIGlmKGggfHwgbSB8fCBzIHx8IG1zZWMxMCkge1xuICAgICAgICBkYXRlU3RyICs9ICcgJyArIGxwYWQoaCwgMikgKyAnOicgKyBscGFkKG0sIDIpO1xuICAgICAgICBpZihzIHx8IG1zZWMxMCkge1xuICAgICAgICAgICAgZGF0ZVN0ciArPSAnOicgKyBscGFkKHMsIDIpO1xuICAgICAgICAgICAgaWYobXNlYzEwKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZ2l0cyA9IDQ7XG4gICAgICAgICAgICAgICAgd2hpbGUobXNlYzEwICUgMTAgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzIC09IDE7XG4gICAgICAgICAgICAgICAgICAgIG1zZWMxMCAvPSAxMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGF0ZVN0ciArPSAnLicgKyBscGFkKG1zZWMxMCwgZGlnaXRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGF0ZVN0cjtcbn1cblxuLy8gbm9ybWFsaXplIGRhdGUgZm9ybWF0IHRvIGRhdGUgc3RyaW5nLCBpbiBjYXNlIGl0IHN0YXJ0cyBhc1xuLy8gYSBEYXRlIG9iamVjdCBvciBtaWxsaXNlY29uZHNcbi8vIG9wdGlvbmFsIGRmbHQgaXMgdGhlIHJldHVybiB2YWx1ZSBpZiBjbGVhbmluZyBmYWlsc1xuZXhwb3J0cy5jbGVhbkRhdGUgPSBmdW5jdGlvbih2LCBkZmx0LCBjYWxlbmRhcikge1xuICAgIC8vIGxldCB1cyB1c2UgY2xlYW5EYXRlIHRvIHByb3ZpZGUgYSBtaXNzaW5nIGRlZmF1bHQgd2l0aG91dCBhbiBlcnJvclxuICAgIGlmKHYgPT09IEJBRE5VTSkgcmV0dXJuIGRmbHQ7XG4gICAgaWYoZXhwb3J0cy5pc0pTRGF0ZSh2KSB8fCAodHlwZW9mIHYgPT09ICdudW1iZXInICYmIGlzRmluaXRlKHYpKSkge1xuICAgICAgICAvLyBkbyBub3QgYWxsb3cgbWlsbGlzZWNvbmRzIChvbGQpIG9yIGpzZGF0ZSBvYmplY3RzIChpbmhlcmVudGx5XG4gICAgICAgIC8vIGRlc2NyaWJlZCBhcyBncmVnb3JpYW4gZGF0ZXMpIHdpdGggd29ybGQgY2FsZW5kYXJzXG4gICAgICAgIGlmKGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikpIHtcbiAgICAgICAgICAgIExvZ2dlcnMuZXJyb3IoJ0pTIERhdGVzIGFuZCBtaWxsaXNlY29uZHMgYXJlIGluY29tcGF0aWJsZSB3aXRoIHdvcmxkIGNhbGVuZGFycycsIHYpO1xuICAgICAgICAgICAgcmV0dXJuIGRmbHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOT1RFOiBpZiBzb21lb25lIHB1dHMgaW4gYSB5ZWFyIGFzIGEgbnVtYmVyIHJhdGhlciB0aGFuIGEgc3RyaW5nLFxuICAgICAgICAvLyB0aGlzIHdpbGwgbWlzdGFrZW5seSBjb252ZXJ0IGl0IHRoaW5raW5nIGl0J3MgbWlsbGlzZWNvbmRzIGZyb20gMTk3MFxuICAgICAgICAvLyB0aGF0IGlzOiAnMjAxMicgLT4gSmFuLiAxLCAyMDEyLCBidXQgMjAxMiAtPiAyMDEyIGVwb2NoIG1pbGxpc2Vjb25kc1xuICAgICAgICB2ID0gZXhwb3J0cy5tczJEYXRlVGltZUxvY2FsKCt2KTtcbiAgICAgICAgaWYoIXYgJiYgZGZsdCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gZGZsdDtcbiAgICB9XG4gICAgZWxzZSBpZighZXhwb3J0cy5pc0RhdGVUaW1lKHYsIGNhbGVuZGFyKSkge1xuICAgICAgICBMb2dnZXJzLmVycm9yKCd1bnJlY29nbml6ZWQgZGF0ZScsIHYpO1xuICAgICAgICByZXR1cm4gZGZsdDtcbiAgICB9XG4gICAgcmV0dXJuIHY7XG59O1xuXG4vKlxuICogIERhdGUgZm9ybWF0dGluZyBmb3IgdGlja3MgYW5kIGhvdmVydGV4dFxuICovXG5cbi8qXG4gKiBtb2REYXRlRm9ybWF0OiBTdXBwb3J0IHdvcmxkIGNhbGVuZGFycywgYW5kIGFkZCBvbmUgaXRlbSB0b1xuICogZDMncyB2b2NhYnVsYXJ5OlxuICogJXtufWYgd2hlcmUgbiBpcyB0aGUgbWF4IG51bWJlciBvZiBkaWdpdHMgb2YgZnJhY3Rpb25hbCBzZWNvbmRzXG4gKi9cbnZhciBmcmFjTWF0Y2ggPSAvJVxcZD9mL2c7XG5mdW5jdGlvbiBtb2REYXRlRm9ybWF0KGZtdCwgeCwgZm9ybWF0dGVyLCBjYWxlbmRhcikge1xuXG4gICAgZm10ID0gZm10LnJlcGxhY2UoZnJhY01hdGNoLCBmdW5jdGlvbihtYXRjaCkge1xuICAgICAgICB2YXIgZGlnaXRzID0gTWF0aC5taW4oKyhtYXRjaC5jaGFyQXQoMSkpIHx8IDYsIDYpLFxuICAgICAgICAgICAgZnJhY1NlY3MgPSAoKHggLyAxMDAwICUgMSkgKyAyKVxuICAgICAgICAgICAgICAgIC50b0ZpeGVkKGRpZ2l0cylcbiAgICAgICAgICAgICAgICAuc3Vic3RyKDIpLnJlcGxhY2UoLzArJC8sICcnKSB8fCAnMCc7XG4gICAgICAgIHJldHVybiBmcmFjU2VjcztcbiAgICB9KTtcblxuICAgIHZhciBkID0gbmV3IERhdGUoTWF0aC5mbG9vcih4ICsgMC4wNSkpO1xuXG4gICAgaWYoaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm10ID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnd29ybGRDYWxGbXQnKShmbXQsIHgsIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaChlKSB7XG4gICAgICAgICAgICByZXR1cm4gJ0ludmFsaWQnO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmb3JtYXR0ZXIoZm10KShkKTtcbn1cblxuLypcbiAqIGZvcm1hdFRpbWU6IGNyZWF0ZSBhIHRpbWUgc3RyaW5nIGZyb206XG4gKiAgIHg6IG1pbGxpc2Vjb25kc1xuICogICB0cjogdGlja3JvdW5kICgnTScsICdTJywgb3IgIyBkaWdpdHMpXG4gKiBvbmx5IHN1cHBvcnRzIFVUQyB0aW1lcyAod2hlcmUgZXZlcnkgZGF5IGlzIDI0IGhvdXJzIGFuZCAwIGlzIGF0IG1pZG5pZ2h0KVxuICovXG52YXIgTUFYU0VDT05EUyA9IFs1OSwgNTkuOSwgNTkuOTksIDU5Ljk5OSwgNTkuOTk5OV07XG5mdW5jdGlvbiBmb3JtYXRUaW1lKHgsIHRyKSB7XG4gICAgdmFyIHRpbWVQYXJ0ID0gbW9kKHggKyAwLjA1LCBPTkVEQVkpO1xuXG4gICAgdmFyIHRpbWVTdHIgPSBscGFkKE1hdGguZmxvb3IodGltZVBhcnQgLyBPTkVIT1VSKSwgMikgKyAnOicgK1xuICAgICAgICBscGFkKG1vZChNYXRoLmZsb29yKHRpbWVQYXJ0IC8gT05FTUlOKSwgNjApLCAyKTtcblxuICAgIGlmKHRyICE9PSAnTScpIHtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyh0cikpIHRyID0gMDsgLy8gc2hvdWxkIG9ubHkgYmUgJ1MnXG5cbiAgICAgICAgLypcbiAgICAgICAgICogdGhpcyBpcyBhIHdlaXJkIG9uZSAtIGFuZCBzaG91bGRuJ3QgY29tZSB1cCB1bmxlc3MgcGVvcGxlXG4gICAgICAgICAqIG1vbmtleSB3aXRoIHRpY2swIGluIHdlaXJkIHdheXMsIGJ1dCB3ZSBuZWVkIHRvIGRvIHNvbWV0aGluZyFcbiAgICAgICAgICogSU4gUEFSVElDVUxBUiB3ZSBoYWQgYmV0dGVyIG5vdCBkaXNwbGF5IGdhcmJhZ2UgKHNlZSBiZWxvdylcbiAgICAgICAgICogZm9yIG51bWJlcnMgd2UgYWx3YXlzIHJvdW5kIHRvIHRoZSBuZWFyZXN0IGluY3JlbWVudCBvZiB0aGVcbiAgICAgICAgICogcHJlY2lzaW9uIHdlJ3JlIHNob3dpbmcsIGFuZCB0aGlzIHNlZW1zIGxpa2UgdGhlIHJpZ2h0IHdheSB0b1xuICAgICAgICAgKiBoYW5kbGUgc2Vjb25kcyBhbmQgbWlsbGlzZWNvbmRzLCBhcyB0aGV5IGhhdmUgYSBkZWNpbWFsIHBvaW50XG4gICAgICAgICAqIGFuZCBwZW9wbGUgd2lsbCBpbnRlcnByZXQgdGhhdCB0byBtZWFuIHJvdW5kaW5nIGxpa2UgbnVtYmVycy5cbiAgICAgICAgICogYnV0IGZvciBsYXJnZXIgaW5jcmVtZW50cyB3ZSBmbG9vciB0aGUgdmFsdWU6IGl0J3MgYWx3YXlzXG4gICAgICAgICAqIDIwMTMgdW50aWwgdGhlIGJhbGwgZHJvcHMgb24gdGhlIG5ldyB5ZWFyLiBXZSBjb3VsZCBhcmd1ZSBhYm91dFxuICAgICAgICAgKiB3aGljaCBmaWVsZCBpdCBpcyB3aGVyZSB3ZSBzdGFydCByb3VuZGluZyAoc2hvdWxkIDEyOjA4OjU5XG4gICAgICAgICAqIHJvdW5kIHRvIDEyOjA5IGlmIHdlJ3JlIHN0b3BwaW5nIGF0IG1pbnV0ZXM/KSBidXQgZm9yIG5vdyBJJ2xsXG4gICAgICAgICAqIHNheSB3ZSByb3VuZCBzZWNvbmRzIGJ1dCBmbG9vciBldmVyeXRoaW5nIGVsc2UuIEJVVCB0aGF0IG1lYW5zXG4gICAgICAgICAqIHdlIG5lZWQgdG8gbmV2ZXIgcm91bmQgdXAgdG8gNjAgc2Vjb25kcywgaWUgMjM6NTk6NjBcbiAgICAgICAgICovXG4gICAgICAgIHZhciBzZWMgPSBNYXRoLm1pbihtb2QoeCAvIE9ORVNFQywgNjApLCBNQVhTRUNPTkRTW3RyXSk7XG5cbiAgICAgICAgdmFyIHNlY1N0ciA9ICgxMDAgKyBzZWMpLnRvRml4ZWQodHIpLnN1YnN0cigxKTtcbiAgICAgICAgaWYodHIgPiAwKSB7XG4gICAgICAgICAgICBzZWNTdHIgPSBzZWNTdHIucmVwbGFjZSgvMCskLywgJycpLnJlcGxhY2UoL1tcXC5dJC8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbWVTdHIgKz0gJzonICsgc2VjU3RyO1xuICAgIH1cbiAgICByZXR1cm4gdGltZVN0cjtcbn1cblxuLypcbiAqIGZvcm1hdERhdGU6IHR1cm4gYSBkYXRlIGludG8gdGljayBvciBob3ZlciBsYWJlbCB0ZXh0LlxuICpcbiAqICAgeDogbWlsbGlzZWNvbmRzLCB0aGUgdmFsdWUgdG8gY29udmVydFxuICogICBmbXQ6IG9wdGlvbmFsLCBhbiBleHBsaWNpdCBmb3JtYXQgc3RyaW5nIChkMyBmb3JtYXQsIGV2ZW4gZm9yIHdvcmxkIGNhbGVuZGFycylcbiAqICAgdHI6IHRpY2tyb3VuZCAoJ3knLCAnbScsICdkJywgJ00nLCAnUycsIG9yICMgZGlnaXRzKVxuICogICAgICB1c2VkIGlmIG5vIGV4cGxpY2l0IGZtdCBpcyBwcm92aWRlZFxuICogICBmb3JtYXR0ZXI6IGxvY2FsZS1hd2FyZSBkMyBkYXRlIGZvcm1hdHRlciBmb3Igc3RhbmRhcmQgZ3JlZ29yaWFuIGNhbGVuZGFyc1xuICogICAgICBzaG91bGQgYmUgdGhlIHJlc3VsdCBvZiBleHBvcnRzLmdldEQzRGF0ZUZvcm1hdChnZClcbiAqICAgY2FsZW5kYXI6IG9wdGlvbmFsIHN0cmluZywgdGhlIHdvcmxkIGNhbGVuZGFyIHN5c3RlbSB0byB1c2VcbiAqXG4gKiByZXR1cm5zIHRoZSBkYXRlL3RpbWUgYXMgYSBzdHJpbmcsIHBvdGVudGlhbGx5IHdpdGggdGhlIGxlYWRpbmcgcG9ydGlvblxuICogb24gYSBzZXBhcmF0ZSBsaW5lIChhZnRlciAnXFxuJylcbiAqIE5vdGUgdGhhdCB0aGlzIG1lYW5zIGlmIHlvdSBwcm92aWRlIGFuIGV4cGxpY2l0IGZvcm1hdCB3aGljaCBpbmNsdWRlcyAnXFxuJ1xuICogdGhlIGF4aXMgbWF5IGNob29zZSB0byBzdHJpcCB0aGluZ3MgYWZ0ZXIgaXQgd2hlbiB0aGV5IGRvbid0IGNoYW5nZSBmcm9tXG4gKiBvbmUgdGljayB0byB0aGUgbmV4dCAoYXMgaXQgZG9lcyB3aXRoIGF1dG9tYXRpYyBmb3JtYXR0aW5nKVxuICovXG5leHBvcnRzLmZvcm1hdERhdGUgPSBmdW5jdGlvbih4LCBmbXQsIHRyLCBmb3JtYXR0ZXIsIGNhbGVuZGFyLCBleHRyYUZvcm1hdCkge1xuICAgIGNhbGVuZGFyID0gaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKSAmJiBjYWxlbmRhcjtcblxuICAgIGlmKCFmbXQpIHtcbiAgICAgICAgaWYodHIgPT09ICd5JykgZm10ID0gZXh0cmFGb3JtYXQueWVhcjtcbiAgICAgICAgZWxzZSBpZih0ciA9PT0gJ20nKSBmbXQgPSBleHRyYUZvcm1hdC5tb250aDtcbiAgICAgICAgZWxzZSBpZih0ciA9PT0gJ2QnKSB7XG4gICAgICAgICAgICBmbXQgPSBleHRyYUZvcm1hdC5kYXlNb250aCArICdcXG4nICsgZXh0cmFGb3JtYXQueWVhcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRUaW1lKHgsIHRyKSArICdcXG4nICsgbW9kRGF0ZUZvcm1hdChleHRyYUZvcm1hdC5kYXlNb250aFllYXIsIHgsIGZvcm1hdHRlciwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZERhdGVGb3JtYXQoZm10LCB4LCBmb3JtYXR0ZXIsIGNhbGVuZGFyKTtcbn07XG5cbi8qXG4gKiBpbmNyZW1lbnRNb250aDogbWFrZSBhIG5ldyBtaWxsaXNlY29uZHMgdmFsdWUgZnJvbSB0aGUgZ2l2ZW4gb25lLFxuICogaGF2aW5nIGNoYW5nZWQgdGhlIG1vbnRoXG4gKlxuICogc3BlY2lhbCBjYXNlIGZvciB3b3JsZCBjYWxlbmRhcnM6IG11bHRpcGxlcyBvZiAxMiBhcmUgdHJlYXRlZCBhcyB5ZWFycyxcbiAqIGV2ZW4gZm9yIGNhbGVuZGFyIHN5c3RlbXMgdGhhdCBkb24ndCBoYXZlIChhbHdheXMgb3IgZXZlcikgMTIgbW9udGhzL3llYXJcbiAqIFRPRE86IHBlcmhhcHMgd2UgbmVlZCBhIGRpZmZlcmVudCBjb2RlIGZvciB5ZWFyIGluY3JlbWVudHMgdG8gc3VwcG9ydCB0aGlzP1xuICpcbiAqIG1zIChudW1iZXIpOiB0aGUgaW5pdGlhbCBtaWxsaXNlY29uZCB2YWx1ZVxuICogZE1vbnRoIChpbnQpOiB0aGUgKHNpZ25lZCkgbnVtYmVyIG9mIG1vbnRocyB0byBzaGlmdFxuICogY2FsZW5kYXIgKHN0cmluZyk6IHRoZSBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlXG4gKlxuICogY2hhbmdpbmcgbW9udGggZG9lcyBub3QgKGFuZCBDQU5OT1QpIGFsd2F5cyBwcmVzZXJ2ZSBkYXksIHNpbmNlXG4gKiBtb250aHMgaGF2ZSBkaWZmZXJlbnQgbGVuZ3Rocy4gVGhlIHdvcnN0IGV4YW1wbGUgb2YgdGhpcyBpczpcbiAqICAgZCA9IG5ldyBEYXRlKDE5NzAsMCwzMSk7IGQuc2V0TW9udGgoMSkgLT4gRmViIDMxIHR1cm5zIGludG8gTWFyIDNcbiAqXG4gKiBCdXQgd2Ugd2FudCB0byBiZSBhYmxlIHRvIGl0ZXJhdGUgb3ZlciB0aGUgbGFzdCBkYXkgb2YgZWFjaCBtb250aCxcbiAqIHJlZ2FyZGxlc3Mgb2Ygd2hhdCBpdHMgbnVtYmVyIGlzLlxuICogU28gc2hpZnQgMyBkYXlzIGZvcndhcmQsIFRIRU4gc2V0IHRoZSBuZXcgbW9udGgsIHRoZW4gdW5zaGlmdDpcbiAqICAgMS8zMSAtPiAyLzI4IChvciAyOSkgLT4gMy8zMSAtPiA0LzMwIC0+IC4uLlxuICpcbiAqIE5vdGUgdGhhdCBvZGQgYmVoYXZpb3Igc3RpbGwgZXhpc3RzIGlmIHlvdSBzdGFydCBmcm9tIHRoZSAyNnRoLTI4dGg6XG4gKiAgIDEvMjggLT4gMi8yOCAtPiAzLzMxXG4gKiBidXQgYXQgbGVhc3QgeW91IGNhbid0IHNoaWZ0IGFueSBkYXRlcyBpbnRvIHRoZSB3cm9uZyBtb250aCxcbiAqIGFuZCB0aWNrcyBvbiB0aGVzZSBkYXlzIGluY3JlbWVudGluZyBieSBtb250aCB3b3VsZCBiZSB2ZXJ5IHVudXN1YWxcbiAqL1xudmFyIFRIUkVFREFZUyA9IDMgKiBPTkVEQVk7XG5leHBvcnRzLmluY3JlbWVudE1vbnRoID0gZnVuY3Rpb24obXMsIGRNb250aCwgY2FsZW5kYXIpIHtcbiAgICBjYWxlbmRhciA9IGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikgJiYgY2FsZW5kYXI7XG5cbiAgICAvLyBwdWxsIHRpbWUgb3V0IGFuZCBvcGVyYXRlIG9uIHB1cmUgZGF0ZXMsIHRoZW4gYWRkIHRpbWUgYmFjayBhdCB0aGUgZW5kXG4gICAgLy8gdGhpcyBnaXZlcyBtYXhpbXVtIHByZWNpc2lvbiAtIG5vdCB0aGF0IHdlICpub3JtYWxseSogY2FyZSBpZiB3ZSdyZVxuICAgIC8vIGluY3JlbWVudGluZyBieSBtb250aCwgYnV0IGJldHRlciB0byBiZSBzYWZlIVxuICAgIHZhciB0aW1lTXMgPSBtb2QobXMsIE9ORURBWSk7XG4gICAgbXMgPSBNYXRoLnJvdW5kKG1zIC0gdGltZU1zKTtcblxuICAgIGlmKGNhbGVuZGFyKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgZGF0ZUpEID0gTWF0aC5yb3VuZChtcyAvIE9ORURBWSkgKyBFUE9DSEpELFxuICAgICAgICAgICAgICAgIGNhbEluc3RhbmNlID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnZ2V0Q2FsJykoY2FsZW5kYXIpLFxuICAgICAgICAgICAgICAgIGNEYXRlID0gY2FsSW5zdGFuY2UuZnJvbUpEKGRhdGVKRCk7XG5cbiAgICAgICAgICAgIGlmKGRNb250aCAlIDEyKSBjYWxJbnN0YW5jZS5hZGQoY0RhdGUsIGRNb250aCwgJ20nKTtcbiAgICAgICAgICAgIGVsc2UgY2FsSW5zdGFuY2UuYWRkKGNEYXRlLCBkTW9udGggLyAxMiwgJ3knKTtcblxuICAgICAgICAgICAgcmV0dXJuIChjRGF0ZS50b0pEKCkgLSBFUE9DSEpEKSAqIE9ORURBWSArIHRpbWVNcztcbiAgICAgICAgfVxuICAgICAgICBjYXRjaChlKSB7XG4gICAgICAgICAgICBMb2dnZXJzLmVycm9yKCdpbnZhbGlkIG1zICcgKyBtcyArICcgaW4gY2FsZW5kYXIgJyArIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIC8vIHRoZW4ga2VlcCBnb2luZyBpbiBncmVnb3JpYW4gZXZlbiB0aG91Z2ggdGhlIHJlc3VsdCB3aWxsIGJlICdJbnZhbGlkJ1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHkgPSBuZXcgRGF0ZShtcyArIFRIUkVFREFZUyk7XG4gICAgcmV0dXJuIHkuc2V0VVRDTW9udGgoeS5nZXRVVENNb250aCgpICsgZE1vbnRoKSArIHRpbWVNcyAtIFRIUkVFREFZUztcbn07XG5cbi8qXG4gKiBmaW5kRXhhY3REYXRlczogd2hhdCBmcmFjdGlvbiBvZiBkYXRhIGlzIGV4YWN0IGRheXMsIG1vbnRocywgb3IgeWVhcnM/XG4gKlxuICogZGF0YTogYXJyYXkgb2YgbWlsbGlzZWNvbmQgdmFsdWVzXG4gKiBjYWxlbmRhciAoc3RyaW5nKSB0aGUgY2FsZW5kYXIgdG8gdGVzdCBhZ2FpbnN0XG4gKi9cbmV4cG9ydHMuZmluZEV4YWN0RGF0ZXMgPSBmdW5jdGlvbihkYXRhLCBjYWxlbmRhcikge1xuICAgIHZhciBleGFjdFllYXJzID0gMCxcbiAgICAgICAgZXhhY3RNb250aHMgPSAwLFxuICAgICAgICBleGFjdERheXMgPSAwLFxuICAgICAgICBibGFua0NvdW50ID0gMCxcbiAgICAgICAgZCxcbiAgICAgICAgZGk7XG5cbiAgICB2YXIgY2FsSW5zdGFuY2UgPSAoXG4gICAgICAgIGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikgJiZcbiAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnZ2V0Q2FsJykoY2FsZW5kYXIpXG4gICAgKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGRpID0gZGF0YVtpXTtcblxuICAgICAgICAvLyBub3QgZGF0ZSBkYXRhIGF0IGFsbFxuICAgICAgICBpZighaXNOdW1lcmljKGRpKSkge1xuICAgICAgICAgICAgYmxhbmtDb3VudCArKztcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbm90IGFuIGV4YWN0IGRhdGVcbiAgICAgICAgaWYoZGkgJSBPTkVEQVkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKGNhbEluc3RhbmNlKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGQgPSBjYWxJbnN0YW5jZS5mcm9tSkQoZGkgLyBPTkVEQVkgKyBFUE9DSEpEKTtcbiAgICAgICAgICAgICAgICBpZihkLmRheSgpID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGQubW9udGgoKSA9PT0gMSkgZXhhY3RZZWFycysrO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGV4YWN0TW9udGhzKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgZXhhY3REYXlzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaChlKSB7XG4gICAgICAgICAgICAgICAgLy8gaW52YWxpZCBkYXRlIGluIHRoaXMgY2FsZW5kYXIgLSBpZ25vcmUgaXQgaGVyZS5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGQgPSBuZXcgRGF0ZShkaSk7XG4gICAgICAgICAgICBpZihkLmdldFVUQ0RhdGUoKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGlmKGQuZ2V0VVRDTW9udGgoKSA9PT0gMCkgZXhhY3RZZWFycysrO1xuICAgICAgICAgICAgICAgIGVsc2UgZXhhY3RNb250aHMrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgZXhhY3REYXlzKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXhhY3RNb250aHMgKz0gZXhhY3RZZWFycztcbiAgICBleGFjdERheXMgKz0gZXhhY3RNb250aHM7XG5cbiAgICB2YXIgZGF0YUNvdW50ID0gZGF0YS5sZW5ndGggLSBibGFua0NvdW50O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZXhhY3RZZWFyczogZXhhY3RZZWFycyAvIGRhdGFDb3VudCxcbiAgICAgICAgZXhhY3RNb250aHM6IGV4YWN0TW9udGhzIC8gZGF0YUNvdW50LFxuICAgICAgICBleGFjdERheXM6IGV4YWN0RGF5cyAvIGRhdGFDb3VudFxuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGdsb2JhbCBqUXVlcnk6ZmFsc2UgKi9cblxudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcjtcblxudmFyIEV2ZW50cyA9IHtcblxuICAgIGluaXQ6IGZ1bmN0aW9uKHBsb3RPYmopIHtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBJZiB3ZSBoYXZlIGFscmVhZHkgaW5zdGFudGlhdGVkIGFuIGVtaXR0ZXIgZm9yIHRoaXMgcGxvdFxuICAgICAgICAgKiByZXR1cm4gZWFybHkuXG4gICAgICAgICAqL1xuICAgICAgICBpZihwbG90T2JqLl9ldiBpbnN0YW5jZW9mIEV2ZW50RW1pdHRlcikgcmV0dXJuIHBsb3RPYmo7XG5cbiAgICAgICAgdmFyIGV2ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgICAgICB2YXIgaW50ZXJuYWxFdiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBBc3NpZ24gdG8gcGxvdC5fZXYgd2hpbGUgd2Ugc3RpbGwgbGl2ZSBpbiBhIGxhbmRcbiAgICAgICAgICogd2hlcmUgcGxvdCBpcyBhIERPTSBlbGVtZW50IHdpdGggc3R1ZmYgYXR0YWNoZWQgdG8gaXQuXG4gICAgICAgICAqIEluIHRoZSBmdXR1cmUgd2UgY2FuIG1ha2UgcGxvdCB0aGUgZXZlbnQgZW1pdHRlciBpdHNlbGYuXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLl9ldiA9IGV2O1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIENyZWF0ZSBhIHNlY29uZCBldmVudCBoYW5kbGVyIHRoYXQgd2lsbCBtYW5hZ2UgZXZlbnRzICppbnRlcm5hbGx5Ki5cbiAgICAgICAgICogVGhpcyBhbGxvd3MgcGFydHMgb2YgcGxvdGx5IHRvIHJlc3BvbmQgdG8gdGhpbmcgbGlrZSByZWxheW91dCB3aXRob3V0XG4gICAgICAgICAqIGhhdmluZyB0byB1c2UgdGhlIHVzZXItZmFjaW5nIGV2ZW50IGhhbmRsZXIuIFRoZXkgY2Fubm90IHBlYWNlZnVsbHlcbiAgICAgICAgICogY29leGlzdCBvbiB0aGUgc2FtZSBoYW5kbGVyIGJlY2F1c2UgYSB1c2VyIGludm9raW5nXG4gICAgICAgICAqIHBsb3RPYmoucmVtb3ZlQWxsTGlzdGVuZXJzKCkgd291bGQgZGV0YWNoIGludGVybmFsIGV2ZW50cywgYnJlYWtpbmdcbiAgICAgICAgICogcGxvdGx5LlxuICAgICAgICAgKi9cbiAgICAgICAgcGxvdE9iai5faW50ZXJuYWxFdiA9IGludGVybmFsRXY7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogQXNzaWduIGJvdW5kIG1ldGhvZHMgZnJvbSB0aGUgZXYgdG8gdGhlIHBsb3Qgb2JqZWN0LiBUaGVzZSBtZXRob2RzXG4gICAgICAgICAqIHdpbGwgcmVmZXJlbmNlIHRoZSAndGhpcycgb2YgcGxvdC5fZXYgZXZlbiB0aG91Z2ggdGhleSBhcmUgbWV0aG9kc1xuICAgICAgICAgKiBvZiBwbG90LiBUaGlzIHdpbGwga2VlcCB0aGUgZXZlbnQgbWFjaGluZXJ5IGF3YXkgZnJvbSB0aGUgcGxvdCBvYmplY3RcbiAgICAgICAgICogd2hpY2ggY3VycmVudGx5IGlzIG9mdGVuIGEgRE9NIGVsZW1lbnQgYnV0IHByZXNlbnRzIGFuIEFQSSB0aGF0IHdpbGxcbiAgICAgICAgICogY29udGludWUgdG8gZnVuY3Rpb24gd2hlbiBwbG90IGJlY29tZXMgYW4gZW1pdHRlci4gTm90IGFsbCBFdmVudEVtaXR0ZXJcbiAgICAgICAgICogbWV0aG9kcyBoYXZlIGJlZW4gYm91bmQgdG8gYHBsb3RgIGFzIHNvbWUgZG8gbm90IGN1cnJlbnRseSBhZGQgdmFsdWUgdG9cbiAgICAgICAgICogdGhlIFBsb3RseSBldmVudCBBUEkuXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLm9uID0gZXYub24uYmluZChldik7XG4gICAgICAgIHBsb3RPYmoub25jZSA9IGV2Lm9uY2UuYmluZChldik7XG4gICAgICAgIHBsb3RPYmoucmVtb3ZlTGlzdGVuZXIgPSBldi5yZW1vdmVMaXN0ZW5lci5iaW5kKGV2KTtcbiAgICAgICAgcGxvdE9iai5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBldi5yZW1vdmVBbGxMaXN0ZW5lcnMuYmluZChldik7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogQ3JlYXRlIGZ1bmN0aW9ucyBmb3IgbWFuYWdpbmcgaW50ZXJuYWwgZXZlbnRzLiBUaGVzZSBhcmUgKm9ubHkqIHRyaWdnZXJlZFxuICAgICAgICAgKiBieSB0aGUgbWlycm9yaW5nIG9mIGV4dGVybmFsIGV2ZW50cyB2aWEgdGhlIGVtaXQgZnVuY3Rpb24uXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLl9pbnRlcm5hbE9uID0gaW50ZXJuYWxFdi5vbi5iaW5kKGludGVybmFsRXYpO1xuICAgICAgICBwbG90T2JqLl9pbnRlcm5hbE9uY2UgPSBpbnRlcm5hbEV2Lm9uY2UuYmluZChpbnRlcm5hbEV2KTtcbiAgICAgICAgcGxvdE9iai5fcmVtb3ZlSW50ZXJuYWxMaXN0ZW5lciA9IGludGVybmFsRXYucmVtb3ZlTGlzdGVuZXIuYmluZChpbnRlcm5hbEV2KTtcbiAgICAgICAgcGxvdE9iai5fcmVtb3ZlQWxsSW50ZXJuYWxMaXN0ZW5lcnMgPSBpbnRlcm5hbEV2LnJlbW92ZUFsbExpc3RlbmVycy5iaW5kKGludGVybmFsRXYpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIFdlIG11c3Qgd3JhcCBlbWl0IHRvIGNvbnRpbnVlIHRvIHN1cHBvcnQgSlF1ZXJ5IGV2ZW50cy4gVGhlIGlkZWFcbiAgICAgICAgICogaXMgdG8gY2hlY2sgdG8gc2VlIGlmIHRoZSB1c2VyIGlzIHVzaW5nIEpRdWVyeSBldmVudHMsIGlmIHRoZXkgYXJlXG4gICAgICAgICAqIHdlIGVtaXQgSlF1ZXJ5IGV2ZW50cyB0byB0cmlnZ2VyIHVzZXIgaGFuZGxlcnMgYXMgd2VsbCBhcyB0aGUgRXZlbnRFbWl0dGVyXG4gICAgICAgICAqIGV2ZW50cy5cbiAgICAgICAgICovXG4gICAgICAgIHBsb3RPYmouZW1pdCA9IGZ1bmN0aW9uKGV2ZW50LCBkYXRhKSB7XG4gICAgICAgICAgICBpZih0eXBlb2YgalF1ZXJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGpRdWVyeShwbG90T2JqKS50cmlnZ2VyKGV2ZW50LCBkYXRhKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZXYuZW1pdChldmVudCwgZGF0YSk7XG4gICAgICAgICAgICBpbnRlcm5hbEV2LmVtaXQoZXZlbnQsIGRhdGEpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBwbG90T2JqO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYmVoYXZlcyBsaWtlIGpRdWVyeSdzIHRyaWdnZXJIYW5kbGVyLiBJdCBjYWxsc1xuICAgICAqIGFsbCBoYW5kbGVycyBmb3IgYSBwYXJ0aWN1bGFyIGV2ZW50IGFuZCByZXR1cm5zIHRoZSByZXR1cm4gdmFsdWVcbiAgICAgKiBvZiB0aGUgTEFTVCBoYW5kbGVyLiBUaGlzIGZ1bmN0aW9uIGFsc28gdHJpZ2dlcnMgalF1ZXJ5J3NcbiAgICAgKiB0cmlnZ2VySGFuZGxlciBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gICAgICovXG4gICAgdHJpZ2dlckhhbmRsZXI6IGZ1bmN0aW9uKHBsb3RPYmosIGV2ZW50LCBkYXRhKSB7XG4gICAgICAgIHZhciBqUXVlcnlIYW5kbGVyVmFsdWU7XG4gICAgICAgIHZhciBub2RlRXZlbnRIYW5kbGVyVmFsdWU7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogSWYgalF1ZXJ5IGV4aXN0cyBydW4gYWxsIGl0cyBoYW5kbGVycyBmb3IgdGhpcyBldmVudCBhbmRcbiAgICAgICAgICogY29sbGVjdCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBMQVNUIGhhbmRsZXIgZnVuY3Rpb25cbiAgICAgICAgICovXG4gICAgICAgIGlmKHR5cGVvZiBqUXVlcnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBqUXVlcnlIYW5kbGVyVmFsdWUgPSBqUXVlcnkocGxvdE9iaikudHJpZ2dlckhhbmRsZXIoZXZlbnQsIGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLypcbiAgICAgICAgICogTm93IHJ1biBhbGwgdGhlIG5vZGUgc3R5bGUgZXZlbnQgaGFuZGxlcnNcbiAgICAgICAgICovXG4gICAgICAgIHZhciBldiA9IHBsb3RPYmouX2V2O1xuICAgICAgICBpZighZXYpIHJldHVybiBqUXVlcnlIYW5kbGVyVmFsdWU7XG5cbiAgICAgICAgdmFyIGhhbmRsZXJzID0gZXYuX2V2ZW50c1tldmVudF07XG4gICAgICAgIGlmKCFoYW5kbGVycykgcmV0dXJuIGpRdWVyeUhhbmRsZXJWYWx1ZTtcblxuICAgICAgICAvLyBtYWtpbmcgc3VyZSAndGhpcycgaXMgdGhlIEV2ZW50RW1pdHRlciBpbnN0YW5jZVxuICAgICAgICBmdW5jdGlvbiBhcHBseShoYW5kbGVyKSB7XG4gICAgICAgICAgICAvLyBUaGUgJ29uY2UnIGNhc2UsIHdlIGNhbid0IGp1c3QgY2FsbCBoYW5kbGVyKCkgYXMgd2UgbmVlZFxuICAgICAgICAgICAgLy8gdGhlIHJldHVybiB2YWx1ZSBoZXJlLiBTbyxcbiAgICAgICAgICAgIC8vIC0gcmVtb3ZlIGhhbmRsZXJcbiAgICAgICAgICAgIC8vIC0gY2FsbCBsaXN0ZW5lciBhbmQgZ3JhYiByZXR1cm4gdmFsdWUhXG4gICAgICAgICAgICAvLyAtIHN0YXNoICdmaXJlZCcga2V5IHRvIG5vdCBjYWxsIGhhbmRsZXIgdHdpY2VcbiAgICAgICAgICAgIGlmKGhhbmRsZXIubGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBldi5yZW1vdmVMaXN0ZW5lcihldmVudCwgaGFuZGxlci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgaWYoIWhhbmRsZXIuZmlyZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlci5maXJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLmxpc3RlbmVyLmFwcGx5KGV2LCBbZGF0YV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIuYXBwbHkoZXYsIFtkYXRhXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBoYW5kbGVycyBjYW4gYmUgZnVuY3Rpb24gb3IgYW4gYXJyYXkgb2YgZnVuY3Rpb25zXG4gICAgICAgIGhhbmRsZXJzID0gQXJyYXkuaXNBcnJheShoYW5kbGVycykgPyBoYW5kbGVycyA6IFtoYW5kbGVyc107XG5cbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgYXBwbHkoaGFuZGxlcnNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5vdyBjYWxsIHRoZSBmaW5hbCBoYW5kbGVyIGFuZCBjb2xsZWN0IGl0cyB2YWx1ZVxuICAgICAgICBub2RlRXZlbnRIYW5kbGVyVmFsdWUgPSBhcHBseShoYW5kbGVyc1tpXSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogUmV0dXJuIGVpdGhlciB0aGUgalF1ZXJ5IGhhbmRsZXIgdmFsdWUgaWYgaXQgZXhpc3RzIG9yIHRoZVxuICAgICAgICAgKiBub2RlRXZlbnRIYW5kbGVyIHZhbHVlLiBqUXVlcnkgZXZlbnQgdmFsdWUgc3VwZXJzZWRlcyBub2RlanNcbiAgICAgICAgICogZXZlbnRzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSByZWFzb25zLlxuICAgICAgICAgKi9cbiAgICAgICAgcmV0dXJuIGpRdWVyeUhhbmRsZXJWYWx1ZSAhPT0gdW5kZWZpbmVkID9cbiAgICAgICAgICAgIGpRdWVyeUhhbmRsZXJWYWx1ZSA6XG4gICAgICAgICAgICBub2RlRXZlbnRIYW5kbGVyVmFsdWU7XG4gICAgfSxcblxuICAgIHB1cmdlOiBmdW5jdGlvbihwbG90T2JqKSB7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9ldjtcbiAgICAgICAgZGVsZXRlIHBsb3RPYmoub247XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLm9uY2U7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLnJlbW92ZUxpc3RlbmVyO1xuICAgICAgICBkZWxldGUgcGxvdE9iai5yZW1vdmVBbGxMaXN0ZW5lcnM7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLmVtaXQ7XG5cbiAgICAgICAgZGVsZXRlIHBsb3RPYmouX2V2O1xuICAgICAgICBkZWxldGUgcGxvdE9iai5faW50ZXJuYWxFdjtcbiAgICAgICAgZGVsZXRlIHBsb3RPYmouX2ludGVybmFsT247XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9pbnRlcm5hbE9uY2U7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9yZW1vdmVJbnRlcm5hbExpc3RlbmVyO1xuICAgICAgICBkZWxldGUgcGxvdE9iai5fcmVtb3ZlQWxsSW50ZXJuYWxMaXN0ZW5lcnM7XG5cbiAgICAgICAgcmV0dXJuIHBsb3RPYmo7XG4gICAgfVxuXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50cztcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNQbGFpbk9iamVjdCA9IHJlcXVpcmUoJy4vaXNfcGxhaW5fb2JqZWN0LmpzJyk7XG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG5cbmZ1bmN0aW9uIHByaW1pdGl2ZXNMb29wU3BsaWNlKHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgdmFyIGksIHZhbHVlO1xuICAgIGZvcihpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YWx1ZSA9IHNvdXJjZVtpXTtcbiAgICAgICAgaWYodmFsdWUgIT09IG51bGwgJiYgdHlwZW9mKHZhbHVlKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZih2YWx1ZSAhPT0gdm9pZCgwKSkge1xuICAgICAgICAgICAgdGFyZ2V0W2ldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydHMuZXh0ZW5kRmxhdCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfZXh0ZW5kKGFyZ3VtZW50cywgZmFsc2UsIGZhbHNlLCBmYWxzZSk7XG59O1xuXG5leHBvcnRzLmV4dGVuZERlZXAgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX2V4dGVuZChhcmd1bWVudHMsIHRydWUsIGZhbHNlLCBmYWxzZSk7XG59O1xuXG5leHBvcnRzLmV4dGVuZERlZXBBbGwgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX2V4dGVuZChhcmd1bWVudHMsIHRydWUsIHRydWUsIGZhbHNlKTtcbn07XG5cbmV4cG9ydHMuZXh0ZW5kRGVlcE5vQXJyYXlzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9leHRlbmQoYXJndW1lbnRzLCB0cnVlLCBmYWxzZSwgdHJ1ZSk7XG59O1xuXG4vKlxuICogSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2p1c3Rtb29uL25vZGUtZXh0ZW5kL2Jsb2IvbWFzdGVyL2luZGV4LmpzXG4gKiBBbGwgY3JlZGl0IHRvIHRoZSBqUXVlcnkgYXV0aG9ycyBmb3IgcGVyZmVjdGluZyB0aGlzIGFtYXppbmcgdXRpbGl0eS5cbiAqXG4gKiBBUEkgZGlmZmVyZW5jZSB3aXRoIGpRdWVyeSB2ZXJzaW9uOlxuICogLSBObyBvcHRpb25hbCBib29sZWFuICh0cnVlIC0+IGRlZXAgZXh0ZW5kKSBmaXJzdCBhcmd1bWVudCxcbiAqICAgdXNlIGBleHRlbmRGbGF0YCBmb3IgZmlyc3QtbGV2ZWwgb25seSBleHRlbmQgYW5kXG4gKiAgIHVzZSBgZXh0ZW5kRGVlcGAgZm9yIGEgZGVlcCBleHRlbmQuXG4gKlxuICogT3RoZXIgZGlmZmVyZW5jZXMgd2l0aCBqUXVlcnkgdmVyc2lvbjpcbiAqIC0gVXNlcyBhIG1vZGVybiAoYW5kIGZhc3RlcikgaXNQbGFpbk9iamVjdCByb3V0aW5lLlxuICogLSBFeHBlY3RlZCB0byB3b3JrIHdpdGggb2JqZWN0IHt9IGFuZCBhcnJheSBbXSBhcmd1bWVudHMgb25seS5cbiAqIC0gRG9lcyBub3QgY2hlY2sgZm9yIGNpcmN1bGFyIHN0cnVjdHVyZS5cbiAqICAgRllJOiBqUXVlcnkgb25seSBkb2VzIGEgY2hlY2sgYWNyb3NzIG9uZSBsZXZlbC5cbiAqICAgV2FybmluZzogdGhpcyBtaWdodCByZXN1bHQgaW4gaW5maW5pdGUgbG9vcHMuXG4gKlxuICovXG5mdW5jdGlvbiBfZXh0ZW5kKGlucHV0cywgaXNEZWVwLCBrZWVwQWxsS2V5cywgbm9BcnJheUNvcGllcykge1xuICAgIHZhciB0YXJnZXQgPSBpbnB1dHNbMF0sXG4gICAgICAgIGxlbmd0aCA9IGlucHV0cy5sZW5ndGg7XG5cbiAgICB2YXIgaW5wdXQsIGtleSwgc3JjLCBjb3B5LCBjb3B5SXNBcnJheSwgY2xvbmUsIGFsbFByaW1pdGl2ZXM7XG5cbiAgICAvLyBUT0RPIGRvZXMgdGhpcyBkbyB0aGUgcmlnaHQgdGhpbmcgZm9yIHR5cGVkIGFycmF5cz9cblxuICAgIGlmKGxlbmd0aCA9PT0gMiAmJiBpc0FycmF5KHRhcmdldCkgJiYgaXNBcnJheShpbnB1dHNbMV0pICYmIHRhcmdldC5sZW5ndGggPT09IDApIHtcblxuICAgICAgICBhbGxQcmltaXRpdmVzID0gcHJpbWl0aXZlc0xvb3BTcGxpY2UoaW5wdXRzWzFdLCB0YXJnZXQpO1xuXG4gICAgICAgIGlmKGFsbFByaW1pdGl2ZXMpIHtcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXQuc3BsaWNlKDAsIHRhcmdldC5sZW5ndGgpOyAvLyByZXNldCB0YXJnZXQgYW5kIGNvbnRpbnVlIHRvIG5leHQgYmxvY2tcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpbnB1dCA9IGlucHV0c1tpXTtcblxuICAgICAgICBmb3Ioa2V5IGluIGlucHV0KSB7XG4gICAgICAgICAgICBzcmMgPSB0YXJnZXRba2V5XTtcbiAgICAgICAgICAgIGNvcHkgPSBpbnB1dFtrZXldO1xuXG4gICAgICAgICAgICAvLyBTdG9wIGVhcmx5IGFuZCBqdXN0IHRyYW5zZmVyIHRoZSBhcnJheSBpZiBhcnJheSBjb3BpZXMgYXJlIGRpc2FsbG93ZWQ6XG4gICAgICAgICAgICBpZihub0FycmF5Q29waWVzICYmIGlzQXJyYXkoY29weSkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IGNvcHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaWYgd2UncmUgbWVyZ2luZyBwbGFpbiBvYmplY3RzIG9yIGFycmF5c1xuICAgICAgICAgICAgZWxzZSBpZihpc0RlZXAgJiYgY29weSAmJiAoaXNQbGFpbk9iamVjdChjb3B5KSB8fCAoY29weUlzQXJyYXkgPSBpc0FycmF5KGNvcHkpKSkpIHtcbiAgICAgICAgICAgICAgICBpZihjb3B5SXNBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICBjb3B5SXNBcnJheSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBjbG9uZSA9IHNyYyAmJiBpc0FycmF5KHNyYykgPyBzcmMgOiBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjbG9uZSA9IHNyYyAmJiBpc1BsYWluT2JqZWN0KHNyYykgPyBzcmMgOiB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBuZXZlciBtb3ZlIG9yaWdpbmFsIG9iamVjdHMsIGNsb25lIHRoZW1cbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IF9leHRlbmQoW2Nsb25lLCBjb3B5XSwgaXNEZWVwLCBrZWVwQWxsS2V5cywgbm9BcnJheUNvcGllcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGRvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXMsIGV4Y2VwdCBmb3IgZXh0ZW5kRGVlcEFsbFxuICAgICAgICAgICAgZWxzZSBpZih0eXBlb2YgY29weSAhPT0gJ3VuZGVmaW5lZCcgfHwga2VlcEFsbEtleXMpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IGNvcHk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuLyoqXG4gKiBSZXR1cm4gbmV3cyBhcnJheSBjb250YWluaW5nIG9ubHkgdGhlIHVuaXF1ZSBpdGVtc1xuICogZm91bmQgaW4gaW5wdXQgYXJyYXkuXG4gKlxuICogSU1QT1JUQU5UOiBOb3RlIHRoYXQgaXRlbXMgYXJlIGNvbnNpZGVyZWQgdW5pcXVlXG4gKiBpZiBgU3RyaW5nKHt9KWAgaXMgdW5pcXVlLiBGb3IgZXhhbXBsZTtcbiAqXG4gKiAgTGliLmZpbHRlclVuaXF1ZShbIHsgYTogMSB9LCB7IGI6IDIgfSBdKVxuICpcbiAqICByZXR1cm5zIFt7IGE6IDEgfV1cbiAqXG4gKiBhbmRcbiAqXG4gKiAgTGliLmZpbHRlclVuaXF1ZShbICcxJywgMSBdKVxuICpcbiAqICByZXR1cm5zIFsnMSddXG4gKlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGFycmF5IGJhc2UgYXJyYXlcbiAqIEByZXR1cm4ge2FycmF5fSBuZXcgZmlsdGVyZWQgYXJyYXlcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWx0ZXJVbmlxdWUoYXJyYXkpIHtcbiAgICB2YXIgc2VlbiA9IHt9LFxuICAgICAgICBvdXQgPSBbXSxcbiAgICAgICAgaiA9IDA7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGl0ZW0gPSBhcnJheVtpXTtcblxuICAgICAgICBpZihzZWVuW2l0ZW1dICE9PSAxKSB7XG4gICAgICAgICAgICBzZWVuW2l0ZW1dID0gMTtcbiAgICAgICAgICAgIG91dFtqKytdID0gaXRlbTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKiogRmlsdGVyIG91dCBvYmplY3QgaXRlbXMgd2l0aCB2aXNpYmxlICE9PSB0cnVlXG4gKiAgaW5zaWRlciBhcnJheSBjb250YWluZXIuXG4gKlxuICogIEBwYXJhbSB7YXJyYXkgb2Ygb2JqZWN0c30gY29udGFpbmVyXG4gKiAgQHJldHVybiB7YXJyYXkgb2Ygb2JqZWN0c30gb2YgbGVuZ3RoIDw9IGNvbnRhaW5lclxuICpcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWx0ZXJWaXNpYmxlKGNvbnRhaW5lcikge1xuICAgIHZhciBmaWx0ZXJGbiA9IGlzQ2FsY0RhdGEoY29udGFpbmVyKSA/IGNhbGNEYXRhRmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICB2YXIgb3V0ID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29udGFpbmVyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gY29udGFpbmVyW2ldO1xuICAgICAgICBpZihmaWx0ZXJGbihpdGVtKSkgb3V0LnB1c2goaXRlbSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbmZ1bmN0aW9uIGJhc2VGaWx0ZXIoaXRlbSkge1xuICAgIHJldHVybiBpdGVtLnZpc2libGUgPT09IHRydWU7XG59XG5cbmZ1bmN0aW9uIGNhbGNEYXRhRmlsdGVyKGl0ZW0pIHtcbiAgICByZXR1cm4gaXRlbVswXS50cmFjZS52aXNpYmxlID09PSB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc0NhbGNEYXRhKGNvbnQpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbnQpICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoY29udFswXSkgJiZcbiAgICAgICAgY29udFswXVswXSAmJlxuICAgICAgICBjb250WzBdWzBdLnRyYWNlXG4gICAgKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY291bnRyeVJlZ2V4ID0gcmVxdWlyZSgnY291bnRyeS1yZWdleCcpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xuXG5cbi8vIG1ha2UgbGlzdCBvZiBhbGwgY291bnRyeSBpc28zIGlkcyBmcm9tIGF0IHJ1bnRpbWVcbnZhciBjb3VudHJ5SWRzID0gT2JqZWN0LmtleXMoY291bnRyeVJlZ2V4KTtcblxudmFyIGxvY2F0aW9ubW9kZVRvSWRGaW5kZXIgPSB7XG4gICAgJ0lTTy0zJzogTGliLmlkZW50aXR5LFxuICAgICdVU0Etc3RhdGVzJzogTGliLmlkZW50aXR5LFxuICAgICdjb3VudHJ5IG5hbWVzJzogY291bnRyeU5hbWVUb0lTTzNcbn07XG5cbmV4cG9ydHMubG9jYXRpb25Ub0ZlYXR1cmUgPSBmdW5jdGlvbihsb2NhdGlvbm1vZGUsIGxvY2F0aW9uLCBmZWF0dXJlcykge1xuICAgIGlmKCFsb2NhdGlvbiB8fCB0eXBlb2YgbG9jYXRpb24gIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgbG9jYXRpb25JZCA9IGdldExvY2F0aW9uSWQobG9jYXRpb25tb2RlLCBsb2NhdGlvbik7XG5cbiAgICBpZihsb2NhdGlvbklkKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1tpXTtcblxuICAgICAgICAgICAgaWYoZmVhdHVyZS5pZCA9PT0gbG9jYXRpb25JZCkgcmV0dXJuIGZlYXR1cmU7XG4gICAgICAgIH1cblxuICAgICAgICBMaWIubG9nKFtcbiAgICAgICAgICAgICdMb2NhdGlvbiB3aXRoIGlkJywgbG9jYXRpb25JZCxcbiAgICAgICAgICAgICdkb2VzIG5vdCBoYXZlIGEgbWF0Y2hpbmcgdG9wb2pzb24gZmVhdHVyZSBhdCB0aGlzIHJlc29sdXRpb24uJ1xuICAgICAgICBdLmpvaW4oJyAnKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuZnVuY3Rpb24gZ2V0TG9jYXRpb25JZChsb2NhdGlvbm1vZGUsIGxvY2F0aW9uKSB7XG4gICAgdmFyIGlkRmluZGVyID0gbG9jYXRpb25tb2RlVG9JZEZpbmRlcltsb2NhdGlvbm1vZGVdO1xuICAgIHJldHVybiBpZEZpbmRlcihsb2NhdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvdW50cnlOYW1lVG9JU08zKGNvdW50cnlOYW1lKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvdW50cnlJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlzbzMgPSBjb3VudHJ5SWRzW2ldLFxuICAgICAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKGNvdW50cnlSZWdleFtpc28zXSk7XG5cbiAgICAgICAgaWYocmVnZXgudGVzdChjb3VudHJ5TmFtZS50cmltKCkudG9Mb3dlckNhc2UoKSkpIHJldHVybiBpc28zO1xuICAgIH1cblxuICAgIExpYi5sb2coJ1VucmVjb2duaXplZCBjb3VudHJ5IG5hbWU6ICcgKyBjb3VudHJ5TmFtZSArICcuJyk7XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbi8qKlxuICogQ29udmVydCBjYWxjVHJhY2UgdG8gR2VvSlNPTiAnTXVsdGlMaW5lU3RyaW5nJyBjb29yZGluYXRlIGFycmF5c1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjYWxjVHJhY2VcbiAqICBnZC5jYWxjZGF0YSBpdGVtLlxuICogIE5vdGUgdGhhdCBjYWxjVHJhY2VbaV0ubG9ubGF0IGlzIGFzc3VtZWQgdG8gYmUgZGVmaW5lZFxuICpcbiAqIEByZXR1cm4ge2FycmF5fVxuICogIHJldHVybiBsaW5lIGNvb3JkcyBhcnJheSAob3IgYXJyYXkgb2YgYXJyYXlzKVxuICpcbiAqL1xuZXhwb3J0cy5jYWxjVHJhY2VUb0xpbmVDb29yZHMgPSBmdW5jdGlvbihjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGNvbm5lY3RnYXBzID0gdHJhY2UuY29ubmVjdGdhcHM7XG5cbiAgICB2YXIgY29vcmRzID0gW107XG4gICAgdmFyIGxpbmVTdHJpbmcgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2UubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNQdCA9IGNhbGNUcmFjZVtpXTtcbiAgICAgICAgdmFyIGxvbmxhdCA9IGNhbGNQdC5sb25sYXQ7XG5cbiAgICAgICAgaWYobG9ubGF0WzBdICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGxpbmVTdHJpbmcucHVzaChsb25sYXQpO1xuICAgICAgICB9IGVsc2UgaWYoIWNvbm5lY3RnYXBzICYmIGxpbmVTdHJpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29vcmRzLnB1c2gobGluZVN0cmluZyk7XG4gICAgICAgICAgICBsaW5lU3RyaW5nID0gW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihsaW5lU3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29vcmRzLnB1c2gobGluZVN0cmluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvb3Jkcztcbn07XG5cblxuLyoqXG4gKiBNYWtlIGxpbmUgKCdMaW5lU3RyaW5nJyBvciAnTXVsdGlMaW5lU3RyaW5nJykgR2VvSlNPTlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGNvb3Jkc1xuICogIHJlc3VsdHMgZm9ybSBjYWxjVHJhY2VUb0xpbmVDb29yZHNcbiAqIEByZXR1cm4ge29iamVjdH0gb3V0XG4gKiAgR2VvSlNPTiBvYmplY3RcbiAqXG4gKi9cbmV4cG9ydHMubWFrZUxpbmUgPSBmdW5jdGlvbihjb29yZHMpIHtcbiAgICBpZihjb29yZHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiAnTGluZVN0cmluZycsXG4gICAgICAgICAgICBjb29yZGluYXRlczogY29vcmRzWzBdXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdNdWx0aUxpbmVTdHJpbmcnLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3Jkc1xuICAgICAgICB9O1xuICAgIH1cbn07XG5cbi8qKlxuICogTWFrZSBwb2x5Z29uICgnUG9seWdvbicgb3IgJ011bHRpUG9seWdvbicpIEdlb0pTT05cbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBjb29yZHNcbiAqICByZXN1bHRzIGZvcm0gY2FsY1RyYWNlVG9MaW5lQ29vcmRzXG4gKiBAcmV0dXJuIHtvYmplY3R9IG91dFxuICogIEdlb0pTT04gb2JqZWN0XG4gKi9cbmV4cG9ydHMubWFrZVBvbHlnb24gPSBmdW5jdGlvbihjb29yZHMpIHtcbiAgICBpZihjb29yZHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiAnUG9seWdvbicsXG4gICAgICAgICAgICBjb29yZGluYXRlczogY29vcmRzXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIF9jb29yZHMgPSBuZXcgQXJyYXkoY29vcmRzLmxlbmd0aCk7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgX2Nvb3Jkc1tpXSA9IFtjb29yZHNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdNdWx0aVBvbHlnb24nLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IF9jb29yZHNcbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG4vKipcbiAqIE1ha2UgYmxhbmsgR2VvSlNPTlxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICBCbGFuayBHZW9KU09OIG9iamVjdFxuICpcbiAqL1xuZXhwb3J0cy5tYWtlQmxhbmsgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICBjb29yZGluYXRlczogW11cbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG1vZCA9IHJlcXVpcmUoJy4vbW9kJykubW9kO1xuXG4vKlxuICogbG9vayBmb3IgaW50ZXJzZWN0aW9uIG9mIHR3byBsaW5lIHNlZ21lbnRzXG4gKiAgICgxLT4yIGFuZCAzLT40KSAtIHJldHVybnMgYXJyYXkgW3gseV0gaWYgdGhleSBkbywgbnVsbCBpZiBub3RcbiAqL1xuZXhwb3J0cy5zZWdtZW50c0ludGVyc2VjdCA9IHNlZ21lbnRzSW50ZXJzZWN0O1xuZnVuY3Rpb24gc2VnbWVudHNJbnRlcnNlY3QoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSB7XG4gICAgdmFyIGEgPSB4MiAtIHgxLFxuICAgICAgICBiID0geDMgLSB4MSxcbiAgICAgICAgYyA9IHg0IC0geDMsXG4gICAgICAgIGQgPSB5MiAtIHkxLFxuICAgICAgICBlID0geTMgLSB5MSxcbiAgICAgICAgZiA9IHk0IC0geTMsXG4gICAgICAgIGRldCA9IGEgKiBmIC0gYyAqIGQ7XG4gICAgLy8gcGFyYWxsZWwgbGluZXM/IGludGVyc2VjdGlvbiBpcyB1bmRlZmluZWRcbiAgICAvLyBpZ25vcmUgdGhlIGNhc2Ugd2hlcmUgdGhleSBhcmUgY29saW5lYXJcbiAgICBpZihkZXQgPT09IDApIHJldHVybiBudWxsO1xuICAgIHZhciB0ID0gKGIgKiBmIC0gYyAqIGUpIC8gZGV0LFxuICAgICAgICB1ID0gKGIgKiBkIC0gYSAqIGUpIC8gZGV0O1xuICAgIC8vIHNlZ21lbnRzIGRvIG5vdCBpbnRlcnNlY3Q/XG4gICAgaWYodSA8IDAgfHwgdSA+IDEgfHwgdCA8IDAgfHwgdCA+IDEpIHJldHVybiBudWxsO1xuXG4gICAgcmV0dXJuIHt4OiB4MSArIGEgKiB0LCB5OiB5MSArIGQgKiB0fTtcbn1cblxuLypcbiAqIGZpbmQgdGhlIG1pbmltdW0gZGlzdGFuY2UgYmV0d2VlbiB0d28gbGluZSBzZWdtZW50cyAoMS0+MiBhbmQgMy0+NClcbiAqL1xuZXhwb3J0cy5zZWdtZW50RGlzdGFuY2UgPSBmdW5jdGlvbiBzZWdtZW50RGlzdGFuY2UoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSB7XG4gICAgaWYoc2VnbWVudHNJbnRlcnNlY3QoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSkgcmV0dXJuIDA7XG5cbiAgICAvLyB0aGUgdHdvIHNlZ21lbnRzIGFuZCB0aGVpciBsZW5ndGhzIHNxdWFyZWRcbiAgICB2YXIgeDEyID0geDIgLSB4MTtcbiAgICB2YXIgeTEyID0geTIgLSB5MTtcbiAgICB2YXIgeDM0ID0geDQgLSB4MztcbiAgICB2YXIgeTM0ID0geTQgLSB5MztcbiAgICB2YXIgbDJfMTIgPSB4MTIgKiB4MTIgKyB5MTIgKiB5MTI7XG4gICAgdmFyIGwyXzM0ID0geDM0ICogeDM0ICsgeTM0ICogeTM0O1xuXG4gICAgLy8gY2FsY3VsYXRlIGRpc3RhbmNlIHNxdWFyZWQsIHRoZW4gdGFrZSB0aGUgc3FydCBhdCB0aGUgdmVyeSBlbmRcbiAgICB2YXIgZGlzdDIgPSBNYXRoLm1pbihcbiAgICAgICAgcGVycERpc3RhbmNlMih4MTIsIHkxMiwgbDJfMTIsIHgzIC0geDEsIHkzIC0geTEpLFxuICAgICAgICBwZXJwRGlzdGFuY2UyKHgxMiwgeTEyLCBsMl8xMiwgeDQgLSB4MSwgeTQgLSB5MSksXG4gICAgICAgIHBlcnBEaXN0YW5jZTIoeDM0LCB5MzQsIGwyXzM0LCB4MSAtIHgzLCB5MSAtIHkzKSxcbiAgICAgICAgcGVycERpc3RhbmNlMih4MzQsIHkzNCwgbDJfMzQsIHgyIC0geDMsIHkyIC0geTMpXG4gICAgKTtcblxuICAgIHJldHVybiBNYXRoLnNxcnQoZGlzdDIpO1xufTtcblxuLypcbiAqIGRpc3RhbmNlIHNxdWFyZWQgZnJvbSBzZWdtZW50IGFiIHRvIHBvaW50IGNcbiAqIFt4YWIsIHlhYl0gaXMgdGhlIHZlY3RvciBiLWFcbiAqIFt4YWMsIHlhY10gaXMgdGhlIHZlY3RvciBjLWFcbiAqIGwyX2FiIGlzIHRoZSBsZW5ndGggc3F1YXJlZCBvZiAoYi1hKSwganVzdCB0byBzaW1wbGlmeSBjYWxjdWxhdGlvblxuICovXG5mdW5jdGlvbiBwZXJwRGlzdGFuY2UyKHhhYiwgeWFiLCBsMl9hYiwgeGFjLCB5YWMpIHtcbiAgICB2YXIgZmNfYWIgPSAoeGFjICogeGFiICsgeWFjICogeWFiKTtcbiAgICBpZihmY19hYiA8IDApIHtcbiAgICAgICAgLy8gcG9pbnQgYyBpcyBjbG9zZXIgdG8gcG9pbnQgYVxuICAgICAgICByZXR1cm4geGFjICogeGFjICsgeWFjICogeWFjO1xuICAgIH1cbiAgICBlbHNlIGlmKGZjX2FiID4gbDJfYWIpIHtcbiAgICAgICAgLy8gcG9pbnQgYyBpcyBjbG9zZXIgdG8gcG9pbnQgYlxuICAgICAgICB2YXIgeGJjID0geGFjIC0geGFiO1xuICAgICAgICB2YXIgeWJjID0geWFjIC0geWFiO1xuICAgICAgICByZXR1cm4geGJjICogeGJjICsgeWJjICogeWJjO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gcGVycGVuZGljdWxhciBkaXN0YW5jZSBpcyB0aGUgc2hvcnRlc3RcbiAgICAgICAgdmFyIGNyb3NzUHJvZHVjdCA9IHhhYyAqIHlhYiAtIHlhYyAqIHhhYjtcbiAgICAgICAgcmV0dXJuIGNyb3NzUHJvZHVjdCAqIGNyb3NzUHJvZHVjdCAvIGwyX2FiO1xuICAgIH1cbn1cblxuLy8gYSB2ZXJ5IHNob3J0LXRlcm0gY2FjaGUgZm9yIGdldFRleHRMb2NhdGlvbiwganVzdCBiZWNhdXNlXG4vLyB3ZSdyZSBvZnRlbiBsb29waW5nIG92ZXIgdGhlIHNhbWUgbG9jYXRpb25zIG11bHRpcGxlIHRpbWVzXG4vLyBpbnZhbGlkYXRlZCBhcyBzb29uIGFzIHdlIGxvb2sgYXQgYSBkaWZmZXJlbnQgcGF0aFxudmFyIGxvY2F0aW9uQ2FjaGUsIHdvcmtpbmdQYXRoLCB3b3JraW5nVGV4dFdpZHRoO1xuXG4vLyB0dXJuIGEgcGF0aCBhbmQgcG9zaXRpb24gYWxvbmcgaXQgaW50byB4LCB5LCBhbmQgYW5nbGUgZm9yIHRoZSBnaXZlbiB0ZXh0XG5leHBvcnRzLmdldFRleHRMb2NhdGlvbiA9IGZ1bmN0aW9uIGdldFRleHRMb2NhdGlvbihwYXRoLCB0b3RhbFBhdGhMZW4sIHBvc2l0aW9uT25QYXRoLCB0ZXh0V2lkdGgpIHtcbiAgICBpZihwYXRoICE9PSB3b3JraW5nUGF0aCB8fCB0ZXh0V2lkdGggIT09IHdvcmtpbmdUZXh0V2lkdGgpIHtcbiAgICAgICAgbG9jYXRpb25DYWNoZSA9IHt9O1xuICAgICAgICB3b3JraW5nUGF0aCA9IHBhdGg7XG4gICAgICAgIHdvcmtpbmdUZXh0V2lkdGggPSB0ZXh0V2lkdGg7XG4gICAgfVxuICAgIGlmKGxvY2F0aW9uQ2FjaGVbcG9zaXRpb25PblBhdGhdKSB7XG4gICAgICAgIHJldHVybiBsb2NhdGlvbkNhY2hlW3Bvc2l0aW9uT25QYXRoXTtcbiAgICB9XG5cbiAgICAvLyBmb3IgdGhlIGFuZ2xlLCB1c2UgcG9pbnRzIG9uIHRoZSBwYXRoIHNlcGFyYXRlZCBieSB0aGUgdGV4dCB3aWR0aFxuICAgIC8vIGV2ZW4gdGhvdWdoIGR1ZSB0byBjdXJ2YXR1cmUsIHRoZSB0ZXh0IHdpbGwgY292ZXIgYSBiaXQgbW9yZSB0aGFuIHRoYXRcbiAgICB2YXIgcDAgPSBwYXRoLmdldFBvaW50QXRMZW5ndGgobW9kKHBvc2l0aW9uT25QYXRoIC0gdGV4dFdpZHRoIC8gMiwgdG90YWxQYXRoTGVuKSk7XG4gICAgdmFyIHAxID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKG1vZChwb3NpdGlvbk9uUGF0aCArIHRleHRXaWR0aCAvIDIsIHRvdGFsUGF0aExlbikpO1xuICAgIC8vIG5vdGU6IGF0YW4gaGFuZGxlcyAxLzAgbmljZWx5XG4gICAgdmFyIHRoZXRhID0gTWF0aC5hdGFuKChwMS55IC0gcDAueSkgLyAocDEueCAtIHAwLngpKTtcbiAgICAvLyBjZW50ZXIgdGhlIHRleHQgYXQgMi8zIG9mIHRoZSBjZW50ZXIgcG9zaXRpb24gcGx1cyAxLzMgdGhlIHAwL3AxIG1pZHBvaW50XG4gICAgLy8gdGhhdCdzIHRoZSBhdmVyYWdlIHBvc2l0aW9uIG9mIHRoaXMgc2VnbWVudCwgYXNzdW1pbmcgaXQncyByb3VnaGx5IHF1YWRyYXRpY1xuICAgIHZhciBwQ2VudGVyID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKG1vZChwb3NpdGlvbk9uUGF0aCwgdG90YWxQYXRoTGVuKSk7XG4gICAgdmFyIHggPSAocENlbnRlci54ICogNCArIHAwLnggKyBwMS54KSAvIDY7XG4gICAgdmFyIHkgPSAocENlbnRlci55ICogNCArIHAwLnkgKyBwMS55KSAvIDY7XG5cbiAgICB2YXIgb3V0ID0ge3g6IHgsIHk6IHksIHRoZXRhOiB0aGV0YX07XG4gICAgbG9jYXRpb25DYWNoZVtwb3NpdGlvbk9uUGF0aF0gPSBvdXQ7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbmV4cG9ydHMuY2xlYXJMb2NhdGlvbkNhY2hlID0gZnVuY3Rpb24oKSB7XG4gICAgd29ya2luZ1BhdGggPSBudWxsO1xufTtcblxuLypcbiAqIEZpbmQgdGhlIHNlZ21lbnQgb2YgYHBhdGhgIHRoYXQncyB3aXRoaW4gdGhlIHZpc2libGUgYXJlYVxuICogZ2l2ZW4gYnkgYGJvdW5kc2Age2xlZnQsIHJpZ2h0LCB0b3AsIGJvdHRvbX0sIHRvIHdpdGhpbiBhXG4gKiBwcmVjaXNpb24gb2YgYGJ1ZmZlcmAgcHhcbiAqXG4gKiByZXR1cm5zOiB1bmRlZmluZWQgaWYgbm90aGluZyBpcyB2aXNpYmxlLCBlbHNlIG9iamVjdDpcbiAqIHtcbiAqICAgbWluOiBwb3NpdGlvbiB3aGVyZSB0aGUgcGF0aCBmaXJzdCBlbnRlcnMgYm91bmRzLCBvciAwIGlmIGl0XG4gKiAgICAgICAgc3RhcnRzIHdpdGhpbiBib3VuZHNcbiAqICAgbWF4OiBwb3NpdGlvbiB3aGVyZSB0aGUgcGF0aCBsYXN0IGV4aXRzIGJvdW5kcywgb3IgdGhlIHBhdGggbGVuZ3RoXG4gKiAgICAgICAgaWYgaXQgZmluaXNoZXMgd2l0aGluIGJvdW5kc1xuICogICBsZW46IG1heCAtIG1pbiwgaWUgdGhlIGxlbmd0aCBvZiB2aXNpYmxlIHBhdGhcbiAqICAgdG90YWw6IHRoZSB0b3RhbCBwYXRoIGxlbmd0aCAtIGp1c3QgaW5jbHVkZWQgc28gdGhlIGNhbGxlciBkb2Vzbid0XG4gKiAgICAgICAgbmVlZCB0byBjYWxsIHBhdGguZ2V0VG90YWxMZW5ndGgoKSBhZ2FpblxuICogICBpc0Nsb3NlZDogdHJ1ZSBpZmYgdGhlIHN0YXJ0IGFuZCBlbmQgcG9pbnRzIG9mIHRoZSBwYXRoIGFyZSBib3RoIHZpc2libGVcbiAqICAgICAgICBhbmQgYXJlIGF0IHRoZSBzYW1lIHBvaW50XG4gKiB9XG4gKlxuICogV29ya3MgYnkgc3RhcnRpbmcgZnJvbSBlaXRoZXIgZW5kIGFuZCByZXBlYXRlZGx5IGZpbmRpbmcgdGhlIGRpc3RhbmNlIGZyb21cbiAqIHRoYXQgcG9pbnQgdG8gdGhlIHBsb3QgYXJlYSwgYW5kIGlmIGl0J3Mgb3V0c2lkZSB0aGUgcGxvdCwgbW92aW5nIGFsb25nIHRoZVxuICogcGF0aCBieSB0aGF0IGRpc3RhbmNlIChiZWNhdXNlIHRoZSBwbG90IG11c3QgYmUgYXQgbGVhc3QgdGhhdCBmYXIgYXdheSBvblxuICogdGhlIHBhdGgpLiBOb3RlIHRoYXQgaWYgYSBwYXRoIGVudGVycywgZXhpdHMsIGFuZCByZS1lbnRlcnMgdGhlIHBsb3QsIHdlXG4gKiB3aWxsIG5vdCBjYXB0dXJlIHRoaXMgYmVoYXZpb3IuXG4gKi9cbmV4cG9ydHMuZ2V0VmlzaWJsZVNlZ21lbnQgPSBmdW5jdGlvbiBnZXRWaXNpYmxlU2VnbWVudChwYXRoLCBib3VuZHMsIGJ1ZmZlcikge1xuICAgIHZhciBsZWZ0ID0gYm91bmRzLmxlZnQ7XG4gICAgdmFyIHJpZ2h0ID0gYm91bmRzLnJpZ2h0O1xuICAgIHZhciB0b3AgPSBib3VuZHMudG9wO1xuICAgIHZhciBib3R0b20gPSBib3VuZHMuYm90dG9tO1xuXG4gICAgdmFyIHBNaW4gPSAwO1xuICAgIHZhciBwVG90YWwgPSBwYXRoLmdldFRvdGFsTGVuZ3RoKCk7XG4gICAgdmFyIHBNYXggPSBwVG90YWw7XG5cbiAgICB2YXIgcHQwLCBwdFRvdGFsO1xuXG4gICAgZnVuY3Rpb24gZ2V0RGlzdFRvUGxvdChsZW4pIHtcbiAgICAgICAgdmFyIHB0ID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKGxlbik7XG5cbiAgICAgICAgLy8gaG9sZCBvbiB0byB0aGUgc3RhcnQgYW5kIGVuZCBwb2ludHMgZm9yIGBjbG9zZWRgXG4gICAgICAgIGlmKGxlbiA9PT0gMCkgcHQwID0gcHQ7XG4gICAgICAgIGVsc2UgaWYobGVuID09PSBwVG90YWwpIHB0VG90YWwgPSBwdDtcblxuICAgICAgICB2YXIgZHggPSAocHQueCA8IGxlZnQpID8gbGVmdCAtIHB0LnggOiAocHQueCA+IHJpZ2h0ID8gcHQueCAtIHJpZ2h0IDogMCk7XG4gICAgICAgIHZhciBkeSA9IChwdC55IDwgdG9wKSA/IHRvcCAtIHB0LnkgOiAocHQueSA+IGJvdHRvbSA/IHB0LnkgLSBib3R0b20gOiAwKTtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgfVxuXG4gICAgdmFyIGRpc3RUb1Bsb3QgPSBnZXREaXN0VG9QbG90KHBNaW4pO1xuICAgIHdoaWxlKGRpc3RUb1Bsb3QpIHtcbiAgICAgICAgcE1pbiArPSBkaXN0VG9QbG90ICsgYnVmZmVyO1xuICAgICAgICBpZihwTWluID4gcE1heCkgcmV0dXJuO1xuICAgICAgICBkaXN0VG9QbG90ID0gZ2V0RGlzdFRvUGxvdChwTWluKTtcbiAgICB9XG5cbiAgICBkaXN0VG9QbG90ID0gZ2V0RGlzdFRvUGxvdChwTWF4KTtcbiAgICB3aGlsZShkaXN0VG9QbG90KSB7XG4gICAgICAgIHBNYXggLT0gZGlzdFRvUGxvdCArIGJ1ZmZlcjtcbiAgICAgICAgaWYocE1pbiA+IHBNYXgpIHJldHVybjtcbiAgICAgICAgZGlzdFRvUGxvdCA9IGdldERpc3RUb1Bsb3QocE1heCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWluOiBwTWluLFxuICAgICAgICBtYXg6IHBNYXgsXG4gICAgICAgIGxlbjogcE1heCAtIHBNaW4sXG4gICAgICAgIHRvdGFsOiBwVG90YWwsXG4gICAgICAgIGlzQ2xvc2VkOiBwTWluID09PSAwICYmIHBNYXggPT09IHBUb3RhbCAmJlxuICAgICAgICAgICAgTWF0aC5hYnMocHQwLnggLSBwdFRvdGFsLngpIDwgMC4xICYmXG4gICAgICAgICAgICBNYXRoLmFicyhwdDAueSAtIHB0VG90YWwueSkgPCAwLjFcbiAgICB9O1xufTtcblxuLyoqXG4gKiBGaW5kIHBvaW50IG9uIFNWRyBwYXRoIGNvcnJlc3BvbmRpbmcgdG8gYSBnaXZlbiBjb25zdHJhaW50IGNvb3JkaW5hdGVcbiAqXG4gKiBAcGFyYW0ge1NWR1BhdGhFbGVtZW50fSBwYXRoXG4gKiBAcGFyYW0ge051bWJlcn0gdmFsIDogY29uc3RyYWludCBjb29yZGluYXRlIHZhbHVlXG4gKiBAcGFyYW0ge1N0cmluZ30gY29vcmQgOiAneCcgb3IgJ3knIHRoZSBjb25zdHJhaW50IGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIDpcbiAqICAtIHtOdW1iZXJ9IHBhdGhMZW5ndGggOiBzdXBwbHkgdG90YWwgcGF0aCBsZW5ndGggYmVmb3JlIGhhbmRcbiAqICAtIHtOdW1iZXJ9IHRvbGVyYW5jZVxuICogIC0ge051bWJlcn0gaXRlcmF0aW9uTGltaXRcbiAqIEByZXR1cm4ge1NWR1BvaW50fVxuICovXG5leHBvcnRzLmZpbmRQb2ludE9uUGF0aCA9IGZ1bmN0aW9uIGZpbmRQb2ludE9uUGF0aChwYXRoLCB2YWwsIGNvb3JkLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgcGF0aExlbmd0aCA9IG9wdHMucGF0aExlbmd0aCB8fCBwYXRoLmdldFRvdGFsTGVuZ3RoKCk7XG4gICAgdmFyIHRvbGVyYW5jZSA9IG9wdHMudG9sZXJhbmNlIHx8IDFlLTM7XG4gICAgdmFyIGl0ZXJhdGlvbkxpbWl0ID0gb3B0cy5pdGVyYXRpb25MaW1pdCB8fCAzMDtcblxuICAgIC8vIGlmIHBhdGggc3RhcnRzIGF0IGEgdmFsIGdyZWF0ZXIgdGhhbiB0aGUgcGF0aCB0YWlsIChsaWtlIG9uIHZlcnRpY2FsIHZpb2xpbnMpLFxuICAgIC8vIHdlIG11c3QgZmxpcCB0aGUgc2lnbiBvZiB0aGUgY29tcHV0ZWQgZGlmZi5cbiAgICB2YXIgbXVsID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKDApW2Nvb3JkXSA+IHBhdGguZ2V0UG9pbnRBdExlbmd0aChwYXRoTGVuZ3RoKVtjb29yZF0gPyAtMSA6IDE7XG5cbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIGIwID0gMDtcbiAgICB2YXIgYjEgPSBwYXRoTGVuZ3RoO1xuICAgIHZhciBtaWQ7XG4gICAgdmFyIHB0O1xuICAgIHZhciBkaWZmO1xuXG4gICAgd2hpbGUoaSA8IGl0ZXJhdGlvbkxpbWl0KSB7XG4gICAgICAgIG1pZCA9IChiMCArIGIxKSAvIDI7XG4gICAgICAgIHB0ID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKG1pZCk7XG4gICAgICAgIGRpZmYgPSBwdFtjb29yZF0gLSB2YWw7XG5cbiAgICAgICAgaWYoTWF0aC5hYnMoZGlmZikgPCB0b2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBwdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKG11bCAqIGRpZmYgPiAwKSB7XG4gICAgICAgICAgICAgICAgYjEgPSBtaWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGIwID0gbWlkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwdDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQWxsb3cgcmVmZXJlbmNpbmcgYSBncmFwaCBET00gZWxlbWVudCBlaXRoZXIgZGlyZWN0bHlcbiAqIG9yIGJ5IGl0cyBpZCBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge0hUTUxEaXZFbGVtZW50fHN0cmluZ30gZ2Q6IGEgZ3JhcGggZWxlbWVudCBvciBpdHMgaWRcbiAqXG4gKiBAcmV0dXJucyB7SFRNTERpdkVsZW1lbnR9IHRoZSBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGhcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBnZEVsZW1lbnQ7XG5cbiAgICBpZih0eXBlb2YgZ2QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGdkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGdkKTtcblxuICAgICAgICBpZihnZEVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gRE9NIGVsZW1lbnQgd2l0aCBpZCBcXCcnICsgZ2QgKyAnXFwnIGV4aXN0cyBvbiB0aGUgcGFnZS4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnZEVsZW1lbnQ7XG4gICAgfVxuICAgIGVsc2UgaWYoZ2QgPT09IG51bGwgfHwgZ2QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RPTSBlbGVtZW50IHByb3ZpZGVkIGlzIG51bGwgb3IgdW5kZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdkOyAgLy8gb3RoZXJ3aXNlIGFzc3VtZSB0aGF0IGdkIGlzIGEgRE9NIGVsZW1lbnRcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xudmFyIHJnYmEgPSByZXF1aXJlKCdjb2xvci1ub3JtYWxpemUnKTtcblxudmFyIENvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcbnZhciBjb2xvckRmbHQgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKS5kZWZhdWx0TGluZTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi9hcnJheScpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbnZhciBjb2xvckRmbHRSZ2JhID0gcmdiYShjb2xvckRmbHQpO1xudmFyIG9wYWNpdHlEZmx0ID0gMTtcblxuZnVuY3Rpb24gY2FsY3VsYXRlQ29sb3IoY29sb3JJbiwgb3BhY2l0eUluKSB7XG4gICAgdmFyIGNvbG9yT3V0ID0gY29sb3JJbjtcbiAgICBjb2xvck91dFszXSAqPSBvcGFjaXR5SW47XG4gICAgcmV0dXJuIGNvbG9yT3V0O1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbG9yKGNvbG9ySW4pIHtcbiAgICBpZihpc051bWVyaWMoY29sb3JJbikpIHJldHVybiBjb2xvckRmbHRSZ2JhO1xuXG4gICAgdmFyIGNvbG9yT3V0ID0gcmdiYShjb2xvckluKTtcblxuICAgIHJldHVybiBjb2xvck91dC5sZW5ndGggPyBjb2xvck91dCA6IGNvbG9yRGZsdFJnYmE7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3BhY2l0eShvcGFjaXR5SW4pIHtcbiAgICByZXR1cm4gaXNOdW1lcmljKG9wYWNpdHlJbikgPyBvcGFjaXR5SW4gOiBvcGFjaXR5RGZsdDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0Q29sb3IoY29udGFpbmVySW4sIG9wYWNpdHlJbiwgbGVuKSB7XG4gICAgdmFyIGNvbG9ySW4gPSBjb250YWluZXJJbi5jb2xvcjtcbiAgICB2YXIgaXNBcnJheUNvbG9ySW4gPSBpc0FycmF5T3JUeXBlZEFycmF5KGNvbG9ySW4pO1xuICAgIHZhciBpc0FycmF5T3BhY2l0eUluID0gaXNBcnJheU9yVHlwZWRBcnJheShvcGFjaXR5SW4pO1xuICAgIHZhciBjb2xvck91dCA9IFtdO1xuXG4gICAgdmFyIHNjbEZ1bmMsIGdldENvbG9yLCBnZXRPcGFjaXR5LCBjb2xvcmksIG9wYWNpdHlpO1xuXG4gICAgaWYoY29udGFpbmVySW4uY29sb3JzY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNjbEZ1bmMgPSBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuYyhcbiAgICAgICAgICAgIENvbG9yc2NhbGUuZXh0cmFjdFNjYWxlKFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lckluLmNvbG9yc2NhbGUsXG4gICAgICAgICAgICAgICAgY29udGFpbmVySW4uY21pbixcbiAgICAgICAgICAgICAgICBjb250YWluZXJJbi5jbWF4XG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBzY2xGdW5jID0gdmFsaWRhdGVDb2xvcjtcbiAgICB9XG5cbiAgICBpZihpc0FycmF5Q29sb3JJbikge1xuICAgICAgICBnZXRDb2xvciA9IGZ1bmN0aW9uKGMsIGkpIHtcbiAgICAgICAgICAgIC8vIEZJWE1FOiB0aGVyZSBpcyBkb3VibGUgd29yaywgY29uc2lkZXJpbmcgdGhhdCBzY2xGdW5jIGRvZXMgdGhlIG9wcG9zaXRlXG4gICAgICAgICAgICByZXR1cm4gY1tpXSA9PT0gdW5kZWZpbmVkID8gY29sb3JEZmx0UmdiYSA6IHJnYmEoc2NsRnVuYyhjW2ldKSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGVsc2UgZ2V0Q29sb3IgPSB2YWxpZGF0ZUNvbG9yO1xuXG4gICAgaWYoaXNBcnJheU9wYWNpdHlJbikge1xuICAgICAgICBnZXRPcGFjaXR5ID0gZnVuY3Rpb24obywgaSkge1xuICAgICAgICAgICAgcmV0dXJuIG9baV0gPT09IHVuZGVmaW5lZCA/IG9wYWNpdHlEZmx0IDogdmFsaWRhdGVPcGFjaXR5KG9baV0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBlbHNlIGdldE9wYWNpdHkgPSB2YWxpZGF0ZU9wYWNpdHk7XG5cbiAgICBpZihpc0FycmF5Q29sb3JJbiB8fCBpc0FycmF5T3BhY2l0eUluKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgY29sb3JpID0gZ2V0Q29sb3IoY29sb3JJbiwgaSk7XG4gICAgICAgICAgICBvcGFjaXR5aSA9IGdldE9wYWNpdHkob3BhY2l0eUluLCBpKTtcbiAgICAgICAgICAgIGNvbG9yT3V0W2ldID0gY2FsY3VsYXRlQ29sb3IoY29sb3JpLCBvcGFjaXR5aSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBjb2xvck91dCA9IGNhbGN1bGF0ZUNvbG9yKHJnYmEoY29sb3JJbiksIG9wYWNpdHlJbik7XG5cbiAgICByZXR1cm4gY29sb3JPdXQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3JTY2FsZShjb2xvcnNjYWxlLCBhbHBoYSkge1xuICAgIGlmKGFscGhhID09PSB1bmRlZmluZWQpIGFscGhhID0gMTtcblxuICAgIHJldHVybiBjb2xvcnNjYWxlLm1hcChmdW5jdGlvbihlbGVtKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGVsZW1bMF07XG4gICAgICAgIHZhciBjb2xvciA9IHRpbnljb2xvcihlbGVtWzFdKTtcbiAgICAgICAgdmFyIHJnYiA9IGNvbG9yLnRvUmdiKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgICAgICByZ2I6IFtyZ2IuciwgcmdiLmcsIHJnYi5iLCBhbHBoYV1cbiAgICAgICAgfTtcbiAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZm9ybWF0Q29sb3I6IGZvcm1hdENvbG9yLFxuICAgIHBhcnNlQ29sb3JTY2FsZTogcGFyc2VDb2xvclNjYWxlXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaWRlbnRpdHkgPSByZXF1aXJlKCcuL2lkZW50aXR5Jyk7XG5cbmZ1bmN0aW9uIHdyYXAoZCkge3JldHVybiBbZF07fVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAgIC8vIFRoZSBEMyBkYXRhIGJpbmRpbmcgY29uY2VwdCBhbmQgdGhlIEdlbmVyYWwgVXBkYXRlIFBhdHRlcm4gcHJvbW90ZXMgdGhlIGlkZWEgb2ZcbiAgICAvLyB0cmF2ZXJzaW5nIGludG8gdGhlIHNjZW5lZ3JhcGggYnkgdXNpbmcgdGhlIGAuZGF0YShmdW4sIGtleUZ1bilgIGNhbGwuXG4gICAgLy8gVGhlIGBmdW5gIGlzIG1vc3Qgb2Z0ZW4gYSBgcmVwZWF0YCwgaWUuIHRoZSBlbGVtZW50cyBiZW5lYXRoIGEgYDxnPmAgZWxlbWVudCBuZWVkXG4gICAgLy8gYWNjZXNzIHRvIHRoZSBzYW1lIGRhdGEsIG9yIGEgYGRlc2NlbmRgLCB3aGljaCBmYW5zIGEgc2NlbmVncmFwaCBub2RlIGludG8gYSBidW5jaCBvZlxuICAgIC8vIG9mIGVsZW1lbnRzLCBlLmcuIHBvaW50cywgbGluZXMsIHJvd3MsIHJlcXVpcmluZyBhbiBhcnJheSBhcyBpbnB1dC5cbiAgICAvLyBUaGUgcm9sZSBvZiB0aGUgYGtleUZ1bmAgaXMgdG8gaWRlbnRpZnkgd2hhdCBlbGVtZW50cyBhcmUgYmVpbmcgZW50ZXJlZC9leGl0ZWQvdXBkYXRlZCxcbiAgICAvLyBvdGhlcndpc2UgRDMgcmV2ZXJ0cyB0byB1c2luZyBhIHBsYWluIGluZGV4IHdoaWNoIHdvdWxkIHNjcmV3IHVwIGB0cmFuc2l0aW9uYHMuXG4gICAga2V5RnVuOiBmdW5jdGlvbihkKSB7cmV0dXJuIGQua2V5O30sXG4gICAgcmVwZWF0OiB3cmFwLFxuICAgIGRlc2NlbmQ6IGlkZW50aXR5LFxuXG4gICAgLy8gUGxvdGx5LmpzIHVzZXMgYSBjb252ZW50aW9uIG9mIHN0b3JpbmcgdGhlIGFjdHVhbCBjb250ZW50cyBvZiB0aGUgYGNhbGNEYXRhYCBhcyB0aGVcbiAgICAvLyBlbGVtZW50IHplcm8gb2YgYSBjb250YWluZXIgYXJyYXkuIFRoZXNlIGhlbHBlcnMgYXJlIGp1c3QgdXNlZCBmb3IgY2xhcml0eSBhcyBhXG4gICAgLy8gbmV3Y29tZXIgdG8gdGhlIGNvZGViYXNlIG1heSBub3Qga25vdyB3aGF0IHRoZSBgWzBdYCBpcywgYW5kIHdoZXRoZXIgdGhlcmUgY2FuIGJlIGZ1cnRoZXJcbiAgICAvLyBlbGVtZW50cyAobm90IGF0bSkuXG4gICAgd3JhcDogd3JhcCxcbiAgICB1bndyYXA6IGZ1bmN0aW9uKGQpIHtyZXR1cm4gZFswXTt9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0b1N1cGVyU2NyaXB0ID0gcmVxdWlyZSgnc3VwZXJzY3JpcHQtdGV4dCcpO1xudmFyIGZpeEVudGl0aWVzID0gcmVxdWlyZSgnLi9zdmdfdGV4dF91dGlscycpLmNvbnZlcnRFbnRpdGllcztcblxuZnVuY3Rpb24gZml4U3VwZXJTY3JpcHQoeCkge1xuICAgIHZhciBpZHggPSAwO1xuXG4gICAgd2hpbGUoKGlkeCA9IHguaW5kZXhPZignPHN1cD4nLCBpZHgpKSA+PSAwKSB7XG4gICAgICAgIHZhciBuaWR4ID0geC5pbmRleE9mKCc8L3N1cD4nLCBpZHgpO1xuICAgICAgICBpZihuaWR4IDwgaWR4KSBicmVhaztcblxuICAgICAgICB4ID0geC5zbGljZSgwLCBpZHgpICsgdG9TdXBlclNjcmlwdCh4LnNsaWNlKGlkeCArIDUsIG5pZHgpKSArIHguc2xpY2UobmlkeCArIDYpO1xuICAgIH1cblxuICAgIHJldHVybiB4O1xufVxuXG5mdW5jdGlvbiBmaXhCUih4KSB7XG4gICAgcmV0dXJuIHgucmVwbGFjZSgvXFw8YnJcXD4vZywgJ1xcbicpO1xufVxuXG5mdW5jdGlvbiBzdHJpcFRhZ3MoeCkge1xuICAgIHJldHVybiB4LnJlcGxhY2UoL1xcPC4qXFw+L2csICcnKTtcbn1cblxuZnVuY3Rpb24gY29udmVydEhUTUxUb1VuaWNvZGUoaHRtbCkge1xuICAgIHJldHVybiAnJyArXG4gICAgICAgIGZpeEVudGl0aWVzKFxuICAgICAgICBzdHJpcFRhZ3MoXG4gICAgICAgIGZpeFN1cGVyU2NyaXB0KFxuICAgICAgICBmaXhCUihcbiAgICAgICAgICBodG1sKSkpKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXJ0SFRNTFRvVW5pY29kZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gU2ltcGxlIGhlbHBlciBmdW5jdGlvbnNcbi8vIG5vbmUgb2YgdGhlc2UgbmVlZCBhbnkgZXh0ZXJuYWwgZGVwc1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlkZW50aXR5KGQpIHsgcmV0dXJuIGQ7IH07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgbnVtQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL251bWVyaWNhbCcpO1xudmFyIEZQX1NBRkUgPSBudW1Db25zdGFudHMuRlBfU0FGRTtcbnZhciBCQUROVU0gPSBudW1Db25zdGFudHMuQkFETlVNO1xuXG52YXIgbGliID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxubGliLm5lc3RlZFByb3BlcnR5ID0gcmVxdWlyZSgnLi9uZXN0ZWRfcHJvcGVydHknKTtcbmxpYi5rZXllZENvbnRhaW5lciA9IHJlcXVpcmUoJy4va2V5ZWRfY29udGFpbmVyJyk7XG5saWIucmVsYXRpdmVBdHRyID0gcmVxdWlyZSgnLi9yZWxhdGl2ZV9hdHRyJyk7XG5saWIuaXNQbGFpbk9iamVjdCA9IHJlcXVpcmUoJy4vaXNfcGxhaW5fb2JqZWN0Jyk7XG5saWIudG9Mb2dSYW5nZSA9IHJlcXVpcmUoJy4vdG9fbG9nX3JhbmdlJyk7XG5saWIucmVsaW5rUHJpdmF0ZUtleXMgPSByZXF1aXJlKCcuL3JlbGlua19wcml2YXRlJyk7XG5cbnZhciBhcnJheU1vZHVsZSA9IHJlcXVpcmUoJy4vYXJyYXknKTtcbmxpYi5pc1R5cGVkQXJyYXkgPSBhcnJheU1vZHVsZS5pc1R5cGVkQXJyYXk7XG5saWIuaXNBcnJheU9yVHlwZWRBcnJheSA9IGFycmF5TW9kdWxlLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5saWIuaXNBcnJheTFEID0gYXJyYXlNb2R1bGUuaXNBcnJheTFEO1xubGliLmVuc3VyZUFycmF5ID0gYXJyYXlNb2R1bGUuZW5zdXJlQXJyYXk7XG5saWIuY29uY2F0ID0gYXJyYXlNb2R1bGUuY29uY2F0O1xuXG52YXIgbW9kTW9kdWxlID0gcmVxdWlyZSgnLi9tb2QnKTtcbmxpYi5tb2QgPSBtb2RNb2R1bGUubW9kO1xubGliLm1vZEhhbGYgPSBtb2RNb2R1bGUubW9kSGFsZjtcblxudmFyIGNvZXJjZU1vZHVsZSA9IHJlcXVpcmUoJy4vY29lcmNlJyk7XG5saWIudmFsT2JqZWN0TWV0YSA9IGNvZXJjZU1vZHVsZS52YWxPYmplY3RNZXRhO1xubGliLmNvZXJjZSA9IGNvZXJjZU1vZHVsZS5jb2VyY2U7XG5saWIuY29lcmNlMiA9IGNvZXJjZU1vZHVsZS5jb2VyY2UyO1xubGliLmNvZXJjZUZvbnQgPSBjb2VyY2VNb2R1bGUuY29lcmNlRm9udDtcbmxpYi5jb2VyY2VIb3ZlcmluZm8gPSBjb2VyY2VNb2R1bGUuY29lcmNlSG92ZXJpbmZvO1xubGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkgPSBjb2VyY2VNb2R1bGUuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eTtcbmxpYi52YWxpZGF0ZSA9IGNvZXJjZU1vZHVsZS52YWxpZGF0ZTtcblxudmFyIGRhdGVzTW9kdWxlID0gcmVxdWlyZSgnLi9kYXRlcycpO1xubGliLmRhdGVUaW1lMm1zID0gZGF0ZXNNb2R1bGUuZGF0ZVRpbWUybXM7XG5saWIuaXNEYXRlVGltZSA9IGRhdGVzTW9kdWxlLmlzRGF0ZVRpbWU7XG5saWIubXMyRGF0ZVRpbWUgPSBkYXRlc01vZHVsZS5tczJEYXRlVGltZTtcbmxpYi5tczJEYXRlVGltZUxvY2FsID0gZGF0ZXNNb2R1bGUubXMyRGF0ZVRpbWVMb2NhbDtcbmxpYi5jbGVhbkRhdGUgPSBkYXRlc01vZHVsZS5jbGVhbkRhdGU7XG5saWIuaXNKU0RhdGUgPSBkYXRlc01vZHVsZS5pc0pTRGF0ZTtcbmxpYi5mb3JtYXREYXRlID0gZGF0ZXNNb2R1bGUuZm9ybWF0RGF0ZTtcbmxpYi5pbmNyZW1lbnRNb250aCA9IGRhdGVzTW9kdWxlLmluY3JlbWVudE1vbnRoO1xubGliLmRhdGVUaWNrMCA9IGRhdGVzTW9kdWxlLmRhdGVUaWNrMDtcbmxpYi5kZmx0UmFuZ2UgPSBkYXRlc01vZHVsZS5kZmx0UmFuZ2U7XG5saWIuZmluZEV4YWN0RGF0ZXMgPSBkYXRlc01vZHVsZS5maW5kRXhhY3REYXRlcztcbmxpYi5NSU5fTVMgPSBkYXRlc01vZHVsZS5NSU5fTVM7XG5saWIuTUFYX01TID0gZGF0ZXNNb2R1bGUuTUFYX01TO1xuXG52YXIgc2VhcmNoTW9kdWxlID0gcmVxdWlyZSgnLi9zZWFyY2gnKTtcbmxpYi5maW5kQmluID0gc2VhcmNoTW9kdWxlLmZpbmRCaW47XG5saWIuc29ydGVyQXNjID0gc2VhcmNoTW9kdWxlLnNvcnRlckFzYztcbmxpYi5zb3J0ZXJEZXMgPSBzZWFyY2hNb2R1bGUuc29ydGVyRGVzO1xubGliLmRpc3RpbmN0VmFscyA9IHNlYXJjaE1vZHVsZS5kaXN0aW5jdFZhbHM7XG5saWIucm91bmRVcCA9IHNlYXJjaE1vZHVsZS5yb3VuZFVwO1xubGliLnNvcnQgPSBzZWFyY2hNb2R1bGUuc29ydDtcbmxpYi5maW5kSW5kZXhPZk1pbiA9IHNlYXJjaE1vZHVsZS5maW5kSW5kZXhPZk1pbjtcblxudmFyIHN0YXRzTW9kdWxlID0gcmVxdWlyZSgnLi9zdGF0cycpO1xubGliLmFnZ051bXMgPSBzdGF0c01vZHVsZS5hZ2dOdW1zO1xubGliLmxlbiA9IHN0YXRzTW9kdWxlLmxlbjtcbmxpYi5tZWFuID0gc3RhdHNNb2R1bGUubWVhbjtcbmxpYi5taWRSYW5nZSA9IHN0YXRzTW9kdWxlLm1pZFJhbmdlO1xubGliLnZhcmlhbmNlID0gc3RhdHNNb2R1bGUudmFyaWFuY2U7XG5saWIuc3RkZXYgPSBzdGF0c01vZHVsZS5zdGRldjtcbmxpYi5pbnRlcnAgPSBzdGF0c01vZHVsZS5pbnRlcnA7XG5cbnZhciBtYXRyaXhNb2R1bGUgPSByZXF1aXJlKCcuL21hdHJpeCcpO1xubGliLmluaXQyZEFycmF5ID0gbWF0cml4TW9kdWxlLmluaXQyZEFycmF5O1xubGliLnRyYW5zcG9zZVJhZ2dlZCA9IG1hdHJpeE1vZHVsZS50cmFuc3Bvc2VSYWdnZWQ7XG5saWIuZG90ID0gbWF0cml4TW9kdWxlLmRvdDtcbmxpYi50cmFuc2xhdGlvbk1hdHJpeCA9IG1hdHJpeE1vZHVsZS50cmFuc2xhdGlvbk1hdHJpeDtcbmxpYi5yb3RhdGlvbk1hdHJpeCA9IG1hdHJpeE1vZHVsZS5yb3RhdGlvbk1hdHJpeDtcbmxpYi5yb3RhdGlvblhZTWF0cml4ID0gbWF0cml4TW9kdWxlLnJvdGF0aW9uWFlNYXRyaXg7XG5saWIuYXBwbHkyRFRyYW5zZm9ybSA9IG1hdHJpeE1vZHVsZS5hcHBseTJEVHJhbnNmb3JtO1xubGliLmFwcGx5MkRUcmFuc2Zvcm0yID0gbWF0cml4TW9kdWxlLmFwcGx5MkRUcmFuc2Zvcm0yO1xuXG52YXIgYW5nbGVzTW9kdWxlID0gcmVxdWlyZSgnLi9hbmdsZXMnKTtcbmxpYi5kZWcycmFkID0gYW5nbGVzTW9kdWxlLmRlZzJyYWQ7XG5saWIucmFkMmRlZyA9IGFuZ2xlc01vZHVsZS5yYWQyZGVnO1xubGliLmFuZ2xlRGVsdGEgPSBhbmdsZXNNb2R1bGUuYW5nbGVEZWx0YTtcbmxpYi5hbmdsZURpc3QgPSBhbmdsZXNNb2R1bGUuYW5nbGVEaXN0O1xubGliLmlzRnVsbENpcmNsZSA9IGFuZ2xlc01vZHVsZS5pc0Z1bGxDaXJjbGU7XG5saWIuaXNBbmdsZUluc2lkZVNlY3RvciA9IGFuZ2xlc01vZHVsZS5pc0FuZ2xlSW5zaWRlU2VjdG9yO1xubGliLmlzUHRJbnNpZGVTZWN0b3IgPSBhbmdsZXNNb2R1bGUuaXNQdEluc2lkZVNlY3RvcjtcbmxpYi5wYXRoQXJjID0gYW5nbGVzTW9kdWxlLnBhdGhBcmM7XG5saWIucGF0aFNlY3RvciA9IGFuZ2xlc01vZHVsZS5wYXRoU2VjdG9yO1xubGliLnBhdGhBbm51bHVzID0gYW5nbGVzTW9kdWxlLnBhdGhBbm51bHVzO1xuXG52YXIgZ2VvbTJkTW9kdWxlID0gcmVxdWlyZSgnLi9nZW9tZXRyeTJkJyk7XG5saWIuc2VnbWVudHNJbnRlcnNlY3QgPSBnZW9tMmRNb2R1bGUuc2VnbWVudHNJbnRlcnNlY3Q7XG5saWIuc2VnbWVudERpc3RhbmNlID0gZ2VvbTJkTW9kdWxlLnNlZ21lbnREaXN0YW5jZTtcbmxpYi5nZXRUZXh0TG9jYXRpb24gPSBnZW9tMmRNb2R1bGUuZ2V0VGV4dExvY2F0aW9uO1xubGliLmNsZWFyTG9jYXRpb25DYWNoZSA9IGdlb20yZE1vZHVsZS5jbGVhckxvY2F0aW9uQ2FjaGU7XG5saWIuZ2V0VmlzaWJsZVNlZ21lbnQgPSBnZW9tMmRNb2R1bGUuZ2V0VmlzaWJsZVNlZ21lbnQ7XG5saWIuZmluZFBvaW50T25QYXRoID0gZ2VvbTJkTW9kdWxlLmZpbmRQb2ludE9uUGF0aDtcblxudmFyIGV4dGVuZE1vZHVsZSA9IHJlcXVpcmUoJy4vZXh0ZW5kJyk7XG5saWIuZXh0ZW5kRmxhdCA9IGV4dGVuZE1vZHVsZS5leHRlbmRGbGF0O1xubGliLmV4dGVuZERlZXAgPSBleHRlbmRNb2R1bGUuZXh0ZW5kRGVlcDtcbmxpYi5leHRlbmREZWVwQWxsID0gZXh0ZW5kTW9kdWxlLmV4dGVuZERlZXBBbGw7XG5saWIuZXh0ZW5kRGVlcE5vQXJyYXlzID0gZXh0ZW5kTW9kdWxlLmV4dGVuZERlZXBOb0FycmF5cztcblxudmFyIGxvZ2dlcnNNb2R1bGUgPSByZXF1aXJlKCcuL2xvZ2dlcnMnKTtcbmxpYi5sb2cgPSBsb2dnZXJzTW9kdWxlLmxvZztcbmxpYi53YXJuID0gbG9nZ2Vyc01vZHVsZS53YXJuO1xubGliLmVycm9yID0gbG9nZ2Vyc01vZHVsZS5lcnJvcjtcblxudmFyIHJlZ2V4TW9kdWxlID0gcmVxdWlyZSgnLi9yZWdleCcpO1xubGliLmNvdW50ZXJSZWdleCA9IHJlZ2V4TW9kdWxlLmNvdW50ZXI7XG5cbnZhciB0aHJvdHRsZU1vZHVsZSA9IHJlcXVpcmUoJy4vdGhyb3R0bGUnKTtcbmxpYi50aHJvdHRsZSA9IHRocm90dGxlTW9kdWxlLnRocm90dGxlO1xubGliLnRocm90dGxlRG9uZSA9IHRocm90dGxlTW9kdWxlLmRvbmU7XG5saWIuY2xlYXJUaHJvdHRsZSA9IHRocm90dGxlTW9kdWxlLmNsZWFyO1xuXG5saWIuZ2V0R3JhcGhEaXYgPSByZXF1aXJlKCcuL2dldF9ncmFwaF9kaXYnKTtcblxubGliLmNsZWFyUmVzcG9uc2l2ZSA9IHJlcXVpcmUoJy4vY2xlYXJfcmVzcG9uc2l2ZScpO1xuXG5saWIubWFrZVRyYWNlR3JvdXBzID0gcmVxdWlyZSgnLi9tYWtlX3RyYWNlX2dyb3VwcycpO1xuXG5saWIuXyA9IHJlcXVpcmUoJy4vbG9jYWxpemUnKTtcblxubGliLm5vdGlmaWVyID0gcmVxdWlyZSgnLi9ub3RpZmllcicpO1xuXG5saWIuZmlsdGVyVW5pcXVlID0gcmVxdWlyZSgnLi9maWx0ZXJfdW5pcXVlJyk7XG5saWIuZmlsdGVyVmlzaWJsZSA9IHJlcXVpcmUoJy4vZmlsdGVyX3Zpc2libGUnKTtcbmxpYi5wdXNoVW5pcXVlID0gcmVxdWlyZSgnLi9wdXNoX3VuaXF1ZScpO1xuXG5saWIuY2xlYW5OdW1iZXIgPSByZXF1aXJlKCcuL2NsZWFuX251bWJlcicpO1xuXG5saWIuZW5zdXJlTnVtYmVyID0gZnVuY3Rpb24gbnVtKHYpIHtcbiAgICBpZighaXNOdW1lcmljKHYpKSByZXR1cm4gQkFETlVNO1xuICAgIHYgPSBOdW1iZXIodik7XG4gICAgaWYodiA8IC1GUF9TQUZFIHx8IHYgPiBGUF9TQUZFKSByZXR1cm4gQkFETlVNO1xuICAgIHJldHVybiBpc051bWVyaWModikgPyBOdW1iZXIodikgOiBCQUROVU07XG59O1xuXG4vKipcbiAqIElzIHYgYSB2YWxpZCBhcnJheSBpbmRleD8gQWNjZXB0cyBudW1lcmljIHN0cmluZ3MgYXMgd2VsbCBhcyBudW1iZXJzLlxuICpcbiAqIEBwYXJhbSB7YW55fSB2OiB0aGUgdmFsdWUgdG8gdGVzdFxuICogQHBhcmFtIHtPcHRpb25hbFtpbnRlZ2VyXX0gbGVuOiB0aGUgYXJyYXkgbGVuZ3RoIHdlIGFyZSBpbmRleGluZ1xuICpcbiAqIEByZXR1cm4ge2Jvb2x9OiB2IGlzIGEgdmFsaWQgYXJyYXkgaW5kZXhcbiAqL1xubGliLmlzSW5kZXggPSBmdW5jdGlvbih2LCBsZW4pIHtcbiAgICBpZihsZW4gIT09IHVuZGVmaW5lZCAmJiB2ID49IGxlbikgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBpc051bWVyaWModikgJiYgKHYgPj0gMCkgJiYgKHYgJSAxID09PSAwKTtcbn07XG5cbmxpYi5ub29wID0gcmVxdWlyZSgnLi9ub29wJyk7XG5saWIuaWRlbnRpdHkgPSByZXF1aXJlKCcuL2lkZW50aXR5Jyk7XG5cbi8qKlxuICogY3JlYXRlIGFuIGFycmF5IG9mIGxlbmd0aCAnY250JyBmaWxsZWQgd2l0aCAndicgYXQgYWxsIGluZGljZXNcbiAqXG4gKiBAcGFyYW0ge2FueX0gdlxuICogQHBhcmFtIHtudW1iZXJ9IGNudFxuICogQHJldHVybiB7YXJyYXl9XG4gKi9cbmxpYi5yZXBlYXQgPSBmdW5jdGlvbih2LCBjbnQpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEFycmF5KGNudCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNudDsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IHY7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIHN3YXAgeCBhbmQgeSBvZiB0aGUgc2FtZSBhdHRyaWJ1dGUgaW4gY29udGFpbmVyIGNvbnRcbiAqIHNwZWNpZnkgYXR0ciB3aXRoIGEgPyBpbiBwbGFjZSBvZiB4L3lcbiAqIHlvdSBjYW4gYWxzbyBzd2FwIG90aGVyIHRoaW5ncyB0aGFuIHgveSBieSBwcm92aWRpbmcgcGFydDEgYW5kIHBhcnQyXG4gKi9cbmxpYi5zd2FwQXR0cnMgPSBmdW5jdGlvbihjb250LCBhdHRyTGlzdCwgcGFydDEsIHBhcnQyKSB7XG4gICAgaWYoIXBhcnQxKSBwYXJ0MSA9ICd4JztcbiAgICBpZighcGFydDIpIHBhcnQyID0gJ3knO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhdHRyTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXR0ciA9IGF0dHJMaXN0W2ldLFxuICAgICAgICAgICAgeHAgPSBsaWIubmVzdGVkUHJvcGVydHkoY29udCwgYXR0ci5yZXBsYWNlKCc/JywgcGFydDEpKSxcbiAgICAgICAgICAgIHlwID0gbGliLm5lc3RlZFByb3BlcnR5KGNvbnQsIGF0dHIucmVwbGFjZSgnPycsIHBhcnQyKSksXG4gICAgICAgICAgICB0ZW1wID0geHAuZ2V0KCk7XG4gICAgICAgIHhwLnNldCh5cC5nZXQoKSk7XG4gICAgICAgIHlwLnNldCh0ZW1wKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFNWRyBwYWludGVyJ3MgYWxnbyB3b3JrZWQgYXJvdW5kIHdpdGggcmVpbnNlcnRpb25cbiAqL1xubGliLnJhaXNlVG9Ub3AgPSBmdW5jdGlvbiByYWlzZVRvVG9wKGVsZW0pIHtcbiAgICBlbGVtLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoZWxlbSk7XG59O1xuXG4vKipcbiAqIGNhbmNlbCBhIHBvc3NpYmx5IHBlbmRpbmcgdHJhbnNpdGlvbjsgcmV0dXJuZWQgc2VsZWN0aW9uIG1heSBiZSB1c2VkIGJ5IGNhbGxlclxuICovXG5saWIuY2FuY2VsVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICAgIHJldHVybiBzZWxlY3Rpb24udHJhbnNpdGlvbigpLmR1cmF0aW9uKDApO1xufTtcblxuLy8gY29uc3RyYWluIC0gcmVzdHJpY3QgYSBudW1iZXIgdiB0byBiZSBiZXR3ZWVuIHYwIGFuZCB2MVxubGliLmNvbnN0cmFpbiA9IGZ1bmN0aW9uKHYsIHYwLCB2MSkge1xuICAgIGlmKHYwID4gdjEpIHJldHVybiBNYXRoLm1heCh2MSwgTWF0aC5taW4odjAsIHYpKTtcbiAgICByZXR1cm4gTWF0aC5tYXgodjAsIE1hdGgubWluKHYxLCB2KSk7XG59O1xuXG4vKipcbiAqIGRvIHR3byBib3VuZGluZyBib3hlcyBmcm9tIGdldEJvdW5kaW5nQ2xpZW50UmVjdCxcbiAqIGllIHtsZWZ0LHJpZ2h0LHRvcCxib3R0b20sd2lkdGgsaGVpZ2h0fSwgb3ZlcmxhcD9cbiAqIHRha2VzIG9wdGlvbmFsIHBhZGRpbmcgcGl4ZWxzXG4gKi9cbmxpYi5iQm94SW50ZXJzZWN0ID0gZnVuY3Rpb24oYSwgYiwgcGFkKSB7XG4gICAgcGFkID0gcGFkIHx8IDA7XG4gICAgcmV0dXJuIChhLmxlZnQgPD0gYi5yaWdodCArIHBhZCAmJlxuICAgICAgICAgICAgYi5sZWZ0IDw9IGEucmlnaHQgKyBwYWQgJiZcbiAgICAgICAgICAgIGEudG9wIDw9IGIuYm90dG9tICsgcGFkICYmXG4gICAgICAgICAgICBiLnRvcCA8PSBhLmJvdHRvbSArIHBhZCk7XG59O1xuXG4vKlxuICogc2ltcGxlTWFwOiBhbHRlcm5hdGl2ZSB0byBBcnJheS5tYXAgdGhhdCBvbmx5XG4gKiBwYXNzZXMgb24gdGhlIGVsZW1lbnQgYW5kIHVwIHRvIDIgZXh0cmEgYXJncyB5b3VcbiAqIHByb3ZpZGUgKGJ1dCBub3QgdGhlIGFycmF5IGluZGV4IG9yIHRoZSB3aG9sZSBhcnJheSlcbiAqXG4gKiBhcnJheTogdGhlIGFycmF5IHRvIG1hcCBpdCB0b1xuICogZnVuYzogdGhlIGZ1bmN0aW9uIHRvIGFwcGx5XG4gKiB4MSwgeDI6IG9wdGlvbmFsIGV4dHJhIGFyZ3NcbiAqL1xubGliLnNpbXBsZU1hcCA9IGZ1bmN0aW9uKGFycmF5LCBmdW5jLCB4MSwgeDIpIHtcbiAgICB2YXIgbGVuID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICBvdXQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dFtpXSA9IGZ1bmMoYXJyYXlbaV0sIHgxLCB4Mik7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmFuZG9tIHN0cmluZyBnZW5lcmF0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZXhpc3RpbmdcbiAqICAgICBwYXNzIGluIHN0cmluZ3MgdG8gYXZvaWQgYXMga2V5cyB3aXRoIHRydXRoeSB2YWx1ZXNcbiAqIEBwYXJhbSB7aW50fSBiaXRzXG4gKiAgICAgYml0cyBvZiBpbmZvcm1hdGlvbiBpbiB0aGUgb3V0cHV0IHN0cmluZywgZGVmYXVsdCAyNFxuICogQHBhcmFtIHtpbnR9IGJhc2VcbiAqICAgICBiYXNlIG9mIHN0cmluZyByZXByZXNlbnRhdGlvbiwgZGVmYXVsdCAxNi4gU2hvdWxkIGJlIGEgcG93ZXIgb2YgMi5cbiAqL1xubGliLnJhbmRzdHIgPSBmdW5jdGlvbiByYW5kc3RyKGV4aXN0aW5nLCBiaXRzLCBiYXNlLCBfcmVjdXJzaW9uKSB7XG4gICAgaWYoIWJhc2UpIGJhc2UgPSAxNjtcbiAgICBpZihiaXRzID09PSB1bmRlZmluZWQpIGJpdHMgPSAyNDtcbiAgICBpZihiaXRzIDw9IDApIHJldHVybiAnMCc7XG5cbiAgICB2YXIgZGlnaXRzID0gTWF0aC5sb2coTWF0aC5wb3coMiwgYml0cykpIC8gTWF0aC5sb2coYmFzZSk7XG4gICAgdmFyIHJlcyA9ICcnO1xuICAgIHZhciBpLCBiLCB4O1xuXG4gICAgZm9yKGkgPSAyOyBkaWdpdHMgPT09IEluZmluaXR5OyBpICo9IDIpIHtcbiAgICAgICAgZGlnaXRzID0gTWF0aC5sb2coTWF0aC5wb3coMiwgYml0cyAvIGkpKSAvIE1hdGgubG9nKGJhc2UpICogaTtcbiAgICB9XG5cbiAgICB2YXIgcmVtID0gZGlnaXRzIC0gTWF0aC5mbG9vcihkaWdpdHMpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgTWF0aC5mbG9vcihkaWdpdHMpOyBpKyspIHtcbiAgICAgICAgeCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGJhc2UpLnRvU3RyaW5nKGJhc2UpO1xuICAgICAgICByZXMgPSB4ICsgcmVzO1xuICAgIH1cblxuICAgIGlmKHJlbSkge1xuICAgICAgICBiID0gTWF0aC5wb3coYmFzZSwgcmVtKTtcbiAgICAgICAgeCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGIpLnRvU3RyaW5nKGJhc2UpO1xuICAgICAgICByZXMgPSB4ICsgcmVzO1xuICAgIH1cblxuICAgIHZhciBwYXJzZWQgPSBwYXJzZUludChyZXMsIGJhc2UpO1xuICAgIGlmKChleGlzdGluZyAmJiBleGlzdGluZ1tyZXNdKSB8fFxuICAgICAgICAgKHBhcnNlZCAhPT0gSW5maW5pdHkgJiYgcGFyc2VkID49IE1hdGgucG93KDIsIGJpdHMpKSkge1xuICAgICAgICBpZihfcmVjdXJzaW9uID4gMTApIHtcbiAgICAgICAgICAgIGxpYi53YXJuKCdyYW5kc3RyIGZhaWxlZCB1bmlxdWVuZXNzJyk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByYW5kc3RyKGV4aXN0aW5nLCBiaXRzLCBiYXNlLCAoX3JlY3Vyc2lvbiB8fCAwKSArIDEpO1xuICAgIH1cbiAgICBlbHNlIHJldHVybiByZXM7XG59O1xuXG5saWIuT3B0aW9uQ29udHJvbCA9IGZ1bmN0aW9uKG9wdCwgb3B0bmFtZSkge1xuICAgIC8qXG4gICAgICogQW4gZW52aXJvbm1lbnQgdG8gY29udGFpbiBhbGwgb3B0aW9uIHNldHRlcnMgYW5kXG4gICAgICogZ2V0dGVycyB0aGF0IGNvbGxlY3RpdmVseSBtb2RpZnkgb3B0cy5cbiAgICAgKlxuICAgICAqIFlvdSBjYW4gY2FsbCB1cCBvcHRzIGZyb20gYW55IGZ1bmN0aW9uIGluIG5ldyBvYmplY3RcbiAgICAgKiBhcyB0aGlzLm9wdG5hbWUgfHwgdGhpcy5vcHRcbiAgICAgKlxuICAgICAqIFNlZSBGaXRPcHRzIGZvciBleGFtcGxlIG9mIHVzYWdlXG4gICAgICovXG4gICAgaWYoIW9wdCkgb3B0ID0ge307XG4gICAgaWYoIW9wdG5hbWUpIG9wdG5hbWUgPSAnb3B0JztcblxuICAgIHZhciBzZWxmID0ge307XG4gICAgc2VsZi5vcHRpb25MaXN0ID0gW107XG5cbiAgICBzZWxmLl9uZXdvcHRpb24gPSBmdW5jdGlvbihvcHRPYmopIHtcbiAgICAgICAgb3B0T2JqW29wdG5hbWVdID0gb3B0O1xuICAgICAgICBzZWxmW29wdE9iai5uYW1lXSA9IG9wdE9iajtcbiAgICAgICAgc2VsZi5vcHRpb25MaXN0LnB1c2gob3B0T2JqKTtcbiAgICB9O1xuXG4gICAgc2VsZlsnXycgKyBvcHRuYW1lXSA9IG9wdDtcbiAgICByZXR1cm4gc2VsZjtcbn07XG5cbi8qKlxuICogbGliLnNtb290aDogc21vb3RoIGFycmF5SW4gYnkgY29udm9sdmluZyB3aXRoXG4gKiBhIGhhbm4gd2luZG93IHdpdGggZ2l2ZW4gZnVsbCB3aWR0aCBhdCBoYWxmIG1heFxuICogYm91bmNlIHRoZSBlbmRzIGluLCBzbyB0aGUgb3V0cHV0IGhhcyB0aGUgc2FtZSBsZW5ndGggYXMgdGhlIGlucHV0XG4gKi9cbmxpYi5zbW9vdGggPSBmdW5jdGlvbihhcnJheUluLCBGV0hNKSB7XG4gICAgRldITSA9IE1hdGgucm91bmQoRldITSkgfHwgMDsgLy8gb25seSBtYWtlcyBzZW5zZSBmb3IgaW50ZWdlcnNcbiAgICBpZihGV0hNIDwgMikgcmV0dXJuIGFycmF5SW47XG5cbiAgICB2YXIgYWxlbiA9IGFycmF5SW4ubGVuZ3RoLFxuICAgICAgICBhbGVuMiA9IDIgKiBhbGVuLFxuICAgICAgICB3bGVuID0gMiAqIEZXSE0gLSAxLFxuICAgICAgICB3ID0gbmV3IEFycmF5KHdsZW4pLFxuICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShhbGVuKSxcbiAgICAgICAgaSxcbiAgICAgICAgaixcbiAgICAgICAgayxcbiAgICAgICAgdjtcblxuICAgIC8vIGZpcnN0IG1ha2UgdGhlIHdpbmRvdyBhcnJheVxuICAgIGZvcihpID0gMDsgaSA8IHdsZW47IGkrKykge1xuICAgICAgICB3W2ldID0gKDEgLSBNYXRoLmNvcyhNYXRoLlBJICogKGkgKyAxKSAvIEZXSE0pKSAvICgyICogRldITSk7XG4gICAgfVxuXG4gICAgLy8gbm93IGRvIHRoZSBjb252b2x1dGlvblxuICAgIGZvcihpID0gMDsgaSA8IGFsZW47IGkrKykge1xuICAgICAgICB2ID0gMDtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgd2xlbjsgaisrKSB7XG4gICAgICAgICAgICBrID0gaSArIGogKyAxIC0gRldITTtcblxuICAgICAgICAgICAgLy8gbXVsdGlib3VuY2VcbiAgICAgICAgICAgIGlmKGsgPCAtYWxlbikgayAtPSBhbGVuMiAqIE1hdGgucm91bmQoayAvIGFsZW4yKTtcbiAgICAgICAgICAgIGVsc2UgaWYoayA+PSBhbGVuMikgayAtPSBhbGVuMiAqIE1hdGguZmxvb3IoayAvIGFsZW4yKTtcblxuICAgICAgICAgICAgLy8gc2luZ2xlIGJvdW5jZVxuICAgICAgICAgICAgaWYoayA8IDApIGsgPSAtIDEgLSBrO1xuICAgICAgICAgICAgZWxzZSBpZihrID49IGFsZW4pIGsgPSBhbGVuMiAtIDEgLSBrO1xuXG4gICAgICAgICAgICB2ICs9IGFycmF5SW5ba10gKiB3W2pdO1xuICAgICAgICB9XG4gICAgICAgIGFycmF5T3V0W2ldID0gdjtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyYXlPdXQ7XG59O1xuXG4vKipcbiAqIHN5bmNPckFzeW5jOiBydW4gYSBzZXF1ZW5jZSBvZiBmdW5jdGlvbnMgc3luY2hyb25vdXNseVxuICogYXMgbG9uZyBhcyBpdHMgcmV0dXJucyBhcmUgbm90IHByb21pc2VzIChpZSBoYXZlIG5vIC50aGVuKVxuICogaW5jbHVkZXMgb25lIGFyZ3VtZW50IGFyZyB0byBzZW5kIHRvIGFsbCBmdW5jdGlvbnMuLi5cbiAqIHRoaXMgaXMgbWFpbmx5IGp1c3QgdG8gcHJldmVudCB1cyBoYXZpbmcgdG8gbWFrZSB3cmFwcGVyIGZ1bmN0aW9uc1xuICogd2hlbiB0aGUgb25seSBwdXJwb3NlIG9mIHRoZSB3cmFwcGVyIGlzIHRvIHJlZmVyZW5jZSBnZFxuICogYW5kIGEgZmluYWwgc3RlcCB0byBiZSBleGVjdXRlZCBhdCB0aGUgZW5kXG4gKiBUT0RPOiBpZiB0aGVyZSdzIGFuIGVycm9yIGFuZCBldmVyeXRoaW5nIGlzIHN5bmMsXG4gKiB0aGlzIGRvZXNuJ3QgaGFwcGVuIHlldCBiZWNhdXNlIHdlIHdhbnQgdG8gbWFrZSBzdXJlXG4gKiB0aGF0IGl0IGdldHMgcmVwb3J0ZWRcbiAqL1xubGliLnN5bmNPckFzeW5jID0gZnVuY3Rpb24oc2VxdWVuY2UsIGFyZywgZmluYWxTdGVwKSB7XG4gICAgdmFyIHJldCwgZm5pO1xuXG4gICAgZnVuY3Rpb24gY29udGludWVBc3luYygpIHtcbiAgICAgICAgcmV0dXJuIGxpYi5zeW5jT3JBc3luYyhzZXF1ZW5jZSwgYXJnLCBmaW5hbFN0ZXApO1xuICAgIH1cblxuICAgIHdoaWxlKHNlcXVlbmNlLmxlbmd0aCkge1xuICAgICAgICBmbmkgPSBzZXF1ZW5jZS5zcGxpY2UoMCwgMSlbMF07XG4gICAgICAgIHJldCA9IGZuaShhcmcpO1xuXG4gICAgICAgIGlmKHJldCAmJiByZXQudGhlbikge1xuICAgICAgICAgICAgcmV0dXJuIHJldC50aGVuKGNvbnRpbnVlQXN5bmMpXG4gICAgICAgICAgICAgICAgLnRoZW4odW5kZWZpbmVkLCBsaWIucHJvbWlzZUVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaW5hbFN0ZXAgJiYgZmluYWxTdGVwKGFyZyk7XG59O1xuXG5cbi8qKlxuICogSGVscGVyIHRvIHN0cmlwIHRyYWlsaW5nIHNsYXNoLCBmcm9tXG4gKiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY2ODA4MjUvcmV0dXJuLXN0cmluZy13aXRob3V0LXRyYWlsaW5nLXNsYXNoXG4gKi9cbmxpYi5zdHJpcFRyYWlsaW5nU2xhc2ggPSBmdW5jdGlvbihzdHIpIHtcbiAgICBpZihzdHIuc3Vic3RyKC0xKSA9PT0gJy8nKSByZXR1cm4gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoIC0gMSk7XG4gICAgcmV0dXJuIHN0cjtcbn07XG5cbmxpYi5ub25lT3JBbGwgPSBmdW5jdGlvbihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyTGlzdCkge1xuICAgIC8qKlxuICAgICAqIHNvbWUgYXR0cmlidXRlcyBjb21lIHRvZ2V0aGVyLCBzbyBpZiB5b3UgaGF2ZSBvbmUgb2YgdGhlbVxuICAgICAqIGluIHRoZSBpbnB1dCwgeW91IHNob3VsZCBjb3B5IHRoZSBkZWZhdWx0IHZhbHVlcyBvZiB0aGUgb3RoZXJzXG4gICAgICogdG8gdGhlIGlucHV0IGFzIHdlbGwuXG4gICAgICovXG4gICAgaWYoIWNvbnRhaW5lckluKSByZXR1cm47XG5cbiAgICB2YXIgaGFzQW55ID0gZmFsc2UsXG4gICAgICAgIGhhc0FsbCA9IHRydWUsXG4gICAgICAgIGksXG4gICAgICAgIHZhbDtcblxuICAgIGZvcihpID0gMDsgaSA8IGF0dHJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbCA9IGNvbnRhaW5lckluW2F0dHJMaXN0W2ldXTtcbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBudWxsKSBoYXNBbnkgPSB0cnVlO1xuICAgICAgICBlbHNlIGhhc0FsbCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKGhhc0FueSAmJiAhaGFzQWxsKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF0dHJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb250YWluZXJJblthdHRyTGlzdFtpXV0gPSBjb250YWluZXJPdXRbYXR0ckxpc3RbaV1dO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqIG1lcmdlcyBjYWxjZGF0YSBmaWVsZCAoZ2l2ZW4gYnkgY2RBdHRyKSB3aXRoIHRyYWNlQXR0ciB2YWx1ZXNcbiAqXG4gKiBOLkIuIExvb3Agb3ZlciBtaW5pbXVtIG9mIGNkLmxlbmd0aCBhbmQgdHJhY2VBdHRyLmxlbmd0aFxuICogaS5lLiBpdCBkb2VzIG5vdCB0cnkgdG8gZmlsbCBpbiBiZXlvbmQgdHJhY2VBdHRyLmxlbmd0aC0xXG4gKlxuICogQHBhcmFtIHthcnJheX0gdHJhY2VBdHRyIDogdHJhY2UgYXR0cmlidXRlXG4gKiBAcGFyYW0ge29iamVjdH0gY2QgOiBjYWxjZGF0YSB0cmFjZVxuICogQHBhcmFtIHtzdHJpbmd9IGNkQXR0ciA6IGNhbGNkYXRhIGtleVxuICovXG5saWIubWVyZ2VBcnJheSA9IGZ1bmN0aW9uKHRyYWNlQXR0ciwgY2QsIGNkQXR0cikge1xuICAgIGlmKGxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlQXR0cikpIHtcbiAgICAgICAgdmFyIGltYXggPSBNYXRoLm1pbih0cmFjZUF0dHIubGVuZ3RoLCBjZC5sZW5ndGgpO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW1heDsgaSsrKSBjZFtpXVtjZEF0dHJdID0gdHJhY2VBdHRyW2ldO1xuICAgIH1cbn07XG5cbi8qKiBmaWxscyBjYWxjZGF0YSBmaWVsZCAoZ2l2ZW4gYnkgY2RBdHRyKSB3aXRoIHRyYWNlQXR0ciB2YWx1ZXNcbiAqICBvciBmdW5jdGlvbiBvZiB0cmFjZUF0dHIgdmFsdWVzIChlLmcuIHNvbWUgZmFsbGJhY2spXG4gKlxuICogTi5CLiBMb29wcyBvdmVyIGFsbCBjZCBpdGVtcy5cbiAqXG4gKiBAcGFyYW0ge2FycmF5fSB0cmFjZUF0dHIgOiB0cmFjZSBhdHRyaWJ1dGVcbiAqIEBwYXJhbSB7b2JqZWN0fSBjZCA6IGNhbGNkYXRhIHRyYWNlXG4gKiBAcGFyYW0ge3N0cmluZ30gY2RBdHRyIDogY2FsY2RhdGEga2V5XG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZm5dIDogb3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwbHkgdG8gZWFjaCBhcnJheSBpdGVtXG4gKi9cbmxpYi5maWxsQXJyYXkgPSBmdW5jdGlvbih0cmFjZUF0dHIsIGNkLCBjZEF0dHIsIGZuKSB7XG4gICAgZm4gPSBmbiB8fCBsaWIuaWRlbnRpdHk7XG5cbiAgICBpZihsaWIuaXNBcnJheU9yVHlwZWRBcnJheSh0cmFjZUF0dHIpKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV1bY2RBdHRyXSA9IGZuKHRyYWNlQXR0cltpXSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKiogSGFuZGxlciBmb3IgdHJhY2Utd2lkZSB2cyBwZXItcG9pbnQgb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZSA6IChmdWxsKSB0cmFjZSBvYmplY3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBwdE51bWJlciA6IGluZGV4IG9mIHRoZSBwb2ludCBpbiBxdWVzdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IGFzdHIgOiBhdHRyaWJ1dGUgc3RyaW5nXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZm5dIDogb3B0aW9uYWwgZnVuY3Rpb24gdG8gYXBwbHkgdG8gZWFjaCBhcnJheSBpdGVtXG4gKlxuICogQHJldHVybiB7YW55fVxuICovXG5saWIuY2FzdE9wdGlvbiA9IGZ1bmN0aW9uKHRyYWNlLCBwdE51bWJlciwgYXN0ciwgZm4pIHtcbiAgICBmbiA9IGZuIHx8IGxpYi5pZGVudGl0eTtcblxuICAgIHZhciB2YWwgPSBsaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGFzdHIpLmdldCgpO1xuXG4gICAgaWYobGliLmlzQXJyYXlPclR5cGVkQXJyYXkodmFsKSkge1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHB0TnVtYmVyKSAmJiBsaWIuaXNBcnJheU9yVHlwZWRBcnJheSh2YWxbcHROdW1iZXJbMF1dKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZuKHZhbFtwdE51bWJlclswXV1bcHROdW1iZXJbMV1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmbih2YWxbcHROdW1iZXJdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfVxufTtcblxuLyoqIEV4dHJhY3Qgb3B0aW9uIGZyb20gY2FsY2RhdGEgaXRlbSwgY29ycmVjdGx5IGZhbGxpbmcgYmFjayB0b1xuICogIHRyYWNlIHZhbHVlIGlmIG5vdCBmb3VuZC5cbiAqXG4gKiAgQHBhcmFtIHtvYmplY3R9IGNhbGNQdCA6IGNhbGNkYXRhW2ldW2pdIGl0ZW1cbiAqICBAcGFyYW0ge29iamVjdH0gdHJhY2UgOiAoZnVsbCkgdHJhY2Ugb2JqZWN0XG4gKiAgQHBhcmFtIHtzdHJpbmd9IGNhbGNLZXkgOiBjYWxjZGF0YSBrZXlcbiAqICBAcGFyYW0ge3N0cmluZ30gdHJhY2VLZXkgOiBha2EgdHJhY2UgYXR0cmlidXRlIHN0cmluZ1xuICogIEByZXR1cm4ge2FueX1cbiAqL1xubGliLmV4dHJhY3RPcHRpb24gPSBmdW5jdGlvbihjYWxjUHQsIHRyYWNlLCBjYWxjS2V5LCB0cmFjZUtleSkge1xuICAgIGlmKGNhbGNLZXkgaW4gY2FsY1B0KSByZXR1cm4gY2FsY1B0W2NhbGNLZXldO1xuXG4gICAgLy8gZmFsbGJhY2sgdG8gdHJhY2UgdmFsdWUsXG4gICAgLy8gICBtdXN0IGNoZWNrIGlmIHZhbHVlIGlzbid0IGl0c2VsZiBhbiBhcnJheVxuICAgIC8vICAgd2hpY2ggbWVhbnMgdGhlIHRyYWNlIGF0dHJpYnV0ZSBoYXMgYSBjb3JyZXNwb25kaW5nXG4gICAgLy8gICBjYWxjZGF0YSBrZXksIGJ1dCBpdHMgdmFsdWUgaXMgZmFsc3lcbiAgICB2YXIgdHJhY2VWYWwgPSBsaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIHRyYWNlS2V5KS5nZXQoKTtcbiAgICBpZighQXJyYXkuaXNBcnJheSh0cmFjZVZhbCkpIHJldHVybiB0cmFjZVZhbDtcbn07XG5cbmZ1bmN0aW9uIG1ha2VQdEluZGV4MlB0TnVtYmVyKGluZGV4VG9Qb2ludHMpIHtcbiAgICB2YXIgcHRJbmRleDJwdE51bWJlciA9IHt9O1xuICAgIGZvcih2YXIgayBpbiBpbmRleFRvUG9pbnRzKSB7XG4gICAgICAgIHZhciBwdHMgPSBpbmRleFRvUG9pbnRzW2tdO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgcHRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBwdEluZGV4MnB0TnVtYmVyW3B0c1tqXV0gPSAraztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcHRJbmRleDJwdE51bWJlcjtcbn1cblxuLyoqIFRhZyBzZWxlY3RlZCBjYWxjZGF0YSBpdGVtc1xuICpcbiAqIE4uQi4gbm90ZSB0aGF0IHBvaW50ICdpbmRleCcgY29ycmVzcG9uZHMgdG8gaW5wdXQgZGF0YSBhcnJheSBpbmRleFxuICogIHdoZXJlYXMgJ251bWJlcicgaXMgaXRzIHBvc3QtdHJhbnNmb3JtIHZlcnNpb24uXG4gKlxuICogQHBhcmFtIHthcnJheX0gY2FsY1RyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VcbiAqICAtIHNlbGVjdGVkcG9pbnRzIHthcnJheX1cbiAqICAtIF9pbmRleFRvUG9pbnRzIHtvYmplY3R9XG4gKiBAcGFyYW0ge3B0TnVtYmVyMmNkSW5kZXh9IHB0TnVtYmVyMmNkSW5kZXggKG9wdGlvbmFsKVxuICogIG9wdGlvbmFsIG1hcCBvYmplY3QgZm9yIHRyYWNlIHR5cGVzIHRoYXQgZG8gbm90IGhhdmUgMS10by0xIHBvaW50IG51bWJlciB0b1xuICogIGNhbGNkYXRhIGl0ZW0gaW5kZXggY29ycmVzcG9uZGVuY2UgKGUuZy4gaGlzdG9ncmFtKVxuICovXG5saWIudGFnU2VsZWN0ZWQgPSBmdW5jdGlvbihjYWxjVHJhY2UsIHRyYWNlLCBwdE51bWJlcjJjZEluZGV4KSB7XG4gICAgdmFyIHNlbGVjdGVkcG9pbnRzID0gdHJhY2Uuc2VsZWN0ZWRwb2ludHM7XG4gICAgdmFyIGluZGV4VG9Qb2ludHMgPSB0cmFjZS5faW5kZXhUb1BvaW50cztcbiAgICB2YXIgcHRJbmRleDJwdE51bWJlcjtcblxuICAgIC8vIG1ha2UgcHQgaW5kZXgtdG8tbnVtYmVyIG1hcCBvYmplY3QsIHdoaWNoIHRha2VzIGNhcmUgb2YgdHJhbnNmb3JtZWQgdHJhY2VzXG4gICAgaWYoaW5kZXhUb1BvaW50cykge1xuICAgICAgICBwdEluZGV4MnB0TnVtYmVyID0gbWFrZVB0SW5kZXgyUHROdW1iZXIoaW5kZXhUb1BvaW50cyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNDZEluZGV4VmFsaWQodikge1xuICAgICAgICByZXR1cm4gdiAhPT0gdW5kZWZpbmVkICYmIHYgPCBjYWxjVHJhY2UubGVuZ3RoO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzZWxlY3RlZHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcHRJbmRleCA9IHNlbGVjdGVkcG9pbnRzW2ldO1xuXG4gICAgICAgIGlmKGxpYi5pc0luZGV4KHB0SW5kZXgpKSB7XG4gICAgICAgICAgICB2YXIgcHROdW1iZXIgPSBwdEluZGV4MnB0TnVtYmVyID8gcHRJbmRleDJwdE51bWJlcltwdEluZGV4XSA6IHB0SW5kZXg7XG4gICAgICAgICAgICB2YXIgY2RJbmRleCA9IHB0TnVtYmVyMmNkSW5kZXggPyBwdE51bWJlcjJjZEluZGV4W3B0TnVtYmVyXSA6IHB0TnVtYmVyO1xuXG4gICAgICAgICAgICBpZihpc0NkSW5kZXhWYWxpZChjZEluZGV4KSkge1xuICAgICAgICAgICAgICAgIGNhbGNUcmFjZVtjZEluZGV4XS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5saWIuc2VsSW5kaWNlczJzZWxQb2ludHMgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBzZWxlY3RlZHBvaW50cyA9IHRyYWNlLnNlbGVjdGVkcG9pbnRzO1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0gdHJhY2UuX2luZGV4VG9Qb2ludHM7XG5cbiAgICBpZihpbmRleFRvUG9pbnRzKSB7XG4gICAgICAgIHZhciBwdEluZGV4MnB0TnVtYmVyID0gbWFrZVB0SW5kZXgyUHROdW1iZXIoaW5kZXhUb1BvaW50cyk7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VsZWN0ZWRwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwdEluZGV4ID0gc2VsZWN0ZWRwb2ludHNbaV07XG4gICAgICAgICAgICBpZihsaWIuaXNJbmRleChwdEluZGV4KSkge1xuICAgICAgICAgICAgICAgIHZhciBwdE51bWJlciA9IHB0SW5kZXgycHROdW1iZXJbcHRJbmRleF07XG4gICAgICAgICAgICAgICAgaWYobGliLmlzSW5kZXgocHROdW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC5wdXNoKHB0TnVtYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBzZWxlY3RlZHBvaW50cztcbiAgICB9XG59O1xuXG4vKiogUmV0dXJucyB0YXJnZXQgYXMgc2V0IGJ5ICd0YXJnZXQnIHRyYW5zZm9ybSBhdHRyaWJ1dGVcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2UgOiBmdWxsIHRyYWNlIG9iamVjdFxuICogQHBhcmFtIHtvYmplY3R9IHRyYW5zZm9ybU9wdHMgOiB0cmFuc2Zvcm0gb3B0aW9uIG9iamVjdFxuICogIC0gdGFyZ2V0IChzdHJpbmd9IDpcbiAqICAgICAgZWl0aGVyIGFuIGF0dHJpYnV0ZSBzdHJpbmcgcmVmZXJlbmNpbmcgYW4gYXJyYXkgaW4gdGhlIHRyYWNlIG9iamVjdCwgb3JcbiAqICAgICAgYSBzZXQgYXJyYXkuXG4gKlxuICogQHJldHVybiB7YXJyYXkgb3IgZmFsc2V9IDogdGhlIHRhcmdldCBhcnJheSAoTk9UIGEgY29weSEhKSBvciBmYWxzZSBpZiBpbnZhbGlkXG4gKi9cbmxpYi5nZXRUYXJnZXRBcnJheSA9IGZ1bmN0aW9uKHRyYWNlLCB0cmFuc2Zvcm1PcHRzKSB7XG4gICAgdmFyIHRhcmdldCA9IHRyYW5zZm9ybU9wdHMudGFyZ2V0O1xuXG4gICAgaWYodHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycgJiYgdGFyZ2V0KSB7XG4gICAgICAgIHZhciBhcnJheSA9IGxpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgdGFyZ2V0KS5nZXQoKTtcbiAgICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYXJyYXkpID8gYXJyYXkgOiBmYWxzZTtcbiAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheSh0YXJnZXQpKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBtb2RpZmllZCB2ZXJzaW9uIG9mIGpRdWVyeSdzIGV4dGVuZCB0byBzdHJpcCBvdXQgcHJpdmF0ZSBvYmpzIGFuZCBmdW5jdGlvbnMsXG4gKiBhbmQgY3V0IGFycmF5cyBkb3duIHRvIGZpcnN0IDxhcnJheWxlbj4gb3IgMSBlbGVtZW50c1xuICogYmVjYXVzZSBleHRlbmQtbGlrZSBhbGdvcml0aG1zIGFyZSBoZWxsYSBzbG93XG4gKiBvYmoyIGlzIGFzc3VtZWQgdG8gYWxyZWFkeSBiZSBjbGVhbiBvZiB0aGVzZSB0aGluZ3MgKGluY2x1ZGluZyBubyBhcnJheXMpXG4gKi9cbmxpYi5taW5FeHRlbmQgPSBmdW5jdGlvbihvYmoxLCBvYmoyKSB7XG4gICAgdmFyIG9iak91dCA9IHt9O1xuICAgIGlmKHR5cGVvZiBvYmoyICE9PSAnb2JqZWN0Jykgb2JqMiA9IHt9O1xuICAgIHZhciBhcnJheUxlbiA9IDMsXG4gICAgICAgIGtleXMgPSBPYmplY3Qua2V5cyhvYmoxKSxcbiAgICAgICAgaSxcbiAgICAgICAgayxcbiAgICAgICAgdjtcbiAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGsgPSBrZXlzW2ldO1xuICAgICAgICB2ID0gb2JqMVtrXTtcbiAgICAgICAgaWYoay5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJykgY29udGludWU7XG4gICAgICAgIGVsc2UgaWYoayA9PT0gJ21vZHVsZScpIG9iak91dFtrXSA9IHY7XG4gICAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheSh2KSkgb2JqT3V0W2tdID0gdi5zbGljZSgwLCBhcnJheUxlbik7XG4gICAgICAgIGVsc2UgaWYodiAmJiAodHlwZW9mIHYgPT09ICdvYmplY3QnKSkgb2JqT3V0W2tdID0gbGliLm1pbkV4dGVuZChvYmoxW2tdLCBvYmoyW2tdKTtcbiAgICAgICAgZWxzZSBvYmpPdXRba10gPSB2O1xuICAgIH1cblxuICAgIGtleXMgPSBPYmplY3Qua2V5cyhvYmoyKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGsgPSBrZXlzW2ldO1xuICAgICAgICB2ID0gb2JqMltrXTtcbiAgICAgICAgaWYodHlwZW9mIHYgIT09ICdvYmplY3QnIHx8ICEoayBpbiBvYmpPdXQpIHx8IHR5cGVvZiBvYmpPdXRba10gIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBvYmpPdXRba10gPSB2O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iak91dDtcbn07XG5cbmxpYi50aXRsZUNhc2UgPSBmdW5jdGlvbihzKSB7XG4gICAgcmV0dXJuIHMuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzLnN1YnN0cigxKTtcbn07XG5cbmxpYi5jb250YWluc0FueSA9IGZ1bmN0aW9uKHMsIGZyYWdtZW50cykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmcmFnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYocy5pbmRleE9mKGZyYWdtZW50c1tpXSkgIT09IC0xKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxubGliLmlzUGxvdERpdiA9IGZ1bmN0aW9uKGVsKSB7XG4gICAgdmFyIGVsMyA9IGQzLnNlbGVjdChlbCk7XG4gICAgcmV0dXJuIGVsMy5ub2RlKCkgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCAmJlxuICAgICAgICBlbDMuc2l6ZSgpICYmXG4gICAgICAgIGVsMy5jbGFzc2VkKCdqcy1wbG90bHktcGxvdCcpO1xufTtcblxubGliLnJlbW92ZUVsZW1lbnQgPSBmdW5jdGlvbihlbCkge1xuICAgIHZhciBlbFBhcmVudCA9IGVsICYmIGVsLnBhcmVudE5vZGU7XG4gICAgaWYoZWxQYXJlbnQpIGVsUGFyZW50LnJlbW92ZUNoaWxkKGVsKTtcbn07XG5cbi8qKlxuICogZm9yIGR5bmFtaWNhbGx5IGFkZGluZyBzdHlsZSBydWxlc1xuICogbWFrZXMgb25lIHN0eWxlc2hlZXQgdGhhdCBjb250YWlucyBhbGwgcnVsZXMgYWRkZWRcbiAqIGJ5IGFsbCBjYWxscyB0byB0aGlzIGZ1bmN0aW9uXG4gKi9cbmxpYi5hZGRTdHlsZVJ1bGUgPSBmdW5jdGlvbihzZWxlY3Rvciwgc3R5bGVTdHJpbmcpIHtcbiAgICBsaWIuYWRkUmVsYXRlZFN0eWxlUnVsZSgnZ2xvYmFsJywgc2VsZWN0b3IsIHN0eWxlU3RyaW5nKTtcbn07XG5cbi8qKlxuICogZm9yIGR5bmFtaWNhbGx5IGFkZGluZyBzdHlsZSBydWxlc1xuICogdG8gYSBzdHlsZXNoZWV0IHVuaXF1ZWx5IGlkZW50aWZpZWQgYnkgYSB1aWRcbiAqL1xubGliLmFkZFJlbGF0ZWRTdHlsZVJ1bGUgPSBmdW5jdGlvbih1aWQsIHNlbGVjdG9yLCBzdHlsZVN0cmluZykge1xuICAgIHZhciBpZCA9ICdwbG90bHkuanMtc3R5bGUtJyArIHVpZCxcbiAgICAgICAgc3R5bGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7XG4gICAgaWYoIXN0eWxlKSB7XG4gICAgICAgIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICAgICAgc3R5bGUuc2V0QXR0cmlidXRlKCdpZCcsIGlkKTtcbiAgICAgICAgLy8gV2ViS2l0IGhhY2sgOihcbiAgICAgICAgc3R5bGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpKTtcbiAgICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7XG4gICAgfVxuICAgIHZhciBzdHlsZVNoZWV0ID0gc3R5bGUuc2hlZXQ7XG5cbiAgICBpZihzdHlsZVNoZWV0Lmluc2VydFJ1bGUpIHtcbiAgICAgICAgc3R5bGVTaGVldC5pbnNlcnRSdWxlKHNlbGVjdG9yICsgJ3snICsgc3R5bGVTdHJpbmcgKyAnfScsIDApO1xuICAgIH1cbiAgICBlbHNlIGlmKHN0eWxlU2hlZXQuYWRkUnVsZSkge1xuICAgICAgICBzdHlsZVNoZWV0LmFkZFJ1bGUoc2VsZWN0b3IsIHN0eWxlU3RyaW5nLCAwKTtcbiAgICB9XG4gICAgZWxzZSBsaWIud2FybignYWRkU3R5bGVSdWxlIGZhaWxlZCcpO1xufTtcblxuLyoqXG4gKiB0byByZW1vdmUgZnJvbSB0aGUgcGFnZSBhIHN0eWxlc2hlZXQgaWRlbnRpZmllZCBieSBhIGdpdmVuIHVpZFxuICovXG5saWIuZGVsZXRlUmVsYXRlZFN0eWxlUnVsZSA9IGZ1bmN0aW9uKHVpZCkge1xuICAgIHZhciBpZCA9ICdwbG90bHkuanMtc3R5bGUtJyArIHVpZCxcbiAgICAgICAgc3R5bGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7XG4gICAgaWYoc3R5bGUpIGxpYi5yZW1vdmVFbGVtZW50KHN0eWxlKTtcbn07XG5cbmxpYi5pc0lFID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cubmF2aWdhdG9yLm1zU2F2ZUJsb2IgIT09ICd1bmRlZmluZWQnO1xufTtcblxuLyoqXG4gKiBEdWNrIHR5cGluZyB0byByZWNvZ25pemUgYSBkMyBzZWxlY3Rpb24sIG1vc3RseSBmb3IgSUU5J3MgYmVuZWZpdFxuICogYmVjYXVzZSBpdCBkb2Vzbid0IGhhbmRsZSBpbnN0YW5jZW9mIGxpa2UgbW9kZXJuIGJyb3dzZXJzXG4gKi9cbmxpYi5pc0QzU2VsZWN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiAmJiAodHlwZW9mIG9iai5jbGFzc2VkID09PSAnZnVuY3Rpb24nKTtcbn07XG5cbi8qKlxuICogQXBwZW5kIGVsZW1lbnQgdG8gRE9NIG9ubHkgaWYgbm90IHByZXNlbnQuXG4gKlxuICogQHBhcmFtIHtkMyBzZWxlY3Rpb259IHBhcmVudCA6IHBhcmVudCBzZWxlY3Rpb24gb2YgdGhlIGVsZW1lbnQgaW4gcXVlc3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBub2RlVHlwZSA6IG5vZGUgdHlwZSBvZiBlbGVtZW50IHRvIGFwcGVuZFxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZSAob3B0aW9uYWwpIDogY2xhc3MgbmFtZSBvZiBlbGVtZW50IGluIHF1ZXN0aW9uXG4gKiBAcGFyYW0ge2ZufSBlbnRlckZuIChvcHRpb25hbCkgOiBvcHRpb25hbCBmbiBhcHBsaWVkIHRvIGVudGVyaW5nIGVsZW1lbnRzIG9ubHlcbiAqIEByZXR1cm4ge2QzIHNlbGVjdGlvbn0gc2VsZWN0aW9uIG9mIG5ldyBsYXllclxuICpcbiAqIFByZXZpb3VzbHksIHdlIHdlcmUgdXNpbmcgdGhlIGZvbGxvd2luZyBwYXR0ZXJuOlxuICpcbiAqIGBgYFxuICogdmFyIHNlbCA9IHBhcmVudC5zZWxlY3RBbGwoJy4nICsgY2xhc3NOYW1lKVxuICogICAgIC5kYXRhKFswXSk7XG4gKlxuICogc2VsLmVudGVyKCkuYXBwZW5kKG5vZGVUeXBlKVxuICogICAgIC5jbGFzc2VkKGNsYXNzTmFtZSwgdHJ1ZSk7XG4gKlxuICogcmV0dXJuIHNlbDtcbiAqIGBgYFxuICpcbiAqIGluIG51bWVyb3VzIHBsYWNlcyBpbiBvdXIgY29kZWJhc2UgdG8gYWNoaWV2ZSB0aGUgc2FtZSBiZWhhdmlvci5cbiAqXG4gKiBUaGUgbG9naWMgYmVsb3cgcGVyZm9ybXMgbXVjaCBiZXR0ZXIsIG1vc3RseSBhcyB3ZSBhcmUgdXNpbmdcbiAqIGAuc2VsZWN0YCBpbnN0ZWFkIGAuc2VsZWN0QWxsYCB0aGF0IGlzIGBxdWVyeVNlbGVjdG9yYCBpbnN0ZWFkIG9mXG4gKiBgcXVlcnlTZWxlY3RvckFsbGAuXG4gKlxuICovXG5saWIuZW5zdXJlU2luZ2xlID0gZnVuY3Rpb24ocGFyZW50LCBub2RlVHlwZSwgY2xhc3NOYW1lLCBlbnRlckZuKSB7XG4gICAgdmFyIHNlbCA9IHBhcmVudC5zZWxlY3Qobm9kZVR5cGUgKyAoY2xhc3NOYW1lID8gJy4nICsgY2xhc3NOYW1lIDogJycpKTtcbiAgICBpZihzZWwuc2l6ZSgpKSByZXR1cm4gc2VsO1xuXG4gICAgdmFyIGxheWVyID0gcGFyZW50LmFwcGVuZChub2RlVHlwZSk7XG4gICAgaWYoY2xhc3NOYW1lKSBsYXllci5jbGFzc2VkKGNsYXNzTmFtZSwgdHJ1ZSk7XG4gICAgaWYoZW50ZXJGbikgbGF5ZXIuY2FsbChlbnRlckZuKTtcblxuICAgIHJldHVybiBsYXllcjtcbn07XG5cbi8qKlxuICogU2FtZSBhcyBMaWIuZW5zdXJlU2luZ2xlLCBidXQgdXNpbmcgaWQgYXMgc2VsZWN0b3IuXG4gKiBUaGlzIHZlcnNpb24gaXMgbW9zdGx5IHVzZWQgZm9yIGNsaXBQYXRoIG5vZGVzLlxuICpcbiAqIEBwYXJhbSB7ZDMgc2VsZWN0aW9ufSBwYXJlbnQgOiBwYXJlbnQgc2VsZWN0aW9uIG9mIHRoZSBlbGVtZW50IGluIHF1ZXN0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gbm9kZVR5cGUgOiBub2RlIHR5cGUgb2YgZWxlbWVudCB0byBhcHBlbmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCA6IGlkIG9mIGVsZW1lbnQgaW4gcXVlc3Rpb25cbiAqIEBwYXJhbSB7Zm59IGVudGVyRm4gKG9wdGlvbmFsKSA6IG9wdGlvbmFsIGZuIGFwcGxpZWQgdG8gZW50ZXJpbmcgZWxlbWVudHMgb25seVxuICogQHJldHVybiB7ZDMgc2VsZWN0aW9ufSBzZWxlY3Rpb24gb2YgbmV3IGxheWVyXG4gKi9cbmxpYi5lbnN1cmVTaW5nbGVCeUlkID0gZnVuY3Rpb24ocGFyZW50LCBub2RlVHlwZSwgaWQsIGVudGVyRm4pIHtcbiAgICB2YXIgc2VsID0gcGFyZW50LnNlbGVjdChub2RlVHlwZSArICcjJyArIGlkKTtcbiAgICBpZihzZWwuc2l6ZSgpKSByZXR1cm4gc2VsO1xuXG4gICAgdmFyIGxheWVyID0gcGFyZW50LmFwcGVuZChub2RlVHlwZSkuYXR0cignaWQnLCBpZCk7XG4gICAgaWYoZW50ZXJGbikgbGF5ZXIuY2FsbChlbnRlckZuKTtcblxuICAgIHJldHVybiBsYXllcjtcbn07XG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgcGF0aCB0byBhbiBvYmplY3QuXG4gKlxuICogV2hlbiBnaXZlbiBhIHN0cmluZyBjb250YWluaW5nIGFuIGFycmF5IGVsZW1lbnQsIGl0IHdpbGwgY3JlYXRlIGEgYG51bGxgXG4gKiBmaWxsZWQgYXJyYXkgb2YgdGhlIGdpdmVuIHNpemUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGxpYi5vYmplY3RGcm9tUGF0aCgnbmVzdGVkLnRlc3RbMl0ucGF0aCcsICd2YWx1ZScpO1xuICogLy8gcmV0dXJucyB7IG5lc3RlZDogeyB0ZXN0OiBbbnVsbCwgbnVsbCwgeyBwYXRoOiAndmFsdWUnIH1dfVxuICpcbiAqIEBwYXJhbSAgIHtzdHJpbmd9ICAgIHBhdGggdG8gbmVzdGVkIHZhbHVlXG4gKiBAcGFyYW0gICB7Kn0gICAgICAgICBhbnkgdmFsdWUgdG8gYmUgc2V0XG4gKlxuICogQHJldHVybiB7T2JqZWN0fSB0aGUgY29uc3RydWN0ZWQgb2JqZWN0IHdpdGggYSBmdWxsIG5lc3RlZCBwYXRoXG4gKi9cbmxpYi5vYmplY3RGcm9tUGF0aCA9IGZ1bmN0aW9uKHBhdGgsIHZhbHVlKSB7XG4gICAgdmFyIGtleXMgPSBwYXRoLnNwbGl0KCcuJyksXG4gICAgICAgIHRtcE9iaixcbiAgICAgICAgb2JqID0gdG1wT2JqID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgdmFyIGVsID0gbnVsbDtcblxuICAgICAgICB2YXIgcGFydHMgPSBrZXlzW2ldLm1hdGNoKC8oLiopXFxbKFswLTldKylcXF0vKTtcblxuICAgICAgICBpZihwYXJ0cykge1xuICAgICAgICAgICAga2V5ID0gcGFydHNbMV07XG4gICAgICAgICAgICBlbCA9IHBhcnRzWzJdO1xuXG4gICAgICAgICAgICB0bXBPYmogPSB0bXBPYmpba2V5XSA9IFtdO1xuXG4gICAgICAgICAgICBpZihpID09PSBrZXlzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICB0bXBPYmpbZWxdID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRtcE9ialtlbF0gPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdG1wT2JqID0gdG1wT2JqW2VsXTtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgaWYoaSA9PT0ga2V5cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgdG1wT2JqW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG1wT2JqW2tleV0gPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdG1wT2JqID0gdG1wT2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb2JqO1xufTtcblxuLyoqXG4gKiBJdGVyYXRlIHRocm91Z2ggYW4gb2JqZWN0IGluLXBsYWNlLCBjb252ZXJ0aW5nIGRvdHRlZCBwcm9wZXJ0aWVzIHRvIG9iamVjdHMuXG4gKlxuICogRXhhbXBsZXM6XG4gKlxuICogICBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoeyduZXN0ZWQudGVzdC5wYXRoJzogJ3ZhbHVlJ30pO1xuICogICAgID0+IHsgbmVzdGVkOiB7IHRlc3Q6IHtwYXRoOiAndmFsdWUnfX19XG4gKlxuICogSXQgYWxzbyBoYW5kbGVzIGFycmF5IG5vdGF0aW9uLCBlLmcuOlxuICpcbiAqICAgbGliLmV4cGFuZE9iamVjdFBhdGhzKHsnZm9vWzFdLmJhcic6ICd2YWx1ZSd9KTtcbiAqICAgICA9PiB7IGZvbzogW251bGwsIHtiYXI6IHZhbHVlfV0gfVxuICpcbiAqIEl0IGhhbmRsZXMgbWVyZ2VzIHRoZSByZXN1bHRzIHdoZW4gdHdvIHByb3BlcnRpZXMgYXJlIHNwZWNpZmllZCBpbiBwYXJhbGxlbDpcbiAqXG4gKiAgIGxpYi5leHBhbmRPYmplY3RQYXRocyh7J2Zvb1sxXS5iYXInOiAxMCwgJ2Zvb1swXS5iYXInOiAyMH0pO1xuICogICAgID0+IHsgZm9vOiBbe2JhcjogMTB9LCB7YmFyOiAyMH1dIH1cbiAqXG4gKiBJdCBkb2VzIE5PVCwgaG93ZXZlciwgbWVyZ2UgbXVsaXRwbGUgbXV0bGlwbHktbmVzdGVkIGFycmF5czo6XG4gKlxuICogICBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoeydtYXJrZXJbMV0ucmFuZ2VbMV0nOiA1LCAnbWFya2VyWzFdLnJhbmdlWzBdJzogNH0pXG4gKiAgICAgPT4geyBtYXJrZXI6IFtudWxsLCB7cmFuZ2U6IDR9XSB9XG4gKi9cblxuLy8gU3RvcmUgdGhpcyB0byBhdm9pZCByZWNvbXBpbGluZyByZWdleCBvbiAqZXZlcnkqIHByb3Agc2luY2UgdGhpcyBtYXkgaGFwcGVuIG1hbnlcbi8vIG1hbnkgdGltZXMgZm9yIGFuaW1hdGlvbnMuIENvdWxkIG1heWJlIGJlIGluc2lkZSB0aGUgZnVuY3Rpb24uIE5vdCBzdXJlIGFib3V0XG4vLyBzY29waW5nIHZzLiByZWNvbXBpbGF0aW9uIHRyYWRlb2ZmLCBidXQgYXQgbGVhc3QgaXQncyBub3QganVzdCBpbmxpbmluZyBpdCBpbnRvXG4vLyB0aGUgaW5uZXIgbG9vcC5cbnZhciBkb3R0ZWRQcm9wZXJ0eVJlZ2V4ID0gL14oW15cXFtcXC5dKylcXC4oLispPy87XG52YXIgaW5kZXhlZFByb3BlcnR5UmVnZXggPSAvXihbXlxcLl0rKVxcWyhbMC05XSspXFxdKFxcLik/KC4rKT8vO1xuXG5saWIuZXhwYW5kT2JqZWN0UGF0aHMgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIG1hdGNoLCBrZXksIHByb3AsIGRhdHVtLCBpZHgsIGRlc3QsIHRyYWlsaW5nUGF0aDtcbiAgICBpZih0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgZm9yKGtleSBpbiBkYXRhKSB7XG4gICAgICAgICAgICBpZihkYXRhLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpZigobWF0Y2ggPSBrZXkubWF0Y2goZG90dGVkUHJvcGVydHlSZWdleCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtID0gZGF0YVtrZXldO1xuICAgICAgICAgICAgICAgICAgICBwcm9wID0gbWF0Y2hbMV07XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFba2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBkYXRhW3Byb3BdID0gbGliLmV4dGVuZERlZXBOb0FycmF5cyhkYXRhW3Byb3BdIHx8IHt9LCBsaWIub2JqZWN0RnJvbVBhdGgoa2V5LCBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoZGF0dW0pKVtwcm9wXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKChtYXRjaCA9IGtleS5tYXRjaChpbmRleGVkUHJvcGVydHlSZWdleCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtID0gZGF0YVtrZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIHByb3AgPSBtYXRjaFsxXTtcbiAgICAgICAgICAgICAgICAgICAgaWR4ID0gcGFyc2VJbnQobWF0Y2hbMl0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhW2tleV07XG5cbiAgICAgICAgICAgICAgICAgICAgZGF0YVtwcm9wXSA9IGRhdGFbcHJvcF0gfHwgW107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYobWF0Y2hbM10gPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgY2FzZSB3aGVyZSB0aGVlcmUgYXJlIHN1YnNlcXVlbnQgcHJvcGVydGllcyBpbnRvIHdoaWNoXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBtdXN0IHJlY3Vyc2UsIGUuZy4gdHJhbnNmb3Jtc1swXS52YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhaWxpbmdQYXRoID0gbWF0Y2hbNF07XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0ID0gZGF0YVtwcm9wXVtpZHhdID0gZGF0YVtwcm9wXVtpZHhdIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOQjogRXh0ZW5kIGRlZXAgbm8gYXJyYXlzIHByZXZlbnRzIHRoaXMgZnJvbSB3b3JraW5nIG9uIG11bHRpcGxlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXN0ZWQgcHJvcGVydGllcyBpbiB0aGUgc2FtZSBvYmplY3QsIGUuZy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGZvb1swXS5iYXJbMV0ucmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgZm9vWzBdLmJhclswXS5yYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgdGhlIGV4dGVuZERlZXBOb0FycmF5cyB3aWxsIG92ZXJ3cml0ZSBvbmUgYXJyYXkgd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG90aGVyLCBzbyB0aGF0IGJvdGggcHJvcGVydGllcyAqd2lsbCBub3QqIGJlIHByZXNlbnQgaW4gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZXN1bHQuIEZpeGluZyB0aGlzIHdvdWxkIHJlcXVpcmUgYSBtb3JlIGludGVsbGlnZW50IHRyYWNraW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvZiBjaGFuZ2VzIGFuZCBtZXJnaW5nIHRoYW4gZXh0ZW5kRGVlcE5vQXJyYXlzIGN1cnJlbnRseSBhY2NvbXBsaXNoZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBsaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKGRlc3QsIGxpYi5vYmplY3RGcm9tUGF0aCh0cmFpbGluZ1BhdGgsIGxpYi5leHBhbmRPYmplY3RQYXRocyhkYXR1bSkpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNhc2Ugd2hlcmUgdGhpcyBwcm9wZXJ0eSBpcyB0aGUgZW5kIG9mIHRoZSBsaW5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZS5nLiB4YXhpcy5yYW5nZVswXVxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtwcm9wXVtpZHhdID0gbGliLmV4cGFuZE9iamVjdFBhdGhzKGRhdHVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFba2V5XSA9IGxpYi5leHBhbmRPYmplY3RQYXRocyhkYXRhW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkYXRhO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyB2YWx1ZSB0byBzdHJpbmcgc2VwYXJhdGVkIGJ5IHRoZSBwcm92aWRlZCBzZXBhcmF0b3JzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBsaWIubnVtU2VwYXJhdGUoMjAxNiwgJy4sJyk7XG4gKiAvLyByZXR1cm5zICcyMDE2J1xuICpcbiAqIEBleGFtcGxlXG4gKiBsaWIubnVtU2VwYXJhdGUoMzAwMCwgJy4sJywgdHJ1ZSk7XG4gKiAvLyByZXR1cm5zICczLDAwMCdcbiAqXG4gKiBAZXhhbXBsZVxuICogbGliLm51bVNlcGFyYXRlKDEyMzQuNTYsICd8LCcpXG4gKiAvLyByZXR1cm5zICcxLDIzNHw1NidcbiAqXG4gKiBAcGFyYW0gICB7c3RyaW5nfG51bWJlcn0gdmFsdWUgICAgICAgdGhlIHZhbHVlIHRvIGJlIGNvbnZlcnRlZFxuICogQHBhcmFtICAge3N0cmluZ30gICAgc2VwYXJhdG9ycyAgc3RyaW5nIG9mIGRlY2ltYWwsIHRoZW4gdGhvdXNhbmRzIHNlcGFyYXRvcnNcbiAqIEBwYXJhbSAgIHtib29sZWFufSAgICBzZXBhcmF0ZXRob3VzYW5kcyAgYm9vbGVhbiwgNC1kaWdpdCBpbnRlZ2VycyBhcmUgc2VwYXJhdGVkIGlmIHRydWVcbiAqXG4gKiBAcmV0dXJuICB7c3RyaW5nfSAgICB0aGUgdmFsdWUgdGhhdCBoYXMgYmVlbiBzZXBhcmF0ZWRcbiAqL1xubGliLm51bVNlcGFyYXRlID0gZnVuY3Rpb24odmFsdWUsIHNlcGFyYXRvcnMsIHNlcGFyYXRldGhvdXNhbmRzKSB7XG4gICAgaWYoIXNlcGFyYXRldGhvdXNhbmRzKSBzZXBhcmF0ZXRob3VzYW5kcyA9IGZhbHNlO1xuXG4gICAgaWYodHlwZW9mIHNlcGFyYXRvcnMgIT09ICdzdHJpbmcnIHx8IHNlcGFyYXRvcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU2VwYXJhdG9yIHN0cmluZyByZXF1aXJlZCBmb3IgZm9ybWF0dGluZyEnKTtcbiAgICB9XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHZhbHVlID0gU3RyaW5nKHZhbHVlKTtcbiAgICB9XG5cbiAgICB2YXIgdGhvdXNhbmRzUmUgPSAvKFxcZCspKFxcZHszfSkvLFxuICAgICAgICBkZWNpbWFsU2VwID0gc2VwYXJhdG9ycy5jaGFyQXQoMCksXG4gICAgICAgIHRob3VTZXAgPSBzZXBhcmF0b3JzLmNoYXJBdCgxKTtcblxuICAgIHZhciB4ID0gdmFsdWUuc3BsaXQoJy4nKSxcbiAgICAgICAgeDEgPSB4WzBdLFxuICAgICAgICB4MiA9IHgubGVuZ3RoID4gMSA/IGRlY2ltYWxTZXAgKyB4WzFdIDogJyc7XG5cbiAgICAvLyBZZWFycyBhcmUgaWdub3JlZCBmb3IgdGhvdXNhbmRzIHNlcGFyYXRvcnNcbiAgICBpZih0aG91U2VwICYmICh4Lmxlbmd0aCA+IDEgfHwgeDEubGVuZ3RoID4gNCB8fCBzZXBhcmF0ZXRob3VzYW5kcykpIHtcbiAgICAgICAgd2hpbGUodGhvdXNhbmRzUmUudGVzdCh4MSkpIHtcbiAgICAgICAgICAgIHgxID0geDEucmVwbGFjZSh0aG91c2FuZHNSZSwgJyQxJyArIHRob3VTZXAgKyAnJDInKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB4MSArIHgyO1xufTtcblxudmFyIFRFTVBMQVRFX1NUUklOR19SRUdFWCA9IC8leyhbXlxccyV7fV0qKX0vZztcbnZhciBTSU1QTEVfUFJPUEVSVFlfUkVHRVggPSAvXlxcdyokLztcblxuLypcbiAqIFN1YnN0aXR1dGUgdmFsdWVzIGZyb20gYW4gb2JqZWN0IGludG8gYSBzdHJpbmdcbiAqXG4gKiBFeGFtcGxlczpcbiAqICBMaWIudGVtcGxhdGVTdHJpbmcoJ25hbWU6ICV7dHJhY2V9Jywge3RyYWNlOiAnYXNkZid9KSAtLT4gJ25hbWU6IGFzZGYnXG4gKiAgTGliLnRlbXBsYXRlU3RyaW5nKCduYW1lOiAle3RyYWNlWzBdLm5hbWV9Jywge3RyYWNlOiBbe25hbWU6ICdhc2RmJ31dfSkgLS0+ICduYW1lOiBhc2RmJ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSAgaW5wdXQgc3RyaW5nIGNvbnRhaW5pbmcgJXsuLi59IHRlbXBsYXRlIHN0cmluZ3NcbiAqIEBwYXJhbSB7b2JqfSAgICAgZGF0YSBvYmplY3QgY29udGFpbmluZyBzdWJzdGl0dXRpb24gdmFsdWVzXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSB0ZW1wbGF0ZWQgc3RyaW5nXG4gKi9cblxubGliLnRlbXBsYXRlU3RyaW5nID0gZnVuY3Rpb24oc3RyaW5nLCBvYmopIHtcbiAgICAvLyBOb3QgYWxsIHRoYXQgdXNlZnVsLCBidXQgY2FjaGUgbmVzdGVkUHJvcGVydHkgaW5zdGFudGlhdGlvblxuICAgIC8vIGp1c3QgaW4gY2FzZSBpdCBzcGVlZHMgdGhpbmdzIHVwICpzbGlnaHRseSo6XG4gICAgdmFyIGdldHRlckNhY2hlID0ge307XG5cbiAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoVEVNUExBVEVfU1RSSU5HX1JFR0VYLCBmdW5jdGlvbihkdW1teSwga2V5KSB7XG4gICAgICAgIGlmKFNJTVBMRV9QUk9QRVJUWV9SRUdFWC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmpba2V5XSB8fCAnJztcbiAgICAgICAgfVxuICAgICAgICBnZXR0ZXJDYWNoZVtrZXldID0gZ2V0dGVyQ2FjaGVba2V5XSB8fCBsaWIubmVzdGVkUHJvcGVydHkob2JqLCBrZXkpLmdldDtcbiAgICAgICAgcmV0dXJuIGdldHRlckNhY2hlW2tleV0oKSB8fCAnJztcbiAgICB9KTtcbn07XG5cbi8qXG4gKiBhbHBoYW51bWVyaWMgc3RyaW5nIHNvcnQsIHRhaWxvcmVkIGZvciBzdWJwbG90IElEcyBsaWtlIHNjZW5lMiwgc2NlbmUxMCwgeDEweTEzIGV0Y1xuICovXG52YXIgY2hhcjAgPSA0ODtcbnZhciBjaGFyOSA9IDU3O1xubGliLnN1YnBsb3RTb3J0ID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBsID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKSArIDE7XG4gICAgdmFyIG51bUEgPSAwO1xuICAgIHZhciBudW1CID0gMDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIHZhciBjaGFyQSA9IGEuY2hhckNvZGVBdChpKSB8fCAwO1xuICAgICAgICB2YXIgY2hhckIgPSBiLmNoYXJDb2RlQXQoaSkgfHwgMDtcbiAgICAgICAgdmFyIGlzTnVtQSA9IGNoYXJBID49IGNoYXIwICYmIGNoYXJBIDw9IGNoYXI5O1xuICAgICAgICB2YXIgaXNOdW1CID0gY2hhckIgPj0gY2hhcjAgJiYgY2hhckIgPD0gY2hhcjk7XG5cbiAgICAgICAgaWYoaXNOdW1BKSBudW1BID0gMTAgKiBudW1BICsgY2hhckEgLSBjaGFyMDtcbiAgICAgICAgaWYoaXNOdW1CKSBudW1CID0gMTAgKiBudW1CICsgY2hhckIgLSBjaGFyMDtcblxuICAgICAgICBpZighaXNOdW1BIHx8ICFpc051bUIpIHtcbiAgICAgICAgICAgIGlmKG51bUEgIT09IG51bUIpIHJldHVybiBudW1BIC0gbnVtQjtcbiAgICAgICAgICAgIGlmKGNoYXJBICE9PSBjaGFyQikgcmV0dXJuIGNoYXJBIC0gY2hhckI7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bUIgLSBudW1BO1xufTtcblxuLy8gcmVwZWF0YWJsZSBwc2V1ZG9yYW5kb20gZ2VuZXJhdG9yXG52YXIgcmFuZFNlZWQgPSAyMDAwMDAwMDAwO1xuXG5saWIuc2VlZFBzZXVkb1JhbmRvbSA9IGZ1bmN0aW9uKCkge1xuICAgIHJhbmRTZWVkID0gMjAwMDAwMDAwMDtcbn07XG5cbmxpYi5wc2V1ZG9SYW5kb20gPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbGFzdFZhbCA9IHJhbmRTZWVkO1xuICAgIHJhbmRTZWVkID0gKDY5MDY5ICogcmFuZFNlZWQgKyAxKSAlIDQyOTQ5NjcyOTY7XG4gICAgLy8gZG9uJ3QgbGV0IGNvbnNlY3V0aXZlIHZhbHMgYmUgdG9vIGNsb3NlIHRvZ2V0aGVyXG4gICAgLy8gZ2V0cyBhd2F5IGZyb20gcmVhbGx5IHRyeWluZyB0byBiZSByYW5kb20sIGluIGZhdm9yIG9mIGJldHRlciBsb2NhbCB1bmlmb3JtaXR5XG4gICAgaWYoTWF0aC5hYnMocmFuZFNlZWQgLSBsYXN0VmFsKSA8IDQyOTQ5NjcyOSkgcmV0dXJuIGxpYi5wc2V1ZG9SYW5kb20oKTtcbiAgICByZXR1cm4gcmFuZFNlZWQgLyA0Mjk0OTY3Mjk2O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBtb3JlIGluZm86IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTg1MzE2MjQvaXNwbGFpbm9iamVjdC10aGluZ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc1BsYWluT2JqZWN0KG9iaikge1xuXG4gICAgLy8gV2UgbmVlZCB0byBiZSBhIGxpdHRsZSBsZXNzIHN0cmljdCBpbiB0aGUgYGltYWdldGVzdGAgY29udGFpbmVyIGJlY2F1c2VcbiAgICAvLyBvZiBob3cgYXN5bmMgaW1hZ2UgcmVxdWVzdHMgYXJlIGhhbmRsZWQuXG4gICAgLy9cbiAgICAvLyBOLkIuIGlzUGxhaW5PYmplY3QobmV3IENvbnN0cnVjdG9yKCkpIHdpbGwgcmV0dXJuIHRydWUgaW4gYGltYWdldGVzdGBcbiAgICBpZih3aW5kb3cgJiYgd2luZG93LnByb2Nlc3MgJiYgd2luZG93LnByb2Nlc3MudmVyc2lvbnMpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBPYmplY3RdJztcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgT2JqZWN0XScgJiZcbiAgICAgICAgT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iaikgPT09IE9iamVjdC5wcm90b3R5cGVcbiAgICApO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG5lc3RlZFByb3BlcnR5ID0gcmVxdWlyZSgnLi9uZXN0ZWRfcHJvcGVydHknKTtcblxudmFyIFNJTVBMRV9QUk9QRVJUWV9SRUdFWCA9IC9eXFx3KiQvO1xuXG4vLyBiaXRtYXNrIGZvciBkZWNpZGluZyB3aGF0J3MgdXBkYXRlZC4gU29tZXRpbWVzIHRoZSBuYW1lIG5lZWRzIHRvIGJlIHVwZGF0ZWQsXG4vLyBzb21ldGltZXMgdGhlIHZhbHVlIG5lZWRzIHRvIGJlIHVwZGF0ZWQsIGFuZCBzb21ldGltZXMgYm90aCBkby4gVGhpcyBpcyBqdXN0XG4vLyBhIHNpbXBsZSB3YXkgdG8gdHJhY2sgd2hhdCdzIHVwZGF0ZWQgc3VjaCB0aGF0IGl0J3MgYSBzaW1wbGUgT1Igb3BlcmF0aW9uIHRvXG4vLyBhc3NpbWlsYXRlIG5ldyB1cGRhdGVzLlxuLy9cbi8vIFRoZSBvbmx5IGV4Y2VwdGlvbiBpcyB0aGUgVU5TRVQgYml0IHRoYXQgdHJhY2tzIHdoZW4gd2UgbmVlZCB0byBleHBsaWNpdGx5XG4vLyB1bnNldCBhbmQgcmVtb3ZlIHRoZSBwcm9wZXJ0eS4gVGhpcyBjb25jcm4gYXJpc2VzIGJlY2F1c2Ugb2YgdGhlIHNwZWNpYWxcbi8vIHdheSBpbiB3aGljaCBuZXN0ZWRQcm9wZXJ0eSBoYW5kbGVzIG51bGwvdW5kZWZpbmVkLiBXaGVuIHlvdSBzcGVjaWZ5IGBudWxsYCxcbi8vIGl0IHBydW5lcyBhbnkgdW51c2VkIGl0ZW1zIGluIHRoZSB0cmVlLiBJIHJhbiBpbnRvIHNvbWUgaXNzdWVzIHdpdGggaXQgZ2V0dGluZ1xuLy8gbnVsbCB2cyB1bmRlZmluZWQgY29uZnVzZWQsIHNvIFVOU0VUIGlzIGp1c3QgYSBiaXQgdGhhdCBmb3JjZXMgdGhlIHByb3BlcnR5XG4vLyB1cGRhdGUgdG8gc2VuZCBgbnVsbGAsIHJlbW92aW5nIHRoZSBwcm9wZXJ0eSBleHBsaWNpdGx5IHJhdGhlciB0aGFuIHNldHRpbmdcbi8vIGl0IHRvIHVuZGVmaW5lZC5cbnZhciBOT05FID0gMDtcbnZhciBOQU1FID0gMTtcbnZhciBWQUxVRSA9IDI7XG52YXIgQk9USCA9IDM7XG52YXIgVU5TRVQgPSA0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGtleWVkQ29udGFpbmVyKGJhc2VPYmosIHBhdGgsIGtleU5hbWUsIHZhbHVlTmFtZSkge1xuICAgIGtleU5hbWUgPSBrZXlOYW1lIHx8ICduYW1lJztcbiAgICB2YWx1ZU5hbWUgPSB2YWx1ZU5hbWUgfHwgJ3ZhbHVlJztcbiAgICB2YXIgaSwgYXJyLCBiYXNlUHJvcDtcbiAgICB2YXIgY2hhbmdlVHlwZXMgPSB7fTtcblxuICAgIGlmKHBhdGggJiYgcGF0aC5sZW5ndGgpIHtcbiAgICAgICAgYmFzZVByb3AgPSBuZXN0ZWRQcm9wZXJ0eShiYXNlT2JqLCBwYXRoKTtcbiAgICAgICAgYXJyID0gYmFzZVByb3AuZ2V0KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXJyID0gYmFzZU9iajtcbiAgICB9XG5cbiAgICBwYXRoID0gcGF0aCB8fCAnJztcblxuICAgIC8vIENvbnN0cnVjdCBhbiBpbmRleDpcbiAgICB2YXIgaW5kZXhMb29rdXAgPSB7fTtcbiAgICBpZihhcnIpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpbmRleExvb2t1cFthcnJbaV1ba2V5TmFtZV1dID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBpc1NpbXBsZVZhbHVlUHJvcCA9IFNJTVBMRV9QUk9QRVJUWV9SRUdFWC50ZXN0KHZhbHVlTmFtZSk7XG5cbiAgICB2YXIgb2JqID0ge1xuICAgICAgICBzZXQ6IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgY2hhbmdlVHlwZSA9IHZhbHVlID09PSBudWxsID8gVU5TRVQgOiBOT05FO1xuXG4gICAgICAgICAgICAvLyBjcmVhdGUgdGhlIGJhc2UgYXJyYXkgaWYgbmVjZXNzYXJ5XG4gICAgICAgICAgICBpZighYXJyKSB7XG4gICAgICAgICAgICAgICAgaWYoIWJhc2VQcm9wIHx8IGNoYW5nZVR5cGUgPT09IFVOU0VUKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICBhcnIgPSBbXTtcbiAgICAgICAgICAgICAgICBiYXNlUHJvcC5zZXQoYXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGlkeCA9IGluZGV4TG9va3VwW25hbWVdO1xuICAgICAgICAgICAgaWYoaWR4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZihjaGFuZ2VUeXBlID09PSBVTlNFVCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgY2hhbmdlVHlwZSA9IGNoYW5nZVR5cGUgfCBCT1RIO1xuICAgICAgICAgICAgICAgIGlkeCA9IGFyci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaW5kZXhMb29rdXBbbmFtZV0gPSBpZHg7XG4gICAgICAgICAgICB9IGVsc2UgaWYodmFsdWUgIT09IChpc1NpbXBsZVZhbHVlUHJvcCA/IGFycltpZHhdW3ZhbHVlTmFtZV0gOiBuZXN0ZWRQcm9wZXJ0eShhcnJbaWR4XSwgdmFsdWVOYW1lKS5nZXQoKSkpIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2VUeXBlID0gY2hhbmdlVHlwZSB8IFZBTFVFO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBhcnJbaWR4XSA9IGFycltpZHhdIHx8IHt9O1xuICAgICAgICAgICAgbmV3VmFsdWVba2V5TmFtZV0gPSBuYW1lO1xuXG4gICAgICAgICAgICBpZihpc1NpbXBsZVZhbHVlUHJvcCkge1xuICAgICAgICAgICAgICAgIG5ld1ZhbHVlW3ZhbHVlTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmVzdGVkUHJvcGVydHkobmV3VmFsdWUsIHZhbHVlTmFtZSkuc2V0KHZhbHVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgaXQncyBub3QgYW4gdW5zZXQsIGZvcmNlIHRoYXQgYml0IHRvIGJlIHVuc2V0LiBUaGlzIGlzIGFsbCByZWxhdGVkIHRvIHRoZSBmYWN0XG4gICAgICAgICAgICAvLyB0aGF0IHVuZGVmaW5lZCBhbmQgbnVsbCBhcmUgYSBiaXQgc3BlY2lhbGx5IGltcGxlbWVudGVkIGluIG5lc3RlZFByb3BlcnRpZXMuXG4gICAgICAgICAgICBpZih2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNoYW5nZVR5cGUgPSBjaGFuZ2VUeXBlICYgflVOU0VUO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjaGFuZ2VUeXBlc1tpZHhdID0gY2hhbmdlVHlwZXNbaWR4XSB8IGNoYW5nZVR5cGU7XG5cbiAgICAgICAgICAgIHJldHVybiBvYmo7XG4gICAgICAgIH0sXG4gICAgICAgIGdldDogZnVuY3Rpb24obmFtZSkge1xuICAgICAgICAgICAgaWYoIWFycikgcmV0dXJuO1xuXG4gICAgICAgICAgICB2YXIgaWR4ID0gaW5kZXhMb29rdXBbbmFtZV07XG5cbiAgICAgICAgICAgIGlmKGlkeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0gZWxzZSBpZihpc1NpbXBsZVZhbHVlUHJvcCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcnJbaWR4XVt2YWx1ZU5hbWVdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmVzdGVkUHJvcGVydHkoYXJyW2lkeF0sIHZhbHVlTmFtZSkuZ2V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlbmFtZTogZnVuY3Rpb24obmFtZSwgbmV3TmFtZSkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IGluZGV4TG9va3VwW25hbWVdO1xuXG4gICAgICAgICAgICBpZihpZHggPT09IHVuZGVmaW5lZCkgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIGNoYW5nZVR5cGVzW2lkeF0gPSBjaGFuZ2VUeXBlc1tpZHhdIHwgTkFNRTtcblxuICAgICAgICAgICAgaW5kZXhMb29rdXBbbmV3TmFtZV0gPSBpZHg7XG4gICAgICAgICAgICBkZWxldGUgaW5kZXhMb29rdXBbbmFtZV07XG5cbiAgICAgICAgICAgIGFycltpZHhdW2tleU5hbWVdID0gbmV3TmFtZTtcblxuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfSxcbiAgICAgICAgcmVtb3ZlOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gaW5kZXhMb29rdXBbbmFtZV07XG5cbiAgICAgICAgICAgIGlmKGlkeCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gb2JqO1xuXG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0gYXJyW2lkeF07XG4gICAgICAgICAgICBpZihPYmplY3Qua2V5cyhvYmplY3QpLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIG9iamVjdCBjb250YWlucyBtb3JlIHRoYW4ganVzdCB0aGUga2V5L3ZhbHVlLCBzbyB1bnNldFxuICAgICAgICAgICAgICAgIC8vIHRoZSB2YWx1ZSB3aXRob3V0IG1vZGlmeWluZyB0aGUgZW50cnkgb3RoZXJ3aXNlOlxuICAgICAgICAgICAgICAgIGNoYW5nZVR5cGVzW2lkeF0gPSBjaGFuZ2VUeXBlc1tpZHhdIHwgVkFMVUU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iai5zZXQobmFtZSwgbnVsbCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzU2ltcGxlVmFsdWVQcm9wKSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSBpZHg7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlVHlwZXNbaV0gPSBjaGFuZ2VUeXBlc1tpXSB8IEJPVEg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcihpID0gaWR4OyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4TG9va3VwW2FycltpXVtrZXlOYW1lXV0tLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZShpbmRleExvb2t1cFtuYW1lXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFBlcmZvcm0gdGhpcyB1cGRhdGUgKnN0cmljdGx5KiBzbyB3ZSBjYW4gY2hlY2sgd2hldGhlciB0aGUgcmVzdWx0J3NcbiAgICAgICAgICAgICAgICAvLyBiZWVuIHBydW5lZC4gSWYgc28sIGl0J3MgYSByZW1vdmFsLiBJZiBub3QsIGl0J3MgYSB2YWx1ZSB1bnNldCBvbmx5LlxuICAgICAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KG9iamVjdCwgdmFsdWVOYW1lKS5zZXQobnVsbCk7XG5cbiAgICAgICAgICAgICAgICAvLyBOb3cgY2hlY2sgaWYgdGhlIHRvcCBsZXZlbCBuZXN0ZWQgcHJvcGVydHkgaGFzIGFueSBrZXlzIGxlZnQuIElmIHNvLFxuICAgICAgICAgICAgICAgIC8vIHRoZSBvYmplY3Qgc3RpbGwgaGFzIHZhbHVlcyBzbyB3ZSBvbmx5IHdhbnQgdG8gdW5zZXQgdGhlIGtleS4gSWYgbm90LFxuICAgICAgICAgICAgICAgIC8vIHRoZSBlbnRpcmUgb2JqZWN0IGNhbiBiZSByZW1vdmVkIHNpbmNlIHRoZXJlJ3Mgbm8gb3RoZXIgZGF0YS5cbiAgICAgICAgICAgICAgICAvLyB2YXIgdG9wTGV2ZWxLZXlzID0gT2JqZWN0LmtleXMob2JqZWN0W3ZhbHVlTmFtZS5zcGxpdCgnLicpWzBdXSB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICBjaGFuZ2VUeXBlc1tpZHhdID0gY2hhbmdlVHlwZXNbaWR4XSB8IFZBTFVFIHwgVU5TRVQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvYmo7XG4gICAgICAgIH0sXG4gICAgICAgIGNvbnN0cnVjdFVwZGF0ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgYXN0ciwgaWR4O1xuICAgICAgICAgICAgdmFyIHVwZGF0ZSA9IHt9O1xuICAgICAgICAgICAgdmFyIGNoYW5nZWQgPSBPYmplY3Qua2V5cyhjaGFuZ2VUeXBlcyk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2hhbmdlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlkeCA9IGNoYW5nZWRbaV07XG4gICAgICAgICAgICAgICAgYXN0ciA9IHBhdGggKyAnWycgKyBpZHggKyAnXSc7XG4gICAgICAgICAgICAgICAgaWYoYXJyW2lkeF0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoY2hhbmdlVHlwZXNbaWR4XSAmIE5BTUUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZVthc3RyICsgJy4nICsga2V5TmFtZV0gPSBhcnJbaWR4XVtrZXlOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZihjaGFuZ2VUeXBlc1tpZHhdICYgVkFMVUUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzU2ltcGxlVmFsdWVQcm9wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlW2FzdHIgKyAnLicgKyB2YWx1ZU5hbWVdID0gKGNoYW5nZVR5cGVzW2lkeF0gJiBVTlNFVCkgPyBudWxsIDogYXJyW2lkeF1bdmFsdWVOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlW2FzdHIgKyAnLicgKyB2YWx1ZU5hbWVdID0gKGNoYW5nZVR5cGVzW2lkeF0gJiBVTlNFVCkgPyBudWxsIDogbmVzdGVkUHJvcGVydHkoYXJyW2lkeF0sIHZhbHVlTmFtZSkuZ2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB1cGRhdGVbYXN0cl0gPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHVwZGF0ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gb2JqO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi9yZWdpc3RyeScpO1xuXG4vKipcbiAqIGxvY2FsaXplOiB0cmFuc2xhdGUgYSBzdHJpbmcgZm9yIHRoZSBjdXJyZW50IGxvY2FsZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBnZDogdGhlIGdyYXBoRGl2IGZvciBjb250ZXh0XG4gKiAgZ2QuX2NvbnRleHQubG9jYWxlIGRldGVybWluZXMgdGhlIGxhbmd1YWdlICgmIG9wdGlvbmFsIHJlZ2lvbi9jb3VudHJ5KVxuICogIHRoZSBkaWN0aW9uYXJ5IGZvciBlYWNoIGxvY2FsZSBtYXkgZWl0aGVyIGJlIHN1cHBsaWVkIGluXG4gKiAgZ2QuX2NvbnRleHQubG9jYWxlcyBvciBnbG9iYWxseSB2aWEgUGxvdGx5LnJlZ2lzdGVyXG4gKiBAcGFyYW0ge3N0cmluZ30gczogdGhlIHN0cmluZyB0byB0cmFuc2xhdGVcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBsb2NhbGl6ZShnZCwgcykge1xuICAgIHZhciBsb2NhbGUgPSBnZC5fY29udGV4dC5sb2NhbGU7XG5cbiAgICAvKlxuICAgICAqIFByaW9yaXR5IG9mIGxvb2t1cDpcbiAgICAgKiAgICAgY29udGV4dERpY3RzW2xvY2FsZV0sXG4gICAgICogICAgIHJlZ2lzdGVyZWREaWN0c1tsb2NhbGVdLFxuICAgICAqICAgICBjb250ZXh0RGljdHNbYmFzZUxvY2FsZV0sIChpZiBiYXNlTG9jYWxlIGlzIGRpc3RpbmN0KVxuICAgICAqICAgICByZWdpc3RlcmVkRGljdHNbYmFzZUxvY2FsZV1cbiAgICAgKiBSZXR1cm4gdGhlIGZpcnN0IHRyYW5zbGF0aW9uIHdlIGZpbmQuXG4gICAgICogVGhpcyB3YXkgaWYgeW91IGhhdmUgYSByZWdpb25hbGl6YXRpb24geW91IGFyZSBhbGxvd2VkIHRvIHNwZWNpZnlcbiAgICAgKiBvbmx5IHdoYXQncyBkaWZmZXJlbnQgZnJvbSB0aGUgYmFzZSBsb2NhbGUsIGV2ZXJ5dGhpbmcgZWxzZSB3aWxsXG4gICAgICogZmFsbCBiYWNrIG9uIHRoZSBiYXNlLlxuICAgICAqL1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgdmFyIGxvY2FsZXMgPSBnZC5fY29udGV4dC5sb2NhbGVzO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgMjsgaisrKSB7XG4gICAgICAgICAgICB2YXIgZGljdCA9IChsb2NhbGVzW2xvY2FsZV0gfHwge30pLmRpY3Rpb25hcnk7XG4gICAgICAgICAgICBpZihkaWN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dCA9IGRpY3Rbc107XG4gICAgICAgICAgICAgICAgaWYob3V0KSByZXR1cm4gb3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9jYWxlcyA9IFJlZ2lzdHJ5LmxvY2FsZVJlZ2lzdHJ5O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGJhc2VMb2NhbGUgPSBsb2NhbGUuc3BsaXQoJy0nKVswXTtcbiAgICAgICAgaWYoYmFzZUxvY2FsZSA9PT0gbG9jYWxlKSBicmVhaztcbiAgICAgICAgbG9jYWxlID0gYmFzZUxvY2FsZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL3Bsb3RfYXBpL3Bsb3RfY29uZmlnJyk7XG5cbnZhciBsb2dnZXJzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyoqXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIGRlYnVnZ2luZyB0b29sc1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxubG9nZ2Vycy5sb2cgPSBmdW5jdGlvbigpIHtcbiAgICBpZihjb25maWcubG9nZ2luZyA+IDEpIHtcbiAgICAgICAgdmFyIG1lc3NhZ2VzID0gWydMT0c6J107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWVzc2FnZXMucHVzaChhcmd1bWVudHNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYXBwbHkoY29uc29sZS50cmFjZSB8fCBjb25zb2xlLmxvZywgbWVzc2FnZXMpO1xuICAgIH1cbn07XG5cbmxvZ2dlcnMud2FybiA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKGNvbmZpZy5sb2dnaW5nID4gMCkge1xuICAgICAgICB2YXIgbWVzc2FnZXMgPSBbJ1dBUk46J107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWVzc2FnZXMucHVzaChhcmd1bWVudHNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYXBwbHkoY29uc29sZS50cmFjZSB8fCBjb25zb2xlLmxvZywgbWVzc2FnZXMpO1xuICAgIH1cbn07XG5cbmxvZ2dlcnMuZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICBpZihjb25maWcubG9nZ2luZyA+IDApIHtcbiAgICAgICAgdmFyIG1lc3NhZ2VzID0gWydFUlJPUjonXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBhcHBseShjb25zb2xlLmVycm9yLCBtZXNzYWdlcyk7XG4gICAgfVxufTtcblxuLypcbiAqIFJvYnVzdCBhcHBseSwgZm9yIElFOSB3aGVyZSBjb25zb2xlLmxvZyBkb2Vzbid0IHN1cHBvcnRcbiAqIGFwcGx5IGxpa2Ugb3RoZXIgZnVuY3Rpb25zIGRvXG4gKi9cbmZ1bmN0aW9uIGFwcGx5KGYsIGFyZ3MpIHtcbiAgICBpZihmICYmIGYuYXBwbHkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIGB0aGlzYCBzaG91bGQgYWx3YXlzIGJlIGNvbnNvbGUsIHNpbmNlIGhlcmUgd2UncmUgYWx3YXlzXG4gICAgICAgICAgICAvLyBhcHBseWluZyBhIG1ldGhvZCBvZiB0aGUgY29uc29sZSBvYmplY3QuXG4gICAgICAgICAgICBmLmFwcGx5KGNvbnNvbGUsIGFyZ3MpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoKGUpIHsgLyogaW4gY2FzZSBhcHBseSBmYWlsZWQsIGZhbGwgYmFjayBvbiB0aGUgY29kZSBiZWxvdyAqLyB9XG4gICAgfVxuXG4gICAgLy8gbm8gYXBwbHkgLSBqdXN0IHRyeSBjYWxsaW5nIHRoZSBmdW5jdGlvbiBvbiBlYWNoIGFyZyBpbmRlcGVuZGVudGx5XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGYoYXJnc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2goZSkge1xuICAgICAgICAgICAgLy8gc3RpbGwgZmFpbHMgLSBsYXN0IHJlc29ydCBzaW1wbGUgY29uc29sZS5sb2dcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGFyZ3NbaV0pO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogR2VuZXJhbCBoZWxwZXIgdG8gbWFuYWdlIHRyYWNlIGdyb3VwcyBiYXNlZCBvbiBjYWxjZGF0YVxuICpcbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSB0cmFjZUxheWVyOiBhIHNlbGVjdGlvbiBjb250YWluaW5nIGEgc2luZ2xlIGdyb3VwXG4gKiAgICAgdG8gZHJhdyB0aGVzZSB0cmFjZXMgaW50b1xuICogQHBhcmFtIHthcnJheX0gY2RNb2R1bGU6IGFycmF5IG9mIGNhbGNkYXRhIGl0ZW1zIGZvciB0aGlzXG4gKiAgICAgbW9kdWxlIGFuZCBzdWJwbG90IGNvbWJpbmF0aW9uLiBBc3N1bWVzIHRoZSBjYWxjZGF0YSBpdGVtIGZvciBlYWNoXG4gKiAgICAgdHJhY2UgaXMgYW4gYXJyYXkgd2l0aCB0aGUgZnVsbERhdGEgdHJhY2UgYXR0YWNoZWQgdG8gdGhlIGZpcnN0IGl0ZW0uXG4gKiBAcGFyYW0ge3N0cmluZ30gY2xzOiB0aGUgY2xhc3MgYXR0cmlidXRlIHRvIGdpdmUgZWFjaCB0cmFjZSBncm91cFxuICogICAgIHNvIHlvdSBjYW4gZ2l2ZSBtdWx0aXBsZSBjbGFzc2VzIHNlcGFyYXRlZCBieSBzcGFjZXNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlVHJhY2VHcm91cHModHJhY2VMYXllciwgY2RNb2R1bGUsIGNscykge1xuICAgIHZhciB0cmFjZXMgPSB0cmFjZUxheWVyLnNlbGVjdEFsbCgnZy4nICsgY2xzLnJlcGxhY2UoL1xccy9nLCAnLicpKVxuICAgICAgICAuZGF0YShjZE1vZHVsZSwgZnVuY3Rpb24oY2QpIHsgcmV0dXJuIGNkWzBdLnRyYWNlLnVpZDsgfSk7XG5cbiAgICB0cmFjZXMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdHJhY2VzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgY2xzKTtcblxuICAgIHRyYWNlcy5vcmRlcigpO1xuXG4gICAgcmV0dXJuIHRyYWNlcztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5leHBvcnRzLmluaXQyZEFycmF5ID0gZnVuY3Rpb24ocm93TGVuZ3RoLCBjb2xMZW5ndGgpIHtcbiAgICB2YXIgYXJyYXkgPSBuZXcgQXJyYXkocm93TGVuZ3RoKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcm93TGVuZ3RoOyBpKyspIGFycmF5W2ldID0gbmV3IEFycmF5KGNvbExlbmd0aCk7XG4gICAgcmV0dXJuIGFycmF5O1xufTtcblxuLyoqXG4gKiB0cmFuc3Bvc2UgYSAocG9zc2libHkgcmFnZ2VkKSAyZCBhcnJheSB6LiBpbnNwaXJlZCBieVxuICogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xNzQyODU4Ny9cbiAqIHRyYW5zcG9zaW5nLWEtMmQtYXJyYXktaW4tamF2YXNjcmlwdFxuICovXG5leHBvcnRzLnRyYW5zcG9zZVJhZ2dlZCA9IGZ1bmN0aW9uKHopIHtcbiAgICB2YXIgbWF4bGVuID0gMCxcbiAgICAgICAgemxlbiA9IHoubGVuZ3RoLFxuICAgICAgICBpLFxuICAgICAgICBqO1xuICAgIC8vIE1heGltdW0gcm93IGxlbmd0aDpcbiAgICBmb3IoaSA9IDA7IGkgPCB6bGVuOyBpKyspIG1heGxlbiA9IE1hdGgubWF4KG1heGxlbiwgeltpXS5sZW5ndGgpO1xuXG4gICAgdmFyIHQgPSBuZXcgQXJyYXkobWF4bGVuKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBtYXhsZW47IGkrKykge1xuICAgICAgICB0W2ldID0gbmV3IEFycmF5KHpsZW4pO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCB6bGVuOyBqKyspIHRbaV1bal0gPSB6W2pdW2ldO1xuICAgIH1cblxuICAgIHJldHVybiB0O1xufTtcblxuLy8gb3VyIG93biBkb3QgZnVuY3Rpb24gc28gdGhhdCB3ZSBkb24ndCBuZWVkIHRvIGluY2x1ZGUgbnVtZXJpY1xuZXhwb3J0cy5kb3QgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgaWYoISh4Lmxlbmd0aCAmJiB5Lmxlbmd0aCkgfHwgeC5sZW5ndGggIT09IHkubGVuZ3RoKSByZXR1cm4gbnVsbDtcblxuICAgIHZhciBsZW4gPSB4Lmxlbmd0aCxcbiAgICAgICAgb3V0LFxuICAgICAgICBpO1xuXG4gICAgaWYoeFswXS5sZW5ndGgpIHtcbiAgICAgICAgLy8gbWF0LXZlYyBvciBtYXQtbWF0XG4gICAgICAgIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykgb3V0W2ldID0gZXhwb3J0cy5kb3QoeFtpXSwgeSk7XG4gICAgfVxuICAgIGVsc2UgaWYoeVswXS5sZW5ndGgpIHtcbiAgICAgICAgLy8gdmVjLW1hdFxuICAgICAgICB2YXIgeVRyYW5zcG9zZSA9IGV4cG9ydHMudHJhbnNwb3NlUmFnZ2VkKHkpO1xuICAgICAgICBvdXQgPSBuZXcgQXJyYXkoeVRyYW5zcG9zZS5sZW5ndGgpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB5VHJhbnNwb3NlLmxlbmd0aDsgaSsrKSBvdXRbaV0gPSBleHBvcnRzLmRvdCh4LCB5VHJhbnNwb3NlW2ldKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIHZlYy12ZWNcbiAgICAgICAgb3V0ID0gMDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dCArPSB4W2ldICogeVtpXTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLy8gdHJhbnNsYXRlIGJ5ICh4LHkpXG5leHBvcnRzLnRyYW5zbGF0aW9uTWF0cml4ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiBbWzEsIDAsIHhdLCBbMCwgMSwgeV0sIFswLCAwLCAxXV07XG59O1xuXG4vLyByb3RhdGUgYnkgYWxwaGEgYXJvdW5kICgwLDApXG5leHBvcnRzLnJvdGF0aW9uTWF0cml4ID0gZnVuY3Rpb24oYWxwaGEpIHtcbiAgICB2YXIgYSA9IGFscGhhICogTWF0aC5QSSAvIDE4MDtcbiAgICByZXR1cm4gW1tNYXRoLmNvcyhhKSwgLU1hdGguc2luKGEpLCAwXSxcbiAgICAgICAgICAgIFtNYXRoLnNpbihhKSwgTWF0aC5jb3MoYSksIDBdLFxuICAgICAgICAgICAgWzAsIDAsIDFdXTtcbn07XG5cbi8vIHJvdGF0ZSBieSBhbHBoYSBhcm91bmQgKHgseSlcbmV4cG9ydHMucm90YXRpb25YWU1hdHJpeCA9IGZ1bmN0aW9uKGEsIHgsIHkpIHtcbiAgICByZXR1cm4gZXhwb3J0cy5kb3QoXG4gICAgICAgIGV4cG9ydHMuZG90KGV4cG9ydHMudHJhbnNsYXRpb25NYXRyaXgoeCwgeSksXG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHMucm90YXRpb25NYXRyaXgoYSkpLFxuICAgICAgICBleHBvcnRzLnRyYW5zbGF0aW9uTWF0cml4KC14LCAteSkpO1xufTtcblxuLy8gYXBwbGllcyBhIDJEIHRyYW5zZm9ybWF0aW9uIG1hdHJpeCB0byBlaXRoZXIgeCBhbmQgeSBwYXJhbXMgb3IgYW4gW3gseV0gYXJyYXlcbmV4cG9ydHMuYXBwbHkyRFRyYW5zZm9ybSA9IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICBhcmdzID0gYXJnc1swXTtcbiAgICAgICAgfS8vIGZyb20gbWFwXG4gICAgICAgIHZhciB4eSA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBhcmdzWzBdIDogW2FyZ3NbMF0sIGFyZ3NbMV1dO1xuICAgICAgICByZXR1cm4gZXhwb3J0cy5kb3QodHJhbnNmb3JtLCBbeHlbMF0sIHh5WzFdLCAxXSkuc2xpY2UoMCwgMik7XG4gICAgfTtcbn07XG5cbi8vIGFwcGxpZXMgYSAyRCB0cmFuc2Zvcm1hdGlvbiBtYXRyaXggdG8gYW4gW3gxLHkxLHgyLHkyXSBhcnJheSAodG8gdHJhbnNmb3JtIGEgc2VnbWVudClcbmV4cG9ydHMuYXBwbHkyRFRyYW5zZm9ybTIgPSBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICB2YXIgYXQgPSBleHBvcnRzLmFwcGx5MkRUcmFuc2Zvcm0odHJhbnNmb3JtKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeHlzKSB7XG4gICAgICAgIHJldHVybiBhdCh4eXMuc2xpY2UoMCwgMikpLmNvbmNhdChhdCh4eXMuc2xpY2UoMiwgNCkpKTtcbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBzYW5pdGl6ZWQgbW9kdWx1cyBmdW5jdGlvbiB0aGF0IGFsd2F5cyByZXR1cm5zIGluIHRoZSByYW5nZSBbMCwgZClcbiAqIHJhdGhlciB0aGFuICgtZCwgMF0gaWYgdiBpcyBuZWdhdGl2ZVxuICovXG5mdW5jdGlvbiBtb2QodiwgZCkge1xuICAgIHZhciBvdXQgPSB2ICUgZDtcbiAgICByZXR1cm4gb3V0IDwgMCA/IG91dCArIGQgOiBvdXQ7XG59XG5cbi8qKlxuICogc2FuaXRpemVkIG1vZHVsdXMgZnVuY3Rpb24gdGhhdCBhbHdheXMgcmV0dXJucyBpbiB0aGUgcmFuZ2UgWy1kLzIsIGQvMl1cbiAqIHJhdGhlciB0aGFuICgtZCwgMF0gaWYgdiBpcyBuZWdhdGl2ZVxuICovXG5mdW5jdGlvbiBtb2RIYWxmKHYsIGQpIHtcbiAgICByZXR1cm4gTWF0aC5hYnModikgPiAoZCAvIDIpID9cbiAgICAgICAgdiAtIE1hdGgucm91bmQodiAvIGQpICogZCA6XG4gICAgICAgIHY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZDogbW9kLFxuICAgIG1vZEhhbGY6IG1vZEhhbGZcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4vYXJyYXknKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG4vKipcbiAqIGNvbnZlcnQgYSBzdHJpbmcgcyAoc3VjaCBhcyAneGF4aXMucmFuZ2VbMF0nKVxuICogcmVwcmVzZW50aW5nIGEgcHJvcGVydHkgb2YgbmVzdGVkIG9iamVjdCBpbnRvIHNldCBhbmQgZ2V0IG1ldGhvZHNcbiAqIGFsc28gcmV0dXJuIHRoZSBzdHJpbmcgYW5kIG9iamVjdCBzbyB3ZSBkb24ndCBoYXZlIHRvIGtlZXAgdHJhY2sgb2YgdGhlbVxuICogYWxsb3dzIFstMV0gZm9yIGFuIGFycmF5IGluZGV4LCB0byBzZXQgYSBwcm9wZXJ0eSBpbnNpZGUgYWxsIGVsZW1lbnRzXG4gKiBvZiBhbiBhcnJheVxuICogZWcgaWYgb2JqID0ge2FycjogW3thOiAxfSwge2E6IDJ9XX1cbiAqIHlvdSBjYW4gZG8gcCA9IG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FyclstMV0uYScpXG4gKiBidXQgeW91IGNhbm5vdCBzZXQgdGhlIGFycmF5IGl0c2VsZiB0aGlzIHdheSwgdG8gZG8gdGhhdFxuICoganVzdCBzZXQgdGhlIHdob2xlIGFycmF5LlxuICogZWcgaWYgb2JqID0ge2FycjogWzEsIDIsIDNdfVxuICogeW91IGNhbid0IGRvIG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FyclstMV0nKS5zZXQoNSlcbiAqIGJ1dCB5b3UgY2FuIGRvIG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FycicpLnNldChbNSwgNSwgNV0pXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbmVzdGVkUHJvcGVydHkoY29udGFpbmVyLCBwcm9wU3RyKSB7XG4gICAgaWYoaXNOdW1lcmljKHByb3BTdHIpKSBwcm9wU3RyID0gU3RyaW5nKHByb3BTdHIpO1xuICAgIGVsc2UgaWYodHlwZW9mIHByb3BTdHIgIT09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICBwcm9wU3RyLnN1YnN0cihwcm9wU3RyLmxlbmd0aCAtIDQpID09PSAnWy0xXScpIHtcbiAgICAgICAgdGhyb3cgJ2JhZCBwcm9wZXJ0eSBzdHJpbmcnO1xuICAgIH1cblxuICAgIHZhciBqID0gMCxcbiAgICAgICAgcHJvcFBhcnRzID0gcHJvcFN0ci5zcGxpdCgnLicpLFxuICAgICAgICBpbmRleGVkLFxuICAgICAgICBpbmRpY2VzLFxuICAgICAgICBpO1xuXG4gICAgLy8gY2hlY2sgZm9yIHBhcnRzIG9mIHRoZSBuZXN0aW5nIGhpZXJhcmNoeSB0aGF0IGFyZSBudW1iZXJzIChpZSBhcnJheSBlbGVtZW50cylcbiAgICB3aGlsZShqIDwgcHJvcFBhcnRzLmxlbmd0aCkge1xuICAgICAgICAvLyBsb29rIGZvciBub24tYnJhY2tldCBjaGFycywgdGhlbiBhbnkgbnVtYmVyIG9mIFsjI10gYmxvY2tzXG4gICAgICAgIGluZGV4ZWQgPSBTdHJpbmcocHJvcFBhcnRzW2pdKS5tYXRjaCgvXihbXlxcW1xcXV0qKSgoXFxbXFwtP1swLTldKlxcXSkrKSQvKTtcbiAgICAgICAgaWYoaW5kZXhlZCkge1xuICAgICAgICAgICAgaWYoaW5kZXhlZFsxXSkgcHJvcFBhcnRzW2pdID0gaW5kZXhlZFsxXTtcbiAgICAgICAgICAgIC8vIGFsbG93IHByb3BTdHIgdG8gc3RhcnQgd2l0aCBicmFja2V0ZWQgYXJyYXkgaW5kaWNlc1xuICAgICAgICAgICAgZWxzZSBpZihqID09PSAwKSBwcm9wUGFydHMuc3BsaWNlKDAsIDEpO1xuICAgICAgICAgICAgZWxzZSB0aHJvdyAnYmFkIHByb3BlcnR5IHN0cmluZyc7XG5cbiAgICAgICAgICAgIGluZGljZXMgPSBpbmRleGVkWzJdXG4gICAgICAgICAgICAgICAgLnN1YnN0cigxLCBpbmRleGVkWzJdLmxlbmd0aCAtIDIpXG4gICAgICAgICAgICAgICAgLnNwbGl0KCddWycpO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgIHByb3BQYXJ0cy5zcGxpY2UoaiwgMCwgTnVtYmVyKGluZGljZXNbaV0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBqKys7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIGNvbnRhaW5lciAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGJhZENvbnRhaW5lcihjb250YWluZXIsIHByb3BTdHIsIHByb3BQYXJ0cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2V0OiBucFNldChjb250YWluZXIsIHByb3BQYXJ0cywgcHJvcFN0ciksXG4gICAgICAgIGdldDogbnBHZXQoY29udGFpbmVyLCBwcm9wUGFydHMpLFxuICAgICAgICBhc3RyOiBwcm9wU3RyLFxuICAgICAgICBwYXJ0czogcHJvcFBhcnRzLFxuICAgICAgICBvYmo6IGNvbnRhaW5lclxuICAgIH07XG59O1xuXG5mdW5jdGlvbiBucEdldChjb250LCBwYXJ0cykge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGN1ckNvbnQgPSBjb250LFxuICAgICAgICAgICAgY3VyUGFydCxcbiAgICAgICAgICAgIGFsbFNhbWUsXG4gICAgICAgICAgICBvdXQsXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgajtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGN1clBhcnQgPSBwYXJ0c1tpXTtcbiAgICAgICAgICAgIGlmKGN1clBhcnQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgYWxsU2FtZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgb3V0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY3VyQ29udC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBvdXRbal0gPSBucEdldChjdXJDb250W2pdLCBwYXJ0cy5zbGljZShpICsgMSkpKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKG91dFtqXSAhPT0gb3V0WzBdKSBhbGxTYW1lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBhbGxTYW1lID8gb3V0WzBdIDogb3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodHlwZW9mIGN1clBhcnQgPT09ICdudW1iZXInICYmICFpc0FycmF5T3JUeXBlZEFycmF5KGN1ckNvbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1ckNvbnQgPSBjdXJDb250W2N1clBhcnRdO1xuICAgICAgICAgICAgaWYodHlwZW9mIGN1ckNvbnQgIT09ICdvYmplY3QnIHx8IGN1ckNvbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gb25seSBoaXQgdGhpcyBpZiBwYXJ0cy5sZW5ndGggPT09IDFcbiAgICAgICAgaWYodHlwZW9mIGN1ckNvbnQgIT09ICdvYmplY3QnIHx8IGN1ckNvbnQgPT09IG51bGwpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgb3V0ID0gY3VyQ29udFtwYXJ0c1tpXV07XG4gICAgICAgIGlmKG91dCA9PT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xufVxuXG4vKlxuICogQ2FuIHRoaXMgdmFsdWUgYmUgZGVsZXRlZD8gV2UgY2FuIGRlbGV0ZSBgdW5kZWZpbmVkYCwgYW5kIGBudWxsYCBleGNlcHQgSU5TSURFIGFuXG4gKiAqYXJncyogYXJyYXkuXG4gKlxuICogUHJldmlvdXNseSB3ZSBhbHNvIGRlbGV0ZWQgc29tZSBge31gIGFuZCBgW11gLCBpbiBvcmRlciB0byB0cnkgYW5kIG1ha2Ugc2V0L3Vuc2V0XG4gKiBhIG5ldCBub29wOyBidXQgdGhpcyBjYXVzZXMgZmFyIG1vcmUgY29tcGxpY2F0aW9uIHRoYW4gaXQncyB3b3J0aCwgYW5kIHN0aWxsIGhhZFxuICogbG90cyBvZiBleGNlcHRpb25zLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzE0MTBcbiAqXG4gKiAqYXJncyogYXJyYXlzIGdldCBwYXNzZWQgZGlyZWN0bHkgdG8gQVBJIG1ldGhvZHMgYW5kIHdlIHNob3VsZCByZXNwZWN0IG51bGwgaWZcbiAqIHRoZSB1c2VyIHB1dCBpdCB0aGVyZSwgYnV0IG90aGVyd2lzZSBudWxsIGlzIGRlbGV0ZWQgYXMgd2UgdXNlIGl0IGFzIGNvZGVcbiAqIGluIHJlc3R5bGUvcmVsYXlvdXQvdXBkYXRlIGZvciBcImRlbGV0ZSB0aGlzIHZhbHVlXCIgd2hlcmVhcyB1bmRlZmluZWQgbWVhbnNcbiAqIFwiaWdub3JlIHRoaXMgZWRpdFwiXG4gKi9cbnZhciBBUkdTX1BBVFRFUk4gPSAvKF58XFwuKWFyZ3NcXFsvO1xuZnVuY3Rpb24gaXNEZWxldGFibGUodmFsLCBwcm9wU3RyKSB7XG4gICAgcmV0dXJuICh2YWwgPT09IHVuZGVmaW5lZCkgfHwgKHZhbCA9PT0gbnVsbCAmJiAhcHJvcFN0ci5tYXRjaChBUkdTX1BBVFRFUk4pKTtcbn1cblxuZnVuY3Rpb24gbnBTZXQoY29udCwgcGFydHMsIHByb3BTdHIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHZhciBjdXJDb250ID0gY29udCxcbiAgICAgICAgICAgIHByb3BQYXJ0ID0gJycsXG4gICAgICAgICAgICBjb250YWluZXJMZXZlbHMgPSBbW2NvbnQsIHByb3BQYXJ0XV0sXG4gICAgICAgICAgICB0b0RlbGV0ZSA9IGlzRGVsZXRhYmxlKHZhbCwgcHJvcFN0ciksXG4gICAgICAgICAgICBjdXJQYXJ0LFxuICAgICAgICAgICAgaTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGN1clBhcnQgPSBwYXJ0c1tpXTtcblxuICAgICAgICAgICAgaWYodHlwZW9mIGN1clBhcnQgPT09ICdudW1iZXInICYmICFpc0FycmF5T3JUeXBlZEFycmF5KGN1ckNvbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgJ2FycmF5IGluZGV4IGJ1dCBjb250YWluZXIgaXMgbm90IGFuIGFycmF5JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaGFuZGxlIHNwZWNpYWwgLTEgYXJyYXkgaW5kZXhcbiAgICAgICAgICAgIGlmKGN1clBhcnQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdG9EZWxldGUgPSAhc2V0QXJyYXlBbGwoY3VyQ29udCwgcGFydHMuc2xpY2UoaSArIDEpLCB2YWwsIHByb3BTdHIpO1xuICAgICAgICAgICAgICAgIGlmKHRvRGVsZXRlKSBicmVhaztcbiAgICAgICAgICAgICAgICBlbHNlIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWNoZWNrTmV3Q29udGFpbmVyKGN1ckNvbnQsIGN1clBhcnQsIHBhcnRzW2kgKyAxXSwgdG9EZWxldGUpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGN1ckNvbnQgPSBjdXJDb250W2N1clBhcnRdO1xuXG4gICAgICAgICAgICBpZih0eXBlb2YgY3VyQ29udCAhPT0gJ29iamVjdCcgfHwgY3VyQ29udCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93ICdjb250YWluZXIgaXMgbm90IGFuIG9iamVjdCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb3BQYXJ0ID0gam9pblByb3BTdHIocHJvcFBhcnQsIGN1clBhcnQpO1xuXG4gICAgICAgICAgICBjb250YWluZXJMZXZlbHMucHVzaChbY3VyQ29udCwgcHJvcFBhcnRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRvRGVsZXRlKSB7XG4gICAgICAgICAgICBpZihpID09PSBwYXJ0cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGN1ckNvbnRbcGFydHNbaV1dO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlIG9uZSBiaXQgb2YgcHJ1bmluZyB3ZSBzdGlsbCBkbzogZHJvcCBgdW5kZWZpbmVkYCBmcm9tIHRoZSBlbmQgb2YgYXJyYXlzLlxuICAgICAgICAgICAgICAgIC8vIEluIGNhc2Ugc29tZW9uZSBoYXMgYWxyZWFkeSB1bnNldCBwcmV2aW91cyBpdGVtcywgY29udGludWUgdW50aWwgd2UgaGl0IGFcbiAgICAgICAgICAgICAgICAvLyBub24tdW5kZWZpbmVkIHZhbHVlLlxuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY3VyQ29udCkgJiYgK3BhcnRzW2ldID09PSBjdXJDb250Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoY3VyQ29udC5sZW5ndGggJiYgY3VyQ29udFtjdXJDb250Lmxlbmd0aCAtIDFdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1ckNvbnQucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBjdXJDb250W3BhcnRzW2ldXSA9IHZhbDtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBqb2luUHJvcFN0cihwcm9wU3RyLCBuZXdQYXJ0KSB7XG4gICAgdmFyIHRvQWRkID0gbmV3UGFydDtcbiAgICBpZihpc051bWVyaWMobmV3UGFydCkpIHRvQWRkID0gJ1snICsgbmV3UGFydCArICddJztcbiAgICBlbHNlIGlmKHByb3BTdHIpIHRvQWRkID0gJy4nICsgbmV3UGFydDtcblxuICAgIHJldHVybiBwcm9wU3RyICsgdG9BZGQ7XG59XG5cbi8vIGhhbmRsZSBzcGVjaWFsIC0xIGFycmF5IGluZGV4XG5mdW5jdGlvbiBzZXRBcnJheUFsbChjb250YWluZXJBcnJheSwgaW5uZXJQYXJ0cywgdmFsLCBwcm9wU3RyKSB7XG4gICAgdmFyIGFycmF5VmFsID0gaXNBcnJheU9yVHlwZWRBcnJheSh2YWwpLFxuICAgICAgICBhbGxTZXQgPSB0cnVlLFxuICAgICAgICB0aGlzVmFsID0gdmFsLFxuICAgICAgICB0aGlzUHJvcFN0ciA9IHByb3BTdHIucmVwbGFjZSgnLTEnLCAwKSxcbiAgICAgICAgZGVsZXRlVGhpcyA9IGFycmF5VmFsID8gZmFsc2UgOiBpc0RlbGV0YWJsZSh2YWwsIHRoaXNQcm9wU3RyKSxcbiAgICAgICAgZmlyc3RQYXJ0ID0gaW5uZXJQYXJ0c1swXSxcbiAgICAgICAgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbnRhaW5lckFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXNQcm9wU3RyID0gcHJvcFN0ci5yZXBsYWNlKCctMScsIGkpO1xuICAgICAgICBpZihhcnJheVZhbCkge1xuICAgICAgICAgICAgdGhpc1ZhbCA9IHZhbFtpICUgdmFsLmxlbmd0aF07XG4gICAgICAgICAgICBkZWxldGVUaGlzID0gaXNEZWxldGFibGUodGhpc1ZhbCwgdGhpc1Byb3BTdHIpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGRlbGV0ZVRoaXMpIGFsbFNldCA9IGZhbHNlO1xuICAgICAgICBpZighY2hlY2tOZXdDb250YWluZXIoY29udGFpbmVyQXJyYXksIGksIGZpcnN0UGFydCwgZGVsZXRlVGhpcykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIG5wU2V0KGNvbnRhaW5lckFycmF5W2ldLCBpbm5lclBhcnRzLCBwcm9wU3RyLnJlcGxhY2UoJy0xJywgaSkpKHRoaXNWYWwpO1xuICAgIH1cbiAgICByZXR1cm4gYWxsU2V0O1xufVxuXG4vKipcbiAqIG1ha2UgbmV3IHN1Yi1jb250YWluZXIgYXMgbmVlZGVkLlxuICogcmV0dXJucyBmYWxzZSBpZiB0aGVyZSdzIG5vIGNvbnRhaW5lciBhbmQgbm9uZSBpcyBuZWVkZWRcbiAqIGJlY2F1c2Ugd2UncmUgb25seSBkZWxldGluZyBhbiBhdHRyaWJ1dGVcbiAqL1xuZnVuY3Rpb24gY2hlY2tOZXdDb250YWluZXIoY29udGFpbmVyLCBwYXJ0LCBuZXh0UGFydCwgdG9EZWxldGUpIHtcbiAgICBpZihjb250YWluZXJbcGFydF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZih0b0RlbGV0ZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGlmKHR5cGVvZiBuZXh0UGFydCA9PT0gJ251bWJlcicpIGNvbnRhaW5lcltwYXJ0XSA9IFtdO1xuICAgICAgICBlbHNlIGNvbnRhaW5lcltwYXJ0XSA9IHt9O1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gYmFkQ29udGFpbmVyKGNvbnRhaW5lciwgcHJvcFN0ciwgcHJvcFBhcnRzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2V0OiBmdW5jdGlvbigpIHsgdGhyb3cgJ2JhZCBjb250YWluZXInOyB9LFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGFzdHI6IHByb3BTdHIsXG4gICAgICAgIHBhcnRzOiBwcm9wUGFydHMsXG4gICAgICAgIG9iajogY29udGFpbmVyXG4gICAgfTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gU2ltcGxlIGhlbHBlciBmdW5jdGlvbnNcbi8vIG5vbmUgb2YgdGhlc2UgbmVlZCBhbnkgZXh0ZXJuYWwgZGVwc1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG5vb3AoKSB7fTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBOT1RFREFUQSA9IFtdO1xuXG4vKipcbiAqIG5vdGlmaWVyXG4gKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBUaGUgcGVyc29uJ3MgdXNlciBuYW1lXG4gKiBAcGFyYW0ge051bWJlcn0gW2RlbGF5PTEwMDBdIFRoZSBkZWxheSB0aW1lIGluIG1pbGxpc2Vjb25kc1xuICogICAgICAgICAgb3IgJ2xvbmcnIHdoaWNoIHByb3ZpZGVzIDIwMDAgbXMgZGVsYXkgdGltZS5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH0gdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCByZXR1cm4gYSB2YWx1ZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHRleHQsIGRpc3BsYXlMZW5ndGgpIHtcbiAgICBpZihOT1RFREFUQS5pbmRleE9mKHRleHQpICE9PSAtMSkgcmV0dXJuO1xuXG4gICAgTk9URURBVEEucHVzaCh0ZXh0KTtcblxuICAgIHZhciB0cyA9IDEwMDA7XG4gICAgaWYoaXNOdW1lcmljKGRpc3BsYXlMZW5ndGgpKSB0cyA9IGRpc3BsYXlMZW5ndGg7XG4gICAgZWxzZSBpZihkaXNwbGF5TGVuZ3RoID09PSAnbG9uZycpIHRzID0gMzAwMDtcblxuICAgIHZhciBub3RpZmllckNvbnRhaW5lciA9IGQzLnNlbGVjdCgnYm9keScpXG4gICAgICAgIC5zZWxlY3RBbGwoJy5wbG90bHktbm90aWZpZXInKVxuICAgICAgICAuZGF0YShbMF0pO1xuICAgIG5vdGlmaWVyQ29udGFpbmVyLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZGl2JylcbiAgICAgICAgLmNsYXNzZWQoJ3Bsb3RseS1ub3RpZmllcicsIHRydWUpO1xuXG4gICAgdmFyIG5vdGVzID0gbm90aWZpZXJDb250YWluZXIuc2VsZWN0QWxsKCcubm90aWZpZXItbm90ZScpLmRhdGEoTk9URURBVEEpO1xuXG4gICAgZnVuY3Rpb24ga2lsbE5vdGUodHJhbnNpdGlvbikge1xuICAgICAgICB0cmFuc2l0aW9uXG4gICAgICAgICAgICAuZHVyYXRpb24oNzAwKVxuICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbih0aGlzVGV4dCkge1xuICAgICAgICAgICAgICAgIHZhciB0aGlzSW5kZXggPSBOT1RFREFUQS5pbmRleE9mKHRoaXNUZXh0KTtcbiAgICAgICAgICAgICAgICBpZih0aGlzSW5kZXggIT09IC0xKSBOT1RFREFUQS5zcGxpY2UodGhpc0luZGV4LCAxKTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBub3Rlcy5lbnRlcigpLmFwcGVuZCgnZGl2JylcbiAgICAgICAgLmNsYXNzZWQoJ25vdGlmaWVyLW5vdGUnLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgICAuZWFjaChmdW5jdGlvbih0aGlzVGV4dCkge1xuICAgICAgICAgICAgdmFyIG5vdGUgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIG5vdGUuYXBwZW5kKCdidXR0b24nKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdub3RpZmllci1jbG9zZScsIHRydWUpXG4gICAgICAgICAgICAgICAgLmh0bWwoJyZ0aW1lczsnKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgbm90ZS50cmFuc2l0aW9uKCkuY2FsbChraWxsTm90ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHZhciBwID0gbm90ZS5hcHBlbmQoJ3AnKTtcbiAgICAgICAgICAgIHZhciBsaW5lcyA9IHRoaXNUZXh0LnNwbGl0KC88YnJcXHMqXFwvPz4vZyk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZihpKSBwLmFwcGVuZCgnYnInKTtcbiAgICAgICAgICAgICAgICBwLmFwcGVuZCgnc3BhbicpLnRleHQobGluZXNbaV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBub3RlLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAuZHVyYXRpb24oNzAwKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAgICAgLmRlbGF5KHRzKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChraWxsTm90ZSk7XG4gICAgICAgIH0pO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2V0Q3Vyc29yID0gcmVxdWlyZSgnLi9zZXRjdXJzb3InKTtcblxudmFyIFNUQVNIQVRUUiA9ICdkYXRhLXNhdmVkY3Vyc29yJztcbnZhciBOT19DVVJTT1IgPSAnISEnO1xuXG4vKlxuICogd29ya3Mgd2l0aCBvdXIgQ1NTIGN1cnNvciBjbGFzc2VzIChzZWUgY3NzL19jdXJzb3Iuc2NzcylcbiAqIHRvIG92ZXJyaWRlIGEgcHJldmlvdXMgY3Vyc29yIHNldCBvbiBkMyBzaW5nbGUtZWxlbWVudCBzZWxlY3Rpb25zLFxuICogYnkgbW92aW5nIHRoZSBuYW1lIG9mIHRoZSBvcmlnaW5hbCBjdXJzb3IgdG8gdGhlIGRhdGEtc2F2ZWRjdXJzb3IgYXR0ci5cbiAqIG9taXQgY3Vyc29yIHRvIHJldmVydCB0byB0aGUgcHJldmlvdXNseSBzZXQgdmFsdWUuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gb3ZlcnJpZGVDdXJzb3IoZWwzLCBjc3IpIHtcbiAgICB2YXIgc2F2ZWRDdXJzb3IgPSBlbDMuYXR0cihTVEFTSEFUVFIpO1xuICAgIGlmKGNzcikge1xuICAgICAgICBpZighc2F2ZWRDdXJzb3IpIHtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gKGVsMy5hdHRyKCdjbGFzcycpIHx8ICcnKS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNsYXNzZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY2xzID0gY2xhc3Nlc1tpXTtcbiAgICAgICAgICAgICAgICBpZihjbHMuaW5kZXhPZignY3Vyc29yLScpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsMy5hdHRyKFNUQVNIQVRUUiwgY2xzLnN1YnN0cig3KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKGNscywgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKCFlbDMuYXR0cihTVEFTSEFUVFIpKSB7XG4gICAgICAgICAgICAgICAgZWwzLmF0dHIoU1RBU0hBVFRSLCBOT19DVVJTT1IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNldEN1cnNvcihlbDMsIGNzcik7XG4gICAgfVxuICAgIGVsc2UgaWYoc2F2ZWRDdXJzb3IpIHtcbiAgICAgICAgZWwzLmF0dHIoU1RBU0hBVFRSLCBudWxsKTtcblxuICAgICAgICBpZihzYXZlZEN1cnNvciA9PT0gTk9fQ1VSU09SKSBzZXRDdXJzb3IoZWwzKTtcbiAgICAgICAgZWxzZSBzZXRDdXJzb3IoZWwzLCBzYXZlZEN1cnNvcik7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZG90ID0gcmVxdWlyZSgnLi9tYXRyaXgnKS5kb3Q7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIHBvbHlnb24gPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIFR1cm4gYW4gYXJyYXkgb2YgW3gsIHldIHBhaXJzIGludG8gYSBwb2x5Z29uIG9iamVjdFxuICogdGhhdCBjYW4gdGVzdCBpZiBwb2ludHMgYXJlIGluc2lkZSBpdFxuICpcbiAqIEBwYXJhbSBwdHNJbiBBcnJheSBvZiBbeCwgeV0gcGFpcnNcbiAqXG4gKiBAcmV0dXJucyBwb2x5Z29uIE9iamVjdCB7eG1pbiwgeG1heCwgeW1pbiwgeW1heCwgcHRzLCBjb250YWluc31cbiAqICAgICAgKHh8eSkobWlufG1heCkgYXJlIHRoZSBib3VuZGluZyByZWN0IG9mIHRoZSBwb2x5Z29uXG4gKiAgICAgIHB0cyBpcyB0aGUgb3JpZ2luYWwgYXJyYXksIHdpdGggdGhlIGZpcnN0IHBhaXIgcmVwZWF0ZWQgYXQgdGhlIGVuZFxuICogICAgICBjb250YWlucyBpcyBhIGZ1bmN0aW9uOiAocHQsIG9taXRGaXJzdEVkZ2UpXG4gKiAgICAgICAgICBwdCBpcyB0aGUgW3gsIHldIHBhaXIgdG8gdGVzdFxuICogICAgICAgICAgb21pdEZpcnN0RWRnZSB0cnV0aHkgbWVhbnMgcG9pbnRzIGV4YWN0bHkgb24gdGhlIGZpcnN0IGVkZ2UgZG9uJ3RcbiAqICAgICAgICAgICAgICBjb3VudC4gVGhpcyBpcyBmb3IgdXNlIGFkZGluZyBvbmUgcG9seWdvbiB0byBhbm90aGVyIHNvIHdlXG4gKiAgICAgICAgICAgICAgZG9uJ3QgZG91YmxlLWNvdW50IHRoZSBlZGdlIHdoZXJlIHRoZXkgbWVldC5cbiAqICAgICAgICAgIHJldHVybnMgYm9vbGVhbjogaXMgcHQgaW5zaWRlIHRoZSBwb2x5Z29uIChpbmNsdWRpbmcgb24gaXRzIGVkZ2VzKVxuICovXG5wb2x5Z29uLnRlc3RlciA9IGZ1bmN0aW9uIHRlc3RlcihwdHNJbikge1xuICAgIHZhciBwdHMgPSBwdHNJbi5zbGljZSgpLFxuICAgICAgICB4bWluID0gcHRzWzBdWzBdLFxuICAgICAgICB4bWF4ID0geG1pbixcbiAgICAgICAgeW1pbiA9IHB0c1swXVsxXSxcbiAgICAgICAgeW1heCA9IHltaW4sXG4gICAgICAgIGk7XG5cbiAgICBwdHMucHVzaChwdHNbMF0pO1xuICAgIGZvcihpID0gMTsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB4bWluID0gTWF0aC5taW4oeG1pbiwgcHRzW2ldWzBdKTtcbiAgICAgICAgeG1heCA9IE1hdGgubWF4KHhtYXgsIHB0c1tpXVswXSk7XG4gICAgICAgIHltaW4gPSBNYXRoLm1pbih5bWluLCBwdHNbaV1bMV0pO1xuICAgICAgICB5bWF4ID0gTWF0aC5tYXgoeW1heCwgcHRzW2ldWzFdKTtcbiAgICB9XG5cbiAgICAvLyBkbyB3ZSBoYXZlIGEgcmVjdGFuZ2xlPyBIYW5kbGUgdGhpcyBoZXJlLCBzbyB3ZSBjYW4gdXNlIHRoZSBzYW1lXG4gICAgLy8gdGVzdGVyIGZvciB0aGUgcmVjdGFuZ3VsYXIgY2FzZSB3aXRob3V0IHNhY3JpZmljaW5nIHNwZWVkXG5cbiAgICB2YXIgaXNSZWN0ID0gZmFsc2UsXG4gICAgICAgIHJlY3RGaXJzdEVkZ2VUZXN0O1xuXG4gICAgaWYocHRzLmxlbmd0aCA9PT0gNSkge1xuICAgICAgICBpZihwdHNbMF1bMF0gPT09IHB0c1sxXVswXSkgeyAvLyB2ZXJ0LCBob3J6LCB2ZXJ0LCBob3J6XG4gICAgICAgICAgICBpZihwdHNbMl1bMF0gPT09IHB0c1szXVswXSAmJlxuICAgICAgICAgICAgICAgICAgICBwdHNbMF1bMV0gPT09IHB0c1szXVsxXSAmJlxuICAgICAgICAgICAgICAgICAgICBwdHNbMV1bMV0gPT09IHB0c1syXVsxXSkge1xuICAgICAgICAgICAgICAgIGlzUmVjdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmVjdEZpcnN0RWRnZVRlc3QgPSBmdW5jdGlvbihwdCkgeyByZXR1cm4gcHRbMF0gPT09IHB0c1swXVswXTsgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHB0c1swXVsxXSA9PT0gcHRzWzFdWzFdKSB7IC8vIGhvcnosIHZlcnQsIGhvcnosIHZlcnRcbiAgICAgICAgICAgIGlmKHB0c1syXVsxXSA9PT0gcHRzWzNdWzFdICYmXG4gICAgICAgICAgICAgICAgICAgIHB0c1swXVswXSA9PT0gcHRzWzNdWzBdICYmXG4gICAgICAgICAgICAgICAgICAgIHB0c1sxXVswXSA9PT0gcHRzWzJdWzBdKSB7XG4gICAgICAgICAgICAgICAgaXNSZWN0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZWN0Rmlyc3RFZGdlVGVzdCA9IGZ1bmN0aW9uKHB0KSB7IHJldHVybiBwdFsxXSA9PT0gcHRzWzBdWzFdOyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVjdENvbnRhaW5zKHB0LCBvbWl0Rmlyc3RFZGdlKSB7XG4gICAgICAgIHZhciB4ID0gcHRbMF0sXG4gICAgICAgICAgICB5ID0gcHRbMV07XG5cbiAgICAgICAgaWYoeCA9PT0gQkFETlVNIHx8IHggPCB4bWluIHx8IHggPiB4bWF4IHx8IHkgPT09IEJBRE5VTSB8fCB5IDwgeW1pbiB8fCB5ID4geW1heCkge1xuICAgICAgICAgICAgLy8gcHQgaXMgb3V0c2lkZSB0aGUgYm91bmRpbmcgYm94IG9mIHBvbHlnb25cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZihvbWl0Rmlyc3RFZGdlICYmIHJlY3RGaXJzdEVkZ2VUZXN0KHB0KSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbnRhaW5zKHB0LCBvbWl0Rmlyc3RFZGdlKSB7XG4gICAgICAgIHZhciB4ID0gcHRbMF0sXG4gICAgICAgICAgICB5ID0gcHRbMV07XG5cbiAgICAgICAgaWYoeCA9PT0gQkFETlVNIHx8IHggPCB4bWluIHx8IHggPiB4bWF4IHx8IHkgPT09IEJBRE5VTSB8fCB5IDwgeW1pbiB8fCB5ID4geW1heCkge1xuICAgICAgICAgICAgLy8gcHQgaXMgb3V0c2lkZSB0aGUgYm91bmRpbmcgYm94IG9mIHBvbHlnb25cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpbWF4ID0gcHRzLmxlbmd0aCxcbiAgICAgICAgICAgIHgxID0gcHRzWzBdWzBdLFxuICAgICAgICAgICAgeTEgPSBwdHNbMF1bMV0sXG4gICAgICAgICAgICBjcm9zc2luZ3MgPSAwLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIHgwLFxuICAgICAgICAgICAgeTAsXG4gICAgICAgICAgICB4bWluaSxcbiAgICAgICAgICAgIHljcm9zcztcblxuICAgICAgICBmb3IoaSA9IDE7IGkgPCBpbWF4OyBpKyspIHtcbiAgICAgICAgICAgIC8vIGZpbmQgYWxsIGNyb3NzaW5ncyBvZiBhIHZlcnRpY2FsIGxpbmUgdXB3YXJkIGZyb20gcHQgd2l0aFxuICAgICAgICAgICAgLy8gcG9seWdvbiBzZWdtZW50c1xuICAgICAgICAgICAgLy8gY3Jvc3NpbmdzIGV4YWN0bHkgYXQgeG1heCBkb24ndCBjb3VudCwgdW5sZXNzIHRoZSBwb2ludCBpc1xuICAgICAgICAgICAgLy8gZXhhY3RseSBvbiB0aGUgc2VnbWVudCwgdGhlbiBpdCBjb3VudHMgYXMgaW5zaWRlLlxuICAgICAgICAgICAgeDAgPSB4MTtcbiAgICAgICAgICAgIHkwID0geTE7XG4gICAgICAgICAgICB4MSA9IHB0c1tpXVswXTtcbiAgICAgICAgICAgIHkxID0gcHRzW2ldWzFdO1xuICAgICAgICAgICAgeG1pbmkgPSBNYXRoLm1pbih4MCwgeDEpO1xuXG4gICAgICAgICAgICAvLyBvdXRzaWRlIHRoZSBib3VuZGluZyBib3ggb2YgdGhpcyBzZWdtZW50LCBpdCdzIG9ubHkgYSBjcm9zc2luZ1xuICAgICAgICAgICAgLy8gaWYgaXQncyBiZWxvdyB0aGUgYm94LlxuICAgICAgICAgICAgaWYoeCA8IHhtaW5pIHx8IHggPiBNYXRoLm1heCh4MCwgeDEpIHx8IHkgPiBNYXRoLm1heCh5MCwgeTEpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHkgPCBNYXRoLm1pbih5MCwgeTEpKSB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgY291bnQgdGhlIGxlZnQtbW9zdCBwb2ludCBvZiB0aGUgc2VnbWVudCBhcyBhIGNyb3NzaW5nXG4gICAgICAgICAgICAgICAgLy8gYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIGRvdWJsZS1jb3VudCBhZGphY2VudCBjcm9zc2luZ3NcbiAgICAgICAgICAgICAgICAvLyBVTkxFU1MgdGhlIHBvbHlnb24gdHVybnMgcGFzdCB2ZXJ0aWNhbCBhdCBleGFjdGx5IHRoaXMgeFxuICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIGlzIHJlcGVhdGVkIGJlbG93LCBidXQgd2UgY2FuJ3QgZmFjdG9yIGl0IG91dFxuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2VcbiAgICAgICAgICAgICAgICBpZih4ICE9PSB4bWluaSkgY3Jvc3NpbmdzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpbnNpZGUgdGhlIGJvdW5kaW5nIGJveCwgY2hlY2sgdGhlIGFjdHVhbCBsaW5lIGludGVyY2VwdFxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gdmVydGljYWwgc2VnbWVudCAtIHdlIGtub3cgYWxyZWFkeSB0aGF0IHRoZSBwb2ludCBpcyBleGFjdGx5XG4gICAgICAgICAgICAgICAgLy8gb24gdGhlIHNlZ21lbnQsIHNvIG1hcmsgdGhlIGNyb3NzaW5nIGFzIGV4YWN0bHkgYXQgdGhlIHBvaW50LlxuICAgICAgICAgICAgICAgIGlmKHgxID09PSB4MCkgeWNyb3NzID0geTtcbiAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgYW5nbGVcbiAgICAgICAgICAgICAgICBlbHNlIHljcm9zcyA9IHkwICsgKHggLSB4MCkgKiAoeTEgLSB5MCkgLyAoeDEgLSB4MCk7XG5cbiAgICAgICAgICAgICAgICAvLyBleGFjdGx5IG9uIHRoZSBlZGdlOiBjb3VudHMgYXMgaW5zaWRlIHRoZSBwb2x5Z29uLCB1bmxlc3MgaXQncyB0aGVcbiAgICAgICAgICAgICAgICAvLyBmaXJzdCBlZGdlIGFuZCB3ZSdyZSBvbWl0dGluZyBpdC5cbiAgICAgICAgICAgICAgICBpZih5ID09PSB5Y3Jvc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaSA9PT0gMSAmJiBvbWl0Rmlyc3RFZGdlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHkgPD0geWNyb3NzICYmIHggIT09IHhtaW5pKSBjcm9zc2luZ3MrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIHdlJ3ZlIGdvdHRlbiB0aGlzIGZhciwgb2RkIGNyb3NzaW5ncyBtZWFucyBpbnNpZGUsIGV2ZW4gaXMgb3V0c2lkZVxuICAgICAgICByZXR1cm4gY3Jvc3NpbmdzICUgMiA9PT0gMTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3QgaWYgcG9seSBpcyBkZWdlbmVyYXRlXG4gICAgdmFyIGRlZ2VuZXJhdGUgPSB0cnVlO1xuICAgIHZhciBsYXN0UHQgPSBwdHNbMF07XG4gICAgZm9yKGkgPSAxOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGxhc3RQdFswXSAhPT0gcHRzW2ldWzBdIHx8IGxhc3RQdFsxXSAhPT0gcHRzW2ldWzFdKSB7XG4gICAgICAgICAgICBkZWdlbmVyYXRlID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHhtaW46IHhtaW4sXG4gICAgICAgIHhtYXg6IHhtYXgsXG4gICAgICAgIHltaW46IHltaW4sXG4gICAgICAgIHltYXg6IHltYXgsXG4gICAgICAgIHB0czogcHRzLFxuICAgICAgICBjb250YWluczogaXNSZWN0ID8gcmVjdENvbnRhaW5zIDogY29udGFpbnMsXG4gICAgICAgIGlzUmVjdDogaXNSZWN0LFxuICAgICAgICBkZWdlbmVyYXRlOiBkZWdlbmVyYXRlXG4gICAgfTtcbn07XG5cbi8qKlxuICogVGVzdCBpZiBhIHNlZ21lbnQgb2YgYSBwb2ludHMgYXJyYXkgaXMgYmVudCBvciBzdHJhaWdodFxuICpcbiAqIEBwYXJhbSBwdHMgQXJyYXkgb2YgW3gsIHldIHBhaXJzXG4gKiBAcGFyYW0gc3RhcnQgdGhlIGluZGV4IG9mIHRoZSBwcm9wb3NlZCBzdGFydCBvZiB0aGUgc3RyYWlnaHQgc2VjdGlvblxuICogQHBhcmFtIGVuZCB0aGUgaW5kZXggb2YgdGhlIHByb3Bvc2VkIGVuZCBwb2ludFxuICogQHBhcmFtIHRvbGVyYW5jZSB0aGUgbWF4IGRpc3RhbmNlIG9mZiB0aGUgbGluZSBjb25uZWN0aW5nIHN0YXJ0IGFuZCBlbmRcbiAqICAgICAgYmVmb3JlIHRoZSBsaW5lIGNvdW50cyBhcyBiZW50XG4gKiBAcmV0dXJucyBib29sZWFuOiB0cnVlIG1lYW5zIHRoaXMgc2VnbWVudCBpcyBiZW50LCBmYWxzZSBtZWFucyBzdHJhaWdodFxuICovXG52YXIgaXNCZW50ID0gcG9seWdvbi5pc1NlZ21lbnRCZW50ID0gZnVuY3Rpb24gaXNCZW50KHB0cywgc3RhcnQsIGVuZCwgdG9sZXJhbmNlKSB7XG4gICAgdmFyIHN0YXJ0UHQgPSBwdHNbc3RhcnRdLFxuICAgICAgICBzZWdtZW50ID0gW3B0c1tlbmRdWzBdIC0gc3RhcnRQdFswXSwgcHRzW2VuZF1bMV0gLSBzdGFydFB0WzFdXSxcbiAgICAgICAgc2VnbWVudFNxdWFyZWQgPSBkb3Qoc2VnbWVudCwgc2VnbWVudCksXG4gICAgICAgIHNlZ21lbnRMZW4gPSBNYXRoLnNxcnQoc2VnbWVudFNxdWFyZWQpLFxuICAgICAgICB1bml0UGVycCA9IFstc2VnbWVudFsxXSAvIHNlZ21lbnRMZW4sIHNlZ21lbnRbMF0gLyBzZWdtZW50TGVuXSxcbiAgICAgICAgaSxcbiAgICAgICAgcGFydCxcbiAgICAgICAgcGFydFBhcmFsbGVsO1xuXG4gICAgZm9yKGkgPSBzdGFydCArIDE7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgICBwYXJ0ID0gW3B0c1tpXVswXSAtIHN0YXJ0UHRbMF0sIHB0c1tpXVsxXSAtIHN0YXJ0UHRbMV1dO1xuICAgICAgICBwYXJ0UGFyYWxsZWwgPSBkb3QocGFydCwgc2VnbWVudCk7XG5cbiAgICAgICAgaWYocGFydFBhcmFsbGVsIDwgMCB8fCBwYXJ0UGFyYWxsZWwgPiBzZWdtZW50U3F1YXJlZCB8fFxuICAgICAgICAgICAgTWF0aC5hYnMoZG90KHBhcnQsIHVuaXRQZXJwKSkgPiB0b2xlcmFuY2UpIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIE1ha2UgYSBmaWx0ZXJpbmcgcG9seWdvbiwgdG8gbWluaW1pemUgdGhlIG51bWJlciBvZiBzZWdtZW50c1xuICpcbiAqIEBwYXJhbSBwdHMgQXJyYXkgb2YgW3gsIHldIHBhaXJzIChtdXN0IHN0YXJ0IHdpdGggYXQgbGVhc3QgMSBwYWlyKVxuICogQHBhcmFtIHRvbGVyYW5jZSB0aGUgbWF4aW11bSBkZXZpYXRpb24gZnJvbSBzdHJhaWdodCBhbGxvd2VkIGZvclxuICogICAgICByZW1vdmluZyBwb2ludHMgdG8gc2ltcGxpZnkgdGhlIHBvbHlnb25cbiAqXG4gKiBAcmV0dXJucyBPYmplY3Qge2FkZFB0LCByYXcsIGZpbHRlcmVkfVxuICogICAgICBhZGRQdCBpcyBhIGZ1bmN0aW9uKHB0OiBbeCwgeV0gcGFpcikgdG8gYWRkIGEgcmF3IHBvaW50IGFuZFxuICogICAgICAgICAgY29udGludWUgZmlsdGVyaW5nXG4gKiAgICAgIHJhdyBpcyBhbGwgdGhlIGlucHV0IHBvaW50c1xuICogICAgICBmaWx0ZXJlZCBpcyB0aGUgcmVzdWx0aW5nIGZpbHRlcmVkIEFycmF5IG9mIFt4LCB5XSBwYWlyc1xuICovXG5wb2x5Z29uLmZpbHRlciA9IGZ1bmN0aW9uIGZpbHRlcihwdHMsIHRvbGVyYW5jZSkge1xuICAgIHZhciBwdHNGaWx0ZXJlZCA9IFtwdHNbMF1dLFxuICAgICAgICBkb25lUmF3SW5kZXggPSAwLFxuICAgICAgICBkb25lRmlsdGVyZWRJbmRleCA9IDA7XG5cbiAgICBmdW5jdGlvbiBhZGRQdChwdCkge1xuICAgICAgICBwdHMucHVzaChwdCk7XG4gICAgICAgIHZhciBwcmV2RmlsdGVyTGVuID0gcHRzRmlsdGVyZWQubGVuZ3RoLFxuICAgICAgICAgICAgaUxhc3QgPSBkb25lUmF3SW5kZXg7XG4gICAgICAgIHB0c0ZpbHRlcmVkLnNwbGljZShkb25lRmlsdGVyZWRJbmRleCArIDEpO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IGlMYXN0ICsgMTsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoaSA9PT0gcHRzLmxlbmd0aCAtIDEgfHwgaXNCZW50KHB0cywgaUxhc3QsIGkgKyAxLCB0b2xlcmFuY2UpKSB7XG4gICAgICAgICAgICAgICAgcHRzRmlsdGVyZWQucHVzaChwdHNbaV0pO1xuICAgICAgICAgICAgICAgIGlmKHB0c0ZpbHRlcmVkLmxlbmd0aCA8IHByZXZGaWx0ZXJMZW4gLSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbmVSYXdJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGRvbmVGaWx0ZXJlZEluZGV4ID0gcHRzRmlsdGVyZWQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaUxhc3QgPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYocHRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdmFyIGxhc3RQdCA9IHB0cy5wb3AoKTtcbiAgICAgICAgYWRkUHQobGFzdFB0KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBhZGRQdDogYWRkUHQsXG4gICAgICAgIHJhdzogcHRzLFxuICAgICAgICBmaWx0ZXJlZDogcHRzRmlsdGVyZWRcbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNob3dOb1dlYkdsTXNnID0gcmVxdWlyZSgnLi9zaG93X25vX3dlYmdsX21zZycpO1xuXG4vLyBOb3RlIHRoYXQgdGhpcyBtb2R1bGUgc2hvdWxkIGJlIE9OTFkgcmVxdWlyZWQgaW50b1xuLy8gZmlsZXMgY29ycmVzcG9uZGluZyB0byByZWdsIHRyYWNlIG1vZHVsZXNcbi8vIHNvIHRoYXQgYnVuZGxlcyB3aXRoIG5vbi1yZWdsIG9ubHkgZG9uJ3QgaW5jbHVkZVxuLy8gcmVnbCBhbmQgYWxsIGl0cyBieXRlcy5cbnZhciBjcmVhdGVSZWdsID0gcmVxdWlyZSgncmVnbCcpO1xuXG4vKipcbiAqIElkZW1wb3RlbnQgdmVyc2lvbiBvZiBjcmVhdGVSZWdsLiBDcmVhdGUgcmVnbCBpbnN0YW5jZXNcbiAqIGluIHRoZSBjb3JyZWN0IGNhbnZhc2VzIHdpdGggdGhlIGNvcnJlY3QgYXR0cmlidXRlcyBhbmRcbiAqIG9wdGlvbnNcbiAqXG4gKiBAcGFyYW0ge0RPTSBub2RlIG9yIG9iamVjdH0gZ2QgOiBncmFwaCBkaXYgb2JqZWN0XG4gKiBAcGFyYW0ge2FycmF5fSBleHRlbnNpb25zIDogbGlzdCBvZiBleHRlbnNpb24gdG8gcGFzcyB0byBjcmVhdGVSZWdsXG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiBhbGwgY3JlYXRlUmVnbCBjYWxscyBzdWNjZWVkZWQsIGZhbHNlIG90aGVyd2lzZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHByZXBhcmVSZWdsKGdkLCBleHRlbnNpb25zKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VjY2VzcyA9IHRydWU7XG5cbiAgICBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgaWYoZC5yZWdsKSByZXR1cm47XG4gICAgICAgIC8vIG9ubHkgcGFyY29vcmRzIG5lZWRzIHBpY2sgbGF5ZXJcbiAgICAgICAgaWYoZC5waWNrICYmICFmdWxsTGF5b3V0Ll9oYXMoJ3BhcmNvb3JkcycpKSByZXR1cm47XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGQucmVnbCA9IGNyZWF0ZVJlZ2woe1xuICAgICAgICAgICAgICAgIGNhbnZhczogdGhpcyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGFudGlhbGlhczogIWQucGljayxcbiAgICAgICAgICAgICAgICAgICAgcHJlc2VydmVEcmF3aW5nQnVmZmVyOiB0cnVlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwaXhlbFJhdGlvOiBnZC5fY29udGV4dC5wbG90R2xQaXhlbFJhdGlvIHx8IGdsb2JhbC5kZXZpY2VQaXhlbFJhdGlvLFxuICAgICAgICAgICAgICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnMgfHwgW11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0bG9zdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYoZ2QgJiYgZ2QuZW1pdCkge1xuICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfd2ViZ2xjb250ZXh0bG9zdCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyOiBkLmtleVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmKCFzdWNjZXNzKSB7XG4gICAgICAgIHNob3dOb1dlYkdsTXNnKHtjb250YWluZXI6IGZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLm5vZGUoKX0pO1xuICAgIH1cbiAgICByZXR1cm4gc3VjY2Vzcztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogUHVzaCBhcnJheSB3aXRoIHVuaXF1ZSBpdGVtc1xuICpcbiAqIElnbm9yZXMgZmFsc3kgaXRlbXMsIGV4Y2VwdCAwIHNvIHdlIGNhbiB1c2UgaXQgdG8gY29uc3RydWN0IGFycmF5cyBvZiBpbmRpY2VzLlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGFycmF5XG4gKiAgYXJyYXkgdG8gYmUgZmlsbGVkXG4gKiBAcGFyYW0ge2FueX0gaXRlbVxuICogIGl0ZW0gdG8gYmUgb3Igbm90IHRvIGJlIGluc2VydGVkXG4gKiBAcmV0dXJuIHthcnJheX1cbiAqICByZWYgdG8gYXJyYXkgKG5vdyBwb3NzaWJseSBjb250YWluaW5nIG9uZSBtb3JlIGl0ZW0pXG4gKlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHB1c2hVbmlxdWUoYXJyYXksIGl0ZW0pIHtcbiAgICBpZihpdGVtIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgIHZhciBpdGVtU3RyID0gaXRlbS50b1N0cmluZygpLFxuICAgICAgICAgICAgaTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGFycmF5W2ldIGluc3RhbmNlb2YgUmVnRXhwICYmIGFycmF5W2ldLnRvU3RyaW5nKCkgPT09IGl0ZW1TdHIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXJyYXkucHVzaChpdGVtKTtcbiAgICB9XG4gICAgZWxzZSBpZigoaXRlbSB8fCBpdGVtID09PSAwKSAmJiBhcnJheS5pbmRleE9mKGl0ZW0pID09PSAtMSkgYXJyYXkucHVzaChpdGVtKTtcblxuICAgIHJldHVybiBhcnJheTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL3Bsb3RfYXBpL3Bsb3RfY29uZmlnJyk7XG5cblxuLyoqXG4gKiBDb3B5IGFyZyBhcnJheSAqd2l0aG91dCogcmVtb3ZpbmcgYHVuZGVmaW5lZGAgdmFsdWVzIGZyb20gb2JqZWN0cy5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSBhcmdzXG4gKiBAcmV0dXJucyB7QXJyYXl9XG4gKi9cbmZ1bmN0aW9uIGNvcHlBcmdBcnJheShnZCwgYXJncykge1xuICAgIHZhciBjb3B5ID0gW107XG4gICAgdmFyIGFyZztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFyZyA9IGFyZ3NbaV07XG5cbiAgICAgICAgaWYoYXJnID09PSBnZCkgY29weVtpXSA9IGFyZztcbiAgICAgICAgZWxzZSBpZih0eXBlb2YgYXJnID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgY29weVtpXSA9IEFycmF5LmlzQXJyYXkoYXJnKSA/XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZERlZXAoW10sIGFyZykgOlxuICAgICAgICAgICAgICAgIExpYi5leHRlbmREZWVwQWxsKHt9LCBhcmcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgY29weVtpXSA9IGFyZztcbiAgICB9XG5cbiAgICByZXR1cm4gY29weTtcbn1cblxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVW5kby9SZWRvIHF1ZXVlIGZvciBwbG90c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG52YXIgcXVldWUgPSB7fTtcblxuLy8gVE9ETzogZGlzYWJsZS9lbmFibGUgdW5kbyBhbmQgcmVkbyBidXR0b25zIGFwcHJvcHJpYXRlbHlcblxuLyoqXG4gKiBBZGQgYW4gaXRlbSB0byB0aGUgdW5kb1F1ZXVlIGZvciBhIGdyYXBoRGl2XG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0gdW5kb0Z1bmMgRnVuY3Rpb24gdW5kbyB0aGlzIG9wZXJhdGlvblxuICogQHBhcmFtIHVuZG9BcmdzIEFyZ3MgdG8gc3VwcGx5IHVuZG9GdW5jIHdpdGhcbiAqIEBwYXJhbSByZWRvRnVuYyBGdW5jdGlvbiB0byByZWRvIHRoaXMgb3BlcmF0aW9uXG4gKiBAcGFyYW0gcmVkb0FyZ3MgQXJncyB0byBzdXBwbHkgcmVkb0Z1bmMgd2l0aFxuICovXG5xdWV1ZS5hZGQgPSBmdW5jdGlvbihnZCwgdW5kb0Z1bmMsIHVuZG9BcmdzLCByZWRvRnVuYywgcmVkb0FyZ3MpIHtcbiAgICB2YXIgcXVldWVPYmosXG4gICAgICAgIHF1ZXVlSW5kZXg7XG5cbiAgICAvLyBtYWtlIHN1cmUgd2UgaGF2ZSB0aGUgcXVldWUgYW5kIG91ciBwb3NpdGlvbiBpbiBpdFxuICAgIGdkLnVuZG9RdWV1ZSA9IGdkLnVuZG9RdWV1ZSB8fCB7aW5kZXg6IDAsIHF1ZXVlOiBbXSwgc2VxdWVuY2U6IGZhbHNlfTtcbiAgICBxdWV1ZUluZGV4ID0gZ2QudW5kb1F1ZXVlLmluZGV4O1xuXG4gICAgLy8gaWYgd2UncmUgYWxyZWFkeSBwbGF5aW5nIGFuIHVuZG8gb3IgcmVkbywgb3IgaWYgdGhpcyBpcyBhbiBhdXRvIG9wZXJhdGlvblxuICAgIC8vIChsaWtlIHBhbmUgcmVzaXplLi4uIGFueSBvdGhlcnM/KSB0aGVuIHdlIGRvbid0IHNhdmUgdGhpcyB0byB0aGUgdW5kbyBxdWV1ZVxuICAgIGlmKGdkLmF1dG9wbGF5KSB7XG4gICAgICAgIGlmKCFnZC51bmRvUXVldWUuaW5TZXF1ZW5jZSkgZ2QuYXV0b3BsYXkgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGlmIHdlJ3JlIG5vdCBpbiBhIHNlcXVlbmNlIG9yIGFyZSBqdXN0IHN0YXJ0aW5nLCB3ZSBuZWVkIGEgbmV3IHF1ZXVlIGl0ZW1cbiAgICBpZighZ2QudW5kb1F1ZXVlLnNlcXVlbmNlIHx8IGdkLnVuZG9RdWV1ZS5iZWdpblNlcXVlbmNlKSB7XG4gICAgICAgIHF1ZXVlT2JqID0ge3VuZG86IHtjYWxsczogW10sIGFyZ3M6IFtdfSwgcmVkbzoge2NhbGxzOiBbXSwgYXJnczogW119fTtcbiAgICAgICAgZ2QudW5kb1F1ZXVlLnF1ZXVlLnNwbGljZShxdWV1ZUluZGV4LCBnZC51bmRvUXVldWUucXVldWUubGVuZ3RoIC0gcXVldWVJbmRleCwgcXVldWVPYmopO1xuICAgICAgICBnZC51bmRvUXVldWUuaW5kZXggKz0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBxdWV1ZU9iaiA9IGdkLnVuZG9RdWV1ZS5xdWV1ZVtxdWV1ZUluZGV4IC0gMV07XG4gICAgfVxuICAgIGdkLnVuZG9RdWV1ZS5iZWdpblNlcXVlbmNlID0gZmFsc2U7XG5cbiAgICAvLyB3ZSB1bnNoaWZ0IHRvIGhhbmRsZSBjYWxscyBmb3IgdW5kbyBpbiBhIGZvcndhcmQgZm9yIGxvb3AgbGF0ZXJcbiAgICBpZihxdWV1ZU9iaikge1xuICAgICAgICBxdWV1ZU9iai51bmRvLmNhbGxzLnVuc2hpZnQodW5kb0Z1bmMpO1xuICAgICAgICBxdWV1ZU9iai51bmRvLmFyZ3MudW5zaGlmdCh1bmRvQXJncyk7XG4gICAgICAgIHF1ZXVlT2JqLnJlZG8uY2FsbHMucHVzaChyZWRvRnVuYyk7XG4gICAgICAgIHF1ZXVlT2JqLnJlZG8uYXJncy5wdXNoKHJlZG9BcmdzKTtcbiAgICB9XG5cbiAgICBpZihnZC51bmRvUXVldWUucXVldWUubGVuZ3RoID4gY29uZmlnLnF1ZXVlTGVuZ3RoKSB7XG4gICAgICAgIGdkLnVuZG9RdWV1ZS5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICBnZC51bmRvUXVldWUuaW5kZXgtLTtcbiAgICB9XG59O1xuXG4vKipcbiAqIEJlZ2luIGEgc2VxdWVuY2Ugb2YgdW5kb1F1ZXVlIGNoYW5nZXNcbiAqXG4gKiBAcGFyYW0gZ2RcbiAqL1xucXVldWUuc3RhcnRTZXF1ZW5jZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QudW5kb1F1ZXVlID0gZ2QudW5kb1F1ZXVlIHx8IHtpbmRleDogMCwgcXVldWU6IFtdLCBzZXF1ZW5jZTogZmFsc2V9O1xuICAgIGdkLnVuZG9RdWV1ZS5zZXF1ZW5jZSA9IHRydWU7XG4gICAgZ2QudW5kb1F1ZXVlLmJlZ2luU2VxdWVuY2UgPSB0cnVlO1xufTtcblxuLyoqXG4gKiBTdG9wIGEgc2VxdWVuY2Ugb2YgdW5kb1F1ZXVlIGNoYW5nZXNcbiAqXG4gKiBDYWxsIHRoaXMgKmFmdGVyKiB5b3UncmUgc3VyZSB5b3VyIHVuZG8gY2hhaW4gaGFzIGVuZGVkXG4gKlxuICogQHBhcmFtIGdkXG4gKi9cbnF1ZXVlLnN0b3BTZXF1ZW5jZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QudW5kb1F1ZXVlID0gZ2QudW5kb1F1ZXVlIHx8IHtpbmRleDogMCwgcXVldWU6IFtdLCBzZXF1ZW5jZTogZmFsc2V9O1xuICAgIGdkLnVuZG9RdWV1ZS5zZXF1ZW5jZSA9IGZhbHNlO1xuICAgIGdkLnVuZG9RdWV1ZS5iZWdpblNlcXVlbmNlID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIE1vdmUgb25lIHN0ZXAgYmFjayBpbiB0aGUgdW5kbyBxdWV1ZSwgYW5kIHVuZG8gdGhlIG9iamVjdCB0aGVyZS5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqL1xucXVldWUudW5kbyA9IGZ1bmN0aW9uIHVuZG8oZ2QpIHtcbiAgICB2YXIgcXVldWVPYmosIGk7XG5cbiAgICBpZihnZC5mcmFtZXdvcmsgJiYgZ2QuZnJhbWV3b3JrLmlzUG9sYXIpIHtcbiAgICAgICAgZ2QuZnJhbWV3b3JrLnVuZG8oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZihnZC51bmRvUXVldWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgaXNOYU4oZ2QudW5kb1F1ZXVlLmluZGV4KSB8fFxuICAgICAgICAgICAgZ2QudW5kb1F1ZXVlLmluZGV4IDw9IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGluZGV4IGlzIHBvaW50aW5nIHRvIG5leHQgKmZvcndhcmQqIHF1ZXVlT2JqLCBwb2ludCB0byB0aGUgb25lIHdlJ3JlIHVuZG9pbmdcbiAgICBnZC51bmRvUXVldWUuaW5kZXgtLTtcblxuICAgIC8vIGdldCB0aGUgcXVldWVPYmogZm9yIGluc3RydWN0aW9ucyBvbiBob3cgdG8gdW5kb1xuICAgIHF1ZXVlT2JqID0gZ2QudW5kb1F1ZXVlLnF1ZXVlW2dkLnVuZG9RdWV1ZS5pbmRleF07XG5cbiAgICAvLyB0aGlzIHNlcXVlbmNlIGtlZXBzIHRoaW5ncyBmcm9tIGFkZGluZyB0byB0aGUgcXVldWUgZHVyaW5nIHVuZG8vcmVkb1xuICAgIGdkLnVuZG9RdWV1ZS5pblNlcXVlbmNlID0gdHJ1ZTtcbiAgICBmb3IoaSA9IDA7IGkgPCBxdWV1ZU9iai51bmRvLmNhbGxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHF1ZXVlLnBsb3REbyhnZCwgcXVldWVPYmoudW5kby5jYWxsc1tpXSwgcXVldWVPYmoudW5kby5hcmdzW2ldKTtcbiAgICB9XG4gICAgZ2QudW5kb1F1ZXVlLmluU2VxdWVuY2UgPSBmYWxzZTtcbiAgICBnZC5hdXRvcGxheSA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBSZWRvIHRoZSBjdXJyZW50IG9iamVjdCBpbiB0aGUgdW5kbywgdGhlbiBtb3ZlIGZvcndhcmQgaW4gdGhlIHF1ZXVlLlxuICpcbiAqIEBwYXJhbSBnZFxuICovXG5xdWV1ZS5yZWRvID0gZnVuY3Rpb24gcmVkbyhnZCkge1xuICAgIHZhciBxdWV1ZU9iaiwgaTtcblxuICAgIGlmKGdkLmZyYW1ld29yayAmJiBnZC5mcmFtZXdvcmsuaXNQb2xhcikge1xuICAgICAgICBnZC5mcmFtZXdvcmsucmVkbygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmKGdkLnVuZG9RdWV1ZSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICBpc05hTihnZC51bmRvUXVldWUuaW5kZXgpIHx8XG4gICAgICAgICAgICBnZC51bmRvUXVldWUuaW5kZXggPj0gZ2QudW5kb1F1ZXVlLnF1ZXVlLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZ2V0IHRoZSBxdWV1ZU9iaiBmb3IgaW5zdHJ1Y3Rpb25zIG9uIGhvdyB0byB1bmRvXG4gICAgcXVldWVPYmogPSBnZC51bmRvUXVldWUucXVldWVbZ2QudW5kb1F1ZXVlLmluZGV4XTtcblxuICAgIC8vIHRoaXMgc2VxdWVuY2Uga2VlcHMgdGhpbmdzIGZyb20gYWRkaW5nIHRvIHRoZSBxdWV1ZSBkdXJpbmcgdW5kby9yZWRvXG4gICAgZ2QudW5kb1F1ZXVlLmluU2VxdWVuY2UgPSB0cnVlO1xuICAgIGZvcihpID0gMDsgaSA8IHF1ZXVlT2JqLnJlZG8uY2FsbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcXVldWUucGxvdERvKGdkLCBxdWV1ZU9iai5yZWRvLmNhbGxzW2ldLCBxdWV1ZU9iai5yZWRvLmFyZ3NbaV0pO1xuICAgIH1cbiAgICBnZC51bmRvUXVldWUuaW5TZXF1ZW5jZSA9IGZhbHNlO1xuICAgIGdkLmF1dG9wbGF5ID0gZmFsc2U7XG5cbiAgICAvLyBpbmRleCBpcyBwb2ludGluZyB0byB0aGUgdGhpbmcgd2UganVzdCByZWRpZCwgbW92ZSBpdFxuICAgIGdkLnVuZG9RdWV1ZS5pbmRleCsrO1xufTtcblxuLyoqXG4gKiBDYWxsZWQgYnkgdW5kby9yZWRvIHRvIG1ha2UgdGhlIGFjdHVhbCBjaGFuZ2VzLlxuICpcbiAqIE5vdCBtZWFudCB0byBiZSBjYWxsZWQgcHVibGljYWxseSwgYnV0IGluY2x1ZGVkIGZvciBtb2NraW5nIG91dCBpbiB0ZXN0cy5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSBmdW5jXG4gKiBAcGFyYW0gYXJnc1xuICovXG5xdWV1ZS5wbG90RG8gPSBmdW5jdGlvbihnZCwgZnVuYywgYXJncykge1xuICAgIGdkLmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgIC8vIHRoaXMgKndvbid0KiBjb3B5IGdkIGFuZCBpdCBwcmVzZXJ2ZXMgYHVuZGVmaW5lZGAgcHJvcGVydGllcyFcbiAgICBhcmdzID0gY29weUFyZ0FycmF5KGdkLCBhcmdzKTtcblxuICAgIC8vIGNhbGwgdGhlIHN1cHBsaWVkIGZ1bmN0aW9uXG4gICAgZnVuYy5hcHBseShudWxsLCBhcmdzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcXVldWU7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBtYWtlIGEgcmVnZXggZm9yIG1hdGNoaW5nIGNvdW50ZXIgaWRzL25hbWVzIGllIHhheGlzLCB4YXhpczIsIHhheGlzMTAuLi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGVhZDogdGhlIGhlYWQgb2YgdGhlIHBhdHRlcm4sIGVnICd4JyBtYXRjaGVzICd4JywgJ3gyJywgJ3gxMCcgZXRjLlxuICogICAgICAneHknIGlzIGEgc3BlY2lhbCBjYXNlIGZvciBjYXJ0ZXNpYW4gc3VicGxvdHM6IGl0IG1hdGNoZXMgJ3gyeTMnIGV0Y1xuICogQHBhcmFtIHtPcHRpb25hbChzdHJpbmcpfSB0YWlsOiBhIGZpeGVkIHBpZWNlIGFmdGVyIHRoZSBpZFxuICogICAgICBlZyBjb3VudGVyUmVnZXgoJ3NjZW5lJywgJy5hbm5vdGF0aW9ucycpIGZvciBzY2VuZTIuYW5ub3RhdGlvbnMgZXRjLlxuICogQHBhcmFtIHtib29sZWFufSBvcGVuRW5kZWQ6IGlmIHRydWUsIHRoZSBzdHJpbmcgbWF5IGNvbnRpbnVlIHBhc3QgdGhlIG1hdGNoLlxuICovXG5leHBvcnRzLmNvdW50ZXIgPSBmdW5jdGlvbihoZWFkLCB0YWlsLCBvcGVuRW5kZWQpIHtcbiAgICB2YXIgZnVsbFRhaWwgPSAodGFpbCB8fCAnJykgKyAob3BlbkVuZGVkID8gJycgOiAnJCcpO1xuICAgIGlmKGhlYWQgPT09ICd4eScpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoJ154KFsyLTldfFsxLTldWzAtOV0rKT95KFsyLTldfFsxLTldWzAtOV0rKT8nICsgZnVsbFRhaWwpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFJlZ0V4cCgnXicgKyBoZWFkICsgJyhbMi05XXxbMS05XVswLTldKyk/JyArIGZ1bGxUYWlsKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gQVNDRU5EOiBjaG9wIG9mZiB0aGUgbGFzdCBuZXN0aW5nIGxldmVsIC0gZWl0aGVyIFs8bj5dIG9yIC48a2V5PiAtIHRvIGFzY2VuZFxuLy8gdGhlIGF0dHJpYnV0ZSB0cmVlLiB0aGUgcmVtYWluaW5nIGF0dHJTdHJpbmcgaXMgaW4gbWF0Y2hbMV1cbnZhciBBU0NFTkQgPSAvXiguKikoXFwuW15cXC5cXFtcXF1dK3xcXFtcXGRcXF0pJC87XG5cbi8vIFNJTVBMRUFUVFI6IGlzIHRoaXMgYW4gdW4tbmVzdGVkIGF0dHJpYnV0ZT8gKG5vIGRvdHMgb3IgYnJhY2tldHMpXG52YXIgU0lNUExFQVRUUiA9IC9eW15cXC5cXFtcXF1dKyQvO1xuXG4vKlxuICogY2FsY3VsYXRlIGEgcmVsYXRpdmUgYXR0cmlidXRlIHN0cmluZywgc2ltaWxhciB0byBhIHJlbGF0aXZlIHBhdGhcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZUF0dHI6XG4gKiAgIGFuIGF0dHJpYnV0ZSBzdHJpbmcsIHN1Y2ggYXMgJ2Fubm90YXRpb25zWzNdLngnLiBUaGUgXCJjdXJyZW50IGxvY2F0aW9uXCJcbiAqICAgaXMgdGhlIGF0dHJpYnV0ZSBzdHJpbmcgbWludXMgdGhlIGxhc3QgY29tcG9uZW50ICgnYW5ub3RhdGlvbnNbM10nKVxuICogQHBhcmFtIHtzdHJpbmd9IHJlbGF0aXZlQXR0cjpcbiAqICAgYSByb3V0ZSB0byB0aGUgZGVzaXJlZCBhdHRyaWJ1dGUgc3RyaW5nLCB1c2luZyAnXicgdG8gYXNjZW5kXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBhdHRyU3RyaW5nOlxuICogICBmb3IgZXhhbXBsZTpcbiAqICAgICByZWxhdGl2ZUF0dHIoJ2Fubm90YXRpb25zWzNdLngnLCAneScpID0gJ2Fubm90YXRpb25zWzNdLnknXG4gKiAgICAgcmVsYXRpdmVBdHRyKCdhbm5vdGF0aW9uc1szXS54JywgJ15bMl0ueicpID0gJ2Fubm90YXRpb25zWzJdLnonXG4gKiAgICAgcmVsYXRpdmVBdHRyKCdhbm5vdGF0aW9uc1szXS54JywgJ15ebWFyZ2luJykgPSAnbWFyZ2luJ1xuICogICAgIHJlbGF0aXZlQXR0cignYW5ub3RhdGlvbnNbM10ueCcsICdeXm1hcmdpbi5yJykgPSAnbWFyZ2luLnInXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYmFzZUF0dHIsIHJlbGF0aXZlQXR0cikge1xuICAgIHdoaWxlKHJlbGF0aXZlQXR0cikge1xuICAgICAgICB2YXIgbWF0Y2ggPSBiYXNlQXR0ci5tYXRjaChBU0NFTkQpO1xuXG4gICAgICAgIGlmKG1hdGNoKSBiYXNlQXR0ciA9IG1hdGNoWzFdO1xuICAgICAgICBlbHNlIGlmKGJhc2VBdHRyLm1hdGNoKFNJTVBMRUFUVFIpKSBiYXNlQXR0ciA9ICcnO1xuICAgICAgICBlbHNlIHRocm93IG5ldyBFcnJvcignYmFkIHJlbGF0aXZlQXR0ciBjYWxsOicgKyBbYmFzZUF0dHIsIHJlbGF0aXZlQXR0cl0pO1xuXG4gICAgICAgIGlmKHJlbGF0aXZlQXR0ci5jaGFyQXQoMCkgPT09ICdeJykgcmVsYXRpdmVBdHRyID0gcmVsYXRpdmVBdHRyLnNsaWNlKDEpO1xuICAgICAgICBlbHNlIGJyZWFrO1xuICAgIH1cblxuICAgIGlmKGJhc2VBdHRyICYmIHJlbGF0aXZlQXR0ci5jaGFyQXQoMCkgIT09ICdbJykge1xuICAgICAgICByZXR1cm4gYmFzZUF0dHIgKyAnLicgKyByZWxhdGl2ZUF0dHI7XG4gICAgfVxuICAgIHJldHVybiBiYXNlQXR0ciArIHJlbGF0aXZlQXR0cjtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSByZXF1aXJlKCcuL2FycmF5JykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBpc1BsYWluT2JqZWN0ID0gcmVxdWlyZSgnLi9pc19wbGFpbl9vYmplY3QnKTtcblxuLyoqXG4gKiBSZWxpbmsgcHJpdmF0ZSBfa2V5cyBhbmQga2V5cyB3aXRoIGEgZnVuY3Rpb24gdmFsdWUgZnJvbSBvbmUgY29udGFpbmVyXG4gKiB0byB0aGUgbmV3IGNvbnRhaW5lci5cbiAqIFJlbGluayBtZWFucyBjb3B5aW5nIGlmIG9iamVjdCBpcyBwYXNzLWJ5LXZhbHVlIGFuZCBhZGRpbmcgYSByZWZlcmVuY2VcbiAqIGlmIG9iamVjdCBpcyBwYXNzLWJ5LXJlZi5cbiAqIFRoaXMgcHJldmVudHMgZGVlcENvcHlpbmcgbWFzc2l2ZSBzdHJ1Y3R1cmVzIGxpa2UgYSB3ZWJnbCBjb250ZXh0LlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHJlbGlua1ByaXZhdGVLZXlzKHRvQ29udGFpbmVyLCBmcm9tQ29udGFpbmVyKSB7XG4gICAgZm9yKHZhciBrIGluIGZyb21Db250YWluZXIpIHtcbiAgICAgICAgdmFyIGZyb21WYWwgPSBmcm9tQ29udGFpbmVyW2tdO1xuICAgICAgICB2YXIgdG9WYWwgPSB0b0NvbnRhaW5lcltrXTtcblxuICAgICAgICBpZih0b1ZhbCA9PT0gZnJvbVZhbCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYoay5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2YgZnJvbVZhbCA9PT0gJ2Z1bmN0aW9uJykge1xuXG4gICAgICAgICAgICAvLyBpZiBpdCBhbHJlYWR5IGV4aXN0cyBhdCB0aGlzIHBvaW50LCBpdCdzIHNvbWV0aGluZ1xuICAgICAgICAgICAgLy8gdGhhdCB3ZSByZWNyZWF0ZSBlYWNoIHRpbWUgYXJvdW5kLCBzbyBpZ25vcmUgaXRcbiAgICAgICAgICAgIGlmKGsgaW4gdG9Db250YWluZXIpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB0b0NvbnRhaW5lcltrXSA9IGZyb21WYWw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihpc0FycmF5T3JUeXBlZEFycmF5KGZyb21WYWwpICYmIGlzQXJyYXlPclR5cGVkQXJyYXkodG9WYWwpICYmIGlzUGxhaW5PYmplY3QoZnJvbVZhbFswXSkpIHtcblxuICAgICAgICAgICAgLy8gZmlsdGVyIG91dCBkYXRhX2FycmF5IGl0ZW1zIHRoYXQgY2FuIGNvbnRhaW4gdXNlciBvYmplY3RzXG4gICAgICAgICAgICAvLyBtb3N0IG9mIHRoZSB0aW1lIHRoZSB0b1ZhbCA9PT0gZnJvbVZhbCBjaGVjayB3aWxsIGNhdGNoIHRoZXNlIGVhcmx5XG4gICAgICAgICAgICAvLyBidXQgaWYgdGhlIHVzZXIgbWFrZXMgbmV3IG9uZXMgd2UgYWxzbyBkb24ndCB3YW50IHRvIHJlY3Vyc2UgaW4uXG4gICAgICAgICAgICBpZihrID09PSAnY3VzdG9tZGF0YScgfHwgayA9PT0gJ2lkcycpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyByZWN1cnNlIGludG8gYXJyYXlzIGNvbnRhaW5lcnNcbiAgICAgICAgICAgIHZhciBtaW5MZW4gPSBNYXRoLm1pbihmcm9tVmFsLmxlbmd0aCwgdG9WYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBtaW5MZW47IGorKykge1xuICAgICAgICAgICAgICAgIGlmKCh0b1ZhbFtqXSAhPT0gZnJvbVZhbFtqXSkgJiYgaXNQbGFpbk9iamVjdChmcm9tVmFsW2pdKSAmJiBpc1BsYWluT2JqZWN0KHRvVmFsW2pdKSkge1xuICAgICAgICAgICAgICAgICAgICByZWxpbmtQcml2YXRlS2V5cyh0b1ZhbFtqXSwgZnJvbVZhbFtqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoaXNQbGFpbk9iamVjdChmcm9tVmFsKSAmJiBpc1BsYWluT2JqZWN0KHRvVmFsKSkge1xuXG4gICAgICAgICAgICAvLyByZWN1cnNlIGludG8gb2JqZWN0cywgYnV0IG9ubHkgaWYgdGhleSBzdGlsbCBleGlzdFxuICAgICAgICAgICAgcmVsaW5rUHJpdmF0ZUtleXModG9WYWwsIGZyb21WYWwpO1xuXG4gICAgICAgICAgICBpZighT2JqZWN0LmtleXModG9WYWwpLmxlbmd0aCkgZGVsZXRlIHRvQ29udGFpbmVyW2tdO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciBsb2dnZXJzID0gcmVxdWlyZSgnLi9sb2dnZXJzJyk7XG52YXIgaWRlbnRpdHkgPSByZXF1aXJlKCcuL2lkZW50aXR5Jyk7XG5cbi8vIGRvbid0IHRydXN0IGZsb2F0aW5nIHBvaW50IGVxdWFsaXR5IC0gZnJhY3Rpb24gb2YgYmluIHNpemUgdG8gY2FsbFxuLy8gXCJvbiB0aGUgbGluZVwiIGFuZCBlbnN1cmUgdGhhdCB0aGV5IGdvIHRoZSByaWdodCB3YXkgc3BlY2lmaWVkIGJ5XG4vLyBsaW5lbG93XG52YXIgcm91bmRpbmdFcnJvciA9IDFlLTk7XG5cblxuLyoqXG4gKiBmaW5kQmluIC0gZmluZCB0aGUgYmluIGZvciB2YWwgLSBub3RlIHRoYXQgaXQgY2FuIHJldHVybiBvdXRzaWRlIHRoZVxuICogYmluIHJhbmdlIGFueSBwb3MuIG9yIG5lZy4gaW50ZWdlciBmb3IgbGluZWFyIGJpbnMsIG9yIC0xIG9yXG4gKiBiaW5zLmxlbmd0aC0xIGZvciBleHBsaWNpdC5cbiAqIGJpbnMgaXMgZWl0aGVyIGFuIG9iamVjdCB7c3RhcnQsc2l6ZSxlbmR9IG9yIGFuIGFycmF5IGxlbmd0aCAjYmlucysxXG4gKiBiaW5zIGNhbiBiZSBlaXRoZXIgaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIGJ1dCBtdXN0IGJlIG1vbm90b25pY1xuICogZm9yIGxpbmVhciBiaW5zLCB3ZSBjYW4ganVzdCBjYWxjdWxhdGUuIEZvciBsaXN0ZWQgYmlucywgcnVuIGEgYmluYXJ5XG4gKiBzZWFyY2ggbGluZWxvdyAodHJ1dGh5KSBzYXlzIHRoZSBiaW4gYm91bmRhcnkgc2hvdWxkIGJlIGF0dHJpYnV0ZWQgdG9cbiAqIHRoZSBsb3dlciBiaW4gcmF0aGVyIHRoYW4gdGhlIGRlZmF1bHQgdXBwZXIgYmluXG4gKi9cbmV4cG9ydHMuZmluZEJpbiA9IGZ1bmN0aW9uKHZhbCwgYmlucywgbGluZWxvdykge1xuICAgIGlmKGlzTnVtZXJpYyhiaW5zLnN0YXJ0KSkge1xuICAgICAgICByZXR1cm4gbGluZWxvdyA/XG4gICAgICAgICAgICBNYXRoLmNlaWwoKHZhbCAtIGJpbnMuc3RhcnQpIC8gYmlucy5zaXplIC0gcm91bmRpbmdFcnJvcikgLSAxIDpcbiAgICAgICAgICAgIE1hdGguZmxvb3IoKHZhbCAtIGJpbnMuc3RhcnQpIC8gYmlucy5zaXplICsgcm91bmRpbmdFcnJvcik7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgbjEgPSAwO1xuICAgICAgICB2YXIgbjIgPSBiaW5zLmxlbmd0aDtcbiAgICAgICAgdmFyIGMgPSAwO1xuICAgICAgICB2YXIgYmluU2l6ZSA9IChuMiA+IDEpID8gKGJpbnNbbjIgLSAxXSAtIGJpbnNbMF0pIC8gKG4yIC0gMSkgOiAxO1xuICAgICAgICB2YXIgbiwgdGVzdDtcbiAgICAgICAgaWYoYmluU2l6ZSA+PSAwKSB7XG4gICAgICAgICAgICB0ZXN0ID0gbGluZWxvdyA/IGxlc3NUaGFuIDogbGVzc09yRXF1YWw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZXN0ID0gbGluZWxvdyA/IGdyZWF0ZXJPckVxdWFsIDogZ3JlYXRlclRoYW47XG4gICAgICAgIH1cbiAgICAgICAgdmFsICs9IGJpblNpemUgKiByb3VuZGluZ0Vycm9yICogKGxpbmVsb3cgPyAtMSA6IDEpICogKGJpblNpemUgPj0gMCA/IDEgOiAtMSk7XG4gICAgICAgIC8vIGMgaXMganVzdCB0byBhdm9pZCBpbmZpbml0ZSBsb29wcyBpZiB0aGVyZSdzIGFuIGVycm9yXG4gICAgICAgIHdoaWxlKG4xIDwgbjIgJiYgYysrIDwgMTAwKSB7XG4gICAgICAgICAgICBuID0gTWF0aC5mbG9vcigobjEgKyBuMikgLyAyKTtcbiAgICAgICAgICAgIGlmKHRlc3QoYmluc1tuXSwgdmFsKSkgbjEgPSBuICsgMTtcbiAgICAgICAgICAgIGVsc2UgbjIgPSBuO1xuICAgICAgICB9XG4gICAgICAgIGlmKGMgPiA5MCkgbG9nZ2Vycy5sb2coJ0xvbmcgYmluYXJ5IHNlYXJjaC4uLicpO1xuICAgICAgICByZXR1cm4gbjEgLSAxO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGxlc3NUaGFuKGEsIGIpIHsgcmV0dXJuIGEgPCBiOyB9XG5mdW5jdGlvbiBsZXNzT3JFcXVhbChhLCBiKSB7IHJldHVybiBhIDw9IGI7IH1cbmZ1bmN0aW9uIGdyZWF0ZXJUaGFuKGEsIGIpIHsgcmV0dXJuIGEgPiBiOyB9XG5mdW5jdGlvbiBncmVhdGVyT3JFcXVhbChhLCBiKSB7IHJldHVybiBhID49IGI7IH1cblxuZXhwb3J0cy5zb3J0ZXJBc2MgPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhIC0gYjsgfTtcbmV4cG9ydHMuc29ydGVyRGVzID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYiAtIGE7IH07XG5cbi8qKlxuICogZmluZCBkaXN0aW5jdCB2YWx1ZXMgaW4gYW4gYXJyYXksIGx1bXBpbmcgdG9nZXRoZXIgb25lcyB0aGF0IGFwcGVhciB0b1xuICoganVzdCBiZSBvZmYgYnkgYSByb3VuZGluZyBlcnJvclxuICogcmV0dXJuIHRoZSBkaXN0aW5jdCB2YWx1ZXMgYW5kIHRoZSBtaW5pbXVtIGRpZmZlcmVuY2UgYmV0d2VlbiBhbnkgdHdvXG4gKi9cbmV4cG9ydHMuZGlzdGluY3RWYWxzID0gZnVuY3Rpb24odmFsc0luKSB7XG4gICAgdmFyIHZhbHMgPSB2YWxzSW4uc2xpY2UoKTsgIC8vIG90aGVyd2lzZSB3ZSBzb3J0IHRoZSBvcmlnaW5hbCBhcnJheS4uLlxuICAgIHZhbHMuc29ydChleHBvcnRzLnNvcnRlckFzYyk7XG5cbiAgICB2YXIgbCA9IHZhbHMubGVuZ3RoIC0gMSxcbiAgICAgICAgbWluRGlmZiA9ICh2YWxzW2xdIC0gdmFsc1swXSkgfHwgMSxcbiAgICAgICAgZXJyRGlmZiA9IG1pbkRpZmYgLyAobCB8fCAxKSAvIDEwMDAwLFxuICAgICAgICB2MiA9IFt2YWxzWzBdXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgLy8gbWFrZSBzdXJlIHZhbHVlcyBhcmVuJ3QganVzdCBvZmYgYnkgYSByb3VuZGluZyBlcnJvclxuICAgICAgICBpZih2YWxzW2kgKyAxXSA+IHZhbHNbaV0gKyBlcnJEaWZmKSB7XG4gICAgICAgICAgICBtaW5EaWZmID0gTWF0aC5taW4obWluRGlmZiwgdmFsc1tpICsgMV0gLSB2YWxzW2ldKTtcbiAgICAgICAgICAgIHYyLnB1c2godmFsc1tpICsgMV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHt2YWxzOiB2MiwgbWluRGlmZjogbWluRGlmZn07XG59O1xuXG4vKipcbiAqIHJldHVybiB0aGUgc21hbGxlc3QgZWxlbWVudCBmcm9tIChzb3J0ZWQpIGFycmF5IGFycmF5SW4gdGhhdCdzIGJpZ2dlciB0aGFuIHZhbCxcbiAqIG9yIChyZXZlcnNlKSB0aGUgbGFyZ2VzdCBlbGVtZW50IHNtYWxsZXIgdGhhbiB2YWxcbiAqIHVzZWQgdG8gZmluZCB0aGUgYmVzdCB0aWNrIGdpdmVuIHRoZSBtaW5pbXVtIChub24tcm91bmRlZCkgdGlja1xuICogcGFydGljdWxhcmx5IHVzZWZ1bCBmb3IgZGF0ZS90aW1lIHdoZXJlIHRoaW5ncyBhcmUgbm90IHBvd2VycyBvZiAxMFxuICogYmluYXJ5IHNlYXJjaCBpcyBwcm9iYWJseSBvdmVya2lsbCBoZXJlLi4uXG4gKi9cbmV4cG9ydHMucm91bmRVcCA9IGZ1bmN0aW9uKHZhbCwgYXJyYXlJbiwgcmV2ZXJzZSkge1xuICAgIHZhciBsb3cgPSAwLFxuICAgICAgICBoaWdoID0gYXJyYXlJbi5sZW5ndGggLSAxLFxuICAgICAgICBtaWQsXG4gICAgICAgIGMgPSAwLFxuICAgICAgICBkbG93ID0gcmV2ZXJzZSA/IDAgOiAxLFxuICAgICAgICBkaGlnaCA9IHJldmVyc2UgPyAxIDogMCxcbiAgICAgICAgcm91bmRlZCA9IHJldmVyc2UgPyBNYXRoLmNlaWwgOiBNYXRoLmZsb29yO1xuICAgIC8vIGMgaXMganVzdCB0byBhdm9pZCBpbmZpbml0ZSBsb29wcyBpZiB0aGVyZSdzIGFuIGVycm9yXG4gICAgd2hpbGUobG93IDwgaGlnaCAmJiBjKysgPCAxMDApIHtcbiAgICAgICAgbWlkID0gcm91bmRlZCgobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgICAgaWYoYXJyYXlJblttaWRdIDw9IHZhbCkgbG93ID0gbWlkICsgZGxvdztcbiAgICAgICAgZWxzZSBoaWdoID0gbWlkIC0gZGhpZ2g7XG4gICAgfVxuICAgIHJldHVybiBhcnJheUluW2xvd107XG59O1xuXG4vKipcbiAqIFR3ZWFrIHRvIEFycmF5LnNvcnQoc29ydEZuKSB0aGF0IGltcHJvdmVzIHBlcmZvcm1hbmNlIGZvciBwcmUtc29ydGVkIGFycmF5c1xuICpcbiAqIE5vdGUgdGhhdCBuZXdlciBicm93c2VycyAoc3VjaCBhcyBDaHJvbWUgdjcwKykgYXJlIHN0YXJ0aW5nIHRvIHBpY2sgdXBcbiAqIG9uIHByZS1zb3J0ZWQgYXJyYXlzIHdoaWNoIG1heSByZW5kZXIgdGhlIGZvbGxvd2luZyBvcHRpbWl6YXRpb24gdW5uZWNlc3NhcnlcbiAqIGluIHRoZSBmdXR1cmUuXG4gKlxuICogTW90aXZhdGlvbjogc29tZXRpbWVzIHdlIG5lZWQgdG8gc29ydCBhcnJheXMgYnV0IHRoZSBpbnB1dCBpcyBsaWtlbHkgdG9cbiAqIGFscmVhZHkgYmUgc29ydGVkLiBCcm93c2VycyBkb24ndCBzZWVtIHRvIHBpY2sgdXAgb24gcHJlLXNvcnRlZCBhcnJheXMsXG4gKiBhbmQgaW4gZmFjdCBDaHJvbWUgaXMgYWN0dWFsbHkgKnNsb3dlciogc29ydGluZyBwcmUtc29ydGVkIGFycmF5cyB0aGFuIHB1cmVseVxuICogcmFuZG9tIGFycmF5cy4gRkYgaXMgYXQgbGVhc3QgZmFzdGVyIGlmIHRoZSBhcnJheSBpcyBwcmUtc29ydGVkLCBidXQgc3RpbGxcbiAqIG5vdCBhcyBmYXN0IGFzIGl0IGNvdWxkIGJlLlxuICogSGVyZSdzIGhvdyB0aGlzIHBsYXlzIG91dCBzb3J0aW5nIGEgbGVuZ3RoLTFlNiBhcnJheTpcbiAqXG4gKiBDYWxscyB0byBTb3J0IEZOICB8ICBDaHJvbWUgYmFyZSAgfCAgRkYgYmFyZSAgfCAgQ2hyb21lIHR3ZWFrICB8ICBGRiB0d2Vha1xuICogICAgICAgICAgICAgICAgICAgfCAgdjY4LjAgTWFjICAgIHwgIHY2MS4wIE1hY3wgICAgICAgICAgICAgICAgfFxuICogLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLVxuICogb3JkZXJlZCAgICAgICAgICAgfCAgMzAuNGU2ICAgICAgIHwgIDEwLjFlNiAgIHwgIDFlNiAgICAgICAgICAgfCAgMWU2XG4gKiByZXZlcnNlZCAgICAgICAgICB8ICAyOS40ZTYgICAgICAgfCAgOS45ZTYgICAgfCAgMWU2ICsgcmV2ZXJzZSB8ICAxZTYgKyByZXZlcnNlXG4gKiByYW5kb20gICAgICAgICAgICB8ICB+MjFlNiAgICAgICAgfCAgfjE4LjdlNiAgfCAgfjIxZTYgICAgICAgICB8ICB+MTguN2U2XG4gKlxuICogU28gdGhpcyBpcyBhIHN1YnN0YW50aWFsIHdpbiBmb3IgcHJlLXNvcnRlZCAob3JkZXJlZCBvciBleGFjdGx5IHJldmVyc2VkKVxuICogYXJyYXlzLiBJbmNsdWRpbmcgdGhpcyB3cmFwcGVyIG9uIGFuIHVuc29ydGVkIGFycmF5IGFkZHMgYSBwZW5hbHR5IHRoYXQgd2lsbFxuICogaW4gZ2VuZXJhbCBiZSBvbmx5IGEgZmV3IGNhbGxzIHRvIHRoZSBzb3J0IGZ1bmN0aW9uLiBUaGUgb25seSBjYXNlIHRoaXNcbiAqIHBlbmFsdHkgd2lsbCBiZSBzaWduaWZpY2FudCBpcyBpZiB0aGUgYXJyYXkgaXMgbW9zdGx5IHNvcnRlZCBidXQgdGhlcmUgYXJlXG4gKiBhIGZldyB1bnNvcnRlZCBpdGVtcyBuZWFyIHRoZSBlbmQsIGJ1dCB0aGUgcGVuYWx0eSBpcyBzdGlsbCBhdCBtb3N0IE4gY2FsbHNcbiAqIG91dCBvZiAoZm9yIE49MWU2KSB+MjBOIHRvdGFsIGNhbGxzXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYXJyYXk6IHRoZSBhcnJheSwgdG8gYmUgc29ydGVkIGluIHBsYWNlXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBzb3J0Rm46IEFzIGluIEFycmF5LnNvcnQsIGZ1bmN0aW9uKGEsIGIpIHRoYXQgcHV0c1xuICogICAgIGl0ZW0gYSBiZWZvcmUgaXRlbSBiIGlmIHRoZSByZXR1cm4gaXMgbmVnYXRpdmUsIGEgYWZ0ZXIgYiBpZiBwb3NpdGl2ZSxcbiAqICAgICBhbmQgbm8gY2hhbmdlIGlmIHplcm8uXG4gKiBAcmV0dXJuIHtBcnJheX06IHRoZSBvcmlnaW5hbCBhcnJheSwgc29ydGVkIGluIHBsYWNlLlxuICovXG5leHBvcnRzLnNvcnQgPSBmdW5jdGlvbihhcnJheSwgc29ydEZuKSB7XG4gICAgdmFyIG5vdE9yZGVyZWQgPSAwO1xuICAgIHZhciBub3RSZXZlcnNlZCA9IDA7XG4gICAgZm9yKHZhciBpID0gMTsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwYWlyT3JkZXIgPSBzb3J0Rm4oYXJyYXlbaV0sIGFycmF5W2kgLSAxXSk7XG4gICAgICAgIGlmKHBhaXJPcmRlciA8IDApIG5vdE9yZGVyZWQgPSAxO1xuICAgICAgICBlbHNlIGlmKHBhaXJPcmRlciA+IDApIG5vdFJldmVyc2VkID0gMTtcbiAgICAgICAgaWYobm90T3JkZXJlZCAmJiBub3RSZXZlcnNlZCkgcmV0dXJuIGFycmF5LnNvcnQoc29ydEZuKTtcbiAgICB9XG4gICAgcmV0dXJuIG5vdFJldmVyc2VkID8gYXJyYXkgOiBhcnJheS5yZXZlcnNlKCk7XG59O1xuXG4vKipcbiAqIGZpbmQgaW5kZXggaW4gYXJyYXkgJ2FycicgdGhhdCBtaW5pbWl6ZXMgJ2ZuJ1xuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGFyciA6IGFycmF5IHdoZXJlIHRvIHNlYXJjaFxuICogQHBhcmFtIHtmbiAob3B0aW9uYWwpfSBmbiA6IGZ1bmN0aW9uIHRvIG1pbmltaXplLFxuICogICBpZiBub3QgZ2l2ZW4sIGZuIGlzIHRoZSBpZGVudGl0eSBmdW5jdGlvblxuICogQHJldHVybiB7aW50ZWdlcn1cbiAqL1xuZXhwb3J0cy5maW5kSW5kZXhPZk1pbiA9IGZ1bmN0aW9uKGFyciwgZm4pIHtcbiAgICBmbiA9IGZuIHx8IGlkZW50aXR5O1xuXG4gICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgIHZhciBpbmQ7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB2ID0gZm4oYXJyW2ldKTtcbiAgICAgICAgaWYodiA8IG1pbikge1xuICAgICAgICAgICAgbWluID0gdjtcbiAgICAgICAgICAgIGluZCA9IGk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gd29ya3Mgd2l0aCBvdXIgQ1NTIGN1cnNvciBjbGFzc2VzIChzZWUgY3NzL19jdXJzb3Iuc2Nzcylcbi8vIHRvIGFwcGx5IGN1cnNvcnMgdG8gZDMgc2luZ2xlLWVsZW1lbnQgc2VsZWN0aW9ucy5cbi8vIG9taXQgY3Vyc29yIHRvIHJldmVydCB0byB0aGUgZGVmYXVsdC5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2V0Q3Vyc29yKGVsMywgY3NyKSB7XG4gICAgKGVsMy5hdHRyKCdjbGFzcycpIHx8ICcnKS5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xzKSB7XG4gICAgICAgIGlmKGNscy5pbmRleE9mKCdjdXJzb3ItJykgPT09IDApIGVsMy5jbGFzc2VkKGNscywgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaWYoY3NyKSBlbDMuY2xhc3NlZCgnY3Vyc29yLScgKyBjc3IsIHRydWUpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciBub29wID0gZnVuY3Rpb24oKSB7fTtcblxuXG4vKipcbiAqIFByaW50cyBhIG5vIHdlYmdsIGVycm9yIG1lc3NhZ2UgaW50byB0aGUgc2NlbmUgY29udGFpbmVyXG4gKiBAcGFyYW0ge3NjZW5lIGluc3RhbmNlfSBzY2VuZVxuICpcbiAqIEV4cGVjdHMgJ3NjZW5lJyB0byBoYXZlIHByb3BlcnR5ICdjb250YWluZXInXG4gKlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNob3dOb1dlYkdsTXNnKHNjZW5lKSB7XG4gICAgZm9yKHZhciBwcm9wIGluIHNjZW5lKSB7XG4gICAgICAgIGlmKHR5cGVvZiBzY2VuZVtwcm9wXSA9PT0gJ2Z1bmN0aW9uJykgc2NlbmVbcHJvcF0gPSBub29wO1xuICAgIH1cblxuICAgIHNjZW5lLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgc2NlbmUuY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2NlbmUuY29udGFpbmVyKTtcbiAgICB9O1xuXG4gICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGRpdi5jbGFzc05hbWUgPSAnbm8td2ViZ2wnO1xuICAgIGRpdi5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7XG4gICAgZGl2LnN0eWxlLmZvbnRTaXplID0gJzI0cHgnO1xuICAgIGRpdi5zdHlsZS5jb2xvciA9IENvbG9yLmRlZmF1bHRzWzBdO1xuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgZGl2LnN0eWxlLmxlZnQgPSBkaXYuc3R5bGUudG9wID0gJzBweCc7XG4gICAgZGl2LnN0eWxlLndpZHRoID0gZGl2LnN0eWxlLmhlaWdodCA9ICcxMDAlJztcbiAgICBkaXYuc3R5bGVbJ2JhY2tncm91bmQtY29sb3InXSA9IENvbG9yLmxpZ2h0TGluZTtcbiAgICBkaXYuc3R5bGVbJ3otaW5kZXgnXSA9IDMwO1xuXG4gICAgdmFyIHAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwJyk7XG4gICAgcC50ZXh0Q29udGVudCA9ICdXZWJHTCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHlvdXIgYnJvd3NlciAtIHZpc2l0IGh0dHBzOi8vZ2V0LndlYmdsLm9yZyBmb3IgbW9yZSBpbmZvJztcbiAgICBwLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICBwLnN0eWxlLnRvcCA9ICc1MCUnO1xuICAgIHAuc3R5bGUubGVmdCA9ICc1MCUnO1xuICAgIHAuc3R5bGUuaGVpZ2h0ID0gJzMwJSc7XG4gICAgcC5zdHlsZS53aWR0aCA9ICc1MCUnO1xuICAgIHAuc3R5bGUubWFyZ2luID0gJy0xNSUgMCAwIC0yNSUnO1xuXG4gICAgZGl2LmFwcGVuZENoaWxkKHApO1xuICAgIHNjZW5lLmNvbnRhaW5lci5hcHBlbmRDaGlsZChkaXYpO1xuICAgIHNjZW5lLmNvbnRhaW5lci5zdHlsZS5iYWNrZ3JvdW5kID0gJyNGRkZGRkYnO1xuICAgIHNjZW5lLmNvbnRhaW5lci5vbmNsaWNrID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5vcGVuKCdodHRwczovL2dldC53ZWJnbC5vcmcnKTtcbiAgICB9O1xuXG4gICAgLy8gcmV0dXJuIGJlZm9yZSBzZXR0aW5nIHVwIGNhbWVyYSBhbmQgb25yZW5kZXIgbWV0aG9kc1xuICAgIHJldHVybiBmYWxzZTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4vYXJyYXknKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG4vKipcbiAqIGFnZ051bXMoKSByZXR1cm5zIHRoZSByZXN1bHQgb2YgYW4gYWdncmVnYXRlIGZ1bmN0aW9uIGFwcGxpZWQgdG8gYW4gYXJyYXkgb2ZcbiAqIHZhbHVlcywgd2hlcmUgbm9uLW51bWVyaWNhbCB2YWx1ZXMgaGF2ZSBiZWVuIHRvc3NlZCBvdXQuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbn0gZiAtIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIChlLmcuLCBNYXRoLm1pbilcbiAqIEBwYXJhbSB7TnVtYmVyfSB2IC0gaW5pdGlhbCB2YWx1ZSAoY29udGludWluZyBmcm9tIHByZXZpb3VzIGNhbGxzKVxuICogICAgICBpZiB0aGVyZSdzIG5vIGNvbnRpbnVpbmcgdmFsdWUsIHVzZSBudWxsIGZvciBzZWxlY3Rvci10eXBlXG4gKiAgICAgIGZ1bmN0aW9ucyAobWF4LG1pbiksIG9yIDAgZm9yIHN1bW1hdGlvbnNcbiAqIEBwYXJhbSB7QXJyYXl9IGEgLSBhcnJheSB0byBhZ2dyZWdhdGUgKG1heSBiZSBuZXN0ZWQsIHdlIHdpbGwgcmVjdXJzZSxcbiAqICAgICAgICAgICAgICAgICAgICBidXQgYWxsIGVsZW1lbnRzIG11c3QgaGF2ZSB0aGUgc2FtZSBkaW1lbnNpb24pXG4gKiBAcGFyYW0ge051bWJlcn0gbGVuIC0gbWF4aW11bSBsZW5ndGggb2YgYSB0byBhZ2dyZWdhdGVcbiAqIEByZXR1cm4ge051bWJlcn0gLSByZXN1bHQgb2YgZiBhcHBsaWVkIHRvIGEgc3RhcnRpbmcgZnJvbSB2XG4gKi9cbmV4cG9ydHMuYWdnTnVtcyA9IGZ1bmN0aW9uKGYsIHYsIGEsIGxlbikge1xuICAgIHZhciBpLFxuICAgICAgICBiO1xuICAgIGlmKCFsZW4gfHwgbGVuID4gYS5sZW5ndGgpIGxlbiA9IGEubGVuZ3RoO1xuICAgIGlmKCFpc051bWVyaWModikpIHYgPSBmYWxzZTtcbiAgICBpZihpc0FycmF5T3JUeXBlZEFycmF5KGFbMF0pKSB7XG4gICAgICAgIGIgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIGJbaV0gPSBleHBvcnRzLmFnZ051bXMoZiwgdiwgYVtpXSk7XG4gICAgICAgIGEgPSBiO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmKCFpc051bWVyaWModikpIHYgPSBhW2ldO1xuICAgICAgICBlbHNlIGlmKGlzTnVtZXJpYyhhW2ldKSkgdiA9IGYoK3YsICthW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHY7XG59O1xuXG4vKipcbiAqIG1lYW4gJiBzdGQgZGV2IGZ1bmN0aW9ucyB1c2luZyBhZ2dOdW1zLCBzbyBpdCBoYW5kbGVzIG5vbi1udW1lcmljcyBuaWNlbHlcbiAqIGV2ZW4gbmVlZCB0byB1c2UgYWdnTnVtcyBpbnN0ZWFkIG9mIC5sZW5ndGgsIHRvIHRvc3Mgb3V0IG5vbi1udW1lcmljc1xuICovXG5leHBvcnRzLmxlbiA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICByZXR1cm4gZXhwb3J0cy5hZ2dOdW1zKGZ1bmN0aW9uKGEpIHsgcmV0dXJuIGEgKyAxOyB9LCAwLCBkYXRhKTtcbn07XG5cbmV4cG9ydHMubWVhbiA9IGZ1bmN0aW9uKGRhdGEsIGxlbikge1xuICAgIGlmKCFsZW4pIGxlbiA9IGV4cG9ydHMubGVuKGRhdGEpO1xuICAgIHJldHVybiBleHBvcnRzLmFnZ051bXMoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSArIGI7IH0sIDAsIGRhdGEpIC8gbGVuO1xufTtcblxuZXhwb3J0cy5taWRSYW5nZSA9IGZ1bmN0aW9uKG51bUFycikge1xuICAgIGlmKG51bUFyciA9PT0gdW5kZWZpbmVkIHx8IG51bUFyci5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIChleHBvcnRzLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIG51bUFycikgKyBleHBvcnRzLmFnZ051bXMoTWF0aC5taW4sIG51bGwsIG51bUFycikpIC8gMjtcbn07XG5cbmV4cG9ydHMudmFyaWFuY2UgPSBmdW5jdGlvbihkYXRhLCBsZW4sIG1lYW4pIHtcbiAgICBpZighbGVuKSBsZW4gPSBleHBvcnRzLmxlbihkYXRhKTtcbiAgICBpZighaXNOdW1lcmljKG1lYW4pKSBtZWFuID0gZXhwb3J0cy5tZWFuKGRhdGEsIGxlbik7XG5cbiAgICByZXR1cm4gZXhwb3J0cy5hZ2dOdW1zKGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgKyBNYXRoLnBvdyhiIC0gbWVhbiwgMik7XG4gICAgfSwgMCwgZGF0YSkgLyBsZW47XG59O1xuXG5leHBvcnRzLnN0ZGV2ID0gZnVuY3Rpb24oZGF0YSwgbGVuLCBtZWFuKSB7XG4gICAgcmV0dXJuIE1hdGguc3FydChleHBvcnRzLnZhcmlhbmNlKGRhdGEsIGxlbiwgbWVhbikpO1xufTtcblxuLyoqXG4gKiBpbnRlcnAoKSBjb21wdXRlcyBhIHBlcmNlbnRpbGUgKHF1YW50aWxlKSBmb3IgYSBnaXZlbiBkaXN0cmlidXRpb24uXG4gKiBXZSBpbnRlcnBvbGF0ZSB0aGUgZGlzdHJpYnV0aW9uICh0byBjb21wdXRlIHF1YW50aWxlcywgd2UgZm9sbG93IG1ldGhvZCAjMTAgaGVyZTpcbiAqIGh0dHA6Ly93d3cuYW1zdGF0Lm9yZy9wdWJsaWNhdGlvbnMvanNlL3YxNG4zL2xhbmdmb3JkLmh0bWwpLlxuICogVHlwaWNhbGx5IHRoZSBpbmRleCBvciByYW5rIChuICogYXJyLmxlbmd0aCkgbWF5IGJlIG5vbi1pbnRlZ2VyLlxuICogRm9yIHJlZmVyZW5jZTogZW5kcyBhcmUgY2xpcHBlZCB0byB0aGUgZXh0cmVtZSB2YWx1ZXMgaW4gdGhlIGFycmF5O1xuICogRm9yIGJveCBwbG90czogaW5kZXggeW91IGdldCBpcyBoYWxmIGEgcG9pbnQgdG9vIGhpZ2ggKHNlZVxuICogaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QZXJjZW50aWxlI05lYXJlc3RfcmFuaykgYnV0IG5vdGUgdGhhdCB0aGlzIGRlZmluaXRpb25cbiAqIGluZGV4ZXMgZnJvbSAxIHJhdGhlciB0aGFuIDAsIHNvIHdlIHN1YnRyYWN0IDEvMiAoaW5zdGVhZCBvZiBhZGQpLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGFyciAtIFRoaXMgYXJyYXkgY29udGFpbnMgdGhlIHZhbHVlcyB0aGF0IG1ha2UgdXAgdGhlIGRpc3RyaWJ1dGlvbi5cbiAqIEBwYXJhbSB7TnVtYmVyfSBuIC0gQmV0d2VlbiAwIGFuZCAxLCBuID0gcC8xMDAgaXMgc3VjaCB0aGF0IHdlIGNvbXB1dGUgdGhlIHBedGggcGVyY2VudGlsZS5cbiAqIEZvciBleGFtcGxlLCB0aGUgNTB0aCBwZXJjZW50aWxlIChvciBtZWRpYW4pIGNvcnJlc3BvbmRzIHRvIG4gPSAwLjVcbiAqIEByZXR1cm4ge051bWJlcn0gLSBwZXJjZW50aWxlXG4gKi9cbmV4cG9ydHMuaW50ZXJwID0gZnVuY3Rpb24oYXJyLCBuKSB7XG4gICAgaWYoIWlzTnVtZXJpYyhuKSkgdGhyb3cgJ24gc2hvdWxkIGJlIGEgZmluaXRlIG51bWJlcic7XG4gICAgbiA9IG4gKiBhcnIubGVuZ3RoIC0gMC41O1xuICAgIGlmKG4gPCAwKSByZXR1cm4gYXJyWzBdO1xuICAgIGlmKG4gPiBhcnIubGVuZ3RoIC0gMSkgcmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG4gICAgdmFyIGZyYWMgPSBuICUgMTtcbiAgICByZXR1cm4gZnJhYyAqIGFycltNYXRoLmNlaWwobildICsgKDEgLSBmcmFjKSAqIGFycltNYXRoLmZsb29yKG4pXTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHJnYmEgPSByZXF1aXJlKCdjb2xvci1ub3JtYWxpemUnKTtcblxuZnVuY3Rpb24gc3RyMlJnYmFBcnJheShjb2xvcikge1xuICAgIGlmKCFjb2xvcikgcmV0dXJuIFswLCAwLCAwLCAxXTtcbiAgICByZXR1cm4gcmdiYShjb2xvcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RyMlJnYmFBcnJheTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKiBnbG9iYWwgTWF0aEpheDpmYWxzZSAqL1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcbnZhciBMSU5FX1NQQUNJTkcgPSByZXF1aXJlKCcuLi9jb25zdGFudHMvYWxpZ25tZW50JykuTElORV9TUEFDSU5HO1xuXG4vLyB0ZXh0IGNvbnZlcnRlclxuXG5mdW5jdGlvbiBnZXRTaXplKF9zZWxlY3Rpb24sIF9kaW1lbnNpb24pIHtcbiAgICByZXR1cm4gX3NlbGVjdGlvbi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClbX2RpbWVuc2lvbl07XG59XG5cbnZhciBGSU5EX1RFWCA9IC8oW14kXSopKFskXStbXiRdKlskXSspKFteJF0qKS87XG5cbmV4cG9ydHMuY29udmVydFRvVHNwYW5zID0gZnVuY3Rpb24oX2NvbnRleHQsIGdkLCBfY2FsbGJhY2spIHtcbiAgICB2YXIgc3RyID0gX2NvbnRleHQudGV4dCgpO1xuXG4gICAgLy8gVW50aWwgd2UgZ2V0IHRleCBpbnRlZ3JhdGVkIG1vcmUgZnVsbHkgKHNvIGl0IGNhbiBiZSB1c2VkIGFsb25nIHdpdGggbm9uLXRleClcbiAgICAvLyBhbGxvdyBzb21lIGVsZW1lbnRzIHRvIHByb2hpYml0IGl0IGJ5IGF0dGFjaGluZyAnZGF0YS1ub3RleCcgdG8gdGhlIG9yaWdpbmFsXG4gICAgdmFyIHRleCA9ICghX2NvbnRleHQuYXR0cignZGF0YS1ub3RleCcpKSAmJlxuICAgICAgICAodHlwZW9mIE1hdGhKYXggIT09ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICBzdHIubWF0Y2goRklORF9URVgpO1xuXG4gICAgdmFyIHBhcmVudCA9IGQzLnNlbGVjdChfY29udGV4dC5ub2RlKCkucGFyZW50Tm9kZSk7XG4gICAgaWYocGFyZW50LmVtcHR5KCkpIHJldHVybjtcbiAgICB2YXIgc3ZnQ2xhc3MgPSAoX2NvbnRleHQuYXR0cignY2xhc3MnKSkgPyBfY29udGV4dC5hdHRyKCdjbGFzcycpLnNwbGl0KCcgJylbMF0gOiAndGV4dCc7XG4gICAgc3ZnQ2xhc3MgKz0gJy1tYXRoJztcbiAgICBwYXJlbnQuc2VsZWN0QWxsKCdzdmcuJyArIHN2Z0NsYXNzKS5yZW1vdmUoKTtcbiAgICBwYXJlbnQuc2VsZWN0QWxsKCdnLicgKyBzdmdDbGFzcyArICctZ3JvdXAnKS5yZW1vdmUoKTtcbiAgICBfY29udGV4dC5zdHlsZSgnZGlzcGxheScsIG51bGwpXG4gICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgIC8vIHNvbWUgY2FsbGVycyB1c2UgZGF0YS11bmZvcm1hdHRlZCAqZnJvbSB0aGUgPHRleHQ+IGVsZW1lbnQqIGluICdjYW5jZWwnXG4gICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIGl0IGhlcmUgZXZlbiBpZiB3ZSdyZSBnb2luZyB0byB0dXJuIGl0IGludG8gbWF0aFxuICAgICAgICAgICAgLy8gdGhlc2UgdHdvIChwbHVzIHN0eWxlIGFuZCB0ZXh0LWFuY2hvciBhdHRyaWJ1dGVzKSBmb3JtIHRoZSBrZXkgd2UncmVcbiAgICAgICAgICAgIC8vIGdvaW5nIHRvIHVzZSBmb3IgRHJhd2luZy5iQm94XG4gICAgICAgICAgICAnZGF0YS11bmZvcm1hdHRlZCc6IHN0cixcbiAgICAgICAgICAgICdkYXRhLW1hdGgnOiAnTidcbiAgICAgICAgfSk7XG5cbiAgICBmdW5jdGlvbiBzaG93VGV4dCgpIHtcbiAgICAgICAgaWYoIXBhcmVudC5lbXB0eSgpKSB7XG4gICAgICAgICAgICBzdmdDbGFzcyA9IF9jb250ZXh0LmF0dHIoJ2NsYXNzJykgKyAnLW1hdGgnO1xuICAgICAgICAgICAgcGFyZW50LnNlbGVjdCgnc3ZnLicgKyBzdmdDbGFzcykucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgX2NvbnRleHQudGV4dCgnJylcbiAgICAgICAgICAgIC5zdHlsZSgnd2hpdGUtc3BhY2UnLCAncHJlJyk7XG5cbiAgICAgICAgdmFyIGhhc0xpbmsgPSBidWlsZFNWR1RleHQoX2NvbnRleHQubm9kZSgpLCBzdHIpO1xuXG4gICAgICAgIGlmKGhhc0xpbmspIHtcbiAgICAgICAgICAgIC8vIGF0IGxlYXN0IGluIENocm9tZSwgcG9pbnRlci1ldmVudHMgZG9lcyBub3Qgc2VlbVxuICAgICAgICAgICAgLy8gdG8gYmUgaG9ub3JlZCBpbiBjaGlsZHJlbiBvZiA8dGV4dD4gZWxlbWVudHNcbiAgICAgICAgICAgIC8vIHNvIGlmIHdlIGhhdmUgYW4gYW5jaG9yLCB3ZSBoYXZlIHRvIG1ha2UgdGhlXG4gICAgICAgICAgICAvLyB3aG9sZSBlbGVtZW50IHJlc3BvbmRcbiAgICAgICAgICAgIF9jb250ZXh0LnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV4cG9ydHMucG9zaXRpb25UZXh0KF9jb250ZXh0KTtcblxuICAgICAgICBpZihfY2FsbGJhY2spIF9jYWxsYmFjay5jYWxsKF9jb250ZXh0KTtcbiAgICB9XG5cbiAgICBpZih0ZXgpIHtcbiAgICAgICAgKChnZCAmJiBnZC5fcHJvbWlzZXMpIHx8IFtdKS5wdXNoKG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgICAgICAgIF9jb250ZXh0LnN0eWxlKCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICAgICAgICAgIHZhciBmb250U2l6ZSA9IHBhcnNlSW50KF9jb250ZXh0Lm5vZGUoKS5zdHlsZS5mb250U2l6ZSwgMTApO1xuICAgICAgICAgICAgdmFyIGNvbmZpZyA9IHtmb250U2l6ZTogZm9udFNpemV9O1xuXG4gICAgICAgICAgICB0ZXhUb1NWRyh0ZXhbMl0sIGNvbmZpZywgZnVuY3Rpb24oX3N2Z0VsLCBfZ2x5cGhEZWZzLCBfc3ZnQkJveCkge1xuICAgICAgICAgICAgICAgIHBhcmVudC5zZWxlY3RBbGwoJ3N2Zy4nICsgc3ZnQ2xhc3MpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHBhcmVudC5zZWxlY3RBbGwoJ2cuJyArIHN2Z0NsYXNzICsgJy1ncm91cCcpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5ld1N2ZyA9IF9zdmdFbCAmJiBfc3ZnRWwuc2VsZWN0KCdzdmcnKTtcbiAgICAgICAgICAgICAgICBpZighbmV3U3ZnIHx8ICFuZXdTdmcubm9kZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNob3dUZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtYXRoamF4R3JvdXAgPSBwYXJlbnQuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoc3ZnQ2xhc3MgKyAnLWdyb3VwJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2RhdGEtdW5mb3JtYXR0ZWQnOiBzdHIsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZGF0YS1tYXRoJzogJ1knXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgbWF0aGpheEdyb3VwLm5vZGUoKS5hcHBlbmRDaGlsZChuZXdTdmcubm9kZSgpKTtcblxuICAgICAgICAgICAgICAgIC8vIHN0aXRjaCB0aGUgZ2x5cGggZGVmc1xuICAgICAgICAgICAgICAgIGlmKF9nbHlwaERlZnMgJiYgX2dseXBoRGVmcy5ub2RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3ZnLm5vZGUoKS5pbnNlcnRCZWZvcmUoX2dseXBoRGVmcy5ub2RlKCkuY2xvbmVOb2RlKHRydWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdTdmcubm9kZSgpLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG5ld1N2Zy5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogc3ZnQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogX3N2Z0JCb3guaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAneE1pbllNaW4gbWVldCdcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5zdHlsZSh7b3ZlcmZsb3c6ICd2aXNpYmxlJywgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnfSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgZmlsbCA9IF9jb250ZXh0Lm5vZGUoKS5zdHlsZS5maWxsIHx8ICdibGFjayc7XG4gICAgICAgICAgICAgICAgbmV3U3ZnLnNlbGVjdCgnZycpLmF0dHIoe2ZpbGw6IGZpbGwsIHN0cm9rZTogZmlsbH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5ld1N2Z1cgPSBnZXRTaXplKG5ld1N2ZywgJ3dpZHRoJyksXG4gICAgICAgICAgICAgICAgICAgIG5ld1N2Z0ggPSBnZXRTaXplKG5ld1N2ZywgJ2hlaWdodCcpLFxuICAgICAgICAgICAgICAgICAgICBuZXdYID0gK19jb250ZXh0LmF0dHIoJ3gnKSAtIG5ld1N2Z1cgKlxuICAgICAgICAgICAgICAgICAgICAgICAge3N0YXJ0OiAwLCBtaWRkbGU6IDAuNSwgZW5kOiAxfVtfY29udGV4dC5hdHRyKCd0ZXh0LWFuY2hvcicpIHx8ICdzdGFydCddLFxuICAgICAgICAgICAgICAgICAgICAvLyBmb250IGJhc2VsaW5lIGlzIGFib3V0IDEvNCBmb250U2l6ZSBiZWxvdyBjZW50ZXJsaW5lXG4gICAgICAgICAgICAgICAgICAgIHRleHRIZWlnaHQgPSBmb250U2l6ZSB8fCBnZXRTaXplKF9jb250ZXh0LCAnaGVpZ2h0JyksXG4gICAgICAgICAgICAgICAgICAgIGR5ID0gLXRleHRIZWlnaHQgLyA0O1xuXG4gICAgICAgICAgICAgICAgaWYoc3ZnQ2xhc3NbMF0gPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICBtYXRoamF4R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICdyb3RhdGUoJyArIFstOTAsICtfY29udGV4dC5hdHRyKCd4JyksICtfY29udGV4dC5hdHRyKCd5JyldICtcbiAgICAgICAgICAgICAgICAgICAgICAgICcpIHRyYW5zbGF0ZSgnICsgWy1uZXdTdmdXIC8gMiwgZHkgLSBuZXdTdmdIIC8gMl0gKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld1N2Zy5hdHRyKHt4OiArX2NvbnRleHQuYXR0cigneCcpLCB5OiArX2NvbnRleHQuYXR0cigneScpfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYoc3ZnQ2xhc3NbMF0gPT09ICdsJykge1xuICAgICAgICAgICAgICAgICAgICBuZXdTdmcuYXR0cih7eDogX2NvbnRleHQuYXR0cigneCcpLCB5OiBkeSAtIChuZXdTdmdIIC8gMil9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihzdmdDbGFzc1swXSA9PT0gJ2EnKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1N2Zy5hdHRyKHt4OiAwLCB5OiBkeX0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3ZnLmF0dHIoe3g6IG5ld1gsIHk6ICgrX2NvbnRleHQuYXR0cigneScpICsgZHkgLSBuZXdTdmdIIC8gMil9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihfY2FsbGJhY2spIF9jYWxsYmFjay5jYWxsKF9jb250ZXh0LCBtYXRoamF4R3JvdXApO1xuICAgICAgICAgICAgICAgIHJlc29sdmUobWF0aGpheEdyb3VwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KSk7XG4gICAgfVxuICAgIGVsc2Ugc2hvd1RleHQoKTtcblxuICAgIHJldHVybiBfY29udGV4dDtcbn07XG5cblxuLy8gTWF0aEpheFxuXG52YXIgTFRfTUFUQ0ggPSAvKDx8Jmx0O3wmIzYwOykvZztcbnZhciBHVF9NQVRDSCA9IC8oPnwmZ3Q7fCYjNjI7KS9nO1xuXG5mdW5jdGlvbiBjbGVhbkVzY2FwZXNGb3JUZXgocykge1xuICAgIHJldHVybiBzLnJlcGxhY2UoTFRfTUFUQ0gsICdcXFxcbHQgJylcbiAgICAgICAgLnJlcGxhY2UoR1RfTUFUQ0gsICdcXFxcZ3QgJyk7XG59XG5cbmZ1bmN0aW9uIHRleFRvU1ZHKF90ZXhTdHJpbmcsIF9jb25maWcsIF9jYWxsYmFjaykge1xuXG4gICAgdmFyIG9yaWdpbmFsUmVuZGVyZXIsXG4gICAgICAgIG9yaWdpbmFsQ29uZmlnLFxuICAgICAgICBvcmlnaW5hbFByb2Nlc3NTZWN0aW9uRGVsYXksXG4gICAgICAgIHRtcERpdjtcblxuICAgIE1hdGhKYXguSHViLlF1ZXVlKFxuICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICBvcmlnaW5hbENvbmZpZyA9IExpYi5leHRlbmREZWVwQWxsKHt9LCBNYXRoSmF4Lkh1Yi5jb25maWcpO1xuXG4gICAgICAgIG9yaWdpbmFsUHJvY2Vzc1NlY3Rpb25EZWxheSA9IE1hdGhKYXguSHViLnByb2Nlc3NTZWN0aW9uRGVsYXk7XG4gICAgICAgIGlmKE1hdGhKYXguSHViLnByb2Nlc3NTZWN0aW9uRGVsYXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gTWF0aEpheCAyLjUrXG4gICAgICAgICAgICBNYXRoSmF4Lkh1Yi5wcm9jZXNzU2VjdGlvbkRlbGF5ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYXRoSmF4Lkh1Yi5Db25maWcoe1xuICAgICAgICAgICAgbWVzc2FnZVN0eWxlOiAnbm9uZScsXG4gICAgICAgICAgICB0ZXgyamF4OiB7XG4gICAgICAgICAgICAgICAgaW5saW5lTWF0aDogW1snJCcsICckJ10sIFsnXFxcXCgnLCAnXFxcXCknXV1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXNwbGF5QWxpZ246ICdsZWZ0JyxcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gR2V0IG9yaWdpbmFsIHJlbmRlcmVyXG4gICAgICAgIG9yaWdpbmFsUmVuZGVyZXIgPSBNYXRoSmF4Lkh1Yi5jb25maWcubWVudVNldHRpbmdzLnJlbmRlcmVyO1xuICAgICAgICBpZihvcmlnaW5hbFJlbmRlcmVyICE9PSAnU1ZHJykge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhKYXguSHViLnNldFJlbmRlcmVyKCdTVkcnKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciByYW5kb21JRCA9ICdtYXRoLW91dHB1dC0nICsgTGliLnJhbmRzdHIoe30sIDY0KTtcbiAgICAgICAgdG1wRGl2ID0gZDMuc2VsZWN0KCdib2R5JykuYXBwZW5kKCdkaXYnKVxuICAgICAgICAgICAgLmF0dHIoe2lkOiByYW5kb21JRH0pXG4gICAgICAgICAgICAuc3R5bGUoe3Zpc2liaWxpdHk6ICdoaWRkZW4nLCBwb3NpdGlvbjogJ2Fic29sdXRlJ30pXG4gICAgICAgICAgICAuc3R5bGUoeydmb250LXNpemUnOiBfY29uZmlnLmZvbnRTaXplICsgJ3B4J30pXG4gICAgICAgICAgICAudGV4dChjbGVhbkVzY2FwZXNGb3JUZXgoX3RleFN0cmluZykpO1xuXG4gICAgICAgIHJldHVybiBNYXRoSmF4Lkh1Yi5UeXBlc2V0KHRtcERpdi5ub2RlKCkpO1xuICAgIH0sXG4gICAgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnbHlwaERlZnMgPSBkMy5zZWxlY3QoJ2JvZHknKS5zZWxlY3QoJyNNYXRoSmF4X1NWR19nbHlwaHMnKTtcblxuICAgICAgICBpZih0bXBEaXYuc2VsZWN0KCcuTWF0aEpheF9TVkcnKS5lbXB0eSgpIHx8ICF0bXBEaXYuc2VsZWN0KCdzdmcnKS5ub2RlKCkpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ1RoZXJlIHdhcyBhbiBlcnJvciBpbiB0aGUgdGV4IHN5bnRheC4nLCBfdGV4U3RyaW5nKTtcbiAgICAgICAgICAgIF9jYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHN2Z0JCb3ggPSB0bXBEaXYuc2VsZWN0KCdzdmcnKS5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBfY2FsbGJhY2sodG1wRGl2LnNlbGVjdCgnLk1hdGhKYXhfU1ZHJyksIGdseXBoRGVmcywgc3ZnQkJveCk7XG4gICAgICAgIH1cblxuICAgICAgICB0bXBEaXYucmVtb3ZlKCk7XG5cbiAgICAgICAgaWYob3JpZ2luYWxSZW5kZXJlciAhPT0gJ1NWRycpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoSmF4Lkh1Yi5zZXRSZW5kZXJlcihvcmlnaW5hbFJlbmRlcmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmKG9yaWdpbmFsUHJvY2Vzc1NlY3Rpb25EZWxheSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBNYXRoSmF4Lkh1Yi5wcm9jZXNzU2VjdGlvbkRlbGF5ID0gb3JpZ2luYWxQcm9jZXNzU2VjdGlvbkRlbGF5O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNYXRoSmF4Lkh1Yi5Db25maWcob3JpZ2luYWxDb25maWcpO1xuICAgIH0pO1xufVxuXG52YXIgVEFHX1NUWUxFUyA9IHtcbiAgICAvLyB3b3VsZCBsaWtlIHRvIHVzZSBiYXNlbGluZS1zaGlmdCBmb3Igc3ViL3N1cCBidXQgRkYgZG9lc24ndCBzdXBwb3J0IGl0XG4gICAgLy8gc28gd2UgbmVlZCB0byB1c2UgZHkgYWxvbmcgd2l0aCB0aGUgdWJlciBoYWNreSBzaGlmdC1iYWNrLXRvXG4gICAgLy8gYmFzZWxpbmUgYmVsb3dcbiAgICBzdXA6ICdmb250LXNpemU6NzAlJyxcbiAgICBzdWI6ICdmb250LXNpemU6NzAlJyxcbiAgICBiOiAnZm9udC13ZWlnaHQ6Ym9sZCcsXG4gICAgaTogJ2ZvbnQtc3R5bGU6aXRhbGljJyxcbiAgICBhOiAnY3Vyc29yOnBvaW50ZXInLFxuICAgIHNwYW46ICcnLFxuICAgIGVtOiAnZm9udC1zdHlsZTppdGFsaWM7Zm9udC13ZWlnaHQ6Ym9sZCdcbn07XG5cbi8vIGJhc2VsaW5lIHNoaWZ0cyBmb3Igc3ViIGFuZCBzdXBcbnZhciBTSElGVF9EWSA9IHtcbiAgICBzdWI6ICcwLjNlbScsXG4gICAgc3VwOiAnLTAuNmVtJ1xufTtcbi8vIHJlc2V0IGJhc2VsaW5lIGJ5IGFkZGluZyBhIHRzcGFuIChlbXB0eSBleGNlcHQgZm9yIGEgemVyby13aWR0aCBzcGFjZSlcbi8vIHdpdGggZHkgb2YgLTcwJSAqIFNISUZUX0RZIChiZWNhdXNlIGZvbnQtc2l6ZT03MCUpXG52YXIgUkVTRVRfRFkgPSB7XG4gICAgc3ViOiAnLTAuMjFlbScsXG4gICAgc3VwOiAnMC40MmVtJ1xufTtcbnZhciBaRVJPX1dJRFRIX1NQQUNFID0gJ1xcdTIwMGInO1xuXG4vKlxuICogV2hpdGVsaXN0IG9mIHByb3RvY29scyBpbiB1c2VyLXN1cHBsaWVkIHVybHMuIE1vc3RseSB3ZSB3YW50IHRvIGF2b2lkIGphdmFzY3JpcHRcbiAqIGFuZCByZWxhdGVkIGF0dGFjayB2ZWN0b3JzLiBUaGUgZW1wdHkgaXRlbXMgYXJlIHRoZXJlIGZvciBJRSwgdGhhdCBpbiB2YXJpb3VzXG4gKiB2ZXJzaW9ucyB0cmVhdHMgcmVsYXRpdmUgcGF0aHMgYXMgaGF2aW5nIGRpZmZlcmVudCBmbGF2b3JzIG9mIG5vIHByb3RvY29sLCB3aGlsZVxuICogb3RoZXIgYnJvd3NlcnMgaGF2ZSB0aGVzZSBleHBsaWNpdGx5IGluaGVyaXQgdGhlIHByb3RvY29sIG9mIHRoZSBwYWdlIHRoZXkncmUgaW4uXG4gKi9cbnZhciBQUk9UT0NPTFMgPSBbJ2h0dHA6JywgJ2h0dHBzOicsICdtYWlsdG86JywgJycsIHVuZGVmaW5lZCwgJzonXTtcblxudmFyIFNUUklQX1RBR1MgPSBuZXcgUmVnRXhwKCc8Lz8oJyArIE9iamVjdC5rZXlzKFRBR19TVFlMRVMpLmpvaW4oJ3wnKSArICcpKCBbXj5dKik/Lz8+JywgJ2cnKTtcblxudmFyIE5FV0xJTkVTID0gLyhcXHJcXG4/fFxcbikvZztcblxudmFyIFNQTElUX1RBR1MgPSAvKDxbXjw+XSo+KS87XG5cbnZhciBPTkVfVEFHID0gLzwoXFwvPykoW14gPl0qKShcXHMrKC4qKSk/Pi9pO1xuXG52YXIgQlJfVEFHID0gLzxicihcXHMrLiopPz4vaTtcblxuLypcbiAqIHN0eWxlIGFuZCBocmVmOiBwdWxsIHRoZW0gb3V0IG9mIGVpdGhlciBzaW5nbGUgb3IgZG91YmxlIHF1b3Rlcy4gQWxzb1xuICogLSB0YXJnZXQ6IChfYmxhbmt8X3NlbGZ8X3BhcmVudHxfdG9wfGZyYW1lbmFtZSlcbiAqICAgICBub3RlIHRoYXQgeW91IGNhbid0IHVzZSB0YXJnZXQgdG8gZ2V0IGEgcG9wdXAgYnV0IGlmIHlvdSB1c2UgcG9wdXAsXG4gKiAgICAgYSBgZnJhbWVuYW1lYCB3aWxsIGJlIHBhc3NlZCBhbG9uZyBhcyB0aGUgbmFtZSBvZiB0aGUgcG9wdXAgd2luZG93LlxuICogICAgIHBlciB0aGUgc3BlYywgY2Fubm90IGNvbnRhaW4gd2hpdGVzcGFjZS5cbiAqICAgICBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSB3ZSBkZWZhdWx0IHRvICdfYmxhbmsnXG4gKiAtIHBvcHVwOiBhIGN1c3RvbSBvbmUgZm9yIHVzIHRvIGVuYWJsZSBwb3B1cCAobmV3IHdpbmRvdykgbGlua3MuIFN0cmluZ1xuICogICAgIGZvciB3aW5kb3cub3BlbiAtPiBzdHJXaW5kb3dGZWF0dXJlcywgbGlrZSAnbWVudWJhcj15ZXMsd2lkdGg9NTAwLGhlaWdodD01NTAnXG4gKiAgICAgbm90ZSB0aGF0IGF0IGxlYXN0IGluIENocm9tZSwgeW91IG5lZWQgdG8gZ2l2ZSBhdCBsZWFzdCBvbmUgcHJvcGVydHlcbiAqICAgICBpbiB0aGlzIHN0cmluZyBvciB0aGUgcGFnZSB3aWxsIG9wZW4gaW4gYSBuZXcgdGFiIGFueXdheS4gV2UgZm9sbG93IHRoaXNcbiAqICAgICBjb252ZW50aW9uIGFuZCB3aWxsIG5vdCBtYWtlIGEgcG9wdXAgaWYgdGhpcyBzdHJpbmcgaXMgZW1wdHkuXG4gKiAgICAgcGVyIHRoZSBzcGVjLCBjYW5ub3QgY29udGFpbiB3aGl0ZXNwYWNlLlxuICpcbiAqIEJlY2F1c2Ugd2UgaGFjayBpbiBvdGhlciBhdHRyaWJ1dGVzIHdpdGggc3R5bGUgKHN1YiAmIHN1cCksIGRyb3AgYW55IHRyYWlsaW5nXG4gKiBzZW1pY29sb24gaW4gdXNlci1zdXBwbGllZCBzdHlsZXMgc28gd2UgY2FuIGNvbnNpc3RlbnRseSBhcHBlbmQgdGhlIHRhZy1kZXBlbmRlbnQgc3R5bGVcbiAqXG4gKiBUaGVzZSBhcmUgZm9yIHRhZyBhdHRyaWJ1dGVzOyBDaHJvbWUgYW55d2F5IHdpbGwgY29udmVydCBlbnRpdGllcyBpblxuICogYXR0cmlidXRlIHZhbHVlcywgYnV0IG5vdCBpbiBhdHRyaWJ1dGUgbmFtZXNcbiAqIHlvdSBjYW4gdGVzdCB0aGlzIGJ5IGZvciBleGFtcGxlOlxuICogPiBwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgncCcpXG4gKiA+IHAuaW5uZXJIVE1MID0gJzxzcGFuIHN0eWwmI3g2NTs9XCJmb250LWNvbG9yOnImI3g2NTtkO1wiPkhpPC9zcGFuPidcbiAqID4gcC5pbm5lckhUTUxcbiAqIDwtICc8c3BhbiBzdHlsJiN4NjU7PVwiZm9udC1jb2xvcjpyZWQ7XCI+SGk8L3NwYW4+J1xuICovXG52YXIgU1RZTEVNQVRDSCA9IC8oXnxbXFxzXCInXSlzdHlsZVxccyo9XFxzKihcIihbXlwiXSopOz9cInwnKFteJ10qKTs/JykvaTtcbnZhciBIUkVGTUFUQ0ggPSAvKF58W1xcc1wiJ10paHJlZlxccyo9XFxzKihcIihbXlwiXSopXCJ8JyhbXiddKiknKS9pO1xudmFyIFRBUkdFVE1BVENIID0gLyhefFtcXHNcIiddKXRhcmdldFxccyo9XFxzKihcIihbXlwiXFxzXSopXCJ8JyhbXidcXHNdKiknKS9pO1xudmFyIFBPUFVQTUFUQ0ggPSAvKF58W1xcc1wiJ10pcG9wdXBcXHMqPVxccyooXCIoW1xcdz0sXSopXCJ8JyhbXFx3PSxdKiknKS9pO1xuXG4vLyBkZWRpY2F0ZWQgbWF0Y2hlciBmb3IgdGhlc2UgcXVvdGVkIHJlZ2V4ZXMsIHRoYXQgY2FuIHJldHVybiB0aGVpciByZXN1bHRzXG4vLyBpbiB0d28gZGlmZmVyZW50IHBsYWNlc1xuZnVuY3Rpb24gZ2V0UXVvdGVkTWF0Y2goX3N0ciwgcmUpIHtcbiAgICBpZighX3N0cikgcmV0dXJuIG51bGw7XG4gICAgdmFyIG1hdGNoID0gX3N0ci5tYXRjaChyZSk7XG4gICAgdmFyIHJlc3VsdCA9IG1hdGNoICYmIChtYXRjaFszXSB8fCBtYXRjaFs0XSk7XG4gICAgcmV0dXJuIHJlc3VsdCAmJiBjb252ZXJ0RW50aXRpZXMocmVzdWx0KTtcbn1cblxudmFyIENPTE9STUFUQ0ggPSAvKF58OylcXHMqY29sb3I6LztcblxuZXhwb3J0cy5wbGFpblRleHQgPSBmdW5jdGlvbihfc3RyKSB7XG4gICAgLy8gc3RyaXAgb3V0IG91ciBwc2V1ZG8taHRtbCBzbyB3ZSBoYXZlIGEgcmVhZGFibGVcbiAgICAvLyB2ZXJzaW9uIHRvIHB1dCBpbnRvIHRleHQgZmllbGRzXG4gICAgcmV0dXJuIChfc3RyIHx8ICcnKS5yZXBsYWNlKFNUUklQX1RBR1MsICcgJyk7XG59O1xuXG4vKlxuICogTi5CLiBIVE1MIGVudGl0aWVzIGFyZSBsaXN0ZWQgd2l0aG91dCB0aGUgbGVhZGluZyAnJicgYW5kIHRyYWlsaW5nICc7J1xuICogaHR0cHM6Ly93d3cuZnJlZWZvcm1hdHRlci5jb20vaHRtbC1lbnRpdGllcy5odG1sXG4gKlxuICogRldJVyBpZiB3ZSB3YW50ZWQgdG8gc3VwcG9ydCB0aGUgZnVsbCBzZXQsIGl0IGhhcyAyMjYxIGVudHJpZXM6XG4gKiBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUvZW50aXRpZXMuanNvblxuICogdGhvdWdoIEkgbm90aWNlIHRoYXQgc29tZSBvZiB0aGVzZSBhcmUgZHVwbGljYXRlcyBhbmQvb3IgYXJlIG1pc3NpbmcgXCI7XCJcbiAqIGVnOiBcIiZhbXA7XCIsIFwiJmFtcFwiLCBcIiZBTVA7XCIsIGFuZCBcIiZBTVBcIiBhbGwgbWFwIHRvIFwiJlwiXG4gKiBXZSBubyBsb25nZXIgbmVlZCB0byBpbmNsdWRlIG51bWVyaWMgZW50aXRpZXMgaGVyZSwgdGhlc2UgYXJlIG5vdyBoYW5kbGVkXG4gKiBieSBTdHJpbmcuZnJvbUNvZGVQb2ludC9mcm9tQ2hhckNvZGVcbiAqXG4gKiBBbnl3YXkgdGhlIG9ubHkgb25lcyB0aGF0IGFyZSByZWFsbHkgaW1wb3J0YW50IHRvIGFsbG93IGFyZSB0aGUgSFRNTCBzcGVjaWFsXG4gKiBjaGFycyA8LCA+LCBhbmQgJiwgYmVjYXVzZSB0aGVzZSBvbmVzIGNhbiB0cmlnZ2VyIHNwZWNpYWwgcHJvY2Vzc2luZyBpZiBub3RcbiAqIHJlcGxhY2VkIGJ5IHRoZSBjb3JyZXNwb25kaW5nIGVudGl0eS5cbiAqL1xudmFyIGVudGl0eVRvVW5pY29kZSA9IHtcbiAgICBtdTogJ868JyxcbiAgICBhbXA6ICcmJyxcbiAgICBsdDogJzwnLFxuICAgIGd0OiAnPicsXG4gICAgbmJzcDogJ8KgJyxcbiAgICB0aW1lczogJ8OXJyxcbiAgICBwbHVzbW46ICfCsScsXG4gICAgZGVnOiAnwrAnXG59O1xuXG4vLyBOT1RFOiBpbiBnZW5lcmFsIGVudGl0aWVzIGNhbiBjb250YWluIHVwcGVyY2FzZSB0b28gKHNvIFthLXpBLVpdKSBidXQgYWxsIHRoZVxuLy8gb25lcyB3ZSBzdXBwb3J0IHVzZSBvbmx5IGxvd2VyY2FzZS4gSWYgd2UgZXZlciBjaGFuZ2UgdGhhdCwgdXBkYXRlIHRoZSByZWdleC5cbnZhciBFTlRJVFlfTUFUQ0ggPSAvJigjXFxkK3wjeFtcXGRhLWZBLUZdK3xbYS16XSspOy9nO1xuZnVuY3Rpb24gY29udmVydEVudGl0aWVzKF9zdHIpIHtcbiAgICByZXR1cm4gX3N0ci5yZXBsYWNlKEVOVElUWV9NQVRDSCwgZnVuY3Rpb24oZnVsbE1hdGNoLCBpbm5lck1hdGNoKSB7XG4gICAgICAgIHZhciBvdXRDaGFyO1xuICAgICAgICBpZihpbm5lck1hdGNoLmNoYXJBdCgwKSA9PT0gJyMnKSB7XG4gICAgICAgICAgICAvLyBjYW5ub3QgdXNlIFN0cmluZy5mcm9tQ29kZVBvaW50IGluIElFXG4gICAgICAgICAgICBvdXRDaGFyID0gZnJvbUNvZGVQb2ludChcbiAgICAgICAgICAgICAgICBpbm5lck1hdGNoLmNoYXJBdCgxKSA9PT0gJ3gnID9cbiAgICAgICAgICAgICAgICAgICAgcGFyc2VJbnQoaW5uZXJNYXRjaC5zdWJzdHIoMiksIDE2KSA6XG4gICAgICAgICAgICAgICAgICAgIHBhcnNlSW50KGlubmVyTWF0Y2guc3Vic3RyKDEpLCAxMClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBvdXRDaGFyID0gZW50aXR5VG9Vbmljb2RlW2lubmVyTWF0Y2hdO1xuXG4gICAgICAgIC8vIGFzIGluIHJlZ3VsYXIgSFRNTCwgaWYgd2UgZGlkbid0IGRlY29kZSB0aGUgZW50aXR5IGp1c3RcbiAgICAgICAgLy8gbGVhdmUgdGhlIHJhdyB0ZXh0IGluIHBsYWNlLlxuICAgICAgICByZXR1cm4gb3V0Q2hhciB8fCBmdWxsTWF0Y2g7XG4gICAgfSk7XG59XG5leHBvcnRzLmNvbnZlcnRFbnRpdGllcyA9IGNvbnZlcnRFbnRpdGllcztcblxuZnVuY3Rpb24gZnJvbUNvZGVQb2ludChjb2RlKSB7XG4gICAgLy8gRG9uJ3QgYWxsb3cgb3ZlcmZsb3cuIEluIENocm9tZSB0aGlzIHR1cm5zIGludG8g77+9IGJ1dCBJIGZlZWwgbGlrZSBpdCdzXG4gICAgLy8gbW9yZSB1c2VmdWwgdG8ganVzdCBub3QgY29udmVydCBpdCBhdCBhbGwuXG4gICAgaWYoY29kZSA+IDB4MTBGRkZGKSByZXR1cm47XG4gICAgdmFyIHN0cmluZ0Zyb21Db2RlUG9pbnQgPSBTdHJpbmcuZnJvbUNvZGVQb2ludDtcbiAgICBpZihzdHJpbmdGcm9tQ29kZVBvaW50KSByZXR1cm4gc3RyaW5nRnJvbUNvZGVQb2ludChjb2RlKTtcblxuICAgIC8vIElFIGRvZXNuJ3QgaGF2ZSBTdHJpbmcuZnJvbUNvZGVQb2ludFxuICAgIC8vIHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9TdHJpbmcvZnJvbUNvZGVQb2ludFxuICAgIHZhciBzdHJpbmdGcm9tQ2hhckNvZGUgPSBTdHJpbmcuZnJvbUNoYXJDb2RlO1xuICAgIGlmKGNvZGUgPD0gMHhGRkZGKSByZXR1cm4gc3RyaW5nRnJvbUNoYXJDb2RlKGNvZGUpO1xuICAgIHJldHVybiBzdHJpbmdGcm9tQ2hhckNvZGUoXG4gICAgICAgIChjb2RlID4+IDEwKSArIDB4RDdDMCxcbiAgICAgICAgKGNvZGUgJSAweDQwMCkgKyAweERDMDBcbiAgICApO1xufVxuXG4vKlxuICogYnVpbGRTVkdUZXh0OiBjb252ZXJ0IG91ciBwc2V1ZG8taHRtbCBpbnRvIFNWRyB0c3BhbiBlbGVtZW50cywgYW5kIGF0dGFjaCB0aGVzZVxuICogdG8gY29udGFpbmVyTm9kZVxuICpcbiAqIEBwYXJhbSB7c3ZnIHRleHQgZWxlbWVudH0gY29udGFpbmVyTm9kZTogdGhlIDx0ZXh0PiBub2RlIHRvIGluc2VydCB0aGlzIHRleHQgaW50b1xuICogQHBhcmFtIHtzdHJpbmd9IHN0cjogdGhlIHBzZXVkby1odG1sIHN0cmluZyB0byBjb252ZXJ0IHRvIHN2Z1xuICpcbiAqIEByZXR1cm5zIHtib29sfTogZG9lcyB0aGUgcmVzdWx0IGNvbnRhaW4gYW55IGxpbmtzPyBXZSBuZWVkIHRvIGhhbmRsZSB0aGUgdGV4dCBlbGVtZW50XG4gKiAgIHNvbWV3aGF0IGRpZmZlcmVudGx5IGlmIGl0IGRvZXMsIHNvIGp1c3Qga2VlcCB0cmFjayBvZiB0aGlzIHdoZW4gaXQgaGFwcGVucy5cbiAqL1xuZnVuY3Rpb24gYnVpbGRTVkdUZXh0KGNvbnRhaW5lck5vZGUsIHN0cikge1xuICAgIC8qXG4gICAgICogTm9ybWFsaXplIGJlaGF2aW9yIGJldHdlZW4gSUUgYW5kIG90aGVycyB3cnQgbmV3bGluZXMgYW5kIHdoaXRlc3BhY2U6cHJlXG4gICAgICogdGhpcyBjb21iaW5hdGlvbiBtYWtlcyBJRSBiYXJmIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy83NDZcbiAgICAgKiBDaHJvbWUgYW5kIEZGIGRpc3BsYXkgXFxuLCBcXHIsIG9yIFxcclxcbiBhcyBhIHNwYWNlIGluIHRoaXMgbW9kZS5cbiAgICAgKiBJIGZlZWwgbGlrZSBhdCBzb21lIHBvaW50IHdlIHR1cm5lZCB0aGVzZSBpbnRvIDxicj4gYnV0IGN1cnJlbnRseSB3ZSBkb24ndCBzb1xuICAgICAqIEknbSBqdXN0IGdvaW5nIHRvIGNlbWVudCB3aGF0IHdlIGRvIG5vdyBpbiBDaHJvbWUgYW5kIEZGXG4gICAgICovXG4gICAgc3RyID0gc3RyLnJlcGxhY2UoTkVXTElORVMsICcgJyk7XG5cbiAgICB2YXIgaGFzTGluayA9IGZhbHNlO1xuXG4gICAgLy8gYXMgd2UncmUgYnVpbGRpbmcgdGhlIHRleHQsIGtlZXAgdHJhY2sgb2Ygd2hhdCBlbGVtZW50cyB3ZSdyZSBuZXN0ZWQgaW5zaWRlXG4gICAgLy8gbm9kZVN0YWNrIHdpbGwgYmUgYW4gYXJyYXkgb2Yge25vZGUsIHR5cGUsIHN0eWxlLCBocmVmLCB0YXJnZXQsIHBvcHVwfVxuICAgIC8vIHdoZXJlIG9ubHkgdHlwZTogJ2EnIGdldHMgdGhlIGxhc3QgMyBhbmQgbm9kZSBpcyBvbmx5IGFkZGVkIHdoZW4gaXQncyBjcmVhdGVkXG4gICAgdmFyIG5vZGVTdGFjayA9IFtdO1xuICAgIHZhciBjdXJyZW50Tm9kZTtcbiAgICB2YXIgY3VycmVudExpbmUgPSAtMTtcblxuICAgIGZ1bmN0aW9uIG5ld0xpbmUoKSB7XG4gICAgICAgIGN1cnJlbnRMaW5lKys7XG5cbiAgICAgICAgdmFyIGxpbmVOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHhtbG5zTmFtZXNwYWNlcy5zdmcsICd0c3BhbicpO1xuICAgICAgICBkMy5zZWxlY3QobGluZU5vZGUpLmF0dHIoe1xuICAgICAgICAgICAgY2xhc3M6ICdsaW5lJyxcbiAgICAgICAgICAgIGR5OiAoY3VycmVudExpbmUgKiBMSU5FX1NQQUNJTkcpICsgJ2VtJ1xuICAgICAgICB9KTtcbiAgICAgICAgY29udGFpbmVyTm9kZS5hcHBlbmRDaGlsZChsaW5lTm9kZSk7XG5cbiAgICAgICAgY3VycmVudE5vZGUgPSBsaW5lTm9kZTtcblxuICAgICAgICB2YXIgb2xkTm9kZVN0YWNrID0gbm9kZVN0YWNrO1xuICAgICAgICBub2RlU3RhY2sgPSBbe25vZGU6IGxpbmVOb2RlfV07XG5cbiAgICAgICAgaWYob2xkTm9kZVN0YWNrLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDE7IGkgPCBvbGROb2RlU3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBlbnRlck5vZGUob2xkTm9kZVN0YWNrW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVudGVyTm9kZShub2RlU3BlYykge1xuICAgICAgICB2YXIgdHlwZSA9IG5vZGVTcGVjLnR5cGU7XG4gICAgICAgIHZhciBub2RlQXR0cnMgPSB7fTtcbiAgICAgICAgdmFyIG5vZGVUeXBlO1xuXG4gICAgICAgIGlmKHR5cGUgPT09ICdhJykge1xuICAgICAgICAgICAgbm9kZVR5cGUgPSAnYSc7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0ID0gbm9kZVNwZWMudGFyZ2V0O1xuICAgICAgICAgICAgdmFyIGhyZWYgPSBub2RlU3BlYy5ocmVmO1xuICAgICAgICAgICAgdmFyIHBvcHVwID0gbm9kZVNwZWMucG9wdXA7XG4gICAgICAgICAgICBpZihocmVmKSB7XG4gICAgICAgICAgICAgICAgbm9kZUF0dHJzID0ge1xuICAgICAgICAgICAgICAgICAgICAneGxpbms6eGxpbms6c2hvdyc6ICh0YXJnZXQgPT09ICdfYmxhbmsnIHx8IHRhcmdldC5jaGFyQXQoMCkgIT09ICdfJykgPyAnbmV3JyA6ICdyZXBsYWNlJyxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgICAgICAgICAgICAgICAgICd4bGluazp4bGluazpocmVmJzogaHJlZlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYocG9wdXApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gc2VjdXJpdHk6IGhyZWYgYW5kIHRhcmdldCBhcmUgbm90IGluc2VydGVkIGFzIGNvZGUgYnV0XG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIGF0dHJpYnV0ZXMuIHBvcHVwIGlzLCBidXQgbGltaXRlZCB0byAvW0EtWmEtejAtOV89LF0vXG4gICAgICAgICAgICAgICAgICAgIG5vZGVBdHRycy5vbmNsaWNrID0gJ3dpbmRvdy5vcGVuKHRoaXMuaHJlZi5iYXNlVmFsLHRoaXMudGFyZ2V0LmJhc2VWYWwsXCInICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVwICsgJ1wiKTtyZXR1cm4gZmFsc2U7JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBub2RlVHlwZSA9ICd0c3Bhbic7XG5cbiAgICAgICAgaWYobm9kZVNwZWMuc3R5bGUpIG5vZGVBdHRycy5zdHlsZSA9IG5vZGVTcGVjLnN0eWxlO1xuXG4gICAgICAgIHZhciBuZXdOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHhtbG5zTmFtZXNwYWNlcy5zdmcsIG5vZGVUeXBlKTtcblxuICAgICAgICBpZih0eXBlID09PSAnc3VwJyB8fCB0eXBlID09PSAnc3ViJykge1xuICAgICAgICAgICAgYWRkVGV4dE5vZGUoY3VycmVudE5vZGUsIFpFUk9fV0lEVEhfU1BBQ0UpO1xuICAgICAgICAgICAgY3VycmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG5cbiAgICAgICAgICAgIHZhciByZXNldHRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyh4bWxuc05hbWVzcGFjZXMuc3ZnLCAndHNwYW4nKTtcbiAgICAgICAgICAgIGFkZFRleHROb2RlKHJlc2V0dGVyLCBaRVJPX1dJRFRIX1NQQUNFKTtcbiAgICAgICAgICAgIGQzLnNlbGVjdChyZXNldHRlcikuYXR0cignZHknLCBSRVNFVF9EWVt0eXBlXSk7XG4gICAgICAgICAgICBub2RlQXR0cnMuZHkgPSBTSElGVF9EWVt0eXBlXTtcblxuICAgICAgICAgICAgY3VycmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICBjdXJyZW50Tm9kZS5hcHBlbmRDaGlsZChyZXNldHRlcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjdXJyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGQzLnNlbGVjdChuZXdOb2RlKS5hdHRyKG5vZGVBdHRycyk7XG5cbiAgICAgICAgY3VycmVudE5vZGUgPSBub2RlU3BlYy5ub2RlID0gbmV3Tm9kZTtcbiAgICAgICAgbm9kZVN0YWNrLnB1c2gobm9kZVNwZWMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFRleHROb2RlKG5vZGUsIHRleHQpIHtcbiAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0ZXh0KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhpdE5vZGUodHlwZSkge1xuICAgICAgICAvLyBBIGJhcmUgY2xvc2luZyB0YWcgY2FuJ3QgY2xvc2UgdGhlIHJvb3Qgbm9kZS4gSWYgd2UgZW5jb3VudGVyIHRoaXMgaXRcbiAgICAgICAgLy8gbWVhbnMgdGhlcmUncyBhbiBleHRyYSBjbG9zaW5nIHRhZyB0aGF0IGNhbiBqdXN0IGJlIGlnbm9yZWQ6XG4gICAgICAgIGlmKG5vZGVTdGFjay5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ0lnbm9yaW5nIHVuZXhwZWN0ZWQgZW5kIHRhZyA8LycgKyB0eXBlICsgJz4uJywgc3RyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpbm5lck5vZGUgPSBub2RlU3RhY2sucG9wKCk7XG5cbiAgICAgICAgaWYodHlwZSAhPT0gaW5uZXJOb2RlLnR5cGUpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ1N0YXJ0IHRhZyA8JyArIGlubmVyTm9kZS50eXBlICsgJz4gZG9lc250IG1hdGNoIGVuZCB0YWcgPCcgK1xuICAgICAgICAgICAgICAgIHR5cGUgKyAnPi4gUHJldGVuZGluZyBpdCBkaWQgbWF0Y2guJywgc3RyKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50Tm9kZSA9IG5vZGVTdGFja1tub2RlU3RhY2subGVuZ3RoIC0gMV0ubm9kZTtcbiAgICB9XG5cbiAgICB2YXIgaGFzTGluZXMgPSBCUl9UQUcudGVzdChzdHIpO1xuXG4gICAgaWYoaGFzTGluZXMpIG5ld0xpbmUoKTtcbiAgICBlbHNlIHtcbiAgICAgICAgY3VycmVudE5vZGUgPSBjb250YWluZXJOb2RlO1xuICAgICAgICBub2RlU3RhY2sgPSBbe25vZGU6IGNvbnRhaW5lck5vZGV9XTtcbiAgICB9XG5cbiAgICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoU1BMSVRfVEFHUyk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwYXJ0aSA9IHBhcnRzW2ldO1xuICAgICAgICB2YXIgbWF0Y2ggPSBwYXJ0aS5tYXRjaChPTkVfVEFHKTtcbiAgICAgICAgdmFyIHRhZ1R5cGUgPSBtYXRjaCAmJiBtYXRjaFsyXS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgdGFnU3R5bGUgPSBUQUdfU1RZTEVTW3RhZ1R5cGVdO1xuXG4gICAgICAgIGlmKHRhZ1R5cGUgPT09ICdicicpIHtcbiAgICAgICAgICAgIG5ld0xpbmUoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHRhZ1N0eWxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGFkZFRleHROb2RlKGN1cnJlbnROb2RlLCBjb252ZXJ0RW50aXRpZXMocGFydGkpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRhZyAtIG9wZW4gb3IgY2xvc2VcbiAgICAgICAgICAgIGlmKG1hdGNoWzFdKSB7XG4gICAgICAgICAgICAgICAgZXhpdE5vZGUodGFnVHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgZXh0cmEgPSBtYXRjaFs0XTtcblxuICAgICAgICAgICAgICAgIHZhciBub2RlU3BlYyA9IHt0eXBlOiB0YWdUeXBlfTtcblxuICAgICAgICAgICAgICAgIC8vIG5vdyBhZGQgc3R5bGUsIGZyb20gYm90aCB0aGUgdGFnIG5hbWUgYW5kIGFueSBleHRyYSBjc3NcbiAgICAgICAgICAgICAgICAvLyBNb3N0IG9mIHRoZSBzdmcgY3NzIHRoYXQgdXNlcnMgd2lsbCBjYXJlIGFib3V0IGlzIGp1c3QgbGlrZSBodG1sLFxuICAgICAgICAgICAgICAgIC8vIGJ1dCBmb250IGNvbG9yIGlzIGRpZmZlcmVudCAodXNlcyBmaWxsKS4gTGV0IG91ciB1c2VycyBpZ25vcmUgdGhpcy5cbiAgICAgICAgICAgICAgICB2YXIgY3NzID0gZ2V0UXVvdGVkTWF0Y2goZXh0cmEsIFNUWUxFTUFUQ0gpO1xuICAgICAgICAgICAgICAgIGlmKGNzcykge1xuICAgICAgICAgICAgICAgICAgICBjc3MgPSBjc3MucmVwbGFjZShDT0xPUk1BVENILCAnJDEgZmlsbDonKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodGFnU3R5bGUpIGNzcyArPSAnOycgKyB0YWdTdHlsZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZih0YWdTdHlsZSkgY3NzID0gdGFnU3R5bGU7XG5cbiAgICAgICAgICAgICAgICBpZihjc3MpIG5vZGVTcGVjLnN0eWxlID0gY3NzO1xuXG4gICAgICAgICAgICAgICAgaWYodGFnVHlwZSA9PT0gJ2EnKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc0xpbmsgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBocmVmID0gZ2V0UXVvdGVkTWF0Y2goZXh0cmEsIEhSRUZNQVRDSCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaHJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgc2FmZSBwcm90b2NvbHNcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkdW1teUFuY2hvciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGR1bW15QW5jaG9yLmhyZWYgPSBocmVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoUFJPVE9DT0xTLmluZGV4T2YoZHVtbXlBbmNob3IucHJvdG9jb2wpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlY29kZSBocmVmIHRvIGFsbG93IGJvdGggYWxyZWFkeSBlbmNvZGVkIGFuZCBub3QgZW5jb2RlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVSSXMuIFdpdGhvdXQgZGVjb2RpbmcgcHJpb3IgZW5jb2RpbmcsIGFuIGFscmVhZHkgZW5jb2RlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVSSSB3b3VsZCBiZSBlbmNvZGVkIHR3aWNlIHByb2R1Y2luZyBhIHNlbWFudGljYWxseSBkaWZmZXJlbnQgVVJJLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVTcGVjLmhyZWYgPSBlbmNvZGVVUkkoZGVjb2RlVVJJKGhyZWYpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlU3BlYy50YXJnZXQgPSBnZXRRdW90ZWRNYXRjaChleHRyYSwgVEFSR0VUTUFUQ0gpIHx8ICdfYmxhbmsnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVTcGVjLnBvcHVwID0gZ2V0UXVvdGVkTWF0Y2goZXh0cmEsIFBPUFVQTUFUQ0gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZW50ZXJOb2RlKG5vZGVTcGVjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBoYXNMaW5rO1xufVxuXG5leHBvcnRzLmxpbmVDb3VudCA9IGZ1bmN0aW9uIGxpbmVDb3VudChzKSB7XG4gICAgcmV0dXJuIHMuc2VsZWN0QWxsKCd0c3Bhbi5saW5lJykuc2l6ZSgpIHx8IDE7XG59O1xuXG5leHBvcnRzLnBvc2l0aW9uVGV4dCA9IGZ1bmN0aW9uIHBvc2l0aW9uVGV4dChzLCB4LCB5KSB7XG4gICAgcmV0dXJuIHMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHRleHQgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgZnVuY3Rpb24gc2V0T3JHZXQoYXR0ciwgdmFsKSB7XG4gICAgICAgICAgICBpZih2YWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZhbCA9IHRleHQuYXR0cihhdHRyKTtcbiAgICAgICAgICAgICAgICBpZih2YWwgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dC5hdHRyKGF0dHIsIDApO1xuICAgICAgICAgICAgICAgICAgICB2YWwgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgdGV4dC5hdHRyKGF0dHIsIHZhbCk7XG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRoaXNYID0gc2V0T3JHZXQoJ3gnLCB4KTtcbiAgICAgICAgdmFyIHRoaXNZID0gc2V0T3JHZXQoJ3knLCB5KTtcblxuICAgICAgICBpZih0aGlzLm5vZGVOYW1lID09PSAndGV4dCcpIHtcbiAgICAgICAgICAgIHRleHQuc2VsZWN0QWxsKCd0c3Bhbi5saW5lJykuYXR0cih7eDogdGhpc1gsIHk6IHRoaXNZfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGFsaWduSFRNTFdpdGgoX2Jhc2UsIGNvbnRhaW5lciwgb3B0aW9ucykge1xuICAgIHZhciBhbGlnbkggPSBvcHRpb25zLmhvcml6b250YWxBbGlnbixcbiAgICAgICAgYWxpZ25WID0gb3B0aW9ucy52ZXJ0aWNhbEFsaWduIHx8ICd0b3AnLFxuICAgICAgICBiUmVjdCA9IF9iYXNlLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxcbiAgICAgICAgY1JlY3QgPSBjb250YWluZXIubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFxuICAgICAgICB0aGlzUmVjdCxcbiAgICAgICAgZ2V0VG9wLFxuICAgICAgICBnZXRMZWZ0O1xuXG4gICAgaWYoYWxpZ25WID09PSAnYm90dG9tJykge1xuICAgICAgICBnZXRUb3AgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGJSZWN0LmJvdHRvbSAtIHRoaXNSZWN0LmhlaWdodDsgfTtcbiAgICB9IGVsc2UgaWYoYWxpZ25WID09PSAnbWlkZGxlJykge1xuICAgICAgICBnZXRUb3AgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGJSZWN0LnRvcCArIChiUmVjdC5oZWlnaHQgLSB0aGlzUmVjdC5oZWlnaHQpIC8gMjsgfTtcbiAgICB9IGVsc2UgeyAvLyBkZWZhdWx0OiB0b3BcbiAgICAgICAgZ2V0VG9wID0gZnVuY3Rpb24oKSB7IHJldHVybiBiUmVjdC50b3A7IH07XG4gICAgfVxuXG4gICAgaWYoYWxpZ25IID09PSAncmlnaHQnKSB7XG4gICAgICAgIGdldExlZnQgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGJSZWN0LnJpZ2h0IC0gdGhpc1JlY3Qud2lkdGg7IH07XG4gICAgfSBlbHNlIGlmKGFsaWduSCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgZ2V0TGVmdCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gYlJlY3QubGVmdCArIChiUmVjdC53aWR0aCAtIHRoaXNSZWN0LndpZHRoKSAvIDI7IH07XG4gICAgfSBlbHNlIHsgLy8gZGVmYXVsdDogbGVmdFxuICAgICAgICBnZXRMZWZ0ID0gZnVuY3Rpb24oKSB7IHJldHVybiBiUmVjdC5sZWZ0OyB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpc1JlY3QgPSB0aGlzLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5zdHlsZSh7XG4gICAgICAgICAgICB0b3A6IChnZXRUb3AoKSAtIGNSZWN0LnRvcCkgKyAncHgnLFxuICAgICAgICAgICAgbGVmdDogKGdldExlZnQoKSAtIGNSZWN0LmxlZnQpICsgJ3B4JyxcbiAgICAgICAgICAgICd6LWluZGV4JzogMTAwMFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbn1cblxuLypcbiAqIEVkaXRhYmxlIHRpdGxlXG4gKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gY29udGV4dDogdGhlIGVsZW1lbnQgYmVpbmcgZWRpdGVkLiBOb3JtYWxseSB0ZXh0LFxuICogICBidXQgaWYgaXQgaXNuJ3QsIHlvdSBzaG91bGQgcHJvdmlkZSB0aGUgc3R5bGluZyBvcHRpb25zXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uczpcbiAqICAgQHBhcmFtIHtkaXZ9IG9wdGlvbnMuZ2Q6IGdyYXBoRGl2XG4gKiAgIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBvcHRpb25zLmRlbGVnYXRlOiBpdGVtIHRvIGJpbmQgZXZlbnRzIHRvIGlmIG5vdCB0aGlzXG4gKiAgIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9ucy5pbW1lZGlhdGU6IHN0YXJ0IGVkaXRpbmcgbm93ICh0cnVlKSBvciBvbiBjbGljayAoZmFsc2UsIGRlZmF1bHQpXG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmZpbGw6IGZvbnQgY29sb3IgaWYgbm90IGFzIHNob3duXG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmJhY2tncm91bmQ6IGJhY2tncm91bmQgY29sb3IgaWYgbm90IGFzIHNob3duXG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnRleHQ6IGluaXRpYWwgdGV4dCwgaWYgbm90IGFzIHNob3duXG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmhvcml6b250YWxBbGlnbjogYWxpZ25tZW50IG9mIHRoZSBlZGl0IGJveCB3cnQuIHRoZSBib3VuZCBlbGVtZW50XG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnZlcnRpY2FsQWxpZ246IGFsaWdubWVudCBvZiB0aGUgZWRpdCBib3ggd3J0LiB0aGUgYm91bmQgZWxlbWVudFxuICovXG5cbmV4cG9ydHMubWFrZUVkaXRhYmxlID0gZnVuY3Rpb24oY29udGV4dCwgb3B0aW9ucykge1xuICAgIHZhciBnZCA9IG9wdGlvbnMuZ2Q7XG4gICAgdmFyIF9kZWxlZ2F0ZSA9IG9wdGlvbnMuZGVsZWdhdGU7XG4gICAgdmFyIGRpc3BhdGNoID0gZDMuZGlzcGF0Y2goJ2VkaXQnLCAnaW5wdXQnLCAnY2FuY2VsJyk7XG4gICAgdmFyIGhhbmRsZXJFbGVtZW50ID0gX2RlbGVnYXRlIHx8IGNvbnRleHQ7XG5cbiAgICBjb250ZXh0LnN0eWxlKHsncG9pbnRlci1ldmVudHMnOiBfZGVsZWdhdGUgPyAnbm9uZScgOiAnYWxsJ30pO1xuXG4gICAgaWYoY29udGV4dC5zaXplKCkgIT09IDEpIHRocm93IG5ldyBFcnJvcignYm9vJyk7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVDbGljaygpIHtcbiAgICAgICAgYXBwZW5kRWRpdGFibGUoKTtcbiAgICAgICAgY29udGV4dC5zdHlsZSh7b3BhY2l0eTogMH0pO1xuICAgICAgICAvLyBhbHNvIGhpZGUgYW55IG1hdGhqYXggc3ZnXG4gICAgICAgIHZhciBzdmdDbGFzcyA9IGhhbmRsZXJFbGVtZW50LmF0dHIoJ2NsYXNzJyksXG4gICAgICAgICAgICBtYXRoamF4Q2xhc3M7XG4gICAgICAgIGlmKHN2Z0NsYXNzKSBtYXRoamF4Q2xhc3MgPSAnLicgKyBzdmdDbGFzcy5zcGxpdCgnICcpWzBdICsgJy1tYXRoLWdyb3VwJztcbiAgICAgICAgZWxzZSBtYXRoamF4Q2xhc3MgPSAnW2NsYXNzKj0tbWF0aC1ncm91cF0nO1xuICAgICAgICBpZihtYXRoamF4Q2xhc3MpIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdChjb250ZXh0Lm5vZGUoKS5wYXJlbnROb2RlKS5zZWxlY3QobWF0aGpheENsYXNzKS5zdHlsZSh7b3BhY2l0eTogMH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VsZWN0RWxlbWVudENvbnRlbnRzKF9lbCkge1xuICAgICAgICB2YXIgZWwgPSBfZWwubm9kZSgpO1xuICAgICAgICB2YXIgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgICAgICByYW5nZS5zZWxlY3ROb2RlQ29udGVudHMoZWwpO1xuICAgICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgIHNlbC5hZGRSYW5nZShyYW5nZSk7XG4gICAgICAgIGVsLmZvY3VzKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXBwZW5kRWRpdGFibGUoKSB7XG4gICAgICAgIHZhciBwbG90RGl2ID0gZDMuc2VsZWN0KGdkKTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHBsb3REaXYuc2VsZWN0KCcuc3ZnLWNvbnRhaW5lcicpO1xuICAgICAgICB2YXIgZGl2ID0gY29udGFpbmVyLmFwcGVuZCgnZGl2Jyk7XG4gICAgICAgIHZhciBjU3R5bGUgPSBjb250ZXh0Lm5vZGUoKS5zdHlsZTtcbiAgICAgICAgdmFyIGZvbnRTaXplID0gcGFyc2VGbG9hdChjU3R5bGUuZm9udFNpemUgfHwgMTIpO1xuXG4gICAgICAgIHZhciBpbml0aWFsVGV4dCA9IG9wdGlvbnMudGV4dDtcbiAgICAgICAgaWYoaW5pdGlhbFRleHQgPT09IHVuZGVmaW5lZCkgaW5pdGlhbFRleHQgPSBjb250ZXh0LmF0dHIoJ2RhdGEtdW5mb3JtYXR0ZWQnKTtcblxuICAgICAgICBkaXYuY2xhc3NlZCgncGx1Z2luLWVkaXRhYmxlIGVkaXRhYmxlJywgdHJ1ZSlcbiAgICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgICAgICAgICAgJ2ZvbnQtZmFtaWx5JzogY1N0eWxlLmZvbnRGYW1pbHkgfHwgJ0FyaWFsJyxcbiAgICAgICAgICAgICAgICAnZm9udC1zaXplJzogZm9udFNpemUsXG4gICAgICAgICAgICAgICAgY29sb3I6IG9wdGlvbnMuZmlsbCB8fCBjU3R5bGUuZmlsbCB8fCAnYmxhY2snLFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICAgICAgJ2JhY2tncm91bmQtY29sb3InOiBvcHRpb25zLmJhY2tncm91bmQgfHwgJ3RyYW5zcGFyZW50JyxcbiAgICAgICAgICAgICAgICBvdXRsaW5lOiAnI2ZmZmZmZjMzIDFweCBzb2xpZCcsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiBbLWZvbnRTaXplIC8gOCArIDEsIDAsIDAsIC0xXS5qb2luKCdweCAnKSArICdweCcsXG4gICAgICAgICAgICAgICAgcGFkZGluZzogJzAnLFxuICAgICAgICAgICAgICAgICdib3gtc2l6aW5nJzogJ2JvcmRlci1ib3gnXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmF0dHIoe2NvbnRlbnRlZGl0YWJsZTogdHJ1ZX0pXG4gICAgICAgICAgICAudGV4dChpbml0aWFsVGV4dClcbiAgICAgICAgICAgIC5jYWxsKGFsaWduSFRNTFdpdGgoY29udGV4dCwgY29udGFpbmVyLCBvcHRpb25zKSlcbiAgICAgICAgICAgIC5vbignYmx1cicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGdkLl9lZGl0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY29udGV4dC50ZXh0KHRoaXMudGV4dENvbnRlbnQpXG4gICAgICAgICAgICAgICAgICAgIC5zdHlsZSh7b3BhY2l0eTogMX0pO1xuICAgICAgICAgICAgICAgIHZhciBzdmdDbGFzcyA9IGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdjbGFzcycpLFxuICAgICAgICAgICAgICAgICAgICBtYXRoamF4Q2xhc3M7XG4gICAgICAgICAgICAgICAgaWYoc3ZnQ2xhc3MpIG1hdGhqYXhDbGFzcyA9ICcuJyArIHN2Z0NsYXNzLnNwbGl0KCcgJylbMF0gKyAnLW1hdGgtZ3JvdXAnO1xuICAgICAgICAgICAgICAgIGVsc2UgbWF0aGpheENsYXNzID0gJ1tjbGFzcyo9LW1hdGgtZ3JvdXBdJztcbiAgICAgICAgICAgICAgICBpZihtYXRoamF4Q2xhc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgZDMuc2VsZWN0KGNvbnRleHQubm9kZSgpLnBhcmVudE5vZGUpLnNlbGVjdChtYXRoamF4Q2xhc3MpLnN0eWxlKHtvcGFjaXR5OiAwfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gdGhpcy50ZXh0Q29udGVudDtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykudHJhbnNpdGlvbigpLmR1cmF0aW9uKDApLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdChkb2N1bWVudCkub24oJ21vdXNldXAnLCBudWxsKTtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaC5lZGl0LmNhbGwoY29udGV4dCwgdGV4dCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdmb2N1cycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciBlZGl0RGl2ID0gdGhpcztcbiAgICAgICAgICAgICAgICBnZC5fZWRpdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KGRvY3VtZW50KS5vbignbW91c2V1cCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZihkMy5ldmVudC50YXJnZXQgPT09IGVkaXREaXYpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZGl2Lm5vZGUoKSkgZGl2Lm5vZGUoKS5ibHVyKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdrZXl1cCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGlmKGQzLmV2ZW50LndoaWNoID09PSAyNykge1xuICAgICAgICAgICAgICAgICAgICBnZC5fZWRpdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LnN0eWxlKHtvcGFjaXR5OiAxfSk7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnN0eWxlKHtvcGFjaXR5OiAwfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5vbignYmx1cicsIGZ1bmN0aW9uKCkgeyByZXR1cm4gZmFsc2U7IH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAudHJhbnNpdGlvbigpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICBkaXNwYXRjaC5jYW5jZWwuY2FsbChjb250ZXh0LCB0aGlzLnRleHRDb250ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoLmlucHV0LmNhbGwoY29udGV4dCwgdGhpcy50ZXh0Q29udGVudCk7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5jYWxsKGFsaWduSFRNTFdpdGgoY29udGV4dCwgY29udGFpbmVyLCBvcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbigna2V5ZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGlmKGQzLmV2ZW50LndoaWNoID09PSAxMykgdGhpcy5ibHVyKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhbGwoc2VsZWN0RWxlbWVudENvbnRlbnRzKTtcbiAgICB9XG5cbiAgICBpZihvcHRpb25zLmltbWVkaWF0ZSkgaGFuZGxlQ2xpY2soKTtcbiAgICBlbHNlIGhhbmRsZXJFbGVtZW50Lm9uKCdjbGljaycsIGhhbmRsZUNsaWNrKTtcblxuICAgIHJldHVybiBkMy5yZWJpbmQoY29udGV4dCwgZGlzcGF0Y2gsICdvbicpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHRpbWVyQ2FjaGUgPSB7fTtcblxuLyoqXG4gKiBUaHJvdHRsZSBhIGNhbGxiYWNrLiBgY2FsbGJhY2tgIGV4ZWN1dGVzIHN5bmNocm9ub3VzbHkgb25seSBpZlxuICogbW9yZSB0aGFuIGBtaW5JbnRlcnZhbGAgbWlsbGlzZWNvbmRzIGhhdmUgYWxyZWFkeSBlbGFwc2VkIHNpbmNlIHRoZSBsYXRlc3RcbiAqIGNhbGwgKGlmIGFueSkuIE90aGVyd2lzZSB3ZSB3YWl0IHVudGlsIGBtaW5JbnRlcnZhbGAgaXMgb3ZlciBhbmQgZXhlY3V0ZSB0aGVcbiAqIGxhc3QgY2FsbGJhY2sgcmVjZWl2ZWQgd2hpbGUgd2FpdGluZy5cbiAqIFNvIHRoZSBmaXJzdCBhbmQgbGFzdCBldmVudHMgaW4gYSB0cmFpbiBhcmUgYWx3YXlzIGV4ZWN1dGVkIChldmVudHVhbGx5KVxuICogYnV0IHNvbWUgb2YgdGhlIGV2ZW50cyBpbiB0aGUgbWlkZGxlIGNhbiBiZSBkcm9wcGVkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZDogYW4gaWRlbnRpZmllciB0byBtYXJrIGV2ZW50cyB0byB0aHJvdHRsZSB0b2dldGhlclxuICogQHBhcmFtIHtudW1iZXJ9IG1pbkludGVydmFsOiBtaW5pbXVtIHRpbWUsIGluIG1pbGxpc2Vjb25kcywgYmV0d2VlblxuICogICBpbnZvY2F0aW9ucyBvZiBgY2FsbGJhY2tgXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjazogdGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLiBgY2FsbGJhY2tgIGl0c2VsZlxuICogICBzaG91bGQgYmUgYSBwdXJlbHkgc3luY2hyb25vdXMgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydHMudGhyb3R0bGUgPSBmdW5jdGlvbiB0aHJvdHRsZShpZCwgbWluSW50ZXJ2YWwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGNhY2hlID0gdGltZXJDYWNoZVtpZF07XG4gICAgdmFyIG5vdyA9IERhdGUubm93KCk7XG5cbiAgICBpZighY2FjaGUpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogVGhyb3cgb3V0IG9sZCBpdGVtcyBiZWZvcmUgbWFraW5nIGEgbmV3IG9uZSwgdG8gcHJldmVudCB0aGUgY2FjaGVcbiAgICAgICAgICogZ2V0dGluZyBvdmVyZ3Jvd24sIGZvciBleGFtcGxlIGZyb20gb2xkIHBsb3RzIHRoYXQgaGF2ZSBiZWVuIHJlcGxhY2VkLlxuICAgICAgICAgKiAxIG1pbnV0ZSBhZ2UgaXMgYXJiaXRyYXJ5LlxuICAgICAgICAgKi9cbiAgICAgICAgZm9yKHZhciBpZGkgaW4gdGltZXJDYWNoZSkge1xuICAgICAgICAgICAgaWYodGltZXJDYWNoZVtpZGldLnRzIDwgbm93IC0gNjAwMDApIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGltZXJDYWNoZVtpZGldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhY2hlID0gdGltZXJDYWNoZVtpZF0gPSB7dHM6IDAsIHRpbWVyOiBudWxsfTtcbiAgICB9XG5cbiAgICBfY2xlYXJUaW1lb3V0KGNhY2hlKTtcblxuICAgIGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGNhY2hlLnRzID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYoY2FjaGUub25Eb25lKSB7XG4gICAgICAgICAgICBjYWNoZS5vbkRvbmUoKTtcbiAgICAgICAgICAgIGNhY2hlLm9uRG9uZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihub3cgPiBjYWNoZS50cyArIG1pbkludGVydmFsKSB7XG4gICAgICAgIGV4ZWMoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNhY2hlLnRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgZXhlYygpO1xuICAgICAgICBjYWNoZS50aW1lciA9IG51bGw7XG4gICAgfSwgbWluSW50ZXJ2YWwpO1xufTtcblxuZXhwb3J0cy5kb25lID0gZnVuY3Rpb24oaWQpIHtcbiAgICB2YXIgY2FjaGUgPSB0aW1lckNhY2hlW2lkXTtcbiAgICBpZighY2FjaGUgfHwgIWNhY2hlLnRpbWVyKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICB2YXIgcHJldmlvdXNPbkRvbmUgPSBjYWNoZS5vbkRvbmU7XG4gICAgICAgIGNhY2hlLm9uRG9uZSA9IGZ1bmN0aW9uIG9uRG9uZSgpIHtcbiAgICAgICAgICAgIGlmKHByZXZpb3VzT25Eb25lKSBwcmV2aW91c09uRG9uZSgpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgY2FjaGUub25Eb25lID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogQ2xlYXIgdGhlIHRocm90dGxlIGNhY2hlIGZvciBvbmUgb3IgYWxsIHRpbWVyc1xuICogQHBhcmFtIHtvcHRpb25hbCBzdHJpbmd9IGlkOlxuICogICBpZiBwcm92aWRlZCwgY2xlYXIganVzdCB0aGlzIHRpbWVyXG4gKiAgIGlmIG9taXR0ZWQsIGNsZWFyIGFsbCB0aW1lcnMgKG1haW5seSB1c2VmdWwgZm9yIHRlc3RpbmcpXG4gKi9cbmV4cG9ydHMuY2xlYXIgPSBmdW5jdGlvbihpZCkge1xuICAgIGlmKGlkKSB7XG4gICAgICAgIF9jbGVhclRpbWVvdXQodGltZXJDYWNoZVtpZF0pO1xuICAgICAgICBkZWxldGUgdGltZXJDYWNoZVtpZF07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmb3IodmFyIGlkaSBpbiB0aW1lckNhY2hlKSBleHBvcnRzLmNsZWFyKGlkaSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gX2NsZWFyVGltZW91dChjYWNoZSkge1xuICAgIGlmKGNhY2hlICYmIGNhY2hlLnRpbWVyICE9PSBudWxsKSB7XG4gICAgICAgIGNsZWFyVGltZW91dChjYWNoZS50aW1lcik7XG4gICAgICAgIGNhY2hlLnRpbWVyID0gbnVsbDtcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG4vKipcbiAqIGNvbnZlcnQgYSBsaW5lYXIgdmFsdWUgaW50byBhIGxvZ2dlZCB2YWx1ZSwgZm9sZGluZyBuZWdhdGl2ZSBudW1iZXJzIGludG9cbiAqIHRoZSBnaXZlbiByYW5nZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRvTG9nUmFuZ2UodmFsLCByYW5nZSkge1xuICAgIGlmKHZhbCA+IDApIHJldHVybiBNYXRoLmxvZyh2YWwpIC8gTWF0aC5MTjEwO1xuXG4gICAgLy8gbW92ZSBhIG5lZ2F0aXZlIHZhbHVlIHJlZmVyZW5jZSB0byBhIGxvZyBheGlzIC0ganVzdCBwdXQgdGhlXG4gICAgLy8gcmVzdWx0IGF0IHRoZSBsb3dlc3QgcmFuZ2UgdmFsdWUgb24gdGhlIHBsb3QgKG9yIGlmIHRoZSByYW5nZSBhbHNvIHdlbnQgbmVnYXRpdmUsXG4gICAgLy8gb25lIG1pbGxpb250aCBvZiB0aGUgdG9wIG9mIHRoZSByYW5nZSlcbiAgICB2YXIgbmV3VmFsID0gTWF0aC5sb2coTWF0aC5taW4ocmFuZ2VbMF0sIHJhbmdlWzFdKSkgLyBNYXRoLkxOMTA7XG4gICAgaWYoIWlzTnVtZXJpYyhuZXdWYWwpKSBuZXdWYWwgPSBNYXRoLmxvZyhNYXRoLm1heChyYW5nZVswXSwgcmFuZ2VbMV0pKSAvIE1hdGguTE4xMCAtIDY7XG4gICAgcmV0dXJuIG5ld1ZhbDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHRvcG9qc29uVXRpbHMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG52YXIgbG9jYXRpb25tb2RlVG9MYXllciA9IHJlcXVpcmUoJy4uL3Bsb3RzL2dlby9jb25zdGFudHMnKS5sb2NhdGlvbm1vZGVUb0xheWVyO1xudmFyIHRvcG9qc29uRmVhdHVyZSA9IHJlcXVpcmUoJ3RvcG9qc29uLWNsaWVudCcpLmZlYXR1cmU7XG5cblxudG9wb2pzb25VdGlscy5nZXRUb3BvanNvbk5hbWUgPSBmdW5jdGlvbihnZW9MYXlvdXQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBnZW9MYXlvdXQuc2NvcGUucmVwbGFjZSgvIC9nLCAnLScpLCAnXycsXG4gICAgICAgIGdlb0xheW91dC5yZXNvbHV0aW9uLnRvU3RyaW5nKCksICdtJ1xuICAgIF0uam9pbignJyk7XG59O1xuXG50b3BvanNvblV0aWxzLmdldFRvcG9qc29uUGF0aCA9IGZ1bmN0aW9uKHRvcG9qc29uVVJMLCB0b3BvanNvbk5hbWUpIHtcbiAgICByZXR1cm4gdG9wb2pzb25VUkwgKyB0b3BvanNvbk5hbWUgKyAnLmpzb24nO1xufTtcblxudG9wb2pzb25VdGlscy5nZXRUb3BvanNvbkZlYXR1cmVzID0gZnVuY3Rpb24odHJhY2UsIHRvcG9qc29uKSB7XG4gICAgdmFyIGxheWVyID0gbG9jYXRpb25tb2RlVG9MYXllclt0cmFjZS5sb2NhdGlvbm1vZGVdLFxuICAgICAgICBvYmogPSB0b3BvanNvbi5vYmplY3RzW2xheWVyXTtcblxuICAgIHJldHVybiB0b3BvanNvbkZlYXR1cmUodG9wb2pzb24sIG9iaikuZmVhdHVyZXM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnbG9jYWxlJyxcbiAgICBuYW1lOiAnZW4tVVMnLFxuICAgIGRpY3Rpb25hcnk6IHtcbiAgICAgICAgJ0NsaWNrIHRvIGVudGVyIENvbG9yc2NhbGUgdGl0bGUnOiAnQ2xpY2sgdG8gZW50ZXIgQ29sb3JzY2FsZSB0aXRsZSdcbiAgICB9LFxuICAgIGZvcm1hdDoge1xuICAgICAgICBkYXRlOiAnJW0vJWQvJVknXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2xvY2FsZScsXG4gICAgbmFtZTogJ2VuJyxcbiAgICBkaWN0aW9uYXJ5OiB7XG4gICAgICAgICdDbGljayB0byBlbnRlciBDb2xvcnNjYWxlIHRpdGxlJzogJ0NsaWNrIHRvIGVudGVyIENvbG91cnNjYWxlIHRpdGxlJ1xuICAgIH0sXG4gICAgZm9ybWF0OiB7XG4gICAgICAgIGRheXM6IFsnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknXSxcbiAgICAgICAgc2hvcnREYXlzOiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLFxuICAgICAgICBtb250aHM6IFtcbiAgICAgICAgICAgICdKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlcidcbiAgICAgICAgXSxcbiAgICAgICAgc2hvcnRNb250aHM6IFtcbiAgICAgICAgICAgICdKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsXG4gICAgICAgICAgICAnSnVsJywgJ0F1ZycsICdTZXAnLCAnT2N0JywgJ05vdicsICdEZWMnXG4gICAgICAgIF0sXG4gICAgICAgIHBlcmlvZHM6IFsnQU0nLCAnUE0nXSxcbiAgICAgICAgZGF0ZVRpbWU6ICclYSAlYiAlZSAlWCAlWScsXG4gICAgICAgIGRhdGU6ICclZC8lbS8lWScsXG4gICAgICAgIHRpbWU6ICclSDolTTolUycsXG4gICAgICAgIGRlY2ltYWw6ICcuJyxcbiAgICAgICAgdGhvdXNhbmRzOiAnLCcsXG4gICAgICAgIGdyb3VwaW5nOiBbM10sXG4gICAgICAgIGN1cnJlbmN5OiBbJyQnLCAnJ10sXG4gICAgICAgIHllYXI6ICclWScsXG4gICAgICAgIG1vbnRoOiAnJWIgJVknLFxuICAgICAgICBkYXlNb250aDogJyViICUtZCcsXG4gICAgICAgIGRheU1vbnRoWWVhcjogJyViICUtZCwgJVknXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi9yZWdpc3RyeScpO1xuXG4vKlxuICogY29udGFpbmVyQXJyYXlNYXRjaDogZG9lcyB0aGlzIGF0dHJpYnV0ZSBzdHJpbmcgcG9pbnQgaW50byBhXG4gKiBsYXlvdXQgY29udGFpbmVyIGFycmF5P1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBhc3RyOiBhbiBhdHRyaWJ1dGUgc3RyaW5nLCBsaWtlICphbm5vdGF0aW9uc1syXS50ZXh0KlxuICpcbiAqIEByZXR1cm5zIHtPYmplY3QgfCBmYWxzZX0gUmV0dXJucyBmYWxzZSBpZiBgYXN0cmAgZG9lc24ndCBtYXRjaCBhIGNvbnRhaW5lclxuICogIGFycmF5LiBJZiBpdCBkb2VzLCByZXR1cm5zOlxuICogICAgIHthcnJheToge1N0cmluZ30sIGluZGV4OiB7TnVtYmVyfSwgcHJvcGVydHk6IHtTdHJpbmd9fVxuICogIGllIHRoZSBhdHRyaWJ1dGUgc3RyaW5nIGZvciB0aGUgYXJyYXksIHRoZSBpbmRleCB3aXRoaW4gdGhlIGFycmF5IChvciAnJ1xuICogIGlmIHRoZSB3aG9sZSBhcnJheSkgYW5kIHRoZSBwcm9wZXJ0eSB3aXRoaW4gdGhhdCAob3IgJycgaWYgdGhlIHdob2xlIGFycmF5XG4gKiAgb3IgdGhlIHdob2xlIG9iamVjdClcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb250YWluZXJBcnJheU1hdGNoKGFzdHIpIHtcbiAgICB2YXIgcm9vdENvbnRhaW5lcnMgPSBSZWdpc3RyeS5sYXlvdXRBcnJheUNvbnRhaW5lcnMsXG4gICAgICAgIHJlZ2V4cENvbnRhaW5lcnMgPSBSZWdpc3RyeS5sYXlvdXRBcnJheVJlZ2V4ZXMsXG4gICAgICAgIHJvb3RQYXJ0ID0gYXN0ci5zcGxpdCgnWycpWzBdLFxuICAgICAgICBhcnJheVN0cixcbiAgICAgICAgbWF0Y2g7XG5cbiAgICAvLyBsb29rIGZvciByZWdleHAgbWF0Y2hlcyBmaXJzdCwgYmVjYXVzZSB0aGV5IG1heSBiZSBuZXN0ZWQgaW5zaWRlIHJvb3QgbWF0Y2hlc1xuICAgIC8vIGVnIHVwZGF0ZW1lbnVzW2ldLmJ1dHRvbnMgaXMgbmVzdGVkIGluc2lkZSB1cGRhdGVtZW51c1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCByZWdleHBDb250YWluZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG1hdGNoID0gYXN0ci5tYXRjaChyZWdleHBDb250YWluZXJzW2ldKTtcbiAgICAgICAgaWYobWF0Y2ggJiYgbWF0Y2guaW5kZXggPT09IDApIHtcbiAgICAgICAgICAgIGFycmF5U3RyID0gbWF0Y2hbMF07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG5vdyBsb29rIGZvciByb290IG1hdGNoZXNcbiAgICBpZighYXJyYXlTdHIpIGFycmF5U3RyID0gcm9vdENvbnRhaW5lcnNbcm9vdENvbnRhaW5lcnMuaW5kZXhPZihyb290UGFydCldO1xuXG4gICAgaWYoIWFycmF5U3RyKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgdGFpbCA9IGFzdHIuc3Vic3RyKGFycmF5U3RyLmxlbmd0aCk7XG4gICAgaWYoIXRhaWwpIHJldHVybiB7YXJyYXk6IGFycmF5U3RyLCBpbmRleDogJycsIHByb3BlcnR5OiAnJ307XG5cbiAgICBtYXRjaCA9IHRhaWwubWF0Y2goL15cXFsoMHxbMS05XVswLTldKilcXF0oXFwuKC4rKSk/JC8pO1xuICAgIGlmKCFtYXRjaCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgcmV0dXJuIHthcnJheTogYXJyYXlTdHIsIGluZGV4OiBOdW1iZXIobWF0Y2hbMV0pLCBwcm9wZXJ0eTogbWF0Y2hbM10gfHwgJyd9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIGV4dGVuZEZsYXQgPSBMaWIuZXh0ZW5kRmxhdDtcbnZhciBpc1BsYWluT2JqZWN0ID0gTGliLmlzUGxhaW5PYmplY3Q7XG5cbnZhciB0cmFjZU9wdHMgPSB7XG4gICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICBleHRyYXM6IFsnbm9uZSddLFxuICAgIGZsYWdzOiBbJ2NhbGMnLCAnY2xlYXJBeGlzVHlwZXMnLCAncGxvdCcsICdzdHlsZScsICdtYXJrZXJTaXplJywgJ2NvbG9yYmFycyddLFxuICAgIFxufTtcblxudmFyIGxheW91dE9wdHMgPSB7XG4gICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICBleHRyYXM6IFsnbm9uZSddLFxuICAgIGZsYWdzOiBbXG4gICAgICAgICdjYWxjJywgJ3Bsb3QnLCAnbGVnZW5kJywgJ3RpY2tzJywgJ2F4cmFuZ2UnLFxuICAgICAgICAnbGF5b3V0c3R5bGUnLCAnbW9kZWJhcicsICdjYW1lcmEnLCAnYXJyYXlkcmF3J1xuICAgIF0sXG4gICAgXG59O1xuXG4vLyBmbGFncyBmb3IgaW5zaWRlIHJlc3R5bGUvcmVsYXlvdXQgaW5jbHVkZSBhIGZldyBleHRyYXNcbi8vIHRoYXQgc2hvdWxkbid0IGJlIHVzZWQgaW4gYXR0cmlidXRlcywgdG8gZGVhbCB3aXRoIGNlcnRhaW5cbi8vIGNvbWJpbmF0aW9ucyBhbmQgY29uZGl0aW9uYWxzIGVmZmljaWVudGx5XG52YXIgdHJhY2VFZGl0VHlwZUZsYWdzID0gdHJhY2VPcHRzLmZsYWdzLnNsaWNlKClcbiAgICAuY29uY2F0KFsnZnVsbFJlcGxvdCddKTtcblxudmFyIGxheW91dEVkaXRUeXBlRmxhZ3MgPSBsYXlvdXRPcHRzLmZsYWdzLnNsaWNlKClcbiAgICAuY29uY2F0KCdsYXlvdXRSZXBsb3QnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgdHJhY2VzOiB0cmFjZU9wdHMsXG4gICAgbGF5b3V0OiBsYXlvdXRPcHRzLFxuICAgIC8qXG4gICAgICogZGVmYXVsdCAoYWxsIGZhbHNlKSBlZGl0IGZsYWdzIGZvciByZXN0eWxlICh0cmFjZXMpXG4gICAgICogY3JlYXRlcyBhIG5ldyBvYmplY3QgZWFjaCBjYWxsLCBzbyB0aGUgY2FsbGVyIGNhbiBtdXRhdGUgZnJlZWx5XG4gICAgICovXG4gICAgdHJhY2VGbGFnczogZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZU9iaih0cmFjZUVkaXRUeXBlRmxhZ3MpOyB9LFxuXG4gICAgLypcbiAgICAgKiBkZWZhdWx0IChhbGwgZmFsc2UpIGVkaXQgZmxhZ3MgZm9yIHJlbGF5b3V0XG4gICAgICogY3JlYXRlcyBhIG5ldyBvYmplY3QgZWFjaCBjYWxsLCBzbyB0aGUgY2FsbGVyIGNhbiBtdXRhdGUgZnJlZWx5XG4gICAgICovXG4gICAgbGF5b3V0RmxhZ3M6IGZ1bmN0aW9uKCkgeyByZXR1cm4gZmFsc2VPYmoobGF5b3V0RWRpdFR5cGVGbGFncyk7IH0sXG5cbiAgICAvKlxuICAgICAqIHVwZGF0ZSBgZmxhZ3NgIHdpdGggdGhlIGBlZGl0VHlwZWAgdmFsdWVzIGZvdW5kIGluIGBhdHRyYFxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24oZmxhZ3MsIGF0dHIpIHtcbiAgICAgICAgdmFyIGVkaXRUeXBlID0gYXR0ci5lZGl0VHlwZTtcbiAgICAgICAgaWYoZWRpdFR5cGUgJiYgZWRpdFR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgdmFyIGVkaXRUeXBlUGFydHMgPSBlZGl0VHlwZS5zcGxpdCgnKycpO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGVkaXRUeXBlUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmbGFnc1tlZGl0VHlwZVBhcnRzW2ldXSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgb3ZlcnJpZGVBbGw6IG92ZXJyaWRlQWxsXG59O1xuXG5mdW5jdGlvbiBmYWxzZU9iaihrZXlzKSB7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSBvdXRba2V5c1tpXV0gPSBmYWxzZTtcbiAgICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIEZvciBhdHRyaWJ1dGVzIHRoYXQgYXJlIGxhcmdlbHkgY29waWVkIGZyb20gZWxzZXdoZXJlIGludG8gYSBwbG90IHR5cGUgdGhhdCBkb2Vzbid0XG4gKiBzdXBwb3J0IHBhcnRpYWwgcmVkcmF3cyAtIG92ZXJyaWRlcyB0aGUgZWRpdFR5cGUgZmllbGQgb2YgYWxsIGF0dHJpYnV0ZXMgaW4gdGhlIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBhdHRyczogdGhlIGF0dHJpYnV0ZXMgdG8gb3ZlcnJpZGUuIFdpbGwgbm90IGJlIG11dGF0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZWRpdFR5cGVPdmVycmlkZTogdGhlIG5ldyBlZGl0VHlwZSB0byB1c2VcbiAqIEBwYXJhbSB7J25lc3RlZCd8J2Zyb20tcm9vdCd9IG92ZXJyaWRlQ29udGFpbmVyczpcbiAqICAgLSAnbmVzdGVkJyB3aWxsIG92ZXJyaWRlIGVkaXRUeXBlIGZvciBuZXN0ZWQgY29udGFpbmVycyBidXQgbm90IHRoZSByb290LlxuICogICAtICdmcm9tLXJvb3QnIHdpbGwgYWxzbyBvdmVycmlkZSBlZGl0VHlwZSBvZiB0aGUgcm9vdCBjb250YWluZXIuXG4gKiAgIENvbnRhaW5lcnMgYmVsb3cgdGhlIGFic29sdXRlIHRvcCBsZXZlbCAodHJhY2Ugb3IgbGF5b3V0IHJvb3QpIERPIG5lZWQgYW5cbiAqICAgZWRpdFR5cGUgZXZlbiBpZiB0aGV5IGFyZSBub3QgYHZhbE9iamVjdGBzIHRoZW1zZWx2ZXMgKGVnIGBzY2F0dGVyLm1hcmtlcmApXG4gKiAgIHRvIGhhbmRsZSB0aGUgY2FzZSB3aGVyZSB5b3UgZWRpdCB0aGUgd2hvbGUgY29udGFpbmVyLlxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gYSBuZXcgYXR0cmlidXRlcyBvYmplY3Qgd2l0aCBgZWRpdFR5cGVgIG1vZGlmaWVkIGFzIGRpcmVjdGVkXG4gKi9cbmZ1bmN0aW9uIG92ZXJyaWRlQWxsKGF0dHJzLCBlZGl0VHlwZU92ZXJyaWRlLCBvdmVycmlkZUNvbnRhaW5lcnMpIHtcbiAgICB2YXIgb3V0ID0gZXh0ZW5kRmxhdCh7fSwgYXR0cnMpO1xuICAgIGZvcih2YXIga2V5IGluIG91dCkge1xuICAgICAgICB2YXIgYXR0ciA9IG91dFtrZXldO1xuICAgICAgICBpZihpc1BsYWluT2JqZWN0KGF0dHIpKSB7XG4gICAgICAgICAgICBvdXRba2V5XSA9IG92ZXJyaWRlT25lKGF0dHIsIGVkaXRUeXBlT3ZlcnJpZGUsIG92ZXJyaWRlQ29udGFpbmVycywga2V5KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZihvdmVycmlkZUNvbnRhaW5lcnMgPT09ICdmcm9tLXJvb3QnKSBvdXQuZWRpdFR5cGUgPSBlZGl0VHlwZU92ZXJyaWRlO1xuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gb3ZlcnJpZGVPbmUoYXR0ciwgZWRpdFR5cGVPdmVycmlkZSwgb3ZlcnJpZGVDb250YWluZXJzLCBrZXkpIHtcbiAgICBpZihhdHRyLnZhbFR5cGUpIHtcbiAgICAgICAgdmFyIG91dCA9IGV4dGVuZEZsYXQoe30sIGF0dHIpO1xuICAgICAgICBvdXQuZWRpdFR5cGUgPSBlZGl0VHlwZU92ZXJyaWRlO1xuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0ci5pdGVtcykpIHtcbiAgICAgICAgICAgIG91dC5pdGVtcyA9IG5ldyBBcnJheShhdHRyLml0ZW1zLmxlbmd0aCk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXR0ci5pdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG91dC5pdGVtc1tpXSA9IG92ZXJyaWRlT25lKGF0dHIuaXRlbXNbaV0sIGVkaXRUeXBlT3ZlcnJpZGUsICdmcm9tLXJvb3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gZG9uJ3QgcHJvdmlkZSBhbiBlZGl0VHlwZSBmb3IgdGhlIF9kZXByZWNhdGVkIGNvbnRhaW5lclxuICAgICAgICByZXR1cm4gb3ZlcnJpZGVBbGwoYXR0ciwgZWRpdFR5cGVPdmVycmlkZSxcbiAgICAgICAgICAgIChrZXkuY2hhckF0KDApID09PSAnXycpID8gJ25lc3RlZCcgOiAnZnJvbS1yb290Jyk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIG00RnJvbVF1YXQgPSByZXF1aXJlKCdnbC1tYXQ0L2Zyb21RdWF0Jyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG52YXIgUGxvdHMgPSByZXF1aXJlKCcuLi9wbG90cy9wbG90cycpO1xudmFyIEF4aXNJZHMgPSByZXF1aXJlKCcuLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcbnZhciBjbGVhbklkID0gQXhpc0lkcy5jbGVhbklkO1xudmFyIGdldEZyb21UcmFjZSA9IEF4aXNJZHMuZ2V0RnJvbVRyYWNlO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG5cbi8vIGNsZWFyIHRoZSBwcm9taXNlIHF1ZXVlIGlmIG9uZSBvZiB0aGVtIGdvdCByZWplY3RlZFxuZXhwb3J0cy5jbGVhclByb21pc2VRdWV1ZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShnZC5fcHJvbWlzZXMpICYmIGdkLl9wcm9taXNlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIExpYi5sb2coJ0NsZWFyaW5nIHByZXZpb3VzIHJlamVjdGVkIHByb21pc2VzIGZyb20gcXVldWUuJyk7XG4gICAgfVxuXG4gICAgZ2QuX3Byb21pc2VzID0gW107XG59O1xuXG4vLyBtYWtlIGEgZmV3IGNoYW5nZXMgdG8gdGhlIGxheW91dCByaWdodCBhd2F5XG4vLyBiZWZvcmUgaXQgZ2V0cyB1c2VkIGZvciBhbnl0aGluZ1xuLy8gYmFja3dhcmQgY29tcGF0aWJpbGl0eSBhbmQgY2xlYW51cCBvZiBub25zdGFuZGFyZCBvcHRpb25zXG5leHBvcnRzLmNsZWFuTGF5b3V0ID0gZnVuY3Rpb24obGF5b3V0KSB7XG4gICAgdmFyIGksIGo7XG5cbiAgICBpZighbGF5b3V0KSBsYXlvdXQgPSB7fTtcblxuICAgIC8vIGNhbm5vdCBoYXZlICh4fHkpYXhpczEsIG51bWJlcmluZyBnb2VzIGF4aXMsIGF4aXMyLCBheGlzMy4uLlxuICAgIGlmKGxheW91dC54YXhpczEpIHtcbiAgICAgICAgaWYoIWxheW91dC54YXhpcykgbGF5b3V0LnhheGlzID0gbGF5b3V0LnhheGlzMTtcbiAgICAgICAgZGVsZXRlIGxheW91dC54YXhpczE7XG4gICAgfVxuICAgIGlmKGxheW91dC55YXhpczEpIHtcbiAgICAgICAgaWYoIWxheW91dC55YXhpcykgbGF5b3V0LnlheGlzID0gbGF5b3V0LnlheGlzMTtcbiAgICAgICAgZGVsZXRlIGxheW91dC55YXhpczE7XG4gICAgfVxuICAgIGlmKGxheW91dC5zY2VuZTEpIHtcbiAgICAgICAgaWYoIWxheW91dC5zY2VuZSkgbGF5b3V0LnNjZW5lID0gbGF5b3V0LnNjZW5lMTtcbiAgICAgICAgZGVsZXRlIGxheW91dC5zY2VuZTE7XG4gICAgfVxuXG4gICAgdmFyIGF4aXNBdHRyUmVnZXggPSAoUGxvdHMuc3VicGxvdHNSZWdpc3RyeS5jYXJ0ZXNpYW4gfHwge30pLmF0dHJSZWdleDtcbiAgICB2YXIgc2NlbmVBdHRyUmVnZXggPSAoUGxvdHMuc3VicGxvdHNSZWdpc3RyeS5nbDNkIHx8IHt9KS5hdHRyUmVnZXg7XG5cbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGxheW91dCk7XG4gICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcblxuICAgICAgICAvLyBtb2RpZmljYXRpb25zIHRvIGNhcnRlc2lhbiBheGVzXG4gICAgICAgIGlmKGF4aXNBdHRyUmVnZXggJiYgYXhpc0F0dHJSZWdleC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgIHZhciBheCA9IGxheW91dFtrZXldO1xuICAgICAgICAgICAgaWYoYXguYW5jaG9yICYmIGF4LmFuY2hvciAhPT0gJ2ZyZWUnKSB7XG4gICAgICAgICAgICAgICAgYXguYW5jaG9yID0gY2xlYW5JZChheC5hbmNob3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoYXgub3ZlcmxheWluZykgYXgub3ZlcmxheWluZyA9IGNsZWFuSWQoYXgub3ZlcmxheWluZyk7XG5cbiAgICAgICAgICAgIC8vIG9sZCBtZXRob2Qgb2YgYXhpcyB0eXBlIC0gaXNkYXRlIGFuZCBpc2xvZyAoYmVmb3JlIGNhdGVnb3J5IGV4aXN0ZWQpXG4gICAgICAgICAgICBpZighYXgudHlwZSkge1xuICAgICAgICAgICAgICAgIGlmKGF4LmlzZGF0ZSkgYXgudHlwZSA9ICdkYXRlJztcbiAgICAgICAgICAgICAgICBlbHNlIGlmKGF4LmlzbG9nKSBheC50eXBlID0gJ2xvZyc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZihheC5pc2RhdGUgPT09IGZhbHNlICYmIGF4LmlzbG9nID09PSBmYWxzZSkgYXgudHlwZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoYXguYXV0b3JhbmdlID09PSAnd2l0aHplcm8nIHx8IGF4LmF1dG9yYW5nZSA9PT0gJ3RvemVybycpIHtcbiAgICAgICAgICAgICAgICBheC5hdXRvcmFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGF4LnJhbmdlbW9kZSA9ICd0b3plcm8nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGF4LmlzbG9nO1xuICAgICAgICAgICAgZGVsZXRlIGF4LmlzZGF0ZTtcbiAgICAgICAgICAgIGRlbGV0ZSBheC5jYXRlZ29yaWVzOyAvLyByZXBsYWNlZCBieSBfY2F0ZWdvcmllc1xuXG4gICAgICAgICAgICAvLyBwcnVuZSBlbXB0eSBkb21haW4gYXJyYXlzIG1hZGUgYmVmb3JlIHRoZSBuZXcgbmVzdGVkUHJvcGVydHlcbiAgICAgICAgICAgIGlmKGVtcHR5Q29udGFpbmVyKGF4LCAnZG9tYWluJykpIGRlbGV0ZSBheC5kb21haW47XG5cbiAgICAgICAgICAgIC8vIGF1dG90aWNrIC0+IHRpY2ttb2RlXG4gICAgICAgICAgICBpZihheC5hdXRvdGljayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYoYXgudGlja21vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBheC50aWNrbW9kZSA9IGF4LmF1dG90aWNrID8gJ2F1dG8nIDogJ2xpbmVhcic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSBheC5hdXRvdGljaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1vZGlmaWNhdGlvbnMgZm9yIDNEIHNjZW5lc1xuICAgICAgICBlbHNlIGlmKHNjZW5lQXR0clJlZ2V4ICYmIHNjZW5lQXR0clJlZ2V4LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgdmFyIHNjZW5lID0gbGF5b3V0W2tleV07XG5cbiAgICAgICAgICAgIC8vIGNsZWFuIG9sZCBDYW1lcmEgY29vcmRzXG4gICAgICAgICAgICB2YXIgY2FtZXJhcG9zaXRpb24gPSBzY2VuZS5jYW1lcmFwb3NpdGlvbjtcblxuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShjYW1lcmFwb3NpdGlvbikgJiYgY2FtZXJhcG9zaXRpb25bMF0ubGVuZ3RoID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvdGF0aW9uID0gY2FtZXJhcG9zaXRpb25bMF0sXG4gICAgICAgICAgICAgICAgICAgIGNlbnRlciA9IGNhbWVyYXBvc2l0aW9uWzFdLFxuICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSBjYW1lcmFwb3NpdGlvblsyXSxcbiAgICAgICAgICAgICAgICAgICAgbWF0ID0gbTRGcm9tUXVhdChbXSwgcm90YXRpb24pLFxuICAgICAgICAgICAgICAgICAgICBleWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICAgICAgICAgICAgICBleWVbal0gPSBjZW50ZXJbal0gKyByYWRpdXMgKiBtYXRbMiArIDQgKiBqXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzY2VuZS5jYW1lcmEgPSB7XG4gICAgICAgICAgICAgICAgICAgIGV5ZToge3g6IGV5ZVswXSwgeTogZXllWzFdLCB6OiBleWVbMl19LFxuICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IHt4OiBjZW50ZXJbMF0sIHk6IGNlbnRlclsxXSwgejogY2VudGVyWzJdfSxcbiAgICAgICAgICAgICAgICAgICAgdXA6IHt4OiBtYXRbMV0sIHk6IG1hdFs1XSwgejogbWF0WzldfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBkZWxldGUgc2NlbmUuY2FtZXJhcG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgYW5ub3RhdGlvbnNMZW4gPSBBcnJheS5pc0FycmF5KGxheW91dC5hbm5vdGF0aW9ucykgPyBsYXlvdXQuYW5ub3RhdGlvbnMubGVuZ3RoIDogMDtcbiAgICBmb3IoaSA9IDA7IGkgPCBhbm5vdGF0aW9uc0xlbjsgaSsrKSB7XG4gICAgICAgIHZhciBhbm4gPSBsYXlvdXQuYW5ub3RhdGlvbnNbaV07XG5cbiAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGFubikpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKGFubi5yZWYpIHtcbiAgICAgICAgICAgIGlmKGFubi5yZWYgPT09ICdwYXBlcicpIHtcbiAgICAgICAgICAgICAgICBhbm4ueHJlZiA9ICdwYXBlcic7XG4gICAgICAgICAgICAgICAgYW5uLnlyZWYgPSAncGFwZXInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihhbm4ucmVmID09PSAnZGF0YScpIHtcbiAgICAgICAgICAgICAgICBhbm4ueHJlZiA9ICd4JztcbiAgICAgICAgICAgICAgICBhbm4ueXJlZiA9ICd5JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBhbm4ucmVmO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYW5BeFJlZihhbm4sICd4cmVmJyk7XG4gICAgICAgIGNsZWFuQXhSZWYoYW5uLCAneXJlZicpO1xuICAgIH1cblxuICAgIHZhciBzaGFwZXNMZW4gPSBBcnJheS5pc0FycmF5KGxheW91dC5zaGFwZXMpID8gbGF5b3V0LnNoYXBlcy5sZW5ndGggOiAwO1xuICAgIGZvcihpID0gMDsgaSA8IHNoYXBlc0xlbjsgaSsrKSB7XG4gICAgICAgIHZhciBzaGFwZSA9IGxheW91dC5zaGFwZXNbaV07XG5cbiAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KHNoYXBlKSkgY29udGludWU7XG5cbiAgICAgICAgY2xlYW5BeFJlZihzaGFwZSwgJ3hyZWYnKTtcbiAgICAgICAgY2xlYW5BeFJlZihzaGFwZSwgJ3lyZWYnKTtcbiAgICB9XG5cbiAgICB2YXIgbGVnZW5kID0gbGF5b3V0LmxlZ2VuZDtcbiAgICBpZihsZWdlbmQpIHtcbiAgICAgICAgLy8gY2hlY2sgZm9yIG9sZC1zdHlsZSBsZWdlbmQgcG9zaXRpb25pbmcgKHggb3IgeSBpcyArLy0gMTAwKVxuICAgICAgICBpZihsZWdlbmQueCA+IDMpIHtcbiAgICAgICAgICAgIGxlZ2VuZC54ID0gMS4wMjtcbiAgICAgICAgICAgIGxlZ2VuZC54YW5jaG9yID0gJ2xlZnQnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYobGVnZW5kLnggPCAtMikge1xuICAgICAgICAgICAgbGVnZW5kLnggPSAtMC4wMjtcbiAgICAgICAgICAgIGxlZ2VuZC54YW5jaG9yID0gJ3JpZ2h0JztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGxlZ2VuZC55ID4gMykge1xuICAgICAgICAgICAgbGVnZW5kLnkgPSAxLjAyO1xuICAgICAgICAgICAgbGVnZW5kLnlhbmNob3IgPSAnYm90dG9tJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGxlZ2VuZC55IDwgLTIpIHtcbiAgICAgICAgICAgIGxlZ2VuZC55ID0gLTAuMDI7XG4gICAgICAgICAgICBsZWdlbmQueWFuY2hvciA9ICd0b3AnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBNb3ZlZCBmcm9tIHJvdGF0ZSAtPiBvcmJpdCBmb3IgZHJhZ21vZGVcbiAgICAgKi9cbiAgICBpZihsYXlvdXQuZHJhZ21vZGUgPT09ICdyb3RhdGUnKSBsYXlvdXQuZHJhZ21vZGUgPSAnb3JiaXQnO1xuXG4gICAgLy8gc2FuaXRpemUgcmdiKGZyYWN0aW9ucykgYW5kIHJnYmEoZnJhY3Rpb25zKSB0aGF0IG9sZCB0aW55Y29sb3JcbiAgICAvLyBzdXBwb3J0ZWQsIGJ1dCBuZXcgdGlueWNvbG9yIGRvZXMgbm90IGJlY2F1c2UgdGhleSdyZSBub3QgdmFsaWQgY3NzXG4gICAgQ29sb3IuY2xlYW4obGF5b3V0KTtcblxuICAgIHJldHVybiBsYXlvdXQ7XG59O1xuXG5mdW5jdGlvbiBjbGVhbkF4UmVmKGNvbnRhaW5lciwgYXR0cikge1xuICAgIHZhciB2YWxJbiA9IGNvbnRhaW5lclthdHRyXSxcbiAgICAgICAgYXhMZXR0ZXIgPSBhdHRyLmNoYXJBdCgwKTtcbiAgICBpZih2YWxJbiAmJiB2YWxJbiAhPT0gJ3BhcGVyJykge1xuICAgICAgICBjb250YWluZXJbYXR0cl0gPSBjbGVhbklkKHZhbEluLCBheExldHRlcik7XG4gICAgfVxufVxuXG4vKlxuICogY2xlYW5EYXRhOiBNYWtlIGEgZmV3IGNoYW5nZXMgdG8gdGhlIGRhdGEgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAqIGJlZm9yZSBpdCBnZXRzIHVzZWQgZm9yIGFueXRoaW5nLiBNb2RpZmllcyB0aGUgZGF0YSB0cmFjZXMgdXNlcnMgcHJvdmlkZS5cbiAqXG4gKiBJbXBvcnRhbnQ6IGlmIHlvdSdyZSBnb2luZyB0byBhZGQgc29tZXRoaW5nIGhlcmUgdGhhdCBtb2RpZmllcyBhIGRhdGEgYXJyYXksXG4gKiB1cGRhdGUgaXQgaW4gcGxhY2Ugc28gdGhlIG5ldyBhcnJheSA9PT0gdGhlIG9sZCBvbmUuXG4gKi9cbmV4cG9ydHMuY2xlYW5EYXRhID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIGZvcih2YXIgdHJhY2VpID0gMDsgdHJhY2VpIDwgZGF0YS5sZW5ndGg7IHRyYWNlaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRhdGFbdHJhY2VpXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgLy8gdXNlIHhiaW5zIHRvIGJpbiBkYXRhIGluIHgsIGFuZCB5YmlucyB0byBiaW4gZGF0YSBpbiB5XG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15JyAmJiAneGJpbnMnIGluIHRyYWNlICYmICEoJ3liaW5zJyBpbiB0cmFjZSkpIHtcbiAgICAgICAgICAgIHRyYWNlLnliaW5zID0gdHJhY2UueGJpbnM7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2UueGJpbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBlcnJvcl95Lm9wYWNpdHkgaXMgb2Jzb2xldGUgLSBtZXJnZSBpbnRvIGNvbG9yXG4gICAgICAgIGlmKHRyYWNlLmVycm9yX3kgJiYgJ29wYWNpdHknIGluIHRyYWNlLmVycm9yX3kpIHtcbiAgICAgICAgICAgIHZhciBkYyA9IENvbG9yLmRlZmF1bHRzLFxuICAgICAgICAgICAgICAgIHllQ29sb3IgPSB0cmFjZS5lcnJvcl95LmNvbG9yIHx8XG4gICAgICAgICAgICAgICAgKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXInKSA/IENvbG9yLmRlZmF1bHRMaW5lIDogZGNbdHJhY2VpICUgZGMubGVuZ3RoXSk7XG4gICAgICAgICAgICB0cmFjZS5lcnJvcl95LmNvbG9yID0gQ29sb3IuYWRkT3BhY2l0eShcbiAgICAgICAgICAgICAgICBDb2xvci5yZ2IoeWVDb2xvciksXG4gICAgICAgICAgICAgICAgQ29sb3Iub3BhY2l0eSh5ZUNvbG9yKSAqIHRyYWNlLmVycm9yX3kub3BhY2l0eSk7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2UuZXJyb3JfeS5vcGFjaXR5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29udmVydCBiYXJkaXIgdG8gb3JpZW50YXRpb24sIGFuZCBwdXQgdGhlIGRhdGEgaW50b1xuICAgICAgICAvLyB0aGUgYXhlcyBpdCdzIGV2ZW50dWFsbHkgZ29pbmcgdG8gYmUgdXNlZCB3aXRoXG4gICAgICAgIGlmKCdiYXJkaXInIGluIHRyYWNlKSB7XG4gICAgICAgICAgICBpZih0cmFjZS5iYXJkaXIgPT09ICdoJyAmJiAoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JhcicpIHx8XG4gICAgICAgICAgICAgICAgICAgICB0cmFjZS50eXBlLnN1YnN0cigwLCA5KSA9PT0gJ2hpc3RvZ3JhbScpKSB7XG4gICAgICAgICAgICAgICAgdHJhY2Uub3JpZW50YXRpb24gPSAnaCc7XG4gICAgICAgICAgICAgICAgZXhwb3J0cy5zd2FwWFlEYXRhKHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5iYXJkaXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBub3cgd2UgaGF2ZSBvbmx5IG9uZSAxRCBoaXN0b2dyYW0gdHlwZSwgYW5kIHdoZXRoZXJcbiAgICAgICAgLy8gaXQgdXNlcyB4IG9yIHkgZGF0YSBkZXBlbmRzIG9uIHRyYWNlLm9yaWVudGF0aW9uXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15JykgZXhwb3J0cy5zd2FwWFlEYXRhKHRyYWNlKTtcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2hpc3RvZ3JhbXgnIHx8IHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15Jykge1xuICAgICAgICAgICAgdHJhY2UudHlwZSA9ICdoaXN0b2dyYW0nO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2NsLT5zY2FsZSwgcmV2ZXJzZXNjbC0+cmV2ZXJzZXNjYWxlXG4gICAgICAgIGlmKCdzY2wnIGluIHRyYWNlKSB7XG4gICAgICAgICAgICB0cmFjZS5jb2xvcnNjYWxlID0gdHJhY2Uuc2NsO1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLnNjbDtcbiAgICAgICAgfVxuICAgICAgICBpZigncmV2ZXJzZXNjbCcgaW4gdHJhY2UpIHtcbiAgICAgICAgICAgIHRyYWNlLnJldmVyc2VzY2FsZSA9IHRyYWNlLnJldmVyc2VzY2w7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2UucmV2ZXJzZXNjbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGF4aXMgaWRzIHgxIC0+IHgsIHkxLT4geVxuICAgICAgICBpZih0cmFjZS54YXhpcykgdHJhY2UueGF4aXMgPSBjbGVhbklkKHRyYWNlLnhheGlzLCAneCcpO1xuICAgICAgICBpZih0cmFjZS55YXhpcykgdHJhY2UueWF4aXMgPSBjbGVhbklkKHRyYWNlLnlheGlzLCAneScpO1xuXG4gICAgICAgIC8vIHNjZW5lIGlkcyBzY2VuZTEgLT4gc2NlbmVcbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2dsM2QnKSAmJiB0cmFjZS5zY2VuZSkge1xuICAgICAgICAgICAgdHJhY2Uuc2NlbmUgPSBQbG90cy5zdWJwbG90c1JlZ2lzdHJ5LmdsM2QuY2xlYW5JZCh0cmFjZS5zY2VuZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZighUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZScpICYmICFSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnYmFyJykpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2UudGV4dHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlLnRleHRwb3NpdGlvbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZS50ZXh0cG9zaXRpb25baV0gPSBjbGVhblRleHRQb3NpdGlvbih0cmFjZS50ZXh0cG9zaXRpb25baV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYodHJhY2UudGV4dHBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgdHJhY2UudGV4dHBvc2l0aW9uID0gY2xlYW5UZXh0UG9zaXRpb24odHJhY2UudGV4dHBvc2l0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpeCB0eXBvIGluIGNvbG9yc2NhbGUgZGVmaW5pdGlvblxuICAgICAgICB2YXIgX21vZHVsZSA9IFJlZ2lzdHJ5LmdldE1vZHVsZSh0cmFjZSk7XG4gICAgICAgIGlmKF9tb2R1bGUgJiYgX21vZHVsZS5jb2xvcmJhcikge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lck5hbWUgPSBfbW9kdWxlLmNvbG9yYmFyLmNvbnRhaW5lcjtcbiAgICAgICAgICAgIHZhciBjb250YWluZXIgPSBjb250YWluZXJOYW1lID8gdHJhY2VbY29udGFpbmVyTmFtZV0gOiB0cmFjZTtcbiAgICAgICAgICAgIGlmKGNvbnRhaW5lciAmJiBjb250YWluZXIuY29sb3JzY2FsZSkge1xuICAgICAgICAgICAgICAgIGlmKGNvbnRhaW5lci5jb2xvcnNjYWxlID09PSAnWUlHbkJ1JykgY29udGFpbmVyLmNvbG9yc2NhbGUgPSAnWWxHbkJ1JztcbiAgICAgICAgICAgICAgICBpZihjb250YWluZXIuY29sb3JzY2FsZSA9PT0gJ1lJT3JSZCcpIGNvbnRhaW5lci5jb2xvcnNjYWxlID0gJ1lsT3JSZCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaXggdHlwbyBpbiBzdXJmYWNlICdoaWdobGlnaHQqJyBkZWZpbml0aW9uc1xuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnc3VyZmFjZScgJiYgTGliLmlzUGxhaW5PYmplY3QodHJhY2UuY29udG91cnMpKSB7XG4gICAgICAgICAgICB2YXIgZGltcyA9IFsneCcsICd5JywgJ3onXTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBvcHRzID0gdHJhY2UuY29udG91cnNbZGltc1tpXV07XG5cbiAgICAgICAgICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3Qob3B0cykpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgaWYob3B0cy5oaWdobGlnaHRDb2xvcikge1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmhpZ2hsaWdodGNvbG9yID0gb3B0cy5oaWdobGlnaHRDb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG9wdHMuaGlnaGxpZ2h0Q29sb3I7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYob3B0cy5oaWdobGlnaHRXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmhpZ2hsaWdodHdpZHRoID0gb3B0cy5oaWdobGlnaHRXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG9wdHMuaGlnaGxpZ2h0V2lkdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZml4ZXMgZnJvbSBjb252ZXJ0aW5nIGZpbmFuY2UgZnJvbSB0cmFuc2Zvcm1zIHRvIHJlYWwgdHJhY2UgdHlwZXNcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2NhbmRsZXN0aWNrJyB8fCB0cmFjZS50eXBlID09PSAnb2hsYycpIHtcbiAgICAgICAgICAgIHZhciBpbmNyZWFzaW5nU2hvd2xlZ2VuZCA9ICh0cmFjZS5pbmNyZWFzaW5nIHx8IHt9KS5zaG93bGVnZW5kICE9PSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBkZWNyZWFzaW5nU2hvd2xlZ2VuZCA9ICh0cmFjZS5kZWNyZWFzaW5nIHx8IHt9KS5zaG93bGVnZW5kICE9PSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBpbmNyZWFzaW5nTmFtZSA9IGNsZWFuRmluYW5jZURpcih0cmFjZS5pbmNyZWFzaW5nKTtcbiAgICAgICAgICAgIHZhciBkZWNyZWFzaW5nTmFtZSA9IGNsZWFuRmluYW5jZURpcih0cmFjZS5kZWNyZWFzaW5nKTtcblxuICAgICAgICAgICAgLy8gbm93IGZpZ3VyZSBvdXQgc29tZXRoaW5nIHNtYXJ0IHRvIGRvIHdpdGggdGhlIHNlcGFyYXRlIGRpcmVjdGlvblxuICAgICAgICAgICAgLy8gbmFtZXMgd2UgcmVtb3ZlZFxuICAgICAgICAgICAgaWYoKGluY3JlYXNpbmdOYW1lICE9PSBmYWxzZSkgJiYgKGRlY3JlYXNpbmdOYW1lICE9PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBib3RoIHN1Yi1uYW1lcyBleGlzdGVkOiBiYXNlIG5hbWUgcHJldmlvdXNseSBoYWQgbm8gZWZmZWN0XG4gICAgICAgICAgICAgICAgLy8gc28gaWdub3JlIGl0IGFuZCB0cnkgdG8gZmluZCBhIHNoYXJlZCBwYXJ0IG9mIHRoZSBzdWItbmFtZXNcblxuICAgICAgICAgICAgICAgIHZhciBuZXdOYW1lID0gY29tbW9uUHJlZml4KFxuICAgICAgICAgICAgICAgICAgICBpbmNyZWFzaW5nTmFtZSwgZGVjcmVhc2luZ05hbWUsXG4gICAgICAgICAgICAgICAgICAgIGluY3JlYXNpbmdTaG93bGVnZW5kLCBkZWNyZWFzaW5nU2hvd2xlZ2VuZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgLy8gaWYgbm8gY29tbW9uIHBhcnQsIGxlYXZlIHdoYXRldmVyIG5hbWUgd2FzIChvciB3YXNuJ3QpIHRoZXJlXG4gICAgICAgICAgICAgICAgaWYobmV3TmFtZSkgdHJhY2UubmFtZSA9IG5ld05hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKChpbmNyZWFzaW5nTmFtZSB8fCBkZWNyZWFzaW5nTmFtZSkgJiYgIXRyYWNlLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBvbmUgc3ViLW5hbWUgZXhpc3RlZCBidXQgbm90IHRoZSBiYXNlIG5hbWUgLSBqdXN0IHVzZSB0aGUgc3ViLW5hbWVcbiAgICAgICAgICAgICAgICB0cmFjZS5uYW1lID0gaW5jcmVhc2luZ05hbWUgfHwgZGVjcmVhc2luZ05hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmFuc2Zvcm1zIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgZml4ZXNcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0cmFjZS50cmFuc2Zvcm1zKSkge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFuc2Zvcm1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYW5zZm9ybXNbaV07XG5cbiAgICAgICAgICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QodHJhbnNmb3JtKSkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2godHJhbnNmb3JtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZmlsdGVyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRyYW5zZm9ybS5maWx0ZXJzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0udGFyZ2V0ID0gdHJhbnNmb3JtLmZpbHRlcnNyYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhbnNmb3JtLmZpbHRlcnNyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhbnNmb3JtLmNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXRyYW5zZm9ybS52YWx1ZWNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybS52YWx1ZWNhbGVuZGFyID0gdHJhbnNmb3JtLmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhbnNmb3JtLmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZ3JvdXBieSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOYW1lIGhhcyBjaGFuZ2VkIGZyb20gYHN0eWxlYCB0byBgc3R5bGVzYCwgc28gdXNlIGBzdHlsZWAgYnV0IHByZWZlciBgc3R5bGVzYDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybS5zdHlsZXMgPSB0cmFuc2Zvcm0uc3R5bGVzIHx8IHRyYW5zZm9ybS5zdHlsZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhbnNmb3JtLnN0eWxlcyAmJiAhQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm0uc3R5bGVzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2U3R5bGVzID0gdHJhbnNmb3JtLnN0eWxlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3R5bGVLZXlzID0gT2JqZWN0LmtleXMocHJldlN0eWxlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0uc3R5bGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHN0eWxlS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0uc3R5bGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBzdHlsZUtleXNbal0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogcHJldlN0eWxlc1tzdHlsZUtleXNbal1dXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHBydW5lIGVtcHR5IGNvbnRhaW5lcnMgbWFkZSBiZWZvcmUgdGhlIG5ldyBuZXN0ZWRQcm9wZXJ0eVxuICAgICAgICBpZihlbXB0eUNvbnRhaW5lcih0cmFjZSwgJ2xpbmUnKSkgZGVsZXRlIHRyYWNlLmxpbmU7XG4gICAgICAgIGlmKCdtYXJrZXInIGluIHRyYWNlKSB7XG4gICAgICAgICAgICBpZihlbXB0eUNvbnRhaW5lcih0cmFjZS5tYXJrZXIsICdsaW5lJykpIGRlbGV0ZSB0cmFjZS5tYXJrZXIubGluZTtcbiAgICAgICAgICAgIGlmKGVtcHR5Q29udGFpbmVyKHRyYWNlLCAnbWFya2VyJykpIGRlbGV0ZSB0cmFjZS5tYXJrZXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzYW5pdGl6ZSByZ2IoZnJhY3Rpb25zKSBhbmQgcmdiYShmcmFjdGlvbnMpIHRoYXQgb2xkIHRpbnljb2xvclxuICAgICAgICAvLyBzdXBwb3J0ZWQsIGJ1dCBuZXcgdGlueWNvbG9yIGRvZXMgbm90IGJlY2F1c2UgdGhleSdyZSBub3QgdmFsaWQgY3NzXG4gICAgICAgIENvbG9yLmNsZWFuKHRyYWNlKTtcblxuICAgICAgICAvLyByZW1vdmUgb2Jzb2xldGUgYXV0b2Jpbih4fHkpIGF0dHJpYnV0ZXMsIGJ1dCBvbmx5IGlmIHRydWVcbiAgICAgICAgLy8gaWYgZmFsc2UsIHRoaXMgbmVlZHMgdG8gaGFwcGVuIGluIEhpc3RvZ3JhbS5jYWxjIGJlY2F1c2UgaXRcbiAgICAgICAgLy8gY2FuIGJlIGEgb25lLXRpbWUgYXV0b2JpbiBzbyB3ZSBuZWVkIHRvIGtub3cgdGhlIHJlc3VsdHMgYmVmb3JlXG4gICAgICAgIC8vIHdlIGNhbiBwdXNoIHRoZW0gYmFjayBpbnRvIHRoZSB0cmFjZS5cbiAgICAgICAgaWYodHJhY2UuYXV0b2JpbngpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5hdXRvYmlueDtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS54YmlucztcbiAgICAgICAgfVxuICAgICAgICBpZih0cmFjZS5hdXRvYmlueSkge1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLmF1dG9iaW55O1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLnliaW5zO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY2xlYW5GaW5hbmNlRGlyKGRpckNvbnRhaW5lcikge1xuICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChkaXJDb250YWluZXIpKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgZGlyTmFtZSA9IGRpckNvbnRhaW5lci5uYW1lO1xuXG4gICAgZGVsZXRlIGRpckNvbnRhaW5lci5uYW1lO1xuICAgIGRlbGV0ZSBkaXJDb250YWluZXIuc2hvd2xlZ2VuZDtcblxuICAgIHJldHVybiAodHlwZW9mIGRpck5hbWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBkaXJOYW1lID09PSAnbnVtYmVyJykgJiYgU3RyaW5nKGRpck5hbWUpO1xufVxuXG5mdW5jdGlvbiBjb21tb25QcmVmaXgobmFtZTEsIG5hbWUyLCBzaG93MSwgc2hvdzIpIHtcbiAgICAvLyBpZiBvbmx5IG9uZSBpcyBzaG93biBpbiB0aGUgbGVnZW5kLCB1c2UgdGhhdFxuICAgIGlmKHNob3cxICYmICFzaG93MikgcmV0dXJuIG5hbWUxO1xuICAgIGlmKHNob3cyICYmICFzaG93MSkgcmV0dXJuIG5hbWUyO1xuXG4gICAgLy8gaWYgYm90aCBvciBuZWl0aGVyIGFyZSBpbiB0aGUgbGVnZW5kLCBjaGVjayBpZiBvbmUgaXMgYmxhbmsgKG9yIHdoaXRlc3BhY2UpXG4gICAgLy8gYW5kIHVzZSB0aGUgb3RoZXIgb25lXG4gICAgLy8gbm90ZSB0aGF0IGhvdmVyIGxhYmVscyBjYW4gc3RpbGwgdXNlIHRoZSBuYW1lIGV2ZW4gaWYgdGhlIGxlZ2VuZCBkb2Vzbid0XG4gICAgaWYoIW5hbWUxLnRyaW0oKSkgcmV0dXJuIG5hbWUyO1xuICAgIGlmKCFuYW1lMi50cmltKCkpIHJldHVybiBuYW1lMTtcblxuICAgIHZhciBtaW5MZW4gPSBNYXRoLm1pbihuYW1lMS5sZW5ndGgsIG5hbWUyLmxlbmd0aCk7XG4gICAgdmFyIGk7XG4gICAgZm9yKGkgPSAwOyBpIDwgbWluTGVuOyBpKyspIHtcbiAgICAgICAgaWYobmFtZTEuY2hhckF0KGkpICE9PSBuYW1lMi5jaGFyQXQoaSkpIGJyZWFrO1xuICAgIH1cblxuICAgIHZhciBvdXQgPSBuYW1lMS5zdWJzdHIoMCwgaSk7XG4gICAgcmV0dXJuIG91dC50cmltKCk7XG59XG5cbi8vIHRleHRwb3NpdGlvbiAtIHN1cHBvcnQgcGFydGlhbCBhdHRyaWJ1dGVzIChpZSBqdXN0ICd0b3AnKVxuLy8gYW5kIGluY29ycmVjdCB1c2Ugb2YgbWlkZGxlIC8gY2VudGVyIGV0Yy5cbmZ1bmN0aW9uIGNsZWFuVGV4dFBvc2l0aW9uKHRleHRwb3NpdGlvbikge1xuICAgIHZhciBwb3NZID0gJ21pZGRsZScsXG4gICAgICAgIHBvc1ggPSAnY2VudGVyJztcbiAgICBpZih0ZXh0cG9zaXRpb24uaW5kZXhPZigndG9wJykgIT09IC0xKSBwb3NZID0gJ3RvcCc7XG4gICAgZWxzZSBpZih0ZXh0cG9zaXRpb24uaW5kZXhPZignYm90dG9tJykgIT09IC0xKSBwb3NZID0gJ2JvdHRvbSc7XG5cbiAgICBpZih0ZXh0cG9zaXRpb24uaW5kZXhPZignbGVmdCcpICE9PSAtMSkgcG9zWCA9ICdsZWZ0JztcbiAgICBlbHNlIGlmKHRleHRwb3NpdGlvbi5pbmRleE9mKCdyaWdodCcpICE9PSAtMSkgcG9zWCA9ICdyaWdodCc7XG5cbiAgICByZXR1cm4gcG9zWSArICcgJyArIHBvc1g7XG59XG5cbmZ1bmN0aW9uIGVtcHR5Q29udGFpbmVyKG91dGVyLCBpbm5lclN0cikge1xuICAgIHJldHVybiAoaW5uZXJTdHIgaW4gb3V0ZXIpICYmXG4gICAgICAgICh0eXBlb2Ygb3V0ZXJbaW5uZXJTdHJdID09PSAnb2JqZWN0JykgJiZcbiAgICAgICAgKE9iamVjdC5rZXlzKG91dGVyW2lubmVyU3RyXSkubGVuZ3RoID09PSAwKTtcbn1cblxuXG4vLyBzd2FwIGFsbCB0aGUgZGF0YSBhbmQgZGF0YSBhdHRyaWJ1dGVzIGFzc29jaWF0ZWQgd2l0aCB4IGFuZCB5XG5leHBvcnRzLnN3YXBYWURhdGEgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBpO1xuICAgIExpYi5zd2FwQXR0cnModHJhY2UsIFsnPycsICc/MCcsICdkPycsICc/YmlucycsICduYmlucz8nLCAnYXV0b2Jpbj8nLCAnP3NyYycsICdlcnJvcl8/J10pO1xuICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2UueikgJiYgQXJyYXkuaXNBcnJheSh0cmFjZS56WzBdKSkge1xuICAgICAgICBpZih0cmFjZS50cmFuc3Bvc2UpIGRlbGV0ZSB0cmFjZS50cmFuc3Bvc2U7XG4gICAgICAgIGVsc2UgdHJhY2UudHJhbnNwb3NlID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYodHJhY2UuZXJyb3JfeCAmJiB0cmFjZS5lcnJvcl95KSB7XG4gICAgICAgIHZhciBlcnJvclkgPSB0cmFjZS5lcnJvcl95LFxuICAgICAgICAgICAgY29weVlzdHlsZSA9ICgnY29weV95c3R5bGUnIGluIGVycm9yWSkgPyBlcnJvclkuY29weV95c3R5bGUgOlxuICAgICAgICAgICAgICAgICEoZXJyb3JZLmNvbG9yIHx8IGVycm9yWS50aGlja25lc3MgfHwgZXJyb3JZLndpZHRoKTtcbiAgICAgICAgTGliLnN3YXBBdHRycyh0cmFjZSwgWydlcnJvcl8/LmNvcHlfeXN0eWxlJ10pO1xuICAgICAgICBpZihjb3B5WXN0eWxlKSB7XG4gICAgICAgICAgICBMaWIuc3dhcEF0dHJzKHRyYWNlLCBbJ2Vycm9yXz8uY29sb3InLCAnZXJyb3JfPy50aGlja25lc3MnLCAnZXJyb3JfPy53aWR0aCddKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZih0eXBlb2YgdHJhY2UuaG92ZXJpbmZvID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgaG92ZXJJbmZvUGFydHMgPSB0cmFjZS5ob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaG92ZXJJbmZvUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGhvdmVySW5mb1BhcnRzW2ldID09PSAneCcpIGhvdmVySW5mb1BhcnRzW2ldID0gJ3knO1xuICAgICAgICAgICAgZWxzZSBpZihob3ZlckluZm9QYXJ0c1tpXSA9PT0gJ3knKSBob3ZlckluZm9QYXJ0c1tpXSA9ICd4JztcbiAgICAgICAgfVxuICAgICAgICB0cmFjZS5ob3ZlcmluZm8gPSBob3ZlckluZm9QYXJ0cy5qb2luKCcrJyk7XG4gICAgfVxufTtcblxuLy8gY29lcmNlIHRyYWNlSW5kaWNlcyBpbnB1dCB0byBhcnJheSBvZiB0cmFjZSBpbmRpY2VzXG5leHBvcnRzLmNvZXJjZVRyYWNlSW5kaWNlcyA9IGZ1bmN0aW9uKGdkLCB0cmFjZUluZGljZXMpIHtcbiAgICBpZihpc051bWVyaWModHJhY2VJbmRpY2VzKSkge1xuICAgICAgICByZXR1cm4gW3RyYWNlSW5kaWNlc107XG4gICAgfVxuICAgIGVsc2UgaWYoIUFycmF5LmlzQXJyYXkodHJhY2VJbmRpY2VzKSB8fCAhdHJhY2VJbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gZ2QuZGF0YS5tYXAoZnVuY3Rpb24oXywgaSkgeyByZXR1cm4gaTsgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheSh0cmFjZUluZGljZXMpKSB7XG4gICAgICAgIHZhciB0cmFjZUluZGljZXNPdXQgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYWNlSW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoTGliLmlzSW5kZXgodHJhY2VJbmRpY2VzW2ldLCBnZC5kYXRhLmxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICB0cmFjZUluZGljZXNPdXQucHVzaCh0cmFjZUluZGljZXNbaV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMaWIud2FybigndHJhY2UgaW5kZXggKCcsIHRyYWNlSW5kaWNlc1tpXSwgJykgaXMgbm90IGEgbnVtYmVyIG9yIGlzIG91dCBvZiBib3VuZHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJhY2VJbmRpY2VzT3V0O1xuICAgIH1cblxuICAgIHJldHVybiB0cmFjZUluZGljZXM7XG59O1xuXG4vKipcbiAqIE1hbmFnZXMgbG9naWMgYXJvdW5kIGFycmF5IGNvbnRhaW5lciBpdGVtIGNyZWF0aW9uIC8gZGVsZXRpb24gLyB1cGRhdGVcbiAqIHRoYXQgbmVzdGVkIHByb3BlcnR5IGFsb25lIGNhbid0IGhhbmRsZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gbnBcbiAqICBuZXN0ZWQgcHJvcGVydHkgb2YgdXBkYXRlIGF0dHJpYnV0ZSBzdHJpbmcgYWJvdXQgdHJhY2Ugb3IgbGF5b3V0IG9iamVjdFxuICogQHBhcmFtIHsqfSBuZXdWYWxcbiAqICB1cGRhdGUgdmFsdWUgcGFzc2VkIHRvIHJlc3R5bGUgLyByZWxheW91dCAvIHVwZGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHVuZG9pdFxuICogIHVuZG8gaGFzaCAoTi5CLiB1bmRvaXQgbWF5IGJlIG11dGF0ZWQgaGVyZSkuXG4gKlxuICovXG5leHBvcnRzLm1hbmFnZUFycmF5Q29udGFpbmVycyA9IGZ1bmN0aW9uKG5wLCBuZXdWYWwsIHVuZG9pdCkge1xuICAgIHZhciBvYmogPSBucC5vYmosXG4gICAgICAgIHBhcnRzID0gbnAucGFydHMsXG4gICAgICAgIHBMZW5ndGggPSBwYXJ0cy5sZW5ndGgsXG4gICAgICAgIHBMYXN0ID0gcGFydHNbcExlbmd0aCAtIDFdO1xuXG4gICAgdmFyIHBMYXN0SXNOdW1iZXIgPSBpc051bWVyaWMocExhc3QpO1xuXG4gICAgLy8gZGVsZXRlIGl0ZW1cbiAgICBpZihwTGFzdElzTnVtYmVyICYmIG5ld1ZhbCA9PT0gbnVsbCkge1xuXG4gICAgICAgIC8vIENsZWFyIGl0ZW0gaW4gYXJyYXkgY29udGFpbmVyIHdoZW4gbmV3IHZhbHVlIGlzIG51bGxcbiAgICAgICAgdmFyIGNvbnRQYXRoID0gcGFydHMuc2xpY2UoMCwgcExlbmd0aCAtIDEpLmpvaW4oJy4nKSxcbiAgICAgICAgICAgIGNvbnQgPSBMaWIubmVzdGVkUHJvcGVydHkob2JqLCBjb250UGF0aCkuZ2V0KCk7XG4gICAgICAgIGNvbnQuc3BsaWNlKHBMYXN0LCAxKTtcblxuICAgICAgICAvLyBOb3RlIHRoYXQgbmVzdGVkIHByb3BlcnR5IGNsZWFycyBudWxsIC8gdW5kZWZpbmVkIGF0IGVuZCBvZlxuICAgICAgICAvLyBhcnJheSBjb250YWluZXIsIGJ1dCBub3Qgd2l0aGluIHRoZW0uXG4gICAgfVxuICAgIC8vIGNyZWF0ZSBpdGVtXG4gICAgZWxzZSBpZihwTGFzdElzTnVtYmVyICYmIG5wLmdldCgpID09PSB1bmRlZmluZWQpIHtcblxuICAgICAgICAvLyBXaGVuIGFkZGluZyBhIG5ldyBpdGVtLCBtYWtlIHN1cmUgdW5kbyBjb21tYW5kIHdpbGwgcmVtb3ZlIGl0XG4gICAgICAgIGlmKG5wLmdldCgpID09PSB1bmRlZmluZWQpIHVuZG9pdFtucC5hc3RyXSA9IG51bGw7XG5cbiAgICAgICAgbnAuc2V0KG5ld1ZhbCk7XG4gICAgfVxuICAgIC8vIHVwZGF0ZSBpdGVtXG4gICAgZWxzZSB7XG5cbiAgICAgICAgLy8gSWYgdGhlIGxhc3QgcGFydCBvZiBhdHRyaWJ1dGUgc3RyaW5nIGlzbid0IGEgbnVtYmVyLFxuICAgICAgICAvLyBucC5zZXQgaXMgYWxsIHdlIG5lZWQuXG4gICAgICAgIG5wLnNldChuZXdWYWwpO1xuICAgIH1cbn07XG5cbi8qXG4gKiBNYXRjaCB0aGUgcGFydCB0byBzdHJpcCBvZmYgdG8gdHVybiBhbiBhdHRyaWJ1dGUgaW50byBpdHMgcGFyZW50XG4gKiByZWFsbHkgaXQgc2hvdWxkIGJlIGVpdGhlciAnLnNvbWVfY2hhcmFjdGVycycgb3IgJ1tudW1iZXJdJ1xuICogYnV0IHdlJ3JlIGEgbGl0dGxlIG1vcmUgcGVybWlzc2l2ZSBoZXJlIGFuZCBtYXRjaCBlaXRoZXJcbiAqICcubm90X2JyYWNrZXRzX29yX2RvdCcgb3IgJ1tub3RfYnJhY2tldHNfb3JfZG90XSdcbiAqL1xudmFyIEFUVFJfVEFJTF9SRSA9IC8oXFwuW15cXFtcXF1cXC5dK3xcXFtbXlxcW1xcXVxcLl0rXFxdKSQvO1xuXG5mdW5jdGlvbiBnZXRQYXJlbnQoYXR0cikge1xuICAgIHZhciB0YWlsID0gYXR0ci5zZWFyY2goQVRUUl9UQUlMX1JFKTtcbiAgICBpZih0YWlsID4gMCkgcmV0dXJuIGF0dHIuc3Vic3RyKDAsIHRhaWwpO1xufVxuXG4vKlxuICogaGFzUGFyZW50OiBkb2VzIGFuIGF0dHJpYnV0ZSBvYmplY3QgY29udGFpbiBhIHBhcmVudCBvZiB0aGUgZ2l2ZW4gYXR0cmlidXRlP1xuICogZm9yIGV4YW1wbGUsIGdpdmVuICdpbWFnZXNbMl0ueCcgZG8gd2UgYWxzbyBoYXZlICdpbWFnZXMnIG9yICdpbWFnZXNbMl0nP1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBhb2JqXG4gKiAgdXBkYXRlIG9iamVjdCwgd2hvc2Uga2V5cyBhcmUgYXR0cmlidXRlIHN0cmluZ3MgYW5kIHZhbHVlcyBhcmUgdGhlaXIgbmV3IHNldHRpbmdzXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0clxuICogIHRoZSBhdHRyaWJ1dGUgc3RyaW5nIHRvIHRlc3QgYWdhaW5zdFxuICogQHJldHVybnMge0Jvb2xlYW59XG4gKiAgaXMgYSBwYXJlbnQgb2YgYXR0ciBwcmVzZW50IGluIGFvYmo/XG4gKi9cbmV4cG9ydHMuaGFzUGFyZW50ID0gZnVuY3Rpb24oYW9iaiwgYXR0cikge1xuICAgIHZhciBhdHRyUGFyZW50ID0gZ2V0UGFyZW50KGF0dHIpO1xuICAgIHdoaWxlKGF0dHJQYXJlbnQpIHtcbiAgICAgICAgaWYoYXR0clBhcmVudCBpbiBhb2JqKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgYXR0clBhcmVudCA9IGdldFBhcmVudChhdHRyUGFyZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBFbXB0eSBvdXQgdHlwZXMgZm9yIGFsbCBheGVzIGNvbnRhaW5pbmcgdGhlc2UgdHJhY2VzIHNvIHdlIGF1dG8tc2V0IHRoZW0gYWdhaW5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZ2RcbiAqIEBwYXJhbSB7W2ludGVnZXJdfSB0cmFjZXM6IHRyYWNlIGluZGljZXMgdG8gc2VhcmNoIGZvciBheGVzIHRvIGNsZWFyIHRoZSB0eXBlcyBvZlxuICogQHBhcmFtIHtvYmplY3R9IGxheW91dFVwZGF0ZTogYW55IHVwZGF0ZSBiZWluZyBkb25lIGNvbmN1cnJlbnRseSB0byB0aGUgbGF5b3V0LFxuICogICB3aGljaCBtYXkgc3VwZXJjZWRlIGNsZWFyaW5nIHRoZSBheGlzIHR5cGVzXG4gKi9cbnZhciBheExldHRlcnMgPSBbJ3gnLCAneScsICd6J107XG5leHBvcnRzLmNsZWFyQXhpc1R5cGVzID0gZnVuY3Rpb24oZ2QsIHRyYWNlcywgbGF5b3V0VXBkYXRlKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBnZC5fZnVsbERhdGFbaV07XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCAzOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBheCA9IGdldEZyb21UcmFjZShnZCwgdHJhY2UsIGF4TGV0dGVyc1tqXSk7XG5cbiAgICAgICAgICAgIC8vIGRvIG5vdCBjbGVhciBsb2cgdHlwZSAtIHRoYXQncyBuZXZlciBhbiBhdXRvIHJlc3VsdCBzbyBtdXN0IGhhdmUgYmVlbiBpbnRlbnRpb25hbFxuICAgICAgICAgICAgaWYoYXggJiYgYXgudHlwZSAhPT0gJ2xvZycpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXhBdHRyID0gYXguX25hbWU7XG4gICAgICAgICAgICAgICAgdmFyIHNjZW5lTmFtZSA9IGF4Ll9pZC5zdWJzdHIoMSk7XG4gICAgICAgICAgICAgICAgaWYoc2NlbmVOYW1lLnN1YnN0cigwLCA1KSA9PT0gJ3NjZW5lJykge1xuICAgICAgICAgICAgICAgICAgICBpZihsYXlvdXRVcGRhdGVbc2NlbmVOYW1lXSAhPT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgYXhBdHRyID0gc2NlbmVOYW1lICsgJy4nICsgYXhBdHRyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdHlwZUF0dHIgPSBheEF0dHIgKyAnLnR5cGUnO1xuXG4gICAgICAgICAgICAgICAgaWYobGF5b3V0VXBkYXRlW2F4QXR0cl0gPT09IHVuZGVmaW5lZCAmJiBsYXlvdXRVcGRhdGVbdHlwZUF0dHJdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KGdkLmxheW91dCwgdHlwZUF0dHIpLnNldChudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbWFpbiA9IHJlcXVpcmUoJy4vcGxvdF9hcGknKTtcblxuZXhwb3J0cy5wbG90ID0gbWFpbi5wbG90O1xuZXhwb3J0cy5uZXdQbG90ID0gbWFpbi5uZXdQbG90O1xuZXhwb3J0cy5yZXN0eWxlID0gbWFpbi5yZXN0eWxlO1xuZXhwb3J0cy5yZWxheW91dCA9IG1haW4ucmVsYXlvdXQ7XG5leHBvcnRzLnJlZHJhdyA9IG1haW4ucmVkcmF3O1xuZXhwb3J0cy51cGRhdGUgPSBtYWluLnVwZGF0ZTtcbmV4cG9ydHMucmVhY3QgPSBtYWluLnJlYWN0O1xuZXhwb3J0cy5leHRlbmRUcmFjZXMgPSBtYWluLmV4dGVuZFRyYWNlcztcbmV4cG9ydHMucHJlcGVuZFRyYWNlcyA9IG1haW4ucHJlcGVuZFRyYWNlcztcbmV4cG9ydHMuYWRkVHJhY2VzID0gbWFpbi5hZGRUcmFjZXM7XG5leHBvcnRzLmRlbGV0ZVRyYWNlcyA9IG1haW4uZGVsZXRlVHJhY2VzO1xuZXhwb3J0cy5tb3ZlVHJhY2VzID0gbWFpbi5tb3ZlVHJhY2VzO1xuZXhwb3J0cy5wdXJnZSA9IG1haW4ucHVyZ2U7XG5leHBvcnRzLmFkZEZyYW1lcyA9IG1haW4uYWRkRnJhbWVzO1xuZXhwb3J0cy5kZWxldGVGcmFtZXMgPSBtYWluLmRlbGV0ZUZyYW1lcztcbmV4cG9ydHMuYW5pbWF0ZSA9IG1haW4uYW5pbWF0ZTtcbmV4cG9ydHMuc2V0UGxvdENvbmZpZyA9IG1haW4uc2V0UGxvdENvbmZpZztcblxuZXhwb3J0cy50b0ltYWdlID0gcmVxdWlyZSgnLi90b19pbWFnZScpO1xuZXhwb3J0cy52YWxpZGF0ZSA9IHJlcXVpcmUoJy4vdmFsaWRhdGUnKTtcbmV4cG9ydHMuZG93bmxvYWRJbWFnZSA9IHJlcXVpcmUoJy4uL3NuYXBzaG90L2Rvd25sb2FkJyk7XG5cbnZhciB0ZW1wbGF0ZUFwaSA9IHJlcXVpcmUoJy4vdGVtcGxhdGVfYXBpJyk7XG5leHBvcnRzLm1ha2VUZW1wbGF0ZSA9IHRlbXBsYXRlQXBpLm1ha2VUZW1wbGF0ZTtcbmV4cG9ydHMudmFsaWRhdGVUZW1wbGF0ZSA9IHRlbXBsYXRlQXBpLnZhbGlkYXRlVGVtcGxhdGU7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG5lc3RlZFByb3BlcnR5ID0gcmVxdWlyZSgnLi4vbGliL25lc3RlZF9wcm9wZXJ0eScpO1xudmFyIGlzUGxhaW5PYmplY3QgPSByZXF1aXJlKCcuLi9saWIvaXNfcGxhaW5fb2JqZWN0Jyk7XG52YXIgbm9vcCA9IHJlcXVpcmUoJy4uL2xpYi9ub29wJyk7XG52YXIgTG9nZ2VycyA9IHJlcXVpcmUoJy4uL2xpYi9sb2dnZXJzJyk7XG52YXIgc29ydGVyQXNjID0gcmVxdWlyZSgnLi4vbGliL3NlYXJjaCcpLnNvcnRlckFzYztcbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uL3JlZ2lzdHJ5Jyk7XG5cblxuZXhwb3J0cy5jb250YWluZXJBcnJheU1hdGNoID0gcmVxdWlyZSgnLi9jb250YWluZXJfYXJyYXlfbWF0Y2gnKTtcblxudmFyIGlzQWRkVmFsID0gZXhwb3J0cy5pc0FkZFZhbCA9IGZ1bmN0aW9uIGlzQWRkVmFsKHZhbCkge1xuICAgIHJldHVybiB2YWwgPT09ICdhZGQnIHx8IGlzUGxhaW5PYmplY3QodmFsKTtcbn07XG5cbnZhciBpc1JlbW92ZVZhbCA9IGV4cG9ydHMuaXNSZW1vdmVWYWwgPSBmdW5jdGlvbiBpc1JlbW92ZVZhbCh2YWwpIHtcbiAgICByZXR1cm4gdmFsID09PSBudWxsIHx8IHZhbCA9PT0gJ3JlbW92ZSc7XG59O1xuXG4vKlxuICogYXBwbHlDb250YWluZXJBcnJheUNoYW5nZXM6IGZvciBtYW5hZ2luZyBhcnJheXMgb2YgbGF5b3V0IGNvbXBvbmVudHMgaW4gcmVsYXlvdXRcbiAqIGhhbmRsZXMgdGhlbSBhbGwgd2l0aCBhIGNvbnNpc3RlbnQgaW50ZXJmYWNlLlxuICpcbiAqIEhlcmUgYXJlIHRoZSBzdXBwb3J0ZWQgYWN0aW9ucyAtPiByZWxheW91dCBjYWxscyAtPiBlZGl0cyB3ZSBnZXQgaGVyZVxuICogKGFzIHByZXBhcmVkIGluIF9yZWxheW91dCk6XG4gKlxuICogYWRkIGFuIGVtcHR5IG9iaiAtPiB7J2Fubm90YXRpb25zWzJdJzogJ2FkZCd9IC0+IHsyOiB7Jyc6ICdhZGQnfX1cbiAqIGFkZCBhIHNwZWNpZmljIG9iaiAtPiB7J2Fubm90YXRpb25zWzJdJzoge2F0dHJzfX0gLT4gezI6IHsnJzoge2F0dHJzfX19XG4gKiBkZWxldGUgYW4gb2JqIC0+IHsnYW5ub3RhdGlvbnNbMl0nOiAncmVtb3ZlJ30gLT4gezI6IHsnJzogJ3JlbW92ZSd9fVxuICogICAgICAgICAgICAgICAtPiB7J2Fubm90YXRpb25zWzJdJzogbnVsbH0gLT4gezI6IHsnJzogbnVsbH19XG4gKiBkZWxldGUgdGhlIHdob2xlIGFycmF5IC0+IHsnYW5ub3RhdGlvbnMnOiAncmVtb3ZlJ30gLT4geycnOiB7Jyc6ICdyZW1vdmUnfX1cbiAqICAgICAgICAgICAgICAgICAgICAgICAgLT4geydhbm5vdGF0aW9ucyc6IG51bGx9IC0+IHsnJzogeycnOiBudWxsfX1cbiAqIGVkaXQgYW4gb2JqZWN0IC0+IHsnYW5ub3RhdGlvbnNbMl0udGV4dCc6ICdib28nfSAtPiB7Mjogeyd0ZXh0JzogJ2Jvbyd9fVxuICpcbiAqIFlvdSBjYW4gY29tYmluZSBtYW55IGVkaXRzIHRvIGRpZmZlcmVudCBvYmplY3RzLiBPYmplY3RzIGFyZSBhZGRlZCBhbmQgZWRpdGVkXG4gKiBpbiBhc2NlbmRpbmcgb3JkZXIsIHRoZW4gcmVtb3ZlZCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICogRm9yIGV4YW1wbGUsIHN0YXJ0aW5nIHdpdGggW2EsIGIsIGNdLCBpZiB5b3Ugd2FudCB0bzpcbiAqIC0gcmVwbGFjZSBiIHdpdGggZDpcbiAqICAgeydhbm5vdGF0aW9uc1sxXSc6IGQsICdhbm5vdGF0aW9uc1syXSc6IG51bGx9IChiIGlzIGl0ZW0gMiBhZnRlciBhZGRpbmcgZClcbiAqIC0gYWRkIGEgbmV3IGl0ZW0gZCBiZXR3ZWVuIGEgYW5kIGIsIGFuZCBlZGl0IGI6XG4gKiAgICB7J2Fubm90YXRpb25zWzFdJzogZCwgJ2Fubm90YXRpb25zWzJdLngnOiBuZXdYfSAoYiBpcyBpdGVtIDIgYWZ0ZXIgYWRkaW5nIGQpXG4gKiAtIGRlbGV0ZSBiIGFuZCBlZGl0IGM6XG4gKiAgICB7J2Fubm90YXRpb25zWzFdJzogbnVsbCwgJ2Fubm90YXRpb25zWzJdLngnOiBuZXdYfSAoYyBpcyBlZGl0ZWQgYmVmb3JlIGIgaXMgcmVtb3ZlZClcbiAqXG4gKiBZb3UgQ0FOTk9UIGNvbWJpbmUgYWRkaW5nL2RlbGV0aW5nIGFuIGl0ZW0gYXQgaW5kZXggYGlgIHdpdGggZWRpdHMgdG8gdGhlIHNhbWUgaW5kZXggYGlgXG4gKiBZb3UgQ0FOTk9UIGNvbWJpbmUgcmVwbGFjaW5nL2RlbGV0aW5nIHRoZSB3aG9sZSBhcnJheSB3aXRoIGFueXRoaW5nIGVsc2UgKGZvciB0aGUgc2FtZSBhcnJheSkuXG4gKlxuICogQHBhcmFtIHtIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICB0aGUgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7TGliLm5lc3RlZFByb3BlcnR5fSBjb21wb25lbnRUeXBlOiB0aGUgYXJyYXkgd2UgYXJlIGVkaXRpbmdcbiAqIEBwYXJhbSB7T2JqZWN0fSBlZGl0c1xuICogIHRoZSBjaGFuZ2VzIHRvIG1ha2U7IGtleXMgYXJlIGluZGljZXMgdG8gZWRpdCwgdmFsdWVzIGFyZSB0aGVtc2VsdmVzIG9iamVjdHM6XG4gKiAge2F0dHI6IG5ld1ZhbHVlfSBvZiBjaGFuZ2VzIHRvIG1ha2UgdG8gdGhhdCBpbmRleCAod2l0aCBhZGQvcmVtb3ZlIGJlaGF2aW9yXG4gKiAgaW4gc3BlY2lhbCB2YWx1ZXMgb2YgdGhlIGVtcHR5IGF0dHIpXG4gKiBAcGFyYW0ge09iamVjdH0gZmxhZ3NcbiAqICB0aGUgZmxhZ3MgZm9yIHdoaWNoIGFjdGlvbnMgd2UncmUgZ29pbmcgdG8gcGVyZm9ybSB0byBkaXNwbGF5IHRoZXNlIChhbmRcbiAqICBhbnkgb3RoZXIpIGNoYW5nZXMuIElmIHdlJ3JlIGFscmVhZHkgYHJlY2FsY2BpbmcsIHdlIGRvbid0IG5lZWQgdG8gcmVkcmF3XG4gKiAgaW5kaXZpZHVhbCBpdGVtc1xuICpcbiAqIEByZXR1cm5zIHtib29sfSBgdHJ1ZWAgaWYgaXQgbWFuYWdlZCB0byBjb21wbGV0ZSBkcmF3aW5nIG9mIHRoZSBjaGFuZ2VzXG4gKiAgYGZhbHNlYCB3b3VsZCBtZWFuIHRoZSBwYXJlbnQgc2hvdWxkIHJlcGxvdC5cbiAqL1xuZXhwb3J0cy5hcHBseUNvbnRhaW5lckFycmF5Q2hhbmdlcyA9IGZ1bmN0aW9uIGFwcGx5Q29udGFpbmVyQXJyYXlDaGFuZ2VzKGdkLCBucCwgZWRpdHMsIGZsYWdzKSB7XG4gICAgdmFyIGNvbXBvbmVudFR5cGUgPSBucC5hc3RyLFxuICAgICAgICBzdXBwbHlDb21wb25lbnREZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZChjb21wb25lbnRUeXBlLCAnc3VwcGx5TGF5b3V0RGVmYXVsdHMnKSxcbiAgICAgICAgZHJhdyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZChjb21wb25lbnRUeXBlLCAnZHJhdycpLFxuICAgICAgICBkcmF3T25lID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKGNvbXBvbmVudFR5cGUsICdkcmF3T25lJyksXG4gICAgICAgIHJlcGxvdExhdGVyID0gZmxhZ3MucmVwbG90IHx8IGZsYWdzLnJlY2FsYyB8fCAoc3VwcGx5Q29tcG9uZW50RGVmYXVsdHMgPT09IG5vb3ApIHx8XG4gICAgICAgICAgICAoZHJhdyA9PT0gbm9vcCksXG4gICAgICAgIGxheW91dCA9IGdkLmxheW91dCxcbiAgICAgICAgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoZWRpdHNbJyddKSB7XG4gICAgICAgIGlmKE9iamVjdC5rZXlzKGVkaXRzKS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBMb2dnZXJzLndhcm4oJ0Z1bGwgYXJyYXkgZWRpdHMgYXJlIGluY29tcGF0aWJsZSB3aXRoIG90aGVyIGVkaXRzJyxcbiAgICAgICAgICAgICAgICBjb21wb25lbnRUeXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmdWxsVmFsID0gZWRpdHNbJyddWycnXTtcblxuICAgICAgICBpZihpc1JlbW92ZVZhbChmdWxsVmFsKSkgbnAuc2V0KG51bGwpO1xuICAgICAgICBlbHNlIGlmKEFycmF5LmlzQXJyYXkoZnVsbFZhbCkpIG5wLnNldChmdWxsVmFsKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXJzLndhcm4oJ1VucmVjb2duaXplZCBmdWxsIGFycmF5IGVkaXQgdmFsdWUnLCBjb21wb25lbnRUeXBlLCBmdWxsVmFsKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYocmVwbG90TGF0ZXIpIHJldHVybiBmYWxzZTtcblxuICAgICAgICBzdXBwbHlDb21wb25lbnREZWZhdWx0cyhsYXlvdXQsIGZ1bGxMYXlvdXQpO1xuICAgICAgICBkcmF3KGdkKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdmFyIGNvbXBvbmVudE51bXMgPSBPYmplY3Qua2V5cyhlZGl0cykubWFwKE51bWJlcikuc29ydChzb3J0ZXJBc2MpLFxuICAgICAgICBjb21wb25lbnRBcnJheUluID0gbnAuZ2V0KCksXG4gICAgICAgIGNvbXBvbmVudEFycmF5ID0gY29tcG9uZW50QXJyYXlJbiB8fCBbXSxcbiAgICAgICAgLy8gY29tcG9uZW50QXJyYXlGdWxsIGlzIHVzZWQganVzdCB0byBrZWVwIHNwbGljZXMgaW4gbGluZSBiZXR3ZWVuXG4gICAgICAgIC8vIGZ1bGwgYW5kIGlucHV0IGFycmF5cywgc28gcHJpdmF0ZSBrZXlzIGNhbiBiZSBjb3BpZWQgb3ZlciBhZnRlclxuICAgICAgICAvLyByZWRvaW5nIHN1cHBseURlZmF1bHRzXG4gICAgICAgIC8vIFRPRE86IHRoaXMgYXNzdW1lcyBjb21wb25lbnRBcnJheSBpcyBpbiBnZC5sYXlvdXQgLSB3aGljaCB3aWxsIG5vdCBiZVxuICAgICAgICAvLyB0cnVlIGFmdGVyIHdlIGV4dGVuZCB0aGlzIHRvIHJlc3R5bGVcbiAgICAgICAgY29tcG9uZW50QXJyYXlGdWxsID0gbmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgY29tcG9uZW50VHlwZSkuZ2V0KCk7XG5cbiAgICB2YXIgZGVsZXRlcyA9IFtdLFxuICAgICAgICBmaXJzdEluZGV4Q2hhbmdlID0gLTEsXG4gICAgICAgIG1heEluZGV4ID0gY29tcG9uZW50QXJyYXkubGVuZ3RoLFxuICAgICAgICBpLFxuICAgICAgICBqLFxuICAgICAgICBjb21wb25lbnROdW0sXG4gICAgICAgIG9iakVkaXRzLFxuICAgICAgICBvYmpLZXlzLFxuICAgICAgICBvYmpWYWwsXG4gICAgICAgIGFkZGluZztcblxuICAgIC8vIGZpcnN0IG1ha2UgdGhlIGFkZCBhbmQgZWRpdCBjaGFuZ2VzXG4gICAgZm9yKGkgPSAwOyBpIDwgY29tcG9uZW50TnVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb21wb25lbnROdW0gPSBjb21wb25lbnROdW1zW2ldO1xuICAgICAgICBvYmpFZGl0cyA9IGVkaXRzW2NvbXBvbmVudE51bV07XG4gICAgICAgIG9iaktleXMgPSBPYmplY3Qua2V5cyhvYmpFZGl0cyk7XG4gICAgICAgIG9ialZhbCA9IG9iakVkaXRzWycnXSxcbiAgICAgICAgYWRkaW5nID0gaXNBZGRWYWwob2JqVmFsKTtcblxuICAgICAgICBpZihjb21wb25lbnROdW0gPCAwIHx8IGNvbXBvbmVudE51bSA+IGNvbXBvbmVudEFycmF5Lmxlbmd0aCAtIChhZGRpbmcgPyAwIDogMSkpIHtcbiAgICAgICAgICAgIExvZ2dlcnMud2FybignaW5kZXggb3V0IG9mIHJhbmdlJywgY29tcG9uZW50VHlwZSwgY29tcG9uZW50TnVtKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob2JqVmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKG9iaktleXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIExvZ2dlcnMud2FybihcbiAgICAgICAgICAgICAgICAgICAgJ0luc2VydGlvbiAmIHJlbW92YWwgYXJlIGluY29tcGF0aWJsZSB3aXRoIGVkaXRzIHRvIHRoZSBzYW1lIGluZGV4LicsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFR5cGUsIGNvbXBvbmVudE51bSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzUmVtb3ZlVmFsKG9ialZhbCkpIHtcbiAgICAgICAgICAgICAgICBkZWxldGVzLnB1c2goY29tcG9uZW50TnVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoYWRkaW5nKSB7XG4gICAgICAgICAgICAgICAgaWYob2JqVmFsID09PSAnYWRkJykgb2JqVmFsID0ge307XG4gICAgICAgICAgICAgICAgY29tcG9uZW50QXJyYXkuc3BsaWNlKGNvbXBvbmVudE51bSwgMCwgb2JqVmFsKTtcbiAgICAgICAgICAgICAgICBpZihjb21wb25lbnRBcnJheUZ1bGwpIGNvbXBvbmVudEFycmF5RnVsbC5zcGxpY2UoY29tcG9uZW50TnVtLCAwLCB7fSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXJzLndhcm4oJ1VucmVjb2duaXplZCBmdWxsIG9iamVjdCBlZGl0IHZhbHVlJyxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50VHlwZSwgY29tcG9uZW50TnVtLCBvYmpWYWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihmaXJzdEluZGV4Q2hhbmdlID09PSAtMSkgZmlyc3RJbmRleENoYW5nZSA9IGNvbXBvbmVudE51bTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG9iaktleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eShjb21wb25lbnRBcnJheVtjb21wb25lbnROdW1dLCBvYmpLZXlzW2pdKS5zZXQob2JqRWRpdHNbb2JqS2V5c1tqXV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbm93IGRvIGRlbGV0ZXNcbiAgICBmb3IoaSA9IGRlbGV0ZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgY29tcG9uZW50QXJyYXkuc3BsaWNlKGRlbGV0ZXNbaV0sIDEpO1xuICAgICAgICAvLyBUT0RPOiB0aGlzIGRyb3BzIHByaXZhdGUga2V5cyB0aGF0IGhhZCBiZWVuIHN0b3JlZCBpbiBjb21wb25lbnRBcnJheUZ1bGxcbiAgICAgICAgLy8gZG9lcyB0aGlzIGhhdmUgYW55IGlsbCBlZmZlY3RzP1xuICAgICAgICBpZihjb21wb25lbnRBcnJheUZ1bGwpIGNvbXBvbmVudEFycmF5RnVsbC5zcGxpY2UoZGVsZXRlc1tpXSwgMSk7XG4gICAgfVxuXG4gICAgaWYoIWNvbXBvbmVudEFycmF5Lmxlbmd0aCkgbnAuc2V0KG51bGwpO1xuICAgIGVsc2UgaWYoIWNvbXBvbmVudEFycmF5SW4pIG5wLnNldChjb21wb25lbnRBcnJheSk7XG5cbiAgICBpZihyZXBsb3RMYXRlcikgcmV0dXJuIGZhbHNlO1xuXG4gICAgc3VwcGx5Q29tcG9uZW50RGVmYXVsdHMobGF5b3V0LCBmdWxsTGF5b3V0KTtcblxuICAgIC8vIGZpbmFsbHkgZHJhdyBhbGwgdGhlIGNvbXBvbmVudHMgd2UgbmVlZCB0b1xuICAgIC8vIGlmIHdlIGFkZGVkIG9yIHJlbW92ZWQgYW55LCByZWRyYXcgYWxsIGFmdGVyIGl0XG4gICAgaWYoZHJhd09uZSAhPT0gbm9vcCkge1xuICAgICAgICB2YXIgaW5kaWNlc1RvRHJhdztcbiAgICAgICAgaWYoZmlyc3RJbmRleENoYW5nZSA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIHRoZXJlJ3Mgbm8gcmUtaW5kZXhpbmcgdG8gZG8sIHNvIG9ubHkgcmVkcmF3IGNvbXBvbmVudHMgdGhhdCBjaGFuZ2VkXG4gICAgICAgICAgICBpbmRpY2VzVG9EcmF3ID0gY29tcG9uZW50TnVtcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGluIGNhc2UgdGhlIGNvbXBvbmVudCBhcnJheSB3YXMgc2hvcnRlbmVkLCB3ZSBzdGlsbCBuZWVkIGRvIGNhbGxcbiAgICAgICAgICAgIC8vIGRyYXdPbmUgb24gdGhlIGxhdHRlciBpdGVtcyBzbyB0aGV5IGdldCBwcm9wZXJseSByZW1vdmVkXG4gICAgICAgICAgICBtYXhJbmRleCA9IE1hdGgubWF4KGNvbXBvbmVudEFycmF5Lmxlbmd0aCwgbWF4SW5kZXgpO1xuICAgICAgICAgICAgaW5kaWNlc1RvRHJhdyA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY29tcG9uZW50TnVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudE51bSA9IGNvbXBvbmVudE51bXNbaV07XG4gICAgICAgICAgICAgICAgaWYoY29tcG9uZW50TnVtID49IGZpcnN0SW5kZXhDaGFuZ2UpIGJyZWFrO1xuICAgICAgICAgICAgICAgIGluZGljZXNUb0RyYXcucHVzaChjb21wb25lbnROdW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKGkgPSBmaXJzdEluZGV4Q2hhbmdlOyBpIDwgbWF4SW5kZXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGluZGljZXNUb0RyYXcucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzVG9EcmF3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBkcmF3T25lKGdkLCBpbmRpY2VzVG9EcmF3W2ldKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGRyYXcoZ2QpO1xuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIGhhc0hvdmVyID0gcmVxdWlyZSgnaGFzLWhvdmVyJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBFdmVudHMgPSByZXF1aXJlKCcuLi9saWIvZXZlbnRzJyk7XG52YXIgUXVldWUgPSByZXF1aXJlKCcuLi9saWIvcXVldWUnKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vcmVnaXN0cnknKTtcbnZhciBQbG90U2NoZW1hID0gcmVxdWlyZSgnLi9wbG90X3NjaGVtYScpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBQb2xhciA9IHJlcXVpcmUoJy4uL3Bsb3RzL3BvbGFyL2xlZ2FjeScpO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGNvbm5lY3RDb2xvcmJhciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvY29sb3JiYXIvY29ubmVjdCcpO1xudmFyIGluaXRJbnRlcmFjdGlvbnMgPSByZXF1aXJlKCcuLi9wbG90cy9jYXJ0ZXNpYW4vZ3JhcGhfaW50ZXJhY3QnKS5pbml0SW50ZXJhY3Rpb25zO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IHJlcXVpcmUoJy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG5cbnZhciBkZWZhdWx0Q29uZmlnID0gcmVxdWlyZSgnLi9wbG90X2NvbmZpZycpO1xudmFyIG1hbmFnZUFycmF5cyA9IHJlcXVpcmUoJy4vbWFuYWdlX2FycmF5cycpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBzdWJyb3V0aW5lcyA9IHJlcXVpcmUoJy4vc3Vicm91dGluZXMnKTtcbnZhciBlZGl0VHlwZXMgPSByZXF1aXJlKCcuL2VkaXRfdHlwZXMnKTtcblxudmFyIEFYX05BTUVfUEFUVEVSTiA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9jb25zdGFudHMnKS5BWF9OQU1FX1BBVFRFUk47XG5cbnZhciBudW1lcmljTmFtZVdhcm5pbmdDb3VudCA9IDA7XG52YXIgbnVtZXJpY05hbWVXYXJuaW5nQ291bnRMaW1pdCA9IDU7XG5cbi8qKlxuICogTWFpbiBwbG90LWNyZWF0aW9uIGZ1bmN0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmcgaWQgb3IgRE9NIGVsZW1lbnR9IGdkXG4gKiAgICAgIHRoZSBpZCBvciBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHthcnJheSBvZiBvYmplY3RzfSBkYXRhXG4gKiAgICAgIGFycmF5IG9mIHRyYWNlcywgY29udGFpbmluZyB0aGUgZGF0YSBhbmQgZGlzcGxheSBpbmZvcm1hdGlvbiBmb3IgZWFjaCB0cmFjZVxuICogQHBhcmFtIHtvYmplY3R9IGxheW91dFxuICogICAgICBvYmplY3QgZGVzY3JpYmluZyB0aGUgb3ZlcmFsbCBkaXNwbGF5IG9mIHRoZSBwbG90LFxuICogICAgICBhbGwgdGhlIHN0dWZmIHRoYXQgZG9lc24ndCBwZXJ0YWluIHRvIGFueSBpbmRpdmlkdWFsIHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gY29uZmlnXG4gKiAgICAgIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyAoc2VlIC4vcGxvdF9jb25maWcuanMgZm9yIG1vcmUgaW5mbylcbiAqXG4gKiBPUlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nIGlkIG9yIERPTSBlbGVtZW50fSBnZFxuICogICAgICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7b2JqZWN0fSBmaWd1cmVcbiAqICAgICAgb2JqZWN0IGNvbnRhaW5pbmcgYGRhdGFgLCBgbGF5b3V0YCwgYGNvbmZpZ2AsIGFuZCBgZnJhbWVzYCBtZW1iZXJzXG4gKlxuICovXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCwgZGF0YSwgbGF5b3V0LCBjb25maWcpIHtcbiAgICB2YXIgZnJhbWVzO1xuXG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgLy8gRXZlbnRzLmluaXQgaXMgaWRlbXBvdGVudCBhbmQgYmFpbHMgZWFybHkgaWYgZ2QgaGFzIGFscmVhZHkgYmVlbiBpbml0J2RcbiAgICBFdmVudHMuaW5pdChnZCk7XG5cbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdChkYXRhKSkge1xuICAgICAgICB2YXIgb2JqID0gZGF0YTtcbiAgICAgICAgZGF0YSA9IG9iai5kYXRhO1xuICAgICAgICBsYXlvdXQgPSBvYmoubGF5b3V0O1xuICAgICAgICBjb25maWcgPSBvYmouY29uZmlnO1xuICAgICAgICBmcmFtZXMgPSBvYmouZnJhbWVzO1xuICAgIH1cblxuICAgIHZhciBva1RvUGxvdCA9IEV2ZW50cy50cmlnZ2VySGFuZGxlcihnZCwgJ3Bsb3RseV9iZWZvcmVwbG90JywgW2RhdGEsIGxheW91dCwgY29uZmlnXSk7XG4gICAgaWYob2tUb1Bsb3QgPT09IGZhbHNlKSByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcblxuICAgIC8vIGlmIHRoZXJlJ3Mgbm8gZGF0YSBvciBsYXlvdXQsIGFuZCB0aGlzIGlzbid0IHlldCBhIHBsb3RseSBwbG90XG4gICAgLy8gY29udGFpbmVyLCBsb2cgYSB3YXJuaW5nIHRvIGhlbHAgcGxvdGx5LmpzIHVzZXJzIGRlYnVnXG4gICAgaWYoIWRhdGEgJiYgIWxheW91dCAmJiAhTGliLmlzUGxvdERpdihnZCkpIHtcbiAgICAgICAgTGliLndhcm4oJ0NhbGxpbmcgUGxvdGx5LnBsb3QgYXMgaWYgcmVkcmF3aW5nICcgK1xuICAgICAgICAgICAgJ2J1dCB0aGlzIGNvbnRhaW5lciBkb2VzblxcJ3QgeWV0IGhhdmUgYSBwbG90LicsIGdkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGRGcmFtZXMoKSB7XG4gICAgICAgIGlmKGZyYW1lcykge1xuICAgICAgICAgICAgcmV0dXJuIGV4cG9ydHMuYWRkRnJhbWVzKGdkLCBmcmFtZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdHJhbnNmZXIgY29uZmlndXJhdGlvbiBvcHRpb25zIHRvIGdkIHVudGlsIHdlIG1vdmUgb3ZlciB0b1xuICAgIC8vIGEgbW9yZSBPTyBsaWtlIG1vZGVsXG4gICAgc2V0UGxvdENvbnRleHQoZ2QsIGNvbmZpZyk7XG5cbiAgICBpZighbGF5b3V0KSBsYXlvdXQgPSB7fTtcblxuICAgIC8vIGhvb2sgY2xhc3MgZm9yIHBsb3RzIG1haW4gY29udGFpbmVyIChpbiBjYXNlIG9mIHBsb3RseS5qc1xuICAgIC8vIHRoaXMgd29uJ3QgYmUgI2VtYmVkZGVkLWdyYXBoIG9yIC5qcy10YWItY29udGVudHMpXG4gICAgZDMuc2VsZWN0KGdkKS5jbGFzc2VkKCdqcy1wbG90bHktcGxvdCcsIHRydWUpO1xuXG4gICAgLy8gb2ZmLXNjcmVlbiBnZXRCb3VuZGluZ0NsaWVudFJlY3QgdGVzdGluZyBzcGFjZSxcbiAgICAvLyBpbiAjanMtcGxvdGx5LXRlc3RlciAoYW5kIHN0b3JlZCBhcyBEcmF3aW5nLnRlc3RlcilcbiAgICAvLyBzbyB3ZSBjYW4gc2hhcmUgY2FjaGVkIHRleHQgYWNyb3NzIHRhYnNcbiAgICBEcmF3aW5nLm1ha2VUZXN0ZXIoKTtcblxuICAgIC8vIGNsZWFyIHN0YXNoZWQgYmFzZSB1cmxcbiAgICBkZWxldGUgRHJhd2luZy5iYXNlVXJsO1xuXG4gICAgLy8gY29sbGVjdCBwcm9taXNlcyBmb3IgYW55IGFzeW5jIGFjdGlvbnMgZHVyaW5nIHBsb3R0aW5nXG4gICAgLy8gYW55IHBhcnQgb2YgdGhlIHBsb3R0aW5nIGNvZGUgY2FuIHB1c2ggdG8gZ2QuX3Byb21pc2VzLCB0aGVuXG4gICAgLy8gYmVmb3JlIHdlIG1vdmUgdG8gdGhlIG5leHQgc3RlcCwgd2UgY2hlY2sgdGhhdCB0aGV5J3JlIGFsbFxuICAgIC8vIGNvbXBsZXRlLCBhbmQgZW1wdHkgb3V0IHRoZSBwcm9taXNlIGxpc3QgYWdhaW4uXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoZ2QuX3Byb21pc2VzKSkgZ2QuX3Byb21pc2VzID0gW107XG5cbiAgICB2YXIgZ3JhcGhXYXNFbXB0eSA9ICgoZ2QuZGF0YSB8fCBbXSkubGVuZ3RoID09PSAwICYmIEFycmF5LmlzQXJyYXkoZGF0YSkpO1xuXG4gICAgLy8gaWYgdGhlcmUgaXMgYWxyZWFkeSBkYXRhIG9uIHRoZSBncmFwaCwgYXBwZW5kIHRoZSBuZXcgZGF0YVxuICAgIC8vIGlmIHlvdSBvbmx5IHdhbnQgdG8gcmVkcmF3LCBwYXNzIGEgbm9uLWFycmF5IGZvciBkYXRhXG4gICAgaWYoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICBoZWxwZXJzLmNsZWFuRGF0YShkYXRhKTtcblxuICAgICAgICBpZihncmFwaFdhc0VtcHR5KSBnZC5kYXRhID0gZGF0YTtcbiAgICAgICAgZWxzZSBnZC5kYXRhLnB1c2guYXBwbHkoZ2QuZGF0YSwgZGF0YSk7XG5cbiAgICAgICAgLy8gZm9yIHJvdXRpbmVzIG91dHNpZGUgZ3JhcGhfb2JqIHRoYXQgd2FudCBhIGNsZWFuIHRhYlxuICAgICAgICAvLyAocmF0aGVyIHRoYW4gYXBwZW5kaW5nIHRvIGFuIGV4aXN0aW5nIG9uZSkgZ2QuZW1wdHlcbiAgICAgICAgLy8gaXMgdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciB0byBtYWtlIGEgbmV3IHRhYlxuICAgICAgICBnZC5lbXB0eSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKCFnZC5sYXlvdXQgfHwgZ3JhcGhXYXNFbXB0eSkgZ2QubGF5b3V0ID0gaGVscGVycy5jbGVhbkxheW91dChsYXlvdXQpO1xuXG4gICAgLy8gaWYgdGhlIHVzZXIgaXMgdHJ5aW5nIHRvIGRyYWcgdGhlIGF4ZXMsIGFsbG93IG5ldyBkYXRhIGFuZCBsYXlvdXRcbiAgICAvLyB0byBjb21lIGluIGJ1dCBkb24ndCBhbGxvdyBhIHJlcGxvdC5cbiAgICBpZihnZC5fZHJhZ2dpbmcgJiYgIWdkLl90cmFuc2l0aW9uaW5nKSB7XG4gICAgICAgIC8vIHNpZ25hbCB0byBkcmFnIGhhbmRsZXIgdGhhdCBhZnRlciBldmVyeXRoaW5nIGVsc2UgaXMgZG9uZVxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHJlcGxvdCwgYmVjYXVzZSBzb21ldGhpbmcgaGFzIGNoYW5nZWRcbiAgICAgICAgZ2QuX3JlcGxvdFBlbmRpbmcgPSB0cnVlO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSdyZSBnb2luZyBhaGVhZCB3aXRoIGEgcmVwbG90IG5vd1xuICAgICAgICBnZC5fcmVwbG90UGVuZGluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGhhc0NhcnRlc2lhbiA9IGZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJyk7XG5cbiAgICAvLyBMZWdhY3kgcG9sYXIgcGxvdHNcbiAgICBpZighZnVsbExheW91dC5faGFzKCdwb2xhcicpICYmIGRhdGEgJiYgZGF0YVswXSAmJiBkYXRhWzBdLnIpIHtcbiAgICAgICAgTGliLmxvZygnTGVnYWN5IHBvbGFyIGNoYXJ0cyBhcmUgZGVwcmVjYXRlZCEnKTtcbiAgICAgICAgcmV0dXJuIHBsb3RQb2xhcihnZCwgZGF0YSwgbGF5b3V0KTtcbiAgICB9XG5cbiAgICAvLyBzbyB3ZSBkb24ndCB0cnkgdG8gcmUtY2FsbCBQbG90bHkucGxvdCBmcm9tIGluc2lkZVxuICAgIC8vIGxlZ2VuZCBhbmQgY29sb3JiYXIsIGlmIG1hcmdpbnMgY2hhbmdlZFxuICAgIGZ1bGxMYXlvdXQuX3JlcGxvdHRpbmcgPSB0cnVlO1xuXG4gICAgLy8gbWFrZSBvciByZW1ha2UgdGhlIGZyYW1ld29yayBpZiB3ZSBuZWVkIHRvXG4gICAgaWYoZ3JhcGhXYXNFbXB0eSkgbWFrZVBsb3RGcmFtZXdvcmsoZ2QpO1xuXG4gICAgLy8gcG9sYXIgbmVlZCBhIGRpZmZlcmVudCBmcmFtZXdvcmtcbiAgICBpZihnZC5mcmFtZXdvcmsgIT09IG1ha2VQbG90RnJhbWV3b3JrKSB7XG4gICAgICAgIGdkLmZyYW1ld29yayA9IG1ha2VQbG90RnJhbWV3b3JrO1xuICAgICAgICBtYWtlUGxvdEZyYW1ld29yayhnZCk7XG4gICAgfVxuXG4gICAgLy8gY2xlYXIgZ3JhZGllbnQgZGVmcyBvbiBlYWNoIC5wbG90IGNhbGwsIGJlY2F1c2Ugd2Uga25vdyB3ZSdsbCBsb29wIHRocm91Z2ggYWxsIHRyYWNlc1xuICAgIERyYXdpbmcuaW5pdEdyYWRpZW50cyhnZCk7XG5cbiAgICAvLyBzYXZlIGluaXRpYWwgc2hvdyBzcGlrZXMgb25jZSBwZXIgZ3JhcGhcbiAgICBpZihncmFwaFdhc0VtcHR5KSBBeGVzLnNhdmVTaG93U3Bpa2VJbml0aWFsKGdkKTtcblxuICAgIC8vIHByZXBhcmUgdGhlIGRhdGEgYW5kIGZpbmQgdGhlIGF1dG9yYW5nZVxuXG4gICAgLy8gZ2VuZXJhdGUgY2FsY2RhdGEsIGlmIHdlIG5lZWQgdG9cbiAgICAvLyB0byBmb3JjZSByZWRvaW5nIGNhbGNkYXRhLCBqdXN0IGRlbGV0ZSBpdCBiZWZvcmUgY2FsbGluZyBQbG90bHkucGxvdFxuICAgIHZhciByZWNhbGMgPSAhZ2QuY2FsY2RhdGEgfHwgZ2QuY2FsY2RhdGEubGVuZ3RoICE9PSAoZ2QuX2Z1bGxEYXRhIHx8IFtdKS5sZW5ndGg7XG4gICAgaWYocmVjYWxjKSBQbG90cy5kb0NhbGNkYXRhKGdkKTtcblxuICAgIC8vIGluIGNhc2UgaXQgaGFzIGNoYW5nZWQsIGF0dGFjaCBmdWxsRGF0YSB0cmFjZXMgdG8gY2FsY2RhdGFcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZ2QuY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ2QuY2FsY2RhdGFbaV1bMF0udHJhY2UgPSBnZC5fZnVsbERhdGFbaV07XG4gICAgfVxuXG4gICAgLy8gbWFrZSB0aGUgZmlndXJlIHJlc3BvbnNpdmVcbiAgICBpZihnZC5fY29udGV4dC5yZXNwb25zaXZlKSB7XG4gICAgICAgIGlmKCFnZC5fcmVzcG9uc2l2ZUNoYXJ0SGFuZGxlcikge1xuICAgICAgICAgICAgLy8gS2VlcCBhIHJlZmVyZW5jZSB0byB0aGUgcmVzaXplIGhhbmRsZXIgdG8gcHVyZ2UgaXQgZG93biB0aGUgcm9hZFxuICAgICAgICAgICAgZ2QuX3Jlc3BvbnNpdmVDaGFydEhhbmRsZXIgPSBmdW5jdGlvbigpIHtQbG90cy5yZXNpemUoZ2QpO307XG5cbiAgICAgICAgICAgIC8vIExpc3RlbiB0byB3aW5kb3cgcmVzaXplXG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgZ2QuX3Jlc3BvbnNpdmVDaGFydEhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgTGliLmNsZWFyUmVzcG9uc2l2ZShnZCk7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBzdGFydCBhc3luYy1mcmllbmRseSBjb2RlIC0gbm93IHdlJ3JlIGFjdHVhbGx5IGRyYXdpbmcgdGhpbmdzXG4gICAgICovXG5cbiAgICB2YXIgb2xkbWFyZ2lucyA9IEpTT04uc3RyaW5naWZ5KGZ1bGxMYXlvdXQuX3NpemUpO1xuXG4gICAgLy8gZHJhdyBmcmFtZXdvcmsgZmlyc3Qgc28gdGhhdCBtYXJnaW4tcHVzaGluZ1xuICAgIC8vIGNvbXBvbmVudHMgY2FuIHBvc2l0aW9uIHRoZW1zZWx2ZXMgY29ycmVjdGx5XG4gICAgdmFyIGRyYXdGcmFtZXdvcmtDYWxscyA9IDA7XG4gICAgZnVuY3Rpb24gZHJhd0ZyYW1ld29yaygpIHtcbiAgICAgICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihiYXNlUGxvdE1vZHVsZXNbaV0uZHJhd0ZyYW1ld29yaykge1xuICAgICAgICAgICAgICAgIGJhc2VQbG90TW9kdWxlc1tpXS5kcmF3RnJhbWV3b3JrKGdkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFmdWxsTGF5b3V0Ll9nbGNhbnZhcyAmJiBmdWxsTGF5b3V0Ll9oYXMoJ2dsJykpIHtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX2dsY2FudmFzID0gZnVsbExheW91dC5fZ2xjb250YWluZXIuc2VsZWN0QWxsKCcuZ2wtY2FudmFzJykuZGF0YShbe1xuICAgICAgICAgICAgICAgIGtleTogJ2NvbnRleHRMYXllcicsXG4gICAgICAgICAgICAgICAgY29udGV4dDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBwaWNrOiBmYWxzZVxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGtleTogJ2ZvY3VzTGF5ZXInLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHBpY2s6IGZhbHNlXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAga2V5OiAncGlja0xheWVyJyxcbiAgICAgICAgICAgICAgICBjb250ZXh0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBwaWNrOiB0cnVlXG4gICAgICAgICAgICB9XSwgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5rZXk7IH0pO1xuXG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5lbnRlcigpLmFwcGVuZCgnY2FudmFzJylcbiAgICAgICAgICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZ2wtY2FudmFzIGdsLWNhbnZhcy0nICsgZC5rZXkucmVwbGFjZSgnTGF5ZXInLCAnJyk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAncG9zaXRpb24nOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgICAgICAgICAndG9wJzogMCxcbiAgICAgICAgICAgICAgICAgICAgJ2xlZnQnOiAwLFxuICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiAnMTAwJScsXG4gICAgICAgICAgICAgICAgICAgICdoZWlnaHQnOiAnMTAwJScsXG4gICAgICAgICAgICAgICAgICAgICdvdmVyZmxvdyc6ICd2aXNpYmxlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihmdWxsTGF5b3V0Ll9nbGNhbnZhcykge1xuICAgICAgICAgICAgZnVsbExheW91dC5fZ2xjYW52YXNcbiAgICAgICAgICAgICAgICAuYXR0cignd2lkdGgnLCBmdWxsTGF5b3V0LndpZHRoKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdWxsTGF5b3V0LmhlaWdodCk7XG5cbiAgICAgICAgICAgIHZhciByZWdsID0gZnVsbExheW91dC5fZ2xjYW52YXMuZGF0YSgpWzBdLnJlZ2w7XG4gICAgICAgICAgICBpZihyZWdsKSB7XG4gICAgICAgICAgICAgICAgLy8gVW5mb3J0dW5hdGVseSwgdGhpcyBjYW4gaGFwcGVuIHdoZW4gcmVsYXlvdXRpbmcgdG8gbGFyZ2VcbiAgICAgICAgICAgICAgICAvLyB3aWR0aC9oZWlnaHQgb24gc29tZSBicm93c2Vycy5cbiAgICAgICAgICAgICAgICBpZihNYXRoLmZsb29yKGZ1bGxMYXlvdXQud2lkdGgpICE9PSByZWdsLl9nbC5kcmF3aW5nQnVmZmVyV2lkdGggfHxcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5mbG9vcihmdWxsTGF5b3V0LmhlaWdodCkgIT09IHJlZ2wuX2dsLmRyYXdpbmdCdWZmZXJIZWlnaHRcbiAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtc2cgPSAnV2ViR0wgY29udGV4dCBidWZmZXIgYW5kIGNhbnZhcyBkaW1lbnNpb25zIGRvIG5vdCBtYXRjaCBkdWUgdG8gYnJvd3Nlci9XZWJHTCBidWcuJztcbiAgICAgICAgICAgICAgICAgICAgaWYoZHJhd0ZyYW1ld29ya0NhbGxzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMaWIuZXJyb3IobXNnKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExpYi5sb2cobXNnICsgJyBDbGVhcmluZyBncmFwaCBhbmQgcGxvdHRpbmcgYWdhaW4uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBQbG90cy5jbGVhblBsb3QoW10sIHt9LCBnZC5fZnVsbERhdGEsIGZ1bGxMYXlvdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZ2QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgUGxvdHMuZG9DYWxjZGF0YShnZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBkcmF3RnJhbWV3b3JrQ2FsbHMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkcmF3RnJhbWV3b3JrKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG4gICAgfVxuXG4gICAgLy8gZHJhdyBhbnl0aGluZyB0aGF0IGNhbiBhZmZlY3QgbWFyZ2lucy5cbiAgICBmdW5jdGlvbiBtYXJnaW5QdXNoZXJzKCkge1xuICAgICAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICAgICAgdmFyIGksIGNkLCB0cmFjZTtcblxuICAgICAgICAvLyBGaXJzdCByZXNldCB0aGUgbGlzdCBvZiB0aGluZ3MgdGhhdCBhcmUgYWxsb3dlZCB0byBjaGFuZ2UgdGhlIG1hcmdpbnNcbiAgICAgICAgLy8gU28gYW55IGRlbGV0ZWQgdHJhY2VzIG9yIGNvbXBvbmVudHMgd2lsbCBiZSB3aXBlZCBvdXQgb2YgdGhlXG4gICAgICAgIC8vIGF1dG9tYXJnaW4gY2FsY3VsYXRpb24uXG4gICAgICAgIC8vIFRoaXMgbWVhbnMgKmV2ZXJ5KiBtYXJnaW4gcHVzaGVyIG11c3QgYmUgbGlzdGVkIGhlcmUsIGV2ZW4gaWYgaXRcbiAgICAgICAgLy8gZG9lc24ndCBhY3R1YWxseSB0cnkgdG8gcHVzaCB0aGUgbWFyZ2lucyB1bnRpbCBsYXRlci5cbiAgICAgICAgUGxvdHMuY2xlYXJBdXRvTWFyZ2luSWRzKGdkKTtcblxuICAgICAgICBzdWJyb3V0aW5lcy5kcmF3TWFyZ2luUHVzaGVycyhnZCk7XG4gICAgICAgIEF4ZXMuYWxsb3dBdXRvTWFyZ2luKGdkKTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjYWxjZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB2YXIgY29sb3JiYXJPcHRzID0gdHJhY2UuX21vZHVsZS5jb2xvcmJhcjtcbiAgICAgICAgICAgIGlmKHRyYWNlLnZpc2libGUgIT09IHRydWUgfHwgIWNvbG9yYmFyT3B0cykge1xuICAgICAgICAgICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdjYicgKyB0cmFjZS51aWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBjb25uZWN0Q29sb3JiYXIoZ2QsIGNkLCBjb2xvcmJhck9wdHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgUGxvdHMuZG9BdXRvTWFyZ2luKGdkKTtcbiAgICAgICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xuICAgIH1cblxuICAgIC8vIGluIGNhc2UgdGhlIG1hcmdpbnMgY2hhbmdlZCwgZHJhdyBtYXJnaW4gcHVzaGVycyBhZ2FpblxuICAgIGZ1bmN0aW9uIG1hcmdpblB1c2hlcnNBZ2FpbigpIHtcbiAgICAgICAgaWYoSlNPTi5zdHJpbmdpZnkoZnVsbExheW91dC5fc2l6ZSkgPT09IG9sZG1hcmdpbnMpIHJldHVybjtcblxuICAgICAgICByZXR1cm4gTGliLnN5bmNPckFzeW5jKFtcbiAgICAgICAgICAgIG1hcmdpblB1c2hlcnMsXG4gICAgICAgICAgICBzdWJyb3V0aW5lcy5sYXlvdXRTdHlsZXNcbiAgICAgICAgXSwgZ2QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc2l0aW9uQW5kQXV0b3JhbmdlKCkge1xuICAgICAgICBpZighcmVjYWxjKSB7XG4gICAgICAgICAgICBkb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiBhdXRvc2l6ZSBleHRyYSBmb3IgdGV4dCBtYXJrZXJzIGFuZCBpbWFnZXNcbiAgICAgICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8xMTExXG4gICAgICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdzaGFwZXMnLCAnY2FsY0F1dG9yYW5nZScpLFxuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdjYWxjQXV0b3JhbmdlJyksXG4gICAgICAgICAgICBkb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzLFxuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdjYWxjQXV0b3JhbmdlJylcbiAgICAgICAgXSwgZ2QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvQXV0b1JhbmdlQW5kQ29uc3RyYWludHMoKSB7XG4gICAgICAgIGlmKGdkLl90cmFuc2l0aW9uaW5nKSByZXR1cm47XG5cbiAgICAgICAgc3Vicm91dGluZXMuZG9BdXRvUmFuZ2VBbmRDb25zdHJhaW50cyhnZCk7XG5cbiAgICAgICAgLy8gc3RvcmUgaW5pdGlhbCByYW5nZXMgKmFmdGVyKiBlbmZvcmNpbmcgY29uc3RyYWludHMsIG90aGVyd2lzZVxuICAgICAgICAvLyB3ZSB3aWxsIG5ldmVyIGxvb2sgbGlrZSB3ZSdyZSBhdCB0aGUgaW5pdGlhbCByYW5nZXNcbiAgICAgICAgaWYoZ3JhcGhXYXNFbXB0eSkgQXhlcy5zYXZlUmFuZ2VJbml0aWFsKGdkKTtcbiAgICB9XG5cbiAgICAvLyBkcmF3IHRpY2tzLCB0aXRsZXMsIGFuZCBjYWxjdWxhdGUgYXhpcyBzY2FsaW5nICguX2IsIC5fbSlcbiAgICBmdW5jdGlvbiBkcmF3QXhlcygpIHtcbiAgICAgICAgcmV0dXJuIEF4ZXMuZG9UaWNrcyhnZCwgZ3JhcGhXYXNFbXB0eSA/ICcnIDogJ3JlZHJhdycpO1xuICAgIH1cblxuICAgIHZhciBzZXEgPSBbXG4gICAgICAgIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMsXG4gICAgICAgIGFkZEZyYW1lcyxcbiAgICAgICAgZHJhd0ZyYW1ld29yayxcbiAgICAgICAgbWFyZ2luUHVzaGVycyxcbiAgICAgICAgbWFyZ2luUHVzaGVyc0FnYWluXG4gICAgXTtcblxuICAgIGlmKGhhc0NhcnRlc2lhbikgc2VxLnB1c2gocG9zaXRpb25BbmRBdXRvcmFuZ2UpO1xuXG4gICAgc2VxLnB1c2goc3Vicm91dGluZXMubGF5b3V0U3R5bGVzKTtcbiAgICBpZihoYXNDYXJ0ZXNpYW4pIHNlcS5wdXNoKGRyYXdBeGVzKTtcblxuICAgIHNlcS5wdXNoKFxuICAgICAgICBzdWJyb3V0aW5lcy5kcmF3RGF0YSxcbiAgICAgICAgc3Vicm91dGluZXMuZmluYWxEcmF3LFxuICAgICAgICBpbml0SW50ZXJhY3Rpb25zLFxuICAgICAgICBQbG90cy5hZGRMaW5rcyxcbiAgICAgICAgUGxvdHMucmVob3ZlcixcbiAgICAgICAgLy8gVE9ETzogZG9BdXRvTWFyZ2luIGlzIG9ubHkgbmVlZGVkIGhlcmUgZm9yIGF4aXMgYXV0b21hcmdpbiwgd2hpY2hcbiAgICAgICAgLy8gaGFwcGVucyBvdXRzaWRlIG9mIG1hcmdpblB1c2hlcnMgd2hlcmUgYWxsIHRoZSBvdGhlciBhdXRvbWFyZ2lucyBhcmVcbiAgICAgICAgLy8gY2FsY3VsYXRlZC4gV291bGQgYmUgbXVjaCBiZXR0ZXIgdG8gc2VwYXJhdGUgbWFyZ2luIGNhbGN1bGF0aW9ucyBmcm9tXG4gICAgICAgIC8vIGNvbXBvbmVudCBkcmF3aW5nIC0gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8yNzA0XG4gICAgICAgIFBsb3RzLmRvQXV0b01hcmdpbixcbiAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlc1xuICAgICk7XG5cbiAgICAvLyBldmVuIGlmIGV2ZXJ5dGhpbmcgd2UgZGlkIHdhcyBzeW5jaHJvbm91cywgcmV0dXJuIGEgcHJvbWlzZVxuICAgIC8vIHNvIHRoYXQgdGhlIGNhbGxlciBkb2Vzbid0IGNhcmUgd2hpY2ggcm91dGUgd2UgdG9va1xuICAgIHZhciBwbG90RG9uZSA9IExpYi5zeW5jT3JBc3luYyhzZXEsIGdkKTtcbiAgICBpZighcGxvdERvbmUgfHwgIXBsb3REb25lLnRoZW4pIHBsb3REb25lID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICByZXR1cm4gcGxvdERvbmUudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgZW1pdEFmdGVyUGxvdChnZCk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGVtaXRBZnRlclBsb3QoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoZnVsbExheW91dC5fcmVkcmF3RnJvbUF1dG9NYXJnaW5Db3VudCkge1xuICAgICAgICBmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50LS07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FmdGVycGxvdCcpO1xuICAgIH1cbn1cblxuZXhwb3J0cy5zZXRQbG90Q29uZmlnID0gZnVuY3Rpb24gc2V0UGxvdENvbmZpZyhvYmopIHtcbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoZGVmYXVsdENvbmZpZywgb2JqKTtcbn07XG5cbmZ1bmN0aW9uIHNldEJhY2tncm91bmQoZ2QsIGJnQ29sb3IpIHtcbiAgICB0cnkge1xuICAgICAgICBnZC5fZnVsbExheW91dC5fcGFwZXIuc3R5bGUoJ2JhY2tncm91bmQnLCBiZ0NvbG9yKTtcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgTGliLmVycm9yKGUpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gb3BhcXVlU2V0QmFja2dyb3VuZChnZCwgYmdDb2xvcikge1xuICAgIHZhciBibGVuZCA9IENvbG9yLmNvbWJpbmUoYmdDb2xvciwgJ3doaXRlJyk7XG4gICAgc2V0QmFja2dyb3VuZChnZCwgYmxlbmQpO1xufVxuXG5mdW5jdGlvbiBzZXRQbG90Q29udGV4dChnZCwgY29uZmlnKSB7XG4gICAgaWYoIWdkLl9jb250ZXh0KSBnZC5fY29udGV4dCA9IExpYi5leHRlbmREZWVwKHt9LCBkZWZhdWx0Q29uZmlnKTtcbiAgICB2YXIgY29udGV4dCA9IGdkLl9jb250ZXh0O1xuXG4gICAgdmFyIGksIGtleXMsIGtleTtcblxuICAgIGlmKGNvbmZpZykge1xuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoY29uZmlnKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICAgIGlmKGtleSA9PT0gJ2VkaXRhYmxlJyB8fCBrZXkgPT09ICdlZGl0cycpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYoa2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZihrZXkgPT09ICdzZXRCYWNrZ3JvdW5kJyAmJiBjb25maWdba2V5XSA9PT0gJ29wYXF1ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dFtrZXldID0gb3BhcXVlU2V0QmFja2dyb3VuZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0W2tleV0gPSBjb25maWdba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtYXAgcGxvdDNkUGl4ZWxSYXRpbyB0byBwbG90R2xQaXhlbFJhdGlvIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICAgIGlmKGNvbmZpZy5wbG90M2RQaXhlbFJhdGlvICYmICFjb250ZXh0LnBsb3RHbFBpeGVsUmF0aW8pIHtcbiAgICAgICAgICAgIGNvbnRleHQucGxvdEdsUGl4ZWxSYXRpbyA9IGNvbnRleHQucGxvdDNkUGl4ZWxSYXRpbztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBkZWFsIHdpdGggZWRpdGFibGUgYW5kIGVkaXRzIC0gZmlyc3QgZWRpdGFibGUgb3ZlcnJpZGVzXG4gICAgICAgIC8vIGV2ZXJ5dGhpbmcsIHRoZW4gZWRpdHMgcmVmaW5lc1xuICAgICAgICB2YXIgZWRpdGFibGUgPSBjb25maWcuZWRpdGFibGU7XG4gICAgICAgIGlmKGVkaXRhYmxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHdlJ3JlIG5vdCBnb2luZyB0byAqdXNlKiBjb250ZXh0LmVkaXRhYmxlLCB3ZSdyZSBvbmx5IGdvaW5nIHRvXG4gICAgICAgICAgICAvLyB1c2UgY29udGV4dC5lZGl0cy4uLiBidXQga2VlcCBpdCBmb3IgdGhlIHJlY29yZFxuICAgICAgICAgICAgY29udGV4dC5lZGl0YWJsZSA9IGVkaXRhYmxlO1xuXG4gICAgICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoY29udGV4dC5lZGl0cyk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5lZGl0c1trZXlzW2ldXSA9IGVkaXRhYmxlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKGNvbmZpZy5lZGl0cykge1xuICAgICAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzKGNvbmZpZy5lZGl0cyk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICAgICAgICBpZihrZXkgaW4gY29udGV4dC5lZGl0cykge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmVkaXRzW2tleV0gPSBjb25maWcuZWRpdHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzdGF0aWNQbG90IGZvcmNlcyBhIGJ1bmNoIG9mIG90aGVyczpcbiAgICBpZihjb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgY29udGV4dC5lZGl0YWJsZSA9IGZhbHNlO1xuICAgICAgICBjb250ZXh0LmVkaXRzID0ge307XG4gICAgICAgIGNvbnRleHQuYXV0b3NpemFibGUgPSBmYWxzZTtcbiAgICAgICAgY29udGV4dC5zY3JvbGxab29tID0gZmFsc2U7XG4gICAgICAgIGNvbnRleHQuZG91YmxlQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgY29udGV4dC5zaG93VGlwcyA9IGZhbHNlO1xuICAgICAgICBjb250ZXh0LnNob3dMaW5rID0gZmFsc2U7XG4gICAgICAgIGNvbnRleHQuZGlzcGxheU1vZGVCYXIgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgaG92ZXItb25seSBkZXZpY2VzIGhhdmUgbW9kZSBiYXIgdmlzaWJsZVxuICAgIGlmKGNvbnRleHQuZGlzcGxheU1vZGVCYXIgPT09ICdob3ZlcicgJiYgIWhhc0hvdmVyKSB7XG4gICAgICAgIGNvbnRleHQuZGlzcGxheU1vZGVCYXIgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIGRlZmF1bHQgYW5kIGZhbGxiYWNrIGZvciBzZXRCYWNrZ3JvdW5kXG4gICAgaWYoY29udGV4dC5zZXRCYWNrZ3JvdW5kID09PSAndHJhbnNwYXJlbnQnIHx8IHR5cGVvZiBjb250ZXh0LnNldEJhY2tncm91bmQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29udGV4dC5zZXRCYWNrZ3JvdW5kID0gc2V0QmFja2dyb3VuZDtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiBnZCBoYXMgYSBzcGVjaWZpZWQgd2lkaHQvaGVpZ2h0IHRvIGJlZ2luIHdpdGhcbiAgICBjb250ZXh0Ll9oYXNaZXJvSGVpZ2h0ID0gY29udGV4dC5faGFzWmVyb0hlaWdodCB8fCBnZC5jbGllbnRIZWlnaHQgPT09IDA7XG4gICAgY29udGV4dC5faGFzWmVyb1dpZHRoID0gY29udGV4dC5faGFzWmVyb1dpZHRoIHx8IGdkLmNsaWVudFdpZHRoID09PSAwO1xufVxuXG5mdW5jdGlvbiBwbG90UG9sYXIoZ2QsIGRhdGEsIGxheW91dCkge1xuICAgIC8vIGJ1aWxkIG9yIHJldXNlIHRoZSBjb250YWluZXIgc2tlbGV0b25cbiAgICB2YXIgcGxvdENvbnRhaW5lciA9IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCcucGxvdC1jb250YWluZXInKVxuICAgICAgICAuZGF0YShbMF0pO1xuICAgIHBsb3RDb250YWluZXIuZW50ZXIoKVxuICAgICAgICAuaW5zZXJ0KCdkaXYnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgLmNsYXNzZWQoJ3Bsb3QtY29udGFpbmVyIHBsb3RseScsIHRydWUpO1xuICAgIHZhciBwYXBlckRpdiA9IHBsb3RDb250YWluZXIuc2VsZWN0QWxsKCcuc3ZnLWNvbnRhaW5lcicpXG4gICAgICAgIC5kYXRhKFswXSk7XG4gICAgcGFwZXJEaXYuZW50ZXIoKS5hcHBlbmQoJ2RpdicpXG4gICAgICAgIC5jbGFzc2VkKCdzdmctY29udGFpbmVyJywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdwb3NpdGlvbicsICdyZWxhdGl2ZScpO1xuXG4gICAgLy8gZW1wdHkgaXQgZXZlcnl0aW1lIGZvciBub3dcbiAgICBwYXBlckRpdi5odG1sKCcnKTtcblxuICAgIC8vIGZ1bGZpbGwgZ2QgcmVxdWlyZW1lbnRzXG4gICAgaWYoZGF0YSkgZ2QuZGF0YSA9IGRhdGE7XG4gICAgaWYobGF5b3V0KSBnZC5sYXlvdXQgPSBsYXlvdXQ7XG4gICAgUG9sYXIubWFuYWdlci5maWxsTGF5b3V0KGdkKTtcblxuICAgIC8vIHJlc2l6ZSBjYW52YXNcbiAgICBwYXBlckRpdi5zdHlsZSh7XG4gICAgICAgIHdpZHRoOiBnZC5fZnVsbExheW91dC53aWR0aCArICdweCcsXG4gICAgICAgIGhlaWdodDogZ2QuX2Z1bGxMYXlvdXQuaGVpZ2h0ICsgJ3B4J1xuICAgIH0pO1xuXG4gICAgLy8gaW5zdGFudGlhdGUgZnJhbWV3b3JrXG4gICAgZ2QuZnJhbWV3b3JrID0gUG9sYXIubWFuYWdlci5mcmFtZXdvcmsoZ2QpO1xuXG4gICAgLy8gcGxvdFxuICAgIGdkLmZyYW1ld29yayh7ZGF0YTogZ2QuZGF0YSwgbGF5b3V0OiBnZC5sYXlvdXR9LCBwYXBlckRpdi5ub2RlKCkpO1xuXG4gICAgLy8gc2V0IHVuZG8gcG9pbnRcbiAgICBnZC5mcmFtZXdvcmsuc2V0VW5kb1BvaW50KCk7XG5cbiAgICAvLyBnZXQgdGhlIHJlc3VsdGluZyBzdmcgZm9yIGV4dGVuZGluZyBpdFxuICAgIHZhciBwb2xhclBsb3RTVkcgPSBnZC5mcmFtZXdvcmsuc3ZnKCk7XG5cbiAgICAvLyBlZGl0YWJsZSB0aXRsZVxuICAgIHZhciBvcGFjaXR5ID0gMTtcbiAgICB2YXIgdHh0ID0gZ2QuX2Z1bGxMYXlvdXQudGl0bGU7XG4gICAgaWYodHh0ID09PSAnJyB8fCAhdHh0KSBvcGFjaXR5ID0gMDtcblxuICAgIHZhciB0aXRsZUxheW91dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgICAgICAvLyBUT0RPOiBodG1sL21hdGhqYXhcbiAgICAgICAgLy8gVE9ETzogY2VudGVyIHRpdGxlXG4gICAgfTtcblxuICAgIHZhciB0aXRsZSA9IHBvbGFyUGxvdFNWRy5zZWxlY3QoJy50aXRsZS1ncm91cCB0ZXh0JylcbiAgICAgICAgLmNhbGwodGl0bGVMYXlvdXQpO1xuXG4gICAgaWYoZ2QuX2NvbnRleHQuZWRpdHMudGl0bGVUZXh0KSB7XG4gICAgICAgIHZhciBwbGFjZWhvbGRlclRleHQgPSBMaWIuXyhnZCwgJ0NsaWNrIHRvIGVudGVyIFBsb3QgdGl0bGUnKTtcbiAgICAgICAgaWYoIXR4dCB8fCB0eHQgPT09IHBsYWNlaG9sZGVyVGV4dCkge1xuICAgICAgICAgICAgb3BhY2l0eSA9IDAuMjtcbiAgICAgICAgICAgIC8vIHBsYWNlaG9sZGVyIGlzIG5vdCBnb2luZyB0aHJvdWdoIGNvbnZlcnRUb1RzcGFuc1xuICAgICAgICAgICAgLy8gc28gbmVlZHMgZXhwbGljaXQgZGF0YS11bmZvcm1hdHRlZFxuICAgICAgICAgICAgdGl0bGUuYXR0cih7J2RhdGEtdW5mb3JtYXR0ZWQnOiBwbGFjZWhvbGRlclRleHR9KVxuICAgICAgICAgICAgICAgIC50ZXh0KHBsYWNlaG9sZGVyVGV4dClcbiAgICAgICAgICAgICAgICAuc3R5bGUoe29wYWNpdHk6IG9wYWNpdHl9KVxuICAgICAgICAgICAgICAgIC5vbignbW91c2VvdmVyLm9wYWNpdHknLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5kdXJhdGlvbigxMDApXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAxKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5vbignbW91c2VvdXQub3BhY2l0eScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykudHJhbnNpdGlvbigpLmR1cmF0aW9uKDEwMDApXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZXRDb250ZW50ZWRpdGFibGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsbChzdmdUZXh0VXRpbHMubWFrZUVkaXRhYmxlLCB7Z2Q6IGdkfSlcbiAgICAgICAgICAgICAgICAub24oJ2VkaXQnLCBmdW5jdGlvbih0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGdkLmZyYW1ld29yayh7bGF5b3V0OiB7dGl0bGU6IHRleHR9fSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dCh0ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwodGl0bGVMYXlvdXQpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGwoc2V0Q29udGVudGVkaXRhYmxlKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5vbignY2FuY2VsJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0eHQgPSB0aGlzLmF0dHIoJ2RhdGEtdW5mb3JtYXR0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0KHR4dCkuY2FsbCh0aXRsZUxheW91dCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHRpdGxlLmNhbGwoc2V0Q29udGVudGVkaXRhYmxlKTtcbiAgICB9XG5cbiAgICBnZC5fY29udGV4dC5zZXRCYWNrZ3JvdW5kKGdkLCBnZC5fZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yKTtcbiAgICBQbG90cy5hZGRMaW5rcyhnZCk7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIGNvbnZlbmllbmNlIGZ1bmN0aW9uIHRvIGZvcmNlIGEgZnVsbCByZWRyYXcsIG1vc3RseSBmb3IgdXNlIGJ5IHBsb3RseS5qc1xuZXhwb3J0cy5yZWRyYXcgPSBmdW5jdGlvbihnZCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGlmKCFMaWIuaXNQbG90RGl2KGdkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgZWxlbWVudCBpcyBub3QgYSBQbG90bHkgcGxvdDogJyArIGdkKTtcbiAgICB9XG5cbiAgICBoZWxwZXJzLmNsZWFuRGF0YShnZC5kYXRhKTtcbiAgICBoZWxwZXJzLmNsZWFuTGF5b3V0KGdkLmxheW91dCk7XG5cbiAgICBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gZXhwb3J0cy5wbG90KGdkKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVkcmF3Jyk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogQ29udmVuaWVuY2UgZnVuY3Rpb24gdG8gbWFrZSBpZGVtcG90ZW50IHBsb3Qgb3B0aW9uIG9idmlvdXMgdG8gdXNlcnMuXG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0ge09iamVjdFtdfSBkYXRhXG4gKiBAcGFyYW0ge09iamVjdH0gbGF5b3V0XG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnXG4gKi9cbmV4cG9ydHMubmV3UGxvdCA9IGZ1bmN0aW9uKGdkLCBkYXRhLCBsYXlvdXQsIGNvbmZpZykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIC8vIHJlbW92ZSBnbCBjb250ZXh0c1xuICAgIFBsb3RzLmNsZWFuUGxvdChbXSwge30sIGdkLl9mdWxsRGF0YSB8fCBbXSwgZ2QuX2Z1bGxMYXlvdXQgfHwge30pO1xuXG4gICAgUGxvdHMucHVyZ2UoZ2QpO1xuICAgIHJldHVybiBleHBvcnRzLnBsb3QoZ2QsIGRhdGEsIGxheW91dCwgY29uZmlnKTtcbn07XG5cbi8qKlxuICogV3JhcCBuZWdhdGl2ZSBpbmRpY2llcyB0byB0aGVpciBwb3NpdGl2ZSBjb3VudGVycGFydHMuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJbXX0gaW5kaWNlcyBBbiBhcnJheSBvZiBpbmRpY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4SW5kZXggVGhlIG1heGltdW0gaW5kZXggYWxsb3dhYmxlIChhcnIubGVuZ3RoIC0gMSlcbiAqL1xuZnVuY3Rpb24gcG9zaXRpdmlmeUluZGljZXMoaW5kaWNlcywgbWF4SW5kZXgpIHtcbiAgICB2YXIgcGFyZW50TGVuZ3RoID0gbWF4SW5kZXggKyAxLFxuICAgICAgICBwb3NpdGl2ZUluZGljZXMgPSBbXSxcbiAgICAgICAgaSxcbiAgICAgICAgaW5kZXg7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgaWYoaW5kZXggPCAwKSB7XG4gICAgICAgICAgICBwb3NpdGl2ZUluZGljZXMucHVzaChwYXJlbnRMZW5ndGggKyBpbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb3NpdGl2ZUluZGljZXMucHVzaChpbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBvc2l0aXZlSW5kaWNlcztcbn1cblxuLyoqXG4gKiBFbnN1cmVzIHRoYXQgYW4gaW5kZXggYXJyYXkgZm9yIG1hbmlwdWxhdGluZyBnZC5kYXRhIGlzIHZhbGlkLlxuICpcbiAqIEludGVuZGVkIGZvciB1c2Ugd2l0aCBhZGRUcmFjZXMsIGRlbGV0ZVRyYWNlcywgYW5kIG1vdmVUcmFjZXMuXG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0gaW5kaWNlc1xuICogQHBhcmFtIGFycmF5TmFtZVxuICovXG5mdW5jdGlvbiBhc3NlcnRJbmRleEFycmF5KGdkLCBpbmRpY2VzLCBhcnJheU5hbWUpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgaW5kZXg7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGluZGV4ID0gaW5kaWNlc1tpXTtcblxuICAgICAgICAvLyB2YWxpZGF0ZSB0aGF0IGluZGljZXMgYXJlIGluZGVlZCBpbnRlZ2Vyc1xuICAgICAgICBpZihpbmRleCAhPT0gcGFyc2VJbnQoaW5kZXgsIDEwKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhbGwgdmFsdWVzIGluICcgKyBhcnJheU5hbWUgKyAnIG11c3QgYmUgaW50ZWdlcnMnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHRoYXQgYWxsIGluZGljZXMgYXJlIGluIGJvdW5kcyBmb3IgZ2l2ZW4gZ2QuZGF0YSBhcnJheSBsZW5ndGhcbiAgICAgICAgaWYoaW5kZXggPj0gZ2QuZGF0YS5sZW5ndGggfHwgaW5kZXggPCAtZ2QuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihhcnJheU5hbWUgKyAnIG11c3QgYmUgdmFsaWQgaW5kaWNlcyBmb3IgZ2QuZGF0YS4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHRoYXQgaW5kaWNlcyBhcmVuJ3QgcmVwZWF0ZWRcbiAgICAgICAgaWYoaW5kaWNlcy5pbmRleE9mKGluZGV4LCBpICsgMSkgPiAtMSB8fFxuICAgICAgICAgICAgICAgIGluZGV4ID49IDAgJiYgaW5kaWNlcy5pbmRleE9mKC1nZC5kYXRhLmxlbmd0aCArIGluZGV4KSA+IC0xIHx8XG4gICAgICAgICAgICAgICAgaW5kZXggPCAwICYmIGluZGljZXMuaW5kZXhPZihnZC5kYXRhLmxlbmd0aCArIGluZGV4KSA+IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VhY2ggaW5kZXggaW4gJyArIGFycmF5TmFtZSArICcgbXVzdCBiZSB1bmlxdWUuJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUHJpdmF0ZSBmdW5jdGlvbiB1c2VkIGJ5IFBsb3RseS5tb3ZlVHJhY2VzIHRvIGNoZWNrIGlucHV0IGFyZ3NcbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSBjdXJyZW50SW5kaWNlc1xuICogQHBhcmFtIG5ld0luZGljZXNcbiAqL1xuZnVuY3Rpb24gY2hlY2tNb3ZlVHJhY2VzQXJncyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpIHtcblxuICAgIC8vIGNoZWNrIHRoYXQgZ2QgaGFzIGF0dHJpYnV0ZSAnZGF0YScgYW5kICdkYXRhJyBpcyBhcnJheVxuICAgIGlmKCFBcnJheS5pc0FycmF5KGdkLmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2QuZGF0YSBtdXN0IGJlIGFuIGFycmF5LicpO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIGN1cnJlbnRJbmRpY2VzIGFycmF5XG4gICAgaWYodHlwZW9mIGN1cnJlbnRJbmRpY2VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRJbmRpY2VzIGlzIGEgcmVxdWlyZWQgYXJndW1lbnQuJyk7XG4gICAgfSBlbHNlIGlmKCFBcnJheS5pc0FycmF5KGN1cnJlbnRJbmRpY2VzKSkge1xuICAgICAgICBjdXJyZW50SW5kaWNlcyA9IFtjdXJyZW50SW5kaWNlc107XG4gICAgfVxuICAgIGFzc2VydEluZGV4QXJyYXkoZ2QsIGN1cnJlbnRJbmRpY2VzLCAnY3VycmVudEluZGljZXMnKTtcblxuICAgIC8vIHZhbGlkYXRlIG5ld0luZGljZXMgYXJyYXkgaWYgaXQgZXhpc3RzXG4gICAgaWYodHlwZW9mIG5ld0luZGljZXMgIT09ICd1bmRlZmluZWQnICYmICFBcnJheS5pc0FycmF5KG5ld0luZGljZXMpKSB7XG4gICAgICAgIG5ld0luZGljZXMgPSBbbmV3SW5kaWNlc107XG4gICAgfVxuICAgIGlmKHR5cGVvZiBuZXdJbmRpY2VzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBhc3NlcnRJbmRleEFycmF5KGdkLCBuZXdJbmRpY2VzLCAnbmV3SW5kaWNlcycpO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGN1cnJlbnRJbmRpY2VzIGFuZCBuZXdJbmRpY2VzIGFyZSB0aGUgc2FtZSBsZW5ndGggaWYgbmV3SWRpY2VzIGV4aXN0c1xuICAgIGlmKHR5cGVvZiBuZXdJbmRpY2VzICE9PSAndW5kZWZpbmVkJyAmJiBjdXJyZW50SW5kaWNlcy5sZW5ndGggIT09IG5ld0luZGljZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudCBhbmQgbmV3IGluZGljZXMgbXVzdCBiZSBvZiBlcXVhbCBsZW5ndGguJyk7XG4gICAgfVxuXG59XG4vKipcbiAqIEEgcHJpdmF0ZSBmdW5jdGlvbiB0byByZWR1Y2UgdGhlIHR5cGUgY2hlY2tpbmcgY2x1dHRlciBpbiBhZGRUcmFjZXMuXG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0gdHJhY2VzXG4gKiBAcGFyYW0gbmV3SW5kaWNlc1xuICovXG5mdW5jdGlvbiBjaGVja0FkZFRyYWNlc0FyZ3MoZ2QsIHRyYWNlcywgbmV3SW5kaWNlcykge1xuICAgIHZhciBpLCB2YWx1ZTtcblxuICAgIC8vIGNoZWNrIHRoYXQgZ2QgaGFzIGF0dHJpYnV0ZSAnZGF0YScgYW5kICdkYXRhJyBpcyBhcnJheVxuICAgIGlmKCFBcnJheS5pc0FycmF5KGdkLmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2QuZGF0YSBtdXN0IGJlIGFuIGFycmF5LicpO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB0cmFjZXMgZXhpc3RzXG4gICAgaWYodHlwZW9mIHRyYWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0cmFjZXMgbXVzdCBiZSBkZWZpbmVkLicpO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB0cmFjZXMgaXMgYW4gYXJyYXlcbiAgICBpZighQXJyYXkuaXNBcnJheSh0cmFjZXMpKSB7XG4gICAgICAgIHRyYWNlcyA9IFt0cmFjZXNdO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSBlYWNoIHZhbHVlIGluIHRyYWNlcyBpcyBhbiBvYmplY3RcbiAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFsdWUgPSB0cmFjZXNbaV07XG4gICAgICAgIGlmKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgfHwgKEFycmF5LmlzQXJyYXkodmFsdWUpIHx8IHZhbHVlID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhbGwgdmFsdWVzIGluIHRyYWNlcyBhcnJheSBtdXN0IGJlIG5vbi1hcnJheSBvYmplY3RzJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgd2UgaGF2ZSBhbiBpbmRleCBmb3IgZWFjaCB0cmFjZVxuICAgIGlmKHR5cGVvZiBuZXdJbmRpY2VzICE9PSAndW5kZWZpbmVkJyAmJiAhQXJyYXkuaXNBcnJheShuZXdJbmRpY2VzKSkge1xuICAgICAgICBuZXdJbmRpY2VzID0gW25ld0luZGljZXNdO1xuICAgIH1cbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyAhPT0gJ3VuZGVmaW5lZCcgJiYgbmV3SW5kaWNlcy5sZW5ndGggIT09IHRyYWNlcy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ2lmIGluZGljZXMgaXMgc3BlY2lmaWVkLCB0cmFjZXMubGVuZ3RoIG11c3QgZXF1YWwgaW5kaWNlcy5sZW5ndGgnXG4gICAgICAgICk7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgcHJpdmF0ZSBmdW5jdGlvbiB0byByZWR1Y2UgdGhlIHR5cGUgY2hlY2tpbmcgY2x1dHRlciBpbiBzcGxpY2VUcmFjZXMuXG4gKiBHZXQgYWxsIHVwZGF0ZSBQcm9wZXJ0aWVzIGZyb20gZ2QuZGF0YS4gVmFsaWRhdGUgaW5wdXRzIGFuZCBvdXRwdXRzLlxuICogVXNlZCBieSBwcmVwZW5kVHJhY2UgYW5kIGV4dGVuZFRyYWNlc1xuICpcbiAqIEBwYXJhbSBnZFxuICogQHBhcmFtIHVwZGF0ZVxuICogQHBhcmFtIGluZGljZXNcbiAqIEBwYXJhbSBtYXhQb2ludHNcbiAqL1xuZnVuY3Rpb24gYXNzZXJ0RXh0ZW5kVHJhY2VzQXJncyhnZCwgdXBkYXRlLCBpbmRpY2VzLCBtYXhQb2ludHMpIHtcblxuICAgIHZhciBtYXhQb2ludHNJc09iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0KG1heFBvaW50cyk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShnZC5kYXRhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dkLmRhdGEgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgIH1cbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QodXBkYXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VwZGF0ZSBtdXN0IGJlIGEga2V5OnZhbHVlIG9iamVjdCcpO1xuICAgIH1cblxuICAgIGlmKHR5cGVvZiBpbmRpY2VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luZGljZXMgbXVzdCBiZSBhbiBpbnRlZ2VyIG9yIGFycmF5IG9mIGludGVnZXJzJyk7XG4gICAgfVxuXG4gICAgYXNzZXJ0SW5kZXhBcnJheShnZCwgaW5kaWNlcywgJ2luZGljZXMnKTtcblxuICAgIGZvcih2YXIga2V5IGluIHVwZGF0ZSkge1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIFZlcmlmeSB0aGF0IHRoZSBhdHRyaWJ1dGUgdG8gYmUgdXBkYXRlZCBjb250YWlucyBhcyBtYW55IHRyYWNlIHVwZGF0ZXNcbiAgICAgICAgICogYXMgaW5kaWNlcy4gRmFpbHVyZSBtdXN0IHJlc3VsdCBpbiB0aHJvdyBhbmQgbm8tb3BcbiAgICAgICAgICovXG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KHVwZGF0ZVtrZXldKSB8fCB1cGRhdGVba2V5XS5sZW5ndGggIT09IGluZGljZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F0dHJpYnV0ZSAnICsga2V5ICsgJyBtdXN0IGJlIGFuIGFycmF5IG9mIGxlbmd0aCBlcXVhbCB0byBpbmRpY2VzIGFycmF5IGxlbmd0aCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLypcbiAgICAgICAgICogaWYgbWF4UG9pbnRzIGlzIGFuIG9iamVjdCBpdCBtdXN0IG1hdGNoIGtleXMgYW5kIGFycmF5IGxlbmd0aHMgb2YgJ3VwZGF0ZScgMToxXG4gICAgICAgICAqL1xuICAgICAgICBpZihtYXhQb2ludHNJc09iamVjdCAmJlxuICAgICAgICAgICAgKCEoa2V5IGluIG1heFBvaW50cykgfHwgIUFycmF5LmlzQXJyYXkobWF4UG9pbnRzW2tleV0pIHx8XG4gICAgICAgICAgICBtYXhQb2ludHNba2V5XS5sZW5ndGggIT09IHVwZGF0ZVtrZXldLmxlbmd0aCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignd2hlbiBtYXhQb2ludHMgaXMgc2V0IGFzIGEga2V5OnZhbHVlIG9iamVjdCBpdCBtdXN0IGNvbnRhaW4gYSAxOjEgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvcnJpc3BvbmRlbmNlIHdpdGggdGhlIGtleXMgYW5kIG51bWJlciBvZiB0cmFjZXMgaW4gdGhlIHVwZGF0ZSBvYmplY3QnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBBIHByaXZhdGUgZnVuY3Rpb24gdG8gcmVkdWNlIHRoZSB0eXBlIGNoZWNraW5nIGNsdXR0ZXIgaW4gc3BsaWNlVHJhY2VzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEhUTUxEaXZFbGVtZW50fSBnZFxuICogQHBhcmFtIHtPYmplY3R9IHVwZGF0ZVxuICogQHBhcmFtIHtOdW1iZXJbXX0gaW5kaWNlc1xuICogQHBhcmFtIHtOdW1iZXJ8fE9iamVjdH0gbWF4UG9pbnRzXG4gKiBAcmV0dXJuIHtPYmplY3RbXX1cbiAqL1xuZnVuY3Rpb24gZ2V0RXh0ZW5kUHJvcGVydGllcyhnZCwgdXBkYXRlLCBpbmRpY2VzLCBtYXhQb2ludHMpIHtcblxuICAgIHZhciBtYXhQb2ludHNJc09iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0KG1heFBvaW50cyksXG4gICAgICAgIHVwZGF0ZVByb3BzID0gW107XG4gICAgdmFyIHRyYWNlLCB0YXJnZXQsIHByb3AsIGluc2VydCwgbWF4cDtcblxuICAgIC8vIGFsbG93IHNjYWxhciBpbmRleCB0byByZXByZXNlbnQgYSBzaW5nbGUgdHJhY2UgcG9zaXRpb25cbiAgICBpZighQXJyYXkuaXNBcnJheShpbmRpY2VzKSkgaW5kaWNlcyA9IFtpbmRpY2VzXTtcblxuICAgIC8vIG5lZ2F0aXZlIGluZGljZXMgYXJlIHdyYXBwZWQgYXJvdW5kIHRvIHRoZWlyIHBvc2l0aXZlIHZhbHVlLiBFcXVpdmFsZW50IHRvIHB5dGhvbiBpbmRleGluZy5cbiAgICBpbmRpY2VzID0gcG9zaXRpdmlmeUluZGljZXMoaW5kaWNlcywgZ2QuZGF0YS5sZW5ndGggLSAxKTtcblxuICAgIC8vIGxvb3AgdGhyb3VnaCBhbGwgdXBkYXRlIGtleXMgYW5kIHRyYWNlcyBhbmQgaGFydmVzdCB2YWxpZGF0ZWQgZGF0YS5cbiAgICBmb3IodmFyIGtleSBpbiB1cGRhdGUpIHtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgaW5kaWNlcy5sZW5ndGg7IGorKykge1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogQ2hvb3NlIHRoZSB0cmFjZSBpbmRleGVkIGJ5IHRoZSBpbmRpY2VzIG1hcCBhcmd1bWVudCBhbmQgZ2V0IHRoZSBwcm9wIHNldHRlci1nZXR0ZXJcbiAgICAgICAgICAgICAqIGluc3RhbmNlIHRoYXQgcmVmZXJlbmNlcyB0aGUga2V5IGFuZCB2YWx1ZSBmb3IgdGhpcyBwYXJ0aWN1bGFyIHRyYWNlLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0cmFjZSA9IGdkLmRhdGFbaW5kaWNlc1tqXV07XG4gICAgICAgICAgICBwcm9wID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBrZXkpO1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogVGFyZ2V0IGlzIHRoZSBleGlzdGluZyBnZC5kYXRhLnRyYWNlLmRhdGFBcnJheSB2YWx1ZSBsaWtlIFwieFwiIG9yIFwibWFya2VyLnNpemVcIlxuICAgICAgICAgICAgICogVGFyZ2V0IG11c3QgZXhpc3QgYXMgYW4gQXJyYXkgdG8gYWxsb3cgdGhlIGV4dGVuZCBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0YXJnZXQgPSBwcm9wLmdldCgpO1xuICAgICAgICAgICAgaW5zZXJ0ID0gdXBkYXRlW2tleV1bal07XG5cbiAgICAgICAgICAgIGlmKCFMaWIuaXNBcnJheU9yVHlwZWRBcnJheShpbnNlcnQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhdHRyaWJ1dGU6ICcgKyBrZXkgKyAnIGluZGV4OiAnICsgaiArICcgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIUxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBleHRlbmQgbWlzc2luZyBvciBub24tYXJyYXkgYXR0cmlidXRlOiAnICsga2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHRhcmdldC5jb25zdHJ1Y3RvciAhPT0gaW5zZXJ0LmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgZXh0ZW5kIGFycmF5IHdpdGggYW4gYXJyYXkgb2YgYSBkaWZmZXJlbnQgdHlwZTogJyArIGtleSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBtYXhQb2ludHMgbWF5IGJlIGFuIG9iamVjdCBtYXAgb3IgYSBzY2FsYXIuIElmIG9iamVjdCBzZWxlY3QgdGhlIGtleTp2YWx1ZSwgZWxzZVxuICAgICAgICAgICAgICogVXNlIHRoZSBzY2FsYXIgbWF4UG9pbnRzIGZvciBhbGwga2V5IGFuZCB0cmFjZSBjb21iaW5hdGlvbnMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1heHAgPSBtYXhQb2ludHNJc09iamVjdCA/IG1heFBvaW50c1trZXldW2pdIDogbWF4UG9pbnRzO1xuXG4gICAgICAgICAgICAvLyBjb3VsZCBoYXZlIGNob3NlbiBudWxsIGhlcmUsIC0xIGp1c3QgdGVsbHMgdXMgdG8gbm90IHRha2UgYSB3aW5kb3dcbiAgICAgICAgICAgIGlmKCFpc051bWVyaWMobWF4cCkpIG1heHAgPSAtMTtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIFdyYXAgdGhlIG5lc3RlZFByb3BlcnR5IGluIGFuIG9iamVjdCBjb250YWluaW5nIHJlcXVpcmVkIGRhdGFcbiAgICAgICAgICAgICAqIGZvciBsZW5ndGhlbmluZyBhbmQgd2luZG93aW5nIHRoaXMgcGFydGljdWxhciB0cmFjZSAtIGtleSBjb21iaW5hdGlvbi5cbiAgICAgICAgICAgICAqIEZsb29yaW5nIG1heHAgbWlycm9ycyB0aGUgYmVoYXZpb3VyIG9mIGZsb2F0cyBpbiB0aGUgQXJyYXkuc2xpY2UgSlNuYXRpdmUgZnVuY3Rpb24uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVwZGF0ZVByb3BzLnB1c2goe1xuICAgICAgICAgICAgICAgIHByb3A6IHByb3AsXG4gICAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgICAgICAgICAgICAgaW5zZXJ0OiBpbnNlcnQsXG4gICAgICAgICAgICAgICAgbWF4cDogTWF0aC5mbG9vcihtYXhwKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhbGwgdGFyZ2V0IGFuZCBpbnNlcnRpb24gZGF0YSBub3cgdmFsaWRhdGVkXG4gICAgcmV0dXJuIHVwZGF0ZVByb3BzO1xufVxuXG4vKipcbiAqIEEgcHJpdmF0ZSBmdW5jdGlvbiB0byBrZXkgRXh0ZW5kIGFuZCBQcmVwZW5kIHRyYWNlcyBEUllcbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7T2JqZWN0fSB1cGRhdGVcbiAqIEBwYXJhbSB7TnVtYmVyW119IGluZGljZXNcbiAqIEBwYXJhbSB7TnVtYmVyfHxPYmplY3R9IG1heFBvaW50c1xuICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlQXJyYXlcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZnVuY3Rpb24gc3BsaWNlVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cywgdXBkYXRlQXJyYXkpIHtcbiAgICBhc3NlcnRFeHRlbmRUcmFjZXNBcmdzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cyk7XG5cbiAgICB2YXIgdXBkYXRlUHJvcHMgPSBnZXRFeHRlbmRQcm9wZXJ0aWVzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cyk7XG4gICAgdmFyIHVuZG9VcGRhdGUgPSB7fTtcbiAgICB2YXIgdW5kb1BvaW50cyA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHVwZGF0ZVByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwcm9wID0gdXBkYXRlUHJvcHNbaV0ucHJvcDtcbiAgICAgICAgdmFyIG1heHAgPSB1cGRhdGVQcm9wc1tpXS5tYXhwO1xuXG4gICAgICAgIC8vIHJldHVybiBuZXcgYXJyYXkgYW5kIHJlbWFpbmRlclxuICAgICAgICB2YXIgb3V0ID0gdXBkYXRlQXJyYXkodXBkYXRlUHJvcHNbaV0udGFyZ2V0LCB1cGRhdGVQcm9wc1tpXS5pbnNlcnQsIG1heHApO1xuICAgICAgICBwcm9wLnNldChvdXRbMF0pO1xuXG4gICAgICAgIC8vIGJ1aWxkIHRoZSBpbnZlcnNlIHVwZGF0ZSBvYmplY3QgZm9yIHRoZSB1bmRvIG9wZXJhdGlvblxuICAgICAgICBpZighQXJyYXkuaXNBcnJheSh1bmRvVXBkYXRlW3Byb3AuYXN0cl0pKSB1bmRvVXBkYXRlW3Byb3AuYXN0cl0gPSBbXTtcbiAgICAgICAgdW5kb1VwZGF0ZVtwcm9wLmFzdHJdLnB1c2gob3V0WzFdKTtcblxuICAgICAgICAgLy8gYnVpbGQgdGhlIG1hdGNoaW5nIG1heFBvaW50cyB1bmRvIG9iamVjdCBjb250YWluaW5nIG9yaWdpbmFsIHRyYWNlIGxlbmd0aHNcbiAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodW5kb1BvaW50c1twcm9wLmFzdHJdKSkgdW5kb1BvaW50c1twcm9wLmFzdHJdID0gW107XG4gICAgICAgIHVuZG9Qb2ludHNbcHJvcC5hc3RyXS5wdXNoKHVwZGF0ZVByb3BzW2ldLnRhcmdldC5sZW5ndGgpO1xuICAgIH1cblxuICAgIHJldHVybiB7dXBkYXRlOiB1bmRvVXBkYXRlLCBtYXhQb2ludHM6IHVuZG9Qb2ludHN9O1xufVxuXG5mdW5jdGlvbiBjb25jYXRUeXBlZEFycmF5KGFycjAsIGFycjEpIHtcbiAgICB2YXIgYXJyMiA9IG5ldyBhcnIwLmNvbnN0cnVjdG9yKGFycjAubGVuZ3RoICsgYXJyMS5sZW5ndGgpO1xuICAgIGFycjIuc2V0KGFycjApO1xuICAgIGFycjIuc2V0KGFycjEsIGFycjAubGVuZ3RoKTtcbiAgICByZXR1cm4gYXJyMjtcbn1cblxuLyoqXG4gKiBleHRlbmQgJiYgcHJlcGVuZCB0cmFjZXMgYXQgaW5kaWNlcyB3aXRoIHVwZGF0ZSBhcnJheXMsIHdpbmRvdyB0cmFjZSBsZW5ndGhzIHRvIG1heFBvaW50c1xuICpcbiAqIEV4dGVuZCBhbmQgUHJlcGVuZCBoYXZlIGlkZW50aWNhbCBBUElzLiBQcmVwZW5kIGluc2VydHMgYW4gYXJyYXkgYXQgdGhlIGhlYWQgd2hpbGUgRXh0ZW5kXG4gKiBpbnNlcnRzIGFuIGFycmF5IG9mZiB0aGUgdGFpbC4gUHJlcGVuZCB0cnVuY2F0ZXMgdGhlIHRhaWwgb2YgdGhlIGFycmF5IC0gY291bnRpbmcgbWF4UG9pbnRzXG4gKiBmcm9tIHRoZSBoZWFkLCB3aGVyZWFzIEV4dGVuZCB0cnVuY2F0ZXMgdGhlIGhlYWQgb2YgdGhlIGFycmF5LCBjb3VudGluZyBiYWNrd2FyZCBtYXhQb2ludHNcbiAqIGZyb20gdGhlIHRhaWwuXG4gKlxuICogSWYgbWF4UG9pbnRzIGlzIHVuZGVmaW5lZCwgbm9uTnVtZXJpYywgbmVnYXRpdmUgb3IgZ3JlYXRlciB0aGFuIGV4dGVuZGVkIHRyYWNlIGxlbmd0aCBub1xuICogdHJ1bmNhdGlvbiAvIHdpbmRvd2luZyB3aWxsIGJlIHBlcmZvcm1lZC4gSWYgaXRzIHplcm8sIHdlbGwgdGhlIHdob2xlIHRyYWNlIGlzIHRydW5jYXRlZC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2QgVGhlIGdyYXBoIGRpdlxuICogQHBhcmFtIHtPYmplY3R9IHVwZGF0ZSBUaGUga2V5OmFycmF5IG1hcCBvZiB0YXJnZXQgYXR0cmlidXRlcyB0byBleHRlbmRcbiAqIEBwYXJhbSB7TnVtYmVyfE51bWJlcltdfSBpbmRpY2VzIFRoZSBsb2NhdGlvbnMgb2YgdHJhY2VzIHRvIGJlIGV4dGVuZGVkXG4gKiBAcGFyYW0ge051bWJlcnxPYmplY3R9IFttYXhQb2ludHNdIE51bWJlciBvZiBwb2ludHMgZm9yIHRyYWNlIHdpbmRvdyBhZnRlciBsZW5ndGhlbmluZy5cbiAqXG4gKi9cbmV4cG9ydHMuZXh0ZW5kVHJhY2VzID0gZnVuY3Rpb24gZXh0ZW5kVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUFycmF5KHRhcmdldCwgaW5zZXJ0LCBtYXhwKSB7XG4gICAgICAgIHZhciBuZXdBcnJheSwgcmVtYWluZGVyO1xuXG4gICAgICAgIGlmKExpYi5pc1R5cGVkQXJyYXkodGFyZ2V0KSkge1xuICAgICAgICAgICAgaWYobWF4cCA8IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9uZSA9IG5ldyB0YXJnZXQuY29uc3RydWN0b3IoMCk7XG4gICAgICAgICAgICAgICAgdmFyIGJvdGggPSBjb25jYXRUeXBlZEFycmF5KHRhcmdldCwgaW5zZXJ0KTtcblxuICAgICAgICAgICAgICAgIGlmKG1heHAgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0FycmF5ID0gYm90aDtcbiAgICAgICAgICAgICAgICAgICAgcmVtYWluZGVyID0gbm9uZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheSA9IG5vbmU7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IGJvdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXdBcnJheSA9IG5ldyB0YXJnZXQuY29uc3RydWN0b3IobWF4cCk7XG4gICAgICAgICAgICAgICAgcmVtYWluZGVyID0gbmV3IHRhcmdldC5jb25zdHJ1Y3Rvcih0YXJnZXQubGVuZ3RoICsgaW5zZXJ0Lmxlbmd0aCAtIG1heHApO1xuXG4gICAgICAgICAgICAgICAgaWYobWF4cCA9PT0gaW5zZXJ0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheS5zZXQoaW5zZXJ0KTtcbiAgICAgICAgICAgICAgICAgICAgcmVtYWluZGVyLnNldCh0YXJnZXQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtYXhwIDwgaW5zZXJ0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyT2ZJdGVtc0Zyb21JbnNlcnQgPSBpbnNlcnQubGVuZ3RoIC0gbWF4cDtcblxuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheS5zZXQoaW5zZXJ0LnN1YmFycmF5KG51bWJlck9mSXRlbXNGcm9tSW5zZXJ0KSk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0KTtcbiAgICAgICAgICAgICAgICAgICAgcmVtYWluZGVyLnNldChpbnNlcnQuc3ViYXJyYXkoMCwgbnVtYmVyT2ZJdGVtc0Zyb21JbnNlcnQpLCB0YXJnZXQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyT2ZJdGVtc0Zyb21UYXJnZXQgPSBtYXhwIC0gaW5zZXJ0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhcmdldEJlZ2luID0gdGFyZ2V0Lmxlbmd0aCAtIG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0O1xuXG4gICAgICAgICAgICAgICAgICAgIG5ld0FycmF5LnNldCh0YXJnZXQuc3ViYXJyYXkodGFyZ2V0QmVnaW4pKTtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydCwgbnVtYmVyT2ZJdGVtc0Zyb21UYXJnZXQpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KHRhcmdldC5zdWJhcnJheSgwLCB0YXJnZXRCZWdpbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld0FycmF5ID0gdGFyZ2V0LmNvbmNhdChpbnNlcnQpO1xuICAgICAgICAgICAgcmVtYWluZGVyID0gKG1heHAgPj0gMCAmJiBtYXhwIDwgbmV3QXJyYXkubGVuZ3RoKSA/XG4gICAgICAgICAgICAgICAgbmV3QXJyYXkuc3BsaWNlKDAsIG5ld0FycmF5Lmxlbmd0aCAtIG1heHApIDpcbiAgICAgICAgICAgICAgICBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbbmV3QXJyYXksIHJlbWFpbmRlcl07XG4gICAgfVxuXG4gICAgdmFyIHVuZG8gPSBzcGxpY2VUcmFjZXMoZ2QsIHVwZGF0ZSwgaW5kaWNlcywgbWF4UG9pbnRzLCB1cGRhdGVBcnJheSk7XG4gICAgdmFyIHByb21pc2UgPSBleHBvcnRzLnJlZHJhdyhnZCk7XG4gICAgdmFyIHVuZG9BcmdzID0gW2dkLCB1bmRvLnVwZGF0ZSwgaW5kaWNlcywgdW5kby5tYXhQb2ludHNdO1xuICAgIFF1ZXVlLmFkZChnZCwgZXhwb3J0cy5wcmVwZW5kVHJhY2VzLCB1bmRvQXJncywgZXh0ZW5kVHJhY2VzLCBhcmd1bWVudHMpO1xuXG4gICAgcmV0dXJuIHByb21pc2U7XG59O1xuXG5leHBvcnRzLnByZXBlbmRUcmFjZXMgPSBmdW5jdGlvbiBwcmVwZW5kVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUFycmF5KHRhcmdldCwgaW5zZXJ0LCBtYXhwKSB7XG4gICAgICAgIHZhciBuZXdBcnJheSwgcmVtYWluZGVyO1xuXG4gICAgICAgIGlmKExpYi5pc1R5cGVkQXJyYXkodGFyZ2V0KSkge1xuICAgICAgICAgICAgaWYobWF4cCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vbmUgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKDApO1xuICAgICAgICAgICAgICAgIHZhciBib3RoID0gY29uY2F0VHlwZWRBcnJheShpbnNlcnQsIHRhcmdldCk7XG5cbiAgICAgICAgICAgICAgICBpZihtYXhwIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheSA9IGJvdGg7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5vbmU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBub25lO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIgPSBib3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKG1heHApO1xuICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5ldyB0YXJnZXQuY29uc3RydWN0b3IodGFyZ2V0Lmxlbmd0aCArIGluc2VydC5sZW5ndGggLSBtYXhwKTtcblxuICAgICAgICAgICAgICAgIGlmKG1heHAgPT09IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWF4cCA8IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlck9mSXRlbXNGcm9tSW5zZXJ0ID0gaW5zZXJ0Lmxlbmd0aCAtIG1heHA7XG5cbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydC5zdWJhcnJheSgwLCBudW1iZXJPZkl0ZW1zRnJvbUluc2VydCkpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KGluc2VydC5zdWJhcnJheShudW1iZXJPZkl0ZW1zRnJvbUluc2VydCkpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KHRhcmdldCwgbnVtYmVyT2ZJdGVtc0Zyb21JbnNlcnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBudW1iZXJPZkl0ZW1zRnJvbVRhcmdldCA9IG1heHAgLSBpbnNlcnQubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgICAgIG5ld0FycmF5LnNldChpbnNlcnQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheS5zZXQodGFyZ2V0LnN1YmFycmF5KDAsIG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0KSwgaW5zZXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0LnN1YmFycmF5KG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3QXJyYXkgPSBpbnNlcnQuY29uY2F0KHRhcmdldCk7XG4gICAgICAgICAgICByZW1haW5kZXIgPSAobWF4cCA+PSAwICYmIG1heHAgPCBuZXdBcnJheS5sZW5ndGgpID9cbiAgICAgICAgICAgICAgICBuZXdBcnJheS5zcGxpY2UobWF4cCwgbmV3QXJyYXkubGVuZ3RoKSA6XG4gICAgICAgICAgICAgICAgW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW25ld0FycmF5LCByZW1haW5kZXJdO1xuICAgIH1cblxuICAgIHZhciB1bmRvID0gc3BsaWNlVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cywgdXBkYXRlQXJyYXkpO1xuICAgIHZhciBwcm9taXNlID0gZXhwb3J0cy5yZWRyYXcoZ2QpO1xuICAgIHZhciB1bmRvQXJncyA9IFtnZCwgdW5kby51cGRhdGUsIGluZGljZXMsIHVuZG8ubWF4UG9pbnRzXTtcbiAgICBRdWV1ZS5hZGQoZ2QsIGV4cG9ydHMuZXh0ZW5kVHJhY2VzLCB1bmRvQXJncywgcHJlcGVuZFRyYWNlcywgYXJndW1lbnRzKTtcblxuICAgIHJldHVybiBwcm9taXNlO1xufTtcblxuLyoqXG4gKiBBZGQgZGF0YSB0cmFjZXMgdG8gYW4gZXhpc3RpbmcgZ3JhcGggZGl2LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEhUTUxEaXZFbGVtZW50fSBnZCBUaGUgZ3JhcGggZGl2XG4gKiBAcGFyYW0ge09iamVjdFtdfSBnZC5kYXRhIFRoZSBhcnJheSBvZiB0cmFjZXMgd2UncmUgYWRkaW5nIHRvXG4gKiBAcGFyYW0ge09iamVjdFtdfE9iamVjdH0gdHJhY2VzIFRoZSBvYmplY3Qgb3IgYXJyYXkgb2Ygb2JqZWN0cyB0byBhZGRcbiAqIEBwYXJhbSB7TnVtYmVyW118TnVtYmVyfSBbbmV3SW5kaWNlcz1bZ2QuZGF0YS5sZW5ndGhdXSBMb2NhdGlvbnMgdG8gYWRkIHRyYWNlc1xuICpcbiAqL1xuZXhwb3J0cy5hZGRUcmFjZXMgPSBmdW5jdGlvbiBhZGRUcmFjZXMoZ2QsIHRyYWNlcywgbmV3SW5kaWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIHZhciBjdXJyZW50SW5kaWNlcyA9IFtdLFxuICAgICAgICB1bmRvRnVuYyA9IGV4cG9ydHMuZGVsZXRlVHJhY2VzLFxuICAgICAgICByZWRvRnVuYyA9IGFkZFRyYWNlcyxcbiAgICAgICAgdW5kb0FyZ3MgPSBbZ2QsIGN1cnJlbnRJbmRpY2VzXSxcbiAgICAgICAgcmVkb0FyZ3MgPSBbZ2QsIHRyYWNlc10sICAvLyBubyBuZXdJbmRpY2VzIGhlcmVcbiAgICAgICAgaSxcbiAgICAgICAgcHJvbWlzZTtcblxuICAgIC8vIGFsbCB2YWxpZGF0aW9uIGlzIGRvbmUgZWxzZXdoZXJlIHRvIHJlbW92ZSBjbHV0dGVyIGhlcmVcbiAgICBjaGVja0FkZFRyYWNlc0FyZ3MoZ2QsIHRyYWNlcywgbmV3SW5kaWNlcyk7XG5cbiAgICAvLyBtYWtlIHN1cmUgdHJhY2VzIGlzIGFuIGFycmF5XG4gICAgaWYoIUFycmF5LmlzQXJyYXkodHJhY2VzKSkge1xuICAgICAgICB0cmFjZXMgPSBbdHJhY2VzXTtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgdHJhY2VzIGRvIG5vdCByZXBlYXQgZXhpc3Rpbmcgb25lc1xuICAgIHRyYWNlcyA9IHRyYWNlcy5tYXAoZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIExpYi5leHRlbmRGbGF0KHt9LCB0cmFjZSk7XG4gICAgfSk7XG5cbiAgICBoZWxwZXJzLmNsZWFuRGF0YSh0cmFjZXMpO1xuXG4gICAgLy8gYWRkIHRoZSB0cmFjZXMgdG8gZ2QuZGF0YSAobm8gcmVkcmF3aW5nIHlldCEpXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdkLmRhdGEucHVzaCh0cmFjZXNbaV0pO1xuICAgIH1cblxuICAgIC8vIHRvIGNvbnRpbnVlLCB3ZSBuZWVkIHRvIGNhbGwgbW92ZVRyYWNlcyB3aGljaCByZXF1aXJlcyBjdXJyZW50SW5kaWNlc1xuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjdXJyZW50SW5kaWNlcy5wdXNoKC10cmFjZXMubGVuZ3RoICsgaSk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlIHVzZXIgZGlkbid0IGRlZmluZSBuZXdJbmRpY2VzLCB0aGV5IGp1c3Qgd2FudCB0aGUgdHJhY2VzIGFwcGVuZGVkXG4gICAgLy8gaS5lLiwgd2UgY2FuIHNpbXBseSByZWRyYXcgYW5kIGJlIGRvbmVcbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcHJvbWlzZSA9IGV4cG9ydHMucmVkcmF3KGdkKTtcbiAgICAgICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSBpbmRpY2VzIGlzIHByb3BlcnR5IGRlZmluZWRcbiAgICBpZighQXJyYXkuaXNBcnJheShuZXdJbmRpY2VzKSkge1xuICAgICAgICBuZXdJbmRpY2VzID0gW25ld0luZGljZXNdO1xuICAgIH1cblxuICAgIHRyeSB7XG5cbiAgICAgICAgLy8gdGhpcyBpcyByZWR1bmRhbnQsIGJ1dCBuZWNlc3NhcnkgdG8gbm90IGNhdGNoIGxhdGVyIHBvc3NpYmxlIGVycm9ycyFcbiAgICAgICAgY2hlY2tNb3ZlVHJhY2VzQXJncyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpO1xuICAgIH1cbiAgICBjYXRjaChlcnJvcikge1xuXG4gICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nLCByZXNldCBnZCB0byBiZSBzYWZlIGFuZCByZXRocm93IGVycm9yXG4gICAgICAgIGdkLmRhdGEuc3BsaWNlKGdkLmRhdGEubGVuZ3RoIC0gdHJhY2VzLmxlbmd0aCwgdHJhY2VzLmxlbmd0aCk7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIC8vIGlmIHdlJ3JlIGhlcmUsIHRoZSB1c2VyIGhhcyBkZWZpbmVkIHNwZWNpZmljIHBsYWNlcyB0byBwbGFjZSB0aGUgbmV3IHRyYWNlc1xuICAgIC8vIHRoaXMgcmVxdWlyZXMgc29tZSBleHRyYSB3b3JrIHRoYXQgbW92ZVRyYWNlcyB3aWxsIGRvXG4gICAgUXVldWUuc3RhcnRTZXF1ZW5jZShnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG4gICAgcHJvbWlzZSA9IGV4cG9ydHMubW92ZVRyYWNlcyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpO1xuICAgIFF1ZXVlLnN0b3BTZXF1ZW5jZShnZCk7XG4gICAgcmV0dXJuIHByb21pc2U7XG59O1xuXG4vKipcbiAqIERlbGV0ZSB0cmFjZXMgYXQgYGluZGljZXNgIGZyb20gZ2QuZGF0YSBhcnJheS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2QgVGhlIGdyYXBoIGRpdlxuICogQHBhcmFtIHtPYmplY3RbXX0gZ2QuZGF0YSBUaGUgYXJyYXkgb2YgdHJhY2VzIHdlJ3JlIHJlbW92aW5nIGZyb21cbiAqIEBwYXJhbSB7TnVtYmVyfE51bWJlcltdfSBpbmRpY2VzIFRoZSBpbmRpY2VzXG4gKi9cbmV4cG9ydHMuZGVsZXRlVHJhY2VzID0gZnVuY3Rpb24gZGVsZXRlVHJhY2VzKGdkLCBpbmRpY2VzKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgdmFyIHRyYWNlcyA9IFtdLFxuICAgICAgICB1bmRvRnVuYyA9IGV4cG9ydHMuYWRkVHJhY2VzLFxuICAgICAgICByZWRvRnVuYyA9IGRlbGV0ZVRyYWNlcyxcbiAgICAgICAgdW5kb0FyZ3MgPSBbZ2QsIHRyYWNlcywgaW5kaWNlc10sXG4gICAgICAgIHJlZG9BcmdzID0gW2dkLCBpbmRpY2VzXSxcbiAgICAgICAgaSxcbiAgICAgICAgZGVsZXRlZFRyYWNlO1xuXG4gICAgLy8gbWFrZSBzdXJlIGluZGljZXMgYXJlIGRlZmluZWRcbiAgICBpZih0eXBlb2YgaW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbmRpY2VzIG11c3QgYmUgYW4gaW50ZWdlciBvciBhcnJheSBvZiBpbnRlZ2Vycy4nKTtcbiAgICB9IGVsc2UgaWYoIUFycmF5LmlzQXJyYXkoaW5kaWNlcykpIHtcbiAgICAgICAgaW5kaWNlcyA9IFtpbmRpY2VzXTtcbiAgICB9XG4gICAgYXNzZXJ0SW5kZXhBcnJheShnZCwgaW5kaWNlcywgJ2luZGljZXMnKTtcblxuICAgIC8vIGNvbnZlcnQgbmVnYXRpdmUgaW5kaWNlcyB0byBwb3NpdGl2ZSBpbmRpY2VzXG4gICAgaW5kaWNlcyA9IHBvc2l0aXZpZnlJbmRpY2VzKGluZGljZXMsIGdkLmRhdGEubGVuZ3RoIC0gMSk7XG5cbiAgICAvLyB3ZSB3YW50IGRlc2NlbmRpbmcgaGVyZSBzbyB0aGF0IHNwbGljaW5nIGxhdGVyIGRvZXNuJ3QgYWZmZWN0IGluZGV4aW5nXG4gICAgaW5kaWNlcy5zb3J0KExpYi5zb3J0ZXJEZXMpO1xuICAgIGZvcihpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgZGVsZXRlZFRyYWNlID0gZ2QuZGF0YS5zcGxpY2UoaW5kaWNlc1tpXSwgMSlbMF07XG4gICAgICAgIHRyYWNlcy5wdXNoKGRlbGV0ZWRUcmFjZSk7XG4gICAgfVxuXG4gICAgdmFyIHByb21pc2UgPSBleHBvcnRzLnJlZHJhdyhnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gcHJvbWlzZTtcbn07XG5cbi8qKlxuICogTW92ZSB0cmFjZXMgYXQgY3VycmVudEluZGljZXMgYXJyYXkgdG8gbG9jYXRpb25zIGluIG5ld0luZGljZXMgYXJyYXkuXG4gKlxuICogSWYgbmV3SW5kaWNlcyBpcyBvbWl0dGVkLCBjdXJyZW50SW5kaWNlcyB3aWxsIGJlIG1vdmVkIHRvIHRoZSBlbmQuIEUuZy4sXG4gKiB0aGVzZSBhcmUgZXF1aXZhbGVudDpcbiAqXG4gKiBQbG90bHkubW92ZVRyYWNlcyhnZCwgWzEsIDIsIDNdLCBbLTMsIC0yLCAtMV0pXG4gKiBQbG90bHkubW92ZVRyYWNlcyhnZCwgWzEsIDIsIDNdKVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEhUTUxEaXZFbGVtZW50fSBnZCBUaGUgZ3JhcGggZGl2XG4gKiBAcGFyYW0ge09iamVjdFtdfSBnZC5kYXRhIFRoZSBhcnJheSBvZiB0cmFjZXMgd2UncmUgcmVtb3ZpbmcgZnJvbVxuICogQHBhcmFtIHtOdW1iZXJ8TnVtYmVyW119IGN1cnJlbnRJbmRpY2VzIFRoZSBsb2NhdGlvbnMgb2YgdHJhY2VzIHRvIGJlIG1vdmVkXG4gKiBAcGFyYW0ge051bWJlcnxOdW1iZXJbXX0gW25ld0luZGljZXNdIFRoZSBsb2NhdGlvbnMgdG8gbW92ZSB0cmFjZXMgdG9cbiAqXG4gKiBFeGFtcGxlIGNhbGxzOlxuICpcbiAqICAgICAgLy8gbW92ZSB0cmFjZSBpIHRvIGxvY2F0aW9uIHhcbiAqICAgICAgUGxvdGx5Lm1vdmVUcmFjZXMoZ2QsIGksIHgpXG4gKlxuICogICAgICAvLyBtb3ZlIHRyYWNlIGkgdG8gZW5kIG9mIGFycmF5XG4gKiAgICAgIFBsb3RseS5tb3ZlVHJhY2VzKGdkLCBpKVxuICpcbiAqICAgICAgLy8gbW92ZSB0cmFjZXMgaSwgaiwgayB0byBlbmQgb2YgYXJyYXkgKGkgIT0gaiAhPSBrKVxuICogICAgICBQbG90bHkubW92ZVRyYWNlcyhnZCwgW2ksIGosIGtdKVxuICpcbiAqICAgICAgLy8gbW92ZSB0cmFjZXMgW2ksIGosIGtdIHRvIFt4LCB5LCB6XSAoaSAhPSBqICE9IGspICh4ICE9IHkgIT0geilcbiAqICAgICAgUGxvdGx5Lm1vdmVUcmFjZXMoZ2QsIFtpLCBqLCBrXSwgW3gsIHksIHpdKVxuICpcbiAqICAgICAgLy8gcmVvcmRlciBhbGwgdHJhY2VzIChhc3N1bWUgdGhlcmUgYXJlIDUtLWEsIGIsIGMsIGQsIGUpXG4gKiAgICAgIFBsb3RseS5tb3ZlVHJhY2VzKGdkLCBbYiwgZCwgZSwgYSwgY10pICAvLyBzYW1lIGFzICdtb3ZlIHRvIGVuZCdcbiAqL1xuZXhwb3J0cy5tb3ZlVHJhY2VzID0gZnVuY3Rpb24gbW92ZVRyYWNlcyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICB2YXIgbmV3RGF0YSA9IFtdLFxuICAgICAgICBtb3ZpbmdUcmFjZU1hcCA9IFtdLFxuICAgICAgICB1bmRvRnVuYyA9IG1vdmVUcmFjZXMsXG4gICAgICAgIHJlZG9GdW5jID0gbW92ZVRyYWNlcyxcbiAgICAgICAgdW5kb0FyZ3MgPSBbZ2QsIG5ld0luZGljZXMsIGN1cnJlbnRJbmRpY2VzXSxcbiAgICAgICAgcmVkb0FyZ3MgPSBbZ2QsIGN1cnJlbnRJbmRpY2VzLCBuZXdJbmRpY2VzXSxcbiAgICAgICAgaTtcblxuICAgIC8vIHRvIHJlZHVjZSBjb21wbGV4aXR5IGhlcmUsIGNoZWNrIGFyZ3MgZWxzZXdoZXJlXG4gICAgLy8gdGhpcyB0aHJvd3MgZXJyb3JzIHdoZXJlIGFwcHJvcHJpYXRlXG4gICAgY2hlY2tNb3ZlVHJhY2VzQXJncyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpO1xuXG4gICAgLy8gbWFrZSBzdXJlIGN1cnJlbnRJbmRpY2VzIGlzIGFuIGFycmF5XG4gICAgY3VycmVudEluZGljZXMgPSBBcnJheS5pc0FycmF5KGN1cnJlbnRJbmRpY2VzKSA/IGN1cnJlbnRJbmRpY2VzIDogW2N1cnJlbnRJbmRpY2VzXTtcblxuICAgIC8vIGlmIHVuZGVmaW5lZCwgZGVmaW5lIG5ld0luZGljZXMgdG8gcG9pbnQgdG8gdGhlIGVuZCBvZiBnZC5kYXRhIGFycmF5XG4gICAgaWYodHlwZW9mIG5ld0luZGljZXMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIG5ld0luZGljZXMgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY3VycmVudEluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5ld0luZGljZXMucHVzaCgtY3VycmVudEluZGljZXMubGVuZ3RoICsgaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgbmV3SW5kaWNlcyBpcyBhbiBhcnJheSBpZiBpdCdzIHVzZXItZGVmaW5lZFxuICAgIG5ld0luZGljZXMgPSBBcnJheS5pc0FycmF5KG5ld0luZGljZXMpID8gbmV3SW5kaWNlcyA6IFtuZXdJbmRpY2VzXTtcblxuICAgIC8vIGNvbnZlcnQgbmVnYXRpdmUgaW5kaWNlcyB0byBwb3NpdGl2ZSBpbmRpY2VzICh0aGV5J3JlIHRoZSBzYW1lIGxlbmd0aClcbiAgICBjdXJyZW50SW5kaWNlcyA9IHBvc2l0aXZpZnlJbmRpY2VzKGN1cnJlbnRJbmRpY2VzLCBnZC5kYXRhLmxlbmd0aCAtIDEpO1xuICAgIG5ld0luZGljZXMgPSBwb3NpdGl2aWZ5SW5kaWNlcyhuZXdJbmRpY2VzLCBnZC5kYXRhLmxlbmd0aCAtIDEpO1xuXG4gICAgLy8gYXQgdGhpcyBwb2ludCwgd2UndmUgY29lcmNlZCB0aGUgaW5kZXggYXJyYXlzIGludG8gcHJlZGljdGFibGUgZm9ybXNcblxuICAgIC8vIGdldCB0aGUgdHJhY2VzIHRoYXQgYXJlbid0IGJlaW5nIG1vdmVkIGFyb3VuZFxuICAgIGZvcihpID0gMDsgaSA8IGdkLmRhdGEubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAvLyBpZiBpbmRleCBpc24ndCBpbiBjdXJyZW50SW5kaWNlcywgaW5jbHVkZSBpdCBpbiBpZ25vcmVkIVxuICAgICAgICBpZihjdXJyZW50SW5kaWNlcy5pbmRleE9mKGkpID09PSAtMSkge1xuICAgICAgICAgICAgbmV3RGF0YS5wdXNoKGdkLmRhdGFbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZ2V0IGEgbWFwcGluZyBvZiBpbmRpY2VzIHRvIG1vdmluZyB0cmFjZXNcbiAgICBmb3IoaSA9IDA7IGkgPCBjdXJyZW50SW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtb3ZpbmdUcmFjZU1hcC5wdXNoKHtuZXdJbmRleDogbmV3SW5kaWNlc1tpXSwgdHJhY2U6IGdkLmRhdGFbY3VycmVudEluZGljZXNbaV1dfSk7XG4gICAgfVxuXG4gICAgLy8gcmVvcmRlciB0aGlzIG1hcHBpbmcgYnkgbmV3SW5kZXgsIGFzY2VuZGluZ1xuICAgIG1vdmluZ1RyYWNlTWFwLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYS5uZXdJbmRleCAtIGIubmV3SW5kZXg7XG4gICAgfSk7XG5cbiAgICAvLyBub3csIGFkZCB0aGUgbW92aW5nIHRyYWNlcyBiYWNrIGluLCBpbiBvcmRlciFcbiAgICBmb3IoaSA9IDA7IGkgPCBtb3ZpbmdUcmFjZU1hcC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBuZXdEYXRhLnNwbGljZShtb3ZpbmdUcmFjZU1hcFtpXS5uZXdJbmRleCwgMCwgbW92aW5nVHJhY2VNYXBbaV0udHJhY2UpO1xuICAgIH1cblxuICAgIGdkLmRhdGEgPSBuZXdEYXRhO1xuXG4gICAgdmFyIHByb21pc2UgPSBleHBvcnRzLnJlZHJhdyhnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gcHJvbWlzZTtcbn07XG5cbi8qKlxuICogcmVzdHlsZTogdXBkYXRlIHRyYWNlIGF0dHJpYnV0ZXMgb2YgYW4gZXhpc3RpbmcgcGxvdFxuICpcbiAqIENhbiBiZSBjYWxsZWQgdHdvIHdheXMuXG4gKlxuICogU2lnbmF0dXJlIDE6XG4gKiBAcGFyYW0ge1N0cmluZyB8IEhUTUxEaXZFbGVtZW50fSBnZFxuICogIHRoZSBpZCBvciBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHtTdHJpbmd9IGFzdHJcbiAqICBhdHRyaWJ1dGUgc3RyaW5nIChsaWtlIGAnbWFya2VyLnN5bWJvbCdgKSB0byB1cGRhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiAgdmFsdWUgdG8gZ2l2ZSB0aGlzIGF0dHJpYnV0ZVxuICogQHBhcmFtIHtOdW1iZXJbXSB8IE51bWJlcn0gW3RyYWNlc11cbiAqICBpbnRlZ2VyIG9yIGFycmF5IG9mIGludGVnZXJzIGZvciB0aGUgdHJhY2VzIHRvIGFsdGVyIChhbGwgaWYgb21pdHRlZClcbiAqXG4gKiBTaWduYXR1cmUgMjpcbiAqIEBwYXJhbSB7U3RyaW5nIHwgSFRNTERpdkVsZW1lbnR9IGdkXG4gKiAgKGFzIGluIHNpZ25hdHVyZSAxKVxuICogQHBhcmFtIHtPYmplY3R9IGFvYmpcbiAqICBhdHRyaWJ1dGUgb2JqZWN0IGB7YXN0cjE6IHZhbDEsIGFzdHIyOiB2YWwyIC4uLn1gXG4gKiAgYWxsb3dzIHNldHRpbmcgbXVsdGlwbGUgYXR0cmlidXRlcyBzaW11bHRhbmVvdXNseVxuICogQHBhcmFtIHtOdW1iZXJbXSB8IE51bWJlcn0gW3RyYWNlc11cbiAqICAoYXMgaW4gc2lnbmF0dXJlIDEpXG4gKlxuICogYHZhbGAgKG9yIGB2YWwxYCwgYHZhbDJgIC4uLiBpbiB0aGUgb2JqZWN0IGZvcm0pIGNhbiBiZSBhbiBhcnJheSxcbiAqIHRvIGFwcGx5IGRpZmZlcmVudCB2YWx1ZXMgdG8gZWFjaCB0cmFjZS5cbiAqXG4gKiBJZiB0aGUgYXJyYXkgaXMgdG9vIHNob3J0LCBpdCB3aWxsIHdyYXAgYXJvdW5kICh1c2VmdWwgZm9yXG4gKiBzdHlsZSBmaWxlcyB0aGF0IHdhbnQgdG8gc3BlY2lmeSBjeWNsaWNhbCBkZWZhdWx0IHZhbHVlcykuXG4gKi9cbmV4cG9ydHMucmVzdHlsZSA9IGZ1bmN0aW9uIHJlc3R5bGUoZ2QsIGFzdHIsIHZhbCwgX3RyYWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcbiAgICBoZWxwZXJzLmNsZWFyUHJvbWlzZVF1ZXVlKGdkKTtcblxuICAgIHZhciBhb2JqID0ge307XG4gICAgaWYodHlwZW9mIGFzdHIgPT09ICdzdHJpbmcnKSBhb2JqW2FzdHJdID0gdmFsO1xuICAgIGVsc2UgaWYoTGliLmlzUGxhaW5PYmplY3QoYXN0cikpIHtcbiAgICAgICAgLy8gdGhlIDMtYXJnIGZvcm1cbiAgICAgICAgYW9iaiA9IExpYi5leHRlbmRGbGF0KHt9LCBhc3RyKTtcbiAgICAgICAgaWYoX3RyYWNlcyA9PT0gdW5kZWZpbmVkKSBfdHJhY2VzID0gdmFsO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgTGliLndhcm4oJ1Jlc3R5bGUgZmFpbC4nLCBhc3RyLCB2YWwsIF90cmFjZXMpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcbiAgICB9XG5cbiAgICBpZihPYmplY3Qua2V5cyhhb2JqKS5sZW5ndGgpIGdkLmNoYW5nZWQgPSB0cnVlO1xuXG4gICAgdmFyIHRyYWNlcyA9IGhlbHBlcnMuY29lcmNlVHJhY2VJbmRpY2VzKGdkLCBfdHJhY2VzKTtcblxuICAgIHZhciBzcGVjcyA9IF9yZXN0eWxlKGdkLCBhb2JqLCB0cmFjZXMpO1xuICAgIHZhciBmbGFncyA9IHNwZWNzLmZsYWdzO1xuXG4gICAgLy8gY2xlYXIgY2FsY2RhdGEgYW5kL29yIGF4aXMgdHlwZXMgaWYgcmVxdWlyZWQgc28gdGhleSBnZXQgcmVnZW5lcmF0ZWRcbiAgICBpZihmbGFncy5jYWxjKSBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICBpZihmbGFncy5jbGVhckF4aXNUeXBlcykgaGVscGVycy5jbGVhckF4aXNUeXBlcyhnZCwgdHJhY2VzLCB7fSk7XG5cbiAgICAvLyBmaWxsIGluIHJlZHJhdyBzZXF1ZW5jZVxuICAgIHZhciBzZXEgPSBbXTtcblxuICAgIGlmKGZsYWdzLmZ1bGxSZXBsb3QpIHtcbiAgICAgICAgc2VxLnB1c2goZXhwb3J0cy5wbG90KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzZXEucHVzaChQbG90cy5wcmV2aW91c1Byb21pc2VzKTtcblxuICAgICAgICAvLyBtYXliZSBvbmx5IGNhbGwgUGxvdHMuc3VwcGx5RGF0YURlZmF1bHRzIGluIHRoZSBzcGxvbSBjYXNlLFxuICAgICAgICAvLyB0byBza2lwIG92ZXIgbG9uZyBhbmQgc2xvdyBheGVzIGRlZmF1bHRzXG4gICAgICAgIFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcblxuICAgICAgICBpZihmbGFncy5tYXJrZXJTaXplKSB7XG4gICAgICAgICAgICBQbG90cy5kb0NhbGNkYXRhKGdkKTtcbiAgICAgICAgICAgIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEpO1xuXG4gICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICAvLyBpZiBhbGwgYXhlcyBoYXZlIGF1dG9yYW5nZTpmYWxzZSwgdGhlblxuICAgICAgICAgICAgLy8gcHJvY2VlZCB0byBzdWJyb3V0aW5lcy5kb1RyYWNlU3R5bGUoKSxcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSB3ZSBtdXN0IGdvIHRocm91Z2ggYWRkQXhSYW5nZVNlcXVlbmNlLFxuICAgICAgICAgICAgLy8gd2hpY2ggaW4gZ2VuZXJhbCBtdXN0IHJlZHJhd3MgJ2FsbCcgYXhlc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZmxhZ3Muc3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvVHJhY2VTdHlsZSk7XG4gICAgICAgIGlmKGZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuXG4gICAgICAgIHNlcS5wdXNoKGVtaXRBZnRlclBsb3QpO1xuICAgIH1cblxuICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIpO1xuXG4gICAgUXVldWUuYWRkKGdkLFxuICAgICAgICByZXN0eWxlLCBbZ2QsIHNwZWNzLnVuZG9pdCwgc3BlY3MudHJhY2VzXSxcbiAgICAgICAgcmVzdHlsZSwgW2dkLCBzcGVjcy5yZWRvaXQsIHNwZWNzLnRyYWNlc11cbiAgICApO1xuXG4gICAgdmFyIHBsb3REb25lID0gTGliLnN5bmNPckFzeW5jKHNlcSwgZ2QpO1xuICAgIGlmKCFwbG90RG9uZSB8fCAhcGxvdERvbmUudGhlbikgcGxvdERvbmUgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgIHJldHVybiBwbG90RG9uZS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVzdHlsZScsIHNwZWNzLmV2ZW50RGF0YSk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn07XG5cbi8vIGZvciB1bmRvOiB1bmRlZmluZWQgaW5pdGlhbCB2YWxzIG11c3QgYmUgdHVybmVkIGludG8gbnVsbHNcbi8vIHNvIHRoYXQgd2UgdW5zZXQgcmF0aGVyIHRoYW4gaWdub3JlIHRoZW1cbmZ1bmN0aW9uIHVuZGVmaW5lZFRvTnVsbCh2YWwpIHtcbiAgICBpZih2YWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHZhbDtcbn1cblxuZnVuY3Rpb24gX3Jlc3R5bGUoZ2QsIGFvYmosIHRyYWNlcykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQsXG4gICAgICAgIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhLFxuICAgICAgICBkYXRhID0gZ2QuZGF0YSxcbiAgICAgICAgaTtcblxuICAgIC8vIGluaXRpYWxpemUgZmxhZ3NcbiAgICB2YXIgZmxhZ3MgPSBlZGl0VHlwZXMudHJhY2VGbGFncygpO1xuXG4gICAgLy8gY29waWVzIG9mIHRoZSBjaGFuZ2UgKGFuZCBwcmV2aW91cyB2YWx1ZXMgb2YgYW55dGhpbmcgYWZmZWN0ZWQpXG4gICAgLy8gZm9yIHRoZSB1bmRvIC8gcmVkbyBxdWV1ZVxuICAgIHZhciByZWRvaXQgPSB7fSxcbiAgICAgICAgdW5kb2l0ID0ge30sXG4gICAgICAgIGF4bGlzdDtcblxuICAgIC8vIG1ha2UgYSBuZXcgZW1wdHkgdmFscyBhcnJheSBmb3IgdW5kb2l0XG4gICAgZnVuY3Rpb24gYTAoKSB7IHJldHVybiB0cmFjZXMubWFwKGZ1bmN0aW9uKCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9KTsgfVxuXG4gICAgLy8gZm9yIGF1dG9yYW5naW5nIG11bHRpcGxlIGF4ZXNcbiAgICBmdW5jdGlvbiBhZGRUb0F4bGlzdChheGlkKSB7XG4gICAgICAgIHZhciBheE5hbWUgPSBBeGVzLmlkMm5hbWUoYXhpZCk7XG4gICAgICAgIGlmKGF4bGlzdC5pbmRleE9mKGF4TmFtZSkgPT09IC0xKSBheGxpc3QucHVzaChheE5hbWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGF1dG9yYW5nZUF0dHIoYXhOYW1lKSB7IHJldHVybiAnTEFZT1VUJyArIGF4TmFtZSArICcuYXV0b3JhbmdlJzsgfVxuXG4gICAgZnVuY3Rpb24gcmFuZ2VBdHRyKGF4TmFtZSkgeyByZXR1cm4gJ0xBWU9VVCcgKyBheE5hbWUgKyAnLnJhbmdlJzsgfVxuXG4gICAgLy8gZm9yIGF0dHJzIHRoYXQgaW50ZXJhY3QgKGxpa2Ugc2NhbGVzICYgYXV0b3NjYWxlcyksIHNhdmUgdGhlXG4gICAgLy8gb2xkIHZhbHMgYmVmb3JlIG1ha2luZyB0aGUgY2hhbmdlXG4gICAgLy8gdmFsPXVuZGVmaW5lZCB3aWxsIG5vdCBzZXQgYSB2YWx1ZSwganVzdCByZWNvcmQgd2hhdCB0aGUgdmFsdWUgd2FzLlxuICAgIC8vIHZhbD1udWxsIHdpbGwgZGVsZXRlIHRoZSBhdHRyaWJ1dGVcbiAgICAvLyBhdHRyIGNhbiBiZSBhbiBhcnJheSB0byBzZXQgc2V2ZXJhbCBhdCBvbmNlIChhbGwgdG8gdGhlIHNhbWUgdmFsKVxuICAgIGZ1bmN0aW9uIGRvZXh0cmEoYXR0ciwgdmFsLCBpKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0cikpIHtcbiAgICAgICAgICAgIGF0dHIuZm9yRWFjaChmdW5jdGlvbihhKSB7IGRvZXh0cmEoYSwgdmFsLCBpKTsgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcXVpdCBpZiBleHBsaWNpdGx5IHNldHRpbmcgdGhpcyBlbHNld2hlcmVcbiAgICAgICAgaWYoYXR0ciBpbiBhb2JqIHx8IGhlbHBlcnMuaGFzUGFyZW50KGFvYmosIGF0dHIpKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGV4dHJhcGFyYW07XG4gICAgICAgIGlmKGF0dHIuc3Vic3RyKDAsIDYpID09PSAnTEFZT1VUJykge1xuICAgICAgICAgICAgZXh0cmFwYXJhbSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShnZC5sYXlvdXQsIGF0dHIucmVwbGFjZSgnTEFZT1VUJywgJycpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4dHJhcGFyYW0gPSBMaWIubmVzdGVkUHJvcGVydHkoZGF0YVt0cmFjZXNbaV1dLCBhdHRyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCEoYXR0ciBpbiB1bmRvaXQpKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl0gPSBhMCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHVuZG9pdFthdHRyXVtpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl1baV0gPSB1bmRlZmluZWRUb051bGwoZXh0cmFwYXJhbS5nZXQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGV4dHJhcGFyYW0uc2V0KHZhbCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhbGxCaW5zKGJpbkF0dHIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGopIHtcbiAgICAgICAgICAgIHJldHVybiBmdWxsRGF0YVtqXVtiaW5BdHRyXTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcnJheUJpbnMoYmluQXR0cikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odmlqLCBqKSB7XG4gICAgICAgICAgICByZXR1cm4gdmlqID09PSBmYWxzZSA/IGZ1bGxEYXRhW3RyYWNlc1tqXV1bYmluQXR0cl0gOiBudWxsO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIG5vdyBtYWtlIHRoZSBjaGFuZ2VzIHRvIGdkLmRhdGEgKGFuZCBvY2Nhc2lvbmFsbHkgZ2QubGF5b3V0KVxuICAgIC8vIGFuZCBmaWd1cmUgb3V0IHdoYXQga2luZCBvZiBncmFwaGljcyB1cGRhdGUgd2UgbmVlZCB0byBkb1xuICAgIGZvcih2YXIgYWkgaW4gYW9iaikge1xuICAgICAgICBpZihoZWxwZXJzLmhhc1BhcmVudChhb2JqLCBhaSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IHNldCAnICsgYWkgKyAnYW5kIGEgcGFyZW50IGF0dHJpYnV0ZSBzaW11bHRhbmVvdXNseScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHZpID0gYW9ialthaV0sXG4gICAgICAgICAgICBjb250LFxuICAgICAgICAgICAgY29udEZ1bGwsXG4gICAgICAgICAgICBwYXJhbSxcbiAgICAgICAgICAgIG9sZFZhbCxcbiAgICAgICAgICAgIG5ld1ZhbCxcbiAgICAgICAgICAgIHZhbE9iamVjdDtcblxuICAgICAgICAvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5IHNoaW0gZm9yIHR1cm5pbmcgaGlzdG9ncmFtIGF1dG9iaW4gb24sXG4gICAgICAgIC8vIG9yIGZyZWV6aW5nIHByZXZpb3VzIGF1dG9iaW5uZWQgdmFsdWVzLlxuICAgICAgICAvLyBSZXBsYWNlIG9ic29sZXRlIGBhdXRvYmluKHh8eSk6IHRydWVgIHdpdGggYCh4fHkpYmluczogbnVsbGBcbiAgICAgICAgLy8gYW5kIGBhdXRvYmluKHh8eSk6IGZhbHNlYCB3aXRoIHRoZSBgKHh8eSliaW5zYCBpbiBgZnVsbERhdGFgXG4gICAgICAgIGlmKGFpID09PSAnYXV0b2JpbngnIHx8IGFpID09PSAnYXV0b2JpbnknKSB7XG4gICAgICAgICAgICBhaSA9IGFpLmNoYXJBdChhaS5sZW5ndGggLSAxKSArICdiaW5zJztcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodmkpKSB2aSA9IHZpLm1hcChhcnJheUJpbnMoYWkpKTtcbiAgICAgICAgICAgIGVsc2UgaWYodmkgPT09IGZhbHNlKSB2aSA9IHRyYWNlcy5tYXAoYWxsQmlucyhhaSkpO1xuICAgICAgICAgICAgZWxzZSB2aSA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZWRvaXRbYWldID0gdmk7XG5cbiAgICAgICAgaWYoYWkuc3Vic3RyKDAsIDYpID09PSAnTEFZT1VUJykge1xuICAgICAgICAgICAgcGFyYW0gPSBMaWIubmVzdGVkUHJvcGVydHkoZ2QubGF5b3V0LCBhaS5yZXBsYWNlKCdMQVlPVVQnLCAnJykpO1xuICAgICAgICAgICAgdW5kb2l0W2FpXSA9IFt1bmRlZmluZWRUb051bGwocGFyYW0uZ2V0KCkpXTtcbiAgICAgICAgICAgIC8vIHNpbmNlIHdlJ3JlIGFsbG93aW5nIHZhbCB0byBiZSBhbiBhcnJheSwgYWxsb3cgaXQgaGVyZSB0b28sXG4gICAgICAgICAgICAvLyBldmVuIHRob3VnaCB0aGF0J3MgbWVhbmluZ2xlc3NcbiAgICAgICAgICAgIHBhcmFtLnNldChBcnJheS5pc0FycmF5KHZpKSA/IHZpWzBdIDogdmkpO1xuICAgICAgICAgICAgLy8gaXJvbmljYWxseSwgdGhlIGxheW91dCBhdHRycyBpbiByZXN0eWxlIG9ubHkgcmVxdWlyZSByZXBsb3QsXG4gICAgICAgICAgICAvLyBub3QgcmVsYXlvdXRcbiAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzZXQgYXR0cmlidXRlIGluIGdkLmRhdGFcbiAgICAgICAgdW5kb2l0W2FpXSA9IGEwKCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udCA9IGRhdGFbdHJhY2VzW2ldXTtcbiAgICAgICAgICAgIGNvbnRGdWxsID0gZnVsbERhdGFbdHJhY2VzW2ldXTtcbiAgICAgICAgICAgIHBhcmFtID0gTGliLm5lc3RlZFByb3BlcnR5KGNvbnQsIGFpKTtcbiAgICAgICAgICAgIG9sZFZhbCA9IHBhcmFtLmdldCgpO1xuICAgICAgICAgICAgbmV3VmFsID0gQXJyYXkuaXNBcnJheSh2aSkgPyB2aVtpICUgdmkubGVuZ3RoXSA6IHZpO1xuXG4gICAgICAgICAgICBpZihuZXdWYWwgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgICAgICAgIHZhciBmaW5hbFBhcnQgPSBwYXJhbS5wYXJ0c1twYXJhbS5wYXJ0cy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIHZhciBwcmVmaXggPSBhaS5zdWJzdHIoMCwgYWkubGVuZ3RoIC0gZmluYWxQYXJ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgdmFyIHByZWZpeERvdCA9IHByZWZpeCA/IHByZWZpeCArICcuJyA6ICcnO1xuICAgICAgICAgICAgdmFyIGlubmVyQ29udEZ1bGwgPSBwcmVmaXggP1xuICAgICAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShjb250RnVsbCwgcHJlZml4KS5nZXQoKSA6IGNvbnRGdWxsO1xuXG4gICAgICAgICAgICB2YWxPYmplY3QgPSBQbG90U2NoZW1hLmdldFRyYWNlVmFsT2JqZWN0KGNvbnRGdWxsLCBwYXJhbS5wYXJ0cyk7XG5cbiAgICAgICAgICAgIGlmKHZhbE9iamVjdCAmJiB2YWxPYmplY3QuaW1wbGllZEVkaXRzICYmIG5ld1ZhbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaW1wbGllZEtleSBpbiB2YWxPYmplY3QuaW1wbGllZEVkaXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvZXh0cmEoTGliLnJlbGF0aXZlQXR0cihhaSwgaW1wbGllZEtleSksIHZhbE9iamVjdC5pbXBsaWVkRWRpdHNbaW1wbGllZEtleV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gY2hhbmdpbmcgY29sb3JiYXIgc2l6ZSBtb2RlcyxcbiAgICAgICAgICAgIC8vIG1ha2UgdGhlIHJlc3VsdGluZyBzaXplIG5vdCBjaGFuZ2VcbiAgICAgICAgICAgIC8vIG5vdGUgdGhhdCBjb2xvcmJhciBmcmFjdGlvbmFsIHNpemluZyBpcyBiYXNlZCBvbiB0aGVcbiAgICAgICAgICAgIC8vIG9yaWdpbmFsIHBsb3Qgc2l6ZSwgYmVmb3JlIGFueXRoaW5nIChsaWtlIGEgY29sb3JiYXIpXG4gICAgICAgICAgICAvLyBpbmNyZWFzZXMgdGhlIG1hcmdpbnNcbiAgICAgICAgICAgIGVsc2UgaWYoKGZpbmFsUGFydCA9PT0gJ3RoaWNrbmVzc21vZGUnIHx8IGZpbmFsUGFydCA9PT0gJ2xlbm1vZGUnKSAmJlxuICAgICAgICAgICAgICAgICAgICBvbGRWYWwgIT09IG5ld1ZhbCAmJlxuICAgICAgICAgICAgICAgICAgICAobmV3VmFsID09PSAnZnJhY3Rpb24nIHx8IG5ld1ZhbCA9PT0gJ3BpeGVscycpICYmXG4gICAgICAgICAgICAgICAgICAgIGlubmVyQ29udEZ1bGxcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgICAgICAgICAgICAgdmFyIG9yaWVudCA9IGlubmVyQ29udEZ1bGwub3JpZW50O1xuICAgICAgICAgICAgICAgIHZhciB0b3BPckJvdHRvbSA9IChvcmllbnQgPT09ICd0b3AnKSB8fCAob3JpZW50ID09PSAnYm90dG9tJyk7XG4gICAgICAgICAgICAgICAgaWYoZmluYWxQYXJ0ID09PSAndGhpY2tuZXNzbW9kZScpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRoaWNrbm9ybSA9IHRvcE9yQm90dG9tID8gZ3MuaCA6IGdzLnc7XG4gICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHJlZml4RG90ICsgJ3RoaWNrbmVzcycsIGlubmVyQ29udEZ1bGwudGhpY2tuZXNzICpcbiAgICAgICAgICAgICAgICAgICAgICAgIChuZXdWYWwgPT09ICdmcmFjdGlvbicgPyAxIC8gdGhpY2tub3JtIDogdGhpY2tub3JtKSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVubm9ybSA9IHRvcE9yQm90dG9tID8gZ3MudyA6IGdzLmg7XG4gICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHJlZml4RG90ICsgJ2xlbicsIGlubmVyQ29udEZ1bGwubGVuICpcbiAgICAgICAgICAgICAgICAgICAgICAgIChuZXdWYWwgPT09ICdmcmFjdGlvbicgPyAxIC8gbGVubm9ybSA6IGxlbm5vcm0pLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVsc2UgaWYoYWkgPT09ICd0eXBlJyAmJiAobmV3VmFsID09PSAncGllJykgIT09IChvbGRWYWwgPT09ICdwaWUnKSkge1xuICAgICAgICAgICAgICAgIHZhciBsYWJlbHNUbyA9ICd4JyxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzVG8gPSAneSc7XG4gICAgICAgICAgICAgICAgaWYoKG5ld1ZhbCA9PT0gJ2JhcicgfHwgb2xkVmFsID09PSAnYmFyJykgJiYgY29udC5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsc1RvID0gJ3knO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZXNUbyA9ICd4JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgTGliLnN3YXBBdHRycyhjb250LCBbJz8nLCAnP3NyYyddLCAnbGFiZWxzJywgbGFiZWxzVG8pO1xuICAgICAgICAgICAgICAgIExpYi5zd2FwQXR0cnMoY29udCwgWydkPycsICc/MCddLCAnbGFiZWwnLCBsYWJlbHNUbyk7XG4gICAgICAgICAgICAgICAgTGliLnN3YXBBdHRycyhjb250LCBbJz8nLCAnP3NyYyddLCAndmFsdWVzJywgdmFsdWVzVG8pO1xuXG4gICAgICAgICAgICAgICAgaWYob2xkVmFsID09PSAncGllJykge1xuICAgICAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29udCwgJ21hcmtlci5jb2xvcicpXG4gICAgICAgICAgICAgICAgICAgICAgICAuc2V0KExpYi5uZXN0ZWRQcm9wZXJ0eShjb250LCAnbWFya2VyLmNvbG9ycycpLmdldCgpKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBzdXBlciBrbHVkZ3kgLSBidXQgaWYgYWxsIHBpZXMgYXJlIGdvbmUgd2Ugd29uJ3QgcmVtb3ZlIHRoZW0gb3RoZXJ3aXNlXG4gICAgICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXQuX3BpZWxheWVyLnNlbGVjdEFsbCgnZy50cmFjZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihSZWdpc3RyeS50cmFjZUlzKGNvbnQsICdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29udCwgJ21hcmtlci5jb2xvcnMnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNldChMaWIubmVzdGVkUHJvcGVydHkoY29udCwgJ21hcmtlci5jb2xvcicpLmdldCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVuZG9pdFthaV1baV0gPSB1bmRlZmluZWRUb051bGwob2xkVmFsKTtcbiAgICAgICAgICAgIC8vIHNldCB0aGUgbmV3IHZhbHVlIC0gaWYgdmFsIGlzIGFuIGFycmF5LCBpdCdzIG9uZSBlbCBwZXIgdHJhY2VcbiAgICAgICAgICAgIC8vIGZpcnN0IGNoZWNrIGZvciBhdHRyaWJ1dGVzIHRoYXQgZ2V0IG1vcmUgY29tcGxleCBhbHRlcmF0aW9uc1xuICAgICAgICAgICAgdmFyIHN3YXBBdHRycyA9IFtcbiAgICAgICAgICAgICAgICAnc3dhcHh5JywgJ3N3YXB4eWF4ZXMnLCAnb3JpZW50YXRpb24nLCAnb3JpZW50YXRpb25heGVzJ1xuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmKHN3YXBBdHRycy5pbmRleE9mKGFpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBzZXR0aW5nIGFuIG9yaWVudGF0aW9uOiBtYWtlIHN1cmUgaXQncyBjaGFuZ2luZ1xuICAgICAgICAgICAgICAgIC8vIGJlZm9yZSB3ZSBzd2FwIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICAgICAgICAgIGlmKGFpID09PSAnb3JpZW50YXRpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtLnNldChuZXdWYWwpO1xuICAgICAgICAgICAgICAgICAgICAvLyBvYm5veGlvdXMgdGhhdCB3ZSBuZWVkIHRoaXMgbGV2ZWwgb2YgY291cGxpbmcuLi4gYnV0IGluIG9yZGVyIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIHByb3Blcmx5IGhhbmRsZSBzZXR0aW5nIG9yaWVudGF0aW9uIHRvIGBudWxsYCB3ZSBuZWVkIHRvIG1pbWljXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBsb2dpYyBpbnNpZGUgQmFycy5zdXBwbHlEZWZhdWx0cyBmb3IgZGVmYXVsdCBvcmllbnRhdGlvblxuICAgICAgICAgICAgICAgICAgICB2YXIgZGVmYXVsdE9yaWVudGF0aW9uID0gKGNvbnQueCAmJiAhY29udC55KSA/ICdoJyA6ICd2JztcbiAgICAgICAgICAgICAgICAgICAgaWYoKHBhcmFtLmdldCgpIHx8IGRlZmF1bHRPcmllbnRhdGlvbikgPT09IGNvbnRGdWxsLm9yaWVudGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBvcmllbnRhdGlvbmF4ZXMgaGFzIG5vIHZhbHVlLFxuICAgICAgICAgICAgICAgIC8vIGl0IGZsaXBzIGV2ZXJ5dGhpbmcgYW5kIHRoZSBheGVzXG4gICAgICAgICAgICAgICAgZWxzZSBpZihhaSA9PT0gJ29yaWVudGF0aW9uYXhlcycpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udC5vcmllbnRhdGlvbiA9XG4gICAgICAgICAgICAgICAgICAgICAgICB7djogJ2gnLCBoOiAndid9W2NvbnRGdWxsLm9yaWVudGF0aW9uXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGVscGVycy5zd2FwWFlEYXRhKGNvbnQpO1xuICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSBmbGFncy5jbGVhckF4aXNUeXBlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKFBsb3RzLmRhdGFBcnJheUNvbnRhaW5lcnMuaW5kZXhPZihwYXJhbS5wYXJ0c1swXSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogdXNlIG1hbmFnZUFycmF5cy5hcHBseUNvbnRhaW5lckFycmF5Q2hhbmdlcyBoZXJlIHRvb1xuICAgICAgICAgICAgICAgIGhlbHBlcnMubWFuYWdlQXJyYXlDb250YWluZXJzKHBhcmFtLCBuZXdWYWwsIHVuZG9pdCk7XG4gICAgICAgICAgICAgICAgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZih2YWxPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbXVzdCByZWRvIGNhbGNkYXRhIHdoZW4gcmVzdHlsaW5nIGFycmF5IHZhbHVlcyBvZiBhcnJheU9rIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gLi4uIGJ1dCBubyBuZWVkIHRvIHRoaXMgZm9yIHJlZ2wtYmFzZWQgdHJhY2VzXG4gICAgICAgICAgICAgICAgICAgIGlmKHZhbE9iamVjdC5hcnJheU9rICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAhUmVnaXN0cnkudHJhY2VJcyhjb250RnVsbCwgJ3JlZ2wnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG5ld1ZhbCkgfHwgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkob2xkVmFsKSlcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncy5jYWxjID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGVkaXRUeXBlcy51cGRhdGUoZmxhZ3MsIHZhbE9iamVjdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAgICAgKiBpZiB3ZSBjb3VsZG4ndCBmaW5kIHZhbE9iamVjdCwgIGFzc3VtZSBhIGZ1bGwgcmVjYWxjLlxuICAgICAgICAgICAgICAgICAgICAgKiBUaGlzIGNhbiBoYXBwZW4gaWYgeW91J3JlIGNoYW5naW5nIHR5cGUgYW5kIG1ha2luZ1xuICAgICAgICAgICAgICAgICAgICAgKiBzb21lIG90aGVyIGVkaXRzIHRvbywgc28gdGhlIG1vZHVsZXMgd2UncmVcbiAgICAgICAgICAgICAgICAgICAgICogbG9va2luZyBhdCBkb24ndCBoYXZlIHRoZXNlIGF0dHJpYnV0ZXMgaW4gdGhlbS5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGFsbCB0aGUgb3RoZXIgb25lcywganVzdCBtb2RpZnkgdGhhdCBvbmUgYXR0cmlidXRlXG4gICAgICAgICAgICAgICAgcGFyYW0uc2V0KG5ld1ZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzd2FwIHRoZSBkYXRhIGF0dHJpYnV0ZXMgb2YgdGhlIHJlbGV2YW50IHggYW5kIHkgYXhlcz9cbiAgICAgICAgaWYoWydzd2FweHlheGVzJywgJ29yaWVudGF0aW9uYXhlcyddLmluZGV4T2YoYWkpICE9PSAtMSkge1xuICAgICAgICAgICAgQXhlcy5zd2FwKGdkLCB0cmFjZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3dhcCBob3Zlcm1vZGUgaWYgc2V0IHRvIFwiY29tcGFyZSB4L3kgZGF0YVwiXG4gICAgICAgIGlmKGFpID09PSAnb3JpZW50YXRpb25heGVzJykge1xuICAgICAgICAgICAgdmFyIGhvdmVybW9kZSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShnZC5sYXlvdXQsICdob3Zlcm1vZGUnKTtcbiAgICAgICAgICAgIGlmKGhvdmVybW9kZS5nZXQoKSA9PT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgaG92ZXJtb2RlLnNldCgneScpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGhvdmVybW9kZS5nZXQoKSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgaG92ZXJtb2RlLnNldCgneCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFqb3IgZW5vdWdoIGNoYW5nZXMgZGVzZXJ2ZSBhdXRvc2NhbGUgYW5kXG4gICAgICAgIC8vIG5vbi1yZXZlcnNlZCBheGVzIHNvIHBlb3BsZSBkb24ndCBnZXQgY29uZnVzZWRcbiAgICAgICAgLy9cbiAgICAgICAgLy8gTm90ZTogYXV0b2JpbiAob3IgaXRzIG5ldyBhbmFsb2cgYmluIGNsZWFyaW5nKSBpcyBub3QgaW5jbHVkZWQgaGVyZVxuICAgICAgICAvLyBzaW5jZSB3ZSdyZSBub3QgcHVzaGluZyBiaW5zIGJhY2sgdG8gZ2QuZGF0YSwgc28gaWYgd2UgaGF2ZSBiaW5cbiAgICAgICAgLy8gaW5mbyBpdCB3YXMgZXhwbGljaXRseSBwcm92aWRlZCBieSB0aGUgdXNlci5cbiAgICAgICAgaWYoWydvcmllbnRhdGlvbicsICd0eXBlJ10uaW5kZXhPZihhaSkgIT09IC0xKSB7XG4gICAgICAgICAgICBheGxpc3QgPSBbXTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciB0cmFjZSA9IGRhdGFbdHJhY2VzW2ldXTtcblxuICAgICAgICAgICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICAgICAgICAgICAgICBhZGRUb0F4bGlzdCh0cmFjZS54YXhpcyB8fCAneCcpO1xuICAgICAgICAgICAgICAgICAgICBhZGRUb0F4bGlzdCh0cmFjZS55YXhpcyB8fCAneScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZG9leHRyYShheGxpc3QubWFwKGF1dG9yYW5nZUF0dHIpLCB0cnVlLCAwKTtcbiAgICAgICAgICAgIGRvZXh0cmEoYXhsaXN0Lm1hcChyYW5nZUF0dHIpLCBbMCwgMV0sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZmxhZ3MuY2FsYyB8fCBmbGFncy5wbG90KSB7XG4gICAgICAgIGZsYWdzLmZ1bGxSZXBsb3QgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGZsYWdzOiBmbGFncyxcbiAgICAgICAgdW5kb2l0OiB1bmRvaXQsXG4gICAgICAgIHJlZG9pdDogcmVkb2l0LFxuICAgICAgICB0cmFjZXM6IHRyYWNlcyxcbiAgICAgICAgZXZlbnREYXRhOiBMaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKFtdLCBbcmVkb2l0LCB0cmFjZXNdKVxuICAgIH07XG59XG5cbi8qKlxuICogcmVsYXlvdXQ6IHVwZGF0ZSBsYXlvdXQgYXR0cmlidXRlcyBvZiBhbiBleGlzdGluZyBwbG90XG4gKlxuICogQ2FuIGJlIGNhbGxlZCB0d28gd2F5czpcbiAqXG4gKiBTaWduYXR1cmUgMTpcbiAqIEBwYXJhbSB7U3RyaW5nIHwgSFRNTERpdkVsZW1lbnR9IGdkXG4gKiAgdGhlIGlkIG9yIGRvbSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKiBAcGFyYW0ge1N0cmluZ30gYXN0clxuICogIGF0dHJpYnV0ZSBzdHJpbmcgKGxpa2UgYCd4YXhpcy5yYW5nZVswXSdgKSB0byB1cGRhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiAgdmFsdWUgdG8gZ2l2ZSB0aGlzIGF0dHJpYnV0ZVxuICpcbiAqIFNpZ25hdHVyZSAyOlxuICogQHBhcmFtIHtTdHJpbmcgfCBIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICAoYXMgaW4gc2lnbmF0dXJlIDEpXG4gKiBAcGFyYW0ge09iamVjdH0gYW9ialxuICogIGF0dHJpYnV0ZSBvYmplY3QgYHthc3RyMTogdmFsMSwgYXN0cjI6IHZhbDIgLi4ufWBcbiAqICBhbGxvd3Mgc2V0dGluZyBtdWx0aXBsZSBhdHRyaWJ1dGVzIHNpbXVsdGFuZW91c2x5XG4gKi9cbmV4cG9ydHMucmVsYXlvdXQgPSBmdW5jdGlvbiByZWxheW91dChnZCwgYXN0ciwgdmFsKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuICAgIGhlbHBlcnMuY2xlYXJQcm9taXNlUXVldWUoZ2QpO1xuXG4gICAgaWYoZ2QuZnJhbWV3b3JrICYmIGdkLmZyYW1ld29yay5pc1BvbGFyKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZ2QpO1xuICAgIH1cblxuICAgIHZhciBhb2JqID0ge307XG4gICAgaWYodHlwZW9mIGFzdHIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFvYmpbYXN0cl0gPSB2YWw7XG4gICAgfSBlbHNlIGlmKExpYi5pc1BsYWluT2JqZWN0KGFzdHIpKSB7XG4gICAgICAgIGFvYmogPSBMaWIuZXh0ZW5kRmxhdCh7fSwgYXN0cik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgTGliLndhcm4oJ1JlbGF5b3V0IGZhaWwuJywgYXN0ciwgdmFsKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG4gICAgfVxuXG4gICAgaWYoT2JqZWN0LmtleXMoYW9iaikubGVuZ3RoKSBnZC5jaGFuZ2VkID0gdHJ1ZTtcblxuICAgIHZhciBzcGVjcyA9IF9yZWxheW91dChnZCwgYW9iaik7XG4gICAgdmFyIGZsYWdzID0gc3BlY3MuZmxhZ3M7XG5cbiAgICAvLyBjbGVhciBjYWxjZGF0YSBpZiByZXF1aXJlZFxuICAgIGlmKGZsYWdzLmNhbGMpIGdkLmNhbGNkYXRhID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gZmlsbCBpbiByZWRyYXcgc2VxdWVuY2VcblxuICAgIC8vIGV2ZW4gaWYgd2UgZG9uJ3QgaGF2ZSBhbnl0aGluZyBsZWZ0IGluIGFvYmosXG4gICAgLy8gc29tZXRoaW5nIG1heSBoYXZlIGhhcHBlbmVkIHdpdGhpbiByZWxheW91dCB0aGF0IHdlXG4gICAgLy8gbmVlZCB0byB3YWl0IGZvclxuICAgIHZhciBzZXEgPSBbUGxvdHMucHJldmlvdXNQcm9taXNlc107XG5cbiAgICBpZihmbGFncy5sYXlvdXRSZXBsb3QpIHtcbiAgICAgICAgc2VxLnB1c2goc3Vicm91dGluZXMubGF5b3V0UmVwbG90KTtcbiAgICB9XG4gICAgZWxzZSBpZihPYmplY3Qua2V5cyhhb2JqKS5sZW5ndGgpIHtcbiAgICAgICAgYXhSYW5nZVN1cHBseURlZmF1bHRzQnlQYXNzKGdkLCBmbGFncywgc3BlY3MpIHx8IFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcblxuICAgICAgICBpZihmbGFncy5sZWdlbmQpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvTGVnZW5kKTtcbiAgICAgICAgaWYoZmxhZ3MubGF5b3V0c3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgICAgIGlmKGZsYWdzLmF4cmFuZ2UpIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEsIHNwZWNzLnJhbmdlc0FsdGVyZWQpO1xuICAgICAgICBpZihmbGFncy50aWNrcykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UaWNrc1JlbGF5b3V0KTtcbiAgICAgICAgaWYoZmxhZ3MubW9kZWJhcikgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Nb2RlQmFyKTtcbiAgICAgICAgaWYoZmxhZ3MuY2FtZXJhKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0NhbWVyYSk7XG5cbiAgICAgICAgc2VxLnB1c2goZW1pdEFmdGVyUGxvdCk7XG4gICAgfVxuXG4gICAgc2VxLnB1c2goUGxvdHMucmVob3Zlcik7XG5cbiAgICBRdWV1ZS5hZGQoZ2QsXG4gICAgICAgIHJlbGF5b3V0LCBbZ2QsIHNwZWNzLnVuZG9pdF0sXG4gICAgICAgIHJlbGF5b3V0LCBbZ2QsIHNwZWNzLnJlZG9pdF1cbiAgICApO1xuXG4gICAgdmFyIHBsb3REb25lID0gTGliLnN5bmNPckFzeW5jKHNlcSwgZ2QpO1xuICAgIGlmKCFwbG90RG9uZSB8fCAhcGxvdERvbmUudGhlbikgcGxvdERvbmUgPSBQcm9taXNlLnJlc29sdmUoZ2QpO1xuXG4gICAgcmV0dXJuIHBsb3REb25lLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dCcsIHNwZWNzLmV2ZW50RGF0YSk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn07XG5cbi8vIE9wdGltaXphdGlvbiBtb3N0bHkgZm9yIGxhcmdlIHNwbG9tIHRyYWNlcyB3aGVyZVxuLy8gUGxvdHMuc3VwcGx5RGVmYXVsdHMgY2FuIHRha2UgPiAxMDBtc1xuZnVuY3Rpb24gYXhSYW5nZVN1cHBseURlZmF1bHRzQnlQYXNzKGdkLCBmbGFncywgc3BlY3MpIHtcbiAgICB2YXIgaztcblxuICAgIGlmKCFmbGFncy5heHJhbmdlKSByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IoayBpbiBmbGFncykge1xuICAgICAgICBpZihrICE9PSAnYXhyYW5nZScgJiYgZmxhZ3Nba10pIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IoayBpbiBzcGVjcy5yYW5nZXNBbHRlcmVkKSB7XG4gICAgICAgIHZhciBheE5hbWUgPSBBeGVzLmlkMm5hbWUoayk7XG4gICAgICAgIHZhciBheEluID0gZ2QubGF5b3V0W2F4TmFtZV07XG4gICAgICAgIHZhciBheE91dCA9IGdkLl9mdWxsTGF5b3V0W2F4TmFtZV07XG4gICAgICAgIGF4T3V0LmF1dG9yYW5nZSA9IGF4SW4uYXV0b3JhbmdlO1xuICAgICAgICBheE91dC5yYW5nZSA9IGF4SW4ucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgYXhPdXQuY2xlYW5SYW5nZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gYWRkQXhSYW5nZVNlcXVlbmNlKHNlcSwgcmFuZ2VzQWx0ZXJlZCkge1xuICAgIC8vIE4uQi4gbGVhdmUgYXMgc2VxdWVuY2Ugb2Ygc3Vicm91dGluZXMgKGZvciBub3cpIGluc3RlYWQgb2ZcbiAgICAvLyBzdWJyb3V0aW5lIG9mIGl0cyBvd24gc28gdGhhdCBmaW5hbERyYXcgYWx3YXlzIGdldHNcbiAgICAvLyBleGVjdXRlZCBhZnRlciBkcmF3RGF0YVxuICAgIHZhciBkb1RpY2tzID0gcmFuZ2VzQWx0ZXJlZCA/XG4gICAgICAgIGZ1bmN0aW9uKGdkKSB7IHJldHVybiBBeGVzLmRvVGlja3MoZ2QsIE9iamVjdC5rZXlzKHJhbmdlc0FsdGVyZWQpLCB0cnVlKTsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKGdkKSB7IHJldHVybiBBeGVzLmRvVGlja3MoZ2QsICdyZWRyYXcnKTsgfTtcblxuICAgIHNlcS5wdXNoKFxuICAgICAgICBzdWJyb3V0aW5lcy5kb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzLFxuICAgICAgICBkb1RpY2tzLFxuICAgICAgICBzdWJyb3V0aW5lcy5kcmF3RGF0YSxcbiAgICAgICAgc3Vicm91dGluZXMuZmluYWxEcmF3XG4gICAgKTtcbn1cblxudmFyIEFYX1JBTkdFX1JFID0gL15beHl6XWF4aXNbMC05XSpcXC5yYW5nZShcXFtbMHwxXVxcXSk/JC87XG52YXIgQVhfQVVUT1JBTkdFX1JFID0gL15beHl6XWF4aXNbMC05XSpcXC5hdXRvcmFuZ2UkLztcbnZhciBBWF9ET01BSU5fUkUgPSAvXlt4eXpdYXhpc1swLTldKlxcLmRvbWFpbihcXFtbMHwxXVxcXSk/JC87XG5cbmZ1bmN0aW9uIF9yZWxheW91dChnZCwgYW9iaikge1xuICAgIHZhciBsYXlvdXQgPSBnZC5sYXlvdXQsXG4gICAgICAgIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCxcbiAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzKGFvYmopLFxuICAgICAgICBheGVzID0gQXhlcy5saXN0KGdkKSxcbiAgICAgICAgYXJyYXlFZGl0cyA9IHt9LFxuICAgICAgICBhcnJheVN0cixcbiAgICAgICAgaSxcbiAgICAgICAgajtcblxuICAgIC8vIGxvb2sgZm9yICdhbGxheGVzJywgc3BsaXQgb3V0IGludG8gYWxsIGF4ZXNcbiAgICAvLyBpbiBjYXNlIG9mIDNEIHRoZSBheGlzIGFyZSBuZXN0ZWQgd2l0aGluIGEgc2NlbmUgd2hpY2ggaXMgaGVsZCBpbiBfaWRcbiAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGtleXNbaV0uaW5kZXhPZignYWxsYXhlcycpID09PSAwKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBheGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjZW5lID0gYXhlc1tqXS5faWQuc3Vic3RyKDEpLFxuICAgICAgICAgICAgICAgICAgICBheGlzQXR0ciA9IChzY2VuZS5pbmRleE9mKCdzY2VuZScpICE9PSAtMSkgPyAoc2NlbmUgKyAnLicpIDogJycsXG4gICAgICAgICAgICAgICAgICAgIG5ld2tleSA9IGtleXNbaV0ucmVwbGFjZSgnYWxsYXhlcycsIGF4aXNBdHRyICsgYXhlc1tqXS5fbmFtZSk7XG5cbiAgICAgICAgICAgICAgICBpZighYW9ialtuZXdrZXldKSBhb2JqW25ld2tleV0gPSBhb2JqW2tleXNbaV1dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZWxldGUgYW9ialtrZXlzW2ldXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGluaXRpYWxpemUgZmxhZ3NcbiAgICB2YXIgZmxhZ3MgPSBlZGl0VHlwZXMubGF5b3V0RmxhZ3MoKTtcblxuICAgIC8vIGNvcGllcyBvZiB0aGUgY2hhbmdlIChhbmQgcHJldmlvdXMgdmFsdWVzIG9mIGFueXRoaW5nIGFmZmVjdGVkKVxuICAgIC8vIGZvciB0aGUgdW5kbyAvIHJlZG8gcXVldWVcbiAgICB2YXIgcmVkb2l0ID0ge30sXG4gICAgICAgIHVuZG9pdCA9IHt9O1xuXG4gICAgLy8gZm9yIGF0dHJzIHRoYXQgaW50ZXJhY3QgKGxpa2Ugc2NhbGVzICYgYXV0b3NjYWxlcyksIHNhdmUgdGhlXG4gICAgLy8gb2xkIHZhbHMgYmVmb3JlIG1ha2luZyB0aGUgY2hhbmdlXG4gICAgLy8gdmFsPXVuZGVmaW5lZCB3aWxsIG5vdCBzZXQgYSB2YWx1ZSwganVzdCByZWNvcmQgd2hhdCB0aGUgdmFsdWUgd2FzLlxuICAgIC8vIGF0dHIgY2FuIGJlIGFuIGFycmF5IHRvIHNldCBzZXZlcmFsIGF0IG9uY2UgKGFsbCB0byB0aGUgc2FtZSB2YWwpXG4gICAgZnVuY3Rpb24gZG9leHRyYShhdHRyLCB2YWwpIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShhdHRyKSkge1xuICAgICAgICAgICAgYXR0ci5mb3JFYWNoKGZ1bmN0aW9uKGEpIHsgZG9leHRyYShhLCB2YWwpOyB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIHdlIGhhdmUgYW5vdGhlciB2YWx1ZSBmb3IgdGhpcyBhdHRyaWJ1dGUgKGV4cGxpY2l0bHkgb3JcbiAgICAgICAgLy8gdmlhIGEgcGFyZW50KSBkbyBub3Qgb3ZlcnJpZGUgd2l0aCB0aGlzIGF1dG8tZ2VuZXJhdGVkIGV4dHJhXG4gICAgICAgIGlmKGF0dHIgaW4gYW9iaiB8fCBoZWxwZXJzLmhhc1BhcmVudChhb2JqLCBhdHRyKSkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBwID0gTGliLm5lc3RlZFByb3BlcnR5KGxheW91dCwgYXR0cik7XG4gICAgICAgIGlmKCEoYXR0ciBpbiB1bmRvaXQpKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl0gPSB1bmRlZmluZWRUb051bGwocC5nZXQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQpIHAuc2V0KHZhbCk7XG4gICAgfVxuXG4gICAgLy8gZm9yIGNvbnN0cmFpbnQgZW5mb3JjZW1lbnQ6IGtlZXAgdHJhY2sgb2YgYWxsIGF4ZXMgKGFzIHtpZDogbmFtZX0pXG4gICAgLy8gd2UncmUgZWRpdGluZyB0aGUgKGF1dG8pcmFuZ2Ugb2YsIHNvIHdlIGNhbiB0ZWxsIHRoZSBvdGhlcnMgY29uc3RyYWluZWRcbiAgICAvLyB0byBzY2FsZSB3aXRoIHRoZW0gdGhhdCBpdCdzIE9LIGZvciB0aGVtIHRvIHNocmlua1xuICAgIHZhciByYW5nZXNBbHRlcmVkID0ge307XG4gICAgdmFyIGF4SWQ7XG5cbiAgICBmdW5jdGlvbiByZWNvcmRBbHRlcmVkQXhpcyhwbGVhZlBsdXMpIHtcbiAgICAgICAgdmFyIGF4SWQgPSBBeGVzLm5hbWUyaWQocGxlYWZQbHVzLnNwbGl0KCcuJylbMF0pO1xuICAgICAgICByYW5nZXNBbHRlcmVkW2F4SWRdID0gMTtcbiAgICAgICAgcmV0dXJuIGF4SWQ7XG4gICAgfVxuXG4gICAgLy8gYWx0ZXIgZ2QubGF5b3V0XG4gICAgZm9yKHZhciBhaSBpbiBhb2JqKSB7XG4gICAgICAgIGlmKGhlbHBlcnMuaGFzUGFyZW50KGFvYmosIGFpKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3Qgc2V0ICcgKyBhaSArICdhbmQgYSBwYXJlbnQgYXR0cmlidXRlIHNpbXVsdGFuZW91c2x5Jyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShsYXlvdXQsIGFpKTtcbiAgICAgICAgdmFyIHZpID0gYW9ialthaV07XG4gICAgICAgIHZhciBwbGVuID0gcC5wYXJ0cy5sZW5ndGg7XG4gICAgICAgIC8vIHAucGFydHMgbWF5IGVuZCB3aXRoIGFuIGluZGV4IGludGVnZXIgaWYgdGhlIHByb3BlcnR5IGlzIGFuIGFycmF5XG4gICAgICAgIHZhciBwZW5kID0gcGxlbiAtIDE7XG4gICAgICAgIHdoaWxlKHBlbmQgPiAwICYmIHR5cGVvZiBwLnBhcnRzW3BlbmRdICE9PSAnc3RyaW5nJykgcGVuZC0tO1xuICAgICAgICAvLyBsYXN0IHByb3BlcnR5IGluIGNoYWluIChsZWFmIG5vZGUpXG4gICAgICAgIHZhciBwbGVhZiA9IHAucGFydHNbcGVuZF07XG4gICAgICAgIC8vIGxlYWYgcGx1cyBpbW1lZGlhdGUgcGFyZW50XG4gICAgICAgIHZhciBwbGVhZlBsdXMgPSBwLnBhcnRzW3BlbmQgLSAxXSArICcuJyArIHBsZWFmO1xuICAgICAgICAvLyB0cnVuayBub2RlcyAoZXZlcnl0aGluZyBleGNlcHQgdGhlIGxlYWYpXG4gICAgICAgIHZhciBwdHJ1bmsgPSBwLnBhcnRzLnNsaWNlKDAsIHBlbmQpLmpvaW4oJy4nKTtcbiAgICAgICAgdmFyIHBhcmVudEluID0gTGliLm5lc3RlZFByb3BlcnR5KGdkLmxheW91dCwgcHRydW5rKS5nZXQoKTtcbiAgICAgICAgdmFyIHBhcmVudEZ1bGwgPSBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rKS5nZXQoKTtcbiAgICAgICAgdmFyIHZPbGQgPSBwLmdldCgpO1xuXG4gICAgICAgIGlmKHZpID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuXG4gICAgICAgIHJlZG9pdFthaV0gPSB2aTtcblxuICAgICAgICAvLyBheGlzIHJldmVyc2UgaXMgc3BlY2lhbCAtIGl0IGlzIGl0cyBvd24gaW52ZXJzZVxuICAgICAgICAvLyBvcCBhbmQgaGFzIG5vIGZsYWcuXG4gICAgICAgIHVuZG9pdFthaV0gPSAocGxlYWYgPT09ICdyZXZlcnNlJykgPyB2aSA6IHVuZGVmaW5lZFRvTnVsbCh2T2xkKTtcblxuICAgICAgICB2YXIgdmFsT2JqZWN0ID0gUGxvdFNjaGVtYS5nZXRMYXlvdXRWYWxPYmplY3QoZnVsbExheW91dCwgcC5wYXJ0cyk7XG5cbiAgICAgICAgaWYodmFsT2JqZWN0ICYmIHZhbE9iamVjdC5pbXBsaWVkRWRpdHMgJiYgdmkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaW1wbGllZEtleSBpbiB2YWxPYmplY3QuaW1wbGllZEVkaXRzKSB7XG4gICAgICAgICAgICAgICAgZG9leHRyYShMaWIucmVsYXRpdmVBdHRyKGFpLCBpbXBsaWVkS2V5KSwgdmFsT2JqZWN0LmltcGxpZWRFZGl0c1tpbXBsaWVkS2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXR0aW5nIHdpZHRoIG9yIGhlaWdodCB0byBudWxsIG11c3QgcmVzZXQgdGhlIGdyYXBoJ3Mgd2lkdGggLyBoZWlnaHRcbiAgICAgICAgLy8gYmFjayB0byBpdHMgaW5pdGlhbCB2YWx1ZSBhcyBjb21wdXRlZCBkdXJpbmcgdGhlIGZpcnN0IHBhc3MgaW4gUGxvdHMucGxvdEF1dG9TaXplLlxuICAgICAgICAvL1xuICAgICAgICAvLyBUbyBkbyBzbywgd2UgbXVzdCBtYW51YWxseSBzZXQgdGhlbSBiYWNrIGhlcmUgdXNpbmcgdGhlIF9pbml0aWFsQXV0b1NpemUgY2FjaGUuXG4gICAgICAgIC8vIGNhbid0IHVzZSBpbXBsaWVkRWRpdHMgZm9yIHRoaXMgYmVjYXVzZSBiZWhhdmlvciBkZXBlbmRzIG9uIHZpXG4gICAgICAgIGlmKFsnd2lkdGgnLCAnaGVpZ2h0J10uaW5kZXhPZihhaSkgIT09IC0xKSB7XG4gICAgICAgICAgICBpZih2aSkge1xuICAgICAgICAgICAgICAgIGRvZXh0cmEoJ2F1dG9zaXplJywgbnVsbCk7XG4gICAgICAgICAgICAgICAgLy8gY3VycmVudGx5IHdlIGRvbid0IHN1cHBvcnQgYXV0b3NpemUgb25lIGRpbSBvbmx5IC0gc29cbiAgICAgICAgICAgICAgICAvLyBleHBsaWNpdGx5IHNldCB0aGUgb3RoZXIgb25lLiBOb3RlIHRoYXQgZG9leHRyYSB3aWxsXG4gICAgICAgICAgICAgICAgLy8gaWdub3JlIHRoaXMgaWYgdGhlIHNhbWUgcmVsYXlvdXQgY2FsbCBhbHNvIHByb3ZpZGVzIG9wcG9zaXRlQXR0clxuICAgICAgICAgICAgICAgIHZhciBvcHBvc2l0ZUF0dHIgPSBhaSA9PT0gJ2hlaWdodCcgPyAnd2lkdGgnIDogJ2hlaWdodCc7XG4gICAgICAgICAgICAgICAgZG9leHRyYShvcHBvc2l0ZUF0dHIsIGZ1bGxMYXlvdXRbb3Bwb3NpdGVBdHRyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0W2FpXSA9IGdkLl9pbml0aWFsQXV0b1NpemVbYWldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoYWkgPT09ICdhdXRvc2l6ZScpIHtcbiAgICAgICAgICAgIC8vIGRlcGVuZHMgb24gdmkgaGVyZSB0b28sIHNvIGFnYWluIGNhbid0IHVzZSBpbXBsaWVkRWRpdHNcbiAgICAgICAgICAgIGRvZXh0cmEoJ3dpZHRoJywgdmkgPyBudWxsIDogZnVsbExheW91dC53aWR0aCk7XG4gICAgICAgICAgICBkb2V4dHJhKCdoZWlnaHQnLCB2aSA/IG51bGwgOiBmdWxsTGF5b3V0LmhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2hlY2sgYXV0b3JhbmdlIHZzIHJhbmdlXG4gICAgICAgIGVsc2UgaWYocGxlYWZQbHVzLm1hdGNoKEFYX1JBTkdFX1JFKSkge1xuICAgICAgICAgICAgcmVjb3JkQWx0ZXJlZEF4aXMocGxlYWZQbHVzKTtcbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShmdWxsTGF5b3V0LCBwdHJ1bmsgKyAnLl9pbnB1dFJhbmdlJykuc2V0KG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocGxlYWZQbHVzLm1hdGNoKEFYX0FVVE9SQU5HRV9SRSkpIHtcbiAgICAgICAgICAgIHJlY29yZEFsdGVyZWRBeGlzKHBsZWFmUGx1cyk7XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rICsgJy5faW5wdXRSYW5nZScpLnNldChudWxsKTtcbiAgICAgICAgICAgIHZhciBheEZ1bGwgPSBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rKS5nZXQoKTtcbiAgICAgICAgICAgIGlmKGF4RnVsbC5faW5wdXREb21haW4pIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSdyZSBhdXRvcmFuZ2luZyBhbmQgdGhpcyBheGlzIGhhcyBhIGNvbnN0cmFpbmVkIGRvbWFpbixcbiAgICAgICAgICAgICAgICAvLyByZXNldCBpdCBzbyB3ZSBkb24ndCBnZXQgbG9ja2VkIGludG8gYSBzaHJ1bmtlbiBzaXplXG4gICAgICAgICAgICAgICAgYXhGdWxsLl9pbnB1dC5kb21haW4gPSBheEZ1bGwuX2lucHV0RG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihwbGVhZlBsdXMubWF0Y2goQVhfRE9NQUlOX1JFKSkge1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KGZ1bGxMYXlvdXQsIHB0cnVuayArICcuX2lucHV0RG9tYWluJykuc2V0KG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdG9nZ2xpbmcgYXhpcyB0eXBlIGJldHdlZW4gbG9nIGFuZCBsaW5lYXI6IHdlIG5lZWQgdG8gY29udmVydFxuICAgICAgICAvLyBwb3NpdGlvbnMgZm9yIGNvbXBvbmVudHMgdGhhdCBhcmUgc3RpbGwgdXNpbmcgbGluZWFyaXplZCB2YWx1ZXMsXG4gICAgICAgIC8vIG5vdCBkYXRhIHZhbHVlcyBsaWtlIG5ld2VyIGNvbXBvbmVudHMuXG4gICAgICAgIC8vIHByZXZpb3VzbHkgd2UgZGlkIHRoaXMgZm9yIGxvZyA8LT4gbm90LWxvZywgYnV0IG5vdyBvbmx5IGRvIGl0XG4gICAgICAgIC8vIGZvciBsb2cgPC0+IGxpbmVhclxuICAgICAgICBpZihwbGVhZiA9PT0gJ3R5cGUnKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBwYXJlbnRJbixcbiAgICAgICAgICAgICAgICB0b0xvZyA9IHBhcmVudEZ1bGwudHlwZSA9PT0gJ2xpbmVhcicgJiYgdmkgPT09ICdsb2cnLFxuICAgICAgICAgICAgICAgIGZyb21Mb2cgPSBwYXJlbnRGdWxsLnR5cGUgPT09ICdsb2cnICYmIHZpID09PSAnbGluZWFyJztcblxuICAgICAgICAgICAgaWYodG9Mb2cgfHwgZnJvbUxvZykge1xuICAgICAgICAgICAgICAgIGlmKCFheCB8fCAhYXgucmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gMkQgbmV2ZXIgZ2V0cyBoZXJlLCBidXQgM0QgZG9lc1xuICAgICAgICAgICAgICAgICAgICAvLyBJIGRvbid0IHRoaW5rIHRoaXMgaXMgbmVlZGVkLCBidXQgbGVmdCBoZXJlIGluIGNhc2UgdGhlcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGVkZ2UgY2FzZXMgSSdtIG5vdCB0aGlua2luZyBvZi5cbiAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKCFwYXJlbnRGdWxsLmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyB0b2dnbGluZyBsb2cgd2l0aG91dCBhdXRvcmFuZ2U6IG5lZWQgdG8gYWxzbyByZWNhbGN1bGF0ZSByYW5nZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVjYXVzZSBsb2cgYXhlcyB1c2UgbGluZWFyaXplZCB2YWx1ZXMgZm9yIHJhbmdlIGVuZHBvaW50c1xuICAgICAgICAgICAgICAgICAgICB2YXIgcjAgPSBheC5yYW5nZVswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHIxID0gYXgucmFuZ2VbMV07XG4gICAgICAgICAgICAgICAgICAgIGlmKHRvTG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBib3RoIGxpbWl0cyBhcmUgbmVnYXRpdmUsIGF1dG9yYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocjAgPD0gMCAmJiByMSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgb25lIGlzIG5lZ2F0aXZlLCBzZXQgaXQgNiBvcmRlcnMgYmVsb3cgdGhlIG90aGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocjAgPD0gMCkgcjAgPSByMSAvIDFlNjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYocjEgPD0gMCkgcjEgPSByMCAvIDFlNjtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vdyBzZXQgdGhlIHJhbmdlIHZhbHVlcyBhcyBhcHByb3ByaWF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLnJhbmdlWzBdJywgTWF0aC5sb2cocjApIC8gTWF0aC5MTjEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHRydW5rICsgJy5yYW5nZVsxXScsIE1hdGgubG9nKHIxKSAvIE1hdGguTE4xMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2V4dHJhKHB0cnVuayArICcucmFuZ2VbMF0nLCBNYXRoLnBvdygxMCwgcjApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHRydW5rICsgJy5yYW5nZVsxXScsIE1hdGgucG93KDEwLCByMSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYodG9Mb2cpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8ganVzdCBtYWtlIHN1cmUgdGhlIHJhbmdlIGlzIHBvc2l0aXZlIGFuZCBpbiB0aGUgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgLy8gb3JkZXIsIGl0J2xsIGdldCByZWNhbGN1bGF0ZWQgbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgYXgucmFuZ2UgPSAoYXgucmFuZ2VbMV0gPiBheC5yYW5nZVswXSkgPyBbMSwgMl0gOiBbMiwgMV07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gY2xlYXIgcG9sYXIgdmlldyBpbml0aWFsIHN0YXNoIGZvciByYWRpYWwgcmFuZ2Ugc28gdGhhdFxuICAgICAgICAgICAgICAgIC8vIHZhbHVlIGdldCByZWNvbXB1dGVkIGluIGNvcnJlY3QgdW5pdHNcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGZ1bGxMYXlvdXQuX3N1YnBsb3RzLnBvbGFyKSAmJlxuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0Ll9zdWJwbG90cy5wb2xhci5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICAgICAgZnVsbExheW91dFtwLnBhcnRzWzBdXSAmJlxuICAgICAgICAgICAgICAgICAgICBwLnBhcnRzWzFdID09PSAncmFkaWFsYXhpcydcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGZ1bGxMYXlvdXRbcC5wYXJ0c1swXV0uX3N1YnBsb3Qudmlld0luaXRpYWxbJ3JhZGlhbGF4aXMucmFuZ2UnXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBbm5vdGF0aW9ucyBhbmQgaW1hZ2VzIGFsc28gbmVlZCB0byBjb252ZXJ0IHRvL2Zyb20gbGluZWFyaXplZCBjb29yZHNcbiAgICAgICAgICAgICAgICAvLyBTaGFwZXMgZG8gbm90IG5lZWQgdGhpcyA6KVxuICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnY29udmVydENvb3JkcycpKGdkLCBwYXJlbnRGdWxsLCB2aSwgZG9leHRyYSk7XG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdpbWFnZXMnLCAnY29udmVydENvb3JkcycpKGdkLCBwYXJlbnRGdWxsLCB2aSwgZG9leHRyYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgdHlwZSBjaGFuZ2VzOiB0aGUgcmFuZ2UgZnJvbSB0aGUgcHJldmlvdXMgdHlwZVxuICAgICAgICAgICAgICAgIC8vIHdpbGwgbm90IG1ha2Ugc2Vuc2UsIHNvIGF1dG9yYW5nZSBpdC5cbiAgICAgICAgICAgICAgICBkb2V4dHJhKHB0cnVuayArICcuYXV0b3JhbmdlJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLnJhbmdlJywgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rICsgJy5faW5wdXRSYW5nZScpLnNldChudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHBsZWFmLm1hdGNoKEFYX05BTUVfUEFUVEVSTikpIHtcbiAgICAgICAgICAgIHZhciBmdWxsUHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShmdWxsTGF5b3V0LCBhaSkuZ2V0KCksXG4gICAgICAgICAgICAgICAgbmV3VHlwZSA9ICh2aSB8fCB7fSkudHlwZTtcblxuICAgICAgICAgICAgLy8gVGhpcyBjYW4gcG90ZW50aWFsbHkgY2F1c2Ugc3RyYW5nZSBiZWhhdmlvciBpZiB0aGUgYXV0b3R5cGUgaXMgbm90XG4gICAgICAgICAgICAvLyBudW1lcmljIChsaW5lYXIsIGJlY2F1c2Ugd2UgZG9uJ3QgYXV0by1sb2cpIGJ1dCB0aGUgcHJldmlvdXMgdHlwZVxuICAgICAgICAgICAgLy8gd2FzIGxvZy4gVGhhdCdzIGEgdmVyeSBzdHJhbmdlIGVkZ2UgY2FzZSB0aG91Z2hcbiAgICAgICAgICAgIGlmKCFuZXdUeXBlIHx8IG5ld1R5cGUgPT09ICctJykgbmV3VHlwZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdjb252ZXJ0Q29vcmRzJykoZ2QsIGZ1bGxQcm9wLCBuZXdUeXBlLCBkb2V4dHJhKTtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnaW1hZ2VzJywgJ2NvbnZlcnRDb29yZHMnKShnZCwgZnVsbFByb3AsIG5ld1R5cGUsIGRvZXh0cmEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWx0ZXIgZ2QubGF5b3V0XG5cbiAgICAgICAgLy8gY29sbGVjdCBhcnJheSBjb21wb25lbnQgZWRpdHMgZm9yIGV4ZWN1dGlvbiBhbGwgdG9nZXRoZXJcbiAgICAgICAgLy8gc28gd2UgY2FuIGVuc3VyZSBjb25zaXN0ZW50IGJlaGF2aW9yIGFkZGluZy9yZW1vdmluZyBpdGVtc1xuICAgICAgICAvLyBhbmQgb3JkZXItaW5kZXBlbmRlbmNlIGZvciBhZGQvcmVtb3ZlL2VkaXQgYWxsIHRvZ2V0aGVyIGluXG4gICAgICAgIC8vIG9uZSByZWxheW91dCBjYWxsXG4gICAgICAgIHZhciBjb250YWluZXJBcnJheU1hdGNoID0gbWFuYWdlQXJyYXlzLmNvbnRhaW5lckFycmF5TWF0Y2goYWkpO1xuICAgICAgICBpZihjb250YWluZXJBcnJheU1hdGNoKSB7XG4gICAgICAgICAgICBhcnJheVN0ciA9IGNvbnRhaW5lckFycmF5TWF0Y2guYXJyYXk7XG4gICAgICAgICAgICBpID0gY29udGFpbmVyQXJyYXlNYXRjaC5pbmRleDtcbiAgICAgICAgICAgIHZhciBwcm9wU3RyID0gY29udGFpbmVyQXJyYXlNYXRjaC5wcm9wZXJ0eTtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnRBcnJheSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShsYXlvdXQsIGFycmF5U3RyKTtcbiAgICAgICAgICAgIHZhciBvYmppID0gKGNvbXBvbmVudEFycmF5IHx8IFtdKVtpXSB8fCB7fTtcbiAgICAgICAgICAgIHZhciB1cGRhdGVWYWxPYmplY3QgPSB2YWxPYmplY3QgfHwge2VkaXRUeXBlOiAnY2FsYyd9O1xuXG4gICAgICAgICAgICBpZihpICE9PSAnJyAmJiBwcm9wU3RyID09PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIHNwZWNpYWwgaGFuZGxpbmcgb2YgdW5kb2l0IGlmIHdlJ3JlIGFkZGluZyBvciByZW1vdmluZyBhbiBlbGVtZW50XG4gICAgICAgICAgICAgICAgLy8gaWUgJ2Fubm90YXRpb25zWzJdJyB3aGljaCBjYW4gYmUgey4uLn0gKGFkZCkgb3IgbnVsbCxcbiAgICAgICAgICAgICAgICAvLyBkb2VzIG5vdCB3b3JrIHdoZW4gcmVwbGFjaW5nIHRoZSBlbnRpcmUgYXJyYXlcbiAgICAgICAgICAgICAgICBpZihtYW5hZ2VBcnJheXMuaXNBZGRWYWwodmkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuZG9pdFthaV0gPSBudWxsO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtYW5hZ2VBcnJheXMuaXNSZW1vdmVWYWwodmkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuZG9pdFthaV0gPSBvYmppO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIExpYi53YXJuKCd1bnJlY29nbml6ZWQgZnVsbCBvYmplY3QgdmFsdWUnLCBhb2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlZGl0VHlwZXMudXBkYXRlKGZsYWdzLCB1cGRhdGVWYWxPYmplY3QpO1xuXG4gICAgICAgICAgICAvLyBwcmVwYXJlIHRoZSBlZGl0cyBvYmplY3Qgd2UnbGwgc2VuZCB0byBhcHBseUNvbnRhaW5lckFycmF5Q2hhbmdlc1xuICAgICAgICAgICAgaWYoIWFycmF5RWRpdHNbYXJyYXlTdHJdKSBhcnJheUVkaXRzW2FycmF5U3RyXSA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iakVkaXRzID0gYXJyYXlFZGl0c1thcnJheVN0cl1baV07XG4gICAgICAgICAgICBpZighb2JqRWRpdHMpIG9iakVkaXRzID0gYXJyYXlFZGl0c1thcnJheVN0cl1baV0gPSB7fTtcbiAgICAgICAgICAgIG9iakVkaXRzW3Byb3BTdHJdID0gdmk7XG5cbiAgICAgICAgICAgIGRlbGV0ZSBhb2JqW2FpXTtcbiAgICAgICAgfVxuICAgICAgICAvLyBoYW5kbGUgYXhpcyByZXZlcnNhbCBleHBsaWNpdGx5LCBhcyB0aGVyZSdzIG5vICdyZXZlcnNlJyBhdHRyaWJ1dGVcbiAgICAgICAgZWxzZSBpZihwbGVhZiA9PT0gJ3JldmVyc2UnKSB7XG4gICAgICAgICAgICBpZihwYXJlbnRJbi5yYW5nZSkgcGFyZW50SW4ucmFuZ2UucmV2ZXJzZSgpO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgIHBhcmVudEluLnJhbmdlID0gWzEsIDBdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihwYXJlbnRGdWxsLmF1dG9yYW5nZSkgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICBlbHNlIGZsYWdzLnBsb3QgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYoKGZ1bGxMYXlvdXQuX2hhcygnc2NhdHRlci1saWtlJykgJiYgZnVsbExheW91dC5faGFzKCdyZWdsJykpICYmXG4gICAgICAgICAgICAgICAgKGFpID09PSAnZHJhZ21vZGUnICYmXG4gICAgICAgICAgICAgICAgKHZpID09PSAnbGFzc28nIHx8IHZpID09PSAnc2VsZWN0JykgJiZcbiAgICAgICAgICAgICAgICAhKHZPbGQgPT09ICdsYXNzbycgfHwgdk9sZCA9PT0gJ3NlbGVjdCcpKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZmxhZ3MucGxvdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHZhbE9iamVjdCkgZWRpdFR5cGVzLnVwZGF0ZShmbGFncywgdmFsT2JqZWN0KTtcbiAgICAgICAgICAgIGVsc2UgZmxhZ3MuY2FsYyA9IHRydWU7XG5cbiAgICAgICAgICAgIHAuc2V0KHZpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG5vdyB3ZSd2ZSBjb2xsZWN0ZWQgY29tcG9uZW50IGVkaXRzIC0gZXhlY3V0ZSB0aGVtIGFsbCB0b2dldGhlclxuICAgIGZvcihhcnJheVN0ciBpbiBhcnJheUVkaXRzKSB7XG4gICAgICAgIHZhciBmaW5pc2hlZCA9IG1hbmFnZUFycmF5cy5hcHBseUNvbnRhaW5lckFycmF5Q2hhbmdlcyhnZCxcbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShsYXlvdXQsIGFycmF5U3RyKSwgYXJyYXlFZGl0c1thcnJheVN0cl0sIGZsYWdzKTtcbiAgICAgICAgaWYoIWZpbmlzaGVkKSBmbGFncy5wbG90ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBmaWd1cmUgb3V0IGlmIHdlIG5lZWQgdG8gcmVjYWxjdWxhdGUgYXhpcyBjb25zdHJhaW50c1xuICAgIHZhciBjb25zdHJhaW50cyA9IGZ1bGxMYXlvdXQuX2F4aXNDb25zdHJhaW50R3JvdXBzIHx8IFtdO1xuICAgIGZvcihheElkIGluIHJhbmdlc0FsdGVyZWQpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY29uc3RyYWludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBncm91cCA9IGNvbnN0cmFpbnRzW2ldO1xuICAgICAgICAgICAgaWYoZ3JvdXBbYXhJZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBBbHdheXMgcmVjYWxjIGlmIHdlJ3JlIGNoYW5naW5nIGNvbnN0cmFpbmVkIHJhbmdlcy5cbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgaXQncyBwb3NzaWJsZSB0byB2aW9sYXRlIHRoZSBjb25zdHJhaW50cyBieVxuICAgICAgICAgICAgICAgIC8vIHNwZWNpZnlpbmcgYXJiaXRyYXJ5IHJhbmdlcyBmb3IgYWxsIGF4ZXMgaW4gdGhlIGdyb3VwLlxuICAgICAgICAgICAgICAgIC8vIHRoaXMgd2F5IHNvbWUgcmFuZ2VzIG1heSBleHBhbmQgYmV5b25kIHdoYXQncyBzcGVjaWZpZWQsXG4gICAgICAgICAgICAgICAgLy8gYXMgdGhleSBkbyBhdCBmaXJzdCBkcmF3LCB0byBzYXRpc2Z5IHRoZSBjb25zdHJhaW50cy5cbiAgICAgICAgICAgICAgICBmbGFncy5jYWxjID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGdyb3VwQXhJZCBpbiBncm91cCkge1xuICAgICAgICAgICAgICAgICAgICBpZighcmFuZ2VzQWx0ZXJlZFtncm91cEF4SWRdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBBeGVzLmdldEZyb21JZChnZCwgZ3JvdXBBeElkKS5fY29uc3RyYWludFNocmlua2FibGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIGF1dG9zaXplIGNoYW5nZWQgb3IgaGVpZ2h0IG9yIHdpZHRoIHdhcyBleHBsaWNpdGx5IHNwZWNpZmllZCxcbiAgICAvLyB0aGlzIHRyaWdnZXJzIGEgcmVkcmF3XG4gICAgLy8gVE9ETzogZG8gd2UgcmVhbGx5IG5lZWQgc3BlY2lhbCBhb2JqLmhlaWdodC93aWR0aCBoYW5kbGluZyBoZXJlP1xuICAgIC8vIGNvdWxkbid0IGVkaXRUeXBlIGRvIHRoaXM/XG4gICAgaWYodXBkYXRlQXV0b3NpemUoZ2QpIHx8IGFvYmouaGVpZ2h0IHx8IGFvYmoud2lkdGgpIGZsYWdzLnBsb3QgPSB0cnVlO1xuXG4gICAgaWYoZmxhZ3MucGxvdCB8fCBmbGFncy5jYWxjKSB7XG4gICAgICAgIGZsYWdzLmxheW91dFJlcGxvdCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gbm93IGFsbCBhdHRyaWJ1dGUgbW9kcyBhcmUgZG9uZSwgYXMgYXJlXG4gICAgLy8gcmVkbyBhbmQgdW5kbyBzbyB3ZSBjYW4gc2F2ZSB0aGVtXG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmbGFnczogZmxhZ3MsXG4gICAgICAgIHJhbmdlc0FsdGVyZWQ6IHJhbmdlc0FsdGVyZWQsXG4gICAgICAgIHVuZG9pdDogdW5kb2l0LFxuICAgICAgICByZWRvaXQ6IHJlZG9pdCxcbiAgICAgICAgZXZlbnREYXRhOiBMaWIuZXh0ZW5kRGVlcCh7fSwgcmVkb2l0KVxuICAgIH07XG59XG5cbi8qXG4gKiB1cGRhdGVBdXRvc2l6ZTogd2UgbWFkZSBhIGNoYW5nZSwgZG9lcyBpdCBjaGFuZ2UgdGhlIGF1dG9zaXplIHJlc3VsdD9cbiAqIHB1dHMgdGhlIG5ldyBzaXplIGludG8gZnVsbExheW91dFxuICogcmV0dXJucyB0cnVlIGlmIGVpdGhlciBoZWlnaHQgb3Igd2lkdGggY2hhbmdlZFxuICovXG5mdW5jdGlvbiB1cGRhdGVBdXRvc2l6ZShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG9sZFdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgb2xkSGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG5cbiAgICAvLyBjYWxjdWxhdGUgYXV0b3NpemluZ1xuICAgIGlmKGdkLmxheW91dC5hdXRvc2l6ZSkgUGxvdHMucGxvdEF1dG9TaXplKGdkLCBnZC5sYXlvdXQsIGZ1bGxMYXlvdXQpO1xuXG4gICAgcmV0dXJuIChmdWxsTGF5b3V0LndpZHRoICE9PSBvbGRXaWR0aCkgfHwgKGZ1bGxMYXlvdXQuaGVpZ2h0ICE9PSBvbGRIZWlnaHQpO1xufVxuXG4vKipcbiAqIHVwZGF0ZTogdXBkYXRlIHRyYWNlIGFuZCBsYXlvdXQgYXR0cmlidXRlcyBvZiBhbiBleGlzdGluZyBwbG90XG4gKlxuICogQHBhcmFtIHtTdHJpbmcgfCBIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7T2JqZWN0fSB0cmFjZVVwZGF0ZVxuICogIGF0dHJpYnV0ZSBvYmplY3QgYHthc3RyMTogdmFsMSwgYXN0cjI6IHZhbDIgLi4ufWBcbiAqICBjb3JyZXNwb25kaW5nIHRvIHVwZGF0ZXMgaW4gdGhlIHBsb3QncyB0cmFjZXNcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXlvdXRVcGRhdGVcbiAqICBhdHRyaWJ1dGUgb2JqZWN0IGB7YXN0cjE6IHZhbDEsIGFzdHIyOiB2YWwyIC4uLn1gXG4gKiAgY29ycmVzcG9uZGluZyB0byB1cGRhdGVzIGluIHRoZSBwbG90J3MgbGF5b3V0XG4gKiBAcGFyYW0ge051bWJlcltdIHwgTnVtYmVyfSBbdHJhY2VzXVxuICogIGludGVnZXIgb3IgYXJyYXkgb2YgaW50ZWdlcnMgZm9yIHRoZSB0cmFjZXMgdG8gYWx0ZXIgKGFsbCBpZiBvbWl0dGVkKVxuICpcbiAqL1xuZXhwb3J0cy51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoZ2QsIHRyYWNlVXBkYXRlLCBsYXlvdXRVcGRhdGUsIF90cmFjZXMpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG4gICAgaGVscGVycy5jbGVhclByb21pc2VRdWV1ZShnZCk7XG5cbiAgICBpZihnZC5mcmFtZXdvcmsgJiYgZ2QuZnJhbWV3b3JrLmlzUG9sYXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShnZCk7XG4gICAgfVxuXG4gICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KHRyYWNlVXBkYXRlKSkgdHJhY2VVcGRhdGUgPSB7fTtcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QobGF5b3V0VXBkYXRlKSkgbGF5b3V0VXBkYXRlID0ge307XG5cbiAgICBpZihPYmplY3Qua2V5cyh0cmFjZVVwZGF0ZSkubGVuZ3RoKSBnZC5jaGFuZ2VkID0gdHJ1ZTtcbiAgICBpZihPYmplY3Qua2V5cyhsYXlvdXRVcGRhdGUpLmxlbmd0aCkgZ2QuY2hhbmdlZCA9IHRydWU7XG5cbiAgICB2YXIgdHJhY2VzID0gaGVscGVycy5jb2VyY2VUcmFjZUluZGljZXMoZ2QsIF90cmFjZXMpO1xuXG4gICAgdmFyIHJlc3R5bGVTcGVjcyA9IF9yZXN0eWxlKGdkLCBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhY2VVcGRhdGUpLCB0cmFjZXMpO1xuICAgIHZhciByZXN0eWxlRmxhZ3MgPSByZXN0eWxlU3BlY3MuZmxhZ3M7XG5cbiAgICB2YXIgcmVsYXlvdXRTcGVjcyA9IF9yZWxheW91dChnZCwgTGliLmV4dGVuZEZsYXQoe30sIGxheW91dFVwZGF0ZSkpO1xuICAgIHZhciByZWxheW91dEZsYWdzID0gcmVsYXlvdXRTcGVjcy5mbGFncztcblxuICAgIC8vIGNsZWFyIGNhbGNkYXRhIGFuZC9vciBheGlzIHR5cGVzIGlmIHJlcXVpcmVkXG4gICAgaWYocmVzdHlsZUZsYWdzLmNhbGMgfHwgcmVsYXlvdXRGbGFncy5jYWxjKSBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICBpZihyZXN0eWxlRmxhZ3MuY2xlYXJBeGlzVHlwZXMpIGhlbHBlcnMuY2xlYXJBeGlzVHlwZXMoZ2QsIHRyYWNlcywgbGF5b3V0VXBkYXRlKTtcblxuICAgIC8vIGZpbGwgaW4gcmVkcmF3IHNlcXVlbmNlXG4gICAgdmFyIHNlcSA9IFtdO1xuXG4gICAgaWYocmVzdHlsZUZsYWdzLmZ1bGxSZXBsb3QgJiYgcmVsYXlvdXRGbGFncy5sYXlvdXRSZXBsb3QpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBnZC5kYXRhLFxuICAgICAgICAgICAgbGF5b3V0ID0gZ2QubGF5b3V0O1xuXG4gICAgICAgIC8vIGNsZWFyIGV4aXN0aW5nIGRhdGEvbGF5b3V0IG9uIGdkXG4gICAgICAgIC8vIHNvIHRoYXQgUGxvdGx5LnBsb3QgZG9lc24ndCB0cnkgdG8gZXh0ZW5kIHRoZW1cbiAgICAgICAgZ2QuZGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgICAgZ2QubGF5b3V0ID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKCkgeyByZXR1cm4gZXhwb3J0cy5wbG90KGdkLCBkYXRhLCBsYXlvdXQpOyB9KTtcbiAgICB9XG4gICAgZWxzZSBpZihyZXN0eWxlRmxhZ3MuZnVsbFJlcGxvdCkge1xuICAgICAgICBzZXEucHVzaChleHBvcnRzLnBsb3QpO1xuICAgIH1cbiAgICBlbHNlIGlmKHJlbGF5b3V0RmxhZ3MubGF5b3V0UmVwbG90KSB7XG4gICAgICAgIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFJlcGxvdCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBzZXEucHVzaChQbG90cy5wcmV2aW91c1Byb21pc2VzKTtcbiAgICAgICAgYXhSYW5nZVN1cHBseURlZmF1bHRzQnlQYXNzKGdkLCByZWxheW91dEZsYWdzLCByZWxheW91dFNwZWNzKSB8fCBQbG90cy5zdXBwbHlEZWZhdWx0cyhnZCk7XG5cbiAgICAgICAgaWYocmVzdHlsZUZsYWdzLnN0eWxlKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb1RyYWNlU3R5bGUpO1xuICAgICAgICBpZihyZXN0eWxlRmxhZ3MuY29sb3JiYXJzKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0NvbG9yQmFycyk7XG4gICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubGVnZW5kKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0xlZ2VuZCk7XG4gICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubGF5b3V0c3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MuYXhyYW5nZSkgYWRkQXhSYW5nZVNlcXVlbmNlKHNlcSwgcmVsYXlvdXRTcGVjcy5yYW5nZXNBbHRlcmVkKTtcbiAgICAgICAgaWYocmVsYXlvdXRGbGFncy50aWNrcykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UaWNrc1JlbGF5b3V0KTtcbiAgICAgICAgaWYocmVsYXlvdXRGbGFncy5tb2RlYmFyKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb01vZGVCYXIpO1xuICAgICAgICBpZihyZWxheW91dEZsYWdzLmNhbWVyYSkgc2VxLnB1c2goc3Vicm91dGluZXMuZG9DYW1lcmEpO1xuXG4gICAgICAgIHNlcS5wdXNoKGVtaXRBZnRlclBsb3QpO1xuICAgIH1cblxuICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIpO1xuXG4gICAgUXVldWUuYWRkKGdkLFxuICAgICAgICB1cGRhdGUsIFtnZCwgcmVzdHlsZVNwZWNzLnVuZG9pdCwgcmVsYXlvdXRTcGVjcy51bmRvaXQsIHJlc3R5bGVTcGVjcy50cmFjZXNdLFxuICAgICAgICB1cGRhdGUsIFtnZCwgcmVzdHlsZVNwZWNzLnJlZG9pdCwgcmVsYXlvdXRTcGVjcy5yZWRvaXQsIHJlc3R5bGVTcGVjcy50cmFjZXNdXG4gICAgKTtcblxuICAgIHZhciBwbG90RG9uZSA9IExpYi5zeW5jT3JBc3luYyhzZXEsIGdkKTtcbiAgICBpZighcGxvdERvbmUgfHwgIXBsb3REb25lLnRoZW4pIHBsb3REb25lID0gUHJvbWlzZS5yZXNvbHZlKGdkKTtcblxuICAgIHJldHVybiBwbG90RG9uZS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfdXBkYXRlJywge1xuICAgICAgICAgICAgZGF0YTogcmVzdHlsZVNwZWNzLmV2ZW50RGF0YSxcbiAgICAgICAgICAgIGxheW91dDogcmVsYXlvdXRTcGVjcy5ldmVudERhdGFcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGdkO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBQbG90bHkucmVhY3Q6XG4gKiBBIHBsb3QvdXBkYXRlIG1ldGhvZCB0aGF0IHRha2VzIHRoZSBmdWxsIHBsb3Qgc3RhdGUgKHNhbWUgQVBJIGFzIHBsb3QvbmV3UGxvdClcbiAqIGFuZCBkaWZmcyB0byBkZXRlcm1pbmUgdGhlIG1pbmltYWwgdXBkYXRlIHBhdGh3YXlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKiBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IGRhdGFcbiAqICAgICAgYXJyYXkgb2YgdHJhY2VzLCBjb250YWluaW5nIHRoZSBkYXRhIGFuZCBkaXNwbGF5IGluZm9ybWF0aW9uIGZvciBlYWNoIHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0XG4gKiAgICAgIG9iamVjdCBkZXNjcmliaW5nIHRoZSBvdmVyYWxsIGRpc3BsYXkgb2YgdGhlIHBsb3QsXG4gKiAgICAgIGFsbCB0aGUgc3R1ZmYgdGhhdCBkb2Vzbid0IHBlcnRhaW4gdG8gYW55IGluZGl2aWR1YWwgdHJhY2VcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWdcbiAqICAgICAgY29uZmlndXJhdGlvbiBvcHRpb25zIChzZWUgLi9wbG90X2NvbmZpZy5qcyBmb3IgbW9yZSBpbmZvKVxuICpcbiAqIE9SXG4gKlxuICogQHBhcmFtIHtzdHJpbmcgaWQgb3IgRE9NIGVsZW1lbnR9IGdkXG4gKiAgICAgIHRoZSBpZCBvciBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHtvYmplY3R9IGZpZ3VyZVxuICogICAgICBvYmplY3QgY29udGFpbmluZyBgZGF0YWAsIGBsYXlvdXRgLCBgY29uZmlnYCwgYW5kIGBmcmFtZXNgIG1lbWJlcnNcbiAqXG4gKi9cbmV4cG9ydHMucmVhY3QgPSBmdW5jdGlvbihnZCwgZGF0YSwgbGF5b3V0LCBjb25maWcpIHtcbiAgICB2YXIgZnJhbWVzLCBwbG90RG9uZTtcblxuICAgIGZ1bmN0aW9uIGFkZEZyYW1lcygpIHsgcmV0dXJuIGV4cG9ydHMuYWRkRnJhbWVzKGdkLCBmcmFtZXMpOyB9XG5cbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICB2YXIgb2xkRnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIG9sZEZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIC8vIHlvdSBjYW4gdXNlIHRoaXMgYXMgdGhlIGluaXRpYWwgZHJhdyBhcyB3ZWxsIGFzIHRvIHVwZGF0ZVxuICAgIGlmKCFMaWIuaXNQbG90RGl2KGdkKSB8fCAhb2xkRnVsbERhdGEgfHwgIW9sZEZ1bGxMYXlvdXQpIHtcbiAgICAgICAgcGxvdERvbmUgPSBleHBvcnRzLm5ld1Bsb3QoZ2QsIGRhdGEsIGxheW91dCwgY29uZmlnKTtcbiAgICB9XG4gICAgZWxzZSB7XG5cbiAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QoZGF0YSkpIHtcbiAgICAgICAgICAgIHZhciBvYmogPSBkYXRhO1xuICAgICAgICAgICAgZGF0YSA9IG9iai5kYXRhO1xuICAgICAgICAgICAgbGF5b3V0ID0gb2JqLmxheW91dDtcbiAgICAgICAgICAgIGNvbmZpZyA9IG9iai5jb25maWc7XG4gICAgICAgICAgICBmcmFtZXMgPSBvYmouZnJhbWVzO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbmZpZ0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgLy8gYXNzdW1lIHRoYXQgaWYgdGhlcmUncyBhIGNvbmZpZyBhdCBhbGwsIHdlJ3JlIHJlYWN0aW5nIHRvIGl0IHRvbyxcbiAgICAgICAgLy8gYW5kIGNvbXBsZXRlbHkgcmVwbGFjZSB0aGUgcHJldmlvdXMgY29uZmlnXG4gICAgICAgIGlmKGNvbmZpZykge1xuICAgICAgICAgICAgdmFyIG9sZENvbmZpZyA9IExpYi5leHRlbmREZWVwKHt9LCBnZC5fY29udGV4dCk7XG4gICAgICAgICAgICBnZC5fY29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNldFBsb3RDb250ZXh0KGdkLCBjb25maWcpO1xuICAgICAgICAgICAgY29uZmlnQ2hhbmdlZCA9IGRpZmZDb25maWcob2xkQ29uZmlnLCBnZC5fY29udGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICBnZC5kYXRhID0gZGF0YSB8fCBbXTtcbiAgICAgICAgaGVscGVycy5jbGVhbkRhdGEoZ2QuZGF0YSk7XG4gICAgICAgIGdkLmxheW91dCA9IGxheW91dCB8fCB7fTtcbiAgICAgICAgaGVscGVycy5jbGVhbkxheW91dChnZC5sYXlvdXQpO1xuXG4gICAgICAgIC8vIFwidHJ1ZVwiIHNraXBzIHVwZGF0aW5nIGNhbGNkYXRhIGFuZCByZW1hcHBpbmcgYXJyYXlzIGZyb20gY2FsY1RyYW5zZm9ybXMsXG4gICAgICAgIC8vIHdoaWNoIHN1cHBseURlZmF1bHRzIHVzdWFsbHkgZG9lcyBhdCB0aGUgZW5kLCBidXQgd2UgbWF5IG5lZWQgdG8gTk9UIGRvXG4gICAgICAgIC8vIGlmIHRoZSBkaWZmICh3aGljaCB3ZSBoYXZlbid0IGRldGVybWluZWQgeWV0KSBzYXlzIHdlJ2xsIHJlY2FsY1xuICAgICAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhnZCwge3NraXBVcGRhdGVDYWxjOiB0cnVlfSk7XG5cbiAgICAgICAgdmFyIG5ld0Z1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgICAgICB2YXIgbmV3RnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICB2YXIgaW1tdXRhYmxlID0gbmV3RnVsbExheW91dC5kYXRhcmV2aXNpb24gPT09IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIHRyYW5zaXRpb24gPSBuZXdGdWxsTGF5b3V0LnRyYW5zaXRpb247XG5cbiAgICAgICAgdmFyIHJlbGF5b3V0RmxhZ3MgPSBkaWZmTGF5b3V0KGdkLCBvbGRGdWxsTGF5b3V0LCBuZXdGdWxsTGF5b3V0LCBpbW11dGFibGUsIHRyYW5zaXRpb24pO1xuICAgICAgICB2YXIgbmV3RGF0YVJldmlzaW9uID0gcmVsYXlvdXRGbGFncy5uZXdEYXRhUmV2aXNpb247XG4gICAgICAgIHZhciByZXN0eWxlRmxhZ3MgPSBkaWZmRGF0YShnZCwgb2xkRnVsbERhdGEsIG5ld0Z1bGxEYXRhLCBpbW11dGFibGUsIHRyYW5zaXRpb24sIG5ld0RhdGFSZXZpc2lvbik7XG5cbiAgICAgICAgLy8gVE9ETzogaG93IHRvIHRyYW5zbGF0ZSB0aGlzIHBhcnQgb2YgcmVsYXlvdXQgdG8gUGxvdGx5LnJlYWN0P1xuICAgICAgICAvLyAvLyBTZXR0aW5nIHdpZHRoIG9yIGhlaWdodCB0byBudWxsIG11c3QgcmVzZXQgdGhlIGdyYXBoJ3Mgd2lkdGggLyBoZWlnaHRcbiAgICAgICAgLy8gLy8gYmFjayB0byBpdHMgaW5pdGlhbCB2YWx1ZSBhcyBjb21wdXRlZCBkdXJpbmcgdGhlIGZpcnN0IHBhc3MgaW4gUGxvdHMucGxvdEF1dG9TaXplLlxuICAgICAgICAvLyAvL1xuICAgICAgICAvLyAvLyBUbyBkbyBzbywgd2UgbXVzdCBtYW51YWxseSBzZXQgdGhlbSBiYWNrIGhlcmUgdXNpbmcgdGhlIF9pbml0aWFsQXV0b1NpemUgY2FjaGUuXG4gICAgICAgIC8vIGlmKFsnd2lkdGgnLCAnaGVpZ2h0J10uaW5kZXhPZihhaSkgIT09IC0xICYmIHZpID09PSBudWxsKSB7XG4gICAgICAgIC8vICAgICBmdWxsTGF5b3V0W2FpXSA9IGdkLl9pbml0aWFsQXV0b1NpemVbYWldO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgaWYodXBkYXRlQXV0b3NpemUoZ2QpKSByZWxheW91dEZsYWdzLmxheW91dFJlcGxvdCA9IHRydWU7XG5cbiAgICAgICAgLy8gY2xlYXIgY2FsY2RhdGEgaWYgcmVxdWlyZWRcbiAgICAgICAgaWYocmVzdHlsZUZsYWdzLmNhbGMgfHwgcmVsYXlvdXRGbGFncy5jYWxjKSBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gb3RoZXJ3aXNlIGRvIHRoZSBjYWxjZGF0YSB1cGRhdGVzIGFuZCBjYWxjVHJhbnNmb3JtIGFycmF5IHJlbWFwcyB0aGF0IHdlIHNraXBwZWQgZWFybGllclxuICAgICAgICBlbHNlIFBsb3RzLnN1cHBseURlZmF1bHRzVXBkYXRlQ2FsYyhnZC5jYWxjZGF0YSwgbmV3RnVsbERhdGEpO1xuXG4gICAgICAgIC8vIE5vdGU6IHdoYXQgcmVzdHlsZS9yZWxheW91dCB1c2UgaW1wbGllZEVkaXRzIGFuZCBjbGVhckF4aXNUeXBlcyBmb3JcbiAgICAgICAgLy8gbXVzdCBiZSBoYW5kbGVkIGJ5IHRoZSB1c2VyIHdoZW4gdXNpbmcgUGxvdGx5LnJlYWN0LlxuXG4gICAgICAgIC8vIGZpbGwgaW4gcmVkcmF3IHNlcXVlbmNlXG4gICAgICAgIHZhciBzZXEgPSBbXTtcblxuICAgICAgICBpZihmcmFtZXMpIHtcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YSA9IHt9O1xuICAgICAgICAgICAgUGxvdHMuY3JlYXRlVHJhbnNpdGlvbkRhdGEoZ2QpO1xuICAgICAgICAgICAgc2VxLnB1c2goYWRkRnJhbWVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYW5zaXRpb24gcGF0aHdheSxcbiAgICAgICAgLy8gb25seSB1c2VkIHdoZW4gJ3RyYW5zaXRpb24nIGlzIHNldCBieSB1c2VyIGFuZFxuICAgICAgICAvLyB3aGVuIGF0IGxlYXN0IG9uZSBhbmltYXRhYmxlIGF0dHJpYnV0ZSBoYXMgY2hhbmdlZCxcbiAgICAgICAgLy8gTi5CLiBjb25maWcgY2hhbmdlZCBhcmVuJ3QgYW5pbWF0YWJsZVxuICAgICAgICBpZihuZXdGdWxsTGF5b3V0LnRyYW5zaXRpb24gJiYgIWNvbmZpZ0NoYW5nZWQgJiYgKHJlc3R5bGVGbGFncy5hbmltIHx8IHJlbGF5b3V0RmxhZ3MuYW5pbSkpIHtcbiAgICAgICAgICAgIFBsb3RzLmRvQ2FsY2RhdGEoZ2QpO1xuICAgICAgICAgICAgc3Vicm91dGluZXMuZG9BdXRvUmFuZ2VBbmRDb25zdHJhaW50cyhnZCk7XG5cbiAgICAgICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQbG90cy50cmFuc2l0aW9uMihnZCwgcmVzdHlsZUZsYWdzLCByZWxheW91dEZsYWdzLCBvbGRGdWxsTGF5b3V0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocmVzdHlsZUZsYWdzLmZ1bGxSZXBsb3QgfHwgcmVsYXlvdXRGbGFncy5sYXlvdXRSZXBsb3QgfHwgY29uZmlnQ2hhbmdlZCkge1xuICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3NraXBEZWZhdWx0cyA9IHRydWU7XG4gICAgICAgICAgICBzZXEucHVzaChleHBvcnRzLnBsb3QpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9yKHZhciBjb21wb25lbnRUeXBlIGluIHJlbGF5b3V0RmxhZ3MuYXJyYXlzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSByZWxheW91dEZsYWdzLmFycmF5c1tjb21wb25lbnRUeXBlXTtcbiAgICAgICAgICAgICAgICBpZihpbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZHJhd09uZSA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZChjb21wb25lbnRUeXBlLCAnZHJhd09uZScpO1xuICAgICAgICAgICAgICAgICAgICBpZihkcmF3T25lICE9PSBMaWIubm9vcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3T25lKGdkLCBpbmRpY2VzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkcmF3ID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKGNvbXBvbmVudFR5cGUsICdkcmF3Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihkcmF3ID09PSBMaWIubm9vcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGRyYXcgY29tcG9uZW50czogJyArIGNvbXBvbmVudFR5cGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhdyhnZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlcS5wdXNoKFBsb3RzLnByZXZpb3VzUHJvbWlzZXMpO1xuICAgICAgICAgICAgaWYocmVzdHlsZUZsYWdzLnN0eWxlKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb1RyYWNlU3R5bGUpO1xuICAgICAgICAgICAgaWYocmVzdHlsZUZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuICAgICAgICAgICAgaWYocmVsYXlvdXRGbGFncy5sZWdlbmQpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvTGVnZW5kKTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubGF5b3V0c3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgICAgICAgICBpZihyZWxheW91dEZsYWdzLmF4cmFuZ2UpIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEpO1xuICAgICAgICAgICAgaWYocmVsYXlvdXRGbGFncy50aWNrcykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UaWNrc1JlbGF5b3V0KTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubW9kZWJhcikgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Nb2RlQmFyKTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MuY2FtZXJhKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0NhbWVyYSk7XG4gICAgICAgICAgICBzZXEucHVzaChlbWl0QWZ0ZXJQbG90KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIpO1xuXG4gICAgICAgIHBsb3REb25lID0gTGliLnN5bmNPckFzeW5jKHNlcSwgZ2QpO1xuICAgICAgICBpZighcGxvdERvbmUgfHwgIXBsb3REb25lLnRoZW4pIHBsb3REb25lID0gUHJvbWlzZS5yZXNvbHZlKGdkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxvdERvbmUudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3JlYWN0Jywge1xuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIGxheW91dDogbGF5b3V0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcblxufTtcblxuZnVuY3Rpb24gZGlmZkRhdGEoZ2QsIG9sZEZ1bGxEYXRhLCBuZXdGdWxsRGF0YSwgaW1tdXRhYmxlLCB0cmFuc2l0aW9uLCBuZXdEYXRhUmV2aXNpb24pIHtcbiAgICBpZihvbGRGdWxsRGF0YS5sZW5ndGggIT09IG5ld0Z1bGxEYXRhLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnVsbFJlcGxvdDogdHJ1ZSxcbiAgICAgICAgICAgIGNhbGM6IHRydWVcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgZmxhZ3MgPSBlZGl0VHlwZXMudHJhY2VGbGFncygpO1xuICAgIGZsYWdzLmFycmF5cyA9IHt9O1xuICAgIHZhciBpLCB0cmFjZTtcblxuICAgIGZ1bmN0aW9uIGdldFRyYWNlVmFsT2JqZWN0KHBhcnRzKSB7XG4gICAgICAgIHJldHVybiBQbG90U2NoZW1hLmdldFRyYWNlVmFsT2JqZWN0KHRyYWNlLCBwYXJ0cyk7XG4gICAgfVxuXG4gICAgdmFyIGRpZmZPcHRzID0ge1xuICAgICAgICBnZXRWYWxPYmplY3Q6IGdldFRyYWNlVmFsT2JqZWN0LFxuICAgICAgICBmbGFnczogZmxhZ3MsXG4gICAgICAgIGltbXV0YWJsZTogaW1tdXRhYmxlLFxuICAgICAgICB0cmFuc2l0aW9uOiB0cmFuc2l0aW9uLFxuICAgICAgICBuZXdEYXRhUmV2aXNpb246IG5ld0RhdGFSZXZpc2lvbixcbiAgICAgICAgZ2Q6IGdkXG4gICAgfTtcblxuICAgIHZhciBzZWVuVUlEcyA9IHt9O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgb2xkRnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2UgPSBuZXdGdWxsRGF0YVtpXS5fZnVsbElucHV0O1xuICAgICAgICBpZihQbG90cy5oYXNNYWtlc0RhdGFUcmFuc2Zvcm0odHJhY2UpKSB0cmFjZSA9IG5ld0Z1bGxEYXRhW2ldO1xuICAgICAgICBpZihzZWVuVUlEc1t0cmFjZS51aWRdKSBjb250aW51ZTtcbiAgICAgICAgc2VlblVJRHNbdHJhY2UudWlkXSA9IDE7XG5cbiAgICAgICAgZ2V0RGlmZkZsYWdzKG9sZEZ1bGxEYXRhW2ldLl9mdWxsSW5wdXQsIHRyYWNlLCBbXSwgZGlmZk9wdHMpO1xuICAgIH1cblxuICAgIGlmKGZsYWdzLmNhbGMgfHwgZmxhZ3MucGxvdCkge1xuICAgICAgICBmbGFncy5mdWxsUmVwbG90ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmxhZ3M7XG59XG5cbmZ1bmN0aW9uIGRpZmZMYXlvdXQoZ2QsIG9sZEZ1bGxMYXlvdXQsIG5ld0Z1bGxMYXlvdXQsIGltbXV0YWJsZSwgdHJhbnNpdGlvbikge1xuICAgIHZhciBmbGFncyA9IGVkaXRUeXBlcy5sYXlvdXRGbGFncygpO1xuICAgIGZsYWdzLmFycmF5cyA9IHt9O1xuICAgIGZsYWdzLnJhbmdlc0FsdGVyZWQgPSB7fTtcbiAgICBmbGFncy5hdXRvcmFuZ2VkQXhlcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0VmFsT2JqZWN0KHBhcnRzKSB7XG4gICAgICAgIHJldHVybiBQbG90U2NoZW1hLmdldExheW91dFZhbE9iamVjdChuZXdGdWxsTGF5b3V0LCBwYXJ0cyk7XG4gICAgfVxuXG4gICAgdmFyIGRpZmZPcHRzID0ge1xuICAgICAgICBnZXRWYWxPYmplY3Q6IGdldExheW91dFZhbE9iamVjdCxcbiAgICAgICAgZmxhZ3M6IGZsYWdzLFxuICAgICAgICBpbW11dGFibGU6IGltbXV0YWJsZSxcbiAgICAgICAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbixcbiAgICAgICAgZ2Q6IGdkXG4gICAgfTtcblxuICAgIGdldERpZmZGbGFncyhvbGRGdWxsTGF5b3V0LCBuZXdGdWxsTGF5b3V0LCBbXSwgZGlmZk9wdHMpO1xuXG4gICAgaWYoZmxhZ3MucGxvdCB8fCBmbGFncy5jYWxjKSB7XG4gICAgICAgIGZsYWdzLmxheW91dFJlcGxvdCA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZsYWdzO1xufVxuXG5mdW5jdGlvbiBnZXREaWZmRmxhZ3Mob2xkQ29udGFpbmVyLCBuZXdDb250YWluZXIsIG91dGVycGFydHMsIG9wdHMpIHtcbiAgICB2YXIgdmFsT2JqZWN0LCBrZXksIGFzdHI7XG5cbiAgICB2YXIgZ2V0VmFsT2JqZWN0ID0gb3B0cy5nZXRWYWxPYmplY3Q7XG4gICAgdmFyIGZsYWdzID0gb3B0cy5mbGFncztcbiAgICB2YXIgaW1tdXRhYmxlID0gb3B0cy5pbW11dGFibGU7XG4gICAgdmFyIGluQXJyYXkgPSBvcHRzLmluQXJyYXk7XG4gICAgdmFyIGFycmF5SW5kZXggPSBvcHRzLmFycmF5SW5kZXg7XG5cbiAgICBmdW5jdGlvbiBjaGFuZ2VkKCkge1xuICAgICAgICB2YXIgZWRpdFR5cGUgPSB2YWxPYmplY3QuZWRpdFR5cGU7XG4gICAgICAgIGlmKGluQXJyYXkgJiYgZWRpdFR5cGUuaW5kZXhPZignYXJyYXlkcmF3JykgIT09IC0xKSB7XG4gICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShmbGFncy5hcnJheXNbaW5BcnJheV0sIGFycmF5SW5kZXgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVkaXRUeXBlcy51cGRhdGUoZmxhZ3MsIHZhbE9iamVjdCk7XG5cbiAgICAgICAgLy8gdHJhY2sgYW5pbWF0YWJsZSBjaGFuZ2VzXG4gICAgICAgIGlmKG9wdHMudHJhbnNpdGlvbikge1xuICAgICAgICAgICAgaWYoZmxhZ3MuYW5pbSA9PT0gJ2FsbCcgJiYgIXZhbE9iamVjdC5hbmltKSB7XG4gICAgICAgICAgICAgICAgZmxhZ3MuYW5pbSA9ICdzb21lJztcbiAgICAgICAgICAgIH0gZWxzZSBpZighZmxhZ3MuYW5pbSAmJiB2YWxPYmplY3QuYW5pbSkge1xuICAgICAgICAgICAgICAgIGZsYWdzLmFuaW0gPSAnYWxsJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRyYWNrIGNhcnRlc2lhbiBheGVzIHdpdGggYWx0ZXJlZCByYW5nZXNcbiAgICAgICAgaWYoQVhfUkFOR0VfUkUudGVzdChhc3RyKSB8fCBBWF9BVVRPUkFOR0VfUkUudGVzdChhc3RyKSkge1xuICAgICAgICAgICAgZmxhZ3MucmFuZ2VzQWx0ZXJlZFtvdXRlcnBhcnRzWzBdXSA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmFjayBkYXRhcmV2aXNpb24gY2hhbmdlc1xuICAgICAgICBpZihrZXkgPT09ICdkYXRhcmV2aXNpb24nKSB7XG4gICAgICAgICAgICBmbGFncy5uZXdEYXRhUmV2aXNpb24gPSAxO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmFsT2JqZWN0Q2FuQmVEYXRhQXJyYXkodmFsT2JqZWN0KSB7XG4gICAgICAgIHJldHVybiB2YWxPYmplY3QudmFsVHlwZSA9PT0gJ2RhdGFfYXJyYXknIHx8IHZhbE9iamVjdC5hcnJheU9rO1xuICAgIH1cblxuICAgIGZvcihrZXkgaW4gb2xkQ29udGFpbmVyKSB7XG4gICAgICAgIC8vIHNob3J0LWNpcmN1aXQgYmFzZWQgb24gcHJldmlvdXMgY2FsbHMgb3IgcHJldmlvdXMga2V5cyB0aGF0IGFscmVhZHkgbWF4aW1pemVkIHRoZSBwYXRod2F5XG4gICAgICAgIGlmKGZsYWdzLmNhbGMgJiYgIW9wdHMudHJhbnNpdGlvbikgcmV0dXJuO1xuXG4gICAgICAgIHZhciBvbGRWYWwgPSBvbGRDb250YWluZXJba2V5XTtcbiAgICAgICAgdmFyIG5ld1ZhbCA9IG5ld0NvbnRhaW5lcltrZXldO1xuICAgICAgICB2YXIgcGFydHMgPSBvdXRlcnBhcnRzLmNvbmNhdChrZXkpO1xuICAgICAgICBhc3RyID0gcGFydHMuam9pbignLicpO1xuXG4gICAgICAgIC8vIHRyYWNrIGF1dG8tcmFuZ2VkIGNhcnRlc2lhbiBheGVzLCBjaGFuZ2VkIG9yIG5vdFxuICAgICAgICBpZihBWF9BVVRPUkFOR0VfUkUudGVzdChhc3RyKSAmJiBuZXdWYWwgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZsYWdzLmF1dG9yYW5nZWRBeGVzW291dGVycGFydHNbMF1dID0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGtleS5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2Ygb2xkVmFsID09PSAnZnVuY3Rpb24nIHx8IG9sZFZhbCA9PT0gbmV3VmFsKSBjb250aW51ZTtcblxuICAgICAgICAvLyBGSVhNRTogYXgudGljazAgYW5kIGR0aWNrIGdldCBmaWxsZWQgaW4gZHVyaW5nIHBsb3R0aW5nIChleGNlcHQgZm9yIGdlbyBzdWJwbG90cyksXG4gICAgICAgIC8vIGFuZCB1bmxpa2Ugb3RoZXIgYXV0byB2YWx1ZXMgdGhleSBkb24ndCBtYWtlIGl0IGJhY2sgaW50byB0aGUgaW5wdXQsXG4gICAgICAgIC8vIHNvIG5ld0NvbnRhaW5lciB3b24ndCBoYXZlIHRoZW0uXG4gICAgICAgIGlmKChrZXkgPT09ICd0aWNrMCcgfHwga2V5ID09PSAnZHRpY2snKSAmJiBvdXRlcnBhcnRzWzBdICE9PSAnZ2VvJykge1xuICAgICAgICAgICAgdmFyIHRpY2tNb2RlID0gbmV3Q29udGFpbmVyLnRpY2ttb2RlO1xuICAgICAgICAgICAgaWYodGlja01vZGUgPT09ICdhdXRvJyB8fCB0aWNrTW9kZSA9PT0gJ2FycmF5JyB8fCAhdGlja01vZGUpIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZJWE1FOiBTaW1pbGFybHkgZm9yIGF4aXMgcmFuZ2VzIGZvciAzRFxuICAgICAgICAvLyBjb250b3VyY2FycGV0IGRvZXNuJ3QgSEFWRSB6bWluL3ptYXgsIHRoZXkncmUganVzdCBhdXRvLWFkZGVkLiBJdCBuZWVkcyB0aGVtLlxuICAgICAgICBpZihrZXkgPT09ICdyYW5nZScgJiYgbmV3Q29udGFpbmVyLmF1dG9yYW5nZSkgY29udGludWU7XG4gICAgICAgIGlmKChrZXkgPT09ICd6bWluJyB8fCBrZXkgPT09ICd6bWF4JykgJiYgbmV3Q29udGFpbmVyLnR5cGUgPT09ICdjb250b3VyY2FycGV0JykgY29udGludWU7XG5cbiAgICAgICAgdmFsT2JqZWN0ID0gZ2V0VmFsT2JqZWN0KHBhcnRzKTtcblxuICAgICAgICAvLyBpbiBjYXNlIHR5cGUgY2hhbmdlZCwgd2UgbWF5IG5vdCBldmVuICpoYXZlKiBhIHZhbE9iamVjdC5cbiAgICAgICAgaWYoIXZhbE9iamVjdCkgY29udGludWU7XG5cbiAgICAgICAgaWYodmFsT2JqZWN0Ll9jb21wYXJlQXNKU09OICYmIEpTT04uc3RyaW5naWZ5KG9sZFZhbCkgPT09IEpTT04uc3RyaW5naWZ5KG5ld1ZhbCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2YWxUeXBlID0gdmFsT2JqZWN0LnZhbFR5cGU7XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIHZhciBjYW5CZURhdGFBcnJheSA9IHZhbE9iamVjdENhbkJlRGF0YUFycmF5KHZhbE9iamVjdCk7XG4gICAgICAgIHZhciB3YXNBcnJheSA9IEFycmF5LmlzQXJyYXkob2xkVmFsKTtcbiAgICAgICAgdmFyIG5vd0FycmF5ID0gQXJyYXkuaXNBcnJheShuZXdWYWwpO1xuXG4gICAgICAgIC8vIGhhY2sgZm9yIHRyYWNlcyB0aGF0IG1vZGlmeSB0aGUgZGF0YSBpbiBzdXBwbHlEZWZhdWx0cywgbGlrZVxuICAgICAgICAvLyBjb252ZXJ0aW5nIDFEIHRvIDJEIGFycmF5cywgd2hpY2ggd2lsbCBhbHdheXMgY3JlYXRlIG5ldyBvYmplY3RzXG4gICAgICAgIGlmKHdhc0FycmF5ICYmIG5vd0FycmF5KSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRLZXkgPSAnX2lucHV0XycgKyBrZXk7XG4gICAgICAgICAgICB2YXIgb2xkVmFsSW4gPSBvbGRDb250YWluZXJbaW5wdXRLZXldO1xuICAgICAgICAgICAgdmFyIG5ld1ZhbEluID0gbmV3Q29udGFpbmVyW2lucHV0S2V5XTtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkob2xkVmFsSW4pICYmIG9sZFZhbEluID09PSBuZXdWYWxJbikgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihuZXdWYWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYoY2FuQmVEYXRhQXJyYXkgJiYgd2FzQXJyYXkpIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgZWxzZSBjaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih2YWxPYmplY3QuX2lzTGlua2VkVG9BcnJheSkge1xuICAgICAgICAgICAgdmFyIGFycmF5RWRpdEluZGljZXMgPSBbXTtcbiAgICAgICAgICAgIHZhciBleHRyYUluZGljZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmKCFpbkFycmF5KSBmbGFncy5hcnJheXNba2V5XSA9IGFycmF5RWRpdEluZGljZXM7XG5cbiAgICAgICAgICAgIHZhciBtaW5MZW4gPSBNYXRoLm1pbihvbGRWYWwubGVuZ3RoLCBuZXdWYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBtYXhMZW4gPSBNYXRoLm1heChvbGRWYWwubGVuZ3RoLCBuZXdWYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKG1pbkxlbiAhPT0gbWF4TGVuKSB7XG4gICAgICAgICAgICAgICAgaWYodmFsT2JqZWN0LmVkaXRUeXBlID09PSAnYXJyYXlkcmF3Jykge1xuICAgICAgICAgICAgICAgICAgICBleHRyYUluZGljZXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG1pbkxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZ2V0RGlmZkZsYWdzKG9sZFZhbFtpXSwgbmV3VmFsW2ldLCBwYXJ0cy5jb25jYXQoaSksXG4gICAgICAgICAgICAgICAgICAgIC8vIGFkZCBhcnJheSBpbmRpY2VzLCBidXQgbm90IGlmIHdlJ3JlIGFscmVhZHkgaW4gYW4gYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoe2luQXJyYXk6IGtleSwgYXJyYXlJbmRleDogaX0sIG9wdHMpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcHV0IHRoaXMgYXQgdGhlIGVuZCBzbyB0aGF0IHdlIGtub3cgb3VyIGNvbGxlY3RlZCBhcnJheSBpbmRpY2VzIGFyZSBzb3J0ZWRcbiAgICAgICAgICAgIC8vIGJ1dCB0aGUgY2hlY2sgZm9yIGxlbmd0aCBjaGFuZ2VzIGhhcHBlbnMgdXAgZnJvbnQgc28gd2UgY2FuIHNob3J0LWNpcmN1aXRcbiAgICAgICAgICAgIC8vIGRpZmZpbmcgaWYgYXBwcm9wcmlhdGVcbiAgICAgICAgICAgIGlmKGV4dHJhSW5kaWNlcykge1xuICAgICAgICAgICAgICAgIGZvcihpID0gbWluTGVuOyBpIDwgbWF4TGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYXJyYXlFZGl0SW5kaWNlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCF2YWxUeXBlICYmIExpYi5pc1BsYWluT2JqZWN0KG9sZFZhbCkpIHtcbiAgICAgICAgICAgIGdldERpZmZGbGFncyhvbGRWYWwsIG5ld1ZhbCwgcGFydHMsIG9wdHMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY2FuQmVEYXRhQXJyYXkpIHtcbiAgICAgICAgICAgIGlmKHdhc0FycmF5ICYmIG5vd0FycmF5KSB7XG5cbiAgICAgICAgICAgICAgICAvLyBkb24ndCB0cnkgdG8gZGlmZiB0d28gZGF0YSBhcnJheXMuIElmIGltbXV0YWJsZSB3ZSBrbm93IHRoZSBkYXRhIGNoYW5nZWQsXG4gICAgICAgICAgICAgICAgLy8gaWYgbm90LCBhc3N1bWUgaXQgZGlkbid0IGFuZCBsZXQgYGxheW91dC5kYXRhcmV2aXNpb25gIHRlbGwgdXMgaWYgaXQgZGlkXG4gICAgICAgICAgICAgICAgaWYoaW1tdXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGxvb2sgZm9yIGFuaW1hdGFibGUgYXR0cmlidXRlcyB3aGVuIHRoZSBkYXRhIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpZihpbW11dGFibGUgfHwgb3B0cy5uZXdEYXRhUmV2aXNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYod2FzQXJyYXkgIT09IG5vd0FycmF5KSB7XG4gICAgICAgICAgICAgICAgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGNoYW5nZWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHdhc0FycmF5ICYmIG5vd0FycmF5KSB7XG4gICAgICAgICAgICAvLyBpbmZvIGFycmF5LCBjb2xvcnNjYWxlLCAnYW55JyAtIHRoZXNlIGFyZSBzaG9ydCwganVzdCBzdHJpbmdpZnkuXG4gICAgICAgICAgICAvLyBJIGRvbid0ICp0aGluayogdGhhdCBjb3ZlcnMgdXAgYW55IHJlYWwgZGlmZmVyZW5jZXMgcG9zdC12YWxpZGF0aW9uLCBkb2VzIGl0P1xuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIG5lZWQgdG8gZGl2ZSBpbiAxIChpbmZvX2FycmF5KSBvciAyIChjb2xvcnNjYWxlKSBsZXZlbHMgYW5kIGNvbXBhcmVcbiAgICAgICAgICAgIC8vIGFsbCBlbGVtZW50cy5cbiAgICAgICAgICAgIGlmKG9sZFZhbC5sZW5ndGggIT09IG5ld1ZhbC5sZW5ndGggfHwgU3RyaW5nKG9sZFZhbCkgIT09IFN0cmluZyhuZXdWYWwpKSB7XG4gICAgICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGtleSBpbiBuZXdDb250YWluZXIpIHtcbiAgICAgICAgaWYoIShrZXkgaW4gb2xkQ29udGFpbmVyIHx8IGtleS5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2YgbmV3Q29udGFpbmVyW2tleV0gPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICB2YWxPYmplY3QgPSBnZXRWYWxPYmplY3Qob3V0ZXJwYXJ0cy5jb25jYXQoa2V5KSk7XG5cbiAgICAgICAgICAgIGlmKHZhbE9iamVjdENhbkJlRGF0YUFycmF5KHZhbE9iamVjdCkgJiYgQXJyYXkuaXNBcnJheShuZXdDb250YWluZXJba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBmbGFncy5jYWxjID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGNoYW5nZWQoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLypcbiAqIHNpbXBsZSBkaWZmIGZvciBjb25maWcgLSBmb3Igbm93LCBqdXN0IHRyZWF0IGFsbCBjaGFuZ2VzIGFzIGVxdWl2YWxlbnRcbiAqL1xuZnVuY3Rpb24gZGlmZkNvbmZpZyhvbGRDb25maWcsIG5ld0NvbmZpZykge1xuICAgIHZhciBrZXk7XG5cbiAgICBmb3Ioa2V5IGluIG9sZENvbmZpZykge1xuICAgICAgICBpZihrZXkuY2hhckF0KDApID09PSAnXycpIGNvbnRpbnVlO1xuICAgICAgICB2YXIgb2xkVmFsID0gb2xkQ29uZmlnW2tleV07XG4gICAgICAgIHZhciBuZXdWYWwgPSBuZXdDb25maWdba2V5XTtcbiAgICAgICAgaWYob2xkVmFsICE9PSBuZXdWYWwpIHtcbiAgICAgICAgICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KG9sZFZhbCkgJiYgTGliLmlzUGxhaW5PYmplY3QobmV3VmFsKSkge1xuICAgICAgICAgICAgICAgIGlmKGRpZmZDb25maWcob2xkVmFsLCBuZXdWYWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShvbGRWYWwpICYmIEFycmF5LmlzQXJyYXkobmV3VmFsKSkge1xuICAgICAgICAgICAgICAgIGlmKG9sZFZhbC5sZW5ndGggIT09IG5ld1ZhbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRWYWwubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYob2xkVmFsW2ldICE9PSBuZXdWYWxbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KG9sZFZhbFtpXSkgJiYgTGliLmlzUGxhaW5PYmplY3QobmV3VmFsW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGRpZmZDb25maWcob2xkVmFsW2ldLCBuZXdWYWxbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQW5pbWF0ZSB0byBhIGZyYW1lLCBzZXF1ZW5jZSBvZiBmcmFtZSwgZnJhbWUgZ3JvdXAsIG9yIGZyYW1lIGRlZmluaXRpb25cbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKlxuICogQHBhcmFtIHtzdHJpbmcgb3Igb2JqZWN0IG9yIGFycmF5IG9mIHN0cmluZ3Mgb3IgYXJyYXkgb2Ygb2JqZWN0c30gZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0XG4gKiAgICAgIGEgc2luZ2xlIGZyYW1lLCBhcnJheSBvZiBmcmFtZXMsIG9yIGdyb3VwIHRvIHdoaWNoIHRvIGFuaW1hdGUuIFRoZSBpbnRlbnQgaXNcbiAqICAgICAgaW5mZXJyZWQgYnkgdGhlIHR5cGUgb2YgdGhlIGlucHV0LiBWYWxpZCBpbnB1dHMgYXJlOlxuICpcbiAqICAgICAgLSBzdHJpbmcsIGUuZy4gJ2dyb3VwbmFtZSc6IGFuaW1hdGUgYWxsIGZyYW1lcyBvZiBhIGdpdmVuIGBncm91cGAgaW4gdGhlIG9yZGVyXG4gKiAgICAgICAgICAgIGluIHdoaWNoIHRoZXkgYXJlIGRlZmluZWQgdmlhIGBQbG90bHkuYWRkRnJhbWVzYC5cbiAqXG4gKiAgICAgIC0gYXJyYXkgb2Ygc3RyaW5ncywgZS5nLiBbJ2ZyYW1lMScsIGZyYW1lMiddOiBhIGxpc3Qgb2YgZnJhbWVzIGJ5IG5hbWUgdG8gd2hpY2hcbiAqICAgICAgICAgICAgdG8gYW5pbWF0ZSBpbiBzZXF1ZW5jZVxuICpcbiAqICAgICAgLSBvYmplY3Q6IHtkYXRhOiAuLi59OiBhIGZyYW1lIGRlZmluaXRpb24gdG8gd2hpY2ggdG8gYW5pbWF0ZS4gVGhlIGZyYW1lIGlzIG5vdFxuICogICAgICAgICAgICBhbmQgZG9lcyBub3QgbmVlZCB0byBiZSBhZGRlZCB2aWEgYFBsb3RseS5hZGRGcmFtZXNgLiBJdCBtYXkgY29udGFpbiBhbnkgb2ZcbiAqICAgICAgICAgICAgdGhlIHByb3BlcnRpZXMgb2YgYSBmcmFtZSwgaW5jbHVkaW5nIGBkYXRhYCwgYGxheW91dGAsIGFuZCBgdHJhY2VzYC4gVGhlXG4gKiAgICAgICAgICAgIGZyYW1lIGlzIHVzZWQgYXMgcHJvdmlkZWQgYW5kIGRvZXMgbm90IHVzZSB0aGUgYGJhc2VmcmFtZWAgcHJvcGVydHkuXG4gKlxuICogICAgICAtIGFycmF5IG9mIG9iamVjdHMsIGUuZy4gW3tkYXRhOiAuLi59LCB7ZGF0YTogLi4ufV06IGEgbGlzdCBvZiBmcmFtZSBvYmplY3RzLFxuICogICAgICAgICAgICBlYWNoIGZvbGxvd2luZyB0aGUgc2FtZSBydWxlcyBhcyBhIHNpbmdsZSBgb2JqZWN0YC5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gYW5pbWF0aW9uT3B0c1xuICogICAgICBjb25maWd1cmF0aW9uIGZvciB0aGUgYW5pbWF0aW9uXG4gKi9cbmV4cG9ydHMuYW5pbWF0ZSA9IGZ1bmN0aW9uKGdkLCBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QsIGFuaW1hdGlvbk9wdHMpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICBpZighTGliLmlzUGxvdERpdihnZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ1RoaXMgZWxlbWVudCBpcyBub3QgYSBQbG90bHkgcGxvdDogJyArIGdkICsgJy4gSXRcXCdzIGxpa2VseSB0aGF0IHlvdVxcJ3ZlIGZhaWxlZCAnICtcbiAgICAgICAgICAgICd0byBjcmVhdGUgYSBwbG90IGJlZm9yZSBhbmltYXRpbmcgaXQuIEZvciBtb3JlIGRldGFpbHMsIHNlZSAnICtcbiAgICAgICAgICAgICdodHRwczovL3Bsb3QubHkvamF2YXNjcmlwdC9hbmltYXRpb25zLydcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnMgPSBnZC5fdHJhbnNpdGlvbkRhdGE7XG5cbiAgICAvLyBUaGlzIGlzIHRoZSBxdWV1ZSBvZiBmcmFtZXMgdGhhdCB3aWxsIGJlIGFuaW1hdGVkIGFzIHNvb24gYXMgcG9zc2libGUuIFRoZXlcbiAgICAvLyBhcmUgcG9wcGVkIGltbWVkaWF0ZWx5IHVwb24gdGhlICpzdGFydCogb2YgYSB0cmFuc2l0aW9uOlxuICAgIGlmKCF0cmFucy5fZnJhbWVRdWV1ZSkge1xuICAgICAgICB0cmFucy5fZnJhbWVRdWV1ZSA9IFtdO1xuICAgIH1cblxuICAgIGFuaW1hdGlvbk9wdHMgPSBQbG90cy5zdXBwbHlBbmltYXRpb25EZWZhdWx0cyhhbmltYXRpb25PcHRzKTtcbiAgICB2YXIgdHJhbnNpdGlvbk9wdHMgPSBhbmltYXRpb25PcHRzLnRyYW5zaXRpb247XG4gICAgdmFyIGZyYW1lT3B0cyA9IGFuaW1hdGlvbk9wdHMuZnJhbWU7XG5cbiAgICAvLyBTaW5jZSBmcmFtZXMgYXJlIHBvcHBlZCBpbW1lZGlhdGVseSwgYW4gZW1wdHkgcXVldWUgb25seSBtZWFucyBhbGwgZnJhbWVzIGhhdmVcbiAgICAvLyAqc3RhcnRlZCogdG8gdHJhbnNpdGlvbiwgbm90IHRoYXQgdGhlIGFuaW1hdGlvbiBpcyBjb21wbGV0ZS4gVG8gc29sdmUgdGhhdCxcbiAgICAvLyB0cmFjayBhIHNlcGFyYXRlIGNvdW50ZXIgdGhhdCBpbmNyZW1lbnRzIGF0IHRoZSBzYW1lIHRpbWUgYXMgZnJhbWVzIGFyZSBhZGRlZFxuICAgIC8vIHRvIHRoZSBxdWV1ZSwgYnV0IGRlY3JlbWVudHMgb25seSB3aGVuIHRoZSB0cmFuc2l0aW9uIGlzIGNvbXBsZXRlLlxuICAgIGlmKHRyYW5zLl9mcmFtZVdhaXRpbmdDbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0cmFucy5fZnJhbWVXYWl0aW5nQ250ID0gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRUcmFuc2l0aW9uT3B0cyhpKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhbnNpdGlvbk9wdHMpKSB7XG4gICAgICAgICAgICBpZihpID49IHRyYW5zaXRpb25PcHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uT3B0c1swXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYW5zaXRpb25PcHRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zaXRpb25PcHRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RnJhbWVPcHRzKGkpIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShmcmFtZU9wdHMpKSB7XG4gICAgICAgICAgICBpZihpID49IGZyYW1lT3B0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnJhbWVPcHRzWzBdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnJhbWVPcHRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZyYW1lT3B0cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEV4ZWN1dGUgYSBjYWxsYmFjayBhZnRlciB0aGUgd3JhcHBlciBmdW5jdGlvbiBoYXMgYmVlbiBjYWxsZWQgbiB0aW1lcy5cbiAgICAvLyBUaGlzIGlzIHVzZWQgdG8gZGVmZXIgdGhlIHJlc29sdXRpb24gdW50aWwgYSB0cmFuc2l0aW9uIGhhcyByZXNvdmxlZCAqYW5kKlxuICAgIC8vIHRoZSBmcmFtZSBoYXMgY29tcGxldGVkLiBJZiBpdCdzIG5vdCBkb25lIHRoaXMgd2F5LCB0aGVuIHdlIGdldCBhIHJhY2VcbiAgICAvLyBjb25kaXRpb24gaW4gd2hpY2ggdGhlIGFuaW1hdGlvbiBtaWdodCByZXNvbHZlIGJlZm9yZSBhIHRyYW5zaXRpb24gaXMgY29tcGxldGVcbiAgICAvLyBvciB2aWNlIHZlcnNhLlxuICAgIGZ1bmN0aW9uIGNhbGxiYWNrT25OdGhUaW1lKGNiLCBuKSB7XG4gICAgICAgIHZhciBjbnQgPSAwO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZihjYiAmJiArK2NudCA9PT0gbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZGlzY2FyZEV4aXN0aW5nRnJhbWVzKCkge1xuICAgICAgICAgICAgaWYodHJhbnMuX2ZyYW1lUXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3aGlsZSh0cmFucy5fZnJhbWVRdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dCA9IHRyYW5zLl9mcmFtZVF1ZXVlLnBvcCgpO1xuICAgICAgICAgICAgICAgIGlmKG5leHQub25JbnRlcnJ1cHQpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dC5vbkludGVycnVwdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FuaW1hdGlvbmludGVycnVwdGVkJywgW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcXVldWVGcmFtZXMoZnJhbWVMaXN0KSB7XG4gICAgICAgICAgICBpZihmcmFtZUxpc3QubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmcmFtZUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY29tcHV0ZWRGcmFtZTtcblxuICAgICAgICAgICAgICAgIGlmKGZyYW1lTGlzdFtpXS50eXBlID09PSAnYnluYW1lJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBpdCdzIGEgbmFtZWQgZnJhbWUsIGNvbXB1dGUgaXQ6XG4gICAgICAgICAgICAgICAgICAgIGNvbXB1dGVkRnJhbWUgPSBQbG90cy5jb21wdXRlRnJhbWUoZ2QsIGZyYW1lTGlzdFtpXS5uYW1lKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2Ugd2UgbXVzdCBoYXZlIGJlZW4gZ2l2ZW4gYSBzaW1wbGUgb2JqZWN0LCBzbyB0cmVhdFxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgaW5wdXQgaXRzZWxmIGFzIHRoZSBjb21wdXRlZCBmcmFtZS5cbiAgICAgICAgICAgICAgICAgICAgY29tcHV0ZWRGcmFtZSA9IGZyYW1lTGlzdFtpXS5kYXRhO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBmcmFtZU9wdHMgPSBnZXRGcmFtZU9wdHMoaSk7XG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zaXRpb25PcHRzID0gZ2V0VHJhbnNpdGlvbk9wdHMoaSk7XG5cbiAgICAgICAgICAgICAgICAvLyBJdCBkb2Vzbid0IG1ha2UgbXVjaCBzZW5zZSBmb3IgdGhlIHRyYW5zaXRpb24gZHVyYXRpb24gdG8gYmUgZ3JlYXRlciB0aGFuXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZyYW1lIGR1cmF0aW9uLCBzbyBsaW1pdCBpdDpcbiAgICAgICAgICAgICAgICB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA9IE1hdGgubWluKHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uLCBmcmFtZU9wdHMuZHVyYXRpb24pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5leHRGcmFtZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWU6IGNvbXB1dGVkRnJhbWUsXG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IGZyYW1lTGlzdFtpXS5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZU9wdHM6IGZyYW1lT3B0cyxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbk9wdHM6IHRyYW5zaXRpb25PcHRzLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYoaSA9PT0gZnJhbWVMaXN0Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGxhc3QgZnJhbWUgaW4gdGhpcyAuYW5pbWF0ZSBjYWxsIHN0b3JlcyB0aGUgcHJvbWlzZSByZXNvbHZlXG4gICAgICAgICAgICAgICAgICAgIC8vIGFuZCByZWplY3QgY2FsbGJhY2tzLiBUaGlzIGlzIGhvdyB3ZSBlbnN1cmUgdGhhdCB0aGUgYW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgICAgIC8vIGxvb3AgKHdoaWNoIG1heSBleGlzdCBhcyBhIHJlc3VsdCBvZiBhICpkaWZmZXJlbnQqIC5hbmltYXRlIGNhbGwpXG4gICAgICAgICAgICAgICAgICAgIC8vIHN0aWxsIHJlc29sdmVzIG9yIHJlamVjZHRzIHRoaXMgLmFuaW1hdGUgY2FsbCdzIHByb21pc2UuIG9uY2UgaXQnc1xuICAgICAgICAgICAgICAgICAgICAvLyBjb21wbGV0ZS5cbiAgICAgICAgICAgICAgICAgICAgbmV4dEZyYW1lLm9uQ29tcGxldGUgPSBjYWxsYmFja09uTnRoVGltZShyZXNvbHZlLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dEZyYW1lLm9uSW50ZXJydXB0ID0gcmVqZWN0O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zLl9mcmFtZVF1ZXVlLnB1c2gobmV4dEZyYW1lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IGl0IGFzIG5ldmVyIGhhdmluZyB0cmFuc2l0aW9uZWQgdG8gYSBmcmFtZS4gVGhpcyB3aWxsIGNhdXNlIHRoZSBhbmltYXRpb25cbiAgICAgICAgICAgIC8vIGxvb3AgdG8gaW1tZWRpYXRlbHkgdHJhbnNpdGlvbiB0byB0aGUgbmV4dCBmcmFtZSAod2hpY2gsIGZvciBpbW1lZGlhdGUgbW9kZSxcbiAgICAgICAgICAgIC8vIGlzIHRoZSBmaXJzdCBmcmFtZSBpbiB0aGUgbGlzdCBzaW5jZSBhbGwgb3RoZXJzIHdvdWxkIGhhdmUgYmVlbiBkaXNjYXJkZWRcbiAgICAgICAgICAgIC8vIGJlbG93KVxuICAgICAgICAgICAgaWYoYW5pbWF0aW9uT3B0cy5tb2RlID09PSAnaW1tZWRpYXRlJykge1xuICAgICAgICAgICAgICAgIHRyYW5zLl9sYXN0RnJhbWVBdCA9IC1JbmZpbml0eTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gT25seSBpdCdzIG5vdCBhbHJlYWR5IHJ1bm5pbmcsIHN0YXJ0IGEgUkFGIGxvb3AuIFRoaXMgY291bGQgYmUgYXZvaWRlZCBpbiB0aGVcbiAgICAgICAgICAgIC8vIGNhc2UgdGhhdCB0aGVyZSdzIG9ubHkgb25lIGZyYW1lLCBidXQgaXQgc2lnbmlmaWNhbnRseSBjb21wbGljYXRlZCB0aGUgbG9naWNcbiAgICAgICAgICAgIC8vIGFuZCBvbmx5IHNwZWQgdGhpbmdzIHVwIGJ5IGFib3V0IDUlIG9yIHNvIGZvciBhIGxvcmVueiBhdHRyYWN0b3Igc2ltdWxhdGlvbi5cbiAgICAgICAgICAgIC8vIEl0IHdvdWxkIGJlIGEgZmluZSB0aGluZyB0byBpbXBsZW1lbnQsIGJ1dCB0aGUgYmVuZWZpdCBvZiB0aGF0IG9wdGltaXphdGlvblxuICAgICAgICAgICAgLy8gZG9lc24ndCBzZWVtIHdvcnRoIHRoZSBleHRyYSBjb21wbGV4aXR5LlxuICAgICAgICAgICAgaWYoIXRyYW5zLl9hbmltYXRpb25SYWYpIHtcbiAgICAgICAgICAgICAgICBiZWdpbkFuaW1hdGlvbkxvb3AoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHN0b3BBbmltYXRpb25Mb29wKCkge1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FuaW1hdGVkJyk7XG5cbiAgICAgICAgICAgIC8vIEJlIHN1cmUgdG8gdW5zZXQgYWxzbyBzaW5jZSBpdCdzIGhvdyB3ZSBrbm93IHdoZXRoZXIgYSBsb29wIGlzIGFscmVhZHkgcnVubmluZzpcbiAgICAgICAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSh0cmFucy5fYW5pbWF0aW9uUmFmKTtcbiAgICAgICAgICAgIHRyYW5zLl9hbmltYXRpb25SYWYgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbmV4dEZyYW1lKCkge1xuICAgICAgICAgICAgaWYodHJhbnMuX2N1cnJlbnRGcmFtZSAmJiB0cmFucy5fY3VycmVudEZyYW1lLm9uQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAvLyBFeGVjdXRlIHRoZSBjYWxsYmFjayBhbmQgdW5zZXQgaXQgdG8gZW5zdXJlIGl0IGRvZXNuJ3RcbiAgICAgICAgICAgICAgICAvLyBhY2NpZGVudGFsbHkgZ2V0IGNhbGxlZCB0d2ljZVxuICAgICAgICAgICAgICAgIHRyYW5zLl9jdXJyZW50RnJhbWUub25Db21wbGV0ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbmV3RnJhbWUgPSB0cmFucy5fY3VycmVudEZyYW1lID0gdHJhbnMuX2ZyYW1lUXVldWUuc2hpZnQoKTtcblxuICAgICAgICAgICAgaWYobmV3RnJhbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBTaW5jZSBpdCdzIHNvbWV0aW1lcyBuZWNlc3NhcnkgdG8gZG8gZGVlcCBkaWdnaW5nIGludG8gZnJhbWUgZGF0YSxcbiAgICAgICAgICAgICAgICAvLyB3ZSdsbCBjb25zaWRlciBpdCBub3QgMTAwJSBpbXBvc3NpYmxlIGZvciBudWxscyBvciBudW1iZXJzIHRvIHNuZWFrIHRocm91Z2gsXG4gICAgICAgICAgICAgICAgLy8gc28gY2hlY2sgd2hlbiBjYXN0aW5nIHRoZSBuYW1lLCBqdXN0IHRvIGJlIGFic29sdXRlbHkgY2VydGFpbjpcbiAgICAgICAgICAgICAgICB2YXIgc3RyaW5nTmFtZSA9IG5ld0ZyYW1lLm5hbWUgPyBuZXdGcmFtZS5uYW1lLnRvU3RyaW5nKCkgOiBudWxsO1xuICAgICAgICAgICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9jdXJyZW50RnJhbWUgPSBzdHJpbmdOYW1lO1xuXG4gICAgICAgICAgICAgICAgdHJhbnMuX2xhc3RGcmFtZUF0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICB0cmFucy5fdGltZVRvTmV4dCA9IG5ld0ZyYW1lLmZyYW1lT3B0cy5kdXJhdGlvbjtcblxuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgc2ltcGx5IGNhbGxlZCBhbmQgaXQncyBsZWZ0IHRvIC50cmFuc2l0aW9uIHRvIGRlY2lkZSBob3cgdG8gbWFuYWdlXG4gICAgICAgICAgICAgICAgLy8gaW50ZXJydXB0aW5nIGN1cnJlbnQgdHJhbnNpdGlvbnMuIFRoYXQgbWVhbnMgd2UgZG9uJ3QgbmVlZCB0byB3b3JyeSBhYm91dFxuICAgICAgICAgICAgICAgIC8vIGhvdyBpdCByZXNvbHZlcyBvciB3aGF0IGhhcHBlbnMgYWZ0ZXIgdGhpczpcbiAgICAgICAgICAgICAgICBQbG90cy50cmFuc2l0aW9uKGdkLFxuICAgICAgICAgICAgICAgICAgICBuZXdGcmFtZS5mcmFtZS5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBuZXdGcmFtZS5mcmFtZS5sYXlvdXQsXG4gICAgICAgICAgICAgICAgICAgIGhlbHBlcnMuY29lcmNlVHJhY2VJbmRpY2VzKGdkLCBuZXdGcmFtZS5mcmFtZS50cmFjZXMpLFxuICAgICAgICAgICAgICAgICAgICBuZXdGcmFtZS5mcmFtZU9wdHMsXG4gICAgICAgICAgICAgICAgICAgIG5ld0ZyYW1lLnRyYW5zaXRpb25PcHRzXG4gICAgICAgICAgICAgICAgKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZihuZXdGcmFtZS5vbkNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdGcmFtZS5vbkNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FuaW1hdGluZ2ZyYW1lJywge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBzdHJpbmdOYW1lLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZTogbmV3RnJhbWUuZnJhbWUsXG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWU6IG5ld0ZyYW1lLmZyYW1lT3B0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb246IG5ld0ZyYW1lLnRyYW5zaXRpb25PcHRzLFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBubyBtb3JlIGZyYW1lcywgdGhlbiBzdG9wIHRoZSBSQUYgbG9vcDpcbiAgICAgICAgICAgICAgICBzdG9wQW5pbWF0aW9uTG9vcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gYmVnaW5BbmltYXRpb25Mb29wKCkge1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FuaW1hdGluZycpO1xuXG4gICAgICAgICAgICAvLyBJZiBubyB0aW1lciBpcyBydW5uaW5nLCB0aGVuIHNldCBsYXN0IGZyYW1lID0gbG9uZyBhZ28gc28gdGhhdCB0aGUgbmV4dFxuICAgICAgICAgICAgLy8gZnJhbWUgaXMgaW1tZWRpYXRlbHkgdHJhbnNpdGlvbmVkOlxuICAgICAgICAgICAgdHJhbnMuX2xhc3RGcmFtZUF0ID0gLUluZmluaXR5O1xuICAgICAgICAgICAgdHJhbnMuX3RpbWVUb05leHQgPSAwO1xuICAgICAgICAgICAgdHJhbnMuX3J1bm5pbmdUcmFuc2l0aW9ucyA9IDA7XG4gICAgICAgICAgICB0cmFucy5fY3VycmVudEZyYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgdmFyIGRvRnJhbWUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzICptdXN0KiBiZSByZXF1ZXN0ZWQgYmVmb3JlIG5leHRGcmFtZSBzaW5jZSBuZXh0RnJhbWUgbWF5IGRlY2lkZVxuICAgICAgICAgICAgICAgIC8vIHRvIGNhbmNlbCBpdCBpZiB0aGVyZSdzIG5vdGhpbmcgbW9yZSB0byBhbmltYXRlZDpcbiAgICAgICAgICAgICAgICB0cmFucy5fYW5pbWF0aW9uUmFmID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShkb0ZyYW1lKTtcblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHdlJ3JlIHJlYWR5IGZvciBhIG5ldyBmcmFtZTpcbiAgICAgICAgICAgICAgICBpZihEYXRlLm5vdygpIC0gdHJhbnMuX2xhc3RGcmFtZUF0ID4gdHJhbnMuX3RpbWVUb05leHQpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dEZyYW1lKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgZG9GcmFtZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhpcyBpcyBhbiBhbmltYXRlLWxvY2FsIGNvdW50ZXIgdGhhdCBoZWxwcyBtYXRjaCB1cCBvcHRpb24gaW5wdXQgbGlzdFxuICAgICAgICAvLyBpdGVtcyB3aXRoIHRoZSBwYXJ0aWN1bGFyIGZyYW1lLlxuICAgICAgICB2YXIgY29uZmlnQ291bnRlciA9IDA7XG4gICAgICAgIGZ1bmN0aW9uIHNldFRyYW5zaXRpb25Db25maWcoZnJhbWUpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhbnNpdGlvbk9wdHMpKSB7XG4gICAgICAgICAgICAgICAgaWYoY29uZmlnQ291bnRlciA+PSB0cmFuc2l0aW9uT3B0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWUudHJhbnNpdGlvbk9wdHMgPSB0cmFuc2l0aW9uT3B0c1tjb25maWdDb3VudGVyXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmcmFtZS50cmFuc2l0aW9uT3B0cyA9IHRyYW5zaXRpb25PcHRzWzBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZnJhbWUudHJhbnNpdGlvbk9wdHMgPSB0cmFuc2l0aW9uT3B0cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbmZpZ0NvdW50ZXIrKztcbiAgICAgICAgICAgIHJldHVybiBmcmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpc2FtYmlndWF0ZSB3aGF0J3Mgc29ydCBvZiBmcmFtZXMgaGF2ZSBiZWVuIHJlY2VpdmVkXG4gICAgICAgIHZhciBpLCBmcmFtZTtcbiAgICAgICAgdmFyIGZyYW1lTGlzdCA9IFtdO1xuICAgICAgICB2YXIgYWxsRnJhbWVzID0gZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0ID09PSB1bmRlZmluZWQgfHwgZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0ID09PSBudWxsO1xuICAgICAgICB2YXIgaXNGcmFtZUFycmF5ID0gQXJyYXkuaXNBcnJheShmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QpO1xuICAgICAgICB2YXIgaXNTaW5nbGVGcmFtZSA9ICFhbGxGcmFtZXMgJiYgIWlzRnJhbWVBcnJheSAmJiBMaWIuaXNQbGFpbk9iamVjdChmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QpO1xuXG4gICAgICAgIGlmKGlzU2luZ2xlRnJhbWUpIHtcbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgYSBzaW1wbGUgb2JqZWN0IGhhcyBiZWVuIHBhc3NlZCB0byBhbmltYXRlLlxuICAgICAgICAgICAgZnJhbWVMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgIGRhdGE6IHNldFRyYW5zaXRpb25Db25maWcoTGliLmV4dGVuZEZsYXQoe30sIGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdCkpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmKGFsbEZyYW1lcyB8fCBbJ3N0cmluZycsICdudW1iZXInXS5pbmRleE9mKHR5cGVvZiBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gSW4gdGhpcyBjYXNlLCBudWxsIG9yIHVuZGVmaW5lZCBoYXMgYmVlbiBwYXNzZWQgc28gdGhhdCB3ZSB3YW50IHRvXG4gICAgICAgICAgICAvLyBhbmltYXRlICphbGwqIGN1cnJlbnRseSBkZWZpbmVkIGZyYW1lc1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgdHJhbnMuX2ZyYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZyYW1lID0gdHJhbnMuX2ZyYW1lc1tpXTtcblxuICAgICAgICAgICAgICAgIGlmKCFmcmFtZSkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICBpZihhbGxGcmFtZXMgfHwgU3RyaW5nKGZyYW1lLmdyb3VwKSA9PT0gU3RyaW5nKGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2J5bmFtZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBTdHJpbmcoZnJhbWUubmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBzZXRUcmFuc2l0aW9uQ29uZmlnKHtuYW1lOiBmcmFtZS5uYW1lfSlcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoaXNGcmFtZUFycmF5KSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZnJhbWVPck5hbWUgPSBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3RbaV07XG4gICAgICAgICAgICAgICAgaWYoWydudW1iZXInLCAnc3RyaW5nJ10uaW5kZXhPZih0eXBlb2YgZnJhbWVPck5hbWUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBmcmFtZU9yTmFtZSA9IFN0cmluZyhmcmFtZU9yTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgdGhlcmUncyBhbiBhcnJheSBhbmQgdGhpcyBmcmFtZSBpcyBhIHN0cmluZyBuYW1lOlxuICAgICAgICAgICAgICAgICAgICBmcmFtZUxpc3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnYnluYW1lJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IGZyYW1lT3JOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogc2V0VHJhbnNpdGlvbkNvbmZpZyh7bmFtZTogZnJhbWVPck5hbWV9KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoTGliLmlzUGxhaW5PYmplY3QoZnJhbWVPck5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogc2V0VHJhbnNpdGlvbkNvbmZpZyhMaWIuZXh0ZW5kRmxhdCh7fSwgZnJhbWVPck5hbWUpKVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWZXJpZnkgdGhhdCBhbGwgb2YgdGhlc2UgZnJhbWVzIGFjdHVhbGx5IGV4aXN0OyByZXR1cm4gYW5kIHJlamVjdCBpZiBub3Q6XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGZyYW1lTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZnJhbWUgPSBmcmFtZUxpc3RbaV07XG4gICAgICAgICAgICBpZihmcmFtZS50eXBlID09PSAnYnluYW1lJyAmJiAhdHJhbnMuX2ZyYW1lSGFzaFtmcmFtZS5kYXRhLm5hbWVdKSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ2FuaW1hdGUgZmFpbHVyZTogZnJhbWUgbm90IGZvdW5kOiBcIicgKyBmcmFtZS5kYXRhLm5hbWUgKyAnXCInKTtcbiAgICAgICAgICAgICAgICByZWplY3QoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgbW9kZSBpcyBlaXRoZXIgbmV4dCBvciBpbW1lZGlhdGUsIHRoZW4gYWxsIGN1cnJlbnRseSBxdWV1ZWQgZnJhbWVzIG11c3RcbiAgICAgICAgLy8gYmUgZHVtcGVkIGFuZCB0aGUgY29ycmVzcG9uZGluZyAuYW5pbWF0ZSBwcm9taXNlcyByZWplY3RlZC5cbiAgICAgICAgaWYoWyduZXh0JywgJ2ltbWVkaWF0ZSddLmluZGV4T2YoYW5pbWF0aW9uT3B0cy5tb2RlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGRpc2NhcmRFeGlzdGluZ0ZyYW1lcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYW5pbWF0aW9uT3B0cy5kaXJlY3Rpb24gPT09ICdyZXZlcnNlJykge1xuICAgICAgICAgICAgZnJhbWVMaXN0LnJldmVyc2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjdXJyZW50RnJhbWUgPSBnZC5fZnVsbExheW91dC5fY3VycmVudEZyYW1lO1xuICAgICAgICBpZihjdXJyZW50RnJhbWUgJiYgYW5pbWF0aW9uT3B0cy5mcm9tY3VycmVudCkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IC0xO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnJhbWVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZnJhbWUgPSBmcmFtZUxpc3RbaV07XG4gICAgICAgICAgICAgICAgaWYoZnJhbWUudHlwZSA9PT0gJ2J5bmFtZScgJiYgZnJhbWUubmFtZSA9PT0gY3VycmVudEZyYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaWR4ID4gMCAmJiBpZHggPCBmcmFtZUxpc3QubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIHZhciBmaWx0ZXJlZEZyYW1lTGlzdCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZyYW1lTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBmcmFtZSA9IGZyYW1lTGlzdFtpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZnJhbWVMaXN0W2ldLnR5cGUgIT09ICdieW5hbWUnIHx8IGkgPiBpZHgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcmVkRnJhbWVMaXN0LnB1c2goZnJhbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZyYW1lTGlzdCA9IGZpbHRlcmVkRnJhbWVMaXN0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoZnJhbWVMaXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHF1ZXVlRnJhbWVzKGZyYW1lTGlzdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBjYXNlIHdoZXJlIHRoZXJlIHdlcmUgc2ltcGx5IG5vIGZyYW1lcy4gSXQncyBhIGxpdHRsZSBzdHJhbmdlXG4gICAgICAgICAgICAvLyBzaW5jZSB0aGVyZSdzIG5vdCBtdWNoIHRvIGRvOlxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2FuaW1hdGVkJyk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8qKlxuICogUmVnaXN0ZXIgbmV3IGZyYW1lc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nIGlkIG9yIERPTSBlbGVtZW50fSBnZFxuICogICAgICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqXG4gKiBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IGZyYW1lTGlzdFxuICogICAgICBsaXN0IG9mIGZyYW1lIGRlZmluaXRpb25zLCBpbiB3aGljaCBlYWNoIG9iamVjdCBpbmNsdWRlcyBhbnkgb2Y6XG4gKiAgICAgIC0gbmFtZToge3N0cmluZ30gbmFtZSBvZiBmcmFtZSB0byBhZGRcbiAqICAgICAgLSBkYXRhOiB7YXJyYXkgb2Ygb2JqZWN0c30gdHJhY2UgZGF0YVxuICogICAgICAtIGxheW91dCB7b2JqZWN0fSBsYXlvdXQgZGVmaW5pdGlvblxuICogICAgICAtIHRyYWNlcyB7YXJyYXl9IHRyYWNlIGluZGljZXNcbiAqICAgICAgLSBiYXNlZnJhbWUge3N0cmluZ30gbmFtZSBvZiBmcmFtZSBmcm9tIHdoaWNoIHRoaXMgZnJhbWUgZ2V0cyBkZWZhdWx0c1xuICpcbiAqICBAcGFyYW0ge2FycmF5IG9mIGludGVnZXJzfSBpbmRpY2VzXG4gKiAgICAgIGFuIGFycmF5IG9mIGludGVnZXIgaW5kaWNlcyBtYXRjaGluZyB0aGUgcmVzcGVjdGl2ZSBmcmFtZXMgaW4gYGZyYW1lTGlzdGAuIElmIG5vdFxuICogICAgICBwcm92aWRlZCwgYW4gaW5kZXggd2lsbCBiZSBwcm92aWRlZCBpbiBzZXJpYWwgb3JkZXIuIElmIGFscmVhZHkgdXNlZCwgdGhlIGZyYW1lXG4gKiAgICAgIHdpbGwgYmUgb3ZlcndyaXR0ZW4uXG4gKi9cbmV4cG9ydHMuYWRkRnJhbWVzID0gZnVuY3Rpb24oZ2QsIGZyYW1lTGlzdCwgaW5kaWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGlmKGZyYW1lTGlzdCA9PT0gbnVsbCB8fCBmcmFtZUxpc3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYoIUxpYi5pc1Bsb3REaXYoZ2QpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdUaGlzIGVsZW1lbnQgaXMgbm90IGEgUGxvdGx5IHBsb3Q6ICcgKyBnZCArICcuIEl0XFwncyBsaWtlbHkgdGhhdCB5b3VcXCd2ZSBmYWlsZWQgJyArXG4gICAgICAgICAgICAndG8gY3JlYXRlIGEgcGxvdCBiZWZvcmUgYWRkaW5nIGZyYW1lcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlICcgK1xuICAgICAgICAgICAgJ2h0dHBzOi8vcGxvdC5seS9qYXZhc2NyaXB0L2FuaW1hdGlvbnMvJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIHZhciBpLCBmcmFtZSwgaiwgaWR4O1xuICAgIHZhciBfZnJhbWVzID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXM7XG4gICAgdmFyIF9mcmFtZUhhc2ggPSBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lSGFzaDtcblxuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoZnJhbWVMaXN0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FkZEZyYW1lcyBmYWlsdXJlOiBmcmFtZUxpc3QgbXVzdCBiZSBhbiBBcnJheSBvZiBmcmFtZSBkZWZpbml0aW9ucycgKyBmcmFtZUxpc3QpO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHNvcnRlZCBsaXN0IG9mIGluc2VydGlvbnMgc2luY2Ugd2UgcnVuIGludG8gbG90cyBvZiBwcm9ibGVtcyBpZiB0aGVzZVxuICAgIC8vIGFyZW4ndCBpbiBhc2NlbmRpbmcgb3JkZXIgb2YgaW5kZXg6XG4gICAgLy9cbiAgICAvLyBTdHJpY3RseSBmb3Igc29ydGluZy4gTWFrZSBzdXJlIHRoaXMgaXMgZ3VhcmFudGVlZCB0byBuZXZlciBjb2xsaWRlIHdpdGggYW55XG4gICAgLy8gYWxyZWFkeS1leGlzaXN0aW5nIGluZGljZXM6XG4gICAgdmFyIGJpZ0luZGV4ID0gX2ZyYW1lcy5sZW5ndGggKyBmcmFtZUxpc3QubGVuZ3RoICogMjtcblxuICAgIHZhciBpbnNlcnRpb25zID0gW107XG4gICAgdmFyIF9mcmFtZUhhc2hMb2NhbCA9IHt9O1xuICAgIGZvcihpID0gZnJhbWVMaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChmcmFtZUxpc3RbaV0pKSBjb250aW51ZTtcblxuICAgICAgICAvLyBUaGUgZW50aXJlIGxvZ2ljIGZvciBjaGVja2luZyBmb3IgdGhpcyB0eXBlIG9mIG5hbWUgY29sbGlzaW9uIGNhbiBiZSByZW1vdmVkIG9uY2Ugd2UgbWlncmF0ZSB0byBFUzYgYW5kXG4gICAgICAgIC8vIHVzZSBhIE1hcCBpbnN0ZWFkIG9mIGFuIE9iamVjdCBpbnN0YW5jZSwgYXMgTWFwIGtleXMgYXJlbid0IGNvbnZlcnRlZCB0byBzdHJpbmdzLlxuICAgICAgICB2YXIgbG9va3VwTmFtZSA9IGZyYW1lTGlzdFtpXS5uYW1lO1xuICAgICAgICB2YXIgbmFtZSA9IChfZnJhbWVIYXNoW2xvb2t1cE5hbWVdIHx8IF9mcmFtZUhhc2hMb2NhbFtsb29rdXBOYW1lXSB8fCB7fSkubmFtZTtcbiAgICAgICAgdmFyIG5ld05hbWUgPSBmcmFtZUxpc3RbaV0ubmFtZTtcbiAgICAgICAgdmFyIGNvbGxpc2lvblByZXNlbnQgPSBfZnJhbWVIYXNoW25hbWVdIHx8IF9mcmFtZUhhc2hMb2NhbFtuYW1lXTtcblxuICAgICAgICBpZihuYW1lICYmIG5ld05hbWUgJiYgdHlwZW9mIG5ld05hbWUgPT09ICdudW1iZXInICYmIGNvbGxpc2lvblByZXNlbnQgJiYgbnVtZXJpY05hbWVXYXJuaW5nQ291bnQgPCBudW1lcmljTmFtZVdhcm5pbmdDb3VudExpbWl0KSB7XG4gICAgICAgICAgICBudW1lcmljTmFtZVdhcm5pbmdDb3VudCsrO1xuXG4gICAgICAgICAgICBMaWIud2FybignYWRkRnJhbWVzOiBvdmVyd3JpdGluZyBmcmFtZSBcIicgKyAoX2ZyYW1lSGFzaFtuYW1lXSB8fCBfZnJhbWVIYXNoTG9jYWxbbmFtZV0pLm5hbWUgK1xuICAgICAgICAgICAgICAgICdcIiB3aXRoIGEgZnJhbWUgd2hvc2UgbmFtZSBvZiB0eXBlIFwibnVtYmVyXCIgYWxzbyBlcXVhdGVzIHRvIFwiJyArXG4gICAgICAgICAgICAgICAgbmFtZSArICdcIi4gVGhpcyBpcyB2YWxpZCBidXQgbWF5IHBvdGVudGlhbGx5IGxlYWQgdG8gdW5leHBlY3RlZCAnICtcbiAgICAgICAgICAgICAgICAnYmVoYXZpb3Igc2luY2UgYWxsIHBsb3RseS5qcyBmcmFtZSBuYW1lcyBhcmUgc3RvcmVkIGludGVybmFsbHkgJyArXG4gICAgICAgICAgICAgICAgJ2FzIHN0cmluZ3MuJyk7XG5cbiAgICAgICAgICAgIGlmKG51bWVyaWNOYW1lV2FybmluZ0NvdW50ID09PSBudW1lcmljTmFtZVdhcm5pbmdDb3VudExpbWl0KSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ2FkZEZyYW1lczogVGhpcyBBUEkgY2FsbCBoYXMgeWllbGRlZCB0b28gbWFueSBvZiB0aGVzZSB3YXJuaW5ncy4gJyArXG4gICAgICAgICAgICAgICAgICAgICdGb3IgdGhlIHJlc3Qgb2YgdGhpcyBjYWxsLCBmdXJ0aGVyIHdhcm5pbmdzIGFib3V0IG51bWVyaWMgZnJhbWUgJyArXG4gICAgICAgICAgICAgICAgICAgICduYW1lcyB3aWxsIGJlIHN1cHByZXNzZWQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBfZnJhbWVIYXNoTG9jYWxbbG9va3VwTmFtZV0gPSB7bmFtZTogbG9va3VwTmFtZX07XG5cbiAgICAgICAgaW5zZXJ0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgIGZyYW1lOiBQbG90cy5zdXBwbHlGcmFtZURlZmF1bHRzKGZyYW1lTGlzdFtpXSksXG4gICAgICAgICAgICBpbmRleDogKGluZGljZXMgJiYgaW5kaWNlc1tpXSAhPT0gdW5kZWZpbmVkICYmIGluZGljZXNbaV0gIT09IG51bGwpID8gaW5kaWNlc1tpXSA6IGJpZ0luZGV4ICsgaVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IHRoaXMsIHRha2luZyBub3RlIHRoYXQgdW5kZWZpbmVkIGluc2VydGlvbnMgZW5kIHVwIGF0IHRoZSBlbmQ6XG4gICAgaW5zZXJ0aW9ucy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgaWYoYS5pbmRleCA+IGIuaW5kZXgpIHJldHVybiAtMTtcbiAgICAgICAgaWYoYS5pbmRleCA8IGIuaW5kZXgpIHJldHVybiAxO1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9KTtcblxuICAgIHZhciBvcHMgPSBbXTtcbiAgICB2YXIgcmV2b3BzID0gW107XG4gICAgdmFyIGZyYW1lQ291bnQgPSBfZnJhbWVzLmxlbmd0aDtcblxuICAgIGZvcihpID0gaW5zZXJ0aW9ucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBmcmFtZSA9IGluc2VydGlvbnNbaV0uZnJhbWU7XG5cbiAgICAgICAgaWYodHlwZW9mIGZyYW1lLm5hbWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBMaWIud2FybignV2FybmluZzogYWRkRnJhbWVzIGFjY2VwdHMgZnJhbWVzIHdpdGggbnVtZXJpYyBuYW1lcywgYnV0IHRoZSBudW1iZXJzIGFyZScgK1xuICAgICAgICAgICAgICAgICdpbXBsaWNpdGx5IGNhc3QgdG8gc3RyaW5ncycpO1xuXG4gICAgICAgIH1cblxuICAgICAgICBpZighZnJhbWUubmFtZSkge1xuICAgICAgICAgICAgLy8gUmVwZWF0ZWRseSBhc3NpZ24gYSBkZWZhdWx0IG5hbWUsIGluY3JlbWVudGluZyB0aGUgY291bnRlciBlYWNoIHRpbWUgdW50aWxcbiAgICAgICAgICAgIC8vIHdlIGdldCBhIG5hbWUgdGhhdCdzIG5vdCBpbiB0aGUgaGFzaGVkIGxvb2t1cCB0YWJsZTpcbiAgICAgICAgICAgIHdoaWxlKF9mcmFtZUhhc2hbKGZyYW1lLm5hbWUgPSAnZnJhbWUgJyArIGdkLl90cmFuc2l0aW9uRGF0YS5fY291bnRlcisrKV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoX2ZyYW1lSGFzaFtmcmFtZS5uYW1lXSkge1xuICAgICAgICAgICAgLy8gSWYgZnJhbWUgaXMgcHJlc2VudCwgb3ZlcndyaXRlIGl0cyBkZWZpbml0aW9uOlxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgX2ZyYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKChfZnJhbWVzW2pdIHx8IHt9KS5uYW1lID09PSBmcmFtZS5uYW1lKSBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wcy5wdXNoKHt0eXBlOiAncmVwbGFjZScsIGluZGV4OiBqLCB2YWx1ZTogZnJhbWV9KTtcbiAgICAgICAgICAgIHJldm9wcy51bnNoaWZ0KHt0eXBlOiAncmVwbGFjZScsIGluZGV4OiBqLCB2YWx1ZTogX2ZyYW1lc1tqXX0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGluc2VydCBpdCBhdCB0aGUgZW5kIG9mIHRoZSBsaXN0OlxuICAgICAgICAgICAgaWR4ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oaW5zZXJ0aW9uc1tpXS5pbmRleCwgZnJhbWVDb3VudCkpO1xuXG4gICAgICAgICAgICBvcHMucHVzaCh7dHlwZTogJ2luc2VydCcsIGluZGV4OiBpZHgsIHZhbHVlOiBmcmFtZX0pO1xuICAgICAgICAgICAgcmV2b3BzLnVuc2hpZnQoe3R5cGU6ICdkZWxldGUnLCBpbmRleDogaWR4fSk7XG4gICAgICAgICAgICBmcmFtZUNvdW50Kys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdW5kb0Z1bmMgPSBQbG90cy5tb2RpZnlGcmFtZXMsXG4gICAgICAgIHJlZG9GdW5jID0gUGxvdHMubW9kaWZ5RnJhbWVzLFxuICAgICAgICB1bmRvQXJncyA9IFtnZCwgcmV2b3BzXSxcbiAgICAgICAgcmVkb0FyZ3MgPSBbZ2QsIG9wc107XG5cbiAgICBpZihRdWV1ZSkgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gUGxvdHMubW9kaWZ5RnJhbWVzKGdkLCBvcHMpO1xufTtcblxuLyoqXG4gKiBEZWxldGUgZnJhbWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKlxuICogQHBhcmFtIHthcnJheSBvZiBpbnRlZ2Vyc30gZnJhbWVMaXN0XG4gKiAgICAgIGxpc3Qgb2YgaW50ZWdlciBpbmRpY2VzIG9mIGZyYW1lcyB0byBiZSBkZWxldGVkXG4gKi9cbmV4cG9ydHMuZGVsZXRlRnJhbWVzID0gZnVuY3Rpb24oZ2QsIGZyYW1lTGlzdCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGlmKCFMaWIuaXNQbG90RGl2KGdkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgZWxlbWVudCBpcyBub3QgYSBQbG90bHkgcGxvdDogJyArIGdkKTtcbiAgICB9XG5cbiAgICB2YXIgaSwgaWR4O1xuICAgIHZhciBfZnJhbWVzID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXM7XG4gICAgdmFyIG9wcyA9IFtdO1xuICAgIHZhciByZXZvcHMgPSBbXTtcblxuICAgIGlmKCFmcmFtZUxpc3QpIHtcbiAgICAgICAgZnJhbWVMaXN0ID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IF9mcmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZyYW1lTGlzdC5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnJhbWVMaXN0ID0gZnJhbWVMaXN0LnNsaWNlKDApO1xuICAgIGZyYW1lTGlzdC5zb3J0KCk7XG5cbiAgICBmb3IoaSA9IGZyYW1lTGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBpZHggPSBmcmFtZUxpc3RbaV07XG4gICAgICAgIG9wcy5wdXNoKHt0eXBlOiAnZGVsZXRlJywgaW5kZXg6IGlkeH0pO1xuICAgICAgICByZXZvcHMudW5zaGlmdCh7dHlwZTogJ2luc2VydCcsIGluZGV4OiBpZHgsIHZhbHVlOiBfZnJhbWVzW2lkeF19KTtcbiAgICB9XG5cbiAgICB2YXIgdW5kb0Z1bmMgPSBQbG90cy5tb2RpZnlGcmFtZXMsXG4gICAgICAgIHJlZG9GdW5jID0gUGxvdHMubW9kaWZ5RnJhbWVzLFxuICAgICAgICB1bmRvQXJncyA9IFtnZCwgcmV2b3BzXSxcbiAgICAgICAgcmVkb0FyZ3MgPSBbZ2QsIG9wc107XG5cbiAgICBpZihRdWV1ZSkgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gUGxvdHMubW9kaWZ5RnJhbWVzKGdkLCBvcHMpO1xufTtcblxuLyoqXG4gKiBQdXJnZSBhIGdyYXBoIGNvbnRhaW5lciBkaXYgYmFjayB0byBpdHMgaW5pdGlhbCBwcmUtUGxvdGx5LnBsb3Qgc3RhdGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKi9cbmV4cG9ydHMucHVyZ2UgPSBmdW5jdGlvbiBwdXJnZShnZCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhIHx8IFtdO1xuXG4gICAgLy8gcmVtb3ZlIGdsIGNvbnRleHRzXG4gICAgUGxvdHMuY2xlYW5QbG90KFtdLCB7fSwgZnVsbERhdGEsIGZ1bGxMYXlvdXQpO1xuXG4gICAgLy8gcHVyZ2UgcHJvcGVydGllc1xuICAgIFBsb3RzLnB1cmdlKGdkKTtcblxuICAgIC8vIHB1cmdlIGV2ZW50IGVtaXR0ZXIgbWV0aG9kc1xuICAgIEV2ZW50cy5wdXJnZShnZCk7XG5cbiAgICAvLyByZW1vdmUgcGxvdCBjb250YWluZXJcbiAgICBpZihmdWxsTGF5b3V0Ll9jb250YWluZXIpIGZ1bGxMYXlvdXQuX2NvbnRhaW5lci5yZW1vdmUoKTtcblxuICAgIC8vIGluIGNvbnRyYXN0IHRvIFBsb3RseS5QbG90cy5wdXJnZSB3aGljaCBkb2VzIE5PVCBjbGVhciBfY29udGV4dCFcbiAgICBkZWxldGUgZ2QuX2NvbnRleHQ7XG5cbiAgICByZXR1cm4gZ2Q7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBtYWtlUGxvdEZyYW1ld29yazogQ3JlYXRlIHRoZSBwbG90IGNvbnRhaW5lciBhbmQgYXhlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZnVuY3Rpb24gbWFrZVBsb3RGcmFtZXdvcmsoZ2QpIHtcbiAgICB2YXIgZ2QzID0gZDMuc2VsZWN0KGdkKTtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgLy8gUGxvdCBjb250YWluZXJcbiAgICBmdWxsTGF5b3V0Ll9jb250YWluZXIgPSBnZDMuc2VsZWN0QWxsKCcucGxvdC1jb250YWluZXInKS5kYXRhKFswXSk7XG4gICAgZnVsbExheW91dC5fY29udGFpbmVyLmVudGVyKCkuaW5zZXJ0KCdkaXYnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgLmNsYXNzZWQoJ3Bsb3QtY29udGFpbmVyJywgdHJ1ZSlcbiAgICAgICAgLmNsYXNzZWQoJ3Bsb3RseScsIHRydWUpO1xuXG4gICAgLy8gTWFrZSB0aGUgc3ZnIGNvbnRhaW5lclxuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2ID0gZnVsbExheW91dC5fY29udGFpbmVyLnNlbGVjdEFsbCgnLnN2Zy1jb250YWluZXInKS5kYXRhKFswXSk7XG4gICAgZnVsbExheW91dC5fcGFwZXJkaXYuZW50ZXIoKS5hcHBlbmQoJ2RpdicpXG4gICAgICAgIC5jbGFzc2VkKCdzdmctY29udGFpbmVyJywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdwb3NpdGlvbicsICdyZWxhdGl2ZScpO1xuXG4gICAgLy8gTWFrZSB0aGUgZ3JhcGggY29udGFpbmVyc1xuICAgIC8vIHN0YXJ0IGZyZXNoIGVhY2ggdGltZSB3ZSBnZXQgaGVyZSwgc28gd2Uga25vdyB0aGUgb3JkZXIgY29tZXMgb3V0XG4gICAgLy8gcmlnaHQsIHJhdGhlciB0aGFuIGVudGVyL2V4aXQgd2hpY2ggY2FuIG11Y2sgdXAgdGhlIG9yZGVyXG4gICAgLy8gVE9ETzogc29ydCBvdXQgYWxsIHRoZSBvcmRlcmluZyBzbyB3ZSBkb24ndCBoYXZlIHRvXG4gICAgLy8gZXhwbGljaXRseSBkZWxldGUgYW55dGhpbmdcbiAgICAvLyBGSVhNRTogcGFyY29vcmRzIHJldXNlcyB0aGlzIG9iamVjdCwgbm90IHRoZSBiZXN0IHBhdHRlcm5cbiAgICBmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lciA9IGZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLmdsLWNvbnRhaW5lcicpXG4gICAgICAgIC5kYXRhKFt7fV0pO1xuXG4gICAgZnVsbExheW91dC5fZ2xjb250YWluZXIuZW50ZXIoKS5hcHBlbmQoJ2RpdicpXG4gICAgICAgIC5jbGFzc2VkKCdnbC1jb250YWluZXInLCB0cnVlKTtcblxuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLm1haW4tc3ZnJykucmVtb3ZlKCk7XG5cbiAgICBmdWxsTGF5b3V0Ll9wYXBlciA9IGZ1bGxMYXlvdXQuX3BhcGVyZGl2Lmluc2VydCgnc3ZnJywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgIC5jbGFzc2VkKCdtYWluLXN2ZycsIHRydWUpO1xuXG4gICAgZnVsbExheW91dC5fdG9wcGFwZXIgPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5hcHBlbmQoJ3N2ZycpXG4gICAgICAgIC5jbGFzc2VkKCdtYWluLXN2ZycsIHRydWUpO1xuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX3VpZCkge1xuICAgICAgICB2YXIgb3RoZXJVaWRzID0ge307XG4gICAgICAgIGQzLnNlbGVjdEFsbCgnZGVmcycpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZih0aGlzLmlkKSBvdGhlclVpZHNbdGhpcy5pZC5zcGxpdCgnLScpWzFdXSA9IDE7XG4gICAgICAgIH0pO1xuICAgICAgICBmdWxsTGF5b3V0Ll91aWQgPSBMaWIucmFuZHN0cihvdGhlclVpZHMpO1xuICAgIH1cblxuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLm1haW4tc3ZnJylcbiAgICAgICAgLmF0dHIoeG1sbnNOYW1lc3BhY2VzLnN2Z0F0dHJzKTtcblxuICAgIGZ1bGxMYXlvdXQuX2RlZnMgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2RlZnMnKVxuICAgICAgICAuYXR0cignaWQnLCAnZGVmcy0nICsgZnVsbExheW91dC5fdWlkKTtcblxuICAgIGZ1bGxMYXlvdXQuX2NsaXBzID0gZnVsbExheW91dC5fZGVmcy5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnY2xpcHMnLCB0cnVlKTtcblxuICAgIGZ1bGxMYXlvdXQuX3RvcGRlZnMgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2RlZnMnKVxuICAgICAgICAuYXR0cignaWQnLCAndG9wZGVmcy0nICsgZnVsbExheW91dC5fdWlkKTtcblxuICAgIGZ1bGxMYXlvdXQuX3RvcGNsaXBzID0gZnVsbExheW91dC5fdG9wZGVmcy5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnY2xpcHMnLCB0cnVlKTtcblxuICAgIGZ1bGxMYXlvdXQuX2JnTGF5ZXIgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnYmdsYXllcicsIHRydWUpO1xuXG4gICAgZnVsbExheW91dC5fZHJhZ2dlcnMgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnZHJhZ2xheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBsb3dlciBzaGFwZS9pbWFnZSBsYXllciAtIG5vdGUgdGhhdCB0aGlzIGlzIGJlaGluZFxuICAgIC8vIGFsbCBzdWJwbG90cyBkYXRhL2dyaWRzIGJ1dCBhYm92ZSB0aGUgYmFja2dyb3VuZHNcbiAgICAvLyBleGNlcHQgaW5zZXQgc3VicGxvdHMsIHdob3NlIGJhY2tncm91bmRzIGFyZSBkcmF3blxuICAgIC8vIGluc2lkZSB0aGVpciBvd24gZ3JvdXAgc28gdGhhdCB0aGV5IGFwcGVhciBhYm92ZVxuICAgIC8vIHRoZSBkYXRhIGZvciB0aGUgbWFpbiBzdWJwbG90XG4gICAgLy8gbG93ZXIgc2hhcGVzIGFuZCBpbWFnZXMgd2hpY2ggYXJlIGZ1bGx5IHJlZmVyZW5jZWQgdG9cbiAgICAvLyBhIHN1YnBsb3Qgc3RpbGwgZ2V0IGRyYXduIHdpdGhpbiB0aGUgc3VicGxvdCdzIGdyb3VwXG4gICAgLy8gc28gdGhleSB3aWxsIHdvcmsgY29ycmVjdGx5IG9uIGluc2V0c1xuICAgIHZhciBsYXllckJlbG93ID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2xheWVyLWJlbG93JywgdHJ1ZSk7XG4gICAgZnVsbExheW91dC5faW1hZ2VMb3dlckxheWVyID0gbGF5ZXJCZWxvdy5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnaW1hZ2VsYXllcicsIHRydWUpO1xuICAgIGZ1bGxMYXlvdXQuX3NoYXBlTG93ZXJMYXllciA9IGxheWVyQmVsb3cuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ3NoYXBlbGF5ZXInLCB0cnVlKTtcblxuICAgIC8vIHNpbmdsZSBjYXJ0ZXNpYW4gbGF5ZXIgZm9yIHRoZSB3aG9sZSBwbG90XG4gICAgZnVsbExheW91dC5fY2FydGVzaWFubGF5ZXIgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdjYXJ0ZXNpYW5sYXllcicsIHRydWUpO1xuXG4gICAgLy8gc2luZ2xlIHBvbGFyIGxheWVyIGZvciB0aGUgd2hvbGUgcGxvdFxuICAgIGZ1bGxMYXlvdXQuX3BvbGFybGF5ZXIgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdwb2xhcmxheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBzaW5nbGUgdGVybmFyeSBsYXllciBmb3IgdGhlIHdob2xlIHBsb3RcbiAgICBmdWxsTGF5b3V0Ll90ZXJuYXJ5bGF5ZXIgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd0ZXJuYXJ5bGF5ZXInLCB0cnVlKTtcblxuICAgIC8vIHNpbmdsZSBnZW8gbGF5ZXIgZm9yIHRoZSB3aG9sZSBwbG90XG4gICAgZnVsbExheW91dC5fZ2VvbGF5ZXIgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdnZW9sYXllcicsIHRydWUpO1xuXG4gICAgLy8gc2luZ2xlIHBpZSBsYXllciBmb3IgdGhlIHdob2xlIHBsb3RcbiAgICBmdWxsTGF5b3V0Ll9waWVsYXllciA9IGZ1bGxMYXlvdXQuX3BhcGVyLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3BpZWxheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBmaWxsIGluIGltYWdlIHNlcnZlciBzY3JhcGUtc3ZnXG4gICAgZnVsbExheW91dC5fZ2xpbWFnZXMgPSBmdWxsTGF5b3V0Ll9wYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdnbGltYWdlcycsIHRydWUpO1xuXG4gICAgLy8gbGFzdGx5IHVwcGVyIHNoYXBlcywgaW5mbyAobGVnZW5kLCBhbm5vdGF0aW9ucykgYW5kIGhvdmVyIGxheWVycyBnbyBvbiB0b3BcbiAgICAvLyB0aGVzZSBhcmUgaW4gYSBkaWZmZXJlbnQgc3ZnIGVsZW1lbnQgbm9ybWFsbHksIGJ1dCBnZXQgY29sbGFwc2VkIGludG8gYSBzaW5nbGVcbiAgICAvLyBzdmcgd2hlbiBleHBvcnRpbmcgKGFmdGVyIGluc2VydGluZyAzRClcbiAgICAvLyB1cHBlciBzaGFwZXMvaW1hZ2VzIGFyZSBvbmx5IHRob3NlIGRyYXduIGFib3ZlIHRoZSB3aG9sZSBwbG90LCBpbmNsdWRpbmcgc3VicGxvdHNcbiAgICB2YXIgbGF5ZXJBYm92ZSA9IGZ1bGxMYXlvdXQuX3RvcHBhcGVyLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdsYXllci1hYm92ZScsIHRydWUpO1xuICAgIGZ1bGxMYXlvdXQuX2ltYWdlVXBwZXJMYXllciA9IGxheWVyQWJvdmUuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2ltYWdlbGF5ZXInLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll9zaGFwZVVwcGVyTGF5ZXIgPSBsYXllckFib3ZlLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdzaGFwZWxheWVyJywgdHJ1ZSk7XG5cbiAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdpbmZvbGF5ZXInLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll9tZW51bGF5ZXIgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdtZW51bGF5ZXInLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll96b29tbGF5ZXIgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd6b29tbGF5ZXInLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyID0gZnVsbExheW91dC5fdG9wcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnaG92ZXJsYXllcicsIHRydWUpO1xuXG4gICAgZ2QuZW1pdCgncGxvdGx5X2ZyYW1ld29yaycpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFRoaXMgd2lsbCBiZSB0cmFuc2ZlcnJlZCBvdmVyIHRvIGdkIGFuZCBvdmVycmlkZGVuIGJ5XG4gKiBjb25maWcgYXJncyB0byBQbG90bHkucGxvdC5cbiAqXG4gKiBUaGUgZGVmYXVsdHMgYXJlIHRoZSBhcHByb3ByaWF0ZSBzZXR0aW5ncyBmb3IgcGxvdGx5LmpzLFxuICogc28gd2UgZ2V0IHRoZSByaWdodCBleHBlcmllbmNlIHdpdGhvdXQgYW55IGNvbmZpZyBhcmd1bWVudC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAgIC8vIG5vIGludGVyYWN0aXZpdHksIGZvciBleHBvcnQgb3IgaW1hZ2UgZ2VuZXJhdGlvblxuICAgIHN0YXRpY1Bsb3Q6IGZhbHNlLFxuXG4gICAgLy8gYmFzZSBVUkwgZm9yIHRoZSAnRWRpdCBpbiBDaGFydCBTdHVkaW8nIChha2Egc2VuZERhdGFUb0Nsb3VkKSBtb2RlIGJhciBidXR0b25cbiAgICAvLyBhbmQgdGhlIHNob3dMaW5rL3NlbmREYXRhIG9uLWdyYXBoIGxpbmtcbiAgICBwbG90bHlTZXJ2ZXJVUkw6ICdodHRwczovL3Bsb3QubHknLFxuXG4gICAgLypcbiAgICAgKiB3ZSBjYW4gZWRpdCB0aXRsZXMsIG1vdmUgYW5ub3RhdGlvbnMsIGV0YyAtIHNldHMgYWxsIHBpZWNlcyBvZiBgZWRpdHNgXG4gICAgICogdW5sZXNzIGEgc2VwYXJhdGUgYGVkaXRzYCBjb25maWcgaXRlbSBvdmVycmlkZXMgaW5kaXZpZHVhbCBwYXJ0c1xuICAgICAqL1xuICAgIGVkaXRhYmxlOiBmYWxzZSxcbiAgICBlZGl0czoge1xuICAgICAgICAvKlxuICAgICAgICAgKiBhbm5vdGF0aW9uUG9zaXRpb246IHRoZSBtYWluIGFuY2hvciBvZiB0aGUgYW5ub3RhdGlvbiwgd2hpY2ggaXMgdGhlXG4gICAgICAgICAqIHRleHQgKGlmIG5vIGFycm93KSBvciB0aGUgYXJyb3cgKHdoaWNoIGRyYWdzIHRoZSB3aG9sZSB0aGluZyBsZWF2aW5nXG4gICAgICAgICAqIHRoZSBhcnJvdyBsZW5ndGggJiBkaXJlY3Rpb24gdW5jaGFuZ2VkKVxuICAgICAgICAgKi9cbiAgICAgICAgYW5ub3RhdGlvblBvc2l0aW9uOiBmYWxzZSxcbiAgICAgICAgLy8ganVzdCBmb3IgYW5ub3RhdGlvbnMgd2l0aCBhcnJvd3MsIGNoYW5nZSB0aGUgbGVuZ3RoICBhbmQgZGlyZWN0aW9uIG9mIHRoZSBhcnJvd1xuICAgICAgICBhbm5vdGF0aW9uVGFpbDogZmFsc2UsXG4gICAgICAgIGFubm90YXRpb25UZXh0OiBmYWxzZSxcbiAgICAgICAgYXhpc1RpdGxlVGV4dDogZmFsc2UsXG4gICAgICAgIGNvbG9yYmFyUG9zaXRpb246IGZhbHNlLFxuICAgICAgICBjb2xvcmJhclRpdGxlVGV4dDogZmFsc2UsXG4gICAgICAgIGxlZ2VuZFBvc2l0aW9uOiBmYWxzZSxcbiAgICAgICAgLy8gZWRpdCB0aGUgdHJhY2UgbmFtZSBmaWVsZHMgZnJvbSB0aGUgbGVnZW5kXG4gICAgICAgIGxlZ2VuZFRleHQ6IGZhbHNlLFxuICAgICAgICBzaGFwZVBvc2l0aW9uOiBmYWxzZSxcbiAgICAgICAgLy8gdGhlIGdsb2JhbCBgbGF5b3V0LnRpdGxlYFxuICAgICAgICB0aXRsZVRleHQ6IGZhbHNlXG4gICAgfSxcblxuICAgIC8qXG4gICAgICogRE8gYXV0b3NpemUgb25jZSByZWdhcmRsZXNzIG9mIGxheW91dC5hdXRvc2l6ZVxuICAgICAqICh1c2UgZGVmYXVsdCB3aWR0aCBvciBoZWlnaHQgdmFsdWVzIG90aGVyd2lzZSlcbiAgICAgKi9cbiAgICBhdXRvc2l6YWJsZTogZmFsc2UsXG5cbiAgICAvKlxuICAgICAqIHJlc3BvbnNpdmU6IGRldGVybWluZXMgd2hldGhlciB0byBjaGFuZ2UgdGhlIGxheW91dCBzaXplIHdoZW4gd2luZG93IGlzIHJlc2l6ZWQuXG4gICAgICogSW4gdjIsIHRoaXMgb3B0aW9uIHdpbGwgYmUgcmVtb3ZlZCBhbmQgd2lsbCBhbHdheXMgYmUgdHJ1ZS5cbiAgICAgKi9cbiAgICByZXNwb25zaXZlOiBmYWxzZSxcblxuICAgIC8vIHNldCB0aGUgbGVuZ3RoIG9mIHRoZSB1bmRvL3JlZG8gcXVldWVcbiAgICBxdWV1ZUxlbmd0aDogMCxcblxuICAgIC8vIGlmIHdlIERPIGF1dG9zaXplLCBkbyB3ZSBmaWxsIHRoZSBjb250YWluZXIgb3IgdGhlIHNjcmVlbj9cbiAgICBmaWxsRnJhbWU6IGZhbHNlLFxuXG4gICAgLy8gaWYgd2UgRE8gYXV0b3NpemUsIHNldCB0aGUgZnJhbWUgbWFyZ2lucyBpbiBwZXJjZW50cyBvZiBwbG90IHNpemVcbiAgICBmcmFtZU1hcmdpbnM6IDAsXG5cbiAgICAvLyBtb3VzZXdoZWVsIG9yIHR3by1maW5nZXIgc2Nyb2xsIHpvb21zIHRoZSBwbG90XG4gICAgc2Nyb2xsWm9vbTogZmFsc2UsXG5cbiAgICAvLyBkb3VibGUgY2xpY2sgaW50ZXJhY3Rpb24gKGZhbHNlLCAncmVzZXQnLCAnYXV0b3NpemUnIG9yICdyZXNldCthdXRvc2l6ZScpXG4gICAgZG91YmxlQ2xpY2s6ICdyZXNldCthdXRvc2l6ZScsXG5cbiAgICAvLyBuZXcgdXNlcnMgc2VlIHNvbWUgaGludHMgYWJvdXQgaW50ZXJhY3Rpdml0eVxuICAgIHNob3dUaXBzOiB0cnVlLFxuXG4gICAgLy8gZW5hYmxlIGF4aXMgcGFuL3pvb20gZHJhZyBoYW5kbGVzXG4gICAgc2hvd0F4aXNEcmFnSGFuZGxlczogdHJ1ZSxcblxuICAgIC8qXG4gICAgICogZW5hYmxlIGRpcmVjdCByYW5nZSBlbnRyeSBhdCB0aGUgcGFuL3pvb20gZHJhZyBwb2ludHNcbiAgICAgKiAoZHJhZyBoYW5kbGVzIG11c3QgYmUgZW5hYmxlZCBhYm92ZSlcbiAgICAgKi9cbiAgICBzaG93QXhpc1JhbmdlRW50cnlCb3hlczogdHJ1ZSxcblxuICAgIC8vIGxpbmsgdG8gb3BlbiB0aGlzIHBsb3QgaW4gcGxvdGx5XG4gICAgc2hvd0xpbms6IGZhbHNlLFxuXG4gICAgLy8gaWYgd2Ugc2hvdyBhIGxpbmssIGRvZXMgaXQgY29udGFpbiBkYXRhIG9yIGp1c3QgbGluayB0byBhIHBsb3RseSBmaWxlP1xuICAgIHNlbmREYXRhOiB0cnVlLFxuXG4gICAgLy8gdGV4dCBhcHBlYXJpbmcgaW4gdGhlIHNlbmREYXRhIGxpbmtcbiAgICBsaW5rVGV4dDogJ0VkaXQgY2hhcnQnLFxuXG4gICAgLy8gZmFsc2Ugb3IgZnVuY3Rpb24gYWRkaW5nIHNvdXJjZShzKSB0byBsaW5rVGV4dCA8dGV4dD5cbiAgICBzaG93U291cmNlczogZmFsc2UsXG5cbiAgICAvLyBkaXNwbGF5IHRoZSBtb2RlIGJhciAodHJ1ZSwgZmFsc2UsIG9yICdob3ZlcicpXG4gICAgZGlzcGxheU1vZGVCYXI6ICdob3ZlcicsXG5cbiAgICAvKlxuICAgICAqIHJlbW92ZSBtb2RlIGJhciBidXR0b24gYnkgbmFtZVxuICAgICAqIChzZWUgLi4vY29tcG9uZW50cy9tb2RlYmFyL2J1dHRvbnMuanMgZm9yIHRoZSBsaXN0IG9mIG5hbWVzKVxuICAgICAqL1xuICAgIG1vZGVCYXJCdXR0b25zVG9SZW1vdmU6IFtdLFxuXG4gICAgLypcbiAgICAgKiBhZGQgbW9kZSBiYXIgYnV0dG9uIHVzaW5nIGNvbmZpZyBvYmplY3RzXG4gICAgICogKHNlZSAuL2NvbXBvbmVudHMvbW9kZWJhci9idXR0b25zLmpzIGZvciBsaXN0IG9mIGFyZ3VtZW50cylcbiAgICAgKi9cbiAgICBtb2RlQmFyQnV0dG9uc1RvQWRkOiBbXSxcblxuICAgIC8qXG4gICAgICogZnVsbHkgY3VzdG9tIG1vZGUgYmFyIGJ1dHRvbnMgYXMgbmVzdGVkIGFycmF5LFxuICAgICAqIHdoZXJlIHRoZSBvdXRlciBhcnJheXMgcmVwcmVzZW50cyBidXR0b24gZ3JvdXBzLCBhbmRcbiAgICAgKiB0aGUgaW5uZXIgYXJyYXlzIGhhdmUgYnV0dG9ucyBjb25maWcgb2JqZWN0cyBvciBuYW1lcyBvZiBkZWZhdWx0IGJ1dHRvbnNcbiAgICAgKiAoc2VlIC4uL2NvbXBvbmVudHMvbW9kZWJhci9idXR0b25zLmpzIGZvciBtb3JlIGluZm8pXG4gICAgICovXG4gICAgbW9kZUJhckJ1dHRvbnM6IGZhbHNlLFxuXG4gICAgLy8gc3RhdGljYWxseSBvdmVycmlkZSBvcHRpb25zIGZvciB0b0ltYWdlIG1vZGViYXIgYnV0dG9uXG4gICAgLy8gYWxsb3dlZCBrZXlzIGFyZSBmb3JtYXQsIGZpbGVuYW1lLCB3aWR0aCwgaGVpZ2h0LCBzY2FsZVxuICAgIC8vIHNlZSAuLi9jb21wb25lbnRzL21vZGViYXIvYnV0dG9ucy5qc1xuICAgIHRvSW1hZ2VCdXR0b25PcHRpb25zOiB7fSxcblxuICAgIC8vIGFkZCB0aGUgcGxvdGx5IGxvZ28gb24gdGhlIGVuZCBvZiB0aGUgbW9kZSBiYXJcbiAgICBkaXNwbGF5bG9nbzogdHJ1ZSxcblxuICAgIC8vIGluY3JlYXNlIHRoZSBwaXhlbCByYXRpbyBmb3IgR2wgcGxvdCBpbWFnZXNcbiAgICBwbG90R2xQaXhlbFJhdGlvOiAyLFxuXG4gICAgLypcbiAgICAgKiBiYWNrZ3JvdW5kIHNldHRpbmcgZnVuY3Rpb25cbiAgICAgKiAndHJhbnNwYXJlbnQnIHNldHMgdGhlIGJhY2tncm91bmQgYGxheW91dC5wYXBlcl9jb2xvcmBcbiAgICAgKiAnb3BhcXVlJyBibGVuZHMgYmcgY29sb3Igd2l0aCB3aGl0ZSBlbnN1cmluZyBhbiBvcGFxdWUgYmFja2dyb3VuZFxuICAgICAqIG9yIGFueSBvdGhlciBjdXN0b20gZnVuY3Rpb24gb2YgZ2RcbiAgICAgKi9cbiAgICBzZXRCYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnLFxuXG4gICAgLy8gVVJMIHRvIHRvcG9qc29uIGZpbGVzIHVzZWQgaW4gZ2VvIGNoYXJ0c1xuICAgIHRvcG9qc29uVVJMOiAnaHR0cHM6Ly9jZG4ucGxvdC5seS8nLFxuXG4gICAgLypcbiAgICAgKiBNYXBib3ggYWNjZXNzIHRva2VuIChyZXF1aXJlZCB0byBwbG90IG1hcGJveCB0cmFjZSB0eXBlcylcbiAgICAgKiBJZiB1c2luZyBhbiBNYXBib3ggQXRsYXMgc2VydmVyLCBzZXQgdGhpcyBvcHRpb24gdG8gJycsXG4gICAgICogc28gdGhhdCBwbG90bHkuanMgd29uJ3QgYXR0ZW1wdCB0byBhdXRoZW50aWNhdGUgdG8gdGhlIHB1YmxpYyBNYXBib3ggc2VydmVyLlxuICAgICAqL1xuICAgIG1hcGJveEFjY2Vzc1Rva2VuOiBudWxsLFxuXG4gICAgLypcbiAgICAgKiBUdXJuIGFsbCBjb25zb2xlIGxvZ2dpbmcgb24gb3Igb2ZmIChlcnJvcnMgd2lsbCBiZSB0aHJvd24pXG4gICAgICogVGhpcyBzaG91bGQgT05MWSBiZSBzZXQgdmlhIFBsb3RseS5zZXRQbG90Q29uZmlnXG4gICAgICogMDogbm8gbG9nc1xuICAgICAqIDE6IHdhcm5pbmdzIGFuZCBlcnJvcnMsIGJ1dCBub3QgaW5mb3JtYXRpb25hbCBtZXNzYWdlc1xuICAgICAqIDI6IHZlcmJvc2UgbG9nc1xuICAgICAqL1xuICAgIGxvZ2dpbmc6IDEsXG5cbiAgICAvKlxuICAgICAqIFNldCBnbG9iYWwgdHJhbnNmb3JtIHRvIGJlIGFwcGxpZWQgdG8gYWxsIHRyYWNlcyB3aXRoIG5vXG4gICAgICogc3BlY2lmaWNhdGlvbiBuZWVkZWRcbiAgICAgKi9cbiAgICBnbG9iYWxUcmFuc2Zvcm1zOiBbXSxcblxuICAgIC8qXG4gICAgICogV2hpY2ggbG9jYWxpemF0aW9uIHNob3VsZCB3ZSB1c2U/XG4gICAgICogU2hvdWxkIGJlIGEgc3RyaW5nIGxpa2UgJ2VuJyBvciAnZW4tVVMnLlxuICAgICAqL1xuICAgIGxvY2FsZTogJ2VuLVVTJyxcblxuICAgIC8qXG4gICAgICogTG9jYWxpemF0aW9uIGRlZmluaXRpb25zXG4gICAgICogTG9jYWxlcyBjYW4gYmUgcHJvdmlkZWQgZWl0aGVyIGhlcmUgKHNwZWNpZmljIHRvIG9uZSBjaGFydCkgb3IgZ2xvYmFsbHlcbiAgICAgKiBieSByZWdpc3RlcmluZyB0aGVtIGFzIG1vZHVsZXMuXG4gICAgICogU2hvdWxkIGJlIGFuIG9iamVjdCBvZiBvYmplY3RzIHtsb2NhbGU6IHtkaWN0aW9uYXJ5OiB7Li4ufSwgZm9ybWF0OiB7Li4ufX19XG4gICAgICoge1xuICAgICAqICAgICBkYToge1xuICAgICAqICAgICAgICAgZGljdGlvbmFyeTogeydSZXNldCBheGVzJzogJ051bHN0aWwgYWtzbGVyJywgLi4ufSxcbiAgICAgKiAgICAgICAgIGZvcm1hdDoge21vbnRoczogWy4uLl0sIHNob3J0TW9udGhzOiBbLi4uXX1cbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgLi4uXG4gICAgICogfVxuICAgICAqIEFsbCBwYXJ0cyBhcmUgb3B0aW9uYWwuIFdoZW4gbG9va2luZyBmb3IgdHJhbnNsYXRpb24gb3IgZm9ybWF0IGZpZWxkcywgd2VcbiAgICAgKiBsb29rIGZpcnN0IGZvciBhbiBleGFjdCBtYXRjaCBpbiBhIGNvbmZpZyBsb2NhbGUsIHRoZW4gaW4gYSByZWdpc3RlcmVkXG4gICAgICogbW9kdWxlLiBJZiB0aG9zZSBmYWlsLCB3ZSBzdHJpcCBvZmYgYW55IHJlZ2lvbmFsaXphdGlvbiAoJ2VuLVVTJyAtPiAnZW4nKVxuICAgICAqIGFuZCB0cnkgZWFjaCAoY29uZmlnLCByZWdpc3RyeSkgYWdhaW4uIFRoZSBmaW5hbCBmYWxsYmFjayBmb3IgdHJhbnNsYXRpb25cbiAgICAgKiBpcyB1bnRyYW5zbGF0ZWQgKHdoaWNoIGlzIFVTIEVuZ2xpc2gpIGFuZCBmb3IgZm9ybWF0cyBpcyB0aGUgYmFzZSBFbmdsaXNoXG4gICAgICogKHRoZSBvbmx5IGNvbnNlcXVlbmNlIGJlaW5nIHRoZSBsYXN0IGZhbGxiYWNrIGRhdGUgZm9ybWF0ICV4IGlzIEREL01NL1lZWVlcbiAgICAgKiBpbnN0ZWFkIG9mIE1NL0REL1lZWVkpLiBDdXJyZW50bHkgYGdyb3VwaW5nYCBhbmQgYGN1cnJlbmN5YCBhcmUgaWdub3JlZFxuICAgICAqIGZvciBvdXIgYXV0b21hdGljIG51bWJlciBmb3JtYXR0aW5nLCBidXQgY2FuIGJlIHVzZWQgaW4gY3VzdG9tIGZvcm1hdHMuXG4gICAgICovXG4gICAgbG9jYWxlczoge31cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcblxudmFyIGJhc2VBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGJhc2VMYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vcGxvdHMvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBmcmFtZUF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi9wbG90cy9mcmFtZV9hdHRyaWJ1dGVzJyk7XG52YXIgYW5pbWF0aW9uQXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2FuaW1hdGlvbl9hdHRyaWJ1dGVzJyk7XG5cbi8vIHBvbGFyIGF0dHJpYnV0ZXMgYXJlIG5vdCBwYXJ0IG9mIHRoZSBSZWdpc3RyeSB5ZXRcbnZhciBwb2xhckFyZWFBdHRycyA9IHJlcXVpcmUoJy4uL3Bsb3RzL3BvbGFyL2xlZ2FjeS9hcmVhX2F0dHJpYnV0ZXMnKTtcbnZhciBwb2xhckF4aXNBdHRycyA9IHJlcXVpcmUoJy4uL3Bsb3RzL3BvbGFyL2xlZ2FjeS9heGlzX2F0dHJpYnV0ZXMnKTtcblxudmFyIGVkaXRUeXBlcyA9IHJlcXVpcmUoJy4vZWRpdF90eXBlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IExpYi5leHRlbmRGbGF0O1xudmFyIGV4dGVuZERlZXBBbGwgPSBMaWIuZXh0ZW5kRGVlcEFsbDtcbnZhciBpc1BsYWluT2JqZWN0ID0gTGliLmlzUGxhaW5PYmplY3Q7XG5cbnZhciBJU19TVUJQTE9UX09CSiA9ICdfaXNTdWJwbG90T2JqJztcbnZhciBJU19MSU5LRURfVE9fQVJSQVkgPSAnX2lzTGlua2VkVG9BcnJheSc7XG52YXIgQVJSQVlfQVRUUl9SRUdFWFBTID0gJ19hcnJheUF0dHJSZWdleHBzJztcbnZhciBERVBSRUNBVEVEID0gJ19kZXByZWNhdGVkJztcbnZhciBVTkRFUlNDT1JFX0FUVFJTID0gW0lTX1NVQlBMT1RfT0JKLCBJU19MSU5LRURfVE9fQVJSQVksIEFSUkFZX0FUVFJfUkVHRVhQUywgREVQUkVDQVRFRF07XG5cbmV4cG9ydHMuSVNfU1VCUExPVF9PQkogPSBJU19TVUJQTE9UX09CSjtcbmV4cG9ydHMuSVNfTElOS0VEX1RPX0FSUkFZID0gSVNfTElOS0VEX1RPX0FSUkFZO1xuZXhwb3J0cy5ERVBSRUNBVEVEID0gREVQUkVDQVRFRDtcbmV4cG9ydHMuVU5ERVJTQ09SRV9BVFRSUyA9IFVOREVSU0NPUkVfQVRUUlM7XG5cbi8qKiBPdXRwdXRzIHRoZSBmdWxsIHBsb3RseS5qcyBwbG90IHNjaGVtYVxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICAtIGRlZnNcbiAqICAtIHRyYWNlc1xuICogIC0gbGF5b3V0XG4gKiAgLSB0cmFuc2Zvcm1zXG4gKiAgLSBmcmFtZXNcbiAqICAtIGFuaW1hdGlvbnNcbiAqICAtIGNvbmZpZyAoY29taW5nIHNvb24gLi4uKVxuICovXG5leHBvcnRzLmdldCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0cmFjZXMgPSB7fTtcblxuICAgIFJlZ2lzdHJ5LmFsbFR5cGVzLmNvbmNhdCgnYXJlYScpLmZvckVhY2goZnVuY3Rpb24odHlwZSkge1xuICAgICAgICB0cmFjZXNbdHlwZV0gPSBnZXRUcmFjZUF0dHJpYnV0ZXModHlwZSk7XG4gICAgfSk7XG5cbiAgICB2YXIgdHJhbnNmb3JtcyA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoUmVnaXN0cnkudHJhbnNmb3Jtc1JlZ2lzdHJ5KS5mb3JFYWNoKGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgdHJhbnNmb3Jtc1t0eXBlXSA9IGdldFRyYW5zZm9ybUF0dHJpYnV0ZXModHlwZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiB7XG4gICAgICAgICAgICB2YWxPYmplY3RzOiBMaWIudmFsT2JqZWN0TWV0YSxcbiAgICAgICAgICAgIG1ldGFLZXlzOiBVTkRFUlNDT1JFX0FUVFJTLmNvbmNhdChbJ2Rlc2NyaXB0aW9uJywgJ3JvbGUnLCAnZWRpdFR5cGUnLCAnaW1wbGllZEVkaXRzJ10pLFxuICAgICAgICAgICAgZWRpdFR5cGU6IHtcbiAgICAgICAgICAgICAgICB0cmFjZXM6IGVkaXRUeXBlcy50cmFjZXMsXG4gICAgICAgICAgICAgICAgbGF5b3V0OiBlZGl0VHlwZXMubGF5b3V0XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgdHJhY2VzOiB0cmFjZXMsXG4gICAgICAgIGxheW91dDogZ2V0TGF5b3V0QXR0cmlidXRlcygpLFxuXG4gICAgICAgIHRyYW5zZm9ybXM6IHRyYW5zZm9ybXMsXG5cbiAgICAgICAgZnJhbWVzOiBnZXRGcmFtZXNBdHRyaWJ1dGVzKCksXG4gICAgICAgIGFuaW1hdGlvbjogZm9ybWF0QXR0cmlidXRlcyhhbmltYXRpb25BdHRyaWJ1dGVzKVxuICAgIH07XG59O1xuXG4vKipcbiAqIENyYXdsIHRoZSBhdHRyaWJ1dGUgdHJlZSwgcmVjdXJzaXZlbHkgY2FsbGluZyBhIGNhbGxiYWNrIGZ1bmN0aW9uXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGF0dHJzXG4gKiAgVGhlIG5vZGUgb2YgdGhlIGF0dHJpYnV0ZSB0cmVlIChlLmcuIHRoZSByb290KSBmcm9tIHdoaWNoIHJlY3Vyc2lvbiBvcmlnaW5hdGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICogIEEgY2FsbGJhY2sgZnVuY3Rpb24gd2l0aCB0aGUgc2lnbmF0dXJlOlxuICogICAgICAgICAgQGNhbGxiYWNrIGNhbGxiYWNrXG4gKiAgICAgICAgICBAcGFyYW0ge29iamVjdH0gYXR0ciBhbiBhdHRyaWJ1dGVcbiAqICAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBhdHRyTmFtZSBuYW1lIHN0cmluZ1xuICogICAgICAgICAgQHBhcmFtIHtvYmplY3RbXX0gYXR0cnMgYWxsIHRoZSBhdHRyaWJ1dGVzXG4gKiAgICAgICAgICBAcGFyYW0ge051bWJlcn0gbGV2ZWwgdGhlIHJlY3Vyc2lvbiBsZXZlbCwgMCBhdCB0aGUgcm9vdFxuICogICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxBdHRyU3RyaW5nIGZ1bGwgYXR0cmlidXRlIG5hbWUgKGllICdtYXJrZXIubGluZScpXG4gKiBAcGFyYW0ge051bWJlcn0gW3NwZWNpZmllZExldmVsXVxuICogIFRoZSBsZXZlbCBpbiB0aGUgdHJlZSwgaW4gb3JkZXIgdG8gbGV0IHRoZSBjYWxsYmFjayBmdW5jdGlvbiBkZXRlY3QgZGVzY2VuZCBvciBiYWNrdHJhY2ssXG4gKiAgdHlwaWNhbGx5IHVuc3VwcGxpZWQgKGltcGxpZWQgMCksIGp1c3QgdXNlZCBieSB0aGUgc2VsZi1yZWN1cnNpdmUgY2FsbC5cbiAqICBUaGUgbmVjZXNzaXR5IGFyaXNlcyBiZWNhdXNlIHRoZSB0cmVlIHRyYXZlcnNhbCBpcyBub3QgY29udHJvbGxlZCBieSBjYWxsYmFjayByZXR1cm4gdmFsdWVzLlxuICogIFRoZSBkZWNpc2lvbiB0byBub3QgdXNlIGNhbGxiYWNrIHJldHVybiB2YWx1ZXMgZm9yIGNvbnRyb2xsaW5nIHRyZWUgcHJ1bmluZyBhcm9zZSBmcm9tXG4gKiAgdGhlIGdvYWwgb2Yga2VlcGluZyB0aGUgY3Jhd2xlciBiYWNrd2FyZHMgY29tcGF0aWJsZS4gT2JzZXJ2ZSB0aGF0IG9uZSBvZiB0aGUgcHJ1bmluZyBjb25kaXRpb25zXG4gKiAgcHJlY2VkZXMgdGhlIGNhbGxiYWNrIGNhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2F0dHJTdHJpbmddXG4gKiAgdGhlIHBhdGggdG8gdGhlIGN1cnJlbnQgYXR0cmlidXRlLCBhcyBhbiBhdHRyaWJ1dGUgc3RyaW5nIChpZSAnbWFya2VyLmxpbmUnKVxuICogIHR5cGljYWxseSB1bnN1cHBsaWVkLCBidXQgeW91IG1heSBzdXBwbHkgaXQgaWYgeW91IHdhbnQgdG8gZGlzYW1iaWd1YXRlIHdoaWNoIGF0dHJzIHRyZWUgeW91XG4gKiAgYXJlIHN0YXJ0aW5nIGZyb21cbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IHRyYW5zZm9ybU91dFxuICogIGNvcHkgb2YgdHJhbnNmb3JtSW4gdGhhdCBjb250YWlucyBhdHRyaWJ1dGUgZGVmYXVsdHNcbiAqL1xuZXhwb3J0cy5jcmF3bCA9IGZ1bmN0aW9uKGF0dHJzLCBjYWxsYmFjaywgc3BlY2lmaWVkTGV2ZWwsIGF0dHJTdHJpbmcpIHtcbiAgICB2YXIgbGV2ZWwgPSBzcGVjaWZpZWRMZXZlbCB8fCAwO1xuICAgIGF0dHJTdHJpbmcgPSBhdHRyU3RyaW5nIHx8ICcnO1xuXG4gICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goZnVuY3Rpb24oYXR0ck5hbWUpIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1thdHRyTmFtZV07XG5cbiAgICAgICAgaWYoVU5ERVJTQ09SRV9BVFRSUy5pbmRleE9mKGF0dHJOYW1lKSAhPT0gLTEpIHJldHVybjtcblxuICAgICAgICB2YXIgZnVsbEF0dHJTdHJpbmcgPSAoYXR0clN0cmluZyA/IGF0dHJTdHJpbmcgKyAnLicgOiAnJykgKyBhdHRyTmFtZTtcbiAgICAgICAgY2FsbGJhY2soYXR0ciwgYXR0ck5hbWUsIGF0dHJzLCBsZXZlbCwgZnVsbEF0dHJTdHJpbmcpO1xuXG4gICAgICAgIGlmKGV4cG9ydHMuaXNWYWxPYmplY3QoYXR0cikpIHJldHVybjtcblxuICAgICAgICBpZihpc1BsYWluT2JqZWN0KGF0dHIpICYmIGF0dHJOYW1lICE9PSAnaW1wbGllZEVkaXRzJykge1xuICAgICAgICAgICAgZXhwb3J0cy5jcmF3bChhdHRyLCBjYWxsYmFjaywgbGV2ZWwgKyAxLCBmdWxsQXR0clN0cmluZyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8qKiBJcyBvYmplY3QgYSB2YWx1ZSBvYmplY3QgKG9yIGEgY29udGFpbmVyIG9iamVjdCk/XG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9ialxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqICByZXR1cm5zIHRydWUgZm9yIGEgdmFsaWQgdmFsdWUgb2JqZWN0IGFuZFxuICogIGZhbHNlIGZvciB0cmVlIG5vZGVzIGluIHRoZSBhdHRyaWJ1dGUgaGllcmFyY2h5XG4gKi9cbmV4cG9ydHMuaXNWYWxPYmplY3QgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai52YWxUeXBlICE9PSB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIEZpbmQgYWxsIGRhdGEgYXJyYXkgYXR0cmlidXRlcyBpbiBhIGdpdmVuIHRyYWNlIG9iamVjdCAtIGluY2x1ZGluZ1xuICogYGFycmF5T2tgIGF0dHJpYnV0ZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiAgZnVsbCB0cmFjZSBvYmplY3QgdGhhdCBjb250YWlucyBhIHJlZmVyZW5jZSB0byBgX21vZHVsZS5hdHRyaWJ1dGVzYFxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBhcnJheUF0dHJpYnV0ZXNcbiAqICBsaXN0IG9mIGFycmF5IGF0dHJpYnV0ZXMgZm9yIHRoZSBnaXZlbiB0cmFjZVxuICovXG5leHBvcnRzLmZpbmRBcnJheUF0dHJpYnV0ZXMgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBhcnJheUF0dHJpYnV0ZXMgPSBbXTtcbiAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICB2YXIgaXNBcnJheVN0YWNrID0gW107XG4gICAgdmFyIGJhc2VDb250YWluZXIsIGJhc2VBdHRyTmFtZTtcblxuICAgIGZ1bmN0aW9uIGNhbGxiYWNrKGF0dHIsIGF0dHJOYW1lLCBhdHRycywgbGV2ZWwpIHtcbiAgICAgICAgc3RhY2sgPSBzdGFjay5zbGljZSgwLCBsZXZlbCkuY29uY2F0KFthdHRyTmFtZV0pO1xuICAgICAgICBpc0FycmF5U3RhY2sgPSBpc0FycmF5U3RhY2suc2xpY2UoMCwgbGV2ZWwpLmNvbmNhdChbYXR0ciAmJiBhdHRyLl9pc0xpbmtlZFRvQXJyYXldKTtcblxuICAgICAgICB2YXIgc3BsaXR0YWJsZUF0dHIgPSAoXG4gICAgICAgICAgICBhdHRyICYmXG4gICAgICAgICAgICAoYXR0ci52YWxUeXBlID09PSAnZGF0YV9hcnJheScgfHwgYXR0ci5hcnJheU9rID09PSB0cnVlKSAmJlxuICAgICAgICAgICAgIShzdGFja1tsZXZlbCAtIDFdID09PSAnY29sb3JiYXInICYmIChhdHRyTmFtZSA9PT0gJ3RpY2t0ZXh0JyB8fCBhdHRyTmFtZSA9PT0gJ3RpY2t2YWxzJykpXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gTWFudWFsbHkgZXhjbHVkZSAnY29sb3JiYXIudGlja3ZhbHMnIGFuZCAnY29sb3JiYXIudGlja3RleHQnIGZvciBub3dcbiAgICAgICAgLy8gd2hpY2ggYXJlIGRlY2xhcmVkIGFzIGB2YWxUeXBlOiAnZGF0YV9hcnJheSdgIGJ1dCBzY2FsZSBpbmRlcGVuZGVudGx5IG9mXG4gICAgICAgIC8vIHRoZSBjb29yZGluYXRlIGFycmF5cy5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gRG93biB0aGUgcm9hZCwgd2UgbWlnaHQgd2FudCB0byBhZGQgYSBzY2hlbWEgZmllbGQgKGUuZyBgdW5jb3JyZWxhdGVkQXJyYXk6IHRydWVgKVxuICAgICAgICAvLyB0byBkaXN0aW5ndWlzaCBhdHRyaWJ1dGVzIG9mIHRoZSBsaWtlcy5cblxuICAgICAgICBpZighc3BsaXR0YWJsZUF0dHIpIHJldHVybjtcblxuICAgICAgICBjcmF3bEludG9UcmFjZShiYXNlQ29udGFpbmVyLCAwLCAnJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3Jhd2xJbnRvVHJhY2UoY29udGFpbmVyLCBpLCBhc3RyUGFydGlhbCkge1xuICAgICAgICB2YXIgaXRlbSA9IGNvbnRhaW5lcltzdGFja1tpXV07XG4gICAgICAgIHZhciBuZXdBc3RyUGFydGlhbCA9IGFzdHJQYXJ0aWFsICsgc3RhY2tbaV07XG4gICAgICAgIGlmKGkgPT09IHN0YWNrLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgYXJyYXlBdHRyaWJ1dGVzLnB1c2goYmFzZUF0dHJOYW1lICsgbmV3QXN0clBhcnRpYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYoaXNBcnJheVN0YWNrW2ldKSB7XG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShpdGVtKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgaXRlbS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QoaXRlbVtqXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmF3bEludG9UcmFjZShpdGVtW2pdLCBpICsgMSwgbmV3QXN0clBhcnRpYWwgKyAnWycgKyBqICsgJ10uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKExpYi5pc1BsYWluT2JqZWN0KGl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgY3Jhd2xJbnRvVHJhY2UoaXRlbSwgaSArIDEsIG5ld0FzdHJQYXJ0aWFsICsgJy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGJhc2VDb250YWluZXIgPSB0cmFjZTtcbiAgICBiYXNlQXR0ck5hbWUgPSAnJztcbiAgICBleHBvcnRzLmNyYXdsKGJhc2VBdHRyaWJ1dGVzLCBjYWxsYmFjayk7XG4gICAgaWYodHJhY2UuX21vZHVsZSAmJiB0cmFjZS5fbW9kdWxlLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgZXhwb3J0cy5jcmF3bCh0cmFjZS5fbW9kdWxlLmF0dHJpYnV0ZXMsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNmb3JtcyA9IHRyYWNlLnRyYW5zZm9ybXM7XG4gICAgaWYodHJhbnNmb3Jtcykge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYW5zZm9ybXNbaV07XG4gICAgICAgICAgICB2YXIgbW9kdWxlID0gdHJhbnNmb3JtLl9tb2R1bGU7XG5cbiAgICAgICAgICAgIGlmKG1vZHVsZSkge1xuICAgICAgICAgICAgICAgIGJhc2VBdHRyTmFtZSA9ICd0cmFuc2Zvcm1zWycgKyBpICsgJ10uJztcbiAgICAgICAgICAgICAgICBiYXNlQ29udGFpbmVyID0gdHJhbnNmb3JtO1xuXG4gICAgICAgICAgICAgICAgZXhwb3J0cy5jcmF3bChtb2R1bGUuYXR0cmlidXRlcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycmF5QXR0cmlidXRlcztcbn07XG5cbi8qXG4gKiBGaW5kIHRoZSB2YWxPYmplY3QgZm9yIG9uZSBhdHRyaWJ1dGUgaW4gYW4gZXhpc3RpbmcgdHJhY2VcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VcbiAqICBmdWxsIHRyYWNlIG9iamVjdCB0aGF0IGNvbnRhaW5zIGEgcmVmZXJlbmNlIHRvIGBfbW9kdWxlLmF0dHJpYnV0ZXNgXG4gKiBAcGFyYW0ge29iamVjdH0gcGFydHNcbiAqICBhbiBhcnJheSBvZiBwYXJ0cywgbGlrZSBbJ3RyYW5zZm9ybXMnLCAxLCAndmFsdWUnXVxuICogIHR5cGljYWxseSBmcm9tIG5lc3RlZFByb3BlcnR5KC4uLikucGFydHNcbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R8ZmFsc2V9XG4gKiAgdGhlIHZhbE9iamVjdCBmb3IgdGhpcyBhdHRyaWJ1dGUsIG9yIHRoZSBsYXN0IGZvdW5kIHBhcmVudFxuICogIGluIHNvbWUgY2FzZXMgdGhlIGlubmVybW9zdCB2YWxPYmplY3Qgd2lsbCBub3QgZXhpc3QsIGZvciBleGFtcGxlXG4gKiAgYHZhbFR5cGU6ICdhbnknYCBhdHRyaWJ1dGVzIHdoZXJlIHdlIG1pZ2h0IHNldCBhIHBhcnQgb2YgdGhlIGF0dHJpYnV0ZS5cbiAqICBJbiB0aGF0IGNhc2UsIHN0b3AgYXQgdGhlIGRlZXBlc3QgdmFsT2JqZWN0IHdlICpkbyogZmluZC5cbiAqL1xuZXhwb3J0cy5nZXRUcmFjZVZhbE9iamVjdCA9IGZ1bmN0aW9uKHRyYWNlLCBwYXJ0cykge1xuICAgIHZhciBoZWFkID0gcGFydHNbMF07XG4gICAgdmFyIGkgPSAxOyAvLyBpbmRleCB0byBzdGFydCByZWN1cnNpbmcgZnJvbVxuICAgIHZhciBtb2R1bGVBdHRycywgdmFsT2JqZWN0O1xuXG4gICAgaWYoaGVhZCA9PT0gJ3RyYW5zZm9ybXMnKSB7XG4gICAgICAgIGlmKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGJhc2VBdHRyaWJ1dGVzLnRyYW5zZm9ybXM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zO1xuICAgICAgICBpZighQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm1zKSB8fCAhdHJhbnNmb3Jtcy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIHROdW0gPSBwYXJ0c1sxXTtcbiAgICAgICAgaWYoIWlzSW5kZXgodE51bSkgfHwgdE51bSA+PSB0cmFuc2Zvcm1zLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIG1vZHVsZUF0dHJzID0gKFJlZ2lzdHJ5LnRyYW5zZm9ybXNSZWdpc3RyeVt0cmFuc2Zvcm1zW3ROdW1dLnR5cGVdIHx8IHt9KS5hdHRyaWJ1dGVzO1xuICAgICAgICB2YWxPYmplY3QgPSBtb2R1bGVBdHRycyAmJiBtb2R1bGVBdHRyc1twYXJ0c1syXV07XG4gICAgICAgIGkgPSAzOyAvLyBzdGFydCByZWN1cnNpbmcgb25seSBpbnNpZGUgdGhlIHRyYW5zZm9ybVxuICAgIH1cbiAgICBlbHNlIGlmKHRyYWNlLnR5cGUgPT09ICdhcmVhJykge1xuICAgICAgICB2YWxPYmplY3QgPSBwb2xhckFyZWFBdHRyc1toZWFkXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIGZpcnN0IGxvb2sgaW4gdGhlIG1vZHVsZSBmb3IgdGhpcyB0cmFjZVxuICAgICAgICAvLyBjb21wb25lbnRzIGhhdmUgYWxyZWFkeSBtZXJnZWQgdGhlaXIgdHJhY2UgYXR0cmlidXRlcyBpbiBoZXJlXG4gICAgICAgIHZhciBfbW9kdWxlID0gdHJhY2UuX21vZHVsZTtcbiAgICAgICAgaWYoIV9tb2R1bGUpIF9tb2R1bGUgPSAoUmVnaXN0cnkubW9kdWxlc1t0cmFjZS50eXBlIHx8IGJhc2VBdHRyaWJ1dGVzLnR5cGUuZGZsdF0gfHwge30pLl9tb2R1bGU7XG4gICAgICAgIGlmKCFfbW9kdWxlKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgbW9kdWxlQXR0cnMgPSBfbW9kdWxlLmF0dHJpYnV0ZXM7XG4gICAgICAgIHZhbE9iamVjdCA9IG1vZHVsZUF0dHJzICYmIG1vZHVsZUF0dHJzW2hlYWRdO1xuXG4gICAgICAgIC8vIHRoZW4gbG9vayBpbiB0aGUgc3VicGxvdCBhdHRyaWJ1dGVzXG4gICAgICAgIGlmKCF2YWxPYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBzdWJwbG90TW9kdWxlID0gX21vZHVsZS5iYXNlUGxvdE1vZHVsZTtcbiAgICAgICAgICAgIGlmKHN1YnBsb3RNb2R1bGUgJiYgc3VicGxvdE1vZHVsZS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgICAgdmFsT2JqZWN0ID0gc3VicGxvdE1vZHVsZS5hdHRyaWJ1dGVzW2hlYWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluYWxseSBsb29rIGluIHRoZSBnbG9iYWwgYXR0cmlidXRlc1xuICAgICAgICBpZighdmFsT2JqZWN0KSB2YWxPYmplY3QgPSBiYXNlQXR0cmlidXRlc1toZWFkXTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdXJzZUludG9WYWxPYmplY3QodmFsT2JqZWN0LCBwYXJ0cywgaSk7XG59O1xuXG4vKlxuICogRmluZCB0aGUgdmFsT2JqZWN0IGZvciBvbmUgbGF5b3V0IGF0dHJpYnV0ZVxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IHBhcnRzXG4gKiAgYW4gYXJyYXkgb2YgcGFydHMsIGxpa2UgWydhbm5vdGF0aW9ucycsIDEsICd4J11cbiAqICB0eXBpY2FsbHkgZnJvbSBuZXN0ZWRQcm9wZXJ0eSguLi4pLnBhcnRzXG4gKlxuICogQHJldHVybiB7b2JqZWN0fGZhbHNlfVxuICogIHRoZSB2YWxPYmplY3QgZm9yIHRoaXMgYXR0cmlidXRlLCBvciB0aGUgbGFzdCBmb3VuZCBwYXJlbnRcbiAqICBpbiBzb21lIGNhc2VzIHRoZSBpbm5lcm1vc3QgdmFsT2JqZWN0IHdpbGwgbm90IGV4aXN0LCBmb3IgZXhhbXBsZVxuICogIGB2YWxUeXBlOiAnYW55J2AgYXR0cmlidXRlcyB3aGVyZSB3ZSBtaWdodCBzZXQgYSBwYXJ0IG9mIHRoZSBhdHRyaWJ1dGUuXG4gKiAgSW4gdGhhdCBjYXNlLCBzdG9wIGF0IHRoZSBkZWVwZXN0IHZhbE9iamVjdCB3ZSAqZG8qIGZpbmQuXG4gKi9cbmV4cG9ydHMuZ2V0TGF5b3V0VmFsT2JqZWN0ID0gZnVuY3Rpb24oZnVsbExheW91dCwgcGFydHMpIHtcbiAgICB2YXIgdmFsT2JqZWN0ID0gbGF5b3V0SGVhZEF0dHIoZnVsbExheW91dCwgcGFydHNbMF0pO1xuXG4gICAgcmV0dXJuIHJlY3Vyc2VJbnRvVmFsT2JqZWN0KHZhbE9iamVjdCwgcGFydHMsIDEpO1xufTtcblxuZnVuY3Rpb24gbGF5b3V0SGVhZEF0dHIoZnVsbExheW91dCwgaGVhZCkge1xuICAgIHZhciBpLCBrZXksIF9tb2R1bGUsIGF0dHJpYnV0ZXM7XG5cbiAgICAvLyBsb29rIGZvciBhdHRyaWJ1dGVzIG9mIHRoZSBzdWJwbG90IHR5cGVzIHVzZWQgb24gdGhlIHBsb3RcbiAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzO1xuICAgIGlmKGJhc2VQbG90TW9kdWxlcykge1xuICAgICAgICB2YXIgb3V0O1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIF9tb2R1bGUgPSBiYXNlUGxvdE1vZHVsZXNbaV07XG4gICAgICAgICAgICBpZihfbW9kdWxlLmF0dHJSZWdleCAmJiBfbW9kdWxlLmF0dHJSZWdleC50ZXN0KGhlYWQpKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgYSBtb2R1bGUgZGVmaW5lcyBvdmVycmlkZXMsIHRoZXNlIHRha2UgcHJlY2VkZW5jZVxuICAgICAgICAgICAgICAgIC8vIGluaXRpYWxseSB0aGlzIGlzIHRvIGFsbG93IGdsMmQgZGlmZmVyZW50IGVkaXRUeXBlcyBmcm9tIHN2ZyBjYXJ0ZXNpYW5cbiAgICAgICAgICAgICAgICBpZihfbW9kdWxlLmxheW91dEF0dHJPdmVycmlkZXMpIHJldHVybiBfbW9kdWxlLmxheW91dEF0dHJPdmVycmlkZXM7XG5cbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgdGFrZSB0aGUgZmlyc3QgYXR0cmlidXRlcyB3ZSBmaW5kXG4gICAgICAgICAgICAgICAgaWYoIW91dCAmJiBfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMpIG91dCA9IF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gYSBtb2R1bGUgY2FuIGFsc28gb3ZlcnJpZGUgdGhlIGJlaGF2aW9yIG9mIGJhc2UgKGFuZCBjb21wb25lbnQpIG1vZHVsZSBsYXlvdXQgYXR0cnNcbiAgICAgICAgICAgIC8vIGFnYWluIHNlZSBnbDJkIGZvciBpbml0aWFsIHVzZSBjYXNlXG4gICAgICAgICAgICB2YXIgYmFzZU92ZXJyaWRlcyA9IF9tb2R1bGUuYmFzZUxheW91dEF0dHJPdmVycmlkZXM7XG4gICAgICAgICAgICBpZihiYXNlT3ZlcnJpZGVzICYmIGhlYWQgaW4gYmFzZU92ZXJyaWRlcykgcmV0dXJuIGJhc2VPdmVycmlkZXNbaGVhZF07XG4gICAgICAgIH1cbiAgICAgICAgaWYob3V0KSByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIC8vIGxvb2sgZm9yIGxheW91dCBhdHRyaWJ1dGVzIGNvbnRyaWJ1dGVkIGJ5IHRyYWNlcyBvbiB0aGUgcGxvdFxuICAgIHZhciBtb2R1bGVzID0gZnVsbExheW91dC5fbW9kdWxlcztcbiAgICBpZihtb2R1bGVzKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXMgPSBtb2R1bGVzW2ldLmxheW91dEF0dHJpYnV0ZXM7XG4gICAgICAgICAgICBpZihhdHRyaWJ1dGVzICYmIGhlYWQgaW4gYXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBhdHRyaWJ1dGVzW2hlYWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBOZXh0IGxvb2sgaW4gY29tcG9uZW50cy5cbiAgICAgKiBDb21wb25lbnRzIHRoYXQgZGVmaW5lIGEgc2NoZW1hIGhhdmUgYWxyZWFkeSBtZXJnZWQgdGhpcyBpbnRvXG4gICAgICogYmFzZSBhbmQgc3VicGxvdCBhdHRyaWJ1dGUgZGVmcywgc28gaWdub3JlIHRoZXNlLlxuICAgICAqIE90aGVycyAob2xkZXIgc3R5bGUpIGFsbCBwdXQgYWxsIHRoZWlyIGF0dHJpYnV0ZXNcbiAgICAgKiBpbnNpZGUgYSBjb250YWluZXIgbWF0Y2hpbmcgdGhlIG1vZHVsZSBgbmFtZWBcbiAgICAgKiBlZyBgYXR0cmlidXRlc2AgKGFycmF5KSBvciBgbGVnZW5kYCAob2JqZWN0KVxuICAgICAqL1xuICAgIGZvcihrZXkgaW4gUmVnaXN0cnkuY29tcG9uZW50c1JlZ2lzdHJ5KSB7XG4gICAgICAgIF9tb2R1bGUgPSBSZWdpc3RyeS5jb21wb25lbnRzUmVnaXN0cnlba2V5XTtcbiAgICAgICAgaWYoIV9tb2R1bGUuc2NoZW1hICYmIChoZWFkID09PSBfbW9kdWxlLm5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaGVhZCBpbiBiYXNlTGF5b3V0QXR0cmlidXRlcykgcmV0dXJuIGJhc2VMYXlvdXRBdHRyaWJ1dGVzW2hlYWRdO1xuXG4gICAgLy8gUG9sYXIgZG9lc24ndCBwb3B1bGF0ZSBfbW9kdWxlcyBvciBfYmFzZVBsb3RNb2R1bGVzXG4gICAgLy8ganVzdCBmYWxsIGJhY2sgb24gdGhlc2Ugd2hlbiB0aGUgb3RoZXJzIGZhaWxcbiAgICBpZihoZWFkID09PSAncmFkaWFsYXhpcycgfHwgaGVhZCA9PT0gJ2FuZ3VsYXJheGlzJykge1xuICAgICAgICByZXR1cm4gcG9sYXJBeGlzQXR0cnNbaGVhZF07XG4gICAgfVxuICAgIHJldHVybiBwb2xhckF4aXNBdHRycy5sYXlvdXRbaGVhZF0gfHwgZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJlY3Vyc2VJbnRvVmFsT2JqZWN0KHZhbE9iamVjdCwgcGFydHMsIGkpIHtcbiAgICBpZighdmFsT2JqZWN0KSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZih2YWxPYmplY3QuX2lzTGlua2VkVG9BcnJheSkge1xuICAgICAgICAvLyBza2lwIGFycmF5IGluZGV4LCBhYm9ydCBpZiB3ZSB0cnkgdG8gZGl2ZSBpbnRvIGFuIGFycmF5IHdpdGhvdXQgYW4gaW5kZXhcbiAgICAgICAgaWYoaXNJbmRleChwYXJ0c1tpXSkpIGkrKztcbiAgICAgICAgZWxzZSBpZihpIDwgcGFydHMubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gbm93IHJlY3Vyc2UgYXMgZmFyIGFzIHdlIGNhbi4gT2NjYXNpb25hbGx5IHdlIGhhdmUgYW4gYXR0cmlidXRlXG4gICAgLy8gc2V0dGluZyBhbiBpbnRlcm5hbCBwYXJ0IGJlbG93IHdoYXQncyBpbiB0aGUgc2NoZW1hOyBqdXN0IHJldHVyblxuICAgIC8vIHRoZSBpbm5lcm1vc3Qgc2NoZW1hIGl0ZW0gd2UgZmluZC5cbiAgICBmb3IoOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG5ld1ZhbE9iamVjdCA9IHZhbE9iamVjdFtwYXJ0c1tpXV07XG4gICAgICAgIGlmKGlzUGxhaW5PYmplY3QobmV3VmFsT2JqZWN0KSkgdmFsT2JqZWN0ID0gbmV3VmFsT2JqZWN0O1xuICAgICAgICBlbHNlIGJyZWFrO1xuXG4gICAgICAgIGlmKGkgPT09IHBhcnRzLmxlbmd0aCAtIDEpIGJyZWFrO1xuXG4gICAgICAgIGlmKHZhbE9iamVjdC5faXNMaW5rZWRUb0FycmF5KSB7XG4gICAgICAgICAgICBpKys7XG4gICAgICAgICAgICBpZighaXNJbmRleChwYXJ0c1tpXSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHZhbE9iamVjdC52YWxUeXBlID09PSAnaW5mb19hcnJheScpIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIHZhciBpbmRleCA9IHBhcnRzW2ldO1xuICAgICAgICAgICAgaWYoIWlzSW5kZXgoaW5kZXgpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAgIHZhciBpdGVtcyA9IHZhbE9iamVjdC5pdGVtcztcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoaXRlbXMpKSB7XG4gICAgICAgICAgICAgICAgaWYoaW5kZXggPj0gaXRlbXMubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYodmFsT2JqZWN0LmRpbWVuc2lvbnMgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgICAgICBpZihwYXJ0cy5sZW5ndGggPT09IGkpIHJldHVybiB2YWxPYmplY3Q7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmRleDIgPSBwYXJ0c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIWlzSW5kZXgoaW5kZXgyKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB2YWxPYmplY3QgPSBpdGVtc1tpbmRleF1baW5kZXgyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB2YWxPYmplY3QgPSBpdGVtc1tpbmRleF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWxPYmplY3QgPSBpdGVtcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWxPYmplY3Q7XG59XG5cbi8vIG5vdGU6IHRoaXMgaXMgZGlmZmVyZW50IGZyb20gTGliLmlzSW5kZXgsIHRoaXMgb25lIGRvZXNuJ3QgYWNjZXB0IG51bWVyaWNcbi8vIHN0cmluZ3MsIG9ubHkgYWN0dWFsIG51bWJlcnMuXG5mdW5jdGlvbiBpc0luZGV4KHZhbCkge1xuICAgIHJldHVybiB2YWwgPT09IE1hdGgucm91bmQodmFsKSAmJiB2YWwgPj0gMDtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhY2VBdHRyaWJ1dGVzKHR5cGUpIHtcbiAgICB2YXIgX21vZHVsZSwgYmFzZVBsb3RNb2R1bGU7XG5cbiAgICBpZih0eXBlID09PSAnYXJlYScpIHtcbiAgICAgICAgX21vZHVsZSA9IHsgYXR0cmlidXRlczogcG9sYXJBcmVhQXR0cnMgfTtcbiAgICAgICAgYmFzZVBsb3RNb2R1bGUgPSB7fTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIF9tb2R1bGUgPSBSZWdpc3RyeS5tb2R1bGVzW3R5cGVdLl9tb2R1bGUsXG4gICAgICAgIGJhc2VQbG90TW9kdWxlID0gX21vZHVsZS5iYXNlUGxvdE1vZHVsZTtcbiAgICB9XG5cbiAgICB2YXIgYXR0cmlidXRlcyA9IHt9O1xuXG4gICAgLy8gbWFrZSAndHlwZScgdGhlIGZpcnN0IGF0dHJpYnV0ZSBpbiB0aGUgb2JqZWN0XG4gICAgYXR0cmlidXRlcy50eXBlID0gbnVsbDtcblxuXG4gICAgdmFyIGNvcHlCYXNlQXR0cmlidXRlcyA9IGV4dGVuZERlZXBBbGwoe30sIGJhc2VBdHRyaWJ1dGVzKTtcbiAgICB2YXIgY29weU1vZHVsZUF0dHJpYnV0ZXMgPSBleHRlbmREZWVwQWxsKHt9LCBfbW9kdWxlLmF0dHJpYnV0ZXMpO1xuXG4gICAgLy8gcHJ1bmUgZ2xvYmFsLWxldmVsIHRyYWNlIGF0dHJpYnV0ZXMgdGhhdCBhcmUgYWxyZWFkeSBkZWZpbmVkIGluIGEgdHJhY2VcbiAgICBleHBvcnRzLmNyYXdsKGNvcHlNb2R1bGVBdHRyaWJ1dGVzLCBmdW5jdGlvbihhdHRyLCBhdHRyTmFtZSwgYXR0cnMsIGxldmVsLCBmdWxsQXR0clN0cmluZykge1xuICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29weUJhc2VBdHRyaWJ1dGVzLCBmdWxsQXR0clN0cmluZykuc2V0KHVuZGVmaW5lZCk7XG4gICAgICAgIC8vIFBydW5lIHVuZGVmaW5lZCBhdHRyaWJ1dGVzXG4gICAgICAgIGlmKGF0dHIgPT09IHVuZGVmaW5lZCkgTGliLm5lc3RlZFByb3BlcnR5KGNvcHlNb2R1bGVBdHRyaWJ1dGVzLCBmdWxsQXR0clN0cmluZykuc2V0KHVuZGVmaW5lZCk7XG4gICAgfSk7XG5cbiAgICAvLyBiYXNlIGF0dHJpYnV0ZXMgKHNhbWUgZm9yIGFsbCB0cmFjZSB0eXBlcylcbiAgICBleHRlbmREZWVwQWxsKGF0dHJpYnV0ZXMsIGNvcHlCYXNlQXR0cmlidXRlcyk7XG5cbiAgICAvLyBtb2R1bGUgYXR0cmlidXRlc1xuICAgIGV4dGVuZERlZXBBbGwoYXR0cmlidXRlcywgY29weU1vZHVsZUF0dHJpYnV0ZXMpO1xuXG4gICAgLy8gc3VicGxvdCBhdHRyaWJ1dGVzXG4gICAgaWYoYmFzZVBsb3RNb2R1bGUuYXR0cmlidXRlcykge1xuICAgICAgICBleHRlbmREZWVwQWxsKGF0dHJpYnV0ZXMsIGJhc2VQbG90TW9kdWxlLmF0dHJpYnV0ZXMpO1xuICAgIH1cblxuICAgIC8vICd0eXBlJyBnZXRzIG92ZXJ3cml0dGVuIGJ5IGJhc2VBdHRyaWJ1dGVzOyByZXNldCBpdCBoZXJlXG4gICAgYXR0cmlidXRlcy50eXBlID0gdHlwZTtcblxuICAgIHZhciBvdXQgPSB7XG4gICAgICAgIG1ldGE6IF9tb2R1bGUubWV0YSB8fCB7fSxcbiAgICAgICAgYXR0cmlidXRlczogZm9ybWF0QXR0cmlidXRlcyhhdHRyaWJ1dGVzKSxcbiAgICB9O1xuXG4gICAgLy8gdHJhY2Utc3BlY2lmaWMgbGF5b3V0IGF0dHJpYnV0ZXNcbiAgICBpZihfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMpIHtcbiAgICAgICAgdmFyIGxheW91dEF0dHJpYnV0ZXMgPSB7fTtcblxuICAgICAgICBleHRlbmREZWVwQWxsKGxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG4gICAgICAgIG91dC5sYXlvdXRBdHRyaWJ1dGVzID0gZm9ybWF0QXR0cmlidXRlcyhsYXlvdXRBdHRyaWJ1dGVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5mdW5jdGlvbiBnZXRMYXlvdXRBdHRyaWJ1dGVzKCkge1xuICAgIHZhciBsYXlvdXRBdHRyaWJ1dGVzID0ge307XG4gICAgdmFyIGtleSwgX21vZHVsZTtcblxuICAgIC8vIGdsb2JhbCBsYXlvdXQgYXR0cmlidXRlc1xuICAgIGV4dGVuZERlZXBBbGwobGF5b3V0QXR0cmlidXRlcywgYmFzZUxheW91dEF0dHJpYnV0ZXMpO1xuXG4gICAgLy8gYWRkIGJhc2UgcGxvdCBtb2R1bGUgbGF5b3V0IGF0dHJpYnV0ZXNcbiAgICBmb3Ioa2V5IGluIFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnkpIHtcbiAgICAgICAgX21vZHVsZSA9IFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnlba2V5XTtcblxuICAgICAgICBpZighX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKSBjb250aW51ZTtcblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KF9tb2R1bGUuYXR0cikpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBfbW9kdWxlLmF0dHIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVCYXNlUGxvdE1vZHVsZShsYXlvdXRBdHRyaWJ1dGVzLCBfbW9kdWxlLCBfbW9kdWxlLmF0dHJbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGFzdHIgPSBfbW9kdWxlLmF0dHIgPT09ICdzdWJwbG90JyA/IF9tb2R1bGUubmFtZSA6IF9tb2R1bGUuYXR0cjtcbiAgICAgICAgICAgIGhhbmRsZUJhc2VQbG90TW9kdWxlKGxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUsIGFzdHIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gcG9sYXIgbGF5b3V0IGF0dHJpYnV0ZXNcbiAgICBsYXlvdXRBdHRyaWJ1dGVzID0gYXNzaWduUG9sYXJMYXlvdXRBdHRycyhsYXlvdXRBdHRyaWJ1dGVzKTtcblxuICAgIC8vIGFkZCByZWdpc3RlcmVkIGNvbXBvbmVudHMgbGF5b3V0IGF0dHJpYnV0ZXNcbiAgICBmb3Ioa2V5IGluIFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBfbW9kdWxlID0gUmVnaXN0cnkuY29tcG9uZW50c1JlZ2lzdHJ5W2tleV07XG4gICAgICAgIHZhciBzY2hlbWEgPSBfbW9kdWxlLnNjaGVtYTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBDb21wb25lbnRzIHdpdGggZGVmaW5lZCBzY2hlbWEgaGF2ZSBhbHJlYWR5IGJlZW4gbWVyZ2VkIGluIGF0IHJlZ2lzdGVyIHRpbWVcbiAgICAgICAgICogYnV0IGEgZmV3IGNvbXBvbmVudHMgZGVmaW5lIGF0dHJpYnV0ZXMgdGhhdCBhcHBseSBvbmx5IHRvIHhheGlzXG4gICAgICAgICAqIG5vdCB5YXhpcyAocmFuZ2VzZWxlY3RvciwgcmFuZ2VzbGlkZXIpIC0gZGVsZXRlIGZyb20geSBzY2hlbWEuXG4gICAgICAgICAqIE5vdGUgdGhhdCB0aGUgaW5wdXQgYXR0cmlidXRlcyBmb3IgeGF4aXMveWF4aXMgYXJlIHRoZSBzYW1lIG9iamVjdFxuICAgICAgICAgKiBzbyBpdCdzIG5vdCBwb3NzaWJsZSB0byBvbmx5IGFkZCB0aGVtIHRvIHhheGlzIGZyb20gdGhlIHN0YXJ0LlxuICAgICAgICAgKiBJZiB3ZSBldmVyIGhhdmUgc3VjaCBhc3ltbWV0cnkgdGhlIG90aGVyIHdheSwgb3IgYW55d2hlcmUgZWxzZSxcbiAgICAgICAgICogd2Ugd2lsbCBuZWVkIHRvIGV4dGVuZCBib3RoIHRoaXMgY29kZSBhbmQgbWVyZ2VDb21wb25lbnRBdHRyc1RvU3VicGxvdFxuICAgICAgICAgKiAod2hpY2ggd2lsbCBub3QgZmluZCB5YXhpcyBvbmx5IGZvciBleGFtcGxlKVxuICAgICAgICAgKi9cbiAgICAgICAgaWYoc2NoZW1hICYmIChzY2hlbWEuc3VicGxvdHMgfHwgc2NoZW1hLmxheW91dCkpIHtcbiAgICAgICAgICAgIHZhciBzdWJwbG90cyA9IHNjaGVtYS5zdWJwbG90cztcbiAgICAgICAgICAgIGlmKHN1YnBsb3RzICYmIHN1YnBsb3RzLnhheGlzICYmICFzdWJwbG90cy55YXhpcykge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgeGtleSBpbiBzdWJwbG90cy54YXhpcykgZGVsZXRlIGxheW91dEF0dHJpYnV0ZXMueWF4aXNbeGtleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gb2xkZXIgc3R5bGUgd2l0aG91dCBzY2hlbWEgbmVlZCB0byBiZSBleHBsaWNpdGx5IG1lcmdlZCBpbiBub3dcbiAgICAgICAgZWxzZSBpZihfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgIGluc2VydEF0dHJzKGxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcywgX21vZHVsZS5uYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGxheW91dEF0dHJpYnV0ZXM6IGZvcm1hdEF0dHJpYnV0ZXMobGF5b3V0QXR0cmlidXRlcylcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2Zvcm1BdHRyaWJ1dGVzKHR5cGUpIHtcbiAgICB2YXIgX21vZHVsZSA9IFJlZ2lzdHJ5LnRyYW5zZm9ybXNSZWdpc3RyeVt0eXBlXTtcbiAgICB2YXIgYXR0cmlidXRlcyA9IGV4dGVuZERlZXBBbGwoe30sIF9tb2R1bGUuYXR0cmlidXRlcyk7XG5cbiAgICAvLyBhZGQgcmVnaXN0ZXJlZCBjb21wb25lbnRzIHRyYW5zZm9ybSBhdHRyaWJ1dGVzXG4gICAgT2JqZWN0LmtleXMoUmVnaXN0cnkuY29tcG9uZW50c1JlZ2lzdHJ5KS5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBSZWdpc3RyeS5jb21wb25lbnRzUmVnaXN0cnlba107XG5cbiAgICAgICAgaWYoX21vZHVsZS5zY2hlbWEgJiYgX21vZHVsZS5zY2hlbWEudHJhbnNmb3JtcyAmJiBfbW9kdWxlLnNjaGVtYS50cmFuc2Zvcm1zW3R5cGVdKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhfbW9kdWxlLnNjaGVtYS50cmFuc2Zvcm1zW3R5cGVdKS5mb3JFYWNoKGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICBpbnNlcnRBdHRycyhhdHRyaWJ1dGVzLCBfbW9kdWxlLnNjaGVtYS50cmFuc2Zvcm1zW3R5cGVdW3ZdLCB2KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBhdHRyaWJ1dGVzOiBmb3JtYXRBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0RnJhbWVzQXR0cmlidXRlcygpIHtcbiAgICB2YXIgYXR0cnMgPSB7XG4gICAgICAgIGZyYW1lczogTGliLmV4dGVuZERlZXBBbGwoe30sIGZyYW1lQXR0cmlidXRlcylcbiAgICB9O1xuXG4gICAgZm9ybWF0QXR0cmlidXRlcyhhdHRycyk7XG5cbiAgICByZXR1cm4gYXR0cnMuZnJhbWVzO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBdHRyaWJ1dGVzKGF0dHJzKSB7XG4gICAgbWVyZ2VWYWxUeXBlQW5kUm9sZShhdHRycyk7XG4gICAgZm9ybWF0QXJyYXlDb250YWluZXJzKGF0dHJzKTtcbiAgICBzdHJpbmdpZnkoYXR0cnMpO1xuXG4gICAgcmV0dXJuIGF0dHJzO1xufVxuXG5mdW5jdGlvbiBtZXJnZVZhbFR5cGVBbmRSb2xlKGF0dHJzKSB7XG5cbiAgICBmdW5jdGlvbiBtYWtlU3JjQXR0cihhdHRyTmFtZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJ1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGxiYWNrKGF0dHIsIGF0dHJOYW1lLCBhdHRycykge1xuICAgICAgICBpZihleHBvcnRzLmlzVmFsT2JqZWN0KGF0dHIpKSB7XG4gICAgICAgICAgICBpZihhdHRyLnZhbFR5cGUgPT09ICdkYXRhX2FycmF5Jykge1xuICAgICAgICAgICAgICAgIC8vIGFsbCAnZGF0YV9hcnJheScgYXR0cnMgaGF2ZSByb2xlICdkYXRhJ1xuICAgICAgICAgICAgICAgIGF0dHIucm9sZSA9ICdkYXRhJztcbiAgICAgICAgICAgICAgICAvLyBhbGwgJ2RhdGFfYXJyYXknIGF0dHJzIGhhdmUgYSBjb3JyZXNwb25kaW5nICdzcmMnIGF0dHJcbiAgICAgICAgICAgICAgICBhdHRyc1thdHRyTmFtZSArICdzcmMnXSA9IG1ha2VTcmNBdHRyKGF0dHJOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoYXR0ci5hcnJheU9rID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgLy8gYWxsICdhcnJheU9rJyBhdHRycyBoYXZlIGEgY29ycmVzcG9uZGluZyAnc3JjJyBhdHRyXG4gICAgICAgICAgICAgICAgYXR0cnNbYXR0ck5hbWUgKyAnc3JjJ10gPSBtYWtlU3JjQXR0cihhdHRyTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihpc1BsYWluT2JqZWN0KGF0dHIpKSB7XG4gICAgICAgICAgICAvLyBhbGwgYXR0cnMgY29udGFpbmVyIG9iamVjdHMgZ2V0IHJvbGUgJ29iamVjdCdcbiAgICAgICAgICAgIGF0dHIucm9sZSA9ICdvYmplY3QnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXhwb3J0cy5jcmF3bChhdHRycywgY2FsbGJhY2spO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBcnJheUNvbnRhaW5lcnMoYXR0cnMpIHtcblxuICAgIGZ1bmN0aW9uIGNhbGxiYWNrKGF0dHIsIGF0dHJOYW1lLCBhdHRycykge1xuICAgICAgICBpZighYXR0cikgcmV0dXJuO1xuXG4gICAgICAgIHZhciBpdGVtTmFtZSA9IGF0dHJbSVNfTElOS0VEX1RPX0FSUkFZXTtcblxuICAgICAgICBpZighaXRlbU5hbWUpIHJldHVybjtcblxuICAgICAgICBkZWxldGUgYXR0cltJU19MSU5LRURfVE9fQVJSQVldO1xuXG4gICAgICAgIGF0dHJzW2F0dHJOYW1lXSA9IHsgaXRlbXM6IHt9IH07XG4gICAgICAgIGF0dHJzW2F0dHJOYW1lXS5pdGVtc1tpdGVtTmFtZV0gPSBhdHRyO1xuICAgICAgICBhdHRyc1thdHRyTmFtZV0ucm9sZSA9ICdvYmplY3QnO1xuICAgIH1cblxuICAgIGV4cG9ydHMuY3Jhd2woYXR0cnMsIGNhbGxiYWNrKTtcbn1cblxuLy8gdGhpcyBjYW4gdGFrZSBhcm91bmQgMTBtcyBhbmQgc2hvdWxkIG9ubHkgYmUgcnVuIGZyb20gUGxvdFNjaGVtYS5nZXQoKSxcbi8vIHRvIGVuc3VyZSBKU09OLnN0cmluZ2lmeShQbG90U2NoZW1hLmdldCgpKSBnaXZlcyB0aGUgaW50ZW5kZWQgcmVzdWx0LlxuZnVuY3Rpb24gc3RyaW5naWZ5KGF0dHJzKSB7XG4gICAgZnVuY3Rpb24gd2FsayhhdHRyKSB7XG4gICAgICAgIGZvcih2YXIgayBpbiBhdHRyKSB7XG4gICAgICAgICAgICBpZihpc1BsYWluT2JqZWN0KGF0dHJba10pKSB7XG4gICAgICAgICAgICAgICAgd2FsayhhdHRyW2tdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihBcnJheS5pc0FycmF5KGF0dHJba10pKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGF0dHJba10ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgd2FsayhhdHRyW2tdW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGFzIEpTT04uc3RyaW5naWZ5KC90ZXN0LykgLy8gPT4ge31cbiAgICAgICAgICAgICAgICBpZihhdHRyW2tdIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJba10gPSBhdHRyW2tdLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgd2FsayhhdHRycyk7XG59XG5cbmZ1bmN0aW9uIGFzc2lnblBvbGFyTGF5b3V0QXR0cnMobGF5b3V0QXR0cmlidXRlcykge1xuICAgIGV4dGVuZEZsYXQobGF5b3V0QXR0cmlidXRlcywge1xuICAgICAgICByYWRpYWxheGlzOiBwb2xhckF4aXNBdHRycy5yYWRpYWxheGlzLFxuICAgICAgICBhbmd1bGFyYXhpczogcG9sYXJBeGlzQXR0cnMuYW5ndWxhcmF4aXNcbiAgICB9KTtcblxuICAgIGV4dGVuZEZsYXQobGF5b3V0QXR0cmlidXRlcywgcG9sYXJBeGlzQXR0cnMubGF5b3V0KTtcblxuICAgIHJldHVybiBsYXlvdXRBdHRyaWJ1dGVzO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVCYXNlUGxvdE1vZHVsZShsYXlvdXRBdHRyaWJ1dGVzLCBfbW9kdWxlLCBhc3RyKSB7XG4gICAgdmFyIG5wID0gTGliLm5lc3RlZFByb3BlcnR5KGxheW91dEF0dHJpYnV0ZXMsIGFzdHIpLFxuICAgICAgICBhdHRycyA9IGV4dGVuZERlZXBBbGwoe30sIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG5cbiAgICBhdHRyc1tJU19TVUJQTE9UX09CSl0gPSB0cnVlO1xuICAgIG5wLnNldChhdHRycyk7XG59XG5cbmZ1bmN0aW9uIGluc2VydEF0dHJzKGJhc2VBdHRycywgbmV3QXR0cnMsIGFzdHIpIHtcbiAgICB2YXIgbnAgPSBMaWIubmVzdGVkUHJvcGVydHkoYmFzZUF0dHJzLCBhc3RyKTtcblxuICAgIG5wLnNldChleHRlbmREZWVwQWxsKG5wLmdldCgpIHx8IHt9LCBuZXdBdHRycykpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBwbG90QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcblxudmFyIFRFTVBMQVRFSVRFTU5BTUUgPSAndGVtcGxhdGVpdGVtbmFtZSc7XG5cbnZhciB0ZW1wbGF0ZUF0dHJzID0ge1xuICAgIG5hbWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9XG59O1xudGVtcGxhdGVBdHRyc1tURU1QTEFURUlURU1OQU1FXSA9IHtcbiAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICBcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIFxufTtcblxuLyoqXG4gKiB0ZW1wbGF0ZWRBcnJheTogZGVjb3JhdGUgYW4gYXR0cmlidXRlcyBvYmplY3Qgd2l0aCB0ZW1wbGF0aW5nIChhbmQgYXJyYXkpXG4gKiBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lOiB0aGUgc2luZ3VsYXIgZm9ybSBvZiB0aGUgYXJyYXkgbmFtZS4gU2V0c1xuICogICAgIGBfaXNMaW5rZWRUb0FycmF5YCB0byB0aGlzLCBzbyB0aGUgc2NoZW1hIGtub3dzIHRvIHRyZWF0IHRoaXMgYXMgYW4gYXJyYXkuXG4gKiBAcGFyYW0ge29iamVjdH0gYXR0cnM6IHRoZSBpdGVtIGF0dHJpYnV0ZXMuIFNpbmNlIGFsbCBjYWxsZXJzIGFyZSBleHBlY3RlZFxuICogICAgIHRvIGJlIGNvbnN0cnVjdGluZyB0aGlzIG9iamVjdCBvbiB0aGUgc3BvdCwgd2UgbXV0YXRlIGl0IGhlcmUgZm9yXG4gKiAgICAgcGVyZm9ybWFuY2UsIHJhdGhlciB0aGFuIGV4dGVuZGluZyBhIG5ldyBvYmplY3Qgd2l0aCBpdC5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fTogdGhlIGRlY29yYXRlZCBgYXR0cnNgIG9iamVjdFxuICovXG5leHBvcnRzLnRlbXBsYXRlZEFycmF5ID0gZnVuY3Rpb24obmFtZSwgYXR0cnMpIHtcbiAgICBhdHRycy5faXNMaW5rZWRUb0FycmF5ID0gbmFtZTtcbiAgICBhdHRycy5uYW1lID0gdGVtcGxhdGVBdHRycy5uYW1lO1xuICAgIGF0dHJzW1RFTVBMQVRFSVRFTU5BTUVdID0gdGVtcGxhdGVBdHRyc1tURU1QTEFURUlURU1OQU1FXTtcbiAgICByZXR1cm4gYXR0cnM7XG59O1xuXG4vKipcbiAqIHRyYWNlVGVtcGxhdGVyOiBsb2dpYyBmb3IgbWF0Y2hpbmcgdHJhY2VzIHRvIHRyYWNlIHRlbXBsYXRlc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBkYXRhVGVtcGxhdGU6IGNvbGxlY3Rpb24gb2Yge3RyYWNlVHlwZTogW3t0ZW1wbGF0ZX0sIC4uLl19XG4gKiAgICAgaWUgZWFjaCB0eXBlIHRoZSB0ZW1wbGF0ZSBhcHBsaWVzIHRvIGNvbnRhaW5zIGEgbGlzdCBvZiB0ZW1wbGF0ZSBvYmplY3RzLFxuICogICAgIHRvIGJlIHByb3ZpZGVkIGN5Y2xpY2FsbHkgdG8gZGF0YSB0cmFjZXMgb2YgdGhhdCB0eXBlLlxuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9OiB7bmV3VHJhY2V9LCBhIGZ1bmN0aW9uOlxuICogICAgIG5ld1RyYWNlKHRyYWNlSW4pOiB0aGF0IHRha2VzIHRoZSBpbnB1dCB0cmFjZUluLCBjb2VyY2VzIGl0cyB0eXBlLCB0aGVuXG4gKiAgICAgICAgIHVzZXMgdGhhdCB0eXBlIHRvIGZpbmQgdGhlIG5leHQgdGVtcGxhdGUgdG8gYXBwbHkuIHJldHVybnMgdGhlIG91dHB1dFxuICogICAgICAgICB0cmFjZU91dCB3aXRoIHRlbXBsYXRlIGF0dGFjaGVkLCByZWFkeSB0byBjb250aW51ZSBzdXBwbHlEZWZhdWx0cy5cbiAqL1xuZXhwb3J0cy50cmFjZVRlbXBsYXRlciA9IGZ1bmN0aW9uKGRhdGFUZW1wbGF0ZSkge1xuICAgIHZhciB0cmFjZUNvdW50cyA9IHt9O1xuICAgIHZhciB0cmFjZVR5cGUsIHR5cGVUZW1wbGF0ZXM7XG5cbiAgICBmb3IodHJhY2VUeXBlIGluIGRhdGFUZW1wbGF0ZSkge1xuICAgICAgICB0eXBlVGVtcGxhdGVzID0gZGF0YVRlbXBsYXRlW3RyYWNlVHlwZV07XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHlwZVRlbXBsYXRlcykgJiYgdHlwZVRlbXBsYXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRyYWNlQ291bnRzW3RyYWNlVHlwZV0gPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV3VHJhY2UodHJhY2VJbikge1xuICAgICAgICB0cmFjZVR5cGUgPSBMaWIuY29lcmNlKHRyYWNlSW4sIHt9LCBwbG90QXR0cmlidXRlcywgJ3R5cGUnKTtcbiAgICAgICAgdmFyIHRyYWNlT3V0ID0ge3R5cGU6IHRyYWNlVHlwZSwgX3RlbXBsYXRlOiBudWxsfTtcbiAgICAgICAgaWYodHJhY2VUeXBlIGluIHRyYWNlQ291bnRzKSB7XG4gICAgICAgICAgICB0eXBlVGVtcGxhdGVzID0gZGF0YVRlbXBsYXRlW3RyYWNlVHlwZV07XG4gICAgICAgICAgICAvLyBjeWNsZSB0aHJvdWdoIHRyYWNlcyBpbiB0aGUgdGVtcGxhdGUgc2V0IGZvciB0aGlzIHR5cGVcbiAgICAgICAgICAgIHZhciB0eXBlaSA9IHRyYWNlQ291bnRzW3RyYWNlVHlwZV0gJSB0eXBlVGVtcGxhdGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHRyYWNlQ291bnRzW3RyYWNlVHlwZV0rKztcbiAgICAgICAgICAgIHRyYWNlT3V0Ll90ZW1wbGF0ZSA9IHR5cGVUZW1wbGF0ZXNbdHlwZWldO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gVE9ETzogYW55dGhpbmcgd2Ugc2hvdWxkIGRvIGZvciB0eXBlcyBtaXNzaW5nIGZyb20gdGhlIHRlbXBsYXRlP1xuICAgICAgICAgICAgLy8gdHJ5IHRvIGFwcGx5IHNvbWUgb3RoZXIgdHlwZT8gT3IganVzdCBiYWlsIGFzIHdlIGRvIGhlcmU/XG4gICAgICAgICAgICAvLyBBY3R1YWxseSBJIHRoaW5rIHllcywgd2Ugc2hvdWxkIGFwcGx5IG90aGVyIHR5cGVzOyB3b3VsZCBiZSBuaWNlXG4gICAgICAgICAgICAvLyBpZiBhbGwgc2NhdHRlciogY291bGQgaW5oZXJpdCBmcm9tIGVhY2ggb3RoZXIsIGFuZCBpZiBoaXN0b2dyYW1cbiAgICAgICAgICAgIC8vIGNvdWxkIGluaGVyaXQgZnJvbSBiYXIsIGV0Yy4uLiBidXQgaG93IHRvIHNwZWNpZnkgdGhpcz8gQW5kIGRvIHdlXG4gICAgICAgICAgICAvLyBjb21wb3NlIHRoZW0sIG9yIGlmIGEgdHlwZSBpcyBwcmVzZW50IHJlcXVpcmUgaXQgdG8gYmUgY29tcGxldGU/XG4gICAgICAgICAgICAvLyBBY3R1YWxseSB0aGlzIGNvdWxkIGFwcGx5IHRvIGxheW91dCB0b28gLSAzRCBhbm5vdGF0aW9uc1xuICAgICAgICAgICAgLy8gaW5oZXJpdGluZyBmcm9tIDJELCBheGVzIG9mIGRpZmZlcmVudCB0eXBlcyBpbmhlcml0aW5nIGZyb20gZWFjaFxuICAgICAgICAgICAgLy8gb3RoZXIuLi5cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJhY2VPdXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbmV3VHJhY2U6IG5ld1RyYWNlXG4gICAgICAgIC8vIFRPRE86IGZ1bmN0aW9uIHRvIGZpZ3VyZSBvdXQgd2hhdCdzIGxlZnQgJiB3aGF0IGRpZG4ndCB3b3JrXG4gICAgfTtcbn07XG5cbi8qKlxuICogbmV3Q29udGFpbmVyOiBDcmVhdGUgYSBuZXcgc3ViLWNvbnRhaW5lciBpbnNpZGUgYGNvbnRhaW5lcmAgYW5kIHByb3BhZ2F0ZSBhbnlcbiAqIGFwcGxpY2FibGUgdGVtcGxhdGUgdG8gaXQuIElmIHRoZXJlJ3Mgbm8gdGVtcGxhdGUsIHN0aWxsIHByb3BhZ2F0ZXNcbiAqIGB1bmRlZmluZWRgIHNvIHJlbGlua1ByaXZhdGUgd2lsbCBub3QgcmV0YWluIGFuIG9sZCB0ZW1wbGF0ZSFcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gY29udGFpbmVyOiB0aGUgb3V0ZXIgY29udGFpbmVyLCBzaG91bGQgYWxyZWFkeSBoYXZlIF90ZW1wbGF0ZVxuICogICAgIGlmIHRoZXJlICppcyogYSB0ZW1wbGF0ZSBmb3IgdGhpcyBwbG90XG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZTogdGhlIGtleSBvZiB0aGUgbmV3IGNvbnRhaW5lciB0byBtYWtlXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZU5hbWU6IGlmIGFwcGxpY2FibGUsIGEgYmFzZSBhdHRyaWJ1dGUgdG8gdGFrZSB0aGVcbiAqICAgICB0ZW1wbGF0ZSBmcm9tLCBpZSBmb3IgeGF4aXMzIHRoZSBiYXNlIHdvdWxkIGJlIHhheGlzXG4gKlxuICogQHJldHVybnMge29iamVjdH06IGFuIG9iamVjdCBmb3IgaW5jbHVzaW9uIF9mdWxsKiwgZW1wdHkgZXhjZXB0IGZvciB0aGVcbiAqICAgICBhcHByb3ByaWF0ZSB0ZW1wbGF0ZSBwaWVjZVxuICovXG5leHBvcnRzLm5ld0NvbnRhaW5lciA9IGZ1bmN0aW9uKGNvbnRhaW5lciwgbmFtZSwgYmFzZU5hbWUpIHtcbiAgICB2YXIgdGVtcGxhdGUgPSBjb250YWluZXIuX3RlbXBsYXRlO1xuICAgIHZhciBwYXJ0ID0gdGVtcGxhdGUgJiYgKHRlbXBsYXRlW25hbWVdIHx8IChiYXNlTmFtZSAmJiB0ZW1wbGF0ZVtiYXNlTmFtZV0pKTtcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QocGFydCkpIHBhcnQgPSBudWxsO1xuXG4gICAgdmFyIG91dCA9IGNvbnRhaW5lcltuYW1lXSA9IHtfdGVtcGxhdGU6IHBhcnR9O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIGFycmF5VGVtcGxhdGVyOiBzcGVjaWFsIGxvZ2ljIGZvciB0ZW1wbGF0aW5nIGJvdGggZGVmYXVsdHMgYW5kIHNwZWNpZmljIGl0ZW1zXG4gKiBpbiBhIGNvbnRhaW5lciBhcnJheSAoYW5ub3RhdGlvbnMgZXRjKVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250YWluZXI6IHRoZSBvdXRlciBjb250YWluZXIsIHNob3VsZCBhbHJlYWR5IGhhdmUgX3RlbXBsYXRlXG4gKiAgICAgaWYgdGhlcmUgKmlzKiBhIHRlbXBsYXRlIGZvciB0aGlzIHBsb3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lOiB0aGUgbmFtZSBvZiB0aGUgYXJyYXkgdG8gdGVtcGxhdGUgKGllICdhbm5vdGF0aW9ucycpXG4gKiAgICAgd2lsbCBiZSB1c2VkIHRvIGZpbmQgZGVmYXVsdCAoJ2Fubm90YXRpb25kZWZhdWx0cycgb2JqZWN0KSBhbmQgc3BlY2lmaWNcbiAqICAgICAoJ2Fubm90YXRpb25zJyBhcnJheSkgdGVtcGxhdGUgc3BlY3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5jbHVzaW9uQXR0cjogdGhlIGF0dHJpYnV0ZSBkZXRlcm1pbmluZyB0aGlzIGl0ZW0nc1xuICogICAgIGluY2x1c2lvbiBpbiB0aGUgb3V0cHV0LCB1c3VhbGx5ICd2aXNpYmxlJyBvciAnZW5hYmxlZCdcbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fToge25ld0l0ZW0sIGRlZmF1bHRJdGVtc30sIGJvdGggZnVuY3Rpb25zOlxuICogICAgIG5ld0l0ZW0oaXRlbUluKTogY3JlYXRlIGFuIG91dHB1dCBpdGVtLCBiYXJlIGV4Y2VwdCBmb3IgdGhlIGNvcnJlY3RcbiAqICAgICAgICAgdGVtcGxhdGUgYW5kIG5hbWUocyksIGFzIHRoZSBiYXNlIGZvciBzdXBwbHlEZWZhdWx0c1xuICogICAgIGRlZmF1bHRJdGVtcygpOiB0byBiZSBjYWxsZWQgYWZ0ZXIgYWxsIG5ld0l0ZW0gY2FsbHMsIHJldHVybiBhbnlcbiAqICAgICAgICAgc3BlY2lmaWMgdGVtcGxhdGUgaXRlbXMgdGhhdCBoYXZlIG5vdCBhbHJlYWR5IGJlZWVuIGluY2x1ZGVkLFxuICogICAgICAgICBhbHNvIGFzIGJhcmUgb3V0cHV0IGl0ZW1zIHJlYWR5IGZvciBzdXBwbHlEZWZhdWx0cy5cbiAqL1xuZXhwb3J0cy5hcnJheVRlbXBsYXRlciA9IGZ1bmN0aW9uKGNvbnRhaW5lciwgbmFtZSwgaW5jbHVzaW9uQXR0cikge1xuICAgIHZhciB0ZW1wbGF0ZSA9IGNvbnRhaW5lci5fdGVtcGxhdGU7XG4gICAgdmFyIGRlZmF1bHRzVGVtcGxhdGUgPSB0ZW1wbGF0ZSAmJiB0ZW1wbGF0ZVthcnJheURlZmF1bHRLZXkobmFtZSldO1xuICAgIHZhciB0ZW1wbGF0ZUl0ZW1zID0gdGVtcGxhdGUgJiYgdGVtcGxhdGVbbmFtZV07XG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGVtcGxhdGVJdGVtcykgfHwgIXRlbXBsYXRlSXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHRlbXBsYXRlSXRlbXMgPSBbXTtcbiAgICB9XG5cbiAgICB2YXIgdXNlZE5hbWVzID0ge307XG5cbiAgICBmdW5jdGlvbiBuZXdJdGVtKGl0ZW1Jbikge1xuICAgICAgICAvLyBpbmNsdWRlIG5hbWUgYW5kIHRlbXBsYXRlaXRlbW5hbWUgaW4gdGhlIG91dHB1dCBvYmplY3QgZm9yIEFMTFxuICAgICAgICAvLyBjb250YWluZXIgYXJyYXkgaXRlbXMuIE5vdGU6IHlvdSBjb3VsZCBwb3RlbnRpYWxseSB1c2UgZGlmZmVyZW50XG4gICAgICAgIC8vIG5hbWUgYW5kIHRlbXBsYXRlaXRlbW5hbWUsIGlmIHlvdSdyZSB1c2luZyBvbmUgdGVtcGxhdGUgdG8gbWFrZVxuICAgICAgICAvLyBhbm90aGVyIHRlbXBsYXRlLiB0ZW1wbGF0ZWl0ZW1uYW1lIHdvdWxkIGJlIHRoZSBuYW1lIGluIHRoZSBvcmlnaW5hbFxuICAgICAgICAvLyB0ZW1wbGF0ZSwgYW5kIG5hbWUgaXMgdGhlIG5ldyBcInN1YmNsYXNzZWRcIiBpdGVtIG5hbWUuXG4gICAgICAgIHZhciBvdXQgPSB7bmFtZTogaXRlbUluLm5hbWUsIF9pbnB1dDogaXRlbUlufTtcbiAgICAgICAgdmFyIHRlbXBsYXRlSXRlbU5hbWUgPSBvdXRbVEVNUExBVEVJVEVNTkFNRV0gPSBpdGVtSW5bVEVNUExBVEVJVEVNTkFNRV07XG5cbiAgICAgICAgLy8gbm8gaXRlbW5hbWU6IHVzZSB0aGUgZGVmYXVsdCB0ZW1wbGF0ZVxuICAgICAgICBpZighdmFsaWRJdGVtTmFtZSh0ZW1wbGF0ZUl0ZW1OYW1lKSkge1xuICAgICAgICAgICAgb3V0Ll90ZW1wbGF0ZSA9IGRlZmF1bHRzVGVtcGxhdGU7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbG9vayBmb3IgYW4gaXRlbSBtYXRjaGluZyB0aGlzIGl0ZW1uYW1lXG4gICAgICAgIC8vIG5vdGUgdGhlc2UgZG8gbm90IGluaGVyaXQgZnJvbSB0aGUgZGVmYXVsdCB0ZW1wbGF0ZSwgb25seSB0aGUgaXRlbS5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRlbXBsYXRlSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZUl0ZW0gPSB0ZW1wbGF0ZUl0ZW1zW2ldO1xuICAgICAgICAgICAgaWYodGVtcGxhdGVJdGVtLm5hbWUgPT09IHRlbXBsYXRlSXRlbU5hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBOb3RlOiBpdCdzIE9LIHRvIHVzZSBhIHRlbXBsYXRlIGl0ZW0gbW9yZSB0aGFuIG9uY2VcbiAgICAgICAgICAgICAgICAvLyBidXQgdXNpbmcgaXQgYXQgbGVhc3Qgb25jZSB3aWxsIHN0b3AgaXQgZnJvbSBnZW5lcmF0aW5nXG4gICAgICAgICAgICAgICAgLy8gYSBkZWZhdWx0IGl0ZW0gYXQgdGhlIGVuZC5cbiAgICAgICAgICAgICAgICB1c2VkTmFtZXNbdGVtcGxhdGVJdGVtTmFtZV0gPSAxO1xuICAgICAgICAgICAgICAgIG91dC5fdGVtcGxhdGUgPSB0ZW1wbGF0ZUl0ZW07XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpZG4ndCBmaW5kIGEgbWF0Y2hpbmcgdGVtcGxhdGUgaXRlbSwgc28gc2luY2UgdGhpcyBpdGVtIGlzIGludGVuZGVkXG4gICAgICAgIC8vIHRvIG9ubHkgYmUgbW9kaWZpY2F0aW9ucyBpdCdzIG1vc3QgbGlrZWx5IGJyb2tlbi4gSGlkZSBpdCB1bmxlc3NcbiAgICAgICAgLy8gaXQncyBleHBsaWNpdGx5IG1hcmtlZCB2aXNpYmxlIC0gaW4gd2hpY2ggY2FzZSBpdCBnZXRzIE5PIHRlbXBsYXRlLFxuICAgICAgICAvLyBub3QgZXZlbiB0aGUgZGVmYXVsdC5cbiAgICAgICAgb3V0W2luY2x1c2lvbkF0dHJdID0gaXRlbUluW2luY2x1c2lvbkF0dHJdIHx8IGZhbHNlO1xuICAgICAgICAvLyBzcGVjaWFsIGZhbHN5IHZhbHVlIHdlIGNhbiBsb29rIGZvciBpbiB2YWxpZGF0ZVRlbXBsYXRlXG4gICAgICAgIG91dC5fdGVtcGxhdGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZWZhdWx0SXRlbXMoKSB7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRlbXBsYXRlSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZUl0ZW0gPSB0ZW1wbGF0ZUl0ZW1zW2ldO1xuICAgICAgICAgICAgdmFyIG5hbWUgPSB0ZW1wbGF0ZUl0ZW0ubmFtZTtcbiAgICAgICAgICAgIC8vIG9ubHkgYWxsb3cgbmFtZWQgaXRlbXMgdG8gYmUgYWRkZWQgYXMgZGVmYXVsdHMsXG4gICAgICAgICAgICAvLyBhbmQgb25seSBhbGxvdyBlYWNoIG5hbWUgb25jZVxuICAgICAgICAgICAgaWYodmFsaWRJdGVtTmFtZShuYW1lKSAmJiAhdXNlZE5hbWVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dGkgPSB7XG4gICAgICAgICAgICAgICAgICAgIF90ZW1wbGF0ZTogdGVtcGxhdGVJdGVtLFxuICAgICAgICAgICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgICAgICAgICBfaW5wdXQ6IHtfdGVtcGxhdGVpdGVtbmFtZTogbmFtZX1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG91dGlbVEVNUExBVEVJVEVNTkFNRV0gPSB0ZW1wbGF0ZUl0ZW1bVEVNUExBVEVJVEVNTkFNRV07XG4gICAgICAgICAgICAgICAgb3V0LnB1c2gob3V0aSk7XG4gICAgICAgICAgICAgICAgdXNlZE5hbWVzW25hbWVdID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIG5ld0l0ZW06IG5ld0l0ZW0sXG4gICAgICAgIGRlZmF1bHRJdGVtczogZGVmYXVsdEl0ZW1zXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkSXRlbU5hbWUobmFtZSkge1xuICAgIHJldHVybiBuYW1lICYmIHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gYXJyYXlEZWZhdWx0S2V5KG5hbWUpIHtcbiAgICB2YXIgbGFzdENoYXIgPSBuYW1lLmxlbmd0aCAtIDE7XG4gICAgaWYobmFtZS5jaGFyQXQobGFzdENoYXIpICE9PSAncycpIHtcbiAgICAgICAgTGliLndhcm4oJ2JhZCBhcmd1bWVudCB0byBhcnJheURlZmF1bHRLZXk6ICcgKyBuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWUuc3Vic3RyKDAsIG5hbWUubGVuZ3RoIC0gMSkgKyAnZGVmYXVsdHMnO1xufVxuZXhwb3J0cy5hcnJheURlZmF1bHRLZXkgPSBhcnJheURlZmF1bHRLZXk7XG5cbi8qKlxuICogYXJyYXlFZGl0b3I6IGhlbHBlciBmb3IgZWRpdGluZyBhcnJheSBpdGVtcyB0aGF0IG1heSBoYXZlIGNvbWUgZnJvbVxuICogICAgIHRlbXBsYXRlIGRlZmF1bHRzIChpbiB3aGljaCBjYXNlIHRoZXkgd2lsbCBub3QgZXhpc3QgaW4gdGhlIGlucHV0IHlldClcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFyZW50SW46IHRoZSBpbnB1dCBjb250YWluZXIgKGVnIGdkLmxheW91dClcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250YWluZXJTdHI6IHRoZSBhdHRyaWJ1dGUgc3RyaW5nIGZvciB0aGUgY29udGFpbmVyIGluc2lkZVxuICogICAgIGBwYXJlbnRJbmAuXG4gKiBAcGFyYW0ge29iamVjdH0gaXRlbU91dDogdGhlIF9mdWxsKiBpdGVtIChlZyBnZC5fZnVsbExheW91dC5hbm5vdGF0aW9uc1swXSlcbiAqICAgICB0aGF0IHdlJ2xsIGJlIGVkaXRpbmcuIEFzc3VtZWQgdG8gaGF2ZSBiZWVuIGNyZWF0ZWQgYnkgYGFycmF5VGVtcGxhdGVyYC5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fToge21vZGlmeUJhc2UsIG1vZGlmeUl0ZW0sIGdldFVwZGF0ZU9iaiwgYXBwbHlVcGRhdGV9LCBhbGwgZnVuY3Rpb25zOlxuICogICAgIG1vZGlmeUJhc2UoYXR0ciwgdmFsdWUpOiBBZGQgYW4gdXBkYXRlIHRoYXQncyAqbm90KiByZWxhdGVkIHRvIHRoZSBpdGVtLlxuICogICAgICAgICBgYXR0cmAgaXMgdGhlIGZ1bGwgYXR0cmlidXRlIHN0cmluZy5cbiAqICAgICBtb2RpZnlJdGVtKGF0dHIsIHZhbHVlKTogQWRkIGFuIHVwZGF0ZSB0byB0aGUgaXRlbS4gYGF0dHJgIGlzIGp1c3QgdGhlXG4gKiAgICAgICAgIHBvcnRpb24gb2YgdGhlIGF0dHJpYnV0ZSBzdHJpbmcgaW5zaWRlIHRoZSBpdGVtLlxuICogICAgIGdldFVwZGF0ZU9iaigpOiBHZXQgdGhlIGZpbmFsIGNvbnN0cnVjdGVkIHVwZGF0ZSBvYmplY3QsIHRvIHVzZSBpblxuICogICAgICAgICBgcmVzdHlsZWAgb3IgYHJlbGF5b3V0YC4gQWxzbyByZXNldHMgdGhlIHVwZGF0ZSBvYmplY3QgaW4gY2FzZSB0aGlzXG4gKiAgICAgICAgIHVwZGF0ZSB3YXMgY2FuY2VsZWQuXG4gKiAgICAgYXBwbHlVcGRhdGUoYXR0ciwgdmFsdWUpOiBvcHRpb25hbGx5IGFkZCBhbiB1cGRhdGUgYGF0dHI6IHZhbHVlYCxcbiAqICAgICAgICAgdGhlbiBhcHBseSBpdCB0byBgcGFyZW50YCB3aGljaCBzaG91bGQgYmUgdGhlIHBhcmVudCBvZiBgY29udGFpbmVySW5gLFxuICogICAgICAgICBpZSB0aGUgb2JqZWN0IHRvIHdoaWNoIGBjb250YWluZXJTdHJgIGlzIHRoZSBhdHRyaWJ1dGUgc3RyaW5nLlxuICovXG5leHBvcnRzLmFycmF5RWRpdG9yID0gZnVuY3Rpb24ocGFyZW50SW4sIGNvbnRhaW5lclN0ciwgaXRlbU91dCkge1xuICAgIHZhciBsZW5ndGhJbiA9IChMaWIubmVzdGVkUHJvcGVydHkocGFyZW50SW4sIGNvbnRhaW5lclN0cikuZ2V0KCkgfHwgW10pLmxlbmd0aDtcbiAgICB2YXIgaW5kZXggPSBpdGVtT3V0Ll9pbmRleDtcbiAgICAvLyBDaGVjayB0aGF0IHdlIGFyZSBpbmRlZWQgb2ZmIHRoZSBlbmQgb2YgdGhpcyBjb250YWluZXIuXG4gICAgLy8gT3RoZXJ3aXNlIGEgZGV2aW91cyB1c2VyIGNvdWxkIHB1dCBhIGtleSBgX3RlbXBsYXRlaXRlbW5hbWVgIGluIHRoZWlyXG4gICAgLy8gb3duIGlucHV0IGFuZCBicmVhayBsb3RzIG9mIHRoaW5ncy5cbiAgICB2YXIgdGVtcGxhdGVJdGVtTmFtZSA9IChpbmRleCA+PSBsZW5ndGhJbikgJiYgKGl0ZW1PdXQuX2lucHV0IHx8IHt9KS5fdGVtcGxhdGVpdGVtbmFtZTtcbiAgICBpZih0ZW1wbGF0ZUl0ZW1OYW1lKSBpbmRleCA9IGxlbmd0aEluO1xuICAgIHZhciBpdGVtU3RyID0gY29udGFpbmVyU3RyICsgJ1snICsgaW5kZXggKyAnXSc7XG5cbiAgICB2YXIgdXBkYXRlO1xuICAgIGZ1bmN0aW9uIHJlc2V0VXBkYXRlKCkge1xuICAgICAgICB1cGRhdGUgPSB7fTtcbiAgICAgICAgaWYodGVtcGxhdGVJdGVtTmFtZSkge1xuICAgICAgICAgICAgdXBkYXRlW2l0ZW1TdHJdID0ge307XG4gICAgICAgICAgICB1cGRhdGVbaXRlbVN0cl1bVEVNUExBVEVJVEVNTkFNRV0gPSB0ZW1wbGF0ZUl0ZW1OYW1lO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlc2V0VXBkYXRlKCk7XG5cbiAgICBmdW5jdGlvbiBtb2RpZnlCYXNlKGF0dHIsIHZhbHVlKSB7XG4gICAgICAgIHVwZGF0ZVthdHRyXSA9IHZhbHVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vZGlmeUl0ZW0oYXR0ciwgdmFsdWUpIHtcbiAgICAgICAgaWYodGVtcGxhdGVJdGVtTmFtZSkge1xuICAgICAgICAgICAgLy8gd2UncmUgbWFraW5nIGEgbmV3IG9iamVjdDogZWRpdCB0aGF0IG9iamVjdFxuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHVwZGF0ZVtpdGVtU3RyXSwgYXR0cikuc2V0KHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHdlJ3JlIGVkaXRpbmcgYW4gZXhpc3Rpbmcgb2JqZWN0OiBpbmNsdWRlICpqdXN0KiB0aGUgZWRpdFxuICAgICAgICAgICAgdXBkYXRlW2l0ZW1TdHIgKyAnLicgKyBhdHRyXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VXBkYXRlT2JqKCkge1xuICAgICAgICB2YXIgdXBkYXRlT3V0ID0gdXBkYXRlO1xuICAgICAgICByZXNldFVwZGF0ZSgpO1xuICAgICAgICByZXR1cm4gdXBkYXRlT3V0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGx5VXBkYXRlKGF0dHIsIHZhbHVlKSB7XG4gICAgICAgIGlmKGF0dHIpIG1vZGlmeUl0ZW0oYXR0ciwgdmFsdWUpO1xuICAgICAgICB2YXIgdXBkYXRlVG9BcHBseSA9IGdldFVwZGF0ZU9iaigpO1xuICAgICAgICBmb3IodmFyIGtleSBpbiB1cGRhdGVUb0FwcGx5KSB7XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkocGFyZW50SW4sIGtleSkuc2V0KHVwZGF0ZVRvQXBwbHlba2V5XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBtb2RpZnlCYXNlOiBtb2RpZnlCYXNlLFxuICAgICAgICBtb2RpZnlJdGVtOiBtb2RpZnlJdGVtLFxuICAgICAgICBnZXRVcGRhdGVPYmo6IGdldFVwZGF0ZU9iaixcbiAgICAgICAgYXBwbHlVcGRhdGU6IGFwcGx5VXBkYXRlXG4gICAgfTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vcGxvdHMvcGxvdHMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IHJlcXVpcmUoJy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIFRpdGxlcyA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvdGl0bGVzJyk7XG52YXIgTW9kZUJhciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvbW9kZWJhcicpO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgYWxpZ25tZW50Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL2FsaWdubWVudCcpO1xudmFyIGF4aXNDb25zdHJhaW50cyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9jb25zdHJhaW50cycpO1xudmFyIGVuZm9yY2VBeGlzQ29uc3RyYWludHMgPSBheGlzQ29uc3RyYWludHMuZW5mb3JjZTtcbnZhciBjbGVhbkF4aXNDb25zdHJhaW50cyA9IGF4aXNDb25zdHJhaW50cy5jbGVhbjtcbnZhciBkb0F1dG9SYW5nZSA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2UnKS5kb0F1dG9SYW5nZTtcblxuZXhwb3J0cy5sYXlvdXRTdHlsZXMgPSBmdW5jdGlvbihnZCkge1xuICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW1Bsb3RzLmRvQXV0b01hcmdpbiwgbHNJbm5lcl0sIGdkKTtcbn07XG5cbmZ1bmN0aW9uIG92ZXJsYXBwaW5nRG9tYWluKHhEb21haW4sIHlEb21haW4sIGRvbWFpbnMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZG9tYWlucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZXhpc3RpbmdYID0gZG9tYWluc1tpXVswXSxcbiAgICAgICAgICAgIGV4aXN0aW5nWSA9IGRvbWFpbnNbaV1bMV07XG5cbiAgICAgICAgaWYoZXhpc3RpbmdYWzBdID49IHhEb21haW5bMV0gfHwgZXhpc3RpbmdYWzFdIDw9IHhEb21haW5bMF0pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmKGV4aXN0aW5nWVswXSA8IHlEb21haW5bMV0gJiYgZXhpc3RpbmdZWzFdID4geURvbWFpblswXSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBsc0lubmVyKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciBwYWQgPSBncy5wO1xuICAgIHZhciBheExpc3QgPSBBeGVzLmxpc3QoZ2QsICcnLCB0cnVlKTtcbiAgICB2YXIgaSwgc3VicGxvdCwgcGxvdGluZm8sIHhhLCB5YTtcblxuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2LnN0eWxlKHtcbiAgICAgICAgd2lkdGg6IChnZC5fY29udGV4dC5yZXNwb25zaXZlICYmIGZ1bGxMYXlvdXQuYXV0b3NpemUgJiYgIWdkLl9jb250ZXh0Ll9oYXNaZXJvV2lkdGggJiYgIWdkLmxheW91dC53aWR0aCkgPyAnMTAwJScgOiBmdWxsTGF5b3V0LndpZHRoICsgJ3B4JyxcbiAgICAgICAgaGVpZ2h0OiAoZ2QuX2NvbnRleHQucmVzcG9uc2l2ZSAmJiBmdWxsTGF5b3V0LmF1dG9zaXplICYmICFnZC5fY29udGV4dC5faGFzWmVyb0hlaWdodCAmJiAhZ2QubGF5b3V0LmhlaWdodCkgPyAnMTAwJScgOiBmdWxsTGF5b3V0LmhlaWdodCArICdweCdcbiAgICB9KVxuICAgIC5zZWxlY3RBbGwoJy5tYWluLXN2ZycpXG4gICAgLmNhbGwoRHJhd2luZy5zZXRTaXplLCBmdWxsTGF5b3V0LndpZHRoLCBmdWxsTGF5b3V0LmhlaWdodCk7XG4gICAgZ2QuX2NvbnRleHQuc2V0QmFja2dyb3VuZChnZCwgZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yKTtcblxuICAgIGV4cG9ydHMuZHJhd01haW5UaXRsZShnZCk7XG4gICAgTW9kZUJhci5tYW5hZ2UoZ2QpO1xuXG4gICAgLy8gX2hhcygnY2FydGVzaWFuJykgbWVhbnMgU1ZHIHNwZWNpZmljYWxseSwgbm90IEdMMkQgLSBidXQgR0wyRFxuICAgIC8vIGNhbiBzdGlsbCBnZXQgaGVyZSBiZWNhdXNlIGl0IG1ha2VzIHNvbWUgb2YgdGhlIFNWRyBzdHJ1Y3R1cmVcbiAgICAvLyBmb3Igc2hhcmVkIGZlYXR1cmVzIGxpa2Ugc2VsZWN0aW9ucy5cbiAgICBpZighZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICByZXR1cm4gZ2QuX3Byb21pc2VzLmxlbmd0aCAmJiBQcm9taXNlLmFsbChnZC5fcHJvbWlzZXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldExpbmVQb3NpdGlvbihheCwgY291bnRlckF4LCBzaWRlKSB7XG4gICAgICAgIHZhciBsd0hhbGYgPSBheC5fbHcgLyAyO1xuXG4gICAgICAgIGlmKGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd4Jykge1xuICAgICAgICAgICAgaWYoIWNvdW50ZXJBeCkgcmV0dXJuIGdzLnQgKyBncy5oICogKDEgLSAoYXgucG9zaXRpb24gfHwgMCkpICsgKGx3SGFsZiAlIDEpO1xuICAgICAgICAgICAgZWxzZSBpZihzaWRlID09PSAndG9wJykgcmV0dXJuIGNvdW50ZXJBeC5fb2Zmc2V0IC0gcGFkIC0gbHdIYWxmO1xuICAgICAgICAgICAgcmV0dXJuIGNvdW50ZXJBeC5fb2Zmc2V0ICsgY291bnRlckF4Ll9sZW5ndGggKyBwYWQgKyBsd0hhbGY7XG4gICAgICAgIH1cblxuICAgICAgICBpZighY291bnRlckF4KSByZXR1cm4gZ3MubCArIGdzLncgKiAoYXgucG9zaXRpb24gfHwgMCkgKyAobHdIYWxmICUgMSk7XG4gICAgICAgIGVsc2UgaWYoc2lkZSA9PT0gJ3JpZ2h0JykgcmV0dXJuIGNvdW50ZXJBeC5fb2Zmc2V0ICsgY291bnRlckF4Ll9sZW5ndGggKyBwYWQgKyBsd0hhbGY7XG4gICAgICAgIHJldHVybiBjb3VudGVyQXguX29mZnNldCAtIHBhZCAtIGx3SGFsZjtcbiAgICB9XG5cbiAgICAvLyBzb21lIHByZXBhcmF0aW9uIG9mIGF4aXMgcG9zaXRpb24gaW5mb1xuICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG5cbiAgICAgICAgLy8gcmVzZXQgc2NhbGUgaW4gY2FzZSB0aGUgbWFyZ2lucyBoYXZlIGNoYW5nZWRcbiAgICAgICAgYXguc2V0U2NhbGUoKTtcblxuICAgICAgICB2YXIgY291bnRlckF4ID0gYXguX2FuY2hvckF4aXM7XG5cbiAgICAgICAgLy8gY2xlYXIgYXhpcyBsaW5lIHBvc2l0aW9ucywgdG8gYmUgc2V0IGluIHRoZSBzdWJwbG90IGxvb3AgYmVsb3dcbiAgICAgICAgYXguX2xpbmVwb3NpdGlvbnMgPSB7fTtcblxuICAgICAgICAvLyBzdGFzaCBjcmlzcFJvdW5kZWQgbGluZXdpZHRoIHNvIHdlIGRvbid0IG5lZWQgdG8gcGFzcyBnZCBhbGwgb3ZlciB0aGUgcGxhY2VcbiAgICAgICAgYXguX2x3ID0gRHJhd2luZy5jcmlzcFJvdW5kKGdkLCBheC5saW5ld2lkdGgsIDEpO1xuXG4gICAgICAgIC8vIGZpZ3VyZSBvdXQgdGhlIG1haW4gYXhpcyBsaW5lIGFuZCBtYWluIG1pcnJvciBsaW5lIHBvc2l0aW9uLlxuICAgICAgICAvLyBpdCdzIGVhc2llciB0byBmb2xsb3cgdGhlIGxvZ2ljIGlmIHdlIGhhbmRsZSB0aGVzZSBzZXBhcmF0ZWx5IGZyb21cbiAgICAgICAgLy8gYXguX2xpbmVwb3NpdGlvbnMsIHdoaWNoIGFyZSBvbmx5IHVzZWQgYnkgbWlycm9yPWFsbHRpY2tzXG4gICAgICAgIC8vIGZvciBub24tbWFpbi1zdWJwbG90IHRpY2tzLCBhbmQgbWlycm9yPWFsbCh0aWNrcyk/IGZvciB6ZXJvIGxpbmVcbiAgICAgICAgLy8gaGlkaW5nIGxvZ2ljXG4gICAgICAgIGF4Ll9tYWluTGluZVBvc2l0aW9uID0gZ2V0TGluZVBvc2l0aW9uKGF4LCBjb3VudGVyQXgsIGF4LnNpZGUpO1xuICAgICAgICBheC5fbWFpbk1pcnJvclBvc2l0aW9uID0gKGF4Lm1pcnJvciAmJiBjb3VudGVyQXgpID9cbiAgICAgICAgICAgIGdldExpbmVQb3NpdGlvbihheCwgY291bnRlckF4LFxuICAgICAgICAgICAgICAgIGFsaWdubWVudENvbnN0YW50cy5PUFBPU0lURV9TSURFW2F4LnNpZGVdKSA6IG51bGw7XG5cbiAgICAgICAgLy8gRmlndXJlIG91dCB3aGljaCBzdWJwbG90IHRvIGRyYXcgdGlja3MsIGxhYmVscywgJiBheGlzIGxpbmVzIG9uXG4gICAgICAgIC8vIGRvIHRoaXMgYXMgYSBzZXBhcmF0ZSBsb29wIHNvIHdlIGFscmVhZHkgaGF2ZSBhbGwgdGhlXG4gICAgICAgIC8vIF9tYWluQXhpcyBhbmQgX2FuY2hvckF4aXMgbGlua3Mgc2V0XG4gICAgICAgIGF4Ll9tYWluU3VicGxvdCA9IGZpbmRNYWluU3VicGxvdChheCwgZnVsbExheW91dCk7XG4gICAgfVxuXG4gICAgLy8gZmlndXJlIG91dCB3aGljaCBiYWNrZ3JvdW5kcyB3ZSBuZWVkIHRvIGRyYXcsXG4gICAgLy8gYW5kIGluIHdoaWNoIGxheWVycyB0byBwdXQgdGhlbVxuICAgIHZhciBsb3dlckJhY2tncm91bmRJRHMgPSBbXTtcbiAgICB2YXIgYmFja2dyb3VuZElkcyA9IFtdO1xuICAgIHZhciBsb3dlckRvbWFpbnMgPSBbXTtcbiAgICAvLyBubyBuZWVkIHRvIGRyYXcgYmFja2dyb3VuZCB3aGVuIHBhcGVyIGFuZCBwbG90IGNvbG9yIGFyZSB0aGUgc2FtZSBjb2xvcixcbiAgICAvLyBhY3RpdmF0ZSBtb2RlIGp1c3QgZm9yIGxhcmdlIHNwbG9tICh3aGljaCBiZW5lZml0IHRoZSBtb3N0IGZyb20gdGhpc1xuICAgIC8vIG9wdGltaXphdGlvbiksIGJ1dCB0aGlzIGNvdWxkIGFwcGx5IHRvIGFsbCBjYXJ0ZXNpYW4gc3VicGxvdHMuXG4gICAgdmFyIG5vTmVlZEZvckJnID0gKFxuICAgICAgICBDb2xvci5vcGFjaXR5KGZ1bGxMYXlvdXQucGFwZXJfYmdjb2xvcikgPT09IDEgJiZcbiAgICAgICAgQ29sb3Iub3BhY2l0eShmdWxsTGF5b3V0LnBsb3RfYmdjb2xvcikgPT09IDEgJiZcbiAgICAgICAgZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yID09PSBmdWxsTGF5b3V0LnBsb3RfYmdjb2xvclxuICAgICk7XG5cbiAgICBmb3Ioc3VicGxvdCBpbiBmdWxsTGF5b3V0Ll9wbG90cykge1xuICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuXG4gICAgICAgIGlmKHBsb3RpbmZvLm1haW5wbG90KSB7XG4gICAgICAgICAgICAvLyBtYWlucGxvdCBpcyBhIHJlZmVyZW5jZSB0byB0aGUgbWFpbiBwbG90IHRoaXMgb25lIGlzIG92ZXJsYWlkIG9uXG4gICAgICAgICAgICAvLyBzbyBpZiBpdCBleGlzdHMsIHRoaXMgaXMgYW4gb3ZlcmxhaWQgcGxvdCBhbmQgd2UgZG9uJ3QgbmVlZCB0b1xuICAgICAgICAgICAgLy8gZ2l2ZSBpdCBpdHMgb3duIGJhY2tncm91bmRcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLmJnKSB7XG4gICAgICAgICAgICAgICAgcGxvdGluZm8uYmcucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwbG90aW5mby5iZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciB4RG9tYWluID0gcGxvdGluZm8ueGF4aXMuZG9tYWluO1xuICAgICAgICAgICAgdmFyIHlEb21haW4gPSBwbG90aW5mby55YXhpcy5kb21haW47XG4gICAgICAgICAgICB2YXIgcGxvdGdyb3VwID0gcGxvdGluZm8ucGxvdGdyb3VwO1xuXG4gICAgICAgICAgICBpZihvdmVybGFwcGluZ0RvbWFpbih4RG9tYWluLCB5RG9tYWluLCBsb3dlckRvbWFpbnMpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBnTm9kZSA9IHBsb3Rncm91cC5ub2RlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHBsb3Rncm91cEJnID0gcGxvdGluZm8uYmcgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ3JlY3QnLCAnYmcnKTtcbiAgICAgICAgICAgICAgICBwZ05vZGUuaW5zZXJ0QmVmb3JlKHBsb3Rncm91cEJnLm5vZGUoKSwgcGdOb2RlLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgICAgICAgICAgIGJhY2tncm91bmRJZHMucHVzaChzdWJwbG90KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGxvdGdyb3VwLnNlbGVjdCgncmVjdC5iZycpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIGxvd2VyRG9tYWlucy5wdXNoKFt4RG9tYWluLCB5RG9tYWluXSk7XG4gICAgICAgICAgICAgICAgaWYoIW5vTmVlZEZvckJnKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvd2VyQmFja2dyb3VuZElEcy5wdXNoKHN1YnBsb3QpO1xuICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kSWRzLnB1c2goc3VicGxvdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbm93IGNyZWF0ZSBhbGwgdGhlIGxvd2VyLWxheWVyIGJhY2tncm91bmRzIGF0IG9uY2Ugbm93IHRoYXRcbiAgICAvLyB3ZSBoYXZlIHRoZSBsaXN0IG9mIHN1YnBsb3RzIHRoYXQgbmVlZCB0aGVtXG4gICAgdmFyIGxvd2VyQmFja2dyb3VuZHMgPSBmdWxsTGF5b3V0Ll9iZ0xheWVyLnNlbGVjdEFsbCgnLmJnJylcbiAgICAgICAgLmRhdGEobG93ZXJCYWNrZ3JvdW5kSURzKTtcblxuICAgIGxvd2VyQmFja2dyb3VuZHMuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZCgnYmcnLCB0cnVlKTtcblxuICAgIGxvd2VyQmFja2dyb3VuZHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbG93ZXJCYWNrZ3JvdW5kcy5lYWNoKGZ1bmN0aW9uKHN1YnBsb3QpIHtcbiAgICAgICAgZnVsbExheW91dC5fcGxvdHNbc3VicGxvdF0uYmcgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgfSk7XG5cbiAgICAvLyBzdHlsZSBhbGwgYmFja2dyb3VuZHNcbiAgICBmb3IoaSA9IDA7IGkgPCBiYWNrZ3JvdW5kSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbYmFja2dyb3VuZElkc1tpXV07XG4gICAgICAgIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgaWYocGxvdGluZm8uYmcpIHtcbiAgICAgICAgICAgIHBsb3RpbmZvLmJnXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRSZWN0LFxuICAgICAgICAgICAgICAgICAgICB4YS5fb2Zmc2V0IC0gcGFkLCB5YS5fb2Zmc2V0IC0gcGFkLFxuICAgICAgICAgICAgICAgICAgICB4YS5fbGVuZ3RoICsgMiAqIHBhZCwgeWEuX2xlbmd0aCArIDIgKiBwYWQpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZnVsbExheW91dC5wbG90X2JnY29sb3IpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCFmdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMpIHtcbiAgICAgICAgZm9yKHN1YnBsb3QgaW4gZnVsbExheW91dC5fcGxvdHMpIHtcbiAgICAgICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbc3VicGxvdF07XG4gICAgICAgICAgICB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICAgICAgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgICAgICAgICAgLy8gQ2xpcCBzbyB0aGF0IGRhdGEgb25seSBzaG93cyB1cCBvbiB0aGUgcGxvdCBhcmVhLlxuICAgICAgICAgICAgdmFyIGNsaXBJZCA9IHBsb3RpbmZvLmNsaXBJZCA9ICdjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIHN1YnBsb3QgKyAncGxvdCc7XG5cbiAgICAgICAgICAgIHZhciBwbG90Q2xpcCA9IExpYi5lbnN1cmVTaW5nbGVCeUlkKGZ1bGxMYXlvdXQuX2NsaXBzLCAnY2xpcFBhdGgnLCBjbGlwSWQsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgICAgICBzLmNsYXNzZWQoJ3Bsb3RjbGlwJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgncmVjdCcpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLmNsaXBSZWN0ID0gcGxvdENsaXAuc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHhhLl9sZW5ndGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiB5YS5fbGVuZ3RoXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUocGxvdGluZm8ucGxvdCwgeGEuX29mZnNldCwgeWEuX29mZnNldCk7XG5cbiAgICAgICAgICAgIHZhciBwbG90Q2xpcElkO1xuICAgICAgICAgICAgdmFyIGxheWVyQ2xpcElkO1xuXG4gICAgICAgICAgICBpZihwbG90aW5mby5faGFzQ2xpcE9uQXhpc0ZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcGxvdENsaXBJZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGF5ZXJDbGlwSWQgPSBjbGlwSWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBsb3RDbGlwSWQgPSBjbGlwSWQ7XG4gICAgICAgICAgICAgICAgbGF5ZXJDbGlwSWQgPSBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwocGxvdGluZm8ucGxvdCwgcGxvdENsaXBJZCk7XG5cbiAgICAgICAgICAgIC8vIHN0YXNoIGxheWVyIGNsaXBJZCB2YWx1ZSAobnVsbCBvciBzYW1lIGFzIGNsaXBJZClcbiAgICAgICAgICAgIC8vIHRvIERSWSB1cCBEcmF3aW5nLnNldENsaXBVcmwgY2FsbHMgb24gdHJhY2UtbW9kdWxlIGFuZCB0cmFjZSBsYXllcnNcbiAgICAgICAgICAgIC8vIGRvd25zdHJlYW1cbiAgICAgICAgICAgIHBsb3RpbmZvLmxheWVyQ2xpcElkID0gbGF5ZXJDbGlwSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgeExpbmVzWExlZnQsIHhMaW5lc1hSaWdodCwgeExpbmVzWUJvdHRvbSwgeExpbmVzWVRvcCxcbiAgICAgICAgbGVmdFlMaW5lV2lkdGgsIHJpZ2h0WUxpbmVXaWR0aDtcbiAgICB2YXIgeUxpbmVzWUJvdHRvbSwgeUxpbmVzWVRvcCwgeUxpbmVzWExlZnQsIHlMaW5lc1hSaWdodCxcbiAgICAgICAgY29ubmVjdFlCb3R0b20sIGNvbm5lY3RZVG9wO1xuICAgIHZhciBleHRyYVN1YnBsb3Q7XG5cbiAgICBmdW5jdGlvbiB4TGluZVBhdGgoeSkge1xuICAgICAgICByZXR1cm4gJ00nICsgeExpbmVzWExlZnQgKyAnLCcgKyB5ICsgJ0gnICsgeExpbmVzWFJpZ2h0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHhMaW5lUGF0aEZyZWUoeSkge1xuICAgICAgICByZXR1cm4gJ00nICsgeGEuX29mZnNldCArICcsJyArIHkgKyAnaCcgKyB4YS5fbGVuZ3RoO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHlMaW5lUGF0aCh4KSB7XG4gICAgICAgIHJldHVybiAnTScgKyB4ICsgJywnICsgeUxpbmVzWVRvcCArICdWJyArIHlMaW5lc1lCb3R0b207XG4gICAgfVxuXG4gICAgZnVuY3Rpb24geUxpbmVQYXRoRnJlZSh4KSB7XG4gICAgICAgIHJldHVybiAnTScgKyB4ICsgJywnICsgeWEuX29mZnNldCArICd2JyArIHlhLl9sZW5ndGg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFpblBhdGgoYXgsIHBhdGhGbiwgcGF0aEZuRnJlZSkge1xuICAgICAgICBpZighYXguc2hvd2xpbmUgfHwgc3VicGxvdCAhPT0gYXguX21haW5TdWJwbG90KSByZXR1cm4gJyc7XG4gICAgICAgIGlmKCFheC5fYW5jaG9yQXhpcykgcmV0dXJuIHBhdGhGbkZyZWUoYXguX21haW5MaW5lUG9zaXRpb24pO1xuICAgICAgICB2YXIgb3V0ID0gcGF0aEZuKGF4Ll9tYWluTGluZVBvc2l0aW9uKTtcbiAgICAgICAgaWYoYXgubWlycm9yKSBvdXQgKz0gcGF0aEZuKGF4Ll9tYWluTWlycm9yUG9zaXRpb24pO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIGZvcihzdWJwbG90IGluIGZ1bGxMYXlvdXQuX3Bsb3RzKSB7XG4gICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbc3VicGxvdF07XG4gICAgICAgIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogeCBsaW5lcyBnZXQgbG9uZ2VyIHdoZXJlIHRoZXkgbWVldCB5IGxpbmVzLCB0byBtYWtlIGEgY3Jpc3AgY29ybmVyLlxuICAgICAgICAgKiBUaGUgeCBsaW5lcyBnZXQgdGhlIHBhZGRpbmcgKG1hcmdpbi5wYWQpIHBsdXMgdGhlIHkgbGluZSB3aWR0aCB0b1xuICAgICAgICAgKiBmaWxsIHVwIHRoZSBjb3JuZXIgbmljZWx5LiBGcmVlIHggbGluZXMgYXJlIGV4Y2x1ZGVkIC0gdGhleSBhbHdheXNcbiAgICAgICAgICogc3BhbiBleGFjdGx5IHRoZSBkYXRhIGFyZWEgb2YgdGhlIHBsb3RcbiAgICAgICAgICpcbiAgICAgICAgICogIHwgWFhYWFhcbiAgICAgICAgICogIHwgWFhYWFhcbiAgICAgICAgICogIHxcbiAgICAgICAgICogICstLS0tLS1cbiAgICAgICAgICogICAgIHgxXG4gICAgICAgICAqICAgIC0tLS0tXG4gICAgICAgICAqICAgICB4MlxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIHhQYXRoID0gJ00wLDAnO1xuICAgICAgICBpZihzaG91bGRTaG93TGluZXNPclRpY2tzKHhhLCBzdWJwbG90KSkge1xuICAgICAgICAgICAgbGVmdFlMaW5lV2lkdGggPSBmaW5kQ291bnRlckF4aXNMaW5lV2lkdGgoeGEsICdsZWZ0JywgeWEsIGF4TGlzdCk7XG4gICAgICAgICAgICB4TGluZXNYTGVmdCA9IHhhLl9vZmZzZXQgLSAobGVmdFlMaW5lV2lkdGggPyAocGFkICsgbGVmdFlMaW5lV2lkdGgpIDogMCk7XG4gICAgICAgICAgICByaWdodFlMaW5lV2lkdGggPSBmaW5kQ291bnRlckF4aXNMaW5lV2lkdGgoeGEsICdyaWdodCcsIHlhLCBheExpc3QpO1xuICAgICAgICAgICAgeExpbmVzWFJpZ2h0ID0geGEuX29mZnNldCArIHhhLl9sZW5ndGggKyAocmlnaHRZTGluZVdpZHRoID8gKHBhZCArIHJpZ2h0WUxpbmVXaWR0aCkgOiAwKTtcbiAgICAgICAgICAgIHhMaW5lc1lCb3R0b20gPSBnZXRMaW5lUG9zaXRpb24oeGEsIHlhLCAnYm90dG9tJyk7XG4gICAgICAgICAgICB4TGluZXNZVG9wID0gZ2V0TGluZVBvc2l0aW9uKHhhLCB5YSwgJ3RvcCcpO1xuXG4gICAgICAgICAgICAvLyBzYXZlIGF4aXMgbGluZSBwb3NpdGlvbnMgZm9yIGV4dHJhIHRpY2tzIHRvIHJlZmVyZW5jZVxuICAgICAgICAgICAgLy8gZWFjaCBzdWJwbG90IHRoYXQgZ2V0cyB0aWNrcyBmcm9tIFwiYWxsdGlja3NcIiBnZXRzIGFuIGVudHJ5OlxuICAgICAgICAgICAgLy8gICAgW2xlZnQgb3IgYm90dG9tLCByaWdodCBvciB0b3BdXG4gICAgICAgICAgICBleHRyYVN1YnBsb3QgPSAoIXhhLl9hbmNob3JBeGlzIHx8IHN1YnBsb3QgIT09IHhhLl9tYWluU3VicGxvdCk7XG4gICAgICAgICAgICBpZihleHRyYVN1YnBsb3QgJiYgKHhhLm1pcnJvciA9PT0gJ2FsbHRpY2tzJyB8fCB4YS5taXJyb3IgPT09ICdhbGwnKSkge1xuICAgICAgICAgICAgICAgIHhhLl9saW5lcG9zaXRpb25zW3N1YnBsb3RdID0gW3hMaW5lc1lCb3R0b20sIHhMaW5lc1lUb3BdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB4UGF0aCA9IG1haW5QYXRoKHhhLCB4TGluZVBhdGgsIHhMaW5lUGF0aEZyZWUpO1xuICAgICAgICAgICAgaWYoZXh0cmFTdWJwbG90ICYmIHhhLnNob3dsaW5lICYmICh4YS5taXJyb3IgPT09ICdhbGwnIHx8IHhhLm1pcnJvciA9PT0gJ2FsbHRpY2tzJykpIHtcbiAgICAgICAgICAgICAgICB4UGF0aCArPSB4TGluZVBhdGgoeExpbmVzWUJvdHRvbSkgKyB4TGluZVBhdGgoeExpbmVzWVRvcCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnhsaW5lc1xuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgeGEuX2x3ICsgJ3B4JylcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHhhLnNob3dsaW5lID9cbiAgICAgICAgICAgICAgICAgICAgeGEubGluZWNvbG9yIDogJ3JnYmEoMCwwLDAsMCknKTtcbiAgICAgICAgfVxuICAgICAgICBwbG90aW5mby54bGluZXMuYXR0cignZCcsIHhQYXRoKTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiB5IGxpbmVzIHRoYXQgbWVldCB4IGF4ZXMgZ2V0IGxvbmdlciBvbmx5IGJ5IG1hcmdpbi5wYWQsIGJlY2F1c2VcbiAgICAgICAgICogdGhlIHggYXhlcyBmaWxsIGluIHRoZSBjb3JuZXIgc3BhY2UuIEZyZWUgeSBheGVzLCBsaWtlIGZyZWUgeCBheGVzLFxuICAgICAgICAgKiBhbHdheXMgc3BhbiBleGFjdGx5IHRoZSBkYXRhIGFyZWEgb2YgdGhlIHBsb3RcbiAgICAgICAgICpcbiAgICAgICAgICogICB8ICAgfCBYWFhYXG4gICAgICAgICAqIHkyfCB5MXwgWFhYWFxuICAgICAgICAgKiAgIHwgICB8IFhYWFhcbiAgICAgICAgICogICAgICAgfFxuICAgICAgICAgKiAgICAgICArLS0tLS1cbiAgICAgICAgICovXG4gICAgICAgIHZhciB5UGF0aCA9ICdNMCwwJztcbiAgICAgICAgaWYoc2hvdWxkU2hvd0xpbmVzT3JUaWNrcyh5YSwgc3VicGxvdCkpIHtcbiAgICAgICAgICAgIGNvbm5lY3RZQm90dG9tID0gZmluZENvdW50ZXJBeGlzTGluZVdpZHRoKHlhLCAnYm90dG9tJywgeGEsIGF4TGlzdCk7XG4gICAgICAgICAgICB5TGluZXNZQm90dG9tID0geWEuX29mZnNldCArIHlhLl9sZW5ndGggKyAoY29ubmVjdFlCb3R0b20gPyBwYWQgOiAwKTtcbiAgICAgICAgICAgIGNvbm5lY3RZVG9wID0gZmluZENvdW50ZXJBeGlzTGluZVdpZHRoKHlhLCAndG9wJywgeGEsIGF4TGlzdCk7XG4gICAgICAgICAgICB5TGluZXNZVG9wID0geWEuX29mZnNldCAtIChjb25uZWN0WVRvcCA/IHBhZCA6IDApO1xuICAgICAgICAgICAgeUxpbmVzWExlZnQgPSBnZXRMaW5lUG9zaXRpb24oeWEsIHhhLCAnbGVmdCcpO1xuICAgICAgICAgICAgeUxpbmVzWFJpZ2h0ID0gZ2V0TGluZVBvc2l0aW9uKHlhLCB4YSwgJ3JpZ2h0Jyk7XG5cbiAgICAgICAgICAgIGV4dHJhU3VicGxvdCA9ICgheWEuX2FuY2hvckF4aXMgfHwgc3VicGxvdCAhPT0geWEuX21haW5TdWJwbG90KTtcbiAgICAgICAgICAgIGlmKGV4dHJhU3VicGxvdCAmJiAoeWEubWlycm9yID09PSAnYWxsdGlja3MnIHx8IHlhLm1pcnJvciA9PT0gJ2FsbCcpKSB7XG4gICAgICAgICAgICAgICAgeWEuX2xpbmVwb3NpdGlvbnNbc3VicGxvdF0gPSBbeUxpbmVzWExlZnQsIHlMaW5lc1hSaWdodF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHlQYXRoID0gbWFpblBhdGgoeWEsIHlMaW5lUGF0aCwgeUxpbmVQYXRoRnJlZSk7XG4gICAgICAgICAgICBpZihleHRyYVN1YnBsb3QgJiYgeWEuc2hvd2xpbmUgJiYgKHlhLm1pcnJvciA9PT0gJ2FsbCcgfHwgeWEubWlycm9yID09PSAnYWxsdGlja3MnKSkge1xuICAgICAgICAgICAgICAgIHlQYXRoICs9IHlMaW5lUGF0aCh5TGluZXNYTGVmdCkgKyB5TGluZVBhdGgoeUxpbmVzWFJpZ2h0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGxvdGluZm8ueWxpbmVzXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB5YS5fbHcgKyAncHgnKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgeWEuc2hvd2xpbmUgP1xuICAgICAgICAgICAgICAgICAgICB5YS5saW5lY29sb3IgOiAncmdiYSgwLDAsMCwwKScpO1xuICAgICAgICB9XG4gICAgICAgIHBsb3RpbmZvLnlsaW5lcy5hdHRyKCdkJywgeVBhdGgpO1xuICAgIH1cblxuICAgIEF4ZXMubWFrZUNsaXBQYXRocyhnZCk7XG5cbiAgICByZXR1cm4gZ2QuX3Byb21pc2VzLmxlbmd0aCAmJiBQcm9taXNlLmFsbChnZC5fcHJvbWlzZXMpO1xufVxuXG5mdW5jdGlvbiBmaW5kTWFpblN1YnBsb3QoYXgsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgc3VicGxvdExpc3QgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cztcbiAgICB2YXIgaWRzID0gc3VicGxvdExpc3QuY2FydGVzaWFuLmNvbmNhdChzdWJwbG90TGlzdC5nbDJkIHx8IFtdKTtcbiAgICB2YXIgbW9ja0dkID0ge19mdWxsTGF5b3V0OiBmdWxsTGF5b3V0fTtcblxuICAgIHZhciBpc1ggPSBheC5faWQuY2hhckF0KDApID09PSAneCc7XG4gICAgdmFyIGFuY2hvckF4ID0gYXguX21haW5BeGlzLl9hbmNob3JBeGlzO1xuICAgIHZhciBtYWluU3VicGxvdElEID0gJyc7XG4gICAgdmFyIG5leHRCZXN0TWFpblN1YnBsb3RJRCA9ICcnO1xuICAgIHZhciBhbmNob3JJRCA9ICcnO1xuXG4gICAgLy8gRmlyc3QgdHJ5IHRoZSBtYWluIElEIHdpdGggdGhlIGFuY2hvclxuICAgIGlmKGFuY2hvckF4KSB7XG4gICAgICAgIGFuY2hvcklEID0gYW5jaG9yQXguX21haW5BeGlzLl9pZDtcbiAgICAgICAgbWFpblN1YnBsb3RJRCA9IGlzWCA/IChheC5faWQgKyBhbmNob3JJRCkgOiAoYW5jaG9ySUQgKyBheC5faWQpO1xuICAgIH1cblxuICAgIC8vIFRoZW4gbG9vayBmb3IgYSBzdWJwbG90IHdpdGggdGhlIGNvdW50ZXJheGlzIG92ZXJsYXlpbmcgdGhlIGFuY2hvclxuICAgIC8vIElmIHRoYXQgZmFpbHMganVzdCB1c2UgdGhlIGZpcnN0IHN1YnBsb3QgaW5jbHVkaW5nIHRoaXMgYXhpc1xuICAgIGlmKCFtYWluU3VicGxvdElEIHx8ICFmdWxsTGF5b3V0Ll9wbG90c1ttYWluU3VicGxvdElEXSkge1xuICAgICAgICBtYWluU3VicGxvdElEID0gJyc7XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGlkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGlkID0gaWRzW2pdO1xuICAgICAgICAgICAgdmFyIHlJbmRleCA9IGlkLmluZGV4T2YoJ3knKTtcbiAgICAgICAgICAgIHZhciBpZFBhcnQgPSBpc1ggPyBpZC5zdWJzdHIoMCwgeUluZGV4KSA6IGlkLnN1YnN0cih5SW5kZXgpO1xuICAgICAgICAgICAgdmFyIGNvdW50ZXJQYXJ0ID0gaXNYID8gaWQuc3Vic3RyKHlJbmRleCkgOiBpZC5zdWJzdHIoMCwgeUluZGV4KTtcblxuICAgICAgICAgICAgaWYoaWRQYXJ0ID09PSBheC5faWQpIHtcbiAgICAgICAgICAgICAgICBpZighbmV4dEJlc3RNYWluU3VicGxvdElEKSBuZXh0QmVzdE1haW5TdWJwbG90SUQgPSBpZDtcbiAgICAgICAgICAgICAgICB2YXIgY291bnRlckF4ID0gQXhlcy5nZXRGcm9tSWQobW9ja0dkLCBjb3VudGVyUGFydCk7XG4gICAgICAgICAgICAgICAgaWYoYW5jaG9ySUQgJiYgY291bnRlckF4Lm92ZXJsYXlpbmcgPT09IGFuY2hvcklEKSB7XG4gICAgICAgICAgICAgICAgICAgIG1haW5TdWJwbG90SUQgPSBpZDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1haW5TdWJwbG90SUQgfHwgbmV4dEJlc3RNYWluU3VicGxvdElEO1xufVxuXG5mdW5jdGlvbiBzaG91bGRTaG93TGluZXNPclRpY2tzKGF4LCBzdWJwbG90KSB7XG4gICAgcmV0dXJuIChheC50aWNrcyB8fCBheC5zaG93bGluZSkgJiZcbiAgICAgICAgKHN1YnBsb3QgPT09IGF4Ll9tYWluU3VicGxvdCB8fCBheC5taXJyb3IgPT09ICdhbGwnIHx8IGF4Lm1pcnJvciA9PT0gJ2FsbHRpY2tzJyk7XG59XG5cbi8qXG4gKiBzaG91bGQgd2UgZHJhdyBhIGxpbmUgb24gY291bnRlckF4IGF0IHRoaXMgc2lkZSBvZiBheD9cbiAqIEl0J3MgYXNzdW1lZCB0aGF0IGNvdW50ZXJBeCBpcyBrbm93biB0byBvdmVybGF5IHRoZSBzdWJwbG90IHdlJ3JlIHdvcmtpbmcgb25cbiAqIGJ1dCBpdCBtYXkgbm90IGJlIGl0cyBtYWluIGF4aXMuXG4gKi9cbmZ1bmN0aW9uIHNob3VsZFNob3dMaW5lVGhpc1NpZGUoYXgsIHNpZGUsIGNvdW50ZXJBeCkge1xuICAgIC8vIGRvZXMgY291bnRlckF4IGdldCBhIGxpbmUgYXQgYWxsP1xuICAgIGlmKCFjb3VudGVyQXguc2hvd2xpbmUgfHwgIWNvdW50ZXJBeC5fbHcpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGFyZSB3ZSBkcmF3aW5nICphbGwqIGxpbmVzIGZvciBjb3VudGVyQXg/XG4gICAgaWYoY291bnRlckF4Lm1pcnJvciA9PT0gJ2FsbCcgfHwgY291bnRlckF4Lm1pcnJvciA9PT0gJ2FsbHRpY2tzJykgcmV0dXJuIHRydWU7XG5cbiAgICB2YXIgYW5jaG9yQXggPSBjb3VudGVyQXguX2FuY2hvckF4aXM7XG5cbiAgICAvLyBpcyB0aGlzIGEgZnJlZSBheGlzPyBmcmVlIGF4ZXMgY2FuIG9ubHkgaGF2ZSBhIHN1YnBsb3Qgc2lkZS1saW5lIHdpdGggYWxsKHRpY2tzKT8gbWlycm9yaW5nXG4gICAgaWYoIWFuY2hvckF4KSByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBpbiBvcmRlciB0byBoYW5kbGUgY2FzZXMgd2hlcmUgdGhlIHVzZXIgZm9yZ290IHRvIGFuY2hvciB0aGlzIGF4aXMgY29ycmVjdGx5XG4gICAgLy8gKGJlY2F1c2UgaXRzIGRlZmF1bHQgYW5jaG9yIGhhcyB0aGUgc2FtZSBkb21haW4gb24gdGhlIHJlbGV2YW50IGVuZClcbiAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSByZWxldmFudCBwb3NpdGlvbiBpcyB0aGUgc2FtZS5cbiAgICB2YXIgc2lkZUluZGV4ID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fQkxbc2lkZV07XG4gICAgaWYoY291bnRlckF4LnNpZGUgPT09IHNpZGUpIHtcbiAgICAgICAgcmV0dXJuIGFuY2hvckF4LmRvbWFpbltzaWRlSW5kZXhdID09PSBheC5kb21haW5bc2lkZUluZGV4XTtcbiAgICB9XG4gICAgcmV0dXJuIGNvdW50ZXJBeC5taXJyb3IgJiYgYW5jaG9yQXguZG9tYWluWzEgLSBzaWRlSW5kZXhdID09PSBheC5kb21haW5bMSAtIHNpZGVJbmRleF07XG59XG5cbi8qXG4gKiBJcyB0aGVyZSBhbm90aGVyIGF4aXMgaW50ZXJzZWN0aW5nIGBzaWRlYCBlbmQgb2YgYGF4YD9cbiAqIEZpcnN0IGxvb2sgYXQgYGNvdW50ZXJBeGAgKHRoZSBheGlzIGZvciB0aGlzIHN1YnBsb3QpLFxuICogdGhlbiBhdCBhbGwgb3RoZXIgcG90ZW50aWFsIGNvdW50ZXJheGVzIG9uIG9yIG92ZXJsYXlpbmcgdGhpcyBzdWJwbG90LlxuICogVGFrZSB0aGUgbGluZSB3aWR0aCBmcm9tIHRoZSBmaXJzdCBvbmUgdGhhdCBoYXMgYSBsaW5lLlxuICovXG5mdW5jdGlvbiBmaW5kQ291bnRlckF4aXNMaW5lV2lkdGgoYXgsIHNpZGUsIGNvdW50ZXJBeCwgYXhMaXN0KSB7XG4gICAgaWYoc2hvdWxkU2hvd0xpbmVUaGlzU2lkZShheCwgc2lkZSwgY291bnRlckF4KSkge1xuICAgICAgICByZXR1cm4gY291bnRlckF4Ll9sdztcbiAgICB9XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXhpID0gYXhMaXN0W2ldO1xuICAgICAgICBpZihheGkuX21haW5BeGlzID09PSBjb3VudGVyQXguX21haW5BeGlzICYmIHNob3VsZFNob3dMaW5lVGhpc1NpZGUoYXgsIHNpZGUsIGF4aSkpIHtcbiAgICAgICAgICAgIHJldHVybiBheGkuX2x3O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuXG5leHBvcnRzLmRyYXdNYWluVGl0bGUgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBUaXRsZXMuZHJhdyhnZCwgJ2d0aXRsZScsIHtcbiAgICAgICAgcHJvcENvbnRhaW5lcjogZnVsbExheW91dCxcbiAgICAgICAgcHJvcE5hbWU6ICd0aXRsZScsXG4gICAgICAgIHBsYWNlaG9sZGVyOiBmdWxsTGF5b3V0Ll9kZmx0VGl0bGUucGxvdCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgeDogZnVsbExheW91dC53aWR0aCAvIDIsXG4gICAgICAgICAgICB5OiBmdWxsTGF5b3V0Ll9zaXplLnQgLyAyLFxuICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuZXhwb3J0cy5kb1RyYWNlU3R5bGUgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBlZGl0U3R5bGVDYWxscyA9IFtdO1xuICAgIHZhciBpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbaV07XG4gICAgICAgIHZhciBjZDAgPSBjZFswXSB8fCB7fTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlIHx8IHt9O1xuICAgICAgICB2YXIgX21vZHVsZSA9IHRyYWNlLl9tb2R1bGUgfHwge307XG5cbiAgICAgICAgLy8gU2VlIGlmIHdlIG5lZWQgdG8gZG8gYXJyYXlzVG9DYWxjZGF0YVxuICAgICAgICAvLyBjYWxsIGl0IHJlZ2FyZGxlc3Mgb2Ygd2hhdCBjaGFuZ2Ugd2UgbWFkZSwgaW4gY2FzZVxuICAgICAgICAvLyBzdXBwbHlEZWZhdWx0cyBicm91Z2h0IGluIGFuIGFycmF5IHRoYXQgd2FzIGFscmVhZHlcbiAgICAgICAgLy8gaW4gZ2QuZGF0YSBidXQgbm90IGluIGdkLl9mdWxsRGF0YSBwcmV2aW91c2x5XG4gICAgICAgIHZhciBhcnJheXNUb0NhbGNkYXRhID0gX21vZHVsZS5hcnJheXNUb0NhbGNkYXRhO1xuICAgICAgICBpZihhcnJheXNUb0NhbGNkYXRhKSBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG5cbiAgICAgICAgdmFyIGVkaXRTdHlsZSA9IF9tb2R1bGUuZWRpdFN0eWxlO1xuICAgICAgICBpZihlZGl0U3R5bGUpIGVkaXRTdHlsZUNhbGxzLnB1c2goe2ZuOiBlZGl0U3R5bGUsIGNkMDogY2QwfSk7XG4gICAgfVxuXG4gICAgaWYoZWRpdFN0eWxlQ2FsbHMubGVuZ3RoKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGVkaXRTdHlsZUNhbGxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWRpdCA9IGVkaXRTdHlsZUNhbGxzW2ldO1xuICAgICAgICAgICAgZWRpdC5mbihnZCwgZWRpdC5jZDApO1xuICAgICAgICB9XG4gICAgICAgIGNsZWFyR2xDYW52YXNlcyhnZCk7XG4gICAgICAgIGV4cG9ydHMucmVkcmF3UmVnbFRyYWNlcyhnZCk7XG4gICAgfVxuXG4gICAgUGxvdHMuc3R5bGUoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnbGVnZW5kJywgJ2RyYXcnKShnZCk7XG5cbiAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG59O1xuXG5leHBvcnRzLmRvQ29sb3JCYXJzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZ2QuY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkaTAgPSBnZC5jYWxjZGF0YVtpXVswXTtcblxuICAgICAgICBpZigoY2RpMC50IHx8IHt9KS5jYikge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RpMC50cmFjZSxcbiAgICAgICAgICAgICAgICBjYiA9IGNkaTAudC5jYjtcblxuICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2NvbnRvdXInKSkge1xuICAgICAgICAgICAgICAgIGNiLmxpbmUoe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogdHJhY2UuY29udG91cnMuc2hvd2xpbmVzICE9PSBmYWxzZSA/XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFjZS5saW5lLndpZHRoIDogMCxcbiAgICAgICAgICAgICAgICAgICAgZGFzaDogdHJhY2UubGluZS5kYXNoLFxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogdHJhY2UuY29udG91cnMuY29sb3JpbmcgPT09ICdsaW5lJyA/XG4gICAgICAgICAgICAgICAgICAgICAgICBjYi5fb3B0cy5saW5lLmNvbG9yIDogdHJhY2UubGluZS5jb2xvclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG1vZHVsZU9wdHMgPSB0cmFjZS5fbW9kdWxlLmNvbG9yYmFyO1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lck5hbWUgPSBtb2R1bGVPcHRzLmNvbnRhaW5lcjtcbiAgICAgICAgICAgIHZhciBvcHRzID0gKGNvbnRhaW5lck5hbWUgPyB0cmFjZVtjb250YWluZXJOYW1lXSA6IHRyYWNlKS5jb2xvcmJhcjtcbiAgICAgICAgICAgIGNiLm9wdGlvbnMob3B0cykoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbn07XG5cbi8vIGZvcmNlIHBsb3QoKSB0byByZWRvIHRoZSBsYXlvdXQgYW5kIHJlcGxvdCB3aXRoIHRoZSBtb2RpZmllZCBsYXlvdXRcbmV4cG9ydHMubGF5b3V0UmVwbG90ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgbGF5b3V0ID0gZ2QubGF5b3V0O1xuICAgIGdkLmxheW91dCA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncGxvdCcsIGdkLCAnJywgbGF5b3V0KTtcbn07XG5cbmV4cG9ydHMuZG9MZWdlbmQgPSBmdW5jdGlvbihnZCkge1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnbGVnZW5kJywgJ2RyYXcnKShnZCk7XG4gICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufTtcblxuZXhwb3J0cy5kb1RpY2tzUmVsYXlvdXQgPSBmdW5jdGlvbihnZCkge1xuICAgIEF4ZXMuZG9UaWNrcyhnZCwgJ3JlZHJhdycpO1xuXG4gICAgaWYoZ2QuX2Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5LnNwbG9tLnVwZGF0ZUdyaWQoZ2QpO1xuICAgICAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuICAgICAgICBleHBvcnRzLnJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgIH1cblxuICAgIGV4cG9ydHMuZHJhd01haW5UaXRsZShnZCk7XG4gICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufTtcblxuZXhwb3J0cy5kb01vZGVCYXIgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBNb2RlQmFyLm1hbmFnZShnZCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1cGRhdGVGeCA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlc1tpXS51cGRhdGVGeDtcbiAgICAgICAgaWYodXBkYXRlRngpIHVwZGF0ZUZ4KGdkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG59O1xuXG5leHBvcnRzLmRvQ2FtZXJhID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2NlbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkc1tpXV07XG4gICAgICAgIHZhciBzY2VuZSA9IHNjZW5lTGF5b3V0Ll9zY2VuZTtcblxuICAgICAgICBzY2VuZS5zZXRDYW1lcmEoc2NlbmVMYXlvdXQuY2FtZXJhKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLmRyYXdEYXRhID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBpO1xuXG4gICAgLy8gcmVtb3ZlIG9sZCBjb2xvcmJhcnMgZXhwbGljaXRseVxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNkYXRhW2ldWzBdLnRyYWNlO1xuICAgICAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8ICF0cmFjZS5fbW9kdWxlLmNvbG9yYmFyKSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0KCcuY2InICsgdHJhY2UudWlkKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsZWFyR2xDYW52YXNlcyhnZCk7XG5cbiAgICAvLyBsb29wIG92ZXIgdGhlIGJhc2UgcGxvdCBtb2R1bGVzIHByZXNlbnQgb24gZ3JhcGhcbiAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzO1xuICAgIGZvcihpID0gMDsgaSA8IGJhc2VQbG90TW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBiYXNlUGxvdE1vZHVsZXNbaV0ucGxvdChnZCk7XG4gICAgfVxuXG4gICAgZXhwb3J0cy5yZWRyYXdSZWdsVHJhY2VzKGdkKTtcblxuICAgIC8vIHN0eWxpbmcgc2VwYXJhdGUgZnJvbSBkcmF3aW5nXG4gICAgUGxvdHMuc3R5bGUoZ2QpO1xuXG4gICAgLy8gc2hvdyBhbm5vdGF0aW9ucyBhbmQgc2hhcGVzXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdzaGFwZXMnLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ2RyYXcnKShnZCk7XG5cbiAgICAvLyBNYXJrIHRoZSBmaXJzdCByZW5kZXIgYXMgY29tcGxldGVcbiAgICBmdWxsTGF5b3V0Ll9yZXBsb3R0aW5nID0gZmFsc2U7XG5cbiAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG59O1xuXG4vLyBEcmF3IChvciByZWRyYXcpIGFsbCByZWdsLWJhc2VkIHRyYWNlcyBpbiBvbmUgZ28sXG4vLyB1c2VmdWwgZHVyaW5nIGRyYWcgYW5kIHNlbGVjdGlvbiB3aGVyZSBidWZmZXJzIG9mIHRhcmdldGVkIHRyYWNlcyBhcmUgdXBkYXRlZCxcbi8vIGJ1dCBhbGwgdHJhY2VzIG5lZWQgdG8gYmUgcmVkcmF3biBmb2xsb3dpbmcgY2xlYXJHbENhbnZhc2VzLlxuLy9cbi8vIE5vdGUgdGhhdCBfbW9kdWxlLnBsb3QgZm9yIHJlZ2wgdHJhY2UgZG9lcyBOT1QgZHJhdyB0aGluZ3Ncbi8vIG9uIHRoZSBjYW52YXMsIHRoZXkgb25seSB1cGRhdGUgdGhlIGJ1ZmZlcnMuXG4vLyBEcmF3aW5nIGlzIHBlcmZvcm0gaGVyZS5cbi8vXG4vLyBUT0RPIHRyeSBhZGRpbmcgcGVyLXN1YnBsb3Qgb3B0aW9uIHVzaW5nIGdsLlNDSVNTT1JfVEVTVCBmb3Jcbi8vIG5vbi1vdmVybGF5aW5nLCBkaXNqb2ludCBzdWJwbG90cy5cbi8vXG4vLyBUT0RPIHRyeSB0byBpbmNsdWRlIHBhcmNvb3JkcyBpbiBoZXJlLlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzMwNjlcbmV4cG9ydHMucmVkcmF3UmVnbFRyYWNlcyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIGlmKGZ1bGxMYXlvdXQuX2hhcygncmVnbCcpKSB7XG4gICAgICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICAgICAgdmFyIGNhcnRlc2lhbklkcyA9IFtdO1xuICAgICAgICB2YXIgcG9sYXJJZHMgPSBbXTtcbiAgICAgICAgdmFyIGksIHNwO1xuXG4gICAgICAgIGlmKGZ1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICAgICAgZnVsbExheW91dC5fc3Bsb21HcmlkLmRyYXcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE4uQi5cbiAgICAgICAgLy8gLSBMb29wIG92ZXIgZnVsbERhdGEgKG5vdCBfc3Bsb21TY2VuZXMpIHRvIHByZXNlcnZlIHNwbG9tIHRyYWNlLXRvLXRyYWNlIG9yZGVyaW5nXG4gICAgICAgIC8vIC0gRmlsbCBsaXN0IGlmIHN1YnBsb3QgaWRzIChpbnN0ZWFkIG9mIGZ1bGxMYXlvdXQuX3N1YnBsb3RzKSB0byBoYW5kbGUgY2FzZXMgd2hlcmUgYWxsIHRyYWNlc1xuICAgICAgICAvLyAgIG9mIGEgZ2l2ZW4gbW9kdWxlIGFyZSBgdmlzaWJsZSAhPT0gdHJ1ZWBcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuXG4gICAgICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3NwbG9tJykge1xuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0Ll9zcGxvbVNjZW5lc1t0cmFjZS51aWRdLmRyYXcoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHJhY2UudHlwZSA9PT0gJ3NjYXR0ZXJnbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoY2FydGVzaWFuSWRzLCB0cmFjZS54YXhpcyArIHRyYWNlLnlheGlzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHJhY2UudHlwZSA9PT0gJ3NjYXR0ZXJwb2xhcmdsJykge1xuICAgICAgICAgICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShwb2xhcklkcywgdHJhY2Uuc3VicGxvdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2FydGVzaWFuSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzcCA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2NhcnRlc2lhbklkc1tpXV07XG4gICAgICAgICAgICBpZihzcC5fc2NlbmUpIHNwLl9zY2VuZS5kcmF3KCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwb2xhcklkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3AgPSBmdWxsTGF5b3V0W3BvbGFySWRzW2ldXS5fc3VicGxvdDtcbiAgICAgICAgICAgIGlmKHNwLl9zY2VuZSkgc3AuX3NjZW5lLmRyYXcoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmV4cG9ydHMuZG9BdXRvUmFuZ2VBbmRDb25zdHJhaW50cyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGF4TGlzdCA9IEF4ZXMubGlzdChnZCwgJycsIHRydWUpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG4gICAgICAgIGNsZWFuQXhpc0NvbnN0cmFpbnRzKGdkLCBheCk7XG4gICAgICAgIGRvQXV0b1JhbmdlKGdkLCBheCk7XG4gICAgfVxuXG4gICAgZW5mb3JjZUF4aXNDb25zdHJhaW50cyhnZCk7XG59O1xuXG4vLyBBbiBpbml0aWFsIHBhaW50IG11c3QgYmUgY29tcGxldGVkIGJlZm9yZSB0aGVzZSBjb21wb25lbnRzIGNhbiBiZVxuLy8gY29ycmVjdGx5IHNpemVkIGFuZCB0aGUgd2hvbGUgcGxvdCByZS1tYXJnaW5lZC4gZnVsbExheW91dC5fcmVwbG90dGluZyBtdXN0XG4vLyBiZSBzZXQgdG8gZmFsc2UgYmVmb3JlIHRoZXNlIHdpbGwgd29yayBwcm9wZXJseS5cbmV4cG9ydHMuZmluYWxEcmF3ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3NoYXBlcycsICdkcmF3JykoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnaW1hZ2VzJywgJ2RyYXcnKShnZCk7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdkcmF3JykoZ2QpO1xuICAgIC8vIFRPRE86IHJhbmdlc2xpZGVycyByZWFsbHkgYmVsb25nIGluIG1hcmdpblB1c2hlcnMgYnV0IHRoZXkgbmVlZCB0byBiZVxuICAgIC8vIGRyYXduIGFmdGVyIGRhdGEgLSBjYW4gd2UgYXQgbGVhc3QgZ2V0IHRoZSBtYXJnaW4gcHVzaGluZyBwYXJ0IHNlcGFyYXRlZFxuICAgIC8vIG91dCBhbmQgZG9uZSBlYXJsaWVyP1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgncmFuZ2VzbGlkZXInLCAnZHJhdycpKGdkKTtcbiAgICAvLyBUT0RPOiByYW5nZXNlbGVjdG9yIG9ubHkgbmVlZHMgdG8gYmUgaGVyZSAoaW4gYWRkaXRpb24gdG8gZHJhd01hcmdpblB1c2hlcnMpXG4gICAgLy8gYmVjYXVzZSB0aGUgbWFyZ2lucyBuZWVkIHRvIGJlIGZ1bGx5IGRldGVybWluZWQgYmVmb3JlIHdlIGNhbiBjYWxsXG4gICAgLy8gYXV0b3JhbmdlIGFuZCB1cGRhdGUgYXhpcyByYW5nZXMgKHdoaWNoIHJhbmdlc2VsZWN0b3IgbmVlZHMgdG8ga25vdyB3aGljaFxuICAgIC8vIGJ1dHRvbiBpcyBhY3RpdmUpLiBDYW4gd2UgYnJlYWsgb3V0IGl0cyBhdXRvbWFyZ2luIHN0ZXAgZnJvbSBpdHMgZHJhdyBzdGVwP1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgncmFuZ2VzZWxlY3RvcicsICdkcmF3JykoZ2QpO1xufTtcblxuZXhwb3J0cy5kcmF3TWFyZ2luUHVzaGVycyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdsZWdlbmQnLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3Jhbmdlc2VsZWN0b3InLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3NsaWRlcnMnLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3VwZGF0ZW1lbnVzJywgJ2RyYXcnKShnZCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBpc1BsYWluT2JqZWN0ID0gTGliLmlzUGxhaW5PYmplY3Q7XG52YXIgUGxvdFNjaGVtYSA9IHJlcXVpcmUoJy4vcGxvdF9zY2hlbWEnKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgcGxvdEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBkZmx0Q29uZmlnID0gcmVxdWlyZSgnLi9wbG90X2NvbmZpZycpO1xuXG4vKipcbiAqIFBsb3RseS5tYWtlVGVtcGxhdGU6IGNyZWF0ZSBhIHRlbXBsYXRlIG9mZiBhbiBleGlzdGluZyBmaWd1cmUgdG8gcmV1c2VcbiAqIHN0eWxlIGF0dHJpYnV0ZXMgb24gb3RoZXIgZmlndXJlcy5cbiAqXG4gKiBOb3RlOiBzZXBhcmF0ZWQgZnJvbSB0aGUgcmVzdCBvZiB0ZW1wbGF0ZXMgYmVjYXVzZSBvdGhlcndpc2Ugd2UgZ2V0IGNpcmN1bGFyXG4gKiByZWZlcmVuY2VzIGR1ZSB0byBQbG90U2NoZW1hLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fERPTSBlbGVtZW50fSBmaWd1cmU6IFRoZSBmaWd1cmUgdG8gYmFzZSB0aGUgdGVtcGxhdGUgb25cbiAqICAgICBzaG91bGQgY29udGFpbiBhIHRyYWNlIGFycmF5IGBmaWd1cmUuZGF0YWBcbiAqICAgICBhbmQgYSBsYXlvdXQgb2JqZWN0IGBmaWd1cmUubGF5b3V0YFxuICogQHJldHVybnMge29iamVjdH0gdGVtcGxhdGU6IHRoZSBleHRyYWN0ZWQgdGVtcGxhdGUgLSBjYW4gdGhlbiBiZSB1c2VkIGFzXG4gKiAgICAgYGxheW91dC50ZW1wbGF0ZWAgaW4gYW5vdGhlciBmaWd1cmUuXG4gKi9cbmV4cG9ydHMubWFrZVRlbXBsYXRlID0gZnVuY3Rpb24oZmlndXJlKSB7XG4gICAgZmlndXJlID0gTGliLmV4dGVuZERlZXAoe19jb250ZXh0OiBkZmx0Q29uZmlnfSwge2RhdGE6IGZpZ3VyZS5kYXRhLCBsYXlvdXQ6IGZpZ3VyZS5sYXlvdXR9KTtcbiAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhmaWd1cmUpO1xuICAgIHZhciBkYXRhID0gZmlndXJlLmRhdGEgfHwgW107XG4gICAgdmFyIGxheW91dCA9IGZpZ3VyZS5sYXlvdXQgfHwge307XG4gICAgLy8gY29weSBvdmVyIGEgZmV3IGl0ZW1zIHRvIGhlbHAgZm9sbG93IHRoZSBzY2hlbWFcbiAgICBsYXlvdXQuX2Jhc2VQbG90TW9kdWxlcyA9IGZpZ3VyZS5fZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzO1xuICAgIGxheW91dC5fbW9kdWxlcyA9IGZpZ3VyZS5fZnVsbExheW91dC5fbW9kdWxlcztcblxuICAgIHZhciB0ZW1wbGF0ZSA9IHtcbiAgICAgICAgZGF0YToge30sXG4gICAgICAgIGxheW91dDoge31cbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBOb3RlOiB3ZSBkbyBOT1QgdmFsaWRhdGUgdGVtcGxhdGUgdmFsdWVzLCB3ZSBqdXN0IHRha2Ugd2hhdCdzIGluIHRoZVxuICAgICAqIHVzZXIgaW5wdXRzIGRhdGEgYW5kIGxheW91dCwgbm90IHRoZSB2YWxpZGF0ZWQgdmFsdWVzIGluIGZ1bGxEYXRhIGFuZFxuICAgICAqIGZ1bGxMYXlvdXQuIEV2ZW4gaWYgd2Ugd2VyZSB0byB2YWxpZGF0ZSBoZXJlLCB0aGVyZSdzIG5vIGd1YXJhbnRlZSB0aGF0XG4gICAgICogdGhlc2UgdmFsdWVzIHdvdWxkIHN0aWxsIGJlIHZhbGlkIHdoZW4gYXBwbGllZCB0byBhIG5ldyBmaWd1cmUsIHdoaWNoXG4gICAgICogbWF5IGNvbnRhaW4gZGlmZmVyZW50IHRyYWNlIG1vZGVzLCBkaWZmZXJlbnQgYXhlcywgZXRjLiBTbyBpdCdzXG4gICAgICogaW1wb3J0YW50IHRoYXQgd2hlbiBhcHBseWluZyBhIHRlbXBsYXRlIHdlIHN0aWxsIHZhbGlkYXRlIHRoZSB0ZW1wbGF0ZVxuICAgICAqIHZhbHVlcywgcmF0aGVyIHRoYW4ganVzdCB1c2luZyB0aGVtIGFzIGRlZmF1bHRzLlxuICAgICAqL1xuXG4gICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNlKSB7XG4gICAgICAgIC8vIFRPRE86IFdoYXQgaWYgbm8gc3R5bGUgaW5mbyBpcyBleHRyYWN0ZWQgZm9yIHRoaXMgdHJhY2UuIFdlIG1heVxuICAgICAgICAvLyBub3Qgd2FudCBhbiBlbXB0eSBvYmplY3QgYXMgdGhlIG51bGwgdmFsdWUuXG4gICAgICAgIC8vIFRPRE86IGFsbG93IHRyYW5zZm9ybXMgdG8gY29udHJpYnV0ZSB0byB0ZW1wbGF0ZXM/XG4gICAgICAgIC8vIGFzIGl0IHN0YW5kcyB0aGV5IGFyZSBpZ25vcmVkLCB3aGljaCBtYXkgYmUgZm9yIHRoZSBiZXN0Li4uXG5cbiAgICAgICAgdmFyIHRyYWNlVGVtcGxhdGUgPSB7fTtcbiAgICAgICAgd2Fsa1N0eWxlS2V5cyh0cmFjZSwgdHJhY2VUZW1wbGF0ZSwgZ2V0VHJhY2VJbmZvLmJpbmQobnVsbCwgdHJhY2UpKTtcblxuICAgICAgICB2YXIgdHJhY2VUeXBlID0gTGliLmNvZXJjZSh0cmFjZSwge30sIHBsb3RBdHRyaWJ1dGVzLCAndHlwZScpO1xuICAgICAgICB2YXIgdHlwZVRlbXBsYXRlcyA9IHRlbXBsYXRlLmRhdGFbdHJhY2VUeXBlXTtcbiAgICAgICAgaWYoIXR5cGVUZW1wbGF0ZXMpIHR5cGVUZW1wbGF0ZXMgPSB0ZW1wbGF0ZS5kYXRhW3RyYWNlVHlwZV0gPSBbXTtcbiAgICAgICAgdHlwZVRlbXBsYXRlcy5wdXNoKHRyYWNlVGVtcGxhdGUpO1xuICAgIH0pO1xuXG4gICAgd2Fsa1N0eWxlS2V5cyhsYXlvdXQsIHRlbXBsYXRlLmxheW91dCwgZ2V0TGF5b3V0SW5mby5iaW5kKG51bGwsIGxheW91dCkpO1xuXG4gICAgLypcbiAgICAgKiBDb21wb3NlIHRoZSBuZXcgdGVtcGxhdGUgd2l0aCBhbiBleGlzdGluZyBvbmUgdG8gdGhlIHNhbWUgZWZmZWN0XG4gICAgICpcbiAgICAgKiBOT1RFOiB0aGVyZSdzIGEgcG9zc2liaWxpdHkgb2Ygc2xpZ2h0bHkgZGlmZmVyZW50IGJlaGF2aW9yOiBpZiB0aGUgcGxvdFxuICAgICAqIGhhcyBhbiBpbnZhbGlkIHZhbHVlIGFuZCB0aGUgb2xkIHRlbXBsYXRlIGhhcyBhIHZhbGlkIHZhbHVlIGZvciB0aGUgc2FtZVxuICAgICAqIGF0dHJpYnV0ZSwgdGhlIHBsb3Qgd2lsbCB1c2UgdGhlIG9sZCB0ZW1wbGF0ZSB2YWx1ZSBidXQgdGhpcyByb3V0aW5lXG4gICAgICogd2lsbCBwdWxsIHRoZSBpbnZhbGlkIHZhbHVlIChyZXN1bHRpbmcgaW4gdGhlIG9yaWdpbmFsIGRlZmF1bHQpLlxuICAgICAqIEluIHRoZSBnZW5lcmFsIGNhc2UgaXQncyBub3QgcG9zc2libGUgdG8gc29sdmUgdGhpcyB3aXRoIGEgc2luZ2xlIHZhbHVlLFxuICAgICAqIHNpbmNlIHZhbGlkIG9wdGlvbnMgY2FuIGJlIGNvbnRleHQtZGVwZW5kZW50LiBJdCBjb3VsZCBiZSBzb2x2ZWQgd2l0aFxuICAgICAqIGEgKmxpc3QqIG9mIHZhbHVlcywgYnV0IHRoYXQgd291bGQgYmUgaHVnZSBjb21wbGV4aXR5IGZvciBsaXR0bGUgZ2Fpbi5cbiAgICAgKi9cbiAgICBkZWxldGUgdGVtcGxhdGUubGF5b3V0LnRlbXBsYXRlO1xuICAgIHZhciBvbGRUZW1wbGF0ZSA9IGxheW91dC50ZW1wbGF0ZTtcbiAgICBpZihpc1BsYWluT2JqZWN0KG9sZFRlbXBsYXRlKSkge1xuICAgICAgICB2YXIgb2xkTGF5b3V0VGVtcGxhdGUgPSBvbGRUZW1wbGF0ZS5sYXlvdXQ7XG5cbiAgICAgICAgdmFyIGksIHRyYWNlVHlwZSwgb2xkVHlwZVRlbXBsYXRlcywgb2xkVHlwZUxlbiwgdHlwZVRlbXBsYXRlcywgdHlwZUxlbjtcblxuICAgICAgICBpZihpc1BsYWluT2JqZWN0KG9sZExheW91dFRlbXBsYXRlKSkge1xuICAgICAgICAgICAgbWVyZ2VUZW1wbGF0ZXMob2xkTGF5b3V0VGVtcGxhdGUsIHRlbXBsYXRlLmxheW91dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9sZERhdGFUZW1wbGF0ZSA9IG9sZFRlbXBsYXRlLmRhdGE7XG4gICAgICAgIGlmKGlzUGxhaW5PYmplY3Qob2xkRGF0YVRlbXBsYXRlKSkge1xuICAgICAgICAgICAgZm9yKHRyYWNlVHlwZSBpbiB0ZW1wbGF0ZS5kYXRhKSB7XG4gICAgICAgICAgICAgICAgb2xkVHlwZVRlbXBsYXRlcyA9IG9sZERhdGFUZW1wbGF0ZVt0cmFjZVR5cGVdO1xuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkob2xkVHlwZVRlbXBsYXRlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZVRlbXBsYXRlcyA9IHRlbXBsYXRlLmRhdGFbdHJhY2VUeXBlXTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZUxlbiA9IHR5cGVUZW1wbGF0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBvbGRUeXBlTGVuID0gb2xkVHlwZVRlbXBsYXRlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHR5cGVMZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVyZ2VUZW1wbGF0ZXMob2xkVHlwZVRlbXBsYXRlc1tpICUgb2xkVHlwZUxlbl0sIHR5cGVUZW1wbGF0ZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gdHlwZUxlbjsgaSA8IG9sZFR5cGVMZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZVRlbXBsYXRlcy5wdXNoKExpYi5leHRlbmREZWVwKHt9LCBvbGRUeXBlVGVtcGxhdGVzW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IodHJhY2VUeXBlIGluIG9sZERhdGFUZW1wbGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmKCEodHJhY2VUeXBlIGluIHRlbXBsYXRlLmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmRhdGFbdHJhY2VUeXBlXSA9IExpYi5leHRlbmREZWVwKFtdLCBvbGREYXRhVGVtcGxhdGVbdHJhY2VUeXBlXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRlbXBsYXRlO1xufTtcblxuZnVuY3Rpb24gbWVyZ2VUZW1wbGF0ZXMob2xkVGVtcGxhdGUsIG5ld1RlbXBsYXRlKSB7XG4gICAgLy8gd2UgZG9uJ3QgY2FyZSBhYm91dCBzcGVlZCBoZXJlLCBqdXN0IG1ha2Ugc3VyZSB3ZSBoYXZlIGEgdG90YWxseVxuICAgIC8vIGRpc3RpbmN0IG9iamVjdCBmcm9tIHRoZSBwcmV2aW91cyB0ZW1wbGF0ZVxuICAgIG9sZFRlbXBsYXRlID0gTGliLmV4dGVuZERlZXAoe30sIG9sZFRlbXBsYXRlKTtcblxuICAgIC8vIHNvcnQga2V5cyBzbyB3ZSBhbHdheXMgZ2V0IGFubm90YXRpb25kZWZhdWx0cyBiZWZvcmUgYW5ub3RhdGlvbnMgZXRjXG4gICAgLy8gc28gYXJyYXlUZW1wbGF0ZXIgd2lsbCB3b3JrIHJpZ2h0XG4gICAgdmFyIG9sZEtleXMgPSBPYmplY3Qua2V5cyhvbGRUZW1wbGF0ZSkuc29ydCgpO1xuICAgIHZhciBpLCBqO1xuXG4gICAgZnVuY3Rpb24gbWVyZ2VPbmUob2xkVmFsLCBuZXdWYWwsIGtleSkge1xuICAgICAgICBpZihpc1BsYWluT2JqZWN0KG5ld1ZhbCkgJiYgaXNQbGFpbk9iamVjdChvbGRWYWwpKSB7XG4gICAgICAgICAgICBtZXJnZVRlbXBsYXRlcyhvbGRWYWwsIG5ld1ZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihBcnJheS5pc0FycmF5KG5ld1ZhbCkgJiYgQXJyYXkuaXNBcnJheShvbGRWYWwpKSB7XG4gICAgICAgICAgICAvLyBOb3RlOiBvbWl0dGVkIGBpbmNsdXNpb25BdHRyYCBmcm9tIGFycmF5VGVtcGxhdGVyIGhlcmUsXG4gICAgICAgICAgICAvLyBpdCdzIGlycmVsZXZhbnQgYXMgd2Ugb25seSB3YW50IHRoZSByZXN1bHRpbmcgYF90ZW1wbGF0ZWAuXG4gICAgICAgICAgICB2YXIgdGVtcGxhdGVyID0gVGVtcGxhdGUuYXJyYXlUZW1wbGF0ZXIoe190ZW1wbGF0ZTogb2xkVGVtcGxhdGV9LCBrZXkpO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbmV3VmFsLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSBuZXdWYWxbal07XG4gICAgICAgICAgICAgICAgdmFyIG9sZEl0ZW0gPSB0ZW1wbGF0ZXIubmV3SXRlbShpdGVtKS5fdGVtcGxhdGU7XG4gICAgICAgICAgICAgICAgaWYob2xkSXRlbSkgbWVyZ2VUZW1wbGF0ZXMob2xkSXRlbSwgaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGVmYXVsdEl0ZW1zID0gdGVtcGxhdGVyLmRlZmF1bHRJdGVtcygpO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgZGVmYXVsdEl0ZW1zLmxlbmd0aDsgaisrKSBuZXdWYWwucHVzaChkZWZhdWx0SXRlbXNbal0uX3RlbXBsYXRlKTtcblxuICAgICAgICAgICAgLy8gdGVtcGxhdGVpdGVtbmFtZSBvbmx5IGFwcGxpZXMgdG8gcmVjZWl2aW5nIHBsb3RzXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBuZXdWYWwubGVuZ3RoOyBqKyspIGRlbGV0ZSBuZXdWYWxbal0udGVtcGxhdGVpdGVtbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IG9sZEtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGtleSA9IG9sZEtleXNbaV07XG4gICAgICAgIHZhciBvbGRWYWwgPSBvbGRUZW1wbGF0ZVtrZXldO1xuICAgICAgICBpZihrZXkgaW4gbmV3VGVtcGxhdGUpIHtcbiAgICAgICAgICAgIG1lcmdlT25lKG9sZFZhbCwgbmV3VGVtcGxhdGVba2V5XSwga2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIG5ld1RlbXBsYXRlW2tleV0gPSBvbGRWYWw7XG5cbiAgICAgICAgLy8gaWYgdGhpcyBpcyBhIGJhc2Uga2V5IGZyb20gdGhlIG9sZCB0ZW1wbGF0ZSAoZWcgeGF4aXMpLCBsb29rIGZvclxuICAgICAgICAvLyBleHRlbmRlZCBrZXlzIChlZyB4YXhpczIpIGluIHRoZSBuZXcgdGVtcGxhdGUgdG8gbWVyZ2UgaW50b1xuICAgICAgICBpZihnZXRCYXNlS2V5KGtleSkgPT09IGtleSkge1xuICAgICAgICAgICAgZm9yKHZhciBrZXkyIGluIG5ld1RlbXBsYXRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJhc2VLZXkyID0gZ2V0QmFzZUtleShrZXkyKTtcbiAgICAgICAgICAgICAgICBpZihrZXkyICE9PSBiYXNlS2V5MiAmJiBiYXNlS2V5MiA9PT0ga2V5ICYmICEoa2V5MiBpbiBvbGRUZW1wbGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVyZ2VPbmUob2xkVmFsLCBuZXdUZW1wbGF0ZVtrZXkyXSwga2V5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEJhc2VLZXkoa2V5KSB7XG4gICAgcmV0dXJuIGtleS5yZXBsYWNlKC9bMC05XSskLywgJycpO1xufVxuXG5mdW5jdGlvbiB3YWxrU3R5bGVLZXlzKHBhcmVudCwgdGVtcGxhdGVPdXQsIGdldEF0dHJpYnV0ZUluZm8sIHBhdGgsIGJhc2VQYXRoKSB7XG4gICAgdmFyIHBhdGhBdHRyID0gYmFzZVBhdGggJiYgZ2V0QXR0cmlidXRlSW5mbyhiYXNlUGF0aCk7XG4gICAgZm9yKHZhciBrZXkgaW4gcGFyZW50KSB7XG4gICAgICAgIHZhciBjaGlsZCA9IHBhcmVudFtrZXldO1xuICAgICAgICB2YXIgbmV4dFBhdGggPSBnZXROZXh0UGF0aChwYXJlbnQsIGtleSwgcGF0aCk7XG4gICAgICAgIHZhciBuZXh0QmFzZVBhdGggPSBnZXROZXh0UGF0aChwYXJlbnQsIGtleSwgYmFzZVBhdGgpO1xuICAgICAgICB2YXIgYXR0ciA9IGdldEF0dHJpYnV0ZUluZm8obmV4dEJhc2VQYXRoKTtcbiAgICAgICAgaWYoIWF0dHIpIHtcbiAgICAgICAgICAgIHZhciBiYXNlS2V5ID0gZ2V0QmFzZUtleShrZXkpO1xuICAgICAgICAgICAgaWYoYmFzZUtleSAhPT0ga2V5KSB7XG4gICAgICAgICAgICAgICAgbmV4dEJhc2VQYXRoID0gZ2V0TmV4dFBhdGgocGFyZW50LCBiYXNlS2V5LCBiYXNlUGF0aCk7XG4gICAgICAgICAgICAgICAgYXR0ciA9IGdldEF0dHJpYnV0ZUluZm8obmV4dEJhc2VQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdlJ2xsIGdldCBhbiBhdHRyIGlmIHBhdGggc3RhcnRzIHdpdGggYSB2YWxpZCBwYXJ0LCB0aGVuIGhhcyBhblxuICAgICAgICAvLyBpbnZhbGlkIGVuZGluZy4gTWFrZSBzdXJlIHdlIGdvdCBhbGwgdGhlIHdheSB0byB0aGUgZW5kLlxuICAgICAgICBpZihwYXRoQXR0ciAmJiAocGF0aEF0dHIgPT09IGF0dHIpKSBjb250aW51ZTtcblxuICAgICAgICBpZighYXR0ciB8fCBhdHRyLl9ub1RlbXBsYXRpbmcgfHxcbiAgICAgICAgICAgIGF0dHIudmFsVHlwZSA9PT0gJ2RhdGFfYXJyYXknIHx8XG4gICAgICAgICAgICAoYXR0ci5hcnJheU9rICYmIEFycmF5LmlzQXJyYXkoY2hpbGQpKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWF0dHIudmFsVHlwZSAmJiBpc1BsYWluT2JqZWN0KGNoaWxkKSkge1xuICAgICAgICAgICAgd2Fsa1N0eWxlS2V5cyhjaGlsZCwgdGVtcGxhdGVPdXQsIGdldEF0dHJpYnV0ZUluZm8sIG5leHRQYXRoLCBuZXh0QmFzZVBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoYXR0ci5faXNMaW5rZWRUb0FycmF5ICYmIEFycmF5LmlzQXJyYXkoY2hpbGQpKSB7XG4gICAgICAgICAgICB2YXIgZGZsdERvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBuYW1lZEluZGV4ID0gMDtcbiAgICAgICAgICAgIHZhciB1c2VkTmFtZXMgPSB7fTtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjaGlsZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gY2hpbGRbaV07XG4gICAgICAgICAgICAgICAgaWYoaXNQbGFpbk9iamVjdChpdGVtKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmFtZSA9IGl0ZW0ubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgaWYobmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXVzZWROYW1lc1tuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5hbWVkIGFycmF5IGl0ZW1zOiBhbGxvdyBhbGwgYXR0cmlidXRlcyBleGNlcHQgZGF0YSBhcnJheXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YWxrU3R5bGVLZXlzKGl0ZW0sIHRlbXBsYXRlT3V0LCBnZXRBdHRyaWJ1dGVJbmZvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXROZXh0UGF0aChjaGlsZCwgbmFtZWRJbmRleCwgbmV4dFBhdGgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXROZXh0UGF0aChjaGlsZCwgbmFtZWRJbmRleCwgbmV4dEJhc2VQYXRoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZWRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZWROYW1lc1tuYW1lXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZighZGZsdERvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZmx0S2V5ID0gVGVtcGxhdGUuYXJyYXlEZWZhdWx0S2V5KGtleSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGZsdFBhdGggPSBnZXROZXh0UGF0aChwYXJlbnQsIGRmbHRLZXksIHBhdGgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBnZXRBdHRyaWJ1dGVJbmZvIHdpbGwgZmFpbCBpZiB3ZSB0cnkgdG8gdXNlIGRmbHRLZXkgZGlyZWN0bHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJbnN0ZWFkIHB1dCB0aGlzIGl0ZW0gaW50byB0aGUgbmV4dCBhcnJheSBlbGVtZW50LCB0aGVuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwdWxsIGl0IG91dCBhbmQgbW92ZSBpdCB0byBkZmx0S2V5LlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBhdGhJbkFycmF5ID0gZ2V0TmV4dFBhdGgoY2hpbGQsIG5hbWVkSW5kZXgsIG5leHRQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGtTdHlsZUtleXMoaXRlbSwgdGVtcGxhdGVPdXQsIGdldEF0dHJpYnV0ZUluZm8sIHBhdGhJbkFycmF5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE5leHRQYXRoKGNoaWxkLCBuYW1lZEluZGV4LCBuZXh0QmFzZVBhdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtUHJvcEluQXJyYXkgPSBMaWIubmVzdGVkUHJvcGVydHkodGVtcGxhdGVPdXQsIHBhdGhJbkFycmF5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZmx0UHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0ZW1wbGF0ZU91dCwgZGZsdFBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGZsdFByb3Auc2V0KGl0ZW1Qcm9wSW5BcnJheS5nZXQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtUHJvcEluQXJyYXkuc2V0KG51bGwpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZmx0RG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGVtcGxhdGVQcm9wID0gTGliLm5lc3RlZFByb3BlcnR5KHRlbXBsYXRlT3V0LCBuZXh0UGF0aCk7XG4gICAgICAgICAgICB0ZW1wbGF0ZVByb3Auc2V0KGNoaWxkKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0TGF5b3V0SW5mbyhsYXlvdXQsIHBhdGgpIHtcbiAgICByZXR1cm4gUGxvdFNjaGVtYS5nZXRMYXlvdXRWYWxPYmplY3QoXG4gICAgICAgIGxheW91dCwgTGliLm5lc3RlZFByb3BlcnR5KHt9LCBwYXRoKS5wYXJ0c1xuICAgICk7XG59XG5cbmZ1bmN0aW9uIGdldFRyYWNlSW5mbyh0cmFjZSwgcGF0aCkge1xuICAgIHJldHVybiBQbG90U2NoZW1hLmdldFRyYWNlVmFsT2JqZWN0KFxuICAgICAgICB0cmFjZSwgTGliLm5lc3RlZFByb3BlcnR5KHt9LCBwYXRoKS5wYXJ0c1xuICAgICk7XG59XG5cbmZ1bmN0aW9uIGdldE5leHRQYXRoKHBhcmVudCwga2V5LCBwYXRoKSB7XG4gICAgdmFyIG5leHRQYXRoO1xuICAgIGlmKCFwYXRoKSBuZXh0UGF0aCA9IGtleTtcbiAgICBlbHNlIGlmKEFycmF5LmlzQXJyYXkocGFyZW50KSkgbmV4dFBhdGggPSBwYXRoICsgJ1snICsga2V5ICsgJ10nO1xuICAgIGVsc2UgbmV4dFBhdGggPSBwYXRoICsgJy4nICsga2V5O1xuXG4gICAgcmV0dXJuIG5leHRQYXRoO1xufVxuXG4vKipcbiAqIHZhbGlkYXRlVGVtcGxhdGU6IFRlc3QgZm9yIGNvbnNpc3RlbmN5IGJldHdlZW4gdGhlIGdpdmVuIGZpZ3VyZSBhbmRcbiAqIGEgdGVtcGxhdGUsIGVpdGhlciBhbHJlYWR5IGluY2x1ZGVkIGluIHRoZSBmaWd1cmUgb3IgZ2l2ZW4gc2VwYXJhdGVseS5cbiAqIE5vdGUgdGhhdCBub3QgZXZlcnkgaXNzdWUgd2UgaWRlbnRpZnkgaGVyZSBpcyBuZWNlc3NhcmlseSBhIHByb2JsZW0sXG4gKiBpdCBkZXBlbmRzIG9uIHdoYXQgeW91J3JlIHVzaW5nIHRoZSB0ZW1wbGF0ZSBmb3IuXG4gKlxuICogQHBhcmFtIHtvYmplY3R8RE9NIGVsZW1lbnR9IGZpZ3VyZTogdGhlIHBsb3QsIHdpdGgge2RhdGEsIGxheW91dH0gbWVtYmVycyxcbiAqICAgICB0byB0ZXN0IHRoZSB0ZW1wbGF0ZSBhZ2FpbnN0XG4gKiBAcGFyYW0ge09wdGlvbmFsKG9iamVjdCl9IHRlbXBsYXRlOiB0aGUgdGVtcGxhdGUsIHdpdGggaXRzIG93biB7ZGF0YSwgbGF5b3V0fSxcbiAqICAgICB0byB0ZXN0LiBJZiBvbWl0dGVkLCB3ZSB3aWxsIGxvb2sgZm9yIGEgdGVtcGxhdGUgYWxyZWFkeSBhdHRhY2hlZCBhcyB0aGVcbiAqICAgICBwbG90J3MgYGxheW91dC50ZW1wbGF0ZWAgYXR0cmlidXRlLlxuICpcbiAqIEByZXR1cm5zIHthcnJheX0gYXJyYXkgb2YgZXJyb3Igb2JqZWN0cyBlYWNoIGNvbnRhaW5pbmc6XG4gKiAgLSB7c3RyaW5nfSBjb2RlXG4gKiAgICAgIGVycm9yIGNvZGUgKCdtaXNzaW5nJywgJ3VudXNlZCcsICdyZXVzZWQnLCAnbm9MYXlvdXQnLCAnbm9EYXRhJylcbiAqICAtIHtzdHJpbmd9IG1zZ1xuICogICAgICBhIGZ1bGwgcmVhZGFibGUgZGVzY3JpcHRpb24gb2YgdGhlIGlzc3VlLlxuICovXG5leHBvcnRzLnZhbGlkYXRlVGVtcGxhdGUgPSBmdW5jdGlvbihmaWd1cmVJbiwgdGVtcGxhdGUpIHtcbiAgICB2YXIgZmlndXJlID0gTGliLmV4dGVuZERlZXAoe30sIHtcbiAgICAgICAgX2NvbnRleHQ6IGRmbHRDb25maWcsXG4gICAgICAgIGRhdGE6IGZpZ3VyZUluLmRhdGEsXG4gICAgICAgIGxheW91dDogZmlndXJlSW4ubGF5b3V0XG4gICAgfSk7XG4gICAgdmFyIGxheW91dCA9IGZpZ3VyZS5sYXlvdXQgfHwge307XG4gICAgaWYoIWlzUGxhaW5PYmplY3QodGVtcGxhdGUpKSB0ZW1wbGF0ZSA9IGxheW91dC50ZW1wbGF0ZSB8fCB7fTtcbiAgICB2YXIgbGF5b3V0VGVtcGxhdGUgPSB0ZW1wbGF0ZS5sYXlvdXQ7XG4gICAgdmFyIGRhdGFUZW1wbGF0ZSA9IHRlbXBsYXRlLmRhdGE7XG4gICAgdmFyIGVycm9yTGlzdCA9IFtdO1xuXG4gICAgZmlndXJlLmxheW91dCA9IGxheW91dDtcbiAgICBmaWd1cmUubGF5b3V0LnRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZmlndXJlKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZmlndXJlLl9mdWxsTGF5b3V0O1xuICAgIHZhciBmdWxsRGF0YSA9IGZpZ3VyZS5fZnVsbERhdGE7XG5cbiAgICB2YXIgbGF5b3V0UGF0aHMgPSB7fTtcbiAgICBmdW5jdGlvbiBjcmF3bExheW91dEZvckNvbnRhaW5lcnMob2JqLCBwYXRocykge1xuICAgICAgICBmb3IodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmKGtleS5jaGFyQXQoMCkgIT09ICdfJyAmJiBpc1BsYWluT2JqZWN0KG9ialtrZXldKSkge1xuICAgICAgICAgICAgICAgIHZhciBiYXNlS2V5ID0gZ2V0QmFzZUtleShrZXkpO1xuICAgICAgICAgICAgICAgIHZhciBuZXh0UGF0aHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBuZXh0UGF0aHMucHVzaChnZXROZXh0UGF0aChvYmosIGtleSwgcGF0aHNbaV0pKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoYmFzZUtleSAhPT0ga2V5KSBuZXh0UGF0aHMucHVzaChnZXROZXh0UGF0aChvYmosIGJhc2VLZXksIHBhdGhzW2ldKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG5leHRQYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsYXlvdXRQYXRoc1tuZXh0UGF0aHNbaV1dID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3Jhd2xMYXlvdXRGb3JDb250YWluZXJzKG9ialtrZXldLCBuZXh0UGF0aHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3Jhd2xMYXlvdXRUZW1wbGF0ZUZvckNvbnRhaW5lcnMob2JqLCBwYXRoKSB7XG4gICAgICAgIGZvcih2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgaWYoa2V5LmluZGV4T2YoJ2RlZmF1bHRzJykgPT09IC0xICYmIGlzUGxhaW5PYmplY3Qob2JqW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHRQYXRoID0gZ2V0TmV4dFBhdGgob2JqLCBrZXksIHBhdGgpO1xuICAgICAgICAgICAgICAgIGlmKGxheW91dFBhdGhzW25leHRQYXRoXSkge1xuICAgICAgICAgICAgICAgICAgICBjcmF3bExheW91dFRlbXBsYXRlRm9yQ29udGFpbmVycyhvYmpba2V5XSwgbmV4dFBhdGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe2NvZGU6ICd1bnVzZWQnLCBwYXRoOiBuZXh0UGF0aH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCFpc1BsYWluT2JqZWN0KGxheW91dFRlbXBsYXRlKSkge1xuICAgICAgICBlcnJvckxpc3QucHVzaCh7Y29kZTogJ2xheW91dCd9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNyYXdsTGF5b3V0Rm9yQ29udGFpbmVycyhmdWxsTGF5b3V0LCBbJ2xheW91dCddKTtcbiAgICAgICAgY3Jhd2xMYXlvdXRUZW1wbGF0ZUZvckNvbnRhaW5lcnMobGF5b3V0VGVtcGxhdGUsICdsYXlvdXQnKTtcbiAgICB9XG5cbiAgICBpZighaXNQbGFpbk9iamVjdChkYXRhVGVtcGxhdGUpKSB7XG4gICAgICAgIGVycm9yTGlzdC5wdXNoKHtjb2RlOiAnZGF0YSd9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciB0eXBlQ291bnQgPSB7fTtcbiAgICAgICAgdmFyIHRyYWNlVHlwZTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZnVsbFRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgICAgICB0cmFjZVR5cGUgPSBmdWxsVHJhY2UudHlwZTtcbiAgICAgICAgICAgIHR5cGVDb3VudFt0cmFjZVR5cGVdID0gKHR5cGVDb3VudFt0cmFjZVR5cGVdIHx8IDApICsgMTtcbiAgICAgICAgICAgIGlmKCFmdWxsVHJhY2UuX2Z1bGxJbnB1dC5fdGVtcGxhdGUpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHRha2VzIGNhcmUgb2YgdGhlIGNhc2Ugb2YgdHJhY2VUeXBlIGluIHRoZSBkYXRhIGJ1dCBub3RcbiAgICAgICAgICAgICAgICAvLyB0aGUgdGVtcGxhdGVcbiAgICAgICAgICAgICAgICBlcnJvckxpc3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6ICdtaXNzaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgaW5kZXg6IGZ1bGxUcmFjZS5fZnVsbElucHV0LmluZGV4LFxuICAgICAgICAgICAgICAgICAgICB0cmFjZVR5cGU6IHRyYWNlVHlwZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvcih0cmFjZVR5cGUgaW4gZGF0YVRlbXBsYXRlKSB7XG4gICAgICAgICAgICB2YXIgdGVtcGxhdGVDb3VudCA9IGRhdGFUZW1wbGF0ZVt0cmFjZVR5cGVdLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBkYXRhQ291bnQgPSB0eXBlQ291bnRbdHJhY2VUeXBlXSB8fCAwO1xuICAgICAgICAgICAgaWYodGVtcGxhdGVDb3VudCA+IGRhdGFDb3VudCkge1xuICAgICAgICAgICAgICAgIGVycm9yTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ3VudXNlZCcsXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlVHlwZTogdHJhY2VUeXBlLFxuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZUNvdW50OiB0ZW1wbGF0ZUNvdW50LFxuICAgICAgICAgICAgICAgICAgICBkYXRhQ291bnQ6IGRhdGFDb3VudFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihkYXRhQ291bnQgPiB0ZW1wbGF0ZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiAncmV1c2VkJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VUeXBlOiB0cmFjZVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlQ291bnQ6IHRlbXBsYXRlQ291bnQsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFDb3VudDogZGF0YUNvdW50XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBfdGVtcGxhdGU6IGZhbHNlIGlzIHdoZW4gc29tZW9uZSB0cmllZCB0byBtb2RpZnkgYW4gYXJyYXkgaXRlbVxuICAgIC8vIGJ1dCB0aGVyZSB3YXMgbm8gdGVtcGxhdGUgd2l0aCBtYXRjaGluZyBuYW1lXG4gICAgZnVuY3Rpb24gY3Jhd2xGb3JNaXNzaW5nVGVtcGxhdGVzKG9iaiwgcGF0aCkge1xuICAgICAgICBmb3IodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmKGtleS5jaGFyQXQoMCkgPT09ICdfJykgY29udGludWU7XG4gICAgICAgICAgICB2YXIgdmFsID0gb2JqW2tleV07XG4gICAgICAgICAgICB2YXIgbmV4dFBhdGggPSBnZXROZXh0UGF0aChvYmosIGtleSwgcGF0aCk7XG4gICAgICAgICAgICBpZihpc1BsYWluT2JqZWN0KHZhbCkpIHtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KG9iaikgJiYgdmFsLl90ZW1wbGF0ZSA9PT0gZmFsc2UgJiYgdmFsLnRlbXBsYXRlaXRlbW5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogJ21pc3NpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogbmV4dFBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZWl0ZW1uYW1lOiB2YWwudGVtcGxhdGVpdGVtbmFtZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3Jhd2xGb3JNaXNzaW5nVGVtcGxhdGVzKHZhbCwgbmV4dFBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihBcnJheS5pc0FycmF5KHZhbCkgJiYgaGFzUGxhaW5PYmplY3QodmFsKSkge1xuICAgICAgICAgICAgICAgIGNyYXdsRm9yTWlzc2luZ1RlbXBsYXRlcyh2YWwsIG5leHRQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBjcmF3bEZvck1pc3NpbmdUZW1wbGF0ZXMoe2RhdGE6IGZ1bGxEYXRhLCBsYXlvdXQ6IGZ1bGxMYXlvdXR9LCAnJyk7XG5cbiAgICBpZihlcnJvckxpc3QubGVuZ3RoKSByZXR1cm4gZXJyb3JMaXN0Lm1hcChmb3JtYXQpO1xufTtcblxuZnVuY3Rpb24gaGFzUGxhaW5PYmplY3QoYXJyKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihpc1BsYWluT2JqZWN0KGFycltpXSkpIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZm9ybWF0KG9wdHMpIHtcbiAgICB2YXIgbXNnO1xuICAgIHN3aXRjaChvcHRzLmNvZGUpIHtcbiAgICAgICAgY2FzZSAnZGF0YSc6XG4gICAgICAgICAgICBtc2cgPSAnVGhlIHRlbXBsYXRlIGhhcyBubyBrZXkgZGF0YS4nO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2xheW91dCc6XG4gICAgICAgICAgICBtc2cgPSAnVGhlIHRlbXBsYXRlIGhhcyBubyBrZXkgbGF5b3V0Lic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbWlzc2luZyc6XG4gICAgICAgICAgICBpZihvcHRzLnBhdGgpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAnVGhlcmUgYXJlIG5vIHRlbXBsYXRlcyBmb3IgaXRlbSAnICsgb3B0cy5wYXRoICtcbiAgICAgICAgICAgICAgICAgICAgJyB3aXRoIG5hbWUgJyArIG9wdHMudGVtcGxhdGVpdGVtbmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1zZyA9ICdUaGVyZSBhcmUgbm8gdGVtcGxhdGVzIGZvciB0cmFjZSAnICsgb3B0cy5pbmRleCArXG4gICAgICAgICAgICAgICAgICAgICcsIG9mIHR5cGUgJyArIG9wdHMudHJhY2VUeXBlICsgJy4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3VudXNlZCc6XG4gICAgICAgICAgICBpZihvcHRzLnBhdGgpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAnVGhlIHRlbXBsYXRlIGl0ZW0gYXQgJyArIG9wdHMucGF0aCArXG4gICAgICAgICAgICAgICAgICAgICcgd2FzIG5vdCB1c2VkIGluIGNvbnN0cnVjdGluZyB0aGUgcGxvdC4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihvcHRzLmRhdGFDb3VudCkge1xuICAgICAgICAgICAgICAgIG1zZyA9ICdTb21lIG9mIHRoZSB0ZW1wbGF0ZXMgb2YgdHlwZSAnICsgb3B0cy50cmFjZVR5cGUgK1xuICAgICAgICAgICAgICAgICAgICAnIHdlcmUgbm90IHVzZWQuIFRoZSB0ZW1wbGF0ZSBoYXMgJyArIG9wdHMudGVtcGxhdGVDb3VudCArXG4gICAgICAgICAgICAgICAgICAgICcgdHJhY2VzLCB0aGUgZGF0YSBvbmx5IGhhcyAnICsgb3B0cy5kYXRhQ291bnQgK1xuICAgICAgICAgICAgICAgICAgICAnIG9mIHRoaXMgdHlwZS4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbXNnID0gJ1RoZSB0ZW1wbGF0ZSBoYXMgJyArIG9wdHMudGVtcGxhdGVDb3VudCArXG4gICAgICAgICAgICAgICAgICAgICcgdHJhY2VzIG9mIHR5cGUgJyArIG9wdHMudHJhY2VUeXBlICtcbiAgICAgICAgICAgICAgICAgICAgJyBidXQgdGhlcmUgYXJlIG5vbmUgaW4gdGhlIGRhdGEuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdyZXVzZWQnOlxuICAgICAgICAgICAgbXNnID0gJ1NvbWUgb2YgdGhlIHRlbXBsYXRlcyBvZiB0eXBlICcgKyBvcHRzLnRyYWNlVHlwZSArXG4gICAgICAgICAgICAgICAgJyB3ZXJlIHVzZWQgbW9yZSB0aGFuIG9uY2UuIFRoZSB0ZW1wbGF0ZSBoYXMgJyArXG4gICAgICAgICAgICAgICAgb3B0cy50ZW1wbGF0ZUNvdW50ICsgJyB0cmFjZXMsIHRoZSBkYXRhIGhhcyAnICtcbiAgICAgICAgICAgICAgICBvcHRzLmRhdGFDb3VudCArICcgb2YgdGhpcyB0eXBlLic7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgb3B0cy5tc2cgPSBtc2c7XG5cbiAgICByZXR1cm4gb3B0cztcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHBsb3RBcGkgPSByZXF1aXJlKCcuL3Bsb3RfYXBpJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG5cbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi4vc25hcHNob3QvaGVscGVycycpO1xudmFyIHRvU1ZHID0gcmVxdWlyZSgnLi4vc25hcHNob3QvdG9zdmcnKTtcbnZhciBzdmdUb0ltZyA9IHJlcXVpcmUoJy4uL3NuYXBzaG90L3N2Z3RvaW1nJyk7XG5cbnZhciBhdHRycyA9IHtcbiAgICBmb3JtYXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsncG5nJywgJ2pwZWcnLCAnd2VicCcsICdzdmcnXSxcbiAgICAgICAgZGZsdDogJ3BuZycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBoZWlnaHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzY2FsZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNldEJhY2tncm91bmQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGltYWdlRGF0YU9ubHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfVxufTtcblxudmFyIElNQUdFX1VSTF9QUkVGSVggPSAvXmRhdGE6aW1hZ2VcXC9cXHcrO2Jhc2U2NCwvO1xuXG4vKiogUGxvdGx5LnRvSW1hZ2VcbiAqXG4gKiBAcGFyYW0ge29iamVjdCB8IHN0cmluZyB8IEhUTUwgZGl2fSBnZFxuICogICBjYW4gZWl0aGVyIGJlIGEgZGF0YS9sYXlvdXQvY29uZmlnIG9iamVjdFxuICogICBvciBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogICBvciBhbiBpZCB0byBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgKHNlZSBhYm92ZSlcbiAqIEByZXR1cm4ge3Byb21pc2V9XG4gKi9cbmZ1bmN0aW9uIHRvSW1hZ2UoZ2QsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBkYXRhO1xuICAgIHZhciBsYXlvdXQ7XG4gICAgdmFyIGNvbmZpZztcblxuICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KGdkKSkge1xuICAgICAgICBkYXRhID0gZ2QuZGF0YSB8fCBbXTtcbiAgICAgICAgbGF5b3V0ID0gZ2QubGF5b3V0IHx8IHt9O1xuICAgICAgICBjb25maWcgPSBnZC5jb25maWcgfHwge307XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuICAgICAgICBkYXRhID0gTGliLmV4dGVuZERlZXAoW10sIGdkLmRhdGEpO1xuICAgICAgICBsYXlvdXQgPSBMaWIuZXh0ZW5kRGVlcCh7fSwgZ2QubGF5b3V0KTtcbiAgICAgICAgY29uZmlnID0gZ2QuX2NvbnRleHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNJbXBsaWVkT3JWYWxpZChhdHRyKSB7XG4gICAgICAgIHJldHVybiAhKGF0dHIgaW4gb3B0cykgfHwgTGliLnZhbGlkYXRlKG9wdHNbYXR0cl0sIGF0dHJzW2F0dHJdKTtcbiAgICB9XG5cbiAgICBpZighaXNJbXBsaWVkT3JWYWxpZCgnd2lkdGgnKSB8fCAhaXNJbXBsaWVkT3JWYWxpZCgnaGVpZ2h0JykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIZWlnaHQgYW5kIHdpZHRoIHNob3VsZCBiZSBwaXhlbCB2YWx1ZXMuJyk7XG4gICAgfVxuXG4gICAgaWYoIWlzSW1wbGllZE9yVmFsaWQoJ2Zvcm1hdCcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgZm9ybWF0IGlzIG5vdCBqcGVnLCBwbmcsIHN2ZyBvciB3ZWJwLicpO1xuICAgIH1cblxuICAgIHZhciBmdWxsT3B0cyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2Uob3B0cywgZnVsbE9wdHMsIGF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZm9ybWF0ID0gY29lcmNlKCdmb3JtYXQnKTtcbiAgICB2YXIgd2lkdGggPSBjb2VyY2UoJ3dpZHRoJyk7XG4gICAgdmFyIGhlaWdodCA9IGNvZXJjZSgnaGVpZ2h0Jyk7XG4gICAgdmFyIHNjYWxlID0gY29lcmNlKCdzY2FsZScpO1xuICAgIHZhciBzZXRCYWNrZ3JvdW5kID0gY29lcmNlKCdzZXRCYWNrZ3JvdW5kJyk7XG4gICAgdmFyIGltYWdlRGF0YU9ubHkgPSBjb2VyY2UoJ2ltYWdlRGF0YU9ubHknKTtcblxuICAgIC8vIHB1dCB0aGUgY2xvbmVkIGRpdiBzb21ld2hlcmUgb2ZmIHNjcmVlbiBiZWZvcmUgYXR0YWNoaW5nIHRvIERPTVxuICAgIHZhciBjbG9uZWRHZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNsb25lZEdkLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBjbG9uZWRHZC5zdHlsZS5sZWZ0ID0gJy01MDAwcHgnO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY2xvbmVkR2QpO1xuXG4gICAgLy8gZXh0ZW5kIGxheW91dCB3aXRoIGltYWdlIG9wdGlvbnNcbiAgICB2YXIgbGF5b3V0SW1hZ2UgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgbGF5b3V0KTtcbiAgICBpZih3aWR0aCkgbGF5b3V0SW1hZ2Uud2lkdGggPSB3aWR0aDtcbiAgICBpZihoZWlnaHQpIGxheW91dEltYWdlLmhlaWdodCA9IGhlaWdodDtcblxuICAgIC8vIGV4dGVuZCBjb25maWcgZm9yIHN0YXRpYyBwbG90XG4gICAgdmFyIGNvbmZpZ0ltYWdlID0gTGliLmV4dGVuZEZsYXQoe30sIGNvbmZpZywge1xuICAgICAgICBzdGF0aWNQbG90OiB0cnVlLFxuICAgICAgICBzZXRCYWNrZ3JvdW5kOiBzZXRCYWNrZ3JvdW5kXG4gICAgfSk7XG5cbiAgICB2YXIgcmVkcmF3RnVuYyA9IGhlbHBlcnMuZ2V0UmVkcmF3RnVuYyhjbG9uZWRHZCk7XG5cbiAgICBmdW5jdGlvbiB3YWl0KCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgICAgc2V0VGltZW91dChyZXNvbHZlLCBoZWxwZXJzLmdldERlbGF5KGNsb25lZEdkLl9mdWxsTGF5b3V0KSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbnZlcnQoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHZhciBzdmcgPSB0b1NWRyhjbG9uZWRHZCwgZm9ybWF0LCBzY2FsZSk7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSBjbG9uZWRHZC5fZnVsbExheW91dC53aWR0aDtcbiAgICAgICAgICAgIHZhciBoZWlnaHQgPSBjbG9uZWRHZC5fZnVsbExheW91dC5oZWlnaHQ7XG5cbiAgICAgICAgICAgIHBsb3RBcGkucHVyZ2UoY2xvbmVkR2QpO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChjbG9uZWRHZCk7XG5cbiAgICAgICAgICAgIGlmKGZvcm1hdCA9PT0gJ3N2ZycpIHtcbiAgICAgICAgICAgICAgICBpZihpbWFnZURhdGFPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHN2Zyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoJ2RhdGE6aW1hZ2Uvc3ZnK3htbCwnICsgZW5jb2RlVVJJQ29tcG9uZW50KHN2ZykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgY2FudmFzLmlkID0gTGliLnJhbmRzdHIoKTtcblxuICAgICAgICAgICAgc3ZnVG9JbWcoe1xuICAgICAgICAgICAgICAgIGZvcm1hdDogZm9ybWF0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgICAgICBzY2FsZTogc2NhbGUsXG4gICAgICAgICAgICAgICAgY2FudmFzOiBjYW52YXMsXG4gICAgICAgICAgICAgICAgc3ZnOiBzdmcsXG4gICAgICAgICAgICAgICAgLy8gYXNrIHN2Z1RvSW1nIHRvIHJldHVybiBhIFByb21pc2VcbiAgICAgICAgICAgICAgICAvLyAgcmF0aGVyIHRoYW4gRXZlbnRFbWl0dGVyXG4gICAgICAgICAgICAgICAgLy8gIGxlYXZlIEV2ZW50RW1pdHRlciBmb3IgYmFja3dhcmRcbiAgICAgICAgICAgICAgICAvLyAgY29tcGF0aWJpbGl0eVxuICAgICAgICAgICAgICAgIHByb21pc2U6IHRydWVcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihyZXNvbHZlKVxuICAgICAgICAgICAgLmNhdGNoKHJlamVjdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVybFRvSW1hZ2VEYXRhKHVybCkge1xuICAgICAgICBpZihpbWFnZURhdGFPbmx5KSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsLnJlcGxhY2UoSU1BR0VfVVJMX1BSRUZJWCwgJycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgcGxvdEFwaS5wbG90KGNsb25lZEdkLCBkYXRhLCBsYXlvdXRJbWFnZSwgY29uZmlnSW1hZ2UpXG4gICAgICAgICAgICAudGhlbihyZWRyYXdGdW5jKVxuICAgICAgICAgICAgLnRoZW4od2FpdClcbiAgICAgICAgICAgIC50aGVuKGNvbnZlcnQpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbih1cmwpIHsgcmVzb2x2ZSh1cmxUb0ltYWdlRGF0YSh1cmwpKTsgfSlcbiAgICAgICAgICAgIC5jYXRjaChmdW5jdGlvbihlcnIpIHsgcmVqZWN0KGVycik7IH0pO1xuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRvSW1hZ2U7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgUGxvdFNjaGVtYSA9IHJlcXVpcmUoJy4vcGxvdF9zY2hlbWEnKTtcbnZhciBkZmx0Q29uZmlnID0gcmVxdWlyZSgnLi9wbG90X2NvbmZpZycpO1xuXG52YXIgaXNQbGFpbk9iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0O1xudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBhIGRhdGEgYXJyYXkgYW5kIGxheW91dCBvYmplY3QuXG4gKlxuICogQHBhcmFtIHthcnJheX0gZGF0YVxuICogQHBhcmFtIHtvYmplY3R9IGxheW91dFxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBhcnJheSBvZiBlcnJvciBvYmplY3RzIGVhY2ggY29udGFpbmluZzpcbiAqICAtIHtzdHJpbmd9IGNvZGVcbiAqICAgICAgZXJyb3IgY29kZSAoJ29iamVjdCcsICdhcnJheScsICdzY2hlbWEnLCAndW51c2VkJywgJ2ludmlzaWJsZScgb3IgJ3ZhbHVlJylcbiAqICAtIHtzdHJpbmd9IGNvbnRhaW5lclxuICogICAgICBjb250YWluZXIgd2hlcmUgdGhlIGVycm9yIG9jY3VycyAoJ2RhdGEnIG9yICdsYXlvdXQnKVxuICogIC0ge251bWJlcn0gdHJhY2VcbiAqICAgICAgdHJhY2UgaW5kZXggb2YgdGhlICdkYXRhJyBjb250YWluZXIgd2hlcmUgdGhlIGVycm9yIG9jY3Vyc1xuICogIC0ge2FycmF5fSBwYXRoXG4gKiAgICAgIG5lc3RlZCBwYXRoIHRvIHRoZSBrZXkgdGhhdCBjYXVzZXMgdGhlIGVycm9yXG4gKiAgLSB7c3RyaW5nfSBhc3RyXG4gKiAgICAgIGF0dHJpYnV0ZSBzdHJpbmcgdmFyaWFudCBvZiAncGF0aCcgY29tcGF0aWJsZSB3aXRoIFBsb3RseS5yZXN0eWxlIGFuZFxuICogICAgICBQbG90bHkucmVsYXlvdXQuXG4gKiAgLSB7c3RyaW5nfSBtc2dcbiAqICAgICAgZXJyb3IgbWVzc2FnZSAoc2hvd24gaW4gY29uc29sZSBpbiBsb2dnZXIgY29uZmlnIGFyZ3VtZW50IGlzIGVuYWJsZSlcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB2YWxpZGF0ZShkYXRhLCBsYXlvdXQpIHtcbiAgICB2YXIgc2NoZW1hID0gUGxvdFNjaGVtYS5nZXQoKTtcbiAgICB2YXIgZXJyb3JMaXN0ID0gW107XG4gICAgdmFyIGdkID0ge19jb250ZXh0OiBMaWIuZXh0ZW5kRmxhdCh7fSwgZGZsdENvbmZpZyl9O1xuXG4gICAgdmFyIGRhdGFJbiwgbGF5b3V0SW47XG5cbiAgICBpZihpc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIGdkLmRhdGEgPSBMaWIuZXh0ZW5kRGVlcChbXSwgZGF0YSk7XG4gICAgICAgIGRhdGFJbiA9IGRhdGE7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBnZC5kYXRhID0gW107XG4gICAgICAgIGRhdGFJbiA9IFtdO1xuICAgICAgICBlcnJvckxpc3QucHVzaChmb3JtYXQoJ2FycmF5JywgJ2RhdGEnKSk7XG4gICAgfVxuXG4gICAgaWYoaXNQbGFpbk9iamVjdChsYXlvdXQpKSB7XG4gICAgICAgIGdkLmxheW91dCA9IExpYi5leHRlbmREZWVwKHt9LCBsYXlvdXQpO1xuICAgICAgICBsYXlvdXRJbiA9IGxheW91dDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGdkLmxheW91dCA9IHt9O1xuICAgICAgICBsYXlvdXRJbiA9IHt9O1xuICAgICAgICBpZihhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goZm9ybWF0KCdvYmplY3QnLCAnbGF5b3V0JykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTi5CLiBkYXRhSW4gYW5kIGxheW91dEluIGFyZSBpbiBnZW5lcmFsIG5vdCB0aGUgc2FtZSBhc1xuICAgIC8vIGdkLmRhdGEgYW5kIGdkLmxheW91dCBhZnRlciBzdXBwbHlEZWZhdWx0cyBhcyBzb21lIGF0dHJpYnV0ZXNcbiAgICAvLyBpbiBnZC5kYXRhIGFuZCBnZC5sYXlvdXQgKHN0aWxsKSBnZXQgbXV0YXRlZCBkdXJpbmcgdGhpcyBzdGVwLlxuXG4gICAgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZ2QpO1xuXG4gICAgdmFyIGRhdGFPdXQgPSBnZC5fZnVsbERhdGEsXG4gICAgICAgIGxlbiA9IGRhdGFJbi5sZW5ndGg7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlSW4gPSBkYXRhSW5baV0sXG4gICAgICAgICAgICBiYXNlID0gWydkYXRhJywgaV07XG5cbiAgICAgICAgaWYoIWlzUGxhaW5PYmplY3QodHJhY2VJbikpIHtcbiAgICAgICAgICAgIGVycm9yTGlzdC5wdXNoKGZvcm1hdCgnb2JqZWN0JywgYmFzZSkpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhY2VPdXQgPSBkYXRhT3V0W2ldLFxuICAgICAgICAgICAgdHJhY2VUeXBlID0gdHJhY2VPdXQudHlwZSxcbiAgICAgICAgICAgIHRyYWNlU2NoZW1hID0gc2NoZW1hLnRyYWNlc1t0cmFjZVR5cGVdLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgLy8gUGxvdFNjaGVtYSBkb2VzIHNvbWV0aGluZyBmYW5jeSB3aXRoIHRyYWNlICd0eXBlJywgcmVzZXQgaXQgaGVyZVxuICAgICAgICAvLyB0byBtYWtlIHRoZSB0cmFjZSBzY2hlbWEgY29tcGF0aWJsZSB3aXRoIExpYi52YWxpZGF0ZS5cbiAgICAgICAgdHJhY2VTY2hlbWEudHlwZSA9IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogW3RyYWNlVHlwZV1cbiAgICAgICAgfTtcblxuICAgICAgICBpZih0cmFjZU91dC52aXNpYmxlID09PSBmYWxzZSAmJiB0cmFjZUluLnZpc2libGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICBlcnJvckxpc3QucHVzaChmb3JtYXQoJ2ludmlzaWJsZScsIGJhc2UpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNyYXdsKHRyYWNlSW4sIHRyYWNlT3V0LCB0cmFjZVNjaGVtYSwgZXJyb3JMaXN0LCBiYXNlKTtcblxuICAgICAgICB2YXIgdHJhbnNmb3Jtc0luID0gdHJhY2VJbi50cmFuc2Zvcm1zLFxuICAgICAgICAgICAgdHJhbnNmb3Jtc091dCA9IHRyYWNlT3V0LnRyYW5zZm9ybXM7XG5cbiAgICAgICAgaWYodHJhbnNmb3Jtc0luKSB7XG4gICAgICAgICAgICBpZighaXNBcnJheSh0cmFuc2Zvcm1zSW4pKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goZm9ybWF0KCdhcnJheScsIGJhc2UsIFsndHJhbnNmb3JtcyddKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJhc2UucHVzaCgndHJhbnNmb3JtcycpO1xuXG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdHJhbnNmb3Jtc0luLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGggPSBbJ3RyYW5zZm9ybXMnLCBqXSxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtVHlwZSA9IHRyYW5zZm9ybXNJbltqXS50eXBlO1xuXG4gICAgICAgICAgICAgICAgaWYoIWlzUGxhaW5PYmplY3QodHJhbnNmb3Jtc0luW2pdKSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckxpc3QucHVzaChmb3JtYXQoJ29iamVjdCcsIGJhc2UsIHBhdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybVNjaGVtYSA9IHNjaGVtYS50cmFuc2Zvcm1zW3RyYW5zZm9ybVR5cGVdID9cbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hLnRyYW5zZm9ybXNbdHJhbnNmb3JtVHlwZV0uYXR0cmlidXRlcyA6XG4gICAgICAgICAgICAgICAgICAgIHt9O1xuXG4gICAgICAgICAgICAgICAgLy8gYWRkICd0eXBlJyB0byB0cmFuc2Zvcm0gc2NoZW1hIHRvIHZhbGlkYXRlIHRoZSB0cmFuc2Zvcm0gdHlwZVxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVNjaGVtYS50eXBlID0ge1xuICAgICAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogT2JqZWN0LmtleXMoc2NoZW1hLnRyYW5zZm9ybXMpXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGNyYXdsKHRyYW5zZm9ybXNJbltqXSwgdHJhbnNmb3Jtc091dFtqXSwgdHJhbnNmb3JtU2NoZW1hLCBlcnJvckxpc3QsIGJhc2UsIHBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGxheW91dE91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBsYXlvdXRTY2hlbWEgPSBmaWxsTGF5b3V0U2NoZW1hKHNjaGVtYSwgZGF0YU91dCk7XG5cbiAgICBjcmF3bChsYXlvdXRJbiwgbGF5b3V0T3V0LCBsYXlvdXRTY2hlbWEsIGVycm9yTGlzdCwgJ2xheW91dCcpO1xuXG4gICAgLy8gcmV0dXJuIHVuZGVmaW5lZCBpZiBubyB2YWxpZGF0aW9uIGVycm9ycyB3ZXJlIGZvdW5kXG4gICAgcmV0dXJuIChlcnJvckxpc3QubGVuZ3RoID09PSAwKSA/IHZvaWQoMCkgOiBlcnJvckxpc3Q7XG59O1xuXG5mdW5jdGlvbiBjcmF3bChvYmpJbiwgb2JqT3V0LCBzY2hlbWEsIGxpc3QsIGJhc2UsIHBhdGgpIHtcbiAgICBwYXRoID0gcGF0aCB8fCBbXTtcblxuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqSW4pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGsgPSBrZXlzW2ldO1xuXG4gICAgICAgIC8vIHRyYW5zZm9ybXMgYXJlIGhhbmRsZWQgc2VwYXJhdGVseVxuICAgICAgICBpZihrID09PSAndHJhbnNmb3JtcycpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBwID0gcGF0aC5zbGljZSgpO1xuICAgICAgICBwLnB1c2goayk7XG5cbiAgICAgICAgdmFyIHZhbEluID0gb2JqSW5ba10sXG4gICAgICAgICAgICB2YWxPdXQgPSBvYmpPdXRba107XG5cbiAgICAgICAgdmFyIG5lc3RlZFNjaGVtYSA9IGdldE5lc3RlZFNjaGVtYShzY2hlbWEsIGspO1xuICAgICAgICB2YXIgaXNJbmZvQXJyYXkgPSAobmVzdGVkU2NoZW1hIHx8IHt9KS52YWxUeXBlID09PSAnaW5mb19hcnJheSc7XG4gICAgICAgIHZhciBpc0NvbG9yc2NhbGUgPSAobmVzdGVkU2NoZW1hIHx8IHt9KS52YWxUeXBlID09PSAnY29sb3JzY2FsZSc7XG4gICAgICAgIHZhciBpdGVtcyA9IChuZXN0ZWRTY2hlbWEgfHwge30pLml0ZW1zO1xuXG4gICAgICAgIGlmKCFpc0luU2NoZW1hKHNjaGVtYSwgaykpIHtcbiAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ3NjaGVtYScsIGJhc2UsIHApKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGlzUGxhaW5PYmplY3QodmFsSW4pICYmIGlzUGxhaW5PYmplY3QodmFsT3V0KSkge1xuICAgICAgICAgICAgY3Jhd2wodmFsSW4sIHZhbE91dCwgbmVzdGVkU2NoZW1hLCBsaXN0LCBiYXNlLCBwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGlzSW5mb0FycmF5ICYmIGlzQXJyYXkodmFsSW4pKSB7XG4gICAgICAgICAgICBpZih2YWxJbi5sZW5ndGggPiB2YWxPdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgndW51c2VkJywgYmFzZSwgcC5jb25jYXQodmFsT3V0Lmxlbmd0aCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBsZW4gPSB2YWxPdXQubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGFycmF5SXRlbXMgPSBBcnJheS5pc0FycmF5KGl0ZW1zKTtcbiAgICAgICAgICAgIGlmKGFycmF5SXRlbXMpIGxlbiA9IE1hdGgubWluKGxlbiwgaXRlbXMubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBtLCBuLCBpdGVtLCB2YWxJblBhcnQsIHZhbE91dFBhcnQ7XG4gICAgICAgICAgICBpZihuZXN0ZWRTY2hlbWEuZGltZW5zaW9ucyA9PT0gMikge1xuICAgICAgICAgICAgICAgIGZvcihuID0gMDsgbiA8IGxlbjsgbisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGlzQXJyYXkodmFsSW5bbl0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih2YWxJbltuXS5sZW5ndGggPiB2YWxPdXRbbl0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgndW51c2VkJywgYmFzZSwgcC5jb25jYXQobiwgdmFsT3V0W25dLmxlbmd0aCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4yID0gdmFsT3V0W25dLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcihtID0gMDsgbSA8IChhcnJheUl0ZW1zID8gTWF0aC5taW4obGVuMiwgaXRlbXNbbl0ubGVuZ3RoKSA6IGxlbjIpOyBtKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtID0gYXJyYXlJdGVtcyA/IGl0ZW1zW25dW21dIDogaXRlbXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsSW5QYXJ0ID0gdmFsSW5bbl1bbV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsT3V0UGFydCA9IHZhbE91dFtuXVttXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighTGliLnZhbGlkYXRlKHZhbEluUGFydCwgaXRlbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgndmFsdWUnLCBiYXNlLCBwLmNvbmNhdChuLCBtKSwgdmFsSW5QYXJ0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYodmFsT3V0UGFydCAhPT0gdmFsSW5QYXJ0ICYmIHZhbE91dFBhcnQgIT09ICt2YWxJblBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnZHluYW1pYycsIGJhc2UsIHAuY29uY2F0KG4sIG0pLCB2YWxJblBhcnQsIHZhbE91dFBhcnQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCdhcnJheScsIGJhc2UsIHAuY29uY2F0KG4pLCB2YWxJbltuXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yKG4gPSAwOyBuIDwgbGVuOyBuKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaXRlbSA9IGFycmF5SXRlbXMgPyBpdGVtc1tuXSA6IGl0ZW1zO1xuICAgICAgICAgICAgICAgICAgICB2YWxJblBhcnQgPSB2YWxJbltuXTtcbiAgICAgICAgICAgICAgICAgICAgdmFsT3V0UGFydCA9IHZhbE91dFtuXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIUxpYi52YWxpZGF0ZSh2YWxJblBhcnQsIGl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd2YWx1ZScsIGJhc2UsIHAuY29uY2F0KG4pLCB2YWxJblBhcnQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKHZhbE91dFBhcnQgIT09IHZhbEluUGFydCAmJiB2YWxPdXRQYXJ0ICE9PSArdmFsSW5QYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCdkeW5hbWljJywgYmFzZSwgcC5jb25jYXQobiksIHZhbEluUGFydCwgdmFsT3V0UGFydCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYobmVzdGVkU2NoZW1hLml0ZW1zICYmICFpc0luZm9BcnJheSAmJiBpc0FycmF5KHZhbEluKSkge1xuICAgICAgICAgICAgdmFyIF9uZXN0ZWRTY2hlbWEgPSBpdGVtc1tPYmplY3Qua2V5cyhpdGVtcylbMF1dLFxuICAgICAgICAgICAgICAgIGluZGV4TGlzdCA9IFtdO1xuXG4gICAgICAgICAgICB2YXIgaiwgX3A7XG5cbiAgICAgICAgICAgIC8vIGxvb3Agb3ZlciB2YWxPdXQgaXRlbXMgd2hpbGUga2VlcGluZyB0cmFjayBvZiB0aGVpclxuICAgICAgICAgICAgLy8gY29ycmVzcG9uZGluZyBpbnB1dCBjb250YWluZXIgaW5kZXggKGdpdmVuIGJ5IF9pbmRleClcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHZhbE91dC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBfaW5kZXggPSB2YWxPdXRbal0uX2luZGV4IHx8IGo7XG5cbiAgICAgICAgICAgICAgICBfcCA9IHAuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICBfcC5wdXNoKF9pbmRleCk7XG5cbiAgICAgICAgICAgICAgICBpZihpc1BsYWluT2JqZWN0KHZhbEluW19pbmRleF0pICYmIGlzUGxhaW5PYmplY3QodmFsT3V0W2pdKSkge1xuICAgICAgICAgICAgICAgICAgICBpbmRleExpc3QucHVzaChfaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsSW5qID0gdmFsSW5bX2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbE91dGogPSB2YWxPdXRbal07XG4gICAgICAgICAgICAgICAgICAgIGlmKGlzUGxhaW5PYmplY3QodmFsSW5qKSAmJiB2YWxJbmoudmlzaWJsZSAhPT0gZmFsc2UgJiYgdmFsT3V0ai52aXNpYmxlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnaW52aXNpYmxlJywgYmFzZSwgX3ApKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGNyYXdsKHZhbEluaiwgdmFsT3V0aiwgX25lc3RlZFNjaGVtYSwgbGlzdCwgYmFzZSwgX3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gbG9vcCBvdmVyIHZhbEluIHRvIGRldGVybWluZSB3aGVyZSBpdCB3ZW50IHdyb25nIGZvciBzb21lIGl0ZW1zXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB2YWxJbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIF9wID0gcC5zbGljZSgpO1xuICAgICAgICAgICAgICAgIF9wLnB1c2goaik7XG5cbiAgICAgICAgICAgICAgICBpZighaXNQbGFpbk9iamVjdCh2YWxJbltqXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnb2JqZWN0JywgYmFzZSwgX3AsIHZhbEluW2pdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYoaW5kZXhMaXN0LmluZGV4T2YoaikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ3VudXNlZCcsIGJhc2UsIF9wKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoIWlzUGxhaW5PYmplY3QodmFsSW4pICYmIGlzUGxhaW5PYmplY3QodmFsT3V0KSkge1xuICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnb2JqZWN0JywgYmFzZSwgcCwgdmFsSW4pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KHZhbEluKSAmJiBpc0FycmF5T3JUeXBlZEFycmF5KHZhbE91dCkgJiYgIWlzSW5mb0FycmF5ICYmICFpc0NvbG9yc2NhbGUpIHtcbiAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ2FycmF5JywgYmFzZSwgcCwgdmFsSW4pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCEoayBpbiBvYmpPdXQpKSB7XG4gICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd1bnVzZWQnLCBiYXNlLCBwLCB2YWxJbikpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoIUxpYi52YWxpZGF0ZSh2YWxJbiwgbmVzdGVkU2NoZW1hKSkge1xuICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgndmFsdWUnLCBiYXNlLCBwLCB2YWxJbikpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYobmVzdGVkU2NoZW1hLnZhbFR5cGUgPT09ICdlbnVtZXJhdGVkJyAmJlxuICAgICAgICAgICAgKChuZXN0ZWRTY2hlbWEuY29lcmNlTnVtYmVyICYmIHZhbEluICE9PSArdmFsT3V0KSB8fCB2YWxJbiAhPT0gdmFsT3V0KVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ2R5bmFtaWMnLCBiYXNlLCBwLCB2YWxJbiwgdmFsT3V0KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdDtcbn1cblxuLy8gdGhlICdmdWxsJyBsYXlvdXQgc2NoZW1hIGRlcGVuZHMgb24gdGhlIHRyYWNlcyB0eXBlcyBwcmVzZW50c1xuZnVuY3Rpb24gZmlsbExheW91dFNjaGVtYShzY2hlbWEsIGRhdGFPdXQpIHtcbiAgICB2YXIgbGF5b3V0U2NoZW1hID0gc2NoZW1hLmxheW91dC5sYXlvdXRBdHRyaWJ1dGVzO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGRhdGFPdXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlT3V0ID0gZGF0YU91dFtpXTtcbiAgICAgICAgdmFyIHRyYWNlU2NoZW1hID0gc2NoZW1hLnRyYWNlc1t0cmFjZU91dC50eXBlXTtcbiAgICAgICAgdmFyIHRyYWNlTGF5b3V0QXR0ciA9IHRyYWNlU2NoZW1hLmxheW91dEF0dHJpYnV0ZXM7XG5cbiAgICAgICAgaWYodHJhY2VMYXlvdXRBdHRyKSB7XG4gICAgICAgICAgICBpZih0cmFjZU91dC5zdWJwbG90KSB7XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQobGF5b3V0U2NoZW1hW3RyYWNlU2NoZW1hLmF0dHJpYnV0ZXMuc3VicGxvdC5kZmx0XSwgdHJhY2VMYXlvdXRBdHRyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQobGF5b3V0U2NoZW1hLCB0cmFjZUxheW91dEF0dHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxheW91dFNjaGVtYTtcbn1cblxuLy8gdmFsaWRhdGlvbiBlcnJvciBjb2Rlc1xudmFyIGNvZGUybXNnRnVuYyA9IHtcbiAgICBvYmplY3Q6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgdmFyIHByZWZpeDtcblxuICAgICAgICBpZihiYXNlID09PSAnbGF5b3V0JyAmJiBhc3RyID09PSAnJykgcHJlZml4ID0gJ1RoZSBsYXlvdXQgYXJndW1lbnQnO1xuICAgICAgICBlbHNlIGlmKGJhc2VbMF0gPT09ICdkYXRhJyAmJiBhc3RyID09PSAnJykge1xuICAgICAgICAgICAgcHJlZml4ID0gJ1RyYWNlICcgKyBiYXNlWzFdICsgJyBpbiB0aGUgZGF0YSBhcmd1bWVudCc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBwcmVmaXggPSBpbkJhc2UoYmFzZSkgKyAna2V5ICcgKyBhc3RyO1xuXG4gICAgICAgIHJldHVybiBwcmVmaXggKyAnIG11c3QgYmUgbGlua2VkIHRvIGFuIG9iamVjdCBjb250YWluZXInO1xuICAgIH0sXG4gICAgYXJyYXk6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgdmFyIHByZWZpeDtcblxuICAgICAgICBpZihiYXNlID09PSAnZGF0YScpIHByZWZpeCA9ICdUaGUgZGF0YSBhcmd1bWVudCc7XG4gICAgICAgIGVsc2UgcHJlZml4ID0gaW5CYXNlKGJhc2UpICsgJ2tleSAnICsgYXN0cjtcblxuICAgICAgICByZXR1cm4gcHJlZml4ICsgJyBtdXN0IGJlIGxpbmtlZCB0byBhbiBhcnJheSBjb250YWluZXInO1xuICAgIH0sXG4gICAgc2NoZW1hOiBmdW5jdGlvbihiYXNlLCBhc3RyKSB7XG4gICAgICAgIHJldHVybiBpbkJhc2UoYmFzZSkgKyAna2V5ICcgKyBhc3RyICsgJyBpcyBub3QgcGFydCBvZiB0aGUgc2NoZW1hJztcbiAgICB9LFxuICAgIHVudXNlZDogZnVuY3Rpb24oYmFzZSwgYXN0ciwgdmFsSW4pIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGlzUGxhaW5PYmplY3QodmFsSW4pID8gJ2NvbnRhaW5lcicgOiAna2V5JztcblxuICAgICAgICByZXR1cm4gaW5CYXNlKGJhc2UpICsgdGFyZ2V0ICsgJyAnICsgYXN0ciArICcgZGlkIG5vdCBnZXQgY29lcmNlZCc7XG4gICAgfSxcbiAgICBkeW5hbWljOiBmdW5jdGlvbihiYXNlLCBhc3RyLCB2YWxJbiwgdmFsT3V0KSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBpbkJhc2UoYmFzZSkgKyAna2V5JyxcbiAgICAgICAgICAgIGFzdHIsXG4gICAgICAgICAgICAnKHNldCB0byBcXCcnICsgdmFsSW4gKyAnXFwnKScsXG4gICAgICAgICAgICAnZ290IHJlc2V0IHRvJyxcbiAgICAgICAgICAgICdcXCcnICsgdmFsT3V0ICsgJ1xcJycsXG4gICAgICAgICAgICAnZHVyaW5nIGRlZmF1bHRzLidcbiAgICAgICAgXS5qb2luKCcgJyk7XG4gICAgfSxcbiAgICBpbnZpc2libGU6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGFzdHIgPyAoaW5CYXNlKGJhc2UpICsgJ2l0ZW0gJyArIGFzdHIpIDogKCdUcmFjZSAnICsgYmFzZVsxXSlcbiAgICAgICAgKSArICcgZ290IGRlZmF1bHRlZCB0byBiZSBub3QgdmlzaWJsZSc7XG4gICAgfSxcbiAgICB2YWx1ZTogZnVuY3Rpb24oYmFzZSwgYXN0ciwgdmFsSW4pIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIGluQmFzZShiYXNlKSArICdrZXkgJyArIGFzdHIsXG4gICAgICAgICAgICAnaXMgc2V0IHRvIGFuIGludmFsaWQgdmFsdWUgKCcgKyB2YWxJbiArICcpJ1xuICAgICAgICBdLmpvaW4oJyAnKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpbkJhc2UoYmFzZSkge1xuICAgIGlmKGlzQXJyYXkoYmFzZSkpIHJldHVybiAnSW4gZGF0YSB0cmFjZSAnICsgYmFzZVsxXSArICcsICc7XG5cbiAgICByZXR1cm4gJ0luICcgKyBiYXNlICsgJywgJztcbn1cblxuZnVuY3Rpb24gZm9ybWF0KGNvZGUsIGJhc2UsIHBhdGgsIHZhbEluLCB2YWxPdXQpIHtcbiAgICBwYXRoID0gcGF0aCB8fCAnJztcblxuICAgIHZhciBjb250YWluZXIsIHRyYWNlO1xuXG4gICAgLy8gY29udGFpbmVyIGlzIGVpdGhlciAnZGF0YScgb3IgJ2xheW91dFxuICAgIC8vIHRyYWNlIGlzIHRoZSB0cmFjZSBpbmRleCBpZiAnZGF0YScsIG51bGwgb3RoZXJ3aXNlXG5cbiAgICBpZihpc0FycmF5KGJhc2UpKSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGJhc2VbMF07XG4gICAgICAgIHRyYWNlID0gYmFzZVsxXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGJhc2U7XG4gICAgICAgIHRyYWNlID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYXN0ciA9IGNvbnZlcnRQYXRoVG9BdHRyaWJ1dGVTdHJpbmcocGF0aCk7XG4gICAgdmFyIG1zZyA9IGNvZGUybXNnRnVuY1tjb2RlXShiYXNlLCBhc3RyLCB2YWxJbiwgdmFsT3V0KTtcblxuICAgIC8vIGxvZyB0byBjb25zb2xlIGlmIGxvZ2dlciBjb25maWcgb3B0aW9uIGlzIGVuYWJsZWRcbiAgICBMaWIubG9nKG1zZyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjb2RlOiBjb2RlLFxuICAgICAgICBjb250YWluZXI6IGNvbnRhaW5lcixcbiAgICAgICAgdHJhY2U6IHRyYWNlLFxuICAgICAgICBwYXRoOiBwYXRoLFxuICAgICAgICBhc3RyOiBhc3RyLFxuICAgICAgICBtc2c6IG1zZ1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGlzSW5TY2hlbWEoc2NoZW1hLCBrZXkpIHtcbiAgICB2YXIgcGFydHMgPSBzcGxpdEtleShrZXkpLFxuICAgICAgICBrZXlNaW51c0lkID0gcGFydHMua2V5TWludXNJZCxcbiAgICAgICAgaWQgPSBwYXJ0cy5pZDtcblxuICAgIGlmKChrZXlNaW51c0lkIGluIHNjaGVtYSkgJiYgc2NoZW1hW2tleU1pbnVzSWRdLl9pc1N1YnBsb3RPYmogJiYgaWQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIChrZXkgaW4gc2NoZW1hKTtcbn1cblxuZnVuY3Rpb24gZ2V0TmVzdGVkU2NoZW1hKHNjaGVtYSwga2V5KSB7XG4gICAgaWYoa2V5IGluIHNjaGVtYSkgcmV0dXJuIHNjaGVtYVtrZXldO1xuXG4gICAgdmFyIHBhcnRzID0gc3BsaXRLZXkoa2V5KTtcblxuICAgIHJldHVybiBzY2hlbWFbcGFydHMua2V5TWludXNJZF07XG59XG5cbnZhciBpZFJlZ2V4ID0gTGliLmNvdW50ZXJSZWdleCgnKFthLXpdKyknKTtcblxuZnVuY3Rpb24gc3BsaXRLZXkoa2V5KSB7XG4gICAgdmFyIGlkTWF0Y2ggPSBrZXkubWF0Y2goaWRSZWdleCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBrZXlNaW51c0lkOiBpZE1hdGNoICYmIGlkTWF0Y2hbMV0sXG4gICAgICAgIGlkOiBpZE1hdGNoICYmIGlkTWF0Y2hbMl1cbiAgICB9O1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0UGF0aFRvQXR0cmlidXRlU3RyaW5nKHBhdGgpIHtcbiAgICBpZighaXNBcnJheShwYXRoKSkgcmV0dXJuIFN0cmluZyhwYXRoKTtcblxuICAgIHZhciBhc3RyID0gJyc7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcCA9IHBhdGhbaV07XG5cbiAgICAgICAgaWYodHlwZW9mIHAgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBhc3RyID0gYXN0ci5zdWJzdHIoMCwgYXN0ci5sZW5ndGggLSAxKSArICdbJyArIHAgKyAnXSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhc3RyICs9IHA7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpIDwgcGF0aC5sZW5ndGggLSAxKSBhc3RyICs9ICcuJztcbiAgICB9XG5cbiAgICByZXR1cm4gYXN0cjtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIGRmbHQ6ICdhZnRlcmFsbCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnaW1tZWRpYXRlJywgJ25leHQnLCAnYWZ0ZXJhbGwnXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkaXJlY3Rpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2ZvcndhcmQnLCAncmV2ZXJzZSddLFxuICAgICAgICBkZmx0OiAnZm9yd2FyZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZnJvbWN1cnJlbnQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZnJhbWU6IHtcbiAgICAgICAgZHVyYXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiA1MDAsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcmVkcmF3OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICB9LFxuICAgIHRyYW5zaXRpb246IHtcbiAgICAgICAgZHVyYXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiA1MDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVhc2luZzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgZGZsdDogJ2N1YmljLWluLW91dCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICAgICAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICAncXVhZCcsXG4gICAgICAgICAgICAgICAgJ2N1YmljJyxcbiAgICAgICAgICAgICAgICAnc2luJyxcbiAgICAgICAgICAgICAgICAnZXhwJyxcbiAgICAgICAgICAgICAgICAnY2lyY2xlJyxcbiAgICAgICAgICAgICAgICAnZWxhc3RpYycsXG4gICAgICAgICAgICAgICAgJ2JhY2snLFxuICAgICAgICAgICAgICAgICdib3VuY2UnLFxuICAgICAgICAgICAgICAgICdsaW5lYXItaW4nLFxuICAgICAgICAgICAgICAgICdxdWFkLWluJyxcbiAgICAgICAgICAgICAgICAnY3ViaWMtaW4nLFxuICAgICAgICAgICAgICAgICdzaW4taW4nLFxuICAgICAgICAgICAgICAgICdleHAtaW4nLFxuICAgICAgICAgICAgICAgICdjaXJjbGUtaW4nLFxuICAgICAgICAgICAgICAgICdlbGFzdGljLWluJyxcbiAgICAgICAgICAgICAgICAnYmFjay1pbicsXG4gICAgICAgICAgICAgICAgJ2JvdW5jZS1pbicsXG4gICAgICAgICAgICAgICAgJ2xpbmVhci1vdXQnLFxuICAgICAgICAgICAgICAgICdxdWFkLW91dCcsXG4gICAgICAgICAgICAgICAgJ2N1YmljLW91dCcsXG4gICAgICAgICAgICAgICAgJ3Npbi1vdXQnLFxuICAgICAgICAgICAgICAgICdleHAtb3V0JyxcbiAgICAgICAgICAgICAgICAnY2lyY2xlLW91dCcsXG4gICAgICAgICAgICAgICAgJ2VsYXN0aWMtb3V0JyxcbiAgICAgICAgICAgICAgICAnYmFjay1vdXQnLFxuICAgICAgICAgICAgICAgICdib3VuY2Utb3V0JyxcbiAgICAgICAgICAgICAgICAnbGluZWFyLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ3F1YWQtaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnY3ViaWMtaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnc2luLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ2V4cC1pbi1vdXQnLFxuICAgICAgICAgICAgICAgICdjaXJjbGUtaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnZWxhc3RpYy1pbi1vdXQnLFxuICAgICAgICAgICAgICAgICdiYWNrLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ2JvdW5jZS1pbi1vdXQnXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIFRlbXBsYXRlID0gcmVxdWlyZSgnLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xuXG4vKiogQ29udmVuaWVuY2Ugd3JhcHBlciBmb3IgbWFraW5nIGFycmF5IGNvbnRhaW5lciBsb2dpYyBEUlkgYW5kIGNvbnNpc3RlbnRcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFyZW50T2JqSW5cbiAqICB1c2VyIGlucHV0IG9iamVjdCB3aGVyZSB0aGUgY29udGFpbmVyIGluIHF1ZXN0aW9uIGlzIGxpbmtlZFxuICogIChpLmUuIGVpdGhlciBhIHVzZXIgdHJhY2Ugb2JqZWN0IG9yIHRoZSB1c2VyIGxheW91dCBvYmplY3QpXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHBhcmVudE9iak91dFxuICogIGZ1bGwgb2JqZWN0IHdoZXJlIHRoZSBjb2VyY2VkIGNvbnRhaW5lciB3aWxsIGJlIGxpbmtlZFxuICogIChpLmUuIGVpdGhlciBhIGZ1bGwgdHJhY2Ugb2JqZWN0IG9yIHRoZSBmdWxsIGxheW91dCBvYmplY3QpXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqICBvcHRpb25zIG9iamVjdDpcbiAqICAgLSBuYW1lIHtzdHJpbmd9XG4gKiAgICAgIG5hbWUgb2YgdGhlIGtleSBsaW5raW5nIHRoZSBjb250YWluZXIgaW4gcXVlc3Rpb25cbiAqICAgLSBpbmNsdXNpb25BdHRyIHtzdHJpbmd9XG4gKiAgICAgIG5hbWUgb2YgdGhlIGl0ZW0gYXR0cmlidXRlIGZvciBpbmNsdXNpb24vZXhjbHVzaW9uLiBEZWZhdWx0IGlzICd2aXNpYmxlJy5cbiAqICAgICAgU2luY2UgaW5jbHVzaW9uIGlzIHRydWUsIHVzZSBlZyAnZW5hYmxlZCcgaW5zdGVhZCBvZiAnZGlzYWJsZWQnLlxuICogICAtIGhhbmRsZUl0ZW1EZWZhdWx0cyB7ZnVuY3Rpb259XG4gKiAgICAgIGRlZmF1bHRzIG1ldGhvZCB0byBiZSBjYWxsZWQgb24gZWFjaCBpdGVtIGluIHRoZSBhcnJheSBjb250YWluZXIgaW4gcXVlc3Rpb25cbiAqXG4gKiAgICAgIEl0cyBhcmd1bWVudHMgYXJlOlxuICogICAgICAgICAgLSBpdGVtSW4ge29iamVjdH0gaXRlbSBpbiB1c2VyIGxheW91dFxuICogICAgICAgICAgLSBpdGVtT3V0IHtvYmplY3R9IGl0ZW0gaW4gZnVsbCBsYXlvdXRcbiAqICAgICAgICAgIC0gcGFyZW50T2JqIHtvYmplY3R9IChhcyBpbiBjbG9zdXJlKVxuICogICAgICAgICAgLSBvcHRzIHtvYmplY3R9IChhcyBpbiBjbG9zdXJlKVxuICogTi5CLlxuICpcbiAqICAtIG9wdHMgaXMgcGFzc2VkIHRvIGhhbmRsZUl0ZW1EZWZhdWx0cyBzbyBpdCBjYW4gYWxzbyBzdG9yZVxuICogICAgbGlua3MgdG8gc3VwcGxlbWVudGFyeSBkYXRhIChlLmcuIGZ1bGxEYXRhIGZvciBsYXlvdXQgY29tcG9uZW50cylcbiAqXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhwYXJlbnRPYmpJbiwgcGFyZW50T2JqT3V0LCBvcHRzKSB7XG4gICAgdmFyIG5hbWUgPSBvcHRzLm5hbWU7XG4gICAgdmFyIGluY2x1c2lvbkF0dHIgPSBvcHRzLmluY2x1c2lvbkF0dHIgfHwgJ3Zpc2libGUnO1xuXG4gICAgdmFyIHByZXZpb3VzQ29udE91dCA9IHBhcmVudE9iak91dFtuYW1lXTtcblxuICAgIHZhciBjb250SW4gPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShwYXJlbnRPYmpJbltuYW1lXSkgPyBwYXJlbnRPYmpJbltuYW1lXSA6IFtdO1xuICAgIHZhciBjb250T3V0ID0gcGFyZW50T2JqT3V0W25hbWVdID0gW107XG4gICAgdmFyIHRlbXBsYXRlciA9IFRlbXBsYXRlLmFycmF5VGVtcGxhdGVyKHBhcmVudE9iak91dCwgbmFtZSwgaW5jbHVzaW9uQXR0cik7XG4gICAgdmFyIGksIGl0ZW1PdXQ7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjb250SW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGl0ZW1JbiA9IGNvbnRJbltpXTtcblxuICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QoaXRlbUluKSkge1xuICAgICAgICAgICAgaXRlbU91dCA9IHRlbXBsYXRlci5uZXdJdGVtKHt9KTtcbiAgICAgICAgICAgIGl0ZW1PdXRbaW5jbHVzaW9uQXR0cl0gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGl0ZW1PdXQgPSB0ZW1wbGF0ZXIubmV3SXRlbShpdGVtSW4pO1xuICAgICAgICB9XG5cbiAgICAgICAgaXRlbU91dC5faW5kZXggPSBpO1xuXG4gICAgICAgIGlmKGl0ZW1PdXRbaW5jbHVzaW9uQXR0cl0gIT09IGZhbHNlKSB7XG4gICAgICAgICAgICBvcHRzLmhhbmRsZUl0ZW1EZWZhdWx0cyhpdGVtSW4sIGl0ZW1PdXQsIHBhcmVudE9iak91dCwgb3B0cyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250T3V0LnB1c2goaXRlbU91dCk7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRJdGVtcyA9IHRlbXBsYXRlci5kZWZhdWx0SXRlbXMoKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBkZWZhdWx0SXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlbU91dCA9IGRlZmF1bHRJdGVtc1tpXTtcbiAgICAgICAgaXRlbU91dC5faW5kZXggPSBjb250T3V0Lmxlbmd0aDtcbiAgICAgICAgb3B0cy5oYW5kbGVJdGVtRGVmYXVsdHMoe30sIGl0ZW1PdXQsIHBhcmVudE9iak91dCwgb3B0cywge30pO1xuICAgICAgICBjb250T3V0LnB1c2goaXRlbU91dCk7XG4gICAgfVxuXG4gICAgLy8gaW4gY2FzZSB0aGlzIGFycmF5IGdldHMgaXRzIGRlZmF1bHRzIHJlYnVpbHQgaW5kZXBlbmRlbnQgb2YgdGhlIHdob2xlIGxheW91dCxcbiAgICAvLyByZWxpbmsgdGhlIHByaXZhdGUga2V5cyBqdXN0IGZvciB0aGlzIGFycmF5LlxuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHByZXZpb3VzQ29udE91dCkpIHtcbiAgICAgICAgdmFyIGxlbiA9IE1hdGgubWluKHByZXZpb3VzQ29udE91dC5sZW5ndGgsIGNvbnRPdXQubGVuZ3RoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIExpYi5yZWxpbmtQcml2YXRlS2V5cyhjb250T3V0W2ldLCBwcmV2aW91c0NvbnRPdXRbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRPdXQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZnhBdHRycyA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvZngvYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogW10sICAgICAvLyBsaXN0ZWQgZHluYW1pY2FsbHlcbiAgICAgICAgZGZsdDogJ3NjYXR0ZXInLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBfbm9UZW1wbGF0aW5nOiB0cnVlIC8vIHdlIGhhbmRsZSB0aGlzIGF0IGEgaGlnaGVyIGxldmVsXG4gICAgfSxcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbdHJ1ZSwgZmFsc2UsICdsZWdlbmRvbmx5J10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dsZWdlbmQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGVnZW5kZ3JvdXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBuYW1lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdWlkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG4gICAgaWRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjdXN0b21kYXRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIE4uQi4gdGhlc2UgY2Fubm90IGJlICdkYXRhX2FycmF5JyBhcyB0aGV5IGRvIG5vdCBoYXZlIHRoZSBzYW1lIGxlbmd0aCBhc1xuICAgIC8vIG90aGVyIGRhdGEgYXJyYXlzIGFuZCBhcnJheU9rIGF0dHJpYnV0ZXMgaW4gZ2VuZXJhbFxuICAgIC8vXG4gICAgLy8gTWF5YmUgYWRkIGFub3RoZXIgdmFsVHlwZTpcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTg5NFxuICAgIHNlbGVjdGVkcG9pbnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBcbiAgICAgICAgZmxhZ3M6IFsneCcsICd5JywgJ3onLCAndGV4dCcsICduYW1lJ10sXG4gICAgICAgIGV4dHJhczogWydhbGwnLCAnbm9uZScsICdza2lwJ10sXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVybGFiZWw6IGZ4QXR0cnMuaG92ZXJsYWJlbCxcbiAgICBzdHJlYW06IHtcbiAgICAgICAgdG9rZW46IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgbm9CbGFuazogdHJ1ZSxcbiAgICAgICAgICAgIHN0cmljdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBtYXhwb2ludHM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxMDAwMCxcbiAgICAgICAgICAgIGRmbHQ6IDUwMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICB0cmFuc2Zvcm1zOiB7XG4gICAgICAgIF9pc0xpbmtlZFRvQXJyYXk6ICd0cmFuc2Zvcm0nLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHhheGlzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3gnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlheGlzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3knLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEZQX1NBRkUgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuRlBfU0FGRTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZ2V0QXV0b1JhbmdlOiBnZXRBdXRvUmFuZ2UsXG4gICAgbWFrZVBhZEZuOiBtYWtlUGFkRm4sXG4gICAgZG9BdXRvUmFuZ2U6IGRvQXV0b1JhbmdlLFxuICAgIGZpbmRFeHRyZW1lczogZmluZEV4dHJlbWVzLFxuICAgIGNvbmNhdEV4dHJlbWVzOiBjb25jYXRFeHRyZW1lc1xufTtcblxuLyoqXG4gKiBnZXRBdXRvUmFuZ2VcbiAqXG4gKiBDb2xsZWN0cyBhbGwgX2V4dHJlbWVzIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIGEgZ2l2ZW4gYXhpc1xuICogYW5kIGNvbXB1dGVzIGl0cyBhdXRvIHJhbmdlLlxuICpcbiAqIE5vdGUgdGhhdCBnZXRBdXRvUmFuZ2UgdXNlcyByZXR1cm4gdmFsdWVzIGZyb20gZmluZEV4dHJlbWVzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBnZDpcbiAqICAgZ3JhcGggZGl2IG9iamVjdCB3aXRoIGZpbGxlZC1pbiBmdWxsRGF0YSBhbmQgZnVsbExheW91dCwgaW4gcGFydGljdWxhclxuICogICB3aXRoIGZpbGxlZC1pbiAnX2V4dHJlbWVzJyBjb250YWluZXJzOlxuICogICB7XG4gKiAgICAgIHZhbDogY2FsY2RhdGEgdmFsdWUsXG4gKiAgICAgIHBhZDogZXh0cmEgcGl4ZWxzIGJleW9uZCB0aGlzIHZhbHVlLFxuICogICAgICBleHRyYXBhZDogYm9vbCwgZG9lcyB0aGlzIHBvaW50IHdhbnQgNSUgZXh0cmEgcGFkZGluZ1xuICogICB9XG4gKiBAcGFyYW0ge29iamVjdH0gYXg6XG4gKiAgIGZ1bGwgYXhpcyBvYmplY3QsIGluIHBhcnRpY3VsYXIgd2l0aCBmaWxsZWQtaW4gJ190cmFjZUluZGljZXMnXG4gKiAgIGFuZCAnX2FubkluZGljZXMnIC8gJ19zaGFwZUluZGljZXMnIGlmIGFwcGxpY2FibGVcbiAqIEByZXR1cm4ge2FycmF5fVxuICogICBhbiBhcnJheSBvZiBbbWluLCBtYXhdLiBUaGVzZSBhcmUgY2FsY2RhdGEgZm9yIGxvZyBhbmQgY2F0ZWdvcnkgYXhlc1xuICogICBhbmQgZGF0YSBmb3IgbGluZWFyIGFuZCBkYXRlIGF4ZXMuXG4gKlxuICogVE9ETzogd2Ugd2FudCB0byBjaGFuZ2UgbG9nIHRvIGRhdGEgYXMgd2VsbCwgYnV0IGl0J3MgaGFyZCB0byBkbyB0aGlzXG4gKiBtYWludGFpbmluZyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBjYXRlZ29yeSB3aWxsIGFsd2F5cyBoYXZlIHRvIHVzZSBjYWxjZGF0YVxuICogdGhvdWdoLCBiZWNhdXNlIG90aGVyd2lzZSB2YWx1ZXMgYmV0d2VlbiBjYXRlZ29yaWVzIChvciBvdXRzaWRlIGFsbCBjYXRlZ29yaWVzKVxuICogd291bGQgYmUgaW1wb3NzaWJsZS5cbiAqL1xuZnVuY3Rpb24gZ2V0QXV0b1JhbmdlKGdkLCBheCkge1xuICAgIHZhciBpLCBqO1xuICAgIHZhciBuZXdSYW5nZSA9IFtdO1xuXG4gICAgdmFyIGdldFBhZCA9IG1ha2VQYWRGbihheCk7XG4gICAgdmFyIGV4dHJlbWVzID0gY29uY2F0RXh0cmVtZXMoZ2QsIGF4KTtcbiAgICB2YXIgbWluQXJyYXkgPSBleHRyZW1lcy5taW47XG4gICAgdmFyIG1heEFycmF5ID0gZXh0cmVtZXMubWF4O1xuXG4gICAgaWYobWluQXJyYXkubGVuZ3RoID09PSAwIHx8IG1heEFycmF5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcbiAgICB9XG5cbiAgICB2YXIgbWlubWluID0gbWluQXJyYXlbMF0udmFsO1xuICAgIHZhciBtYXhtYXggPSBtYXhBcnJheVswXS52YWw7XG5cbiAgICBmb3IoaSA9IDE7IGkgPCBtaW5BcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihtaW5taW4gIT09IG1heG1heCkgYnJlYWs7XG4gICAgICAgIG1pbm1pbiA9IE1hdGgubWluKG1pbm1pbiwgbWluQXJyYXlbaV0udmFsKTtcbiAgICB9XG4gICAgZm9yKGkgPSAxOyBpIDwgbWF4QXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYobWlubWluICE9PSBtYXhtYXgpIGJyZWFrO1xuICAgICAgICBtYXhtYXggPSBNYXRoLm1heChtYXhtYXgsIG1heEFycmF5W2ldLnZhbCk7XG4gICAgfVxuXG4gICAgdmFyIGF4UmV2ZXJzZSA9IGZhbHNlO1xuXG4gICAgaWYoYXgucmFuZ2UpIHtcbiAgICAgICAgdmFyIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG4gICAgICAgIGF4UmV2ZXJzZSA9IHJuZ1sxXSA8IHJuZ1swXTtcbiAgICB9XG4gICAgLy8gb25lLXRpbWUgc2V0dGluZyB0byBlYXNpbHkgcmV2ZXJzZSB0aGUgYXhpc1xuICAgIC8vIHdoZW4gcGxvdHRpbmcgZnJvbSBjb2RlXG4gICAgaWYoYXguYXV0b3JhbmdlID09PSAncmV2ZXJzZWQnKSB7XG4gICAgICAgIGF4UmV2ZXJzZSA9IHRydWU7XG4gICAgICAgIGF4LmF1dG9yYW5nZSA9IHRydWU7XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlTW9kZSA9IGF4LnJhbmdlbW9kZTtcbiAgICB2YXIgdG9aZXJvID0gcmFuZ2VNb2RlID09PSAndG96ZXJvJztcbiAgICB2YXIgbm9uTmVnYXRpdmUgPSByYW5nZU1vZGUgPT09ICdub25uZWdhdGl2ZSc7XG4gICAgdmFyIGF4TGVuID0gYXguX2xlbmd0aDtcbiAgICAvLyBkb24ndCBhbGxvdyBwYWRkaW5nIHRvIHJlZHVjZSB0aGUgZGF0YSB0byA8IDEwJSBvZiB0aGUgbGVuZ3RoXG4gICAgdmFyIG1pblNwYW4gPSBheExlbiAvIDEwO1xuXG4gICAgdmFyIG1iZXN0ID0gMDtcbiAgICB2YXIgbWlucHQsIG1heHB0LCBtaW5iZXN0LCBtYXhiZXN0LCBkcCwgZHY7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBtaW5BcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBtaW5wdCA9IG1pbkFycmF5W2ldO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBtYXhBcnJheS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgbWF4cHQgPSBtYXhBcnJheVtqXTtcbiAgICAgICAgICAgIGR2ID0gbWF4cHQudmFsIC0gbWlucHQudmFsO1xuICAgICAgICAgICAgaWYoZHYgPiAwKSB7XG4gICAgICAgICAgICAgICAgZHAgPSBheExlbiAtIGdldFBhZChtaW5wdCkgLSBnZXRQYWQobWF4cHQpO1xuICAgICAgICAgICAgICAgIGlmKGRwID4gbWluU3Bhbikge1xuICAgICAgICAgICAgICAgICAgICBpZihkdiAvIGRwID4gbWJlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbmJlc3QgPSBtaW5wdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heGJlc3QgPSBtYXhwdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1iZXN0ID0gZHYgLyBkcDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKGR2IC8gYXhMZW4gPiBtYmVzdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIG9mIHBhZGRpbmcgbG9uZ2VyIHRoYW4gdGhlIGF4aXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYXQgbGVhc3QgaW5jbHVkZSB0aGUgdW5wYWRkZWQgZGF0YSB2YWx1ZXMuXG4gICAgICAgICAgICAgICAgICAgIG1pbmJlc3QgPSB7dmFsOiBtaW5wdC52YWwsIHBhZDogMH07XG4gICAgICAgICAgICAgICAgICAgIG1heGJlc3QgPSB7dmFsOiBtYXhwdC52YWwsIHBhZDogMH07XG4gICAgICAgICAgICAgICAgICAgIG1iZXN0ID0gZHYgLyBheExlbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRNYXhQYWQocHJldiwgcHQpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHByZXYsIGdldFBhZChwdCkpO1xuICAgIH1cblxuICAgIGlmKG1pbm1pbiA9PT0gbWF4bWF4KSB7XG4gICAgICAgIHZhciBsb3dlciA9IG1pbm1pbiAtIDE7XG4gICAgICAgIHZhciB1cHBlciA9IG1pbm1pbiArIDE7XG4gICAgICAgIGlmKHRvWmVybykge1xuICAgICAgICAgICAgaWYobWlubWluID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIG9ubHkgdmFsdWUgd2UgaGF2ZSBvbiB0aGlzIGF4aXMgaXMgMCwgYW5kIHdlIHdhbnQgdG9cbiAgICAgICAgICAgICAgICAvLyBhdXRvcmFuZ2Ugc28gemVybyBpcyBvbmUgZW5kLlxuICAgICAgICAgICAgICAgIC8vIEluIHByaW5jaXBsZSB0aGlzIGNvdWxkIGJlIFswLCAxXSBvciBbLTEsIDBdIGJ1dCB1c3VhbGx5XG4gICAgICAgICAgICAgICAgLy8gJ3RvemVybycgcGlucyAwIHRvIHRoZSBsb3cgZW5kLCBzbyBmb2xsb3cgdGhhdC5cbiAgICAgICAgICAgICAgICBuZXdSYW5nZSA9IFswLCAxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtYXhQYWQgPSAobWlubWluID4gMCA/IG1heEFycmF5IDogbWluQXJyYXkpLnJlZHVjZShnZXRNYXhQYWQsIDApO1xuICAgICAgICAgICAgICAgIC8vIHdlJ3JlIHB1c2hpbmcgYSBzaW5nbGUgdmFsdWUgYXdheSBmcm9tIHRoZSBlZGdlIGR1ZSB0byBpdHNcbiAgICAgICAgICAgICAgICAvLyBwYWRkaW5nLCB3aXRoIHRoZSBvdGhlciBlbmQgY2xhbXBlZCBhdCB6ZXJvXG4gICAgICAgICAgICAgICAgLy8gMC41IG1lYW5zIGRvbid0IHB1c2ggaXQgZmFydGhlciB0aGFuIHRoZSBjZW50ZXIuXG4gICAgICAgICAgICAgICAgdmFyIHJhbmdlRW5kID0gbWlubWluIC8gKDEgLSBNYXRoLm1pbigwLjUsIG1heFBhZCAvIGF4TGVuKSk7XG4gICAgICAgICAgICAgICAgbmV3UmFuZ2UgPSBtaW5taW4gPiAwID8gWzAsIHJhbmdlRW5kXSA6IFtyYW5nZUVuZCwgMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihub25OZWdhdGl2ZSkge1xuICAgICAgICAgICAgbmV3UmFuZ2UgPSBbTWF0aC5tYXgoMCwgbG93ZXIpLCBNYXRoLm1heCgxLCB1cHBlcildO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3UmFuZ2UgPSBbbG93ZXIsIHVwcGVyXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYodG9aZXJvKSB7XG4gICAgICAgICAgICBpZihtaW5iZXN0LnZhbCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgbWluYmVzdCA9IHt2YWw6IDAsIHBhZDogMH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihtYXhiZXN0LnZhbCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgbWF4YmVzdCA9IHt2YWw6IDAsIHBhZDogMH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihub25OZWdhdGl2ZSkge1xuICAgICAgICAgICAgaWYobWluYmVzdC52YWwgLSBtYmVzdCAqIGdldFBhZChtaW5iZXN0KSA8IDApIHtcbiAgICAgICAgICAgICAgICBtaW5iZXN0ID0ge3ZhbDogMCwgcGFkOiAwfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKG1heGJlc3QudmFsIDw9IDApIHtcbiAgICAgICAgICAgICAgICBtYXhiZXN0ID0ge3ZhbDogMSwgcGFkOiAwfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGluIGNhc2UgaXQgY2hhbmdlZCBhZ2Fpbi4uLlxuICAgICAgICBtYmVzdCA9IChtYXhiZXN0LnZhbCAtIG1pbmJlc3QudmFsKSAvXG4gICAgICAgICAgICAoYXhMZW4gLSBnZXRQYWQobWluYmVzdCkgLSBnZXRQYWQobWF4YmVzdCkpO1xuXG4gICAgICAgIG5ld1JhbmdlID0gW1xuICAgICAgICAgICAgbWluYmVzdC52YWwgLSBtYmVzdCAqIGdldFBhZChtaW5iZXN0KSxcbiAgICAgICAgICAgIG1heGJlc3QudmFsICsgbWJlc3QgKiBnZXRQYWQobWF4YmVzdClcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICAvLyBtYWludGFpbiByZXZlcnNhbFxuICAgIGlmKGF4UmV2ZXJzZSkgbmV3UmFuZ2UucmV2ZXJzZSgpO1xuXG4gICAgcmV0dXJuIExpYi5zaW1wbGVNYXAobmV3UmFuZ2UsIGF4LmwyciB8fCBOdW1iZXIpO1xufVxuXG4vKlxuICogY2FsY3VsYXRlIHRoZSBwaXhlbCBwYWRkaW5nIGZvciBheC5fbWluIGFuZCBheC5fbWF4IGVudHJpZXMgd2l0aFxuICogb3B0aW9uYWwgZXh0cmFwYWQgYXMgNSUgb2YgdGhlIHRvdGFsIGF4aXMgbGVuZ3RoXG4gKi9cbmZ1bmN0aW9uIG1ha2VQYWRGbihheCkge1xuICAgIC8vIDUlIHBhZGRpbmcgZm9yIHBvaW50cyB0aGF0IHNwZWNpZnkgZXh0cmFwYWQ6IHRydWVcbiAgICB2YXIgZXh0cmFwcGFkID0gYXguX2xlbmd0aCAvIDIwO1xuXG4gICAgLy8gZG9tYWluLWNvbnN0cmFpbmVkIGF4ZXM6IGJhc2UgZXh0cmFwcGFkIG9uIHRoZSB1bmNvbnN0cmFpbmVkXG4gICAgLy8gZG9tYWluIHNvIGl0J3MgY29uc2lzdGVudCBhcyB0aGUgZG9tYWluIGNoYW5nZXNcbiAgICBpZigoYXguY29uc3RyYWluID09PSAnZG9tYWluJykgJiYgYXguX2lucHV0RG9tYWluKSB7XG4gICAgICAgIGV4dHJhcHBhZCAqPSAoYXguX2lucHV0RG9tYWluWzFdIC0gYXguX2lucHV0RG9tYWluWzBdKSAvXG4gICAgICAgICAgICAoYXguZG9tYWluWzFdIC0gYXguZG9tYWluWzBdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gZ2V0UGFkKHB0KSB7IHJldHVybiBwdC5wYWQgKyAocHQuZXh0cmFwYWQgPyBleHRyYXBwYWQgOiAwKTsgfTtcbn1cblxuZnVuY3Rpb24gY29uY2F0RXh0cmVtZXMoZ2QsIGF4KSB7XG4gICAgdmFyIGF4SWQgPSBheC5faWQ7XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG1pbkFycmF5ID0gW107XG4gICAgdmFyIG1heEFycmF5ID0gW107XG4gICAgdmFyIGksIGosIGQ7XG5cbiAgICBmdW5jdGlvbiBfY29uY2F0KGNvbnQsIGluZGljZXMpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSBjb250W2luZGljZXNbaV1dO1xuICAgICAgICAgICAgdmFyIGV4dHJlbWVzID0gKGl0ZW0uX2V4dHJlbWVzIHx8IHt9KVtheElkXTtcbiAgICAgICAgICAgIGlmKGl0ZW0udmlzaWJsZSA9PT0gdHJ1ZSAmJiBleHRyZW1lcykge1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGV4dHJlbWVzLm1pbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBkID0gZXh0cmVtZXMubWluW2pdO1xuICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZU1pbkFycmF5KG1pbkFycmF5LCBkLnZhbCwgZC5wYWQsIHtleHRyYXBhZDogZC5leHRyYXBhZH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBleHRyZW1lcy5tYXgubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZCA9IGV4dHJlbWVzLm1heFtqXTtcbiAgICAgICAgICAgICAgICAgICAgY29sbGFwc2VNYXhBcnJheShtYXhBcnJheSwgZC52YWwsIGQucGFkLCB7ZXh0cmFwYWQ6IGQuZXh0cmFwYWR9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfY29uY2F0KGZ1bGxEYXRhLCBheC5fdHJhY2VJbmRpY2VzKTtcbiAgICBfY29uY2F0KGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnMgfHwgW10sIGF4Ll9hbm5JbmRpY2VzIHx8IFtdKTtcbiAgICBfY29uY2F0KGZ1bGxMYXlvdXQuc2hhcGVzIHx8IFtdLCBheC5fc2hhcGVJbmRpY2VzIHx8IFtdKTtcblxuICAgIHJldHVybiB7bWluOiBtaW5BcnJheSwgbWF4OiBtYXhBcnJheX07XG59XG5cbmZ1bmN0aW9uIGRvQXV0b1JhbmdlKGdkLCBheCkge1xuICAgIGlmKCFheC5fbGVuZ3RoKSBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIGF4SW47XG5cbiAgICBpZihheC5hdXRvcmFuZ2UpIHtcbiAgICAgICAgYXgucmFuZ2UgPSBnZXRBdXRvUmFuZ2UoZ2QsIGF4KTtcblxuICAgICAgICBheC5fciA9IGF4LnJhbmdlLnNsaWNlKCk7XG4gICAgICAgIGF4Ll9ybCA9IExpYi5zaW1wbGVNYXAoYXguX3IsIGF4LnIybCk7XG5cbiAgICAgICAgLy8gZG9BdXRvUmFuZ2Ugd2lsbCBnZXQgY2FsbGVkIG9uIGZ1bGxMYXlvdXQsXG4gICAgICAgIC8vIGJ1dCB3ZSB3YW50IHRvIHJlcG9ydCBpdHMgcmVzdWx0cyBiYWNrIHRvIGxheW91dFxuXG4gICAgICAgIGF4SW4gPSBheC5faW5wdXQ7XG4gICAgICAgIGF4SW4ucmFuZ2UgPSBheC5yYW5nZS5zbGljZSgpO1xuICAgICAgICBheEluLmF1dG9yYW5nZSA9IGF4LmF1dG9yYW5nZTtcbiAgICB9XG5cbiAgICBpZihheC5fYW5jaG9yQXhpcyAmJiBheC5fYW5jaG9yQXhpcy5yYW5nZXNsaWRlcikge1xuICAgICAgICB2YXIgYXhlUmFuZ2VPcHRzID0gYXguX2FuY2hvckF4aXMucmFuZ2VzbGlkZXJbYXguX25hbWVdO1xuICAgICAgICBpZihheGVSYW5nZU9wdHMpIHtcbiAgICAgICAgICAgIGlmKGF4ZVJhbmdlT3B0cy5yYW5nZW1vZGUgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgICAgIGF4ZVJhbmdlT3B0cy5yYW5nZSA9IGdldEF1dG9SYW5nZShnZCwgYXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGF4SW4gPSBheC5fYW5jaG9yQXhpcy5faW5wdXQ7XG4gICAgICAgIGF4SW4ucmFuZ2VzbGlkZXJbYXguX25hbWVdID0gTGliLmV4dGVuZEZsYXQoe30sIGF4ZVJhbmdlT3B0cyk7XG4gICAgfVxufVxuXG4vKipcbiAqIGZpbmRFeHRyZW1lc1xuICpcbiAqIEZpbmQgbWluL21heCBleHRyZW1lcyBvZiBhbiBhcnJheSBvZiBjb29yZGluYXRlcyBvbiBhIGdpdmVuIGF4aXMuXG4gKlxuICogTm90ZSB0aGF0IGZpbmRFeHRyZW1lcyBpcyBjYWxsZWQgZHVyaW5nIGBjYWxjYCwgd2hlbiB3ZSBkb24ndCB5ZXQga25vdyB0aGUgYXhpc1xuICogbGVuZ3RoOyBhbGwgdGhlIGlucHV0cyBzaG91bGQgYmUgYmFzZWQgc29sZWx5IG9uIHRoZSB0cmFjZSBkYXRhLCBub3RoaW5nXG4gKiBhYm91dCB0aGUgYXhpcyBsYXlvdXQuXG4gKlxuICogTm90ZSB0aGF0IGBwcGFkYCBhbmQgYHZwYWRgIGFzIHdlbGwgYXMgdGhlaXIgYXN5bW1ldHJpYyB2YXJpYW50cyByZWZlciB0b1xuICogdGhlIGJlZm9yZSBhbmQgYWZ0ZXIgcGFkZGluZyBvZiB0aGUgcGFzc2VkIGBkYXRhYCBhcnJheSwgbm90IHRvIHRoZSB3aG9sZSBheGlzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBheDogZnVsbCBheGlzIG9iamVjdFxuICogICByZWxpZXMgb25cbiAqICAgLSBheC50eXBlXG4gKiAgIC0gYXguX20gKGp1c3QgaXRzIHNpZ24pXG4gKiAgIC0gYXguZDJsXG4gKiBAcGFyYW0ge2FycmF5fSBkYXRhOlxuICogIGFycmF5IG9mIG51bWJlcnMgKGkuZS4gYWxyZWFkeSBydW4gdGhvdWdoIGF4LmQyYylcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zOlxuICogIGF2YWlsYWJsZSBrZXlzIGFyZTpcbiAqICAgICAgdnBhZDogKG51bWJlciBvciBudW1iZXIgYXJyYXkpIHBhZCB2YWx1ZXMgKGRhdGEgdmFsdWUgKy12cGFkKVxuICogICAgICBwcGFkOiAobnVtYmVyIG9yIG51bWJlciBhcnJheSkgcGFkIHBpeGVscyAocGl4ZWwgbG9jYXRpb24gKy1wcGFkKVxuICogICAgICBwcGFkcGx1cywgcHBhZG1pbnVzLCB2cGFkcGx1cywgdnBhZG1pbnVzOlxuICogICAgICAgICAgc2VwYXJhdGUgcGFkZGluZyBmb3IgZWFjaCBzaWRlLCBvdmVycmlkZXMgc3ltbWV0cmljXG4gKiAgICAgIHBhZGRlZDogKGJvb2xlYW4pIGFkZCA1JSBwYWRkaW5nIHRvIGJvdGggZW5kc1xuICogICAgICAgICAgKHVubGVzcyBvbmUgZW5kIGlzIG92ZXJyaWRkZW4gYnkgdG96ZXJvKVxuICogICAgICB0b3plcm86IChib29sZWFuKSBtYWtlIHN1cmUgdG8gaW5jbHVkZSB6ZXJvIGlmIGF4aXMgaXMgbGluZWFyLFxuICogICAgICAgICAgYW5kIG1ha2UgaXQgYSB0aWdodCBib3VuZCBpZiBwb3NzaWJsZVxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICAtIG1pbiB7YXJyYXkgb2Ygb2JqZWN0c31cbiAqICAtIG1heCB7YXJyYXkgb2Ygb2JqZWN0c31cbiAqICBlYWNoIG9iamVjdCBpdGVtIGhhcyBmaWVsZHM6XG4gKiAgICAtIHZhbCB7bnVtYmVyfVxuICogICAgLSBwYWQge251bWJlcn1cbiAqICAgIC0gZXh0cmFwcGFkIHtudW1iZXJ9XG4gKi9cbmZ1bmN0aW9uIGZpbmRFeHRyZW1lcyhheCwgZGF0YSwgb3B0aW9ucykge1xuICAgIGlmKCFvcHRpb25zKSBvcHRpb25zID0ge307XG4gICAgaWYoIWF4Ll9tKSBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIG1pbkFycmF5ID0gW107XG4gICAgdmFyIG1heEFycmF5ID0gW107XG5cbiAgICB2YXIgbGVuID0gZGF0YS5sZW5ndGg7XG4gICAgdmFyIGV4dHJhcGFkID0gb3B0aW9ucy5wYWRkZWQgfHwgZmFsc2U7XG4gICAgdmFyIHRvemVybyA9IG9wdGlvbnMudG96ZXJvICYmIChheC50eXBlID09PSAnbGluZWFyJyB8fCBheC50eXBlID09PSAnLScpO1xuICAgIHZhciBpc0xvZyA9IGF4LnR5cGUgPT09ICdsb2cnO1xuICAgIHZhciBoYXNBcnJheU9wdGlvbiA9IGZhbHNlO1xuICAgIHZhciBpLCB2LCBkaSwgZG1pbiwgZG1heCwgcHBhZGlwbHVzLCBwcGFkaW1pbnVzLCB2bWluLCB2bWF4O1xuXG4gICAgZnVuY3Rpb24gbWFrZVBhZEFjY2Vzc29yKGl0ZW0pIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShpdGVtKSkge1xuICAgICAgICAgICAgaGFzQXJyYXlPcHRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGkpIHsgcmV0dXJuIE1hdGgubWF4KE51bWJlcihpdGVtW2ldfHwwKSwgMCk7IH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KE51bWJlcihpdGVtfHwwKSwgMCk7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiB2OyB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBwYWRwbHVzID0gbWFrZVBhZEFjY2Vzc29yKChheC5fbSA+IDAgP1xuICAgICAgICBvcHRpb25zLnBwYWRwbHVzIDogb3B0aW9ucy5wcGFkbWludXMpIHx8IG9wdGlvbnMucHBhZCB8fCAwKTtcbiAgICB2YXIgcHBhZG1pbnVzID0gbWFrZVBhZEFjY2Vzc29yKChheC5fbSA+IDAgP1xuICAgICAgICBvcHRpb25zLnBwYWRtaW51cyA6IG9wdGlvbnMucHBhZHBsdXMpIHx8IG9wdGlvbnMucHBhZCB8fCAwKTtcbiAgICB2YXIgdnBhZHBsdXMgPSBtYWtlUGFkQWNjZXNzb3Iob3B0aW9ucy52cGFkcGx1cyB8fCBvcHRpb25zLnZwYWQpO1xuICAgIHZhciB2cGFkbWludXMgPSBtYWtlUGFkQWNjZXNzb3Iob3B0aW9ucy52cGFkbWludXMgfHwgb3B0aW9ucy52cGFkKTtcblxuICAgIGlmKCFoYXNBcnJheU9wdGlvbikge1xuICAgICAgICAvLyB3aXRoIG5vIGFycmF5cyBvdGhlciB0aGFuIGBkYXRhYCB3ZSBkb24ndCBuZWVkIHRvIGNvbnNpZGVyXG4gICAgICAgIC8vIGV2ZXJ5IHBvaW50LCBvbmx5IHRoZSBleHRyZW1lIGRhdGEgcG9pbnRzXG4gICAgICAgIHZtaW4gPSBJbmZpbml0eTtcbiAgICAgICAgdm1heCA9IC1JbmZpbml0eTtcblxuICAgICAgICBpZihpc0xvZykge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2ID0gZGF0YVtpXTtcbiAgICAgICAgICAgICAgICAvLyBkYXRhIGlzIG5vdCBsaW5lYXJpemVkIHlldCBzbyB3ZSBzdGlsbCBoYXZlIHRvIGZpbHRlciBvdXQgbmVnYXRpdmUgbG9nc1xuICAgICAgICAgICAgICAgIGlmKHYgPCB2bWluICYmIHYgPiAwKSB2bWluID0gdjtcbiAgICAgICAgICAgICAgICBpZih2ID4gdm1heCAmJiB2IDwgRlBfU0FGRSkgdm1heCA9IHY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIHYgPSBkYXRhW2ldO1xuICAgICAgICAgICAgICAgIGlmKHYgPCB2bWluICYmIHYgPiAtRlBfU0FGRSkgdm1pbiA9IHY7XG4gICAgICAgICAgICAgICAgaWYodiA+IHZtYXggJiYgdiA8IEZQX1NBRkUpIHZtYXggPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGF0YSA9IFt2bWluLCB2bWF4XTtcbiAgICAgICAgbGVuID0gMjtcbiAgICB9XG5cbiAgICB2YXIgY29sbGFwc2VPcHRzID0ge3RvemVybzogdG96ZXJvLCBleHRyYXBhZDogZXh0cmFwYWR9O1xuXG4gICAgZnVuY3Rpb24gYWRkSXRlbShpKSB7XG4gICAgICAgIGRpID0gZGF0YVtpXTtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhkaSkpIHJldHVybjtcbiAgICAgICAgcHBhZGlwbHVzID0gcHBhZHBsdXMoaSk7XG4gICAgICAgIHBwYWRpbWludXMgPSBwcGFkbWludXMoaSk7XG4gICAgICAgIHZtaW4gPSBkaSAtIHZwYWRtaW51cyhpKTtcbiAgICAgICAgdm1heCA9IGRpICsgdnBhZHBsdXMoaSk7XG4gICAgICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgbG9nIGF4ZXM6IGlmIHZwYWQgbWFrZXMgdGhpcyBvYmplY3Qgc3BhblxuICAgICAgICAvLyBtb3JlIHRoYW4gYW4gb3JkZXIgb2YgbWFnLCBjbGlwIGl0IHRvIG9uZSBvcmRlci4gVGhpcyBpcyBzb1xuICAgICAgICAvLyB3ZSBkb24ndCBoYXZlIG5vbi1wb3NpdGl2ZSBlcnJvcnMgb3IgYWJzdXJkbHkgbGFyZ2UgbG93ZXJcbiAgICAgICAgLy8gcmFuZ2UgZHVlIHRvIHJvdW5kaW5nIGVycm9yc1xuICAgICAgICBpZihpc0xvZyAmJiB2bWluIDwgdm1heCAvIDEwKSB2bWluID0gdm1heCAvIDEwO1xuXG4gICAgICAgIGRtaW4gPSBheC5jMmwodm1pbik7XG4gICAgICAgIGRtYXggPSBheC5jMmwodm1heCk7XG5cbiAgICAgICAgaWYodG96ZXJvKSB7XG4gICAgICAgICAgICBkbWluID0gTWF0aC5taW4oMCwgZG1pbik7XG4gICAgICAgICAgICBkbWF4ID0gTWF0aC5tYXgoMCwgZG1heCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoZ29vZE51bWJlcihkbWluKSkge1xuICAgICAgICAgICAgY29sbGFwc2VNaW5BcnJheShtaW5BcnJheSwgZG1pbiwgcHBhZGltaW51cywgY29sbGFwc2VPcHRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZihnb29kTnVtYmVyKGRtYXgpKSB7XG4gICAgICAgICAgICBjb2xsYXBzZU1heEFycmF5KG1heEFycmF5LCBkbWF4LCBwcGFkaXBsdXMsIGNvbGxhcHNlT3B0cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGb3IgZWZmaWNpZW5jeSBjb3ZlcmluZyBtb25vdG9uaWMgb3IgbmVhci1tb25vdG9uaWMgZGF0YSxcbiAgICAvLyBjaGVjayBhIGZldyBwb2ludHMgYXQgYm90aCBlbmRzIGZpcnN0IGFuZCB0aGVuIHN3ZWVwXG4gICAgLy8gdGhyb3VnaCB0aGUgbWlkZGxlXG4gICAgdmFyIGlNYXggPSBNYXRoLm1pbig2LCBsZW4pO1xuICAgIGZvcihpID0gMDsgaSA8IGlNYXg7IGkrKykgYWRkSXRlbShpKTtcbiAgICBmb3IoaSA9IGxlbiAtIDE7IGkgPj0gaU1heDsgaS0tKSBhZGRJdGVtKGkpO1xuXG4gICAgcmV0dXJuIHttaW46IG1pbkFycmF5LCBtYXg6IG1heEFycmF5fTtcbn1cblxuZnVuY3Rpb24gY29sbGFwc2VNaW5BcnJheShhcnJheSwgbmV3VmFsLCBuZXdQYWQsIG9wdHMpIHtcbiAgICBjb2xsYXBzZUFycmF5KGFycmF5LCBuZXdWYWwsIG5ld1BhZCwgb3B0cywgbGVzc09yRXF1YWwpO1xufVxuXG5mdW5jdGlvbiBjb2xsYXBzZU1heEFycmF5KGFycmF5LCBuZXdWYWwsIG5ld1BhZCwgb3B0cykge1xuICAgIGNvbGxhcHNlQXJyYXkoYXJyYXksIG5ld1ZhbCwgbmV3UGFkLCBvcHRzLCBncmVhdGVyT3JFcXVhbCk7XG59XG5cbi8qKlxuICogY29sbGFwc2VBcnJheVxuICpcbiAqIFRha2VzIGl0ZW1zIGZyb20gJ2FycmF5JyBhbmQgY29tcGFyZXMgdGhlbSB0byAnbmV3VmFsJywgJ25ld1BhZCcuXG4gKlxuICogQHBhcmFtIHthcnJheX0gYXJyYXk6XG4gKiAgY3VycmVudCBzZXQgb2YgbWluIG9yIG1heCBleHRyZW1lc1xuICogQHBhcmFtIHtudW1iZXJ9IG5ld1ZhbDpcbiAqICBuZXcgdmFsdWUgdG8gY29tcGFyZSBhZ2FpbnN0XG4gKiBAcGFyYW0ge251bWJlcn0gbmV3UGFkOlxuICogIHBhZCB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggJ25ld1ZhbCdcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzOlxuICogIC0gdG96ZXJvIHtib29sZWFufVxuICogIC0gZXh0cmFwYWQge251bWJlcn1cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGF0TGVhc3RBc0V4dHJlbWU6XG4gKiAgY29tcGFyaXNvbiBmdW5jdGlvbiwgdXNlXG4gKiAgLSBsZXNzT3JFcXVhbCBmb3IgbWluICdhcnJheScgYW5kXG4gKiAgLSBncmVhdGVyT3JFcXVhbCBmb3IgbWF4ICdhcnJheSdcbiAqXG4gKiBJbiBwcmFjdGljZSwgJ2FycmF5JyBpcyBlaXRoZXJcbiAqICAtICdleHRyZW1lc1theC5faWRdLm1pbicgb3JcbiAqICAtICdleHRyZW1lc1theC5faWRdLm1heFxuICogIGZvdW5kIGluIHRyYWNlcyBhbmQgbGF5b3V0IGl0ZW1zIHRoYXQgYWZmZWN0IGF1dG9yYW5nZS5cbiAqXG4gKiBTaW5jZSB3ZSBkb24ndCB5ZXQga25vdyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcGl4ZWxzIGFuZCB2YWx1ZXNcbiAqICh0aGF0J3Mgd2hhdCB3ZSdyZSB0cnlpbmcgdG8gZmlndXJlIG91dCEpIEFORCB3ZSBkb24ndCB5ZXQga25vdyBob3dcbiAqIG1hbnkgcGl4ZWxzIGBleHRyYXBhZGAgcmVwcmVzZW50cyAoaXQncyBnb2luZyB0byBiZSA1JSBvZiB0aGUgbGVuZ3RoLFxuICogYnV0IHdlIGRvbid0IHdhbnQgdG8gaGF2ZSB0byByZWRvIGNhbGMganVzdCBiZWNhdXNlIGxlbmd0aCBjaGFuZ2VkKVxuICogdHdvIHBvaW50IG11c3Qgc2F0aXNmeSB0aHJlZSBjcml0ZXJpYSBzaW11bHRhbmVvdXNseSBmb3Igb25lIHRvIHN1cGVyc2VkZSB0aGUgb3RoZXI6XG4gKiAgLSBhdCBsZWFzdCBhcyBleHRyZW1lIGEgYHZhbGBcbiAqICAtIGF0IGxlYXN0IGFzIGJpZyBhIGBwYWRgXG4gKiAgLSBhbiB1bnBhZGRlZCBwb2ludCBjYW5ub3Qgc3VwZXJzZWRlIGEgcGFkZGVkIHBvaW50LCBidXQgYW55IG90aGVyIGNvbWJpbmF0aW9uIGNhblxuICpcbiAqIFRoZW46XG4gKiAtIElmIHRoZSBpdGVtIHN1cGVyc2VkZXMgdGhlIG5ldyBwb2ludCwgc2V0IGluY2x1ZGVUaGlzIGZhbHNlXG4gKiAtIElmIHRoZSBuZXcgcHQgc3VwZXJzZWRlcyB0aGUgaXRlbSwgZGVsZXRlIGl0IGZyb20gJ2FycmF5J1xuICovXG5mdW5jdGlvbiBjb2xsYXBzZUFycmF5KGFycmF5LCBuZXdWYWwsIG5ld1BhZCwgb3B0cywgYXRMZWFzdEFzRXh0cmVtZSkge1xuICAgIHZhciB0b3plcm8gPSBvcHRzLnRvemVybztcbiAgICB2YXIgZXh0cmFwYWQgPSBvcHRzLmV4dHJhcGFkO1xuICAgIHZhciBpbmNsdWRlVGhpcyA9IHRydWU7XG5cbiAgICBmb3IodmFyIGogPSAwOyBqIDwgYXJyYXkubGVuZ3RoICYmIGluY2x1ZGVUaGlzOyBqKyspIHtcbiAgICAgICAgdmFyIHYgPSBhcnJheVtqXTtcbiAgICAgICAgaWYoYXRMZWFzdEFzRXh0cmVtZSh2LnZhbCwgbmV3VmFsKSAmJiB2LnBhZCA+PSBuZXdQYWQgJiYgKHYuZXh0cmFwYWQgfHwgIWV4dHJhcGFkKSkge1xuICAgICAgICAgICAgaW5jbHVkZVRoaXMgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IGVsc2UgaWYoYXRMZWFzdEFzRXh0cmVtZShuZXdWYWwsIHYudmFsKSAmJiB2LnBhZCA8PSBuZXdQYWQgJiYgKGV4dHJhcGFkIHx8ICF2LmV4dHJhcGFkKSkge1xuICAgICAgICAgICAgYXJyYXkuc3BsaWNlKGosIDEpO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmKGluY2x1ZGVUaGlzKSB7XG4gICAgICAgIHZhciBjbGlwQXRaZXJvID0gKHRvemVybyAmJiBuZXdWYWwgPT09IDApO1xuICAgICAgICBhcnJheS5wdXNoKHtcbiAgICAgICAgICAgIHZhbDogbmV3VmFsLFxuICAgICAgICAgICAgcGFkOiBjbGlwQXRaZXJvID8gMCA6IG5ld1BhZCxcbiAgICAgICAgICAgIGV4dHJhcGFkOiBjbGlwQXRaZXJvID8gZmFsc2UgOiBleHRyYXBhZFxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbi8vIEluIG9yZGVyIHRvIHN0b3Agb3ZlcmZsb3cgZXJyb3JzLCBkb24ndCBjb25zaWRlciBwb2ludHNcbi8vIHRvbyBjbG9zZSB0byB0aGUgbGltaXRzIG9mIGpzIGZsb2F0aW5nIHBvaW50XG5mdW5jdGlvbiBnb29kTnVtYmVyKHYpIHtcbiAgICByZXR1cm4gaXNOdW1lcmljKHYpICYmIE1hdGguYWJzKHYpIDwgRlBfU0FGRTtcbn1cblxuZnVuY3Rpb24gbGVzc09yRXF1YWwodjAsIHYxKSB7IHJldHVybiB2MCA8PSB2MTsgfVxuZnVuY3Rpb24gZ3JlYXRlck9yRXF1YWwodjAsIHYxKSB7IHJldHVybiB2MCA+PSB2MTsgfVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgVGl0bGVzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy90aXRsZXMnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbnZhciBheEF0dHJzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGNsZWFuVGlja3MgPSByZXF1aXJlKCcuL2NsZWFuX3RpY2tzJyk7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJyk7XG52YXIgT05FQVZHWUVBUiA9IGNvbnN0YW50cy5PTkVBVkdZRUFSO1xudmFyIE9ORUFWR01PTlRIID0gY29uc3RhbnRzLk9ORUFWR01PTlRIO1xudmFyIE9ORURBWSA9IGNvbnN0YW50cy5PTkVEQVk7XG52YXIgT05FSE9VUiA9IGNvbnN0YW50cy5PTkVIT1VSO1xudmFyIE9ORU1JTiA9IGNvbnN0YW50cy5PTkVNSU47XG52YXIgT05FU0VDID0gY29uc3RhbnRzLk9ORVNFQztcbnZhciBNSU5VU19TSUdOID0gY29uc3RhbnRzLk1JTlVTX1NJR047XG52YXIgQkFETlVNID0gY29uc3RhbnRzLkJBRE5VTTtcblxudmFyIE1JRF9TSElGVCA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5NSURfU0hJRlQ7XG52YXIgTElORV9TUEFDSU5HID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpLkxJTkVfU1BBQ0lORztcblxudmFyIGF4ZXMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5heGVzLnNldENvbnZlcnQgPSByZXF1aXJlKCcuL3NldF9jb252ZXJ0Jyk7XG52YXIgYXV0b1R5cGUgPSByZXF1aXJlKCcuL2F4aXNfYXV0b3R5cGUnKTtcblxudmFyIGF4aXNJZHMgPSByZXF1aXJlKCcuL2F4aXNfaWRzJyk7XG5heGVzLmlkMm5hbWUgPSBheGlzSWRzLmlkMm5hbWU7XG5heGVzLm5hbWUyaWQgPSBheGlzSWRzLm5hbWUyaWQ7XG5heGVzLmNsZWFuSWQgPSBheGlzSWRzLmNsZWFuSWQ7XG5heGVzLmxpc3QgPSBheGlzSWRzLmxpc3Q7XG5heGVzLmxpc3RJZHMgPSBheGlzSWRzLmxpc3RJZHM7XG5heGVzLmdldEZyb21JZCA9IGF4aXNJZHMuZ2V0RnJvbUlkO1xuYXhlcy5nZXRGcm9tVHJhY2UgPSBheGlzSWRzLmdldEZyb21UcmFjZTtcblxudmFyIGF1dG9yYW5nZSA9IHJlcXVpcmUoJy4vYXV0b3JhbmdlJyk7XG5heGVzLmdldEF1dG9SYW5nZSA9IGF1dG9yYW5nZS5nZXRBdXRvUmFuZ2U7XG5heGVzLmZpbmRFeHRyZW1lcyA9IGF1dG9yYW5nZS5maW5kRXh0cmVtZXM7XG5cbi8qXG4gKiBmaW5kIHRoZSBsaXN0IG9mIHBvc3NpYmxlIGF4ZXMgdG8gcmVmZXJlbmNlIHdpdGggYW4geHJlZiBvciB5cmVmIGF0dHJpYnV0ZVxuICogYW5kIGNvZXJjZSBpdCB0byB0aGF0IGxpc3RcbiAqXG4gKiBhdHRyOiB0aGUgYXR0cmlidXRlIHdlJ3JlIGdlbmVyYXRpbmcgYSByZWZlcmVuY2UgZm9yLiBTaG91bGQgZW5kIGluICd4JyBvciAneSdcbiAqICAgICBidXQgY2FuIGJlIHByZWZpeGVkLCBsaWtlICdheCcgZm9yIGFubm90YXRpb24ncyBhcnJvdyB4XG4gKiBkZmx0OiB0aGUgZGVmYXVsdCB0byBjb2VyY2UgdG8sIG9yIGJsYW5rIHRvIHVzZSB0aGUgZmlyc3QgYXhpcyAoZmFsbGluZyBiYWNrIG9uXG4gKiAgICAgZXh0cmFPcHRpb24gaWYgdGhlcmUgaXMgbm8gYXhpcylcbiAqIGV4dHJhT3B0aW9uOiBhc2lkZSBmcm9tIGV4aXN0aW5nIGF4ZXMgd2l0aCB0aGlzIGxldHRlciwgd2hhdCBub24tYXhpcyB2YWx1ZSBpcyBhbGxvd2VkP1xuICogICAgIE9ubHkgcmVxdWlyZWQgaWYgaXQncyBkaWZmZXJlbnQgZnJvbSBgZGZsdGBcbiAqL1xuYXhlcy5jb2VyY2VSZWYgPSBmdW5jdGlvbihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBnZCwgYXR0ciwgZGZsdCwgZXh0cmFPcHRpb24pIHtcbiAgICB2YXIgYXhMZXR0ZXIgPSBhdHRyLmNoYXJBdChhdHRyLmxlbmd0aCAtIDEpO1xuICAgIHZhciBheGxpc3QgPSBnZC5fZnVsbExheW91dC5fc3VicGxvdHNbYXhMZXR0ZXIgKyAnYXhpcyddO1xuICAgIHZhciByZWZBdHRyID0gYXR0ciArICdyZWYnO1xuICAgIHZhciBhdHRyRGVmID0ge307XG5cbiAgICBpZighZGZsdCkgZGZsdCA9IGF4bGlzdFswXSB8fCBleHRyYU9wdGlvbjtcbiAgICBpZighZXh0cmFPcHRpb24pIGV4dHJhT3B0aW9uID0gZGZsdDtcblxuICAgIC8vIGRhdGEtcmVmIGFubm90YXRpb25zIGFyZSBub3Qgc3VwcG9ydGVkIGluIGdsMmQgeWV0XG5cbiAgICBhdHRyRGVmW3JlZkF0dHJdID0ge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogYXhsaXN0LmNvbmNhdChleHRyYU9wdGlvbiA/IFtleHRyYU9wdGlvbl0gOiBbXSksXG4gICAgICAgIGRmbHQ6IGRmbHRcbiAgICB9O1xuXG4gICAgLy8geHJlZiwgeXJlZlxuICAgIHJldHVybiBMaWIuY29lcmNlKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGF0dHJEZWYsIHJlZkF0dHIpO1xufTtcblxuLypcbiAqIGNvZXJjZSBwb3NpdGlvbiBhdHRyaWJ1dGVzIChyYW5nZS10eXBlKSB0aGF0IGNhbiBiZSBlaXRoZXIgb24gYXhlcyBvciBhYnNvbHV0ZVxuICogKHBhcGVyIG9yIHBpeGVsKSByZWZlcmVuY2VkLiBUaGUgYmlnZ2VzdCBjb21wbGljYXRpb24gaGVyZSBpcyB0aGF0IHdlIGRvbid0IGtub3dcbiAqIGJlZm9yZSBsb29raW5nIGF0IHRoZSBheGlzIHdoZXRoZXIgdGhlIHZhbHVlIG11c3QgYmUgYSBudW1iZXIgb3Igbm90IChpdCBtYXkgYmVcbiAqIGEgZGF0ZSBzdHJpbmcpLCBzbyB3ZSBjYW4ndCB1c2UgdGhlIHJlZ3VsYXIgdmFsVHlwZT0nbnVtYmVyJyBtYWNoaW5lcnlcbiAqXG4gKiBheFJlZiAoc3RyaW5nKTogdGhlIGF4aXMgdGhpcyBwb3NpdGlvbiBpcyByZWZlcmVuY2VkIHRvLCBvcjpcbiAqICAgICBwYXBlcjogZnJhY3Rpb24gb2YgdGhlIHBsb3QgYXJlYVxuICogICAgIHBpeGVsOiBwaXhlbHMgcmVsYXRpdmUgdG8gc29tZSBzdGFydGluZyBwb3NpdGlvblxuICogYXR0ciAoc3RyaW5nKTogdGhlIGF0dHJpYnV0ZSBpbiBjb250YWluZXJPdXQgd2UgYXJlIGNvZXJjaW5nXG4gKiBkZmx0IChudW1iZXIpOiB0aGUgZGVmYXVsdCBwb3NpdGlvbiwgYXMgYSBmcmFjdGlvbiBvciBwaXhlbHMuIElmIHRoZSBhdHRyaWJ1dGVcbiAqICAgICBpcyB0byBiZSBheGlzLXJlZmVyZW5jZWQsIHRoaXMgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYW4gYXhpcyBkYXRhIHZhbHVlXG4gKlxuICogQWxzbyBjbGVhbnMgdGhlIHZhbHVlcywgc2luY2UgdGhlIGF0dHJpYnV0ZSBkZWZpbml0aW9uIGl0c2VsZiBoYXMgdG8gc2F5XG4gKiB2YWxUeXBlOiAnYW55JyB0byBoYW5kbGUgZGF0ZSBheGVzLiBUaGlzIGFsbG93cyB1cyB0byBhY2NlcHQ6XG4gKiAtIGZvciBjYXRlZ29yeSBheGVzOiBjYXRlZ29yeSBuYW1lcywgYW5kIGNvbnZlcnQgdGhlbSBoZXJlIGludG8gc2VyaWFsIG51bWJlcnMuXG4gKiAgIE5vdGUgdGhhdCB0aGlzIHdpbGwgTk9UIHdvcmsgZm9yIGF4aXMgcmFuZ2UgZW5kcG9pbnRzLCBiZWNhdXNlIHdlIGRvbid0IGtub3dcbiAqICAgdGhlIGNhdGVnb3J5IGxpc3QgeWV0IChpdCdzIHNldCBieSBheC5tYWtlQ2FsY2RhdGEgZHVyaW5nIGNhbGMpXG4gKiAgIGJ1dCBpdCB3b3JrcyBmb3IgY29tcG9uZW50IChub3RlLCBzaGFwZSwgaW1hZ2VzKSBwb3NpdGlvbnMuXG4gKiAtIGZvciBkYXRlIGF4ZXM6IEpTIERhdGVzIG9yIG1pbGxpc2Vjb25kcywgYW5kIGNvbnZlcnQgdG8gZGF0ZSBzdHJpbmdzXG4gKiAtIGZvciBvdGhlciB0eXBlczogY29lcmNlIHRoZW0gdG8gbnVtYmVyc1xuICovXG5heGVzLmNvZXJjZVBvc2l0aW9uID0gZnVuY3Rpb24oY29udGFpbmVyT3V0LCBnZCwgY29lcmNlLCBheFJlZiwgYXR0ciwgZGZsdCkge1xuICAgIHZhciBjbGVhblBvcywgcG9zO1xuXG4gICAgaWYoYXhSZWYgPT09ICdwYXBlcicgfHwgYXhSZWYgPT09ICdwaXhlbCcpIHtcbiAgICAgICAgY2xlYW5Qb3MgPSBMaWIuZW5zdXJlTnVtYmVyO1xuICAgICAgICBwb3MgPSBjb2VyY2UoYXR0ciwgZGZsdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGF4ID0gYXhlcy5nZXRGcm9tSWQoZ2QsIGF4UmVmKTtcbiAgICAgICAgZGZsdCA9IGF4LmZyYWN0aW9uMnIoZGZsdCk7XG4gICAgICAgIHBvcyA9IGNvZXJjZShhdHRyLCBkZmx0KTtcbiAgICAgICAgY2xlYW5Qb3MgPSBheC5jbGVhblBvcztcbiAgICB9XG5cbiAgICBjb250YWluZXJPdXRbYXR0cl0gPSBjbGVhblBvcyhwb3MpO1xufTtcblxuYXhlcy5jbGVhblBvc2l0aW9uID0gZnVuY3Rpb24ocG9zLCBnZCwgYXhSZWYpIHtcbiAgICB2YXIgY2xlYW5Qb3MgPSAoYXhSZWYgPT09ICdwYXBlcicgfHwgYXhSZWYgPT09ICdwaXhlbCcpID9cbiAgICAgICAgTGliLmVuc3VyZU51bWJlciA6XG4gICAgICAgIGF4ZXMuZ2V0RnJvbUlkKGdkLCBheFJlZikuY2xlYW5Qb3M7XG5cbiAgICByZXR1cm4gY2xlYW5Qb3MocG9zKTtcbn07XG5cbnZhciBnZXREYXRhQ29udmVyc2lvbnMgPSBheGVzLmdldERhdGFDb252ZXJzaW9ucyA9IGZ1bmN0aW9uKGdkLCB0cmFjZSwgdGFyZ2V0LCB0YXJnZXRBcnJheSkge1xuICAgIHZhciBheDtcblxuICAgIC8vIElmIHRhcmdldCBwb2ludHMgdG8gYW4gYXhpcywgdXNlIHRoZSB0eXBlIHdlIGFscmVhZHkgaGF2ZSBmb3IgdGhhdFxuICAgIC8vIGF4aXMgdG8gZmluZCB0aGUgZGF0YSB0eXBlLiBPdGhlcndpc2UgdXNlIHRoZSB2YWx1ZXMgdG8gYXV0b3R5cGUuXG4gICAgdmFyIGQyY1RhcmdldCA9ICh0YXJnZXQgPT09ICd4JyB8fCB0YXJnZXQgPT09ICd5JyB8fCB0YXJnZXQgPT09ICd6JykgP1xuICAgICAgICB0YXJnZXQgOlxuICAgICAgICB0YXJnZXRBcnJheTtcblxuICAgIC8vIEluIHRoZSBjYXNlIG9mIGFuIGFycmF5IHRhcmdldCwgbWFrZSBhIG1vY2sgZGF0YSBhcnJheVxuICAgIC8vIGFuZCBjYWxsIHN1cHBseURlZmF1bHRzIHRvIHRoZSBkYXRhIHR5cGUgYW5kXG4gICAgLy8gc2V0dXAgdGhlIGRhdGEtdG8tY2FsYyBtZXRob2QuXG4gICAgaWYoQXJyYXkuaXNBcnJheShkMmNUYXJnZXQpKSB7XG4gICAgICAgIGF4ID0ge1xuICAgICAgICAgICAgdHlwZTogYXV0b1R5cGUodGFyZ2V0QXJyYXkpLFxuICAgICAgICAgICAgX2NhdGVnb3JpZXM6IFtdXG4gICAgICAgIH07XG4gICAgICAgIGF4ZXMuc2V0Q29udmVydChheCk7XG5cbiAgICAgICAgLy8gYnVpbGQgdXAgYXguX2NhdGVnb3JpZXMgKHVzdWFsbHkgZG9uZSBkdXJpbmcgYXgubWFrZUNhbGNkYXRhKClcbiAgICAgICAgaWYoYXgudHlwZSA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRhcmdldEFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYXguZDJjKHRhcmdldEFycmF5W2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGF4ID0gYXhlcy5nZXRGcm9tVHJhY2UoZ2QsIHRyYWNlLCBkMmNUYXJnZXQpO1xuICAgIH1cblxuICAgIC8vIGlmICd0YXJnZXQnIGhhcyBjb3JyZXNwb25kaW5nIGF4aXNcbiAgICAvLyAtPiB1c2Ugc2V0Q29udmVydCBtZXRob2RcbiAgICBpZihheCkgcmV0dXJuIHtkMmM6IGF4LmQyYywgYzJkOiBheC5jMmR9O1xuXG4gICAgLy8gc3BlY2lhbCBjYXNlIGZvciAnaWRzJ1xuICAgIC8vIC0+IGNhc3QgdG8gU3RyaW5nXG4gICAgaWYoZDJjVGFyZ2V0ID09PSAnaWRzJykgcmV0dXJuIHtkMmM6IHRvU3RyaW5nLCBjMmQ6IHRvU3RyaW5nfTtcblxuICAgIC8vIG90aGVyd2lzZSAoZS5nLiBudW1lcmljLWFycmF5IG9mICdtYXJrZXIuY29sb3InIG9yICdtYXJrZXIuc2l6ZScpXG4gICAgLy8gLT4gY2FzdCB0byBOdW1iZXJcblxuICAgIHJldHVybiB7ZDJjOiB0b051bSwgYzJkOiB0b051bX07XG59O1xuXG5mdW5jdGlvbiB0b051bSh2KSB7IHJldHVybiArdjsgfVxuZnVuY3Rpb24gdG9TdHJpbmcodikgeyByZXR1cm4gU3RyaW5nKHYpOyB9XG5cbmF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jID0gZnVuY3Rpb24oZ2QsIHRyYWNlLCB0YXJnZXQsIHRhcmdldEFycmF5KSB7XG4gICAgcmV0dXJuIGdldERhdGFDb252ZXJzaW9ucyhnZCwgdHJhY2UsIHRhcmdldCwgdGFyZ2V0QXJyYXkpLmQyYztcbn07XG5cbi8vIGdldCBjb3VudGVyYXhpcyBsZXR0ZXIgZm9yIHRoaXMgYXhpcyAobmFtZSBvciBpZClcbi8vIHRoaXMgY2FuIGFsc28gYmUgdXNlZCBhcyB0aGUgaWQgZm9yIGRlZmF1bHQgY291bnRlciBheGlzXG5heGVzLmNvdW50ZXJMZXR0ZXIgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciBheExldHRlciA9IGlkLmNoYXJBdCgwKTtcbiAgICBpZihheExldHRlciA9PT0gJ3gnKSByZXR1cm4gJ3knO1xuICAgIGlmKGF4TGV0dGVyID09PSAneScpIHJldHVybiAneCc7XG59O1xuXG4vLyBpbmNvcnBvcmF0ZSBhIG5ldyBtaW5pbXVtIGRpZmZlcmVuY2UgYW5kIGZpcnN0IHRpY2sgaW50b1xuLy8gZm9yY2VkXG4vLyBub3RlIHRoYXQgX2ZvcmNlVGljazAgaXMgbGluZWFyaXplZCwgc28gbmVlZHMgdG8gYmUgdHVybmVkIGludG9cbi8vIGEgcmFuZ2UgdmFsdWUgZm9yIHNldHRpbmcgdGljazBcbmF4ZXMubWluRHRpY2sgPSBmdW5jdGlvbihheCwgbmV3RGlmZiwgbmV3Rmlyc3QsIGFsbG93KSB7XG4gICAgLy8gZG9lc24ndCBtYWtlIHNlbnNlIHRvIGRvIGZvcmNlZCBtaW4gZFRpY2sgb24gbG9nIG9yIGNhdGVnb3J5IGF4ZXMsXG4gICAgLy8gYW5kIHRoZSBwbG90IGl0c2VsZiBtYXkgZGVjaWRlIHRvIGNhbmNlbCAoaWUgbm9uLWdyb3VwZWQgYmFycylcbiAgICBpZihbJ2xvZycsICdjYXRlZ29yeSddLmluZGV4T2YoYXgudHlwZSkgIT09IC0xIHx8ICFhbGxvdykge1xuICAgICAgICBheC5fbWluRHRpY2sgPSAwO1xuICAgIH1cbiAgICAvLyB1bmRlZmluZWQgbWVhbnMgdGhlcmUncyBub3RoaW5nIHRoZXJlIHlldFxuICAgIGVsc2UgaWYoYXguX21pbkR0aWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXguX21pbkR0aWNrID0gbmV3RGlmZjtcbiAgICAgICAgYXguX2ZvcmNlVGljazAgPSBuZXdGaXJzdDtcbiAgICB9XG4gICAgZWxzZSBpZihheC5fbWluRHRpY2spIHtcbiAgICAgICAgLy8gZXhpc3RpbmcgbWluRHRpY2sgaXMgYW4gaW50ZWdlciBtdWx0aXBsZSBvZiBuZXdEaWZmXG4gICAgICAgIC8vICh3aXRoaW4gcm91bmRpbmcgZXJyKVxuICAgICAgICAvLyBhbmQgZm9yY2VUaWNrMCBjYW4gYmUgc2hpZnRlZCB0byBuZXdGaXJzdFxuICAgICAgICBpZigoYXguX21pbkR0aWNrIC8gbmV3RGlmZiArIDFlLTYpICUgMSA8IDJlLTYgJiZcbiAgICAgICAgICAgICAgICAoKChuZXdGaXJzdCAtIGF4Ll9mb3JjZVRpY2swKSAvIG5ld0RpZmYgJSAxKSArXG4gICAgICAgICAgICAgICAgICAgIDEuMDAwMDAxKSAlIDEgPCAyZS02KSB7XG4gICAgICAgICAgICBheC5fbWluRHRpY2sgPSBuZXdEaWZmO1xuICAgICAgICAgICAgYXguX2ZvcmNlVGljazAgPSBuZXdGaXJzdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0aGUgY29udmVyc2UgaXMgdHJ1ZSAobmV3RGlmZiBpcyBhIG11bHRpcGxlIG9mIG1pbkR0aWNrIGFuZFxuICAgICAgICAvLyBuZXdGaXJzdCBjYW4gYmUgc2hpZnRlZCB0byBmb3JjZVRpY2swKSB0aGVuIGRvIG5vdGhpbmcgLSBzYW1lXG4gICAgICAgIC8vIGZvcmNpbmcgc3RhbmRzLiBPdGhlcndpc2UsIGNhbmNlbCBmb3JjZWQgbWluaW11bVxuICAgICAgICBlbHNlIGlmKChuZXdEaWZmIC8gYXguX21pbkR0aWNrICsgMWUtNikgJSAxID4gMmUtNiB8fFxuICAgICAgICAgICAgICAgICgoKG5ld0ZpcnN0IC0gYXguX2ZvcmNlVGljazApIC8gYXguX21pbkR0aWNrICUgMSkgK1xuICAgICAgICAgICAgICAgICAgICAxLjAwMDAwMSkgJSAxID4gMmUtNikge1xuICAgICAgICAgICAgYXguX21pbkR0aWNrID0gMDtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8vIHNhdmUgYSBjb3B5IG9mIHRoZSBpbml0aWFsIGF4aXMgcmFuZ2VzIGluIGZ1bGxMYXlvdXRcbi8vIHVzZSB0aGVtIGluIG1vZGUgYmFyIGFuZCBkYmxjbGljayBldmVudHNcbmF4ZXMuc2F2ZVJhbmdlSW5pdGlhbCA9IGZ1bmN0aW9uKGdkLCBvdmVyd3JpdGUpIHtcbiAgICB2YXIgYXhMaXN0ID0gYXhlcy5saXN0KGdkLCAnJywgdHJ1ZSksXG4gICAgICAgIGhhc09uZUF4aXNDaGFuZ2VkID0gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheCA9IGF4TGlzdFtpXTtcblxuICAgICAgICB2YXIgaXNOZXcgPSAoYXguX3JhbmdlSW5pdGlhbCA9PT0gdW5kZWZpbmVkKTtcbiAgICAgICAgdmFyIGhhc0NoYW5nZWQgPSAoXG4gICAgICAgICAgICBpc05ldyB8fCAhKFxuICAgICAgICAgICAgICAgIGF4LnJhbmdlWzBdID09PSBheC5fcmFuZ2VJbml0aWFsWzBdICYmXG4gICAgICAgICAgICAgICAgYXgucmFuZ2VbMV0gPT09IGF4Ll9yYW5nZUluaXRpYWxbMV1cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICBpZigoaXNOZXcgJiYgYXguYXV0b3JhbmdlID09PSBmYWxzZSkgfHwgKG92ZXJ3cml0ZSAmJiBoYXNDaGFuZ2VkKSkge1xuICAgICAgICAgICAgYXguX3JhbmdlSW5pdGlhbCA9IGF4LnJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICBoYXNPbmVBeGlzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaGFzT25lQXhpc0NoYW5nZWQ7XG59O1xuXG4vLyBzYXZlIGEgY29weSBvZiB0aGUgaW5pdGlhbCBzcGlrZSB2aXNpYmlsaXR5XG5heGVzLnNhdmVTaG93U3Bpa2VJbml0aWFsID0gZnVuY3Rpb24oZ2QsIG92ZXJ3cml0ZSkge1xuICAgIHZhciBheExpc3QgPSBheGVzLmxpc3QoZ2QsICcnLCB0cnVlKSxcbiAgICAgICAgaGFzT25lQXhpc0NoYW5nZWQgPSBmYWxzZSxcbiAgICAgICAgYWxsU3Bpa2VzRW5hYmxlZCA9ICdvbic7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheCA9IGF4TGlzdFtpXTtcblxuICAgICAgICB2YXIgaXNOZXcgPSAoYXguX3Nob3dTcGlrZUluaXRpYWwgPT09IHVuZGVmaW5lZCk7XG4gICAgICAgIHZhciBoYXNDaGFuZ2VkID0gKFxuICAgICAgICAgICAgaXNOZXcgfHwgIShcbiAgICAgICAgICAgICAgICBheC5zaG93c3Bpa2VzID09PSBheC5fc2hvd3NwaWtlc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIGlmKChpc05ldykgfHwgKG92ZXJ3cml0ZSAmJiBoYXNDaGFuZ2VkKSkge1xuICAgICAgICAgICAgYXguX3Nob3dTcGlrZUluaXRpYWwgPSBheC5zaG93c3Bpa2VzO1xuICAgICAgICAgICAgaGFzT25lQXhpc0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYWxsU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyAmJiAhYXguc2hvd3NwaWtlcykge1xuICAgICAgICAgICAgYWxsU3Bpa2VzRW5hYmxlZCA9ICdvZmYnO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdkLl9mdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5TcGlrZXNFbmFibGVkID0gYWxsU3Bpa2VzRW5hYmxlZDtcbiAgICByZXR1cm4gaGFzT25lQXhpc0NoYW5nZWQ7XG59O1xuXG5heGVzLmF1dG9CaW4gPSBmdW5jdGlvbihkYXRhLCBheCwgbmJpbnMsIGlzMmQsIGNhbGVuZGFyLCBzaXplKSB7XG4gICAgdmFyIGRhdGFNaW4gPSBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgZGF0YSk7XG4gICAgdmFyIGRhdGFNYXggPSBMaWIuYWdnTnVtcyhNYXRoLm1heCwgbnVsbCwgZGF0YSk7XG5cbiAgICBpZihheC50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGFydDogZGF0YU1pbiAtIDAuNSxcbiAgICAgICAgICAgIGVuZDogZGF0YU1heCArIDAuNSxcbiAgICAgICAgICAgIHNpemU6IE1hdGgubWF4KDEsIE1hdGgucm91bmQoc2l6ZSkgfHwgMSksXG4gICAgICAgICAgICBfZGF0YVNwYW46IGRhdGFNYXggLSBkYXRhTWluLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmKCFjYWxlbmRhcikgY2FsZW5kYXIgPSBheC5jYWxlbmRhcjtcblxuICAgIC8vIHBpZ2d5YmFjayBvZmYgdGljayBjb2RlIHRvIG1ha2UgXCJuaWNlXCIgYmluIHNpemVzIGFuZCBlZGdlc1xuICAgIHZhciBkdW1teUF4O1xuICAgIGlmKGF4LnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgIGR1bW15QXggPSB7XG4gICAgICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgICAgIHJhbmdlOiBbZGF0YU1pbiwgZGF0YU1heF1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGR1bW15QXggPSB7XG4gICAgICAgICAgICB0eXBlOiBheC50eXBlLFxuICAgICAgICAgICAgcmFuZ2U6IExpYi5zaW1wbGVNYXAoW2RhdGFNaW4sIGRhdGFNYXhdLCBheC5jMnIsIDAsIGNhbGVuZGFyKSxcbiAgICAgICAgICAgIGNhbGVuZGFyOiBjYWxlbmRhclxuICAgICAgICB9O1xuICAgIH1cbiAgICBheGVzLnNldENvbnZlcnQoZHVtbXlBeCk7XG5cbiAgICBzaXplID0gc2l6ZSAmJiBjbGVhblRpY2tzLmR0aWNrKHNpemUsIGR1bW15QXgudHlwZSk7XG5cbiAgICBpZihzaXplKSB7XG4gICAgICAgIGR1bW15QXguZHRpY2sgPSBzaXplO1xuICAgICAgICBkdW1teUF4LnRpY2swID0gY2xlYW5UaWNrcy50aWNrMCh1bmRlZmluZWQsIGR1bW15QXgudHlwZSwgY2FsZW5kYXIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHNpemUwO1xuICAgICAgICBpZihuYmlucykgc2l6ZTAgPSAoKGRhdGFNYXggLSBkYXRhTWluKSAvIG5iaW5zKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyB0b3RhbGx5IGF1dG86IHNjYWxlIG9mZiBzdGQgZGV2aWF0aW9uIHNvIHRoZSBoaWdoZXN0IGJpbiBpc1xuICAgICAgICAgICAgLy8gc29tZXdoYXQgdGFsbGVyIHRoYW4gdGhlIHRvdGFsIG51bWJlciBvZiBiaW5zLCBidXQgZG9uJ3QgbGV0XG4gICAgICAgICAgICAvLyB0aGUgc2l6ZSBnZXQgc21hbGxlciB0aGFuIHRoZSAnbmljZScgcm91bmRlZCBkb3duIG1pbmltdW1cbiAgICAgICAgICAgIC8vIGRpZmZlcmVuY2UgYmV0d2VlbiB2YWx1ZXNcbiAgICAgICAgICAgIHZhciBkaXN0aW5jdERhdGEgPSBMaWIuZGlzdGluY3RWYWxzKGRhdGEpO1xuICAgICAgICAgICAgdmFyIG1zZXhwID0gTWF0aC5wb3coMTAsIE1hdGguZmxvb3IoXG4gICAgICAgICAgICAgICAgTWF0aC5sb2coZGlzdGluY3REYXRhLm1pbkRpZmYpIC8gTWF0aC5MTjEwKSk7XG4gICAgICAgICAgICB2YXIgbWluU2l6ZSA9IG1zZXhwICogTGliLnJvdW5kVXAoXG4gICAgICAgICAgICAgICAgZGlzdGluY3REYXRhLm1pbkRpZmYgLyBtc2V4cCwgWzAuOSwgMS45LCA0LjksIDkuOV0sIHRydWUpO1xuICAgICAgICAgICAgc2l6ZTAgPSBNYXRoLm1heChtaW5TaXplLCAyICogTGliLnN0ZGV2KGRhdGEpIC9cbiAgICAgICAgICAgICAgICBNYXRoLnBvdyhkYXRhLmxlbmd0aCwgaXMyZCA/IDAuMjUgOiAwLjQpKTtcblxuICAgICAgICAgICAgLy8gZmFsbGJhY2sgaWYgYXguZDJjIG91dHB1dCBCQUROVU1zXG4gICAgICAgICAgICAvLyBlLmcuIHdoZW4gdXNlciB0cnkgdG8gcGxvdCBjYXRlZ29yaWNhbCBiaW5zXG4gICAgICAgICAgICAvLyBvbiBhIGxheW91dC54YXhpcy50eXBlOiAnbGluZWFyJ1xuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhzaXplMCkpIHNpemUwID0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF4ZXMuYXV0b1RpY2tzKGR1bW15QXgsIHNpemUwKTtcbiAgICB9XG5cblxuICAgIHZhciBmaW5hbFNpemUgPSBkdW1teUF4LmR0aWNrO1xuICAgIHZhciBiaW5TdGFydCA9IGF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgIGF4ZXMudGlja0ZpcnN0KGR1bW15QXgpLCBmaW5hbFNpemUsICdyZXZlcnNlJywgY2FsZW5kYXIpO1xuICAgIHZhciBiaW5FbmQsIGJpbmNvdW50O1xuXG4gICAgLy8gY2hlY2sgZm9yIHRvbyBtYW55IGRhdGEgcG9pbnRzIHJpZ2h0IGF0IHRoZSBlZGdlcyBvZiBiaW5zXG4gICAgLy8gKD41MCUgd2l0aGluIDElIG9mIGJpbiBlZGdlcykgb3IgYWxsIGRhdGEgcG9pbnRzIGludGVncmFsXG4gICAgLy8gYW5kIG9mZnNldCB0aGUgYmlucyBhY2NvcmRpbmdseVxuICAgIGlmKHR5cGVvZiBmaW5hbFNpemUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGJpblN0YXJ0ID0gYXV0b1NoaWZ0TnVtZXJpY0JpbnMoYmluU3RhcnQsIGRhdGEsIGR1bW15QXgsIGRhdGFNaW4sIGRhdGFNYXgpO1xuXG4gICAgICAgIGJpbmNvdW50ID0gMSArIE1hdGguZmxvb3IoKGRhdGFNYXggLSBiaW5TdGFydCkgLyBmaW5hbFNpemUpO1xuICAgICAgICBiaW5FbmQgPSBiaW5TdGFydCArIGJpbmNvdW50ICogZmluYWxTaXplO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gbW9udGggdGlja3MgLSBzaG91bGQgYmUgdGhlIG9ubHkgbm9ubGluZWFyIGtpbmQgd2UgaGF2ZSBhdCB0aGlzIHBvaW50LlxuICAgICAgICAvLyBkdGljayAoYXMgc3VwcGxpZWQgYnkgYXhlcy5hdXRvVGljaykgb25seSBoYXMgbm9ubGluZWFyIHZhbHVlcyBvblxuICAgICAgICAvLyBkYXRlIGFuZCBsb2cgYXhlcywgYnV0IGV2ZW4gaWYgeW91IGRpc3BsYXkgYSBoaXN0b2dyYW0gb24gYSBsb2cgYXhpc1xuICAgICAgICAvLyB3ZSBiaW4gaXQgb24gYSBsaW5lYXIgYXhpcyAod2hpY2ggb25lIGNvdWxkIGFyZ3VlIGFnYWluc3QsIGJ1dCB0aGF0J3NcbiAgICAgICAgLy8gYSBzZXBhcmF0ZSBpc3N1ZSlcbiAgICAgICAgaWYoZHVtbXlBeC5kdGljay5jaGFyQXQoMCkgPT09ICdNJykge1xuICAgICAgICAgICAgYmluU3RhcnQgPSBhdXRvU2hpZnRNb250aEJpbnMoYmluU3RhcnQsIGRhdGEsIGZpbmFsU2l6ZSwgZGF0YU1pbiwgY2FsZW5kYXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBlbmRwb2ludCBmb3Igbm9ubGluZWFyIHRpY2tzIC0geW91IGhhdmUgdG9cbiAgICAgICAgLy8ganVzdCBpbmNyZW1lbnQgdW50aWwgeW91J3JlIGRvbmVcbiAgICAgICAgYmluRW5kID0gYmluU3RhcnQ7XG4gICAgICAgIGJpbmNvdW50ID0gMDtcbiAgICAgICAgd2hpbGUoYmluRW5kIDw9IGRhdGFNYXgpIHtcbiAgICAgICAgICAgIGJpbkVuZCA9IGF4ZXMudGlja0luY3JlbWVudChiaW5FbmQsIGZpbmFsU2l6ZSwgZmFsc2UsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIGJpbmNvdW50Kys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFydDogYXguYzJyKGJpblN0YXJ0LCAwLCBjYWxlbmRhciksXG4gICAgICAgIGVuZDogYXguYzJyKGJpbkVuZCwgMCwgY2FsZW5kYXIpLFxuICAgICAgICBzaXplOiBmaW5hbFNpemUsXG4gICAgICAgIF9kYXRhU3BhbjogZGF0YU1heCAtIGRhdGFNaW5cbiAgICB9O1xufTtcblxuXG5mdW5jdGlvbiBhdXRvU2hpZnROdW1lcmljQmlucyhiaW5TdGFydCwgZGF0YSwgYXgsIGRhdGFNaW4sIGRhdGFNYXgpIHtcbiAgICB2YXIgZWRnZWNvdW50ID0gMCxcbiAgICAgICAgbWlkY291bnQgPSAwLFxuICAgICAgICBpbnRjb3VudCA9IDAsXG4gICAgICAgIGJsYW5rQ291bnQgPSAwO1xuXG4gICAgZnVuY3Rpb24gbmVhckVkZ2Uodikge1xuICAgICAgICAvLyBpcyBhIHZhbHVlIHdpdGhpbiAxJSBvZiBhIGJpbiBlZGdlP1xuICAgICAgICByZXR1cm4gKDEgKyAodiAtIGJpblN0YXJ0KSAqIDEwMCAvIGF4LmR0aWNrKSAlIDEwMCA8IDI7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZGF0YVtpXSAlIDEgPT09IDApIGludGNvdW50Kys7XG4gICAgICAgIGVsc2UgaWYoIWlzTnVtZXJpYyhkYXRhW2ldKSkgYmxhbmtDb3VudCsrO1xuXG4gICAgICAgIGlmKG5lYXJFZGdlKGRhdGFbaV0pKSBlZGdlY291bnQrKztcbiAgICAgICAgaWYobmVhckVkZ2UoZGF0YVtpXSArIGF4LmR0aWNrIC8gMikpIG1pZGNvdW50Kys7XG4gICAgfVxuICAgIHZhciBkYXRhQ291bnQgPSBkYXRhLmxlbmd0aCAtIGJsYW5rQ291bnQ7XG5cbiAgICBpZihpbnRjb3VudCA9PT0gZGF0YUNvdW50ICYmIGF4LnR5cGUgIT09ICdkYXRlJykge1xuICAgICAgICAvLyBhbGwgaW50ZWdlcnM6IGlmIGJpbiBzaXplIGlzIDwxLCBpdCdzIGJlY2F1c2VcbiAgICAgICAgLy8gdGhhdCB3YXMgc3BlY2lmaWNhbGx5IHJlcXVlc3RlZCAobGFyZ2UgbmJpbnMpXG4gICAgICAgIC8vIHNvIHJlc3BlY3QgdGhhdC4uLiBidXQgY2VudGVyIHRoZSBiaW5zIGNvbnRhaW5pbmdcbiAgICAgICAgLy8gaW50ZWdlcnMgb24gdGhvc2UgaW50ZWdlcnNcbiAgICAgICAgaWYoYXguZHRpY2sgPCAxKSB7XG4gICAgICAgICAgICBiaW5TdGFydCA9IGRhdGFNaW4gLSAwLjUgKiBheC5kdGljaztcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2Ugc3RhcnQgaGFsZiBhbiBpbnRlZ2VyIGRvd24gcmVnYXJkbGVzcyBvZlxuICAgICAgICAvLyB0aGUgYmluIHNpemUsIGp1c3QgZW5vdWdoIHRvIGNsZWFyIHVwIGVuZHBvaW50XG4gICAgICAgIC8vIGFtYmlndWl0eSBhYm91dCB3aGljaCBpbnRlZ2VycyBhcmUgaW4gd2hpY2ggYmlucy5cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBiaW5TdGFydCAtPSAwLjU7XG4gICAgICAgICAgICBpZihiaW5TdGFydCArIGF4LmR0aWNrIDwgZGF0YU1pbikgYmluU3RhcnQgKz0gYXguZHRpY2s7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZihtaWRjb3VudCA8IGRhdGFDb3VudCAqIDAuMSkge1xuICAgICAgICBpZihlZGdlY291bnQgPiBkYXRhQ291bnQgKiAwLjMgfHxcbiAgICAgICAgICAgICAgICBuZWFyRWRnZShkYXRhTWluKSB8fCBuZWFyRWRnZShkYXRhTWF4KSkge1xuICAgICAgICAgICAgLy8gbG90cyBvZiBwb2ludHMgYXQgdGhlIGVkZ2UsIG5vdCBtYW55IGluIHRoZSBtaWRkbGVcbiAgICAgICAgICAgIC8vIHNoaWZ0IGhhbGYgYSBiaW5cbiAgICAgICAgICAgIHZhciBiaW5zaGlmdCA9IGF4LmR0aWNrIC8gMjtcbiAgICAgICAgICAgIGJpblN0YXJ0ICs9IChiaW5TdGFydCArIGJpbnNoaWZ0IDwgZGF0YU1pbikgPyBiaW5zaGlmdCA6IC1iaW5zaGlmdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmluU3RhcnQ7XG59XG5cblxuZnVuY3Rpb24gYXV0b1NoaWZ0TW9udGhCaW5zKGJpblN0YXJ0LCBkYXRhLCBkdGljaywgZGF0YU1pbiwgY2FsZW5kYXIpIHtcbiAgICB2YXIgc3RhdHMgPSBMaWIuZmluZEV4YWN0RGF0ZXMoZGF0YSwgY2FsZW5kYXIpO1xuICAgIC8vIG51bWJlciBvZiBkYXRhIHBvaW50cyB0aGF0IG5lZWRzIHRvIGJlIGFuIGV4YWN0IHZhbHVlXG4gICAgLy8gdG8gc2hpZnQgdGhhdCBpbmNyZW1lbnQgdG8gKG5lYXIpIHRoZSBiaW4gY2VudGVyXG4gICAgdmFyIHRocmVzaG9sZCA9IDAuODtcblxuICAgIGlmKHN0YXRzLmV4YWN0RGF5cyA+IHRocmVzaG9sZCkge1xuICAgICAgICB2YXIgbnVtTW9udGhzID0gTnVtYmVyKGR0aWNrLnN1YnN0cigxKSk7XG5cbiAgICAgICAgaWYoKHN0YXRzLmV4YWN0WWVhcnMgPiB0aHJlc2hvbGQpICYmIChudW1Nb250aHMgJSAxMiA9PT0gMCkpIHtcbiAgICAgICAgICAgIC8vIFRoZSBleGFjdCBtaWRkbGUgb2YgYSBub24tbGVhcC15ZWFyIGlzIDEuNSBkYXlzIGludG8gSnVseVxuICAgICAgICAgICAgLy8gc28gaWYgd2Ugc3RhcnQgdGhlIGJpbnMgaGVyZSwgYWxsIGJ1dCBsZWFwIHllYXJzIHdpbGxcbiAgICAgICAgICAgIC8vIGdldCBob3Zlci1sYWJlbGVkIGFzIGV4YWN0IHllYXJzLlxuICAgICAgICAgICAgYmluU3RhcnQgPSBheGVzLnRpY2tJbmNyZW1lbnQoYmluU3RhcnQsICdNNicsICdyZXZlcnNlJykgKyBPTkVEQVkgKiAxLjU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihzdGF0cy5leGFjdE1vbnRocyA+IHRocmVzaG9sZCkge1xuICAgICAgICAgICAgLy8gTW9udGhzIGFyZSBub3QgYXMgY2xlYW4sIGJ1dCBpZiB3ZSBzaGlmdCBoYWxmIHRoZSAqbG9uZ2VzdCpcbiAgICAgICAgICAgIC8vIG1vbnRoICgzMS8yIGRheXMpIHRoZW4gMzEtZGF5IG1vbnRocyB3aWxsIGdldCBsYWJlbGVkIGV4YWN0bHlcbiAgICAgICAgICAgIC8vIGFuZCBzaG9ydGVyIG1vbnRocyB3aWxsIGdldCBsYWJlbGVkIHdpdGggdGhlIGNvcnJlY3QgbW9udGhcbiAgICAgICAgICAgIC8vIGJ1dCBzaGlmdGVkIDEyLTM2IGhvdXJzIGludG8gaXQuXG4gICAgICAgICAgICBiaW5TdGFydCA9IGF4ZXMudGlja0luY3JlbWVudChiaW5TdGFydCwgJ00xJywgJ3JldmVyc2UnKSArIE9ORURBWSAqIDE1LjU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTaGlmdGluZyBoYWxmIGEgZGF5IGlzIGV4YWN0LCBidXQgc2luY2UgdGhlc2UgYXJlIG1vbnRoIGJpbnMgaXRcbiAgICAgICAgICAgIC8vIHdpbGwgYWx3YXlzIGdpdmUgYSBzb21ld2hhdCBvZGQtbG9va2luZyBsYWJlbCwgdW50aWwgd2UgZG8gc29tZXRoaW5nXG4gICAgICAgICAgICAvLyBzbWFydGVyIGxpa2Ugc2hvd2luZyB0aGUgYmluIGJvdW5kYXJpZXMgKG9yIHRoZSBib3VuZHMgb2YgdGhlIGFjdHVhbFxuICAgICAgICAgICAgLy8gZGF0YSBpbiBlYWNoIGJpbilcbiAgICAgICAgICAgIGJpblN0YXJ0IC09IE9ORURBWSAvIDI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5leHRCaW5TdGFydCA9IGF4ZXMudGlja0luY3JlbWVudChiaW5TdGFydCwgZHRpY2spO1xuXG4gICAgICAgIGlmKG5leHRCaW5TdGFydCA8PSBkYXRhTWluKSByZXR1cm4gbmV4dEJpblN0YXJ0O1xuICAgIH1cbiAgICByZXR1cm4gYmluU3RhcnQ7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRpY2tzIGFuZCBncmlkc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBlbnN1cmUgd2UgaGF2ZSB0aWNrMCwgZHRpY2ssIGFuZCB0aWNrIHJvdW5kaW5nIGNhbGN1bGF0ZWRcbmF4ZXMucHJlcFRpY2tzID0gZnVuY3Rpb24oYXgpIHtcbiAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBtYXggbnVtYmVyIG9mIChhdXRvKSB0aWNrcyB0byBkaXNwbGF5IGJhc2VkIG9uIHBsb3Qgc2l6ZVxuICAgIGlmKGF4LnRpY2ttb2RlID09PSAnYXV0bycgfHwgIWF4LmR0aWNrKSB7XG4gICAgICAgIHZhciBudCA9IGF4Lm50aWNrcyxcbiAgICAgICAgICAgIG1pblB4O1xuICAgICAgICBpZighbnQpIHtcbiAgICAgICAgICAgIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgICAgICBtaW5QeCA9IGF4LnRpY2tmb250ID8gKGF4LnRpY2tmb250LnNpemUgfHwgMTIpICogMS4yIDogMTU7XG4gICAgICAgICAgICAgICAgbnQgPSBheC5fbGVuZ3RoIC8gbWluUHg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtaW5QeCA9IGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd5JyA/IDQwIDogODA7XG4gICAgICAgICAgICAgICAgbnQgPSBMaWIuY29uc3RyYWluKGF4Ll9sZW5ndGggLyBtaW5QeCwgNCwgOSkgKyAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyByYWRpYWwgYXhlcyBzcGFuIGhhbGYgdGhlaXIgZG9tYWluLFxuICAgICAgICAgICAgLy8gbXVsdGlwbHkgbnRpY2tzIHZhbHVlIGJ5IHR3byB0byBnZXQgY29ycmVjdCBudW1iZXIgb2YgYXV0byB0aWNrcy5cbiAgICAgICAgICAgIGlmKGF4Ll9uYW1lID09PSAncmFkaWFsYXhpcycpIG50ICo9IDI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgYSBjb3VwbGUgb2YgZXh0cmEgZGlnaXRzIGZvciBmaWxsaW5nIGluIHRpY2tzIHdoZW4gd2VcbiAgICAgICAgLy8gaGF2ZSBleHBsaWNpdCB0aWNrdmFscyB3aXRob3V0IHRpY2sgdGV4dFxuICAgICAgICBpZihheC50aWNrbW9kZSA9PT0gJ2FycmF5JykgbnQgKj0gMTAwO1xuXG4gICAgICAgIGF4ZXMuYXV0b1RpY2tzKGF4LCBNYXRoLmFicyhybmdbMV0gLSBybmdbMF0pIC8gbnQpO1xuICAgICAgICAvLyBjaGVjayBmb3IgYSBmb3JjZWQgbWluaW11bSBkdGlja1xuICAgICAgICBpZihheC5fbWluRHRpY2sgPiAwICYmIGF4LmR0aWNrIDwgYXguX21pbkR0aWNrICogMikge1xuICAgICAgICAgICAgYXguZHRpY2sgPSBheC5fbWluRHRpY2s7XG4gICAgICAgICAgICBheC50aWNrMCA9IGF4LmwycihheC5fZm9yY2VUaWNrMCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjaGVjayBmb3IgbWlzc2luZyB0aWNrMFxuICAgIGlmKCFheC50aWNrMCkge1xuICAgICAgICBheC50aWNrMCA9IChheC50eXBlID09PSAnZGF0ZScpID8gJzIwMDAtMDEtMDEnIDogMDtcbiAgICB9XG5cbiAgICAvLyBlbnN1cmUgd2UgZG9uJ3QgdHJ5IHRvIG1ha2UgdGlja3MgYmVsb3cgb3VyIG1pbmltdW0gcHJlY2lzaW9uXG4gICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8yODkyXG4gICAgaWYoYXgudHlwZSA9PT0gJ2RhdGUnICYmIGF4LmR0aWNrIDwgMC4xKSBheC5kdGljayA9IDAuMTtcblxuICAgIC8vIG5vdyBmaWd1cmUgb3V0IHJvdW5kaW5nIG9mIHRpY2sgdmFsdWVzXG4gICAgYXV0b1RpY2tSb3VuZChheCk7XG59O1xuXG4vLyBjYWxjdWxhdGUgdGhlIHRpY2tzOiB0ZXh0LCB2YWx1ZXMsIHBvc2l0aW9uaW5nXG4vLyBpZiB0aWNrcyBhcmUgc2V0IHRvIGF1dG9tYXRpYywgZGV0ZXJtaW5lIHRoZSByaWdodCB2YWx1ZXMgKHRpY2swLGR0aWNrKVxuLy8gaW4gYW55IGNhc2UsIHNldCB0aWNrcm91bmQgdG8gIyBvZiBkaWdpdHMgdG8gcm91bmQgdGljayBsYWJlbHMgdG8sXG4vLyBvciBjb2RlcyB0byB0aGlzIGVmZmVjdCBmb3IgbG9nIGFuZCBkYXRlIHNjYWxlc1xuYXhlcy5jYWxjVGlja3MgPSBmdW5jdGlvbiBjYWxjVGlja3MoYXgpIHtcbiAgICBheGVzLnByZXBUaWNrcyhheCk7XG4gICAgdmFyIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG5cbiAgICAvLyBub3cgdGhhdCB3ZSd2ZSBmaWd1cmVkIG91dCB0aGUgYXV0byB2YWx1ZXMgZm9yIGZvcm1hdHRpbmdcbiAgICAvLyBpbiBjYXNlIHdlJ3JlIG1pc3Npbmcgc29tZSB0aWNrdGV4dCwgd2UgY2FuIGJyZWFrIG91dCBmb3IgYXJyYXkgdGlja3NcbiAgICBpZihheC50aWNrbW9kZSA9PT0gJ2FycmF5JykgcmV0dXJuIGFycmF5VGlja3MoYXgpO1xuXG4gICAgLy8gZmluZCB0aGUgZmlyc3QgdGlja1xuICAgIGF4Ll90bWluID0gYXhlcy50aWNrRmlyc3QoYXgpO1xuXG4gICAgLy8gYWRkIGEgdGlueSBiaXQgc28gd2UgZ2V0IHRpY2tzIHdoaWNoIG1heSBoYXZlIHJvdW5kZWQgb3V0XG4gICAgdmFyIHN0YXJ0VGljayA9IHJuZ1swXSAqIDEuMDAwMSAtIHJuZ1sxXSAqIDAuMDAwMTtcbiAgICB2YXIgZW5kVGljayA9IHJuZ1sxXSAqIDEuMDAwMSAtIHJuZ1swXSAqIDAuMDAwMTtcbiAgICAvLyBjaGVjayBmb3IgcmV2ZXJzZWQgYXhpc1xuICAgIHZhciBheHJldiA9IChybmdbMV0gPCBybmdbMF0pO1xuXG4gICAgLy8gTm8gdmlzaWJsZSB0aWNrcz8gUXVpdC5cbiAgICAvLyBJJ3ZlIG9ubHkgc2VlbiB0aGlzIG9uIGNhdGVnb3J5IGF4ZXMgd2l0aCBhbGwgY2F0ZWdvcmllcyBvZmYgdGhlIGVkZ2UuXG4gICAgaWYoKGF4Ll90bWluIDwgc3RhcnRUaWNrKSAhPT0gYXhyZXYpIHJldHVybiBbXTtcblxuICAgIC8vIHJldHVybiB0aGUgZnVsbCBzZXQgb2YgdGljayB2YWxzXG4gICAgdmFyIHZhbHMgPSBbXTtcbiAgICBpZihheC50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIGVuZFRpY2sgPSAoYXhyZXYpID8gTWF0aC5tYXgoLTAuNSwgZW5kVGljaykgOlxuICAgICAgICAgICAgTWF0aC5taW4oYXguX2NhdGVnb3JpZXMubGVuZ3RoIC0gMC41LCBlbmRUaWNrKTtcbiAgICB9XG5cbiAgICB2YXIgeFByZXZpb3VzID0gbnVsbDtcbiAgICB2YXIgbWF4VGlja3MgPSBNYXRoLm1heCgxMDAwLCBheC5fbGVuZ3RoIHx8IDApO1xuICAgIGZvcih2YXIgeCA9IGF4Ll90bWluO1xuICAgICAgICAgICAgKGF4cmV2KSA/ICh4ID49IGVuZFRpY2spIDogKHggPD0gZW5kVGljayk7XG4gICAgICAgICAgICB4ID0gYXhlcy50aWNrSW5jcmVtZW50KHgsIGF4LmR0aWNrLCBheHJldiwgYXguY2FsZW5kYXIpKSB7XG4gICAgICAgIC8vIHByZXZlbnQgaW5maW5pdGUgbG9vcHMgLSBubyBtb3JlIHRoYW4gb25lIHRpY2sgcGVyIHBpeGVsLFxuICAgICAgICAvLyBhbmQgbWFrZSBzdXJlIGVhY2ggdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gdGhlIHByZXZpb3VzXG4gICAgICAgIGlmKHZhbHMubGVuZ3RoID4gbWF4VGlja3MgfHwgeCA9PT0geFByZXZpb3VzKSBicmVhaztcbiAgICAgICAgeFByZXZpb3VzID0geDtcblxuICAgICAgICB2YWxzLnB1c2goeCk7XG4gICAgfVxuXG4gICAgLy8gSWYgc2FtZSBhbmdsZSBvdmVyIGEgZnVsbCBjaXJjbGUsIHRoZSBsYXN0IHRpY2sgdmFscyBpcyBhIGR1cGxpY2F0ZS5cbiAgICAvLyBUT0RPIG11c3QgZG8gc29tZXRoaW5nIHNpbWlsYXIgZm9yIGFuZ3VsYXIgZGF0ZSBheGVzLlxuICAgIGlmKGlzQW5ndWxhcihheCkgJiYgTWF0aC5hYnMocm5nWzFdIC0gcm5nWzBdKSA9PT0gMzYwKSB7XG4gICAgICAgIHZhbHMucG9wKCk7XG4gICAgfVxuXG4gICAgLy8gc2F2ZSB0aGUgbGFzdCB0aWNrIGFzIHdlbGwgYXMgZmlyc3QsIHNvIHdlIGNhblxuICAgIC8vIHNob3cgdGhlIGV4cG9uZW50IG9ubHkgb24gdGhlIGxhc3Qgb25lXG4gICAgYXguX3RtYXggPSB2YWxzW3ZhbHMubGVuZ3RoIC0gMV07XG5cbiAgICAvLyBmb3Igc2hvd2luZyB0aGUgcmVzdCBvZiBhIGRhdGUgd2hlbiB0aGUgbWFpbiB0aWNrIGxhYmVsIGlzIG9ubHkgdGhlXG4gICAgLy8gbGF0dGVyIHBhcnQ6IGF4Ll9wcmV2RGF0ZUhlYWQgaG9sZHMgd2hhdCB3ZSBzaG93ZWQgbW9zdCByZWNlbnRseS5cbiAgICAvLyBTdGFydCB3aXRoIGl0IGNsZWFyZWQgYW5kIG1hcmsgdGhhdCB3ZSdyZSBpbiBjYWxjVGlja3MgKGllIGNhbGN1bGF0aW5nIGFcbiAgICAvLyB3aG9sZSBzdHJpbmcgb2YgdGhlc2Ugc28gd2Ugc2hvdWxkIGNhcmUgd2hhdCB0aGUgcHJldmlvdXMgZGF0ZSBoZWFkIHdhcyEpXG4gICAgYXguX3ByZXZEYXRlSGVhZCA9ICcnO1xuICAgIGF4Ll9pbkNhbGNUaWNrcyA9IHRydWU7XG5cbiAgICB2YXIgdGlja3NPdXQgPSBuZXcgQXJyYXkodmFscy5sZW5ndGgpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB0aWNrc091dFtpXSA9IGF4ZXMudGlja1RleHQoYXgsIHZhbHNbaV0pO1xuXG4gICAgYXguX2luQ2FsY1RpY2tzID0gZmFsc2U7XG5cbiAgICByZXR1cm4gdGlja3NPdXQ7XG59O1xuXG5mdW5jdGlvbiBhcnJheVRpY2tzKGF4KSB7XG4gICAgdmFyIHZhbHMgPSBheC50aWNrdmFscyxcbiAgICAgICAgdGV4dCA9IGF4LnRpY2t0ZXh0LFxuICAgICAgICB0aWNrc091dCA9IG5ldyBBcnJheSh2YWxzLmxlbmd0aCksXG4gICAgICAgIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCksXG4gICAgICAgIHIwZXhwYW5kZWQgPSBybmdbMF0gKiAxLjAwMDEgLSBybmdbMV0gKiAwLjAwMDEsXG4gICAgICAgIHIxZXhwYW5kZWQgPSBybmdbMV0gKiAxLjAwMDEgLSBybmdbMF0gKiAwLjAwMDEsXG4gICAgICAgIHRpY2tNaW4gPSBNYXRoLm1pbihyMGV4cGFuZGVkLCByMWV4cGFuZGVkKSxcbiAgICAgICAgdGlja01heCA9IE1hdGgubWF4KHIwZXhwYW5kZWQsIHIxZXhwYW5kZWQpLFxuICAgICAgICB2YWxpLFxuICAgICAgICBpLFxuICAgICAgICBqID0gMDtcblxuICAgIC8vIHdpdGhvdXQgYSB0ZXh0IGFycmF5LCBqdXN0IGZvcm1hdCB0aGUgZ2l2ZW4gdmFsdWVzIGFzIGFueSBvdGhlciB0aWNrc1xuICAgIC8vIGV4Y2VwdCB3aXRoIG1vcmUgcHJlY2lzaW9uIHRvIHRoZSBudW1iZXJzXG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGV4dCkpIHRleHQgPSBbXTtcblxuICAgIC8vIG1ha2Ugc3VyZSBzaG93aW5nIHRpY2tzIGRvZXNuJ3QgYWNjaWRlbnRhbGx5IGFkZCBuZXcgY2F0ZWdvcmllc1xuICAgIHZhciB0aWNrVmFsMmwgPSBheC50eXBlID09PSAnY2F0ZWdvcnknID8gYXguZDJsX25vYWRkIDogYXguZDJsO1xuXG4gICAgLy8gYXJyYXkgdGlja3Mgb24gbG9nIGF4ZXMgYWx3YXlzIHNob3cgdGhlIGZ1bGwgbnVtYmVyXG4gICAgLy8gKGlmIG5vIGV4cGxpY2l0IHRpY2t0ZXh0IG92ZXJyaWRlcyBpdClcbiAgICBpZihheC50eXBlID09PSAnbG9nJyAmJiBTdHJpbmcoYXguZHRpY2spLmNoYXJBdCgwKSAhPT0gJ0wnKSB7XG4gICAgICAgIGF4LmR0aWNrID0gJ0wnICsgTWF0aC5wb3coMTAsIE1hdGguZmxvb3IoTWF0aC5taW4oYXgucmFuZ2VbMF0sIGF4LnJhbmdlWzFdKSkgLSAxKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbGkgPSB0aWNrVmFsMmwodmFsc1tpXSk7XG4gICAgICAgIGlmKHZhbGkgPiB0aWNrTWluICYmIHZhbGkgPCB0aWNrTWF4KSB7XG4gICAgICAgICAgICBpZih0ZXh0W2ldID09PSB1bmRlZmluZWQpIHRpY2tzT3V0W2pdID0gYXhlcy50aWNrVGV4dChheCwgdmFsaSk7XG4gICAgICAgICAgICBlbHNlIHRpY2tzT3V0W2pdID0gdGlja1RleHRPYmooYXgsIHZhbGksIFN0cmluZyh0ZXh0W2ldKSk7XG4gICAgICAgICAgICBqKys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihqIDwgdmFscy5sZW5ndGgpIHRpY2tzT3V0LnNwbGljZShqLCB2YWxzLmxlbmd0aCAtIGopO1xuXG4gICAgcmV0dXJuIHRpY2tzT3V0O1xufVxuXG52YXIgcm91bmRCYXNlMTAgPSBbMiwgNSwgMTBdLFxuICAgIHJvdW5kQmFzZTI0ID0gWzEsIDIsIDMsIDYsIDEyXSxcbiAgICByb3VuZEJhc2U2MCA9IFsxLCAyLCA1LCAxMCwgMTUsIDMwXSxcbiAgICAvLyAyJjMgZGF5IHRpY2tzIGFyZSB3ZWlyZCwgYnV0IG5lZWQgc29tZXRoaW5nIGJ0d24gMSY3XG4gICAgcm91bmREYXlzID0gWzEsIDIsIDMsIDcsIDE0XSxcbiAgICAvLyBhcHByb3guIHRpY2sgcG9zaXRpb25zIGZvciBsb2cgYXhlcywgc2hvd2luZyBhbGwgKDEpIGFuZCBqdXN0IDEsIDIsIDUgKDIpXG4gICAgLy8gdGhlc2UgZG9uJ3QgaGF2ZSB0byBiZSBleGFjdCwganVzdCBjbG9zZSBlbm91Z2ggdG8gcm91bmQgdG8gdGhlIHJpZ2h0IHZhbHVlXG4gICAgcm91bmRMb2cxID0gWy0wLjA0NiwgMCwgMC4zMDEsIDAuNDc3LCAwLjYwMiwgMC42OTksIDAuNzc4LCAwLjg0NSwgMC45MDMsIDAuOTU0LCAxXSxcbiAgICByb3VuZExvZzIgPSBbLTAuMzAxLCAwLCAwLjMwMSwgMC42OTksIDFdLFxuICAgIC8vIE4uQi4gYHRoZXRhdW5pdDsgJ3JhZGlhbnMnIGFuZ3VsYXIgYXhlcyBtdXN0IGJlIGNvbnZlcnRlZCB0byBkZWdyZWVzXG4gICAgcm91bmRBbmdsZXMgPSBbMTUsIDMwLCA0NSwgOTAsIDE4MF07XG5cbmZ1bmN0aW9uIHJvdW5kRFRpY2socm91Z2hEVGljaywgYmFzZSwgcm91bmRpbmdTZXQpIHtcbiAgICByZXR1cm4gYmFzZSAqIExpYi5yb3VuZFVwKHJvdWdoRFRpY2sgLyBiYXNlLCByb3VuZGluZ1NldCk7XG59XG5cbi8vIGF1dG9UaWNrczogY2FsY3VsYXRlIGJlc3QgZ3Vlc3MgYXQgcGxlYXNhbnQgdGlja3MgZm9yIHRoaXMgYXhpc1xuLy8gaW5wdXRzOlxuLy8gICAgICBheCAtIGFuIGF4aXMgb2JqZWN0XG4vLyAgICAgIHJvdWdoRFRpY2sgLSByb3VnaCB0aWNrIHNwYWNpbmcgKHRvIGJlIHR1cm5lZCBpbnRvIGEgbmljZSByb3VuZCBudW1iZXIpXG4vLyBvdXRwdXRzIChpbnRvIGF4KTpcbi8vICAgdGljazA6IHN0YXJ0aW5nIHBvaW50IGZvciB0aWNrcyAobm90IG5lY2Vzc2FyaWx5IG9uIHRoZSBncmFwaClcbi8vICAgICAgdXN1YWxseSAwIGZvciBudW1lcmljICg9MTBeMD0xIGZvciBsb2cpIG9yIGphbiAxLCAyMDAwIGZvciBkYXRlc1xuLy8gICBkdGljazogdGhlIGFjdHVhbCwgbmljZSByb3VuZCB0aWNrIHNwYWNpbmcsIHVzdWFsbHkgYSBsaXR0bGUgbGFyZ2VyIHRoYW4gcm91Z2hEVGlja1xuLy8gICAgICBpZiB0aGUgdGlja3MgYXJlIHNwYWNlZCBsaW5lYXJseSAobGluZWFyIHNjYWxlLCBjYXRlZ29yaWVzLFxuLy8gICAgICAgICAgbG9nIHdpdGggb25seSBmdWxsIHBvd2VycywgZGF0ZSB0aWNrcyA8IG1vbnRoKSxcbi8vICAgICAgICAgIHRoaXMgd2lsbCBqdXN0IGJlIGEgbnVtYmVyXG4vLyAgICAgIG1vbnRoczogTSNcbi8vICAgICAgeWVhcnM6IE0jIHdoZXJlICMgaXMgMTIqbnVtYmVyIG9mIHllYXJzXG4vLyAgICAgIGxvZyB3aXRoIGxpbmVhciB0aWNrczogTCMgd2hlcmUgIyBpcyB0aGUgbGluZWFyIHRpY2sgc3BhY2luZ1xuLy8gICAgICBsb2cgc2hvd2luZyBwb3dlcnMgcGx1cyBzb21lIGludGVybWVkaWF0ZXM6XG4vLyAgICAgICAgICBEMSBzaG93cyBhbGwgZGlnaXRzLCBEMiBzaG93cyAyIGFuZCA1XG5heGVzLmF1dG9UaWNrcyA9IGZ1bmN0aW9uKGF4LCByb3VnaERUaWNrKSB7XG4gICAgdmFyIGJhc2U7XG5cbiAgICBmdW5jdGlvbiBnZXRCYXNlKHYpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucG93KHYsIE1hdGguZmxvb3IoTWF0aC5sb2cocm91Z2hEVGljaykgLyBNYXRoLkxOMTApKTtcbiAgICB9XG5cbiAgICBpZihheC50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgYXgudGljazAgPSBMaWIuZGF0ZVRpY2swKGF4LmNhbGVuZGFyKTtcbiAgICAgICAgLy8gdGhlIGNyaXRlcmlhIGJlbG93IGFyZSBhbGwgYmFzZWQgb24gdGhlIHJvdWdoIHNwYWNpbmcgd2UgY2FsY3VsYXRlXG4gICAgICAgIC8vIGJlaW5nID4gaGFsZiBvZiB0aGUgZmluYWwgdW5pdCAtIHNvIHByZWNhbGN1bGF0ZSB0d2ljZSB0aGUgcm91Z2ggdmFsXG4gICAgICAgIHZhciByb3VnaFgyID0gMiAqIHJvdWdoRFRpY2s7XG5cbiAgICAgICAgaWYocm91Z2hYMiA+IE9ORUFWR1lFQVIpIHtcbiAgICAgICAgICAgIHJvdWdoRFRpY2sgLz0gT05FQVZHWUVBUjtcbiAgICAgICAgICAgIGJhc2UgPSBnZXRCYXNlKDEwKTtcbiAgICAgICAgICAgIGF4LmR0aWNrID0gJ00nICsgKDEyICogcm91bmREVGljayhyb3VnaERUaWNrLCBiYXNlLCByb3VuZEJhc2UxMCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocm91Z2hYMiA+IE9ORUFWR01PTlRIKSB7XG4gICAgICAgICAgICByb3VnaERUaWNrIC89IE9ORUFWR01PTlRIO1xuICAgICAgICAgICAgYXguZHRpY2sgPSAnTScgKyByb3VuZERUaWNrKHJvdWdoRFRpY2ssIDEsIHJvdW5kQmFzZTI0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHJvdWdoWDIgPiBPTkVEQVkpIHtcbiAgICAgICAgICAgIGF4LmR0aWNrID0gcm91bmREVGljayhyb3VnaERUaWNrLCBPTkVEQVksIHJvdW5kRGF5cyk7XG4gICAgICAgICAgICAvLyBnZXQgd2VlayB0aWNrcyBvbiBzdW5kYXlcbiAgICAgICAgICAgIC8vIHRoaXMgd2lsbCBhbHNvIG1vdmUgdGhlIGJhc2UgdGljayBvZmYgMjAwMC0wMS0wMSBpZiBkdGljayBpc1xuICAgICAgICAgICAgLy8gMiBvciAzIGRheXMuLi4gYnV0IHRoYXQncyBhIHdlaXJkIGVub3VnaCBjYXNlIHRoYXQgd2UnbGwgaWdub3JlIGl0LlxuICAgICAgICAgICAgYXgudGljazAgPSBMaWIuZGF0ZVRpY2swKGF4LmNhbGVuZGFyLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHJvdWdoWDIgPiBPTkVIT1VSKSB7XG4gICAgICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgT05FSE9VUiwgcm91bmRCYXNlMjQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocm91Z2hYMiA+IE9ORU1JTikge1xuICAgICAgICAgICAgYXguZHRpY2sgPSByb3VuZERUaWNrKHJvdWdoRFRpY2ssIE9ORU1JTiwgcm91bmRCYXNlNjApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocm91Z2hYMiA+IE9ORVNFQykge1xuICAgICAgICAgICAgYXguZHRpY2sgPSByb3VuZERUaWNrKHJvdWdoRFRpY2ssIE9ORVNFQywgcm91bmRCYXNlNjApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gbWlsbGlzZWNvbmRzXG4gICAgICAgICAgICBiYXNlID0gZ2V0QmFzZSgxMCk7XG4gICAgICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgYmFzZSwgcm91bmRCYXNlMTApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYoYXgudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgYXgudGljazAgPSAwO1xuICAgICAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcblxuICAgICAgICBpZihyb3VnaERUaWNrID4gMC43KSB7XG4gICAgICAgICAgICAvLyBvbmx5IHNob3cgcG93ZXJzIG9mIDEwXG4gICAgICAgICAgICBheC5kdGljayA9IE1hdGguY2VpbChyb3VnaERUaWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKE1hdGguYWJzKHJuZ1sxXSAtIHJuZ1swXSkgPCAxKSB7XG4gICAgICAgICAgICAvLyBzcGFuIGlzIGxlc3MgdGhhbiBvbmUgcG93ZXIgb2YgMTBcbiAgICAgICAgICAgIHZhciBudCA9IDEuNSAqIE1hdGguYWJzKChybmdbMV0gLSBybmdbMF0pIC8gcm91Z2hEVGljayk7XG5cbiAgICAgICAgICAgIC8vIHRpY2tzIG9uIGEgbGluZWFyIHNjYWxlLCBsYWJlbGVkIGZ1bGx5XG4gICAgICAgICAgICByb3VnaERUaWNrID0gTWF0aC5hYnMoTWF0aC5wb3coMTAsIHJuZ1sxXSkgLVxuICAgICAgICAgICAgICAgIE1hdGgucG93KDEwLCBybmdbMF0pKSAvIG50O1xuICAgICAgICAgICAgYmFzZSA9IGdldEJhc2UoMTApO1xuICAgICAgICAgICAgYXguZHRpY2sgPSAnTCcgKyByb3VuZERUaWNrKHJvdWdoRFRpY2ssIGJhc2UsIHJvdW5kQmFzZTEwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGluY2x1ZGUgaW50ZXJtZWRpYXRlcyBiZXR3ZWVuIHBvd2VycyBvZiAxMCxcbiAgICAgICAgICAgIC8vIGxhYmVsZWQgd2l0aCBzbWFsbCBkaWdpdHNcbiAgICAgICAgICAgIC8vIGF4LmR0aWNrID0gXCJEMlwiIChzaG93IDIgYW5kIDUpIG9yIFwiRDFcIiAoc2hvdyBhbGwgZGlnaXRzKVxuICAgICAgICAgICAgYXguZHRpY2sgPSAocm91Z2hEVGljayA+IDAuMykgPyAnRDInIDogJ0QxJztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgYXgudGljazAgPSAwO1xuICAgICAgICBheC5kdGljayA9IE1hdGguY2VpbChNYXRoLm1heChyb3VnaERUaWNrLCAxKSk7XG4gICAgfVxuICAgIGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkge1xuICAgICAgICBheC50aWNrMCA9IDA7XG4gICAgICAgIGJhc2UgPSAxO1xuICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgYmFzZSwgcm91bmRBbmdsZXMpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gYXV0byB0aWNrcyBhbHdheXMgc3RhcnQgYXQgMFxuICAgICAgICBheC50aWNrMCA9IDA7XG4gICAgICAgIGJhc2UgPSBnZXRCYXNlKDEwKTtcbiAgICAgICAgYXguZHRpY2sgPSByb3VuZERUaWNrKHJvdWdoRFRpY2ssIGJhc2UsIHJvdW5kQmFzZTEwKTtcbiAgICB9XG5cbiAgICAvLyBwcmV2ZW50IGluZmluaXRlIGxvb3BzXG4gICAgaWYoYXguZHRpY2sgPT09IDApIGF4LmR0aWNrID0gMTtcblxuICAgIC8vIFRPRE86IHRoaXMgaXMgZnJvbSBsb2cgYXhpcyBoaXN0b2dyYW1zIHdpdGggYXV0b3JhbmdlIG9mZlxuICAgIGlmKCFpc051bWVyaWMoYXguZHRpY2spICYmIHR5cGVvZiBheC5kdGljayAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIG9sZGR0aWNrID0gYXguZHRpY2s7XG4gICAgICAgIGF4LmR0aWNrID0gMTtcbiAgICAgICAgdGhyb3cgJ2F4LmR0aWNrIGVycm9yOiAnICsgU3RyaW5nKG9sZGR0aWNrKTtcbiAgICB9XG59O1xuXG4vLyBhZnRlciBkdGljayBpcyBhbHJlYWR5IGtub3duLCBmaW5kIHRpY2tyb3VuZCA9IHByZWNpc2lvblxuLy8gdG8gZGlzcGxheSBpbiB0aWNrIGxhYmVsc1xuLy8gICBmb3IgbnVtZXJpYyB0aWNrcywgaW50ZWdlciAjIGRpZ2l0cyBhZnRlciAuIHRvIHJvdW5kIHRvXG4vLyAgIGZvciBkYXRlIHRpY2tzLCB0aGUgbGFzdCBkYXRlIHBhcnQgdG8gc2hvdyAoeSxtLGQsSCxNLFMpXG4vLyAgICAgIG9yIGFuIGludGVnZXIgIyBkaWdpdHMgcGFzdCBzZWNvbmRzXG5mdW5jdGlvbiBhdXRvVGlja1JvdW5kKGF4KSB7XG4gICAgdmFyIGR0aWNrID0gYXguZHRpY2s7XG5cbiAgICBheC5fdGlja2V4cG9uZW50ID0gMDtcbiAgICBpZighaXNOdW1lcmljKGR0aWNrKSAmJiB0eXBlb2YgZHRpY2sgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGR0aWNrID0gMTtcbiAgICB9XG5cbiAgICBpZihheC50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIGF4Ll90aWNrcm91bmQgPSBudWxsO1xuICAgIH1cbiAgICBpZihheC50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgLy8gSWYgdGljazAgaXMgdW51c3VhbCwgZ2l2ZSB0aWNrcm91bmQgYSBiaXQgbW9yZSBpbmZvcm1hdGlvblxuICAgICAgICAvLyBub3QgbmVjZXNzYXJpbHkgKmFsbCogdGhlIGluZm9ybWF0aW9uIGluIHRpY2swIHRob3VnaCwgaWYgaXQncyByZWFsbHkgb2RkXG4gICAgICAgIC8vIG1pbmltYWwgc3RyaW5nIGxlbmd0aCBmb3IgdGljazA6ICdkJyBpcyAxMCwgJ00nIGlzIDE2LCAnUycgaXMgMTlcbiAgICAgICAgLy8gdGFrZSBvZmYgYSBsZWFkaW5nIG1pbnVzICh5ZWFyIDwgMCkgYW5kIGkgKGludGVyY2FsYXJ5IG1vbnRoKSBzbyBsZW5ndGggaXMgY29uc2lzdGVudFxuICAgICAgICB2YXIgdGljazBtcyA9IGF4LnIybChheC50aWNrMCksXG4gICAgICAgICAgICB0aWNrMHN0ciA9IGF4Lmwycih0aWNrMG1zKS5yZXBsYWNlKC8oXi18aSkvZywgJycpLFxuICAgICAgICAgICAgdGljazBsZW4gPSB0aWNrMHN0ci5sZW5ndGg7XG5cbiAgICAgICAgaWYoU3RyaW5nKGR0aWNrKS5jaGFyQXQoMCkgPT09ICdNJykge1xuICAgICAgICAgICAgLy8gYW55IHRpY2swIG1vcmUgc3BlY2lmaWMgdGhhbiBhIHllYXI6IGFsd2F5IHNob3cgdGhlIGZ1bGwgZGF0ZVxuICAgICAgICAgICAgaWYodGljazBsZW4gPiAxMCB8fCB0aWNrMHN0ci5zdWJzdHIoNSkgIT09ICcwMS0wMScpIGF4Ll90aWNrcm91bmQgPSAnZCc7XG4gICAgICAgICAgICAvLyBzaG93IHRoZSBtb250aCB1bmxlc3MgdGlja3MgYXJlIGZ1bGwgbXVsdGlwbGVzIG9mIGEgeWVhclxuICAgICAgICAgICAgZWxzZSBheC5fdGlja3JvdW5kID0gKCsoZHRpY2suc3Vic3RyKDEpKSAlIDEyID09PSAwKSA/ICd5JyA6ICdtJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKChkdGljayA+PSBPTkVEQVkgJiYgdGljazBsZW4gPD0gMTApIHx8IChkdGljayA+PSBPTkVEQVkgKiAxNSkpIGF4Ll90aWNrcm91bmQgPSAnZCc7XG4gICAgICAgIGVsc2UgaWYoKGR0aWNrID49IE9ORU1JTiAmJiB0aWNrMGxlbiA8PSAxNikgfHwgKGR0aWNrID49IE9ORUhPVVIpKSBheC5fdGlja3JvdW5kID0gJ00nO1xuICAgICAgICBlbHNlIGlmKChkdGljayA+PSBPTkVTRUMgJiYgdGljazBsZW4gPD0gMTkpIHx8IChkdGljayA+PSBPTkVNSU4pKSBheC5fdGlja3JvdW5kID0gJ1MnO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRpY2tyb3VuZCBpcyBhIG51bWJlciBvZiBkaWdpdHMgb2YgZnJhY3Rpb25hbCBzZWNvbmRzXG4gICAgICAgICAgICAvLyBvZiBhbnkgdHdvIGFkamFjZW50IHRpY2tzLCBhdCBsZWFzdCBvbmUgd2lsbCBoYXZlIHRoZSBtYXhpbXVtIGZyYWN0aW9uYWwgZGlnaXRzXG4gICAgICAgICAgICAvLyBvZiBhbGwgcG9zc2libGUgdGlja3MgLSBzbyB0YWtlIHRoZSBtYXguIGxlbmd0aCBvZiB0aWNrMCBhbmQgdGhlIG5leHQgb25lXG4gICAgICAgICAgICB2YXIgdGljazFsZW4gPSBheC5sMnIodGljazBtcyArIGR0aWNrKS5yZXBsYWNlKC9eLS8sICcnKS5sZW5ndGg7XG4gICAgICAgICAgICBheC5fdGlja3JvdW5kID0gTWF0aC5tYXgodGljazBsZW4sIHRpY2sxbGVuKSAtIDIwO1xuXG4gICAgICAgICAgICAvLyBXZSBzaG91bGRuJ3QgZ2V0IGhlcmUuLi4gYnV0IGluIGNhc2UgdGhlcmUncyBhIHNpdHVhdGlvbiBJJ21cbiAgICAgICAgICAgIC8vIG5vdCB0aGlua2luZyBvZiB3aGVyZSB0aWNrMHN0ciBhbmQgdGljazFzdHIgYXJlIGlkZW50aWNhbCBvclxuICAgICAgICAgICAgLy8gc29tZXRoaW5nLCBmYWxsIGJhY2sgb24gbWF4aW11bSBwcmVjaXNpb25cbiAgICAgICAgICAgIGlmKGF4Ll90aWNrcm91bmQgPCAwKSBheC5fdGlja3JvdW5kID0gNDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmKGlzTnVtZXJpYyhkdGljaykgfHwgZHRpY2suY2hhckF0KDApID09PSAnTCcpIHtcbiAgICAgICAgLy8gbGluZWFyIG9yIGxvZyAoZXhjZXB0IEQxLCBEMilcbiAgICAgICAgdmFyIHJuZyA9IGF4LnJhbmdlLm1hcChheC5yMmQgfHwgTnVtYmVyKTtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhkdGljaykpIGR0aWNrID0gTnVtYmVyKGR0aWNrLnN1YnN0cigxKSk7XG4gICAgICAgIC8vIDIgZGlnaXRzIHBhc3QgbGFyZ2VzdCBkaWdpdCBvZiBkdGlja1xuICAgICAgICBheC5fdGlja3JvdW5kID0gMiAtIE1hdGguZmxvb3IoTWF0aC5sb2coZHRpY2spIC8gTWF0aC5MTjEwICsgMC4wMSk7XG5cbiAgICAgICAgdmFyIG1heGVuZCA9IE1hdGgubWF4KE1hdGguYWJzKHJuZ1swXSksIE1hdGguYWJzKHJuZ1sxXSkpO1xuXG4gICAgICAgIHZhciByYW5nZWV4cCA9IE1hdGguZmxvb3IoTWF0aC5sb2cobWF4ZW5kKSAvIE1hdGguTE4xMCArIDAuMDEpO1xuICAgICAgICBpZihNYXRoLmFicyhyYW5nZWV4cCkgPiAzKSB7XG4gICAgICAgICAgICBpZihpc1NJRm9ybWF0KGF4LmV4cG9uZW50Zm9ybWF0KSAmJiAhYmV5b25kU0kocmFuZ2VleHApKSB7XG4gICAgICAgICAgICAgICAgYXguX3RpY2tleHBvbmVudCA9IDMgKiBNYXRoLnJvdW5kKChyYW5nZWV4cCAtIDEpIC8gMyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGF4Ll90aWNrZXhwb25lbnQgPSByYW5nZWV4cDtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBEMSBvciBEMiAobG9nKVxuICAgIGVsc2UgYXguX3RpY2tyb3VuZCA9IG51bGw7XG59XG5cbi8vIG1vbnRocyBhbmQgeWVhcnMgZG9uJ3QgaGF2ZSBjb25zdGFudCBtaWxsaXNlY29uZCB2YWx1ZXNcbi8vIChidXQgYSB5ZWFyIGlzIGFsd2F5cyAxMiBtb250aHMgc28gd2Ugb25seSBuZWVkIG1vbnRocylcbi8vIGxvZy1zY2FsZSB0aWNrcyBhcmUgYWxzbyBub3QgY29uc2lzdGVudGx5IHNwYWNlZCwgZXhjZXB0XG4vLyBmb3IgcHVyZSBwb3dlcnMgb2YgMTBcbi8vIG51bWVyaWMgdGlja3MgYWx3YXlzIGhhdmUgY29uc3RhbnQgZGlmZmVyZW5jZXMsIG90aGVyIGRhdGV0aW1lIHRpY2tzXG4vLyBjYW4gYWxsIGJlIGNhbGN1bGF0ZWQgYXMgY29uc3RhbnQgbnVtYmVyIG9mIG1pbGxpc2Vjb25kc1xuYXhlcy50aWNrSW5jcmVtZW50ID0gZnVuY3Rpb24oeCwgZHRpY2ssIGF4cmV2LCBjYWxlbmRhcikge1xuICAgIHZhciBheFNpZ24gPSBheHJldiA/IC0xIDogMTtcblxuICAgIC8vIGluY2x1ZGVzIGxpbmVhciwgYWxsIGRhdGVzIHNtYWxsZXIgdGhhbiBtb250aCwgYW5kIHB1cmUgMTBebiBpbiBsb2dcbiAgICBpZihpc051bWVyaWMoZHRpY2spKSByZXR1cm4geCArIGF4U2lnbiAqIGR0aWNrO1xuXG4gICAgLy8gZXZlcnl0aGluZyBlbHNlIGlzIGEgc3RyaW5nLCBvbmUgY2hhcmFjdGVyIHBsdXMgYSBudW1iZXJcbiAgICB2YXIgdFR5cGUgPSBkdGljay5jaGFyQXQoMCksXG4gICAgICAgIGR0U2lnbmVkID0gYXhTaWduICogTnVtYmVyKGR0aWNrLnN1YnN0cigxKSk7XG5cbiAgICAvLyBEYXRlczogbW9udGhzIChvciB5ZWFycyAtIHNlZSBMaWIuaW5jcmVtZW50TW9udGgpXG4gICAgaWYodFR5cGUgPT09ICdNJykgcmV0dXJuIExpYi5pbmNyZW1lbnRNb250aCh4LCBkdFNpZ25lZCwgY2FsZW5kYXIpO1xuXG4gICAgLy8gTG9nIHNjYWxlczogTGluZWFyLCBEaWdpdHNcbiAgICBlbHNlIGlmKHRUeXBlID09PSAnTCcpIHJldHVybiBNYXRoLmxvZyhNYXRoLnBvdygxMCwgeCkgKyBkdFNpZ25lZCkgLyBNYXRoLkxOMTA7XG5cbiAgICAvLyBsb2cxMCBvZiAyLDUsMTAsIG9yIGFsbCBkaWdpdHMgKGxvZ3MganVzdCBoYXZlIHRvIGJlXG4gICAgLy8gY2xvc2UgZW5vdWdoIHRvIHJvdW5kKVxuICAgIGVsc2UgaWYodFR5cGUgPT09ICdEJykge1xuICAgICAgICB2YXIgdGlja3NldCA9IChkdGljayA9PT0gJ0QyJykgPyByb3VuZExvZzIgOiByb3VuZExvZzEsXG4gICAgICAgICAgICB4MiA9IHggKyBheFNpZ24gKiAwLjAxLFxuICAgICAgICAgICAgZnJhYyA9IExpYi5yb3VuZFVwKExpYi5tb2QoeDIsIDEpLCB0aWNrc2V0LCBheHJldik7XG5cbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoeDIpICtcbiAgICAgICAgICAgIE1hdGgubG9nKGQzLnJvdW5kKE1hdGgucG93KDEwLCBmcmFjKSwgMSkpIC8gTWF0aC5MTjEwO1xuICAgIH1cbiAgICBlbHNlIHRocm93ICd1bnJlY29nbml6ZWQgZHRpY2sgJyArIFN0cmluZyhkdGljayk7XG59O1xuXG4vLyBjYWxjdWxhdGUgdGhlIGZpcnN0IHRpY2sgb24gYW4gYXhpc1xuYXhlcy50aWNrRmlyc3QgPSBmdW5jdGlvbihheCkge1xuICAgIHZhciByMmwgPSBheC5yMmwgfHwgTnVtYmVyLFxuICAgICAgICBybmcgPSBMaWIuc2ltcGxlTWFwKGF4LnJhbmdlLCByMmwpLFxuICAgICAgICBheHJldiA9IHJuZ1sxXSA8IHJuZ1swXSxcbiAgICAgICAgc1JvdW5kID0gYXhyZXYgPyBNYXRoLmZsb29yIDogTWF0aC5jZWlsLFxuICAgICAgICAvLyBhZGQgYSB0aW55IGV4dHJhIGJpdCB0byBtYWtlIHN1cmUgd2UgZ2V0IHRpY2tzXG4gICAgICAgIC8vIHRoYXQgbWF5IGhhdmUgYmVlbiByb3VuZGVkIG91dFxuICAgICAgICByMCA9IHJuZ1swXSAqIDEuMDAwMSAtIHJuZ1sxXSAqIDAuMDAwMSxcbiAgICAgICAgZHRpY2sgPSBheC5kdGljayxcbiAgICAgICAgdGljazAgPSByMmwoYXgudGljazApO1xuXG4gICAgaWYoaXNOdW1lcmljKGR0aWNrKSkge1xuICAgICAgICB2YXIgdG1pbiA9IHNSb3VuZCgocjAgLSB0aWNrMCkgLyBkdGljaykgKiBkdGljayArIHRpY2swO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSBubyB0aWNrcyBvdXRzaWRlIHRoZSBjYXRlZ29yeSBsaXN0XG4gICAgICAgIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgIHRtaW4gPSBMaWIuY29uc3RyYWluKHRtaW4sIDAsIGF4Ll9jYXRlZ29yaWVzLmxlbmd0aCAtIDEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0bWluO1xuICAgIH1cblxuICAgIHZhciB0VHlwZSA9IGR0aWNrLmNoYXJBdCgwKSxcbiAgICAgICAgZHROdW0gPSBOdW1iZXIoZHRpY2suc3Vic3RyKDEpKTtcblxuICAgIC8vIERhdGVzOiBtb250aHMgKG9yIHllYXJzKVxuICAgIGlmKHRUeXBlID09PSAnTScpIHtcbiAgICAgICAgdmFyIGNudCA9IDAsXG4gICAgICAgICAgICB0MCA9IHRpY2swLFxuICAgICAgICAgICAgdDEsXG4gICAgICAgICAgICBtdWx0LFxuICAgICAgICAgICAgbmV3RFRpY2s7XG5cbiAgICAgICAgLy8gVGhpcyBhbGdvcml0aG0gc2hvdWxkIHdvcmsgZm9yICphbnkqIG5vbmxpbmVhciAoYnV0IGNsb3NlIHRvIGxpbmVhciEpXG4gICAgICAgIC8vIHRpY2sgc3BhY2luZy4gTGltaXQgdG8gMTAgaXRlcmF0aW9ucywgZm9yIGdyZWdvcmlhbiBtb250aHMgaXQncyBub3JtYWxseSA8PTMuXG4gICAgICAgIHdoaWxlKGNudCA8IDEwKSB7XG4gICAgICAgICAgICB0MSA9IGF4ZXMudGlja0luY3JlbWVudCh0MCwgZHRpY2ssIGF4cmV2LCBheC5jYWxlbmRhcik7XG4gICAgICAgICAgICBpZigodDEgLSByMCkgKiAodDAgLSByMCkgPD0gMCkge1xuICAgICAgICAgICAgICAgIC8vIHQxIGFuZCB0MCBhcmUgb24gb3Bwb3NpdGUgc2lkZXMgb2YgcjAhIHdlJ3ZlIHN1Y2NlZWRlZCFcbiAgICAgICAgICAgICAgICBpZihheHJldikgcmV0dXJuIE1hdGgubWluKHQwLCB0MSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KHQwLCB0MSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtdWx0ID0gKHIwIC0gKCh0MCArIHQxKSAvIDIpKSAvICh0MSAtIHQwKTtcbiAgICAgICAgICAgIG5ld0RUaWNrID0gdFR5cGUgKyAoKE1hdGguYWJzKE1hdGgucm91bmQobXVsdCkpIHx8IDEpICogZHROdW0pO1xuICAgICAgICAgICAgdDAgPSBheGVzLnRpY2tJbmNyZW1lbnQodDAsIG5ld0RUaWNrLCBtdWx0IDwgMCA/ICFheHJldiA6IGF4cmV2LCBheC5jYWxlbmRhcik7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgfVxuICAgICAgICBMaWIuZXJyb3IoJ3RpY2tGaXJzdCBkaWQgbm90IGNvbnZlcmdlJywgYXgpO1xuICAgICAgICByZXR1cm4gdDA7XG4gICAgfVxuXG4gICAgLy8gTG9nIHNjYWxlczogTGluZWFyLCBEaWdpdHNcbiAgICBlbHNlIGlmKHRUeXBlID09PSAnTCcpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubG9nKHNSb3VuZChcbiAgICAgICAgICAgIChNYXRoLnBvdygxMCwgcjApIC0gdGljazApIC8gZHROdW0pICogZHROdW0gKyB0aWNrMCkgLyBNYXRoLkxOMTA7XG4gICAgfVxuICAgIGVsc2UgaWYodFR5cGUgPT09ICdEJykge1xuICAgICAgICB2YXIgdGlja3NldCA9IChkdGljayA9PT0gJ0QyJykgPyByb3VuZExvZzIgOiByb3VuZExvZzEsXG4gICAgICAgICAgICBmcmFjID0gTGliLnJvdW5kVXAoTGliLm1vZChyMCwgMSksIHRpY2tzZXQsIGF4cmV2KTtcblxuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihyMCkgK1xuICAgICAgICAgICAgTWF0aC5sb2coZDMucm91bmQoTWF0aC5wb3coMTAsIGZyYWMpLCAxKSkgLyBNYXRoLkxOMTA7XG4gICAgfVxuICAgIGVsc2UgdGhyb3cgJ3VucmVjb2duaXplZCBkdGljayAnICsgU3RyaW5nKGR0aWNrKTtcbn07XG5cbi8vIGRyYXcgdGhlIHRleHQgZm9yIG9uZSB0aWNrLlxuLy8gcHgscHkgYXJlIHRoZSBsb2NhdGlvbiBvbiBnZC5wYXBlclxuLy8gcHJlZml4IGlzIHRoZXJlIHNvIHRoZSB4IGF4aXMgdGlja3MgY2FuIGJlIGRyb3BwZWQgYSBsaW5lXG4vLyBheCBpcyB0aGUgYXhpcyBsYXlvdXQsIHggaXMgdGhlIHRpY2sgdmFsdWVcbi8vIGhvdmVyIGlzIGEgKHRydXRoeSkgZmxhZyBmb3Igd2hldGhlciB0byBzaG93IG51bWJlcnMgd2l0aCBhIGJpdFxuLy8gbW9yZSBwcmVjaXNpb24gZm9yIGhvdmVydGV4dFxuYXhlcy50aWNrVGV4dCA9IGZ1bmN0aW9uKGF4LCB4LCBob3Zlcikge1xuICAgIHZhciBvdXQgPSB0aWNrVGV4dE9iaihheCwgeCksXG4gICAgICAgIGhpZGVleHAsXG4gICAgICAgIGFycmF5TW9kZSA9IGF4LnRpY2ttb2RlID09PSAnYXJyYXknLFxuICAgICAgICBleHRyYVByZWNpc2lvbiA9IGhvdmVyIHx8IGFycmF5TW9kZSxcbiAgICAgICAgaSxcbiAgICAgICAgdGlja1ZhbDJsID0gYXgudHlwZSA9PT0gJ2NhdGVnb3J5JyA/IGF4LmQybF9ub2FkZCA6IGF4LmQybDtcblxuICAgIGlmKGFycmF5TW9kZSAmJiBBcnJheS5pc0FycmF5KGF4LnRpY2t0ZXh0KSkge1xuICAgICAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKSxcbiAgICAgICAgICAgIG1pbkRpZmYgPSBNYXRoLmFicyhybmdbMV0gLSBybmdbMF0pIC8gMTAwMDA7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF4LnRpY2t0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihNYXRoLmFicyh4IC0gdGlja1ZhbDJsKGF4LnRpY2t2YWxzW2ldKSkgPCBtaW5EaWZmKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZihpIDwgYXgudGlja3RleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBvdXQudGV4dCA9IFN0cmluZyhheC50aWNrdGV4dFtpXSk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNIaWRkZW4oc2hvd0F0dHIpIHtcbiAgICAgICAgdmFyIGZpcnN0X29yX2xhc3Q7XG5cbiAgICAgICAgaWYoc2hvd0F0dHIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmKGhvdmVyKSByZXR1cm4gc2hvd0F0dHIgPT09ICdub25lJztcblxuICAgICAgICBmaXJzdF9vcl9sYXN0ID0ge1xuICAgICAgICAgICAgZmlyc3Q6IGF4Ll90bWluLFxuICAgICAgICAgICAgbGFzdDogYXguX3RtYXhcbiAgICAgICAgfVtzaG93QXR0cl07XG5cbiAgICAgICAgcmV0dXJuIHNob3dBdHRyICE9PSAnYWxsJyAmJiB4ICE9PSBmaXJzdF9vcl9sYXN0O1xuICAgIH1cblxuICAgIGlmKGhvdmVyKSB7XG4gICAgICAgIGhpZGVleHAgPSAnbmV2ZXInO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhpZGVleHAgPSBheC5leHBvbmVudGZvcm1hdCAhPT0gJ25vbmUnICYmIGlzSGlkZGVuKGF4LnNob3dleHBvbmVudCkgPyAnaGlkZScgOiAnJztcbiAgICB9XG5cbiAgICBpZihheC50eXBlID09PSAnZGF0ZScpIGZvcm1hdERhdGUoYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uKTtcbiAgICBlbHNlIGlmKGF4LnR5cGUgPT09ICdsb2cnKSBmb3JtYXRMb2coYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKTtcbiAgICBlbHNlIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIGZvcm1hdENhdGVnb3J5KGF4LCBvdXQpO1xuICAgIGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkgZm9ybWF0QW5nbGUoYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKTtcbiAgICBlbHNlIGZvcm1hdExpbmVhcihheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24sIGhpZGVleHApO1xuXG4gICAgLy8gYWRkIHByZWZpeCBhbmQgc3VmZml4XG4gICAgaWYoYXgudGlja3ByZWZpeCAmJiAhaXNIaWRkZW4oYXguc2hvd3RpY2twcmVmaXgpKSBvdXQudGV4dCA9IGF4LnRpY2twcmVmaXggKyBvdXQudGV4dDtcbiAgICBpZihheC50aWNrc3VmZml4ICYmICFpc0hpZGRlbihheC5zaG93dGlja3N1ZmZpeCkpIG91dC50ZXh0ICs9IGF4LnRpY2tzdWZmaXg7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBjcmVhdGUgdGV4dCBmb3IgYSBob3ZlciBsYWJlbCBvbiB0aGlzIGF4aXMsIHdpdGggc3BlY2lhbCBoYW5kbGluZyBvZlxuICogbG9nIGF4ZXMgKHdoZXJlIG5lZ2F0aXZlIHZhbHVlcyBjYW4ndCBiZSBkaXNwbGF5ZWQgYnV0IGNhbiBhcHBlYXIgaW4gaG92ZXIgdGV4dClcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gYXg6IHRoZSBheGlzIHRvIGZvcm1hdCB0ZXh0IGZvclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbDogY2FsY2RhdGEgdmFsdWUgdG8gZm9ybWF0XG4gKiBAcGFyYW0ge09wdGlvbmFsKG51bWJlcil9IHZhbDI6IGEgc2Vjb25kIHZhbHVlIHRvIGRpc3BsYXlcbiAqXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBgdmFsYCBmb3JtYXR0ZWQgYXMgYSBzdHJpbmcgYXBwcm9wcmlhdGUgdG8gdGhpcyBheGlzLCBvclxuICogICAgIGB2YWxgIGFuZCBgdmFsMmAgYXMgYSByYW5nZSAoaWUgJzx2YWw+IC0gPHZhbDI+JykgaWYgYHZhbDJgIGlzIHByb3ZpZGVkIGFuZFxuICogICAgIGl0J3MgZGlmZmVyZW50IGZyb20gYHZhbGAuXG4gKi9cbmF4ZXMuaG92ZXJMYWJlbFRleHQgPSBmdW5jdGlvbihheCwgdmFsLCB2YWwyKSB7XG4gICAgaWYodmFsMiAhPT0gQkFETlVNICYmIHZhbDIgIT09IHZhbCkge1xuICAgICAgICByZXR1cm4gYXhlcy5ob3ZlckxhYmVsVGV4dChheCwgdmFsKSArICcgLSAnICsgYXhlcy5ob3ZlckxhYmVsVGV4dChheCwgdmFsMik7XG4gICAgfVxuXG4gICAgdmFyIGxvZ09mZlNjYWxlID0gKGF4LnR5cGUgPT09ICdsb2cnICYmIHZhbCA8PSAwKTtcbiAgICB2YXIgdHggPSBheGVzLnRpY2tUZXh0KGF4LCBheC5jMmwobG9nT2ZmU2NhbGUgPyAtdmFsIDogdmFsKSwgJ2hvdmVyJykudGV4dDtcblxuICAgIGlmKGxvZ09mZlNjYWxlKSB7XG4gICAgICAgIHJldHVybiB2YWwgPT09IDAgPyAnMCcgOiBNSU5VU19TSUdOICsgdHg7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogc2hvdWxkIHdlIGRvIHNvbWV0aGluZyBzcGVjaWFsIGlmIHRoZSBheGlzIGNhbGVuZGFyIGFuZFxuICAgIC8vIHRoZSBkYXRhIGNhbGVuZGFyIGFyZSBkaWZmZXJlbnQ/IFNvbWVob3cgZGlzcGxheSBib3RoIGRhdGVzIHdpdGhcbiAgICAvLyB0aGVpciBzeXN0ZW0gbmFtZXM/IFJpZ2h0IG5vdyBpdCB3aWxsIGp1c3QgZGlzcGxheSBpbiB0aGUgYXhpcyBjYWxlbmRhclxuICAgIC8vIGJ1dCB1c2VycyBjb3VsZCBhZGQgdGhlIG90aGVyIG9uZSBhcyB0ZXh0LlxuICAgIHJldHVybiB0eDtcbn07XG5cbmZ1bmN0aW9uIHRpY2tUZXh0T2JqKGF4LCB4LCB0ZXh0KSB7XG4gICAgdmFyIHRmID0gYXgudGlja2ZvbnQgfHwge307XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4OiB4LFxuICAgICAgICBkeDogMCxcbiAgICAgICAgZHk6IDAsXG4gICAgICAgIHRleHQ6IHRleHQgfHwgJycsXG4gICAgICAgIGZvbnRTaXplOiB0Zi5zaXplLFxuICAgICAgICBmb250OiB0Zi5mYW1pbHksXG4gICAgICAgIGZvbnRDb2xvcjogdGYuY29sb3JcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBmb3JtYXREYXRlKGF4LCBvdXQsIGhvdmVyLCBleHRyYVByZWNpc2lvbikge1xuICAgIHZhciB0ciA9IGF4Ll90aWNrcm91bmQsXG4gICAgICAgIGZtdCA9IChob3ZlciAmJiBheC5ob3ZlcmZvcm1hdCkgfHwgYXhlcy5nZXRUaWNrRm9ybWF0KGF4KTtcblxuICAgIGlmKGV4dHJhUHJlY2lzaW9uKSB7XG4gICAgICAgIC8vIHNlY29uZCBvciBzdWItc2Vjb25kIHByZWNpc2lvbjogZXh0cmEgYWx3YXlzIHNob3dzIG1heCBkaWdpdHMuXG4gICAgICAgIC8vIGZvciBvdGhlciBmaWVsZHMsIGV4dHJhIHByZWNpc2lvbiBqdXN0IGFkZHMgb25lIGZpZWxkLlxuICAgICAgICBpZihpc051bWVyaWModHIpKSB0ciA9IDQ7XG4gICAgICAgIGVsc2UgdHIgPSB7eTogJ20nLCBtOiAnZCcsIGQ6ICdNJywgTTogJ1MnLCBTOiA0fVt0cl07XG4gICAgfVxuXG4gICAgdmFyIGRhdGVTdHIgPSBMaWIuZm9ybWF0RGF0ZShvdXQueCwgZm10LCB0ciwgYXguX2RhdGVGb3JtYXQsIGF4LmNhbGVuZGFyLCBheC5fZXh0cmFGb3JtYXQpLFxuICAgICAgICBoZWFkU3RyO1xuXG4gICAgdmFyIHNwbGl0SW5kZXggPSBkYXRlU3RyLmluZGV4T2YoJ1xcbicpO1xuICAgIGlmKHNwbGl0SW5kZXggIT09IC0xKSB7XG4gICAgICAgIGhlYWRTdHIgPSBkYXRlU3RyLnN1YnN0cihzcGxpdEluZGV4ICsgMSk7XG4gICAgICAgIGRhdGVTdHIgPSBkYXRlU3RyLnN1YnN0cigwLCBzcGxpdEluZGV4KTtcbiAgICB9XG5cbiAgICBpZihleHRyYVByZWNpc2lvbikge1xuICAgICAgICAvLyBpZiBleHRyYVByZWNpc2lvbiBsZWQgdG8gdHJhaWxpbmcgemVyb3MsIHN0cmlwIHRoZW0gb2ZmXG4gICAgICAgIC8vIGFjdHVhbGx5LCB0aGlzIGNhbiBsZWFkIHRvIHJlbW92aW5nIGV2ZW4gbW9yZSB6ZXJvcyB0aGFuXG4gICAgICAgIC8vIGluIHRoZSBvcmlnaW5hbCByb3VuZGluZywgYnV0IHRoYXQncyBmaW5lIGJlY2F1c2UgaW4gdGhlc2VcbiAgICAgICAgLy8gY29udGV4dHMgdW5pZm9ybWl0eSBpcyBub3Qgc28gaW1wb3J0YW50IChpZiB0aGVyZSdzIGV2ZW5cbiAgICAgICAgLy8gYW55dGhpbmcgdG8gYmUgdW5pZm9ybSB3aXRoISlcblxuICAgICAgICAvLyBjYW4gd2UgcmVtb3ZlIHRoZSB3aG9sZSB0aW1lIHBhcnQ/XG4gICAgICAgIGlmKGRhdGVTdHIgPT09ICcwMDowMDowMCcgfHwgZGF0ZVN0ciA9PT0gJzAwOjAwJykge1xuICAgICAgICAgICAgZGF0ZVN0ciA9IGhlYWRTdHI7XG4gICAgICAgICAgICBoZWFkU3RyID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihkYXRlU3RyLmxlbmd0aCA9PT0gOCkge1xuICAgICAgICAgICAgLy8gc3RyaXAgb2ZmIHNlY29uZHMgaWYgdGhleSdyZSB6ZXJvICh6ZXJvIGZyYWN0aW9uYWwgc2Vjb25kc1xuICAgICAgICAgICAgLy8gYXJlIGFscmVhZHkgb21pdHRlZClcbiAgICAgICAgICAgIC8vIGJ1dCB3ZSBuZXZlciByZW1vdmUgbWludXRlcyBhbmQgbGVhdmUganVzdCBob3Vyc1xuICAgICAgICAgICAgZGF0ZVN0ciA9IGRhdGVTdHIucmVwbGFjZSgvOjAwJC8sICcnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGhlYWRTdHIpIHtcbiAgICAgICAgaWYoaG92ZXIpIHtcbiAgICAgICAgICAgIC8vIGhvdmVyIHB1dHMgaXQgYWxsIG9uIG9uZSBsaW5lLCBzbyBoZWFkUGFydCB3b3JrcyBiZXN0IHVwIGZyb250XG4gICAgICAgICAgICAvLyBleGNlcHQgZm9yIHllYXIgaGVhZFBhcnQ6IHR1cm4gdGhpcyBpbnRvIFwiSmFuIDEsIDIwMDBcIiBldGMuXG4gICAgICAgICAgICBpZih0ciA9PT0gJ2QnKSBkYXRlU3RyICs9ICcsICcgKyBoZWFkU3RyO1xuICAgICAgICAgICAgZWxzZSBkYXRlU3RyID0gaGVhZFN0ciArIChkYXRlU3RyID8gJywgJyArIGRhdGVTdHIgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZighYXguX2luQ2FsY1RpY2tzIHx8IChoZWFkU3RyICE9PSBheC5fcHJldkRhdGVIZWFkKSkge1xuICAgICAgICAgICAgZGF0ZVN0ciArPSAnPGJyPicgKyBoZWFkU3RyO1xuICAgICAgICAgICAgYXguX3ByZXZEYXRlSGVhZCA9IGhlYWRTdHI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvdXQudGV4dCA9IGRhdGVTdHI7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdExvZyhheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24sIGhpZGVleHApIHtcbiAgICB2YXIgZHRpY2sgPSBheC5kdGljaztcbiAgICB2YXIgeCA9IG91dC54O1xuICAgIHZhciB0aWNrZm9ybWF0ID0gYXgudGlja2Zvcm1hdDtcbiAgICB2YXIgZHRDaGFyMCA9IHR5cGVvZiBkdGljayA9PT0gJ3N0cmluZycgJiYgZHRpY2suY2hhckF0KDApO1xuXG4gICAgaWYoaGlkZWV4cCA9PT0gJ25ldmVyJykge1xuICAgICAgICAvLyBJZiB0aGlzIGlzIGEgaG92ZXIgbGFiZWwsIHRoZW4gd2UgbXVzdCAqbmV2ZXIqIGhpZGUgdGhlIGV4cG9uZW50XG4gICAgICAgIC8vIGZvciB0aGUgc2FrZSBvZiBkaXNwbGF5LCB3aGljaCBjb3VsZCBnaXZlIHRoZSB3cm9uZyB2YWx1ZSBieVxuICAgICAgICAvLyBwb3RlbnRpYWxseSBtYW55IG9yZGVycyBvZiBtYWduaXR1ZGUuIElmIGhpZGVleHAgd2FzICduZXZlcicsIHRoZW5cbiAgICAgICAgLy8gaXQncyBub3cgc3VjY2VlZGVkIGJ5IHByZXZlbnRpbmcgdGhlIG90aGVyIGNvbmRpdGlvbiBmcm9tIGF1dG9tYXRpbmdcbiAgICAgICAgLy8gdGhpcyBjaG9pY2UuIFRodXMgd2UgY2FuIHVuc2V0IGl0IHNvIHRoYXQgdGhlIGF4aXMgZm9ybWF0dGluZyB0YWtlc1xuICAgICAgICAvLyBwcmVjZWRlbmNlLlxuICAgICAgICBoaWRlZXhwID0gJyc7XG4gICAgfVxuXG4gICAgaWYoZXh0cmFQcmVjaXNpb24gJiYgKGR0Q2hhcjAgIT09ICdMJykpIHtcbiAgICAgICAgZHRpY2sgPSAnTDMnO1xuICAgICAgICBkdENoYXIwID0gJ0wnO1xuICAgIH1cblxuICAgIGlmKHRpY2tmb3JtYXQgfHwgKGR0Q2hhcjAgPT09ICdMJykpIHtcbiAgICAgICAgb3V0LnRleHQgPSBudW1Gb3JtYXQoTWF0aC5wb3coMTAsIHgpLCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xuICAgIH1cbiAgICBlbHNlIGlmKGlzTnVtZXJpYyhkdGljaykgfHwgKChkdENoYXIwID09PSAnRCcpICYmIChMaWIubW9kKHggKyAwLjAxLCAxKSA8IDAuMSkpKSB7XG4gICAgICAgIHZhciBwID0gTWF0aC5yb3VuZCh4KTtcbiAgICAgICAgdmFyIGFic1AgPSBNYXRoLmFicyhwKTtcbiAgICAgICAgdmFyIGV4cG9uZW50Rm9ybWF0ID0gYXguZXhwb25lbnRmb3JtYXQ7XG4gICAgICAgIGlmKGV4cG9uZW50Rm9ybWF0ID09PSAncG93ZXInIHx8IChpc1NJRm9ybWF0KGV4cG9uZW50Rm9ybWF0KSAmJiBiZXlvbmRTSShwKSkpIHtcbiAgICAgICAgICAgIGlmKHAgPT09IDApIG91dC50ZXh0ID0gMTtcbiAgICAgICAgICAgIGVsc2UgaWYocCA9PT0gMSkgb3V0LnRleHQgPSAnMTAnO1xuICAgICAgICAgICAgZWxzZSBvdXQudGV4dCA9ICcxMDxzdXA+JyArIChwID4gMSA/ICcnIDogTUlOVVNfU0lHTikgKyBhYnNQICsgJzwvc3VwPic7XG5cbiAgICAgICAgICAgIG91dC5mb250U2l6ZSAqPSAxLjI1O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoKGV4cG9uZW50Rm9ybWF0ID09PSAnZScgfHwgZXhwb25lbnRGb3JtYXQgPT09ICdFJykgJiYgYWJzUCA+IDIpIHtcbiAgICAgICAgICAgIG91dC50ZXh0ID0gJzEnICsgZXhwb25lbnRGb3JtYXQgKyAocCA+IDAgPyAnKycgOiBNSU5VU19TSUdOKSArIGFic1A7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvdXQudGV4dCA9IG51bUZvcm1hdChNYXRoLnBvdygxMCwgeCksIGF4LCAnJywgJ2Zha2Vob3ZlcicpO1xuICAgICAgICAgICAgaWYoZHRpY2sgPT09ICdEMScgJiYgYXguX2lkLmNoYXJBdCgwKSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgb3V0LmR5IC09IG91dC5mb250U2l6ZSAvIDY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZihkdENoYXIwID09PSAnRCcpIHtcbiAgICAgICAgb3V0LnRleHQgPSBTdHJpbmcoTWF0aC5yb3VuZChNYXRoLnBvdygxMCwgTGliLm1vZCh4LCAxKSkpKTtcbiAgICAgICAgb3V0LmZvbnRTaXplICo9IDAuNzU7XG4gICAgfVxuICAgIGVsc2UgdGhyb3cgJ3VucmVjb2duaXplZCBkdGljayAnICsgU3RyaW5nKGR0aWNrKTtcblxuICAgIC8vIGlmIDkncyBhcmUgcHJpbnRlZCBvbiBsb2cgc2NhbGUsIG1vdmUgdGhlIDEwJ3MgYXdheSBhIGJpdFxuICAgIGlmKGF4LmR0aWNrID09PSAnRDEnKSB7XG4gICAgICAgIHZhciBmaXJzdENoYXIgPSBTdHJpbmcob3V0LnRleHQpLmNoYXJBdCgwKTtcbiAgICAgICAgaWYoZmlyc3RDaGFyID09PSAnMCcgfHwgZmlyc3RDaGFyID09PSAnMScpIHtcbiAgICAgICAgICAgIGlmKGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIG91dC5keCAtPSBvdXQuZm9udFNpemUgLyA0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgb3V0LmR5ICs9IG91dC5mb250U2l6ZSAvIDI7XG4gICAgICAgICAgICAgICAgb3V0LmR4ICs9IChheC5yYW5nZVsxXSA+IGF4LnJhbmdlWzBdID8gMSA6IC0xKSAqXG4gICAgICAgICAgICAgICAgICAgIG91dC5mb250U2l6ZSAqICh4IDwgMCA/IDAuNSA6IDAuMjUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXRDYXRlZ29yeShheCwgb3V0KSB7XG4gICAgdmFyIHR0ID0gYXguX2NhdGVnb3JpZXNbTWF0aC5yb3VuZChvdXQueCldO1xuICAgIGlmKHR0ID09PSB1bmRlZmluZWQpIHR0ID0gJyc7XG4gICAgb3V0LnRleHQgPSBTdHJpbmcodHQpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRMaW5lYXIoYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKSB7XG4gICAgaWYoaGlkZWV4cCA9PT0gJ25ldmVyJykge1xuICAgICAgICAvLyBJZiB0aGlzIGlzIGEgaG92ZXIgbGFiZWwsIHRoZW4gd2UgbXVzdCAqbmV2ZXIqIGhpZGUgdGhlIGV4cG9uZW50XG4gICAgICAgIC8vIGZvciB0aGUgc2FrZSBvZiBkaXNwbGF5LCB3aGljaCBjb3VsZCBnaXZlIHRoZSB3cm9uZyB2YWx1ZSBieVxuICAgICAgICAvLyBwb3RlbnRpYWxseSBtYW55IG9yZGVycyBvZiBtYWduaXR1ZGUuIElmIGhpZGVleHAgd2FzICduZXZlcicsIHRoZW5cbiAgICAgICAgLy8gaXQncyBub3cgc3VjY2VlZGVkIGJ5IHByZXZlbnRpbmcgdGhlIG90aGVyIGNvbmRpdGlvbiBmcm9tIGF1dG9tYXRpbmdcbiAgICAgICAgLy8gdGhpcyBjaG9pY2UuIFRodXMgd2UgY2FuIHVuc2V0IGl0IHNvIHRoYXQgdGhlIGF4aXMgZm9ybWF0dGluZyB0YWtlc1xuICAgICAgICAvLyBwcmVjZWRlbmNlLlxuICAgICAgICBoaWRlZXhwID0gJyc7XG4gICAgfSBlbHNlIGlmKGF4LnNob3dleHBvbmVudCA9PT0gJ2FsbCcgJiYgTWF0aC5hYnMob3V0LnggLyBheC5kdGljaykgPCAxZS02KSB7XG4gICAgICAgIC8vIGRvbid0IGFkZCBhbiBleHBvbmVudCB0byB6ZXJvIGlmIHdlJ3JlIHNob3dpbmcgYWxsIGV4cG9uZW50c1xuICAgICAgICAvLyBzbyB0aGUgb25seSByZWFzb24geW91J2Qgc2hvdyBhbiBleHBvbmVudCBvbiB6ZXJvIGlzIGlmIGl0J3MgdGhlXG4gICAgICAgIC8vIE9OTFkgdGljayB0byBnZXQgYW4gZXhwb25lbnQgKGZpcnN0IG9yIGxhc3QpXG4gICAgICAgIGhpZGVleHAgPSAnaGlkZSc7XG4gICAgfVxuICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KG91dC54LCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBbmdsZShheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24sIGhpZGVleHApIHtcbiAgICBpZihheC50aGV0YXVuaXQgPT09ICdyYWRpYW5zJyAmJiAhaG92ZXIpIHtcbiAgICAgICAgdmFyIG51bSA9IG91dC54IC8gMTgwO1xuXG4gICAgICAgIGlmKG51bSA9PT0gMCkge1xuICAgICAgICAgICAgb3V0LnRleHQgPSAnMCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgZnJhYyA9IG51bTJmcmFjKG51bSk7XG5cbiAgICAgICAgICAgIGlmKGZyYWNbMV0gPj0gMTAwKSB7XG4gICAgICAgICAgICAgICAgb3V0LnRleHQgPSBudW1Gb3JtYXQoTGliLmRlZzJyYWQob3V0LngpLCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgaXNOZWcgPSBvdXQueCA8IDA7XG5cbiAgICAgICAgICAgICAgICBpZihmcmFjWzFdID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGZyYWNbMF0gPT09IDEpIG91dC50ZXh0ID0gJ8+AJztcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBvdXQudGV4dCA9IGZyYWNbMF0gKyAnz4AnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC50ZXh0ID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgJzxzdXA+JywgZnJhY1swXSwgJzwvc3VwPicsXG4gICAgICAgICAgICAgICAgICAgICAgICAn4oGEJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICc8c3ViPicsIGZyYWNbMV0sICc8L3N1Yj4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ8+AJ1xuICAgICAgICAgICAgICAgICAgICBdLmpvaW4oJycpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGlzTmVnKSBvdXQudGV4dCA9IE1JTlVTX1NJR04gKyBvdXQudGV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KG91dC54LCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xuICAgIH1cbn1cblxuLy8gaW5zcGlyZWQgYnlcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS95aXNpYmwvbnVtMmZyYWN0aW9uL2Jsb2IvbWFzdGVyL2luZGV4LmpzXG5mdW5jdGlvbiBudW0yZnJhYyhudW0pIHtcbiAgICBmdW5jdGlvbiBhbG1vc3RFcShhLCBiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmFicyhhIC0gYikgPD0gMWUtNjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaW5kR0NEKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFsbW9zdEVxKGIsIDApID8gYSA6IGZpbmRHQ0QoYiwgYSAlIGIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbmRQcmVjaXNpb24obikge1xuICAgICAgICB2YXIgZSA9IDE7XG4gICAgICAgIHdoaWxlKCFhbG1vc3RFcShNYXRoLnJvdW5kKG4gKiBlKSAvIGUsIG4pKSB7XG4gICAgICAgICAgICBlICo9IDEwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlO1xuICAgIH1cblxuICAgIHZhciBwcmVjaXNpb24gPSBmaW5kUHJlY2lzaW9uKG51bSk7XG4gICAgdmFyIG51bWJlciA9IG51bSAqIHByZWNpc2lvbjtcbiAgICB2YXIgZ2NkID0gTWF0aC5hYnMoZmluZEdDRChudW1iZXIsIHByZWNpc2lvbikpO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgICAgLy8gbnVtZXJhdG9yXG4gICAgICAgIE1hdGgucm91bmQobnVtYmVyIC8gZ2NkKSxcbiAgICAgICAgLy8gZGVub21pbmF0b3JcbiAgICAgICAgTWF0aC5yb3VuZChwcmVjaXNpb24gLyBnY2QpXG4gICAgXTtcbn1cblxuLy8gZm9ybWF0IGEgbnVtYmVyICh0aWNrIHZhbHVlKSBhY2NvcmRpbmcgdG8gdGhlIGF4aXMgc2V0dGluZ3Ncbi8vIG5ldywgbW9yZSByZWxpYWJsZSBwcm9jZWR1cmUgdGhhbiBkMy5yb3VuZCBvciBzaW1pbGFyOlxuLy8gYWRkIGhhbGYgdGhlIHJvdW5kaW5nIGluY3JlbWVudCwgdGhlbiBzdHJpbmdpZnkgYW5kIHRydW5jYXRlXG4vLyBhbHNvIGF1dG9tYXRpY2FsbHkgc3dpdGNoIHRvIHNjaS4gbm90YXRpb25cbnZhciBTSVBSRUZJWEVTID0gWydmJywgJ3AnLCAnbicsICfOvCcsICdtJywgJycsICdrJywgJ00nLCAnRycsICdUJ107XG5cbmZ1bmN0aW9uIGlzU0lGb3JtYXQoZXhwb25lbnRGb3JtYXQpIHtcbiAgICByZXR1cm4gZXhwb25lbnRGb3JtYXQgPT09ICdTSScgfHwgZXhwb25lbnRGb3JtYXQgPT09ICdCJztcbn1cblxuLy8gYXJlIHdlIGJleW9uZCB0aGUgcmFuZ2Ugb2YgY29tbW9uIFNJIHByZWZpeGVzP1xuLy8gMTBeLTE2IC0+IDF4MTBeLTE2XG4vLyAxMF4tMTUgLT4gMWZcbi8vIC4uLlxuLy8gMTBeMTQgLT4gMTAwVFxuLy8gMTBeMTUgLT4gMXgxMF4xNVxuLy8gMTBeMTYgLT4gMXgxMF4xNlxuZnVuY3Rpb24gYmV5b25kU0koZXhwb25lbnQpIHtcbiAgICByZXR1cm4gZXhwb25lbnQgPiAxNCB8fCBleHBvbmVudCA8IC0xNTtcbn1cblxuZnVuY3Rpb24gbnVtRm9ybWF0KHYsIGF4LCBmbXRvdmVycmlkZSwgaG92ZXIpIHtcbiAgICAgICAgLy8gbmVnYXRpdmU/XG4gICAgdmFyIGlzTmVnID0gdiA8IDAsXG4gICAgICAgIC8vIG1heCBudW1iZXIgb2YgZGlnaXRzIHBhc3QgZGVjaW1hbCBwb2ludCB0byBzaG93XG4gICAgICAgIHRpY2tSb3VuZCA9IGF4Ll90aWNrcm91bmQsXG4gICAgICAgIGV4cG9uZW50Rm9ybWF0ID0gZm10b3ZlcnJpZGUgfHwgYXguZXhwb25lbnRmb3JtYXQgfHwgJ0InLFxuICAgICAgICBleHBvbmVudCA9IGF4Ll90aWNrZXhwb25lbnQsXG4gICAgICAgIHRpY2tmb3JtYXQgPSBheGVzLmdldFRpY2tGb3JtYXQoYXgpLFxuICAgICAgICBzZXBhcmF0ZXRob3VzYW5kcyA9IGF4LnNlcGFyYXRldGhvdXNhbmRzO1xuXG4gICAgLy8gc3BlY2lhbCBjYXNlIGZvciBob3Zlcjogc2V0IGV4cG9uZW50IGp1c3QgZm9yIHRoaXMgdmFsdWUsIGFuZFxuICAgIC8vIGFkZCBhIGNvdXBsZSBtb3JlIGRpZ2l0cyBvZiBwcmVjaXNpb24gb3ZlciB0aWNrIGxhYmVsc1xuICAgIGlmKGhvdmVyKSB7XG4gICAgICAgIC8vIG1ha2UgYSBkdW1teSBheGlzIG9iaiB0byBnZXQgdGhlIGF1dG8gcm91bmRpbmcgYW5kIGV4cG9uZW50XG4gICAgICAgIHZhciBhaCA9IHtcbiAgICAgICAgICAgIGV4cG9uZW50Zm9ybWF0OiBleHBvbmVudEZvcm1hdCxcbiAgICAgICAgICAgIGR0aWNrOiBheC5zaG93ZXhwb25lbnQgPT09ICdub25lJyA/IGF4LmR0aWNrIDpcbiAgICAgICAgICAgICAgICAoaXNOdW1lcmljKHYpID8gTWF0aC5hYnModikgfHwgMSA6IDEpLFxuICAgICAgICAgICAgLy8gaWYgbm90IHNob3dpbmcgYW55IGV4cG9uZW50cywgZG9uJ3QgY2hhbmdlIHRoZSBleHBvbmVudFxuICAgICAgICAgICAgLy8gZnJvbSB3aGF0IHdlIGNhbGN1bGF0ZVxuICAgICAgICAgICAgcmFuZ2U6IGF4LnNob3dleHBvbmVudCA9PT0gJ25vbmUnID8gYXgucmFuZ2UubWFwKGF4LnIyZCkgOiBbMCwgdiB8fCAxXVxuICAgICAgICB9O1xuICAgICAgICBhdXRvVGlja1JvdW5kKGFoKTtcbiAgICAgICAgdGlja1JvdW5kID0gKE51bWJlcihhaC5fdGlja3JvdW5kKSB8fCAwKSArIDQ7XG4gICAgICAgIGV4cG9uZW50ID0gYWguX3RpY2tleHBvbmVudDtcbiAgICAgICAgaWYoYXguaG92ZXJmb3JtYXQpIHRpY2tmb3JtYXQgPSBheC5ob3ZlcmZvcm1hdDtcbiAgICB9XG5cbiAgICBpZih0aWNrZm9ybWF0KSByZXR1cm4gYXguX251bUZvcm1hdCh0aWNrZm9ybWF0KSh2KS5yZXBsYWNlKC8tL2csIE1JTlVTX1NJR04pO1xuXG4gICAgLy8gJ2Vwc2lsb24nIC0gcm91bmRpbmcgaW5jcmVtZW50XG4gICAgdmFyIGUgPSBNYXRoLnBvdygxMCwgLXRpY2tSb3VuZCkgLyAyO1xuXG4gICAgLy8gZXhwb25lbnRGb3JtYXQgY29kZXM6XG4gICAgLy8gJ2UnICgxLjJlKzYsIGRlZmF1bHQpXG4gICAgLy8gJ0UnICgxLjJFKzYpXG4gICAgLy8gJ1NJJyAoMS4yTSlcbiAgICAvLyAnQicgKHNhbWUgYXMgU0kgZXhjZXB0IDEwXjk9QiBub3QgRylcbiAgICAvLyAnbm9uZScgKDEyMDAwMDApXG4gICAgLy8gJ3Bvd2VyJyAoMS4yeDEwXjYpXG4gICAgLy8gJ2hpZGUnICgxLjIsIHVzZSAzcmQgYXJndW1lbnQ9PSdoaWRlJyB0byBlZ1xuICAgIC8vICAgICAgb25seSBzaG93IGV4cG9uZW50IG9uIGxhc3QgdGljaylcbiAgICBpZihleHBvbmVudEZvcm1hdCA9PT0gJ25vbmUnKSBleHBvbmVudCA9IDA7XG5cbiAgICAvLyB0YWtlIHRoZSBzaWduIG91dCwgcHV0IGl0IGJhY2sgbWFudWFsbHkgYXQgdGhlIGVuZFxuICAgIC8vIC0gbWFrZXMgY2FzZXMgZWFzaWVyXG4gICAgdiA9IE1hdGguYWJzKHYpO1xuICAgIGlmKHYgPCBlKSB7XG4gICAgICAgIC8vIDAgaXMganVzdCAwLCBidXQgbWF5IGdldCBleHBvbmVudCBpZiBpdCdzIHRoZSBsYXN0IHRpY2tcbiAgICAgICAgdiA9ICcwJztcbiAgICAgICAgaXNOZWcgPSBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHYgKz0gZTtcbiAgICAgICAgLy8gdGFrZSBvdXQgYSBjb21tb24gZXhwb25lbnQsIGlmIGFueVxuICAgICAgICBpZihleHBvbmVudCkge1xuICAgICAgICAgICAgdiAqPSBNYXRoLnBvdygxMCwgLWV4cG9uZW50KTtcbiAgICAgICAgICAgIHRpY2tSb3VuZCArPSBleHBvbmVudDtcbiAgICAgICAgfVxuICAgICAgICAvLyByb3VuZCB0aGUgbWFudGlzc2FcbiAgICAgICAgaWYodGlja1JvdW5kID09PSAwKSB2ID0gU3RyaW5nKE1hdGguZmxvb3IodikpO1xuICAgICAgICBlbHNlIGlmKHRpY2tSb3VuZCA8IDApIHtcbiAgICAgICAgICAgIHYgPSBTdHJpbmcoTWF0aC5yb3VuZCh2KSk7XG4gICAgICAgICAgICB2ID0gdi5zdWJzdHIoMCwgdi5sZW5ndGggKyB0aWNrUm91bmQpO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gdGlja1JvdW5kOyBpIDwgMDsgaSsrKSB2ICs9ICcwJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHYgPSBTdHJpbmcodik7XG4gICAgICAgICAgICB2YXIgZHAgPSB2LmluZGV4T2YoJy4nKSArIDE7XG4gICAgICAgICAgICBpZihkcCkgdiA9IHYuc3Vic3RyKDAsIGRwICsgdGlja1JvdW5kKS5yZXBsYWNlKC9cXC4/MCskLywgJycpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGluc2VydCBhcHByb3ByaWF0ZSBkZWNpbWFsIHBvaW50IGFuZCB0aG91c2FuZHMgc2VwYXJhdG9yXG4gICAgICAgIHYgPSBMaWIubnVtU2VwYXJhdGUodiwgYXguX3NlcGFyYXRvcnMsIHNlcGFyYXRldGhvdXNhbmRzKTtcbiAgICB9XG5cbiAgICAvLyBhZGQgZXhwb25lbnRcbiAgICBpZihleHBvbmVudCAmJiBleHBvbmVudEZvcm1hdCAhPT0gJ2hpZGUnKSB7XG4gICAgICAgIGlmKGlzU0lGb3JtYXQoZXhwb25lbnRGb3JtYXQpICYmIGJleW9uZFNJKGV4cG9uZW50KSkgZXhwb25lbnRGb3JtYXQgPSAncG93ZXInO1xuXG4gICAgICAgIHZhciBzaWduZWRFeHBvbmVudDtcbiAgICAgICAgaWYoZXhwb25lbnQgPCAwKSBzaWduZWRFeHBvbmVudCA9IE1JTlVTX1NJR04gKyAtZXhwb25lbnQ7XG4gICAgICAgIGVsc2UgaWYoZXhwb25lbnRGb3JtYXQgIT09ICdwb3dlcicpIHNpZ25lZEV4cG9uZW50ID0gJysnICsgZXhwb25lbnQ7XG4gICAgICAgIGVsc2Ugc2lnbmVkRXhwb25lbnQgPSBTdHJpbmcoZXhwb25lbnQpO1xuXG4gICAgICAgIGlmKGV4cG9uZW50Rm9ybWF0ID09PSAnZScgfHwgZXhwb25lbnRGb3JtYXQgPT09ICdFJykge1xuICAgICAgICAgICAgdiArPSBleHBvbmVudEZvcm1hdCArIHNpZ25lZEV4cG9uZW50O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoZXhwb25lbnRGb3JtYXQgPT09ICdwb3dlcicpIHtcbiAgICAgICAgICAgIHYgKz0gJ8OXMTA8c3VwPicgKyBzaWduZWRFeHBvbmVudCArICc8L3N1cD4nO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoZXhwb25lbnRGb3JtYXQgPT09ICdCJyAmJiBleHBvbmVudCA9PT0gOSkge1xuICAgICAgICAgICAgdiArPSAnQic7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihpc1NJRm9ybWF0KGV4cG9uZW50Rm9ybWF0KSkge1xuICAgICAgICAgICAgdiArPSBTSVBSRUZJWEVTW2V4cG9uZW50IC8gMyArIDVdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gcHV0IHNpZ24gYmFjayBpbiBhbmQgcmV0dXJuXG4gICAgLy8gcmVwbGFjZSBzdGFuZGFyZCBtaW51cyBjaGFyYWN0ZXIgKHdoaWNoIGlzIHRlY2huaWNhbGx5IGEgaHlwaGVuKVxuICAgIC8vIHdpdGggYSB0cnVlIG1pbnVzIHNpZ25cbiAgICBpZihpc05lZykgcmV0dXJuIE1JTlVTX1NJR04gKyB2O1xuICAgIHJldHVybiB2O1xufVxuXG5heGVzLmdldFRpY2tGb3JtYXQgPSBmdW5jdGlvbihheCkge1xuICAgIHZhciBpO1xuXG4gICAgZnVuY3Rpb24gY29udmVydFRvTXMoZHRpY2spIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBkdGljayAhPT0gJ3N0cmluZycgPyBkdGljayA6IE51bWJlcihkdGljay5yZXBsYWNlKCdNJywgJycpKSAqIE9ORUFWR01PTlRIO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXBhcmVMb2dUaWNrcyhsZWZ0LCByaWdodCkge1xuICAgICAgICB2YXIgcHJpb3JpdHkgPSBbJ0wnLCAnRCddO1xuICAgICAgICBpZih0eXBlb2YgbGVmdCA9PT0gdHlwZW9mIHJpZ2h0KSB7XG4gICAgICAgICAgICBpZih0eXBlb2YgbGVmdCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdCAtIHJpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVmdFByaW9yaXR5ID0gcHJpb3JpdHkuaW5kZXhPZihsZWZ0LmNoYXJBdCgwKSk7XG4gICAgICAgICAgICAgICAgdmFyIHJpZ2h0UHJpb3JpdHkgPSBwcmlvcml0eS5pbmRleE9mKHJpZ2h0LmNoYXJBdCgwKSk7XG4gICAgICAgICAgICAgICAgaWYobGVmdFByaW9yaXR5ID09PSByaWdodFByaW9yaXR5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBOdW1iZXIobGVmdC5yZXBsYWNlKC8oTHxEKS9nLCAnJykpIC0gTnVtYmVyKHJpZ2h0LnJlcGxhY2UoLyhMfEQpL2csICcnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRQcmlvcml0eSAtIHJpZ2h0UHJpb3JpdHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBsZWZ0ID09PSAnbnVtYmVyJyA/IDEgOiAtMTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzUHJvcGVyU3RvcChkdGljaywgcmFuZ2UsIGNvbnZlcnQpIHtcbiAgICAgICAgdmFyIGNvbnZlcnRGbiA9IGNvbnZlcnQgfHwgZnVuY3Rpb24oeCkgeyByZXR1cm4geDt9O1xuICAgICAgICB2YXIgbGVmdER0aWNrID0gcmFuZ2VbMF07XG4gICAgICAgIHZhciByaWdodER0aWNrID0gcmFuZ2VbMV07XG4gICAgICAgIHJldHVybiAoKCFsZWZ0RHRpY2sgJiYgdHlwZW9mIGxlZnREdGljayAhPT0gJ251bWJlcicpIHx8IGNvbnZlcnRGbihsZWZ0RHRpY2spIDw9IGNvbnZlcnRGbihkdGljaykpICYmXG4gICAgICAgICAgICAgICAoKCFyaWdodER0aWNrICYmIHR5cGVvZiByaWdodER0aWNrICE9PSAnbnVtYmVyJykgfHwgY29udmVydEZuKHJpZ2h0RHRpY2spID49IGNvbnZlcnRGbihkdGljaykpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzUHJvcGVyTG9nU3RvcChkdGljaywgcmFuZ2UpIHtcbiAgICAgICAgdmFyIGlzTGVmdER0aWNrTnVsbCA9IHJhbmdlWzBdID09PSBudWxsO1xuICAgICAgICB2YXIgaXNSaWdodER0aWNrTnVsbCA9IHJhbmdlWzFdID09PSBudWxsO1xuICAgICAgICB2YXIgaXNEdGlja0luUmFuZ2VMZWZ0ID0gY29tcGFyZUxvZ1RpY2tzKGR0aWNrLCByYW5nZVswXSkgPj0gMDtcbiAgICAgICAgdmFyIGlzRHRpY2tJblJhbmdlUmlnaHQgPSBjb21wYXJlTG9nVGlja3MoZHRpY2ssIHJhbmdlWzFdKSA8PSAwO1xuICAgICAgICByZXR1cm4gKGlzTGVmdER0aWNrTnVsbCB8fCBpc0R0aWNrSW5SYW5nZUxlZnQpICYmIChpc1JpZ2h0RHRpY2tOdWxsIHx8IGlzRHRpY2tJblJhbmdlUmlnaHQpO1xuICAgIH1cblxuICAgIHZhciB0aWNrc3RvcCwgc3RvcGk7XG4gICAgaWYoYXgudGlja2Zvcm1hdHN0b3BzICYmIGF4LnRpY2tmb3JtYXRzdG9wcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHN3aXRjaChheC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdkYXRlJzpcbiAgICAgICAgICAgIGNhc2UgJ2xpbmVhcic6IHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheC50aWNrZm9ybWF0c3RvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc3RvcGkgPSBheC50aWNrZm9ybWF0c3RvcHNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmKHN0b3BpLmVuYWJsZWQgJiYgaXNQcm9wZXJTdG9wKGF4LmR0aWNrLCBzdG9waS5kdGlja3JhbmdlLCBjb252ZXJ0VG9NcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2tzdG9wID0gc3RvcGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ2xvZyc6IHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheC50aWNrZm9ybWF0c3RvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc3RvcGkgPSBheC50aWNrZm9ybWF0c3RvcHNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmKHN0b3BpLmVuYWJsZWQgJiYgaXNQcm9wZXJMb2dTdG9wKGF4LmR0aWNrLCBzdG9waS5kdGlja3JhbmdlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja3N0b3AgPSBzdG9waTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGlja3N0b3AgPyB0aWNrc3RvcC52YWx1ZSA6IGF4LnRpY2tmb3JtYXQ7XG59O1xuXG4vLyBnZXRTdWJwbG90cyAtIGV4dHJhY3QgYWxsIHN1YnBsb3QgSURzIHdlIG5lZWRcbi8vIGFzIGFuIGFycmF5IG9mIGl0ZW1zIGxpa2UgJ3h5JywgJ3gyeScsICd4MnkyJy4uLlxuLy8gc29ydGVkIGJ5IHggKHgseDIseDMuLi4pIHRoZW4geVxuLy8gb3B0aW9uYWxseSByZXN0cmljdCB0byBvbmx5IHN1YnBsb3RzIGNvbnRhaW5pbmcgYXhpcyBvYmplY3QgYXhcbmF4ZXMuZ2V0U3VicGxvdHMgPSBmdW5jdGlvbihnZCwgYXgpIHtcbiAgICB2YXIgc3VicGxvdE9iaiA9IGdkLl9mdWxsTGF5b3V0Ll9zdWJwbG90cztcbiAgICB2YXIgYWxsU3VicGxvdHMgPSBzdWJwbG90T2JqLmNhcnRlc2lhbi5jb25jYXQoc3VicGxvdE9iai5nbDJkIHx8IFtdKTtcblxuICAgIHZhciBvdXQgPSBheCA/IGF4ZXMuZmluZFN1YnBsb3RzV2l0aEF4aXMoYWxsU3VicGxvdHMsIGF4KSA6IGFsbFN1YnBsb3RzO1xuXG4gICAgb3V0LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICB2YXIgYVBhcnRzID0gYS5zdWJzdHIoMSkuc3BsaXQoJ3knKTtcbiAgICAgICAgdmFyIGJQYXJ0cyA9IGIuc3Vic3RyKDEpLnNwbGl0KCd5Jyk7XG5cbiAgICAgICAgaWYoYVBhcnRzWzBdID09PSBiUGFydHNbMF0pIHJldHVybiArYVBhcnRzWzFdIC0gK2JQYXJ0c1sxXTtcbiAgICAgICAgcmV0dXJuICthUGFydHNbMF0gLSArYlBhcnRzWzBdO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8vIGZpbmQgYWxsIHN1YnBsb3RzIHdpdGggYXhpcyAnYXgnXG5heGVzLmZpbmRTdWJwbG90c1dpdGhBeGlzID0gZnVuY3Rpb24oc3VicGxvdHMsIGF4KSB7XG4gICAgdmFyIGF4TWF0Y2ggPSBuZXcgUmVnRXhwKFxuICAgICAgICAoYXguX2lkLmNoYXJBdCgwKSA9PT0gJ3gnKSA/ICgnXicgKyBheC5faWQgKyAneScpIDogKGF4Ll9pZCArICckJylcbiAgICApO1xuICAgIHZhciBzdWJwbG90c1dpdGhBeGlzID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNwID0gc3VicGxvdHNbaV07XG4gICAgICAgIGlmKGF4TWF0Y2gudGVzdChzcCkpIHN1YnBsb3RzV2l0aEF4aXMucHVzaChzcCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1YnBsb3RzV2l0aEF4aXM7XG59O1xuXG4vLyBtYWtlQ2xpcFBhdGhzOiBwcmVwYXJlIGNsaXBQYXRocyBmb3IgYWxsIHNpbmdsZSBheGVzIGFuZCBhbGwgcG9zc2libGUgeHkgcGFpcmluZ3NcbmF4ZXMubWFrZUNsaXBQYXRocyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIC8vIGZvciBtb3JlIGluZm86IGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8yNTk1XG4gICAgaWYoZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSByZXR1cm47XG5cbiAgICB2YXIgZnVsbFdpZHRoID0ge19vZmZzZXQ6IDAsIF9sZW5ndGg6IGZ1bGxMYXlvdXQud2lkdGgsIF9pZDogJyd9O1xuICAgIHZhciBmdWxsSGVpZ2h0ID0ge19vZmZzZXQ6IDAsIF9sZW5ndGg6IGZ1bGxMYXlvdXQuaGVpZ2h0LCBfaWQ6ICcnfTtcbiAgICB2YXIgeGFMaXN0ID0gYXhlcy5saXN0KGdkLCAneCcsIHRydWUpO1xuICAgIHZhciB5YUxpc3QgPSBheGVzLmxpc3QoZ2QsICd5JywgdHJ1ZSk7XG4gICAgdmFyIGNsaXBMaXN0ID0gW107XG4gICAgdmFyIGksIGo7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB4YUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY2xpcExpc3QucHVzaCh7eDogeGFMaXN0W2ldLCB5OiBmdWxsSGVpZ2h0fSk7XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHlhTGlzdC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYoaSA9PT0gMCkgY2xpcExpc3QucHVzaCh7eDogZnVsbFdpZHRoLCB5OiB5YUxpc3Rbal19KTtcbiAgICAgICAgICAgIGNsaXBMaXN0LnB1c2goe3g6IHhhTGlzdFtpXSwgeTogeWFMaXN0W2pdfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzZWxlY3RvcnMgZG9uJ3Qgd29yayByaWdodCB3aXRoIGNhbWVsQ2FzZSB0YWdzLFxuICAgIC8vIGhhdmUgdG8gdXNlIGNsYXNzIGluc3RlYWRcbiAgICAvLyBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2ZvcnVtLyMhdG9waWMvZDMtanMvNkVwQXpRMmdVOUlcbiAgICB2YXIgYXhDbGlwcyA9IGZ1bGxMYXlvdXQuX2NsaXBzLnNlbGVjdEFsbCgnLmF4ZXNjbGlwJylcbiAgICAgICAgLmRhdGEoY2xpcExpc3QsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQueC5faWQgKyBkLnkuX2lkOyB9KTtcblxuICAgIGF4Q2xpcHMuZW50ZXIoKS5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgLmNsYXNzZWQoJ2F4ZXNjbGlwJywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gJ2NsaXAnICsgZnVsbExheW91dC5fdWlkICsgZC54Ll9pZCArIGQueS5faWQ7IH0pXG4gICAgICAuYXBwZW5kKCdyZWN0Jyk7XG5cbiAgICBheENsaXBzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGF4Q2xpcHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ3JlY3QnKS5hdHRyKHtcbiAgICAgICAgICAgIHg6IGQueC5fb2Zmc2V0IHx8IDAsXG4gICAgICAgICAgICB5OiBkLnkuX29mZnNldCB8fCAwLFxuICAgICAgICAgICAgd2lkdGg6IGQueC5fbGVuZ3RoIHx8IDEsXG4gICAgICAgICAgICBoZWlnaHQ6IGQueS5fbGVuZ3RoIHx8IDFcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIE1haW4gbXVsdGktYXhpcyBkcmF3aW5nIHJvdXRpbmUhXG4gKlxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2QgOiBncmFwaCBkaXZcbiAqIEBwYXJhbSB7c3RyaW5nIG9yIGFycmF5IG9mIHN0cmluZ3N9IGFyZyA6IHBvbHltb3JwaGljIGFyZ3VtZW50XG4gKiBAcGFyYW0ge2Jvb2xlYW59IHNraXBUaXRsZSA6IG9wdGlvbmFsIGZsYWcgdG8gc2tpcCBheGlzIHRpdGxlIGRyYXcvdXBkYXRlXG4gKlxuICogU2lnbmF0dXJlIDE6IEF4ZXMuZG9UaWNrcyhnZCwgJ3JlZHJhdycpXG4gKiAgIHVzZSB0aGlzIHRvIGNsZWFyIGFuZCByZWRyYXcgYWxsIGF4ZXMgb24gZ3JhcGhcbiAqXG4gKiBTaWduYXR1cmUgMjogQXhlcy5kb1RpY2tzKGdkLCAnJylcbiAqICAgdXNlIHRoaXMgdG8gZHJhdyBhbGwgYXhlcyBvbiBncmFwaCB3L28gdGhlIHNlbGVjdEFsbCgpLnJlbW92ZSgpXG4gKiAgIG9mIHRoZSAncmVkcmF3JyBzaWduYXR1cmVcbiAqXG4gKiBTaWduYXR1cmUgMzogQXhlcy5kb1RpY2tzKGdkLCBbYXhJZCwgYXhJZDIsIC4uLl0pXG4gKiAgIHdoZXJlIHRoZSBpdGVtcyBhcmUgYXhpcyBpZCBzdHJpbmcsXG4gKiAgIHVzZSB0aGlzIHRvIHVwZGF0ZSBtdWx0aXBsZSBheGVzIGluIG9uZSBjYWxsXG4gKlxuICogTi5CIGRvVGlja3MgdXBkYXRlczpcbiAqIC0gYXguX3IgKHN0b3JlZCByYW5nZSBmb3IgdXNlIGJ5IHpvb20vcGFuKVxuICogLSBheC5fcmwgKHN0b3JlZCBsaW5lYXJpemVkIHJhbmdlIGZvciB1c2UgYnkgem9vbS9wYW4pXG4gKi9cbmF4ZXMuZG9UaWNrcyA9IGZ1bmN0aW9uKGdkLCBhcmcsIHNraXBUaXRsZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZihhcmcgPT09ICdyZWRyYXcnKSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX3BhcGVyLnNlbGVjdEFsbCgnZy5zdWJwbG90JykuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBkWzBdO1xuICAgICAgICAgICAgdmFyIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbaWRdO1xuICAgICAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgICAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgICAgICAgICAgcGxvdGluZm8ueGF4aXNsYXllci5zZWxlY3RBbGwoJy4nICsgeGEuX2lkICsgJ3RpY2snKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnlheGlzbGF5ZXIuc2VsZWN0QWxsKCcuJyArIHlhLl9pZCArICd0aWNrJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBpZihwbG90aW5mby5ncmlkbGF5ZXIpIHBsb3RpbmZvLmdyaWRsYXllci5zZWxlY3RBbGwoJ3BhdGgnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLnplcm9saW5lbGF5ZXIpIHBsb3RpbmZvLnplcm9saW5lbGF5ZXIuc2VsZWN0QWxsKCdwYXRoJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0KCcuZy0nICsgeGEuX2lkICsgJ3RpdGxlJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0KCcuZy0nICsgeWEuX2lkICsgJ3RpdGxlJykucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBheExpc3QgPSAoIWFyZyB8fCBhcmcgPT09ICdyZWRyYXcnKSA/IGF4ZXMubGlzdElkcyhnZCkgOiBhcmc7XG5cbiAgICBMaWIuc3luY09yQXN5bmMoYXhMaXN0Lm1hcChmdW5jdGlvbihheGlkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmKCFheGlkKSByZXR1cm47XG5cbiAgICAgICAgICAgIHZhciBheERvbmUgPSBheGVzLmRvVGlja3NTaW5nbGUoZ2QsIGF4aWQsIHNraXBUaXRsZSk7XG5cbiAgICAgICAgICAgIHZhciBheCA9IGF4ZXMuZ2V0RnJvbUlkKGdkLCBheGlkKTtcbiAgICAgICAgICAgIGF4Ll9yID0gYXgucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgIGF4Ll9ybCA9IExpYi5zaW1wbGVNYXAoYXguX3IsIGF4LnIybCk7XG5cbiAgICAgICAgICAgIHJldHVybiBheERvbmU7XG4gICAgICAgIH07XG4gICAgfSkpO1xufTtcblxuLyoqXG4gKiBQZXItYXhpcyBkcmF3aW5nIHJvdXRpbmUhXG4gKlxuICogVGhpcyByb3V0aW5lIGRyYXdzIGF4aXMgdGlja3MgYW5kIG11Y2ggbW9yZSAoLi4uIGdyaWRzLCBsYWJlbHMsIHRpdGxlIGV0Yy4pXG4gKiBTdXBwb3J0cyBtdWx0aXBsZSBhcmd1bWVudCBzaWduYXR1cmVzLlxuICogTi5CLiB0aGlzIHRoaW5nIGlzIGFzeW5jIGluIGdlbmVyYWwgKGJlY2F1c2Ugb2YgTWF0aEpheCByZW5kZXJpbmcpXG4gKlxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2QgOiBncmFwaCBkaXZcbiAqIEBwYXJhbSB7c3RyaW5nIG9yIG9iamVjdH0gYXJnIDogcG9seW1vcnBoaWMgYXJndW1lbnRcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gc2tpcFRpdGxlIDogb3B0aW9uYWwgZmxhZyB0byBza2lwIGF4aXMgdGl0bGUgZHJhdy91cGRhdGVcbiAqIEByZXR1cm4ge3Byb21pc2V9XG4gKlxuICogU2lnbmF0dXJlIDE6IEF4ZXMuZG9UaWNrcyhnZCwgYXgpXG4gKiAgIHdoZXJlIGF4IGlzIGFuIGF4aXMgb2JqZWN0IGFzIGluIGZ1bGxMYXlvdXRcbiAqXG4gKiBTaWduYXR1cmUgMjogQXhlcy5kb1RpY2tzKGdkLCBheElkKVxuICogICB3aGVyZSBheElkIGlzIGEgYXhpcyBpZCBzdHJpbmdcbiAqL1xuYXhlcy5kb1RpY2tzU2luZ2xlID0gZnVuY3Rpb24oZ2QsIGFyZywgc2tpcFRpdGxlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgaW5kZXBlbmRlbnQgPSBmYWxzZTtcbiAgICB2YXIgYXg7XG5cbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdChhcmcpKSB7XG4gICAgICAgIGF4ID0gYXJnO1xuICAgICAgICBpbmRlcGVuZGVudCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXggPSBheGVzLmdldEZyb21JZChnZCwgYXJnKTtcbiAgICB9XG5cbiAgICAvLyBzZXQgc2NhbGluZyB0byBwaXhlbHNcbiAgICBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIGF4aWQgPSBheC5faWQ7XG4gICAgdmFyIGF4TGV0dGVyID0gYXhpZC5jaGFyQXQoMCk7XG4gICAgdmFyIGNvdW50ZXJMZXR0ZXIgPSBheGVzLmNvdW50ZXJMZXR0ZXIoYXhpZCk7XG4gICAgdmFyIHZhbHMgPSBheC5fdmFscyA9IGF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICB2YXIgZGF0YWZuID0gZnVuY3Rpb24oZCkgeyByZXR1cm4gW2QudGV4dCwgZC54LCBheC5taXJyb3IsIGQuZm9udCwgZC5mb250U2l6ZSwgZC5mb250Q29sb3JdLmpvaW4oJ18nKTsgfTtcbiAgICB2YXIgdGNscyA9IGF4aWQgKyAndGljayc7XG4gICAgdmFyIGdjbHMgPSBheGlkICsgJ2dyaWQnO1xuICAgIHZhciB6Y2xzID0gYXhpZCArICd6bCc7XG4gICAgdmFyIHBhZCA9IChheC5saW5ld2lkdGggfHwgMSkgLyAyO1xuICAgIHZhciBsYWJlbFN0YW5kb2ZmID0gKGF4LnRpY2tzID09PSAnb3V0c2lkZScgPyBheC50aWNrbGVuIDogMCk7XG4gICAgdmFyIGxhYmVsU2hpZnQgPSAwO1xuICAgIHZhciBncmlkV2lkdGggPSBEcmF3aW5nLmNyaXNwUm91bmQoZ2QsIGF4LmdyaWR3aWR0aCwgMSk7XG4gICAgdmFyIHplcm9MaW5lV2lkdGggPSBEcmF3aW5nLmNyaXNwUm91bmQoZ2QsIGF4Lnplcm9saW5ld2lkdGgsIGdyaWRXaWR0aCk7XG4gICAgdmFyIHRpY2tXaWR0aCA9IERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgYXgudGlja3dpZHRoLCAxKTtcbiAgICB2YXIgc2lkZXMsIHRyYW5zZm4sIHRpY2twYXRoZm4sIHN1YnBsb3RzO1xuICAgIHZhciB0aWNrTGFiZWxzO1xuICAgIHZhciBpO1xuXG4gICAgaWYoYXguX2NvdW50ZXJhbmdsZSAmJiBheC50aWNrcyA9PT0gJ291dHNpZGUnKSB7XG4gICAgICAgIHZhciBjYVJhZCA9IGF4Ll9jb3VudGVyYW5nbGUgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICBsYWJlbFN0YW5kb2ZmID0gYXgudGlja2xlbiAqIE1hdGguY29zKGNhUmFkKSArIDE7XG4gICAgICAgIGxhYmVsU2hpZnQgPSBheC50aWNrbGVuICogTWF0aC5zaW4oY2FSYWQpO1xuICAgIH1cblxuICAgIGlmKGF4LnNob3d0aWNrbGFiZWxzICYmIChheC50aWNrcyA9PT0gJ291dHNpZGUnIHx8IGF4LnNob3dsaW5lKSkge1xuICAgICAgICBsYWJlbFN0YW5kb2ZmICs9IDAuMiAqIGF4LnRpY2tmb250LnNpemU7XG4gICAgfVxuXG4gICAgLy8gcG9zaXRpb25pbmcgYXJndW1lbnRzIGZvciB4IHZzIHkgYXhlc1xuICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgc2lkZXMgPSBbJ2JvdHRvbScsICd0b3AnXTtcbiAgICAgICAgdHJhbnNmbiA9IGF4Ll90cmFuc2ZuIHx8IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyAoYXguX29mZnNldCArIGF4LmwycChkLngpKSArICcsMCknO1xuICAgICAgICB9O1xuICAgICAgICB0aWNrcGF0aGZuID0gZnVuY3Rpb24oc2hpZnQsIGxlbikge1xuICAgICAgICAgICAgaWYoYXguX2NvdW50ZXJhbmdsZSkge1xuICAgICAgICAgICAgICAgIHZhciBjYVJhZCA9IGF4Ll9jb3VudGVyYW5nbGUgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHNoaWZ0ICsgJ2wnICsgKE1hdGguc2luKGNhUmFkKSAqIGxlbikgKyAnLCcgKyAoTWF0aC5jb3MoY2FSYWQpICogbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgcmV0dXJuICdNMCwnICsgc2hpZnQgKyAndicgKyBsZW47XG4gICAgICAgIH07XG4gICAgfVxuICAgIGVsc2UgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICBzaWRlcyA9IFsnbGVmdCcsICdyaWdodCddO1xuICAgICAgICB0cmFuc2ZuID0gYXguX3RyYW5zZm4gfHwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoMCwnICsgKGF4Ll9vZmZzZXQgKyBheC5sMnAoZC54KSkgKyAnKSc7XG4gICAgICAgIH07XG4gICAgICAgIHRpY2twYXRoZm4gPSBmdW5jdGlvbihzaGlmdCwgbGVuKSB7XG4gICAgICAgICAgICBpZihheC5fY291bnRlcmFuZ2xlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhUmFkID0gYXguX2NvdW50ZXJhbmdsZSAqIE1hdGguUEkgLyAxODA7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdNJyArIHNoaWZ0ICsgJywwbCcgKyAoTWF0aC5jb3MoY2FSYWQpICogbGVuKSArICcsJyArICgtTWF0aC5zaW4oY2FSYWQpICogbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgcmV0dXJuICdNJyArIHNoaWZ0ICsgJywwaCcgKyBsZW47XG4gICAgICAgIH07XG4gICAgfVxuICAgIGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkge1xuICAgICAgICBzaWRlcyA9IFsnbGVmdCcsICdyaWdodCddO1xuICAgICAgICB0cmFuc2ZuID0gYXguX3RyYW5zZm47XG4gICAgICAgIHRpY2twYXRoZm4gPSBmdW5jdGlvbihzaGlmdCwgbGVuKSB7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgc2hpZnQgKyAnLDBoJyArIGxlbjtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIExpYi53YXJuKCdVbnJlY29nbml6ZWQgZG9UaWNrcyBheGlzOicsIGF4aWQpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGF4c2lkZSA9IGF4LnNpZGUgfHwgc2lkZXNbMF07XG4gICAgLy8gd2hpY2ggZGlyZWN0aW9uIGRvIHRoZSBzaWRlWzBdLCBzaWRlWzFdLCBhbmQgZnJlZSB0aWNrcyBnbz9cbiAgICAvLyB0aGVuIHdlIGZsaXAgaWYgb3V0c2lkZSBYT1IgeSBheGlzXG4gICAgdmFyIHRpY2tzaWduID0gWy0xLCAxLCBheHNpZGUgPT09IHNpZGVzWzFdID8gMSA6IC0xXTtcbiAgICBpZigoYXgudGlja3MgIT09ICdpbnNpZGUnKSA9PT0gKGF4TGV0dGVyID09PSAneCcpKSB7XG4gICAgICAgIHRpY2tzaWduID0gdGlja3NpZ24ubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIC12OyB9KTtcbiAgICB9XG5cbiAgICBpZighYXgudmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgaWYoYXguX3RpY2tGaWx0ZXIpIHtcbiAgICAgICAgdmFscyA9IHZhbHMuZmlsdGVyKGF4Ll90aWNrRmlsdGVyKTtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgemVybyBsaW5lcywgZ3JpZCBsaW5lcywgYW5kIGluc2lkZSB0aWNrcyBpZiB0aGV5J3JlIHdpdGhpblxuICAgIC8vIDEgcGl4ZWwgb2YgdGhlIGVuZC5cbiAgICAvLyBUaGUga2V5IGNhc2UgaGVyZSBpcyByZW1vdmluZyB6ZXJvIGxpbmVzIHdoZW4gdGhlIGF4aXMgYm91bmQgaXMgemVyby5cbiAgICAvLyBEb24ndCBjbGlwIGFuZ3VsYXIgdmFsdWVzLlxuICAgIHZhciB2YWxzQ2xpcHBlZCA9IGF4Ll92YWxzQ2xpcHBlZCA9IGlzQW5ndWxhcihheCkgP1xuICAgICAgICB2YWxzIDpcbiAgICAgICAgdmFscy5maWx0ZXIoZnVuY3Rpb24oZCkgeyByZXR1cm4gY2xpcEVuZHMoYXgsIGQueCk7IH0pO1xuXG4gICAgZnVuY3Rpb24gZHJhd1RpY2tzKGNvbnRhaW5lciwgdGlja3BhdGgpIHtcbiAgICAgICAgdmFyIHRpY2tzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aC4nICsgdGNscylcbiAgICAgICAgICAgIC5kYXRhKGF4LnRpY2tzID09PSAnaW5zaWRlJyA/IHZhbHNDbGlwcGVkIDogdmFscywgZGF0YWZuKTtcblxuICAgICAgICBpZih0aWNrcGF0aCAmJiBheC50aWNrcykge1xuICAgICAgICAgICAgdGlja3MuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKHRjbHMsIDEpLmNsYXNzZWQoJ3RpY2tzJywgMSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCAxKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYXgudGlja2NvbG9yKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgdGlja1dpZHRoICsgJ3B4JylcbiAgICAgICAgICAgICAgICAuYXR0cignZCcsIHRpY2twYXRoKTtcbiAgICAgICAgICAgIHRpY2tzLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm4pO1xuICAgICAgICAgICAgdGlja3MuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgdGlja3MucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0xhYmVscyhjb250YWluZXIsIHBvc2l0aW9uKSB7XG4gICAgICAgIC8vIHRpY2sgbGFiZWxzIC0gZm9yIG5vdyBqdXN0IHRoZSBtYWluIGxhYmVscy5cbiAgICAgICAgLy8gVE9ETzogbWlycm9yIGxhYmVscywgZXNwIGZvciBzdWJwbG90c1xuICAgICAgICB0aWNrTGFiZWxzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nICsgdGNscykuZGF0YSh2YWxzLCBkYXRhZm4pO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMocG9zaXRpb24pKSB7XG4gICAgICAgICAgICB0aWNrTGFiZWxzLnJlbW92ZSgpO1xuICAgICAgICAgICAgZHJhd0F4VGl0bGUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZighYXguc2hvd3RpY2tsYWJlbHMpIHtcbiAgICAgICAgICAgIHRpY2tMYWJlbHMucmVtb3ZlKCk7XG4gICAgICAgICAgICBkcmF3QXhUaXRsZSgpO1xuICAgICAgICAgICAgY2FsY0JvdW5kaW5nQm94KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGFiZWx4LCBsYWJlbHksIGxhYmVsYW5jaG9yLCBsYWJlbHBvczAsIGZsaXBpdDtcbiAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgZmxpcGl0ID0gKGF4c2lkZSA9PT0gJ2JvdHRvbScpID8gMSA6IC0xO1xuICAgICAgICAgICAgbGFiZWx4ID0gZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5keCArIGxhYmVsU2hpZnQgKiBmbGlwaXQ7IH07XG4gICAgICAgICAgICBsYWJlbHBvczAgPSBwb3NpdGlvbiArIChsYWJlbFN0YW5kb2ZmICsgcGFkKSAqIGZsaXBpdDtcbiAgICAgICAgICAgIGxhYmVseSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZC5keSArIGxhYmVscG9zMCArIGQuZm9udFNpemUgKlxuICAgICAgICAgICAgICAgICAgICAoKGF4c2lkZSA9PT0gJ2JvdHRvbScpID8gMSA6IC0wLjIpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxhYmVsYW5jaG9yID0gZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgICAgICAgICBpZighaXNOdW1lcmljKGFuZ2xlKSB8fCBhbmdsZSA9PT0gMCB8fCBhbmdsZSA9PT0gMTgwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnbWlkZGxlJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIChhbmdsZSAqIGZsaXBpdCA8IDApID8gJ2VuZCcgOiAnc3RhcnQnO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF4TGV0dGVyID09PSAneScpIHtcbiAgICAgICAgICAgIGZsaXBpdCA9IChheHNpZGUgPT09ICdyaWdodCcpID8gMSA6IC0xO1xuICAgICAgICAgICAgbGFiZWx5ID0gZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkLmR5ICsgZC5mb250U2l6ZSAqIE1JRF9TSElGVCAtIGxhYmVsU2hpZnQgKiBmbGlwaXQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGFiZWx4ID0gZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkLmR4ICsgcG9zaXRpb24gKyAobGFiZWxTdGFuZG9mZiArIHBhZCArXG4gICAgICAgICAgICAgICAgICAgICgoTWF0aC5hYnMoYXgudGlja2FuZ2xlKSA9PT0gOTApID8gZC5mb250U2l6ZSAvIDIgOiAwKSkgKiBmbGlwaXQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGFiZWxhbmNob3IgPSBmdW5jdGlvbihhbmdsZSkge1xuICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhhbmdsZSkgJiYgTWF0aC5hYnMoYW5nbGUpID09PSA5MCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ21pZGRsZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBheHNpZGUgPT09ICdyaWdodCcgPyAnc3RhcnQnIDogJ2VuZCc7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkge1xuICAgICAgICAgICAgYXguX2xhYmVsU2hpZnQgPSBsYWJlbFNoaWZ0O1xuICAgICAgICAgICAgYXguX2xhYmVsU3RhbmRvZmYgPSBsYWJlbFN0YW5kb2ZmO1xuICAgICAgICAgICAgYXguX3BhZCA9IHBhZDtcblxuICAgICAgICAgICAgbGFiZWx4ID0gYXguX2xhYmVseDtcbiAgICAgICAgICAgIGxhYmVseSA9IGF4Ll9sYWJlbHk7XG4gICAgICAgICAgICBsYWJlbGFuY2hvciA9IGF4Ll9sYWJlbGFuY2hvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtYXhGb250U2l6ZSA9IDAsXG4gICAgICAgICAgICBhdXRvYW5nbGUgPSAwLFxuICAgICAgICAgICAgbGFiZWxzUmVhZHkgPSBbXTtcbiAgICAgICAgdGlja0xhYmVscy5lbnRlcigpLmFwcGVuZCgnZycpLmNsYXNzZWQodGNscywgMSlcbiAgICAgICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgICAgICAgIC8vIG9ubHkgc28gdGV4IGhhcyBwcmVkaWN0YWJsZSBhbGlnbm1lbnQgdGhhdCB3ZSBjYW5cbiAgICAgICAgICAgICAgICAvLyBhbHRlciBsYXRlclxuICAgICAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRoaXNMYWJlbCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Byb21pc2UgPSBnZC5fcHJvbWlzZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB0aGlzTGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIGxhYmVseChkKSwgbGFiZWx5KGQpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBkLmZvbnQsIGQuZm9udFNpemUsIGQuZm9udENvbG9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRleHQoZC50ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgICAgICAgICAgICAgICAgICBuZXdQcm9taXNlID0gZ2QuX3Byb21pc2VzW25ld1Byb21pc2VdO1xuICAgICAgICAgICAgICAgICAgICBpZihuZXdQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBoYXZlIGFuIGFzeW5jIGxhYmVsLCB3ZSdsbCBkZWFsIHdpdGggdGhhdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxsIGhlcmUgc28gdGFrZSBpdCBvdXQgb2YgZ2QuX3Byb21pc2VzIGFuZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5zdGVhZCBwb3NpdGlvbiB0aGUgbGFiZWwgYW5kIHByb21pc2UgdGhpcyBpblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGFiZWxzUmVhZHlcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc1JlYWR5LnB1c2goZ2QuX3Byb21pc2VzLnBvcCgpLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25MYWJlbHModGhpc0xhYmVsLCBheC50aWNrYW5nbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3luYyBsYWJlbDoganVzdCBwb3NpdGlvbiBpdCBub3cuXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbkxhYmVscyh0aGlzTGFiZWwsIGF4LnRpY2thbmdsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgdGlja0xhYmVscy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgdGlja0xhYmVscy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIG1heEZvbnRTaXplID0gTWF0aC5tYXgobWF4Rm9udFNpemUsIGQuZm9udFNpemUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZihpc0FuZ3VsYXIoYXgpKSB7XG4gICAgICAgICAgICB0aWNrTGFiZWxzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ3RleHQnKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0LCBsYWJlbHgoZCksIGxhYmVseShkKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhvdyBtdWNoIHRvIHNoaWZ0IGEgbXVsdGktbGluZSBsYWJlbCB0byBjZW50ZXIgaXQgdmVydGljYWxseS5cbiAgICAgICAgZnVuY3Rpb24gZ2V0QW5jaG9ySGVpZ2h0KGxpbmVDb3VudCwgbGluZUhlaWdodCwgYW5nbGUpIHtcbiAgICAgICAgICAgIHZhciBoID0gKGxpbmVDb3VudCAtIDEpICogbGluZUhlaWdodDtcbiAgICAgICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICBpZihhbmdsZSA8IC02MCB8fCA2MCA8IGFuZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAtMC41ICogaDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoYXhzaWRlID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLWg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbmdsZSAqPSBheHNpZGUgPT09ICdsZWZ0JyA/IDEgOiAtMTtcbiAgICAgICAgICAgICAgICBpZihhbmdsZSA8IC0zMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLWg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGFuZ2xlIDwgMzApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC0wLjUgKiBoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcG9zaXRpb25MYWJlbHMocywgYW5nbGUpIHtcbiAgICAgICAgICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IGxhYmVsYW5jaG9yKGFuZ2xlLCBkKTtcbiAgICAgICAgICAgICAgICB2YXIgdGhpc0xhYmVsID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICBtYXRoamF4R3JvdXAgPSB0aGlzTGFiZWwuc2VsZWN0KCcudGV4dC1tYXRoLWdyb3VwJyksXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHRyYW5zZm4uY2FsbCh0aGlzTGFiZWwubm9kZSgpLCBkKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAoKGlzTnVtZXJpYyhhbmdsZSkgJiYgK2FuZ2xlICE9PSAwKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAoJyByb3RhdGUoJyArIGFuZ2xlICsgJywnICsgbGFiZWx4KGQpICsgJywnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAobGFiZWx5KGQpIC0gZC5mb250U2l6ZSAvIDIpICsgJyknKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAnJyk7XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvckhlaWdodCA9IGdldEFuY2hvckhlaWdodChcbiAgICAgICAgICAgICAgICAgICAgc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0aGlzTGFiZWwpLFxuICAgICAgICAgICAgICAgICAgICBMSU5FX1NQQUNJTkcgKiBkLmZvbnRTaXplLFxuICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoYW5nbGUpID8gK2FuZ2xlIDogMCk7XG4gICAgICAgICAgICAgICAgaWYoYW5jaG9ySGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSArPSAnIHRyYW5zbGF0ZSgwLCAnICsgYW5jaG9ySGVpZ2h0ICsgJyknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihtYXRoamF4R3JvdXAuZW1wdHkoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzTGFiZWwuc2VsZWN0KCd0ZXh0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgICAgICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IGFuY2hvclxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtalNoaWZ0ID1cbiAgICAgICAgICAgICAgICAgICAgICAgIERyYXdpbmcuYkJveChtYXRoamF4R3JvdXAubm9kZSgpKS53aWR0aCAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge2VuZDogLTAuNSwgc3RhcnQ6IDAuNX1bYW5jaG9yXTtcbiAgICAgICAgICAgICAgICAgICAgbWF0aGpheEdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSArXG4gICAgICAgICAgICAgICAgICAgICAgICAobWpTaGlmdCA/ICd0cmFuc2xhdGUoJyArIG1qU2hpZnQgKyAnLDApJyA6ICcnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtYWtlIHN1cmUgYWxsIGxhYmVscyBhcmUgY29ycmVjdGx5IHBvc2l0aW9uZWQgYXQgdGhlaXIgYmFzZSBhbmdsZVxuICAgICAgICAvLyB0aGUgcG9zaXRpb25MYWJlbHMgY2FsbCBhYm92ZSBpcyBvbmx5IGZvciBuZXdseSBkcmF3biBsYWJlbHMuXG4gICAgICAgIC8vIGRvIHRoaXMgd2l0aG91dCB3YWl0aW5nLCB1c2luZyB0aGUgbGFzdCBjYWxjdWxhdGVkIGFuZ2xlIHRvXG4gICAgICAgIC8vIG1pbmltaXplIGZsaWNrZXIsIHRoZW4gZG8gaXQgYWdhaW4gd2hlbiB3ZSBrbm93IGFsbCBsYWJlbHMgYXJlXG4gICAgICAgIC8vIHRoZXJlLCBwdXR0aW5nIGJhY2sgdGhlIHByZXNjcmliZWQgYW5nbGUgdG8gY2hlY2sgZm9yIG92ZXJsYXBzLlxuICAgICAgICBwb3NpdGlvbkxhYmVscyh0aWNrTGFiZWxzLCBheC5fbGFzdGFuZ2xlIHx8IGF4LnRpY2thbmdsZSk7XG5cbiAgICAgICAgZnVuY3Rpb24gYWxsTGFiZWxzUmVhZHkoKSB7XG4gICAgICAgICAgICByZXR1cm4gbGFiZWxzUmVhZHkubGVuZ3RoICYmIFByb21pc2UuYWxsKGxhYmVsc1JlYWR5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGZpeExhYmVsT3ZlcmxhcHMoKSB7XG4gICAgICAgICAgICBwb3NpdGlvbkxhYmVscyh0aWNrTGFiZWxzLCBheC50aWNrYW5nbGUpO1xuXG4gICAgICAgICAgICAvLyBjaGVjayBmb3IgYXV0by1hbmdsaW5nIGlmIHggbGFiZWxzIG92ZXJsYXBcbiAgICAgICAgICAgIC8vIGRvbid0IGF1dG8tYW5nbGUgYXQgYWxsIGZvciBsb2cgYXhlcyB3aXRoXG4gICAgICAgICAgICAvLyBiYXNlIGFuZCBkaWdpdCBmb3JtYXRcbiAgICAgICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcgJiYgIWlzTnVtZXJpYyhheC50aWNrYW5nbGUpICYmXG4gICAgICAgICAgICAgICAgICAgIChheC50eXBlICE9PSAnbG9nJyB8fCBTdHJpbmcoYXguZHRpY2spLmNoYXJBdCgwKSAhPT0gJ0QnKSkge1xuICAgICAgICAgICAgICAgIHZhciBsYmJBcnJheSA9IFtdO1xuICAgICAgICAgICAgICAgIHRpY2tMYWJlbHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc0xhYmVsID0gcy5zZWxlY3QoJy50ZXh0LW1hdGgtZ3JvdXAnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBheC5sMnAoZC54KTtcbiAgICAgICAgICAgICAgICAgICAgaWYodGhpc0xhYmVsLmVtcHR5KCkpIHRoaXNMYWJlbCA9IHMuc2VsZWN0KCd0ZXh0Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGJiID0gRHJhd2luZy5iQm94KHRoaXNMYWJlbC5ub2RlKCkpO1xuXG4gICAgICAgICAgICAgICAgICAgIGxiYkFycmF5LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWdub3JlIGFib3V0IHksIGp1c3QgZGVhbCB3aXRoIHggb3ZlcmxhcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvdHRvbTogMTAsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogeCAtIGJiLndpZHRoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGltcG9zZSBhIDJweCBnYXBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0OiB4ICsgYmIud2lkdGggLyAyICsgMixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBiYi53aWR0aCArIDJcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGJiQXJyYXkubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKExpYi5iQm94SW50ZXJzZWN0KGxiYkFycmF5W2ldLCBsYmJBcnJheVtpICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbnkgb3ZlcmxhcCBhdCBhbGwgLSBzZXQgMzAgZGVncmVlc1xuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b2FuZ2xlID0gMzA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihhdXRvYW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRpY2tzcGFjaW5nID0gTWF0aC5hYnMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZhbHNbdmFscy5sZW5ndGggLSAxXS54IC0gdmFsc1swXS54KSAqIGF4Ll9tXG4gICAgICAgICAgICAgICAgICAgICAgICApIC8gKHZhbHMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHRpY2tzcGFjaW5nIDwgbWF4Rm9udFNpemUgKiAyLjUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9hbmdsZSA9IDkwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uTGFiZWxzKHRpY2tMYWJlbHMsIGF1dG9hbmdsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF4Ll9sYXN0YW5nbGUgPSBhdXRvYW5nbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgYXhpcyB0aXRsZVxuICAgICAgICAgICAgLy8gKHNvIGl0IGNhbiBtb3ZlIG91dCBvZiB0aGUgd2F5IGlmIG5lZWRlZClcbiAgICAgICAgICAgIC8vIFRPRE86IHNlcGFyYXRlIG91dCBzY29vdCBzbyB3ZSBkb24ndCBuZWVkIHRvIGRvXG4gICAgICAgICAgICAvLyBhIGZ1bGwgcmVkcmF3IG9mIHRoZSB0aXRsZSAobW9zdGx5IHJlbGV2YW50IGZvciBNYXRoSmF4KVxuICAgICAgICAgICAgZHJhd0F4VGl0bGUoKTtcbiAgICAgICAgICAgIHJldHVybiBheGlkICsgJyBkb25lJztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNhbGNCb3VuZGluZ0JveCgpIHtcbiAgICAgICAgICAgIGlmKGF4LnNob3d0aWNrbGFiZWxzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdkQkIgPSBnZC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgICAgICB2YXIgYkJveCA9IGNvbnRhaW5lci5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAqIHRoZSB3YXkgd2UncmUgZ29pbmcgdG8gdXNlIHRoaXMsIHRoZSBwb3NpdGlvbmluZyB0aGF0IG1hdHRlcnNcbiAgICAgICAgICAgICAgICAgKiBpcyByZWxhdGl2ZSB0byB0aGUgb3JpZ2luIG9mIGdkLiBUaGlzIGlzIGltcG9ydGFudCBwYXJ0aWN1bGFybHlcbiAgICAgICAgICAgICAgICAgKiBpZiBnZCBpcyBzY3JvbGxhYmxlLCBhbmQgbWF5IGhhdmUgYmVlbiBzY3JvbGxlZCBiZXR3ZWVuIHRoZSB0aW1lXG4gICAgICAgICAgICAgICAgICogd2UgY2FsY3VsYXRlIHRoaXMgYW5kIHRoZSB0aW1lIHdlIHVzZSBpdFxuICAgICAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAgICAgYXguX2JvdW5kaW5nQm94ID0ge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYkJveC53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBiQm94LmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogYkJveC5sZWZ0IC0gZ2RCQi5sZWZ0LFxuICAgICAgICAgICAgICAgICAgICByaWdodDogYkJveC5yaWdodCAtIGdkQkIubGVmdCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiBiQm94LnRvcCAtIGdkQkIudG9wLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IGJCb3guYm90dG9tIC0gZ2RCQi50b3BcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgICAgICAgICAgICAgIHZhciBwb3M7XG5cbiAgICAgICAgICAgICAgICAvLyBzZXQgZHVtbXkgYmJveCBmb3IgdGlja2xhYmVsLWxlc3MgYXhlc1xuXG4gICAgICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgICAgICBwb3MgPSBheC5hbmNob3IgPT09ICdmcmVlJyA/XG4gICAgICAgICAgICAgICAgICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gYXgucG9zaXRpb24pIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGdzLnQgKyBncy5oICogKDEgLSBheC5fYW5jaG9yQXhpcy5kb21haW5be2JvdHRvbTogMCwgdG9wOiAxfVtheC5zaWRlXV0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGF4Ll9ib3VuZGluZ0JveCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm90dG9tOiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBheC5fb2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGF4Ll9sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb3MgPSBheC5hbmNob3IgPT09ICdmcmVlJyA/XG4gICAgICAgICAgICAgICAgICAgICAgICBncy5sICsgZ3MudyAqIGF4LnBvc2l0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGdzLmwgKyBncy53ICogYXguX2FuY2hvckF4aXMuZG9tYWluW3tsZWZ0OiAwLCByaWdodDogMX1bYXguc2lkZV1dO1xuXG4gICAgICAgICAgICAgICAgICAgIGF4Ll9ib3VuZGluZ0JveCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQ6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3R0b206IGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBheC5fb2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBheC5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IDBcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBmb3Igc3Bpa2VsaW5lczogd2hhdCdzIHRoZSBmdWxsIGRvbWFpbiBvZiBwb3NpdGlvbnMgaW4gdGhlXG4gICAgICAgICAgICAgKiBvcHBvc2l0ZSBkaXJlY3Rpb24gdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgYXhpcz9cbiAgICAgICAgICAgICAqIFRoaXMgbWVhbnMgYW55IGF4ZXMgdGhhdCB3ZSBtYWtlIGEgc3VicGxvdCB3aXRoLCBwbHVzIHRoZVxuICAgICAgICAgICAgICogcG9zaXRpb24gb2YgdGhlIGF4aXMgaXRzZWxmIGlmIGl0J3MgZnJlZS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYoc3VicGxvdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnVsbFJhbmdlID0gYXguX2NvdW50ZXJTcGFuID0gW0luZmluaXR5LCAtSW5maW5pdHldO1xuXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN1YnBsb3QgPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90c1tpXV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb3VudGVyQXhpcyA9IHN1YnBsb3RbKGF4TGV0dGVyID09PSAneCcpID8gJ3lheGlzJyA6ICd4YXhpcyddO1xuXG4gICAgICAgICAgICAgICAgICAgIGV4dGVuZFJhbmdlKGZ1bGxSYW5nZSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlckF4aXMuX29mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJBeGlzLl9vZmZzZXQgKyBjb3VudGVyQXhpcy5fbGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGF4LmFuY2hvciA9PT0gJ2ZyZWUnKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4dGVuZFJhbmdlKGZ1bGxSYW5nZSwgKGF4TGV0dGVyID09PSAneCcpID9cbiAgICAgICAgICAgICAgICAgICAgICAgIFtheC5fYm91bmRpbmdCb3guYm90dG9tLCBheC5fYm91bmRpbmdCb3gudG9wXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbYXguX2JvdW5kaW5nQm94LnJpZ2h0LCBheC5fYm91bmRpbmdCb3gubGVmdF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXh0ZW5kUmFuZ2UocmFuZ2UsIG5ld1JhbmdlKSB7XG4gICAgICAgICAgICAgICAgcmFuZ2VbMF0gPSBNYXRoLm1pbihyYW5nZVswXSwgbmV3UmFuZ2VbMF0pO1xuICAgICAgICAgICAgICAgIHJhbmdlWzFdID0gTWF0aC5tYXgocmFuZ2VbMV0sIG5ld1JhbmdlWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGRvQXV0b01hcmdpbnMoKSB7XG4gICAgICAgICAgICB2YXIgcHVzaEtleSA9IGF4Ll9uYW1lICsgJy5hdXRvbWFyZ2luJztcbiAgICAgICAgICAgIGlmKGF4TGV0dGVyICE9PSAneCcgJiYgYXhMZXR0ZXIgIT09ICd5JykgeyByZXR1cm47IH1cbiAgICAgICAgICAgIGlmKCFheC5hdXRvbWFyZ2luKSB7XG4gICAgICAgICAgICAgICAgUGxvdHMuYXV0b01hcmdpbihnZCwgcHVzaEtleSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcyA9IGF4LnNpZGVbMF07XG4gICAgICAgICAgICB2YXIgcHVzaCA9IHt4OiAwLCB5OiAwLCByOiAwLCBsOiAwLCB0OiAwLCBiOiAwfTtcblxuICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgIHB1c2gueSA9IChheC5hbmNob3IgPT09ICdmcmVlJyA/IGF4LnBvc2l0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4Ll9hbmNob3JBeGlzLmRvbWFpbltzID09PSAndCcgPyAxIDogMF0pO1xuICAgICAgICAgICAgICAgIHB1c2hbc10gKz0gYXguX2JvdW5kaW5nQm94LmhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHB1c2gueCA9IChheC5hbmNob3IgPT09ICdmcmVlJyA/IGF4LnBvc2l0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4Ll9hbmNob3JBeGlzLmRvbWFpbltzID09PSAncicgPyAxIDogMF0pO1xuICAgICAgICAgICAgICAgIHB1c2hbc10gKz0gYXguX2JvdW5kaW5nQm94LndpZHRoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihheC50aXRsZSAhPT0gZnVsbExheW91dC5fZGZsdFRpdGxlW2F4TGV0dGVyXSkge1xuICAgICAgICAgICAgICAgIHB1c2hbc10gKz0gYXgudGl0bGVmb250LnNpemU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIHB1c2hLZXksIHB1c2gpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRvbmUgPSBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgYWxsTGFiZWxzUmVhZHksXG4gICAgICAgICAgICBmaXhMYWJlbE92ZXJsYXBzLFxuICAgICAgICAgICAgY2FsY0JvdW5kaW5nQm94LFxuICAgICAgICAgICAgZG9BdXRvTWFyZ2luc1xuICAgICAgICBdKTtcbiAgICAgICAgaWYoZG9uZSAmJiBkb25lLnRoZW4pIGdkLl9wcm9taXNlcy5wdXNoKGRvbmUpO1xuICAgICAgICByZXR1cm4gZG9uZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3QXhUaXRsZSgpIHtcbiAgICAgICAgaWYoc2tpcFRpdGxlKSByZXR1cm47XG5cbiAgICAgICAgLy8gbm93IHRoaXMgb25seSBhcHBsaWVzIHRvIHJlZ3VsYXIgY2FydGVzaWFuIGF4ZXM7IGNvbG9yYmFycyBhbmRcbiAgICAgICAgLy8gb3RoZXJzIEFMV0FZUyBjYWxsIGRvVGlja3Mgd2l0aCBza2lwVGl0bGU9dHJ1ZSBzbyB0aGV5IGNhblxuICAgICAgICAvLyBjb25maWd1cmUgdGhlaXIgb3duIHRpdGxlcy5cblxuICAgICAgICAvLyByYW5nZXNsaWRlciB0YWtlcyBvdmVyIGEgYm90dG9tIHRpdGxlIHNvIGRyb3AgaXQgaGVyZVxuICAgICAgICBpZihheC5yYW5nZXNsaWRlciAmJiBheC5yYW5nZXNsaWRlci52aXNpYmxlICYmIGF4Ll9ib3VuZGluZ0JveCAmJiBheC5zaWRlID09PSAnYm90dG9tJykgcmV0dXJuO1xuXG4gICAgICAgIHZhciBhdm9pZCA9IHtcbiAgICAgICAgICAgIHNlbGVjdGlvbjogdGlja0xhYmVscyxcbiAgICAgICAgICAgIHNpZGU6IGF4LnNpZGVcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhpZC5jaGFyQXQoMCk7XG4gICAgICAgIHZhciBncyA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgICAgICB2YXIgb2Zmc2V0QmFzZSA9IDEuNTtcbiAgICAgICAgdmFyIGZvbnRTaXplID0gYXgudGl0bGVmb250LnNpemU7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSwgY291bnRlckF4aXMsIHgsIHk7XG5cbiAgICAgICAgaWYodGlja0xhYmVscy5zaXplKCkpIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2xhdGlvbiA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKHRpY2tMYWJlbHMubm9kZSgpLnBhcmVudE5vZGUpO1xuICAgICAgICAgICAgYXZvaWQub2Zmc2V0TGVmdCA9IHRyYW5zbGF0aW9uLng7XG4gICAgICAgICAgICBhdm9pZC5vZmZzZXRUb3AgPSB0cmFuc2xhdGlvbi55O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRpdGxlU3RhbmRvZmYgPSAxMCArIGZvbnRTaXplICogb2Zmc2V0QmFzZSArXG4gICAgICAgICAgICAoYXgubGluZXdpZHRoID8gYXgubGluZXdpZHRoIC0gMSA6IDApO1xuXG4gICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgIGNvdW50ZXJBeGlzID0gKGF4LmFuY2hvciA9PT0gJ2ZyZWUnKSA/XG4gICAgICAgICAgICAgICAge19vZmZzZXQ6IGdzLnQgKyAoMSAtIChheC5wb3NpdGlvbiB8fCAwKSkgKiBncy5oLCBfbGVuZ3RoOiAwfSA6XG4gICAgICAgICAgICAgICAgYXhpc0lkcy5nZXRGcm9tSWQoZ2QsIGF4LmFuY2hvcik7XG5cbiAgICAgICAgICAgIHggPSBheC5fb2Zmc2V0ICsgYXguX2xlbmd0aCAvIDI7XG5cbiAgICAgICAgICAgIGlmKGF4LnNpZGUgPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgeSA9IC10aXRsZVN0YW5kb2ZmIC0gZm9udFNpemUgKiAoYXguc2hvd3RpY2tsYWJlbHMgPyAxIDogMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB5ID0gY291bnRlckF4aXMuX2xlbmd0aCArIHRpdGxlU3RhbmRvZmYgK1xuICAgICAgICAgICAgICAgICAgICBmb250U2l6ZSAqIChheC5zaG93dGlja2xhYmVscyA/IDEuNSA6IDAuNSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB5ICs9IGNvdW50ZXJBeGlzLl9vZmZzZXQ7XG5cbiAgICAgICAgICAgIGlmKCFhdm9pZC5zaWRlKSBhdm9pZC5zaWRlID0gJ2JvdHRvbSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb3VudGVyQXhpcyA9IChheC5hbmNob3IgPT09ICdmcmVlJykgP1xuICAgICAgICAgICAgICAgIHtfb2Zmc2V0OiBncy5sICsgKGF4LnBvc2l0aW9uIHx8IDApICogZ3MudywgX2xlbmd0aDogMH0gOlxuICAgICAgICAgICAgICAgIGF4aXNJZHMuZ2V0RnJvbUlkKGdkLCBheC5hbmNob3IpO1xuXG4gICAgICAgICAgICB5ID0gYXguX29mZnNldCArIGF4Ll9sZW5ndGggLyAyO1xuICAgICAgICAgICAgaWYoYXguc2lkZSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgIHggPSBjb3VudGVyQXhpcy5fbGVuZ3RoICsgdGl0bGVTdGFuZG9mZiArXG4gICAgICAgICAgICAgICAgICAgIGZvbnRTaXplICogKGF4LnNob3d0aWNrbGFiZWxzID8gMSA6IDAuNSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB4ID0gLXRpdGxlU3RhbmRvZmYgLSBmb250U2l6ZSAqIChheC5zaG93dGlja2xhYmVscyA/IDAuNSA6IDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeCArPSBjb3VudGVyQXhpcy5fb2Zmc2V0O1xuXG4gICAgICAgICAgICB0cmFuc2Zvcm0gPSB7cm90YXRlOiAnLTkwJywgb2Zmc2V0OiAwfTtcbiAgICAgICAgICAgIGlmKCFhdm9pZC5zaWRlKSBhdm9pZC5zaWRlID0gJ2xlZnQnO1xuICAgICAgICB9XG5cbiAgICAgICAgVGl0bGVzLmRyYXcoZ2QsIGF4aWQgKyAndGl0bGUnLCB7XG4gICAgICAgICAgICBwcm9wQ29udGFpbmVyOiBheCxcbiAgICAgICAgICAgIHByb3BOYW1lOiBheC5fbmFtZSArICcudGl0bGUnLFxuICAgICAgICAgICAgcGxhY2Vob2xkZXI6IGZ1bGxMYXlvdXQuX2RmbHRUaXRsZVtheExldHRlcl0sXG4gICAgICAgICAgICBhdm9pZDogYXZvaWQsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHt4OiB4LCB5OiB5LCAndGV4dC1hbmNob3InOiAnbWlkZGxlJ31cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0dyaWQocGxvdGluZm8sIGNvdW50ZXJheGlzKSB7XG4gICAgICAgIGlmKGZ1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykgcmV0dXJuO1xuXG4gICAgICAgIHZhciBncmlkY29udGFpbmVyID0gcGxvdGluZm8uZ3JpZGxheWVyLnNlbGVjdEFsbCgnLicgKyBheGlkKTtcbiAgICAgICAgdmFyIHpsY29udGFpbmVyID0gcGxvdGluZm8uemVyb2xpbmVsYXllcjtcbiAgICAgICAgdmFyIGdyaWRwYXRoID0gYXguX2dyaWRwYXRoIHx8ICgoYXhMZXR0ZXIgPT09ICd4JyA/XG4gICAgICAgICAgICAgICAgKCdNMCwnICsgY291bnRlcmF4aXMuX29mZnNldCArICd2JykgOlxuICAgICAgICAgICAgICAgICgnTScgKyBjb3VudGVyYXhpcy5fb2Zmc2V0ICsgJywwaCcpXG4gICAgICAgICAgICApICsgY291bnRlcmF4aXMuX2xlbmd0aCk7XG4gICAgICAgIHZhciBncmlkID0gZ3JpZGNvbnRhaW5lci5zZWxlY3RBbGwoJ3BhdGguJyArIGdjbHMpXG4gICAgICAgICAgICAuZGF0YSgoYXguc2hvd2dyaWQgPT09IGZhbHNlKSA/IFtdIDogdmFsc0NsaXBwZWQsIGRhdGFmbik7XG4gICAgICAgIGdyaWQuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKGdjbHMsIDEpXG4gICAgICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCAxKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCBncmlkcGF0aClcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihheC56ZXJvbGluZSAmJiAoYXgudHlwZSA9PT0gJ2xpbmVhcicgfHwgYXgudHlwZSA9PT0gJy0nKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5hYnMoZC54KSA8IGF4LmR0aWNrIC8gMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgZ3JpZC5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2ZuKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBheC5ncmlkY29sb3IgfHwgJyNkZGQnKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBncmlkV2lkdGggKyAncHgnKTtcbiAgICAgICAgaWYodHlwZW9mIGdyaWRwYXRoID09PSAnZnVuY3Rpb24nKSBncmlkLmF0dHIoJ2QnLCBncmlkcGF0aCk7XG4gICAgICAgIGdyaWQuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIHplcm8gbGluZVxuICAgICAgICBpZih6bGNvbnRhaW5lcikge1xuICAgICAgICAgICAgdmFyIHpsRGF0YSA9IHt4OiAwLCBpZDogYXhpZH07XG4gICAgICAgICAgICB2YXIgc2hvd1psID0gYXhlcy5zaG91bGRTaG93WmVyb0xpbmUoZ2QsIGF4LCBjb3VudGVyYXhpcyk7XG4gICAgICAgICAgICB2YXIgemwgPSB6bGNvbnRhaW5lci5zZWxlY3RBbGwoJ3BhdGguJyArIHpjbHMpXG4gICAgICAgICAgICAgICAgLmRhdGEoc2hvd1psID8gW3psRGF0YV0gOiBbXSk7XG4gICAgICAgICAgICB6bC5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoemNscywgMSkuY2xhc3NlZCgnemwnLCAxKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIDEpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCBncmlkcGF0aClcbiAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdXNlIHRoZSBmYWN0IHRoYXQgb25seSBvbmUgZWxlbWVudCBjYW4gZW50ZXIgdG8gdHJpZ2dlciBhIHNvcnQuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHNldmVyYWwgemVyb2xpbmVzIGVudGVyIGF0IHRoZSBzYW1lIHRpbWUgd2Ugd2lsbCBzb3J0IG9uY2UgcGVyLFxuICAgICAgICAgICAgICAgICAgICAvLyBidXQgZ2VuZXJhbGx5IHRoaXMgc2hvdWxkIGJlIGEgbWluaW1hbCBvdmVyaGVhZC5cbiAgICAgICAgICAgICAgICAgICAgemxjb250YWluZXIuc2VsZWN0QWxsKCdwYXRoJykuc29ydChmdW5jdGlvbihkYSwgZGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBheGlzSWRzLmlkU29ydChkYS5pZCwgZGIuaWQpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHpsLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm4pXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBheC56ZXJvbGluZWNvbG9yIHx8IENvbG9yLmRlZmF1bHRMaW5lKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgemVyb0xpbmVXaWR0aCArICdweCcpO1xuICAgICAgICAgICAgemwuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaW5kZXBlbmRlbnQpIHtcbiAgICAgICAgZHJhd1RpY2tzKGF4Ll9heGlzbGF5ZXIsIHRpY2twYXRoZm4oYXguX3BvcyArIHBhZCAqIHRpY2tzaWduWzJdLCB0aWNrc2lnblsyXSAqIGF4LnRpY2tsZW4pKTtcbiAgICAgICAgaWYoYXguX2NvdW50ZXJheGlzKSB7XG4gICAgICAgICAgICB2YXIgZmljdGlvbmFsUGxvdGluZm8gPSB7XG4gICAgICAgICAgICAgICAgZ3JpZGxheWVyOiBheC5fZ3JpZGxheWVyLFxuICAgICAgICAgICAgICAgIHplcm9saW5lbGF5ZXI6IGF4Ll96ZXJvbGluZWxheWVyXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZHJhd0dyaWQoZmljdGlvbmFsUGxvdGluZm8sIGF4Ll9jb3VudGVyYXhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRyYXdMYWJlbHMoYXguX2F4aXNsYXllciwgYXguX3Bvcyk7XG4gICAgfVxuICAgIGVsc2UgaWYoZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICBzdWJwbG90cyA9IGF4ZXMuZ2V0U3VicGxvdHMoZ2QsIGF4KTtcblxuICAgICAgICAvLyBrZWVwIHRyYWNrIG9mIHdoaWNoIHN1YnBsb3RzIChieSBtYWluIGNvbnRlcmF4aXMpIHdlJ3ZlIGFscmVhZHlcbiAgICAgICAgLy8gZHJhd24gZ3JpZHMgZm9yLCBzbyB3ZSBkb24ndCBvdmVyZHJhdyBvdmVybGF5aW5nIHN1YnBsb3RzXG4gICAgICAgIHZhciBmaW5pc2hlZEdyaWRzID0ge307XG5cbiAgICAgICAgc3VicGxvdHMubWFwKGZ1bmN0aW9uKHN1YnBsb3QpIHtcbiAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuICAgICAgICAgICAgdmFyIGNvdW50ZXJBeGlzID0gcGxvdGluZm9bY291bnRlckxldHRlciArICdheGlzJ107XG5cbiAgICAgICAgICAgIHZhciBtYWluQ291bnRlcklEID0gY291bnRlckF4aXMuX21haW5BeGlzLl9pZDtcbiAgICAgICAgICAgIGlmKGZpbmlzaGVkR3JpZHNbbWFpbkNvdW50ZXJJRF0pIHJldHVybjtcbiAgICAgICAgICAgIGZpbmlzaGVkR3JpZHNbbWFpbkNvdW50ZXJJRF0gPSAxO1xuXG4gICAgICAgICAgICBkcmF3R3JpZChwbG90aW5mbywgY291bnRlckF4aXMsIHN1YnBsb3QpO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgbWFpblN1YnBsb3QgPSBheC5fbWFpblN1YnBsb3Q7XG4gICAgICAgIHZhciBtYWluUGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1ttYWluU3VicGxvdF07XG4gICAgICAgIHZhciB0aWNrU3VicGxvdHMgPSBbXTtcblxuICAgICAgICBpZihheC50aWNrcykge1xuICAgICAgICAgICAgdmFyIG1haW5TaWduID0gdGlja3NpZ25bMl07XG4gICAgICAgICAgICB2YXIgdGlja3BhdGggPSB0aWNrcGF0aGZuKGF4Ll9tYWluTGluZVBvc2l0aW9uICsgcGFkICogbWFpblNpZ24sIG1haW5TaWduICogYXgudGlja2xlbik7XG4gICAgICAgICAgICBpZihheC5fYW5jaG9yQXhpcyAmJiBheC5taXJyb3IgJiYgYXgubWlycm9yICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgdGlja3BhdGggKz0gdGlja3BhdGhmbihheC5fbWFpbk1pcnJvclBvc2l0aW9uIC0gcGFkICogbWFpblNpZ24sIC1tYWluU2lnbiAqIGF4LnRpY2tsZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZHJhd1RpY2tzKG1haW5QbG90aW5mb1theExldHRlciArICdheGlzbGF5ZXInXSwgdGlja3BhdGgpO1xuXG4gICAgICAgICAgICB0aWNrU3VicGxvdHMgPSBPYmplY3Qua2V5cyhheC5fbGluZXBvc2l0aW9ucyB8fCB7fSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aWNrU3VicGxvdHMubWFwKGZ1bmN0aW9uKHN1YnBsb3QpIHtcbiAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuXG4gICAgICAgICAgICB2YXIgY29udGFpbmVyID0gcGxvdGluZm9bYXhMZXR0ZXIgKyAnYXhpc2xheWVyJ107XG5cbiAgICAgICAgICAgIC8vIFtib3R0b20gb3IgbGVmdCwgdG9wIG9yIHJpZ2h0XVxuICAgICAgICAgICAgLy8gZnJlZSBhbmQgbWFpbiBhcmUgaGFuZGxlZCBhYm92ZVxuICAgICAgICAgICAgdmFyIGxpbmVwb3NpdGlvbnMgPSBheC5fbGluZXBvc2l0aW9uc1tzdWJwbG90XSB8fCBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdGlja1BhdGhTaWRlKHNpZGVpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRzaWduID0gdGlja3NpZ25bc2lkZWldO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrcGF0aGZuKGxpbmVwb3NpdGlvbnNbc2lkZWldICsgcGFkICogdHNpZ24sIHRzaWduICogYXgudGlja2xlbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRyYXdUaWNrcyhjb250YWluZXIsIHRpY2tQYXRoU2lkZSgwKSArIHRpY2tQYXRoU2lkZSgxKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtYWluQ29udGFpbmVyID0gbWFpblBsb3RpbmZvW2F4TGV0dGVyICsgJ2F4aXNsYXllciddO1xuXG4gICAgICAgIHJldHVybiBkcmF3TGFiZWxzKG1haW5Db250YWluZXIsIGF4Ll9tYWluTGluZVBvc2l0aW9uKTtcbiAgICB9XG59O1xuXG5heGVzLnNob3VsZFNob3daZXJvTGluZSA9IGZ1bmN0aW9uKGdkLCBheCwgY291bnRlckF4aXMpIHtcbiAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcbiAgICByZXR1cm4gKFxuICAgICAgICAocm5nWzBdICogcm5nWzFdIDw9IDApICYmXG4gICAgICAgIGF4Lnplcm9saW5lICYmXG4gICAgICAgIChheC50eXBlID09PSAnbGluZWFyJyB8fCBheC50eXBlID09PSAnLScpICYmXG4gICAgICAgIGF4Ll92YWxzQ2xpcHBlZC5sZW5ndGggJiZcbiAgICAgICAgKFxuICAgICAgICAgICAgY2xpcEVuZHMoYXgsIDApIHx8XG4gICAgICAgICAgICAhYW55Q291bnRlckF4TGluZUF0WmVybyhnZCwgYXgsIGNvdW50ZXJBeGlzLCBybmcpIHx8XG4gICAgICAgICAgICBoYXNCYXJzT3JGaWxsKGdkLCBheClcbiAgICAgICAgKVxuICAgICk7XG59O1xuXG5mdW5jdGlvbiBjbGlwRW5kcyhheCwgbCkge1xuICAgIHZhciBwID0gYXgubDJwKGwpO1xuICAgIHJldHVybiAocCA+IDEgJiYgcCA8IGF4Ll9sZW5ndGggLSAxKTtcbn1cblxuZnVuY3Rpb24gYW55Q291bnRlckF4TGluZUF0WmVybyhnZCwgYXgsIGNvdW50ZXJBeGlzLCBybmcpIHtcbiAgICB2YXIgbWFpbkNvdW50ZXJBeGlzID0gY291bnRlckF4aXMuX21haW5BeGlzO1xuICAgIGlmKCFtYWluQ291bnRlckF4aXMpIHJldHVybjtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgY291bnRlckxldHRlciA9IGF4ZXMuY291bnRlckxldHRlcihheC5faWQpO1xuXG4gICAgdmFyIHplcm9Qb3NpdGlvbiA9IGF4Ll9vZmZzZXQgKyAoXG4gICAgICAgICgoTWF0aC5hYnMocm5nWzBdKSA8IE1hdGguYWJzKHJuZ1sxXSkpID09PSAoYXhMZXR0ZXIgPT09ICd4JykpID9cbiAgICAgICAgMCA6IGF4Ll9sZW5ndGhcbiAgICApO1xuXG4gICAgZnVuY3Rpb24gbGluZU5lYXJaZXJvKGF4Mikge1xuICAgICAgICBpZighYXgyLnNob3dsaW5lIHx8ICFheDIubGluZXdpZHRoKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHZhciB0b2xlcmFuY2UgPSBNYXRoLm1heCgoYXgyLmxpbmV3aWR0aCArIGF4Lnplcm9saW5ld2lkdGgpIC8gMiwgMSk7XG5cbiAgICAgICAgZnVuY3Rpb24gY2xvc2VFbm91Z2gocG9zMikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBwb3MyID09PSAnbnVtYmVyJyAmJiBNYXRoLmFicyhwb3MyIC0gemVyb1Bvc2l0aW9uKSA8IHRvbGVyYW5jZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsb3NlRW5vdWdoKGF4Mi5fbWFpbkxpbmVQb3NpdGlvbikgfHwgY2xvc2VFbm91Z2goYXgyLl9tYWluTWlycm9yUG9zaXRpb24pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGluZVBvc2l0aW9ucyA9IGF4Mi5fbGluZXBvc2l0aW9ucyB8fCB7fTtcbiAgICAgICAgZm9yKHZhciBrIGluIGxpbmVQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgIGlmKGNsb3NlRW5vdWdoKGxpbmVQb3NpdGlvbnNba11bMF0pIHx8IGNsb3NlRW5vdWdoKGxpbmVQb3NpdGlvbnNba11bMV0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tjb3VudGVyQXhpcy5fbWFpblN1YnBsb3RdO1xuICAgIGlmKCEocGxvdGluZm8ubWFpbnBsb3RpbmZvIHx8IHBsb3RpbmZvKS5vdmVybGF5cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGxpbmVOZWFyWmVybyhjb3VudGVyQXhpcywgemVyb1Bvc2l0aW9uKTtcbiAgICB9XG5cbiAgICB2YXIgY291bnRlckxldHRlckF4ZXMgPSBheGVzLmxpc3QoZ2QsIGNvdW50ZXJMZXR0ZXIpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb3VudGVyTGV0dGVyQXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY291bnRlckF4aXMyID0gY291bnRlckxldHRlckF4ZXNbaV07XG4gICAgICAgIGlmKFxuICAgICAgICAgICAgY291bnRlckF4aXMyLl9tYWluQXhpcyA9PT0gbWFpbkNvdW50ZXJBeGlzICYmXG4gICAgICAgICAgICBsaW5lTmVhclplcm8oY291bnRlckF4aXMyLCB6ZXJvUG9zaXRpb24pXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhc0JhcnNPckZpbGwoZ2QsIGF4KSB7XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgIHZhciBzdWJwbG90ID0gYXguX21haW5TdWJwbG90O1xuICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgKHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXMpID09PSBzdWJwbG90ICYmXG4gICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JhcicpICYmIHRyYWNlLm9yaWVudGF0aW9uID09PSB7eDogJ2gnLCB5OiAndid9W2F4TGV0dGVyXSB8fFxuICAgICAgICAgICAgICAgIHRyYWNlLmZpbGwgJiYgdHJhY2UuZmlsbC5jaGFyQXQodHJhY2UuZmlsbC5sZW5ndGggLSAxKSA9PT0gYXhMZXR0ZXJcbiAgICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogRmluZCBhbGwgbWFyZ2luIHB1c2hlcnMgZm9yIDJEIGF4ZXMgYW5kIHJlc2VydmUgdGhlbSBmb3IgbGF0ZXIgdXNlXG4gKiBCb3RoIGxhYmVsIGFuZCByYW5nZXNsaWRlciBhdXRvbWFyZ2luIGNhbGN1bGF0aW9ucyBoYXBwZW4gbGF0ZXIgc29cbiAqIHdlIG5lZWQgdG8gZXhwbGljaXRseSBhbGxvdyB0aGVpciBpZHMgaW4gb3JkZXIgdG8gbm90IGRlbGV0ZSB0aGVtLlxuICpcbiAqIFRPRE86IGNhbiB3ZSBwdWxsIHRoZSBhY3R1YWwgYXV0b21hcmdpbiBjYWxscyBmb3J3YXJkIHRvIGF2b2lkIHRoaXMgaGFjaz9cbiAqIFdlJ3JlIHByb2JhYmx5IGFsc28gZG9pbmcgbXVsdGlwbGUgcmVkcmF3cyBpbiB0aGlzIGNhc2UsIHdvdWxkIGJlIGZhc3RlclxuICogaWYgd2UgY2FuIGp1c3QgZG8gdGhlIHdob2xlIGNhbGN1bGF0aW9uIGFoZWFkIG9mIHRpbWUgYW5kIGRyYXcgb25jZS5cbiAqL1xuYXhlcy5hbGxvd0F1dG9NYXJnaW4gPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBheExpc3QgPSBheGVzLmxpc3QoZ2QsICcnLCB0cnVlKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgaWYoYXguYXV0b21hcmdpbikge1xuICAgICAgICAgICAgUGxvdHMuYWxsb3dBdXRvTWFyZ2luKGdkLCBheC5fbmFtZSArICcuYXV0b21hcmdpbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGF4LnJhbmdlc2xpZGVyICYmIGF4LnJhbmdlc2xpZGVyLnZpc2libGUpIHtcbiAgICAgICAgICAgIFBsb3RzLmFsbG93QXV0b01hcmdpbihnZCwgJ3Jhbmdlc2xpZGVyJyArIGF4Ll9pZCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBzd2FwIGFsbCB0aGUgcHJlc2VudGF0aW9uIGF0dHJpYnV0ZXMgb2YgdGhlIGF4ZXMgc2hvd2luZyB0aGVzZSB0cmFjZXNcbmF4ZXMuc3dhcCA9IGZ1bmN0aW9uKGdkLCB0cmFjZXMpIHtcbiAgICB2YXIgYXhHcm91cHMgPSBtYWtlQXhpc0dyb3VwcyhnZCwgdHJhY2VzKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzd2FwQXhpc0dyb3VwKGdkLCBheEdyb3Vwc1tpXS54LCBheEdyb3Vwc1tpXS55KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBtYWtlQXhpc0dyb3VwcyhnZCwgdHJhY2VzKSB7XG4gICAgdmFyIGdyb3VwcyA9IFtdLFxuICAgICAgICBpLFxuICAgICAgICBqO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBncm91cHNpID0gW10sXG4gICAgICAgICAgICB4aSA9IGdkLl9mdWxsRGF0YVt0cmFjZXNbaV1dLnhheGlzLFxuICAgICAgICAgICAgeWkgPSBnZC5fZnVsbERhdGFbdHJhY2VzW2ldXS55YXhpcztcbiAgICAgICAgaWYoIXhpIHx8ICF5aSkgY29udGludWU7IC8vIG5vdCBhIDJEIGNhcnRlc2lhbiB0cmFjZT9cblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBncm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGdyb3Vwc1tqXS54LmluZGV4T2YoeGkpICE9PSAtMSB8fCBncm91cHNbal0ueS5pbmRleE9mKHlpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBncm91cHNpLnB1c2goaik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZighZ3JvdXBzaS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGdyb3Vwcy5wdXNoKHt4OiBbeGldLCB5OiBbeWldfSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBncm91cDAgPSBncm91cHNbZ3JvdXBzaVswXV0sXG4gICAgICAgICAgICBncm91cGo7XG5cbiAgICAgICAgaWYoZ3JvdXBzaS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDE7IGogPCBncm91cHNpLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBqID0gZ3JvdXBzW2dyb3Vwc2lbal1dO1xuICAgICAgICAgICAgICAgIG1lcmdlQXhpc0dyb3Vwcyhncm91cDAueCwgZ3JvdXBqLngpO1xuICAgICAgICAgICAgICAgIG1lcmdlQXhpc0dyb3Vwcyhncm91cDAueSwgZ3JvdXBqLnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG1lcmdlQXhpc0dyb3Vwcyhncm91cDAueCwgW3hpXSk7XG4gICAgICAgIG1lcmdlQXhpc0dyb3Vwcyhncm91cDAueSwgW3lpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdyb3Vwcztcbn1cblxuZnVuY3Rpb24gbWVyZ2VBeGlzR3JvdXBzKGludG9TZXQsIGZyb21TZXQpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnJvbVNldC5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihpbnRvU2V0LmluZGV4T2YoZnJvbVNldFtpXSkgPT09IC0xKSBpbnRvU2V0LnB1c2goZnJvbVNldFtpXSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzd2FwQXhpc0dyb3VwKGdkLCB4SWRzLCB5SWRzKSB7XG4gICAgdmFyIGksXG4gICAgICAgIGosXG4gICAgICAgIHhGdWxsQXhlcyA9IFtdLFxuICAgICAgICB5RnVsbEF4ZXMgPSBbXSxcbiAgICAgICAgbGF5b3V0ID0gZ2QubGF5b3V0O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgeElkcy5sZW5ndGg7IGkrKykgeEZ1bGxBeGVzLnB1c2goYXhlcy5nZXRGcm9tSWQoZ2QsIHhJZHNbaV0pKTtcbiAgICBmb3IoaSA9IDA7IGkgPCB5SWRzLmxlbmd0aDsgaSsrKSB5RnVsbEF4ZXMucHVzaChheGVzLmdldEZyb21JZChnZCwgeUlkc1tpXSkpO1xuXG4gICAgdmFyIGFsbEF4S2V5cyA9IE9iamVjdC5rZXlzKGF4QXR0cnMpO1xuXG4gICAgdmFyIG5vU3dhcEF0dHJzID0gW1xuICAgICAgICAnYW5jaG9yJywgJ2RvbWFpbicsICdvdmVybGF5aW5nJywgJ3Bvc2l0aW9uJywgJ3NpZGUnLCAndGlja2FuZ2xlJywgJ2VkaXRUeXBlJ1xuICAgIF07XG4gICAgdmFyIG51bWVyaWNUeXBlcyA9IFsnbGluZWFyJywgJ2xvZyddO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYWxsQXhLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrZXlpID0gYWxsQXhLZXlzW2ldLFxuICAgICAgICAgICAgeFZhbCA9IHhGdWxsQXhlc1swXVtrZXlpXSxcbiAgICAgICAgICAgIHlWYWwgPSB5RnVsbEF4ZXNbMF1ba2V5aV0sXG4gICAgICAgICAgICBhbGxFcXVhbCA9IHRydWUsXG4gICAgICAgICAgICBjb2VyY2VMaW5lYXJYID0gZmFsc2UsXG4gICAgICAgICAgICBjb2VyY2VMaW5lYXJZID0gZmFsc2U7XG4gICAgICAgIGlmKGtleWkuY2hhckF0KDApID09PSAnXycgfHwgdHlwZW9mIHhWYWwgPT09ICdmdW5jdGlvbicgfHxcbiAgICAgICAgICAgICAgICBub1N3YXBBdHRycy5pbmRleE9mKGtleWkpICE9PSAtMSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGogPSAxOyBqIDwgeEZ1bGxBeGVzLmxlbmd0aCAmJiBhbGxFcXVhbDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgeFZhbGkgPSB4RnVsbEF4ZXNbal1ba2V5aV07XG4gICAgICAgICAgICBpZihrZXlpID09PSAndHlwZScgJiYgbnVtZXJpY1R5cGVzLmluZGV4T2YoeFZhbCkgIT09IC0xICYmXG4gICAgICAgICAgICAgICAgICAgIG51bWVyaWNUeXBlcy5pbmRleE9mKHhWYWxpKSAhPT0gLTEgJiYgeFZhbCAhPT0geFZhbGkpIHtcbiAgICAgICAgICAgICAgICAvLyB0eXBlIGlzIHNwZWNpYWwgLSBpZiB3ZSBmaW5kIGEgbWl4dHVyZSBvZiBsaW5lYXIgYW5kIGxvZyxcbiAgICAgICAgICAgICAgICAvLyBjb2VyY2UgdGhlbSBhbGwgdG8gbGluZWFyIG9uIGZsaXBwaW5nXG4gICAgICAgICAgICAgICAgY29lcmNlTGluZWFyWCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHhWYWxpICE9PSB4VmFsKSBhbGxFcXVhbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvcihqID0gMTsgaiA8IHlGdWxsQXhlcy5sZW5ndGggJiYgYWxsRXF1YWw7IGorKykge1xuICAgICAgICAgICAgdmFyIHlWYWxpID0geUZ1bGxBeGVzW2pdW2tleWldO1xuICAgICAgICAgICAgaWYoa2V5aSA9PT0gJ3R5cGUnICYmIG51bWVyaWNUeXBlcy5pbmRleE9mKHlWYWwpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgICAgICBudW1lcmljVHlwZXMuaW5kZXhPZih5VmFsaSkgIT09IC0xICYmIHlWYWwgIT09IHlWYWxpKSB7XG4gICAgICAgICAgICAgICAgLy8gdHlwZSBpcyBzcGVjaWFsIC0gaWYgd2UgZmluZCBhIG1peHR1cmUgb2YgbGluZWFyIGFuZCBsb2csXG4gICAgICAgICAgICAgICAgLy8gY29lcmNlIHRoZW0gYWxsIHRvIGxpbmVhciBvbiBmbGlwcGluZ1xuICAgICAgICAgICAgICAgIGNvZXJjZUxpbmVhclkgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZih5RnVsbEF4ZXNbal1ba2V5aV0gIT09IHlWYWwpIGFsbEVxdWFsID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYoYWxsRXF1YWwpIHtcbiAgICAgICAgICAgIGlmKGNvZXJjZUxpbmVhclgpIGxheW91dFt4RnVsbEF4ZXNbMF0uX25hbWVdLnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgICAgIGlmKGNvZXJjZUxpbmVhclkpIGxheW91dFt5RnVsbEF4ZXNbMF0uX25hbWVdLnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgICAgIHN3YXBBeGlzQXR0cnMobGF5b3V0LCBrZXlpLCB4RnVsbEF4ZXMsIHlGdWxsQXhlcywgZ2QuX2Z1bGxMYXlvdXQuX2RmbHRUaXRsZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBub3cgc3dhcCB4JnkgZm9yIGFueSBhbm5vdGF0aW9ucyBhbmNob3JlZCB0byB0aGVzZSB4ICYgeVxuICAgIGZvcihpID0gMDsgaSA8IGdkLl9mdWxsTGF5b3V0LmFubm90YXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhbm4gPSBnZC5fZnVsbExheW91dC5hbm5vdGF0aW9uc1tpXTtcbiAgICAgICAgaWYoeElkcy5pbmRleE9mKGFubi54cmVmKSAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgICB5SWRzLmluZGV4T2YoYW5uLnlyZWYpICE9PSAtMSkge1xuICAgICAgICAgICAgTGliLnN3YXBBdHRycyhsYXlvdXQuYW5ub3RhdGlvbnNbaV0sIFsnPyddKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gc3dhcEF4aXNBdHRycyhsYXlvdXQsIGtleSwgeEZ1bGxBeGVzLCB5RnVsbEF4ZXMsIGRmbHRUaXRsZSkge1xuICAgIC8vIGluIGNhc2UgdGhlIHZhbHVlIGlzIHRoZSBkZWZhdWx0IGZvciBlaXRoZXIgYXhpcyxcbiAgICAvLyBsb29rIGF0IHRoZSBmaXJzdCBheGlzIGluIGVhY2ggbGlzdCBhbmQgc2VlIGlmXG4gICAgLy8gdGhpcyBrZXkncyB2YWx1ZSBpcyB1bmRlZmluZWRcbiAgICB2YXIgbnAgPSBMaWIubmVzdGVkUHJvcGVydHksXG4gICAgICAgIHhWYWwgPSBucChsYXlvdXRbeEZ1bGxBeGVzWzBdLl9uYW1lXSwga2V5KS5nZXQoKSxcbiAgICAgICAgeVZhbCA9IG5wKGxheW91dFt5RnVsbEF4ZXNbMF0uX25hbWVdLCBrZXkpLmdldCgpLFxuICAgICAgICBpO1xuICAgIGlmKGtleSA9PT0gJ3RpdGxlJykge1xuICAgICAgICAvLyBzcGVjaWFsIGhhbmRsaW5nIG9mIHBsYWNlaG9sZGVyIHRpdGxlc1xuICAgICAgICBpZih4VmFsID09PSBkZmx0VGl0bGUueCkge1xuICAgICAgICAgICAgeFZhbCA9IGRmbHRUaXRsZS55O1xuICAgICAgICB9XG4gICAgICAgIGlmKHlWYWwgPT09IGRmbHRUaXRsZS55KSB7XG4gICAgICAgICAgICB5VmFsID0gZGZsdFRpdGxlLng7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB4RnVsbEF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbnAobGF5b3V0LCB4RnVsbEF4ZXNbaV0uX25hbWUgKyAnLicgKyBrZXkpLnNldCh5VmFsKTtcbiAgICB9XG4gICAgZm9yKGkgPSAwOyBpIDwgeUZ1bGxBeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5wKGxheW91dCwgeUZ1bGxBeGVzW2ldLl9uYW1lICsgJy4nICsga2V5KS5zZXQoeFZhbCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0FuZ3VsYXIoYXgpIHtcbiAgICByZXR1cm4gYXguX2lkID09PSAnYW5ndWxhcmF4aXMnO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhdXRvVHlwZShhcnJheSwgY2FsZW5kYXIpIHtcbiAgICBpZihtb3JlRGF0ZXMoYXJyYXksIGNhbGVuZGFyKSkgcmV0dXJuICdkYXRlJztcbiAgICBpZihjYXRlZ29yeShhcnJheSkpIHJldHVybiAnY2F0ZWdvcnknO1xuICAgIGlmKGxpbmVhck9LKGFycmF5KSkgcmV0dXJuICdsaW5lYXInO1xuICAgIGVsc2UgcmV0dXJuICctJztcbn07XG5cbi8vIGlzIHRoZXJlIGF0IGxlYXN0IG9uZSBudW1iZXIgaW4gYXJyYXk/IElmIG5vdCwgd2Ugc2hvdWxkIGxlYXZlXG4vLyBheC50eXBlIGVtcHR5IHNvIGl0IGNhbiBiZSBhdXRvc2V0IGxhdGVyXG5mdW5jdGlvbiBsaW5lYXJPSyhhcnJheSkge1xuICAgIGlmKCFhcnJheSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGlzTnVtZXJpYyhhcnJheVtpXSkpIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLy8gZG9lcyB0aGUgYXJyYXkgYSBoYXZlIG1vc3RseSBkYXRlcyByYXRoZXIgdGhhbiBudW1iZXJzP1xuLy8gbm90ZTogc29tZSB2YWx1ZXMgY2FuIGJlIG5laXRoZXIgKHN1Y2ggYXMgYmxhbmtzLCB0ZXh0KVxuLy8gMi0gb3IgNC1kaWdpdCBpbnRlZ2VycyBjYW4gYmUgYm90aCwgc28gcmVxdWlyZSB0d2ljZSBhcyBtYW55XG4vLyBkYXRlcyBhcyBub24tZGF0ZXMsIHRvIGV4Y2x1ZGUgY2FzZXMgd2l0aCBtb3N0bHkgMiAmIDQgZGlnaXRcbi8vIG51bWJlcnMgYW5kIGEgZmV3IGRhdGVzXG4vLyBhcyB3aXRoIGNhdGVnb3JpZXMsIGNvbnNpZGVyIERJU1RJTkNUIHZhbHVlcyBvbmx5LlxuZnVuY3Rpb24gbW9yZURhdGVzKGEsIGNhbGVuZGFyKSB7XG4gICAgLy8gdGVzdCBhdCBtb3N0IDEwMDAgcG9pbnRzLCBldmVubHkgc3BhY2VkXG4gICAgdmFyIGluYyA9IE1hdGgubWF4KDEsIChhLmxlbmd0aCAtIDEpIC8gMTAwMCk7XG4gICAgdmFyIGRjbnQgPSAwO1xuICAgIHZhciBuY250ID0gMDtcbiAgICB2YXIgc2VlbiA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGEubGVuZ3RoOyBpICs9IGluYykge1xuICAgICAgICB2YXIgYWkgPSBhW01hdGgucm91bmQoaSldO1xuICAgICAgICB2YXIgc3RyaSA9IFN0cmluZyhhaSk7XG4gICAgICAgIGlmKHNlZW5bc3RyaV0pIGNvbnRpbnVlO1xuICAgICAgICBzZWVuW3N0cmldID0gMTtcblxuICAgICAgICBpZihMaWIuaXNEYXRlVGltZShhaSwgY2FsZW5kYXIpKSBkY250ICs9IDE7XG4gICAgICAgIGlmKGlzTnVtZXJpYyhhaSkpIG5jbnQgKz0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGRjbnQgPiBuY250ICogMik7XG59XG5cbi8vIGFyZSB0aGUgKHgseSktdmFsdWVzIGluIGdkLmRhdGEgbW9zdGx5IHRleHQ/XG4vLyByZXF1aXJlIHR3aWNlIGFzIG1hbnkgRElTVElOQ1QgY2F0ZWdvcmllcyBhcyBkaXN0aW5jdCBudW1iZXJzXG5mdW5jdGlvbiBjYXRlZ29yeShhKSB7XG4gICAgLy8gdGVzdCBhdCBtb3N0IDEwMDAgcG9pbnRzXG4gICAgdmFyIGluYyA9IE1hdGgubWF4KDEsIChhLmxlbmd0aCAtIDEpIC8gMTAwMCk7XG4gICAgdmFyIGN1cnZlbnVtcyA9IDA7XG4gICAgdmFyIGN1cnZlY2F0cyA9IDA7XG4gICAgdmFyIHNlZW4gPSB7fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSArPSBpbmMpIHtcbiAgICAgICAgdmFyIGFpID0gYVtNYXRoLnJvdW5kKGkpXTtcbiAgICAgICAgdmFyIHN0cmkgPSBTdHJpbmcoYWkpO1xuICAgICAgICBpZihzZWVuW3N0cmldKSBjb250aW51ZTtcbiAgICAgICAgc2VlbltzdHJpXSA9IDE7XG5cbiAgICAgICAgaWYodHlwZW9mIGFpID09PSAnYm9vbGVhbicpIGN1cnZlY2F0cysrO1xuICAgICAgICBlbHNlIGlmKExpYi5jbGVhbk51bWJlcihhaSkgIT09IEJBRE5VTSkgY3VydmVudW1zKys7XG4gICAgICAgIGVsc2UgaWYodHlwZW9mIGFpID09PSAnc3RyaW5nJykgY3VydmVjYXRzKys7XG4gICAgfVxuXG4gICAgcmV0dXJuIGN1cnZlY2F0cyA+IGN1cnZlbnVtcyAqIDI7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gcmVxdWlyZSgnLi90aWNrX3ZhbHVlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGlja01hcmtEZWZhdWx0cyA9IHJlcXVpcmUoJy4vdGlja19tYXJrX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVDYXRlZ29yeU9yZGVyRGVmYXVsdHMgPSByZXF1aXJlKCcuL2NhdGVnb3J5X29yZGVyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZUdyaWREZWZhdWx0cyA9IHJlcXVpcmUoJy4vbGluZV9ncmlkX2RlZmF1bHRzJyk7XG52YXIgc2V0Q29udmVydCA9IHJlcXVpcmUoJy4vc2V0X2NvbnZlcnQnKTtcblxuLyoqXG4gKiBvcHRpb25zOiBvYmplY3QgY29udGFpbmluZzpcbiAqXG4gKiAgbGV0dGVyOiAneCcgb3IgJ3knXG4gKiAgdGl0bGU6IG5hbWUgb2YgdGhlIGF4aXMgKGllICdDb2xvcmJhcicpIHRvIGdvIGluIGRlZmF1bHQgdGl0bGVcbiAqICBmb250OiB0aGUgZGVmYXVsdCBmb250IHRvIGluaGVyaXRcbiAqICBvdXRlclRpY2tzOiBib29sZWFuLCBzaG91bGQgdGlja3MgZGVmYXVsdCB0byBvdXRzaWRlP1xuICogIHNob3dHcmlkOiBib29sZWFuLCBzaG91bGQgZ3JpZGxpbmVzIGJlIHNob3duIGJ5IGRlZmF1bHQ/XG4gKiAgbm9Ib3ZlcjogYm9vbGVhbiwgdGhpcyBheGlzIGRvZXNuJ3Qgc3VwcG9ydCBob3ZlciBlZmZlY3RzP1xuICogIGRhdGE6IHRoZSBwbG90IGRhdGEsIHVzZWQgdG8gbWFuYWdlIGNhdGVnb3JpZXNcbiAqICBiZ0NvbG9yOiB0aGUgcGxvdCBiYWNrZ3JvdW5kIGNvbG9yLCB0byBjYWxjdWxhdGUgZGVmYXVsdCBncmlkbGluZSBjb2xvcnNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVBeGlzRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgbGV0dGVyID0gb3B0aW9ucy5sZXR0ZXI7XG4gICAgdmFyIGZvbnQgPSBvcHRpb25zLmZvbnQgfHwge307XG4gICAgdmFyIHNwbG9tU3Rhc2ggPSBvcHRpb25zLnNwbG9tU3Rhc2ggfHwge307XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScsICFvcHRpb25zLmNoZWF0ZXJvbmx5KTtcblxuICAgIHZhciBheFR5cGUgPSBjb250YWluZXJPdXQudHlwZTtcblxuICAgIGlmKGF4VHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlRGVmYXVsdHMnKTtcbiAgICAgICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCAnY2FsZW5kYXInLCBvcHRpb25zLmNhbGVuZGFyKTtcbiAgICB9XG5cbiAgICBzZXRDb252ZXJ0KGNvbnRhaW5lck91dCwgbGF5b3V0T3V0KTtcblxuICAgIHZhciBhdXRvUmFuZ2UgPSBjb2VyY2UoJ2F1dG9yYW5nZScsICFjb250YWluZXJPdXQuaXNWYWxpZFJhbmdlKGNvbnRhaW5lckluLnJhbmdlKSk7XG4gICAgaWYoYXV0b1JhbmdlICYmIChheFR5cGUgPT09ICdsaW5lYXInIHx8IGF4VHlwZSA9PT0gJy0nKSkgY29lcmNlKCdyYW5nZW1vZGUnKTtcblxuICAgIGNvZXJjZSgncmFuZ2UnKTtcbiAgICBjb250YWluZXJPdXQuY2xlYW5SYW5nZSgpO1xuXG4gICAgaGFuZGxlQ2F0ZWdvcnlPcmRlckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0aW9ucyk7XG5cbiAgICBpZihheFR5cGUgIT09ICdjYXRlZ29yeScgJiYgIW9wdGlvbnMubm9Ib3ZlcikgY29lcmNlKCdob3ZlcmZvcm1hdCcpO1xuXG4gICAgaWYoIXZpc2libGUpIHJldHVybiBjb250YWluZXJPdXQ7XG5cbiAgICB2YXIgZGZsdENvbG9yID0gY29lcmNlKCdjb2xvcicpO1xuICAgIC8vIGlmIGF4aXMuY29sb3Igd2FzIHByb3ZpZGVkLCB1c2UgaXQgZm9yIGZvbnRzIHRvbzsgb3RoZXJ3aXNlLFxuICAgIC8vIGluaGVyaXQgZnJvbSBnbG9iYWwgZm9udCBjb2xvciBpbiBjYXNlIHRoYXQgd2FzIHByb3ZpZGVkLlxuICAgIC8vIENvbXBhcmUgdG8gZGZsdCByYXRoZXIgdGhhbiB0byBjb250YWluZXJJbiwgc28gd2UgY2FuIHByb3ZpZGUgY29sb3IgdmlhXG4gICAgLy8gdGVtcGxhdGUgdG9vLlxuICAgIHZhciBkZmx0Rm9udENvbG9yID0gKGRmbHRDb2xvciAhPT0gbGF5b3V0QXR0cmlidXRlcy5jb2xvci5kZmx0KSA/IGRmbHRDb2xvciA6IGZvbnQuY29sb3I7XG4gICAgLy8gdHJ5IHRvIGdldCBkZWZhdWx0IHRpdGxlIGZyb20gc3Bsb20gdHJhY2UsIGZhbGxiYWNrIHRvIGdyYXBoLXdpZGUgdmFsdWVcbiAgICB2YXIgZGZsdFRpdGxlID0gc3Bsb21TdGFzaC5sYWJlbCB8fCBsYXlvdXRPdXQuX2RmbHRUaXRsZVtsZXR0ZXJdO1xuXG4gICAgY29lcmNlKCd0aXRsZScsIGRmbHRUaXRsZSk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGl0bGVmb250Jywge1xuICAgICAgICBmYW1pbHk6IGZvbnQuZmFtaWx5LFxuICAgICAgICBzaXplOiBNYXRoLnJvdW5kKGZvbnQuc2l6ZSAqIDEuMiksXG4gICAgICAgIGNvbG9yOiBkZmx0Rm9udENvbG9yXG4gICAgfSk7XG5cbiAgICBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIGF4VHlwZSk7XG4gICAgaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUsIG9wdGlvbnMpO1xuICAgIGhhbmRsZVRpY2tNYXJrRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zKTtcbiAgICBoYW5kbGVMaW5lR3JpZERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwge1xuICAgICAgICBkZmx0Q29sb3I6IGRmbHRDb2xvcixcbiAgICAgICAgYmdDb2xvcjogb3B0aW9ucy5iZ0NvbG9yLFxuICAgICAgICBzaG93R3JpZDogb3B0aW9ucy5zaG93R3JpZCxcbiAgICAgICAgYXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlc1xuICAgIH0pO1xuXG4gICAgaWYoY29udGFpbmVyT3V0LnNob3dsaW5lIHx8IGNvbnRhaW5lck91dC50aWNrcykgY29lcmNlKCdtaXJyb3InKTtcblxuICAgIGlmKG9wdGlvbnMuYXV0b21hcmdpbikgY29lcmNlKCdhdXRvbWFyZ2luJyk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyT3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cblxuLy8gY29udmVydCBiZXR3ZWVuIGF4aXMgbmFtZXMgKHhheGlzLCB4YXhpczIsIGV0YywgZWxlbWVudHMgb2YgZ2QubGF5b3V0KVxuLy8gYW5kIGF4aXMgaWQncyAoeCwgeDIsIGV0YykuIFdvdWxkIHByb2JhYmx5IGhhdmUgZGl0Y2hlZCAneGF4aXMnXG4vLyBjb21wbGV0ZWx5IGluIGZhdm9yIG9mIGp1c3QgJ3gnIGlmIGl0IHdlcmVuJ3QgaW5ncmFpbmVkIGluIHRoZSBBUEkgZXRjLlxuZXhwb3J0cy5pZDJuYW1lID0gZnVuY3Rpb24gaWQybmFtZShpZCkge1xuICAgIGlmKHR5cGVvZiBpZCAhPT0gJ3N0cmluZycgfHwgIWlkLm1hdGNoKGNvbnN0YW50cy5BWF9JRF9QQVRURVJOKSkgcmV0dXJuO1xuICAgIHZhciBheE51bSA9IGlkLnN1YnN0cigxKTtcbiAgICBpZihheE51bSA9PT0gJzEnKSBheE51bSA9ICcnO1xuICAgIHJldHVybiBpZC5jaGFyQXQoMCkgKyAnYXhpcycgKyBheE51bTtcbn07XG5cbmV4cG9ydHMubmFtZTJpZCA9IGZ1bmN0aW9uIG5hbWUyaWQobmFtZSkge1xuICAgIGlmKCFuYW1lLm1hdGNoKGNvbnN0YW50cy5BWF9OQU1FX1BBVFRFUk4pKSByZXR1cm47XG4gICAgdmFyIGF4TnVtID0gbmFtZS5zdWJzdHIoNSk7XG4gICAgaWYoYXhOdW0gPT09ICcxJykgYXhOdW0gPSAnJztcbiAgICByZXR1cm4gbmFtZS5jaGFyQXQoMCkgKyBheE51bTtcbn07XG5cbmV4cG9ydHMuY2xlYW5JZCA9IGZ1bmN0aW9uIGNsZWFuSWQoaWQsIGF4TGV0dGVyKSB7XG4gICAgaWYoIWlkLm1hdGNoKGNvbnN0YW50cy5BWF9JRF9QQVRURVJOKSkgcmV0dXJuO1xuICAgIGlmKGF4TGV0dGVyICYmIGlkLmNoYXJBdCgwKSAhPT0gYXhMZXR0ZXIpIHJldHVybjtcblxuICAgIHZhciBheE51bSA9IGlkLnN1YnN0cigxKS5yZXBsYWNlKC9eMCsvLCAnJyk7XG4gICAgaWYoYXhOdW0gPT09ICcxJykgYXhOdW0gPSAnJztcbiAgICByZXR1cm4gaWQuY2hhckF0KDApICsgYXhOdW07XG59O1xuXG4vLyBnZXQgYWxsIGF4aXMgb2JqZWN0cywgYXMgcmVzdHJpY3RlZCBpbiBsaXN0TmFtZXNcbmV4cG9ydHMubGlzdCA9IGZ1bmN0aW9uKGdkLCBheExldHRlciwgb25seTJkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICBpZighZnVsbExheW91dCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIGlkTGlzdCA9IGV4cG9ydHMubGlzdElkcyhnZCwgYXhMZXR0ZXIpO1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkoaWRMaXN0Lmxlbmd0aCk7XG4gICAgdmFyIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpZExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkaSA9IGlkTGlzdFtpXTtcbiAgICAgICAgb3V0W2ldID0gZnVsbExheW91dFtpZGkuY2hhckF0KDApICsgJ2F4aXMnICsgaWRpLnN1YnN0cigxKV07XG4gICAgfVxuXG4gICAgaWYoIW9ubHkyZCkge1xuICAgICAgICB2YXIgc2NlbmVJZHMzRCA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2QgfHwgW107XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2NlbmVJZHMzRC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNjZW5lID0gZnVsbExheW91dFtzY2VuZUlkczNEW2ldXTtcblxuICAgICAgICAgICAgaWYoYXhMZXR0ZXIpIG91dC5wdXNoKHNjZW5lW2F4TGV0dGVyICsgJ2F4aXMnXSk7XG4gICAgICAgICAgICBlbHNlIG91dC5wdXNoKHNjZW5lLnhheGlzLCBzY2VuZS55YXhpcywgc2NlbmUuemF4aXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8vIGdldCBhbGwgYXhpcyBpZHMsIG9wdGlvbmFsbHkgcmVzdHJpY3RlZCBieSBsZXR0ZXJcbi8vIHRoaXMgb25seSBtYWtlcyBzZW5zZSBmb3IgMmQgYXhlc1xuZXhwb3J0cy5saXN0SWRzID0gZnVuY3Rpb24oZ2QsIGF4TGV0dGVyKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICBpZighZnVsbExheW91dCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIHN1YnBsb3RMaXN0cyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzO1xuICAgIGlmKGF4TGV0dGVyKSByZXR1cm4gc3VicGxvdExpc3RzW2F4TGV0dGVyICsgJ2F4aXMnXTtcbiAgICByZXR1cm4gc3VicGxvdExpc3RzLnhheGlzLmNvbmNhdChzdWJwbG90TGlzdHMueWF4aXMpO1xufTtcblxuLy8gZ2V0IGFuIGF4aXMgb2JqZWN0IGZyb20gaXRzIGlkICd4JywneDInIGV0Y1xuLy8gb3B0aW9uYWxseSwgaWQgY2FuIGJlIGEgc3VicGxvdCAoaWUgJ3gyeTMnKSBhbmQgdHlwZSBnZXRzIHggb3IgeSBmcm9tIGl0XG5leHBvcnRzLmdldEZyb21JZCA9IGZ1bmN0aW9uKGdkLCBpZCwgdHlwZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZih0eXBlID09PSAneCcpIGlkID0gaWQucmVwbGFjZSgveVswLTldKi8sICcnKTtcbiAgICBlbHNlIGlmKHR5cGUgPT09ICd5JykgaWQgPSBpZC5yZXBsYWNlKC94WzAtOV0qLywgJycpO1xuXG4gICAgcmV0dXJuIGZ1bGxMYXlvdXRbZXhwb3J0cy5pZDJuYW1lKGlkKV07XG59O1xuXG4vLyBnZXQgYW4gYXhpcyBvYmplY3Qgb2Ygc3BlY2lmaWVkIHR5cGUgZnJvbSB0aGUgY29udGFpbmluZyB0cmFjZVxuZXhwb3J0cy5nZXRGcm9tVHJhY2UgPSBmdW5jdGlvbihnZCwgZnVsbFRyYWNlLCB0eXBlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXggPSBudWxsO1xuXG4gICAgaWYoUmVnaXN0cnkudHJhY2VJcyhmdWxsVHJhY2UsICdnbDNkJykpIHtcbiAgICAgICAgdmFyIHNjZW5lID0gZnVsbFRyYWNlLnNjZW5lO1xuICAgICAgICBpZihzY2VuZS5zdWJzdHIoMCwgNSkgPT09ICdzY2VuZScpIHtcbiAgICAgICAgICAgIGF4ID0gZnVsbExheW91dFtzY2VuZV1bdHlwZSArICdheGlzJ107XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGF4ID0gZXhwb3J0cy5nZXRGcm9tSWQoZ2QsIGZ1bGxUcmFjZVt0eXBlICsgJ2F4aXMnXSB8fCB0eXBlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXg7XG59O1xuXG4vLyBzb3J0IHgsIHgyLCB4MTAsIHksIHkyLCB5MTAuLi5cbmV4cG9ydHMuaWRTb3J0ID0gZnVuY3Rpb24oaWQxLCBpZDIpIHtcbiAgICB2YXIgbGV0dGVyMSA9IGlkMS5jaGFyQXQoMCk7XG4gICAgdmFyIGxldHRlcjIgPSBpZDIuY2hhckF0KDApO1xuICAgIGlmKGxldHRlcjEgIT09IGxldHRlcjIpIHJldHVybiBsZXR0ZXIxID4gbGV0dGVyMiA/IDEgOiAtMTtcbiAgICByZXR1cm4gKyhpZDEuc3Vic3RyKDEpIHx8IDEpIC0gKyhpZDIuc3Vic3RyKDEpIHx8IDEpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gZmluZENhdGVnb3JpZXMoYXgsIG9wdHMpIHtcbiAgICB2YXIgZGF0YUF0dHIgPSBvcHRzLmRhdGFBdHRyIHx8IGF4Ll9pZC5jaGFyQXQoMCk7XG4gICAgdmFyIGxvb2t1cCA9IHt9O1xuICAgIHZhciBheERhdGE7XG4gICAgdmFyIGksIGo7XG5cbiAgICBpZihvcHRzLmF4RGF0YSkge1xuICAgICAgICAvLyBub24teC95IGNhc2VcbiAgICAgICAgYXhEYXRhID0gb3B0cy5heERhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8geC95IGNhc2VcbiAgICAgICAgYXhEYXRhID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9wdHMuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gb3B0cy5kYXRhW2ldO1xuICAgICAgICAgICAgaWYodHJhY2VbZGF0YUF0dHIgKyAnYXhpcyddID09PSBheC5faWQpIHtcbiAgICAgICAgICAgICAgICBheERhdGEucHVzaCh0cmFjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBheERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbHMgPSBheERhdGFbaV1bZGF0YUF0dHJdO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCB2YWxzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgdiA9IHZhbHNbal07XG4gICAgICAgICAgICBpZih2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGxvb2t1cFt2XSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMobG9va3VwKTtcbn1cblxuLyoqXG4gKiBGaWxscyBpbiBjYXRlZ29yeSogZGVmYXVsdCBhbmQgaW5pdGlhbCBjYXRlZ29yaWVzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250YWluZXJJbiA6IGlucHV0IGF4aXMgb2JqZWN0XG4gKiBAcGFyYW0ge29iamVjdH0gY29udGFpbmVyT3V0IDogZnVsbCBheGlzIG9iamVjdFxuICogQHBhcmFtIHtmdW5jdGlvbn0gY29lcmNlIDogTGliLmNvZXJjZSBmbiB3cmFwcGVyXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyA6XG4gKiAgIC0gZGF0YSB7YXJyYXl9IDogKGZ1bGwpIGRhdGEgdHJhY2VcbiAqIE9SXG4gKiAgIC0gYXhEYXRhIHthcnJheX0gOiAoZnVsbCkgZGF0YSBhc3NvY2lhdGVkIHdpdGggYXhpcyBiZWluZyBjb2VyY2VkIGhlcmVcbiAqICAgLSBkYXRhQXR0ciB7c3RyaW5nfSA6IGF0dHJpYnV0ZSBuYW1lIGNvcnJlc3BvbmRpbmcgdG8gY29vcmRpbmF0ZSBhcnJheVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZUNhdGVnb3J5T3JkZXJEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICBpZihjb250YWluZXJPdXQudHlwZSAhPT0gJ2NhdGVnb3J5JykgcmV0dXJuO1xuXG4gICAgdmFyIGFycmF5SW4gPSBjb250YWluZXJJbi5jYXRlZ29yeWFycmF5O1xuICAgIHZhciBpc1ZhbGlkQXJyYXkgPSAoQXJyYXkuaXNBcnJheShhcnJheUluKSAmJiBhcnJheUluLmxlbmd0aCA+IDApO1xuXG4gICAgLy8gb3ZlcnJpZGUgZGVmYXVsdCAnY2F0ZWdvcnlvcmRlcicgdmFsdWUgd2hlbiBub24tZW1wdHkgYXJyYXkgaXMgc3VwcGxpZWRcbiAgICB2YXIgb3JkZXJEZWZhdWx0O1xuICAgIGlmKGlzVmFsaWRBcnJheSkgb3JkZXJEZWZhdWx0ID0gJ2FycmF5JztcblxuICAgIHZhciBvcmRlciA9IGNvZXJjZSgnY2F0ZWdvcnlvcmRlcicsIG9yZGVyRGVmYXVsdCk7XG4gICAgdmFyIGFycmF5O1xuXG4gICAgLy8gY29lcmNlICdjYXRlZ29yeWFycmF5JyBvbmx5IGluIGFycmF5IG9yZGVyIGNhc2VcbiAgICBpZihvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICBhcnJheSA9IGNvZXJjZSgnY2F0ZWdvcnlhcnJheScpO1xuICAgIH1cblxuICAgIC8vIGNhbm5vdCBzZXQgJ2NhdGVnb3J5b3JkZXInIHRvICdhcnJheScgd2l0aCBhbiBpbnZhbGlkICdjYXRlZ29yeWFycmF5J1xuICAgIGlmKCFpc1ZhbGlkQXJyYXkgJiYgb3JkZXIgPT09ICdhcnJheScpIHtcbiAgICAgICAgb3JkZXIgPSBjb250YWluZXJPdXQuY2F0ZWdvcnlvcmRlciA9ICd0cmFjZSc7XG4gICAgfVxuXG4gICAgLy8gc2V0IHVwIHRoaW5ncyBmb3IgbWFrZUNhbGNkYXRhXG4gICAgaWYob3JkZXIgPT09ICd0cmFjZScpIHtcbiAgICAgICAgY29udGFpbmVyT3V0Ll9pbml0aWFsQ2F0ZWdvcmllcyA9IFtdO1xuICAgIH0gZWxzZSBpZihvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICBjb250YWluZXJPdXQuX2luaXRpYWxDYXRlZ29yaWVzID0gYXJyYXkuc2xpY2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBhcnJheSA9IGZpbmRDYXRlZ29yaWVzKGNvbnRhaW5lck91dCwgb3B0cykuc29ydCgpO1xuICAgICAgICBpZihvcmRlciA9PT0gJ2NhdGVnb3J5IGFzY2VuZGluZycpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lck91dC5faW5pdGlhbENhdGVnb3JpZXMgPSBhcnJheTtcbiAgICAgICAgfSBlbHNlIGlmKG9yZGVyID09PSAnY2F0ZWdvcnkgZGVzY2VuZGluZycpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lck91dC5faW5pdGlhbENhdGVnb3JpZXMgPSBhcnJheS5yZXZlcnNlKCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIE9ORURBWSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5PTkVEQVk7XG5cbi8qKlxuICogUmV0dXJuIGEgdmFsaWRhdGVkIGR0aWNrIHZhbHVlIGZvciB0aGlzIGF4aXNcbiAqXG4gKiBAcGFyYW0ge2FueX0gZHRpY2s6IHRoZSBjYW5kaWRhdGUgZHRpY2suIHZhbGlkIHZhbHVlcyBhcmUgbnVtYmVycyBhbmQgc3RyaW5ncyxcbiAqICAgICBhbmQgZnVydGhlciBjb25zdHJhaW5lZCBkZXBlbmRpbmcgb24gdGhlIGF4aXMgdHlwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBheFR5cGU6IHRoZSBheGlzIHR5cGVcbiAqL1xuZXhwb3J0cy5kdGljayA9IGZ1bmN0aW9uKGR0aWNrLCBheFR5cGUpIHtcbiAgICB2YXIgaXNMb2cgPSBheFR5cGUgPT09ICdsb2cnO1xuICAgIHZhciBpc0RhdGUgPSBheFR5cGUgPT09ICdkYXRlJztcbiAgICB2YXIgaXNDYXQgPSBheFR5cGUgPT09ICdjYXRlZ29yeSc7XG4gICAgdmFyIGR0aWNrRGZsdCA9IGlzRGF0ZSA/IE9ORURBWSA6IDE7XG5cbiAgICBpZighZHRpY2spIHJldHVybiBkdGlja0RmbHQ7XG5cbiAgICBpZihpc051bWVyaWMoZHRpY2spKSB7XG4gICAgICAgIGR0aWNrID0gTnVtYmVyKGR0aWNrKTtcbiAgICAgICAgaWYoZHRpY2sgPD0gMCkgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICAgICAgaWYoaXNDYXQpIHtcbiAgICAgICAgICAgIC8vIGNhdGVnb3J5IGR0aWNrIG11c3QgYmUgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKGR0aWNrKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaXNEYXRlKSB7XG4gICAgICAgICAgICAvLyBkYXRlIGR0aWNrIG11c3QgYmUgYXQgbGVhc3QgMC4xbXMgKG91ciBjdXJyZW50IHByZWNpc2lvbilcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgwLjEsIGR0aWNrKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZHRpY2s7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIGR0aWNrICE9PSAnc3RyaW5nJyB8fCAhKGlzRGF0ZSB8fCBpc0xvZykpIHtcbiAgICAgICAgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICB9XG5cbiAgICB2YXIgcHJlZml4ID0gZHRpY2suY2hhckF0KDApO1xuICAgIHZhciBkdGlja051bSA9IGR0aWNrLnN1YnN0cigxKTtcbiAgICBkdGlja051bSA9IGlzTnVtZXJpYyhkdGlja051bSkgPyBOdW1iZXIoZHRpY2tOdW0pIDogMDtcblxuICAgIGlmKChkdGlja051bSA8PSAwKSB8fCAhKFxuICAgICAgICAgICAgLy8gXCJNPG4+XCIgZ2l2ZXMgdGlja3MgZXZlcnkgKGludGVnZXIpIG4gbW9udGhzXG4gICAgICAgICAgICAoaXNEYXRlICYmIHByZWZpeCA9PT0gJ00nICYmIGR0aWNrTnVtID09PSBNYXRoLnJvdW5kKGR0aWNrTnVtKSkgfHxcbiAgICAgICAgICAgIC8vIFwiTDxmPlwiIGdpdmVzIHRpY2tzIGxpbmVhcmx5IHNwYWNlZCBpbiBkYXRhIChub3QgaW4gcG9zaXRpb24pIGV2ZXJ5IChmbG9hdCkgZlxuICAgICAgICAgICAgKGlzTG9nICYmIHByZWZpeCA9PT0gJ0wnKSB8fFxuICAgICAgICAgICAgLy8gXCJEMVwiIGdpdmVzIHBvd2VycyBvZiAxMCB3aXRoIGFsbCBzbWFsbCBkaWdpdHMgYmV0d2VlbiwgXCJEMlwiIGdpdmVzIG9ubHkgMiBhbmQgNVxuICAgICAgICAgICAgKGlzTG9nICYmIHByZWZpeCA9PT0gJ0QnICYmIChkdGlja051bSA9PT0gMSB8fCBkdGlja051bSA9PT0gMikpXG4gICAgICAgICkpIHtcbiAgICAgICAgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gZHRpY2s7XG59O1xuXG4vKipcbiAqIFJldHVybiBhIHZhbGlkYXRlZCB0aWNrMCBmb3IgdGhpcyBheGlzXG4gKlxuICogQHBhcmFtIHthbnl9IHRpY2swOiB0aGUgY2FuZGlkYXRlIHRpY2swLiBWYWxpZCB2YWx1ZXMgYXJlIG51bWJlcnMgYW5kIHN0cmluZ3MsXG4gKiAgICAgZnVydGhlciBjb25zdHJhaW5lZCBkZXBlbmRpbmcgb24gdGhlIGF4aXMgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IGF4VHlwZTogdGhlIGF4aXMgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IGNhbGVuZGFyOiBmb3IgZGF0ZSBheGVzLCB0aGUgY2FsZW5kYXIgdG8gdmFsaWRhdGUvY29udmVydCB3aXRoXG4gKiBAcGFyYW0ge2FueX0gZHRpY2s6IGFuIGFscmVhZHkgdmFsaWQgZHRpY2suIE9ubHkgdXNlZCBmb3IgRDEgYW5kIEQyIGxvZyBkdGlja3MsXG4gKiAgICAgd2hpY2ggZG8gbm90IHN1cHBvcnQgdGljazAgYXQgYWxsLlxuICovXG5leHBvcnRzLnRpY2swID0gZnVuY3Rpb24odGljazAsIGF4VHlwZSwgY2FsZW5kYXIsIGR0aWNrKSB7XG4gICAgaWYoYXhUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jbGVhbkRhdGUodGljazAsIExpYi5kYXRlVGljazAoY2FsZW5kYXIpKTtcbiAgICB9XG4gICAgaWYoZHRpY2sgPT09ICdEMScgfHwgZHRpY2sgPT09ICdEMicpIHtcbiAgICAgICAgLy8gRDEgYW5kIEQyIG1vZGVzIGlnbm9yZSB0aWNrMCBlbnRpcmVseVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvLyBBc2lkZSBmcm9tIGRhdGUgYXhlcywgdGljazAgbXVzdCBiZSBudW1lcmljXG4gICAgcmV0dXJuIGlzTnVtZXJpYyh0aWNrMCkgPyBOdW1iZXIodGljazApIDogMDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG52YXIgY291bnRlclJlZ2V4ID0gcmVxdWlyZSgnLi4vLi4vbGliL3JlZ2V4JykuY291bnRlcjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAgIGlkUmVnZXg6IHtcbiAgICAgICAgeDogY291bnRlclJlZ2V4KCd4JyksXG4gICAgICAgIHk6IGNvdW50ZXJSZWdleCgneScpXG4gICAgfSxcblxuICAgIGF0dHJSZWdleDogY291bnRlclJlZ2V4KCdbeHldYXhpcycpLFxuXG4gICAgLy8gYXhpcyBtYXRjaCByZWd1bGFyIGV4cHJlc3Npb25cbiAgICB4QXhpc01hdGNoOiBjb3VudGVyUmVnZXgoJ3hheGlzJyksXG4gICAgeUF4aXNNYXRjaDogY291bnRlclJlZ2V4KCd5YXhpcycpLFxuXG4gICAgLy8gcGF0dGVybiBtYXRjaGluZyBheGlzIGlkcyBhbmQgbmFtZXNcbiAgICAvLyBub3RlIHRoYXQgdGhpcyBpcyBtb3JlIHBlcm1pc3NpdmUgdGhhbiBjb3VudGVyUmVnZXgsIGFzXG4gICAgLy8gaWQybmFtZSwgbmFtZTJpZCwgYW5kIGNsZWFuSWQgYWNjZXB0IFwieDFcIiBldGNcbiAgICBBWF9JRF9QQVRURVJOOiAvXlt4eXpdWzAtOV0qJC8sXG4gICAgQVhfTkFNRV9QQVRURVJOOiAvXlt4eXpdYXhpc1swLTldKiQvLFxuXG4gICAgLy8gYW5kIGZvciAyRCBzdWJwbG90c1xuICAgIFNVQlBMT1RfUEFUVEVSTjogL154KFswLTldKil5KFswLTldKikkLyxcblxuICAgIC8vIHBpeGVscyB0byBtb3ZlIG1vdXNlIGJlZm9yZSB5b3Ugc3RvcCBjbGFtcGluZyB0byBzdGFydGluZyBwb2ludFxuICAgIE1JTkRSQUc6IDgsXG5cbiAgICAvLyBzbWFsbGVzdCBkaW1lbnNpb24gYWxsb3dlZCBmb3IgYSBzZWxlY3QgYm94XG4gICAgTUlOU0VMRUNUOiAxMixcblxuICAgIC8vIHNtYWxsZXN0IGRpbWVuc2lvbiBhbGxvd2VkIGZvciBhIHpvb21ib3hcbiAgICBNSU5aT09NOiAyMCxcblxuICAgIC8vIHdpZHRoIG9mIGF4aXMgZHJhZyByZWdpb25zXG4gICAgRFJBR0dFUlNJWkU6IDIwLFxuXG4gICAgLy8gbWF4IHBpeGVscyBvZmYgc3RyYWlnaHQgYmVmb3JlIGEgbGFzc28gc2VsZWN0IGxpbmUgY291bnRzIGFzIGJlbnRcbiAgICBCRU5EUFg6IDEuNSxcblxuICAgIC8vIGRlbGF5IGJlZm9yZSBhIHJlZHJhdyAocmVsYXlvdXQpIGFmdGVyIHNtb290aCBwYW5uaW5nIGFuZCB6b29taW5nXG4gICAgUkVEUkFXREVMQVk6IDUwLFxuXG4gICAgLy8gdGhyb3R0bGluZyBsaW1pdCAobXMpIGZvciBzZWxlY3RQb2ludHMgY2FsbHNcbiAgICBTRUxFQ1RERUxBWTogMTAwLFxuXG4gICAgLy8gY2FjaGUgSUQgc3VmZml4IGZvciB0aHJvdHRsZVxuICAgIFNFTEVDVElEOiAnLXNlbGVjdCcsXG5cbiAgICAvLyBsYXN0IHJlc29ydCBheGlzIHJhbmdlcyBmb3IgeCBhbmQgeSBheGVzIGlmIHdlIGhhdmUgbm8gZGF0YVxuICAgIERGTFRSQU5HRVg6IFstMSwgNl0sXG4gICAgREZMVFJBTkdFWTogWy0xLCA0XSxcblxuICAgIC8vIExheWVycyB0byBrZWVwIHRyYWNlIHR5cGVzIGluIHRoZSByaWdodCBvcmRlclxuICAgIC8vIE4uQi4gZWFjaCAgJ3VuaXF1ZScgcGxvdCBtZXRob2QgbXVzdCBoYXZlIGl0cyBvd24gbGF5ZXJcbiAgICB0cmFjZUxheWVyQ2xhc3NlczogW1xuICAgICAgICAnaGVhdG1hcGxheWVyJyxcbiAgICAgICAgJ2NvbnRvdXJjYXJwZXRsYXllcicsICdjb250b3VybGF5ZXInLFxuICAgICAgICAnYmFybGF5ZXInLFxuICAgICAgICAnY2FycGV0bGF5ZXInLFxuICAgICAgICAndmlvbGlubGF5ZXInLFxuICAgICAgICAnYm94bGF5ZXInLFxuICAgICAgICAnb2hsY2xheWVyJyxcbiAgICAgICAgJ3NjYXR0ZXJjYXJwZXRsYXllcicsICdzY2F0dGVybGF5ZXInXG4gICAgXSxcblxuICAgIGxheWVyVmFsdWUybGF5ZXJDbGFzczoge1xuICAgICAgICAnYWJvdmUgdHJhY2VzJzogJ2Fib3ZlJyxcbiAgICAgICAgJ2JlbG93IHRyYWNlcyc6ICdiZWxvdydcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBpZDJuYW1lID0gcmVxdWlyZSgnLi9heGlzX2lkcycpLmlkMm5hbWU7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBhbGxBeGlzSWRzLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgY29uc3RyYWludEdyb3VwcyA9IGxheW91dE91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHM7XG4gICAgdmFyIHRoaXNJRCA9IGNvbnRhaW5lck91dC5faWQ7XG4gICAgdmFyIGxldHRlciA9IHRoaXNJRC5jaGFyQXQoMCk7XG5cbiAgICBpZihjb250YWluZXJPdXQuZml4ZWRyYW5nZSkgcmV0dXJuO1xuXG4gICAgLy8gY29lcmNlIHRoZSBjb25zdHJhaW50IG1lY2hhbmljcyBldmVuIGlmIHRoaXMgYXhpcyBoYXMgbm8gc2NhbGVhbmNob3JcbiAgICAvLyBiZWNhdXNlIGl0IG1heSBiZSB0aGUgYW5jaG9yIG9mIGFub3RoZXIgYXhpcy5cbiAgICBjb2VyY2UoJ2NvbnN0cmFpbicpO1xuICAgIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICBjb25zdHJhaW50b3dhcmQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogbGV0dGVyID09PSAneCcgPyBbJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10gOiBbJ2JvdHRvbScsICdtaWRkbGUnLCAndG9wJ10sXG4gICAgICAgICAgICBkZmx0OiBsZXR0ZXIgPT09ICd4JyA/ICdjZW50ZXInIDogJ21pZGRsZSdcbiAgICAgICAgfVxuICAgIH0sICdjb25zdHJhaW50b3dhcmQnKTtcblxuICAgIGlmKCFjb250YWluZXJJbi5zY2FsZWFuY2hvcikgcmV0dXJuO1xuXG4gICAgdmFyIGNvbnN0cmFpbnRPcHRzID0gZ2V0Q29uc3RyYWludE9wdHMoY29uc3RyYWludEdyb3VwcywgdGhpc0lELCBhbGxBeGlzSWRzLCBsYXlvdXRPdXQpO1xuXG4gICAgdmFyIHNjYWxlYW5jaG9yID0gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgIHNjYWxlYW5jaG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IGNvbnN0cmFpbnRPcHRzLmxpbmthYmxlQXhlc1xuICAgICAgICB9XG4gICAgfSwgJ3NjYWxlYW5jaG9yJyk7XG5cbiAgICBpZihzY2FsZWFuY2hvcikge1xuICAgICAgICB2YXIgc2NhbGVyYXRpbyA9IGNvZXJjZSgnc2NhbGVyYXRpbycpO1xuICAgICAgICAvLyBUT0RPOiBJIHN1cHBvc2UgSSBjb3VsZCBkbyBhdHRyaWJ1dGUubWluOiBOdW1iZXIuTUlOX1ZBTFVFIHRvIGF2b2lkIHplcm8sXG4gICAgICAgIC8vIGJ1dCB0aGF0IHNlZW1zIGhhY2t5LiBCZXR0ZXIgd2F5IHRvIHNheSBcIm11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXJcIj9cbiAgICAgICAgLy8gT2YgY291cnNlIGlmIHlvdSB1c2Ugc2V2ZXJhbCBzdXBlci10aW55IHZhbHVlcyB5b3UgY291bGQgZXZlbnR1YWxseVxuICAgICAgICAvLyBmb3JjZSBhIHByb2R1Y3Qgb2YgdGhlc2UgdG8gemVybyBhbmQgYWxsIGhlbGwgd291bGQgYnJlYWsgbG9vc2UuLi5cbiAgICAgICAgLy8gTGlrZXdpc2Ugd2l0aCBzdXBlci1odWdlIHZhbHVlcy5cbiAgICAgICAgaWYoIXNjYWxlcmF0aW8pIHNjYWxlcmF0aW8gPSBjb250YWluZXJPdXQuc2NhbGVyYXRpbyA9IDE7XG5cbiAgICAgICAgdXBkYXRlQ29uc3RyYWludEdyb3Vwcyhjb25zdHJhaW50R3JvdXBzLCBjb25zdHJhaW50T3B0cy50aGlzR3JvdXAsXG4gICAgICAgICAgICB0aGlzSUQsIHNjYWxlYW5jaG9yLCBzY2FsZXJhdGlvKTtcbiAgICB9XG4gICAgZWxzZSBpZihhbGxBeGlzSWRzLmluZGV4T2YoY29udGFpbmVySW4uc2NhbGVhbmNob3IpICE9PSAtMSkge1xuICAgICAgICBMaWIud2FybignaWdub3JlZCAnICsgY29udGFpbmVyT3V0Ll9uYW1lICsgJy5zY2FsZWFuY2hvcjogXCInICtcbiAgICAgICAgICAgIGNvbnRhaW5lckluLnNjYWxlYW5jaG9yICsgJ1wiIHRvIGF2b2lkIGVpdGhlciBhbiBpbmZpbml0ZSBsb29wICcgK1xuICAgICAgICAgICAgJ2FuZCBwb3NzaWJseSBpbmNvbnNpc3RlbnQgc2NhbGVyYXRpb3MsIG9yIGJlY2F1c2UgdGhlIHRhcmdldCcgK1xuICAgICAgICAgICAgJ2F4aXMgaGFzIGZpeGVkIHJhbmdlLicpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldENvbnN0cmFpbnRPcHRzKGNvbnN0cmFpbnRHcm91cHMsIHRoaXNJRCwgYWxsQXhpc0lkcywgbGF5b3V0T3V0KSB7XG4gICAgLy8gSWYgdGhpcyBheGlzIGlzIGFscmVhZHkgcGFydCBvZiBhIGNvbnN0cmFpbnQgZ3JvdXAsIHdlIGNhbid0XG4gICAgLy8gc2NhbGVhbmNob3IgYW55IG90aGVyIGF4aXMgaW4gdGhhdCBncm91cCwgb3Igd2UnZCBtYWtlIGEgbG9vcC5cbiAgICAvLyBGaWx0ZXIgYWxsQXhpc0lkcyB0byBlbmZvcmNlIHRoaXMsIGFsc28gbWF0Y2hpbmcgYXhpcyB0eXBlcy5cblxuICAgIHZhciB0aGlzVHlwZSA9IGxheW91dE91dFtpZDJuYW1lKHRoaXNJRCldLnR5cGU7XG5cbiAgICB2YXIgaSwgaiwgaWRqLCBheGo7XG5cbiAgICB2YXIgbGlua2FibGVBeGVzID0gW107XG4gICAgZm9yKGogPSAwOyBqIDwgYWxsQXhpc0lkcy5sZW5ndGg7IGorKykge1xuICAgICAgICBpZGogPSBhbGxBeGlzSWRzW2pdO1xuICAgICAgICBpZihpZGogPT09IHRoaXNJRCkgY29udGludWU7XG5cbiAgICAgICAgYXhqID0gbGF5b3V0T3V0W2lkMm5hbWUoaWRqKV07XG4gICAgICAgIGlmKGF4ai50eXBlID09PSB0aGlzVHlwZSAmJiAhYXhqLmZpeGVkcmFuZ2UpIGxpbmthYmxlQXhlcy5wdXNoKGlkaik7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgY29uc3RyYWludEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihjb25zdHJhaW50R3JvdXBzW2ldW3RoaXNJRF0pIHtcbiAgICAgICAgICAgIHZhciB0aGlzR3JvdXAgPSBjb25zdHJhaW50R3JvdXBzW2ldO1xuXG4gICAgICAgICAgICB2YXIgbGlua2FibGVBeGVzTm9Mb29wcyA9IFtdO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbGlua2FibGVBeGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWRqID0gbGlua2FibGVBeGVzW2pdO1xuICAgICAgICAgICAgICAgIGlmKCF0aGlzR3JvdXBbaWRqXSkgbGlua2FibGVBeGVzTm9Mb29wcy5wdXNoKGlkaik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge2xpbmthYmxlQXhlczogbGlua2FibGVBeGVzTm9Mb29wcywgdGhpc0dyb3VwOiB0aGlzR3JvdXB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtsaW5rYWJsZUF4ZXM6IGxpbmthYmxlQXhlcywgdGhpc0dyb3VwOiBudWxsfTtcbn1cblxuXG4vKlxuICogQWRkIHRoaXMgYXhpcyB0byB0aGUgYXhpcyBjb25zdHJhaW50IGdyb3Vwcywgd2hpY2ggaXMgdGhlIGNvbGxlY3Rpb25cbiAqIG9mIGF4ZXMgdGhhdCBhcmUgYWxsIGNvbnN0cmFpbmVkIHRvZ2V0aGVyIG9uIHNjYWxlLlxuICpcbiAqIGNvbnN0cmFpbnRHcm91cHM6IGEgbGlzdCBvZiBvYmplY3RzLiBlYWNoIG9iamVjdCBpc1xuICoge2F4aXNfaWQ6IHNjYWxlX3dpdGhpbl9ncm91cH0sIHdoZXJlIHNjYWxlX3dpdGhpbl9ncm91cCBpc1xuICogb25seSBpbXBvcnRhbnQgcmVsYXRpdmUgdG8gdGhlIHJlc3Qgb2YgdGhlIGdyb3VwLCBhbmQgZGVmaW5lc1xuICogdGhlIHJlbGF0aXZlIHNjYWxlcyBiZXR3ZWVuIGFsbCBheGVzIGluIHRoZSBncm91cFxuICpcbiAqIHRoaXNHcm91cDogdGhlIGdyb3VwIHRoZSBjdXJyZW50IGF4aXMgaXMgYWxyZWFkeSBpblxuICogdGhpc0lEOiB0aGUgaWQgaWYgdGhlIGN1cnJlbnQgYXhpc1xuICogc2NhbGVhbmNob3I6IHRoZSBpZCBvZiB0aGUgYXhpcyB0byBzY2FsZSBpdCB3aXRoXG4gKiBzY2FsZXJhdGlvOiB0aGUgcmF0aW8gb2YgdGhpcyBheGlzIHRvIHRoZSBzY2FsZWFuY2hvciBheGlzXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZUNvbnN0cmFpbnRHcm91cHMoY29uc3RyYWludEdyb3VwcywgdGhpc0dyb3VwLCB0aGlzSUQsIHNjYWxlYW5jaG9yLCBzY2FsZXJhdGlvKSB7XG4gICAgdmFyIGksIGosIGdyb3VwaSwga2V5aiwgdGhpc0dyb3VwSW5kZXg7XG5cbiAgICBpZih0aGlzR3JvdXAgPT09IG51bGwpIHtcbiAgICAgICAgdGhpc0dyb3VwID0ge307XG4gICAgICAgIHRoaXNHcm91cFt0aGlzSURdID0gMTtcbiAgICAgICAgdGhpc0dyb3VwSW5kZXggPSBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDtcbiAgICAgICAgY29uc3RyYWludEdyb3Vwcy5wdXNoKHRoaXNHcm91cCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0aGlzR3JvdXBJbmRleCA9IGNvbnN0cmFpbnRHcm91cHMuaW5kZXhPZih0aGlzR3JvdXApO1xuICAgIH1cblxuICAgIHZhciB0aGlzR3JvdXBLZXlzID0gT2JqZWN0LmtleXModGhpc0dyb3VwKTtcblxuICAgIC8vIHdlIGtub3cgdGhhdCB0aGlzIGF4aXMgaXNuJ3QgaW4gYW55IG90aGVyIGdyb3VwcywgYnV0IHdlIGRvbid0IGtub3dcbiAgICAvLyBhYm91dCB0aGUgc2NhbGVhbmNob3IgYXhpcy4gSWYgaXQgaXMsIHdlIG5lZWQgdG8gbWVyZ2UgdGhlIGdyb3Vwcy5cbiAgICBmb3IoaSA9IDA7IGkgPCBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdyb3VwaSA9IGNvbnN0cmFpbnRHcm91cHNbaV07XG4gICAgICAgIGlmKGkgIT09IHRoaXNHcm91cEluZGV4ICYmIGdyb3VwaVtzY2FsZWFuY2hvcl0pIHtcbiAgICAgICAgICAgIHZhciBiYXNlU2NhbGUgPSBncm91cGlbc2NhbGVhbmNob3JdO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdGhpc0dyb3VwS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGtleWogPSB0aGlzR3JvdXBLZXlzW2pdO1xuICAgICAgICAgICAgICAgIGdyb3VwaVtrZXlqXSA9IGJhc2VTY2FsZSAqIHNjYWxlcmF0aW8gKiB0aGlzR3JvdXBba2V5al07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdHJhaW50R3JvdXBzLnNwbGljZSh0aGlzR3JvdXBJbmRleCwgMSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBvdGhlcndpc2UsIHdlIGluc2VydCB0aGUgbmV3IHNjYWxlYW5jaG9yIGF4aXMgYXMgdGhlIGJhc2Ugc2NhbGUgKDEpXG4gICAgLy8gaW4gaXRzIGdyb3VwLCBhbmQgc2NhbGUgdGhlIHJlc3Qgb2YgdGhlIGdyb3VwIHRvIGl0XG4gICAgaWYoc2NhbGVyYXRpbyAhPT0gMSkge1xuICAgICAgICBmb3IoaiA9IDA7IGogPCB0aGlzR3JvdXBLZXlzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB0aGlzR3JvdXBbdGhpc0dyb3VwS2V5c1tqXV0gKj0gc2NhbGVyYXRpbztcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aGlzR3JvdXBbc2NhbGVhbmNob3JdID0gMTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaWQybmFtZSA9IHJlcXVpcmUoJy4vYXhpc19pZHMnKS5pZDJuYW1lO1xudmFyIHNjYWxlWm9vbSA9IHJlcXVpcmUoJy4vc2NhbGVfem9vbScpO1xudmFyIG1ha2VQYWRGbiA9IHJlcXVpcmUoJy4vYXV0b3JhbmdlJykubWFrZVBhZEZuO1xudmFyIGNvbmNhdEV4dHJlbWVzID0gcmVxdWlyZSgnLi9hdXRvcmFuZ2UnKS5jb25jYXRFeHRyZW1lcztcblxudmFyIEFMTU9TVF9FUVVBTCA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5BTE1PU1RfRVFVQUw7XG5cbnZhciBGUk9NX0JMID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpLkZST01fQkw7XG5cblxuZXhwb3J0cy5lbmZvcmNlID0gZnVuY3Rpb24gZW5mb3JjZUF4aXNDb25zdHJhaW50cyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNvbnN0cmFpbnRHcm91cHMgPSBmdWxsTGF5b3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcyB8fCBbXTtcblxuICAgIHZhciBpLCBqLCBheGlzSUQsIGF4LCBub3JtU2NhbGUsIG1vZGUsIGZhY3RvcjtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbnN0cmFpbnRHcm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGdyb3VwID0gY29uc3RyYWludEdyb3Vwc1tpXTtcbiAgICAgICAgdmFyIGF4aXNJRHMgPSBPYmplY3Qua2V5cyhncm91cCk7XG5cbiAgICAgICAgdmFyIG1pblNjYWxlID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtYXhTY2FsZSA9IDA7XG4gICAgICAgIC8vIG1vc3RseSBtYXRjaFNjYWxlIHdpbGwgYmUgdGhlIHNhbWUgYXMgbWluU2NhbGVcbiAgICAgICAgLy8gaWUgd2UgZXhwYW5kIGF4aXMgcmFuZ2VzIHRvIGVuY29tcGFzcyAqZXZlcnl0aGluZypcbiAgICAgICAgLy8gdGhhdCdzIGN1cnJlbnRseSBpbiBhbnkgb2YgdGhlaXIgcmFuZ2VzLCBidXQgZHVyaW5nXG4gICAgICAgIC8vIGF1dG9yYW5nZSBvZiBhIHN1YnNldCBvZiBheGVzIHdlIHdpbGwgaWdub3JlIG90aGVyXG4gICAgICAgIC8vIGF4ZXMgZm9yIHRoaXMgcHVycG9zZS5cbiAgICAgICAgdmFyIG1hdGNoU2NhbGUgPSBJbmZpbml0eTtcbiAgICAgICAgdmFyIG5vcm1TY2FsZXMgPSB7fTtcbiAgICAgICAgdmFyIGF4ZXMgPSB7fTtcbiAgICAgICAgdmFyIGhhc0FueURvbWFpbkNvbnN0cmFpbnQgPSBmYWxzZTtcblxuICAgICAgICAvLyBmaW5kIHRoZSAobm9ybWFsaXplZCkgc2NhbGUgb2YgZWFjaCBheGlzIGluIHRoZSBncm91cFxuICAgICAgICBmb3IoaiA9IDA7IGogPCBheGlzSURzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBheGlzSUQgPSBheGlzSURzW2pdO1xuICAgICAgICAgICAgYXhlc1theGlzSURdID0gYXggPSBmdWxsTGF5b3V0W2lkMm5hbWUoYXhpc0lEKV07XG5cbiAgICAgICAgICAgIGlmKGF4Ll9pbnB1dERvbWFpbikgYXguZG9tYWluID0gYXguX2lucHV0RG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICBlbHNlIGF4Ll9pbnB1dERvbWFpbiA9IGF4LmRvbWFpbi5zbGljZSgpO1xuXG4gICAgICAgICAgICBpZighYXguX2lucHV0UmFuZ2UpIGF4Ll9pbnB1dFJhbmdlID0gYXgucmFuZ2Uuc2xpY2UoKTtcblxuICAgICAgICAgICAgLy8gc2V0IGF4aXMgc2NhbGUgaGVyZSBzbyB3ZSBjYW4gdXNlIF9tIHJhdGhlciB0aGFuXG4gICAgICAgICAgICAvLyBoYXZpbmcgdG8gY2FsY3VsYXRlIGl0IGZyb20gbGVuZ3RoIGFuZCByYW5nZVxuICAgICAgICAgICAgYXguc2V0U2NhbGUoKTtcblxuICAgICAgICAgICAgLy8gYWJzOiBpbnZlcnRlZCBzY2FsZXMgc3RpbGwgc2F0aXNmeSB0aGUgY29uc3RyYWludFxuICAgICAgICAgICAgbm9ybVNjYWxlc1theGlzSURdID0gbm9ybVNjYWxlID0gTWF0aC5hYnMoYXguX20pIC8gZ3JvdXBbYXhpc0lEXTtcbiAgICAgICAgICAgIG1pblNjYWxlID0gTWF0aC5taW4obWluU2NhbGUsIG5vcm1TY2FsZSk7XG4gICAgICAgICAgICBpZihheC5jb25zdHJhaW4gPT09ICdkb21haW4nIHx8ICFheC5fY29uc3RyYWludFNocmlua2FibGUpIHtcbiAgICAgICAgICAgICAgICBtYXRjaFNjYWxlID0gTWF0aC5taW4obWF0Y2hTY2FsZSwgbm9ybVNjYWxlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBoYXMgc2VydmVkIGl0cyBwdXJwb3NlLCBzbyByZW1vdmUgaXRcbiAgICAgICAgICAgIGRlbGV0ZSBheC5fY29uc3RyYWludFNocmlua2FibGU7XG4gICAgICAgICAgICBtYXhTY2FsZSA9IE1hdGgubWF4KG1heFNjYWxlLCBub3JtU2NhbGUpO1xuXG4gICAgICAgICAgICBpZihheC5jb25zdHJhaW4gPT09ICdkb21haW4nKSBoYXNBbnlEb21haW5Db25zdHJhaW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERvIHdlIGhhdmUgYSBjb25zdHJhaW50IG1pc21hdGNoPyBHaXZlIGEgc21hbGwgYnVmZmVyIGZvciByb3VuZGluZyBlcnJvcnNcbiAgICAgICAgaWYobWluU2NhbGUgPiBBTE1PU1RfRVFVQUwgKiBtYXhTY2FsZSAmJiAhaGFzQW55RG9tYWluQ29uc3RyYWludCkgY29udGludWU7XG5cbiAgICAgICAgLy8gbm93IGluY3JlYXNlIGFueSByYW5nZXMgd2UgbmVlZCB0byB1bnRpbCBhbGwgbm9ybWFsaXplZCBzY2FsZXMgYXJlIGVxdWFsXG4gICAgICAgIGZvcihqID0gMDsgaiA8IGF4aXNJRHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGF4aXNJRCA9IGF4aXNJRHNbal07XG4gICAgICAgICAgICBub3JtU2NhbGUgPSBub3JtU2NhbGVzW2F4aXNJRF07XG4gICAgICAgICAgICBheCA9IGF4ZXNbYXhpc0lEXTtcbiAgICAgICAgICAgIG1vZGUgPSBheC5jb25zdHJhaW47XG5cbiAgICAgICAgICAgIC8vIGV2ZW4gaWYgdGhlIHNjYWxlIGRpZG4ndCBjaGFuZ2UsIGlmIHdlJ3JlIHNocmlua2luZyBkb21haW5cbiAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8gcmVjYWxjdWxhdGUgaW4gY2FzZSBgY29uc3RyYWludG93YXJkYCBjaGFuZ2VkXG4gICAgICAgICAgICBpZihub3JtU2NhbGUgIT09IG1hdGNoU2NhbGUgfHwgbW9kZSA9PT0gJ2RvbWFpbicpIHtcbiAgICAgICAgICAgICAgICBmYWN0b3IgPSBub3JtU2NhbGUgLyBtYXRjaFNjYWxlO1xuXG4gICAgICAgICAgICAgICAgaWYobW9kZSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICBzY2FsZVpvb20oYXgsIGZhY3Rvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBtb2RlID09PSAnZG9tYWluJ1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dERvbWFpbiA9IGF4Ll9pbnB1dERvbWFpbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvbWFpblNocnVuayA9IChheC5kb21haW5bMV0gLSBheC5kb21haW5bMF0pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIChpbnB1dERvbWFpblsxXSAtIGlucHV0RG9tYWluWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJhbmdlU2hydW5rID0gKGF4LnIybChheC5yYW5nZVsxXSkgLSBheC5yMmwoYXgucmFuZ2VbMF0pKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAoYXgucjJsKGF4Ll9pbnB1dFJhbmdlWzFdKSAtIGF4LnIybChheC5faW5wdXRSYW5nZVswXSkpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZhY3RvciAvPSBkb21haW5TaHJ1bms7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoZmFjdG9yICogcmFuZ2VTaHJ1bmsgPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSd2ZSBhc2tlZCB0byBtYWduaWZ5IHRoZSBheGlzIG1vcmUgdGhhbiB3ZSBjYW4ganVzdCBieVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW5sYXJnaW5nIHRoZSBkb21haW4gLSBzbyB3ZSBuZWVkIHRvIGNvbnN0cmljdCByYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgYXguZG9tYWluID0gYXguX2lucHV0LmRvbWFpbiA9IGlucHV0RG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZVpvb20oYXgsIGZhY3Rvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKHJhbmdlU2hydW5rIDwgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJhbmdlIGhhcyBwcmV2aW91c2x5IGJlZW4gY29uc3RyaWN0ZWQgYnkgXl4sIGJ1dCB3ZSd2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3dpdGNoZWQgdG8gdGhlIGRvbWFpbi1jb25zdHJpY3RlZCByZWdpbWUsIHNvIHJlc2V0IHJhbmdlXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5yYW5nZSA9IGF4Ll9pbnB1dC5yYW5nZSA9IGF4Ll9pbnB1dFJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3IgKj0gcmFuZ2VTaHJ1bms7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZihheC5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiByYW5nZSAmIGZhY3RvciBtYXkgbmVlZCB0byBjaGFuZ2UgYmVjYXVzZSByYW5nZSB3YXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIGNhbGN1bGF0ZWQgZm9yIHRoZSBsYXJnZXIgc2NhbGluZywgc28gc29tZSBwaXhlbFxuICAgICAgICAgICAgICAgICAgICAgICAgICogcGFkZGluZ3MgbWF5IGdldCBjdXQgb2ZmIHdoZW4gd2UgcmVkdWNlIHRoZSBkb21haW4uXG4gICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICogVGhpcyBpcyBlYXNpZXIgdGhhbiB0aGUgcmVndWxhciBhdXRvcmFuZ2UgY2FsY3VsYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAqIGJlY2F1c2Ugd2UgYWxyZWFkeSBrbm93IHRoZSBzY2FsaW5nIGBtYCwgYnV0IHdlIHN0aWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBuZWVkIHRvIGN1dCBvdXQgaW1wb3NzaWJsZSBjb25zdHJhaW50cyAobGlrZVxuICAgICAgICAgICAgICAgICAgICAgICAgICogYW5ub3RhdGlvbnMgd2l0aCBzdXBlci1sb25nIGFycm93cykuIFRoYXQncyB3aGF0XG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBvdXRlck1pbi9NYXggYXJlIGZvciAtIGlmIHRoZSBleHBhbnNpb24gd2FzIGdvaW5nIHRvXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBnbyBiZXlvbmQgdGhlIG9yaWdpbmFsIGRvbWFpbiwgaXQgbXVzdCBiZSBpbXBvc3NpYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBybDAgPSBheC5yMmwoYXgucmFuZ2VbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJsMSA9IGF4LnIybChheC5yYW5nZVsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFuZ2VDZW50ZXIgPSAocmwwICsgcmwxKSAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFuZ2VNaW4gPSByYW5nZUNlbnRlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYW5nZU1heCA9IHJhbmdlQ2VudGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhhbGZSYW5nZSA9IE1hdGguYWJzKHJsMSAtIHJhbmdlQ2VudGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGV4dHJhIHRpbnkgYml0IGZvciByb3VuZGluZyBlcnJvcnMsIGluIGNhc2Ugd2UgYWN0dWFsbHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICphcmUqIGV4cGFuZGluZyB0byB0aGUgZnVsbCBkb21haW5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvdXRlck1pbiA9IHJhbmdlQ2VudGVyIC0gaGFsZlJhbmdlICogZmFjdG9yICogMS4wMDAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG91dGVyTWF4ID0gcmFuZ2VDZW50ZXIgKyBoYWxmUmFuZ2UgKiBmYWN0b3IgKiAxLjAwMDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZ2V0UGFkID0gbWFrZVBhZEZuKGF4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlRG9tYWluKGF4LCBmYWN0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXguc2V0U2NhbGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtID0gTWF0aC5hYnMoYXguX20pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV4dHJlbWVzID0gY29uY2F0RXh0cmVtZXMoZ2QsIGF4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtaW5BcnJheSA9IGV4dHJlbWVzLm1pbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXhBcnJheSA9IGV4dHJlbWVzLm1heDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdWYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgbWluQXJyYXkubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWwgPSBtaW5BcnJheVtrXS52YWwgLSBnZXRQYWQobWluQXJyYXlba10pIC8gbTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihuZXdWYWwgPiBvdXRlck1pbiAmJiBuZXdWYWwgPCByYW5nZU1pbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZU1pbiA9IG5ld1ZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcihrID0gMDsgayA8IG1heEFycmF5Lmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsID0gbWF4QXJyYXlba10udmFsICsgZ2V0UGFkKG1heEFycmF5W2tdKSAvIG07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYobmV3VmFsIDwgb3V0ZXJNYXggJiYgbmV3VmFsID4gcmFuZ2VNYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VNYXggPSBuZXdWYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZG9tYWluRXhwYW5kID0gKHJhbmdlTWF4IC0gcmFuZ2VNaW4pIC8gKDIgKiBoYWxmUmFuZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9yIC89IGRvbWFpbkV4cGFuZDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VNaW4gPSBheC5sMnIocmFuZ2VNaW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VNYXggPSBheC5sMnIocmFuZ2VNYXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXgucmFuZ2UgPSBheC5faW5wdXQucmFuZ2UgPSAocmwwIDwgcmwxKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JhbmdlTWluLCByYW5nZU1heF0gOiBbcmFuZ2VNYXgsIHJhbmdlTWluXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZURvbWFpbihheCwgZmFjdG9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBGb3IgdXNlIGJlZm9yZSBhdXRvcmFuZ2luZywgY2hlY2sgaWYgdGhpcyBheGlzIHdhcyBwcmV2aW91c2x5IGNvbnN0cmFpbmVkXG4vLyBieSBkb21haW4gYnV0IG5vIGxvbmdlciBpc1xuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uIGNsZWFuQ29uc3RyYWludHMoZ2QsIGF4KSB7XG4gICAgaWYoYXguX2lucHV0RG9tYWluKSB7XG4gICAgICAgIHZhciBpc0NvbnN0cmFpbmVkID0gZmFsc2U7XG4gICAgICAgIHZhciBheElkID0gYXguX2lkO1xuICAgICAgICB2YXIgY29uc3RyYWludEdyb3VwcyA9IGdkLl9mdWxsTGF5b3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcztcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNvbnN0cmFpbnRHcm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGNvbnN0cmFpbnRHcm91cHNbal1bYXhJZF0pIHtcbiAgICAgICAgICAgICAgICBpc0NvbnN0cmFpbmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZighaXNDb25zdHJhaW5lZCB8fCBheC5jb25zdHJhaW4gIT09ICdkb21haW4nKSB7XG4gICAgICAgICAgICBheC5faW5wdXQuZG9tYWluID0gYXguZG9tYWluID0gYXguX2lucHV0RG9tYWluO1xuICAgICAgICAgICAgZGVsZXRlIGF4Ll9pbnB1dERvbWFpbjtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHVwZGF0ZURvbWFpbihheCwgZmFjdG9yKSB7XG4gICAgdmFyIGlucHV0RG9tYWluID0gYXguX2lucHV0RG9tYWluO1xuICAgIHZhciBjZW50ZXJGcmFjdGlvbiA9IEZST01fQkxbYXguY29uc3RyYWludG93YXJkXTtcbiAgICB2YXIgY2VudGVyID0gaW5wdXREb21haW5bMF0gKyAoaW5wdXREb21haW5bMV0gLSBpbnB1dERvbWFpblswXSkgKiBjZW50ZXJGcmFjdGlvbjtcblxuICAgIGF4LmRvbWFpbiA9IGF4Ll9pbnB1dC5kb21haW4gPSBbXG4gICAgICAgIGNlbnRlciArIChpbnB1dERvbWFpblswXSAtIGNlbnRlcikgLyBmYWN0b3IsXG4gICAgICAgIGNlbnRlciArIChpbnB1dERvbWFpblsxXSAtIGNlbnRlcikgLyBmYWN0b3JcbiAgICBdO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xudmFyIHN1cHBvcnRzUGFzc2l2ZSA9IHJlcXVpcmUoJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBzZXRDdXJzb3IgPSByZXF1aXJlKCcuLi8uLi9saWIvc2V0Y3Vyc29yJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50Jyk7XG52YXIgRlJPTV9UTCA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5GUk9NX1RMO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xudmFyIHJlZHJhd1JlZ2xUcmFjZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lcycpLnJlZHJhd1JlZ2xUcmFjZXM7XG5cbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzJyk7XG5cbnZhciBkb1RpY2tzU2luZ2xlID0gcmVxdWlyZSgnLi9heGVzJykuZG9UaWNrc1NpbmdsZTtcbnZhciBnZXRGcm9tSWQgPSByZXF1aXJlKCcuL2F4aXNfaWRzJykuZ2V0RnJvbUlkO1xudmFyIHByZXBTZWxlY3QgPSByZXF1aXJlKCcuL3NlbGVjdCcpLnByZXBTZWxlY3Q7XG52YXIgY2xlYXJTZWxlY3QgPSByZXF1aXJlKCcuL3NlbGVjdCcpLmNsZWFyU2VsZWN0O1xudmFyIHNlbGVjdE9uQ2xpY2sgPSByZXF1aXJlKCcuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG52YXIgc2NhbGVab29tID0gcmVxdWlyZSgnLi9zY2FsZV96b29tJyk7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xudmFyIE1JTkRSQUcgPSBjb25zdGFudHMuTUlORFJBRztcbnZhciBNSU5aT09NID0gY29uc3RhbnRzLk1JTlpPT007XG5cblxuLy8gZmxhZyBmb3Igc2hvd2luZyBcImRvdWJsZWNsaWNrIHRvIHpvb20gb3V0XCIgb25seSBhdCB0aGUgYmVnaW5uaW5nXG52YXIgU0hPV1pPT01PVVRUSVAgPSB0cnVlO1xuXG4vLyBkcmFnQm94OiBjcmVhdGUgYW4gZWxlbWVudCB0byBkcmFnIG9uZSBvciBtb3JlIGF4aXMgZW5kc1xuLy8gaW5wdXRzOlxuLy8gICAgICBwbG90aW5mbyAtIHdoaWNoIHN1YnBsb3QgYXJlIHdlIG1ha2luZyBkcmFnYm94ZXMgb24/XG4vLyAgICAgIHgseSx3LGggLSBsZWZ0LCB0b3AsIHdpZHRoLCBoZWlnaHQgb2YgdGhlIGJveFxuLy8gICAgICBucyAtIGhvdyBkb2VzIHRoaXMgZHJhZyB0aGUgdmVydGljYWwgYXhpcz9cbi8vICAgICAgICAgICduJyAtIHRvcCBvbmx5XG4vLyAgICAgICAgICAncycgLSBib3R0b20gb25seVxuLy8gICAgICAgICAgJ25zJyAtIHRvcCBhbmQgYm90dG9tIHRvZ2V0aGVyLCBkaWZmZXJlbmNlIHVuY2hhbmdlZFxuLy8gICAgICBldyAtIHNhbWUgZm9yIGhvcml6b250YWwgYXhpc1xuZnVuY3Rpb24gbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4LCB5LCB3LCBoLCBucywgZXcpIHtcbiAgICAvLyBtb3VzZURvd24gc3RvcmVzIG1zIG9mIGZpcnN0IG1vdXNlZG93biBldmVudCBpbiB0aGUgbGFzdFxuICAgIC8vIERCTENMSUNLREVMQVkgbXMgb24gdGhlIGRyYWcgYmFyc1xuICAgIC8vIG51bUNsaWNrcyBzdG9yZXMgaG93IG1hbnkgbW91c2Vkb3ducyBoYXZlIGJlZW4gc2VlblxuICAgIC8vIHdpdGhpbiBEQkxDTElDS0RFTEFZIHNvIHdlIGNhbiBjaGVjayBmb3IgY2xpY2sgb3IgZG91YmxlY2xpY2sgZXZlbnRzXG4gICAgLy8gZHJhZ2dlZCBzdG9yZXMgd2hldGhlciBhIGRyYWcgaGFzIG9jY3VycmVkLCBzbyB3ZSBkb24ndCBoYXZlIHRvXG4gICAgLy8gcmVkcmF3IHVubmVjZXNzYXJpbHksIGllIGlmIG5vIG1vdmUgYmlnZ2VyIHRoYW4gTUlORFJBRyBvciBNSU5aT09NIHB4XG4gICAgdmFyIHpvb21sYXllciA9IGdkLl9mdWxsTGF5b3V0Ll96b29tbGF5ZXI7XG4gICAgdmFyIGlzTWFpbkRyYWcgPSAobnMgKyBldyA9PT0gJ25zZXcnKTtcbiAgICB2YXIgc2luZ2xlRW5kID0gKG5zICsgZXcpLmxlbmd0aCA9PT0gMTtcblxuICAgIC8vIG1haW4gc3VicGxvdCB4IGFuZCB5IChpLmUuIGZvdW5kIGluIHBsb3RpbmZvIC0gdGhlIG1haW4gb25lcylcbiAgICB2YXIgeGEwLCB5YTA7XG4gICAgLy8ge2F4Ll9pZDogYXh9IGhhc2ggb2JqZWN0c1xuICAgIHZhciB4YUhhc2gsIHlhSGFzaDtcbiAgICAvLyB4YUhhc2gveWFIYXNoIHZhbHVlcyAoYXJyYXlzKVxuICAgIHZhciB4YXhlcywgeWF4ZXM7XG4gICAgLy8gbWFpbiBheGlzIG9mZnNldHNcbiAgICB2YXIgeHMsIHlzO1xuICAgIC8vIG1haW4gYXhpcyBsZW5ndGhzXG4gICAgdmFyIHB3LCBwaDtcbiAgICAvLyBjb250YWlucyBrZXlzICd4YUhhc2gnLCAneWFIYXNoJywgJ3hheGVzJywgYW5kICd5YXhlcydcbiAgICAvLyB3aGljaCBhcmUgdGhlIHgveSB7YXguX2lkOiBheH0gaGFzaCBvYmplY3RzIGFuZCB0aGVpciB2YWx1ZXNcbiAgICAvLyBmb3IgbGlua2VkIGF4aXMgcmVsYXRpdmUgdG8gdGhpcyBzdWJwbG90XG4gICAgdmFyIGxpbmtzO1xuICAgIC8vIHNldCB0byBldy9ucyB2YWwgd2hlbiBhY3RpdmUsIHNldCB0byAnJyB3aGVuIGluYWN0aXZlXG4gICAgdmFyIHhBY3RpdmUsIHlBY3RpdmU7XG4gICAgLy8gYXJlIGFsbCBheGVzIGluIHRoaXMgc3VicGxvdCBhcmUgZml4ZWQ/XG4gICAgdmFyIGFsbEZpeGVkUmFuZ2VzO1xuICAgIC8vIGlzIHN1YnBsb3QgY29uc3RyYWluZWQ/XG4gICAgdmFyIGlzU3VicGxvdENvbnN0cmFpbmVkO1xuICAgIC8vIGRvIHdlIG5lZWQgdG8gZWRpdCB4L3kgcmFuZ2VzP1xuICAgIHZhciBlZGl0WCwgZWRpdFk7XG4gICAgLy8gZ3JhcGgtd2lkZSBvcHRpbWl6YXRpb24gZmxhZ3NcbiAgICB2YXIgaGFzU2NhdHRlckdsLCBoYXNTcGxvbSwgaGFzU1ZHO1xuICAgIC8vIGNvbGxlY3RlZCBjaGFuZ2VzIHRvIGJlIG1hZGUgdG8gdGhlIHBsb3QgYnkgcmVsYXlvdXQgYXQgdGhlIGVuZFxuICAgIHZhciB1cGRhdGVzO1xuXG4gICAgZnVuY3Rpb24gcmVjb21wdXRlQXhpc0xpc3RzKCkge1xuICAgICAgICB4YTAgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgeWEwID0gcGxvdGluZm8ueWF4aXM7XG4gICAgICAgIHB3ID0geGEwLl9sZW5ndGg7XG4gICAgICAgIHBoID0geWEwLl9sZW5ndGg7XG4gICAgICAgIHhzID0geGEwLl9vZmZzZXQ7XG4gICAgICAgIHlzID0geWEwLl9vZmZzZXQ7XG5cbiAgICAgICAgeGFIYXNoID0ge307XG4gICAgICAgIHhhSGFzaFt4YTAuX2lkXSA9IHhhMDtcbiAgICAgICAgeWFIYXNoID0ge307XG4gICAgICAgIHlhSGFzaFt5YTAuX2lkXSA9IHlhMDtcblxuICAgICAgICAvLyBpZiB3ZSdyZSBkcmFnZ2luZyB0d28gYXhlcyBhdCBvbmNlLCBhbHNvIGRyYWcgb3ZlcmxheXNcbiAgICAgICAgaWYobnMgJiYgZXcpIHtcbiAgICAgICAgICAgIHZhciBvdmVybGF5cyA9IHBsb3RpbmZvLm92ZXJsYXlzO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG92ZXJsYXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhhID0gb3ZlcmxheXNbaV0ueGF4aXM7XG4gICAgICAgICAgICAgICAgeGFIYXNoW3hhLl9pZF0gPSB4YTtcbiAgICAgICAgICAgICAgICB2YXIgeWEgPSBvdmVybGF5c1tpXS55YXhpcztcbiAgICAgICAgICAgICAgICB5YUhhc2hbeWEuX2lkXSA9IHlhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgeGF4ZXMgPSBoYXNoVmFsdWVzKHhhSGFzaCk7XG4gICAgICAgIHlheGVzID0gaGFzaFZhbHVlcyh5YUhhc2gpO1xuICAgICAgICB4QWN0aXZlID0gaXNEaXJlY3Rpb25BY3RpdmUoeGF4ZXMsIGV3KTtcbiAgICAgICAgeUFjdGl2ZSA9IGlzRGlyZWN0aW9uQWN0aXZlKHlheGVzLCBucyk7XG4gICAgICAgIGFsbEZpeGVkUmFuZ2VzID0gIXlBY3RpdmUgJiYgIXhBY3RpdmU7XG5cbiAgICAgICAgbGlua3MgPSBjYWxjTGlua3MoZ2QsIHhhSGFzaCwgeWFIYXNoKTtcbiAgICAgICAgaXNTdWJwbG90Q29uc3RyYWluZWQgPSBsaW5rcy5pc1N1YnBsb3RDb25zdHJhaW5lZDtcbiAgICAgICAgZWRpdFggPSBldyB8fCBpc1N1YnBsb3RDb25zdHJhaW5lZDtcbiAgICAgICAgZWRpdFkgPSBucyB8fCBpc1N1YnBsb3RDb25zdHJhaW5lZDtcblxuICAgICAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICBoYXNTY2F0dGVyR2wgPSBmdWxsTGF5b3V0Ll9oYXMoJ3NjYXR0ZXJnbCcpO1xuICAgICAgICBoYXNTcGxvbSA9IGZ1bGxMYXlvdXQuX2hhcygnc3Bsb20nKTtcbiAgICAgICAgaGFzU1ZHID0gZnVsbExheW91dC5faGFzKCdzdmcnKTtcbiAgICB9XG5cbiAgICByZWNvbXB1dGVBeGlzTGlzdHMoKTtcblxuICAgIHZhciBjdXJzb3IgPSBnZXREcmFnQ3Vyc29yKHlBY3RpdmUgKyB4QWN0aXZlLCBnZC5fZnVsbExheW91dC5kcmFnbW9kZSwgaXNNYWluRHJhZyk7XG4gICAgdmFyIGRyYWdnZXIgPSBtYWtlUmVjdERyYWdnZXIocGxvdGluZm8sIG5zICsgZXcgKyAnZHJhZycsIGN1cnNvciwgeCwgeSwgdywgaCk7XG5cbiAgICAvLyBzdGlsbCBuZWVkIHRvIG1ha2UgdGhlIGVsZW1lbnQgaWYgdGhlIGF4ZXMgYXJlIGRpc2FibGVkXG4gICAgLy8gYnV0IG51a2UgaXRzIGV2ZW50cyAoZXhjZXB0IGZvciBtYWluZHJhZyB3aGljaCBuZWVkcyB0aGVtIGZvciBob3ZlcilcbiAgICAvLyBhbmQgc3RvcCB0aGVyZVxuICAgIGlmKGFsbEZpeGVkUmFuZ2VzICYmICFpc01haW5EcmFnKSB7XG4gICAgICAgIGRyYWdnZXIub25tb3VzZWRvd24gPSBudWxsO1xuICAgICAgICBkcmFnZ2VyLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgIHJldHVybiBkcmFnZ2VyO1xuICAgIH1cblxuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZWxlbWVudDogZHJhZ2dlcixcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBwbG90aW5mbzogcGxvdGluZm9cbiAgICB9O1xuXG4gICAgZHJhZ09wdGlvbnMucHJlcEZuID0gZnVuY3Rpb24oZSwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgdmFyIGRyYWdNb2RlUHJldiA9IGRyYWdPcHRpb25zLmRyYWdtb2RlO1xuICAgICAgICB2YXIgZHJhZ01vZGVOb3cgPSBnZC5fZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICAgICAgaWYoZHJhZ01vZGVOb3cgIT09IGRyYWdNb2RlUHJldikge1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMuZHJhZ21vZGUgPSBkcmFnTW9kZU5vdztcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29tcHV0ZUF4aXNMaXN0cygpO1xuXG4gICAgICAgIGlmKCFhbGxGaXhlZFJhbmdlcykge1xuICAgICAgICAgICAgaWYoaXNNYWluRHJhZykge1xuICAgICAgICAgICAgICAgIC8vIG1haW4gZHJhZ2dlciBoYW5kbGVzIGFsbCBkcmFnIG1vZGVzLCBhbmQgY2hhbmdlc1xuICAgICAgICAgICAgICAgIC8vIHRvIHBhbiAob3IgdG8gem9vbSBpZiBpdCBhbHJlYWR5IGlzIHBhbikgb24gc2hpZnRcbiAgICAgICAgICAgICAgICBpZihlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAncGFuJykgZHJhZ01vZGVOb3cgPSAnem9vbSc7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoIWlzU2VsZWN0T3JMYXNzbyhkcmFnTW9kZU5vdykpIGRyYWdNb2RlTm93ID0gJ3Bhbic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdNb2RlTm93ID0gJ3Bhbic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYWxsIG90aGVyIGRyYWdnZXJzIGp1c3QgcGFuXG4gICAgICAgICAgICBlbHNlIGRyYWdNb2RlTm93ID0gJ3Bhbic7XG4gICAgICAgIH1cblxuICAgICAgICBpZihkcmFnTW9kZU5vdyA9PT0gJ2xhc3NvJykgZHJhZ09wdGlvbnMubWluRHJhZyA9IDE7XG4gICAgICAgIGVsc2UgZHJhZ09wdGlvbnMubWluRHJhZyA9IHVuZGVmaW5lZDtcblxuICAgICAgICBpZihpc1NlbGVjdE9yTGFzc28oZHJhZ01vZGVOb3cpKSB7XG4gICAgICAgICAgICBkcmFnT3B0aW9ucy54YXhlcyA9IHhheGVzO1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMueWF4ZXMgPSB5YXhlcztcbiAgICAgICAgICAgIC8vIHRoaXMgYXR0YWNoZXMgbW92ZUZuLCBjbGlja0ZuLCBkb25lRm4gb24gZHJhZ09wdGlvbnNcbiAgICAgICAgICAgIHByZXBTZWxlY3QoZSwgc3RhcnRYLCBzdGFydFksIGRyYWdPcHRpb25zLCBkcmFnTW9kZU5vdyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkcmFnT3B0aW9ucy5jbGlja0ZuID0gY2xpY2tGbjtcbiAgICAgICAgICAgIGlmKGlzU2VsZWN0T3JMYXNzbyhkcmFnTW9kZVByZXYpKSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETyBGaXggcG90ZW50aWFsIGJ1Z1xuICAgICAgICAgICAgICAgIC8vIE5vdGU6IGNsZWFyaW5nIC8gcmVzZXR0aW5nIHNlbGVjdGlvbiBzdGF0ZSBvbmx5IGhhcHBlbnMsIHdoZW4gdXNlclxuICAgICAgICAgICAgICAgIC8vIHRyaWdnZXJzIGF0IGxlYXN0IG9uZSBpbnRlcmFjdGlvbiBpbiBwYW4vem9vbSBtb2RlLiBPdGhlcndpc2UsIHRoZVxuICAgICAgICAgICAgICAgIC8vIHNlbGVjdC9sYXNzbyBvdXRsaW5lcyBhcmUgZGVsZXRlZCAoaW4gcGxvdHMuanMuY2xlYW5QbG90KSBidXQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIC8vIGNhY2hlIGlzbid0IGNsZWFyZWQuIFNvIHdoZW4gdGhlIHVzZXIgc3dpdGNoZXMgYmFjayB0byBzZWxlY3QvbGFzc28gYW5kXG4gICAgICAgICAgICAgICAgLy8gJ2FkZHMgdG8gYSBzZWxlY3Rpb24nIHdpdGggU2hpZnQsIHRoZSBcIm9sZFwiLCBzZWVtaW5nbHkgcmVtb3ZlZCBvdXRsaW5lc1xuICAgICAgICAgICAgICAgIC8vIGFyZSByZWRyYXduIGFnYWluIGJlY2F1c2UgdGhlIHNlbGVjdGlvbiBjYWNoZSBzdGlsbCBob2xkcyB0aGVpciBjb29yZGluYXRlcy5cbiAgICAgICAgICAgICAgICAvLyBIb3dldmVyLCB0aGlzIGlzbid0IGVhc2lseSBzb2x2ZWQsIHNpbmNlIHBsb3RzLmpzIHdvdWxkIG5lZWRcbiAgICAgICAgICAgICAgICAvLyB0byBoYXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBkcmFnT3B0aW9ucyBvYmplY3QgKHdoaWNoIGhvbGRzIHRoZVxuICAgICAgICAgICAgICAgIC8vIHNlbGVjdGlvbiBjYWNoZSkuXG4gICAgICAgICAgICAgICAgY2xlYXJBbmRSZXNldFNlbGVjdCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZighYWxsRml4ZWRSYW5nZXMpIHtcbiAgICAgICAgICAgICAgICBpZihkcmFnTW9kZU5vdyA9PT0gJ3pvb20nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IHpvb21Nb3ZlO1xuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5kb25lRm4gPSB6b29tRG9uZTtcblxuICAgICAgICAgICAgICAgICAgICAvLyB6b29tTW92ZSB0YWtlcyBjYXJlIG9mIHRoZSB0aHJlc2hvbGQsIGJ1dCB3ZSBuZWVkIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIG1pbmltaXplIHRoaXMgc28gdGhhdCBjb25zdHJhaW5lZCB6b29tIGJveGVzIHdpbGwgZmxpcFxuICAgICAgICAgICAgICAgICAgICAvLyBvcmllbnRhdGlvbiBhdCB0aGUgcmlnaHQgcGxhY2VcbiAgICAgICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMubWluRHJhZyA9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgem9vbVByZXAoZSwgc3RhcnRYLCBzdGFydFkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihkcmFnTW9kZU5vdyA9PT0gJ3BhbicpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMubW92ZUZuID0gcGxvdERyYWc7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmRvbmVGbiA9IGRyYWdUYWlsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjbGVhckFuZFJlc2V0U2VsZWN0KCkge1xuICAgICAgICAvLyBjbGVhciBzZWxlY3Rpb24gcG9seWdvbiBjYWNoZSAoaWYgYW55KVxuICAgICAgICBkcmFnT3B0aW9ucy5wbG90aW5mby5zZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgLy8gY2xlYXIgc2VsZWN0aW9uIG91dGxpbmVzXG4gICAgICAgIGNsZWFyU2VsZWN0KHpvb21sYXllcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xpY2tGbihudW1DbGlja3MsIGV2dCkge1xuICAgICAgICB2YXIgY2xpY2ttb2RlID0gZ2QuX2Z1bGxMYXlvdXQuY2xpY2ttb2RlO1xuXG4gICAgICAgIHJlbW92ZVpvb21ib3goZ2QpO1xuXG4gICAgICAgIGlmKG51bUNsaWNrcyA9PT0gMiAmJiAhc2luZ2xlRW5kKSBkb3VibGVDbGljaygpO1xuXG4gICAgICAgIGlmKGlzTWFpbkRyYWcpIHtcbiAgICAgICAgICAgIGlmKGNsaWNrbW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0T25DbGljayhldnQsIGdkLCB4YXhlcywgeWF4ZXMsIHBsb3RpbmZvLmlkLCBkcmFnT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGNsaWNrbW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBGeC5jbGljayhnZCwgZXZ0LCBwbG90aW5mby5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihudW1DbGlja3MgPT09IDEgJiYgc2luZ2xlRW5kKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBucyA/IHlhMCA6IHhhMCxcbiAgICAgICAgICAgICAgICBlbmQgPSAobnMgPT09ICdzJyB8fCBldyA9PT0gJ3cnKSA/IDAgOiAxLFxuICAgICAgICAgICAgICAgIGF0dHJTdHIgPSBheC5fbmFtZSArICcucmFuZ2VbJyArIGVuZCArICddJyxcbiAgICAgICAgICAgICAgICBpbml0aWFsVGV4dCA9IGdldEVuZFRleHQoYXgsIGVuZCksXG4gICAgICAgICAgICAgICAgaEFsaWduID0gJ2xlZnQnLFxuICAgICAgICAgICAgICAgIHZBbGlnbiA9ICdtaWRkbGUnO1xuXG4gICAgICAgICAgICBpZihheC5maXhlZHJhbmdlKSByZXR1cm47XG5cbiAgICAgICAgICAgIGlmKG5zKSB7XG4gICAgICAgICAgICAgICAgdkFsaWduID0gKG5zID09PSAnbicpID8gJ3RvcCcgOiAnYm90dG9tJztcbiAgICAgICAgICAgICAgICBpZihheC5zaWRlID09PSAncmlnaHQnKSBoQWxpZ24gPSAncmlnaHQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihldyA9PT0gJ2UnKSBoQWxpZ24gPSAncmlnaHQnO1xuXG4gICAgICAgICAgICBpZihnZC5fY29udGV4dC5zaG93QXhpc1JhbmdlRW50cnlCb3hlcykge1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdChkcmFnZ2VyKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMubWFrZUVkaXRhYmxlLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZDogZ2QsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbW1lZGlhdGU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiBnZC5fZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogU3RyaW5nKGluaXRpYWxUZXh0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw6IGF4LnRpY2tmb250ID8gYXgudGlja2ZvbnQuY29sb3IgOiAnIzQ0NCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3Jpem9udGFsQWxpZ246IGhBbGlnbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRpY2FsQWxpZ246IHZBbGlnblxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAub24oJ2VkaXQnLCBmdW5jdGlvbih0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdiA9IGF4LmQycih0ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGF0dHJTdHIsIHYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRyYWdFbGVtZW50LmluaXQoZHJhZ09wdGlvbnMpO1xuXG4gICAgdmFyIHgwLFxuICAgICAgICB5MCxcbiAgICAgICAgYm94LFxuICAgICAgICBsdW0sXG4gICAgICAgIHBhdGgwLFxuICAgICAgICBkaW1tZWQsXG4gICAgICAgIHpvb21Nb2RlLFxuICAgICAgICB6YixcbiAgICAgICAgY29ybmVycztcblxuICAgIC8vIHpvb20gdGFrZXMgb3ZlciBtaW5EcmFnLCBzbyBpdCBhbHNvIGhhcyB0byB0YWtlIG92ZXIgZ2QuX2RyYWdnZWRcbiAgICB2YXIgem9vbURyYWdnZWQ7XG5cbiAgICBmdW5jdGlvbiB6b29tUHJlcChlLCBzdGFydFgsIHN0YXJ0WSkge1xuICAgICAgICB2YXIgZHJhZ0JCb3ggPSBkcmFnZ2VyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB4MCA9IHN0YXJ0WCAtIGRyYWdCQm94LmxlZnQ7XG4gICAgICAgIHkwID0gc3RhcnRZIC0gZHJhZ0JCb3gudG9wO1xuICAgICAgICBib3ggPSB7bDogeDAsIHI6IHgwLCB3OiAwLCB0OiB5MCwgYjogeTAsIGg6IDB9O1xuICAgICAgICBsdW0gPSBnZC5faG1waXhjb3VudCA/XG4gICAgICAgICAgICAoZ2QuX2htbHVtY291bnQgLyBnZC5faG1waXhjb3VudCkgOlxuICAgICAgICAgICAgdGlueWNvbG9yKGdkLl9mdWxsTGF5b3V0LnBsb3RfYmdjb2xvcikuZ2V0THVtaW5hbmNlKCk7XG4gICAgICAgIHBhdGgwID0gJ00wLDBIJyArIHB3ICsgJ1YnICsgcGggKyAnSDBWMCc7XG4gICAgICAgIGRpbW1lZCA9IGZhbHNlO1xuICAgICAgICB6b29tTW9kZSA9ICd4eSc7XG4gICAgICAgIHpvb21EcmFnZ2VkID0gZmFsc2U7XG5cbiAgICAgICAgemIgPSBtYWtlWm9vbWJveCh6b29tbGF5ZXIsIGx1bSwgeHMsIHlzLCBwYXRoMCk7XG5cbiAgICAgICAgY29ybmVycyA9IG1ha2VDb3JuZXJzKHpvb21sYXllciwgeHMsIHlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tTW92ZShkeDAsIGR5MCkge1xuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbmluZ1dpdGhEdXJhdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHgxID0gTWF0aC5tYXgoMCwgTWF0aC5taW4ocHcsIGR4MCArIHgwKSksXG4gICAgICAgICAgICB5MSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHBoLCBkeTAgKyB5MCkpLFxuICAgICAgICAgICAgZHggPSBNYXRoLmFicyh4MSAtIHgwKSxcbiAgICAgICAgICAgIGR5ID0gTWF0aC5hYnMoeTEgLSB5MCk7XG5cbiAgICAgICAgYm94LmwgPSBNYXRoLm1pbih4MCwgeDEpO1xuICAgICAgICBib3guciA9IE1hdGgubWF4KHgwLCB4MSk7XG4gICAgICAgIGJveC50ID0gTWF0aC5taW4oeTAsIHkxKTtcbiAgICAgICAgYm94LmIgPSBNYXRoLm1heCh5MCwgeTEpO1xuXG4gICAgICAgIGZ1bmN0aW9uIG5vWm9vbSgpIHtcbiAgICAgICAgICAgIHpvb21Nb2RlID0gJyc7XG4gICAgICAgICAgICBib3guciA9IGJveC5sO1xuICAgICAgICAgICAgYm94LnQgPSBib3guYjtcbiAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNMCwwWicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaXNTdWJwbG90Q29uc3RyYWluZWQpIHtcbiAgICAgICAgICAgIGlmKGR4ID4gTUlOWk9PTSB8fCBkeSA+IE1JTlpPT00pIHtcbiAgICAgICAgICAgICAgICB6b29tTW9kZSA9ICd4eSc7XG4gICAgICAgICAgICAgICAgaWYoZHggLyBwdyA+IGR5IC8gcGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZHkgPSBkeCAqIHBoIC8gcHc7XG4gICAgICAgICAgICAgICAgICAgIGlmKHkwID4geTEpIGJveC50ID0geTAgLSBkeTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBib3guYiA9IHkwICsgZHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkeCA9IGR5ICogcHcgLyBwaDtcbiAgICAgICAgICAgICAgICAgICAgaWYoeDAgPiB4MSkgYm94LmwgPSB4MCAtIGR4O1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGJveC5yID0geDAgKyBkeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeHlDb3JuZXJzKGJveCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9ab29tKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gbG9vayBmb3Igc21hbGwgZHJhZ3MgaW4gb25lIGRpcmVjdGlvbiBvciB0aGUgb3RoZXIsXG4gICAgICAgIC8vIGFuZCBvbmx5IGRyYWcgdGhlIG90aGVyIGF4aXNcbiAgICAgICAgZWxzZSBpZigheUFjdGl2ZSB8fCBkeSA8IE1hdGgubWluKE1hdGgubWF4KGR4ICogMC42LCBNSU5EUkFHKSwgTUlOWk9PTSkpIHtcbiAgICAgICAgICAgIGlmKGR4IDwgTUlORFJBRyB8fCAheEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIG5vWm9vbSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBib3gudCA9IDA7XG4gICAgICAgICAgICAgICAgYm94LmIgPSBwaDtcbiAgICAgICAgICAgICAgICB6b29tTW9kZSA9ICd4JztcbiAgICAgICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCB4Q29ybmVycyhib3gsIHkwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZigheEFjdGl2ZSB8fCBkeCA8IE1hdGgubWluKGR5ICogMC42LCBNSU5aT09NKSkge1xuICAgICAgICAgICAgYm94LmwgPSAwO1xuICAgICAgICAgICAgYm94LnIgPSBwdztcbiAgICAgICAgICAgIHpvb21Nb2RlID0gJ3knO1xuICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeUNvcm5lcnMoYm94LCB4MCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgem9vbU1vZGUgPSAneHknO1xuICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeHlDb3JuZXJzKGJveCkpO1xuICAgICAgICB9XG4gICAgICAgIGJveC53ID0gYm94LnIgLSBib3gubDtcbiAgICAgICAgYm94LmggPSBib3guYiAtIGJveC50O1xuXG4gICAgICAgIGlmKHpvb21Nb2RlKSB6b29tRHJhZ2dlZCA9IHRydWU7XG4gICAgICAgIGdkLl9kcmFnZ2VkID0gem9vbURyYWdnZWQ7XG5cbiAgICAgICAgdXBkYXRlWm9vbWJveCh6YiwgY29ybmVycywgYm94LCBwYXRoMCwgZGltbWVkLCBsdW0pO1xuICAgICAgICBkaW1tZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHpvb21Eb25lKCkge1xuICAgICAgICB1cGRhdGVzID0ge307XG5cbiAgICAgICAgLy8gbW9yZSBzdHJpY3QgdGhhbiBkcmFnZ2VkLCB3aGljaCBhbGxvd3MgeW91IHRvIGNvbWUgYmFjayB0byB3aGVyZSB5b3Ugc3RhcnRlZFxuICAgICAgICAvLyBhbmQgc3RpbGwgY291bnQgYXMgZHJhZ2dlZFxuICAgICAgICBpZihNYXRoLm1pbihib3guaCwgYm94LncpIDwgTUlORFJBRyAqIDIpIHtcbiAgICAgICAgICAgIHJldHVybiByZW1vdmVab29tYm94KGdkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRPRE86IGVkaXQgbGlua2VkIGF4ZXMgaW4gem9vbUF4UmFuZ2VzIGFuZCBpbiBkcmFnVGFpbFxuICAgICAgICBpZih6b29tTW9kZSA9PT0gJ3h5JyB8fCB6b29tTW9kZSA9PT0gJ3gnKSB7XG4gICAgICAgICAgICB6b29tQXhSYW5nZXMoeGF4ZXMsIGJveC5sIC8gcHcsIGJveC5yIC8gcHcsIHVwZGF0ZXMsIGxpbmtzLnhheGVzKTtcbiAgICAgICAgfVxuICAgICAgICBpZih6b29tTW9kZSA9PT0gJ3h5JyB8fCB6b29tTW9kZSA9PT0gJ3knKSB7XG4gICAgICAgICAgICB6b29tQXhSYW5nZXMoeWF4ZXMsIChwaCAtIGJveC5iKSAvIHBoLCAocGggLSBib3gudCkgLyBwaCwgdXBkYXRlcywgbGlua3MueWF4ZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVtb3ZlWm9vbWJveChnZCk7XG4gICAgICAgIGRyYWdUYWlsKCk7XG4gICAgICAgIHNob3dEb3VibGVDbGlja05vdGlmaWVyKGdkKTtcbiAgICB9XG5cbiAgICAvLyBzY3JvbGwgem9vbSwgb24gYWxsIGRyYWdnZXJzIGV4Y2VwdCBjb3JuZXJzXG4gICAgdmFyIHNjcm9sbFZpZXdCb3ggPSBbMCwgMCwgcHcsIHBoXTtcbiAgICAvLyB3YWl0IGEgbGl0dGxlIGFmdGVyIHNjcm9sbGluZyBiZWZvcmUgcmVkcmF3aW5nXG4gICAgdmFyIHJlZHJhd1RpbWVyID0gbnVsbDtcbiAgICB2YXIgUkVEUkFXREVMQVkgPSBjb25zdGFudHMuUkVEUkFXREVMQVk7XG4gICAgdmFyIG1haW5wbG90ID0gcGxvdGluZm8ubWFpbnBsb3QgPyBnZC5fZnVsbExheW91dC5fcGxvdHNbcGxvdGluZm8ubWFpbnBsb3RdIDogcGxvdGluZm87XG5cbiAgICBmdW5jdGlvbiB6b29tV2hlZWwoZSkge1xuICAgICAgICAvLyBkZWFjdGl2YXRlIG1vdXNld2hlZWwgc2Nyb2xsaW5nIG9uIGVtYmVkZGVkIGdyYXBoc1xuICAgICAgICAvLyBkZXZzIGNhbiBvdmVycmlkZSB0aGlzIHdpdGggbGF5b3V0Ll9lbmFibGVzY3JvbGx6b29tLFxuICAgICAgICAvLyBidXQgXyBlbnN1cmVzIHRoaXMgc2V0dGluZyB3b24ndCBsZWF2ZSB0aGVpciBwYWdlXG4gICAgICAgIGlmKCFnZC5fY29udGV4dC5zY3JvbGxab29tICYmICFnZC5fZnVsbExheW91dC5fZW5hYmxlc2Nyb2xsem9vbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYXJBbmRSZXNldFNlbGVjdCgpO1xuXG4gICAgICAgIC8vIElmIGEgdHJhbnNpdGlvbiBpcyBpbiBwcm9ncmVzcywgdGhlbiBkaXNhYmxlIGFueSBiZWhhdmlvcjpcbiAgICAgICAgaWYoZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24pIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGMgPSBnZC5xdWVyeVNlbGVjdG9yKCcucGxvdGx5Jyk7XG5cbiAgICAgICAgcmVjb21wdXRlQXhpc0xpc3RzKCk7XG5cbiAgICAgICAgLy8gaWYgdGhlIHBsb3QgaGFzIHNjcm9sbGJhcnMgKG1vcmUgdGhhbiBhIHRpbnkgZXhjZXNzKVxuICAgICAgICAvLyBkaXNhYmxlIHNjcm9sbHpvb20gdG9vLlxuICAgICAgICBpZihwYy5zY3JvbGxIZWlnaHQgLSBwYy5jbGllbnRIZWlnaHQgPiAxMCB8fFxuICAgICAgICAgICAgICAgIHBjLnNjcm9sbFdpZHRoIC0gcGMuY2xpZW50V2lkdGggPiAxMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYXJUaW1lb3V0KHJlZHJhd1RpbWVyKTtcblxuICAgICAgICB2YXIgd2hlZWxEZWx0YSA9IC1lLmRlbHRhWTtcbiAgICAgICAgaWYoIWlzRmluaXRlKHdoZWVsRGVsdGEpKSB3aGVlbERlbHRhID0gZS53aGVlbERlbHRhIC8gMTA7XG4gICAgICAgIGlmKCFpc0Zpbml0ZSh3aGVlbERlbHRhKSkge1xuICAgICAgICAgICAgTGliLmxvZygnRGlkIG5vdCBmaW5kIHdoZWVsIG1vdGlvbiBhdHRyaWJ1dGVzOiAnLCBlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB6b29tID0gTWF0aC5leHAoLU1hdGgubWluKE1hdGgubWF4KHdoZWVsRGVsdGEsIC0yMCksIDIwKSAvIDIwMCksXG4gICAgICAgICAgICBnYmIgPSBtYWlucGxvdC5kcmFnbGF5ZXIuc2VsZWN0KCcubnNld2RyYWcnKVxuICAgICAgICAgICAgICAgIC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksXG4gICAgICAgICAgICB4ZnJhYyA9IChlLmNsaWVudFggLSBnYmIubGVmdCkgLyBnYmIud2lkdGgsXG4gICAgICAgICAgICB5ZnJhYyA9IChnYmIuYm90dG9tIC0gZS5jbGllbnRZKSAvIGdiYi5oZWlnaHQsXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHpvb21XaGVlbE9uZUF4aXMoYXgsIGNlbnRlckZyYWN0aW9uLCB6b29tKSB7XG4gICAgICAgICAgICBpZihheC5maXhlZHJhbmdlKSByZXR1cm47XG5cbiAgICAgICAgICAgIHZhciBheFJhbmdlID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKSxcbiAgICAgICAgICAgICAgICB2MCA9IGF4UmFuZ2VbMF0gKyAoYXhSYW5nZVsxXSAtIGF4UmFuZ2VbMF0pICogY2VudGVyRnJhY3Rpb247XG4gICAgICAgICAgICBmdW5jdGlvbiBkb1pvb20odikgeyByZXR1cm4gYXgubDJyKHYwICsgKHYgLSB2MCkgKiB6b29tKTsgfVxuICAgICAgICAgICAgYXgucmFuZ2UgPSBheFJhbmdlLm1hcChkb1pvb20pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZWRpdFgpIHtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIG9ubHkgem9vbWluZyB0aGlzIGF4aXMgYmVjYXVzZSBvZiBjb25zdHJhaW50cyxcbiAgICAgICAgICAgIC8vIHpvb20gaXQgYWJvdXQgdGhlIGNlbnRlclxuICAgICAgICAgICAgaWYoIWV3KSB4ZnJhYyA9IDAuNTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB6b29tV2hlZWxPbmVBeGlzKHhheGVzW2ldLCB4ZnJhYywgem9vbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNjcm9sbFZpZXdCb3hbMl0gKj0gem9vbTtcbiAgICAgICAgICAgIHNjcm9sbFZpZXdCb3hbMF0gKz0gc2Nyb2xsVmlld0JveFsyXSAqIHhmcmFjICogKDEgLyB6b29tIC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoZWRpdFkpIHtcbiAgICAgICAgICAgIGlmKCFucykgeWZyYWMgPSAwLjU7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHlheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgem9vbVdoZWVsT25lQXhpcyh5YXhlc1tpXSwgeWZyYWMsIHpvb20pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzY3JvbGxWaWV3Qm94WzNdICo9IHpvb207XG4gICAgICAgICAgICBzY3JvbGxWaWV3Qm94WzFdICs9IHNjcm9sbFZpZXdCb3hbM10gKiAoMSAtIHlmcmFjKSAqICgxIC8gem9vbSAtIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmlld2JveCByZWRyYXcgYXQgZmlyc3RcbiAgICAgICAgdXBkYXRlU3VicGxvdHMoc2Nyb2xsVmlld0JveCk7XG4gICAgICAgIHRpY2tzQW5kQW5ub3RhdGlvbnMobnMsIGV3KTtcblxuICAgICAgICAvLyB0aGVuIHJlcGxvdCBhZnRlciBhIGRlbGF5IHRvIG1ha2Ugc3VyZVxuICAgICAgICAvLyBubyBtb3JlIHNjcm9sbGluZyBpcyBjb21pbmdcbiAgICAgICAgcmVkcmF3VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2Nyb2xsVmlld0JveCA9IFswLCAwLCBwdywgcGhdO1xuICAgICAgICAgICAgZHJhZ1RhaWwoKTtcbiAgICAgICAgfSwgUkVEUkFXREVMQVkpO1xuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGV2ZXJ5dGhpbmcgYnV0IHRoZSBjb3JuZXJzIGdldHMgd2hlZWwgem9vbVxuICAgIGlmKG5zLmxlbmd0aCAqIGV3Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICBhdHRhY2hXaGVlbEV2ZW50SGFuZGxlcihkcmFnZ2VyLCB6b29tV2hlZWwpO1xuICAgIH1cblxuICAgIC8vIHBsb3REcmFnOiBtb3ZlIHRoZSBwbG90IGluIHJlc3BvbnNlIHRvIGEgZHJhZ1xuICAgIGZ1bmN0aW9uIHBsb3REcmFnKGR4LCBkeSkge1xuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgaW4gcHJvZ3Jlc3MsIHRoZW4gZGlzYWJsZSBhbnkgYmVoYXZpb3I6XG4gICAgICAgIGlmKGdkLl90cmFuc2l0aW9uaW5nV2l0aER1cmF0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZih4QWN0aXZlID09PSAnZXcnIHx8IHlBY3RpdmUgPT09ICducycpIHtcbiAgICAgICAgICAgIGlmKHhBY3RpdmUpIGRyYWdBeExpc3QoeGF4ZXMsIGR4KTtcbiAgICAgICAgICAgIGlmKHlBY3RpdmUpIGRyYWdBeExpc3QoeWF4ZXMsIGR5KTtcbiAgICAgICAgICAgIHVwZGF0ZVN1YnBsb3RzKFt4QWN0aXZlID8gLWR4IDogMCwgeUFjdGl2ZSA/IC1keSA6IDAsIHB3LCBwaF0pO1xuICAgICAgICAgICAgdGlja3NBbmRBbm5vdGF0aW9ucyh5QWN0aXZlLCB4QWN0aXZlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGR6OiBzZXQgYSBuZXcgdmFsdWUgZm9yIG9uZSBlbmQgKDAgb3IgMSkgb2YgYW4gYXhpcyBhcnJheSBheEFycmF5LFxuICAgICAgICAvLyBhbmQgcmV0dXJuIGEgcGl4ZWwgc2hpZnQgZm9yIHRoYXQgZW5kIGZvciB0aGUgdmlld2JveFxuICAgICAgICAvLyBiYXNlZCBvbiBwaXhlbCBkcmFnIGRpc3RhbmNlIGRcbiAgICAgICAgLy8gVE9ETzogdGhpcyBtYWtlcyAoZ2VuZXJhbGx5IG5vbi1mYXRhbCkgZXJyb3JzIHdoZW4geW91IGdldFxuICAgICAgICAvLyBuZWFyIGZsb2F0aW5nIHBvaW50IGxpbWl0c1xuICAgICAgICBmdW5jdGlvbiBkeihheEFycmF5LCBlbmQsIGQpIHtcbiAgICAgICAgICAgIHZhciBvdGhlckVuZCA9IDEgLSBlbmQsXG4gICAgICAgICAgICAgICAgbW92ZWRBeCxcbiAgICAgICAgICAgICAgICBuZXdMaW5lYXJpemVkRW5kO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGF4QXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYXhpID0gYXhBcnJheVtpXTtcbiAgICAgICAgICAgICAgICBpZihheGkuZml4ZWRyYW5nZSkgY29udGludWU7XG4gICAgICAgICAgICAgICAgbW92ZWRBeCA9IGF4aTtcbiAgICAgICAgICAgICAgICBuZXdMaW5lYXJpemVkRW5kID0gYXhpLl9ybFtvdGhlckVuZF0gK1xuICAgICAgICAgICAgICAgICAgICAoYXhpLl9ybFtlbmRdIC0gYXhpLl9ybFtvdGhlckVuZF0pIC8gZFpvb20oZCAvIGF4aS5fbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RW5kID0gYXhpLmwycihuZXdMaW5lYXJpemVkRW5kKTtcblxuICAgICAgICAgICAgICAgIC8vIGlmIGwyciBjb21lcyBiYWNrIGZhbHNlIG9yIHVuZGVmaW5lZCwgaXQgbWVhbnMgd2UndmUgZHJhZ2dlZCBvZmZcbiAgICAgICAgICAgICAgICAvLyB0aGUgZW5kIG9mIHZhbGlkIHJhbmdlcyAtIHNvIHN0b3AuXG4gICAgICAgICAgICAgICAgaWYobmV3RW5kICE9PSBmYWxzZSAmJiBuZXdFbmQgIT09IHVuZGVmaW5lZCkgYXhpLnJhbmdlW2VuZF0gPSBuZXdFbmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbW92ZWRBeC5fbGVuZ3RoICogKG1vdmVkQXguX3JsW2VuZF0gLSBuZXdMaW5lYXJpemVkRW5kKSAvXG4gICAgICAgICAgICAgICAgKG1vdmVkQXguX3JsW2VuZF0gLSBtb3ZlZEF4Ll9ybFtvdGhlckVuZF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaXNTdWJwbG90Q29uc3RyYWluZWQgJiYgeEFjdGl2ZSAmJiB5QWN0aXZlKSB7XG4gICAgICAgICAgICAvLyBkcmFnZ2luZyBhIGNvcm5lciBvZiBhIGNvbnN0cmFpbmVkIHN1YnBsb3Q6XG4gICAgICAgICAgICAvLyByZXNwZWN0IHRoZSBmaXhlZCBjb3JuZXIsIGJ1dCBoYXJtb25pemUgZHggYW5kIGR5XG4gICAgICAgICAgICB2YXIgZHh5U2lnbiA9ICgoeEFjdGl2ZSA9PT0gJ3cnKSA9PT0gKHlBY3RpdmUgPT09ICduJykpID8gMSA6IC0xO1xuICAgICAgICAgICAgdmFyIGR4eUZyYWN0aW9uID0gKGR4IC8gcHcgKyBkeHlTaWduICogZHkgLyBwaCkgLyAyO1xuICAgICAgICAgICAgZHggPSBkeHlGcmFjdGlvbiAqIHB3O1xuICAgICAgICAgICAgZHkgPSBkeHlTaWduICogZHh5RnJhY3Rpb24gKiBwaDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHhBY3RpdmUgPT09ICd3JykgZHggPSBkeih4YXhlcywgMCwgZHgpO1xuICAgICAgICBlbHNlIGlmKHhBY3RpdmUgPT09ICdlJykgZHggPSBkeih4YXhlcywgMSwgLWR4KTtcbiAgICAgICAgZWxzZSBpZigheEFjdGl2ZSkgZHggPSAwO1xuXG4gICAgICAgIGlmKHlBY3RpdmUgPT09ICduJykgZHkgPSBkeih5YXhlcywgMSwgZHkpO1xuICAgICAgICBlbHNlIGlmKHlBY3RpdmUgPT09ICdzJykgZHkgPSBkeih5YXhlcywgMCwgLWR5KTtcbiAgICAgICAgZWxzZSBpZigheUFjdGl2ZSkgZHkgPSAwO1xuXG4gICAgICAgIHZhciB4MCA9ICh4QWN0aXZlID09PSAndycpID8gZHggOiAwO1xuICAgICAgICB2YXIgeTAgPSAoeUFjdGl2ZSA9PT0gJ24nKSA/IGR5IDogMDtcblxuICAgICAgICBpZihpc1N1YnBsb3RDb25zdHJhaW5lZCkge1xuICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICBpZigheEFjdGl2ZSAmJiB5QWN0aXZlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIC8vIGRyYWdnaW5nIG9uZSBlbmQgb2YgdGhlIHkgYXhpcyBvZiBhIGNvbnN0cmFpbmVkIHN1YnBsb3RcbiAgICAgICAgICAgICAgICAvLyBzY2FsZSB0aGUgb3RoZXIgYXhpcyB0aGUgc2FtZSBhYm91dCBpdHMgbWlkZGxlXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeGF4ZXNbaV0ucmFuZ2UgPSB4YXhlc1tpXS5fci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICBzY2FsZVpvb20oeGF4ZXNbaV0sIDEgLSBkeSAvIHBoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZHggPSBkeSAqIHB3IC8gcGg7XG4gICAgICAgICAgICAgICAgeDAgPSBkeCAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZigheUFjdGl2ZSAmJiB4QWN0aXZlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHlheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHlheGVzW2ldLnJhbmdlID0geWF4ZXNbaV0uX3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgc2NhbGVab29tKHlheGVzW2ldLCAxIC0gZHggLyBwdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGR5ID0gZHggKiBwaCAvIHB3O1xuICAgICAgICAgICAgICAgIHkwID0gZHkgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdXBkYXRlU3VicGxvdHMoW3gwLCB5MCwgcHcgLSBkeCwgcGggLSBkeV0pO1xuICAgICAgICB0aWNrc0FuZEFubm90YXRpb25zKHlBY3RpdmUsIHhBY3RpdmUpO1xuICAgIH1cblxuICAgIC8vIERyYXcgdGlja3MgYW5kIGFubm90YXRpb25zIChhbmQgb3RoZXIgY29tcG9uZW50cykgd2hlbiByYW5nZXMgY2hhbmdlLlxuICAgIC8vIEFsc28gcmVjb3JkcyB0aGUgcmFuZ2VzIHRoYXQgaGF2ZSBjaGFuZ2VkIGZvciB1c2UgYnkgdXBkYXRlIGF0IHRoZSBlbmQuXG4gICAgZnVuY3Rpb24gdGlja3NBbmRBbm5vdGF0aW9ucyhucywgZXcpIHtcbiAgICAgICAgdmFyIGFjdGl2ZUF4SWRzID0gW10sXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHB1c2hBY3RpdmVBeElkcyhheExpc3QpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKCFheExpc3RbaV0uZml4ZWRyYW5nZSkgYWN0aXZlQXhJZHMucHVzaChheExpc3RbaV0uX2lkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGVkaXRYKSB7XG4gICAgICAgICAgICBwdXNoQWN0aXZlQXhJZHMoeGF4ZXMpO1xuICAgICAgICAgICAgcHVzaEFjdGl2ZUF4SWRzKGxpbmtzLnhheGVzKTtcbiAgICAgICAgfVxuICAgICAgICBpZihlZGl0WSkge1xuICAgICAgICAgICAgcHVzaEFjdGl2ZUF4SWRzKHlheGVzKTtcbiAgICAgICAgICAgIHB1c2hBY3RpdmVBeElkcyhsaW5rcy55YXhlcyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cGRhdGVzID0ge307XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGFjdGl2ZUF4SWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYXhJZCA9IGFjdGl2ZUF4SWRzW2ldO1xuICAgICAgICAgICAgZG9UaWNrc1NpbmdsZShnZCwgYXhJZCwgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgYXggPSBnZXRGcm9tSWQoZ2QsIGF4SWQpO1xuICAgICAgICAgICAgdXBkYXRlc1theC5fbmFtZSArICcucmFuZ2VbMF0nXSA9IGF4LnJhbmdlWzBdO1xuICAgICAgICAgICAgdXBkYXRlc1theC5fbmFtZSArICcucmFuZ2VbMV0nXSA9IGF4LnJhbmdlWzFdO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVkcmF3T2JqcyhvYmpBcnJheSwgbWV0aG9kLCBzaG9ydENpcmN1aXQpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG9iakFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iamkgPSBvYmpBcnJheVtpXTtcblxuICAgICAgICAgICAgICAgIGlmKChldyAmJiBhY3RpdmVBeElkcy5pbmRleE9mKG9iamkueHJlZikgIT09IC0xKSB8fFxuICAgICAgICAgICAgICAgICAgICAobnMgJiYgYWN0aXZlQXhJZHMuaW5kZXhPZihvYmppLnlyZWYpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kKGdkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gb25jZSBpcyBlbm91Z2ggZm9yIGltYWdlcyAod2hpY2ggZG9lc24ndCB1c2UgdGhlIGBpYCBhcmcgYW55d2F5KVxuICAgICAgICAgICAgICAgICAgICBpZihzaG9ydENpcmN1aXQpIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhbm5vdGF0aW9ucyBhbmQgc2hhcGVzICdkcmF3JyBtZXRob2QgaXMgc2xvdyxcbiAgICAgICAgLy8gdXNlIHRoZSBmaW5lci1ncmFpbmVkICdkcmF3T25lJyBtZXRob2QgaW5zdGVhZFxuXG4gICAgICAgIHJlZHJhd09ianMoZ2QuX2Z1bGxMYXlvdXQuYW5ub3RhdGlvbnMgfHwgW10sIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhd09uZScpKTtcbiAgICAgICAgcmVkcmF3T2JqcyhnZC5fZnVsbExheW91dC5zaGFwZXMgfHwgW10sIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnc2hhcGVzJywgJ2RyYXdPbmUnKSk7XG4gICAgICAgIHJlZHJhd09ianMoZ2QuX2Z1bGxMYXlvdXQuaW1hZ2VzIHx8IFtdLCBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2ltYWdlcycsICdkcmF3JyksIHRydWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvdWJsZUNsaWNrKCkge1xuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbmluZ1dpdGhEdXJhdGlvbikgcmV0dXJuO1xuXG4gICAgICAgIHZhciBkb3VibGVDbGlja0NvbmZpZyA9IGdkLl9jb250ZXh0LmRvdWJsZUNsaWNrLFxuICAgICAgICAgICAgYXhMaXN0ID0gKHhBY3RpdmUgPyB4YXhlcyA6IFtdKS5jb25jYXQoeUFjdGl2ZSA/IHlheGVzIDogW10pLFxuICAgICAgICAgICAgYXR0cnMgPSB7fTtcblxuICAgICAgICB2YXIgYXgsIGksIHJhbmdlSW5pdGlhbDtcblxuICAgICAgICAvLyBGb3IgcmVzZXQrYXV0b3NpemUgbW9kZTpcbiAgICAgICAgLy8gSWYgKmFueSogb2YgdGhlIG1haW4gYXhlcyBpcyBub3QgYXQgaXRzIGluaXRpYWwgcmFuZ2VcbiAgICAgICAgLy8gKG9yIGF1dG9yYW5nZWQsIGlmIHdlIGhhdmUgbm8gaW5pdGlhbCByYW5nZSwgdG8gbWF0Y2ggdGhlIGxvZ2ljIGluXG4gICAgICAgIC8vIGRvdWJsZUNsaWNrQ29uZmlnID09PSAncmVzZXQnIGJlbG93KSwgd2UgcmVzZXQuXG4gICAgICAgIC8vIElmIHRoZXkgYXJlICphbGwqIGF0IHRoZWlyIGluaXRpYWwgcmFuZ2VzLCB0aGVuIHdlIGF1dG9zaXplLlxuICAgICAgICBpZihkb3VibGVDbGlja0NvbmZpZyA9PT0gJ3Jlc2V0K2F1dG9zaXplJykge1xuXG4gICAgICAgICAgICBkb3VibGVDbGlja0NvbmZpZyA9ICdhdXRvc2l6ZSc7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICAgICAgICAgIGlmKChheC5fcmFuZ2VJbml0aWFsICYmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlWzBdICE9PSBheC5fcmFuZ2VJbml0aWFsWzBdIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBheC5yYW5nZVsxXSAhPT0gYXguX3JhbmdlSW5pdGlhbFsxXVxuICAgICAgICAgICAgICAgICAgICApKSB8fFxuICAgICAgICAgICAgICAgICAgICAoIWF4Ll9yYW5nZUluaXRpYWwgJiYgIWF4LmF1dG9yYW5nZSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgZG91YmxlQ2xpY2tDb25maWcgPSAncmVzZXQnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihkb3VibGVDbGlja0NvbmZpZyA9PT0gJ2F1dG9zaXplJykge1xuICAgICAgICAgICAgLy8gZG9uJ3Qgc2V0IHRoZSBsaW5rZWQgYXhlcyBoZXJlLCBzbyByZWxheW91dCBtYXJrcyB0aGVtIGFzIHNocmlua2FibGVcbiAgICAgICAgICAgIC8vIGFuZCB3ZSBhdXRvc2l6ZSBqdXN0IHRvIHRoZSByZXF1ZXN0ZWQgYXhpcy9heGVzXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgICAgICAgICBpZighYXguZml4ZWRyYW5nZSkgYXR0cnNbYXguX25hbWUgKyAnLmF1dG9yYW5nZSddID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGRvdWJsZUNsaWNrQ29uZmlnID09PSAncmVzZXQnKSB7XG4gICAgICAgICAgICAvLyB3aGVuIHdlJ3JlIHJlc2V0dGluZywgcmVzZXQgYWxsIGxpbmtlZCBheGVzIHRvbywgc28gd2UgZ2V0IGJhY2tcbiAgICAgICAgICAgIC8vIHRvIHRoZSBmdWxseS1hdXRvLXdpdGgtY29uc3RyYWludHMgc2l0dWF0aW9uXG4gICAgICAgICAgICBpZih4QWN0aXZlIHx8IGlzU3VicGxvdENvbnN0cmFpbmVkKSBheExpc3QgPSBheExpc3QuY29uY2F0KGxpbmtzLnhheGVzKTtcbiAgICAgICAgICAgIGlmKHlBY3RpdmUgJiYgIWlzU3VicGxvdENvbnN0cmFpbmVkKSBheExpc3QgPSBheExpc3QuY29uY2F0KGxpbmtzLnlheGVzKTtcblxuICAgICAgICAgICAgaWYoaXNTdWJwbG90Q29uc3RyYWluZWQpIHtcbiAgICAgICAgICAgICAgICBpZigheEFjdGl2ZSkgYXhMaXN0ID0gYXhMaXN0LmNvbmNhdCh4YXhlcyk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZigheUFjdGl2ZSkgYXhMaXN0ID0gYXhMaXN0LmNvbmNhdCh5YXhlcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoIWF4Ll9yYW5nZUluaXRpYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgYXR0cnNbYXguX25hbWUgKyAnLmF1dG9yYW5nZSddID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlSW5pdGlhbCA9IGF4Ll9yYW5nZUluaXRpYWw7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJzW2F4Ll9uYW1lICsgJy5yYW5nZVswXSddID0gcmFuZ2VJbml0aWFsWzBdO1xuICAgICAgICAgICAgICAgICAgICBhdHRyc1theC5fbmFtZSArICcucmFuZ2VbMV0nXSA9IHJhbmdlSW5pdGlhbFsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnZC5lbWl0KCdwbG90bHlfZG91YmxlY2xpY2snLCBudWxsKTtcbiAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYXR0cnMpO1xuICAgIH1cblxuICAgIC8vIGRyYWdUYWlsIC0gZmluaXNoIGEgZHJhZyBldmVudCB3aXRoIGEgcmVkcmF3XG4gICAgZnVuY3Rpb24gZHJhZ1RhaWwoKSB7XG4gICAgICAgIC8vIHB1dCB0aGUgc3VicGxvdCB2aWV3Ym94ZXMgYmFjayB0byBkZWZhdWx0IChCZWNhdXNlIHdlJ3JlIGdvaW5nIHRvKVxuICAgICAgICAvLyBiZSByZXBvc2l0aW9uaW5nIHRoZSBkYXRhIGluIHRoZSByZWxheW91dC4gQnV0IERPTidUIGNhbGxcbiAgICAgICAgLy8gdGlja3NBbmRBbm5vdGF0aW9ucyBhZ2FpbiAtIGl0J3MgdW5uZWNlc3NhcnkgYW5kIHdvdWxkIG92ZXJ3cml0ZSBgdXBkYXRlc2BcbiAgICAgICAgdXBkYXRlU3VicGxvdHMoWzAsIDAsIHB3LCBwaF0pO1xuXG4gICAgICAgIC8vIHNpbmNlIHdlIG1heSBoYXZlIGJlZW4gcmVkcmF3aW5nIHNvbWUgdGhpbmdzIGR1cmluZyB0aGUgZHJhZywgd2UgbWF5IGhhdmVcbiAgICAgICAgLy8gYWNjdW11bGF0ZWQgTWF0aEpheCBwcm9taXNlcyAtIHdhaXQgZm9yIHRoZW0gYmVmb3JlIHdlIHJlbGF5b3V0LlxuICAgICAgICBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKCkgeyBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCB1cGRhdGVzKTsgfVxuICAgICAgICBdLCBnZCk7XG4gICAgfVxuXG4gICAgLy8geC95IHNjYWxlRmFjdG9yIHN0YXNoLFxuICAgIC8vIG1pbmltaXplcyBudW1iZXIgb2YgcGVyLXBvaW50IERPTSB1cGRhdGVzIGluIHVwZGF0ZVN1YnBsb3RzIGJlbG93XG4gICAgdmFyIHhTY2FsZUZhY3Rvck9sZCwgeVNjYWxlRmFjdG9yT2xkO1xuXG4gICAgLy8gdXBkYXRlU3VicGxvdHMgLSBmaW5kIGFsbCBwbG90IHZpZXdib3hlcyB0aGF0IHNob3VsZCBiZVxuICAgIC8vIGFmZmVjdGVkIGJ5IHRoaXMgZHJhZywgYW5kIHVwZGF0ZSB0aGVtLiBsb29rIGZvciBhbGwgcGxvdHNcbiAgICAvLyBzaGFyaW5nIGFuIGFmZmVjdGVkIGF4aXMgKGluY2x1ZGluZyB0aGUgb25lIGJlaW5nIGRyYWdnZWQpLFxuICAgIC8vIGluY2x1ZGVzIGFsc28gc2NhdHRlcmdsIGFuZCBzcGxvbSBsb2dpYy5cbiAgICBmdW5jdGlvbiB1cGRhdGVTdWJwbG90cyh2aWV3Qm94KSB7XG4gICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciBwbG90aW5mb3MgPSBmdWxsTGF5b3V0Ll9wbG90cztcbiAgICAgICAgdmFyIHN1YnBsb3RzID0gZnVsbExheW91dC5fc3VicGxvdHMuY2FydGVzaWFuO1xuICAgICAgICB2YXIgaSwgc3AsIHhhLCB5YTtcblxuICAgICAgICBpZihoYXNTcGxvbSkge1xuICAgICAgICAgICAgUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeS5zcGxvbS5kcmFnKGdkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhhc1NjYXR0ZXJHbCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzcCA9IHBsb3RpbmZvc1tzdWJwbG90c1tpXV07XG4gICAgICAgICAgICAgICAgeGEgPSBzcC54YXhpcztcbiAgICAgICAgICAgICAgICB5YSA9IHNwLnlheGlzO1xuXG4gICAgICAgICAgICAgICAgaWYoc3AuX3NjZW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4cm5nID0gTGliLnNpbXBsZU1hcCh4YS5yYW5nZSwgeGEucjJsKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHlybmcgPSBMaWIuc2ltcGxlTWFwKHlhLnJhbmdlLCB5YS5yMmwpO1xuICAgICAgICAgICAgICAgICAgICBzcC5fc2NlbmUudXBkYXRlKHtyYW5nZTogW3hybmdbMF0sIHlybmdbMF0sIHhybmdbMV0sIHlybmdbMV1dfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzU3Bsb20gfHwgaGFzU2NhdHRlckdsKSB7XG4gICAgICAgICAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuICAgICAgICAgICAgcmVkcmF3UmVnbFRyYWNlcyhnZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNTVkcpIHtcbiAgICAgICAgICAgIHZhciB4U2NhbGVGYWN0b3IgPSB2aWV3Qm94WzJdIC8geGEwLl9sZW5ndGg7XG4gICAgICAgICAgICB2YXIgeVNjYWxlRmFjdG9yID0gdmlld0JveFszXSAvIHlhMC5fbGVuZ3RoO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBzdWJwbG90cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNwID0gcGxvdGluZm9zW3N1YnBsb3RzW2ldXTtcbiAgICAgICAgICAgICAgICB4YSA9IHNwLnhheGlzO1xuICAgICAgICAgICAgICAgIHlhID0gc3AueWF4aXM7XG5cbiAgICAgICAgICAgICAgICB2YXIgZWRpdFgyID0gZWRpdFggJiYgIXhhLmZpeGVkcmFuZ2UgJiYgeGFIYXNoW3hhLl9pZF07XG4gICAgICAgICAgICAgICAgdmFyIGVkaXRZMiA9IGVkaXRZICYmICF5YS5maXhlZHJhbmdlICYmIHlhSGFzaFt5YS5faWRdO1xuXG4gICAgICAgICAgICAgICAgdmFyIHhTY2FsZUZhY3RvcjIsIHlTY2FsZUZhY3RvcjI7XG4gICAgICAgICAgICAgICAgdmFyIGNsaXBEeCwgY2xpcER5O1xuXG4gICAgICAgICAgICAgICAgaWYoZWRpdFgyKSB7XG4gICAgICAgICAgICAgICAgICAgIHhTY2FsZUZhY3RvcjIgPSB4U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeCA9IGV3ID8gdmlld0JveFswXSA6IGdldFNoaWZ0KHhhLCB4U2NhbGVGYWN0b3IyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB4U2NhbGVGYWN0b3IyID0gZ2V0TGlua2VkU2NhbGVGYWN0b3IoeGEsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpcER4ID0gc2NhbGVBbmRHZXRTaGlmdCh4YSwgeFNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoZWRpdFkyKSB7XG4gICAgICAgICAgICAgICAgICAgIHlTY2FsZUZhY3RvcjIgPSB5U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeSA9IG5zID8gdmlld0JveFsxXSA6IGdldFNoaWZ0KHlhLCB5U2NhbGVGYWN0b3IyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB5U2NhbGVGYWN0b3IyID0gZ2V0TGlua2VkU2NhbGVGYWN0b3IoeWEsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpcER5ID0gc2NhbGVBbmRHZXRTaGlmdCh5YSwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZG9uJ3Qgc2NhbGUgYXQgYWxsIGlmIG5laXRoZXIgYXhpcyBpcyBzY2FsYWJsZSBoZXJlXG4gICAgICAgICAgICAgICAgaWYoIXhTY2FsZUZhY3RvcjIgJiYgIXlTY2FsZUZhY3RvcjIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYnV0IGlmIG9ubHkgb25lIGlzLCByZXNldCB0aGUgb3RoZXIgYXhpcyBzY2FsaW5nXG4gICAgICAgICAgICAgICAgaWYoIXhTY2FsZUZhY3RvcjIpIHhTY2FsZUZhY3RvcjIgPSAxO1xuICAgICAgICAgICAgICAgIGlmKCF5U2NhbGVGYWN0b3IyKSB5U2NhbGVGYWN0b3IyID0gMTtcblxuICAgICAgICAgICAgICAgIHZhciBwbG90RHggPSB4YS5fb2Zmc2V0IC0gY2xpcER4IC8geFNjYWxlRmFjdG9yMjtcbiAgICAgICAgICAgICAgICB2YXIgcGxvdER5ID0geWEuX29mZnNldCAtIGNsaXBEeSAvIHlTY2FsZUZhY3RvcjI7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIGNvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGhlcmU6XG4gICAgICAgICAgICAgICAgLy8gc2V0VHJhbnNsYXRlIGFuZCBzZXRTY2FsZSBkbyBhIGxvdCBvZiBleHRyYSB3b3JrXG4gICAgICAgICAgICAgICAgLy8gd2hlbiB3b3JraW5nIGluZGVwZW5kZW50bHksIHNob3VsZCBwZXJoYXBzIGNvbWJpbmVcbiAgICAgICAgICAgICAgICAvLyB0aGVtIGludG8gYSBzaW5nbGUgcm91dGluZS5cbiAgICAgICAgICAgICAgICBzcC5jbGlwUmVjdFxuICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgY2xpcER4LCBjbGlwRHkpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIHhTY2FsZUZhY3RvcjIsIHlTY2FsZUZhY3RvcjIpO1xuXG4gICAgICAgICAgICAgICAgc3AucGxvdFxuICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgcGxvdER4LCBwbG90RHkpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEgLyB4U2NhbGVGYWN0b3IyLCAxIC8geVNjYWxlRmFjdG9yMik7XG5cbiAgICAgICAgICAgICAgICAvLyBhcHBseSBhbiBpbnZlcnNlIHNjYWxlIHRvIGluZGl2aWR1YWwgcG9pbnRzIHRvIGNvdW50ZXJhY3RcbiAgICAgICAgICAgICAgICAvLyB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlIGdyb3VwLlxuICAgICAgICAgICAgICAgIC8vIGFwcGx5IG9ubHkgd2hlbiBzY2FsZSBjaGFuZ2VzLCBhcyBhZGp1c3RpbmcgdGhlIHNjYWxlIG9mXG4gICAgICAgICAgICAgICAgLy8gYWxsIHRoZSBwb2ludHMgY2FuIGJlIGV4cGFuc2l2ZS5cbiAgICAgICAgICAgICAgICBpZih4U2NhbGVGYWN0b3IyICE9PSB4U2NhbGVGYWN0b3JPbGQgfHwgeVNjYWxlRmFjdG9yMiAhPT0geVNjYWxlRmFjdG9yT2xkKSB7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlKHNwLnpvb21TY2FsZVB0cywgeFNjYWxlRmFjdG9yMiwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlKHNwLnpvb21TY2FsZVR4dCwgeFNjYWxlRmFjdG9yMiwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnRzKHNwLmNsaXBPbkF4aXNGYWxzZVRyYWNlcywgc3ApO1xuXG4gICAgICAgICAgICAgICAgLy8gdXBkYXRlIHgveSBzY2FsZUZhY3RvciBzdGFzaFxuICAgICAgICAgICAgICAgIHhTY2FsZUZhY3Rvck9sZCA9IHhTY2FsZUZhY3RvcjI7XG4gICAgICAgICAgICAgICAgeVNjYWxlRmFjdG9yT2xkID0geVNjYWxlRmFjdG9yMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZpbmQgdGhlIGFwcHJvcHJpYXRlIHNjYWxpbmcgZm9yIHRoaXMgYXhpcywgaWYgaXQncyBsaW5rZWQgdG8gdGhlXG4gICAgLy8gZHJhZ2dlZCBheGVzIGJ5IGNvbnN0cmFpbnRzLiAwIGlzIHNwZWNpYWwsIGl0IG1lYW5zIHRoaXMgYXhpcyBzaG91bGRuJ3RcbiAgICAvLyBldmVyIGJlIHNjYWxlZCAod2lsbCBiZSBjb252ZXJ0ZWQgdG8gMSBpZiB0aGUgb3RoZXIgYXhpcyBpcyBzY2FsZWQpXG4gICAgZnVuY3Rpb24gZ2V0TGlua2VkU2NhbGVGYWN0b3IoYXgsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKSB7XG4gICAgICAgIGlmKGF4LmZpeGVkcmFuZ2UpIHJldHVybiAwO1xuXG4gICAgICAgIGlmKGVkaXRYICYmIGxpbmtzLnhhSGFzaFtheC5faWRdKSB7XG4gICAgICAgICAgICByZXR1cm4geFNjYWxlRmFjdG9yO1xuICAgICAgICB9XG4gICAgICAgIGlmKGVkaXRZICYmIChpc1N1YnBsb3RDb25zdHJhaW5lZCA/IGxpbmtzLnhhSGFzaCA6IGxpbmtzLnlhSGFzaClbYXguX2lkXSkge1xuICAgICAgICAgICAgcmV0dXJuIHlTY2FsZUZhY3RvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzY2FsZUFuZEdldFNoaWZ0KGF4LCBzY2FsZUZhY3Rvcikge1xuICAgICAgICBpZihzY2FsZUZhY3Rvcikge1xuICAgICAgICAgICAgYXgucmFuZ2UgPSBheC5fci5zbGljZSgpO1xuICAgICAgICAgICAgc2NhbGVab29tKGF4LCBzY2FsZUZhY3Rvcik7XG4gICAgICAgICAgICByZXR1cm4gZ2V0U2hpZnQoYXgsIHNjYWxlRmFjdG9yKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTaGlmdChheCwgc2NhbGVGYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGF4Ll9sZW5ndGggKiAoMSAtIHNjYWxlRmFjdG9yKSAqIEZST01fVExbYXguY29uc3RyYWludG93YXJkIHx8ICdtaWRkbGUnXTtcbiAgICB9XG5cbiAgICByZXR1cm4gZHJhZ2dlcjtcbn1cblxuZnVuY3Rpb24gbWFrZURyYWdnZXIocGxvdGluZm8sIG5vZGVOYW1lLCBkcmFnQ2xhc3MsIGN1cnNvcikge1xuICAgIHZhciBkcmFnZ2VyMyA9IExpYi5lbnN1cmVTaW5nbGUocGxvdGluZm8uZHJhZ2xheWVyLCBub2RlTmFtZSwgZHJhZ0NsYXNzLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2xhc3NlZCgnZHJhZycsIHRydWUpXG4gICAgICAgICAgICAuc3R5bGUoe2ZpbGw6ICd0cmFuc3BhcmVudCcsICdzdHJva2Utd2lkdGgnOiAwfSlcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLXN1YnBsb3QnLCBwbG90aW5mby5pZCk7XG4gICAgfSk7XG5cbiAgICBkcmFnZ2VyMy5jYWxsKHNldEN1cnNvciwgY3Vyc29yKTtcblxuICAgIHJldHVybiBkcmFnZ2VyMy5ub2RlKCk7XG59XG5cbmZ1bmN0aW9uIG1ha2VSZWN0RHJhZ2dlcihwbG90aW5mbywgZHJhZ0NsYXNzLCBjdXJzb3IsIHgsIHksIHcsIGgpIHtcbiAgICB2YXIgZHJhZ2dlciA9IG1ha2VEcmFnZ2VyKHBsb3RpbmZvLCAncmVjdCcsIGRyYWdDbGFzcywgY3Vyc29yKTtcbiAgICBkMy5zZWxlY3QoZHJhZ2dlcikuY2FsbChEcmF3aW5nLnNldFJlY3QsIHgsIHksIHcsIGgpO1xuICAgIHJldHVybiBkcmFnZ2VyO1xufVxuXG5mdW5jdGlvbiBpc0RpcmVjdGlvbkFjdGl2ZShheExpc3QsIGFjdGl2ZVZhbCkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoIWF4TGlzdFtpXS5maXhlZHJhbmdlKSByZXR1cm4gYWN0aXZlVmFsO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG59XG5cbmZ1bmN0aW9uIGdldEVuZFRleHQoYXgsIGVuZCkge1xuICAgIHZhciBpbml0aWFsVmFsID0gYXgucmFuZ2VbZW5kXSxcbiAgICAgICAgZGlmZiA9IE1hdGguYWJzKGluaXRpYWxWYWwgLSBheC5yYW5nZVsxIC0gZW5kXSksXG4gICAgICAgIGRpZztcblxuICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkIGJhc2ljYWxseSBiZSBheC5yMmQgYnV0IHdlJ3JlIGRvaW5nIGV4dHJhXG4gICAgLy8gcm91bmRpbmcgaGVyZS4uLiBjYW4gd2UgY2xlYW4gdXAgYXQgYWxsP1xuICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICByZXR1cm4gaW5pdGlhbFZhbDtcbiAgICB9XG4gICAgZWxzZSBpZihheC50eXBlID09PSAnbG9nJykge1xuICAgICAgICBkaWcgPSBNYXRoLmNlaWwoTWF0aC5tYXgoMCwgLU1hdGgubG9nKGRpZmYpIC8gTWF0aC5MTjEwKSkgKyAzO1xuICAgICAgICByZXR1cm4gZDMuZm9ybWF0KCcuJyArIGRpZyArICdnJykoTWF0aC5wb3coMTAsIGluaXRpYWxWYWwpKTtcbiAgICB9XG4gICAgZWxzZSB7IC8vIGxpbmVhciBudW1lcmljIChvciBjYXRlZ29yeS4uLiBidXQganVzdCBzaG93IG51bWJlcnMgaGVyZSlcbiAgICAgICAgZGlnID0gTWF0aC5mbG9vcihNYXRoLmxvZyhNYXRoLmFicyhpbml0aWFsVmFsKSkgLyBNYXRoLkxOMTApIC1cbiAgICAgICAgICAgIE1hdGguZmxvb3IoTWF0aC5sb2coZGlmZikgLyBNYXRoLkxOMTApICsgNDtcbiAgICAgICAgcmV0dXJuIGQzLmZvcm1hdCgnLicgKyBTdHJpbmcoZGlnKSArICdnJykoaW5pdGlhbFZhbCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB6b29tQXhSYW5nZXMoYXhMaXN0LCByMEZyYWN0aW9uLCByMUZyYWN0aW9uLCB1cGRhdGVzLCBsaW5rZWRBeGVzKSB7XG4gICAgdmFyIGksXG4gICAgICAgIGF4aSxcbiAgICAgICAgYXhSYW5nZUxpbmVhcjAsXG4gICAgICAgIGF4UmFuZ2VMaW5lYXJTcGFuO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4aSA9IGF4TGlzdFtpXTtcbiAgICAgICAgaWYoYXhpLmZpeGVkcmFuZ2UpIGNvbnRpbnVlO1xuXG4gICAgICAgIGF4UmFuZ2VMaW5lYXIwID0gYXhpLl9ybFswXTtcbiAgICAgICAgYXhSYW5nZUxpbmVhclNwYW4gPSBheGkuX3JsWzFdIC0gYXhSYW5nZUxpbmVhcjA7XG4gICAgICAgIGF4aS5yYW5nZSA9IFtcbiAgICAgICAgICAgIGF4aS5sMnIoYXhSYW5nZUxpbmVhcjAgKyBheFJhbmdlTGluZWFyU3BhbiAqIHIwRnJhY3Rpb24pLFxuICAgICAgICAgICAgYXhpLmwycihheFJhbmdlTGluZWFyMCArIGF4UmFuZ2VMaW5lYXJTcGFuICogcjFGcmFjdGlvbilcbiAgICAgICAgXTtcblxuICAgICAgICB1cGRhdGVzW2F4aS5fbmFtZSArICcucmFuZ2VbMF0nXSA9IGF4aS5yYW5nZVswXTtcbiAgICAgICAgdXBkYXRlc1theGkuX25hbWUgKyAnLnJhbmdlWzFdJ10gPSBheGkucmFuZ2VbMV07XG4gICAgfVxuXG4gICAgLy8gem9vbSBsaW5rZWQgYXhlcyBhYm91dCB0aGVpciBjZW50ZXJzXG4gICAgaWYobGlua2VkQXhlcyAmJiBsaW5rZWRBeGVzLmxlbmd0aCkge1xuICAgICAgICB2YXIgbGlua2VkUjBGcmFjdGlvbiA9IChyMEZyYWN0aW9uICsgKDEgLSByMUZyYWN0aW9uKSkgLyAyO1xuXG4gICAgICAgIHpvb21BeFJhbmdlcyhsaW5rZWRBeGVzLCBsaW5rZWRSMEZyYWN0aW9uLCAxIC0gbGlua2VkUjBGcmFjdGlvbiwgdXBkYXRlcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFnQXhMaXN0KGF4TGlzdCwgcGl4KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXhpID0gYXhMaXN0W2ldO1xuICAgICAgICBpZighYXhpLmZpeGVkcmFuZ2UpIHtcbiAgICAgICAgICAgIGF4aS5yYW5nZSA9IFtcbiAgICAgICAgICAgICAgICBheGkubDJyKGF4aS5fcmxbMF0gLSBwaXggLyBheGkuX20pLFxuICAgICAgICAgICAgICAgIGF4aS5sMnIoYXhpLl9ybFsxXSAtIHBpeCAvIGF4aS5fbSlcbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8vIGNvbW1vbiB0cmFuc2Zvcm0gZm9yIGRyYWdnaW5nIG9uZSBlbmQgb2YgYW4gYXhpc1xuLy8gZD4wIGlzIGNvbXByZXNzaW5nIHNjYWxlIChjdXJzb3IgaXMgb3ZlciB0aGUgcGxvdCxcbi8vICB0aGUgYXhpcyBlbmQgc2hvdWxkIG1vdmUgd2l0aCB0aGUgY3Vyc29yKVxuLy8gZDwwIGlzIGV4cGFuZGluZyAoY3Vyc29yIGlzIG9mZiB0aGUgcGxvdCwgYXhpcyBlbmQgbW92ZXNcbi8vICBub25saW5lYXJseSBzbyB5b3UgY2FuIGV4cGFuZCBmYXIpXG5mdW5jdGlvbiBkWm9vbShkKSB7XG4gICAgcmV0dXJuIDEgLSAoKGQgPj0gMCkgPyBNYXRoLm1pbihkLCAwLjkpIDpcbiAgICAgICAgMSAvICgxIC8gTWF0aC5tYXgoZCwgLTAuMykgKyAzLjIyMikpO1xufVxuXG5mdW5jdGlvbiBnZXREcmFnQ3Vyc29yKG5zZXcsIGRyYWdtb2RlLCBpc01haW5EcmFnKSB7XG4gICAgaWYoIW5zZXcpIHJldHVybiAncG9pbnRlcic7XG4gICAgaWYobnNldyA9PT0gJ25zZXcnKSB7XG4gICAgICAgIC8vIGluIHRoaXMgY2FzZSBoZXJlLCBjbGVhciBjdXJzb3IgYW5kXG4gICAgICAgIC8vIHVzZSB0aGUgY3Vyc29yIHN0eWxlIHNldCBvbiA8ZyAuZHJhZ2xheWVyPlxuICAgICAgICBpZihpc01haW5EcmFnKSByZXR1cm4gJyc7XG4gICAgICAgIGlmKGRyYWdtb2RlID09PSAncGFuJykgcmV0dXJuICdtb3ZlJztcbiAgICAgICAgcmV0dXJuICdjcm9zc2hhaXInO1xuICAgIH1cbiAgICByZXR1cm4gbnNldy50b0xvd2VyQ2FzZSgpICsgJy1yZXNpemUnO1xufVxuXG5mdW5jdGlvbiBtYWtlWm9vbWJveCh6b29tbGF5ZXIsIGx1bSwgeHMsIHlzLCBwYXRoMCkge1xuICAgIHJldHVybiB6b29tbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3pvb21ib3gnKVxuICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgJ2ZpbGwnOiBsdW0gPiAwLjIgPyAncmdiYSgwLDAsMCwwKScgOiAncmdiYSgyNTUsMjU1LDI1NSwwKScsXG4gICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMFxuICAgICAgICB9KVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgeHMgKyAnLCAnICsgeXMgKyAnKScpXG4gICAgICAgIC5hdHRyKCdkJywgcGF0aDAgKyAnWicpO1xufVxuXG5mdW5jdGlvbiBtYWtlQ29ybmVycyh6b29tbGF5ZXIsIHhzLCB5cykge1xuICAgIHJldHVybiB6b29tbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3pvb21ib3gtY29ybmVycycpXG4gICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICBmaWxsOiBDb2xvci5iYWNrZ3JvdW5kLFxuICAgICAgICAgICAgc3Ryb2tlOiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiAxLFxuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICB9KVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgeHMgKyAnLCAnICsgeXMgKyAnKScpXG4gICAgICAgIC5hdHRyKCdkJywgJ00wLDBaJyk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVpvb21ib3goemIsIGNvcm5lcnMsIGJveCwgcGF0aDAsIGRpbW1lZCwgbHVtKSB7XG4gICAgemIuYXR0cignZCcsXG4gICAgICAgIHBhdGgwICsgJ00nICsgKGJveC5sKSArICcsJyArIChib3gudCkgKyAndicgKyAoYm94LmgpICtcbiAgICAgICAgJ2gnICsgKGJveC53KSArICd2LScgKyAoYm94LmgpICsgJ2gtJyArIChib3gudykgKyAnWicpO1xuICAgIHRyYW5zaXRpb25ab29tYm94KHpiLCBjb3JuZXJzLCBkaW1tZWQsIGx1bSk7XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb25ab29tYm94KHpiLCBjb3JuZXJzLCBkaW1tZWQsIGx1bSkge1xuICAgIGlmKCFkaW1tZWQpIHtcbiAgICAgICAgemIudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBsdW0gPiAwLjIgPyAncmdiYSgwLDAsMCwwLjQpJyA6XG4gICAgICAgICAgICAgICAgJ3JnYmEoMjU1LDI1NSwyNTUsMC4zKScpXG4gICAgICAgICAgICAuZHVyYXRpb24oMjAwKTtcbiAgICAgICAgY29ybmVycy50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgICAgICAuZHVyYXRpb24oMjAwKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZVpvb21ib3goZ2QpIHtcbiAgICBkMy5zZWxlY3QoZ2QpXG4gICAgICAgIC5zZWxlY3RBbGwoJy56b29tYm94LC5qcy16b29tYm94LWJhY2tkcm9wLC5qcy16b29tYm94LW1lbnUsLnpvb21ib3gtY29ybmVycycpXG4gICAgICAgIC5yZW1vdmUoKTtcbn1cblxuZnVuY3Rpb24gc2hvd0RvdWJsZUNsaWNrTm90aWZpZXIoZ2QpIHtcbiAgICBpZihTSE9XWk9PTU9VVFRJUCAmJiBnZC5kYXRhICYmIGdkLl9jb250ZXh0LnNob3dUaXBzKSB7XG4gICAgICAgIExpYi5ub3RpZmllcihMaWIuXyhnZCwgJ0RvdWJsZS1jbGljayB0byB6b29tIGJhY2sgb3V0JyksICdsb25nJyk7XG4gICAgICAgIFNIT1daT09NT1VUVElQID0gZmFsc2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc1NlbGVjdE9yTGFzc28oZHJhZ21vZGUpIHtcbiAgICByZXR1cm4gZHJhZ21vZGUgPT09ICdsYXNzbycgfHwgZHJhZ21vZGUgPT09ICdzZWxlY3QnO1xufVxuXG5mdW5jdGlvbiB4Q29ybmVycyhib3gsIHkwKSB7XG4gICAgcmV0dXJuICdNJyArXG4gICAgICAgIChib3gubCAtIDAuNSkgKyAnLCcgKyAoeTAgLSBNSU5aT09NIC0gMC41KSArXG4gICAgICAgICdoLTN2JyArICgyICogTUlOWk9PTSArIDEpICsgJ2gzWk0nICtcbiAgICAgICAgKGJveC5yICsgMC41KSArICcsJyArICh5MCAtIE1JTlpPT00gLSAwLjUpICtcbiAgICAgICAgJ2gzdicgKyAoMiAqIE1JTlpPT00gKyAxKSArICdoLTNaJztcbn1cblxuZnVuY3Rpb24geUNvcm5lcnMoYm94LCB4MCkge1xuICAgIHJldHVybiAnTScgK1xuICAgICAgICAoeDAgLSBNSU5aT09NIC0gMC41KSArICcsJyArIChib3gudCAtIDAuNSkgK1xuICAgICAgICAndi0zaCcgKyAoMiAqIE1JTlpPT00gKyAxKSArICd2M1pNJyArXG4gICAgICAgICh4MCAtIE1JTlpPT00gLSAwLjUpICsgJywnICsgKGJveC5iICsgMC41KSArXG4gICAgICAgICd2M2gnICsgKDIgKiBNSU5aT09NICsgMSkgKyAndi0zWic7XG59XG5cbmZ1bmN0aW9uIHh5Q29ybmVycyhib3gpIHtcbiAgICB2YXIgY2xlbiA9IE1hdGguZmxvb3IoTWF0aC5taW4oYm94LmIgLSBib3gudCwgYm94LnIgLSBib3gubCwgTUlOWk9PTSkgLyAyKTtcbiAgICByZXR1cm4gJ00nICtcbiAgICAgICAgKGJveC5sIC0gMy41KSArICcsJyArIChib3gudCAtIDAuNSArIGNsZW4pICsgJ2gzdicgKyAoLWNsZW4pICtcbiAgICAgICAgICAgICdoJyArIGNsZW4gKyAndi0zaC0nICsgKGNsZW4gKyAzKSArICdaTScgK1xuICAgICAgICAoYm94LnIgKyAzLjUpICsgJywnICsgKGJveC50IC0gMC41ICsgY2xlbikgKyAnaC0zdicgKyAoLWNsZW4pICtcbiAgICAgICAgICAgICdoJyArICgtY2xlbikgKyAndi0zaCcgKyAoY2xlbiArIDMpICsgJ1pNJyArXG4gICAgICAgIChib3guciArIDMuNSkgKyAnLCcgKyAoYm94LmIgKyAwLjUgLSBjbGVuKSArICdoLTN2JyArIGNsZW4gK1xuICAgICAgICAgICAgJ2gnICsgKC1jbGVuKSArICd2M2gnICsgKGNsZW4gKyAzKSArICdaTScgK1xuICAgICAgICAoYm94LmwgLSAzLjUpICsgJywnICsgKGJveC5iICsgMC41IC0gY2xlbikgKyAnaDN2JyArIGNsZW4gK1xuICAgICAgICAgICAgJ2gnICsgY2xlbiArICd2M2gtJyArIChjbGVuICsgMykgKyAnWic7XG59XG5cbmZ1bmN0aW9uIGNhbGNMaW5rcyhnZCwgeGFIYXNoLCB5YUhhc2gpIHtcbiAgICB2YXIgY29uc3RyYWludEdyb3VwcyA9IGdkLl9mdWxsTGF5b3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcztcbiAgICB2YXIgaXNTdWJwbG90Q29uc3RyYWluZWQgPSBmYWxzZTtcbiAgICB2YXIgeExpbmtzID0ge307XG4gICAgdmFyIHlMaW5rcyA9IHt9O1xuICAgIHZhciB4SUQsIHlJRCwgeExpbmtJRCwgeUxpbmtJRDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBncm91cCA9IGNvbnN0cmFpbnRHcm91cHNbaV07XG4gICAgICAgIC8vIGNoZWNrIGlmIGFueSBvZiB0aGUgeCBheGVzIHdlJ3JlIGRyYWdnaW5nIGlzIGluIHRoaXMgY29uc3RyYWludCBncm91cFxuICAgICAgICBmb3IoeElEIGluIHhhSGFzaCkge1xuICAgICAgICAgICAgaWYoZ3JvdXBbeElEXSkge1xuICAgICAgICAgICAgICAgIC8vIHB1dCB0aGUgcmVzdCBvZiB0aGVzZSBheGVzIGludG8geExpbmtzLCBpZiB3ZSdyZSBub3QgYWxyZWFkeVxuICAgICAgICAgICAgICAgIC8vIGRyYWdnaW5nIHRoZW0sIHNvIHdlIGtub3cgdG8gc2NhbGUgdGhlc2UgYXhlcyBhdXRvbWF0aWNhbGx5IHRvb1xuICAgICAgICAgICAgICAgIC8vIHRvIG1hdGNoIHRoZSBjaGFuZ2VzIGluIHRoZSBkcmFnZ2VkIHggYXhlc1xuICAgICAgICAgICAgICAgIGZvcih4TGlua0lEIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCEoeExpbmtJRC5jaGFyQXQoMCkgPT09ICd4JyA/IHhhSGFzaCA6IHlhSGFzaClbeExpbmtJRF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHhMaW5rc1t4TGlua0lEXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgeCBhbmQgeSBheGVzIG9mIFRISVMgZHJhZyBhcmUgbGlua2VkXG4gICAgICAgICAgICAgICAgZm9yKHlJRCBpbiB5YUhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZ3JvdXBbeUlEXSkgaXNTdWJwbG90Q29uc3RyYWluZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBjaGVjayBpZiBhbnkgb2YgdGhlIHkgYXhlcyB3ZSdyZSBkcmFnZ2luZyBpcyBpbiB0aGlzIGNvbnN0cmFpbnQgZ3JvdXBcbiAgICAgICAgLy8gb25seSBsb29rIGZvciBvdXRzaWRlIGxpbmtzLCBhcyB3ZSd2ZSBhbHJlYWR5IGNoZWNrZWQgZm9yIGxpbmtzIHdpdGhpbiB0aGUgZHJhZ2dlclxuICAgICAgICBmb3IoeUlEIGluIHlhSGFzaCkge1xuICAgICAgICAgICAgaWYoZ3JvdXBbeUlEXSkge1xuICAgICAgICAgICAgICAgIGZvcih5TGlua0lEIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCEoeUxpbmtJRC5jaGFyQXQoMCkgPT09ICd4JyA/IHhhSGFzaCA6IHlhSGFzaClbeUxpbmtJRF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHlMaW5rc1t5TGlua0lEXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihpc1N1YnBsb3RDb25zdHJhaW5lZCkge1xuICAgICAgICAvLyBtZXJnZSB4TGlua3MgYW5kIHlMaW5rcyBpZiB0aGUgc3VicGxvdCBpcyBjb25zdHJhaW5lZCxcbiAgICAgICAgLy8gc2luY2Ugd2UnbGwgYWx3YXlzIGFwcGx5IGJvdGggYW55d2F5IGFuZCB0aGUgdHdvIHdpbGwgY29udGFpblxuICAgICAgICAvLyBkdXBsaWNhdGVzXG4gICAgICAgIExpYi5leHRlbmRGbGF0KHhMaW5rcywgeUxpbmtzKTtcbiAgICAgICAgeUxpbmtzID0ge307XG4gICAgfVxuXG4gICAgdmFyIHhhSGFzaExpbmtlZCA9IHt9O1xuICAgIHZhciB4YXhlc0xpbmtlZCA9IFtdO1xuICAgIGZvcih4TGlua0lEIGluIHhMaW5rcykge1xuICAgICAgICB2YXIgeGEgPSBnZXRGcm9tSWQoZ2QsIHhMaW5rSUQpO1xuICAgICAgICB4YXhlc0xpbmtlZC5wdXNoKHhhKTtcbiAgICAgICAgeGFIYXNoTGlua2VkW3hhLl9pZF0gPSB4YTtcbiAgICB9XG5cbiAgICB2YXIgeWFIYXNoTGlua2VkID0ge307XG4gICAgdmFyIHlheGVzTGlua2VkID0gW107XG4gICAgZm9yKHlMaW5rSUQgaW4geUxpbmtzKSB7XG4gICAgICAgIHZhciB5YSA9IGdldEZyb21JZChnZCwgeUxpbmtJRCk7XG4gICAgICAgIHlheGVzTGlua2VkLnB1c2goeWEpO1xuICAgICAgICB5YUhhc2hMaW5rZWRbeWEuX2lkXSA9IHlhO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHhhSGFzaDogeGFIYXNoTGlua2VkLFxuICAgICAgICB5YUhhc2g6IHlhSGFzaExpbmtlZCxcbiAgICAgICAgeGF4ZXM6IHhheGVzTGlua2VkLFxuICAgICAgICB5YXhlczogeWF4ZXNMaW5rZWQsXG4gICAgICAgIGlzU3VicGxvdENvbnN0cmFpbmVkOiBpc1N1YnBsb3RDb25zdHJhaW5lZFxuICAgIH07XG59XG5cbi8vIHN0aWxsIHNlZW1zIHRvIGJlIHNvbWUgY29uZnVzaW9uIGFib3V0IG9ud2hlZWwgdnMgb25tb3VzZXdoZWVsLi4uXG5mdW5jdGlvbiBhdHRhY2hXaGVlbEV2ZW50SGFuZGxlcihlbGVtZW50LCBoYW5kbGVyKSB7XG4gICAgaWYoIXN1cHBvcnRzUGFzc2l2ZSkge1xuICAgICAgICBpZihlbGVtZW50Lm9ud2hlZWwgIT09IHVuZGVmaW5lZCkgZWxlbWVudC5vbndoZWVsID0gaGFuZGxlcjtcbiAgICAgICAgZWxzZSBpZihlbGVtZW50Lm9ubW91c2V3aGVlbCAhPT0gdW5kZWZpbmVkKSBlbGVtZW50Lm9ubW91c2V3aGVlbCA9IGhhbmRsZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgd2hlZWxFdmVudE5hbWUgPSBlbGVtZW50Lm9ud2hlZWwgIT09IHVuZGVmaW5lZCA/ICd3aGVlbCcgOiAnbW91c2V3aGVlbCc7XG5cbiAgICAgICAgaWYoZWxlbWVudC5fb253aGVlbCkge1xuICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHdoZWVsRXZlbnROYW1lLCBlbGVtZW50Ll9vbndoZWVsKTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50Ll9vbndoZWVsID0gaGFuZGxlcjtcblxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIod2hlZWxFdmVudE5hbWUsIGhhbmRsZXIsIHtwYXNzaXZlOiBmYWxzZX0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaGFzaFZhbHVlcyhoYXNoKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvcih2YXIgayBpbiBoYXNoKSBvdXQucHVzaChoYXNoW2tdKTtcbiAgICByZXR1cm4gb3V0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtYWtlRHJhZ0JveDogbWFrZURyYWdCb3gsXG5cbiAgICBtYWtlRHJhZ2dlcjogbWFrZURyYWdnZXIsXG4gICAgbWFrZVJlY3REcmFnZ2VyOiBtYWtlUmVjdERyYWdnZXIsXG4gICAgbWFrZVpvb21ib3g6IG1ha2Vab29tYm94LFxuICAgIG1ha2VDb3JuZXJzOiBtYWtlQ29ybmVycyxcblxuICAgIHVwZGF0ZVpvb21ib3g6IHVwZGF0ZVpvb21ib3gsXG4gICAgeHlDb3JuZXJzOiB4eUNvcm5lcnMsXG4gICAgdHJhbnNpdGlvblpvb21ib3g6IHRyYW5zaXRpb25ab29tYm94LFxuICAgIHJlbW92ZVpvb21ib3g6IHJlbW92ZVpvb21ib3gsXG4gICAgc2hvd0RvdWJsZUNsaWNrTm90aWZpZXI6IHNob3dEb3VibGVDbGlja05vdGlmaWVyLFxuXG4gICAgYXR0YWNoV2hlZWxFdmVudEhhbmRsZXI6IGF0dGFjaFdoZWVsRXZlbnRIYW5kbGVyXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBkcmFnRWxlbWVudCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnQnKTtcbnZhciBzZXRDdXJzb3IgPSByZXF1aXJlKCcuLi8uLi9saWIvc2V0Y3Vyc29yJyk7XG5cbnZhciBtYWtlRHJhZ0JveCA9IHJlcXVpcmUoJy4vZHJhZ2JveCcpLm1ha2VEcmFnQm94O1xudmFyIERSQUdHRVJTSVpFID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKS5EUkFHR0VSU0laRTtcblxuZXhwb3J0cy5pbml0SW50ZXJhY3Rpb25zID0gZnVuY3Rpb24gaW5pdEludGVyYWN0aW9ucyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZihnZC5fY29udGV4dC5zdGF0aWNQbG90KSB7XG4gICAgICAgIC8vIHRoaXMgc3dlZXBzIHVwIG1vcmUgdGhhbiBqdXN0IGNhcnRlc2lhbiBkcmFnIGVsZW1lbnRzLi4uXG4gICAgICAgIGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCcuZHJhZycpLnJlbW92ZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJykgJiYgIWZ1bGxMYXlvdXQuX2hhcygnc3Bsb20nKSkgcmV0dXJuO1xuXG4gICAgdmFyIHN1YnBsb3RzID0gT2JqZWN0LmtleXMoZnVsbExheW91dC5fcGxvdHMgfHwge30pLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAvLyBzb3J0IG92ZXJsYXlzIGxhc3QsIHRoZW4gYnkgeCBheGlzIG51bWJlciwgdGhlbiB5IGF4aXMgbnVtYmVyXG4gICAgICAgIGlmKChmdWxsTGF5b3V0Ll9wbG90c1thXS5tYWlucGxvdCAmJiB0cnVlKSA9PT1cbiAgICAgICAgICAgIChmdWxsTGF5b3V0Ll9wbG90c1tiXS5tYWlucGxvdCAmJiB0cnVlKSkge1xuICAgICAgICAgICAgdmFyIGFQYXJ0cyA9IGEuc3BsaXQoJ3knKSxcbiAgICAgICAgICAgICAgICBiUGFydHMgPSBiLnNwbGl0KCd5Jyk7XG4gICAgICAgICAgICByZXR1cm4gKGFQYXJ0c1swXSA9PT0gYlBhcnRzWzBdKSA/XG4gICAgICAgICAgICAgICAgKE51bWJlcihhUGFydHNbMV0gfHwgMSkgLSBOdW1iZXIoYlBhcnRzWzFdIHx8IDEpKSA6XG4gICAgICAgICAgICAgICAgKE51bWJlcihhUGFydHNbMF0gfHwgMSkgLSBOdW1iZXIoYlBhcnRzWzBdIHx8IDEpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVsbExheW91dC5fcGxvdHNbYV0ubWFpbnBsb3QgPyAxIDogLTE7XG4gICAgfSk7XG5cbiAgICBzdWJwbG90cy5mb3JFYWNoKGZ1bmN0aW9uKHN1YnBsb3QpIHtcbiAgICAgICAgdmFyIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbc3VicGxvdF07XG4gICAgICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgICAgICAvLyBtYWluIGFuZCBjb3JuZXIgZHJhZ2dlcnMgbmVlZCBub3QgYmUgcmVwZWF0ZWQgZm9yXG4gICAgICAgIC8vIG92ZXJsYWlkIHN1YnBsb3RzIC0gdGhlc2UgZHJhZ2dlcnMgZHJhZyB0aGVtIGFsbFxuICAgICAgICBpZighcGxvdGluZm8ubWFpbnBsb3QpIHtcbiAgICAgICAgICAgIC8vIG1haW4gZHJhZ2dlciBnb2VzIG92ZXIgdGhlIGdyaWRzIGFuZCBkYXRhLCBzbyB3ZSB1c2UgaXRzXG4gICAgICAgICAgICAvLyBtb3VzZW1vdmUgZXZlbnRzIGZvciBhbGwgZGF0YSBob3ZlciBlZmZlY3RzXG4gICAgICAgICAgICB2YXIgbWFpbmRyYWcgPSBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHhhLl9vZmZzZXQsIHlhLl9vZmZzZXQsXG4gICAgICAgICAgICAgICAgeGEuX2xlbmd0aCwgeWEuX2xlbmd0aCwgJ25zJywgJ2V3Jyk7XG5cbiAgICAgICAgICAgIG1haW5kcmFnLm9ubW91c2Vtb3ZlID0gZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBvbiBgZ2QuX2Z1bGxMYXlvdXRgLCAqbm90KiBmdWxsTGF5b3V0IGJlY2F1c2UgdGhlIHJlZmVyZW5jZVxuICAgICAgICAgICAgICAgIC8vIGNoYW5nZXMgYnkgdGhlIHRpbWUgdGhpcyBpcyBjYWxsZWQgYWdhaW4uXG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3JlaG92ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9PT0gc3VicGxvdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgRnguaG92ZXIoZ2QsIGV2dCwgc3VicGxvdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgRnguaG92ZXIoZ2QsIGV2dCwgc3VicGxvdCk7XG5cbiAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgd2UgaGF2ZSAqbm90KiB1c2VkIHRoZSBjYWNoZWQgZnVsbExheW91dCB2YXJpYWJsZSBoZXJlXG4gICAgICAgICAgICAgICAgLy8gc2luY2UgdGhhdCBtYXkgYmUgb3V0ZGF0ZWQgd2hlbiB0aGlzIGlzIGNhbGxlZCBhcyBhIGNhbGxiYWNrIGxhdGVyIG9uXG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2xhc3Rob3ZlciA9IG1haW5kcmFnO1xuICAgICAgICAgICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9ob3ZlcnN1YnBsb3QgPSBzdWJwbG90O1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIElNUE9SVEFOVDpcbiAgICAgICAgICAgICAqIFdlIG11c3QgY2hlY2sgZm9yIHRoZSBwcmVzZW5jZSBvZiB0aGUgZHJhZyBjb3ZlciBoZXJlLlxuICAgICAgICAgICAgICogSWYgd2UgZG9uJ3QsIGEgJ21vdXNlb3V0JyBldmVudCBpcyB0cmlnZ2VyZWQgb24gdGhlXG4gICAgICAgICAgICAgKiBtYWluZHJhZyBiZWZvcmUgZWFjaCAnY2xpY2snIGV2ZW50LCB3aGljaCBoYXMgdGhlIGVmZmVjdFxuICAgICAgICAgICAgICogb2YgY2xlYXJpbmcgdGhlIGhvdmVyZGF0YTsgdGh1cywgY2FuY2VsbGluZyB0aGUgY2xpY2sgZXZlbnQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1haW5kcmFnLm9ubW91c2VvdXQgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgICAgICAgICBpZihnZC5fZHJhZ2dpbmcpIHJldHVybjtcblxuICAgICAgICAgICAgICAgIC8vIFdoZW4gdGhlIG1vdXNlIGxlYXZlcyB0aGlzIG1haW5kcmFnLCB1bnNldCB0aGUgaG92ZXJlZCBzdWJwbG90LlxuICAgICAgICAgICAgICAgIC8vIFRoaXMgbWF5IGNhdXNlIHByb2JsZW1zIGlmIGl0IGxlYXZlcyB0aGUgc3VicGxvdCBkaXJlY3RseSAqb250bypcbiAgICAgICAgICAgICAgICAvLyBhbm90aGVyIHN1YnBsb3QsIGJ1dCB0aGF0J3MgYSB0aW55IGNvcm5lciBjYXNlIGF0IHRoZSBtb21lbnQuXG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC51bmhvdmVyKGdkLCBldnQpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gY29ybmVyIGRyYWdnZXJzXG4gICAgICAgICAgICBpZihnZC5fY29udGV4dC5zaG93QXhpc0RyYWdIYW5kbGVzKSB7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4YS5fb2Zmc2V0IC0gRFJBR0dFUlNJWkUsIHlhLl9vZmZzZXQgLSBEUkFHR0VSU0laRSxcbiAgICAgICAgICAgICAgICAgICAgRFJBR0dFUlNJWkUsIERSQUdHRVJTSVpFLCAnbicsICd3Jyk7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCwgeWEuX29mZnNldCAtIERSQUdHRVJTSVpFLFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgRFJBR0dFUlNJWkUsICduJywgJ2UnKTtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHhhLl9vZmZzZXQgLSBEUkFHR0VSU0laRSwgeWEuX29mZnNldCArIHlhLl9sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIERSQUdHRVJTSVpFLCBEUkFHR0VSU0laRSwgJ3MnLCAndycpO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCArIHhhLl9sZW5ndGgsIHlhLl9vZmZzZXQgKyB5YS5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgRFJBR0dFUlNJWkUsICdzJywgJ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZihnZC5fY29udGV4dC5zaG93QXhpc0RyYWdIYW5kbGVzKSB7XG4gICAgICAgICAgICAvLyB4IGF4aXMgZHJhZ2dlcnMgLSBpZiB5b3UgaGF2ZSBvdmVybGFpZCBwbG90cyxcbiAgICAgICAgICAgIC8vIHRoZXNlIGRyYWcgZWFjaCBheGlzIHNlcGFyYXRlbHlcbiAgICAgICAgICAgIGlmKHN1YnBsb3QgPT09IHhhLl9tYWluU3VicGxvdCkge1xuICAgICAgICAgICAgICAgIC8vIHRoZSB5IHBvc2l0aW9uIG9mIHRoZSBtYWluIHggYXhpcyBsaW5lXG4gICAgICAgICAgICAgICAgdmFyIHkwID0geGEuX21haW5MaW5lUG9zaXRpb247XG4gICAgICAgICAgICAgICAgaWYoeGEuc2lkZSA9PT0gJ3RvcCcpIHkwIC09IERSQUdHRVJTSVpFO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCArIHhhLl9sZW5ndGggKiAwLjEsIHkwLFxuICAgICAgICAgICAgICAgICAgICB4YS5fbGVuZ3RoICogMC44LCBEUkFHR0VSU0laRSwgJycsICdldycpO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCwgeTAsXG4gICAgICAgICAgICAgICAgICAgIHhhLl9sZW5ndGggKiAwLjEsIERSQUdHRVJTSVpFLCAnJywgJ3cnKTtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHhhLl9vZmZzZXQgKyB4YS5fbGVuZ3RoICogMC45LCB5MCxcbiAgICAgICAgICAgICAgICAgICAgeGEuX2xlbmd0aCAqIDAuMSwgRFJBR0dFUlNJWkUsICcnLCAnZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8geSBheGlzIGRyYWdnZXJzXG4gICAgICAgICAgICBpZihzdWJwbG90ID09PSB5YS5fbWFpblN1YnBsb3QpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgeCBwb3NpdGlvbiBvZiB0aGUgbWFpbiB5IGF4aXMgbGluZVxuICAgICAgICAgICAgICAgIHZhciB4MCA9IHlhLl9tYWluTGluZVBvc2l0aW9uO1xuICAgICAgICAgICAgICAgIGlmKHlhLnNpZGUgIT09ICdyaWdodCcpIHgwIC09IERSQUdHRVJTSVpFO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeDAsIHlhLl9vZmZzZXQgKyB5YS5fbGVuZ3RoICogMC4xLFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgeWEuX2xlbmd0aCAqIDAuOCwgJ25zJywgJycpO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeDAsIHlhLl9vZmZzZXQgKyB5YS5fbGVuZ3RoICogMC45LFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgeWEuX2xlbmd0aCAqIDAuMSwgJ3MnLCAnJyk7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4MCwgeWEuX29mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgRFJBR0dFUlNJWkUsIHlhLl9sZW5ndGggKiAwLjEsICduJywgJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBJbiBjYXNlIHlvdSBtb3VzZW1vdmUgb3ZlciBzb21lIGhvdmVydGV4dCwgc2VuZCBpdCB0byBGeC5ob3ZlciB0b29cbiAgICAvLyB3ZSBkbyB0aGlzIHNvIHRoYXQgd2UgY2FuIHB1dCB0aGUgaG92ZXIgdGV4dCBpbiBmcm9udCBvZiBldmVyeXRoaW5nLFxuICAgIC8vIGJ1dCBzdGlsbCBiZSBhYmxlIHRvIGludGVyYWN0IHdpdGggZXZlcnl0aGluZyBhcyBpZiBpdCBpc24ndCB0aGVyZVxuICAgIHZhciBob3ZlckxheWVyID0gZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCk7XG5cbiAgICBob3ZlckxheWVyLm9ubW91c2Vtb3ZlID0gZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgIGV2dC50YXJnZXQgPSBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyO1xuICAgICAgICBGeC5ob3ZlcihnZCwgZXZ0LCBmdWxsTGF5b3V0Ll9ob3ZlcnN1YnBsb3QpO1xuICAgIH07XG5cbiAgICBob3ZlckxheWVyLm9uY2xpY2sgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgZXZ0LnRhcmdldCA9IGdkLl9mdWxsTGF5b3V0Ll9sYXN0aG92ZXI7XG4gICAgICAgIEZ4LmNsaWNrKGdkLCBldnQpO1xuICAgIH07XG5cbiAgICAvLyBhbHNvIGRlbGVnYXRlIG1vdXNlZG93bnMuLi4gVE9ETzogZG9lcyB0aGlzIGFjdHVhbGx5IHdvcms/XG4gICAgaG92ZXJMYXllci5vbm1vdXNlZG93biA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyLm9ubW91c2Vkb3duKGV2dCk7XG4gICAgfTtcblxuICAgIGV4cG9ydHMudXBkYXRlRngoZ2QpO1xufTtcblxuLy8gTWluaW1hbCBzZXQgb2YgdXBkYXRlIG5lZWRlZCBvbiAnbW9kZWJhcicgZWRpdHMuXG4vLyBXZSBvbmx5IG5lZWQgdG8gdXBkYXRlIHRoZSA8ZyAuZHJhZ2xheWVyPiBjdXJzb3Igc3R5bGUuXG4vL1xuLy8gTm90ZSB0aGF0IGNoYW5naW5nIHRoZSBheGlzIGNvbmZpZ3VyYXRpb24gYW5kL29yIHRoZSBmaXhlZHJhbmdlIGF0dHJpYnV0ZVxuLy8gc2hvdWxkIHRyaWdnZXIgYSBmdWxsIGluaXRJbnRlcmFjdGlvbnMuXG5leHBvcnRzLnVwZGF0ZUZ4ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjdXJzb3IgPSBmdWxsTGF5b3V0LmRyYWdtb2RlID09PSAncGFuJyA/ICdtb3ZlJyA6ICdjcm9zc2hhaXInO1xuICAgIHNldEN1cnNvcihmdWxsTGF5b3V0Ll9kcmFnZ2VycywgY3Vyc29yKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLyoqXG4gKiBGYWN0b3J5IGZ1bmN0aW9uIGZvciBjaGVja2luZyBjb21wb25lbnQgYXJyYXlzIGZvciBzdWJwbG90IHJlZmVyZW5jZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRhaW5lckFycmF5TmFtZTogdGhlIHRvcC1sZXZlbCBhcnJheSBpbiBnZC5sYXlvdXQgdG8gY2hlY2tcbiAqICAgSWYgYW4gaXRlbSBpbiB0aGlzIGNvbnRhaW5lciBpcyBmb3VuZCB0aGF0IHJlZmVyZW5jZXMgYSBjYXJ0ZXNpYW4geCBhbmQvb3IgeSBheGlzLFxuICogICBlbnN1cmUgY2FydGVzaWFuIGlzIG1hcmtlZCBhcyBhIGJhc2UgcGxvdCBtb2R1bGUgYW5kIHJlY29yZCB0aGUgYXhlcyAoYW5kIHN1YnBsb3RcbiAqICAgaWYgYm90aCByZWZzIGFyZSBheGVzKSBpbiBnZC5fZnVsbExheW91dFxuICpcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufTogd2l0aCBhcmdzIGxheW91dEluIChnZC5sYXlvdXQpIGFuZCBsYXlvdXRPdXQgKGdkLl9mdWxsTGF5b3V0KVxuICogYXMgZXhwZWN0ZWQgb2YgYSBjb21wb25lbnQgaW5jbHVkZUJhc2VQbG90IG1ldGhvZFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VJbmNsdWRlQ29tcG9uZW50cyhjb250YWluZXJBcnJheU5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gaW5jbHVkZUNvbXBvbmVudHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgICAgICB2YXIgYXJyYXkgPSBsYXlvdXRJbltjb250YWluZXJBcnJheU5hbWVdO1xuICAgICAgICBpZighQXJyYXkuaXNBcnJheShhcnJheSkpIHJldHVybjtcblxuICAgICAgICB2YXIgQ2FydGVzaWFuID0gUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeS5jYXJ0ZXNpYW47XG4gICAgICAgIHZhciBpZFJlZ2V4ID0gQ2FydGVzaWFuLmlkUmVnZXg7XG4gICAgICAgIHZhciBzdWJwbG90cyA9IGxheW91dE91dC5fc3VicGxvdHM7XG4gICAgICAgIHZhciB4YUxpc3QgPSBzdWJwbG90cy54YXhpcztcbiAgICAgICAgdmFyIHlhTGlzdCA9IHN1YnBsb3RzLnlheGlzO1xuICAgICAgICB2YXIgY2FydGVzaWFuTGlzdCA9IHN1YnBsb3RzLmNhcnRlc2lhbjtcbiAgICAgICAgdmFyIGhhc0NhcnRlc2lhbk9yR0wyRCA9IGxheW91dE91dC5faGFzKCdjYXJ0ZXNpYW4nKSB8fCBsYXlvdXRPdXQuX2hhcygnZ2wyZCcpO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGl0ZW1pID0gYXJyYXlbaV07XG4gICAgICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QoaXRlbWkpKSBjb250aW51ZTtcblxuICAgICAgICAgICAgdmFyIHhyZWYgPSBpdGVtaS54cmVmO1xuICAgICAgICAgICAgdmFyIHlyZWYgPSBpdGVtaS55cmVmO1xuXG4gICAgICAgICAgICB2YXIgaGFzWHJlZiA9IGlkUmVnZXgueC50ZXN0KHhyZWYpO1xuICAgICAgICAgICAgdmFyIGhhc1lyZWYgPSBpZFJlZ2V4LnkudGVzdCh5cmVmKTtcbiAgICAgICAgICAgIGlmKGhhc1hyZWYgfHwgaGFzWXJlZikge1xuICAgICAgICAgICAgICAgIGlmKCFoYXNDYXJ0ZXNpYW5PckdMMkQpIExpYi5wdXNoVW5pcXVlKGxheW91dE91dC5fYmFzZVBsb3RNb2R1bGVzLCBDYXJ0ZXNpYW4pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5ld0F4aXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZihoYXNYcmVmICYmIHhhTGlzdC5pbmRleE9mKHhyZWYpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB4YUxpc3QucHVzaCh4cmVmKTtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXhpcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGhhc1lyZWYgJiYgeWFMaXN0LmluZGV4T2YoeXJlZikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHlhTGlzdC5wdXNoKHlyZWYpO1xuICAgICAgICAgICAgICAgICAgICBuZXdBeGlzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAqIE5vdGljZSB0aGUgbG9naWMgaGVyZTogb25seSBhZGQgYSBzdWJwbG90IGZvciBhIGNvbXBvbmVudCBpZlxuICAgICAgICAgICAgICAgICAqIGl0J3MgcmVmZXJlbmNpbmcgYm90aCB4IGFuZCB5IGF4ZXMgQU5EIGl0J3MgY3JlYXRpbmcgYSBuZXcgYXhpc1xuICAgICAgICAgICAgICAgICAqIHNvIGZvciBleGFtcGxlIGlmIHlvdXIgcGxvdCBhbHJlYWR5IGhhcyB4eSBhbmQgeDJ5MiwgYW4gYW5ub3RhdGlvblxuICAgICAgICAgICAgICAgICAqIG9uIHgyeSBvciB4eTIgd2lsbCBub3QgY3JlYXRlIGEgbmV3IHN1YnBsb3QuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYobmV3QXhpcyAmJiBoYXNYcmVmICYmIGhhc1lyZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FydGVzaWFuTGlzdC5wdXNoKHhyZWYgKyB5cmVmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIFBsb3RzID0gcmVxdWlyZSgnLi4vcGxvdHMnKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbnZhciBnZXRNb2R1bGVDYWxjRGF0YSA9IHJlcXVpcmUoJy4uL2dldF9kYXRhJykuZ2V0TW9kdWxlQ2FsY0RhdGE7XG52YXIgYXhpc0lkcyA9IHJlcXVpcmUoJy4vYXhpc19pZHMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG5cbnZhciBlbnN1cmVTaW5nbGUgPSBMaWIuZW5zdXJlU2luZ2xlO1xuXG5mdW5jdGlvbiBlbnN1cmVTaW5nbGVBbmRBZGREYXR1bShwYXJlbnQsIG5vZGVUeXBlLCBjbGFzc05hbWUpIHtcbiAgICByZXR1cm4gTGliLmVuc3VyZVNpbmdsZShwYXJlbnQsIG5vZGVUeXBlLCBjbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5kYXR1bShjbGFzc05hbWUpO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLm5hbWUgPSAnY2FydGVzaWFuJztcblxuZXhwb3J0cy5hdHRyID0gWyd4YXhpcycsICd5YXhpcyddO1xuXG5leHBvcnRzLmlkUm9vdCA9IFsneCcsICd5J107XG5cbmV4cG9ydHMuaWRSZWdleCA9IGNvbnN0YW50cy5pZFJlZ2V4O1xuXG5leHBvcnRzLmF0dHJSZWdleCA9IGNvbnN0YW50cy5hdHRyUmVnZXg7XG5cbmV4cG9ydHMuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5leHBvcnRzLmxheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSByZXF1aXJlKCcuL2xheW91dF9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnRyYW5zaXRpb25BeGVzID0gcmVxdWlyZSgnLi90cmFuc2l0aW9uX2F4ZXMnKS50cmFuc2l0aW9uQXhlcztcbmV4cG9ydHMudHJhbnNpdGlvbkF4ZXMyID0gcmVxdWlyZSgnLi90cmFuc2l0aW9uX2F4ZXMnKS50cmFuc2l0aW9uQXhlczI7XG5cbmV4cG9ydHMuZmluYWxpemVTdWJwbG90cyA9IGZ1bmN0aW9uKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXRPdXQuX3N1YnBsb3RzO1xuICAgIHZhciB4TGlzdCA9IHN1YnBsb3RzLnhheGlzO1xuICAgIHZhciB5TGlzdCA9IHN1YnBsb3RzLnlheGlzO1xuICAgIHZhciBzcFNWRyA9IHN1YnBsb3RzLmNhcnRlc2lhbjtcbiAgICB2YXIgc3BBbGwgPSBzcFNWRy5jb25jYXQoc3VicGxvdHMuZ2wyZCB8fCBbXSk7XG4gICAgdmFyIGFsbFggPSB7fTtcbiAgICB2YXIgYWxsWSA9IHt9O1xuICAgIHZhciBpLCB4aSwgeWk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzcEFsbC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcGFydHMgPSBzcEFsbFtpXS5zcGxpdCgneScpO1xuICAgICAgICBhbGxYW3BhcnRzWzBdXSA9IDE7XG4gICAgICAgIGFsbFlbJ3knICsgcGFydHNbMV1dID0gMTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayBmb3IgeCBheGVzIHdpdGggbm8gc3VicGxvdCwgYW5kIG1ha2Ugb25lIGZyb20gdGhlIGFuY2hvciBvZiB0aGF0IHggYXhpc1xuICAgIGZvcihpID0gMDsgaSA8IHhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHhpID0geExpc3RbaV07XG4gICAgICAgIGlmKCFhbGxYW3hpXSkge1xuICAgICAgICAgICAgeWkgPSAobGF5b3V0SW5bYXhpc0lkcy5pZDJuYW1lKHhpKV0gfHwge30pLmFuY2hvcjtcbiAgICAgICAgICAgIGlmKCFjb25zdGFudHMuaWRSZWdleC55LnRlc3QoeWkpKSB5aSA9ICd5JztcbiAgICAgICAgICAgIHNwU1ZHLnB1c2goeGkgKyB5aSk7XG4gICAgICAgICAgICBzcEFsbC5wdXNoKHhpICsgeWkpO1xuXG4gICAgICAgICAgICBpZighYWxsWVt5aV0pIHtcbiAgICAgICAgICAgICAgICBhbGxZW3lpXSA9IDE7XG4gICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoeUxpc3QsIHlpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNhbWUgZm9yIHkgYXhlcyB3aXRoIG5vIHN1YnBsb3RcbiAgICBmb3IoaSA9IDA7IGkgPCB5TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB5aSA9IHlMaXN0W2ldO1xuICAgICAgICBpZighYWxsWVt5aV0pIHtcbiAgICAgICAgICAgIHhpID0gKGxheW91dEluW2F4aXNJZHMuaWQybmFtZSh5aSldIHx8IHt9KS5hbmNob3I7XG4gICAgICAgICAgICBpZighY29uc3RhbnRzLmlkUmVnZXgueC50ZXN0KHhpKSkgeGkgPSAneCc7XG4gICAgICAgICAgICBzcFNWRy5wdXNoKHhpICsgeWkpO1xuICAgICAgICAgICAgc3BBbGwucHVzaCh4aSArIHlpKTtcblxuICAgICAgICAgICAgaWYoIWFsbFhbeGldKSB7XG4gICAgICAgICAgICAgICAgYWxsWFt4aV0gPSAxO1xuICAgICAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHhMaXN0LCB4aSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5LCBpZiB3ZSd2ZSBnb3R0ZW4gaGVyZSB3ZSdyZSBzdXBwb3NlZCB0byBzaG93IGNhcnRlc2lhbi4uLlxuICAgIC8vIHNvIGlmIHRoZXJlIGFyZSBOTyBzdWJwbG90cyBhdCBhbGwsIG1ha2Ugb25lIGZyb20gdGhlIGZpcnN0XG4gICAgLy8geCAmIHkgYXhlcyBpbiB0aGUgaW5wdXQgbGF5b3V0XG4gICAgaWYoIXNwQWxsLmxlbmd0aCkge1xuICAgICAgICB4aSA9ICcnO1xuICAgICAgICB5aSA9ICcnO1xuICAgICAgICBmb3IodmFyIGtpIGluIGxheW91dEluKSB7XG4gICAgICAgICAgICBpZihjb25zdGFudHMuYXR0clJlZ2V4LnRlc3Qoa2kpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0ga2kuY2hhckF0KDApO1xuICAgICAgICAgICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIXhpIHx8ICgra2kuc3Vic3RyKDUpIDwgK3hpLnN1YnN0cig1KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHhpID0ga2k7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZigheWkgfHwgKCtraS5zdWJzdHIoNSkgPCAreWkuc3Vic3RyKDUpKSkge1xuICAgICAgICAgICAgICAgICAgICB5aSA9IGtpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB4aSA9IHhpID8gYXhpc0lkcy5uYW1lMmlkKHhpKSA6ICd4JztcbiAgICAgICAgeWkgPSB5aSA/IGF4aXNJZHMubmFtZTJpZCh5aSkgOiAneSc7XG4gICAgICAgIHhMaXN0LnB1c2goeGkpO1xuICAgICAgICB5TGlzdC5wdXNoKHlpKTtcbiAgICAgICAgc3BTVkcucHVzaCh4aSArIHlpKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIENhcnRlc2lhbi5wbG90XG4gKlxuICogQHBhcmFtIHtET00gZGl2IHwgb2JqZWN0fSBnZFxuICogQHBhcmFtIHthcnJheSB8IG51bGx9IChvcHRpb25hbCkgdHJhY2VzXG4gKiAgYXJyYXkgb2YgdHJhY2VzIGluZGljZXMgdG8gcGxvdFxuICogIGlmIHVuZGVmaW5lZCwgcGxvdHMgYWxsIGNhcnRlc2lhbiB0cmFjZXMsXG4gKiAgaWYgbnVsbCwgcGxvdHMgbm8gdHJhY2VzXG4gKiBAcGFyYW0ge29iamVjdH0gKG9wdGlvbmFsKSB0cmFuc2l0aW9uT3B0c1xuICogIHRyYW5zaXRpb24gb3B0aW9uIG9iamVjdFxuICogQHBhcmFtIHtmdW5jdGlvbn0gKG9wdGlvbmFsKSBtYWtlT25Db21wbGV0ZUNhbGxiYWNrXG4gKiAgdHJhbnNpdGlvbiBtYWtlIGNhbGxiYWNrIGZ1bmN0aW9uIGZyb20gUGxvdHMudHJhbnNpdGlvblxuICovXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCwgdHJhY2VzLCB0cmFuc2l0aW9uT3B0cywgbWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RzID0gZnVsbExheW91dC5fc3VicGxvdHMuY2FydGVzaWFuO1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBpO1xuXG4gICAgaWYodHJhY2VzID09PSBudWxsKSB7XG4gICAgICAgIC8vIHRoaXMgbWVhbnMgbm8gdXBkYXRlcyByZXF1aXJlZCwgbXVzdCByZXR1cm4gaGVyZVxuICAgICAgICAvLyBzbyB0aGF0IHBsb3RPbmUgZG9lc24ndCByZW1vdmUgdGhlIHRyYWNlIGxheWVyc1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmKCFBcnJheS5pc0FycmF5KHRyYWNlcykpIHtcbiAgICAgICAgLy8gSWYgdHJhY2VzIGlzIG5vdCBwcm92aWRlZCwgdGhlbiBpdCdzIGEgY29tcGxldGUgcmVwbG90IGFuZCBtaXNzaW5nXG4gICAgICAgIC8vIHRyYWNlcyBhcmUgcmVtb3ZlZFxuICAgICAgICB0cmFjZXMgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHRyYWNlcy5wdXNoKGkpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IHN1YnBsb3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzdWJwbG90ID0gc3VicGxvdHNbaV07XG4gICAgICAgIHZhciBzdWJwbG90SW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuXG4gICAgICAgIC8vIEdldCBhbGwgY2FsY2RhdGEgZm9yIHRoaXMgc3VicGxvdDpcbiAgICAgICAgdmFyIGNkU3VicGxvdCA9IFtdO1xuICAgICAgICB2YXIgcGNkO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjYWxjZGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbal07XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICAgICAgLy8gU2tpcCB0cmFjZSBpZiB3aGl0ZWxpc3QgcHJvdmlkZWQgYW5kIGl0J3Mgbm90IHdoaXRlbGlzdGVkOlxuICAgICAgICAgICAgLy8gaWYgKEFycmF5LmlzQXJyYXkodHJhY2VzKSAmJiB0cmFjZXMuaW5kZXhPZihpKSA9PT0gLTEpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYodHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcyA9PT0gc3VicGxvdCkge1xuICAgICAgICAgICAgICAgIC8vIFhYWDogU2hvdWxkIHRyYWNlIGNhcnBldCBkZXBlbmRlbmNpZXMuIE9ubHkgcmVwbG90IGFsbCBjYXJwZXQgcGxvdHMgaWYgdGhlIGNhcnBldFxuICAgICAgICAgICAgICAgIC8vIGF4aXMgaGFzIGFjdHVhbGx5IGNoYW5nZWQ6XG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIHRyYWNlIGlzIHNwZWNpZmljYWxseSByZXF1ZXN0ZWQsIGFkZCBpdCB0byB0aGUgbGlzdDpcbiAgICAgICAgICAgICAgICBpZih0cmFjZXMuaW5kZXhPZih0cmFjZS5pbmRleCkgIT09IC0xIHx8IHRyYWNlLmNhcnBldCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBPa2F5LCBzbyBleGFtcGxlOiB0cmFjZXMgMCwgMSwgYW5kIDIgaGF2ZSBmaWxsID0gdG9uZXh0LiBZb3UgYW5pbWF0ZVxuICAgICAgICAgICAgICAgICAgICAvLyB0cmFjZXMgMCBhbmQgMi4gVHJhY2UgMSBhbHNvIG5lZWRzIHRvIGJlIHVwZGF0ZWQsIG90aGVyd2lzZSBpdHMgZmlsbFxuICAgICAgICAgICAgICAgICAgICAvLyBpcyBvdXRkYXRlZC4gU28gdGhpcyByZXRyb2FjdGl2ZWx5IGFkZHMgdGhlIHByZXZpb3VzIHRyYWNlIGlmIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyB0cmFjZXMgYXJlIGludGVyZGVwZW5kZW50LlxuICAgICAgICAgICAgICAgICAgICBpZihcbiAgICAgICAgICAgICAgICAgICAgICAgIHBjZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgcGNkWzBdLnRyYWNlLnhheGlzICsgcGNkWzBdLnRyYWNlLnlheGlzID09PSBzdWJwbG90ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBbJ3RvbmV4dHgnLCAndG9uZXh0eScsICd0b25leHQnXS5pbmRleE9mKHRyYWNlLmZpbGwpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgY2RTdWJwbG90LmluZGV4T2YocGNkKSA9PT0gLTFcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjZFN1YnBsb3QucHVzaChwY2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY2RTdWJwbG90LnB1c2goY2QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFRyYWNrIHRoZSBwcmV2aW91cyB0cmFjZSBvbiB0aGlzIHN1YnBsb3QgZm9yIHRoZSByZXRyb2FjdGl2ZS1hZGQgc3RlcFxuICAgICAgICAgICAgICAgIC8vIGFib3ZlOlxuICAgICAgICAgICAgICAgIHBjZCA9IGNkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcGxvdE9uZShnZCwgc3VicGxvdEluZm8sIGNkU3VicGxvdCwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBsb3RPbmUoZ2QsIHBsb3RpbmZvLCBjZFN1YnBsb3QsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgdmFyIHRyYWNlTGF5ZXJDbGFzc2VzID0gY29uc3RhbnRzLnRyYWNlTGF5ZXJDbGFzc2VzO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9tb2R1bGVzO1xuICAgIHZhciBfbW9kdWxlLCBjZE1vZHVsZUFuZE90aGVycywgY2RNb2R1bGU7XG5cbiAgICB2YXIgbGF5ZXJEYXRhID0gW107XG4gICAgdmFyIHpvb21TY2FsZVF1ZXJ5UGFydHMgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIF9tb2R1bGUgPSBtb2R1bGVzW2ldO1xuICAgICAgICB2YXIgbmFtZSA9IF9tb2R1bGUubmFtZTtcbiAgICAgICAgdmFyIGNhdGVnb3JpZXMgPSBSZWdpc3RyeS5tb2R1bGVzW25hbWVdLmNhdGVnb3JpZXM7XG5cbiAgICAgICAgaWYoY2F0ZWdvcmllcy5zdmcpIHtcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSAoX21vZHVsZS5sYXllck5hbWUgfHwgbmFtZSArICdsYXllcicpO1xuICAgICAgICAgICAgdmFyIHBsb3RNZXRob2QgPSBfbW9kdWxlLnBsb3Q7XG5cbiAgICAgICAgICAgIC8vIHBsb3QgYWxsIHZpc2libGUgdHJhY2VzIG9mIHRoaXMgdHlwZSBvbiB0aGlzIHN1YnBsb3QgYXQgb25jZVxuICAgICAgICAgICAgY2RNb2R1bGVBbmRPdGhlcnMgPSBnZXRNb2R1bGVDYWxjRGF0YShjZFN1YnBsb3QsIHBsb3RNZXRob2QpO1xuICAgICAgICAgICAgY2RNb2R1bGUgPSBjZE1vZHVsZUFuZE90aGVyc1swXTtcbiAgICAgICAgICAgIC8vIGRvbid0IG5lZWQgdG8gc2VhcmNoIHRoZSBmb3VuZCB0cmFjZXMgYWdhaW4gLSBpbiBmYWN0IHdlIG5lZWQgdG8gTk9UXG4gICAgICAgICAgICAvLyBzbyB0aGF0IGlmIHR3byBtb2R1bGVzIHNoYXJlIHRoZSBzYW1lIHBsb3R0ZXIgd2UgZG9uJ3QgZG91YmxlLXBsb3RcbiAgICAgICAgICAgIGNkU3VicGxvdCA9IGNkTW9kdWxlQW5kT3RoZXJzWzFdO1xuXG4gICAgICAgICAgICBpZihjZE1vZHVsZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsYXllckRhdGEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGk6IHRyYWNlTGF5ZXJDbGFzc2VzLmluZGV4T2YoY2xhc3NOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgICAgIHBsb3RNZXRob2Q6IHBsb3RNZXRob2QsXG4gICAgICAgICAgICAgICAgICAgIGNkTW9kdWxlOiBjZE1vZHVsZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihjYXRlZ29yaWVzLnpvb21TY2FsZSkge1xuICAgICAgICAgICAgICAgIHpvb21TY2FsZVF1ZXJ5UGFydHMucHVzaCgnLicgKyBjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGF5ZXJEYXRhLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYS5pIC0gYi5pOyB9KTtcblxuICAgIHZhciBsYXllcnMgPSBwbG90aW5mby5wbG90LnNlbGVjdEFsbCgnZy5tbGF5ZXInKVxuICAgICAgICAuZGF0YShsYXllckRhdGEsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuY2xhc3NOYW1lOyB9KTtcblxuICAgIGxheWVycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuY2xhc3NOYW1lOyB9KVxuICAgICAgICAuY2xhc3NlZCgnbWxheWVyJywgdHJ1ZSk7XG5cbiAgICBsYXllcnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGF5ZXJzLm9yZGVyKCk7XG5cbiAgICBsYXllcnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBkLmNsYXNzTmFtZTtcblxuICAgICAgICBkLnBsb3RNZXRob2QoXG4gICAgICAgICAgICBnZCwgcGxvdGluZm8sIGQuY2RNb2R1bGUsIHNlbCxcbiAgICAgICAgICAgIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gbGF5ZXJzIHRoYXQgYWxsb3cgYGNsaXBvbmF4aXM6IGZhbHNlYFxuICAgICAgICBpZihjbGFzc05hbWUgIT09ICdzY2F0dGVybGF5ZXInICYmIGNsYXNzTmFtZSAhPT0gJ2JhcmxheWVyJykge1xuICAgICAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHNlbCwgcGxvdGluZm8ubGF5ZXJDbGlwSWQpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBjYWxsIFNjYXR0ZXJnbC5wbG90IHNlcGFyYXRlbHlcbiAgICBpZihmdWxsTGF5b3V0Ll9oYXMoJ3NjYXR0ZXJnbCcpKSB7XG4gICAgICAgIF9tb2R1bGUgPSBSZWdpc3RyeS5nZXRNb2R1bGUoJ3NjYXR0ZXJnbCcpO1xuICAgICAgICBjZE1vZHVsZSA9IGdldE1vZHVsZUNhbGNEYXRhKGNkU3VicGxvdCwgX21vZHVsZSlbMF07XG4gICAgICAgIF9tb2R1bGUucGxvdChnZCwgcGxvdGluZm8sIGNkTW9kdWxlKTtcbiAgICB9XG5cbiAgICAvLyBzdGFzaCBcImhvdFwiIHNlbGVjdGlvbnMgZm9yIGZhc3RlciBpbnRlcmFjdGlvbiBvbiBkcmFnIGFuZCBzY3JvbGxcbiAgICBpZighZ2QuX2NvbnRleHQuc3RhdGljUGxvdCkge1xuICAgICAgICBpZihwbG90aW5mby5faGFzQ2xpcE9uQXhpc0ZhbHNlKSB7XG4gICAgICAgICAgICBwbG90aW5mby5jbGlwT25BeGlzRmFsc2VUcmFjZXMgPSBwbG90aW5mby5wbG90XG4gICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgnLnNjYXR0ZXJsYXllciwgLmJhcmxheWVyJylcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCcudHJhY2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHpvb21TY2FsZVF1ZXJ5UGFydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VzID0gcGxvdGluZm8ucGxvdFxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoem9vbVNjYWxlUXVlcnlQYXJ0cy5qb2luKCcsJykpXG4gICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgnLnRyYWNlJyk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnpvb21TY2FsZVB0cyA9IHRyYWNlcy5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnpvb21TY2FsZVR4dCA9IHRyYWNlcy5zZWxlY3RBbGwoJy50ZXh0cG9pbnQnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRQbG90cyA9IG9sZEZ1bGxMYXlvdXQuX3Bsb3RzIHx8IHt9O1xuICAgIHZhciBuZXdQbG90cyA9IG5ld0Z1bGxMYXlvdXQuX3Bsb3RzIHx8IHt9O1xuICAgIHZhciBvbGRTdWJwbG90TGlzdCA9IG9sZEZ1bGxMYXlvdXQuX3N1YnBsb3RzIHx8IHt9O1xuICAgIHZhciBwbG90aW5mbztcbiAgICB2YXIgaSwgaztcblxuICAgIC8vIHdoZW4gZ29pbmcgZnJvbSBhIGxhcmdlIHNwbG9tIGdyYXBoIHRvIHNvbWV0aGluZyBlbHNlLFxuICAgIC8vIHdlIG5lZWQgdG8gY2xlYXIgPGcgc3VicGxvdD4gc28gdGhhdCB0aGUgbmV3IGNhcnRlc2lhbiBzdWJwbG90XG4gICAgLy8gY2FuIGhhdmUgdGhlIGNvcnJlY3QgbGF5ZXIgb3JkZXJpbmdcbiAgICBpZihvbGRGdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMgJiYgIW5ld0Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICBmb3IoayBpbiBvbGRQbG90cykge1xuICAgICAgICAgICAgcGxvdGluZm8gPSBvbGRQbG90c1trXTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLnBsb3Rncm91cCkgcGxvdGluZm8ucGxvdGdyb3VwLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGhhZEdsID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ2dsJykpO1xuICAgIHZhciBoYXNHbCA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdnbCcpKTtcblxuICAgIGlmKGhhZEdsICYmICFoYXNHbCkge1xuICAgICAgICBmb3IoayBpbiBvbGRQbG90cykge1xuICAgICAgICAgICAgcGxvdGluZm8gPSBvbGRQbG90c1trXTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLl9zY2VuZSkgcGxvdGluZm8uX3NjZW5lLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGRlbGV0ZSBhbnkgdGl0bGVzIHdlIGRvbid0IG5lZWQgYW55bW9yZVxuICAgIC8vIGNoZWNrIGlmIGF4aXMgbGlzdCBoYXMgY2hhbmdlZCwgYW5kIGlmIHNvIGNsZWFyIG9sZCB0aXRsZXNcbiAgICBpZihvbGRTdWJwbG90TGlzdC54YXhpcyAmJiBvbGRTdWJwbG90TGlzdC55YXhpcykge1xuICAgICAgICB2YXIgb2xkQXhJRHMgPSBheGlzSWRzLmxpc3RJZHMoe19mdWxsTGF5b3V0OiBvbGRGdWxsTGF5b3V0fSk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9sZEF4SURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2xkQXhJZCA9IG9sZEF4SURzW2ldO1xuICAgICAgICAgICAgaWYoIW5ld0Z1bGxMYXlvdXRbYXhpc0lkcy5pZDJuYW1lKG9sZEF4SWQpXSkge1xuICAgICAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJy5nLScgKyBvbGRBeElkICsgJ3RpdGxlJykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiB3ZSd2ZSBnb3R0ZW4gcmlkIG9mIGFsbCBjYXJ0ZXNpYW4gdHJhY2VzLCByZW1vdmUgYWxsIHRoZSBzdWJwbG90IHN2ZyBpdGVtc1xuICAgIHZhciBoYWRDYXJ0ZXNpYW4gPSAob2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJykpO1xuICAgIHZhciBoYXNDYXJ0ZXNpYW4gPSAobmV3RnVsbExheW91dC5faGFzICYmIG5ld0Z1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJykpO1xuXG4gICAgaWYoaGFkQ2FydGVzaWFuICYmICFoYXNDYXJ0ZXNpYW4pIHtcbiAgICAgICAgcHVyZ2VTdWJwbG90TGF5ZXJzKG9sZEZ1bGxMYXlvdXQuX2NhcnRlc2lhbmxheWVyLnNlbGVjdEFsbCgnLnN1YnBsb3QnKSwgb2xkRnVsbExheW91dCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX2RlZnMuc2VsZWN0QWxsKCcuYXhlc2NsaXAnKS5yZW1vdmUoKTtcbiAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX2F4aXNDb25zdHJhaW50R3JvdXBzO1xuICAgIH1cbiAgICAvLyBvdGhlcndpc2UgbG9vayBmb3Igc3VicGxvdHMgd2UgbmVlZCB0byByZW1vdmVcbiAgICBlbHNlIGlmKG9sZFN1YnBsb3RMaXN0LmNhcnRlc2lhbikge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBvbGRTdWJwbG90TGlzdC5jYXJ0ZXNpYW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBvbGRTdWJwbG90SWQgPSBvbGRTdWJwbG90TGlzdC5jYXJ0ZXNpYW5baV07XG4gICAgICAgICAgICBpZighbmV3UGxvdHNbb2xkU3VicGxvdElkXSkge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RvciA9ICcuJyArIG9sZFN1YnBsb3RJZCArICcsLicgKyBvbGRTdWJwbG90SWQgKyAnLXgsLicgKyBvbGRTdWJwbG90SWQgKyAnLXknO1xuICAgICAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2NhcnRlc2lhbmxheWVyLnNlbGVjdEFsbChzZWxlY3RvcikucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgcmVtb3ZlU3VicGxvdEV4dHJhcyhvbGRTdWJwbG90SWQsIG9sZEZ1bGxMYXlvdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZXhwb3J0cy5kcmF3RnJhbWV3b3JrID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90RGF0YSA9IG1ha2VTdWJwbG90RGF0YShnZCk7XG5cbiAgICB2YXIgc3VicGxvdExheWVycyA9IGZ1bGxMYXlvdXQuX2NhcnRlc2lhbmxheWVyLnNlbGVjdEFsbCgnLnN1YnBsb3QnKVxuICAgICAgICAuZGF0YShzdWJwbG90RGF0YSwgU3RyaW5nKTtcblxuICAgIHN1YnBsb3RMYXllcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiAnc3VicGxvdCAnICsgZFswXTsgfSk7XG5cbiAgICBzdWJwbG90TGF5ZXJzLm9yZGVyKCk7XG5cbiAgICBzdWJwbG90TGF5ZXJzLmV4aXQoKVxuICAgICAgICAuY2FsbChwdXJnZVN1YnBsb3RMYXllcnMsIGZ1bGxMYXlvdXQpO1xuXG4gICAgc3VicGxvdExheWVycy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGlkID0gZFswXTtcbiAgICAgICAgdmFyIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbaWRdO1xuXG4gICAgICAgIHBsb3RpbmZvLnBsb3Rncm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgbWFrZVN1YnBsb3RMYXllcihnZCwgcGxvdGluZm8pO1xuXG4gICAgICAgIC8vIG1ha2Ugc2VwYXJhdGUgZHJhZyBsYXllcnMgZm9yIGVhY2ggc3VicGxvdCxcbiAgICAgICAgLy8gYnV0IGFwcGVuZCB0aGVtIHRvIHBhcGVyIHJhdGhlciB0aGFuIHRoZSBwbG90IGdyb3VwcyxcbiAgICAgICAgLy8gc28gdGhleSBlbmQgdXAgb24gdG9wIG9mIHRoZSByZXN0XG4gICAgICAgIHBsb3RpbmZvLmRyYWdsYXllciA9IGVuc3VyZVNpbmdsZShmdWxsTGF5b3V0Ll9kcmFnZ2VycywgJ2cnLCBpZCk7XG4gICAgfSk7XG59O1xuXG5leHBvcnRzLnJhbmdlUGxvdCA9IGZ1bmN0aW9uKGdkLCBwbG90aW5mbywgY2RTdWJwbG90KSB7XG4gICAgbWFrZVN1YnBsb3RMYXllcihnZCwgcGxvdGluZm8pO1xuICAgIHBsb3RPbmUoZ2QsIHBsb3RpbmZvLCBjZFN1YnBsb3QpO1xuICAgIFBsb3RzLnN0eWxlKGdkKTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VTdWJwbG90RGF0YShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmNhcnRlc2lhbjtcbiAgICB2YXIgbGVuID0gaWRzLmxlbmd0aDtcbiAgICB2YXIgaSwgaiwgaWQsIHBsb3RpbmZvLCB4YSwgeWE7XG5cbiAgICAvLyBzcGxpdCAncmVndWxhcicgYW5kICdvdmVybGF5aW5nJyBzdWJwbG90c1xuICAgIHZhciByZWd1bGFycyA9IFtdO1xuICAgIHZhciBvdmVybGF5cyA9IFtdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWQgPSBpZHNbaV07XG4gICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbaWRdO1xuICAgICAgICB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIHZhciB4YTIgPSB4YS5fbWFpbkF4aXM7XG4gICAgICAgIHZhciB5YTIgPSB5YS5fbWFpbkF4aXM7XG4gICAgICAgIHZhciBtYWlucGxvdCA9IHhhMi5faWQgKyB5YTIuX2lkO1xuICAgICAgICB2YXIgbWFpbnBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbbWFpbnBsb3RdO1xuICAgICAgICBwbG90aW5mby5vdmVybGF5cyA9IFtdO1xuXG4gICAgICAgIGlmKG1haW5wbG90ICE9PSBpZCAmJiBtYWlucGxvdGluZm8pIHtcbiAgICAgICAgICAgIHBsb3RpbmZvLm1haW5wbG90ID0gbWFpbnBsb3Q7XG4gICAgICAgICAgICBwbG90aW5mby5tYWlucGxvdGluZm8gPSBtYWlucGxvdGluZm87XG4gICAgICAgICAgICBvdmVybGF5cy5wdXNoKGlkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBsb3RpbmZvLm1haW5wbG90ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgcGxvdGluZm8ubWFpblBsb3RpbmZvID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmVndWxhcnMucHVzaChpZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaWxsIGluIGxpc3Qgb2Ygb3ZlcmxheWluZyBzdWJwbG90cyBpbiAnbWFpbiBwbG90J1xuICAgIGZvcihpID0gMDsgaSA8IG92ZXJsYXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlkID0gb3ZlcmxheXNbaV07XG4gICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbaWRdO1xuICAgICAgICBwbG90aW5mby5tYWlucGxvdGluZm8ub3ZlcmxheXMucHVzaChwbG90aW5mbyk7XG4gICAgfVxuXG4gICAgLy8gcHV0ICdyZWd1bGFyJyBzdWJwbG90IGRhdGEgYmVmb3JlICdvdmVybGF5aW5nJ1xuICAgIHZhciBzdWJwbG90SWRzID0gcmVndWxhcnMuY29uY2F0KG92ZXJsYXlzKTtcbiAgICB2YXIgc3VicGxvdERhdGEgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlkID0gc3VicGxvdElkc1tpXTtcbiAgICAgICAgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tpZF07XG4gICAgICAgIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgLy8gdXNlIGluZm8gYWJvdXQgYXhpcyBsYXllciBhbmQgb3ZlcmxheWluZyBwYXR0ZXJuXG4gICAgICAgIC8vIHRvIGNsZWFuIHdoYXQgbmVlZCB0byBiZSBjbGVhbmVkIHVwIGluIGV4aXQgc2VsZWN0aW9uXG4gICAgICAgIHZhciBkID0gW2lkLCB4YS5sYXllciwgeWEubGF5ZXIsIHhhLm92ZXJsYXlpbmcgfHwgJycsIHlhLm92ZXJsYXlpbmcgfHwgJyddO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBwbG90aW5mby5vdmVybGF5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgZC5wdXNoKHBsb3RpbmZvLm92ZXJsYXlzW2pdLmlkKTtcbiAgICAgICAgfVxuICAgICAgICBzdWJwbG90RGF0YVtpXSA9IGQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1YnBsb3REYXRhO1xufVxuXG5mdW5jdGlvbiBtYWtlU3VicGxvdExheWVyKGdkLCBwbG90aW5mbykge1xuICAgIHZhciBwbG90Z3JvdXAgPSBwbG90aW5mby5wbG90Z3JvdXA7XG4gICAgdmFyIGlkID0gcGxvdGluZm8uaWQ7XG4gICAgdmFyIHhMYXllciA9IGNvbnN0YW50cy5sYXllclZhbHVlMmxheWVyQ2xhc3NbcGxvdGluZm8ueGF4aXMubGF5ZXJdO1xuICAgIHZhciB5TGF5ZXIgPSBjb25zdGFudHMubGF5ZXJWYWx1ZTJsYXllckNsYXNzW3Bsb3RpbmZvLnlheGlzLmxheWVyXTtcbiAgICB2YXIgaGFzT25seUxhcmdlU3Bsb21zID0gZ2QuX2Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcztcblxuICAgIGlmKCFwbG90aW5mby5tYWlucGxvdCkge1xuICAgICAgICBpZihoYXNPbmx5TGFyZ2VTcGxvbXMpIHtcbiAgICAgICAgICAgIC8vIFRPRE8gY291bGQgZG8gZXZlbiBiZXR0ZXJcbiAgICAgICAgICAgIC8vIC0gd2UgZG9uJ3QgbmVlZCBwbG90IChidXQgd2Ugd291bGQgaGF2ZSB0byBtb2NrIGl0IGluIGxzSW5uZXJcbiAgICAgICAgICAgIC8vICAgYW5kIG90aGVyIHBsYWNlc1xuICAgICAgICAgICAgLy8gLSB3ZSBkb24ndCAoeHx5KWxpbmVzIGFuZCAoeHx5KWF4aXNsYXllciBmb3IgbW9zdCBzdWJwbG90c1xuICAgICAgICAgICAgLy8gICB1c3VhbGx5IGp1c3QgdGhlIGJvdHRvbSB4IGFuZCBsZWZ0IHkgYXhlcy5cbiAgICAgICAgICAgIHBsb3RpbmZvLnhsaW5lcyA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdwYXRoJywgJ3hsaW5lcy1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWxpbmVzID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ3BhdGgnLCAneWxpbmVzLWFib3ZlJyk7XG4gICAgICAgICAgICBwbG90aW5mby54YXhpc2xheWVyID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAneGF4aXNsYXllci1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWF4aXNsYXllciA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ3lheGlzbGF5ZXItYWJvdmUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBiYWNrTGF5ZXIgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdsYXllci1zdWJwbG90Jyk7XG4gICAgICAgICAgICBwbG90aW5mby5zaGFwZWxheWVyID0gZW5zdXJlU2luZ2xlKGJhY2tMYXllciwgJ2cnLCAnc2hhcGVsYXllcicpO1xuICAgICAgICAgICAgcGxvdGluZm8uaW1hZ2VsYXllciA9IGVuc3VyZVNpbmdsZShiYWNrTGF5ZXIsICdnJywgJ2ltYWdlbGF5ZXInKTtcblxuICAgICAgICAgICAgcGxvdGluZm8uZ3JpZGxheWVyID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnZ3JpZGxheWVyJyk7XG4gICAgICAgICAgICBwbG90aW5mby56ZXJvbGluZWxheWVyID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnemVyb2xpbmVsYXllcicpO1xuXG4gICAgICAgICAgICBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAncGF0aCcsICd4bGluZXMtYmVsb3cnKTtcbiAgICAgICAgICAgIGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdwYXRoJywgJ3lsaW5lcy1iZWxvdycpO1xuICAgICAgICAgICAgcGxvdGluZm8ub3ZlcmxpbmVzQmVsb3cgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdvdmVybGluZXMtYmVsb3cnKTtcblxuICAgICAgICAgICAgZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAneGF4aXNsYXllci1iZWxvdycpO1xuICAgICAgICAgICAgZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAneWF4aXNsYXllci1iZWxvdycpO1xuICAgICAgICAgICAgcGxvdGluZm8ub3ZlcmF4ZXNCZWxvdyA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ292ZXJheGVzLWJlbG93Jyk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnBsb3QgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdwbG90Jyk7XG4gICAgICAgICAgICBwbG90aW5mby5vdmVycGxvdCA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ292ZXJwbG90Jyk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnhsaW5lcyA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdwYXRoJywgJ3hsaW5lcy1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWxpbmVzID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ3BhdGgnLCAneWxpbmVzLWFib3ZlJyk7XG4gICAgICAgICAgICBwbG90aW5mby5vdmVybGluZXNBYm92ZSA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ292ZXJsaW5lcy1hYm92ZScpO1xuXG4gICAgICAgICAgICBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICd4YXhpc2xheWVyLWFib3ZlJyk7XG4gICAgICAgICAgICBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICd5YXhpc2xheWVyLWFib3ZlJyk7XG4gICAgICAgICAgICBwbG90aW5mby5vdmVyYXhlc0Fib3ZlID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnb3ZlcmF4ZXMtYWJvdmUnKTtcblxuICAgICAgICAgICAgLy8gc2V0IHJlZnMgdG8gY29ycmVjdCBsYXllcnMgYXMgZGV0ZXJtaW5lZCBieSAnYXhpcy5sYXllcidcbiAgICAgICAgICAgIHBsb3RpbmZvLnhsaW5lcyA9IHBsb3Rncm91cC5zZWxlY3QoJy54bGluZXMtJyArIHhMYXllcik7XG4gICAgICAgICAgICBwbG90aW5mby55bGluZXMgPSBwbG90Z3JvdXAuc2VsZWN0KCcueWxpbmVzLScgKyB5TGF5ZXIpO1xuICAgICAgICAgICAgcGxvdGluZm8ueGF4aXNsYXllciA9IHBsb3Rncm91cC5zZWxlY3QoJy54YXhpc2xheWVyLScgKyB4TGF5ZXIpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWF4aXNsYXllciA9IHBsb3Rncm91cC5zZWxlY3QoJy55YXhpc2xheWVyLScgKyB5TGF5ZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgbWFpbnBsb3RpbmZvID0gcGxvdGluZm8ubWFpbnBsb3RpbmZvO1xuICAgICAgICB2YXIgbWFpbnBsb3Rncm91cCA9IG1haW5wbG90aW5mby5wbG90Z3JvdXA7XG4gICAgICAgIHZhciB4SWQgPSBpZCArICcteCc7XG4gICAgICAgIHZhciB5SWQgPSBpZCArICcteSc7XG5cbiAgICAgICAgLy8gbm93IG1ha2UgdGhlIGNvbXBvbmVudHMgb2Ygb3ZlcmxhaWQgc3VicGxvdHNcbiAgICAgICAgLy8gb3ZlcmxheXMgZG9uJ3QgaGF2ZSBiYWNrZ3JvdW5kcywgYW5kIGFwcGVuZCBhbGxcbiAgICAgICAgLy8gdGhlaXIgb3RoZXIgY29tcG9uZW50cyB0byB0aGUgY29ycmVzcG9uZGluZ1xuICAgICAgICAvLyBleHRyYSBncm91cHMgb2YgdGhlaXIgbWFpbiBwbG90cy5cblxuICAgICAgICBwbG90aW5mby5ncmlkbGF5ZXIgPSBtYWlucGxvdGluZm8uZ3JpZGxheWVyO1xuICAgICAgICBwbG90aW5mby56ZXJvbGluZWxheWVyID0gbWFpbnBsb3RpbmZvLnplcm9saW5lbGF5ZXI7XG5cbiAgICAgICAgZW5zdXJlU2luZ2xlKG1haW5wbG90aW5mby5vdmVybGluZXNCZWxvdywgJ3BhdGgnLCB4SWQpO1xuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJsaW5lc0JlbG93LCAncGF0aCcsIHlJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmF4ZXNCZWxvdywgJ2cnLCB4SWQpO1xuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJheGVzQmVsb3csICdnJywgeUlkKTtcblxuICAgICAgICBwbG90aW5mby5wbG90ID0gZW5zdXJlU2luZ2xlKG1haW5wbG90aW5mby5vdmVycGxvdCwgJ2cnLCBpZCk7XG5cbiAgICAgICAgZW5zdXJlU2luZ2xlKG1haW5wbG90aW5mby5vdmVybGluZXNBYm92ZSwgJ3BhdGgnLCB4SWQpO1xuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJsaW5lc0Fib3ZlLCAncGF0aCcsIHlJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmF4ZXNBYm92ZSwgJ2cnLCB4SWQpO1xuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJheGVzQWJvdmUsICdnJywgeUlkKTtcblxuICAgICAgICAvLyBzZXQgcmVmcyB0byBjb3JyZWN0IGxheWVycyBhcyBkZXRlcm1pbmVkIGJ5ICdhYm92ZXRyYWNlcydcbiAgICAgICAgcGxvdGluZm8ueGxpbmVzID0gbWFpbnBsb3Rncm91cC5zZWxlY3QoJy5vdmVybGluZXMtJyArIHhMYXllcikuc2VsZWN0KCcuJyArIHhJZCk7XG4gICAgICAgIHBsb3RpbmZvLnlsaW5lcyA9IG1haW5wbG90Z3JvdXAuc2VsZWN0KCcub3ZlcmxpbmVzLScgKyB5TGF5ZXIpLnNlbGVjdCgnLicgKyB5SWQpO1xuICAgICAgICBwbG90aW5mby54YXhpc2xheWVyID0gbWFpbnBsb3Rncm91cC5zZWxlY3QoJy5vdmVyYXhlcy0nICsgeExheWVyKS5zZWxlY3QoJy4nICsgeElkKTtcbiAgICAgICAgcGxvdGluZm8ueWF4aXNsYXllciA9IG1haW5wbG90Z3JvdXAuc2VsZWN0KCcub3ZlcmF4ZXMtJyArIHlMYXllcikuc2VsZWN0KCcuJyArIHlJZCk7XG4gICAgfVxuXG4gICAgLy8gY29tbW9uIGF0dHJpYnV0ZXMgZm9yIGFsbCBzdWJwbG90cywgb3ZlcmxheXMgb3Igbm90XG5cbiAgICBpZighaGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgIGVuc3VyZVNpbmdsZUFuZEFkZERhdHVtKHBsb3RpbmZvLmdyaWRsYXllciwgJ2cnLCBwbG90aW5mby54YXhpcy5faWQpO1xuICAgICAgICBlbnN1cmVTaW5nbGVBbmRBZGREYXR1bShwbG90aW5mby5ncmlkbGF5ZXIsICdnJywgcGxvdGluZm8ueWF4aXMuX2lkKTtcbiAgICAgICAgcGxvdGluZm8uZ3JpZGxheWVyLnNlbGVjdEFsbCgnZycpXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF07IH0pXG4gICAgICAgICAgICAuc29ydChheGlzSWRzLmlkU29ydCk7XG4gICAgfVxuXG4gICAgcGxvdGluZm8ueGxpbmVzXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsICdub25lJylcbiAgICAgICAgLmNsYXNzZWQoJ2NyaXNwJywgdHJ1ZSk7XG5cbiAgICBwbG90aW5mby55bGluZXNcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCB0cnVlKTtcbn1cblxuZnVuY3Rpb24gcHVyZ2VTdWJwbG90TGF5ZXJzKGxheWVycywgZnVsbExheW91dCkge1xuICAgIGlmKCFsYXllcnMpIHJldHVybjtcblxuICAgIHZhciBvdmVybGF5SWRzVG9SZW1vdmUgPSB7fTtcblxuICAgIGxheWVycy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGlkID0gZFswXTtcbiAgICAgICAgdmFyIHBsb3Rncm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBwbG90Z3JvdXAucmVtb3ZlKCk7XG4gICAgICAgIHJlbW92ZVN1YnBsb3RFeHRyYXMoaWQsIGZ1bGxMYXlvdXQpO1xuICAgICAgICBvdmVybGF5SWRzVG9SZW1vdmVbaWRdID0gdHJ1ZTtcblxuICAgICAgICAvLyBkbyBub3QgcmVtb3ZlIGluZGl2aWR1YWwgYXhpcyA8Y2xpcFBhdGg+cyBoZXJlXG4gICAgICAgIC8vIGFzIG90aGVyIHN1YnBsb3RzIG1heSBuZWVkIHRoZW1cbiAgICB9KTtcblxuICAgIC8vIG11c3QgcmVtb3ZlIG92ZXJsYWlkIHN1YnBsb3QgdHJhY2UgbGF5ZXJzICdtYW51YWxseSdcblxuICAgIGZvcih2YXIgayBpbiBmdWxsTGF5b3V0Ll9wbG90cykge1xuICAgICAgICB2YXIgc3VicGxvdEluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1trXTtcbiAgICAgICAgdmFyIG92ZXJsYXlzID0gc3VicGxvdEluZm8ub3ZlcmxheXMgfHwgW107XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IG92ZXJsYXlzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgb3ZlcmxheUluZm8gPSBvdmVybGF5c1tqXTtcblxuICAgICAgICAgICAgaWYob3ZlcmxheUlkc1RvUmVtb3ZlW292ZXJsYXlJbmZvLmlkXSkge1xuICAgICAgICAgICAgICAgIG92ZXJsYXlJbmZvLnBsb3Quc2VsZWN0QWxsKCcudHJhY2UnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlU3VicGxvdEV4dHJhcyhzdWJwbG90SWQsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdWxsTGF5b3V0Ll9kcmFnZ2Vycy5zZWxlY3RBbGwoJ2cuJyArIHN1YnBsb3RJZCkucmVtb3ZlKCk7XG4gICAgZnVsbExheW91dC5fZGVmcy5zZWxlY3QoJyNjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIHN1YnBsb3RJZCArICdwbG90JykucmVtb3ZlKCk7XG59XG5cbmV4cG9ydHMudG9TVkcgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBpbWFnZVJvb3QgPSBnZC5fZnVsbExheW91dC5fZ2xpbWFnZXM7XG4gICAgdmFyIHJvb3QgPSBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnLnN2Zy1jb250YWluZXInKTtcbiAgICB2YXIgY2FudmFzZXMgPSByb290LmZpbHRlcihmdW5jdGlvbihkLCBpKSB7cmV0dXJuIGkgPT09IHJvb3Quc2l6ZSgpIC0gMTt9KVxuICAgICAgICAuc2VsZWN0QWxsKCcuZ2wtY2FudmFzLWNvbnRleHQsIC5nbC1jYW52YXMtZm9jdXMnKTtcblxuICAgIGZ1bmN0aW9uIGNhbnZhc1RvSW1hZ2UoKSB7XG4gICAgICAgIHZhciBjYW52YXMgPSB0aGlzO1xuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGltYWdlUm9vdC5hcHBlbmQoJ3N2ZzppbWFnZScpO1xuXG4gICAgICAgIGltYWdlLmF0dHIoe1xuICAgICAgICAgICAgeG1sbnM6IHhtbG5zTmFtZXNwYWNlcy5zdmcsXG4gICAgICAgICAgICAneGxpbms6aHJlZic6IGltYWdlRGF0YSxcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICdub25lJyxcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgd2lkdGg6IGNhbnZhcy53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogY2FudmFzLmhlaWdodFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjYW52YXNlcy5lYWNoKGNhbnZhc1RvSW1hZ2UpO1xufTtcblxuZXhwb3J0cy51cGRhdGVGeCA9IHJlcXVpcmUoJy4vZ3JhcGhfaW50ZXJhY3QnKS51cGRhdGVGeDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKTtcbnZhciBkYXNoID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXMnKS5kYXNoO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcblxudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgdmlzaWJsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aXRsZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpdGxlZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAvLyAnLScgbWVhbnMgd2UgaGF2ZW4ndCB5ZXQgcnVuIGF1dG90eXBlIG9yIGNvdWxkbid0IGZpbmQgYW55IGRhdGFcbiAgICAgICAgLy8gaXQgZ2V0cyB0dXJuZWQgaW50byBsaW5lYXIgaW4gZ2QuX2Z1bGxMYXlvdXQgYnV0IG5vdCBjb3BpZWQgYmFja1xuICAgICAgICAvLyB0byBnZC5kYXRhIGxpa2UgdGhlIG90aGVycyBhcmUuXG4gICAgICAgIHZhbHVlczogWyctJywgJ2xpbmVhcicsICdsb2cnLCAnZGF0ZScsICdjYXRlZ29yeSddLFxuICAgICAgICBkZmx0OiAnLScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAvLyB3ZSBmb3JnZXQgd2hlbiBhbiBheGlzIGhhcyBiZWVuIGF1dG90eXBlZCwganVzdCB3cml0aW5nIHRoZSBhdXRvXG4gICAgICAgIC8vIHZhbHVlIGJhY2sgdG8gdGhlIGlucHV0IC0gc28gaXQgZG9lc24ndCBtYWtlIHNlbnNlIHRvIHRlbXBsYXRlIHRoaXMuXG4gICAgICAgIC8vIE5vdGU6IHdlIGRvIE5PVCBwcm9oaWJpdCB0aGlzIGluIGBjb2VyY2VgLCBzbyBpZiBzb21lb25lIGVudGVycyBhXG4gICAgICAgIC8vIHR5cGUgaW4gdGhlIHRlbXBsYXRlIGV4cGxpY2l0bHkgaXQgd2lsbCBiZSBob25vcmVkIGFzIHRoZSBkZWZhdWx0LlxuICAgICAgICBfbm9UZW1wbGF0aW5nOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGF1dG9yYW5nZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW3RydWUsIGZhbHNlLCAncmV2ZXJzZWQnXSxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXhyYW5nZScsXG4gICAgICAgIGltcGxpZWRFZGl0czogeydyYW5nZVswXSc6IHVuZGVmaW5lZCwgJ3JhbmdlWzFdJzogdW5kZWZpbmVkfSxcbiAgICAgICAgXG4gICAgfSxcbiAgICByYW5nZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9ybWFsJywgJ3RvemVybycsICdub25uZWdhdGl2ZSddLFxuICAgICAgICBkZmx0OiAnbm9ybWFsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdheHJhbmdlJywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX0sIGFuaW06IHRydWV9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ2F4cmFuZ2UnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfSwgYW5pbTogdHJ1ZX1cbiAgICAgICAgXSxcbiAgICAgICAgZWRpdFR5cGU6ICdheHJhbmdlJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7J2F1dG9yYW5nZSc6IGZhbHNlfSxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmaXhlZHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIHNjYWxlYW5jaG9yOiBub3QgdXNlZCBkaXJlY3RseSwganVzdCBwdXQgaGVyZSBmb3IgcmVmZXJlbmNlXG4gICAgLy8gdmFsdWVzIGFyZSBhbnkgb3Bwb3NpdGUtbGV0dGVyIGF4aXMgaWRcbiAgICBzY2FsZWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueC50b1N0cmluZygpLFxuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNjYWxlcmF0aW86IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29uc3RyYWluOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3JhbmdlJywgJ2RvbWFpbiddLFxuICAgICAgICBkZmx0OiAncmFuZ2UnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBjb25zdHJhaW50b3dhcmQ6IG5vdCB1c2VkIGRpcmVjdGx5LCBqdXN0IHB1dCBoZXJlIGZvciByZWZlcmVuY2VcbiAgICBjb25zdHJhaW50b3dhcmQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gdGlja3NcbiAgICB0aWNrbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ2xpbmVhcicsICdhcnJheSddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge3RpY2swOiB1bmRlZmluZWQsIGR0aWNrOiB1bmRlZmluZWR9LFxuICAgICAgICBcbiAgICB9LFxuICAgIG50aWNrczoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2swOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge3RpY2ttb2RlOiAnbGluZWFyJ30sXG4gICAgICAgIFxuICAgIH0sXG4gICAgZHRpY2s6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7dGlja21vZGU6ICdsaW5lYXInfSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrdmFsczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2t0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3M6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnb3V0c2lkZScsICdpbnNpZGUnLCAnJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaXJyb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFt0cnVlLCAndGlja3MnLCBmYWxzZSwgJ2FsbCcsICdhbGx0aWNrcyddLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MrbGF5b3V0c3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tsZW46IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogNSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2t3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93dGlja2xhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhdXRvbWFyZ2luOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93c3Bpa2VzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwaWtlY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3Bpa2V0aGlja25lc3M6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwaWtlZGFzaDogZXh0ZW5kRmxhdCh7fSwgZGFzaCwge2RmbHQ6ICdkYXNoJywgZWRpdFR5cGU6ICdub25lJ30pLFxuICAgIHNwaWtlbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWyd0b2F4aXMnLCAnYWNyb3NzJywgJ21hcmtlciddLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3RvYXhpcycsXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3Bpa2VzbmFwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2RhdGEnLCAnY3Vyc29yJ10sXG4gICAgICAgIGRmbHQ6ICdkYXRhJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2ZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICB0aWNrYW5nbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3ByZWZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93dGlja3ByZWZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhbGwnLCAnZmlyc3QnLCAnbGFzdCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3N1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93dGlja3N1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhbGwnLCAnZmlyc3QnLCAnbGFzdCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2V4cG9uZW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdmaXJzdCcsICdsYXN0JywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2FsbCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleHBvbmVudGZvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydub25lJywgJ2UnLCAnRScsICdwb3dlcicsICdTSScsICdCJ10sXG4gICAgICAgIGRmbHQ6ICdCJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNlcGFyYXRldGhvdXNhbmRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb3JtYXRzdG9wczogdGVtcGxhdGVkQXJyYXkoJ3RpY2tmb3JtYXRzdG9wJywge1xuICAgICAgICBlbmFibGVkOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkdGlja3JhbmdlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3RpY2tzJ30sXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3RpY2tzJ31cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcydcbiAgICB9KSxcbiAgICBob3ZlcmZvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIGxpbmVzIGFuZCBncmlkc1xuICAgIHNob3dsaW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzK2xheW91dHN0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsaW5lY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmV3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcytsYXlvdXRzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2dyaWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMubGlnaHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6ZXJvbGluZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6ZXJvbGluZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6ZXJvbGluZXdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gcG9zaXRpb25pbmcgYXR0cmlidXRlc1xuICAgIC8vIGFuY2hvcjogbm90IHVzZWQgZGlyZWN0bHksIGp1c3QgcHV0IGhlcmUgZm9yIHJlZmVyZW5jZVxuICAgIC8vIHZhbHVlcyBhcmUgYW55IG9wcG9zaXRlLWxldHRlciBheGlzIGlkXG4gICAgYW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAnZnJlZScsXG4gICAgICAgICAgICBjb25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBjb25zdGFudHMuaWRSZWdleC55LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gc2lkZTogbm90IHVzZWQgZGlyZWN0bHksIGFzIHZhbHVlcyBkZXBlbmQgb24gZGlyZWN0aW9uXG4gICAgLy8gdmFsdWVzIGFyZSB0b3AsIGJvdHRvbSBmb3IgeCBheGVzLCBhbmQgbGVmdCwgcmlnaHQgZm9yIHlcbiAgICBzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvcCcsICdib3R0b20nLCAnbGVmdCcsICdyaWdodCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBvdmVybGF5aW5nOiBub3QgdXNlZCBkaXJlY3RseSwganVzdCBwdXQgaGVyZSBmb3IgcmVmZXJlbmNlXG4gICAgLy8gdmFsdWVzIGFyZSBmYWxzZSBhbmQgYW55IG90aGVyIHNhbWUtbGV0dGVyIGF4aXMgaWQgdGhhdCdzIG5vdFxuICAgIC8vIGl0c2VsZiBvdmVybGF5aW5nIGFueXRoaW5nXG4gICAgb3ZlcmxheWluZzoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ2ZyZWUnLFxuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueC50b1N0cmluZygpLFxuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxheWVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2Fib3ZlIHRyYWNlcycsICdiZWxvdyB0cmFjZXMnXSxcbiAgICAgICAgZGZsdDogJ2Fib3ZlIHRyYWNlcycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRvbWFpbjoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBtaW46IDAsIG1heDogMSwgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIG1pbjogMCwgbWF4OiAxLCBlZGl0VHlwZTogJ3Bsb3QnfVxuICAgICAgICBdLFxuICAgICAgICBkZmx0OiBbMCwgMV0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcG9zaXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjYXRlZ29yeW9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAndHJhY2UnLCAnY2F0ZWdvcnkgYXNjZW5kaW5nJywgJ2NhdGVnb3J5IGRlc2NlbmRpbmcnLCAnYXJyYXknXG4gICAgICAgICAgICAvKiAsICd2YWx1ZSBhc2NlbmRpbmcnLCAndmFsdWUgZGVzY2VuZGluZycqLyAvLyB2YWx1ZSBhc2NlbmRpbmcgLyBkZXNjZW5kaW5nIHRvIGJlIGltcGxlbWVudGVkIGxhdGVyXG4gICAgICAgIF0sXG4gICAgICAgIGRmbHQ6ICd0cmFjZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNhdGVnb3J5YXJyYXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgYXV0b3RpY2s6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIFRlbXBsYXRlID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIGJhc2VQbG90TGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZVR5cGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4vdHlwZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUF4aXNEZWZhdWx0cyA9IHJlcXVpcmUoJy4vYXhpc19kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyA9IHJlcXVpcmUoJy4vY29uc3RyYWludF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVBvc2l0aW9uRGVmYXVsdHMgPSByZXF1aXJlKCcuL3Bvc2l0aW9uX2RlZmF1bHRzJyk7XG5cbnZhciBheGlzSWRzID0gcmVxdWlyZSgnLi9heGlzX2lkcycpO1xudmFyIGlkMm5hbWUgPSBheGlzSWRzLmlkMm5hbWU7XG52YXIgbmFtZTJpZCA9IGF4aXNJZHMubmFtZTJpZDtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciB0cmFjZUlzID0gUmVnaXN0cnkudHJhY2VJcztcbnZhciBnZXRDb21wb25lbnRNZXRob2QgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2Q7XG5cbmZ1bmN0aW9uIGFwcGVuZExpc3QoY29udCwgaywgaXRlbSkge1xuICAgIGlmKEFycmF5LmlzQXJyYXkoY29udFtrXSkpIGNvbnRba10ucHVzaChpdGVtKTtcbiAgICBlbHNlIGNvbnRba10gPSBbaXRlbV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICB2YXIgYXgydHJhY2VzID0ge307XG4gICAgdmFyIHhhQ2hlYXRlciA9IHt9O1xuICAgIHZhciB4YU5vbkNoZWF0ZXIgPSB7fTtcbiAgICB2YXIgb3V0ZXJUaWNrcyA9IHt9O1xuICAgIHZhciBub0dyaWRzID0ge307XG4gICAgdmFyIGksIGo7XG5cbiAgICAvLyBsb29rIGZvciBheGVzIGluIHRoZSBkYXRhXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIGlmKCF0cmFjZUlzKHRyYWNlLCAnY2FydGVzaWFuJykgJiYgIXRyYWNlSXModHJhY2UsICdnbDJkJykpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB4YU5hbWU7XG4gICAgICAgIGlmKHRyYWNlLnhheGlzKSB7XG4gICAgICAgICAgICB4YU5hbWUgPSBpZDJuYW1lKHRyYWNlLnhheGlzKTtcbiAgICAgICAgICAgIGFwcGVuZExpc3QoYXgydHJhY2VzLCB4YU5hbWUsIHRyYWNlKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnhheGVzKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB0cmFjZS54YXhlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGFwcGVuZExpc3QoYXgydHJhY2VzLCBpZDJuYW1lKHRyYWNlLnhheGVzW2pdKSwgdHJhY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHlhTmFtZTtcbiAgICAgICAgaWYodHJhY2UueWF4aXMpIHtcbiAgICAgICAgICAgIHlhTmFtZSA9IGlkMm5hbWUodHJhY2UueWF4aXMpO1xuICAgICAgICAgICAgYXBwZW5kTGlzdChheDJ0cmFjZXMsIHlhTmFtZSwgdHJhY2UpO1xuICAgICAgICB9IGVsc2UgaWYodHJhY2UueWF4ZXMpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHRyYWNlLnlheGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgYXBwZW5kTGlzdChheDJ0cmFjZXMsIGlkMm5hbWUodHJhY2UueWF4ZXNbal0pLCB0cmFjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUd28gdGhpbmdzIHRyaWdnZXIgYXhpcyB2aXNpYmlsaXR5OlxuICAgICAgICAvLyAxLiBpcyBub3QgY2FycGV0XG4gICAgICAgIC8vIDIuIGNhcnBldCB0aGF0J3Mgbm90IGNoZWF0ZXJcbiAgICAgICAgaWYoIXRyYWNlSXModHJhY2UsICdjYXJwZXQnKSB8fCAodHJhY2UudHlwZSA9PT0gJ2NhcnBldCcgJiYgIXRyYWNlLl9jaGVhdGVyKSkge1xuICAgICAgICAgICAgaWYoeGFOYW1lKSB4YU5vbkNoZWF0ZXJbeGFOYW1lXSA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgYWJvdmUgY2hlY2sgZm9yIGRlZmluaXRlbHktbm90LWNoZWF0ZXIgaXMgbm90IGFkZXF1YXRlLiBUaGlzXG4gICAgICAgIC8vIHNlY29uZCBsaXN0IHRyYWNrcyB3aGljaCBheGVzICpjb3VsZCogYmUgYSBjaGVhdGVyIHNvIHRoYXQgdGhlXG4gICAgICAgIC8vIGZ1bGwgY29uZGl0aW9uIHRyaWdnZXJpbmcgaGlkaW5nIGlzOlxuICAgICAgICAvLyAgICpjb3VsZCogYmUgYSBjaGVhdGVyIGFuZCAqaXMgbm90IGRlZmluaXRlbHkgdmlzaWJsZSpcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2NhcnBldCcgJiYgdHJhY2UuX2NoZWF0ZXIpIHtcbiAgICAgICAgICAgIGlmKHhhTmFtZSkgeGFDaGVhdGVyW3hhTmFtZV0gPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2hlY2sgZm9yIGRlZmF1bHQgZm9ybWF0dGluZyB0d2Vha3NcbiAgICAgICAgaWYodHJhY2VJcyh0cmFjZSwgJzJkTWFwJykpIHtcbiAgICAgICAgICAgIG91dGVyVGlja3NbeGFOYW1lXSA9IDE7XG4gICAgICAgICAgICBvdXRlclRpY2tzW3lhTmFtZV0gPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHJhY2VJcyh0cmFjZSwgJ29yaWVudGVkJykpIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbkF4aXMgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8geWFOYW1lIDogeGFOYW1lO1xuICAgICAgICAgICAgbm9Hcmlkc1twb3NpdGlvbkF4aXNdID0gMTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzdWJwbG90cyA9IGxheW91dE91dC5fc3VicGxvdHM7XG4gICAgdmFyIHhJZHMgPSBzdWJwbG90cy54YXhpcztcbiAgICB2YXIgeUlkcyA9IHN1YnBsb3RzLnlheGlzO1xuICAgIHZhciB4TmFtZXMgPSBMaWIuc2ltcGxlTWFwKHhJZHMsIGlkMm5hbWUpO1xuICAgIHZhciB5TmFtZXMgPSBMaWIuc2ltcGxlTWFwKHlJZHMsIGlkMm5hbWUpO1xuICAgIHZhciBheE5hbWVzID0geE5hbWVzLmNvbmNhdCh5TmFtZXMpO1xuXG4gICAgLy8gcGxvdF9iZ2NvbG9yIG9ubHkgbWFrZXMgc2Vuc2UgaWYgdGhlcmUncyBhICgyRCkgcGxvdCFcbiAgICAvLyBUT0RPOiBiZ2NvbG9yIGZvciBlYWNoIHN1YnBsb3QsIHRvIGluaGVyaXQgZnJvbSB0aGUgbWFpbiBvbmVcbiAgICB2YXIgcGxvdF9iZ2NvbG9yID0gQ29sb3IuYmFja2dyb3VuZDtcbiAgICBpZih4SWRzLmxlbmd0aCAmJiB5SWRzLmxlbmd0aCkge1xuICAgICAgICBwbG90X2JnY29sb3IgPSBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGJhc2VQbG90TGF5b3V0QXR0cmlidXRlcywgJ3Bsb3RfYmdjb2xvcicpO1xuICAgIH1cblxuICAgIHZhciBiZ0NvbG9yID0gQ29sb3IuY29tYmluZShwbG90X2JnY29sb3IsIGxheW91dE91dC5wYXBlcl9iZ2NvbG9yKTtcblxuICAgIHZhciBheE5hbWUsIGF4TGV0dGVyLCBheExheW91dEluLCBheExheW91dE91dDtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGF4TGF5b3V0SW4sIGF4TGF5b3V0T3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UyKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UyKGF4TGF5b3V0SW4sIGF4TGF5b3V0T3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDb3VudGVyQXhlcyhheExldHRlcikge1xuICAgICAgICByZXR1cm4gKGF4TGV0dGVyID09PSAneCcpID8geUlkcyA6IHhJZHM7XG4gICAgfVxuXG4gICAgdmFyIGNvdW50ZXJBeGVzID0ge3g6IGdldENvdW50ZXJBeGVzKCd4JyksIHk6IGdldENvdW50ZXJBeGVzKCd5Jyl9O1xuXG4gICAgZnVuY3Rpb24gZ2V0T3ZlcmxheWFibGVBeGVzKGF4TGV0dGVyLCBheE5hbWUpIHtcbiAgICAgICAgdmFyIGxpc3QgPSAoYXhMZXR0ZXIgPT09ICd4JykgPyB4TmFtZXMgOiB5TmFtZXM7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgbGlzdC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGF4TmFtZTIgPSBsaXN0W2pdO1xuXG4gICAgICAgICAgICBpZihheE5hbWUyICE9PSBheE5hbWUgJiYgIShsYXlvdXRJbltheE5hbWUyXSB8fCB7fSkub3ZlcmxheWluZykge1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKG5hbWUyaWQoYXhOYW1lMikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyBmaXJzdCBwYXNzIGNyZWF0ZXMgdGhlIGNvbnRhaW5lcnMsIGRldGVybWluZXMgdHlwZXMsIGFuZCBoYW5kbGVzIG1vc3Qgb2YgdGhlIHNldHRpbmdzXG4gICAgZm9yKGkgPSAwOyBpIDwgYXhOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBheE5hbWUgPSBheE5hbWVzW2ldO1xuICAgICAgICBheExldHRlciA9IGF4TmFtZS5jaGFyQXQoMCk7XG5cbiAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGxheW91dEluW2F4TmFtZV0pKSB7XG4gICAgICAgICAgICBsYXlvdXRJbltheE5hbWVdID0ge307XG4gICAgICAgIH1cblxuICAgICAgICBheExheW91dEluID0gbGF5b3V0SW5bYXhOYW1lXTtcbiAgICAgICAgYXhMYXlvdXRPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIobGF5b3V0T3V0LCBheE5hbWUsIGF4TGV0dGVyICsgJ2F4aXMnKTtcblxuICAgICAgICB2YXIgdHJhY2VzID0gYXgydHJhY2VzW2F4TmFtZV0gfHwgW107XG4gICAgICAgIGF4TGF5b3V0T3V0Ll90cmFjZUluZGljZXMgPSB0cmFjZXMubWFwKGZ1bmN0aW9uKHQpIHsgcmV0dXJuIHQuX2V4cGFuZGVkSW5kZXg7IH0pO1xuICAgICAgICBheExheW91dE91dC5fYW5uSW5kaWNlcyA9IFtdO1xuICAgICAgICBheExheW91dE91dC5fc2hhcGVJbmRpY2VzID0gW107XG5cbiAgICAgICAgLy8gc2V0IHVwIHNvbWUgcHJpdmF0ZSBwcm9wZXJ0aWVzXG4gICAgICAgIGF4TGF5b3V0T3V0Ll9uYW1lID0gYXhOYW1lO1xuICAgICAgICB2YXIgaWQgPSBheExheW91dE91dC5faWQgPSBuYW1lMmlkKGF4TmFtZSk7XG5cbiAgICAgICAgdmFyIG92ZXJsYXlhYmxlQXhlcyA9IGdldE92ZXJsYXlhYmxlQXhlcyhheExldHRlciwgYXhOYW1lKTtcblxuICAgICAgICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgICAgICAgICBsZXR0ZXI6IGF4TGV0dGVyLFxuICAgICAgICAgICAgZm9udDogbGF5b3V0T3V0LmZvbnQsXG4gICAgICAgICAgICBvdXRlclRpY2tzOiBvdXRlclRpY2tzW2F4TmFtZV0sXG4gICAgICAgICAgICBzaG93R3JpZDogIW5vR3JpZHNbYXhOYW1lXSxcbiAgICAgICAgICAgIGRhdGE6IHRyYWNlcyxcbiAgICAgICAgICAgIGJnQ29sb3I6IGJnQ29sb3IsXG4gICAgICAgICAgICBjYWxlbmRhcjogbGF5b3V0T3V0LmNhbGVuZGFyLFxuICAgICAgICAgICAgYXV0b21hcmdpbjogdHJ1ZSxcbiAgICAgICAgICAgIGNoZWF0ZXJvbmx5OiBheExldHRlciA9PT0gJ3gnICYmIHhhQ2hlYXRlcltheE5hbWVdICYmICF4YU5vbkNoZWF0ZXJbYXhOYW1lXSxcbiAgICAgICAgICAgIHNwbG9tU3Rhc2g6ICgobGF5b3V0T3V0Ll9zcGxvbUF4ZXMgfHwge30pW2F4TGV0dGVyXSB8fCB7fSlbaWRdXG4gICAgICAgIH07XG5cbiAgICAgICAgaGFuZGxlVHlwZURlZmF1bHRzKGF4TGF5b3V0SW4sIGF4TGF5b3V0T3V0LCBjb2VyY2UsIGRlZmF1bHRPcHRpb25zKTtcbiAgICAgICAgaGFuZGxlQXhpc0RlZmF1bHRzKGF4TGF5b3V0SW4sIGF4TGF5b3V0T3V0LCBjb2VyY2UsIGRlZmF1bHRPcHRpb25zLCBsYXlvdXRPdXQpO1xuXG4gICAgICAgIHZhciBzcGlrZWNvbG9yID0gY29lcmNlMignc3Bpa2Vjb2xvcicpLFxuICAgICAgICAgICAgc3Bpa2V0aGlja25lc3MgPSBjb2VyY2UyKCdzcGlrZXRoaWNrbmVzcycpLFxuICAgICAgICAgICAgc3Bpa2VkYXNoID0gY29lcmNlMignc3Bpa2VkYXNoJyksXG4gICAgICAgICAgICBzcGlrZW1vZGUgPSBjb2VyY2UyKCdzcGlrZW1vZGUnKSxcbiAgICAgICAgICAgIHNwaWtlc25hcCA9IGNvZXJjZTIoJ3NwaWtlc25hcCcpLFxuICAgICAgICAgICAgc2hvd1NwaWtlcyA9IGNvZXJjZSgnc2hvd3NwaWtlcycsICEhc3Bpa2Vjb2xvciB8fCAhIXNwaWtldGhpY2tuZXNzIHx8ICEhc3Bpa2VkYXNoIHx8ICEhc3Bpa2Vtb2RlIHx8ICEhc3Bpa2VzbmFwKTtcblxuICAgICAgICBpZighc2hvd1NwaWtlcykge1xuICAgICAgICAgICAgZGVsZXRlIGF4TGF5b3V0T3V0LnNwaWtlY29sb3I7XG4gICAgICAgICAgICBkZWxldGUgYXhMYXlvdXRPdXQuc3Bpa2V0aGlja25lc3M7XG4gICAgICAgICAgICBkZWxldGUgYXhMYXlvdXRPdXQuc3Bpa2VkYXNoO1xuICAgICAgICAgICAgZGVsZXRlIGF4TGF5b3V0T3V0LnNwaWtlbW9kZTtcbiAgICAgICAgICAgIGRlbGV0ZSBheExheW91dE91dC5zcGlrZXNuYXA7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9zaXRpb25pbmdPcHRpb25zID0ge1xuICAgICAgICAgICAgbGV0dGVyOiBheExldHRlcixcbiAgICAgICAgICAgIGNvdW50ZXJBeGVzOiBjb3VudGVyQXhlc1theExldHRlcl0sXG4gICAgICAgICAgICBvdmVybGF5YWJsZUF4ZXM6IG92ZXJsYXlhYmxlQXhlcyxcbiAgICAgICAgICAgIGdyaWQ6IGxheW91dE91dC5ncmlkXG4gICAgICAgIH07XG5cbiAgICAgICAgaGFuZGxlUG9zaXRpb25EZWZhdWx0cyhheExheW91dEluLCBheExheW91dE91dCwgY29lcmNlLCBwb3NpdGlvbmluZ09wdGlvbnMpO1xuXG4gICAgICAgIGF4TGF5b3V0T3V0Ll9pbnB1dCA9IGF4TGF5b3V0SW47XG4gICAgfVxuXG4gICAgLy8gcXVpY2sgc2Vjb25kIHBhc3MgZm9yIHJhbmdlIHNsaWRlciBhbmQgc2VsZWN0b3IgZGVmYXVsdHNcbiAgICB2YXIgcmFuZ2VTbGlkZXJEZWZhdWx0cyA9IGdldENvbXBvbmVudE1ldGhvZCgncmFuZ2VzbGlkZXInLCAnaGFuZGxlRGVmYXVsdHMnKTtcbiAgICB2YXIgcmFuZ2VTZWxlY3RvckRlZmF1bHRzID0gZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNlbGVjdG9yJywgJ2hhbmRsZURlZmF1bHRzJyk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB4TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXhOYW1lID0geE5hbWVzW2ldO1xuICAgICAgICBheExheW91dEluID0gbGF5b3V0SW5bYXhOYW1lXTtcbiAgICAgICAgYXhMYXlvdXRPdXQgPSBsYXlvdXRPdXRbYXhOYW1lXTtcblxuICAgICAgICByYW5nZVNsaWRlckRlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGF4TmFtZSk7XG5cbiAgICAgICAgaWYoYXhMYXlvdXRPdXQudHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgICAgICByYW5nZVNlbGVjdG9yRGVmYXVsdHMoXG4gICAgICAgICAgICAgICAgYXhMYXlvdXRJbixcbiAgICAgICAgICAgICAgICBheExheW91dE91dCxcbiAgICAgICAgICAgICAgICBsYXlvdXRPdXQsXG4gICAgICAgICAgICAgICAgeU5hbWVzLFxuICAgICAgICAgICAgICAgIGF4TGF5b3V0T3V0LmNhbGVuZGFyXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29lcmNlKCdmaXhlZHJhbmdlJyk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgeU5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4TmFtZSA9IHlOYW1lc1tpXTtcbiAgICAgICAgYXhMYXlvdXRJbiA9IGxheW91dEluW2F4TmFtZV07XG4gICAgICAgIGF4TGF5b3V0T3V0ID0gbGF5b3V0T3V0W2F4TmFtZV07XG5cbiAgICAgICAgdmFyIGFuY2hvcmVkQXhpcyA9IGxheW91dE91dFtpZDJuYW1lKGF4TGF5b3V0T3V0LmFuY2hvcildO1xuXG4gICAgICAgIHZhciBmaXhlZFJhbmdlRGZsdCA9IChcbiAgICAgICAgICAgIGFuY2hvcmVkQXhpcyAmJlxuICAgICAgICAgICAgYW5jaG9yZWRBeGlzLnJhbmdlc2xpZGVyICYmXG4gICAgICAgICAgICBhbmNob3JlZEF4aXMucmFuZ2VzbGlkZXIudmlzaWJsZVxuICAgICAgICApO1xuXG4gICAgICAgIGNvZXJjZSgnZml4ZWRyYW5nZScsIGZpeGVkUmFuZ2VEZmx0KTtcbiAgICB9XG5cbiAgICAvLyBGaW5hbGx5LCBoYW5kbGUgc2NhbGUgY29uc3RyYWludHMuIFdlIG5lZWQgdG8gZG8gdGhpcyBhZnRlciBhbGwgYXhlcyBoYXZlXG4gICAgLy8gY29lcmNlZCBib3RoIGB0eXBlYCAoc28gd2UgbGluayBvbmx5IGF4ZXMgb2YgdGhlIHNhbWUgdHlwZSkgYW5kXG4gICAgLy8gYGZpeGVkcmFuZ2VgIChzbyB3ZSBjYW4gYXZvaWQgbGlua2luZyBmcm9tIE9SIFRPIGEgZml4ZWQgYXhpcykuXG5cbiAgICAvLyBzZXRzIG9mIGF4ZXMgbGlua2VkIGJ5IGBzY2FsZWFuY2hvcmAgYWxvbmcgd2l0aCB0aGUgc2NhbGVyYXRpb3MgY29tcG91bmRlZFxuICAgIC8vIHRvZ2V0aGVyLCBwb3B1bGF0ZWQgaW4gaGFuZGxlQ29uc3RyYWludERlZmF1bHRzXG4gICAgbGF5b3V0T3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcyA9IFtdO1xuICAgIHZhciBhbGxBeGlzSWRzID0gY291bnRlckF4ZXMueC5jb25jYXQoY291bnRlckF4ZXMueSk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBheE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4TmFtZSA9IGF4TmFtZXNbaV07XG4gICAgICAgIGF4TGV0dGVyID0gYXhOYW1lLmNoYXJBdCgwKTtcblxuICAgICAgICBheExheW91dEluID0gbGF5b3V0SW5bYXhOYW1lXTtcbiAgICAgICAgYXhMYXlvdXRPdXQgPSBsYXlvdXRPdXRbYXhOYW1lXTtcblxuICAgICAgICBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHMoYXhMYXlvdXRJbiwgYXhMYXlvdXRPdXQsIGNvZXJjZSwgYWxsQXhpc0lkcywgbGF5b3V0T3V0KTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JNaXggPSByZXF1aXJlKCd0aW55Y29sb3IyJykubWl4O1xudmFyIGxpZ2h0RnJhY3Rpb24gPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKS5saWdodEZyYWN0aW9uO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG4vKipcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIDpcbiAqICAgLSBkZmx0Q29sb3Ige3N0cmluZ30gOiBkZWZhdWx0IGF4aXMgY29sb3JcbiAqICAgLSBiZ0NvbG9yIHtzdHJpbmd9IDogY29tYmluZWQgc3VicGxvdCBiZyBjb2xvclxuICogICAtIGJsZW5kIHtudW1iZXIsIG9wdGlvbmFsfSA6IGJsZW5kIHBlcmNlbnRhZ2UgKHRvIGNvbXB1dGUgZGZsdCBncmlkIGNvbG9yKVxuICogICAtIHNob3dMaW5lIHtib29sZWFufSA6IHNob3cgbGluZSBieSBkZWZhdWx0XG4gKiAgIC0gc2hvd0dyaWQge2Jvb2xlYW59IDogc2hvdyBncmlkIGJ5IGRlZmF1bHRcbiAqICAgLSBub1plcm9MaW5lIHtib29sZWFufSA6IGRvbid0IGNvZXJjZSB6ZXJvbGluZSogYXR0cmlidXRlc1xuICogICAtIGF0dHJpYnV0ZXMge29iamVjdH0gOiBhdHRyaWJ1dGUgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCBpbnB1dCBjb250YWluZXJzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlTGluZUdyaWREZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBkZmx0Q29sb3IgPSBvcHRzLmRmbHRDb2xvcjtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZTIoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZTIoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgb3B0cy5hdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlMignbGluZWNvbG9yJywgZGZsdENvbG9yKTtcbiAgICB2YXIgbGluZVdpZHRoID0gY29lcmNlMignbGluZXdpZHRoJyk7XG4gICAgdmFyIHNob3dMaW5lID0gY29lcmNlKCdzaG93bGluZScsIG9wdHMuc2hvd0xpbmUgfHwgISFsaW5lQ29sb3IgfHwgISFsaW5lV2lkdGgpO1xuXG4gICAgaWYoIXNob3dMaW5lKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQubGluZWNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmxpbmV3aWR0aDtcbiAgICB9XG5cbiAgICB2YXIgZ3JpZENvbG9yRGZsdCA9IGNvbG9yTWl4KGRmbHRDb2xvciwgb3B0cy5iZ0NvbG9yLCBvcHRzLmJsZW5kIHx8IGxpZ2h0RnJhY3Rpb24pLnRvUmdiU3RyaW5nKCk7XG4gICAgdmFyIGdyaWRDb2xvciA9IGNvZXJjZTIoJ2dyaWRjb2xvcicsIGdyaWRDb2xvckRmbHQpO1xuICAgIHZhciBncmlkV2lkdGggPSBjb2VyY2UyKCdncmlkd2lkdGgnKTtcbiAgICB2YXIgc2hvd0dyaWRMaW5lcyA9IGNvZXJjZSgnc2hvd2dyaWQnLCBvcHRzLnNob3dHcmlkIHx8ICEhZ3JpZENvbG9yIHx8ICEhZ3JpZFdpZHRoKTtcblxuICAgIGlmKCFzaG93R3JpZExpbmVzKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZGNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmdyaWR3aWR0aDtcbiAgICB9XG5cbiAgICBpZighb3B0cy5ub1plcm9MaW5lKSB7XG4gICAgICAgIHZhciB6ZXJvTGluZUNvbG9yID0gY29lcmNlMignemVyb2xpbmVjb2xvcicsIGRmbHRDb2xvcik7XG4gICAgICAgIHZhciB6ZXJvTGluZVdpZHRoID0gY29lcmNlMignemVyb2xpbmV3aWR0aCcpO1xuICAgICAgICB2YXIgc2hvd1plcm9MaW5lID0gY29lcmNlKCd6ZXJvbGluZScsIG9wdHMuc2hvd0dyaWQgfHwgISF6ZXJvTGluZUNvbG9yIHx8ICEhemVyb0xpbmVXaWR0aCk7XG5cbiAgICAgICAgaWYoIXNob3daZXJvTGluZSkge1xuICAgICAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC56ZXJvbGluZWNvbG9yO1xuICAgICAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC56ZXJvbGluZXdpZHRoO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlUG9zaXRpb25EZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgY291bnRlckF4ZXMgPSBvcHRpb25zLmNvdW50ZXJBeGVzIHx8IFtdO1xuICAgIHZhciBvdmVybGF5YWJsZUF4ZXMgPSBvcHRpb25zLm92ZXJsYXlhYmxlQXhlcyB8fCBbXTtcbiAgICB2YXIgbGV0dGVyID0gb3B0aW9ucy5sZXR0ZXI7XG4gICAgdmFyIGdyaWQgPSBvcHRpb25zLmdyaWQ7XG5cbiAgICB2YXIgZGZsdEFuY2hvciwgZGZsdERvbWFpbiwgZGZsdFNpZGUsIGRmbHRQb3NpdGlvbjtcblxuICAgIGlmKGdyaWQpIHtcbiAgICAgICAgZGZsdERvbWFpbiA9IGdyaWQuX2RvbWFpbnNbbGV0dGVyXVtncmlkLl9heGlzTWFwW2NvbnRhaW5lck91dC5faWRdXTtcbiAgICAgICAgZGZsdEFuY2hvciA9IGdyaWQuX2FuY2hvcnNbY29udGFpbmVyT3V0Ll9pZF07XG4gICAgICAgIGlmKGRmbHREb21haW4pIHtcbiAgICAgICAgICAgIGRmbHRTaWRlID0gZ3JpZFtsZXR0ZXIgKyAnc2lkZSddLnNwbGl0KCcgJylbMF07XG4gICAgICAgICAgICBkZmx0UG9zaXRpb24gPSBncmlkLmRvbWFpbltsZXR0ZXJdW2RmbHRTaWRlID09PSAncmlnaHQnIHx8IGRmbHRTaWRlID09PSAndG9wJyA/IDEgOiAwXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEV2ZW4gaWYgdGhlcmUncyBhIGdyaWQsIHRoaXMgYXhpcyBtYXkgbm90IGJlIGluIGl0IC0gZmFsbCBiYWNrIG9uIG5vbi1ncmlkIGRlZmF1bHRzXG4gICAgZGZsdERvbWFpbiA9IGRmbHREb21haW4gfHwgWzAsIDFdO1xuICAgIGRmbHRBbmNob3IgPSBkZmx0QW5jaG9yIHx8IChpc051bWVyaWMoY29udGFpbmVySW4ucG9zaXRpb24pID8gJ2ZyZWUnIDogKGNvdW50ZXJBeGVzWzBdIHx8ICdmcmVlJykpO1xuICAgIGRmbHRTaWRlID0gZGZsdFNpZGUgfHwgKGxldHRlciA9PT0gJ3gnID8gJ2JvdHRvbScgOiAnbGVmdCcpO1xuICAgIGRmbHRQb3NpdGlvbiA9IGRmbHRQb3NpdGlvbiB8fCAwO1xuXG4gICAgdmFyIGFuY2hvciA9IExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICBhbmNob3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydmcmVlJ10uY29uY2F0KGNvdW50ZXJBeGVzKSxcbiAgICAgICAgICAgIGRmbHQ6IGRmbHRBbmNob3JcbiAgICAgICAgfVxuICAgIH0sICdhbmNob3InKTtcblxuICAgIGlmKGFuY2hvciA9PT0gJ2ZyZWUnKSBjb2VyY2UoJ3Bvc2l0aW9uJywgZGZsdFBvc2l0aW9uKTtcblxuICAgIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICBzaWRlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IGxldHRlciA9PT0gJ3gnID8gWydib3R0b20nLCAndG9wJ10gOiBbJ2xlZnQnLCAncmlnaHQnXSxcbiAgICAgICAgICAgIGRmbHQ6IGRmbHRTaWRlXG4gICAgICAgIH1cbiAgICB9LCAnc2lkZScpO1xuXG4gICAgdmFyIG92ZXJsYXlpbmcgPSBmYWxzZTtcbiAgICBpZihvdmVybGF5YWJsZUF4ZXMubGVuZ3RoKSB7XG4gICAgICAgIG92ZXJsYXlpbmcgPSBMaWIuY29lcmNlKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIHtcbiAgICAgICAgICAgIG92ZXJsYXlpbmc6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBbZmFsc2VdLmNvbmNhdChvdmVybGF5YWJsZUF4ZXMpLFxuICAgICAgICAgICAgICAgIGRmbHQ6IGZhbHNlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sICdvdmVybGF5aW5nJyk7XG4gICAgfVxuXG4gICAgaWYoIW92ZXJsYXlpbmcpIHtcbiAgICAgICAgLy8gVE9ETzogcmlnaHQgbm93IEknbSBjb3B5aW5nIHRoaXMgZG9tYWluIG92ZXIgdG8gb3ZlcmxheWluZyBheGVzXG4gICAgICAgIC8vIGluIGF4LnNldHNjYWxlKCkuLi4gYnV0IHRoaXMgbWVhbnMgd2Ugc3RpbGwgbmVlZCAoaW1wZXJmZWN0KSBsb2dpY1xuICAgICAgICAvLyBpbiB0aGUgYXhlcyBwb3BvdmVyIHRvIGhpZGUgZG9tYWluIGZvciB0aGUgb3ZlcmxheWluZyBheGlzLlxuICAgICAgICAvLyBwZXJoYXBzIEkgc2hvdWxkIG1ha2UgYSBwcml2YXRlIHZlcnNpb24gX2RvbWFpbiB0aGF0IGFsbCBheGVzIGdldD8/P1xuICAgICAgICB2YXIgZG9tYWluID0gY29lcmNlKCdkb21haW4nLCBkZmx0RG9tYWluKTtcbiAgICAgICAgaWYoZG9tYWluWzBdID4gZG9tYWluWzFdIC0gMC4wMSkgY29udGFpbmVyT3V0LmRvbWFpbiA9IGRmbHREb21haW47XG4gICAgICAgIExpYi5ub25lT3JBbGwoY29udGFpbmVySW4uZG9tYWluLCBjb250YWluZXJPdXQuZG9tYWluLCBkZmx0RG9tYWluKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2xheWVyJyk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyT3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRlJPTV9CTCA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5GUk9NX0JMO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNjYWxlWm9vbShheCwgZmFjdG9yLCBjZW50ZXJGcmFjdGlvbikge1xuICAgIGlmKGNlbnRlckZyYWN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY2VudGVyRnJhY3Rpb24gPSBGUk9NX0JMW2F4LmNvbnN0cmFpbnRvd2FyZCB8fCAnY2VudGVyJ107XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlTGluZWFyID0gW2F4LnIybChheC5yYW5nZVswXSksIGF4LnIybChheC5yYW5nZVsxXSldO1xuICAgIHZhciBjZW50ZXIgPSByYW5nZUxpbmVhclswXSArIChyYW5nZUxpbmVhclsxXSAtIHJhbmdlTGluZWFyWzBdKSAqIGNlbnRlckZyYWN0aW9uO1xuXG4gICAgYXgucmFuZ2UgPSBheC5faW5wdXQucmFuZ2UgPSBbXG4gICAgICAgIGF4LmwycihjZW50ZXIgKyAocmFuZ2VMaW5lYXJbMF0gLSBjZW50ZXIpICogZmFjdG9yKSxcbiAgICAgICAgYXgubDJyKGNlbnRlciArIChyYW5nZUxpbmVhclsxXSAtIGNlbnRlcikgKiBmYWN0b3IpXG4gICAgXTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHBvbHlib29sID0gcmVxdWlyZSgncG9seWJvb2xqcycpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xuXG52YXIgcG9seWdvbiA9IHJlcXVpcmUoJy4uLy4uL2xpYi9wb2x5Z29uJyk7XG52YXIgdGhyb3R0bGUgPSByZXF1aXJlKCcuLi8uLi9saWIvdGhyb3R0bGUnKTtcbnZhciBtYWtlRXZlbnREYXRhID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meC9oZWxwZXJzJykubWFrZUV2ZW50RGF0YTtcbnZhciBnZXRGcm9tSWQgPSByZXF1aXJlKCcuL2F4aXNfaWRzJykuZ2V0RnJvbUlkO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xudmFyIHJlZHJhd1JlZ2xUcmFjZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lcycpLnJlZHJhd1JlZ2xUcmFjZXM7XG5cbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xudmFyIE1JTlNFTEVDVCA9IGNvbnN0YW50cy5NSU5TRUxFQ1Q7XG5cbnZhciBmaWx0ZXJlZFBvbHlnb24gPSBwb2x5Z29uLmZpbHRlcjtcbnZhciBwb2x5Z29uVGVzdGVyID0gcG9seWdvbi50ZXN0ZXI7XG5cbmZ1bmN0aW9uIGdldEF4SWQoYXgpIHsgcmV0dXJuIGF4Ll9pZDsgfVxuXG5mdW5jdGlvbiBwcmVwU2VsZWN0KGUsIHN0YXJ0WCwgc3RhcnRZLCBkcmFnT3B0aW9ucywgbW9kZSkge1xuICAgIHZhciBnZCA9IGRyYWdPcHRpb25zLmdkO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHpvb21MYXllciA9IGZ1bGxMYXlvdXQuX3pvb21sYXllcjtcbiAgICB2YXIgZHJhZ0JCb3ggPSBkcmFnT3B0aW9ucy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBwbG90aW5mbyA9IGRyYWdPcHRpb25zLnBsb3RpbmZvO1xuICAgIHZhciB4cyA9IHBsb3RpbmZvLnhheGlzLl9vZmZzZXQ7XG4gICAgdmFyIHlzID0gcGxvdGluZm8ueWF4aXMuX29mZnNldDtcbiAgICB2YXIgeDAgPSBzdGFydFggLSBkcmFnQkJveC5sZWZ0O1xuICAgIHZhciB5MCA9IHN0YXJ0WSAtIGRyYWdCQm94LnRvcDtcbiAgICB2YXIgeDEgPSB4MDtcbiAgICB2YXIgeTEgPSB5MDtcbiAgICB2YXIgcGF0aDAgPSAnTScgKyB4MCArICcsJyArIHkwO1xuICAgIHZhciBwdyA9IGRyYWdPcHRpb25zLnhheGVzWzBdLl9sZW5ndGg7XG4gICAgdmFyIHBoID0gZHJhZ09wdGlvbnMueWF4ZXNbMF0uX2xlbmd0aDtcbiAgICB2YXIgYWxsQXhlcyA9IGRyYWdPcHRpb25zLnhheGVzLmNvbmNhdChkcmFnT3B0aW9ucy55YXhlcyk7XG4gICAgdmFyIHN1YnRyYWN0ID0gZS5hbHRLZXk7XG5cbiAgICB2YXIgZmlsdGVyUG9seSwgc2VsZWN0aW9uVGVzdGVyLCBtZXJnZWRQb2x5Z29ucywgY3VycmVudFBvbHlnb247XG4gICAgdmFyIGksIHNlYXJjaEluZm8sIGV2ZW50RGF0YTtcblxuICAgIGNvZXJjZVNlbGVjdGlvbnNDYWNoZShlLCBnZCwgZHJhZ09wdGlvbnMpO1xuXG4gICAgaWYobW9kZSA9PT0gJ2xhc3NvJykge1xuICAgICAgICBmaWx0ZXJQb2x5ID0gZmlsdGVyZWRQb2x5Z29uKFtbeDAsIHkwXV0sIGNvbnN0YW50cy5CRU5EUFgpO1xuICAgIH1cblxuICAgIHZhciBvdXRsaW5lcyA9IHpvb21MYXllci5zZWxlY3RBbGwoJ3BhdGguc2VsZWN0LW91dGxpbmUtJyArIHBsb3RpbmZvLmlkKS5kYXRhKFsxLCAyXSk7XG5cbiAgICBvdXRsaW5lcy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiAnc2VsZWN0LW91dGxpbmUgc2VsZWN0LW91dGxpbmUtJyArIGQgKyAnIHNlbGVjdC1vdXRsaW5lLScgKyBwbG90aW5mby5pZDsgfSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHhzICsgJywgJyArIHlzICsgJyknKVxuICAgICAgICAuYXR0cignZCcsIHBhdGgwICsgJ1onKTtcblxuICAgIHZhciBjb3JuZXJzID0gem9vbUxheWVyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgICAgIHN0cm9rZTogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMVxuICAgICAgICB9KVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgeHMgKyAnLCAnICsgeXMgKyAnKScpXG4gICAgICAgIC5hdHRyKCdkJywgJ00wLDBaJyk7XG5cblxuICAgIHZhciB0aHJvdHRsZUlEID0gZnVsbExheW91dC5fdWlkICsgY29uc3RhbnRzLlNFTEVDVElEO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcblxuICAgIC8vIGZpbmQgdGhlIHRyYWNlcyB0byBzZWFyY2ggZm9yIHNlbGVjdGlvbiBwb2ludHNcbiAgICB2YXIgc2VhcmNoVHJhY2VzID0gZGV0ZXJtaW5lU2VhcmNoVHJhY2VzKGdkLCBkcmFnT3B0aW9ucy54YXhlcyxcbiAgICAgIGRyYWdPcHRpb25zLnlheGVzLCBkcmFnT3B0aW9ucy5zdWJwbG90KTtcblxuICAgIGZ1bmN0aW9uIGF4VmFsdWUoYXgpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gKGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd5JykgPyAxIDogMDtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGF4LnAyZCh2W2luZGV4XSk7IH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9XG5cbiAgICAvLyBhbGxvdyBzdWJwbG90cyB0byBvdmVycmlkZSBmaWxsUmFuZ2VJdGVtcyByb3V0aW5lXG4gICAgdmFyIGZpbGxSYW5nZUl0ZW1zO1xuXG4gICAgaWYocGxvdGluZm8uZmlsbFJhbmdlSXRlbXMpIHtcbiAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBwbG90aW5mby5maWxsUmFuZ2VJdGVtcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihtb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBmdW5jdGlvbihldmVudERhdGEsIHBvbHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2VzID0gZXZlbnREYXRhLnJhbmdlID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBhbGxBeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBheCA9IGFsbEF4ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VzW2F4Ll9pZF0gPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5wMmQocG9seVtheExldHRlciArICdtaW4nXSksXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5wMmQocG9seVtheExldHRlciArICdtYXgnXSlcbiAgICAgICAgICAgICAgICAgICAgXS5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zID0gZnVuY3Rpb24oZXZlbnREYXRhLCBwb2x5LCBmaWx0ZXJQb2x5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGRhdGFQdHMgPSBldmVudERhdGEubGFzc29Qb2ludHMgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGFsbEF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGF4ID0gYWxsQXhlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YVB0c1theC5faWRdID0gZmlsdGVyUG9seS5maWx0ZXJlZC5tYXAoYXhWYWx1ZShheCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkcmFnT3B0aW9ucy5tb3ZlRm4gPSBmdW5jdGlvbihkeDAsIGR5MCkge1xuICAgICAgICB4MSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHB3LCBkeDAgKyB4MCkpO1xuICAgICAgICB5MSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHBoLCBkeTAgKyB5MCkpO1xuXG4gICAgICAgIHZhciBkeCA9IE1hdGguYWJzKHgxIC0geDApLFxuICAgICAgICAgICAgZHkgPSBNYXRoLmFicyh5MSAtIHkwKTtcblxuICAgICAgICBpZihtb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGZ1bGxMYXlvdXQuc2VsZWN0ZGlyZWN0aW9uO1xuXG4gICAgICAgICAgICBpZihmdWxsTGF5b3V0LnNlbGVjdGRpcmVjdGlvbiA9PT0gJ2FueScpIHtcbiAgICAgICAgICAgICAgICBpZihkeSA8IE1hdGgubWluKGR4ICogMC42LCBNSU5TRUxFQ1QpKSBkaXJlY3Rpb24gPSAnaCc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZihkeCA8IE1hdGgubWluKGR5ICogMC42LCBNSU5TRUxFQ1QpKSBkaXJlY3Rpb24gPSAndic7XG4gICAgICAgICAgICAgICAgZWxzZSBkaXJlY3Rpb24gPSAnZCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSBmdWxsTGF5b3V0LnNlbGVjdGRpcmVjdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZGlyZWN0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICAvLyBob3Jpem9udGFsIG1vdGlvbjogbWFrZSBhIHZlcnRpY2FsIGJveFxuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uID0gW1t4MCwgMF0sIFt4MCwgcGhdLCBbeDEsIHBoXSwgW3gxLCAwXV07XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueG1pbiA9IE1hdGgubWluKHgwLCB4MSk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueG1heCA9IE1hdGgubWF4KHgwLCB4MSk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueW1pbiA9IE1hdGgubWluKDAsIHBoKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbi55bWF4ID0gTWF0aC5tYXgoMCwgcGgpO1xuICAgICAgICAgICAgICAgIC8vIGV4dHJhcyB0byBndWlkZSB1c2VycyBpbiBrZWVwaW5nIGEgc3RyYWlnaHQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgJ00nICsgY3VycmVudFBvbHlnb24ueG1pbiArICcsJyArICh5MCAtIE1JTlNFTEVDVCkgK1xuICAgICAgICAgICAgICAgICAgICAnaC00dicgKyAoMiAqIE1JTlNFTEVDVCkgKyAnaDRaJyArXG4gICAgICAgICAgICAgICAgICAgICdNJyArIChjdXJyZW50UG9seWdvbi54bWF4IC0gMSkgKyAnLCcgKyAoeTAgLSBNSU5TRUxFQ1QpICtcbiAgICAgICAgICAgICAgICAgICAgJ2g0dicgKyAoMiAqIE1JTlNFTEVDVCkgKyAnaC00WicpO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKGRpcmVjdGlvbiA9PT0gJ3YnKSB7XG4gICAgICAgICAgICAgICAgLy8gdmVydGljYWwgbW90aW9uOiBtYWtlIGEgaG9yaXpvbnRhbCBib3hcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbiA9IFtbMCwgeTBdLCBbMCwgeTFdLCBbcHcsIHkxXSwgW3B3LCB5MF1dO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtaW4gPSBNYXRoLm1pbigwLCBwdyk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueG1heCA9IE1hdGgubWF4KDAsIHB3KTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbi55bWluID0gTWF0aC5taW4oeTAsIHkxKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbi55bWF4ID0gTWF0aC5tYXgoeTAsIHkxKTtcbiAgICAgICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCAnTScgKyAoeDAgLSBNSU5TRUxFQ1QpICsgJywnICsgY3VycmVudFBvbHlnb24ueW1pbiArXG4gICAgICAgICAgICAgICAgICAgICd2LTRoJyArICgyICogTUlOU0VMRUNUKSArICd2NFonICtcbiAgICAgICAgICAgICAgICAgICAgJ00nICsgKHgwIC0gTUlOU0VMRUNUKSArICcsJyArIChjdXJyZW50UG9seWdvbi55bWF4IC0gMSkgK1xuICAgICAgICAgICAgICAgICAgICAndjRoJyArICgyICogTUlOU0VMRUNUKSArICd2LTRaJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKGRpcmVjdGlvbiA9PT0gJ2QnKSB7XG4gICAgICAgICAgICAgICAgLy8gZGlhZ29uYWwgbW90aW9uXG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24gPSBbW3gwLCB5MF0sIFt4MCwgeTFdLCBbeDEsIHkxXSwgW3gxLCB5MF1dO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtaW4gPSBNYXRoLm1pbih4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtYXggPSBNYXRoLm1heCh4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnltaW4gPSBNYXRoLm1pbih5MCwgeTEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnltYXggPSBNYXRoLm1heCh5MCwgeTEpO1xuICAgICAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNMCwwWicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYobW9kZSA9PT0gJ2xhc3NvJykge1xuICAgICAgICAgICAgZmlsdGVyUG9seS5hZGRQdChbeDEsIHkxXSk7XG4gICAgICAgICAgICBjdXJyZW50UG9seWdvbiA9IGZpbHRlclBvbHkuZmlsdGVyZWQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgb3V0bGluZSAmIHRlc3RlclxuICAgICAgICBpZihkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzICYmIGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBtZXJnZWRQb2x5Z29ucyA9IG1lcmdlUG9seWdvbnMoZHJhZ09wdGlvbnMubWVyZ2VkUG9seWdvbnMsIGN1cnJlbnRQb2x5Z29uLCBzdWJ0cmFjdCk7XG4gICAgICAgICAgICBjdXJyZW50UG9seWdvbi5zdWJ0cmFjdCA9IHN1YnRyYWN0O1xuICAgICAgICAgICAgc2VsZWN0aW9uVGVzdGVyID0gbXVsdGlUZXN0ZXIoZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcy5jb25jYXQoW2N1cnJlbnRQb2x5Z29uXSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbWVyZ2VkUG9seWdvbnMgPSBbY3VycmVudFBvbHlnb25dO1xuICAgICAgICAgICAgc2VsZWN0aW9uVGVzdGVyID0gcG9seWdvblRlc3RlcihjdXJyZW50UG9seWdvbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkcmF3IHNlbGVjdGlvblxuICAgICAgICBkcmF3U2VsZWN0aW9uKG1lcmdlZFBvbHlnb25zLCBvdXRsaW5lcyk7XG5cblxuICAgICAgICB0aHJvdHRsZS50aHJvdHRsZShcbiAgICAgICAgICAgIHRocm90dGxlSUQsXG4gICAgICAgICAgICBjb25zdGFudHMuU0VMRUNUREVMQVksXG4gICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciB0aGlzU2VsZWN0aW9uLCB0cmFjZVNlbGVjdGlvbnMgPSBbXSwgdHJhY2VTZWxlY3Rpb247XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaEluZm8gPSBzZWFyY2hUcmFjZXNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgdHJhY2VTZWxlY3Rpb24gPSBzZWFyY2hJbmZvLl9tb2R1bGUuc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcik7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlU2VsZWN0aW9ucy5wdXNoKHRyYWNlU2VsZWN0aW9uKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzU2VsZWN0aW9uID0gZmlsbFNlbGVjdGlvbkl0ZW0odHJhY2VTZWxlY3Rpb24sIHNlYXJjaEluZm8pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKHNlbGVjdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0aGlzU2VsZWN0aW9uLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2godGhpc1NlbGVjdGlvbltqXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBzZWxlY3Rpb24gPSB0aGlzU2VsZWN0aW9uO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSA9IHtwb2ludHM6IHNlbGVjdGlvbn07XG4gICAgICAgICAgICAgICAgdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzLCBldmVudERhdGEpO1xuICAgICAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zKGV2ZW50RGF0YSwgY3VycmVudFBvbHlnb24sIGZpbHRlclBvbHkpO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmdkLmVtaXQoJ3Bsb3RseV9zZWxlY3RpbmcnLCBldmVudERhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH07XG5cbiAgICBkcmFnT3B0aW9ucy5jbGlja0ZuID0gZnVuY3Rpb24obnVtQ2xpY2tzLCBldnQpIHtcbiAgICAgICAgdmFyIGNsaWNrbW9kZSA9IGZ1bGxMYXlvdXQuY2xpY2ttb2RlO1xuXG4gICAgICAgIGNvcm5lcnMucmVtb3ZlKCk7XG5cbiAgICAgICAgdGhyb3R0bGUuZG9uZSh0aHJvdHRsZUlEKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhyb3R0bGUuY2xlYXIodGhyb3R0bGVJRCk7XG4gICAgICAgICAgICBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAvLyBjbGVhciBzZWxlY3Rpb24gb24gZG91YmxlY2xpY2tcbiAgICAgICAgICAgICAgICBvdXRsaW5lcy5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgc2VhcmNoSW5mby5fbW9kdWxlLnNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzKTtcblxuICAgICAgICAgICAgICAgIGNsZWFyU2VsZWN0aW9uc0NhY2hlKGRyYWdPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kZXNlbGVjdCcsIG51bGwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihjbGlja21vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3RPbkNsaWNrKGV2dCwgZ2QsIGRyYWdPcHRpb25zLnhheGVzLCBkcmFnT3B0aW9ucy55YXhlcyxcbiAgICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5zdWJwbG90LCBkcmFnT3B0aW9ucywgb3V0bGluZXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGNsaWNrbW9kZSA9PT0gJ2V2ZW50Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiByZW1vdmUgaW4gdjIgLSB0aGlzIHdhcyBwcm9iYWJseSBuZXZlciBpbnRlbmRlZCB0byB3b3JrIGFzIGl0IGRvZXMsXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBpbiBjYXNlIGFueW9uZSBkZXBlbmRzIG9uIGl0IHdlIGRvbid0IHdhbnQgdG8gYnJlYWsgaXQgbm93LlxuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgY2xpY2stdG8tc2VsZWN0IGludHJvZHVjZWQgcHJlIHYyIGFsc28gZW1pdHRzIHByb3BlclxuICAgICAgICAgICAgICAgICAgICAvLyBldmVudCBkYXRhIHdoZW4gY2xpY2ttb2RlIGlzIGhhdmluZyAnc2VsZWN0JyBpbiBpdHMgZmxhZyBsaXN0LlxuICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfc2VsZWN0ZWQnLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRnguY2xpY2soZ2QsIGV2dCk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBkcmFnT3B0aW9ucy5kb25lRm4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY29ybmVycy5yZW1vdmUoKTtcblxuICAgICAgICB0aHJvdHRsZS5kb25lKHRocm90dGxlSUQpLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB0aHJvdHRsZS5jbGVhcih0aHJvdHRsZUlEKTtcbiAgICAgICAgICAgIGRyYWdPcHRpb25zLmdkLmVtaXQoJ3Bsb3RseV9zZWxlY3RlZCcsIGV2ZW50RGF0YSk7XG5cbiAgICAgICAgICAgIGlmKGN1cnJlbnRQb2x5Z29uICYmIGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMpIHtcbiAgICAgICAgICAgICAgICAvLyBzYXZlIGxhc3QgcG9seWdvbnNcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbi5zdWJ0cmFjdCA9IHN1YnRyYWN0O1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMucHVzaChjdXJyZW50UG9seWdvbik7XG5cbiAgICAgICAgICAgICAgICAvLyB3ZSBoYXZlIHRvIGtlZXAgcmVmZXJlbmNlIHRvIGFycmF5cyBjb250YWluZXJcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5tZXJnZWRQb2x5Z29ucy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgIFtdLnB1c2guYXBwbHkoZHJhZ09wdGlvbnMubWVyZ2VkUG9seWdvbnMsIG1lcmdlZFBvbHlnb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0T25DbGljayhldnQsIGdkLCB4QXhlcywgeUF4ZXMsIHN1YnBsb3QsIGRyYWdPcHRpb25zLCBwb2x5Z29uT3V0bGluZXMpIHtcbiAgICB2YXIgaG92ZXJEYXRhID0gZ2QuX2hvdmVyZGF0YTtcbiAgICB2YXIgY2xpY2ttb2RlID0gZ2QuX2Z1bGxMYXlvdXQuY2xpY2ttb2RlO1xuICAgIHZhciBzZW5kRXZlbnRzID0gY2xpY2ttb2RlLmluZGV4T2YoJ2V2ZW50JykgPiAtMTtcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIHNlYXJjaFRyYWNlcywgc2VhcmNoSW5mbywgY3VycmVudFNlbGVjdGlvbkRlZiwgc2VsZWN0aW9uVGVzdGVyLCB0cmFjZVNlbGVjdGlvbjtcbiAgICB2YXIgdGhpc1RyYWNlc1NlbGVjdGlvbiwgcG9pbnRPckJpblNlbGVjdGVkLCBzdWJ0cmFjdCwgZXZlbnREYXRhLCBpO1xuXG4gICAgaWYoaXNIb3ZlckRhdGFTZXQoaG92ZXJEYXRhKSkge1xuICAgICAgICBjb2VyY2VTZWxlY3Rpb25zQ2FjaGUoZXZ0LCBnZCwgZHJhZ09wdGlvbnMpO1xuICAgICAgICBzZWFyY2hUcmFjZXMgPSBkZXRlcm1pbmVTZWFyY2hUcmFjZXMoZ2QsIHhBeGVzLCB5QXhlcywgc3VicGxvdCk7XG4gICAgICAgIHZhciBjbGlja2VkUHRJbmZvID0gZXh0cmFjdENsaWNrZWRQdEluZm8oaG92ZXJEYXRhLCBzZWFyY2hUcmFjZXMpO1xuICAgICAgICB2YXIgaXNCaW5uZWRUcmFjZSA9IGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXJzLmxlbmd0aCA+IDA7XG5cblxuICAgICAgICAvLyBOb3RlOiBwb3RlbnRpYWxseSBjb3N0bHkgb3BlcmF0aW9uIGlzUG9pbnRPckJpblNlbGVjdGVkIGlzXG4gICAgICAgIC8vIGNhbGxlZCBhcyBsYXRlIGFzIHBvc3NpYmxlIHRocm91Z2ggdGhlIHVzZSBvZiBhbiBhc3NpZ25tZW50XG4gICAgICAgIC8vIGluIGFuIGlmIGNvbmRpdGlvbi5cbiAgICAgICAgaWYoaXNCaW5uZWRUcmFjZSA/XG4gICAgICAgICAgICBpc09ubHlUaGlzQmluU2VsZWN0ZWQoc2VhcmNoVHJhY2VzLCBjbGlja2VkUHRJbmZvKSA6XG4gICAgICAgICAgICBpc09ubHlPbmVQb2ludFNlbGVjdGVkKHNlYXJjaFRyYWNlcykgJiZcbiAgICAgICAgICAgICAgICAocG9pbnRPckJpblNlbGVjdGVkID0gaXNQb2ludE9yQmluU2VsZWN0ZWQoY2xpY2tlZFB0SW5mbykpKVxuICAgICAgICB7XG4gICAgICAgICAgICBpZihwb2x5Z29uT3V0bGluZXMpIHBvbHlnb25PdXRsaW5lcy5yZW1vdmUoKTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNlYXJjaEluZm8gPSBzZWFyY2hUcmFjZXNbaV07XG4gICAgICAgICAgICAgICAgc2VhcmNoSW5mby5fbW9kdWxlLnNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVwZGF0ZVNlbGVjdGVkU3RhdGUoZ2QsIHNlYXJjaFRyYWNlcyk7XG5cbiAgICAgICAgICAgIGNsZWFyU2VsZWN0aW9uc0NhY2hlKGRyYWdPcHRpb25zKTtcblxuICAgICAgICAgICAgaWYoc2VuZEV2ZW50cykge1xuICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kZXNlbGVjdCcsIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3VidHJhY3QgPSBldnQuc2hpZnRLZXkgJiZcbiAgICAgICAgICAgICAgKHBvaW50T3JCaW5TZWxlY3RlZCAhPT0gdW5kZWZpbmVkID9cbiAgICAgICAgICAgICAgICBwb2ludE9yQmluU2VsZWN0ZWQgOlxuICAgICAgICAgICAgICAgIGlzUG9pbnRPckJpblNlbGVjdGVkKGNsaWNrZWRQdEluZm8pKTtcbiAgICAgICAgICAgIGN1cnJlbnRTZWxlY3Rpb25EZWYgPSBuZXdQb2ludFNlbGVjdGlvbkRlZihjbGlja2VkUHRJbmZvLnBvaW50TnVtYmVyLCBjbGlja2VkUHRJbmZvLnNlYXJjaEluZm8sIHN1YnRyYWN0KTtcblxuICAgICAgICAgICAgdmFyIGFsbFNlbGVjdGlvbkRlZnMgPSBkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzLmNvbmNhdChbY3VycmVudFNlbGVjdGlvbkRlZl0pO1xuICAgICAgICAgICAgc2VsZWN0aW9uVGVzdGVyID0gbXVsdGlUZXN0ZXIoYWxsU2VsZWN0aW9uRGVmcyk7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRyYWNlU2VsZWN0aW9uID0gc2VhcmNoVHJhY2VzW2ldLl9tb2R1bGUuc2VsZWN0UG9pbnRzKHNlYXJjaFRyYWNlc1tpXSwgc2VsZWN0aW9uVGVzdGVyKTtcbiAgICAgICAgICAgICAgICB0aGlzVHJhY2VzU2VsZWN0aW9uID0gZmlsbFNlbGVjdGlvbkl0ZW0odHJhY2VTZWxlY3Rpb24sIHNlYXJjaFRyYWNlc1tpXSk7XG5cbiAgICAgICAgICAgICAgICBpZihzZWxlY3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0aGlzVHJhY2VzU2VsZWN0aW9uLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh0aGlzVHJhY2VzU2VsZWN0aW9uW2pdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHNlbGVjdGlvbiA9IHRoaXNUcmFjZXNTZWxlY3Rpb247XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGV2ZW50RGF0YSA9IHtwb2ludHM6IHNlbGVjdGlvbn07XG4gICAgICAgICAgICB1cGRhdGVTZWxlY3RlZFN0YXRlKGdkLCBzZWFyY2hUcmFjZXMsIGV2ZW50RGF0YSk7XG5cbiAgICAgICAgICAgIGlmKGN1cnJlbnRTZWxlY3Rpb25EZWYgJiYgZHJhZ09wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzLnB1c2goY3VycmVudFNlbGVjdGlvbkRlZik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHBvbHlnb25PdXRsaW5lcykgZHJhd1NlbGVjdGlvbihkcmFnT3B0aW9ucy5tZXJnZWRQb2x5Z29ucywgcG9seWdvbk91dGxpbmVzKTtcblxuICAgICAgICAgICAgaWYoc2VuZEV2ZW50cykge1xuICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9zZWxlY3RlZCcsIGV2ZW50RGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyBwb2ludCBzZWxlY3Rpb24gZGVmaW5pdGlvbiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIG5ld1BvaW50U2VsZWN0aW9uRGVmKHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvLCBzdWJ0cmFjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHBvaW50TnVtYmVyOiBwb2ludE51bWJlcixcbiAgICAgICAgc2VhcmNoSW5mbzogc2VhcmNoSW5mbyxcbiAgICAgICAgc3VidHJhY3Q6IHN1YnRyYWN0XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gaXNQb2ludFNlbGVjdGlvbkRlZihvKSB7XG4gICAgcmV0dXJuICdwb2ludE51bWJlcicgaW4gbyAmJiAnc2VhcmNoSW5mbycgaW4gbztcbn1cblxuLypcbiAqIENvbnN0cnVjdHMgYSBuZXcgcG9pbnQgbnVtYmVyIHRlc3Rlci5cbiAqL1xuZnVuY3Rpb24gbmV3UG9pbnROdW1UZXN0ZXIocG9pbnRTZWxlY3Rpb25EZWYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4bWluOiAwLFxuICAgICAgICB4bWF4OiAwLFxuICAgICAgICB5bWluOiAwLFxuICAgICAgICB5bWF4OiAwLFxuICAgICAgICBwdHM6IFtdLFxuICAgICAgICBjb250YWluczogZnVuY3Rpb24ocHQsIG9taXRGaXJzdEVkZ2UsIHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvKSB7XG4gICAgICAgICAgICB2YXIgaWR4V2FudGVkVHJhY2UgPSBwb2ludFNlbGVjdGlvbkRlZi5zZWFyY2hJbmZvLmNkWzBdLnRyYWNlLl9leHBhbmRlZEluZGV4O1xuICAgICAgICAgICAgdmFyIGlkeEFjdHVhbFRyYWNlID0gc2VhcmNoSW5mby5jZFswXS50cmFjZS5fZXhwYW5kZWRJbmRleDtcbiAgICAgICAgICAgIHJldHVybiBpZHhBY3R1YWxUcmFjZSA9PT0gaWR4V2FudGVkVHJhY2UgJiZcbiAgICAgICAgICAgICAgcG9pbnROdW1iZXIgPT09IHBvaW50U2VsZWN0aW9uRGVmLnBvaW50TnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICBpc1JlY3Q6IGZhbHNlLFxuICAgICAgICBkZWdlbmVyYXRlOiBmYWxzZSxcbiAgICAgICAgc3VidHJhY3Q6IHBvaW50U2VsZWN0aW9uRGVmLnN1YnRyYWN0XG4gICAgfTtcbn1cblxuLyoqXG4gKiBXcmFwcyBtdWx0aXBsZSBzZWxlY3Rpb24gdGVzdGVycy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBsaXN0IC0gQW4gYXJyYXkgb2Ygc2VsZWN0aW9uIHRlc3RlcnMuXG4gKlxuICogQHJldHVybiBhIHNlbGVjdGlvbiB0ZXN0ZXIgb2JqZWN0IHdpdGggYSBjb250YWlucyBmdW5jdGlvblxuICogdGhhdCBjYW4gYmUgY2FsbGVkIHRvIGV2YWx1YXRlIGEgcG9pbnQgYWdhaW5zdCBhbGwgd3JhcHBlZFxuICogc2VsZWN0aW9uIHRlc3RlcnMgdGhhdCB3ZXJlIHBhc3NlZCBpbiBsaXN0LlxuICovXG5mdW5jdGlvbiBtdWx0aVRlc3RlcihsaXN0KSB7XG4gICAgdmFyIHRlc3RlcnMgPSBbXTtcbiAgICB2YXIgeG1pbiA9IGlzUG9pbnRTZWxlY3Rpb25EZWYobGlzdFswXSkgPyAwIDogbGlzdFswXVswXVswXTtcbiAgICB2YXIgeG1heCA9IHhtaW47XG4gICAgdmFyIHltaW4gPSBpc1BvaW50U2VsZWN0aW9uRGVmKGxpc3RbMF0pID8gMCA6IGxpc3RbMF1bMF1bMV07XG4gICAgdmFyIHltYXggPSB5bWluO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoaXNQb2ludFNlbGVjdGlvbkRlZihsaXN0W2ldKSkge1xuICAgICAgICAgICAgdGVzdGVycy5wdXNoKG5ld1BvaW50TnVtVGVzdGVyKGxpc3RbaV0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciB0ZXN0ZXIgPSBwb2x5Z29uLnRlc3RlcihsaXN0W2ldKTtcbiAgICAgICAgICAgIHRlc3Rlci5zdWJ0cmFjdCA9IGxpc3RbaV0uc3VidHJhY3Q7XG4gICAgICAgICAgICB0ZXN0ZXJzLnB1c2godGVzdGVyKTtcbiAgICAgICAgICAgIHhtaW4gPSBNYXRoLm1pbih4bWluLCB0ZXN0ZXIueG1pbik7XG4gICAgICAgICAgICB4bWF4ID0gTWF0aC5tYXgoeG1heCwgdGVzdGVyLnhtYXgpO1xuICAgICAgICAgICAgeW1pbiA9IE1hdGgubWluKHltaW4sIHRlc3Rlci55bWluKTtcbiAgICAgICAgICAgIHltYXggPSBNYXRoLm1heCh5bWF4LCB0ZXN0ZXIueW1heCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZXN0cyBpZiB0aGUgZ2l2ZW4gcG9pbnQgaXMgd2l0aGluIHRoaXMgdGVzdGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHQgLSBbMF0gaXMgdGhlIHggY29vcmRpbmF0ZSwgWzFdIGlzIHRoZSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50LlxuICAgICAqIEBwYXJhbSB7Kn0gYXJnIC0gQW4gb3B0aW9uYWwgcGFyYW1ldGVyIHRvIHBhc3MgZG93biB0byB3cmFwcGVkIHRlc3RlcnMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBvaW50TnVtYmVyIC0gVGhlIHBvaW50IG51bWJlciBvZiB0aGUgcG9pbnQgd2l0aGluIHRoZSB1bmRlcmx5aW5nIGRhdGEgYXJyYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNlYXJjaEluZm8gLSBBbiBvYmplY3QgaWRlbnRpZnlpbmcgdGhlIHRyYWNlIHRoZSBwb2ludCBpcyBjb250YWluZWQgaW4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHBvaW50IGlzIGNvbnNpZGVyZWQgdG8gYmUgc2VsZWN0ZWQsIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb250YWlucyhwdCwgYXJnLCBwb2ludE51bWJlciwgc2VhcmNoSW5mbykge1xuICAgICAgICB2YXIgY29udGFpbmVkID0gZmFsc2U7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0ZXN0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZih0ZXN0ZXJzW2ldLmNvbnRhaW5zKHB0LCBhcmcsIHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIGNvbnRhaW5lZCBieSBzdWJ0cmFjdCB0ZXN0ZXIgLSBleGNsdWRlIHRoZSBwb2ludFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lZCA9IHRlc3RlcnNbaV0uc3VidHJhY3QgPT09IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4bWluOiB4bWluLFxuICAgICAgICB4bWF4OiB4bWF4LFxuICAgICAgICB5bWluOiB5bWluLFxuICAgICAgICB5bWF4OiB5bWF4LFxuICAgICAgICBwdHM6IFtdLFxuICAgICAgICBjb250YWluczogY29udGFpbnMsXG4gICAgICAgIGlzUmVjdDogZmFsc2UsXG4gICAgICAgIGRlZ2VuZXJhdGU6IGZhbHNlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29lcmNlU2VsZWN0aW9uc0NhY2hlKGV2dCwgZ2QsIGRyYWdPcHRpb25zKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgem9vbUxheWVyID0gZnVsbExheW91dC5fem9vbWxheWVyO1xuICAgIHZhciBwbG90aW5mbyA9IGRyYWdPcHRpb25zLnBsb3RpbmZvO1xuXG4gICAgdmFyIHNlbGVjdGluZ09uU2FtZVN1YnBsb3QgPSAoXG4gICAgICBmdWxsTGF5b3V0Ll9sYXN0U2VsZWN0ZWRTdWJwbG90ICYmXG4gICAgICBmdWxsTGF5b3V0Ll9sYXN0U2VsZWN0ZWRTdWJwbG90ID09PSBwbG90aW5mby5pZFxuICAgICk7XG4gICAgdmFyIGhhc01vZGlmaWVyS2V5ID0gZXZ0LnNoaWZ0S2V5IHx8IGV2dC5hbHRLZXk7XG4gICAgaWYoc2VsZWN0aW5nT25TYW1lU3VicGxvdCAmJiBoYXNNb2RpZmllcktleSAmJlxuICAgICAgKHBsb3RpbmZvLnNlbGVjdGlvbiAmJiBwbG90aW5mby5zZWxlY3Rpb24uc2VsZWN0aW9uRGVmcykgJiYgIWRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMpIHtcbiAgICAgICAgLy8gdGFrZSBvdmVyIHNlbGVjdGlvbiBkZWZpbml0aW9ucyBmcm9tIHByZXYgbW9kZSwgaWYgYW55XG4gICAgICAgIGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMgPSBwbG90aW5mby5zZWxlY3Rpb24uc2VsZWN0aW9uRGVmcztcbiAgICAgICAgZHJhZ09wdGlvbnMubWVyZ2VkUG9seWdvbnMgPSBwbG90aW5mby5zZWxlY3Rpb24ubWVyZ2VkUG9seWdvbnM7XG4gICAgfSBlbHNlIGlmKCFoYXNNb2RpZmllcktleSB8fCAhcGxvdGluZm8uc2VsZWN0aW9uKSB7XG4gICAgICAgIGNsZWFyU2VsZWN0aW9uc0NhY2hlKGRyYWdPcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyBjbGVhciBzZWxlY3Rpb24gb3V0bGluZSB3aGVuIHNlbGVjdGluZyBhIGRpZmZlcmVudCBzdWJwbG90XG4gICAgaWYoIXNlbGVjdGluZ09uU2FtZVN1YnBsb3QpIHtcbiAgICAgICAgY2xlYXJTZWxlY3Qoem9vbUxheWVyKTtcbiAgICAgICAgZnVsbExheW91dC5fbGFzdFNlbGVjdGVkU3VicGxvdCA9IHBsb3RpbmZvLmlkO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY2xlYXJTZWxlY3Rpb25zQ2FjaGUoZHJhZ09wdGlvbnMpIHtcbiAgICB2YXIgcGxvdGluZm8gPSBkcmFnT3B0aW9ucy5wbG90aW5mbztcblxuICAgIHBsb3RpbmZvLnNlbGVjdGlvbiA9IHt9O1xuICAgIHBsb3RpbmZvLnNlbGVjdGlvbi5zZWxlY3Rpb25EZWZzID0gZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcyA9IFtdO1xuICAgIHBsb3RpbmZvLnNlbGVjdGlvbi5tZXJnZWRQb2x5Z29ucyA9IGRyYWdPcHRpb25zLm1lcmdlZFBvbHlnb25zID0gW107XG59XG5cbmZ1bmN0aW9uIGRldGVybWluZVNlYXJjaFRyYWNlcyhnZCwgeEF4ZXMsIHlBeGVzLCBzdWJwbG90KSB7XG4gICAgdmFyIHNlYXJjaFRyYWNlcyA9IFtdO1xuICAgIHZhciB4QXhpc0lkcyA9IHhBeGVzLm1hcChnZXRBeElkKTtcbiAgICB2YXIgeUF4aXNJZHMgPSB5QXhlcy5tYXAoZ2V0QXhJZCk7XG4gICAgdmFyIGNkLCB0cmFjZSwgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGdkLmNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkID0gZ2QuY2FsY2RhdGFbaV07XG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCAhdHJhY2UuX21vZHVsZSB8fCAhdHJhY2UuX21vZHVsZS5zZWxlY3RQb2ludHMpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKHN1YnBsb3QgJiYgKHRyYWNlLnN1YnBsb3QgPT09IHN1YnBsb3QgfHwgdHJhY2UuZ2VvID09PSBzdWJwbG90KSkge1xuICAgICAgICAgICAgc2VhcmNoVHJhY2VzLnB1c2goY3JlYXRlU2VhcmNoSW5mbyh0cmFjZS5fbW9kdWxlLCBjZCwgeEF4ZXNbMF0sIHlBeGVzWzBdKSk7XG4gICAgICAgIH0gZWxzZSBpZihcbiAgICAgICAgICB0cmFjZS50eXBlID09PSAnc3Bsb20nICYmXG4gICAgICAgICAgLy8gRklYTUU6IG1ha2Ugc3VyZSB3ZSBkb24ndCBoYXZlIG1vcmUgdGhhbiBzaW5nbGUgYXhpcyBmb3Igc3Bsb21cbiAgICAgICAgICB0cmFjZS5feGF4ZXNbeEF4aXNJZHNbMF1dICYmIHRyYWNlLl95YXhlc1t5QXhpc0lkc1swXV1cbiAgICAgICAgKSB7XG4gICAgICAgICAgICB2YXIgaW5mbyA9IGNyZWF0ZVNlYXJjaEluZm8odHJhY2UuX21vZHVsZSwgY2QsIHhBeGVzWzBdLCB5QXhlc1swXSk7XG4gICAgICAgICAgICBpbmZvLnNjZW5lID0gZ2QuX2Z1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG4gICAgICAgICAgICBzZWFyY2hUcmFjZXMucHVzaChpbmZvKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKHhBeGlzSWRzLmluZGV4T2YodHJhY2UueGF4aXMpID09PSAtMSkgY29udGludWU7XG4gICAgICAgICAgICBpZih5QXhpc0lkcy5pbmRleE9mKHRyYWNlLnlheGlzKSA9PT0gLTEpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBzZWFyY2hUcmFjZXMucHVzaChjcmVhdGVTZWFyY2hJbmZvKHRyYWNlLl9tb2R1bGUsIGNkLFxuICAgICAgICAgICAgICBnZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKSwgZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcykpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWFyY2hUcmFjZXM7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVTZWFyY2hJbmZvKG1vZHVsZSwgY2FsY0RhdGEsIHhheGlzLCB5YXhpcykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgX21vZHVsZTogbW9kdWxlLFxuICAgICAgICAgICAgY2Q6IGNhbGNEYXRhLFxuICAgICAgICAgICAgeGF4aXM6IHhheGlzLFxuICAgICAgICAgICAgeWF4aXM6IHlheGlzXG4gICAgICAgIH07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3U2VsZWN0aW9uKHBvbHlnb25zLCBvdXRsaW5lcykge1xuICAgIHZhciBwYXRocyA9IFtdO1xuICAgIHZhciBpLCBkO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgcG9seWdvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHBwdHMgPSBwb2x5Z29uc1tpXTtcbiAgICAgICAgcGF0aHMucHVzaChwcHRzLmpvaW4oJ0wnKSArICdMJyArIHBwdHNbMF0pO1xuICAgIH1cblxuICAgIGQgPSBwb2x5Z29ucy5sZW5ndGggPiAwID9cbiAgICAgICdNJyArIHBhdGhzLmpvaW4oJ00nKSArICdaJyA6XG4gICAgICAnTTAsMFonO1xuICAgIG91dGxpbmVzLmF0dHIoJ2QnLCBkKTtcbn1cblxuZnVuY3Rpb24gaXNIb3ZlckRhdGFTZXQoaG92ZXJEYXRhKSB7XG4gICAgcmV0dXJuIGhvdmVyRGF0YSAmJlxuICAgICAgQXJyYXkuaXNBcnJheShob3ZlckRhdGEpICYmXG4gICAgICBob3ZlckRhdGFbMF0uaG92ZXJPbkJveCAhPT0gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdENsaWNrZWRQdEluZm8oaG92ZXJEYXRhLCBzZWFyY2hUcmFjZXMpIHtcbiAgICB2YXIgaG92ZXJEYXR1bSA9IGhvdmVyRGF0YVswXTtcbiAgICB2YXIgcG9pbnROdW1iZXIgPSAtMTtcbiAgICB2YXIgcG9pbnROdW1iZXJzID0gW107XG4gICAgdmFyIHNlYXJjaEluZm8sIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgaWYoaG92ZXJEYXR1bS5mdWxsRGF0YS5fZXhwYW5kZWRJbmRleCA9PT0gc2VhcmNoSW5mby5jZFswXS50cmFjZS5fZXhwYW5kZWRJbmRleCkge1xuXG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIGJveCAoYW5kIHZpb2xpbilcbiAgICAgICAgICAgIGlmKGhvdmVyRGF0dW0uaG92ZXJPbkJveCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIaW50OiBpbiBzb21lIHRyYWNlcyBsaWtlIGhpc3RvZ3JhbSwgb25lIGdyYXBoaWNhbCBlbGVtZW50XG4gICAgICAgICAgICAvLyBkb2Vzbid0IGNvcnJlc3BvbmQgdG8gb25lIHBhcnRpY3VsYXIgZGF0YSBwb2ludCwgYnV0IHRvXG4gICAgICAgICAgICAvLyBiaW5zIG9mIGRhdGEgcG9pbnRzLiBUaHVzLCBob3ZlckRhdHVtIGNhbiBoYXZlIGEgYmluTnVtYmVyXG4gICAgICAgICAgICAvLyBwcm9wZXJ0eSBpbnN0ZWFkIG9mIHBvaW50TnVtYmVyLlxuICAgICAgICAgICAgaWYoaG92ZXJEYXR1bS5wb2ludE51bWJlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcG9pbnROdW1iZXIgPSBob3ZlckRhdHVtLnBvaW50TnVtYmVyO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGhvdmVyRGF0dW0uYmluTnVtYmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwb2ludE51bWJlciA9IGhvdmVyRGF0dW0uYmluTnVtYmVyO1xuICAgICAgICAgICAgICAgIHBvaW50TnVtYmVycyA9IGhvdmVyRGF0dW0ucG9pbnROdW1iZXJzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHBvaW50TnVtYmVyOiBwb2ludE51bWJlcixcbiAgICAgICAgcG9pbnROdW1iZXJzOiBwb2ludE51bWJlcnMsXG4gICAgICAgIHNlYXJjaEluZm86IHNlYXJjaEluZm9cbiAgICB9O1xufVxuXG5mdW5jdGlvbiBpc1BvaW50T3JCaW5TZWxlY3RlZChjbGlja2VkUHRJbmZvKSB7XG4gICAgdmFyIHRyYWNlID0gY2xpY2tlZFB0SW5mby5zZWFyY2hJbmZvLmNkWzBdLnRyYWNlO1xuICAgIHZhciBwdE51bSA9IGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXI7XG4gICAgdmFyIHB0TnVtcyA9IGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXJzO1xuICAgIHZhciBwdE51bXNTZXQgPSBwdE51bXMubGVuZ3RoID4gMDtcblxuICAgIC8vIFdoZW4gcG9pbnRzTnVtYmVycyBpcyBzZXQgKGUuZy4gaGlzdG9ncmFtJ3MgYmlubmluZyksXG4gICAgLy8gaXQgaXMgYXNzdW1lZCB0aGF0IHdoZW4gdGhlIGZpcnN0IHBvaW50IG9mXG4gICAgLy8gYSBiaW4gaXMgc2VsZWN0ZWQsIGFsbCBvdGhlcnMgYXJlIGFzIHdlbGxcbiAgICB2YXIgcHROdW1Ub1Rlc3QgPSBwdE51bXNTZXQgPyBwdE51bXNbMF0gOiBwdE51bTtcblxuICAgIC8vIFRPRE8gcG90ZW50aWFsIHBlcmZvcm1hbmNlIGltcHJvdmVtZW50XG4gICAgLy8gUHJpbWFyaWx5IHdlIG5lZWQgdGhpcyBmdW5jdGlvbiB0byBkZXRlcm1pbmUgaWYgYSBjbGljayBhZGRzXG4gICAgLy8gb3Igc3VidHJhY3RzIGZyb20gYSBzZWxlY3Rpb24uXG4gICAgLy8gSW4gY2FzZXMgYHRyYWNlLnNlbGVjdGVkcG9pbnRzYCBpcyBhIGh1Z2UgYXJyYXksIGluZGV4T2ZcbiAgICAvLyBtaWdodCBiZSBzbG93LiBPbmUgcmVtZWR5IHdvdWxkIGJlIHRvIGludHJvZHVjZSBhIGhhc2ggc29tZXdoZXJlLlxuICAgIHJldHVybiB0cmFjZS5zZWxlY3RlZHBvaW50cyA/IHRyYWNlLnNlbGVjdGVkcG9pbnRzLmluZGV4T2YocHROdW1Ub1Rlc3QpID4gLTEgOiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNPbmx5VGhpc0JpblNlbGVjdGVkKHNlYXJjaFRyYWNlcywgY2xpY2tlZFB0SW5mbykge1xuICAgIHZhciB0cmFjZXNXaXRoU2VsZWN0ZWRQdHMgPSBbXTtcbiAgICB2YXIgc2VhcmNoSW5mbywgdHJhY2UsIGlzU2FtZVRyYWNlLCBpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlYXJjaEluZm8gPSBzZWFyY2hUcmFjZXNbaV07XG4gICAgICAgIGlmKHNlYXJjaEluZm8uY2RbMF0udHJhY2Uuc2VsZWN0ZWRwb2ludHMgJiYgc2VhcmNoSW5mby5jZFswXS50cmFjZS5zZWxlY3RlZHBvaW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0cmFjZXNXaXRoU2VsZWN0ZWRQdHMucHVzaChzZWFyY2hJbmZvKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHRyYWNlc1dpdGhTZWxlY3RlZFB0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgaXNTYW1lVHJhY2UgPSB0cmFjZXNXaXRoU2VsZWN0ZWRQdHNbMF0gPT09IGNsaWNrZWRQdEluZm8uc2VhcmNoSW5mbztcbiAgICAgICAgaWYoaXNTYW1lVHJhY2UpIHtcbiAgICAgICAgICAgIHRyYWNlID0gY2xpY2tlZFB0SW5mby5zZWFyY2hJbmZvLmNkWzBdLnRyYWNlO1xuICAgICAgICAgICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMubGVuZ3RoID09PSBjbGlja2VkUHRJbmZvLnBvaW50TnVtYmVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjbGlja2VkUHRJbmZvLnBvaW50TnVtYmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cy5pbmRleE9mKGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXJzW2ldKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNPbmx5T25lUG9pbnRTZWxlY3RlZChzZWFyY2hUcmFjZXMpIHtcbiAgICB2YXIgbGVuID0gMDtcbiAgICB2YXIgc2VhcmNoSW5mbywgdHJhY2UsIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgdHJhY2UgPSBzZWFyY2hJbmZvLmNkWzBdLnRyYWNlO1xuICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cykge1xuICAgICAgICAgICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMubGVuZ3RoID4gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgICAgICBsZW4gKz0gdHJhY2Uuc2VsZWN0ZWRwb2ludHMubGVuZ3RoO1xuICAgICAgICAgICAgaWYobGVuID4gMSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxlbiA9PT0gMTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzLCBldmVudERhdGEpIHtcbiAgICB2YXIgaSwgc2VhcmNoSW5mbywgY2QsIHRyYWNlO1xuXG4gICAgaWYoZXZlbnREYXRhKSB7XG4gICAgICAgIHZhciBwdHMgPSBldmVudERhdGEucG9pbnRzIHx8IFtdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2UgPSBzZWFyY2hUcmFjZXNbaV0uY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB0cmFjZS5zZWxlY3RlZHBvaW50cyA9IFtdO1xuICAgICAgICAgICAgdHJhY2UuX2lucHV0LnNlbGVjdGVkcG9pbnRzID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwdCA9IHB0c1tpXTtcbiAgICAgICAgICAgIHZhciBkYXRhID0gcHQuZGF0YTtcbiAgICAgICAgICAgIHZhciBmdWxsRGF0YSA9IHB0LmZ1bGxEYXRhO1xuXG4gICAgICAgICAgICBpZihwdC5wb2ludEluZGljZXMpIHtcbiAgICAgICAgICAgICAgICBbXS5wdXNoLmFwcGx5KGRhdGEuc2VsZWN0ZWRwb2ludHMsIHB0LnBvaW50SW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgW10ucHVzaC5hcHBseShmdWxsRGF0YS5zZWxlY3RlZHBvaW50cywgcHQucG9pbnRJbmRpY2VzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGF0YS5zZWxlY3RlZHBvaW50cy5wdXNoKHB0LnBvaW50SW5kZXgpO1xuICAgICAgICAgICAgICAgIGZ1bGxEYXRhLnNlbGVjdGVkcG9pbnRzLnB1c2gocHQucG9pbnRJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2UgPSBzZWFyY2hUcmFjZXNbaV0uY2RbMF0udHJhY2U7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2Uuc2VsZWN0ZWRwb2ludHM7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2UuX2lucHV0LnNlbGVjdGVkcG9pbnRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzZWFyY2hJbmZvID0gc2VhcmNoVHJhY2VzW2ldO1xuICAgICAgICBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3JlZ2wnKSkge1xuICAgICAgICAgICAgaGFzUmVnbCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgX21vZHVsZSA9IHNlYXJjaEluZm8uX21vZHVsZTtcbiAgICAgICAgdmFyIGZuID0gX21vZHVsZS5zdHlsZU9uU2VsZWN0IHx8IF9tb2R1bGUuc3R5bGU7XG4gICAgICAgIGlmKGZuKSBmbihnZCwgY2QpO1xuICAgIH1cblxuICAgIGlmKGhhc1JlZ2wpIHtcbiAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgcmVkcmF3UmVnbFRyYWNlcyhnZCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtZXJnZVBvbHlnb25zKGxpc3QsIHBvbHksIHN1YnRyYWN0KSB7XG4gICAgdmFyIHJlcztcblxuICAgIGlmKHN1YnRyYWN0KSB7XG4gICAgICAgIHJlcyA9IHBvbHlib29sLmRpZmZlcmVuY2Uoe1xuICAgICAgICAgICAgcmVnaW9uczogbGlzdCxcbiAgICAgICAgICAgIGludmVydGVkOiBmYWxzZVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICByZWdpb25zOiBbcG9seV0sXG4gICAgICAgICAgICBpbnZlcnRlZDogZmFsc2VcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcy5yZWdpb25zO1xuICAgIH1cblxuICAgIHJlcyA9IHBvbHlib29sLnVuaW9uKHtcbiAgICAgICAgcmVnaW9uczogbGlzdCxcbiAgICAgICAgaW52ZXJ0ZWQ6IGZhbHNlXG4gICAgfSwge1xuICAgICAgICByZWdpb25zOiBbcG9seV0sXG4gICAgICAgIGludmVydGVkOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlcy5yZWdpb25zO1xufVxuXG5mdW5jdGlvbiBmaWxsU2VsZWN0aW9uSXRlbShzZWxlY3Rpb24sIHNlYXJjaEluZm8pIHtcbiAgICBpZihBcnJheS5pc0FycmF5KHNlbGVjdGlvbikpIHtcbiAgICAgICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICAgICAgdmFyIHRyYWNlID0gc2VhcmNoSW5mby5jZFswXS50cmFjZTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VsZWN0aW9uLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb25baV0gPSBtYWtlRXZlbnREYXRhKHNlbGVjdGlvbltpXSwgdHJhY2UsIGNkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIGNsZWFyU2VsZWN0KHpvb21sYXllcikge1xuICAgIC8vIHVudGlsIHdlIGdldCBhcm91bmQgdG8gcGVyc2lzdGVudCBzZWxlY3Rpb25zLCByZW1vdmUgdGhlIG91dGxpbmVcbiAgICAvLyBoZXJlLiBUaGUgc2VsZWN0aW9uIGl0c2VsZiB3aWxsIGJlIHJlbW92ZWQgd2hlbiB0aGUgcGxvdCByZWRyYXdzXG4gICAgLy8gYXQgdGhlIGVuZC5cbiAgICB6b29tbGF5ZXIuc2VsZWN0QWxsKCcuc2VsZWN0LW91dGxpbmUnKS5yZW1vdmUoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcHJlcFNlbGVjdDogcHJlcFNlbGVjdCxcbiAgICBjbGVhclNlbGVjdDogY2xlYXJTZWxlY3QsXG4gICAgc2VsZWN0T25DbGljazogc2VsZWN0T25DbGlja1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBjbGVhbk51bWJlciA9IExpYi5jbGVhbk51bWJlcjtcbnZhciBtczJEYXRlVGltZSA9IExpYi5tczJEYXRlVGltZTtcbnZhciBkYXRlVGltZTJtcyA9IExpYi5kYXRlVGltZTJtcztcbnZhciBlbnN1cmVOdW1iZXIgPSBMaWIuZW5zdXJlTnVtYmVyO1xuXG52YXIgbnVtQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpO1xudmFyIEZQX1NBRkUgPSBudW1Db25zdGFudHMuRlBfU0FGRTtcbnZhciBCQUROVU0gPSBudW1Db25zdGFudHMuQkFETlVNO1xudmFyIExPR19DTElQID0gbnVtQ29uc3RhbnRzLkxPR19DTElQO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBheGlzSWRzID0gcmVxdWlyZSgnLi9heGlzX2lkcycpO1xuXG5mdW5jdGlvbiBmcm9tTG9nKHYpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHYpO1xufVxuXG4vKipcbiAqIERlZmluZSB0aGUgY29udmVyc2lvbiBmdW5jdGlvbnMgZm9yIGFuIGF4aXMgZGF0YSBpcyB1c2VkIGluIDUgd2F5czpcbiAqXG4gKiAgZDogZGF0YSwgaW4gd2hhdGV2ZXIgZm9ybSBpdCdzIHByb3ZpZGVkXG4gKiAgYzogY2FsY2RhdGE6IHR1cm5lZCBpbnRvIG51bWJlcnMsIGJ1dCBub3QgbGluZWFyaXplZFxuICogIGw6IGxpbmVhcml6ZWQgLSBzYW1lIGFzIGMgZXhjZXB0IGZvciBsb2cgYXhlcyAoYW5kIG90aGVyIG5vbmxpbmVhclxuICogICAgICBtYXBwaW5ncyBsYXRlcj8pIHRoaXMgaXMgdXNlZCB3aGVuIHdlIG5lZWQgdG8ga25vdyBpZiBpdCdzXG4gKiAgICAgICpwb3NzaWJsZSogdG8gc2hvdyBzb21lIGRhdGEgb24gdGhpcyBheGlzLCB3aXRob3V0IGNhcmluZyBhYm91dFxuICogICAgICB0aGUgY3VycmVudCByYW5nZVxuICogIHA6IHBpeGVsIHZhbHVlIC0gbWFwcGVkIHRvIHRoZSBzY3JlZW4gd2l0aCBjdXJyZW50IHNpemUgYW5kIHpvb21cbiAqICByOiByYW5nZXMsIHRpY2swLCBhbmQgYW5ub3RhdGlvbiBwb3NpdGlvbnMgbWF0Y2ggb25lIG9mIHRoZSBhYm92ZVxuICogICAgIGJ1dCBhcmUgaGFuZGxlZCBkaWZmZXJlbnRseSBmb3IgZGlmZmVyZW50IHR5cGVzOlxuICogICAgIC0gbGluZWFyIGFuZCBkYXRlOiBkYXRhIGZvcm1hdCAoZClcbiAqICAgICAtIGNhdGVnb3J5OiBjYWxjZGF0YSBmb3JtYXQgKGMpLCBhbmQgd2lsbCBzdGF5IHRoYXQgd2F5IGJlY2F1c2VcbiAqICAgICAgIHRoZSBkYXRhIGZvcm1hdCBoYXMgbm8gY29udGludW91cyBtYXBwaW5nXG4gKiAgICAgLSBsb2c6IGxpbmVhcml6ZWQgKGwpIGZvcm1hdFxuICogICAgICAgVE9ETzogaW4gdjIuMCB3ZSBwbGFuIHRvIGNoYW5nZSBpdCB0byBkYXRhIGZvcm1hdC4gQXQgdGhhdCBwb2ludFxuICogICAgICAgc2hhcGVzIHdpbGwgd29yayB0aGUgc2FtZSB3YXkgYXMgcmFuZ2VzLCB0aWNrMCwgYW5kIGFubm90YXRpb25zXG4gKiAgICAgICBzbyB0aGV5IGNhbiB1c2UgdGhpcyBjb252ZXJzaW9uIHRvby5cbiAqXG4gKiBDcmVhdGVzL3VwZGF0ZXMgdGhlc2UgY29udmVyc2lvbiBmdW5jdGlvbnMsIGFuZCBhIGZldyBtb3JlIHV0aWxpdGllc1xuICogbGlrZSBjbGVhblJhbmdlLCBhbmQgbWFrZUNhbGNkYXRhXG4gKlxuICogYWxzbyBjbGVhcnMgdGhlIGF1dG90aWNrIGNvbnN0cmFpbnRzIC5fbWluRHRpY2ssIC5fZm9yY2VUaWNrMFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNldENvbnZlcnQoYXgsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdWxsTGF5b3V0ID0gZnVsbExheW91dCB8fCB7fTtcblxuICAgIHZhciBheExldHRlciA9IChheC5faWQgfHwgJ3gnKS5jaGFyQXQoMCk7XG5cbiAgICBmdW5jdGlvbiB0b0xvZyh2LCBjbGlwKSB7XG4gICAgICAgIGlmKHYgPiAwKSByZXR1cm4gTWF0aC5sb2codikgLyBNYXRoLkxOMTA7XG5cbiAgICAgICAgZWxzZSBpZih2IDw9IDAgJiYgY2xpcCAmJiBheC5yYW5nZSAmJiBheC5yYW5nZS5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIC8vIGNsaXAgTmFOIChpZSBwYXN0IG5lZ2F0aXZlIGluZmluaXR5KSB0byBMT0dfQ0xJUCBheGlzXG4gICAgICAgICAgICAvLyBsZW5ndGggcGFzdCB0aGUgbmVnYXRpdmUgZWRnZVxuICAgICAgICAgICAgdmFyIHIwID0gYXgucmFuZ2VbMF0sXG4gICAgICAgICAgICAgICAgcjEgPSBheC5yYW5nZVsxXTtcbiAgICAgICAgICAgIHJldHVybiAwLjUgKiAocjAgKyByMSAtIDIgKiBMT0dfQ0xJUCAqIE1hdGguYWJzKHIwIC0gcjEpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsc2UgcmV0dXJuIEJBRE5VTTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIHdyYXBwZWQgZGF0ZVRpbWUybXMgdGhhdDpcbiAgICAgKiAtIGFjY2VwdHMgbXMgbnVtYmVycyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgICAqIC0gaW5zZXJ0cyBhIGR1bW15IGFyZyBzbyBjYWxlbmRhciBpcyB0aGUgM3JkIGFyZyAoc2VlIG5vdGVzIGJlbG93KS5cbiAgICAgKiAtIGRlZmF1bHRzIHRvIGF4LmNhbGVuZGFyXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHQybXModiwgXywgY2FsZW5kYXIpIHtcbiAgICAgICAgLy8gTk9URTogQ2hhbmdlZCB0aGlzIGJlaGF2aW9yOiBwcmV2aW91c2x5IHdlIHRvb2sgYW55IG51bWVyaWMgdmFsdWVcbiAgICAgICAgLy8gdG8gYmUgYSBtcywgZXZlbiBpZiBpdCB3YXMgYSBzdHJpbmcgdGhhdCBjb3VsZCBiZSBhIGJhcmUgeWVhci5cbiAgICAgICAgLy8gTm93IHdlIGNvbnZlcnQgaXQgYXMgYSBkYXRlIGlmIGF0IGFsbCBwb3NzaWJsZSwgYW5kIG9ubHkgdHJ5XG4gICAgICAgIC8vIGFzIChsb2NhbCkgbXMgaWYgdGhhdCBmYWlscy5cbiAgICAgICAgdmFyIG1zID0gZGF0ZVRpbWUybXModiwgY2FsZW5kYXIgfHwgYXguY2FsZW5kYXIpO1xuICAgICAgICBpZihtcyA9PT0gQkFETlVNKSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWModikpIHtcbiAgICAgICAgICAgICAgICB2ID0gK3Y7XG4gICAgICAgICAgICAgICAgLy8ga2VlcCB0cmFjayBvZiB0ZW50aHMgb2YgbXMsIHRoYXQgYG5ldyBEYXRlYCB3aWxsIGRyb3BcbiAgICAgICAgICAgICAgICAvLyBzYW1lIGxvZ2ljIGFzIGluIExpYi5tczJEYXRlVGltZVxuICAgICAgICAgICAgICAgIHZhciBtc2VjVGVudGhzID0gTWF0aC5mbG9vcihMaWIubW9kKHYgKyAwLjA1LCAxKSAqIDEwKTtcbiAgICAgICAgICAgICAgICB2YXIgbXNSb3VuZGVkID0gTWF0aC5yb3VuZCh2IC0gbXNlY1RlbnRocyAvIDEwKTtcbiAgICAgICAgICAgICAgICBtcyA9IGRhdGVUaW1lMm1zKG5ldyBEYXRlKG1zUm91bmRlZCkpICsgbXNlY1RlbnRocyAvIDEwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSByZXR1cm4gQkFETlVNO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtcztcbiAgICB9XG5cbiAgICAvLyB3cmFwcGVkIG1zMkRhdGVUaW1lIHRvIGluc2VydCBkZWZhdWx0IGF4LmNhbGVuZGFyXG4gICAgZnVuY3Rpb24gbXMyZHQodiwgciwgY2FsZW5kYXIpIHtcbiAgICAgICAgcmV0dXJuIG1zMkRhdGVUaW1lKHYsIHIsIGNhbGVuZGFyIHx8IGF4LmNhbGVuZGFyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDYXRlZ29yeU5hbWUodikge1xuICAgICAgICByZXR1cm4gYXguX2NhdGVnb3JpZXNbTWF0aC5yb3VuZCh2KV07XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBzZXRDYXRlZ29yeUluZGV4OiByZXR1cm4gdGhlIGluZGV4IG9mIGNhdGVnb3J5IHYsXG4gICAgICogaW5zZXJ0aW5nIGl0IGluIHRoZSBsaXN0IGlmIGl0J3Mgbm90IGFscmVhZHkgdGhlcmVcbiAgICAgKlxuICAgICAqIHRoaXMgd2lsbCBlbnRlciB0aGUgY2F0ZWdvcmllcyBpbiB0aGUgb3JkZXIgaXRcbiAgICAgKiBlbmNvdW50ZXJzIHRoZW0sIGllIGFsbCB0aGUgY2F0ZWdvcmllcyBmcm9tIHRoZVxuICAgICAqIGZpcnN0IGRhdGEgc2V0LCB0aGVuIGFsbCB0aGUgb25lcyBmcm9tIHRoZSBzZWNvbmRcbiAgICAgKiB0aGF0IGFyZW4ndCBpbiB0aGUgZmlyc3QgZXRjLlxuICAgICAqXG4gICAgICogaXQgaXMgYXNzdW1lZCB0aGF0IHRoaXMgZnVuY3Rpb24gaXMgYmVpbmcgaW52b2tlZCBpbiB0aGVcbiAgICAgKiBhbHJlYWR5IHNvcnRlZCBjYXRlZ29yeSBvcmRlcjsgb3RoZXJ3aXNlIHRoZXJlIHdvdWxkIGJlXG4gICAgICogYSBkaXNjb25uZWN0IGJldHdlZW4gdGhlIGFycmF5IGFuZCB0aGUgaW5kZXggcmV0dXJuZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRDYXRlZ29yeUluZGV4KHYpIHtcbiAgICAgICAgaWYodiAhPT0gbnVsbCAmJiB2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKGF4Ll9jYXRlZ29yaWVzTWFwID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBheC5fY2F0ZWdvcmllc01hcCA9IHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihheC5fY2F0ZWdvcmllc01hcFt2XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF4Ll9jYXRlZ29yaWVzTWFwW3ZdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBheC5fY2F0ZWdvcmllcy5wdXNoKHYpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGN1ckxlbmd0aCA9IGF4Ll9jYXRlZ29yaWVzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgYXguX2NhdGVnb3JpZXNNYXBbdl0gPSBjdXJMZW5ndGg7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gY3VyTGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBCQUROVU07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2F0ZWdvcnlJbmRleCh2KSB7XG4gICAgICAgIC8vIGQybC9kMmMgdmFyaWFudCB0aGF0IHRoYXQgd29uJ3QgYWRkIGNhdGVnb3JpZXMgYnV0IHdpbGwgYWxzb1xuICAgICAgICAvLyBhbGxvdyBudW1iZXJzIHRvIGJlIG1hcHBlZCB0byB0aGUgbGluZWFyaXplZCBheGlzIHBvc2l0aW9uc1xuICAgICAgICBpZihheC5fY2F0ZWdvcmllc01hcCkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gYXguX2NhdGVnb3JpZXNNYXBbdl07XG4gICAgICAgICAgICBpZihpbmRleCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpc051bWVyaWModikpIHJldHVybiArdjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsMnAodikge1xuICAgICAgICBpZighaXNOdW1lcmljKHYpKSByZXR1cm4gQkFETlVNO1xuXG4gICAgICAgIC8vIGluY2x1ZGUgMiBmcmFjdGlvbmFsIGRpZ2l0cyBvbiBwaXhlbCwgZm9yIFBERiB6b29taW5nIGV0Y1xuICAgICAgICByZXR1cm4gZDMucm91bmQoYXguX2IgKyBheC5fbSAqIHYsIDIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHAybChweCkgeyByZXR1cm4gKHB4IC0gYXguX2IpIC8gYXguX207IH1cblxuICAgIC8vIGNvbnZlcnNpb25zIGFtb25nIGMvbC9wIGFyZSBmYWlybHkgc2ltcGxlIC0gZG8gdGhlbSB0b2dldGhlciBmb3IgYWxsIGF4aXMgdHlwZXNcbiAgICBheC5jMmwgPSAoYXgudHlwZSA9PT0gJ2xvZycpID8gdG9Mb2cgOiBlbnN1cmVOdW1iZXI7XG4gICAgYXgubDJjID0gKGF4LnR5cGUgPT09ICdsb2cnKSA/IGZyb21Mb2cgOiBlbnN1cmVOdW1iZXI7XG5cbiAgICBheC5sMnAgPSBsMnA7XG4gICAgYXgucDJsID0gcDJsO1xuXG4gICAgYXguYzJwID0gKGF4LnR5cGUgPT09ICdsb2cnKSA/IGZ1bmN0aW9uKHYsIGNsaXApIHsgcmV0dXJuIGwycCh0b0xvZyh2LCBjbGlwKSk7IH0gOiBsMnA7XG4gICAgYXgucDJjID0gKGF4LnR5cGUgPT09ICdsb2cnKSA/IGZ1bmN0aW9uKHB4KSB7IHJldHVybiBmcm9tTG9nKHAybChweCkpOyB9IDogcDJsO1xuXG4gICAgLypcbiAgICAgKiBub3cgdHlwZS1zcGVjaWZpYyBjb252ZXJzaW9ucyBmb3IgKipBTEwqKiBvdGhlciBjb21iaW5hdGlvbnNcbiAgICAgKiB0aGV5J3JlIGFsbCB3cml0dGVuIG91dCwgaW5zdGVhZCBvZiBiZWluZyBjb21iaW5hdGlvbnMgb2YgZWFjaCBvdGhlciwgZm9yXG4gICAgICogYm90aCBjbGFyaXR5IGFuZCBzcGVlZC5cbiAgICAgKi9cbiAgICBpZihbJ2xpbmVhcicsICctJ10uaW5kZXhPZihheC50eXBlKSAhPT0gLTEpIHtcbiAgICAgICAgLy8gYWxsIGFyZSBkYXRhIHZhbHMsIGJ1dCBkIGFuZCByIG5lZWQgY2xlYW5pbmdcbiAgICAgICAgYXguZDJyID0gYXgucjJkID0gYXguZDJjID0gYXgucjJjID0gYXguZDJsID0gYXgucjJsID0gY2xlYW5OdW1iZXI7XG4gICAgICAgIGF4LmMyZCA9IGF4LmMyciA9IGF4LmwyZCA9IGF4LmwyciA9IGVuc3VyZU51bWJlcjtcblxuICAgICAgICBheC5kMnAgPSBheC5yMnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5sMnAoY2xlYW5OdW1iZXIodikpOyB9O1xuICAgICAgICBheC5wMmQgPSBheC5wMnIgPSBwMmw7XG5cbiAgICAgICAgYXguY2xlYW5Qb3MgPSBlbnN1cmVOdW1iZXI7XG4gICAgfVxuICAgIGVsc2UgaWYoYXgudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgLy8gZCBhbmQgYyBhcmUgZGF0YSB2YWxzLCByIGFuZCBsIGFyZSBsb2dnZWQgKGJ1dCBkIGFuZCByIG5lZWQgY2xlYW5pbmcpXG4gICAgICAgIGF4LmQyciA9IGF4LmQybCA9IGZ1bmN0aW9uKHYsIGNsaXApIHsgcmV0dXJuIHRvTG9nKGNsZWFuTnVtYmVyKHYpLCBjbGlwKTsgfTtcbiAgICAgICAgYXgucjJkID0gYXgucjJjID0gZnVuY3Rpb24odikgeyByZXR1cm4gZnJvbUxvZyhjbGVhbk51bWJlcih2KSk7IH07XG5cbiAgICAgICAgYXguZDJjID0gYXgucjJsID0gY2xlYW5OdW1iZXI7XG4gICAgICAgIGF4LmMyZCA9IGF4LmwyciA9IGVuc3VyZU51bWJlcjtcblxuICAgICAgICBheC5jMnIgPSB0b0xvZztcbiAgICAgICAgYXgubDJkID0gZnJvbUxvZztcblxuICAgICAgICBheC5kMnAgPSBmdW5jdGlvbih2LCBjbGlwKSB7IHJldHVybiBheC5sMnAoYXguZDJyKHYsIGNsaXApKTsgfTtcbiAgICAgICAgYXgucDJkID0gZnVuY3Rpb24ocHgpIHsgcmV0dXJuIGZyb21Mb2cocDJsKHB4KSk7IH07XG5cbiAgICAgICAgYXgucjJwID0gZnVuY3Rpb24odikgeyByZXR1cm4gYXgubDJwKGNsZWFuTnVtYmVyKHYpKTsgfTtcbiAgICAgICAgYXgucDJyID0gcDJsO1xuXG4gICAgICAgIGF4LmNsZWFuUG9zID0gZW5zdXJlTnVtYmVyO1xuICAgIH1cbiAgICBlbHNlIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAvLyByIGFuZCBkIGFyZSBkYXRlIHN0cmluZ3MsIGwgYW5kIGMgYXJlIG1zXG5cbiAgICAgICAgLypcbiAgICAgICAgICogQW55IG9mIHRoZXNlIGZ1bmN0aW9ucyB3aXRoIHIgYW5kIGQgb24gZWl0aGVyIHNpZGUsIGNhbGVuZGFyIGlzIHRoZVxuICAgICAgICAgKiAqKjNyZCoqIGFyZ3VtZW50LiBsb2cgaGFzIHJlc2VydmVkIHRoZSBzZWNvbmQgYXJndW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIFVubGVzcyB5b3UgbmVlZCB0aGUgc3BlY2lhbCBiZWhhdmlvciBvZiB0aGUgc2Vjb25kIGFyZyAobXMyRGF0ZVRpbWVcbiAgICAgICAgICogdXNlcyB0aGlzIHRvIGxpbWl0IHByZWNpc2lvbiwgdG9Mb2cgdXNlcyB0cnVlIHRvIGNsaXAgbmVnYXRpdmVzXG4gICAgICAgICAqIHRvIG9mZnNjcmVlbiBsb3cgcmF0aGVyIHRoYW4gdW5kZWZpbmVkKSwgaXQncyBzYWZlIHRvIHBhc3MgMC5cbiAgICAgICAgICovXG4gICAgICAgIGF4LmQyciA9IGF4LnIyZCA9IExpYi5pZGVudGl0eTtcblxuICAgICAgICBheC5kMmMgPSBheC5yMmMgPSBheC5kMmwgPSBheC5yMmwgPSBkdDJtcztcbiAgICAgICAgYXguYzJkID0gYXguYzJyID0gYXgubDJkID0gYXgubDJyID0gbXMyZHQ7XG5cbiAgICAgICAgYXguZDJwID0gYXgucjJwID0gZnVuY3Rpb24odiwgXywgY2FsZW5kYXIpIHsgcmV0dXJuIGF4LmwycChkdDJtcyh2LCAwLCBjYWxlbmRhcikpOyB9O1xuICAgICAgICBheC5wMmQgPSBheC5wMnIgPSBmdW5jdGlvbihweCwgciwgY2FsZW5kYXIpIHsgcmV0dXJuIG1zMmR0KHAybChweCksIHIsIGNhbGVuZGFyKTsgfTtcblxuICAgICAgICBheC5jbGVhblBvcyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIExpYi5jbGVhbkRhdGUodiwgQkFETlVNLCBheC5jYWxlbmRhcik7IH07XG4gICAgfVxuICAgIGVsc2UgaWYoYXgudHlwZSA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICAvLyBkIGlzIGNhdGVnb3JpZXMgKHN0cmluZylcbiAgICAgICAgLy8gYyBhbmQgbCBhcmUgaW5kaWNlcyAobnVtYmVycylcbiAgICAgICAgLy8gciBpcyBjYXRlZ29yaWVzIG9yIG51bWJlcnNcblxuICAgICAgICBheC5kMmMgPSBheC5kMmwgPSBzZXRDYXRlZ29yeUluZGV4O1xuICAgICAgICBheC5yMmQgPSBheC5jMmQgPSBheC5sMmQgPSBnZXRDYXRlZ29yeU5hbWU7XG5cbiAgICAgICAgYXguZDJyID0gYXguZDJsX25vYWRkID0gZ2V0Q2F0ZWdvcnlJbmRleDtcblxuICAgICAgICBheC5yMmMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICB2YXIgaW5kZXggPSBnZXRDYXRlZ29yeUluZGV4KHYpO1xuICAgICAgICAgICAgcmV0dXJuIGluZGV4ICE9PSB1bmRlZmluZWQgPyBpbmRleCA6IGF4LmZyYWN0aW9uMnIoMC41KTtcbiAgICAgICAgfTtcblxuICAgICAgICBheC5sMnIgPSBheC5jMnIgPSBlbnN1cmVOdW1iZXI7XG4gICAgICAgIGF4LnIybCA9IGdldENhdGVnb3J5SW5kZXg7XG5cbiAgICAgICAgYXguZDJwID0gZnVuY3Rpb24odikgeyByZXR1cm4gYXgubDJwKGF4LnIyYyh2KSk7IH07XG4gICAgICAgIGF4LnAyZCA9IGZ1bmN0aW9uKHB4KSB7IHJldHVybiBnZXRDYXRlZ29yeU5hbWUocDJsKHB4KSk7IH07XG4gICAgICAgIGF4LnIycCA9IGF4LmQycDtcbiAgICAgICAgYXgucDJyID0gcDJsO1xuXG4gICAgICAgIGF4LmNsZWFuUG9zID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgaWYodHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYgIT09ICcnKSByZXR1cm4gdjtcbiAgICAgICAgICAgIHJldHVybiBlbnN1cmVOdW1iZXIodik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gZmluZCB0aGUgcmFuZ2UgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCAobGluZWFyKSBmcmFjdGlvbiBvZiB0aGUgYXhpc1xuICAgIGF4LmZyYWN0aW9uMnIgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBybDAgPSBheC5yMmwoYXgucmFuZ2VbMF0pLFxuICAgICAgICAgICAgcmwxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcbiAgICAgICAgcmV0dXJuIGF4LmwycihybDAgKyB2ICogKHJsMSAtIHJsMCkpO1xuICAgIH07XG5cbiAgICAvLyBmaW5kIHRoZSBmcmFjdGlvbiBvZiB0aGUgcmFuZ2UgYXQgdGhlIHNwZWNpZmllZCByYW5nZSB2YWx1ZVxuICAgIGF4LnIyZnJhY3Rpb24gPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBybDAgPSBheC5yMmwoYXgucmFuZ2VbMF0pLFxuICAgICAgICAgICAgcmwxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcbiAgICAgICAgcmV0dXJuIChheC5yMmwodikgLSBybDApIC8gKHJsMSAtIHJsMCk7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogY2xlYW5SYW5nZTogbWFrZSBzdXJlIHJhbmdlIGlzIGEgY291cGxldCBvZiB2YWxpZCAmIGRpc3RpbmN0IHZhbHVlc1xuICAgICAqIGtlZXAgbnVtYmVycyBhd2F5IGZyb20gdGhlIGxpbWl0cyBvZiBmbG9hdGluZyBwb2ludCBudW1iZXJzLFxuICAgICAqIGFuZCBkYXRlcyBhd2F5IGZyb20gdGhlIGVuZHMgb2Ygb3VyIGRhdGUgc3lzdGVtICgrLy0gOTk5OSB5ZWFycylcbiAgICAgKlxuICAgICAqIG9wdGlvbmFsIHBhcmFtIHJhbmdlQXR0cjogb3BlcmF0ZSBvbiBhIGRpZmZlcmVudCBhdHRyaWJ1dGUsIGxpa2VcbiAgICAgKiBheC5fciwgcmF0aGVyIHRoYW4gYXgucmFuZ2VcbiAgICAgKi9cbiAgICBheC5jbGVhblJhbmdlID0gZnVuY3Rpb24ocmFuZ2VBdHRyLCBvcHRzKSB7XG4gICAgICAgIGlmKCFvcHRzKSBvcHRzID0ge307XG4gICAgICAgIGlmKCFyYW5nZUF0dHIpIHJhbmdlQXR0ciA9ICdyYW5nZSc7XG5cbiAgICAgICAgdmFyIHJhbmdlID0gTGliLm5lc3RlZFByb3BlcnR5KGF4LCByYW5nZUF0dHIpLmdldCgpO1xuICAgICAgICB2YXIgaSwgZGZsdDtcblxuICAgICAgICBpZihheC50eXBlID09PSAnZGF0ZScpIGRmbHQgPSBMaWIuZGZsdFJhbmdlKGF4LmNhbGVuZGFyKTtcbiAgICAgICAgZWxzZSBpZihheExldHRlciA9PT0gJ3knKSBkZmx0ID0gY29uc3RhbnRzLkRGTFRSQU5HRVk7XG4gICAgICAgIGVsc2UgZGZsdCA9IG9wdHMuZGZsdFJhbmdlIHx8IGNvbnN0YW50cy5ERkxUUkFOR0VYO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSBkb24ndCBsYXRlciBtdXRhdGUgdGhlIGRlZmF1bHRzXG4gICAgICAgIGRmbHQgPSBkZmx0LnNsaWNlKCk7XG5cbiAgICAgICAgaWYoIXJhbmdlIHx8IHJhbmdlLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KGF4LCByYW5nZUF0dHIpLnNldChkZmx0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgLy8gY2hlY2sgaWYgbWlsbGlzZWNvbmRzIG9yIGpzIGRhdGUgb2JqZWN0cyBhcmUgcHJvdmlkZWQgZm9yIHJhbmdlXG4gICAgICAgICAgICAvLyBhbmQgY29udmVydCB0byBkYXRlIHN0cmluZ3NcbiAgICAgICAgICAgIHJhbmdlWzBdID0gTGliLmNsZWFuRGF0ZShyYW5nZVswXSwgQkFETlVNLCBheC5jYWxlbmRhcik7XG4gICAgICAgICAgICByYW5nZVsxXSA9IExpYi5jbGVhbkRhdGUocmFuZ2VbMV0sIEJBRE5VTSwgYXguY2FsZW5kYXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgICAgICBpZihheC50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgICAgICBpZighTGliLmlzRGF0ZVRpbWUocmFuZ2VbaV0sIGF4LmNhbGVuZGFyKSkge1xuICAgICAgICAgICAgICAgICAgICBheFtyYW5nZUF0dHJdID0gZGZsdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoYXgucjJsKHJhbmdlWzBdKSA9PT0gYXgucjJsKHJhbmdlWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzcGxpdCBieSArLy0gMSBzZWNvbmRcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxpbkNlbnRlciA9IExpYi5jb25zdHJhaW4oYXgucjJsKHJhbmdlWzBdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIExpYi5NSU5fTVMgKyAxMDAwLCBMaWIuTUFYX01TIC0gMTAwMCk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlWzBdID0gYXgubDJyKGxpbkNlbnRlciAtIDEwMDApO1xuICAgICAgICAgICAgICAgICAgICByYW5nZVsxXSA9IGF4LmwycihsaW5DZW50ZXIgKyAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhyYW5nZVtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKHJhbmdlWzEgLSBpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlW2ldID0gcmFuZ2VbMSAtIGldICogKGkgPyAxMCA6IDAuMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBheFtyYW5nZUF0dHJdID0gZGZsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYocmFuZ2VbaV0gPCAtRlBfU0FGRSkgcmFuZ2VbaV0gPSAtRlBfU0FGRTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmKHJhbmdlW2ldID4gRlBfU0FGRSkgcmFuZ2VbaV0gPSBGUF9TQUZFO1xuXG4gICAgICAgICAgICAgICAgaWYocmFuZ2VbMF0gPT09IHJhbmdlWzFdKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNvbWV3aGF0IGFyYml0cmFyeTogc3BsaXQgYnkgMSBvciAxcHBtLCB3aGljaGV2ZXIgaXMgYmlnZ2VyXG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmMgPSBNYXRoLm1heCgxLCBNYXRoLmFicyhyYW5nZVswXSAqIDFlLTYpKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VbMF0gLT0gaW5jO1xuICAgICAgICAgICAgICAgICAgICByYW5nZVsxXSArPSBpbmM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIHNldCBzY2FsaW5nIHRvIHBpeGVsc1xuICAgIGF4LnNldFNjYWxlID0gZnVuY3Rpb24odXNlUHJpdmF0ZVJhbmdlKSB7XG4gICAgICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICAgICAgLy8gVE9ETyBjbGVhbmVyIHdheSB0byBoYW5kbGUgdGhpcyBjYXNlXG4gICAgICAgIGlmKCFheC5fY2F0ZWdvcmllcykgYXguX2NhdGVnb3JpZXMgPSBbXTtcbiAgICAgICAgLy8gQWRkIGEgbWFwIHRvIG9wdGltaXplIHRoZSBwZXJmb3JtYW5jZSBvZiBjYXRlZ29yeSBjb2xsZWN0aW9uXG4gICAgICAgIGlmKCFheC5fY2F0ZWdvcmllc01hcCkgYXguX2NhdGVnb3JpZXNNYXAgPSB7fTtcblxuICAgICAgICAvLyBtYWtlIHN1cmUgd2UgaGF2ZSBhIGRvbWFpbiAocHVsbCBpdCBpbiBmcm9tIHRoZSBheGlzXG4gICAgICAgIC8vIHRoaXMgb25lIGlzIG92ZXJsYXlpbmcgaWYgbmVjZXNzYXJ5KVxuICAgICAgICBpZihheC5vdmVybGF5aW5nKSB7XG4gICAgICAgICAgICB2YXIgYXgyID0gYXhpc0lkcy5nZXRGcm9tSWQoeyBfZnVsbExheW91dDogZnVsbExheW91dCB9LCBheC5vdmVybGF5aW5nKTtcbiAgICAgICAgICAgIGF4LmRvbWFpbiA9IGF4Mi5kb21haW47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaGlsZSB0cmFuc2l0aW9ucyBhcmUgb2NjdXJpbmcsIG9jY3VycmluZywgd2UgZ2V0IGEgZG91YmxlLXRyYW5zZm9ybVxuICAgICAgICAvLyBpc3N1ZSBpZiB3ZSB0cmFuc2Zvcm0gdGhlIGRyYXduIGxheWVyICphbmQqIHVzZSB0aGUgbmV3IGF4aXMgcmFuZ2UgdG9cbiAgICAgICAgLy8gZHJhdyB0aGUgZGF0YS4gVGhpcyBhbGxvd3MgdXMgdG8gY29uc3RydWN0IHNldENvbnZlcnQgdXNpbmcgdGhlIHByZS1cbiAgICAgICAgLy8gaW50ZXJhY3Rpb24gdmFsdWVzIG9mIHRoZSByYW5nZTpcbiAgICAgICAgdmFyIHJhbmdlQXR0ciA9ICh1c2VQcml2YXRlUmFuZ2UgJiYgYXguX3IpID8gJ19yJyA6ICdyYW5nZScsXG4gICAgICAgICAgICBjYWxlbmRhciA9IGF4LmNhbGVuZGFyO1xuICAgICAgICBheC5jbGVhblJhbmdlKHJhbmdlQXR0cik7XG5cbiAgICAgICAgdmFyIHJsMCA9IGF4LnIybChheFtyYW5nZUF0dHJdWzBdLCBjYWxlbmRhciksXG4gICAgICAgICAgICBybDEgPSBheC5yMmwoYXhbcmFuZ2VBdHRyXVsxXSwgY2FsZW5kYXIpO1xuXG4gICAgICAgIGlmKGF4TGV0dGVyID09PSAneScpIHtcbiAgICAgICAgICAgIGF4Ll9vZmZzZXQgPSBncy50ICsgKDEgLSBheC5kb21haW5bMV0pICogZ3MuaDtcbiAgICAgICAgICAgIGF4Ll9sZW5ndGggPSBncy5oICogKGF4LmRvbWFpblsxXSAtIGF4LmRvbWFpblswXSk7XG4gICAgICAgICAgICBheC5fbSA9IGF4Ll9sZW5ndGggLyAocmwwIC0gcmwxKTtcbiAgICAgICAgICAgIGF4Ll9iID0gLWF4Ll9tICogcmwxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXguX29mZnNldCA9IGdzLmwgKyBheC5kb21haW5bMF0gKiBncy53O1xuICAgICAgICAgICAgYXguX2xlbmd0aCA9IGdzLncgKiAoYXguZG9tYWluWzFdIC0gYXguZG9tYWluWzBdKTtcbiAgICAgICAgICAgIGF4Ll9tID0gYXguX2xlbmd0aCAvIChybDEgLSBybDApO1xuICAgICAgICAgICAgYXguX2IgPSAtYXguX20gKiBybDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZighaXNGaW5pdGUoYXguX20pIHx8ICFpc0Zpbml0ZShheC5fYikpIHtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX3JlcGxvdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCBheGlzIHNjYWxpbmcnKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBtYWtlQ2FsY2RhdGE6IHRha2VzIGFuIHggb3IgeSBhcnJheSBhbmQgY29udmVydHMgaXRcbiAgICAvLyB0byBhIHBvc2l0aW9uIG9uIHRoZSBheGlzIG9iamVjdCBcImF4XCJcbiAgICAvLyBpbnB1dHM6XG4gICAgLy8gICAgICB0cmFjZSAtIGEgZGF0YSBvYmplY3QgZnJvbSBnZC5kYXRhXG4gICAgLy8gICAgICBheExldHRlciAtIGEgc3RyaW5nLCBlaXRoZXIgJ3gnIG9yICd5JywgZm9yIHdoaWNoIGl0ZW1cbiAgICAvLyAgICAgICAgICB0byBjb252ZXJ0IChUT0RPOiBpcyB0aGlzIG5vdyBhbHdheXMgdGhlIHNhbWUgYXNcbiAgICAvLyAgICAgICAgICB0aGUgZmlyc3QgbGV0dGVyIG9mIGF4Ll9pZD8pXG4gICAgLy8gaW4gY2FzZSB0aGUgZXhwZWN0ZWQgZGF0YSBpc24ndCB0aGVyZSwgbWFrZSBhIGxpc3Qgb2ZcbiAgICAvLyBpbnRlZ2VycyBiYXNlZCBvbiB0aGUgb3Bwb3NpdGUgZGF0YVxuICAgIGF4Lm1ha2VDYWxjZGF0YSA9IGZ1bmN0aW9uKHRyYWNlLCBheExldHRlcikge1xuICAgICAgICB2YXIgYXJyYXlJbiwgYXJyYXlPdXQsIGksIGxlbjtcblxuICAgICAgICB2YXIgYXhUeXBlID0gYXgudHlwZTtcbiAgICAgICAgdmFyIGNhbCA9IGF4VHlwZSA9PT0gJ2RhdGUnICYmIHRyYWNlW2F4TGV0dGVyICsgJ2NhbGVuZGFyJ107XG5cbiAgICAgICAgaWYoYXhMZXR0ZXIgaW4gdHJhY2UpIHtcbiAgICAgICAgICAgIGFycmF5SW4gPSB0cmFjZVtheExldHRlcl07XG4gICAgICAgICAgICBsZW4gPSB0cmFjZS5fbGVuZ3RoIHx8IGFycmF5SW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KGFycmF5SW4pICYmIChheFR5cGUgPT09ICdsaW5lYXInIHx8IGF4VHlwZSA9PT0gJ2xvZycpKSB7XG4gICAgICAgICAgICAgICAgaWYobGVuID09PSBhcnJheUluLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlJbjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoYXJyYXlJbi5zdWJhcnJheSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlJbi5zdWJhcnJheSgwLCBsZW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXJyYXlPdXQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYXJyYXlPdXRbaV0gPSBheC5kMmMoYXJyYXlJbltpXSwgMCwgY2FsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciB2MCA9ICgoYXhMZXR0ZXIgKyAnMCcpIGluIHRyYWNlKSA/IGF4LmQyYyh0cmFjZVtheExldHRlciArICcwJ10sIDAsIGNhbCkgOiAwO1xuICAgICAgICAgICAgdmFyIGR2ID0gKHRyYWNlWydkJyArIGF4TGV0dGVyXSkgPyBOdW1iZXIodHJhY2VbJ2QnICsgYXhMZXR0ZXJdKSA6IDE7XG5cbiAgICAgICAgICAgIC8vIHRoZSBvcHBvc2luZyBkYXRhLCBmb3Igc2l6ZSBpZiB3ZSBoYXZlIHggYW5kIGR4IGV0Y1xuICAgICAgICAgICAgYXJyYXlJbiA9IHRyYWNlW3t4OiAneScsIHk6ICd4J31bYXhMZXR0ZXJdXTtcbiAgICAgICAgICAgIGxlbiA9IHRyYWNlLl9sZW5ndGggfHwgYXJyYXlJbi5sZW5ndGg7XG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGFycmF5T3V0W2ldID0gdjAgKyBpICogZHY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXJyYXlPdXQ7XG4gICAgfTtcblxuICAgIGF4LmlzVmFsaWRSYW5nZSA9IGZ1bmN0aW9uKHJhbmdlKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBBcnJheS5pc0FycmF5KHJhbmdlKSAmJlxuICAgICAgICAgICAgcmFuZ2UubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgICBpc051bWVyaWMoYXgucjJsKHJhbmdlWzBdKSkgJiZcbiAgICAgICAgICAgIGlzTnVtZXJpYyhheC5yMmwocmFuZ2VbMV0pKVxuICAgICAgICApO1xuICAgIH07XG5cbiAgICBheC5pc1B0V2l0aGluUmFuZ2UgPSBmdW5jdGlvbihkLCBjYWxlbmRhcikge1xuICAgICAgICB2YXIgY29vcmQgPSBheC5jMmwoZFtheExldHRlcl0sIG51bGwsIGNhbGVuZGFyKTtcbiAgICAgICAgdmFyIHIwID0gYXgucjJsKGF4LnJhbmdlWzBdKTtcbiAgICAgICAgdmFyIHIxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcblxuICAgICAgICBpZihyMCA8IHIxKSB7XG4gICAgICAgICAgICByZXR1cm4gcjAgPD0gY29vcmQgJiYgY29vcmQgPD0gcjE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZXZlcnNlZCBheGlzIGNhc2UuXG4gICAgICAgICAgICByZXR1cm4gcjEgPD0gY29vcmQgJiYgY29vcmQgPD0gcjA7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgYXguY2xlYXJDYWxjID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIGluaXRpYWxpemUgdGhlIGNhdGVnb3J5IGxpc3QsIGlmIHRoZXJlIGlzIG9uZSwgc28gd2Ugc3RhcnQgb3ZlclxuICAgICAgICAvLyB0byBiZSBmaWxsZWQgaW4gbGF0ZXIgYnkgYXguZDJjXG4gICAgICAgIGF4Ll9jYXRlZ29yaWVzID0gKGF4Ll9pbml0aWFsQ2F0ZWdvcmllcyB8fCBbXSkuc2xpY2UoKTtcblxuICAgICAgICAvLyBCdWlsZCB0aGUgbG9va3VwIG1hcCBmb3IgaW5pdGlhbGl6ZWQgY2F0ZWdvcmllc1xuICAgICAgICBheC5fY2F0ZWdvcmllc01hcCA9IHt9O1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYXguX2NhdGVnb3JpZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGF4Ll9jYXRlZ29yaWVzTWFwW2F4Ll9jYXRlZ29yaWVzW2pdXSA9IGo7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gUHJvcGFnYXRlIGxvY2FsaXphdGlvbiBpbnRvIHRoZSBheGlzIHNvIHRoYXRcbiAgICAvLyBtZXRob2RzIGluIEF4ZXMgY2FuIHVzZSBpdCB3L28gaGF2aW5nIHRvIHBhc3MgZnVsbExheW91dFxuICAgIC8vIERlZmF1bHQgKG5vbi1kMykgbnVtYmVyIGZvcm1hdHRpbmcgdXNlcyBzZXBhcmF0b3JzIGRpcmVjdGx5XG4gICAgLy8gZGF0ZXMgYW5kIGQzLWZvcm1hdHRlZCBudW1iZXJzIHVzZSB0aGUgZDMgbG9jYWxlXG4gICAgLy8gRmFsbCBiYWNrIG9uIGRlZmF1bHQgZm9ybWF0IGZvciBkdW1teSBheGVzIHRoYXQgZG9uJ3QgY2FyZSBhYm91dCBmb3JtYXR0aW5nXG4gICAgdmFyIGxvY2FsZSA9IGZ1bGxMYXlvdXQuX2QzbG9jYWxlO1xuICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICBheC5fZGF0ZUZvcm1hdCA9IGxvY2FsZSA/IGxvY2FsZS50aW1lRm9ybWF0LnV0YyA6IGQzLnRpbWUuZm9ybWF0LnV0YztcbiAgICAgICAgYXguX2V4dHJhRm9ybWF0ID0gZnVsbExheW91dC5fZXh0cmFGb3JtYXQ7XG4gICAgfVxuICAgIC8vIG9jY2FzaW9uYWxseSB3ZSBuZWVkIF9udW1Gb3JtYXQgdG8gcGFzcyB0aHJvdWdoXG4gICAgLy8gZXZlbiB0aG91Z2ggaXQgd29uJ3QgYmUgbmVlZGVkIGJ5IHRoaXMgYXhpc1xuICAgIGF4Ll9zZXBhcmF0b3JzID0gZnVsbExheW91dC5zZXBhcmF0b3JzO1xuICAgIGF4Ll9udW1Gb3JtYXQgPSBsb2NhbGUgPyBsb2NhbGUubnVtYmVyRm9ybWF0IDogZDMuZm9ybWF0O1xuXG4gICAgLy8gYW5kIGZvciBiYXIgY2hhcnRzIGFuZCBib3ggcGxvdHM6IHJlc2V0IGZvcmNlZCBtaW5pbXVtIHRpY2sgc3BhY2luZ1xuICAgIGRlbGV0ZSBheC5fbWluRHRpY2s7XG4gICAgZGVsZXRlIGF4Ll9mb3JjZVRpY2swO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUsIG9wdGlvbnMpIHtcbiAgICB2YXIgc2hvd0F0dHJEZmx0ID0gZ2V0U2hvd0F0dHJEZmx0KGNvbnRhaW5lckluKTtcblxuICAgIHZhciB0aWNrUHJlZml4ID0gY29lcmNlKCd0aWNrcHJlZml4Jyk7XG4gICAgaWYodGlja1ByZWZpeCkgY29lcmNlKCdzaG93dGlja3ByZWZpeCcsIHNob3dBdHRyRGZsdCk7XG5cbiAgICB2YXIgdGlja1N1ZmZpeCA9IGNvZXJjZSgndGlja3N1ZmZpeCcsIG9wdGlvbnMudGlja1N1ZmZpeERmbHQpO1xuICAgIGlmKHRpY2tTdWZmaXgpIGNvZXJjZSgnc2hvd3RpY2tzdWZmaXgnLCBzaG93QXR0ckRmbHQpO1xuXG4gICAgdmFyIHNob3dUaWNrTGFiZWxzID0gY29lcmNlKCdzaG93dGlja2xhYmVscycpO1xuICAgIGlmKHNob3dUaWNrTGFiZWxzKSB7XG4gICAgICAgIHZhciBmb250ID0gb3B0aW9ucy5mb250IHx8IHt9O1xuICAgICAgICB2YXIgY29udENvbG9yID0gY29udGFpbmVyT3V0LmNvbG9yO1xuICAgICAgICAvLyBhcyB3aXRoIHRpdGxlZm9udC5jb2xvciwgaW5oZXJpdCBheGlzLmNvbG9yIG9ubHkgaWYgb25lIHdhc1xuICAgICAgICAvLyBleHBsaWNpdGx5IHByb3ZpZGVkXG4gICAgICAgIHZhciBkZmx0Rm9udENvbG9yID0gKGNvbnRDb2xvciAmJiBjb250Q29sb3IgIT09IGxheW91dEF0dHJpYnV0ZXMuY29sb3IuZGZsdCkgP1xuICAgICAgICAgICAgY29udENvbG9yIDogZm9udC5jb2xvcjtcbiAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGlja2ZvbnQnLCB7XG4gICAgICAgICAgICBmYW1pbHk6IGZvbnQuZmFtaWx5LFxuICAgICAgICAgICAgc2l6ZTogZm9udC5zaXplLFxuICAgICAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgndGlja2FuZ2xlJyk7XG5cbiAgICAgICAgaWYoYXhUeXBlICE9PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgICAgICB2YXIgdGlja0Zvcm1hdCA9IGNvZXJjZSgndGlja2Zvcm1hdCcpO1xuICAgICAgICAgICAgdmFyIHRpY2tmb3JtYXRTdG9wcyA9IGNvbnRhaW5lckluLnRpY2tmb3JtYXRzdG9wcztcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGlja2Zvcm1hdFN0b3BzKSAmJiB0aWNrZm9ybWF0U3RvcHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6ICd0aWNrZm9ybWF0c3RvcHMnLFxuICAgICAgICAgICAgICAgICAgICBpbmNsdXNpb25BdHRyOiAnZW5hYmxlZCcsXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogdGlja2Zvcm1hdHN0b3BEZWZhdWx0c1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIXRpY2tGb3JtYXQgJiYgYXhUeXBlICE9PSAnZGF0ZScpIHtcbiAgICAgICAgICAgICAgICBjb2VyY2UoJ3Nob3dleHBvbmVudCcsIHNob3dBdHRyRGZsdCk7XG4gICAgICAgICAgICAgICAgY29lcmNlKCdleHBvbmVudGZvcm1hdCcpO1xuICAgICAgICAgICAgICAgIGNvZXJjZSgnc2VwYXJhdGV0aG91c2FuZHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qXG4gKiBBdHRyaWJ1dGVzICdzaG93ZXhwb25lbnQnLCAnc2hvd3RpY2twcmVmaXgnIGFuZCAnc2hvd3RpY2tzdWZmaXgnXG4gKiBzaGFyZSB2YWx1ZXMuXG4gKlxuICogSWYgb25seSAxIGF0dHJpYnV0ZSBpcyBzZXQsXG4gKiB0aGUgcmVtYWluaW5nIGF0dHJpYnV0ZXMgaW5oZXJpdCB0aGF0IHZhbHVlLlxuICpcbiAqIElmIDIgYXR0cmlidXRlcyBhcmUgc2V0IHRvIHRoZSBzYW1lIHZhbHVlLFxuICogdGhlIHJlbWFpbmluZyBhdHRyaWJ1dGUgaW5oZXJpdHMgdGhhdCB2YWx1ZS5cbiAqXG4gKiBJZiAyIGF0dHJpYnV0ZXMgYXJlIHNldCB0byBkaWZmZXJlbnQgdmFsdWVzLFxuICogdGhlIHJlbWFpbmluZyBpcyBzZXQgdG8gaXRzIGRmbHQgdmFsdWUuXG4gKlxuICovXG5mdW5jdGlvbiBnZXRTaG93QXR0ckRmbHQoY29udGFpbmVySW4pIHtcbiAgICB2YXIgc2hvd0F0dHJzQWxsID0gWydzaG93ZXhwb25lbnQnLFxuICAgICAgICAgICAgJ3Nob3d0aWNrcHJlZml4JyxcbiAgICAgICAgICAgICdzaG93dGlja3N1ZmZpeCddLFxuICAgICAgICBzaG93QXR0cnMgPSBzaG93QXR0cnNBbGwuZmlsdGVyKGZ1bmN0aW9uKGEpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250YWluZXJJblthXSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICB9KSxcbiAgICAgICAgc2FtZVZhbCA9IGZ1bmN0aW9uKGEpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250YWluZXJJblthXSA9PT0gY29udGFpbmVySW5bc2hvd0F0dHJzWzBdXTtcbiAgICAgICAgfTtcblxuICAgIGlmKHNob3dBdHRycy5ldmVyeShzYW1lVmFsKSB8fCBzaG93QXR0cnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBjb250YWluZXJJbltzaG93QXR0cnNbMF1dO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdGlja2Zvcm1hdHN0b3BEZWZhdWx0cyh2YWx1ZUluLCB2YWx1ZU91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHZhbHVlSW4sIHZhbHVlT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLnRpY2tmb3JtYXRzdG9wcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGVuYWJsZWQgPSBjb2VyY2UoJ2VuYWJsZWQnKTtcbiAgICBpZihlbmFibGVkKSB7XG4gICAgICAgIGNvZXJjZSgnZHRpY2tyYW5nZScpO1xuICAgICAgICBjb2VyY2UoJ3ZhbHVlJyk7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGxheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cblxuLyoqXG4gKiBvcHRpb25zOiBpbmhlcml0cyBvdXRlclRpY2tzIGZyb20gYXhlcy5oYW5kbGVBeGlzRGVmYXVsdHNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVUaWNrRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zKSB7XG4gICAgdmFyIHRpY2tMZW4gPSBMaWIuY29lcmNlMihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCAndGlja2xlbicpLFxuICAgICAgICB0aWNrV2lkdGggPSBMaWIuY29lcmNlMihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCAndGlja3dpZHRoJyksXG4gICAgICAgIHRpY2tDb2xvciA9IExpYi5jb2VyY2UyKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGxheW91dEF0dHJpYnV0ZXMsICd0aWNrY29sb3InLCBjb250YWluZXJPdXQuY29sb3IpLFxuICAgICAgICBzaG93VGlja3MgPSBjb2VyY2UoJ3RpY2tzJywgKG9wdGlvbnMub3V0ZXJUaWNrcyB8fCB0aWNrTGVuIHx8IHRpY2tXaWR0aCB8fCB0aWNrQ29sb3IpID8gJ291dHNpZGUnIDogJycpO1xuXG4gICAgaWYoIXNob3dUaWNrcykge1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnRpY2tsZW47XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja3dpZHRoO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnRpY2tjb2xvcjtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjbGVhblRpY2tzID0gcmVxdWlyZSgnLi9jbGVhbl90aWNrcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUpIHtcbiAgICB2YXIgdGlja21vZGU7XG5cbiAgICBpZihjb250YWluZXJJbi50aWNrbW9kZSA9PT0gJ2FycmF5JyAmJlxuICAgICAgICAgICAgKGF4VHlwZSA9PT0gJ2xvZycgfHwgYXhUeXBlID09PSAnZGF0ZScpKSB7XG4gICAgICAgIHRpY2ttb2RlID0gY29udGFpbmVyT3V0LnRpY2ttb2RlID0gJ2F1dG8nO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHRpY2ttb2RlRGVmYXVsdCA9XG4gICAgICAgICAgICBBcnJheS5pc0FycmF5KGNvbnRhaW5lckluLnRpY2t2YWxzKSA/ICdhcnJheScgOlxuICAgICAgICAgICAgY29udGFpbmVySW4uZHRpY2sgPyAnbGluZWFyJyA6XG4gICAgICAgICAgICAnYXV0byc7XG4gICAgICAgIHRpY2ttb2RlID0gY29lcmNlKCd0aWNrbW9kZScsIHRpY2ttb2RlRGVmYXVsdCk7XG4gICAgfVxuXG4gICAgaWYodGlja21vZGUgPT09ICdhdXRvJykgY29lcmNlKCdudGlja3MnKTtcbiAgICBlbHNlIGlmKHRpY2ttb2RlID09PSAnbGluZWFyJykge1xuICAgICAgICAvLyBkdGljayBpcyB1c3VhbGx5IGEgcG9zaXRpdmUgbnVtYmVyLCBidXQgdGhlcmUgYXJlIHNvbWVcbiAgICAgICAgLy8gc3BlY2lhbCBzdHJpbmdzIGF2YWlsYWJsZSBmb3IgbG9nIG9yIGRhdGUgYXhlc1xuICAgICAgICAvLyB0aWNrMCBhbHNvIGhhcyBzcGVjaWFsIGxvZ2ljXG4gICAgICAgIHZhciBkdGljayA9IGNvbnRhaW5lck91dC5kdGljayA9IGNsZWFuVGlja3MuZHRpY2soXG4gICAgICAgICAgICBjb250YWluZXJJbi5kdGljaywgYXhUeXBlKTtcbiAgICAgICAgY29udGFpbmVyT3V0LnRpY2swID0gY2xlYW5UaWNrcy50aWNrMChcbiAgICAgICAgICAgIGNvbnRhaW5lckluLnRpY2swLCBheFR5cGUsIGNvbnRhaW5lck91dC5jYWxlbmRhciwgZHRpY2spO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHRpY2t2YWxzID0gY29lcmNlKCd0aWNrdmFscycpO1xuICAgICAgICBpZih0aWNrdmFscyA9PT0gdW5kZWZpbmVkKSBjb250YWluZXJPdXQudGlja21vZGUgPSAnYXV0byc7XG4gICAgICAgIGVsc2UgY29lcmNlKCd0aWNrdGV4dCcpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuL2F4ZXMnKTtcbnZhciBheGlzUmVnZXggPSByZXF1aXJlKCcuL2NvbnN0YW50cycpLmF0dHJSZWdleDtcblxuZnVuY3Rpb24gdHJhbnNpdGlvbkF4ZXMoZ2QsIG5ld0xheW91dCwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBheGVzID0gW107XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlVXBkYXRlcyhsYXlvdXQpIHtcbiAgICAgICAgdmFyIGFpLCBhdHRyTGlzdCwgbWF0Y2gsIGF4aXMsIHVwZGF0ZTtcbiAgICAgICAgdmFyIHVwZGF0ZXMgPSB7fTtcblxuICAgICAgICBmb3IoYWkgaW4gbGF5b3V0KSB7XG4gICAgICAgICAgICBhdHRyTGlzdCA9IGFpLnNwbGl0KCcuJyk7XG4gICAgICAgICAgICBtYXRjaCA9IGF0dHJMaXN0WzBdLm1hdGNoKGF4aXNSZWdleCk7XG4gICAgICAgICAgICBpZihtYXRjaCkge1xuICAgICAgICAgICAgICAgIHZhciBheGlzTGV0dGVyID0gYWkuY2hhckF0KDApO1xuICAgICAgICAgICAgICAgIHZhciBheGlzTmFtZSA9IGF0dHJMaXN0WzBdO1xuICAgICAgICAgICAgICAgIGF4aXMgPSBmdWxsTGF5b3V0W2F4aXNOYW1lXTtcbiAgICAgICAgICAgICAgICB1cGRhdGUgPSB7fTtcblxuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkobGF5b3V0W2FpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlLnRvID0gbGF5b3V0W2FpXS5zbGljZSgwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGxheW91dFthaV0ucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGUudG8gPSBsYXlvdXRbYWldLnJhbmdlLnNsaWNlKDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKCF1cGRhdGUudG8pIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgdXBkYXRlLmF4aXNOYW1lID0gYXhpc05hbWU7XG4gICAgICAgICAgICAgICAgdXBkYXRlLmxlbmd0aCA9IGF4aXMuX2xlbmd0aDtcblxuICAgICAgICAgICAgICAgIGF4ZXMucHVzaChheGlzTGV0dGVyKTtcblxuICAgICAgICAgICAgICAgIHVwZGF0ZXNbYXhpc0xldHRlcl0gPSB1cGRhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdXBkYXRlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlQWZmZWN0ZWRTdWJwbG90cyhmdWxsTGF5b3V0LCB1cGRhdGVkQXhpc0lkcywgdXBkYXRlcykge1xuICAgICAgICB2YXIgcGxvdE5hbWU7XG4gICAgICAgIHZhciBwbG90aW5mb3MgPSBmdWxsTGF5b3V0Ll9wbG90cztcbiAgICAgICAgdmFyIGFmZmVjdGVkU3VicGxvdHMgPSBbXTtcbiAgICAgICAgdmFyIHRvWCwgdG9ZO1xuXG4gICAgICAgIGZvcihwbG90TmFtZSBpbiBwbG90aW5mb3MpIHtcbiAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IHBsb3RpbmZvc1twbG90TmFtZV07XG5cbiAgICAgICAgICAgIGlmKGFmZmVjdGVkU3VicGxvdHMuaW5kZXhPZihwbG90aW5mbykgIT09IC0xKSBjb250aW51ZTtcblxuICAgICAgICAgICAgdmFyIHggPSBwbG90aW5mby54YXhpcy5faWQ7XG4gICAgICAgICAgICB2YXIgeSA9IHBsb3RpbmZvLnlheGlzLl9pZDtcbiAgICAgICAgICAgIHZhciBmcm9tWCA9IHBsb3RpbmZvLnhheGlzLnJhbmdlO1xuICAgICAgICAgICAgdmFyIGZyb21ZID0gcGxvdGluZm8ueWF4aXMucmFuZ2U7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHJhbmdlIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhpcyB0cmFuc2l0aW9uOlxuICAgICAgICAgICAgcGxvdGluZm8ueGF4aXMuX3IgPSBwbG90aW5mby54YXhpcy5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWF4aXMuX3IgPSBwbG90aW5mby55YXhpcy5yYW5nZS5zbGljZSgpO1xuXG4gICAgICAgICAgICBpZih1cGRhdGVzW3hdKSB7XG4gICAgICAgICAgICAgICAgdG9YID0gdXBkYXRlc1t4XS50bztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG9YID0gZnJvbVg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih1cGRhdGVzW3ldKSB7XG4gICAgICAgICAgICAgICAgdG9ZID0gdXBkYXRlc1t5XS50bztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG9ZID0gZnJvbVk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGZyb21YWzBdID09PSB0b1hbMF0gJiYgZnJvbVhbMV0gPT09IHRvWFsxXSAmJiBmcm9tWVswXSA9PT0gdG9ZWzBdICYmIGZyb21ZWzFdID09PSB0b1lbMV0pIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBpZih1cGRhdGVkQXhpc0lkcy5pbmRleE9mKHgpICE9PSAtMSB8fCB1cGRhdGVkQXhpc0lkcy5pbmRleE9mKHkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGFmZmVjdGVkU3VicGxvdHMucHVzaChwbG90aW5mbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYWZmZWN0ZWRTdWJwbG90cztcbiAgICB9XG5cbiAgICB2YXIgdXBkYXRlcyA9IGNvbXB1dGVVcGRhdGVzKG5ld0xheW91dCk7XG4gICAgdmFyIHVwZGF0ZWRBeGlzSWRzID0gT2JqZWN0LmtleXModXBkYXRlcyk7XG4gICAgdmFyIGFmZmVjdGVkU3VicGxvdHMgPSBjb21wdXRlQWZmZWN0ZWRTdWJwbG90cyhmdWxsTGF5b3V0LCB1cGRhdGVkQXhpc0lkcywgdXBkYXRlcyk7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVMYXlvdXRPYmpzKCkge1xuICAgICAgICBmdW5jdGlvbiByZWRyYXdPYmpzKG9iakFycmF5LCBtZXRob2QsIHNob3J0Q2lyY3VpdCkge1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG9iakFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbWV0aG9kKGdkLCBpKTtcblxuICAgICAgICAgICAgICAgIC8vIG9uY2UgaXMgZW5vdWdoIGZvciBpbWFnZXMgKHdoaWNoIGRvZXNuJ3QgdXNlIHRoZSBgaWAgYXJnIGFueXdheSlcbiAgICAgICAgICAgICAgICBpZihzaG9ydENpcmN1aXQpIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlZHJhd09ianMoZnVsbExheW91dC5hbm5vdGF0aW9ucyB8fCBbXSwgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdkcmF3T25lJykpO1xuICAgICAgICByZWRyYXdPYmpzKGZ1bGxMYXlvdXQuc2hhcGVzIHx8IFtdLCBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3NoYXBlcycsICdkcmF3T25lJykpO1xuICAgICAgICByZWRyYXdPYmpzKGZ1bGxMYXlvdXQuaW1hZ2VzIHx8IFtdLCBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2ltYWdlcycsICdkcmF3JyksIHRydWUpO1xuICAgIH1cblxuICAgIGlmKCFhZmZlY3RlZFN1YnBsb3RzLmxlbmd0aCkge1xuICAgICAgICB1cGRhdGVMYXlvdXRPYmpzKCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0aWNrc0FuZEFubm90YXRpb25zKHhhLCB5YSkge1xuICAgICAgICB2YXIgYWN0aXZlQXhJZHMgPSBbXSxcbiAgICAgICAgICAgIGk7XG5cbiAgICAgICAgYWN0aXZlQXhJZHMgPSBbeGEuX2lkLCB5YS5faWRdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGFjdGl2ZUF4SWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBBeGVzLmRvVGlja3NTaW5nbGUoZ2QsIGFjdGl2ZUF4SWRzW2ldLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlZHJhd09ianMob2JqQXJyYXksIG1ldGhvZCwgc2hvcnRDaXJjdWl0KSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBvYmpBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBvYmppID0gb2JqQXJyYXlbaV07XG5cbiAgICAgICAgICAgICAgICBpZigoYWN0aXZlQXhJZHMuaW5kZXhPZihvYmppLnhyZWYpICE9PSAtMSkgfHxcbiAgICAgICAgICAgICAgICAgICAgKGFjdGl2ZUF4SWRzLmluZGV4T2Yob2JqaS55cmVmKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZChnZCwgaSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gb25jZSBpcyBlbm91Z2ggZm9yIGltYWdlcyAod2hpY2ggZG9lc24ndCB1c2UgdGhlIGBpYCBhcmcgYW55d2F5KVxuICAgICAgICAgICAgICAgIGlmKHNob3J0Q2lyY3VpdCkgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmVkcmF3T2JqcyhmdWxsTGF5b3V0LmFubm90YXRpb25zIHx8IFtdLCBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ2RyYXdPbmUnKSk7XG4gICAgICAgIHJlZHJhd09ianMoZnVsbExheW91dC5zaGFwZXMgfHwgW10sIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnc2hhcGVzJywgJ2RyYXdPbmUnKSk7XG4gICAgICAgIHJlZHJhd09ianMoZnVsbExheW91dC5pbWFnZXMgfHwgW10sIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnaW1hZ2VzJywgJ2RyYXcnKSwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdW5zZXRTdWJwbG90VHJhbnNmb3JtKHN1YnBsb3QpIHtcbiAgICAgICAgdmFyIHhhMiA9IHN1YnBsb3QueGF4aXM7XG4gICAgICAgIHZhciB5YTIgPSBzdWJwbG90LnlheGlzO1xuXG4gICAgICAgIGZ1bGxMYXlvdXQuX2RlZnMuc2VsZWN0KCcjJyArIHN1YnBsb3QuY2xpcElkICsgJz4gcmVjdCcpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgMCwgMClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEsIDEpO1xuXG4gICAgICAgIHN1YnBsb3QucGxvdFxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIHhhMi5fb2Zmc2V0LCB5YTIuX29mZnNldClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEsIDEpO1xuXG4gICAgICAgIHZhciB0cmFjZUdyb3VwcyA9IHN1YnBsb3QucGxvdC5zZWxlY3RBbGwoJy5zY2F0dGVybGF5ZXIgLnRyYWNlJyk7XG5cbiAgICAgICAgLy8gVGhpcyBpcyBzcGVjaWZpY2FsbHkgZGlyZWN0ZWQgYXQgc2NhdHRlciB0cmFjZXMsIGFwcGx5aW5nIGFuIGludmVyc2VcbiAgICAgICAgLy8gc2NhbGUgdG8gaW5kaXZpZHVhbCBwb2ludHMgdG8gY291bnRlcmFjdCB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlXG4gICAgICAgIC8vIGFzIGEgd2hvbGU6XG4gICAgICAgIHRyYWNlR3JvdXBzLnNlbGVjdEFsbCgnLnBvaW50JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlLCAxLCAxKTtcbiAgICAgICAgdHJhY2VHcm91cHMuc2VsZWN0QWxsKCcudGV4dHBvaW50JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlLCAxLCAxKTtcbiAgICAgICAgdHJhY2VHcm91cHNcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgc3VicGxvdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlU3VicGxvdChzdWJwbG90LCBwcm9ncmVzcykge1xuICAgICAgICB2YXIgYXhpcywgcjAsIHIxO1xuICAgICAgICB2YXIgeFVwZGF0ZSA9IHVwZGF0ZXNbc3VicGxvdC54YXhpcy5faWRdO1xuICAgICAgICB2YXIgeVVwZGF0ZSA9IHVwZGF0ZXNbc3VicGxvdC55YXhpcy5faWRdO1xuXG4gICAgICAgIHZhciB2aWV3Qm94ID0gW107XG5cbiAgICAgICAgaWYoeFVwZGF0ZSkge1xuICAgICAgICAgICAgYXhpcyA9IGdkLl9mdWxsTGF5b3V0W3hVcGRhdGUuYXhpc05hbWVdO1xuICAgICAgICAgICAgcjAgPSBheGlzLl9yO1xuICAgICAgICAgICAgcjEgPSB4VXBkYXRlLnRvO1xuICAgICAgICAgICAgdmlld0JveFswXSA9IChyMFswXSAqICgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiByMVswXSAtIHIwWzBdKSAvIChyMFsxXSAtIHIwWzBdKSAqIHN1YnBsb3QueGF4aXMuX2xlbmd0aDtcbiAgICAgICAgICAgIHZhciBkeDEgPSByMFsxXSAtIHIwWzBdO1xuICAgICAgICAgICAgdmFyIGR4MiA9IHIxWzFdIC0gcjFbMF07XG5cbiAgICAgICAgICAgIGF4aXMucmFuZ2VbMF0gPSByMFswXSAqICgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiByMVswXTtcbiAgICAgICAgICAgIGF4aXMucmFuZ2VbMV0gPSByMFsxXSAqICgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiByMVsxXTtcblxuICAgICAgICAgICAgdmlld0JveFsyXSA9IHN1YnBsb3QueGF4aXMuX2xlbmd0aCAqICgoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogZHgyIC8gZHgxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZpZXdCb3hbMF0gPSAwO1xuICAgICAgICAgICAgdmlld0JveFsyXSA9IHN1YnBsb3QueGF4aXMuX2xlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHlVcGRhdGUpIHtcbiAgICAgICAgICAgIGF4aXMgPSBnZC5fZnVsbExheW91dFt5VXBkYXRlLmF4aXNOYW1lXTtcbiAgICAgICAgICAgIHIwID0gYXhpcy5fcjtcbiAgICAgICAgICAgIHIxID0geVVwZGF0ZS50bztcbiAgICAgICAgICAgIHZpZXdCb3hbMV0gPSAocjBbMV0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogcjFbMV0gLSByMFsxXSkgLyAocjBbMF0gLSByMFsxXSkgKiBzdWJwbG90LnlheGlzLl9sZW5ndGg7XG4gICAgICAgICAgICB2YXIgZHkxID0gcjBbMV0gLSByMFswXTtcbiAgICAgICAgICAgIHZhciBkeTIgPSByMVsxXSAtIHIxWzBdO1xuXG4gICAgICAgICAgICBheGlzLnJhbmdlWzBdID0gcjBbMF0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogcjFbMF07XG4gICAgICAgICAgICBheGlzLnJhbmdlWzFdID0gcjBbMV0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogcjFbMV07XG5cbiAgICAgICAgICAgIHZpZXdCb3hbM10gPSBzdWJwbG90LnlheGlzLl9sZW5ndGggKiAoKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIGR5MiAvIGR5MSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2aWV3Qm94WzFdID0gMDtcbiAgICAgICAgICAgIHZpZXdCb3hbM10gPSBzdWJwbG90LnlheGlzLl9sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICB0aWNrc0FuZEFubm90YXRpb25zKHN1YnBsb3QueGF4aXMsIHN1YnBsb3QueWF4aXMpO1xuXG4gICAgICAgIHZhciB4YTIgPSBzdWJwbG90LnhheGlzO1xuICAgICAgICB2YXIgeWEyID0gc3VicGxvdC55YXhpcztcblxuICAgICAgICB2YXIgZWRpdFggPSAhIXhVcGRhdGU7XG4gICAgICAgIHZhciBlZGl0WSA9ICEheVVwZGF0ZTtcblxuICAgICAgICB2YXIgeFNjYWxlRmFjdG9yID0gZWRpdFggPyB4YTIuX2xlbmd0aCAvIHZpZXdCb3hbMl0gOiAxLFxuICAgICAgICAgICAgeVNjYWxlRmFjdG9yID0gZWRpdFkgPyB5YTIuX2xlbmd0aCAvIHZpZXdCb3hbM10gOiAxO1xuXG4gICAgICAgIHZhciBjbGlwRHggPSBlZGl0WCA/IHZpZXdCb3hbMF0gOiAwLFxuICAgICAgICAgICAgY2xpcER5ID0gZWRpdFkgPyB2aWV3Qm94WzFdIDogMDtcblxuICAgICAgICB2YXIgZnJhY0R4ID0gZWRpdFggPyAodmlld0JveFswXSAvIHZpZXdCb3hbMl0gKiB4YTIuX2xlbmd0aCkgOiAwLFxuICAgICAgICAgICAgZnJhY0R5ID0gZWRpdFkgPyAodmlld0JveFsxXSAvIHZpZXdCb3hbM10gKiB5YTIuX2xlbmd0aCkgOiAwO1xuXG4gICAgICAgIHZhciBwbG90RHggPSB4YTIuX29mZnNldCAtIGZyYWNEeCxcbiAgICAgICAgICAgIHBsb3REeSA9IHlhMi5fb2Zmc2V0IC0gZnJhY0R5O1xuXG4gICAgICAgIHN1YnBsb3QuY2xpcFJlY3RcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0VHJhbnNsYXRlLCBjbGlwRHgsIGNsaXBEeSlcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEgLyB4U2NhbGVGYWN0b3IsIDEgLyB5U2NhbGVGYWN0b3IpO1xuXG4gICAgICAgIHN1YnBsb3QucGxvdFxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIHBsb3REeCwgcGxvdER5KVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRTY2FsZSwgeFNjYWxlRmFjdG9yLCB5U2NhbGVGYWN0b3IpO1xuXG4gICAgICAgIC8vIGFwcGx5IGFuIGludmVyc2Ugc2NhbGUgdG8gaW5kaXZpZHVhbCBwb2ludHMgdG8gY291bnRlcmFjdFxuICAgICAgICAvLyB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlIGdyb3VwLlxuICAgICAgICBEcmF3aW5nLnNldFBvaW50R3JvdXBTY2FsZShzdWJwbG90Lnpvb21TY2FsZVB0cywgMSAvIHhTY2FsZUZhY3RvciwgMSAvIHlTY2FsZUZhY3Rvcik7XG4gICAgICAgIERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlKHN1YnBsb3Quem9vbVNjYWxlVHh0LCAxIC8geFNjYWxlRmFjdG9yLCAxIC8geVNjYWxlRmFjdG9yKTtcbiAgICB9XG5cbiAgICB2YXIgb25Db21wbGV0ZTtcbiAgICBpZihtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIC8vIFRoaXMgbW9kdWxlIG1ha2VzIHRoZSBjaG9pY2Ugd2hldGhlciBvciBub3QgaXQgbm90aWZpZXMgUGxvdGx5LnRyYW5zaXRpb25cbiAgICAgICAgLy8gYWJvdXQgY29tcGxldGlvbjpcbiAgICAgICAgb25Db21wbGV0ZSA9IG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uQ29tcGxldGUoKSB7XG4gICAgICAgIHZhciBhb2JqID0ge307XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB1cGRhdGVkQXhpc0lkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGF4aSA9IGdkLl9mdWxsTGF5b3V0W3VwZGF0ZXNbdXBkYXRlZEF4aXNJZHNbaV1dLmF4aXNOYW1lXTtcbiAgICAgICAgICAgIHZhciB0byA9IHVwZGF0ZXNbdXBkYXRlZEF4aXNJZHNbaV1dLnRvO1xuICAgICAgICAgICAgYW9ialtheGkuX25hbWUgKyAnLnJhbmdlWzBdJ10gPSB0b1swXTtcbiAgICAgICAgICAgIGFvYmpbYXhpLl9uYW1lICsgJy5yYW5nZVsxXSddID0gdG9bMV07XG5cbiAgICAgICAgICAgIGF4aS5yYW5nZSA9IHRvLnNsaWNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTaWduYWwgdGhhdCB0aGlzIHRyYW5zaXRpb24gaGFzIGNvbXBsZXRlZDpcbiAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGFvYmopLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYWZmZWN0ZWRTdWJwbG90cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHVuc2V0U3VicGxvdFRyYW5zZm9ybShhZmZlY3RlZFN1YnBsb3RzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbkludGVycnVwdCgpIHtcbiAgICAgICAgdmFyIGFvYmogPSB7fTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHVwZGF0ZWRBeGlzSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYXhpID0gZ2QuX2Z1bGxMYXlvdXRbdXBkYXRlZEF4aXNJZHNbaV0gKyAnYXhpcyddO1xuICAgICAgICAgICAgYW9ialtheGkuX25hbWUgKyAnLnJhbmdlWzBdJ10gPSBheGkucmFuZ2VbMF07XG4gICAgICAgICAgICBhb2JqW2F4aS5fbmFtZSArICcucmFuZ2VbMV0nXSA9IGF4aS5yYW5nZVsxXTtcblxuICAgICAgICAgICAgYXhpLnJhbmdlID0gYXhpLl9yLnNsaWNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYW9iaikudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhZmZlY3RlZFN1YnBsb3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdW5zZXRTdWJwbG90VHJhbnNmb3JtKGFmZmVjdGVkU3VicGxvdHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgdDEsIHQyLCByYWY7XG4gICAgdmFyIGVhc2VGbiA9IGQzLmVhc2UodHJhbnNpdGlvbk9wdHMuZWFzaW5nKTtcblxuICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZShyYWYpO1xuICAgICAgICByYWYgPSBudWxsO1xuICAgICAgICByZXR1cm4gdHJhbnNpdGlvbkludGVycnVwdCgpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gZG9GcmFtZSgpIHtcbiAgICAgICAgdDIgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHZhciB0SW50ZXJwID0gTWF0aC5taW4oMSwgKHQyIC0gdDEpIC8gdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pO1xuICAgICAgICB2YXIgcHJvZ3Jlc3MgPSBlYXNlRm4odEludGVycCk7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGFmZmVjdGVkU3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHVwZGF0ZVN1YnBsb3QoYWZmZWN0ZWRTdWJwbG90c1tpXSwgcHJvZ3Jlc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodDIgLSB0MSA+IHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uKSB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uQ29tcGxldGUoKTtcbiAgICAgICAgICAgIHJhZiA9IHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZShkb0ZyYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJhZiA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZG9GcmFtZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0MSA9IERhdGUubm93KCk7XG4gICAgcmFmID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShkb0ZyYW1lKTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuZnVuY3Rpb24gdHJhbnNpdGlvbkF4ZXMyKGdkLCBlZGl0cywgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgZnVuY3Rpb24gdGlja3NBbmRBbm5vdGF0aW9ucyh4YSwgeWEpIHtcbiAgICAgICAgdmFyIGFjdGl2ZUF4SWRzID0gW3hhLl9pZCwgeWEuX2lkXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWN0aXZlQXhJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIEF4ZXMuZG9UaWNrc1NpbmdsZShnZCwgYWN0aXZlQXhJZHNbaV0sIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVkcmF3T2JqcyhvYmpBcnJheSwgbWV0aG9kLCBzaG9ydENpcmN1aXQpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG9iakFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iamkgPSBvYmpBcnJheVtpXTtcblxuICAgICAgICAgICAgICAgIGlmKChhY3RpdmVBeElkcy5pbmRleE9mKG9iamkueHJlZikgIT09IC0xKSB8fFxuICAgICAgICAgICAgICAgICAgICAoYWN0aXZlQXhJZHMuaW5kZXhPZihvYmppLnlyZWYpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kKGdkLCBpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBvbmNlIGlzIGVub3VnaCBmb3IgaW1hZ2VzICh3aGljaCBkb2Vzbid0IHVzZSB0aGUgYGlgIGFyZyBhbnl3YXkpXG4gICAgICAgICAgICAgICAgaWYoc2hvcnRDaXJjdWl0KSByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZWRyYXdPYmpzKGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnMgfHwgW10sIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhd09uZScpKTtcbiAgICAgICAgcmVkcmF3T2JqcyhmdWxsTGF5b3V0LnNoYXBlcyB8fCBbXSwgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdzaGFwZXMnLCAnZHJhd09uZScpKTtcbiAgICAgICAgcmVkcmF3T2JqcyhmdWxsTGF5b3V0LmltYWdlcyB8fCBbXSwgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdpbWFnZXMnLCAnZHJhdycpLCB0cnVlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bnNldFN1YnBsb3RUcmFuc2Zvcm0ocGxvdGluZm8pIHtcbiAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIGZ1bGxMYXlvdXQuX2RlZnMuc2VsZWN0KCcjJyArIHBsb3RpbmZvLmNsaXBJZCArICc+IHJlY3QnKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIDAsIDApXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFNjYWxlLCAxLCAxKTtcblxuICAgICAgICBwbG90aW5mby5wbG90XG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgeGEuX29mZnNldCwgeWEuX29mZnNldClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEsIDEpO1xuXG4gICAgICAgIHZhciB0cmFjZUdyb3VwcyA9IHBsb3RpbmZvLnBsb3Quc2VsZWN0QWxsKCcuc2NhdHRlcmxheWVyIC50cmFjZScpO1xuXG4gICAgICAgIC8vIFRoaXMgaXMgc3BlY2lmaWNhbGx5IGRpcmVjdGVkIGF0IHNjYXR0ZXIgdHJhY2VzLCBhcHBseWluZyBhbiBpbnZlcnNlXG4gICAgICAgIC8vIHNjYWxlIHRvIGluZGl2aWR1YWwgcG9pbnRzIHRvIGNvdW50ZXJhY3QgdGhlIHNjYWxlIG9mIHRoZSB0cmFjZVxuICAgICAgICAvLyBhcyBhIHdob2xlOlxuICAgICAgICB0cmFjZUdyb3Vwcy5zZWxlY3RBbGwoJy5wb2ludCcpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFBvaW50R3JvdXBTY2FsZSwgMSwgMSk7XG4gICAgICAgIHRyYWNlR3JvdXBzLnNlbGVjdEFsbCgnLnRleHRwb2ludCcpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRleHRQb2ludHNTY2FsZSwgMSwgMSk7XG4gICAgICAgIHRyYWNlR3JvdXBzXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmhpZGVPdXRzaWRlUmFuZ2VQb2ludHMsIHBsb3RpbmZvKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVTdWJwbG90KGVkaXQsIHByb2dyZXNzKSB7XG4gICAgICAgIHZhciBwbG90aW5mbyA9IGVkaXQucGxvdGluZm87XG4gICAgICAgIHZhciB4YTEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgdmFyIHlhMSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIHZhciB4cjAgPSBlZGl0LnhyMDtcbiAgICAgICAgdmFyIHhyMSA9IGVkaXQueHIxO1xuICAgICAgICB2YXIgeGxlbiA9IHhhMS5fbGVuZ3RoO1xuICAgICAgICB2YXIgeXIwID0gZWRpdC55cjA7XG4gICAgICAgIHZhciB5cjEgPSBlZGl0LnlyMTtcbiAgICAgICAgdmFyIHlsZW4gPSB5YTEuX2xlbmd0aDtcblxuICAgICAgICB2YXIgZWRpdFggPSB4cjBbMF0gIT09IHhyMVswXSB8fCB4cjBbMV0gIT09IHhyMVsxXTtcbiAgICAgICAgdmFyIGVkaXRZID0geXIwWzBdICE9PSB5cjFbMF0gfHwgeXIwWzFdICE9PSB5cjFbMV07XG4gICAgICAgIHZhciB2aWV3Qm94ID0gW107XG5cbiAgICAgICAgaWYoZWRpdFgpIHtcbiAgICAgICAgICAgIHZhciBkeDAgPSB4cjBbMV0gLSB4cjBbMF07XG4gICAgICAgICAgICB2YXIgZHgxID0geHIxWzFdIC0geHIxWzBdO1xuICAgICAgICAgICAgdmlld0JveFswXSA9ICh4cjBbMF0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogeHIxWzBdIC0geHIwWzBdKSAvICh4cjBbMV0gLSB4cjBbMF0pICogeGxlbjtcbiAgICAgICAgICAgIHZpZXdCb3hbMl0gPSB4bGVuICogKCgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiBkeDEgLyBkeDApO1xuICAgICAgICAgICAgeGExLnJhbmdlWzBdID0geHIwWzBdICogKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIHhyMVswXTtcbiAgICAgICAgICAgIHhhMS5yYW5nZVsxXSA9IHhyMFsxXSAqICgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiB4cjFbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2aWV3Qm94WzBdID0gMDtcbiAgICAgICAgICAgIHZpZXdCb3hbMl0gPSB4bGVuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZWRpdFkpIHtcbiAgICAgICAgICAgIHZhciBkeTAgPSB5cjBbMV0gLSB5cjBbMF07XG4gICAgICAgICAgICB2YXIgZHkxID0geXIxWzFdIC0geXIxWzBdO1xuICAgICAgICAgICAgdmlld0JveFsxXSA9ICh5cjBbMV0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogeXIxWzFdIC0geXIwWzFdKSAvICh5cjBbMF0gLSB5cjBbMV0pICogeWxlbjtcbiAgICAgICAgICAgIHZpZXdCb3hbM10gPSB5bGVuICogKCgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiBkeTEgLyBkeTApO1xuICAgICAgICAgICAgeWExLnJhbmdlWzBdID0geXIwWzBdICogKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIHlyMVswXTtcbiAgICAgICAgICAgIHlhMS5yYW5nZVsxXSA9IHlyMFsxXSAqICgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiB5cjFbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2aWV3Qm94WzFdID0gMDtcbiAgICAgICAgICAgIHZpZXdCb3hbM10gPSB5bGVuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGlja3NBbmRBbm5vdGF0aW9ucyhwbG90aW5mby54YXhpcywgcGxvdGluZm8ueWF4aXMpO1xuXG4gICAgICAgIHZhciB4U2NhbGVGYWN0b3IgPSBlZGl0WCA/IHhsZW4gLyB2aWV3Qm94WzJdIDogMTtcbiAgICAgICAgdmFyIHlTY2FsZUZhY3RvciA9IGVkaXRZID8geWxlbiAvIHZpZXdCb3hbM10gOiAxO1xuICAgICAgICB2YXIgY2xpcER4ID0gZWRpdFggPyB2aWV3Qm94WzBdIDogMDtcbiAgICAgICAgdmFyIGNsaXBEeSA9IGVkaXRZID8gdmlld0JveFsxXSA6IDA7XG4gICAgICAgIHZhciBmcmFjRHggPSBlZGl0WCA/ICh2aWV3Qm94WzBdIC8gdmlld0JveFsyXSAqIHhsZW4pIDogMDtcbiAgICAgICAgdmFyIGZyYWNEeSA9IGVkaXRZID8gKHZpZXdCb3hbMV0gLyB2aWV3Qm94WzNdICogeWxlbikgOiAwO1xuICAgICAgICB2YXIgcGxvdER4ID0geGExLl9vZmZzZXQgLSBmcmFjRHg7XG4gICAgICAgIHZhciBwbG90RHkgPSB5YTEuX29mZnNldCAtIGZyYWNEeTtcblxuICAgICAgICBwbG90aW5mby5jbGlwUmVjdFxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIGNsaXBEeCwgY2xpcER5KVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRTY2FsZSwgMSAvIHhTY2FsZUZhY3RvciwgMSAvIHlTY2FsZUZhY3Rvcik7XG5cbiAgICAgICAgcGxvdGluZm8ucGxvdFxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIHBsb3REeCwgcGxvdER5KVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRTY2FsZSwgeFNjYWxlRmFjdG9yLCB5U2NhbGVGYWN0b3IpO1xuXG4gICAgICAgIC8vIGFwcGx5IGFuIGludmVyc2Ugc2NhbGUgdG8gaW5kaXZpZHVhbCBwb2ludHMgdG8gY291bnRlcmFjdFxuICAgICAgICAvLyB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlIGdyb3VwLlxuICAgICAgICBEcmF3aW5nLnNldFBvaW50R3JvdXBTY2FsZShwbG90aW5mby56b29tU2NhbGVQdHMsIDEgLyB4U2NhbGVGYWN0b3IsIDEgLyB5U2NhbGVGYWN0b3IpO1xuICAgICAgICBEcmF3aW5nLnNldFRleHRQb2ludHNTY2FsZShwbG90aW5mby56b29tU2NhbGVUeHQsIDEgLyB4U2NhbGVGYWN0b3IsIDEgLyB5U2NhbGVGYWN0b3IpO1xuICAgIH1cblxuICAgIHZhciBvbkNvbXBsZXRlO1xuICAgIGlmKG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgLy8gVGhpcyBtb2R1bGUgbWFrZXMgdGhlIGNob2ljZSB3aGV0aGVyIG9yIG5vdCBpdCBub3RpZmllcyBQbG90bHkudHJhbnNpdGlvblxuICAgICAgICAvLyBhYm91dCBjb21wbGV0aW9uOlxuICAgICAgICBvbkNvbXBsZXRlID0gbWFrZU9uQ29tcGxldGVDYWxsYmFjaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zaXRpb25Db21wbGV0ZSgpIHtcbiAgICAgICAgdmFyIGFvYmogPSB7fTtcbiAgICAgICAgdmFyIGs7XG5cbiAgICAgICAgZm9yKGsgaW4gZWRpdHMpIHtcbiAgICAgICAgICAgIHZhciBlZGl0ID0gZWRpdHNba107XG4gICAgICAgICAgICBhb2JqW2VkaXQucGxvdGluZm8ueGF4aXMuX25hbWUgKyAnLnJhbmdlJ10gPSBlZGl0LnhyMS5zbGljZSgpO1xuICAgICAgICAgICAgYW9ialtlZGl0LnBsb3RpbmZvLnlheGlzLl9uYW1lICsgJy5yYW5nZSddID0gZWRpdC55cjEuc2xpY2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNpZ25hbCB0aGF0IHRoaXMgdHJhbnNpdGlvbiBoYXMgY29tcGxldGVkOlxuICAgICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTtcblxuICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYW9iaikudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvcihrIGluIGVkaXRzKSB7XG4gICAgICAgICAgICAgICAgdW5zZXRTdWJwbG90VHJhbnNmb3JtKGVkaXRzW2tdLnBsb3RpbmZvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHQxLCB0MiwgcmFmO1xuICAgIHZhciBlYXNlRm4gPSBkMy5lYXNlKHRyYW5zaXRpb25PcHRzLmVhc2luZyk7XG5cbiAgICBnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcy5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUocmFmKTtcbiAgICAgICAgcmFmID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRyYW5zaXRpb25Db21wbGV0ZSgpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gZG9GcmFtZSgpIHtcbiAgICAgICAgdDIgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHZhciB0SW50ZXJwID0gTWF0aC5taW4oMSwgKHQyIC0gdDEpIC8gdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pO1xuICAgICAgICB2YXIgcHJvZ3Jlc3MgPSBlYXNlRm4odEludGVycCk7XG5cbiAgICAgICAgZm9yKHZhciBrIGluIGVkaXRzKSB7XG4gICAgICAgICAgICB1cGRhdGVTdWJwbG90KGVkaXRzW2tdLCBwcm9ncmVzcyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0MiAtIHQxID4gdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pIHtcbiAgICAgICAgICAgIHRyYW5zaXRpb25Db21wbGV0ZSgpO1xuICAgICAgICAgICAgcmFmID0gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKGRvRnJhbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmFmID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShkb0ZyYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHQxID0gRGF0ZS5ub3coKTtcbiAgICByYWYgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGRvRnJhbWUpO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB0cmFuc2l0aW9uQXhlczogdHJhbnNpdGlvbkF4ZXMsXG4gICAgdHJhbnNpdGlvbkF4ZXMyOiB0cmFuc2l0aW9uQXhlczJcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgYXV0b1R5cGUgPSByZXF1aXJlKCcuL2F4aXNfYXV0b3R5cGUnKTtcblxuLypcbiAqICBkYXRhOiB0aGUgcGxvdCBkYXRhIHRvIHVzZSBpbiBjaG9vc2luZyBhdXRvIHR5cGVcbiAqICBuYW1lOiBheGlzIG9iamVjdCBuYW1lIChpZSAneGF4aXMnKSBpZiBvbmUgc2hvdWxkIGJlIHN0b3JlZFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVR5cGVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgYXhUeXBlID0gY29lcmNlKCd0eXBlJywgKG9wdGlvbnMuc3Bsb21TdGFzaCB8fCB7fSkudHlwZSk7XG5cbiAgICBpZihheFR5cGUgPT09ICctJykge1xuICAgICAgICBzZXRBdXRvVHlwZShjb250YWluZXJPdXQsIG9wdGlvbnMuZGF0YSk7XG5cbiAgICAgICAgaWYoY29udGFpbmVyT3V0LnR5cGUgPT09ICctJykge1xuICAgICAgICAgICAgY29udGFpbmVyT3V0LnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvcHkgYXV0b1R5cGUgYmFjayB0byBpbnB1dCBheGlzXG4gICAgICAgICAgICAvLyBub3RlIHRoYXQgaWYgdGhpcyBvYmplY3QgZGlkbid0IGV4aXN0XG4gICAgICAgICAgICAvLyBpbiB0aGUgaW5wdXQgbGF5b3V0LCB3ZSBoYXZlIHRvIHB1dCBpdCBpblxuICAgICAgICAgICAgLy8gdGhpcyBoYXBwZW5zIGluIHRoZSBtYWluIHN1cHBseURlZmF1bHRzIGZ1bmN0aW9uXG4gICAgICAgICAgICBjb250YWluZXJJbi50eXBlID0gY29udGFpbmVyT3V0LnR5cGU7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5mdW5jdGlvbiBzZXRBdXRvVHlwZShheCwgZGF0YSkge1xuICAgIC8vIG5ldyBsb2dpYzogbGV0IHBlb3BsZSBzcGVjaWZ5IGFueSB0eXBlIHRoZXkgd2FudCxcbiAgICAvLyBvbmx5IGF1dG90eXBlIGlmIHR5cGUgaXMgJy0nXG4gICAgaWYoYXgudHlwZSAhPT0gJy0nKSByZXR1cm47XG5cbiAgICB2YXIgaWQgPSBheC5faWQ7XG4gICAgdmFyIGF4TGV0dGVyID0gaWQuY2hhckF0KDApO1xuXG4gICAgLy8gc3VwcG9ydCAzZFxuICAgIGlmKGlkLmluZGV4T2YoJ3NjZW5lJykgIT09IC0xKSBpZCA9IGF4TGV0dGVyO1xuXG4gICAgdmFyIGQwID0gZ2V0Rmlyc3ROb25FbXB0eVRyYWNlKGRhdGEsIGlkLCBheExldHRlcik7XG4gICAgaWYoIWQwKSByZXR1cm47XG5cbiAgICAvLyBmaXJzdCBjaGVjayBmb3IgaGlzdG9ncmFtcywgYXMgdGhlIGNvdW50IGRpcmVjdGlvblxuICAgIC8vIHNob3VsZCBhbHdheXMgZGVmYXVsdCB0byBhIGxpbmVhciBheGlzXG4gICAgaWYoZDAudHlwZSA9PT0gJ2hpc3RvZ3JhbScgJiZcbiAgICAgICAgICAgIGF4TGV0dGVyID09PSB7djogJ3knLCBoOiAneCd9W2QwLm9yaWVudGF0aW9uIHx8ICd2J10pIHtcbiAgICAgICAgYXgudHlwZSA9ICdsaW5lYXInO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGNhbEF0dHIgPSBheExldHRlciArICdjYWxlbmRhcic7XG4gICAgdmFyIGNhbGVuZGFyID0gZDBbY2FsQXR0cl07XG4gICAgdmFyIGk7XG5cbiAgICAvLyBjaGVjayBhbGwgYm94ZXMgb24gdGhpcyB4IGF4aXMgdG8gc2VlXG4gICAgLy8gaWYgdGhleSdyZSBkYXRlcywgbnVtYmVycywgb3IgY2F0ZWdvcmllc1xuICAgIGlmKGlzQm94V2l0aG91dFBvc2l0aW9uQ29vcmRzKGQwLCBheExldHRlcikpIHtcbiAgICAgICAgdmFyIHBvc0xldHRlciA9IGdldEJveFBvc0xldHRlcihkMCk7XG4gICAgICAgIHZhciBib3hQb3NpdGlvbnMgPSBbXTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBkYXRhW2ldO1xuICAgICAgICAgICAgaWYoIVJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdib3gtdmlvbGluJykgfHxcbiAgICAgICAgICAgICAgICh0cmFjZVtheExldHRlciArICdheGlzJ10gfHwgYXhMZXR0ZXIpICE9PSBpZCkgY29udGludWU7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlW3Bvc0xldHRlcl0gIT09IHVuZGVmaW5lZCkgYm94UG9zaXRpb25zLnB1c2godHJhY2VbcG9zTGV0dGVyXVswXSk7XG4gICAgICAgICAgICBlbHNlIGlmKHRyYWNlLm5hbWUgIT09IHVuZGVmaW5lZCkgYm94UG9zaXRpb25zLnB1c2godHJhY2UubmFtZSk7XG4gICAgICAgICAgICBlbHNlIGJveFBvc2l0aW9ucy5wdXNoKCd0ZXh0Jyk7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlW2NhbEF0dHJdICE9PSBjYWxlbmRhcikgY2FsZW5kYXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBheC50eXBlID0gYXV0b1R5cGUoYm94UG9zaXRpb25zLCBjYWxlbmRhcik7XG4gICAgfVxuICAgIGVsc2UgaWYoZDAudHlwZSA9PT0gJ3NwbG9tJykge1xuICAgICAgICB2YXIgZGltZW5zaW9ucyA9IGQwLmRpbWVuc2lvbnM7XG4gICAgICAgIHZhciBkaWFnID0gZDAuX2RpYWc7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGRpbWVuc2lvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaW0gPSBkaW1lbnNpb25zW2ldO1xuICAgICAgICAgICAgaWYoZGltLnZpc2libGUgJiYgKGRpYWdbaV1bMF0gPT09IGlkIHx8IGRpYWdbaV1bMV0gPT09IGlkKSkge1xuICAgICAgICAgICAgICAgIGF4LnR5cGUgPSBhdXRvVHlwZShkaW0udmFsdWVzLCBjYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGF4LnR5cGUgPSBhdXRvVHlwZShkMFtheExldHRlcl0gfHwgW2QwW2F4TGV0dGVyICsgJzAnXV0sIGNhbGVuZGFyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEZpcnN0Tm9uRW1wdHlUcmFjZShkYXRhLCBpZCwgYXhMZXR0ZXIpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBkYXRhW2ldO1xuXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdzcGxvbScgJiZcbiAgICAgICAgICAgICAgICB0cmFjZS5fbGVuZ3RoID4gMCAmJlxuICAgICAgICAgICAgICAgICh0cmFjZVsnXycgKyBheExldHRlciArICdheGVzJ10gfHwge30pW2lkXVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB0cmFjZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCh0cmFjZVtheExldHRlciArICdheGlzJ10gfHwgYXhMZXR0ZXIpID09PSBpZCkge1xuICAgICAgICAgICAgaWYoaXNCb3hXaXRob3V0UG9zaXRpb25Db29yZHModHJhY2UsIGF4TGV0dGVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoKHRyYWNlW2F4TGV0dGVyXSB8fCBbXSkubGVuZ3RoIHx8IHRyYWNlW2F4TGV0dGVyICsgJzAnXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0Qm94UG9zTGV0dGVyKHRyYWNlKSB7XG4gICAgcmV0dXJuIHt2OiAneCcsIGg6ICd5J31bdHJhY2Uub3JpZW50YXRpb24gfHwgJ3YnXTtcbn1cblxuZnVuY3Rpb24gaXNCb3hXaXRob3V0UG9zaXRpb25Db29yZHModHJhY2UsIGF4TGV0dGVyKSB7XG4gICAgdmFyIHBvc0xldHRlciA9IGdldEJveFBvc0xldHRlcih0cmFjZSksXG4gICAgICAgIGlzQm94ID0gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2JveC12aW9saW4nKSxcbiAgICAgICAgaXNDYW5kbGVzdGljayA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UuX2Z1bGxJbnB1dCB8fCB7fSwgJ2NhbmRsZXN0aWNrJyk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICBpc0JveCAmJlxuICAgICAgICAhaXNDYW5kbGVzdGljayAmJlxuICAgICAgICBheExldHRlciA9PT0gcG9zTGV0dGVyICYmXG4gICAgICAgIHRyYWNlW3Bvc0xldHRlcl0gPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0cmFjZVtwb3NMZXR0ZXIgKyAnMCddID09PSB1bmRlZmluZWRcbiAgICApO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xuXG4vKlxuICogQ3JlYXRlIG9yIHVwZGF0ZSBhbiBvYnNlcnZlci4gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZVxuICogaWRlbXBvdGVudCBzbyB0aGF0IGl0IGNhbiBiZSBjYWxsZWQgb3ZlciBhbmQgb3ZlciBhcyB0aGUgY29tcG9uZW50XG4gKiB1cGRhdGVzLCBhbmQgd2lsbCBhdHRhY2ggYW5kIGRldGFjaCBsaXN0ZW5lcnMgYXMgbmVlZGVkLlxuICpcbiAqIEBwYXJhbSB7b3B0aW9uYWwgb2JqZWN0fSBjb250YWluZXJcbiAqICAgICAgQW4gb2JqZWN0IG9uIHdoaWNoIHRoZSBvYnNlcnZlciBpcyBzdG9yZWQuIFRoaXMgaXMgdGhlIG1lY2hhbmlzbVxuICogICAgICBieSB3aGljaCBpdCBpcyBpZGVtcG90ZW50LiBJZiBpdCBhbHJlYWR5IGV4aXN0cywgYW5vdGhlciB3b24ndCBiZVxuICogICAgICBhZGRlZC4gRWFjaCB0aW1lIGl0J3MgY2FsbGVkLCB0aGUgdmFsdWUgbG9va3VwIHRhYmxlIGlzIHVwZGF0ZWQuXG4gKiBAcGFyYW0ge2FycmF5fSBjb21tYW5kTGlzdFxuICogICAgICBBbiBhcnJheSBvZiBjb21tYW5kcywgZm9sbG93aW5nIGVpdGhlciBgYnV0dG9uc2Agb2YgYHVwZGF0ZW1lbnVzYFxuICogICAgICBvciBgc3RlcHNgIG9mIGBzbGlkZXJzYC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IG9uY2hhbmdlXG4gKiAgICAgIEEgbGlzdGVuZXIgY2FsbGVkIHdoZW4gdGhlIHZhbHVlIGlzIGNoYW5nZWQuIFJlY2VpdmVzIGRhdGEgb2JqZWN0XG4gKiAgICAgIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIG5ldyBzdGF0ZS5cbiAqL1xuZXhwb3J0cy5tYW5hZ2VDb21tYW5kT2JzZXJ2ZXIgPSBmdW5jdGlvbihnZCwgY29udGFpbmVyLCBjb21tYW5kTGlzdCwgb25jaGFuZ2UpIHtcbiAgICB2YXIgcmV0ID0ge307XG4gICAgdmFyIGVuYWJsZWQgPSB0cnVlO1xuXG4gICAgaWYoY29udGFpbmVyICYmIGNvbnRhaW5lci5fY29tbWFuZE9ic2VydmVyKSB7XG4gICAgICAgIHJldCA9IGNvbnRhaW5lci5fY29tbWFuZE9ic2VydmVyO1xuICAgIH1cblxuICAgIGlmKCFyZXQuY2FjaGUpIHtcbiAgICAgICAgcmV0LmNhY2hlID0ge307XG4gICAgfVxuXG4gICAgLy8gRWl0aGVyIGNyZWF0ZSBvciBqdXN0IHJlY29tcHV0ZSB0aGlzOlxuICAgIHJldC5sb29rdXBUYWJsZSA9IHt9O1xuXG4gICAgdmFyIGJpbmRpbmcgPSBleHBvcnRzLmhhc1NpbXBsZUFQSUNvbW1hbmRCaW5kaW5ncyhnZCwgY29tbWFuZExpc3QsIHJldC5sb29rdXBUYWJsZSk7XG5cbiAgICBpZihjb250YWluZXIgJiYgY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIpIHtcbiAgICAgICAgaWYoIWJpbmRpbmcpIHtcbiAgICAgICAgICAgIC8vIElmIGNvbnRhaW5lciBleGlzdHMgYW5kIHRoZXJlIGFyZSBubyBsb25nZXIgYW55IGJpbmRpbmdzLFxuICAgICAgICAgICAgLy8gcmVtb3ZlIGV4aXN0aW5nOlxuICAgICAgICAgICAgaWYoY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIucmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIgPSBudWxsO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJZiBjb250YWluZXIgZXhpc3RzIGFuZCB0aGVyZSAqYXJlKiBiaW5kaW5ncywgdGhlbiB0aGUgbG9va3VwXG4gICAgICAgICAgICAvLyB0YWJsZSBzaG91bGQgaGF2ZSBiZWVuIHVwZGF0ZWQgYW5kIGNoZWNrIGlzIGFscmVhZHkgYXR0YWNoZWQsXG4gICAgICAgICAgICAvLyBzbyB0aGVyZSdzIG5vdGhpbmcgdG8gYmUgZG9uZTpcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG5cblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgdGhlcmUncyBhbnl0aGluZyB0byBkbyBmb3IgdGhpcyBiaW5kaW5nOlxuXG4gICAgaWYoYmluZGluZykge1xuICAgICAgICAvLyBCdWlsZCB0aGUgY2FjaGU6XG4gICAgICAgIGJpbmRpbmdWYWx1ZUhhc0NoYW5nZWQoZ2QsIGJpbmRpbmcsIHJldC5jYWNoZSk7XG5cbiAgICAgICAgcmV0LmNoZWNrID0gZnVuY3Rpb24gY2hlY2soKSB7XG4gICAgICAgICAgICBpZighZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlID0gYmluZGluZ1ZhbHVlSGFzQ2hhbmdlZChnZCwgYmluZGluZywgcmV0LmNhY2hlKTtcblxuICAgICAgICAgICAgaWYodXBkYXRlLmNoYW5nZWQgJiYgb25jaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICAvLyBEaXNhYmxlIGNoZWNrcyBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoaXMgY29tbWFuZCBpbiBvcmRlciB0byBhdm9pZFxuICAgICAgICAgICAgICAgIC8vIGluZmluaXRlIGxvb3BzOlxuICAgICAgICAgICAgICAgIGlmKHJldC5sb29rdXBUYWJsZVt1cGRhdGUudmFsdWVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0LmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKG9uY2hhbmdlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1cGRhdGUudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBiaW5kaW5nLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wOiBiaW5kaW5nLnByb3AsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFjZXM6IGJpbmRpbmcudHJhY2VzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IHJldC5sb29rdXBUYWJsZVt1cGRhdGUudmFsdWVdXG4gICAgICAgICAgICAgICAgICAgIH0pKS50aGVuKHJldC5lbmFibGUsIHJldC5lbmFibGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHVwZGF0ZS5jaGFuZ2VkO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjaGVja0V2ZW50cyA9IFtcbiAgICAgICAgICAgICdwbG90bHlfcmVsYXlvdXQnLFxuICAgICAgICAgICAgJ3Bsb3RseV9yZWRyYXcnLFxuICAgICAgICAgICAgJ3Bsb3RseV9yZXN0eWxlJyxcbiAgICAgICAgICAgICdwbG90bHlfdXBkYXRlJyxcbiAgICAgICAgICAgICdwbG90bHlfYW5pbWF0aW5nZnJhbWUnLFxuICAgICAgICAgICAgJ3Bsb3RseV9hZnRlcnBsb3QnXG4gICAgICAgIF07XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNoZWNrRXZlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBnZC5faW50ZXJuYWxPbihjaGVja0V2ZW50c1tpXSwgcmV0LmNoZWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldC5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjaGVja0V2ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGdkLl9yZW1vdmVJbnRlcm5hbExpc3RlbmVyKGNoZWNrRXZlbnRzW2ldLCByZXQuY2hlY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRPRE86IEl0J2QgYmUgcmVhbGx5IG5lYXQgdG8gYWN0dWFsbHkgZ2l2ZSBhICpyZWFzb24qIGZvciB0aGlzLCBidXQgYXQgbGVhc3QgYSB3YXJuaW5nXG4gICAgICAgIC8vIGlzIGEgc3RhcnRcbiAgICAgICAgTGliLmxvZygnVW5hYmxlIHRvIGF1dG9tYXRpY2FsbHkgYmluZCBwbG90IHVwZGF0ZXMgdG8gQVBJIGNvbW1hbmQnKTtcblxuICAgICAgICByZXQubG9va3VwVGFibGUgPSB7fTtcbiAgICAgICAgcmV0LnJlbW92ZSA9IGZ1bmN0aW9uKCkge307XG4gICAgfVxuXG4gICAgcmV0LmRpc2FibGUgPSBmdW5jdGlvbiBkaXNhYmxlKCkge1xuICAgICAgICBlbmFibGVkID0gZmFsc2U7XG4gICAgfTtcblxuICAgIHJldC5lbmFibGUgPSBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgIGVuYWJsZWQgPSB0cnVlO1xuICAgIH07XG5cbiAgICBpZihjb250YWluZXIpIHtcbiAgICAgICAgY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIgPSByZXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbn07XG5cbi8qXG4gKiBUaGlzIGZ1bmN0aW9uIGNoZWNrcyB0byBzZWUgaWYgYW4gYXJyYXkgb2Ygb2JqZWN0cyBjb250YWluaW5nXG4gKiBtZXRob2QgYW5kIGFyZ3MgcHJvcGVydGllcyBpcyBjb21wYXRpYmxlIHdpdGggYXV0b21hdGljIHR3by13YXlcbiAqIGJpbmRpbmcuIFRoZSBjcml0ZXJpYSByaWdodCBub3cgYXJlIHRoYXRcbiAqXG4gKiAgIDEuIG11bHRpcGxlIHRyYWNlcyBtYXkgYmUgYWZmZWN0ZWRcbiAqICAgMi4gb25seSBvbmUgcHJvcGVydHkgbWF5IGJlIGFmZmVjdGVkXG4gKiAgIDMuIHRoZSBzYW1lIHByb3BlcnR5IG11c3QgYmUgYWZmZWN0ZWQgYnkgYWxsIGNvbW1hbmRzXG4gKi9cbmV4cG9ydHMuaGFzU2ltcGxlQVBJQ29tbWFuZEJpbmRpbmdzID0gZnVuY3Rpb24oZ2QsIGNvbW1hbmRMaXN0LCBiaW5kaW5nc0J5VmFsdWUpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgbiA9IGNvbW1hbmRMaXN0Lmxlbmd0aDtcblxuICAgIHZhciByZWZCaW5kaW5nO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHZhciBiaW5kaW5nO1xuICAgICAgICB2YXIgY29tbWFuZCA9IGNvbW1hbmRMaXN0W2ldO1xuICAgICAgICB2YXIgbWV0aG9kID0gY29tbWFuZC5tZXRob2Q7XG4gICAgICAgIHZhciBhcmdzID0gY29tbWFuZC5hcmdzO1xuXG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGFyZ3MpKSBhcmdzID0gW107XG5cbiAgICAgICAgLy8gSWYgYW55IGNvbW1hbmQgaGFzIG5vIG1ldGhvZCwgcmVmdXNlIHRvIGJpbmQ6XG4gICAgICAgIGlmKCFtZXRob2QpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYmluZGluZ3MgPSBleHBvcnRzLmNvbXB1dGVBUElDb21tYW5kQmluZGluZ3MoZ2QsIG1ldGhvZCwgYXJncyk7XG5cbiAgICAgICAgLy8gUmlnaHQgbm93LCBoYW5kbGUgb25lIGFuZCAqb25seSogb25lIHByb3BlcnR5IGJlaW5nIHNldDpcbiAgICAgICAgaWYoYmluZGluZ3MubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZighcmVmQmluZGluZykge1xuICAgICAgICAgICAgcmVmQmluZGluZyA9IGJpbmRpbmdzWzBdO1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShyZWZCaW5kaW5nLnRyYWNlcykpIHtcbiAgICAgICAgICAgICAgICByZWZCaW5kaW5nLnRyYWNlcy5zb3J0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiaW5kaW5nID0gYmluZGluZ3NbMF07XG4gICAgICAgICAgICBpZihiaW5kaW5nLnR5cGUgIT09IHJlZkJpbmRpbmcudHlwZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGJpbmRpbmcucHJvcCAhPT0gcmVmQmluZGluZy5wcm9wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShyZWZCaW5kaW5nLnRyYWNlcykpIHtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGJpbmRpbmcudHJhY2VzKSkge1xuICAgICAgICAgICAgICAgICAgICBiaW5kaW5nLnRyYWNlcy5zb3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCByZWZCaW5kaW5nLnRyYWNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVmQmluZGluZy50cmFjZXNbal0gIT09IGJpbmRpbmcudHJhY2VzW2pdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYoYmluZGluZy5wcm9wICE9PSByZWZCaW5kaW5nLnByb3ApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJpbmRpbmcgPSBiaW5kaW5nc1swXTtcbiAgICAgICAgdmFyIHZhbHVlID0gYmluZGluZy52YWx1ZTtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmKHZhbHVlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWVbMF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZihiaW5kaW5nc0J5VmFsdWUpIHtcbiAgICAgICAgICAgIGJpbmRpbmdzQnlWYWx1ZVt2YWx1ZV0gPSBpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlZkJpbmRpbmc7XG59O1xuXG5mdW5jdGlvbiBiaW5kaW5nVmFsdWVIYXNDaGFuZ2VkKGdkLCBiaW5kaW5nLCBjYWNoZSkge1xuICAgIHZhciBjb250YWluZXIsIHZhbHVlLCBvYmo7XG4gICAgdmFyIGNoYW5nZWQgPSBmYWxzZTtcblxuICAgIGlmKGJpbmRpbmcudHlwZSA9PT0gJ2RhdGEnKSB7XG4gICAgICAgIC8vIElmIGl0J3MgZGF0YSwgd2UgbmVlZCB0byBnZXQgYSB0cmFjZS4gQmFzZWQgb24gdGhlIGxpbWl0ZWQgc2NvcGVcbiAgICAgICAgLy8gb2Ygd2hhdCB3ZSBjb3Zlciwgd2UgY2FuIGp1c3QgdGFrZSB0aGUgZmlyc3QgdHJhY2UgZnJvbSB0aGUgbGlzdCxcbiAgICAgICAgLy8gb3Igb3RoZXJ3aXNlIGp1c3QgdGhlIGZpcnN0IHRyYWNlOlxuICAgICAgICBjb250YWluZXIgPSBnZC5fZnVsbERhdGFbYmluZGluZy50cmFjZXMgIT09IG51bGwgPyBiaW5kaW5nLnRyYWNlc1swXSA6IDBdO1xuICAgIH0gZWxzZSBpZihiaW5kaW5nLnR5cGUgPT09ICdsYXlvdXQnKSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YWx1ZSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShjb250YWluZXIsIGJpbmRpbmcucHJvcCkuZ2V0KCk7XG5cbiAgICBvYmogPSBjYWNoZVtiaW5kaW5nLnR5cGVdID0gY2FjaGVbYmluZGluZy50eXBlXSB8fCB7fTtcblxuICAgIGlmKG9iai5oYXNPd25Qcm9wZXJ0eShiaW5kaW5nLnByb3ApKSB7XG4gICAgICAgIGlmKG9ialtiaW5kaW5nLnByb3BdICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvYmpbYmluZGluZy5wcm9wXSA9IHZhbHVlO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY2hhbmdlZDogY2hhbmdlZCxcbiAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgfTtcbn1cblxuLypcbiAqIEV4ZWN1dGUgYW4gQVBJIGNvbW1hbmQuIFRoZXJlJ3MgcmVhbGx5IG5vdCBtdWNoIHRvIHRoaXM7IGl0IGp1c3QgcHJvdmlkZXNcbiAqIGEgY29tbW9uIGhvb2sgc28gdGhhdCBpbXBsZW1lbnRhdGlvbnMgZG9uJ3QgbmVlZCB0byBiZSBzeW5jaHJvbml6ZWQgYWNyb3NzXG4gKiBtdWx0aXBsZSBjb21wb25lbnRzIHdpdGggdGhlIGFiaWxpdHkgdG8gaW52b2tlIEFQSSBjb21tYW5kcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kXG4gKiAgICAgIFRoZSBuYW1lIG9mIHRoZSBwbG90bHkgY29tbWFuZCB0byBleGVjdXRlLiBNdXN0IGJlIG9uZSBvZiAnYW5pbWF0ZScsXG4gKiAgICAgICdyZXN0eWxlJywgJ3JlbGF5b3V0JywgJ3VwZGF0ZScuXG4gKiBAcGFyYW0ge2FycmF5fSBhcmdzXG4gKiAgICAgIEEgbGlzdCBvZiBhcmd1bWVudHMgcGFzc2VkIHRvIHRoZSBBUEkgY29tbWFuZFxuICovXG5leHBvcnRzLmV4ZWN1dGVBUElDb21tYW5kID0gZnVuY3Rpb24oZ2QsIG1ldGhvZCwgYXJncykge1xuICAgIGlmKG1ldGhvZCA9PT0gJ3NraXAnKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICB2YXIgX21ldGhvZCA9IFJlZ2lzdHJ5LmFwaU1ldGhvZFJlZ2lzdHJ5W21ldGhvZF07XG4gICAgdmFyIGFsbEFyZ3MgPSBbZ2RdO1xuICAgIGlmKCFBcnJheS5pc0FycmF5KGFyZ3MpKSBhcmdzID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhbGxBcmdzLnB1c2goYXJnc1tpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIF9tZXRob2QuYXBwbHkobnVsbCwgYWxsQXJncykuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgIExpYi53YXJuKCdBUEkgY2FsbCB0byBQbG90bHkuJyArIG1ldGhvZCArICcgcmVqZWN0ZWQuJywgZXJyKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XG4gICAgfSk7XG59O1xuXG5leHBvcnRzLmNvbXB1dGVBUElDb21tYW5kQmluZGluZ3MgPSBmdW5jdGlvbihnZCwgbWV0aG9kLCBhcmdzKSB7XG4gICAgdmFyIGJpbmRpbmdzO1xuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoYXJncykpIGFyZ3MgPSBbXTtcblxuICAgIHN3aXRjaChtZXRob2QpIHtcbiAgICAgICAgY2FzZSAncmVzdHlsZSc6XG4gICAgICAgICAgICBiaW5kaW5ncyA9IGNvbXB1dGVEYXRhQmluZGluZ3MoZ2QsIGFyZ3MpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3JlbGF5b3V0JzpcbiAgICAgICAgICAgIGJpbmRpbmdzID0gY29tcHV0ZUxheW91dEJpbmRpbmdzKGdkLCBhcmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1cGRhdGUnOlxuICAgICAgICAgICAgYmluZGluZ3MgPSBjb21wdXRlRGF0YUJpbmRpbmdzKGdkLCBbYXJnc1swXSwgYXJnc1syXV0pXG4gICAgICAgICAgICAgICAgLmNvbmNhdChjb21wdXRlTGF5b3V0QmluZGluZ3MoZ2QsIFthcmdzWzFdXSkpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2FuaW1hdGUnOlxuICAgICAgICAgICAgYmluZGluZ3MgPSBjb21wdXRlQW5pbWF0ZUJpbmRpbmdzKGdkLCBhcmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgY2FzZSB3aGVyZSBpbnRlbGxpZ2VudCBsb2dpYyBhYm91dCB3aGF0IGFmZmVjdHNcbiAgICAgICAgICAgIC8vIHRoaXMgY29tbWFuZCBpcyBub3QgaW1wbGVtZW50ZWQuIEl0IGNhdXNlcyBubyBpbGwgZWZmZWN0cy5cbiAgICAgICAgICAgIC8vIEZvciBleGFtcGxlLCBhZGRGcmFtZXMgc2ltcGx5IHdvbid0IGJpbmQgdG8gYSBjb250cm9sIGNvbXBvbmVudC5cbiAgICAgICAgICAgIGJpbmRpbmdzID0gW107XG4gICAgfVxuICAgIHJldHVybiBiaW5kaW5ncztcbn07XG5cbmZ1bmN0aW9uIGNvbXB1dGVBbmltYXRlQmluZGluZ3MoZ2QsIGFyZ3MpIHtcbiAgICAvLyBXZSdsbCBhc3N1bWUgdGhhdCB0aGUgb25seSByZWxldmFudCBtb2RpZmljYXRpb24gYW4gYW5pbWF0aW9uXG4gICAgLy8gbWFrZXMgdGhhdCdzIG1lYW5pbmdmdWxseSB0cmFja2VkIGlzIHRoZSBmcmFtZTpcbiAgICBpZihBcnJheS5pc0FycmF5KGFyZ3NbMF0pICYmIGFyZ3NbMF0ubGVuZ3RoID09PSAxICYmIFsnc3RyaW5nJywgJ251bWJlciddLmluZGV4T2YodHlwZW9mIGFyZ3NbMF1bMF0pICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gW3t0eXBlOiAnbGF5b3V0JywgcHJvcDogJ19jdXJyZW50RnJhbWUnLCB2YWx1ZTogYXJnc1swXVswXS50b1N0cmluZygpfV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY29tcHV0ZUxheW91dEJpbmRpbmdzKGdkLCBhcmdzKSB7XG4gICAgdmFyIGJpbmRpbmdzID0gW107XG5cbiAgICB2YXIgYXN0ciA9IGFyZ3NbMF07XG4gICAgdmFyIGFvYmogPSB7fTtcbiAgICBpZih0eXBlb2YgYXN0ciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgYW9ialthc3RyXSA9IGFyZ3NbMV07XG4gICAgfSBlbHNlIGlmKExpYi5pc1BsYWluT2JqZWN0KGFzdHIpKSB7XG4gICAgICAgIGFvYmogPSBhc3RyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBiaW5kaW5ncztcbiAgICB9XG5cbiAgICBjcmF3bChhb2JqLCBmdW5jdGlvbihwYXRoLCBhdHRyTmFtZSwgYXR0cikge1xuICAgICAgICBiaW5kaW5ncy5wdXNoKHt0eXBlOiAnbGF5b3V0JywgcHJvcDogcGF0aCwgdmFsdWU6IGF0dHJ9KTtcbiAgICB9LCAnJywgMCk7XG5cbiAgICByZXR1cm4gYmluZGluZ3M7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVEYXRhQmluZGluZ3MoZ2QsIGFyZ3MpIHtcbiAgICB2YXIgdHJhY2VzLCBhc3RyLCB2YWwsIGFvYmo7XG4gICAgdmFyIGJpbmRpbmdzID0gW107XG5cbiAgICAvLyBMb2dpYyBjb3BpZWQgZnJvbSBQbG90bHkucmVzdHlsZTpcbiAgICBhc3RyID0gYXJnc1swXTtcbiAgICB2YWwgPSBhcmdzWzFdO1xuICAgIHRyYWNlcyA9IGFyZ3NbMl07XG4gICAgYW9iaiA9IHt9O1xuICAgIGlmKHR5cGVvZiBhc3RyID09PSAnc3RyaW5nJykge1xuICAgICAgICBhb2JqW2FzdHJdID0gdmFsO1xuICAgIH0gZWxzZSBpZihMaWIuaXNQbGFpbk9iamVjdChhc3RyKSkge1xuICAgICAgICAvLyB0aGUgMy1hcmcgZm9ybVxuICAgICAgICBhb2JqID0gYXN0cjtcblxuICAgICAgICBpZih0cmFjZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJhY2VzID0gdmFsO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGJpbmRpbmdzO1xuICAgIH1cblxuICAgIGlmKHRyYWNlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIEV4cGxpY2l0bHkgYXNzaWduIHRoaXMgdG8gbnVsbCBpbnN0ZWFkIG9mIHVuZGVmaW5lZDpcbiAgICAgICAgdHJhY2VzID0gbnVsbDtcbiAgICB9XG5cbiAgICBjcmF3bChhb2JqLCBmdW5jdGlvbihwYXRoLCBhdHRyTmFtZSwgYXR0cikge1xuICAgICAgICB2YXIgdGhpc1RyYWNlcztcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShhdHRyKSkge1xuICAgICAgICAgICAgdmFyIG5BdHRyID0gTWF0aC5taW4oYXR0ci5sZW5ndGgsIGdkLmRhdGEubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKHRyYWNlcykge1xuICAgICAgICAgICAgICAgIG5BdHRyID0gTWF0aC5taW4obkF0dHIsIHRyYWNlcy5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpc1RyYWNlcyA9IFtdO1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IG5BdHRyOyBqKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzVHJhY2VzW2pdID0gdHJhY2VzID8gdHJhY2VzW2pdIDogajtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXNUcmFjZXMgPSB0cmFjZXMgPyB0cmFjZXMuc2xpY2UoMCkgOiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBbN10gdG8ganVzdCA3IHdoZW4gdHJhY2VzIGlzIG51bGw6XG4gICAgICAgIGlmKHRoaXNUcmFjZXMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0cikpIHtcbiAgICAgICAgICAgICAgICBhdHRyID0gYXR0clswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkodGhpc1RyYWNlcykpIHtcbiAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGF0dHIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRtcCA9IGF0dHI7XG4gICAgICAgICAgICAgICAgYXR0ciA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJbaV0gPSB0bXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXR0ci5sZW5ndGggPSBNYXRoLm1pbih0aGlzVHJhY2VzLmxlbmd0aCwgYXR0ci5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgYmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnZGF0YScsXG4gICAgICAgICAgICBwcm9wOiBwYXRoLFxuICAgICAgICAgICAgdHJhY2VzOiB0aGlzVHJhY2VzLFxuICAgICAgICAgICAgdmFsdWU6IGF0dHJcbiAgICAgICAgfSk7XG4gICAgfSwgJycsIDApO1xuXG4gICAgcmV0dXJuIGJpbmRpbmdzO1xufVxuXG5mdW5jdGlvbiBjcmF3bChhdHRycywgY2FsbGJhY2ssIHBhdGgsIGRlcHRoKSB7XG4gICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goZnVuY3Rpb24oYXR0ck5hbWUpIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1thdHRyTmFtZV07XG5cbiAgICAgICAgaWYoYXR0ck5hbWVbMF0gPT09ICdfJykgcmV0dXJuO1xuXG4gICAgICAgIHZhciB0aGlzUGF0aCA9IHBhdGggKyAoZGVwdGggPiAwID8gJy4nIDogJycpICsgYXR0ck5hbWU7XG5cbiAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QoYXR0cikpIHtcbiAgICAgICAgICAgIGNyYXdsKGF0dHIsIGNhbGxiYWNrLCB0aGlzUGF0aCwgZGVwdGggKyAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9ubHkgZXhlY3V0ZSB0aGUgY2FsbGJhY2sgb24gbGVhZiBub2RlczpcbiAgICAgICAgICAgIGNhbGxiYWNrKHRoaXNQYXRoLCBhdHRyTmFtZSwgYXR0cik7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxuLyoqXG4gKiBNYWtlIGEgeHkgZG9tYWluIGF0dHJpYnV0ZSBncm91cFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiAgIEBwYXJhbSB7c3RyaW5nfVxuICogICAgIG9wdHMubmFtZTogbmFtZSB0byBiZSBpbnNlcnRlZCBpbiB0aGUgZGVmYXVsdCBkZXNjcmlwdGlvblxuICogICBAcGFyYW0ge2Jvb2xlYW59XG4gKiAgICAgb3B0cy50cmFjZTogc2V0IHRvIHRydWUgZm9yIHRyYWNlIGNvbnRhaW5lcnNcbiAqICAgQHBhcmFtIHtzdHJpbmd9XG4gKiAgICAgb3B0cy5lZGl0VHlwZTogZWRpdFR5cGUgZm9yIGFsbCBwaWVjZXNcbiAqICAgQHBhcmFtIHtib29sZWFufVxuICogICAgIG9wdHMubm9HcmlkQ2VsbDogc2V0IHRvIHRydWUgdG8gb21pdCBgcm93YCBhbmQgYGNvbHVtbmBcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZXh0cmFcbiAqICAgQHBhcmFtIHtzdHJpbmd9XG4gKiAgICAgZXh0cmEuZGVzY3JpcHRpb246IGV4dHJhIGRlc2NyaXB0aW9uLiBOLkIgd2UgdXNlXG4gKiAgICAgYSBzZXBhcmF0ZSBleHRyYSBjb250YWluZXIgdG8gbWFrZSBpdCBjb21wYXRpYmxlIHdpdGhcbiAqICAgICB0aGUgY29tcHJlc3NfYXR0cmlidXRlcyB0cmFuc2Zvcm0uXG4gKlxuICogQHJldHVybiB7b2JqZWN0fSBhdHRyaWJ1dGVzIG9iamVjdCBjb250YWluaW5nIHt4LHl9IGFzIHNwZWNpZmllZFxuICovXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSBmdW5jdGlvbihvcHRzLCBleHRyYSkge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAgIGV4dHJhID0gZXh0cmEgfHwge307XG5cbiAgICB2YXIgYmFzZSA9IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6IG9wdHMuZWRpdFR5cGUsXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIG1pbjogMCwgbWF4OiAxLCBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZX0sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIG1pbjogMCwgbWF4OiAxLCBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZX1cbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogWzAsIDFdXG4gICAgfTtcblxuICAgIHZhciBuYW1lUGFydCA9IG9wdHMubmFtZSA/IG9wdHMubmFtZSArICcgJyA6ICcnO1xuICAgIHZhciBjb250UGFydCA9IG9wdHMudHJhY2UgPyAndHJhY2UgJyA6ICdzdWJwbG90ICc7XG4gICAgdmFyIGRlc2NQYXJ0ID0gZXh0cmEuZGVzY3JpcHRpb24gPyAnICcgKyBleHRyYS5kZXNjcmlwdGlvbiA6ICcnO1xuXG4gICAgdmFyIG91dCA9IHtcbiAgICAgICAgeDogZXh0ZW5kRmxhdCh7fSwgYmFzZSwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB5OiBleHRlbmRGbGF0KHt9LCBiYXNlLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiBvcHRzLmVkaXRUeXBlXG4gICAgfTtcblxuICAgIGlmKCFvcHRzLm5vR3JpZENlbGwpIHtcbiAgICAgICAgb3V0LnJvdyA9IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiBvcHRzLmVkaXRUeXBlLFxuICAgICAgICAgICAgXG4gICAgICAgIH07XG4gICAgICAgIG91dC5jb2x1bW4gPSB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG5leHBvcnRzLmRlZmF1bHRzID0gZnVuY3Rpb24oY29udGFpbmVyT3V0LCBsYXlvdXQsIGNvZXJjZSwgZGZsdERvbWFpbnMpIHtcbiAgICB2YXIgZGZsdFggPSAoZGZsdERvbWFpbnMgJiYgZGZsdERvbWFpbnMueCkgfHwgWzAsIDFdO1xuICAgIHZhciBkZmx0WSA9IChkZmx0RG9tYWlucyAmJiBkZmx0RG9tYWlucy55KSB8fCBbMCwgMV07XG5cbiAgICB2YXIgZ3JpZCA9IGxheW91dC5ncmlkO1xuICAgIGlmKGdyaWQpIHtcbiAgICAgICAgdmFyIGNvbHVtbiA9IGNvZXJjZSgnZG9tYWluLmNvbHVtbicpO1xuICAgICAgICBpZihjb2x1bW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYoY29sdW1uIDwgZ3JpZC5jb2x1bW5zKSBkZmx0WCA9IGdyaWQuX2RvbWFpbnMueFtjb2x1bW5dO1xuICAgICAgICAgICAgZWxzZSBkZWxldGUgY29udGFpbmVyT3V0LmRvbWFpbi5jb2x1bW47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcm93ID0gY29lcmNlKCdkb21haW4ucm93Jyk7XG4gICAgICAgIGlmKHJvdyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihyb3cgPCBncmlkLnJvd3MpIGRmbHRZID0gZ3JpZC5fZG9tYWlucy55W3Jvd107XG4gICAgICAgICAgICBlbHNlIGRlbGV0ZSBjb250YWluZXJPdXQuZG9tYWluLnJvdztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvZXJjZSgnZG9tYWluLngnLCBkZmx0WCk7XG4gICAgY29lcmNlKCdkb21haW4ueScsIGRmbHRZKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBtYWtlIGEgZm9udCBhdHRyaWJ1dGUgZ3JvdXBcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICogICBAcGFyYW0ge3N0cmluZ31cbiAqICAgICBvcHRzLmRlc2NyaXB0aW9uOiB3aGVyZSAmIGhvdyB0aGlzIGZvbnQgaXMgdXNlZFxuICogICBAcGFyYW0ge29wdGlvbmFsIGJvb2x9IGFycmF5T2s6XG4gKiAgICAgc2hvdWxkIGVhY2ggcGFydCAoZmFtaWx5LCBzaXplLCBjb2xvcikgYmUgYXJyYXlPaz8gZGVmYXVsdCBmYWxzZS5cbiAqICAgQHBhcmFtIHtzdHJpbmd9IGVkaXRUeXBlOlxuICogICAgIHRoZSBlZGl0VHlwZSBmb3IgYWxsIHBpZWNlcyBvZiB0aGlzIGZvbnRcbiAqICAgQHBhcmFtIHtvcHRpb25hbCBzdHJpbmd9IGNvbG9yRWRpdFR5cGU6XG4gKiAgICAgYSBzZXBhcmF0ZSBlZGl0VHlwZSBqdXN0IGZvciBjb2xvclxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gYXR0cmlidXRlcyBvYmplY3QgY29udGFpbmluZyB7ZmFtaWx5LCBzaXplLCBjb2xvcn0gYXMgc3BlY2lmaWVkXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHZhciBlZGl0VHlwZSA9IG9wdHMuZWRpdFR5cGU7XG4gICAgdmFyIGNvbG9yRWRpdFR5cGUgPSBvcHRzLmNvbG9yRWRpdFR5cGU7XG4gICAgaWYoY29sb3JFZGl0VHlwZSA9PT0gdW5kZWZpbmVkKSBjb2xvckVkaXRUeXBlID0gZWRpdFR5cGU7XG4gICAgdmFyIGF0dHJzID0ge1xuICAgICAgICBmYW1pbHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICAgICAgZWRpdFR5cGU6IGVkaXRUeXBlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDEsXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGVcbiAgICAgICAgfSxcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiBjb2xvckVkaXRUeXBlXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiBlZGl0VHlwZSxcbiAgICAgICAgLy8gYmxhbmsgc3RyaW5ncyBzbyBjb21wcmVzc19hdHRyaWJ1dGVzIGNhbiByZW1vdmVcbiAgICAgICAgLy8gVE9ETyAtIHRoYXQncyB1YmVyIGhhY2t5Li4uIGJldHRlciBzb2x1dGlvbj9cbiAgICAgICAgXG4gICAgfTtcblxuICAgIGlmKG9wdHMuYXJyYXlPaykge1xuICAgICAgICBhdHRycy5mYW1pbHkuYXJyYXlPayA9IHRydWU7XG4gICAgICAgIGF0dHJzLnNpemUuYXJyYXlPayA9IHRydWU7XG4gICAgICAgIGF0dHJzLmNvbG9yLmFycmF5T2sgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBhdHRycztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIF9pc0xpbmtlZFRvQXJyYXk6ICdmcmFtZXNfZW50cnknLFxuXG4gICAgZ3JvdXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIG5hbWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHRyYWNlczoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYmFzZWZyYW1lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBkYXRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBsYXlvdXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBwcm9qZWN0aW9uIG5hbWVzIHRvIGQzIGZ1bmN0aW9uIG5hbWVcbmV4cG9ydHMucHJvak5hbWVzID0ge1xuICAgIC8vIGQzLmdlby5wcm9qZWN0aW9uXG4gICAgJ2VxdWlyZWN0YW5ndWxhcic6ICdlcXVpcmVjdGFuZ3VsYXInLFxuICAgICdtZXJjYXRvcic6ICdtZXJjYXRvcicsXG4gICAgJ29ydGhvZ3JhcGhpYyc6ICdvcnRob2dyYXBoaWMnLFxuICAgICduYXR1cmFsIGVhcnRoJzogJ25hdHVyYWxFYXJ0aCcsXG4gICAgJ2thdnJheXNraXk3JzogJ2thdnJheXNraXk3JyxcbiAgICAnbWlsbGVyJzogJ21pbGxlcicsXG4gICAgJ3JvYmluc29uJzogJ3JvYmluc29uJyxcbiAgICAnZWNrZXJ0NCc6ICdlY2tlcnQ0JyxcbiAgICAnYXppbXV0aGFsIGVxdWFsIGFyZWEnOiAnYXppbXV0aGFsRXF1YWxBcmVhJyxcbiAgICAnYXppbXV0aGFsIGVxdWlkaXN0YW50JzogJ2F6aW11dGhhbEVxdWlkaXN0YW50JyxcbiAgICAnY29uaWMgZXF1YWwgYXJlYSc6ICdjb25pY0VxdWFsQXJlYScsXG4gICAgJ2NvbmljIGNvbmZvcm1hbCc6ICdjb25pY0NvbmZvcm1hbCcsXG4gICAgJ2NvbmljIGVxdWlkaXN0YW50JzogJ2NvbmljRXF1aWRpc3RhbnQnLFxuICAgICdnbm9tb25pYyc6ICdnbm9tb25pYycsXG4gICAgJ3N0ZXJlb2dyYXBoaWMnOiAnc3RlcmVvZ3JhcGhpYycsXG4gICAgJ21vbGx3ZWlkZSc6ICdtb2xsd2VpZGUnLFxuICAgICdoYW1tZXInOiAnaGFtbWVyJyxcbiAgICAndHJhbnN2ZXJzZSBtZXJjYXRvcic6ICd0cmFuc3ZlcnNlTWVyY2F0b3InLFxuICAgICdhbGJlcnMgdXNhJzogJ2FsYmVyc1VzYScsXG4gICAgJ3dpbmtlbCB0cmlwZWwnOiAnd2lua2VsMycsXG4gICAgJ2FpdG9mZic6ICdhaXRvZmYnLFxuICAgICdzaW51c29pZGFsJzogJ3NpbnVzb2lkYWwnXG59O1xuXG4vLyBuYW1lIG9mIHRoZSBheGVzXG5leHBvcnRzLmF4ZXNOYW1lcyA9IFsnbG9uYXhpcycsICdsYXRheGlzJ107XG5cbi8vIG1heCBsb25naXR1ZGluYWwgYW5ndWxhciBzcGFuIChFWFBFUklNRU5UQUwpXG5leHBvcnRzLmxvbmF4aXNTcGFuID0ge1xuICAgICdvcnRob2dyYXBoaWMnOiAxODAsXG4gICAgJ2F6aW11dGhhbCBlcXVhbCBhcmVhJzogMzYwLFxuICAgICdhemltdXRoYWwgZXF1aWRpc3RhbnQnOiAzNjAsXG4gICAgJ2NvbmljIGNvbmZvcm1hbCc6IDE4MCxcbiAgICAnZ25vbW9uaWMnOiAxNjAsXG4gICAgJ3N0ZXJlb2dyYXBoaWMnOiAxODAsXG4gICAgJ3RyYW5zdmVyc2UgbWVyY2F0b3InOiAxODAsXG4gICAgJyonOiAzNjBcbn07XG5cbi8vIG1heCBsYXRpdHVkaW5hbCBhbmd1bGFyIHNwYW4gKEVYUEVSSU1FTlRBTClcbmV4cG9ydHMubGF0YXhpc1NwYW4gPSB7XG4gICAgJ2NvbmljIGNvbmZvcm1hbCc6IDE1MCxcbiAgICAnc3RlcmVvZ3JhcGhpYyc6IDE3OS41LFxuICAgICcqJzogMTgwXG59O1xuXG4vLyBkZWZhdWx0cyBmb3IgZWFjaCBzY29wZVxuZXhwb3J0cy5zY29wZURlZmF1bHRzID0ge1xuICAgIHdvcmxkOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWy0xODAsIDE4MF0sXG4gICAgICAgIGxhdGF4aXNSYW5nZTogWy05MCwgOTBdLFxuICAgICAgICBwcm9qVHlwZTogJ2VxdWlyZWN0YW5ndWxhcicsXG4gICAgICAgIHByb2pSb3RhdGU6IFswLCAwLCAwXVxuICAgIH0sXG4gICAgdXNhOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWy0xODAsIC01MF0sXG4gICAgICAgIGxhdGF4aXNSYW5nZTogWzE1LCA4MF0sXG4gICAgICAgIHByb2pUeXBlOiAnYWxiZXJzIHVzYSdcbiAgICB9LFxuICAgIGV1cm9wZToge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMzAsIDYwXSxcbiAgICAgICAgbGF0YXhpc1JhbmdlOiBbMzAsIDg1XSxcbiAgICAgICAgcHJvalR5cGU6ICdjb25pYyBjb25mb3JtYWwnLFxuICAgICAgICBwcm9qUm90YXRlOiBbMTUsIDAsIDBdLFxuICAgICAgICBwcm9qUGFyYWxsZWxzOiBbMCwgNjBdXG4gICAgfSxcbiAgICBhc2lhOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWzIyLCAxNjBdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFstMTUsIDU1XSxcbiAgICAgICAgcHJvalR5cGU6ICdtZXJjYXRvcicsXG4gICAgICAgIHByb2pSb3RhdGU6IFswLCAwLCAwXVxuICAgIH0sXG4gICAgYWZyaWNhOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWy0zMCwgNjBdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFstNDAsIDQwXSxcbiAgICAgICAgcHJvalR5cGU6ICdtZXJjYXRvcicsXG4gICAgICAgIHByb2pSb3RhdGU6IFswLCAwLCAwXVxuICAgIH0sXG4gICAgJ25vcnRoIGFtZXJpY2EnOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWy0xODAsIC00NV0sXG4gICAgICAgIGxhdGF4aXNSYW5nZTogWzUsIDg1XSxcbiAgICAgICAgcHJvalR5cGU6ICdjb25pYyBjb25mb3JtYWwnLFxuICAgICAgICBwcm9qUm90YXRlOiBbLTEwMCwgMCwgMF0sXG4gICAgICAgIHByb2pQYXJhbGxlbHM6IFsyOS41LCA0NS41XVxuICAgIH0sXG4gICAgJ3NvdXRoIGFtZXJpY2EnOiB7XG4gICAgICAgIGxvbmF4aXNSYW5nZTogWy0xMDAsIC0zMF0sXG4gICAgICAgIGxhdGF4aXNSYW5nZTogWy02MCwgMTVdLFxuICAgICAgICBwcm9qVHlwZTogJ21lcmNhdG9yJyxcbiAgICAgICAgcHJvalJvdGF0ZTogWzAsIDAsIDBdXG4gICAgfVxufTtcblxuLy8gYW5ndWxhciBwYWQgdG8gYXZvaWQgcm91bmRpbmcgZXJyb3IgYXJvdW5kIGNsaXAgYW5nbGVzXG5leHBvcnRzLmNsaXBQYWQgPSAxZS0zO1xuXG4vLyBtYXAgcHJvamVjdGlvbiBwcmVjaXNpb25cbmV4cG9ydHMucHJlY2lzaW9uID0gMC4xO1xuXG4vLyBkZWZhdWx0IGxhbmQgYW5kIHdhdGVyIGZpbGwgY29sb3JzXG5leHBvcnRzLmxhbmRDb2xvciA9ICcjRjBEQzgyJztcbmV4cG9ydHMud2F0ZXJDb2xvciA9ICcjMzM5OUZGJztcblxuLy8gbG9jYXRpb25tb2RlIHRvIGxheWVyIG5hbWVcbmV4cG9ydHMubG9jYXRpb25tb2RlVG9MYXllciA9IHtcbiAgICAnSVNPLTMnOiAnY291bnRyaWVzJyxcbiAgICAnVVNBLXN0YXRlcyc6ICdzdWJ1bml0cycsXG4gICAgJ2NvdW50cnkgbmFtZXMnOiAnY291bnRyaWVzJ1xufTtcblxuLy8gU1ZHIGVsZW1lbnQgZm9yIGEgc3BoZXJlICh1c2UgdG8gZnJhbWUgbWFwcylcbmV4cG9ydHMuc3BoZXJlU1ZHID0ge3R5cGU6ICdTcGhlcmUnfTtcblxuLy8gTi5CLiBiYXNlIGxheWVyIG5hbWVzIG11c3QgYmUgdGhlIHNhbWUgYXMgaW4gdGhlIHRvcG9qc29uIGZpbGVzXG5cbi8vIGJhc2UgbGF5ZXIgd2l0aCBhIGZpbGwgY29sb3JcbmV4cG9ydHMuZmlsbExheWVycyA9IHtcbiAgICBvY2VhbjogMSxcbiAgICBsYW5kOiAxLFxuICAgIGxha2VzOiAxXG59O1xuXG4vLyBiYXNlIGxheWVyIHdpdGggYSBvbmx5IGEgbGluZSBjb2xvclxuZXhwb3J0cy5saW5lTGF5ZXJzID0ge1xuICAgIHN1YnVuaXRzOiAxLFxuICAgIGNvdW50cmllczogMSxcbiAgICBjb2FzdGxpbmVzOiAxLFxuICAgIHJpdmVyczogMSxcbiAgICBmcmFtZTogMVxufTtcblxuZXhwb3J0cy5sYXllcnMgPSBbXG4gICAgJ2JnJyxcbiAgICAnb2NlYW4nLCAnbGFuZCcsICdsYWtlcycsXG4gICAgJ3N1YnVuaXRzJywgJ2NvdW50cmllcycsICdjb2FzdGxpbmVzJywgJ3JpdmVycycsXG4gICAgJ2xhdGF4aXMnLCAnbG9uYXhpcycsICdmcmFtZScsXG4gICAgJ2JhY2twbG90JyxcbiAgICAnZnJvbnRwbG90J1xuXTtcblxuZXhwb3J0cy5sYXllcnNGb3JDaG9yb3BsZXRoID0gW1xuICAgICdiZycsXG4gICAgJ29jZWFuJywgJ2xhbmQnLFxuICAgICdzdWJ1bml0cycsICdjb3VudHJpZXMnLCAnY29hc3RsaW5lcycsXG4gICAgJ2xhdGF4aXMnLCAnbG9uYXhpcycsICdmcmFtZScsXG4gICAgJ2JhY2twbG90JyxcbiAgICAncml2ZXJzJywgJ2xha2VzJyxcbiAgICAnZnJvbnRwbG90J1xuXTtcblxuZXhwb3J0cy5sYXllck5hbWVUb0FkamVjdGl2ZSA9IHtcbiAgICBvY2VhbjogJ29jZWFuJyxcbiAgICBsYW5kOiAnbGFuZCcsXG4gICAgbGFrZXM6ICdsYWtlJyxcbiAgICBzdWJ1bml0czogJ3N1YnVuaXQnLFxuICAgIGNvdW50cmllczogJ2NvdW50cnknLFxuICAgIGNvYXN0bGluZXM6ICdjb2FzdGxpbmUnLFxuICAgIHJpdmVyczogJ3JpdmVyJyxcbiAgICBmcmFtZTogJ2ZyYW1lJ1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyogZ2xvYmFsIFBsb3RseUdlb0Fzc2V0czpmYWxzZSAqL1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50Jyk7XG52YXIgcHJlcFNlbGVjdCA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9zZWxlY3QnKS5wcmVwU2VsZWN0O1xudmFyIHNlbGVjdE9uQ2xpY2sgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0Jykuc2VsZWN0T25DbGljaztcblxudmFyIGNyZWF0ZUdlb1pvb20gPSByZXF1aXJlKCcuL3pvb20nKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xuXG52YXIgdG9wb2pzb25VdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi90b3BvanNvbl91dGlscycpO1xudmFyIHRvcG9qc29uRmVhdHVyZSA9IHJlcXVpcmUoJ3RvcG9qc29uLWNsaWVudCcpLmZlYXR1cmU7XG5cbnJlcXVpcmUoJy4vcHJvamVjdGlvbnMnKShkMyk7XG5cbmZ1bmN0aW9uIEdlbyhvcHRzKSB7XG4gICAgdGhpcy5pZCA9IG9wdHMuaWQ7XG4gICAgdGhpcy5ncmFwaERpdiA9IG9wdHMuZ3JhcGhEaXY7XG4gICAgdGhpcy5jb250YWluZXIgPSBvcHRzLmNvbnRhaW5lcjtcbiAgICB0aGlzLnRvcG9qc29uVVJMID0gb3B0cy50b3BvanNvblVSTDtcbiAgICB0aGlzLmlzU3RhdGljID0gb3B0cy5zdGF0aWNQbG90O1xuXG4gICAgdGhpcy50b3BvanNvbk5hbWUgPSBudWxsO1xuICAgIHRoaXMudG9wb2pzb24gPSBudWxsO1xuXG4gICAgdGhpcy5wcm9qZWN0aW9uID0gbnVsbDtcbiAgICB0aGlzLnZpZXdJbml0aWFsID0gbnVsbDtcbiAgICB0aGlzLmZpdFNjYWxlID0gbnVsbDtcbiAgICB0aGlzLmJvdW5kcyA9IG51bGw7XG4gICAgdGhpcy5taWRQdCA9IG51bGw7XG5cbiAgICB0aGlzLmhhc0Nob3JvcGxldGggPSBmYWxzZTtcbiAgICB0aGlzLnRyYWNlSGFzaCA9IHt9O1xuXG4gICAgdGhpcy5sYXllcnMgPSB7fTtcbiAgICB0aGlzLmJhc2VQYXRocyA9IHt9O1xuICAgIHRoaXMuZGF0YVBhdGhzID0ge307XG4gICAgdGhpcy5kYXRhUG9pbnRzID0ge307XG5cbiAgICB0aGlzLmNsaXBEZWYgPSBudWxsO1xuICAgIHRoaXMuY2xpcFJlY3QgPSBudWxsO1xuICAgIHRoaXMuYmdSZWN0ID0gbnVsbDtcblxuICAgIHRoaXMubWFrZUZyYW1ld29yaygpO1xufVxuXG52YXIgcHJvdG8gPSBHZW8ucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZUdlbyhvcHRzKSB7XG4gICAgcmV0dXJuIG5ldyBHZW8ob3B0cyk7XG59O1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24oZ2VvQ2FsY0RhdGEsIGZ1bGxMYXlvdXQsIHByb21pc2VzKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2VvTGF5b3V0ID0gZnVsbExheW91dFt0aGlzLmlkXTtcbiAgICB2YXIgdG9wb2pzb25OYW1lTmV3ID0gdG9wb2pzb25VdGlscy5nZXRUb3BvanNvbk5hbWUoZ2VvTGF5b3V0KTtcblxuICAgIGlmKF90aGlzLnRvcG9qc29uID09PSBudWxsIHx8IHRvcG9qc29uTmFtZU5ldyAhPT0gX3RoaXMudG9wb2pzb25OYW1lKSB7XG4gICAgICAgIF90aGlzLnRvcG9qc29uTmFtZSA9IHRvcG9qc29uTmFtZU5ldztcblxuICAgICAgICBpZihQbG90bHlHZW9Bc3NldHMudG9wb2pzb25bX3RoaXMudG9wb2pzb25OYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKF90aGlzLmZldGNoVG9wb2pzb24oKS50aGVuKGZ1bmN0aW9uKHRvcG9qc29uKSB7XG4gICAgICAgICAgICAgICAgUGxvdGx5R2VvQXNzZXRzLnRvcG9qc29uW190aGlzLnRvcG9qc29uTmFtZV0gPSB0b3BvanNvbjtcbiAgICAgICAgICAgICAgICBfdGhpcy50b3BvanNvbiA9IHRvcG9qc29uO1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZShnZW9DYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBfdGhpcy50b3BvanNvbiA9IFBsb3RseUdlb0Fzc2V0cy50b3BvanNvbltfdGhpcy50b3BvanNvbk5hbWVdO1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIF90aGlzLnVwZGF0ZShnZW9DYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgfVxufTtcblxucHJvdG8uZmV0Y2hUb3BvanNvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0b3BvanNvblBhdGggPSB0b3BvanNvblV0aWxzLmdldFRvcG9qc29uUGF0aChcbiAgICAgICAgdGhpcy50b3BvanNvblVSTCxcbiAgICAgICAgdGhpcy50b3BvanNvbk5hbWVcbiAgICApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZDMuanNvbih0b3BvanNvblBhdGgsIGZ1bmN0aW9uKGVyciwgdG9wb2pzb24pIHtcbiAgICAgICAgICAgIGlmKGVycikge1xuICAgICAgICAgICAgICAgIGlmKGVyci5zdGF0dXMgPT09IDQwNCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAncGxvdGx5LmpzIGNvdWxkIG5vdCBmaW5kIHRvcG9qc29uIGZpbGUgYXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wb2pzb25QYXRoLCAnLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAnTWFrZSBzdXJlIHRoZSAqdG9wb2pzb25VUkwqIHBsb3QgY29uZmlnIG9wdGlvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAnaXMgc2V0IHByb3Blcmx5LidcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAndW5leHBlY3RlZCBlcnJvciB3aGlsZSBmZXRjaGluZyB0b3BvanNvbiBmaWxlIGF0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcG9qc29uUGF0aFxuICAgICAgICAgICAgICAgICAgICBdLmpvaW4oJyAnKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUodG9wb2pzb24pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIGdlb0xheW91dCA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG5cbiAgICB2YXIgaGFzSW52YWxpZEJvdW5kcyA9IHRoaXMudXBkYXRlUHJvamVjdGlvbihmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIGlmKGhhc0ludmFsaWRCb3VuZHMpIHJldHVybjtcblxuICAgIC8vIGltcG9ydGFudDogbWFwcyB3aXRoIGNob3JvcGxldGggdHJhY2VzIGhhdmUgYSBkaWZmZXJlbnQgbGF5ZXIgb3JkZXJcbiAgICB0aGlzLmhhc0Nob3JvcGxldGggPSBmYWxzZTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZ2VvQ2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZ2VvQ2FsY0RhdGFbaV1bMF0udHJhY2UudHlwZSA9PT0gJ2Nob3JvcGxldGgnKSB7XG4gICAgICAgICAgICB0aGlzLmhhc0Nob3JvcGxldGggPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighdGhpcy52aWV3SW5pdGlhbCkge1xuICAgICAgICB0aGlzLnNhdmVWaWV3SW5pdGlhbChnZW9MYXlvdXQpO1xuICAgIH1cblxuICAgIHRoaXMudXBkYXRlQmFzZUxheWVycyhmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRGltcyhmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRngoZnVsbExheW91dCwgZ2VvTGF5b3V0KTtcblxuICAgIFBsb3RzLmdlbmVyYWxVcGRhdGVQZXJUcmFjZU1vZHVsZSh0aGlzLmdyYXBoRGl2LCB0aGlzLCBnZW9DYWxjRGF0YSwgZ2VvTGF5b3V0KTtcblxuICAgIHZhciBzY2F0dGVyTGF5ZXIgPSB0aGlzLmxheWVycy5mcm9udHBsb3Quc2VsZWN0KCcuc2NhdHRlcmxheWVyJyk7XG4gICAgdGhpcy5kYXRhUG9pbnRzLnBvaW50ID0gc2NhdHRlckxheWVyLnNlbGVjdEFsbCgnLnBvaW50Jyk7XG4gICAgdGhpcy5kYXRhUG9pbnRzLnRleHQgPSBzY2F0dGVyTGF5ZXIuc2VsZWN0QWxsKCd0ZXh0Jyk7XG4gICAgdGhpcy5kYXRhUGF0aHMubGluZSA9IHNjYXR0ZXJMYXllci5zZWxlY3RBbGwoJy5qcy1saW5lJyk7XG5cbiAgICB2YXIgY2hvcm9wbGV0aExheWVyID0gdGhpcy5sYXllcnMuYmFja3Bsb3Quc2VsZWN0KCcuY2hvcm9wbGV0aGxheWVyJyk7XG4gICAgdGhpcy5kYXRhUGF0aHMuY2hvcm9wbGV0aCA9IGNob3JvcGxldGhMYXllci5zZWxlY3RBbGwoJ3BhdGgnKTtcblxuICAgIHRoaXMucmVuZGVyKCk7XG59O1xuXG5wcm90by51cGRhdGVQcm9qZWN0aW9uID0gZnVuY3Rpb24oZnVsbExheW91dCwgZ2VvTGF5b3V0KSB7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgZG9tYWluID0gZ2VvTGF5b3V0LmRvbWFpbjtcbiAgICB2YXIgcHJvakxheW91dCA9IGdlb0xheW91dC5wcm9qZWN0aW9uO1xuICAgIHZhciByb3RhdGlvbiA9IHByb2pMYXlvdXQucm90YXRpb24gfHwge307XG4gICAgdmFyIGNlbnRlciA9IGdlb0xheW91dC5jZW50ZXIgfHwge307XG5cbiAgICB2YXIgcHJvamVjdGlvbiA9IHRoaXMucHJvamVjdGlvbiA9IGdldFByb2plY3Rpb24oZ2VvTGF5b3V0KTtcblxuICAgIC8vIHNldCAncHJlLWZpdCcgcHJvamVjdGlvblxuICAgIHByb2plY3Rpb25cbiAgICAgICAgLmNlbnRlcihbY2VudGVyLmxvbiAtIHJvdGF0aW9uLmxvbiwgY2VudGVyLmxhdCAtIHJvdGF0aW9uLmxhdF0pXG4gICAgICAgIC5yb3RhdGUoWy1yb3RhdGlvbi5sb24sIC1yb3RhdGlvbi5sYXQsIHJvdGF0aW9uLnJvbGxdKVxuICAgICAgICAucGFyYWxsZWxzKHByb2pMYXlvdXQucGFyYWxsZWxzKTtcblxuICAgIC8vIHNldHVwIHN1YnBsb3QgZXh0ZW50IFtbeDAseTBdLCBbeDEseTFdXVxuICAgIHZhciBleHRlbnQgPSBbW1xuICAgICAgICBncy5sICsgZ3MudyAqIGRvbWFpbi54WzBdLFxuICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gZG9tYWluLnlbMV0pXG4gICAgXSwgW1xuICAgICAgICBncy5sICsgZ3MudyAqIGRvbWFpbi54WzFdLFxuICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gZG9tYWluLnlbMF0pXG4gICAgXV07XG5cbiAgICB2YXIgbG9uYXhpcyA9IGdlb0xheW91dC5sb25heGlzO1xuICAgIHZhciBsYXRheGlzID0gZ2VvTGF5b3V0LmxhdGF4aXM7XG4gICAgdmFyIHJhbmdlQm94ID0gbWFrZVJhbmdlQm94KGxvbmF4aXMucmFuZ2UsIGxhdGF4aXMucmFuZ2UpO1xuXG4gICAgLy8gZml0IHByb2plY3Rpb24gJ3NjYWxlJyBhbmQgJ3RyYW5zbGF0ZScgdG8gc2V0IGxvbi9sYXQgcmFuZ2VzXG4gICAgcHJvamVjdGlvbi5maXRFeHRlbnQoZXh0ZW50LCByYW5nZUJveCk7XG5cbiAgICB2YXIgYiA9IHRoaXMuYm91bmRzID0gcHJvamVjdGlvbi5nZXRCb3VuZHMocmFuZ2VCb3gpO1xuICAgIHZhciBzID0gdGhpcy5maXRTY2FsZSA9IHByb2plY3Rpb24uc2NhbGUoKTtcbiAgICB2YXIgdCA9IHByb2plY3Rpb24udHJhbnNsYXRlKCk7XG5cbiAgICBpZihcbiAgICAgICAgIWlzRmluaXRlKGJbMF1bMF0pIHx8ICFpc0Zpbml0ZShiWzBdWzFdKSB8fFxuICAgICAgICAhaXNGaW5pdGUoYlsxXVswXSkgfHwgIWlzRmluaXRlKGJbMV1bMV0pIHx8XG4gICAgICAgIGlzTmFOKHRbMF0pIHx8IGlzTmFOKHRbMF0pXG4gICAgKSB7XG4gICAgICAgIHZhciBnZCA9IHRoaXMuZ3JhcGhEaXY7XG4gICAgICAgIHZhciBhdHRyVG9VbnNldCA9IFsncHJvamVjdGlvbi5yb3RhdGlvbicsICdjZW50ZXInLCAnbG9uYXhpcy5yYW5nZScsICdsYXRheGlzLnJhbmdlJ107XG4gICAgICAgIHZhciBtc2cgPSAnSW52YWxpZCBnZW8gc2V0dGluZ3MsIHJlbGF5b3V0XFwnaW5nIHRvIGRlZmF1bHQgdmlldy4nO1xuICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG5cbiAgICAgICAgLy8gY2xlYXIgYWxsIGF0dHJpYnV0ZSB0aGF0IGNvdWxkIGNhdXNlIGludmFsaWQgYm91bmRzLFxuICAgICAgICAvLyBjbGVhciB2aWV3SW5pdGlhbCB0byB1cGRhdGUgcmVzZXQtdmlldyBiZWhhdmlvclxuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhdHRyVG9VbnNldC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdXBkYXRlT2JqW3RoaXMuaWQgKyAnLicgKyBhdHRyVG9VbnNldFtpXV0gPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWV3SW5pdGlhbCA9IG51bGw7XG5cbiAgICAgICAgTGliLndhcm4obXNnKTtcbiAgICAgICAgZ2QuX3Byb21pc2VzLnB1c2goUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgdXBkYXRlT2JqKSk7XG4gICAgICAgIHJldHVybiBtc2c7XG4gICAgfVxuXG4gICAgLy8gcHggY29vcmRpbmF0ZXMgb2YgdmlldyBtaWQtcG9pbnQsXG4gICAgLy8gdXNlZnVsIHRvIHVwZGF0ZSBgZ2VvLmNlbnRlcmAgYWZ0ZXIgaW50ZXJhY3Rpb25zXG4gICAgdmFyIG1pZFB0ID0gdGhpcy5taWRQdCA9IFtcbiAgICAgICAgKGJbMF1bMF0gKyBiWzFdWzBdKSAvIDIsXG4gICAgICAgIChiWzBdWzFdICsgYlsxXVsxXSkgLyAyXG4gICAgXTtcblxuICAgIC8vIGFkanVzdCBwcm9qZWN0aW9uIHRvIHVzZXIgc2V0dGluZ1xuICAgIHByb2plY3Rpb25cbiAgICAgICAgLnNjYWxlKHByb2pMYXlvdXQuc2NhbGUgKiBzKVxuICAgICAgICAudHJhbnNsYXRlKFt0WzBdICsgKG1pZFB0WzBdIC0gdFswXSksIHRbMV0gKyAobWlkUHRbMV0gLSB0WzFdKV0pXG4gICAgICAgIC5jbGlwRXh0ZW50KGIpO1xuXG4gICAgLy8gdGhlICdhbGJlcnMgdXNhJyBwcm9qZWN0aW9uIGRvZXMgbm90IGV4cG9zZSBhICdjZW50ZXInIG1ldGhvZFxuICAgIC8vIHNvIGhlcmUncyB0aGlzIGhhY2sgdG8gbWFrZSBpdCByZXNwb25kIHRvICdnZW9MYXlvdXQuY2VudGVyJ1xuICAgIGlmKGdlb0xheW91dC5faXNBbGJlcnNVc2EpIHtcbiAgICAgICAgdmFyIGNlbnRlclB4ID0gcHJvamVjdGlvbihbY2VudGVyLmxvbiwgY2VudGVyLmxhdF0pO1xuICAgICAgICB2YXIgdHQgPSBwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpO1xuXG4gICAgICAgIHByb2plY3Rpb24udHJhbnNsYXRlKFtcbiAgICAgICAgICAgIHR0WzBdIC0gKGNlbnRlclB4WzBdIC0gdHRbMF0pLFxuICAgICAgICAgICAgdHRbMV0gLSAoY2VudGVyUHhbMV0gLSB0dFsxXSlcbiAgICAgICAgXSk7XG4gICAgfVxufTtcblxucHJvdG8udXBkYXRlQmFzZUxheWVycyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIGdlb0xheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIHRvcG9qc29uID0gX3RoaXMudG9wb2pzb247XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgYmFzZVBhdGhzID0gX3RoaXMuYmFzZVBhdGhzO1xuXG4gICAgZnVuY3Rpb24gaXNBeGlzTGF5ZXIoZCkge1xuICAgICAgICByZXR1cm4gKGQgPT09ICdsb25heGlzJyB8fCBkID09PSAnbGF0YXhpcycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTGluZUxheWVyKGQpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oY29uc3RhbnRzLmxpbmVMYXllcnNbZF0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRmlsbExheWVyKGQpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oY29uc3RhbnRzLmZpbGxMYXllcnNbZF0pO1xuICAgIH1cblxuICAgIHZhciBhbGxMYXllcnMgPSB0aGlzLmhhc0Nob3JvcGxldGggP1xuICAgICAgICBjb25zdGFudHMubGF5ZXJzRm9yQ2hvcm9wbGV0aCA6XG4gICAgICAgIGNvbnN0YW50cy5sYXllcnM7XG5cbiAgICB2YXIgbGF5ZXJEYXRhID0gYWxsTGF5ZXJzLmZpbHRlcihmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAoaXNMaW5lTGF5ZXIoZCkgfHwgaXNGaWxsTGF5ZXIoZCkpID8gZ2VvTGF5b3V0WydzaG93JyArIGRdIDpcbiAgICAgICAgICAgIGlzQXhpc0xheWVyKGQpID8gZ2VvTGF5b3V0W2RdLnNob3dncmlkIDpcbiAgICAgICAgICAgIHRydWU7XG4gICAgfSk7XG5cbiAgICB2YXIgam9pbiA9IF90aGlzLmZyYW1ld29yay5zZWxlY3RBbGwoJy5sYXllcicpXG4gICAgICAgIC5kYXRhKGxheWVyRGF0YSwgU3RyaW5nKTtcblxuICAgIGpvaW4uZXhpdCgpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBkZWxldGUgbGF5ZXJzW2RdO1xuICAgICAgICBkZWxldGUgYmFzZVBhdGhzW2RdO1xuICAgICAgICBkMy5zZWxlY3QodGhpcykucmVtb3ZlKCk7XG4gICAgfSk7XG5cbiAgICBqb2luLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gJ2xheWVyICcgKyBkOyB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgbGF5ZXIgPSBsYXllcnNbZF0gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIGlmKGQgPT09ICdiZycpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5iZ1JlY3QgPSBsYXllci5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGlzQXhpc0xheWVyKGQpKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBhdGhzW2RdID0gbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkID09PSAnYmFja3Bsb3QnKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2Nob3JvcGxldGhsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGQgPT09ICdmcm9udHBsb3QnKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3NjYXR0ZXJsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGlzTGluZUxheWVyKGQpKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBhdGhzW2RdID0gbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMik7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNGaWxsTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgICAgICBiYXNlUGF0aHNbZF0gPSBsYXllci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZScsICdub25lJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgam9pbi5vcmRlcigpO1xuXG4gICAgam9pbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHBhdGggPSBiYXNlUGF0aHNbZF07XG4gICAgICAgIHZhciBhZGogPSBjb25zdGFudHMubGF5ZXJOYW1lVG9BZGplY3RpdmVbZF07XG5cbiAgICAgICAgaWYoZCA9PT0gJ2ZyYW1lJykge1xuICAgICAgICAgICAgcGF0aC5kYXR1bShjb25zdGFudHMuc3BoZXJlU1ZHKTtcbiAgICAgICAgfSBlbHNlIGlmKGlzTGluZUxheWVyKGQpIHx8IGlzRmlsbExheWVyKGQpKSB7XG4gICAgICAgICAgICBwYXRoLmRhdHVtKHRvcG9qc29uRmVhdHVyZSh0b3BvanNvbiwgdG9wb2pzb24ub2JqZWN0c1tkXSkpO1xuICAgICAgICB9IGVsc2UgaWYoaXNBeGlzTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgIHBhdGguZGF0dW0obWFrZUdyYXRpY3VsZShkLCBnZW9MYXlvdXQpKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgZ2VvTGF5b3V0W2RdLmdyaWRjb2xvcilcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCAnJywgZ2VvTGF5b3V0W2RdLmdyaWR3aWR0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpc0xpbmVMYXllcihkKSkge1xuICAgICAgICAgICAgcGF0aC5jYWxsKENvbG9yLnN0cm9rZSwgZ2VvTGF5b3V0W2FkaiArICdjb2xvciddKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZGFzaExpbmUsICcnLCBnZW9MYXlvdXRbYWRqICsgJ3dpZHRoJ10pO1xuICAgICAgICB9IGVsc2UgaWYoaXNGaWxsTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgIHBhdGguY2FsbChDb2xvci5maWxsLCBnZW9MYXlvdXRbYWRqICsgJ2NvbG9yJ10pO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5wcm90by51cGRhdGVEaW1zID0gZnVuY3Rpb24oZnVsbExheW91dCwgZ2VvTGF5b3V0KSB7XG4gICAgdmFyIGIgPSB0aGlzLmJvdW5kcztcbiAgICB2YXIgaEZyYW1lV2lkdGggPSAoZ2VvTGF5b3V0LmZyYW1ld2lkdGggfHwgMCkgLyAyO1xuXG4gICAgdmFyIGwgPSBiWzBdWzBdIC0gaEZyYW1lV2lkdGg7XG4gICAgdmFyIHQgPSBiWzBdWzFdIC0gaEZyYW1lV2lkdGg7XG4gICAgdmFyIHcgPSBiWzFdWzBdIC0gbCArIGhGcmFtZVdpZHRoO1xuICAgIHZhciBoID0gYlsxXVsxXSAtIHQgKyBoRnJhbWVXaWR0aDtcblxuICAgIERyYXdpbmcuc2V0UmVjdCh0aGlzLmNsaXBSZWN0LCBsLCB0LCB3LCBoKTtcblxuICAgIHRoaXMuYmdSZWN0XG4gICAgICAgIC5jYWxsKERyYXdpbmcuc2V0UmVjdCwgbCwgdCwgdywgaClcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZ2VvTGF5b3V0LmJnY29sb3IpO1xuXG4gICAgdGhpcy54YXhpcy5fb2Zmc2V0ID0gbDtcbiAgICB0aGlzLnhheGlzLl9sZW5ndGggPSB3O1xuXG4gICAgdGhpcy55YXhpcy5fb2Zmc2V0ID0gdDtcbiAgICB0aGlzLnlheGlzLl9sZW5ndGggPSBoO1xufTtcblxucHJvdG8udXBkYXRlRnggPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBnZW9MYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBnZCA9IF90aGlzLmdyYXBoRGl2O1xuICAgIHZhciBiZ1JlY3QgPSBfdGhpcy5iZ1JlY3Q7XG4gICAgdmFyIGRyYWdNb2RlID0gZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICB2YXIgY2xpY2tNb2RlID0gZnVsbExheW91dC5jbGlja21vZGU7XG5cbiAgICBpZihfdGhpcy5pc1N0YXRpYykgcmV0dXJuO1xuXG4gICAgZnVuY3Rpb24gem9vbVJlc2V0KCkge1xuICAgICAgICB2YXIgdmlld0luaXRpYWwgPSBfdGhpcy52aWV3SW5pdGlhbDtcbiAgICAgICAgdmFyIHVwZGF0ZU9iaiA9IHt9O1xuXG4gICAgICAgIGZvcih2YXIgayBpbiB2aWV3SW5pdGlhbCkge1xuICAgICAgICAgICAgdXBkYXRlT2JqW190aGlzLmlkICsgJy4nICsga10gPSB2aWV3SW5pdGlhbFtrXTtcbiAgICAgICAgfVxuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIHVwZGF0ZU9iaik7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kb3VibGVjbGljaycsIG51bGwpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGludmVydChsb25sYXQpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzLnByb2plY3Rpb24uaW52ZXJ0KFtcbiAgICAgICAgICAgIGxvbmxhdFswXSArIF90aGlzLnhheGlzLl9vZmZzZXQsXG4gICAgICAgICAgICBsb25sYXRbMV0gKyBfdGhpcy55YXhpcy5fb2Zmc2V0XG4gICAgICAgIF0pO1xuICAgIH1cblxuICAgIHZhciBmaWxsUmFuZ2VJdGVtcztcblxuICAgIGlmKGRyYWdNb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICBmaWxsUmFuZ2VJdGVtcyA9IGZ1bmN0aW9uKGV2ZW50RGF0YSwgcG9seSkge1xuICAgICAgICAgICAgdmFyIHJhbmdlcyA9IGV2ZW50RGF0YS5yYW5nZSA9IHt9O1xuICAgICAgICAgICAgcmFuZ2VzW190aGlzLmlkXSA9IFtcbiAgICAgICAgICAgICAgICBpbnZlcnQoW3BvbHkueG1pbiwgcG9seS55bWluXSksXG4gICAgICAgICAgICAgICAgaW52ZXJ0KFtwb2x5LnhtYXgsIHBvbHkueW1heF0pXG4gICAgICAgICAgICBdO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihkcmFnTW9kZSA9PT0gJ2xhc3NvJykge1xuICAgICAgICBmaWxsUmFuZ2VJdGVtcyA9IGZ1bmN0aW9uKGV2ZW50RGF0YSwgcG9seSwgcHRzKSB7XG4gICAgICAgICAgICB2YXIgZGF0YVB0cyA9IGV2ZW50RGF0YS5sYXNzb1BvaW50cyA9IHt9O1xuICAgICAgICAgICAgZGF0YVB0c1tfdGhpcy5pZF0gPSBwdHMuZmlsdGVyZWQubWFwKGludmVydCk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gTm90ZTogZHJhZ09wdGlvbnMgaXMgbmVlZGVkIHRvIGJlIGRlY2xhcmVkIGZvciBhbGwgZHJhZ21vZGVzIGJlY2F1c2VcbiAgICAvLyBpdCdzIHRoZSBvYmplY3QgdGhhdCBob2xkcyBwZXJzaXN0ZW50IHNlbGVjdGlvbiBzdGF0ZS5cbiAgICB2YXIgZHJhZ09wdGlvbnMgPSB7XG4gICAgICAgIGVsZW1lbnQ6IF90aGlzLmJnUmVjdC5ub2RlKCksXG4gICAgICAgIGdkOiBnZCxcbiAgICAgICAgcGxvdGluZm86IHtcbiAgICAgICAgICAgIGlkOiBfdGhpcy5pZCxcbiAgICAgICAgICAgIHhheGlzOiBfdGhpcy54YXhpcyxcbiAgICAgICAgICAgIHlheGlzOiBfdGhpcy55YXhpcyxcbiAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zOiBmaWxsUmFuZ2VJdGVtc1xuICAgICAgICB9LFxuICAgICAgICB4YXhlczogW190aGlzLnhheGlzXSxcbiAgICAgICAgeWF4ZXM6IFtfdGhpcy55YXhpc10sXG4gICAgICAgIHN1YnBsb3Q6IF90aGlzLmlkLFxuICAgICAgICBjbGlja0ZuOiBmdW5jdGlvbihudW1DbGlja3MpIHtcbiAgICAgICAgICAgIGlmKG51bUNsaWNrcyA9PT0gMikge1xuICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXQuX3pvb21sYXllci5zZWxlY3RBbGwoJy5zZWxlY3Qtb3V0bGluZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmKGRyYWdNb2RlID09PSAncGFuJykge1xuICAgICAgICBiZ1JlY3Qubm9kZSgpLm9ubW91c2Vkb3duID0gbnVsbDtcbiAgICAgICAgYmdSZWN0LmNhbGwoY3JlYXRlR2VvWm9vbShfdGhpcywgZ2VvTGF5b3V0KSk7XG4gICAgICAgIGJnUmVjdC5vbignZGJsY2xpY2suem9vbScsIHpvb21SZXNldCk7XG4gICAgfVxuICAgIGVsc2UgaWYoZHJhZ01vZGUgPT09ICdzZWxlY3QnIHx8IGRyYWdNb2RlID09PSAnbGFzc28nKSB7XG4gICAgICAgIGJnUmVjdC5vbignLnpvb20nLCBudWxsKTtcblxuICAgICAgICBkcmFnT3B0aW9ucy5wcmVwRm4gPSBmdW5jdGlvbihlLCBzdGFydFgsIHN0YXJ0WSkge1xuICAgICAgICAgICAgcHJlcFNlbGVjdChlLCBzdGFydFgsIHN0YXJ0WSwgZHJhZ09wdGlvbnMsIGRyYWdNb2RlKTtcbiAgICAgICAgfTtcblxuICAgICAgICBkcmFnRWxlbWVudC5pbml0KGRyYWdPcHRpb25zKTtcbiAgICB9XG5cbiAgICBiZ1JlY3Qub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgbG9ubGF0ID0gX3RoaXMucHJvamVjdGlvbi5pbnZlcnQoZDMubW91c2UodGhpcykpO1xuXG4gICAgICAgIGlmKCFsb25sYXQgfHwgaXNOYU4obG9ubGF0WzBdKSB8fCBpc05hTihsb25sYXRbMV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCwgZDMuZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgX3RoaXMueGF4aXMucDJjID0gZnVuY3Rpb24oKSB7IHJldHVybiBsb25sYXRbMF07IH07XG4gICAgICAgIF90aGlzLnlheGlzLnAyYyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gbG9ubGF0WzFdOyB9O1xuXG4gICAgICAgIEZ4LmhvdmVyKGdkLCBkMy5ldmVudCwgX3RoaXMuaWQpO1xuICAgIH0pO1xuXG4gICAgYmdSZWN0Lm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZihnZC5fZHJhZ2dpbmcpIHJldHVybjtcbiAgICAgICAgZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCwgZDMuZXZlbnQpO1xuICAgIH0pO1xuXG4gICAgYmdSZWN0Lm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBGb3Igc2VsZWN0IGFuZCBsYXNzbyB0aGUgZHJhZ0VsZW1lbnQgaXMgaGFuZGxpbmcgY2xpY2tzXG4gICAgICAgIGlmKGRyYWdNb2RlICE9PSAnc2VsZWN0JyAmJiBkcmFnTW9kZSAhPT0gJ2xhc3NvJykge1xuICAgICAgICAgICAgaWYoY2xpY2tNb2RlLmluZGV4T2YoJ3NlbGVjdCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RPbkNsaWNrKGQzLmV2ZW50LCBnZCwgW190aGlzLnhheGlzXSwgW190aGlzLnlheGlzXSxcbiAgICAgICAgICAgICAgICAgIF90aGlzLmlkLCBkcmFnT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBsaWtlIHBpZSBhbmQgbWFwYm94LCB0aGlzIGRvZXNuJ3Qgc3VwcG9ydCByaWdodC1jbGlja1xuICAgICAgICAgICAgICAgIC8vIGFjdHVhbGx5IHRoaXMgb25lIGlzIHdvcnNlLCBhcyByaWdodC1jbGljayBzdGFydHMgYSBwYW4sIG9yIGxlYXZlc1xuICAgICAgICAgICAgICAgIC8vIHNlbGVjdCBpbiBhIHdlaXJkIHN0YXRlLlxuICAgICAgICAgICAgICAgIC8vIEFsc28sIG9ubHkgdGFuZ2VudGlhbGx5IHJlbGF0ZWQsIHdlIHNob3VsZCBjYW5jZWwgaG92ZXIgZHVyaW5nIHBhblxuICAgICAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBkMy5ldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbnByb3RvLm1ha2VGcmFtZXdvcmsgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gX3RoaXMuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNsaXBJZCA9ICdjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIF90aGlzLmlkO1xuXG4gICAgX3RoaXMuY2xpcERlZiA9IGZ1bGxMYXlvdXQuX2NsaXBzLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuYXR0cignaWQnLCBjbGlwSWQpO1xuXG4gICAgX3RoaXMuY2xpcFJlY3QgPSBfdGhpcy5jbGlwRGVmLmFwcGVuZCgncmVjdCcpO1xuXG4gICAgX3RoaXMuZnJhbWV3b3JrID0gZDMuc2VsZWN0KF90aGlzLmNvbnRhaW5lcikuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dlbyAnICsgX3RoaXMuaWQpXG4gICAgICAgIC5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgY2xpcElkKTtcblxuICAgIC8vIHNhbmUgbG9ubGF0IHRvIHB4XG4gICAgX3RoaXMucHJvamVjdCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgdmFyIHB4ID0gX3RoaXMucHJvamVjdGlvbih2KTtcbiAgICAgICAgcmV0dXJuIHB4ID9cbiAgICAgICAgICAgIFtweFswXSAtIF90aGlzLnhheGlzLl9vZmZzZXQsIHB4WzFdIC0gX3RoaXMueWF4aXMuX29mZnNldF0gOlxuICAgICAgICAgICAgW251bGwsIG51bGxdO1xuICAgIH07XG5cbiAgICBfdGhpcy54YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneCcsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gX3RoaXMucHJvamVjdCh2KVswXTsgfVxuICAgIH07XG5cbiAgICBfdGhpcy55YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gX3RoaXMucHJvamVjdCh2KVsxXTsgfVxuICAgIH07XG5cbiAgICAvLyBtb2NrIGF4aXMgZm9yIGhvdmVyIGZvcm1hdHRpbmdcbiAgICBfdGhpcy5tb2NrQXhpcyA9IHtcbiAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgIHNob3dleHBvbmVudDogJ2FsbCcsXG4gICAgICAgIGV4cG9uZW50Zm9ybWF0OiAnQidcbiAgICB9O1xuICAgIEF4ZXMuc2V0Q29udmVydChfdGhpcy5tb2NrQXhpcywgZnVsbExheW91dCk7XG59O1xuXG5wcm90by5zYXZlVmlld0luaXRpYWwgPSBmdW5jdGlvbihnZW9MYXlvdXQpIHtcbiAgICB2YXIgY2VudGVyID0gZ2VvTGF5b3V0LmNlbnRlciB8fCB7fTtcbiAgICB2YXIgcHJvakxheW91dCA9IGdlb0xheW91dC5wcm9qZWN0aW9uO1xuICAgIHZhciByb3RhdGlvbiA9IHByb2pMYXlvdXQucm90YXRpb24gfHwge307XG5cbiAgICBpZihnZW9MYXlvdXQuX2lzU2NvcGVkKSB7XG4gICAgICAgIHRoaXMudmlld0luaXRpYWwgPSB7XG4gICAgICAgICAgICAnY2VudGVyLmxvbic6IGNlbnRlci5sb24sXG4gICAgICAgICAgICAnY2VudGVyLmxhdCc6IGNlbnRlci5sYXQsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5zY2FsZSc6IHByb2pMYXlvdXQuc2NhbGVcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoZ2VvTGF5b3V0Ll9pc0NsaXBwZWQpIHtcbiAgICAgICAgdGhpcy52aWV3SW5pdGlhbCA9IHtcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnNjYWxlJzogcHJvakxheW91dC5zY2FsZSxcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnJvdGF0aW9uLmxvbic6IHJvdGF0aW9uLmxvbixcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnJvdGF0aW9uLmxhdCc6IHJvdGF0aW9uLmxhdFxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudmlld0luaXRpYWwgPSB7XG4gICAgICAgICAgICAnY2VudGVyLmxvbic6IGNlbnRlci5sb24sXG4gICAgICAgICAgICAnY2VudGVyLmxhdCc6IGNlbnRlci5sYXQsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5zY2FsZSc6IHByb2pMYXlvdXQuc2NhbGUsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5yb3RhdGlvbi5sb24nOiByb3RhdGlvbi5sb25cbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG4vLyBbaG90IGNvZGUgcGF0aF0gKHJlKWRyYXcgYWxsIHBhdGhzIHdoaWNoIGRlcGVuZCBvbiB0aGUgcHJvamVjdGlvblxucHJvdG8ucmVuZGVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSB0aGlzLnByb2plY3Rpb247XG4gICAgdmFyIHBhdGhGbiA9IHByb2plY3Rpb24uZ2V0UGF0aCgpO1xuICAgIHZhciBrO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlUG9pbnRzKGQpIHtcbiAgICAgICAgdmFyIGxvbmxhdFB4ID0gcHJvamVjdGlvbihkLmxvbmxhdCk7XG4gICAgICAgIHJldHVybiBsb25sYXRQeCA/XG4gICAgICAgICAgICAndHJhbnNsYXRlKCcgKyBsb25sYXRQeFswXSArICcsJyArIGxvbmxhdFB4WzFdICsgJyknIDpcbiAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhpZGVTaG93UG9pbnRzKGQpIHtcbiAgICAgICAgcmV0dXJuIHByb2plY3Rpb24uaXNMb25MYXRPdmVyRWRnZXMoZC5sb25sYXQpID8gJ25vbmUnIDogbnVsbDtcbiAgICB9XG5cbiAgICBmb3IoayBpbiB0aGlzLmJhc2VQYXRocykge1xuICAgICAgICB0aGlzLmJhc2VQYXRoc1trXS5hdHRyKCdkJywgcGF0aEZuKTtcbiAgICB9XG5cbiAgICBmb3IoayBpbiB0aGlzLmRhdGFQYXRocykge1xuICAgICAgICB0aGlzLmRhdGFQYXRoc1trXS5hdHRyKCdkJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gcGF0aEZuKGQuZ2VvanNvbik7IH0pO1xuICAgIH1cblxuICAgIGZvcihrIGluIHRoaXMuZGF0YVBvaW50cykge1xuICAgICAgICB0aGlzLmRhdGFQb2ludHNba11cbiAgICAgICAgICAgIC5hdHRyKCdkaXNwbGF5JywgaGlkZVNob3dQb2ludHMpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgdHJhbnNsYXRlUG9pbnRzKTtcbiAgICB9XG59O1xuXG4vLyBIZWxwZXIgdGhhdCB3cmFwcyBkMy5nZW9bLyogcHJvamVjdGlvbiBuYW1lIC8qXSgpIHdoaWNoOlxuLy9cbi8vIC0gYWRkcyAnZml0RXh0ZW50JyAoYXZhaWxhYmxlIGluIGQzIHY0KVxuLy8gLSBhZGRzICdnZXRQYXRoJywgJ2dldEJvdW5kcycgY29udmVuaWVuY2UgbWV0aG9kc1xuLy8gLSBzY29wZXMgbG9naWMgcmVsYXRlZCB0byAnY2xpcEFuZ2xlJ1xuLy8gLSBhZGRzICdpc0xvbkxhdE92ZXJFZGdlcycgbWV0aG9kXG4vLyAtIHNldHMgcHJvamVjdGlvbiBwcmVjaXNpb25cbi8vIC0gc2V0cyBtZXRob2RzIHRoYXQgYXJlbid0IGFsd2F5cyBkZWZpbmVkIGRlcGVuZGluZ1xuLy8gICBvbiB0aGUgcHJvamVjdGlvbiB0eXBlIHRvIGEgZHVtbXkgJ2QzLWVzcXVlJyBmdW5jdGlvbixcbi8vXG4vLyBUaGlzIHdyYXBwZXIgYWxsZXZpYXRlcyBzdWJzZXF1ZW50IGNvZGUgb2YgKG1hbnkpIGFubm95aW5nIGlmLXN0YXRlbWVudHMuXG5mdW5jdGlvbiBnZXRQcm9qZWN0aW9uKGdlb0xheW91dCkge1xuICAgIHZhciBwcm9qTGF5b3V0ID0gZ2VvTGF5b3V0LnByb2plY3Rpb247XG4gICAgdmFyIHByb2pUeXBlID0gcHJvakxheW91dC50eXBlO1xuXG4gICAgdmFyIHByb2plY3Rpb24gPSBkMy5nZW9bY29uc3RhbnRzLnByb2pOYW1lc1twcm9qVHlwZV1dKCk7XG5cbiAgICB2YXIgY2xpcEFuZ2xlID0gZ2VvTGF5b3V0Ll9pc0NsaXBwZWQgP1xuICAgICAgICBjb25zdGFudHMubG9uYXhpc1NwYW5bcHJvalR5cGVdIC8gMiA6XG4gICAgICAgIG51bGw7XG5cbiAgICB2YXIgbWV0aG9kcyA9IFsnY2VudGVyJywgJ3JvdGF0ZScsICdwYXJhbGxlbHMnLCAnY2xpcEV4dGVudCddO1xuICAgIHZhciBkdW1teUZuID0gZnVuY3Rpb24oXykgeyByZXR1cm4gXyA/IHByb2plY3Rpb24gOiBbXTsgfTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtZXRob2RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBtID0gbWV0aG9kc1tpXTtcbiAgICAgICAgaWYodHlwZW9mIHByb2plY3Rpb25bbV0gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb2plY3Rpb25bbV0gPSBkdW1teUZuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvamVjdGlvbi5pc0xvbkxhdE92ZXJFZGdlcyA9IGZ1bmN0aW9uKGxvbmxhdCkge1xuICAgICAgICBpZihwcm9qZWN0aW9uKGxvbmxhdCkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY2xpcEFuZ2xlKSB7XG4gICAgICAgICAgICB2YXIgciA9IHByb2plY3Rpb24ucm90YXRlKCk7XG4gICAgICAgICAgICB2YXIgYW5nbGUgPSBkMy5nZW8uZGlzdGFuY2UobG9ubGF0LCBbLXJbMF0sIC1yWzFdXSk7XG4gICAgICAgICAgICB2YXIgbWF4QW5nbGUgPSBjbGlwQW5nbGUgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgcmV0dXJuIGFuZ2xlID4gbWF4QW5nbGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvamVjdGlvbi5nZXRQYXRoID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBkMy5nZW8ucGF0aCgpLnByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgfTtcblxuICAgIHByb2plY3Rpb24uZ2V0Qm91bmRzID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBwcm9qZWN0aW9uLmdldFBhdGgoKS5ib3VuZHMob2JqZWN0KTtcbiAgICB9O1xuXG4gICAgLy8gYWRhcHRlZCBmcm9tIGQzIHY0OlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy1nZW8vYmxvYi9tYXN0ZXIvc3JjL3Byb2plY3Rpb24vZml0LmpzXG4gICAgcHJvamVjdGlvbi5maXRFeHRlbnQgPSBmdW5jdGlvbihleHRlbnQsIG9iamVjdCkge1xuICAgICAgICB2YXIgdyA9IGV4dGVudFsxXVswXSAtIGV4dGVudFswXVswXTtcbiAgICAgICAgdmFyIGggPSBleHRlbnRbMV1bMV0gLSBleHRlbnRbMF1bMV07XG4gICAgICAgIHZhciBjbGlwID0gcHJvamVjdGlvbi5jbGlwRXh0ZW50ICYmIHByb2plY3Rpb24uY2xpcEV4dGVudCgpO1xuXG4gICAgICAgIHByb2plY3Rpb25cbiAgICAgICAgICAgIC5zY2FsZSgxNTApXG4gICAgICAgICAgICAudHJhbnNsYXRlKFswLCAwXSk7XG5cbiAgICAgICAgaWYoY2xpcCkgcHJvamVjdGlvbi5jbGlwRXh0ZW50KG51bGwpO1xuXG4gICAgICAgIHZhciBiID0gcHJvamVjdGlvbi5nZXRCb3VuZHMob2JqZWN0KTtcbiAgICAgICAgdmFyIGsgPSBNYXRoLm1pbih3IC8gKGJbMV1bMF0gLSBiWzBdWzBdKSwgaCAvIChiWzFdWzFdIC0gYlswXVsxXSkpO1xuICAgICAgICB2YXIgeCA9ICtleHRlbnRbMF1bMF0gKyAodyAtIGsgKiAoYlsxXVswXSArIGJbMF1bMF0pKSAvIDI7XG4gICAgICAgIHZhciB5ID0gK2V4dGVudFswXVsxXSArIChoIC0gayAqIChiWzFdWzFdICsgYlswXVsxXSkpIC8gMjtcblxuICAgICAgICBpZihjbGlwKSBwcm9qZWN0aW9uLmNsaXBFeHRlbnQoY2xpcCk7XG5cbiAgICAgICAgcmV0dXJuIHByb2plY3Rpb25cbiAgICAgICAgICAgIC5zY2FsZShrICogMTUwKVxuICAgICAgICAgICAgLnRyYW5zbGF0ZShbeCwgeV0pO1xuICAgIH07XG5cbiAgICBwcm9qZWN0aW9uLnByZWNpc2lvbihjb25zdGFudHMucHJlY2lzaW9uKTtcblxuICAgIGlmKGNsaXBBbmdsZSkge1xuICAgICAgICBwcm9qZWN0aW9uLmNsaXBBbmdsZShjbGlwQW5nbGUgLSBjb25zdGFudHMuY2xpcFBhZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2plY3Rpb247XG59XG5cbmZ1bmN0aW9uIG1ha2VHcmF0aWN1bGUoYXhpc05hbWUsIGdlb0xheW91dCkge1xuICAgIHZhciBheGlzTGF5b3V0ID0gZ2VvTGF5b3V0W2F4aXNOYW1lXTtcbiAgICB2YXIgZHRpY2sgPSBheGlzTGF5b3V0LmR0aWNrO1xuICAgIHZhciBzY29wZURlZmF1bHRzID0gY29uc3RhbnRzLnNjb3BlRGVmYXVsdHNbZ2VvTGF5b3V0LnNjb3BlXTtcbiAgICB2YXIgbG9uYXhpc1JhbmdlID0gc2NvcGVEZWZhdWx0cy5sb25heGlzUmFuZ2U7XG4gICAgdmFyIGxhdGF4aXNSYW5nZSA9IHNjb3BlRGVmYXVsdHMubGF0YXhpc1JhbmdlO1xuICAgIHZhciBzdGVwID0gYXhpc05hbWUgPT09ICdsb25heGlzJyA/IFtkdGlja10gOiBbMCwgZHRpY2tdO1xuXG4gICAgcmV0dXJuIGQzLmdlby5ncmF0aWN1bGUoKVxuICAgICAgICAuZXh0ZW50KFtcbiAgICAgICAgICAgIFtsb25heGlzUmFuZ2VbMF0sIGxhdGF4aXNSYW5nZVswXV0sXG4gICAgICAgICAgICBbbG9uYXhpc1JhbmdlWzFdLCBsYXRheGlzUmFuZ2VbMV1dXG4gICAgICAgIF0pXG4gICAgICAgIC5zdGVwKHN0ZXApO1xufVxuXG4vLyBSZXR1cm5zIHBvbHlnb24gR2VvSlNPTiBjb3JyZXNwb25kaW5nIHRvIGxvbi9sYXQgcmFuZ2UgYm94XG4vLyB3aXRoIHdlbGwtZGVmaW5lZCBkaXJlY3Rpb25cbi8vXG4vLyBOb3RlIHRoYXQgY2xpcFBhZCBwYWRkaW5nIGlzIGFkZGVkIGFyb3VuZCByYW5nZSB0byBhdm9pZCBhbGlhc2luZy5cbmZ1bmN0aW9uIG1ha2VSYW5nZUJveChsb24sIGxhdCkge1xuICAgIHZhciBjbGlwUGFkID0gY29uc3RhbnRzLmNsaXBQYWQ7XG4gICAgdmFyIGxvbjAgPSBsb25bMF0gKyBjbGlwUGFkO1xuICAgIHZhciBsb24xID0gbG9uWzFdIC0gY2xpcFBhZDtcbiAgICB2YXIgbGF0MCA9IGxhdFswXSArIGNsaXBQYWQ7XG4gICAgdmFyIGxhdDEgPSBsYXRbMV0gLSBjbGlwUGFkO1xuXG4gICAgLy8gdG8gY3Jvc3MgYW50aW1lcmlkaWFuIHcvbyBhbWJpZ3VpdHlcbiAgICBpZihsb24wID4gMCAmJiBsb24xIDwgMCkgbG9uMSArPSAzNjA7XG5cbiAgICB2YXIgZGxvbjQgPSAobG9uMSAtIGxvbjApIC8gNDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6ICdQb2x5Z29uJyxcbiAgICAgICAgY29vcmRpbmF0ZXM6IFtbXG4gICAgICAgICAgICBbbG9uMCwgbGF0MF0sXG4gICAgICAgICAgICBbbG9uMCwgbGF0MV0sXG4gICAgICAgICAgICBbbG9uMCArIGRsb240LCBsYXQxXSxcbiAgICAgICAgICAgIFtsb24wICsgMiAqIGRsb240LCBsYXQxXSxcbiAgICAgICAgICAgIFtsb24wICsgMyAqIGRsb240LCBsYXQxXSxcbiAgICAgICAgICAgIFtsb24xLCBsYXQxXSxcbiAgICAgICAgICAgIFtsb24xLCBsYXQwXSxcbiAgICAgICAgICAgIFtsb24xIC0gZGxvbjQsIGxhdDBdLFxuICAgICAgICAgICAgW2xvbjEgLSAyICogZGxvbjQsIGxhdDBdLFxuICAgICAgICAgICAgW2xvbjEgLSAzICogZGxvbjQsIGxhdDBdLFxuICAgICAgICAgICAgW2xvbjAsIGxhdDBdXG4gICAgICAgIF1dXG4gICAgfTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlR2VvID0gcmVxdWlyZSgnLi9nZW8nKTtcbnZhciBnZXRTdWJwbG90Q2FsY0RhdGEgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldFN1YnBsb3RDYWxjRGF0YTtcbnZhciBjb3VudGVyUmVnZXggPSByZXF1aXJlKCcuLi8uLi9saWInKS5jb3VudGVyUmVnZXg7XG5cbnZhciBHRU8gPSAnZ2VvJztcblxuZXhwb3J0cy5uYW1lID0gR0VPO1xuXG5leHBvcnRzLmF0dHIgPSBHRU87XG5cbmV4cG9ydHMuaWRSb290ID0gR0VPO1xuXG5leHBvcnRzLmlkUmVnZXggPSBleHBvcnRzLmF0dHJSZWdleCA9IGNvdW50ZXJSZWdleChHRU8pO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2xheW91dC9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMubGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0L2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSByZXF1aXJlKCcuL2xheW91dC9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbiBwbG90R2VvKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY0RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgZ2VvSWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbR0VPXTtcblxuICAgIC8qKlxuICAgICAqIElmICdwbG90bHktZ2VvLWFzc2V0cy5qcycgaXMgbm90IGluY2x1ZGVkLFxuICAgICAqIGluaXRpYWxpemUgb2JqZWN0IHRvIGtlZXAgcmVmZXJlbmNlIHRvIGV2ZXJ5IGxvYWRlZCB0b3BvanNvblxuICAgICAqL1xuICAgIGlmKHdpbmRvdy5QbG90bHlHZW9Bc3NldHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB3aW5kb3cuUGxvdGx5R2VvQXNzZXRzID0ge3RvcG9qc29uOiB7fX07XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdlb0lkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ2VvSWQgPSBnZW9JZHNbaV07XG4gICAgICAgIHZhciBnZW9DYWxjRGF0YSA9IGdldFN1YnBsb3RDYWxjRGF0YShjYWxjRGF0YSwgR0VPLCBnZW9JZCk7XG4gICAgICAgIHZhciBnZW9MYXlvdXQgPSBmdWxsTGF5b3V0W2dlb0lkXTtcbiAgICAgICAgdmFyIGdlbyA9IGdlb0xheW91dC5fc3VicGxvdDtcblxuICAgICAgICBpZighZ2VvKSB7XG4gICAgICAgICAgICBnZW8gPSBjcmVhdGVHZW8oe1xuICAgICAgICAgICAgICAgIGlkOiBnZW9JZCxcbiAgICAgICAgICAgICAgICBncmFwaERpdjogZ2QsXG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll9nZW9sYXllci5ub2RlKCksXG4gICAgICAgICAgICAgICAgdG9wb2pzb25VUkw6IGdkLl9jb250ZXh0LnRvcG9qc29uVVJMLFxuICAgICAgICAgICAgICAgIHN0YXRpY1Bsb3Q6IGdkLl9jb250ZXh0LnN0YXRpY1Bsb3RcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBmdWxsTGF5b3V0W2dlb0lkXS5fc3VicGxvdCA9IGdlbztcbiAgICAgICAgfVxuXG4gICAgICAgIGdlby5wbG90KGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0LCBnZC5fcHJvbWlzZXMpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkR2VvS2V5cyA9IG9sZEZ1bGxMYXlvdXQuX3N1YnBsb3RzW0dFT10gfHwgW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkR2VvS2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb2xkR2VvS2V5ID0gb2xkR2VvS2V5c1tpXTtcbiAgICAgICAgdmFyIG9sZEdlbyA9IG9sZEZ1bGxMYXlvdXRbb2xkR2VvS2V5XS5fc3VicGxvdDtcblxuICAgICAgICBpZighbmV3RnVsbExheW91dFtvbGRHZW9LZXldICYmICEhb2xkR2VvKSB7XG4gICAgICAgICAgICBvbGRHZW8uZnJhbWV3b3JrLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkR2VvLmNsaXBEZWYucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5leHBvcnRzLnVwZGF0ZUZ4ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbR0VPXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzdWJwbG90SWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzdWJwbG90TGF5b3V0ID0gZnVsbExheW91dFtzdWJwbG90SWRzW2ldXTtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBzdWJwbG90TGF5b3V0Ll9zdWJwbG90O1xuICAgICAgICBzdWJwbG90T2JqLnVwZGF0ZUZ4KGZ1bGxMYXlvdXQsIHN1YnBsb3RMYXlvdXQpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZ2VvOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ2dlbycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhhbmRsZVN1YnBsb3REZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL3N1YnBsb3RfZGVmYXVsdHMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuLi9jb25zdGFudHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgYXhlc05hbWVzID0gY29uc3RhbnRzLmF4ZXNOYW1lcztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGhhbmRsZVN1YnBsb3REZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSwge1xuICAgICAgICB0eXBlOiAnZ2VvJyxcbiAgICAgICAgYXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlcyxcbiAgICAgICAgaGFuZGxlRGVmYXVsdHM6IGhhbmRsZUdlb0RlZmF1bHRzLFxuICAgICAgICBwYXJ0aXRpb246ICd5J1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlR2VvRGVmYXVsdHMoZ2VvTGF5b3V0SW4sIGdlb0xheW91dE91dCwgY29lcmNlKSB7XG4gICAgdmFyIHNob3c7XG5cbiAgICB2YXIgcmVzb2x1dGlvbiA9IGNvZXJjZSgncmVzb2x1dGlvbicpO1xuICAgIHZhciBzY29wZSA9IGNvZXJjZSgnc2NvcGUnKTtcbiAgICB2YXIgc2NvcGVQYXJhbXMgPSBjb25zdGFudHMuc2NvcGVEZWZhdWx0c1tzY29wZV07XG5cbiAgICB2YXIgcHJvalR5cGUgPSBjb2VyY2UoJ3Byb2plY3Rpb24udHlwZScsIHNjb3BlUGFyYW1zLnByb2pUeXBlKTtcbiAgICB2YXIgaXNBbGJlcnNVc2EgPSBnZW9MYXlvdXRPdXQuX2lzQWxiZXJzVXNhID0gcHJvalR5cGUgPT09ICdhbGJlcnMgdXNhJztcblxuICAgIC8vIG5vIG90aGVyIHNjb3BlcyBhcmUgYWxsb3dlZCBmb3IgJ2FsYmVycyB1c2EnIHByb2plY3Rpb25cbiAgICBpZihpc0FsYmVyc1VzYSkgc2NvcGUgPSBnZW9MYXlvdXRPdXQuc2NvcGUgPSAndXNhJztcblxuICAgIHZhciBpc1Njb3BlZCA9IGdlb0xheW91dE91dC5faXNTY29wZWQgPSAoc2NvcGUgIT09ICd3b3JsZCcpO1xuICAgIHZhciBpc0NvbmljID0gZ2VvTGF5b3V0T3V0Ll9pc0NvbmljID0gcHJvalR5cGUuaW5kZXhPZignY29uaWMnKSAhPT0gLTE7XG4gICAgZ2VvTGF5b3V0T3V0Ll9pc0NsaXBwZWQgPSAhIWNvbnN0YW50cy5sb25heGlzU3Bhbltwcm9qVHlwZV07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhlc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheGlzTmFtZSA9IGF4ZXNOYW1lc1tpXTtcbiAgICAgICAgdmFyIGR0aWNrRGZsdCA9IFszMCwgMTBdW2ldO1xuICAgICAgICB2YXIgcmFuZ2VEZmx0O1xuXG4gICAgICAgIGlmKGlzU2NvcGVkKSB7XG4gICAgICAgICAgICByYW5nZURmbHQgPSBzY29wZVBhcmFtc1theGlzTmFtZSArICdSYW5nZSddO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGRmbHRTcGFucyA9IGNvbnN0YW50c1theGlzTmFtZSArICdTcGFuJ107XG4gICAgICAgICAgICB2YXIgaFNwYW4gPSAoZGZsdFNwYW5zW3Byb2pUeXBlXSB8fCBkZmx0U3BhbnNbJyonXSkgLyAyO1xuICAgICAgICAgICAgdmFyIHJvdCA9IGNvZXJjZShcbiAgICAgICAgICAgICAgICAncHJvamVjdGlvbi5yb3RhdGlvbi4nICsgYXhpc05hbWUuc3Vic3RyKDAsIDMpLFxuICAgICAgICAgICAgICAgIHNjb3BlUGFyYW1zLnByb2pSb3RhdGVbaV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByYW5nZURmbHQgPSBbcm90IC0gaFNwYW4sIHJvdCArIGhTcGFuXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByYW5nZSA9IGNvZXJjZShheGlzTmFtZSArICcucmFuZ2UnLCByYW5nZURmbHQpO1xuXG4gICAgICAgIGNvZXJjZShheGlzTmFtZSArICcudGljazAnLCByYW5nZVswXSk7XG4gICAgICAgIGNvZXJjZShheGlzTmFtZSArICcuZHRpY2snLCBkdGlja0RmbHQpO1xuXG4gICAgICAgIHNob3cgPSBjb2VyY2UoYXhpc05hbWUgKyAnLnNob3dncmlkJyk7XG4gICAgICAgIGlmKHNob3cpIHtcbiAgICAgICAgICAgIGNvZXJjZShheGlzTmFtZSArICcuZ3JpZGNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoYXhpc05hbWUgKyAnLmdyaWR3aWR0aCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGxvblJhbmdlID0gZ2VvTGF5b3V0T3V0LmxvbmF4aXMucmFuZ2U7XG4gICAgdmFyIGxhdFJhbmdlID0gZ2VvTGF5b3V0T3V0LmxhdGF4aXMucmFuZ2U7XG5cbiAgICAvLyB0byBjcm9zcyBhbnRpbWVyaWRpYW4gdy9vIGFtYmlndWl0eVxuICAgIHZhciBsb24wID0gbG9uUmFuZ2VbMF07XG4gICAgdmFyIGxvbjEgPSBsb25SYW5nZVsxXTtcbiAgICBpZihsb24wID4gMCAmJiBsb24xIDwgMCkgbG9uMSArPSAzNjA7XG5cbiAgICB2YXIgY2VudGVyTG9uID0gKGxvbjAgKyBsb24xKSAvIDI7XG4gICAgdmFyIHByb2pMb247XG5cbiAgICBpZighaXNBbGJlcnNVc2EpIHtcbiAgICAgICAgdmFyIGRmbHRQcm9qUm90YXRlID0gaXNTY29wZWQgPyBzY29wZVBhcmFtcy5wcm9qUm90YXRlIDogW2NlbnRlckxvbiwgMCwgMF07XG5cbiAgICAgICAgcHJvakxvbiA9IGNvZXJjZSgncHJvamVjdGlvbi5yb3RhdGlvbi5sb24nLCBkZmx0UHJvalJvdGF0ZVswXSk7XG4gICAgICAgIGNvZXJjZSgncHJvamVjdGlvbi5yb3RhdGlvbi5sYXQnLCBkZmx0UHJvalJvdGF0ZVsxXSk7XG4gICAgICAgIGNvZXJjZSgncHJvamVjdGlvbi5yb3RhdGlvbi5yb2xsJywgZGZsdFByb2pSb3RhdGVbMl0pO1xuXG4gICAgICAgIHNob3cgPSBjb2VyY2UoJ3Nob3djb2FzdGxpbmVzJywgIWlzU2NvcGVkKTtcbiAgICAgICAgaWYoc2hvdykge1xuICAgICAgICAgICAgY29lcmNlKCdjb2FzdGxpbmVjb2xvcicpO1xuICAgICAgICAgICAgY29lcmNlKCdjb2FzdGxpbmV3aWR0aCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2hvdyA9IGNvZXJjZSgnc2hvd29jZWFuJyk7XG4gICAgICAgIGlmKHNob3cpIGNvZXJjZSgnb2NlYW5jb2xvcicpO1xuICAgIH1cblxuICAgIHZhciBjZW50ZXJMb25EZmx0O1xuICAgIHZhciBjZW50ZXJMYXREZmx0O1xuXG4gICAgaWYoaXNBbGJlcnNVc2EpIHtcbiAgICAgICAgLy8gJ2FsYmVycyB1c2EnIGRvZXMgbm90IGhhdmUgYSAnY2VudGVyJyxcbiAgICAgICAgLy8gdGhlc2UgdmFsdWVzIHdlcmUgZm91bmQgdXNpbmcgdmlhOlxuICAgICAgICAvLyAgIHByb2plY3Rpb24uaW52ZXJ0KFtnZW9MYXlvdXQuY2VudGVyLmxvbiwgZ2VvTGF5b3V0SW4uY2VudGVyLmxhdF0pXG4gICAgICAgIGNlbnRlckxvbkRmbHQgPSAtOTYuNjtcbiAgICAgICAgY2VudGVyTGF0RGZsdCA9IDM4Ljc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2VudGVyTG9uRGZsdCA9IGlzU2NvcGVkID8gY2VudGVyTG9uIDogcHJvakxvbjtcbiAgICAgICAgY2VudGVyTGF0RGZsdCA9IChsYXRSYW5nZVswXSArIGxhdFJhbmdlWzFdKSAvIDI7XG4gICAgfVxuXG4gICAgY29lcmNlKCdjZW50ZXIubG9uJywgY2VudGVyTG9uRGZsdCk7XG4gICAgY29lcmNlKCdjZW50ZXIubGF0JywgY2VudGVyTGF0RGZsdCk7XG5cbiAgICBpZihpc0NvbmljKSB7XG4gICAgICAgIHZhciBkZmx0UHJvalBhcmFsbGVscyA9IHNjb3BlUGFyYW1zLnByb2pQYXJhbGxlbHMgfHwgWzAsIDYwXTtcbiAgICAgICAgY29lcmNlKCdwcm9qZWN0aW9uLnBhcmFsbGVscycsIGRmbHRQcm9qUGFyYWxsZWxzKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3Byb2plY3Rpb24uc2NhbGUnKTtcblxuICAgIHNob3cgPSBjb2VyY2UoJ3Nob3dsYW5kJyk7XG4gICAgaWYoc2hvdykgY29lcmNlKCdsYW5kY29sb3InKTtcblxuICAgIHNob3cgPSBjb2VyY2UoJ3Nob3dsYWtlcycpO1xuICAgIGlmKHNob3cpIGNvZXJjZSgnbGFrZWNvbG9yJyk7XG5cbiAgICBzaG93ID0gY29lcmNlKCdzaG93cml2ZXJzJyk7XG4gICAgaWYoc2hvdykge1xuICAgICAgICBjb2VyY2UoJ3JpdmVyY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdyaXZlcndpZHRoJyk7XG4gICAgfVxuXG4gICAgc2hvdyA9IGNvZXJjZSgnc2hvd2NvdW50cmllcycsIGlzU2NvcGVkICYmIHNjb3BlICE9PSAndXNhJyk7XG4gICAgaWYoc2hvdykge1xuICAgICAgICBjb2VyY2UoJ2NvdW50cnljb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ2NvdW50cnl3aWR0aCcpO1xuICAgIH1cblxuICAgIGlmKHNjb3BlID09PSAndXNhJyB8fCAoc2NvcGUgPT09ICdub3J0aCBhbWVyaWNhJyAmJiByZXNvbHV0aW9uID09PSA1MCkpIHtcbiAgICAgICAgLy8gT25seSB3b3JrcyBmb3I6XG4gICAgICAgIC8vICAgVVNBIHN0YXRlcyBhdCAxMTBtXG4gICAgICAgIC8vICAgVVNBIHN0YXRlcyArIENhbmFkYSBwcm92aW5jZXMgYXQgNTBtXG4gICAgICAgIGNvZXJjZSgnc2hvd3N1YnVuaXRzJywgdHJ1ZSk7XG4gICAgICAgIGNvZXJjZSgnc3VidW5pdGNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgnc3VidW5pdHdpZHRoJyk7XG4gICAgfVxuXG4gICAgaWYoIWlzU2NvcGVkKSB7XG4gICAgICAgIC8vIERvZXMgbm90IHdvcmsgaW4gbm9uLXdvcmxkIHNjb3Blc1xuICAgICAgICBzaG93ID0gY29lcmNlKCdzaG93ZnJhbWUnLCB0cnVlKTtcbiAgICAgICAgaWYoc2hvdykge1xuICAgICAgICAgICAgY29lcmNlKCdmcmFtZWNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ2ZyYW1ld2lkdGgnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvZXJjZSgnYmdjb2xvcicpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vLi4vZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuLi9jb25zdGFudHMnKTtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIGdlb0F4ZXNBdHRycyA9IHtcbiAgICByYW5nZToge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInfSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJ31cbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93Z3JpZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrMDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZHRpY2s6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyaWRjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5saWdodExpbmUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICBkb21haW46IGRvbWFpbkF0dHJzKHtuYW1lOiAnZ2VvJ30sIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICByZXNvbHV0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbMTEwLCA1MF0sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAxMTAsXG4gICAgICAgIGNvZXJjZU51bWJlcjogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzY29wZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IE9iamVjdC5rZXlzKGNvbnN0YW50cy5zY29wZURlZmF1bHRzKSxcbiAgICAgICAgZGZsdDogJ3dvcmxkJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBwcm9qZWN0aW9uOiB7XG4gICAgICAgIHR5cGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgdmFsdWVzOiBPYmplY3Qua2V5cyhjb25zdGFudHMucHJvak5hbWVzKSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICByb3RhdGlvbjoge1xuICAgICAgICAgICAgbG9uOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGF0OiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcm9sbDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBwYXJhbGxlbHM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcid9LFxuICAgICAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJ31cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2NhbGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgfSxcbiAgICBjZW50ZXI6IHtcbiAgICAgICAgbG9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxhdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcbiAgICBzaG93Y29hc3RsaW5lczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvYXN0bGluZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvYXN0bGluZXdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dsYW5kOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhbmRjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLmxhbmRDb2xvcixcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93b2NlYW46IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgb2NlYW5jb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLndhdGVyQ29sb3IsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2xha2VzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxha2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLndhdGVyQ29sb3IsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd3JpdmVyczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICByaXZlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMud2F0ZXJDb2xvcixcbiAgICAgICAgXG4gICAgfSxcbiAgICByaXZlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3djb3VudHJpZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb3VudHJ5Y29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY291bnRyeXdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dzdWJ1bml0czoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1YnVuaXRjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdWJ1bml0d2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2ZyYW1lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZnJhbWVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmcmFtZXdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuYmFja2dyb3VuZCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsb25heGlzOiBnZW9BeGVzQXR0cnMsXG4gICAgbGF0YXhpczogZ2VvQXhlc0F0dHJzXG59LCAncGxvdCcsICdmcm9tLXJvb3QnKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbi8qXG4gKiBHZW5lcmF0ZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2V0cGluYXJkL2QzLWdlby1wcm9qZWN0aW9uLXBpY2tlclxuICpcbiAqIHdoaWNoIGlzIGhhbmQtcGlja3MgcHJvamVjdGlvbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy1nZW8tcHJvamVjdGlvblxuICpcbiAqIGludG8gYSBDb21tb25KUyByZXF1aXJlLWFibGUgbW9kdWxlLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuLyogZXNsaW50LWRpc2FibGUgKi9cblxuZnVuY3Rpb24gYWRkUHJvamVjdGlvbnNUb0QzKGQzKSB7XG4gIGQzLmdlby5wcm9qZWN0ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHN0cmVhbSA9IHByb2plY3Rpb24uc3RyZWFtO1xuICAgIGlmICghc3RyZWFtKSB0aHJvdyBuZXcgRXJyb3IoXCJub3QgeWV0IHN1cHBvcnRlZFwiKTtcbiAgICByZXR1cm4gKG9iamVjdCAmJiBkM19nZW9fcHJvamVjdE9iamVjdFR5cGUuaGFzT3duUHJvcGVydHkob2JqZWN0LnR5cGUpID8gZDNfZ2VvX3Byb2plY3RPYmplY3RUeXBlW29iamVjdC50eXBlXSA6IGQzX2dlb19wcm9qZWN0R2VvbWV0cnkpKG9iamVjdCwgc3RyZWFtKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3RGZWF0dXJlKG9iamVjdCwgc3RyZWFtKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgaWQ6IG9iamVjdC5pZCxcbiAgICAgIHByb3BlcnRpZXM6IG9iamVjdC5wcm9wZXJ0aWVzLFxuICAgICAgZ2VvbWV0cnk6IGQzX2dlb19wcm9qZWN0R2VvbWV0cnkob2JqZWN0Lmdlb21ldHJ5LCBzdHJlYW0pXG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdEdlb21ldHJ5KGdlb21ldHJ5LCBzdHJlYW0pIHtcbiAgICBpZiAoIWdlb21ldHJ5KSByZXR1cm4gbnVsbDtcbiAgICBpZiAoZ2VvbWV0cnkudHlwZSA9PT0gXCJHZW9tZXRyeUNvbGxlY3Rpb25cIikgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFwiR2VvbWV0cnlDb2xsZWN0aW9uXCIsXG4gICAgICBnZW9tZXRyaWVzOiBvYmplY3QuZ2VvbWV0cmllcy5tYXAoZnVuY3Rpb24oZ2VvbWV0cnkpIHtcbiAgICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0R2VvbWV0cnkoZ2VvbWV0cnksIHN0cmVhbSk7XG4gICAgICB9KVxuICAgIH07XG4gICAgaWYgKCFkM19nZW9fcHJvamVjdEdlb21ldHJ5VHlwZS5oYXNPd25Qcm9wZXJ0eShnZW9tZXRyeS50eXBlKSkgcmV0dXJuIG51bGw7XG4gICAgdmFyIHNpbmsgPSBkM19nZW9fcHJvamVjdEdlb21ldHJ5VHlwZVtnZW9tZXRyeS50eXBlXTtcbiAgICBkMy5nZW8uc3RyZWFtKGdlb21ldHJ5LCBzdHJlYW0oc2luaykpO1xuICAgIHJldHVybiBzaW5rLnJlc3VsdCgpO1xuICB9XG4gIHZhciBkM19nZW9fcHJvamVjdE9iamVjdFR5cGUgPSB7XG4gICAgRmVhdHVyZTogZDNfZ2VvX3Byb2plY3RGZWF0dXJlLFxuICAgIEZlYXR1cmVDb2xsZWN0aW9uOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICAgICAgICBmZWF0dXJlczogb2JqZWN0LmZlYXR1cmVzLm1hcChmdW5jdGlvbihmZWF0dXJlKSB7XG4gICAgICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0RmVhdHVyZShmZWF0dXJlLCBzdHJlYW0pO1xuICAgICAgICB9KVxuICAgICAgfTtcbiAgICB9XG4gIH07XG4gIHZhciBkM19nZW9fcHJvamVjdFBvaW50cyA9IFtdLCBkM19nZW9fcHJvamVjdExpbmVzID0gW107XG4gIHZhciBkM19nZW9fcHJvamVjdFBvaW50ID0ge1xuICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBkM19nZW9fcHJvamVjdFBvaW50cy5wdXNoKFsgeCwgeSBdKTtcbiAgICB9LFxuICAgIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gIWQzX2dlb19wcm9qZWN0UG9pbnRzLmxlbmd0aCA/IG51bGwgOiBkM19nZW9fcHJvamVjdFBvaW50cy5sZW5ndGggPCAyID8ge1xuICAgICAgICB0eXBlOiBcIlBvaW50XCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdFBvaW50c1swXVxuICAgICAgfSA6IHtcbiAgICAgICAgdHlwZTogXCJNdWx0aVBvaW50XCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdFBvaW50c1xuICAgICAgfTtcbiAgICAgIGQzX2dlb19wcm9qZWN0UG9pbnRzID0gW107XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfTtcbiAgdmFyIGQzX2dlb19wcm9qZWN0TGluZSA9IHtcbiAgICBsaW5lU3RhcnQ6IGQzX2dlb19wcm9qZWN0Tm9vcCxcbiAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgZDNfZ2VvX3Byb2plY3RQb2ludHMucHVzaChbIHgsIHkgXSk7XG4gICAgfSxcbiAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChkM19nZW9fcHJvamVjdFBvaW50cy5sZW5ndGgpIGQzX2dlb19wcm9qZWN0TGluZXMucHVzaChkM19nZW9fcHJvamVjdFBvaW50cyksIFxuICAgICAgZDNfZ2VvX3Byb2plY3RQb2ludHMgPSBbXTtcbiAgICB9LFxuICAgIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gIWQzX2dlb19wcm9qZWN0TGluZXMubGVuZ3RoID8gbnVsbCA6IGQzX2dlb19wcm9qZWN0TGluZXMubGVuZ3RoIDwgMiA/IHtcbiAgICAgICAgdHlwZTogXCJMaW5lU3RyaW5nXCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdExpbmVzWzBdXG4gICAgICB9IDoge1xuICAgICAgICB0eXBlOiBcIk11bHRpTGluZVN0cmluZ1wiLFxuICAgICAgICBjb29yZGluYXRlczogZDNfZ2VvX3Byb2plY3RMaW5lc1xuICAgICAgfTtcbiAgICAgIGQzX2dlb19wcm9qZWN0TGluZXMgPSBbXTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9O1xuICB2YXIgZDNfZ2VvX3Byb2plY3RQb2x5Z29uID0ge1xuICAgIHBvbHlnb25TdGFydDogZDNfZ2VvX3Byb2plY3ROb29wLFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX3Byb2plY3ROb29wLFxuICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBkM19nZW9fcHJvamVjdFBvaW50cy5wdXNoKFsgeCwgeSBdKTtcbiAgICB9LFxuICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG4gPSBkM19nZW9fcHJvamVjdFBvaW50cy5sZW5ndGg7XG4gICAgICBpZiAobikge1xuICAgICAgICBkbyBkM19nZW9fcHJvamVjdFBvaW50cy5wdXNoKGQzX2dlb19wcm9qZWN0UG9pbnRzWzBdLnNsaWNlKCkpOyB3aGlsZSAoKytuIDwgNCk7XG4gICAgICAgIGQzX2dlb19wcm9qZWN0TGluZXMucHVzaChkM19nZW9fcHJvamVjdFBvaW50cyksIGQzX2dlb19wcm9qZWN0UG9pbnRzID0gW107XG4gICAgICB9XG4gICAgfSxcbiAgICBwb2x5Z29uRW5kOiBkM19nZW9fcHJvamVjdE5vb3AsXG4gICAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghZDNfZ2VvX3Byb2plY3RMaW5lcy5sZW5ndGgpIHJldHVybiBudWxsO1xuICAgICAgdmFyIHBvbHlnb25zID0gW10sIGhvbGVzID0gW107XG4gICAgICBkM19nZW9fcHJvamVjdExpbmVzLmZvckVhY2goZnVuY3Rpb24ocmluZykge1xuICAgICAgICBpZiAoZDNfZ2VvX3Byb2plY3RDbG9ja3dpc2UocmluZykpIHBvbHlnb25zLnB1c2goWyByaW5nIF0pOyBlbHNlIGhvbGVzLnB1c2gocmluZyk7XG4gICAgICB9KTtcbiAgICAgIGhvbGVzLmZvckVhY2goZnVuY3Rpb24oaG9sZSkge1xuICAgICAgICB2YXIgcG9pbnQgPSBob2xlWzBdO1xuICAgICAgICBwb2x5Z29ucy5zb21lKGZ1bmN0aW9uKHBvbHlnb24pIHtcbiAgICAgICAgICBpZiAoZDNfZ2VvX3Byb2plY3RDb250YWlucyhwb2x5Z29uWzBdLCBwb2ludCkpIHtcbiAgICAgICAgICAgIHBvbHlnb24ucHVzaChob2xlKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkgfHwgcG9seWdvbnMucHVzaChbIGhvbGUgXSk7XG4gICAgICB9KTtcbiAgICAgIGQzX2dlb19wcm9qZWN0TGluZXMgPSBbXTtcbiAgICAgIHJldHVybiAhcG9seWdvbnMubGVuZ3RoID8gbnVsbCA6IHBvbHlnb25zLmxlbmd0aCA+IDEgPyB7XG4gICAgICAgIHR5cGU6IFwiTXVsdGlQb2x5Z29uXCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBwb2x5Z29uc1xuICAgICAgfSA6IHtcbiAgICAgICAgdHlwZTogXCJQb2x5Z29uXCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBwb2x5Z29uc1swXVxuICAgICAgfTtcbiAgICB9XG4gIH07XG4gIHZhciBkM19nZW9fcHJvamVjdEdlb21ldHJ5VHlwZSA9IHtcbiAgICBQb2ludDogZDNfZ2VvX3Byb2plY3RQb2ludCxcbiAgICBNdWx0aVBvaW50OiBkM19nZW9fcHJvamVjdFBvaW50LFxuICAgIExpbmVTdHJpbmc6IGQzX2dlb19wcm9qZWN0TGluZSxcbiAgICBNdWx0aUxpbmVTdHJpbmc6IGQzX2dlb19wcm9qZWN0TGluZSxcbiAgICBQb2x5Z29uOiBkM19nZW9fcHJvamVjdFBvbHlnb24sXG4gICAgTXVsdGlQb2x5Z29uOiBkM19nZW9fcHJvamVjdFBvbHlnb24sXG4gICAgU3BoZXJlOiBkM19nZW9fcHJvamVjdFBvbHlnb25cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3ROb29wKCkge31cbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3RDbG9ja3dpc2UocmluZykge1xuICAgIGlmICgobiA9IHJpbmcubGVuZ3RoKSA8IDQpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgaSA9IDAsIG4sIGFyZWEgPSByaW5nW24gLSAxXVsxXSAqIHJpbmdbMF1bMF0gLSByaW5nW24gLSAxXVswXSAqIHJpbmdbMF1bMV07XG4gICAgd2hpbGUgKCsraSA8IG4pIGFyZWEgKz0gcmluZ1tpIC0gMV1bMV0gKiByaW5nW2ldWzBdIC0gcmluZ1tpIC0gMV1bMF0gKiByaW5nW2ldWzFdO1xuICAgIHJldHVybiBhcmVhIDw9IDA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3RDb250YWlucyhyaW5nLCBwb2ludCkge1xuICAgIHZhciB4ID0gcG9pbnRbMF0sIHkgPSBwb2ludFsxXSwgY29udGFpbnMgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IHJpbmcubGVuZ3RoLCBqID0gbiAtIDE7IGkgPCBuOyBqID0gaSsrKSB7XG4gICAgICB2YXIgcGkgPSByaW5nW2ldLCB4aSA9IHBpWzBdLCB5aSA9IHBpWzFdLCBwaiA9IHJpbmdbal0sIHhqID0gcGpbMF0sIHlqID0gcGpbMV07XG4gICAgICBpZiAoeWkgPiB5IF4geWogPiB5ICYmIHggPCAoeGogLSB4aSkgKiAoeSAtIHlpKSAvICh5aiAtIHlpKSArIHhpKSBjb250YWlucyA9ICFjb250YWlucztcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRhaW5zO1xuICB9XG4gIHZhciDOtSA9IDFlLTYsIM61MiA9IM61ICogzrUsIM+AID0gTWF0aC5QSSwgaGFsZs+AID0gz4AgLyAyLCBzcXJ0z4AgPSBNYXRoLnNxcnQoz4ApLCByYWRpYW5zID0gz4AgLyAxODAsIGRlZ3JlZXMgPSAxODAgLyDPgDtcbiAgZnVuY3Rpb24gc2luY2koeCkge1xuICAgIHJldHVybiB4ID8geCAvIE1hdGguc2luKHgpIDogMTtcbiAgfVxuICBmdW5jdGlvbiBzZ24oeCkge1xuICAgIHJldHVybiB4ID4gMCA/IDEgOiB4IDwgMCA/IC0xIDogMDtcbiAgfVxuICBmdW5jdGlvbiBhc2luKHgpIHtcbiAgICByZXR1cm4geCA+IDEgPyBoYWxmz4AgOiB4IDwgLTEgPyAtaGFsZs+AIDogTWF0aC5hc2luKHgpO1xuICB9XG4gIGZ1bmN0aW9uIGFjb3MoeCkge1xuICAgIHJldHVybiB4ID4gMSA/IDAgOiB4IDwgLTEgPyDPgCA6IE1hdGguYWNvcyh4KTtcbiAgfVxuICBmdW5jdGlvbiBhc3FydCh4KSB7XG4gICAgcmV0dXJuIHggPiAwID8gTWF0aC5zcXJ0KHgpIDogMDtcbiAgfVxuICB2YXIgcHJvamVjdGlvbiA9IGQzLmdlby5wcm9qZWN0aW9uLCBwcm9qZWN0aW9uTXV0YXRvciA9IGQzLmdlby5wcm9qZWN0aW9uTXV0YXRvcjtcbiAgZDMuZ2VvLmludGVycnVwdCA9IGZ1bmN0aW9uKHByb2plY3QpIHtcbiAgICB2YXIgbG9iZXMgPSBbIFsgWyBbIC3PgCwgMCBdLCBbIDAsIGhhbGbPgCBdLCBbIM+ALCAwIF0gXSBdLCBbIFsgWyAtz4AsIDAgXSwgWyAwLCAtaGFsZs+AIF0sIFsgz4AsIDAgXSBdIF0gXTtcbiAgICB2YXIgYm91bmRzO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICB2YXIgc2lnbiA9IM+GIDwgMCA/IC0xIDogKzEsIGhlbWlsb2JlcyA9IGxvYmVzWysoz4YgPCAwKV07XG4gICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGhlbWlsb2Jlcy5sZW5ndGggLSAxOyBpIDwgbiAmJiDOuyA+IGhlbWlsb2Jlc1tpXVsyXVswXTsgKytpKSA7XG4gICAgICB2YXIgY29vcmRpbmF0ZXMgPSBwcm9qZWN0KM67IC0gaGVtaWxvYmVzW2ldWzFdWzBdLCDPhik7XG4gICAgICBjb29yZGluYXRlc1swXSArPSBwcm9qZWN0KGhlbWlsb2Jlc1tpXVsxXVswXSwgc2lnbiAqIM+GID4gc2lnbiAqIGhlbWlsb2Jlc1tpXVswXVsxXSA/IGhlbWlsb2Jlc1tpXVswXVsxXSA6IM+GKVswXTtcbiAgICAgIHJldHVybiBjb29yZGluYXRlcztcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICBib3VuZHMgPSBsb2Jlcy5tYXAoZnVuY3Rpb24oaGVtaWxvYmVzKSB7XG4gICAgICAgIHJldHVybiBoZW1pbG9iZXMubWFwKGZ1bmN0aW9uKGxvYmUpIHtcbiAgICAgICAgICB2YXIgeDAgPSBwcm9qZWN0KGxvYmVbMF1bMF0sIGxvYmVbMF1bMV0pWzBdLCB4MSA9IHByb2plY3QobG9iZVsyXVswXSwgbG9iZVsyXVsxXSlbMF0sIHkwID0gcHJvamVjdChsb2JlWzFdWzBdLCBsb2JlWzBdWzFdKVsxXSwgeTEgPSBwcm9qZWN0KGxvYmVbMV1bMF0sIGxvYmVbMV1bMV0pWzFdLCB0O1xuICAgICAgICAgIGlmICh5MCA+IHkxKSB0ID0geTAsIHkwID0geTEsIHkxID0gdDtcbiAgICAgICAgICByZXR1cm4gWyBbIHgwLCB5MCBdLCBbIHgxLCB5MSBdIF07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChwcm9qZWN0LmludmVydCkgZm9yd2FyZC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgaGVtaWJvdW5kcyA9IGJvdW5kc1srKHkgPCAwKV0sIGhlbWlsb2JlcyA9IGxvYmVzWysoeSA8IDApXTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gaGVtaWJvdW5kcy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgdmFyIGIgPSBoZW1pYm91bmRzW2ldO1xuICAgICAgICBpZiAoYlswXVswXSA8PSB4ICYmIHggPCBiWzFdWzBdICYmIGJbMF1bMV0gPD0geSAmJiB5IDwgYlsxXVsxXSkge1xuICAgICAgICAgIHZhciBjb29yZGluYXRlcyA9IHByb2plY3QuaW52ZXJ0KHggLSBwcm9qZWN0KGhlbWlsb2Jlc1tpXVsxXVswXSwgMClbMF0sIHkpO1xuICAgICAgICAgIGNvb3JkaW5hdGVzWzBdICs9IGhlbWlsb2Jlc1tpXVsxXVswXTtcbiAgICAgICAgICByZXR1cm4gcG9pbnRFcXVhbChmb3J3YXJkKGNvb3JkaW5hdGVzWzBdLCBjb29yZGluYXRlc1sxXSksIFsgeCwgeSBdKSA/IGNvb3JkaW5hdGVzIDogbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgdmFyIHByb2plY3Rpb24gPSBkMy5nZW8ucHJvamVjdGlvbihmb3J3YXJkKSwgc3RyZWFtXyA9IHByb2plY3Rpb24uc3RyZWFtO1xuICAgIHByb2plY3Rpb24uc3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcm90YXRlID0gcHJvamVjdGlvbi5yb3RhdGUoKSwgcm90YXRlU3RyZWFtID0gc3RyZWFtXyhzdHJlYW0pLCBzcGhlcmVTdHJlYW0gPSAocHJvamVjdGlvbi5yb3RhdGUoWyAwLCAwIF0pLCBcbiAgICAgIHN0cmVhbV8oc3RyZWFtKSk7XG4gICAgICBwcm9qZWN0aW9uLnJvdGF0ZShyb3RhdGUpO1xuICAgICAgcm90YXRlU3RyZWFtLnNwaGVyZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBkMy5nZW8uc3RyZWFtKHNwaGVyZSgpLCBzcGhlcmVTdHJlYW0pO1xuICAgICAgfTtcbiAgICAgIHJldHVybiByb3RhdGVTdHJlYW07XG4gICAgfTtcbiAgICBwcm9qZWN0aW9uLmxvYmVzID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbG9iZXMubWFwKGZ1bmN0aW9uKGxvYmVzKSB7XG4gICAgICAgIHJldHVybiBsb2Jlcy5tYXAoZnVuY3Rpb24obG9iZSkge1xuICAgICAgICAgIHJldHVybiBbIFsgbG9iZVswXVswXSAqIDE4MCAvIM+ALCBsb2JlWzBdWzFdICogMTgwIC8gz4AgXSwgWyBsb2JlWzFdWzBdICogMTgwIC8gz4AsIGxvYmVbMV1bMV0gKiAxODAgLyDPgCBdLCBbIGxvYmVbMl1bMF0gKiAxODAgLyDPgCwgbG9iZVsyXVsxXSAqIDE4MCAvIM+AIF0gXTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIGxvYmVzID0gXy5tYXAoZnVuY3Rpb24obG9iZXMpIHtcbiAgICAgICAgcmV0dXJuIGxvYmVzLm1hcChmdW5jdGlvbihsb2JlKSB7XG4gICAgICAgICAgcmV0dXJuIFsgWyBsb2JlWzBdWzBdICogz4AgLyAxODAsIGxvYmVbMF1bMV0gKiDPgCAvIDE4MCBdLCBbIGxvYmVbMV1bMF0gKiDPgCAvIDE4MCwgbG9iZVsxXVsxXSAqIM+AIC8gMTgwIF0sIFsgbG9iZVsyXVswXSAqIM+AIC8gMTgwLCBsb2JlWzJdWzFdICogz4AgLyAxODAgXSBdO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgcmVzZXQoKTtcbiAgICAgIHJldHVybiBwcm9qZWN0aW9uO1xuICAgIH07XG4gICAgZnVuY3Rpb24gc3BoZXJlKCkge1xuICAgICAgdmFyIM61ID0gMWUtNiwgY29vcmRpbmF0ZXMgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gbG9iZXNbMF0ubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBsb2JlID0gbG9iZXNbMF1baV0sIM67MCA9IGxvYmVbMF1bMF0gKiAxODAgLyDPgCwgz4YwID0gbG9iZVswXVsxXSAqIDE4MCAvIM+ALCDPhjEgPSBsb2JlWzFdWzFdICogMTgwIC8gz4AsIM67MiA9IGxvYmVbMl1bMF0gKiAxODAgLyDPgCwgz4YyID0gbG9iZVsyXVsxXSAqIDE4MCAvIM+AO1xuICAgICAgICBjb29yZGluYXRlcy5wdXNoKHJlc2FtcGxlKFsgWyDOuzAgKyDOtSwgz4YwICsgzrUgXSwgWyDOuzAgKyDOtSwgz4YxIC0gzrUgXSwgWyDOuzIgLSDOtSwgz4YxIC0gzrUgXSwgWyDOuzIgLSDOtSwgz4YyICsgzrUgXSBdLCAzMCkpO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IGxvYmVzWzFdLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIHZhciBsb2JlID0gbG9iZXNbMV1baV0sIM67MCA9IGxvYmVbMF1bMF0gKiAxODAgLyDPgCwgz4YwID0gbG9iZVswXVsxXSAqIDE4MCAvIM+ALCDPhjEgPSBsb2JlWzFdWzFdICogMTgwIC8gz4AsIM67MiA9IGxvYmVbMl1bMF0gKiAxODAgLyDPgCwgz4YyID0gbG9iZVsyXVsxXSAqIDE4MCAvIM+AO1xuICAgICAgICBjb29yZGluYXRlcy5wdXNoKHJlc2FtcGxlKFsgWyDOuzIgLSDOtSwgz4YyIC0gzrUgXSwgWyDOuzIgLSDOtSwgz4YxICsgzrUgXSwgWyDOuzAgKyDOtSwgz4YxICsgzrUgXSwgWyDOuzAgKyDOtSwgz4YwIC0gzrUgXSBdLCAzMCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJQb2x5Z29uXCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBbIGQzLm1lcmdlKGNvb3JkaW5hdGVzKSBdXG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNhbXBsZShjb29yZGluYXRlcywgbSkge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aCwgcDAgPSBjb29yZGluYXRlc1swXSwgcDEsIGR4LCBkeSwgcmVzYW1wbGVkID0gW107XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBwMSA9IGNvb3JkaW5hdGVzW2ldO1xuICAgICAgICBkeCA9IChwMVswXSAtIHAwWzBdKSAvIG07XG4gICAgICAgIGR5ID0gKHAxWzFdIC0gcDBbMV0pIC8gbTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtOyArK2opIHJlc2FtcGxlZC5wdXNoKFsgcDBbMF0gKyBqICogZHgsIHAwWzFdICsgaiAqIGR5IF0pO1xuICAgICAgICBwMCA9IHAxO1xuICAgICAgfVxuICAgICAgcmVzYW1wbGVkLnB1c2gocDEpO1xuICAgICAgcmV0dXJuIHJlc2FtcGxlZDtcbiAgICB9XG4gICAgZnVuY3Rpb24gcG9pbnRFcXVhbChhLCBiKSB7XG4gICAgICByZXR1cm4gTWF0aC5hYnMoYVswXSAtIGJbMF0pIDwgzrUgJiYgTWF0aC5hYnMoYVsxXSAtIGJbMV0pIDwgzrU7XG4gICAgfVxuICAgIHJldHVybiBwcm9qZWN0aW9uO1xuICB9O1xuICBmdW5jdGlvbiBlY2tlcnQ0KM67LCDPhikge1xuICAgIHZhciBrID0gKDIgKyBoYWxmz4ApICogTWF0aC5zaW4oz4YpO1xuICAgIM+GIC89IDI7XG4gICAgZm9yICh2YXIgaSA9IDAsIM60ID0gSW5maW5pdHk7IGkgPCAxMCAmJiBNYXRoLmFicyjOtCkgPiDOtTsgaSsrKSB7XG4gICAgICB2YXIgY29zz4YgPSBNYXRoLmNvcyjPhik7XG4gICAgICDPhiAtPSDOtCA9ICjPhiArIE1hdGguc2luKM+GKSAqIChjb3PPhiArIDIpIC0gaykgLyAoMiAqIGNvc8+GICogKDEgKyBjb3PPhikpO1xuICAgIH1cbiAgICByZXR1cm4gWyAyIC8gTWF0aC5zcXJ0KM+AICogKDQgKyDPgCkpICogzrsgKiAoMSArIE1hdGguY29zKM+GKSksIDIgKiBNYXRoLnNxcnQoz4AgLyAoNCArIM+AKSkgKiBNYXRoLnNpbijPhikgXTtcbiAgfVxuICBlY2tlcnQ0LmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgQSA9IC41ICogeSAqIE1hdGguc3FydCgoNCArIM+AKSAvIM+AKSwgayA9IGFzaW4oQSksIGMgPSBNYXRoLmNvcyhrKTtcbiAgICByZXR1cm4gWyB4IC8gKDIgLyBNYXRoLnNxcnQoz4AgKiAoNCArIM+AKSkgKiAoMSArIGMpKSwgYXNpbigoayArIEEgKiAoYyArIDIpKSAvICgyICsgaGFsZs+AKSkgXTtcbiAgfTtcbiAgKGQzLmdlby5lY2tlcnQ0ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24oZWNrZXJ0NCk7XG4gIH0pLnJhdyA9IGVja2VydDQ7XG4gIHZhciBoYW1tZXJBemltdXRoYWxFcXVhbEFyZWEgPSBkMy5nZW8uYXppbXV0aGFsRXF1YWxBcmVhLnJhdztcbiAgZnVuY3Rpb24gaGFtbWVyKEEsIEIpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIEIgPSBBO1xuICAgIGlmIChCID09PSAxKSByZXR1cm4gaGFtbWVyQXppbXV0aGFsRXF1YWxBcmVhO1xuICAgIGlmIChCID09PSBJbmZpbml0eSkgcmV0dXJuIGhhbW1lclF1YXJ0aWNBdXRoYWxpYztcbiAgICBmdW5jdGlvbiBmb3J3YXJkKM67LCDPhikge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gaGFtbWVyQXppbXV0aGFsRXF1YWxBcmVhKM67IC8gQiwgz4YpO1xuICAgICAgY29vcmRpbmF0ZXNbMF0gKj0gQTtcbiAgICAgIHJldHVybiBjb29yZGluYXRlcztcbiAgICB9XG4gICAgZm9yd2FyZC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgY29vcmRpbmF0ZXMgPSBoYW1tZXJBemltdXRoYWxFcXVhbEFyZWEuaW52ZXJ0KHggLyBBLCB5KTtcbiAgICAgIGNvb3JkaW5hdGVzWzBdICo9IEI7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXM7XG4gICAgfTtcbiAgICByZXR1cm4gZm9yd2FyZDtcbiAgfVxuICBmdW5jdGlvbiBoYW1tZXJQcm9qZWN0aW9uKCkge1xuICAgIHZhciBCID0gMiwgbSA9IHByb2plY3Rpb25NdXRhdG9yKGhhbW1lciksIHAgPSBtKEIpO1xuICAgIHAuY29lZmZpY2llbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBCO1xuICAgICAgcmV0dXJuIG0oQiA9ICtfKTtcbiAgICB9O1xuICAgIHJldHVybiBwO1xuICB9XG4gIGZ1bmN0aW9uIGhhbW1lclF1YXJ0aWNBdXRoYWxpYyjOuywgz4YpIHtcbiAgICByZXR1cm4gWyDOuyAqIE1hdGguY29zKM+GKSAvIE1hdGguY29zKM+GIC89IDIpLCAyICogTWF0aC5zaW4oz4YpIF07XG4gIH1cbiAgaGFtbWVyUXVhcnRpY0F1dGhhbGljLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgz4YgPSAyICogYXNpbih5IC8gMik7XG4gICAgcmV0dXJuIFsgeCAqIE1hdGguY29zKM+GIC8gMikgLyBNYXRoLmNvcyjPhiksIM+GIF07XG4gIH07XG4gIChkMy5nZW8uaGFtbWVyID0gaGFtbWVyUHJvamVjdGlvbikucmF3ID0gaGFtbWVyO1xuICBmdW5jdGlvbiBrYXZyYXlza2l5NyjOuywgz4YpIHtcbiAgICByZXR1cm4gWyAzICogzrsgLyAoMiAqIM+AKSAqIE1hdGguc3FydCjPgCAqIM+AIC8gMyAtIM+GICogz4YpLCDPhiBdO1xuICB9XG4gIGthdnJheXNraXk3LmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICByZXR1cm4gWyAyIC8gMyAqIM+AICogeCAvIE1hdGguc3FydCjPgCAqIM+AIC8gMyAtIHkgKiB5KSwgeSBdO1xuICB9O1xuICAoZDMuZ2VvLmthdnJheXNraXk3ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24oa2F2cmF5c2tpeTcpO1xuICB9KS5yYXcgPSBrYXZyYXlza2l5NztcbiAgZnVuY3Rpb24gbWlsbGVyKM67LCDPhikge1xuICAgIHJldHVybiBbIM67LCAxLjI1ICogTWF0aC5sb2coTWF0aC50YW4oz4AgLyA0ICsgLjQgKiDPhikpIF07XG4gIH1cbiAgbWlsbGVyLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICByZXR1cm4gWyB4LCAyLjUgKiBNYXRoLmF0YW4oTWF0aC5leHAoLjggKiB5KSkgLSAuNjI1ICogz4AgXTtcbiAgfTtcbiAgKGQzLmdlby5taWxsZXIgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcHJvamVjdGlvbihtaWxsZXIpO1xuICB9KS5yYXcgPSBtaWxsZXI7XG4gIGZ1bmN0aW9uIG1vbGx3ZWlkZUJyb21sZXnOuChDcCkge1xuICAgIHJldHVybiBmdW5jdGlvbijOuCkge1xuICAgICAgdmFyIENwc2luzrggPSBDcCAqIE1hdGguc2luKM64KSwgaSA9IDMwLCDOtDtcbiAgICAgIGRvIM64IC09IM60ID0gKM64ICsgTWF0aC5zaW4ozrgpIC0gQ3BzaW7OuCkgLyAoMSArIE1hdGguY29zKM64KSk7IHdoaWxlIChNYXRoLmFicyjOtCkgPiDOtSAmJiAtLWkgPiAwKTtcbiAgICAgIHJldHVybiDOuCAvIDI7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBtb2xsd2VpZGVCcm9tbGV5KEN4LCBDeSwgQ3ApIHtcbiAgICB2YXIgzrggPSBtb2xsd2VpZGVCcm9tbGV5zrgoQ3ApO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICByZXR1cm4gWyBDeCAqIM67ICogTWF0aC5jb3Moz4YgPSDOuCjPhikpLCBDeSAqIE1hdGguc2luKM+GKSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDOuCA9IGFzaW4oeSAvIEN5KTtcbiAgICAgIHJldHVybiBbIHggLyAoQ3ggKiBNYXRoLmNvcyjOuCkpLCBhc2luKCgyICogzrggKyBNYXRoLnNpbigyICogzrgpKSAvIENwKSBdO1xuICAgIH07XG4gICAgcmV0dXJuIGZvcndhcmQ7XG4gIH1cbiAgdmFyIG1vbGx3ZWlkZc64ID0gbW9sbHdlaWRlQnJvbWxlec64KM+AKSwgbW9sbHdlaWRlID0gbW9sbHdlaWRlQnJvbWxleShNYXRoLlNRUlQyIC8gaGFsZs+ALCBNYXRoLlNRUlQyLCDPgCk7XG4gIChkMy5nZW8ubW9sbHdlaWRlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24obW9sbHdlaWRlKTtcbiAgfSkucmF3ID0gbW9sbHdlaWRlO1xuICBmdW5jdGlvbiBuYXR1cmFsRWFydGgozrssIM+GKSB7XG4gICAgdmFyIM+GMiA9IM+GICogz4YsIM+GNCA9IM+GMiAqIM+GMjtcbiAgICByZXR1cm4gWyDOuyAqICguODcwNyAtIC4xMzE5NzkgKiDPhjIgKyDPhjQgKiAoLS4wMTM3OTEgKyDPhjQgKiAoLjAwMzk3MSAqIM+GMiAtIC4wMDE1MjkgKiDPhjQpKSksIM+GICogKDEuMDA3MjI2ICsgz4YyICogKC4wMTUwODUgKyDPhjQgKiAoLS4wNDQ0NzUgKyAuMDI4ODc0ICogz4YyIC0gLjAwNTkxNiAqIM+GNCkpKSBdO1xuICB9XG4gIG5hdHVyYWxFYXJ0aC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIM+GID0geSwgaSA9IDI1LCDOtDtcbiAgICBkbyB7XG4gICAgICB2YXIgz4YyID0gz4YgKiDPhiwgz4Y0ID0gz4YyICogz4YyO1xuICAgICAgz4YgLT0gzrQgPSAoz4YgKiAoMS4wMDcyMjYgKyDPhjIgKiAoLjAxNTA4NSArIM+GNCAqICgtLjA0NDQ3NSArIC4wMjg4NzQgKiDPhjIgLSAuMDA1OTE2ICogz4Y0KSkpIC0geSkgLyAoMS4wMDcyMjYgKyDPhjIgKiAoLjAxNTA4NSAqIDMgKyDPhjQgKiAoLS4wNDQ0NzUgKiA3ICsgLjAyODg3NCAqIDkgKiDPhjIgLSAuMDA1OTE2ICogMTEgKiDPhjQpKSk7XG4gICAgfSB3aGlsZSAoTWF0aC5hYnMozrQpID4gzrUgJiYgLS1pID4gMCk7XG4gICAgcmV0dXJuIFsgeCAvICguODcwNyArICjPhjIgPSDPhiAqIM+GKSAqICgtLjEzMTk3OSArIM+GMiAqICgtLjAxMzc5MSArIM+GMiAqIM+GMiAqIM+GMiAqICguMDAzOTcxIC0gLjAwMTUyOSAqIM+GMikpKSksIM+GIF07XG4gIH07XG4gIChkMy5nZW8ubmF0dXJhbEVhcnRoID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24obmF0dXJhbEVhcnRoKTtcbiAgfSkucmF3ID0gbmF0dXJhbEVhcnRoO1xuICB2YXIgcm9iaW5zb25Db25zdGFudHMgPSBbIFsgLjk5ODYsIC0uMDYyIF0sIFsgMSwgMCBdLCBbIC45OTg2LCAuMDYyIF0sIFsgLjk5NTQsIC4xMjQgXSwgWyAuOTksIC4xODYgXSwgWyAuOTgyMiwgLjI0OCBdLCBbIC45NzMsIC4zMSBdLCBbIC45NiwgLjM3MiBdLCBbIC45NDI3LCAuNDM0IF0sIFsgLjkyMTYsIC40OTU4IF0sIFsgLjg5NjIsIC41NTcxIF0sIFsgLjg2NzksIC42MTc2IF0sIFsgLjgzNSwgLjY3NjkgXSwgWyAuNzk4NiwgLjczNDYgXSwgWyAuNzU5NywgLjc5MDMgXSwgWyAuNzE4NiwgLjg0MzUgXSwgWyAuNjczMiwgLjg5MzYgXSwgWyAuNjIxMywgLjkzOTQgXSwgWyAuNTcyMiwgLjk3NjEgXSwgWyAuNTMyMiwgMSBdIF07XG4gIHJvYmluc29uQ29uc3RhbnRzLmZvckVhY2goZnVuY3Rpb24oZCkge1xuICAgIGRbMV0gKj0gMS4wMTQ0O1xuICB9KTtcbiAgZnVuY3Rpb24gcm9iaW5zb24ozrssIM+GKSB7XG4gICAgdmFyIGkgPSBNYXRoLm1pbigxOCwgTWF0aC5hYnMoz4YpICogMzYgLyDPgCksIGkwID0gTWF0aC5mbG9vcihpKSwgZGkgPSBpIC0gaTAsIGF4ID0gKGsgPSByb2JpbnNvbkNvbnN0YW50c1tpMF0pWzBdLCBheSA9IGtbMV0sIGJ4ID0gKGsgPSByb2JpbnNvbkNvbnN0YW50c1srK2kwXSlbMF0sIGJ5ID0ga1sxXSwgY3ggPSAoayA9IHJvYmluc29uQ29uc3RhbnRzW01hdGgubWluKDE5LCArK2kwKV0pWzBdLCBjeSA9IGtbMV0sIGs7XG4gICAgcmV0dXJuIFsgzrsgKiAoYnggKyBkaSAqIChjeCAtIGF4KSAvIDIgKyBkaSAqIGRpICogKGN4IC0gMiAqIGJ4ICsgYXgpIC8gMiksICjPhiA+IDAgPyBoYWxmz4AgOiAtaGFsZs+AKSAqIChieSArIGRpICogKGN5IC0gYXkpIC8gMiArIGRpICogZGkgKiAoY3kgLSAyICogYnkgKyBheSkgLyAyKSBdO1xuICB9XG4gIHJvYmluc29uLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgeXkgPSB5IC8gaGFsZs+ALCDPhiA9IHl5ICogOTAsIGkgPSBNYXRoLm1pbigxOCwgTWF0aC5hYnMoz4YgLyA1KSksIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihpKSk7XG4gICAgZG8ge1xuICAgICAgdmFyIGF5ID0gcm9iaW5zb25Db25zdGFudHNbaTBdWzFdLCBieSA9IHJvYmluc29uQ29uc3RhbnRzW2kwICsgMV1bMV0sIGN5ID0gcm9iaW5zb25Db25zdGFudHNbTWF0aC5taW4oMTksIGkwICsgMildWzFdLCB1ID0gY3kgLSBheSwgdiA9IGN5IC0gMiAqIGJ5ICsgYXksIHQgPSAyICogKE1hdGguYWJzKHl5KSAtIGJ5KSAvIHUsIGMgPSB2IC8gdSwgZGkgPSB0ICogKDEgLSBjICogdCAqICgxIC0gMiAqIGMgKiB0KSk7XG4gICAgICBpZiAoZGkgPj0gMCB8fCBpMCA9PT0gMSkge1xuICAgICAgICDPhiA9ICh5ID49IDAgPyA1IDogLTUpICogKGRpICsgaSk7XG4gICAgICAgIHZhciBqID0gNTAsIM60O1xuICAgICAgICBkbyB7XG4gICAgICAgICAgaSA9IE1hdGgubWluKDE4LCBNYXRoLmFicyjPhikgLyA1KTtcbiAgICAgICAgICBpMCA9IE1hdGguZmxvb3IoaSk7XG4gICAgICAgICAgZGkgPSBpIC0gaTA7XG4gICAgICAgICAgYXkgPSByb2JpbnNvbkNvbnN0YW50c1tpMF1bMV07XG4gICAgICAgICAgYnkgPSByb2JpbnNvbkNvbnN0YW50c1tpMCArIDFdWzFdO1xuICAgICAgICAgIGN5ID0gcm9iaW5zb25Db25zdGFudHNbTWF0aC5taW4oMTksIGkwICsgMildWzFdO1xuICAgICAgICAgIM+GIC09ICjOtCA9ICh5ID49IDAgPyBoYWxmz4AgOiAtaGFsZs+AKSAqIChieSArIGRpICogKGN5IC0gYXkpIC8gMiArIGRpICogZGkgKiAoY3kgLSAyICogYnkgKyBheSkgLyAyKSAtIHkpICogZGVncmVlcztcbiAgICAgICAgfSB3aGlsZSAoTWF0aC5hYnMozrQpID4gzrUyICYmIC0taiA+IDApO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9IHdoaWxlICgtLWkwID49IDApO1xuICAgIHZhciBheCA9IHJvYmluc29uQ29uc3RhbnRzW2kwXVswXSwgYnggPSByb2JpbnNvbkNvbnN0YW50c1tpMCArIDFdWzBdLCBjeCA9IHJvYmluc29uQ29uc3RhbnRzW01hdGgubWluKDE5LCBpMCArIDIpXVswXTtcbiAgICByZXR1cm4gWyB4IC8gKGJ4ICsgZGkgKiAoY3ggLSBheCkgLyAyICsgZGkgKiBkaSAqIChjeCAtIDIgKiBieCArIGF4KSAvIDIpLCDPhiAqIHJhZGlhbnMgXTtcbiAgfTtcbiAgKGQzLmdlby5yb2JpbnNvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKHJvYmluc29uKTtcbiAgfSkucmF3ID0gcm9iaW5zb247XG4gIGZ1bmN0aW9uIHNpbnVzb2lkYWwozrssIM+GKSB7XG4gICAgcmV0dXJuIFsgzrsgKiBNYXRoLmNvcyjPhiksIM+GIF07XG4gIH1cbiAgc2ludXNvaWRhbC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFsgeCAvIE1hdGguY29zKHkpLCB5IF07XG4gIH07XG4gIChkMy5nZW8uc2ludXNvaWRhbCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKHNpbnVzb2lkYWwpO1xuICB9KS5yYXcgPSBzaW51c29pZGFsO1xuICBmdW5jdGlvbiBhaXRvZmYozrssIM+GKSB7XG4gICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBzaW5jac6xID0gc2luY2koYWNvcyhjb3PPhiAqIE1hdGguY29zKM67IC89IDIpKSk7XG4gICAgcmV0dXJuIFsgMiAqIGNvc8+GICogTWF0aC5zaW4ozrspICogc2luY2nOsSwgTWF0aC5zaW4oz4YpICogc2luY2nOsSBdO1xuICB9XG4gIGFpdG9mZi5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgaWYgKHggKiB4ICsgNCAqIHkgKiB5ID4gz4AgKiDPgCArIM61KSByZXR1cm47XG4gICAgdmFyIM67ID0geCwgz4YgPSB5LCBpID0gMjU7XG4gICAgZG8ge1xuICAgICAgdmFyIHNpbs67ID0gTWF0aC5zaW4ozrspLCBzaW7Ou18yID0gTWF0aC5zaW4ozrsgLyAyKSwgY29zzrtfMiA9IE1hdGguY29zKM67IC8gMiksIHNpbs+GID0gTWF0aC5zaW4oz4YpLCBjb3PPhiA9IE1hdGguY29zKM+GKSwgc2luXzLPhiA9IE1hdGguc2luKDIgKiDPhiksIHNpbjLPhiA9IHNpbs+GICogc2luz4YsIGNvczLPhiA9IGNvc8+GICogY29zz4YsIHNpbjLOu18yID0gc2luzrtfMiAqIHNpbs67XzIsIEMgPSAxIC0gY29zMs+GICogY29zzrtfMiAqIGNvc867XzIsIEUgPSBDID8gYWNvcyhjb3PPhiAqIGNvc867XzIpICogTWF0aC5zcXJ0KEYgPSAxIC8gQykgOiBGID0gMCwgRiwgZnggPSAyICogRSAqIGNvc8+GICogc2luzrtfMiAtIHgsIGZ5ID0gRSAqIHNpbs+GIC0geSwgzrR4zrTOuyA9IEYgKiAoY29zMs+GICogc2luMs67XzIgKyBFICogY29zz4YgKiBjb3POu18yICogc2luMs+GKSwgzrR4zrTPhiA9IEYgKiAoLjUgKiBzaW7OuyAqIHNpbl8yz4YgLSBFICogMiAqIHNpbs+GICogc2luzrtfMiksIM60ec60zrsgPSBGICogLjI1ICogKHNpbl8yz4YgKiBzaW7Ou18yIC0gRSAqIHNpbs+GICogY29zMs+GICogc2luzrspLCDOtHnOtM+GID0gRiAqIChzaW4yz4YgKiBjb3POu18yICsgRSAqIHNpbjLOu18yICogY29zz4YpLCBkZW5vbWluYXRvciA9IM60eM60z4YgKiDOtHnOtM67IC0gzrR5zrTPhiAqIM60eM60zrs7XG4gICAgICBpZiAoIWRlbm9taW5hdG9yKSBicmVhaztcbiAgICAgIHZhciDOtM67ID0gKGZ5ICogzrR4zrTPhiAtIGZ4ICogzrR5zrTPhikgLyBkZW5vbWluYXRvciwgzrTPhiA9IChmeCAqIM60ec60zrsgLSBmeSAqIM60eM60zrspIC8gZGVub21pbmF0b3I7XG4gICAgICDOuyAtPSDOtM67LCDPhiAtPSDOtM+GO1xuICAgIH0gd2hpbGUgKChNYXRoLmFicyjOtM67KSA+IM61IHx8IE1hdGguYWJzKM60z4YpID4gzrUpICYmIC0taSA+IDApO1xuICAgIHJldHVybiBbIM67LCDPhiBdO1xuICB9O1xuICAoZDMuZ2VvLmFpdG9mZiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKGFpdG9mZik7XG4gIH0pLnJhdyA9IGFpdG9mZjtcbiAgZnVuY3Rpb24gd2lua2VsMyjOuywgz4YpIHtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSBhaXRvZmYozrssIM+GKTtcbiAgICByZXR1cm4gWyAoY29vcmRpbmF0ZXNbMF0gKyDOuyAvIGhhbGbPgCkgLyAyLCAoY29vcmRpbmF0ZXNbMV0gKyDPhikgLyAyIF07XG4gIH1cbiAgd2lua2VsMy5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIM67ID0geCwgz4YgPSB5LCBpID0gMjU7XG4gICAgZG8ge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBzaW7PhiA9IE1hdGguc2luKM+GKSwgc2luXzLPhiA9IE1hdGguc2luKDIgKiDPhiksIHNpbjLPhiA9IHNpbs+GICogc2luz4YsIGNvczLPhiA9IGNvc8+GICogY29zz4YsIHNpbs67ID0gTWF0aC5zaW4ozrspLCBjb3POu18yID0gTWF0aC5jb3MozrsgLyAyKSwgc2luzrtfMiA9IE1hdGguc2luKM67IC8gMiksIHNpbjLOu18yID0gc2luzrtfMiAqIHNpbs67XzIsIEMgPSAxIC0gY29zMs+GICogY29zzrtfMiAqIGNvc867XzIsIEUgPSBDID8gYWNvcyhjb3PPhiAqIGNvc867XzIpICogTWF0aC5zcXJ0KEYgPSAxIC8gQykgOiBGID0gMCwgRiwgZnggPSAuNSAqICgyICogRSAqIGNvc8+GICogc2luzrtfMiArIM67IC8gaGFsZs+AKSAtIHgsIGZ5ID0gLjUgKiAoRSAqIHNpbs+GICsgz4YpIC0geSwgzrR4zrTOuyA9IC41ICogRiAqIChjb3Myz4YgKiBzaW4yzrtfMiArIEUgKiBjb3PPhiAqIGNvc867XzIgKiBzaW4yz4YpICsgLjUgLyBoYWxmz4AsIM60eM60z4YgPSBGICogKHNpbs67ICogc2luXzLPhiAvIDQgLSBFICogc2luz4YgKiBzaW7Ou18yKSwgzrR5zrTOuyA9IC4xMjUgKiBGICogKHNpbl8yz4YgKiBzaW7Ou18yIC0gRSAqIHNpbs+GICogY29zMs+GICogc2luzrspLCDOtHnOtM+GID0gLjUgKiBGICogKHNpbjLPhiAqIGNvc867XzIgKyBFICogc2luMs67XzIgKiBjb3PPhikgKyAuNSwgZGVub21pbmF0b3IgPSDOtHjOtM+GICogzrR5zrTOuyAtIM60ec60z4YgKiDOtHjOtM67LCDOtM67ID0gKGZ5ICogzrR4zrTPhiAtIGZ4ICogzrR5zrTPhikgLyBkZW5vbWluYXRvciwgzrTPhiA9IChmeCAqIM60ec60zrsgLSBmeSAqIM60eM60zrspIC8gZGVub21pbmF0b3I7XG4gICAgICDOuyAtPSDOtM67LCDPhiAtPSDOtM+GO1xuICAgIH0gd2hpbGUgKChNYXRoLmFicyjOtM67KSA+IM61IHx8IE1hdGguYWJzKM60z4YpID4gzrUpICYmIC0taSA+IDApO1xuICAgIHJldHVybiBbIM67LCDPhiBdO1xuICB9O1xuICAoZDMuZ2VvLndpbmtlbDMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcHJvamVjdGlvbih3aW5rZWwzKTtcbiAgfSkucmF3ID0gd2lua2VsMztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhZGRQcm9qZWN0aW9uc1RvRDM7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIHJhZGlhbnMgPSBNYXRoLlBJIC8gMTgwO1xudmFyIGRlZ3JlZXMgPSAxODAgLyBNYXRoLlBJO1xudmFyIHpvb21zdGFydFN0eWxlID0ge2N1cnNvcjogJ3BvaW50ZXInfTtcbnZhciB6b29tZW5kU3R5bGUgPSB7Y3Vyc29yOiAnYXV0byd9O1xuXG5mdW5jdGlvbiBjcmVhdGVHZW9ab29tKGdlbywgZ2VvTGF5b3V0KSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSBnZW8ucHJvamVjdGlvbjtcbiAgICB2YXIgem9vbUNvbnN0cnVjdG9yO1xuXG4gICAgaWYoZ2VvTGF5b3V0Ll9pc1Njb3BlZCkge1xuICAgICAgICB6b29tQ29uc3RydWN0b3IgPSB6b29tU2NvcGVkO1xuICAgIH0gZWxzZSBpZihnZW9MYXlvdXQuX2lzQ2xpcHBlZCkge1xuICAgICAgICB6b29tQ29uc3RydWN0b3IgPSB6b29tQ2xpcHBlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB6b29tQ29uc3RydWN0b3IgPSB6b29tTm9uQ2xpcHBlZDtcbiAgICB9XG5cbiAgICAvLyBUT0RPIGFkZCBhIGNvbmljLXNwZWNpZmljIHpvb21cblxuICAgIHJldHVybiB6b29tQ29uc3RydWN0b3IoZ2VvLCBwcm9qZWN0aW9uKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVHZW9ab29tO1xuXG4vLyBjb21tb24gdG8gYWxsIHpvb20gdHlwZXNcbmZ1bmN0aW9uIGluaXRab29tKGdlbywgcHJvamVjdGlvbikge1xuICAgIHJldHVybiBkMy5iZWhhdmlvci56b29tKClcbiAgICAgICAgLnRyYW5zbGF0ZShwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpKVxuICAgICAgICAuc2NhbGUocHJvamVjdGlvbi5zY2FsZSgpKTtcbn1cblxuLy8gc3luYyB6b29tIHVwZGF0ZXMgd2l0aCB1c2VyICYgZnVsbCBsYXlvdXRcbmZ1bmN0aW9uIHN5bmMoZ2VvLCBwcm9qZWN0aW9uLCBjYikge1xuICAgIHZhciBpZCA9IGdlby5pZDtcbiAgICB2YXIgZ2QgPSBnZW8uZ3JhcGhEaXY7XG4gICAgdmFyIHVzZXJPcHRzID0gZ2QubGF5b3V0W2lkXTtcbiAgICB2YXIgZnVsbE9wdHMgPSBnZC5fZnVsbExheW91dFtpZF07XG5cbiAgICB2YXIgZXZlbnREYXRhID0ge307XG5cbiAgICBmdW5jdGlvbiBzZXQocHJvcFN0ciwgdmFsKSB7XG4gICAgICAgIHZhciBmdWxsTnAgPSBMaWIubmVzdGVkUHJvcGVydHkoZnVsbE9wdHMsIHByb3BTdHIpO1xuXG4gICAgICAgIGlmKGZ1bGxOcC5nZXQoKSAhPT0gdmFsKSB7XG4gICAgICAgICAgICBmdWxsTnAuc2V0KHZhbCk7XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkodXNlck9wdHMsIHByb3BTdHIpLnNldCh2YWwpO1xuICAgICAgICAgICAgZXZlbnREYXRhW2lkICsgJy4nICsgcHJvcFN0cl0gPSB2YWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjYihzZXQpO1xuICAgIHNldCgncHJvamVjdGlvbi5zY2FsZScsIHByb2plY3Rpb24uc2NhbGUoKSAvIGdlby5maXRTY2FsZSk7XG4gICAgZ2QuZW1pdCgncGxvdGx5X3JlbGF5b3V0JywgZXZlbnREYXRhKTtcbn1cblxuLy8gem9vbSBmb3Igc2NvcGVkIHByb2plY3Rpb25zXG5mdW5jdGlvbiB6b29tU2NvcGVkKGdlbywgcHJvamVjdGlvbikge1xuICAgIHZhciB6b29tID0gaW5pdFpvb20oZ2VvLCBwcm9qZWN0aW9uKTtcblxuICAgIGZ1bmN0aW9uIGhhbmRsZVpvb21zdGFydCgpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnN0eWxlKHpvb21zdGFydFN0eWxlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVab29tKCkge1xuICAgICAgICBwcm9qZWN0aW9uXG4gICAgICAgICAgICAuc2NhbGUoZDMuZXZlbnQuc2NhbGUpXG4gICAgICAgICAgICAudHJhbnNsYXRlKGQzLmV2ZW50LnRyYW5zbGF0ZSk7XG4gICAgICAgIGdlby5yZW5kZXIoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzeW5jQ2Ioc2V0KSB7XG4gICAgICAgIHZhciBjZW50ZXIgPSBwcm9qZWN0aW9uLmludmVydChnZW8ubWlkUHQpO1xuXG4gICAgICAgIHNldCgnY2VudGVyLmxvbicsIGNlbnRlclswXSk7XG4gICAgICAgIHNldCgnY2VudGVyLmxhdCcsIGNlbnRlclsxXSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFuZGxlWm9vbWVuZCgpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnN0eWxlKHpvb21lbmRTdHlsZSk7XG4gICAgICAgIHN5bmMoZ2VvLCBwcm9qZWN0aW9uLCBzeW5jQ2IpO1xuICAgIH1cblxuICAgIHpvb21cbiAgICAgICAgLm9uKCd6b29tc3RhcnQnLCBoYW5kbGVab29tc3RhcnQpXG4gICAgICAgIC5vbignem9vbScsIGhhbmRsZVpvb20pXG4gICAgICAgIC5vbignem9vbWVuZCcsIGhhbmRsZVpvb21lbmQpO1xuXG4gICAgcmV0dXJuIHpvb207XG59XG5cbi8vIHpvb20gZm9yIG5vbi1jbGlwcGVkIHByb2plY3Rpb25zXG5mdW5jdGlvbiB6b29tTm9uQ2xpcHBlZChnZW8sIHByb2plY3Rpb24pIHtcbiAgICB2YXIgem9vbSA9IGluaXRab29tKGdlbywgcHJvamVjdGlvbik7XG5cbiAgICB2YXIgSU5TSURFVE9MT1JBTkNFUFhTID0gMjtcblxuICAgIHZhciBtb3VzZTAsIHJvdGF0ZTAsIHRyYW5zbGF0ZTAsIGxhc3RSb3RhdGUsIHpvb21Qb2ludCxcbiAgICAgICAgbW91c2UxLCByb3RhdGUxLCBwb2ludDEsIGRpZFpvb207XG5cbiAgICBmdW5jdGlvbiBwb3NpdGlvbih4KSB7IHJldHVybiBwcm9qZWN0aW9uLmludmVydCh4KTsgfVxuXG4gICAgZnVuY3Rpb24gb3V0c2lkZSh4KSB7XG4gICAgICAgIHZhciBwb3MgPSBwb3NpdGlvbih4KTtcbiAgICAgICAgaWYoIXBvcykgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgdmFyIHB0ID0gcHJvamVjdGlvbihwb3MpO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgTWF0aC5hYnMocHRbMF0gLSB4WzBdKSA+IElOU0lERVRPTE9SQU5DRVBYUyB8fFxuICAgICAgICAgICAgTWF0aC5hYnMocHRbMV0gLSB4WzFdKSA+IElOU0lERVRPTE9SQU5DRVBYU1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVpvb21zdGFydCgpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnN0eWxlKHpvb21zdGFydFN0eWxlKTtcblxuICAgICAgICBtb3VzZTAgPSBkMy5tb3VzZSh0aGlzKTtcbiAgICAgICAgcm90YXRlMCA9IHByb2plY3Rpb24ucm90YXRlKCk7XG4gICAgICAgIHRyYW5zbGF0ZTAgPSBwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpO1xuICAgICAgICBsYXN0Um90YXRlID0gcm90YXRlMDtcbiAgICAgICAgem9vbVBvaW50ID0gcG9zaXRpb24obW91c2UwKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVab29tKCkge1xuICAgICAgICBtb3VzZTEgPSBkMy5tb3VzZSh0aGlzKTtcblxuICAgICAgICBpZihvdXRzaWRlKG1vdXNlMCkpIHtcbiAgICAgICAgICAgIHpvb20uc2NhbGUocHJvamVjdGlvbi5zY2FsZSgpKTtcbiAgICAgICAgICAgIHpvb20udHJhbnNsYXRlKHByb2plY3Rpb24udHJhbnNsYXRlKCkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJvamVjdGlvbi5zY2FsZShkMy5ldmVudC5zY2FsZSk7XG4gICAgICAgIHByb2plY3Rpb24udHJhbnNsYXRlKFt0cmFuc2xhdGUwWzBdLCBkMy5ldmVudC50cmFuc2xhdGVbMV1dKTtcblxuICAgICAgICBpZighem9vbVBvaW50KSB7XG4gICAgICAgICAgICBtb3VzZTAgPSBtb3VzZTE7XG4gICAgICAgICAgICB6b29tUG9pbnQgPSBwb3NpdGlvbihtb3VzZTApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocG9zaXRpb24obW91c2UxKSkge1xuICAgICAgICAgICAgcG9pbnQxID0gcG9zaXRpb24obW91c2UxKTtcbiAgICAgICAgICAgIHJvdGF0ZTEgPSBbbGFzdFJvdGF0ZVswXSArIChwb2ludDFbMF0gLSB6b29tUG9pbnRbMF0pLCByb3RhdGUwWzFdLCByb3RhdGUwWzJdXTtcbiAgICAgICAgICAgIHByb2plY3Rpb24ucm90YXRlKHJvdGF0ZTEpO1xuICAgICAgICAgICAgbGFzdFJvdGF0ZSA9IHJvdGF0ZTE7XG4gICAgICAgIH1cblxuICAgICAgICBkaWRab29tID0gdHJ1ZTtcbiAgICAgICAgZ2VvLnJlbmRlcigpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVpvb21lbmQoKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tZW5kU3R5bGUpO1xuICAgICAgICBpZihkaWRab29tKSBzeW5jKGdlbywgcHJvamVjdGlvbiwgc3luY0NiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzeW5jQ2Ioc2V0KSB7XG4gICAgICAgIHZhciByb3RhdGUgPSBwcm9qZWN0aW9uLnJvdGF0ZSgpO1xuICAgICAgICB2YXIgY2VudGVyID0gcHJvamVjdGlvbi5pbnZlcnQoZ2VvLm1pZFB0KTtcblxuICAgICAgICBzZXQoJ3Byb2plY3Rpb24ucm90YXRpb24ubG9uJywgLXJvdGF0ZVswXSk7XG4gICAgICAgIHNldCgnY2VudGVyLmxvbicsIGNlbnRlclswXSk7XG4gICAgICAgIHNldCgnY2VudGVyLmxhdCcsIGNlbnRlclsxXSk7XG4gICAgfVxuXG4gICAgem9vbVxuICAgICAgICAub24oJ3pvb21zdGFydCcsIGhhbmRsZVpvb21zdGFydClcbiAgICAgICAgLm9uKCd6b29tJywgaGFuZGxlWm9vbSlcbiAgICAgICAgLm9uKCd6b29tZW5kJywgaGFuZGxlWm9vbWVuZCk7XG5cbiAgICByZXR1cm4gem9vbTtcbn1cblxuLy8gem9vbSBmb3IgY2xpcHBlZCBwcm9qZWN0aW9uc1xuLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly93d3cuamFzb25kYXZpZXMuY29tL21hcHMvZDMuZ2VvLnpvb20uanNcbmZ1bmN0aW9uIHpvb21DbGlwcGVkKGdlbywgcHJvamVjdGlvbikge1xuICAgIHZhciB2aWV3ID0ge3I6IHByb2plY3Rpb24ucm90YXRlKCksIGs6IHByb2plY3Rpb24uc2NhbGUoKX0sXG4gICAgICAgIHpvb20gPSBpbml0Wm9vbShnZW8sIHByb2plY3Rpb24pLFxuICAgICAgICBldmVudCA9IGQzX2V2ZW50RGlzcGF0Y2goem9vbSwgJ3pvb21zdGFydCcsICd6b29tJywgJ3pvb21lbmQnKSxcbiAgICAgICAgem9vbWluZyA9IDAsXG4gICAgICAgIHpvb21PbiA9IHpvb20ub247XG5cbiAgICB2YXIgem9vbVBvaW50O1xuXG4gICAgem9vbS5vbignem9vbXN0YXJ0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tc3RhcnRTdHlsZSk7XG5cbiAgICAgICAgdmFyIG1vdXNlMCA9IGQzLm1vdXNlKHRoaXMpLFxuICAgICAgICAgICAgcm90YXRlMCA9IHByb2plY3Rpb24ucm90YXRlKCksXG4gICAgICAgICAgICBsYXN0Um90YXRlID0gcm90YXRlMCxcbiAgICAgICAgICAgIHRyYW5zbGF0ZTAgPSBwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpLFxuICAgICAgICAgICAgcSA9IHF1YXRlcm5pb25Gcm9tRXVsZXIocm90YXRlMCk7XG5cbiAgICAgICAgem9vbVBvaW50ID0gcG9zaXRpb24ocHJvamVjdGlvbiwgbW91c2UwKTtcblxuICAgICAgICB6b29tT24uY2FsbCh6b29tLCAnem9vbScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIG1vdXNlMSA9IGQzLm1vdXNlKHRoaXMpO1xuXG4gICAgICAgICAgICBwcm9qZWN0aW9uLnNjYWxlKHZpZXcuayA9IGQzLmV2ZW50LnNjYWxlKTtcblxuICAgICAgICAgICAgaWYoIXpvb21Qb2ludCkge1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vIHpvb21Qb2ludCwgdGhlIG1vdXNlIHdhc24ndCBvdmVyIHRoZSBhY3R1YWwgZ2VvZ3JhcGh5IHlldFxuICAgICAgICAgICAgICAgIC8vIG1heWJlIHRoaXMgcG9pbnQgaXMgdGhlIHN0YXJ0Li4uIHdlJ2xsIGZpbmQgb3V0IG5leHQgdGltZSFcbiAgICAgICAgICAgICAgICBtb3VzZTAgPSBtb3VzZTE7XG4gICAgICAgICAgICAgICAgem9vbVBvaW50ID0gcG9zaXRpb24ocHJvamVjdGlvbiwgbW91c2UwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHRoZSBwb2ludCBpcyBvbiB0aGUgbWFwXG4gICAgICAgICAgICAvLyBpZiBub3QsIGRvbid0IGRvIGFueXRoaW5nIG5ldyBidXQgc2NhbGVcbiAgICAgICAgICAgIC8vIGlmIGl0IGlzLCB0aGVuIHdlIGNhbiBhc3N1bWUgYmV0d2VlbiB3aWxsIGV4aXN0IGJlbG93XG4gICAgICAgICAgICAvLyBzbyB3ZSBkb24ndCBuZWVkIHRoZSAnYmFuaycgZnVuY3Rpb24sIHdoYXRldmVyIHRoYXQgaXMuXG4gICAgICAgICAgICBlbHNlIGlmKHBvc2l0aW9uKHByb2plY3Rpb24sIG1vdXNlMSkpIHtcbiAgICAgICAgICAgICAgICAvLyBnbyBiYWNrIHRvIG9yaWdpbmFsIHByb2plY3Rpb24gdGVtcG9yYXJpbHlcbiAgICAgICAgICAgICAgICAvLyBleGNlcHQgZm9yIHNjYWxlLi4uIHRoYXQncyBraW5kIG9mIGluZGVwZW5kZW50P1xuICAgICAgICAgICAgICAgIHByb2plY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgLnJvdGF0ZShyb3RhdGUwKVxuICAgICAgICAgICAgICAgICAgICAudHJhbnNsYXRlKHRyYW5zbGF0ZTApO1xuXG4gICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBuZXcgcGFyYW1zXG4gICAgICAgICAgICAgICAgdmFyIHBvaW50MSA9IHBvc2l0aW9uKHByb2plY3Rpb24sIG1vdXNlMSksXG4gICAgICAgICAgICAgICAgICAgIGJldHdlZW4gPSByb3RhdGVCZXR3ZWVuKHpvb21Qb2ludCwgcG9pbnQxKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3RXVsZXIgPSBldWxlckZyb21RdWF0ZXJuaW9uKG11bHRpcGx5KHEsIGJldHdlZW4pKSxcbiAgICAgICAgICAgICAgICAgICAgcm90YXRlQW5nbGVzID0gdmlldy5yID0gdW5Sb2xsKG5ld0V1bGVyLCB6b29tUG9pbnQsIGxhc3RSb3RhdGUpO1xuXG4gICAgICAgICAgICAgICAgaWYoIWlzRmluaXRlKHJvdGF0ZUFuZ2xlc1swXSkgfHwgIWlzRmluaXRlKHJvdGF0ZUFuZ2xlc1sxXSkgfHxcbiAgICAgICAgICAgICAgICAgICAhaXNGaW5pdGUocm90YXRlQW5nbGVzWzJdKSkge1xuICAgICAgICAgICAgICAgICAgICByb3RhdGVBbmdsZXMgPSBsYXN0Um90YXRlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcHJvamVjdGlvblxuICAgICAgICAgICAgICAgIHByb2plY3Rpb24ucm90YXRlKHJvdGF0ZUFuZ2xlcyk7XG4gICAgICAgICAgICAgICAgbGFzdFJvdGF0ZSA9IHJvdGF0ZUFuZ2xlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgem9vbWVkKGV2ZW50Lm9mKHRoaXMsIGFyZ3VtZW50cykpO1xuICAgICAgICB9KTtcblxuICAgICAgICB6b29tc3RhcnRlZChldmVudC5vZih0aGlzLCBhcmd1bWVudHMpKTtcbiAgICB9KVxuICAgIC5vbignem9vbWVuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICBkMy5zZWxlY3QodGhpcykuc3R5bGUoem9vbWVuZFN0eWxlKTtcbiAgICAgICAgem9vbU9uLmNhbGwoem9vbSwgJ3pvb20nLCBudWxsKTtcbiAgICAgICAgem9vbWVuZGVkKGV2ZW50Lm9mKHRoaXMsIGFyZ3VtZW50cykpO1xuICAgICAgICBzeW5jKGdlbywgcHJvamVjdGlvbiwgc3luY0NiKTtcbiAgICB9KVxuICAgIC5vbignem9vbS5yZWRyYXcnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZ2VvLnJlbmRlcigpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gem9vbXN0YXJ0ZWQoZGlzcGF0Y2gpIHtcbiAgICAgICAgaWYoIXpvb21pbmcrKykgZGlzcGF0Y2goe3R5cGU6ICd6b29tc3RhcnQnfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbWVkKGRpc3BhdGNoKSB7XG4gICAgICAgIGRpc3BhdGNoKHt0eXBlOiAnem9vbSd9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tZW5kZWQoZGlzcGF0Y2gpIHtcbiAgICAgICAgaWYoIS0tem9vbWluZykgZGlzcGF0Y2goe3R5cGU6ICd6b29tZW5kJ30pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN5bmNDYihzZXQpIHtcbiAgICAgICAgdmFyIF9yb3RhdGUgPSBwcm9qZWN0aW9uLnJvdGF0ZSgpO1xuICAgICAgICBzZXQoJ3Byb2plY3Rpb24ucm90YXRpb24ubG9uJywgLV9yb3RhdGVbMF0pO1xuICAgICAgICBzZXQoJ3Byb2plY3Rpb24ucm90YXRpb24ubGF0JywgLV9yb3RhdGVbMV0pO1xuICAgIH1cblxuICAgIHJldHVybiBkMy5yZWJpbmQoem9vbSwgZXZlbnQsICdvbicpO1xufVxuXG4vLyAtLSBoZWxwZXIgZnVuY3Rpb25zIGZvciB6b29tQ2xpcHBlZFxuXG5mdW5jdGlvbiBwb3NpdGlvbihwcm9qZWN0aW9uLCBwb2ludCkge1xuICAgIHZhciBzcGhlcmljYWwgPSBwcm9qZWN0aW9uLmludmVydChwb2ludCk7XG4gICAgcmV0dXJuIHNwaGVyaWNhbCAmJiBpc0Zpbml0ZShzcGhlcmljYWxbMF0pICYmIGlzRmluaXRlKHNwaGVyaWNhbFsxXSkgJiYgY2FydGVzaWFuKHNwaGVyaWNhbCk7XG59XG5cbmZ1bmN0aW9uIHF1YXRlcm5pb25Gcm9tRXVsZXIoZXVsZXIpIHtcbiAgICB2YXIgbGFtYmRhID0gMC41ICogZXVsZXJbMF0gKiByYWRpYW5zLFxuICAgICAgICBwaGkgPSAwLjUgKiBldWxlclsxXSAqIHJhZGlhbnMsXG4gICAgICAgIGdhbW1hID0gMC41ICogZXVsZXJbMl0gKiByYWRpYW5zLFxuICAgICAgICBzaW5MYW1iZGEgPSBNYXRoLnNpbihsYW1iZGEpLCBjb3NMYW1iZGEgPSBNYXRoLmNvcyhsYW1iZGEpLFxuICAgICAgICBzaW5QaGkgPSBNYXRoLnNpbihwaGkpLCBjb3NQaGkgPSBNYXRoLmNvcyhwaGkpLFxuICAgICAgICBzaW5HYW1tYSA9IE1hdGguc2luKGdhbW1hKSwgY29zR2FtbWEgPSBNYXRoLmNvcyhnYW1tYSk7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgY29zTGFtYmRhICogY29zUGhpICogY29zR2FtbWEgKyBzaW5MYW1iZGEgKiBzaW5QaGkgKiBzaW5HYW1tYSxcbiAgICAgICAgc2luTGFtYmRhICogY29zUGhpICogY29zR2FtbWEgLSBjb3NMYW1iZGEgKiBzaW5QaGkgKiBzaW5HYW1tYSxcbiAgICAgICAgY29zTGFtYmRhICogc2luUGhpICogY29zR2FtbWEgKyBzaW5MYW1iZGEgKiBjb3NQaGkgKiBzaW5HYW1tYSxcbiAgICAgICAgY29zTGFtYmRhICogY29zUGhpICogc2luR2FtbWEgLSBzaW5MYW1iZGEgKiBzaW5QaGkgKiBjb3NHYW1tYVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIG11bHRpcGx5KGEsIGIpIHtcbiAgICB2YXIgYTAgPSBhWzBdLCBhMSA9IGFbMV0sIGEyID0gYVsyXSwgYTMgPSBhWzNdLFxuICAgICAgICBiMCA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107XG4gICAgcmV0dXJuIFtcbiAgICAgICAgYTAgKiBiMCAtIGExICogYjEgLSBhMiAqIGIyIC0gYTMgKiBiMyxcbiAgICAgICAgYTAgKiBiMSArIGExICogYjAgKyBhMiAqIGIzIC0gYTMgKiBiMixcbiAgICAgICAgYTAgKiBiMiAtIGExICogYjMgKyBhMiAqIGIwICsgYTMgKiBiMSxcbiAgICAgICAgYTAgKiBiMyArIGExICogYjIgLSBhMiAqIGIxICsgYTMgKiBiMFxuICAgIF07XG59XG5cbmZ1bmN0aW9uIHJvdGF0ZUJldHdlZW4oYSwgYikge1xuICAgIGlmKCFhIHx8ICFiKSByZXR1cm47XG4gICAgdmFyIGF4aXMgPSBjcm9zcyhhLCBiKSxcbiAgICAgICAgbm9ybSA9IE1hdGguc3FydChkb3QoYXhpcywgYXhpcykpLFxuICAgICAgICBoYWxmZ2FtbWEgPSAwLjUgKiBNYXRoLmFjb3MoTWF0aC5tYXgoLTEsIE1hdGgubWluKDEsIGRvdChhLCBiKSkpKSxcbiAgICAgICAgayA9IE1hdGguc2luKGhhbGZnYW1tYSkgLyBub3JtO1xuICAgIHJldHVybiBub3JtICYmIFtNYXRoLmNvcyhoYWxmZ2FtbWEpLCBheGlzWzJdICogaywgLWF4aXNbMV0gKiBrLCBheGlzWzBdICoga107XG59XG5cbi8vIGlucHV0OlxuLy8gICByb3RhdGVBbmdsZXM6IGEgY2FsY3VsYXRlZCBzZXQgb2YgRXVsZXIgYW5nbGVzXG4vLyAgIHB0OiBhIHBvaW50IChjYXJ0ZXNpYW4gaW4gMy1zcGFjZSkgdG8ga2VlcCBmaXhlZFxuLy8gICByb2xsMDogYW4gaW5pdGlhbCByb2xsLCB0byBiZSBwcmVzZXJ2ZWRcbi8vIG91dHB1dDpcbi8vICAgYSBzZXQgb2YgRXVsZXIgYW5nbGVzIHRoYXQgcHJlc2VydmUgdGhlIHByb2plY3Rpb24gb2YgcHRcbi8vICAgICBidXQgc2V0IHJvbGwgKG91dHB1dFsyXSkgZXF1YWwgdG8gcm9sbDBcbi8vICAgICBub3RlIHRoYXQgdGhpcyBkb2Vzbid0IGRlcGVuZCBvbiB0aGUgcGFydGljdWxhciBwcm9qZWN0aW9uLFxuLy8gICAgIGp1c3Qgb24gdGhlIHJvdGF0aW9uIGFuZ2xlc1xuZnVuY3Rpb24gdW5Sb2xsKHJvdGF0ZUFuZ2xlcywgcHQsIGxhc3RSb3RhdGUpIHtcbiAgICAvLyBjYWxjdWxhdGUgdGhlIGZpeGVkIHBvaW50IHRyYW5zZm9ybWVkIGJ5IHRoZXNlIEV1bGVyIGFuZ2xlc1xuICAgIC8vIGJ1dCB3aXRoIHRoZSBkZXNpcmVkIHJvbGwgdW5kb25lXG4gICAgdmFyIHB0Um90YXRlZCA9IHJvdGF0ZUNhcnRlc2lhbihwdCwgMiwgcm90YXRlQW5nbGVzWzBdKTtcbiAgICBwdFJvdGF0ZWQgPSByb3RhdGVDYXJ0ZXNpYW4ocHRSb3RhdGVkLCAxLCByb3RhdGVBbmdsZXNbMV0pO1xuICAgIHB0Um90YXRlZCA9IHJvdGF0ZUNhcnRlc2lhbihwdFJvdGF0ZWQsIDAsIHJvdGF0ZUFuZ2xlc1syXSAtIGxhc3RSb3RhdGVbMl0pO1xuXG4gICAgdmFyIHggPSBwdFswXSxcbiAgICAgICAgeSA9IHB0WzFdLFxuICAgICAgICB6ID0gcHRbMl0sXG4gICAgICAgIGYgPSBwdFJvdGF0ZWRbMF0sXG4gICAgICAgIGcgPSBwdFJvdGF0ZWRbMV0sXG4gICAgICAgIGggPSBwdFJvdGF0ZWRbMl0sXG5cbiAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBlc3NlbnRpYWxseSBzb2x2ZXM6XG4gICAgICAgIC8vIHB0Um90YXRlZCA9IHJvdGF0ZUNhcnRlc2lhbihyb3RhdGVDYXJ0ZXNpYW4ocHQsIDIsIG5ld1lhdyksIDEsIG5ld1BpdGNoKVxuICAgICAgICAvLyBmb3IgbmV3WWF3IGFuZCBuZXdQaXRjaCwgYXMgYmVzdCBpdCBjYW5cbiAgICAgICAgdGhldGEgPSBNYXRoLmF0YW4yKHksIHgpICogZGVncmVlcyxcbiAgICAgICAgYSA9IE1hdGguc3FydCh4ICogeCArIHkgKiB5KSxcbiAgICAgICAgYixcbiAgICAgICAgbmV3WWF3MTtcblxuICAgIGlmKE1hdGguYWJzKGcpID4gYSkge1xuICAgICAgICBuZXdZYXcxID0gKGcgPiAwID8gOTAgOiAtOTApIC0gdGhldGE7XG4gICAgICAgIGIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1lhdzEgPSBNYXRoLmFzaW4oZyAvIGEpICogZGVncmVlcyAtIHRoZXRhO1xuICAgICAgICBiID0gTWF0aC5zcXJ0KGEgKiBhIC0gZyAqIGcpO1xuICAgIH1cblxuICAgIHZhciBuZXdZYXcyID0gMTgwIC0gbmV3WWF3MSAtIDIgKiB0aGV0YSxcbiAgICAgICAgbmV3UGl0Y2gxID0gKE1hdGguYXRhbjIoaCwgZikgLSBNYXRoLmF0YW4yKHosIGIpKSAqIGRlZ3JlZXMsXG4gICAgICAgIG5ld1BpdGNoMiA9IChNYXRoLmF0YW4yKGgsIGYpIC0gTWF0aC5hdGFuMih6LCAtYikpICogZGVncmVlcztcblxuICAgIC8vIHdoaWNoIGlzIGNsb3Nlc3QgdG8gbGFzdFJvdGF0ZVswLDFdOiBuZXdZYXcvUGl0Y2ggb3IgbmV3WWF3Mi9QaXRjaDI/XG4gICAgdmFyIGRpc3QxID0gYW5nbGVEaXN0YW5jZShsYXN0Um90YXRlWzBdLCBsYXN0Um90YXRlWzFdLCBuZXdZYXcxLCBuZXdQaXRjaDEpLFxuICAgICAgICBkaXN0MiA9IGFuZ2xlRGlzdGFuY2UobGFzdFJvdGF0ZVswXSwgbGFzdFJvdGF0ZVsxXSwgbmV3WWF3MiwgbmV3UGl0Y2gyKTtcblxuICAgIGlmKGRpc3QxIDw9IGRpc3QyKSByZXR1cm4gW25ld1lhdzEsIG5ld1BpdGNoMSwgbGFzdFJvdGF0ZVsyXV07XG4gICAgZWxzZSByZXR1cm4gW25ld1lhdzIsIG5ld1BpdGNoMiwgbGFzdFJvdGF0ZVsyXV07XG59XG5cbmZ1bmN0aW9uIGFuZ2xlRGlzdGFuY2UoeWF3MCwgcGl0Y2gwLCB5YXcxLCBwaXRjaDEpIHtcbiAgICB2YXIgZFlhdyA9IGFuZ2xlTW9kKHlhdzEgLSB5YXcwKSxcbiAgICAgICAgZFBpdGNoID0gYW5nbGVNb2QocGl0Y2gxIC0gcGl0Y2gwKTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KGRZYXcgKiBkWWF3ICsgZFBpdGNoICogZFBpdGNoKTtcbn1cblxuLy8gcmVkdWNlIGFuIGFuZ2xlIGluIGRlZ3JlZXMgdG8gWy0xODAsMTgwXVxuZnVuY3Rpb24gYW5nbGVNb2QoYW5nbGUpIHtcbiAgICByZXR1cm4gKGFuZ2xlICUgMzYwICsgNTQwKSAlIDM2MCAtIDE4MDtcbn1cblxuLy8gcm90YXRlIGEgY2FydGVzaWFuIHZlY3RvclxuLy8gYXhpcyBpcyAwICh4KSwgMSAoeSksIG9yIDIgKHopXG4vLyBhbmdsZSBpcyBpbiBkZWdyZWVzXG5mdW5jdGlvbiByb3RhdGVDYXJ0ZXNpYW4odmVjdG9yLCBheGlzLCBhbmdsZSkge1xuICAgIHZhciBhbmdsZVJhZHMgPSBhbmdsZSAqIHJhZGlhbnMsXG4gICAgICAgIHZlY3Rvck91dCA9IHZlY3Rvci5zbGljZSgpLFxuICAgICAgICBheDEgPSAoYXhpcyA9PT0gMCkgPyAxIDogMCxcbiAgICAgICAgYXgyID0gKGF4aXMgPT09IDIpID8gMSA6IDIsXG4gICAgICAgIGNvc2EgPSBNYXRoLmNvcyhhbmdsZVJhZHMpLFxuICAgICAgICBzaW5hID0gTWF0aC5zaW4oYW5nbGVSYWRzKTtcblxuICAgIHZlY3Rvck91dFtheDFdID0gdmVjdG9yW2F4MV0gKiBjb3NhIC0gdmVjdG9yW2F4Ml0gKiBzaW5hO1xuICAgIHZlY3Rvck91dFtheDJdID0gdmVjdG9yW2F4Ml0gKiBjb3NhICsgdmVjdG9yW2F4MV0gKiBzaW5hO1xuXG4gICAgcmV0dXJuIHZlY3Rvck91dDtcbn1cbmZ1bmN0aW9uIGV1bGVyRnJvbVF1YXRlcm5pb24ocSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIE1hdGguYXRhbjIoMiAqIChxWzBdICogcVsxXSArIHFbMl0gKiBxWzNdKSwgMSAtIDIgKiAocVsxXSAqIHFbMV0gKyBxWzJdICogcVsyXSkpICogZGVncmVlcyxcbiAgICAgICAgTWF0aC5hc2luKE1hdGgubWF4KC0xLCBNYXRoLm1pbigxLCAyICogKHFbMF0gKiBxWzJdIC0gcVszXSAqIHFbMV0pKSkpICogZGVncmVlcyxcbiAgICAgICAgTWF0aC5hdGFuMigyICogKHFbMF0gKiBxWzNdICsgcVsxXSAqIHFbMl0pLCAxIC0gMiAqIChxWzJdICogcVsyXSArIHFbM10gKiBxWzNdKSkgKiBkZWdyZWVzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY2FydGVzaWFuKHNwaGVyaWNhbCkge1xuICAgIHZhciBsYW1iZGEgPSBzcGhlcmljYWxbMF0gKiByYWRpYW5zLFxuICAgICAgICBwaGkgPSBzcGhlcmljYWxbMV0gKiByYWRpYW5zLFxuICAgICAgICBjb3NQaGkgPSBNYXRoLmNvcyhwaGkpO1xuICAgIHJldHVybiBbXG4gICAgICAgIGNvc1BoaSAqIE1hdGguY29zKGxhbWJkYSksXG4gICAgICAgIGNvc1BoaSAqIE1hdGguc2luKGxhbWJkYSksXG4gICAgICAgIE1hdGguc2luKHBoaSlcbiAgICBdO1xufVxuXG5mdW5jdGlvbiBkb3QoYSwgYikge1xuICAgIHZhciBzID0gMDtcbiAgICBmb3IodmFyIGkgPSAwLCBuID0gYS5sZW5ndGg7IGkgPCBuOyArK2kpIHMgKz0gYVtpXSAqIGJbaV07XG4gICAgcmV0dXJuIHM7XG59XG5cbmZ1bmN0aW9uIGNyb3NzKGEsIGIpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBhWzFdICogYlsyXSAtIGFbMl0gKiBiWzFdLFxuICAgICAgICBhWzJdICogYlswXSAtIGFbMF0gKiBiWzJdLFxuICAgICAgICBhWzBdICogYlsxXSAtIGFbMV0gKiBiWzBdXG4gICAgXTtcbn1cblxuLy8gTGlrZSBkMy5kaXNwYXRjaCwgYnV0IGZvciBjdXN0b20gZXZlbnRzIGFic3RyYWN0aW5nIG5hdGl2ZSBVSSBldmVudHMuIFRoZXNlXG4vLyBldmVudHMgaGF2ZSBhIHRhcmdldCBjb21wb25lbnQgKHN1Y2ggYXMgYSBicnVzaCksIGEgdGFyZ2V0IGVsZW1lbnQgKHN1Y2ggYXNcbi8vIHRoZSBzdmc6ZyBlbGVtZW50IGNvbnRhaW5pbmcgdGhlIGJydXNoKSBhbmQgdGhlIHN0YW5kYXJkIGFyZ3VtZW50cyBgZGAgKHRoZVxuLy8gdGFyZ2V0IGVsZW1lbnQncyBkYXRhKSBhbmQgYGlgICh0aGUgc2VsZWN0aW9uIGluZGV4IG9mIHRoZSB0YXJnZXQgZWxlbWVudCkuXG5mdW5jdGlvbiBkM19ldmVudERpc3BhdGNoKHRhcmdldCkge1xuICAgIHZhciBpID0gMCxcbiAgICAgICAgbiA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgIGFyZ3VtZW50eiA9IFtdO1xuXG4gICAgd2hpbGUoKytpIDwgbikgYXJndW1lbnR6LnB1c2goYXJndW1lbnRzW2ldKTtcblxuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoLmFwcGx5KG51bGwsIGFyZ3VtZW50eik7XG5cbiAgICAvLyBDcmVhdGVzIGEgZGlzcGF0Y2ggY29udGV4dCBmb3IgdGhlIHNwZWNpZmllZCBgdGhpemAgKHR5cGljYWxseSwgdGhlIHRhcmdldFxuICAgIC8vIERPTSBlbGVtZW50IHRoYXQgcmVjZWl2ZWQgdGhlIHNvdXJjZSBldmVudCkgYW5kIGBhcmd1bWVudHpgICh0eXBpY2FsbHksIHRoZVxuICAgIC8vIGRhdGEgYGRgIGFuZCBpbmRleCBgaWAgb2YgdGhlIHRhcmdldCBlbGVtZW50KS4gVGhlIHJldHVybmVkIGZ1bmN0aW9uIGNhbiBiZVxuICAgIC8vIHVzZWQgdG8gZGlzcGF0Y2ggYW4gZXZlbnQgdG8gYW55IHJlZ2lzdGVyZWQgbGlzdGVuZXJzOyB0aGUgZnVuY3Rpb24gdGFrZXMgYVxuICAgIC8vIHNpbmdsZSBhcmd1bWVudCBhcyBpbnB1dCwgYmVpbmcgdGhlIGV2ZW50IHRvIGRpc3BhdGNoLiBUaGUgZXZlbnQgbXVzdCBoYXZlXG4gICAgLy8gYSBcInR5cGVcIiBhdHRyaWJ1dGUgd2hpY2ggY29ycmVzcG9uZHMgdG8gYSB0eXBlIHJlZ2lzdGVyZWQgaW4gdGhlXG4gICAgLy8gY29uc3RydWN0b3IuIFRoaXMgY29udGV4dCB3aWxsIGF1dG9tYXRpY2FsbHkgcG9wdWxhdGUgdGhlIFwic291cmNlRXZlbnRcIiBhbmRcbiAgICAvLyBcInRhcmdldFwiIGF0dHJpYnV0ZXMgb2YgdGhlIGV2ZW50LCBhcyB3ZWxsIGFzIHNldHRpbmcgdGhlIGBkMy5ldmVudGAgZ2xvYmFsXG4gICAgLy8gZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGUgbm90aWZpY2F0aW9uLlxuICAgIGRpc3BhdGNoLm9mID0gZnVuY3Rpb24odGhpeiwgYXJndW1lbnR6KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihlMSkge1xuICAgICAgICAgICAgdmFyIGUwO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBlMCA9IGUxLnNvdXJjZUV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgICAgICAgZTEudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICAgICAgICAgIGQzLmV2ZW50ID0gZTE7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2hbZTEudHlwZV0uYXBwbHkodGhpeiwgYXJndW1lbnR6KTtcbiAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQgPSBlMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRpc3BhdGNoO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi9yZWdpc3RyeScpO1xudmFyIFNVQlBMT1RfUEFUVEVSTiA9IHJlcXVpcmUoJy4vY2FydGVzaWFuL2NvbnN0YW50cycpLlNVQlBMT1RfUEFUVEVSTjtcblxuLyoqXG4gKiBHZXQgY2FsY2RhdGEgdHJhY2UocykgYXNzb2NpYXRlZCB3aXRoIGEgZ2l2ZW4gc3VicGxvdFxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGNhbGNEYXRhOiBhcyBpbiBnZC5jYWxjZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IHR5cGU6IHN1YnBsb3QgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IHN1YnBsb3RJZDogc3VicGxvdCBpZCB0byBsb29rIGZvclxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBhcnJheSBvZiBjYWxjZGF0YSB0cmFjZXNcbiAqL1xuZXhwb3J0cy5nZXRTdWJwbG90Q2FsY0RhdGEgPSBmdW5jdGlvbihjYWxjRGF0YSwgdHlwZSwgc3VicGxvdElkKSB7XG4gICAgdmFyIGJhc2VQbG90TW9kdWxlID0gUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeVt0eXBlXTtcbiAgICBpZighYmFzZVBsb3RNb2R1bGUpIHJldHVybiBbXTtcblxuICAgIHZhciBhdHRyID0gYmFzZVBsb3RNb2R1bGUuYXR0cjtcbiAgICB2YXIgc3VicGxvdENhbGNEYXRhID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNEYXRhW2ldO1xuICAgICAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2VbYXR0cl0gPT09IHN1YnBsb3RJZCkgc3VicGxvdENhbGNEYXRhLnB1c2goY2FsY1RyYWNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VicGxvdENhbGNEYXRhO1xufTtcbi8qKlxuICogR2V0IGNhbGNkYXRhIHRyYWNlKHMpIHRoYXQgY2FuIGJlIHBsb3R0ZWQgd2l0aCBhIGdpdmVuIG1vZHVsZVxuICogTk9URTogdGhpcyBpc24ndCBuZWNlc3NhcmlseSBqdXN0IGV4YWN0bHkgbWF0Y2hpbmcgdHJhY2UgdHlwZSxcbiAqIGlmIG11bHRpcGxlIHRyYWNlIHR5cGVzIHVzZSB0aGUgc2FtZSBwbG90dGluZyByb3V0aW5lLCB0aGV5IHdpbGwgYmVcbiAqIGNvbGxlY3RlZCBoZXJlLlxuICogSW4gb3JkZXIgdG8gbm90IHBsb3QgdGhlIHNhbWUgdGhpbmcgbXVsdGlwbGUgdGltZXMsIHdlIHJldHVybiB0d28gYXJyYXlzLFxuICogdGhlIGNhbGNkYXRhIHdlICp3aWxsKiBwbG90IHdpdGggdGhpcyBtb2R1bGUsIGFuZCB0aGUgb25lcyB3ZSAqd29uJ3QqXG4gKlxuICogQHBhcmFtIHthcnJheX0gY2FsY2RhdGE6IGFzIGluIGdkLmNhbGNkYXRhXG4gKiBAcGFyYW0ge29iamVjdHxzdHJpbmd8Zm59IGFyZzE6XG4gKiAgdGhlIHBsb3R0aW5nIG1vZHVsZSwgb3IgaXRzIG5hbWUsIG9yIGl0cyBwbG90IG1ldGhvZFxuICpcbiAqIEByZXR1cm4ge2FycmF5W2FycmF5XX0gW2ZvdW5kQ2FsY2RhdGEsIHJlbWFpbmluZ0NhbGNkYXRhXVxuICovXG5leHBvcnRzLmdldE1vZHVsZUNhbGNEYXRhID0gZnVuY3Rpb24oY2FsY2RhdGEsIGFyZzEpIHtcbiAgICB2YXIgbW9kdWxlQ2FsY0RhdGEgPSBbXTtcbiAgICB2YXIgcmVtYWluaW5nQ2FsY0RhdGEgPSBbXTtcblxuICAgIHZhciBwbG90TWV0aG9kO1xuICAgIGlmKHR5cGVvZiBhcmcxID09PSAnc3RyaW5nJykge1xuICAgICAgICBwbG90TWV0aG9kID0gUmVnaXN0cnkuZ2V0TW9kdWxlKGFyZzEpLnBsb3Q7XG4gICAgfSBlbHNlIGlmKHR5cGVvZiBhcmcxID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHBsb3RNZXRob2QgPSBhcmcxO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBsb3RNZXRob2QgPSBhcmcxLnBsb3Q7XG4gICAgfVxuICAgIGlmKCFwbG90TWV0aG9kKSB7XG4gICAgICAgIHJldHVybiBbbW9kdWxlQ2FsY0RhdGEsIGNhbGNkYXRhXTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbaV07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICAvLyBOLkIuICdsZWdlbmRvbmx5JyB0cmFjZXMgZG8gbm90IG1ha2UgaXQgcGFzdCBoZXJlXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgIT09IHRydWUpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIGdyb3VwIGNhbGNkYXRhIHRyYWNlIG5vdCBieSAnbW9kdWxlJyAoYXMgdGhlIG5hbWUgb2YgdGhpcyBmdW5jdGlvblxuICAgICAgICAvLyB3b3VsZCBzdWdnZXN0KSwgYnV0IGJ5ICdtb2R1bGUgcGxvdCBtZXRob2QnIHNvIHRoYXQgaWYgc29tZSB0cmFjZXNcbiAgICAgICAgLy8gc2hhcmUgdGhlIHNhbWUgbW9kdWxlIHBsb3QgbWV0aG9kIChlLmcuIGJhciBhbmQgaGlzdG9ncmFtKSwgd2VcbiAgICAgICAgLy8gb25seSBjYWxsIGl0IG9uZSFcbiAgICAgICAgaWYodHJhY2UuX21vZHVsZS5wbG90ID09PSBwbG90TWV0aG9kKSB7XG4gICAgICAgICAgICBtb2R1bGVDYWxjRGF0YS5wdXNoKGNkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbWFpbmluZ0NhbGNEYXRhLnB1c2goY2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFttb2R1bGVDYWxjRGF0YSwgcmVtYWluaW5nQ2FsY0RhdGFdO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGRhdGEgdHJhY2UocykgYXNzb2NpYXRlZCB3aXRoIGEgZ2l2ZW4gc3VicGxvdC5cbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBkYXRhICBwbG90bHkgZnVsbCBkYXRhIGFycmF5LlxuICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgc3VicGxvdCB0eXBlIHRvIGxvb2sgZm9yLlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YnBsb3RJZCBzdWJwbG90IGlkIHRvIGxvb2sgZm9yLlxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBsaXN0IG9mIHRyYWNlIG9iamVjdHMuXG4gKlxuICovXG5leHBvcnRzLmdldFN1YnBsb3REYXRhID0gZnVuY3Rpb24gZ2V0U3VicGxvdERhdGEoZGF0YSwgdHlwZSwgc3VicGxvdElkKSB7XG4gICAgaWYoIVJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnlbdHlwZV0pIHJldHVybiBbXTtcblxuICAgIHZhciBhdHRyID0gUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeVt0eXBlXS5hdHRyO1xuICAgIHZhciBzdWJwbG90RGF0YSA9IFtdO1xuICAgIHZhciB0cmFjZSwgc3VicGxvdFgsIHN1YnBsb3RZO1xuXG4gICAgaWYodHlwZSA9PT0gJ2dsMmQnKSB7XG4gICAgICAgIHZhciBzcG1hdGNoID0gc3VicGxvdElkLm1hdGNoKFNVQlBMT1RfUEFUVEVSTik7XG4gICAgICAgIHN1YnBsb3RYID0gJ3gnICsgc3BtYXRjaFsxXTtcbiAgICAgICAgc3VicGxvdFkgPSAneScgKyBzcG1hdGNoWzJdO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gZGF0YVtpXTtcblxuICAgICAgICBpZih0eXBlID09PSAnZ2wyZCcgJiYgUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2dsMmQnKSkge1xuICAgICAgICAgICAgaWYodHJhY2VbYXR0clswXV0gPT09IHN1YnBsb3RYICYmIHRyYWNlW2F0dHJbMV1dID09PSBzdWJwbG90WSkge1xuICAgICAgICAgICAgICAgIHN1YnBsb3REYXRhLnB1c2godHJhY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYodHJhY2VbYXR0cl0gPT09IHN1YnBsb3RJZCkgc3VicGxvdERhdGEucHVzaCh0cmFjZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3VicGxvdERhdGE7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtb3VzZUNoYW5nZSA9IHJlcXVpcmUoJ21vdXNlLWNoYW5nZScpO1xudmFyIG1vdXNlV2hlZWwgPSByZXF1aXJlKCdtb3VzZS13aGVlbCcpO1xudmFyIG1vdXNlT2Zmc2V0ID0gcmVxdWlyZSgnbW91c2UtZXZlbnQtb2Zmc2V0Jyk7XG52YXIgY2FydGVzaWFuQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIGhhc1Bhc3NpdmUgPSByZXF1aXJlKCdoYXMtcGFzc2l2ZS1ldmVudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVDYW1lcmE7XG5cbmZ1bmN0aW9uIENhbWVyYTJEKGVsZW1lbnQsIHBsb3QpIHtcbiAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMucGxvdCA9IHBsb3Q7XG4gICAgdGhpcy5tb3VzZUxpc3RlbmVyID0gbnVsbDtcbiAgICB0aGlzLndoZWVsTGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMubGFzdElucHV0VGltZSA9IERhdGUubm93KCk7XG4gICAgdGhpcy5sYXN0UG9zID0gWzAsIDBdO1xuICAgIHRoaXMuYm94RW5hYmxlZCA9IGZhbHNlO1xuICAgIHRoaXMuYm94SW5pdGVkID0gZmFsc2U7XG4gICAgdGhpcy5ib3hTdGFydCA9IFswLCAwXTtcbiAgICB0aGlzLmJveEVuZCA9IFswLCAwXTtcbiAgICB0aGlzLmRyYWdTdGFydCA9IFswLCAwXTtcbn1cblxuXG5mdW5jdGlvbiBjcmVhdGVDYW1lcmEoc2NlbmUpIHtcbiAgICB2YXIgZWxlbWVudCA9IHNjZW5lLm1vdXNlQ29udGFpbmVyLFxuICAgICAgICBwbG90ID0gc2NlbmUuZ2xwbG90LFxuICAgICAgICByZXN1bHQgPSBuZXcgQ2FtZXJhMkQoZWxlbWVudCwgcGxvdCk7XG5cbiAgICBmdW5jdGlvbiB1blNldEF1dG9SYW5nZSgpIHtcbiAgICAgICAgc2NlbmUueGF4aXMuYXV0b3JhbmdlID0gZmFsc2U7XG4gICAgICAgIHNjZW5lLnlheGlzLmF1dG9yYW5nZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFN1YnBsb3RDb25zdHJhaW50KCkge1xuICAgICAgICAvLyBub3RlOiB0aGlzIGFzc3VtZXMgd2Ugb25seSBoYXZlIG9uZSB4IGFuZCBvbmUgeSBheGlzIG9uIHRoaXMgc3VicGxvdFxuICAgICAgICAvLyB3aGVuIHRoaXMgY29uc3RyYWludCBpcyBsaWZ0ZWQgdGhpcyBibG9jayB3b24ndCBtYWtlIHNlbnNlXG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IHNjZW5lLmdyYXBoRGl2Ll9mdWxsTGF5b3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcztcbiAgICAgICAgdmFyIHhhSWQgPSBzY2VuZS54YXhpcy5faWQ7XG4gICAgICAgIHZhciB5YUlkID0gc2NlbmUueWF4aXMuX2lkO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29uc3RyYWludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGNvbnN0cmFpbnRzW2ldW3hhSWRdICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGlmKGNvbnN0cmFpbnRzW2ldW3lhSWRdICE9PSAtMSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJlc3VsdC5tb3VzZUxpc3RlbmVyID0gbW91c2VDaGFuZ2UoZWxlbWVudCwgaGFuZGxlSW50ZXJhY3Rpb24pO1xuXG4gICAgLy8gZW5hYmxlIHNpbXBsZSB0b3VjaCBpbnRlcmFjdGlvbnNcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBmdW5jdGlvbihldikge1xuICAgICAgICB2YXIgeHkgPSBtb3VzZU9mZnNldChldi5jaGFuZ2VkVG91Y2hlc1swXSwgZWxlbWVudCk7XG4gICAgICAgIGhhbmRsZUludGVyYWN0aW9uKDAsIHh5WzBdLCB4eVsxXSk7XG4gICAgICAgIGhhbmRsZUludGVyYWN0aW9uKDEsIHh5WzBdLCB4eVsxXSk7XG5cbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9LCBoYXNQYXNzaXZlID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKTtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KTtcbiAgICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMSwgeHlbMF0sIHh5WzFdKTtcblxuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGhhc1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpO1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBmdW5jdGlvbihldikge1xuICAgICAgICBoYW5kbGVJbnRlcmFjdGlvbigwLCByZXN1bHQubGFzdFBvc1swXSwgcmVzdWx0Lmxhc3RQb3NbMV0pO1xuXG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSwgaGFzUGFzc2l2ZSA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSk7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVJbnRlcmFjdGlvbihidXR0b25zLCB4LCB5KSB7XG4gICAgICAgIHZhciBkYXRhQm94ID0gc2NlbmUuY2FsY0RhdGFCb3goKSxcbiAgICAgICAgICAgIHZpZXdCb3ggPSBwbG90LnZpZXdCb3g7XG5cbiAgICAgICAgdmFyIGxhc3RYID0gcmVzdWx0Lmxhc3RQb3NbMF0sXG4gICAgICAgICAgICBsYXN0WSA9IHJlc3VsdC5sYXN0UG9zWzFdO1xuXG4gICAgICAgIHZhciBNSU5EUkFHID0gY2FydGVzaWFuQ29uc3RhbnRzLk1JTkRSQUcgKiBwbG90LnBpeGVsUmF0aW87XG4gICAgICAgIHZhciBNSU5aT09NID0gY2FydGVzaWFuQ29uc3RhbnRzLk1JTlpPT00gKiBwbG90LnBpeGVsUmF0aW87XG5cbiAgICAgICAgdmFyIGR4LCBkeTtcblxuICAgICAgICB4ICo9IHBsb3QucGl4ZWxSYXRpbztcbiAgICAgICAgeSAqPSBwbG90LnBpeGVsUmF0aW87XG5cbiAgICAgICAgLy8gbW91c2VDaGFuZ2UgZ2l2ZXMgeSBhYm91dCB0b3A7IGNvbnZlcnQgdG8gYWJvdXQgYm90dG9tXG4gICAgICAgIHkgPSAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pIC0geTtcblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGVSYW5nZShpMCwgc3RhcnQsIGVuZCkge1xuICAgICAgICAgICAgdmFyIHJhbmdlMCA9IE1hdGgubWluKHN0YXJ0LCBlbmQpLFxuICAgICAgICAgICAgICAgIHJhbmdlMSA9IE1hdGgubWF4KHN0YXJ0LCBlbmQpO1xuXG4gICAgICAgICAgICBpZihyYW5nZTAgIT09IHJhbmdlMSkge1xuICAgICAgICAgICAgICAgIGRhdGFCb3hbaTBdID0gcmFuZ2UwO1xuICAgICAgICAgICAgICAgIGRhdGFCb3hbaTAgKyAyXSA9IHJhbmdlMTtcbiAgICAgICAgICAgICAgICByZXN1bHQuZGF0YUJveCA9IGRhdGFCb3g7XG4gICAgICAgICAgICAgICAgc2NlbmUuc2V0UmFuZ2VzKGRhdGFCb3gpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc2NlbmUuc2VsZWN0Qm94LnNlbGVjdEJveCA9IFswLCAwLCAxLCAxXTtcbiAgICAgICAgICAgICAgICBzY2VuZS5nbHBsb3Quc2V0RGlydHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaChzY2VuZS5mdWxsTGF5b3V0LmRyYWdtb2RlKSB7XG4gICAgICAgICAgICBjYXNlICd6b29tJzpcbiAgICAgICAgICAgICAgICBpZihidXR0b25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhWCA9IHggL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2aWV3Qm94WzJdIC0gdmlld0JveFswXSkgKiAoZGF0YUJveFsyXSAtIGRhdGFCb3hbMF0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbMF07XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhWSA9IHkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2aWV3Qm94WzNdIC0gdmlld0JveFsxXSkgKiAoZGF0YUJveFszXSAtIGRhdGFCb3hbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbMV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoIXJlc3VsdC5ib3hJbml0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hTdGFydFswXSA9IGRhdGFYO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveFN0YXJ0WzFdID0gZGF0YVk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZHJhZ1N0YXJ0WzBdID0geDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5kcmFnU3RhcnRbMV0gPSB5O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFswXSA9IGRhdGFYO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzFdID0gZGF0YVk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gd2UgbmVlZCB0byBtYXJrIHRoZSBib3ggYXMgaW5pdGlhbGl6ZWQgcmlnaHQgYXdheVxuICAgICAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IHdlIGNhbiB0ZWxsIHRoZSBzdGFydCBhbmQgZW5kIHBvaW50cyBhcGFydFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94SW5pdGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBidXQgZG9uJ3QgYWN0dWFsbHkgZW5hYmxlIHRoZSBib3ggdW50aWwgdGhlIGN1cnNvciBtb3Zlc1xuICAgICAgICAgICAgICAgICAgICBpZighcmVzdWx0LmJveEVuYWJsZWQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveFN0YXJ0WzBdICE9PSByZXN1bHQuYm94RW5kWzBdIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94U3RhcnRbMV0gIT09IHJlc3VsdC5ib3hFbmRbMV0pXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gY29uc3RyYWluIGFzcGVjdCByYXRpbyBpZiB0aGUgYXhlcyByZXF1aXJlIGl0XG4gICAgICAgICAgICAgICAgICAgIHZhciBzbWFsbER4ID0gTWF0aC5hYnMocmVzdWx0LmRyYWdTdGFydFswXSAtIHgpIDwgTUlOWk9PTTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNtYWxsRHkgPSBNYXRoLmFicyhyZXN1bHQuZHJhZ1N0YXJ0WzFdIC0geSkgPCBNSU5aT09NO1xuICAgICAgICAgICAgICAgICAgICBpZihnZXRTdWJwbG90Q29uc3RyYWludCgpICYmICEoc21hbGxEeCAmJiBzbWFsbER5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZHggPSByZXN1bHQuYm94RW5kWzBdIC0gcmVzdWx0LmJveFN0YXJ0WzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHkgPSByZXN1bHQuYm94RW5kWzFdIC0gcmVzdWx0LmJveFN0YXJ0WzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGR5ZHggPSAoZGF0YUJveFszXSAtIGRhdGFCb3hbMV0pIC8gKGRhdGFCb3hbMl0gLSBkYXRhQm94WzBdKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZHggKiBkeWR4KSA+IE1hdGguYWJzKGR5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMV0gPSByZXN1bHQuYm94U3RhcnRbMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmFicyhkeCkgKiBkeWR4ICogKGR5ID49IDAgPyAxIDogLTEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2wtc2VsZWN0LWJveCBjbGlwcyB0byB0aGUgcGxvdCBhcmVhIGJvdW5kcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGljaCBicmVha3MgdGhlIGF4aXMgY29uc3RyYWludCwgc28gZG9uJ3QgYWxsb3dcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGJveCB0byBnbyBvdXQgb2YgYm91bmRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVzdWx0LmJveEVuZFsxXSA8IGRhdGFCb3hbMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFsxXSA9IGRhdGFCb3hbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMF0gPSByZXN1bHQuYm94U3RhcnRbMF0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRhdGFCb3hbMV0gLSByZXN1bHQuYm94U3RhcnRbMV0pIC8gTWF0aC5hYnMoZHlkeCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYocmVzdWx0LmJveEVuZFsxXSA+IGRhdGFCb3hbM10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFsxXSA9IGRhdGFCb3hbM107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMF0gPSByZXN1bHQuYm94U3RhcnRbMF0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRhdGFCb3hbM10gLSByZXN1bHQuYm94U3RhcnRbMV0pIC8gTWF0aC5hYnMoZHlkeCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFswXSA9IHJlc3VsdC5ib3hTdGFydFswXSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKGR5KSAvIGR5ZHggKiAoZHggPj0gMCA/IDEgOiAtMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihyZXN1bHQuYm94RW5kWzBdIDwgZGF0YUJveFswXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzBdID0gZGF0YUJveFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFsxXSA9IHJlc3VsdC5ib3hTdGFydFsxXSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF0YUJveFswXSAtIHJlc3VsdC5ib3hTdGFydFswXSkgKiBNYXRoLmFicyhkeWR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZihyZXN1bHQuYm94RW5kWzBdID4gZGF0YUJveFsyXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzBdID0gZGF0YUJveFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFsxXSA9IHJlc3VsdC5ib3hTdGFydFsxXSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF0YUJveFsyXSAtIHJlc3VsdC5ib3hTdGFydFswXSkgKiBNYXRoLmFicyhkeWR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGNsYW1wIHNtYWxsIGNoYW5nZXMgdG8gdGhlIG9yaWdpbiBzbyB3ZSBnZXQgMUQgem9vbVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHNtYWxsRHgpIHJlc3VsdC5ib3hFbmRbMF0gPSByZXN1bHQuYm94U3RhcnRbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihzbWFsbER5KSByZXN1bHQuYm94RW5kWzFdID0gcmVzdWx0LmJveFN0YXJ0WzFdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYocmVzdWx0LmJveEVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZHggPSByZXN1bHQuYm94U3RhcnRbMF0gIT09IHJlc3VsdC5ib3hFbmRbMF07XG4gICAgICAgICAgICAgICAgICAgIGR5ID0gcmVzdWx0LmJveFN0YXJ0WzFdICE9PSByZXN1bHQuYm94RW5kWzFdO1xuICAgICAgICAgICAgICAgICAgICBpZihkeCB8fCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZHgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVSYW5nZSgwLCByZXN1bHQuYm94U3RhcnRbMF0sIHJlc3VsdC5ib3hFbmRbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjZW5lLnhheGlzLmF1dG9yYW5nZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVSYW5nZSgxLCByZXN1bHQuYm94U3RhcnRbMV0sIHJlc3VsdC5ib3hFbmRbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjZW5lLnlheGlzLmF1dG9yYW5nZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2NlbmUucmVsYXlvdXRDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2NlbmUuZ2xwbG90LnNldERpcnR5KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEluaXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiBib3ggd2FzIGluaXRlZCBidXQgYnV0dG9uIHJlbGVhc2VkIHRoZW4gLSByZXNldCB0aGUgYm94XG4gICAgICAgICAgICAgICAgZWxzZSBpZihyZXN1bHQuYm94SW5pdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hJbml0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ3Bhbic6XG4gICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYm94SW5pdGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZihidXR0b25zKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFyZXN1bHQucGFubmluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmRyYWdTdGFydFswXSA9IHg7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZHJhZ1N0YXJ0WzFdID0geTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKHJlc3VsdC5kcmFnU3RhcnRbMF0gLSB4KSA8IE1JTkRSQUcpIHggPSByZXN1bHQuZHJhZ1N0YXJ0WzBdO1xuICAgICAgICAgICAgICAgICAgICBpZihNYXRoLmFicyhyZXN1bHQuZHJhZ1N0YXJ0WzFdIC0geSkgPCBNSU5EUkFHKSB5ID0gcmVzdWx0LmRyYWdTdGFydFsxXTtcblxuICAgICAgICAgICAgICAgICAgICBkeCA9IChsYXN0WCAtIHgpICogKGRhdGFCb3hbMl0gLSBkYXRhQm94WzBdKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAocGxvdC52aWV3Qm94WzJdIC0gcGxvdC52aWV3Qm94WzBdKTtcbiAgICAgICAgICAgICAgICAgICAgZHkgPSAobGFzdFkgLSB5KSAqIChkYXRhQm94WzNdIC0gZGF0YUJveFsxXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgKHBsb3Qudmlld0JveFszXSAtIHBsb3Qudmlld0JveFsxXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGF0YUJveFswXSArPSBkeDtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUJveFsyXSArPSBkeDtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUJveFsxXSArPSBkeTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YUJveFszXSArPSBkeTtcblxuICAgICAgICAgICAgICAgICAgICBzY2VuZS5zZXRSYW5nZXMoZGF0YUJveCk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnBhbm5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQubGFzdElucHV0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIHVuU2V0QXV0b1JhbmdlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNjZW5lLmNhbWVyYUNoYW5nZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUuaGFuZGxlQW5ub3RhdGlvbnMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihyZXN1bHQucGFubmluZykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucGFubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBzY2VuZS5yZWxheW91dENhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzdWx0Lmxhc3RQb3NbMF0gPSB4O1xuICAgICAgICByZXN1bHQubGFzdFBvc1sxXSA9IHk7XG4gICAgfVxuXG4gICAgcmVzdWx0LndoZWVsTGlzdGVuZXIgPSBtb3VzZVdoZWVsKGVsZW1lbnQsIGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICBpZighc2NlbmUuc2Nyb2xsWm9vbSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHZhciBkYXRhQm94ID0gc2NlbmUuY2FsY0RhdGFCb3goKSxcbiAgICAgICAgICAgIHZpZXdCb3ggPSBwbG90LnZpZXdCb3g7XG5cbiAgICAgICAgdmFyIGxhc3RYID0gcmVzdWx0Lmxhc3RQb3NbMF0sXG4gICAgICAgICAgICBsYXN0WSA9IHJlc3VsdC5sYXN0UG9zWzFdO1xuXG4gICAgICAgIHZhciBzY2FsZSA9IE1hdGguZXhwKDUuMCAqIGR5IC8gKHZpZXdCb3hbM10gLSB2aWV3Qm94WzFdKSk7XG5cbiAgICAgICAgdmFyIGN4ID0gbGFzdFggL1xuICAgICAgICAgICAgICAgICh2aWV3Qm94WzJdIC0gdmlld0JveFswXSkgKiAoZGF0YUJveFsyXSAtIGRhdGFCb3hbMF0pICtcbiAgICAgICAgICAgIGRhdGFCb3hbMF07XG4gICAgICAgIHZhciBjeSA9IGxhc3RZIC9cbiAgICAgICAgICAgICAgICAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pICogKGRhdGFCb3hbM10gLSBkYXRhQm94WzFdKSArXG4gICAgICAgICAgICBkYXRhQm94WzFdO1xuXG4gICAgICAgIGRhdGFCb3hbMF0gPSAoZGF0YUJveFswXSAtIGN4KSAqIHNjYWxlICsgY3g7XG4gICAgICAgIGRhdGFCb3hbMl0gPSAoZGF0YUJveFsyXSAtIGN4KSAqIHNjYWxlICsgY3g7XG4gICAgICAgIGRhdGFCb3hbMV0gPSAoZGF0YUJveFsxXSAtIGN5KSAqIHNjYWxlICsgY3k7XG4gICAgICAgIGRhdGFCb3hbM10gPSAoZGF0YUJveFszXSAtIGN5KSAqIHNjYWxlICsgY3k7XG5cbiAgICAgICAgc2NlbmUuc2V0UmFuZ2VzKGRhdGFCb3gpO1xuXG4gICAgICAgIHJlc3VsdC5sYXN0SW5wdXRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdW5TZXRBdXRvUmFuZ2UoKTtcbiAgICAgICAgc2NlbmUuY2FtZXJhQ2hhbmdlZCgpO1xuICAgICAgICBzY2VuZS5oYW5kbGVBbm5vdGF0aW9ucygpO1xuICAgICAgICBzY2VuZS5yZWxheW91dENhbGxiYWNrKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGNvbnZlcnRIVE1MVG9Vbmljb2RlID0gcmVxdWlyZSgnLi4vLi4vbGliL2h0bWwydW5pY29kZScpO1xudmFyIHN0cjJSR0JBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdHIycmdiYXJyYXknKTtcblxuZnVuY3Rpb24gQXhlczJET3B0aW9ucyhzY2VuZSkge1xuICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB0aGlzLmdsID0gc2NlbmUuZ2w7XG4gICAgdGhpcy5waXhlbFJhdGlvID0gc2NlbmUucGl4ZWxSYXRpbztcblxuICAgIHRoaXMuc2NyZWVuQm94ID0gWzAsIDAsIDEsIDFdO1xuICAgIHRoaXMudmlld0JveCA9IFswLCAwLCAxLCAxXTtcbiAgICB0aGlzLmRhdGFCb3ggPSBbLTEsIC0xLCAxLCAxXTtcblxuICAgIHRoaXMuYm9yZGVyTGluZUVuYWJsZSA9IFtmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgdGhpcy5ib3JkZXJMaW5lV2lkdGggPSBbMSwgMSwgMSwgMV07XG4gICAgdGhpcy5ib3JkZXJMaW5lQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXVxuICAgIF07XG5cbiAgICB0aGlzLnRpY2tzID0gW1tdLCBbXV07XG4gICAgdGhpcy50aWNrRW5hYmxlID0gW3RydWUsIHRydWUsIGZhbHNlLCBmYWxzZV07XG4gICAgdGhpcy50aWNrUGFkID0gWzE1LCAxNSwgMTUsIDE1XTtcbiAgICB0aGlzLnRpY2tBbmdsZSA9IFswLCAwLCAwLCAwXTtcbiAgICB0aGlzLnRpY2tDb2xvciA9IFtcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdXG4gICAgXTtcbiAgICB0aGlzLnRpY2tNYXJrTGVuZ3RoID0gWzAsIDAsIDAsIDBdO1xuICAgIHRoaXMudGlja01hcmtXaWR0aCA9IFswLCAwLCAwLCAwXTtcbiAgICB0aGlzLnRpY2tNYXJrQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXVxuICAgIF07XG5cbiAgICB0aGlzLmxhYmVscyA9IFsneCcsICd5J107XG4gICAgdGhpcy5sYWJlbEVuYWJsZSA9IFt0cnVlLCB0cnVlLCBmYWxzZSwgZmFsc2VdO1xuICAgIHRoaXMubGFiZWxBbmdsZSA9IFswLCBNYXRoLlBJIC8gMiwgMCwgMy4wICogTWF0aC5QSSAvIDJdO1xuICAgIHRoaXMubGFiZWxQYWQgPSBbMTUsIDE1LCAxNSwgMTVdO1xuICAgIHRoaXMubGFiZWxTaXplID0gWzEyLCAxMl07XG4gICAgdGhpcy5sYWJlbEZvbnQgPSBbJ3NhbnMtc2VyaWYnLCAnc2Fucy1zZXJpZiddO1xuICAgIHRoaXMubGFiZWxDb2xvciA9IFtcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdXG4gICAgXTtcblxuICAgIHRoaXMudGl0bGUgPSAnJztcbiAgICB0aGlzLnRpdGxlRW5hYmxlID0gdHJ1ZTtcbiAgICB0aGlzLnRpdGxlQ2VudGVyID0gWzAsIDAsIDAsIDBdO1xuICAgIHRoaXMudGl0bGVBbmdsZSA9IDA7XG4gICAgdGhpcy50aXRsZUNvbG9yID0gWzAsIDAsIDAsIDFdO1xuICAgIHRoaXMudGl0bGVGb250ID0gJ3NhbnMtc2VyaWYnO1xuICAgIHRoaXMudGl0bGVTaXplID0gMTg7XG5cbiAgICB0aGlzLmdyaWRMaW5lRW5hYmxlID0gW3RydWUsIHRydWVdO1xuICAgIHRoaXMuZ3JpZExpbmVDb2xvciA9IFtcbiAgICAgICAgWzAsIDAsIDAsIDAuNV0sXG4gICAgICAgIFswLCAwLCAwLCAwLjVdXG4gICAgXTtcbiAgICB0aGlzLmdyaWRMaW5lV2lkdGggPSBbMSwgMV07XG5cbiAgICB0aGlzLnplcm9MaW5lRW5hYmxlID0gW3RydWUsIHRydWVdO1xuICAgIHRoaXMuemVyb0xpbmVXaWR0aCA9IFsxLCAxXTtcbiAgICB0aGlzLnplcm9MaW5lQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdXG4gICAgXTtcblxuICAgIHRoaXMuYm9yZGVyQ29sb3IgPSBmYWxzZTtcbiAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9IFswLCAwLCAwLCAwXTtcblxuICAgIHRoaXMuc3RhdGljID0gdGhpcy5zY2VuZS5zdGF0aWNQbG90O1xufVxuXG52YXIgcHJvdG8gPSBBeGVzMkRPcHRpb25zLnByb3RvdHlwZTtcblxudmFyIEFYRVMgPSBbJ3hheGlzJywgJ3lheGlzJ107XG5cbnByb3RvLm1lcmdlID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gICAgLy8gdGl0bGVzIGFyZSByZW5kZXJlZCBpbiBTVkdcbiAgICB0aGlzLnRpdGxlRW5hYmxlID0gZmFsc2U7XG4gICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBzdHIyUkdCQXJyYXkob3B0aW9ucy5wbG90X2JnY29sb3IpO1xuXG4gICAgdmFyIGF4aXNOYW1lLCBheCwgYXhUaXRsZSwgYXhNaXJyb3I7XG4gICAgdmFyIGhhc0F4aXNJbkRmbHRQb3MsIGhhc0F4aXNJbkFsdHJQb3MsIGhhc1NoYXJlZEF4aXMsIG1pcnJvckxpbmVzLCBtaXJyb3JUaWNrcztcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICBheGlzTmFtZSA9IEFYRVNbaV07XG4gICAgICAgIHZhciBheGlzTGV0dGVyID0gYXhpc05hbWUuY2hhckF0KDApO1xuXG4gICAgICAgIC8vIGdldCBvcHRpb25zIHJlbGV2YW50IHRvIHRoaXMgc3VicGxvdCxcbiAgICAgICAgLy8gJ19uYW1lJyBpcyBlLmcuIHhheGlzLCB4YXhpczIsIHlheGlzLCB5YXhpczQgLi4uXG4gICAgICAgIGF4ID0gb3B0aW9uc1t0aGlzLnNjZW5lW2F4aXNOYW1lXS5fbmFtZV07XG5cbiAgICAgICAgYXhUaXRsZSA9IGF4LnRpdGxlID09PSB0aGlzLnNjZW5lLmZ1bGxMYXlvdXQuX2RmbHRUaXRsZVtheGlzTGV0dGVyXSA/ICcnIDogYXgudGl0bGU7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDw9IDI7IGogKz0gMikge1xuICAgICAgICAgICAgdGhpcy5sYWJlbEVuYWJsZVtpICsgal0gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubGFiZWxzW2kgKyBqXSA9IGNvbnZlcnRIVE1MVG9Vbmljb2RlKGF4VGl0bGUpO1xuICAgICAgICAgICAgdGhpcy5sYWJlbENvbG9yW2kgKyBqXSA9IHN0cjJSR0JBcnJheShheC50aXRsZWZvbnQuY29sb3IpO1xuICAgICAgICAgICAgdGhpcy5sYWJlbEZvbnRbaSArIGpdID0gYXgudGl0bGVmb250LmZhbWlseTtcbiAgICAgICAgICAgIHRoaXMubGFiZWxTaXplW2kgKyBqXSA9IGF4LnRpdGxlZm9udC5zaXplO1xuICAgICAgICAgICAgdGhpcy5sYWJlbFBhZFtpICsgal0gPSB0aGlzLmdldExhYmVsUGFkKGF4aXNOYW1lLCBheCk7XG5cbiAgICAgICAgICAgIHRoaXMudGlja0VuYWJsZVtpICsgal0gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudGlja0NvbG9yW2kgKyBqXSA9IHN0cjJSR0JBcnJheSgoYXgudGlja2ZvbnQgfHwge30pLmNvbG9yKTtcbiAgICAgICAgICAgIHRoaXMudGlja0FuZ2xlW2kgKyBqXSA9IChheC50aWNrYW5nbGUgPT09ICdhdXRvJykgP1xuICAgICAgICAgICAgICAgIDAgOlxuICAgICAgICAgICAgICAgIE1hdGguUEkgKiAtYXgudGlja2FuZ2xlIC8gMTgwO1xuICAgICAgICAgICAgdGhpcy50aWNrUGFkW2kgKyBqXSA9IHRoaXMuZ2V0VGlja1BhZChheCk7XG5cbiAgICAgICAgICAgIHRoaXMudGlja01hcmtMZW5ndGhbaSArIGpdID0gMDtcbiAgICAgICAgICAgIHRoaXMudGlja01hcmtXaWR0aFtpICsgal0gPSBheC50aWNrd2lkdGggfHwgMDtcbiAgICAgICAgICAgIHRoaXMudGlja01hcmtDb2xvcltpICsgal0gPSBzdHIyUkdCQXJyYXkoYXgudGlja2NvbG9yKTtcblxuICAgICAgICAgICAgdGhpcy5ib3JkZXJMaW5lRW5hYmxlW2kgKyBqXSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ib3JkZXJMaW5lQ29sb3JbaSArIGpdID0gc3RyMlJHQkFycmF5KGF4LmxpbmVjb2xvcik7XG4gICAgICAgICAgICB0aGlzLmJvcmRlckxpbmVXaWR0aFtpICsgal0gPSBheC5saW5ld2lkdGggfHwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGhhc1NoYXJlZEF4aXMgPSB0aGlzLmhhc1NoYXJlZEF4aXMoYXgpO1xuICAgICAgICBoYXNBeGlzSW5EZmx0UG9zID0gdGhpcy5oYXNBeGlzSW5EZmx0UG9zKGF4aXNOYW1lLCBheCkgJiYgIWhhc1NoYXJlZEF4aXM7XG4gICAgICAgIGhhc0F4aXNJbkFsdHJQb3MgPSB0aGlzLmhhc0F4aXNJbkFsdHJQb3MoYXhpc05hbWUsIGF4KSAmJiAhaGFzU2hhcmVkQXhpcztcblxuICAgICAgICBheE1pcnJvciA9IGF4Lm1pcnJvciB8fCBmYWxzZTtcbiAgICAgICAgbWlycm9yTGluZXMgPSBoYXNTaGFyZWRBeGlzID9cbiAgICAgICAgICAgIChTdHJpbmcoYXhNaXJyb3IpLmluZGV4T2YoJ2FsbCcpICE9PSAtMSkgOiAgLy8gJ2FsbCcgb3IgJ2FsbHRpY2tzJ1xuICAgICAgICAgICAgISFheE1pcnJvcjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbGwgYnV0IGZhbHNlXG4gICAgICAgIG1pcnJvclRpY2tzID0gaGFzU2hhcmVkQXhpcyA/XG4gICAgICAgICAgICAoYXhNaXJyb3IgPT09ICdhbGx0aWNrcycpIDpcbiAgICAgICAgICAgIChTdHJpbmcoYXhNaXJyb3IpLmluZGV4T2YoJ3RpY2tzJykgIT09IC0xKTsgLy8gJ3RpY2tzJyBvciAnYWxsdGlja3MnXG5cbiAgICAgICAgLy8gQXhpcyB0aXRsZXMgYW5kIHRpY2sgbGFiZWxzIGNhbiBvbmx5IGFwcGVhciBvZiBvbmUgc2lkZSBvZiB0aGUgc2NlbmVcbiAgICAgICAgLy8gIGFuZCBhcmUgbmV2ZXIgc2hvdyBvbiBzdWJwbG90cyB0aGF0IHNoYXJlIGV4aXN0aW5nIGF4ZXMuXG5cbiAgICAgICAgaWYoaGFzQXhpc0luRGZsdFBvcykgdGhpcy5sYWJlbEVuYWJsZVtpXSA9IHRydWU7XG4gICAgICAgIGVsc2UgaWYoaGFzQXhpc0luQWx0clBvcykgdGhpcy5sYWJlbEVuYWJsZVtpICsgMl0gPSB0cnVlO1xuXG4gICAgICAgIGlmKGhhc0F4aXNJbkRmbHRQb3MpIHRoaXMudGlja0VuYWJsZVtpXSA9IGF4LnNob3d0aWNrbGFiZWxzO1xuICAgICAgICBlbHNlIGlmKGhhc0F4aXNJbkFsdHJQb3MpIHRoaXMudGlja0VuYWJsZVtpICsgMl0gPSBheC5zaG93dGlja2xhYmVscztcblxuICAgICAgICAvLyBHcmlkIGxpbmVzIGFuZCB0aWNrcyBjYW4gYXBwZWFyIG9uIGJvdGggc2lkZXMgb2YgdGhlIHNjZW5lXG4gICAgICAgIC8vICBhbmQgY2FuIGFwcGVhciBvbiBzdWJwbG90IHRoYXQgc2hhcmUgZXhpc3RpbmcgYXhlcyB2aWEgYGF4Lm1pcnJvcmAuXG5cbiAgICAgICAgaWYoaGFzQXhpc0luRGZsdFBvcyB8fCBtaXJyb3JMaW5lcykgdGhpcy5ib3JkZXJMaW5lRW5hYmxlW2ldID0gYXguc2hvd2xpbmU7XG4gICAgICAgIGlmKGhhc0F4aXNJbkFsdHJQb3MgfHwgbWlycm9yTGluZXMpIHRoaXMuYm9yZGVyTGluZUVuYWJsZVtpICsgMl0gPSBheC5zaG93bGluZTtcblxuICAgICAgICBpZihoYXNBeGlzSW5EZmx0UG9zIHx8IG1pcnJvclRpY2tzKSB0aGlzLnRpY2tNYXJrTGVuZ3RoW2ldID0gdGhpcy5nZXRUaWNrTWFya0xlbmd0aChheCk7XG4gICAgICAgIGlmKGhhc0F4aXNJbkFsdHJQb3MgfHwgbWlycm9yVGlja3MpIHRoaXMudGlja01hcmtMZW5ndGhbaSArIDJdID0gdGhpcy5nZXRUaWNrTWFya0xlbmd0aChheCk7XG5cbiAgICAgICAgdGhpcy5ncmlkTGluZUVuYWJsZVtpXSA9IGF4LnNob3dncmlkO1xuICAgICAgICB0aGlzLmdyaWRMaW5lQ29sb3JbaV0gPSBzdHIyUkdCQXJyYXkoYXguZ3JpZGNvbG9yKTtcbiAgICAgICAgdGhpcy5ncmlkTGluZVdpZHRoW2ldID0gYXguZ3JpZHdpZHRoO1xuXG4gICAgICAgIHRoaXMuemVyb0xpbmVFbmFibGVbaV0gPSBheC56ZXJvbGluZTtcbiAgICAgICAgdGhpcy56ZXJvTGluZUNvbG9yW2ldID0gc3RyMlJHQkFycmF5KGF4Lnplcm9saW5lY29sb3IpO1xuICAgICAgICB0aGlzLnplcm9MaW5lV2lkdGhbaV0gPSBheC56ZXJvbGluZXdpZHRoO1xuICAgIH1cbn07XG5cbi8vIGlzIGFuIGF4aXMgc2hhcmVkIHdpdGggYW4gYWxyZWFkeS1kcmF3biBzdWJwbG90ID9cbnByb3RvLmhhc1NoYXJlZEF4aXMgPSBmdW5jdGlvbihheCkge1xuICAgIHZhciBzY2VuZSA9IHRoaXMuc2NlbmU7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBzY2VuZS5mdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuICAgIHZhciBsaXN0ID0gQXhlcy5maW5kU3VicGxvdHNXaXRoQXhpcyhzdWJwbG90SWRzLCBheCk7XG5cbiAgICAvLyBpZiBpbmRleCA9PT0gMCwgdGhlbiB0aGUgc3VicGxvdCBpcyBhbHJlYWR5IGRyYXduIGFzIHN1YnBsb3RzXG4gICAgLy8gYXJlIGRyYXduIGluIG9yZGVyLlxuICAgIHJldHVybiAobGlzdC5pbmRleE9mKHNjZW5lLmlkKSAhPT0gMCk7XG59O1xuXG4vLyBoYXMgYW4gYXhpcyBpbiBkZWZhdWx0IHBvc2l0aW9uIChpLmUuIGJvdHRvbS9sZWZ0KSA/XG5wcm90by5oYXNBeGlzSW5EZmx0UG9zID0gZnVuY3Rpb24oYXhpc05hbWUsIGF4KSB7XG4gICAgdmFyIGF4U2lkZSA9IGF4LnNpZGU7XG5cbiAgICBpZihheGlzTmFtZSA9PT0gJ3hheGlzJykgcmV0dXJuIChheFNpZGUgPT09ICdib3R0b20nKTtcbiAgICBlbHNlIGlmKGF4aXNOYW1lID09PSAneWF4aXMnKSByZXR1cm4gKGF4U2lkZSA9PT0gJ2xlZnQnKTtcbn07XG5cbi8vIGhhcyBhbiBheGlzIGluIGFsdGVybmF0ZSBwb3NpdGlvbiAoaS5lLiB0b3AvcmlnaHQpID9cbnByb3RvLmhhc0F4aXNJbkFsdHJQb3MgPSBmdW5jdGlvbihheGlzTmFtZSwgYXgpIHtcbiAgICB2YXIgYXhTaWRlID0gYXguc2lkZTtcblxuICAgIGlmKGF4aXNOYW1lID09PSAneGF4aXMnKSByZXR1cm4gKGF4U2lkZSA9PT0gJ3RvcCcpO1xuICAgIGVsc2UgaWYoYXhpc05hbWUgPT09ICd5YXhpcycpIHJldHVybiAoYXhTaWRlID09PSAncmlnaHQnKTtcbn07XG5cbnByb3RvLmdldExhYmVsUGFkID0gZnVuY3Rpb24oYXhpc05hbWUsIGF4KSB7XG4gICAgdmFyIG9mZnNldEJhc2UgPSAxLjUsXG4gICAgICAgIGZvbnRTaXplID0gYXgudGl0bGVmb250LnNpemUsXG4gICAgICAgIHNob3d0aWNrbGFiZWxzID0gYXguc2hvd3RpY2tsYWJlbHM7XG5cbiAgICBpZihheGlzTmFtZSA9PT0gJ3hheGlzJykge1xuICAgICAgICByZXR1cm4gKGF4LnNpZGUgPT09ICd0b3AnKSA/XG4gICAgICAgICAgICAtMTAgKyBmb250U2l6ZSAqIChvZmZzZXRCYXNlICsgKHNob3d0aWNrbGFiZWxzID8gMSA6IDApKSA6XG4gICAgICAgICAgICAtMTAgKyBmb250U2l6ZSAqIChvZmZzZXRCYXNlICsgKHNob3d0aWNrbGFiZWxzID8gMC41IDogMCkpO1xuICAgIH1cbiAgICBlbHNlIGlmKGF4aXNOYW1lID09PSAneWF4aXMnKSB7XG4gICAgICAgIHJldHVybiAoYXguc2lkZSA9PT0gJ3JpZ2h0JykgP1xuICAgICAgICAgICAgMTAgKyBmb250U2l6ZSAqIChvZmZzZXRCYXNlICsgKHNob3d0aWNrbGFiZWxzID8gMSA6IDAuNSkpIDpcbiAgICAgICAgICAgIDEwICsgZm9udFNpemUgKiAob2Zmc2V0QmFzZSArIChzaG93dGlja2xhYmVscyA/IDAuNSA6IDApKTtcbiAgICB9XG59O1xuXG5wcm90by5nZXRUaWNrUGFkID0gZnVuY3Rpb24oYXgpIHtcbiAgICByZXR1cm4gKGF4LnRpY2tzID09PSAnb3V0c2lkZScpID8gMTAgKyBheC50aWNrbGVuIDogMTU7XG59O1xuXG5wcm90by5nZXRUaWNrTWFya0xlbmd0aCA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgaWYoIWF4LnRpY2tzKSByZXR1cm4gMDtcblxuICAgIHZhciB0aWNrbGVuID0gYXgudGlja2xlbjtcblxuICAgIHJldHVybiAoYXgudGlja3MgPT09ICdpbnNpZGUnKSA/IC10aWNrbGVuIDogdGlja2xlbjtcbn07XG5cblxuZnVuY3Rpb24gY3JlYXRlQXhlczJEKHNjZW5lKSB7XG4gICAgcmV0dXJuIG5ldyBBeGVzMkRPcHRpb25zKHNjZW5lKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBeGVzMkQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgU2NlbmUyRCA9IHJlcXVpcmUoJy4vc2NlbmUyZCcpO1xudmFyIGxheW91dEdsb2JhbEF0dHJzID0gcmVxdWlyZSgnLi4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciB4bWxuc05hbWVzcGFjZXMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9jb25zdGFudHMnKTtcbnZhciBDYXJ0ZXNpYW4gPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4nKTtcbnZhciBmeEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meC9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGdldFN1YnBsb3REYXRhID0gcmVxdWlyZSgnLi4vZ2V0X2RhdGEnKS5nZXRTdWJwbG90RGF0YTtcblxuZXhwb3J0cy5uYW1lID0gJ2dsMmQnO1xuXG5leHBvcnRzLmF0dHIgPSBbJ3hheGlzJywgJ3lheGlzJ107XG5cbmV4cG9ydHMuaWRSb290ID0gWyd4JywgJ3knXTtcblxuZXhwb3J0cy5pZFJlZ2V4ID0gY29uc3RhbnRzLmlkUmVnZXg7XG5cbmV4cG9ydHMuYXR0clJlZ2V4ID0gY29uc3RhbnRzLmF0dHJSZWdleDtcblxuZXhwb3J0cy5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2F0dHJpYnV0ZXMnKTtcblxuZXhwb3J0cy5zdXBwbHlMYXlvdXREZWZhdWx0cyA9IGZ1bmN0aW9uKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgaWYoIWxheW91dE91dC5faGFzKCdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICBDYXJ0ZXNpYW4uc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpO1xuICAgIH1cbn07XG5cbi8vIGdsMmQgdXNlcyBzdmcgYXhpcyBhdHRyaWJ1dGVzIHZlcmJhdGltLCBidXQgb3ZlcnJpZGVzIGVkaXRUeXBlXG4vLyB0aGlzIGNvdWxkIHBvdGVudGlhbGx5IGJlIGp1c3QgYGxheW91dEF0dHJpYnV0ZXNgIGJ1dCBpdCB3b3VsZFxuLy8gc3RpbGwgbmVlZCBzcGVjaWFsIGhhbmRsaW5nIHNvbWV3aGVyZSB0byBnaXZlIGl0IHByZWNlZGVuY2Ugb3ZlclxuLy8gdGhlIHN2ZyB2ZXJzaW9uIHdoZW4gYm90aCBhcmUgaW4gdXNlIG9uIG9uZSBwbG90XG5leHBvcnRzLmxheW91dEF0dHJPdmVycmlkZXMgPSBvdmVycmlkZUFsbChDYXJ0ZXNpYW4ubGF5b3V0QXR0cmlidXRlcywgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG5cbi8vIHNpbWlsYXIgb3ZlcnJpZGVzIGZvciBiYXNlIHBsb3QgYXR0cmlidXRlcyAoYW5kIHRob3NlIGFkZGVkIGJ5IGNvbXBvbmVudHMpXG5leHBvcnRzLmJhc2VMYXlvdXRBdHRyT3ZlcnJpZGVzID0gb3ZlcnJpZGVBbGwoe1xuICAgIHBsb3RfYmdjb2xvcjogbGF5b3V0R2xvYmFsQXR0cnMucGxvdF9iZ2NvbG9yLFxuICAgIGhvdmVybGFiZWw6IGZ4QXR0cnMuaG92ZXJsYWJlbFxuICAgIC8vIGRyYWdtb2RlIG5lZWRzIGNhbGMgYnV0IG9ubHkgd2hlbiB0cmFuc2l0aW9uaW5nIFRPIGxhc3NvIG9yIHNlbGVjdFxuICAgIC8vIHNvIGZvciBub3cgaXQncyBsZWZ0IGluc2lkZSBfcmVsYXlvdXRcbiAgICAvLyBkcmFnbW9kZTogZnhBdHRycy5kcmFnbW9kZVxufSwgJ3Bsb3QnLCAnbmVzdGVkJyk7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uIHBsb3RHbDJkKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3RJZCA9IHN1YnBsb3RJZHNbaV0sXG4gICAgICAgICAgICBzdWJwbG90T2JqID0gZnVsbExheW91dC5fcGxvdHNbc3VicGxvdElkXSxcbiAgICAgICAgICAgIGZ1bGxTdWJwbG90RGF0YSA9IGdldFN1YnBsb3REYXRhKGZ1bGxEYXRhLCAnZ2wyZCcsIHN1YnBsb3RJZCk7XG5cbiAgICAgICAgLy8gcmVmLiB0byBjb3JyZXNwLiBTY2VuZSBpbnN0YW5jZVxuICAgICAgICB2YXIgc2NlbmUgPSBzdWJwbG90T2JqLl9zY2VuZTJkO1xuXG4gICAgICAgIC8vIElmIFNjZW5lIGlzIG5vdCBpbnN0YW50aWF0ZWQsIGNyZWF0ZSBvbmUhXG4gICAgICAgIGlmKHNjZW5lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHNjZW5lID0gbmV3IFNjZW5lMkQoe1xuICAgICAgICAgICAgICAgIGlkOiBzdWJwbG90SWQsXG4gICAgICAgICAgICAgICAgZ3JhcGhEaXY6IGdkLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogZ2QucXVlcnlTZWxlY3RvcignLmdsLWNvbnRhaW5lcicpLFxuICAgICAgICAgICAgICAgIHN0YXRpY1Bsb3Q6IGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QsXG4gICAgICAgICAgICAgICAgcGxvdEdsUGl4ZWxSYXRpbzogZ2QuX2NvbnRleHQucGxvdEdsUGl4ZWxSYXRpb1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBzZXQgcmVmIHRvIFNjZW5lIGluc3RhbmNlXG4gICAgICAgICAgICBzdWJwbG90T2JqLl9zY2VuZTJkID0gc2NlbmU7XG4gICAgICAgIH1cblxuICAgICAgICBzY2VuZS5wbG90KGZ1bGxTdWJwbG90RGF0YSwgZ2QuY2FsY2RhdGEsIGZ1bGxMYXlvdXQsIGdkLmxheW91dCk7XG4gICAgfVxufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRTY2VuZUtleXMgPSBvbGRGdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkIHx8IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG9sZFNjZW5lS2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBvbGRTY2VuZUtleXNbaV0sXG4gICAgICAgICAgICBvbGRTdWJwbG90ID0gb2xkRnVsbExheW91dC5fcGxvdHNbaWRdO1xuXG4gICAgICAgIC8vIG9sZCBzdWJwbG90IHdhc24ndCBnbDJkOyBub3RoaW5nIHRvIGRvXG4gICAgICAgIGlmKCFvbGRTdWJwbG90Ll9zY2VuZTJkKSBjb250aW51ZTtcblxuICAgICAgICAvLyBpZiBubyB0cmFjZXMgYXJlIHByZXNlbnQsIGRlbGV0ZSBnbDJkIHN1YnBsb3RcbiAgICAgICAgdmFyIHN1YnBsb3REYXRhID0gZ2V0U3VicGxvdERhdGEobmV3RnVsbERhdGEsICdnbDJkJywgaWQpO1xuICAgICAgICBpZihzdWJwbG90RGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QuX3NjZW5lMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNpbmNlIHdlIHVzZSBjYXJ0ZXNpYW4gaW50ZXJhY3Rpb25zLCBkbyBjYXJ0ZXNpYW4gY2xlYW5cbiAgICBDYXJ0ZXNpYW4uY2xlYW4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG5cbmV4cG9ydHMuZHJhd0ZyYW1ld29yayA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoIWdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgQ2FydGVzaWFuLmRyYXdGcmFtZXdvcmsoZ2QpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMudG9TVkcgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3QgPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90SWRzW2ldXSxcbiAgICAgICAgICAgIHNjZW5lID0gc3VicGxvdC5fc2NlbmUyZDtcblxuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gc2NlbmUudG9JbWFnZSgncG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnc3ZnOmltYWdlJyk7XG5cbiAgICAgICAgaW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4bWxuczogeG1sbnNOYW1lc3BhY2VzLnN2ZyxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogaW1hZ2VEYXRhLFxuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnMTAwJScsXG4gICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAnbm9uZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2NlbmUuZGVzdHJveSgpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMudXBkYXRlRnggPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90SWRzW2ldXS5fc2NlbmUyZDtcbiAgICAgICAgc3VicGxvdE9iai51cGRhdGVGeChmdWxsTGF5b3V0LmRyYWdtb2RlKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgRnggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG5cbnZhciBjcmVhdGVQbG90MkQgPSByZXF1aXJlKCdnbC1wbG90MmQnKTtcbnZhciBjcmVhdGVTcGlrZXMgPSByZXF1aXJlKCdnbC1zcGlrZXMyZCcpO1xudmFyIGNyZWF0ZVNlbGVjdEJveCA9IHJlcXVpcmUoJ2dsLXNlbGVjdC1ib3gnKTtcbnZhciBnZXRDb250ZXh0ID0gcmVxdWlyZSgnd2ViZ2wtY29udGV4dCcpO1xuXG52YXIgY3JlYXRlT3B0aW9ucyA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xudmFyIGNyZWF0ZUNhbWVyYSA9IHJlcXVpcmUoJy4vY2FtZXJhJyk7XG52YXIgY29udmVydEhUTUxUb1VuaWNvZGUgPSByZXF1aXJlKCcuLi8uLi9saWIvaHRtbDJ1bmljb2RlJyk7XG52YXIgc2hvd05vV2ViR2xNc2cgPSByZXF1aXJlKCcuLi8uLi9saWIvc2hvd19ub193ZWJnbF9tc2cnKTtcbnZhciBheGlzQ29uc3RyYWludHMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vY29uc3RyYWludHMnKTtcbnZhciBlbmZvcmNlQXhpc0NvbnN0cmFpbnRzID0gYXhpc0NvbnN0cmFpbnRzLmVuZm9yY2U7XG52YXIgY2xlYW5BeGlzQ29uc3RyYWludHMgPSBheGlzQ29uc3RyYWludHMuY2xlYW47XG52YXIgZG9BdXRvUmFuZ2UgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vYXV0b3JhbmdlJykuZG9BdXRvUmFuZ2U7XG5cbnZhciBBWEVTID0gWyd4YXhpcycsICd5YXhpcyddO1xudmFyIFNUQVRJQ19DQU5WQVMsIFNUQVRJQ19DT05URVhUO1xuXG52YXIgU1VCUExPVF9QQVRURVJOID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2NvbnN0YW50cycpLlNVQlBMT1RfUEFUVEVSTjtcblxuXG5mdW5jdGlvbiBTY2VuZTJEKG9wdGlvbnMsIGZ1bGxMYXlvdXQpIHtcbiAgICB0aGlzLmNvbnRhaW5lciA9IG9wdGlvbnMuY29udGFpbmVyO1xuICAgIHRoaXMuZ3JhcGhEaXYgPSBvcHRpb25zLmdyYXBoRGl2O1xuICAgIHRoaXMucGl4ZWxSYXRpbyA9IG9wdGlvbnMucGxvdEdsUGl4ZWxSYXRpbyB8fCB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB0aGlzLmlkID0gb3B0aW9ucy5pZDtcbiAgICB0aGlzLnN0YXRpY1Bsb3QgPSAhIW9wdGlvbnMuc3RhdGljUGxvdDtcbiAgICB0aGlzLnNjcm9sbFpvb20gPSB0aGlzLmdyYXBoRGl2Ll9jb250ZXh0LnNjcm9sbFpvb207XG5cbiAgICB0aGlzLmZ1bGxEYXRhID0gbnVsbDtcbiAgICB0aGlzLnVwZGF0ZVJlZnMoZnVsbExheW91dCk7XG5cbiAgICB0aGlzLm1ha2VGcmFtZXdvcmsoKTtcbiAgICBpZih0aGlzLnN0b3BwZWQpIHJldHVybjtcblxuICAgIC8vIHVwZGF0ZSBvcHRpb25zXG4gICAgdGhpcy5nbHBsb3RPcHRpb25zID0gY3JlYXRlT3B0aW9ucyh0aGlzKTtcbiAgICB0aGlzLmdscGxvdE9wdGlvbnMubWVyZ2UoZnVsbExheW91dCk7XG5cbiAgICAvLyBjcmVhdGUgdGhlIHBsb3RcbiAgICB0aGlzLmdscGxvdCA9IGNyZWF0ZVBsb3QyRCh0aGlzLmdscGxvdE9wdGlvbnMpO1xuXG4gICAgLy8gY3JlYXRlIGNhbWVyYVxuICAgIHRoaXMuY2FtZXJhID0gY3JlYXRlQ2FtZXJhKHRoaXMpO1xuXG4gICAgLy8gdHJhY2Ugc2V0XG4gICAgdGhpcy50cmFjZXMgPSB7fTtcblxuICAgIC8vIGNyZWF0ZSBheGVzIHNwaWtlc1xuICAgIHRoaXMuc3Bpa2VzID0gY3JlYXRlU3Bpa2VzKHRoaXMuZ2xwbG90KTtcblxuICAgIHRoaXMuc2VsZWN0Qm94ID0gY3JlYXRlU2VsZWN0Qm94KHRoaXMuZ2xwbG90LCB7XG4gICAgICAgIGlubmVyRmlsbDogZmFsc2UsXG4gICAgICAgIG91dGVyRmlsbDogdHJ1ZVxuICAgIH0pO1xuXG4gICAgLy8gbGFzdCBidXR0b24gc3RhdGVcbiAgICB0aGlzLmxhc3RCdXR0b25TdGF0ZSA9IDA7XG5cbiAgICAvLyBsYXN0IHBpY2sgcmVzdWx0XG4gICAgdGhpcy5waWNrUmVzdWx0ID0gbnVsbDtcblxuICAgIC8vIGlzIHRoZSBtb3VzZSBvdmVyIHRoZSBwbG90P1xuICAgIC8vIGl0J3MgT0sgaWYgdGhpcyBzYXlzIHRydWUgd2hlbiBpdCdzIG5vdCwgc28gbG9uZyBhc1xuICAgIC8vIHdoZW4gd2UgZ2V0IGEgbW91c2VvdXQgd2Ugc2V0IGl0IHRvIGZhbHNlIGJlZm9yZSBoYW5kbGluZ1xuICAgIHRoaXMuaXNNb3VzZU92ZXIgPSB0cnVlO1xuXG4gICAgLy8gZmxhZyB0byBzdG9wIHJlbmRlciBsb29wXG4gICAgdGhpcy5zdG9wcGVkID0gZmFsc2U7XG5cbiAgICAvLyByZWRyYXcgdGhlIHBsb3RcbiAgICB0aGlzLnJlZHJhdyA9IHRoaXMuZHJhdy5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVkcmF3KCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2NlbmUyRDtcblxudmFyIHByb3RvID0gU2NlbmUyRC5wcm90b3R5cGU7XG5cbnByb3RvLm1ha2VGcmFtZXdvcmsgPSBmdW5jdGlvbigpIHtcblxuICAgIC8vIGNyZWF0ZSBjYW52YXMgYW5kIGdsIGNvbnRleHRcbiAgICBpZih0aGlzLnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgaWYoIVNUQVRJQ19DT05URVhUKSB7XG4gICAgICAgICAgICBTVEFUSUNfQ0FOVkFTID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG5cbiAgICAgICAgICAgIFNUQVRJQ19DT05URVhUID0gZ2V0Q29udGV4dCh7XG4gICAgICAgICAgICAgICAgY2FudmFzOiBTVEFUSUNfQ0FOVkFTLFxuICAgICAgICAgICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2UsXG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbGllZEFscGhhOiB0cnVlLFxuICAgICAgICAgICAgICAgIGFudGlhbGlhczogdHJ1ZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmKCFTVEFUSUNfQ09OVEVYVCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRXJyb3IgY3JlYXRpbmcgc3RhdGljIGNhbnZhcy9jb250ZXh0IGZvciBpbWFnZSBzZXJ2ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY2FudmFzID0gU1RBVElDX0NBTlZBUztcbiAgICAgICAgdGhpcy5nbCA9IFNUQVRJQ19DT05URVhUO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGxpdmVDYW52YXMgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuZ2wtY2FudmFzLWZvY3VzJyk7XG5cbiAgICAgICAgdmFyIGdsID0gZ2V0Q29udGV4dCh7XG4gICAgICAgICAgICBjYW52YXM6IGxpdmVDYW52YXMsXG4gICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRydWUsXG4gICAgICAgICAgICBwcmVtdWx0aXBsaWVkQWxwaGE6IHRydWVcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoIWdsKSB7XG4gICAgICAgICAgICBzaG93Tm9XZWJHbE1zZyh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNhbnZhcyA9IGxpdmVDYW52YXM7XG4gICAgICAgIHRoaXMuZ2wgPSBnbDtcbiAgICB9XG5cbiAgICAvLyBwb3NpdGlvbiB0aGUgY2FudmFzXG4gICAgdmFyIGNhbnZhcyA9IHRoaXMuY2FudmFzO1xuXG4gICAgY2FudmFzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgY2FudmFzLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBjYW52YXMuc3R5bGUudG9wID0gJzBweCc7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAnMHB4JztcbiAgICBjYW52YXMuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnbm9uZSc7XG5cbiAgICB0aGlzLnVwZGF0ZVNpemUoY2FudmFzKTtcblxuICAgIC8vIGRpc2FibGluZyB1c2VyIHNlbGVjdCBvbiB0aGUgY2FudmFzXG4gICAgLy8gc2FuaXRpemVzIGRvdWJsZS1jbGlja3MgaW50ZXJhY3Rpb25zXG4gICAgLy8gcmVmOiBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvNzQ0XG4gICAgY2FudmFzLmNsYXNzTmFtZSArPSAnIHVzZXItc2VsZWN0LW5vbmUnO1xuXG4gICAgLy8gY3JlYXRlIFNWRyBjb250YWluZXIgZm9yIGhvdmVyIHRleHRcbiAgICB2YXIgc3ZnQ29udGFpbmVyID0gdGhpcy5zdmdDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoXG4gICAgICAgICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsXG4gICAgICAgICdzdmcnKTtcbiAgICBzdmdDb250YWluZXIuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZS50b3AgPSBzdmdDb250YWluZXIuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZS53aWR0aCA9IHN2Z0NvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlWyd6LWluZGV4J10gPSAyMDtcbiAgICBzdmdDb250YWluZXIuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnbm9uZSc7XG5cbiAgICAvLyBjcmVhdGUgZGl2IHRvIGNhdGNoIHRoZSBtb3VzZSBldmVudFxuICAgIHZhciBtb3VzZUNvbnRhaW5lciA9IHRoaXMubW91c2VDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBtb3VzZUNvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgbW91c2VDb250YWluZXIuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnYXV0byc7XG5cbiAgICB0aGlzLnBpY2tDYW52YXMgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuZ2wtY2FudmFzLXBpY2snKTtcblxuXG4gICAgLy8gYXBwZW5kIGNhbnZhcywgaG92ZXIgc3ZnIGFuZCBtb3VzZSBkaXYgdG8gY29udGFpbmVyXG4gICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyO1xuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChzdmdDb250YWluZXIpO1xuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChtb3VzZUNvbnRhaW5lcik7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgbW91c2VDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgc2VsZi5pc01vdXNlT3ZlciA9IGZhbHNlO1xuICAgICAgICBzZWxmLnVuaG92ZXIoKTtcbiAgICB9KTtcbiAgICBtb3VzZUNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgc2VsZi5pc01vdXNlT3ZlciA9IHRydWU7XG4gICAgfSk7XG59O1xuXG5wcm90by50b0ltYWdlID0gZnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgaWYoIWZvcm1hdCkgZm9ybWF0ID0gJ3BuZyc7XG5cbiAgICB0aGlzLnN0b3BwZWQgPSB0cnVlO1xuXG4gICAgaWYodGhpcy5zdGF0aWNQbG90KSB0aGlzLmNvbnRhaW5lci5hcHBlbmRDaGlsZChTVEFUSUNfQ0FOVkFTKTtcblxuICAgIC8vIHVwZGF0ZSBjYW52YXMgc2l6ZVxuICAgIHRoaXMudXBkYXRlU2l6ZSh0aGlzLmNhbnZhcyk7XG5cblxuICAgIC8vIGdyYWIgY29udGV4dCBhbmQgeWFuayBvdXQgcGl4ZWxzXG4gICAgdmFyIGdsID0gdGhpcy5nbHBsb3QuZ2wsXG4gICAgICAgIHcgPSBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsXG4gICAgICAgIGggPSBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0O1xuXG4gICAgLy8gZm9yY2UgcmVkcmF3XG4gICAgZ2wuY2xlYXJDb2xvcigxLCAxLCAxLCAwKTtcbiAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUIHwgZ2wuREVQVEhfQlVGRkVSX0JJVCk7XG4gICAgdGhpcy5nbHBsb3Quc2V0RGlydHkoKTtcbiAgICB0aGlzLmdscGxvdC5kcmF3KCk7XG5cbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xuXG4gICAgdmFyIHBpeGVscyA9IG5ldyBVaW50OEFycmF5KHcgKiBoICogNCk7XG4gICAgZ2wucmVhZFBpeGVscygwLCAwLCB3LCBoLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBwaXhlbHMpO1xuXG4gICAgLy8gZmxpcCBwaXhlbHNcbiAgICBmb3IodmFyIGogPSAwLCBrID0gaCAtIDE7IGogPCBrOyArK2osIC0taykge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdzsgKytpKSB7XG4gICAgICAgICAgICBmb3IodmFyIGwgPSAwOyBsIDwgNDsgKytsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRtcCA9IHBpeGVsc1s0ICogKHcgKiBqICsgaSkgKyBsXTtcbiAgICAgICAgICAgICAgICBwaXhlbHNbNCAqICh3ICogaiArIGkpICsgbF0gPSBwaXhlbHNbNCAqICh3ICogayArIGkpICsgbF07XG4gICAgICAgICAgICAgICAgcGl4ZWxzWzQgKiAodyAqIGsgKyBpKSArIGxdID0gdG1wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGNhbnZhcy53aWR0aCA9IHc7XG4gICAgY2FudmFzLmhlaWdodCA9IGg7XG5cbiAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIHZhciBpbWFnZURhdGEgPSBjb250ZXh0LmNyZWF0ZUltYWdlRGF0YSh3LCBoKTtcbiAgICBpbWFnZURhdGEuZGF0YS5zZXQocGl4ZWxzKTtcbiAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuXG4gICAgdmFyIGRhdGFVUkw7XG5cbiAgICBzd2l0Y2goZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgJ2pwZWcnOlxuICAgICAgICAgICAgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd3ZWJwJzpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS93ZWJwJyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9wbmcnKTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnN0YXRpY1Bsb3QpIHRoaXMuY29udGFpbmVyLnJlbW92ZUNoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgcmV0dXJuIGRhdGFVUkw7XG59O1xuXG5wcm90by51cGRhdGVTaXplID0gZnVuY3Rpb24oY2FudmFzKSB7XG4gICAgaWYoIWNhbnZhcykgY2FudmFzID0gdGhpcy5jYW52YXM7XG5cbiAgICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbyxcbiAgICAgICAgZnVsbExheW91dCA9IHRoaXMuZnVsbExheW91dDtcblxuICAgIHZhciB3aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGgsXG4gICAgICAgIGhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0LFxuICAgICAgICBwaXhlbFdpZHRoID0gTWF0aC5jZWlsKHBpeGVsUmF0aW8gKiB3aWR0aCkgfDAsXG4gICAgICAgIHBpeGVsSGVpZ2h0ID0gTWF0aC5jZWlsKHBpeGVsUmF0aW8gKiBoZWlnaHQpIHwwO1xuXG4gICAgLy8gY2hlY2sgZm9yIHJlc2l6ZVxuICAgIGlmKGNhbnZhcy53aWR0aCAhPT0gcGl4ZWxXaWR0aCB8fCBjYW52YXMuaGVpZ2h0ICE9PSBwaXhlbEhlaWdodCkge1xuICAgICAgICBjYW52YXMud2lkdGggPSBwaXhlbFdpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gcGl4ZWxIZWlnaHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNhbnZhcztcbn07XG5cbnByb3RvLmNvbXB1dGVUaWNrTWFya3MgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnhheGlzLnNldFNjYWxlKCk7XG4gICAgdGhpcy55YXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIG5leHRUaWNrcyA9IFtcbiAgICAgICAgQXhlcy5jYWxjVGlja3ModGhpcy54YXhpcyksXG4gICAgICAgIEF4ZXMuY2FsY1RpY2tzKHRoaXMueWF4aXMpXG4gICAgXTtcblxuICAgIGZvcih2YXIgaiA9IDA7IGogPCAyOyArK2opIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG5leHRUaWNrc1tqXS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgLy8gY29lcmNpbmcgdGljayB2YWx1ZSAobWF5IG5vdCBiZSBhIHN0cmluZykgdG8gYSBzdHJpbmdcbiAgICAgICAgICAgIG5leHRUaWNrc1tqXVtpXS50ZXh0ID0gY29udmVydEhUTUxUb1VuaWNvZGUobmV4dFRpY2tzW2pdW2ldLnRleHQgKyAnJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV4dFRpY2tzO1xufTtcblxuZnVuY3Rpb24gY29tcGFyZVRpY2tzKGEsIGIpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMjsgKytpKSB7XG4gICAgICAgIHZhciBhdGlja3MgPSBhW2ldLFxuICAgICAgICAgICAgYnRpY2tzID0gYltpXTtcblxuICAgICAgICBpZihhdGlja3MubGVuZ3RoICE9PSBidGlja3MubGVuZ3RoKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYXRpY2tzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBpZihhdGlja3Nbal0ueCAhPT0gYnRpY2tzW2pdLngpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5wcm90by51cGRhdGVSZWZzID0gZnVuY3Rpb24obmV3RnVsbExheW91dCkge1xuICAgIHRoaXMuZnVsbExheW91dCA9IG5ld0Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgc3BtYXRjaCA9IHRoaXMuaWQubWF0Y2goU1VCUExPVF9QQVRURVJOKTtcbiAgICB2YXIgeGF4aXNOYW1lID0gJ3hheGlzJyArIHNwbWF0Y2hbMV07XG4gICAgdmFyIHlheGlzTmFtZSA9ICd5YXhpcycgKyBzcG1hdGNoWzJdO1xuXG4gICAgdGhpcy54YXhpcyA9IHRoaXMuZnVsbExheW91dFt4YXhpc05hbWVdO1xuICAgIHRoaXMueWF4aXMgPSB0aGlzLmZ1bGxMYXlvdXRbeWF4aXNOYW1lXTtcbn07XG5cbnByb3RvLnJlbGF5b3V0Q2FsbGJhY2sgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ3JhcGhEaXYgPSB0aGlzLmdyYXBoRGl2LFxuICAgICAgICB4YXhpcyA9IHRoaXMueGF4aXMsXG4gICAgICAgIHlheGlzID0gdGhpcy55YXhpcyxcbiAgICAgICAgbGF5b3V0ID0gZ3JhcGhEaXYubGF5b3V0O1xuXG4gICAgLy8gdXBkYXRlIHVzZXIgbGF5b3V0XG4gICAgbGF5b3V0LnhheGlzLmF1dG9yYW5nZSA9IHhheGlzLmF1dG9yYW5nZTtcbiAgICBsYXlvdXQueGF4aXMucmFuZ2UgPSB4YXhpcy5yYW5nZS5zbGljZSgwKTtcbiAgICBsYXlvdXQueWF4aXMuYXV0b3JhbmdlID0geWF4aXMuYXV0b3JhbmdlO1xuICAgIGxheW91dC55YXhpcy5yYW5nZSA9IHlheGlzLnJhbmdlLnNsaWNlKDApO1xuXG4gICAgLy8gbWFrZSBhIG1lYW5pbmdmdWwgdmFsdWUgdG8gYmUgcGFzc2VkIG9uIHRvIHRoZSBwb3NzaWJsZSAncGxvdGx5X3JlbGF5b3V0JyBzdWJzY3JpYmVyKHMpXG4gICAgLy8gc2NlbmUuY2FtZXJhIGhhcyBubyBtYW55IHVzZWZ1bCBwcm9qZWN0aW9uIG9yIHNjYWxlIGluZm9ybWF0aW9uXG4gICAgLy8gaGVscHMgZGV0ZXJtaW5lIHdoaWNoIG9uZSBpcyB0aGUgbGF0ZXN0IGlucHV0IChpZiBhc3luYylcbiAgICB2YXIgdXBkYXRlID0ge1xuICAgICAgICBsYXN0SW5wdXRUaW1lOiB0aGlzLmNhbWVyYS5sYXN0SW5wdXRUaW1lXG4gICAgfTtcblxuICAgIHVwZGF0ZVt4YXhpcy5fbmFtZV0gPSB4YXhpcy5yYW5nZS5zbGljZSgwKTtcbiAgICB1cGRhdGVbeWF4aXMuX25hbWVdID0geWF4aXMucmFuZ2Uuc2xpY2UoMCk7XG5cbiAgICBncmFwaERpdi5lbWl0KCdwbG90bHlfcmVsYXlvdXQnLCB1cGRhdGUpO1xufTtcblxucHJvdG8uY2FtZXJhQ2hhbmdlZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjYW1lcmEgPSB0aGlzLmNhbWVyYTtcblxuICAgIHRoaXMuZ2xwbG90LnNldERhdGFCb3godGhpcy5jYWxjRGF0YUJveCgpKTtcblxuICAgIHZhciBuZXh0VGlja3MgPSB0aGlzLmNvbXB1dGVUaWNrTWFya3MoKTtcbiAgICB2YXIgY3VyVGlja3MgPSB0aGlzLmdscGxvdE9wdGlvbnMudGlja3M7XG5cbiAgICBpZihjb21wYXJlVGlja3MobmV4dFRpY2tzLCBjdXJUaWNrcykpIHtcbiAgICAgICAgdGhpcy5nbHBsb3RPcHRpb25zLnRpY2tzID0gbmV4dFRpY2tzO1xuICAgICAgICB0aGlzLmdscGxvdE9wdGlvbnMuZGF0YUJveCA9IGNhbWVyYS5kYXRhQm94O1xuICAgICAgICB0aGlzLmdscGxvdC51cGRhdGUodGhpcy5nbHBsb3RPcHRpb25zKTtcbiAgICAgICAgdGhpcy5oYW5kbGVBbm5vdGF0aW9ucygpO1xuICAgIH1cbn07XG5cbnByb3RvLmhhbmRsZUFubm90YXRpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdkID0gdGhpcy5ncmFwaERpdixcbiAgICAgICAgYW5ub3RhdGlvbnMgPSB0aGlzLmZ1bGxMYXlvdXQuYW5ub3RhdGlvbnM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFubiA9IGFubm90YXRpb25zW2ldO1xuXG4gICAgICAgIGlmKGFubi54cmVmID09PSB0aGlzLnhheGlzLl9pZCAmJiBhbm4ueXJlZiA9PT0gdGhpcy55YXhpcy5faWQpIHtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhd09uZScpKGdkLCBpKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbnByb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgICBpZighdGhpcy5nbHBsb3QpIHJldHVybjtcblxuICAgIHZhciB0cmFjZXMgPSB0aGlzLnRyYWNlcztcblxuICAgIGlmKHRyYWNlcykge1xuICAgICAgICBPYmplY3Qua2V5cyh0cmFjZXMpLm1hcChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIHRyYWNlc1trZXldLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZXNba2V5XTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5nbHBsb3QuZGlzcG9zZSgpO1xuXG4gICAgdGhpcy5jb250YWluZXIucmVtb3ZlQ2hpbGQodGhpcy5zdmdDb250YWluZXIpO1xuICAgIHRoaXMuY29udGFpbmVyLnJlbW92ZUNoaWxkKHRoaXMubW91c2VDb250YWluZXIpO1xuXG4gICAgdGhpcy5mdWxsRGF0YSA9IG51bGw7XG4gICAgdGhpcy5nbHBsb3QgPSBudWxsO1xuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gICAgdGhpcy5jYW1lcmEubW91c2VMaXN0ZW5lci5lbmFibGVkID0gZmFsc2U7XG4gICAgdGhpcy5tb3VzZUNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuY2FtZXJhLndoZWVsTGlzdGVuZXIpO1xuICAgIHRoaXMuY2FtZXJhID0gbnVsbDtcbn07XG5cbnByb3RvLnBsb3QgPSBmdW5jdGlvbihmdWxsRGF0YSwgY2FsY0RhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgZ2xwbG90ID0gdGhpcy5nbHBsb3Q7XG5cbiAgICB0aGlzLnVwZGF0ZVJlZnMoZnVsbExheW91dCk7XG4gICAgdGhpcy54YXhpcy5jbGVhckNhbGMoKTtcbiAgICB0aGlzLnlheGlzLmNsZWFyQ2FsYygpO1xuICAgIHRoaXMudXBkYXRlVHJhY2VzKGZ1bGxEYXRhLCBjYWxjRGF0YSk7XG4gICAgdGhpcy51cGRhdGVGeChmdWxsTGF5b3V0LmRyYWdtb2RlKTtcblxuICAgIHZhciB3aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGgsXG4gICAgICAgIGhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgdGhpcy51cGRhdGVTaXplKHRoaXMuY2FudmFzKTtcblxuICAgIHZhciBvcHRpb25zID0gdGhpcy5nbHBsb3RPcHRpb25zO1xuICAgIG9wdGlvbnMubWVyZ2UoZnVsbExheW91dCk7XG4gICAgb3B0aW9ucy5zY3JlZW5Cb3ggPSBbMCwgMCwgd2lkdGgsIGhlaWdodF07XG5cbiAgICB2YXIgbW9ja0dyYXBoRGl2ID0ge19mdWxsTGF5b3V0OiB7XG4gICAgICAgIF9heGlzQ29uc3RyYWludEdyb3VwczogdGhpcy5ncmFwaERpdi5fZnVsbExheW91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHMsXG4gICAgICAgIHhheGlzOiB0aGlzLnhheGlzLFxuICAgICAgICB5YXhpczogdGhpcy55YXhpc1xuICAgIH19O1xuXG4gICAgY2xlYW5BeGlzQ29uc3RyYWludHMobW9ja0dyYXBoRGl2LCB0aGlzLnhheGlzKTtcbiAgICBjbGVhbkF4aXNDb25zdHJhaW50cyhtb2NrR3JhcGhEaXYsIHRoaXMueWF4aXMpO1xuXG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplLFxuICAgICAgICBkb21haW5YID0gdGhpcy54YXhpcy5kb21haW4sXG4gICAgICAgIGRvbWFpblkgPSB0aGlzLnlheGlzLmRvbWFpbjtcblxuICAgIG9wdGlvbnMudmlld0JveCA9IFtcbiAgICAgICAgc2l6ZS5sICsgZG9tYWluWFswXSAqIHNpemUudyxcbiAgICAgICAgc2l6ZS5iICsgZG9tYWluWVswXSAqIHNpemUuaCxcbiAgICAgICAgKHdpZHRoIC0gc2l6ZS5yKSAtICgxIC0gZG9tYWluWFsxXSkgKiBzaXplLncsXG4gICAgICAgIChoZWlnaHQgLSBzaXplLnQpIC0gKDEgLSBkb21haW5ZWzFdKSAqIHNpemUuaFxuICAgIF07XG5cbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlLndpZHRoID0gc2l6ZS53ICogKGRvbWFpblhbMV0gLSBkb21haW5YWzBdKSArICdweCc7XG4gICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSBzaXplLmggKiAoZG9tYWluWVsxXSAtIGRvbWFpbllbMF0pICsgJ3B4JztcbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLmhlaWdodCA9IHNpemUuaCAqIChkb21haW5ZWzFdIC0gZG9tYWluWVswXSk7XG4gICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gc2l6ZS5sICsgZG9tYWluWFswXSAqIHNpemUudyArICdweCc7XG4gICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS50b3AgPSBzaXplLnQgKyAoMSAtIGRvbWFpbllbMV0pICogc2l6ZS5oICsgJ3B4JztcblxuICAgIHZhciBheCwgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICBheCA9IHRoaXNbQVhFU1tpXV07XG4gICAgICAgIGF4Ll9sZW5ndGggPSBvcHRpb25zLnZpZXdCb3hbaSArIDJdIC0gb3B0aW9ucy52aWV3Qm94W2ldO1xuXG4gICAgICAgIGRvQXV0b1JhbmdlKHRoaXMuZ3JhcGhEaXYsIGF4KTtcbiAgICAgICAgYXguc2V0U2NhbGUoKTtcbiAgICB9XG5cbiAgICBlbmZvcmNlQXhpc0NvbnN0cmFpbnRzKG1vY2tHcmFwaERpdik7XG5cbiAgICBvcHRpb25zLnRpY2tzID0gdGhpcy5jb21wdXRlVGlja01hcmtzKCk7XG5cbiAgICBvcHRpb25zLmRhdGFCb3ggPSB0aGlzLmNhbGNEYXRhQm94KCk7XG5cbiAgICBvcHRpb25zLm1lcmdlKGZ1bGxMYXlvdXQpO1xuICAgIGdscGxvdC51cGRhdGUob3B0aW9ucyk7XG5cbiAgICAvLyBmb3JjZSByZWRyYXcgc28gdGhhdCBwcm9taXNlIGlzIHJldHVybmVkIHdoZW4gcmVuZGVyaW5nIGlzIGNvbXBsZXRlZFxuICAgIHRoaXMuZ2xwbG90LmRyYXcoKTtcbn07XG5cbnByb3RvLmNhbGNEYXRhQm94ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHhheGlzID0gdGhpcy54YXhpcyxcbiAgICAgICAgeWF4aXMgPSB0aGlzLnlheGlzLFxuICAgICAgICB4cmFuZ2UgPSB4YXhpcy5yYW5nZSxcbiAgICAgICAgeXJhbmdlID0geWF4aXMucmFuZ2UsXG4gICAgICAgIHhyMmwgPSB4YXhpcy5yMmwsXG4gICAgICAgIHlyMmwgPSB5YXhpcy5yMmw7XG5cbiAgICByZXR1cm4gW3hyMmwoeHJhbmdlWzBdKSwgeXIybCh5cmFuZ2VbMF0pLCB4cjJsKHhyYW5nZVsxXSksIHlyMmwoeXJhbmdlWzFdKV07XG59O1xuXG5wcm90by5zZXRSYW5nZXMgPSBmdW5jdGlvbihkYXRhQm94KSB7XG4gICAgdmFyIHhheGlzID0gdGhpcy54YXhpcyxcbiAgICAgICAgeWF4aXMgPSB0aGlzLnlheGlzLFxuICAgICAgICB4bDJyID0geGF4aXMubDJyLFxuICAgICAgICB5bDJyID0geWF4aXMubDJyO1xuXG4gICAgeGF4aXMucmFuZ2UgPSBbeGwycihkYXRhQm94WzBdKSwgeGwycihkYXRhQm94WzJdKV07XG4gICAgeWF4aXMucmFuZ2UgPSBbeWwycihkYXRhQm94WzFdKSwgeWwycihkYXRhQm94WzNdKV07XG59O1xuXG5wcm90by51cGRhdGVUcmFjZXMgPSBmdW5jdGlvbihmdWxsRGF0YSwgY2FsY0RhdGEpIHtcbiAgICB2YXIgdHJhY2VJZHMgPSBPYmplY3Qua2V5cyh0aGlzLnRyYWNlcyk7XG4gICAgdmFyIGksIGosIGZ1bGxUcmFjZTtcblxuICAgIHRoaXMuZnVsbERhdGEgPSBmdWxsRGF0YTtcblxuICAgIC8vIHJlbW92ZSBlbXB0eSB0cmFjZXNcbiAgICB0cmFjZV9pZF9sb29wOlxuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvbGRVaWQgPSB0cmFjZUlkc1tpXSxcbiAgICAgICAgICAgIG9sZFRyYWNlID0gdGhpcy50cmFjZXNbb2xkVWlkXTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBmdWxsRGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgZnVsbFRyYWNlID0gZnVsbERhdGFbal07XG5cbiAgICAgICAgICAgIGlmKGZ1bGxUcmFjZS51aWQgPT09IG9sZFVpZCAmJiBmdWxsVHJhY2UudHlwZSA9PT0gb2xkVHJhY2UudHlwZSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlIHRyYWNlX2lkX2xvb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvbGRUcmFjZS5kaXNwb3NlKCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnRyYWNlc1tvbGRVaWRdO1xuICAgIH1cblxuICAgIC8vIHVwZGF0ZSAvIGNyZWF0ZSB0cmFjZSBvYmplY3RzXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZnVsbFRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjRGF0YVtpXSxcbiAgICAgICAgICAgIHRyYWNlT2JqID0gdGhpcy50cmFjZXNbZnVsbFRyYWNlLnVpZF07XG5cbiAgICAgICAgaWYodHJhY2VPYmopIHRyYWNlT2JqLnVwZGF0ZShmdWxsVHJhY2UsIGNhbGNUcmFjZSk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdHJhY2VPYmogPSBmdWxsVHJhY2UuX21vZHVsZS5wbG90KHRoaXMsIGZ1bGxUcmFjZSwgY2FsY1RyYWNlKTtcbiAgICAgICAgICAgIHRoaXMudHJhY2VzW2Z1bGxUcmFjZS51aWRdID0gdHJhY2VPYmo7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBvcmRlciBvYmplY3QgcGVyIHRyYWNlc1xuICAgIHRoaXMuZ2xwbG90Lm9iamVjdHMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBhLl90cmFjZS5pbmRleCAtIGIuX3RyYWNlLmluZGV4O1xuICAgIH0pO1xufTtcblxucHJvdG8udXBkYXRlRnggPSBmdW5jdGlvbihkcmFnbW9kZSkge1xuICAgIC8vIHN3aXRjaCB0byBzdmcgaW50ZXJhY3Rpb25zIGluIGxhc3NvL3NlbGVjdCBtb2RlXG4gICAgaWYoZHJhZ21vZGUgPT09ICdsYXNzbycgfHwgZHJhZ21vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgIHRoaXMucGlja0NhbnZhcy5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdub25lJztcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdub25lJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnBpY2tDYW52YXMuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnYXV0byc7XG4gICAgICAgIHRoaXMubW91c2VDb250YWluZXIuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnYXV0byc7XG4gICAgfVxuXG4gICAgLy8gc2V0IHByb3BlciBjdXJzb3JcbiAgICBpZihkcmFnbW9kZSA9PT0gJ3BhbicpIHtcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS5jdXJzb3IgPSAnbW92ZSc7XG4gICAgfVxuICAgIGVsc2UgaWYoZHJhZ21vZGUgPT09ICd6b29tJykge1xuICAgICAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlLmN1cnNvciA9ICdjcm9zc2hhaXInO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS5jdXJzb3IgPSBudWxsO1xuICAgIH1cbn07XG5cbnByb3RvLmVtaXRQb2ludEFjdGlvbiA9IGZ1bmN0aW9uKG5leHRTZWxlY3Rpb24sIGV2ZW50VHlwZSkge1xuICAgIHZhciB1aWQgPSBuZXh0U2VsZWN0aW9uLnRyYWNlLnVpZDtcbiAgICB2YXIgcHROdW1iZXIgPSBuZXh0U2VsZWN0aW9uLnBvaW50SW5kZXg7XG4gICAgdmFyIHRyYWNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRoaXMuZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodGhpcy5mdWxsRGF0YVtpXS51aWQgPT09IHVpZCkge1xuICAgICAgICAgICAgdHJhY2UgPSB0aGlzLmZ1bGxEYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvaW50RGF0YSA9IHtcbiAgICAgICAgeDogbmV4dFNlbGVjdGlvbi50cmFjZUNvb3JkWzBdLFxuICAgICAgICB5OiBuZXh0U2VsZWN0aW9uLnRyYWNlQ29vcmRbMV0sXG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgcG9pbnROdW1iZXI6IHB0TnVtYmVyLFxuICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgIGZ1bGxEYXRhOiB0aGlzLmZ1bGxEYXRhLFxuICAgICAgICB4YXhpczogdGhpcy54YXhpcyxcbiAgICAgICAgeWF4aXM6IHRoaXMueWF4aXNcbiAgICB9O1xuXG4gICAgRnguYXBwZW5kQXJyYXlQb2ludFZhbHVlKHBvaW50RGF0YSwgdHJhY2UsIHB0TnVtYmVyKTtcblxuICAgIHRoaXMuZ3JhcGhEaXYuZW1pdChldmVudFR5cGUsIHtwb2ludHM6IFtwb2ludERhdGFdfSk7XG59O1xuXG5wcm90by5kcmF3ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5zdG9wcGVkKSByZXR1cm47XG5cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5yZWRyYXcpO1xuXG4gICAgdmFyIGdscGxvdCA9IHRoaXMuZ2xwbG90LFxuICAgICAgICBjYW1lcmEgPSB0aGlzLmNhbWVyYSxcbiAgICAgICAgbW91c2VMaXN0ZW5lciA9IGNhbWVyYS5tb3VzZUxpc3RlbmVyLFxuICAgICAgICBtb3VzZVVwID0gdGhpcy5sYXN0QnV0dG9uU3RhdGUgPT09IDEgJiYgbW91c2VMaXN0ZW5lci5idXR0b25zID09PSAwLFxuICAgICAgICBmdWxsTGF5b3V0ID0gdGhpcy5mdWxsTGF5b3V0O1xuXG4gICAgdGhpcy5sYXN0QnV0dG9uU3RhdGUgPSBtb3VzZUxpc3RlbmVyLmJ1dHRvbnM7XG5cbiAgICB0aGlzLmNhbWVyYUNoYW5nZWQoKTtcblxuICAgIHZhciB4ID0gbW91c2VMaXN0ZW5lci54ICogZ2xwbG90LnBpeGVsUmF0aW87XG4gICAgdmFyIHkgPSB0aGlzLmNhbnZhcy5oZWlnaHQgLSBnbHBsb3QucGl4ZWxSYXRpbyAqIG1vdXNlTGlzdGVuZXIueTtcblxuICAgIHZhciByZXN1bHQ7XG5cbiAgICBpZihjYW1lcmEuYm94RW5hYmxlZCAmJiBmdWxsTGF5b3V0LmRyYWdtb2RlID09PSAnem9vbScpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RCb3guZW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgdmFyIHNlbGVjdEJveCA9IHRoaXMuc2VsZWN0Qm94LnNlbGVjdEJveCA9IFtcbiAgICAgICAgICAgIE1hdGgubWluKGNhbWVyYS5ib3hTdGFydFswXSwgY2FtZXJhLmJveEVuZFswXSksXG4gICAgICAgICAgICBNYXRoLm1pbihjYW1lcmEuYm94U3RhcnRbMV0sIGNhbWVyYS5ib3hFbmRbMV0pLFxuICAgICAgICAgICAgTWF0aC5tYXgoY2FtZXJhLmJveFN0YXJ0WzBdLCBjYW1lcmEuYm94RW5kWzBdKSxcbiAgICAgICAgICAgIE1hdGgubWF4KGNhbWVyYS5ib3hTdGFydFsxXSwgY2FtZXJhLmJveEVuZFsxXSlcbiAgICAgICAgXTtcblxuICAgICAgICAvLyAxRCB6b29tXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGNhbWVyYS5ib3hTdGFydFtpXSA9PT0gY2FtZXJhLmJveEVuZFtpXSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdEJveFtpXSA9IGdscGxvdC5kYXRhQm94W2ldO1xuICAgICAgICAgICAgICAgIHNlbGVjdEJveFtpICsgMl0gPSBnbHBsb3QuZGF0YUJveFtpICsgMl07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnbHBsb3Quc2V0RGlydHkoKTtcbiAgICB9XG4gICAgZWxzZSBpZighY2FtZXJhLnBhbm5pbmcgJiYgdGhpcy5pc01vdXNlT3Zlcikge1xuICAgICAgICB0aGlzLnNlbGVjdEJveC5lbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplLFxuICAgICAgICAgICAgZG9tYWluWCA9IHRoaXMueGF4aXMuZG9tYWluLFxuICAgICAgICAgICAgZG9tYWluWSA9IHRoaXMueWF4aXMuZG9tYWluO1xuXG4gICAgICAgIHJlc3VsdCA9IGdscGxvdC5waWNrKFxuICAgICAgICAgICAgKHggLyBnbHBsb3QucGl4ZWxSYXRpbykgKyBzaXplLmwgKyBkb21haW5YWzBdICogc2l6ZS53LFxuICAgICAgICAgICAgKHkgLyBnbHBsb3QucGl4ZWxSYXRpbykgLSAoc2l6ZS50ICsgKDEgLSBkb21haW5ZWzFdKSAqIHNpemUuaClcbiAgICAgICAgKTtcblxuICAgICAgICB2YXIgbmV4dFNlbGVjdGlvbiA9IHJlc3VsdCAmJiByZXN1bHQub2JqZWN0Ll90cmFjZS5oYW5kbGVQaWNrKHJlc3VsdCk7XG5cbiAgICAgICAgaWYobmV4dFNlbGVjdGlvbiAmJiBtb3VzZVVwKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXRQb2ludEFjdGlvbihuZXh0U2VsZWN0aW9uLCAncGxvdGx5X2NsaWNrJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihyZXN1bHQgJiYgcmVzdWx0Lm9iamVjdC5fdHJhY2UuaG92ZXJpbmZvICE9PSAnc2tpcCcgJiYgZnVsbExheW91dC5ob3Zlcm1vZGUpIHtcblxuICAgICAgICAgICAgaWYobmV4dFNlbGVjdGlvbiAmJiAoXG4gICAgICAgICAgICAgICAgIXRoaXMubGFzdFBpY2tSZXN1bHQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQaWNrUmVzdWx0LnRyYWNlVWlkICE9PSBuZXh0U2VsZWN0aW9uLnRyYWNlLnVpZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFBpY2tSZXN1bHQuZGF0YUNvb3JkWzBdICE9PSBuZXh0U2VsZWN0aW9uLmRhdGFDb29yZFswXSB8fFxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFBpY2tSZXN1bHQuZGF0YUNvb3JkWzFdICE9PSBuZXh0U2VsZWN0aW9uLmRhdGFDb29yZFsxXSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3Rpb24gPSBuZXh0U2VsZWN0aW9uO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UGlja1Jlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VVaWQ6IG5leHRTZWxlY3Rpb24udHJhY2UgPyBuZXh0U2VsZWN0aW9uLnRyYWNlLnVpZCA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFDb29yZDogbmV4dFNlbGVjdGlvbi5kYXRhQ29vcmQuc2xpY2UoKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5zcGlrZXMudXBkYXRlKHsgY2VudGVyOiByZXN1bHQuZGF0YUNvb3JkIH0pO1xuXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnNjcmVlbkNvb3JkID0gW1xuICAgICAgICAgICAgICAgICAgICAoKGdscGxvdC52aWV3Qm94WzJdIC0gZ2xwbG90LnZpZXdCb3hbMF0pICpcbiAgICAgICAgICAgICAgICAgICAgKHJlc3VsdC5kYXRhQ29vcmRbMF0gLSBnbHBsb3QuZGF0YUJveFswXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgKGdscGxvdC5kYXRhQm94WzJdIC0gZ2xwbG90LmRhdGFCb3hbMF0pICsgZ2xwbG90LnZpZXdCb3hbMF0pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbHBsb3QucGl4ZWxSYXRpbyxcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMuY2FudmFzLmhlaWdodCAtIChnbHBsb3Qudmlld0JveFszXSAtIGdscGxvdC52aWV3Qm94WzFdKSAqXG4gICAgICAgICAgICAgICAgICAgIChyZXN1bHQuZGF0YUNvb3JkWzFdIC0gZ2xwbG90LmRhdGFCb3hbMV0pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIChnbHBsb3QuZGF0YUJveFszXSAtIGdscGxvdC5kYXRhQm94WzFdKSAtIGdscGxvdC52aWV3Qm94WzFdKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2xwbG90LnBpeGVsUmF0aW9cbiAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBuZWVkcyB0byBoYXBwZW4gYmVmb3JlIHRoZSBuZXh0IGJsb2NrIHRoYXQgZGVsZXRlcyB0cmFjZUNvb3JkIGRhdGFcbiAgICAgICAgICAgICAgICAvLyBhbHNvIGl0J3MgaW1wb3J0YW50IHRvIGNvcHksIG90aGVyd2lzZSBkYXRhIGlzIGxvc3QgYnkgdGhlIHRpbWUgZXZlbnQgZGF0YSBpcyByZWFkXG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0UG9pbnRBY3Rpb24obmV4dFNlbGVjdGlvbiwgJ3Bsb3RseV9ob3ZlcicpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlID0gdGhpcy5mdWxsRGF0YVtzZWxlY3Rpb24udHJhY2UuaW5kZXhdIHx8IHt9O1xuICAgICAgICAgICAgICAgIHZhciBwdE51bWJlciA9IHNlbGVjdGlvbi5wb2ludEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBob3ZlcmluZm8gPSBGeC5jYXN0SG92ZXJpbmZvKHRyYWNlLCBmdWxsTGF5b3V0LCBwdE51bWJlcik7XG5cbiAgICAgICAgICAgICAgICBpZihob3ZlcmluZm8gJiYgaG92ZXJpbmZvICE9PSAnYWxsJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZigneCcpID09PSAtMSkgc2VsZWN0aW9uLnRyYWNlQ29vcmRbMF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKHBhcnRzLmluZGV4T2YoJ3knKSA9PT0gLTEpIHNlbGVjdGlvbi50cmFjZUNvb3JkWzFdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCd6JykgPT09IC0xKSBzZWxlY3Rpb24udHJhY2VDb29yZFsyXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZigndGV4dCcpID09PSAtMSkgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZignbmFtZScpID09PSAtMSkgc2VsZWN0aW9uLm5hbWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgICAgICAgICAgeDogc2VsZWN0aW9uLnNjcmVlbkNvb3JkWzBdLFxuICAgICAgICAgICAgICAgICAgICB5OiBzZWxlY3Rpb24uc2NyZWVuQ29vcmRbMV0sXG4gICAgICAgICAgICAgICAgICAgIHhMYWJlbDogdGhpcy5ob3ZlckZvcm1hdHRlcigneGF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZFswXSksXG4gICAgICAgICAgICAgICAgICAgIHlMYWJlbDogdGhpcy5ob3ZlckZvcm1hdHRlcigneWF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZFsxXSksXG4gICAgICAgICAgICAgICAgICAgIHpMYWJlbDogc2VsZWN0aW9uLnRyYWNlQ29vcmRbMl0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHNlbGVjdGlvbi50ZXh0TGFiZWwsXG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IHNlbGVjdGlvbi5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogRnguY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2JnY29sb3InKSB8fCBzZWxlY3Rpb24uY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnYm9yZGVyY29sb3InKSxcbiAgICAgICAgICAgICAgICAgICAgZm9udEZhbWlseTogRnguY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2ZvbnQuZmFtaWx5JyksXG4gICAgICAgICAgICAgICAgICAgIGZvbnRTaXplOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnZm9udC5zaXplJyksXG4gICAgICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogRnguY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2ZvbnQuY29sb3InKVxuICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyOiB0aGlzLnN2Z0NvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgZ2Q6IHRoaXMuZ3JhcGhEaXZcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlbW92ZSBob3ZlciBlZmZlY3RzIGlmIHdlJ3JlIG5vdCBvdmVyIGEgcG9pbnQgT1JcbiAgICAvLyBpZiB3ZSdyZSB6b29taW5nIG9yIHBhbm5pbmcgKGluIHdoaWNoIGNhc2UgcmVzdWx0IGlzIG5vdCBzZXQpXG4gICAgaWYoIXJlc3VsdCkge1xuICAgICAgICB0aGlzLnVuaG92ZXIoKTtcbiAgICB9XG5cbiAgICBnbHBsb3QuZHJhdygpO1xufTtcblxucHJvdG8udW5ob3ZlciA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMubGFzdFBpY2tSZXN1bHQpIHtcbiAgICAgICAgdGhpcy5zcGlrZXMudXBkYXRlKHt9KTtcbiAgICAgICAgdGhpcy5sYXN0UGlja1Jlc3VsdCA9IG51bGw7XG4gICAgICAgIHRoaXMuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X3VuaG92ZXInKTtcbiAgICAgICAgRngubG9uZVVuaG92ZXIodGhpcy5zdmdDb250YWluZXIpO1xuICAgIH1cbn07XG5cbnByb3RvLmhvdmVyRm9ybWF0dGVyID0gZnVuY3Rpb24oYXhpc05hbWUsIHZhbCkge1xuICAgIGlmKHZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgdmFyIGF4aXMgPSB0aGlzW2F4aXNOYW1lXTtcbiAgICByZXR1cm4gQXhlcy50aWNrVGV4dChheGlzLCBheGlzLmMybCh2YWwpLCAnaG92ZXInKS50ZXh0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVDYW1lcmE7XG5cbnZhciBub3cgPSByZXF1aXJlKCdyaWdodC1ub3cnKTtcbnZhciBjcmVhdGVWaWV3ID0gcmVxdWlyZSgnM2QtdmlldycpO1xudmFyIG1vdXNlQ2hhbmdlID0gcmVxdWlyZSgnbW91c2UtY2hhbmdlJyk7XG52YXIgbW91c2VXaGVlbCA9IHJlcXVpcmUoJ21vdXNlLXdoZWVsJyk7XG52YXIgbW91c2VPZmZzZXQgPSByZXF1aXJlKCdtb3VzZS1ldmVudC1vZmZzZXQnKTtcbnZhciBzdXBwb3J0c1Bhc3NpdmUgPSByZXF1aXJlKCdoYXMtcGFzc2l2ZS1ldmVudHMnKTtcblxuZnVuY3Rpb24gY3JlYXRlQ2FtZXJhKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICBlbGVtZW50ID0gZWxlbWVudCB8fCBkb2N1bWVudC5ib2R5O1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgdmFyIGxpbWl0cyA9IFsgMC4wMSwgSW5maW5pdHkgXTtcbiAgICBpZignZGlzdGFuY2VMaW1pdHMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgbGltaXRzWzBdID0gb3B0aW9ucy5kaXN0YW5jZUxpbWl0c1swXTtcbiAgICAgICAgbGltaXRzWzFdID0gb3B0aW9ucy5kaXN0YW5jZUxpbWl0c1sxXTtcbiAgICB9XG4gICAgaWYoJ3pvb21NaW4nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgbGltaXRzWzBdID0gb3B0aW9ucy56b29tTWluO1xuICAgIH1cbiAgICBpZignem9vbU1heCcgaW4gb3B0aW9ucykge1xuICAgICAgICBsaW1pdHNbMV0gPSBvcHRpb25zLnpvb21NYXg7XG4gICAgfVxuXG4gICAgdmFyIHZpZXcgPSBjcmVhdGVWaWV3KHtcbiAgICAgICAgY2VudGVyOiBvcHRpb25zLmNlbnRlciB8fCBbMCwgMCwgMF0sXG4gICAgICAgIHVwOiBvcHRpb25zLnVwIHx8IFswLCAxLCAwXSxcbiAgICAgICAgZXllOiBvcHRpb25zLmV5ZSB8fCBbMCwgMCwgMTBdLFxuICAgICAgICBtb2RlOiBvcHRpb25zLm1vZGUgfHwgJ29yYml0JyxcbiAgICAgICAgZGlzdGFuY2VMaW1pdHM6IGxpbWl0c1xuICAgIH0pO1xuXG4gICAgdmFyIHBtYXRyaXggPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07XG4gICAgdmFyIGRpc3RhbmNlID0gMC4wO1xuICAgIHZhciB3aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgdmFyIGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuXG4gICAgdmFyIGNhbWVyYSA9IHtcbiAgICAgICAga2V5QmluZGluZ01vZGU6ICdyb3RhdGUnLFxuICAgICAgICB2aWV3OiB2aWV3LFxuICAgICAgICBlbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBkZWxheTogb3B0aW9ucy5kZWxheSB8fCAxNixcbiAgICAgICAgcm90YXRlU3BlZWQ6IG9wdGlvbnMucm90YXRlU3BlZWQgfHwgMSxcbiAgICAgICAgem9vbVNwZWVkOiBvcHRpb25zLnpvb21TcGVlZCB8fCAxLFxuICAgICAgICB0cmFuc2xhdGVTcGVlZDogb3B0aW9ucy50cmFuc2xhdGVTcGVlZCB8fCAxLFxuICAgICAgICBmbGlwWDogISFvcHRpb25zLmZsaXBYLFxuICAgICAgICBmbGlwWTogISFvcHRpb25zLmZsaXBZLFxuICAgICAgICBtb2Rlczogdmlldy5tb2RlcyxcbiAgICAgICAgdGljazogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgdCA9IG5vdygpO1xuICAgICAgICAgICAgdmFyIGRlbGF5ID0gdGhpcy5kZWxheTtcbiAgICAgICAgICAgIHZhciBjdGltZSA9IHQgLSAyICogZGVsYXk7XG4gICAgICAgICAgICB2aWV3LmlkbGUodCAtIGRlbGF5KTtcbiAgICAgICAgICAgIHZpZXcucmVjYWxjTWF0cml4KGN0aW1lKTtcbiAgICAgICAgICAgIHZpZXcuZmx1c2godCAtICgxMDAgKyBkZWxheSAqIDIpKTtcbiAgICAgICAgICAgIHZhciBhbGxFcXVhbCA9IHRydWU7XG4gICAgICAgICAgICB2YXIgbWF0cml4ID0gdmlldy5jb21wdXRlZE1hdHJpeDtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCAxNjsgKytpKSB7XG4gICAgICAgICAgICAgICAgYWxsRXF1YWwgPSBhbGxFcXVhbCAmJiAocG1hdHJpeFtpXSA9PT0gbWF0cml4W2ldKTtcbiAgICAgICAgICAgICAgICBwbWF0cml4W2ldID0gbWF0cml4W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHNpemVDaGFuZ2VkID1cbiAgICAgICAgICAgICAgICBlbGVtZW50LmNsaWVudFdpZHRoID09PSB3aWR0aCAmJlxuICAgICAgICAgICAgICAgIGVsZW1lbnQuY2xpZW50SGVpZ2h0ID09PSBoZWlnaHQ7XG4gICAgICAgICAgICB3aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIGlmKGFsbEVxdWFsKSByZXR1cm4gIXNpemVDaGFuZ2VkO1xuICAgICAgICAgICAgZGlzdGFuY2UgPSBNYXRoLmV4cCh2aWV3LmNvbXB1dGVkUmFkaXVzWzBdKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBsb29rQXQ6IGZ1bmN0aW9uKGNlbnRlciwgZXllLCB1cCkge1xuICAgICAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBjZW50ZXIsIGV5ZSwgdXApO1xuICAgICAgICB9LFxuICAgICAgICByb3RhdGU6IGZ1bmN0aW9uKHBpdGNoLCB5YXcsIHJvbGwpIHtcbiAgICAgICAgICAgIHZpZXcucm90YXRlKHZpZXcubGFzdFQoKSwgcGl0Y2gsIHlhdywgcm9sbCk7XG4gICAgICAgIH0sXG4gICAgICAgIHBhbjogZnVuY3Rpb24oZHgsIGR5LCBkeikge1xuICAgICAgICAgICAgdmlldy5wYW4odmlldy5sYXN0VCgpLCBkeCwgZHksIGR6KTtcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNsYXRlOiBmdW5jdGlvbihkeCwgZHksIGR6KSB7XG4gICAgICAgICAgICB2aWV3LnRyYW5zbGF0ZSh2aWV3Lmxhc3RUKCksIGR4LCBkeSwgZHopO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGNhbWVyYSwge1xuICAgICAgICBtYXRyaXg6IHtcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRNYXRyaXg7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihtYXQpIHtcbiAgICAgICAgICAgICAgICB2aWV3LnNldE1hdHJpeCh2aWV3Lmxhc3RUKCksIG1hdCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRNYXRyaXg7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBtb2RlOiB7XG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2aWV3LmdldE1vZGUoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKG1vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VyVXAgPSB2aWV3LmNvbXB1dGVkVXAuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgY3VyRXllID0gdmlldy5jb21wdXRlZEV5ZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBjdXJDZW50ZXIgPSB2aWV3LmNvbXB1dGVkQ2VudGVyLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmlldy5zZXRNb2RlKG1vZGUpO1xuICAgICAgICAgICAgICAgIGlmKG1vZGUgPT09ICd0dXJudGFibGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhhY2t5IHRpbWUgd2FycGluZyBzdHVmZiB0byBnZW5lcmF0ZSBzbW9vdGggYW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgICAgIHZhciB0MCA9IG5vdygpO1xuICAgICAgICAgICAgICAgICAgICB2aWV3Ll9hY3RpdmUubG9va0F0KHQwLCBjdXJFeWUsIGN1ckNlbnRlciwgY3VyVXApO1xuICAgICAgICAgICAgICAgICAgICB2aWV3Ll9hY3RpdmUubG9va0F0KHQwICsgNTAwLCBjdXJFeWUsIGN1ckNlbnRlciwgWzAsIDAsIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgdmlldy5fYWN0aXZlLmZsdXNoKHQwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuZ2V0TW9kZSgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgY2VudGVyOiB7XG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkQ2VudGVyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24obmNlbnRlcikge1xuICAgICAgICAgICAgICAgIHZpZXcubG9va0F0KHZpZXcubGFzdFQoKSwgbnVsbCwgbmNlbnRlcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRDZW50ZXI7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBleWU6IHtcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRFeWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihuZXllKSB7XG4gICAgICAgICAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBuZXllKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZEV5ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIHVwOiB7XG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkVXA7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihudXApIHtcbiAgICAgICAgICAgICAgICB2aWV3Lmxvb2tBdCh2aWV3Lmxhc3RUKCksIG51bGwsIG51bGwsIG51cCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRVcDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIGRpc3RhbmNlOiB7XG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkaXN0YW5jZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2aWV3LnNldERpc3RhbmNlKHZpZXcubGFzdFQoKSwgZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBkaXN0YW5jZUxpbWl0czoge1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmlldy5nZXREaXN0YW5jZUxpbWl0cyhsaW1pdHMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgIHZpZXcuc2V0RGlzdGFuY2VMaW1pdHModik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuXG4gICAgdmFyIGxhc3RYID0gMCwgbGFzdFkgPSAwLCBsYXN0TW9kcyA9IHtzaGlmdDogZmFsc2UsIGNvbnRyb2w6IGZhbHNlLCBhbHQ6IGZhbHNlLCBtZXRhOiBmYWxzZX07XG4gICAgY2FtZXJhLm1vdXNlTGlzdGVuZXIgPSBtb3VzZUNoYW5nZShlbGVtZW50LCBoYW5kbGVJbnRlcmFjdGlvbik7XG5cbiAgICAvLyBlbmFibGUgc2ltcGxlIHRvdWNoIGludGVyYWN0aW9uc1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KTtcbiAgICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMCwgeHlbMF0sIHh5WzFdLCBsYXN0TW9kcyk7XG4gICAgICAgIGhhbmRsZUludGVyYWN0aW9uKDEsIHh5WzBdLCB4eVsxXSwgbGFzdE1vZHMpO1xuXG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSwgc3VwcG9ydHNQYXNzaXZlID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKTtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KTtcbiAgICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMSwgeHlbMF0sIHh5WzFdLCBsYXN0TW9kcyk7XG5cbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9LCBzdXBwb3J0c1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpO1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBmdW5jdGlvbihldikge1xuICAgICAgICBoYW5kbGVJbnRlcmFjdGlvbigwLCBsYXN0WCwgbGFzdFksIGxhc3RNb2RzKTtcblxuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIHN1cHBvcnRzUGFzc2l2ZSA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSk7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVJbnRlcmFjdGlvbihidXR0b25zLCB4LCB5LCBtb2RzKSB7XG4gICAgICAgIHZhciBrZXlCaW5kaW5nTW9kZSA9IGNhbWVyYS5rZXlCaW5kaW5nTW9kZTtcblxuICAgICAgICBpZihrZXlCaW5kaW5nTW9kZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgICAgICB2YXIgcm90YXRlID0ga2V5QmluZGluZ01vZGUgPT09ICdyb3RhdGUnO1xuICAgICAgICB2YXIgcGFuID0ga2V5QmluZGluZ01vZGUgPT09ICdwYW4nO1xuICAgICAgICB2YXIgem9vbSA9IGtleUJpbmRpbmdNb2RlID09PSAnem9vbSc7XG5cbiAgICAgICAgdmFyIGN0cmwgPSAhIW1vZHMuY29udHJvbDtcbiAgICAgICAgdmFyIGFsdCA9ICEhbW9kcy5hbHQ7XG4gICAgICAgIHZhciBzaGlmdCA9ICEhbW9kcy5zaGlmdDtcbiAgICAgICAgdmFyIGxlZnQgPSAhIShidXR0b25zICYgMSk7XG4gICAgICAgIHZhciByaWdodCA9ICEhKGJ1dHRvbnMgJiAyKTtcbiAgICAgICAgdmFyIG1pZGRsZSA9ICEhKGJ1dHRvbnMgJiA0KTtcblxuICAgICAgICB2YXIgc2NhbGUgPSAxLjAgLyBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgdmFyIGR4ID0gc2NhbGUgKiAoeCAtIGxhc3RYKTtcbiAgICAgICAgdmFyIGR5ID0gc2NhbGUgKiAoeSAtIGxhc3RZKTtcblxuICAgICAgICB2YXIgZmxpcFggPSBjYW1lcmEuZmxpcFggPyAxIDogLTE7XG4gICAgICAgIHZhciBmbGlwWSA9IGNhbWVyYS5mbGlwWSA/IDEgOiAtMTtcblxuICAgICAgICB2YXIgdCA9IG5vdygpO1xuXG4gICAgICAgIHZhciBkcm90ID0gTWF0aC5QSSAqIGNhbWVyYS5yb3RhdGVTcGVlZDtcblxuICAgICAgICBpZigocm90YXRlICYmIGxlZnQgJiYgIWN0cmwgJiYgIWFsdCAmJiAhc2hpZnQpIHx8IChsZWZ0ICYmICFjdHJsICYmICFhbHQgJiYgc2hpZnQpKSB7XG4gICAgICAgICAgICAvLyBSb3RhdGVcbiAgICAgICAgICAgIHZpZXcucm90YXRlKHQsIGZsaXBYICogZHJvdCAqIGR4LCAtZmxpcFkgKiBkcm90ICogZHksIDApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoKHBhbiAmJiBsZWZ0ICYmICFjdHJsICYmICFhbHQgJiYgIXNoaWZ0KSB8fCByaWdodCB8fCAobGVmdCAmJiBjdHJsICYmICFhbHQgJiYgIXNoaWZ0KSkge1xuICAgICAgICAgICAgLy8gUGFuXG4gICAgICAgICAgICB2aWV3LnBhbih0LCAtY2FtZXJhLnRyYW5zbGF0ZVNwZWVkICogZHggKiBkaXN0YW5jZSwgY2FtZXJhLnRyYW5zbGF0ZVNwZWVkICogZHkgKiBkaXN0YW5jZSwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZigoem9vbSAmJiBsZWZ0ICYmICFjdHJsICYmICFhbHQgJiYgIXNoaWZ0KSB8fCBtaWRkbGUgfHwgKGxlZnQgJiYgIWN0cmwgJiYgYWx0ICYmICFzaGlmdCkpIHtcbiAgICAgICAgICAgIC8vIFpvb21cbiAgICAgICAgICAgIHZhciBrem9vbSA9IC1jYW1lcmEuem9vbVNwZWVkICogZHkgLyB3aW5kb3cuaW5uZXJIZWlnaHQgKiAodCAtIHZpZXcubGFzdFQoKSkgKiAxMDA7XG4gICAgICAgICAgICB2aWV3LnBhbih0LCAwLCAwLCBkaXN0YW5jZSAqIChNYXRoLmV4cChrem9vbSkgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXN0WCA9IHg7XG4gICAgICAgIGxhc3RZID0geTtcbiAgICAgICAgbGFzdE1vZHMgPSBtb2RzO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGNhbWVyYS53aGVlbExpc3RlbmVyID0gbW91c2VXaGVlbChlbGVtZW50LCBmdW5jdGlvbihkeCwgZHkpIHtcbiAgICAgICAgaWYoY2FtZXJhLmtleUJpbmRpbmdNb2RlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBmbGlwWCA9IGNhbWVyYS5mbGlwWCA/IDEgOiAtMTtcbiAgICAgICAgdmFyIGZsaXBZID0gY2FtZXJhLmZsaXBZID8gMSA6IC0xO1xuICAgICAgICB2YXIgdCA9IG5vdygpO1xuICAgICAgICBpZihNYXRoLmFicyhkeCkgPiBNYXRoLmFicyhkeSkpIHtcbiAgICAgICAgICAgIHZpZXcucm90YXRlKHQsIDAsIDAsIC1keCAqIGZsaXBYICogTWF0aC5QSSAqIGNhbWVyYS5yb3RhdGVTcGVlZCAvIHdpbmRvdy5pbm5lcldpZHRoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBrem9vbSA9IC1jYW1lcmEuem9vbVNwZWVkICogZmxpcFkgKiBkeSAvIHdpbmRvdy5pbm5lckhlaWdodCAqICh0IC0gdmlldy5sYXN0VCgpKSAvIDIwLjA7XG4gICAgICAgICAgICB2aWV3LnBhbih0LCAwLCAwLCBkaXN0YW5jZSAqIChNYXRoLmV4cChrem9vbSkgLSAxKSk7XG4gICAgICAgIH1cbiAgICB9LCB0cnVlKTtcblxuICAgIHJldHVybiBjYW1lcmE7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGZ4QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4L2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBTY2VuZSA9IHJlcXVpcmUoJy4vc2NlbmUnKTtcbnZhciBnZXRTdWJwbG90RGF0YSA9IHJlcXVpcmUoJy4uL2dldF9kYXRhJykuZ2V0U3VicGxvdERhdGE7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcblxudmFyIEdMM0QgPSAnZ2wzZCc7XG52YXIgU0NFTkUgPSAnc2NlbmUnO1xuXG5cbmV4cG9ydHMubmFtZSA9IEdMM0Q7XG5cbmV4cG9ydHMuYXR0ciA9IFNDRU5FO1xuXG5leHBvcnRzLmlkUm9vdCA9IFNDRU5FO1xuXG5leHBvcnRzLmlkUmVnZXggPSBleHBvcnRzLmF0dHJSZWdleCA9IExpYi5jb3VudGVyUmVnZXgoJ3NjZW5lJyk7XG5cbmV4cG9ydHMuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0L2F0dHJpYnV0ZXMnKTtcblxuZXhwb3J0cy5sYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXQvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxuZXhwb3J0cy5iYXNlTGF5b3V0QXR0ck92ZXJyaWRlcyA9IG92ZXJyaWRlQWxsKHtcbiAgICBob3ZlcmxhYmVsOiBmeEF0dHJzLmhvdmVybGFiZWxcbn0sICdwbG90JywgJ25lc3RlZCcpO1xuXG5leHBvcnRzLnN1cHBseUxheW91dERlZmF1bHRzID0gcmVxdWlyZSgnLi9sYXlvdXQvZGVmYXVsdHMnKTtcblxuZXhwb3J0cy5wbG90ID0gZnVuY3Rpb24gcGxvdEdsM2QoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgc2NlbmVJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1tHTDNEXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzY2VuZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2NlbmVJZCA9IHNjZW5lSWRzW2ldLFxuICAgICAgICAgICAgZnVsbFNjZW5lRGF0YSA9IGdldFN1YnBsb3REYXRhKGZ1bGxEYXRhLCBHTDNELCBzY2VuZUlkKSxcbiAgICAgICAgICAgIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkXSxcbiAgICAgICAgICAgIHNjZW5lID0gc2NlbmVMYXlvdXQuX3NjZW5lO1xuXG4gICAgICAgIGlmKCFzY2VuZSkge1xuICAgICAgICAgICAgc2NlbmUgPSBuZXcgU2NlbmUoe1xuICAgICAgICAgICAgICAgIGlkOiBzY2VuZUlkLFxuICAgICAgICAgICAgICAgIGdyYXBoRGl2OiBnZCxcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGdkLnF1ZXJ5U2VsZWN0b3IoJy5nbC1jb250YWluZXInKSxcbiAgICAgICAgICAgICAgICBzdGF0aWNQbG90OiBnZC5fY29udGV4dC5zdGF0aWNQbG90LFxuICAgICAgICAgICAgICAgIHBsb3RHbFBpeGVsUmF0aW86IGdkLl9jb250ZXh0LnBsb3RHbFBpeGVsUmF0aW9cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZnVsbExheW91dFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgLy8gc2V0IHJlZiB0byBTY2VuZSBpbnN0YW5jZVxuICAgICAgICAgICAgc2NlbmVMYXlvdXQuX3NjZW5lID0gc2NlbmU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzYXZlICdpbml0aWFsJyBjYW1lcmEgc2V0dGluZ3MgZm9yIG1vZGViYXIgYnV0dG9uXG4gICAgICAgIGlmKCFzY2VuZS5jYW1lcmFJbml0aWFsKSB7XG4gICAgICAgICAgICBzY2VuZS5jYW1lcmFJbml0aWFsID0gTGliLmV4dGVuZERlZXAoe30sIHNjZW5lTGF5b3V0LmNhbWVyYSk7XG4gICAgICAgIH1cblxuICAgICAgICBzY2VuZS5wbG90KGZ1bGxTY2VuZURhdGEsIGZ1bGxMYXlvdXQsIGdkLmxheW91dCk7XG4gICAgfVxufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRTY2VuZUtleXMgPSBvbGRGdWxsTGF5b3V0Ll9zdWJwbG90c1tHTDNEXSB8fCBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRTY2VuZUtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9sZFNjZW5lS2V5ID0gb2xkU2NlbmVLZXlzW2ldO1xuXG4gICAgICAgIGlmKCFuZXdGdWxsTGF5b3V0W29sZFNjZW5lS2V5XSAmJiAhIW9sZEZ1bGxMYXlvdXRbb2xkU2NlbmVLZXldLl9zY2VuZSkge1xuICAgICAgICAgICAgb2xkRnVsbExheW91dFtvbGRTY2VuZUtleV0uX3NjZW5lLmRlc3Ryb3koKTtcblxuICAgICAgICAgICAgaWYob2xkRnVsbExheW91dC5faW5mb2xheWVyKSB7XG4gICAgICAgICAgICAgICAgb2xkRnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJy5hbm5vdGF0aW9uLScgKyBvbGRTY2VuZUtleSlcbiAgICAgICAgICAgICAgICAgICAgLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZXhwb3J0cy50b1NWRyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc2NlbmVJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1tHTDNEXTtcbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2NlbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkc1tpXV07XG4gICAgICAgIHZhciBkb21haW4gPSBzY2VuZUxheW91dC5kb21haW47XG4gICAgICAgIHZhciBzY2VuZSA9IHNjZW5lTGF5b3V0Ll9zY2VuZTtcblxuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gc2NlbmUudG9JbWFnZSgncG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnc3ZnOmltYWdlJyk7XG5cbiAgICAgICAgaW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4bWxuczogeG1sbnNOYW1lc3BhY2VzLnN2ZyxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogaW1hZ2VEYXRhLFxuICAgICAgICAgICAgeDogc2l6ZS5sICsgc2l6ZS53ICogZG9tYWluLnhbMF0sXG4gICAgICAgICAgICB5OiBzaXplLnQgKyBzaXplLmggKiAoMSAtIGRvbWFpbi55WzFdKSxcbiAgICAgICAgICAgIHdpZHRoOiBzaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSksXG4gICAgICAgICAgICBoZWlnaHQ6IHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSxcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICdub25lJ1xuICAgICAgICB9KTtcblxuICAgICAgICBzY2VuZS5kZXN0cm95KCk7XG4gICAgfVxufTtcblxuLy8gY2xlYW4gc2NlbmUgaWRzLCAnc2NlbmUxJyAtPiAnc2NlbmUnXG5leHBvcnRzLmNsZWFuSWQgPSBmdW5jdGlvbiBjbGVhbklkKGlkKSB7XG4gICAgaWYoIWlkLm1hdGNoKC9ec2NlbmVbMC05XSokLykpIHJldHVybjtcblxuICAgIHZhciBzY2VuZU51bSA9IGlkLnN1YnN0cig1KTtcbiAgICBpZihzY2VuZU51bSA9PT0gJzEnKSBzY2VuZU51bSA9ICcnO1xuXG4gICAgcmV0dXJuIFNDRU5FICsgc2NlbmVOdW07XG59O1xuXG5leHBvcnRzLnVwZGF0ZUZ4ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbR0wzRF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VicGxvdE9iaiA9IGZ1bGxMYXlvdXRbc3VicGxvdElkc1tpXV0uX3NjZW5lO1xuICAgICAgICBzdWJwbG90T2JqLnVwZGF0ZUZ4KGZ1bGxMYXlvdXQuZHJhZ21vZGUsIGZ1bGxMYXlvdXQuaG92ZXJtb2RlKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNjZW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3NjZW5lJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGF4ZXNBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgdmlzaWJsZTogYXhlc0F0dHJzLnZpc2libGUsXG4gICAgc2hvd3NwaWtlczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwaWtlc2lkZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZXRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMixcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93YmFja2dyb3VuZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYWNrZ3JvdW5kY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdyZ2JhKDIwNCwgMjA0LCAyMDQsIDAuNSknLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dheGVzbGFiZWxzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29sb3I6IGF4ZXNBdHRycy5jb2xvcixcbiAgICBjYXRlZ29yeW9yZGVyOiBheGVzQXR0cnMuY2F0ZWdvcnlvcmRlcixcbiAgICBjYXRlZ29yeWFycmF5OiBheGVzQXR0cnMuY2F0ZWdvcnlhcnJheSxcbiAgICB0aXRsZTogYXhlc0F0dHJzLnRpdGxlLFxuICAgIHRpdGxlZm9udDogYXhlc0F0dHJzLnRpdGxlZm9udCxcbiAgICB0eXBlOiBheGVzQXR0cnMudHlwZSxcbiAgICBhdXRvcmFuZ2U6IGF4ZXNBdHRycy5hdXRvcmFuZ2UsXG4gICAgcmFuZ2Vtb2RlOiBheGVzQXR0cnMucmFuZ2Vtb2RlLFxuICAgIHJhbmdlOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMucmFuZ2UsIHtcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdwbG90JywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX19LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3Bsb3QnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfX1cbiAgICAgICAgXSxcbiAgICAgICAgYW5pbTogZmFsc2VcbiAgICB9KSxcbiAgICAvLyB0aWNrc1xuICAgIHRpY2ttb2RlOiBheGVzQXR0cnMudGlja21vZGUsXG4gICAgbnRpY2tzOiBheGVzQXR0cnMubnRpY2tzLFxuICAgIHRpY2swOiBheGVzQXR0cnMudGljazAsXG4gICAgZHRpY2s6IGF4ZXNBdHRycy5kdGljayxcbiAgICB0aWNrdmFsczogYXhlc0F0dHJzLnRpY2t2YWxzLFxuICAgIHRpY2t0ZXh0OiBheGVzQXR0cnMudGlja3RleHQsXG4gICAgdGlja3M6IGF4ZXNBdHRycy50aWNrcyxcbiAgICBtaXJyb3I6IGF4ZXNBdHRycy5taXJyb3IsXG4gICAgdGlja2xlbjogYXhlc0F0dHJzLnRpY2tsZW4sXG4gICAgdGlja3dpZHRoOiBheGVzQXR0cnMudGlja3dpZHRoLFxuICAgIHRpY2tjb2xvcjogYXhlc0F0dHJzLnRpY2tjb2xvcixcbiAgICBzaG93dGlja2xhYmVsczogYXhlc0F0dHJzLnNob3d0aWNrbGFiZWxzLFxuICAgIHRpY2tmb250OiBheGVzQXR0cnMudGlja2ZvbnQsXG4gICAgdGlja2FuZ2xlOiBheGVzQXR0cnMudGlja2FuZ2xlLFxuICAgIHRpY2twcmVmaXg6IGF4ZXNBdHRycy50aWNrcHJlZml4LFxuICAgIHNob3d0aWNrcHJlZml4OiBheGVzQXR0cnMuc2hvd3RpY2twcmVmaXgsXG4gICAgdGlja3N1ZmZpeDogYXhlc0F0dHJzLnRpY2tzdWZmaXgsXG4gICAgc2hvd3RpY2tzdWZmaXg6IGF4ZXNBdHRycy5zaG93dGlja3N1ZmZpeCxcbiAgICBzaG93ZXhwb25lbnQ6IGF4ZXNBdHRycy5zaG93ZXhwb25lbnQsXG4gICAgZXhwb25lbnRmb3JtYXQ6IGF4ZXNBdHRycy5leHBvbmVudGZvcm1hdCxcbiAgICBzZXBhcmF0ZXRob3VzYW5kczogYXhlc0F0dHJzLnNlcGFyYXRldGhvdXNhbmRzLFxuICAgIHRpY2tmb3JtYXQ6IGF4ZXNBdHRycy50aWNrZm9ybWF0LFxuICAgIHRpY2tmb3JtYXRzdG9wczogYXhlc0F0dHJzLnRpY2tmb3JtYXRzdG9wcyxcbiAgICBob3ZlcmZvcm1hdDogYXhlc0F0dHJzLmhvdmVyZm9ybWF0LFxuICAgIC8vIGxpbmVzIGFuZCBncmlkc1xuICAgIHNob3dsaW5lOiBheGVzQXR0cnMuc2hvd2xpbmUsXG4gICAgbGluZWNvbG9yOiBheGVzQXR0cnMubGluZWNvbG9yLFxuICAgIGxpbmV3aWR0aDogYXhlc0F0dHJzLmxpbmV3aWR0aCxcbiAgICBzaG93Z3JpZDogYXhlc0F0dHJzLnNob3dncmlkLFxuICAgIGdyaWRjb2xvcjogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLmdyaWRjb2xvciwgIC8vIHNob3VsZG4ndCB0aGlzIGJlIG9uLXBhciB3aXRoIDJEP1xuICAgICAgICB7ZGZsdDogJ3JnYigyMDQsIDIwNCwgMjA0KSd9KSxcbiAgICBncmlkd2lkdGg6IGF4ZXNBdHRycy5ncmlkd2lkdGgsXG4gICAgemVyb2xpbmU6IGF4ZXNBdHRycy56ZXJvbGluZSxcbiAgICB6ZXJvbGluZWNvbG9yOiBheGVzQXR0cnMuemVyb2xpbmVjb2xvcixcbiAgICB6ZXJvbGluZXdpZHRoOiBheGVzQXR0cnMuemVyb2xpbmV3aWR0aFxufSwgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yTWl4ID0gcmVxdWlyZSgndGlueWNvbG9yMicpLm1peDtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYicpO1xudmFyIFRlbXBsYXRlID0gcmVxdWlyZSgnLi4vLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xuXG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXhpc19hdHRyaWJ1dGVzJyk7XG52YXIgaGFuZGxlVHlwZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vY2FydGVzaWFuL3R5cGVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVBeGlzRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jYXJ0ZXNpYW4vYXhpc19kZWZhdWx0cycpO1xuXG52YXIgYXhlc05hbWVzID0gWyd4YXhpcycsICd5YXhpcycsICd6YXhpcyddO1xuXG4vLyBUT0RPOiBoYXJkLWNvZGVkIGxpZ2h0bmVzcyBmcmFjdGlvbiBiYXNlZCBvbiBncmlkbGluZSBkZWZhdWx0IGNvbG9yc1xuLy8gdGhhdCBkaWZmZXIgZnJvbSBvdGhlciBzdWJwbG90IHR5cGVzLlxudmFyIGdyaWRMaWdodG5lc3MgPSAxMDAgKiAoMjA0IC0gMHg0NCkgLyAoMjU1IC0gMHg0NCk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgb3B0aW9ucykge1xuICAgIHZhciBjb250YWluZXJJbiwgY29udGFpbmVyT3V0O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGF4ZXNOYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgYXhOYW1lID0gYXhlc05hbWVzW2pdO1xuICAgICAgICBjb250YWluZXJJbiA9IGxheW91dEluW2F4TmFtZV0gfHwge307XG5cbiAgICAgICAgY29udGFpbmVyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGxheW91dE91dCwgYXhOYW1lKTtcbiAgICAgICAgY29udGFpbmVyT3V0Ll9pZCA9IGF4TmFtZVswXSArIG9wdGlvbnMuc2NlbmU7XG4gICAgICAgIGNvbnRhaW5lck91dC5fbmFtZSA9IGF4TmFtZTtcblxuICAgICAgICBoYW5kbGVUeXBlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zKTtcblxuICAgICAgICBoYW5kbGVBeGlzRGVmYXVsdHMoXG4gICAgICAgICAgICBjb250YWluZXJJbixcbiAgICAgICAgICAgIGNvbnRhaW5lck91dCxcbiAgICAgICAgICAgIGNvZXJjZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmb250OiBvcHRpb25zLmZvbnQsXG4gICAgICAgICAgICAgICAgbGV0dGVyOiBheE5hbWVbMF0sXG4gICAgICAgICAgICAgICAgZGF0YTogb3B0aW9ucy5kYXRhLFxuICAgICAgICAgICAgICAgIHNob3dHcmlkOiB0cnVlLFxuICAgICAgICAgICAgICAgIGJnQ29sb3I6IG9wdGlvbnMuYmdDb2xvcixcbiAgICAgICAgICAgICAgICBjYWxlbmRhcjogb3B0aW9ucy5jYWxlbmRhclxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbnMuZnVsbExheW91dCk7XG5cbiAgICAgICAgY29lcmNlKCdncmlkY29sb3InLCBjb2xvck1peChjb250YWluZXJPdXQuY29sb3IsIG9wdGlvbnMuYmdDb2xvciwgZ3JpZExpZ2h0bmVzcykudG9SZ2JTdHJpbmcoKSk7XG4gICAgICAgIGNvZXJjZSgndGl0bGUnLCBheE5hbWVbMF0pOyAgLy8gc2hvdWxkbid0IHRoaXMgYmUgb24tcGFyIHdpdGggMkQ/XG5cbiAgICAgICAgY29udGFpbmVyT3V0LnNldFNjYWxlID0gTGliLm5vb3A7XG5cbiAgICAgICAgaWYoY29lcmNlKCdzaG93c3Bpa2VzJykpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnc3Bpa2VzaWRlcycpO1xuICAgICAgICAgICAgY29lcmNlKCdzcGlrZXRoaWNrbmVzcycpO1xuICAgICAgICAgICAgY29lcmNlKCdzcGlrZWNvbG9yJywgY29udGFpbmVyT3V0LmNvbG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvZXJjZSgnc2hvd2F4ZXNsYWJlbHMnKTtcbiAgICAgICAgaWYoY29lcmNlKCdzaG93YmFja2dyb3VuZCcpKSBjb2VyY2UoJ2JhY2tncm91bmRjb2xvcicpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbnZlcnRIVE1MVG9Vbmljb2RlID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL2h0bWwydW5pY29kZScpO1xudmFyIHN0cjJSZ2JhQXJyYXkgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG5cbnZhciBBWEVTX05BTUVTID0gWyd4YXhpcycsICd5YXhpcycsICd6YXhpcyddO1xuXG5mdW5jdGlvbiBBeGVzT3B0aW9ucygpIHtcbiAgICB0aGlzLmJvdW5kcyA9IFtcbiAgICAgICAgWy0xMCwgLTEwLCAtMTBdLFxuICAgICAgICBbMTAsIDEwLCAxMF1cbiAgICBdO1xuXG4gICAgdGhpcy50aWNrcyA9IFsgW10sIFtdLCBbXSBdO1xuICAgIHRoaXMudGlja0VuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMudGlja0ZvbnQgPSBbICdzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnLCAnc2Fucy1zZXJpZicgXTtcbiAgICB0aGlzLnRpY2tTaXplID0gWyAxMiwgMTIsIDEyIF07XG4gICAgdGhpcy50aWNrQW5nbGUgPSBbIDAsIDAsIDAgXTtcbiAgICB0aGlzLnRpY2tDb2xvciA9IFsgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSBdO1xuICAgIHRoaXMudGlja1BhZCA9IFsgMTgsIDE4LCAxOCBdO1xuXG4gICAgdGhpcy5sYWJlbHMgPSBbICd4JywgJ3knLCAneicgXTtcbiAgICB0aGlzLmxhYmVsRW5hYmxlID0gWyB0cnVlLCB0cnVlLCB0cnVlIF07XG4gICAgdGhpcy5sYWJlbEZvbnQgPSBbJ09wZW4gU2FucycsICdPcGVuIFNhbnMnLCAnT3BlbiBTYW5zJ107XG4gICAgdGhpcy5sYWJlbFNpemUgPSBbIDIwLCAyMCwgMjAgXTtcbiAgICB0aGlzLmxhYmVsQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXTtcbiAgICB0aGlzLmxhYmVsUGFkID0gWyAzMCwgMzAsIDMwIF07XG5cbiAgICB0aGlzLmxpbmVFbmFibGUgPSBbIHRydWUsIHRydWUsIHRydWUgXTtcbiAgICB0aGlzLmxpbmVNaXJyb3IgPSBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXTtcbiAgICB0aGlzLmxpbmVXaWR0aCA9IFsgMSwgMSwgMSBdO1xuICAgIHRoaXMubGluZUNvbG9yID0gWyBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdIF07XG5cbiAgICB0aGlzLmxpbmVUaWNrRW5hYmxlID0gWyB0cnVlLCB0cnVlLCB0cnVlIF07XG4gICAgdGhpcy5saW5lVGlja01pcnJvciA9IFsgZmFsc2UsIGZhbHNlLCBmYWxzZSBdO1xuICAgIHRoaXMubGluZVRpY2tMZW5ndGggPSBbIDEwLCAxMCwgMTAgXTtcbiAgICB0aGlzLmxpbmVUaWNrV2lkdGggPSBbIDEsIDEsIDEgXTtcbiAgICB0aGlzLmxpbmVUaWNrQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXTtcblxuICAgIHRoaXMuZ3JpZEVuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMuZ3JpZFdpZHRoID0gWyAxLCAxLCAxIF07XG4gICAgdGhpcy5ncmlkQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXTtcblxuICAgIHRoaXMuemVyb0VuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMuemVyb0xpbmVDb2xvciA9IFsgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSBdO1xuICAgIHRoaXMuemVyb0xpbmVXaWR0aCA9IFsgMiwgMiwgMiBdO1xuXG4gICAgdGhpcy5iYWNrZ3JvdW5kRW5hYmxlID0gWyB0cnVlLCB0cnVlLCB0cnVlIF07XG4gICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBbIFswLjgsIDAuOCwgMC44LCAwLjVdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAuOCwgMC44LCAwLjgsIDAuNV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMC44LCAwLjgsIDAuOCwgMC41XSBdO1xuXG4gICAgLy8gc29tZSBkZWZhdWx0IHZhbHVlcyBhcmUgc3RvcmVkIGZvciBhcHBseWluZyBtb2RlbCB0cmFuc2Zvcm1zXG4gICAgdGhpcy5fZGVmYXVsdFRpY2tQYWQgPSB0aGlzLnRpY2tQYWQuc2xpY2UoKTtcbiAgICB0aGlzLl9kZWZhdWx0TGFiZWxQYWQgPSB0aGlzLmxhYmVsUGFkLnNsaWNlKCk7XG4gICAgdGhpcy5fZGVmYXVsdExpbmVUaWNrTGVuZ3RoID0gdGhpcy5saW5lVGlja0xlbmd0aC5zbGljZSgpO1xufVxuXG52YXIgcHJvdG8gPSBBeGVzT3B0aW9ucy5wcm90b3R5cGU7XG5cbnByb3RvLm1lcmdlID0gZnVuY3Rpb24oc2NlbmVMYXlvdXQpIHtcbiAgICB2YXIgb3B0cyA9IHRoaXM7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgYXhlcyA9IHNjZW5lTGF5b3V0W0FYRVNfTkFNRVNbaV1dO1xuXG4gICAgICAgIGlmKCFheGVzLnZpc2libGUpIHtcbiAgICAgICAgICAgIG9wdHMudGlja0VuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgb3B0cy5sYWJlbEVuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgb3B0cy5saW5lRW5hYmxlW2ldID0gZmFsc2U7XG4gICAgICAgICAgICBvcHRzLmxpbmVUaWNrRW5hYmxlW2ldID0gZmFsc2U7XG4gICAgICAgICAgICBvcHRzLmdyaWRFbmFibGVbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgIG9wdHMuemVyb0VuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgb3B0cy5iYWNrZ3JvdW5kRW5hYmxlW2ldID0gZmFsc2U7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEF4ZXMgbGFiZWxzXG4gICAgICAgIG9wdHMubGFiZWxzW2ldID0gY29udmVydEhUTUxUb1VuaWNvZGUoYXhlcy50aXRsZSk7XG4gICAgICAgIGlmKCd0aXRsZWZvbnQnIGluIGF4ZXMpIHtcbiAgICAgICAgICAgIGlmKGF4ZXMudGl0bGVmb250LmNvbG9yKSBvcHRzLmxhYmVsQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGF4ZXMudGl0bGVmb250LmNvbG9yKTtcbiAgICAgICAgICAgIGlmKGF4ZXMudGl0bGVmb250LmZhbWlseSkgb3B0cy5sYWJlbEZvbnRbaV0gPSBheGVzLnRpdGxlZm9udC5mYW1pbHk7XG4gICAgICAgICAgICBpZihheGVzLnRpdGxlZm9udC5zaXplKSBvcHRzLmxhYmVsU2l6ZVtpXSA9IGF4ZXMudGl0bGVmb250LnNpemU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMaW5lc1xuICAgICAgICBpZignc2hvd2xpbmUnIGluIGF4ZXMpIG9wdHMubGluZUVuYWJsZVtpXSA9IGF4ZXMuc2hvd2xpbmU7XG4gICAgICAgIGlmKCdsaW5lY29sb3InIGluIGF4ZXMpIG9wdHMubGluZUNvbG9yW2ldID0gc3RyMlJnYmFBcnJheShheGVzLmxpbmVjb2xvcik7XG4gICAgICAgIGlmKCdsaW5ld2lkdGgnIGluIGF4ZXMpIG9wdHMubGluZVdpZHRoW2ldID0gYXhlcy5saW5ld2lkdGg7XG5cbiAgICAgICAgaWYoJ3Nob3dncmlkJyBpbiBheGVzKSBvcHRzLmdyaWRFbmFibGVbaV0gPSBheGVzLnNob3dncmlkO1xuICAgICAgICBpZignZ3JpZGNvbG9yJyBpbiBheGVzKSBvcHRzLmdyaWRDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoYXhlcy5ncmlkY29sb3IpO1xuICAgICAgICBpZignZ3JpZHdpZHRoJyBpbiBheGVzKSBvcHRzLmdyaWRXaWR0aFtpXSA9IGF4ZXMuZ3JpZHdpZHRoO1xuXG4gICAgICAgIC8vIFJlbW92ZSB6ZXJvbGluZSBpZiBheGlzIHR5cGUgaXMgbG9nXG4gICAgICAgIC8vIG90aGVyd2lzZSB0aGUgemVyb2xpbmUgaXMgaW5jb3JyZWN0bHkgZHJhd24gYXQgMSBvbiBsb2cgYXhlc1xuICAgICAgICBpZihheGVzLnR5cGUgPT09ICdsb2cnKSBvcHRzLnplcm9FbmFibGVbaV0gPSBmYWxzZTtcbiAgICAgICAgZWxzZSBpZignemVyb2xpbmUnIGluIGF4ZXMpIG9wdHMuemVyb0VuYWJsZVtpXSA9IGF4ZXMuemVyb2xpbmU7XG4gICAgICAgIGlmKCd6ZXJvbGluZWNvbG9yJyBpbiBheGVzKSBvcHRzLnplcm9MaW5lQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGF4ZXMuemVyb2xpbmVjb2xvcik7XG4gICAgICAgIGlmKCd6ZXJvbGluZXdpZHRoJyBpbiBheGVzKSBvcHRzLnplcm9MaW5lV2lkdGhbaV0gPSBheGVzLnplcm9saW5ld2lkdGg7XG5cbiAgICAgICAgLy8gdGljayBsaW5lc1xuICAgICAgICBpZigndGlja3MnIGluIGF4ZXMgJiYgISFheGVzLnRpY2tzKSBvcHRzLmxpbmVUaWNrRW5hYmxlW2ldID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBvcHRzLmxpbmVUaWNrRW5hYmxlW2ldID0gZmFsc2U7XG5cbiAgICAgICAgaWYoJ3RpY2tsZW4nIGluIGF4ZXMpIHtcbiAgICAgICAgICAgIG9wdHMubGluZVRpY2tMZW5ndGhbaV0gPSBvcHRzLl9kZWZhdWx0TGluZVRpY2tMZW5ndGhbaV0gPSBheGVzLnRpY2tsZW47XG4gICAgICAgIH1cbiAgICAgICAgaWYoJ3RpY2tjb2xvcicgaW4gYXhlcykgb3B0cy5saW5lVGlja0NvbG9yW2ldID0gc3RyMlJnYmFBcnJheShheGVzLnRpY2tjb2xvcik7XG4gICAgICAgIGlmKCd0aWNrd2lkdGgnIGluIGF4ZXMpIG9wdHMubGluZVRpY2tXaWR0aFtpXSA9IGF4ZXMudGlja3dpZHRoO1xuICAgICAgICBpZigndGlja2FuZ2xlJyBpbiBheGVzKSB7XG4gICAgICAgICAgICBvcHRzLnRpY2tBbmdsZVtpXSA9IChheGVzLnRpY2thbmdsZSA9PT0gJ2F1dG8nKSA/XG4gICAgICAgICAgICAgICAgLTM2MDAgOiAvLyBpLmUuIHNwZWNpYWwgbnVtYmVyIHRvIHNldCBhdXRvIG9wdGlvblxuICAgICAgICAgICAgICAgIE1hdGguUEkgKiAtYXhlcy50aWNrYW5nbGUgLyAxODA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aWNrIGxhYmVsc1xuICAgICAgICBpZignc2hvd3RpY2tsYWJlbHMnIGluIGF4ZXMpIG9wdHMudGlja0VuYWJsZVtpXSA9IGF4ZXMuc2hvd3RpY2tsYWJlbHM7XG4gICAgICAgIGlmKCd0aWNrZm9udCcgaW4gYXhlcykge1xuICAgICAgICAgICAgaWYoYXhlcy50aWNrZm9udC5jb2xvcikgb3B0cy50aWNrQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGF4ZXMudGlja2ZvbnQuY29sb3IpO1xuICAgICAgICAgICAgaWYoYXhlcy50aWNrZm9udC5mYW1pbHkpIG9wdHMudGlja0ZvbnRbaV0gPSBheGVzLnRpY2tmb250LmZhbWlseTtcbiAgICAgICAgICAgIGlmKGF4ZXMudGlja2ZvbnQuc2l6ZSkgb3B0cy50aWNrU2l6ZVtpXSA9IGF4ZXMudGlja2ZvbnQuc2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCdtaXJyb3InIGluIGF4ZXMpIHtcbiAgICAgICAgICAgIGlmKFsndGlja3MnLCAnYWxsJywgJ2FsbHRpY2tzJ10uaW5kZXhPZihheGVzLm1pcnJvcikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgb3B0cy5saW5lVGlja01pcnJvcltpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgb3B0cy5saW5lTWlycm9yW2ldID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihheGVzLm1pcnJvciA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIG9wdHMubGluZVRpY2tNaXJyb3JbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBvcHRzLmxpbmVNaXJyb3JbaV0gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvcHRzLmxpbmVUaWNrTWlycm9yW2ldID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgb3B0cy5saW5lTWlycm9yW2ldID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBvcHRzLmxpbmVNaXJyb3JbaV0gPSBmYWxzZTtcblxuICAgICAgICAvLyBncmlkIGJhY2tncm91bmRcbiAgICAgICAgaWYoJ3Nob3diYWNrZ3JvdW5kJyBpbiBheGVzICYmIGF4ZXMuc2hvd2JhY2tncm91bmQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICBvcHRzLmJhY2tncm91bmRFbmFibGVbaV0gPSB0cnVlO1xuICAgICAgICAgICAgb3B0cy5iYWNrZ3JvdW5kQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGF4ZXMuYmFja2dyb3VuZGNvbG9yKTtcbiAgICAgICAgfSBlbHNlIG9wdHMuYmFja2dyb3VuZEVuYWJsZVtpXSA9IGZhbHNlO1xuICAgIH1cbn07XG5cblxuZnVuY3Rpb24gY3JlYXRlQXhlc09wdGlvbnMocGxvdGx5T3B0aW9ucykge1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXhlc09wdGlvbnMoKTtcbiAgICByZXN1bHQubWVyZ2UocGxvdGx5T3B0aW9ucyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBeGVzT3B0aW9ucztcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgaGFuZGxlU3VicGxvdERlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vc3VicGxvdF9kZWZhdWx0cycpO1xudmFyIHN1cHBseUdsM2RBeGlzTGF5b3V0RGVmYXVsdHMgPSByZXF1aXJlKCcuL2F4aXNfZGVmYXVsdHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICB2YXIgaGFzTm9uM0QgPSBsYXlvdXRPdXQuX2Jhc2VQbG90TW9kdWxlcy5sZW5ndGggPiAxO1xuXG4gICAgLy8gc29tZSBsYXlvdXQtd2lkZSBhdHRyaWJ1dGUgYXJlIHVzZWQgaW4gYWxsIHNjZW5lc1xuICAgIC8vIGlmIDNEIGlzIHRoZSBvbmx5IHZpc2libGUgcGxvdCB0eXBlXG4gICAgZnVuY3Rpb24gZ2V0RGZsdEZyb21MYXlvdXQoYXR0cikge1xuICAgICAgICBpZihoYXNOb24zRCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBpc1ZhbGlkID0gTGliLnZhbGlkYXRlKGxheW91dEluW2F0dHJdLCBsYXlvdXRBdHRyaWJ1dGVzW2F0dHJdKTtcbiAgICAgICAgaWYoaXNWYWxpZCkgcmV0dXJuIGxheW91dEluW2F0dHJdO1xuICAgIH1cblxuICAgIGhhbmRsZVN1YnBsb3REZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSwge1xuICAgICAgICB0eXBlOiAnZ2wzZCcsXG4gICAgICAgIGF0dHJpYnV0ZXM6IGxheW91dEF0dHJpYnV0ZXMsXG4gICAgICAgIGhhbmRsZURlZmF1bHRzOiBoYW5kbGVHbDNkRGVmYXVsdHMsXG4gICAgICAgIGZ1bGxMYXlvdXQ6IGxheW91dE91dCxcbiAgICAgICAgZm9udDogbGF5b3V0T3V0LmZvbnQsXG4gICAgICAgIGZ1bGxEYXRhOiBmdWxsRGF0YSxcbiAgICAgICAgZ2V0RGZsdEZyb21MYXlvdXQ6IGdldERmbHRGcm9tTGF5b3V0LFxuICAgICAgICBwYXBlcl9iZ2NvbG9yOiBsYXlvdXRPdXQucGFwZXJfYmdjb2xvcixcbiAgICAgICAgY2FsZW5kYXI6IGxheW91dE91dC5jYWxlbmRhclxuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlR2wzZERlZmF1bHRzKHNjZW5lTGF5b3V0SW4sIHNjZW5lTGF5b3V0T3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICAvKlxuICAgICAqIFNjZW5lIG51bWJlcmluZyBwcm9jZWVkcyBhcyBmb2xsb3dzXG4gICAgICogc2NlbmVcbiAgICAgKiBzY2VuZTJcbiAgICAgKiBzY2VuZTNcbiAgICAgKlxuICAgICAqIGFuZCBkLnNjZW5lIHdpbGwgYmUgdW5kZWZpbmVkIG9yIHNvbWUgbnVtYmVyIG9yIG51bWJlciBzdHJpbmdcbiAgICAgKlxuICAgICAqIEFsc28gd3JpdGUgYmFjayBhIGJsYW5rIHNjZW5lIG9iamVjdCB0byB1c2VyIGxheW91dCBzbyB0aGF0IHNvbWVcbiAgICAgKiBhdHRyaWJ1dGVzIGxpa2UgYXNwZWN0cmF0aW8gY2FuIGJlIHdyaXR0ZW4gYmFjayBkeW5hbWljYWxseS5cbiAgICAgKi9cblxuICAgIHZhciBiZ2NvbG9yID0gY29lcmNlKCdiZ2NvbG9yJyksXG4gICAgICAgIGJnQ29sb3JDb21iaW5lZCA9IENvbG9yLmNvbWJpbmUoYmdjb2xvciwgb3B0cy5wYXBlcl9iZ2NvbG9yKTtcblxuICAgIHZhciBjYW1lcmFLZXlzID0gWyd1cCcsICdjZW50ZXInLCAnZXllJ107XG5cbiAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FtZXJhS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICBjb2VyY2UoJ2NhbWVyYS4nICsgY2FtZXJhS2V5c1tqXSArICcueCcpO1xuICAgICAgICBjb2VyY2UoJ2NhbWVyYS4nICsgY2FtZXJhS2V5c1tqXSArICcueScpO1xuICAgICAgICBjb2VyY2UoJ2NhbWVyYS4nICsgY2FtZXJhS2V5c1tqXSArICcueicpO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogY29lcmNlIHRvIHBvc2l0aXZlIG51bWJlciAobWluIDApIGJ1dCBhbHNvIGRvIG5vdCBhY2NlcHQgMCAoPjAgbm90ID49MClcbiAgICAgKiBub3RlIHRoYXQgMCdzIGdvIGZhbHNlIHdpdGggdGhlICEhIGNhbGxcbiAgICAgKi9cbiAgICB2YXIgaGFzQXNwZWN0ID0gISFjb2VyY2UoJ2FzcGVjdHJhdGlvLngnKSAmJlxuICAgICAgICAgICAgICAgICAgICAhIWNvZXJjZSgnYXNwZWN0cmF0aW8ueScpICYmXG4gICAgICAgICAgICAgICAgICAgICEhY29lcmNlKCdhc3BlY3RyYXRpby56Jyk7XG5cbiAgICB2YXIgZGVmYXVsdEFzcGVjdE1vZGUgPSBoYXNBc3BlY3QgPyAnbWFudWFsJyA6ICdhdXRvJztcbiAgICB2YXIgYXNwZWN0TW9kZSA9IGNvZXJjZSgnYXNwZWN0bW9kZScsIGRlZmF1bHRBc3BlY3RNb2RlKTtcblxuICAgIC8qXG4gICAgICogV2UgbmVlZCBhc3BlY3RyYXRpbyBvYmplY3QgaW4gYWxsIHRoZSBMYXlvdXRzIGFzIGl0IGlzIGR5bmFtaWNhbGx5IHNldFxuICAgICAqIGluIHRoZSBjYWxjdWxhdGlvbiBzdGVwcywgaWUsIHdlIGNhbnQgc2V0IHRoZSBjb3JyZWN0IGRhdGEgbm93LCBpdCBoYXBwZW5zIGxhdGVyLlxuICAgICAqIFdlIG11c3QgYWxzbyBhY2NvdW50IGZvciB0aGUgY2FzZSB0aGUgdXNlciBzZW5kcyBiYWQgcmF0aW8gZGF0YSB3aXRoICdtYW51YWwnIHNldFxuICAgICAqIGZvciB0aGUgbW9kZS4gSW4gdGhpcyBjYXNlIHdlIG11c3QgZm9yY2UgY2hhbmdlIGl0IGhlcmUgYXMgdGhlIGRlZmF1bHQgY29lcmNlXG4gICAgICogbWlzc2VzIGl0IGFib3ZlLlxuICAgICAqL1xuICAgIGlmKCFoYXNBc3BlY3QpIHtcbiAgICAgICAgc2NlbmVMYXlvdXRJbi5hc3BlY3RyYXRpbyA9IHNjZW5lTGF5b3V0T3V0LmFzcGVjdHJhdGlvID0ge3g6IDEsIHk6IDEsIHo6IDF9O1xuXG4gICAgICAgIGlmKGFzcGVjdE1vZGUgPT09ICdtYW51YWwnKSBzY2VuZUxheW91dE91dC5hc3BlY3Rtb2RlID0gJ2F1dG8nO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIGtpbmQgb2YgbGlrZSBhdXRvcmFuZ2UgLSB3ZSBuZWVkIHRoZSBjYWxjdWxhdGVkIGFzcGVjdG1vZGUgYmFjayBpblxuICAgICAgICAgKiB0aGUgaW5wdXQgbGF5b3V0IG9yIHJlbGF5b3V0IGNhbiBjYXVzZSBwcm9ibGVtcyBsYXRlclxuICAgICAgICAgKi9cbiAgICAgICAgc2NlbmVMYXlvdXRJbi5hc3BlY3Rtb2RlID0gc2NlbmVMYXlvdXRPdXQuYXNwZWN0bW9kZTtcbiAgICB9XG5cbiAgICBzdXBwbHlHbDNkQXhpc0xheW91dERlZmF1bHRzKHNjZW5lTGF5b3V0SW4sIHNjZW5lTGF5b3V0T3V0LCB7XG4gICAgICAgIGZvbnQ6IG9wdHMuZm9udCxcbiAgICAgICAgc2NlbmU6IG9wdHMuaWQsXG4gICAgICAgIGRhdGE6IG9wdHMuZnVsbERhdGEsXG4gICAgICAgIGJnQ29sb3I6IGJnQ29sb3JDb21iaW5lZCxcbiAgICAgICAgY2FsZW5kYXI6IG9wdHMuY2FsZW5kYXIsXG4gICAgICAgIGZ1bGxMYXlvdXQ6IG9wdHMuZnVsbExheW91dFxuICAgIH0pO1xuXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9uczNkJywgJ2hhbmRsZURlZmF1bHRzJykoXG4gICAgICAgIHNjZW5lTGF5b3V0SW4sIHNjZW5lTGF5b3V0T3V0LCBvcHRzXG4gICAgKTtcblxuICAgIGNvZXJjZSgnZHJhZ21vZGUnLCBvcHRzLmdldERmbHRGcm9tTGF5b3V0KCdkcmFnbW9kZScpKTtcbiAgICBjb2VyY2UoJ2hvdmVybW9kZScsIG9wdHMuZ2V0RGZsdEZyb21MYXlvdXQoJ2hvdmVybW9kZScpKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2wzZEF4aXNBdHRycyA9IHJlcXVpcmUoJy4vYXhpc19hdHRyaWJ1dGVzJyk7XG52YXIgZG9tYWluQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBjb3VudGVyUmVnZXggPSByZXF1aXJlKCcuLi8uLi8uLi9saWInKS5jb3VudGVyUmVnZXg7XG5cbmZ1bmN0aW9uIG1ha2VDYW1lcmFWZWN0b3IoeCwgeSwgeikge1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB4LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB5LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIHo6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB6LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FtZXJhJ1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIF9hcnJheUF0dHJSZWdleHBzOiBbY291bnRlclJlZ2V4KCdzY2VuZScsICcuYW5ub3RhdGlvbnMnLCB0cnVlKV0sXG5cbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAncmdiYSgwLDAsMCwwKScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIGNhbWVyYToge1xuICAgICAgICB1cDogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDAsIDAsIDEpLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGNlbnRlcjogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDAsIDAsIDApLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGV5ZTogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDEuMjUsIDEuMjUsIDEuMjUpLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnY2FtZXJhJ1xuICAgIH0sXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3NjZW5lJywgZWRpdFR5cGU6ICdwbG90J30pLFxuICAgIGFzcGVjdG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnY3ViZScsICdkYXRhJywgJ21hbnVhbCddLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czoge1xuICAgICAgICAgICAgJ2FzcGVjdHJhdGlvLngnOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAnYXNwZWN0cmF0aW8ueSc6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICdhc3BlY3RyYXRpby56JzogdW5kZWZpbmVkXG4gICAgICAgIH0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXNwZWN0cmF0aW86IHsgLy8gbXVzdCBiZSBwb3NpdGl2ZSAoMCdzIGFyZSBjb2VyY2VkIHRvIDEpXG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIHo6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czoge2FzcGVjdG1vZGU6ICdtYW51YWwnfSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhheGlzOiBnbDNkQXhpc0F0dHJzLFxuICAgIHlheGlzOiBnbDNkQXhpc0F0dHJzLFxuICAgIHpheGlzOiBnbDNkQXhpc0F0dHJzLFxuXG4gICAgZHJhZ21vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ29yYml0JywgJ3R1cm50YWJsZScsICd6b29tJywgJ3BhbicsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogJ3R1cm50YWJsZScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydjbG9zZXN0JywgZmFsc2VdLFxuICAgICAgICBkZmx0OiAnY2xvc2VzdCcsXG4gICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdwbG90JyxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIGNhbWVyYXBvc2l0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FtZXJhJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3RyMlJHQkFycmF5ID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xuXG52YXIgQVhFU19OQU1FUyA9IFsneGF4aXMnLCAneWF4aXMnLCAnemF4aXMnXTtcblxuZnVuY3Rpb24gU3Bpa2VPcHRpb25zKCkge1xuICAgIHRoaXMuZW5hYmxlZCA9IFt0cnVlLCB0cnVlLCB0cnVlXTtcbiAgICB0aGlzLmNvbG9ycyA9IFtbMCwgMCwgMCwgMV0sXG4gICAgICAgICAgICAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICAgICAgICAgICAgIFswLCAwLCAwLCAxXV07XG4gICAgdGhpcy5kcmF3U2lkZXMgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZV07XG4gICAgdGhpcy5saW5lV2lkdGggPSBbMSwgMSwgMV07XG59XG5cbnZhciBwcm90byA9IFNwaWtlT3B0aW9ucy5wcm90b3R5cGU7XG5cbnByb3RvLm1lcmdlID0gZnVuY3Rpb24oc2NlbmVMYXlvdXQpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIHZhciBheGVzID0gc2NlbmVMYXlvdXRbQVhFU19OQU1FU1tpXV07XG5cbiAgICAgICAgaWYoIWF4ZXMudmlzaWJsZSkge1xuICAgICAgICAgICAgdGhpcy5lbmFibGVkW2ldID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRyYXdTaWRlc1tpXSA9IGZhbHNlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVuYWJsZWRbaV0gPSBheGVzLnNob3dzcGlrZXM7XG4gICAgICAgIHRoaXMuY29sb3JzW2ldID0gc3RyMlJHQkFycmF5KGF4ZXMuc3Bpa2Vjb2xvcik7XG4gICAgICAgIHRoaXMuZHJhd1NpZGVzW2ldID0gYXhlcy5zcGlrZXNpZGVzO1xuICAgICAgICB0aGlzLmxpbmVXaWR0aFtpXSA9IGF4ZXMuc3Bpa2V0aGlja25lc3M7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY3JlYXRlU3Bpa2VPcHRpb25zKGxheW91dCkge1xuICAgIHZhciByZXN1bHQgPSBuZXcgU3Bpa2VPcHRpb25zKCk7XG4gICAgcmVzdWx0Lm1lcmdlKGxheW91dCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTcGlrZU9wdGlvbnM7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4vKiBlc2xpbnQgYmxvY2stc2NvcGVkLXZhcjogMCovXG4vKiBlc2xpbnQgbm8tcmVkZWNsYXJlOiAwKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbXB1dGVUaWNrTWFya3M7XG5cbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWInKTtcbnZhciBjb252ZXJ0SFRNTFRvVW5pY29kZSA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9odG1sMnVuaWNvZGUnKTtcblxudmFyIEFYRVNfTkFNRVMgPSBbJ3hheGlzJywgJ3lheGlzJywgJ3pheGlzJ107XG5cbnZhciBjZW50ZXJQb2ludCA9IFswLCAwLCAwXTtcblxuZnVuY3Rpb24gY29udG91ckxldmVsc0Zyb21UaWNrcyh0aWNrcykge1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoMyk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgdGxldmVsID0gdGlja3NbaV07XG4gICAgICAgIHZhciBjbGV2ZWwgPSBuZXcgQXJyYXkodGxldmVsLmxlbmd0aCk7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0bGV2ZWwubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgIGNsZXZlbFtqXSA9IHRsZXZlbFtqXS54O1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdFtpXSA9IGNsZXZlbDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZVRpY2tNYXJrcyhzY2VuZSkge1xuICAgIHZhciBheGVzT3B0aW9ucyA9IHNjZW5lLmF4ZXNPcHRpb25zO1xuICAgIHZhciBnbFJhbmdlID0gc2NlbmUuZ2xwbG90LmF4ZXNQaXhlbHM7XG4gICAgdmFyIHNjZW5lTGF5b3V0ID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuXG4gICAgdmFyIHRpY2tzID0gW1tdLCBbXSwgW11dO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgYXhlcyA9IHNjZW5lTGF5b3V0W0FYRVNfTkFNRVNbaV1dO1xuXG4gICAgICAgIGF4ZXMuX2xlbmd0aCA9IChnbFJhbmdlW2ldLmhpIC0gZ2xSYW5nZVtpXS5sbykgKlxuICAgICAgICAgICAgZ2xSYW5nZVtpXS5waXhlbHNQZXJEYXRhVW5pdCAvIHNjZW5lLmRhdGFTY2FsZVtpXTtcblxuICAgICAgICBpZihNYXRoLmFicyhheGVzLl9sZW5ndGgpID09PSBJbmZpbml0eSkge1xuICAgICAgICAgICAgdGlja3NbaV0gPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF4ZXMuX2lucHV0X3JhbmdlID0gYXhlcy5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgYXhlcy5yYW5nZVswXSA9IChnbFJhbmdlW2ldLmxvKSAvIHNjZW5lLmRhdGFTY2FsZVtpXTtcbiAgICAgICAgICAgIGF4ZXMucmFuZ2VbMV0gPSAoZ2xSYW5nZVtpXS5oaSkgLyBzY2VuZS5kYXRhU2NhbGVbaV07XG4gICAgICAgICAgICBheGVzLl9tID0gMS4wIC8gKHNjZW5lLmRhdGFTY2FsZVtpXSAqIGdsUmFuZ2VbaV0ucGl4ZWxzUGVyRGF0YVVuaXQpO1xuXG4gICAgICAgICAgICBpZihheGVzLnJhbmdlWzBdID09PSBheGVzLnJhbmdlWzFdKSB7XG4gICAgICAgICAgICAgICAgYXhlcy5yYW5nZVswXSAtPSAxO1xuICAgICAgICAgICAgICAgIGF4ZXMucmFuZ2VbMV0gKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbmVjZXNzYXJ5IHRvIHNob3J0LWNpcmN1aXQgdGhlICd5JyBoYW5kbGluZ1xuICAgICAgICAgICAgLy8gaW4gYXV0b3RpY2sgcGFydCBvZiBjYWxjVGlja3MuLi4gVHJlYXRpbmcgYWxsIGF4ZXMgYXMgJ3knIGluIHRoaXMgY2FzZVxuICAgICAgICAgICAgLy8gcnVubmluZyB0aGUgYXV0b3RpY2tzIGhlcmUsIHRoZW4gc2V0dGluZ1xuICAgICAgICAgICAgLy8gYXV0b3RpY2tzIHRvIGZhbHNlIHRvIGdldCBhcm91bmQgdGhlIDJEIGhhbmRsaW5nIGluIGNhbGNUaWNrcy5cbiAgICAgICAgICAgIHZhciB0aWNrTW9kZUNhY2hlZCA9IGF4ZXMudGlja21vZGU7XG4gICAgICAgICAgICBpZihheGVzLnRpY2ttb2RlID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgICAgICBheGVzLnRpY2ttb2RlID0gJ2xpbmVhcic7XG4gICAgICAgICAgICAgICAgdmFyIG50aWNrcyA9IGF4ZXMubnRpY2tzIHx8IExpYi5jb25zdHJhaW4oKGF4ZXMuX2xlbmd0aCAvIDQwKSwgNCwgOSk7XG4gICAgICAgICAgICAgICAgQXhlcy5hdXRvVGlja3MoYXhlcywgTWF0aC5hYnMoYXhlcy5yYW5nZVsxXSAtIGF4ZXMucmFuZ2VbMF0pIC8gbnRpY2tzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkYXRhVGlja3MgPSBBeGVzLmNhbGNUaWNrcyhheGVzKTtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBkYXRhVGlja3MubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgICAgICBkYXRhVGlja3Nbal0ueCA9IGRhdGFUaWNrc1tqXS54ICogc2NlbmUuZGF0YVNjYWxlW2ldO1xuICAgICAgICAgICAgICAgIGRhdGFUaWNrc1tqXS50ZXh0ID0gY29udmVydEhUTUxUb1VuaWNvZGUoZGF0YVRpY2tzW2pdLnRleHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGlja3NbaV0gPSBkYXRhVGlja3M7XG5cblxuICAgICAgICAgICAgYXhlcy50aWNrbW9kZSA9IHRpY2tNb2RlQ2FjaGVkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXhlc09wdGlvbnMudGlja3MgPSB0aWNrcztcblxuICAgIC8vIENhbGN1bGF0ZSB0aWNrIGxlbmd0aHMgZHluYW1pY2FsbHlcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGNlbnRlclBvaW50W2ldID0gMC41ICogKHNjZW5lLmdscGxvdC5ib3VuZHNbMF1baV0gKyBzY2VuZS5nbHBsb3QuYm91bmRzWzFdW2ldKTtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDI7ICsraikge1xuICAgICAgICAgICAgYXhlc09wdGlvbnMuYm91bmRzW2pdW2ldID0gc2NlbmUuZ2xwbG90LmJvdW5kc1tqXVtpXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNjZW5lLmNvbnRvdXJMZXZlbHMgPSBjb250b3VyTGV2ZWxzRnJvbVRpY2tzKHRpY2tzKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiB4Zm9ybU1hdHJpeChtLCB2KSB7XG4gICAgdmFyIG91dCA9IFswLCAwLCAwLCAwXTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IDQ7ICsraSkge1xuICAgICAgICBmb3IoaiA9IDA7IGogPCA0OyArK2opIHtcbiAgICAgICAgICAgIG91dFtqXSArPSBtWzQgKiBpICsgal0gKiB2W2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gcHJvamVjdChjYW1lcmEsIHYpIHtcbiAgICB2YXIgcCA9IHhmb3JtTWF0cml4KGNhbWVyYS5wcm9qZWN0aW9uLFxuICAgICAgICB4Zm9ybU1hdHJpeChjYW1lcmEudmlldyxcbiAgICAgICAgeGZvcm1NYXRyaXgoY2FtZXJhLm1vZGVsLCBbdlswXSwgdlsxXSwgdlsyXSwgMV0pKSk7XG4gICAgcmV0dXJuIHA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvamVjdDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlUGxvdCA9IHJlcXVpcmUoJ2dsLXBsb3QzZCcpO1xudmFyIGdldENvbnRleHQgPSByZXF1aXJlKCd3ZWJnbC1jb250ZXh0Jyk7XG52YXIgcGFzc2l2ZVN1cHBvcnRlZCA9IHJlcXVpcmUoJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgRnggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG5cbnZhciBzdHIyUkdCQWFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIHNob3dOb1dlYkdsTXNnID0gcmVxdWlyZSgnLi4vLi4vbGliL3Nob3dfbm9fd2ViZ2xfbXNnJyk7XG5cbnZhciBjcmVhdGVDYW1lcmEgPSByZXF1aXJlKCcuL2NhbWVyYScpO1xudmFyIHByb2plY3QgPSByZXF1aXJlKCcuL3Byb2plY3QnKTtcbnZhciBjcmVhdGVBeGVzT3B0aW9ucyA9IHJlcXVpcmUoJy4vbGF5b3V0L2NvbnZlcnQnKTtcbnZhciBjcmVhdGVTcGlrZU9wdGlvbnMgPSByZXF1aXJlKCcuL2xheW91dC9zcGlrZXMnKTtcbnZhciBjb21wdXRlVGlja01hcmtzID0gcmVxdWlyZSgnLi9sYXlvdXQvdGlja19tYXJrcycpO1xuXG5cbnZhciBTVEFUSUNfQ0FOVkFTLCBTVEFUSUNfQ09OVEVYVDtcblxuZnVuY3Rpb24gcmVuZGVyKHNjZW5lKSB7XG4gICAgdmFyIHRyYWNlO1xuXG4gICAgLy8gdXBkYXRlIHNpemUgb2Ygc3ZnIGNvbnRhaW5lclxuICAgIHZhciBzdmdDb250YWluZXIgPSBzY2VuZS5zdmdDb250YWluZXI7XG4gICAgdmFyIGNsaWVudFJlY3QgPSBzY2VuZS5jb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdmFyIHdpZHRoID0gY2xpZW50UmVjdC53aWR0aCwgaGVpZ2h0ID0gY2xpZW50UmVjdC5oZWlnaHQ7XG4gICAgc3ZnQ29udGFpbmVyLnNldEF0dHJpYnV0ZU5TKG51bGwsICd2aWV3Qm94JywgJzAgMCAnICsgd2lkdGggKyAnICcgKyBoZWlnaHQpO1xuICAgIHN2Z0NvbnRhaW5lci5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnd2lkdGgnLCB3aWR0aCk7XG4gICAgc3ZnQ29udGFpbmVyLnNldEF0dHJpYnV0ZU5TKG51bGwsICdoZWlnaHQnLCBoZWlnaHQpO1xuXG4gICAgY29tcHV0ZVRpY2tNYXJrcyhzY2VuZSk7XG4gICAgc2NlbmUuZ2xwbG90LmF4ZXMudXBkYXRlKHNjZW5lLmF4ZXNPcHRpb25zKTtcblxuICAgIC8vIGNoZWNrIGlmIHBpY2sgaGFzIGNoYW5nZWRcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHNjZW5lLnRyYWNlcyk7XG4gICAgdmFyIGxhc3RQaWNrZWQgPSBudWxsO1xuICAgIHZhciBzZWxlY3Rpb24gPSBzY2VuZS5nbHBsb3Quc2VsZWN0aW9uO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHRyYWNlID0gc2NlbmUudHJhY2VzW2tleXNbaV1dO1xuICAgICAgICBpZih0cmFjZS5kYXRhLmhvdmVyaW5mbyAhPT0gJ3NraXAnICYmIHRyYWNlLmhhbmRsZVBpY2soc2VsZWN0aW9uKSkge1xuICAgICAgICAgICAgbGFzdFBpY2tlZCA9IHRyYWNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHJhY2Uuc2V0Q29udG91ckxldmVscykgdHJhY2Uuc2V0Q29udG91ckxldmVscygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZvcm1hdHRlcihheGlzTmFtZSwgdmFsKSB7XG4gICAgICAgIHZhciBheGlzID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0W2F4aXNOYW1lXTtcblxuICAgICAgICByZXR1cm4gQXhlcy50aWNrVGV4dChheGlzLCBheGlzLmQybCh2YWwpLCAnaG92ZXInKS50ZXh0O1xuICAgIH1cblxuICAgIHZhciBvbGRFdmVudERhdGE7XG5cbiAgICBpZihsYXN0UGlja2VkICE9PSBudWxsKSB7XG4gICAgICAgIHZhciBwZGF0YSA9IHByb2plY3Qoc2NlbmUuZ2xwbG90LmNhbWVyYVBhcmFtcywgc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlKTtcbiAgICAgICAgdHJhY2UgPSBsYXN0UGlja2VkLmRhdGE7XG4gICAgICAgIHZhciBwdE51bWJlciA9IHNlbGVjdGlvbi5pbmRleDtcbiAgICAgICAgdmFyIGhvdmVyaW5mbyA9IEZ4LmNhc3RIb3ZlcmluZm8odHJhY2UsIHNjZW5lLmZ1bGxMYXlvdXQsIHB0TnVtYmVyKTtcbiAgICAgICAgdmFyIGhvdmVyaW5mb1BhcnRzID0gaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgICAgIHZhciBpc0hvdmVyaW5mb0FsbCA9IGhvdmVyaW5mbyA9PT0gJ2FsbCc7XG5cbiAgICAgICAgdmFyIHhWYWwgPSBmb3JtYXR0ZXIoJ3hheGlzJywgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVswXSk7XG4gICAgICAgIHZhciB5VmFsID0gZm9ybWF0dGVyKCd5YXhpcycsIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbMV0pO1xuICAgICAgICB2YXIgelZhbCA9IGZvcm1hdHRlcignemF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzJdKTtcblxuICAgICAgICBpZighaXNIb3ZlcmluZm9BbGwpIHtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mb1BhcnRzLmluZGV4T2YoJ3gnKSA9PT0gLTEpIHhWYWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZihob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd5JykgPT09IC0xKSB5VmFsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYoaG92ZXJpbmZvUGFydHMuaW5kZXhPZigneicpID09PSAtMSkgelZhbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mb1BhcnRzLmluZGV4T2YoJ3RleHQnKSA9PT0gLTEpIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZihob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCduYW1lJykgPT09IC0xKSBsYXN0UGlja2VkLm5hbWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHg7XG5cbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2NvbmUnIHx8IHRyYWNlLnR5cGUgPT09ICdzdHJlYW10dWJlJykge1xuICAgICAgICAgICAgdmFyIHZlY3RvclR4ID0gW107XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd1JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgndTogJyArIGZvcm1hdHRlcigneGF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzNdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd2JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgndjogJyArIGZvcm1hdHRlcigneWF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzRdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd3JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgndzogJyArIGZvcm1hdHRlcignemF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzVdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCdub3JtJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgnbm9ybTogJyArIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbNl0udG9QcmVjaXNpb24oMykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3N0cmVhbXR1YmUnICYmIChpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCdkaXZlcmdlbmNlJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIHZlY3RvclR4LnB1c2goJ2RpdmVyZ2VuY2U6ICcgKyBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzddLnRvUHJlY2lzaW9uKDMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHNlbGVjdGlvbi50ZXh0TGFiZWwpIHtcbiAgICAgICAgICAgICAgICB2ZWN0b3JUeC5wdXNoKHNlbGVjdGlvbi50ZXh0TGFiZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHggPSB2ZWN0b3JUeC5qb2luKCc8YnI+Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0eCA9IHNlbGVjdGlvbi50ZXh0TGFiZWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZihzY2VuZS5mdWxsU2NlbmVMYXlvdXQuaG92ZXJtb2RlKSB7XG4gICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgIHg6ICgwLjUgKyAwLjUgKiBwZGF0YVswXSAvIHBkYXRhWzNdKSAqIHdpZHRoLFxuICAgICAgICAgICAgICAgIHk6ICgwLjUgLSAwLjUgKiBwZGF0YVsxXSAvIHBkYXRhWzNdKSAqIGhlaWdodCxcbiAgICAgICAgICAgICAgICB4TGFiZWw6IHhWYWwsXG4gICAgICAgICAgICAgICAgeUxhYmVsOiB5VmFsLFxuICAgICAgICAgICAgICAgIHpMYWJlbDogelZhbCxcbiAgICAgICAgICAgICAgICB0ZXh0OiB0eCxcbiAgICAgICAgICAgICAgICBuYW1lOiBsYXN0UGlja2VkLm5hbWUsXG4gICAgICAgICAgICAgICAgY29sb3I6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdiZ2NvbG9yJykgfHwgbGFzdFBpY2tlZC5jb2xvcixcbiAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogRnguY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2JvcmRlcmNvbG9yJyksXG4gICAgICAgICAgICAgICAgZm9udEZhbWlseTogRnguY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2ZvbnQuZmFtaWx5JyksXG4gICAgICAgICAgICAgICAgZm9udFNpemU6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdmb250LnNpemUnKSxcbiAgICAgICAgICAgICAgICBmb250Q29sb3I6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdmb250LmNvbG9yJylcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IHN2Z0NvbnRhaW5lcixcbiAgICAgICAgICAgICAgICBnZDogc2NlbmUuZ3JhcGhEaXZcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVE9ETyBub3Qgc3VyZSBpZiBzdHJlYW10dWJlIHgveS96IHNob3VsZCBiZSBlbWl0dGVkIGFzIHgveS96XG4gICAgICAgIHZhciBwb2ludERhdGEgPSB7XG4gICAgICAgICAgICB4OiBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzBdLFxuICAgICAgICAgICAgeTogc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVsxXSxcbiAgICAgICAgICAgIHo6IHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbMl0sXG4gICAgICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgICAgICBmdWxsRGF0YTogdHJhY2UsXG4gICAgICAgICAgICBjdXJ2ZU51bWJlcjogdHJhY2UuaW5kZXgsXG4gICAgICAgICAgICBwb2ludE51bWJlcjogcHROdW1iZXJcbiAgICAgICAgfTtcblxuICAgICAgICBpZih0cmFjZS5fbW9kdWxlLmV2ZW50RGF0YSkge1xuICAgICAgICAgICAgcG9pbnREYXRhID0gdHJhY2UuX21vZHVsZS5ldmVudERhdGEocG9pbnREYXRhLCBzZWxlY3Rpb24sIHRyYWNlLCB7fSwgcHROdW1iZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgRnguYXBwZW5kQXJyYXlQb2ludFZhbHVlKHBvaW50RGF0YSwgdHJhY2UsIHB0TnVtYmVyKTtcblxuICAgICAgICB2YXIgZXZlbnREYXRhID0ge3BvaW50czogW3BvaW50RGF0YV19O1xuXG4gICAgICAgIGlmKHNlbGVjdGlvbi5idXR0b25zICYmIHNlbGVjdGlvbi5kaXN0YW5jZSA8IDUpIHtcbiAgICAgICAgICAgIHNjZW5lLmdyYXBoRGl2LmVtaXQoJ3Bsb3RseV9jbGljaycsIGV2ZW50RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzY2VuZS5ncmFwaERpdi5lbWl0KCdwbG90bHlfaG92ZXInLCBldmVudERhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgb2xkRXZlbnREYXRhID0gZXZlbnREYXRhO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgRngubG9uZVVuaG92ZXIoc3ZnQ29udGFpbmVyKTtcbiAgICAgICAgc2NlbmUuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X3VuaG92ZXInLCBvbGRFdmVudERhdGEpO1xuICAgIH1cblxuICAgIHNjZW5lLmRyYXdBbm5vdGF0aW9ucyhzY2VuZSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVHTFBsb3Qoc2NlbmUsIGZ1bGxMYXlvdXQsIGNhbnZhcywgZ2wpIHtcbiAgICB2YXIgZ2QgPSBzY2VuZS5ncmFwaERpdjtcblxuICAgIHZhciBnbHBsb3RPcHRpb25zID0ge1xuICAgICAgICBjYW52YXM6IGNhbnZhcyxcbiAgICAgICAgZ2w6IGdsLFxuICAgICAgICBjb250YWluZXI6IHNjZW5lLmNvbnRhaW5lcixcbiAgICAgICAgYXhlczogc2NlbmUuYXhlc09wdGlvbnMsXG4gICAgICAgIHNwaWtlczogc2NlbmUuc3Bpa2VPcHRpb25zLFxuICAgICAgICBwaWNrUmFkaXVzOiAxMCxcbiAgICAgICAgc25hcFRvRGF0YTogdHJ1ZSxcbiAgICAgICAgYXV0b1NjYWxlOiB0cnVlLFxuICAgICAgICBhdXRvQm91bmRzOiBmYWxzZVxuICAgIH07XG5cbiAgICAvLyBmb3Igc3RhdGljIHBsb3RzLCB3ZSByZXVzZSB0aGUgV2ViR0wgY29udGV4dFxuICAgIC8vICBhcyBXZWJLaXQgZG9lc24ndCBjb2xsZWN0IHRoZW0gcmVsaWFibHlcbiAgICBpZihzY2VuZS5zdGF0aWNNb2RlKSB7XG4gICAgICAgIGlmKCFTVEFUSUNfQ09OVEVYVCkge1xuICAgICAgICAgICAgU1RBVElDX0NBTlZBUyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgU1RBVElDX0NPTlRFWFQgPSBnZXRDb250ZXh0KHtcbiAgICAgICAgICAgICAgICBjYW52YXM6IFNUQVRJQ19DQU5WQVMsXG4gICAgICAgICAgICAgICAgcHJlc2VydmVEcmF3aW5nQnVmZmVyOiB0cnVlLFxuICAgICAgICAgICAgICAgIHByZW11bHRpcGxpZWRBbHBoYTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhbnRpYWxpYXM6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYoIVNUQVRJQ19DT05URVhUKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdlcnJvciBjcmVhdGluZyBzdGF0aWMgY2FudmFzL2NvbnRleHQgZm9yIGltYWdlIHNlcnZlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdscGxvdE9wdGlvbnMucGl4ZWxSYXRpbyA9IHNjZW5lLnBpeGVsUmF0aW87XG4gICAgICAgIGdscGxvdE9wdGlvbnMuZ2wgPSBTVEFUSUNfQ09OVEVYVDtcbiAgICAgICAgZ2xwbG90T3B0aW9ucy5jYW52YXMgPSBTVEFUSUNfQ0FOVkFTO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIHNjZW5lLmdscGxvdCA9IGNyZWF0ZVBsb3QoZ2xwbG90T3B0aW9ucyk7XG4gICAgfVxuICAgIGNhdGNoKGUpIHtcbiAgICAgICAgLypcbiAgICAgICAgKiBjcmVhdGVQbG90IHdpbGwgdGhyb3cgd2hlbiB3ZWJnbCBpcyBub3QgZW5hYmxlZCBpbiB0aGUgY2xpZW50LlxuICAgICAgICAqIExldHMgcmV0dXJuIGFuIGluc3RhbmNlIG9mIHRoZSBtb2R1bGUgd2l0aCBhbGwgZnVuY3Rpb25zIG5vb3AnZC5cbiAgICAgICAgKiBUaGUgZGVzdHJveSBtZXRob2QgLSB3aGljaCB3aWxsIHJlbW92ZSB0aGUgY29udGFpbmVyIGZyb20gdGhlIERPTVxuICAgICAgICAqIGlzIG92ZXJyaWRkZW4gd2l0aCBhIGZ1bmN0aW9uIHRoYXQgcmVtb3ZlcyB0aGUgY29udGFpbmVyIG9ubHkuXG4gICAgICAgICovXG4gICAgICAgIHJldHVybiBzaG93Tm9XZWJHbE1zZyhzY2VuZSk7XG4gICAgfVxuXG4gICAgdmFyIHJlbGF5b3V0Q2FsbGJhY2sgPSBmdW5jdGlvbihzY2VuZSkge1xuICAgICAgICBpZihzY2VuZS5mdWxsU2NlbmVMYXlvdXQuZHJhZ21vZGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAgICAgdmFyIHVwZGF0ZSA9IHt9O1xuICAgICAgICB1cGRhdGVbc2NlbmUuaWQgKyAnLmNhbWVyYSddID0gZ2V0TGF5b3V0Q2FtZXJhKHNjZW5lLmNhbWVyYSk7XG4gICAgICAgIHNjZW5lLnNhdmVDYW1lcmEoZ2QubGF5b3V0KTtcbiAgICAgICAgc2NlbmUuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X3JlbGF5b3V0JywgdXBkYXRlKTtcbiAgICB9O1xuXG4gICAgc2NlbmUuZ2xwbG90LmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgcmVsYXlvdXRDYWxsYmFjay5iaW5kKG51bGwsIHNjZW5lKSk7XG4gICAgc2NlbmUuZ2xwbG90LmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3aGVlbCcsIHJlbGF5b3V0Q2FsbGJhY2suYmluZChudWxsLCBzY2VuZSksIHBhc3NpdmVTdXBwb3J0ZWQgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpO1xuXG4gICAgaWYoIXNjZW5lLnN0YXRpY01vZGUpIHtcbiAgICAgICAgc2NlbmUuZ2xwbG90LmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgIGlmKGdkICYmIGdkLmVtaXQpIHtcbiAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfd2ViZ2xjb250ZXh0bG9zdCcsIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICBsYXllcjogc2NlbmUuaWRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgZmFsc2UpO1xuICAgIH1cblxuICAgIGlmKCFzY2VuZS5jYW1lcmEpIHtcbiAgICAgICAgdmFyIGNhbWVyYURhdGEgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQuY2FtZXJhO1xuICAgICAgICBzY2VuZS5jYW1lcmEgPSBjcmVhdGVDYW1lcmEoc2NlbmUuY29udGFpbmVyLCB7XG4gICAgICAgICAgICBjZW50ZXI6IFtjYW1lcmFEYXRhLmNlbnRlci54LCBjYW1lcmFEYXRhLmNlbnRlci55LCBjYW1lcmFEYXRhLmNlbnRlci56XSxcbiAgICAgICAgICAgIGV5ZTogW2NhbWVyYURhdGEuZXllLngsIGNhbWVyYURhdGEuZXllLnksIGNhbWVyYURhdGEuZXllLnpdLFxuICAgICAgICAgICAgdXA6IFtjYW1lcmFEYXRhLnVwLngsIGNhbWVyYURhdGEudXAueSwgY2FtZXJhRGF0YS51cC56XSxcbiAgICAgICAgICAgIHpvb21NaW46IDAuMSxcbiAgICAgICAgICAgIHpvb21NYXg6IDEwMCxcbiAgICAgICAgICAgIG1vZGU6ICdvcmJpdCdcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2NlbmUuZ2xwbG90LmNhbWVyYSA9IHNjZW5lLmNhbWVyYTtcblxuICAgIHNjZW5lLmdscGxvdC5vbmNvbnRleHRsb3NzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHNjZW5lLnJlY292ZXJDb250ZXh0KCk7XG4gICAgfTtcblxuICAgIHNjZW5lLmdscGxvdC5vbnJlbmRlciA9IHJlbmRlci5iaW5kKG51bGwsIHNjZW5lKTtcblxuICAgIC8vIExpc3Qgb2Ygc2NlbmUgb2JqZWN0c1xuICAgIHNjZW5lLnRyYWNlcyA9IHt9O1xuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIFNjZW5lKG9wdGlvbnMsIGZ1bGxMYXlvdXQpIHtcblxuICAgIC8vIGNyZWF0ZSBzdWIgY29udGFpbmVyIGZvciBwbG90XG4gICAgdmFyIHNjZW5lQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdmFyIHBsb3RDb250YWluZXIgPSBvcHRpb25zLmNvbnRhaW5lcjtcblxuICAgIC8vIGtlZXAgYSByZWYgdG8gdGhlIGdyYXBoIGRpdiB0byBmaXJlIGhvdmVyK2NsaWNrIGV2ZW50c1xuICAgIHRoaXMuZ3JhcGhEaXYgPSBvcHRpb25zLmdyYXBoRGl2O1xuXG4gICAgLy8gY3JlYXRlIFNWRyBjb250YWluZXIgZm9yIGhvdmVyIHRleHRcbiAgICB2YXIgc3ZnQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFxuICAgICAgICAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLFxuICAgICAgICAnc3ZnJyk7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzdmdDb250YWluZXIuc3R5bGUudG9wID0gc3ZnQ29udGFpbmVyLnN0eWxlLmxlZnQgPSAnMHB4JztcbiAgICBzdmdDb250YWluZXIuc3R5bGUud2lkdGggPSBzdmdDb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZVsnei1pbmRleCddID0gMjA7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlWydwb2ludGVyLWV2ZW50cyddID0gJ25vbmUnO1xuICAgIHNjZW5lQ29udGFpbmVyLmFwcGVuZENoaWxkKHN2Z0NvbnRhaW5lcik7XG4gICAgdGhpcy5zdmdDb250YWluZXIgPSBzdmdDb250YWluZXI7XG5cbiAgICAvLyBUYWcgdGhlIGNvbnRhaW5lciB3aXRoIHRoZSBzY2VuZUlEXG4gICAgc2NlbmVDb250YWluZXIuaWQgPSBvcHRpb25zLmlkO1xuICAgIHNjZW5lQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzY2VuZUNvbnRhaW5lci5zdHlsZS50b3AgPSBzY2VuZUNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJzBweCc7XG4gICAgc2NlbmVDb250YWluZXIuc3R5bGUud2lkdGggPSBzY2VuZUNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgcGxvdENvbnRhaW5lci5hcHBlbmRDaGlsZChzY2VuZUNvbnRhaW5lcik7XG5cbiAgICB0aGlzLmZ1bGxMYXlvdXQgPSBmdWxsTGF5b3V0O1xuICAgIHRoaXMuaWQgPSBvcHRpb25zLmlkIHx8ICdzY2VuZSc7XG4gICAgdGhpcy5mdWxsU2NlbmVMYXlvdXQgPSBmdWxsTGF5b3V0W3RoaXMuaWRdO1xuXG4gICAgLy8gU2F2ZWQgZnJvbSBsYXN0IGNhbGwgdG8gcGxvdCgpXG4gICAgdGhpcy5wbG90QXJncyA9IFsgW10sIHt9LCB7fSBdO1xuXG4gICAgLypcbiAgICAgKiBNb3ZlIHRoaXMgdG8gY2FsYyBzdGVwPyBXaHkgZG9lcyBpdCB3b3JrIGhlcmU/XG4gICAgICovXG4gICAgdGhpcy5heGVzT3B0aW9ucyA9IGNyZWF0ZUF4ZXNPcHRpb25zKGZ1bGxMYXlvdXRbdGhpcy5pZF0pO1xuICAgIHRoaXMuc3Bpa2VPcHRpb25zID0gY3JlYXRlU3Bpa2VPcHRpb25zKGZ1bGxMYXlvdXRbdGhpcy5pZF0pO1xuICAgIHRoaXMuY29udGFpbmVyID0gc2NlbmVDb250YWluZXI7XG4gICAgdGhpcy5zdGF0aWNNb2RlID0gISFvcHRpb25zLnN0YXRpY1Bsb3Q7XG4gICAgdGhpcy5waXhlbFJhdGlvID0gb3B0aW9ucy5wbG90R2xQaXhlbFJhdGlvIHx8IDI7XG5cbiAgICAvLyBDb29yZGluYXRlIHJlc2NhbGluZ1xuICAgIHRoaXMuZGF0YVNjYWxlID0gWzEsIDEsIDFdO1xuXG4gICAgdGhpcy5jb250b3VyTGV2ZWxzID0gWyBbXSwgW10sIFtdIF07XG5cbiAgICB0aGlzLmNvbnZlcnRBbm5vdGF0aW9ucyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMzZCcsICdjb252ZXJ0Jyk7XG4gICAgdGhpcy5kcmF3QW5ub3RhdGlvbnMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zM2QnLCAnZHJhdycpO1xuXG4gICAgaWYoIWluaXRpYWxpemVHTFBsb3QodGhpcywgZnVsbExheW91dCkpIHJldHVybjsgLy8gdG9kbyBjaGVjayB0aGUgbmVjZXNzaXR5IGZvciB0aGlzIGxpbmVcbn1cblxudmFyIHByb3RvID0gU2NlbmUucHJvdG90eXBlO1xuXG5wcm90by5yZWNvdmVyQ29udGV4dCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzY2VuZSA9IHRoaXM7XG4gICAgdmFyIGdsID0gdGhpcy5nbHBsb3QuZ2w7XG4gICAgdmFyIGNhbnZhcyA9IHRoaXMuZ2xwbG90LmNhbnZhcztcbiAgICB0aGlzLmdscGxvdC5kaXNwb3NlKCk7XG5cbiAgICBmdW5jdGlvbiB0cnlSZWNvdmVyKCkge1xuICAgICAgICBpZihnbC5pc0NvbnRleHRMb3N0KCkpIHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSh0cnlSZWNvdmVyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZighaW5pdGlhbGl6ZUdMUGxvdChzY2VuZSwgc2NlbmUuZnVsbExheW91dCwgY2FudmFzLCBnbCkpIHtcbiAgICAgICAgICAgIExpYi5lcnJvcignQ2F0YXN0cm9waGljIGFuZCB1bnJlY292ZXJhYmxlIFdlYkdMIGVycm9yLiBDb250ZXh0IGxvc3QuJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2NlbmUucGxvdC5hcHBseShzY2VuZSwgc2NlbmUucGxvdEFyZ3MpO1xuICAgIH1cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodHJ5UmVjb3Zlcik7XG59O1xuXG52YXIgYXhpc1Byb3BlcnRpZXMgPSBbICd4YXhpcycsICd5YXhpcycsICd6YXhpcycgXTtcblxuZnVuY3Rpb24gY29tcHV0ZVRyYWNlQm91bmRzKHNjZW5lLCB0cmFjZSwgYm91bmRzKSB7XG4gICAgdmFyIHNjZW5lTGF5b3V0ID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuXG4gICAgZm9yKHZhciBkID0gMDsgZCA8IDM7IGQrKykge1xuICAgICAgICB2YXIgYXhpc05hbWUgPSBheGlzUHJvcGVydGllc1tkXTtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhpc05hbWUuY2hhckF0KDApO1xuICAgICAgICB2YXIgYXggPSBzY2VuZUxheW91dFtheGlzTmFtZV07XG4gICAgICAgIHZhciBjb29yZHMgPSB0cmFjZVtheExldHRlcl07XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRyYWNlW2F4TGV0dGVyICsgJ2NhbGVuZGFyJ107XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZVsnXycgKyBheExldHRlciArICdsZW5ndGgnXTtcblxuICAgICAgICBpZighTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoY29vcmRzKSkge1xuICAgICAgICAgICAgYm91bmRzWzBdW2RdID0gTWF0aC5taW4oYm91bmRzWzBdW2RdLCAwKTtcbiAgICAgICAgICAgIGJvdW5kc1sxXVtkXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtkXSwgbGVuIC0gMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdjtcblxuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IChsZW4gfHwgY29vcmRzLmxlbmd0aCk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGNvb3Jkc1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNvb3Jkc1tpXS5sZW5ndGg7ICsraikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdiA9IGF4LmQybChjb29yZHNbaV1bal0sIDAsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTih2KSAmJiBpc0Zpbml0ZSh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1swXVtkXSA9IE1hdGgubWluKGJvdW5kc1swXVtkXSwgdik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzFdW2RdID0gTWF0aC5tYXgoYm91bmRzWzFdW2RdLCB2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHYgPSBheC5kMmwoY29vcmRzW2ldLCAwLCBjYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTih2KSAmJiBpc0Zpbml0ZSh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdW2RdID0gTWF0aC5taW4oYm91bmRzWzBdW2RdLCB2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1sxXVtkXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtkXSwgdik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbnByb3RvLnBsb3QgPSBmdW5jdGlvbihzY2VuZURhdGEsIGZ1bGxMYXlvdXQsIGxheW91dCkge1xuXG4gICAgLy8gU2F2ZSBwYXJhbWV0ZXJzXG4gICAgdGhpcy5wbG90QXJncyA9IFtzY2VuZURhdGEsIGZ1bGxMYXlvdXQsIGxheW91dF07XG5cbiAgICBpZih0aGlzLmdscGxvdC5jb250ZXh0TG9zdCkgcmV0dXJuO1xuXG4gICAgdmFyIGRhdGEsIHRyYWNlO1xuICAgIHZhciBpLCBqLCBheGlzLCBheGlzVHlwZTtcbiAgICB2YXIgZnVsbFNjZW5lTGF5b3V0ID0gZnVsbExheW91dFt0aGlzLmlkXTtcbiAgICB2YXIgc2NlbmVMYXlvdXQgPSBsYXlvdXRbdGhpcy5pZF07XG5cbiAgICBpZihmdWxsU2NlbmVMYXlvdXQuYmdjb2xvcikgdGhpcy5nbHBsb3QuY2xlYXJDb2xvciA9IHN0cjJSR0JBYXJyYXkoZnVsbFNjZW5lTGF5b3V0LmJnY29sb3IpO1xuICAgIGVsc2UgdGhpcy5nbHBsb3QuY2xlYXJDb2xvciA9IFswLCAwLCAwLCAwXTtcblxuICAgIHRoaXMuZ2xwbG90LnNuYXBUb0RhdGEgPSB0cnVlO1xuXG4gICAgLy8gVXBkYXRlIGxheW91dFxuICAgIHRoaXMuZnVsbExheW91dCA9IGZ1bGxMYXlvdXQ7XG4gICAgdGhpcy5mdWxsU2NlbmVMYXlvdXQgPSBmdWxsU2NlbmVMYXlvdXQ7XG5cbiAgICB0aGlzLmdscGxvdExheW91dCA9IGZ1bGxTY2VuZUxheW91dDtcbiAgICB0aGlzLmF4ZXNPcHRpb25zLm1lcmdlKGZ1bGxTY2VuZUxheW91dCk7XG4gICAgdGhpcy5zcGlrZU9wdGlvbnMubWVyZ2UoZnVsbFNjZW5lTGF5b3V0KTtcblxuICAgIC8vIFVwZGF0ZSBjYW1lcmEgYW5kIGNhbWVyYSBtb2RlXG4gICAgdGhpcy5zZXRDYW1lcmEoZnVsbFNjZW5lTGF5b3V0LmNhbWVyYSk7XG4gICAgdGhpcy51cGRhdGVGeChmdWxsU2NlbmVMYXlvdXQuZHJhZ21vZGUsIGZ1bGxTY2VuZUxheW91dC5ob3Zlcm1vZGUpO1xuXG4gICAgLy8gVXBkYXRlIHNjZW5lXG4gICAgdGhpcy5nbHBsb3QudXBkYXRlKHt9KTtcblxuICAgIC8vIFVwZGF0ZSBheGVzIGZ1bmN0aW9ucyBCRUZPUkUgdXBkYXRpbmcgdHJhY2VzXG4gICAgdGhpcy5zZXRDb252ZXJ0KGF4aXMpO1xuXG4gICAgLy8gQ29udmVydCBzY2VuZSBkYXRhXG4gICAgaWYoIXNjZW5lRGF0YSkgc2NlbmVEYXRhID0gW107XG4gICAgZWxzZSBpZighQXJyYXkuaXNBcnJheShzY2VuZURhdGEpKSBzY2VuZURhdGEgPSBbc2NlbmVEYXRhXTtcblxuICAgIC8vIENvbXB1dGUgdHJhY2UgYm91bmRpbmcgYm94XG4gICAgdmFyIGRhdGFCb3VuZHMgPSBbXG4gICAgICAgIFtJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSxcbiAgICAgICAgWy1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXG4gICAgXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzY2VuZURhdGEubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgZGF0YSA9IHNjZW5lRGF0YVtpXTtcbiAgICAgICAgaWYoZGF0YS52aXNpYmxlICE9PSB0cnVlKSBjb250aW51ZTtcblxuICAgICAgICBjb21wdXRlVHJhY2VCb3VuZHModGhpcywgZGF0YSwgZGF0YUJvdW5kcyk7XG4gICAgfVxuICAgIHZhciBkYXRhU2NhbGUgPSBbMSwgMSwgMV07XG4gICAgZm9yKGogPSAwOyBqIDwgMzsgKytqKSB7XG4gICAgICAgIGlmKGRhdGFCb3VuZHNbMV1bal0gPT09IGRhdGFCb3VuZHNbMF1bal0pIHtcbiAgICAgICAgICAgIGRhdGFTY2FsZVtqXSA9IDEuMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRhdGFTY2FsZVtqXSA9IDEuMCAvIChkYXRhQm91bmRzWzFdW2pdIC0gZGF0YUJvdW5kc1swXVtqXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTYXZlIHNjYWxlXG4gICAgdGhpcy5kYXRhU2NhbGUgPSBkYXRhU2NhbGU7XG5cbiAgICAvLyBhZnRlciBjb21wdXRlVHJhY2VCb3VuZHMgd2hlcmUgYXguX2NhdGVnb3JpZXMgYXJlIGZpbGxlZCBpblxuICAgIHRoaXMuY29udmVydEFubm90YXRpb25zKHRoaXMpO1xuXG4gICAgLy8gVXBkYXRlIHRyYWNlc1xuICAgIGZvcihpID0gMDsgaSA8IHNjZW5lRGF0YS5sZW5ndGg7ICsraSkge1xuICAgICAgICBkYXRhID0gc2NlbmVEYXRhW2ldO1xuICAgICAgICBpZihkYXRhLnZpc2libGUgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRyYWNlID0gdGhpcy50cmFjZXNbZGF0YS51aWRdO1xuICAgICAgICBpZih0cmFjZSkge1xuICAgICAgICAgICAgaWYodHJhY2UuZGF0YS50eXBlID09PSBkYXRhLnR5cGUpIHtcbiAgICAgICAgICAgICAgICB0cmFjZS51cGRhdGUoZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyYWNlLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICB0cmFjZSA9IGRhdGEuX21vZHVsZS5wbG90KHRoaXMsIGRhdGEpO1xuICAgICAgICAgICAgICAgIHRoaXMudHJhY2VzW2RhdGEudWlkXSA9IHRyYWNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhY2UgPSBkYXRhLl9tb2R1bGUucGxvdCh0aGlzLCBkYXRhKTtcbiAgICAgICAgICAgIHRoaXMudHJhY2VzW2RhdGEudWlkXSA9IHRyYWNlO1xuICAgICAgICB9XG4gICAgICAgIHRyYWNlLm5hbWUgPSBkYXRhLm5hbWU7XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGVtcHR5IHRyYWNlc1xuICAgIHZhciB0cmFjZUlkcyA9IE9iamVjdC5rZXlzKHRoaXMudHJhY2VzKTtcblxuICAgIHRyYWNlX2lkX2xvb3A6XG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VJZHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgc2NlbmVEYXRhLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBpZihzY2VuZURhdGFbal0udWlkID09PSB0cmFjZUlkc1tpXSAmJiBzY2VuZURhdGFbal0udmlzaWJsZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlIHRyYWNlX2lkX2xvb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2UgPSB0aGlzLnRyYWNlc1t0cmFjZUlkc1tpXV07XG4gICAgICAgIHRyYWNlLmRpc3Bvc2UoKTtcbiAgICAgICAgZGVsZXRlIHRoaXMudHJhY2VzW3RyYWNlSWRzW2ldXTtcbiAgICB9XG5cbiAgICAvLyBvcmRlciBvYmplY3QgcGVyIHRyYWNlIGluZGV4XG4gICAgdGhpcy5nbHBsb3Qub2JqZWN0cy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEuX3RyYWNlLmRhdGEuaW5kZXggLSBiLl90cmFjZS5kYXRhLmluZGV4O1xuICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlIHJhbmdlcyAobmVlZHMgdG8gYmUgY2FsbGVkICphZnRlciogb2JqZWN0cyBhcmUgYWRkZWQgZHVlIHRvIHVwZGF0ZXMpXG4gICAgdmFyIHNjZW5lQm91bmRzID0gW1swLCAwLCAwXSwgWzAsIDAsIDBdXSxcbiAgICAgICAgYXhpc0RhdGFSYW5nZSA9IFtdLFxuICAgICAgICBheGlzVHlwZVJhdGlvcyA9IHt9O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGF4aXMgPSBmdWxsU2NlbmVMYXlvdXRbYXhpc1Byb3BlcnRpZXNbaV1dO1xuICAgICAgICBheGlzVHlwZSA9IGF4aXMudHlwZTtcblxuICAgICAgICBpZihheGlzVHlwZSBpbiBheGlzVHlwZVJhdGlvcykge1xuICAgICAgICAgICAgYXhpc1R5cGVSYXRpb3NbYXhpc1R5cGVdLmFjYyAqPSBkYXRhU2NhbGVbaV07XG4gICAgICAgICAgICBheGlzVHlwZVJhdGlvc1theGlzVHlwZV0uY291bnQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGF4aXNUeXBlUmF0aW9zW2F4aXNUeXBlXSA9IHtcbiAgICAgICAgICAgICAgICBhY2M6IGRhdGFTY2FsZVtpXSxcbiAgICAgICAgICAgICAgICBjb3VudDogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4aXMuYXV0b3JhbmdlKSB7XG4gICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IEluZmluaXR5O1xuICAgICAgICAgICAgc2NlbmVCb3VuZHNbMV1baV0gPSAtSW5maW5pdHk7XG5cbiAgICAgICAgICAgIHZhciBvYmplY3RzID0gdGhpcy5nbHBsb3Qub2JqZWN0cztcbiAgICAgICAgICAgIHZhciBhbm5vdGF0aW9ucyA9IHRoaXMuZnVsbFNjZW5lTGF5b3V0LmFubm90YXRpb25zIHx8IFtdO1xuICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhpcy5fbmFtZS5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG9iamVjdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgb2JqID0gb2JqZWN0c1tqXTtcbiAgICAgICAgICAgICAgICB2YXIgb2JqQm91bmRzID0gb2JqLmJvdW5kcztcbiAgICAgICAgICAgICAgICB2YXIgcGFkID0gb2JqLl90cmFjZS5kYXRhLl9wYWQgfHwgMDtcblxuICAgICAgICAgICAgICAgIGlmKG9iai5jb25zdHJ1Y3Rvci5uYW1lID09PSAnRXJyb3JCYXJzJyAmJiBheGlzLl9sb3dlckxvZ0Vycm9yQm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gPSBNYXRoLm1pbihzY2VuZUJvdW5kc1swXVtpXSwgYXhpcy5fbG93ZXJMb2dFcnJvckJvdW5kKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IE1hdGgubWluKHNjZW5lQm91bmRzWzBdW2ldLCBvYmpCb3VuZHNbMF1baV0gLyBkYXRhU2NhbGVbaV0gLSBwYWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IE1hdGgubWF4KHNjZW5lQm91bmRzWzFdW2ldLCBvYmpCb3VuZHNbMV1baV0gLyBkYXRhU2NhbGVbaV0gKyBwYWQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBhbm5vdGF0aW9ucy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBhbm4gPSBhbm5vdGF0aW9uc1tqXTtcblxuICAgICAgICAgICAgICAgIC8vIE4uQi4gbm90IHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gdGhlIGFycm93aGVhZFxuICAgICAgICAgICAgICAgIGlmKGFubi52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSBheGlzLnIybChhbm5bYXhMZXR0ZXJdKTtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gPSBNYXRoLm1pbihzY2VuZUJvdW5kc1swXVtpXSwgcG9zKTtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMV1baV0gPSBNYXRoLm1heChzY2VuZUJvdW5kc1sxXVtpXSwgcG9zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCdyYW5nZW1vZGUnIGluIGF4aXMgJiYgYXhpcy5yYW5nZW1vZGUgPT09ICd0b3plcm8nKSB7XG4gICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gPSBNYXRoLm1pbihzY2VuZUJvdW5kc1swXVtpXSwgMCk7XG4gICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMV1baV0gPSBNYXRoLm1heChzY2VuZUJvdW5kc1sxXVtpXSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihzY2VuZUJvdW5kc1swXVtpXSA+IHNjZW5lQm91bmRzWzFdW2ldKSB7XG4gICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gPSAtMTtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkID0gc2NlbmVCb3VuZHNbMV1baV0gLSBzY2VuZUJvdW5kc1swXVtpXTtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSAtPSBkIC8gMzIuMDtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSArPSBkIC8gMzIuMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoYXhpcy5hdXRvcmFuZ2UgPT09ICdyZXZlcnNlZCcpIHtcbiAgICAgICAgICAgICAgICAvLyBzd2FwIGJvdW5kczpcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gc2NlbmVCb3VuZHNbMF1baV07XG4gICAgICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gPSBzY2VuZUJvdW5kc1sxXVtpXTtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IHRtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciByYW5nZSA9IGF4aXMucmFuZ2U7XG4gICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IGF4aXMucjJsKHJhbmdlWzBdKTtcbiAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldID0gYXhpcy5yMmwocmFuZ2VbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lQm91bmRzWzBdW2ldID09PSBzY2VuZUJvdW5kc1sxXVtpXSkge1xuICAgICAgICAgICAgc2NlbmVCb3VuZHNbMF1baV0gLT0gMTtcbiAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgYXhpc0RhdGFSYW5nZVtpXSA9IHNjZW5lQm91bmRzWzFdW2ldIC0gc2NlbmVCb3VuZHNbMF1baV07XG5cbiAgICAgICAgLy8gVXBkYXRlIHBsb3QgYm91bmRzXG4gICAgICAgIHRoaXMuZ2xwbG90LmJvdW5kc1swXVtpXSA9IHNjZW5lQm91bmRzWzBdW2ldICogZGF0YVNjYWxlW2ldO1xuICAgICAgICB0aGlzLmdscGxvdC5ib3VuZHNbMV1baV0gPSBzY2VuZUJvdW5kc1sxXVtpXSAqIGRhdGFTY2FsZVtpXTtcbiAgICB9XG5cbiAgICB2YXIgYXhlc1NjYWxlUmF0aW8gPSBbMSwgMSwgMV07XG5cbiAgICAvLyBDb21wdXRlIGF4aXMgc2NhbGUgcGVyIGNhdGVnb3J5XG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGF4aXMgPSBmdWxsU2NlbmVMYXlvdXRbYXhpc1Byb3BlcnRpZXNbaV1dO1xuICAgICAgICBheGlzVHlwZSA9IGF4aXMudHlwZTtcbiAgICAgICAgdmFyIGF4aXNSYXRpbyA9IGF4aXNUeXBlUmF0aW9zW2F4aXNUeXBlXTtcbiAgICAgICAgYXhlc1NjYWxlUmF0aW9baV0gPSBNYXRoLnBvdyhheGlzUmF0aW8uYWNjLCAxLjAgLyBheGlzUmF0aW8uY291bnQpIC8gZGF0YVNjYWxlW2ldO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogRHluYW1pY2FsbHkgc2V0IHRoZSBhc3BlY3QgcmF0aW8gZGVwZW5kaW5nIG9uIHRoZSB1c2VycyBhc3BlY3Qgc2V0dGluZ3NcbiAgICAgKi9cbiAgICB2YXIgYXhpc0F1dG9TY2FsZUZhY3RvciA9IDQ7XG4gICAgdmFyIGFzcGVjdFJhdGlvO1xuXG4gICAgaWYoZnVsbFNjZW5lTGF5b3V0LmFzcGVjdG1vZGUgPT09ICdhdXRvJykge1xuXG4gICAgICAgIGlmKE1hdGgubWF4LmFwcGx5KG51bGwsIGF4ZXNTY2FsZVJhdGlvKSAvIE1hdGgubWluLmFwcGx5KG51bGwsIGF4ZXNTY2FsZVJhdGlvKSA8PSBheGlzQXV0b1NjYWxlRmFjdG9yKSB7XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBVU0UgREFUQSBNT0RFIFdIRU4gQVhJUyBSQU5HRSBESU1FTlNJT05TIEFSRSBSRUxBVElWRUxZIEVRVUFMXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgYXNwZWN0UmF0aW8gPSBheGVzU2NhbGVSYXRpbztcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIFVTRSBFUVVBTCBNT0RFIFdIRU4gQVhJUyBSQU5HRSBESU1FTlNJT05TIEFSRSBISUdITFkgVU5FUVVBTFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBhc3BlY3RSYXRpbyA9IFsxLCAxLCAxXTtcbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIGlmKGZ1bGxTY2VuZUxheW91dC5hc3BlY3Rtb2RlID09PSAnY3ViZScpIHtcbiAgICAgICAgYXNwZWN0UmF0aW8gPSBbMSwgMSwgMV07XG5cbiAgICB9IGVsc2UgaWYoZnVsbFNjZW5lTGF5b3V0LmFzcGVjdG1vZGUgPT09ICdkYXRhJykge1xuICAgICAgICBhc3BlY3RSYXRpbyA9IGF4ZXNTY2FsZVJhdGlvO1xuXG4gICAgfSBlbHNlIGlmKGZ1bGxTY2VuZUxheW91dC5hc3BlY3Rtb2RlID09PSAnbWFudWFsJykge1xuICAgICAgICB2YXIgdXNlclJhdGlvID0gZnVsbFNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvO1xuICAgICAgICBhc3BlY3RSYXRpbyA9IFt1c2VyUmF0aW8ueCwgdXNlclJhdGlvLnksIHVzZXJSYXRpby56XTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc2NlbmUuanMgYXNwZWN0UmF0aW8gd2FzIG5vdCBvbmUgb2YgdGhlIGVudW1lcmF0ZWQgdHlwZXMnKTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIFdyaXRlIGFzcGVjdCBSYXRpbyBiYWNrIHRvIHVzZXIgZGF0YSBhbmQgZnVsbExheW91dCBzbyB0aGF0IGl0IGlzIG1vZGlmaWVzIGFzIHVzZXJcbiAgICAgKiBtYW5pcHVsYXRlcyB0aGUgYXNwZWN0bW9kZSBzZXR0aW5ncyBhbmQgdGhlIGZ1bGxMYXlvdXQgaXMgdXAtdG8tZGF0ZS5cbiAgICAgKi9cbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueCA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnggPSBhc3BlY3RSYXRpb1swXTtcbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueSA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnkgPSBhc3BlY3RSYXRpb1sxXTtcbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueiA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnogPSBhc3BlY3RSYXRpb1syXTtcblxuICAgIC8qXG4gICAgICogRmluYWxseSBhc3NpZ24gdGhlIGNvbXB1dGVkIGFzcGVjcmF0aW8gdG8gdGhlIGdscGxvdCBtb2R1bGUuIFRoaXMgd2lsbCBoYXZlIGFuIGVmZmVjdFxuICAgICAqIG9uIHRoZSBuZXh0IHJlbmRlciBjeWNsZS5cbiAgICAgKi9cbiAgICB0aGlzLmdscGxvdC5hc3BlY3QgPSBhc3BlY3RSYXRpbztcblxuXG4gICAgLy8gVXBkYXRlIGZyYW1lIHBvc2l0aW9uIGZvciBtdWx0aSBwbG90c1xuICAgIHZhciBkb21haW4gPSBmdWxsU2NlbmVMYXlvdXQuZG9tYWluIHx8IG51bGwsXG4gICAgICAgIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplIHx8IG51bGw7XG5cbiAgICBpZihkb21haW4gJiYgc2l6ZSkge1xuICAgICAgICB2YXIgY29udGFpbmVyU3R5bGUgPSB0aGlzLmNvbnRhaW5lci5zdHlsZTtcbiAgICAgICAgY29udGFpbmVyU3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICBjb250YWluZXJTdHlsZS5sZWZ0ID0gKHNpemUubCArIGRvbWFpbi54WzBdICogc2l6ZS53KSArICdweCc7XG4gICAgICAgIGNvbnRhaW5lclN0eWxlLnRvcCA9IChzaXplLnQgKyAoMSAtIGRvbWFpbi55WzFdKSAqIHNpemUuaCkgKyAncHgnO1xuICAgICAgICBjb250YWluZXJTdHlsZS53aWR0aCA9IChzaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpICsgJ3B4JztcbiAgICAgICAgY29udGFpbmVyU3R5bGUuaGVpZ2h0ID0gKHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSkgKyAncHgnO1xuICAgIH1cblxuICAgIC8vIGZvcmNlIHJlZHJhdyBzbyB0aGF0IHByb21pc2UgaXMgcmV0dXJuZWQgd2hlbiByZW5kZXJpbmcgaXMgY29tcGxldGVkXG4gICAgdGhpcy5nbHBsb3QucmVkcmF3KCk7XG59O1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYoIXRoaXMuZ2xwbG90KSByZXR1cm47XG5cbiAgICB0aGlzLmNhbWVyYS5tb3VzZUxpc3RlbmVyLmVuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuY2FtZXJhLndoZWVsTGlzdGVuZXIpO1xuICAgIHRoaXMuY2FtZXJhID0gdGhpcy5nbHBsb3QuY2FtZXJhID0gbnVsbDtcbiAgICB0aGlzLmdscGxvdC5kaXNwb3NlKCk7XG4gICAgdGhpcy5jb250YWluZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmNvbnRhaW5lcik7XG4gICAgdGhpcy5nbHBsb3QgPSBudWxsO1xufTtcblxuLy8gZ2V0T3JiaXRDYW1lcmEgOjogcGxvdGx5X2Nvb3JkcyAtPiBvcmJpdF9jYW1lcmFfY29vcmRzXG4vLyBpbnZlcnNlIG9mIGdldExheW91dENhbWVyYVxuZnVuY3Rpb24gZ2V0T3JiaXRDYW1lcmEoY2FtZXJhKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgW2NhbWVyYS5leWUueCwgY2FtZXJhLmV5ZS55LCBjYW1lcmEuZXllLnpdLFxuICAgICAgICBbY2FtZXJhLmNlbnRlci54LCBjYW1lcmEuY2VudGVyLnksIGNhbWVyYS5jZW50ZXIuel0sXG4gICAgICAgIFtjYW1lcmEudXAueCwgY2FtZXJhLnVwLnksIGNhbWVyYS51cC56XVxuICAgIF07XG59XG5cbi8vIGdldExheW91dENhbWVyYSA6OiBvcmJpdF9jYW1lcmFfY29vcmRzIC0+IHBsb3RseV9jb29yZHNcbi8vIGludmVyc2Ugb2YgZ2V0T3JiaXRDYW1lcmFcbmZ1bmN0aW9uIGdldExheW91dENhbWVyYShjYW1lcmEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB1cDoge3g6IGNhbWVyYS51cFswXSwgeTogY2FtZXJhLnVwWzFdLCB6OiBjYW1lcmEudXBbMl19LFxuICAgICAgICBjZW50ZXI6IHt4OiBjYW1lcmEuY2VudGVyWzBdLCB5OiBjYW1lcmEuY2VudGVyWzFdLCB6OiBjYW1lcmEuY2VudGVyWzJdfSxcbiAgICAgICAgZXllOiB7eDogY2FtZXJhLmV5ZVswXSwgeTogY2FtZXJhLmV5ZVsxXSwgejogY2FtZXJhLmV5ZVsyXX1cbiAgICB9O1xufVxuXG4vLyBnZXQgY2FtZXJhIHBvc2l0aW9uIGluIHBsb3RseSBjb29yZHMgZnJvbSAnb3JiaXQtY2FtZXJhJyBjb29yZHNcbnByb3RvLmdldENhbWVyYSA9IGZ1bmN0aW9uIGdldENhbWVyYSgpIHtcbiAgICB0aGlzLmdscGxvdC5jYW1lcmEudmlldy5yZWNhbGNNYXRyaXgodGhpcy5jYW1lcmEudmlldy5sYXN0VCgpKTtcbiAgICByZXR1cm4gZ2V0TGF5b3V0Q2FtZXJhKHRoaXMuZ2xwbG90LmNhbWVyYSk7XG59O1xuXG4vLyBzZXQgY2FtZXJhIHBvc2l0aW9uIHdpdGggYSBzZXQgb2YgcGxvdGx5IGNvb3Jkc1xucHJvdG8uc2V0Q2FtZXJhID0gZnVuY3Rpb24gc2V0Q2FtZXJhKGNhbWVyYURhdGEpIHtcbiAgICB0aGlzLmdscGxvdC5jYW1lcmEubG9va0F0LmFwcGx5KHRoaXMsIGdldE9yYml0Q2FtZXJhKGNhbWVyYURhdGEpKTtcbn07XG5cbi8vIHNhdmUgY2FtZXJhIHRvIHVzZXIgbGF5b3V0IChpLmUuIGdkLmxheW91dClcbnByb3RvLnNhdmVDYW1lcmEgPSBmdW5jdGlvbiBzYXZlQ2FtZXJhKGxheW91dCkge1xuICAgIHZhciBjYW1lcmFEYXRhID0gdGhpcy5nZXRDYW1lcmEoKSxcbiAgICAgICAgY2FtZXJhTmVzdGVkUHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShsYXlvdXQsIHRoaXMuaWQgKyAnLmNhbWVyYScpLFxuICAgICAgICBjYW1lcmFEYXRhTGFzdFNhdmUgPSBjYW1lcmFOZXN0ZWRQcm9wLmdldCgpLFxuICAgICAgICBoYXNDaGFuZ2VkID0gZmFsc2U7XG5cbiAgICBmdW5jdGlvbiBzYW1lKHgsIHksIGksIGopIHtcbiAgICAgICAgdmFyIHZlY3RvcnMgPSBbJ3VwJywgJ2NlbnRlcicsICdleWUnXSxcbiAgICAgICAgICAgIGNvbXBvbmVudHMgPSBbJ3gnLCAneScsICd6J107XG4gICAgICAgIHJldHVybiB5W3ZlY3RvcnNbaV1dICYmICh4W3ZlY3RvcnNbaV1dW2NvbXBvbmVudHNbal1dID09PSB5W3ZlY3RvcnNbaV1dW2NvbXBvbmVudHNbal1dKTtcbiAgICB9XG5cbiAgICBpZihjYW1lcmFEYXRhTGFzdFNhdmUgPT09IHVuZGVmaW5lZCkgaGFzQ2hhbmdlZCA9IHRydWU7XG4gICAgZWxzZSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCAzOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZighc2FtZShjYW1lcmFEYXRhLCBjYW1lcmFEYXRhTGFzdFNhdmUsIGksIGopKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoYXNDaGFuZ2VkKSBjYW1lcmFOZXN0ZWRQcm9wLnNldChjYW1lcmFEYXRhKTtcblxuICAgIHJldHVybiBoYXNDaGFuZ2VkO1xufTtcblxucHJvdG8udXBkYXRlRnggPSBmdW5jdGlvbihkcmFnbW9kZSwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGNhbWVyYSA9IHRoaXMuY2FtZXJhO1xuXG4gICAgaWYoY2FtZXJhKSB7XG4gICAgICAgIC8vIHJvdGF0ZSBhbmQgb3JiaXRhbCBhcmUgc3lub255bW91c1xuICAgICAgICBpZihkcmFnbW9kZSA9PT0gJ29yYml0Jykge1xuICAgICAgICAgICAgY2FtZXJhLm1vZGUgPSAnb3JiaXQnO1xuICAgICAgICAgICAgY2FtZXJhLmtleUJpbmRpbmdNb2RlID0gJ3JvdGF0ZSc7XG5cbiAgICAgICAgfSBlbHNlIGlmKGRyYWdtb2RlID09PSAndHVybnRhYmxlJykge1xuICAgICAgICAgICAgY2FtZXJhLnVwID0gWzAsIDAsIDFdO1xuICAgICAgICAgICAgY2FtZXJhLm1vZGUgPSAndHVybnRhYmxlJztcbiAgICAgICAgICAgIGNhbWVyYS5rZXlCaW5kaW5nTW9kZSA9ICdyb3RhdGUnO1xuXG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIC8vIG5vbmUgcm90YXRpb24gbW9kZXMgW3BhbiBvciB6b29tXVxuICAgICAgICAgICAgY2FtZXJhLmtleUJpbmRpbmdNb2RlID0gZHJhZ21vZGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0byBwdXQgZHJhZ21vZGUgYW5kIGhvdmVybW9kZSBvbiB0aGUgc2FtZSBncm91bmRzIGZyb20gcmVsYXlvdXRcbiAgICB0aGlzLmZ1bGxTY2VuZUxheW91dC5ob3Zlcm1vZGUgPSBob3Zlcm1vZGU7XG59O1xuXG5wcm90by50b0ltYWdlID0gZnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgaWYoIWZvcm1hdCkgZm9ybWF0ID0gJ3BuZyc7XG5cbiAgICBpZih0aGlzLnN0YXRpY01vZGUpIHRoaXMuY29udGFpbmVyLmFwcGVuZENoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgLy8gRm9yY2UgcmVkcmF3XG4gICAgdGhpcy5nbHBsb3QucmVkcmF3KCk7XG5cbiAgICAvLyBHcmFiIGNvbnRleHQgYW5kIHlhbmsgb3V0IHBpeGVsc1xuICAgIHZhciBnbCA9IHRoaXMuZ2xwbG90LmdsO1xuICAgIHZhciB3ID0gZ2wuZHJhd2luZ0J1ZmZlcldpZHRoO1xuICAgIHZhciBoID0gZ2wuZHJhd2luZ0J1ZmZlckhlaWdodDtcblxuICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbCk7XG5cbiAgICB2YXIgcGl4ZWxzID0gbmV3IFVpbnQ4QXJyYXkodyAqIGggKiA0KTtcbiAgICBnbC5yZWFkUGl4ZWxzKDAsIDAsIHcsIGgsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHBpeGVscyk7XG5cbiAgICAvLyBGbGlwIHBpeGVsc1xuICAgIGZvcih2YXIgaiA9IDAsIGsgPSBoIC0gMTsgaiA8IGs7ICsraiwgLS1rKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB3OyArK2kpIHtcbiAgICAgICAgICAgIGZvcih2YXIgbCA9IDA7IGwgPCA0OyArK2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gcGl4ZWxzWzQgKiAodyAqIGogKyBpKSArIGxdO1xuICAgICAgICAgICAgICAgIHBpeGVsc1s0ICogKHcgKiBqICsgaSkgKyBsXSA9IHBpeGVsc1s0ICogKHcgKiBrICsgaSkgKyBsXTtcbiAgICAgICAgICAgICAgICBwaXhlbHNbNCAqICh3ICogayArIGkpICsgbF0gPSB0bXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY2FudmFzLndpZHRoID0gdztcbiAgICBjYW52YXMuaGVpZ2h0ID0gaDtcbiAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIHZhciBpbWFnZURhdGEgPSBjb250ZXh0LmNyZWF0ZUltYWdlRGF0YSh3LCBoKTtcbiAgICBpbWFnZURhdGEuZGF0YS5zZXQocGl4ZWxzKTtcbiAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuXG4gICAgdmFyIGRhdGFVUkw7XG5cbiAgICBzd2l0Y2goZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgJ2pwZWcnOlxuICAgICAgICAgICAgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd3ZWJwJzpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS93ZWJwJyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9wbmcnKTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnN0YXRpY01vZGUpIHRoaXMuY29udGFpbmVyLnJlbW92ZUNoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgcmV0dXJuIGRhdGFVUkw7XG59O1xuXG5wcm90by5zZXRDb252ZXJ0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICB2YXIgYXggPSB0aGlzLmZ1bGxTY2VuZUxheW91dFtheGlzUHJvcGVydGllc1tpXV07XG4gICAgICAgIEF4ZXMuc2V0Q29udmVydChheCwgdGhpcy5mdWxsTGF5b3V0KTtcbiAgICAgICAgYXguc2V0U2NhbGUgPSBMaWIubm9vcDtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNjZW5lO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHppcDMoeCwgeSwgeiwgbGVuKSB7XG4gICAgbGVuID0gbGVuIHx8IHgubGVuZ3RoO1xuXG4gICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShsZW4pO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBbeFtpXSwgeVtpXSwgeltpXV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBhbmltYXRpb25BdHRycyA9IHJlcXVpcmUoJy4vYW5pbWF0aW9uX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgZ2xvYmFsRm9udCA9IGZvbnRBdHRycyh7XG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBcbn0pO1xuZ2xvYmFsRm9udC5mYW1pbHkuZGZsdCA9ICdcIk9wZW4gU2Fuc1wiLCB2ZXJkYW5hLCBhcmlhbCwgc2Fucy1zZXJpZic7XG5nbG9iYWxGb250LnNpemUuZGZsdCA9IDEyO1xuZ2xvYmFsRm9udC5jb2xvci5kZmx0ID0gY29sb3JBdHRycy5kZWZhdWx0TGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZm9udDogZ2xvYmFsRm9udCxcbiAgICB0aXRsZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpdGxlZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIGF1dG9zaXplOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAvLyBhdXRvc2l6ZSwgd2lkdGgsIGFuZCBoZWlnaHQgZ2V0IHNwZWNpYWwgZWRpdFR5cGUgdHJlYXRtZW50IGluIF9yZWxheW91dFxuICAgICAgICAvLyBzbyB3ZSBjYW4gaGFuZGxlIG5vb3AgcmVzaXplcyBtb3JlIGVmZmljaWVudGx5XG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDEwLFxuICAgICAgICBkZmx0OiA3MDAsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaGVpZ2h0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAxMCxcbiAgICAgICAgZGZsdDogNDUwLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1hcmdpbjoge1xuICAgICAgICBsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogODAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHI6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiA4MCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDEwMCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDgwLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBwYWQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBhdXRvZXhwYW5kOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIHBhcGVyX2JnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuYmFja2dyb3VuZCxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBwbG90X2JnY29sb3I6IHtcbiAgICAgICAgLy8gZGVmaW5lZCBoZXJlLCBidXQgc2V0IGluIGNhcnRlc2lhbi5zdXBwbHlMYXlvdXREZWZhdWx0c1xuICAgICAgICAvLyBiZWNhdXNlIGl0IG5lZWRzIHRvIGtub3cgaWYgdGhlcmUgYXJlICgyRCkgYXhlcyBvciBub3RcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuYmFja2dyb3VuZCxcbiAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2VwYXJhdG9yczoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaGlkZXNvdXJjZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2xlZ2VuZDoge1xuICAgICAgICAvLyBoYW5kbGVkIGluIGxlZ2VuZC5zdXBwbHlMYXlvdXREZWZhdWx0c1xuICAgICAgICAvLyBidXQgaW5jbHVkZWQgaGVyZSBiZWNhdXNlIGl0J3Mgbm90IGluIHRoZSBsZWdlbmQgb2JqZWN0XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb2xvcndheToge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3JsaXN0JyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0cyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGF0YXJldmlzaW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbW9kZWJhcjoge1xuICAgICAgICBvcmllbnRhdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ3YnLCAnaCddLFxuICAgICAgICAgICAgZGZsdDogJ2gnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGJnY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYWN0aXZlY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdtb2RlYmFyJ1xuICAgIH0sXG5cbiAgICB0cmFuc2l0aW9uOiBleHRlbmRGbGF0KHt9LCBhbmltYXRpb25BdHRycy50cmFuc2l0aW9uLCB7XG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnXG4gICAgfSlcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciByZXF1aXJlZFZlcnNpb24gPSAnMC40NS4wJztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcmVxdWlyZWRWZXJzaW9uOiByZXF1aXJlZFZlcnNpb24sXG5cbiAgICBzdHlsZVVybFByZWZpeDogJ21hcGJveDovL3N0eWxlcy9tYXBib3gvJyxcbiAgICBzdHlsZVVybFN1ZmZpeDogJ3Y5JyxcblxuICAgIGNvbnRyb2xDb250YWluZXJDbGFzc05hbWU6ICdtYXBib3hnbC1jb250cm9sLWNvbnRhaW5lcicsXG5cbiAgICB3cm9uZ1ZlcnNpb25FcnJvck1zZzogW1xuICAgICAgICAnWW91ciBjdXN0b20gcGxvdGx5LmpzIGJ1bmRsZSBpcyBub3QgdXNpbmcgdGhlIGNvcnJlY3QgbWFwYm94LWdsIHZlcnNpb24nLFxuICAgICAgICAnUGxlYXNlIGluc3RhbGwgbWFwYm94LWdsQCcgKyByZXF1aXJlZFZlcnNpb24gKyAnLidcbiAgICBdLmpvaW4oJ1xcbicpLFxuXG4gICAgbm9BY2Nlc3NUb2tlbkVycm9yTXNnOiBbXG4gICAgICAgICdNaXNzaW5nIE1hcGJveCBhY2Nlc3MgdG9rZW4uJyxcbiAgICAgICAgJ01hcGJveCB0cmFjZSB0eXBlIHJlcXVpcmUgYSBNYXBib3ggYWNjZXNzIHRva2VuIHRvIGJlIHJlZ2lzdGVyZWQuJyxcbiAgICAgICAgJ0ZvciBleGFtcGxlOicsXG4gICAgICAgICcgIFBsb3RseS5wbG90KGdkLCBkYXRhLCBsYXlvdXQsIHsgbWFwYm94QWNjZXNzVG9rZW46IFxcJ215LWFjY2Vzcy10b2tlblxcJyB9KTsnLFxuICAgICAgICAnTW9yZSBpbmZvIGhlcmU6IGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vaGVscC9kZWZpbmUtYWNjZXNzLXRva2VuLydcbiAgICBdLmpvaW4oJ1xcbicpLFxuXG4gICAgbWFwT25FcnJvck1zZzogJ01hcGJveCBlcnJvci4nLFxuXG4gICAgLy8gYSBzdWJzZXQgb2Ygbm9kZV9tb2R1bGVzL21hcGJveC1nbC9kaXN0L21hcGJveC1nbC5jc3NcbiAgICBzdHlsZVJ1bGVzOiB7XG4gICAgICAgIG1hcDogJ292ZXJmbG93OmhpZGRlbjtwb3NpdGlvbjpyZWxhdGl2ZTsnLFxuICAgICAgICAnbWlzc2luZy1jc3MnOiAnZGlzcGxheTpub25lJyxcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLyoqXG4gKiBDb252ZXJ0IHBsb3RseS5qcyAndGV4dHBvc2l0aW9uJyB0byBtYXBib3gtZ2wgJ2FuY2hvcicgYW5kICdvZmZzZXQnXG4gKiAod2l0aCB0aGUgaGVscCBvZiB0aGUgaWNvbiBzaXplKS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dHBvc3Rpb24gOiBwbG90bHkuanMgdGV4dHBvc2l0aW9uIHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gaWNvblNpemUgOiBwbG90bHkuanMgaWNvbiBzaXplIChlLmcuIG1hcmtlci5zaXplIGZvciB0cmFjZXMpXG4gKlxuICogQHJldHVybiB7b2JqZWN0fVxuICogICAgICAtIGFuY2hvclxuICogICAgICAtIG9mZnNldFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbnZlcnRUZXh0T3B0cyh0ZXh0cG9zaXRpb24sIGljb25TaXplKSB7XG4gICAgdmFyIHBhcnRzID0gdGV4dHBvc2l0aW9uLnNwbGl0KCcgJyksXG4gICAgICAgIHZQb3MgPSBwYXJ0c1swXSxcbiAgICAgICAgaFBvcyA9IHBhcnRzWzFdO1xuXG4gICAgLy8gYmFsbHBhY2sgdmFsdWVzXG4gICAgdmFyIGZhY3RvciA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGljb25TaXplKSA/IExpYi5tZWFuKGljb25TaXplKSA6IGljb25TaXplLFxuICAgICAgICB4SW5jID0gMC41ICsgKGZhY3RvciAvIDEwMCksXG4gICAgICAgIHlJbmMgPSAxLjUgKyAoZmFjdG9yIC8gMTAwKTtcblxuICAgIHZhciBhbmNob3JWYWxzID0gWycnLCAnJ10sXG4gICAgICAgIG9mZnNldCA9IFswLCAwXTtcblxuICAgIHN3aXRjaCh2UG9zKSB7XG4gICAgICAgIGNhc2UgJ3RvcCc6XG4gICAgICAgICAgICBhbmNob3JWYWxzWzBdID0gJ3RvcCc7XG4gICAgICAgICAgICBvZmZzZXRbMV0gPSAteUluYztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgICAgYW5jaG9yVmFsc1swXSA9ICdib3R0b20nO1xuICAgICAgICAgICAgb2Zmc2V0WzFdID0geUluYztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHN3aXRjaChoUG9zKSB7XG4gICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgICAgYW5jaG9yVmFsc1sxXSA9ICdyaWdodCc7XG4gICAgICAgICAgICBvZmZzZXRbMF0gPSAteEluYztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgICBhbmNob3JWYWxzWzFdID0gJ2xlZnQnO1xuICAgICAgICAgICAgb2Zmc2V0WzBdID0geEluYztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIE1hcGJveCB0ZXh0LWFuY2hvciBtdXN0IGJlIG9uZSBvZjpcbiAgICAvLyAgY2VudGVyLCBsZWZ0LCByaWdodCwgdG9wLCBib3R0b20sXG4gICAgLy8gIHRvcC1sZWZ0LCB0b3AtcmlnaHQsIGJvdHRvbS1sZWZ0LCBib3R0b20tcmlnaHRcblxuICAgIHZhciBhbmNob3I7XG4gICAgaWYoYW5jaG9yVmFsc1swXSAmJiBhbmNob3JWYWxzWzFdKSBhbmNob3IgPSBhbmNob3JWYWxzLmpvaW4oJy0nKTtcbiAgICBlbHNlIGlmKGFuY2hvclZhbHNbMF0pIGFuY2hvciA9IGFuY2hvclZhbHNbMF07XG4gICAgZWxzZSBpZihhbmNob3JWYWxzWzFdKSBhbmNob3IgPSBhbmNob3JWYWxzWzFdO1xuICAgIGVsc2UgYW5jaG9yID0gJ2NlbnRlcic7XG5cbiAgICByZXR1cm4geyBhbmNob3I6IGFuY2hvciwgb2Zmc2V0OiBvZmZzZXQgfTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtYXBib3hnbCA9IHJlcXVpcmUoJ21hcGJveC1nbCcpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgZ2V0U3VicGxvdENhbGNEYXRhID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRTdWJwbG90Q2FsY0RhdGE7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcblxudmFyIGNyZWF0ZU1hcGJveCA9IHJlcXVpcmUoJy4vbWFwYm94Jyk7XG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcblxudmFyIE1BUEJPWCA9ICdtYXBib3gnO1xuXG5mb3IodmFyIGsgaW4gY29uc3RhbnRzLnN0eWxlUnVsZXMpIHtcbiAgICBMaWIuYWRkU3R5bGVSdWxlKCcubWFwYm94Z2wtJyArIGssIGNvbnN0YW50cy5zdHlsZVJ1bGVzW2tdKTtcbn1cblxuZXhwb3J0cy5uYW1lID0gTUFQQk9YO1xuXG5leHBvcnRzLmF0dHIgPSAnc3VicGxvdCc7XG5cbmV4cG9ydHMuaWRSb290ID0gTUFQQk9YO1xuXG5leHBvcnRzLmlkUmVnZXggPSBleHBvcnRzLmF0dHJSZWdleCA9IExpYi5jb3VudGVyUmVnZXgoTUFQQk9YKTtcblxuZXhwb3J0cy5hdHRyaWJ1dGVzID0ge1xuICAgIHN1YnBsb3Q6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N1YnBsb3RpZCcsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnbWFwYm94JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxuZXhwb3J0cy5sYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5leHBvcnRzLnN1cHBseUxheW91dERlZmF1bHRzID0gcmVxdWlyZSgnLi9sYXlvdXRfZGVmYXVsdHMnKTtcblxuZXhwb3J0cy5wbG90ID0gZnVuY3Rpb24gcGxvdE1hcGJveChnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIG1hcGJveElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW01BUEJPWF07XG5cbiAgICBpZihtYXBib3hnbC52ZXJzaW9uICE9PSBjb25zdGFudHMucmVxdWlyZWRWZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihjb25zdGFudHMud3JvbmdWZXJzaW9uRXJyb3JNc2cpO1xuICAgIH1cblxuICAgIHZhciBhY2Nlc3NUb2tlbiA9IGZpbmRBY2Nlc3NUb2tlbihnZCwgbWFwYm94SWRzKTtcbiAgICBtYXBib3hnbC5hY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG1hcGJveElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBtYXBib3hJZHNbaV0sXG4gICAgICAgICAgICBzdWJwbG90Q2FsY0RhdGEgPSBnZXRTdWJwbG90Q2FsY0RhdGEoY2FsY0RhdGEsIE1BUEJPWCwgaWQpLFxuICAgICAgICAgICAgb3B0cyA9IGZ1bGxMYXlvdXRbaWRdLFxuICAgICAgICAgICAgbWFwYm94ID0gb3B0cy5fc3VicGxvdDtcblxuICAgICAgICBpZighbWFwYm94KSB7XG4gICAgICAgICAgICBtYXBib3ggPSBjcmVhdGVNYXBib3goe1xuICAgICAgICAgICAgICAgIGdkOiBnZCxcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBpZDogaWQsXG4gICAgICAgICAgICAgICAgZnVsbExheW91dDogZnVsbExheW91dCxcbiAgICAgICAgICAgICAgICBzdGF0aWNQbG90OiBnZC5fY29udGV4dC5zdGF0aWNQbG90XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZnVsbExheW91dFtpZF0uX3N1YnBsb3QgPSBtYXBib3g7XG4gICAgICAgIH1cblxuICAgICAgICBpZighbWFwYm94LnZpZXdJbml0aWFsKSB7XG4gICAgICAgICAgICBtYXBib3gudmlld0luaXRpYWwgPSB7XG4gICAgICAgICAgICAgICAgY2VudGVyOiBMaWIuZXh0ZW5kRmxhdCh7fSwgb3B0cy5jZW50ZXIpLFxuICAgICAgICAgICAgICAgIHpvb206IG9wdHMuem9vbSxcbiAgICAgICAgICAgICAgICBiZWFyaW5nOiBvcHRzLmJlYXJpbmcsXG4gICAgICAgICAgICAgICAgcGl0Y2g6IG9wdHMucGl0Y2hcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBtYXBib3gucGxvdChzdWJwbG90Q2FsY0RhdGEsIGZ1bGxMYXlvdXQsIGdkLl9wcm9taXNlcyk7XG4gICAgfVxufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRNYXBib3hLZXlzID0gb2xkRnVsbExheW91dC5fc3VicGxvdHNbTUFQQk9YXSB8fCBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRNYXBib3hLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvbGRNYXBib3hLZXkgPSBvbGRNYXBib3hLZXlzW2ldO1xuXG4gICAgICAgIGlmKCFuZXdGdWxsTGF5b3V0W29sZE1hcGJveEtleV0gJiYgISFvbGRGdWxsTGF5b3V0W29sZE1hcGJveEtleV0uX3N1YnBsb3QpIHtcbiAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXRbb2xkTWFwYm94S2V5XS5fc3VicGxvdC5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5leHBvcnRzLnRvU1ZHID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbTUFQQk9YXTtcbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbc3VicGxvdElkc1tpXV0sXG4gICAgICAgICAgICBkb21haW4gPSBvcHRzLmRvbWFpbixcbiAgICAgICAgICAgIG1hcGJveCA9IG9wdHMuX3N1YnBsb3Q7XG5cbiAgICAgICAgdmFyIGltYWdlRGF0YSA9IG1hcGJveC50b0ltYWdlKCdwbmcnKTtcbiAgICAgICAgdmFyIGltYWdlID0gZnVsbExheW91dC5fZ2xpbWFnZXMuYXBwZW5kKCdzdmc6aW1hZ2UnKTtcblxuICAgICAgICBpbWFnZS5hdHRyKHtcbiAgICAgICAgICAgIHhtbG5zOiB4bWxuc05hbWVzcGFjZXMuc3ZnLFxuICAgICAgICAgICAgJ3hsaW5rOmhyZWYnOiBpbWFnZURhdGEsXG4gICAgICAgICAgICB4OiBzaXplLmwgKyBzaXplLncgKiBkb21haW4ueFswXSxcbiAgICAgICAgICAgIHk6IHNpemUudCArIHNpemUuaCAqICgxIC0gZG9tYWluLnlbMV0pLFxuICAgICAgICAgICAgd2lkdGg6IHNpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKSxcbiAgICAgICAgICAgIGhlaWdodDogc2l6ZS5oICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pLFxuICAgICAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogJ25vbmUnXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1hcGJveC5kZXN0cm95KCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gZmluZEFjY2Vzc1Rva2VuKGdkLCBtYXBib3hJZHMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBjb250ZXh0ID0gZ2QuX2NvbnRleHQ7XG5cbiAgICAvLyBzcGVjaWFsIGNhc2UgZm9yIE1hcGJveCBBdGxhcyB1c2Vyc1xuICAgIGlmKGNvbnRleHQubWFwYm94QWNjZXNzVG9rZW4gPT09ICcnKSByZXR1cm4gJyc7XG5cbiAgICAvLyBUYWtlIHRoZSBmaXJzdCB0b2tlbiB3ZSBmaW5kIGluIGEgbWFwYm94IHN1YnBsb3QuXG4gICAgLy8gVGhlc2UgZGVmYXVsdCB0byB0aGUgY29udGV4dCB2YWx1ZSBidXQgbWF5IGJlIG92ZXJyaWRkZW4uXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG1hcGJveElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbbWFwYm94SWRzW2ldXTtcblxuICAgICAgICBpZihvcHRzLmFjY2Vzc3Rva2VuKSB7XG4gICAgICAgICAgICByZXR1cm4gb3B0cy5hY2Nlc3N0b2tlbjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihjb25zdGFudHMubm9BY2Nlc3NUb2tlbkVycm9yTXNnKTtcbn1cblxuZXhwb3J0cy51cGRhdGVGeCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW01BUEJPWF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VicGxvdE9iaiA9IGZ1bGxMYXlvdXRbc3VicGxvdElkc1tpXV0uX3N1YnBsb3Q7XG4gICAgICAgIHN1YnBsb3RPYmoudXBkYXRlRngoZnVsbExheW91dCk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGNvbnZlcnRUZXh0T3B0cyA9IHJlcXVpcmUoJy4vY29udmVydF90ZXh0X29wdHMnKTtcblxuZnVuY3Rpb24gTWFwYm94TGF5ZXIobWFwYm94LCBpbmRleCkge1xuICAgIHRoaXMubWFwYm94ID0gbWFwYm94O1xuICAgIHRoaXMubWFwID0gbWFwYm94Lm1hcDtcblxuICAgIHRoaXMudWlkID0gbWFwYm94LnVpZCArICctJyArICdsYXllcicgKyBpbmRleDtcblxuICAgIHRoaXMuaWRTb3VyY2UgPSB0aGlzLnVpZCArICctc291cmNlJztcbiAgICB0aGlzLmlkTGF5ZXIgPSB0aGlzLnVpZCArICctbGF5ZXInO1xuXG4gICAgLy8gc29tZSBzdGF0ZSB2YXJpYWJsZSB0byBjaGVjayBpZiBhIHJlbW92ZS9hZGQgc3RlcCBpcyBuZWVkZWRcbiAgICB0aGlzLnNvdXJjZVR5cGUgPSBudWxsO1xuICAgIHRoaXMuc291cmNlID0gbnVsbDtcbiAgICB0aGlzLmxheWVyVHlwZSA9IG51bGw7XG4gICAgdGhpcy5iZWxvdyA9IG51bGw7XG5cbiAgICAvLyBpcyBsYXllciBjdXJyZW50bHkgdmlzaWJsZVxuICAgIHRoaXMudmlzaWJsZSA9IGZhbHNlO1xufVxuXG52YXIgcHJvdG8gPSBNYXBib3hMYXllci5wcm90b3R5cGU7XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShvcHRzKSB7XG4gICAgaWYoIXRoaXMudmlzaWJsZSkge1xuICAgICAgICAvLyBJTVBPUlRBTlQ6IG11c3QgY3JlYXRlIHNvdXJjZSBiZWZvcmUgbGF5ZXIgdG8gbm90IGNhdXNlIGVycm9yc1xuICAgICAgICB0aGlzLnVwZGF0ZVNvdXJjZShvcHRzKTtcbiAgICAgICAgdGhpcy51cGRhdGVMYXllcihvcHRzKTtcbiAgICB9IGVsc2UgaWYodGhpcy5uZWVkc05ld1NvdXJjZShvcHRzKSkge1xuICAgICAgICAvLyBJTVBPUlRBTlQ6IG11c3QgZGVsZXRlIGxheWVyIGJlZm9yZSBzb3VyY2UgdG8gbm90IGNhdXNlIGVycm9yc1xuICAgICAgICB0aGlzLnJlbW92ZUxheWVyKCk7XG4gICAgICAgIHRoaXMudXBkYXRlU291cmNlKG9wdHMpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxheWVyKG9wdHMpO1xuICAgIH0gZWxzZSBpZih0aGlzLm5lZWRzTmV3TGF5ZXIob3B0cykpIHtcbiAgICAgICAgdGhpcy51cGRhdGVMYXllcihvcHRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZGF0ZVN0eWxlKG9wdHMpO1xuICAgIH1cblxuICAgIHRoaXMudmlzaWJsZSA9IGlzVmlzaWJsZShvcHRzKTtcbn07XG5cbnByb3RvLm5lZWRzTmV3U291cmNlID0gZnVuY3Rpb24ob3B0cykge1xuICAgIC8vIGZvciBzb21lIHJlYXNvbiBjaGFuZ2luZyBsYXllciB0byAnZmlsbCcgb3IgJ3N5bWJvbCdcbiAgICAvLyB3L28gY2hhbmdpbmcgdGhlIHNvdXJjZSB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIG1hcGJveC1nbCAwLjE4IDtcbiAgICAvLyBzdGF5IHNhZmUgYW5kIG1ha2UgbmV3IHNvdXJjZSBvbiB0eXBlIGNoYW5nZXNcbiAgICByZXR1cm4gKFxuICAgICAgICB0aGlzLnNvdXJjZVR5cGUgIT09IG9wdHMuc291cmNldHlwZSB8fFxuICAgICAgICB0aGlzLnNvdXJjZSAhPT0gb3B0cy5zb3VyY2UgfHxcbiAgICAgICAgdGhpcy5sYXllclR5cGUgIT09IG9wdHMudHlwZVxuICAgICk7XG59O1xuXG5wcm90by5uZWVkc05ld0xheWVyID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMubGF5ZXJUeXBlICE9PSBvcHRzLnR5cGUgfHxcbiAgICAgICAgdGhpcy5iZWxvdyAhPT0gb3B0cy5iZWxvd1xuICAgICk7XG59O1xuXG5wcm90by51cGRhdGVTb3VyY2UgPSBmdW5jdGlvbihvcHRzKSB7XG4gICAgdmFyIG1hcCA9IHRoaXMubWFwO1xuXG4gICAgaWYobWFwLmdldFNvdXJjZSh0aGlzLmlkU291cmNlKSkgbWFwLnJlbW92ZVNvdXJjZSh0aGlzLmlkU291cmNlKTtcblxuICAgIHRoaXMuc291cmNlVHlwZSA9IG9wdHMuc291cmNldHlwZTtcbiAgICB0aGlzLnNvdXJjZSA9IG9wdHMuc291cmNlO1xuXG4gICAgaWYoIWlzVmlzaWJsZShvcHRzKSkgcmV0dXJuO1xuXG4gICAgdmFyIHNvdXJjZU9wdHMgPSBjb252ZXJ0U291cmNlT3B0cyhvcHRzKTtcblxuICAgIG1hcC5hZGRTb3VyY2UodGhpcy5pZFNvdXJjZSwgc291cmNlT3B0cyk7XG59O1xuXG5wcm90by51cGRhdGVMYXllciA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG4gICAgdmFyIGNvbnZlcnRlZE9wdHMgPSBjb252ZXJ0T3B0cyhvcHRzKTtcblxuICAgIHRoaXMucmVtb3ZlTGF5ZXIoKTtcbiAgICB0aGlzLmxheWVyVHlwZSA9IG9wdHMudHlwZTtcblxuICAgIGlmKGlzVmlzaWJsZShvcHRzKSkge1xuICAgICAgICBtYXAuYWRkTGF5ZXIoe1xuICAgICAgICAgICAgaWQ6IHRoaXMuaWRMYXllcixcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5pZFNvdXJjZSxcbiAgICAgICAgICAgICdzb3VyY2UtbGF5ZXInOiBvcHRzLnNvdXJjZWxheWVyIHx8ICcnLFxuICAgICAgICAgICAgdHlwZTogb3B0cy50eXBlLFxuICAgICAgICAgICAgbGF5b3V0OiBjb252ZXJ0ZWRPcHRzLmxheW91dCxcbiAgICAgICAgICAgIHBhaW50OiBjb252ZXJ0ZWRPcHRzLnBhaW50XG4gICAgICAgIH0sIG9wdHMuYmVsb3cpO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZVN0eWxlID0gZnVuY3Rpb24ob3B0cykge1xuICAgIGlmKGlzVmlzaWJsZShvcHRzKSkge1xuICAgICAgICB2YXIgY29udmVydGVkT3B0cyA9IGNvbnZlcnRPcHRzKG9wdHMpO1xuICAgICAgICB0aGlzLm1hcGJveC5zZXRPcHRpb25zKHRoaXMuaWRMYXllciwgJ3NldExheW91dFByb3BlcnR5JywgY29udmVydGVkT3B0cy5sYXlvdXQpO1xuICAgICAgICB0aGlzLm1hcGJveC5zZXRPcHRpb25zKHRoaXMuaWRMYXllciwgJ3NldFBhaW50UHJvcGVydHknLCBjb252ZXJ0ZWRPcHRzLnBhaW50KTtcbiAgICB9XG59O1xuXG5wcm90by5yZW1vdmVMYXllciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcbiAgICBpZihtYXAuZ2V0TGF5ZXIodGhpcy5pZExheWVyKSkge1xuICAgICAgICBtYXAucmVtb3ZlTGF5ZXIodGhpcy5pZExheWVyKTtcbiAgICB9XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG4gICAgbWFwLnJlbW92ZUxheWVyKHRoaXMuaWRMYXllcik7XG4gICAgbWFwLnJlbW92ZVNvdXJjZSh0aGlzLmlkU291cmNlKTtcbn07XG5cbmZ1bmN0aW9uIGlzVmlzaWJsZShvcHRzKSB7XG4gICAgdmFyIHNvdXJjZSA9IG9wdHMuc291cmNlO1xuXG4gICAgcmV0dXJuIG9wdHMudmlzaWJsZSAmJiAoXG4gICAgICAgIExpYi5pc1BsYWluT2JqZWN0KHNvdXJjZSkgfHxcbiAgICAgICAgKHR5cGVvZiBzb3VyY2UgPT09ICdzdHJpbmcnICYmIHNvdXJjZS5sZW5ndGggPiAwKVxuICAgICk7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRPcHRzKG9wdHMpIHtcbiAgICB2YXIgbGF5b3V0ID0ge30sXG4gICAgICAgIHBhaW50ID0ge307XG5cbiAgICBzd2l0Y2gob3B0cy50eXBlKSB7XG5cbiAgICAgICAgY2FzZSAnY2lyY2xlJzpcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHBhaW50LCB7XG4gICAgICAgICAgICAgICAgJ2NpcmNsZS1yYWRpdXMnOiBvcHRzLmNpcmNsZS5yYWRpdXMsXG4gICAgICAgICAgICAgICAgJ2NpcmNsZS1jb2xvcic6IG9wdHMuY29sb3IsXG4gICAgICAgICAgICAgICAgJ2NpcmNsZS1vcGFjaXR5Jzogb3B0cy5vcGFjaXR5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2xpbmUnOlxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocGFpbnQsIHtcbiAgICAgICAgICAgICAgICAnbGluZS13aWR0aCc6IG9wdHMubGluZS53aWR0aCxcbiAgICAgICAgICAgICAgICAnbGluZS1jb2xvcic6IG9wdHMuY29sb3IsXG4gICAgICAgICAgICAgICAgJ2xpbmUtb3BhY2l0eSc6IG9wdHMub3BhY2l0eVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdmaWxsJzpcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHBhaW50LCB7XG4gICAgICAgICAgICAgICAgJ2ZpbGwtY29sb3InOiBvcHRzLmNvbG9yLFxuICAgICAgICAgICAgICAgICdmaWxsLW91dGxpbmUtY29sb3InOiBvcHRzLmZpbGwub3V0bGluZWNvbG9yLFxuICAgICAgICAgICAgICAgICdmaWxsLW9wYWNpdHknOiBvcHRzLm9wYWNpdHlcblxuICAgICAgICAgICAgICAgIC8vIG5vIHdheSB0byBwYXNzIHNwZWNpZnkgb3V0bGluZSB3aWR0aCBhdCB0aGUgbW9tZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3N5bWJvbCc6XG4gICAgICAgICAgICB2YXIgc3ltYm9sID0gb3B0cy5zeW1ib2wsXG4gICAgICAgICAgICAgICAgdGV4dE9wdHMgPSBjb252ZXJ0VGV4dE9wdHMoc3ltYm9sLnRleHRwb3NpdGlvbiwgc3ltYm9sLmljb25zaXplKTtcblxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQobGF5b3V0LCB7XG4gICAgICAgICAgICAgICAgJ2ljb24taW1hZ2UnOiBzeW1ib2wuaWNvbiArICctMTUnLFxuICAgICAgICAgICAgICAgICdpY29uLXNpemUnOiBzeW1ib2wuaWNvbnNpemUgLyAxMCxcblxuICAgICAgICAgICAgICAgICd0ZXh0LWZpZWxkJzogc3ltYm9sLnRleHQsXG4gICAgICAgICAgICAgICAgJ3RleHQtc2l6ZSc6IHN5bWJvbC50ZXh0Zm9udC5zaXplLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IHRleHRPcHRzLmFuY2hvcixcbiAgICAgICAgICAgICAgICAndGV4dC1vZmZzZXQnOiB0ZXh0T3B0cy5vZmZzZXRcblxuICAgICAgICAgICAgICAgIC8vIFRPRE8gZm9udCBmYW1pbHlcbiAgICAgICAgICAgICAgICAvLyAndGV4dC1mb250Jzogc3ltYm9sLnRleHRmb250LmZhbWlseS5zcGxpdCgnLCAnKSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChwYWludCwge1xuICAgICAgICAgICAgICAgICdpY29uLWNvbG9yJzogb3B0cy5jb2xvcixcbiAgICAgICAgICAgICAgICAndGV4dC1jb2xvcic6IHN5bWJvbC50ZXh0Zm9udC5jb2xvcixcbiAgICAgICAgICAgICAgICAndGV4dC1vcGFjaXR5Jzogb3B0cy5vcGFjaXR5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiB7IGxheW91dDogbGF5b3V0LCBwYWludDogcGFpbnQgfTtcbn1cblxuZnVuY3Rpb24gY29udmVydFNvdXJjZU9wdHMob3B0cykge1xuICAgIHZhciBzb3VyY2VUeXBlID0gb3B0cy5zb3VyY2V0eXBlO1xuICAgIHZhciBzb3VyY2UgPSBvcHRzLnNvdXJjZTtcbiAgICB2YXIgc291cmNlT3B0cyA9IHt0eXBlOiBzb3VyY2VUeXBlfTtcbiAgICB2YXIgZmllbGQ7XG5cbiAgICBpZihzb3VyY2VUeXBlID09PSAnZ2VvanNvbicpIHtcbiAgICAgICAgZmllbGQgPSAnZGF0YSc7XG4gICAgfSBlbHNlIGlmKHNvdXJjZVR5cGUgPT09ICd2ZWN0b3InKSB7XG4gICAgICAgIGZpZWxkID0gdHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZycgPyAndXJsJyA6ICd0aWxlcyc7XG4gICAgfVxuXG4gICAgc291cmNlT3B0c1tmaWVsZF0gPSBzb3VyY2U7XG4gICAgcmV0dXJuIHNvdXJjZU9wdHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlTWFwYm94TGF5ZXIobWFwYm94LCBpbmRleCwgb3B0cykge1xuICAgIHZhciBtYXBib3hMYXllciA9IG5ldyBNYXBib3hMYXllcihtYXBib3gsIGluZGV4KTtcblxuICAgIG1hcGJveExheWVyLnVwZGF0ZShvcHRzKTtcblxuICAgIHJldHVybiBtYXBib3hMYXllcjtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGRlZmF1bHRMaW5lID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpLmRlZmF1bHRMaW5lO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciB0ZXh0cG9zaXRpb24gPSByZXF1aXJlKCcuLi8uLi90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzJykudGV4dHBvc2l0aW9uO1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG52YXIgZm9udEF0dHIgPSBmb250QXR0cnMoe1xuICAgIFxufSk7XG5mb250QXR0ci5mYW1pbHkuZGZsdCA9ICdPcGVuIFNhbnMgUmVndWxhciwgQXJpYWwgVW5pY29kZSBNUyBSZWd1bGFyJztcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgX2FycmF5QXR0clJlZ2V4cHM6IFtMaWIuY291bnRlclJlZ2V4KCdtYXBib3gnLCAnLmxheWVycycsIHRydWUpXSxcblxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdtYXBib3gnfSksXG5cbiAgICBhY2Nlc3N0b2tlbjoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgbm9CbGFuazogdHJ1ZSxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgdmFsdWVzOiBbJ2Jhc2ljJywgJ3N0cmVldHMnLCAnb3V0ZG9vcnMnLCAnbGlnaHQnLCAnZGFyaycsICdzYXRlbGxpdGUnLCAnc2F0ZWxsaXRlLXN0cmVldHMnXSxcbiAgICAgICAgZGZsdDogJ2Jhc2ljJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjZW50ZXI6IHtcbiAgICAgICAgbG9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBsYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuICAgIHpvb206IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGJlYXJpbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHBpdGNoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGxheWVyczogdGVtcGxhdGVkQXJyYXkoJ2xheWVyJywge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc291cmNldHlwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2dlb2pzb24nLCAndmVjdG9yJ10sXG4gICAgICAgICAgICBkZmx0OiAnZ2VvanNvbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHNvdXJjZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHNvdXJjZWxheWVyOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICB0eXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnY2lyY2xlJywgJ2xpbmUnLCAnZmlsbCcsICdzeW1ib2wnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdjaXJjbGUnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICAvLyBhdHRyaWJ1dGVzIHNoYXJlZCBiZXR3ZWVuIGFsbCB0eXBlc1xuICAgICAgICBiZWxvdzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgZGZsdDogZGVmYXVsdExpbmUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIHR5cGUtc3BlY2lmaWMgc3R5bGUgYXR0cmlidXRlc1xuICAgICAgICBjaXJjbGU6IHtcbiAgICAgICAgICAgIHJhZGl1czoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDE1LFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgZGZsdDogMixcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICBvdXRsaW5lY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIGRmbHQ6IGRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgaWNvbjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdtYXJrZXInLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGljb25zaXplOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgZGZsdDogMTAsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGV4dDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRleHRmb250OiBmb250QXR0cixcbiAgICAgICAgICAgIHRleHRwb3NpdGlvbjogTGliLmV4dGVuZEZsYXQoe30sIHRleHRwb3NpdGlvbiwgeyBhcnJheU9rOiBmYWxzZSB9KVxuICAgICAgICB9XG4gICAgfSlcbn0sICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZVN1YnBsb3REZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3N1YnBsb3RfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgaGFuZGxlU3VicGxvdERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCB7XG4gICAgICAgIHR5cGU6ICdtYXBib3gnLFxuICAgICAgICBhdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzLFxuICAgICAgICBoYW5kbGVEZWZhdWx0czogaGFuZGxlRGVmYXVsdHMsXG4gICAgICAgIHBhcnRpdGlvbjogJ3knLFxuICAgICAgICBhY2Nlc3NUb2tlbjogbGF5b3V0T3V0Ll9tYXBib3hBY2Nlc3NUb2tlblxuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgY29lcmNlKCdhY2Nlc3N0b2tlbicsIG9wdHMuYWNjZXNzVG9rZW4pO1xuICAgIGNvZXJjZSgnc3R5bGUnKTtcbiAgICBjb2VyY2UoJ2NlbnRlci5sb24nKTtcbiAgICBjb2VyY2UoJ2NlbnRlci5sYXQnKTtcbiAgICBjb2VyY2UoJ3pvb20nKTtcbiAgICBjb2VyY2UoJ2JlYXJpbmcnKTtcbiAgICBjb2VyY2UoJ3BpdGNoJyk7XG5cbiAgICBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIHtcbiAgICAgICAgbmFtZTogJ2xheWVycycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogaGFuZGxlTGF5ZXJEZWZhdWx0c1xuICAgIH0pO1xuXG4gICAgLy8gY29weSByZWYgdG8gaW5wdXQgY29udGFpbmVyIHRvIHVwZGF0ZSAnY2VudGVyJyBhbmQgJ3pvb20nIG9uIG1hcCBtb3ZlXG4gICAgY29udGFpbmVyT3V0Ll9pbnB1dCA9IGNvbnRhaW5lckluO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVMYXllckRlZmF1bHRzKGxheWVySW4sIGxheWVyT3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5ZXJJbiwgbGF5ZXJPdXQsIGxheW91dEF0dHJpYnV0ZXMubGF5ZXJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgdmFyIHNvdXJjZVR5cGUgPSBjb2VyY2UoJ3NvdXJjZXR5cGUnKTtcbiAgICAgICAgY29lcmNlKCdzb3VyY2UnKTtcblxuICAgICAgICBpZihzb3VyY2VUeXBlID09PSAndmVjdG9yJykgY29lcmNlKCdzb3VyY2VsYXllcicpO1xuXG4gICAgICAgIC8vIG1heWJlIGFkZCBzbWFydCBkZWZhdWx0IGJhc2VkIG9mZiBHZW9KU09OIGdlb21ldHJ5P1xuICAgICAgICB2YXIgdHlwZSA9IGNvZXJjZSgndHlwZScpO1xuXG4gICAgICAgIGNvZXJjZSgnYmVsb3cnKTtcbiAgICAgICAgY29lcmNlKCdjb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ29wYWNpdHknKTtcblxuICAgICAgICBpZih0eXBlID09PSAnY2lyY2xlJykge1xuICAgICAgICAgICAgY29lcmNlKCdjaXJjbGUucmFkaXVzJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0eXBlID09PSAnbGluZScpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnbGluZS53aWR0aCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHlwZSA9PT0gJ2ZpbGwnKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ2ZpbGwub3V0bGluZWNvbG9yJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgY29lcmNlKCdzeW1ib2wuaWNvbicpO1xuICAgICAgICAgICAgY29lcmNlKCdzeW1ib2wuaWNvbnNpemUnKTtcblxuICAgICAgICAgICAgY29lcmNlKCdzeW1ib2wudGV4dCcpO1xuICAgICAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnc3ltYm9sLnRleHRmb250Jyk7XG4gICAgICAgICAgICBjb2VyY2UoJ3N5bWJvbC50ZXh0cG9zaXRpb24nKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbWFwYm94Z2wgPSByZXF1aXJlKCdtYXBib3gtZ2wnKTtcblxudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGRyYWdFbGVtZW50ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIHByZXBTZWxlY3QgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGNyZWF0ZU1hcGJveExheWVyID0gcmVxdWlyZSgnLi9sYXllcnMnKTtcblxuZnVuY3Rpb24gTWFwYm94KG9wdHMpIHtcbiAgICB0aGlzLmlkID0gb3B0cy5pZDtcbiAgICB0aGlzLmdkID0gb3B0cy5nZDtcbiAgICB0aGlzLmNvbnRhaW5lciA9IG9wdHMuY29udGFpbmVyO1xuICAgIHRoaXMuaXNTdGF0aWMgPSBvcHRzLnN0YXRpY1Bsb3Q7XG5cbiAgICB2YXIgZnVsbExheW91dCA9IG9wdHMuZnVsbExheW91dDtcblxuICAgIC8vIHVuaXF1ZSBpZCBmb3IgdGhpcyBNYXBib3ggaW5zdGFuY2VcbiAgICB0aGlzLnVpZCA9IGZ1bGxMYXlvdXQuX3VpZCArICctJyArIHRoaXMuaWQ7XG5cbiAgICAvLyBmdWxsIG1hcGJveCBvcHRpb25zIChOLkIuIG5lZWRzIHRvIGJlIHVwZGF0ZWQgb24gZXZlcnkgdXBkYXRlcylcbiAgICB0aGlzLm9wdHMgPSBmdWxsTGF5b3V0W3RoaXMuaWRdO1xuXG4gICAgLy8gY3JlYXRlIGZyYW1ld29yayBvbiBpbnN0YW50aWF0aW9uIGZvciBhIHNtb290aGVyIGZpcnN0IHBsb3QgY2FsbFxuICAgIHRoaXMuZGl2ID0gbnVsbDtcbiAgICB0aGlzLnhheGlzID0gbnVsbDtcbiAgICB0aGlzLnlheGlzID0gbnVsbDtcbiAgICB0aGlzLmNyZWF0ZUZyYW1ld29yayhmdWxsTGF5b3V0KTtcblxuICAgIC8vIHN0YXRlIHZhcmlhYmxlcyB1c2VkIHRvIGluZmVyIGhvdyBhbmQgd2hhdCB0byB1cGRhdGVcbiAgICB0aGlzLm1hcCA9IG51bGw7XG4gICAgdGhpcy5hY2Nlc3NUb2tlbiA9IG51bGw7XG4gICAgdGhpcy5zdHlsZU9iaiA9IG51bGw7XG4gICAgdGhpcy50cmFjZUhhc2ggPSB7fTtcbiAgICB0aGlzLmxheWVyTGlzdCA9IFtdO1xufVxuXG52YXIgcHJvdG8gPSBNYXBib3gucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZU1hcGJveChvcHRzKSB7XG4gICAgcmV0dXJuIG5ldyBNYXBib3gob3B0cyk7XG59O1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24oY2FsY0RhdGEsIGZ1bGxMYXlvdXQsIHByb21pc2VzKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgLy8gZmVlZCBpbiBuZXcgbWFwYm94IG9wdGlvbnNcbiAgICB2YXIgb3B0cyA9IHNlbGYub3B0cyA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG5cbiAgICAvLyByZW1vdmUgbWFwIGFuZCBjcmVhdGUgYSBuZXcgbWFwIGlmIGFjY2VzcyB0b2tlbiBoYXMgY2hhbmdlXG4gICAgaWYoc2VsZi5tYXAgJiYgKG9wdHMuYWNjZXNzdG9rZW4gIT09IHNlbGYuYWNjZXNzVG9rZW4pKSB7XG4gICAgICAgIHNlbGYubWFwLnJlbW92ZSgpO1xuICAgICAgICBzZWxmLm1hcCA9IG51bGw7XG4gICAgICAgIHNlbGYuc3R5bGVPYmogPSBudWxsO1xuICAgICAgICBzZWxmLnRyYWNlSGFzaCA9IFtdO1xuICAgICAgICBzZWxmLmxheWVyTGlzdCA9IHt9O1xuICAgIH1cblxuICAgIHZhciBwcm9taXNlO1xuXG4gICAgaWYoIXNlbGYubWFwKSB7XG4gICAgICAgIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHNlbGYuY3JlYXRlTWFwKGNhbGNEYXRhLCBmdWxsTGF5b3V0LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICBzZWxmLnVwZGF0ZU1hcChjYWxjRGF0YSwgZnVsbExheW91dCwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJvbWlzZXMucHVzaChwcm9taXNlKTtcbn07XG5cbnByb3RvLmNyZWF0ZU1hcCA9IGZ1bmN0aW9uKGNhbGNEYXRhLCBmdWxsTGF5b3V0LCByZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGdkID0gc2VsZi5nZDtcbiAgICB2YXIgb3B0cyA9IHNlbGYub3B0cztcblxuICAgIC8vIHN0b3JlIHN0eWxlIGlkIGFuZCBVUkwgb3Igb2JqZWN0XG4gICAgdmFyIHN0eWxlT2JqID0gc2VsZi5zdHlsZU9iaiA9IGdldFN0eWxlT2JqKG9wdHMuc3R5bGUpO1xuXG4gICAgLy8gc3RvcmUgYWNjZXNzIHRva2VuIGFzc29jaWF0ZWQgd2l0aCB0aGlzIG1hcFxuICAgIHNlbGYuYWNjZXNzVG9rZW4gPSBvcHRzLmFjY2Vzc3Rva2VuO1xuXG4gICAgLy8gY3JlYXRlIHRoZSBtYXAhXG4gICAgdmFyIG1hcCA9IHNlbGYubWFwID0gbmV3IG1hcGJveGdsLk1hcCh7XG4gICAgICAgIGNvbnRhaW5lcjogc2VsZi5kaXYsXG5cbiAgICAgICAgc3R5bGU6IHN0eWxlT2JqLnN0eWxlLFxuICAgICAgICBjZW50ZXI6IGNvbnZlcnRDZW50ZXIob3B0cy5jZW50ZXIpLFxuICAgICAgICB6b29tOiBvcHRzLnpvb20sXG4gICAgICAgIGJlYXJpbmc6IG9wdHMuYmVhcmluZyxcbiAgICAgICAgcGl0Y2g6IG9wdHMucGl0Y2gsXG5cbiAgICAgICAgaW50ZXJhY3RpdmU6ICFzZWxmLmlzU3RhdGljLFxuICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHNlbGYuaXNTdGF0aWMsXG5cbiAgICAgICAgZG91YmxlQ2xpY2tab29tOiBmYWxzZSxcbiAgICAgICAgYm94Wm9vbTogZmFsc2VcbiAgICB9KTtcblxuICAgIC8vIGNsZWFyIG5hdmlnYXRpb24gY29udGFpbmVyXG4gICAgdmFyIGNsYXNzTmFtZSA9IGNvbnN0YW50cy5jb250cm9sQ29udGFpbmVyQ2xhc3NOYW1lO1xuICAgIHZhciBjb250cm9sQ29udGFpbmVyID0gc2VsZi5kaXYuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShjbGFzc05hbWUpWzBdO1xuICAgIHNlbGYuZGl2LnJlbW92ZUNoaWxkKGNvbnRyb2xDb250YWluZXIpO1xuXG4gICAgLy8gbWFrZSBzdXJlIGNhbnZhcyBkb2VzIG5vdCBpbmhlcml0IGxlZnQgYW5kIHRvcCBjc3NcbiAgICBtYXAuX2NhbnZhcy5zdHlsZS5sZWZ0ID0gJzBweCc7XG4gICAgbWFwLl9jYW52YXMuc3R5bGUudG9wID0gJzBweCc7XG5cbiAgICBzZWxmLnJlamVjdE9uRXJyb3IocmVqZWN0KTtcblxuICAgIG1hcC5vbmNlKCdsb2FkJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHNlbGYudXBkYXRlRGF0YShjYWxjRGF0YSk7XG4gICAgICAgIHNlbGYudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQpO1xuICAgICAgICBzZWxmLnJlc29sdmVPblJlbmRlcihyZXNvbHZlKTtcbiAgICB9KTtcblxuICAgIGlmKHNlbGYuaXNTdGF0aWMpIHJldHVybjtcblxuICAgIHZhciB3aGVlbGluZyA9IGZhbHNlO1xuXG4gICAgLy8ga2VlcCB0cmFjayBvZiBwYW4gLyB6b29tIGluIHVzZXIgbGF5b3V0IGFuZCBlbWl0IHJlbGF5b3V0IGV2ZW50XG4gICAgbWFwLm9uKCdtb3ZlZW5kJywgZnVuY3Rpb24oZXZlbnREYXRhKSB7XG4gICAgICAgIGlmKCFzZWxmLm1hcCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciB2aWV3ID0gc2VsZi5nZXRWaWV3KCk7XG5cbiAgICAgICAgb3B0cy5faW5wdXQuY2VudGVyID0gb3B0cy5jZW50ZXIgPSB2aWV3LmNlbnRlcjtcbiAgICAgICAgb3B0cy5faW5wdXQuem9vbSA9IG9wdHMuem9vbSA9IHZpZXcuem9vbTtcbiAgICAgICAgb3B0cy5faW5wdXQuYmVhcmluZyA9IG9wdHMuYmVhcmluZyA9IHZpZXcuYmVhcmluZztcbiAgICAgICAgb3B0cy5faW5wdXQucGl0Y2ggPSBvcHRzLnBpdGNoID0gdmlldy5waXRjaDtcblxuICAgICAgICAvLyAnbW92ZWVuZCcgZ2V0cyB0cmlnZ2VyZWQgYnkgbWFwLnNldENlbnRlciwgbWFwLnNldFpvb20sXG4gICAgICAgIC8vIG1hcC5zZXRCZWFyaW5nIGFuZCBtYXAuc2V0UGl0Y2guXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEhlcmUsIHdlIG1ha2Ugc3VyZSB0aGF0ICdwbG90bHlfcmVsYXlvdXQnIGlzXG4gICAgICAgIC8vIHRyaWdnZXJlZCBoZXJlIG9ubHkgd2hlbiB0aGUgJ21vdmVlbmQnIG9yaWdpbmF0ZXMgZnJvbSBhXG4gICAgICAgIC8vIG1vdXNlIHRhcmdldCAoZmlsdGVyaW5nIG91dCBBUEkgY2FsbHMpIHRvIG5vdFxuICAgICAgICAvLyBkdXBsaWNhdGUgJ3Bsb3RseV9yZWxheW91dCcgZXZlbnRzLlxuXG4gICAgICAgIGlmKGV2ZW50RGF0YS5vcmlnaW5hbEV2ZW50IHx8IHdoZWVsaW5nKSB7XG4gICAgICAgICAgICBlbWl0UmVsYXlvdXRGcm9tVmlldyh2aWV3KTtcbiAgICAgICAgfVxuICAgICAgICB3aGVlbGluZyA9IGZhbHNlO1xuICAgIH0pO1xuXG4gICAgbWFwLm9uKCd3aGVlbCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICB3aGVlbGluZyA9IHRydWU7XG4gICAgfSk7XG5cbiAgICBtYXAub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICB2YXIgYmIgPSBzZWxmLmRpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAvLyBzb21lIGhhY2tlcnkgdG8gZ2V0IEZ4LmhvdmVyIHRvIHdvcmtcbiAgICAgICAgZXZ0LmNsaWVudFggPSBldnQucG9pbnQueCArIGJiLmxlZnQ7XG4gICAgICAgIGV2dC5jbGllbnRZID0gZXZ0LnBvaW50LnkgKyBiYi50b3A7XG5cbiAgICAgICAgZXZ0LnRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGJiOyB9O1xuXG4gICAgICAgIHNlbGYueGF4aXMucDJjID0gZnVuY3Rpb24oKSB7IHJldHVybiBldnQubG5nTGF0LmxuZzsgfTtcbiAgICAgICAgc2VsZi55YXhpcy5wMmMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGV2dC5sbmdMYXQubGF0OyB9O1xuXG4gICAgICAgIEZ4LmhvdmVyKGdkLCBldnQsIHNlbGYuaWQpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gdW5ob3ZlcigpIHtcbiAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dC5fdG9wcGFwZXIpO1xuICAgIH1cblxuICAgIG1hcC5vbignZHJhZ3N0YXJ0JywgdW5ob3Zlcik7XG4gICAgbWFwLm9uKCd6b29tc3RhcnQnLCB1bmhvdmVyKTtcblxuICAgIG1hcC5vbignZGJsY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2RvdWJsZWNsaWNrJywgbnVsbCk7XG5cbiAgICAgICAgdmFyIHZpZXdJbml0aWFsID0gc2VsZi52aWV3SW5pdGlhbDtcblxuICAgICAgICBtYXAuc2V0Q2VudGVyKGNvbnZlcnRDZW50ZXIodmlld0luaXRpYWwuY2VudGVyKSk7XG4gICAgICAgIG1hcC5zZXRab29tKHZpZXdJbml0aWFsLnpvb20pO1xuICAgICAgICBtYXAuc2V0QmVhcmluZyh2aWV3SW5pdGlhbC5iZWFyaW5nKTtcbiAgICAgICAgbWFwLnNldFBpdGNoKHZpZXdJbml0aWFsLnBpdGNoKTtcblxuICAgICAgICB2YXIgdmlld05vdyA9IHNlbGYuZ2V0VmlldygpO1xuXG4gICAgICAgIG9wdHMuX2lucHV0LmNlbnRlciA9IG9wdHMuY2VudGVyID0gdmlld05vdy5jZW50ZXI7XG4gICAgICAgIG9wdHMuX2lucHV0Lnpvb20gPSBvcHRzLnpvb20gPSB2aWV3Tm93Lnpvb207XG4gICAgICAgIG9wdHMuX2lucHV0LmJlYXJpbmcgPSBvcHRzLmJlYXJpbmcgPSB2aWV3Tm93LmJlYXJpbmc7XG4gICAgICAgIG9wdHMuX2lucHV0LnBpdGNoID0gb3B0cy5waXRjaCA9IHZpZXdOb3cucGl0Y2g7XG5cbiAgICAgICAgZW1pdFJlbGF5b3V0RnJvbVZpZXcodmlld05vdyk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBlbWl0UmVsYXlvdXRGcm9tVmlldyh2aWV3KSB7XG4gICAgICAgIHZhciBpZCA9IHNlbGYuaWQ7XG4gICAgICAgIHZhciBldnREYXRhID0ge307XG4gICAgICAgIGZvcih2YXIgayBpbiB2aWV3KSB7XG4gICAgICAgICAgICBldnREYXRhW2lkICsgJy4nICsga10gPSB2aWV3W2tdO1xuICAgICAgICB9XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dCcsIGV2dERhdGEpO1xuICAgIH1cblxuICAgIC8vIGRlZmluZSBldmVudCBoYW5kbGVycyBvbiBtYXAgY3JlYXRpb24sIHRvIGtlZXAgb25lIHJlZiBwZXIgbWFwLFxuICAgIC8vIHNvIHRoYXQgbWFwLm9uIC8gbWFwLm9mZiBpbiB1cGRhdGVGeCB3b3JrcyBhcyBleHBlY3RlZFxuICAgIHNlbGYuY2xlYXJTZWxlY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3pvb21sYXllci5zZWxlY3RBbGwoJy5zZWxlY3Qtb3V0bGluZScpLnJlbW92ZSgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgY2xpY2sgaGFuZGxlciBmdW5jdGlvbiB0aGF0IGlzIHN1cHBvc2VkXG4gICAgICogdG8gaGFuZGxlIGNsaWNrcyBpbiBwYW4gbW9kZS5cbiAgICAgKi9cbiAgICBzZWxmLm9uQ2xpY2tJblBhbkZuID0gZnVuY3Rpb24oZHJhZ09wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICAgICAgdmFyIGNsaWNrTW9kZSA9IGdkLl9mdWxsTGF5b3V0LmNsaWNrbW9kZTtcblxuICAgICAgICAgICAgaWYoY2xpY2tNb2RlLmluZGV4T2YoJ3NlbGVjdCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RPbkNsaWNrKGV2dC5vcmlnaW5hbEV2ZW50LCBnZCwgW3NlbGYueGF4aXNdLCBbc2VsZi55YXhpc10sIHNlbGYuaWQsIGRyYWdPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY2xpY2tNb2RlLmluZGV4T2YoJ2V2ZW50JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAgICAgICAgIC8vIHdvdWxkIGxpa2VseSBuZWVkIHRvIGNoYW5nZSBtYXBib3ggdG8gdXNlIGRyYWdFbGVtZW50IGluc3RlYWQgb2Ygc3RyYWlnaHRcbiAgICAgICAgICAgICAgICAvLyBtYXBib3ggZXZlbnQgYmluZGluZy4gT3IgcGVyaGFwcyBiZXR0ZXIsIG1ha2UgYSBzaW1wbGUgd3JhcHBlciB3aXRoIHRoZVxuICAgICAgICAgICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgICAgICAgICAvLyBwaWUgd291bGQgdXNlIHRoaXMgdG9vLlxuICAgICAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBldnQub3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfTtcbn07XG5cbnByb3RvLnVwZGF0ZU1hcCA9IGZ1bmN0aW9uKGNhbGNEYXRhLCBmdWxsTGF5b3V0LCByZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG1hcCA9IHNlbGYubWFwO1xuXG4gICAgc2VsZi5yZWplY3RPbkVycm9yKHJlamVjdCk7XG5cbiAgICB2YXIgc3R5bGVPYmogPSBnZXRTdHlsZU9iaihzZWxmLm9wdHMuc3R5bGUpO1xuXG4gICAgaWYoc2VsZi5zdHlsZU9iai5pZCAhPT0gc3R5bGVPYmouaWQpIHtcbiAgICAgICAgc2VsZi5zdHlsZU9iaiA9IHN0eWxlT2JqO1xuICAgICAgICBtYXAuc2V0U3R5bGUoc3R5bGVPYmouc3R5bGUpO1xuXG4gICAgICAgIG1hcC5vbmNlKCdzdHlsZWRhdGEnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIC8vIG5lZWQgdG8gcmVidWlsZCB0cmFjZSBsYXllcnMgb24gcmVsb2FkXG4gICAgICAgICAgICAvLyB0byBhdm9pZCAnbG9zdCBldmVudCcgZXJyb3JzXG4gICAgICAgICAgICBzZWxmLnRyYWNlSGFzaCA9IHt9O1xuICAgICAgICAgICAgc2VsZi51cGRhdGVEYXRhKGNhbGNEYXRhKTtcbiAgICAgICAgICAgIHNlbGYudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQpO1xuICAgICAgICAgICAgc2VsZi5yZXNvbHZlT25SZW5kZXIocmVzb2x2ZSk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYudXBkYXRlRGF0YShjYWxjRGF0YSk7XG4gICAgICAgIHNlbGYudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQpO1xuICAgICAgICBzZWxmLnJlc29sdmVPblJlbmRlcihyZXNvbHZlKTtcbiAgICB9XG59O1xuXG5wcm90by51cGRhdGVEYXRhID0gZnVuY3Rpb24oY2FsY0RhdGEpIHtcbiAgICB2YXIgdHJhY2VIYXNoID0gdGhpcy50cmFjZUhhc2g7XG4gICAgdmFyIHRyYWNlT2JqLCB0cmFjZSwgaSwgajtcblxuICAgIC8vIHVwZGF0ZSBvciBjcmVhdGUgdHJhY2Ugb2JqZWN0c1xuICAgIGZvcihpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjRGF0YVtpXTtcblxuICAgICAgICB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICAgICAgdHJhY2VPYmogPSB0cmFjZUhhc2hbdHJhY2UudWlkXTtcblxuICAgICAgICBpZih0cmFjZU9iaikge1xuICAgICAgICAgICAgdHJhY2VPYmoudXBkYXRlKGNhbGNUcmFjZSk7XG4gICAgICAgIH0gZWxzZSBpZih0cmFjZS5fbW9kdWxlKSB7XG4gICAgICAgICAgICB0cmFjZUhhc2hbdHJhY2UudWlkXSA9IHRyYWNlLl9tb2R1bGUucGxvdCh0aGlzLCBjYWxjVHJhY2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIGVtcHR5IHRyYWNlIG9iamVjdHNcbiAgICB2YXIgaWRzID0gT2JqZWN0LmtleXModHJhY2VIYXNoKTtcbiAgICBpZF9sb29wOlxuICAgIGZvcihpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBpZHNbaV07XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY0RhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHRyYWNlID0gY2FsY0RhdGFbal1bMF0udHJhY2U7XG4gICAgICAgICAgICBpZihpZCA9PT0gdHJhY2UudWlkKSBjb250aW51ZSBpZF9sb29wO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJhY2VPYmogPSB0cmFjZUhhc2hbaWRdO1xuICAgICAgICB0cmFjZU9iai5kaXNwb3NlKCk7XG4gICAgICAgIGRlbGV0ZSB0cmFjZUhhc2hbaWRdO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZUxheW91dCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXAsXG4gICAgICAgIG9wdHMgPSB0aGlzLm9wdHM7XG5cbiAgICBtYXAuc2V0Q2VudGVyKGNvbnZlcnRDZW50ZXIob3B0cy5jZW50ZXIpKTtcbiAgICBtYXAuc2V0Wm9vbShvcHRzLnpvb20pO1xuICAgIG1hcC5zZXRCZWFyaW5nKG9wdHMuYmVhcmluZyk7XG4gICAgbWFwLnNldFBpdGNoKG9wdHMucGl0Y2gpO1xuXG4gICAgdGhpcy51cGRhdGVMYXllcnMoKTtcbiAgICB0aGlzLnVwZGF0ZUZyYW1ld29yayhmdWxsTGF5b3V0KTtcbiAgICB0aGlzLnVwZGF0ZUZ4KGZ1bGxMYXlvdXQpO1xuICAgIHRoaXMubWFwLnJlc2l6ZSgpO1xufTtcblxucHJvdG8ucmVzb2x2ZU9uUmVuZGVyID0gZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcblxuICAgIG1hcC5vbigncmVuZGVyJywgZnVuY3Rpb24gb25SZW5kZXIoKSB7XG4gICAgICAgIGlmKG1hcC5sb2FkZWQoKSkge1xuICAgICAgICAgICAgbWFwLm9mZigncmVuZGVyJywgb25SZW5kZXIpO1xuICAgICAgICAgICAgLy8gcmVzb2x2ZSBhdCBlbmQgb2YgcmVuZGVyIGxvb3BcbiAgICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgMCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbnByb3RvLnJlamVjdE9uRXJyb3IgPSBmdW5jdGlvbihyZWplY3QpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVyKCkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGNvbnN0YW50cy5tYXBPbkVycm9yTXNnKSk7XG4gICAgfVxuXG4gICAgbWFwLm9uY2UoJ2Vycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ3N0eWxlLmVycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ3NvdXJjZS5lcnJvcicsIGhhbmRsZXIpO1xuICAgIG1hcC5vbmNlKCd0aWxlLmVycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ2xheWVyLmVycm9yJywgaGFuZGxlcik7XG59O1xuXG5wcm90by5jcmVhdGVGcmFtZXdvcmsgPSBmdW5jdGlvbihmdWxsTGF5b3V0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIGRpdiA9IHNlbGYuZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LmlkID0gc2VsZi51aWQ7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzZWxmLmNvbnRhaW5lci5hcHBlbmRDaGlsZChkaXYpO1xuXG4gICAgLy8gY3JlYXRlIG1vY2sgeC95IGF4ZXMgZm9yIGhvdmVyIHJvdXRpbmVcbiAgICBzZWxmLnhheGlzID0ge1xuICAgICAgICBfaWQ6ICd4JyxcbiAgICAgICAgYzJwOiBmdW5jdGlvbih2KSB7IHJldHVybiBzZWxmLnByb2plY3QodikueDsgfVxuICAgIH07XG4gICAgc2VsZi55YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gc2VsZi5wcm9qZWN0KHYpLnk7IH1cbiAgICB9O1xuXG4gICAgc2VsZi51cGRhdGVGcmFtZXdvcmsoZnVsbExheW91dCk7XG59O1xuXG5wcm90by51cGRhdGVGeCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG1hcCA9IHNlbGYubWFwO1xuICAgIHZhciBnZCA9IHNlbGYuZ2Q7XG5cbiAgICBpZihzZWxmLmlzU3RhdGljKSByZXR1cm47XG5cbiAgICBmdW5jdGlvbiBpbnZlcnQocHhweSkge1xuICAgICAgICB2YXIgb2JqID0gc2VsZi5tYXAudW5wcm9qZWN0KHB4cHkpO1xuICAgICAgICByZXR1cm4gW29iai5sbmcsIG9iai5sYXRdO1xuICAgIH1cblxuICAgIHZhciBkcmFnTW9kZSA9IGZ1bGxMYXlvdXQuZHJhZ21vZGU7XG4gICAgdmFyIGZpbGxSYW5nZUl0ZW1zO1xuXG4gICAgaWYoZHJhZ01vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgIGZpbGxSYW5nZUl0ZW1zID0gZnVuY3Rpb24oZXZlbnREYXRhLCBwb2x5KSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2VzID0gZXZlbnREYXRhLnJhbmdlID0ge307XG4gICAgICAgICAgICByYW5nZXNbc2VsZi5pZF0gPSBbXG4gICAgICAgICAgICAgICAgaW52ZXJ0KFtwb2x5LnhtaW4sIHBvbHkueW1pbl0pLFxuICAgICAgICAgICAgICAgIGludmVydChbcG9seS54bWF4LCBwb2x5LnltYXhdKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBmaWxsUmFuZ2VJdGVtcyA9IGZ1bmN0aW9uKGV2ZW50RGF0YSwgcG9seSwgcHRzKSB7XG4gICAgICAgICAgICB2YXIgZGF0YVB0cyA9IGV2ZW50RGF0YS5sYXNzb1BvaW50cyA9IHt9O1xuICAgICAgICAgICAgZGF0YVB0c1tzZWxmLmlkXSA9IHB0cy5maWx0ZXJlZC5tYXAoaW52ZXJ0KTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBOb3RlOiBkcmFnT3B0aW9ucyBpcyBuZWVkZWQgdG8gYmUgZGVjbGFyZWQgZm9yIGFsbCBkcmFnbW9kZXMgYmVjYXVzZVxuICAgIC8vIGl0J3MgdGhlIG9iamVjdCB0aGF0IGhvbGRzIHBlcnNpc3RlbnQgc2VsZWN0aW9uIHN0YXRlLlxuICAgIC8vIE1lcmdlIG9sZCBkcmFnT3B0aW9ucyB3aXRoIG5ldyB0byBrZWVwIHBvc3NpYmx5IGluaXRpYWxpemVkXG4gICAgLy8gcGVyc2lzdGVudCBzZWxlY3Rpb24gc3RhdGUuXG4gICAgdmFyIG9sZERyYWdPcHRpb25zID0gc2VsZi5kcmFnT3B0aW9ucztcbiAgICBzZWxmLmRyYWdPcHRpb25zID0gTGliLmV4dGVuZERlZXAob2xkRHJhZ09wdGlvbnMgfHwge30sIHtcbiAgICAgICAgZWxlbWVudDogc2VsZi5kaXYsXG4gICAgICAgIGdkOiBnZCxcbiAgICAgICAgcGxvdGluZm86IHtcbiAgICAgICAgICAgIGlkOiBzZWxmLmlkLFxuICAgICAgICAgICAgeGF4aXM6IHNlbGYueGF4aXMsXG4gICAgICAgICAgICB5YXhpczogc2VsZi55YXhpcyxcbiAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zOiBmaWxsUmFuZ2VJdGVtc1xuICAgICAgICB9LFxuICAgICAgICB4YXhlczogW3NlbGYueGF4aXNdLFxuICAgICAgICB5YXhlczogW3NlbGYueWF4aXNdLFxuICAgICAgICBzdWJwbG90OiBzZWxmLmlkXG4gICAgfSk7XG5cbiAgICAvLyBVbnJlZ2lzdGVyIHRoZSBvbGQgaGFuZGxlciBiZWZvcmUgcG90ZW50aWFsbHkgcmVnaXN0ZXJpbmdcbiAgICAvLyBhIG5ldyBvbmUuIE90aGVyd2lzZSBtdWx0aXBsZSBjbGljayBoYW5kbGVycyBtaWdodFxuICAgIC8vIGJlIHJlZ2lzdGVyZWQgcmVzdWx0aW5nIGluIHVud2FudGVkIGJlaGF2aW9yLlxuICAgIG1hcC5vZmYoJ2NsaWNrJywgc2VsZi5vbkNsaWNrSW5QYW5IYW5kbGVyKTtcbiAgICBpZihkcmFnTW9kZSA9PT0gJ3NlbGVjdCcgfHwgZHJhZ01vZGUgPT09ICdsYXNzbycpIHtcbiAgICAgICAgbWFwLmRyYWdQYW4uZGlzYWJsZSgpO1xuICAgICAgICBtYXAub24oJ3pvb21zdGFydCcsIHNlbGYuY2xlYXJTZWxlY3QpO1xuXG4gICAgICAgIHNlbGYuZHJhZ09wdGlvbnMucHJlcEZuID0gZnVuY3Rpb24oZSwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgICAgIHByZXBTZWxlY3QoZSwgc3RhcnRYLCBzdGFydFksIHNlbGYuZHJhZ09wdGlvbnMsIGRyYWdNb2RlKTtcbiAgICAgICAgfTtcblxuICAgICAgICBkcmFnRWxlbWVudC5pbml0KHNlbGYuZHJhZ09wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcC5kcmFnUGFuLmVuYWJsZSgpO1xuICAgICAgICBtYXAub2ZmKCd6b29tc3RhcnQnLCBzZWxmLmNsZWFyU2VsZWN0KTtcbiAgICAgICAgc2VsZi5kaXYub25tb3VzZWRvd24gPSBudWxsO1xuXG4gICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgbWFwYm94IHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgIC8vIG1hcGJveCBldmVudCBiaW5kaW5nLiBPciBwZXJoYXBzIGJldHRlciwgbWFrZSBhIHNpbXBsZSB3cmFwcGVyIHdpdGggdGhlXG4gICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgLy8gcGllIHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgc2VsZi5vbkNsaWNrSW5QYW5IYW5kbGVyID0gc2VsZi5vbkNsaWNrSW5QYW5GbihzZWxmLmRyYWdPcHRpb25zKTtcbiAgICAgICAgbWFwLm9uKCdjbGljaycsIHNlbGYub25DbGlja0luUGFuSGFuZGxlcik7XG4gICAgfVxufTtcblxucHJvdG8udXBkYXRlRnJhbWV3b3JrID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBkb21haW4gPSBmdWxsTGF5b3V0W3RoaXMuaWRdLmRvbWFpbjtcbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICB2YXIgc3R5bGUgPSB0aGlzLmRpdi5zdHlsZTtcbiAgICBzdHlsZS53aWR0aCA9IHNpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKSArICdweCc7XG4gICAgc3R5bGUuaGVpZ2h0ID0gc2l6ZS5oICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pICsgJ3B4JztcbiAgICBzdHlsZS5sZWZ0ID0gc2l6ZS5sICsgZG9tYWluLnhbMF0gKiBzaXplLncgKyAncHgnO1xuICAgIHN0eWxlLnRvcCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oICsgJ3B4JztcblxuICAgIHRoaXMueGF4aXMuX29mZnNldCA9IHNpemUubCArIGRvbWFpbi54WzBdICogc2l6ZS53O1xuICAgIHRoaXMueGF4aXMuX2xlbmd0aCA9IHNpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKTtcblxuICAgIHRoaXMueWF4aXMuX29mZnNldCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oO1xuICAgIHRoaXMueWF4aXMuX2xlbmd0aCA9IHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbn07XG5cbnByb3RvLnVwZGF0ZUxheWVycyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvcHRzID0gdGhpcy5vcHRzO1xuICAgIHZhciBsYXllcnMgPSBvcHRzLmxheWVycztcbiAgICB2YXIgbGF5ZXJMaXN0ID0gdGhpcy5sYXllckxpc3Q7XG4gICAgdmFyIGk7XG5cbiAgICAvLyBpZiB0aGUgbGF5ZXIgYXJyYXlzIGRvbid0IG1hdGNoLFxuICAgIC8vIGRvbid0IHRyeSB0byBiZSBzbWFydCxcbiAgICAvLyBkZWxldGUgdGhlbSBhbGwsIGFuZCBzdGFydCBhbGwgb3Zlci5cblxuICAgIGlmKGxheWVycy5sZW5ndGggIT09IGxheWVyTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGF5ZXJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsYXllckxpc3RbaV0uZGlzcG9zZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGF5ZXJMaXN0ID0gdGhpcy5sYXllckxpc3QgPSBbXTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsYXllcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxheWVyTGlzdC5wdXNoKGNyZWF0ZU1hcGJveExheWVyKHRoaXMsIGksIGxheWVyc1tpXSkpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsYXllckxpc3RbaV0udXBkYXRlKGxheWVyc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5tYXApIHtcbiAgICAgICAgdGhpcy5tYXAucmVtb3ZlKCk7XG4gICAgICAgIHRoaXMubWFwID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250YWluZXIucmVtb3ZlQ2hpbGQodGhpcy5kaXYpO1xuICAgIH1cbn07XG5cbnByb3RvLnRvSW1hZ2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLm1hcC5zdG9wKCk7XG4gICAgcmV0dXJuIHRoaXMubWFwLmdldENhbnZhcygpLnRvRGF0YVVSTCgpO1xufTtcblxuLy8gY29udmVuaWVuY2Ugd3JhcHBlciB0byBjcmVhdGUgc2V0IG11bHRpcGxlIGxheWVyXG4vLyAnbGF5b3V0JyBvciAncGFpbnQgb3B0aW9ucyBhdCBvbmNlLlxucHJvdG8uc2V0T3B0aW9ucyA9IGZ1bmN0aW9uKGlkLCBtZXRob2ROYW1lLCBvcHRzKSB7XG4gICAgZm9yKHZhciBrIGluIG9wdHMpIHtcbiAgICAgICAgdGhpcy5tYXBbbWV0aG9kTmFtZV0oaWQsIGssIG9wdHNba10pO1xuICAgIH1cbn07XG5cbi8vIGNvbnZlbmllbmNlIG1ldGhvZCB0byBwcm9qZWN0IGEgW2xvbiwgbGF0XSBhcnJheSB0byBwaXhlbCBjb29yZHNcbnByb3RvLnByb2plY3QgPSBmdW5jdGlvbih2KSB7XG4gICAgcmV0dXJuIHRoaXMubWFwLnByb2plY3QobmV3IG1hcGJveGdsLkxuZ0xhdCh2WzBdLCB2WzFdKSk7XG59O1xuXG4vLyBnZXQgbWFwJ3MgY3VycmVudCB2aWV3IHZhbHVlcyBpbiBwbG90bHkuanMgbm90YXRpb25cbnByb3RvLmdldFZpZXcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG5cbiAgICB2YXIgbWFwQ2VudGVyID0gbWFwLmdldENlbnRlcigpO1xuICAgIHZhciBjZW50ZXIgPSB7IGxvbjogbWFwQ2VudGVyLmxuZywgbGF0OiBtYXBDZW50ZXIubGF0IH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjZW50ZXI6IGNlbnRlcixcbiAgICAgICAgem9vbTogbWFwLmdldFpvb20oKSxcbiAgICAgICAgYmVhcmluZzogbWFwLmdldEJlYXJpbmcoKSxcbiAgICAgICAgcGl0Y2g6IG1hcC5nZXRQaXRjaCgpXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIGdldFN0eWxlT2JqKHZhbCkge1xuICAgIHZhciBzdHlsZVZhbHVlcyA9IGxheW91dEF0dHJpYnV0ZXMuc3R5bGUudmFsdWVzO1xuICAgIHZhciBzdHlsZURmbHQgPSBsYXlvdXRBdHRyaWJ1dGVzLnN0eWxlLmRmbHQ7XG4gICAgdmFyIHN0eWxlT2JqID0ge307XG5cbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdCh2YWwpKSB7XG4gICAgICAgIHN0eWxlT2JqLmlkID0gdmFsLmlkO1xuICAgICAgICBzdHlsZU9iai5zdHlsZSA9IHZhbDtcbiAgICB9IGVsc2UgaWYodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc3R5bGVPYmouaWQgPSB2YWw7XG4gICAgICAgIHN0eWxlT2JqLnN0eWxlID0gKHN0eWxlVmFsdWVzLmluZGV4T2YodmFsKSAhPT0gLTEpID9cbiAgICAgICAgICAgICBjb252ZXJ0U3R5bGVWYWwodmFsKSA6XG4gICAgICAgICAgICAgdmFsO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlT2JqLmlkID0gc3R5bGVEZmx0O1xuICAgICAgICBzdHlsZU9iai5zdHlsZSA9IGNvbnZlcnRTdHlsZVZhbChzdHlsZURmbHQpO1xuICAgIH1cblxuICAgIHN0eWxlT2JqLnRyYW5zaXRpb24gPSB7ZHVyYXRpb246IDAsIGRlbGF5OiAwfTtcblxuICAgIHJldHVybiBzdHlsZU9iajtcbn1cblxuLy8gaWYgc3R5bGUgaXMgcGFydCBvZiB0aGUgJ29mZmljaWFsJyBtYXBib3ggdmFsdWVzLCBhZGQgVVJMIHByZWZpeCBhbmQgc3VmZml4XG5mdW5jdGlvbiBjb252ZXJ0U3R5bGVWYWwodmFsKSB7XG4gICAgcmV0dXJuIGNvbnN0YW50cy5zdHlsZVVybFByZWZpeCArIHZhbCArICctJyArIGNvbnN0YW50cy5zdHlsZVVybFN1ZmZpeDtcbn1cblxuZnVuY3Rpb24gY29udmVydENlbnRlcihjZW50ZXIpIHtcbiAgICByZXR1cm4gW2NlbnRlci5sb24sIGNlbnRlci5sYXRdO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBUaGlzIGlzIHVzZWQgZXhjbHVzaXZlbHkgYnkgY29tcG9uZW50cyBpbnNpZGUgY29tcG9uZW50IGFycmF5cyxcbi8vIGhlbmNlIHRoZSAnYXJyYXlkcmF3JyBlZGl0VHlwZS4gSWYgdGhpcyBldmVyIGdldHMgdXNlZCBlbHNld2hlcmVcbi8vIHdlIGNvdWxkIGdlbmVyYWxpemUgaXQgYXMgYSBmdW5jdGlvbiBhbGEgZm9udF9hdHRyaWJ1dGVzXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHI6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3J1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uL3JlZ2lzdHJ5Jyk7XG52YXIgUGxvdFNjaGVtYSA9IHJlcXVpcmUoJy4uL3Bsb3RfYXBpL3Bsb3Rfc2NoZW1hJyk7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIGF4aXNJRHMgPSByZXF1aXJlKCcuLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcblxudmFyIGFuaW1hdGlvbkF0dHJzID0gcmVxdWlyZSgnLi9hbmltYXRpb25fYXR0cmlidXRlcycpO1xudmFyIGZyYW1lQXR0cnMgPSByZXF1aXJlKCcuL2ZyYW1lX2F0dHJpYnV0ZXMnKTtcblxudmFyIHJlbGlua1ByaXZhdGVLZXlzID0gTGliLnJlbGlua1ByaXZhdGVLZXlzO1xudmFyIF8gPSBMaWIuXztcblxudmFyIHBsb3RzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gRXhwb3NlIHJlZ2lzdHJ5IG1ldGhvZHMgb24gUGxvdHMgZm9yIGJhY2t3YXJkLWNvbXBhdGliaWxpdHlcbkxpYi5leHRlbmRGbGF0KHBsb3RzLCBSZWdpc3RyeSk7XG5cbnBsb3RzLmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnBsb3RzLmF0dHJpYnV0ZXMudHlwZS52YWx1ZXMgPSBwbG90cy5hbGxUeXBlcztcbnBsb3RzLmZvbnRBdHRycyA9IHJlcXVpcmUoJy4vZm9udF9hdHRyaWJ1dGVzJyk7XG5wbG90cy5sYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG4vLyBUT0RPIG1ha2UgdGhpcyBhIHBsb3QgYXR0cmlidXRlP1xucGxvdHMuZm9udFdlaWdodCA9ICdub3JtYWwnO1xuXG52YXIgdHJhbnNmb3Jtc1JlZ2lzdHJ5ID0gcGxvdHMudHJhbnNmb3Jtc1JlZ2lzdHJ5O1xuXG52YXIgY29tbWFuZE1vZHVsZSA9IHJlcXVpcmUoJy4vY29tbWFuZCcpO1xucGxvdHMuZXhlY3V0ZUFQSUNvbW1hbmQgPSBjb21tYW5kTW9kdWxlLmV4ZWN1dGVBUElDb21tYW5kO1xucGxvdHMuY29tcHV0ZUFQSUNvbW1hbmRCaW5kaW5ncyA9IGNvbW1hbmRNb2R1bGUuY29tcHV0ZUFQSUNvbW1hbmRCaW5kaW5ncztcbnBsb3RzLm1hbmFnZUNvbW1hbmRPYnNlcnZlciA9IGNvbW1hbmRNb2R1bGUubWFuYWdlQ29tbWFuZE9ic2VydmVyO1xucGxvdHMuaGFzU2ltcGxlQVBJQ29tbWFuZEJpbmRpbmdzID0gY29tbWFuZE1vZHVsZS5oYXNTaW1wbGVBUElDb21tYW5kQmluZGluZ3M7XG5cbi8vIGluIHNvbWUgY2FzZXMgdGhlIGJyb3dzZXIgZG9lc24ndCBzZWVtIHRvIGtub3cgaG93IGJpZ1xuLy8gdGhlIHRleHQgaXMgYXQgZmlyc3QsIHNvIGl0IG5lZWRzIHRvIGRyYXcgaXQsXG4vLyB0aGVuIHdhaXQgYSBsaXR0bGUsIHRoZW4gZHJhdyBpdCBhZ2FpblxucGxvdHMucmVkcmF3VGV4dCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgLy8gZG8gbm90IHdvcmsgaWYgcG9sYXIgaXMgcHJlc2VudFxuICAgIGlmKChnZC5kYXRhICYmIGdkLmRhdGFbMF0gJiYgZ2QuZGF0YVswXS5yKSkgcmV0dXJuO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhdycpKGdkKTtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnbGVnZW5kJywgJ2RyYXcnKShnZCk7XG5cbiAgICAgICAgICAgIChnZC5jYWxjZGF0YSB8fCBbXSkuZm9yRWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgaWYoZFswXSAmJiBkWzBdLnQgJiYgZFswXS50LmNiKSBkWzBdLnQuY2IoKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXNvbHZlKHBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpKTtcbiAgICAgICAgfSwgMzAwKTtcbiAgICB9KTtcbn07XG5cbi8vIHJlc2l6ZSBwbG90IGFib3V0IHRoZSBjb250YWluZXIgc2l6ZVxucGxvdHMucmVzaXplID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cbiAgICAgICAgZnVuY3Rpb24gaXNIaWRkZW4oZ2QpIHtcbiAgICAgICAgICAgIHZhciBkaXNwbGF5ID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZ2QpLmRpc3BsYXk7XG4gICAgICAgICAgICByZXR1cm4gIWRpc3BsYXkgfHwgZGlzcGxheSA9PT0gJ25vbmUnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWdkIHx8IGlzSGlkZGVuKGdkKSkge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUmVzaXplIG11c3QgYmUgcGFzc2VkIGEgZGlzcGxheWVkIHBsb3QgZGl2IGVsZW1lbnQuJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZ2QuX3JlZHJhd1RpbWVyKSBjbGVhclRpbWVvdXQoZ2QuX3JlZHJhd1RpbWVyKTtcblxuICAgICAgICBnZC5fcmVkcmF3VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgLy8gcmV0dXJuIGlmIHRoZXJlIGlzIG5vdGhpbmcgdG8gcmVzaXplIG9yIGlzIGhpZGRlblxuICAgICAgICAgICAgaWYoIWdkLmxheW91dCB8fCAoZ2QubGF5b3V0LndpZHRoICYmIGdkLmxheW91dC5oZWlnaHQpIHx8IGlzSGlkZGVuKGdkKSkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZ2QpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGdkLmxheW91dC53aWR0aDtcbiAgICAgICAgICAgIGRlbGV0ZSBnZC5sYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgICAgICAvLyBhdXRvc2l6aW5nIGRvZXNuJ3QgY291bnQgYXMgYSBjaGFuZ2UgdGhhdCBuZWVkcyBzYXZpbmdcbiAgICAgICAgICAgIHZhciBvbGRjaGFuZ2VkID0gZ2QuY2hhbmdlZDtcblxuICAgICAgICAgICAgLy8gbm9yIHNob3VsZCBpdCBiZSBpbmNsdWRlZCBpbiB0aGUgdW5kbyBxdWV1ZVxuICAgICAgICAgICAgZ2QuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCB7YXV0b3NpemU6IHRydWV9KS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGdkLmNoYW5nZWQgPSBvbGRjaGFuZ2VkO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZ2QpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgfSk7XG59O1xuXG5cbi8vIGZvciB1c2UgaW4gTGliLnN5bmNPckFzeW5jLCBjaGVjayBpZiB0aGVyZSBhcmUgYW55XG4vLyBwZW5kaW5nIHByb21pc2VzIGluIHRoaXMgcGxvdCBhbmQgd2FpdCBmb3IgdGhlbVxucGxvdHMucHJldmlvdXNQcm9taXNlcyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoKGdkLl9wcm9taXNlcyB8fCBbXSkubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChnZC5fcHJvbWlzZXMpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbigpIHsgZ2QuX3Byb21pc2VzID0gW107IH0pO1xuICAgIH1cbn07XG5cbi8qKlxuICogQWRkcyB0aGUgJ0VkaXQgY2hhcnQnIGxpbmsuXG4gKiBOb3RlIHRoYXQgbm93IFBsb3RseS5wbG90KCkgY2FsbHMgdGhpcyBzbyBpdCBjYW4gcmVnZW5lcmF0ZSB3aGVuZXZlciBpdCByZXBsb3RzXG4gKlxuICogQWRkIHNvdXJjZSBsaW5rcyB0byB5b3VyIGdyYXBoIGluc2lkZSB0aGUgJ3Nob3dTb3VyY2VzJyBjb25maWcgYXJndW1lbnQuXG4gKi9cbnBsb3RzLmFkZExpbmtzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICAvLyBEbyBub3QgZG8gYW55dGhpbmcgaWYgc2hvd0xpbmsgYW5kIHNob3dTb3VyY2VzIGFyZSBub3Qgc2V0IHRvIHRydWUgaW4gY29uZmlnXG4gICAgaWYoIWdkLl9jb250ZXh0LnNob3dMaW5rICYmICFnZC5fY29udGV4dC5zaG93U291cmNlcykgcmV0dXJuO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBsaW5rQ29udGFpbmVyID0gTGliLmVuc3VyZVNpbmdsZShmdWxsTGF5b3V0Ll9wYXBlciwgJ3RleHQnLCAnanMtcGxvdC1saW5rLWNvbnRhaW5lcicsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5zdHlsZSh7XG4gICAgICAgICAgICAnZm9udC1mYW1pbHknOiAnXCJPcGVuIFNhbnNcIiwgQXJpYWwsIHNhbnMtc2VyaWYnLFxuICAgICAgICAgICAgJ2ZvbnQtc2l6ZSc6ICcxMnB4JyxcbiAgICAgICAgICAgICdmaWxsJzogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnYWxsJ1xuICAgICAgICB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBsaW5rcyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIGxpbmtzLmFwcGVuZCgndHNwYW4nKS5jbGFzc2VkKCdqcy1saW5rLXRvLXRvb2wnLCB0cnVlKTtcbiAgICAgICAgICAgIGxpbmtzLmFwcGVuZCgndHNwYW4nKS5jbGFzc2VkKCdqcy1saW5rLXNwYWNlcicsIHRydWUpO1xuICAgICAgICAgICAgbGlua3MuYXBwZW5kKCd0c3BhbicpLmNsYXNzZWQoJ2pzLXNvdXJjZWxpbmtzJywgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gVGhlIHRleHQgbm9kZSBpbnNpZGUgc3ZnXG4gICAgdmFyIHRleHQgPSBsaW5rQ29udGFpbmVyLm5vZGUoKTtcbiAgICB2YXIgYXR0cnMgPSB7eTogZnVsbExheW91dC5fcGFwZXIuYXR0cignaGVpZ2h0JykgLSA5fTtcblxuICAgIC8vIElmIHRleHQncyB3aWR0aCBpcyBiaWdnZXIgdGhhbiB0aGUgbGF5b3V0XG4gICAgLy8gQ2hlY2sgdGhhdCB0ZXh0IGlzIGEgY2hpbGQgbm9kZSBvciBkb2N1bWVudC5ib2R5XG4gICAgLy8gYmVjYXVzZSBvdGhlcndpc2UgSUUvRWRnZSBtaWdodCB0aHJvdyBhbiBleGNlcHRpb25cbiAgICAvLyB3aGVuIGNhbGxpbmcgZ2V0Q29tcHV0ZWRUZXh0TGVuZ3RoKCkuXG4gICAgLy8gQXBwYXJlbnRseSBvZmZzZXRQYXJlbnQgaXMgbnVsbCBmb3IgaW52aXNpYmxlcy5cbiAgICBpZihkb2N1bWVudC5ib2R5LmNvbnRhaW5zKHRleHQpICYmIHRleHQuZ2V0Q29tcHV0ZWRUZXh0TGVuZ3RoKCkgPj0gKGZ1bGxMYXlvdXQud2lkdGggLSAyMCkpIHtcbiAgICAgICAgLy8gQWxpZ24gdGhlIHRleHQgYXQgdGhlIGxlZnRcbiAgICAgICAgYXR0cnNbJ3RleHQtYW5jaG9yJ10gPSAnc3RhcnQnO1xuICAgICAgICBhdHRycy54ID0gNTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIEFsaWduIHRoZSB0ZXh0IGF0IHRoZSByaWdodFxuICAgICAgICBhdHRyc1sndGV4dC1hbmNob3InXSA9ICdlbmQnO1xuICAgICAgICBhdHRycy54ID0gZnVsbExheW91dC5fcGFwZXIuYXR0cignd2lkdGgnKSAtIDc7XG4gICAgfVxuXG4gICAgbGlua0NvbnRhaW5lci5hdHRyKGF0dHJzKTtcblxuICAgIHZhciB0b29sc3BhbiA9IGxpbmtDb250YWluZXIuc2VsZWN0KCcuanMtbGluay10by10b29sJyksXG4gICAgICAgIHNwYWNlc3BhbiA9IGxpbmtDb250YWluZXIuc2VsZWN0KCcuanMtbGluay1zcGFjZXInKSxcbiAgICAgICAgc291cmNlc3BhbiA9IGxpbmtDb250YWluZXIuc2VsZWN0KCcuanMtc291cmNlbGlua3MnKTtcblxuICAgIGlmKGdkLl9jb250ZXh0LnNob3dTb3VyY2VzKSBnZC5fY29udGV4dC5zaG93U291cmNlcyhnZCk7XG5cbiAgICAvLyAndmlldyBpbiBwbG90bHknIGxpbmsgZm9yIGVtYmVkZGVkIHBsb3RzXG4gICAgaWYoZ2QuX2NvbnRleHQuc2hvd0xpbmspIHBvc2l0aW9uUGxheVdpdGhEYXRhKGdkLCB0b29sc3Bhbik7XG5cbiAgICAvLyBzZXBhcmF0b3IgaWYgd2UgaGF2ZSBib3RoIHNvdXJjZXMgYW5kIHRvb2wgbGlua1xuICAgIHNwYWNlc3Bhbi50ZXh0KCh0b29sc3Bhbi50ZXh0KCkgJiYgc291cmNlc3Bhbi50ZXh0KCkpID8gJyAtICcgOiAnJyk7XG59O1xuXG4vLyBub3RlIHRoYXQgbm93IHRoaXMgZnVuY3Rpb24gaXMgb25seSBhZGRpbmcgdGhlIGJyYW5kIGluXG4vLyBpZnJhbWVzIGFuZCAzcmQtcGFydHkgYXBwc1xuZnVuY3Rpb24gcG9zaXRpb25QbGF5V2l0aERhdGEoZ2QsIGNvbnRhaW5lcikge1xuICAgIGNvbnRhaW5lci50ZXh0KCcnKTtcbiAgICB2YXIgbGluayA9IGNvbnRhaW5lci5hcHBlbmQoJ2EnKVxuICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAneGxpbms6eGxpbms6aHJlZic6ICcjJyxcbiAgICAgICAgICAgICdjbGFzcyc6ICdsaW5rLS1pbXB0IGxpbmstLWVtYmVkdmlldycsXG4gICAgICAgICAgICAnZm9udC13ZWlnaHQnOiAnYm9sZCdcbiAgICAgICAgfSlcbiAgICAgICAgLnRleHQoZ2QuX2NvbnRleHQubGlua1RleHQgKyAnICcgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKDE4NykpO1xuXG4gICAgaWYoZ2QuX2NvbnRleHQuc2VuZERhdGEpIHtcbiAgICAgICAgbGluay5vbignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHBsb3RzLnNlbmREYXRhVG9DbG91ZChnZCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUuc3BsaXQoJy8nKTtcbiAgICAgICAgdmFyIHF1ZXJ5ID0gd2luZG93LmxvY2F0aW9uLnNlYXJjaDtcbiAgICAgICAgbGluay5hdHRyKHtcbiAgICAgICAgICAgICd4bGluazp4bGluazpzaG93JzogJ25ldycsXG4gICAgICAgICAgICAneGxpbms6eGxpbms6aHJlZic6ICcvJyArIHBhdGhbMl0uc3BsaXQoJy4nKVswXSArICcvJyArIHBhdGhbMV0gKyBxdWVyeVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbnBsb3RzLnNlbmREYXRhVG9DbG91ZCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QuZW1pdCgncGxvdGx5X2JlZm9yZWV4cG9ydCcpO1xuXG4gICAgdmFyIGJhc2VVcmwgPSAod2luZG93LlBMT1RMWUVOViB8fCB7fSkuQkFTRV9VUkwgfHwgZ2QuX2NvbnRleHQucGxvdGx5U2VydmVyVVJMO1xuXG4gICAgdmFyIGhpZGRlbmZvcm1EaXYgPSBkMy5zZWxlY3QoZ2QpXG4gICAgICAgIC5hcHBlbmQoJ2RpdicpXG4gICAgICAgIC5hdHRyKCdpZCcsICdoaWRkZW5mb3JtJylcbiAgICAgICAgLnN0eWxlKCdkaXNwbGF5JywgJ25vbmUnKTtcblxuICAgIHZhciBoaWRkZW5mb3JtID0gaGlkZGVuZm9ybURpdlxuICAgICAgICAuYXBwZW5kKCdmb3JtJylcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgYWN0aW9uOiBiYXNlVXJsICsgJy9leHRlcm5hbCcsXG4gICAgICAgICAgICBtZXRob2Q6ICdwb3N0JyxcbiAgICAgICAgICAgIHRhcmdldDogJ19ibGFuaydcbiAgICAgICAgfSk7XG5cbiAgICB2YXIgaGlkZGVuZm9ybUlucHV0ID0gaGlkZGVuZm9ybVxuICAgICAgICAuYXBwZW5kKCdpbnB1dCcpXG4gICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgICAgIG5hbWU6ICdkYXRhJ1xuICAgICAgICB9KTtcblxuICAgIGhpZGRlbmZvcm1JbnB1dC5ub2RlKCkudmFsdWUgPSBwbG90cy5ncmFwaEpzb24oZ2QsIGZhbHNlLCAna2VlcGRhdGEnKTtcbiAgICBoaWRkZW5mb3JtLm5vZGUoKS5zdWJtaXQoKTtcbiAgICBoaWRkZW5mb3JtRGl2LnJlbW92ZSgpO1xuXG4gICAgZ2QuZW1pdCgncGxvdGx5X2FmdGVyZXhwb3J0Jyk7XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxudmFyIGQzRm9ybWF0S2V5cyA9IFtcbiAgICAnZGF5cycsICdzaG9ydERheXMnLCAnbW9udGhzJywgJ3Nob3J0TW9udGhzJywgJ3BlcmlvZHMnLFxuICAgICdkYXRlVGltZScsICdkYXRlJywgJ3RpbWUnLFxuICAgICdkZWNpbWFsJywgJ3Rob3VzYW5kcycsICdncm91cGluZycsICdjdXJyZW5jeSdcbl07XG5cbnZhciBleHRyYUZvcm1hdEtleXMgPSBbXG4gICAgJ3llYXInLCAnbW9udGgnLCAnZGF5TW9udGgnLCAnZGF5TW9udGhZZWFyJ1xuXTtcblxuLypcbiAqIEZpbGwgaW4gZGVmYXVsdCB2YWx1ZXNcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICogQHBhcmFtIHtib29sZWFufSBvcHRzLnNraXBVcGRhdGVDYWxjOiBub3JtYWxseSBpZiB0aGUgZXhpc3RpbmcgZ2QuY2FsY2RhdGEgbG9va3NcbiAqICAgY29tcGF0aWJsZSB3aXRoIHRoZSBuZXcgZ2QuX2Z1bGxEYXRhIHdlIGZpbmlzaCBieSBsaW5raW5nIHRoZSBuZXcgX2Z1bGxEYXRhIHRyYWNlc1xuICogICB0byB0aGUgb2xkIGdkLmNhbGNkYXRhLCBzbyBpdCdzIGNvcnJlY3RseSBzZXQgaWYgd2UncmUgbm90IGdvaW5nIHRvIHJlY2FsYy4gQnV0IGFsc28sXG4gKiAgIGlmIHRoZXJlIGFyZSBjYWxjVHJhbnNmb3JtcyBvbiB0aGUgdHJhY2UsIHdlIGZpcnN0IHJlbWFwIGRhdGEgYXJyYXlzIGZyb20gdGhlIG9sZCBmdWxsXG4gKiAgIHRyYWNlIGludG8gdGhlIG5ldyBvbmUuIFVzZSBza2lwVXBkYXRlQ2FsYyB0byBkZWZlciB0aGlzIChuZWVkZWQgYnkgUGxvdGx5LnJlYWN0KVxuICpcbiAqIGdkLmRhdGEsIGdkLmxheW91dDpcbiAqICAgYXJlIHByZWNpc2VseSB3aGF0IHRoZSB1c2VyIHNwZWNpZmllZCAoZXhjZXB0IGFzIG1vZGlmaWVkIGJ5IGNsZWFuRGF0YS9jbGVhbkxheW91dCksXG4gKiAgIHRoZXNlIGZpZWxkcyBzaG91bGRuJ3QgYmUgbW9kaWZpZWQgKGV4Y2VwdCBmb3IgZmlsbGluZyBpbiBzb21lIGF1dG8gdmFsdWVzKVxuICogICBub3IgdXNlZCBkaXJlY3RseSBhZnRlciB0aGUgc3VwcGx5IGRlZmF1bHRzIHN0ZXAuXG4gKlxuICogZ2QuX2Z1bGxEYXRhLCBnZC5fZnVsbExheW91dDpcbiAqICAgYXJlIGNvbXBsZXRlIGRlc2NyaXB0aW9ucyBvZiBob3cgdG8gZHJhdyB0aGUgcGxvdCxcbiAqICAgdXNlIHRoZXNlIGZpZWxkcyBpbiBhbGwgcmVxdWlyZWQgY29tcHV0YXRpb25zLlxuICpcbiAqIGdkLl9mdWxsTGF5b3V0Ll9tb2R1bGVzXG4gKiAgIGlzIGEgbGlzdCBvZiBhbGwgdGhlIHRyYWNlIG1vZHVsZXMgcmVxdWlyZWQgdG8gZHJhdyB0aGUgcGxvdC5cbiAqXG4gKiBnZC5fZnVsbExheW91dC5fdmlzaWJsZU1vZHVsZXNcbiAqICAgc3Vic2V0IG9mIF9tb2R1bGVzLCBhIGxpc3Qgb2YgbW9kdWxlcyBjb3JyZXNwb25kaW5nIHRvIHZpc2libGU6dHJ1ZSB0cmFjZXMuXG4gKlxuICogZ2QuX2Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlc1xuICogICBpcyBhIGxpc3Qgb2YgYWxsIHRoZSBwbG90IG1vZHVsZXMgcmVxdWlyZWQgdG8gZHJhdyB0aGUgcGxvdC5cbiAqXG4gKiBnZC5fZnVsbExheW91dC5fdHJhbnNmb3JtTW9kdWxlc1xuICogICBpcyBhIGxpc3Qgb2YgYWxsIHRoZSB0cmFuc2Zvcm0gbW9kdWxlcyBpbnZva2VkLlxuICpcbiAqL1xucGxvdHMuc3VwcGx5RGVmYXVsdHMgPSBmdW5jdGlvbihnZCwgb3B0cykge1xuICAgIHZhciBza2lwVXBkYXRlQ2FsYyA9IG9wdHMgJiYgb3B0cy5za2lwVXBkYXRlQ2FsYztcbiAgICB2YXIgb2xkRnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0IHx8IHt9O1xuXG4gICAgaWYob2xkRnVsbExheW91dC5fc2tpcERlZmF1bHRzKSB7XG4gICAgICAgIGRlbGV0ZSBvbGRGdWxsTGF5b3V0Ll9za2lwRGVmYXVsdHM7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbmV3RnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0ID0ge307XG4gICAgdmFyIG5ld0xheW91dCA9IGdkLmxheW91dCB8fCB7fTtcblxuICAgIHZhciBvbGRGdWxsRGF0YSA9IGdkLl9mdWxsRGF0YSB8fCBbXTtcbiAgICB2YXIgbmV3RnVsbERhdGEgPSBnZC5fZnVsbERhdGEgPSBbXTtcbiAgICB2YXIgbmV3RGF0YSA9IGdkLmRhdGEgfHwgW107XG5cbiAgICB2YXIgb2xkQ2FsY2RhdGEgPSBnZC5jYWxjZGF0YSB8fCBbXTtcblxuICAgIHZhciBjb250ZXh0ID0gZ2QuX2NvbnRleHQgfHwge307XG5cbiAgICB2YXIgaTtcblxuICAgIC8vIENyZWF0ZSBhbGwgdGhlIHN0b3JhZ2Ugc3BhY2UgZm9yIGZyYW1lcywgYnV0IG9ubHkgaWYgZG9lc24ndCBhbHJlYWR5IGV4aXN0XG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YSkgcGxvdHMuY3JlYXRlVHJhbnNpdGlvbkRhdGEoZ2QpO1xuXG4gICAgLy8gU28gd2Ugb25seSBuZWVkIHRvIGRvIHRoaXMgb25jZSAoYW5kIHNpbmNlIHdlIGhhdmUgZ2QgaGVyZSlcbiAgICAvLyBnZXQgdGhlIHRyYW5zbGF0ZWQgcGxhY2Vob2xkZXIgdGl0bGVzLlxuICAgIC8vIFRoZXNlIG9uZXMgZ2V0IHVzZWQgYXMgZGVmYXVsdCB2YWx1ZXMgc28gbmVlZCB0byBiZSBrbm93biBhdCBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIG90aGVycyBrZWVwIHRoZWlyIGJsYW5rIGRlZmF1bHRzIGJ1dCByZW5kZXIgdGhlIHBsYWNlaG9sZGVyIGFzIGRlc2lyZWQgbGF0ZXJcbiAgICAvLyBUT0RPOiBtYWtlIHRoZXNlIHdvcmsgdGhlIHNhbWUgd2F5LCBvbmx5IGluc2VydGluZyB0aGUgcGxhY2Vob2xkZXIgdGV4dCBhdCBkcmF3IHRpbWU/XG4gICAgLy8gVGhlIGNoYWxsZW5nZSBpcyB0aGF0IHRoaXMgaGFzIHNsaWdodGx5IGRpZmZlcmVudCBiZWhhdmlvciByaWdodCBub3cgaW4gZWRpdGFibGUgbW9kZTpcbiAgICAvLyB1c2luZyB0aGUgcGxhY2Vob2xkZXIgYXMgZGVmYXVsdCBtYWtlcyB0aGlzIHRleHQgcGVybWFuZW50bHkgKGJ1dCBsaWdodGx5KSB2aXNpYmxlLFxuICAgIC8vIGJ1dCBleHBsaWNpdCAnJyBmb3IgdGhlc2UgdGl0bGVzIGdpdmVzIHlvdSBhIHBsYWNlaG9sZGVyIHRoYXQncyBoaWRkZW4gdW50aWwgeW91IG1vdXNlXG4gICAgLy8gb3ZlciBpdCAtIHNvIHlvdSdyZSBub3QgZGlzdHJhY3RlZCBieSBpdCBpZiB5b3UgcmVhbGx5IGRvbid0IHdhbnQgYSB0aXRsZSwgYnV0IGlmIHlvdSBkb1xuICAgIC8vIGFuZCB5b3UncmUgbmV3IHRvIHBsb3RseSB5b3UgbWF5IG5vdCBiZSBhYmxlIHRvIGZpbmQgaXQuXG4gICAgLy8gV2hlbiBlZGl0YWJsZT1mYWxzZSB0aGUgdHdvIGJlaGF2ZSB0aGUgc2FtZSwgbm8gdGl0bGUgaXMgZHJhd24uXG4gICAgbmV3RnVsbExheW91dC5fZGZsdFRpdGxlID0ge1xuICAgICAgICBwbG90OiBfKGdkLCAnQ2xpY2sgdG8gZW50ZXIgUGxvdCB0aXRsZScpLFxuICAgICAgICB4OiBfKGdkLCAnQ2xpY2sgdG8gZW50ZXIgWCBheGlzIHRpdGxlJyksXG4gICAgICAgIHk6IF8oZ2QsICdDbGljayB0byBlbnRlciBZIGF4aXMgdGl0bGUnKSxcbiAgICAgICAgY29sb3JiYXI6IF8oZ2QsICdDbGljayB0byBlbnRlciBDb2xvcnNjYWxlIHRpdGxlJyksXG4gICAgICAgIGFubm90YXRpb246IF8oZ2QsICduZXcgdGV4dCcpXG4gICAgfTtcbiAgICBuZXdGdWxsTGF5b3V0Ll90cmFjZVdvcmQgPSBfKGdkLCAndHJhY2UnKTtcblxuICAgIHZhciBmb3JtYXRPYmogPSBnZXRGb3JtYXRPYmooZ2QsIGQzRm9ybWF0S2V5cyk7XG5cbiAgICAvLyBzdGFzaCB0aGUgdG9rZW4gZnJvbSBjb250ZXh0IHNvIG1hcGJveCBzdWJwbG90cyBjYW4gdXNlIGl0IGFzIGRlZmF1bHRcbiAgICBuZXdGdWxsTGF5b3V0Ll9tYXBib3hBY2Nlc3NUb2tlbiA9IGNvbnRleHQubWFwYm94QWNjZXNzVG9rZW47XG5cbiAgICAvLyBmaXJzdCBmaWxsIGluIHdoYXQgd2UgY2FuIG9mIGxheW91dCB3aXRob3V0IGxvb2tpbmcgYXQgZGF0YVxuICAgIC8vIGJlY2F1c2UgZnVsbERhdGEgbmVlZHMgYSBmZXcgdGhpbmdzIGZyb20gbGF5b3V0XG4gICAgaWYob2xkRnVsbExheW91dC5faW5pdGlhbEF1dG9TaXplSXNEb25lKSB7XG5cbiAgICAgICAgLy8gY29lcmNlIHRoZSB1cGRhdGVkIGxheW91dCB3aGlsZSBwcmVzZXJ2aW5nIHdpZHRoIGFuZCBoZWlnaHRcbiAgICAgICAgdmFyIG9sZFdpZHRoID0gb2xkRnVsbExheW91dC53aWR0aCxcbiAgICAgICAgICAgIG9sZEhlaWdodCA9IG9sZEZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgIHBsb3RzLnN1cHBseUxheW91dEdsb2JhbERlZmF1bHRzKG5ld0xheW91dCwgbmV3RnVsbExheW91dCwgZm9ybWF0T2JqKTtcblxuICAgICAgICBpZighbmV3TGF5b3V0LndpZHRoKSBuZXdGdWxsTGF5b3V0LndpZHRoID0gb2xkV2lkdGg7XG4gICAgICAgIGlmKCFuZXdMYXlvdXQuaGVpZ2h0KSBuZXdGdWxsTGF5b3V0LmhlaWdodCA9IG9sZEhlaWdodDtcbiAgICAgICAgcGxvdHMuc2FuaXRpemVNYXJnaW5zKG5ld0Z1bGxMYXlvdXQpO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICAvLyBjb2VyY2UgdGhlIHVwZGF0ZWQgbGF5b3V0IGFuZCBhdXRvc2l6ZSBpZiBuZWVkZWRcbiAgICAgICAgcGxvdHMuc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHMobmV3TGF5b3V0LCBuZXdGdWxsTGF5b3V0LCBmb3JtYXRPYmopO1xuXG4gICAgICAgIHZhciBtaXNzaW5nV2lkdGhPckhlaWdodCA9ICghbmV3TGF5b3V0LndpZHRoIHx8ICFuZXdMYXlvdXQuaGVpZ2h0KSxcbiAgICAgICAgICAgIGF1dG9zaXplID0gbmV3RnVsbExheW91dC5hdXRvc2l6ZSxcbiAgICAgICAgICAgIGF1dG9zaXphYmxlID0gY29udGV4dC5hdXRvc2l6YWJsZSxcbiAgICAgICAgICAgIGluaXRpYWxBdXRvU2l6ZSA9IG1pc3NpbmdXaWR0aE9ySGVpZ2h0ICYmIChhdXRvc2l6ZSB8fCBhdXRvc2l6YWJsZSk7XG5cbiAgICAgICAgaWYoaW5pdGlhbEF1dG9TaXplKSBwbG90cy5wbG90QXV0b1NpemUoZ2QsIG5ld0xheW91dCwgbmV3RnVsbExheW91dCk7XG4gICAgICAgIGVsc2UgaWYobWlzc2luZ1dpZHRoT3JIZWlnaHQpIHBsb3RzLnNhbml0aXplTWFyZ2lucyhuZXdGdWxsTGF5b3V0KTtcblxuICAgICAgICAvLyBmb3IgYmFja3dhcmRzLWNvbXBhdGliaWxpdHkgd2l0aCBQbG90bHkgdjEueC54XG4gICAgICAgIGlmKCFhdXRvc2l6ZSAmJiBtaXNzaW5nV2lkdGhPckhlaWdodCkge1xuICAgICAgICAgICAgbmV3TGF5b3V0LndpZHRoID0gbmV3RnVsbExheW91dC53aWR0aDtcbiAgICAgICAgICAgIG5ld0xheW91dC5oZWlnaHQgPSBuZXdGdWxsTGF5b3V0LmhlaWdodDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5ld0Z1bGxMYXlvdXQuX2QzbG9jYWxlID0gZ2V0Rm9ybWF0dGVyKGZvcm1hdE9iaiwgbmV3RnVsbExheW91dC5zZXBhcmF0b3JzKTtcbiAgICBuZXdGdWxsTGF5b3V0Ll9leHRyYUZvcm1hdCA9IGdldEZvcm1hdE9iaihnZCwgZXh0cmFGb3JtYXRLZXlzKTtcblxuICAgIG5ld0Z1bGxMYXlvdXQuX2luaXRpYWxBdXRvU2l6ZUlzRG9uZSA9IHRydWU7XG5cbiAgICAvLyBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRyYWNlcyBhcmUgaW5wdXR0ZWRcbiAgICBuZXdGdWxsTGF5b3V0Ll9kYXRhTGVuZ3RoID0gbmV3RGF0YS5sZW5ndGg7XG5cbiAgICAvLyBjbGVhciB0aGUgbGlzdHMgb2YgdHJhY2UgYW5kIGJhc2VwbG90IG1vZHVsZXMsIGFuZCBzdWJwbG90c1xuICAgIG5ld0Z1bGxMYXlvdXQuX21vZHVsZXMgPSBbXTtcbiAgICBuZXdGdWxsTGF5b3V0Ll92aXNpYmxlTW9kdWxlcyA9IFtdO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcyA9IFtdO1xuICAgIHZhciBzdWJwbG90cyA9IG5ld0Z1bGxMYXlvdXQuX3N1YnBsb3RzID0gZW1wdHlTdWJwbG90TGlzdHMoKTtcblxuICAgIC8vIGluaXRpYWxpemUgYXhpcyBhbmQgc3VicGxvdCBoYXNoIG9iamVjdHMgZm9yIHNwbG9tLWdlbmVyYXRlZCBncmlkc1xuICAgIHZhciBzcGxvbUF4ZXMgPSBuZXdGdWxsTGF5b3V0Ll9zcGxvbUF4ZXMgPSB7eDoge30sIHk6IHt9fTtcbiAgICB2YXIgc3Bsb21TdWJwbG90cyA9IG5ld0Z1bGxMYXlvdXQuX3NwbG9tU3VicGxvdHMgPSB7fTtcbiAgICAvLyBpbml0aWFsaXplIHNwbG9tIGdyaWQgZGVmYXVsdHNcbiAgICBuZXdGdWxsTGF5b3V0Ll9zcGxvbUdyaWREZmx0ID0ge307XG5cbiAgICAvLyBmb3Igc3RhY2tlZCBhcmVhIHRyYWNlcyB0byBzaGFyZSBjb25maWcgYWNyb3NzIHRyYWNlc1xuICAgIG5ld0Z1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHMgPSB7fTtcbiAgICAvLyBmb3IgdGhlIGZpcnN0IHNjYXR0ZXIgdHJhY2Ugb24gZWFjaCBzdWJwbG90IChzbyBpdCBrbm93cyB0b25leHQtPnRvemVybylcbiAgICBuZXdGdWxsTGF5b3V0Ll9maXJzdFNjYXR0ZXIgPSB7fTtcblxuICAgIC8vIGZvciB0cmFjZXMgdG8gcmVxdWVzdCBhIGRlZmF1bHQgcmFuZ2VzbGlkZXIgb24gdGhlaXIgeCBheGVzXG4gICAgLy8gZWcgc2V0IGBfcmVxdWVzdFJhbmdlc2xpZGVyLngyID0gdHJ1ZWAgZm9yIHhheGlzMlxuICAgIG5ld0Z1bGxMYXlvdXQuX3JlcXVlc3RSYW5nZXNsaWRlciA9IHt9O1xuXG4gICAgLy8gcHVsbCB1aWRzIGZyb20gb2xkIGRhdGEgdG8gdXNlIGFzIG5ldyBkZWZhdWx0c1xuICAgIG5ld0Z1bGxMYXlvdXQuX3RyYWNlVWlkcyA9IGdldFRyYWNlVWlkcyhvbGRGdWxsRGF0YSwgbmV3RGF0YSk7XG5cbiAgICAvLyB0aGVuIGRvIHRoZSBkYXRhXG4gICAgbmV3RnVsbExheW91dC5fZ2xvYmFsVHJhbnNmb3JtcyA9IChnZC5fY29udGV4dCB8fCB7fSkuZ2xvYmFsVHJhbnNmb3JtcztcbiAgICBwbG90cy5zdXBwbHlEYXRhRGVmYXVsdHMobmV3RGF0YSwgbmV3RnVsbERhdGEsIG5ld0xheW91dCwgbmV3RnVsbExheW91dCk7XG5cbiAgICAvLyByZWRvIGdyaWQgc2l6ZSBkZWZhdWx0cyB3aXRoIGluZm8gYWJvdXQgc3Bsb20geC95IGF4ZXMsXG4gICAgLy8gYW5kIGZpbGwgaW4gZ2VuZXJhdGVkIGNhcnRlc2lhbiBheGVzIGFuZCBzdWJwbG90c1xuICAgIHZhciBzcGxvbVhhID0gT2JqZWN0LmtleXMoc3Bsb21BeGVzLngpO1xuICAgIHZhciBzcGxvbVlhID0gT2JqZWN0LmtleXMoc3Bsb21BeGVzLnkpO1xuICAgIGlmKHNwbG9tWGEubGVuZ3RoID4gMSAmJiBzcGxvbVlhLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdncmlkJywgJ3NpemVEZWZhdWx0cycpKG5ld0xheW91dCwgbmV3RnVsbExheW91dCk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3Bsb21YYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoc3VicGxvdHMueGF4aXMsIHNwbG9tWGFbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNwbG9tWWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHN1YnBsb3RzLnlheGlzLCBzcGxvbVlhW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IodmFyIGsgaW4gc3Bsb21TdWJwbG90cykge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoc3VicGxvdHMuY2FydGVzaWFuLCBrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGF0dGFjaCBoZWxwZXIgbWV0aG9kIHRvIGNoZWNrIHdoZXRoZXIgYSBwbG90IHR5cGUgaXMgcHJlc2VudCBvbiBncmFwaFxuICAgIG5ld0Z1bGxMYXlvdXQuX2hhcyA9IHBsb3RzLl9oYXNQbG90VHlwZS5iaW5kKG5ld0Z1bGxMYXlvdXQpO1xuXG4gICAgaWYob2xkRnVsbERhdGEubGVuZ3RoID09PSBuZXdGdWxsRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbmV3RnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJlbGlua1ByaXZhdGVLZXlzKG5ld0Z1bGxEYXRhW2ldLCBvbGRGdWxsRGF0YVtpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5LCBmaWxsIGluIHRoZSBwaWVjZXMgb2YgbGF5b3V0IHRoYXQgbWF5IG5lZWQgdG8gbG9vayBhdCBkYXRhXG4gICAgcGxvdHMuc3VwcGx5TGF5b3V0TW9kdWxlRGVmYXVsdHMobmV3TGF5b3V0LCBuZXdGdWxsTGF5b3V0LCBuZXdGdWxsRGF0YSwgZ2QuX3RyYW5zaXRpb25EYXRhKTtcblxuICAgIC8vIFNwZWNpYWwgY2FzZXMgdGhhdCBpbnRyb2R1Y2UgaW50ZXJhY3Rpb25zIGJldHdlZW4gdHJhY2VzLlxuICAgIC8vIFRoaXMgaXMgYWZ0ZXIgcmVsaW5rUHJpdmF0ZUtleXMgc28gd2UgY2FuIHVzZSB0aG9zZSBpbiBjcm9zc1RyYWNlRGVmYXVsdHNcbiAgICAvLyBhbmQgYWZ0ZXIgbGF5b3V0IG1vZHVsZSBkZWZhdWx0cywgc28gd2UgY2FuIHVzZSBlZyBiYXJtb2RlXG4gICAgdmFyIF9tb2R1bGVzID0gbmV3RnVsbExheW91dC5fdmlzaWJsZU1vZHVsZXM7XG4gICAgdmFyIGNyb3NzVHJhY2VEZWZhdWx0c0Z1bmNzID0gW107XG4gICAgZm9yKGkgPSAwOyBpIDwgX21vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZ1bmNpID0gX21vZHVsZXNbaV0uY3Jvc3NUcmFjZURlZmF1bHRzO1xuICAgICAgICAvLyBzb21lIHRyYWNlIHR5cGVzIHNoYXJlIGNyb3NzVHJhY2VEZWZhdWx0cyAoaWUgaGlzdG9ncmFtMmQsIGhpc3RvZ3JhbTJkY29udG91cilcbiAgICAgICAgaWYoZnVuY2kpIExpYi5wdXNoVW5pcXVlKGNyb3NzVHJhY2VEZWZhdWx0c0Z1bmNzLCBmdW5jaSk7XG4gICAgfVxuICAgIGZvcihpID0gMDsgaSA8IGNyb3NzVHJhY2VEZWZhdWx0c0Z1bmNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNyb3NzVHJhY2VEZWZhdWx0c0Z1bmNzW2ldKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0KTtcbiAgICB9XG5cbiAgICAvLyB0dXJuIG9uIGZsYWcgdG8gb3B0aW1pemUgbGFyZ2Ugc3Bsb20tb25seSBncmFwaHNcbiAgICAvLyBtb3N0bHkgYnkgb21pdHRpbmcgU1ZHIGxheWVycyBkdXJpbmcgQ2FydGVzaWFuLmRyYXdGcmFtZXdvcmtcbiAgICBuZXdGdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMgPSAoXG4gICAgICAgIG5ld0Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgbmV3RnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzWzBdLm5hbWUgPT09ICdzcGxvbScgJiZcbiAgICAgICAgc3Bsb21YYS5sZW5ndGggPiAxNSAmJlxuICAgICAgICBzcGxvbVlhLmxlbmd0aCA+IDE1ICYmXG4gICAgICAgIG5ld0Z1bGxMYXlvdXQuc2hhcGVzLmxlbmd0aCA9PT0gMCAmJlxuICAgICAgICBuZXdGdWxsTGF5b3V0LmltYWdlcy5sZW5ndGggPT09IDBcbiAgICApO1xuXG4gICAgLy8gVE9ETyByZW1vdmUgaW4gdjIuMC4wXG4gICAgLy8gYWRkIGhhcy1wbG90LXR5cGUgcmVmcyB0byBmdWxsTGF5b3V0IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgbmV3RnVsbExheW91dC5faGFzQ2FydGVzaWFuID0gbmV3RnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKTtcbiAgICBuZXdGdWxsTGF5b3V0Ll9oYXNHZW8gPSBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2dlbycpO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2hhc0dMM0QgPSBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2dsM2QnKTtcbiAgICBuZXdGdWxsTGF5b3V0Ll9oYXNHTDJEID0gbmV3RnVsbExheW91dC5faGFzKCdnbDJkJyk7XG4gICAgbmV3RnVsbExheW91dC5faGFzVGVybmFyeSA9IG5ld0Z1bGxMYXlvdXQuX2hhcygndGVybmFyeScpO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2hhc1BpZSA9IG5ld0Z1bGxMYXlvdXQuX2hhcygncGllJyk7XG5cbiAgICAvLyByZWxpbmsgLyBpbml0aWFsaXplIHN1YnBsb3QgYXhpcyBvYmplY3RzXG4gICAgcGxvdHMubGlua1N1YnBsb3RzKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCk7XG5cbiAgICAvLyBjbGVhbiBzdWJwbG90cyBhbmQgb3RoZXIgYXJ0aWZhY3RzIGZyb20gcHJldmlvdXMgcGxvdCBjYWxsc1xuICAgIHBsb3RzLmNsZWFuUGxvdChuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpO1xuXG4gICAgLy8gcmVsaW5rIGZ1bmN0aW9ucyBhbmQgXyBhdHRyaWJ1dGVzIHRvIHByb21vdGUgY29uc2lzdGVuY3kgYmV0d2VlbiBwbG90c1xuICAgIHJlbGlua1ByaXZhdGVLZXlzKG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxMYXlvdXQpO1xuXG4gICAgLy8gVE9ETyBtYXkgcmV0dXJuIGEgcHJvbWlzZVxuICAgIHBsb3RzLmRvQXV0b01hcmdpbihnZCk7XG5cbiAgICAvLyBzZXQgc2NhbGUgYWZ0ZXIgYXV0byBtYXJnaW4gcm91dGluZVxuICAgIHZhciBheExpc3QgPSBheGlzSURzLmxpc3QoZ2QpO1xuICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG4gICAgICAgIGF4LnNldFNjYWxlKCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIG9iamVjdCByZWZlcmVuY2VzIGluIGNhbGNkYXRhXG4gICAgaWYoIXNraXBVcGRhdGVDYWxjICYmIG9sZENhbGNkYXRhLmxlbmd0aCA9PT0gbmV3RnVsbERhdGEubGVuZ3RoKSB7XG4gICAgICAgIHBsb3RzLnN1cHBseURlZmF1bHRzVXBkYXRlQ2FsYyhvbGRDYWxjZGF0YSwgbmV3RnVsbERhdGEpO1xuICAgIH1cbn07XG5cbnBsb3RzLnN1cHBseURlZmF1bHRzVXBkYXRlQ2FsYyA9IGZ1bmN0aW9uKG9sZENhbGNkYXRhLCBuZXdGdWxsRGF0YSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuZXdGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmV3VHJhY2UgPSBuZXdGdWxsRGF0YVtpXTtcbiAgICAgICAgdmFyIGNkMCA9IG9sZENhbGNkYXRhW2ldWzBdO1xuICAgICAgICBpZihjZDAgJiYgY2QwLnRyYWNlKSB7XG4gICAgICAgICAgICB2YXIgb2xkVHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgICAgICBpZihvbGRUcmFjZS5faGFzQ2FsY1RyYW5zZm9ybSkge1xuICAgICAgICAgICAgICAgIHZhciBhcnJheUF0dHJzID0gb2xkVHJhY2UuX2FycmF5QXR0cnM7XG4gICAgICAgICAgICAgICAgdmFyIGosIGFzdHIsIG9sZEFycmF5VmFsO1xuXG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgYXJyYXlBdHRycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBhc3RyID0gYXJyYXlBdHRyc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgb2xkQXJyYXlWYWwgPSBMaWIubmVzdGVkUHJvcGVydHkob2xkVHJhY2UsIGFzdHIpLmdldCgpLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdUcmFjZSwgYXN0cikuc2V0KG9sZEFycmF5VmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjZDAudHJhY2UgPSBuZXdUcmFjZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgbGlzdCBvZiB1aWQgc3RyaW5ncyBzYXRpc2Z5aW5nIChpbiB0aGlzIG9yZGVyIG9mIGltcG9ydGFuY2UpOlxuICogMS4gYWxsIHVuaXF1ZSwgYWxsIHN0cmluZ3NcbiAqIDIuIG1hdGNoZXMgaW5wdXQgdWlkcyBpZiBwcm92aWRlZFxuICogMy4gbWF0Y2hlcyBwcmV2aW91cyBkYXRhIHVpZHNcbiAqL1xuZnVuY3Rpb24gZ2V0VHJhY2VVaWRzKG9sZEZ1bGxEYXRhLCBuZXdEYXRhKSB7XG4gICAgdmFyIGxlbiA9IG5ld0RhdGEubGVuZ3RoO1xuICAgIHZhciBvbGRGdWxsSW5wdXQgPSBbXTtcbiAgICB2YXIgaSwgcHJldkZ1bGxJbnB1dDtcbiAgICBmb3IoaSA9IDA7IGkgPCBvbGRGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGhpc0Z1bGxJbnB1dCA9IG9sZEZ1bGxEYXRhW2ldLl9mdWxsSW5wdXQ7XG4gICAgICAgIGlmKHRoaXNGdWxsSW5wdXQgIT09IHByZXZGdWxsSW5wdXQpIG9sZEZ1bGxJbnB1dC5wdXNoKHRoaXNGdWxsSW5wdXQpO1xuICAgICAgICBwcmV2RnVsbElucHV0ID0gdGhpc0Z1bGxJbnB1dDtcbiAgICB9XG4gICAgdmFyIG9sZExlbiA9IG9sZEZ1bGxJbnB1dC5sZW5ndGg7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBzZWVuVWlkcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gc2V0VWlkKHVpZCwgaSkge1xuICAgICAgICBvdXRbaV0gPSB1aWQ7XG4gICAgICAgIHNlZW5VaWRzW3VpZF0gPSAxO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyeVVpZCh1aWQsIGkpIHtcbiAgICAgICAgaWYodWlkICYmIHR5cGVvZiB1aWQgPT09ICdzdHJpbmcnICYmICFzZWVuVWlkc1t1aWRdKSB7XG4gICAgICAgICAgICBzZXRVaWQodWlkLCBpKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYodHJ5VWlkKG5ld0RhdGFbaV0udWlkLCBpKSkgY29udGludWU7XG4gICAgICAgIGlmKGkgPCBvbGRMZW4gJiYgdHJ5VWlkKG9sZEZ1bGxJbnB1dFtpXS51aWQsIGkpKSBjb250aW51ZTtcbiAgICAgICAgc2V0VWlkKExpYi5yYW5kc3RyKHNlZW5VaWRzKSwgaSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBNYWtlIGEgY29udGFpbmVyIGZvciBjb2xsZWN0aW5nIHN1YnBsb3RzIHdlIG5lZWQgdG8gZGlzcGxheS5cbiAqXG4gKiBGaW5kcyBhbGwgc3VicGxvdCB0eXBlcyB3ZSBuZWVkIHRvIGVudW1lcmF0ZSBvbmNlIGFuZCBjYWNoZXMgaXQsXG4gKiBidXQgbWFrZXMgYSBuZXcgb3V0cHV0IG9iamVjdCBlYWNoIHRpbWUuXG4gKiBTaW5nbGUtdHJhY2Ugc3VicGxvdHMgKHdoaWNoIGhhdmUgbm8gYGlkYCkgc3VjaCBhcyBwaWUsIHRhYmxlLCBldGNcbiAqIGRvIG5vdCBuZWVkIHRvIGJlIGNvbGxlY3RlZCBiZWNhdXNlIHdlIGp1c3QgZHJhdyBhbGwgdmlzaWJsZSB0cmFjZXMuXG4gKi9cbnZhciBjb2xsZWN0YWJsZVN1YnBsb3RUeXBlcztcbmZ1bmN0aW9uIGVtcHR5U3VicGxvdExpc3RzKCkge1xuICAgIHZhciBvdXQgPSB7fTtcbiAgICB2YXIgaSwgajtcblxuICAgIGlmKCFjb2xsZWN0YWJsZVN1YnBsb3RUeXBlcykge1xuICAgICAgICBjb2xsZWN0YWJsZVN1YnBsb3RUeXBlcyA9IFtdO1xuXG4gICAgICAgIHZhciBzdWJwbG90c1JlZ2lzdHJ5ID0gUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeTtcblxuICAgICAgICBmb3IodmFyIHN1YnBsb3RUeXBlIGluIHN1YnBsb3RzUmVnaXN0cnkpIHtcbiAgICAgICAgICAgIHZhciBzdWJwbG90TW9kdWxlID0gc3VicGxvdHNSZWdpc3RyeVtzdWJwbG90VHlwZV07XG4gICAgICAgICAgICB2YXIgc3VicGxvdEF0dHIgPSBzdWJwbG90TW9kdWxlLmF0dHI7XG5cbiAgICAgICAgICAgIGlmKHN1YnBsb3RBdHRyKSB7XG4gICAgICAgICAgICAgICAgY29sbGVjdGFibGVTdWJwbG90VHlwZXMucHVzaChzdWJwbG90VHlwZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBzcGVjaWFsIGNhc2UsIGN1cnJlbnRseSBqdXN0IGZvciBjYXJ0ZXNpYW46XG4gICAgICAgICAgICAgICAgLy8gd2UgbmVlZCB0byBlbnVtZXJhdGUgYXhlcywgbm90IGp1c3Qgc3VicGxvdHNcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHN1YnBsb3RBdHRyKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBzdWJwbG90QXR0ci5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoY29sbGVjdGFibGVTdWJwbG90VHlwZXMsIHN1YnBsb3RBdHRyW2pdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGNvbGxlY3RhYmxlU3VicGxvdFR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG91dFtjb2xsZWN0YWJsZVN1YnBsb3RUeXBlc1tpXV0gPSBbXTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBnZXRGb3JtYXRPYmo6IHVzZSBfY29udGV4dCB0byBnZXQgdGhlIGZvcm1hdCBvYmplY3QgZnJvbSBsb2NhbGUuXG4gKiBVc2VkIHRvIGdldCBkMy5sb2NhbGUgYXJndW1lbnQgb2JqZWN0IGFuZCBleHRyYUZvcm1hdCBhcmd1bWVudCBvYmplY3RcbiAqXG4gKiBSZWdhcmRpbmcgZDMubG9jYWxlIGFyZ3VtZW50IDpcbiAqIGRlY2ltYWwgYW5kIHRob3VzYW5kcyBjYW4gYmUgb3ZlcnJpZGRlbiBsYXRlciBieSBsYXlvdXQuc2VwYXJhdG9yc1xuICogZ3JvdXBpbmcgYW5kIGN1cnJlbmN5IGFyZSBub3QgcHJlc2VudGx5IHVzZWQgYnkgb3VyIGF1dG9tYXRpYyBudW1iZXJcbiAqIGZvcm1hdHRpbmcgc3lzdGVtIGJ1dCBjYW4gYmUgdXNlZCBieSBjdXN0b20gZm9ybWF0cy5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBkMy5sb2NhbGUgZm9ybWF0IG9iamVjdFxuICovXG5mdW5jdGlvbiBnZXRGb3JtYXRPYmooZ2QsIGZvcm1hdEtleXMpIHtcbiAgICB2YXIgbG9jYWxlID0gZ2QuX2NvbnRleHQubG9jYWxlO1xuICAgIGlmKCFsb2NhbGUpIGxvY2FsZSA9PT0gJ2VuLVVTJztcblxuICAgIHZhciBmb3JtYXREb25lID0gZmFsc2U7XG4gICAgdmFyIGZvcm1hdE9iaiA9IHt9O1xuXG4gICAgZnVuY3Rpb24gaW5jbHVkZUZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgdmFyIGZvcm1hdEZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGZvcm1hdEtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBmb3JtYXRLZXkgPSBmb3JtYXRLZXlzW2ldO1xuICAgICAgICAgICAgaWYoIWZvcm1hdE9ialtmb3JtYXRLZXldKSB7XG4gICAgICAgICAgICAgICAgaWYobmV3Rm9ybWF0W2Zvcm1hdEtleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybWF0T2JqW2Zvcm1hdEtleV0gPSBuZXdGb3JtYXRbZm9ybWF0S2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBmb3JtYXRGaW5pc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKGZvcm1hdEZpbmlzaGVkKSBmb3JtYXREb25lID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBzYW1lIGFzIGxvY2FsaXplLCBsb29rIGZvciBmb3JtYXQgcGFydHMgaW4gZWFjaCBmb3JtYXQgc3BlYyBpbiB0aGUgY2hhaW5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgIHZhciBsb2NhbGVzID0gZ2QuX2NvbnRleHQubG9jYWxlcztcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDI7IGorKykge1xuICAgICAgICAgICAgdmFyIGZvcm1hdGogPSAobG9jYWxlc1tsb2NhbGVdIHx8IHt9KS5mb3JtYXQ7XG4gICAgICAgICAgICBpZihmb3JtYXRqKSB7XG4gICAgICAgICAgICAgICAgaW5jbHVkZUZvcm1hdChmb3JtYXRqKTtcbiAgICAgICAgICAgICAgICBpZihmb3JtYXREb25lKSBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvY2FsZXMgPSBSZWdpc3RyeS5sb2NhbGVSZWdpc3RyeTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBiYXNlTG9jYWxlID0gbG9jYWxlLnNwbGl0KCctJylbMF07XG4gICAgICAgIGlmKGZvcm1hdERvbmUgfHwgYmFzZUxvY2FsZSA9PT0gbG9jYWxlKSBicmVhaztcbiAgICAgICAgbG9jYWxlID0gYmFzZUxvY2FsZTtcbiAgICB9XG5cbiAgICAvLyBsYXN0bHkgcGljayBvdXQgZGVmYXVsdHMgZnJvbSBlbmdsaXNoIChub24tVVMsIGFzIERNWSBpcyBzbyBtdWNoIG1vcmUgY29tbW9uKVxuICAgIGlmKCFmb3JtYXREb25lKSBpbmNsdWRlRm9ybWF0KFJlZ2lzdHJ5LmxvY2FsZVJlZ2lzdHJ5LmVuLmZvcm1hdCk7XG5cbiAgICByZXR1cm4gZm9ybWF0T2JqO1xufVxuXG4vKipcbiAqIGdldEZvcm1hdHRlcjogY29tYmluZSB0aGUgZmluYWwgc2VwYXJhdG9ycyB3aXRoIHRoZSBsb2NhbGUgZm9ybWF0dGluZyBvYmplY3RcbiAqIHdlIHB1bGxlZCBlYXJsaWVyIHRvIGdlbmVyYXRlIG51bWJlciBhbmQgdGltZSBmb3JtYXR0ZXJzXG4gKiBUT0RPOiByZW1vdmUgc2VwYXJhdG9ycyBpbiB2Miwgb25seSB1c2UgbG9jYWxlLCBzbyB3ZSBkb24ndCBuZWVkIHRoaXMgc3RlcD9cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZm9ybWF0T2JqOiBkMy5sb2NhbGUgZm9ybWF0IG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IHNlcGFyYXRvcnM6IGxlbmd0aC0yIHN0cmluZyB0byBvdmVycmlkZSBkZWNpbWFsIGFuZCB0aG91c2FuZHNcbiAqICAgc2VwYXJhdG9ycyBpbiBudW1iZXIgZm9ybWF0dGluZ1xuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9IHtudW1iZXJGb3JtYXQsIHRpbWVGb3JtYXR9IGQzIGZvcm1hdHRlciBmYWN0b3J5IGZ1bmN0aW9uc1xuICogICBmb3IgbnVtYmVycyBhbmQgdGltZVxuICovXG5mdW5jdGlvbiBnZXRGb3JtYXR0ZXIoZm9ybWF0T2JqLCBzZXBhcmF0b3JzKSB7XG4gICAgZm9ybWF0T2JqLmRlY2ltYWwgPSBzZXBhcmF0b3JzLmNoYXJBdCgwKTtcbiAgICBmb3JtYXRPYmoudGhvdXNhbmRzID0gc2VwYXJhdG9ycy5jaGFyQXQoMSk7XG5cbiAgICByZXR1cm4gZDMubG9jYWxlKGZvcm1hdE9iaik7XG59XG5cbi8vIENyZWF0ZSBzdG9yYWdlIGZvciBhbGwgb2YgdGhlIGRhdGEgcmVsYXRlZCB0byBmcmFtZXMgYW5kIHRyYW5zaXRpb25zOlxucGxvdHMuY3JlYXRlVHJhbnNpdGlvbkRhdGEgPSBmdW5jdGlvbihnZCkge1xuICAgIC8vIFNldCB1cCB0aGUgZGVmYXVsdCBrZXlmcmFtZSBpZiBpdCBkb2Vzbid0IGV4aXN0OlxuICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEpIHtcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhID0ge307XG4gICAgfVxuXG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVzKSB7XG4gICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVzID0gW107XG4gICAgfVxuXG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoKSB7XG4gICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoID0ge307XG4gICAgfVxuXG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YS5fY291bnRlcikge1xuICAgICAgICBnZC5fdHJhbnNpdGlvbkRhdGEuX2NvdW50ZXIgPSAwO1xuICAgIH1cblxuICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcykge1xuICAgICAgICBnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcyA9IFtdO1xuICAgIH1cbn07XG5cbi8vIGhlbHBlciBmdW5jdGlvbiB0byBiZSBib3VuZCB0byBmdWxsTGF5b3V0IHRvIGNoZWNrXG4vLyB3aGV0aGVyIGEgY2VydGFpbiBwbG90IHR5cGUgaXMgcHJlc2VudCBvbiBwbG90XG4vLyBvciB0cmFjZSBoYXMgYSBjYXRlZ29yeVxucGxvdHMuX2hhc1Bsb3RUeXBlID0gZnVuY3Rpb24oY2F0ZWdvcnkpIHtcbiAgICB2YXIgaTtcblxuICAgIC8vIGNoZWNrIGJhc2UgcGxvdCBtb2R1bGVzXG4gICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IHRoaXMuX2Jhc2VQbG90TW9kdWxlcyB8fCBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoYmFzZVBsb3RNb2R1bGVzW2ldLm5hbWUgPT09IGNhdGVnb3J5KSByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayB0cmFjZSBtb2R1bGVzIChpbmNsdWRpbmcgbm9uLXZpc2libGU6dHJ1ZSlcbiAgICB2YXIgbW9kdWxlcyA9IHRoaXMuX21vZHVsZXMgfHwgW107XG4gICAgZm9yKGkgPSAwOyBpIDwgbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmFtZSA9IG1vZHVsZXNbaV0ubmFtZTtcbiAgICAgICAgaWYobmFtZSA9PT0gY2F0ZWdvcnkpIHJldHVybiB0cnVlO1xuICAgICAgICAvLyBOLkIuIHRoaXMgaXMgbW9kdWxlc1tpXSBhbG9uZyB3aXRoICdjYXRlZ29yaWVzJyBhcyBhIGhhc2ggb2JqZWN0XG4gICAgICAgIHZhciBfbW9kdWxlID0gUmVnaXN0cnkubW9kdWxlc1tuYW1lXTtcbiAgICAgICAgaWYoX21vZHVsZSAmJiBfbW9kdWxlLmNhdGVnb3JpZXNbY2F0ZWdvcnldKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG5wbG90cy5jbGVhblBsb3QgPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaSwgajtcblxuICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBvbGRGdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXMgfHwgW107XG4gICAgZm9yKGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gYmFzZVBsb3RNb2R1bGVzW2ldO1xuXG4gICAgICAgIGlmKF9tb2R1bGUuY2xlYW4pIHtcbiAgICAgICAgICAgIF9tb2R1bGUuY2xlYW4obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBoYWRHbCA9IG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ2dsJyk7XG4gICAgdmFyIGhhc0dsID0gbmV3RnVsbExheW91dC5faGFzICYmIG5ld0Z1bGxMYXlvdXQuX2hhcygnZ2wnKTtcblxuICAgIGlmKGhhZEdsICYmICFoYXNHbCkge1xuICAgICAgICBpZihvbGRGdWxsTGF5b3V0Ll9nbGNvbnRhaW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9nbGNvbnRhaW5lci5zZWxlY3RBbGwoJy5nbC1jYW52YXMnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLnNlbGVjdEFsbCgnLm5vLXdlYmdsJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9nbGNhbnZhcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaGFzSW5mb0xheWVyID0gISFvbGRGdWxsTGF5b3V0Ll9pbmZvbGF5ZXI7XG5cbiAgICBvbGRMb29wOlxuICAgIGZvcihpID0gMDsgaSA8IG9sZEZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvbGRUcmFjZSA9IG9sZEZ1bGxEYXRhW2ldLFxuICAgICAgICAgICAgb2xkVWlkID0gb2xkVHJhY2UudWlkO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IG5ld0Z1bGxEYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgbmV3VHJhY2UgPSBuZXdGdWxsRGF0YVtqXTtcblxuICAgICAgICAgICAgaWYob2xkVWlkID09PSBuZXdUcmFjZS51aWQpIGNvbnRpbnVlIG9sZExvb3A7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjbGVhbiBvbGQgY29sb3JiYXJzXG4gICAgICAgIGlmKGhhc0luZm9MYXllcikge1xuICAgICAgICAgICAgb2xkRnVsbExheW91dC5faW5mb2xheWVyLnNlbGVjdCgnLmNiJyArIG9sZFVpZCkucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihvbGRGdWxsTGF5b3V0Ll96b29tbGF5ZXIpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fem9vbWxheWVyLnNlbGVjdEFsbCgnLnNlbGVjdC1vdXRsaW5lJykucmVtb3ZlKCk7XG4gICAgfVxufTtcblxucGxvdHMubGlua1N1YnBsb3RzID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGksIGo7XG5cbiAgICB2YXIgb2xkU3VicGxvdHMgPSBvbGRGdWxsTGF5b3V0Ll9wbG90cyB8fCB7fTtcbiAgICB2YXIgbmV3U3VicGxvdHMgPSBuZXdGdWxsTGF5b3V0Ll9wbG90cyA9IHt9O1xuICAgIHZhciBuZXdTdWJwbG90TGlzdCA9IG5ld0Z1bGxMYXlvdXQuX3N1YnBsb3RzO1xuXG4gICAgdmFyIG1vY2tHZCA9IHtcbiAgICAgICAgX2Z1bGxEYXRhOiBuZXdGdWxsRGF0YSxcbiAgICAgICAgX2Z1bGxMYXlvdXQ6IG5ld0Z1bGxMYXlvdXRcbiAgICB9O1xuXG4gICAgdmFyIGlkcyA9IG5ld1N1YnBsb3RMaXN0LmNhcnRlc2lhbi5jb25jYXQobmV3U3VicGxvdExpc3QuZ2wyZCB8fCBbXSk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gaWRzW2ldO1xuICAgICAgICB2YXIgb2xkU3VicGxvdCA9IG9sZFN1YnBsb3RzW2lkXTtcbiAgICAgICAgdmFyIHhheGlzID0gYXhpc0lEcy5nZXRGcm9tSWQobW9ja0dkLCBpZCwgJ3gnKTtcbiAgICAgICAgdmFyIHlheGlzID0gYXhpc0lEcy5nZXRGcm9tSWQobW9ja0dkLCBpZCwgJ3knKTtcbiAgICAgICAgdmFyIHBsb3RpbmZvO1xuXG4gICAgICAgIC8vIGxpbmsgb3IgY3JlYXRlIHN1YnBsb3Qgb2JqZWN0XG4gICAgICAgIGlmKG9sZFN1YnBsb3QpIHtcbiAgICAgICAgICAgIHBsb3RpbmZvID0gbmV3U3VicGxvdHNbaWRdID0gb2xkU3VicGxvdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBsb3RpbmZvID0gbmV3U3VicGxvdHNbaWRdID0ge307XG4gICAgICAgICAgICBwbG90aW5mby5pZCA9IGlkO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdXBkYXRlIHggYW5kIHkgYXhpcyBsYXlvdXQgb2JqZWN0IHJlZnNcbiAgICAgICAgcGxvdGluZm8ueGF4aXMgPSB4YXhpcztcbiAgICAgICAgcGxvdGluZm8ueWF4aXMgPSB5YXhpcztcblxuICAgICAgICAvLyBCeSBkZWZhdWx0LCB3ZSBjbGlwIGF0IHRoZSBzdWJwbG90IGxldmVsLFxuICAgICAgICAvLyBidXQgaWYgb25lIHRyYWNlIG9uIGEgZ2l2ZW4gc3VicGxvdCBoYXMgKmNsaXBvbmF4aXMqIHNldCB0byBmYWxzZSxcbiAgICAgICAgLy8gd2UgbmVlZCB0byBjbGlwIGF0IHRoZSB0cmFjZSBtb2R1bGUgbGF5ZXIgbGV2ZWw7XG4gICAgICAgIC8vIGZpbmQgdGhpcyBvdXQgaGVyZSwgb25jZSBvZiBmb3IgYWxsLlxuICAgICAgICBwbG90aW5mby5faGFzQ2xpcE9uQXhpc0ZhbHNlID0gZmFsc2U7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgbmV3RnVsbERhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IG5ld0Z1bGxEYXRhW2pdO1xuXG4gICAgICAgICAgICBpZihcbiAgICAgICAgICAgICAgICB0cmFjZS54YXhpcyA9PT0gcGxvdGluZm8ueGF4aXMuX2lkICYmXG4gICAgICAgICAgICAgICAgdHJhY2UueWF4aXMgPT09IHBsb3RpbmZvLnlheGlzLl9pZCAmJlxuICAgICAgICAgICAgICAgIHRyYWNlLmNsaXBvbmF4aXMgPT09IGZhbHNlXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBwbG90aW5mby5faGFzQ2xpcE9uQXhpc0ZhbHNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHdoaWxlIHdlJ3JlIGF0IGl0LCBsaW5rIG92ZXJsYXlpbmcgYXhlcyB0byB0aGVpciBtYWluIGF4ZXMgYW5kXG4gICAgLy8gYW5jaG9yZWQgYXhlcyB0byB0aGUgYXhlcyB0aGV5J3JlIGFuY2hvcmVkIHRvXG4gICAgdmFyIGF4TGlzdCA9IGF4aXNJRHMubGlzdChtb2NrR2QsIG51bGwsIHRydWUpO1xuICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG4gICAgICAgIHZhciBtYWluQXggPSBudWxsO1xuXG4gICAgICAgIGlmKGF4Lm92ZXJsYXlpbmcpIHtcbiAgICAgICAgICAgIG1haW5BeCA9IGF4aXNJRHMuZ2V0RnJvbUlkKG1vY2tHZCwgYXgub3ZlcmxheWluZyk7XG5cbiAgICAgICAgICAgIC8vIHlvdSBjYW5ub3Qgb3ZlcmxheSBhbiBheGlzIHRoYXQncyBhbHJlYWR5IG92ZXJsYXlpbmcgYW5vdGhlclxuICAgICAgICAgICAgaWYobWFpbkF4ICYmIG1haW5BeC5vdmVybGF5aW5nKSB7XG4gICAgICAgICAgICAgICAgYXgub3ZlcmxheWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIG1haW5BeCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXguX21haW5BeGlzID0gbWFpbkF4IHx8IGF4O1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIEZvciBub3cgZm9yY2Ugb3ZlcmxheXMgdG8gb3ZlcmxheSBjb21wbGV0ZWx5Li4uIHNvIHRoZXlcbiAgICAgICAgICogY2FuIGRyYWcgdG9nZXRoZXIgY29ycmVjdGx5IGFuZCBzaGFyZSBiYWNrZ3JvdW5kcy5cbiAgICAgICAgICogTGF0ZXIgcGVyaGFwcyB3ZSBtYWtlIHNlcGFyYXRlIGF4aXMgZG9tYWluIGFuZFxuICAgICAgICAgKiB0aWNrL2xpbmUgZG9tYWluIG9yIHNvbWV0aGluZywgc28gdGhleSBjYW4gc3RpbGwgc2hhcmVcbiAgICAgICAgICogdGhlIChwb3NzaWJseSBsYXJnZXIpIGRyYWdnZXIgYW5kIGJhY2tncm91bmQgYnV0IGRvbid0XG4gICAgICAgICAqIGhhdmUgdG8gYm90aCBiZSBkcmF3biBvdmVyIHRoYXQgd2hvbGUgZG9tYWluXG4gICAgICAgICAqL1xuICAgICAgICBpZihtYWluQXgpIGF4LmRvbWFpbiA9IG1haW5BeC5kb21haW4uc2xpY2UoKTtcblxuICAgICAgICBheC5fYW5jaG9yQXhpcyA9IGF4LmFuY2hvciA9PT0gJ2ZyZWUnID9cbiAgICAgICAgICAgIG51bGwgOlxuICAgICAgICAgICAgYXhpc0lEcy5nZXRGcm9tSWQobW9ja0dkLCBheC5hbmNob3IpO1xuICAgIH1cbn07XG5cbi8vIFRoaXMgZnVuY3Rpb24gY2xlYXJzIGFueSB0cmFjZSBhdHRyaWJ1dGVzIHdpdGggdmFsVHlwZTogY29sb3IgYW5kXG4vLyBubyBzZXQgZGZsdCBmaWxlZCBpbiB0aGUgcGxvdCBzY2hlbWEuIFRoaXMgaXMgbmVlZGVkIGJlY2F1c2UgZ3JvdXBieSAod2hpY2hcbi8vIGlzIHRoZSBvbmx5IHRyYW5zZm9ybSBmb3Igd2hpY2ggdGhpcyBjdXJyZW50bHkgYXBwbGllcykgc3VwcGxpZXMgcGFyZW50XG4vLyB0cmFjZSBkZWZhdWx0cywgdGhlbiBleHBhbmRlZCB0cmFjZSBkZWZhdWx0cy4gVGhlIHJlc3VsdCBpcyB0aGF0IGBudWxsYFxuLy8gY29sb3JzIGFyZSBkZWZhdWx0LXN1cHBsaWVkIGFuZCBpbmhlcml0ZWQgYXMgYSBjb2xvciBpbnN0ZWFkIG9mIGEgbnVsbC5cbi8vIFRoZSByZXN1bHQgaXMgdGhhdCBleHBhbmRlZCB0cmFjZSBkZWZhdWx0IGNvbG9ycyBoYXZlIG5vIGVmZmVjdCwgd2l0aFxuLy8gdGhlIGZpbmFsIHJlc3VsdCB0aGF0IGdyb3VwcyBhcmUgaW5kaXN0aW5ndWlzaGFibGUuIFRoaXMgZnVuY3Rpb24gY2xlYXJzXG4vLyB0aG9zZSBjb2xvcnMgc28gdGhhdCBpbmRpdmlkdWFsIGdyb3VwYnkgZ3JvdXBzIGdldCB1bmlxdWUgY29sb3JzLlxucGxvdHMuY2xlYXJFeHBhbmRlZFRyYWNlRGVmYXVsdENvbG9ycyA9IGZ1bmN0aW9uKHRyYWNlKSB7XG4gICAgdmFyIGNvbG9yQXR0cnMsIHBhdGgsIGk7XG5cbiAgICAvLyBUaGlzIHVzZXMgd2VpcmQgY2xvc3VyZSBzdGF0ZSBpbiBvcmRlciB0byBzYXRpc2Z5IHRoZSBsaW50ZXIgcnVsZVxuICAgIC8vIHRoYXQgd2UgY2FuJ3QgY3JlYXRlIGZ1bmN0aW9ucyBpbiBhIGxvb3AuXG4gICAgZnVuY3Rpb24gbG9jYXRlQ29sb3JBdHRycyhhdHRyLCBhdHRyTmFtZSwgYXR0cnMsIGxldmVsKSB7XG4gICAgICAgIHBhdGhbbGV2ZWxdID0gYXR0ck5hbWU7XG4gICAgICAgIHBhdGgubGVuZ3RoID0gbGV2ZWwgKyAxO1xuICAgICAgICBpZihhdHRyLnZhbFR5cGUgPT09ICdjb2xvcicgJiYgYXR0ci5kZmx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbG9yQXR0cnMucHVzaChwYXRoLmpvaW4oJy4nKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwYXRoID0gW107XG5cbiAgICAvLyBHZXQgdGhlIGNhY2hlZCBjb2xvckF0dHJzOlxuICAgIGNvbG9yQXR0cnMgPSB0cmFjZS5fbW9kdWxlLl9jb2xvckF0dHJzO1xuXG4gICAgLy8gT3IgZWxzZSBjb21wdXRlIGFuZCBjYWNoZSB0aGUgY29sb3JBdHRycyBvbiB0aGUgbW9kdWxlOlxuICAgIGlmKCFjb2xvckF0dHJzKSB7XG4gICAgICAgIHRyYWNlLl9tb2R1bGUuX2NvbG9yQXR0cnMgPSBjb2xvckF0dHJzID0gW107XG4gICAgICAgIFBsb3RTY2hlbWEuY3Jhd2woXG4gICAgICAgICAgICB0cmFjZS5fbW9kdWxlLmF0dHJpYnV0ZXMsXG4gICAgICAgICAgICBsb2NhdGVDb2xvckF0dHJzXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgY29sb3JBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3JpZ3Byb3AgPSBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsICdfaW5wdXQuJyArIGNvbG9yQXR0cnNbaV0pO1xuXG4gICAgICAgIGlmKCFvcmlncHJvcC5nZXQoKSkge1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBjb2xvckF0dHJzW2ldKS5zZXQobnVsbCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cbnBsb3RzLnN1cHBseURhdGFEZWZhdWx0cyA9IGZ1bmN0aW9uKGRhdGFJbiwgZGF0YU91dCwgbGF5b3V0LCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIG1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9tb2R1bGVzO1xuICAgIHZhciB2aXNpYmxlTW9kdWxlcyA9IGZ1bGxMYXlvdXQuX3Zpc2libGVNb2R1bGVzO1xuICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG4gICAgdmFyIGNudCA9IDA7XG4gICAgdmFyIGNvbG9yQ250ID0gMDtcblxuICAgIHZhciBpLCBmdWxsVHJhY2UsIHRyYWNlO1xuXG4gICAgZnVsbExheW91dC5fdHJhbnNmb3JtTW9kdWxlcyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gcHVzaE1vZHVsZShmdWxsVHJhY2UpIHtcbiAgICAgICAgZGF0YU91dC5wdXNoKGZ1bGxUcmFjZSk7XG5cbiAgICAgICAgdmFyIF9tb2R1bGUgPSBmdWxsVHJhY2UuX21vZHVsZTtcbiAgICAgICAgaWYoIV9tb2R1bGUpIHJldHVybjtcblxuICAgICAgICBMaWIucHVzaFVuaXF1ZShtb2R1bGVzLCBfbW9kdWxlKTtcbiAgICAgICAgaWYoZnVsbFRyYWNlLnZpc2libGUgPT09IHRydWUpIExpYi5wdXNoVW5pcXVlKHZpc2libGVNb2R1bGVzLCBfbW9kdWxlKTtcbiAgICAgICAgTGliLnB1c2hVbmlxdWUoYmFzZVBsb3RNb2R1bGVzLCBmdWxsVHJhY2UuX21vZHVsZS5iYXNlUGxvdE1vZHVsZSk7XG4gICAgICAgIGNudCsrO1xuXG4gICAgICAgIC8vIFRPRE86IGRvIHdlIHJlYWxseSB3YW50IGNvbG9yIG5vdCB0byBpbmNyZW1lbnQgZm9yIGV4cGxpY2l0bHkgaW52aXNpYmxlIHRyYWNlcz9cbiAgICAgICAgLy8gVGhpcyBsb2dpYyBpcyB3ZWlyZCwgYnV0IG1hdGNoZXMgcHJldmlvdXMgYmVoYXZpb3I6IHRyYWNlcyB0aGF0IHlvdSBleHBsaWNpdGx5XG4gICAgICAgIC8vIHNldCB0byB2aXNpYmxlOmZhbHNlIGRvIG5vdCBpbmNyZW1lbnQgdGhlIGNvbG9yLCBidXQgdHJhY2VzIFdFIGRldGVybWluZSB0byBiZVxuICAgICAgICAvLyBlbXB0eSBvciBpbnZhbGlkIChhbmQgdGh1cyBzZXQgdG8gdmlzaWJsZTpmYWxzZSkgRE8gaW5jcmVtZW50IGNvbG9yLlxuICAgICAgICAvLyBJIGtpbmQgb2YgdGhpbmsgd2Ugc2hvdWxkIGp1c3QgbGV0IGFsbCB0cmFjZXMgaW5jcmVtZW50IGNvbG9yLCB2aXNpYmxlIG9yIG5vdC5cbiAgICAgICAgLy8gc2VlIG1vY2s6IGF4ZXMtYXV0b3R5cGUtZW1wdHkgdnMuIGEgdGVzdCBvZiByZXN0eWxpbmcgdmlzaWJsZTogZmFsc2UgdGhhdFxuICAgICAgICAvLyBJIGNhbid0IGZpbmQgcmlnaHQgbm93Li4uXG4gICAgICAgIGlmKGZ1bGxUcmFjZS5faW5wdXQudmlzaWJsZSAhPT0gZmFsc2UpIGNvbG9yQ250Kys7XG4gICAgfVxuXG4gICAgdmFyIGNhcnBldEluZGV4ID0ge307XG4gICAgdmFyIGNhcnBldERlcGVuZGVudHMgPSBbXTtcbiAgICB2YXIgZGF0YVRlbXBsYXRlID0gKGxheW91dC50ZW1wbGF0ZSB8fCB7fSkuZGF0YSB8fCB7fTtcbiAgICB2YXIgdGVtcGxhdGVyID0gVGVtcGxhdGUudHJhY2VUZW1wbGF0ZXIoZGF0YVRlbXBsYXRlKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGRhdGFJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGRhdGFJbltpXTtcblxuICAgICAgICAvLyByZXVzZSB1aWQgd2UgbWF5IGhhdmUgcHVsbGVkIG91dCBvZiBvbGRGdWxsRGF0YVxuICAgICAgICAvLyBOb3RlOiB0ZW1wbGF0ZXIgc3VwcGxpZXMgdHJhY2UgdHlwZVxuICAgICAgICBmdWxsVHJhY2UgPSB0ZW1wbGF0ZXIubmV3VHJhY2UodHJhY2UpO1xuICAgICAgICBmdWxsVHJhY2UudWlkID0gZnVsbExheW91dC5fdHJhY2VVaWRzW2ldO1xuICAgICAgICBwbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzKHRyYWNlLCBmdWxsVHJhY2UsIGNvbG9yQ250LCBmdWxsTGF5b3V0LCBpKTtcblxuICAgICAgICBmdWxsVHJhY2UuaW5kZXggPSBpO1xuICAgICAgICBmdWxsVHJhY2UuX2lucHV0ID0gdHJhY2U7XG4gICAgICAgIGZ1bGxUcmFjZS5fZXhwYW5kZWRJbmRleCA9IGNudDtcblxuICAgICAgICBpZihmdWxsVHJhY2UudHJhbnNmb3JtcyAmJiBmdWxsVHJhY2UudHJhbnNmb3Jtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBzZEludmlzaWJsZSA9IHRyYWNlLnZpc2libGUgIT09IGZhbHNlICYmIGZ1bGxUcmFjZS52aXNpYmxlID09PSBmYWxzZTtcblxuICAgICAgICAgICAgdmFyIGV4cGFuZGVkVHJhY2VzID0gYXBwbHlUcmFuc2Zvcm1zKGZ1bGxUcmFjZSwgZGF0YU91dCwgbGF5b3V0LCBmdWxsTGF5b3V0KTtcblxuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGV4cGFuZGVkVHJhY2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4cGFuZGVkVHJhY2UgPSBleHBhbmRlZFRyYWNlc1tqXTtcblxuICAgICAgICAgICAgICAgIC8vIE5vIGZ1cnRoZXIgdGVtcGxhdGluZyBkdXJpbmcgdHJhbnNmb3Jtcy5cbiAgICAgICAgICAgICAgICB2YXIgZnVsbEV4cGFuZGVkVHJhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgIF90ZW1wbGF0ZTogZnVsbFRyYWNlLl90ZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogZnVsbFRyYWNlLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIC8vIHNldCB1aWQgdXNpbmcgcGFyZW50IHVpZCBhbmQgZXhwYW5kZWQgaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgLy8gdG8gcHJvbW90ZSBjb25zaXN0ZW5jeSBiZXR3ZWVuIHVwZGF0ZSBjYWxsc1xuICAgICAgICAgICAgICAgICAgICB1aWQ6IGZ1bGxUcmFjZS51aWQgKyBqXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBzdXBwbHlEZWZhdWx0cyBjcmVhdGVkIGB2aXNpYmxlOiBmYWxzZWAsXG4gICAgICAgICAgICAgICAgLy8gY2xlYXIgaXQgYmVmb3JlIHJ1bm5pbmcgc3VwcGx5RGVmYXVsdHMgYSBzZWNvbmQgdGltZSxcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHNvbWV0aW1lcyB0aGVyZSBhcmUgaXRlbXMgd2Ugc3RpbGwgd2FudCB0byBjb2VyY2VcbiAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdHJhY2UgbW9kdWxlcyBiZWZvcmUgZGV0ZXJtaW5pbmcgdGhhdCB0aGUgdHJhY2UgaXNcbiAgICAgICAgICAgICAgICAvLyBhZ2FpbiBgdmlzaWJsZTogZmFsc2VgLCBmb3IgZXhhbXBsZSBwYXJ0aWFsIHZpc2liaWxpdGllc1xuICAgICAgICAgICAgICAgIC8vIGluIGBzcGxvbWAgdHJhY2VzLlxuICAgICAgICAgICAgICAgIGlmKHNkSW52aXNpYmxlICYmIGV4cGFuZGVkVHJhY2UudmlzaWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV4cGFuZGVkVHJhY2UudmlzaWJsZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzKGV4cGFuZGVkVHJhY2UsIGZ1bGxFeHBhbmRlZFRyYWNlLCBjbnQsIGZ1bGxMYXlvdXQsIGkpO1xuXG4gICAgICAgICAgICAgICAgLy8gcmVsaW5rIHByaXZhdGUgKGkuZS4gdW5kZXJzY29yZSkga2V5cyBleHBhbmRlZCB0cmFjZSB0byBmdWxsIGV4cGFuZGVkIHRyYWNlIHNvXG4gICAgICAgICAgICAgICAgLy8gdGhhdCB0cmFuc2Zvcm0gc3VwcGx5LWRlZmF1bHQgbWV0aG9kcyBjYW4gc2V0IF8ga2V5cyBmb3IgZnV0dXJlIHVzZS5cbiAgICAgICAgICAgICAgICByZWxpbmtQcml2YXRlS2V5cyhmdWxsRXhwYW5kZWRUcmFjZSwgZXhwYW5kZWRUcmFjZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgaW5mbyBhYm91dCBwYXJlbnQgZGF0YSB0cmFjZVxuICAgICAgICAgICAgICAgIGZ1bGxFeHBhbmRlZFRyYWNlLmluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5faW5wdXQgPSB0cmFjZTtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZnVsbElucHV0ID0gZnVsbFRyYWNlO1xuXG4gICAgICAgICAgICAgICAgLy8gYWRkIGluZm8gYWJvdXQgdGhlIGV4cGFuZGVkIGRhdGFcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZXhwYW5kZWRJbmRleCA9IGNudDtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZXhwYW5kZWRJbnB1dCA9IGV4cGFuZGVkVHJhY2U7XG5cbiAgICAgICAgICAgICAgICBwdXNoTW9kdWxlKGZ1bGxFeHBhbmRlZFRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFkZCBpZGVudGlmeSByZWZzIGZvciBjb25zaXN0ZW5jeSB3aXRoIHRyYW5zZm9ybWVkIHRyYWNlc1xuICAgICAgICAgICAgZnVsbFRyYWNlLl9mdWxsSW5wdXQgPSBmdWxsVHJhY2U7XG4gICAgICAgICAgICBmdWxsVHJhY2UuX2V4cGFuZGVkSW5wdXQgPSBmdWxsVHJhY2U7XG5cbiAgICAgICAgICAgIHB1c2hNb2R1bGUoZnVsbFRyYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAnY2FycGV0QXhpcycpKSB7XG4gICAgICAgICAgICBjYXJwZXRJbmRleFtmdWxsVHJhY2UuY2FycGV0XSA9IGZ1bGxUcmFjZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAnY2FycGV0RGVwZW5kZW50JykpIHtcbiAgICAgICAgICAgIGNhcnBldERlcGVuZGVudHMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGNhcnBldERlcGVuZGVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZnVsbFRyYWNlID0gZGF0YU91dFtjYXJwZXREZXBlbmRlbnRzW2ldXTtcblxuICAgICAgICBpZighZnVsbFRyYWNlLnZpc2libGUpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjYXJwZXRBeGlzID0gY2FycGV0SW5kZXhbZnVsbFRyYWNlLmNhcnBldF07XG4gICAgICAgIGZ1bGxUcmFjZS5fY2FycGV0ID0gY2FycGV0QXhpcztcblxuICAgICAgICBpZighY2FycGV0QXhpcyB8fCAhY2FycGV0QXhpcy52aXNpYmxlKSB7XG4gICAgICAgICAgICBmdWxsVHJhY2UudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBmdWxsVHJhY2UueGF4aXMgPSBjYXJwZXRBeGlzLnhheGlzO1xuICAgICAgICBmdWxsVHJhY2UueWF4aXMgPSBjYXJwZXRBeGlzLnlheGlzO1xuICAgIH1cbn07XG5cbnBsb3RzLnN1cHBseUFuaW1hdGlvbkRlZmF1bHRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAgIHZhciBpO1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShvcHRzIHx8IHt9LCBvcHRzT3V0LCBhbmltYXRpb25BdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdtb2RlJyk7XG4gICAgY29lcmNlKCdkaXJlY3Rpb24nKTtcbiAgICBjb2VyY2UoJ2Zyb21jdXJyZW50Jyk7XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9wdHMuZnJhbWUpKSB7XG4gICAgICAgIG9wdHNPdXQuZnJhbWUgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb3B0cy5mcmFtZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3B0c091dC5mcmFtZVtpXSA9IHBsb3RzLnN1cHBseUFuaW1hdGlvbkZyYW1lRGVmYXVsdHMob3B0cy5mcmFtZVtpXSB8fCB7fSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LmZyYW1lID0gcGxvdHMuc3VwcGx5QW5pbWF0aW9uRnJhbWVEZWZhdWx0cyhvcHRzLmZyYW1lIHx8IHt9KTtcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9wdHMudHJhbnNpdGlvbikpIHtcbiAgICAgICAgb3B0c091dC50cmFuc2l0aW9uID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9wdHMudHJhbnNpdGlvbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3B0c091dC50cmFuc2l0aW9uW2ldID0gcGxvdHMuc3VwcGx5QW5pbWF0aW9uVHJhbnNpdGlvbkRlZmF1bHRzKG9wdHMudHJhbnNpdGlvbltpXSB8fCB7fSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LnRyYW5zaXRpb24gPSBwbG90cy5zdXBwbHlBbmltYXRpb25UcmFuc2l0aW9uRGVmYXVsdHMob3B0cy50cmFuc2l0aW9uIHx8IHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0c091dDtcbn07XG5cbnBsb3RzLnN1cHBseUFuaW1hdGlvbkZyYW1lRGVmYXVsdHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gICAgdmFyIG9wdHNPdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKG9wdHMgfHwge30sIG9wdHNPdXQsIGFuaW1hdGlvbkF0dHJzLmZyYW1lLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2R1cmF0aW9uJyk7XG4gICAgY29lcmNlKCdyZWRyYXcnKTtcblxuICAgIHJldHVybiBvcHRzT3V0O1xufTtcblxucGxvdHMuc3VwcGx5QW5pbWF0aW9uVHJhbnNpdGlvbkRlZmF1bHRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShvcHRzIHx8IHt9LCBvcHRzT3V0LCBhbmltYXRpb25BdHRycy50cmFuc2l0aW9uLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2R1cmF0aW9uJyk7XG4gICAgY29lcmNlKCdlYXNpbmcnKTtcblxuICAgIHJldHVybiBvcHRzT3V0O1xufTtcblxucGxvdHMuc3VwcGx5RnJhbWVEZWZhdWx0cyA9IGZ1bmN0aW9uKGZyYW1lSW4pIHtcbiAgICB2YXIgZnJhbWVPdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGZyYW1lSW4sIGZyYW1lT3V0LCBmcmFtZUF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2dyb3VwJyk7XG4gICAgY29lcmNlKCduYW1lJyk7XG4gICAgY29lcmNlKCd0cmFjZXMnKTtcbiAgICBjb2VyY2UoJ2Jhc2VmcmFtZScpO1xuICAgIGNvZXJjZSgnZGF0YScpO1xuICAgIGNvZXJjZSgnbGF5b3V0Jyk7XG5cbiAgICByZXR1cm4gZnJhbWVPdXQ7XG59O1xuXG5wbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGNvbG9ySW5kZXgsIGxheW91dCwgdHJhY2VJbkluZGV4KSB7XG4gICAgdmFyIGNvbG9yd2F5ID0gbGF5b3V0LmNvbG9yd2F5IHx8IENvbG9yLmRlZmF1bHRzO1xuICAgIHZhciBkZWZhdWx0Q29sb3IgPSBjb2xvcndheVtjb2xvckluZGV4ICUgY29sb3J3YXkubGVuZ3RoXTtcblxuICAgIHZhciBpO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIHBsb3RzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJyk7XG5cbiAgICBjb2VyY2UoJ3R5cGUnKTtcbiAgICBjb2VyY2UoJ25hbWUnLCBsYXlvdXQuX3RyYWNlV29yZCArICcgJyArIHRyYWNlSW5JbmRleCk7XG5cbiAgICAvLyB3ZSB3YW50IGV2ZW4gaW52aXNpYmxlIHRyYWNlcyB0byBtYWtlIHRoZWlyIHdvdWxkLWJlIHN1YnBsb3RzIHZpc2libGVcbiAgICAvLyBzbyBjb2VyY2UgdGhlIHN1YnBsb3QgaWQocykgbm93IG5vIG1hdHRlciB3aGF0XG4gICAgdmFyIF9tb2R1bGUgPSBwbG90cy5nZXRNb2R1bGUodHJhY2VPdXQpO1xuXG4gICAgdHJhY2VPdXQuX21vZHVsZSA9IF9tb2R1bGU7XG4gICAgaWYoX21vZHVsZSkge1xuICAgICAgICB2YXIgYmFzZVBsb3RNb2R1bGUgPSBfbW9kdWxlLmJhc2VQbG90TW9kdWxlO1xuICAgICAgICB2YXIgc3VicGxvdEF0dHIgPSBiYXNlUGxvdE1vZHVsZS5hdHRyO1xuICAgICAgICB2YXIgc3VicGxvdEF0dHJzID0gYmFzZVBsb3RNb2R1bGUuYXR0cmlidXRlcztcbiAgICAgICAgaWYoc3VicGxvdEF0dHIgJiYgc3VicGxvdEF0dHJzKSB7XG4gICAgICAgICAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXQuX3N1YnBsb3RzO1xuICAgICAgICAgICAgdmFyIHN1YnBsb3RJZCA9ICcnO1xuXG4gICAgICAgICAgICAvLyBUT0RPIC0gY3VycmVudGx5IGlmIHdlIGRyYXcgYW4gZW1wdHkgZ2wyZCBzdWJwbG90LCBpdCBkcmF3c1xuICAgICAgICAgICAgLy8gbm90aGluZyB0aGVuIGdldHMgc3R1Y2sgYW5kIHlvdSBjYW4ndCBnZXQgaXQgYmFjayB3aXRob3V0IG5ld1Bsb3RcbiAgICAgICAgICAgIC8vIHNvcnQgdGhpcyBvdXQgaW4gdGhlIHJlZ2wgcmVmYWN0b3I/IGJ1dCBmb3Igbm93IGp1c3QgZHJvcCBlbXB0eSBnbDJkIHN1YnBsb3RzXG4gICAgICAgICAgICBpZihiYXNlUGxvdE1vZHVsZS5uYW1lICE9PSAnZ2wyZCcgfHwgdmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoc3VicGxvdEF0dHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHN1YnBsb3RBdHRyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0cmkgPSBzdWJwbG90QXR0cltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxpID0gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgc3VicGxvdEF0dHJzLCBhdHRyaSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHN1YnBsb3RzW2F0dHJpXSkgTGliLnB1c2hVbmlxdWUoc3VicGxvdHNbYXR0cmldLCB2YWxpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnBsb3RJZCArPSB2YWxpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdWJwbG90SWQgPSBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBzdWJwbG90QXR0cnMsIHN1YnBsb3RBdHRyKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihzdWJwbG90c1tiYXNlUGxvdE1vZHVsZS5uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShzdWJwbG90c1tiYXNlUGxvdE1vZHVsZS5uYW1lXSwgc3VicGxvdElkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb2VyY2VVbmxlc3NQcnVuZWQoYXR0ciwgZGZsdCwgY2IpIHtcbiAgICAgICAgaWYoX21vZHVsZSAmJiAoYXR0ciBpbiBfbW9kdWxlLmF0dHJpYnV0ZXMpICYmIF9tb2R1bGUuYXR0cmlidXRlc1thdHRyXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBQcnVuZWRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGNiICYmIHR5cGVvZiBjYiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvZXJjZShhdHRyLCBkZmx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdjdXN0b21kYXRhJyk7XG4gICAgICAgIGNvZXJjZSgnaWRzJyk7XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZU91dCwgJ3Nob3dMZWdlbmQnKSkge1xuICAgICAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvZXJjZSgnc2hvd2xlZ2VuZCcpO1xuICAgICAgICAgICAgY29lcmNlKCdsZWdlbmRncm91cCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2VVbmxlc3NQcnVuZWQoJ2hvdmVybGFiZWwnLCAnJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoXG4gICAgICAgICAgICAgICAgJ2Z4JyxcbiAgICAgICAgICAgICAgICAnc3VwcGx5RGVmYXVsdHMnXG4gICAgICAgICAgICApKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRPRE8gYWRkIHBlci1iYXNlLXBsb3QtbW9kdWxlIHRyYWNlIGRlZmF1bHRzIHN0ZXBcblxuICAgICAgICBpZihfbW9kdWxlKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCk7XG4gICAgICAgICAgICBMaWIuY29lcmNlSG92ZXJpbmZvKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIVJlZ2lzdHJ5LnRyYWNlSXModHJhY2VPdXQsICdub09wYWNpdHknKSkgY29lcmNlKCdvcGFjaXR5Jyk7XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZU91dCwgJ25vdExlZ2VuZElzb2xhdGFibGUnKSkge1xuICAgICAgICAgICAgLy8gVGhpcyBjbGVhcnMgb3V0IHRoZSBsZWdlbmRvbmx5IHN0YXRlIGZvciB0cmFjZXMgbGlrZSBjYXJwZXQgdGhhdFxuICAgICAgICAgICAgLy8gY2Fubm90IGJlIGlzb2xhdGVkIGluIHRoZSBsZWdlbmRcbiAgICAgICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSAhIXRyYWNlT3V0LnZpc2libGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuc2VsZWN0UG9pbnRzKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkcG9pbnRzJyk7XG4gICAgICAgIH1cblxuICAgICAgICBwbG90cy5zdXBwbHlUcmFuc2Zvcm1EZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhY2VPdXQ7XG59O1xuXG4vKipcbiAqIGhhc01ha2VzRGF0YVRyYW5zZm9ybTogZG9lcyB0aGlzIHRyYWNlIGhhdmUgYSB0cmFuc2Zvcm0gdGhhdCBtYWtlcyBpdHMgb3duXG4gKiBkYXRhLCBlaXRoZXIgYnkgZ3JhYmJpbmcgaXQgZnJvbSBzb21ld2hlcmUgZWxzZSBvciBieSBjcmVhdGluZyBpdCBmcm9tIGlucHV0XG4gKiBwYXJhbWV0ZXJzPyBJZiBzbywgd2Ugc2hvdWxkIHN0aWxsIGtlZXAgZ29pbmcgd2l0aCBzdXBwbHlEZWZhdWx0c1xuICogZXZlbiBpZiB0aGUgdHJhY2UgaXMgaW52aXNpYmxlLCB3aGljaCBtYXkganVzdCBiZSBiZWNhdXNlIGl0IGhhcyBubyBkYXRhIHlldC5cbiAqL1xuZnVuY3Rpb24gaGFzTWFrZXNEYXRhVHJhbnNmb3JtKHRyYWNlKSB7XG4gICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zO1xuICAgIGlmKEFycmF5LmlzQXJyYXkodHJhbnNmb3JtcykgJiYgdHJhbnNmb3Jtcy5sZW5ndGgpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aSA9IHRyYW5zZm9ybXNbaV07XG4gICAgICAgICAgICB2YXIgX21vZHVsZSA9IHRpLl9tb2R1bGUgfHwgdHJhbnNmb3Jtc1JlZ2lzdHJ5W3RpLnR5cGVdO1xuICAgICAgICAgICAgaWYoX21vZHVsZSAmJiBfbW9kdWxlLm1ha2VzRGF0YSkgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5wbG90cy5oYXNNYWtlc0RhdGFUcmFuc2Zvcm0gPSBoYXNNYWtlc0RhdGFUcmFuc2Zvcm07XG5cbnBsb3RzLnN1cHBseVRyYW5zZm9ybURlZmF1bHRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCkge1xuICAgIC8vIEZvciBub3cgd2Ugb25seSBhbGxvdyB0cmFuc2Zvcm1zIG9uIDFEIHRyYWNlcywgaWUgdGhvc2UgdGhhdCBzcGVjaWZ5IGEgX2xlbmd0aC5cbiAgICAvLyBJZiB3ZSB3ZXJlIHRvIGltcGxlbWVudCAyRCB0cmFuc2Zvcm1zLCB3ZSdkIG5lZWQgdG8gaGF2ZSBlYWNoIHRyYW5zZm9ybVxuICAgIC8vIGRlc2NyaWJlIGl0cyBvd24gYXBwbGljYWJpbGl0eSBhbmQgZGlzYWJsZSBpdHNlbGYgd2hlbiBpdCBkb2Vzbid0IGFwcGx5LlxuICAgIC8vIEFsc28gYWxsb3cgdHJhbnNmb3JtcyB0aGF0IG1ha2UgdGhlaXIgb3duIGRhdGEsIGJ1dCBub3QgaW4gZ2xvYmFsVHJhbnNmb3Jtc1xuICAgIGlmKCEodHJhY2VPdXQuX2xlbmd0aCB8fCBoYXNNYWtlc0RhdGFUcmFuc2Zvcm0odHJhY2VJbikpKSByZXR1cm47XG5cbiAgICB2YXIgZ2xvYmFsVHJhbnNmb3JtcyA9IGxheW91dC5fZ2xvYmFsVHJhbnNmb3JtcyB8fCBbXTtcbiAgICB2YXIgdHJhbnNmb3JtTW9kdWxlcyA9IGxheW91dC5fdHJhbnNmb3JtTW9kdWxlcyB8fCBbXTtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRyYWNlSW4udHJhbnNmb3JtcykgJiYgZ2xvYmFsVHJhbnNmb3Jtcy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIHZhciBjb250YWluZXJJbiA9IHRyYWNlSW4udHJhbnNmb3JtcyB8fCBbXSxcbiAgICAgICAgdHJhbnNmb3JtTGlzdCA9IGdsb2JhbFRyYW5zZm9ybXMuY29uY2F0KGNvbnRhaW5lckluKSxcbiAgICAgICAgY29udGFpbmVyT3V0ID0gdHJhY2VPdXQudHJhbnNmb3JtcyA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybUluID0gdHJhbnNmb3JtTGlzdFtpXSxcbiAgICAgICAgICAgIHR5cGUgPSB0cmFuc2Zvcm1Jbi50eXBlLFxuICAgICAgICAgICAgX21vZHVsZSA9IHRyYW5zZm9ybXNSZWdpc3RyeVt0eXBlXSxcbiAgICAgICAgICAgIHRyYW5zZm9ybU91dDtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBTdXBwbHkgZGVmYXVsdHMgbWF5IHJ1biB0d2ljZS4gRmlyc3QgcGFzcyBydW5zIGFsbCBzdXBwbHkgZGVmYXVsdHMgc3RlcHNcbiAgICAgICAgICogYW5kIGFkZHMgdGhlIF9tb2R1bGUgdG8gYW55IG91dHB1dCB0cmFuc2Zvcm1zLlxuICAgICAgICAgKiBJZiB0cmFuc2Zvcm1zIGV4aXN0IGFub3RoZXIgcGFzcyBpcyBydW4gc28gdGhhdCBhbnkgZ2VuZXJhdGVkIHRyYWNlcyBhbHNvXG4gICAgICAgICAqIGdvIHRocm91Z2ggc3VwcGx5IGRlZmF1bHRzLiBUaGlzIGhhcyB0aGUgZWZmZWN0IG9mIHJlcnVubmluZ1xuICAgICAgICAgKiBzdXBwbHlUcmFuc2Zvcm1EZWZhdWx0cy4gSWYgdGhlIHRyYW5zZm9ybSBkb2VzIG5vdCBoYXZlIGEgYHRyYW5zZm9ybWBcbiAgICAgICAgICogZnVuY3Rpb24gaXQgY291bGQgbm90IGhhdmUgZ2VuZXJhdGVkIGFueSBuZXcgdHJhY2VzIGFuZCB0aGUgc2Vjb25kIHN0YWdlXG4gICAgICAgICAqIGlzIHVubmVjZXNzYXJ5LiBXZSBkZXRlY3QgdGhpcyBjYXNlIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgaXNGaXJzdFN0YWdlID0gISh0cmFuc2Zvcm1Jbi5fbW9kdWxlICYmIHRyYW5zZm9ybUluLl9tb2R1bGUgPT09IF9tb2R1bGUpLFxuICAgICAgICAgICAgZG9MYXRlclN0YWdlcyA9IF9tb2R1bGUgJiYgdHlwZW9mIF9tb2R1bGUudHJhbnNmb3JtID09PSAnZnVuY3Rpb24nO1xuXG4gICAgICAgIGlmKCFfbW9kdWxlKSBMaWIud2FybignVW5yZWNvZ25pemVkIHRyYW5zZm9ybSB0eXBlICcgKyB0eXBlICsgJy4nKTtcblxuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuc3VwcGx5RGVmYXVsdHMgJiYgKGlzRmlyc3RTdGFnZSB8fCBkb0xhdGVyU3RhZ2VzKSkge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0ID0gX21vZHVsZS5zdXBwbHlEZWZhdWx0cyh0cmFuc2Zvcm1JbiwgdHJhY2VPdXQsIGxheW91dCwgdHJhY2VJbik7XG4gICAgICAgICAgICB0cmFuc2Zvcm1PdXQudHlwZSA9IHR5cGU7XG4gICAgICAgICAgICB0cmFuc2Zvcm1PdXQuX21vZHVsZSA9IF9tb2R1bGU7XG5cbiAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHRyYW5zZm9ybU1vZHVsZXMsIF9tb2R1bGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0ID0gTGliLmV4dGVuZEZsYXQoe30sIHRyYW5zZm9ybUluKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRhaW5lck91dC5wdXNoKHRyYW5zZm9ybU91dCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gYXBwbHlUcmFuc2Zvcm1zKGZ1bGxUcmFjZSwgZnVsbERhdGEsIGxheW91dCwgZnVsbExheW91dCkge1xuICAgIHZhciBjb250YWluZXIgPSBmdWxsVHJhY2UudHJhbnNmb3JtcyxcbiAgICAgICAgZGF0YU91dCA9IFtmdWxsVHJhY2VdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbnRhaW5lci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtID0gY29udGFpbmVyW2ldLFxuICAgICAgICAgICAgX21vZHVsZSA9IHRyYW5zZm9ybXNSZWdpc3RyeVt0cmFuc2Zvcm0udHlwZV07XG5cbiAgICAgICAgaWYoX21vZHVsZSAmJiBfbW9kdWxlLnRyYW5zZm9ybSkge1xuICAgICAgICAgICAgZGF0YU91dCA9IF9tb2R1bGUudHJhbnNmb3JtKGRhdGFPdXQsIHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgICAgICAgICAgICBmdWxsVHJhY2U6IGZ1bGxUcmFjZSxcbiAgICAgICAgICAgICAgICBmdWxsRGF0YTogZnVsbERhdGEsXG4gICAgICAgICAgICAgICAgbGF5b3V0OiBsYXlvdXQsXG4gICAgICAgICAgICAgICAgZnVsbExheW91dDogZnVsbExheW91dCxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1JbmRleDogaVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YU91dDtcbn1cblxucGxvdHMuc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHMgPSBmdW5jdGlvbihsYXlvdXRJbiwgbGF5b3V0T3V0LCBmb3JtYXRPYmopIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXlvdXRJbiwgbGF5b3V0T3V0LCBwbG90cy5sYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdGVtcGxhdGUgPSBsYXlvdXRJbi50ZW1wbGF0ZTtcbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdCh0ZW1wbGF0ZSkpIHtcbiAgICAgICAgbGF5b3V0T3V0LnRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgICAgIGxheW91dE91dC5fdGVtcGxhdGUgPSB0ZW1wbGF0ZS5sYXlvdXQ7XG4gICAgICAgIGxheW91dE91dC5fZGF0YVRlbXBsYXRlID0gdGVtcGxhdGUuZGF0YTtcbiAgICB9XG5cbiAgICB2YXIgZ2xvYmFsRm9udCA9IExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnKTtcblxuICAgIGNvZXJjZSgndGl0bGUnLCBsYXlvdXRPdXQuX2RmbHRUaXRsZS5wbG90KTtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBnbG9iYWxGb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChnbG9iYWxGb250LnNpemUgKiAxLjQpLFxuICAgICAgICBjb2xvcjogZ2xvYmFsRm9udC5jb2xvclxuICAgIH0pO1xuXG4gICAgLy8gTWFrZSBzdXJlIHRoYXQgYXV0b3NpemUgaXMgZGVmYXVsdGVkIHRvICp0cnVlKlxuICAgIC8vIG9uIGxheW91dHMgd2l0aCBubyBzZXQgd2lkdGggYW5kIGhlaWdodCBmb3IgYmFja3dhcmQgY29tcGF0aWJseSxcbiAgICAvLyBpbiBwYXJ0aWN1bGFyIGh0dHBzOi8vcGxvdC5seS9qYXZhc2NyaXB0L3Jlc3BvbnNpdmUtZmx1aWQtbGF5b3V0L1xuICAgIC8vXG4gICAgLy8gQmVmb3JlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvNjM1ICxcbiAgICAvLyBsYXlvdXRzIHdpdGggbm8gc2V0IHdpZHRoIGFuZCBoZWlnaHQgd2VyZSBzZXQgdGVtcG9yYXJ5IHNldCB0byAnaW5pdGlhbCdcbiAgICAvLyB0byBwYXNzIHRocm91Z2ggdGhlIGF1dG9zaXplIHJvdXRpbmVcbiAgICAvL1xuICAgIC8vIFRoaXMgYmVoYXZpb3IgaXMgc3ViamVjdCB0byBjaGFuZ2UgaW4gdjIuXG4gICAgY29lcmNlKCdhdXRvc2l6ZScsICEobGF5b3V0SW4ud2lkdGggJiYgbGF5b3V0SW4uaGVpZ2h0KSk7XG5cbiAgICBjb2VyY2UoJ3dpZHRoJyk7XG4gICAgY29lcmNlKCdoZWlnaHQnKTtcbiAgICBjb2VyY2UoJ21hcmdpbi5sJyk7XG4gICAgY29lcmNlKCdtYXJnaW4ucicpO1xuICAgIGNvZXJjZSgnbWFyZ2luLnQnKTtcbiAgICBjb2VyY2UoJ21hcmdpbi5iJyk7XG4gICAgY29lcmNlKCdtYXJnaW4ucGFkJyk7XG4gICAgY29lcmNlKCdtYXJnaW4uYXV0b2V4cGFuZCcpO1xuXG4gICAgaWYobGF5b3V0SW4ud2lkdGggJiYgbGF5b3V0SW4uaGVpZ2h0KSBwbG90cy5zYW5pdGl6ZU1hcmdpbnMobGF5b3V0T3V0KTtcblxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZ3JpZCcsICdzaXplRGVmYXVsdHMnKShsYXlvdXRJbiwgbGF5b3V0T3V0KTtcblxuICAgIGNvZXJjZSgncGFwZXJfYmdjb2xvcicpO1xuXG4gICAgY29lcmNlKCdzZXBhcmF0b3JzJywgZm9ybWF0T2JqLmRlY2ltYWwgKyBmb3JtYXRPYmoudGhvdXNhbmRzKTtcbiAgICBjb2VyY2UoJ2hpZGVzb3VyY2VzJyk7XG5cbiAgICBjb2VyY2UoJ2NvbG9yd2F5Jyk7XG5cbiAgICBjb2VyY2UoJ2RhdGFyZXZpc2lvbicpO1xuXG4gICAgY29lcmNlKCdtb2RlYmFyLm9yaWVudGF0aW9uJyk7XG4gICAgY29lcmNlKCdtb2RlYmFyLmJnY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KGxheW91dE91dC5wYXBlcl9iZ2NvbG9yLCAwLjUpKTtcbiAgICB2YXIgbW9kZWJhckRlZmF1bHRDb2xvciA9IENvbG9yLmNvbnRyYXN0KENvbG9yLnJnYihsYXlvdXRPdXQubW9kZWJhci5iZ2NvbG9yKSk7XG4gICAgY29lcmNlKCdtb2RlYmFyLmNvbG9yJywgQ29sb3IuYWRkT3BhY2l0eShtb2RlYmFyRGVmYXVsdENvbG9yLCAwLjMpKTtcbiAgICBjb2VyY2UoJ21vZGViYXIuYWN0aXZlY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KG1vZGViYXJEZWZhdWx0Q29sb3IsIDAuNykpO1xuXG4gICAgLy8gZG8gbm90IGluY2x1ZGUgZGVmYXVsdHMgaW4gZnVsbExheW91dCB3aGVuIHVzZXJzIGRvIG5vdCBzZXQgdHJhbnNpdGlvblxuICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KGxheW91dEluLnRyYW5zaXRpb24pKSB7XG4gICAgICAgIGNvZXJjZSgndHJhbnNpdGlvbi5kdXJhdGlvbicpO1xuICAgICAgICBjb2VyY2UoJ3RyYW5zaXRpb24uZWFzaW5nJyk7XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKFxuICAgICAgICAnY2FsZW5kYXJzJyxcbiAgICAgICAgJ2hhbmRsZURlZmF1bHRzJ1xuICAgICkobGF5b3V0SW4sIGxheW91dE91dCwgJ2NhbGVuZGFyJyk7XG5cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoXG4gICAgICAgICdmeCcsXG4gICAgICAgICdzdXBwbHlMYXlvdXRHbG9iYWxEZWZhdWx0cydcbiAgICApKGxheW91dEluLCBsYXlvdXRPdXQsIGNvZXJjZSk7XG59O1xuXG5wbG90cy5wbG90QXV0b1NpemUgPSBmdW5jdGlvbiBwbG90QXV0b1NpemUoZ2QsIGxheW91dCwgZnVsbExheW91dCkge1xuICAgIHZhciBjb250ZXh0ID0gZ2QuX2NvbnRleHQgfHwge30sXG4gICAgICAgIGZyYW1lTWFyZ2lucyA9IGNvbnRleHQuZnJhbWVNYXJnaW5zLFxuICAgICAgICBuZXdXaWR0aCxcbiAgICAgICAgbmV3SGVpZ2h0O1xuXG4gICAgdmFyIGlzUGxvdERpdiA9IExpYi5pc1Bsb3REaXYoZ2QpO1xuXG4gICAgaWYoaXNQbG90RGl2KSBnZC5lbWl0KCdwbG90bHlfYXV0b3NpemUnKTtcblxuICAgIC8vIGVtYmVkZGVkIGluIGFuIGlmcmFtZSAtIGp1c3QgdGFrZSB0aGUgZnVsbCBpZnJhbWUgc2l6ZVxuICAgIC8vIGlmIHdlIGdldCB0byB0aGlzIHBvaW50LCB3aXRoIG5vIGFzcGVjdCByYXRpbyByZXN0cmljdGlvbnNcbiAgICBpZihjb250ZXh0LmZpbGxGcmFtZSkge1xuICAgICAgICBuZXdXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgICAgICBuZXdIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAgICAgLy8gc29tZWhvdyB3ZSBnZXQgYSBmZXcgZXh0cmEgcHggaGVpZ2h0IHNvbWV0aW1lcy4uLlxuICAgICAgICAvLyBqdXN0IGhpZGUgaXRcbiAgICAgICAgZG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gcGxvdGx5LmpzIC0gbGV0IHRoZSBkZXZlbG9wZXJzIGRvIHdoYXQgdGhleSB3YW50LCBlaXRoZXJcbiAgICAgICAgLy8gcHJvdmlkZSBoZWlnaHQgYW5kIHdpZHRoIGZvciB0aGUgY29udGFpbmVyIGRpdixcbiAgICAgICAgLy8gc3BlY2lmeSBzaXplIGluIGxheW91dCwgb3IgdGFrZSB0aGUgZGVmYXVsdHMsXG4gICAgICAgIC8vIGJ1dCBkb24ndCBlbmZvcmNlIGFueSByYXRpbyByZXN0cmljdGlvbnNcbiAgICAgICAgdmFyIGNvbXB1dGVkU3R5bGUgPSBpc1Bsb3REaXYgPyB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShnZCkgOiB7fTtcblxuICAgICAgICBuZXdXaWR0aCA9IHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZS53aWR0aCkgfHwgcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlLm1heFdpZHRoKSB8fCBmdWxsTGF5b3V0LndpZHRoO1xuICAgICAgICBuZXdIZWlnaHQgPSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUuaGVpZ2h0KSB8fCBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUubWF4SGVpZ2h0KSB8fCBmdWxsTGF5b3V0LmhlaWdodDtcblxuICAgICAgICBpZihpc051bWVyaWMoZnJhbWVNYXJnaW5zKSAmJiBmcmFtZU1hcmdpbnMgPiAwKSB7XG4gICAgICAgICAgICB2YXIgZmFjdG9yID0gMSAtIDIgKiBmcmFtZU1hcmdpbnM7XG4gICAgICAgICAgICBuZXdXaWR0aCA9IE1hdGgucm91bmQoZmFjdG9yICogbmV3V2lkdGgpO1xuICAgICAgICAgICAgbmV3SGVpZ2h0ID0gTWF0aC5yb3VuZChmYWN0b3IgKiBuZXdIZWlnaHQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG1pbldpZHRoID0gcGxvdHMubGF5b3V0QXR0cmlidXRlcy53aWR0aC5taW4sXG4gICAgICAgIG1pbkhlaWdodCA9IHBsb3RzLmxheW91dEF0dHJpYnV0ZXMuaGVpZ2h0Lm1pbjtcbiAgICBpZihuZXdXaWR0aCA8IG1pbldpZHRoKSBuZXdXaWR0aCA9IG1pbldpZHRoO1xuICAgIGlmKG5ld0hlaWdodCA8IG1pbkhlaWdodCkgbmV3SGVpZ2h0ID0gbWluSGVpZ2h0O1xuXG4gICAgdmFyIHdpZHRoSGFzQ2hhbmdlZCA9ICFsYXlvdXQud2lkdGggJiZcbiAgICAgICAgICAgIChNYXRoLmFicyhmdWxsTGF5b3V0LndpZHRoIC0gbmV3V2lkdGgpID4gMSksXG4gICAgICAgIGhlaWdodEhhc0NoYW5nZWQgPSAhbGF5b3V0LmhlaWdodCAmJlxuICAgICAgICAgICAgKE1hdGguYWJzKGZ1bGxMYXlvdXQuaGVpZ2h0IC0gbmV3SGVpZ2h0KSA+IDEpO1xuXG4gICAgaWYoaGVpZ2h0SGFzQ2hhbmdlZCB8fCB3aWR0aEhhc0NoYW5nZWQpIHtcbiAgICAgICAgaWYod2lkdGhIYXNDaGFuZ2VkKSBmdWxsTGF5b3V0LndpZHRoID0gbmV3V2lkdGg7XG4gICAgICAgIGlmKGhlaWdodEhhc0NoYW5nZWQpIGZ1bGxMYXlvdXQuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgIH1cblxuICAgIC8vIGNhY2hlIGluaXRpYWwgYXV0b3NpemUgdmFsdWUsIHVzZWQgaW4gcmVsYXlvdXQgd2hlblxuICAgIC8vIHdpZHRoIG9yIGhlaWdodCB2YWx1ZXMgYXJlIHNldCB0byBudWxsXG4gICAgaWYoIWdkLl9pbml0aWFsQXV0b1NpemUpIHtcbiAgICAgICAgZ2QuX2luaXRpYWxBdXRvU2l6ZSA9IHsgd2lkdGg6IG5ld1dpZHRoLCBoZWlnaHQ6IG5ld0hlaWdodCB9O1xuICAgIH1cblxuICAgIHBsb3RzLnNhbml0aXplTWFyZ2lucyhmdWxsTGF5b3V0KTtcbn07XG5cbnBsb3RzLnN1cHBseUxheW91dE1vZHVsZURlZmF1bHRzID0gZnVuY3Rpb24obGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHRyYW5zaXRpb25EYXRhKSB7XG4gICAgdmFyIGNvbXBvbmVudHNSZWdpc3RyeSA9IFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeTtcbiAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gbGF5b3V0T3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG4gICAgdmFyIGNvbXBvbmVudCwgaSwgX21vZHVsZTtcblxuICAgIHZhciBDYXJ0ZXNpYW4gPSBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5LmNhcnRlc2lhbjtcblxuICAgIC8vIGNoZWNrIGlmIGFueSBjb21wb25lbnRzIG5lZWQgdG8gYWRkIG1vcmUgYmFzZSBwbG90IG1vZHVsZXNcbiAgICAvLyB0aGF0IHdlcmVuJ3QgY2FwdHVyZWQgYnkgdHJhY2VzXG4gICAgZm9yKGNvbXBvbmVudCBpbiBjb21wb25lbnRzUmVnaXN0cnkpIHtcbiAgICAgICAgX21vZHVsZSA9IGNvbXBvbmVudHNSZWdpc3RyeVtjb21wb25lbnRdO1xuXG4gICAgICAgIGlmKF9tb2R1bGUuaW5jbHVkZUJhc2VQbG90KSB7XG4gICAgICAgICAgICBfbW9kdWxlLmluY2x1ZGVCYXNlUGxvdChsYXlvdXRJbiwgbGF5b3V0T3V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSAqYXQgbGVhc3QqIGhhdmUgc29tZSBjYXJ0ZXNpYW4gYXhlc1xuICAgIGlmKCFiYXNlUGxvdE1vZHVsZXMubGVuZ3RoKSB7XG4gICAgICAgIGJhc2VQbG90TW9kdWxlcy5wdXNoKENhcnRlc2lhbik7XG4gICAgfVxuXG4gICAgLy8gZW5zdXJlIGFsbCBjYXJ0ZXNpYW4gYXhlcyBoYXZlIGF0IGxlYXN0IG9uZSBzdWJwbG90XG4gICAgaWYobGF5b3V0T3V0Ll9oYXMoJ2NhcnRlc2lhbicpKSB7XG4gICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZ3JpZCcsICdjb250ZW50RGVmYXVsdHMnKShsYXlvdXRJbiwgbGF5b3V0T3V0KTtcbiAgICAgICAgQ2FydGVzaWFuLmZpbmFsaXplU3VicGxvdHMobGF5b3V0SW4sIGxheW91dE91dCk7XG4gICAgfVxuXG4gICAgLy8gc29ydCBzdWJwbG90IGxpc3RzXG4gICAgZm9yKHZhciBzdWJwbG90VHlwZSBpbiBsYXlvdXRPdXQuX3N1YnBsb3RzKSB7XG4gICAgICAgIGxheW91dE91dC5fc3VicGxvdHNbc3VicGxvdFR5cGVdLnNvcnQoTGliLnN1YnBsb3RTb3J0KTtcbiAgICB9XG5cbiAgICAvLyBiYXNlIHBsb3QgbW9kdWxlIGxheW91dCBkZWZhdWx0c1xuICAgIGZvcihpID0gMDsgaSA8IGJhc2VQbG90TW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gYmFzZVBsb3RNb2R1bGVzW2ldO1xuXG4gICAgICAgIC8vIGUuZy4gcGllIGRvZXMgbm90IGhhdmUgYSBsYXlvdXQtZGVmYXVsdHMgc3RlcFxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRyYWNlIG1vZHVsZSBsYXlvdXQgZGVmYXVsdHNcbiAgICAvLyB1c2UgX21vZHVsZXMgcmF0aGVyIHRoYW4gX3Zpc2libGVNb2R1bGVzIHNvIHRoYXQgZXZlblxuICAgIC8vIGxlZ2VuZG9ubHkgdHJhY2VzIGNhbiBpbmNsdWRlIHNldHRpbmdzIC0gZWcgYmFybW9kZSwgd2hpY2ggYWZmZWN0c1xuICAgIC8vIGxlZ2VuZC50cmFjZW9yZGVyIGRlZmF1bHQgdmFsdWUuXG4gICAgdmFyIG1vZHVsZXMgPSBsYXlvdXRPdXQuX21vZHVsZXM7XG4gICAgZm9yKGkgPSAwOyBpIDwgbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gbW9kdWxlc1tpXTtcblxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRyYW5zZm9ybSBtb2R1bGUgbGF5b3V0IGRlZmF1bHRzXG4gICAgdmFyIHRyYW5zZm9ybU1vZHVsZXMgPSBsYXlvdXRPdXQuX3RyYW5zZm9ybU1vZHVsZXM7XG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhbnNmb3JtTW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gdHJhbnNmb3JtTW9kdWxlc1tpXTtcblxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCB0cmFuc2l0aW9uRGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoY29tcG9uZW50IGluIGNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBfbW9kdWxlID0gY29tcG9uZW50c1JlZ2lzdHJ5W2NvbXBvbmVudF07XG5cbiAgICAgICAgaWYoX21vZHVsZS5zdXBwbHlMYXlvdXREZWZhdWx0cykge1xuICAgICAgICAgICAgX21vZHVsZS5zdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBSZW1vdmUgYWxsIHBsb3RseSBhdHRyaWJ1dGVzIGZyb20gYSBkaXYgc28gaXQgY2FuIGJlIHJlcGxvdHRlZCBmcmVzaFxuLy8gVE9ETzogdGhlc2UgcmVhbGx5IG5lZWQgdG8gYmUgZW5jYXBzdWxhdGVkIGludG8gYSBtdWNoIHNtYWxsZXIgc2V0Li4uXG5wbG90cy5wdXJnZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgLy8gbm90ZTogd2UgRE8gTk9UIHJlbW92ZSBfY29udGV4dCBiZWNhdXNlIGl0IGRvZXNuJ3QgY2hhbmdlIHdoZW4gd2UgaW5zZXJ0XG4gICAgLy8gYSBuZXcgcGxvdCwgYW5kIG1heSBoYXZlIGJlZW4gc2V0IG91dHNpZGUgb2Ygb3VyIHNjb3BlLlxuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCB8fCB7fTtcbiAgICBpZihmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLnNlbGVjdEFsbCgnLmdsLWNhbnZhcycpLnJlbW92ZSgpO1xuICAgICAgICBmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lci5yZW1vdmUoKTtcbiAgICAgICAgZnVsbExheW91dC5fZ2xjYW52YXMgPSBudWxsO1xuICAgIH1cbiAgICBpZihmdWxsTGF5b3V0Ll9nZW9jb250YWluZXIgIT09IHVuZGVmaW5lZCkgZnVsbExheW91dC5fZ2VvY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgLy8gcmVtb3ZlIG1vZGViYXJcbiAgICBpZihmdWxsTGF5b3V0Ll9tb2RlQmFyKSBmdWxsTGF5b3V0Ll9tb2RlQmFyLmRlc3Ryb3koKTtcblxuICAgIGlmKGdkLl90cmFuc2l0aW9uRGF0YSkge1xuICAgICAgICAvLyBFbnN1cmUgYW55IGRhbmdsaW5nIGNhbGxiYWNrcyBhcmUgc2ltcGx5IGRyb3BwZWQgaWYgdGhlIHBsb3QgaXMgcHVyZ2VkLlxuICAgICAgICAvLyBUaGlzIGlzIG1vcmUgb3IgbGVzcyBvbmx5IGFjdHVhbGx5IGltcG9ydGFudCBmb3IgdGVzdGluZy5cbiAgICAgICAgaWYoZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLmxlbmd0aCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbkRhdGEuX2FuaW1hdGlvblJhZikge1xuICAgICAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKGdkLl90cmFuc2l0aW9uRGF0YS5fYW5pbWF0aW9uUmFmKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHJlbW92ZSBhbnkgcGxhbm5lZCB0aHJvdHRsZXNcbiAgICBMaWIuY2xlYXJUaHJvdHRsZSgpO1xuXG4gICAgLy8gcmVtb3ZlIHJlc3BvbnNpdmUgaGFuZGxlclxuICAgIExpYi5jbGVhclJlc3BvbnNpdmUoZ2QpO1xuXG4gICAgLy8gZGF0YSBhbmQgbGF5b3V0XG4gICAgZGVsZXRlIGdkLmRhdGE7XG4gICAgZGVsZXRlIGdkLmxheW91dDtcbiAgICBkZWxldGUgZ2QuX2Z1bGxEYXRhO1xuICAgIGRlbGV0ZSBnZC5fZnVsbExheW91dDtcbiAgICBkZWxldGUgZ2QuY2FsY2RhdGE7XG4gICAgZGVsZXRlIGdkLmZyYW1ld29yaztcbiAgICBkZWxldGUgZ2QuZW1wdHk7XG5cbiAgICBkZWxldGUgZ2QuZmlkO1xuXG4gICAgZGVsZXRlIGdkLnVuZG9xdWV1ZTsgLy8gYWN0aW9uIHF1ZXVlXG4gICAgZGVsZXRlIGdkLnVuZG9udW07XG4gICAgZGVsZXRlIGdkLmF1dG9wbGF5OyAvLyBhcmUgd2UgZG9pbmcgYW4gYWN0aW9uIHRoYXQgZG9lc24ndCBnbyBpbiB1bmRvIHF1ZXVlP1xuICAgIGRlbGV0ZSBnZC5jaGFuZ2VkO1xuXG4gICAgLy8gdGhlc2UgZ2V0IHJlY3JlYXRlZCBvbiBQbG90bHkucGxvdCBhbnl3YXksIGJ1dCBqdXN0IHRvIGJlIHNhZmVcbiAgICAvLyAoYW5kIHRvIGhhdmUgYSByZWNvcmQgb2YgdGhlbS4uLilcbiAgICBkZWxldGUgZ2QuX3Byb21pc2VzO1xuICAgIGRlbGV0ZSBnZC5fcmVkcmF3VGltZXI7XG4gICAgZGVsZXRlIGdkLl9obWx1bWNvdW50O1xuICAgIGRlbGV0ZSBnZC5faG1waXhjb3VudDtcbiAgICBkZWxldGUgZ2QuX3RyYW5zaXRpb25EYXRhO1xuICAgIGRlbGV0ZSBnZC5fdHJhbnNpdGlvbmluZztcbiAgICBkZWxldGUgZ2QuX2luaXRpYWxBdXRvU2l6ZTtcbiAgICBkZWxldGUgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb247XG5cbiAgICAvLyBjcmVhdGVkIGR1cmluZyBjZXJ0YWluIGV2ZW50cywgdGhhdCAqc2hvdWxkKiBjbGVhbiB0aGVtIHVwXG4gICAgLy8gdGhlbXNlbHZlcywgYnV0IG1heSBub3QgaWYgdGhlcmUgd2FzIGFuIGVycm9yXG4gICAgZGVsZXRlIGdkLl9kcmFnZ2luZztcbiAgICBkZWxldGUgZ2QuX2RyYWdnZWQ7XG4gICAgZGVsZXRlIGdkLl9ob3ZlcmRhdGE7XG4gICAgZGVsZXRlIGdkLl9zbmFwc2hvdEluUHJvZ3Jlc3M7XG4gICAgZGVsZXRlIGdkLl9lZGl0aW5nO1xuICAgIGRlbGV0ZSBnZC5fcmVwbG90UGVuZGluZztcbiAgICBkZWxldGUgZ2QuX21vdXNlRG93blRpbWU7XG4gICAgZGVsZXRlIGdkLl9sZWdlbmRNb3VzZURvd25UaW1lO1xuXG4gICAgLy8gcmVtb3ZlIGFsbCBldmVudCBsaXN0ZW5lcnNcbiAgICBpZihnZC5yZW1vdmVBbGxMaXN0ZW5lcnMpIGdkLnJlbW92ZUFsbExpc3RlbmVycygpO1xufTtcblxucGxvdHMuc3R5bGUgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBfbW9kdWxlcyA9IGdkLl9mdWxsTGF5b3V0Ll92aXNpYmxlTW9kdWxlcztcbiAgICB2YXIgc3R5bGVNb2R1bGVzID0gW107XG4gICAgdmFyIGk7XG5cbiAgICAvLyBzb21lIHRyYWNlIG1vZHVsZXMgcmV1c2UgdGhlIHNhbWUgc3R5bGUgbWV0aG9kLFxuICAgIC8vIG1ha2Ugc3VyZSB0byBub3QgdW5uZWNlc3NhcnkgY2FsbCB0aGVtIG11bHRpcGxlIHRpbWVzLlxuXG4gICAgZm9yKGkgPSAwOyBpIDwgX21vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBfbW9kdWxlc1tpXTtcbiAgICAgICAgaWYoX21vZHVsZS5zdHlsZSkge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoc3R5bGVNb2R1bGVzLCBfbW9kdWxlLnN0eWxlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IHN0eWxlTW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzdHlsZU1vZHVsZXNbaV0oZ2QpO1xuICAgIH1cbn07XG5cbnBsb3RzLnNhbml0aXplTWFyZ2lucyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICAvLyBwb2xhciBkb2Vzbid0IGRvIG1hcmdpbnMuLi5cbiAgICBpZighZnVsbExheW91dCB8fCAhZnVsbExheW91dC5tYXJnaW4pIHJldHVybjtcblxuICAgIHZhciB3aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGgsXG4gICAgICAgIGhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0LFxuICAgICAgICBtYXJnaW4gPSBmdWxsTGF5b3V0Lm1hcmdpbixcbiAgICAgICAgcGxvdFdpZHRoID0gd2lkdGggLSAobWFyZ2luLmwgKyBtYXJnaW4uciksXG4gICAgICAgIHBsb3RIZWlnaHQgPSBoZWlnaHQgLSAobWFyZ2luLnQgKyBtYXJnaW4uYiksXG4gICAgICAgIGNvcnJlY3Rpb247XG5cbiAgICAvLyBpZiBtYXJnaW4ubCArIG1hcmdpbi5yID0gMCB0aGVuIHBsb3RXaWR0aCA+IDBcbiAgICAvLyBhcyB3aWR0aCA+PSAxMCBieSBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIHNpbWlsYXJseSBmb3IgbWFyZ2luLnQgKyBtYXJnaW4uYlxuXG4gICAgaWYocGxvdFdpZHRoIDwgMCkge1xuICAgICAgICBjb3JyZWN0aW9uID0gKHdpZHRoIC0gMSkgLyAobWFyZ2luLmwgKyBtYXJnaW4ucik7XG4gICAgICAgIG1hcmdpbi5sID0gTWF0aC5mbG9vcihjb3JyZWN0aW9uICogbWFyZ2luLmwpO1xuICAgICAgICBtYXJnaW4uciA9IE1hdGguZmxvb3IoY29ycmVjdGlvbiAqIG1hcmdpbi5yKTtcbiAgICB9XG5cbiAgICBpZihwbG90SGVpZ2h0IDwgMCkge1xuICAgICAgICBjb3JyZWN0aW9uID0gKGhlaWdodCAtIDEpIC8gKG1hcmdpbi50ICsgbWFyZ2luLmIpO1xuICAgICAgICBtYXJnaW4udCA9IE1hdGguZmxvb3IoY29ycmVjdGlvbiAqIG1hcmdpbi50KTtcbiAgICAgICAgbWFyZ2luLmIgPSBNYXRoLmZsb29yKGNvcnJlY3Rpb24gKiBtYXJnaW4uYik7XG4gICAgfVxufTtcblxucGxvdHMuY2xlYXJBdXRvTWFyZ2luSWRzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBnZC5fZnVsbExheW91dC5fcHVzaG1hcmdpbklkcyA9IHt9O1xufTtcblxucGxvdHMuYWxsb3dBdXRvTWFyZ2luID0gZnVuY3Rpb24oZ2QsIGlkKSB7XG4gICAgZ2QuX2Z1bGxMYXlvdXQuX3B1c2htYXJnaW5JZHNbaWRdID0gMTtcbn07XG5cbmZ1bmN0aW9uIHNldHVwQXV0b01hcmdpbihmdWxsTGF5b3V0KSB7XG4gICAgaWYoIWZ1bGxMYXlvdXQuX3B1c2htYXJnaW4pIGZ1bGxMYXlvdXQuX3B1c2htYXJnaW4gPSB7fTtcbiAgICBpZighZnVsbExheW91dC5fcHVzaG1hcmdpbklkcykgZnVsbExheW91dC5fcHVzaG1hcmdpbklkcyA9IHt9O1xufVxuXG4vKipcbiAqIGF1dG9NYXJnaW46IGNhbGxlZCBieSBjb21wb25lbnRzIHRoYXQgbWF5IG5lZWQgdG8gZXhwYW5kIHRoZSBtYXJnaW5zIHRvXG4gKiBiZSByZW5kZXJlZCBvbi1wbG90LlxuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBhbiBpZGVudGlmaWVyIHVuaXF1ZSAod2l0aGluIHRoaXMgcGxvdCkgdG8gdGhpcyBvYmplY3QsXG4gKiAgICAgc28gd2UgY2FuIHJlbW92ZSBhIHByZXZpb3VzIG1hcmdpbiBleHBhbnNpb24gZnJvbSB0aGUgc2FtZSBvYmplY3QuXG4gKiBAcGFyYW0ge29iamVjdH0gbyAtIHRoZSBtYXJnaW4gcmVxdWlyZW1lbnRzIG9mIHRoaXMgb2JqZWN0LCBvciBvbWl0IHRvIGRlbGV0ZVxuICogICAgIHRoaXMgZW50cnkgKGxpa2UgaWYgaXQncyBoaWRkZW4pLiBLZXlzIGFyZTpcbiAqICAgICB4LCB5OiBwbG90IGZyYWN0aW9uIG9mIHRoZSBhbmNob3IgcG9pbnQuXG4gKiAgICAgeGwsIHhyLCB5dCwgeWI6IGlmIHRoZSBvYmplY3QgaGFzIGFuIGV4dGVudCBkZWZpbmVkIGluIHBsb3QgZnJhY3Rpb24sXG4gKiAgICAgICAgIHlvdSBjYW4gc3BlY2lmeSBib3RoIGVkZ2VzIGFzIHBsb3QgZnJhY3Rpb25zIGluIGVhY2ggZGltZW5zaW9uXG4gKiAgICAgbCwgciwgdCwgYjogdGhlIHBpeGVscyB0byBwYWQgcGFzdCB0aGUgcGxvdCBmcmFjdGlvbiB4W2x8cl0gYW5kIHlbdHxiXVxuICogICAgIHBhZDogZXh0cmEgcGl4ZWxzIHRvIGFkZCBpbiBhbGwgZGlyZWN0aW9ucywgZGVmYXVsdCAxMiAod2h5PylcbiAqL1xucGxvdHMuYXV0b01hcmdpbiA9IGZ1bmN0aW9uKGdkLCBpZCwgbykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBzZXR1cEF1dG9NYXJnaW4oZnVsbExheW91dCk7XG5cbiAgICB2YXIgcHVzaE1hcmdpbiA9IGZ1bGxMYXlvdXQuX3B1c2htYXJnaW47XG4gICAgdmFyIHB1c2hNYXJnaW5JZHMgPSBmdWxsTGF5b3V0Ll9wdXNobWFyZ2luSWRzO1xuXG4gICAgaWYoZnVsbExheW91dC5tYXJnaW4uYXV0b2V4cGFuZCAhPT0gZmFsc2UpIHtcbiAgICAgICAgaWYoIW8pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBwdXNoTWFyZ2luW2lkXTtcbiAgICAgICAgICAgIGRlbGV0ZSBwdXNoTWFyZ2luSWRzW2lkXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBwYWQgPSBvLnBhZDtcbiAgICAgICAgICAgIGlmKHBhZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hcmdpbiA9IGZ1bGxMYXlvdXQubWFyZ2luO1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vIGV4cGxpY2l0IHBhZCBpcyBnaXZlbiwgdXNlIDEycHggdW5sZXNzIHRoZXJlJ3MgYVxuICAgICAgICAgICAgICAgIC8vIHNwZWNpZmllZCBtYXJnaW4gdGhhdCdzIHNtYWxsZXIgdGhhbiB0aGF0XG4gICAgICAgICAgICAgICAgcGFkID0gTWF0aC5taW4oMTIsIG1hcmdpbi5sLCBtYXJnaW4uciwgbWFyZ2luLnQsIG1hcmdpbi5iKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaWYgdGhlIGl0ZW0gaXMgdG9vIGJpZywganVzdCBnaXZlIGl0IGVub3VnaCBhdXRvbWFyZ2luIHRvXG4gICAgICAgICAgICAvLyBtYWtlIHN1cmUgeW91IGNhbiBzdGlsbCBncmFiIGl0IGFuZCBicmluZyBpdCBiYWNrXG4gICAgICAgICAgICBpZihvLmwgKyBvLnIgPiBmdWxsTGF5b3V0LndpZHRoICogMC41KSBvLmwgPSBvLnIgPSAwO1xuICAgICAgICAgICAgaWYoby5iICsgby50ID4gZnVsbExheW91dC5oZWlnaHQgKiAwLjUpIG8uYiA9IG8udCA9IDA7XG5cbiAgICAgICAgICAgIHZhciB4bCA9IG8ueGwgIT09IHVuZGVmaW5lZCA/IG8ueGwgOiBvLng7XG4gICAgICAgICAgICB2YXIgeHIgPSBvLnhyICE9PSB1bmRlZmluZWQgPyBvLnhyIDogby54O1xuICAgICAgICAgICAgdmFyIHl0ID0gby55dCAhPT0gdW5kZWZpbmVkID8gby55dCA6IG8ueTtcbiAgICAgICAgICAgIHZhciB5YiA9IG8ueWIgIT09IHVuZGVmaW5lZCA/IG8ueWIgOiBvLnk7XG5cbiAgICAgICAgICAgIHB1c2hNYXJnaW5baWRdID0ge1xuICAgICAgICAgICAgICAgIGw6IHt2YWw6IHhsLCBzaXplOiBvLmwgKyBwYWR9LFxuICAgICAgICAgICAgICAgIHI6IHt2YWw6IHhyLCBzaXplOiBvLnIgKyBwYWR9LFxuICAgICAgICAgICAgICAgIGI6IHt2YWw6IHliLCBzaXplOiBvLmIgKyBwYWR9LFxuICAgICAgICAgICAgICAgIHQ6IHt2YWw6IHl0LCBzaXplOiBvLnQgKyBwYWR9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcHVzaE1hcmdpbklkc1tpZF0gPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZ1bGxMYXlvdXQuX3JlcGxvdHRpbmcpIHBsb3RzLmRvQXV0b01hcmdpbihnZCk7XG4gICAgfVxufTtcblxucGxvdHMuZG9BdXRvTWFyZ2luID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIGlmKCFmdWxsTGF5b3V0Ll9zaXplKSBmdWxsTGF5b3V0Ll9zaXplID0ge307XG4gICAgc2V0dXBBdXRvTWFyZ2luKGZ1bGxMYXlvdXQpO1xuXG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZSxcbiAgICAgICAgb2xkbWFyZ2lucyA9IEpTT04uc3RyaW5naWZ5KGdzKTtcblxuICAgIC8vIGFkanVzdCBtYXJnaW5zIGZvciBvdXRzaWRlIGNvbXBvbmVudHNcbiAgICAvLyBmdWxsTGF5b3V0Lm1hcmdpbiBpcyB0aGUgcmVxdWVzdGVkIG1hcmdpbixcbiAgICAvLyBmdWxsTGF5b3V0Ll9zaXplIGhhcyBtYXJnaW5zIGFuZCBwbG90c2l6ZSBhZnRlciBhZGp1c3RtZW50XG4gICAgdmFyIG1sID0gTWF0aC5tYXgoZnVsbExheW91dC5tYXJnaW4ubCB8fCAwLCAwKTtcbiAgICB2YXIgbXIgPSBNYXRoLm1heChmdWxsTGF5b3V0Lm1hcmdpbi5yIHx8IDAsIDApO1xuICAgIHZhciBtdCA9IE1hdGgubWF4KGZ1bGxMYXlvdXQubWFyZ2luLnQgfHwgMCwgMCk7XG4gICAgdmFyIG1iID0gTWF0aC5tYXgoZnVsbExheW91dC5tYXJnaW4uYiB8fCAwLCAwKTtcbiAgICB2YXIgcHVzaE1hcmdpbiA9IGZ1bGxMYXlvdXQuX3B1c2htYXJnaW47XG4gICAgdmFyIHB1c2hNYXJnaW5JZHMgPSBmdWxsTGF5b3V0Ll9wdXNobWFyZ2luSWRzO1xuXG4gICAgaWYoZnVsbExheW91dC5tYXJnaW4uYXV0b2V4cGFuZCAhPT0gZmFsc2UpIHtcblxuICAgICAgICBmb3IodmFyIGsgaW4gcHVzaE1hcmdpbikge1xuICAgICAgICAgICAgaWYoIXB1c2hNYXJnaW5JZHNba10pIGRlbGV0ZSBwdXNoTWFyZ2luW2tdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmlsbCBpbiB0aGUgcmVxdWVzdGVkIG1hcmdpbnNcbiAgICAgICAgcHVzaE1hcmdpbi5iYXNlID0ge1xuICAgICAgICAgICAgbDoge3ZhbDogMCwgc2l6ZTogbWx9LFxuICAgICAgICAgICAgcjoge3ZhbDogMSwgc2l6ZTogbXJ9LFxuICAgICAgICAgICAgdDoge3ZhbDogMSwgc2l6ZTogbXR9LFxuICAgICAgICAgICAgYjoge3ZhbDogMCwgc2l6ZTogbWJ9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gbm93IGN5Y2xlIHRocm91Z2ggYWxsIHRoZSBjb21iaW5hdGlvbnMgb2YgbCBhbmQgclxuICAgICAgICAvLyAoYW5kIHQgYW5kIGIpIHRvIGZpbmQgdGhlIHJlcXVpcmVkIG1hcmdpbnNcblxuICAgICAgICBmb3IodmFyIGsxIGluIHB1c2hNYXJnaW4pIHtcblxuICAgICAgICAgICAgdmFyIHB1c2hsZWZ0ID0gcHVzaE1hcmdpbltrMV0ubCB8fCB7fSxcbiAgICAgICAgICAgICAgICBwdXNoYm90dG9tID0gcHVzaE1hcmdpbltrMV0uYiB8fCB7fSxcbiAgICAgICAgICAgICAgICBmbCA9IHB1c2hsZWZ0LnZhbCxcbiAgICAgICAgICAgICAgICBwbCA9IHB1c2hsZWZ0LnNpemUsXG4gICAgICAgICAgICAgICAgZmIgPSBwdXNoYm90dG9tLnZhbCxcbiAgICAgICAgICAgICAgICBwYiA9IHB1c2hib3R0b20uc2l6ZTtcblxuICAgICAgICAgICAgZm9yKHZhciBrMiBpbiBwdXNoTWFyZ2luKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKHBsKSAmJiBwdXNoTWFyZ2luW2syXS5yKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmciA9IHB1c2hNYXJnaW5bazJdLnIudmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHIgPSBwdXNoTWFyZ2luW2syXS5yLnNpemU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoZnIgPiBmbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld2wgPSAocGwgKiBmciArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwciAtIGZ1bGxMYXlvdXQud2lkdGgpICogZmwpIC8gKGZyIC0gZmwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld3IgPSAocHIgKiAoMSAtIGZsKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwbCAtIGZ1bGxMYXlvdXQud2lkdGgpICogKDEgLSBmcikpIC8gKGZyIC0gZmwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYobmV3bCA+PSAwICYmIG5ld3IgPj0gMCAmJiBuZXdsICsgbmV3ciA+IG1sICsgbXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtbCA9IG5ld2w7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXIgPSBuZXdyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKHBiKSAmJiBwdXNoTWFyZ2luW2syXS50KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmdCA9IHB1c2hNYXJnaW5bazJdLnQudmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHQgPSBwdXNoTWFyZ2luW2syXS50LnNpemU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoZnQgPiBmYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld2IgPSAocGIgKiBmdCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwdCAtIGZ1bGxMYXlvdXQuaGVpZ2h0KSAqIGZiKSAvIChmdCAtIGZiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXd0ID0gKHB0ICogKDEgLSBmYikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocGIgLSBmdWxsTGF5b3V0LmhlaWdodCkgKiAoMSAtIGZ0KSkgLyAoZnQgLSBmYik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihuZXdiID49IDAgJiYgbmV3dCA+PSAwICYmIG5ld2IgKyBuZXd0ID4gbWIgKyBtdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1iID0gbmV3YjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdCA9IG5ld3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBncy5sID0gTWF0aC5yb3VuZChtbCk7XG4gICAgZ3MuciA9IE1hdGgucm91bmQobXIpO1xuICAgIGdzLnQgPSBNYXRoLnJvdW5kKG10KTtcbiAgICBncy5iID0gTWF0aC5yb3VuZChtYik7XG4gICAgZ3MucCA9IE1hdGgucm91bmQoZnVsbExheW91dC5tYXJnaW4ucGFkKTtcbiAgICBncy53ID0gTWF0aC5yb3VuZChmdWxsTGF5b3V0LndpZHRoKSAtIGdzLmwgLSBncy5yO1xuICAgIGdzLmggPSBNYXRoLnJvdW5kKGZ1bGxMYXlvdXQuaGVpZ2h0KSAtIGdzLnQgLSBncy5iO1xuXG4gICAgLy8gaWYgdGhpbmdzIGNoYW5nZWQgYW5kIHdlJ3JlIG5vdCBhbHJlYWR5IHJlZHJhd2luZywgdHJpZ2dlciBhIHJlZHJhd1xuICAgIGlmKCFmdWxsTGF5b3V0Ll9yZXBsb3R0aW5nICYmXG4gICAgICAgIG9sZG1hcmdpbnMgIT09ICd7fScgJiZcbiAgICAgICAgb2xkbWFyZ2lucyAhPT0gSlNPTi5zdHJpbmdpZnkoZnVsbExheW91dC5fc2l6ZSlcbiAgICApIHtcbiAgICAgICAgaWYoJ19yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50JyBpbiBmdWxsTGF5b3V0KSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50ID0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncGxvdCcsIGdkKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIEpTT05pZnkgdGhlIGdyYXBoIGRhdGEgYW5kIGxheW91dFxuICpcbiAqIFRoaXMgZnVuY3Rpb24gbmVlZHMgdG8gcmVjdXJzZSBiZWNhdXNlIHNvbWUgc3JjIGNhbiBiZSBpbnNpZGVcbiAqIHN1Yi1vYmplY3RzLlxuICpcbiAqIEl0IGFsc28gc3RyaXBzIG91dCBmdW5jdGlvbnMgYW5kIHByaXZhdGUgKHN0YXJ0cyB3aXRoIF8pIGVsZW1lbnRzLlxuICogVGhlcmVmb3JlLCB3ZSBjYW4gYWRkIHRlbXBvcmFyeSB0aGluZ3MgdG8gZGF0YSBhbmQgbGF5b3V0IHRoYXQgZG9uJ3RcbiAqIGdldCBzYXZlZC5cbiAqXG4gKiBAcGFyYW0gZ2QgVGhlIGdyYXBoRGl2XG4gKiBAcGFyYW0ge0Jvb2xlYW59IGRhdGFvbmx5IElmIHRydWUsIGRvbid0IHJldHVybiBsYXlvdXQuXG4gKiBAcGFyYW0geydrZWVwcmVmJ3wna2VlcGRhdGEnfCdrZWVwYWxsJ30gW21vZGU9J2tlZXByZWYnXSBGaWx0ZXIgd2hhdCdzIGtlcHRcbiAqICAgICAga2VlcHJlZjogcmVtb3ZlIGRhdGEgZm9yIHdoaWNoIHRoZXJlJ3MgYSBzcmMgcHJlc2VudFxuICogICAgICAgICAgZWcgaWYgdGhlcmUncyB4c3JjIHByZXNlbnQgKGFuZCB4c3JjIGlzIHdlbGwtZm9ybWVkLFxuICogICAgICAgICAgaWUgaGFzIDogYW5kIHNvbWUgY2hhcnMgYmVmb3JlIGl0KSwgc3RyaXAgb3V0IHhcbiAqICAgICAga2VlcGRhdGE6IHJlbW92ZSBhbGwgc3JjIHRhZ3MsIGRvbid0IHJlbW92ZSB0aGUgZGF0YSBpdHNlbGZcbiAqICAgICAga2VlcGFsbDoga2VlcCBkYXRhIGFuZCBzcmNcbiAqIEBwYXJhbSB7U3RyaW5nfSBvdXRwdXQgSWYgeW91IHNwZWNpZnkgJ29iamVjdCcsIHRoZSByZXN1bHQgd2lsbCBub3QgYmUgc3RyaW5naWZpZWRcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gdXNlRGVmYXVsdHMgSWYgdHJ1dGh5LCB1c2UgX2Z1bGxMYXlvdXQgYW5kIF9mdWxsRGF0YVxuICogQHJldHVybnMge09iamVjdHxTdHJpbmd9XG4gKi9cbnBsb3RzLmdyYXBoSnNvbiA9IGZ1bmN0aW9uKGdkLCBkYXRhb25seSwgbW9kZSwgb3V0cHV0LCB1c2VEZWZhdWx0cykge1xuICAgIC8vIGlmIHRoZSBkZWZhdWx0cyBhcmVuJ3Qgc3VwcGxpZWQgeWV0LCB3ZSBuZWVkIHRvIGRvIHRoYXQuLi5cbiAgICBpZigodXNlRGVmYXVsdHMgJiYgZGF0YW9ubHkgJiYgIWdkLl9mdWxsRGF0YSkgfHxcbiAgICAgICAgICAgICh1c2VEZWZhdWx0cyAmJiAhZGF0YW9ubHkgJiYgIWdkLl9mdWxsTGF5b3V0KSkge1xuICAgICAgICBwbG90cy5zdXBwbHlEZWZhdWx0cyhnZCk7XG4gICAgfVxuXG4gICAgdmFyIGRhdGEgPSAodXNlRGVmYXVsdHMpID8gZ2QuX2Z1bGxEYXRhIDogZ2QuZGF0YSxcbiAgICAgICAgbGF5b3V0ID0gKHVzZURlZmF1bHRzKSA/IGdkLl9mdWxsTGF5b3V0IDogZ2QubGF5b3V0LFxuICAgICAgICBmcmFtZXMgPSAoZ2QuX3RyYW5zaXRpb25EYXRhIHx8IHt9KS5fZnJhbWVzO1xuXG4gICAgZnVuY3Rpb24gc3RyaXBPYmooZCkge1xuICAgICAgICBpZih0eXBlb2YgZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QoZCkpIHtcbiAgICAgICAgICAgIHZhciBvID0ge30sIHYsIHNyYztcbiAgICAgICAgICAgIGZvcih2IGluIGQpIHtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgcHJpdmF0ZSBlbGVtZW50cyBhbmQgZnVuY3Rpb25zXG4gICAgICAgICAgICAgICAgLy8gXyBpcyBmb3IgcHJpdmF0ZSwgWyBpcyBhIG1pc3Rha2UgaWUgW29iamVjdCBPYmplY3RdXG4gICAgICAgICAgICAgICAgaWYodHlwZW9mIGRbdl0gPT09ICdmdW5jdGlvbicgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIFsnXycsICdbJ10uaW5kZXhPZih2LmNoYXJBdCgwKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGxvb2sgZm9yIHNyYy9kYXRhIG1hdGNoZXMgYW5kIHJlbW92ZSB0aGUgYXBwcm9wcmlhdGUgb25lXG4gICAgICAgICAgICAgICAgaWYobW9kZSA9PT0gJ2tlZXBkYXRhJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBrZWVwZGF0YTogcmVtb3ZlIGFsbCAuLi5zcmMgdGFnc1xuICAgICAgICAgICAgICAgICAgICBpZih2LnN1YnN0cih2Lmxlbmd0aCAtIDMpID09PSAnc3JjJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihtb2RlID09PSAna2VlcHN0cmVhbScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8ga2VlcCBzb3VyY2VkIGRhdGEgaWYgaXQncyBiZWluZyBzdHJlYW1lZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gc2ltaWxhciB0byBrZWVwcmVmLCBidXQgaWYgdGhlICdzdHJlYW0nIG9iamVjdCBleGlzdHNcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gYSB0cmFjZSwgd2Ugd2lsbCBrZWVwIHRoZSBkYXRhIGFycmF5LlxuICAgICAgICAgICAgICAgICAgICBzcmMgPSBkW3YgKyAnc3JjJ107XG4gICAgICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBzcmMgPT09ICdzdHJpbmcnICYmIHNyYy5pbmRleE9mKCc6JykgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QoZC5zdHJlYW0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihtb2RlICE9PSAna2VlcGFsbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8ga2VlcHJlZjogcmVtb3ZlIHNvdXJjZWQgZGF0YSBidXQgb25seVxuICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgc291cmNlIHRhZyBpcyB3ZWxsLWZvcm1lZFxuICAgICAgICAgICAgICAgICAgICBzcmMgPSBkW3YgKyAnc3JjJ107XG4gICAgICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBzcmMgPT09ICdzdHJpbmcnICYmIHNyYy5pbmRleE9mKCc6JykgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE9LLCB3ZSdyZSBpbmNsdWRpbmcgdGhpcy4uLiByZWN1cnNlIGludG8gaXRcbiAgICAgICAgICAgICAgICBvW3ZdID0gc3RyaXBPYmooZFt2XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBkLm1hcChzdHJpcE9iaik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KGQpKSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLnNpbXBsZU1hcChkLCBMaWIuaWRlbnRpdHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29udmVydCBuYXRpdmUgZGF0ZXMgdG8gZGF0ZSBzdHJpbmdzLi4uXG4gICAgICAgIC8vIG1vc3RseSBmb3IgZXh0ZXJuYWwgdXNlcnMgZXhwb3J0aW5nIHRvIHBsb3RseVxuICAgICAgICBpZihMaWIuaXNKU0RhdGUoZCkpIHJldHVybiBMaWIubXMyRGF0ZVRpbWVMb2NhbCgrZCk7XG5cbiAgICAgICAgcmV0dXJuIGQ7XG4gICAgfVxuXG4gICAgdmFyIG9iaiA9IHtcbiAgICAgICAgZGF0YTogKGRhdGEgfHwgW10pLm1hcChmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICB2YXIgZCA9IHN0cmlwT2JqKHYpO1xuICAgICAgICAgICAgLy8gZml0IGhhcyBzb21lIGxpdHRsZSBhcnJheXMgaW4gaXQgdGhhdCBkb24ndCBjb250YWluIGRhdGEsXG4gICAgICAgICAgICAvLyBqdXN0IGZpdCBwYXJhbXMgYW5kIG1ldGFcbiAgICAgICAgICAgIGlmKGRhdGFvbmx5KSB7IGRlbGV0ZSBkLmZpdDsgfVxuICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgIH0pXG4gICAgfTtcbiAgICBpZighZGF0YW9ubHkpIHsgb2JqLmxheW91dCA9IHN0cmlwT2JqKGxheW91dCk7IH1cblxuICAgIGlmKGdkLmZyYW1ld29yayAmJiBnZC5mcmFtZXdvcmsuaXNQb2xhcikgb2JqID0gZ2QuZnJhbWV3b3JrLmdldENvbmZpZygpO1xuXG4gICAgaWYoZnJhbWVzKSBvYmouZnJhbWVzID0gc3RyaXBPYmooZnJhbWVzKTtcblxuICAgIHJldHVybiAob3V0cHV0ID09PSAnb2JqZWN0JykgPyBvYmogOiBKU09OLnN0cmluZ2lmeShvYmopO1xufTtcblxuLyoqXG4gKiBNb2RpZnkgYSBrZXlmcmFtZSB1c2luZyBhIGxpc3Qgb2Ygb3BlcmF0aW9uczpcbiAqXG4gKiBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IG9wZXJhdGlvbnNcbiAqICAgICAgU2VxdWVuY2Ugb2Ygb3BlcmF0aW9ucyB0byBiZSBwZXJmb3JtZWQgb24gdGhlIGtleWZyYW1lc1xuICovXG5wbG90cy5tb2RpZnlGcmFtZXMgPSBmdW5jdGlvbihnZCwgb3BlcmF0aW9ucykge1xuICAgIHZhciBpLCBvcCwgZnJhbWU7XG4gICAgdmFyIF9mcmFtZXMgPSBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lcztcbiAgICB2YXIgX2ZyYW1lSGFzaCA9IGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgb3BlcmF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvcCA9IG9wZXJhdGlvbnNbaV07XG5cbiAgICAgICAgc3dpdGNoKG9wLnR5cGUpIHtcbiAgICAgICAgICAgIC8vIE5vIHJlYXNvbiB0aGlzIGNvdWxkbid0IGV4aXN0LCBidXQgaXMgY3VycmVudGx5IHVudXNlZC91bnRlc3RlZDpcbiAgICAgICAgICAgIC8qIGNhc2UgJ3JlbmFtZSc6XG4gICAgICAgICAgICAgICAgZnJhbWUgPSBfZnJhbWVzW29wLmluZGV4XTtcbiAgICAgICAgICAgICAgICBkZWxldGUgX2ZyYW1lSGFzaFtmcmFtZS5uYW1lXTtcbiAgICAgICAgICAgICAgICBfZnJhbWVIYXNoW29wLm5hbWVdID0gZnJhbWU7XG4gICAgICAgICAgICAgICAgZnJhbWUubmFtZSA9IG9wLm5hbWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7Ki9cbiAgICAgICAgICAgIGNhc2UgJ3JlcGxhY2UnOlxuICAgICAgICAgICAgICAgIGZyYW1lID0gb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgdmFyIG9sZE5hbWUgPSAoX2ZyYW1lc1tvcC5pbmRleF0gfHwge30pLm5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05hbWUgPSBmcmFtZS5uYW1lO1xuICAgICAgICAgICAgICAgIF9mcmFtZXNbb3AuaW5kZXhdID0gX2ZyYW1lSGFzaFtuZXdOYW1lXSA9IGZyYW1lO1xuXG4gICAgICAgICAgICAgICAgaWYobmV3TmFtZSAhPT0gb2xkTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBuYW1lIGhhcyBjaGFuZ2VkIGluIGFkZGl0aW9uIHRvIHJlcGxhY2VtZW50LCB0aGVuIHVwZGF0ZVxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9va3VwIHRhYmxlOlxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgX2ZyYW1lSGFzaFtvbGROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgX2ZyYW1lSGFzaFtuZXdOYW1lXSA9IGZyYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaW5zZXJ0JzpcbiAgICAgICAgICAgICAgICBmcmFtZSA9IG9wLnZhbHVlO1xuICAgICAgICAgICAgICAgIF9mcmFtZUhhc2hbZnJhbWUubmFtZV0gPSBmcmFtZTtcbiAgICAgICAgICAgICAgICBfZnJhbWVzLnNwbGljZShvcC5pbmRleCwgMCwgZnJhbWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZGVsZXRlJzpcbiAgICAgICAgICAgICAgICBmcmFtZSA9IF9mcmFtZXNbb3AuaW5kZXhdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBfZnJhbWVIYXNoW2ZyYW1lLm5hbWVdO1xuICAgICAgICAgICAgICAgIF9mcmFtZXMuc3BsaWNlKG9wLmluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cbi8qXG4gKiBDb21wdXRlIGEga2V5ZnJhbWUuIE1lcmdlIGEga2V5ZnJhbWUgaW50byBpdHMgYmFzZSBmcmFtZShzKSBhbmRcbiAqIGV4cGFuZCBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBmcmFtZUxvb2t1cFxuICogICAgICBBbiBvYmplY3QgY29udGFpbmluZyBmcmFtZXMga2V5ZWQgYnkgbmFtZSAoaS5lLiBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lSGFzaClcbiAqIEBwYXJhbSB7c3RyaW5nfSBmcmFtZVxuICogICAgICBUaGUgbmFtZSBvZiB0aGUga2V5ZnJhbWUgdG8gYmUgY29tcHV0ZWRcbiAqXG4gKiBSZXR1cm5zOiBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgbWVyZ2VkIGNvbnRlbnRcbiAqL1xucGxvdHMuY29tcHV0ZUZyYW1lID0gZnVuY3Rpb24oZ2QsIGZyYW1lTmFtZSkge1xuICAgIHZhciBmcmFtZUxvb2t1cCA9IGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoO1xuICAgIHZhciBpLCB0cmFjZUluZGljZXMsIHRyYWNlSW5kZXgsIGRlc3RJbmRleDtcblxuICAgIC8vIE51bGwgb3IgdW5kZWZpbmVkIHdpbGwgZmFpbCBvbiAudG9TdHJpbmcoKS4gV2UnbGwgYWxsb3cgbnVtYmVycyBzaW5jZSB3ZVxuICAgIC8vIG1ha2UgaXQgY2xlYXIgZnJhbWVzIG11c3QgYmUgZ2l2ZW4gc3RyaW5nIG5hbWVzLCBidXQgd2UnbGwgYWxsb3cgbnVtYmVyc1xuICAgIC8vIGhlcmUgc2luY2UgdGhleSdyZSBvdGhlcndpc2UgZmluZSBmb3IgbG9va2luZyB1cCBmcmFtZXMgYXMgbG9uZyBhcyB0aGV5J3JlXG4gICAgLy8gcHJvcGVybHkgY2FzdCB0byBzdHJpbmdzLiBXZSByZWFsbHkganVzdCB3YW50IHRvIGVuc3VyZSBoZXJlIHRoYXQgdGhpc1xuICAgIC8vIDEpIGRvZXNuJ3QgZmFpbCwgYW5kXG4gICAgLy8gMikgZG9lbnMndCBnaXZlIGFuIGluY29ycmVjdCBhbnN3ZXIgKHdoaWNoIFN0cmluZyhmcmFtZU5hbWUpIHdvdWxkKVxuICAgIGlmKCFmcmFtZU5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb21wdXRlRnJhbWUgbXVzdCBiZSBnaXZlbiBhIHN0cmluZyBmcmFtZSBuYW1lJyk7XG4gICAgfVxuXG4gICAgdmFyIGZyYW1lUHRyID0gZnJhbWVMb29rdXBbZnJhbWVOYW1lLnRvU3RyaW5nKCldO1xuXG4gICAgLy8gUmV0dXJuIGZhbHNlIGlmIHRoZSBuYW1lIGlzIGludmFsaWQ6XG4gICAgaWYoIWZyYW1lUHRyKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZnJhbWVTdGFjayA9IFtmcmFtZVB0cl07XG4gICAgdmFyIGZyYW1lTmFtZVN0YWNrID0gW2ZyYW1lUHRyLm5hbWVdO1xuXG4gICAgLy8gRm9sbG93IGZyYW1lIHBvaW50ZXJzOlxuICAgIHdoaWxlKGZyYW1lUHRyLmJhc2VmcmFtZSAmJiAoZnJhbWVQdHIgPSBmcmFtZUxvb2t1cFtmcmFtZVB0ci5iYXNlZnJhbWUudG9TdHJpbmcoKV0pKSB7XG4gICAgICAgIC8vIEF2b2lkIGluZmluaXRlIGxvb3BzOlxuICAgICAgICBpZihmcmFtZU5hbWVTdGFjay5pbmRleE9mKGZyYW1lUHRyLm5hbWUpICE9PSAtMSkgYnJlYWs7XG5cbiAgICAgICAgZnJhbWVTdGFjay5wdXNoKGZyYW1lUHRyKTtcbiAgICAgICAgZnJhbWVOYW1lU3RhY2sucHVzaChmcmFtZVB0ci5uYW1lKTtcbiAgICB9XG5cbiAgICAvLyBBIG5ldyBvYmplY3QgZm9yIHRoZSBtZXJnZWQgcmVzdWx0OlxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIC8vIE1lcmdlLCBzdGFydGluZyB3aXRoIHRoZSBsYXN0IGFuZCBlbmRpbmcgd2l0aCB0aGUgZGVzaXJlZCBmcmFtZTpcbiAgICB3aGlsZSgoZnJhbWVQdHIgPSBmcmFtZVN0YWNrLnBvcCgpKSkge1xuICAgICAgICBpZihmcmFtZVB0ci5sYXlvdXQpIHtcbiAgICAgICAgICAgIHJlc3VsdC5sYXlvdXQgPSBwbG90cy5leHRlbmRMYXlvdXQocmVzdWx0LmxheW91dCwgZnJhbWVQdHIubGF5b3V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGZyYW1lUHRyLmRhdGEpIHtcbiAgICAgICAgICAgIGlmKCFyZXN1bHQuZGF0YSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5kYXRhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cmFjZUluZGljZXMgPSBmcmFtZVB0ci50cmFjZXM7XG5cbiAgICAgICAgICAgIGlmKCF0cmFjZUluZGljZXMpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBub3QgZGVmaW5lZCwgYXNzdW1lIHNlcmlhbCBvcmRlciBzdGFydGluZyBhdCB6ZXJvXG4gICAgICAgICAgICAgICAgdHJhY2VJbmRpY2VzID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnJhbWVQdHIuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZUluZGljZXNbaV0gPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIXJlc3VsdC50cmFjZXMpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQudHJhY2VzID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZyYW1lUHRyLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAvLyBMb29wIHRocm91Z2ggdGhpcyBmcmFtZXMgZGF0YSwgZmluZCBvdXQgd2hlcmUgaXQgc2hvdWxkIGdvLFxuICAgICAgICAgICAgICAgIC8vIGFuZCBtZXJnZSBpdCFcbiAgICAgICAgICAgICAgICB0cmFjZUluZGV4ID0gdHJhY2VJbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlSW5kZXggPT09IHVuZGVmaW5lZCB8fCB0cmFjZUluZGV4ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3RJbmRleCA9IHJlc3VsdC50cmFjZXMuaW5kZXhPZih0cmFjZUluZGV4KTtcbiAgICAgICAgICAgICAgICBpZihkZXN0SW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RJbmRleCA9IHJlc3VsdC5kYXRhLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnRyYWNlc1tkZXN0SW5kZXhdID0gdHJhY2VJbmRleDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXN1bHQuZGF0YVtkZXN0SW5kZXhdID0gcGxvdHMuZXh0ZW5kVHJhY2UocmVzdWx0LmRhdGFbZGVzdEluZGV4XSwgZnJhbWVQdHIuZGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcblxuLypcbiAqIFJlY29tcHV0ZSB0aGUgbG9va3VwIHRhYmxlIHRoYXQgbWFwcyBmcmFtZSBuYW1lIC0+IGZyYW1lIG9iamVjdC4gYWRkRnJhbWVzL1xuICogZGVsZXRlRnJhbWVzIGFscmVhZHkgbWFuYWdlcyB0aGlzIGRhdGEgb25lIGF0IGEgdGltZSwgc28gdGhlIG9ubHkgdGltZSB0aGlzXG4gKiBpcyBuZWNlc3NhcnkgaXMgaWYgeW91IHBva2UgYXJvdW5kIG1hbnVhbGx5IGluIGBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lc2BcbiAqIGFuZCBjcmVhdGUgYW5kIGhhdmVuJ3QgdXBkYXRlZCB0aGUgbG9va3VwIHRhYmxlLlxuICovXG5wbG90cy5yZWNvbXB1dGVGcmFtZUhhc2ggPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBoYXNoID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZUhhc2ggPSB7fTtcbiAgICB2YXIgZnJhbWVzID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXM7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZyYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZnJhbWUgPSBmcmFtZXNbaV07XG4gICAgICAgIGlmKGZyYW1lICYmIGZyYW1lLm5hbWUpIHtcbiAgICAgICAgICAgIGhhc2hbZnJhbWUubmFtZV0gPSBmcmFtZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogRXh0ZW5kIGFuIG9iamVjdCwgdHJlYXRpbmcgY29udGFpbmVyIGFycmF5cyB2ZXJ5IGRpZmZlcmVudGx5IGJ5IGV4dHJhY3RpbmdcbiAqIHRoZWlyIGNvbnRlbnRzIGFuZCBtZXJnaW5nIHRoZW0gc2VwYXJhdGVseS5cbiAqXG4gKiBUaGlzIGV4aXN0cyBzbyB0aGF0IHdlIGNhbiBleHRlbmREZWVwTm9BcnJheXMgYW5kIGF2b2lkIHN0ZXBwaW5nIGludG8gZGF0YVxuICogYXJyYXlzIHdpdGhvdXQga25vd2xlZGdlIG9mIHRoZSBwbG90IHNjaGVtYSwgYnV0IHNvIHRoYXQgd2UgbWF5IGFsc28gbWFudWFsbHlcbiAqIHJlY3Vyc2UgaW50byBrbm93biBjb250YWluZXIgYXJyYXlzLCBzdWNoIGFzIHRyYW5zZm9ybXMuXG4gKlxuICogU2VlIGV4dGVuZFRyYWNlIGFuZCBleHRlbmRMYXlvdXQgYmVsb3cgZm9yIHVzYWdlLlxuICovXG5wbG90cy5leHRlbmRPYmplY3RXaXRoQ29udGFpbmVycyA9IGZ1bmN0aW9uKGRlc3QsIHNyYywgY29udGFpbmVyUGF0aHMpIHtcbiAgICB2YXIgY29udGFpbmVyUHJvcCwgY29udGFpbmVyVmFsLCBpLCBqLCBzcmNQcm9wLCBkZXN0UHJvcCwgc3JjQ29udGFpbmVyLCBkZXN0Q29udGFpbmVyO1xuICAgIHZhciBjb3B5ID0gTGliLmV4dGVuZERlZXBOb0FycmF5cyh7fSwgc3JjIHx8IHt9KTtcbiAgICB2YXIgZXhwYW5kZWRPYmogPSBMaWIuZXhwYW5kT2JqZWN0UGF0aHMoY29weSk7XG4gICAgdmFyIGNvbnRhaW5lck9iaiA9IHt9O1xuXG4gICAgLy8gU3RlcCB0aHJvdWdoIGFuZCBleHRyYWN0IGFueSBjb250YWluZXIgcHJvcGVydGllcy4gT3RoZXJ3aXNlIGV4dGVuZERlZXBOb0FycmF5c1xuICAgIC8vIHdpbGwgY2xvYmJlciBhbnkgZXhpc3RpbmcgcHJvcGVydGllcyB3aXRoIGFuIGVtcHR5IGFycmF5IGFuZCB0aGVuIHN1cHBseURlZmF1bHRzXG4gICAgLy8gd2lsbCByZXNldCBldmVyeXRoaW5nIHRvIGRlZmF1bHRzLlxuICAgIGlmKGNvbnRhaW5lclBhdGhzICYmIGNvbnRhaW5lclBhdGhzLmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb250YWluZXJQYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udGFpbmVyUHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShleHBhbmRlZE9iaiwgY29udGFpbmVyUGF0aHNbaV0pO1xuICAgICAgICAgICAgY29udGFpbmVyVmFsID0gY29udGFpbmVyUHJvcC5nZXQoKTtcblxuICAgICAgICAgICAgaWYoY29udGFpbmVyVmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29udGFpbmVyT2JqLCBjb250YWluZXJQYXRoc1tpXSkuc2V0KG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyUHJvcC5zZXQobnVsbCk7XG4gICAgICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KGNvbnRhaW5lck9iaiwgY29udGFpbmVyUGF0aHNbaV0pLnNldChjb250YWluZXJWYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGVzdCA9IExpYi5leHRlbmREZWVwTm9BcnJheXMoZGVzdCB8fCB7fSwgZXhwYW5kZWRPYmopO1xuXG4gICAgaWYoY29udGFpbmVyUGF0aHMgJiYgY29udGFpbmVyUGF0aHMubGVuZ3RoKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvbnRhaW5lclBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzcmNQcm9wID0gTGliLm5lc3RlZFByb3BlcnR5KGNvbnRhaW5lck9iaiwgY29udGFpbmVyUGF0aHNbaV0pO1xuICAgICAgICAgICAgc3JjQ29udGFpbmVyID0gc3JjUHJvcC5nZXQoKTtcblxuICAgICAgICAgICAgaWYoIXNyY0NvbnRhaW5lcikgY29udGludWU7XG5cbiAgICAgICAgICAgIGRlc3RQcm9wID0gTGliLm5lc3RlZFByb3BlcnR5KGRlc3QsIGNvbnRhaW5lclBhdGhzW2ldKTtcbiAgICAgICAgICAgIGRlc3RDb250YWluZXIgPSBkZXN0UHJvcC5nZXQoKTtcblxuICAgICAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkoZGVzdENvbnRhaW5lcikpIHtcbiAgICAgICAgICAgICAgICBkZXN0Q29udGFpbmVyID0gW107XG4gICAgICAgICAgICAgICAgZGVzdFByb3Auc2V0KGRlc3RDb250YWluZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBzcmNDb250YWluZXIubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc3JjT2JqID0gc3JjQ29udGFpbmVyW2pdO1xuXG4gICAgICAgICAgICAgICAgaWYoc3JjT2JqID09PSBudWxsKSBkZXN0Q29udGFpbmVyW2pdID0gbnVsbDtcbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdENvbnRhaW5lcltqXSA9IHBsb3RzLmV4dGVuZE9iamVjdFdpdGhDb250YWluZXJzKGRlc3RDb250YWluZXJbal0sIHNyY09iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZXN0UHJvcC5zZXQoZGVzdENvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGVzdDtcbn07XG5cbnBsb3RzLmRhdGFBcnJheUNvbnRhaW5lcnMgPSBbJ3RyYW5zZm9ybXMnLCAnZGltZW5zaW9ucyddO1xucGxvdHMubGF5b3V0QXJyYXlDb250YWluZXJzID0gUmVnaXN0cnkubGF5b3V0QXJyYXlDb250YWluZXJzO1xuXG4vKlxuICogRXh0ZW5kIGEgdHJhY2UgZGVmaW5pdGlvbi4gVGhpcyBtZXRob2Q6XG4gKlxuICogIDEuIGRpcmVjdGx5IHRyYW5zZmVycyBhbnkgYXJyYXkgcmVmZXJlbmNlc1xuICogIDIuIG1hbnVhbGx5IHJlY3Vyc2VzIGludG8gY29udGFpbmVyIGFycmF5cyBsaWtlIHRyYW5zZm9ybXNcbiAqXG4gKiBUaGUgcmVzdWx0IGlzIHRoZSBvcmlnaW5hbCBvYmplY3QgcmVmZXJlbmNlIHdpdGggdGhlIG5ldyBjb250ZW50cyBtZXJnZWQgaW4uXG4gKi9cbnBsb3RzLmV4dGVuZFRyYWNlID0gZnVuY3Rpb24oZGVzdFRyYWNlLCBzcmNUcmFjZSkge1xuICAgIHJldHVybiBwbG90cy5leHRlbmRPYmplY3RXaXRoQ29udGFpbmVycyhkZXN0VHJhY2UsIHNyY1RyYWNlLCBwbG90cy5kYXRhQXJyYXlDb250YWluZXJzKTtcbn07XG5cbi8qXG4gKiBFeHRlbmQgYSBsYXlvdXQgZGVmaW5pdGlvbi4gVGhpcyBtZXRob2Q6XG4gKlxuICogIDEuIGRpcmVjdGx5IHRyYW5zZmVycyBhbnkgYXJyYXkgcmVmZXJlbmNlcyAobm90IGNyaXRpY2FsbHkgaW1wb3J0YW50IGZvclxuICogICAgIGxheW91dCBzaW5jZSB0aGVyZSBhcmVuJ3QgcmVhbGx5IGRhdGEgYXJyYXlzKVxuICogIDIuIG1hbnVhbGx5IHJlY3Vyc2VzIGludG8gY29udGFpbmVyIGFycmF5cyBsaWtlIGFubm90YXRpb25zXG4gKlxuICogVGhlIHJlc3VsdCBpcyB0aGUgb3JpZ2luYWwgb2JqZWN0IHJlZmVyZW5jZSB3aXRoIHRoZSBuZXcgY29udGVudHMgbWVyZ2VkIGluLlxuICovXG5wbG90cy5leHRlbmRMYXlvdXQgPSBmdW5jdGlvbihkZXN0TGF5b3V0LCBzcmNMYXlvdXQpIHtcbiAgICByZXR1cm4gcGxvdHMuZXh0ZW5kT2JqZWN0V2l0aENvbnRhaW5lcnMoZGVzdExheW91dCwgc3JjTGF5b3V0LCBwbG90cy5sYXlvdXRBcnJheUNvbnRhaW5lcnMpO1xufTtcblxuLyoqXG4gKiBUcmFuc2l0aW9uIHRvIGEgc2V0IG9mIG5ldyBkYXRhIGFuZCBsYXlvdXQgcHJvcGVydGllc1xuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiAgICAgIHRoZSBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHtPYmplY3RbXX0gZGF0YVxuICogICAgICBhbiBhcnJheSBvZiBkYXRhIG9iamVjdHMgZm9sbG93aW5nIHRoZSBub3JtYWwgUGxvdGx5IGRhdGEgZGVmaW5pdGlvbiBmb3JtYXRcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXlvdXRcbiAqICAgICAgYSBsYXlvdXQgb2JqZWN0LCBmb2xsb3dpbmcgbm9ybWFsIFBsb3RseSBsYXlvdXQgZm9ybWF0XG4gKiBAcGFyYW0ge051bWJlcltdfSB0cmFjZXNcbiAqICAgICAgaW5kaWNlcyBvZiB0aGUgY29ycmVzcG9uZGluZyB0cmFjZXMgc3BlY2lmaWVkIGluIGBkYXRhYFxuICogQHBhcmFtIHtPYmplY3R9IGZyYW1lT3B0c1xuICogICAgICBvcHRpb25zIGZvciB0aGUgZnJhbWUgKGkuZS4gd2hldGhlciB0byByZWRyYXcgcG9zdC10cmFuc2l0aW9uKVxuICogQHBhcmFtIHtPYmplY3R9IHRyYW5zaXRpb25PcHRzXG4gKiAgICAgIG9wdGlvbnMgZm9yIHRoZSB0cmFuc2l0aW9uXG4gKi9cbnBsb3RzLnRyYW5zaXRpb24gPSBmdW5jdGlvbihnZCwgZGF0YSwgbGF5b3V0LCB0cmFjZXMsIGZyYW1lT3B0cywgdHJhbnNpdGlvbk9wdHMpIHtcbiAgICB2YXIgaSwgdHJhY2VJZHg7XG5cbiAgICB2YXIgZGF0YUxlbmd0aCA9IEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhLmxlbmd0aCA6IDA7XG4gICAgdmFyIHRyYWNlSW5kaWNlcyA9IHRyYWNlcy5zbGljZSgwLCBkYXRhTGVuZ3RoKTtcblxuICAgIHZhciB0cmFuc2l0aW9uZWRUcmFjZXMgPSBbXTtcblxuICAgIGZ1bmN0aW9uIHByZXBhcmVUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VJbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VJZHggPSB0cmFjZUluZGljZXNbaV07XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBnZC5fZnVsbERhdGFbdHJhY2VJZHhdO1xuICAgICAgICAgICAgdmFyIG1vZHVsZSA9IHRyYWNlLl9tb2R1bGU7XG5cbiAgICAgICAgICAgIC8vIFRoZXJlJ3Mgbm90aGluZyB0byBkbyBpZiB0aGlzIG1vZHVsZSBpcyBub3QgZGVmaW5lZDpcbiAgICAgICAgICAgIGlmKCFtb2R1bGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBEb24ndCByZWdpc3RlciB0aGUgdHJhY2UgYXMgdHJhbnNpdGlvbmVkIGlmIGl0IGRvZXNuJ3Qga25vdyB3aGF0IHRvIGRvLlxuICAgICAgICAgICAgLy8gSWYgaXQgKmlzKiByZWdpc3RlcmVkLCBpdCB3aWxsIHJlY2VpdmUgYSBjYWxsYmFjayB0aGF0IGl0J3MgcmVzcG9uc2libGVcbiAgICAgICAgICAgIC8vIGZvciBjYWxsaW5nIGluIG9yZGVyIHRvIHJlZ2lzdGVyIHRoZSB0cmFuc2l0aW9uIGFzIGhhdmluZyBjb21wbGV0ZWQuXG4gICAgICAgICAgICBpZihtb2R1bGUuYW5pbWF0YWJsZSkge1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25lZFRyYWNlcy5wdXNoKHRyYWNlSWR4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZGF0YVt0cmFjZUluZGljZXNbaV1dID0gcGxvdHMuZXh0ZW5kVHJhY2UoZ2QuZGF0YVt0cmFjZUluZGljZXNbaV1dLCBkYXRhW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvbGxvdyB0aGUgc2FtZSBwcm9jZWR1cmUuIENsb25lIGl0IHNvIHdlIGRvbid0IG1hbmdsZSB0aGUgaW5wdXQsIHRoZW5cbiAgICAgICAgLy8gZXhwYW5kIGFueSBvYmplY3QgcGF0aHMgc28gd2UgY2FuIG1lcmdlIGRlZXAgaW50byBnZC5sYXlvdXQ6XG4gICAgICAgIHZhciBsYXlvdXRVcGRhdGUgPSBMaWIuZXhwYW5kT2JqZWN0UGF0aHMoTGliLmV4dGVuZERlZXBOb0FycmF5cyh7fSwgbGF5b3V0KSk7XG5cbiAgICAgICAgLy8gQmVmb3JlIG1lcmdpbmcgdGhvdWdoLCB3ZSBuZWVkIHRvIG1vZGlmeSB0aGUgaW5jb21pbmcgbGF5b3V0LiBXZSBvbmx5XG4gICAgICAgIC8vIGtub3cgaG93IHRvICp0cmFuc2l0aW9uKiBsYXlvdXQgcmFuZ2VzLCBzbyBpdCdzIGltcGVyYXRpdmUgdGhhdCBhIG5ld1xuICAgICAgICAvLyByYW5nZSBub3QgYmUgc2VudCB0byB0aGUgbGF5b3V0IGJlZm9yZSB0aGUgdHJhbnNpdGlvbiBoYXMgc3RhcnRlZC4gU29cbiAgICAgICAgLy8gd2UgbXVzdCByZW1vdmUgdGhlIHRoaW5ncyB3ZSBjYW4gdHJhbnNpdGlvbjpcbiAgICAgICAgdmFyIGF4aXNBdHRyUmUgPSAvXlt4eV1heGlzWzAtOV0qJC87XG4gICAgICAgIGZvcih2YXIgYXR0ciBpbiBsYXlvdXRVcGRhdGUpIHtcbiAgICAgICAgICAgIGlmKCFheGlzQXR0clJlLnRlc3QoYXR0cikpIGNvbnRpbnVlO1xuICAgICAgICAgICAgZGVsZXRlIGxheW91dFVwZGF0ZVthdHRyXS5yYW5nZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBsb3RzLmV4dGVuZExheW91dChnZC5sYXlvdXQsIGxheW91dFVwZGF0ZSk7XG5cbiAgICAgICAgLy8gU3VwcGx5IGRlZmF1bHRzIGFmdGVyIGFwcGx5aW5nIHRoZSBpbmNvbWluZyBwcm9wZXJ0aWVzLiBOb3RlIHRoYXQgYW55IGF0dGVtcHRcbiAgICAgICAgLy8gdG8gc2ltcGxpZnkgdGhpcyBzdGVwIGFuZCByZWR1Y2UgdGhlIGFtb3VudCBvZiB3b3JrIHJlc3VsdGVkIGluIHRoZSByZWNvbnN0cnVjdGlvblxuICAgICAgICAvLyBvZiBlc3NlbnRpYWxseSB0aGUgd2hvbGUgc3VwcGx5RGVmYXVsdHMgc3RlcCwgc28gdGhhdCBpdCBzZWVtcyBzZW5zaWJsZSB0byBqdXN0IHVzZVxuICAgICAgICAvLyBzdXBwbHlEZWZhdWx0cyBldmVuIHRob3VnaCBpdCdzIGhlYXZpZXIgdGhhbiB3b3VsZCBvdGhlcndpc2UgYmUgZGVzaXJlZCBmb3JcbiAgICAgICAgLy8gdHJhbnNpdGlvbnM6XG5cbiAgICAgICAgLy8gZmlyc3QgZGVsZXRlIGNhbGNkYXRhIHNvIHN1cHBseURlZmF1bHRzIGtub3dzIGEgY2FsYyBzdGVwIGlzIGNvbWluZ1xuICAgICAgICBkZWxldGUgZ2QuY2FsY2RhdGE7XG5cbiAgICAgICAgcGxvdHMuc3VwcGx5RGVmYXVsdHMoZ2QpO1xuICAgICAgICBwbG90cy5kb0NhbGNkYXRhKGdkKTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhlY3V0ZUNhbGxiYWNrcyhsaXN0KSB7XG4gICAgICAgIHZhciBwID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIGlmKCFsaXN0KSByZXR1cm4gcDtcbiAgICAgICAgd2hpbGUobGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHAgPSBwLnRoZW4oKGxpc3Quc2hpZnQoKSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZsdXNoQ2FsbGJhY2tzKGxpc3QpIHtcbiAgICAgICAgaWYoIWxpc3QpIHJldHVybjtcbiAgICAgICAgd2hpbGUobGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBhYm9ydGVkID0gZmFsc2U7XG5cbiAgICBmdW5jdGlvbiBleGVjdXRlVHJhbnNpdGlvbnMoKSB7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV90cmFuc2l0aW9uaW5nJywgW10pO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGZsYWcgaXMgdXNlZCB0byBkaXNhYmxlZCB0aGluZ3MgbGlrZSBhdXRvcmFuZ2U6XG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbmluZyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIFdoZW4gaW5zdGFudGFuZW91cyB1cGRhdGVzIGFyZSBjb21pbmcgdGhyb3VnaCBxdWlja2x5LCBpdCdzIHRvbyBtdWNoIHRvIHNpbXBseSBkaXNhYmxlXG4gICAgICAgICAgICAvLyBhbGwgaW50ZXJhY3Rpb24sIHNvIHN0b3JlIHRoaXMgZmxhZyBzbyB3ZSBjYW4gZGlzYW1iaWd1YXRlIHdoZXRoZXIgbW91c2UgaW50ZXJhY3Rpb25zXG4gICAgICAgICAgICAvLyBzaG91bGQgYmUgZnVsbHkgZGlzYWJsZWQgb3Igbm90OlxuICAgICAgICAgICAgaWYodHJhbnNpdGlvbk9wdHMuZHVyYXRpb24gPiAwKSB7XG4gICAgICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIC8vIElmIGFub3RoZXIgdHJhbnNpdGlvbiBpcyB0cmlnZ2VyZWQsIHRoaXMgY2FsbGJhY2sgd2lsbCBiZSBleGVjdXRlZCBzaW1wbHkgYmVjYXVzZSBpdCdzXG4gICAgICAgICAgICAvLyBpbiB0aGUgaW50ZXJydXB0Q2FsbGJhY2tzIHF1ZXVlLiBJZiB0aGlzIHRyYW5zaXRpb24gY29tcGxldGVzLCBpdCB3aWxsIGluc3RlYWQgZmx1c2hcbiAgICAgICAgICAgIC8vIHRoYXQgcXVldWUgYW5kIGZvcmdldCBhYm91dCB0aGlzIGNhbGxiYWNrLlxuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZihmcmFtZU9wdHMucmVkcmF3KSB7XG4gICAgICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFJlZ2lzdHJ5LmNhbGwoJ3JlZHJhdycsIGdkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRW1pdCB0aGlzIGFuZCBtYWtlIHN1cmUgaXQgaGFwcGVucyBsYXN0OlxuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfdHJhbnNpdGlvbmludGVycnVwdGVkJywgW10pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cnVjdCBjYWxsYmFja3MgdGhhdCBhcmUgZXhlY3V0ZWQgb24gdHJhbnNpdGlvbiBlbmQuIFRoaXMgZW5zdXJlcyB0aGUgZDMgdHJhbnNpdGlvbnNcbiAgICAgICAgICAgIC8vIGFyZSAqY29tcGxldGUqIGJlZm9yZSBhbnl0aGluZyBlbHNlIGlzIGRvbmUuXG4gICAgICAgICAgICB2YXIgbnVtQ2FsbGJhY2tzID0gMDtcbiAgICAgICAgICAgIHZhciBudW1Db21wbGV0ZWQgPSAwO1xuICAgICAgICAgICAgZnVuY3Rpb24gbWFrZUNhbGxiYWNrKCkge1xuICAgICAgICAgICAgICAgIG51bUNhbGxiYWNrcysrO1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgbnVtQ29tcGxldGVkKys7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gYWxsIGFyZSBjb21wbGV0ZSwgcGVyZm9ybSBhIHJlZHJhdzpcbiAgICAgICAgICAgICAgICAgICAgaWYoIWFib3J0ZWQgJiYgbnVtQ29tcGxldGVkID09PSBudW1DYWxsYmFja3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlVHJhbnNpdGlvbihyZXNvbHZlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0cmFjZVRyYW5zaXRpb25PcHRzO1xuICAgICAgICAgICAgdmFyIGo7XG4gICAgICAgICAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gZ2QuX2Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcbiAgICAgICAgICAgIHZhciBoYXNBeGlzVHJhbnNpdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZihsYXlvdXQpIHtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoYmFzZVBsb3RNb2R1bGVzW2pdLnRyYW5zaXRpb25BeGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3TGF5b3V0ID0gTGliLmV4cGFuZE9iamVjdFBhdGhzKGxheW91dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNBeGlzVHJhbnNpdGlvbiA9IGJhc2VQbG90TW9kdWxlc1tqXS50cmFuc2l0aW9uQXhlcyhnZCwgbmV3TGF5b3V0LCB0cmFuc2l0aW9uT3B0cywgbWFrZUNhbGxiYWNrKSB8fCBoYXNBeGlzVHJhbnNpdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSGVyZSBoYW5kbGUgdGhlIGV4Y2VwdGlvbiB0aGF0IHdlIHJlZnVzZSB0byBhbmltYXRlIHNjYWxlcyBhbmQgYXhlcyBhdCB0aGUgc2FtZVxuICAgICAgICAgICAgLy8gdGltZS4gSW4gb3RoZXIgd29yZHMsIGlmIHRoZXJlJ3MgYW4gYXhpcyB0cmFuc2l0aW9uLCB0aGVuIHNldCB0aGUgZGF0YSB0cmFuc2l0aW9uXG4gICAgICAgICAgICAvLyB0byBpbnN0YW50YW5lb3VzLlxuICAgICAgICAgICAgaWYoaGFzQXhpc1RyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzID0gTGliLmV4dGVuZEZsYXQoe30sIHRyYW5zaXRpb25PcHRzKTtcbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzLmR1cmF0aW9uID0gMDtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIG1lYW5zIGRvIG5vdCB0cmFuc2l0aW9uIHRyYWNlcyxcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGhhcHBlbnMgb24gbGF5b3V0LW9ubHkgKGUuZy4gYXhpcyByYW5nZSkgYW5pbWF0aW9uc1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25lZFRyYWNlcyA9IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyYWNlVHJhbnNpdGlvbk9wdHMgPSB0cmFuc2l0aW9uT3B0cztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHdlIHBhc3MgYSBjYWxsYmFjayB0byAqY3JlYXRlKiB0aGUgY2FsbGJhY2sgdGhhdCBtdXN0IGJlIGludm9rZWQgb24gY29tcGxldGlvbi5cbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHNpbmNlIG5vdCBhbGwgdHJhY2VzIGtub3cgYWJvdXQgdHJhbnNpdGlvbnMsIHNvIGl0IGdyZWF0bHkgc2ltcGxpZmllcyBtYXR0ZXJzIGlmXG4gICAgICAgICAgICAgICAgLy8gdGhlIHRyYWNlIGlzIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyBhIGNhbGxiYWNrLCBpZiBuZWVkZWQsIGFuZCB0aGVuIGV4ZWN1dGluZyBpdCB3aGVuXG4gICAgICAgICAgICAgICAgLy8gdGhlIHRpbWUgaXMgcmlnaHQuXG4gICAgICAgICAgICAgICAgYmFzZVBsb3RNb2R1bGVzW2pdLnBsb3QoZ2QsIHRyYW5zaXRpb25lZFRyYWNlcywgdHJhY2VUcmFuc2l0aW9uT3B0cywgbWFrZUNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgbm90aGluZyBlbHNlIGNyZWF0ZXMgYSBjYWxsYmFjaywgdGhlbiB0aGlzIHdpbGwgdHJpZ2dlciB0aGUgY29tcGxldGlvbiBpbiB0aGUgbmV4dCB0aWNrOlxuICAgICAgICAgICAgc2V0VGltZW91dChtYWtlQ2FsbGJhY2soKSk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcGxldGVUcmFuc2l0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgIC8vIFRoaXMgYSBzaW1wbGUgd29ya2Fyb3VuZCBmb3IgdGVzdHMgd2hpY2ggcHVyZ2UgdGhlIGdyYXBoIGJlZm9yZSBhbmltYXRpb25zXG4gICAgICAgIC8vIGhhdmUgY29tcGxldGVkLiBUaGF0J3Mgbm90IGEgdmVyeSBjb21tb24gY2FzZSwgc28gdGhpcyBpcyB0aGUgc2ltcGxlc3RcbiAgICAgICAgLy8gZml4LlxuICAgICAgICBpZighZ2QuX3RyYW5zaXRpb25EYXRhKSByZXR1cm47XG5cbiAgICAgICAgZmx1c2hDYWxsYmFja3MoZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MpO1xuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYoZnJhbWVPcHRzLnJlZHJhdykge1xuICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdyZWRyYXcnLCBnZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBTZXQgdHJhbnNpdGlvbmluZyBmYWxzZSBhZ2FpbiBvbmNlIHRoZSByZWRyYXcgaGFzIG9jY3VycmVkLiBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLFxuICAgICAgICAgICAgLy8gdG8gcHJldmVudCB0aGUgdHJhaWxpbmcgcmVkcmF3IGZyb20gYXV0b3Jhbmdpbmc6XG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24gPSBmYWxzZTtcblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25lZCcsIFtdKTtcbiAgICAgICAgfSkudGhlbihjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW50ZXJydXB0UHJldmlvdXNUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgLy8gRmFpbC1zYWZlIGFnYWluc3QgcHVyZ2VkIHBsb3Q6XG4gICAgICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgaW50ZXJydXB0ZWQsIHNldCB0aGlzIHRvIGZhbHNlLiBBdCB0aGUgbW9tZW50LCB0aGUgb25seSB0aGluZyB0aGF0IHdvdWxkXG4gICAgICAgIC8vIGludGVycnVwdCBhIHRyYW5zaXRpb24gaXMgYW5vdGhlciB0cmFuc2l0aW9uLCBzbyB0aGF0IGl0IHdpbGwgbW9tZW50YXJpbHkgYmUgc2V0IHRvIHRydWVcbiAgICAgICAgLy8gYWdhaW4sIGJ1dCB0aGlzIGRldGVybWluZXMgd2hldGhlciBhdXRvcmFuZ2Ugb3IgZHJhZ2JveCB3b3JrLCBzbyBpdCdzIGZvciB0aGUgc2FrZSBvZlxuICAgICAgICAvLyBjbGVhbmxpbmVzczpcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4gZXhlY3V0ZUNhbGxiYWNrcyhnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcyk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VJbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlSWR4ID0gdHJhY2VJbmRpY2VzW2ldO1xuICAgICAgICB2YXIgY29udEZ1bGwgPSBnZC5fZnVsbERhdGFbdHJhY2VJZHhdO1xuICAgICAgICB2YXIgbW9kdWxlID0gY29udEZ1bGwuX21vZHVsZTtcblxuICAgICAgICBpZighbW9kdWxlKSBjb250aW51ZTtcbiAgICB9XG5cbiAgICB2YXIgc2VxID0gW3Bsb3RzLnByZXZpb3VzUHJvbWlzZXMsIGludGVycnVwdFByZXZpb3VzVHJhbnNpdGlvbnMsIHByZXBhcmVUcmFuc2l0aW9ucywgcGxvdHMucmVob3ZlciwgZXhlY3V0ZVRyYW5zaXRpb25zXTtcblxuICAgIHZhciB0cmFuc2l0aW9uU3RhcnRpbmcgPSBMaWIuc3luY09yQXN5bmMoc2VxLCBnZCk7XG5cbiAgICBpZighdHJhbnNpdGlvblN0YXJ0aW5nIHx8ICF0cmFuc2l0aW9uU3RhcnRpbmcudGhlbikge1xuICAgICAgICB0cmFuc2l0aW9uU3RhcnRpbmcgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNpdGlvblN0YXJ0aW5nLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogVHJhbnNpdGlvbiB1c2VkIGluIFBsb3RseS5yZWFjdFxuICovXG5wbG90cy50cmFuc2l0aW9uMiA9IGZ1bmN0aW9uKGdkLCByZXN0eWxlRmxhZ3MsIHJlbGF5b3V0RmxhZ3MsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgYWJvcnRlZCA9IGZhbHNlO1xuICAgIHZhciByZWRyYXcgPSB0cnVlO1xuICAgIHZhciBlZGl0cztcblxuICAgIGZ1bmN0aW9uIHByZXBhcmVUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgdmFyIHN1YnBsb3RzID0gZnVsbExheW91dC5fcGxvdHM7XG4gICAgICAgIHZhciByYW5nZXNBbHRlcmVkID0gcmVsYXlvdXRGbGFncy5yYW5nZXNBbHRlcmVkO1xuICAgICAgICB2YXIgYXV0b3JhbmdlZEF4ZXMgPSByZWxheW91dEZsYWdzLmF1dG9yYW5nZWRBeGVzO1xuXG4gICAgICAgIC8vIG5vIG5lZWQgdG8gcmVkcmF3IGF0IGVuZCBvZiB0cmFuc2l0aW9uLFxuICAgICAgICAvLyBpZiBhbGwgY2hhbmdlcyBhcmUgYW5pbWF0YWJsZVxuICAgICAgICByZWRyYXcgPSBmYWxzZTtcbiAgICAgICAgaWYocmVzdHlsZUZsYWdzLmFuaW0gPT09ICdzb21lJykgcmVkcmF3ID0gdHJ1ZTtcbiAgICAgICAgaWYocmVsYXlvdXRGbGFncy5hbmltID09PSAnc29tZScpIHJlZHJhdyA9IHRydWU7XG5cbiAgICAgICAgZWRpdHMgPSB7fTtcbiAgICAgICAgZm9yKHZhciBrIGluIHN1YnBsb3RzKSB7XG4gICAgICAgICAgICB2YXIgcGxvdGluZm8gPSBzdWJwbG90c1trXTtcbiAgICAgICAgICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICAgICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgICAgIGlmKHJhbmdlc0FsdGVyZWRbeGEuX25hbWVdIHx8IHJhbmdlc0FsdGVyZWRbeWEuX25hbWVdIHx8XG4gICAgICAgICAgICAgICAgYXV0b3JhbmdlZEF4ZXNbeGEuX25hbWVdIHx8IGF1dG9yYW5nZWRBeGVzW3lhLl9uYW1lXVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZWRpdHNba10gPSB7XG4gICAgICAgICAgICAgICAgICAgIHBsb3RpbmZvOiBwbG90aW5mbyxcbiAgICAgICAgICAgICAgICAgICAgeHIwOiBvbGRGdWxsTGF5b3V0W3hhLl9uYW1lXS5yYW5nZS5zbGljZSgpLFxuICAgICAgICAgICAgICAgICAgICB5cjA6IG9sZEZ1bGxMYXlvdXRbeWEuX25hbWVdLnJhbmdlLnNsaWNlKCksXG4gICAgICAgICAgICAgICAgICAgIHhyMTogeGEucmFuZ2Uuc2xpY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgeXIxOiB5YS5yYW5nZS5zbGljZSgpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleGVjdXRlQ2FsbGJhY2tzKGxpc3QpIHtcbiAgICAgICAgdmFyIHAgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgaWYoIWxpc3QpIHJldHVybiBwO1xuICAgICAgICB3aGlsZShsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgcCA9IHAudGhlbigobGlzdC5zaGlmdCgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZmx1c2hDYWxsYmFja3MobGlzdCkge1xuICAgICAgICBpZighbGlzdCkgcmV0dXJuO1xuICAgICAgICB3aGlsZShsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhlY3V0ZVRyYW5zaXRpb25zKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfdHJhbnNpdGlvbmluZycsIFtdKTtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uT3B0cyA9IGZ1bGxMYXlvdXQudHJhbnNpdGlvbjtcbiAgICAgICAgICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG4gICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgLy8gVGhpcyBmbGFnIGlzIHVzZWQgdG8gZGlzYWJsZWQgdGhpbmdzIGxpa2UgYXV0b3JhbmdlOlxuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmcgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBXaGVuIGluc3RhbnRhbmVvdXMgdXBkYXRlcyBhcmUgY29taW5nIHRocm91Z2ggcXVpY2tseSwgaXQncyB0b28gbXVjaCB0byBzaW1wbHkgZGlzYWJsZVxuICAgICAgICAgICAgLy8gYWxsIGludGVyYWN0aW9uLCBzbyBzdG9yZSB0aGlzIGZsYWcgc28gd2UgY2FuIGRpc2FtYmlndWF0ZSB3aGV0aGVyIG1vdXNlIGludGVyYWN0aW9uc1xuICAgICAgICAgICAgLy8gc2hvdWxkIGJlIGZ1bGx5IGRpc2FibGVkIG9yIG5vdDpcbiAgICAgICAgICAgIGlmKHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uID4gMCkge1xuICAgICAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uaW5nV2l0aER1cmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgYW5vdGhlciB0cmFuc2l0aW9uIGlzIHRyaWdnZXJlZCwgdGhpcyBjYWxsYmFjayB3aWxsIGJlIGV4ZWN1dGVkIHNpbXBseSBiZWNhdXNlIGl0J3NcbiAgICAgICAgICAgIC8vIGluIHRoZSBpbnRlcnJ1cHRDYWxsYmFja3MgcXVldWUuIElmIHRoaXMgdHJhbnNpdGlvbiBjb21wbGV0ZXMsIGl0IHdpbGwgaW5zdGVhZCBmbHVzaFxuICAgICAgICAgICAgLy8gdGhhdCBxdWV1ZSBhbmQgZm9yZ2V0IGFib3V0IHRoaXMgY2FsbGJhY2suXG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcy5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmKHJlZHJhdykge1xuICAgICAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdyZWRyYXcnLCBnZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVtaXQgdGhpcyBhbmQgbWFrZSBzdXJlIGl0IGhhcHBlbnMgbGFzdDpcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25pbnRlcnJ1cHRlZCcsIFtdKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3QgY2FsbGJhY2tzIHRoYXQgYXJlIGV4ZWN1dGVkIG9uIHRyYW5zaXRpb24gZW5kLiBUaGlzIGVuc3VyZXMgdGhlIGQzIHRyYW5zaXRpb25zXG4gICAgICAgICAgICAvLyBhcmUgKmNvbXBsZXRlKiBiZWZvcmUgYW55dGhpbmcgZWxzZSBpcyBkb25lLlxuICAgICAgICAgICAgdmFyIG51bUNhbGxiYWNrcyA9IDA7XG4gICAgICAgICAgICB2YXIgbnVtQ29tcGxldGVkID0gMDtcbiAgICAgICAgICAgIGZ1bmN0aW9uIG1ha2VDYWxsYmFjaygpIHtcbiAgICAgICAgICAgICAgICBudW1DYWxsYmFja3MrKztcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bUNvbXBsZXRlZCsrO1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGFsbCBhcmUgY29tcGxldGUsIHBlcmZvcm0gYSByZWRyYXc6XG4gICAgICAgICAgICAgICAgICAgIGlmKCFhYm9ydGVkICYmIG51bUNvbXBsZXRlZCA9PT0gbnVtQ2FsbGJhY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZVRyYW5zaXRpb24ocmVzb2x2ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIZXJlIGhhbmRsZSB0aGUgZXhjZXB0aW9uIHRoYXQgd2UgcmVmdXNlIHRvIGFuaW1hdGUgdHJhY2VzIGFuZCBheGVzIGF0IHRoZSBzYW1lXG4gICAgICAgICAgICAvLyB0aW1lLiBJbiBvdGhlciB3b3JkcywgaWYgdGhlcmUncyBhbiBheGlzIHRyYW5zaXRpb24sIHRoZW4gc2V0IHRoZSBkYXRhIHRyYW5zaXRpb25cbiAgICAgICAgICAgIC8vIHRvIGluc3RhbnRhbmVvdXMuXG4gICAgICAgICAgICB2YXIgdHJhY2VUcmFuc2l0aW9uT3B0cztcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uZWRUcmFjZXMgPSBbXTtcblxuICAgICAgICAgICAgaWYoT2JqZWN0LmtleXMoZWRpdHMpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGJhc2VQbG90TW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZihiYXNlUGxvdE1vZHVsZXNbaV0udHJhbnNpdGlvbkF4ZXMyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXNlUGxvdE1vZHVsZXNbaV0udHJhbnNpdGlvbkF4ZXMyKGdkLCBlZGl0cywgdHJhbnNpdGlvbk9wdHMsIG1ha2VDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzID0gTGliLmV4dGVuZEZsYXQoe30sIHRyYW5zaXRpb25PcHRzKTtcbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzLmR1cmF0aW9uID0gMDtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIG1lYW5zIGRvIG5vdCB0cmFuc2l0aW9uIHRyYWNlcyxcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGhhcHBlbnMgb24gbGF5b3V0LW9ubHkgKGUuZy4gYXhpcyByYW5nZSkgYW5pbWF0aW9uc1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25lZFRyYWNlcyA9IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyYWNlVHJhbnNpdGlvbk9wdHMgPSB0cmFuc2l0aW9uT3B0cztcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uZWRUcmFjZXMucHVzaChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB3ZSBwYXNzIGEgY2FsbGJhY2sgdG8gKmNyZWF0ZSogdGhlIGNhbGxiYWNrIHRoYXQgbXVzdCBiZSBpbnZva2VkIG9uIGNvbXBsZXRpb24uXG4gICAgICAgICAgICAvLyBUaGlzIGlzIHNpbmNlIG5vdCBhbGwgdHJhY2VzIGtub3cgYWJvdXQgdHJhbnNpdGlvbnMsIHNvIGl0IGdyZWF0bHkgc2ltcGxpZmllcyBtYXR0ZXJzIGlmXG4gICAgICAgICAgICAvLyB0aGUgdHJhY2UgaXMgcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIGEgY2FsbGJhY2ssIGlmIG5lZWRlZCwgYW5kIHRoZW4gZXhlY3V0aW5nIGl0IHdoZW5cbiAgICAgICAgICAgIC8vIHRoZSB0aW1lIGlzIHJpZ2h0LlxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBsb3RNb2R1bGVzW2ldLnBsb3QoZ2QsIHRyYW5zaXRpb25lZFRyYWNlcywgdHJhY2VUcmFuc2l0aW9uT3B0cywgbWFrZUNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgbm90aGluZyBlbHNlIGNyZWF0ZXMgYSBjYWxsYmFjaywgdGhlbiB0aGlzIHdpbGwgdHJpZ2dlciB0aGUgY29tcGxldGlvbiBpbiB0aGUgbmV4dCB0aWNrOlxuICAgICAgICAgICAgc2V0VGltZW91dChtYWtlQ2FsbGJhY2soKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXBsZXRlVHJhbnNpdGlvbihjYWxsYmFjaykge1xuICAgICAgICAvLyBUaGlzIGEgc2ltcGxlIHdvcmthcm91bmQgZm9yIHRlc3RzIHdoaWNoIHB1cmdlIHRoZSBncmFwaCBiZWZvcmUgYW5pbWF0aW9uc1xuICAgICAgICAvLyBoYXZlIGNvbXBsZXRlZC4gVGhhdCdzIG5vdCBhIHZlcnkgY29tbW9uIGNhc2UsIHNvIHRoaXMgaXMgdGhlIHNpbXBsZXN0XG4gICAgICAgIC8vIGZpeC5cbiAgICAgICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGZsdXNoQ2FsbGJhY2tzKGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzKTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmKHJlZHJhdykge1xuICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdyZWRyYXcnLCBnZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBTZXQgdHJhbnNpdGlvbmluZyBmYWxzZSBhZ2FpbiBvbmNlIHRoZSByZWRyYXcgaGFzIG9jY3VycmVkLiBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLFxuICAgICAgICAgICAgLy8gdG8gcHJldmVudCB0aGUgdHJhaWxpbmcgcmVkcmF3IGZyb20gYXV0b3Jhbmdpbmc6XG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24gPSBmYWxzZTtcblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25lZCcsIFtdKTtcbiAgICAgICAgfSkudGhlbihjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW50ZXJydXB0UHJldmlvdXNUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgLy8gRmFpbC1zYWZlIGFnYWluc3QgcHVyZ2VkIHBsb3Q6XG4gICAgICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgaW50ZXJydXB0ZWQsIHNldCB0aGlzIHRvIGZhbHNlLiBBdCB0aGUgbW9tZW50LCB0aGUgb25seSB0aGluZyB0aGF0IHdvdWxkXG4gICAgICAgIC8vIGludGVycnVwdCBhIHRyYW5zaXRpb24gaXMgYW5vdGhlciB0cmFuc2l0aW9uLCBzbyB0aGF0IGl0IHdpbGwgbW9tZW50YXJpbHkgYmUgc2V0IHRvIHRydWVcbiAgICAgICAgLy8gYWdhaW4sIGJ1dCB0aGlzIGRldGVybWluZXMgd2hldGhlciBhdXRvcmFuZ2Ugb3IgZHJhZ2JveCB3b3JrLCBzbyBpdCdzIGZvciB0aGUgc2FrZSBvZlxuICAgICAgICAvLyBjbGVhbmxpbmVzczpcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4gZXhlY3V0ZUNhbGxiYWNrcyhnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcyk7XG4gICAgfVxuXG4gICAgdmFyIHNlcSA9IFtcbiAgICAgICAgcGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgaW50ZXJydXB0UHJldmlvdXNUcmFuc2l0aW9ucyxcbiAgICAgICAgcHJlcGFyZVRyYW5zaXRpb25zLFxuICAgICAgICBwbG90cy5yZWhvdmVyLFxuICAgICAgICBleGVjdXRlVHJhbnNpdGlvbnNcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zaXRpb25TdGFydGluZyA9IExpYi5zeW5jT3JBc3luYyhzZXEsIGdkKTtcblxuICAgIGlmKCF0cmFuc2l0aW9uU3RhcnRpbmcgfHwgIXRyYW5zaXRpb25TdGFydGluZy50aGVuKSB7XG4gICAgICAgIHRyYW5zaXRpb25TdGFydGluZyA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2l0aW9uU3RhcnRpbmcudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGdkO1xuICAgIH0pO1xufTtcblxucGxvdHMuZG9DYWxjZGF0YSA9IGZ1bmN0aW9uKGdkLCB0cmFjZXMpIHtcbiAgICB2YXIgYXhMaXN0ID0gYXhpc0lEcy5saXN0KGdkKSxcbiAgICAgICAgZnVsbERhdGEgPSBnZC5fZnVsbERhdGEsXG4gICAgICAgIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciB0cmFjZSwgX21vZHVsZSwgaSwgajtcblxuICAgIC8vIFhYWDogSXMgdGhpcyBjb3JyZWN0PyBOZWVkcyBhIGNsb3NlciBsb29rIHNvIHRoYXQgKnNvbWUqIHRyYWNlcyBjYW4gYmUgcmVjb21wdXRlZCB3aXRob3V0XG4gICAgLy8gKmFsbCogbmVlZGluZyBkb0NhbGNkYXRhOlxuICAgIHZhciBjYWxjZGF0YSA9IG5ldyBBcnJheShmdWxsRGF0YS5sZW5ndGgpO1xuICAgIHZhciBvbGRDYWxjZGF0YSA9IChnZC5jYWxjZGF0YSB8fCBbXSkuc2xpY2UoMCk7XG4gICAgZ2QuY2FsY2RhdGEgPSBjYWxjZGF0YTtcblxuICAgIC8vIGV4dHJhIGhlbHBlciB2YXJpYWJsZXNcblxuICAgIC8vIGhvdyBtYW55IGJveC92aW9saW5zIHBsb3RzIGRvIHdlIGhhdmUgKGluIGNhc2UgdGhleSdyZSBncm91cGVkKVxuICAgIGZ1bGxMYXlvdXQuX251bUJveGVzID0gMDtcbiAgICBmdWxsTGF5b3V0Ll9udW1WaW9saW5zID0gMDtcblxuICAgIC8vIGluaXRpYWxpemUgdmlvbGluIHBlci1zY2FsZS1ncm91cCBzdGF0cyBjb250YWluZXJcbiAgICBmdWxsTGF5b3V0Ll92aW9saW5TY2FsZUdyb3VwU3RhdHMgPSB7fTtcblxuICAgIC8vIGZvciBjYWxjdWxhdGluZyBhdmcgbHVtaW5vc2l0eSBvZiBoZWF0bWFwc1xuICAgIGdkLl9obXBpeGNvdW50ID0gMDtcbiAgICBnZC5faG1sdW1jb3VudCA9IDA7XG5cbiAgICAvLyBmb3Igc2hhcmluZyBjb2xvcnMgYWNyb3NzIHBpZXMgKGFuZCBmb3IgbGVnZW5kKVxuICAgIGZ1bGxMYXlvdXQuX3BpZWNvbG9ybWFwID0ge307XG5cbiAgICAvLyBJZiB0cmFjZXMgd2VyZSBzcGVjaWZpZWQgYW5kIHRoaXMgdHJhY2Ugd2FzIG5vdCBpbmNsdWRlZCxcbiAgICAvLyB0aGVuIHRyYW5zZmVyIGl0IG92ZXIgZnJvbSB0aGUgb2xkIGNhbGNkYXRhOlxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2VzKSAmJiB0cmFjZXMuaW5kZXhPZihpKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIGNhbGNkYXRhW2ldID0gb2xkQ2FsY2RhdGFbaV07XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgdHJhY2UuX2FycmF5QXR0cnMgPSBQbG90U2NoZW1hLmZpbmRBcnJheUF0dHJpYnV0ZXModHJhY2UpO1xuXG4gICAgICAgIC8vIGtlZXAgdHJhY2sgb2YgdHJhY2UgZXh0cmVtZXMgKGZvciBhdXRvcmFuZ2UpIGluIGhlcmVcbiAgICAgICAgdHJhY2UuX2V4dHJlbWVzID0ge307XG4gICAgfVxuXG4gICAgLy8gYWRkIHBvbGFyIGF4ZXMgdG8gYXhpcyBsaXN0XG4gICAgdmFyIHBvbGFySWRzID0gZnVsbExheW91dC5fc3VicGxvdHMucG9sYXIgfHwgW107XG4gICAgZm9yKGkgPSAwOyBpIDwgcG9sYXJJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXhMaXN0LnB1c2goXG4gICAgICAgICAgICBmdWxsTGF5b3V0W3BvbGFySWRzW2ldXS5yYWRpYWxheGlzLFxuICAgICAgICAgICAgZnVsbExheW91dFtwb2xhcklkc1tpXV0uYW5ndWxhcmF4aXNcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjbGVhckF4ZXNDYWxjKGF4TGlzdCk7XG5cbiAgICB2YXIgaGFzQ2FsY1RyYW5zZm9ybSA9IGZhbHNlO1xuXG4gICAgLy8gdHJhbnNmb3JtIGxvb3BcbiAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgdHJhY2UudHJhbnNmb3Jtcykge1xuICAgICAgICAgICAgX21vZHVsZSA9IHRyYWNlLl9tb2R1bGU7XG5cbiAgICAgICAgICAgIC8vIHdlIG5lZWQgb25lIHJvdW5kIG9mIHRyYWNlIG1vZHVsZSBjYWxjIGJlZm9yZVxuICAgICAgICAgICAgLy8gdGhlIGNhbGMgdHJhbnNmb3JtIHRvICdmaWxsIGluJyB0aGUgY2F0ZWdvcmllcyBsaXN0XG4gICAgICAgICAgICAvLyB1c2VkIGZvciBleGFtcGxlIGluIHRoZSBkYXRhLXRvLWNvb3JkaW5hdGUgbWV0aG9kXG4gICAgICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2FsYykge1xuICAgICAgICAgICAgICAgIHZhciBjZGkgPSBfbW9kdWxlLmNhbGMoZ2QsIHRyYWNlKTtcblxuICAgICAgICAgICAgICAgIC8vIG11c3QgY2xlYXIgc2NlbmUgJ2JhdGNoZXMnLCBzbyB0aGF0IDJuZFxuICAgICAgICAgICAgICAgIC8vIF9tb2R1bGUuY2FsYyBjYWxsIHN0YXJ0cyBmcm9tIHNjcmF0Y2hcbiAgICAgICAgICAgICAgICBpZihjZGlbMF0gJiYgY2RpWzBdLnQgJiYgY2RpWzBdLnQuX3NjZW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjZGlbMF0udC5fc2NlbmUuZGlydHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB0cmFjZS50cmFuc2Zvcm1zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYWNlLnRyYW5zZm9ybXNbal07XG5cbiAgICAgICAgICAgICAgICBfbW9kdWxlID0gdHJhbnNmb3Jtc1JlZ2lzdHJ5W3RyYW5zZm9ybS50eXBlXTtcbiAgICAgICAgICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2FsY1RyYW5zZm9ybSkge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZS5faGFzQ2FsY1RyYW5zZm9ybSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGhhc0NhbGNUcmFuc2Zvcm0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBfbW9kdWxlLmNhbGNUcmFuc2Zvcm0oZ2QsIHRyYWNlLCB0cmFuc2Zvcm0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNsZWFyIHN0dWZmIHRoYXQgc2hvdWxkIHJlY29tcHV0ZWQgaW4gJ3JlZ3VsYXInIGxvb3BcbiAgICBpZihoYXNDYWxjVHJhbnNmb3JtKSBjbGVhckF4ZXNDYWxjKGF4TGlzdCk7XG5cbiAgICBmdW5jdGlvbiBjYWxjaShpLCBpc0NvbnRhaW5lcikge1xuICAgICAgICB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBfbW9kdWxlID0gdHJhY2UuX21vZHVsZTtcblxuICAgICAgICBpZighIV9tb2R1bGUuaXNDb250YWluZXIgIT09IGlzQ29udGFpbmVyKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGNkID0gW107XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICAvLyBjbGVhciBleGlzdGluZyByZWYgaW4gY2FzZSBpdCBnb3QgcmVsaW5rZWRcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5faW5kZXhUb1BvaW50cztcbiAgICAgICAgICAgIC8vIGtlZXAgcmVmIG9mIGluZGV4LXRvLXBvaW50cyBtYXAgb2JqZWN0IG9mIHRoZSAqbGFzdCogZW5hYmxlZCB0cmFuc2Zvcm0sXG4gICAgICAgICAgICAvLyB0aGlzIGluZGV4LXRvLXBvaW50cyBtYXAgb2JqZWN0IGlzIHJlcXVpcmVkIHRvIGRldGVybWluZSB0aGUgY2FsY2RhdGEgaW5kaWNlc1xuICAgICAgICAgICAgLy8gdGhhdCBjb3JyZXNwb25kIHRvIGlucHV0IGluZGljZXMgKGUuZy4gZnJvbSAnc2VsZWN0ZWRwb2ludHMnKVxuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zIHx8IFtdO1xuICAgICAgICAgICAgZm9yKGogPSB0cmFuc2Zvcm1zLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSB7XG4gICAgICAgICAgICAgICAgaWYodHJhbnNmb3Jtc1tqXS5lbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLl9pbmRleFRvUG9pbnRzID0gdHJhbnNmb3Jtc1tqXS5faW5kZXhUb1BvaW50cztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2FsYykge1xuICAgICAgICAgICAgICAgIGNkID0gX21vZHVsZS5jYWxjKGdkLCB0cmFjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNYWtlIHN1cmUgdGhlcmUgaXMgYSBmaXJzdCBwb2ludC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZXJlIGlzIGEgY2FsY2RhdGEgaXRlbSBmb3IgZXZlcnkgdHJhY2UsXG4gICAgICAgIC8vIGV2ZW4gaWYgY2FydGVzaWFuIGxvZ2ljIGRvZXNuJ3QgaGFuZGxlIGl0IChmb3IgdGhpbmdzIGxpa2UgbGVnZW5kcykuXG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGNkKSB8fCAhY2RbMF0pIHtcbiAgICAgICAgICAgIGNkID0gW3t4OiBCQUROVU0sIHk6IEJBRE5VTX1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWRkIHRoZSB0cmFjZS13aWRlIHByb3BlcnRpZXMgdG8gdGhlIGZpcnN0IHBvaW50LFxuICAgICAgICAvLyBwZXIgcG9pbnQgcHJvcGVydGllcyB0byBldmVyeSBwb2ludFxuICAgICAgICAvLyB0IGlzIHRoZSBob2xkZXIgZm9yIHRyYWNlLXdpZGUgcHJvcGVydGllc1xuICAgICAgICBpZighY2RbMF0udCkgY2RbMF0udCA9IHt9O1xuICAgICAgICBjZFswXS50cmFjZSA9IHRyYWNlO1xuXG4gICAgICAgIGNhbGNkYXRhW2ldID0gY2Q7XG4gICAgfVxuXG4gICAgLy8gJ3JlZ3VsYXInIGxvb3AgLSBtYWtlIHN1cmUgY29udGFpbmVyIHRyYWNlcyAoZWcgY2FycGV0KSBjYWxjIGJlZm9yZVxuICAgIC8vIGNvbnRhaW5lZCB0cmFjZXMgKGVnIGNvbnRvdXJjYXJwZXQpXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIGNhbGNpKGksIHRydWUpO1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSBjYWxjaShpLCBmYWxzZSk7XG5cbiAgICBkb0Nyb3NzVHJhY2VDYWxjKGdkKTtcblxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZngnLCAnY2FsYycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdjYWxjJykoZ2QpO1xufTtcblxuZnVuY3Rpb24gY2xlYXJBeGVzQ2FsYyhheExpc3QpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4TGlzdFtpXS5jbGVhckNhbGMoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRvQ3Jvc3NUcmFjZUNhbGMoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBtb2R1bGVzID0gZnVsbExheW91dC5fdmlzaWJsZU1vZHVsZXM7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICB2YXIgaSwgaiwgaztcblxuICAgIC8vIHBvc2l0aW9uIGFuZCByYW5nZSBjYWxjdWxhdGlvbnMgZm9yIHRyYWNlcyB0aGF0XG4gICAgLy8gZGVwZW5kIG9uIGVhY2ggb3RoZXIgaWUgYmFycyAoc3RhY2tlZCBvciBncm91cGVkKVxuICAgIC8vIGFuZCBib3hlcyAoZ3JvdXBlZCkgcHVzaCBlYWNoIG90aGVyIG91dCBvZiB0aGUgd2F5XG5cbiAgICBmb3IoaiA9IDA7IGogPCBtb2R1bGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gbW9kdWxlc1tqXTtcbiAgICAgICAgdmFyIGZuID0gX21vZHVsZS5jcm9zc1RyYWNlQ2FsYztcbiAgICAgICAgaWYoZm4pIHtcbiAgICAgICAgICAgIHZhciBzcFR5cGUgPSBfbW9kdWxlLmJhc2VQbG90TW9kdWxlLm5hbWU7XG4gICAgICAgICAgICBpZihoYXNoW3NwVHlwZV0pIHtcbiAgICAgICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShoYXNoW3NwVHlwZV0sIGZuKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaGFzaFtzcFR5cGVdID0gW2ZuXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihrIGluIGhhc2gpIHtcbiAgICAgICAgdmFyIG1ldGhvZHMgPSBoYXNoW2tdO1xuICAgICAgICB2YXIgc3VicGxvdHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1trXTtcblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHN1YnBsb3RzKSkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc3AgPSBzdWJwbG90c1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgc3BJbmZvID0gayA9PT0gJ2NhcnRlc2lhbicgP1xuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0Ll9wbG90c1tzcF0gOlxuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0W3NwXTtcblxuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG1ldGhvZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1tqXShnZCwgc3BJbmZvLCBzcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbWV0aG9kcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIG1ldGhvZHNbal0oZ2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5wbG90cy5yZWhvdmVyID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBpZihnZC5fZnVsbExheW91dC5fcmVob3Zlcikge1xuICAgICAgICBnZC5fZnVsbExheW91dC5fcmVob3ZlcigpO1xuICAgIH1cbn07XG5cbnBsb3RzLmdlbmVyYWxVcGRhdGVQZXJUcmFjZU1vZHVsZSA9IGZ1bmN0aW9uKGdkLCBzdWJwbG90LCBzdWJwbG90Q2FsY0RhdGEsIHN1YnBsb3RMYXlvdXQpIHtcbiAgICB2YXIgdHJhY2VIYXNoT2xkID0gc3VicGxvdC50cmFjZUhhc2g7XG4gICAgdmFyIHRyYWNlSGFzaCA9IHt9O1xuICAgIHZhciBpO1xuXG4gICAgLy8gYnVpbGQgdXAgbW9kdWxlTmFtZSAtPiBjYWxjRGF0YSBoYXNoXG4gICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdENhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2VzID0gc3VicGxvdENhbGNEYXRhW2ldLFxuICAgICAgICAgICAgdHJhY2UgPSBjYWxjVHJhY2VzWzBdLnRyYWNlO1xuXG4gICAgICAgIC8vIHNraXAgb3ZlciB2aXNpYmxlID09PSBmYWxzZSB0cmFjZXNcbiAgICAgICAgLy8gYXMgdGhleSBkb24ndCBoYXZlIGBfbW9kdWxlYCByZWZcbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSkge1xuICAgICAgICAgICAgdHJhY2VIYXNoW3RyYWNlLnR5cGVdID0gdHJhY2VIYXNoW3RyYWNlLnR5cGVdIHx8IFtdO1xuICAgICAgICAgICAgdHJhY2VIYXNoW3RyYWNlLnR5cGVdLnB1c2goY2FsY1RyYWNlcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB3aGVuIGEgdHJhY2UgZ2V0cyBkZWxldGVkLCBtYWtlIHN1cmUgdGhhdCBpdHMgbW9kdWxlJ3NcbiAgICAvLyBwbG90IG1ldGhvZCBpcyBjYWxsZWQgc28gdGhhdCBpdCBpcyBwcm9wZXJseVxuICAgIC8vIHJlbW92ZWQgZnJvbSB0aGUgRE9NLlxuICAgIGZvcih2YXIgbW9kdWxlTmFtZU9sZCBpbiB0cmFjZUhhc2hPbGQpIHtcbiAgICAgICAgaWYoIXRyYWNlSGFzaFttb2R1bGVOYW1lT2xkXSkge1xuICAgICAgICAgICAgdmFyIGZha2VDYWxjVHJhY2UgPSB0cmFjZUhhc2hPbGRbbW9kdWxlTmFtZU9sZF1bMF0sXG4gICAgICAgICAgICAgICAgZmFrZVRyYWNlID0gZmFrZUNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICAgICAgZmFrZVRyYWNlLnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRyYWNlSGFzaFttb2R1bGVOYW1lT2xkXSA9IFtmYWtlQ2FsY1RyYWNlXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNhbGwgbW9kdWxlIHBsb3QgbWV0aG9kXG4gICAgZm9yKHZhciBtb2R1bGVOYW1lIGluIHRyYWNlSGFzaCkge1xuICAgICAgICB2YXIgbW9kdWxlQ2FsY0RhdGEgPSB0cmFjZUhhc2hbbW9kdWxlTmFtZV07XG4gICAgICAgIHZhciBfbW9kdWxlID0gbW9kdWxlQ2FsY0RhdGFbMF1bMF0udHJhY2UuX21vZHVsZTtcblxuICAgICAgICBfbW9kdWxlLnBsb3QoZ2QsIHN1YnBsb3QsIExpYi5maWx0ZXJWaXNpYmxlKG1vZHVsZUNhbGNEYXRhKSwgc3VicGxvdExheW91dCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIG1vZHVsZU5hbWUgLT4gY2FsY0RhdGEgaGFzaFxuICAgIHN1YnBsb3QudHJhY2VIYXNoID0gdHJhY2VIYXNoO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cjogJ3N1YnBsb3QnLFxuICAgIG5hbWU6ICdwb2xhcicsXG5cbiAgICBheGlzTmFtZXM6IFsnYW5ndWxhcmF4aXMnLCAncmFkaWFsYXhpcyddLFxuICAgIGF4aXNOYW1lMmRhdGFBcnJheToge2FuZ3VsYXJheGlzOiAndGhldGEnLCByYWRpYWxheGlzOiAncid9LFxuXG4gICAgbGF5ZXJOYW1lczogW1xuICAgICAgICAnZHJhZ2xheWVyJyxcbiAgICAgICAgJ3Bsb3RiZycsXG4gICAgICAgICdiYWNrcGxvdCcsXG4gICAgICAgICdhbmd1bGFyLWdyaWQnLFxuICAgICAgICAncmFkaWFsLWdyaWQnLFxuICAgICAgICAnZnJvbnRwbG90JyxcbiAgICAgICAgJ2FuZ3VsYXItbGluZScsXG4gICAgICAgICdyYWRpYWwtbGluZScsXG4gICAgICAgICdhbmd1bGFyLWF4aXMnLFxuICAgICAgICAncmFkaWFsLWF4aXMnXG4gICAgXSxcblxuICAgIHJhZGlhbERyYWdCb3hTaXplOiA1MCxcbiAgICBhbmd1bGFyRHJhZ0JveFNpemU6IDMwLFxuICAgIGNvcm5lckxlbjogMjUsXG4gICAgY29ybmVySGFsZldpZHRoOiAyLFxuXG4gICAgLy8gcGl4ZWxzIHRvIG1vdmUgbW91c2UgYmVmb3JlIHlvdSBzdG9wIGNsYW1waW5nIHRvIHN0YXJ0aW5nIHBvaW50XG4gICAgTUlORFJBRzogOCxcbiAgICAvLyBzbWFsbGVzdCByYWRpYWwgZGlzdGFuY2UgW3B4XSBhbGxvd2VkIGZvciBhIHpvb21ib3hcbiAgICBNSU5aT09NOiAyMCxcbiAgICAvLyBkaXN0YW5jZSBbcHhdIG9mZiAocj0wKSBvciAocj1yYWRpdXMpIHdoZXJlIHdlIHRyYW5zaXRpb25cbiAgICAvLyBmcm9tIHNpbmdsZS1zaWRlZCB0byB0d28tc2lkZWQgcmFkaWFsIHpvb21cbiAgICBPRkZFREdFOiAyMFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHBvbHlnb25UZXN0ZXIgPSByZXF1aXJlKCcuLi8uLi9saWIvcG9seWdvbicpLnRlc3RlcjtcblxudmFyIGZpbmRJbmRleE9mTWluID0gTGliLmZpbmRJbmRleE9mTWluO1xudmFyIGlzQW5nbGVJbnNpZGVTZWN0b3IgPSBMaWIuaXNBbmdsZUluc2lkZVNlY3RvcjtcbnZhciBhbmdsZURlbHRhID0gTGliLmFuZ2xlRGVsdGE7XG52YXIgYW5nbGVEaXN0ID0gTGliLmFuZ2xlRGlzdDtcblxuLyoqXG4gKiBpcyBwdCAocixhKSBpbnNpZGUgcG9seWdvbiBtYWRlIHVwIHZlcnRpY2VzIGF0IGFuZ2xlcyAndmFuZ2xlcydcbiAqIGluc2lkZSBhIGdpdmVuIHBvbGFyIHNlY3RvclxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSByIDogcHQncyByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEgOiBwdCdzIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSByQm5kcyA6IHNlY3RvcidzIHJhZGlhbCBib3VuZHNcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSBhQm5kcyA6IHNlY3RvcidzIGFuZ3VsYXIgYm91bmRzICpyYWRpYW5zKlxuICogQHBhcmFtIHthcnJheX0gdmFuZ2xlcyA6IGFuZ2xlcyBvZiBwb2x5Z29uIHZlcnRpY2VzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNQdEluc2lkZVBvbHlnb24ociwgYSwgckJuZHMsIGFCbmRzLCB2YW5nbGVzKSB7XG4gICAgaWYoIWlzQW5nbGVJbnNpZGVTZWN0b3IoYSwgYUJuZHMpKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgcjAsIHIxO1xuXG4gICAgaWYockJuZHNbMF0gPCByQm5kc1sxXSkge1xuICAgICAgICByMCA9IHJCbmRzWzBdO1xuICAgICAgICByMSA9IHJCbmRzWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHIwID0gckJuZHNbMV07XG4gICAgICAgIHIxID0gckJuZHNbMF07XG4gICAgfVxuXG4gICAgdmFyIHBvbHlnb25JbiA9IHBvbHlnb25UZXN0ZXIobWFrZVBvbHlnb24ocjAsIGFCbmRzWzBdLCBhQm5kc1sxXSwgdmFuZ2xlcykpO1xuICAgIHZhciBwb2x5Z29uT3V0ID0gcG9seWdvblRlc3RlcihtYWtlUG9seWdvbihyMSwgYUJuZHNbMF0sIGFCbmRzWzFdLCB2YW5nbGVzKSk7XG4gICAgdmFyIHh5ID0gW3IgKiBNYXRoLmNvcyhhKSwgciAqIE1hdGguc2luKGEpXTtcbiAgICByZXR1cm4gcG9seWdvbk91dC5jb250YWlucyh4eSkgJiYgIXBvbHlnb25Jbi5jb250YWlucyh4eSk7XG59XG5cbi8vIGZpbmQgaW50ZXJzZWN0aW9uIG9mICd2MCcgPC0+ICd2MScgZWRnZSB3aXRoIGEgcmF5IGF0IGFuZ2xlICdhJ1xuLy8gKGkuZS4gYSBsaW5lIHRoYXQgc3RhcnRzIGZyb20gdGhlIG9yaWdpbiBhdCBhbmdsZSAnYScpXG4vLyBnaXZlbiBhbiAoeHAseXApIHBhaXIgb24gdGhlICd2MCcgPC0+ICd2MScgbGluZVxuLy8gKE4uQi4gJ3YwJyBhbmQgJ3YxJyBhcmUgYW5nbGVzIGluIHJhZGlhbnMpXG5mdW5jdGlvbiBmaW5kSW50ZXJzZWN0aW9uWFkodjAsIHYxLCBhLCB4cHlwKSB7XG4gICAgdmFyIHhzdGFyLCB5c3RhcjtcblxuICAgIHZhciB4cCA9IHhweXBbMF07XG4gICAgdmFyIHlwID0geHB5cFsxXTtcbiAgICB2YXIgZHNpbiA9IGNsYW1wVGlueShNYXRoLnNpbih2MSkgLSBNYXRoLnNpbih2MCkpO1xuICAgIHZhciBkY29zID0gY2xhbXBUaW55KE1hdGguY29zKHYxKSAtIE1hdGguY29zKHYwKSk7XG4gICAgdmFyIHRhbkEgPSBNYXRoLnRhbihhKTtcbiAgICB2YXIgY290YW5BID0gY2xhbXBUaW55KDEgLyB0YW5BKTtcbiAgICB2YXIgbSA9IGRzaW4gLyBkY29zO1xuICAgIHZhciBiID0geXAgLSBtICogeHA7XG5cbiAgICBpZihjb3RhbkEpIHtcbiAgICAgICAgaWYoZHNpbiAmJiBkY29zKSB7XG4gICAgICAgICAgICAvLyBnaXZlblxuICAgICAgICAgICAgLy8gIGcoeCkgOj0gdjAgLT4gdjEgbGluZSA9IG0qeCArIGJcbiAgICAgICAgICAgIC8vICBoKHgpIDo9IHJheSBhdCBhbmdsZSAnYScgPSBtKnggPSB0YW5BKnhcbiAgICAgICAgICAgIC8vIHNvbHZlIGcoeHN0YXIpID0gaCh4c3RhcilcbiAgICAgICAgICAgIHhzdGFyID0gYiAvICh0YW5BIC0gbSk7XG4gICAgICAgICAgICB5c3RhciA9IHRhbkEgKiB4c3RhcjtcbiAgICAgICAgfSBlbHNlIGlmKGRjb3MpIHtcbiAgICAgICAgICAgIC8vIGhvcml6b250YWwgdjAgLT4gdjFcbiAgICAgICAgICAgIHhzdGFyID0geXAgKiBjb3RhbkE7XG4gICAgICAgICAgICB5c3RhciA9IHlwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdmVydGljYWwgdjAgLT4gdjFcbiAgICAgICAgICAgIHhzdGFyID0geHA7XG4gICAgICAgICAgICB5c3RhciA9IHhwICogdGFuQTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHZlcnRpY2FsIHJheVxuICAgICAgICBpZihkc2luICYmIGRjb3MpIHtcbiAgICAgICAgICAgIHhzdGFyID0gMDtcbiAgICAgICAgICAgIHlzdGFyID0gYjtcbiAgICAgICAgfSBlbHNlIGlmKGRjb3MpIHtcbiAgICAgICAgICAgIHhzdGFyID0gMDtcbiAgICAgICAgICAgIHlzdGFyID0geXA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBkb2VzIHRoaXMgY2FzZSBleGlzdHM/XG4gICAgICAgICAgICB4c3RhciA9IHlzdGFyID0gTmFOO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4c3RhciwgeXN0YXJdO1xufVxuXG4vLyBzb2x2ZXMgbF4yID0gKGYoeCleMiAtIHlwKV4yICsgKHggLSB4cCleMlxuLy8gcmVhcnJhbmdlZCBpbnRvIDAgPSBhKnheMiArIGIgKiB4ICsgY1xuLy9cbi8vIHdoZXJlIGYoeCkgPSBtKnggKyB0ICsgeXBcbi8vIGFuZCAgICh4MCwgeDEpID0gKC1iICsvLSBkZWwpIC8gKDIqYSlcbmZ1bmN0aW9uIGZpbmRYWWF0TGVuZ3RoKGwsIG0sIHhwLCB5cCkge1xuICAgIHZhciB0ID0gLW0gKiB4cDtcbiAgICB2YXIgYSA9IG0gKiBtICsgMTtcbiAgICB2YXIgYiA9IDIgKiAobSAqIHQgLSB4cCk7XG4gICAgdmFyIGMgPSB0ICogdCArIHhwICogeHAgLSBsICogbDtcbiAgICB2YXIgZGVsID0gTWF0aC5zcXJ0KGIgKiBiIC0gNCAqIGEgKiBjKTtcbiAgICB2YXIgeDAgPSAoLWIgKyBkZWwpIC8gKDIgKiBhKTtcbiAgICB2YXIgeDEgPSAoLWIgLSBkZWwpIC8gKDIgKiBhKTtcbiAgICByZXR1cm4gW1xuICAgICAgICBbeDAsIG0gKiB4MCArIHQgKyB5cF0sXG4gICAgICAgIFt4MSwgbSAqIHgxICsgdCArIHlwXVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIG1ha2VSZWd1bGFyUG9seWdvbihyLCB2YW5nbGVzKSB7XG4gICAgdmFyIGxlbiA9IHZhbmdsZXMubGVuZ3RoO1xuICAgIHZhciB2ZXJ0aWNlcyA9IG5ldyBBcnJheShsZW4gKyAxKTtcbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgdmEgPSB2YW5nbGVzW2ldO1xuICAgICAgICB2ZXJ0aWNlc1tpXSA9IFtyICogTWF0aC5jb3ModmEpLCByICogTWF0aC5zaW4odmEpXTtcbiAgICB9XG4gICAgdmVydGljZXNbaV0gPSB2ZXJ0aWNlc1swXS5zbGljZSgpO1xuICAgIHJldHVybiB2ZXJ0aWNlcztcbn1cblxuZnVuY3Rpb24gbWFrZUNsaXBwZWRQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcykge1xuICAgIHZhciBsZW4gPSB2YW5nbGVzLmxlbmd0aDtcbiAgICB2YXIgdmVydGljZXMgPSBbXTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZ1bmN0aW9uIGEyeHkoYSkge1xuICAgICAgICByZXR1cm4gW3IgKiBNYXRoLmNvcyhhKSwgciAqIE1hdGguc2luKGEpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaW5kWFkodmEwLCB2YTEsIHMpIHtcbiAgICAgICAgcmV0dXJuIGZpbmRJbnRlcnNlY3Rpb25YWSh2YTAsIHZhMSwgcywgYTJ4eSh2YTApKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjeWNsZUluZGV4KGluZCkge1xuICAgICAgICByZXR1cm4gTGliLm1vZChpbmQsIGxlbik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNJbnNpZGUodikge1xuICAgICAgICByZXR1cm4gaXNBbmdsZUluc2lkZVNlY3Rvcih2LCBbYTAsIGExXSk7XG4gICAgfVxuXG4gICAgLy8gZmluZCBpbmRleCBpbiBzZWN0b3IgY2xvc2VzdCB0byBhMFxuICAgIC8vIHVzZSBpdCB0byBmaW5kIGludGVyc2VjdGlvbiBvZiB2W2kwXSA8LT4gdltpMC0xXSBlZGdlIHdpdGggc2VjdG9yIHJhZGl1c1xuICAgIHZhciBpMCA9IGZpbmRJbmRleE9mTWluKHZhbmdsZXMsIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIGlzSW5zaWRlKHYpID8gYW5nbGVEaXN0KHYsIGEwKSA6IEluZmluaXR5O1xuICAgIH0pO1xuICAgIHZhciB4eTAgPSBmaW5kWFkodmFuZ2xlc1tpMF0sIHZhbmdsZXNbY3ljbGVJbmRleChpMCAtIDEpXSwgYTApO1xuICAgIHZlcnRpY2VzLnB1c2goeHkwKTtcblxuICAgIC8vIGZpbGwgaW4gaW4tc2VjdG9yIHZlcnRpY2VzXG4gICAgZm9yKGkgPSBpMCwgaiA9IDA7IGogPCBsZW47IGkrKywgaisrKSB7XG4gICAgICAgIHZhciB2YSA9IHZhbmdsZXNbY3ljbGVJbmRleChpKV07XG4gICAgICAgIGlmKCFpc0luc2lkZSh2YSkpIGJyZWFrO1xuICAgICAgICB2ZXJ0aWNlcy5wdXNoKGEyeHkodmEpKTtcbiAgICB9XG5cbiAgICAvLyBmaW5kIGluZGV4IGluIHNlY3RvciBjbG9zZXN0IHRvIGExLFxuICAgIC8vIHVzZSBpdCB0byBmaW5kIGludGVyc2VjdGlvbiBvZiB2W2lOXSA8LT4gdltpTisxXSBlZGdlIHdpdGggc2VjdG9yIHJhZGl1c1xuICAgIHZhciBpTiA9IGZpbmRJbmRleE9mTWluKHZhbmdsZXMsIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIGlzSW5zaWRlKHYpID8gYW5nbGVEaXN0KHYsIGExKSA6IEluZmluaXR5O1xuICAgIH0pO1xuICAgIHZhciB4eU4gPSBmaW5kWFkodmFuZ2xlc1tpTl0sIHZhbmdsZXNbY3ljbGVJbmRleChpTiArIDEpXSwgYTEpO1xuICAgIHZlcnRpY2VzLnB1c2goeHlOKTtcblxuICAgIHZlcnRpY2VzLnB1c2goWzAsIDBdKTtcbiAgICB2ZXJ0aWNlcy5wdXNoKHZlcnRpY2VzWzBdLnNsaWNlKCkpO1xuXG4gICAgcmV0dXJuIHZlcnRpY2VzO1xufVxuXG5mdW5jdGlvbiBtYWtlUG9seWdvbihyLCBhMCwgYTEsIHZhbmdsZXMpIHtcbiAgICByZXR1cm4gTGliLmlzRnVsbENpcmNsZShbYTAsIGExXSkgP1xuICAgICAgICBtYWtlUmVndWxhclBvbHlnb24ociwgdmFuZ2xlcykgOlxuICAgICAgICBtYWtlQ2xpcHBlZFBvbHlnb24ociwgYTAsIGExLCB2YW5nbGVzKTtcbn1cblxuZnVuY3Rpb24gZmluZFBvbHlnb25PZmZzZXQociwgYTAsIGExLCB2YW5nbGVzKSB7XG4gICAgdmFyIG1pblggPSBJbmZpbml0eTtcbiAgICB2YXIgbWluWSA9IEluZmluaXR5O1xuICAgIHZhciB2ZXJ0aWNlcyA9IG1ha2VQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcyk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHYgPSB2ZXJ0aWNlc1tpXTtcbiAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIHZbMF0pO1xuICAgICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgLXZbMV0pO1xuICAgIH1cbiAgICByZXR1cm4gW21pblgsIG1pblldO1xufVxuXG4vKipcbiAqIGZpbmQgdmVydGV4IGFuZ2xlcyAoaW4gJ3ZhbmdsZXMnKSB0aGUgZW5jbG9zZSBhbmdsZSAnYSdcbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYSA6IGFuZ2xlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHthcnJheX0gdmFuZ2xlcyA6IGFuZ2xlcyBvZiBwb2x5Z29uIHZlcnRpY2VzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Mi1pdGVtIGFycmF5fVxuICovXG5mdW5jdGlvbiBmaW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzKGEsIHZhbmdsZXMpIHtcbiAgICB2YXIgbWluRm4gPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBhZGVsdGEgPSBhbmdsZURlbHRhKHYsIGEpO1xuICAgICAgICByZXR1cm4gYWRlbHRhID4gMCA/IGFkZWx0YSA6IEluZmluaXR5O1xuICAgIH07XG4gICAgdmFyIGkwID0gZmluZEluZGV4T2ZNaW4odmFuZ2xlcywgbWluRm4pO1xuICAgIHZhciBpMSA9IExpYi5tb2QoaTAgKyAxLCB2YW5nbGVzLmxlbmd0aCk7XG4gICAgcmV0dXJuIFt2YW5nbGVzW2kwXSwgdmFuZ2xlc1tpMV1dO1xufVxuXG4vLyB0byBtb3JlIGVhc2lseSBjYXRjaCAnYWxtb3N0IHplcm8nIG51bWJlcnMgaW4gaWYtZWxzZSBibG9ja3NcbmZ1bmN0aW9uIGNsYW1wVGlueSh2KSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKHYpID4gMWUtMTAgPyB2IDogMDtcbn1cblxuZnVuY3Rpb24gdHJhbnNmb3JtRm9yU1ZHKHB0czAsIGN4LCBjeSkge1xuICAgIGN4ID0gY3ggfHwgMDtcbiAgICBjeSA9IGN5IHx8IDA7XG5cbiAgICB2YXIgbGVuID0gcHRzMC5sZW5ndGg7XG4gICAgdmFyIHB0czEgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgcHQgPSBwdHMwW2ldO1xuICAgICAgICBwdHMxW2ldID0gW2N4ICsgcHRbMF0sIGN5IC0gcHRbMV1dO1xuICAgIH1cbiAgICByZXR1cm4gcHRzMTtcbn1cblxuLyoqXG4gKiBwYXRoIHBvbHlnb25cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gciA6IHBvbHlnb24gJ3JhZGl1cydcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMCA6IGZpcnN0IGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMSA6IHNlY29uZCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge2FycmF5fSB2YW5nbGVzIDogYW5nbGVzIG9mIHBvbHlnb24gdmVydGljZXMgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeCA6IHggY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN5IDogeSBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHJldHVybiB7c3RyaW5nfSBzdmcgcGF0aFxuICpcbiAqL1xuZnVuY3Rpb24gcGF0aFBvbHlnb24ociwgYTAsIGExLCB2YW5nbGVzLCBjeCwgY3kpIHtcbiAgICB2YXIgcG9seSA9IG1ha2VQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcyk7XG4gICAgcmV0dXJuICdNJyArIHRyYW5zZm9ybUZvclNWRyhwb2x5LCBjeCwgY3kpLmpvaW4oJ0wnKTtcbn1cblxuLyoqXG4gKiBwYXRoIGEgcG9seWdvbiAnYW5udWx1cydcbiAqIGkuZS4gYSBwb2x5Z29uIHdpdGggYSBjb25jZW50cmljIGhvbGVcbiAqXG4gKiBOLkIuIHRoaXMgcm91dGluZSB1c2VzIHRoZSBldmVub2RkIFNWRyBydWxlXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHIwIDogZmlyc3QgcmFkaWFsIGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByMSA6IHNlY29uZCByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEwIDogZmlyc3QgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXJ9IGExIDogc2Vjb25kIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7YXJyYXl9IHZhbmdsZXMgOiBhbmdsZXMgb2YgcG9seWdvbiB2ZXJ0aWNlcyBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN4IDogeCBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3kgOiB5IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHN2ZyBwYXRoXG4gKlxuICovXG5mdW5jdGlvbiBwYXRoUG9seWdvbkFubnVsdXMocjAsIHIxLCBhMCwgYTEsIHZhbmdsZXMsIGN4LCBjeSkge1xuICAgIHZhciByU3RhcnQsIHJFbmQ7XG5cbiAgICBpZihyMCA8IHIxKSB7XG4gICAgICAgIHJTdGFydCA9IHIwO1xuICAgICAgICByRW5kID0gcjE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgclN0YXJ0ID0gcjE7XG4gICAgICAgIHJFbmQgPSByMDtcbiAgICB9XG5cbiAgICB2YXIgaW5uZXIgPSB0cmFuc2Zvcm1Gb3JTVkcobWFrZVBvbHlnb24oclN0YXJ0LCBhMCwgYTEsIHZhbmdsZXMpLCBjeCwgY3kpO1xuICAgIHZhciBvdXRlciA9IHRyYW5zZm9ybUZvclNWRyhtYWtlUG9seWdvbihyRW5kLCBhMCwgYTEsIHZhbmdsZXMpLCBjeCwgY3kpO1xuICAgIHJldHVybiAnTScgKyBvdXRlci5yZXZlcnNlKCkuam9pbignTCcpICsgJ00nICsgaW5uZXIuam9pbignTCcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBpc1B0SW5zaWRlUG9seWdvbjogaXNQdEluc2lkZVBvbHlnb24sXG4gICAgZmluZFBvbHlnb25PZmZzZXQ6IGZpbmRQb2x5Z29uT2Zmc2V0LFxuICAgIGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXM6IGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXMsXG4gICAgZmluZEludGVyc2VjdGlvblhZOiBmaW5kSW50ZXJzZWN0aW9uWFksXG4gICAgZmluZFhZYXRMZW5ndGg6IGZpbmRYWWF0TGVuZ3RoLFxuICAgIGNsYW1wVGlueTogY2xhbXBUaW55LFxuICAgIHBhdGhQb2x5Z29uOiBwYXRoUG9seWdvbixcbiAgICBwYXRoUG9seWdvbkFubnVsdXM6IHBhdGhQb2x5Z29uQW5udWx1c1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGdldFN1YnBsb3RDYWxjRGF0YSA9IHJlcXVpcmUoJy4uL2dldF9kYXRhJykuZ2V0U3VicGxvdENhbGNEYXRhO1xudmFyIGNvdW50ZXJSZWdleCA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmNvdW50ZXJSZWdleDtcblxudmFyIGNyZWF0ZVBvbGFyID0gcmVxdWlyZSgnLi9wb2xhcicpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbnZhciBhdHRyID0gY29uc3RhbnRzLmF0dHI7XG52YXIgbmFtZSA9IGNvbnN0YW50cy5uYW1lO1xudmFyIGNvdW50ZXIgPSBjb3VudGVyUmVnZXgobmFtZSk7XG5cbnZhciBhdHRyaWJ1dGVzID0ge307XG5hdHRyaWJ1dGVzW2F0dHJdID0ge1xuICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgIFxuICAgIGRmbHQ6IG5hbWUsXG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBcbn07XG5cbmZ1bmN0aW9uIHBsb3QoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjYWxjRGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBzdWJwbG90SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbbmFtZV07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBzdWJwbG90SWRzW2ldO1xuICAgICAgICB2YXIgc3VicGxvdENhbGNEYXRhID0gZ2V0U3VicGxvdENhbGNEYXRhKGNhbGNEYXRhLCBuYW1lLCBpZCk7XG4gICAgICAgIHZhciBzdWJwbG90ID0gZnVsbExheW91dFtpZF0uX3N1YnBsb3Q7XG5cbiAgICAgICAgaWYoIXN1YnBsb3QpIHtcbiAgICAgICAgICAgIHN1YnBsb3QgPSBjcmVhdGVQb2xhcihnZCwgaWQpO1xuICAgICAgICAgICAgZnVsbExheW91dFtpZF0uX3N1YnBsb3QgPSBzdWJwbG90O1xuICAgICAgICB9XG5cbiAgICAgICAgc3VicGxvdC5wbG90KHN1YnBsb3RDYWxjRGF0YSwgZnVsbExheW91dCwgZ2QuX3Byb21pc2VzKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNsZWFuKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRJZHMgPSBvbGRGdWxsTGF5b3V0Ll9zdWJwbG90c1tuYW1lXSB8fCBbXTtcbiAgICB2YXIgaGFkR2wgPSAob2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcygnZ2wnKSk7XG4gICAgdmFyIGhhc0dsID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2dsJykpO1xuICAgIHZhciBtdXN0Q2xlYW5TY2VuZSA9IGhhZEdsICYmICFoYXNHbDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gb2xkSWRzW2ldO1xuICAgICAgICB2YXIgb2xkU3VicGxvdCA9IG9sZEZ1bGxMYXlvdXRbaWRdLl9zdWJwbG90O1xuXG4gICAgICAgIGlmKCFuZXdGdWxsTGF5b3V0W2lkXSAmJiAhIW9sZFN1YnBsb3QpIHtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QuZnJhbWV3b3JrLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkU3VicGxvdC5sYXllcnNbJ3JhZGlhbC1heGlzLXRpdGxlJ10ucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgayBpbiBvbGRTdWJwbG90LmNsaXBQYXRocykge1xuICAgICAgICAgICAgICAgIG9sZFN1YnBsb3QuY2xpcFBhdGhzW2tdLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYobXVzdENsZWFuU2NlbmUgJiYgb2xkU3VicGxvdC5fc2NlbmUpIHtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QuX3NjZW5lLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QuX3NjZW5lID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cjogYXR0cixcbiAgICBuYW1lOiBuYW1lLFxuICAgIGlkUm9vdDogbmFtZSxcbiAgICBpZFJlZ2V4OiBjb3VudGVyLFxuICAgIGF0dHJSZWdleDogY291bnRlcixcbiAgICBhdHRyaWJ1dGVzOiBhdHRyaWJ1dGVzLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogcmVxdWlyZSgnLi9sYXlvdXRfZGVmYXVsdHMnKSxcbiAgICBwbG90OiBwbG90LFxuICAgIGNsZWFuOiBjbGVhbixcbiAgICB0b1NWRzogcmVxdWlyZSgnLi4vY2FydGVzaWFuJykudG9TVkdcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgYXhlc0F0dHJzID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgZG9tYWluQXR0cnMgPSByZXF1aXJlKCcuLi9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWInKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgYXhpc0xpbmVHcmlkQXR0ciA9IG92ZXJyaWRlQWxsKHtcbiAgICBjb2xvcjogYXhlc0F0dHJzLmNvbG9yLFxuICAgIHNob3dsaW5lOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMuc2hvd2xpbmUsIHtkZmx0OiB0cnVlfSksXG4gICAgbGluZWNvbG9yOiBheGVzQXR0cnMubGluZWNvbG9yLFxuICAgIGxpbmV3aWR0aDogYXhlc0F0dHJzLmxpbmV3aWR0aCxcbiAgICBzaG93Z3JpZDogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnNob3dncmlkLCB7ZGZsdDogdHJ1ZX0pLFxuICAgIGdyaWRjb2xvcjogYXhlc0F0dHJzLmdyaWRjb2xvcixcbiAgICBncmlkd2lkdGg6IGF4ZXNBdHRycy5ncmlkd2lkdGhcblxuICAgIC8vIFRPRE8gYWRkIHNwaWtlKiBhdHRyaWJ1dGVzIGRvd24gdGhlIHJvYWRcblxuICAgIC8vIHNob3VsZCB3ZSBhZGQgemVyb2xpbmUqIGF0dHJpYnV0ZXM/XG5cbn0sICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuXG52YXIgYXhpc1RpY2tBdHRycyA9IG92ZXJyaWRlQWxsKHtcbiAgICB0aWNrbW9kZTogYXhlc0F0dHJzLnRpY2ttb2RlLFxuICAgIG50aWNrczogYXhlc0F0dHJzLm50aWNrcyxcbiAgICB0aWNrMDogYXhlc0F0dHJzLnRpY2swLFxuICAgIGR0aWNrOiBheGVzQXR0cnMuZHRpY2ssXG4gICAgdGlja3ZhbHM6IGF4ZXNBdHRycy50aWNrdmFscyxcbiAgICB0aWNrdGV4dDogYXhlc0F0dHJzLnRpY2t0ZXh0LFxuICAgIHRpY2tzOiBheGVzQXR0cnMudGlja3MsXG4gICAgdGlja2xlbjogYXhlc0F0dHJzLnRpY2tsZW4sXG4gICAgdGlja3dpZHRoOiBheGVzQXR0cnMudGlja3dpZHRoLFxuICAgIHRpY2tjb2xvcjogYXhlc0F0dHJzLnRpY2tjb2xvcixcbiAgICBzaG93dGlja2xhYmVsczogYXhlc0F0dHJzLnNob3d0aWNrbGFiZWxzLFxuICAgIHNob3d0aWNrcHJlZml4OiBheGVzQXR0cnMuc2hvd3RpY2twcmVmaXgsXG4gICAgdGlja3ByZWZpeDogYXhlc0F0dHJzLnRpY2twcmVmaXgsXG4gICAgc2hvd3RpY2tzdWZmaXg6IGF4ZXNBdHRycy5zaG93dGlja3N1ZmZpeCxcbiAgICB0aWNrc3VmZml4OiBheGVzQXR0cnMudGlja3N1ZmZpeCxcbiAgICBzaG93ZXhwb25lbnQ6IGF4ZXNBdHRycy5zaG93ZXhwb25lbnQsXG4gICAgZXhwb25lbnRmb3JtYXQ6IGF4ZXNBdHRycy5leHBvbmVudGZvcm1hdCxcbiAgICBzZXBhcmF0ZXRob3VzYW5kczogYXhlc0F0dHJzLnNlcGFyYXRldGhvdXNhbmRzLFxuICAgIHRpY2tmb250OiBheGVzQXR0cnMudGlja2ZvbnQsXG4gICAgdGlja2FuZ2xlOiBheGVzQXR0cnMudGlja2FuZ2xlLFxuICAgIHRpY2tmb3JtYXQ6IGF4ZXNBdHRycy50aWNrZm9ybWF0LFxuICAgIHRpY2tmb3JtYXRzdG9wczogYXhlc0F0dHJzLnRpY2tmb3JtYXRzdG9wcyxcbiAgICBsYXllcjogYXhlc0F0dHJzLmxheWVyXG59LCAncGxvdCcsICdmcm9tLXJvb3QnKTtcblxudmFyIHJhZGlhbEF4aXNBdHRycyA9IHtcbiAgICB2aXNpYmxlOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMudmlzaWJsZSwge2RmbHQ6IHRydWV9KSxcbiAgICB0eXBlOiBheGVzQXR0cnMudHlwZSxcblxuICAgIGF1dG9yYW5nZTogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLmF1dG9yYW5nZSwge2VkaXRUeXBlOiAncGxvdCd9KSxcbiAgICByYW5nZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsndG96ZXJvJywgJ25vbm5lZ2F0aXZlJywgJ25vcm1hbCddLFxuICAgICAgICBkZmx0OiAndG96ZXJvJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5yYW5nZSwge1xuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3Bsb3QnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfX0sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAncGxvdCcsIGltcGxpZWRFZGl0czogeydeYXV0b3JhbmdlJzogZmFsc2V9fVxuICAgICAgICBdLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSksXG5cbiAgICBjYXRlZ29yeW9yZGVyOiBheGVzQXR0cnMuY2F0ZWdvcnlvcmRlcixcbiAgICBjYXRlZ29yeWFycmF5OiBheGVzQXR0cnMuY2F0ZWdvcnlhcnJheSxcblxuICAgIGFuZ2xlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbmdsZScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2lkZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIC8vIFRPRE8gYWRkICdjZW50ZXInIGZvciBgc2hvd2xpbmU6IGZhbHNlYCByYWRpYWwgYXhlc1xuICAgICAgICB2YWx1ZXM6IFsnY2xvY2t3aXNlJywgJ2NvdW50ZXJjbG9ja3dpc2UnXSxcbiAgICAgICAgZGZsdDogJ2Nsb2Nrd2lzZScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG5cbiAgICB0aXRsZTogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnRpdGxlLCB7ZWRpdFR5cGU6ICdwbG90JywgZGZsdDogJyd9KSxcbiAgICB0aXRsZWZvbnQ6IG92ZXJyaWRlQWxsKGF4ZXNBdHRycy50aXRsZWZvbnQsICdwbG90JywgJ2Zyb20tcm9vdCcpLFxuICAgIC8vIG1pZ2h0IG5lZWQgYSAndGl0bGVzaWRlJyBhbmQgZXZlbiAndGl0bGVkaXJlY3Rpb24nIGRvd24gdGhlIHJvYWRcblxuICAgIGhvdmVyZm9ybWF0OiBheGVzQXR0cnMuaG92ZXJmb3JtYXQsXG5cbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHRlbmRGbGF0KFxuICAgIHJhZGlhbEF4aXNBdHRycyxcblxuICAgIC8vIE4uQi4gcmFkaWFsYXhpcyBncmlkIGxpbmVzIGFyZSBjaXJjdWxhcixcbiAgICAvLyBidXQgcmFkaWFsYXhpcyBsaW5lcyBhcmUgc3RyYWlnaHQgZnJvbSBjaXJjbGUgY2VudGVyIHRvIG91dGVyIGJvdW5kXG4gICAgYXhpc0xpbmVHcmlkQXR0cixcbiAgICBheGlzVGlja0F0dHJzXG4pO1xuXG52YXIgYW5ndWxhckF4aXNBdHRycyA9IHtcbiAgICB2aXNpYmxlOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMudmlzaWJsZSwge2RmbHQ6IHRydWV9KSxcbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgLy8gJ2xpbmVhcicgc2hvdWxkIG1heWJlIGJlIGNhbGxlZCAnYW5nbGUnIG9yICdhbmd1bGFyJyBoZXJlXG4gICAgICAgIC8vIHRvIG1ha2UgY2xlYXIgdGhhdCBheGlzIGhlcmUgaXMgcGVyaW9kaWMgYW5kIG1vcmUgdGlnaHRseSBtYXRjaFxuICAgICAgICAvLyBgdGhldGF1bml0YD9cbiAgICAgICAgLy9cbiAgICAgICAgLy8gc2tpcCAnZGF0ZScgZm9yIGZpcnN0IHB1c2hcbiAgICAgICAgLy8gbm8gJ2xvZycgZm9yIG5vd1xuICAgICAgICB2YWx1ZXM6IFsnLScsICdsaW5lYXInLCAnY2F0ZWdvcnknXSxcbiAgICAgICAgZGZsdDogJy0nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgX25vVGVtcGxhdGluZzogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGNhdGVnb3J5b3JkZXI6IGF4ZXNBdHRycy5jYXRlZ29yeW9yZGVyLFxuICAgIGNhdGVnb3J5YXJyYXk6IGF4ZXNBdHRycy5jYXRlZ29yeWFycmF5LFxuXG4gICAgdGhldGF1bml0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3JhZGlhbnMnLCAnZGVncmVlcyddLFxuICAgICAgICBkZmx0OiAnZGVncmVlcycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcGVyaW9kOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLy8gRXhhbXBsZXMgZm9yIGRhdGUgYXhlczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gLSBwZXJpb2QgdGhhdCBlcXVhbHMgdGhlIHRpbWVzZXJpZXMgbGVuZ3RoXG4gICAgICAgIC8vICBodHRwOi8vZmxvd2luZ2RhdGEuY29tLzIwMTcvMDEvMjQvb25lLWRhdGFzZXQtdmlzdWFsaXplZC0yNS13YXlzLzE4LXBvbGFyLWNvb3JkaW5hdGVzL1xuICAgICAgICAvLyAtIGFuZCAxLXllYXIgcGVyaW9kcyAoZm9jdXNpbmcgb24gc2Vhc29uYWwgY2hhbmdlMFxuICAgICAgICAvLyAgaHR0cDovL290ZXh0cy5vcmcvZnBwMi9zZWFzb25hbC1wbG90cy5odG1sXG4gICAgICAgIC8vICBodHRwczovL2Jsb2dzLnNjaWVudGlmaWNhbWVyaWNhbi5jb20vc2EtdmlzdWFsL3doeS1hcmUtc28tbWFueS1iYWJpZXMtYm9ybi1hcm91bmQtOC0wMC1hLW0vXG4gICAgICAgIC8vICBodHRwOi8vd3d3LnNlYXNvbmFsYWRqdXN0bWVudC5jb20vMjAxMi8wOS8wNS9jbG9jay1wbG90LXZpc3VhbGlzaW5nLXNlYXNvbmFsaXR5LXVzaW5nLXItYW5kLWdncGxvdDItcGFydC0zL1xuICAgICAgICAvLyAgaHR0cHM6Ly9pLnBpbmltZy5jb20vNzM2eC80OS9iOS83Mi80OWI5NzJjY2IzMjA2YTFhNmQ2Zjg3MGRhYzU0MzI4MC5qcGdcbiAgICAgICAgLy8gIGh0dHBzOi8vd3d3LmNsaW1hdGUtbGFiLWJvb2suYWMudWsvc3BpcmFscy9cbiAgICB9LFxuXG4gICAgZGlyZWN0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2NvdW50ZXJjbG9ja3dpc2UnLCAnY2xvY2t3aXNlJ10sXG4gICAgICAgIGRmbHQ6ICdjb3VudGVyY2xvY2t3aXNlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICByb3RhdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW5nbGUnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGhvdmVyZm9ybWF0OiBheGVzQXR0cnMuaG92ZXJmb3JtYXQsXG5cbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHRlbmRGbGF0KFxuICAgIGFuZ3VsYXJBeGlzQXR0cnMsXG5cbiAgICAvLyBOLkIuIGFuZ3VsYXIgZ3JpZCBsaW5lcyBhcmUgc3RyYWlnaHQgbGluZXMgZnJvbSBjaXJjbGUgY2VudGVyIHRvIG91dGVyIGJvdW5kXG4gICAgLy8gdGhlIGFuZ3VsYXIgbGluZSBpcyBjaXJjdWxhciBib3VuZGluZyB0aGUgcG9sYXIgcGxvdCBhcmVhLlxuICAgIGF4aXNMaW5lR3JpZEF0dHIsXG5cbiAgICAvLyBOLkIuIHRpY2tzdWZmaXggZGVmYXVsdHMgdG8gJ8KwJyBmb3IgYW5ndWxhciBheGVzIHdpdGggYHRoZXRhdW5pdDogJ2RlZ3JlZXMnYFxuICAgIGF4aXNUaWNrQXR0cnNcbik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8vIFRPRE8gZm9yIHgveS96b29tIHN5c3RlbSBmb3IgcGFwZXItYmFzZWQgem9vbWluZzpcbiAgICAvLyB4OiB7fSxcbiAgICAvLyB5OiB7fSxcbiAgICAvLyB6b29tOiB7fSxcblxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdwb2xhcicsIGVkaXRUeXBlOiAncGxvdCd9KSxcblxuICAgIHNlY3Rvcjoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAncGxvdCd9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBlZGl0VHlwZTogJ3Bsb3QnfVxuICAgICAgICBdLFxuICAgICAgICBkZmx0OiBbMCwgMzYwXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG9sZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5iYWNrZ3JvdW5kLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcmFkaWFsYXhpczogcmFkaWFsQXhpc0F0dHJzLFxuICAgIGFuZ3VsYXJheGlzOiBhbmd1bGFyQXhpc0F0dHJzLFxuXG4gICAgZ3JpZHNoYXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2NpcmN1bGFyJywgJ2xpbmVhciddLFxuICAgICAgICBkZmx0OiAnY2lyY3VsYXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIFRPRE8gbWF5YmU/XG4gICAgLy8gYW5ub3RhdGlvbnM6XG5cbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbnZhciBoYW5kbGVTdWJwbG90RGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zdWJwbG90X2RlZmF1bHRzJyk7XG52YXIgZ2V0U3VicGxvdERhdGEgPSByZXF1aXJlKCcuLi9nZXRfZGF0YScpLmdldFN1YnBsb3REYXRhO1xuXG52YXIgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vdGlja192YWx1ZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tNYXJrRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vdGlja19tYXJrX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vdGlja19sYWJlbF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNhdGVnb3J5T3JkZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9jYXRlZ29yeV9vcmRlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVHcmlkRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vbGluZV9ncmlkX2RlZmF1bHRzJyk7XG52YXIgYXV0b1R5cGUgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vYXhpc19hdXRvdHlwZScpO1xuXG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBzZXRDb252ZXJ0ID0gcmVxdWlyZSgnLi9zZXRfY29udmVydCcpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgYXhpc05hbWVzID0gY29uc3RhbnRzLmF4aXNOYW1lcztcblxuZnVuY3Rpb24gaGFuZGxlRGVmYXVsdHMoY29udEluLCBjb250T3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICB2YXIgYmdDb2xvciA9IGNvZXJjZSgnYmdjb2xvcicpO1xuICAgIG9wdHMuYmdDb2xvciA9IENvbG9yLmNvbWJpbmUoYmdDb2xvciwgb3B0cy5wYXBlcl9iZ2NvbG9yKTtcblxuICAgIHZhciBzZWN0b3IgPSBjb2VyY2UoJ3NlY3RvcicpO1xuICAgIGNvZXJjZSgnaG9sZScpO1xuXG4gICAgLy8gY291bGQgb3B0aW1pemUsIHN1YnBsb3REYXRhIGlzIG5vdCBhbHdheXMgbmVlZGVkIVxuICAgIHZhciBzdWJwbG90RGF0YSA9IGdldFN1YnBsb3REYXRhKG9wdHMuZnVsbERhdGEsIGNvbnN0YW50cy5uYW1lLCBvcHRzLmlkKTtcbiAgICB2YXIgbGF5b3V0T3V0ID0gb3B0cy5sYXlvdXRPdXQ7XG4gICAgdmFyIGF4TmFtZTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZUF4aXMoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gY29lcmNlKGF4TmFtZSArICcuJyArIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheGlzTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXhOYW1lID0gYXhpc05hbWVzW2ldO1xuXG4gICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChjb250SW5bYXhOYW1lXSkpIHtcbiAgICAgICAgICAgIGNvbnRJbltheE5hbWVdID0ge307XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYXhJbiA9IGNvbnRJbltheE5hbWVdO1xuICAgICAgICB2YXIgYXhPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIoY29udE91dCwgYXhOYW1lKTtcbiAgICAgICAgYXhPdXQuX2lkID0gYXhPdXQuX25hbWUgPSBheE5hbWU7XG4gICAgICAgIGF4T3V0Ll90cmFjZUluZGljZXMgPSBzdWJwbG90RGF0YS5tYXAoZnVuY3Rpb24odCkgeyByZXR1cm4gdC5fZXhwYW5kZWRJbmRleDsgfSk7XG5cbiAgICAgICAgdmFyIGRhdGFBdHRyID0gY29uc3RhbnRzLmF4aXNOYW1lMmRhdGFBcnJheVtheE5hbWVdO1xuICAgICAgICB2YXIgYXhUeXBlID0gaGFuZGxlQXhpc1R5cGVEZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlQXhpcywgc3VicGxvdERhdGEsIGRhdGFBdHRyKTtcblxuICAgICAgICBoYW5kbGVDYXRlZ29yeU9yZGVyRGVmYXVsdHMoYXhJbiwgYXhPdXQsIGNvZXJjZUF4aXMsIHtcbiAgICAgICAgICAgIGF4RGF0YTogc3VicGxvdERhdGEsXG4gICAgICAgICAgICBkYXRhQXR0cjogZGF0YUF0dHJcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIHZpc2libGUgPSBjb2VyY2VBeGlzKCd2aXNpYmxlJyk7XG4gICAgICAgIHNldENvbnZlcnQoYXhPdXQsIGNvbnRPdXQsIGxheW91dE91dCk7XG5cbiAgICAgICAgdmFyIGRmbHRDb2xvcjtcbiAgICAgICAgdmFyIGRmbHRGb250Q29sb3I7XG5cbiAgICAgICAgaWYodmlzaWJsZSkge1xuICAgICAgICAgICAgZGZsdENvbG9yID0gY29lcmNlQXhpcygnY29sb3InKTtcbiAgICAgICAgICAgIGRmbHRGb250Q29sb3IgPSAoZGZsdENvbG9yID09PSBheEluLmNvbG9yKSA/IGRmbHRDb2xvciA6IG9wdHMuZm9udC5jb2xvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gbWFrZSBkb3duc3RyZWFtIGNvZGUgY2FsbCBheC5zZXRTY2FsZSxcbiAgICAgICAgLy8gYXMgYm90aCByYWRpYWwgYW5kIGFuZ3VsYXIgYXhlcyBkb24ndCBoYXZlIGEgc2V0IGRvbWFpbi5cbiAgICAgICAgLy8gRnVydGhlcm1vcmUsIGFuZ3VsYXIgYXhlcyBkb24ndCBoYXZlIGEgc2V0IHJhbmdlLlxuICAgICAgICAvL1xuICAgICAgICAvLyBNb2NrZWQgZG9tYWlucyBhbmQgcmFuZ2VzIGFyZSBzZXQgYnkgdGhlIHBvbGFyIHN1YnBsb3QgaW5zdGFuY2VzLFxuICAgICAgICAvLyBidXQgQXhlcy5maW5kRXh0cmVtZXMgdXNlcyB0aGUgc2lnbiBvZiBfbSB0byBkZXRlcm1pbmUgd2hpY2ggcGFkZGluZyB2YWx1ZVxuICAgICAgICAvLyB0byB1c2UuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEJ5IHNldHRpbmcsIF9tIHRvIDEgaGVyZSwgd2UgbWFrZSBBeGVzLmZpbmRFeHRyZW1lcyB0aGluayB0aGF0XG4gICAgICAgIC8vIHJhbmdlWzFdID4gcmFuZ2VbMF0sIGFuZCB2aWNlLXZlcnNhIGZvciBgYXV0b3JhbmdlOiAncmV2ZXJzZWQnYCBiZWxvdy5cbiAgICAgICAgYXhPdXQuX20gPSAxO1xuXG4gICAgICAgIHN3aXRjaChheE5hbWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3JhZGlhbGF4aXMnOlxuICAgICAgICAgICAgICAgIHZhciBhdXRvUmFuZ2UgPSBjb2VyY2VBeGlzKCdhdXRvcmFuZ2UnLCAhYXhPdXQuaXNWYWxpZFJhbmdlKGF4SW4ucmFuZ2UpKTtcbiAgICAgICAgICAgICAgICBheEluLmF1dG9yYW5nZSA9IGF1dG9SYW5nZTtcbiAgICAgICAgICAgICAgICBpZihhdXRvUmFuZ2UgJiYgKGF4VHlwZSA9PT0gJ2xpbmVhcicgfHwgYXhUeXBlID09PSAnLScpKSBjb2VyY2VBeGlzKCdyYW5nZW1vZGUnKTtcbiAgICAgICAgICAgICAgICBpZihhdXRvUmFuZ2UgPT09ICdyZXZlcnNlZCcpIGF4T3V0Ll9tID0gLTE7XG5cbiAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCdyYW5nZScpO1xuICAgICAgICAgICAgICAgIGF4T3V0LmNsZWFuUmFuZ2UoJ3JhbmdlJywge2RmbHRSYW5nZTogWzAsIDFdfSk7XG5cbiAgICAgICAgICAgICAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3NpZGUnKTtcbiAgICAgICAgICAgICAgICAgICAgY29lcmNlQXhpcygnYW5nbGUnLCBzZWN0b3JbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3RpdGxlJyk7XG4gICAgICAgICAgICAgICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZUF4aXMsICd0aXRsZWZvbnQnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHk6IG9wdHMuZm9udC5mYW1pbHksXG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplOiBNYXRoLnJvdW5kKG9wdHMuZm9udC5zaXplICogMS4yKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBkZmx0Rm9udENvbG9yXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAnYW5ndWxhcmF4aXMnOlxuICAgICAgICAgICAgICAgIC8vIFdlIGRvIG5vdCBzdXBwb3J0ICd0cnVlJyBkYXRlIGFuZ3VsYXIgYXhlcyB5ZXQsXG4gICAgICAgICAgICAgICAgLy8gdXNlcnMgY2FuIHN0aWxsIHBsb3QgZGF0ZXMgb24gYW5ndWxhciBheGVzIGJ5IHNldHRpbmdcbiAgICAgICAgICAgICAgICAvLyBgYW5ndWxhcmF4aXMudHlwZTogJ2NhdGVnb3J5J2AuXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBIZXJlLCBpZiBhIGRhdGUgYW5ndWxhciBheGVzIGlzIGRldGVjdGVkLCB3ZSBtYWtlXG4gICAgICAgICAgICAgICAgLy8gYWxsIGl0cyBjb3JyZXNwb25kaW5nIHRyYWNlcyBpbnZpc2libGUsIHNvIHRoYXRcbiAgICAgICAgICAgICAgICAvLyB3aGVuIHdlIGRvIGFkZCBzdXBwb3J0IGZvciBkYXRhIGFuZ3VsYXIgYXhlcywgdGhlIG5ld1xuICAgICAgICAgICAgICAgIC8vIGJlaGF2aW9yIHdvbid0IGNvbmZsaWN0IHdpdGggZXhpc3RpbmcgYmVoYXZpb3JcbiAgICAgICAgICAgICAgICBpZihheFR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICBMaWIubG9nKCdQb2xhciBwbG90cyBkbyBub3Qgc3VwcG9ydCBkYXRlIGFuZ3VsYXIgYXhlcyB5ZXQuJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHN1YnBsb3REYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJwbG90RGF0YVtqXS52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyB0dXJuIHRoaXMgaW50byBhICdkdW1teScgbGluZWFyIGF4aXMgc28gdGhhdFxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc3VicGxvdCBzdGlsbCByZW5kZXJzIG9rXG4gICAgICAgICAgICAgICAgICAgIGF4VHlwZSA9IGF4SW4udHlwZSA9IGF4T3V0LnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihheFR5cGUgPT09ICdsaW5lYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3RoZXRhdW5pdCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3BlcmlvZCcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBjb2VyY2VBeGlzKCdkaXJlY3Rpb24nKTtcbiAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCdyb3RhdGlvbicsIHtjb3VudGVyY2xvY2t3aXNlOiAwLCBjbG9ja3dpc2U6IDkwfVtkaXJlY3Rpb25dKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgICAgIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2VBeGlzLCBheE91dC50eXBlKTtcbiAgICAgICAgICAgIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2VBeGlzLCBheE91dC50eXBlLCB7XG4gICAgICAgICAgICAgICAgdGlja1N1ZmZpeERmbHQ6IGF4T3V0LnRoZXRhdW5pdCA9PT0gJ2RlZ3JlZXMnID8gJ8KwJyA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBoYW5kbGVUaWNrTWFya0RlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2VBeGlzLCB7b3V0ZXJUaWNrczogdHJ1ZX0pO1xuXG4gICAgICAgICAgICB2YXIgc2hvd1RpY2tMYWJlbHMgPSBjb2VyY2VBeGlzKCdzaG93dGlja2xhYmVscycpO1xuICAgICAgICAgICAgaWYoc2hvd1RpY2tMYWJlbHMpIHtcbiAgICAgICAgICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2VBeGlzLCAndGlja2ZvbnQnLCB7XG4gICAgICAgICAgICAgICAgICAgIGZhbWlseTogb3B0cy5mb250LmZhbWlseSxcbiAgICAgICAgICAgICAgICAgICAgc2l6ZTogb3B0cy5mb250LnNpemUsXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBkZmx0Rm9udENvbG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29lcmNlQXhpcygndGlja2FuZ2xlJyk7XG4gICAgICAgICAgICAgICAgY29lcmNlQXhpcygndGlja2Zvcm1hdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoYW5kbGVMaW5lR3JpZERlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2VBeGlzLCB7XG4gICAgICAgICAgICAgICAgZGZsdENvbG9yOiBkZmx0Q29sb3IsXG4gICAgICAgICAgICAgICAgYmdDb2xvcjogb3B0cy5iZ0NvbG9yLFxuICAgICAgICAgICAgICAgIC8vIGRlZmF1bHQgZ3JpZCBjb2xvciBpcyBkYXJrZXIgaGVyZSAoNjAlLCB2cyBjYXJ0ZXNpYW4gZGVmYXVsdCB+OTElKVxuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIGdyaWQgaXMgbm90IHNxdWFyZSBzbyB0aGUgZXllIG5lZWRzIGhlYXZpZXIgY3VlcyB0byBmb2xsb3dcbiAgICAgICAgICAgICAgICBibGVuZDogNjAsXG4gICAgICAgICAgICAgICAgc2hvd0xpbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgc2hvd0dyaWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgbm9aZXJvTGluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzW2F4TmFtZV1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb2VyY2VBeGlzKCdsYXllcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXhUeXBlICE9PSAnY2F0ZWdvcnknKSBjb2VyY2VBeGlzKCdob3ZlcmZvcm1hdCcpO1xuXG4gICAgICAgIGF4T3V0Ll9pbnB1dCA9IGF4SW47XG4gICAgfVxuXG4gICAgaWYoY29udE91dC5hbmd1bGFyYXhpcy50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIGNvZXJjZSgnZ3JpZHNoYXBlJyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVBeGlzVHlwZURlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2UsIHN1YnBsb3REYXRhLCBkYXRhQXR0cikge1xuICAgIHZhciBheFR5cGUgPSBjb2VyY2UoJ3R5cGUnKTtcblxuICAgIGlmKGF4VHlwZSA9PT0gJy0nKSB7XG4gICAgICAgIHZhciB0cmFjZTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKHN1YnBsb3REYXRhW2ldLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB0cmFjZSA9IHN1YnBsb3REYXRhW2ldO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodHJhY2UgJiYgdHJhY2VbZGF0YUF0dHJdKSB7XG4gICAgICAgICAgICBheE91dC50eXBlID0gYXV0b1R5cGUodHJhY2VbZGF0YUF0dHJdLCAnZ3JlZ29yaWFuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihheE91dC50eXBlID09PSAnLScpIHtcbiAgICAgICAgICAgIGF4T3V0LnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvcHkgYXV0b1R5cGUgYmFjayB0byBpbnB1dCBheGlzXG4gICAgICAgICAgICAvLyBub3RlIHRoYXQgaWYgdGhpcyBvYmplY3QgZGlkbid0IGV4aXN0XG4gICAgICAgICAgICAvLyBpbiB0aGUgaW5wdXQgbGF5b3V0LCB3ZSBoYXZlIHRvIHB1dCBpdCBpblxuICAgICAgICAgICAgLy8gdGhpcyBoYXBwZW5zIGluIHRoZSBtYWluIHN1cHBseURlZmF1bHRzIGZ1bmN0aW9uXG4gICAgICAgICAgICBheEluLnR5cGUgPSBheE91dC50eXBlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGF4T3V0LnR5cGU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICBoYW5kbGVTdWJwbG90RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHtcbiAgICAgICAgdHlwZTogY29uc3RhbnRzLm5hbWUsXG4gICAgICAgIGF0dHJpYnV0ZXM6IGxheW91dEF0dHJpYnV0ZXMsXG4gICAgICAgIGhhbmRsZURlZmF1bHRzOiBoYW5kbGVEZWZhdWx0cyxcbiAgICAgICAgZm9udDogbGF5b3V0T3V0LmZvbnQsXG4gICAgICAgIHBhcGVyX2JnY29sb3I6IGxheW91dE91dC5wYXBlcl9iZ2NvbG9yLFxuICAgICAgICBmdWxsRGF0YTogZnVsbERhdGEsXG4gICAgICAgIGxheW91dE91dDogbGF5b3V0T3V0XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vLi4vdHJhY2VzL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJNYXJrZXJBdHRycyA9IHNjYXR0ZXJBdHRycy5tYXJrZXI7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgZGVwcmVjYXRpb25XYXJuaW5nID0gW1xuICAgICdBcmVhIHRyYWNlcyBhcmUgZGVwcmVjYXRlZCEnLFxuICAgICdQbGVhc2Ugc3dpdGNoIHRvIHRoZSAqYmFycG9sYXIqIHRyYWNlIHR5cGUuJ1xuXS5qb2luKCcgJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHI6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5yLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIG1hcmtlcjoge1xuICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLmNvbG9yLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHNpemU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHN5bWJvbDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLnN5bWJvbCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBvcGFjaXR5OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXhlc0F0dHJzID0gcmVxdWlyZSgnLi4vLi4vY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgZGVwcmVjYXRpb25XYXJuaW5nID0gW1xuICAgICdMZWdhY3kgcG9sYXIgY2hhcnRzIGFyZSBkZXByZWNhdGVkIScsXG4gICAgJ1BsZWFzZSBzd2l0Y2ggdG8gKnBvbGFyKiBzdWJwbG90cy4nXG5dLmpvaW4oJyAnKTtcblxudmFyIGRvbWFpbkF0dHIgPSBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMuZG9tYWluLCB7XG4gICAgXG59KTtcblxuZnVuY3Rpb24gbWVyZ2VBdHRycyhheGlzTmFtZSwgbm9uQ29tbW9uQXR0cnMpIHtcbiAgICB2YXIgY29tbW9uQXR0cnMgPSB7XG4gICAgICAgIHNob3dsaW5lOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaG93dGlja2xhYmVsczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGlja29yaWVudGF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnaG9yaXpvbnRhbCcsICd2ZXJ0aWNhbCddLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGlja2xlbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aWNrY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aWNrc3VmZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVuZHBhZGRpbmc6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogZGVwcmVjYXRpb25XYXJuaW5nLFxuICAgICAgICB9LFxuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBleHRlbmRGbGF0KHt9LCBub25Db21tb25BdHRycywgY29tbW9uQXR0cnMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICByYWRpYWxheGlzOiBtZXJnZUF0dHJzKCdyYWRpYWwnLCB7XG4gICAgICAgIHJhbmdlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICAgICAgeyB2YWxUeXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgIHsgdmFsVHlwZTogJ251bWJlcicgfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkb21haW46IGRvbWFpbkF0dHIsXG4gICAgICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9KSxcblxuICAgIGFuZ3VsYXJheGlzOiBtZXJnZUF0dHJzKCdhbmd1bGFyJywge1xuICAgICAgICByYW5nZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgICAgIHsgdmFsVHlwZTogJ251bWJlcicsIGRmbHQ6IDAgfSxcbiAgICAgICAgICAgICAgICB7IHZhbFR5cGU6ICdudW1iZXInLCBkZmx0OiAzNjAgfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkb21haW46IGRvbWFpbkF0dHJcbiAgICB9KSxcblxuICAgIC8vIGF0dHJpYnV0ZXMgdGhhdCBhcHBlYXIgYXQgbGF5b3V0IHJvb3RcbiAgICBsYXlvdXQ6IHtcbiAgICAgICAgZGlyZWN0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnY2xvY2t3aXNlJywgJ2NvdW50ZXJjbG9ja3dpc2UnXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYW5nbGUnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH1cbn0sICdwbG90JywgJ25lc3RlZCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9sYXIgPSBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbWljcm9wb2xhcicpO1xuXG5Qb2xhci5tYW5hZ2VyID0gcmVxdWlyZSgnLi9taWNyb3BvbGFyX21hbmFnZXInKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliJyk7XG52YXIgZXh0ZW5kRGVlcEFsbCA9IExpYi5leHRlbmREZWVwQWxsO1xudmFyIE1JRF9TSElGVCA9IHJlcXVpcmUoJy4uLy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5NSURfU0hJRlQ7XG5cbnZhciDCtSA9IG1vZHVsZS5leHBvcnRzID0geyB2ZXJzaW9uOiAnMC4yLjInIH07XG5cbsK1LkF4aXMgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogW10sXG4gICAgICAgIGxheW91dDoge31cbiAgICB9LCBpbnB1dENvbmZpZyA9IHt9LCBsaXZlQ29uZmlnID0ge307XG4gICAgdmFyIHN2ZywgY29udGFpbmVyLCBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpLCByYWRpYWxTY2FsZSwgYW5ndWxhclNjYWxlO1xuICAgIHZhciBleHBvcnRzID0ge307XG4gICAgZnVuY3Rpb24gcmVuZGVyKF9jb250YWluZXIpIHtcbiAgICAgICAgY29udGFpbmVyID0gX2NvbnRhaW5lciB8fCBjb250YWluZXI7XG4gICAgICAgIHZhciBkYXRhID0gY29uZmlnLmRhdGE7XG4gICAgICAgIHZhciBheGlzQ29uZmlnID0gY29uZmlnLmxheW91dDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb250YWluZXIgPT0gJ3N0cmluZycgfHwgY29udGFpbmVyLm5vZGVOYW1lKSBjb250YWluZXIgPSBkMy5zZWxlY3QoY29udGFpbmVyKTtcbiAgICAgICAgY29udGFpbmVyLmRhdHVtKGRhdGEpLmVhY2goZnVuY3Rpb24oX2RhdGEsIF9pbmRleCkge1xuICAgICAgICAgICAgdmFyIGRhdGFPcmlnaW5hbCA9IF9kYXRhLnNsaWNlKCk7XG4gICAgICAgICAgICBsaXZlQ29uZmlnID0ge1xuICAgICAgICAgICAgICAgIGRhdGE6IMK1LnV0aWwuY2xvbmVKc29uKGRhdGFPcmlnaW5hbCksXG4gICAgICAgICAgICAgICAgbGF5b3V0OiDCtS51dGlsLmNsb25lSnNvbihheGlzQ29uZmlnKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBjb2xvckluZGV4ID0gMDtcbiAgICAgICAgICAgIGRhdGFPcmlnaW5hbC5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWQuY29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZC5jb2xvciA9IGF4aXNDb25maWcuZGVmYXVsdENvbG9yUmFuZ2VbY29sb3JJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIGNvbG9ySW5kZXggPSAoY29sb3JJbmRleCArIDEpICUgYXhpc0NvbmZpZy5kZWZhdWx0Q29sb3JSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghZC5zdHJva2VDb2xvcikge1xuICAgICAgICAgICAgICAgICAgICBkLnN0cm9rZUNvbG9yID0gZC5nZW9tZXRyeSA9PT0gJ0xpbmVQbG90JyA/IGQuY29sb3IgOiBkMy5yZ2IoZC5jb2xvcikuZGFya2VyKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGl2ZUNvbmZpZy5kYXRhW2ldLmNvbG9yID0gZC5jb2xvcjtcbiAgICAgICAgICAgICAgICBsaXZlQ29uZmlnLmRhdGFbaV0uc3Ryb2tlQ29sb3IgPSBkLnN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgICAgIGxpdmVDb25maWcuZGF0YVtpXS5zdHJva2VEYXNoID0gZC5zdHJva2VEYXNoO1xuICAgICAgICAgICAgICAgIGxpdmVDb25maWcuZGF0YVtpXS5zdHJva2VTaXplID0gZC5zdHJva2VTaXplO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgZGF0YSA9IGRhdGFPcmlnaW5hbC5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciB2aXNpYmxlID0gZC52aXNpYmxlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgdmlzaWJsZSA9PT0gJ3VuZGVmaW5lZCcgfHwgdmlzaWJsZSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGlzU3RhY2tlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIGRhdGFXaXRoR3JvdXBJZCA9IGRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBpc1N0YWNrZWQgPSBpc1N0YWNrZWQgfHwgdHlwZW9mIGQuZ3JvdXBJZCAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBlZCA9IGQzLm5lc3QoKS5rZXkoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGQuZ3JvdXBJZCAhPSAndW5kZWZpbmVkJyA/IGQuZ3JvdXBJZCA6ICd1bnN0YWNrZWQnO1xuICAgICAgICAgICAgICAgIH0pLmVudHJpZXMoZGF0YVdpdGhHcm91cElkKTtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YVlTdGFjayA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzdGFja2VkID0gZ3JvdXBlZC5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZC5rZXkgPT09ICd1bnN0YWNrZWQnKSByZXR1cm4gZC52YWx1ZXM7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZBcnJheSA9IGQudmFsdWVzWzBdLnIubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgZC52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbihkLCBpLCBhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZC55U3RhY2sgPSBbIHByZXZBcnJheSBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFZU3RhY2sucHVzaChwcmV2QXJyYXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZBcnJheSA9IMK1LnV0aWwuc3VtQXJyYXlzKGQuciwgcHJldkFycmF5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGQudmFsdWVzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGQzLm1lcmdlKHN0YWNrZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBkLnQgPSBBcnJheS5pc0FycmF5KGQudFswXSkgPyBkLnQgOiBbIGQudCBdO1xuICAgICAgICAgICAgICAgIGQuciA9IEFycmF5LmlzQXJyYXkoZC5yWzBdKSA/IGQuciA6IFsgZC5yIF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciByYWRpdXMgPSBNYXRoLm1pbihheGlzQ29uZmlnLndpZHRoIC0gYXhpc0NvbmZpZy5tYXJnaW4ubGVmdCAtIGF4aXNDb25maWcubWFyZ2luLnJpZ2h0LCBheGlzQ29uZmlnLmhlaWdodCAtIGF4aXNDb25maWcubWFyZ2luLnRvcCAtIGF4aXNDb25maWcubWFyZ2luLmJvdHRvbSkgLyAyO1xuICAgICAgICAgICAgcmFkaXVzID0gTWF0aC5tYXgoMTAsIHJhZGl1cyk7XG4gICAgICAgICAgICB2YXIgY2hhcnRDZW50ZXIgPSBbIGF4aXNDb25maWcubWFyZ2luLmxlZnQgKyByYWRpdXMsIGF4aXNDb25maWcubWFyZ2luLnRvcCArIHJhZGl1cyBdO1xuICAgICAgICAgICAgdmFyIGV4dGVudDtcbiAgICAgICAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgaGlnaGVzdFN0YWNrZWRWYWx1ZSA9IGQzLm1heCjCtS51dGlsLnN1bUFycmF5cyjCtS51dGlsLmFycmF5TGFzdChkYXRhKS5yWzBdLCDCtS51dGlsLmFycmF5TGFzdChkYXRhWVN0YWNrKSkpO1xuICAgICAgICAgICAgICAgIGV4dGVudCA9IFsgMCwgaGlnaGVzdFN0YWNrZWRWYWx1ZSBdO1xuICAgICAgICAgICAgfSBlbHNlIGV4dGVudCA9IGQzLmV4dGVudCjCtS51dGlsLmZsYXR0ZW5BcnJheShkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQucjtcbiAgICAgICAgICAgIH0pKSk7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5yYWRpYWxBeGlzLmRvbWFpbiAhPSDCtS5EQVRBRVhURU5UKSBleHRlbnRbMF0gPSAwO1xuICAgICAgICAgICAgcmFkaWFsU2NhbGUgPSBkMy5zY2FsZS5saW5lYXIoKS5kb21haW4oYXhpc0NvbmZpZy5yYWRpYWxBeGlzLmRvbWFpbiAhPSDCtS5EQVRBRVhURU5UICYmIGF4aXNDb25maWcucmFkaWFsQXhpcy5kb21haW4gPyBheGlzQ29uZmlnLnJhZGlhbEF4aXMuZG9tYWluIDogZXh0ZW50KS5yYW5nZShbIDAsIHJhZGl1cyBdKTtcbiAgICAgICAgICAgIGxpdmVDb25maWcubGF5b3V0LnJhZGlhbEF4aXMuZG9tYWluID0gcmFkaWFsU2NhbGUuZG9tYWluKCk7XG4gICAgICAgICAgICB2YXIgYW5ndWxhckRhdGFNZXJnZWQgPSDCtS51dGlsLmZsYXR0ZW5BcnJheShkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQudDtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIHZhciBpc09yZGluYWwgPSB0eXBlb2YgYW5ndWxhckRhdGFNZXJnZWRbMF0gPT09ICdzdHJpbmcnO1xuICAgICAgICAgICAgdmFyIHRpY2tzO1xuICAgICAgICAgICAgaWYgKGlzT3JkaW5hbCkge1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJEYXRhTWVyZ2VkID0gwrUudXRpbC5kZWR1cGxpY2F0ZShhbmd1bGFyRGF0YU1lcmdlZCk7XG4gICAgICAgICAgICAgICAgdGlja3MgPSBhbmd1bGFyRGF0YU1lcmdlZC5zbGljZSgpO1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJEYXRhTWVyZ2VkID0gZDMucmFuZ2UoYW5ndWxhckRhdGFNZXJnZWQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gZDtcbiAgICAgICAgICAgICAgICAgICAgZC50ID0gWyBhbmd1bGFyRGF0YU1lcmdlZCBdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdGFja2VkKSByZXN1bHQueVN0YWNrID0gZC55U3RhY2s7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaGFzT25seUxpbmVPckRvdFBsb3QgPSBkYXRhLmZpbHRlcihmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQuZ2VvbWV0cnkgPT09ICdMaW5lUGxvdCcgfHwgZC5nZW9tZXRyeSA9PT0gJ0RvdFBsb3QnO1xuICAgICAgICAgICAgfSkubGVuZ3RoID09PSBkYXRhLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBuZWVkc0VuZFNwYWNpbmcgPSBheGlzQ29uZmlnLm5lZWRzRW5kU3BhY2luZyA9PT0gbnVsbCA/IGlzT3JkaW5hbCB8fCAhaGFzT25seUxpbmVPckRvdFBsb3QgOiBheGlzQ29uZmlnLm5lZWRzRW5kU3BhY2luZztcbiAgICAgICAgICAgIHZhciB1c2VQcm92aWRlZERvbWFpbiA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluICYmIGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluICE9IMK1LkRBVEFFWFRFTlQgJiYgIWlzT3JkaW5hbCAmJiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLmRvbWFpblswXSA+PSAwO1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJEb21haW4gPSB1c2VQcm92aWRlZERvbWFpbiA/IGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluIDogZDMuZXh0ZW50KGFuZ3VsYXJEYXRhTWVyZ2VkKTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyRG9tYWluU3RlcCA9IE1hdGguYWJzKGFuZ3VsYXJEYXRhTWVyZ2VkWzFdIC0gYW5ndWxhckRhdGFNZXJnZWRbMF0pO1xuICAgICAgICAgICAgaWYgKGhhc09ubHlMaW5lT3JEb3RQbG90ICYmICFpc09yZGluYWwpIGFuZ3VsYXJEb21haW5TdGVwID0gMDtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyRG9tYWluV2l0aFBhZGRpbmcgPSBhbmd1bGFyRG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICBpZiAobmVlZHNFbmRTcGFjaW5nICYmIGlzT3JkaW5hbCkgYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzFdICs9IGFuZ3VsYXJEb21haW5TdGVwO1xuICAgICAgICAgICAgdmFyIHRpY2tDb3VudCA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja3NDb3VudCB8fCA0O1xuICAgICAgICAgICAgaWYgKHRpY2tDb3VudCA+IDgpIHRpY2tDb3VudCA9IHRpY2tDb3VudCAvICh0aWNrQ291bnQgLyA4KSArIHRpY2tDb3VudCAlIDg7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy50aWNrc1N0ZXApIHtcbiAgICAgICAgICAgICAgICB0aWNrQ291bnQgPSAoYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzFdIC0gYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzBdKSAvIHRpY2tDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyVGlja3NTdGVwID0gYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy50aWNrc1N0ZXAgfHwgKGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1sxXSAtIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1swXSkgLyAodGlja0NvdW50ICogKGF4aXNDb25maWcubWlub3JUaWNrcyArIDEpKTtcbiAgICAgICAgICAgIGlmICh0aWNrcykgYW5ndWxhclRpY2tzU3RlcCA9IE1hdGgubWF4KE1hdGgucm91bmQoYW5ndWxhclRpY2tzU3RlcCksIDEpO1xuICAgICAgICAgICAgaWYgKCFhbmd1bGFyRG9tYWluV2l0aFBhZGRpbmdbMl0pIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1syXSA9IGFuZ3VsYXJUaWNrc1N0ZXA7XG4gICAgICAgICAgICB2YXIgYW5ndWxhckF4aXNSYW5nZSA9IGQzLnJhbmdlLmFwcGx5KHRoaXMsIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZyk7XG4gICAgICAgICAgICBhbmd1bGFyQXhpc1JhbmdlID0gYW5ndWxhckF4aXNSYW5nZS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KGQudG9QcmVjaXNpb24oMTIpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYW5ndWxhclNjYWxlID0gZDMuc2NhbGUubGluZWFyKCkuZG9tYWluKGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZy5zbGljZSgwLCAyKSkucmFuZ2UoYXhpc0NvbmZpZy5kaXJlY3Rpb24gPT09ICdjbG9ja3dpc2UnID8gWyAwLCAzNjAgXSA6IFsgMzYwLCAwIF0pO1xuICAgICAgICAgICAgbGl2ZUNvbmZpZy5sYXlvdXQuYW5ndWxhckF4aXMuZG9tYWluID0gYW5ndWxhclNjYWxlLmRvbWFpbigpO1xuICAgICAgICAgICAgbGl2ZUNvbmZpZy5sYXlvdXQuYW5ndWxhckF4aXMuZW5kUGFkZGluZyA9IG5lZWRzRW5kU3BhY2luZyA/IGFuZ3VsYXJEb21haW5TdGVwIDogMDtcbiAgICAgICAgICAgIHN2ZyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ3N2Zy5jaGFydC1yb290Jyk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHN2ZyA9PT0gJ3VuZGVmaW5lZCcgfHwgc3ZnLmVtcHR5KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2tlbGV0b24gPSBcIjxzdmcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyBjbGFzcz0nY2hhcnQtcm9vdCc+JyArICc8ZyBjbGFzcz0nb3V0ZXItZ3JvdXAnPicgKyAnPGcgY2xhc3M9J2NoYXJ0LWdyb3VwJz4nICsgJzxjaXJjbGUgY2xhc3M9J2JhY2tncm91bmQtY2lyY2xlJz48L2NpcmNsZT4nICsgJzxnIGNsYXNzPSdnZW9tZXRyeS1ncm91cCc+PC9nPicgKyAnPGcgY2xhc3M9J3JhZGlhbCBheGlzLWdyb3VwJz4nICsgJzxjaXJjbGUgY2xhc3M9J291dHNpZGUtY2lyY2xlJz48L2NpcmNsZT4nICsgJzwvZz4nICsgJzxnIGNsYXNzPSdhbmd1bGFyIGF4aXMtZ3JvdXAnPjwvZz4nICsgJzxnIGNsYXNzPSdndWlkZXMtZ3JvdXAnPjxsaW5lPjwvbGluZT48Y2lyY2xlIHI9JzAnPjwvY2lyY2xlPjwvZz4nICsgJzwvZz4nICsgJzxnIGNsYXNzPSdsZWdlbmQtZ3JvdXAnPjwvZz4nICsgJzxnIGNsYXNzPSd0b29sdGlwcy1ncm91cCc+PC9nPicgKyAnPGcgY2xhc3M9J3RpdGxlLWdyb3VwJz48dGV4dD48L3RleHQ+PC9nPicgKyAnPC9nPicgKyAnPC9zdmc+XCI7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG5ldyBET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoc2tlbGV0b24sICdhcHBsaWNhdGlvbi94bWwnKTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3U3ZnID0gdGhpcy5hcHBlbmRDaGlsZCh0aGlzLm93bmVyRG9jdW1lbnQuaW1wb3J0Tm9kZShkb2MuZG9jdW1lbnRFbGVtZW50LCB0cnVlKSk7XG4gICAgICAgICAgICAgICAgc3ZnID0gZDMuc2VsZWN0KG5ld1N2Zyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcuZ3VpZGVzLWdyb3VwJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcuYW5ndWxhci5heGlzLWdyb3VwJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcucmFkaWFsLmF4aXMtZ3JvdXAnKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBjaGFydEdyb3VwID0gc3ZnLnNlbGVjdCgnLmNoYXJ0LWdyb3VwJyk7XG4gICAgICAgICAgICB2YXIgbGluZVN0eWxlID0ge1xuICAgICAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcudGlja0NvbG9yXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGZvbnRTdHlsZSA9IHtcbiAgICAgICAgICAgICAgICAnZm9udC1zaXplJzogYXhpc0NvbmZpZy5mb250LnNpemUsXG4gICAgICAgICAgICAgICAgJ2ZvbnQtZmFtaWx5JzogYXhpc0NvbmZpZy5mb250LmZhbWlseSxcbiAgICAgICAgICAgICAgICBmaWxsOiBheGlzQ29uZmlnLmZvbnQuY29sb3IsXG4gICAgICAgICAgICAgICAgJ3RleHQtc2hhZG93JzogWyAnLTFweCAwcHgnLCAnMXB4IC0xcHgnLCAnLTFweCAxcHgnLCAnMXB4IDFweCcgXS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyAnICsgZCArICcgMCAnICsgYXhpc0NvbmZpZy5mb250Lm91dGxpbmVDb2xvcjtcbiAgICAgICAgICAgICAgICB9KS5qb2luKCcsJylcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbGVnZW5kQ29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcuc2hvd0xlZ2VuZCkge1xuICAgICAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lciA9IHN2Zy5zZWxlY3QoJy5sZWdlbmQtZ3JvdXAnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlKCcgKyBbIHJhZGl1cywgYXhpc0NvbmZpZy5tYXJnaW4udG9wIF0gKyAnKSdcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB2YXIgZWxlbWVudHMgPSBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXR1bUNsb25lID0gwrUudXRpbC5jbG9uZUpzb24oZCk7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtQ2xvbmUuc3ltYm9sID0gZC5nZW9tZXRyeSA9PT0gJ0RvdFBsb3QnID8gZC5kb3RUeXBlIHx8ICdjaXJjbGUnIDogZC5nZW9tZXRyeSAhPSAnTGluZVBsb3QnID8gJ3NxdWFyZScgOiAnbGluZSc7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtQ2xvbmUudmlzaWJsZUluTGVnZW5kID0gdHlwZW9mIGQudmlzaWJsZUluTGVnZW5kID09PSAndW5kZWZpbmVkJyB8fCBkLnZpc2libGVJbkxlZ2VuZDtcbiAgICAgICAgICAgICAgICAgICAgZGF0dW1DbG9uZS5jb2xvciA9IGQuZ2VvbWV0cnkgPT09ICdMaW5lUGxvdCcgPyBkLnN0cm9rZUNvbG9yIDogZC5jb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdHVtQ2xvbmU7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICDCtS5MZWdlbmQoKS5jb25maWcoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhOiBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC5uYW1lIHx8ICdFbGVtZW50JyArIGk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBsZWdlbmRDb25maWc6IGV4dGVuZERlZXBBbGwoe30sXG4gICAgICAgICAgICAgICAgICAgICAgICDCtS5MZWdlbmQuZGVmYXVsdENvbmZpZygpLmxlZ2VuZENvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IGxlZ2VuZENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJzZU9yZGVyOiBheGlzQ29uZmlnLmxlZ2VuZC5yZXZlcnNlT3JkZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIH0pKCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVnZW5kQkJveCA9IGxlZ2VuZENvbnRhaW5lci5ub2RlKCkuZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJhZGl1cyA9IE1hdGgubWluKGF4aXNDb25maWcud2lkdGggLSBsZWdlbmRCQm94LndpZHRoIC0gYXhpc0NvbmZpZy5tYXJnaW4ubGVmdCAtIGF4aXNDb25maWcubWFyZ2luLnJpZ2h0LCBheGlzQ29uZmlnLmhlaWdodCAtIGF4aXNDb25maWcubWFyZ2luLnRvcCAtIGF4aXNDb25maWcubWFyZ2luLmJvdHRvbSkgLyAyO1xuICAgICAgICAgICAgICAgIHJhZGl1cyA9IE1hdGgubWF4KDEwLCByYWRpdXMpO1xuICAgICAgICAgICAgICAgIGNoYXJ0Q2VudGVyID0gWyBheGlzQ29uZmlnLm1hcmdpbi5sZWZ0ICsgcmFkaXVzLCBheGlzQ29uZmlnLm1hcmdpbi50b3AgKyByYWRpdXMgXTtcbiAgICAgICAgICAgICAgICByYWRpYWxTY2FsZS5yYW5nZShbIDAsIHJhZGl1cyBdKTtcbiAgICAgICAgICAgICAgICBsaXZlQ29uZmlnLmxheW91dC5yYWRpYWxBeGlzLmRvbWFpbiA9IHJhZGlhbFNjYWxlLmRvbWFpbigpO1xuICAgICAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBbIGNoYXJ0Q2VudGVyWzBdICsgcmFkaXVzLCBjaGFydENlbnRlclsxXSAtIHJhZGl1cyBdICsgJyknKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGVnZW5kQ29udGFpbmVyID0gc3ZnLnNlbGVjdCgnLmxlZ2VuZC1ncm91cCcpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogJ25vbmUnXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdmcuYXR0cih7XG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXNDb25maWcud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBheGlzQ29uZmlnLmhlaWdodFxuICAgICAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IGF4aXNDb25maWcub3BhY2l0eVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjaGFydEdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGNoYXJ0Q2VudGVyICsgJyknKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgY3Vyc29yOiAnY3Jvc3NoYWlyJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgY2VudGVyaW5nT2Zmc2V0ID0gWyAoYXhpc0NvbmZpZy53aWR0aCAtIChheGlzQ29uZmlnLm1hcmdpbi5sZWZ0ICsgYXhpc0NvbmZpZy5tYXJnaW4ucmlnaHQgKyByYWRpdXMgKiAyICsgKGxlZ2VuZEJCb3ggPyBsZWdlbmRCQm94LndpZHRoIDogMCkpKSAvIDIsIChheGlzQ29uZmlnLmhlaWdodCAtIChheGlzQ29uZmlnLm1hcmdpbi50b3AgKyBheGlzQ29uZmlnLm1hcmdpbi5ib3R0b20gKyByYWRpdXMgKiAyKSkgLyAyIF07XG4gICAgICAgICAgICBjZW50ZXJpbmdPZmZzZXRbMF0gPSBNYXRoLm1heCgwLCBjZW50ZXJpbmdPZmZzZXRbMF0pO1xuICAgICAgICAgICAgY2VudGVyaW5nT2Zmc2V0WzFdID0gTWF0aC5tYXgoMCwgY2VudGVyaW5nT2Zmc2V0WzFdKTtcbiAgICAgICAgICAgIHN2Zy5zZWxlY3QoJy5vdXRlci1ncm91cCcpLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGNlbnRlcmluZ09mZnNldCArICcpJyk7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy50aXRsZSkge1xuICAgICAgICAgICAgICAgIHZhciB0aXRsZSA9IHN2Zy5zZWxlY3QoJ2cudGl0bGUtZ3JvdXAgdGV4dCcpLnN0eWxlKGZvbnRTdHlsZSkudGV4dChheGlzQ29uZmlnLnRpdGxlKTtcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGVCQm94ID0gdGl0bGUubm9kZSgpLmdldEJCb3goKTtcbiAgICAgICAgICAgICAgICB0aXRsZS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDogY2hhcnRDZW50ZXJbMF0gLSB0aXRsZUJCb3gud2lkdGggLyAyLFxuICAgICAgICAgICAgICAgICAgICB5OiBjaGFydENlbnRlclsxXSAtIHJhZGl1cyAtIDIwXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmFkaWFsQXhpcyA9IHN2Zy5zZWxlY3QoJy5yYWRpYWwuYXhpcy1ncm91cCcpO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcucmFkaWFsQXhpcy5ncmlkTGluZXNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyaWRDaXJjbGVzID0gcmFkaWFsQXhpcy5zZWxlY3RBbGwoJ2NpcmNsZS5ncmlkLWNpcmNsZScpLmRhdGEocmFkaWFsU2NhbGUudGlja3MoNSkpO1xuICAgICAgICAgICAgICAgIGdyaWRDaXJjbGVzLmVudGVyKCkuYXBwZW5kKCdjaXJjbGUnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2dyaWQtY2lyY2xlJ1xuICAgICAgICAgICAgICAgIH0pLnN0eWxlKGxpbmVTdHlsZSk7XG4gICAgICAgICAgICAgICAgZ3JpZENpcmNsZXMuYXR0cigncicsIHJhZGlhbFNjYWxlKTtcbiAgICAgICAgICAgICAgICBncmlkQ2lyY2xlcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdCgnY2lyY2xlLm91dHNpZGUtY2lyY2xlJykuYXR0cih7XG4gICAgICAgICAgICAgICAgcjogcmFkaXVzXG4gICAgICAgICAgICB9KS5zdHlsZShsaW5lU3R5bGUpO1xuICAgICAgICAgICAgdmFyIGJhY2tncm91bmRDaXJjbGUgPSBzdmcuc2VsZWN0KCdjaXJjbGUuYmFja2dyb3VuZC1jaXJjbGUnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICByOiByYWRpdXNcbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBmaWxsOiBheGlzQ29uZmlnLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcuc3Ryb2tlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGN1cnJlbnRBbmdsZShkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFuZ3VsYXJTY2FsZShkKSAlIDM2MCArIGF4aXNDb25maWcub3JpZW50YXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5yYWRpYWxBeGlzLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXhpcyA9IGQzLnN2Zy5heGlzKCkuc2NhbGUocmFkaWFsU2NhbGUpLnRpY2tzKDUpLnRpY2tTaXplKDUpO1xuICAgICAgICAgICAgICAgIHJhZGlhbEF4aXMuY2FsbChheGlzKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAncm90YXRlKCcgKyBheGlzQ29uZmlnLnJhZGlhbEF4aXMub3JpZW50YXRpb24gKyAnKSdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdEFsbCgnLmRvbWFpbicpLnN0eWxlKGxpbmVTdHlsZSk7XG4gICAgICAgICAgICAgICAgcmFkaWFsQXhpcy5zZWxlY3RBbGwoJ2c+dGV4dCcpLnRleHQoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0Q29udGVudCArIGF4aXNDb25maWcucmFkaWFsQXhpcy50aWNrc1N1ZmZpeDtcbiAgICAgICAgICAgICAgICB9KS5zdHlsZShmb250U3R5bGUpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ3N0YXJ0J1xuICAgICAgICAgICAgICAgIH0pLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICAgICAgICBkeDogMCxcbiAgICAgICAgICAgICAgICAgICAgZHk6IDAsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF4aXNDb25maWcucmFkaWFsQXhpcy50aWNrT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAncm90YXRlKCcgKyAtYXhpc0NvbmZpZy5yYWRpYWxBeGlzLm9yaWVudGF0aW9uICsgJykgdHJhbnNsYXRlKCcgKyBbIDAsIGZvbnRTdHlsZVsnZm9udC1zaXplJ10gXSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgWyAwLCBmb250U3R5bGVbJ2ZvbnQtc2l6ZSddIF0gKyAnKSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdEFsbCgnZz5saW5lJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICBzdHJva2U6ICdibGFjaydcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyQXhpcyA9IHN2Zy5zZWxlY3QoJy5hbmd1bGFyLmF4aXMtZ3JvdXAnKS5zZWxlY3RBbGwoJ2cuYW5ndWxhci10aWNrJykuZGF0YShhbmd1bGFyQXhpc1JhbmdlKTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyQXhpc0VudGVyID0gYW5ndWxhckF4aXMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdhbmd1bGFyLXRpY2snLCB0cnVlKTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmF0dHIoe1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgY3VycmVudEFuZ2xlKGQsIGkpICsgJyknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnZpc2libGUgPyAnYmxvY2snIDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzRW50ZXIuYXBwZW5kKCdsaW5lJykuY2xhc3NlZCgnZ3JpZC1saW5lJywgdHJ1ZSkuY2xhc3NlZCgnbWFqb3InLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgPT0gMDtcbiAgICAgICAgICAgIH0pLmNsYXNzZWQoJ21pbm9yJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgPT0gMCk7XG4gICAgICAgICAgICB9KS5zdHlsZShsaW5lU3R5bGUpO1xuICAgICAgICAgICAgYW5ndWxhckF4aXNFbnRlci5zZWxlY3RBbGwoJy5taW5vcicpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcubWlub3JUaWNrQ29sb3JcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYW5ndWxhckF4aXMuc2VsZWN0KCdsaW5lLmdyaWQtbGluZScpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHgxOiBheGlzQ29uZmlnLnRpY2tMZW5ndGggPyByYWRpdXMgLSBheGlzQ29uZmlnLnRpY2tMZW5ndGggOiAwLFxuICAgICAgICAgICAgICAgIHgyOiByYWRpdXNcbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLmdyaWRMaW5lc1Zpc2libGUgPyAnYmxvY2snIDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzRW50ZXIuYXBwZW5kKCd0ZXh0JykuY2xhc3NlZCgnYXhpcy10ZXh0JywgdHJ1ZSkuc3R5bGUoZm9udFN0eWxlKTtcbiAgICAgICAgICAgIHZhciB0aWNrc1RleHQgPSBhbmd1bGFyQXhpcy5zZWxlY3QoJ3RleHQuYXhpcy10ZXh0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgeDogcmFkaXVzICsgYXhpc0NvbmZpZy5sYWJlbE9mZnNldCxcbiAgICAgICAgICAgICAgICBkeTogTUlEX1NISUZUICsgJ2VtJyxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFuZ2xlID0gY3VycmVudEFuZ2xlKGQsIGkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmFkID0gcmFkaXVzICsgYXhpc0NvbmZpZy5sYWJlbE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9yaWVudCA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja09yaWVudGF0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3JpZW50ID09ICdob3Jpem9udGFsJykgcmV0dXJuICdyb3RhdGUoJyArIC1hbmdsZSArICcgJyArIHJhZCArICcgMCknOyBlbHNlIGlmIChvcmllbnQgPT0gJ3JhZGlhbCcpIHJldHVybiBhbmdsZSA8IDI3MCAmJiBhbmdsZSA+IDkwID8gJ3JvdGF0ZSgxODAgJyArIHJhZCArICcgMCknIDogbnVsbDsgZWxzZSByZXR1cm4gJ3JvdGF0ZSgnICsgKGFuZ2xlIDw9IDE4MCAmJiBhbmdsZSA+IDAgPyAtOTAgOiA5MCkgKyAnICcgKyByYWQgKyAnIDApJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZScsXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy5sYWJlbHNWaXNpYmxlID8gJ2Jsb2NrJyA6ICdub25lJ1xuICAgICAgICAgICAgfSkudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgIT0gMCkgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgIGlmICh0aWNrcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGlja3NbZF0gKyBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnRpY2tzU3VmZml4O1xuICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gZCArIGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja3NTdWZmaXg7XG4gICAgICAgICAgICB9KS5zdHlsZShmb250U3R5bGUpO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcuYW5ndWxhckF4aXMucmV3cml0ZVRpY2tzKSB0aWNrc1RleHQudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgIT0gMCkgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgIHJldHVybiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnJld3JpdGVUaWNrcyh0aGlzLnRleHRDb250ZW50LCBpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIHJpZ2h0bW9zdFRpY2tFbmRYID0gZDMubWF4KGNoYXJ0R3JvdXAuc2VsZWN0QWxsKCcuYW5ndWxhci10aWNrIHRleHQnKVswXS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkLmdldENUTSgpLmUgKyBkLmdldEJCb3goKS53aWR0aDtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lci5hdHRyKHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgcmFkaXVzICsgcmlnaHRtb3N0VGlja0VuZFgsIGF4aXNDb25maWcubWFyZ2luLnRvcCBdICsgJyknXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBoYXNHZW9tZXRyeSA9IHN2Zy5zZWxlY3QoJ2cuZ2VvbWV0cnktZ3JvdXAnKS5zZWxlY3RBbGwoJ2cnKS5zaXplKCkgPiAwO1xuICAgICAgICAgICAgdmFyIGdlb21ldHJ5Q29udGFpbmVyID0gc3ZnLnNlbGVjdCgnZy5nZW9tZXRyeS1ncm91cCcpLnNlbGVjdEFsbCgnZy5nZW9tZXRyeScpLmRhdGEoZGF0YSk7XG4gICAgICAgICAgICBnZW9tZXRyeUNvbnRhaW5lci5lbnRlcigpLmFwcGVuZCgnZycpLmF0dHIoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdnZW9tZXRyeSBnZW9tZXRyeScgKyBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2VvbWV0cnlDb250YWluZXIuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICAgICAgaWYgKGRhdGFbMF0gfHwgaGFzR2VvbWV0cnkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzID0gW107XG4gICAgICAgICAgICAgICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdlb21ldHJ5Q29uZmlnID0ge307XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlID0gcmFkaWFsU2NhbGU7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLmFuZ3VsYXJTY2FsZSA9IGFuZ3VsYXJTY2FsZTtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWcuY29udGFpbmVyID0gZ2VvbWV0cnlDb250YWluZXIuZmlsdGVyKGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlCID09IGk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBnZW9tZXRyeUNvbmZpZy5nZW9tZXRyeSA9IGQuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uID0gYXhpc0NvbmZpZy5vcmllbnRhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWcuZGlyZWN0aW9uID0gYXhpc0NvbmZpZy5kaXJlY3Rpb247XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLmluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnOiBnZW9tZXRyeUNvbmZpZ1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzR3JvdXBlZCA9IGQzLm5lc3QoKS5rZXkoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGQuZGF0YS5ncm91cElkICE9ICd1bmRlZmluZWQnIHx8ICd1bnN0YWNrZWQnO1xuICAgICAgICAgICAgICAgIH0pLmVudHJpZXMoZ2VvbWV0cnlDb25maWdzKTtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIgPSBbXTtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeUNvbmZpZ3NHcm91cGVkLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZC5rZXkgPT09ICd1bnN0YWNrZWQnKSBnZW9tZXRyeUNvbmZpZ3NHcm91cGVkMiA9IGdlb21ldHJ5Q29uZmlnc0dyb3VwZWQyLmNvbmNhdChkLnZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsgZCBdO1xuICAgICAgICAgICAgICAgICAgICB9KSk7IGVsc2UgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIucHVzaChkLnZhbHVlcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIuZm9yRWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBnZW9tZXRyeTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZCkpIGdlb21ldHJ5ID0gZFswXS5nZW9tZXRyeUNvbmZpZy5nZW9tZXRyeTsgZWxzZSBnZW9tZXRyeSA9IGQuZ2VvbWV0cnlDb25maWcuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaW5hbEdlb21ldHJ5Q29uZmlnID0gZC5tYXAoZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXh0ZW5kRGVlcEFsbCjCtVtnZW9tZXRyeV0uZGVmYXVsdENvbmZpZygpLCBkQik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICDCtVtnZW9tZXRyeV0oKS5jb25maWcoZmluYWxHZW9tZXRyeUNvbmZpZykoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBndWlkZXMgPSBzdmcuc2VsZWN0KCcuZ3VpZGVzLWdyb3VwJyk7XG4gICAgICAgICAgICB2YXIgdG9vbHRpcENvbnRhaW5lciA9IHN2Zy5zZWxlY3QoJy50b29sdGlwcy1ncm91cCcpO1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJUb29sdGlwID0gwrUudG9vbHRpcFBhbmVsKCkuY29uZmlnKHtcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IHRvb2x0aXBDb250YWluZXIsXG4gICAgICAgICAgICAgICAgZm9udFNpemU6IDhcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICB2YXIgcmFkaWFsVG9vbHRpcCA9IMK1LnRvb2x0aXBQYW5lbCgpLmNvbmZpZyh7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiB0b29sdGlwQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgIGZvbnRTaXplOiA4XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgdmFyIGdlb21ldHJ5VG9vbHRpcCA9IMK1LnRvb2x0aXBQYW5lbCgpLmNvbmZpZyh7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiB0b29sdGlwQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgIGhhc1RpY2s6IHRydWVcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICB2YXIgYW5ndWxhclZhbHVlLCByYWRpYWxWYWx1ZTtcbiAgICAgICAgICAgIGlmICghaXNPcmRpbmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFuZ3VsYXJHdWlkZUxpbmUgPSBndWlkZXMuc2VsZWN0KCdsaW5lJykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHgxOiAwLFxuICAgICAgICAgICAgICAgICAgICB5MTogMCxcbiAgICAgICAgICAgICAgICAgICAgeTI6IDBcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogJ2dyZXknLFxuICAgICAgICAgICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZSdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjaGFydEdyb3VwLm9uKCdtb3VzZW1vdmUuYW5ndWxhci1ndWlkZScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1vdXNlQW5nbGUgPSDCtS51dGlsLmdldE1vdXNlUG9zKGJhY2tncm91bmRDaXJjbGUpLmFuZ2xlO1xuICAgICAgICAgICAgICAgICAgICBhbmd1bGFyR3VpZGVMaW5lLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgeDI6IC1yYWRpdXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICdyb3RhdGUoJyArIG1vdXNlQW5nbGUgKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogLjVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhbmdsZVdpdGhPcmlnaW5PZmZzZXQgPSAobW91c2VBbmdsZSArIDE4MCArIDM2MCAtIGF4aXNDb25maWcub3JpZW50YXRpb24pICUgMzYwO1xuICAgICAgICAgICAgICAgICAgICBhbmd1bGFyVmFsdWUgPSBhbmd1bGFyU2NhbGUuaW52ZXJ0KGFuZ2xlV2l0aE9yaWdpbk9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSDCtS51dGlsLmNvbnZlcnRUb0NhcnRlc2lhbihyYWRpdXMgKyAxMiwgbW91c2VBbmdsZSArIDE4MCk7XG4gICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJUb29sdGlwLnRleHQowrUudXRpbC5yb3VuZChhbmd1bGFyVmFsdWUpKS5tb3ZlKFsgcG9zWzBdICsgY2hhcnRDZW50ZXJbMF0sIHBvc1sxXSArIGNoYXJ0Q2VudGVyWzFdIF0pO1xuICAgICAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC5hbmd1bGFyLWd1aWRlJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBndWlkZXMuc2VsZWN0KCdsaW5lJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyR3VpZGVDaXJjbGUgPSBndWlkZXMuc2VsZWN0KCdjaXJjbGUnKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgc3Ryb2tlOiAnZ3JleScsXG4gICAgICAgICAgICAgICAgZmlsbDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNoYXJ0R3JvdXAub24oJ21vdXNlbW92ZS5yYWRpYWwtZ3VpZGUnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHIgPSDCtS51dGlsLmdldE1vdXNlUG9zKGJhY2tncm91bmRDaXJjbGUpLnJhZGl1cztcbiAgICAgICAgICAgICAgICBhbmd1bGFyR3VpZGVDaXJjbGUuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHI6IHJcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IC41XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmFkaWFsVmFsdWUgPSByYWRpYWxTY2FsZS5pbnZlcnQowrUudXRpbC5nZXRNb3VzZVBvcyhiYWNrZ3JvdW5kQ2lyY2xlKS5yYWRpdXMpO1xuICAgICAgICAgICAgICAgIHZhciBwb3MgPSDCtS51dGlsLmNvbnZlcnRUb0NhcnRlc2lhbihyLCBheGlzQ29uZmlnLnJhZGlhbEF4aXMub3JpZW50YXRpb24pO1xuICAgICAgICAgICAgICAgIHJhZGlhbFRvb2x0aXAudGV4dCjCtS51dGlsLnJvdW5kKHJhZGlhbFZhbHVlKSkubW92ZShbIHBvc1swXSArIGNoYXJ0Q2VudGVyWzBdLCBwb3NbMV0gKyBjaGFydENlbnRlclsxXSBdKTtcbiAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC5yYWRpYWwtZ3VpZGUnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgYW5ndWxhckd1aWRlQ2lyY2xlLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgYW5ndWxhclRvb2x0aXAuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJhZGlhbFRvb2x0aXAuaGlkZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0QWxsKCcuZ2VvbWV0cnktZ3JvdXAgLm1hcmsnKS5vbignbW91c2VvdmVyLnRvb2x0aXAnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBjb2xvciA9IHRoaXMuc3R5bGUuZmlsbDtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q29sb3IgPSAnYmxhY2snO1xuICAgICAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gdGhpcy5zdHlsZS5vcGFjaXR5IHx8IDE7XG4gICAgICAgICAgICAgICAgZWwuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdkYXRhLW9wYWNpdHknOiBvcGFjaXR5XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbG9yICYmIGNvbG9yICE9PSAnbm9uZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAnZGF0YS1maWxsJzogY29sb3JcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbG9yID0gZDMuaHNsKGNvbG9yKS5kYXJrZXIoKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsOiBuZXdDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZXh0RGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHQ6IMK1LnV0aWwucm91bmQoZFswXSksXG4gICAgICAgICAgICAgICAgICAgICAgICByOiDCtS51dGlsLnJvdW5kKGRbMV0pXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc09yZGluYWwpIHRleHREYXRhLnQgPSB0aWNrc1tkWzBdXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRleHQgPSAndDogJyArIHRleHREYXRhLnQgKyAnLCByOiAnICsgdGV4dERhdGEucjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3ZnQkJveCA9IHN2Zy5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSBbIGJib3gubGVmdCArIGJib3gud2lkdGggLyAyIC0gY2VudGVyaW5nT2Zmc2V0WzBdIC0gc3ZnQkJveC5sZWZ0LCBiYm94LnRvcCArIGJib3guaGVpZ2h0IC8gMiAtIGNlbnRlcmluZ09mZnNldFsxXSAtIHN2Z0JCb3gudG9wIF07XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5jb25maWcoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IG5ld0NvbG9yXG4gICAgICAgICAgICAgICAgICAgIH0pLnRleHQodGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5tb3ZlKHBvcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB0aGlzLnN0eWxlLnN0cm9rZSB8fCAnYmxhY2snO1xuICAgICAgICAgICAgICAgICAgICBlbC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICdkYXRhLXN0cm9rZSc6IGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBuZXdDb2xvciA9IGQzLmhzbChjb2xvcikuZGFya2VyKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgZWwuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiBuZXdDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkub24oJ21vdXNlbW92ZS50b29sdGlwJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIGlmIChkMy5ldmVudC53aGljaCAhPSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdkYXRhLWZpbGwnKSkgZ2VvbWV0cnlUb29sdGlwLnNob3coKTtcbiAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC50b29sdGlwJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBmaWxsQ29sb3IgPSBlbC5hdHRyKCdkYXRhLWZpbGwnKTtcbiAgICAgICAgICAgICAgICBpZiAoZmlsbENvbG9yKSBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IGZpbGxDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogZWwuYXR0cignZGF0YS1vcGFjaXR5JylcbiAgICAgICAgICAgICAgICB9KTsgZWxzZSBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogZWwuYXR0cignZGF0YS1zdHJva2UnKSxcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogZWwuYXR0cignZGF0YS1vcGFjaXR5JylcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfVxuICAgIGV4cG9ydHMucmVuZGVyID0gZnVuY3Rpb24oX2NvbnRhaW5lcikge1xuICAgICAgICByZW5kZXIoX2NvbnRhaW5lcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjb25maWc7XG4gICAgICAgIHZhciB4Q2xvbmUgPSDCtS51dGlsLmNsb25lSnNvbihfeCk7XG4gICAgICAgIHhDbG9uZS5kYXRhLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgaWYgKCFjb25maWcuZGF0YVtpXSkgY29uZmlnLmRhdGFbaV0gPSB7fTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLmRhdGFbaV0sIMK1LkF4aXMuZGVmYXVsdENvbmZpZygpLmRhdGFbMF0pO1xuICAgICAgICAgICAgZXh0ZW5kRGVlcEFsbChjb25maWcuZGF0YVtpXSwgZCk7XG4gICAgICAgIH0pO1xuICAgICAgICBleHRlbmREZWVwQWxsKGNvbmZpZy5sYXlvdXQsIMK1LkF4aXMuZGVmYXVsdENvbmZpZygpLmxheW91dCk7XG4gICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLmxheW91dCwgeENsb25lLmxheW91dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRMaXZlQ29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBsaXZlQ29uZmlnO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRpbnB1dENvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaW5wdXRDb25maWc7XG4gICAgfTtcbiAgICBleHBvcnRzLnJhZGlhbFNjYWxlID0gZnVuY3Rpb24oX3gpIHtcbiAgICAgICAgcmV0dXJuIHJhZGlhbFNjYWxlO1xuICAgIH07XG4gICAgZXhwb3J0cy5hbmd1bGFyU2NhbGUgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICByZXR1cm4gYW5ndWxhclNjYWxlO1xuICAgIH07XG4gICAgZXhwb3J0cy5zdmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHN2ZztcbiAgICB9O1xuICAgIGQzLnJlYmluZChleHBvcnRzLCBkaXNwYXRjaCwgJ29uJyk7XG4gICAgcmV0dXJuIGV4cG9ydHM7XG59O1xuXG7CtS5BeGlzLmRlZmF1bHRDb25maWcgPSBmdW5jdGlvbihkLCBpKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogWyB7XG4gICAgICAgICAgICB0OiBbIDEsIDIsIDMsIDQgXSxcbiAgICAgICAgICAgIHI6IFsgMTAsIDExLCAxMiwgMTMgXSxcbiAgICAgICAgICAgIG5hbWU6ICdMaW5lMScsXG4gICAgICAgICAgICBnZW9tZXRyeTogJ0xpbmVQbG90JyxcbiAgICAgICAgICAgIGNvbG9yOiBudWxsLFxuICAgICAgICAgICAgc3Ryb2tlRGFzaDogJ3NvbGlkJyxcbiAgICAgICAgICAgIHN0cm9rZUNvbG9yOiBudWxsLFxuICAgICAgICAgICAgc3Ryb2tlU2l6ZTogJzEnLFxuICAgICAgICAgICAgdmlzaWJsZUluTGVnZW5kOiB0cnVlLFxuICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICB9IF0sXG4gICAgICAgIGxheW91dDoge1xuICAgICAgICAgICAgZGVmYXVsdENvbG9yUmFuZ2U6IGQzLnNjYWxlLmNhdGVnb3J5MTAoKS5yYW5nZSgpLFxuICAgICAgICAgICAgdGl0bGU6IG51bGwsXG4gICAgICAgICAgICBoZWlnaHQ6IDQ1MCxcbiAgICAgICAgICAgIHdpZHRoOiA1MDAsXG4gICAgICAgICAgICBtYXJnaW46IHtcbiAgICAgICAgICAgICAgICB0b3A6IDQwLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiA0MCxcbiAgICAgICAgICAgICAgICBib3R0b206IDQwLFxuICAgICAgICAgICAgICAgIGxlZnQ6IDQwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9udDoge1xuICAgICAgICAgICAgICAgIHNpemU6IDEyLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnZ3JheScsXG4gICAgICAgICAgICAgICAgb3V0bGluZUNvbG9yOiAnd2hpdGUnLFxuICAgICAgICAgICAgICAgIGZhbWlseTogJ1RhaG9tYSwgc2Fucy1zZXJpZidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXJlY3Rpb246ICdjbG9ja3dpc2UnLFxuICAgICAgICAgICAgb3JpZW50YXRpb246IDAsXG4gICAgICAgICAgICBsYWJlbE9mZnNldDogMTAsXG4gICAgICAgICAgICByYWRpYWxBeGlzOiB7XG4gICAgICAgICAgICAgICAgZG9tYWluOiBudWxsLFxuICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uOiAtNDUsXG4gICAgICAgICAgICAgICAgdGlja3NTdWZmaXg6ICcnLFxuICAgICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ3JpZExpbmVzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB0aWNrT3JpZW50YXRpb246ICdob3Jpem9udGFsJyxcbiAgICAgICAgICAgICAgICByZXdyaXRlVGlja3M6IG51bGxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbmd1bGFyQXhpczoge1xuICAgICAgICAgICAgICAgIGRvbWFpbjogWyAwLCAzNjAgXSxcbiAgICAgICAgICAgICAgICB0aWNrc1N1ZmZpeDogJycsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBncmlkTGluZXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGxhYmVsc1Zpc2libGU6IHRydWUsXG4gICAgICAgICAgICAgICAgdGlja09yaWVudGF0aW9uOiAnaG9yaXpvbnRhbCcsXG4gICAgICAgICAgICAgICAgcmV3cml0ZVRpY2tzOiBudWxsLFxuICAgICAgICAgICAgICAgIHRpY2tzQ291bnQ6IG51bGwsXG4gICAgICAgICAgICAgICAgdGlja3NTdGVwOiBudWxsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWlub3JUaWNrczogMCxcbiAgICAgICAgICAgIHRpY2tMZW5ndGg6IG51bGwsXG4gICAgICAgICAgICB0aWNrQ29sb3I6ICdzaWx2ZXInLFxuICAgICAgICAgICAgbWlub3JUaWNrQ29sb3I6ICcjZWVlJyxcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJ25vbmUnLFxuICAgICAgICAgICAgbmVlZHNFbmRTcGFjaW5nOiBudWxsLFxuICAgICAgICAgICAgc2hvd0xlZ2VuZDogdHJ1ZSxcbiAgICAgICAgICAgIGxlZ2VuZDoge1xuICAgICAgICAgICAgICAgIHJldmVyc2VPcmRlcjogZmFsc2VcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBjb25maWc7XG59O1xuXG7CtS51dGlsID0ge307XG5cbsK1LkRBVEFFWFRFTlQgPSAnZGF0YUV4dGVudCc7XG5cbsK1LkFSRUEgPSAnQXJlYUNoYXJ0JztcblxuwrUuTElORSA9ICdMaW5lUGxvdCc7XG5cbsK1LkRPVCA9ICdEb3RQbG90JztcblxuwrUuQkFSID0gJ0JhckNoYXJ0JztcblxuwrUudXRpbC5fb3ZlcnJpZGUgPSBmdW5jdGlvbihfb2JqQSwgX29iakIpIHtcbiAgICBmb3IgKHZhciB4IGluIF9vYmpBKSBpZiAoeCBpbiBfb2JqQikgX29iakJbeF0gPSBfb2JqQVt4XTtcbn07XG5cbsK1LnV0aWwuX2V4dGVuZCA9IGZ1bmN0aW9uKF9vYmpBLCBfb2JqQikge1xuICAgIGZvciAodmFyIHggaW4gX29iakEpIF9vYmpCW3hdID0gX29iakFbeF07XG59O1xuXG7CtS51dGlsLl9ybmRTbmQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gTWF0aC5yYW5kb20oKSAqIDIgLSAxICsgKE1hdGgucmFuZG9tKCkgKiAyIC0gMSkgKyAoTWF0aC5yYW5kb20oKSAqIDIgLSAxKTtcbn07XG5cbsK1LnV0aWwuZGF0YUZyb21FcXVhdGlvbjIgPSBmdW5jdGlvbihfZXF1YXRpb24sIF9zdGVwKSB7XG4gICAgdmFyIHN0ZXAgPSBfc3RlcCB8fCA2O1xuICAgIHZhciBkYXRhID0gZDMucmFuZ2UoMCwgMzYwICsgc3RlcCwgc3RlcCkubWFwKGZ1bmN0aW9uKGRlZywgaW5kZXgpIHtcbiAgICAgICAgdmFyIHRoZXRhID0gZGVnICogTWF0aC5QSSAvIDE4MDtcbiAgICAgICAgdmFyIHJhZGl1cyA9IF9lcXVhdGlvbih0aGV0YSk7XG4gICAgICAgIHJldHVybiBbIGRlZywgcmFkaXVzIF07XG4gICAgfSk7XG4gICAgcmV0dXJuIGRhdGE7XG59O1xuXG7CtS51dGlsLmRhdGFGcm9tRXF1YXRpb24gPSBmdW5jdGlvbihfZXF1YXRpb24sIF9zdGVwLCBfbmFtZSkge1xuICAgIHZhciBzdGVwID0gX3N0ZXAgfHwgNjtcbiAgICB2YXIgdCA9IFtdLCByID0gW107XG4gICAgZDMucmFuZ2UoMCwgMzYwICsgc3RlcCwgc3RlcCkuZm9yRWFjaChmdW5jdGlvbihkZWcsIGluZGV4KSB7XG4gICAgICAgIHZhciB0aGV0YSA9IGRlZyAqIE1hdGguUEkgLyAxODA7XG4gICAgICAgIHZhciByYWRpdXMgPSBfZXF1YXRpb24odGhldGEpO1xuICAgICAgICB0LnB1c2goZGVnKTtcbiAgICAgICAgci5wdXNoKHJhZGl1cyk7XG4gICAgfSk7XG4gICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgdDogdCxcbiAgICAgICAgcjogclxuICAgIH07XG4gICAgaWYgKF9uYW1lKSByZXN1bHQubmFtZSA9IF9uYW1lO1xuICAgIHJldHVybiByZXN1bHQ7XG59O1xuXG7CtS51dGlsLmVuc3VyZUFycmF5ID0gZnVuY3Rpb24oX3ZhbCwgX2NvdW50KSB7XG4gICAgaWYgKHR5cGVvZiBfdmFsID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gICAgdmFyIGFyciA9IFtdLmNvbmNhdChfdmFsKTtcbiAgICByZXR1cm4gZDMucmFuZ2UoX2NvdW50KS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gYXJyW2ldIHx8IGFyclswXTtcbiAgICB9KTtcbn07XG5cbsK1LnV0aWwuZmlsbEFycmF5cyA9IGZ1bmN0aW9uKF9vYmosIF92YWx1ZU5hbWVzLCBfY291bnQpIHtcbiAgICBfdmFsdWVOYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgX29ialtkXSA9IMK1LnV0aWwuZW5zdXJlQXJyYXkoX29ialtkXSwgX2NvdW50KTtcbiAgICB9KTtcbiAgICByZXR1cm4gX29iajtcbn07XG5cbsK1LnV0aWwuY2xvbmVKc29uID0gZnVuY3Rpb24oanNvbikge1xuICAgIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbn07XG5cbsK1LnV0aWwudmFsaWRhdGVLZXlzID0gZnVuY3Rpb24ob2JqLCBrZXlzKSB7XG4gICAgaWYgKHR5cGVvZiBrZXlzID09PSAnc3RyaW5nJykga2V5cyA9IGtleXMuc3BsaXQoJy4nKTtcbiAgICB2YXIgbmV4dCA9IGtleXMuc2hpZnQoKTtcbiAgICByZXR1cm4gb2JqW25leHRdICYmICgha2V5cy5sZW5ndGggfHwgb2JqSGFzS2V5cyhvYmpbbmV4dF0sIGtleXMpKTtcbn07XG5cbsK1LnV0aWwuc3VtQXJyYXlzID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBkMy56aXAoYSwgYikubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGQzLnN1bShkKTtcbiAgICB9KTtcbn07XG5cbsK1LnV0aWwuYXJyYXlMYXN0ID0gZnVuY3Rpb24oYSkge1xuICAgIHJldHVybiBhW2EubGVuZ3RoIC0gMV07XG59O1xuXG7CtS51dGlsLmFycmF5RXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIGkgPSBNYXRoLm1heChhLmxlbmd0aCwgYi5sZW5ndGgsIDEpO1xuICAgIHdoaWxlIChpLS0gPj0gMCAmJiBhW2ldID09PSBiW2ldKSA7XG4gICAgcmV0dXJuIGkgPT09IC0yO1xufTtcblxuwrUudXRpbC5mbGF0dGVuQXJyYXkgPSBmdW5jdGlvbihhcnIpIHtcbiAgICB2YXIgciA9IFtdO1xuICAgIHdoaWxlICghwrUudXRpbC5hcnJheUVxdWFsKHIsIGFycikpIHtcbiAgICAgICAgciA9IGFycjtcbiAgICAgICAgYXJyID0gW10uY29uY2F0LmFwcGx5KFtdLCBhcnIpO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufTtcblxuwrUudXRpbC5kZWR1cGxpY2F0ZSA9IGZ1bmN0aW9uKGFycikge1xuICAgIHJldHVybiBhcnIuZmlsdGVyKGZ1bmN0aW9uKHYsIGksIGEpIHtcbiAgICAgICAgcmV0dXJuIGEuaW5kZXhPZih2KSA9PSBpO1xuICAgIH0pO1xufTtcblxuwrUudXRpbC5jb252ZXJ0VG9DYXJ0ZXNpYW4gPSBmdW5jdGlvbihyYWRpdXMsIHRoZXRhKSB7XG4gICAgdmFyIHRoZXRhUmFkaWFucyA9IHRoZXRhICogTWF0aC5QSSAvIDE4MDtcbiAgICB2YXIgeCA9IHJhZGl1cyAqIE1hdGguY29zKHRoZXRhUmFkaWFucyk7XG4gICAgdmFyIHkgPSByYWRpdXMgKiBNYXRoLnNpbih0aGV0YVJhZGlhbnMpO1xuICAgIHJldHVybiBbIHgsIHkgXTtcbn07XG5cbsK1LnV0aWwucm91bmQgPSBmdW5jdGlvbihfdmFsdWUsIF9kaWdpdHMpIHtcbiAgICB2YXIgZGlnaXRzID0gX2RpZ2l0cyB8fCAyO1xuICAgIHZhciBtdWx0ID0gTWF0aC5wb3coMTAsIGRpZ2l0cyk7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoX3ZhbHVlICogbXVsdCkgLyBtdWx0O1xufTtcblxuwrUudXRpbC5nZXRNb3VzZVBvcyA9IGZ1bmN0aW9uKF9yZWZlcmVuY2VFbGVtZW50KSB7XG4gICAgdmFyIG1vdXNlUG9zID0gZDMubW91c2UoX3JlZmVyZW5jZUVsZW1lbnQubm9kZSgpKTtcbiAgICB2YXIgbW91c2VYID0gbW91c2VQb3NbMF07XG4gICAgdmFyIG1vdXNlWSA9IG1vdXNlUG9zWzFdO1xuICAgIHZhciBtb3VzZSA9IHt9O1xuICAgIG1vdXNlLnggPSBtb3VzZVg7XG4gICAgbW91c2UueSA9IG1vdXNlWTtcbiAgICBtb3VzZS5wb3MgPSBtb3VzZVBvcztcbiAgICBtb3VzZS5hbmdsZSA9IChNYXRoLmF0YW4yKG1vdXNlWSwgbW91c2VYKSArIE1hdGguUEkpICogMTgwIC8gTWF0aC5QSTtcbiAgICBtb3VzZS5yYWRpdXMgPSBNYXRoLnNxcnQobW91c2VYICogbW91c2VYICsgbW91c2VZICogbW91c2VZKTtcbiAgICByZXR1cm4gbW91c2U7XG59O1xuXG7CtS51dGlsLmR1cGxpY2F0ZXNDb3VudCA9IGZ1bmN0aW9uKGFycikge1xuICAgIHZhciB1bmlxdWVzID0ge30sIHZhbDtcbiAgICB2YXIgZHVwcyA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhcnIubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFsID0gYXJyW2ldO1xuICAgICAgICBpZiAodmFsIGluIHVuaXF1ZXMpIHtcbiAgICAgICAgICAgIHVuaXF1ZXNbdmFsXSsrO1xuICAgICAgICAgICAgZHVwc1t2YWxdID0gdW5pcXVlc1t2YWxdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdW5pcXVlc1t2YWxdID0gMTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZHVwcztcbn07XG5cbsK1LnV0aWwuZHVwbGljYXRlcyA9IGZ1bmN0aW9uKGFycikge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyjCtS51dGlsLmR1cGxpY2F0ZXNDb3VudChhcnIpKTtcbn07XG5cbsK1LnV0aWwudHJhbnNsYXRvciA9IGZ1bmN0aW9uKG9iaiwgc291cmNlQnJhbmNoLCB0YXJnZXRCcmFuY2gsIHJldmVyc2UpIHtcbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICB2YXIgdGFyZ2V0QnJhbmNoQ29weSA9IHRhcmdldEJyYW5jaC5zbGljZSgpO1xuICAgICAgICB0YXJnZXRCcmFuY2ggPSBzb3VyY2VCcmFuY2g7XG4gICAgICAgIHNvdXJjZUJyYW5jaCA9IHRhcmdldEJyYW5jaENvcHk7XG4gICAgfVxuICAgIHZhciB2YWx1ZSA9IHNvdXJjZUJyYW5jaC5yZWR1Y2UoZnVuY3Rpb24ocHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSAhPSAndW5kZWZpbmVkJykgcmV0dXJuIHByZXZpb3VzVmFsdWVbY3VycmVudFZhbHVlXTtcbiAgICB9LCBvYmopO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnKSByZXR1cm47XG4gICAgc291cmNlQnJhbmNoLnJlZHVjZShmdW5jdGlvbihwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PSAndW5kZWZpbmVkJykgcmV0dXJuO1xuICAgICAgICBpZiAoaW5kZXggPT09IHNvdXJjZUJyYW5jaC5sZW5ndGggLSAxKSBkZWxldGUgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgIH0sIG9iaik7XG4gICAgdGFyZ2V0QnJhbmNoLnJlZHVjZShmdW5jdGlvbihwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdID09PSAndW5kZWZpbmVkJykgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdID0ge307XG4gICAgICAgIGlmIChpbmRleCA9PT0gdGFyZ2V0QnJhbmNoLmxlbmd0aCAtIDEpIHByZXZpb3VzVmFsdWVbY3VycmVudFZhbHVlXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgIH0sIG9iaik7XG59O1xuXG7CtS5Qb2x5Q2hhcnQgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGNvbmZpZyA9IFsgwrUuUG9seUNoYXJ0LmRlZmF1bHRDb25maWcoKSBdO1xuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpO1xuICAgIHZhciBkYXNoQXJyYXkgPSB7XG4gICAgICAgIHNvbGlkOiAnbm9uZScsXG4gICAgICAgIGRhc2g6IFsgNSwgMiBdLFxuICAgICAgICBkb3Q6IFsgMiwgNSBdXG4gICAgfTtcbiAgICB2YXIgY29sb3JTY2FsZTtcbiAgICBmdW5jdGlvbiBleHBvcnRzKCkge1xuICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWcgPSBjb25maWdbMF0uZ2VvbWV0cnlDb25maWc7XG4gICAgICAgIHZhciBjb250YWluZXIgPSBnZW9tZXRyeUNvbmZpZy5jb250YWluZXI7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGFpbmVyID09ICdzdHJpbmcnKSBjb250YWluZXIgPSBkMy5zZWxlY3QoY29udGFpbmVyKTtcbiAgICAgICAgY29udGFpbmVyLmRhdHVtKGNvbmZpZykuZWFjaChmdW5jdGlvbihfY29uZmlnLCBfaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBpc1N0YWNrID0gISFfY29uZmlnWzBdLmRhdGEueVN0YWNrO1xuICAgICAgICAgICAgdmFyIGRhdGEgPSBfY29uZmlnLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzU3RhY2spIHJldHVybiBkMy56aXAoZC5kYXRhLnRbMF0sIGQuZGF0YS5yWzBdLCBkLmRhdGEueVN0YWNrWzBdKTsgZWxzZSByZXR1cm4gZDMuemlwKGQuZGF0YS50WzBdLCBkLmRhdGEuclswXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyU2NhbGUgPSBnZW9tZXRyeUNvbmZpZy5hbmd1bGFyU2NhbGU7XG4gICAgICAgICAgICB2YXIgZG9tYWluTWluID0gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUuZG9tYWluKClbMF07XG4gICAgICAgICAgICB2YXIgZ2VuZXJhdG9yID0ge307XG4gICAgICAgICAgICBnZW5lcmF0b3IuYmFyID0gZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YUNvbmZpZyA9IF9jb25maWdbcEldLmRhdGE7XG4gICAgICAgICAgICAgICAgdmFyIGggPSBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkWzFdKSAtIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKDApO1xuICAgICAgICAgICAgICAgIHZhciBzdGFja1RvcCA9IGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKGRbMl0gfHwgMCk7XG4gICAgICAgICAgICAgICAgdmFyIHcgPSBkYXRhQ29uZmlnLmJhcldpZHRoO1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21hcmsgYmFyJyxcbiAgICAgICAgICAgICAgICAgICAgZDogJ00nICsgWyBbIGggKyBzdGFja1RvcCwgLXcgLyAyIF0sIFsgaCArIHN0YWNrVG9wLCB3IC8gMiBdLCBbIHN0YWNrVG9wLCB3IC8gMiBdLCBbIHN0YWNrVG9wLCAtdyAvIDIgXSBdLmpvaW4oJ0wnKSArICdaJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgKGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uICsgYW5ndWxhclNjYWxlKGRbMF0pKSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGdlbmVyYXRvci5kb3QgPSBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgIHZhciBzdGFja2VkRGF0YSA9IGRbMl0gPyBbIGRbMF0sIGRbMV0gKyBkWzJdIF0gOiBkO1xuICAgICAgICAgICAgICAgIHZhciBzeW1ib2wgPSBkMy5zdmcuc3ltYm9sKCkuc2l6ZShfY29uZmlnW3BJXS5kYXRhLmRvdFNpemUpLnR5cGUoX2NvbmZpZ1twSV0uZGF0YS5kb3RUeXBlKShkLCBpKTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtYXJrIGRvdCcsXG4gICAgICAgICAgICAgICAgICAgIGQ6IHN5bWJvbCxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBjb252ZXJ0VG9DYXJ0ZXNpYW4oZ2V0UG9sYXJDb29yZGluYXRlcyhzdGFja2VkRGF0YSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIFsgY29vcmQueCwgY29vcmQueSBdICsgJyknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBkMy5zdmcubGluZS5yYWRpYWwoKS5pbnRlcnBvbGF0ZShfY29uZmlnWzBdLmRhdGEubGluZUludGVycG9sYXRpb24pLnJhZGl1cyhmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKGRbMV0pO1xuICAgICAgICAgICAgfSkuYW5nbGUoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBnZW9tZXRyeUNvbmZpZy5hbmd1bGFyU2NhbGUoZFswXSkgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBnZW5lcmF0b3IubGluZSA9IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpbmVEYXRhID0gZFsyXSA/IGRhdGFbcEldLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbIGRbMF0sIGRbMV0gKyBkWzJdIF07XG4gICAgICAgICAgICAgICAgfSkgOiBkYXRhW3BJXTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuZWFjaChnZW5lcmF0b3JbJ2RvdCddKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICtfY29uZmlnW3BJXS5kYXRhLmRvdFZpc2libGU7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IG1hcmtTdHlsZS5zdHJva2UoZCwgaSwgcEkpXG4gICAgICAgICAgICAgICAgfSkuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtYXJrIGRvdCdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoaSA+IDApIHJldHVybjtcbiAgICAgICAgICAgICAgICB2YXIgbGluZVNlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzLnBhcmVudE5vZGUpLnNlbGVjdEFsbCgncGF0aC5saW5lJykuZGF0YShbIDAgXSk7XG4gICAgICAgICAgICAgICAgbGluZVNlbGVjdGlvbi5lbnRlcigpLmluc2VydCgncGF0aCcpO1xuICAgICAgICAgICAgICAgIGxpbmVTZWxlY3Rpb24uYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdsaW5lJyxcbiAgICAgICAgICAgICAgICAgICAgZDogbGluZShsaW5lRGF0YSksXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgKGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uICsgOTApICsgJyknO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZSdcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hcmtTdHlsZS5maWxsKGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6IDAsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFya1N0eWxlLnN0cm9rZShkLCBpLCBwSSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBmdW5jdGlvbihkQiwgaUIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXJrU3R5bGVbJ3N0cm9rZS13aWR0aCddKGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiBmdW5jdGlvbihkQiwgaUIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXJrU3R5bGVbJ3N0cm9rZS1kYXNoYXJyYXknXShkLCBpLCBwSSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hcmtTdHlsZS5vcGFjaXR5KGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFya1N0eWxlLmRpc3BsYXkoZCwgaSwgcEkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJSYW5nZSA9IGdlb21ldHJ5Q29uZmlnLmFuZ3VsYXJTY2FsZS5yYW5nZSgpO1xuICAgICAgICAgICAgdmFyIHRyaWFuZ2xlQW5nbGUgPSBNYXRoLmFicyhhbmd1bGFyUmFuZ2VbMV0gLSBhbmd1bGFyUmFuZ2VbMF0pIC8gZGF0YVswXS5sZW5ndGggKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgdmFyIGFyYyA9IGQzLnN2Zy5hcmMoKS5zdGFydEFuZ2xlKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLXRyaWFuZ2xlQW5nbGUgLyAyO1xuICAgICAgICAgICAgfSkuZW5kQW5nbGUoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmlhbmdsZUFuZ2xlIC8gMjtcbiAgICAgICAgICAgIH0pLmlubmVyUmFkaXVzKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUoZG9tYWluTWluICsgKGRbMl0gfHwgMCkpO1xuICAgICAgICAgICAgfSkub3V0ZXJSYWRpdXMoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkb21haW5NaW4gKyAoZFsyXSB8fCAwKSkgKyBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkWzFdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2VuZXJhdG9yLmFyYyA9IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWFyayBhcmMnLFxuICAgICAgICAgICAgICAgICAgICBkOiBhcmMsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdyb3RhdGUoJyArIChnZW9tZXRyeUNvbmZpZy5vcmllbnRhdGlvbiArIGFuZ3VsYXJTY2FsZShkWzBdKSArIDkwKSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBtYXJrU3R5bGUgPSB7XG4gICAgICAgICAgICAgICAgZmlsbDogZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jb25maWdbcEldLmRhdGEuY29sb3I7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzdHJva2U6IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfY29uZmlnW3BJXS5kYXRhLnN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfY29uZmlnW3BJXS5kYXRhLnN0cm9rZVNpemUgKyAncHgnO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGFzaEFycmF5W19jb25maWdbcEldLmRhdGEuc3Ryb2tlRGFzaF07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NvbmZpZ1twSV0uZGF0YS5vcGFjaXR5O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGlzcGxheTogZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBfY29uZmlnW3BJXS5kYXRhLnZpc2libGUgPT09ICd1bmRlZmluZWQnIHx8IF9jb25maWdbcEldLmRhdGEudmlzaWJsZSA/ICdibG9jaycgOiAnbm9uZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBnZW9tZXRyeUxheWVyID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgnZy5sYXllcicpLmRhdGEoZGF0YSk7XG4gICAgICAgICAgICBnZW9tZXRyeUxheWVyLmVudGVyKCkuYXBwZW5kKCdnJykuYXR0cih7XG4gICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2xheWVyJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgZ2VvbWV0cnkgPSBnZW9tZXRyeUxheWVyLnNlbGVjdEFsbCgncGF0aC5tYXJrJykuZGF0YShmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGdlb21ldHJ5LmVudGVyKCkuYXBwZW5kKCdwYXRoJykuYXR0cih7XG4gICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21hcmsnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGdlb21ldHJ5LnN0eWxlKG1hcmtTdHlsZSkuZWFjaChnZW5lcmF0b3JbZ2VvbWV0cnlDb25maWcuZ2VvbWV0cnlUeXBlXSk7XG4gICAgICAgICAgICBnZW9tZXRyeS5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICBnZW9tZXRyeUxheWVyLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFBvbGFyQ29vcmRpbmF0ZXMoZCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciByID0gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUoZFsxXSk7XG4gICAgICAgICAgICAgICAgdmFyIHQgPSAoZ2VvbWV0cnlDb25maWcuYW5ndWxhclNjYWxlKGRbMF0pICsgZ2VvbWV0cnlDb25maWcub3JpZW50YXRpb24pICogTWF0aC5QSSAvIDE4MDtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICByOiByLFxuICAgICAgICAgICAgICAgICAgICB0OiB0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNvbnZlcnRUb0NhcnRlc2lhbihwb2xhckNvb3JkaW5hdGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHggPSBwb2xhckNvb3JkaW5hdGVzLnIgKiBNYXRoLmNvcyhwb2xhckNvb3JkaW5hdGVzLnQpO1xuICAgICAgICAgICAgICAgIHZhciB5ID0gcG9sYXJDb29yZGluYXRlcy5yICogTWF0aC5zaW4ocG9sYXJDb29yZGluYXRlcy50KTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgICAgICAgICB5OiB5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGV4cG9ydHMuY29uZmlnID0gZnVuY3Rpb24oX3gpIHtcbiAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY29uZmlnO1xuICAgICAgICBfeC5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnW2ldKSBjb25maWdbaV0gPSB7fTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnW2ldLCDCtS5Qb2x5Q2hhcnQuZGVmYXVsdENvbmZpZygpKTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnW2ldLCBkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRDb2xvclNjYWxlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBjb2xvclNjYWxlO1xuICAgIH07XG4gICAgZDMucmViaW5kKGV4cG9ydHMsIGRpc3BhdGNoLCAnb24nKTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbsK1LlBvbHlDaGFydC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgbmFtZTogJ2dlb20xJyxcbiAgICAgICAgICAgIHQ6IFsgWyAxLCAyLCAzLCA0IF0gXSxcbiAgICAgICAgICAgIHI6IFsgWyAxLCAyLCAzLCA0IF0gXSxcbiAgICAgICAgICAgIGRvdFR5cGU6ICdjaXJjbGUnLFxuICAgICAgICAgICAgZG90U2l6ZTogNjQsXG4gICAgICAgICAgICBkb3RWaXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGJhcldpZHRoOiAyMCxcbiAgICAgICAgICAgIGNvbG9yOiAnI2ZmYTUwMCcsXG4gICAgICAgICAgICBzdHJva2VTaXplOiAxLFxuICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICdzaWx2ZXInLFxuICAgICAgICAgICAgc3Ryb2tlRGFzaDogJ3NvbGlkJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgICAgICB2aXNpYmxlSW5MZWdlbmQ6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5OiAnTGluZVBsb3QnLFxuICAgICAgICAgICAgZ2VvbWV0cnlUeXBlOiAnYXJjJyxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ2Nsb2Nrd2lzZScsXG4gICAgICAgICAgICBvcmllbnRhdGlvbjogMCxcbiAgICAgICAgICAgIGNvbnRhaW5lcjogJ2JvZHknLFxuICAgICAgICAgICAgcmFkaWFsU2NhbGU6IG51bGwsXG4gICAgICAgICAgICBhbmd1bGFyU2NhbGU6IG51bGwsXG4gICAgICAgICAgICBjb2xvclNjYWxlOiBkMy5zY2FsZS5jYXRlZ29yeTIwKClcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGNvbmZpZztcbn07XG5cbsK1LkJhckNoYXJ0ID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHJldHVybiDCtS5Qb2x5Q2hhcnQoKTtcbn07XG5cbsK1LkJhckNoYXJ0LmRlZmF1bHRDb25maWcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgY29uZmlnID0ge1xuICAgICAgICBnZW9tZXRyeUNvbmZpZzoge1xuICAgICAgICAgICAgZ2VvbWV0cnlUeXBlOiAnYmFyJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuQXJlYUNoYXJ0ID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHJldHVybiDCtS5Qb2x5Q2hhcnQoKTtcbn07XG5cbsK1LkFyZWFDaGFydC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5VHlwZTogJ2FyYydcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGNvbmZpZztcbn07XG5cbsK1LkRvdFBsb3QgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgcmV0dXJuIMK1LlBvbHlDaGFydCgpO1xufTtcblxuwrUuRG90UGxvdC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5VHlwZTogJ2RvdCcsXG4gICAgICAgICAgICBkb3RUeXBlOiAnY2lyY2xlJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuTGluZVBsb3QgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgcmV0dXJuIMK1LlBvbHlDaGFydCgpO1xufTtcblxuwrUuTGluZVBsb3QuZGVmYXVsdENvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGdlb21ldHJ5Q29uZmlnOiB7XG4gICAgICAgICAgICBnZW9tZXRyeVR5cGU6ICdsaW5lJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuTGVnZW5kID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHZhciBjb25maWcgPSDCtS5MZWdlbmQuZGVmYXVsdENvbmZpZygpO1xuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpO1xuICAgIGZ1bmN0aW9uIGV4cG9ydHMoKSB7XG4gICAgICAgIHZhciBsZWdlbmRDb25maWcgPSBjb25maWcubGVnZW5kQ29uZmlnO1xuICAgICAgICB2YXIgZmxhdHRlbkRhdGEgPSBjb25maWcuZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdLmNvbmNhdChkKS5tYXAoZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBleHRlbmREZWVwQWxsKHt9LCBsZWdlbmRDb25maWcuZWxlbWVudHNbaV0pO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQubmFtZSA9IGRCO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuY29sb3IgPSBbXS5jb25jYXQobGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLmNvbG9yKVtpQl07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBkYXRhID0gZDMubWVyZ2UoZmxhdHRlbkRhdGEpO1xuICAgICAgICBkYXRhID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIGxlZ2VuZENvbmZpZy5lbGVtZW50c1tpXSAmJiAobGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLnZpc2libGVJbkxlZ2VuZCB8fCB0eXBlb2YgbGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLnZpc2libGVJbkxlZ2VuZCA9PT0gJ3VuZGVmaW5lZCcpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGxlZ2VuZENvbmZpZy5yZXZlcnNlT3JkZXIpIGRhdGEgPSBkYXRhLnJldmVyc2UoKTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IGxlZ2VuZENvbmZpZy5jb250YWluZXI7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGFpbmVyID09ICdzdHJpbmcnIHx8IGNvbnRhaW5lci5ub2RlTmFtZSkgY29udGFpbmVyID0gZDMuc2VsZWN0KGNvbnRhaW5lcik7XG4gICAgICAgIHZhciBjb2xvcnMgPSBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jb2xvcjtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBsaW5lSGVpZ2h0ID0gbGVnZW5kQ29uZmlnLmZvbnRTaXplO1xuICAgICAgICB2YXIgaXNDb250aW51b3VzID0gbGVnZW5kQ29uZmlnLmlzQ29udGludW91cyA9PSBudWxsID8gdHlwZW9mIGRhdGFbMF0gPT09ICdudW1iZXInIDogbGVnZW5kQ29uZmlnLmlzQ29udGludW91cztcbiAgICAgICAgdmFyIGhlaWdodCA9IGlzQ29udGludW91cyA/IGxlZ2VuZENvbmZpZy5oZWlnaHQgOiBsaW5lSGVpZ2h0ICogZGF0YS5sZW5ndGg7XG4gICAgICAgIHZhciBsZWdlbmRDb250YWluZXJHcm91cCA9IGNvbnRhaW5lci5jbGFzc2VkKCdsZWdlbmQtZ3JvdXAnLCB0cnVlKTtcbiAgICAgICAgdmFyIHN2ZyA9IGxlZ2VuZENvbnRhaW5lckdyb3VwLnNlbGVjdEFsbCgnc3ZnJykuZGF0YShbIDAgXSk7XG4gICAgICAgIHZhciBzdmdFbnRlciA9IHN2Zy5lbnRlcigpLmFwcGVuZCgnc3ZnJykuYXR0cih7XG4gICAgICAgICAgICB3aWR0aDogMzAwLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyBsaW5lSGVpZ2h0LFxuICAgICAgICAgICAgeG1sbnM6ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsXG4gICAgICAgICAgICAneG1sbnM6eGxpbmsnOiAnaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluaycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAnMS4xJ1xuICAgICAgICB9KTtcbiAgICAgICAgc3ZnRW50ZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnbGVnZW5kLWF4aXMnLCB0cnVlKTtcbiAgICAgICAgc3ZnRW50ZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnbGVnZW5kLW1hcmtzJywgdHJ1ZSk7XG4gICAgICAgIHZhciBkYXRhTnVtYmVyZWQgPSBkMy5yYW5nZShkYXRhLmxlbmd0aCk7XG4gICAgICAgIHZhciBjb2xvclNjYWxlID0gZDMuc2NhbGVbaXNDb250aW51b3VzID8gJ2xpbmVhcicgOiAnb3JkaW5hbCddKCkuZG9tYWluKGRhdGFOdW1iZXJlZCkucmFuZ2UoY29sb3JzKTtcbiAgICAgICAgdmFyIGRhdGFTY2FsZSA9IGQzLnNjYWxlW2lzQ29udGludW91cyA/ICdsaW5lYXInIDogJ29yZGluYWwnXSgpLmRvbWFpbihkYXRhTnVtYmVyZWQpW2lzQ29udGludW91cyA/ICdyYW5nZScgOiAncmFuZ2VQb2ludHMnXShbIDAsIGhlaWdodCBdKTtcbiAgICAgICAgdmFyIHNoYXBlR2VuZXJhdG9yID0gZnVuY3Rpb24oX3R5cGUsIF9zaXplKSB7XG4gICAgICAgICAgICB2YXIgc3F1YXJlU2l6ZSA9IF9zaXplICogMztcbiAgICAgICAgICAgIGlmIChfdHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdNJyArIFsgWyAtX3NpemUgLyAyLCAtX3NpemUgLyAxMiBdLCBbIF9zaXplIC8gMiwgLV9zaXplIC8gMTIgXSwgWyBfc2l6ZSAvIDIsIF9zaXplIC8gMTIgXSwgWyAtX3NpemUgLyAyLCBfc2l6ZSAvIDEyIF0gXSArICdaJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZDMuc3ZnLnN5bWJvbFR5cGVzLmluZGV4T2YoX3R5cGUpICE9IC0xKSByZXR1cm4gZDMuc3ZnLnN5bWJvbCgpLnR5cGUoX3R5cGUpLnNpemUoc3F1YXJlU2l6ZSkoKTsgZWxzZSByZXR1cm4gZDMuc3ZnLnN5bWJvbCgpLnR5cGUoJ3NxdWFyZScpLnNpemUoc3F1YXJlU2l6ZSkoKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGlzQ29udGludW91cykge1xuICAgICAgICAgICAgdmFyIGdyYWRpZW50ID0gc3ZnLnNlbGVjdCgnLmxlZ2VuZC1tYXJrcycpLmFwcGVuZCgnZGVmcycpLmFwcGVuZCgnbGluZWFyR3JhZGllbnQnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICBpZDogJ2dyYWQxJyxcbiAgICAgICAgICAgICAgICB4MTogJzAlJyxcbiAgICAgICAgICAgICAgICB5MTogJzAlJyxcbiAgICAgICAgICAgICAgICB4MjogJzAlJyxcbiAgICAgICAgICAgICAgICB5MjogJzEwMCUnXG4gICAgICAgICAgICB9KS5zZWxlY3RBbGwoJ3N0b3AnKS5kYXRhKGNvbG9ycyk7XG4gICAgICAgICAgICBncmFkaWVudC5lbnRlcigpLmFwcGVuZCgnc3RvcCcpO1xuICAgICAgICAgICAgZ3JhZGllbnQuYXR0cih7XG4gICAgICAgICAgICAgICAgb2Zmc2V0OiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpIC8gKGNvbG9ycy5sZW5ndGggLSAxKSAqIDEwMCArICclJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3N0b3AtY29sb3InOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3ZnLmFwcGVuZCgncmVjdCcpLmNsYXNzZWQoJ2xlZ2VuZC1tYXJrJywgdHJ1ZSkuYXR0cih7XG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBsZWdlbmRDb25maWcuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBsZWdlbmRDb25maWcuY29sb3JCYW5kV2lkdGgsXG4gICAgICAgICAgICAgICAgZmlsbDogJ3VybCgjZ3JhZDEpJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgbGVnZW5kRWxlbWVudCA9IHN2Zy5zZWxlY3QoJy5sZWdlbmQtbWFya3MnKS5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kLW1hcmsnKS5kYXRhKGRhdGEpO1xuICAgICAgICAgICAgbGVnZW5kRWxlbWVudC5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZC1tYXJrJywgdHJ1ZSk7XG4gICAgICAgICAgICBsZWdlbmRFbGVtZW50LmF0dHIoe1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgWyBsaW5lSGVpZ2h0IC8gMiwgZGF0YVNjYWxlKGkpICsgbGluZUhlaWdodCAvIDIgXSArICcpJztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGQ6IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN5bWJvbFR5cGUgPSBkLnN5bWJvbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYXBlR2VuZXJhdG9yKHN5bWJvbFR5cGUsIGxpbmVIZWlnaHQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmlsbDogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sb3JTY2FsZShpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGxlZ2VuZEVsZW1lbnQuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWdlbmRBeGlzID0gZDMuc3ZnLmF4aXMoKS5zY2FsZShkYXRhU2NhbGUpLm9yaWVudCgncmlnaHQnKTtcbiAgICAgICAgdmFyIGF4aXMgPSBzdmcuc2VsZWN0KCdnLmxlZ2VuZC1heGlzJykuYXR0cih7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgaXNDb250aW51b3VzID8gbGVnZW5kQ29uZmlnLmNvbG9yQmFuZFdpZHRoIDogbGluZUhlaWdodCwgbGluZUhlaWdodCAvIDIgXSArICcpJ1xuICAgICAgICB9KS5jYWxsKGxlZ2VuZEF4aXMpO1xuICAgICAgICBheGlzLnNlbGVjdEFsbCgnLmRvbWFpbicpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgIHN0cm9rZTogJ25vbmUnXG4gICAgICAgIH0pO1xuICAgICAgICBheGlzLnNlbGVjdEFsbCgnbGluZScpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgIHN0cm9rZTogaXNDb250aW51b3VzID8gbGVnZW5kQ29uZmlnLnRleHRDb2xvciA6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgYXhpcy5zZWxlY3RBbGwoJ3RleHQnKS5zdHlsZSh7XG4gICAgICAgICAgICBmaWxsOiBsZWdlbmRDb25maWcudGV4dENvbG9yLFxuICAgICAgICAgICAgJ2ZvbnQtc2l6ZSc6IGxlZ2VuZENvbmZpZy5mb250U2l6ZVxuICAgICAgICB9KS50ZXh0KGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhW2ldLm5hbWU7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZXhwb3J0cztcbiAgICB9XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjb25maWc7XG4gICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLCBfeCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZDMucmViaW5kKGV4cG9ydHMsIGRpc3BhdGNoLCAnb24nKTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbsK1LkxlZ2VuZC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oZCwgaSkge1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGRhdGE6IFsgJ2EnLCAnYicsICdjJyBdLFxuICAgICAgICBsZWdlbmRDb25maWc6IHtcbiAgICAgICAgICAgIGVsZW1lbnRzOiBbIHtcbiAgICAgICAgICAgICAgICBzeW1ib2w6ICdsaW5lJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogJ3JlZCdcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBzeW1ib2w6ICdzcXVhcmUnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAneWVsbG93J1xuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHN5bWJvbDogJ2RpYW1vbmQnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnbGltZWdyZWVuJ1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgaGVpZ2h0OiAxNTAsXG4gICAgICAgICAgICBjb2xvckJhbmRXaWR0aDogMzAsXG4gICAgICAgICAgICBmb250U2l6ZTogMTIsXG4gICAgICAgICAgICBjb250YWluZXI6ICdib2R5JyxcbiAgICAgICAgICAgIGlzQ29udGludW91czogbnVsbCxcbiAgICAgICAgICAgIHRleHRDb2xvcjogJ2dyZXknLFxuICAgICAgICAgICAgcmV2ZXJzZU9yZGVyOiBmYWxzZVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUudG9vbHRpcFBhbmVsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRvb2x0aXBFbCwgdG9vbHRpcFRleHRFbCwgYmFja2dyb3VuZEVsO1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGNvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgaGFzVGljazogZmFsc2UsXG4gICAgICAgIGZvbnRTaXplOiAxMixcbiAgICAgICAgY29sb3I6ICd3aGl0ZScsXG4gICAgICAgIHBhZGRpbmc6IDVcbiAgICB9O1xuICAgIHZhciBpZCA9ICd0b29sdGlwLScgKyDCtS50b29sdGlwUGFuZWwudWlkKys7XG4gICAgdmFyIHRpY2tTaXplID0gMTA7XG4gICAgdmFyIGV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdG9vbHRpcEVsID0gY29uZmlnLmNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJyArIGlkKS5kYXRhKFsgMCBdKTtcbiAgICAgICAgdmFyIHRvb2x0aXBFbnRlciA9IHRvb2x0aXBFbC5lbnRlcigpLmFwcGVuZCgnZycpLmNsYXNzZWQoaWQsIHRydWUpLnN0eWxlKHtcbiAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJyxcbiAgICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgYmFja2dyb3VuZEVsID0gdG9vbHRpcEVudGVyLmFwcGVuZCgncGF0aCcpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICd3aGl0ZScsXG4gICAgICAgICAgICAnZmlsbC1vcGFjaXR5JzogLjlcbiAgICAgICAgfSkuYXR0cih7XG4gICAgICAgICAgICBkOiAnTTAgMCdcbiAgICAgICAgfSk7XG4gICAgICAgIHRvb2x0aXBUZXh0RWwgPSB0b29sdGlwRW50ZXIuYXBwZW5kKCd0ZXh0JykuYXR0cih7XG4gICAgICAgICAgICBkeDogY29uZmlnLnBhZGRpbmcgKyB0aWNrU2l6ZSxcbiAgICAgICAgICAgIGR5OiArY29uZmlnLmZvbnRTaXplICogLjNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBleHBvcnRzO1xuICAgIH07XG4gICAgZXhwb3J0cy50ZXh0ID0gZnVuY3Rpb24oX3RleHQpIHtcbiAgICAgICAgdmFyIGwgPSBkMy5oc2woY29uZmlnLmNvbG9yKS5sO1xuICAgICAgICB2YXIgc3Ryb2tlQ29sb3IgPSBsID49IC41ID8gJyNhYWEnIDogJ3doaXRlJztcbiAgICAgICAgdmFyIGZpbGxDb2xvciA9IGwgPj0gLjUgPyAnYmxhY2snIDogJ3doaXRlJztcbiAgICAgICAgdmFyIHRleHQgPSBfdGV4dCB8fCAnJztcbiAgICAgICAgdG9vbHRpcFRleHRFbC5zdHlsZSh7XG4gICAgICAgICAgICBmaWxsOiBmaWxsQ29sb3IsXG4gICAgICAgICAgICAnZm9udC1zaXplJzogY29uZmlnLmZvbnRTaXplICsgJ3B4J1xuICAgICAgICB9KS50ZXh0KHRleHQpO1xuICAgICAgICB2YXIgcGFkZGluZyA9IGNvbmZpZy5wYWRkaW5nO1xuICAgICAgICB2YXIgYmJveCA9IHRvb2x0aXBUZXh0RWwubm9kZSgpLmdldEJCb3goKTtcbiAgICAgICAgdmFyIGJveFN0eWxlID0ge1xuICAgICAgICAgICAgZmlsbDogY29uZmlnLmNvbG9yLFxuICAgICAgICAgICAgc3Ryb2tlOiBzdHJva2VDb2xvcixcbiAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiAnMnB4J1xuICAgICAgICB9O1xuICAgICAgICB2YXIgYmFja0dyb3VuZFcgPSBiYm94LndpZHRoICsgcGFkZGluZyAqIDIgKyB0aWNrU2l6ZTtcbiAgICAgICAgdmFyIGJhY2tHcm91bmRIID0gYmJveC5oZWlnaHQgKyBwYWRkaW5nICogMjtcbiAgICAgICAgYmFja2dyb3VuZEVsLmF0dHIoe1xuICAgICAgICAgICAgZDogJ00nICsgWyBbIHRpY2tTaXplLCAtYmFja0dyb3VuZEggLyAyIF0sIFsgdGlja1NpemUsIC1iYWNrR3JvdW5kSCAvIDQgXSwgWyBjb25maWcuaGFzVGljayA/IDAgOiB0aWNrU2l6ZSwgMCBdLCBbIHRpY2tTaXplLCBiYWNrR3JvdW5kSCAvIDQgXSwgWyB0aWNrU2l6ZSwgYmFja0dyb3VuZEggLyAyIF0sIFsgYmFja0dyb3VuZFcsIGJhY2tHcm91bmRIIC8gMiBdLCBbIGJhY2tHcm91bmRXLCAtYmFja0dyb3VuZEggLyAyIF0gXS5qb2luKCdMJykgKyAnWidcbiAgICAgICAgfSkuc3R5bGUoYm94U3R5bGUpO1xuICAgICAgICB0b29sdGlwRWwuYXR0cih7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgdGlja1NpemUsIC1iYWNrR3JvdW5kSCAvIDIgKyBwYWRkaW5nICogMiBdICsgJyknXG4gICAgICAgIH0pO1xuICAgICAgICB0b29sdGlwRWwuc3R5bGUoe1xuICAgICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLm1vdmUgPSBmdW5jdGlvbihfcG9zKSB7XG4gICAgICAgIGlmICghdG9vbHRpcEVsKSByZXR1cm47XG4gICAgICAgIHRvb2x0aXBFbC5hdHRyKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZSgnICsgWyBfcG9zWzBdLCBfcG9zWzFdIF0gKyAnKSdcbiAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLmhpZGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0b29sdGlwRWwpIHJldHVybjtcbiAgICAgICAgdG9vbHRpcEVsLnN0eWxlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLnNob3cgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0b29sdGlwRWwpIHJldHVybjtcbiAgICAgICAgdG9vbHRpcEVsLnN0eWxlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBleHBvcnRzO1xuICAgIH07XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBleHRlbmREZWVwQWxsKGNvbmZpZywgX3gpO1xuICAgICAgICByZXR1cm4gZXhwb3J0cztcbiAgICB9O1xuICAgIHJldHVybiBleHBvcnRzO1xufTtcblxuwrUudG9vbHRpcFBhbmVsLnVpZCA9IDE7XG5cbsK1LmFkYXB0ZXIgPSB7fTtcblxuwrUuYWRhcHRlci5wbG90bHkgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGV4cG9ydHMgPSB7fTtcbiAgICBleHBvcnRzLmNvbnZlcnQgPSBmdW5jdGlvbihfaW5wdXRDb25maWcsIHJldmVyc2UpIHtcbiAgICAgICAgdmFyIG91dHB1dENvbmZpZyA9IHt9O1xuICAgICAgICBpZiAoX2lucHV0Q29uZmlnLmRhdGEpIHtcbiAgICAgICAgICAgIG91dHB1dENvbmZpZy5kYXRhID0gX2lucHV0Q29uZmlnLmRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgciA9IGV4dGVuZERlZXBBbGwoe30sIGQpO1xuICAgICAgICAgICAgICAgIHZhciB0b1RyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnY29sb3InIF0sIFsgJ2NvbG9yJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ29wYWNpdHknIF0sIFsgJ29wYWNpdHknIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnbGluZScsICdjb2xvcicgXSwgWyAnc3Ryb2tlQ29sb3InIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnbGluZScsICdkYXNoJyBdLCBbICdzdHJva2VEYXNoJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ2xpbmUnLCAnd2lkdGgnIF0sIFsgJ3N0cm9rZVNpemUnIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnc3ltYm9sJyBdLCBbICdkb3RUeXBlJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ3NpemUnIF0sIFsgJ2RvdFNpemUnIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnYmFyV2lkdGgnIF0sIFsgJ2JhcldpZHRoJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbGluZScsICdpbnRlcnBvbGF0aW9uJyBdLCBbICdsaW5lSW50ZXJwb2xhdGlvbicgXSBdLFxuICAgICAgICAgICAgICAgICAgICBbIHIsIFsgJ3Nob3dsZWdlbmQnIF0sIFsgJ3Zpc2libGVJbkxlZ2VuZCcgXSBdXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB0b1RyYW5zbGF0ZS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgwrUudXRpbC50cmFuc2xhdG9yLmFwcGx5KG51bGwsIGQuY29uY2F0KHJldmVyc2UpKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICghcmV2ZXJzZSkgZGVsZXRlIHIubWFya2VyO1xuICAgICAgICAgICAgICAgIGlmIChyZXZlcnNlKSBkZWxldGUgci5ncm91cElkO1xuICAgICAgICAgICAgICAgIGlmICghcmV2ZXJzZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoci50eXBlID09PSAnc2NhdHRlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyLm1vZGUgPT09ICdsaW5lcycpIHIuZ2VvbWV0cnkgPSAnTGluZVBsb3QnOyBlbHNlIGlmIChyLm1vZGUgPT09ICdtYXJrZXJzJykgci5nZW9tZXRyeSA9ICdEb3RQbG90JzsgZWxzZSBpZiAoci5tb2RlID09PSAnbGluZXMrbWFya2VycycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLmdlb21ldHJ5ID0gJ0xpbmVQbG90JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLmRvdFZpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHIudHlwZSA9PT0gJ2FyZWEnKSByLmdlb21ldHJ5ID0gJ0FyZWFDaGFydCc7IGVsc2UgaWYgKHIudHlwZSA9PT0gJ2JhcicpIHIuZ2VvbWV0cnkgPSAnQmFyQ2hhcnQnO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci5tb2RlO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci50eXBlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyLmdlb21ldHJ5ID09PSAnTGluZVBsb3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByLnR5cGUgPSAnc2NhdHRlcic7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoci5kb3RWaXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIuZG90VmlzaWJsZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLm1vZGUgPSAnbGluZXMrbWFya2Vycyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugci5tb2RlID0gJ2xpbmVzJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnRG90UGxvdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHIudHlwZSA9ICdzY2F0dGVyJztcbiAgICAgICAgICAgICAgICAgICAgICAgIHIubW9kZSA9ICdtYXJrZXJzJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnQXJlYUNoYXJ0Jykgci50eXBlID0gJ2FyZWEnOyBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnQmFyQ2hhcnQnKSByLnR5cGUgPSAnYmFyJztcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIXJldmVyc2UgJiYgX2lucHV0Q29uZmlnLmxheW91dCAmJiBfaW5wdXRDb25maWcubGF5b3V0LmJhcm1vZGUgPT09ICdzdGFjaycpIHtcbiAgICAgICAgICAgICAgICB2YXIgZHVwbGljYXRlcyA9IMK1LnV0aWwuZHVwbGljYXRlcyhvdXRwdXRDb25maWcuZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC5nZW9tZXRyeTtcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgb3V0cHV0Q29uZmlnLmRhdGEuZm9yRWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpZHggPSBkdXBsaWNhdGVzLmluZGV4T2YoZC5nZW9tZXRyeSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpZHggIT0gLTEpIG91dHB1dENvbmZpZy5kYXRhW2ldLmdyb3VwSWQgPSBpZHg7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF9pbnB1dENvbmZpZy5sYXlvdXQpIHtcbiAgICAgICAgICAgIHZhciByID0gZXh0ZW5kRGVlcEFsbCh7fSwgX2lucHV0Q29uZmlnLmxheW91dCk7XG4gICAgICAgICAgICB2YXIgdG9UcmFuc2xhdGUgPSBbXG4gICAgICAgICAgICAgICAgWyByLCBbICdwbG90X2JnY29sb3InIF0sIFsgJ2JhY2tncm91bmRDb2xvcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnc2hvd2xlZ2VuZCcgXSwgWyAnc2hvd0xlZ2VuZCcgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAncmFkaWFsYXhpcycgXSwgWyAncmFkaWFsQXhpcycgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnYW5ndWxhcmF4aXMnIF0sIFsgJ2FuZ3VsYXJBeGlzJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdzaG93bGluZScgXSwgWyAnZ3JpZExpbmVzVmlzaWJsZScgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyYXhpcywgWyAnc2hvd3RpY2tsYWJlbHMnIF0sIFsgJ2xhYmVsc1Zpc2libGUnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhcmF4aXMsIFsgJ250aWNrcycgXSwgWyAndGlja3NDb3VudCcgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyYXhpcywgWyAndGlja29yaWVudGF0aW9uJyBdLCBbICd0aWNrT3JpZW50YXRpb24nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhcmF4aXMsIFsgJ3RpY2tzdWZmaXgnIF0sIFsgJ3RpY2tzU3VmZml4JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdyYW5nZScgXSwgWyAnZG9tYWluJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdlbmRwYWRkaW5nJyBdLCBbICdlbmRQYWRkaW5nJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3Nob3dsaW5lJyBdLCBbICdncmlkTGluZXNWaXNpYmxlJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3RpY2tvcmllbnRhdGlvbicgXSwgWyAndGlja09yaWVudGF0aW9uJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3RpY2tzdWZmaXgnIF0sIFsgJ3RpY2tzU3VmZml4JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3JhbmdlJyBdLCBbICdkb21haW4nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ3Nob3dsaW5lJyBdLCBbICdncmlkTGluZXNWaXNpYmxlJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJBeGlzLCBbICdzaG93dGlja2xhYmVscycgXSwgWyAnbGFiZWxzVmlzaWJsZScgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyQXhpcywgWyAnbnRpY2tzJyBdLCBbICd0aWNrc0NvdW50JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJBeGlzLCBbICd0aWNrb3JpZW50YXRpb24nIF0sIFsgJ3RpY2tPcmllbnRhdGlvbicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyQXhpcywgWyAndGlja3N1ZmZpeCcgXSwgWyAndGlja3NTdWZmaXgnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ3JhbmdlJyBdLCBbICdkb21haW4nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ2VuZHBhZGRpbmcnIF0sIFsgJ2VuZFBhZGRpbmcnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAnc2hvd2xpbmUnIF0sIFsgJ2dyaWRMaW5lc1Zpc2libGUnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAndGlja29yaWVudGF0aW9uJyBdLCBbICd0aWNrT3JpZW50YXRpb24nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAndGlja3N1ZmZpeCcgXSwgWyAndGlja3NTdWZmaXgnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAncmFuZ2UnIF0sIFsgJ2RvbWFpbicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5mb250LCBbICdvdXRsaW5lY29sb3InIF0sIFsgJ291dGxpbmVDb2xvcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5sZWdlbmQsIFsgJ3RyYWNlb3JkZXInIF0sIFsgJ3JldmVyc2VPcmRlcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnbGFiZWxvZmZzZXQnIF0sIFsgJ2xhYmVsT2Zmc2V0JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLCBbICdkZWZhdWx0Y29sb3JyYW5nZScgXSwgWyAnZGVmYXVsdENvbG9yUmFuZ2UnIF0gXVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHRvVHJhbnNsYXRlLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIMK1LnV0aWwudHJhbnNsYXRvci5hcHBseShudWxsLCBkLmNvbmNhdChyZXZlcnNlKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCFyZXZlcnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHIuYW5ndWxhckF4aXMgJiYgdHlwZW9mIHIuYW5ndWxhckF4aXMudGlja2xlbiAhPT0gJ3VuZGVmaW5lZCcpIHIudGlja0xlbmd0aCA9IHIuYW5ndWxhckF4aXMudGlja2xlbjtcbiAgICAgICAgICAgICAgICBpZiAoci5hbmd1bGFyQXhpcyAmJiB0eXBlb2Ygci5hbmd1bGFyQXhpcy50aWNrY29sb3IgIT09ICd1bmRlZmluZWQnKSByLnRpY2tDb2xvciA9IHIuYW5ndWxhckF4aXMudGlja2NvbG9yO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHIudGlja0xlbmd0aCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgci5hbmd1bGFyYXhpcy50aWNrbGVuID0gci50aWNrTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci50aWNrTGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoci50aWNrQ29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgci5hbmd1bGFyYXhpcy50aWNrY29sb3IgPSByLnRpY2tDb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIudGlja0NvbG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyLmxlZ2VuZCAmJiB0eXBlb2Ygci5sZWdlbmQucmV2ZXJzZU9yZGVyICE9ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHIubGVnZW5kLnJldmVyc2VPcmRlciA9IHIubGVnZW5kLnJldmVyc2VPcmRlciAhPSAnbm9ybWFsJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyLmxlZ2VuZCAmJiB0eXBlb2Ygci5sZWdlbmQudHJhY2VvcmRlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICByLmxlZ2VuZC50cmFjZW9yZGVyID0gci5sZWdlbmQudHJhY2VvcmRlciA/ICdyZXZlcnNlZCcgOiAnbm9ybWFsJztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5sZWdlbmQucmV2ZXJzZU9yZGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHIubWFyZ2luICYmIHR5cGVvZiByLm1hcmdpbi50ICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IFsgJ3QnLCAncicsICdiJywgJ2wnLCAncGFkJyBdO1xuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBbICd0b3AnLCAncmlnaHQnLCAnYm90dG9tJywgJ2xlZnQnLCAncGFkJyBdO1xuICAgICAgICAgICAgICAgIHZhciBtYXJnaW4gPSB7fTtcbiAgICAgICAgICAgICAgICBkMy5lbnRyaWVzKHIubWFyZ2luKS5mb3JFYWNoKGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICBtYXJnaW5bdGFyZ2V0W3NvdXJjZS5pbmRleE9mKGRCLmtleSldXSA9IGRCLnZhbHVlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHIubWFyZ2luID0gbWFyZ2luO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5uZWVkc0VuZFNwYWNpbmc7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIubWlub3JUaWNrQ29sb3I7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIubWlub3JUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5hbmd1bGFyYXhpcy50aWNrc0NvdW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLmFuZ3VsYXJheGlzLnRpY2tzQ291bnQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIuYW5ndWxhcmF4aXMudGlja3NTdGVwO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLmFuZ3VsYXJheGlzLnJld3JpdGVUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5hbmd1bGFyYXhpcy5udGlja3M7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIucmFkaWFsYXhpcy50aWNrc0NvdW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLnJhZGlhbGF4aXMudGlja3NDb3VudDtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLnRpY2tzU3RlcDtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLnJld3JpdGVUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLm50aWNrcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG91dHB1dENvbmZpZy5sYXlvdXQgPSByO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXRwdXRDb25maWc7XG4gICAgfTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuZXctY2FwICovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWInKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxudmFyIG1pY3JvcG9sYXIgPSByZXF1aXJlKCcuL21pY3JvcG9sYXInKTtcbnZhciBVbmRvTWFuYWdlciA9IHJlcXVpcmUoJy4vdW5kb19tYW5hZ2VyJyk7XG52YXIgZXh0ZW5kRGVlcEFsbCA9IExpYi5leHRlbmREZWVwQWxsO1xuXG52YXIgbWFuYWdlciA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbm1hbmFnZXIuZnJhbWV3b3JrID0gZnVuY3Rpb24oX2dkKSB7XG4gICAgdmFyIGNvbmZpZywgcHJldmlvdXNDb25maWdDbG9uZSwgcGxvdCwgY29udmVydGVkSW5wdXQsIGNvbnRhaW5lcjtcbiAgICB2YXIgdW5kb01hbmFnZXIgPSBuZXcgVW5kb01hbmFnZXIoKTtcblxuICAgIGZ1bmN0aW9uIGV4cG9ydHMoX2lucHV0Q29uZmlnLCBfY29udGFpbmVyKSB7XG4gICAgICAgIGlmKF9jb250YWluZXIpIGNvbnRhaW5lciA9IF9jb250YWluZXI7XG4gICAgICAgIGQzLnNlbGVjdChkMy5zZWxlY3QoY29udGFpbmVyKS5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0QWxsKCcuc3ZnLWNvbnRhaW5lcj4qOm5vdCguY2hhcnQtcm9vdCknKS5yZW1vdmUoKTtcblxuICAgICAgICBjb25maWcgPSAoIWNvbmZpZykgP1xuICAgICAgICAgICAgX2lucHV0Q29uZmlnIDpcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLCBfaW5wdXRDb25maWcpO1xuXG4gICAgICAgIGlmKCFwbG90KSBwbG90ID0gbWljcm9wb2xhci5BeGlzKCk7XG4gICAgICAgIGNvbnZlcnRlZElucHV0ID0gbWljcm9wb2xhci5hZGFwdGVyLnBsb3RseSgpLmNvbnZlcnQoY29uZmlnKTtcbiAgICAgICAgcGxvdC5jb25maWcoY29udmVydGVkSW5wdXQpLnJlbmRlcihjb250YWluZXIpO1xuICAgICAgICBfZ2QuZGF0YSA9IGNvbmZpZy5kYXRhO1xuICAgICAgICBfZ2QubGF5b3V0ID0gY29uZmlnLmxheW91dDtcbiAgICAgICAgbWFuYWdlci5maWxsTGF5b3V0KF9nZCk7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuICAgIGV4cG9ydHMuaXNQb2xhciA9IHRydWU7XG4gICAgZXhwb3J0cy5zdmcgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHBsb3Quc3ZnKCk7IH07XG4gICAgZXhwb3J0cy5nZXRDb25maWcgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGNvbmZpZzsgfTtcbiAgICBleHBvcnRzLmdldExpdmVDb25maWcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG1pY3JvcG9sYXIuYWRhcHRlci5wbG90bHkoKS5jb252ZXJ0KHBsb3QuZ2V0TGl2ZUNvbmZpZygpLCB0cnVlKTtcbiAgICB9O1xuICAgIGV4cG9ydHMuZ2V0TGl2ZVNjYWxlcyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4ge3Q6IHBsb3QuYW5ndWxhclNjYWxlKCksIHI6IHBsb3QucmFkaWFsU2NhbGUoKX07IH07XG4gICAgZXhwb3J0cy5zZXRVbmRvUG9pbnQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICB2YXIgY29uZmlnQ2xvbmUgPSBtaWNyb3BvbGFyLnV0aWwuY2xvbmVKc29uKGNvbmZpZyk7XG4gICAgICAgIChmdW5jdGlvbihfY29uZmlnQ2xvbmUsIF9wcmV2aW91c0NvbmZpZ0Nsb25lKSB7XG4gICAgICAgICAgICB1bmRvTWFuYWdlci5hZGQoe1xuICAgICAgICAgICAgICAgIHVuZG86IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZihfcHJldmlvdXNDb25maWdDbG9uZSkgdGhhdChfcHJldmlvdXNDb25maWdDbG9uZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWRvOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhhdChfY29uZmlnQ2xvbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KShjb25maWdDbG9uZSwgcHJldmlvdXNDb25maWdDbG9uZSk7XG4gICAgICAgIHByZXZpb3VzQ29uZmlnQ2xvbmUgPSBtaWNyb3BvbGFyLnV0aWwuY2xvbmVKc29uKGNvbmZpZ0Nsb25lKTtcbiAgICB9O1xuICAgIGV4cG9ydHMudW5kbyA9IGZ1bmN0aW9uKCkgeyB1bmRvTWFuYWdlci51bmRvKCk7IH07XG4gICAgZXhwb3J0cy5yZWRvID0gZnVuY3Rpb24oKSB7IHVuZG9NYW5hZ2VyLnJlZG8oKTsgfTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbm1hbmFnZXIuZmlsbExheW91dCA9IGZ1bmN0aW9uKF9nZCkge1xuICAgIHZhciBjb250YWluZXIgPSBkMy5zZWxlY3QoX2dkKS5zZWxlY3RBbGwoJy5wbG90LWNvbnRhaW5lcicpLFxuICAgICAgICBwYXBlckRpdiA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJy5zdmctY29udGFpbmVyJyksXG4gICAgICAgIHBhcGVyID0gX2dkLmZyYW1ld29yayAmJiBfZ2QuZnJhbWV3b3JrLnN2ZyAmJiBfZ2QuZnJhbWV3b3JrLnN2ZygpLFxuICAgICAgICBkZmx0cyA9IHtcbiAgICAgICAgICAgIHdpZHRoOiA4MDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDYwMCxcbiAgICAgICAgICAgIHBhcGVyX2JnY29sb3I6IENvbG9yLmJhY2tncm91bmQsXG4gICAgICAgICAgICBfY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICAgICAgICBfcGFwZXJkaXY6IHBhcGVyRGl2LFxuICAgICAgICAgICAgX3BhcGVyOiBwYXBlclxuICAgICAgICB9O1xuXG4gICAgX2dkLl9mdWxsTGF5b3V0ID0gZXh0ZW5kRGVlcEFsbChkZmx0cywgX2dkLmxheW91dCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBNb2RpZmllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9BcnRodXJDbGVtZW5zL0phdmFzY3JpcHQtVW5kby1NYW5hZ2VyXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBBcnRodXIgQ2xlbWVucywgYXJ0aHVyQHZpc2libGVhcmVhLmNvbVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBVbmRvTWFuYWdlcigpIHtcbiAgICB2YXIgdW5kb0NvbW1hbmRzID0gW10sXG4gICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgIGlzRXhlY3V0aW5nID0gZmFsc2UsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgZnVuY3Rpb24gZXhlY3V0ZShjb21tYW5kLCBhY3Rpb24pIHtcbiAgICAgICAgaWYoIWNvbW1hbmQpIHJldHVybiB0aGlzO1xuXG4gICAgICAgIGlzRXhlY3V0aW5nID0gdHJ1ZTtcbiAgICAgICAgY29tbWFuZFthY3Rpb25dKCk7XG4gICAgICAgIGlzRXhlY3V0aW5nID0gZmFsc2U7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWRkOiBmdW5jdGlvbihjb21tYW5kKSB7XG4gICAgICAgICAgICBpZihpc0V4ZWN1dGluZykgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB1bmRvQ29tbWFuZHMuc3BsaWNlKGluZGV4ICsgMSwgdW5kb0NvbW1hbmRzLmxlbmd0aCAtIGluZGV4KTtcbiAgICAgICAgICAgIHVuZG9Db21tYW5kcy5wdXNoKGNvbW1hbmQpO1xuICAgICAgICAgICAgaW5kZXggPSB1bmRvQ29tbWFuZHMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuICAgICAgICBzZXRDYWxsYmFjazogZnVuY3Rpb24oY2FsbGJhY2tGdW5jKSB7IGNhbGxiYWNrID0gY2FsbGJhY2tGdW5jOyB9LFxuICAgICAgICB1bmRvOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjb21tYW5kID0gdW5kb0NvbW1hbmRzW2luZGV4XTtcbiAgICAgICAgICAgIGlmKCFjb21tYW5kKSByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIGV4ZWN1dGUoY29tbWFuZCwgJ3VuZG8nKTtcbiAgICAgICAgICAgIGluZGV4IC09IDE7XG4gICAgICAgICAgICBpZihjYWxsYmFjaykgY2FsbGJhY2soY29tbWFuZC51bmRvKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuICAgICAgICByZWRvOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjb21tYW5kID0gdW5kb0NvbW1hbmRzW2luZGV4ICsgMV07XG4gICAgICAgICAgICBpZighY29tbWFuZCkgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICBleGVjdXRlKGNvbW1hbmQsICdyZWRvJyk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgaWYoY2FsbGJhY2spIGNhbGxiYWNrKGNvbW1hbmQucmVkbyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcbiAgICAgICAgY2xlYXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdW5kb0NvbW1hbmRzID0gW107XG4gICAgICAgICAgICBpbmRleCA9IC0xO1xuICAgICAgICB9LFxuICAgICAgICBoYXNVbmRvOiBmdW5jdGlvbigpIHsgcmV0dXJuIGluZGV4ICE9PSAtMTsgfSxcbiAgICAgICAgaGFzUmVkbzogZnVuY3Rpb24oKSB7IHJldHVybiBpbmRleCA8ICh1bmRvQ29tbWFuZHMubGVuZ3RoIC0gMSk7IH0sXG4gICAgICAgIGdldENvbW1hbmRzOiBmdW5jdGlvbigpIHsgcmV0dXJuIHVuZG9Db21tYW5kczsgfSxcbiAgICAgICAgZ2V0UHJldmlvdXNDb21tYW5kOiBmdW5jdGlvbigpIHsgcmV0dXJuIHVuZG9Db21tYW5kc1tpbmRleCAtIDFdOyB9LFxuICAgICAgICBnZXRJbmRleDogZnVuY3Rpb24oKSB7IHJldHVybiBpbmRleDsgfVxuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIHRpbnljb2xvciA9IHJlcXVpcmUoJ3Rpbnljb2xvcjInKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgUGxvdHMgPSByZXF1aXJlKCcuLi9wbG90cycpO1xudmFyIHNldENvbnZlcnRDYXJ0ZXNpYW4gPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vc2V0X2NvbnZlcnQnKTtcbnZhciBzZXRDb252ZXJ0UG9sYXIgPSByZXF1aXJlKCcuL3NldF9jb252ZXJ0Jyk7XG52YXIgZG9BdXRvUmFuZ2UgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vYXV0b3JhbmdlJykuZG9BdXRvUmFuZ2U7XG52YXIgZG9UaWNrc1NpbmdsZSA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9heGVzJykuZG9UaWNrc1NpbmdsZTtcbnZhciBkcmFnQm94ID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL2RyYWdib3gnKTtcbnZhciBkcmFnRWxlbWVudCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnQnKTtcbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBUaXRsZXMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL3RpdGxlcycpO1xudmFyIHByZXBTZWxlY3QgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG52YXIgY2xlYXJTZWxlY3QgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykuY2xlYXJTZWxlY3Q7XG52YXIgc2V0Q3Vyc29yID0gcmVxdWlyZSgnLi4vLi4vbGliL3NldGN1cnNvcicpO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xudmFyIHJlZHJhd1JlZ2xUcmFjZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lcycpLnJlZHJhd1JlZ2xUcmFjZXM7XG5cbnZhciBNSURfU0hJRlQgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuTUlEX1NISUZUO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xuXG52YXIgXyA9IExpYi5fO1xudmFyIG1vZCA9IExpYi5tb2Q7XG52YXIgZGVnMnJhZCA9IExpYi5kZWcycmFkO1xudmFyIHJhZDJkZWcgPSBMaWIucmFkMmRlZztcblxuZnVuY3Rpb24gUG9sYXIoZ2QsIGlkKSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMuZ2QgPSBnZDtcblxuICAgIHRoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA9IG51bGw7XG4gICAgdGhpcy52YW5nbGVzID0gbnVsbDtcbiAgICB0aGlzLnJhZGlhbEF4aXNBbmdsZSA9IG51bGw7XG4gICAgdGhpcy50cmFjZUhhc2ggPSB7fTtcbiAgICB0aGlzLmxheWVycyA9IHt9O1xuICAgIHRoaXMuY2xpcFBhdGhzID0ge307XG4gICAgdGhpcy5jbGlwSWRzID0ge307XG4gICAgdGhpcy52aWV3SW5pdGlhbCA9IHt9O1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2xpcElkQmFzZSA9ICdjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIGlkO1xuXG4gICAgdGhpcy5jbGlwSWRzLmZvclRyYWNlcyA9IGNsaXBJZEJhc2UgKyAnLWZvci10cmFjZXMnO1xuICAgIHRoaXMuY2xpcFBhdGhzLmZvclRyYWNlcyA9IGZ1bGxMYXlvdXQuX2NsaXBzLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuYXR0cignaWQnLCB0aGlzLmNsaXBJZHMuZm9yVHJhY2VzKTtcbiAgICB0aGlzLmNsaXBQYXRocy5mb3JUcmFjZXMuYXBwZW5kKCdwYXRoJyk7XG5cbiAgICB0aGlzLmZyYW1ld29yayA9IGZ1bGxMYXlvdXQuX3BvbGFybGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgaWQpO1xuXG4gICAgLy8gdW5mb3J0dW5hdGVseSwgd2UgaGF2ZSB0byBrZWVwIHRyYWNrIG9mIHNvbWUgYXhpcyB0aWNrIHNldHRpbmdzXG4gICAgLy8gc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIGNhbGwgZG9UaWNrc1NpbmdsZSB3aXRoIGl0cyBzcGVjaWFsIHJlZHJhdyBmbGFnXG4gICAgdGhpcy5yYWRpYWxUaWNrTGF5b3V0ID0gbnVsbDtcbiAgICB0aGlzLmFuZ3VsYXJUaWNrTGF5b3V0ID0gbnVsbDtcbn1cblxudmFyIHByb3RvID0gUG9sYXIucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZVBvbGFyKGdkLCBpZCkge1xuICAgIHJldHVybiBuZXcgUG9sYXIoZ2QsIGlkKTtcbn07XG5cbnByb3RvLnBsb3QgPSBmdW5jdGlvbihwb2xhckNhbGNEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgcG9sYXJMYXlvdXQgPSBmdWxsTGF5b3V0W190aGlzLmlkXTtcblxuICAgIF90aGlzLl9oYXNDbGlwT25BeGlzRmFsc2UgPSBmYWxzZTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcG9sYXJDYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBwb2xhckNhbGNEYXRhW2ldWzBdLnRyYWNlO1xuICAgICAgICBpZih0cmFjZS5jbGlwb25heGlzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgX3RoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF90aGlzLnVwZGF0ZUxheWVycyhmdWxsTGF5b3V0LCBwb2xhckxheW91dCk7XG4gICAgX3RoaXMudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KTtcbiAgICBQbG90cy5nZW5lcmFsVXBkYXRlUGVyVHJhY2VNb2R1bGUoX3RoaXMuZ2QsIF90aGlzLCBwb2xhckNhbGNEYXRhLCBwb2xhckxheW91dCk7XG4gICAgX3RoaXMudXBkYXRlRngoZnVsbExheW91dCwgcG9sYXJMYXlvdXQpO1xufTtcblxucHJvdG8udXBkYXRlTGF5ZXJzID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBsYXllcnMgPSBfdGhpcy5sYXllcnM7XG4gICAgdmFyIHJhZGlhbExheW91dCA9IHBvbGFyTGF5b3V0LnJhZGlhbGF4aXM7XG4gICAgdmFyIGFuZ3VsYXJMYXlvdXQgPSBwb2xhckxheW91dC5hbmd1bGFyYXhpcztcbiAgICB2YXIgbGF5ZXJOYW1lcyA9IGNvbnN0YW50cy5sYXllck5hbWVzO1xuXG4gICAgdmFyIGZyb250UGxvdEluZGV4ID0gbGF5ZXJOYW1lcy5pbmRleE9mKCdmcm9udHBsb3QnKTtcbiAgICB2YXIgbGF5ZXJEYXRhID0gbGF5ZXJOYW1lcy5zbGljZSgwLCBmcm9udFBsb3RJbmRleCk7XG4gICAgdmFyIGlzQW5ndWxhckF4aXNCZWxvd1RyYWNlcyA9IGFuZ3VsYXJMYXlvdXQubGF5ZXIgPT09ICdiZWxvdyB0cmFjZXMnO1xuICAgIHZhciBpc1JhZGlhbEF4aXNCZWxvd1RyYWNlcyA9IHJhZGlhbExheW91dC5sYXllciA9PT0gJ2JlbG93IHRyYWNlcyc7XG5cbiAgICBpZihpc0FuZ3VsYXJBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdhbmd1bGFyLWxpbmUnKTtcbiAgICBpZihpc1JhZGlhbEF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ3JhZGlhbC1saW5lJyk7XG4gICAgaWYoaXNBbmd1bGFyQXhpc0JlbG93VHJhY2VzKSBsYXllckRhdGEucHVzaCgnYW5ndWxhci1heGlzJyk7XG4gICAgaWYoaXNSYWRpYWxBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdyYWRpYWwtYXhpcycpO1xuXG4gICAgbGF5ZXJEYXRhLnB1c2goJ2Zyb250cGxvdCcpO1xuXG4gICAgaWYoIWlzQW5ndWxhckF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ2FuZ3VsYXItbGluZScpO1xuICAgIGlmKCFpc1JhZGlhbEF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ3JhZGlhbC1saW5lJyk7XG4gICAgaWYoIWlzQW5ndWxhckF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ2FuZ3VsYXItYXhpcycpO1xuICAgIGlmKCFpc1JhZGlhbEF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ3JhZGlhbC1heGlzJyk7XG5cbiAgICB2YXIgam9pbiA9IF90aGlzLmZyYW1ld29yay5zZWxlY3RBbGwoJy5wb2xhcnN1YmxheWVyJylcbiAgICAgICAgLmRhdGEobGF5ZXJEYXRhLCBTdHJpbmcpO1xuXG4gICAgam9pbi5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICdwb2xhcnN1YmxheWVyICcgKyBkO30pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBzZWwgPSBsYXllcnNbZF0gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIHN3aXRjaChkKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZnJvbnRwbG90JzpcbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyBhZGQgb3B0aW9uIHRvIHBsYWNlIGluICdiYWNrcGxvdCcgbGF5ZXI/P1xuICAgICAgICAgICAgICAgICAgICBzZWwuYXBwZW5kKCdnJykuY2xhc3NlZCgnYmFybGF5ZXInLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3NjYXR0ZXJsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdiYWNrcGxvdCc6XG4gICAgICAgICAgICAgICAgICAgIHNlbC5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdtYXBsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdwbG90YmcnOlxuICAgICAgICAgICAgICAgICAgICBsYXllcnMuYmcgPSBzZWwuYXBwZW5kKCdwYXRoJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JhZGlhbC1ncmlkJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3gnLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYW5ndWxhci1ncmlkJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnZycpLmNsYXNzZWQoJ2FuZ3VsYXJheGlzJywgMSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JhZGlhbC1saW5lJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnbGluZScpLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYW5ndWxhci1saW5lJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgncGF0aCcpLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgam9pbi5vcmRlcigpO1xufTtcblxuLyogUG9sYXIgc3VicGxvdHMganVnZ2xlIHdpdGggNiAnYXhpcyBvYmplY3RzJyAoISksIHRoZXNlIGFyZTpcbiAqXG4gKiAtIHBvbGFyTGF5b3V0LnJhZGlhbGF4aXMgKGFrYSByYWRpYWxMYXlvdXQgaW4gdGhpcyBmaWxlKTpcbiAqIC0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXMgKGFrYSBhbmd1bGFyTGF5b3V0IGluIHRoaXMgZmlsZSk6XG4gKiAgIHVzZWQgZm9yIGRhdGEgLT4gY2FsY2RhdGEgY29udmVyc2lvbnMgKGFrYSBkMmMpIGR1cmluZyB0aGUgY2FsYyBzdGVwXG4gKlxuICogLSB0aGlzLnJhZGlhbEF4aXNcbiAqICAgZXh0ZW5kcyBwb2xhckxheW91dC5yYWRpYWxheGlzLCBhZGRzIG1vY2tlZCAnZG9tYWluJyBhbmRcbiAqICAgZmV3IG90aGVyIGtleXMgaW4gb3JkZXIgdG8gcmV1c2UgQ2FydGVzaWFuIGRvQXV0b1JhbmdlIGFuZCBkb1RpY2tzU2luZ2xlLFxuICogICB1c2VkIGZvciBjYWxjZGF0YSAtPiBnZW9tZXRyaWMgY29udmVyc2lvbnMgKGFrYSBjMmcpIGR1cmluZyB0aGUgcGxvdCBzdGVwXG4gKiAgICsgc2V0R2VvbWV0cnkgc2V0dXBzIGF4LmMyZyBmb3IgZ2l2ZW4gYXgucmFuZ2VcbiAqICAgKyBzZXRTY2FsZSBzZXR1cHMgYXguX20sYXguX2IgZm9yIGdpdmVuIGF4LnJhbmdlXG4gKlxuICogLSB0aGlzLmFuZ3VsYXJBeGlzXG4gKiAgIGV4dGVuZHMgcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXMsIGFkZHMgbW9ja2VkICdyYW5nZScgYW5kICdkb21haW4nIGFuZFxuICogICBhIGZldyBvdGhlciBrZXlzIGluIG9yZGVyIHRvIHJldXNlIENhcnRlc2lhbiBkb1RpY2tzU2luZ2xlLFxuICogICB1c2VkIGZvciBjYWxjZGF0YSAtPiBnZW9tZXRyaWMgY29udmVyc2lvbnMgKGFrYSBjMmcpIGR1cmluZyB0aGUgcGxvdCBzdGVwXG4gKiAgICsgc2V0R2VvbWV0cnkgc2V0dXBzIGF4LmMyZyBnaXZlbiBheC5yb3RhdGlvbiwgYXguZGlyZWN0aW9uICYgYXguX2NhdGVnb3JpZXMsXG4gKiAgICAgICAgICAgICAgICAgYW5kIG1vY2tzIGF4LnJhbmdlXG4gKiAgICsgc2V0U2NhbGUgc2V0dXBzIGF4Ll9tLGF4Ll9iIHdpdGggdGhhdCBtb2NrZWQgYXgucmFuZ2VcbiAqXG4gKiAtIHRoaXMueGF4aXNcbiAqIC0gdGhpcy55YXhpc1xuICogICBzZXR1cCBzbyB0aGF0IHBvbGFyIHRyYWNlcyBjYW4gcmV1c2UgcGxvdCBtZXRob2RzIG9mIENhcnRlc2lhbiB0cmFjZXNcbiAqICAgd2hpY2ggbW9zdGx5IHJlbHkgb24gMnBpeGVsIG1ldGhvZHMgKGUuZyBheC5jMnApXG4gKi9cbnByb3RvLnVwZGF0ZUxheW91dCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICAvLyBheGlzIGF0dHJpYnV0ZXNcbiAgICB2YXIgcmFkaWFsTGF5b3V0ID0gcG9sYXJMYXlvdXQucmFkaWFsYXhpcztcbiAgICB2YXIgYW5ndWxhckxheW91dCA9IHBvbGFyTGF5b3V0LmFuZ3VsYXJheGlzO1xuICAgIC8vIGxheW91dCBkb21haW5zXG4gICAgdmFyIHhEb21haW4gPSBwb2xhckxheW91dC5kb21haW4ueDtcbiAgICB2YXIgeURvbWFpbiA9IHBvbGFyTGF5b3V0LmRvbWFpbi55O1xuICAgIC8vIG9mZnNldHMgZnJvbSBwYXBlciBlZGdlIHRvIGxheW91dCBkb21haW4gYm94XG4gICAgX3RoaXMueE9mZnNldCA9IGdzLmwgKyBncy53ICogeERvbWFpblswXTtcbiAgICBfdGhpcy55T2Zmc2V0ID0gZ3MudCArIGdzLmggKiAoMSAtIHlEb21haW5bMV0pO1xuICAgIC8vIGxlbmd0aHMgb2YgdGhlIGxheW91dCBkb21haW4gYm94XG4gICAgdmFyIHhMZW5ndGggPSBfdGhpcy54TGVuZ3RoID0gZ3MudyAqICh4RG9tYWluWzFdIC0geERvbWFpblswXSk7XG4gICAgdmFyIHlMZW5ndGggPSBfdGhpcy55TGVuZ3RoID0gZ3MuaCAqICh5RG9tYWluWzFdIC0geURvbWFpblswXSk7XG4gICAgLy8gc2VjdG9yIHRvIHBsb3RcbiAgICB2YXIgc2VjdG9yID0gcG9sYXJMYXlvdXQuc2VjdG9yO1xuICAgIF90aGlzLnNlY3RvckluUmFkID0gc2VjdG9yLm1hcChkZWcycmFkKTtcbiAgICB2YXIgc2VjdG9yQkJveCA9IF90aGlzLnNlY3RvckJCb3ggPSBjb21wdXRlU2VjdG9yQkJveChzZWN0b3IpO1xuICAgIHZhciBkeFNlY3RvckJCb3ggPSBzZWN0b3JCQm94WzJdIC0gc2VjdG9yQkJveFswXTtcbiAgICB2YXIgZHlTZWN0b3JCQm94ID0gc2VjdG9yQkJveFszXSAtIHNlY3RvckJCb3hbMV07XG4gICAgLy8gYXNwZWN0IHJhdGlvc1xuICAgIHZhciBhckRvbWFpbiA9IHlMZW5ndGggLyB4TGVuZ3RoO1xuICAgIHZhciBhclNlY3RvciA9IE1hdGguYWJzKGR5U2VjdG9yQkJveCAvIGR4U2VjdG9yQkJveCk7XG4gICAgLy8gYWN0dWFsIGxlbmd0aHMgYW5kIGRvbWFpbnMgb2Ygc3VicGxvdCBib3hcbiAgICB2YXIgeExlbmd0aDIsIHlMZW5ndGgyO1xuICAgIHZhciB4RG9tYWluMiwgeURvbWFpbjI7XG4gICAgdmFyIGdhcDtcbiAgICBpZihhckRvbWFpbiA+IGFyU2VjdG9yKSB7XG4gICAgICAgIHhMZW5ndGgyID0geExlbmd0aDtcbiAgICAgICAgeUxlbmd0aDIgPSB4TGVuZ3RoICogYXJTZWN0b3I7XG4gICAgICAgIGdhcCA9ICh5TGVuZ3RoIC0geUxlbmd0aDIpIC8gZ3MuaCAvIDI7XG4gICAgICAgIHhEb21haW4yID0gW3hEb21haW5bMF0sIHhEb21haW5bMV1dO1xuICAgICAgICB5RG9tYWluMiA9IFt5RG9tYWluWzBdICsgZ2FwLCB5RG9tYWluWzFdIC0gZ2FwXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB4TGVuZ3RoMiA9IHlMZW5ndGggLyBhclNlY3RvcjtcbiAgICAgICAgeUxlbmd0aDIgPSB5TGVuZ3RoO1xuICAgICAgICBnYXAgPSAoeExlbmd0aCAtIHhMZW5ndGgyKSAvIGdzLncgLyAyO1xuICAgICAgICB4RG9tYWluMiA9IFt4RG9tYWluWzBdICsgZ2FwLCB4RG9tYWluWzFdIC0gZ2FwXTtcbiAgICAgICAgeURvbWFpbjIgPSBbeURvbWFpblswXSwgeURvbWFpblsxXV07XG4gICAgfVxuICAgIF90aGlzLnhMZW5ndGgyID0geExlbmd0aDI7XG4gICAgX3RoaXMueUxlbmd0aDIgPSB5TGVuZ3RoMjtcbiAgICBfdGhpcy54RG9tYWluMiA9IHhEb21haW4yO1xuICAgIF90aGlzLnlEb21haW4yID0geURvbWFpbjI7XG4gICAgLy8gYWN0dWFsIG9mZnNldHMgZnJvbSBwYXBlciBlZGdlIHRvIHRoZSBzdWJwbG90IGJveCB0b3AtbGVmdCBjb3JuZXJcbiAgICB2YXIgeE9mZnNldDIgPSBfdGhpcy54T2Zmc2V0MiA9IGdzLmwgKyBncy53ICogeERvbWFpbjJbMF07XG4gICAgdmFyIHlPZmZzZXQyID0gX3RoaXMueU9mZnNldDIgPSBncy50ICsgZ3MuaCAqICgxIC0geURvbWFpbjJbMV0pO1xuICAgIC8vIGNpcmNsZSByYWRpdXMgaW4gcHhcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzID0geExlbmd0aDIgLyBkeFNlY3RvckJCb3g7XG4gICAgLy8gJ2lubmVyJyByYWRpdXMgaW4gcHggKHdoZW4gcG9sYXIuaG9sZSBpcyBzZXQpXG4gICAgdmFyIGlubmVyUmFkaXVzID0gX3RoaXMuaW5uZXJSYWRpdXMgPSBwb2xhckxheW91dC5ob2xlICogcmFkaXVzO1xuICAgIC8vIGNpcmNsZSBjZW50ZXIgcG9zaXRpb24gaW4gcHhcbiAgICB2YXIgY3ggPSBfdGhpcy5jeCA9IHhPZmZzZXQyIC0gcmFkaXVzICogc2VjdG9yQkJveFswXTtcbiAgICB2YXIgY3kgPSBfdGhpcy5jeSA9IHlPZmZzZXQyICsgcmFkaXVzICogc2VjdG9yQkJveFszXTtcbiAgICAvLyBjaXJjbGUgY2VudGVyIGluIHRoZSBjb29yZGluYXRlIHN5c3RlbSBvZiBwbG90IGFyZWFcbiAgICB2YXIgY3h4ID0gX3RoaXMuY3h4ID0gY3ggLSB4T2Zmc2V0MjtcbiAgICB2YXIgY3l5ID0gX3RoaXMuY3l5ID0gY3kgLSB5T2Zmc2V0MjtcblxuICAgIF90aGlzLnJhZGlhbEF4aXMgPSBfdGhpcy5tb2NrQXhpcyhmdWxsTGF5b3V0LCBwb2xhckxheW91dCwgcmFkaWFsTGF5b3V0LCB7XG4gICAgICAgIF9heGlzbGF5ZXI6IGxheWVyc1sncmFkaWFsLWF4aXMnXSxcbiAgICAgICAgX2dyaWRsYXllcjogbGF5ZXJzWydyYWRpYWwtZ3JpZCddLFxuICAgICAgICAvLyBtYWtlIHRoaXMgYW4gJ3gnIGF4aXMgdG8gbWFrZSBwb3NpdGlvbmluZyAoZXNwZWNpYWxseSByb3RhdGlvbikgZWFzaWVyXG4gICAgICAgIF9pZDogJ3gnLFxuICAgICAgICAvLyBjb252ZXJ0IHRvICd4JyBheGlzIGVxdWl2YWxlbnRcbiAgICAgICAgc2lkZToge1xuICAgICAgICAgICAgY291bnRlcmNsb2Nrd2lzZTogJ3RvcCcsXG4gICAgICAgICAgICBjbG9ja3dpc2U6ICdib3R0b20nXG4gICAgICAgIH1bcmFkaWFsTGF5b3V0LnNpZGVdLFxuICAgICAgICAvLyBzcGFucyBsZW5ndGggMSByYWRpdXNcbiAgICAgICAgZG9tYWluOiBbaW5uZXJSYWRpdXMgLyBncy53LCByYWRpdXMgLyBncy53XVxuICAgIH0pO1xuXG4gICAgX3RoaXMuYW5ndWxhckF4aXMgPSBfdGhpcy5tb2NrQXhpcyhmdWxsTGF5b3V0LCBwb2xhckxheW91dCwgYW5ndWxhckxheW91dCwge1xuICAgICAgICBfYXhpc2xheWVyOiBsYXllcnNbJ2FuZ3VsYXItYXhpcyddLFxuICAgICAgICBfZ3JpZGxheWVyOiBsYXllcnNbJ2FuZ3VsYXItZ3JpZCddLFxuICAgICAgICBzaWRlOiAncmlnaHQnLFxuICAgICAgICAvLyB0byBnZXQgYXV0byBudGlja3MgcmlnaHRcbiAgICAgICAgZG9tYWluOiBbMCwgTWF0aC5QSV0sXG4gICAgICAgIC8vIGRvbid0IHBhc3MgdGhyb3VnaCBhdXRvcmFuZ2UgbG9naWNcbiAgICAgICAgYXV0b3JhbmdlOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgX3RoaXMuZG9BdXRvUmFuZ2UoZnVsbExheW91dCwgcG9sYXJMYXlvdXQpO1xuICAgIC8vIE4uQi4gdGhpcyBzZXRzIF90aGlzLnZhbmdsZXNcbiAgICBfdGhpcy51cGRhdGVBbmd1bGFyQXhpcyhmdWxsTGF5b3V0LCBwb2xhckxheW91dCk7XG4gICAgLy8gTi5CLiB0aGlzIHNldHMgX3RoaXMucmFkaWFsQXhpc0FuZ2xlXG4gICAgX3RoaXMudXBkYXRlUmFkaWFsQXhpcyhmdWxsTGF5b3V0LCBwb2xhckxheW91dCk7XG4gICAgX3RoaXMudXBkYXRlUmFkaWFsQXhpc1RpdGxlKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KTtcblxuICAgIF90aGlzLnhheGlzID0gX3RoaXMubW9ja0NhcnRlc2lhbkF4aXMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIHtcbiAgICAgICAgX2lkOiAneCcsXG4gICAgICAgIGRvbWFpbjogeERvbWFpbjJcbiAgICB9KTtcblxuICAgIF90aGlzLnlheGlzID0gX3RoaXMubW9ja0NhcnRlc2lhbkF4aXMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIHtcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIGRvbWFpbjogeURvbWFpbjJcbiAgICB9KTtcblxuICAgIHZhciBkUGF0aCA9IF90aGlzLnBhdGhTdWJwbG90KCk7XG5cbiAgICBfdGhpcy5jbGlwUGF0aHMuZm9yVHJhY2VzLnNlbGVjdCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdkJywgZFBhdGgpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBzdHJUcmFuc2xhdGUoY3h4LCBjeXkpKTtcblxuICAgIGxheWVycy5mcm9udHBsb3RcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zbGF0ZSh4T2Zmc2V0MiwgeU9mZnNldDIpKVxuICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIF90aGlzLl9oYXNDbGlwT25BeGlzRmFsc2UgPyBudWxsIDogX3RoaXMuY2xpcElkcy5mb3JUcmFjZXMpO1xuXG4gICAgbGF5ZXJzLmJnXG4gICAgICAgIC5hdHRyKCdkJywgZFBhdGgpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBzdHJUcmFuc2xhdGUoY3gsIGN5KSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgcG9sYXJMYXlvdXQuYmdjb2xvcik7XG5cbiAgICAvLyByZW1vdmUgY3Jpc3BFZGdlcyAtIGFsbCB0aGUgb2ZmLXNxdWFyZSBhbmdsZXMgaW4gcG9sYXIgcGxvdHNcbiAgICAvLyBtYWtlIHRoZXNlIGNvdW50ZXJwcm9kdWN0aXZlLlxuICAgIF90aGlzLmZyYW1ld29yay5zZWxlY3RBbGwoJy5jcmlzcCcpLmNsYXNzZWQoJ2NyaXNwJywgMCk7XG59O1xuXG5wcm90by5tb2NrQXhpcyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCBheExheW91dCwgb3B0cykge1xuICAgIHZhciBjb21tb25PcHRzID0ge1xuICAgICAgICAvLyB0byBnZXQgX2JvdW5kaW5nQm94IGNvbXB1dGF0aW9uIHJpZ2h0IHdoZW4gc2hvd3RpY2tsYWJlbHMgaXMgZmFsc2VcbiAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgIHBvc2l0aW9uOiAwLFxuICAgICAgICBfcG9zOiAwLFxuICAgICAgICAvLyBkdW1teSB0cnV0aHkgdmFsdWUgdG8gbWFrZSBkb1RpY2tzU2luZ2xlIGRyYXcgdGhlIGdyaWRcbiAgICAgICAgX2NvdW50ZXJheGlzOiB0cnVlLFxuICAgICAgICAvLyBkb24ndCB1c2UgYXV0b21hcmdpbnMgcm91dGluZSBmb3IgbGFiZWxzXG4gICAgICAgIGF1dG9tYXJnaW46IGZhbHNlXG4gICAgfTtcblxuICAgIHZhciBheCA9IExpYi5leHRlbmRGbGF0KGNvbW1vbk9wdHMsIGF4TGF5b3V0LCBvcHRzKTtcbiAgICBzZXRDb252ZXJ0UG9sYXIoYXgsIHBvbGFyTGF5b3V0LCBmdWxsTGF5b3V0KTtcbiAgICByZXR1cm4gYXg7XG59O1xuXG5wcm90by5tb2NrQ2FydGVzaWFuQXhpcyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCBvcHRzKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgYXhJZCA9IG9wdHMuX2lkO1xuXG4gICAgdmFyIGF4ID0gTGliLmV4dGVuZEZsYXQoe3R5cGU6ICdsaW5lYXInfSwgb3B0cyk7XG4gICAgc2V0Q29udmVydENhcnRlc2lhbihheCwgZnVsbExheW91dCk7XG5cbiAgICB2YXIgYmJveEluZGljZXMgPSB7XG4gICAgICAgIHg6IFswLCAyXSxcbiAgICAgICAgeTogWzEsIDNdXG4gICAgfTtcblxuICAgIGF4LnNldFJhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBzZWN0b3JCQm94ID0gX3RoaXMuc2VjdG9yQkJveDtcbiAgICAgICAgdmFyIGluZCA9IGJib3hJbmRpY2VzW2F4SWRdO1xuICAgICAgICB2YXIgcmwgPSBfdGhpcy5yYWRpYWxBeGlzLl9ybDtcbiAgICAgICAgdmFyIGRybCA9IChybFsxXSAtIHJsWzBdKSAvICgxIC0gcG9sYXJMYXlvdXQuaG9sZSk7XG4gICAgICAgIGF4LnJhbmdlID0gW3NlY3RvckJCb3hbaW5kWzBdXSAqIGRybCwgc2VjdG9yQkJveFtpbmRbMV1dICogZHJsXTtcbiAgICB9O1xuXG4gICAgYXguaXNQdFdpdGhpblJhbmdlID0gYXhJZCA9PT0gJ3gnID9cbiAgICAgICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gX3RoaXMuaXNQdEluc2lkZShkKTsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfTtcblxuICAgIGF4LnNldFJhbmdlKCk7XG4gICAgYXguc2V0U2NhbGUoKTtcbiAgICByZXR1cm4gYXg7XG59O1xuXG5wcm90by5kb0F1dG9SYW5nZSA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIGdkID0gdGhpcy5nZDtcbiAgICB2YXIgcmFkaWFsQXhpcyA9IHRoaXMucmFkaWFsQXhpcztcbiAgICB2YXIgcmFkaWFsTGF5b3V0ID0gcG9sYXJMYXlvdXQucmFkaWFsYXhpcztcblxuICAgIHJhZGlhbEF4aXMuc2V0U2NhbGUoKTtcbiAgICBkb0F1dG9SYW5nZShnZCwgcmFkaWFsQXhpcyk7XG5cbiAgICB2YXIgcm5nID0gcmFkaWFsQXhpcy5yYW5nZTtcbiAgICByYWRpYWxMYXlvdXQucmFuZ2UgPSBybmcuc2xpY2UoKTtcbiAgICByYWRpYWxMYXlvdXQuX2lucHV0LnJhbmdlID0gcm5nLnNsaWNlKCk7XG5cbiAgICByYWRpYWxBeGlzLl9ybCA9IFtcbiAgICAgICAgcmFkaWFsQXhpcy5yMmwocm5nWzBdLCBudWxsLCAnZ3JlZ29yaWFuJyksXG4gICAgICAgIHJhZGlhbEF4aXMucjJsKHJuZ1sxXSwgbnVsbCwgJ2dyZWdvcmlhbicpXG4gICAgXTtcbn07XG5cbnByb3RvLnVwZGF0ZVJhZGlhbEF4aXMgPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBwb2xhckxheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ2Q7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBpbm5lclJhZGl1cyA9IF90aGlzLmlubmVyUmFkaXVzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciByYWRpYWxMYXlvdXQgPSBwb2xhckxheW91dC5yYWRpYWxheGlzO1xuICAgIHZhciBhMCA9IG1vZChwb2xhckxheW91dC5zZWN0b3JbMF0sIDM2MCk7XG4gICAgdmFyIGF4ID0gX3RoaXMucmFkaWFsQXhpcztcbiAgICB2YXIgaGFzUm9vbUZvckl0ID0gaW5uZXJSYWRpdXMgPCByYWRpdXM7XG5cbiAgICBfdGhpcy5maWxsVmlld0luaXRpYWxLZXkoJ3JhZGlhbGF4aXMuYW5nbGUnLCByYWRpYWxMYXlvdXQuYW5nbGUpO1xuICAgIF90aGlzLmZpbGxWaWV3SW5pdGlhbEtleSgncmFkaWFsYXhpcy5yYW5nZScsIGF4LnJhbmdlLnNsaWNlKCkpO1xuXG4gICAgYXguc2V0R2VvbWV0cnkoKTtcblxuICAgIC8vIHJvdGF0ZSBhdXRvIHRpY2sgbGFiZWxzIGJ5IDE4MCBpZiBpbiBxdWFkcmFudCBJSSBhbmQgSUlJIHRvIG1ha2UgdGhlbVxuICAgIC8vIHJlYWRhYmxlIGZyb20gbGVmdC10by1yaWdodFxuICAgIC8vXG4gICAgLy8gVE9ETyB0cnkgbW92aW5nIGRlZXBlciBpbiBkb1RpY2tzU2luZ2xlIGZvciBiZXR0ZXIgcmVzdWx0cz9cbiAgICBpZihheC50aWNrYW5nbGUgPT09ICdhdXRvJyAmJiAoYTAgPiA5MCAmJiBhMCA8PSAyNzApKSB7XG4gICAgICAgIGF4LnRpY2thbmdsZSA9IDE4MDtcbiAgICB9XG5cbiAgICAvLyBlYXNpZXIgdG8gc2V0IHJvdGF0ZSBhbmdsZSB3aXRoIGN1c3RvbSB0cmFuc2xhdGUgZnVuY3Rpb25cbiAgICBheC5fdHJhbnNmbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIChheC5sMnAoZC54KSArIGlubmVyUmFkaXVzKSArICcsMCknO1xuICAgIH07XG5cbiAgICAvLyBzZXQgc3BlY2lhbCBncmlkIHBhdGggZnVuY3Rpb25cbiAgICBheC5fZ3JpZHBhdGggPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5wYXRoQXJjKGF4LnIycChkLngpICsgaW5uZXJSYWRpdXMpO1xuICAgIH07XG5cbiAgICB2YXIgbmV3VGlja0xheW91dCA9IHN0clRpY2tMYXlvdXQocmFkaWFsTGF5b3V0KTtcbiAgICBpZihfdGhpcy5yYWRpYWxUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVyc1sncmFkaWFsLWF4aXMnXS5zZWxlY3RBbGwoJy54dGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpcy5yYWRpYWxUaWNrTGF5b3V0ID0gbmV3VGlja0xheW91dDtcbiAgICB9XG5cbiAgICBpZihoYXNSb29tRm9ySXQpIHtcbiAgICAgICAgYXguc2V0U2NhbGUoKTtcbiAgICAgICAgZG9UaWNrc1NpbmdsZShnZCwgYXgsIHRydWUpO1xuICAgIH1cblxuICAgIC8vIHN0YXNoICdhY3R1YWwnIHJhZGlhbCBheGlzIGFuZ2xlIGZvciBkcmFnIGhhbmRsZXJzIChpbiBkZWdyZWVzKVxuICAgIHZhciBhbmdsZSA9IF90aGlzLnJhZGlhbEF4aXNBbmdsZSA9IF90aGlzLnZhbmdsZXMgP1xuICAgICAgICByYWQyZGVnKHNuYXBUb1ZlcnRleEFuZ2xlKGRlZzJyYWQocmFkaWFsTGF5b3V0LmFuZ2xlKSwgX3RoaXMudmFuZ2xlcykpIDpcbiAgICAgICAgcmFkaWFsTGF5b3V0LmFuZ2xlO1xuXG4gICAgdmFyIHRyYW5zID0gc3RyVHJhbnNsYXRlKGN4LCBjeSkgKyBzdHJSb3RhdGUoLWFuZ2xlKTtcblxuICAgIHVwZGF0ZUVsZW1lbnQoXG4gICAgICAgIGxheWVyc1sncmFkaWFsLWF4aXMnXSxcbiAgICAgICAgaGFzUm9vbUZvckl0ICYmIChyYWRpYWxMYXlvdXQuc2hvd3RpY2tsYWJlbHMgfHwgcmFkaWFsTGF5b3V0LnRpY2tzKSxcbiAgICAgICAge3RyYW5zZm9ybTogdHJhbnN9XG4gICAgKTtcblxuICAgIC8vIG1vdmUgYWxsIGdyaWQgcGF0aHMgdG8gYWJvdXQgY2lyY2xlIGNlbnRlcixcbiAgICAvLyB1bmRvIGluZGl2aWR1YWwgZ3JpZCBsaW5lcyB0cmFuc2xhdGlvbnNcbiAgICB1cGRhdGVFbGVtZW50KFxuICAgICAgICBsYXllcnNbJ3JhZGlhbC1ncmlkJ10sXG4gICAgICAgIGhhc1Jvb21Gb3JJdCAmJiByYWRpYWxMYXlvdXQuc2hvd2dyaWQsXG4gICAgICAgIHt0cmFuc2Zvcm06IHN0clRyYW5zbGF0ZShjeCwgY3kpfVxuICAgICkuc2VsZWN0QWxsKCdwYXRoJykuYXR0cigndHJhbnNmb3JtJywgbnVsbCk7XG5cbiAgICB1cGRhdGVFbGVtZW50KFxuICAgICAgICBsYXllcnNbJ3JhZGlhbC1saW5lJ10uc2VsZWN0KCdsaW5lJyksXG4gICAgICAgIGhhc1Jvb21Gb3JJdCAmJiByYWRpYWxMYXlvdXQuc2hvd2xpbmUsXG4gICAgICAgIHtcbiAgICAgICAgICAgIHgxOiBpbm5lclJhZGl1cyxcbiAgICAgICAgICAgIHkxOiAwLFxuICAgICAgICAgICAgeDI6IHJhZGl1cyxcbiAgICAgICAgICAgIHkyOiAwLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc1xuICAgICAgICB9XG4gICAgKVxuICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCByYWRpYWxMYXlvdXQubGluZXdpZHRoKVxuICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgcmFkaWFsTGF5b3V0LmxpbmVjb2xvcik7XG59O1xuXG5wcm90by51cGRhdGVSYWRpYWxBeGlzVGl0bGUgPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBwb2xhckxheW91dCwgX2FuZ2xlKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5nZDtcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciByYWRpYWxMYXlvdXQgPSBwb2xhckxheW91dC5yYWRpYWxheGlzO1xuICAgIHZhciB0aXRsZUNsYXNzID0gX3RoaXMuaWQgKyAndGl0bGUnO1xuXG4gICAgdmFyIGFuZ2xlID0gX2FuZ2xlICE9PSB1bmRlZmluZWQgPyBfYW5nbGUgOiBfdGhpcy5yYWRpYWxBeGlzQW5nbGU7XG4gICAgdmFyIGFuZ2xlUmFkID0gZGVnMnJhZChhbmdsZSk7XG4gICAgdmFyIGNvc2EgPSBNYXRoLmNvcyhhbmdsZVJhZCk7XG4gICAgdmFyIHNpbmEgPSBNYXRoLnNpbihhbmdsZVJhZCk7XG5cbiAgICB2YXIgcGFkID0gMDtcbiAgICBpZihyYWRpYWxMYXlvdXQudGl0bGUpIHtcbiAgICAgICAgdmFyIGggPSBEcmF3aW5nLmJCb3goX3RoaXMubGF5ZXJzWydyYWRpYWwtYXhpcyddLm5vZGUoKSkuaGVpZ2h0O1xuICAgICAgICB2YXIgdHMgPSByYWRpYWxMYXlvdXQudGl0bGVmb250LnNpemU7XG4gICAgICAgIHBhZCA9IHJhZGlhbExheW91dC5zaWRlID09PSAnY291bnRlcmNsb2Nrd2lzZScgP1xuICAgICAgICAgICAgLWggLSB0cyAqIDAuNCA6XG4gICAgICAgICAgICBoICsgdHMgKiAwLjg7XG4gICAgfVxuXG4gICAgX3RoaXMubGF5ZXJzWydyYWRpYWwtYXhpcy10aXRsZSddID0gVGl0bGVzLmRyYXcoZ2QsIHRpdGxlQ2xhc3MsIHtcbiAgICAgICAgcHJvcENvbnRhaW5lcjogcmFkaWFsTGF5b3V0LFxuICAgICAgICBwcm9wTmFtZTogX3RoaXMuaWQgKyAnLnJhZGlhbGF4aXMudGl0bGUnLFxuICAgICAgICBwbGFjZWhvbGRlcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIHJhZGlhbCBheGlzIHRpdGxlJyksXG4gICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgIHg6IGN4ICsgKHJhZGl1cyAvIDIpICogY29zYSArIHBhZCAqIHNpbmEsXG4gICAgICAgICAgICB5OiBjeSAtIChyYWRpdXMgLyAyKSAqIHNpbmEgKyBwYWQgKiBjb3NhLFxuICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmb3JtOiB7cm90YXRlOiAtYW5nbGV9XG4gICAgfSk7XG59O1xuXG5wcm90by51cGRhdGVBbmd1bGFyQXhpcyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5nZDtcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXM7XG4gICAgdmFyIGlubmVyUmFkaXVzID0gX3RoaXMuaW5uZXJSYWRpdXM7XG4gICAgdmFyIGN4ID0gX3RoaXMuY3g7XG4gICAgdmFyIGN5ID0gX3RoaXMuY3k7XG4gICAgdmFyIGFuZ3VsYXJMYXlvdXQgPSBwb2xhckxheW91dC5hbmd1bGFyYXhpcztcbiAgICB2YXIgYXggPSBfdGhpcy5hbmd1bGFyQXhpcztcblxuICAgIF90aGlzLmZpbGxWaWV3SW5pdGlhbEtleSgnYW5ndWxhcmF4aXMucm90YXRpb24nLCBhbmd1bGFyTGF5b3V0LnJvdGF0aW9uKTtcblxuICAgIGF4LnNldEdlb21ldHJ5KCk7XG5cbiAgICAvLyAndCdpY2sgdG8gJ2cnZW9tZXRyaWMgcmFkaWFucyBpcyB1c2VkIGFsbCBvdmVyIHRoZSBwbGFjZSBoZXJlXG4gICAgdmFyIHQyZyA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGF4LnQyZyhkLngpOyB9O1xuXG4gICAgLy8gcnVuIHJhZDJkZWcgb24gdGljazAgYW5kIGRpdGNrIGZvciB0aGV0YXVuaXQ6ICdyYWRpYW5zJyBheGVzXG4gICAgaWYoYXgudHlwZSA9PT0gJ2xpbmVhcicgJiYgYXgudGhldGF1bml0ID09PSAncmFkaWFucycpIHtcbiAgICAgICAgYXgudGljazAgPSByYWQyZGVnKGF4LnRpY2swKTtcbiAgICAgICAgYXguZHRpY2sgPSByYWQyZGVnKGF4LmR0aWNrKTtcbiAgICB9XG5cbiAgICAvLyBVc2UgdGlja3ZhbCBmaWx0ZXIgZm9yIGNhdGVnb3J5IGF4ZXMgaW5zdGVhZCBvZiB0d2Vha2luZ1xuICAgIC8vIHRoZSByYW5nZSB3LnIudCBzZWN0b3IsIHNvIHRoYXQgc2VjdG9ycyB0aGF0IGNyb3NzIDM2MCBjYW5cbiAgICAvLyBzaG93IGFsbCB0aGVpciB0aWNrcy5cbiAgICBpZihheC50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIGF4Ll90aWNrRmlsdGVyID0gZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIExpYi5pc0FuZ2xlSW5zaWRlU2VjdG9yKHQyZyhkKSwgX3RoaXMuc2VjdG9ySW5SYWQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGF4Ll90cmFuc2ZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgaGFzRWxlbWVudCA9IHNlbCAmJiBzZWwubm9kZSgpO1xuXG4gICAgICAgIC8vIGRvbid0IHRyYW5zbGF0ZSBncmlkIGxpbmVzXG4gICAgICAgIGlmKGhhc0VsZW1lbnQgJiYgc2VsLmNsYXNzZWQoJ2FuZ3VsYXJheGlzZ3JpZCcpKSByZXR1cm4gJyc7XG5cbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgdmFyIG91dCA9IHN0clRyYW5zbGF0ZShjeCArIHJhZGl1cyAqIE1hdGguY29zKHJhZCksIGN5IC0gcmFkaXVzICogTWF0aC5zaW4ocmFkKSk7XG5cbiAgICAgICAgLy8gbXVzdCBhbHNvIHJvdGF0ZSB0aWNrcywgYnV0IGRvbid0IHJvdGF0ZSBsYWJlbHNcbiAgICAgICAgaWYoaGFzRWxlbWVudCAmJiBzZWwuY2xhc3NlZCgndGlja3MnKSkge1xuICAgICAgICAgICAgb3V0ICs9IHN0clJvdGF0ZSgtcmFkMmRlZyhyYWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcblxuICAgIGF4Ll9ncmlkcGF0aCA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgdmFyIGNvc1JhZCA9IE1hdGguY29zKHJhZCk7XG4gICAgICAgIHZhciBzaW5SYWQgPSBNYXRoLnNpbihyYWQpO1xuICAgICAgICByZXR1cm4gJ00nICsgW2N4ICsgaW5uZXJSYWRpdXMgKiBjb3NSYWQsIGN5IC0gaW5uZXJSYWRpdXMgKiBzaW5SYWRdICtcbiAgICAgICAgICAgICdMJyArIFtjeCArIHJhZGl1cyAqIGNvc1JhZCwgY3kgLSByYWRpdXMgKiBzaW5SYWRdO1xuICAgIH07XG5cbiAgICB2YXIgb2Zmc2V0NGZvbnRzaXplID0gKGFuZ3VsYXJMYXlvdXQudGlja3MgIT09ICdvdXRzaWRlJyA/IDAuNyA6IDAuNSk7XG5cbiAgICBheC5fbGFiZWx4ID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICB2YXIgbGFiZWxTdGFuZG9mZiA9IGF4Ll9sYWJlbFN0YW5kb2ZmO1xuICAgICAgICB2YXIgcGFkID0gYXguX3BhZDtcblxuICAgICAgICB2YXIgb2Zmc2V0NHR4ID0gc2lnblNpbihyYWQpID09PSAwID9cbiAgICAgICAgICAgIDAgOlxuICAgICAgICAgICAgTWF0aC5jb3MocmFkKSAqIChsYWJlbFN0YW5kb2ZmICsgcGFkICsgb2Zmc2V0NGZvbnRzaXplICogZC5mb250U2l6ZSk7XG4gICAgICAgIHZhciBvZmZzZXQ0dGljayA9IHNpZ25Db3MocmFkKSAqIChkLmR4ICsgbGFiZWxTdGFuZG9mZiArIHBhZCk7XG5cbiAgICAgICAgcmV0dXJuIG9mZnNldDR0eCArIG9mZnNldDR0aWNrO1xuICAgIH07XG5cbiAgICBheC5fbGFiZWx5ID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICB2YXIgbGFiZWxTdGFuZG9mZiA9IGF4Ll9sYWJlbFN0YW5kb2ZmO1xuICAgICAgICB2YXIgbGFiZWxTaGlmdCA9IGF4Ll9sYWJlbFNoaWZ0O1xuICAgICAgICB2YXIgcGFkID0gYXguX3BhZDtcblxuICAgICAgICB2YXIgb2Zmc2V0NHR4ID0gZC5keSArIGQuZm9udFNpemUgKiBNSURfU0hJRlQgLSBsYWJlbFNoaWZ0O1xuICAgICAgICB2YXIgb2Zmc2V0NHRpY2sgPSAtTWF0aC5zaW4ocmFkKSAqIChsYWJlbFN0YW5kb2ZmICsgcGFkICsgb2Zmc2V0NGZvbnRzaXplICogZC5mb250U2l6ZSk7XG5cbiAgICAgICAgcmV0dXJuIG9mZnNldDR0eCArIG9mZnNldDR0aWNrO1xuICAgIH07XG5cbiAgICBheC5fbGFiZWxhbmNob3IgPSBmdW5jdGlvbihhbmdsZSwgZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICByZXR1cm4gc2lnblNpbihyYWQpID09PSAwID9cbiAgICAgICAgICAgIChzaWduQ29zKHJhZCkgPiAwID8gJ3N0YXJ0JyA6ICdlbmQnKSA6XG4gICAgICAgICAgICAnbWlkZGxlJztcbiAgICB9O1xuXG4gICAgdmFyIG5ld1RpY2tMYXlvdXQgPSBzdHJUaWNrTGF5b3V0KGFuZ3VsYXJMYXlvdXQpO1xuICAgIGlmKF90aGlzLmFuZ3VsYXJUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVyc1snYW5ndWxhci1heGlzJ10uc2VsZWN0QWxsKCcuJyArIGF4Ll9pZCArICd0aWNrJykucmVtb3ZlKCk7XG4gICAgICAgIF90aGlzLmFuZ3VsYXJUaWNrTGF5b3V0ID0gbmV3VGlja0xheW91dDtcbiAgICB9XG5cbiAgICBheC5zZXRTY2FsZSgpO1xuICAgIGRvVGlja3NTaW5nbGUoZ2QsIGF4LCB0cnVlKTtcblxuICAgIC8vIGFuZ2xlIG9mIHBvbHlnb24gdmVydGljZXMgaW4gZ2VvbWV0cmljIHJhZGlhbnMgKG51bGwgbWVhbnMgY2lyY2xlcylcbiAgICAvLyBUT0RPIHdoYXQgdG8gZG8gd2hlbiBheC5wZXJpb2QgPiBheC5fY2F0ZWdvcmllcyA/P1xuICAgIHZhciB2YW5nbGVzO1xuICAgIGlmKHBvbGFyTGF5b3V0LmdyaWRzaGFwZSA9PT0gJ2xpbmVhcicpIHtcbiAgICAgICAgdmFuZ2xlcyA9IGF4Ll92YWxzLm1hcCh0MmcpO1xuXG4gICAgICAgIC8vIGF4Ll92YWxzIHNob3VsZCBiZSBhbHdheXMgb3JkZXJlZCwgbWFrZSB0aGVtXG4gICAgICAgIC8vIGFsd2F5cyB0dXJuIGNvdW50ZXJjbG9ja3dpc2UgZm9yIGNvbnZlbmllbmNlIGhlcmVcbiAgICAgICAgaWYoTGliLmFuZ2xlRGVsdGEodmFuZ2xlc1swXSwgdmFuZ2xlc1sxXSkgPCAwKSB7XG4gICAgICAgICAgICB2YW5nbGVzID0gdmFuZ2xlcy5zbGljZSgpLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbmdsZXMgPSBudWxsO1xuICAgIH1cbiAgICBfdGhpcy52YW5nbGVzID0gdmFuZ2xlcztcblxuICAgIC8vIFRPRE8gbWF5YmUgdHdvIGFyY3MgaXMgYmV0dGVyIGhlcmU/XG4gICAgLy8gbWF5YmUgc3BsaXQgc3R5bGUgYXR0cmlidXRlcyBiZXR3ZWVuIGlubmVyIGFuZCBvdXRlciBhbmd1bGFyIGF4ZXM/XG5cbiAgICB1cGRhdGVFbGVtZW50KGxheWVyc1snYW5ndWxhci1saW5lJ10uc2VsZWN0KCdwYXRoJyksIGFuZ3VsYXJMYXlvdXQuc2hvd2xpbmUsIHtcbiAgICAgICAgZDogX3RoaXMucGF0aFN1YnBsb3QoKSxcbiAgICAgICAgdHJhbnNmb3JtOiBzdHJUcmFuc2xhdGUoY3gsIGN5KVxuICAgIH0pXG4gICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGFuZ3VsYXJMYXlvdXQubGluZXdpZHRoKVxuICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYW5ndWxhckxheW91dC5saW5lY29sb3IpO1xufTtcblxucHJvdG8udXBkYXRlRnggPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBwb2xhckxheW91dCkge1xuICAgIGlmKCF0aGlzLmdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgdGhpcy51cGRhdGVBbmd1bGFyRHJhZyhmdWxsTGF5b3V0KTtcbiAgICAgICAgdGhpcy51cGRhdGVSYWRpYWxEcmFnKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCAwKTtcbiAgICAgICAgdGhpcy51cGRhdGVSYWRpYWxEcmFnKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCAxKTtcbiAgICAgICAgdGhpcy51cGRhdGVNYWluRHJhZyhmdWxsTGF5b3V0KTtcbiAgICB9XG59O1xuXG5wcm90by51cGRhdGVNYWluRHJhZyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBnZCA9IF90aGlzLmdkO1xuICAgIHZhciBsYXllcnMgPSBfdGhpcy5sYXllcnM7XG4gICAgdmFyIHpvb21sYXllciA9IGZ1bGxMYXlvdXQuX3pvb21sYXllcjtcbiAgICB2YXIgTUlOWk9PTSA9IGNvbnN0YW50cy5NSU5aT09NO1xuICAgIHZhciBPRkZFREdFID0gY29uc3RhbnRzLk9GRkVER0U7XG4gICAgdmFyIHJhZGl1cyA9IF90aGlzLnJhZGl1cztcbiAgICB2YXIgaW5uZXJSYWRpdXMgPSBfdGhpcy5pbm5lclJhZGl1cztcbiAgICB2YXIgY3ggPSBfdGhpcy5jeDtcbiAgICB2YXIgY3kgPSBfdGhpcy5jeTtcbiAgICB2YXIgY3h4ID0gX3RoaXMuY3h4O1xuICAgIHZhciBjeXkgPSBfdGhpcy5jeXk7XG4gICAgdmFyIHNlY3RvckluUmFkID0gX3RoaXMuc2VjdG9ySW5SYWQ7XG4gICAgdmFyIHZhbmdsZXMgPSBfdGhpcy52YW5nbGVzO1xuICAgIHZhciByYWRpYWxBeGlzID0gX3RoaXMucmFkaWFsQXhpcztcbiAgICB2YXIgY2xhbXBUaW55ID0gaGVscGVycy5jbGFtcFRpbnk7XG4gICAgdmFyIGZpbmRYWWF0TGVuZ3RoID0gaGVscGVycy5maW5kWFlhdExlbmd0aDtcbiAgICB2YXIgZmluZEVuY2xvc2luZ1ZlcnRleEFuZ2xlcyA9IGhlbHBlcnMuZmluZEVuY2xvc2luZ1ZlcnRleEFuZ2xlcztcbiAgICB2YXIgY2h3ID0gY29uc3RhbnRzLmNvcm5lckhhbGZXaWR0aDtcbiAgICB2YXIgY2hsID0gY29uc3RhbnRzLmNvcm5lckxlbiAvIDI7XG5cbiAgICB2YXIgbWFpbkRyYWcgPSBkcmFnQm94Lm1ha2VEcmFnZ2VyKGxheWVycywgJ3BhdGgnLCAnbWFpbmRyYWcnLCAnY3Jvc3NoYWlyJyk7XG5cbiAgICBkMy5zZWxlY3QobWFpbkRyYWcpXG4gICAgICAgIC5hdHRyKCdkJywgX3RoaXMucGF0aFN1YnBsb3QoKSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zbGF0ZShjeCwgY3kpKTtcblxuICAgIHZhciBkcmFnT3B0cyA9IHtcbiAgICAgICAgZWxlbWVudDogbWFpbkRyYWcsXG4gICAgICAgIGdkOiBnZCxcbiAgICAgICAgc3VicGxvdDogX3RoaXMuaWQsXG4gICAgICAgIHBsb3RpbmZvOiB7XG4gICAgICAgICAgICBpZDogX3RoaXMuaWQsXG4gICAgICAgICAgICB4YXhpczogX3RoaXMueGF4aXMsXG4gICAgICAgICAgICB5YXhpczogX3RoaXMueWF4aXNcbiAgICAgICAgfSxcbiAgICAgICAgeGF4ZXM6IFtfdGhpcy54YXhpc10sXG4gICAgICAgIHlheGVzOiBbX3RoaXMueWF4aXNdXG4gICAgfTtcblxuICAgIC8vIG1vdXNlIHB4IHBvc2l0aW9uIGF0IGRyYWcgc3RhcnQgKDApLCBtb3ZlICgxKVxuICAgIHZhciB4MCwgeTA7XG4gICAgLy8gcmFkaWFsIGRpc3RhbmNlIGZyb20gY2lyY2xlIGNlbnRlciBhdCBkcmFnIHN0YXJ0ICgwKSwgbW92ZSAoMSlcbiAgICB2YXIgcjAsIHIxO1xuICAgIC8vIHpvb21ib3ggcGVyc2lzdGVudCBxdWFudGl0aWVzXG4gICAgdmFyIHBhdGgwLCBkaW1tZWQsIGx1bTtcbiAgICAvLyB6b29tYm94LCBjb3JuZXJzIGVsZW1lbnRzXG4gICAgdmFyIHpiLCBjb3JuZXJzO1xuXG4gICAgZnVuY3Rpb24gbm9ybSh4LCB5KSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24geHkycih4LCB5KSB7XG4gICAgICAgIHJldHVybiBub3JtKHggLSBjeHgsIHkgLSBjeXkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHh5MmEoeCwgeSkge1xuICAgICAgICByZXR1cm4gTWF0aC5hdGFuMihjeXkgLSB5LCB4IC0gY3h4KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByYTJ4eShyLCBhKSB7XG4gICAgICAgIHJldHVybiBbciAqIE1hdGguY29zKGEpLCByICogTWF0aC5zaW4oLWEpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXRoQ29ybmVyKHIsIGEpIHtcbiAgICAgICAgaWYociA9PT0gMCkgcmV0dXJuIF90aGlzLnBhdGhTZWN0b3IoMiAqIGNodyk7XG5cbiAgICAgICAgdmFyIGRhID0gY2hsIC8gcjtcbiAgICAgICAgdmFyIGFtID0gYSAtIGRhO1xuICAgICAgICB2YXIgYXAgPSBhICsgZGE7XG4gICAgICAgIHZhciByYiA9IE1hdGgubWF4KDAsIE1hdGgubWluKHIsIHJhZGl1cykpO1xuICAgICAgICB2YXIgcm0gPSByYiAtIGNodztcbiAgICAgICAgdmFyIHJwID0gcmIgKyBjaHc7XG5cbiAgICAgICAgcmV0dXJuICdNJyArIHJhMnh5KHJtLCBhbSkgK1xuICAgICAgICAgICAgJ0EnICsgW3JtLCBybV0gKyAnIDAsMCwwICcgKyByYTJ4eShybSwgYXApICtcbiAgICAgICAgICAgICdMJyArIHJhMnh5KHJwLCBhcCkgK1xuICAgICAgICAgICAgJ0EnICsgW3JwLCBycF0gKyAnIDAsMCwxICcgKyByYTJ4eShycCwgYW0pICtcbiAgICAgICAgICAgICdaJztcbiAgICB9XG5cbiAgICAvLyAoeCx5KSBpcyB0aGUgcHQgYXQgbWlkZGxlIG9mIHRoZSB2YTAgPC0+IHZhMSBlZGdlXG4gICAgLy9cbiAgICAvLyAuLi4gd2UgY291bGQgZXZlbnR1YWxseSBhZGQgYW5vdGhlciBtb2RlIGZvciBjdXJzb3JcbiAgICAvLyBhbmdsZXMgJ2Nsb3NlIHRvJyBlbm91Z2ggdG8gYSBwYXJ0aWN1bGFyIHZlcnRleC5cbiAgICBmdW5jdGlvbiBwYXRoQ29ybmVyRm9yUG9seWdvbnMociwgdmEwLCB2YTEpIHtcbiAgICAgICAgaWYociA9PT0gMCkgcmV0dXJuIF90aGlzLnBhdGhTZWN0b3IoMiAqIGNodyk7XG5cbiAgICAgICAgdmFyIHh5MCA9IHJhMnh5KHIsIHZhMCk7XG4gICAgICAgIHZhciB4eTEgPSByYTJ4eShyLCB2YTEpO1xuICAgICAgICB2YXIgeCA9IGNsYW1wVGlueSgoeHkwWzBdICsgeHkxWzBdKSAvIDIpO1xuICAgICAgICB2YXIgeSA9IGNsYW1wVGlueSgoeHkwWzFdICsgeHkxWzFdKSAvIDIpO1xuICAgICAgICB2YXIgaW5uZXJQdHMsIG91dGVyUHRzO1xuXG4gICAgICAgIGlmKHggJiYgeSkge1xuICAgICAgICAgICAgdmFyIG0gPSB5IC8geDtcbiAgICAgICAgICAgIHZhciBtcGVycCA9IC0xIC8gbTtcbiAgICAgICAgICAgIHZhciBtaWRQdHMgPSBmaW5kWFlhdExlbmd0aChjaHcsIG0sIHgsIHkpO1xuICAgICAgICAgICAgaW5uZXJQdHMgPSBmaW5kWFlhdExlbmd0aChjaGwsIG1wZXJwLCBtaWRQdHNbMF1bMF0sIG1pZFB0c1swXVsxXSk7XG4gICAgICAgICAgICBvdXRlclB0cyA9IGZpbmRYWWF0TGVuZ3RoKGNobCwgbXBlcnAsIG1pZFB0c1sxXVswXSwgbWlkUHRzWzFdWzFdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBkeCwgZHk7XG4gICAgICAgICAgICBpZih5KSB7XG4gICAgICAgICAgICAgICAgLy8gaG9yaXpvbnRhbCBoYW5kbGVzXG4gICAgICAgICAgICAgICAgZHggPSBjaGw7XG4gICAgICAgICAgICAgICAgZHkgPSBjaHc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHZlcnRpY2FsIGhhbmRsZXNcbiAgICAgICAgICAgICAgICBkeCA9IGNodztcbiAgICAgICAgICAgICAgICBkeSA9IGNobDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlubmVyUHRzID0gW1t4IC0gZHgsIHkgLSBkeV0sIFt4ICsgZHgsIHkgLSBkeV1dO1xuICAgICAgICAgICAgb3V0ZXJQdHMgPSBbW3ggLSBkeCwgeSArIGR5XSwgW3ggKyBkeCwgeSArIGR5XV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gJ00nICsgaW5uZXJQdHMuam9pbignTCcpICtcbiAgICAgICAgICAgICdMJyArIG91dGVyUHRzLnJldmVyc2UoKS5qb2luKCdMJykgKyAnWic7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbVByZXAoKSB7XG4gICAgICAgIHIwID0gbnVsbDtcbiAgICAgICAgcjEgPSBudWxsO1xuICAgICAgICBwYXRoMCA9IF90aGlzLnBhdGhTdWJwbG90KCk7XG4gICAgICAgIGRpbW1lZCA9IGZhbHNlO1xuXG4gICAgICAgIHZhciBwb2xhckxheW91dE5vdyA9IGdkLl9mdWxsTGF5b3V0W190aGlzLmlkXTtcbiAgICAgICAgbHVtID0gdGlueWNvbG9yKHBvbGFyTGF5b3V0Tm93LmJnY29sb3IpLmdldEx1bWluYW5jZSgpO1xuXG4gICAgICAgIHpiID0gZHJhZ0JveC5tYWtlWm9vbWJveCh6b29tbGF5ZXIsIGx1bSwgY3gsIGN5LCBwYXRoMCk7XG4gICAgICAgIHpiLmF0dHIoJ2ZpbGwtcnVsZScsICdldmVub2RkJyk7XG4gICAgICAgIGNvcm5lcnMgPSBkcmFnQm94Lm1ha2VDb3JuZXJzKHpvb21sYXllciwgY3gsIGN5KTtcbiAgICAgICAgY2xlYXJTZWxlY3Qoem9vbWxheWVyKTtcbiAgICB9XG5cbiAgICAvLyBOLkIuIHRoaXMgc2V0cyBzY29wZWQgJ3IwJyBhbmQgJ3IxJ1xuICAgIC8vIHJldHVybiB0cnVlIGlmICd2YWxpZCcgem9vbSBkaXN0YW5jZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgZnVuY3Rpb24gY2xhbXBBbmRTZXRSMFIxKHJyMCwgcnIxKSB7XG4gICAgICAgIHJyMSA9IE1hdGgubWF4KE1hdGgubWluKHJyMSwgcmFkaXVzKSwgaW5uZXJSYWRpdXMpO1xuXG4gICAgICAgIC8vIHN0YXJ0aW5nIG9yIGVuZGluZyBkcmFnIG5lYXIgY2VudGVyIChvdXRlciBlZGdlKSxcbiAgICAgICAgLy8gY2xhbXBzIHJhZGlhbCBkaXN0YW5jZSBhdCBvcmlnaW4gKGF0IHI9cmFkaXVzKVxuICAgICAgICBpZihycjAgPCBPRkZFREdFKSBycjAgPSAwO1xuICAgICAgICBlbHNlIGlmKChyYWRpdXMgLSBycjApIDwgT0ZGRURHRSkgcnIwID0gcmFkaXVzO1xuICAgICAgICBlbHNlIGlmKHJyMSA8IE9GRkVER0UpIHJyMSA9IDA7XG4gICAgICAgIGVsc2UgaWYoKHJhZGl1cyAtIHJyMSkgPCBPRkZFREdFKSBycjEgPSByYWRpdXM7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIHIwIDwgcjEsXG4gICAgICAgIC8vIHRvIGdldCBjb3JyZWN0IGZpbGwgcGF0dGVybiBpbiBwYXRoMSBiZWxvd1xuICAgICAgICBpZihNYXRoLmFicyhycjEgLSBycjApID4gTUlOWk9PTSkge1xuICAgICAgICAgICAgaWYocnIwIDwgcnIxKSB7XG4gICAgICAgICAgICAgICAgcjAgPSBycjA7XG4gICAgICAgICAgICAgICAgcjEgPSBycjE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHIwID0gcnIxO1xuICAgICAgICAgICAgICAgIHIxID0gcnIwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByMCA9IG51bGw7XG4gICAgICAgICAgICByMSA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcHBseVpvb21Nb3ZlKHBhdGgxLCBjcGF0aCkge1xuICAgICAgICBwYXRoMSA9IHBhdGgxIHx8IHBhdGgwO1xuICAgICAgICBjcGF0aCA9IGNwYXRoIHx8ICdNMCwwWic7XG5cbiAgICAgICAgemIuYXR0cignZCcsIHBhdGgxKTtcbiAgICAgICAgY29ybmVycy5hdHRyKCdkJywgY3BhdGgpO1xuICAgICAgICBkcmFnQm94LnRyYW5zaXRpb25ab29tYm94KHpiLCBjb3JuZXJzLCBkaW1tZWQsIGx1bSk7XG4gICAgICAgIGRpbW1lZCA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbU1vdmUoZHgsIGR5KSB7XG4gICAgICAgIHZhciB4MSA9IHgwICsgZHg7XG4gICAgICAgIHZhciB5MSA9IHkwICsgZHk7XG4gICAgICAgIHZhciBycjAgPSB4eTJyKHgwLCB5MCk7XG4gICAgICAgIHZhciBycjEgPSBNYXRoLm1pbih4eTJyKHgxLCB5MSksIHJhZGl1cyk7XG4gICAgICAgIHZhciBhMCA9IHh5MmEoeDAsIHkwKTtcbiAgICAgICAgdmFyIHBhdGgxO1xuICAgICAgICB2YXIgY3BhdGg7XG5cbiAgICAgICAgaWYoY2xhbXBBbmRTZXRSMFIxKHJyMCwgcnIxKSkge1xuICAgICAgICAgICAgcGF0aDEgPSBwYXRoMCArIF90aGlzLnBhdGhTZWN0b3IocjEpO1xuICAgICAgICAgICAgaWYocjApIHBhdGgxICs9IF90aGlzLnBhdGhTZWN0b3IocjApO1xuICAgICAgICAgICAgLy8ga2VlcCAnc3RhcnRpbmcnIGFuZ2xlXG4gICAgICAgICAgICBjcGF0aCA9IHBhdGhDb3JuZXIocjAsIGEwKSArIHBhdGhDb3JuZXIocjEsIGEwKTtcbiAgICAgICAgfVxuICAgICAgICBhcHBseVpvb21Nb3ZlKHBhdGgxLCBjcGF0aCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZmluZFBvbHlnb25SYWRpdXMoeCwgeSwgdmEwLCB2YTEpIHtcbiAgICAgICAgdmFyIHh5ID0gaGVscGVycy5maW5kSW50ZXJzZWN0aW9uWFkodmEwLCB2YTEsIHZhMCwgW3ggLSBjeHgsIGN5eSAtIHldKTtcbiAgICAgICAgcmV0dXJuIG5vcm0oeHlbMF0sIHh5WzFdKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tTW92ZUZvclBvbHlnb25zKGR4LCBkeSkge1xuICAgICAgICB2YXIgeDEgPSB4MCArIGR4O1xuICAgICAgICB2YXIgeTEgPSB5MCArIGR5O1xuICAgICAgICB2YXIgYTAgPSB4eTJhKHgwLCB5MCk7XG4gICAgICAgIHZhciBhMSA9IHh5MmEoeDEsIHkxKTtcbiAgICAgICAgdmFyIHZhbmdsZXMwID0gZmluZEVuY2xvc2luZ1ZlcnRleEFuZ2xlcyhhMCwgdmFuZ2xlcyk7XG4gICAgICAgIHZhciB2YW5nbGVzMSA9IGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXMoYTEsIHZhbmdsZXMpO1xuICAgICAgICB2YXIgcnIwID0gZmluZFBvbHlnb25SYWRpdXMoeDAsIHkwLCB2YW5nbGVzMFswXSwgdmFuZ2xlczBbMV0pO1xuICAgICAgICB2YXIgcnIxID0gTWF0aC5taW4oZmluZFBvbHlnb25SYWRpdXMoeDEsIHkxLCB2YW5nbGVzMVswXSwgdmFuZ2xlczFbMV0pLCByYWRpdXMpO1xuICAgICAgICB2YXIgcGF0aDE7XG4gICAgICAgIHZhciBjcGF0aDtcblxuICAgICAgICBpZihjbGFtcEFuZFNldFIwUjEocnIwLCBycjEpKSB7XG4gICAgICAgICAgICBwYXRoMSA9IHBhdGgwICsgX3RoaXMucGF0aFNlY3RvcihyMSk7XG4gICAgICAgICAgICBpZihyMCkgcGF0aDEgKz0gX3RoaXMucGF0aFNlY3RvcihyMCk7XG4gICAgICAgICAgICAvLyBrZWVwICdzdGFydGluZycgYW5nbGUgaGVyZSB0b29cbiAgICAgICAgICAgIGNwYXRoID0gW1xuICAgICAgICAgICAgICAgIHBhdGhDb3JuZXJGb3JQb2x5Z29ucyhyMCwgdmFuZ2xlczBbMF0sIHZhbmdsZXMwWzFdKSxcbiAgICAgICAgICAgICAgICBwYXRoQ29ybmVyRm9yUG9seWdvbnMocjEsIHZhbmdsZXMwWzBdLCB2YW5nbGVzMFsxXSlcbiAgICAgICAgICAgIF0uam9pbignICcpO1xuICAgICAgICB9XG4gICAgICAgIGFwcGx5Wm9vbU1vdmUocGF0aDEsIGNwYXRoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tRG9uZSgpIHtcbiAgICAgICAgZHJhZ0JveC5yZW1vdmVab29tYm94KGdkKTtcblxuICAgICAgICBpZihyMCA9PT0gbnVsbCB8fCByMSA9PT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgICAgIGRyYWdCb3guc2hvd0RvdWJsZUNsaWNrTm90aWZpZXIoZ2QpO1xuXG4gICAgICAgIHZhciBybCA9IHJhZGlhbEF4aXMuX3JsO1xuICAgICAgICB2YXIgbSA9IChybFsxXSAtIHJsWzBdKSAvICgxIC0gaW5uZXJSYWRpdXMgLyByYWRpdXMpIC8gcmFkaXVzO1xuICAgICAgICB2YXIgbmV3Um5nID0gW1xuICAgICAgICAgICAgcmxbMF0gKyAocjAgLSBpbm5lclJhZGl1cykgKiBtLFxuICAgICAgICAgICAgcmxbMF0gKyAocjEgLSBpbm5lclJhZGl1cykgKiBtXG4gICAgICAgIF07XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIF90aGlzLmlkICsgJy5yYWRpYWxheGlzLnJhbmdlJywgbmV3Um5nKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tQ2xpY2sobnVtQ2xpY2tzLCBldnQpIHtcbiAgICAgICAgdmFyIGNsaWNrTW9kZSA9IGdkLl9mdWxsTGF5b3V0LmNsaWNrbW9kZTtcblxuICAgICAgICBkcmFnQm94LnJlbW92ZVpvb21ib3goZ2QpO1xuXG4gICAgICAgIC8vIFRPRE8gZG91YmxlIG9uY2UgdnMgdHdpY2UgbG9naWMgKGF1dG9yYW5nZSB2cyBmaXhlZCByYW5nZSlcbiAgICAgICAgaWYobnVtQ2xpY2tzID09PSAyKSB7XG4gICAgICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG4gICAgICAgICAgICBmb3IodmFyIGsgaW4gX3RoaXMudmlld0luaXRpYWwpIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVPYmpbX3RoaXMuaWQgKyAnLicgKyBrXSA9IF90aGlzLnZpZXdJbml0aWFsW2tdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfZG91YmxlY2xpY2snLCBudWxsKTtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIHVwZGF0ZU9iaik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjbGlja01vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSAmJiBudW1DbGlja3MgPT09IDEpIHtcbiAgICAgICAgICAgIHNlbGVjdE9uQ2xpY2soZXZ0LCBnZCwgW190aGlzLnhheGlzXSwgW190aGlzLnlheGlzXSwgX3RoaXMuaWQsIGRyYWdPcHRzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBldnQsIF90aGlzLmlkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRyYWdPcHRzLnByZXBGbiA9IGZ1bmN0aW9uKGV2dCwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgdmFyIGRyYWdNb2RlTm93ID0gZ2QuX2Z1bGxMYXlvdXQuZHJhZ21vZGU7XG5cbiAgICAgICAgdmFyIGJib3ggPSBtYWluRHJhZy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgeDAgPSBzdGFydFggLSBiYm94LmxlZnQ7XG4gICAgICAgIHkwID0gc3RhcnRZIC0gYmJveC50b3A7XG5cbiAgICAgICAgLy8gbmVlZCB0byBvZmZzZXQgeC95IGFzIGJib3ggY2VudGVyIGRvZXMgbm90XG4gICAgICAgIC8vIG1hdGNoIG9yaWdpbiBmb3IgYXN5bW1ldHJpYyBwb2x5Z29uc1xuICAgICAgICBpZih2YW5nbGVzKSB7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gaGVscGVycy5maW5kUG9seWdvbk9mZnNldChyYWRpdXMsIHNlY3RvckluUmFkWzBdLCBzZWN0b3JJblJhZFsxXSwgdmFuZ2xlcyk7XG4gICAgICAgICAgICB4MCArPSBjeHggKyBvZmZzZXRbMF07XG4gICAgICAgICAgICB5MCArPSBjeXkgKyBvZmZzZXRbMV07XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2goZHJhZ01vZGVOb3cpIHtcbiAgICAgICAgICAgIGNhc2UgJ3pvb20nOlxuICAgICAgICAgICAgICAgIGlmKHZhbmdsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ09wdHMubW92ZUZuID0gem9vbU1vdmVGb3JQb2x5Z29ucztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0cy5tb3ZlRm4gPSB6b29tTW92ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZHJhZ09wdHMuY2xpY2tGbiA9IHpvb21DbGljaztcbiAgICAgICAgICAgICAgICBkcmFnT3B0cy5kb25lRm4gPSB6b29tRG9uZTtcbiAgICAgICAgICAgICAgICB6b29tUHJlcChldnQsIHN0YXJ0WCwgc3RhcnRZKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NlbGVjdCc6XG4gICAgICAgICAgICBjYXNlICdsYXNzbyc6XG4gICAgICAgICAgICAgICAgcHJlcFNlbGVjdChldnQsIHN0YXJ0WCwgc3RhcnRZLCBkcmFnT3B0cywgZHJhZ01vZGVOb3cpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIG1haW5EcmFnLm9ubW91c2Vtb3ZlID0gZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgIEZ4LmhvdmVyKGdkLCBldnQsIF90aGlzLmlkKTtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2xhc3Rob3ZlciA9IG1haW5EcmFnO1xuICAgICAgICBnZC5fZnVsbExheW91dC5faG92ZXJzdWJwbG90ID0gX3RoaXMuaWQ7XG4gICAgfTtcblxuICAgIG1haW5EcmFnLm9ubW91c2VvdXQgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgaWYoZ2QuX2RyYWdnaW5nKSByZXR1cm47XG4gICAgICAgIGRyYWdFbGVtZW50LnVuaG92ZXIoZ2QsIGV2dCk7XG4gICAgfTtcblxuICAgIGRyYWdFbGVtZW50LmluaXQoZHJhZ09wdHMpO1xufTtcblxucHJvdG8udXBkYXRlUmFkaWFsRHJhZyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCBybmdJbmRleCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ2Q7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBpbm5lclJhZGl1cyA9IF90aGlzLmlubmVyUmFkaXVzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciByYWRpYWxBeGlzID0gX3RoaXMucmFkaWFsQXhpcztcbiAgICB2YXIgYmwgPSBjb25zdGFudHMucmFkaWFsRHJhZ0JveFNpemU7XG4gICAgdmFyIGJsMiA9IGJsIC8gMjtcblxuICAgIGlmKCFyYWRpYWxBeGlzLnZpc2libGUpIHJldHVybjtcblxuICAgIHZhciBhbmdsZTAgPSBkZWcycmFkKF90aGlzLnJhZGlhbEF4aXNBbmdsZSk7XG4gICAgdmFyIHJsID0gcmFkaWFsQXhpcy5fcmw7XG4gICAgdmFyIHJsMCA9IHJsWzBdO1xuICAgIHZhciBybDEgPSBybFsxXTtcbiAgICB2YXIgcmJhc2UgPSBybFtybmdJbmRleF07XG4gICAgdmFyIG0gPSAwLjc1ICogKHJsWzFdIC0gcmxbMF0pIC8gKDEgLSBwb2xhckxheW91dC5ob2xlKSAvIHJhZGl1cztcblxuICAgIHZhciB0eCwgdHksIGNsYXNzTmFtZTtcbiAgICBpZihybmdJbmRleCkge1xuICAgICAgICB0eCA9IGN4ICsgKHJhZGl1cyArIGJsMikgKiBNYXRoLmNvcyhhbmdsZTApO1xuICAgICAgICB0eSA9IGN5IC0gKHJhZGl1cyArIGJsMikgKiBNYXRoLnNpbihhbmdsZTApO1xuICAgICAgICBjbGFzc05hbWUgPSAncmFkaWFsZHJhZyc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gdGhlICdpbm5lcicgYm94IGNhbiBnZXQgY2FsbGVkOlxuICAgICAgICAvLyAtIHdoZW4gcG9sYXIuaG9sZT4wXG4gICAgICAgIC8vIC0gd2hlbiBwb2xhci5zZWN0b3IgaXNuJ3QgYSBmdWxsIGNpcmNsZVxuICAgICAgICAvLyBvdGhlcndpc2UgaXQgaXMgaGlkZGVuIGJlaGluZCB0aGUgbWFpbiBkcmFnLlxuICAgICAgICB0eCA9IGN4ICsgKGlubmVyUmFkaXVzIC0gYmwyKSAqIE1hdGguY29zKGFuZ2xlMCk7XG4gICAgICAgIHR5ID0gY3kgLSAoaW5uZXJSYWRpdXMgLSBibDIpICogTWF0aC5zaW4oYW5nbGUwKTtcbiAgICAgICAgY2xhc3NOYW1lID0gJ3JhZGlhbGRyYWctaW5uZXInO1xuICAgIH1cblxuICAgIHZhciByYWRpYWxEcmFnID0gZHJhZ0JveC5tYWtlUmVjdERyYWdnZXIobGF5ZXJzLCBjbGFzc05hbWUsICdjcm9zc2hhaXInLCAtYmwyLCAtYmwyLCBibCwgYmwpO1xuICAgIHZhciBkcmFnT3B0cyA9IHtlbGVtZW50OiByYWRpYWxEcmFnLCBnZDogZ2R9O1xuXG4gICAgdXBkYXRlRWxlbWVudChkMy5zZWxlY3QocmFkaWFsRHJhZyksIHJhZGlhbEF4aXMudmlzaWJsZSAmJiBpbm5lclJhZGl1cyA8IHJhZGl1cywge1xuICAgICAgICB0cmFuc2Zvcm06IHN0clRyYW5zbGF0ZSh0eCwgdHkpXG4gICAgfSk7XG5cbiAgICAvLyBtb3ZlIGZ1bmN0aW9uIChlaXRoZXIgcm90YXRlIG9yIHJlLXJhbmdlIGZsYXZvcilcbiAgICB2YXIgbW92ZUZuMjtcbiAgICAvLyByb3RhdGUgYW5nbGUgb24gZG9uZVxuICAgIHZhciBhbmdsZTE7XG4gICAgLy8gcmUtcmFuZ2UgcmFuZ2VbMV0gKG9yIHJhbmdlWzBdKSBvbiBkb25lXG4gICAgdmFyIHJwcmltZTtcblxuICAgIGZ1bmN0aW9uIG1vdmVGbihkeCwgZHkpIHtcbiAgICAgICAgaWYobW92ZUZuMikge1xuICAgICAgICAgICAgbW92ZUZuMihkeCwgZHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGR2ZWMgPSBbZHgsIC1keV07XG4gICAgICAgICAgICB2YXIgcnZlYyA9IFtNYXRoLmNvcyhhbmdsZTApLCBNYXRoLnNpbihhbmdsZTApXTtcbiAgICAgICAgICAgIHZhciBjb21wID0gTWF0aC5hYnMoTGliLmRvdChkdmVjLCBydmVjKSAvIE1hdGguc3FydChMaWIuZG90KGR2ZWMsIGR2ZWMpKSk7XG5cbiAgICAgICAgICAgIC8vIG1vc3RseSBwZXJwZW5kaWN1bGFyIG1vdGlvbnMgcm90YXRlLFxuICAgICAgICAgICAgLy8gbW9zdGx5IHBhcmFsbGVsIG1vdGlvbnMgcmUtcmFuZ2VcbiAgICAgICAgICAgIGlmKCFpc05hTihjb21wKSkge1xuICAgICAgICAgICAgICAgIG1vdmVGbjIgPSBjb21wIDwgMC41ID8gcm90YXRlTW92ZSA6IHJlcmFuZ2VNb3ZlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG9uZUZuKCkge1xuICAgICAgICBpZihhbmdsZTEgIT09IG51bGwpIHtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIF90aGlzLmlkICsgJy5yYWRpYWxheGlzLmFuZ2xlJywgYW5nbGUxKTtcbiAgICAgICAgfSBlbHNlIGlmKHJwcmltZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgX3RoaXMuaWQgKyAnLnJhZGlhbGF4aXMucmFuZ2VbJyArIHJuZ0luZGV4ICsgJ10nLCBycHJpbWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcm90YXRlTW92ZShkeCwgZHkpIHtcbiAgICAgICAgLy8gZGlzYWJsZSBmb3IgaW5uZXIgZHJhZyBib3hlc1xuICAgICAgICBpZihybmdJbmRleCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciB4MSA9IHR4ICsgZHg7XG4gICAgICAgIHZhciB5MSA9IHR5ICsgZHk7XG5cbiAgICAgICAgYW5nbGUxID0gTWF0aC5hdGFuMihjeSAtIHkxLCB4MSAtIGN4KTtcbiAgICAgICAgaWYoX3RoaXMudmFuZ2xlcykgYW5nbGUxID0gc25hcFRvVmVydGV4QW5nbGUoYW5nbGUxLCBfdGhpcy52YW5nbGVzKTtcbiAgICAgICAgYW5nbGUxID0gcmFkMmRlZyhhbmdsZTEpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBzdHJUcmFuc2xhdGUoY3gsIGN5KSArIHN0clJvdGF0ZSgtYW5nbGUxKTtcbiAgICAgICAgbGF5ZXJzWydyYWRpYWwtYXhpcyddLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSk7XG4gICAgICAgIGxheWVyc1sncmFkaWFsLWxpbmUnXS5zZWxlY3QoJ2xpbmUnKS5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xuXG4gICAgICAgIHZhciBmdWxsTGF5b3V0Tm93ID0gX3RoaXMuZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciBwb2xhckxheW91dE5vdyA9IGZ1bGxMYXlvdXROb3dbX3RoaXMuaWRdO1xuICAgICAgICBfdGhpcy51cGRhdGVSYWRpYWxBeGlzVGl0bGUoZnVsbExheW91dE5vdywgcG9sYXJMYXlvdXROb3csIGFuZ2xlMSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVyYW5nZU1vdmUoZHgsIGR5KSB7XG4gICAgICAgIC8vIHByb2plY3QgKGR4LCBkeSkgdW50byB1bml0IHJhZGlhbCBheGlzIHZlY3RvclxuICAgICAgICB2YXIgZHIgPSBMaWIuZG90KFtkeCwgLWR5XSwgW01hdGguY29zKGFuZ2xlMCksIE1hdGguc2luKGFuZ2xlMCldKTtcbiAgICAgICAgcnByaW1lID0gcmJhc2UgLSBtICogZHI7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIHJwcmltZSBkb2VzIG5vdCBjaGFuZ2UgdGhlIHJhbmdlWzBdIC0+IHJhbmdlWzFdIHNpZ25cbiAgICAgICAgaWYoKG0gPiAwKSAhPT0gKHJuZ0luZGV4ID8gcnByaW1lID4gcmwwIDogcnByaW1lIDwgcmwxKSkge1xuICAgICAgICAgICAgcnByaW1lID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSByYWRpYWwgcmFuZ2UgLT4gdXBkYXRlIGMyZyAtPiB1cGRhdGUgX20sX2JcbiAgICAgICAgcmFkaWFsQXhpcy5yYW5nZVtybmdJbmRleF0gPSBycHJpbWU7XG4gICAgICAgIHJhZGlhbEF4aXMuX3JsW3JuZ0luZGV4XSA9IHJwcmltZTtcbiAgICAgICAgcmFkaWFsQXhpcy5zZXRHZW9tZXRyeSgpO1xuICAgICAgICByYWRpYWxBeGlzLnNldFNjYWxlKCk7XG5cbiAgICAgICAgX3RoaXMueGF4aXMuc2V0UmFuZ2UoKTtcbiAgICAgICAgX3RoaXMueGF4aXMuc2V0U2NhbGUoKTtcbiAgICAgICAgX3RoaXMueWF4aXMuc2V0UmFuZ2UoKTtcbiAgICAgICAgX3RoaXMueWF4aXMuc2V0U2NhbGUoKTtcblxuICAgICAgICBkb1RpY2tzU2luZ2xlKGdkLCByYWRpYWxBeGlzLCB0cnVlKTtcbiAgICAgICAgbGF5ZXJzWydyYWRpYWwtZ3JpZCddXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgc3RyVHJhbnNsYXRlKGN4LCBjeSkpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoJykuYXR0cigndHJhbnNmb3JtJywgbnVsbCk7XG5cbiAgICAgICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIHRyYWNlVHlwZSBpbiBfdGhpcy50cmFjZUhhc2gpIHtcbiAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YSA9IF90aGlzLnRyYWNlSGFzaFt0cmFjZVR5cGVdO1xuICAgICAgICAgICAgdmFyIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSA9IExpYi5maWx0ZXJWaXNpYmxlKG1vZHVsZUNhbGNEYXRhKTtcbiAgICAgICAgICAgIHZhciBfbW9kdWxlID0gbW9kdWxlQ2FsY0RhdGFbMF1bMF0udHJhY2UuX21vZHVsZTtcbiAgICAgICAgICAgIHZhciBwb2xhckxheW91dE5vdyA9IGdkLl9mdWxsTGF5b3V0W190aGlzLmlkXTtcbiAgICAgICAgICAgIF9tb2R1bGUucGxvdChnZCwgX3RoaXMsIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSwgcG9sYXJMYXlvdXROb3cpO1xuICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZVR5cGUsICdnbCcpICYmIG1vZHVsZUNhbGNEYXRhVmlzaWJsZS5sZW5ndGgpIGhhc1JlZ2wgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzUmVnbCkge1xuICAgICAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgICAgIHJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHJhZ09wdHMucHJlcEZuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIG1vdmVGbjIgPSBudWxsO1xuICAgICAgICBhbmdsZTEgPSBudWxsO1xuICAgICAgICBycHJpbWUgPSBudWxsO1xuXG4gICAgICAgIGRyYWdPcHRzLm1vdmVGbiA9IG1vdmVGbjtcbiAgICAgICAgZHJhZ09wdHMuZG9uZUZuID0gZG9uZUZuO1xuXG4gICAgICAgIGNsZWFyU2VsZWN0KGZ1bGxMYXlvdXQuX3pvb21sYXllcik7XG4gICAgfTtcblxuICAgIGRyYWdPcHRzLmNsYW1wRm4gPSBmdW5jdGlvbihkeCwgZHkpIHtcbiAgICAgICAgaWYoTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KSA8IGNvbnN0YW50cy5NSU5EUkFHKSB7XG4gICAgICAgICAgICBkeCA9IDA7XG4gICAgICAgICAgICBkeSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtkeCwgZHldO1xuICAgIH07XG5cbiAgICBkcmFnRWxlbWVudC5pbml0KGRyYWdPcHRzKTtcbn07XG5cbnByb3RvLnVwZGF0ZUFuZ3VsYXJEcmFnID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ2Q7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IF90aGlzLmFuZ3VsYXJBeGlzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciBjeHggPSBfdGhpcy5jeHg7XG4gICAgdmFyIGN5eSA9IF90aGlzLmN5eTtcbiAgICB2YXIgZGJzID0gY29uc3RhbnRzLmFuZ3VsYXJEcmFnQm94U2l6ZTtcblxuICAgIHZhciBhbmd1bGFyRHJhZyA9IGRyYWdCb3gubWFrZURyYWdnZXIobGF5ZXJzLCAncGF0aCcsICdhbmd1bGFyZHJhZycsICdtb3ZlJyk7XG4gICAgdmFyIGRyYWdPcHRzID0ge2VsZW1lbnQ6IGFuZ3VsYXJEcmFnLCBnZDogZ2R9O1xuXG4gICAgZDMuc2VsZWN0KGFuZ3VsYXJEcmFnKVxuICAgICAgICAuYXR0cignZCcsIF90aGlzLnBhdGhBbm51bHVzKHJhZGl1cywgcmFkaXVzICsgZGJzKSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zbGF0ZShjeCwgY3kpKVxuICAgICAgICAuY2FsbChzZXRDdXJzb3IsICdtb3ZlJyk7XG5cbiAgICBmdW5jdGlvbiB4eTJhKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoY3l5ICsgZGJzIC0geSwgeCAtIGN4eCAtIGRicyk7XG4gICAgfVxuXG4gICAgLy8gc2NhdHRlciB0cmFjZSwgcG9pbnRzIGFuZCB0ZXh0cG9pbnRzIHNlbGVjdGlvbnNcbiAgICB2YXIgc2NhdHRlclRyYWNlcyA9IGxheWVycy5mcm9udHBsb3Quc2VsZWN0KCcuc2NhdHRlcmxheWVyJykuc2VsZWN0QWxsKCcudHJhY2UnKTtcbiAgICB2YXIgc2NhdHRlclBvaW50cyA9IHNjYXR0ZXJUcmFjZXMuc2VsZWN0QWxsKCcucG9pbnQnKTtcbiAgICB2YXIgc2NhdHRlclRleHRQb2ludHMgPSBzY2F0dGVyVHJhY2VzLnNlbGVjdEFsbCgnLnRleHRwb2ludCcpO1xuXG4gICAgLy8gbW91c2UgcHggcG9zaXRpb24gYXQgZHJhZyBzdGFydCAoMCksIG1vdmUgKDEpXG4gICAgdmFyIHgwLCB5MDtcbiAgICAvLyBhbmd1bGFyIGF4aXMgYW5nbGUgcm90YXRpb24gYXQgZHJhZyBzdGFydCAoMCksIG1vdmUgKDEpXG4gICAgdmFyIHJvdDAsIHJvdDE7XG4gICAgLy8gaW5kdWNlZCByYWRpYWwgYXhpcyByb3RhdGlvbiAob25seSB1c2VkIG9uIHBvbHlnb24gZ3JpZHMpXG4gICAgdmFyIHJyb3QxO1xuICAgIC8vIGFuZ2xlIGFib3V0IGNpcmNsZSBjZW50ZXIgYXQgZHJhZyBzdGFydFxuICAgIHZhciBhMDtcblxuICAgIGZ1bmN0aW9uIG1vdmVGbihkeCwgZHkpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXROb3cgPSBfdGhpcy5nZC5fZnVsbExheW91dDtcbiAgICAgICAgdmFyIHBvbGFyTGF5b3V0Tm93ID0gZnVsbExheW91dE5vd1tfdGhpcy5pZF07XG4gICAgICAgIHZhciB4MSA9IHgwICsgZHg7XG4gICAgICAgIHZhciB5MSA9IHkwICsgZHk7XG4gICAgICAgIHZhciBhMSA9IHh5MmEoeDEsIHkxKTtcbiAgICAgICAgdmFyIGRhID0gcmFkMmRlZyhhMSAtIGEwKTtcbiAgICAgICAgcm90MSA9IHJvdDAgKyBkYTtcblxuICAgICAgICBsYXllcnMuZnJvbnRwbG90LmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICBzdHJUcmFuc2xhdGUoX3RoaXMueE9mZnNldDIsIF90aGlzLnlPZmZzZXQyKSArIHN0clJvdGF0ZShbLWRhLCBjeHgsIGN5eV0pXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYoX3RoaXMudmFuZ2xlcykge1xuICAgICAgICAgICAgcnJvdDEgPSBfdGhpcy5yYWRpYWxBeGlzQW5nbGUgKyBkYTtcblxuICAgICAgICAgICAgdmFyIHRyYW5zID0gc3RyVHJhbnNsYXRlKGN4LCBjeSkgKyBzdHJSb3RhdGUoLWRhKTtcbiAgICAgICAgICAgIHZhciB0cmFuczIgPSBzdHJUcmFuc2xhdGUoY3gsIGN5KSArIHN0clJvdGF0ZSgtcnJvdDEpO1xuXG4gICAgICAgICAgICBsYXllcnMuYmcuYXR0cigndHJhbnNmb3JtJywgdHJhbnMpO1xuICAgICAgICAgICAgbGF5ZXJzWydyYWRpYWwtZ3JpZCddLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zKTtcbiAgICAgICAgICAgIGxheWVyc1snYW5ndWxhci1saW5lJ10uc2VsZWN0KCdwYXRoJykuYXR0cigndHJhbnNmb3JtJywgdHJhbnMpO1xuICAgICAgICAgICAgbGF5ZXJzWydyYWRpYWwtYXhpcyddLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zMik7XG4gICAgICAgICAgICBsYXllcnNbJ3JhZGlhbC1saW5lJ10uc2VsZWN0KCdsaW5lJykuYXR0cigndHJhbnNmb3JtJywgdHJhbnMyKTtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZVJhZGlhbEF4aXNUaXRsZShmdWxsTGF5b3V0Tm93LCBwb2xhckxheW91dE5vdywgcnJvdDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgX3RoaXMuY2xpcFBhdGhzLmZvclRyYWNlcy5zZWxlY3QoJ3BhdGgnKS5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgIHN0clRyYW5zbGF0ZShjeHgsIGN5eSkgKyBzdHJSb3RhdGUoZGEpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gJ3VuLXJvdGF0ZScgbWFya2VyIGFuZCB0ZXh0IHBvaW50c1xuICAgICAgICBzY2F0dGVyUG9pbnRzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHh5ID0gRHJhd2luZy5nZXRUcmFuc2xhdGUoc2VsKTtcbiAgICAgICAgICAgIHNlbC5hdHRyKCd0cmFuc2Zvcm0nLCBzdHJUcmFuc2xhdGUoeHkueCwgeHkueSkgKyBzdHJSb3RhdGUoW2RhXSkpO1xuICAgICAgICB9KTtcbiAgICAgICAgc2NhdHRlclRleHRQb2ludHMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgdHggPSBzZWwuc2VsZWN0KCd0ZXh0Jyk7XG4gICAgICAgICAgICB2YXIgeHkgPSBEcmF3aW5nLmdldFRyYW5zbGF0ZShzZWwpO1xuICAgICAgICAgICAgLy8gTi5CIHJvdGF0ZSAtPiB0cmFuc2xhdGUgb3JkZXJpbmcgbWF0dGVyc1xuICAgICAgICAgICAgc2VsLmF0dHIoJ3RyYW5zZm9ybScsIHN0clJvdGF0ZShbZGEsIHR4LmF0dHIoJ3gnKSwgdHguYXR0cigneScpXSkgKyBzdHJUcmFuc2xhdGUoeHkueCwgeHkueSkpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyB1cGRhdGUgcm90YXRpb24gLT4gcmFuZ2UgLT4gX20sX2JcbiAgICAgICAgYW5ndWxhckF4aXMucm90YXRpb24gPSBMaWIubW9kSGFsZihyb3QxLCAzNjApO1xuICAgICAgICBhbmd1bGFyQXhpcy5zZXRHZW9tZXRyeSgpO1xuICAgICAgICBhbmd1bGFyQXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgICAgIGRvVGlja3NTaW5nbGUoZ2QsIGFuZ3VsYXJBeGlzLCB0cnVlKTtcblxuICAgICAgICBpZihfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlICYmICFMaWIuaXNGdWxsQ2lyY2xlKF90aGlzLnNlY3RvckluUmFkKSkge1xuICAgICAgICAgICAgc2NhdHRlclRyYWNlcy5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgX3RoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIHRyYWNlVHlwZSBpbiBfdGhpcy50cmFjZUhhc2gpIHtcbiAgICAgICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2VUeXBlLCAnZ2wnKSkge1xuICAgICAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YSA9IF90aGlzLnRyYWNlSGFzaFt0cmFjZVR5cGVdO1xuICAgICAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YVZpc2libGUgPSBMaWIuZmlsdGVyVmlzaWJsZShtb2R1bGVDYWxjRGF0YSk7XG4gICAgICAgICAgICAgICAgdmFyIF9tb2R1bGUgPSBtb2R1bGVDYWxjRGF0YVswXVswXS50cmFjZS5fbW9kdWxlO1xuICAgICAgICAgICAgICAgIF9tb2R1bGUucGxvdChnZCwgX3RoaXMsIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSwgcG9sYXJMYXlvdXROb3cpO1xuICAgICAgICAgICAgICAgIGlmKG1vZHVsZUNhbGNEYXRhVmlzaWJsZS5sZW5ndGgpIGhhc1JlZ2wgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzUmVnbCkge1xuICAgICAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgICAgIHJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG9uZUZuKCkge1xuICAgICAgICBzY2F0dGVyVGV4dFBvaW50cy5zZWxlY3QoJ3RleHQnKS5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG4gICAgICAgIHVwZGF0ZU9ialtfdGhpcy5pZCArICcuYW5ndWxhcmF4aXMucm90YXRpb24nXSA9IHJvdDE7XG5cbiAgICAgICAgaWYoX3RoaXMudmFuZ2xlcykge1xuICAgICAgICAgICAgdXBkYXRlT2JqW190aGlzLmlkICsgJy5yYWRpYWxheGlzLmFuZ2xlJ10gPSBycm90MTtcbiAgICAgICAgfVxuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIHVwZGF0ZU9iaik7XG4gICAgfVxuXG4gICAgZHJhZ09wdHMucHJlcEZuID0gZnVuY3Rpb24oZXZ0LCBzdGFydFgsIHN0YXJ0WSkge1xuICAgICAgICB2YXIgcG9sYXJMYXlvdXROb3cgPSBmdWxsTGF5b3V0W190aGlzLmlkXTtcbiAgICAgICAgcm90MCA9IHBvbGFyTGF5b3V0Tm93LmFuZ3VsYXJheGlzLnJvdGF0aW9uO1xuXG4gICAgICAgIHZhciBiYm94ID0gYW5ndWxhckRyYWcuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHgwID0gc3RhcnRYIC0gYmJveC5sZWZ0O1xuICAgICAgICB5MCA9IHN0YXJ0WSAtIGJib3gudG9wO1xuICAgICAgICBhMCA9IHh5MmEoeDAsIHkwKTtcblxuICAgICAgICBkcmFnT3B0cy5tb3ZlRm4gPSBtb3ZlRm47XG4gICAgICAgIGRyYWdPcHRzLmRvbmVGbiA9IGRvbmVGbjtcblxuICAgICAgICBjbGVhclNlbGVjdChmdWxsTGF5b3V0Ll96b29tbGF5ZXIpO1xuICAgIH07XG5cbiAgICAvLyBJIGRvbid0IHdoYXQgd2Ugc2hvdWxkIGRvIGluIHRoaXMgY2FzZSwgc2tpcCB3ZSBub3dcbiAgICBpZihfdGhpcy52YW5nbGVzICYmICFMaWIuaXNGdWxsQ2lyY2xlKF90aGlzLnNlY3RvckluUmFkKSkge1xuICAgICAgICBkcmFnT3B0cy5wcmVwRm4gPSBMaWIubm9vcDtcbiAgICAgICAgc2V0Q3Vyc29yKGQzLnNlbGVjdChhbmd1bGFyRHJhZyksIG51bGwpO1xuICAgIH1cblxuICAgIGRyYWdFbGVtZW50LmluaXQoZHJhZ09wdHMpO1xufTtcblxucHJvdG8uaXNQdEluc2lkZSA9IGZ1bmN0aW9uKGQpIHtcbiAgICB2YXIgc2VjdG9ySW5SYWQgPSB0aGlzLnNlY3RvckluUmFkO1xuICAgIHZhciB2YW5nbGVzID0gdGhpcy52YW5nbGVzO1xuICAgIHZhciB0aGV0YWcgPSB0aGlzLmFuZ3VsYXJBeGlzLmMyZyhkLnRoZXRhKTtcbiAgICB2YXIgcmFkaWFsQXhpcyA9IHRoaXMucmFkaWFsQXhpcztcbiAgICB2YXIgciA9IHJhZGlhbEF4aXMuYzJsKGQucik7XG4gICAgdmFyIHJsID0gcmFkaWFsQXhpcy5fcmw7XG5cbiAgICB2YXIgZm4gPSB2YW5nbGVzID8gaGVscGVycy5pc1B0SW5zaWRlUG9seWdvbiA6IExpYi5pc1B0SW5zaWRlU2VjdG9yO1xuICAgIHJldHVybiBmbihyLCB0aGV0YWcsIHJsLCBzZWN0b3JJblJhZCwgdmFuZ2xlcyk7XG59O1xuXG5wcm90by5wYXRoQXJjID0gZnVuY3Rpb24ocikge1xuICAgIHZhciBzZWN0b3JJblJhZCA9IHRoaXMuc2VjdG9ySW5SYWQ7XG4gICAgdmFyIHZhbmdsZXMgPSB0aGlzLnZhbmdsZXM7XG4gICAgdmFyIGZuID0gdmFuZ2xlcyA/IGhlbHBlcnMucGF0aFBvbHlnb24gOiBMaWIucGF0aEFyYztcbiAgICByZXR1cm4gZm4ociwgc2VjdG9ySW5SYWRbMF0sIHNlY3RvckluUmFkWzFdLCB2YW5nbGVzKTtcbn07XG5cbnByb3RvLnBhdGhTZWN0b3IgPSBmdW5jdGlvbihyKSB7XG4gICAgdmFyIHNlY3RvckluUmFkID0gdGhpcy5zZWN0b3JJblJhZDtcbiAgICB2YXIgdmFuZ2xlcyA9IHRoaXMudmFuZ2xlcztcbiAgICB2YXIgZm4gPSB2YW5nbGVzID8gaGVscGVycy5wYXRoUG9seWdvbiA6IExpYi5wYXRoU2VjdG9yO1xuICAgIHJldHVybiBmbihyLCBzZWN0b3JJblJhZFswXSwgc2VjdG9ySW5SYWRbMV0sIHZhbmdsZXMpO1xufTtcblxucHJvdG8ucGF0aEFubnVsdXMgPSBmdW5jdGlvbihyMCwgcjEpIHtcbiAgICB2YXIgc2VjdG9ySW5SYWQgPSB0aGlzLnNlY3RvckluUmFkO1xuICAgIHZhciB2YW5nbGVzID0gdGhpcy52YW5nbGVzO1xuICAgIHZhciBmbiA9IHZhbmdsZXMgPyBoZWxwZXJzLnBhdGhQb2x5Z29uQW5udWx1cyA6IExpYi5wYXRoQW5udWx1cztcbiAgICByZXR1cm4gZm4ocjAsIHIxLCBzZWN0b3JJblJhZFswXSwgc2VjdG9ySW5SYWRbMV0sIHZhbmdsZXMpO1xufTtcblxucHJvdG8ucGF0aFN1YnBsb3QgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcjAgPSB0aGlzLmlubmVyUmFkaXVzO1xuICAgIHZhciByMSA9IHRoaXMucmFkaXVzO1xuICAgIHJldHVybiByMCA/IHRoaXMucGF0aEFubnVsdXMocjAsIHIxKSA6IHRoaXMucGF0aFNlY3RvcihyMSk7XG59O1xuXG5wcm90by5maWxsVmlld0luaXRpYWxLZXkgPSBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgIGlmKCEoa2V5IGluIHRoaXMudmlld0luaXRpYWwpKSB7XG4gICAgICAgIHRoaXMudmlld0luaXRpYWxba2V5XSA9IHZhbDtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBzdHJUaWNrTGF5b3V0KGF4TGF5b3V0KSB7XG4gICAgdmFyIG91dCA9IGF4TGF5b3V0LnRpY2tzICsgU3RyaW5nKGF4TGF5b3V0LnRpY2tsZW4pICsgU3RyaW5nKGF4TGF5b3V0LnNob3d0aWNrbGFiZWxzKTtcbiAgICBpZignc2lkZScgaW4gYXhMYXlvdXQpIG91dCArPSBheExheW91dC5zaWRlO1xuICAgIHJldHVybiBvdXQ7XG59XG5cbi8vIEZpbmRzIHRoZSBib3VuZGluZyBib3ggb2YgYSBnaXZlbiBjaXJjbGUgc2VjdG9yLFxuLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly9tYXRoLnN0YWNrZXhjaGFuZ2UuY29tL3EvMTg1MjcwM1xuLy9cbi8vIGFzc3VtZXM6XG4vLyAtIHNlY3RvclswXSA8IHNlY3RvclsxXVxuLy8gLSBjb3VudGVyY2xvY2t3aXNlIHJvdGF0aW9uXG5mdW5jdGlvbiBjb21wdXRlU2VjdG9yQkJveChzZWN0b3IpIHtcbiAgICB2YXIgczAgPSBzZWN0b3JbMF07XG4gICAgdmFyIHMxID0gc2VjdG9yWzFdO1xuICAgIHZhciBhcmMgPSBzMSAtIHMwO1xuICAgIHZhciBhMCA9IG1vZChzMCwgMzYwKTtcbiAgICB2YXIgYTEgPSBhMCArIGFyYztcblxuICAgIHZhciBheDAgPSBNYXRoLmNvcyhkZWcycmFkKGEwKSk7XG4gICAgdmFyIGF5MCA9IE1hdGguc2luKGRlZzJyYWQoYTApKTtcbiAgICB2YXIgYXgxID0gTWF0aC5jb3MoZGVnMnJhZChhMSkpO1xuICAgIHZhciBheTEgPSBNYXRoLnNpbihkZWcycmFkKGExKSk7XG5cbiAgICB2YXIgeDAsIHkwLCB4MSwgeTE7XG5cbiAgICBpZigoYTAgPD0gOTAgJiYgYTEgPj0gOTApIHx8IChhMCA+IDkwICYmIGExID49IDQ1MCkpIHtcbiAgICAgICAgeTEgPSAxO1xuICAgIH0gZWxzZSBpZihheTAgPD0gMCAmJiBheTEgPD0gMCkge1xuICAgICAgICB5MSA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgeTEgPSBNYXRoLm1heChheTAsIGF5MSk7XG4gICAgfVxuXG4gICAgaWYoKGEwIDw9IDE4MCAmJiBhMSA+PSAxODApIHx8IChhMCA+IDE4MCAmJiBhMSA+PSA1NDApKSB7XG4gICAgICAgIHgwID0gLTE7XG4gICAgfSBlbHNlIGlmKGF4MCA+PSAwICYmIGF4MSA+PSAwKSB7XG4gICAgICAgIHgwID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB4MCA9IE1hdGgubWluKGF4MCwgYXgxKTtcbiAgICB9XG5cbiAgICBpZigoYTAgPD0gMjcwICYmIGExID49IDI3MCkgfHwgKGEwID4gMjcwICYmIGExID49IDYzMCkpIHtcbiAgICAgICAgeTAgPSAtMTtcbiAgICB9IGVsc2UgaWYoYXkwID49IDAgJiYgYXkxID49IDApIHtcbiAgICAgICAgeTAgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHkwID0gTWF0aC5taW4oYXkwLCBheTEpO1xuICAgIH1cblxuICAgIGlmKGExID49IDM2MCkge1xuICAgICAgICB4MSA9IDE7XG4gICAgfSBlbHNlIGlmKGF4MCA8PSAwICYmIGF4MSA8PSAwKSB7XG4gICAgICAgIHgxID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB4MSA9IE1hdGgubWF4KGF4MCwgYXgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW3gwLCB5MCwgeDEsIHkxXTtcbn1cblxuZnVuY3Rpb24gc25hcFRvVmVydGV4QW5nbGUoYSwgdmFuZ2xlcykge1xuICAgIHZhciBmbiA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIExpYi5hbmdsZURpc3QoYSwgdik7IH07XG4gICAgdmFyIGluZCA9IExpYi5maW5kSW5kZXhPZk1pbih2YW5nbGVzLCBmbik7XG4gICAgcmV0dXJuIHZhbmdsZXNbaW5kXTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlRWxlbWVudChzZWwsIHNob3dBdHRyLCBhdHRycykge1xuICAgIGlmKHNob3dBdHRyKSB7XG4gICAgICAgIHNlbC5hdHRyKCdkaXNwbGF5JywgbnVsbCk7XG4gICAgICAgIHNlbC5hdHRyKGF0dHJzKTtcbiAgICB9IGVsc2UgaWYoc2VsKSB7XG4gICAgICAgIHNlbC5hdHRyKCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlbDtcbn1cblxuZnVuY3Rpb24gc3RyVHJhbnNsYXRlKHgsIHkpIHtcbiAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgeCArICcsJyArIHkgKyAnKSc7XG59XG5cbmZ1bmN0aW9uIHN0clJvdGF0ZShhbmdsZSkge1xuICAgIHJldHVybiAncm90YXRlKCcgKyBhbmdsZSArICcpJztcbn1cblxuLy8gYmVjYXVzZSBNYXRoLnNpZ24oTWF0aC5jb3MoTWF0aC5QSSAvIDIpKSA9PT0gMVxuLy8gb2ggamF2YXNjcmlwdCA7KVxuZnVuY3Rpb24gc2lnbih2KSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKHYpIDwgMWUtMTAgPyAwIDpcbiAgICAgICAgdiA+IDAgPyAxIDogLTE7XG59XG5cbmZ1bmN0aW9uIHNpZ25Db3Modikge1xuICAgIHJldHVybiBzaWduKE1hdGguY29zKHYpKTtcbn1cblxuZnVuY3Rpb24gc2lnblNpbih2KSB7XG4gICAgcmV0dXJuIHNpZ24oTWF0aC5zaW4odikpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgc2V0Q29udmVydENhcnRlc2lhbiA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xuXG52YXIgZGVnMnJhZCA9IExpYi5kZWcycmFkO1xudmFyIHJhZDJkZWcgPSBMaWIucmFkMmRlZztcblxuLyoqXG4gKiBzZXRDb252ZXJ0IGZvciBwb2xhciBheGVzIVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBheFxuICogICBheGlzIGluIHF1ZXN0aW9uICh3b3JrcyBmb3IgYm90aCByYWRpYWwgYW5kIGFuZ3VsYXIgYXhlcylcbiAqIEBwYXJhbSB7b2JqZWN0fSBwb2xhckxheW91dFxuICogICBmdWxsIHBvbGFyIGxheW91dCBvZiB0aGUgc3VicGxvdCBhc3NvY2lhdGVkIHdpdGggJ2F4J1xuICogQHBhcmFtIHtvYmplY3R9IGZ1bGxMYXlvdXRcbiAqICAgZnVsbCBsYXlvdXRcbiAqXG4gKiBIZXJlLCByZXVzZSBzb21lIG9mIHRoZSBDYXJ0ZXNpYW4gc2V0Q29udmVydCBsb2dpYyxcbiAqIGJ1dCB3ZSBtdXN0IGV4dGVuZCBzb21lIG9mIGl0LCBhcyBib3RoIHJhZGlhbCBhbmQgYW5ndWxhciBheGVzXG4gKiBkb24ndCBoYXZlIGRvbWFpbnMgYW5kIGFuZ3VsYXIgYXhlcyBkb24ndCBoYXZlIF90cnVlXyByYW5nZXMuXG4gKlxuICogTW9yZW92ZXIsIHdlIGludHJvZHVjZSB0d28gbmV3IGNvb3JkaW5hdGUgc3lzdGVtczpcbiAqIC0gJ2cnIGZvciBnZW9tZXRyaWMgY29vcmRpbmF0ZXMgYW5kXG4gKiAtICd0JyBmb3IgYW5ndWxhciB0aWNrc1xuICpcbiAqIFJhZGlhbCBheGlzIGNvb3JkaW5hdGUgc3lzdGVtczpcbiAqIC0gZCwgYyBhbmQgbDogc2FtZSBhcyBmb3IgY2FydGVzaWFuIGF4ZXNcbiAqIC0gZzogbGlrZSBjYWxjZGF0YSBidXQgdHJhbnNsYXRlZCBhYm91dCBgcmFkaWFsYXhpcy5yYW5nZVswXWAgJiBgcG9sYXIuaG9sZWBcbiAqXG4gKiBBbmd1bGFyIGF4aXMgY29vcmRpbmF0ZSBzeXN0ZW1zOlxuICogLSBkOiBkYXRhLCBpbiB3aGF0ZXZlciBmb3JtIGl0J3MgcHJvdmlkZWRcbiAqIC0gYzogY2FsY2RhdGEsIHR1cm5lZCBpbnRvIHJhZGlhbnMgKGZvciBsaW5lYXIgYXhlcylcbiAqICAgICAgb3IgY2F0ZWdvcnkgaW5kaWNlcyAoY2F0ZWdvcnkgYXhlcylcbiAqIC0gdDogdGljayBjYWxjZGF0YSwganVzdCBsaWtlICdjJyBidXQgaW4gZGVncmVlcyBmb3IgbGluZWFyIGF4ZXNcbiAqIC0gZzogZ2VvbWV0cmljIGNhbGNkYXRhLCByYWRpYW5zIGNvb3JkaW5hdGVzIHRoYXQgdGFrZSBpbnRvIGFjY291bnRcbiAqICAgICAgYXhpcyByb3RhdGlvbiBhbmQgZGlyZWN0aW9uXG4gKlxuICogVGhlbiwgJ2cnZW9tZXRyaWMgZGF0YSBpcyByZWFkeSB0byBiZSBjb252ZXJ0ZWQgdG8gKHgseSkuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2V0Q29udmVydChheCwgcG9sYXJMYXlvdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICBzZXRDb252ZXJ0Q2FydGVzaWFuKGF4LCBmdWxsTGF5b3V0KTtcblxuICAgIHN3aXRjaChheC5faWQpIHtcbiAgICAgICAgY2FzZSAneCc6XG4gICAgICAgIGNhc2UgJ3JhZGlhbGF4aXMnOlxuICAgICAgICAgICAgc2V0Q29udmVydFJhZGlhbChheCwgcG9sYXJMYXlvdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2FuZ3VsYXJheGlzJzpcbiAgICAgICAgICAgIHNldENvbnZlcnRBbmd1bGFyKGF4LCBwb2xhckxheW91dCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBzZXRDb252ZXJ0UmFkaWFsKGF4LCBwb2xhckxheW91dCkge1xuICAgIHZhciBzdWJwbG90ID0gcG9sYXJMYXlvdXQuX3N1YnBsb3Q7XG5cbiAgICBheC5zZXRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmwwID0gYXguX3JsWzBdO1xuICAgICAgICB2YXIgcmwxID0gYXguX3JsWzFdO1xuXG4gICAgICAgIHZhciBiID0gc3VicGxvdC5pbm5lclJhZGl1cztcbiAgICAgICAgdmFyIG0gPSAoc3VicGxvdC5yYWRpdXMgLSBiKSAvIChybDEgLSBybDApO1xuICAgICAgICB2YXIgYjIgPSBiIC8gbTtcblxuICAgICAgICB2YXIgckZpbHRlciA9IHJsMCA+IHJsMSA/XG4gICAgICAgICAgICBmdW5jdGlvbih2KSB7IHJldHVybiB2IDw9IDA7IH0gOlxuICAgICAgICAgICAgZnVuY3Rpb24odikgeyByZXR1cm4gdiA+PSAwOyB9O1xuXG4gICAgICAgIGF4LmMyZyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHZhciByID0gYXguYzJsKHYpIC0gcmwwO1xuICAgICAgICAgICAgcmV0dXJuIChyRmlsdGVyKHIpID8gciA6IDApICsgYjI7XG4gICAgICAgIH07XG5cbiAgICAgICAgYXguZzJjID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuIGF4LmwyYyh2ICsgcmwwIC0gYjIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGF4LmcycCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYgKiBtOyB9O1xuICAgICAgICBheC5jMnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5nMnAoYXguYzJnKHYpKTsgfTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB0b1JhZGlhbnModiwgdW5pdCkge1xuICAgIHJldHVybiB1bml0ID09PSAnZGVncmVlcycgPyBkZWcycmFkKHYpIDogdjtcbn1cblxuZnVuY3Rpb24gZnJvbVJhZGlhbnModiwgdW5pdCkge1xuICAgIHJldHVybiB1bml0ID09PSAnZGVncmVlcycgPyByYWQyZGVnKHYpIDogdjtcbn1cblxuZnVuY3Rpb24gc2V0Q29udmVydEFuZ3VsYXIoYXgsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIGF4VHlwZSA9IGF4LnR5cGU7XG5cbiAgICBpZihheFR5cGUgPT09ICdsaW5lYXInKSB7XG4gICAgICAgIHZhciBfZDJjID0gYXguZDJjO1xuICAgICAgICB2YXIgX2MyZCA9IGF4LmMyZDtcblxuICAgICAgICBheC5kMmMgPSBmdW5jdGlvbih2LCB1bml0KSB7IHJldHVybiB0b1JhZGlhbnMoX2QyYyh2KSwgdW5pdCk7IH07XG4gICAgICAgIGF4LmMyZCA9IGZ1bmN0aW9uKHYsIHVuaXQpIHsgcmV0dXJuIF9jMmQoZnJvbVJhZGlhbnModiwgdW5pdCkpOyB9O1xuICAgIH1cblxuICAgIC8vIG92ZXJyaWRlIG1ha2VDYWxjZGF0YSB0byBoYW5kbGUgdGhldGF1bml0IGFuZCBzcGVjaWFsIHRoZXRhMC9kdGhldGEgbG9naWNcbiAgICBheC5tYWtlQ2FsY2RhdGEgPSBmdW5jdGlvbih0cmFjZSwgY29vcmQpIHtcbiAgICAgICAgdmFyIGFycmF5SW4gPSB0cmFjZVtjb29yZF07XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgICAgICB2YXIgYXJyYXlPdXQsIGk7XG5cbiAgICAgICAgdmFyIF9kMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5kMmModiwgdHJhY2UudGhldGF1bml0KTsgfTtcblxuICAgICAgICBpZihhcnJheUluKSB7XG4gICAgICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KGFycmF5SW4pICYmIGF4VHlwZSA9PT0gJ2xpbmVhcicpIHtcbiAgICAgICAgICAgICAgICBpZihsZW4gPT09IGFycmF5SW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheUluO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihhcnJheUluLnN1YmFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheUluLnN1YmFycmF5KDAsIGxlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dFtpXSA9IF9kMmMoYXJyYXlJbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgY29vcmQwID0gY29vcmQgKyAnMCc7XG4gICAgICAgICAgICB2YXIgZGNvb3JkID0gJ2QnICsgY29vcmQ7XG4gICAgICAgICAgICB2YXIgdjAgPSAoY29vcmQwIGluIHRyYWNlKSA/IF9kMmModHJhY2VbY29vcmQwXSkgOiAwO1xuICAgICAgICAgICAgdmFyIGR2ID0gKHRyYWNlW2Rjb29yZF0pID8gX2QyYyh0cmFjZVtkY29vcmRdKSA6IChheC5wZXJpb2QgfHwgMiAqIE1hdGguUEkpIC8gbGVuO1xuXG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dFtpXSA9IHYwICsgaSAqIGR2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFycmF5T3V0O1xuICAgIH07XG5cbiAgICAvLyBOLkIuIHdlIG1vY2sgdGhlIGF4aXMgJ3JhbmdlJyBoZXJlXG4gICAgYXguc2V0R2VvbWV0cnkgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHNlY3RvciA9IHBvbGFyTGF5b3V0LnNlY3RvcjtcbiAgICAgICAgdmFyIHNlY3RvckluUmFkID0gc2VjdG9yLm1hcChkZWcycmFkKTtcbiAgICAgICAgdmFyIGRpciA9IHtjbG9ja3dpc2U6IC0xLCBjb3VudGVyY2xvY2t3aXNlOiAxfVtheC5kaXJlY3Rpb25dO1xuICAgICAgICB2YXIgcm90ID0gZGVnMnJhZChheC5yb3RhdGlvbik7XG5cbiAgICAgICAgdmFyIHJhZDJnID0gZnVuY3Rpb24odikgeyByZXR1cm4gZGlyICogdiArIHJvdDsgfTtcbiAgICAgICAgdmFyIGcycmFkID0gZnVuY3Rpb24odikgeyByZXR1cm4gKHYgLSByb3QpIC8gZGlyOyB9O1xuXG4gICAgICAgIHZhciByYWQyYywgYzJyYWQ7XG4gICAgICAgIHZhciByYWQydCwgdDJyYWQ7XG5cbiAgICAgICAgc3dpdGNoKGF4VHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnbGluZWFyJzpcbiAgICAgICAgICAgICAgICBjMnJhZCA9IHJhZDJjID0gTGliLmlkZW50aXR5O1xuICAgICAgICAgICAgICAgIHQycmFkID0gZGVnMnJhZDtcbiAgICAgICAgICAgICAgICByYWQydCA9IHJhZDJkZWc7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGFuZ3VsYXIgcmFuZ2UgaW4gZGVncmVlcyB0byBtYWtlIGF1dG8tdGljayBjb21wdXRhdGlvbiBjbGVhbmVyLFxuICAgICAgICAgICAgICAgIC8vIGNoYW5naW5nIHJvdGF0aW9uL2RpcmVjdGlvbiBzaG91bGQgbm90IGFmZmVjdCB0aGUgYW5ndWxhciB0aWNrIHZhbHVlLlxuICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gTGliLmlzRnVsbENpcmNsZShzZWN0b3JJblJhZCkgP1xuICAgICAgICAgICAgICAgICAgICBbc2VjdG9yWzBdLCBzZWN0b3JbMF0gKyAzNjBdIDpcbiAgICAgICAgICAgICAgICAgICAgc2VjdG9ySW5SYWQubWFwKGcycmFkKS5tYXAocmFkMmRlZyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2NhdGVnb3J5JzpcbiAgICAgICAgICAgICAgICB2YXIgY2F0TGVuID0gYXguX2NhdGVnb3JpZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBfcGVyaW9kID0gYXgucGVyaW9kID8gTWF0aC5tYXgoYXgucGVyaW9kLCBjYXRMZW4pIDogY2F0TGVuO1xuXG4gICAgICAgICAgICAgICAgYzJyYWQgPSB0MnJhZCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYgKiAyICogTWF0aC5QSSAvIF9wZXJpb2Q7IH07XG4gICAgICAgICAgICAgICAgcmFkMmMgPSByYWQydCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYgKiBfcGVyaW9kIC8gTWF0aC5QSSAvIDI7IH07XG5cbiAgICAgICAgICAgICAgICBheC5yYW5nZSA9IFswLCBfcGVyaW9kXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGF4LmMyZyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHJhZDJnKGMycmFkKHYpKTsgfTtcbiAgICAgICAgYXguZzJjID0gZnVuY3Rpb24odikgeyByZXR1cm4gcmFkMmMoZzJyYWQodikpOyB9O1xuXG4gICAgICAgIGF4LnQyZyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHJhZDJnKHQycmFkKHYpKTsgfTtcbiAgICAgICAgYXguZzJ0ID0gZnVuY3Rpb24odikgeyByZXR1cm4gcmFkMnQoZzJyYWQodikpOyB9O1xuICAgIH07XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIFRlbXBsYXRlID0gcmVxdWlyZSgnLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gcmVxdWlyZSgnLi9kb21haW4nKS5kZWZhdWx0cztcblxuXG4vKipcbiAqIEZpbmQgYW5kIHN1cHBseSBkZWZhdWx0cyB0byBhbGwgc3VicGxvdHMgb2YgYSBnaXZlbiB0eXBlXG4gKiBUaGlzIGhhbmRsZXMgc3VicGxvdHMgdGhhdCBhcmUgY29udGFpbmVkIHdpdGhpbiBvbmUgY29udGFpbmVyIC0gc29cbiAqIGdsM2QsIGdlbywgdGVybmFyeS4uLiBidXQgbm90IDJkIGF4ZXMgd2hpY2ggaGF2ZSBzZXBhcmF0ZSB4IGFuZCB5IGF4ZXNcbiAqIGZpbmRzIHN1YnBsb3RzLCBjb2VyY2VzIHRoZWlyIGBkb21haW5gIGF0dHJpYnV0ZXMsIHRoZW4gY2FsbHMgdGhlXG4gKiBnaXZlbiBoYW5kbGVEZWZhdWx0cyBmdW5jdGlvbiB0byBmaWxsIGluIGV2ZXJ5dGhpbmcgZWxzZS5cbiAqXG4gKiBsYXlvdXRJbjogdGhlIGNvbXBsZXRlIHVzZXItc3VwcGxpZWQgaW5wdXQgbGF5b3V0XG4gKiBsYXlvdXRPdXQ6IHRoZSBjb21wbGV0ZSBmaW5pc2hlZCBsYXlvdXRcbiAqIGZ1bGxEYXRhOiB0aGUgZmluaXNoZWQgZGF0YSBhcnJheSwgdXNlZCBvbmx5IHRvIGZpbmQgc3VicGxvdHNcbiAqIG9wdHM6IHtcbiAqICB0eXBlOiBzdWJwbG90IHR5cGUgc3RyaW5nXG4gKiAgYXR0cmlidXRlczogc3VicGxvdCBhdHRyaWJ1dGVzIG9iamVjdFxuICogIHBhcnRpdGlvbjogJ3gnIG9yICd5Jywgd2hpY2ggZGlyZWN0aW9uIHRvIGRpdmlkZSBkb21haW4gc3BhY2UgYnkgZGVmYXVsdFxuICogICAgICAoZGVmYXVsdCAneCcsIGllIHNpZGUtYnktc2lkZSBzdWJwbG90cylcbiAqICAgICAgVE9ETzogdGhpcyBvcHRpb24gaXMgb25seSBoZXJlIGJlY2F1c2UgM0QgYW5kIGdlbyBtYWRlIG9wcG9zaXRlXG4gKiAgICAgIGNob2ljZXMgaW4gdGhpcyByZWdhcmQgcHJldmlvdXNseSBhbmQgSSBkaWRuJ3Qgd2FudCB0byBjaGFuZ2UgaXQuXG4gKiAgICAgIEluc3RlYWQgd2Ugc2hvdWxkIGRvOlxuICogICAgICAtIHNvbWV0aGluZyBjb25zaXN0ZW50XG4gKiAgICAgIC0gc29tZXRoaW5nIG1vcmUgc3F1YXJlICg0IGN1dHMgMngyLCA1LzYgY3V0cyAyeDMsIGV0Yy4pXG4gKiAgICAgIC0gc29tZXRoaW5nIHRoYXQgaW5jbHVkZXMgYWxsIHN1YnBsb3QgdHlwZXMgaW4gb25lIGFycmFuZ2VtZW50LFxuICogICAgICAgIG5vdyB0aGF0IHdlIGNhbiBoYXZlIHRoZW0gdG9nZXRoZXIhXG4gKiAgaGFuZGxlRGVmYXVsdHM6IGZ1bmN0aW9uIG9mIChzdWJwbG90TGF5b3V0SW4sIHN1YnBsb3RMYXlvdXRPdXQsIGNvZXJjZSwgb3B0cylcbiAqICAgICAgdGhpcyBvcHRzIG9iamVjdCBpcyBwYXNzZWQgdGhyb3VnaCB0byBoYW5kbGVEZWZhdWx0cywgc28gYXR0YWNoIGFueVxuICogICAgICBhZGRpdGlvbmFsIGl0ZW1zIG5lZWRlZCBieSB0aGlzIGZ1bmN0aW9uIGhlcmUgYXMgd2VsbFxuICogfVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVN1YnBsb3REZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSwgb3B0cykge1xuICAgIHZhciBzdWJwbG90VHlwZSA9IG9wdHMudHlwZTtcbiAgICB2YXIgc3VicGxvdEF0dHJpYnV0ZXMgPSBvcHRzLmF0dHJpYnV0ZXM7XG4gICAgdmFyIGhhbmRsZURlZmF1bHRzID0gb3B0cy5oYW5kbGVEZWZhdWx0cztcbiAgICB2YXIgcGFydGl0aW9uID0gb3B0cy5wYXJ0aXRpb24gfHwgJ3gnO1xuXG4gICAgdmFyIGlkcyA9IGxheW91dE91dC5fc3VicGxvdHNbc3VicGxvdFR5cGVdO1xuICAgIHZhciBpZHNMZW5ndGggPSBpZHMubGVuZ3RoO1xuXG4gICAgdmFyIGJhc2VJZCA9IGlkc0xlbmd0aCAmJiBpZHNbMF0ucmVwbGFjZSgvXFxkKyQvLCAnJyk7XG5cbiAgICB2YXIgc3VicGxvdExheW91dEluLCBzdWJwbG90TGF5b3V0T3V0O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2Uoc3VicGxvdExheW91dEluLCBzdWJwbG90TGF5b3V0T3V0LCBzdWJwbG90QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGlkc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZCA9IGlkc1tpXTtcblxuICAgICAgICAvLyB0ZXJuYXJ5IHRyYWNlcyBnZXQgYSBsYXlvdXQgdGVybmFyeSBmb3IgZnJlZSFcbiAgICAgICAgaWYobGF5b3V0SW5baWRdKSBzdWJwbG90TGF5b3V0SW4gPSBsYXlvdXRJbltpZF07XG4gICAgICAgIGVsc2Ugc3VicGxvdExheW91dEluID0gbGF5b3V0SW5baWRdID0ge307XG5cbiAgICAgICAgc3VicGxvdExheW91dE91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihsYXlvdXRPdXQsIGlkLCBiYXNlSWQpO1xuXG4gICAgICAgIHZhciBkZmx0RG9tYWlucyA9IHt9O1xuICAgICAgICBkZmx0RG9tYWluc1twYXJ0aXRpb25dID0gW2kgLyBpZHNMZW5ndGgsIChpICsgMSkgLyBpZHNMZW5ndGhdO1xuICAgICAgICBoYW5kbGVEb21haW5EZWZhdWx0cyhzdWJwbG90TGF5b3V0T3V0LCBsYXlvdXRPdXQsIGNvZXJjZSwgZGZsdERvbWFpbnMpO1xuXG4gICAgICAgIG9wdHMuaWQgPSBpZDtcbiAgICAgICAgaGFuZGxlRGVmYXVsdHMoc3VicGxvdExheW91dEluLCBzdWJwbG90TGF5b3V0T3V0LCBjb2VyY2UsIG9wdHMpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFRlcm5hcnkgPSByZXF1aXJlKCcuL3Rlcm5hcnknKTtcblxudmFyIGdldFN1YnBsb3RDYWxjRGF0YSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dldF9kYXRhJykuZ2V0U3VicGxvdENhbGNEYXRhO1xudmFyIGNvdW50ZXJSZWdleCA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmNvdW50ZXJSZWdleDtcbnZhciBURVJOQVJZID0gJ3Rlcm5hcnknO1xuXG5leHBvcnRzLm5hbWUgPSBURVJOQVJZO1xuXG52YXIgYXR0ciA9IGV4cG9ydHMuYXR0ciA9ICdzdWJwbG90JztcblxuZXhwb3J0cy5pZFJvb3QgPSBURVJOQVJZO1xuXG5leHBvcnRzLmlkUmVnZXggPSBleHBvcnRzLmF0dHJSZWdleCA9IGNvdW50ZXJSZWdleChURVJOQVJZKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBleHBvcnRzLmF0dHJpYnV0ZXMgPSB7fTtcbmF0dHJpYnV0ZXNbYXR0cl0gPSB7XG4gICAgdmFsVHlwZTogJ3N1YnBsb3RpZCcsXG4gICAgXG4gICAgZGZsdDogJ3Rlcm5hcnknLFxuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgXG59O1xuXG5leHBvcnRzLmxheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSByZXF1aXJlKCcuL2xheW91dF9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbiBwbG90VGVybmFyeShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIHRlcm5hcnlJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1tURVJOQVJZXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0ZXJuYXJ5SWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXJuYXJ5SWQgPSB0ZXJuYXJ5SWRzW2ldLFxuICAgICAgICAgICAgdGVybmFyeUNhbGNEYXRhID0gZ2V0U3VicGxvdENhbGNEYXRhKGNhbGNEYXRhLCBURVJOQVJZLCB0ZXJuYXJ5SWQpLFxuICAgICAgICAgICAgdGVybmFyeSA9IGZ1bGxMYXlvdXRbdGVybmFyeUlkXS5fc3VicGxvdDtcblxuICAgICAgICAvLyBJZiB0ZXJuYXJ5IGlzIG5vdCBpbnN0YW50aWF0ZWQsIGNyZWF0ZSBvbmUhXG4gICAgICAgIGlmKCF0ZXJuYXJ5KSB7XG4gICAgICAgICAgICB0ZXJuYXJ5ID0gbmV3IFRlcm5hcnkoe1xuICAgICAgICAgICAgICAgIGlkOiB0ZXJuYXJ5SWQsXG4gICAgICAgICAgICAgICAgZ3JhcGhEaXY6IGdkLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5fdGVybmFyeWxheWVyLm5vZGUoKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBmdWxsTGF5b3V0W3Rlcm5hcnlJZF0uX3N1YnBsb3QgPSB0ZXJuYXJ5O1xuICAgICAgICB9XG5cbiAgICAgICAgdGVybmFyeS5wbG90KHRlcm5hcnlDYWxjRGF0YSwgZnVsbExheW91dCwgZ2QuX3Byb21pc2VzKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLmNsZWFuID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIG9sZFRlcm5hcnlLZXlzID0gb2xkRnVsbExheW91dC5fc3VicGxvdHNbVEVSTkFSWV0gfHwgW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkVGVybmFyeUtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9sZFRlcm5hcnlLZXkgPSBvbGRUZXJuYXJ5S2V5c1tpXTtcbiAgICAgICAgdmFyIG9sZFRlcm5hcnkgPSBvbGRGdWxsTGF5b3V0W29sZFRlcm5hcnlLZXldLl9zdWJwbG90O1xuXG4gICAgICAgIGlmKCFuZXdGdWxsTGF5b3V0W29sZFRlcm5hcnlLZXldICYmICEhb2xkVGVybmFyeSkge1xuICAgICAgICAgICAgb2xkVGVybmFyeS5wbG90Q29udGFpbmVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkVGVybmFyeS5jbGlwRGVmLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkVGVybmFyeS5jbGlwRGVmUmVsYXRpdmUucmVtb3ZlKCk7XG4gICAgICAgICAgICBvbGRUZXJuYXJ5LmxheWVyc1snYS10aXRsZSddLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkVGVybmFyeS5sYXllcnNbJ2ItdGl0bGUnXS5yZW1vdmUoKTtcbiAgICAgICAgICAgIG9sZFRlcm5hcnkubGF5ZXJzWydjLXRpdGxlJ10ucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBheGVzQXR0cnMgPSByZXF1aXJlKCcuLi9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHRlcm5hcnlBeGVzQXR0cnMgPSB7XG4gICAgdGl0bGU6IGF4ZXNBdHRycy50aXRsZSxcbiAgICB0aXRsZWZvbnQ6IGF4ZXNBdHRycy50aXRsZWZvbnQsXG4gICAgY29sb3I6IGF4ZXNBdHRycy5jb2xvcixcbiAgICAvLyB0aWNrc1xuICAgIHRpY2ttb2RlOiBheGVzQXR0cnMudGlja21vZGUsXG4gICAgbnRpY2tzOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMubnRpY2tzLCB7ZGZsdDogNiwgbWluOiAxfSksXG4gICAgdGljazA6IGF4ZXNBdHRycy50aWNrMCxcbiAgICBkdGljazogYXhlc0F0dHJzLmR0aWNrLFxuICAgIHRpY2t2YWxzOiBheGVzQXR0cnMudGlja3ZhbHMsXG4gICAgdGlja3RleHQ6IGF4ZXNBdHRycy50aWNrdGV4dCxcbiAgICB0aWNrczogYXhlc0F0dHJzLnRpY2tzLFxuICAgIHRpY2tsZW46IGF4ZXNBdHRycy50aWNrbGVuLFxuICAgIHRpY2t3aWR0aDogYXhlc0F0dHJzLnRpY2t3aWR0aCxcbiAgICB0aWNrY29sb3I6IGF4ZXNBdHRycy50aWNrY29sb3IsXG4gICAgc2hvd3RpY2tsYWJlbHM6IGF4ZXNBdHRycy5zaG93dGlja2xhYmVscyxcbiAgICBzaG93dGlja3ByZWZpeDogYXhlc0F0dHJzLnNob3d0aWNrcHJlZml4LFxuICAgIHRpY2twcmVmaXg6IGF4ZXNBdHRycy50aWNrcHJlZml4LFxuICAgIHNob3d0aWNrc3VmZml4OiBheGVzQXR0cnMuc2hvd3RpY2tzdWZmaXgsXG4gICAgdGlja3N1ZmZpeDogYXhlc0F0dHJzLnRpY2tzdWZmaXgsXG4gICAgc2hvd2V4cG9uZW50OiBheGVzQXR0cnMuc2hvd2V4cG9uZW50LFxuICAgIGV4cG9uZW50Zm9ybWF0OiBheGVzQXR0cnMuZXhwb25lbnRmb3JtYXQsXG4gICAgc2VwYXJhdGV0aG91c2FuZHM6IGF4ZXNBdHRycy5zZXBhcmF0ZXRob3VzYW5kcyxcbiAgICB0aWNrZm9udDogYXhlc0F0dHJzLnRpY2tmb250LFxuICAgIHRpY2thbmdsZTogYXhlc0F0dHJzLnRpY2thbmdsZSxcbiAgICB0aWNrZm9ybWF0OiBheGVzQXR0cnMudGlja2Zvcm1hdCxcbiAgICB0aWNrZm9ybWF0c3RvcHM6IGF4ZXNBdHRycy50aWNrZm9ybWF0c3RvcHMsXG4gICAgaG92ZXJmb3JtYXQ6IGF4ZXNBdHRycy5ob3ZlcmZvcm1hdCxcbiAgICAvLyBsaW5lcyBhbmQgZ3JpZHNcbiAgICBzaG93bGluZTogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnNob3dsaW5lLCB7ZGZsdDogdHJ1ZX0pLFxuICAgIGxpbmVjb2xvcjogYXhlc0F0dHJzLmxpbmVjb2xvcixcbiAgICBsaW5ld2lkdGg6IGF4ZXNBdHRycy5saW5ld2lkdGgsXG4gICAgc2hvd2dyaWQ6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5zaG93Z3JpZCwge2RmbHQ6IHRydWV9KSxcbiAgICBncmlkY29sb3I6IGF4ZXNBdHRycy5ncmlkY29sb3IsXG4gICAgZ3JpZHdpZHRoOiBheGVzQXR0cnMuZ3JpZHdpZHRoLFxuICAgIGxheWVyOiBheGVzQXR0cnMubGF5ZXIsXG4gICAgLy8gcmFuZ2VcbiAgICBtaW46IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICd0ZXJuYXJ5J30pLFxuXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5iYWNrZ3JvdW5kLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1bToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhYXhpczogdGVybmFyeUF4ZXNBdHRycyxcbiAgICBiYXhpczogdGVybmFyeUF4ZXNBdHRycyxcbiAgICBjYXhpczogdGVybmFyeUF4ZXNBdHRyc1xufSwgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBUZW1wbGF0ZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZVN1YnBsb3REZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3N1YnBsb3RfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGlja01hcmtEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi90aWNrX21hcmtfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZUdyaWREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9saW5lX2dyaWRfZGVmYXVsdHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgYXhlc05hbWVzID0gWydhYXhpcycsICdiYXhpcycsICdjYXhpcyddO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgaGFuZGxlU3VicGxvdERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCB7XG4gICAgICAgIHR5cGU6ICd0ZXJuYXJ5JyxcbiAgICAgICAgYXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlcyxcbiAgICAgICAgaGFuZGxlRGVmYXVsdHM6IGhhbmRsZVRlcm5hcnlEZWZhdWx0cyxcbiAgICAgICAgZm9udDogbGF5b3V0T3V0LmZvbnQsXG4gICAgICAgIHBhcGVyX2JnY29sb3I6IGxheW91dE91dC5wYXBlcl9iZ2NvbG9yXG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVUZXJuYXJ5RGVmYXVsdHModGVybmFyeUxheW91dEluLCB0ZXJuYXJ5TGF5b3V0T3V0LCBjb2VyY2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgYmdDb2xvciA9IGNvZXJjZSgnYmdjb2xvcicpO1xuICAgIHZhciBzdW0gPSBjb2VyY2UoJ3N1bScpO1xuICAgIG9wdGlvbnMuYmdDb2xvciA9IENvbG9yLmNvbWJpbmUoYmdDb2xvciwgb3B0aW9ucy5wYXBlcl9iZ2NvbG9yKTtcbiAgICB2YXIgYXhOYW1lLCBjb250YWluZXJJbiwgY29udGFpbmVyT3V0O1xuXG4gICAgLy8gVE9ETzogYWxsb3cgbW9zdCAoaWYgbm90IGFsbCkgYXhpcyBhdHRyaWJ1dGVzIHRvIGJlIHNldFxuICAgIC8vIGluIHRoZSBvdXRlciBjb250YWluZXIgYW5kIHVzZWQgYXMgZGVmYXVsdHMgaW4gdGhlIGluZGl2aWR1YWwgYXhlcz9cblxuICAgIGZvcih2YXIgaiA9IDA7IGogPCBheGVzTmFtZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgYXhOYW1lID0gYXhlc05hbWVzW2pdO1xuICAgICAgICBjb250YWluZXJJbiA9IHRlcm5hcnlMYXlvdXRJbltheE5hbWVdIHx8IHt9O1xuICAgICAgICBjb250YWluZXJPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIodGVybmFyeUxheW91dE91dCwgYXhOYW1lKTtcbiAgICAgICAgY29udGFpbmVyT3V0Ll9uYW1lID0gYXhOYW1lO1xuXG4gICAgICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgbWluIHZhbHVlcyBjb250cmFkaWN0IGVhY2ggb3RoZXIsIHNldCB0aGVtIGFsbCB0byBkZWZhdWx0ICgwKVxuICAgIC8vIGFuZCBkZWxldGUgKmFsbCogdGhlIGlucHV0cyBzbyB0aGUgdXNlciBkb2Vzbid0IGdldCBjb25mdXNlZCBsYXRlciBieVxuICAgIC8vIGNoYW5naW5nIG9uZSBhbmQgaGF2aW5nIHRoZW0gYWxsIGNoYW5nZS5cbiAgICB2YXIgYWF4aXMgPSB0ZXJuYXJ5TGF5b3V0T3V0LmFheGlzLFxuICAgICAgICBiYXhpcyA9IHRlcm5hcnlMYXlvdXRPdXQuYmF4aXMsXG4gICAgICAgIGNheGlzID0gdGVybmFyeUxheW91dE91dC5jYXhpcztcbiAgICBpZihhYXhpcy5taW4gKyBiYXhpcy5taW4gKyBjYXhpcy5taW4gPj0gc3VtKSB7XG4gICAgICAgIGFheGlzLm1pbiA9IDA7XG4gICAgICAgIGJheGlzLm1pbiA9IDA7XG4gICAgICAgIGNheGlzLm1pbiA9IDA7XG4gICAgICAgIGlmKHRlcm5hcnlMYXlvdXRJbi5hYXhpcykgZGVsZXRlIHRlcm5hcnlMYXlvdXRJbi5hYXhpcy5taW47XG4gICAgICAgIGlmKHRlcm5hcnlMYXlvdXRJbi5iYXhpcykgZGVsZXRlIHRlcm5hcnlMYXlvdXRJbi5iYXhpcy5taW47XG4gICAgICAgIGlmKHRlcm5hcnlMYXlvdXRJbi5jYXhpcykgZGVsZXRlIHRlcm5hcnlMYXlvdXRJbi5jYXhpcy5taW47XG4gICAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVBeGlzRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgb3B0aW9ucykge1xuICAgIHZhciBheEF0dHJzID0gbGF5b3V0QXR0cmlidXRlc1tjb250YWluZXJPdXQuX25hbWVdO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXhBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29udGFpbmVyT3V0LnR5cGUgPSAnbGluZWFyJzsgLy8gbm8gb3RoZXIgdHlwZXMgYWxsb3dlZCBmb3IgdGVybmFyeVxuXG4gICAgdmFyIGRmbHRDb2xvciA9IGNvZXJjZSgnY29sb3InKTtcbiAgICAvLyBpZiBheGlzLmNvbG9yIHdhcyBwcm92aWRlZCwgdXNlIGl0IGZvciBmb250cyB0b287IG90aGVyd2lzZSxcbiAgICAvLyBpbmhlcml0IGZyb20gZ2xvYmFsIGZvbnQgY29sb3IgaW4gY2FzZSB0aGF0IHdhcyBwcm92aWRlZC5cbiAgICB2YXIgZGZsdEZvbnRDb2xvciA9IChkZmx0Q29sb3IgIT09IGF4QXR0cnMuY29sb3IuZGZsdCkgPyBkZmx0Q29sb3IgOiBvcHRpb25zLmZvbnQuY29sb3I7XG5cbiAgICB2YXIgYXhOYW1lID0gY29udGFpbmVyT3V0Ll9uYW1lLFxuICAgICAgICBsZXR0ZXJVcHBlciA9IGF4TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSxcbiAgICAgICAgZGZsdFRpdGxlID0gJ0NvbXBvbmVudCAnICsgbGV0dGVyVXBwZXI7XG5cbiAgICB2YXIgdGl0bGUgPSBjb2VyY2UoJ3RpdGxlJywgZGZsdFRpdGxlKTtcbiAgICBjb250YWluZXJPdXQuX2hvdmVydGl0bGUgPSB0aXRsZSA9PT0gZGZsdFRpdGxlID8gdGl0bGUgOiBsZXR0ZXJVcHBlcjtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBvcHRpb25zLmZvbnQuZmFtaWx5LFxuICAgICAgICBzaXplOiBNYXRoLnJvdW5kKG9wdGlvbnMuZm9udC5zaXplICogMS4yKSxcbiAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICB9KTtcblxuICAgIC8vIHJhbmdlIGlzIGp1c3Qgc2V0IGJ5ICdtaW4nIC0gbWF4IGlzIGRldGVybWluZWQgYnkgdGhlIG90aGVyIGF4ZXMgbWluc1xuICAgIGNvZXJjZSgnbWluJyk7XG5cbiAgICBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsICdsaW5lYXInKTtcbiAgICBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsICdsaW5lYXInLCB7fSk7XG4gICAgaGFuZGxlVGlja01hcmtEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsXG4gICAgICAgIHsgb3V0ZXJUaWNrczogdHJ1ZSB9KTtcblxuICAgIHZhciBzaG93VGlja0xhYmVscyA9IGNvZXJjZSgnc2hvd3RpY2tsYWJlbHMnKTtcbiAgICBpZihzaG93VGlja0xhYmVscykge1xuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aWNrZm9udCcsIHtcbiAgICAgICAgICAgIGZhbWlseTogb3B0aW9ucy5mb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IG9wdGlvbnMuZm9udC5zaXplLFxuICAgICAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgndGlja2FuZ2xlJyk7XG4gICAgICAgIGNvZXJjZSgndGlja2Zvcm1hdCcpO1xuICAgIH1cblxuICAgIGhhbmRsZUxpbmVHcmlkRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCB7XG4gICAgICAgIGRmbHRDb2xvcjogZGZsdENvbG9yLFxuICAgICAgICBiZ0NvbG9yOiBvcHRpb25zLmJnQ29sb3IsXG4gICAgICAgIC8vIGRlZmF1bHQgZ3JpZCBjb2xvciBpcyBkYXJrZXIgaGVyZSAoNjAlLCB2cyBjYXJ0ZXNpYW4gZGVmYXVsdCB+OTElKVxuICAgICAgICAvLyBiZWNhdXNlIHRoZSBncmlkIGlzIG5vdCBzcXVhcmUgc28gdGhlIGV5ZSBuZWVkcyBoZWF2aWVyIGN1ZXMgdG8gZm9sbG93XG4gICAgICAgIGJsZW5kOiA2MCxcbiAgICAgICAgc2hvd0xpbmU6IHRydWUsXG4gICAgICAgIHNob3dHcmlkOiB0cnVlLFxuICAgICAgICBub1plcm9MaW5lOiB0cnVlLFxuICAgICAgICBhdHRyaWJ1dGVzOiBheEF0dHJzXG4gICAgfSk7XG5cbiAgICBjb2VyY2UoJ2hvdmVyZm9ybWF0Jyk7XG4gICAgY29lcmNlKCdsYXllcicpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIF8gPSBMaWIuXztcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgc2V0Q29udmVydCA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50Jyk7XG52YXIgRnggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgVGl0bGVzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy90aXRsZXMnKTtcbnZhciBwcmVwU2VsZWN0ID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnByZXBTZWxlY3Q7XG52YXIgc2VsZWN0T25DbGljayA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9zZWxlY3QnKS5zZWxlY3RPbkNsaWNrO1xudmFyIGNsZWFyU2VsZWN0ID0gcmVxdWlyZSgnLi4vY2FydGVzaWFuL3NlbGVjdCcpLmNsZWFyU2VsZWN0O1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4uL2NhcnRlc2lhbi9jb25zdGFudHMnKTtcblxuZnVuY3Rpb24gVGVybmFyeShvcHRpb25zLCBmdWxsTGF5b3V0KSB7XG4gICAgdGhpcy5pZCA9IG9wdGlvbnMuaWQ7XG4gICAgdGhpcy5ncmFwaERpdiA9IG9wdGlvbnMuZ3JhcGhEaXY7XG4gICAgdGhpcy5pbml0KGZ1bGxMYXlvdXQpO1xuICAgIHRoaXMubWFrZUZyYW1ld29yayhmdWxsTGF5b3V0KTtcblxuICAgIC8vIHVuZm9ydHVuYXRlbHksIHdlIGhhdmUgdG8ga2VlcCB0cmFjayBvZiBzb21lIGF4aXMgdGljayBzZXR0aW5nc1xuICAgIC8vIGFzIHRlcm5hcnkgc3VicGxvdHMgZG8gbm90IGltcGxlbWVudCB0aGUgJ3RpY2tzJyBlZGl0VHlwZVxuICAgIHRoaXMuYVRpY2tMYXlvdXQgPSBudWxsO1xuICAgIHRoaXMuYlRpY2tMYXlvdXQgPSBudWxsO1xuICAgIHRoaXMuY1RpY2tMYXlvdXQgPSBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFRlcm5hcnk7XG5cbnZhciBwcm90byA9IFRlcm5hcnkucHJvdG90eXBlO1xuXG5wcm90by5pbml0ID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHRoaXMuY29udGFpbmVyID0gZnVsbExheW91dC5fdGVybmFyeWxheWVyO1xuICAgIHRoaXMuZGVmcyA9IGZ1bGxMYXlvdXQuX2RlZnM7XG4gICAgdGhpcy5sYXlvdXRJZCA9IGZ1bGxMYXlvdXQuX3VpZDtcbiAgICB0aGlzLnRyYWNlSGFzaCA9IHt9O1xuICAgIHRoaXMubGF5ZXJzID0ge307XG59O1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24odGVybmFyeUNhbGNEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgdGVybmFyeUxheW91dCA9IGZ1bGxMYXlvdXRbX3RoaXMuaWRdO1xuICAgIHZhciBncmFwaFNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgX3RoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA9IGZhbHNlO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0ZXJuYXJ5Q2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gdGVybmFyeUNhbGNEYXRhW2ldWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlLmNsaXBvbmF4aXMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX3RoaXMudXBkYXRlTGF5ZXJzKHRlcm5hcnlMYXlvdXQpO1xuICAgIF90aGlzLmFkanVzdExheW91dCh0ZXJuYXJ5TGF5b3V0LCBncmFwaFNpemUpO1xuICAgIFBsb3RzLmdlbmVyYWxVcGRhdGVQZXJUcmFjZU1vZHVsZShfdGhpcy5ncmFwaERpdiwgX3RoaXMsIHRlcm5hcnlDYWxjRGF0YSwgdGVybmFyeUxheW91dCk7XG4gICAgX3RoaXMubGF5ZXJzLnBsb3RiZy5zZWxlY3QoJ3BhdGgnKS5jYWxsKENvbG9yLmZpbGwsIHRlcm5hcnlMYXlvdXQuYmdjb2xvcik7XG59O1xuXG5wcm90by5tYWtlRnJhbWV3b3JrID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIHRlcm5hcnlMYXlvdXQgPSBmdWxsTGF5b3V0W190aGlzLmlkXTtcblxuICAgIHZhciBjbGlwSWQgPSBfdGhpcy5jbGlwSWQgPSAnY2xpcCcgKyBfdGhpcy5sYXlvdXRJZCArIF90aGlzLmlkO1xuICAgIHZhciBjbGlwSWRSZWxhdGl2ZSA9IF90aGlzLmNsaXBJZFJlbGF0aXZlID0gJ2NsaXAtcmVsYXRpdmUnICsgX3RoaXMubGF5b3V0SWQgKyBfdGhpcy5pZDtcblxuICAgIC8vIGNsaXBwYXRoIGZvciB0aGlzIHRlcm5hcnkgc3VicGxvdFxuICAgIF90aGlzLmNsaXBEZWYgPSBMaWIuZW5zdXJlU2luZ2xlQnlJZChmdWxsTGF5b3V0Ll9jbGlwcywgJ2NsaXBQYXRoJywgY2xpcElkLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXBwZW5kKCdwYXRoJykuYXR0cignZCcsICdNMCwwWicpO1xuICAgIH0pO1xuXG4gICAgLy8gJ3JlbGF0aXZlJyBjbGlwcGF0aCAoaS5lLiBubyB0cmFuc2xhdGlvbikgZm9yIHRoaXMgdGVybmFyeSBzdWJwbG90XG4gICAgX3RoaXMuY2xpcERlZlJlbGF0aXZlID0gTGliLmVuc3VyZVNpbmdsZUJ5SWQoZnVsbExheW91dC5fY2xpcHMsICdjbGlwUGF0aCcsIGNsaXBJZFJlbGF0aXZlLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXBwZW5kKCdwYXRoJykuYXR0cignZCcsICdNMCwwWicpO1xuICAgIH0pO1xuXG4gICAgLy8gY29udGFpbmVyIGZvciBldmVyeXRoaW5nIGluIHRoaXMgdGVybmFyeSBzdWJwbG90XG4gICAgX3RoaXMucGxvdENvbnRhaW5lciA9IExpYi5lbnN1cmVTaW5nbGUoX3RoaXMuY29udGFpbmVyLCAnZycsIF90aGlzLmlkKTtcbiAgICBfdGhpcy51cGRhdGVMYXllcnModGVybmFyeUxheW91dCk7XG5cbiAgICBEcmF3aW5nLnNldENsaXBVcmwoX3RoaXMubGF5ZXJzLmJhY2twbG90LCBjbGlwSWQpO1xuICAgIERyYXdpbmcuc2V0Q2xpcFVybChfdGhpcy5sYXllcnMuZ3JpZHMsIGNsaXBJZCk7XG59O1xuXG5wcm90by51cGRhdGVMYXllcnMgPSBmdW5jdGlvbih0ZXJuYXJ5TGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuXG4gICAgLy8gaW5zaWRlIHRoYXQgY29udGFpbmVyLCB3ZSBoYXZlIG9uZSBjb250YWluZXIgZm9yIHRoZSBkYXRhLCBhbmRcbiAgICAvLyBvbmUgZWFjaCBmb3IgdGhlIHRocmVlIGF4ZXMgYXJvdW5kIGl0LlxuXG4gICAgdmFyIHBsb3RMYXllcnMgPSBbJ2RyYWdsYXllcicsICdwbG90YmcnLCAnYmFja3Bsb3QnLCAnZ3JpZHMnXTtcblxuICAgIGlmKHRlcm5hcnlMYXlvdXQuYWF4aXMubGF5ZXIgPT09ICdiZWxvdyB0cmFjZXMnKSB7XG4gICAgICAgIHBsb3RMYXllcnMucHVzaCgnYWF4aXMnLCAnYWxpbmUnKTtcbiAgICB9XG4gICAgaWYodGVybmFyeUxheW91dC5iYXhpcy5sYXllciA9PT0gJ2JlbG93IHRyYWNlcycpIHtcbiAgICAgICAgcGxvdExheWVycy5wdXNoKCdiYXhpcycsICdibGluZScpO1xuICAgIH1cbiAgICBpZih0ZXJuYXJ5TGF5b3V0LmNheGlzLmxheWVyID09PSAnYmVsb3cgdHJhY2VzJykge1xuICAgICAgICBwbG90TGF5ZXJzLnB1c2goJ2NheGlzJywgJ2NsaW5lJyk7XG4gICAgfVxuXG4gICAgcGxvdExheWVycy5wdXNoKCdmcm9udHBsb3QnKTtcblxuICAgIGlmKHRlcm5hcnlMYXlvdXQuYWF4aXMubGF5ZXIgPT09ICdhYm92ZSB0cmFjZXMnKSB7XG4gICAgICAgIHBsb3RMYXllcnMucHVzaCgnYWF4aXMnLCAnYWxpbmUnKTtcbiAgICB9XG4gICAgaWYodGVybmFyeUxheW91dC5iYXhpcy5sYXllciA9PT0gJ2Fib3ZlIHRyYWNlcycpIHtcbiAgICAgICAgcGxvdExheWVycy5wdXNoKCdiYXhpcycsICdibGluZScpO1xuICAgIH1cbiAgICBpZih0ZXJuYXJ5TGF5b3V0LmNheGlzLmxheWVyID09PSAnYWJvdmUgdHJhY2VzJykge1xuICAgICAgICBwbG90TGF5ZXJzLnB1c2goJ2NheGlzJywgJ2NsaW5lJyk7XG4gICAgfVxuXG4gICAgdmFyIHRvcGxldmVsID0gX3RoaXMucGxvdENvbnRhaW5lci5zZWxlY3RBbGwoJ2cudG9wbGV2ZWwnKVxuICAgICAgICAuZGF0YShwbG90TGF5ZXJzLCBTdHJpbmcpO1xuXG4gICAgdmFyIGdyaWRzID0gWydhZ3JpZCcsICdiZ3JpZCcsICdjZ3JpZCddO1xuXG4gICAgdG9wbGV2ZWwuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiAndG9wbGV2ZWwgJyArIGQ7IH0pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBzID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgbGF5ZXJzW2RdID0gcztcblxuICAgICAgICAgICAgLy8gY29udGFpbmVycyBmb3IgZGlmZmVyZW50IHRyYWNlIHR5cGVzLlxuICAgICAgICAgICAgLy8gTk9URSAtIHRoaXMgaXMgZGlmZmVyZW50IGZyb20gY2FydGVzaWFuLCB3aGVyZSBhbGwgdHJhY2VzXG4gICAgICAgICAgICAvLyBhcmUgaW4gZnJvbnQgb2YgZ3JpZHMuIEhlcmUgSSdtIHB1dHRpbmcgbWFwcyBiZWhpbmQgdGhlIGdyaWRzXG4gICAgICAgICAgICAvLyBzbyB0aGUgZ3JpZHMgd2lsbCBhbHdheXMgYmUgdmlzaWJsZSBpZiB0aGV5J3JlIHJlcXVlc3RlZC5cbiAgICAgICAgICAgIC8vIFBlcmhhcHMgd2Ugd2FudCB0aGF0IGZvciBjYXJ0ZXNpYW4gdG9vP1xuICAgICAgICAgICAgaWYoZCA9PT0gJ2Zyb250cGxvdCcpIHtcbiAgICAgICAgICAgICAgICBzLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3NjYXR0ZXJsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGQgPT09ICdiYWNrcGxvdCcpIHtcbiAgICAgICAgICAgICAgICBzLmFwcGVuZCgnZycpLmNsYXNzZWQoJ21hcGxheWVyJywgdHJ1ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZCA9PT0gJ3Bsb3RiZycpIHtcbiAgICAgICAgICAgICAgICBzLmFwcGVuZCgncGF0aCcpLmF0dHIoJ2QnLCAnTTAsMFonKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkID09PSAnYWxpbmUnIHx8IGQgPT09ICdibGluZScgfHwgZCA9PT0gJ2NsaW5lJykge1xuICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdwYXRoJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZCA9PT0gJ2dyaWRzJykge1xuICAgICAgICAgICAgICAgIGdyaWRzLmZvckVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgICAgICBsYXllcnNbZF0gPSBzLmFwcGVuZCgnZycpLmNsYXNzZWQoJ2dyaWQgJyArIGQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWN0SUQgPSAoZCA9PT0gJ2JncmlkJykgPyAneCcgOiAneSc7XG4gICAgICAgICAgICAgICAgICAgIGxheWVyc1tkXS5hcHBlbmQoJ2cnKS5jbGFzc2VkKGZpY3RJRCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdG9wbGV2ZWwub3JkZXIoKTtcbn07XG5cbnZhciB3X292ZXJfaCA9IE1hdGguc3FydCg0IC8gMyk7XG5cbnByb3RvLmFkanVzdExheW91dCA9IGZ1bmN0aW9uKHRlcm5hcnlMYXlvdXQsIGdyYXBoU2l6ZSkge1xuICAgIHZhciBfdGhpcyA9IHRoaXMsXG4gICAgICAgIGRvbWFpbiA9IHRlcm5hcnlMYXlvdXQuZG9tYWluLFxuICAgICAgICB4RG9tYWluQ2VudGVyID0gKGRvbWFpbi54WzBdICsgZG9tYWluLnhbMV0pIC8gMixcbiAgICAgICAgeURvbWFpbkNlbnRlciA9IChkb21haW4ueVswXSArIGRvbWFpbi55WzFdKSAvIDIsXG4gICAgICAgIHhEb21haW4gPSBkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdLFxuICAgICAgICB5RG9tYWluID0gZG9tYWluLnlbMV0gLSBkb21haW4ueVswXSxcbiAgICAgICAgd21heCA9IHhEb21haW4gKiBncmFwaFNpemUudyxcbiAgICAgICAgaG1heCA9IHlEb21haW4gKiBncmFwaFNpemUuaCxcbiAgICAgICAgc3VtID0gdGVybmFyeUxheW91dC5zdW0sXG4gICAgICAgIGFtaW4gPSB0ZXJuYXJ5TGF5b3V0LmFheGlzLm1pbixcbiAgICAgICAgYm1pbiA9IHRlcm5hcnlMYXlvdXQuYmF4aXMubWluLFxuICAgICAgICBjbWluID0gdGVybmFyeUxheW91dC5jYXhpcy5taW47XG5cbiAgICB2YXIgeDAsIHkwLCB3LCBoLCB4RG9tYWluRmluYWwsIHlEb21haW5GaW5hbDtcblxuICAgIGlmKHdtYXggPiB3X292ZXJfaCAqIGhtYXgpIHtcbiAgICAgICAgaCA9IGhtYXg7XG4gICAgICAgIHcgPSBoICogd19vdmVyX2g7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB3ID0gd21heDtcbiAgICAgICAgaCA9IHcgLyB3X292ZXJfaDtcbiAgICB9XG5cbiAgICB4RG9tYWluRmluYWwgPSB4RG9tYWluICogdyAvIHdtYXg7XG4gICAgeURvbWFpbkZpbmFsID0geURvbWFpbiAqIGggLyBobWF4O1xuXG4gICAgeDAgPSBncmFwaFNpemUubCArIGdyYXBoU2l6ZS53ICogeERvbWFpbkNlbnRlciAtIHcgLyAyO1xuICAgIHkwID0gZ3JhcGhTaXplLnQgKyBncmFwaFNpemUuaCAqICgxIC0geURvbWFpbkNlbnRlcikgLSBoIC8gMjtcblxuICAgIF90aGlzLngwID0geDA7XG4gICAgX3RoaXMueTAgPSB5MDtcbiAgICBfdGhpcy53ID0gdztcbiAgICBfdGhpcy5oID0gaDtcbiAgICBfdGhpcy5zdW0gPSBzdW07XG5cbiAgICAvLyBzZXQgdXAgdGhlIHggYW5kIHkgYXhpcyBvYmplY3RzIHdlJ2xsIHVzZSB0byBsYXkgb3V0IHRoZSBwb2ludHNcbiAgICBfdGhpcy54YXhpcyA9IHtcbiAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgIHJhbmdlOiBbYW1pbiArIDIgKiBjbWluIC0gc3VtLCBzdW0gLSBhbWluIC0gMiAqIGJtaW5dLFxuICAgICAgICBkb21haW46IFtcbiAgICAgICAgICAgIHhEb21haW5DZW50ZXIgLSB4RG9tYWluRmluYWwgLyAyLFxuICAgICAgICAgICAgeERvbWFpbkNlbnRlciArIHhEb21haW5GaW5hbCAvIDJcbiAgICAgICAgXSxcbiAgICAgICAgX2lkOiAneCdcbiAgICB9O1xuICAgIHNldENvbnZlcnQoX3RoaXMueGF4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBfdGhpcy54YXhpcy5zZXRTY2FsZSgpO1xuICAgIF90aGlzLnhheGlzLmlzUHRXaXRoaW5SYW5nZSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGQuYSA+PSBfdGhpcy5hYXhpcy5yYW5nZVswXSAmJlxuICAgICAgICAgICAgZC5hIDw9IF90aGlzLmFheGlzLnJhbmdlWzFdICYmXG4gICAgICAgICAgICBkLmIgPj0gX3RoaXMuYmF4aXMucmFuZ2VbMV0gJiZcbiAgICAgICAgICAgIGQuYiA8PSBfdGhpcy5iYXhpcy5yYW5nZVswXSAmJlxuICAgICAgICAgICAgZC5jID49IF90aGlzLmNheGlzLnJhbmdlWzFdICYmXG4gICAgICAgICAgICBkLmMgPD0gX3RoaXMuY2F4aXMucmFuZ2VbMF1cbiAgICAgICAgKTtcbiAgICB9O1xuXG4gICAgX3RoaXMueWF4aXMgPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogW2FtaW4sIHN1bSAtIGJtaW4gLSBjbWluXSxcbiAgICAgICAgZG9tYWluOiBbXG4gICAgICAgICAgICB5RG9tYWluQ2VudGVyIC0geURvbWFpbkZpbmFsIC8gMixcbiAgICAgICAgICAgIHlEb21haW5DZW50ZXIgKyB5RG9tYWluRmluYWwgLyAyXG4gICAgICAgIF0sXG4gICAgICAgIF9pZDogJ3knXG4gICAgfTtcbiAgICBzZXRDb252ZXJ0KF90aGlzLnlheGlzLCBfdGhpcy5ncmFwaERpdi5fZnVsbExheW91dCk7XG4gICAgX3RoaXMueWF4aXMuc2V0U2NhbGUoKTtcbiAgICBfdGhpcy55YXhpcy5pc1B0V2l0aGluUmFuZ2UgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRydWU7IH07XG5cbiAgICAvLyBzZXQgdXAgdGhlIG1vZGlmaWVkIGF4ZXMgZm9yIHRpY2sgZHJhd2luZ1xuICAgIHZhciB5RG9tYWluMCA9IF90aGlzLnlheGlzLmRvbWFpblswXTtcblxuICAgIC8vIGFheGlzIGdvZXMgdXAgdGhlIGxlZnQgc2lkZS4gU2V0IGl0IHVwIGFzIGEgeSBheGlzLCBidXQgd2l0aFxuICAgIC8vIGZpY3RpdGlvdXMgYW5nbGVzIGFuZCBkb21haW4sIGJ1dCB0aGVuIHJvdGF0ZSBhbmQgdHJhbnNsYXRlXG4gICAgLy8gaXQgaW50byBwbGFjZSBhdCB0aGUgZW5kXG4gICAgdmFyIGFheGlzID0gX3RoaXMuYWF4aXMgPSBleHRlbmRGbGF0KHt9LCB0ZXJuYXJ5TGF5b3V0LmFheGlzLCB7XG4gICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgIHJhbmdlOiBbYW1pbiwgc3VtIC0gYm1pbiAtIGNtaW5dLFxuICAgICAgICBzaWRlOiAnbGVmdCcsXG4gICAgICAgIF9jb3VudGVyYW5nbGU6IDMwLFxuICAgICAgICAvLyB0aWNrYW5nbGUgPSAnYXV0bycgbWVhbnMgMCBhbnl3YXkgZm9yIGEgeSBheGlzLCBuZWVkIHRvIGNvZXJjZSB0byAwIGhlcmVcbiAgICAgICAgLy8gc28gd2UgY2FuIHNoaWZ0IGJ5IDMwLlxuICAgICAgICB0aWNrYW5nbGU6ICgrdGVybmFyeUxheW91dC5hYXhpcy50aWNrYW5nbGUgfHwgMCkgLSAzMCxcbiAgICAgICAgZG9tYWluOiBbeURvbWFpbjAsIHlEb21haW4wICsgeURvbWFpbkZpbmFsICogd19vdmVyX2hdLFxuICAgICAgICBfYXhpc2xheWVyOiBfdGhpcy5sYXllcnMuYWF4aXMsXG4gICAgICAgIF9ncmlkbGF5ZXI6IF90aGlzLmxheWVycy5hZ3JpZCxcbiAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgIHBvc2l0aW9uOiAwLFxuICAgICAgICBfcG9zOiAwLCAvLyBfdGhpcy54YXhpcy5kb21haW5bMF0gKiBncmFwaFNpemUudyxcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIF9sZW5ndGg6IHcsXG4gICAgICAgIF9ncmlkcGF0aDogJ00wLDBsJyArIGggKyAnLC0nICsgKHcgLyAyKSxcbiAgICAgICAgYXV0b21hcmdpbjogZmFsc2UgLy8gZG9uJ3QgdXNlIGF1dG9tYXJnaW5zIHJvdXRpbmUgZm9yIGxhYmVsc1xuICAgIH0pO1xuICAgIHNldENvbnZlcnQoYWF4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBhYXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgLy8gYmF4aXMgZ29lcyBhY3Jvc3MgdGhlIGJvdHRvbSAoYmFja3dhcmQpLiBXZSBjYW4gc2V0IGl0IHVwIGFzIGFuIHggYXhpc1xuICAgIC8vIHdpdGhvdXQgYW55IGVuY2xvc2luZyB0cmFuc2Zvcm1hdGlvbi5cbiAgICB2YXIgYmF4aXMgPSBfdGhpcy5iYXhpcyA9IGV4dGVuZEZsYXQoe30sIHRlcm5hcnlMYXlvdXQuYmF4aXMsIHtcbiAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgcmFuZ2U6IFtzdW0gLSBhbWluIC0gY21pbiwgYm1pbl0sXG4gICAgICAgIHNpZGU6ICdib3R0b20nLFxuICAgICAgICBfY291bnRlcmFuZ2xlOiAzMCxcbiAgICAgICAgZG9tYWluOiBfdGhpcy54YXhpcy5kb21haW4sXG4gICAgICAgIF9heGlzbGF5ZXI6IF90aGlzLmxheWVycy5iYXhpcyxcbiAgICAgICAgX2dyaWRsYXllcjogX3RoaXMubGF5ZXJzLmJncmlkLFxuICAgICAgICBfY291bnRlcmF4aXM6IF90aGlzLmFheGlzLFxuICAgICAgICBhbmNob3I6ICdmcmVlJyxcbiAgICAgICAgcG9zaXRpb246IDAsXG4gICAgICAgIF9wb3M6IDAsIC8vICgxIC0geURvbWFpbjApICogZ3JhcGhTaXplLmgsXG4gICAgICAgIF9pZDogJ3gnLFxuICAgICAgICBfbGVuZ3RoOiB3LFxuICAgICAgICBfZ3JpZHBhdGg6ICdNMCwwbC0nICsgKHcgLyAyKSArICcsLScgKyBoLFxuICAgICAgICBhdXRvbWFyZ2luOiBmYWxzZSAvLyBkb24ndCB1c2UgYXV0b21hcmdpbnMgcm91dGluZSBmb3IgbGFiZWxzXG4gICAgfSk7XG4gICAgc2V0Q29udmVydChiYXhpcywgX3RoaXMuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQpO1xuICAgIGJheGlzLnNldFNjYWxlKCk7XG4gICAgYWF4aXMuX2NvdW50ZXJheGlzID0gYmF4aXM7XG5cbiAgICAvLyBjYXhpcyBnb2VzIGRvd24gdGhlIHJpZ2h0IHNpZGUuIFNldCBpdCB1cCBhcyBhIHkgYXhpcywgd2l0aFxuICAgIC8vIHBvc3QtdHJhbnNmb3JtYXRpb24gc2ltaWxhciB0byBhYXhpc1xuICAgIHZhciBjYXhpcyA9IF90aGlzLmNheGlzID0gZXh0ZW5kRmxhdCh7fSwgdGVybmFyeUxheW91dC5jYXhpcywge1xuICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICByYW5nZTogW3N1bSAtIGFtaW4gLSBibWluLCBjbWluXSxcbiAgICAgICAgc2lkZTogJ3JpZ2h0JyxcbiAgICAgICAgX2NvdW50ZXJhbmdsZTogMzAsXG4gICAgICAgIHRpY2thbmdsZTogKCt0ZXJuYXJ5TGF5b3V0LmNheGlzLnRpY2thbmdsZSB8fCAwKSArIDMwLFxuICAgICAgICBkb21haW46IFt5RG9tYWluMCwgeURvbWFpbjAgKyB5RG9tYWluRmluYWwgKiB3X292ZXJfaF0sXG4gICAgICAgIF9heGlzbGF5ZXI6IF90aGlzLmxheWVycy5jYXhpcyxcbiAgICAgICAgX2dyaWRsYXllcjogX3RoaXMubGF5ZXJzLmNncmlkLFxuICAgICAgICBfY291bnRlcmF4aXM6IF90aGlzLmJheGlzLFxuICAgICAgICBhbmNob3I6ICdmcmVlJyxcbiAgICAgICAgcG9zaXRpb246IDAsXG4gICAgICAgIF9wb3M6IDAsIC8vIF90aGlzLnhheGlzLmRvbWFpblsxXSAqIGdyYXBoU2l6ZS53LFxuICAgICAgICBfaWQ6ICd5JyxcbiAgICAgICAgX2xlbmd0aDogdyxcbiAgICAgICAgX2dyaWRwYXRoOiAnTTAsMGwtJyArIGggKyAnLCcgKyAodyAvIDIpLFxuICAgICAgICBhdXRvbWFyZ2luOiBmYWxzZSAvLyBkb24ndCB1c2UgYXV0b21hcmdpbnMgcm91dGluZSBmb3IgbGFiZWxzXG4gICAgfSk7XG4gICAgc2V0Q29udmVydChjYXhpcywgX3RoaXMuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQpO1xuICAgIGNheGlzLnNldFNjYWxlKCk7XG5cbiAgICB2YXIgdHJpYW5nbGVDbGlwID0gJ00nICsgeDAgKyAnLCcgKyAoeTAgKyBoKSArICdoJyArIHcgKyAnbC0nICsgKHcgLyAyKSArICcsLScgKyBoICsgJ1onO1xuICAgIF90aGlzLmNsaXBEZWYuc2VsZWN0KCdwYXRoJykuYXR0cignZCcsIHRyaWFuZ2xlQ2xpcCk7XG4gICAgX3RoaXMubGF5ZXJzLnBsb3RiZy5zZWxlY3QoJ3BhdGgnKS5hdHRyKCdkJywgdHJpYW5nbGVDbGlwKTtcblxuICAgIHZhciB0cmlhbmdsZUNsaXBSZWxhdGl2ZSA9ICdNMCwnICsgaCArICdoJyArIHcgKyAnbC0nICsgKHcgLyAyKSArICcsLScgKyBoICsgJ1onO1xuICAgIF90aGlzLmNsaXBEZWZSZWxhdGl2ZS5zZWxlY3QoJ3BhdGgnKS5hdHRyKCdkJywgdHJpYW5nbGVDbGlwUmVsYXRpdmUpO1xuXG4gICAgdmFyIHBsb3RUcmFuc2Zvcm0gPSAndHJhbnNsYXRlKCcgKyB4MCArICcsJyArIHkwICsgJyknO1xuICAgIF90aGlzLnBsb3RDb250YWluZXIuc2VsZWN0QWxsKCcuc2NhdHRlcmxheWVyLC5tYXBsYXllcicpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBwbG90VHJhbnNmb3JtKTtcblxuICAgIF90aGlzLmNsaXBEZWZSZWxhdGl2ZS5zZWxlY3QoJ3BhdGgnKS5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgIC8vIFRPRE86IHNoaWZ0IGF4ZXMgdG8gYWNjb21tb2RhdGUgbGluZXdpZHRoKnNpbigzMCkgdGljayBtYXJrIGFuZ2xlXG5cbiAgICAvLyBUT0RPOiB0aGVyZSdzIHByb2JhYmx5IGFuIGVhc2llciB3YXkgdG8gaGFuZGxlIHRoZXNlIHRyYW5zbGF0aW9ucy9vZmZzZXRzIG5vdy4uLlxuICAgIHZhciBiVHJhbnNmb3JtID0gJ3RyYW5zbGF0ZSgnICsgKHgwIC0gYmF4aXMuX29mZnNldCkgKyAnLCcgKyAoeTAgKyBoKSArICcpJztcblxuICAgIF90aGlzLmxheWVycy5iYXhpcy5hdHRyKCd0cmFuc2Zvcm0nLCBiVHJhbnNmb3JtKTtcbiAgICBfdGhpcy5sYXllcnMuYmdyaWQuYXR0cigndHJhbnNmb3JtJywgYlRyYW5zZm9ybSk7XG5cbiAgICB2YXIgYVRyYW5zZm9ybSA9ICd0cmFuc2xhdGUoJyArICh4MCArIHcgLyAyKSArICcsJyArIHkwICtcbiAgICAgICAgJylyb3RhdGUoMzApdHJhbnNsYXRlKDAsJyArIC1hYXhpcy5fb2Zmc2V0ICsgJyknO1xuICAgIF90aGlzLmxheWVycy5hYXhpcy5hdHRyKCd0cmFuc2Zvcm0nLCBhVHJhbnNmb3JtKTtcbiAgICBfdGhpcy5sYXllcnMuYWdyaWQuYXR0cigndHJhbnNmb3JtJywgYVRyYW5zZm9ybSk7XG5cbiAgICB2YXIgY1RyYW5zZm9ybSA9ICd0cmFuc2xhdGUoJyArICh4MCArIHcgLyAyKSArICcsJyArIHkwICtcbiAgICAgICAgJylyb3RhdGUoLTMwKXRyYW5zbGF0ZSgwLCcgKyAtY2F4aXMuX29mZnNldCArICcpJztcbiAgICBfdGhpcy5sYXllcnMuY2F4aXMuYXR0cigndHJhbnNmb3JtJywgY1RyYW5zZm9ybSk7XG4gICAgX3RoaXMubGF5ZXJzLmNncmlkLmF0dHIoJ3RyYW5zZm9ybScsIGNUcmFuc2Zvcm0pO1xuXG4gICAgX3RoaXMuZHJhd0F4ZXModHJ1ZSk7XG5cbiAgICAvLyByZW1vdmUgY3Jpc3BFZGdlcyAtIGFsbCB0aGUgb2ZmLXNxdWFyZSBhbmdsZXMgaW4gdGVybmFyeSBwbG90c1xuICAgIC8vIG1ha2UgdGhlc2UgY291bnRlcnByb2R1Y3RpdmUuXG4gICAgX3RoaXMucGxvdENvbnRhaW5lci5zZWxlY3RBbGwoJy5jcmlzcCcpLmNsYXNzZWQoJ2NyaXNwJywgZmFsc2UpO1xuXG4gICAgX3RoaXMubGF5ZXJzLmFsaW5lLnNlbGVjdCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdkJywgYWF4aXMuc2hvd2xpbmUgP1xuICAgICAgICAgICAgJ00nICsgeDAgKyAnLCcgKyAoeTAgKyBoKSArICdsJyArICh3IC8gMikgKyAnLC0nICsgaCA6ICdNMCwwJylcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBhYXhpcy5saW5lY29sb3IgfHwgJyMwMDAnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIChhYXhpcy5saW5ld2lkdGggfHwgMCkgKyAncHgnKTtcbiAgICBfdGhpcy5sYXllcnMuYmxpbmUuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2QnLCBiYXhpcy5zaG93bGluZSA/XG4gICAgICAgICAgICAnTScgKyB4MCArICcsJyArICh5MCArIGgpICsgJ2gnICsgdyA6ICdNMCwwJylcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBiYXhpcy5saW5lY29sb3IgfHwgJyMwMDAnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIChiYXhpcy5saW5ld2lkdGggfHwgMCkgKyAncHgnKTtcbiAgICBfdGhpcy5sYXllcnMuY2xpbmUuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2QnLCBjYXhpcy5zaG93bGluZSA/XG4gICAgICAgICAgICAnTScgKyAoeDAgKyB3IC8gMikgKyAnLCcgKyB5MCArICdsJyArICh3IC8gMikgKyAnLCcgKyBoIDogJ00wLDAnKVxuICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGNheGlzLmxpbmVjb2xvciB8fCAnIzAwMCcpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgKGNheGlzLmxpbmV3aWR0aCB8fCAwKSArICdweCcpO1xuXG4gICAgaWYoIV90aGlzLmdyYXBoRGl2Ll9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgX3RoaXMuaW5pdEludGVyYWN0aW9ucygpO1xuICAgIH1cblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChcbiAgICAgICAgX3RoaXMubGF5ZXJzLmZyb250cGxvdCxcbiAgICAgICAgX3RoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA/IG51bGwgOiBfdGhpcy5jbGlwSWRcbiAgICApO1xufTtcblxucHJvdG8uZHJhd0F4ZXMgPSBmdW5jdGlvbihkb1RpdGxlcykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ3JhcGhEaXY7XG4gICAgdmFyIHRpdGxlc3VmZml4ID0gX3RoaXMuaWQuc3Vic3RyKDcpICsgJ3RpdGxlJztcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciBhYXhpcyA9IF90aGlzLmFheGlzO1xuICAgIHZhciBiYXhpcyA9IF90aGlzLmJheGlzO1xuICAgIHZhciBjYXhpcyA9IF90aGlzLmNheGlzO1xuICAgIHZhciBuZXdUaWNrTGF5b3V0O1xuXG4gICAgbmV3VGlja0xheW91dCA9IHN0clRpY2tMYXlvdXQoYWF4aXMpO1xuICAgIGlmKF90aGlzLmFUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVycy5hYXhpcy5zZWxlY3RBbGwoJy55dGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpcy5hVGlja0xheW91dCA9IG5ld1RpY2tMYXlvdXQ7XG4gICAgfVxuXG4gICAgbmV3VGlja0xheW91dCA9IHN0clRpY2tMYXlvdXQoYmF4aXMpO1xuICAgIGlmKF90aGlzLmJUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVycy5iYXhpcy5zZWxlY3RBbGwoJy54dGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpcy5iVGlja0xheW91dCA9IG5ld1RpY2tMYXlvdXQ7XG4gICAgfVxuXG4gICAgbmV3VGlja0xheW91dCA9IHN0clRpY2tMYXlvdXQoY2F4aXMpO1xuICAgIGlmKF90aGlzLmNUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVycy5jYXhpcy5zZWxlY3RBbGwoJy55dGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpcy5jVGlja0xheW91dCA9IG5ld1RpY2tMYXlvdXQ7XG4gICAgfVxuXG4gICAgLy8gM3JkIGFyZyB0cnVlIGJlbG93IHNraXBzIHRpdGxlcywgc28gd2UgY2FuIGNvbmZpZ3VyZSB0aGVtXG4gICAgLy8gY29ycmVjdGx5IGxhdGVyIG9uLlxuICAgIEF4ZXMuZG9UaWNrc1NpbmdsZShnZCwgYWF4aXMsIHRydWUpO1xuICAgIEF4ZXMuZG9UaWNrc1NpbmdsZShnZCwgYmF4aXMsIHRydWUpO1xuICAgIEF4ZXMuZG9UaWNrc1NpbmdsZShnZCwgY2F4aXMsIHRydWUpO1xuXG4gICAgaWYoZG9UaXRsZXMpIHtcbiAgICAgICAgdmFyIGFwYWQgPSBNYXRoLm1heChhYXhpcy5zaG93dGlja2xhYmVscyA/IGFheGlzLnRpY2tmb250LnNpemUgLyAyIDogMCxcbiAgICAgICAgICAgIChjYXhpcy5zaG93dGlja2xhYmVscyA/IGNheGlzLnRpY2tmb250LnNpemUgKiAwLjc1IDogMCkgK1xuICAgICAgICAgICAgKGNheGlzLnRpY2tzID09PSAnb3V0c2lkZScgPyBjYXhpcy50aWNrbGVuICogMC44NyA6IDApKTtcbiAgICAgICAgX3RoaXMubGF5ZXJzWydhLXRpdGxlJ10gPSBUaXRsZXMuZHJhdyhnZCwgJ2EnICsgdGl0bGVzdWZmaXgsIHtcbiAgICAgICAgICAgIHByb3BDb250YWluZXI6IGFheGlzLFxuICAgICAgICAgICAgcHJvcE5hbWU6IF90aGlzLmlkICsgJy5hYXhpcy50aXRsZScsXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIENvbXBvbmVudCBBIHRpdGxlJyksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgeDogX3RoaXMueDAgKyBfdGhpcy53IC8gMixcbiAgICAgICAgICAgICAgICB5OiBfdGhpcy55MCAtIGFheGlzLnRpdGxlZm9udC5zaXplIC8gMyAtIGFwYWQsXG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cblxuICAgICAgICB2YXIgYnBhZCA9IChiYXhpcy5zaG93dGlja2xhYmVscyA/IGJheGlzLnRpY2tmb250LnNpemUgOiAwKSArXG4gICAgICAgICAgICAoYmF4aXMudGlja3MgPT09ICdvdXRzaWRlJyA/IGJheGlzLnRpY2tsZW4gOiAwKSArIDM7XG5cbiAgICAgICAgX3RoaXMubGF5ZXJzWydiLXRpdGxlJ10gPSBUaXRsZXMuZHJhdyhnZCwgJ2InICsgdGl0bGVzdWZmaXgsIHtcbiAgICAgICAgICAgIHByb3BDb250YWluZXI6IGJheGlzLFxuICAgICAgICAgICAgcHJvcE5hbWU6IF90aGlzLmlkICsgJy5iYXhpcy50aXRsZScsXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIENvbXBvbmVudCBCIHRpdGxlJyksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgeDogX3RoaXMueDAgLSBicGFkLFxuICAgICAgICAgICAgICAgIHk6IF90aGlzLnkwICsgX3RoaXMuaCArIGJheGlzLnRpdGxlZm9udC5zaXplICogMC44MyArIGJwYWQsXG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgX3RoaXMubGF5ZXJzWydjLXRpdGxlJ10gPSBUaXRsZXMuZHJhdyhnZCwgJ2MnICsgdGl0bGVzdWZmaXgsIHtcbiAgICAgICAgICAgIHByb3BDb250YWluZXI6IGNheGlzLFxuICAgICAgICAgICAgcHJvcE5hbWU6IF90aGlzLmlkICsgJy5jYXhpcy50aXRsZScsXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIENvbXBvbmVudCBDIHRpdGxlJyksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgeDogX3RoaXMueDAgKyBfdGhpcy53ICsgYnBhZCxcbiAgICAgICAgICAgICAgICB5OiBfdGhpcy55MCArIF90aGlzLmggKyBjYXhpcy50aXRsZWZvbnQuc2l6ZSAqIDAuODMgKyBicGFkLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHN0clRpY2tMYXlvdXQoYXhMYXlvdXQpIHtcbiAgICByZXR1cm4gYXhMYXlvdXQudGlja3MgKyBTdHJpbmcoYXhMYXlvdXQudGlja2xlbikgKyBTdHJpbmcoYXhMYXlvdXQuc2hvd3RpY2tsYWJlbHMpO1xufVxuXG5cbi8vIGhhcmQgY29kZWQgcGF0aHMgZm9yIHpvb20gY29ybmVyc1xuLy8gdXNlcyB0aGUgc2FtZSBzaXppbmcgYXMgY2FydGVzaWFuLCBsZW5ndGggaXMgTUlOWk9PTS8yLCB3aWR0aCBpcyAzcHhcbnZhciBDTEVOID0gY29uc3RhbnRzLk1JTlpPT00gLyAyICsgMC44NztcbnZhciBCTFBBVEggPSAnbS0wLjg3LC41aCcgKyBDTEVOICsgJ3YzaC0nICsgKENMRU4gKyA1LjIpICtcbiAgICAnbCcgKyAoQ0xFTiAvIDIgKyAyLjYpICsgJywtJyArIChDTEVOICogMC44NyArIDQuNSkgK1xuICAgICdsMi42LDEuNWwtJyArIChDTEVOIC8gMikgKyAnLCcgKyAoQ0xFTiAqIDAuODcpICsgJ1onO1xudmFyIEJSUEFUSCA9ICdtMC44NywuNWgtJyArIENMRU4gKyAndjNoJyArIChDTEVOICsgNS4yKSArXG4gICAgJ2wtJyArIChDTEVOIC8gMiArIDIuNikgKyAnLC0nICsgKENMRU4gKiAwLjg3ICsgNC41KSArXG4gICAgJ2wtMi42LDEuNWwnICsgKENMRU4gLyAyKSArICcsJyArIChDTEVOICogMC44NykgKyAnWic7XG52YXIgVE9QUEFUSCA9ICdtMCwxbCcgKyAoQ0xFTiAvIDIpICsgJywnICsgKENMRU4gKiAwLjg3KSArXG4gICAgJ2wyLjYsLTEuNWwtJyArIChDTEVOIC8gMiArIDIuNikgKyAnLC0nICsgKENMRU4gKiAwLjg3ICsgNC41KSArXG4gICAgJ2wtJyArIChDTEVOIC8gMiArIDIuNikgKyAnLCcgKyAoQ0xFTiAqIDAuODcgKyA0LjUpICtcbiAgICAnbDIuNiwxLjVsJyArIChDTEVOIC8gMikgKyAnLC0nICsgKENMRU4gKiAwLjg3KSArICdaJztcbnZhciBTVEFSVE1BUktFUiA9ICdtMC41LDAuNWg1di0yaC01di01aC0ydjVoLTV2Mmg1djVoMlonO1xuXG4vLyBJIGd1ZXNzIHRoaXMgY291bGQgYmUgc2hhcmVkIHdpdGggY2FydGVzaWFuLi4uIGJ1dCBmb3Igbm93IGl0J3Mgc2VwYXJhdGUuXG52YXIgU0hPV1pPT01PVVRUSVAgPSB0cnVlO1xuXG5wcm90by5pbml0SW50ZXJhY3Rpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcyxcbiAgICAgICAgZHJhZ2dlciA9IF90aGlzLmxheWVycy5wbG90Ymcuc2VsZWN0KCdwYXRoJykubm9kZSgpLFxuICAgICAgICBnZCA9IF90aGlzLmdyYXBoRGl2LFxuICAgICAgICB6b29tQ29udGFpbmVyID0gZ2QuX2Z1bGxMYXlvdXQuX3pvb21sYXllcjtcblxuICAgIC8vIHVzZSBwbG90YmcgZm9yIHRoZSBtYWluIGludGVyYWN0aW9uc1xuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZWxlbWVudDogZHJhZ2dlcixcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBwbG90aW5mbzoge1xuICAgICAgICAgICAgaWQ6IF90aGlzLmlkLFxuICAgICAgICAgICAgeGF4aXM6IF90aGlzLnhheGlzLFxuICAgICAgICAgICAgeWF4aXM6IF90aGlzLnlheGlzXG4gICAgICAgIH0sXG4gICAgICAgIHN1YnBsb3Q6IF90aGlzLmlkLFxuICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgICAgICAvLyB0aGVzZSBhcmVuJ3QgYXZhaWxhYmxlIHlldCB3aGVuIGluaXRJbnRlcmFjdGlvbnNcbiAgICAgICAgICAgIC8vIGlzIGNhbGxlZFxuICAgICAgICAgICAgZHJhZ09wdGlvbnMueGF4ZXMgPSBbX3RoaXMueGF4aXNdO1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMueWF4ZXMgPSBbX3RoaXMueWF4aXNdO1xuICAgICAgICAgICAgdmFyIGRyYWdNb2RlTm93ID0gZ2QuX2Z1bGxMYXlvdXQuZHJhZ21vZGU7XG5cbiAgICAgICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAnbGFzc28nKSBkcmFnT3B0aW9ucy5taW5EcmFnID0gMTtcbiAgICAgICAgICAgIGVsc2UgZHJhZ09wdGlvbnMubWluRHJhZyA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgaWYoZHJhZ01vZGVOb3cgPT09ICd6b29tJykge1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IHpvb21Nb3ZlO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmNsaWNrRm4gPSBjbGlja1pvb21QYW47XG4gICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMuZG9uZUZuID0gem9vbURvbmU7XG4gICAgICAgICAgICAgICAgem9vbVByZXAoZSwgc3RhcnRYLCBzdGFydFkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihkcmFnTW9kZU5vdyA9PT0gJ3BhbicpIHtcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5tb3ZlRm4gPSBwbG90RHJhZztcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5jbGlja0ZuID0gY2xpY2tab29tUGFuO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmRvbmVGbiA9IGRyYWdEb25lO1xuICAgICAgICAgICAgICAgIHBhblByZXAoKTtcbiAgICAgICAgICAgICAgICBjbGVhclNlbGVjdCh6b29tQ29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoZHJhZ01vZGVOb3cgPT09ICdzZWxlY3QnIHx8IGRyYWdNb2RlTm93ID09PSAnbGFzc28nKSB7XG4gICAgICAgICAgICAgICAgcHJlcFNlbGVjdChlLCBzdGFydFgsIHN0YXJ0WSwgZHJhZ09wdGlvbnMsIGRyYWdNb2RlTm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgeDAsIHkwLCBtaW5zMCwgc3BhbjAsIG1pbnMsIGx1bSwgcGF0aDAsIGRpbW1lZCwgemIsIGNvcm5lcnM7XG5cbiAgICBmdW5jdGlvbiBjbGlja1pvb21QYW4obnVtQ2xpY2tzLCBldnQpIHtcbiAgICAgICAgdmFyIGNsaWNrTW9kZSA9IGdkLl9mdWxsTGF5b3V0LmNsaWNrbW9kZTtcblxuICAgICAgICByZW1vdmVab29tYm94KGdkKTtcblxuICAgICAgICBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgIHZhciBhdHRycyA9IHt9O1xuICAgICAgICAgICAgYXR0cnNbX3RoaXMuaWQgKyAnLmFheGlzLm1pbiddID0gMDtcbiAgICAgICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5iYXhpcy5taW4nXSA9IDA7XG4gICAgICAgICAgICBhdHRyc1tfdGhpcy5pZCArICcuY2F4aXMubWluJ10gPSAwO1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2RvdWJsZWNsaWNrJywgbnVsbCk7XG4gICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBhdHRycyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjbGlja01vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSAmJiBudW1DbGlja3MgPT09IDEpIHtcbiAgICAgICAgICAgIHNlbGVjdE9uQ2xpY2soZXZ0LCBnZCwgW190aGlzLnhheGlzXSwgW190aGlzLnlheGlzXSwgX3RoaXMuaWQsIGRyYWdPcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBldnQsIF90aGlzLmlkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHpvb21QcmVwKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgIHZhciBkcmFnQkJveCA9IGRyYWdnZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHgwID0gc3RhcnRYIC0gZHJhZ0JCb3gubGVmdDtcbiAgICAgICAgeTAgPSBzdGFydFkgLSBkcmFnQkJveC50b3A7XG4gICAgICAgIG1pbnMwID0ge1xuICAgICAgICAgICAgYTogX3RoaXMuYWF4aXMucmFuZ2VbMF0sXG4gICAgICAgICAgICBiOiBfdGhpcy5iYXhpcy5yYW5nZVsxXSxcbiAgICAgICAgICAgIGM6IF90aGlzLmNheGlzLnJhbmdlWzFdXG4gICAgICAgIH07XG4gICAgICAgIG1pbnMgPSBtaW5zMDtcbiAgICAgICAgc3BhbjAgPSBfdGhpcy5hYXhpcy5yYW5nZVsxXSAtIG1pbnMwLmE7XG4gICAgICAgIGx1bSA9IHRpbnljb2xvcihfdGhpcy5ncmFwaERpdi5fZnVsbExheW91dFtfdGhpcy5pZF0uYmdjb2xvcikuZ2V0THVtaW5hbmNlKCk7XG4gICAgICAgIHBhdGgwID0gJ00wLCcgKyBfdGhpcy5oICsgJ0wnICsgKF90aGlzLncgLyAyKSArICcsIDBMJyArIF90aGlzLncgKyAnLCcgKyBfdGhpcy5oICsgJ1onO1xuICAgICAgICBkaW1tZWQgPSBmYWxzZTtcblxuICAgICAgICB6YiA9IHpvb21Db250YWluZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94JylcbiAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBfdGhpcy54MCArICcsICcgKyBfdGhpcy55MCArICcpJylcbiAgICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ2ZpbGwnOiBsdW0gPiAwLjIgPyAncmdiYSgwLDAsMCwwKScgOiAncmdiYSgyNTUsMjU1LDI1NSwwKScsXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IDBcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYXR0cignZCcsIHBhdGgwKTtcblxuICAgICAgICBjb3JuZXJzID0gem9vbUNvbnRhaW5lci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3pvb21ib3gtY29ybmVycycpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgX3RoaXMueDAgKyAnLCAnICsgX3RoaXMueTAgKyAnKScpXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgIGZpbGw6IENvbG9yLmJhY2tncm91bmQsXG4gICAgICAgICAgICAgICAgc3Ryb2tlOiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCAnTTAsMFonKTtcblxuICAgICAgICBjbGVhclNlbGVjdCh6b29tQ29udGFpbmVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRBRnJhYyh4LCB5KSB7IHJldHVybiAxIC0gKHkgLyBfdGhpcy5oKTsgfVxuICAgIGZ1bmN0aW9uIGdldEJGcmFjKHgsIHkpIHsgcmV0dXJuIDEgLSAoKHggKyAoX3RoaXMuaCAtIHkpIC8gTWF0aC5zcXJ0KDMpKSAvIF90aGlzLncpOyB9XG4gICAgZnVuY3Rpb24gZ2V0Q0ZyYWMoeCwgeSkgeyByZXR1cm4gKCh4IC0gKF90aGlzLmggLSB5KSAvIE1hdGguc3FydCgzKSkgLyBfdGhpcy53KTsgfVxuXG4gICAgZnVuY3Rpb24gem9vbU1vdmUoZHgwLCBkeTApIHtcbiAgICAgICAgdmFyIHgxID0geDAgKyBkeDAsXG4gICAgICAgICAgICB5MSA9IHkwICsgZHkwLFxuICAgICAgICAgICAgYWZyYWMgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBnZXRBRnJhYyh4MCwgeTApLCBnZXRBRnJhYyh4MSwgeTEpKSksXG4gICAgICAgICAgICBiZnJhYyA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGdldEJGcmFjKHgwLCB5MCksIGdldEJGcmFjKHgxLCB5MSkpKSxcbiAgICAgICAgICAgIGNmcmFjID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgZ2V0Q0ZyYWMoeDAsIHkwKSwgZ2V0Q0ZyYWMoeDEsIHkxKSkpLFxuICAgICAgICAgICAgeExlZnQgPSAoKGFmcmFjIC8gMikgKyBjZnJhYykgKiBfdGhpcy53LFxuICAgICAgICAgICAgeFJpZ2h0ID0gKDEgLSAoYWZyYWMgLyAyKSAtIGJmcmFjKSAqIF90aGlzLncsXG4gICAgICAgICAgICB4Q2VudGVyID0gKHhMZWZ0ICsgeFJpZ2h0KSAvIDIsXG4gICAgICAgICAgICB4U3BhbiA9IHhSaWdodCAtIHhMZWZ0LFxuICAgICAgICAgICAgeUJvdHRvbSA9ICgxIC0gYWZyYWMpICogX3RoaXMuaCxcbiAgICAgICAgICAgIHlUb3AgPSB5Qm90dG9tIC0geFNwYW4gLyB3X292ZXJfaDtcblxuICAgICAgICBpZih4U3BhbiA8IGNvbnN0YW50cy5NSU5aT09NKSB7XG4gICAgICAgICAgICBtaW5zID0gbWluczA7XG4gICAgICAgICAgICB6Yi5hdHRyKCdkJywgcGF0aDApO1xuICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgJ00wLDBaJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtaW5zID0ge1xuICAgICAgICAgICAgICAgIGE6IG1pbnMwLmEgKyBhZnJhYyAqIHNwYW4wLFxuICAgICAgICAgICAgICAgIGI6IG1pbnMwLmIgKyBiZnJhYyAqIHNwYW4wLFxuICAgICAgICAgICAgICAgIGM6IG1pbnMwLmMgKyBjZnJhYyAqIHNwYW4wXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgemIuYXR0cignZCcsIHBhdGgwICsgJ00nICsgeExlZnQgKyAnLCcgKyB5Qm90dG9tICtcbiAgICAgICAgICAgICAgICAnSCcgKyB4UmlnaHQgKyAnTCcgKyB4Q2VudGVyICsgJywnICsgeVRvcCArXG4gICAgICAgICAgICAgICAgJ0wnICsgeExlZnQgKyAnLCcgKyB5Qm90dG9tICsgJ1onKTtcbiAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNJyArIHgwICsgJywnICsgeTAgKyBTVEFSVE1BUktFUiArXG4gICAgICAgICAgICAgICAgJ00nICsgeExlZnQgKyAnLCcgKyB5Qm90dG9tICsgQkxQQVRIICtcbiAgICAgICAgICAgICAgICAnTScgKyB4UmlnaHQgKyAnLCcgKyB5Qm90dG9tICsgQlJQQVRIICtcbiAgICAgICAgICAgICAgICAnTScgKyB4Q2VudGVyICsgJywnICsgeVRvcCArIFRPUFBBVEgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWRpbW1lZCkge1xuICAgICAgICAgICAgemIudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgbHVtID4gMC4yID8gJ3JnYmEoMCwwLDAsMC40KScgOlxuICAgICAgICAgICAgICAgICAgICAncmdiYSgyNTUsMjU1LDI1NSwwLjMpJylcbiAgICAgICAgICAgICAgICAuZHVyYXRpb24oMjAwKTtcbiAgICAgICAgICAgIGNvcm5lcnMudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgICAgICAgICAuZHVyYXRpb24oMjAwKTtcbiAgICAgICAgICAgIGRpbW1lZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tRG9uZSgpIHtcbiAgICAgICAgcmVtb3ZlWm9vbWJveChnZCk7XG5cbiAgICAgICAgaWYobWlucyA9PT0gbWluczApIHJldHVybjtcblxuICAgICAgICB2YXIgYXR0cnMgPSB7fTtcbiAgICAgICAgYXR0cnNbX3RoaXMuaWQgKyAnLmFheGlzLm1pbiddID0gbWlucy5hO1xuICAgICAgICBhdHRyc1tfdGhpcy5pZCArICcuYmF4aXMubWluJ10gPSBtaW5zLmI7XG4gICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5jYXhpcy5taW4nXSA9IG1pbnMuYztcblxuICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCBhdHRycyk7XG5cbiAgICAgICAgaWYoU0hPV1pPT01PVVRUSVAgJiYgZ2QuZGF0YSAmJiBnZC5fY29udGV4dC5zaG93VGlwcykge1xuICAgICAgICAgICAgTGliLm5vdGlmaWVyKF8oZ2QsICdEb3VibGUtY2xpY2sgdG8gem9vbSBiYWNrIG91dCcpLCAnbG9uZycpO1xuICAgICAgICAgICAgU0hPV1pPT01PVVRUSVAgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhblByZXAoKSB7XG4gICAgICAgIG1pbnMwID0ge1xuICAgICAgICAgICAgYTogX3RoaXMuYWF4aXMucmFuZ2VbMF0sXG4gICAgICAgICAgICBiOiBfdGhpcy5iYXhpcy5yYW5nZVsxXSxcbiAgICAgICAgICAgIGM6IF90aGlzLmNheGlzLnJhbmdlWzFdXG4gICAgICAgIH07XG4gICAgICAgIG1pbnMgPSBtaW5zMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwbG90RHJhZyhkeCwgZHkpIHtcbiAgICAgICAgdmFyIGR4U2NhbGVkID0gZHggLyBfdGhpcy54YXhpcy5fbSxcbiAgICAgICAgICAgIGR5U2NhbGVkID0gZHkgLyBfdGhpcy55YXhpcy5fbTtcbiAgICAgICAgbWlucyA9IHtcbiAgICAgICAgICAgIGE6IG1pbnMwLmEgLSBkeVNjYWxlZCxcbiAgICAgICAgICAgIGI6IG1pbnMwLmIgKyAoZHhTY2FsZWQgKyBkeVNjYWxlZCkgLyAyLFxuICAgICAgICAgICAgYzogbWluczAuYyAtIChkeFNjYWxlZCAtIGR5U2NhbGVkKSAvIDJcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIG1pbnNvcnRlZCA9IFttaW5zLmEsIG1pbnMuYiwgbWlucy5jXS5zb3J0KCksXG4gICAgICAgICAgICBtaW5pbmRpY2VzID0ge1xuICAgICAgICAgICAgICAgIGE6IG1pbnNvcnRlZC5pbmRleE9mKG1pbnMuYSksXG4gICAgICAgICAgICAgICAgYjogbWluc29ydGVkLmluZGV4T2YobWlucy5iKSxcbiAgICAgICAgICAgICAgICBjOiBtaW5zb3J0ZWQuaW5kZXhPZihtaW5zLmMpXG4gICAgICAgICAgICB9O1xuICAgICAgICBpZihtaW5zb3J0ZWRbMF0gPCAwKSB7XG4gICAgICAgICAgICBpZihtaW5zb3J0ZWRbMV0gKyBtaW5zb3J0ZWRbMF0gLyAyIDwgMCkge1xuICAgICAgICAgICAgICAgIG1pbnNvcnRlZFsyXSArPSBtaW5zb3J0ZWRbMF0gKyBtaW5zb3J0ZWRbMV07XG4gICAgICAgICAgICAgICAgbWluc29ydGVkWzBdID0gbWluc29ydGVkWzFdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1pbnNvcnRlZFsyXSArPSBtaW5zb3J0ZWRbMF0gLyAyO1xuICAgICAgICAgICAgICAgIG1pbnNvcnRlZFsxXSArPSBtaW5zb3J0ZWRbMF0gLyAyO1xuICAgICAgICAgICAgICAgIG1pbnNvcnRlZFswXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtaW5zID0ge1xuICAgICAgICAgICAgICAgIGE6IG1pbnNvcnRlZFttaW5pbmRpY2VzLmFdLFxuICAgICAgICAgICAgICAgIGI6IG1pbnNvcnRlZFttaW5pbmRpY2VzLmJdLFxuICAgICAgICAgICAgICAgIGM6IG1pbnNvcnRlZFttaW5pbmRpY2VzLmNdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZHkgPSAobWluczAuYSAtIG1pbnMuYSkgKiBfdGhpcy55YXhpcy5fbTtcbiAgICAgICAgICAgIGR4ID0gKG1pbnMwLmMgLSBtaW5zLmMgLSBtaW5zMC5iICsgbWlucy5iKSAqIF90aGlzLnhheGlzLl9tO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbW92ZSB0aGUgZGF0YSAodHJhbnNsYXRlLCBkb24ndCByZWRyYXcpXG4gICAgICAgIHZhciBwbG90VHJhbnNmb3JtID0gJ3RyYW5zbGF0ZSgnICsgKF90aGlzLngwICsgZHgpICsgJywnICsgKF90aGlzLnkwICsgZHkpICsgJyknO1xuICAgICAgICBfdGhpcy5wbG90Q29udGFpbmVyLnNlbGVjdEFsbCgnLnNjYXR0ZXJsYXllciwubWFwbGF5ZXInKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHBsb3RUcmFuc2Zvcm0pO1xuXG4gICAgICAgIHZhciBwbG90VHJhbnNmb3JtMiA9ICd0cmFuc2xhdGUoJyArIC1keCArICcsJyArIC1keSArICcpJztcbiAgICAgICAgX3RoaXMuY2xpcERlZlJlbGF0aXZlLnNlbGVjdCgncGF0aCcpLmF0dHIoJ3RyYW5zZm9ybScsIHBsb3RUcmFuc2Zvcm0yKTtcblxuICAgICAgICAvLyBtb3ZlIHRoZSB0aWNrc1xuICAgICAgICBfdGhpcy5hYXhpcy5yYW5nZSA9IFttaW5zLmEsIF90aGlzLnN1bSAtIG1pbnMuYiAtIG1pbnMuY107XG4gICAgICAgIF90aGlzLmJheGlzLnJhbmdlID0gW190aGlzLnN1bSAtIG1pbnMuYSAtIG1pbnMuYywgbWlucy5iXTtcbiAgICAgICAgX3RoaXMuY2F4aXMucmFuZ2UgPSBbX3RoaXMuc3VtIC0gbWlucy5hIC0gbWlucy5iLCBtaW5zLmNdO1xuXG4gICAgICAgIF90aGlzLmRyYXdBeGVzKGZhbHNlKTtcbiAgICAgICAgX3RoaXMucGxvdENvbnRhaW5lci5zZWxlY3RBbGwoJy5jcmlzcCcpLmNsYXNzZWQoJ2NyaXNwJywgZmFsc2UpO1xuXG4gICAgICAgIGlmKF90aGlzLl9oYXNDbGlwT25BeGlzRmFsc2UpIHtcbiAgICAgICAgICAgIF90aGlzLnBsb3RDb250YWluZXJcbiAgICAgICAgICAgICAgICAuc2VsZWN0KCcuc2NhdHRlcmxheWVyJykuc2VsZWN0QWxsKCcudHJhY2UnKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgX3RoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhZ0RvbmUoKSB7XG4gICAgICAgIHZhciBhdHRycyA9IHt9O1xuICAgICAgICBhdHRyc1tfdGhpcy5pZCArICcuYWF4aXMubWluJ10gPSBtaW5zLmE7XG4gICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5iYXhpcy5taW4nXSA9IG1pbnMuYjtcbiAgICAgICAgYXR0cnNbX3RoaXMuaWQgKyAnLmNheGlzLm1pbiddID0gbWlucy5jO1xuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGF0dHJzKTtcbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5LCBzZXQgdXAgaG92ZXIgYW5kIGNsaWNrXG4gICAgLy8gdGhlc2UgZXZlbnQgaGFuZGxlcnMgbXVzdCBhbHJlYWR5IGJlIHNldCBiZWZvcmUgZHJhZ0VsZW1lbnQuaW5pdFxuICAgIC8vIHNvIGl0IGNhbiBzdGFzaCB0aGVtIGFuZCBvdmVycmlkZSB0aGVtLlxuICAgIGRyYWdnZXIub25tb3VzZW1vdmUgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgRnguaG92ZXIoZ2QsIGV2dCwgX3RoaXMuaWQpO1xuICAgICAgICBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyID0gZHJhZ2dlcjtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9IF90aGlzLmlkO1xuICAgIH07XG5cbiAgICBkcmFnZ2VyLm9ubW91c2VvdXQgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgaWYoZ2QuX2RyYWdnaW5nKSByZXR1cm47XG5cbiAgICAgICAgZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCwgZXZ0KTtcbiAgICB9O1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG59O1xuXG5mdW5jdGlvbiByZW1vdmVab29tYm94KGdkKSB7XG4gICAgZDMuc2VsZWN0KGdkKVxuICAgICAgICAuc2VsZWN0QWxsKCcuem9vbWJveCwuanMtem9vbWJveC1iYWNrZHJvcCwuanMtem9vbWJveC1tZW51LC56b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAucmVtb3ZlKCk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMb2dnZXJzID0gcmVxdWlyZSgnLi9saWIvbG9nZ2VycycpO1xudmFyIG5vb3AgPSByZXF1aXJlKCcuL2xpYi9ub29wJyk7XG52YXIgcHVzaFVuaXF1ZSA9IHJlcXVpcmUoJy4vbGliL3B1c2hfdW5pcXVlJyk7XG52YXIgaXNQbGFpbk9iamVjdCA9IHJlcXVpcmUoJy4vbGliL2lzX3BsYWluX29iamVjdCcpO1xudmFyIEV4dGVuZE1vZHVsZSA9IHJlcXVpcmUoJy4vbGliL2V4dGVuZCcpO1xuXG52YXIgYmFzZVBsb3RBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgYmFzZUxheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL3Bsb3RzL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gRXh0ZW5kTW9kdWxlLmV4dGVuZEZsYXQ7XG52YXIgZXh0ZW5kRGVlcEFsbCA9IEV4dGVuZE1vZHVsZS5leHRlbmREZWVwQWxsO1xuXG5leHBvcnRzLm1vZHVsZXMgPSB7fTtcbmV4cG9ydHMuYWxsQ2F0ZWdvcmllcyA9IHt9O1xuZXhwb3J0cy5hbGxUeXBlcyA9IFtdO1xuZXhwb3J0cy5zdWJwbG90c1JlZ2lzdHJ5ID0ge307XG5leHBvcnRzLnRyYW5zZm9ybXNSZWdpc3RyeSA9IHt9O1xuZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnkgPSB7fTtcbmV4cG9ydHMubGF5b3V0QXJyYXlDb250YWluZXJzID0gW107XG5leHBvcnRzLmxheW91dEFycmF5UmVnZXhlcyA9IFtdO1xuZXhwb3J0cy50cmFjZUxheW91dEF0dHJpYnV0ZXMgPSB7fTtcbmV4cG9ydHMubG9jYWxlUmVnaXN0cnkgPSB7fTtcbmV4cG9ydHMuYXBpTWV0aG9kUmVnaXN0cnkgPSB7fTtcblxuLyoqXG4gKiBUb3AtbGV2ZWwgcmVnaXN0ZXIgcm91dGluZSwgZXhwb3J0ZWQgYXMgUGxvdGx5LnJlZ2lzdGVyXG4gKlxuICogQHBhcmFtIHtvYmplY3QgYXJyYXkgb3IgYXJyYXkgb2Ygb2JqZWN0c30gX21vZHVsZXMgOlxuICogIG1vZHVsZSBvYmplY3Qgb3IgbGlzdCBvZiBtb2R1bGUgb2JqZWN0IHRvIHJlZ2lzdGVyLlxuICpcbiAqICBBIHZhbGlkIGBtb2R1bGVUeXBlOiAndHJhY2UnYCBtb2R1bGUgaGFzIGZpZWxkczpcbiAqICAtIG5hbWUge3N0cmluZ30gOiB0aGUgdHJhY2UgdHlwZVxuICogIC0gY2F0ZWdvcmllcyB7YXJyYXl9IDogY2F0ZWdvcmllcyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0cmFjZSB0eXBlLFxuICogICAgICAgICAgICAgICAgICAgICAgICAgdGVzdGVkIHdpdGggUmVnaXN0ZXIudHJhY2VJcygpXG4gKiAgLSBtZXRhIHtvYmplY3R9IDogbWV0YSBpbmZvIChtb3N0bHkgZm9yIHBsb3Qtc2NoZW1hKVxuICpcbiAqICBBIHZhbGlkIGBtb2R1bGVUeXBlOiAnbG9jYWxlJ2AgbW9kdWxlIGhhcyBmaWVsZHM6XG4gKiAgLSBuYW1lIHtzdHJpbmd9IDogdGhlIGxvY2FsZSBuYW1lLiBTaG91bGQgYmUgYSAyLWRpZ2l0IGxhbmd1YWdlIHN0cmluZyAoJ2VuJywgJ2RlJylcbiAqICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGx5IHdpdGggYSBjb3VudHJ5L3JlZ2lvbiBjb2RlICgnZW4tR0InLCAnZGUtQ0gnKS4gSWYgYSBjb3VudHJ5XG4gKiAgICAgICAgICAgICAgICAgICAgY29kZSBpcyB1c2VkIGJ1dCB0aGUgYmFzZSBsYW5ndWFnZSBsb2NhbGUgaGFzIG5vdCB5ZXQgYmVlbiBzdXBwbGllZCxcbiAqICAgICAgICAgICAgICAgICAgICB3ZSB3aWxsIHVzZSB0aGlzIGxvY2FsZSBmb3IgdGhlIGJhc2UgYXMgd2VsbC5cbiAqICAtIGRpY3Rpb25hcnkge29iamVjdH0gOiB0aGUgZGljdGlvbmFyeSBtYXBwaW5nIGlucHV0IHN0cmluZ3MgdG8gbG9jYWxpemVkIHN0cmluZ3NcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcmFsbHkgdGhlIGtleXMgc2hvdWxkIGJlIHRoZSBsaXRlcmFsIGlucHV0IHN0cmluZ3MsIGJ1dFxuICogICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGRlZmF1bHQgdHJhbnNsYXRpb25zIGFyZSBwcm92aWRlZCB5b3UgY2FuIHVzZSBhbnkgc3RyaW5nIGFzIGEga2V5LlxuICogIC0gZm9ybWF0IHtvYmplY3R9IDogYSBgZDMubG9jYWxlYCBmb3JtYXQgc3BlY2lmaWVyIGZvciB0aGlzIGxvY2FsZVxuICogICAgICAgICAgICAgICAgICAgICAgYW55IG9taXR0ZWQga2V5cyB3ZSdsbCBmYWxsIGJhY2sgb24gZW4tVVMuXG4gKlxuICogIEEgdmFsaWQgYG1vZHVsZVR5cGU6ICd0cmFuc2Zvcm0nYCBtb2R1bGUgaGFzIGZpZWxkczpcbiAqICAtIG5hbWUge3N0cmluZ30gOiB0cmFuc2Zvcm0gbmFtZVxuICogIC0gdHJhbnNmb3JtIHtmdW5jdGlvbn0gOiBkZWZhdWx0LWxldmVsIHRyYW5zZm9ybSBmdW5jdGlvblxuICogIC0gY2FsY1RyYW5zZm9ybSB7ZnVuY3Rpb259IDogY2FsYy1sZXZlbCB0cmFuc2Zvcm0gZnVuY3Rpb25cbiAqICAtIGF0dHJpYnV0ZXMge29iamVjdH0gOiB0cmFuc2Zvcm0gYXR0cmlidXRlcyBkZWNsYXJhdGlvbnNcbiAqICAtIHN1cHBseURlZmF1bHRzIHtmdW5jdGlvbn0gOiBhdHRyaWJ1dGVzIGRlZmF1bHQtc3VwcGx5IGZ1bmN0aW9uXG4gKlxuICogIEEgdmFsaWQgYG1vZHVsZVR5cGU6ICdjb21wb25lbnQnYCBtb2R1bGUgaGFzIGZpZWxkczpcbiAqICAtIG5hbWUge3N0cmluZ30gOiB0aGUgY29tcG9uZW50IG5hbWUsIHVzZWQgaXQgd2l0aCBSZWdpc3Rlci5nZXRDb21wb25lbnRNZXRob2QoKVxuICogICAgICAgICAgICAgICAgICAgIHRvIGVtcGxveSBjb21wb25lbnQgbWV0aG9kLlxuICpcbiAqICBBIHZhbGlkIGBtb2R1bGVUeXBlOiAnYXBpTWV0aG9kJ2AgbW9kdWxlIGhhcyBmaWVsZHM6XG4gKiAgLSBuYW1lIHtzdHJpbmd9IDogdGhlIGFwaSBtZXRob2QgbmFtZS5cbiAqICAtIGZuIHtmdW5jdGlvbn0gOiB0aGUgYXBpIG1ldGhvZCBjYWxsZWQgd2l0aCBSZWdpc3Rlci5jYWxsKCk7XG4gKlxuICovXG5leHBvcnRzLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIoX21vZHVsZXMpIHtcbiAgICBpZighX21vZHVsZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhcmd1bWVudCBwYXNzZWQgdG8gUGxvdGx5LnJlZ2lzdGVyLicpO1xuICAgIH0gZWxzZSBpZihfbW9kdWxlcyAmJiAhQXJyYXkuaXNBcnJheShfbW9kdWxlcykpIHtcbiAgICAgICAgX21vZHVsZXMgPSBbX21vZHVsZXNdO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBfbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmV3TW9kdWxlID0gX21vZHVsZXNbaV07XG5cbiAgICAgICAgaWYoIW5ld01vZHVsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZHVsZSB3YXMgYXR0ZW1wdGVkIHRvIGJlIHJlZ2lzdGVyZWQhJyk7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2gobmV3TW9kdWxlLm1vZHVsZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3RyYWNlJzpcbiAgICAgICAgICAgICAgICByZWdpc3RlclRyYWNlTW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0cmFuc2Zvcm0nOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyVHJhbnNmb3JtTW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdjb21wb25lbnQnOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyQ29tcG9uZW50TW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdsb2NhbGUnOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyTG9jYWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdhcGlNZXRob2QnOlxuICAgICAgICAgICAgICAgIHZhciBuYW1lID0gbmV3TW9kdWxlLm5hbWU7XG4gICAgICAgICAgICAgICAgZXhwb3J0cy5hcGlNZXRob2RSZWdpc3RyeVtuYW1lXSA9IG5ld01vZHVsZS5mbjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZHVsZSB3YXMgYXR0ZW1wdGVkIHRvIGJlIHJlZ2lzdGVyZWQhJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKipcbiAqIEdldCByZWdpc3RlcmVkIG1vZHVsZSB1c2luZyB0cmFjZSBvYmplY3Qgb3IgdHJhY2UgdHlwZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fHxzdHJpbmd9IHRyYWNlXG4gKiAgdHJhY2Ugb2JqZWN0IHdpdGggcHJvcCAndHlwZScgb3IgdHJhY2UgdHlwZSBhcyBhIHN0cmluZ1xuICogQHJldHVybiB7b2JqZWN0fVxuICogIG1vZHVsZSBvYmplY3QgY29ycmVzcG9uZGluZyB0byB0cmFjZSB0eXBlXG4gKi9cbmV4cG9ydHMuZ2V0TW9kdWxlID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgX21vZHVsZSA9IGV4cG9ydHMubW9kdWxlc1tnZXRUcmFjZVR5cGUodHJhY2UpXTtcbiAgICBpZighX21vZHVsZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBfbW9kdWxlLl9tb2R1bGU7XG59O1xuXG4vKipcbiAqIERldGVybWluZSBpZiB0aGlzIHRyYWNlIHR5cGUgaXMgaW4gYSBnaXZlbiBjYXRlZ29yeVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fHxzdHJpbmd9IHRyYWNlVHlwZVxuICogIGEgdHJhY2UgKG9iamVjdCkgb3IgdHJhY2UgdHlwZSAoc3RyaW5nKVxuICogQHBhcmFtIHtzdHJpbmd9IGNhdGVnb3J5XG4gKiAgY2F0ZWdvcnkgaW4gcXVlc3Rpb25cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydHMudHJhY2VJcyA9IGZ1bmN0aW9uKHRyYWNlVHlwZSwgY2F0ZWdvcnkpIHtcbiAgICB0cmFjZVR5cGUgPSBnZXRUcmFjZVR5cGUodHJhY2VUeXBlKTtcblxuICAgIC8vIG9sZCBwbG90Lmx5IHdvcmtzcGFjZSBoYWNrLCBub3RoaW5nIHRvIHNlZSBoZXJlXG4gICAgaWYodHJhY2VUeXBlID09PSAndmFyaW91cycpIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBfbW9kdWxlID0gZXhwb3J0cy5tb2R1bGVzW3RyYWNlVHlwZV07XG5cbiAgICBpZighX21vZHVsZSkge1xuICAgICAgICBpZih0cmFjZVR5cGUgJiYgdHJhY2VUeXBlICE9PSAnYXJlYScpIHtcbiAgICAgICAgICAgIExvZ2dlcnMubG9nKCdVbnJlY29nbml6ZWQgdHJhY2UgdHlwZSAnICsgdHJhY2VUeXBlICsgJy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIF9tb2R1bGUgPSBleHBvcnRzLm1vZHVsZXNbYmFzZVBsb3RBdHRyaWJ1dGVzLnR5cGUuZGZsdF07XG4gICAgfVxuXG4gICAgcmV0dXJuICEhX21vZHVsZS5jYXRlZ29yaWVzW2NhdGVnb3J5XTtcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHRoaXMgdHJhY2UgaGFzIGEgdHJhbnNmb3JtIG9mIHRoZSBnaXZlbiB0eXBlIGFuZCByZXR1cm5cbiAqIGFycmF5IG9mIG1hdGNoaW5nIGluZGljZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRhdGFcbiAqICBhIHRyYWNlIG9iamVjdCAobWVtYmVyIG9mIGRhdGEgb3IgZnVsbERhdGEpXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogIHR5cGUgb2YgdHJhY2UgdG8gdGVzdFxuICogQHJldHVybiB7YXJyYXl9XG4gKiAgYXJyYXkgb2YgbWF0Y2hpbmcgaW5kaWNlcy4gSWYgbm9uZSBmb3VuZCwgcmV0dXJucyBbXVxuICovXG5leHBvcnRzLmdldFRyYW5zZm9ybUluZGljZXMgPSBmdW5jdGlvbihkYXRhLCB0eXBlKSB7XG4gICAgdmFyIGluZGljZXMgPSBbXTtcbiAgICB2YXIgdHJhbnNmb3JtcyA9IGRhdGEudHJhbnNmb3JtcyB8fCBbXTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZih0cmFuc2Zvcm1zW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgIGluZGljZXMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5kaWNlcztcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHRoaXMgdHJhY2UgaGFzIGEgdHJhbnNmb3JtIG9mIHRoZSBnaXZlbiB0eXBlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRhdGFcbiAqICBhIHRyYWNlIG9iamVjdCAobWVtYmVyIG9mIGRhdGEgb3IgZnVsbERhdGEpXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogIHR5cGUgb2YgdHJhY2UgdG8gdGVzdFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0cy5oYXNUcmFuc2Zvcm0gPSBmdW5jdGlvbihkYXRhLCB0eXBlKSB7XG4gICAgdmFyIHRyYW5zZm9ybXMgPSBkYXRhLnRyYW5zZm9ybXMgfHwgW107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodHJhbnNmb3Jtc1tpXS50eXBlID09PSB0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIGNvbXBvbmVudCBtb2R1bGUgbWV0aG9kLiBGYWxscyBiYWNrIG9uIG5vb3AgaWYgZWl0aGVyIHRoZVxuICogbW9kdWxlIG9yIHRoZSBtZXRob2QgaXMgbWlzc2luZywgc28gdGhlIHJlc3VsdCBjYW4gYWx3YXlzIGJlIHNhZmVseSBjYWxsZWRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogIG5hbWUgb2YgY29tcG9uZW50IChhcyBkZWNsYXJlZCBpbiBjb21wb25lbnQgbW9kdWxlKVxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZFxuICogIG5hbWUgb2YgY29tcG9uZW50IG1vZHVsZSBtZXRob2RcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufVxuICovXG5leHBvcnRzLmdldENvbXBvbmVudE1ldGhvZCA9IGZ1bmN0aW9uKG5hbWUsIG1ldGhvZCkge1xuICAgIHZhciBfbW9kdWxlID0gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnlbbmFtZV07XG5cbiAgICBpZighX21vZHVsZSkgcmV0dXJuIG5vb3A7XG4gICAgcmV0dXJuIF9tb2R1bGVbbWV0aG9kXSB8fCBub29wO1xufTtcblxuLyoqXG4gKiBDYWxsIHJlZ2lzdGVyZWQgYXBpIG1ldGhvZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSA6IGFwaSBtZXRob2QgbmFtZVxuICogQHBhcmFtIHsuLi5hcnJheX0gYXJncyA6IGFyZ3VtZW50cyBwYXNzZWQgdG8gYXBpIG1ldGhvZFxuICogQHJldHVybiB7YW55fSA6IHJldHVybnMgYXBpIG1ldGhvZCBvdXRwdXRcbiAqL1xuZXhwb3J0cy5jYWxsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG5hbWUgPSBhcmd1bWVudHNbMF07XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIGV4cG9ydHMuYXBpTWV0aG9kUmVnaXN0cnlbbmFtZV0uYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG5mdW5jdGlvbiByZWdpc3RlclRyYWNlTW9kdWxlKF9tb2R1bGUpIHtcbiAgICB2YXIgdGhpc1R5cGUgPSBfbW9kdWxlLm5hbWU7XG4gICAgdmFyIGNhdGVnb3JpZXNJbiA9IF9tb2R1bGUuY2F0ZWdvcmllcztcbiAgICB2YXIgbWV0YSA9IF9tb2R1bGUubWV0YTtcblxuICAgIGlmKGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0pIHtcbiAgICAgICAgTG9nZ2Vycy5sb2coJ1R5cGUgJyArIHRoaXNUeXBlICsgJyBhbHJlYWR5IHJlZ2lzdGVyZWQnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKCFleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnlbX21vZHVsZS5iYXNlUGxvdE1vZHVsZS5uYW1lXSkge1xuICAgICAgICByZWdpc3RlclN1YnBsb3QoX21vZHVsZS5iYXNlUGxvdE1vZHVsZSk7XG4gICAgfVxuXG4gICAgdmFyIGNhdGVnb3J5T2JqID0ge307XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhdGVnb3JpZXNJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYXRlZ29yeU9ialtjYXRlZ29yaWVzSW5baV1dID0gdHJ1ZTtcbiAgICAgICAgZXhwb3J0cy5hbGxDYXRlZ29yaWVzW2NhdGVnb3JpZXNJbltpXV0gPSB0cnVlO1xuICAgIH1cblxuICAgIGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0gPSB7XG4gICAgICAgIF9tb2R1bGU6IF9tb2R1bGUsXG4gICAgICAgIGNhdGVnb3JpZXM6IGNhdGVnb3J5T2JqXG4gICAgfTtcblxuICAgIGlmKG1ldGEgJiYgT2JqZWN0LmtleXMobWV0YSkubGVuZ3RoKSB7XG4gICAgICAgIGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0ubWV0YSA9IG1ldGE7XG4gICAgfVxuXG4gICAgZXhwb3J0cy5hbGxUeXBlcy5wdXNoKHRoaXNUeXBlKTtcblxuICAgIGZvcih2YXIgY29tcG9uZW50TmFtZSBpbiBleHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBtZXJnZUNvbXBvbmVudEF0dHJzVG9UcmFjZShjb21wb25lbnROYW1lLCB0aGlzVHlwZSk7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb2xsZWN0IGFsbCB0cmFjZSBsYXlvdXQgYXR0cmlidXRlcyBpbiBvbmUgcGxhY2UgZm9yIGVhc2llciBsb29rdXAgbGF0ZXJcbiAgICAgKiBidXQgZG9uJ3QgbWVyZ2UgdGhlbSBpbnRvIHRoZSBiYXNlIHNjaGVtYSBhcyBpdCB3b3VsZCBjb25mdXNlIHRoZSBkb2NzXG4gICAgICogKGF0IGxlYXN0IGFmdGVyIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvZG9jdW1lbnRhdGlvbi9pc3N1ZXMvMjAyIGdldHMgZG9uZSEpXG4gICAgICovXG4gICAgaWYoX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKSB7XG4gICAgICAgIGV4dGVuZEZsYXQoZXhwb3J0cy50cmFjZUxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWdpc3RlclN1YnBsb3QoX21vZHVsZSkge1xuICAgIHZhciBwbG90VHlwZSA9IF9tb2R1bGUubmFtZTtcblxuICAgIGlmKGV4cG9ydHMuc3VicGxvdHNSZWdpc3RyeVtwbG90VHlwZV0pIHtcbiAgICAgICAgTG9nZ2Vycy5sb2coJ1Bsb3QgdHlwZSAnICsgcGxvdFR5cGUgKyAnIGFscmVhZHkgcmVnaXN0ZXJlZC4nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIHJlbGF5b3V0IGFycmF5IGhhbmRsaW5nIHdpbGwgbG9vayBmb3IgY29tcG9uZW50IG1vZHVsZSBtZXRob2RzIHdpdGggdGhpc1xuICAgIC8vIG5hbWUgYW5kIHdvbid0IGZpbmQgdGhlbSBiZWNhdXNlIHRoaXMgaXMgYSBzdWJwbG90IG1vZHVsZS4uLiBidXQgdGhhdFxuICAgIC8vIHNob3VsZCBiZSBmaW5lLCBpdCB3aWxsIGp1c3QgZmFsbCBiYWNrIG9uIHJlZHJhd2luZyB0aGUgcGxvdC5cbiAgICBmaW5kQXJyYXlSZWdleHBzKF9tb2R1bGUpO1xuXG4gICAgLy8gbm90IHN1cmUgd2hhdCdzIGJlc3QgZm9yIHRoZSAnY2FydGVzaWFuJyB0eXBlIGF0IHRoaXMgcG9pbnRcbiAgICBleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnlbcGxvdFR5cGVdID0gX21vZHVsZTtcblxuICAgIGZvcih2YXIgY29tcG9uZW50TmFtZSBpbiBleHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBtZXJnZUNvbXBvbmVudEF0dHJzVG9TdWJwbG90KGNvbXBvbmVudE5hbWUsIF9tb2R1bGUubmFtZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWdpc3RlckNvbXBvbmVudE1vZHVsZShfbW9kdWxlKSB7XG4gICAgaWYodHlwZW9mIF9tb2R1bGUubmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb21wb25lbnQgbW9kdWxlICpuYW1lKiBtdXN0IGJlIGEgc3RyaW5nLicpO1xuICAgIH1cblxuICAgIHZhciBuYW1lID0gX21vZHVsZS5uYW1lO1xuICAgIGV4cG9ydHMuY29tcG9uZW50c1JlZ2lzdHJ5W25hbWVdID0gX21vZHVsZTtcblxuICAgIGlmKF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcykge1xuICAgICAgICBpZihfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMuX2lzTGlua2VkVG9BcnJheSkge1xuICAgICAgICAgICAgcHVzaFVuaXF1ZShleHBvcnRzLmxheW91dEFycmF5Q29udGFpbmVycywgbmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluZEFycmF5UmVnZXhwcyhfbW9kdWxlKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIHRyYWNlVHlwZSBpbiBleHBvcnRzLm1vZHVsZXMpIHtcbiAgICAgICAgbWVyZ2VDb21wb25lbnRBdHRyc1RvVHJhY2UobmFtZSwgdHJhY2VUeXBlKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIHN1YnBsb3ROYW1lIGluIGV4cG9ydHMuc3VicGxvdHNSZWdpc3RyeSkge1xuICAgICAgICBtZXJnZUNvbXBvbmVudEF0dHJzVG9TdWJwbG90KG5hbWUsIHN1YnBsb3ROYW1lKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIHRyYW5zZm9ybVR5cGUgaW4gZXhwb3J0cy50cmFuc2Zvcm1zUmVnaXN0cnkpIHtcbiAgICAgICAgbWVyZ2VDb21wb25lbnRBdHRyc1RvVHJhbnNmb3JtKG5hbWUsIHRyYW5zZm9ybVR5cGUpO1xuICAgIH1cblxuICAgIGlmKF9tb2R1bGUuc2NoZW1hICYmIF9tb2R1bGUuc2NoZW1hLmxheW91dCkge1xuICAgICAgICBleHRlbmREZWVwQWxsKGJhc2VMYXlvdXRBdHRyaWJ1dGVzLCBfbW9kdWxlLnNjaGVtYS5sYXlvdXQpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVnaXN0ZXJUcmFuc2Zvcm1Nb2R1bGUoX21vZHVsZSkge1xuICAgIGlmKHR5cGVvZiBfbW9kdWxlLm5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVHJhbnNmb3JtIG1vZHVsZSAqbmFtZSogbXVzdCBiZSBhIHN0cmluZy4nKTtcbiAgICB9XG5cbiAgICB2YXIgcHJlZml4ID0gJ1RyYW5zZm9ybSBtb2R1bGUgJyArIF9tb2R1bGUubmFtZTtcbiAgICB2YXIgaGFzVHJhbnNmb3JtID0gdHlwZW9mIF9tb2R1bGUudHJhbnNmb3JtID09PSAnZnVuY3Rpb24nO1xuICAgIHZhciBoYXNDYWxjVHJhbnNmb3JtID0gdHlwZW9mIF9tb2R1bGUuY2FsY1RyYW5zZm9ybSA9PT0gJ2Z1bmN0aW9uJztcblxuICAgIGlmKCFoYXNUcmFuc2Zvcm0gJiYgIWhhc0NhbGNUcmFuc2Zvcm0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHByZWZpeCArICcgaXMgbWlzc2luZyBhICp0cmFuc2Zvcm0qIG9yICpjYWxjVHJhbnNmb3JtKiBtZXRob2QuJyk7XG4gICAgfVxuICAgIGlmKGhhc1RyYW5zZm9ybSAmJiBoYXNDYWxjVHJhbnNmb3JtKSB7XG4gICAgICAgIExvZ2dlcnMubG9nKFtcbiAgICAgICAgICAgIHByZWZpeCArICcgaGFzIGJvdGggYSAqdHJhbnNmb3JtKiBhbmQgKmNhbGNUcmFuc2Zvcm0qIG1ldGhvZHMuJyxcbiAgICAgICAgICAgICdQbGVhc2Ugbm90ZSB0aGF0IGFsbCAqdHJhbnNmb3JtKiBtZXRob2RzIGFyZSBleGVjdXRlZCcsXG4gICAgICAgICAgICAnYmVmb3JlIGFsbCAqY2FsY1RyYW5zZm9ybSogbWV0aG9kcy4nXG4gICAgICAgIF0uam9pbignICcpKTtcbiAgICB9XG4gICAgaWYoIWlzUGxhaW5PYmplY3QoX21vZHVsZS5hdHRyaWJ1dGVzKSkge1xuICAgICAgICBMb2dnZXJzLmxvZyhwcmVmaXggKyAnIHJlZ2lzdGVyZWQgd2l0aG91dCBhbiAqYXR0cmlidXRlcyogb2JqZWN0LicpO1xuICAgIH1cbiAgICBpZih0eXBlb2YgX21vZHVsZS5zdXBwbHlEZWZhdWx0cyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBMb2dnZXJzLmxvZyhwcmVmaXggKyAnIHJlZ2lzdGVyZWQgd2l0aG91dCBhICpzdXBwbHlEZWZhdWx0cyogbWV0aG9kLicpO1xuICAgIH1cblxuICAgIGV4cG9ydHMudHJhbnNmb3Jtc1JlZ2lzdHJ5W19tb2R1bGUubmFtZV0gPSBfbW9kdWxlO1xuXG4gICAgZm9yKHZhciBjb21wb25lbnROYW1lIGluIGV4cG9ydHMuY29tcG9uZW50c1JlZ2lzdHJ5KSB7XG4gICAgICAgIG1lcmdlQ29tcG9uZW50QXR0cnNUb1RyYW5zZm9ybShjb21wb25lbnROYW1lLCBfbW9kdWxlLm5hbWUpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVnaXN0ZXJMb2NhbGUoX21vZHVsZSkge1xuICAgIHZhciBsb2NhbGUgPSBfbW9kdWxlLm5hbWU7XG4gICAgdmFyIGJhc2VMb2NhbGUgPSBsb2NhbGUuc3BsaXQoJy0nKVswXTtcblxuICAgIHZhciBuZXdEaWN0ID0gX21vZHVsZS5kaWN0aW9uYXJ5O1xuICAgIHZhciBuZXdGb3JtYXQgPSBfbW9kdWxlLmZvcm1hdDtcbiAgICB2YXIgaGFzRGljdCA9IG5ld0RpY3QgJiYgT2JqZWN0LmtleXMobmV3RGljdCkubGVuZ3RoO1xuICAgIHZhciBoYXNGb3JtYXQgPSBuZXdGb3JtYXQgJiYgT2JqZWN0LmtleXMobmV3Rm9ybWF0KS5sZW5ndGg7XG5cbiAgICB2YXIgbG9jYWxlcyA9IGV4cG9ydHMubG9jYWxlUmVnaXN0cnk7XG5cbiAgICB2YXIgbG9jYWxlT2JqID0gbG9jYWxlc1tsb2NhbGVdO1xuICAgIGlmKCFsb2NhbGVPYmopIGxvY2FsZXNbbG9jYWxlXSA9IGxvY2FsZU9iaiA9IHt9O1xuXG4gICAgLy8gU2hvdWxkIHdlIHVzZSB0aGlzIGRpY3QgZm9yIHRoZSBiYXNlIGxvY2FsZT9cbiAgICAvLyBJbiBjYXNlIHdlJ3JlIG92ZXJ3cml0aW5nIGEgcHJldmlvdXMgZGljdCBmb3IgdGhpcyBsb2NhbGUsIGNoZWNrXG4gICAgLy8gd2hldGhlciB0aGUgYmFzZSBtYXRjaGVzIHRoZSBmdWxsIGxvY2FsZSBkaWN0IG5vdy4gSWYgd2UncmUgbm90XG4gICAgLy8gb3ZlcndyaXRpbmcsIGxvY2FsZXNbbG9jYWxlXSBpcyB1bmRlZmluZWQgc28gdGhpcyBqdXN0IGNoZWNrcyBpZlxuICAgIC8vIGJhc2VMb2NhbGUgYWxyZWFkeSBoYWQgYSBkaWN0IG9yIG5vdC5cbiAgICAvLyBTYW1lIGxvZ2ljIGZvciBkYXRlRm9ybWF0c1xuICAgIGlmKGJhc2VMb2NhbGUgIT09IGxvY2FsZSkge1xuICAgICAgICB2YXIgYmFzZUxvY2FsZU9iaiA9IGxvY2FsZXNbYmFzZUxvY2FsZV07XG4gICAgICAgIGlmKCFiYXNlTG9jYWxlT2JqKSBsb2NhbGVzW2Jhc2VMb2NhbGVdID0gYmFzZUxvY2FsZU9iaiA9IHt9O1xuXG4gICAgICAgIGlmKGhhc0RpY3QgJiYgYmFzZUxvY2FsZU9iai5kaWN0aW9uYXJ5ID09PSBsb2NhbGVPYmouZGljdGlvbmFyeSkge1xuICAgICAgICAgICAgYmFzZUxvY2FsZU9iai5kaWN0aW9uYXJ5ID0gbmV3RGljdDtcbiAgICAgICAgfVxuICAgICAgICBpZihoYXNGb3JtYXQgJiYgYmFzZUxvY2FsZU9iai5mb3JtYXQgPT09IGxvY2FsZU9iai5mb3JtYXQpIHtcbiAgICAgICAgICAgIGJhc2VMb2NhbGVPYmouZm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaGFzRGljdCkgbG9jYWxlT2JqLmRpY3Rpb25hcnkgPSBuZXdEaWN0O1xuICAgIGlmKGhhc0Zvcm1hdCkgbG9jYWxlT2JqLmZvcm1hdCA9IG5ld0Zvcm1hdDtcbn1cblxuZnVuY3Rpb24gZmluZEFycmF5UmVnZXhwcyhfbW9kdWxlKSB7XG4gICAgaWYoX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKSB7XG4gICAgICAgIHZhciBhcnJheUF0dHJSZWdleHBzID0gX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzLl9hcnJheUF0dHJSZWdleHBzO1xuICAgICAgICBpZihhcnJheUF0dHJSZWdleHBzKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyYXlBdHRyUmVnZXhwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHB1c2hVbmlxdWUoZXhwb3J0cy5sYXlvdXRBcnJheVJlZ2V4ZXMsIGFycmF5QXR0clJlZ2V4cHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtZXJnZUNvbXBvbmVudEF0dHJzVG9UcmFjZShjb21wb25lbnROYW1lLCB0cmFjZVR5cGUpIHtcbiAgICB2YXIgY29tcG9uZW50U2NoZW1hID0gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnlbY29tcG9uZW50TmFtZV0uc2NoZW1hO1xuICAgIGlmKCFjb21wb25lbnRTY2hlbWEgfHwgIWNvbXBvbmVudFNjaGVtYS50cmFjZXMpIHJldHVybjtcblxuICAgIHZhciB0cmFjZUF0dHJzID0gY29tcG9uZW50U2NoZW1hLnRyYWNlc1t0cmFjZVR5cGVdO1xuICAgIGlmKHRyYWNlQXR0cnMpIHtcbiAgICAgICAgZXh0ZW5kRGVlcEFsbChleHBvcnRzLm1vZHVsZXNbdHJhY2VUeXBlXS5fbW9kdWxlLmF0dHJpYnV0ZXMsIHRyYWNlQXR0cnMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gbWVyZ2VDb21wb25lbnRBdHRyc1RvVHJhbnNmb3JtKGNvbXBvbmVudE5hbWUsIHRyYW5zZm9ybVR5cGUpIHtcbiAgICB2YXIgY29tcG9uZW50U2NoZW1hID0gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnlbY29tcG9uZW50TmFtZV0uc2NoZW1hO1xuICAgIGlmKCFjb21wb25lbnRTY2hlbWEgfHwgIWNvbXBvbmVudFNjaGVtYS50cmFuc2Zvcm1zKSByZXR1cm47XG5cbiAgICB2YXIgdHJhbnNmb3JtQXR0cnMgPSBjb21wb25lbnRTY2hlbWEudHJhbnNmb3Jtc1t0cmFuc2Zvcm1UeXBlXTtcbiAgICBpZih0cmFuc2Zvcm1BdHRycykge1xuICAgICAgICBleHRlbmREZWVwQWxsKGV4cG9ydHMudHJhbnNmb3Jtc1JlZ2lzdHJ5W3RyYW5zZm9ybVR5cGVdLmF0dHJpYnV0ZXMsIHRyYW5zZm9ybUF0dHJzKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG1lcmdlQ29tcG9uZW50QXR0cnNUb1N1YnBsb3QoY29tcG9uZW50TmFtZSwgc3VicGxvdE5hbWUpIHtcbiAgICB2YXIgY29tcG9uZW50U2NoZW1hID0gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnlbY29tcG9uZW50TmFtZV0uc2NoZW1hO1xuICAgIGlmKCFjb21wb25lbnRTY2hlbWEgfHwgIWNvbXBvbmVudFNjaGVtYS5zdWJwbG90cykgcmV0dXJuO1xuXG4gICAgdmFyIHN1YnBsb3RNb2R1bGUgPSBleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnlbc3VicGxvdE5hbWVdO1xuICAgIHZhciBzdWJwbG90QXR0cnMgPSBzdWJwbG90TW9kdWxlLmxheW91dEF0dHJpYnV0ZXM7XG4gICAgdmFyIHN1YnBsb3RBdHRyID0gc3VicGxvdE1vZHVsZS5hdHRyID09PSAnc3VicGxvdCcgPyBzdWJwbG90TW9kdWxlLm5hbWUgOiBzdWJwbG90TW9kdWxlLmF0dHI7XG4gICAgaWYoQXJyYXkuaXNBcnJheShzdWJwbG90QXR0cikpIHN1YnBsb3RBdHRyID0gc3VicGxvdEF0dHJbMF07XG5cbiAgICB2YXIgY29tcG9uZW50TGF5b3V0QXR0cnMgPSBjb21wb25lbnRTY2hlbWEuc3VicGxvdHNbc3VicGxvdEF0dHJdO1xuICAgIGlmKHN1YnBsb3RBdHRycyAmJiBjb21wb25lbnRMYXlvdXRBdHRycykge1xuICAgICAgICBleHRlbmREZWVwQWxsKHN1YnBsb3RBdHRycywgY29tcG9uZW50TGF5b3V0QXR0cnMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0VHJhY2VUeXBlKHRyYWNlVHlwZSkge1xuICAgIGlmKHR5cGVvZiB0cmFjZVR5cGUgPT09ICdvYmplY3QnKSB0cmFjZVR5cGUgPSB0cmFjZVR5cGUudHlwZTtcbiAgICByZXR1cm4gdHJhY2VUeXBlO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcblxudmFyIGV4dGVuZEZsYXQgPSBMaWIuZXh0ZW5kRmxhdDtcbnZhciBleHRlbmREZWVwID0gTGliLmV4dGVuZERlZXA7XG5cbi8vIFB1dCBkZWZhdWx0IHBsb3RUaWxlIGxheW91dHMgaGVyZVxuZnVuY3Rpb24gY2xvbmVMYXlvdXRPdmVycmlkZSh0aWxlQ2xhc3MpIHtcbiAgICB2YXIgb3ZlcnJpZGU7XG5cbiAgICBzd2l0Y2godGlsZUNsYXNzKSB7XG4gICAgICAgIGNhc2UgJ3RoZW1lc19fdGh1bWInOlxuICAgICAgICAgICAgb3ZlcnJpZGUgPSB7XG4gICAgICAgICAgICAgICAgYXV0b3NpemU6IHRydWUsXG4gICAgICAgICAgICAgICAgd2lkdGg6IDE1MCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDE1MCxcbiAgICAgICAgICAgICAgICB0aXRsZTogJycsXG4gICAgICAgICAgICAgICAgc2hvd2xlZ2VuZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiB7bDogNSwgcjogNSwgdDogNSwgYjogNSwgcGFkOiAwfSxcbiAgICAgICAgICAgICAgICBhbm5vdGF0aW9uczogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICd0aHVtYm5haWwnOlxuICAgICAgICAgICAgb3ZlcnJpZGUgPSB7XG4gICAgICAgICAgICAgICAgdGl0bGU6ICcnLFxuICAgICAgICAgICAgICAgIGhpZGVzb3VyY2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNob3dsZWdlbmQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGJvcmRlcndpZHRoOiAwLFxuICAgICAgICAgICAgICAgIGJvcmRlcmNvbG9yOiAnJyxcbiAgICAgICAgICAgICAgICBtYXJnaW46IHtsOiAxLCByOiAxLCB0OiAxLCBiOiAxLCBwYWQ6IDB9LFxuICAgICAgICAgICAgICAgIGFubm90YXRpb25zOiBbXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBvdmVycmlkZSA9IHt9O1xuICAgIH1cblxuXG4gICAgcmV0dXJuIG92ZXJyaWRlO1xufVxuXG5mdW5jdGlvbiBrZXlJc0F4aXMoa2V5TmFtZSkge1xuICAgIHZhciB0eXBlcyA9IFsneGF4aXMnLCAneWF4aXMnLCAnemF4aXMnXTtcbiAgICByZXR1cm4gKHR5cGVzLmluZGV4T2Yoa2V5TmFtZS5zbGljZSgwLCA1KSkgPiAtMSk7XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjbG9uZVBsb3QoZ3JhcGhPYmosIG9wdGlvbnMpIHtcblxuICAgIC8vIFBvbGFyIHBsb3QgY29tcGF0aWJpbGl0eVxuICAgIGlmKGdyYXBoT2JqLmZyYW1ld29yayAmJiBncmFwaE9iai5mcmFtZXdvcmsuaXNQb2xhcikge1xuICAgICAgICBncmFwaE9iaiA9IGdyYXBoT2JqLmZyYW1ld29yay5nZXRDb25maWcoKTtcbiAgICB9XG5cbiAgICB2YXIgaTtcbiAgICB2YXIgb2xkRGF0YSA9IGdyYXBoT2JqLmRhdGE7XG4gICAgdmFyIG9sZExheW91dCA9IGdyYXBoT2JqLmxheW91dDtcbiAgICB2YXIgbmV3RGF0YSA9IGV4dGVuZERlZXAoW10sIG9sZERhdGEpO1xuICAgIHZhciBuZXdMYXlvdXQgPSBleHRlbmREZWVwKHt9LCBvbGRMYXlvdXQsIGNsb25lTGF5b3V0T3ZlcnJpZGUob3B0aW9ucy50aWxlQ2xhc3MpKTtcbiAgICB2YXIgY29udGV4dCA9IGdyYXBoT2JqLl9jb250ZXh0IHx8IHt9O1xuXG4gICAgaWYob3B0aW9ucy53aWR0aCkgbmV3TGF5b3V0LndpZHRoID0gb3B0aW9ucy53aWR0aDtcbiAgICBpZihvcHRpb25zLmhlaWdodCkgbmV3TGF5b3V0LmhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0O1xuXG4gICAgaWYob3B0aW9ucy50aWxlQ2xhc3MgPT09ICd0aHVtYm5haWwnIHx8IG9wdGlvbnMudGlsZUNsYXNzID09PSAndGhlbWVzX190aHVtYicpIHtcbiAgICAgICAgLy8ga2lsbCBhbm5vdGF0aW9uc1xuICAgICAgICBuZXdMYXlvdXQuYW5ub3RhdGlvbnMgPSBbXTtcbiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhuZXdMYXlvdXQpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGtleUlzQXhpcyhrZXlzW2ldKSkge1xuICAgICAgICAgICAgICAgIG5ld0xheW91dFtrZXlzW2ldXS50aXRsZSA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8ga2lsbCBjb2xvcmJhciBhbmQgcGllIGxhYmVsc1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBuZXdEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBuZXdEYXRhW2ldO1xuICAgICAgICAgICAgdHJhY2Uuc2hvd3NjYWxlID0gZmFsc2U7XG4gICAgICAgICAgICBpZih0cmFjZS5tYXJrZXIpIHRyYWNlLm1hcmtlci5zaG93c2NhbGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdwaWUnKSB0cmFjZS50ZXh0cG9zaXRpb24gPSAnbm9uZSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9wdGlvbnMuYW5ub3RhdGlvbnMpKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9wdGlvbnMuYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5ld0xheW91dC5hbm5vdGF0aW9ucy5wdXNoKG9wdGlvbnMuYW5ub3RhdGlvbnNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETzogZG9lcyB0aGlzIHNjZW5lIG1vZGlmaWNhdGlvbiByZWFsbHkgYmVsb25nIGhlcmU/XG4gICAgLy8gSWYgd2Ugc3RpbGwgbmVlZCBpdCwgY2FuIGl0IG1vdmUgaW50byB0aGUgZ2wzZCBtb2R1bGU/XG4gICAgdmFyIHNjZW5lSWRzID0gT2JqZWN0LmtleXMobmV3TGF5b3V0KS5maWx0ZXIoZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIHJldHVybiBrZXkubWF0Y2goL15zY2VuZVxcZCokLyk7XG4gICAgfSk7XG4gICAgaWYoc2NlbmVJZHMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBheGVzSW1hZ2VPdmVycmlkZSA9IHt9O1xuICAgICAgICBpZihvcHRpb25zLnRpbGVDbGFzcyA9PT0gJ3RodW1ibmFpbCcpIHtcbiAgICAgICAgICAgIGF4ZXNJbWFnZU92ZXJyaWRlID0ge1xuICAgICAgICAgICAgICAgIHRpdGxlOiAnJyxcbiAgICAgICAgICAgICAgICBzaG93YXhlc2xhYmVsczogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2hvd3RpY2tsYWJlbHM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGxpbmV0aWNrZW5hYmxlOiBmYWxzZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzY2VuZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNjZW5lID0gbmV3TGF5b3V0W3NjZW5lSWRzW2ldXTtcblxuICAgICAgICAgICAgaWYoIXNjZW5lLnhheGlzKSB7XG4gICAgICAgICAgICAgICAgc2NlbmUueGF4aXMgPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIXNjZW5lLnlheGlzKSB7XG4gICAgICAgICAgICAgICAgc2NlbmUueWF4aXMgPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIXNjZW5lLnpheGlzKSB7XG4gICAgICAgICAgICAgICAgc2NlbmUuemF4aXMgPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZXh0ZW5kRmxhdChzY2VuZS54YXhpcywgYXhlc0ltYWdlT3ZlcnJpZGUpO1xuICAgICAgICAgICAgZXh0ZW5kRmxhdChzY2VuZS55YXhpcywgYXhlc0ltYWdlT3ZlcnJpZGUpO1xuICAgICAgICAgICAgZXh0ZW5kRmxhdChzY2VuZS56YXhpcywgYXhlc0ltYWdlT3ZlcnJpZGUpO1xuXG4gICAgICAgICAgICAvLyBUT0RPIHdoYXQgZG9lcyB0aGlzIGRvP1xuICAgICAgICAgICAgc2NlbmUuX3NjZW5lID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBnZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGlmKG9wdGlvbnMudGlsZUNsYXNzKSBnZC5jbGFzc05hbWUgPSBvcHRpb25zLnRpbGVDbGFzcztcblxuICAgIHZhciBwbG90VGlsZSA9IHtcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICB0ZDogZ2QsIC8vIGZvciBleHRlcm5hbCAoaW1hZ2Ugc2VydmVyKSBjb21wYXRpYmlsaXR5XG4gICAgICAgIGxheW91dDogbmV3TGF5b3V0LFxuICAgICAgICBkYXRhOiBuZXdEYXRhLFxuICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICAgIHN0YXRpY1Bsb3Q6IChvcHRpb25zLnN0YXRpY1Bsb3QgPT09IHVuZGVmaW5lZCkgP1xuICAgICAgICAgICAgICAgIHRydWUgOlxuICAgICAgICAgICAgICAgIG9wdGlvbnMuc3RhdGljUGxvdCxcbiAgICAgICAgICAgIHBsb3RHbFBpeGVsUmF0aW86IChvcHRpb25zLnBsb3RHbFBpeGVsUmF0aW8gPT09IHVuZGVmaW5lZCkgP1xuICAgICAgICAgICAgICAgIDIgOlxuICAgICAgICAgICAgICAgIG9wdGlvbnMucGxvdEdsUGl4ZWxSYXRpbyxcbiAgICAgICAgICAgIGRpc3BsYXlsb2dvOiBvcHRpb25zLmRpc3BsYXlsb2dvIHx8IGZhbHNlLFxuICAgICAgICAgICAgc2hvd0xpbms6IG9wdGlvbnMuc2hvd0xpbmsgfHwgZmFsc2UsXG4gICAgICAgICAgICBzaG93VGlwczogb3B0aW9ucy5zaG93VGlwcyB8fCBmYWxzZSxcbiAgICAgICAgICAgIG1hcGJveEFjY2Vzc1Rva2VuOiBjb250ZXh0Lm1hcGJveEFjY2Vzc1Rva2VuXG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYob3B0aW9ucy5zZXRCYWNrZ3JvdW5kICE9PSAndHJhbnNwYXJlbnQnKSB7XG4gICAgICAgIHBsb3RUaWxlLmNvbmZpZy5zZXRCYWNrZ3JvdW5kID0gb3B0aW9ucy5zZXRCYWNrZ3JvdW5kIHx8ICdvcGFxdWUnO1xuICAgIH1cblxuICAgIC8vIGF0dGFjaGluZyB0aGUgZGVmYXVsdCBMYXlvdXQgdGhlIGdkLCBzbyB5b3UgY2FuIGdyYWIgaXQgbGF0ZXJcbiAgICBwbG90VGlsZS5nZC5kZWZhdWx0TGF5b3V0ID0gY2xvbmVMYXlvdXRPdmVycmlkZShvcHRpb25zLnRpbGVDbGFzcyk7XG5cbiAgICByZXR1cm4gcGxvdFRpbGU7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0b0ltYWdlID0gcmVxdWlyZSgnLi4vcGxvdF9hcGkvdG9faW1hZ2UnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTsgLy8gZm9yIGlzSUVcbnZhciBmaWxlU2F2ZXIgPSByZXF1aXJlKCcuL2ZpbGVzYXZlcicpO1xuXG4vKiogUGxvdGx5LmRvd25sb2FkSW1hZ2VcbiAqXG4gKiBAcGFyYW0ge29iamVjdCB8IHN0cmluZyB8IEhUTUwgZGl2fSBnZFxuICogICBjYW4gZWl0aGVyIGJlIGEgZGF0YS9sYXlvdXQvY29uZmlnIG9iamVjdFxuICogICBvciBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogICBvciBhbiBpZCB0byBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgKHNlZSAuLi9wbG90X2FwaS90b19pbWFnZSlcbiAqIEByZXR1cm4ge3Byb21pc2V9XG4gKi9cbmZ1bmN0aW9uIGRvd25sb2FkSW1hZ2UoZ2QsIG9wdHMpIHtcbiAgICB2YXIgX2dkO1xuICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChnZCkpIF9nZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICAvLyBjaGVjayBmb3IgdW5kZWZpbmVkIG9wdHNcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICAvLyBkZWZhdWx0IHRvIHBuZ1xuICAgIG9wdHMuZm9ybWF0ID0gb3B0cy5mb3JtYXQgfHwgJ3BuZyc7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGlmKF9nZCAmJiBfZ2QuX3NuYXBzaG90SW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignU25hcHNob3R0aW5nIGFscmVhZHkgaW4gcHJvZ3Jlc3MuJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2VlIGNvbW1lbnRzIHdpdGhpbiBzdmd0b2ltZyBmb3IgYWRkaXRpb25hbFxuICAgICAgICAvLyAgIGRpc2N1c3Npb24gb2YgcHJvYmxlbXMgd2l0aCBJRVxuICAgICAgICAvLyAgIGNhbiBub3cgZHJhdyB0byBjYW52YXMsIGJ1dCBDT1JTIHRhaW50ZWQgY2FudmFzXG4gICAgICAgIC8vICAgZG9lcyBub3QgYWxsb3cgdG9EYXRhVVJMXG4gICAgICAgIC8vICAgc3ZnIGZvcm1hdCB3aWxsIHdvcmsgdGhvdWdoXG4gICAgICAgIGlmKExpYi5pc0lFKCkgJiYgb3B0cy5mb3JtYXQgIT09ICdzdmcnKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdTb3JyeSBJRSBkb2VzIG5vdCBzdXBwb3J0IGRvd25sb2FkaW5nIGZyb20gY2FudmFzLiBUcnkge2Zvcm1hdDpcXCdzdmdcXCd9IGluc3RlYWQuJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoX2dkKSBfZ2QuX3NuYXBzaG90SW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgICAgIHZhciBwcm9taXNlID0gdG9JbWFnZShnZCwgb3B0cyk7XG5cbiAgICAgICAgdmFyIGZpbGVuYW1lID0gb3B0cy5maWxlbmFtZSB8fCBnZC5mbiB8fCAnbmV3cGxvdCc7XG4gICAgICAgIGZpbGVuYW1lICs9ICcuJyArIG9wdHMuZm9ybWF0O1xuXG4gICAgICAgIHByb21pc2UudGhlbihmdW5jdGlvbihyZXN1bHQpIHtcbiAgICAgICAgICAgIGlmKF9nZCkgX2dkLl9zbmFwc2hvdEluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBmaWxlU2F2ZXIocmVzdWx0LCBmaWxlbmFtZSk7XG4gICAgICAgIH0pLnRoZW4oZnVuY3Rpb24obmFtZSkge1xuICAgICAgICAgICAgcmVzb2x2ZShuYW1lKTtcbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICBpZihfZ2QpIF9nZC5fc25hcHNob3RJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZG93bmxvYWRJbWFnZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbi8qXG4qIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoaXMgY29kZSBmcm9tIEZpbGVTYXZlci5qc1xuKiBodHRwczovL2dpdGh1Yi5jb20vZWxpZ3JleS9GaWxlU2F2ZXIuanNcbiogTGljZW5zZTogaHR0cHM6Ly9naXRodWIuY29tL2VsaWdyZXkvRmlsZVNhdmVyLmpzL2Jsb2IvbWFzdGVyL0xJQ0VOU0UubWRcbiogRmlsZVNhdmVyLmpzXG4qIEEgc2F2ZUFzKCkgRmlsZVNhdmVyIGltcGxlbWVudGF0aW9uLlxuKiAxLjEuMjAxNjAzMjhcbipcbiogQnkgRWxpIEdyZXksIGh0dHA6Ly9lbGlncmV5LmNvbVxuKiBMaWNlbnNlOiBNSVRcbiogICBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2VsaWdyZXkvRmlsZVNhdmVyLmpzL2Jsb2IvbWFzdGVyL0xJQ0VOU0UubWRcbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZpbGVTYXZlciA9IGZ1bmN0aW9uKHVybCwgbmFtZSkge1xuICAgIHZhciBzYXZlTGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICB2YXIgY2FuVXNlU2F2ZUxpbmsgPSAnZG93bmxvYWQnIGluIHNhdmVMaW5rO1xuICAgIHZhciBpc1NhZmFyaSA9IC9WZXJzaW9uXFwvW1xcZFxcLl0rLipTYWZhcmkvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgdmFyIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgLy8gSUUgPDEwIGlzIGV4cGxpY2l0bHkgdW5zdXBwb3J0ZWRcbiAgICAgICAgaWYodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgL01TSUUgWzEtOV1cXC4vLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0lFIDwgMTAgdW5zdXBwb3J0ZWQnKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaXJzdCB0cnkgYS5kb3dubG9hZCwgdGhlbiB3ZWIgZmlsZXN5c3RlbSwgdGhlbiBvYmplY3QgVVJMc1xuICAgICAgICBpZihpc1NhZmFyaSkge1xuICAgICAgICAgICAgLy8gU2FmYXJpIGRvZXNuJ3QgYWxsb3cgZG93bmxvYWRpbmcgb2YgYmxvYiB1cmxzXG4gICAgICAgICAgICBkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gJ2RhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyArIHVybC5zbGljZSh1cmwuc2VhcmNoKC9bLDtdLykpO1xuICAgICAgICAgICAgcmVzb2x2ZShuYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gJ2Rvd25sb2FkJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNhblVzZVNhdmVMaW5rKSB7XG4gICAgICAgICAgICBzYXZlTGluay5ocmVmID0gdXJsO1xuICAgICAgICAgICAgc2F2ZUxpbmsuZG93bmxvYWQgPSBuYW1lO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChzYXZlTGluayk7XG4gICAgICAgICAgICBzYXZlTGluay5jbGljaygpO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzYXZlTGluayk7XG4gICAgICAgICAgICByZXNvbHZlKG5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSUUgMTArIChuYXRpdmUgc2F2ZUFzKVxuICAgICAgICBpZih0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IubXNTYXZlQmxvYikge1xuICAgICAgICAgICAgLy8gQXQgdGhpcyBwb2ludCB3ZSBhcmUgb25seSBkZWFsaW5nIHdpdGggYSBTVkcgZW5jb2RlZCBhc1xuICAgICAgICAgICAgLy8gYSBkYXRhIFVSTCAoc2luY2UgSUUgb25seSBzdXBwb3J0cyBTVkcpXG4gICAgICAgICAgICB2YXIgZW5jb2RlZCA9IHVybC5zcGxpdCgvXmRhdGE6aW1hZ2VcXC9zdmdcXCt4bWwsLylbMV07XG4gICAgICAgICAgICB2YXIgc3ZnID0gZGVjb2RlVVJJQ29tcG9uZW50KGVuY29kZWQpO1xuICAgICAgICAgICAgbmF2aWdhdG9yLm1zU2F2ZUJsb2IobmV3IEJsb2IoW3N2Z10pLCBuYW1lKTtcbiAgICAgICAgICAgIHJlc29sdmUobmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZWplY3QobmV3IEVycm9yKCdkb3dubG9hZCBlcnJvcicpKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBwcm9taXNlO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmaWxlU2F2ZXI7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5nZXREZWxheSA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICBpZighZnVsbExheW91dC5faGFzKSByZXR1cm4gMDtcblxuICAgIHJldHVybiAoXG4gICAgICAgIGZ1bGxMYXlvdXQuX2hhcygnZ2wzZCcpIHx8XG4gICAgICAgIGZ1bGxMYXlvdXQuX2hhcygnZ2wyZCcpIHx8XG4gICAgICAgIGZ1bGxMYXlvdXQuX2hhcygnbWFwYm94JylcbiAgICApID8gNTAwIDogMDtcbn07XG5cbmV4cG9ydHMuZ2V0UmVkcmF3RnVuYyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCB8fCB7fTtcbiAgICB2YXIgaGFzUG9sYXIgPSBmdWxsTGF5b3V0Ll9oYXMgJiYgZnVsbExheW91dC5faGFzKCdwb2xhcicpO1xuICAgIHZhciBoYXNMZWdhY3lQb2xhciA9ICFoYXNQb2xhciAmJiBnZC5kYXRhICYmIGdkLmRhdGFbMF0gJiYgZ2QuZGF0YVswXS5yO1xuXG4gICAgLy8gZG8gbm90IHdvcmsgZm9yIGxlZ2FjeSBwb2xhclxuICAgIGlmKGhhc0xlZ2FjeVBvbGFyKSByZXR1cm47XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIChnZC5jYWxjZGF0YSB8fCBbXSkuZm9yRWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkWzBdICYmIGRbMF0udCAmJiBkWzBdLnQuY2IpIGRbMF0udC5jYigpO1xuICAgICAgICB9KTtcbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xuXG52YXIgU25hcHNob3QgPSB7XG4gICAgZ2V0RGVsYXk6IGhlbHBlcnMuZ2V0RGVsYXksXG4gICAgZ2V0UmVkcmF3RnVuYzogaGVscGVycy5nZXRSZWRyYXdGdW5jLFxuICAgIGNsb25lOiByZXF1aXJlKCcuL2Nsb25lcGxvdCcpLFxuICAgIHRvU1ZHOiByZXF1aXJlKCcuL3Rvc3ZnJyksXG4gICAgc3ZnVG9JbWc6IHJlcXVpcmUoJy4vc3ZndG9pbWcnKSxcbiAgICB0b0ltYWdlOiByZXF1aXJlKCcuL3RvaW1hZ2UnKSxcbiAgICBkb3dubG9hZEltYWdlOiByZXF1aXJlKCcuL2Rvd25sb2FkJylcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU25hcHNob3Q7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbmZ1bmN0aW9uIHN2Z1RvSW1nKG9wdHMpIHtcbiAgICB2YXIgZXYgPSBvcHRzLmVtaXR0ZXIgfHwgbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgdmFyIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgdmFyIEltYWdlID0gd2luZG93LkltYWdlO1xuICAgICAgICB2YXIgc3ZnID0gb3B0cy5zdmc7XG4gICAgICAgIHZhciBmb3JtYXQgPSBvcHRzLmZvcm1hdCB8fCAncG5nJztcblxuICAgICAgICAvLyBJRSBvbmx5IHN1cHBvcnQgc3ZnXG4gICAgICAgIGlmKExpYi5pc0lFKCkgJiYgZm9ybWF0ICE9PSAnc3ZnJykge1xuICAgICAgICAgICAgdmFyIGllU3ZnRXJyb3IgPSBuZXcgRXJyb3IoJ1NvcnJ5IElFIGRvZXMgbm90IHN1cHBvcnQgZG93bmxvYWRpbmcgZnJvbSBjYW52YXMuIFRyeSB7Zm9ybWF0OlxcJ3N2Z1xcJ30gaW5zdGVhZC4nKTtcbiAgICAgICAgICAgIHJlamVjdChpZVN2Z0Vycm9yKTtcbiAgICAgICAgICAgIC8vIGV2ZW50dWFsbHkgcmVtb3ZlIHRoZSBldlxuICAgICAgICAgICAgLy8gIGluIGZhdm9yIG9mIHByb21pc2VzXG4gICAgICAgICAgICBpZighb3B0cy5wcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV2LmVtaXQoJ2Vycm9yJywgaWVTdmdFcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNhbnZhcyA9IG9wdHMuY2FudmFzO1xuICAgICAgICB2YXIgc2NhbGUgPSBvcHRzLnNjYWxlIHx8IDE7XG4gICAgICAgIHZhciB3MCA9IG9wdHMud2lkdGggfHwgMzAwO1xuICAgICAgICB2YXIgaDAgPSBvcHRzLmhlaWdodCB8fCAxNTA7XG4gICAgICAgIHZhciB3MSA9IHNjYWxlICogdzA7XG4gICAgICAgIHZhciBoMSA9IHNjYWxlICogaDA7XG5cbiAgICAgICAgdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICB2YXIgaW1nID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgLy8gZm9yIFNhZmFyaSBzdXBwb3J0LCBlbGltaW5hdGUgY3JlYXRlT2JqZWN0VVJMXG4gICAgICAgIC8vICB0aGlzIGRlY2lzaW9uIGNvdWxkIGNhdXNlIHByb2JsZW1zIGlmIGNvbnRlbnRcbiAgICAgICAgLy8gIGlzIG5vdCByZXN0cmljdGVkIHRvIHN2Z1xuICAgICAgICB2YXIgdXJsID0gJ2RhdGE6aW1hZ2Uvc3ZnK3htbCwnICsgZW5jb2RlVVJJQ29tcG9uZW50KHN2Zyk7XG5cbiAgICAgICAgY2FudmFzLndpZHRoID0gdzE7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoMTtcblxuICAgICAgICBpbWcub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgaW1nRGF0YTtcblxuICAgICAgICAgICAgLy8gZG9uJ3QgbmVlZCB0byBkcmF3IHRvIGNhbnZhcyBpZiBzdmdcbiAgICAgICAgICAgIC8vICBzYXZlIHNvbWUgdGltZSBhbmQgYWxzbyBhdm9pZCBmYWlsdXJlIG9uIElFXG4gICAgICAgICAgICBpZihmb3JtYXQgIT09ICdzdmcnKSB7XG4gICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWcsIDAsIDAsIHcxLCBoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN3aXRjaChmb3JtYXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdqcGVnJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncG5nJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd3ZWJwJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3dlYnAnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3ZnJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IHVybDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gJ0ltYWdlIGZvcm1hdCBpcyBub3QganBlZywgcG5nLCBzdmcgb3Igd2VicC4nO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGVycm9yTXNnKSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGV2ZW50dWFsbHkgcmVtb3ZlIHRoZSBldlxuICAgICAgICAgICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgICAgICAgICAgaWYoIW9wdHMucHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV2LmVtaXQoJ2Vycm9yJywgZXJyb3JNc2cpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKGltZ0RhdGEpO1xuICAgICAgICAgICAgLy8gZXZlbnR1YWxseSByZW1vdmUgdGhlIGV2XG4gICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgIGlmKCFvcHRzLnByb21pc2UpIHtcbiAgICAgICAgICAgICAgICBldi5lbWl0KCdzdWNjZXNzJywgaW1nRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaW1nLm9uZXJyb3IgPSBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgLy8gZXZlbnR1YWxseSByZW1vdmUgdGhlIGV2XG4gICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgIGlmKCFvcHRzLnByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXYuZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGltZy5zcmMgPSB1cmw7XG4gICAgfSk7XG5cbiAgICAvLyB0ZW1wb3JhcnkgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICAvLyAgbW92ZSB0byBvbmx5IFByb21pc2UgaW4gMi4wLjBcbiAgICAvLyAgYW5kIGVsaW1pbmF0ZSB0aGUgRXZlbnRFbWl0dGVyXG4gICAgaWYob3B0cy5wcm9taXNlKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIHJldHVybiBldjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdmdUb0ltZztcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcjtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcblxudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBjbG9uZVBsb3QgPSByZXF1aXJlKCcuL2Nsb25lcGxvdCcpO1xudmFyIHRvU1ZHID0gcmVxdWlyZSgnLi90b3N2ZycpO1xudmFyIHN2Z1RvSW1nID0gcmVxdWlyZSgnLi9zdmd0b2ltZycpO1xuXG4vKipcbiAqIEBwYXJhbSB7b2JqZWN0fSBnZCBmaWd1cmUgT2JqZWN0XG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyBvcHRpb24gb2JqZWN0XG4gKiBAcGFyYW0gb3B0cy5mb3JtYXQgJ2pwZWcnIHwgJ3BuZycgfCAnd2VicCcgfCAnc3ZnJ1xuICovXG5mdW5jdGlvbiB0b0ltYWdlKGdkLCBvcHRzKSB7XG5cbiAgICAvLyBmaXJzdCBjbG9uZSB0aGUgR0Qgc28gd2UgY2FuIG9wZXJhdGUgaW4gYSBjbGVhbiBlbnZpcm9ubWVudFxuICAgIHZhciBldiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHZhciBjbG9uZSA9IGNsb25lUGxvdChnZCwge2Zvcm1hdDogJ3BuZyd9KTtcbiAgICB2YXIgY2xvbmVkR2QgPSBjbG9uZS5nZDtcblxuICAgIC8vIHB1dCB0aGUgY2xvbmVkIGRpdiBzb21ld2hlcmUgb2ZmIHNjcmVlbiBiZWZvcmUgYXR0YWNoaW5nIHRvIERPTVxuICAgIGNsb25lZEdkLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBjbG9uZWRHZC5zdHlsZS5sZWZ0ID0gJy01MDAwcHgnO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY2xvbmVkR2QpO1xuXG4gICAgZnVuY3Rpb24gd2FpdCgpIHtcbiAgICAgICAgdmFyIGRlbGF5ID0gaGVscGVycy5nZXREZWxheShjbG9uZWRHZC5fZnVsbExheW91dCk7XG5cbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzdmcgPSB0b1NWRyhjbG9uZWRHZCk7XG5cbiAgICAgICAgICAgIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIGNhbnZhcy5pZCA9IExpYi5yYW5kc3RyKCk7XG5cbiAgICAgICAgICAgIGV2ID0gc3ZnVG9JbWcoe1xuICAgICAgICAgICAgICAgIGZvcm1hdDogb3B0cy5mb3JtYXQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGNsb25lZEdkLl9mdWxsTGF5b3V0LndpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogY2xvbmVkR2QuX2Z1bGxMYXlvdXQuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIGNhbnZhczogY2FudmFzLFxuICAgICAgICAgICAgICAgIGVtaXR0ZXI6IGV2LFxuICAgICAgICAgICAgICAgIHN2Zzogc3ZnXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZXYuY2xlYW4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBpZihjbG9uZWRHZCkgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChjbG9uZWRHZCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIH0sIGRlbGF5KTtcbiAgICB9XG5cbiAgICB2YXIgcmVkcmF3RnVuYyA9IGhlbHBlcnMuZ2V0UmVkcmF3RnVuYyhjbG9uZWRHZCk7XG5cbiAgICBSZWdpc3RyeS5jYWxsKCdwbG90JywgY2xvbmVkR2QsIGNsb25lLmRhdGEsIGNsb25lLmxheW91dCwgY2xvbmUuY29uZmlnKVxuICAgICAgICAudGhlbihyZWRyYXdGdW5jKVxuICAgICAgICAudGhlbih3YWl0KVxuICAgICAgICAuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICBldi5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgIH0pO1xuXG5cbiAgICByZXR1cm4gZXY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdG9JbWFnZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgeG1sbnNOYW1lc3BhY2VzID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcbnZhciBET1VCTEVRVU9URV9SRUdFWCA9IC9cIi9nO1xudmFyIERVTU1ZX1NVQiA9ICdUT0JFU1RSSVBQRUQnO1xudmFyIERVTU1ZX1JFR0VYID0gbmV3IFJlZ0V4cCgnKFwiJyArIERVTU1ZX1NVQiArICcpfCgnICsgRFVNTVlfU1VCICsgJ1wiKScsICdnJyk7XG5cbmZ1bmN0aW9uIGh0bWxFbnRpdHlEZWNvZGUocykge1xuICAgIHZhciBoaWRkZW5EaXYgPSBkMy5zZWxlY3QoJ2JvZHknKS5hcHBlbmQoJ2RpdicpLnN0eWxlKHtkaXNwbGF5OiAnbm9uZSd9KS5odG1sKCcnKTtcbiAgICB2YXIgcmVwbGFjZWQgPSBzLnJlcGxhY2UoLygmW147XSo7KS9naSwgZnVuY3Rpb24oZCkge1xuICAgICAgICBpZihkID09PSAnJmx0OycpIHsgcmV0dXJuICcmIzYwOyc7IH0gLy8gc3BlY2lhbCBoYW5kbGluZyBmb3IgYnJhY2tldHNcbiAgICAgICAgaWYoZCA9PT0gJyZydDsnKSB7IHJldHVybiAnJiM2MjsnOyB9XG4gICAgICAgIGlmKGQuaW5kZXhPZignPCcpICE9PSAtMSB8fCBkLmluZGV4T2YoJz4nKSAhPT0gLTEpIHsgcmV0dXJuICcnOyB9XG4gICAgICAgIHJldHVybiBoaWRkZW5EaXYuaHRtbChkKS50ZXh0KCk7IC8vIGV2ZXJ5dGhpbmcgZWxzZSwgbGV0IHRoZSBicm93c2VyIGRlY29kZSBpdCB0byB1bmljb2RlXG4gICAgfSk7XG4gICAgaGlkZGVuRGl2LnJlbW92ZSgpO1xuICAgIHJldHVybiByZXBsYWNlZDtcbn1cblxuZnVuY3Rpb24geG1sRW50aXR5RW5jb2RlKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvJig/IVxcdys7fFxcI1swLTldKzt8IFxcI3hbMC05QS1GXSs7KS9nLCAnJmFtcDsnKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0b1NWRyhnZCwgZm9ybWF0LCBzY2FsZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN2ZyA9IGZ1bGxMYXlvdXQuX3BhcGVyO1xuICAgIHZhciB0b3BwYXBlciA9IGZ1bGxMYXlvdXQuX3RvcHBhcGVyO1xuICAgIHZhciB3aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGg7XG4gICAgdmFyIGhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuICAgIHZhciBpO1xuXG4gICAgLy8gbWFrZSBiYWNrZ3JvdW5kIGNvbG9yIGEgcmVjdCBpbiB0aGUgc3ZnLCB0aGVuIHJldmVydCBhZnRlciBzY3JhcGluZ1xuICAgIC8vIGFsbCBvdGhlciBhbHRlcmF0aW9ucyBoYXZlIGJlZW4gZGVhbHQgd2l0aCBieSBwcm9wZXJseSBwcmVwYXJpbmcgdGhlIHN2Z1xuICAgIC8vIGluIHRoZSBmaXJzdCBwbGFjZS4uLiBsaWtlIHNldHRpbmcgY3Vyc29ycyB3aXRoIGNzcyBjbGFzc2VzIHNvIHdlIGRvbid0XG4gICAgLy8gaGF2ZSB0byByZW1vdmUgdGhlbSwgYW5kIHByb3ZpZGluZyB0aGUgcmlnaHQgbmFtZXNwYWNlcyBpbiB0aGUgc3ZnIHRvXG4gICAgLy8gYmVnaW4gd2l0aFxuICAgIHN2Zy5pbnNlcnQoJ3JlY3QnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRSZWN0LCAwLCAwLCB3aWR0aCwgaGVpZ2h0KVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBmdWxsTGF5b3V0LnBhcGVyX2JnY29sb3IpO1xuXG4gICAgLy8gc3VicGxvdC1zcGVjaWZpYyB0by1TVkcgbWV0aG9kc1xuICAgIC8vIHdoaWNoIG5vdGFibHkgYWRkIHRoZSBjb250ZW50cyBvZiB0aGUgZ2wtY29udGFpbmVyXG4gICAgLy8gaW50byB0aGUgbWFpbiBzdmcgbm9kZVxuICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXMgfHwgW107XG4gICAgZm9yKGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gYmFzZVBsb3RNb2R1bGVzW2ldO1xuXG4gICAgICAgIGlmKF9tb2R1bGUudG9TVkcpIF9tb2R1bGUudG9TVkcoZ2QpO1xuICAgIH1cblxuICAgIC8vIGFkZCB0b3AgaXRlbXMgYWJvdmUgdGhlbSBhc3N1bWVzIGV2ZXJ5dGhpbmcgaW4gdG9wcGFwZXIgaXMgZWl0aGVyXG4gICAgLy8gYSBncm91cCBvciBhIGRlZnMsIGFuZCBpZiBpdCdzIGVtcHR5IChsaWtlIGhvdmVybGF5ZXIpIHdlIGNhbiBpZ25vcmUgaXQuXG4gICAgaWYodG9wcGFwZXIpIHtcbiAgICAgICAgdmFyIG5vZGVzID0gdG9wcGFwZXIubm9kZSgpLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgLy8gbWFrZSBjb3B5IG9mIG5vZGVzIGFzIGNoaWxkTm9kZXMgcHJvcCBnZXRzIG11dGF0ZWQgaW4gbG9vcCBiZWxvd1xuICAgICAgICB2YXIgdG9wR3JvdXBzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobm9kZXMpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHRvcEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRvcEdyb3VwID0gdG9wR3JvdXBzW2ldO1xuXG4gICAgICAgICAgICBpZih0b3BHcm91cC5jaGlsZE5vZGVzLmxlbmd0aCkgc3ZnLm5vZGUoKS5hcHBlbmRDaGlsZCh0b3BHcm91cCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZW1vdmUgZHJhZ2xheWVyIGZvciBBZG9iZSBJbGx1c3RyYXRvciBjb21wYXRpYmlsaXR5XG4gICAgaWYoZnVsbExheW91dC5fZHJhZ2dlcnMpIHtcbiAgICAgICAgZnVsbExheW91dC5fZHJhZ2dlcnMucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgLy8gaW4gY2FzZSB0aGUgc3ZnIGVsZW1lbnQgaGFkIGFuIGV4cGxpY2l0IGJhY2tncm91bmQgY29sb3IsIHJlbW92ZSB0aGlzXG4gICAgLy8gd2Ugd2FudCB0aGUgcmVjdCB0byBnZXQgdGhlIGNvbG9yIHNvIGl0J3MgdGhlIHJpZ2h0IHNpemU7IHN2ZyBiZyB3aWxsXG4gICAgLy8gZmlsbCB3aGF0ZXZlciBjb250YWluZXIgaXQncyBkaXNwbGF5ZWQgaW4gcmVnYXJkbGVzcyBvZiBwbG90IHNpemUuXG4gICAgc3ZnLm5vZGUoKS5zdHlsZS5iYWNrZ3JvdW5kID0gJyc7XG5cbiAgICBzdmcuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoeydkYXRhLXVuZm9ybWF0dGVkJzogbnVsbCwgJ2RhdGEtbWF0aCc6IG51bGx9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB0eHQgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIC8vIGhpZGRlbiB0ZXh0IGlzIHByZS1mb3JtYXR0aW5nIG1hdGhqYXgsIHRoZSBicm93c2VyIGlnbm9yZXMgaXRcbiAgICAgICAgICAgIC8vIGJ1dCBpbiBhIHN0YXRpYyBwbG90IGl0J3MgdXNlbGVzcyBhbmQgaXQgY2FuIGNvbmZ1c2UgYmF0aWtcbiAgICAgICAgICAgIC8vIHdlJ3ZlIHRyaWVkIHRvIHN0YW5kYXJkaXplIG9uIGRpc3BsYXk6bm9uZSBidXQgbWFrZSBzdXJlIHdlIHN0aWxsXG4gICAgICAgICAgICAvLyBjYXRjaCB2aXNpYmlsaXR5OmhpZGRlbiBpZiBpdCBldmVyIGFyaXNlc1xuICAgICAgICAgICAgaWYodGhpcy5zdHlsZS52aXNpYmlsaXR5ID09PSAnaGlkZGVuJyB8fCB0aGlzLnN0eWxlLmRpc3BsYXkgPT09ICdub25lJykge1xuICAgICAgICAgICAgICAgIHR4dC5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBjbGVhciBvdGhlciB2aXNpYmlsaXR5L2Rpc3BsYXkgdmFsdWVzIHRvIGRlZmF1bHRcbiAgICAgICAgICAgICAgICAvLyB0byBub3QgcG90ZW50aWFsbHkgY29uZnVzZSBub24tYnJvd3NlciBTVkcgaW1wbGVtZW50YXRpb25zXG4gICAgICAgICAgICAgICAgdHh0LnN0eWxlKHt2aXNpYmlsaXR5OiBudWxsLCBkaXNwbGF5OiBudWxsfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZvbnQgZmFtaWx5IHN0eWxlcyBicmVhayB0aGluZ3MgYmVjYXVzZSBvZiBxdW90YXRpb24gbWFya3MsXG4gICAgICAgICAgICAvLyBzbyB3ZSBtdXN0IHJlbW92ZSB0aGVtICphZnRlciogdGhlIFNWRyBET00gaGFzIGJlZW4gc2VyaWFsaXplZFxuICAgICAgICAgICAgLy8gdG8gYSBzdHJpbmcgKGJyb3dzZXJzIGNvbnZlcnQgc2luZ2xlcyBiYWNrKVxuICAgICAgICAgICAgdmFyIGZmID0gdGhpcy5zdHlsZS5mb250RmFtaWx5O1xuICAgICAgICAgICAgaWYoZmYgJiYgZmYuaW5kZXhPZignXCInKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0eHQuc3R5bGUoJ2ZvbnQtZmFtaWx5JywgZmYucmVwbGFjZShET1VCTEVRVU9URV9SRUdFWCwgRFVNTVlfU1VCKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgc3ZnLnNlbGVjdEFsbCgnLnBvaW50LCAuc2NhdHRlcnB0cywgLmxlZ2VuZGZpbGw+cGF0aCwgLmxlZ2VuZGxpbmVzPnBhdGgsIC5jYmZpbGwnKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcHQgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgLy8gc2ltaWxhciB0byBmb250IGZhbWlseSBzdHlsZXMgYWJvdmUsXG4gICAgICAgIC8vIHdlIG11c3QgcmVtb3ZlIFwiIGFmdGVyIHRoZSBTVkcgRE9NIGhhcyBiZWVuIHNlcmlhbGl6ZWRcbiAgICAgICAgdmFyIGZpbGwgPSB0aGlzLnN0eWxlLmZpbGw7XG4gICAgICAgIGlmKGZpbGwgJiYgZmlsbC5pbmRleE9mKCd1cmwoJykgIT09IC0xKSB7XG4gICAgICAgICAgICBwdC5zdHlsZSgnZmlsbCcsIGZpbGwucmVwbGFjZShET1VCTEVRVU9URV9SRUdFWCwgRFVNTVlfU1VCKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3Ryb2tlID0gdGhpcy5zdHlsZS5zdHJva2U7XG4gICAgICAgIGlmKHN0cm9rZSAmJiBzdHJva2UuaW5kZXhPZigndXJsKCcpICE9PSAtMSkge1xuICAgICAgICAgICAgcHQuc3R5bGUoJ3N0cm9rZScsIHN0cm9rZS5yZXBsYWNlKERPVUJMRVFVT1RFX1JFR0VYLCBEVU1NWV9TVUIpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYoZm9ybWF0ID09PSAncGRmJyB8fCBmb3JtYXQgPT09ICdlcHMnKSB7XG4gICAgICAgIC8vIHRoZXNlIGZvcm1hdHMgbWFrZSB0aGUgZXh0cmEgbGluZSBNYXRoSmF4IGFkZHMgYXJvdW5kIHN5bWJvbHMgbG9vayBzdXBlciB0aGljayBpbiBzb21lIGNhc2VzXG4gICAgICAgIC8vIGl0IGxvb2tzIGJldHRlciBpZiB0aGlzIGlzIHJlbW92ZWQgZW50aXJlbHkuXG4gICAgICAgIHN2Zy5zZWxlY3RBbGwoJyNNYXRoSmF4X1NWR19nbHlwaHMgcGF0aCcpXG4gICAgICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMCk7XG4gICAgfVxuXG4gICAgLy8gZml4IGZvciBJRSBuYW1lc3BhY2luZyBxdWlyaz9cbiAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE5NjEwMDg5L3Vud2FudGVkLW5hbWVzcGFjZXMtb24tc3ZnLW1hcmt1cC13aGVuLXVzaW5nLXhtbHNlcmlhbGl6ZXItaW4tamF2YXNjcmlwdC13aXRoLWllXG4gICAgc3ZnLm5vZGUoKS5zZXRBdHRyaWJ1dGVOUyh4bWxuc05hbWVzcGFjZXMueG1sbnMsICd4bWxucycsIHhtbG5zTmFtZXNwYWNlcy5zdmcpO1xuICAgIHN2Zy5ub2RlKCkuc2V0QXR0cmlidXRlTlMoeG1sbnNOYW1lc3BhY2VzLnhtbG5zLCAneG1sbnM6eGxpbmsnLCB4bWxuc05hbWVzcGFjZXMueGxpbmspO1xuXG4gICAgaWYoZm9ybWF0ID09PSAnc3ZnJyAmJiBzY2FsZSkge1xuICAgICAgICBzdmcuYXR0cignd2lkdGgnLCBzY2FsZSAqIHdpZHRoKTtcbiAgICAgICAgc3ZnLmF0dHIoJ2hlaWdodCcsIHNjYWxlICogaGVpZ2h0KTtcbiAgICAgICAgc3ZnLmF0dHIoJ3ZpZXdCb3gnLCAnMCAwICcgKyB3aWR0aCArICcgJyArIGhlaWdodCk7XG4gICAgfVxuXG4gICAgdmFyIHMgPSBuZXcgd2luZG93LlhNTFNlcmlhbGl6ZXIoKS5zZXJpYWxpemVUb1N0cmluZyhzdmcubm9kZSgpKTtcbiAgICBzID0gaHRtbEVudGl0eURlY29kZShzKTtcbiAgICBzID0geG1sRW50aXR5RW5jb2RlKHMpO1xuXG4gICAgLy8gRml4IHF1b3RhdGlvbnMgYXJvdW5kIGZvbnQgc3RyaW5ncyBhbmQgZ3JhZGllbnQgVVJMc1xuICAgIHMgPSBzLnJlcGxhY2UoRFVNTVlfUkVHRVgsICdcXCcnKTtcblxuICAgIC8vIElFIGlzIHZlcnkgc3RyaWN0LCBzbyB3ZSB3aWxsIG5lZWQgdG8gY2xlYW5cbiAgICAvLyAgc3ZnIHdpdGggdGhlIGZvbGxvd2luZyByZWdleFxuICAgIC8vICB5ZXMgdGhpcyBpcyBtZXNzeSwgYnV0IGRvIG5vdCBrbm93IGEgYmV0dGVyIHdheVxuICAgIC8vIEV2ZW4gd2l0aCB0aGlzIElFIHdpbGwgbm90IHdvcmsgZHVlIHRvIHRhaW50ZWQgY2FudmFzXG4gICAgLy8gIHNlZSBodHRwczovL2dpdGh1Yi5jb20va2FuZ2F4L2ZhYnJpYy5qcy9pc3N1ZXMvMTk1N1xuICAgIC8vICAgICAgaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xODExMjA0Ny9jYW52YXMtdG9kYXRhdXJsLXdvcmtpbmctaW4tYWxsLWJyb3dzZXJzLWV4Y2VwdC1pZTEwXG4gICAgLy8gTGVhdmUgaGVyZSBqdXN0IGluIGNhc2UgdGhlIENPUlMvdGFpbnRlZCBJRSBpc3N1ZSBnZXRzIHJlc29sdmVkXG4gICAgaWYoTGliLmlzSUUoKSkge1xuICAgICAgICAvLyByZXBsYWNlIGRvdWJsZSBxdW90ZSB3aXRoIHNpbmdsZSBxdW90ZVxuICAgICAgICBzID0gcy5yZXBsYWNlKC9cIi9naSwgJ1xcJycpO1xuICAgICAgICAvLyB1cmwgaW4gc3ZnIGFyZSBzaW5nbGUgcXVvdGVkXG4gICAgICAgIC8vICAgc2luY2Ugd2UgY2hhbmdlZCBkb3VibGUgdG8gc2luZ2xlXG4gICAgICAgIC8vICAgd2UnbGwgbmVlZCB0byBjaGFuZ2UgdGhlc2UgdG8gZG91YmxlLXF1b3RlZFxuICAgICAgICBzID0gcy5yZXBsYWNlKC8oXFwoJyMpKFteJ10qKSgnXFwpKS9naSwgJyhcXFwiIyQyXFxcIiknKTtcbiAgICAgICAgLy8gZm9udCBuYW1lcyB3aXRoIHNwYWNlcyB3aWxsIGJlIGVzY2FwZWQgc2luZ2xlLXF1b3RlZFxuICAgICAgICAvLyAgIHdlJ2xsIG5lZWQgdG8gY2hhbmdlIHRoZXNlIHRvIGRvdWJsZS1xdW90ZWRcbiAgICAgICAgcyA9IHMucmVwbGFjZSgvKFxcXFwnKS9naSwgJ1xcXCInKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG1lcmdlQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9saWInKS5tZXJnZUFycmF5O1xuXG5cbi8vIGFycmF5T2sgYXR0cmlidXRlcywgbWVyZ2UgdGhlbSBpbnRvIGNhbGNkYXRhIGFycmF5XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5c1RvQ2FsY2RhdGEoY2QsIHRyYWNlKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSBjZFtpXS5pID0gaTtcblxuICAgIG1lcmdlQXJyYXkodHJhY2UudGV4dCwgY2QsICd0eCcpO1xuICAgIG1lcmdlQXJyYXkodHJhY2UuaG92ZXJ0ZXh0LCBjZCwgJ2h0eCcpO1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlcjtcbiAgICBpZihtYXJrZXIpIHtcbiAgICAgICAgbWVyZ2VBcnJheShtYXJrZXIub3BhY2l0eSwgY2QsICdtbycpO1xuICAgICAgICBtZXJnZUFycmF5KG1hcmtlci5jb2xvciwgY2QsICdtYycpO1xuXG4gICAgICAgIHZhciBtYXJrZXJMaW5lID0gbWFya2VyLmxpbmU7XG4gICAgICAgIGlmKG1hcmtlckxpbmUpIHtcbiAgICAgICAgICAgIG1lcmdlQXJyYXkobWFya2VyTGluZS5jb2xvciwgY2QsICdtbGMnKTtcbiAgICAgICAgICAgIG1lcmdlQXJyYXkobWFya2VyTGluZS53aWR0aCwgY2QsICdtbHcnKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yYmFyQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMnKTtcbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHRleHRGb250QXR0cnMgPSBmb250QXR0cnMoe1xuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgYXJyYXlPazogdHJ1ZSxcbiAgICBjb2xvckVkaXRUeXBlOiAnc3R5bGUnLFxuICAgIFxufSk7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxudmFyIG1hcmtlckxpbmVXaWR0aCA9IGV4dGVuZEZsYXQoe30sXG4gICAgc2NhdHRlck1hcmtlckxpbmVBdHRycy53aWR0aCwgeyBkZmx0OiAwIH0pO1xuXG52YXIgbWFya2VyTGluZSA9IGV4dGVuZEZsYXQoe1xuICAgIHdpZHRoOiBtYXJrZXJMaW5lV2lkdGgsXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSwgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScpKTtcblxudmFyIG1hcmtlciA9IGV4dGVuZEZsYXQoe1xuICAgIGxpbmU6IG1hcmtlckxpbmUsXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSwgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXInKSwge1xuICAgIGNvbG9yYmFyOiBjb2xvcmJhckF0dHJzLFxuICAgIG9wYWNpdHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB4OiBzY2F0dGVyQXR0cnMueCxcbiAgICB4MDogc2NhdHRlckF0dHJzLngwLFxuICAgIGR4OiBzY2F0dGVyQXR0cnMuZHgsXG4gICAgeTogc2NhdHRlckF0dHJzLnksXG4gICAgeTA6IHNjYXR0ZXJBdHRycy55MCxcbiAgICBkeTogc2NhdHRlckF0dHJzLmR5LFxuXG4gICAgdGV4dDogc2NhdHRlckF0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBzY2F0dGVyQXR0cnMuaG92ZXJ0ZXh0LFxuXG4gICAgdGV4dHBvc2l0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydpbnNpZGUnLCAnb3V0c2lkZScsICdhdXRvJywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dGZvbnQ6IGV4dGVuZEZsYXQoe30sIHRleHRGb250QXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBpbnNpZGV0ZXh0Zm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG91dHNpZGV0ZXh0Zm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGNvbnN0cmFpbnRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnaW5zaWRlJywgJ291dHNpZGUnLCAnYm90aCcsICdub25lJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnYm90aCcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjbGlwb25heGlzOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuY2xpcG9uYXhpcywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyd2JywgJ2gnXSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGJhc2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb2Zmc2V0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFya2VyOiBtYXJrZXIsXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSxcbiAgICAgICAgICAgIGNvbG9yOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQubWFya2VyLmNvbG9yLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICAgICAgfSxcbiAgICAgICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZC50ZXh0Zm9udCxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9LFxuICAgIHVuc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSxcbiAgICAgICAgICAgIGNvbG9yOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZC5tYXJrZXIuY29sb3IsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQudGV4dGZvbnQsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIHI6IHNjYXR0ZXJBdHRycy5yLFxuICAgIHQ6IHNjYXR0ZXJBdHRycy50LFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgYmFyZGlyOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICB2YWx1ZXM6IFsndicsICdoJ10sXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hhc19jb2xvcnNjYWxlJyk7XG52YXIgY29sb3JzY2FsZUNhbGMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSByZXF1aXJlKCcuL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSByZXF1aXJlKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICB2YXIgc2l6ZSwgcG9zO1xuXG4gICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICBzaXplID0geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpO1xuICAgICAgICBwb3MgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd5Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2l6ZSA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKTtcbiAgICAgICAgcG9zID0geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0aGUgXCJjYWxjdWxhdGVkIGRhdGFcIiB0byBwbG90XG4gICAgdmFyIHNlcmllc2xlbiA9IE1hdGgubWluKHBvcy5sZW5ndGgsIHNpemUubGVuZ3RoKTtcbiAgICB2YXIgY2QgPSBuZXcgQXJyYXkoc2VyaWVzbGVuKTtcblxuICAgIC8vIHNldCBwb3NpdGlvbiBhbmQgc2l6ZVxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICBjZFtpXSA9IHsgcDogcG9zW2ldLCBzOiBzaXplW2ldIH07XG5cbiAgICAgICAgaWYodHJhY2UuaWRzKSB7XG4gICAgICAgICAgICBjZFtpXS5pZCA9IFN0cmluZyh0cmFjZS5pZHNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gYXV0by16IGFuZCBhdXRvY29sb3JzY2FsZSBpZiBhcHBsaWNhYmxlXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZSwgJ21hcmtlcicpKSB7XG4gICAgICAgIGNvbG9yc2NhbGVDYWxjKHRyYWNlLCB0cmFjZS5tYXJrZXIuY29sb3IsICdtYXJrZXInLCAnYycpO1xuICAgIH1cbiAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UubWFya2VyLmxpbmUuY29sb3IsICdtYXJrZXIubGluZScsICdjJyk7XG4gICAgfVxuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBTaWV2ZSA9IHJlcXVpcmUoJy4vc2lldmUuanMnKTtcblxuLypcbiAqIEJhciBjaGFydCBzdGFja2luZy9ncm91cGluZyBwb3NpdGlvbmluZyBhbmQgYXV0b3NjYWxpbmcgY2FsY3VsYXRpb25zXG4gKiBmb3IgZWFjaCBkaXJlY3Rpb24gc2VwYXJhdGVseSBjYWxjdWxhdGUgdGhlIHJhbmdlcyBhbmQgcG9zaXRpb25zXG4gKiBub3RlIHRoYXQgdGhpcyBoYW5kbGVzIGhpc3RvZ3JhbXMgdG9vXG4gKiBub3cgZG9pbmcgdGhpcyBvbmUgc3VicGxvdCBhdCBhIHRpbWVcbiAqL1xuXG5mdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCwgcGxvdGluZm8pIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcyxcbiAgICAgICAgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIHZhciBmdWxsVHJhY2VzID0gZ2QuX2Z1bGxEYXRhLFxuICAgICAgICBjYWxjVHJhY2VzID0gZ2QuY2FsY2RhdGEsXG4gICAgICAgIGNhbGNUcmFjZXNIb3Jpem9udGFsID0gW10sXG4gICAgICAgIGNhbGNUcmFjZXNWZXJ0aWNhbCA9IFtdLFxuICAgICAgICBpO1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZ1bGxUcmFjZSA9IGZ1bGxUcmFjZXNbaV07XG4gICAgICAgIGlmKFxuICAgICAgICAgICAgZnVsbFRyYWNlLnZpc2libGUgPT09IHRydWUgJiZcbiAgICAgICAgICAgIFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAnYmFyJykgJiZcbiAgICAgICAgICAgIGZ1bGxUcmFjZS54YXhpcyA9PT0geGEuX2lkICYmXG4gICAgICAgICAgICBmdWxsVHJhY2UueWF4aXMgPT09IHlhLl9pZFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGlmKGZ1bGxUcmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgY2FsY1RyYWNlc0hvcml6b250YWwucHVzaChjYWxjVHJhY2VzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGNUcmFjZXNWZXJ0aWNhbC5wdXNoKGNhbGNUcmFjZXNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0R3JvdXBQb3NpdGlvbnMoZ2QsIHhhLCB5YSwgY2FsY1RyYWNlc1ZlcnRpY2FsKTtcbiAgICBzZXRHcm91cFBvc2l0aW9ucyhnZCwgeWEsIHhhLCBjYWxjVHJhY2VzSG9yaXpvbnRhbCk7XG59XG5cbmZ1bmN0aW9uIHNldEdyb3VwUG9zaXRpb25zKGdkLCBwYSwgc2EsIGNhbGNUcmFjZXMpIHtcbiAgICBpZighY2FsY1RyYWNlcy5sZW5ndGgpIHJldHVybjtcblxuICAgIHZhciBiYXJtb2RlID0gZ2QuX2Z1bGxMYXlvdXQuYmFybW9kZSxcbiAgICAgICAgb3ZlcmxheSA9IChiYXJtb2RlID09PSAnb3ZlcmxheScpLFxuICAgICAgICBncm91cCA9IChiYXJtb2RlID09PSAnZ3JvdXAnKSxcbiAgICAgICAgZXhjbHVkZWQsXG4gICAgICAgIGluY2x1ZGVkLFxuICAgICAgICBpLCBjYWxjVHJhY2UsIGZ1bGxUcmFjZTtcblxuICAgIGluaXRCYXNlKGdkLCBwYSwgc2EsIGNhbGNUcmFjZXMpO1xuXG4gICAgaWYob3ZlcmxheSkge1xuICAgICAgICBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGUoZ2QsIHBhLCBzYSwgY2FsY1RyYWNlcyk7XG4gICAgfVxuICAgIGVsc2UgaWYoZ3JvdXApIHtcbiAgICAgICAgLy8gZXhjbHVkZSBmcm9tIHRoZSBncm91cCB0aG9zZSB0cmFjZXMgZm9yIHdoaWNoIHRoZSB1c2VyIHNldCBhbiBvZmZzZXRcbiAgICAgICAgZXhjbHVkZWQgPSBbXTtcbiAgICAgICAgaW5jbHVkZWQgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgICAgIGZ1bGxUcmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICAgICAgaWYoZnVsbFRyYWNlLm9mZnNldCA9PT0gdW5kZWZpbmVkKSBpbmNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICBlbHNlIGV4Y2x1ZGVkLnB1c2goY2FsY1RyYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGluY2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgc2V0R3JvdXBQb3NpdGlvbnNJbkdyb3VwTW9kZShnZCwgcGEsIHNhLCBpbmNsdWRlZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoZXhjbHVkZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGUoZ2QsIHBhLCBzYSwgZXhjbHVkZWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyBleGNsdWRlIGZyb20gdGhlIHN0YWNrIHRob3NlIHRyYWNlcyBmb3Igd2hpY2ggdGhlIHVzZXIgc2V0IGEgYmFzZVxuICAgICAgICBleGNsdWRlZCA9IFtdO1xuICAgICAgICBpbmNsdWRlZCA9IFtdO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuICAgICAgICAgICAgZnVsbFRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgICAgICBpZihmdWxsVHJhY2UuYmFzZSA9PT0gdW5kZWZpbmVkKSBpbmNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICBlbHNlIGV4Y2x1ZGVkLnB1c2goY2FsY1RyYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGluY2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgc2V0R3JvdXBQb3NpdGlvbnNJblN0YWNrT3JSZWxhdGl2ZU1vZGUoZ2QsIHBhLCBzYSwgaW5jbHVkZWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGV4Y2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgc2V0R3JvdXBQb3NpdGlvbnNJbk92ZXJsYXlNb2RlKGdkLCBwYSwgc2EsIGV4Y2x1ZGVkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbGxlY3RFeHRlbnRzKGNhbGNUcmFjZXMsIHBhKTtcbn1cblxuZnVuY3Rpb24gaW5pdEJhc2UoZ2QsIHBhLCBzYSwgY2FsY1RyYWNlcykge1xuICAgIHZhciBpLCBqO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2QgPSBjYWxjVHJhY2VzW2ldO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICAgICAgdmFyIGJhc2UgPSB0cmFjZS5iYXNlO1xuICAgICAgICB2YXIgYjtcblxuICAgICAgICAvLyBub3Qgc3VyZSBpZiBpdCByZWFsbHkgbWFrZXMgc2Vuc2UgdG8gaGF2ZSBkYXRlcyBmb3IgYmFyIHNpemUgZGF0YS4uLlxuICAgICAgICAvLyBpZGVhbGx5IGlmIHdlIHdhbnQgdG8gbWFrZSBnYW50dCBjaGFydHMgb3Igc29tZXRoaW5nIHdlJ2QgdHJlYXRcbiAgICAgICAgLy8gdGhlIGFjdHVhbCBzaXplICh0cmFjZS54IG9yIHkpIGFzIHRpbWUgZGVsdGEgYnV0IGJhc2UgYXMgYWJzb2x1dGVcbiAgICAgICAgLy8gdGltZS4gQnV0IGluY2x1ZGVkIGhlcmUgZm9yIGNvbXBsZXRlbmVzcy5cbiAgICAgICAgdmFyIHNjYWxlbmRhciA9IHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcgPyB0cmFjZS54Y2FsZW5kYXIgOiB0cmFjZS55Y2FsZW5kYXI7XG5cbiAgICAgICAgaWYoaXNBcnJheU9yVHlwZWRBcnJheShiYXNlKSkge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgTWF0aC5taW4oYmFzZS5sZW5ndGgsIGNkLmxlbmd0aCk7IGorKykge1xuICAgICAgICAgICAgICAgIGIgPSBzYS5kMmMoYmFzZVtqXSwgMCwgc2NhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICBpZihpc051bWVyaWMoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgY2Rbal0uYiA9ICtiO1xuICAgICAgICAgICAgICAgICAgICBjZFtqXS5oYXNCID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBjZFtqXS5iID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvcig7IGogPCBjZC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGNkW2pdLmIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYiA9IHNhLmQyYyhiYXNlLCAwLCBzY2FsZW5kYXIpO1xuICAgICAgICAgICAgdmFyIGhhc0Jhc2UgPSBpc051bWVyaWMoYik7XG4gICAgICAgICAgICBiID0gaGFzQmFzZSA/IGIgOiAwO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjZFtqXS5iID0gYjtcbiAgICAgICAgICAgICAgICBpZihoYXNCYXNlKSBjZFtqXS5oYXNCID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGUoZ2QsIHBhLCBzYSwgY2FsY1RyYWNlcykge1xuICAgIHZhciBiYXJub3JtID0gZ2QuX2Z1bGxMYXlvdXQuYmFybm9ybSxcbiAgICAgICAgc2VwYXJhdGVOZWdhdGl2ZVZhbHVlcyA9IGZhbHNlLFxuICAgICAgICBkb250TWVyZ2VPdmVybGFwcGluZ0RhdGEgPSAhYmFybm9ybTtcblxuICAgIC8vIHVwZGF0ZSBwb3NpdGlvbiBheGlzIGFuZCBzZXQgYmFyIG9mZnNldHMgYW5kIHdpZHRoc1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuXG4gICAgICAgIHZhciBzaWV2ZSA9IG5ldyBTaWV2ZShcbiAgICAgICAgICAgIFtjYWxjVHJhY2VdLCBzZXBhcmF0ZU5lZ2F0aXZlVmFsdWVzLCBkb250TWVyZ2VPdmVybGFwcGluZ0RhdGFcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBzZXQgYmFyIG9mZnNldHMgYW5kIHdpZHRocywgYW5kIHVwZGF0ZSBwb3NpdGlvbiBheGlzXG4gICAgICAgIHNldE9mZnNldEFuZFdpZHRoKGdkLCBwYSwgc2lldmUpO1xuXG4gICAgICAgIC8vIHNldCBiYXIgYmFzZXMgYW5kIHNpemVzLCBhbmQgdXBkYXRlIHNpemUgYXhpc1xuICAgICAgICAvL1xuICAgICAgICAvLyAobm90ZSB0aGF0IGBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGVgIGhhbmRsZXMgdGhlIGNhc2UgYmFybm9ybVxuICAgICAgICAvLyBpcyBkZWZpbmVkLCBiZWNhdXNlIHRoaXMgZnVuY3Rpb24gaXMgYWxzbyBpbnZva2VkIGZvciB0cmFjZXMgdGhhdFxuICAgICAgICAvLyBjYW4ndCBiZSBncm91cGVkIG9yIHN0YWNrZWQpXG4gICAgICAgIGlmKGJhcm5vcm0pIHtcbiAgICAgICAgICAgIHNpZXZlQmFycyhnZCwgc2EsIHNpZXZlKTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZUJhcnMoZ2QsIHNhLCBzaWV2ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZXRCYXNlQW5kVG9wKGdkLCBzYSwgc2lldmUpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIHNldEdyb3VwUG9zaXRpb25zSW5Hcm91cE1vZGUoZ2QsIHBhLCBzYSwgY2FsY1RyYWNlcykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQsXG4gICAgICAgIGJhcm5vcm0gPSBmdWxsTGF5b3V0LmJhcm5vcm0sXG4gICAgICAgIHNlcGFyYXRlTmVnYXRpdmVWYWx1ZXMgPSBmYWxzZSxcbiAgICAgICAgZG9udE1lcmdlT3ZlcmxhcHBpbmdEYXRhID0gIWJhcm5vcm0sXG4gICAgICAgIHNpZXZlID0gbmV3IFNpZXZlKFxuICAgICAgICAgICAgICAgIGNhbGNUcmFjZXMsIHNlcGFyYXRlTmVnYXRpdmVWYWx1ZXMsIGRvbnRNZXJnZU92ZXJsYXBwaW5nRGF0YVxuICAgICAgICAgICAgKTtcblxuICAgIC8vIHNldCBiYXIgb2Zmc2V0cyBhbmQgd2lkdGhzLCBhbmQgdXBkYXRlIHBvc2l0aW9uIGF4aXNcbiAgICBzZXRPZmZzZXRBbmRXaWR0aEluR3JvdXBNb2RlKGdkLCBwYSwgc2lldmUpO1xuXG4gICAgLy8gc2V0IGJhciBiYXNlcyBhbmQgc2l6ZXMsIGFuZCB1cGRhdGUgc2l6ZSBheGlzXG4gICAgaWYoYmFybm9ybSkge1xuICAgICAgICBzaWV2ZUJhcnMoZ2QsIHNhLCBzaWV2ZSk7XG4gICAgICAgIG5vcm1hbGl6ZUJhcnMoZ2QsIHNhLCBzaWV2ZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBzZXRCYXNlQW5kVG9wKGdkLCBzYSwgc2lldmUpO1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBzZXRHcm91cFBvc2l0aW9uc0luU3RhY2tPclJlbGF0aXZlTW9kZShnZCwgcGEsIHNhLCBjYWxjVHJhY2VzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCxcbiAgICAgICAgYmFybW9kZSA9IGZ1bGxMYXlvdXQuYmFybW9kZSxcbiAgICAgICAgc3RhY2sgPSAoYmFybW9kZSA9PT0gJ3N0YWNrJyksXG4gICAgICAgIHJlbGF0aXZlID0gKGJhcm1vZGUgPT09ICdyZWxhdGl2ZScpLFxuICAgICAgICBiYXJub3JtID0gZ2QuX2Z1bGxMYXlvdXQuYmFybm9ybSxcbiAgICAgICAgc2VwYXJhdGVOZWdhdGl2ZVZhbHVlcyA9IHJlbGF0aXZlLFxuICAgICAgICBkb250TWVyZ2VPdmVybGFwcGluZ0RhdGEgPSAhKGJhcm5vcm0gfHwgc3RhY2sgfHwgcmVsYXRpdmUpLFxuICAgICAgICBzaWV2ZSA9IG5ldyBTaWV2ZShcbiAgICAgICAgICAgICAgICBjYWxjVHJhY2VzLCBzZXBhcmF0ZU5lZ2F0aXZlVmFsdWVzLCBkb250TWVyZ2VPdmVybGFwcGluZ0RhdGFcbiAgICAgICAgICAgICk7XG5cbiAgICAvLyBzZXQgYmFyIG9mZnNldHMgYW5kIHdpZHRocywgYW5kIHVwZGF0ZSBwb3NpdGlvbiBheGlzXG4gICAgc2V0T2Zmc2V0QW5kV2lkdGgoZ2QsIHBhLCBzaWV2ZSk7XG5cbiAgICAvLyBzZXQgYmFyIGJhc2VzIGFuZCBzaXplcywgYW5kIHVwZGF0ZSBzaXplIGF4aXNcbiAgICBzdGFja0JhcnMoZ2QsIHNhLCBzaWV2ZSk7XG5cbiAgICAvLyBmbGFnIHRoZSBvdXRtb3N0IGJhciAoZm9yIHRleHQgZGlzcGxheSBwdXJwb3NlcylcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYmFyID0gY2FsY1RyYWNlW2pdO1xuXG4gICAgICAgICAgICBpZihiYXIucyA9PT0gQkFETlVNKSBjb250aW51ZTtcblxuICAgICAgICAgICAgdmFyIGlzT3V0bW9zdEJhciA9ICgoYmFyLmIgKyBiYXIucykgPT09IHNpZXZlLmdldChiYXIucCwgYmFyLnMpKTtcbiAgICAgICAgICAgIGlmKGlzT3V0bW9zdEJhcikgYmFyLl9vdXRtb3N0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGUgdGhhdCBtYXJraW5nIHRoZSBvdXRtb3N0IGJhcnMgaGFzIHRvIGJlIGRvbmVcbiAgICAvLyBiZWZvcmUgYG5vcm1hbGl6ZUJhcnNgIGNoYW5nZXMgYGJhci5iYCBhbmQgYGJhci5zYC5cbiAgICBpZihiYXJub3JtKSBub3JtYWxpemVCYXJzKGdkLCBzYSwgc2lldmUpO1xufVxuXG5cbmZ1bmN0aW9uIHNldE9mZnNldEFuZFdpZHRoKGdkLCBwYSwgc2lldmUpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBiYXJnYXAgPSBmdWxsTGF5b3V0LmJhcmdhcCxcbiAgICAgICAgYmFyZ3JvdXBnYXAgPSBmdWxsTGF5b3V0LmJhcmdyb3VwZ2FwIHx8IDAsXG4gICAgICAgIG1pbkRpZmYgPSBzaWV2ZS5taW5EaWZmLFxuICAgICAgICBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzLFxuICAgICAgICBpLCBjYWxjVHJhY2UsIGNhbGNUcmFjZTAsXG4gICAgICAgIHQ7XG5cbiAgICAvLyBzZXQgYmFyIG9mZnNldHMgYW5kIHdpZHRoc1xuICAgIHZhciBiYXJHcm91cFdpZHRoID0gbWluRGlmZiAqICgxIC0gYmFyZ2FwKSxcbiAgICAgICAgYmFyV2lkdGhQbHVzR2FwID0gYmFyR3JvdXBXaWR0aCxcbiAgICAgICAgYmFyV2lkdGggPSBiYXJXaWR0aFBsdXNHYXAgKiAoMSAtIGJhcmdyb3VwZ2FwKTtcblxuICAgIC8vIGNvbXB1dGVyIGJhciBncm91cCBjZW50ZXIgYW5kIGJhciBvZmZzZXRcbiAgICB2YXIgb2Zmc2V0RnJvbUNlbnRlciA9IC1iYXJXaWR0aCAvIDI7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGNhbGNUcmFjZTAgPSBjYWxjVHJhY2VbMF07XG5cbiAgICAgICAgLy8gc3RvcmUgYmFyIHdpZHRoIGFuZCBvZmZzZXQgZm9yIHRoaXMgdHJhY2VcbiAgICAgICAgdCA9IGNhbGNUcmFjZTAudDtcbiAgICAgICAgdC5iYXJ3aWR0aCA9IGJhcldpZHRoO1xuICAgICAgICB0LnBvZmZzZXQgPSBvZmZzZXRGcm9tQ2VudGVyO1xuICAgICAgICB0LmJhcmdyb3Vwd2lkdGggPSBiYXJHcm91cFdpZHRoO1xuICAgICAgICB0LmJhcmRlbHRhID0gbWluRGlmZjtcbiAgICB9XG5cbiAgICAvLyBzdGFjayBiYXJzIHRoYXQgb25seSBkaWZmZXIgYnkgcm91bmRpbmdcbiAgICBzaWV2ZS5iaW5XaWR0aCA9IGNhbGNUcmFjZXNbMF1bMF0udC5iYXJ3aWR0aCAvIDEwMDtcblxuICAgIC8vIGlmIGRlZmluZWQsIGFwcGx5IHRyYWNlIG9mZnNldCBhbmQgd2lkdGhcbiAgICBhcHBseUF0dHJpYnV0ZXMoc2lldmUpO1xuXG4gICAgLy8gc3RvcmUgdGhlIGJhciBjZW50ZXIgaW4gZWFjaCBjYWxjZGF0YSBpdGVtXG4gICAgc2V0QmFyQ2VudGVyQW5kV2lkdGgoZ2QsIHBhLCBzaWV2ZSk7XG5cbiAgICAvLyB1cGRhdGUgcG9zaXRpb24gYXhlc1xuICAgIHVwZGF0ZVBvc2l0aW9uQXhpcyhnZCwgcGEsIHNpZXZlKTtcbn1cblxuXG5mdW5jdGlvbiBzZXRPZmZzZXRBbmRXaWR0aEluR3JvdXBNb2RlKGdkLCBwYSwgc2lldmUpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0LFxuICAgICAgICBiYXJnYXAgPSBmdWxsTGF5b3V0LmJhcmdhcCxcbiAgICAgICAgYmFyZ3JvdXBnYXAgPSBmdWxsTGF5b3V0LmJhcmdyb3VwZ2FwIHx8IDAsXG4gICAgICAgIHBvc2l0aW9ucyA9IHNpZXZlLnBvc2l0aW9ucyxcbiAgICAgICAgZGlzdGluY3RQb3NpdGlvbnMgPSBzaWV2ZS5kaXN0aW5jdFBvc2l0aW9ucyxcbiAgICAgICAgbWluRGlmZiA9IHNpZXZlLm1pbkRpZmYsXG4gICAgICAgIGNhbGNUcmFjZXMgPSBzaWV2ZS50cmFjZXMsXG4gICAgICAgIGksIGNhbGNUcmFjZSwgY2FsY1RyYWNlMCxcbiAgICAgICAgdDtcblxuICAgIC8vIGlmIHRoZXJlIGFyZW4ndCBhbnkgb3ZlcmxhcHBpbmcgcG9zaXRpb25zLFxuICAgIC8vIGxldCB0aGVtIGhhdmUgZnVsbCB3aWR0aCBldmVuIGlmIG1vZGUgaXMgZ3JvdXBcbiAgICB2YXIgb3ZlcmxhcCA9IChwb3NpdGlvbnMubGVuZ3RoICE9PSBkaXN0aW5jdFBvc2l0aW9ucy5sZW5ndGgpO1xuXG4gICAgdmFyIG5UcmFjZXMgPSBjYWxjVHJhY2VzLmxlbmd0aCxcbiAgICAgICAgYmFyR3JvdXBXaWR0aCA9IG1pbkRpZmYgKiAoMSAtIGJhcmdhcCksXG4gICAgICAgIGJhcldpZHRoUGx1c0dhcCA9IChvdmVybGFwKSA/IGJhckdyb3VwV2lkdGggLyBuVHJhY2VzIDogYmFyR3JvdXBXaWR0aCxcbiAgICAgICAgYmFyV2lkdGggPSBiYXJXaWR0aFBsdXNHYXAgKiAoMSAtIGJhcmdyb3VwZ2FwKTtcblxuICAgIGZvcihpID0gMDsgaSA8IG5UcmFjZXM7IGkrKykge1xuICAgICAgICBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuICAgICAgICBjYWxjVHJhY2UwID0gY2FsY1RyYWNlWzBdO1xuXG4gICAgICAgIC8vIGNvbXB1dGVyIGJhciBncm91cCBjZW50ZXIgYW5kIGJhciBvZmZzZXRcbiAgICAgICAgdmFyIG9mZnNldEZyb21DZW50ZXIgPSAob3ZlcmxhcCkgP1xuICAgICAgICAgICAgICAgICgoMiAqIGkgKyAxIC0gblRyYWNlcykgKiBiYXJXaWR0aFBsdXNHYXAgLSBiYXJXaWR0aCkgLyAyIDpcbiAgICAgICAgICAgICAgICAtYmFyV2lkdGggLyAyO1xuXG4gICAgICAgIC8vIHN0b3JlIGJhciB3aWR0aCBhbmQgb2Zmc2V0IGZvciB0aGlzIHRyYWNlXG4gICAgICAgIHQgPSBjYWxjVHJhY2UwLnQ7XG4gICAgICAgIHQuYmFyd2lkdGggPSBiYXJXaWR0aDtcbiAgICAgICAgdC5wb2Zmc2V0ID0gb2Zmc2V0RnJvbUNlbnRlcjtcbiAgICAgICAgdC5iYXJncm91cHdpZHRoID0gYmFyR3JvdXBXaWR0aDtcbiAgICAgICAgdC5iYXJkZWx0YSA9IG1pbkRpZmY7XG4gICAgfVxuXG4gICAgLy8gc3RhY2sgYmFycyB0aGF0IG9ubHkgZGlmZmVyIGJ5IHJvdW5kaW5nXG4gICAgc2lldmUuYmluV2lkdGggPSBjYWxjVHJhY2VzWzBdWzBdLnQuYmFyd2lkdGggLyAxMDA7XG5cbiAgICAvLyBpZiBkZWZpbmVkLCBhcHBseSB0cmFjZSB3aWR0aFxuICAgIGFwcGx5QXR0cmlidXRlcyhzaWV2ZSk7XG5cbiAgICAvLyBzdG9yZSB0aGUgYmFyIGNlbnRlciBpbiBlYWNoIGNhbGNkYXRhIGl0ZW1cbiAgICBzZXRCYXJDZW50ZXJBbmRXaWR0aChnZCwgcGEsIHNpZXZlKTtcblxuICAgIC8vIHVwZGF0ZSBwb3NpdGlvbiBheGVzXG4gICAgdXBkYXRlUG9zaXRpb25BeGlzKGdkLCBwYSwgc2lldmUsIG92ZXJsYXApO1xufVxuXG5cbmZ1bmN0aW9uIGFwcGx5QXR0cmlidXRlcyhzaWV2ZSkge1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzLFxuICAgICAgICBpLCBjYWxjVHJhY2UsIGNhbGNUcmFjZTAsIGZ1bGxUcmFjZSxcbiAgICAgICAgaixcbiAgICAgICAgdDtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgY2FsY1RyYWNlMCA9IGNhbGNUcmFjZVswXTtcbiAgICAgICAgZnVsbFRyYWNlID0gY2FsY1RyYWNlMC50cmFjZTtcbiAgICAgICAgdCA9IGNhbGNUcmFjZTAudDtcblxuICAgICAgICB2YXIgb2Zmc2V0ID0gZnVsbFRyYWNlLl9vZmZzZXQgfHwgZnVsbFRyYWNlLm9mZnNldCxcbiAgICAgICAgICAgIGluaXRpYWxQb2Zmc2V0ID0gdC5wb2Zmc2V0LFxuICAgICAgICAgICAgbmV3UG9mZnNldDtcblxuICAgICAgICBpZihpc0FycmF5T3JUeXBlZEFycmF5KG9mZnNldCkpIHtcbiAgICAgICAgICAgIC8vIGlmIG9mZnNldCBpcyBhbiBhcnJheSwgdGhlbiBjbG9uZSBpdCBpbnRvIHQucG9mZnNldC5cbiAgICAgICAgICAgIG5ld1BvZmZzZXQgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChvZmZzZXQsIDAsIGNhbGNUcmFjZS5sZW5ndGgpO1xuXG4gICAgICAgICAgICAvLyBndWFyZCBhZ2FpbnN0IG5vbi1udW1lcmljIGl0ZW1zXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBuZXdQb2Zmc2V0Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhuZXdQb2Zmc2V0W2pdKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdQb2Zmc2V0W2pdID0gaW5pdGlhbFBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheSBpcyB0b28gc2hvcnQsXG4gICAgICAgICAgICAvLyB0aGVuIGV4dGVuZCBpdCB3aXRoIHRoZSBpbml0aWFsIHZhbHVlIG9mIHQucG9mZnNldFxuICAgICAgICAgICAgZm9yKGogPSBuZXdQb2Zmc2V0Lmxlbmd0aDsgaiA8IGNhbGNUcmFjZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIG5ld1BvZmZzZXQucHVzaChpbml0aWFsUG9mZnNldCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHQucG9mZnNldCA9IG5ld1BvZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihvZmZzZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdC5wb2Zmc2V0ID0gb2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHdpZHRoID0gZnVsbFRyYWNlLl93aWR0aCB8fCBmdWxsVHJhY2Uud2lkdGg7XG4gICAgICAgIHZhciBpbml0aWFsQmFyd2lkdGggPSB0LmJhcndpZHRoO1xuXG4gICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkod2lkdGgpKSB7XG4gICAgICAgICAgICAvLyBpZiB3aWR0aCBpcyBhbiBhcnJheSwgdGhlbiBjbG9uZSBpdCBpbnRvIHQuYmFyd2lkdGguXG4gICAgICAgICAgICB2YXIgbmV3QmFyd2lkdGggPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh3aWR0aCwgMCwgY2FsY1RyYWNlLmxlbmd0aCk7XG5cbiAgICAgICAgICAgIC8vIGd1YXJkIGFnYWluc3Qgbm9uLW51bWVyaWMgaXRlbXNcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5ld0JhcndpZHRoLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhuZXdCYXJ3aWR0aFtqXSkpIG5ld0JhcndpZHRoW2pdID0gaW5pdGlhbEJhcndpZHRoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheSBpcyB0b28gc2hvcnQsXG4gICAgICAgICAgICAvLyB0aGVuIGV4dGVuZCBpdCB3aXRoIHRoZSBpbml0aWFsIHZhbHVlIG9mIHQuYmFyd2lkdGhcbiAgICAgICAgICAgIGZvcihqID0gbmV3QmFyd2lkdGgubGVuZ3RoOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbmV3QmFyd2lkdGgucHVzaChpbml0aWFsQmFyd2lkdGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0LmJhcndpZHRoID0gbmV3QmFyd2lkdGg7XG5cbiAgICAgICAgICAgIC8vIGlmIHVzZXIgZGlkbid0IHNldCBvZmZzZXQsXG4gICAgICAgICAgICAvLyB0aGVuIGNvcnJlY3QgdC5wb2Zmc2V0IHRvIGVuc3VyZSBiYXJzIHJlbWFpbiBjZW50ZXJlZFxuICAgICAgICAgICAgaWYob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBuZXdQb2Zmc2V0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BvZmZzZXQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxQb2Zmc2V0ICsgKGluaXRpYWxCYXJ3aWR0aCAtIG5ld0JhcndpZHRoW2pdKSAvIDJcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdC5wb2Zmc2V0ID0gbmV3UG9mZnNldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHdpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHQuYmFyd2lkdGggPSB3aWR0aDtcblxuICAgICAgICAgICAgLy8gaWYgdXNlciBkaWRuJ3Qgc2V0IG9mZnNldCxcbiAgICAgICAgICAgIC8vIHRoZW4gY29ycmVjdCB0LnBvZmZzZXQgdG8gZW5zdXJlIGJhcnMgcmVtYWluIGNlbnRlcmVkXG4gICAgICAgICAgICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHQucG9mZnNldCA9IGluaXRpYWxQb2Zmc2V0ICsgKGluaXRpYWxCYXJ3aWR0aCAtIHdpZHRoKSAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblxuZnVuY3Rpb24gc2V0QmFyQ2VudGVyQW5kV2lkdGgoZ2QsIHBhLCBzaWV2ZSkge1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzLFxuICAgICAgICBwTGV0dGVyID0gZ2V0QXhpc0xldHRlcihwYSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXSxcbiAgICAgICAgICAgIHQgPSBjYWxjVHJhY2VbMF0udCxcbiAgICAgICAgICAgIHBvZmZzZXQgPSB0LnBvZmZzZXQsXG4gICAgICAgICAgICBwb2Zmc2V0SXNBcnJheSA9IEFycmF5LmlzQXJyYXkocG9mZnNldCksXG4gICAgICAgICAgICBiYXJ3aWR0aCA9IHQuYmFyd2lkdGgsXG4gICAgICAgICAgICBiYXJ3aWR0aElzQXJyYXkgPSBBcnJheS5pc0FycmF5KGJhcndpZHRoKTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2FsY0JhciA9IGNhbGNUcmFjZVtqXTtcblxuICAgICAgICAgICAgLy8gc3RvcmUgdGhlIGFjdHVhbCBiYXIgd2lkdGggYW5kIHBvc2l0aW9uLCBmb3IgdXNlIGJ5IGhvdmVyXG4gICAgICAgICAgICB2YXIgd2lkdGggPSBjYWxjQmFyLncgPSAoYmFyd2lkdGhJc0FycmF5KSA/IGJhcndpZHRoW2pdIDogYmFyd2lkdGg7XG4gICAgICAgICAgICBjYWxjQmFyW3BMZXR0ZXJdID0gY2FsY0Jhci5wICtcbiAgICAgICAgICAgICAgICAoKHBvZmZzZXRJc0FycmF5KSA/IHBvZmZzZXRbal0gOiBwb2Zmc2V0KSArXG4gICAgICAgICAgICAgICAgd2lkdGggLyAyO1xuXG5cbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG5mdW5jdGlvbiB1cGRhdGVQb3NpdGlvbkF4aXMoZ2QsIHBhLCBzaWV2ZSwgYWxsb3dNaW5EdGljaykge1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzLFxuICAgICAgICBkaXN0aW5jdFBvc2l0aW9ucyA9IHNpZXZlLmRpc3RpbmN0UG9zaXRpb25zLFxuICAgICAgICBkaXN0aW5jdFBvc2l0aW9uczAgPSBkaXN0aW5jdFBvc2l0aW9uc1swXSxcbiAgICAgICAgbWluRGlmZiA9IHNpZXZlLm1pbkRpZmYsXG4gICAgICAgIHZwYWQgPSBtaW5EaWZmIC8gMjtcblxuICAgIEF4ZXMubWluRHRpY2socGEsIG1pbkRpZmYsIGRpc3RpbmN0UG9zaXRpb25zMCwgYWxsb3dNaW5EdGljayk7XG5cbiAgICAvLyBJZiB0aGUgdXNlciBzZXQgdGhlIGJhciB3aWR0aCBvciB0aGUgb2Zmc2V0LFxuICAgIC8vIHRoZW4gYmFycyBjYW4gYmUgc2hpZnRlZCBhd2F5IGZyb20gdGhlaXIgcG9zaXRpb25zXG4gICAgLy8gYW5kIHdpZHRocyBjYW4gYmUgbGFyZ2VyIHRoYW4gbWluRGlmZi5cbiAgICAvL1xuICAgIC8vIEhlcmUsIHdlIGNvbXB1dGUgcE1pbiBhbmQgcE1heCB0byBleHBhbmQgdGhlIHBvc2l0aW9uIGF4aXMsXG4gICAgLy8gc28gdGhhdCBhbGwgYmFycyBhcmUgZnVsbHkgd2l0aGluIHRoZSBheGlzIHJhbmdlLlxuICAgIHZhciBwTWluID0gTWF0aC5taW4uYXBwbHkoTWF0aCwgZGlzdGluY3RQb3NpdGlvbnMpIC0gdnBhZCxcbiAgICAgICAgcE1heCA9IE1hdGgubWF4LmFwcGx5KE1hdGgsIGRpc3RpbmN0UG9zaXRpb25zKSArIHZwYWQ7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXSxcbiAgICAgICAgICAgIGNhbGNUcmFjZTAgPSBjYWxjVHJhY2VbMF0sXG4gICAgICAgICAgICBmdWxsVHJhY2UgPSBjYWxjVHJhY2UwLnRyYWNlO1xuXG4gICAgICAgIGlmKGZ1bGxUcmFjZS53aWR0aCA9PT0gdW5kZWZpbmVkICYmIGZ1bGxUcmFjZS5vZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdCA9IGNhbGNUcmFjZTAudCxcbiAgICAgICAgICAgIHBvZmZzZXQgPSB0LnBvZmZzZXQsXG4gICAgICAgICAgICBiYXJ3aWR0aCA9IHQuYmFyd2lkdGgsXG4gICAgICAgICAgICBwb2Zmc2V0SXNBcnJheSA9IEFycmF5LmlzQXJyYXkocG9mZnNldCksXG4gICAgICAgICAgICBiYXJ3aWR0aElzQXJyYXkgPSBBcnJheS5pc0FycmF5KGJhcndpZHRoKTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2FsY0JhciA9IGNhbGNUcmFjZVtqXSxcbiAgICAgICAgICAgICAgICBjYWxjQmFyT2Zmc2V0ID0gKHBvZmZzZXRJc0FycmF5KSA/IHBvZmZzZXRbal0gOiBwb2Zmc2V0LFxuICAgICAgICAgICAgICAgIGNhbGNCYXJXaWR0aCA9IChiYXJ3aWR0aElzQXJyYXkpID8gYmFyd2lkdGhbal0gOiBiYXJ3aWR0aCxcbiAgICAgICAgICAgICAgICBwID0gY2FsY0Jhci5wLFxuICAgICAgICAgICAgICAgIGwgPSBwICsgY2FsY0Jhck9mZnNldCxcbiAgICAgICAgICAgICAgICByID0gbCArIGNhbGNCYXJXaWR0aDtcblxuICAgICAgICAgICAgcE1pbiA9IE1hdGgubWluKHBNaW4sIGwpO1xuICAgICAgICAgICAgcE1heCA9IE1hdGgubWF4KHBNYXgsIHIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGV4dHJlbWVzID0gQXhlcy5maW5kRXh0cmVtZXMocGEsIFtwTWluLCBwTWF4XSwge3BhZGRlZDogZmFsc2V9KTtcbiAgICBwdXRFeHRyZW1lcyhjYWxjVHJhY2VzLCBwYSwgZXh0cmVtZXMpO1xufVxuXG5mdW5jdGlvbiBleHBhbmRSYW5nZShyYW5nZSwgbmV3VmFsdWUpIHtcbiAgICBpZihpc051bWVyaWMocmFuZ2VbMF0pKSByYW5nZVswXSA9IE1hdGgubWluKHJhbmdlWzBdLCBuZXdWYWx1ZSk7XG4gICAgZWxzZSByYW5nZVswXSA9IG5ld1ZhbHVlO1xuXG4gICAgaWYoaXNOdW1lcmljKHJhbmdlWzFdKSkgcmFuZ2VbMV0gPSBNYXRoLm1heChyYW5nZVsxXSwgbmV3VmFsdWUpO1xuICAgIGVsc2UgcmFuZ2VbMV0gPSBuZXdWYWx1ZTtcbn1cblxuZnVuY3Rpb24gc2V0QmFzZUFuZFRvcChnZCwgc2EsIHNpZXZlKSB7XG4gICAgLy8gc3RvcmUgdGhlc2UgYmFyIGJhc2VzIGFuZCB0b3BzIGluIGNhbGNkYXRhXG4gICAgLy8gYW5kIG1ha2Ugc3VyZSB0aGUgc2l6ZSBheGlzIGluY2x1ZGVzIHplcm8sXG4gICAgLy8gYWxvbmcgd2l0aCB0aGUgYmFzZXMgYW5kIHRvcHMgb2YgZWFjaCBiYXIuXG4gICAgdmFyIHRyYWNlcyA9IHNpZXZlLnRyYWNlcyxcbiAgICAgICAgc0xldHRlciA9IGdldEF4aXNMZXR0ZXIoc2EpLFxuICAgICAgICBzUmFuZ2UgPSBbbnVsbCwgbnVsbF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IHRyYWNlc1tpXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSB0cmFjZVtqXSxcbiAgICAgICAgICAgICAgICBiYXJCYXNlID0gYmFyLmIsXG4gICAgICAgICAgICAgICAgYmFyVG9wID0gYmFyQmFzZSArIGJhci5zO1xuXG4gICAgICAgICAgICBiYXJbc0xldHRlcl0gPSBiYXJUb3A7XG5cbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhzYS5jMmwoYmFyVG9wKSkpIGV4cGFuZFJhbmdlKHNSYW5nZSwgYmFyVG9wKTtcbiAgICAgICAgICAgIGlmKGJhci5oYXNCICYmIGlzTnVtZXJpYyhzYS5jMmwoYmFyQmFzZSkpKSBleHBhbmRSYW5nZShzUmFuZ2UsIGJhckJhc2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGV4dHJlbWVzID0gQXhlcy5maW5kRXh0cmVtZXMoc2EsIHNSYW5nZSwge3RvemVybzogdHJ1ZSwgcGFkZGVkOiB0cnVlfSk7XG4gICAgcHV0RXh0cmVtZXModHJhY2VzLCBzYSwgZXh0cmVtZXMpO1xufVxuXG5cbmZ1bmN0aW9uIHN0YWNrQmFycyhnZCwgc2EsIHNpZXZlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCxcbiAgICAgICAgYmFybm9ybSA9IGZ1bGxMYXlvdXQuYmFybm9ybSxcbiAgICAgICAgc0xldHRlciA9IGdldEF4aXNMZXR0ZXIoc2EpLFxuICAgICAgICB0cmFjZXMgPSBzaWV2ZS50cmFjZXMsXG4gICAgICAgIGksIHRyYWNlLFxuICAgICAgICBqLCBiYXI7XG5cbiAgICB2YXIgc1JhbmdlID0gW251bGwsIG51bGxdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gdHJhY2VzW2ldO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IHRyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBiYXIgPSB0cmFjZVtqXTtcblxuICAgICAgICAgICAgaWYoYmFyLnMgPT09IEJBRE5VTSkgY29udGludWU7XG5cbiAgICAgICAgICAgIC8vIHN0YWNrIGN1cnJlbnQgYmFyIGFuZCBnZXQgcHJldmlvdXMgc3VtXG4gICAgICAgICAgICB2YXIgYmFyQmFzZSA9IHNpZXZlLnB1dChiYXIucCwgYmFyLmIgKyBiYXIucyksXG4gICAgICAgICAgICAgICAgYmFyVG9wID0gYmFyQmFzZSArIGJhci5iICsgYmFyLnM7XG5cbiAgICAgICAgICAgIC8vIHN0b3JlIHRoZSBiYXIgYmFzZSBhbmQgdG9wIGluIGVhY2ggY2FsY2RhdGEgaXRlbVxuICAgICAgICAgICAgYmFyLmIgPSBiYXJCYXNlO1xuICAgICAgICAgICAgYmFyW3NMZXR0ZXJdID0gYmFyVG9wO1xuXG4gICAgICAgICAgICBpZighYmFybm9ybSkge1xuICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhzYS5jMmwoYmFyVG9wKSkpIGV4cGFuZFJhbmdlKHNSYW5nZSwgYmFyVG9wKTtcbiAgICAgICAgICAgICAgICBpZihiYXIuaGFzQiAmJiBpc051bWVyaWMoc2EuYzJsKGJhckJhc2UpKSkgZXhwYW5kUmFuZ2Uoc1JhbmdlLCBiYXJCYXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIGJhcm5vcm0gaXMgc2V0LCBsZXQgbm9ybWFsaXplQmFycyB1cGRhdGUgdGhlIGF4aXMgcmFuZ2VcbiAgICBpZighYmFybm9ybSkge1xuICAgICAgICB2YXIgZXh0cmVtZXMgPSBBeGVzLmZpbmRFeHRyZW1lcyhzYSwgc1JhbmdlLCB7dG96ZXJvOiB0cnVlLCBwYWRkZWQ6IHRydWV9KTtcbiAgICAgICAgcHV0RXh0cmVtZXModHJhY2VzLCBzYSwgZXh0cmVtZXMpO1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBzaWV2ZUJhcnMoZ2QsIHNhLCBzaWV2ZSkge1xuICAgIHZhciB0cmFjZXMgPSBzaWV2ZS50cmFjZXM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IHRyYWNlc1tpXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSB0cmFjZVtqXTtcblxuICAgICAgICAgICAgaWYoYmFyLnMgIT09IEJBRE5VTSkgc2lldmUucHV0KGJhci5wLCBiYXIuYiArIGJhci5zKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBub3JtYWxpemVCYXJzKGdkLCBzYSwgc2lldmUpIHtcbiAgICAvLyBOb3RlOlxuICAgIC8vXG4gICAgLy8gbm9ybWFsaXplQmFycyByZXF1aXJlcyB0aGF0IGVpdGhlciBzaWV2ZUJhcnMgb3Igc3RhY2tCYXJzIGhhcyBiZWVuXG4gICAgLy8gcHJldmlvdXNseSBpbnZva2VkLlxuXG4gICAgdmFyIHRyYWNlcyA9IHNpZXZlLnRyYWNlcyxcbiAgICAgICAgc0xldHRlciA9IGdldEF4aXNMZXR0ZXIoc2EpLFxuICAgICAgICBzVG9wID0gKGdkLl9mdWxsTGF5b3V0LmJhcm5vcm0gPT09ICdmcmFjdGlvbicpID8gMSA6IDEwMCxcbiAgICAgICAgc1RpbnkgPSBzVG9wIC8gMWU5LCAvLyBpbiBjYXNlIG9mIHJvdW5kaW5nIGVycm9yIGluIHN1bVxuICAgICAgICBzTWluID0gc2EubDJjKHNhLmMybCgwKSksXG4gICAgICAgIHNNYXggPSAoZ2QuX2Z1bGxMYXlvdXQuYmFybW9kZSA9PT0gJ3N0YWNrJykgPyBzVG9wIDogc01pbixcbiAgICAgICAgc1JhbmdlID0gW3NNaW4sIHNNYXhdLFxuICAgICAgICBwYWRkZWQgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIG1heWJlRXhwYW5kKG5ld1ZhbHVlKSB7XG4gICAgICAgIGlmKGlzTnVtZXJpYyhzYS5jMmwobmV3VmFsdWUpKSAmJlxuICAgICAgICAgICAgKChuZXdWYWx1ZSA8IHNNaW4gLSBzVGlueSkgfHwgKG5ld1ZhbHVlID4gc01heCArIHNUaW55KSB8fCAhaXNOdW1lcmljKHNNaW4pKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHBhZGRlZCA9IHRydWU7XG4gICAgICAgICAgICBleHBhbmRSYW5nZShzUmFuZ2UsIG5ld1ZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gdHJhY2VzW2ldO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0cmFjZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGJhciA9IHRyYWNlW2pdO1xuXG4gICAgICAgICAgICBpZihiYXIucyA9PT0gQkFETlVNKSBjb250aW51ZTtcblxuICAgICAgICAgICAgdmFyIHNjYWxlID0gTWF0aC5hYnMoc1RvcCAvIHNpZXZlLmdldChiYXIucCwgYmFyLnMpKTtcbiAgICAgICAgICAgIGJhci5iICo9IHNjYWxlO1xuICAgICAgICAgICAgYmFyLnMgKj0gc2NhbGU7XG5cbiAgICAgICAgICAgIHZhciBiYXJCYXNlID0gYmFyLmIsXG4gICAgICAgICAgICAgICAgYmFyVG9wID0gYmFyQmFzZSArIGJhci5zO1xuICAgICAgICAgICAgYmFyW3NMZXR0ZXJdID0gYmFyVG9wO1xuXG4gICAgICAgICAgICBtYXliZUV4cGFuZChiYXJUb3ApO1xuICAgICAgICAgICAgaWYoYmFyLmhhc0IpIG1heWJlRXhwYW5kKGJhckJhc2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIHJhbmdlIG9mIHNpemUgYXhpc1xuICAgIHZhciBleHRyZW1lcyA9IEF4ZXMuZmluZEV4dHJlbWVzKHNhLCBzUmFuZ2UsIHt0b3plcm86IHRydWUsIHBhZGRlZDogcGFkZGVkfSk7XG4gICAgcHV0RXh0cmVtZXModHJhY2VzLCBzYSwgZXh0cmVtZXMpO1xufVxuXG5cbmZ1bmN0aW9uIGdldEF4aXNMZXR0ZXIoYXgpIHtcbiAgICByZXR1cm4gYXguX2lkLmNoYXJBdCgwKTtcbn1cblxuZnVuY3Rpb24gcHV0RXh0cmVtZXMoY2QsIGF4LCBleHRyZW1lcykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZFtpXVswXS50cmFjZS5fZXh0cmVtZXNbYXguX2lkXSA9IGV4dHJlbWVzO1xuICAgIH1cbn1cblxuLy8gZmluZCB0aGUgZnVsbCBwb3NpdGlvbiBzcGFuIG9mIGJhcnMgYXQgZWFjaCBwb3NpdGlvblxuLy8gZm9yIHVzZSBieSBob3ZlciwgdG8gZW5zdXJlIGxhYmVscyBtb3ZlIGluIGlmIGJhcnMgYXJlXG4vLyBuYXJyb3dlciB0aGFuIHRoZSBzcGFjZSB0aGV5J3JlIGluLlxuLy8gcnVuIG9uY2UgcGVyIHRyYWNlIGdyb3VwIChzdWJwbG90ICYgZGlyZWN0aW9uKSBhbmRcbi8vIHRoZSBzYW1lIG1hcHBpbmcgaXMgYXR0YWNoZWQgdG8gYWxsIGNhbGNkYXRhIHRyYWNlc1xuZnVuY3Rpb24gY29sbGVjdEV4dGVudHMoY2FsY1RyYWNlcywgcGEpIHtcbiAgICB2YXIgcG9zTGV0dGVyID0gcGEuX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgZXh0ZW50cyA9IHt9O1xuICAgIHZhciBwTWluID0gSW5maW5pdHk7XG4gICAgdmFyIHBNYXggPSAtSW5maW5pdHk7XG5cbiAgICB2YXIgaSwgaiwgY2Q7XG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGZvcihqID0gMDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGNkW2pdLnA7XG4gICAgICAgICAgICBpZihpc051bWVyaWMocCkpIHtcbiAgICAgICAgICAgICAgICBwTWluID0gTWF0aC5taW4ocE1pbiwgcCk7XG4gICAgICAgICAgICAgICAgcE1heCA9IE1hdGgubWF4KHBNYXgsIHApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBpcyBqdXN0IGZvciBwb3NpdGlvbmluZyBvZiBob3ZlciBsYWJlbHMsIGFuZCBub2JvZHkgd2lsbCBjYXJlIGlmXG4gICAgLy8gdGhlIGxhYmVsIGlzIDFweCB0b28gZmFyIG91dDsgc28gcm91bmQgcG9zaXRpb25zIHRvIDEvMTBLIGluIGNhc2VcbiAgICAvLyBwb3NpdGlvbiB2YWx1ZXMgZG9uJ3QgZXhhY3RseSBtYXRjaCBmcm9tIHRyYWNlIHRvIHRyYWNlXG4gICAgdmFyIHJvdW5kRmFjdG9yID0gMTAwMDAgLyAocE1heCAtIHBNaW4pO1xuICAgIHZhciByb3VuZCA9IGV4dGVudHMucm91bmQgPSBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoTWF0aC5yb3VuZChyb3VuZEZhY3RvciAqIChwIC0gcE1pbikpKTtcbiAgICB9O1xuXG4gICAgdmFyIHBvZmZzZXQsIHBvZmZzZXRJc0FycmF5O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGNkWzBdLnQuZXh0ZW50cyA9IGV4dGVudHM7XG4gICAgICAgIHBvZmZzZXQgPSBjZFswXS50LnBvZmZzZXQ7XG4gICAgICAgIHBvZmZzZXRJc0FycmF5ID0gQXJyYXkuaXNBcnJheShwb2Zmc2V0KTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBjZC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGRpID0gY2Rbal07XG4gICAgICAgICAgICB2YXIgcDAgPSBkaVtwb3NMZXR0ZXJdIC0gZGkudyAvIDI7XG5cbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhwMCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcDEgPSBkaVtwb3NMZXR0ZXJdICsgZGkudyAvIDI7XG4gICAgICAgICAgICAgICAgdmFyIHBWYWwgPSByb3VuZChkaS5wKTtcbiAgICAgICAgICAgICAgICBpZihleHRlbnRzW3BWYWxdKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4dGVudHNbcFZhbF0gPSBbTWF0aC5taW4ocDAsIGV4dGVudHNbcFZhbF1bMF0pLCBNYXRoLm1heChwMSwgZXh0ZW50c1twVmFsXVsxXSldO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV4dGVudHNbcFZhbF0gPSBbcDAsIHAxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRpLnAwID0gZGkucCArICgocG9mZnNldElzQXJyYXkpID8gcG9mZnNldFtqXSA6IHBvZmZzZXQpO1xuICAgICAgICAgICAgZGkucDEgPSBkaS5wMCArIGRpLnc7XG4gICAgICAgICAgICBkaS5zMCA9IGRpLmI7XG4gICAgICAgICAgICBkaS5zMSA9IGRpLnMwICsgZGkucztcbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY3Jvc3NUcmFjZUNhbGM6IGNyb3NzVHJhY2VDYWxjLFxuICAgIHNldEdyb3VwUG9zaXRpb25zOiBzZXRHcm91cFBvc2l0aW9uc1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgaGFuZGxlWFlEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIveHlfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVTdHlsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vYmFyL3N0eWxlX2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgY29lcmNlRm9udCA9IExpYi5jb2VyY2VGb250O1xuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnb3JpZW50YXRpb24nLCAodHJhY2VPdXQueCAmJiAhdHJhY2VPdXQueSkgPyAnaCcgOiAndicpO1xuICAgIGNvZXJjZSgnYmFzZScpO1xuICAgIGNvZXJjZSgnb2Zmc2V0Jyk7XG4gICAgY29lcmNlKCd3aWR0aCcpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcblxuICAgIHZhciB0ZXh0UG9zaXRpb24gPSBjb2VyY2UoJ3RleHRwb3NpdGlvbicpO1xuXG4gICAgdmFyIGhhc0JvdGggPSBBcnJheS5pc0FycmF5KHRleHRQb3NpdGlvbikgfHwgdGV4dFBvc2l0aW9uID09PSAnYXV0bycsXG4gICAgICAgIGhhc0luc2lkZSA9IGhhc0JvdGggfHwgdGV4dFBvc2l0aW9uID09PSAnaW5zaWRlJyxcbiAgICAgICAgaGFzT3V0c2lkZSA9IGhhc0JvdGggfHwgdGV4dFBvc2l0aW9uID09PSAnb3V0c2lkZSc7XG5cbiAgICBpZihoYXNJbnNpZGUgfHwgaGFzT3V0c2lkZSkge1xuICAgICAgICB2YXIgdGV4dEZvbnQgPSBjb2VyY2VGb250KGNvZXJjZSwgJ3RleHRmb250JywgbGF5b3V0LmZvbnQpO1xuXG4gICAgICAgIC8vIE5vdGUgdGhhdCBjb2VyY2luZyBgaW5zaWRldGV4dGZvbnRgIGlzIGFsd2F5cyBuZWVkZWQg4oCTXG4gICAgICAgIC8vIGV2ZW4gaWYgYHRleHRwb3NpdGlvbmAgaXMgYG91dHNpZGVgIGZvciBlYWNoIHRyYWNlIOKAkyBzaW5jZVxuICAgICAgICAvLyBhbiBvdXRzaWRlIGxhYmVsIGNhbiBiZWNvbWUgYW4gaW5zaWRlIG9uZSwgZm9yIGV4YW1wbGUgYmVjYXVzZVxuICAgICAgICAvLyBvZiBhIGJhciBiZWluZyBzdGFja2VkIG9uIHRvcCBvZiBpdC5cbiAgICAgICAgdmFyIGluc2lkZVRleHRGb250RGVmYXVsdCA9IExpYi5leHRlbmRGbGF0KHt9LCB0ZXh0Rm9udCk7XG4gICAgICAgIHZhciBpc1RyYWNlVGV4dGZvbnRDb2xvclNldCA9IHRyYWNlSW4udGV4dGZvbnQgJiYgdHJhY2VJbi50ZXh0Zm9udC5jb2xvcjtcbiAgICAgICAgdmFyIGlzQ29sb3JJbmhlcml0ZWRGcm9tTGF5b3V0Rm9udCA9ICFpc1RyYWNlVGV4dGZvbnRDb2xvclNldDtcbiAgICAgICAgaWYoaXNDb2xvckluaGVyaXRlZEZyb21MYXlvdXRGb250KSB7XG4gICAgICAgICAgICBkZWxldGUgaW5zaWRlVGV4dEZvbnREZWZhdWx0LmNvbG9yO1xuICAgICAgICB9XG4gICAgICAgIGNvZXJjZUZvbnQoY29lcmNlLCAnaW5zaWRldGV4dGZvbnQnLCBpbnNpZGVUZXh0Rm9udERlZmF1bHQpO1xuXG4gICAgICAgIGlmKGhhc091dHNpZGUpIGNvZXJjZUZvbnQoY29lcmNlLCAnb3V0c2lkZXRleHRmb250JywgdGV4dEZvbnQpO1xuXG4gICAgICAgIGNvZXJjZSgnY29uc3RyYWludGV4dCcpO1xuICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkLnRleHRmb250LmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgndW5zZWxlY3RlZC50ZXh0Zm9udC5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ2NsaXBvbmF4aXMnKTtcbiAgICB9XG5cbiAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KTtcblxuICAgIC8vIG92ZXJyaWRlIGRlZmF1bHRDb2xvciBmb3IgZXJyb3IgYmFycyB3aXRoIGRlZmF1bHRMaW5lXG4gICAgdmFyIGVycm9yQmFyc1N1cHBseURlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3VwcGx5RGVmYXVsdHMnKTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneSd9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneCcsIGluaGVyaXQ6ICd5J30pO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG5cbmV4cG9ydHMuY29lcmNlU3RyaW5nID0gZnVuY3Rpb24oYXR0cmlidXRlRGVmaW5pdGlvbiwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYodmFsdWUgfHwgIWF0dHJpYnV0ZURlZmluaXRpb24ubm9CbGFuaykgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBlbHNlIGlmKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgaWYoIWF0dHJpYnV0ZURlZmluaXRpb24uc3RyaWN0KSByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSA/XG4gICAgICBkZWZhdWx0VmFsdWUgOlxuICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5kZmx0O1xufTtcblxuZXhwb3J0cy5jb2VyY2VOdW1iZXIgPSBmdW5jdGlvbihhdHRyaWJ1dGVEZWZpbml0aW9uLCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgaWYoaXNOdW1lcmljKHZhbHVlKSkge1xuICAgICAgICB2YWx1ZSA9ICt2YWx1ZTtcblxuICAgICAgICB2YXIgbWluID0gYXR0cmlidXRlRGVmaW5pdGlvbi5taW4sXG4gICAgICAgICAgICBtYXggPSBhdHRyaWJ1dGVEZWZpbml0aW9uLm1heCxcbiAgICAgICAgICAgIGlzT3V0T2ZCb3VuZHMgPSAobWluICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgPCBtaW4pIHx8XG4gICAgICAgICAgICAgIChtYXggIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSA+IG1heCk7XG5cbiAgICAgICAgaWYoIWlzT3V0T2ZCb3VuZHMpIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSA/XG4gICAgICBkZWZhdWx0VmFsdWUgOlxuICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5kZmx0O1xufTtcblxuZXhwb3J0cy5jb2VyY2VDb2xvciA9IGZ1bmN0aW9uKGF0dHJpYnV0ZURlZmluaXRpb24sIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgICBpZih0aW55Y29sb3IodmFsdWUpLmlzVmFsaWQoKSkgcmV0dXJuIHZhbHVlO1xuXG4gICAgcmV0dXJuIChkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkgP1xuICAgICAgZGVmYXVsdFZhbHVlIDpcbiAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uZGZsdDtcbn07XG5cbmV4cG9ydHMuY29lcmNlRW51bWVyYXRlZCA9IGZ1bmN0aW9uKGF0dHJpYnV0ZURlZmluaXRpb24sIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgICBpZihhdHRyaWJ1dGVEZWZpbml0aW9uLmNvZXJjZU51bWJlcikgdmFsdWUgPSArdmFsdWU7XG5cbiAgICBpZihhdHRyaWJ1dGVEZWZpbml0aW9uLnZhbHVlcy5pbmRleE9mKHZhbHVlKSAhPT0gLTEpIHJldHVybiB2YWx1ZTtcblxuICAgIHJldHVybiAoZGVmYXVsdFZhbHVlICE9PSB1bmRlZmluZWQpID9cbiAgICAgIGRlZmF1bHRWYWx1ZSA6XG4gICAgICBhdHRyaWJ1dGVEZWZpbml0aW9uLmRmbHQ7XG59O1xuXG5leHBvcnRzLmdldFZhbHVlID0gZnVuY3Rpb24oYXJyYXlPclNjYWxhciwgaW5kZXgpIHtcbiAgICB2YXIgdmFsdWU7XG4gICAgaWYoIUFycmF5LmlzQXJyYXkoYXJyYXlPclNjYWxhcikpIHZhbHVlID0gYXJyYXlPclNjYWxhcjtcbiAgICBlbHNlIGlmKGluZGV4IDwgYXJyYXlPclNjYWxhci5sZW5ndGgpIHZhbHVlID0gYXJyYXlPclNjYWxhcltpbmRleF07XG4gICAgcmV0dXJuIHZhbHVlO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRnggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGZpbGxIb3ZlclRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dCcpO1xuXG5mdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgdCA9IGNkWzBdLnQ7XG4gICAgdmFyIGlzQ2xvc2VzdCA9IChob3Zlcm1vZGUgPT09ICdjbG9zZXN0Jyk7XG4gICAgdmFyIG1heEhvdmVyRGlzdGFuY2UgPSBwb2ludERhdGEubWF4SG92ZXJEaXN0YW5jZTtcbiAgICB2YXIgbWF4U3Bpa2VEaXN0YW5jZSA9IHBvaW50RGF0YS5tYXhTcGlrZURpc3RhbmNlO1xuXG4gICAgdmFyIHBvc1ZhbCwgc2l6ZVZhbCwgcG9zTGV0dGVyLCBzaXplTGV0dGVyLCBkeCwgZHksIHBSYW5nZUNhbGM7XG5cbiAgICBmdW5jdGlvbiB0aGlzQmFyTWluUG9zKGRpKSB7IHJldHVybiBkaVtwb3NMZXR0ZXJdIC0gZGkudyAvIDI7IH1cbiAgICBmdW5jdGlvbiB0aGlzQmFyTWF4UG9zKGRpKSB7IHJldHVybiBkaVtwb3NMZXR0ZXJdICsgZGkudyAvIDI7IH1cblxuICAgIHZhciBtaW5Qb3MgPSBpc0Nsb3Nlc3QgP1xuICAgICAgICB0aGlzQmFyTWluUG9zIDpcbiAgICAgICAgZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBJbiBjb21wYXJlIG1vZGUsIGFjY2VwdCBhIGJhciBpZiB5b3UncmUgb24gaXQgKm9yKiBpdHMgZ3JvdXAuXG4gICAgICAgICAgICAgKiBOZWFybHkgYWx3YXlzIGl0J3MgdGhlIGdyb3VwIHRoYXQgbWF0dGVycywgYnV0IGluIGNhc2UgdGhlIGJhclxuICAgICAgICAgICAgICogd2FzIGV4cGxpY2l0bHkgc2V0IHdpZGVyIHRoYW4gaXRzIGdyb3VwIHdlJ2QgYmV0dGVyIGFjY2VwdCB0aGVcbiAgICAgICAgICAgICAqIHdob2xlIGJhci5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiB1c2UgYGJhcmRlbHRhYCBpbnN0ZWFkIG9mIGBiYXJncm91cHdpZHRoYCBzbyB3ZSBhY2NlcHQgaG92ZXJcbiAgICAgICAgICAgICAqIGluIHRoZSBnYXAuIFRoYXQgd2F5IGhvdmVyIGRvZXNuJ3QgZmxhc2ggb24gYW5kIG9mZiBhcyB5b3VcbiAgICAgICAgICAgICAqIG1vdXNlIG92ZXIgdGhlIHBsb3QgaW4gY29tcGFyZSBtb2Rlcy5cbiAgICAgICAgICAgICAqIEluICdjbG9zZXN0JyBtb2RlIHRob3VnaCB0aGUgZmxhc2hpbmcgc2VlbXMgaW5ldml0YWJsZSxcbiAgICAgICAgICAgICAqIHdpdGhvdXQgZmFyIG1vcmUgY29tcGxleCBsb2dpY1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5taW4odGhpc0Jhck1pblBvcyhkaSksIGRpLnAgLSB0LmJhcmRlbHRhIC8gMik7XG4gICAgICAgIH07XG5cbiAgICB2YXIgbWF4UG9zID0gaXNDbG9zZXN0ID9cbiAgICAgICAgdGhpc0Jhck1heFBvcyA6XG4gICAgICAgIGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5tYXgodGhpc0Jhck1heFBvcyhkaSksIGRpLnAgKyB0LmJhcmRlbHRhIC8gMik7XG4gICAgICAgIH07XG5cbiAgICBmdW5jdGlvbiBfcG9zaXRpb25GbihfbWluUG9zLCBfbWF4UG9zKSB7XG4gICAgICAgIC8vIGFkZCBhIGxpdHRsZSB0byB0aGUgcHNldWRvLWRpc3RhbmNlIGZvciB3aWRlciBiYXJzLCBzbyB0aGF0IGxpa2Ugc2NhdHRlcixcbiAgICAgICAgLy8gaWYgeW91IGFyZSBvdmVyIHR3byBvdmVybGFwcGluZyBiYXJzLCB0aGUgbmFycm93ZXIgb25lIHdpbnMuXG4gICAgICAgIHJldHVybiBGeC5pbmJveChfbWluUG9zIC0gcG9zVmFsLCBfbWF4UG9zIC0gcG9zVmFsLFxuICAgICAgICAgICAgbWF4SG92ZXJEaXN0YW5jZSArIE1hdGgubWluKDEsIE1hdGguYWJzKF9tYXhQb3MgLSBfbWluUG9zKSAvIHBSYW5nZUNhbGMpIC0gMSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcG9zaXRpb25GbihkaSkge1xuICAgICAgICByZXR1cm4gX3Bvc2l0aW9uRm4obWluUG9zKGRpKSwgbWF4UG9zKGRpKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGhpc0JhclBvc2l0aW9uRm4oZGkpIHtcbiAgICAgICAgcmV0dXJuIF9wb3NpdGlvbkZuKHRoaXNCYXJNaW5Qb3MoZGkpLCB0aGlzQmFyTWF4UG9zKGRpKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2l6ZUZuKGRpKSB7XG4gICAgICAgIC8vIGFkZCBhIGdyYWRpZW50IHNvIGhvdmVyaW5nIG5lYXIgdGhlIGVuZCBvZiBhXG4gICAgICAgIC8vIGJhciBtYWtlcyBpdCBhIGxpdHRsZSBjbG9zZXIgbWF0Y2hcbiAgICAgICAgcmV0dXJuIEZ4LmluYm94KGRpLmIgLSBzaXplVmFsLCBkaVtzaXplTGV0dGVyXSAtIHNpemVWYWwsXG4gICAgICAgICAgICBtYXhIb3ZlckRpc3RhbmNlICsgKGRpW3NpemVMZXR0ZXJdIC0gc2l6ZVZhbCkgLyAoZGlbc2l6ZUxldHRlcl0gLSBkaS5iKSAtIDEpO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgcG9zVmFsID0geXZhbDtcbiAgICAgICAgc2l6ZVZhbCA9IHh2YWw7XG4gICAgICAgIHBvc0xldHRlciA9ICd5JztcbiAgICAgICAgc2l6ZUxldHRlciA9ICd4JztcbiAgICAgICAgZHggPSBzaXplRm47XG4gICAgICAgIGR5ID0gcG9zaXRpb25GbjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHBvc1ZhbCA9IHh2YWw7XG4gICAgICAgIHNpemVWYWwgPSB5dmFsO1xuICAgICAgICBwb3NMZXR0ZXIgPSAneCc7XG4gICAgICAgIHNpemVMZXR0ZXIgPSAneSc7XG4gICAgICAgIGR5ID0gc2l6ZUZuO1xuICAgICAgICBkeCA9IHBvc2l0aW9uRm47XG4gICAgfVxuXG4gICAgdmFyIHBhID0gcG9pbnREYXRhW3Bvc0xldHRlciArICdhJ107XG4gICAgdmFyIHNhID0gcG9pbnREYXRhW3NpemVMZXR0ZXIgKyAnYSddO1xuXG4gICAgcFJhbmdlQ2FsYyA9IE1hdGguYWJzKHBhLnIyYyhwYS5yYW5nZVsxXSkgLSBwYS5yMmMocGEucmFuZ2VbMF0pKTtcblxuICAgIGZ1bmN0aW9uIGR4eShkaSkgeyByZXR1cm4gKGR4KGRpKSArIGR5KGRpKSkgLyAyOyB9XG4gICAgdmFyIGRpc3RmbiA9IEZ4LmdldERpc3RhbmNlRnVuY3Rpb24oaG92ZXJtb2RlLCBkeCwgZHksIGR4eSk7XG4gICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdGZuLCBwb2ludERhdGEpO1xuXG4gICAgLy8gc2tpcCB0aGUgcmVzdCAoZm9yIHRoaXMgdHJhY2UpIGlmIHdlIGRpZG4ndCBmaW5kIGEgY2xvc2UgcG9pbnRcbiAgICBpZihwb2ludERhdGEuaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAvLyBpZiB3ZSBnZXQgaGVyZSBhbmQgd2UncmUgbm90IGluICdjbG9zZXN0JyBtb2RlLCBwdXNoIG1pbi9tYXggcG9zIGJhY2tcbiAgICAvLyBvbnRvIHRoZSBncm91cCAtIGV2ZW4gdGhvdWdoIHRoYXQgbWVhbnMgb2NjYXNpb25hbGx5IHRoZSBtb3VzZSB3aWxsIGJlXG4gICAgLy8gb3ZlciB0aGUgaG92ZXIgbGFiZWwuXG4gICAgaWYoIWlzQ2xvc2VzdCkge1xuICAgICAgICBtaW5Qb3MgPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWluKHRoaXNCYXJNaW5Qb3MoZGkpLCBkaS5wIC0gdC5iYXJncm91cHdpZHRoIC8gMik7XG4gICAgICAgIH07XG4gICAgICAgIG1heFBvcyA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5tYXgodGhpc0Jhck1heFBvcyhkaSksIGRpLnAgKyB0LmJhcmdyb3Vwd2lkdGggLyAyKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyB0aGUgY2xvc2VzdCBkYXRhIHBvaW50XG4gICAgdmFyIGluZGV4ID0gcG9pbnREYXRhLmluZGV4O1xuICAgIHZhciBkaSA9IGNkW2luZGV4XTtcblxuICAgIHZhciBzaXplID0gKHRyYWNlLmJhc2UpID8gZGkuYiArIGRpLnMgOiBkaS5zO1xuICAgIHBvaW50RGF0YVtzaXplTGV0dGVyICsgJzAnXSA9IHBvaW50RGF0YVtzaXplTGV0dGVyICsgJzEnXSA9IHNhLmMycChkaVtzaXplTGV0dGVyXSwgdHJ1ZSk7XG4gICAgcG9pbnREYXRhW3NpemVMZXR0ZXIgKyAnTGFiZWxWYWwnXSA9IHNpemU7XG5cbiAgICB2YXIgZXh0ZW50ID0gdC5leHRlbnRzW3QuZXh0ZW50cy5yb3VuZChkaS5wKV07XG4gICAgcG9pbnREYXRhW3Bvc0xldHRlciArICcwJ10gPSBwYS5jMnAoaXNDbG9zZXN0ID8gbWluUG9zKGRpKSA6IGV4dGVudFswXSwgdHJ1ZSk7XG4gICAgcG9pbnREYXRhW3Bvc0xldHRlciArICcxJ10gPSBwYS5jMnAoaXNDbG9zZXN0ID8gbWF4UG9zKGRpKSA6IGV4dGVudFsxXSwgdHJ1ZSk7XG4gICAgcG9pbnREYXRhW3Bvc0xldHRlciArICdMYWJlbFZhbCddID0gZGkucDtcblxuICAgIC8vIHNwaWtlbGluZXMgYWx3YXlzIHdhbnQgXCJjbG9zZXN0XCIgZGlzdGFuY2UgcmVnYXJkbGVzcyBvZiBob3Zlcm1vZGVcbiAgICBwb2ludERhdGEuc3Bpa2VEaXN0YW5jZSA9IChzaXplRm4oZGkpICsgdGhpc0JhclBvc2l0aW9uRm4oZGkpKSAvIDIgKyBtYXhTcGlrZURpc3RhbmNlIC0gbWF4SG92ZXJEaXN0YW5jZTtcbiAgICAvLyB0aGV5IGFsc28gd2FudCB0byBwb2ludCB0byB0aGUgZGF0YSB2YWx1ZSwgcmVnYXJkbGVzcyBvZiB3aGVyZSB0aGUgbGFiZWwgZ29lc1xuICAgIC8vIGluIGNhc2Ugb2YgYmFycyBzaGlmdGVkIHdpdGhpbiBncm91cHNcbiAgICBwb2ludERhdGFbcG9zTGV0dGVyICsgJ1NwaWtlJ10gPSBwYS5jMnAoZGkucCwgdHJ1ZSk7XG5cbiAgICBwb2ludERhdGEuY29sb3IgPSBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSk7XG4gICAgZmlsbEhvdmVyVGV4dChkaSwgdHJhY2UsIHBvaW50RGF0YSk7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnaG92ZXJJbmZvJykoZGksIHRyYWNlLCBwb2ludERhdGEpO1xuXG4gICAgcmV0dXJuIFtwb2ludERhdGFdO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSkge1xuICAgIHZhciBtYyA9IGRpLm1jYyB8fCB0cmFjZS5tYXJrZXIuY29sb3I7XG4gICAgdmFyIG1sYyA9IGRpLm1sY2MgfHwgdHJhY2UubWFya2VyLmxpbmUuY29sb3I7XG4gICAgdmFyIG1sdyA9IGRpLm1sdyB8fCB0cmFjZS5tYXJrZXIubGluZS53aWR0aDtcblxuICAgIGlmKENvbG9yLm9wYWNpdHkobWMpKSByZXR1cm4gbWM7XG4gICAgZWxzZSBpZihDb2xvci5vcGFjaXR5KG1sYykgJiYgbWx3KSByZXR1cm4gbWxjO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBob3ZlclBvaW50czogaG92ZXJQb2ludHMsXG4gICAgZ2V0VHJhY2VDb2xvcjogZ2V0VHJhY2VDb2xvclxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmFyID0ge307XG5cbkJhci5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5CYXIubGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbkJhci5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbkJhci5zdXBwbHlMYXlvdXREZWZhdWx0cyA9IHJlcXVpcmUoJy4vbGF5b3V0X2RlZmF1bHRzJyk7XG5CYXIuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuQmFyLmNyb3NzVHJhY2VDYWxjID0gcmVxdWlyZSgnLi9jcm9zc190cmFjZV9jYWxjJykuY3Jvc3NUcmFjZUNhbGM7XG5CYXIuY29sb3JiYXIgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpO1xuQmFyLmFycmF5c1RvQ2FsY2RhdGEgPSByZXF1aXJlKCcuL2FycmF5c190b19jYWxjZGF0YScpO1xuQmFyLnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcbkJhci5zdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUnKS5zdHlsZTtcbkJhci5zdHlsZU9uU2VsZWN0ID0gcmVxdWlyZSgnLi9zdHlsZScpLnN0eWxlT25TZWxlY3Q7XG5CYXIuaG92ZXJQb2ludHMgPSByZXF1aXJlKCcuL2hvdmVyJykuaG92ZXJQb2ludHM7XG5CYXIuc2VsZWN0UG9pbnRzID0gcmVxdWlyZSgnLi9zZWxlY3QnKTtcblxuQmFyLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuQmFyLm5hbWUgPSAnYmFyJztcbkJhci5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpO1xuQmFyLmNhdGVnb3JpZXMgPSBbJ2NhcnRlc2lhbicsICdzdmcnLCAnYmFyJywgJ29yaWVudGVkJywgJ2Vycm9yQmFyc09LJywgJ3Nob3dMZWdlbmQnLCAnem9vbVNjYWxlJ107XG5CYXIubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQmFyO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGJhcm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc3RhY2snLCAnZ3JvdXAnLCAnb3ZlcmxheScsICdyZWxhdGl2ZSddLFxuICAgICAgICBkZmx0OiAnZ3JvdXAnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYXJub3JtOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJycsICdmcmFjdGlvbicsICdwZXJjZW50J10sXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYXJnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYXJncm91cGdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXlvdXRJbiwgbGF5b3V0T3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgaGFzQmFycyA9IGZhbHNlLFxuICAgICAgICBzaG91bGRCZUdhcGxlc3MgPSBmYWxzZSxcbiAgICAgICAgZ2FwcGVkQW55d2F5ID0gZmFsc2UsXG4gICAgICAgIHVzZWRTdWJwbG90cyA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnYmFyJykgJiYgdHJhY2UudmlzaWJsZSkgaGFzQmFycyA9IHRydWU7XG4gICAgICAgIGVsc2UgY29udGludWU7XG5cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBhdCBsZWFzdCAyIGdyb3VwZWQgYmFyIHRyYWNlcyBvbiB0aGUgc2FtZSBzdWJwbG90LFxuICAgICAgICAvLyB3ZSBzaG91bGQgZGVmYXVsdCB0byBhIGdhcCBhbnl3YXksIGV2ZW4gaWYgdGhlIGRhdGEgaXMgaGlzdG9ncmFtc1xuICAgICAgICBpZihsYXlvdXRJbi5iYXJtb2RlICE9PSAnb3ZlcmxheScgJiYgbGF5b3V0SW4uYmFybW9kZSAhPT0gJ3N0YWNrJykge1xuICAgICAgICAgICAgdmFyIHN1YnBsb3RpID0gdHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcztcbiAgICAgICAgICAgIGlmKHVzZWRTdWJwbG90c1tzdWJwbG90aV0pIGdhcHBlZEFueXdheSA9IHRydWU7XG4gICAgICAgICAgICB1c2VkU3VicGxvdHNbc3VicGxvdGldID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgJiYgdHJhY2UudHlwZSA9PT0gJ2hpc3RvZ3JhbScpIHtcbiAgICAgICAgICAgIHZhciBwYSA9IEF4ZXMuZ2V0RnJvbUlkKHtfZnVsbExheW91dDogbGF5b3V0T3V0fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlW3RyYWNlLm9yaWVudGF0aW9uID09PSAndicgPyAneGF4aXMnIDogJ3lheGlzJ10pO1xuICAgICAgICAgICAgaWYocGEudHlwZSAhPT0gJ2NhdGVnb3J5Jykgc2hvdWxkQmVHYXBsZXNzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCFoYXNCYXJzKSByZXR1cm47XG5cbiAgICB2YXIgbW9kZSA9IGNvZXJjZSgnYmFybW9kZScpO1xuICAgIGlmKG1vZGUgIT09ICdvdmVybGF5JykgY29lcmNlKCdiYXJub3JtJyk7XG5cbiAgICBjb2VyY2UoJ2JhcmdhcCcsIChzaG91bGRCZUdhcGxlc3MgJiYgIWdhcHBlZEFueXdheSkgPyAwIDogMC4yKTtcbiAgICBjb2VyY2UoJ2Jhcmdyb3VwZ2FwJyk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBhdHRyaWJ1dGVUZXh0ID0gYXR0cmlidXRlcy50ZXh0LFxuICAgIGF0dHJpYnV0ZVRleHRQb3NpdGlvbiA9IGF0dHJpYnV0ZXMudGV4dHBvc2l0aW9uO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBzdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUnKTtcblxuLy8gcGFkZGluZyBpbiBwaXhlbHMgYXJvdW5kIHRleHRcbnZhciBURVhUUEFEID0gMztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2RiYXIsIGJhckxheWVyKSB7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBiYXJ0cmFjZXMgPSBMaWIubWFrZVRyYWNlR3JvdXBzKGJhckxheWVyLCBjZGJhciwgJ3RyYWNlIGJhcnMnKS5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgIHZhciBwbG90R3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuXG4gICAgICAgIGlmKCFwbG90aW5mby5pc1JhbmdlUGxvdCkgY2QwLm5vZGUzID0gcGxvdEdyb3VwO1xuXG4gICAgICAgIHZhciBwb2ludEdyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90R3JvdXAsICdnJywgJ3BvaW50cycpO1xuXG4gICAgICAgIHZhciBiYXJzID0gcG9pbnRHcm91cC5zZWxlY3RBbGwoJ2cucG9pbnQnKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgYmFycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgncG9pbnQnLCB0cnVlKTtcblxuICAgICAgICBiYXJzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICBiYXJzLmVhY2goZnVuY3Rpb24oZGksIGkpIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIC8vIG5vdyBkaXNwbGF5IHRoZSBiYXJcbiAgICAgICAgICAgIC8vIGNsaXBwZWQgeGYveWYgKDJuZCBhcmcgdHJ1ZSk6IG5vbi1wb3NpdGl2ZVxuICAgICAgICAgICAgLy8gbG9nIHZhbHVlcyBnbyBvZmYtc2NyZWVuIGJ5IHBsb3R3aWR0aFxuICAgICAgICAgICAgLy8gc28geW91IHNlZSB0aGVtIGNvbnRpbnVlIGlmIHlvdSBkcmFnIHRoZSBwbG90XG4gICAgICAgICAgICB2YXIgeDAsIHgxLCB5MCwgeTE7XG4gICAgICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgeTAgPSB5YS5jMnAoZGkucDAsIHRydWUpO1xuICAgICAgICAgICAgICAgIHkxID0geWEuYzJwKGRpLnAxLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB4MCA9IHhhLmMycChkaS5zMCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgeDEgPSB4YS5jMnAoZGkuczEsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgLy8gZm9yIHNlbGVjdGlvbnNcbiAgICAgICAgICAgICAgICBkaS5jdCA9IFt4MSwgKHkwICsgeTEpIC8gMl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB4MCA9IHhhLmMycChkaS5wMCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgeDEgPSB4YS5jMnAoZGkucDEsIHRydWUpO1xuICAgICAgICAgICAgICAgIHkwID0geWEuYzJwKGRpLnMwLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB5MSA9IHlhLmMycChkaS5zMSwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBmb3Igc2VsZWN0aW9uc1xuICAgICAgICAgICAgICAgIGRpLmN0ID0gWyh4MCArIHgxKSAvIDIsIHkxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyh4MCkgfHwgIWlzTnVtZXJpYyh4MSkgfHxcbiAgICAgICAgICAgICAgICAgICAgIWlzTnVtZXJpYyh5MCkgfHwgIWlzTnVtZXJpYyh5MSkgfHxcbiAgICAgICAgICAgICAgICAgICAgeDAgPT09IHgxIHx8IHkwID09PSB5MSkge1xuICAgICAgICAgICAgICAgIGJhci5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBsdyA9IChkaS5tbHcgKyAxIHx8IHRyYWNlLm1hcmtlci5saW5lLndpZHRoICsgMSB8fFxuICAgICAgICAgICAgICAgICAgICAoZGkudHJhY2UgPyBkaS50cmFjZS5tYXJrZXIubGluZS53aWR0aCA6IDApICsgMSkgLSAxLFxuICAgICAgICAgICAgICAgIG9mZnNldCA9IGQzLnJvdW5kKChsdyAvIDIpICUgMSwgMik7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJvdW5kV2l0aExpbmUodikge1xuICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlIGFyZSBleHBsaWNpdCBnYXBzLCBkb24ndCByb3VuZCxcbiAgICAgICAgICAgICAgICAvLyBpdCBjYW4gbWFrZSB0aGUgZ2FwcyBsb29rIGNyYXBweVxuICAgICAgICAgICAgICAgIHJldHVybiAoZnVsbExheW91dC5iYXJnYXAgPT09IDAgJiYgZnVsbExheW91dC5iYXJncm91cGdhcCA9PT0gMCkgP1xuICAgICAgICAgICAgICAgICAgICBkMy5yb3VuZChNYXRoLnJvdW5kKHYpIC0gb2Zmc2V0LCAyKSA6IHY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGV4cGFuZFRvVmlzaWJsZSh2LCB2Yykge1xuICAgICAgICAgICAgICAgIC8vIGlmIGl0J3Mgbm90IGluIGRhbmdlciBvZiBkaXNhcHBlYXJpbmcgZW50aXJlbHksXG4gICAgICAgICAgICAgICAgLy8gcm91bmQgbW9yZSBwcmVjaXNlbHlcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5hYnModiAtIHZjKSA+PSAyID8gcm91bmRXaXRoTGluZSh2KSA6XG4gICAgICAgICAgICAgICAgLy8gYnV0IGlmIGl0J3MgdmVyeSB0aGluLCBleHBhbmQgaXQgc28gaXQnc1xuICAgICAgICAgICAgICAgIC8vIG5lY2Vzc2FyaWx5IHZpc2libGUsIGV2ZW4gaWYgaXQgbWlnaHQgb3ZlcmxhcFxuICAgICAgICAgICAgICAgIC8vIGl0cyBuZWlnaGJvclxuICAgICAgICAgICAgICAgICh2ID4gdmMgPyBNYXRoLmNlaWwodikgOiBNYXRoLmZsb29yKHYpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiBiYXJzIGFyZSBub3QgZnVsbHkgb3BhcXVlIG9yIHRoZXkgaGF2ZSBhIGxpbmVcbiAgICAgICAgICAgICAgICAvLyBhcm91bmQgdGhlbSwgcm91bmQgdG8gaW50ZWdlciBwaXhlbHMsIG1haW5seSBmb3JcbiAgICAgICAgICAgICAgICAvLyBzYWZhcmkgc28gd2UgcHJldmVudCBvdmVybGFwcyBmcm9tIGl0cyBleHBhbnNpdmVcbiAgICAgICAgICAgICAgICAvLyBwaXhlbGF0aW9uLiBpZiB0aGUgYmFycyBBUkUgZnVsbHkgb3BhcXVlIGFuZCBoYXZlXG4gICAgICAgICAgICAgICAgLy8gbm8gbGluZSwgZXhwYW5kIHRvIGEgZnVsbCBwaXhlbCB0byBtYWtlIHN1cmUgd2VcbiAgICAgICAgICAgICAgICAvLyBjYW4gc2VlIHRoZW1cbiAgICAgICAgICAgICAgICB2YXIgb3AgPSBDb2xvci5vcGFjaXR5KGRpLm1jIHx8IHRyYWNlLm1hcmtlci5jb2xvciksXG4gICAgICAgICAgICAgICAgICAgIGZpeHB4ID0gKG9wIDwgMSB8fCBsdyA+IDAuMDEpID9cbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kV2l0aExpbmUgOiBleHBhbmRUb1Zpc2libGU7XG4gICAgICAgICAgICAgICAgeDAgPSBmaXhweCh4MCwgeDEpO1xuICAgICAgICAgICAgICAgIHgxID0gZml4cHgoeDEsIHgwKTtcbiAgICAgICAgICAgICAgICB5MCA9IGZpeHB4KHkwLCB5MSk7XG4gICAgICAgICAgICAgICAgeTEgPSBmaXhweCh5MSwgeTApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGJhciwgJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAgICAgJ00nICsgeDAgKyAnLCcgKyB5MCArICdWJyArIHkxICsgJ0gnICsgeDEgKyAnVicgKyB5MCArICdaJylcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIHBsb3RpbmZvLmxheWVyQ2xpcElkKTtcblxuICAgICAgICAgICAgYXBwZW5kQmFyVGV4dChnZCwgYmFyLCBjZCwgaSwgeDAsIHgxLCB5MCwgeTEpO1xuXG4gICAgICAgICAgICBpZihwbG90aW5mby5sYXllckNsaXBJZCkge1xuICAgICAgICAgICAgICAgIERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50KGRpLCBiYXIuc2VsZWN0KCd0ZXh0JyksIHhhLCB5YSwgdHJhY2UueGNhbGVuZGFyLCB0cmFjZS55Y2FsZW5kYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBsYXN0bHksIGNsaXAgcG9pbnRzIGdyb3VwcyBvZiBgY2xpcG9uYXhpcyAhPT0gZmFsc2VgIHRyYWNlc1xuICAgICAgICAvLyBvbiBgcGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSA9PT0gdHJ1ZWAgc3VicGxvdHNcbiAgICAgICAgdmFyIGhhc0NsaXBPbkF4aXNGYWxzZSA9IGNkMC50cmFjZS5jbGlwb25heGlzID09PSBmYWxzZTtcbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHBsb3RHcm91cCwgaGFzQ2xpcE9uQXhpc0ZhbHNlID8gbnVsbCA6IHBsb3RpbmZvLmxheWVyQ2xpcElkKTtcbiAgICB9KTtcblxuICAgIC8vIGVycm9yIGJhcnMgYXJlIG9uIHRoZSB0b3BcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdwbG90JykoYmFydHJhY2VzLCBwbG90aW5mbyk7XG59O1xuXG5mdW5jdGlvbiBhcHBlbmRCYXJUZXh0KGdkLCBiYXIsIGNhbGNUcmFjZSwgaSwgeDAsIHgxLCB5MCwgeTEpIHtcbiAgICB2YXIgdGV4dFBvc2l0aW9uO1xuXG4gICAgZnVuY3Rpb24gYXBwZW5kVGV4dE5vZGUoYmFyLCB0ZXh0LCB0ZXh0Rm9udCkge1xuICAgICAgICB2YXIgdGV4dFNlbGVjdGlvbiA9IExpYi5lbnN1cmVTaW5nbGUoYmFyLCAndGV4dCcpXG4gICAgICAgICAgICAudGV4dCh0ZXh0KVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6ICdiYXJ0ZXh0IGJhcnRleHQtJyArIHRleHRQb3NpdGlvbixcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICcnLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnLFxuICAgICAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiB1bnRpbCB3ZSBjYW4gaGFuZGxlXG4gICAgICAgICAgICAgICAgLy8gdGV4IGFuZCByZWd1bGFyIHRleHQgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICAnZGF0YS1ub3RleCc6IDFcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRleHRGb250KVxuICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgIHJldHVybiB0ZXh0U2VsZWN0aW9uO1xuICAgIH1cblxuICAgIC8vIGdldCB0cmFjZSBhdHRyaWJ1dGVzXG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlLFxuICAgICAgICBvcmllbnRhdGlvbiA9IHRyYWNlLm9yaWVudGF0aW9uO1xuXG4gICAgdmFyIHRleHQgPSBnZXRUZXh0KHRyYWNlLCBpKTtcbiAgICB0ZXh0UG9zaXRpb24gPSBnZXRUZXh0UG9zaXRpb24odHJhY2UsIGkpO1xuXG4gICAgaWYoIXRleHQgfHwgdGV4dFBvc2l0aW9uID09PSAnbm9uZScpIHtcbiAgICAgICAgYmFyLnNlbGVjdCgndGV4dCcpLnJlbW92ZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGxheW91dEZvbnQgPSBnZC5fZnVsbExheW91dC5mb250O1xuICAgIHZhciBiYXJDb2xvciA9IHN0eWxlLmdldEJhckNvbG9yKGNhbGNUcmFjZVtpXSwgdHJhY2UpO1xuICAgIHZhciBpbnNpZGVUZXh0Rm9udCA9IHN0eWxlLmdldEluc2lkZVRleHRGb250KHRyYWNlLCBpLCBsYXlvdXRGb250LCBiYXJDb2xvcik7XG4gICAgdmFyIG91dHNpZGVUZXh0Rm9udCA9IHN0eWxlLmdldE91dHNpZGVUZXh0Rm9udCh0cmFjZSwgaSwgbGF5b3V0Rm9udCk7XG5cbiAgICAvLyBjb21wdXRlIHRleHQgcG9zaXRpb25cbiAgICB2YXIgYmFybW9kZSA9IGdkLl9mdWxsTGF5b3V0LmJhcm1vZGUsXG4gICAgICAgIGluU3RhY2tNb2RlID0gKGJhcm1vZGUgPT09ICdzdGFjaycpLFxuICAgICAgICBpblJlbGF0aXZlTW9kZSA9IChiYXJtb2RlID09PSAncmVsYXRpdmUnKSxcbiAgICAgICAgaW5TdGFja09yUmVsYXRpdmVNb2RlID0gaW5TdGFja01vZGUgfHwgaW5SZWxhdGl2ZU1vZGUsXG5cbiAgICAgICAgY2FsY0JhciA9IGNhbGNUcmFjZVtpXSxcbiAgICAgICAgaXNPdXRtb3N0QmFyID0gIWluU3RhY2tPclJlbGF0aXZlTW9kZSB8fCBjYWxjQmFyLl9vdXRtb3N0LFxuXG4gICAgICAgIGJhcldpZHRoID0gTWF0aC5hYnMoeDEgLSB4MCkgLSAyICogVEVYVFBBRCwgIC8vIHBhZGRpbmcgZXhjbHVkZWRcbiAgICAgICAgYmFySGVpZ2h0ID0gTWF0aC5hYnMoeTEgLSB5MCkgLSAyICogVEVYVFBBRCwgIC8vIHBhZGRpbmcgZXhjbHVkZWRcblxuICAgICAgICB0ZXh0U2VsZWN0aW9uLFxuICAgICAgICB0ZXh0QkIsXG4gICAgICAgIHRleHRXaWR0aCxcbiAgICAgICAgdGV4dEhlaWdodDtcblxuICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnKSB7XG4gICAgICAgIGlmKCFpc091dG1vc3RCYXIgJiYgIWNhbGNCYXIuaGFzQikgdGV4dFBvc2l0aW9uID0gJ2luc2lkZSc7XG4gICAgfVxuXG4gICAgaWYodGV4dFBvc2l0aW9uID09PSAnYXV0bycpIHtcbiAgICAgICAgaWYoaXNPdXRtb3N0QmFyKSB7XG4gICAgICAgICAgICAvLyBkcmF3IHRleHQgdXNpbmcgaW5zaWRlVGV4dEZvbnQgYW5kIGNoZWNrIGlmIGl0IGZpdHMgaW5zaWRlIGJhclxuICAgICAgICAgICAgdGV4dFBvc2l0aW9uID0gJ2luc2lkZSc7XG4gICAgICAgICAgICB0ZXh0U2VsZWN0aW9uID0gYXBwZW5kVGV4dE5vZGUoYmFyLCB0ZXh0LCBpbnNpZGVUZXh0Rm9udCk7XG5cbiAgICAgICAgICAgIHRleHRCQiA9IERyYXdpbmcuYkJveCh0ZXh0U2VsZWN0aW9uLm5vZGUoKSksXG4gICAgICAgICAgICB0ZXh0V2lkdGggPSB0ZXh0QkIud2lkdGgsXG4gICAgICAgICAgICB0ZXh0SGVpZ2h0ID0gdGV4dEJCLmhlaWdodDtcblxuICAgICAgICAgICAgdmFyIHRleHRIYXNTaXplID0gKHRleHRXaWR0aCA+IDAgJiYgdGV4dEhlaWdodCA+IDApLFxuICAgICAgICAgICAgICAgIGZpdHNJbnNpZGUgPVxuICAgICAgICAgICAgICAgICAgICAodGV4dFdpZHRoIDw9IGJhcldpZHRoICYmIHRleHRIZWlnaHQgPD0gYmFySGVpZ2h0KSxcbiAgICAgICAgICAgICAgICBmaXRzSW5zaWRlSWZSb3RhdGVkID1cbiAgICAgICAgICAgICAgICAgICAgKHRleHRXaWR0aCA8PSBiYXJIZWlnaHQgJiYgdGV4dEhlaWdodCA8PSBiYXJXaWR0aCksXG4gICAgICAgICAgICAgICAgZml0c0luc2lkZUlmU2hydW5rID0gKG9yaWVudGF0aW9uID09PSAnaCcpID9cbiAgICAgICAgICAgICAgICAgICAgKGJhcldpZHRoID49IHRleHRXaWR0aCAqIChiYXJIZWlnaHQgLyB0ZXh0SGVpZ2h0KSkgOlxuICAgICAgICAgICAgICAgICAgICAoYmFySGVpZ2h0ID49IHRleHRIZWlnaHQgKiAoYmFyV2lkdGggLyB0ZXh0V2lkdGgpKTtcbiAgICAgICAgICAgIGlmKHRleHRIYXNTaXplICYmXG4gICAgICAgICAgICAgICAgICAgIChmaXRzSW5zaWRlIHx8IGZpdHNJbnNpZGVJZlJvdGF0ZWQgfHwgZml0c0luc2lkZUlmU2hydW5rKSkge1xuICAgICAgICAgICAgICAgIHRleHRQb3NpdGlvbiA9ICdpbnNpZGUnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGV4dFBvc2l0aW9uID0gJ291dHNpZGUnO1xuICAgICAgICAgICAgICAgIHRleHRTZWxlY3Rpb24ucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgdGV4dFNlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB0ZXh0UG9zaXRpb24gPSAnaW5zaWRlJztcbiAgICB9XG5cbiAgICBpZighdGV4dFNlbGVjdGlvbikge1xuICAgICAgICB0ZXh0U2VsZWN0aW9uID0gYXBwZW5kVGV4dE5vZGUoYmFyLCB0ZXh0LFxuICAgICAgICAgICAgICAgICh0ZXh0UG9zaXRpb24gPT09ICdvdXRzaWRlJykgP1xuICAgICAgICAgICAgICAgIG91dHNpZGVUZXh0Rm9udCA6IGluc2lkZVRleHRGb250KTtcblxuICAgICAgICB0ZXh0QkIgPSBEcmF3aW5nLmJCb3godGV4dFNlbGVjdGlvbi5ub2RlKCkpLFxuICAgICAgICB0ZXh0V2lkdGggPSB0ZXh0QkIud2lkdGgsXG4gICAgICAgIHRleHRIZWlnaHQgPSB0ZXh0QkIuaGVpZ2h0O1xuXG4gICAgICAgIGlmKHRleHRXaWR0aCA8PSAwIHx8IHRleHRIZWlnaHQgPD0gMCkge1xuICAgICAgICAgICAgdGV4dFNlbGVjdGlvbi5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvbXB1dGUgdGV4dCB0cmFuc2Zvcm1cbiAgICB2YXIgdHJhbnNmb3JtLCBjb25zdHJhaW5lZDtcbiAgICBpZih0ZXh0UG9zaXRpb24gPT09ICdvdXRzaWRlJykge1xuICAgICAgICBjb25zdHJhaW5lZCA9IHRyYWNlLmNvbnN0cmFpbnRleHQgPT09ICdib3RoJyB8fCB0cmFjZS5jb25zdHJhaW50ZXh0ID09PSAnb3V0c2lkZSc7XG4gICAgICAgIHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybVRvTW92ZU91dHNpZGVCYXIoeDAsIHgxLCB5MCwgeTEsIHRleHRCQixcbiAgICAgICAgICAgIG9yaWVudGF0aW9uLCBjb25zdHJhaW5lZCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjb25zdHJhaW5lZCA9IHRyYWNlLmNvbnN0cmFpbnRleHQgPT09ICdib3RoJyB8fCB0cmFjZS5jb25zdHJhaW50ZXh0ID09PSAnaW5zaWRlJztcbiAgICAgICAgdHJhbnNmb3JtID0gZ2V0VHJhbnNmb3JtVG9Nb3ZlSW5zaWRlQmFyKHgwLCB4MSwgeTAsIHkxLCB0ZXh0QkIsXG4gICAgICAgICAgICBvcmllbnRhdGlvbiwgY29uc3RyYWluZWQpO1xuICAgIH1cblxuICAgIHRleHRTZWxlY3Rpb24uYXR0cigndHJhbnNmb3JtJywgdHJhbnNmb3JtKTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNmb3JtVG9Nb3ZlSW5zaWRlQmFyKHgwLCB4MSwgeTAsIHkxLCB0ZXh0QkIsIG9yaWVudGF0aW9uLCBjb25zdHJhaW5lZCkge1xuICAgIC8vIGNvbXB1dGUgdGV4dCBhbmQgdGFyZ2V0IHBvc2l0aW9uc1xuICAgIHZhciB0ZXh0V2lkdGggPSB0ZXh0QkIud2lkdGgsXG4gICAgICAgIHRleHRIZWlnaHQgPSB0ZXh0QkIuaGVpZ2h0LFxuICAgICAgICB0ZXh0WCA9ICh0ZXh0QkIubGVmdCArIHRleHRCQi5yaWdodCkgLyAyLFxuICAgICAgICB0ZXh0WSA9ICh0ZXh0QkIudG9wICsgdGV4dEJCLmJvdHRvbSkgLyAyLFxuICAgICAgICBiYXJXaWR0aCA9IE1hdGguYWJzKHgxIC0geDApLFxuICAgICAgICBiYXJIZWlnaHQgPSBNYXRoLmFicyh5MSAtIHkwKSxcbiAgICAgICAgdGFyZ2V0V2lkdGgsXG4gICAgICAgIHRhcmdldEhlaWdodCxcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WTtcblxuICAgIC8vIGFwcGx5IHRleHQgcGFkZGluZ1xuICAgIHZhciB0ZXh0cGFkO1xuICAgIGlmKGJhcldpZHRoID4gKDIgKiBURVhUUEFEKSAmJiBiYXJIZWlnaHQgPiAoMiAqIFRFWFRQQUQpKSB7XG4gICAgICAgIHRleHRwYWQgPSBURVhUUEFEO1xuICAgICAgICBiYXJXaWR0aCAtPSAyICogdGV4dHBhZDtcbiAgICAgICAgYmFySGVpZ2h0IC09IDIgKiB0ZXh0cGFkO1xuICAgIH1cbiAgICBlbHNlIHRleHRwYWQgPSAwO1xuXG4gICAgLy8gY29tcHV0ZSByb3RhdGlvbiBhbmQgc2NhbGVcbiAgICB2YXIgcm90YXRlLFxuICAgICAgICBzY2FsZTtcblxuICAgIGlmKHRleHRXaWR0aCA8PSBiYXJXaWR0aCAmJiB0ZXh0SGVpZ2h0IDw9IGJhckhlaWdodCkge1xuICAgICAgICAvLyBubyBzY2FsZSBvciByb3RhdGlvbiBpcyByZXF1aXJlZFxuICAgICAgICByb3RhdGUgPSBmYWxzZTtcbiAgICAgICAgc2NhbGUgPSAxO1xuICAgIH1cbiAgICBlbHNlIGlmKHRleHRXaWR0aCA8PSBiYXJIZWlnaHQgJiYgdGV4dEhlaWdodCA8PSBiYXJXaWR0aCkge1xuICAgICAgICAvLyBvbmx5IHJvdGF0aW9uIGlzIHJlcXVpcmVkXG4gICAgICAgIHJvdGF0ZSA9IHRydWU7XG4gICAgICAgIHNjYWxlID0gMTtcbiAgICB9XG4gICAgZWxzZSBpZigodGV4dFdpZHRoIDwgdGV4dEhlaWdodCkgPT09IChiYXJXaWR0aCA8IGJhckhlaWdodCkpIHtcbiAgICAgICAgLy8gb25seSBzY2FsZSBpcyByZXF1aXJlZFxuICAgICAgICByb3RhdGUgPSBmYWxzZTtcbiAgICAgICAgc2NhbGUgPSBjb25zdHJhaW5lZCA/IE1hdGgubWluKGJhcldpZHRoIC8gdGV4dFdpZHRoLCBiYXJIZWlnaHQgLyB0ZXh0SGVpZ2h0KSA6IDE7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyBib3RoIHNjYWxlIGFuZCByb3RhdGlvbiBhcmUgcmVxdWlyZWRcbiAgICAgICAgcm90YXRlID0gdHJ1ZTtcbiAgICAgICAgc2NhbGUgPSBjb25zdHJhaW5lZCA/IE1hdGgubWluKGJhckhlaWdodCAvIHRleHRXaWR0aCwgYmFyV2lkdGggLyB0ZXh0SGVpZ2h0KSA6IDE7XG4gICAgfVxuXG4gICAgaWYocm90YXRlKSByb3RhdGUgPSA5MDsgIC8vIHJvdGF0ZSBjbG9ja3dpc2VcblxuICAgIC8vIGNvbXB1dGUgdGV4dCBhbmQgdGFyZ2V0IHBvc2l0aW9uc1xuICAgIGlmKHJvdGF0ZSkge1xuICAgICAgICB0YXJnZXRXaWR0aCA9IHNjYWxlICogdGV4dEhlaWdodDtcbiAgICAgICAgdGFyZ2V0SGVpZ2h0ID0gc2NhbGUgKiB0ZXh0V2lkdGg7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0YXJnZXRXaWR0aCA9IHNjYWxlICogdGV4dFdpZHRoO1xuICAgICAgICB0YXJnZXRIZWlnaHQgPSBzY2FsZSAqIHRleHRIZWlnaHQ7XG4gICAgfVxuXG4gICAgaWYob3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICBpZih4MSA8IHgwKSB7XG4gICAgICAgICAgICAvLyBiYXIgZW5kIGlzIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZVxuICAgICAgICAgICAgdGFyZ2V0WCA9IHgxICsgdGV4dHBhZCArIHRhcmdldFdpZHRoIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0WCA9IHgxIC0gdGV4dHBhZCAtIHRhcmdldFdpZHRoIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZih5MSA+IHkwKSB7XG4gICAgICAgICAgICAvLyBiYXIgZW5kIGlzIG9uIHRoZSBib3R0b21cbiAgICAgICAgICAgIHRhcmdldFggPSAoeDAgKyB4MSkgLyAyO1xuICAgICAgICAgICAgdGFyZ2V0WSA9IHkxIC0gdGV4dHBhZCAtIHRhcmdldEhlaWdodCAvIDI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXRYID0gKHgwICsgeDEpIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSB5MSArIHRleHRwYWQgKyB0YXJnZXRIZWlnaHQgLyAyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldFRyYW5zZm9ybSh0ZXh0WCwgdGV4dFksIHRhcmdldFgsIHRhcmdldFksIHNjYWxlLCByb3RhdGUpO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2Zvcm1Ub01vdmVPdXRzaWRlQmFyKHgwLCB4MSwgeTAsIHkxLCB0ZXh0QkIsIG9yaWVudGF0aW9uLCBjb25zdHJhaW5lZCkge1xuICAgIHZhciBiYXJXaWR0aCA9IChvcmllbnRhdGlvbiA9PT0gJ2gnKSA/XG4gICAgICAgICAgICBNYXRoLmFicyh5MSAtIHkwKSA6XG4gICAgICAgICAgICBNYXRoLmFicyh4MSAtIHgwKSxcbiAgICAgICAgdGV4dHBhZDtcblxuICAgIC8vIEtlZXAgdGhlIHBhZGRpbmcgc28gdGhlIHRleHQgZG9lc24ndCBzaXQgcmlnaHQgYWdhaW5zdFxuICAgIC8vIHRoZSBiYXJzLCBidXQgZG9uJ3QgZmFjdG9yIGl0IGludG8gYmFyV2lkdGhcbiAgICBpZihiYXJXaWR0aCA+IDIgKiBURVhUUEFEKSB7XG4gICAgICAgIHRleHRwYWQgPSBURVhUUEFEO1xuICAgIH1cblxuICAgIC8vIGNvbXB1dGUgcm90YXRpb24gYW5kIHNjYWxlXG4gICAgdmFyIHNjYWxlID0gMTtcbiAgICBpZihjb25zdHJhaW5lZCkge1xuICAgICAgICBzY2FsZSA9IChvcmllbnRhdGlvbiA9PT0gJ2gnKSA/XG4gICAgICAgICAgICBNYXRoLm1pbigxLCBiYXJXaWR0aCAvIHRleHRCQi5oZWlnaHQpIDpcbiAgICAgICAgICAgIE1hdGgubWluKDEsIGJhcldpZHRoIC8gdGV4dEJCLndpZHRoKTtcbiAgICB9XG5cbiAgICAvLyBjb21wdXRlIHRleHQgYW5kIHRhcmdldCBwb3NpdGlvbnNcbiAgICB2YXIgdGV4dFggPSAodGV4dEJCLmxlZnQgKyB0ZXh0QkIucmlnaHQpIC8gMixcbiAgICAgICAgdGV4dFkgPSAodGV4dEJCLnRvcCArIHRleHRCQi5ib3R0b20pIC8gMixcbiAgICAgICAgdGFyZ2V0V2lkdGgsXG4gICAgICAgIHRhcmdldEhlaWdodCxcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WTtcblxuICAgIHRhcmdldFdpZHRoID0gc2NhbGUgKiB0ZXh0QkIud2lkdGg7XG4gICAgdGFyZ2V0SGVpZ2h0ID0gc2NhbGUgKiB0ZXh0QkIuaGVpZ2h0O1xuXG4gICAgaWYob3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICBpZih4MSA8IHgwKSB7XG4gICAgICAgICAgICAvLyBiYXIgZW5kIGlzIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZVxuICAgICAgICAgICAgdGFyZ2V0WCA9IHgxIC0gdGV4dHBhZCAtIHRhcmdldFdpZHRoIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0WCA9IHgxICsgdGV4dHBhZCArIHRhcmdldFdpZHRoIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZih5MSA+IHkwKSB7XG4gICAgICAgICAgICAvLyBiYXIgZW5kIGlzIG9uIHRoZSBib3R0b21cbiAgICAgICAgICAgIHRhcmdldFggPSAoeDAgKyB4MSkgLyAyO1xuICAgICAgICAgICAgdGFyZ2V0WSA9IHkxICsgdGV4dHBhZCArIHRhcmdldEhlaWdodCAvIDI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXRYID0gKHgwICsgeDEpIC8gMjtcbiAgICAgICAgICAgIHRhcmdldFkgPSB5MSAtIHRleHRwYWQgLSB0YXJnZXRIZWlnaHQgLyAyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldFRyYW5zZm9ybSh0ZXh0WCwgdGV4dFksIHRhcmdldFgsIHRhcmdldFksIHNjYWxlLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIGdldFRyYW5zZm9ybSh0ZXh0WCwgdGV4dFksIHRhcmdldFgsIHRhcmdldFksIHNjYWxlLCByb3RhdGUpIHtcbiAgICB2YXIgdHJhbnNmb3JtU2NhbGUsXG4gICAgICAgIHRyYW5zZm9ybVJvdGF0ZSxcbiAgICAgICAgdHJhbnNmb3JtVHJhbnNsYXRlO1xuXG4gICAgaWYoc2NhbGUgPCAxKSB0cmFuc2Zvcm1TY2FsZSA9ICdzY2FsZSgnICsgc2NhbGUgKyAnKSAnO1xuICAgIGVsc2Uge1xuICAgICAgICBzY2FsZSA9IDE7XG4gICAgICAgIHRyYW5zZm9ybVNjYWxlID0gJyc7XG4gICAgfVxuXG4gICAgdHJhbnNmb3JtUm90YXRlID0gKHJvdGF0ZSkgP1xuICAgICAgICAncm90YXRlKCcgKyByb3RhdGUgKyAnICcgKyB0ZXh0WCArICcgJyArIHRleHRZICsgJykgJyA6ICcnO1xuXG4gICAgLy8gTm90ZSB0aGF0IHNjYWxpbmcgYWxzbyBhZmZlY3RzIHRoZSBjZW50ZXIgb2YgdGhlIHRleHQgYm94XG4gICAgdmFyIHRyYW5zbGF0ZVggPSAodGFyZ2V0WCAtIHNjYWxlICogdGV4dFgpLFxuICAgICAgICB0cmFuc2xhdGVZID0gKHRhcmdldFkgLSBzY2FsZSAqIHRleHRZKTtcbiAgICB0cmFuc2Zvcm1UcmFuc2xhdGUgPSAndHJhbnNsYXRlKCcgKyB0cmFuc2xhdGVYICsgJyAnICsgdHJhbnNsYXRlWSArICcpJztcblxuICAgIHJldHVybiB0cmFuc2Zvcm1UcmFuc2xhdGUgKyB0cmFuc2Zvcm1TY2FsZSArIHRyYW5zZm9ybVJvdGF0ZTtcbn1cblxuZnVuY3Rpb24gZ2V0VGV4dCh0cmFjZSwgaW5kZXgpIHtcbiAgICB2YXIgdmFsdWUgPSBoZWxwZXJzLmdldFZhbHVlKHRyYWNlLnRleHQsIGluZGV4KTtcbiAgICByZXR1cm4gaGVscGVycy5jb2VyY2VTdHJpbmcoYXR0cmlidXRlVGV4dCwgdmFsdWUpO1xufVxuXG5mdW5jdGlvbiBnZXRUZXh0UG9zaXRpb24odHJhY2UsIGluZGV4KSB7XG4gICAgdmFyIHZhbHVlID0gaGVscGVycy5nZXRWYWx1ZSh0cmFjZS50ZXh0cG9zaXRpb24sIGluZGV4KTtcbiAgICByZXR1cm4gaGVscGVycy5jb2VyY2VFbnVtZXJhdGVkKGF0dHJpYnV0ZVRleHRQb3NpdGlvbiwgdmFsdWUpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGk7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuXG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoZGkuY3QsIGZhbHNlLCBpLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnROdW1iZXI6IGksXG4gICAgICAgICAgICAgICAgICAgIHg6IHhhLmMyZChkaS54KSxcbiAgICAgICAgICAgICAgICAgICAgeTogeWEuYzJkKGRpLnkpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBTaWV2ZTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbi8qKlxuICogSGVscGVyIGNsYXNzIHRvIHNpZXZlIGRhdGEgZnJvbSB0cmFjZXMgaW50byBiaW5zXG4gKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge0FycmF5fSAgIHRyYWNlc1xuICogICAgICAgICAgICAgICAgICBBcnJheSBvZiBjYWxjdWxhdGVkIHRyYWNlc1xuICogQHBhcmFtIHtib29sZWFufSBbc2VwYXJhdGVOZWdhdGl2ZVZhbHVlc11cbiAqICAgICAgICAgICAgICAgICAgSWYgdHJ1ZSwgdGhlbiBzcGxpdCBkYXRhIGF0IHRoZSBzYW1lIHBvc2l0aW9uIGludG8gYSBiYXJcbiAqICAgICAgICAgICAgICAgICAgZm9yIHBvc2l0aXZlIHZhbHVlcyBhbmQgYW5vdGhlciBmb3IgbmVnYXRpdmUgdmFsdWVzXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtkb250TWVyZ2VPdmVybGFwcGluZ0RhdGFdXG4gKiAgICAgICAgICAgICAgICAgIElmIHRydWUsIHRoZW4gZG9uJ3QgbWVyZ2Ugb3ZlcmxhcHBpbmcgYmFycyBpbnRvIGEgc2luZ2xlIGJhclxuICovXG5mdW5jdGlvbiBTaWV2ZSh0cmFjZXMsIHNlcGFyYXRlTmVnYXRpdmVWYWx1ZXMsIGRvbnRNZXJnZU92ZXJsYXBwaW5nRGF0YSkge1xuICAgIHRoaXMudHJhY2VzID0gdHJhY2VzO1xuICAgIHRoaXMuc2VwYXJhdGVOZWdhdGl2ZVZhbHVlcyA9IHNlcGFyYXRlTmVnYXRpdmVWYWx1ZXM7XG4gICAgdGhpcy5kb250TWVyZ2VPdmVybGFwcGluZ0RhdGEgPSBkb250TWVyZ2VPdmVybGFwcGluZ0RhdGE7XG5cbiAgICAvLyBmb3Igc2luZ2xlLWJpbiBoaXN0b2dyYW1zIC0gc2VlIGhpc3RvZ3JhbS9jYWxjXG4gICAgdmFyIHdpZHRoMSA9IEluZmluaXR5O1xuXG4gICAgdmFyIHBvc2l0aW9ucyA9IFtdO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gdHJhY2VzW2ldO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSB0cmFjZVtqXTtcbiAgICAgICAgICAgIGlmKGJhci5wICE9PSBCQUROVU0pIHBvc2l0aW9ucy5wdXNoKGJhci5wKTtcbiAgICAgICAgfVxuICAgICAgICBpZih0cmFjZVswXSAmJiB0cmFjZVswXS53aWR0aDEpIHtcbiAgICAgICAgICAgIHdpZHRoMSA9IE1hdGgubWluKHRyYWNlWzBdLndpZHRoMSwgd2lkdGgxKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcblxuICAgIHZhciBkdiA9IExpYi5kaXN0aW5jdFZhbHMocG9zaXRpb25zKTtcbiAgICB0aGlzLmRpc3RpbmN0UG9zaXRpb25zID0gZHYudmFscztcbiAgICBpZihkdi52YWxzLmxlbmd0aCA9PT0gMSAmJiB3aWR0aDEgIT09IEluZmluaXR5KSB0aGlzLm1pbkRpZmYgPSB3aWR0aDE7XG4gICAgZWxzZSB0aGlzLm1pbkRpZmYgPSBNYXRoLm1pbihkdi5taW5EaWZmLCB3aWR0aDEpO1xuXG4gICAgdGhpcy5iaW5XaWR0aCA9IHRoaXMubWluRGlmZjtcblxuICAgIHRoaXMuYmlucyA9IHt9O1xufVxuXG4vKipcbiAqIFNpZXZlIGRhdHVtXG4gKlxuICogQG1ldGhvZFxuICogQHBhcmFtIHtudW1iZXJ9IHBvc2l0aW9uXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFByZXZpb3VzIGJpbiB2YWx1ZVxuICovXG5TaWV2ZS5wcm90b3R5cGUucHV0ID0gZnVuY3Rpb24gcHV0KHBvc2l0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBsYWJlbCA9IHRoaXMuZ2V0TGFiZWwocG9zaXRpb24sIHZhbHVlKSxcbiAgICAgICAgb2xkVmFsdWUgPSB0aGlzLmJpbnNbbGFiZWxdIHx8IDA7XG5cbiAgICB0aGlzLmJpbnNbbGFiZWxdID0gb2xkVmFsdWUgKyB2YWx1ZTtcblxuICAgIHJldHVybiBvbGRWYWx1ZTtcbn07XG5cbi8qKlxuICogR2V0IGN1cnJlbnQgYmluIHZhbHVlIGZvciBhIGdpdmVuIGRhdHVtXG4gKlxuICogQG1ldGhvZFxuICogQHBhcmFtIHtudW1iZXJ9IHBvc2l0aW9uICBQb3NpdGlvbiBvZiBkYXR1bVxuICogQHBhcmFtIHtudW1iZXJ9IFt2YWx1ZV0gICBWYWx1ZSBvZiBkYXR1bVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAocmVxdWlyZWQgaWYgdGhpcy5zZXBhcmF0ZU5lZ2F0aXZlVmFsdWVzIGlzIHRydWUpXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBDdXJyZW50IGJpbiB2YWx1ZVxuICovXG5TaWV2ZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gcHV0KHBvc2l0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBsYWJlbCA9IHRoaXMuZ2V0TGFiZWwocG9zaXRpb24sIHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcy5iaW5zW2xhYmVsXSB8fCAwO1xufTtcblxuLyoqXG4gKiBHZXQgYmluIGxhYmVsIGZvciBhIGdpdmVuIGRhdHVtXG4gKlxuICogQG1ldGhvZFxuICogQHBhcmFtIHtudW1iZXJ9IHBvc2l0aW9uICBQb3NpdGlvbiBvZiBkYXR1bVxuICogQHBhcmFtIHtudW1iZXJ9IFt2YWx1ZV0gICBWYWx1ZSBvZiBkYXR1bVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAocmVxdWlyZWQgaWYgdGhpcy5zZXBhcmF0ZU5lZ2F0aXZlVmFsdWVzIGlzIHRydWUpXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBCaW4gbGFiZWxcbiAqIChwcmVmaXhlZCB3aXRoIGEgJ3YnIGlmIHZhbHVlIGlzIG5lZ2F0aXZlIGFuZCB0aGlzLnNlcGFyYXRlTmVnYXRpdmVWYWx1ZXMgaXNcbiAqIHRydWU7IG90aGVyd2lzZSBwcmVmaXhlZCB3aXRoICdeJylcbiAqL1xuU2lldmUucHJvdG90eXBlLmdldExhYmVsID0gZnVuY3Rpb24gZ2V0TGFiZWwocG9zaXRpb24sIHZhbHVlKSB7XG4gICAgdmFyIHByZWZpeCA9ICh2YWx1ZSA8IDAgJiYgdGhpcy5zZXBhcmF0ZU5lZ2F0aXZlVmFsdWVzKSA/ICd2JyA6ICdeJyxcbiAgICAgICAgbGFiZWwgPSAodGhpcy5kb250TWVyZ2VPdmVybGFwcGluZ0RhdGEpID9cbiAgICAgICAgICAgIHBvc2l0aW9uIDpcbiAgICAgICAgICAgIE1hdGgucm91bmQocG9zaXRpb24gLyB0aGlzLmJpbldpZHRoKTtcbiAgICByZXR1cm4gcHJlZml4ICsgbGFiZWw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBhdHRyaWJ1dGVUZXh0Rm9udCA9IGF0dHJpYnV0ZXMudGV4dGZvbnQsXG4gICAgYXR0cmlidXRlSW5zaWRlVGV4dEZvbnQgPSBhdHRyaWJ1dGVzLmluc2lkZXRleHRmb250LFxuICAgIGF0dHJpYnV0ZU91dHNpZGVUZXh0Rm9udCA9IGF0dHJpYnV0ZXMub3V0c2lkZXRleHRmb250O1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcblxuZnVuY3Rpb24gc3R5bGUoZ2QsIGNkKSB7XG4gICAgdmFyIHMgPSBjZCA/IGNkWzBdLm5vZGUzIDogZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cudHJhY2UuYmFycycpO1xuICAgIHZhciBiYXJjb3VudCA9IHMuc2l6ZSgpO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICAvLyB0cmFjZSBzdHlsaW5nXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF0udHJhY2Uub3BhY2l0eTsgfSlcblxuICAgIC8vIGZvciBnYXBsZXNzIChlaXRoZXIgc3RhY2tlZCBvciBuZWlnaGJvcmluZyBncm91cGVkKSBiYXJzIHVzZVxuICAgIC8vIGNyaXNwRWRnZXMgdG8gdHVybiBvZmYgYW50aWFsaWFzaW5nIHNvIGFuIGFydGlmaWNpYWwgZ2FwXG4gICAgLy8gaXNuJ3QgaW50cm9kdWNlZC5cbiAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIGlmKChmdWxsTGF5b3V0LmJhcm1vZGUgPT09ICdzdGFjaycgJiYgYmFyY291bnQgPiAxKSB8fFxuICAgICAgICAgICAgICAgIChmdWxsTGF5b3V0LmJhcmdhcCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0LmJhcmdyb3VwZ2FwID09PSAwICYmXG4gICAgICAgICAgICAgICAgICFkWzBdLnRyYWNlLm1hcmtlci5saW5lLndpZHRoKSkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHMuc2VsZWN0QWxsKCdnLnBvaW50cycpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICBzdHlsZVBvaW50cyhzZWwsIHRyYWNlLCBnZCk7XG4gICAgfSk7XG5cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdHlsZScpKHMpO1xufVxuXG5mdW5jdGlvbiBzdHlsZVBvaW50cyhzZWwsIHRyYWNlLCBnZCkge1xuICAgIHZhciBwdHMgPSBzZWwuc2VsZWN0QWxsKCdwYXRoJyk7XG4gICAgdmFyIHR4cyA9IHNlbC5zZWxlY3RBbGwoJ3RleHQnKTtcblxuICAgIERyYXdpbmcucG9pbnRTdHlsZShwdHMsIHRyYWNlLCBnZCk7XG5cbiAgICB0eHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0eCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGZvbnQgPSBkZXRlcm1pbmVGb250KHR4LCBkLCB0cmFjZSwgZ2QpO1xuICAgICAgICBEcmF3aW5nLmZvbnQodHgsIGZvbnQpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBzdHlsZU9uU2VsZWN0KGdkLCBjZCkge1xuICAgIHZhciBzID0gY2RbMF0ubm9kZTM7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cykge1xuICAgICAgICBzdHlsZVBvaW50c0luU2VsZWN0aW9uTW9kZShzLCB0cmFjZSwgZ2QpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlUG9pbnRzKHMsIHRyYWNlLCBnZCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzdHlsZVBvaW50c0luU2VsZWN0aW9uTW9kZShzLCB0cmFjZSwgZ2QpIHtcbiAgICBEcmF3aW5nLnNlbGVjdGVkUG9pbnRTdHlsZShzLnNlbGVjdEFsbCgncGF0aCcpLCB0cmFjZSk7XG4gICAgc3R5bGVUZXh0SW5TZWxlY3Rpb25Nb2RlKHMuc2VsZWN0QWxsKCd0ZXh0JyksIHRyYWNlLCBnZCk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlVGV4dEluU2VsZWN0aW9uTW9kZSh0eHMsIHRyYWNlLCBnZCkge1xuICAgIHR4cy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHR4ID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgZm9udDtcblxuICAgICAgICBpZihkLnNlbGVjdGVkKSB7XG4gICAgICAgICAgICBmb250ID0gTGliLmV4dGVuZEZsYXQoe30sIGRldGVybWluZUZvbnQodHgsIGQsIHRyYWNlLCBnZCkpO1xuXG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRGb250Q29sb3IgPSB0cmFjZS5zZWxlY3RlZC50ZXh0Zm9udCAmJiB0cmFjZS5zZWxlY3RlZC50ZXh0Zm9udC5jb2xvcjtcbiAgICAgICAgICAgIGlmKHNlbGVjdGVkRm9udENvbG9yKSB7XG4gICAgICAgICAgICAgICAgZm9udC5jb2xvciA9IHNlbGVjdGVkRm9udENvbG9yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBEcmF3aW5nLmZvbnQodHgsIGZvbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRHJhd2luZy5zZWxlY3RlZFRleHRTdHlsZSh0eCwgdHJhY2UpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRldGVybWluZUZvbnQodHgsIGQsIHRyYWNlLCBnZCkge1xuICAgIHZhciBsYXlvdXRGb250ID0gZ2QuX2Z1bGxMYXlvdXQuZm9udDtcbiAgICB2YXIgdGV4dEZvbnQgPSB0cmFjZS50ZXh0Zm9udDtcblxuICAgIGlmKHR4LmNsYXNzZWQoJ2JhcnRleHQtaW5zaWRlJykpIHtcbiAgICAgICAgdmFyIGJhckNvbG9yID0gZ2V0QmFyQ29sb3IoZCwgdHJhY2UpO1xuICAgICAgICB0ZXh0Rm9udCA9IGdldEluc2lkZVRleHRGb250KHRyYWNlLCBkLmksIGxheW91dEZvbnQsIGJhckNvbG9yKTtcbiAgICB9IGVsc2UgaWYodHguY2xhc3NlZCgnYmFydGV4dC1vdXRzaWRlJykpIHtcbiAgICAgICAgdGV4dEZvbnQgPSBnZXRPdXRzaWRlVGV4dEZvbnQodHJhY2UsIGQuaSwgbGF5b3V0Rm9udCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRleHRGb250O1xufVxuXG5mdW5jdGlvbiBnZXRUZXh0Rm9udCh0cmFjZSwgaW5kZXgsIGRlZmF1bHRWYWx1ZSkge1xuICAgIHJldHVybiBnZXRGb250VmFsdWUoXG4gICAgICBhdHRyaWJ1dGVUZXh0Rm9udCwgdHJhY2UudGV4dGZvbnQsIGluZGV4LCBkZWZhdWx0VmFsdWUpO1xufVxuXG5mdW5jdGlvbiBnZXRJbnNpZGVUZXh0Rm9udCh0cmFjZSwgaW5kZXgsIGxheW91dEZvbnQsIGJhckNvbG9yKSB7XG4gICAgdmFyIGRlZmF1bHRGb250ID0gZ2V0VGV4dEZvbnQodHJhY2UsIGluZGV4LCBsYXlvdXRGb250KTtcblxuICAgIHZhciB3b3VsZEZhbGxCYWNrVG9MYXlvdXRGb250ID1cbiAgICAgICh0cmFjZS5faW5wdXQudGV4dGZvbnQgPT09IHVuZGVmaW5lZCB8fCB0cmFjZS5faW5wdXQudGV4dGZvbnQuY29sb3IgPT09IHVuZGVmaW5lZCkgfHxcbiAgICAgIChBcnJheS5pc0FycmF5KHRyYWNlLnRleHRmb250LmNvbG9yKSAmJiB0cmFjZS50ZXh0Zm9udC5jb2xvcltpbmRleF0gPT09IHVuZGVmaW5lZCk7XG4gICAgaWYod291bGRGYWxsQmFja1RvTGF5b3V0Rm9udCkge1xuICAgICAgICBkZWZhdWx0Rm9udCA9IHtcbiAgICAgICAgICAgIGNvbG9yOiBDb2xvci5jb250cmFzdChiYXJDb2xvciksXG4gICAgICAgICAgICBmYW1pbHk6IGRlZmF1bHRGb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IGRlZmF1bHRGb250LnNpemVcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0Rm9udFZhbHVlKFxuICAgICAgYXR0cmlidXRlSW5zaWRlVGV4dEZvbnQsIHRyYWNlLmluc2lkZXRleHRmb250LCBpbmRleCwgZGVmYXVsdEZvbnQpO1xufVxuXG5mdW5jdGlvbiBnZXRPdXRzaWRlVGV4dEZvbnQodHJhY2UsIGluZGV4LCBsYXlvdXRGb250KSB7XG4gICAgdmFyIGRlZmF1bHRGb250ID0gZ2V0VGV4dEZvbnQodHJhY2UsIGluZGV4LCBsYXlvdXRGb250KTtcbiAgICByZXR1cm4gZ2V0Rm9udFZhbHVlKFxuICAgICAgYXR0cmlidXRlT3V0c2lkZVRleHRGb250LCB0cmFjZS5vdXRzaWRldGV4dGZvbnQsIGluZGV4LCBkZWZhdWx0Rm9udCk7XG59XG5cbmZ1bmN0aW9uIGdldEZvbnRWYWx1ZShhdHRyaWJ1dGVEZWZpbml0aW9uLCBhdHRyaWJ1dGVWYWx1ZSwgaW5kZXgsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGF0dHJpYnV0ZVZhbHVlID0gYXR0cmlidXRlVmFsdWUgfHwge307XG5cbiAgICB2YXIgZmFtaWx5VmFsdWUgPSBoZWxwZXJzLmdldFZhbHVlKGF0dHJpYnV0ZVZhbHVlLmZhbWlseSwgaW5kZXgpLFxuICAgICAgICBzaXplVmFsdWUgPSBoZWxwZXJzLmdldFZhbHVlKGF0dHJpYnV0ZVZhbHVlLnNpemUsIGluZGV4KSxcbiAgICAgICAgY29sb3JWYWx1ZSA9IGhlbHBlcnMuZ2V0VmFsdWUoYXR0cmlidXRlVmFsdWUuY29sb3IsIGluZGV4KTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhbWlseTogaGVscGVycy5jb2VyY2VTdHJpbmcoXG4gICAgICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5mYW1pbHksIGZhbWlseVZhbHVlLCBkZWZhdWx0VmFsdWUuZmFtaWx5KSxcbiAgICAgICAgc2l6ZTogaGVscGVycy5jb2VyY2VOdW1iZXIoXG4gICAgICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5zaXplLCBzaXplVmFsdWUsIGRlZmF1bHRWYWx1ZS5zaXplKSxcbiAgICAgICAgY29sb3I6IGhlbHBlcnMuY29lcmNlQ29sb3IoXG4gICAgICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5jb2xvciwgY29sb3JWYWx1ZSwgZGVmYXVsdFZhbHVlLmNvbG9yKVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldEJhckNvbG9yKGNkLCB0cmFjZSkge1xuICAgIHJldHVybiBjZC5tYyB8fCB0cmFjZS5tYXJrZXIuY29sb3I7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBzdHlsZU9uU2VsZWN0LFxuICAgIGdldEluc2lkZVRleHRGb250OiBnZXRJbnNpZGVUZXh0Rm9udCxcbiAgICBnZXRPdXRzaWRlVGV4dEZvbnQ6IGdldE91dHNpZGVUZXh0Rm9udCxcbiAgICBnZXRCYXJDb2xvcjogZ2V0QmFyQ29sb3Jcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGhhc0NvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGFzX2NvbG9yc2NhbGUnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgY29lcmNlKCdtYXJrZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbWFya2VyJykpIHtcbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKFxuICAgICAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbWFya2VyLicsIGNMZXR0ZXI6ICdjJ31cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJywgQ29sb3IuZGVmYXVsdExpbmUpO1xuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHMoXG4gICAgICAgICAgICB0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdtYXJrZXIubGluZS4nLCBjTGV0dGVyOiAnYyd9XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnbWFya2VyLm9wYWNpdHknKTtcbiAgICBjb2VyY2UoJ3NlbGVjdGVkLm1hcmtlci5jb2xvcicpO1xuICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIuY29sb3InKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgc2NhdHRlclBvbGFyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVycG9sYXIvYXR0cmlidXRlcycpO1xudmFyIGJhckF0dHJzID0gcmVxdWlyZSgnLi4vYmFyL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcjogc2NhdHRlclBvbGFyQXR0cnMucixcbiAgICB0aGV0YTogc2NhdHRlclBvbGFyQXR0cnMudGhldGEsXG4gICAgcjA6IHNjYXR0ZXJQb2xhckF0dHJzLnIwLFxuICAgIGRyOiBzY2F0dGVyUG9sYXJBdHRycy5kcixcbiAgICB0aGV0YTA6IHNjYXR0ZXJQb2xhckF0dHJzLnRoZXRhMCxcbiAgICBkdGhldGE6IHNjYXR0ZXJQb2xhckF0dHJzLmR0aGV0YSxcbiAgICB0aGV0YXVuaXQ6IHNjYXR0ZXJQb2xhckF0dHJzLnRoZXRhdW5pdCxcblxuICAgIC8vIG9yaWVudGF0aW9uOiB7XG4gICAgLy8gICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAvLyAgICAgXG4gICAgLy8gICAgIHZhbHVlczogWydyYWRpYWwnLCAnYW5ndWxhciddLFxuICAgIC8vICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgIC8vICAgICBcbiAgICAvLyB9LFxuXG4gICAgYmFzZTogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMuYmFzZSwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBvZmZzZXQ6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLm9mZnNldCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMud2lkdGgsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBiYXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIC8vIGhvdmVydGV4dDogYmFyQXR0cnMuaG92ZXJ0ZXh0LFxuXG4gICAgLy8gdGV4dHBvc2l0aW9uOiB7fSxcbiAgICAvLyB0ZXh0Zm9udDoge30sXG4gICAgLy8gaW5zaWRldGV4dGZvbnQ6IHt9LFxuICAgIC8vIG91dHNpZGV0ZXh0Zm9udDoge30sXG4gICAgLy8gY29uc3RyYWludGV4dDoge30sXG4gICAgLy8gY2xpcG9uYXhpczogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMuY2xpcG9uYXhpcywge2RmbHQ6IGZhbHNlfSksXG5cbiAgICBtYXJrZXI6IGJhckF0dHJzLm1hcmtlcixcblxuICAgIGhvdmVyaW5mbzogc2NhdHRlclBvbGFyQXR0cnMuaG92ZXJpbmZvLFxuXG4gICAgc2VsZWN0ZWQ6IGJhckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IGJhckF0dHJzLnVuc2VsZWN0ZWRcblxuICAgIC8vIGVycm9yX3ggKGVycm9yX3IsIGVycm9yX3RoZXRhKVxuICAgIC8vIGVycm9yX3lcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoYXNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hhc19jb2xvcnNjYWxlJyk7XG52YXIgY29sb3JzY2FsZUNhbGMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSByZXF1aXJlKCcuLi9iYXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgc2V0R3JvdXBQb3NpdGlvbnMgPSByZXF1aXJlKCcuLi9iYXIvY3Jvc3NfdHJhY2VfY2FsYycpLnNldEdyb3VwUG9zaXRpb25zO1xudmFyIGNhbGNTZWxlY3Rpb24gPSByZXF1aXJlKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG52YXIgdHJhY2VJcyA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5JykudHJhY2VJcztcbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliJykuZXh0ZW5kRmxhdDtcblxuZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWQgPSB0cmFjZS5zdWJwbG90O1xuICAgIHZhciByYWRpYWxBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLnJhZGlhbGF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLmFuZ3VsYXJheGlzO1xuICAgIHZhciByQXJyYXkgPSByYWRpYWxBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3InKTtcbiAgICB2YXIgdGhldGFBcnJheSA9IGFuZ3VsYXJBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3RoZXRhJyk7XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICAvLyAnc2l6ZScgYXhpcyB2YXJpYWJsZXNcbiAgICB2YXIgc0FycmF5ID0gckFycmF5O1xuICAgIC8vICdwb3MnIGF4aXMgdmFyaWFibGVzXG4gICAgdmFyIHBBcnJheSA9IHRoZXRhQXJyYXk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgY2RbaV0gPSB7cDogcEFycmF5W2ldLCBzOiBzQXJyYXlbaV19O1xuICAgIH1cblxuICAgIC8vIGNvbnZlcnQgd2lkdGggYW5kIG9mZnNldCBpbiAnYycgY29vcmRpbmF0ZSxcbiAgICAvLyBzZXQgJ2MnIHZhbHVlKHMpIGluIHRyYWNlLl93aWR0aCBhbmQgdHJhY2UuX29mZnNldCxcbiAgICAvLyB0byBtYWtlIEJhci5jcm9zc1RyYWNlQ2FsYyBcImp1c3Qgd29ya1wiXG4gICAgZnVuY3Rpb24gZDJjKGF0dHIpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRyYWNlW2F0dHJdO1xuICAgICAgICBpZih2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJhY2VbJ18nICsgYXR0cl0gPSBBcnJheS5pc0FycmF5KHZhbCkgP1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgYXR0cikgOlxuICAgICAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmQyYyh2YWwsIHRyYWNlLnRoZXRhdW5pdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihhbmd1bGFyQXhpcy50eXBlID09PSAnbGluZWFyJykge1xuICAgICAgICBkMmMoJ3dpZHRoJyk7XG4gICAgICAgIGQyYygnb2Zmc2V0Jyk7XG4gICAgfVxuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZSwgJ21hcmtlcicpKSB7XG4gICAgICAgIGNvbG9yc2NhbGVDYWxjKHRyYWNlLCB0cmFjZS5tYXJrZXIuY29sb3IsICdtYXJrZXInLCAnYycpO1xuICAgIH1cbiAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UubWFya2VyLmxpbmUuY29sb3IsICdtYXJrZXIubGluZScsICdjJyk7XG4gICAgfVxuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn1cblxuZnVuY3Rpb24gY3Jvc3NUcmFjZUNhbGMoZ2QsIHBvbGFyTGF5b3V0LCBzdWJwbG90SWQpIHtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgYmFyUG9sYXJDZCA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZGkgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2RpWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgdHJhY2VJcyh0cmFjZSwgJ2JhcicpICYmXG4gICAgICAgICAgICB0cmFjZS5zdWJwbG90ID09PSBzdWJwbG90SWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBiYXJQb2xhckNkLnB1c2goY2RpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRvIG1ha2UgX2V4dHJlbWVzIGlzIGZpbGxlZCBpbiBjb3JyZWN0bHkgc28gdGhhdFxuICAgIC8vIHBvbGFyLl9zdWJwbG90LnJhZGlhbEF4aXMgY2FuIGdldCBhdW90cmFuZ2UnZFxuICAgIC8vIFRPRE8gY2xlYW4gdXAhXG4gICAgLy8gSSB0aGluayB3ZSB3YW50IHRvIGNhbGwgZ2V0QXV0b3JhbmdlIG9uIHBvbGFyLnJhZGlhbGF4aXNcbiAgICAvLyBOT1Qgb24gcG9sYXIuX3N1YnBsb3QucmFkaWFsQXhpc1xuICAgIHZhciByQXhpcyA9IGV4dGVuZEZsYXQoe30sIHBvbGFyTGF5b3V0LnJhZGlhbGF4aXMsIHtfaWQ6ICd4J30pO1xuICAgIHZhciBhQXhpcyA9IHBvbGFyTGF5b3V0LmFuZ3VsYXJheGlzO1xuXG4gICAgLy8gJ2JhcmdhcCcsICdiYXJtb2RlJyBhcmUgaW4gX2Z1bGxMYXlvdXQucG9sYXJcbiAgICAvLyBUT0RPIGNsZWFuIHVwIHNldEdyb3VwUG9zaXRpb25zIEFQSSBpbnN0ZWFkXG4gICAgdmFyIG1vY2tHZCA9IHtfZnVsbExheW91dDogcG9sYXJMYXlvdXR9O1xuXG4gICAgc2V0R3JvdXBQb3NpdGlvbnMobW9ja0dkLCBhQXhpcywgckF4aXMsIGJhclBvbGFyQ2QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjYWxjOiBjYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBjcm9zc1RyYWNlQ2FsY1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlUlRoZXRhRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVycG9sYXIvZGVmYXVsdHMnKS5oYW5kbGVSVGhldGFEZWZhdWx0cztcbnZhciBoYW5kbGVTdHlsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vYmFyL3N0eWxlX2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlUlRoZXRhRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGNvZXJjZSgnb3JpZW50YXRpb24nLCAodHJhY2VPdXQudGhldGEgJiYgIXRyYWNlT3V0LnIpID8gJ2FuZ3VsYXInIDogJ3JhZGlhbCcpO1xuXG4gICAgY29lcmNlKCd0aGV0YXVuaXQnKTtcbiAgICBjb2VyY2UoJ2Jhc2UnKTtcbiAgICBjb2VyY2UoJ29mZnNldCcpO1xuICAgIGNvZXJjZSgnd2lkdGgnKTtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIC8vIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG5cbiAgICAvLyB2YXIgdGV4dFBvc2l0aW9uID0gY29lcmNlKCd0ZXh0cG9zaXRpb24nKTtcbiAgICAvLyB2YXIgaGFzQm90aCA9IEFycmF5LmlzQXJyYXkodGV4dFBvc2l0aW9uKSB8fCB0ZXh0UG9zaXRpb24gPT09ICdhdXRvJztcbiAgICAvLyB2YXIgaGFzSW5zaWRlID0gaGFzQm90aCB8fCB0ZXh0UG9zaXRpb24gPT09ICdpbnNpZGUnO1xuICAgIC8vIHZhciBoYXNPdXRzaWRlID0gaGFzQm90aCB8fCB0ZXh0UG9zaXRpb24gPT09ICdvdXRzaWRlJztcblxuICAgIC8vIGlmKGhhc0luc2lkZSB8fCBoYXNPdXRzaWRlKSB7XG4gICAgLy8gICAgIHZhciB0ZXh0Rm9udCA9IGNvZXJjZUZvbnQoY29lcmNlLCAndGV4dGZvbnQnLCBsYXlvdXQuZm9udCk7XG4gICAgLy8gICAgIGlmKGhhc0luc2lkZSkgY29lcmNlRm9udChjb2VyY2UsICdpbnNpZGV0ZXh0Zm9udCcsIHRleHRGb250KTtcbiAgICAvLyAgICAgaWYoaGFzT3V0c2lkZSkgY29lcmNlRm9udChjb2VyY2UsICdvdXRzaWRldGV4dGZvbnQnLCB0ZXh0Rm9udCk7XG4gICAgLy8gICAgIGNvZXJjZSgnY29uc3RyYWludGV4dCcpO1xuICAgIC8vICAgICBjb2VyY2UoJ3NlbGVjdGVkLnRleHRmb250LmNvbG9yJyk7XG4gICAgLy8gICAgIGNvZXJjZSgndW5zZWxlY3RlZC50ZXh0Zm9udC5jb2xvcicpO1xuICAgIC8vICAgICBjb2VyY2UoJ2NsaXBvbmF4aXMnKTtcbiAgICAvLyB9XG5cbiAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGdldFRyYWNlQ29sb3IgPSByZXF1aXJlKCcuLi9iYXIvaG92ZXInKS5nZXRUcmFjZUNvbG9yO1xudmFyIGZpbGxIb3ZlclRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dCcpO1xudmFyIG1ha2VIb3ZlclBvaW50VGV4dCA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJwb2xhci9ob3ZlcicpLm1ha2VIb3ZlclBvaW50VGV4dDtcbnZhciBpc1B0SW5zaWRlUG9seWdvbiA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3BvbGFyL2hlbHBlcnMnKS5pc1B0SW5zaWRlUG9seWdvbjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICB2YXIgc3VicGxvdCA9IHBvaW50RGF0YS5zdWJwbG90O1xuICAgIHZhciByYWRpYWxBeGlzID0gc3VicGxvdC5yYWRpYWxBeGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IHN1YnBsb3QuYW5ndWxhckF4aXM7XG4gICAgdmFyIHZhbmdsZXMgPSBzdWJwbG90LnZhbmdsZXM7XG4gICAgdmFyIGluYm94Rm4gPSB2YW5nbGVzID8gaXNQdEluc2lkZVBvbHlnb24gOiBMaWIuaXNQdEluc2lkZVNlY3RvcjtcbiAgICB2YXIgbWF4SG92ZXJEaXN0YW5jZSA9IHBvaW50RGF0YS5tYXhIb3ZlckRpc3RhbmNlO1xuICAgIHZhciBwZXJpb2QgPSBhbmd1bGFyQXhpcy5fcGVyaW9kIHx8IDIgKiBNYXRoLlBJO1xuXG4gICAgdmFyIHJWYWwgPSBNYXRoLmFicyhyYWRpYWxBeGlzLmcycChNYXRoLnNxcnQoeHZhbCAqIHh2YWwgKyB5dmFsICogeXZhbCkpKTtcbiAgICB2YXIgdGhldGFWYWwgPSBNYXRoLmF0YW4yKHl2YWwsIHh2YWwpO1xuXG4gICAgLy8gcG9sYXIuKHh8eSlheGlzLnAyYyBkb2Vzbid0IGdldCB0aGUgcmV2ZXJzZWQgcmFkaWFsIGF4aXMgcmFuZ2UgY2FzZSByaWdodFxuICAgIGlmKHJhZGlhbEF4aXMucmFuZ2VbMF0gPiByYWRpYWxBeGlzLnJhbmdlWzFdKSB7XG4gICAgICAgIHRoZXRhVmFsICs9IE1hdGguUEk7XG4gICAgfVxuXG4gICAgdmFyIGRpc3RGbiA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgIGlmKGluYm94Rm4oclZhbCwgdGhldGFWYWwsIFtkaS5ycDAsIGRpLnJwMV0sIFtkaS50aGV0YWcwLCBkaS50aGV0YWcxXSwgdmFuZ2xlcykpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXhIb3ZlckRpc3RhbmNlICtcbiAgICAgICAgICAgICAgICAvLyBhZGQgYSBsaXR0bGUgdG8gdGhlIHBzZXVkby1kaXN0YW5jZSBmb3Igd2lkZXIgYmFycywgc28gdGhhdCBsaWtlIHNjYXR0ZXIsXG4gICAgICAgICAgICAgICAgLy8gaWYgeW91IGFyZSBvdmVyIHR3byBvdmVybGFwcGluZyBiYXJzLCB0aGUgbmFycm93ZXIgb25lIHdpbnMuXG4gICAgICAgICAgICAgICAgTWF0aC5taW4oMSwgTWF0aC5hYnMoZGkudGhldGFnMSAtIGRpLnRoZXRhZzApIC8gcGVyaW9kKSAtIDEgK1xuICAgICAgICAgICAgICAgIC8vIGFkZCBhIGdyYWRpZW50IHNvIGhvdmVyaW5nIG5lYXIgdGhlIGVuZCBvZiBhXG4gICAgICAgICAgICAgICAgLy8gYmFyIG1ha2VzIGl0IGEgbGl0dGxlIGNsb3NlciBtYXRjaFxuICAgICAgICAgICAgICAgIChkaS5ycDEgLSByVmFsKSAvIChkaS5ycDEgLSBkaS5ycDApIC0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBJbmZpbml0eTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBGeC5nZXRDbG9zZXN0KGNkLCBkaXN0Rm4sIHBvaW50RGF0YSk7XG4gICAgaWYocG9pbnREYXRhLmluZGV4ID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIGluZGV4ID0gcG9pbnREYXRhLmluZGV4O1xuICAgIHZhciBjZGkgPSBjZFtpbmRleF07XG5cbiAgICBwb2ludERhdGEueDAgPSBwb2ludERhdGEueDEgPSBjZGkuY3RbMF07XG4gICAgcG9pbnREYXRhLnkwID0gcG9pbnREYXRhLnkxID0gY2RpLmN0WzFdO1xuXG4gICAgdmFyIF9jZGkgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgY2RpLCB7cjogY2RpLnMsIHRoZXRhOiBjZGkucH0pO1xuICAgIGZpbGxIb3ZlclRleHQoY2RpLCB0cmFjZSwgcG9pbnREYXRhKTtcbiAgICBtYWtlSG92ZXJQb2ludFRleHQoX2NkaSwgdHJhY2UsIHN1YnBsb3QsIHBvaW50RGF0YSk7XG4gICAgcG9pbnREYXRhLmNvbG9yID0gZ2V0VHJhY2VDb2xvcih0cmFjZSwgY2RpKTtcbiAgICBwb2ludERhdGEueExhYmVsVmFsID0gcG9pbnREYXRhLnlMYWJlbFZhbCA9IHVuZGVmaW5lZDtcblxuICAgIGlmKGNkaS5zIDwgMCkge1xuICAgICAgICBwb2ludERhdGEuaWRlYWxBbGlnbiA9ICdsZWZ0JztcbiAgICB9XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdiYXJwb2xhcicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3BvbGFyJyksXG4gICAgY2F0ZWdvcmllczogWydwb2xhcicsICdiYXInLCAnc2hvd0xlZ2VuZCddLFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiByZXF1aXJlKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHJlcXVpcmUoJy4vbGF5b3V0X2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiByZXF1aXJlKCcuL2NhbGMnKS5jYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiByZXF1aXJlKCcuL2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcblxuICAgIHBsb3Q6IHJlcXVpcmUoJy4vcGxvdCcpLFxuICAgIGNvbG9yYmFyOiByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuICAgIHN0eWxlOiByZXF1aXJlKCcuLi9iYXIvc3R5bGUnKS5zdHlsZSxcblxuICAgIGhvdmVyUG9pbnRzOiByZXF1aXJlKCcuL2hvdmVyJyksXG4gICAgc2VsZWN0UG9pbnRzOiByZXF1aXJlKCcuLi9iYXIvc2VsZWN0JyksXG5cbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBiYXJtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3N0YWNrJywgJ292ZXJsYXknXSxcbiAgICAgICAgZGZsdDogJ3N0YWNrJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYmFyZ2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLjEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGF0dHJzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgdmFyIHN1YnBsb3RzRG9uZSA9IHt9O1xuICAgIHZhciBzcDtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluW3NwXSB8fCB7fSwgbGF5b3V0T3V0W3NwXSwgYXR0cnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBmdWxsRGF0YVtpXTtcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2JhcnBvbGFyJyAmJiB0cmFjZS52aXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICBzcCA9IHRyYWNlLnN1YnBsb3Q7XG4gICAgICAgICAgICBpZighc3VicGxvdHNEb25lW3NwXSkge1xuICAgICAgICAgICAgICAgIGNvZXJjZSgnYmFybW9kZScpO1xuICAgICAgICAgICAgICAgIGNvZXJjZSgnYmFyZ2FwJyk7XG4gICAgICAgICAgICAgICAgc3VicGxvdHNEb25lW3NwXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3BvbGFyL2hlbHBlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBzdWJwbG90LCBjZGJhcikge1xuICAgIHZhciB4YSA9IHN1YnBsb3QueGF4aXM7XG4gICAgdmFyIHlhID0gc3VicGxvdC55YXhpcztcbiAgICB2YXIgcmFkaWFsQXhpcyA9IHN1YnBsb3QucmFkaWFsQXhpcztcbiAgICB2YXIgYW5ndWxhckF4aXMgPSBzdWJwbG90LmFuZ3VsYXJBeGlzO1xuICAgIHZhciBwYXRoRm4gPSBtYWtlUGF0aEZuKHN1YnBsb3QpO1xuICAgIHZhciBiYXJMYXllciA9IHN1YnBsb3QubGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJ2cuYmFybGF5ZXInKTtcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHMoYmFyTGF5ZXIsIGNkYmFyLCAndHJhY2UgYmFycycpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGNkWzBdLm5vZGUzID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgcG9pbnRHcm91cCA9IExpYi5lbnN1cmVTaW5nbGUocGxvdEdyb3VwLCAnZycsICdwb2ludHMnKTtcbiAgICAgICAgdmFyIGJhcnMgPSBwb2ludEdyb3VwLnNlbGVjdEFsbCgnZy5wb2ludCcpLmRhdGEoTGliLmlkZW50aXR5KTtcblxuICAgICAgICBiYXJzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2UtbWl0ZXJsaW1pdCcsIDIpXG4gICAgICAgICAgICAuY2xhc3NlZCgncG9pbnQnLCB0cnVlKTtcblxuICAgICAgICBiYXJzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICBiYXJzLmVhY2goZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIHZhciBycDAgPSBkaS5ycDAgPSByYWRpYWxBeGlzLmMycChkaS5zMCk7XG4gICAgICAgICAgICB2YXIgcnAxID0gZGkucnAxID0gcmFkaWFsQXhpcy5jMnAoZGkuczEpO1xuICAgICAgICAgICAgdmFyIHRoZXRhZzAgPSBkaS50aGV0YWcwID0gYW5ndWxhckF4aXMuYzJnKGRpLnAwKTtcbiAgICAgICAgICAgIHZhciB0aGV0YWcxID0gZGkudGhldGFnMSA9IGFuZ3VsYXJBeGlzLmMyZyhkaS5wMSk7XG5cbiAgICAgICAgICAgIHZhciBkUGF0aDtcblxuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhycDApIHx8ICFpc051bWVyaWMocnAxKSB8fFxuICAgICAgICAgICAgICAgICFpc051bWVyaWModGhldGFnMCkgfHwgIWlzTnVtZXJpYyh0aGV0YWcxKSB8fFxuICAgICAgICAgICAgICAgIHJwMCA9PT0gcnAxIHx8IHRoZXRhZzAgPT09IHRoZXRhZzFcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIC8vIGRvIG5vdCByZW1vdmUgYmxhbmsgYmFycywgdG8ga2VlcCBkYXRhLXRvLW5vZGVcbiAgICAgICAgICAgICAgICAvLyBtYXBwaW5nIGludGFjdCBkdXJpbmcgcmFkaWFsIGRyYWcsIHRoYXQgd2VcbiAgICAgICAgICAgICAgICAvLyBjYW4gc2tpcCBjYWxsaW5nIF9tb2R1bGUuc3R5bGUgZHVyaW5nIGludGVyYWN0aW9uc1xuICAgICAgICAgICAgICAgIGRQYXRoID0gJ00wLDBaJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyAnY2VudGVyJyBwdCBpcyB1c2VkIGZvciBzZWxlY3Rpb25zIGFuZCBob3ZlciBsYWJlbHNcbiAgICAgICAgICAgICAgICB2YXIgcmcxID0gcmFkaWFsQXhpcy5jMmcoZGkuczEpO1xuICAgICAgICAgICAgICAgIHZhciB0aGV0YWdNaWQgPSAodGhldGFnMCArIHRoZXRhZzEpIC8gMjtcbiAgICAgICAgICAgICAgICBkaS5jdCA9IFtcbiAgICAgICAgICAgICAgICAgICAgeGEuYzJwKHJnMSAqIE1hdGguY29zKHRoZXRhZ01pZCkpLFxuICAgICAgICAgICAgICAgICAgICB5YS5jMnAocmcxICogTWF0aC5zaW4odGhldGFnTWlkKSlcbiAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgZFBhdGggPSBwYXRoRm4ocnAwLCBycDEsIHRoZXRhZzAsIHRoZXRhZzEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGJhciwgJ3BhdGgnKS5hdHRyKCdkJywgZFBhdGgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBjbGlwIHBsb3RHcm91cCwgd2hlbiB0cmFjZSBsYXllciBpc24ndCBjbGlwcGVkXG4gICAgICAgIERyYXdpbmcuc2V0Q2xpcFVybChwbG90R3JvdXAsIHN1YnBsb3QuX2hhc0NsaXBPbkF4aXNGYWxzZSA/IHN1YnBsb3QuY2xpcElkcy5mb3JUcmFjZXMgOiBudWxsKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VQYXRoRm4oc3VicGxvdCkge1xuICAgIHZhciBjeHggPSBzdWJwbG90LmN4eDtcbiAgICB2YXIgY3l5ID0gc3VicGxvdC5jeXk7XG5cbiAgICBpZihzdWJwbG90LnZhbmdsZXMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHIwLCByMSwgX2EwLCBfYTEpIHtcbiAgICAgICAgICAgIHZhciBhMCwgYTE7XG5cbiAgICAgICAgICAgIGlmKExpYi5hbmdsZURlbHRhKF9hMCwgX2ExKSA+IDApIHtcbiAgICAgICAgICAgICAgICBhMCA9IF9hMDtcbiAgICAgICAgICAgICAgICBhMSA9IF9hMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYTAgPSBfYTE7XG4gICAgICAgICAgICAgICAgYTEgPSBfYTA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB2YTAgPSBoZWxwZXJzLmZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXMoYTAsIHN1YnBsb3QudmFuZ2xlcylbMF07XG4gICAgICAgICAgICB2YXIgdmExID0gaGVscGVycy5maW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzKGExLCBzdWJwbG90LnZhbmdsZXMpWzFdO1xuICAgICAgICAgICAgdmFyIHZhQmFyID0gW3ZhMCwgKGEwICsgYTEpIC8gMiwgdmExXTtcbiAgICAgICAgICAgIHJldHVybiBoZWxwZXJzLnBhdGhQb2x5Z29uQW5udWx1cyhyMCwgcjEsIGEwLCBhMSwgdmFCYXIsIGN4eCwgY3l5KTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ocjAsIHIxLCBhMCwgYTEpIHtcbiAgICAgICAgcmV0dXJuIExpYi5wYXRoQW5udWx1cyhyMCwgcjEsIGEwLCBhMSwgY3h4LCBjeXkpO1xuICAgIH07XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHgwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5MDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbmFtZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgd2hpc2tlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMC41LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBub3RjaGVkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbm90Y2h3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDAuNSxcbiAgICAgICAgZGZsdDogMC4yNSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm94cG9pbnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdvdXRsaWVycycsICdzdXNwZWN0ZWRvdXRsaWVycycsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogJ291dGxpZXJzJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm94bWVhbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW3RydWUsICdzZCcsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGppdHRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHBvaW50cG9zOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDIsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3YnLCAnaCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtYXJrZXI6IHtcbiAgICAgICAgb3V0bGllcmNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgZGZsdDogJ3JnYmEoMCwgMCwgMCwgMCknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzeW1ib2w6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5zeW1ib2wsXG4gICAgICAgICAgICB7YXJyYXlPazogZmFsc2UsIGVkaXRUeXBlOiAncGxvdCd9KSxcbiAgICAgICAgb3BhY2l0eTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLm9wYWNpdHksXG4gICAgICAgICAgICB7YXJyYXlPazogZmFsc2UsIGRmbHQ6IDEsIGVkaXRUeXBlOiAnc3R5bGUnfSksXG4gICAgICAgIHNpemU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLFxuICAgICAgICAgICAge2FycmF5T2s6IGZhbHNlLCBlZGl0VHlwZTogJ2NhbGMnfSksXG4gICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMuY29sb3IsXG4gICAgICAgICAgICB7YXJyYXlPazogZmFsc2UsIGVkaXRUeXBlOiAnc3R5bGUnfSksXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyTGluZUF0dHJzLmNvbG9yLFxuICAgICAgICAgICAgICAgIHthcnJheU9rOiBmYWxzZSwgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSwgZWRpdFR5cGU6ICdzdHlsZSd9XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgICAgICAgICAge2FycmF5T2s6IGZhbHNlLCBkZmx0OiAwLCBlZGl0VHlwZTogJ3N0eWxlJ31cbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBvdXRsaWVyY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG91dGxpZXJ3aWR0aDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMixcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIGZpbGxjb2xvcjogc2NhdHRlckF0dHJzLmZpbGxjb2xvcixcblxuICAgIHNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9LFxuICAgIHVuc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZC5tYXJrZXIsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIGhvdmVyb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsnYm94ZXMnLCAncG9pbnRzJ10sXG4gICAgICAgIGRmbHQ6ICdib3hlcytwb2ludHMnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgXyA9IExpYi5fO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG4vLyBvdXRsaWVyIGRlZmluaXRpb24gYmFzZWQgb24gaHR0cDovL3d3dy5waHlzaWNzLmNzYnNqdS5lZHUvc3RhdHMvYm94Mi5odG1sXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICB2YXIgY2QgPSBbXTtcblxuICAgIC8vIE4uQi4gdmlvbGluIHJldXNlcyBzYW1lIEJveC5jYWxjXG4gICAgdmFyIG51bUtleSA9IHRyYWNlLnR5cGUgPT09ICd2aW9saW4nID8gJ19udW1WaW9saW5zJyA6ICdfbnVtQm94ZXMnO1xuXG4gICAgdmFyIGk7XG4gICAgdmFyIHZhbEF4aXMsIHZhbExldHRlcjtcbiAgICB2YXIgcG9zQXhpcywgcG9zTGV0dGVyO1xuXG4gICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICB2YWxBeGlzID0geGE7XG4gICAgICAgIHZhbExldHRlciA9ICd4JztcbiAgICAgICAgcG9zQXhpcyA9IHlhO1xuICAgICAgICBwb3NMZXR0ZXIgPSAneSc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFsQXhpcyA9IHlhO1xuICAgICAgICB2YWxMZXR0ZXIgPSAneSc7XG4gICAgICAgIHBvc0F4aXMgPSB4YTtcbiAgICAgICAgcG9zTGV0dGVyID0gJ3gnO1xuICAgIH1cblxuICAgIHZhciB2YWwgPSB2YWxBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgdmFsTGV0dGVyKTtcbiAgICB2YXIgcG9zID0gZ2V0UG9zKHRyYWNlLCBwb3NMZXR0ZXIsIHBvc0F4aXMsIHZhbCwgZnVsbExheW91dFtudW1LZXldKTtcblxuICAgIHZhciBkdiA9IExpYi5kaXN0aW5jdFZhbHMocG9zKTtcbiAgICB2YXIgcG9zRGlzdGluY3QgPSBkdi52YWxzO1xuICAgIHZhciBkUG9zID0gZHYubWluRGlmZiAvIDI7XG4gICAgdmFyIHBvc0JpbnMgPSBtYWtlQmlucyhwb3NEaXN0aW5jdCwgZFBvcyk7XG5cbiAgICB2YXIgcExlbiA9IHBvc0Rpc3RpbmN0Lmxlbmd0aDtcbiAgICB2YXIgcHRzUGVyQmluID0gaW5pdE5lc3RlZEFycmF5KHBMZW4pO1xuXG4gICAgLy8gYmluIHB0cyBpbmZvIHBlciBwb3NpdGlvbiBiaW5zXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2UuX2xlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB2ID0gdmFsW2ldO1xuICAgICAgICBpZighaXNOdW1lcmljKHYpKSBjb250aW51ZTtcblxuICAgICAgICB2YXIgbiA9IExpYi5maW5kQmluKHBvc1tpXSwgcG9zQmlucyk7XG4gICAgICAgIGlmKG4gPj0gMCAmJiBuIDwgcExlbikge1xuICAgICAgICAgICAgdmFyIHB0ID0ge3Y6IHYsIGk6IGl9O1xuICAgICAgICAgICAgYXJyYXlzVG9DYWxjZGF0YShwdCwgdHJhY2UsIGkpO1xuICAgICAgICAgICAgcHRzUGVyQmluW25dLnB1c2gocHQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gYnVpbGQgY2FsY2RhdGEgdHJhY2UgaXRlbXMsIG9uZSBpdGVtIHBlciBkaXN0aW5jdCBwb3NpdGlvblxuICAgIGZvcihpID0gMDsgaSA8IHBMZW47IGkrKykge1xuICAgICAgICBpZihwdHNQZXJCaW5baV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdmFyIHB0cyA9IHB0c1BlckJpbltpXS5zb3J0KHNvcnRCeVZhbCk7XG4gICAgICAgICAgICB2YXIgYm94VmFscyA9IHB0cy5tYXAoZXh0cmFjdFZhbCk7XG4gICAgICAgICAgICB2YXIgYnZMZW4gPSBib3hWYWxzLmxlbmd0aDtcblxuICAgICAgICAgICAgdmFyIGNkaSA9IHtcbiAgICAgICAgICAgICAgICBwb3M6IHBvc0Rpc3RpbmN0W2ldLFxuICAgICAgICAgICAgICAgIHB0czogcHRzXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjZGkubWluID0gYm94VmFsc1swXTtcbiAgICAgICAgICAgIGNkaS5tYXggPSBib3hWYWxzW2J2TGVuIC0gMV07XG4gICAgICAgICAgICBjZGkubWVhbiA9IExpYi5tZWFuKGJveFZhbHMsIGJ2TGVuKTtcbiAgICAgICAgICAgIGNkaS5zZCA9IExpYi5zdGRldihib3hWYWxzLCBidkxlbiwgY2RpLm1lYW4pO1xuXG4gICAgICAgICAgICAvLyBmaXJzdCBxdWFydGlsZVxuICAgICAgICAgICAgY2RpLnExID0gTGliLmludGVycChib3hWYWxzLCAwLjI1KTtcbiAgICAgICAgICAgICAvLyBtZWRpYW5cbiAgICAgICAgICAgIGNkaS5tZWQgPSBMaWIuaW50ZXJwKGJveFZhbHMsIDAuNSk7XG4gICAgICAgICAgICAvLyB0aGlyZCBxdWFydGlsZVxuICAgICAgICAgICAgY2RpLnEzID0gTGliLmludGVycChib3hWYWxzLCAwLjc1KTtcblxuICAgICAgICAgICAgLy8gbG93ZXIgYW5kIHVwcGVyIGZlbmNlcyAtIGxhc3QgcG9pbnQgaW5zaWRlXG4gICAgICAgICAgICAvLyAxLjUgaW50ZXJxdWFydGlsZSByYW5nZXMgZnJvbSBxdWFydGlsZXNcbiAgICAgICAgICAgIGNkaS5sZiA9IE1hdGgubWluKFxuICAgICAgICAgICAgICAgIGNkaS5xMSxcbiAgICAgICAgICAgICAgICBib3hWYWxzW01hdGgubWluKFxuICAgICAgICAgICAgICAgICAgICBMaWIuZmluZEJpbigyLjUgKiBjZGkucTEgLSAxLjUgKiBjZGkucTMsIGJveFZhbHMsIHRydWUpICsgMSxcbiAgICAgICAgICAgICAgICAgICAgYnZMZW4gLSAxXG4gICAgICAgICAgICAgICAgKV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjZGkudWYgPSBNYXRoLm1heChcbiAgICAgICAgICAgICAgICBjZGkucTMsXG4gICAgICAgICAgICAgICAgYm94VmFsc1tNYXRoLm1heChcbiAgICAgICAgICAgICAgICAgICAgTGliLmZpbmRCaW4oMi41ICogY2RpLnEzIC0gMS41ICogY2RpLnExLCBib3hWYWxzKSxcbiAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICldXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBsb3dlciBhbmQgdXBwZXIgb3V0bGllcnMgLSAzIElRUiBvdXQgKGRvbid0IGNsaXAgdG8gbWF4L21pbixcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgb25seSBmb3IgZGlzY3JpbWluYXRpbmcgc3VzcGVjdGVkICYgZmFyIG91dGxpZXJzKVxuICAgICAgICAgICAgY2RpLmxvID0gNCAqIGNkaS5xMSAtIDMgKiBjZGkucTM7XG4gICAgICAgICAgICBjZGkudW8gPSA0ICogY2RpLnEzIC0gMyAqIGNkaS5xMTtcblxuXG4gICAgICAgICAgICAvLyBsb3dlciBhbmQgdXBwZXIgbm90Y2hlcyB+OTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGZvciBtZWRpYW5cbiAgICAgICAgICAgIHZhciBpcXIgPSBjZGkucTMgLSBjZGkucTE7XG4gICAgICAgICAgICB2YXIgbWNpID0gMS41NyAqIGlxciAvIE1hdGguc3FydChidkxlbik7XG4gICAgICAgICAgICBjZGkubG4gPSBjZGkubWVkIC0gbWNpO1xuICAgICAgICAgICAgY2RpLnVuID0gY2RpLm1lZCArIG1jaTtcblxuICAgICAgICAgICAgY2QucHVzaChjZGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuICAgIHZhciBleHRyZW1lcyA9IEF4ZXMuZmluZEV4dHJlbWVzKHZhbEF4aXMsIHZhbCwge3BhZGRlZDogdHJ1ZX0pO1xuICAgIHRyYWNlLl9leHRyZW1lc1t2YWxBeGlzLl9pZF0gPSBleHRyZW1lcztcblxuICAgIGlmKGNkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY2RbMF0udCA9IHtcbiAgICAgICAgICAgIG51bTogZnVsbExheW91dFtudW1LZXldLFxuICAgICAgICAgICAgZFBvczogZFBvcyxcbiAgICAgICAgICAgIHBvc0xldHRlcjogcG9zTGV0dGVyLFxuICAgICAgICAgICAgdmFsTGV0dGVyOiB2YWxMZXR0ZXIsXG4gICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICBtZWQ6IF8oZ2QsICdtZWRpYW46JyksXG4gICAgICAgICAgICAgICAgbWluOiBfKGdkLCAnbWluOicpLFxuICAgICAgICAgICAgICAgIHExOiBfKGdkLCAncTE6JyksXG4gICAgICAgICAgICAgICAgcTM6IF8oZ2QsICdxMzonKSxcbiAgICAgICAgICAgICAgICBtYXg6IF8oZ2QsICdtYXg6JyksXG4gICAgICAgICAgICAgICAgbWVhbjogdHJhY2UuYm94bWVhbiA9PT0gJ3NkJyA/IF8oZ2QsICdtZWFuIMKxIM+DOicpIDogXyhnZCwgJ21lYW46JyksXG4gICAgICAgICAgICAgICAgbGY6IF8oZ2QsICdsb3dlciBmZW5jZTonKSxcbiAgICAgICAgICAgICAgICB1ZjogXyhnZCwgJ3VwcGVyIGZlbmNlOicpXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgZnVsbExheW91dFtudW1LZXldKys7XG4gICAgICAgIHJldHVybiBjZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW3t0OiB7ZW1wdHk6IHRydWV9fV07XG4gICAgfVxufTtcblxuLy8gSW4gdmVydGljYWwgKGhvcml6b250YWwpIGJveCBwbG90czpcbi8vIGlmIG5vIHggKHkpIGRhdGEsIHVzZSB4MCAoeTApLCBvciBuYW1lXG4vLyBzbyBpZiB5b3Ugd2FudCBvbmUgYm94XG4vLyBwZXIgdHJhY2UsIHNldCB4MCAoeTApIHRvIHRoZSB4ICh5KSB2YWx1ZSBvciBjYXRlZ29yeSBmb3IgdGhpcyB0cmFjZVxuLy8gKG9yIHNldCB4ICh5KSB0byBhIGNvbnN0YW50IGFycmF5IG1hdGNoaW5nIHkgKHgpKVxuZnVuY3Rpb24gZ2V0UG9zKHRyYWNlLCBwb3NMZXR0ZXIsIHBvc0F4aXMsIHZhbCwgbnVtKSB7XG4gICAgaWYocG9zTGV0dGVyIGluIHRyYWNlKSB7XG4gICAgICAgIHJldHVybiBwb3NBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgcG9zTGV0dGVyKTtcbiAgICB9XG5cbiAgICB2YXIgcG9zMDtcblxuICAgIGlmKHBvc0xldHRlciArICcwJyBpbiB0cmFjZSkge1xuICAgICAgICBwb3MwID0gdHJhY2VbcG9zTGV0dGVyICsgJzAnXTtcbiAgICB9IGVsc2UgaWYoJ25hbWUnIGluIHRyYWNlICYmIChcbiAgICAgICAgcG9zQXhpcy50eXBlID09PSAnY2F0ZWdvcnknIHx8IChcbiAgICAgICAgICAgIGlzTnVtZXJpYyh0cmFjZS5uYW1lKSAmJlxuICAgICAgICAgICAgWydsaW5lYXInLCAnbG9nJ10uaW5kZXhPZihwb3NBeGlzLnR5cGUpICE9PSAtMVxuICAgICAgICApIHx8IChcbiAgICAgICAgICAgIExpYi5pc0RhdGVUaW1lKHRyYWNlLm5hbWUpICYmXG4gICAgICAgICAgICBwb3NBeGlzLnR5cGUgPT09ICdkYXRlJ1xuICAgICAgICApXG4gICAgKSkge1xuICAgICAgICBwb3MwID0gdHJhY2UubmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwb3MwID0gbnVtO1xuICAgIH1cblxuICAgIHZhciBwb3MwYyA9IHBvc0F4aXMuZDJjKHBvczAsIDAsIHRyYWNlW3Bvc0xldHRlciArICdjYWxlbmRhciddKTtcbiAgICByZXR1cm4gdmFsLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHBvczBjOyB9KTtcbn1cblxuZnVuY3Rpb24gbWFrZUJpbnMoeCwgZHgpIHtcbiAgICB2YXIgbGVuID0geC5sZW5ndGg7XG4gICAgdmFyIGJpbnMgPSBuZXcgQXJyYXkobGVuICsgMSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgYmluc1tpXSA9IHhbaV0gLSBkeDtcbiAgICB9XG4gICAgYmluc1tsZW5dID0geFtsZW4gLSAxXSArIGR4O1xuXG4gICAgcmV0dXJuIGJpbnM7XG59XG5cbmZ1bmN0aW9uIGluaXROZXN0ZWRBcnJheShsZW4pIHtcbiAgICB2YXIgYXJyID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGFycltpXSA9IFtdO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufVxuXG5mdW5jdGlvbiBhcnJheXNUb0NhbGNkYXRhKHB0LCB0cmFjZSwgaSkge1xuICAgIHZhciB0cmFjZTJjYWxjID0ge1xuICAgICAgICB0ZXh0OiAndHgnXG4gICAgfTtcblxuICAgIGZvcih2YXIgayBpbiB0cmFjZTJjYWxjKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2Vba10pKSB7XG4gICAgICAgICAgICBwdFt0cmFjZTJjYWxjW2tdXSA9IHRyYWNlW2tdW2ldO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjYWxjU2VsZWN0aW9uKGNkLCB0cmFjZSkge1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlLnNlbGVjdGVkcG9pbnRzKSkge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwdHMgPSBjZFtpXS5wdHMgfHwgW107XG4gICAgICAgICAgICB2YXIgcHROdW1iZXIyY2RJbmRleCA9IHt9O1xuXG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgcHRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcHROdW1iZXIyY2RJbmRleFtwdHNbal0uaV0gPSBqO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIudGFnU2VsZWN0ZWQocHRzLCB0cmFjZSwgcHROdW1iZXIyY2RJbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNvcnRCeVZhbChhLCBiKSB7IHJldHVybiBhLnYgLSBiLnY7IH1cblxuZnVuY3Rpb24gZXh0cmFjdFZhbChvKSB7IHJldHVybiBvLnY7IH1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgb3JpZW50YXRpb25zID0gWyd2JywgJ2gnXTtcblxuZnVuY3Rpb24gY3Jvc3NUcmFjZUNhbGMoZ2QsIHBsb3RpbmZvKSB7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb3JpZW50YXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcmllbnRhdGlvbiA9IG9yaWVudGF0aW9uc1tpXTtcbiAgICAgICAgdmFyIHBvc0F4aXMgPSBvcmllbnRhdGlvbiA9PT0gJ2gnID8geWEgOiB4YTtcbiAgICAgICAgdmFyIGJveExpc3QgPSBbXTtcbiAgICAgICAgdmFyIG1pblBhZCA9IDA7XG4gICAgICAgIHZhciBtYXhQYWQgPSAwO1xuXG4gICAgICAgIC8vIG1ha2UgbGlzdCBvZiBib3hlcyAvIGNhbmRsZXN0aWNrc1xuICAgICAgICAvLyBGb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSwgY2FuZGxlc3RpY2tzIGFyZSB0cmVhdGVkIGFzIGlmIHRoZXkgKmFyZSogYm94IHRyYWNlcyBoZXJlXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjYWxjZGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbal07XG4gICAgICAgICAgICB2YXIgdCA9IGNkWzBdLnQ7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgICAgICAgICAodHJhY2UudHlwZSA9PT0gJ2JveCcgfHwgdHJhY2UudHlwZSA9PT0gJ2NhbmRsZXN0aWNrJykgJiZcbiAgICAgICAgICAgICAgICAgICAgIXQuZW1wdHkgJiZcbiAgICAgICAgICAgICAgICAgICAgKHRyYWNlLm9yaWVudGF0aW9uIHx8ICd2JykgPT09IG9yaWVudGF0aW9uICYmXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLnhheGlzID09PSB4YS5faWQgJiZcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UueWF4aXMgPT09IHlhLl9pZFxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBib3hMaXN0LnB1c2goaik7XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS5ib3hwb2ludHMpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluUGFkID0gTWF0aC5tYXgobWluUGFkLCB0cmFjZS5qaXR0ZXIgLSB0cmFjZS5wb2ludHBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICBtYXhQYWQgPSBNYXRoLm1heChtYXhQYWQsIHRyYWNlLmppdHRlciArIHRyYWNlLnBvaW50cG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0UG9zaXRpb25PZmZzZXQoJ2JveCcsIGdkLCBib3hMaXN0LCBwb3NBeGlzLCBbbWluUGFkLCBtYXhQYWRdKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFBvc2l0aW9uT2Zmc2V0KHRyYWNlVHlwZSwgZ2QsIGJveExpc3QsIHBvc0F4aXMsIHBhZCkge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHBvaW50TGlzdCA9IFtdO1xuXG4gICAgLy8gTi5CLiByZXVzZWQgaW4gdmlvbGluXG4gICAgdmFyIG51bUtleSA9IHRyYWNlVHlwZSA9PT0gJ3Zpb2xpbicgPyAnX251bVZpb2xpbnMnIDogJ19udW1Cb3hlcyc7XG5cbiAgICB2YXIgaSwgaiwgY2FsY1RyYWNlO1xuXG4gICAgLy8gbWFrZSBsaXN0IG9mIGJveCBwb2ludHNcbiAgICBmb3IoaSA9IDA7IGkgPCBib3hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGNUcmFjZSA9IGNhbGNkYXRhW2JveExpc3RbaV1dO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHBvaW50TGlzdC5wdXNoKGNhbGNUcmFjZVtqXS5wb3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIXBvaW50TGlzdC5sZW5ndGgpIHJldHVybjtcblxuICAgIC8vIGJveCBwbG90cyAtIHVwZGF0ZSBkUG9zIGJhc2VkIG9uIG11bHRpcGxlIHRyYWNlc1xuICAgIC8vIGFuZCB0aGVuIHVzZSBmb3IgcG9zQXhpcyBhdXRvcmFuZ2VcbiAgICB2YXIgYm94ZHYgPSBMaWIuZGlzdGluY3RWYWxzKHBvaW50TGlzdCk7XG4gICAgdmFyIGRQb3MgPSBib3hkdi5taW5EaWZmIC8gMjtcblxuICAgIC8vIGlmIHRoZXJlJ3Mgbm8gZHVwbGljYXRpb24gb2YgeCBwb2ludHMsXG4gICAgLy8gZGlzYWJsZSAnZ3JvdXAnIG1vZGUgYnkgc2V0dGluZyBjb3VudGVyIHRvIDFcbiAgICBpZihwb2ludExpc3QubGVuZ3RoID09PSBib3hkdi52YWxzLmxlbmd0aCkge1xuICAgICAgICBmdWxsTGF5b3V0W251bUtleV0gPSAxO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGZvciBmb3JjZWQgbWluaW11bSBkdGlja1xuICAgIEF4ZXMubWluRHRpY2socG9zQXhpcywgYm94ZHYubWluRGlmZiwgYm94ZHYudmFsc1swXSwgdHJ1ZSk7XG5cbiAgICB2YXIgZ2FwID0gZnVsbExheW91dFt0cmFjZVR5cGUgKyAnZ2FwJ107XG4gICAgdmFyIGdyb3VwZ2FwID0gZnVsbExheW91dFt0cmFjZVR5cGUgKyAnZ3JvdXBnYXAnXTtcbiAgICB2YXIgcGFkZmFjdG9yID0gKDEgLSBnYXApICogKDEgLSBncm91cGdhcCkgKiBkUG9zIC8gZnVsbExheW91dFtudW1LZXldO1xuXG4gICAgLy8gYXV0b3NjYWxlIHRoZSB4IGF4aXMgLSBpbmNsdWRpbmcgc3BhY2UgZm9yIHBvaW50cyBpZiB0aGV5J3JlIG9mZiB0aGUgc2lkZVxuICAgIC8vIFRPRE86IHRoaXMgd2lsbCBvdmVyZG8gaXQgaWYgdGhlIG91dGVybW9zdCBib3hlcyBkb24ndCBoYXZlXG4gICAgLy8gdGhlaXIgcG9pbnRzIGFzIGZhciBvdXQgYXMgdGhlIG90aGVyIGJveGVzXG4gICAgdmFyIGV4dHJlbWVzID0gQXhlcy5maW5kRXh0cmVtZXMocG9zQXhpcywgYm94ZHYudmFscywge1xuICAgICAgICB2cGFkbWludXM6IGRQb3MgKyBwYWRbMF0gKiBwYWRmYWN0b3IsXG4gICAgICAgIHZwYWRwbHVzOiBkUG9zICsgcGFkWzFdICogcGFkZmFjdG9yXG4gICAgfSk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBib3hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGNUcmFjZSA9IGNhbGNkYXRhW2JveExpc3RbaV1dO1xuICAgICAgICAvLyBzZXQgdGhlIHdpZHRoIG9mIGFsbCBib3hlc1xuICAgICAgICBjYWxjVHJhY2VbMF0udC5kUG9zID0gZFBvcztcbiAgICAgICAgLy8gbGluayBleHRyZW1lcyB0byBhbGwgYm94ZXNcbiAgICAgICAgY2FsY1RyYWNlWzBdLnRyYWNlLl9leHRyZW1lc1twb3NBeGlzLl9pZF0gPSBleHRyZW1lcztcbiAgICB9XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY3Jvc3NUcmFjZUNhbGM6IGNyb3NzVHJhY2VDYWxjLFxuICAgIHNldFBvc2l0aW9uT2Zmc2V0OiBzZXRQb3NpdGlvbk9mZnNldFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZVNhbXBsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYodHJhY2VPdXQudmlzaWJsZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIGNvZXJjZSgnbGluZS5jb2xvcicsICh0cmFjZUluLm1hcmtlciB8fCB7fSkuY29sb3IgfHwgZGVmYXVsdENvbG9yKTtcbiAgICBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcbiAgICBjb2VyY2UoJ2ZpbGxjb2xvcicsIENvbG9yLmFkZE9wYWNpdHkodHJhY2VPdXQubGluZS5jb2xvciwgMC41KSk7XG5cbiAgICBjb2VyY2UoJ3doaXNrZXJ3aWR0aCcpO1xuICAgIGNvZXJjZSgnYm94bWVhbicpO1xuXG4gICAgdmFyIG5vdGNoZWQgPSBjb2VyY2UoJ25vdGNoZWQnLCB0cmFjZUluLm5vdGNod2lkdGggIT09IHVuZGVmaW5lZCk7XG4gICAgaWYobm90Y2hlZCkgY29lcmNlKCdub3RjaHdpZHRoJyk7XG5cbiAgICBoYW5kbGVQb2ludHNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCB7cHJlZml4OiAnYm94J30pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTYW1wbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpIHtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIGhhc1ggPSB4ICYmIHgubGVuZ3RoO1xuXG4gICAgdmFyIGRlZmF1bHRPcmllbnRhdGlvbiwgbGVuO1xuXG4gICAgaWYoeSAmJiB5Lmxlbmd0aCkge1xuICAgICAgICBkZWZhdWx0T3JpZW50YXRpb24gPSAndic7XG4gICAgICAgIGlmKGhhc1gpIHtcbiAgICAgICAgICAgIGxlbiA9IE1hdGgubWluKHgubGVuZ3RoLCB5Lmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb2VyY2UoJ3gwJyk7XG4gICAgICAgICAgICBsZW4gPSB5Lmxlbmd0aDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihoYXNYKSB7XG4gICAgICAgIGRlZmF1bHRPcmllbnRhdGlvbiA9ICdoJztcbiAgICAgICAgY29lcmNlKCd5MCcpO1xuICAgICAgICBsZW4gPSB4Lmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5J10sIGxheW91dCk7XG5cbiAgICBjb2VyY2UoJ29yaWVudGF0aW9uJywgZGVmYXVsdE9yaWVudGF0aW9uKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUG9pbnRzRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIHZhciBwcmVmaXggPSBvcHRzLnByZWZpeDtcblxuICAgIHZhciBvdXRsaWVyQ29sb3JEZmx0ID0gTGliLmNvZXJjZTIodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsICdtYXJrZXIub3V0bGllcmNvbG9yJyk7XG4gICAgdmFyIGxpbmVvdXRsaWVyY29sb3IgPSBjb2VyY2UoJ21hcmtlci5saW5lLm91dGxpZXJjb2xvcicpO1xuXG4gICAgdmFyIHBvaW50cyA9IGNvZXJjZShcbiAgICAgICAgcHJlZml4ICsgJ3BvaW50cycsXG4gICAgICAgIChvdXRsaWVyQ29sb3JEZmx0IHx8IGxpbmVvdXRsaWVyY29sb3IpID8gJ3N1c3BlY3RlZG91dGxpZXJzJyA6IHVuZGVmaW5lZFxuICAgICk7XG5cbiAgICBpZihwb2ludHMpIHtcbiAgICAgICAgY29lcmNlKCdqaXR0ZXInLCBwb2ludHMgPT09ICdhbGwnID8gMC4zIDogMCk7XG4gICAgICAgIGNvZXJjZSgncG9pbnRwb3MnLCBwb2ludHMgPT09ICdhbGwnID8gLTEuNSA6IDApO1xuXG4gICAgICAgIGNvZXJjZSgnbWFya2VyLnN5bWJvbCcpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5vcGFjaXR5Jyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLnNpemUnKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIuY29sb3InLCB0cmFjZU91dC5saW5lLmNvbG9yKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIubGluZS5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG5cbiAgICAgICAgaWYocG9pbnRzID09PSAnc3VzcGVjdGVkb3V0bGllcnMnKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLm91dGxpZXJjb2xvcicsIHRyYWNlT3V0Lm1hcmtlci5jb2xvcik7XG4gICAgICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLm91dGxpZXJ3aWR0aCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29lcmNlKCdzZWxlY3RlZC5tYXJrZXIuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCd1bnNlbGVjdGVkLm1hcmtlci5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkLm1hcmtlci5zaXplJyk7XG4gICAgICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIuc2l6ZScpO1xuXG4gICAgICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSB0cmFjZU91dC5tYXJrZXI7XG4gICAgfVxuXG4gICAgY29lcmNlKCdob3Zlcm9uJyk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5RGVmYXVsdHM6IHN1cHBseURlZmF1bHRzLFxuICAgIGhhbmRsZVNhbXBsZURlZmF1bHRzOiBoYW5kbGVTYW1wbGVEZWZhdWx0cyxcbiAgICBoYW5kbGVQb2ludHNEZWZhdWx0czogaGFuZGxlUG9pbnRzRGVmYXVsdHNcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXZlbnREYXRhKG91dCwgcHQpIHtcblxuICAgIC8vIE5vdGU6IGhvdmVyT25Cb3ggcHJvcGVydHkgaXMgbmVlZGVkIGZvciBjbGljay10by1zZWxlY3RcbiAgICAvLyB0byBpZ25vcmUgd2hlbiBhIGJveCB3YXMgY2xpY2tlZC4gVGhpcyBpcyB0aGUgcmVhc29uIGJveFxuICAgIC8vIGltcGxlbWVudHMgdGhpcyBjdXN0b20gZXZlbnREYXRhIGZ1bmN0aW9uLlxuICAgIGlmKHB0LmhvdmVyT25Cb3gpIG91dC5ob3Zlck9uQm94ID0gcHQuaG92ZXJPbkJveDtcblxuICAgIGlmKCd4VmFsJyBpbiBwdCkgb3V0LnggPSBwdC54VmFsO1xuICAgIGlmKCd5VmFsJyBpbiBwdCkgb3V0LnkgPSBwdC55VmFsO1xuICAgIGlmKHB0LnhhKSBvdXQueGF4aXMgPSBwdC54YTtcbiAgICBpZihwdC55YSkgb3V0LnlheGlzID0gcHQueWE7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGZpbGxIb3ZlclRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dCcpO1xuXG5mdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgaG92ZXJvbiA9IHRyYWNlLmhvdmVyb247XG4gICAgdmFyIGNsb3NlQm94RGF0YSA9IFtdO1xuICAgIHZhciBjbG9zZVB0RGF0YTtcblxuICAgIGlmKGhvdmVyb24uaW5kZXhPZignYm94ZXMnKSAhPT0gLTEpIHtcbiAgICAgICAgY2xvc2VCb3hEYXRhID0gY2xvc2VCb3hEYXRhLmNvbmNhdChob3Zlck9uQm94ZXMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpKTtcbiAgICB9XG5cbiAgICBpZihob3Zlcm9uLmluZGV4T2YoJ3BvaW50cycpICE9PSAtMSkge1xuICAgICAgICBjbG9zZVB0RGF0YSA9IGhvdmVyT25Qb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsKTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGVyZSdzIGEgcG9pbnQgaW4gcmFuZ2UgYW5kIGhvdmVyb24gaGFzIHBvaW50cywgc2hvdyB0aGUgYmVzdCBzaW5nbGUgcG9pbnQgb25seS5cbiAgICAvLyBJZiBob3Zlcm9uIGhhcyBib3hlcyBhbmQgdGhlcmUncyBubyBwb2ludCBpbiByYW5nZSAob3IgaG92ZXJvbiBkb2Vzbid0IGhhdmUgcG9pbnRzKSwgc2hvdyB0aGUgYm94IHN0YXRzLlxuICAgIGlmKGhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnKSB7XG4gICAgICAgIGlmKGNsb3NlUHREYXRhKSByZXR1cm4gW2Nsb3NlUHREYXRhXTtcbiAgICAgICAgcmV0dXJuIGNsb3NlQm94RGF0YTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UgaW4gY29tcGFyZSBtb2RlLCBhbGxvdyBhIHBvaW50IEFORCB0aGUgYm94IHN0YXRzIHRvIGJlIGxhYmVsZWRcbiAgICAvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgYm94ZXMgaW4gcmFuZ2UgKGllIGJveG1vZGUgPSAnb3ZlcmxheScpIHdlJ2xsIHNlZSBzdGF0cyBmb3IgYWxsIG9mIHRoZW0uXG4gICAgaWYoY2xvc2VQdERhdGEpIHtcbiAgICAgICAgY2xvc2VCb3hEYXRhLnB1c2goY2xvc2VQdERhdGEpO1xuICAgICAgICByZXR1cm4gY2xvc2VCb3hEYXRhO1xuICAgIH1cbiAgICByZXR1cm4gY2xvc2VCb3hEYXRhO1xufVxuXG5mdW5jdGlvbiBob3Zlck9uQm94ZXMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgdCA9IGNkWzBdLnQ7XG4gICAgdmFyIGlzVmlvbGluID0gdHJhY2UudHlwZSA9PT0gJ3Zpb2xpbic7XG4gICAgdmFyIGNsb3NlQm94RGF0YSA9IFtdO1xuXG4gICAgdmFyIHBMZXR0ZXIsIHZMZXR0ZXIsIHBBeGlzLCB2QXhpcywgdlZhbCwgcFZhbCwgZHgsIGR5LCBkUG9zLFxuICAgICAgICBob3ZlclBzZXVkb0Rpc3RhbmNlLCBzcGlrZVBzZXVkb0Rpc3RhbmNlO1xuXG4gICAgdmFyIGJveERlbHRhID0gdC5iZFBvcztcbiAgICB2YXIgcG9zQWNjZXB0YW5jZSA9IHQud0hvdmVyO1xuICAgIHZhciBzaGlmdFBvcyA9IGZ1bmN0aW9uKGRpKSB7IHJldHVybiBkaS5wb3MgKyB0LmJQb3MgLSBwVmFsOyB9O1xuXG4gICAgaWYoaXNWaW9saW4gJiYgdHJhY2Uuc2lkZSAhPT0gJ2JvdGgnKSB7XG4gICAgICAgIGlmKHRyYWNlLnNpZGUgPT09ICdwb3NpdGl2ZScpIHtcbiAgICAgICAgICAgIGRQb3MgPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgICAgIHZhciBwb3MgPSBzaGlmdFBvcyhkaSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZ4LmluYm94KHBvcywgcG9zICsgcG9zQWNjZXB0YW5jZSwgaG92ZXJQc2V1ZG9EaXN0YW5jZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmKHRyYWNlLnNpZGUgPT09ICduZWdhdGl2ZScpIHtcbiAgICAgICAgICAgIGRQb3MgPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgICAgIHZhciBwb3MgPSBzaGlmdFBvcyhkaSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZ4LmluYm94KHBvcyAtIHBvc0FjY2VwdGFuY2UsIHBvcywgaG92ZXJQc2V1ZG9EaXN0YW5jZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZFBvcyA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICB2YXIgcG9zID0gc2hpZnRQb3MoZGkpO1xuICAgICAgICAgICAgcmV0dXJuIEZ4LmluYm94KHBvcyAtIHBvc0FjY2VwdGFuY2UsIHBvcyArIHBvc0FjY2VwdGFuY2UsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBkVmFsO1xuXG4gICAgaWYoaXNWaW9saW4pIHtcbiAgICAgICAgZFZhbCA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICByZXR1cm4gRnguaW5ib3goZGkuc3BhblswXSAtIHZWYWwsIGRpLnNwYW5bMV0gLSB2VmFsLCBob3ZlclBzZXVkb0Rpc3RhbmNlKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkVmFsID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHJldHVybiBGeC5pbmJveChkaS5taW4gLSB2VmFsLCBkaS5tYXggLSB2VmFsLCBob3ZlclBzZXVkb0Rpc3RhbmNlKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgIHZWYWwgPSB4dmFsO1xuICAgICAgICBwVmFsID0geXZhbDtcbiAgICAgICAgZHggPSBkVmFsO1xuICAgICAgICBkeSA9IGRQb3M7XG4gICAgICAgIHBMZXR0ZXIgPSAneSc7XG4gICAgICAgIHBBeGlzID0geWE7XG4gICAgICAgIHZMZXR0ZXIgPSAneCc7XG4gICAgICAgIHZBeGlzID0geGE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdlZhbCA9IHl2YWw7XG4gICAgICAgIHBWYWwgPSB4dmFsO1xuICAgICAgICBkeCA9IGRQb3M7XG4gICAgICAgIGR5ID0gZFZhbDtcbiAgICAgICAgcExldHRlciA9ICd4JztcbiAgICAgICAgcEF4aXMgPSB4YTtcbiAgICAgICAgdkxldHRlciA9ICd5JztcbiAgICAgICAgdkF4aXMgPSB5YTtcbiAgICB9XG5cbiAgICAvLyBpZiB0d28gYm94ZXMgYXJlIG92ZXJsYXlpbmcsIGxldCB0aGUgbmFycm93ZXN0IG9uZSB3aW5cbiAgICB2YXIgcHNldWRvRGlzdGFuY2UgPSBNYXRoLm1pbigxLCBib3hEZWx0YSAvIE1hdGguYWJzKHBBeGlzLnIyYyhwQXhpcy5yYW5nZVsxXSkgLSBwQXhpcy5yMmMocEF4aXMucmFuZ2VbMF0pKSk7XG4gICAgaG92ZXJQc2V1ZG9EaXN0YW5jZSA9IHBvaW50RGF0YS5tYXhIb3ZlckRpc3RhbmNlIC0gcHNldWRvRGlzdGFuY2U7XG4gICAgc3Bpa2VQc2V1ZG9EaXN0YW5jZSA9IHBvaW50RGF0YS5tYXhTcGlrZURpc3RhbmNlIC0gcHNldWRvRGlzdGFuY2U7XG5cbiAgICBmdW5jdGlvbiBkeHkoZGkpIHsgcmV0dXJuIChkeChkaSkgKyBkeShkaSkpIC8gMjsgfVxuICAgIHZhciBkaXN0Zm4gPSBGeC5nZXREaXN0YW5jZUZ1bmN0aW9uKGhvdmVybW9kZSwgZHgsIGR5LCBkeHkpO1xuICAgIEZ4LmdldENsb3Nlc3QoY2QsIGRpc3RmbiwgcG9pbnREYXRhKTtcblxuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgLy8gYW5kIGNyZWF0ZSB0aGUgaXRlbShzKSBpbiBjbG9zZWRhdGEgZm9yIHRoaXMgcG9pbnRcbiAgICBpZihwb2ludERhdGEuaW5kZXggPT09IGZhbHNlKSByZXR1cm4gW107XG5cbiAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciBsYyA9IHRyYWNlLmxpbmUuY29sb3I7XG4gICAgdmFyIG1jID0gKHRyYWNlLm1hcmtlciB8fCB7fSkuY29sb3I7XG5cbiAgICBpZihDb2xvci5vcGFjaXR5KGxjKSAmJiB0cmFjZS5saW5lLndpZHRoKSBwb2ludERhdGEuY29sb3IgPSBsYztcbiAgICBlbHNlIGlmKENvbG9yLm9wYWNpdHkobWMpICYmIHRyYWNlLmJveHBvaW50cykgcG9pbnREYXRhLmNvbG9yID0gbWM7XG4gICAgZWxzZSBwb2ludERhdGEuY29sb3IgPSB0cmFjZS5maWxsY29sb3I7XG5cbiAgICBwb2ludERhdGFbcExldHRlciArICcwJ10gPSBwQXhpcy5jMnAoZGkucG9zICsgdC5iUG9zIC0gYm94RGVsdGEsIHRydWUpO1xuICAgIHBvaW50RGF0YVtwTGV0dGVyICsgJzEnXSA9IHBBeGlzLmMycChkaS5wb3MgKyB0LmJQb3MgKyBib3hEZWx0YSwgdHJ1ZSk7XG5cbiAgICBwb2ludERhdGFbcExldHRlciArICdMYWJlbFZhbCddID0gZGkucG9zO1xuXG4gICAgdmFyIHNwaWtlUG9zQXR0ciA9IHBMZXR0ZXIgKyAnU3Bpa2UnO1xuICAgIHBvaW50RGF0YS5zcGlrZURpc3RhbmNlID0gZHh5KGRpKSAqIHNwaWtlUHNldWRvRGlzdGFuY2UgLyBob3ZlclBzZXVkb0Rpc3RhbmNlO1xuICAgIHBvaW50RGF0YVtzcGlrZVBvc0F0dHJdID0gcEF4aXMuYzJwKGRpLnBvcywgdHJ1ZSk7XG5cbiAgICAvLyBib3ggcGxvdHM6IGVhY2ggXCJwb2ludFwiIGdldHMgbWFueSBsYWJlbHNcbiAgICB2YXIgdXNlZFZhbHMgPSB7fTtcbiAgICB2YXIgYXR0cnMgPSBbJ21lZCcsICdtaW4nLCAncTEnLCAncTMnLCAnbWF4J107XG5cbiAgICBpZih0cmFjZS5ib3htZWFuIHx8ICh0cmFjZS5tZWFubGluZSB8fCB7fSkudmlzaWJsZSkge1xuICAgICAgICBhdHRycy5wdXNoKCdtZWFuJyk7XG4gICAgfVxuICAgIGlmKHRyYWNlLmJveHBvaW50cyB8fCB0cmFjZS5wb2ludHMpIHtcbiAgICAgICAgYXR0cnMucHVzaCgnbGYnLCAndWYnKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1tpXTtcblxuICAgICAgICBpZighKGF0dHIgaW4gZGkpIHx8IChkaVthdHRyXSBpbiB1c2VkVmFscykpIGNvbnRpbnVlO1xuICAgICAgICB1c2VkVmFsc1tkaVthdHRyXV0gPSB0cnVlO1xuXG4gICAgICAgIC8vIGNvcHkgb3V0IHRvIGEgbmV3IG9iamVjdCBmb3IgZWFjaCB2YWx1ZSB0byBsYWJlbFxuICAgICAgICB2YXIgdmFsID0gZGlbYXR0cl07XG4gICAgICAgIHZhciB2YWxQeCA9IHZBeGlzLmMycCh2YWwsIHRydWUpO1xuICAgICAgICB2YXIgcG9pbnREYXRhMiA9IExpYi5leHRlbmRGbGF0KHt9LCBwb2ludERhdGEpO1xuXG4gICAgICAgIHBvaW50RGF0YTJbdkxldHRlciArICcwJ10gPSBwb2ludERhdGEyW3ZMZXR0ZXIgKyAnMSddID0gdmFsUHg7XG4gICAgICAgIHBvaW50RGF0YTJbdkxldHRlciArICdMYWJlbFZhbCddID0gdmFsO1xuICAgICAgICBwb2ludERhdGEyW3ZMZXR0ZXIgKyAnTGFiZWwnXSA9ICh0LmxhYmVscyA/IHQubGFiZWxzW2F0dHJdICsgJyAnIDogJycpICsgQXhlcy5ob3ZlckxhYmVsVGV4dCh2QXhpcywgdmFsKTtcblxuICAgICAgICAvLyBOb3RlOiBpbnRyb2R1Y2VkIHRvIGJlIGFibGUgdG8gZGlzdGluZ3Vpc2ggYVxuICAgICAgICAvLyBjbGlja2VkIHBvaW50IGZyb20gYSBib3ggZHVyaW5nIGNsaWNrLXRvLXNlbGVjdFxuICAgICAgICBwb2ludERhdGEyLmhvdmVyT25Cb3ggPSB0cnVlO1xuXG4gICAgICAgIGlmKGF0dHIgPT09ICdtZWFuJyAmJiAoJ3NkJyBpbiBkaSkgJiYgdHJhY2UuYm94bWVhbiA9PT0gJ3NkJykge1xuICAgICAgICAgICAgcG9pbnREYXRhMlt2TGV0dGVyICsgJ2VyciddID0gZGkuc2Q7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb25seSBrZWVwIG5hbWUgYW5kIHNwaWtlcyBvbiB0aGUgZmlyc3QgaXRlbSAobWVkaWFuKVxuICAgICAgICBwb2ludERhdGEubmFtZSA9ICcnO1xuICAgICAgICBwb2ludERhdGEuc3Bpa2VEaXN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgcG9pbnREYXRhW3NwaWtlUG9zQXR0cl0gPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgY2xvc2VCb3hEYXRhLnB1c2gocG9pbnREYXRhMik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsb3NlQm94RGF0YTtcbn1cblxuZnVuY3Rpb24gaG92ZXJPblBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgeFB4ID0geGEuYzJwKHh2YWwpO1xuICAgIHZhciB5UHggPSB5YS5jMnAoeXZhbCk7XG4gICAgdmFyIGNsb3NlUHREYXRhO1xuXG4gICAgdmFyIGR4ID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgdmFyIHJhZCA9IE1hdGgubWF4KDMsIGRpLm1yYyB8fCAwKTtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KE1hdGguYWJzKHhhLmMycChkaS54KSAtIHhQeCkgLSByYWQsIDEgLSAzIC8gcmFkKTtcbiAgICB9O1xuICAgIHZhciBkeSA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgIHZhciByYWQgPSBNYXRoLm1heCgzLCBkaS5tcmMgfHwgMCk7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLmFicyh5YS5jMnAoZGkueSkgLSB5UHgpIC0gcmFkLCAxIC0gMyAvIHJhZCk7XG4gICAgfTtcbiAgICB2YXIgZGlzdGZuID0gRngucXVhZHJhdHVyZShkeCwgZHkpO1xuXG4gICAgLy8gc2hvdyBvbmUgcG9pbnQgcGVyIHRyYWNlXG4gICAgdmFyIGlqQ2xvc2VzdCA9IGZhbHNlO1xuICAgIHZhciBkaSwgcHQ7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGkgPSBjZFtpXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgKGRpLnB0cyB8fCBbXSkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHB0ID0gZGkucHRzW2pdO1xuXG4gICAgICAgICAgICB2YXIgbmV3RGlzdGFuY2UgPSBkaXN0Zm4ocHQpO1xuICAgICAgICAgICAgaWYobmV3RGlzdGFuY2UgPD0gcG9pbnREYXRhLmRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLmRpc3RhbmNlID0gbmV3RGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgaWpDbG9zZXN0ID0gW2ksIGpdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIWlqQ2xvc2VzdCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZGkgPSBjZFtpakNsb3Nlc3RbMF1dO1xuICAgIHB0ID0gZGkucHRzW2lqQ2xvc2VzdFsxXV07XG5cbiAgICB2YXIgeGMgPSB4YS5jMnAocHQueCwgdHJ1ZSk7XG4gICAgdmFyIHljID0geWEuYzJwKHB0LnksIHRydWUpO1xuICAgIHZhciByYWQgPSBwdC5tcmMgfHwgMTtcblxuICAgIGNsb3NlUHREYXRhID0gTGliLmV4dGVuZEZsYXQoe30sIHBvaW50RGF0YSwge1xuICAgICAgICAvLyBjb3JyZXNwb25kcyB0byBpbmRleCBpbiB4L3kgaW5wdXQgZGF0YSBhcnJheVxuICAgICAgICBpbmRleDogcHQuaSxcbiAgICAgICAgY29sb3I6ICh0cmFjZS5tYXJrZXIgfHwge30pLmNvbG9yLFxuICAgICAgICBuYW1lOiB0cmFjZS5uYW1lLFxuICAgICAgICB4MDogeGMgLSByYWQsXG4gICAgICAgIHgxOiB4YyArIHJhZCxcbiAgICAgICAgeExhYmVsVmFsOiBwdC54LFxuICAgICAgICB5MDogeWMgLSByYWQsXG4gICAgICAgIHkxOiB5YyArIHJhZCxcbiAgICAgICAgeUxhYmVsVmFsOiBwdC55LFxuICAgICAgICBzcGlrZURpc3RhbmNlOiBwb2ludERhdGEuZGlzdGFuY2VcbiAgICB9KTtcbiAgICB2YXIgcExldHRlciA9IHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcgPyAneScgOiAneCc7XG4gICAgdmFyIHBhID0gdHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyA/IHlhIDogeGE7XG4gICAgY2xvc2VQdERhdGFbcExldHRlciArICdTcGlrZSddID0gcGEuYzJwKGRpLnBvcywgdHJ1ZSk7XG4gICAgZmlsbEhvdmVyVGV4dChwdCwgdHJhY2UsIGNsb3NlUHREYXRhKTtcblxuICAgIHJldHVybiBjbG9zZVB0RGF0YTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIGhvdmVyT25Cb3hlczogaG92ZXJPbkJveGVzLFxuICAgIGhvdmVyT25Qb2ludHM6IGhvdmVyT25Qb2ludHNcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBCb3ggPSB7fTtcblxuQm94LmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbkJveC5sYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuQm94LnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpLnN1cHBseURlZmF1bHRzO1xuQm94LnN1cHBseUxheW91dERlZmF1bHRzID0gcmVxdWlyZSgnLi9sYXlvdXRfZGVmYXVsdHMnKS5zdXBwbHlMYXlvdXREZWZhdWx0cztcbkJveC5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5Cb3guY3Jvc3NUcmFjZUNhbGMgPSByZXF1aXJlKCcuL2Nyb3NzX3RyYWNlX2NhbGMnKS5jcm9zc1RyYWNlQ2FsYztcbkJveC5wbG90ID0gcmVxdWlyZSgnLi9wbG90JykucGxvdDtcbkJveC5zdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUnKS5zdHlsZTtcbkJveC5zdHlsZU9uU2VsZWN0ID0gcmVxdWlyZSgnLi9zdHlsZScpLnN0eWxlT25TZWxlY3Q7XG5Cb3guaG92ZXJQb2ludHMgPSByZXF1aXJlKCcuL2hvdmVyJykuaG92ZXJQb2ludHM7XG5Cb3guZXZlbnREYXRhID0gcmVxdWlyZSgnLi9ldmVudF9kYXRhJyk7XG5Cb3guc2VsZWN0UG9pbnRzID0gcmVxdWlyZSgnLi9zZWxlY3QnKTtcblxuQm94Lm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuQm94Lm5hbWUgPSAnYm94JztcbkJveC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpO1xuQm94LmNhdGVnb3JpZXMgPSBbJ2NhcnRlc2lhbicsICdzdmcnLCAnc3ltYm9scycsICdvcmllbnRlZCcsICdib3gtdmlvbGluJywgJ3Nob3dMZWdlbmQnLCAnYm94TGF5b3V0JywgJ3pvb21TY2FsZSddO1xuQm94Lm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEJveDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBib3htb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2dyb3VwJywgJ292ZXJsYXknXSxcbiAgICAgICAgZGZsdDogJ292ZXJsYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3hnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAwLjMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJveGdyb3VwZ2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMC4zLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5mdW5jdGlvbiBfc3VwcGx5KGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCBjb2VyY2UsIHRyYWNlVHlwZSkge1xuICAgIHZhciBoYXNUcmFjZVR5cGU7XG4gICAgdmFyIGNhdGVnb3J5ID0gdHJhY2VUeXBlICsgJ0xheW91dCc7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbERhdGFbaV0sIGNhdGVnb3J5KSkge1xuICAgICAgICAgICAgaGFzVHJhY2VUeXBlID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmKCFoYXNUcmFjZVR5cGUpIHJldHVybjtcblxuICAgIGNvZXJjZSh0cmFjZVR5cGUgKyAnbW9kZScpO1xuICAgIGNvZXJjZSh0cmFjZVR5cGUgKyAnZ2FwJyk7XG4gICAgY29lcmNlKHRyYWNlVHlwZSArICdncm91cGdhcCcpO1xufVxuXG5mdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cbiAgICBfc3VwcGx5KGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCBjb2VyY2UsICdib3gnKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHN1cHBseUxheW91dERlZmF1bHRzLFxuICAgIF9zdXBwbHk6IF9zdXBwbHlcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbi8vIGNvbnN0YW50cyBmb3IgZHluYW1pYyBqaXR0ZXIgKGllIGxlc3Mgaml0dGVyIGZvciBzcGFyc2VyIHBvaW50cylcbnZhciBKSVRURVJDT1VOVCA9IDU7IC8vIHBvaW50cyBlaXRoZXIgc2lkZSBvZiB0aGlzIHRvIGluY2x1ZGVcbnZhciBKSVRURVJTUFJFQUQgPSAwLjAxOyAvLyBmcmFjdGlvbiBvZiBJUVIgdG8gY291bnQgYXMgXCJkZW5zZVwiXG5cbmZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZGJveCwgYm94TGF5ZXIpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuICAgIHZhciBudW1Cb3hlcyA9IGZ1bGxMYXlvdXQuX251bUJveGVzO1xuICAgIHZhciBncm91cEZyYWN0aW9uID0gKDEgLSBmdWxsTGF5b3V0LmJveGdhcCk7XG4gICAgdmFyIGdyb3VwID0gKGZ1bGxMYXlvdXQuYm94bW9kZSA9PT0gJ2dyb3VwJyAmJiBudW1Cb3hlcyA+IDEpO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyhib3hMYXllciwgY2Rib3gsICd0cmFjZSBib3hlcycpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdCA9IGNkMC50O1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIGlmKCFwbG90aW5mby5pc1JhbmdlUGxvdCkgY2QwLm5vZGUzID0gcGxvdEdyb3VwO1xuICAgICAgICAvLyBib3ggaGFsZiB3aWR0aFxuICAgICAgICB2YXIgYmRQb3MgPSB0LmRQb3MgKiBncm91cEZyYWN0aW9uICogKDEgLSBmdWxsTGF5b3V0LmJveGdyb3VwZ2FwKSAvIChncm91cCA/IG51bUJveGVzIDogMSk7XG4gICAgICAgIC8vIGJveCBjZW50ZXIgb2Zmc2V0XG4gICAgICAgIHZhciBiUG9zID0gZ3JvdXAgPyAyICogdC5kUG9zICogKC0wLjUgKyAodC5udW0gKyAwLjUpIC8gbnVtQm94ZXMpICogZ3JvdXBGcmFjdGlvbiA6IDA7XG4gICAgICAgIC8vIHdoaXNrZXIgd2lkdGhcbiAgICAgICAgdmFyIHdkUG9zID0gYmRQb3MgKiB0cmFjZS53aGlza2Vyd2lkdGg7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCB0LmVtcHR5KSB7XG4gICAgICAgICAgICBwbG90R3JvdXAucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9zQXhpcywgdmFsQXhpcztcblxuICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICBwb3NBeGlzID0geWE7XG4gICAgICAgICAgICB2YWxBeGlzID0geGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb3NBeGlzID0geGE7XG4gICAgICAgICAgICB2YWxBeGlzID0geWE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzYXZlIHRoZSBib3ggc2l6ZSBhbmQgYm94IHBvc2l0aW9uIGZvciB1c2UgYnkgaG92ZXJcbiAgICAgICAgdC5iUG9zID0gYlBvcztcbiAgICAgICAgdC5iZFBvcyA9IGJkUG9zO1xuICAgICAgICB0LndkUG9zID0gd2RQb3M7XG4gICAgICAgIC8vIGhhbGYtd2lkdGggd2l0aGluIHdoaWNoIHRvIGFjY2VwdCBob3ZlciBmb3IgdGhpcyBib3hcbiAgICAgICAgLy8gYWx3YXlzIHNwbGl0IHRoZSBkaXN0YW5jZSB0byB0aGUgY2xvc2VzdCBib3hcbiAgICAgICAgdC53SG92ZXIgPSB0LmRQb3MgKiAoZ3JvdXAgPyBncm91cEZyYWN0aW9uIC8gbnVtQm94ZXMgOiAxKTtcblxuICAgICAgICBwbG90Qm94QW5kV2hpc2tlcnMocGxvdEdyb3VwLCB7cG9zOiBwb3NBeGlzLCB2YWw6IHZhbEF4aXN9LCB0cmFjZSwgdCk7XG4gICAgICAgIHBsb3RQb2ludHMocGxvdEdyb3VwLCB7eDogeGEsIHk6IHlhfSwgdHJhY2UsIHQpO1xuICAgICAgICBwbG90Qm94TWVhbihwbG90R3JvdXAsIHtwb3M6IHBvc0F4aXMsIHZhbDogdmFsQXhpc30sIHRyYWNlLCB0KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcGxvdEJveEFuZFdoaXNrZXJzKHNlbCwgYXhlcywgdHJhY2UsIHQpIHtcbiAgICB2YXIgcG9zQXhpcyA9IGF4ZXMucG9zO1xuICAgIHZhciB2YWxBeGlzID0gYXhlcy52YWw7XG4gICAgdmFyIGJQb3MgPSB0LmJQb3M7XG4gICAgdmFyIHdkUG9zID0gdC53ZFBvcyB8fCAwO1xuICAgIHZhciBiUG9zUHhPZmZzZXQgPSB0LmJQb3NQeE9mZnNldCB8fCAwO1xuICAgIHZhciB3aGlza2VyV2lkdGggPSB0cmFjZS53aGlza2Vyd2lkdGggfHwgMDtcbiAgICB2YXIgbm90Y2hlZCA9IHRyYWNlLm5vdGNoZWQgfHwgZmFsc2U7XG4gICAgdmFyIG53ID0gbm90Y2hlZCA/IDEgLSAyICogdHJhY2Uubm90Y2h3aWR0aCA6IDE7XG5cbiAgICAvLyB0byBzdXBwb3J0IGZvciBvbmUtc2lkZWQgYm94XG4gICAgdmFyIGJkUG9zMDtcbiAgICB2YXIgYmRQb3MxO1xuICAgIGlmKEFycmF5LmlzQXJyYXkodC5iZFBvcykpIHtcbiAgICAgICAgYmRQb3MwID0gdC5iZFBvc1swXTtcbiAgICAgICAgYmRQb3MxID0gdC5iZFBvc1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBiZFBvczAgPSB0LmJkUG9zO1xuICAgICAgICBiZFBvczEgPSB0LmJkUG9zO1xuICAgIH1cblxuICAgIHZhciBwYXRocyA9IHNlbC5zZWxlY3RBbGwoJ3BhdGguYm94JykuZGF0YSgoXG4gICAgICAgIHRyYWNlLnR5cGUgIT09ICd2aW9saW4nIHx8XG4gICAgICAgIHRyYWNlLmJveC52aXNpYmxlXG4gICAgKSA/IExpYi5pZGVudGl0eSA6IFtdKTtcblxuICAgIHBhdGhzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdib3gnKTtcblxuICAgIHBhdGhzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHBhdGhzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcG9zID0gZC5wb3M7XG4gICAgICAgIHZhciBwb3NjID0gcG9zQXhpcy5jMnAocG9zICsgYlBvcywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3MwID0gcG9zQXhpcy5jMnAocG9zICsgYlBvcyAtIGJkUG9zMCwgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3MxID0gcG9zQXhpcy5jMnAocG9zICsgYlBvcyArIGJkUG9zMSwgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3N3MCA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgLSB3ZFBvcywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3N3MSA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgKyB3ZFBvcywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3NtMCA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgLSBiZFBvczAgKiBudywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3NtMSA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgKyBiZFBvczEgKiBudywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBxMSA9IHZhbEF4aXMuYzJwKGQucTEsIHRydWUpO1xuICAgICAgICB2YXIgcTMgPSB2YWxBeGlzLmMycChkLnEzLCB0cnVlKTtcbiAgICAgICAgLy8gbWFrZSBzdXJlIG1lZGlhbiBpc24ndCBpZGVudGljYWwgdG8gZWl0aGVyIG9mIHRoZVxuICAgICAgICAvLyBxdWFydGlsZXMsIHNvIHdlIGNhbiBzZWUgaXRcbiAgICAgICAgdmFyIG0gPSBMaWIuY29uc3RyYWluKFxuICAgICAgICAgICAgdmFsQXhpcy5jMnAoZC5tZWQsIHRydWUpLFxuICAgICAgICAgICAgTWF0aC5taW4ocTEsIHEzKSArIDEsIE1hdGgubWF4KHExLCBxMykgLSAxXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBib3gsIHZpb2xpbiwgYW5kIGNhbmRsZXN0aWNrXG4gICAgICAgIC8vIHBlcmhhcHMgd2Ugc2hvdWxkIHB1dCB0aGlzIGludG8gY2QwLnQgaW5zdGVhZCBzbyBpdCdzIG1vcmUgZXhwbGljaXQsXG4gICAgICAgIC8vIGJ1dCB3aGF0IHdlIGhhdmUgbm93IGlzOlxuICAgICAgICAvLyAtIGJveCBhbHdheXMgaGFzIGQubGYsIGJ1dCBib3hwb2ludHMgY2FuIGJlIGFueXRoaW5nXG4gICAgICAgIC8vIC0gdmlvbGluIGhhcyBkLmxmIGFuZCBzaG91bGQgYWx3YXlzIHVzZSBpdCAoYm94cG9pbnRzIGlzIHVuZGVmaW5lZClcbiAgICAgICAgLy8gLSBjYW5kbGVzdGljayBoYXMgb25seSBtaW4vbWF4XG4gICAgICAgIHZhciB1c2VFeHRyZW1lcyA9IChkLmxmID09PSB1bmRlZmluZWQpIHx8ICh0cmFjZS5ib3hwb2ludHMgPT09IGZhbHNlKTtcbiAgICAgICAgdmFyIGxmID0gdmFsQXhpcy5jMnAodXNlRXh0cmVtZXMgPyBkLm1pbiA6IGQubGYsIHRydWUpO1xuICAgICAgICB2YXIgdWYgPSB2YWxBeGlzLmMycCh1c2VFeHRyZW1lcyA/IGQubWF4IDogZC51ZiwgdHJ1ZSk7XG4gICAgICAgIHZhciBsbiA9IHZhbEF4aXMuYzJwKGQubG4sIHRydWUpO1xuICAgICAgICB2YXIgdW4gPSB2YWxBeGlzLmMycChkLnVuLCB0cnVlKTtcblxuICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsXG4gICAgICAgICAgICAgICAgJ00nICsgbSArICcsJyArIHBvc20wICsgJ1YnICsgcG9zbTEgKyAvLyBtZWRpYW4gbGluZVxuICAgICAgICAgICAgICAgICdNJyArIHExICsgJywnICsgcG9zMCArICdWJyArIHBvczEgKyAvLyBsZWZ0IGVkZ2VcbiAgICAgICAgICAgICAgICAobm90Y2hlZCA/ICdIJyArIGxuICsgJ0wnICsgbSArICcsJyArIHBvc20xICsgJ0wnICsgdW4gKyAnLCcgKyBwb3MxIDogJycpICsgLy8gdG9wIG5vdGNoZWQgZWRnZVxuICAgICAgICAgICAgICAgICdIJyArIHEzICsgLy8gZW5kIG9mIHRoZSB0b3AgZWRnZVxuICAgICAgICAgICAgICAgICdWJyArIHBvczAgKyAvLyByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgKG5vdGNoZWQgPyAnSCcgKyB1biArICdMJyArIG0gKyAnLCcgKyBwb3NtMCArICdMJyArIGxuICsgJywnICsgcG9zMCA6ICcnKSArIC8vIGJvdHRvbSBub3RjaGVkIGVkZ2VcbiAgICAgICAgICAgICAgICAnWicgKyAvLyBlbmQgb2YgdGhlIGJveFxuICAgICAgICAgICAgICAgICdNJyArIHExICsgJywnICsgcG9zYyArICdIJyArIGxmICsgJ00nICsgcTMgKyAnLCcgKyBwb3NjICsgJ0gnICsgdWYgKyAvLyB3aGlza2Vyc1xuICAgICAgICAgICAgICAgICgod2hpc2tlcldpZHRoID09PSAwKSA/ICcnIDogLy8gd2hpc2tlciBjYXBzXG4gICAgICAgICAgICAgICAgICAgICdNJyArIGxmICsgJywnICsgcG9zdzAgKyAnVicgKyBwb3N3MSArICdNJyArIHVmICsgJywnICsgcG9zdzAgKyAnVicgKyBwb3N3MSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICdNJyArIHBvc20wICsgJywnICsgbSArICdIJyArIHBvc20xICsgLy8gbWVkaWFuIGxpbmVcbiAgICAgICAgICAgICAgICAnTScgKyBwb3MwICsgJywnICsgcTEgKyAnSCcgKyBwb3MxICsgLy8gdG9wIG9mIHRoZSBib3hcbiAgICAgICAgICAgICAgICAobm90Y2hlZCA/ICdWJyArIGxuICsgJ0wnICsgcG9zbTEgKyAnLCcgKyBtICsgJ0wnICsgcG9zMSArICcsJyArIHVuIDogJycpICsgLy8gbm90Y2hlZCByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgJ1YnICsgcTMgKyAvLyBlbmQgb2YgdGhlIHJpZ2h0IGVkZ2VcbiAgICAgICAgICAgICAgICAnSCcgKyBwb3MwICsgLy8gYm90dG9tIG9mIHRoZSBib3hcbiAgICAgICAgICAgICAgICAobm90Y2hlZCA/ICdWJyArIHVuICsgJ0wnICsgcG9zbTAgKyAnLCcgKyBtICsgJ0wnICsgcG9zMCArICcsJyArIGxuIDogJycpICsgLy8gbm90Y2hlZCBsZWZ0IGVkZ2VcbiAgICAgICAgICAgICAgICAnWicgKyAvLyBlbmQgb2YgdGhlIGJveFxuICAgICAgICAgICAgICAgICdNJyArIHBvc2MgKyAnLCcgKyBxMSArICdWJyArIGxmICsgJ00nICsgcG9zYyArICcsJyArIHEzICsgJ1YnICsgdWYgKyAvLyB3aGlza2Vyc1xuICAgICAgICAgICAgICAgICgod2hpc2tlcldpZHRoID09PSAwKSA/ICcnIDogLy8gd2hpc2tlciBjYXBzXG4gICAgICAgICAgICAgICAgICAgICdNJyArIHBvc3cwICsgJywnICsgbGYgKyAnSCcgKyBwb3N3MSArICdNJyArIHBvc3cwICsgJywnICsgdWYgKyAnSCcgKyBwb3N3MSkpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHBsb3RQb2ludHMoc2VsLCBheGVzLCB0cmFjZSwgdCkge1xuICAgIHZhciB4YSA9IGF4ZXMueDtcbiAgICB2YXIgeWEgPSBheGVzLnk7XG4gICAgdmFyIGJkUG9zID0gdC5iZFBvcztcbiAgICB2YXIgYlBvcyA9IHQuYlBvcztcblxuICAgIC8vIHRvIHN1cHBvcnQgdmlvbGluIHBvaW50c1xuICAgIHZhciBtb2RlID0gdHJhY2UuYm94cG9pbnRzIHx8IHRyYWNlLnBvaW50cztcblxuICAgIC8vIHJlcGVhdGFibGUgcHNldWRvLXJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yXG4gICAgTGliLnNlZWRQc2V1ZG9SYW5kb20oKTtcblxuICAgIC8vIHNpbmNlIGJveCBwbG90IHBvaW50cyBnZXQgYW4gZXh0cmEgbGV2ZWwgb2YgbmVzdGluZywgZWFjaFxuICAgIC8vIGJveCBuZWVkcyB0aGUgdHJhY2Ugc3R5bGluZyBpbmZvXG4gICAgdmFyIGZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICBkLmZvckVhY2goZnVuY3Rpb24odikge1xuICAgICAgICAgICAgdi50ID0gdDtcbiAgICAgICAgICAgIHYudHJhY2UgPSB0cmFjZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBkO1xuICAgIH07XG5cbiAgICB2YXIgZ1BvaW50cyA9IHNlbC5zZWxlY3RBbGwoJ2cucG9pbnRzJylcbiAgICAgICAgLmRhdGEobW9kZSA/IGZuIDogW10pO1xuXG4gICAgZ1BvaW50cy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdwb2ludHMnKTtcblxuICAgIGdQb2ludHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIHBhdGhzID0gZ1BvaW50cy5zZWxlY3RBbGwoJ3BhdGgnKVxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgdmFyIHB0cyA9IG1vZGUgPT09ICdhbGwnID9cbiAgICAgICAgICAgICAgICBkLnB0cyA6XG4gICAgICAgICAgICAgICAgZC5wdHMuZmlsdGVyKGZ1bmN0aW9uKHB0KSB7IHJldHVybiAocHQudiA8IGQubGYgfHwgcHQudiA+IGQudWYpOyB9KTtcblxuICAgICAgICAgICAgLy8gbm9ybWFsbHkgdXNlIElRUiwgYnV0IGlmIHRoaXMgaXMgMCBvciB0b28gc21hbGwsIHVzZSBtYXgtbWluXG4gICAgICAgICAgICB2YXIgdHlwaWNhbFNwcmVhZCA9IE1hdGgubWF4KChkLm1heCAtIGQubWluKSAvIDEwLCBkLnEzIC0gZC5xMSk7XG4gICAgICAgICAgICB2YXIgbWluU3ByZWFkID0gdHlwaWNhbFNwcmVhZCAqIDFlLTk7XG4gICAgICAgICAgICB2YXIgc3ByZWFkTGltaXQgPSB0eXBpY2FsU3ByZWFkICogSklUVEVSU1BSRUFEO1xuICAgICAgICAgICAgdmFyIGppdHRlckZhY3RvcnMgPSBbXTtcbiAgICAgICAgICAgIHZhciBtYXhKaXR0ZXJGYWN0b3IgPSAwO1xuICAgICAgICAgICAgdmFyIG5ld0ppdHRlcjtcblxuICAgICAgICAgICAgLy8gZHluYW1pYyBqaXR0ZXJcbiAgICAgICAgICAgIGlmKHRyYWNlLmppdHRlcikge1xuICAgICAgICAgICAgICAgIGlmKHR5cGljYWxTcHJlYWQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZWRnZSBjYXNlIG9mIG5vIHNwcmVhZCBhdCBhbGw6IGZhbGwgYmFjayB0byBtYXggaml0dGVyXG4gICAgICAgICAgICAgICAgICAgIG1heEppdHRlckZhY3RvciA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGppdHRlckZhY3RvcnMgPSBuZXcgQXJyYXkocHRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyRmFjdG9yc1tpXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIGkgLSBKSVRURVJDT1VOVCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG1pbiA9IHB0c1tpMF0udjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpMSA9IE1hdGgubWluKHB0cy5sZW5ndGggLSAxLCBpICsgSklUVEVSQ09VTlQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBtYXggPSBwdHNbaTFdLnY7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG1vZGUgIT09ICdhbGwnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocHRzW2ldLnYgPCBkLmxmKSBwbWF4ID0gTWF0aC5taW4ocG1heCwgZC5sZik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBwbWluID0gTWF0aC5tYXgocG1pbiwgZC51Zik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBqaXR0ZXJGYWN0b3IgPSBNYXRoLnNxcnQoc3ByZWFkTGltaXQgKiAoaTEgLSBpMCkgLyAocG1heCAtIHBtaW4gKyBtaW5TcHJlYWQpKSB8fCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyRmFjdG9yID0gTGliLmNvbnN0cmFpbihNYXRoLmFicyhqaXR0ZXJGYWN0b3IpLCAwLCAxKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyRmFjdG9ycy5wdXNoKGppdHRlckZhY3Rvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhKaXR0ZXJGYWN0b3IgPSBNYXRoLm1heChqaXR0ZXJGYWN0b3IsIG1heEppdHRlckZhY3Rvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmV3Sml0dGVyID0gdHJhY2Uuaml0dGVyICogMiAvIChtYXhKaXR0ZXJGYWN0b3IgfHwgMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGZpbGxzIGluICd4JyBhbmQgJ3knIGluIGNhbGNkYXRhICdwdHMnIGl0ZW1cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBwdCA9IHB0c1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IHB0LnY7XG5cbiAgICAgICAgICAgICAgICB2YXIgaml0dGVyT2Zmc2V0ID0gdHJhY2Uuaml0dGVyID9cbiAgICAgICAgICAgICAgICAgICAgKG5ld0ppdHRlciAqIGppdHRlckZhY3RvcnNbaV0gKiAoTGliLnBzZXVkb1JhbmRvbSgpIC0gMC41KSkgOlxuICAgICAgICAgICAgICAgICAgICAwO1xuXG4gICAgICAgICAgICAgICAgdmFyIHBvc1B4ID0gZC5wb3MgKyBiUG9zICsgYmRQb3MgKiAodHJhY2UucG9pbnRwb3MgKyBqaXR0ZXJPZmZzZXQpO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgICAgICAgICBwdC55ID0gcG9zUHg7XG4gICAgICAgICAgICAgICAgICAgIHB0LnggPSB2O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHB0LnggPSBwb3NQeDtcbiAgICAgICAgICAgICAgICAgICAgcHQueSA9IHY7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gdGFnIHN1c3BlY3RlZCBvdXRsaWVyc1xuICAgICAgICAgICAgICAgIGlmKG1vZGUgPT09ICdzdXNwZWN0ZWRvdXRsaWVycycgJiYgdiA8IGQudW8gJiYgdiA+IGQubG8pIHtcbiAgICAgICAgICAgICAgICAgICAgcHQuc28gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHB0cztcbiAgICAgICAgfSk7XG5cbiAgICBwYXRocy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKCdwb2ludCcsIHRydWUpO1xuXG4gICAgcGF0aHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgcGF0aHMuY2FsbChEcmF3aW5nLnRyYW5zbGF0ZVBvaW50cywgeGEsIHlhKTtcbn1cblxuZnVuY3Rpb24gcGxvdEJveE1lYW4oc2VsLCBheGVzLCB0cmFjZSwgdCkge1xuICAgIHZhciBwb3NBeGlzID0gYXhlcy5wb3M7XG4gICAgdmFyIHZhbEF4aXMgPSBheGVzLnZhbDtcbiAgICB2YXIgYlBvcyA9IHQuYlBvcztcbiAgICB2YXIgYlBvc1B4T2Zmc2V0ID0gdC5iUG9zUHhPZmZzZXQgfHwgMDtcblxuICAgIC8vIHRvIHN1cHBvcnQgdmlvbGluIG1lYW4gbGluZXNcbiAgICB2YXIgbW9kZSA9IHRyYWNlLmJveG1lYW4gfHwgKHRyYWNlLm1lYW5saW5lIHx8IHt9KS52aXNpYmxlO1xuXG4gICAgLy8gdG8gc3VwcG9ydCBmb3Igb25lLXNpZGVkIGJveFxuICAgIHZhciBiZFBvczA7XG4gICAgdmFyIGJkUG9zMTtcbiAgICBpZihBcnJheS5pc0FycmF5KHQuYmRQb3MpKSB7XG4gICAgICAgIGJkUG9zMCA9IHQuYmRQb3NbMF07XG4gICAgICAgIGJkUG9zMSA9IHQuYmRQb3NbMV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYmRQb3MwID0gdC5iZFBvcztcbiAgICAgICAgYmRQb3MxID0gdC5iZFBvcztcbiAgICB9XG5cbiAgICB2YXIgcGF0aHMgPSBzZWwuc2VsZWN0QWxsKCdwYXRoLm1lYW4nKS5kYXRhKChcbiAgICAgICAgKHRyYWNlLnR5cGUgPT09ICdib3gnICYmIHRyYWNlLmJveG1lYW4pIHx8XG4gICAgICAgICh0cmFjZS50eXBlID09PSAndmlvbGluJyAmJiB0cmFjZS5ib3gudmlzaWJsZSAmJiB0cmFjZS5tZWFubGluZS52aXNpYmxlKVxuICAgICkgPyBMaWIuaWRlbnRpdHkgOiBbXSk7XG5cbiAgICBwYXRocy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdtZWFuJylcbiAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgICd2ZWN0b3ItZWZmZWN0JzogJ25vbi1zY2FsaW5nLXN0cm9rZSdcbiAgICAgICAgfSk7XG5cbiAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBwYXRocy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHBvc2MgPSBwb3NBeGlzLmMycChkLnBvcyArIGJQb3MsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zMCA9IHBvc0F4aXMuYzJwKGQucG9zICsgYlBvcyAtIGJkUG9zMCwgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3MxID0gcG9zQXhpcy5jMnAoZC5wb3MgKyBiUG9zICsgYmRQb3MxLCB0cnVlKSArIGJQb3NQeE9mZnNldDtcbiAgICAgICAgdmFyIG0gPSB2YWxBeGlzLmMycChkLm1lYW4sIHRydWUpO1xuICAgICAgICB2YXIgc2wgPSB2YWxBeGlzLmMycChkLm1lYW4gLSBkLnNkLCB0cnVlKTtcbiAgICAgICAgdmFyIHNoID0gdmFsQXhpcy5jMnAoZC5tZWFuICsgZC5zZCwgdHJ1ZSk7XG5cbiAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICdNJyArIG0gKyAnLCcgKyBwb3MwICsgJ1YnICsgcG9zMSArXG4gICAgICAgICAgICAgICAgKG1vZGUgPT09ICdzZCcgP1xuICAgICAgICAgICAgICAgICAgICAnbTAsMEwnICsgc2wgKyAnLCcgKyBwb3NjICsgJ0wnICsgbSArICcsJyArIHBvczAgKyAnTCcgKyBzaCArICcsJyArIHBvc2MgKyAnWicgOlxuICAgICAgICAgICAgICAgICAgICAnJylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsXG4gICAgICAgICAgICAgICAgJ00nICsgcG9zMCArICcsJyArIG0gKyAnSCcgKyBwb3MxICtcbiAgICAgICAgICAgICAgICAobW9kZSA9PT0gJ3NkJyA/XG4gICAgICAgICAgICAgICAgICAgICdtMCwwTCcgKyBwb3NjICsgJywnICsgc2wgKyAnTCcgKyBwb3MwICsgJywnICsgbSArICdMJyArIHBvc2MgKyAnLCcgKyBzaCArICdaJyA6XG4gICAgICAgICAgICAgICAgICAgICcnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBwbG90OiBwbG90LFxuICAgIHBsb3RCb3hBbmRXaGlza2VyczogcGxvdEJveEFuZFdoaXNrZXJzLFxuICAgIHBsb3RQb2ludHM6IHBsb3RQb2ludHMsXG4gICAgcGxvdEJveE1lYW46IHBsb3RCb3hNZWFuXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGksIGo7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCAoY2RbaV0ucHRzIHx8IFtdKS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIGNkW2ldLnB0c1tqXS5zZWxlY3RlZCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgKGNkW2ldLnB0cyB8fCBbXSkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHQgPSBjZFtpXS5wdHNbal07XG4gICAgICAgICAgICAgICAgdmFyIHggPSB4YS5jMnAocHQueCk7XG4gICAgICAgICAgICAgICAgdmFyIHkgPSB5YS5jMnAocHQueSk7XG5cbiAgICAgICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBudWxsLCBwdC5pLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogcHQuaSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHhhLmMyZChwdC54KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IHlhLmMyZChwdC55KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcHQuc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHB0LnNlbGVjdGVkID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbmZ1bmN0aW9uIHN0eWxlKGdkLCBjZCkge1xuICAgIHZhciBzID0gY2QgPyBjZFswXS5ub2RlMyA6IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLnRyYWNlLmJveGVzJyk7XG5cbiAgICBzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5OyB9KTtcblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcbiAgICAgICAgdmFyIGxpbmVXaWR0aCA9IHRyYWNlLmxpbmUud2lkdGg7XG5cbiAgICAgICAgZnVuY3Rpb24gc3R5bGVCb3goYm94U2VsLCBsaW5lV2lkdGgsIGxpbmVDb2xvciwgZmlsbENvbG9yKSB7XG4gICAgICAgICAgICBib3hTZWwuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGxpbmVXaWR0aCArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBsaW5lQ29sb3IpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZmlsbENvbG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhbGxCb3hlcyA9IGVsLnNlbGVjdEFsbCgncGF0aC5ib3gnKTtcblxuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnY2FuZGxlc3RpY2snKSB7XG4gICAgICAgICAgICBhbGxCb3hlcy5lYWNoKGZ1bmN0aW9uKGJveERhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhpc0JveCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGFpbmVyID0gdHJhY2VbYm94RGF0YS5kaXJdOyAvLyBkaXIgPSAnaW5jcmVhc2luZycgb3IgJ2RlY3JlYXNpbmcnXG4gICAgICAgICAgICAgICAgc3R5bGVCb3godGhpc0JveCwgY29udGFpbmVyLmxpbmUud2lkdGgsIGNvbnRhaW5lci5saW5lLmNvbG9yLCBjb250YWluZXIuZmlsbGNvbG9yKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBjdXN0b20gc2VsZWN0aW9uIHN0eWxlIGZvciBjYW5kbGVzdGlja3NcbiAgICAgICAgICAgICAgICB0aGlzQm94LnN0eWxlKCdvcGFjaXR5JywgdHJhY2Uuc2VsZWN0ZWRwb2ludHMgJiYgIWJveERhdGEuc2VsZWN0ZWQgPyAwLjMgOiAxKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3R5bGVCb3goYWxsQm94ZXMsIGxpbmVXaWR0aCwgdHJhY2UubGluZS5jb2xvciwgdHJhY2UuZmlsbGNvbG9yKTtcbiAgICAgICAgICAgIGVsLnNlbGVjdEFsbCgncGF0aC5tZWFuJylcbiAgICAgICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogbGluZVdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAnc3Ryb2tlLWRhc2hhcnJheSc6ICgyICogbGluZVdpZHRoKSArICdweCwnICsgbGluZVdpZHRoICsgJ3B4J1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCB0cmFjZS5saW5lLmNvbG9yKTtcblxuICAgICAgICAgICAgdmFyIHB0cyA9IGVsLnNlbGVjdEFsbCgncGF0aC5wb2ludCcpO1xuICAgICAgICAgICAgRHJhd2luZy5wb2ludFN0eWxlKHB0cywgdHJhY2UsIGdkKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBzdHlsZU9uU2VsZWN0KGdkLCBjZCkge1xuICAgIHZhciBzID0gY2RbMF0ubm9kZTM7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHB0cyA9IHMuc2VsZWN0QWxsKCdwYXRoLnBvaW50Jyk7XG5cbiAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cykge1xuICAgICAgICBEcmF3aW5nLnNlbGVjdGVkUG9pbnRTdHlsZShwdHMsIHRyYWNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBEcmF3aW5nLnBvaW50U3R5bGUocHRzLCB0cmFjZSwgZ2QpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3R5bGU6IHN0eWxlLFxuICAgIHN0eWxlT25TZWxlY3Q6IHN0eWxlT25TZWxlY3Rcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWInKS5leHRlbmRGbGF0O1xudmFyIE9ITENhdHRycyA9IHJlcXVpcmUoJy4uL29obGMvYXR0cmlidXRlcycpO1xudmFyIGJveEF0dHJzID0gcmVxdWlyZSgnLi4vYm94L2F0dHJpYnV0ZXMnKTtcblxuZnVuY3Rpb24gZGlyZWN0aW9uQXR0cnMobGluZUNvbG9yRGVmYXVsdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBib3hBdHRycy5saW5lLmNvbG9yLCB7ZGZsdDogbGluZUNvbG9yRGVmYXVsdH0pLFxuICAgICAgICAgICAgd2lkdGg6IGJveEF0dHJzLmxpbmUud2lkdGgsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuXG4gICAgICAgIGZpbGxjb2xvcjogYm94QXR0cnMuZmlsbGNvbG9yLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHg6IE9ITENhdHRycy54LFxuICAgIG9wZW46IE9ITENhdHRycy5vcGVuLFxuICAgIGhpZ2g6IE9ITENhdHRycy5oaWdoLFxuICAgIGxvdzogT0hMQ2F0dHJzLmxvdyxcbiAgICBjbG9zZTogT0hMQ2F0dHJzLmNsb3NlLFxuXG4gICAgbGluZToge1xuICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMubGluZS53aWR0aCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG5cbiAgICBpbmNyZWFzaW5nOiBkaXJlY3Rpb25BdHRycyhPSExDYXR0cnMuaW5jcmVhc2luZy5saW5lLmNvbG9yLmRmbHQpLFxuXG4gICAgZGVjcmVhc2luZzogZGlyZWN0aW9uQXR0cnMoT0hMQ2F0dHJzLmRlY3JlYXNpbmcubGluZS5jb2xvci5kZmx0KSxcblxuICAgIHRleHQ6IE9ITENhdHRycy50ZXh0LFxuICAgIHdoaXNrZXJ3aWR0aDogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMud2hpc2tlcndpZHRoLCB7IGRmbHQ6IDAgfSksXG5cbiAgICBob3ZlcmxhYmVsOiBPSExDYXR0cnMuaG92ZXJsYWJlbCxcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGNhbGNDb21tb24gPSByZXF1aXJlKCcuLi9vaGxjL2NhbGMnKS5jYWxjQ29tbW9uO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuXG4gICAgdmFyIHggPSB4YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd4Jyk7XG5cbiAgICB2YXIgY2QgPSBjYWxjQ29tbW9uKGdkLCB0cmFjZSwgeCwgeWEsIHB0RnVuYyk7XG5cbiAgICBpZihjZC5sZW5ndGgpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoY2RbMF0udCwge1xuICAgICAgICAgICAgbnVtOiBmdWxsTGF5b3V0Ll9udW1Cb3hlcyxcbiAgICAgICAgICAgIGRQb3M6IExpYi5kaXN0aW5jdFZhbHMoeCkubWluRGlmZiAvIDIsXG4gICAgICAgICAgICBwb3NMZXR0ZXI6ICd4JyxcbiAgICAgICAgICAgIHZhbExldHRlcjogJ3knLFxuICAgICAgICB9KTtcblxuICAgICAgICBmdWxsTGF5b3V0Ll9udW1Cb3hlcysrO1xuICAgICAgICByZXR1cm4gY2Q7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFt7dDoge2VtcHR5OiB0cnVlfX1dO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHB0RnVuYyhvLCBoLCBsLCBjKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWluOiBsLFxuICAgICAgICBxMTogTWF0aC5taW4obywgYyksXG4gICAgICAgIG1lZDogYyxcbiAgICAgICAgcTM6IE1hdGgubWF4KG8sIGMpLFxuICAgICAgICBtYXg6IGgsXG4gICAgfTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgaGFuZGxlT0hMQyA9IHJlcXVpcmUoJy4uL29obGMvb2hsY19kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZU9ITEModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGluZS53aWR0aCcpO1xuXG4gICAgaGFuZGxlRGlyZWN0aW9uKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsICdpbmNyZWFzaW5nJyk7XG4gICAgaGFuZGxlRGlyZWN0aW9uKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsICdkZWNyZWFzaW5nJyk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ3doaXNrZXJ3aWR0aCcpO1xuXG4gICAgbGF5b3V0Ll9yZXF1ZXN0UmFuZ2VzbGlkZXJbdHJhY2VPdXQueGF4aXNdID0gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlKGRpcmVjdGlvbiArICcubGluZS5jb2xvcicpO1xuICAgIGNvZXJjZShkaXJlY3Rpb24gKyAnLmxpbmUud2lkdGgnLCB0cmFjZU91dC5saW5lLndpZHRoKTtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5maWxsY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KGxpbmVDb2xvciwgMC41KSk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2NhbmRsZXN0aWNrJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyksXG4gICAgY2F0ZWdvcmllczogWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ3Nob3dMZWdlbmQnLCAnY2FuZGxlc3RpY2snLCAnYm94TGF5b3V0J10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9LFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogcmVxdWlyZSgnLi4vYm94L2xheW91dF9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IHJlcXVpcmUoJy4uL2JveC9sYXlvdXRfZGVmYXVsdHMnKS5zdXBwbHlMYXlvdXREZWZhdWx0cyxcbiAgICBjcm9zc1RyYWNlQ2FsYzogcmVxdWlyZSgnLi4vYm94L2Nyb3NzX3RyYWNlX2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuICAgIGNhbGM6IHJlcXVpcmUoJy4vY2FsYycpLFxuICAgIHBsb3Q6IHJlcXVpcmUoJy4uL2JveC9wbG90JykucGxvdCxcbiAgICBsYXllck5hbWU6ICdib3hsYXllcicsXG4gICAgc3R5bGU6IHJlcXVpcmUoJy4uL2JveC9zdHlsZScpLnN0eWxlLFxuICAgIGhvdmVyUG9pbnRzOiByZXF1aXJlKCcuLi9vaGxjL2hvdmVyJykuaG92ZXJQb2ludHMsXG4gICAgc2VsZWN0UG9pbnRzOiByZXF1aXJlKCcuLi9vaGxjL3NlbGVjdCcpXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGFuZGxlQXhpc0RlZmF1bHRzID0gcmVxdWlyZSgnLi9heGlzX2RlZmF1bHRzJyk7XG52YXIgVGVtcGxhdGUgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlQUJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgY29lcmNlLCBkZmx0Q29sb3IpIHtcbiAgICB2YXIgYSA9IGNvZXJjZSgnYScpO1xuXG4gICAgaWYoIWEpIHtcbiAgICAgICAgY29lcmNlKCdkYScpO1xuICAgICAgICBjb2VyY2UoJ2EwJyk7XG4gICAgfVxuXG4gICAgdmFyIGIgPSBjb2VyY2UoJ2InKTtcblxuICAgIGlmKCFiKSB7XG4gICAgICAgIGNvZXJjZSgnZGInKTtcbiAgICAgICAgY29lcmNlKCdiMCcpO1xuICAgIH1cblxuICAgIG1pbWlja0F4aXNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgZGZsdENvbG9yKTtcbn07XG5cbmZ1bmN0aW9uIG1pbWlja0F4aXNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgZGZsdENvbG9yKSB7XG4gICAgdmFyIGF4ZXNMaXN0ID0gWydhYXhpcycsICdiYXhpcyddO1xuXG4gICAgYXhlc0xpc3QuZm9yRWFjaChmdW5jdGlvbihheE5hbWUpIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhOYW1lLmNoYXJBdCgwKTtcbiAgICAgICAgdmFyIGF4SW4gPSB0cmFjZUluW2F4TmFtZV0gfHwge307XG4gICAgICAgIHZhciBheE91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcih0cmFjZU91dCwgYXhOYW1lKTtcblxuICAgICAgICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgICAgICAgICB0aWNrZm9udDogJ3gnLFxuICAgICAgICAgICAgaWQ6IGF4TGV0dGVyICsgJ2F4aXMnLFxuICAgICAgICAgICAgbGV0dGVyOiBheExldHRlcixcbiAgICAgICAgICAgIGZvbnQ6IHRyYWNlT3V0LmZvbnQsXG4gICAgICAgICAgICBuYW1lOiBheE5hbWUsXG4gICAgICAgICAgICBkYXRhOiB0cmFjZUluW2F4TGV0dGVyXSxcbiAgICAgICAgICAgIGNhbGVuZGFyOiB0cmFjZU91dC5jYWxlbmRhcixcbiAgICAgICAgICAgIGRmbHRDb2xvcjogZGZsdENvbG9yLFxuICAgICAgICAgICAgYmdDb2xvcjogZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yLFxuICAgICAgICAgICAgZnVsbExheW91dDogZnVsbExheW91dFxuICAgICAgICB9O1xuXG4gICAgICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhheEluLCBheE91dCwgZGVmYXVsdE9wdGlvbnMpO1xuICAgICAgICBheE91dC5fY2F0ZWdvcmllcyA9IGF4T3V0Ll9jYXRlZ29yaWVzIHx8IFtdO1xuXG4gICAgICAgIC8vIHNvIHdlIGRvbid0IGhhdmUgdG8gcmVwZWF0IGF1dG90eXBlIHVubmVjZXNzYXJpbHksXG4gICAgICAgIC8vIGNvcHkgYW4gYXV0b3R5cGUgYmFjayB0byB0cmFjZUluXG4gICAgICAgIGlmKCF0cmFjZUluW2F4TmFtZV0gJiYgYXhJbi50eXBlICE9PSAnLScpIHtcbiAgICAgICAgICAgIHRyYWNlSW5bYXhOYW1lXSA9IHt0eXBlOiBheEluLnR5cGV9O1xuICAgICAgICB9XG4gICAgfSk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhKSB7XG4gICAgcmV0dXJuIG1pbk1heChhLCAwKTtcbn07XG5cbmZ1bmN0aW9uIG1pbk1heChhLCBkZXB0aCkge1xuICAgIC8vIExpbWl0IHRvIHRlbiBkaW1lbnNpb25hbCBkYXRhc2V0cy4gVGhpcyBzZWVtcyAqZXhjZWVkaW5nbHkqIHVubGlrZWx5IHRvXG4gICAgLy8gZXZlciBjYXVzZSBwcm9ibGVtcyBvciBldmVuIGJlIGEgY29uY2Vybi4gSXQncyBpbmNsdWRlIHN0cmljdGx5IHNvIHRoYXRcbiAgICAvLyBjaXJjdWxhciBhcnJheXMgY291bGQgbmV2ZXIgY2F1c2UgdGhpcyB0byBsb29wLlxuICAgIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KGEpIHx8IGRlcHRoID49IDEwKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBtaW4gPSBJbmZpbml0eTtcbiAgICB2YXIgbWF4ID0gLUluZmluaXR5O1xuICAgIHZhciBuID0gYS5sZW5ndGg7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICB2YXIgZGF0dW0gPSBhW2ldO1xuXG4gICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoZGF0dW0pKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gbWluTWF4KGRhdHVtLCBkZXB0aCArIDEpO1xuXG4gICAgICAgICAgICBpZihyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihyZXN1bHRbMF0sIG1pbik7XG4gICAgICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgocmVzdWx0WzFdLCBtYXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWluID0gTWF0aC5taW4oZGF0dW0sIG1pbik7XG4gICAgICAgICAgICBtYXggPSBNYXRoLm1heChkYXR1bSwgbWF4KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbbWluLCBtYXhdO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgYXhpc0F0dHJzID0gcmVxdWlyZSgnLi9heGlzX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG5cbnZhciBjYXJwZXRGb250ID0gZm9udEF0dHJzKHtcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIFxufSk7XG4vLyBUT0RPOiBpbmhlcml0IGZyb20gZ2xvYmFsIGZvbnRcbmNhcnBldEZvbnQuZmFtaWx5LmRmbHQgPSAnXCJPcGVuIFNhbnNcIiwgdmVyZGFuYSwgYXJpYWwsIHNhbnMtc2VyaWYnO1xuY2FycGV0Rm9udC5zaXplLmRmbHQgPSAxMjtcbmNhcnBldEZvbnQuY29sb3IuZGZsdCA9IGNvbG9yQXR0cnMuZGVmYXVsdExpbmU7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhcnBldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYTA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiMDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGI6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNoZWF0ZXJzbG9wZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYWF4aXM6IGF4aXNBdHRycyxcbiAgICBiYXhpczogYXhpc0F0dHJzLFxuICAgIGZvbnQ6IGNhcnBldEZvbnQsXG4gICAgY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdHJhbnNmb3JtczogdW5kZWZpbmVkXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbi8qIFRoaXMgZnVuY3Rpb24gcmV0cm5zIGEgc2V0IG9mIGNvbnRyb2wgcG9pbnRzIHRoYXQgZGVmaW5lIGEgY3VydmUgYWxpZ25lZCBhbG9uZ1xuICogZWl0aGVyIHRoZSBhIG9yIGIgYXhpcy4gRXhhY3RseSBvbmUgb2YgYSBvciBiIG11c3QgYmUgYW4gYXJyYXkgZGVmaW5pbmcgdGhlIHJhbmdlXG4gKiBzcGFubmVkLlxuICpcbiAqIEhvbmVzdGx5IHRoaXMgaXMgdGhlIG1vc3QgY29tcGxpY2F0ZWQgZnVuY3Rpb24gSSd2ZSBpbXBsZW1lbnRlIGhlcmUgc28gZmFyIGJlY2F1c2VcbiAqIG9mIHRoZSB3YXkgaXQgaGFuZGxlcyBrbm90IGluc2VydGlvbiBhbmQgZGlyZWN0aW9uL2F4aXMtYWdub3N0aWMgc2xpY2VzLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNhcnBldCwgY2FycGV0Y2QsIGEsIGIpIHtcbiAgICB2YXIgaWR4LCB0YW5nZW50LCB0YW5Jc29JZHgsIHRhbklzb1Bhciwgc2VnbWVudCwgcmVmaWR4O1xuICAgIHZhciBwMCwgcDEsIHYwLCB2MSwgc3RhcnQsIGVuZCwgcmFuZ2U7XG5cbiAgICB2YXIgYXhpcyA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYSkgPyAnYScgOiAnYic7XG4gICAgdmFyIGF4ID0gYXhpcyA9PT0gJ2EnID8gY2FycGV0LmFheGlzIDogY2FycGV0LmJheGlzO1xuICAgIHZhciBzbW9vdGhpbmcgPSBheC5zbW9vdGhpbmc7XG4gICAgdmFyIHRvSWR4ID0gYXhpcyA9PT0gJ2EnID8gY2FycGV0LmEyaSA6IGNhcnBldC5iMmo7XG4gICAgdmFyIHB0ID0gYXhpcyA9PT0gJ2EnID8gYSA6IGI7XG4gICAgdmFyIGlzbyA9IGF4aXMgPT09ICdhJyA/IGIgOiBhO1xuICAgIHZhciBuID0gYXhpcyA9PT0gJ2EnID8gY2FycGV0Y2QuYS5sZW5ndGggOiBjYXJwZXRjZC5iLmxlbmd0aDtcbiAgICB2YXIgbSA9IGF4aXMgPT09ICdhJyA/IGNhcnBldGNkLmIubGVuZ3RoIDogY2FycGV0Y2QuYS5sZW5ndGg7XG4gICAgdmFyIGlzb0lkeCA9IE1hdGguZmxvb3IoYXhpcyA9PT0gJ2EnID8gY2FycGV0LmIyaihpc28pIDogY2FycGV0LmEyaShpc28pKTtcblxuICAgIHZhciB4eSA9IGF4aXMgPT09ICdhJyA/IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBjYXJwZXQuZXZhbHh5KFtdLCB2YWx1ZSwgaXNvSWR4KTtcbiAgICB9IDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGNhcnBldC5ldmFseHkoW10sIGlzb0lkeCwgdmFsdWUpO1xuICAgIH07XG5cbiAgICBpZihzbW9vdGhpbmcpIHtcbiAgICAgICAgdGFuSXNvSWR4ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obSAtIDIsIGlzb0lkeCkpO1xuICAgICAgICB0YW5Jc29QYXIgPSBpc29JZHggLSB0YW5Jc29JZHg7XG4gICAgICAgIHRhbmdlbnQgPSBheGlzID09PSAnYScgPyBmdW5jdGlvbihpLCB0aSkge1xuICAgICAgICAgICAgcmV0dXJuIGNhcnBldC5keHlkaShbXSwgaSwgdGFuSXNvSWR4LCB0aSwgdGFuSXNvUGFyKTtcbiAgICAgICAgfSA6IGZ1bmN0aW9uKGosIHRqKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FycGV0LmR4eWRqKFtdLCB0YW5Jc29JZHgsIGosIHRhbklzb1BhciwgdGopO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciB2c3RhcnQgPSB0b0lkeChwdFswXSk7XG4gICAgdmFyIHZlbmQgPSB0b0lkeChwdFsxXSk7XG5cbiAgICAvLyBTbyB0aGF0IHdlIGNhbiBtYWtlIHRoaXMgd29yayBpbiB0d28gZGlyZWN0aW9ucywgZmxpcCBhbGwgb2YgdGhlXG4gICAgLy8gbWF0aCBmdW5jdGlvbnMgaWYgdGhlIGRpcmVjdGlvbiBpcyBmcm9tIGhpZ2hlciB0byBsb3dlciBpbmRpY2VzOlxuICAgIC8vXG4gICAgLy8gTm90ZSB0aGF0IHRoZSB0b2xlcmFuY2UgaXMgZGlyZWN0aW9uYWwhXG4gICAgdmFyIGRpciA9IHZzdGFydCA8IHZlbmQgPyAxIDogLTE7XG4gICAgdmFyIHRvbCA9ICh2ZW5kIC0gdnN0YXJ0KSAqIDFlLTg7XG4gICAgdmFyIGRpcmZsb29yID0gZGlyID4gMCA/IE1hdGguZmxvb3IgOiBNYXRoLmNlaWw7XG4gICAgdmFyIGRpcmNlaWwgPSBkaXIgPiAwID8gTWF0aC5jZWlsIDogTWF0aC5mbG9vcjtcbiAgICB2YXIgZGlybWluID0gZGlyID4gMCA/IE1hdGgubWluIDogTWF0aC5tYXg7XG4gICAgdmFyIGRpcm1heCA9IGRpciA+IDAgPyBNYXRoLm1heCA6IE1hdGgubWluO1xuXG4gICAgdmFyIGlkeDAgPSBkaXJmbG9vcih2c3RhcnQgKyB0b2wpO1xuICAgIHZhciBpZHgxID0gZGlyY2VpbCh2ZW5kIC0gdG9sKTtcblxuICAgIHAwID0geHkodnN0YXJ0KTtcbiAgICB2YXIgc2VnbWVudHMgPSBbW3AwXV07XG5cbiAgICBmb3IoaWR4ID0gaWR4MDsgaWR4ICogZGlyIDwgaWR4MSAqIGRpcjsgaWR4ICs9IGRpcikge1xuICAgICAgICBzZWdtZW50ID0gW107XG4gICAgICAgIHN0YXJ0ID0gZGlybWF4KHZzdGFydCwgaWR4KTtcbiAgICAgICAgZW5kID0gZGlybWluKHZlbmQsIGlkeCArIGRpcik7XG4gICAgICAgIHJhbmdlID0gZW5kIC0gc3RhcnQ7XG5cbiAgICAgICAgLy8gSW4gb3JkZXIgdG8gZmlndXJlIG91dCB3aGljaCBjZWxsIHdlJ3JlIGluIGZvciB0aGUgZGVyaXZhdGl2ZSAocmVtZW1iZXIsXG4gICAgICAgIC8vIHRoZSBkZXJpdmF0aXZlcyBhcmUgKm5vdCogY29uc3RhbnQgYWNyb3NzIGdyaWQgbGluZXMpLCBsZXQncyBqdXN0IGF2ZXJhZ2VcbiAgICAgICAgLy8gdGhlIHN0YXJ0IGFuZCBlbmQgcG9pbnRzLiBUaGlzIGN1dHMgb3V0IGp1c3QgYSB0aW55IGJpdCBvZiBsb2dpYyBhbmRcbiAgICAgICAgLy8gdGhlcmUncyByZWFsbHkgbm8gY29tcHV0YXRpb25hbCBkaWZmZXJlbmNlOlxuICAgICAgICByZWZpZHggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihuIC0gMiwgTWF0aC5mbG9vcigwLjUgKiAoc3RhcnQgKyBlbmQpKSkpO1xuXG4gICAgICAgIHAxID0geHkoZW5kKTtcbiAgICAgICAgaWYoc21vb3RoaW5nKSB7XG4gICAgICAgICAgICB2MCA9IHRhbmdlbnQocmVmaWR4LCBzdGFydCAtIHJlZmlkeCk7XG4gICAgICAgICAgICB2MSA9IHRhbmdlbnQocmVmaWR4LCBlbmQgLSByZWZpZHgpO1xuXG4gICAgICAgICAgICBzZWdtZW50LnB1c2goW1xuICAgICAgICAgICAgICAgIHAwWzBdICsgdjBbMF0gLyAzICogcmFuZ2UsXG4gICAgICAgICAgICAgICAgcDBbMV0gKyB2MFsxXSAvIDMgKiByYW5nZVxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIHNlZ21lbnQucHVzaChbXG4gICAgICAgICAgICAgICAgcDFbMF0gLSB2MVswXSAvIDMgKiByYW5nZSxcbiAgICAgICAgICAgICAgICBwMVsxXSAtIHYxWzFdIC8gMyAqIHJhbmdlXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlZ21lbnQucHVzaChwMSk7XG5cbiAgICAgICAgc2VnbWVudHMucHVzaChzZWdtZW50KTtcbiAgICAgICAgcDAgPSBwMTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VnbWVudHM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGF4ZXNBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzbW9vdGhpbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLjMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICB0aXRsZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGl0bGVmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICB0aXRsZW9mZnNldDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAvLyAnLScgbWVhbnMgd2UgaGF2ZW4ndCB5ZXQgcnVuIGF1dG90eXBlIG9yIGNvdWxkbid0IGZpbmQgYW55IGRhdGFcbiAgICAgICAgLy8gaXQgZ2V0cyB0dXJuZWQgaW50byBsaW5lYXIgaW4gZ2QuX2Z1bGxMYXlvdXQgYnV0IG5vdCBjb3BpZWQgYmFja1xuICAgICAgICAvLyB0byBnZC5kYXRhIGxpa2UgdGhlIG90aGVycyBhcmUuXG4gICAgICAgIHZhbHVlczogWyctJywgJ2xpbmVhcicsICdkYXRlJywgJ2NhdGVnb3J5J10sXG4gICAgICAgIGRmbHQ6ICctJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXV0b3JhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbdHJ1ZSwgZmFsc2UsICdyZXZlcnNlZCddLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICByYW5nZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9ybWFsJywgJ3RvemVybycsICdub25uZWdhdGl2ZSddLFxuICAgICAgICBkZmx0OiAnbm9ybWFsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdjYWxjJ30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAnY2FsYyd9XG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBmaXhlZHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNoZWF0ZXJ0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2luZGV4JywgJ3ZhbHVlJ10sXG4gICAgICAgIGRmbHQ6ICd2YWx1ZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICB0aWNrbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsaW5lYXInLCAnYXJyYXknXSxcbiAgICAgICAgZGZsdDogJ2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIG50aWNrczoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3ZhbHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2t0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93dGlja2xhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzdGFydCcsICdlbmQnLCAnYm90aCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdzdGFydCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICB0aWNrYW5nbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrcHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd3RpY2twcmVmaXg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYWxsJywgJ2ZpcnN0JywgJ2xhc3QnLCAnbm9uZSddLFxuICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3N1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3d0aWNrc3VmZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdmaXJzdCcsICdsYXN0JywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2FsbCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dleHBvbmVudDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhbGwnLCAnZmlyc3QnLCAnbGFzdCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleHBvbmVudGZvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydub25lJywgJ2UnLCAnRScsICdwb3dlcicsICdTSScsICdCJ10sXG4gICAgICAgIGRmbHQ6ICdCJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2VwYXJhdGV0aG91c2FuZHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2Zvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb3JtYXRzdG9wczogb3ZlcnJpZGVBbGwoYXhlc0F0dHJzLnRpY2tmb3JtYXRzdG9wcywgJ2NhbGMnLCAnZnJvbS1yb290JyksXG4gICAgY2F0ZWdvcnlvcmRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3RyYWNlJywgJ2NhdGVnb3J5IGFzY2VuZGluZycsICdjYXRlZ29yeSBkZXNjZW5kaW5nJywgJ2FycmF5J1xuICAgICAgICAgICAgLyogLCAndmFsdWUgYXNjZW5kaW5nJywgJ3ZhbHVlIGRlc2NlbmRpbmcnKi8gLy8gdmFsdWUgYXNjZW5kaW5nIC8gZGVzY2VuZGluZyB0byBiZSBpbXBsZW1lbnRlZCBsYXRlclxuICAgICAgICBdLFxuICAgICAgICBkZmx0OiAndHJhY2UnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjYXRlZ29yeWFycmF5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFiZWxwYWRkaW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVscHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsYWJlbHN1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIGxpbmVzIGFuZCBncmlkc1xuICAgIHNob3dsaW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyaWR3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93Z3JpZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1pbm9yZ3JpZGNvdW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaW5vcmdyaWR3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaW5vcmdyaWRjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmxpZ2h0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5lY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVuZGxpbmU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlbmRsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVuZGxpbmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrMDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkdGljazoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheXRpY2swOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheWR0aWNrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FycGV0QXR0cnMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxudmFyIGFkZE9wYWNpdHkgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJykuYWRkT3BhY2l0eTtcbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vdGlja192YWx1ZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVDYXRlZ29yeU9yZGVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vY2F0ZWdvcnlfb3JkZXJfZGVmYXVsdHMnKTtcbnZhciBzZXRDb252ZXJ0ID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3NldF9jb252ZXJ0Jyk7XG52YXIgYXV0b1R5cGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19hdXRvdHlwZScpO1xuXG4vKipcbiAqIG9wdGlvbnM6IG9iamVjdCBjb250YWluaW5nOlxuICpcbiAqICBsZXR0ZXI6ICdhJyBvciAnYidcbiAqICB0aXRsZTogbmFtZSBvZiB0aGUgYXhpcyAoaWUgJ0NvbG9yYmFyJykgdG8gZ28gaW4gZGVmYXVsdCB0aXRsZVxuICogIG5hbWU6IGF4aXMgb2JqZWN0IG5hbWUgKGllICd4YXhpcycpIGlmIG9uZSBzaG91bGQgYmUgc3RvcmVkXG4gKiAgZm9udDogdGhlIGRlZmF1bHQgZm9udCB0byBpbmhlcml0XG4gKiAgb3V0ZXJUaWNrczogYm9vbGVhbiwgc2hvdWxkIHRpY2tzIGRlZmF1bHQgdG8gb3V0c2lkZT9cbiAqICBzaG93R3JpZDogYm9vbGVhbiwgc2hvdWxkIGdyaWRsaW5lcyBiZSBzaG93biBieSBkZWZhdWx0P1xuICogIGRhdGE6IHRoZSBwbG90IGRhdGEgdG8gdXNlIGluIGNob29zaW5nIGF1dG8gdHlwZVxuICogIGJnQ29sb3I6IHRoZSBwbG90IGJhY2tncm91bmQgY29sb3IsIHRvIGNhbGN1bGF0ZSBkZWZhdWx0IGdyaWRsaW5lIGNvbG9yc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZUF4aXNEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBvcHRpb25zKSB7XG4gICAgdmFyIGxldHRlciA9IG9wdGlvbnMubGV0dGVyLFxuICAgICAgICBmb250ID0gb3B0aW9ucy5mb250IHx8IHt9LFxuICAgICAgICBhdHRyaWJ1dGVzID0gY2FycGV0QXR0cnNbbGV0dGVyICsgJ2F4aXMnXTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvZXJjZTIoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZTIoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgLy8gc2V0IHVwIHNvbWUgcHJpdmF0ZSBwcm9wZXJ0aWVzXG4gICAgaWYob3B0aW9ucy5uYW1lKSB7XG4gICAgICAgIGNvbnRhaW5lck91dC5fbmFtZSA9IG9wdGlvbnMubmFtZTtcbiAgICAgICAgY29udGFpbmVyT3V0Ll9pZCA9IG9wdGlvbnMubmFtZTtcbiAgICB9XG5cbiAgICAvLyBub3cgZmlndXJlIG91dCB0eXBlIGFuZCBkbyBzb21lIG1vcmUgaW5pdGlhbGl6YXRpb25cbiAgICB2YXIgYXhUeXBlID0gY29lcmNlKCd0eXBlJyk7XG4gICAgaWYoYXhUeXBlID09PSAnLScpIHtcbiAgICAgICAgaWYob3B0aW9ucy5kYXRhKSBzZXRBdXRvVHlwZShjb250YWluZXJPdXQsIG9wdGlvbnMuZGF0YSk7XG5cbiAgICAgICAgaWYoY29udGFpbmVyT3V0LnR5cGUgPT09ICctJykge1xuICAgICAgICAgICAgY29udGFpbmVyT3V0LnR5cGUgPSAnbGluZWFyJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvcHkgYXV0b1R5cGUgYmFjayB0byBpbnB1dCBheGlzXG4gICAgICAgICAgICAvLyBub3RlIHRoYXQgaWYgdGhpcyBvYmplY3QgZGlkbid0IGV4aXN0XG4gICAgICAgICAgICAvLyBpbiB0aGUgaW5wdXQgbGF5b3V0LCB3ZSBoYXZlIHRvIHB1dCBpdCBpblxuICAgICAgICAgICAgLy8gdGhpcyBoYXBwZW5zIGluIHRoZSBtYWluIHN1cHBseURlZmF1bHRzIGZ1bmN0aW9uXG4gICAgICAgICAgICBheFR5cGUgPSBjb250YWluZXJJbi50eXBlID0gY29udGFpbmVyT3V0LnR5cGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb2VyY2UoJ3Ntb290aGluZycpO1xuICAgIGNvZXJjZSgnY2hlYXRlcnR5cGUnKTtcblxuICAgIGNvZXJjZSgnc2hvd3RpY2tsYWJlbHMnKTtcbiAgICBjb2VyY2UoJ2xhYmVscHJlZml4JywgbGV0dGVyICsgJyA9ICcpO1xuICAgIGNvZXJjZSgnbGFiZWxzdWZmaXgnKTtcbiAgICBjb2VyY2UoJ3Nob3d0aWNrcHJlZml4Jyk7XG4gICAgY29lcmNlKCdzaG93dGlja3N1ZmZpeCcpO1xuXG4gICAgY29lcmNlKCdzZXBhcmF0ZXRob3VzYW5kcycpO1xuICAgIGNvZXJjZSgndGlja2Zvcm1hdCcpO1xuICAgIGNvZXJjZSgnZXhwb25lbnRmb3JtYXQnKTtcbiAgICBjb2VyY2UoJ3Nob3dleHBvbmVudCcpO1xuICAgIGNvZXJjZSgnY2F0ZWdvcnlvcmRlcicpO1xuXG4gICAgY29lcmNlKCd0aWNrbW9kZScpO1xuICAgIGNvZXJjZSgndGlja3ZhbHMnKTtcbiAgICBjb2VyY2UoJ3RpY2t0ZXh0Jyk7XG4gICAgY29lcmNlKCd0aWNrMCcpO1xuICAgIGNvZXJjZSgnZHRpY2snKTtcblxuICAgIGlmKGNvbnRhaW5lck91dC50aWNrbW9kZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICBjb2VyY2UoJ2FycmF5dGljazAnKTtcbiAgICAgICAgY29lcmNlKCdhcnJheWR0aWNrJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdsYWJlbHBhZGRpbmcnKTtcblxuICAgIGNvbnRhaW5lck91dC5faG92ZXJ0aXRsZSA9IGxldHRlcjtcblxuXG4gICAgaWYoYXhUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVEZWZhdWx0cycpO1xuICAgICAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsICdjYWxlbmRhcicsIG9wdGlvbnMuY2FsZW5kYXIpO1xuICAgIH1cblxuICAgIC8vIHdlIG5lZWQgc29tZSBvZiB0aGUgb3RoZXIgZnVuY3Rpb25zIHNldENvbnZlcnQgYXR0YWNoZXMsIGJ1dCBmb3JcbiAgICAvLyBwYXRoIGZpbmRpbmcsIG92ZXJyaWRlIHBpeGVsIHNjYWxpbmcgdG8gc2ltcGxlIHBhc3N0aHJvdWdoIChpZGVudGl0eSlcbiAgICBzZXRDb252ZXJ0KGNvbnRhaW5lck91dCwgb3B0aW9ucy5mdWxsTGF5b3V0KTtcbiAgICBjb250YWluZXJPdXQuYzJwID0gTGliLmlkZW50aXR5O1xuXG4gICAgdmFyIGRmbHRDb2xvciA9IGNvZXJjZSgnY29sb3InLCBvcHRpb25zLmRmbHRDb2xvcik7XG4gICAgLy8gaWYgYXhpcy5jb2xvciB3YXMgcHJvdmlkZWQsIHVzZSBpdCBmb3IgZm9udHMgdG9vOyBvdGhlcndpc2UsXG4gICAgLy8gaW5oZXJpdCBmcm9tIGdsb2JhbCBmb250IGNvbG9yIGluIGNhc2UgdGhhdCB3YXMgcHJvdmlkZWQuXG4gICAgdmFyIGRmbHRGb250Q29sb3IgPSAoZGZsdENvbG9yID09PSBjb250YWluZXJJbi5jb2xvcikgPyBkZmx0Q29sb3IgOiBmb250LmNvbG9yO1xuXG4gICAgY29lcmNlKCd0aXRsZScpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBmb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChmb250LnNpemUgKiAxLjIpLFxuICAgICAgICBjb2xvcjogZGZsdEZvbnRDb2xvclxuICAgIH0pO1xuXG4gICAgY29lcmNlKCd0aXRsZW9mZnNldCcpO1xuXG4gICAgY29lcmNlKCd0aWNrYW5nbGUnKTtcblxuICAgIHZhciBhdXRvUmFuZ2UgPSBjb2VyY2UoJ2F1dG9yYW5nZScsICFjb250YWluZXJPdXQuaXNWYWxpZFJhbmdlKGNvbnRhaW5lckluLnJhbmdlKSk7XG5cbiAgICBpZihhdXRvUmFuZ2UpIGNvZXJjZSgncmFuZ2Vtb2RlJyk7XG5cbiAgICBjb2VyY2UoJ3JhbmdlJyk7XG4gICAgY29udGFpbmVyT3V0LmNsZWFuUmFuZ2UoKTtcblxuICAgIGNvZXJjZSgnZml4ZWRyYW5nZScpO1xuXG4gICAgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUpO1xuICAgIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zKTtcbiAgICBoYW5kbGVDYXRlZ29yeU9yZGVyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCB7XG4gICAgICAgIGRhdGE6IG9wdGlvbnMuZGF0YSxcbiAgICAgICAgZGF0YUF0dHI6IGxldHRlclxuICAgIH0pO1xuXG4gICAgdmFyIGdyaWRDb2xvciA9IGNvZXJjZTIoJ2dyaWRjb2xvcicsIGFkZE9wYWNpdHkoZGZsdENvbG9yLCAwLjMpKTtcbiAgICB2YXIgZ3JpZFdpZHRoID0gY29lcmNlMignZ3JpZHdpZHRoJyk7XG4gICAgdmFyIHNob3dHcmlkID0gY29lcmNlKCdzaG93Z3JpZCcpO1xuXG4gICAgaWYoIXNob3dHcmlkKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZGNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmdyaWR3aWR0aDtcbiAgICB9XG5cbiAgICB2YXIgc3RhcnRMaW5lQ29sb3IgPSBjb2VyY2UyKCdzdGFydGxpbmVjb2xvcicsIGRmbHRDb2xvcik7XG4gICAgdmFyIHN0YXJ0TGluZVdpZHRoID0gY29lcmNlMignc3RhcnRsaW5ld2lkdGgnLCBncmlkV2lkdGgpO1xuICAgIHZhciBzaG93U3RhcnRMaW5lID0gY29lcmNlKCdzdGFydGxpbmUnLCBjb250YWluZXJPdXQuc2hvd2dyaWQgfHwgISFzdGFydExpbmVDb2xvciB8fCAhIXN0YXJ0TGluZVdpZHRoKTtcblxuICAgIGlmKCFzaG93U3RhcnRMaW5lKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuc3RhcnRsaW5lY29sb3I7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuc3RhcnRsaW5ld2lkdGg7XG4gICAgfVxuXG4gICAgdmFyIGVuZExpbmVDb2xvciA9IGNvZXJjZTIoJ2VuZGxpbmVjb2xvcicsIGRmbHRDb2xvcik7XG4gICAgdmFyIGVuZExpbmVXaWR0aCA9IGNvZXJjZTIoJ2VuZGxpbmV3aWR0aCcsIGdyaWRXaWR0aCk7XG4gICAgdmFyIHNob3dFbmRMaW5lID0gY29lcmNlKCdlbmRsaW5lJywgY29udGFpbmVyT3V0LnNob3dncmlkIHx8ICEhZW5kTGluZUNvbG9yIHx8ICEhZW5kTGluZVdpZHRoKTtcblxuICAgIGlmKCFzaG93RW5kTGluZSkge1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmVuZGxpbmVjb2xvcjtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5lbmRsaW5ld2lkdGg7XG4gICAgfVxuXG4gICAgaWYoIXNob3dHcmlkKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZGNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmdyaWRXaWR0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2VyY2UoJ21pbm9yZ3JpZGNvdW50Jyk7XG4gICAgICAgIGNvZXJjZSgnbWlub3Jncmlkd2lkdGgnLCBncmlkV2lkdGgpO1xuICAgICAgICBjb2VyY2UoJ21pbm9yZ3JpZGNvbG9yJywgYWRkT3BhY2l0eShncmlkQ29sb3IsIDAuMDYpKTtcblxuICAgICAgICBpZighY29udGFpbmVyT3V0Lm1pbm9yZ3JpZGNvdW50KSB7XG4gICAgICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0Lm1pbm9yZ3JpZHdpZHRoO1xuICAgICAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5taW5vcmdyaWRjb2xvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNvbnRhaW5lck91dC5zaG93dGlja2xhYmVscyA9PT0gJ25vbmUnKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja2ZvbnQ7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja2FuZ2xlO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3dleHBvbmVudDtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5leHBvbmVudGZvcm1hdDtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrZm9ybWF0O1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3d0aWNrc3VmZml4O1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3d0aWNrcHJlZml4O1xuICAgIH1cblxuICAgIGlmKCFjb250YWluZXJPdXQuc2hvd3RpY2tzdWZmaXgpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrc3VmZml4O1xuICAgIH1cblxuICAgIGlmKCFjb250YWluZXJPdXQuc2hvd3RpY2twcmVmaXgpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrcHJlZml4O1xuICAgIH1cblxuICAgIC8vIEl0IG5lZWRzIHRvIGJlIGNvZXJjZWQsIHRoZW4gc29tZXRoaW5nIGFib3ZlIG92ZXJyaWRlcyB0aGlzIGRlZXAgaW4gdGhlIGF4aXMgY29kZSxcbiAgICAvLyBidXQgbm8sIHdlICphY3R1YWxseSogd2FudCB0byBjb2VyY2UgdGhpcy5cbiAgICBjb2VyY2UoJ3RpY2ttb2RlJyk7XG5cbiAgICBpZighY29udGFpbmVyT3V0LnRpdGxlIHx8IChjb250YWluZXJPdXQudGl0bGUgJiYgY29udGFpbmVyT3V0LnRpdGxlLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aXRsZWZvbnQ7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGl0bGVvZmZzZXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lck91dDtcbn07XG5cbmZ1bmN0aW9uIHNldEF1dG9UeXBlKGF4LCBkYXRhKSB7XG4gICAgLy8gbmV3IGxvZ2ljOiBsZXQgcGVvcGxlIHNwZWNpZnkgYW55IHR5cGUgdGhleSB3YW50LFxuICAgIC8vIG9ubHkgYXV0b3R5cGUgaWYgdHlwZSBpcyAnLSdcbiAgICBpZihheC50eXBlICE9PSAnLScpIHJldHVybjtcblxuICAgIHZhciBpZCA9IGF4Ll9pZCxcbiAgICAgICAgYXhMZXR0ZXIgPSBpZC5jaGFyQXQoMCk7XG5cbiAgICB2YXIgY2FsQXR0ciA9IGF4TGV0dGVyICsgJ2NhbGVuZGFyJyxcbiAgICAgICAgY2FsZW5kYXIgPSBheFtjYWxBdHRyXTtcblxuICAgIGF4LnR5cGUgPSBhdXRvVHlwZShkYXRhLCBjYWxlbmRhcik7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBpc0FycmF5MUQgPSByZXF1aXJlKCcuLi8uLi9saWInKS5pc0FycmF5MUQ7XG52YXIgY2hlYXRlckJhc2lzID0gcmVxdWlyZSgnLi9jaGVhdGVyX2Jhc2lzJyk7XG52YXIgYXJyYXlNaW5tYXggPSByZXF1aXJlKCcuL2FycmF5X21pbm1heCcpO1xudmFyIGNhbGNHcmlkbGluZXMgPSByZXF1aXJlKCcuL2NhbGNfZ3JpZGxpbmVzJyk7XG52YXIgY2FsY0xhYmVscyA9IHJlcXVpcmUoJy4vY2FsY19sYWJlbHMnKTtcbnZhciBjYWxjQ2xpcFBhdGggPSByZXF1aXJlKCcuL2NhbGNfY2xpcHBhdGgnKTtcbnZhciBjbGVhbjJkQXJyYXkgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NsZWFuXzJkX2FycmF5Jyk7XG52YXIgc21vb3RoRmlsbDJkQXJyYXkgPSByZXF1aXJlKCcuL3Ntb290aF9maWxsXzJkX2FycmF5Jyk7XG52YXIgY29udmVydENvbHVtbkRhdGEgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NvbnZlcnRfY29sdW1uX3h5eicpO1xudmFyIHNldENvbnZlcnQgPSByZXF1aXJlKCcuL3NldF9jb252ZXJ0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyk7XG4gICAgdmFyIGFheCA9IHRyYWNlLmFheGlzO1xuICAgIHZhciBiYXggPSB0cmFjZS5iYXhpcztcblxuICAgIHZhciB4ID0gdHJhY2UueDtcbiAgICB2YXIgeSA9IHRyYWNlLnk7XG4gICAgdmFyIGNvbHMgPSBbXTtcbiAgICBpZih4ICYmIGlzQXJyYXkxRCh4KSkgY29scy5wdXNoKCd4Jyk7XG4gICAgaWYoeSAmJiBpc0FycmF5MUQoeSkpIGNvbHMucHVzaCgneScpO1xuXG4gICAgaWYoY29scy5sZW5ndGgpIHtcbiAgICAgICAgY29udmVydENvbHVtbkRhdGEodHJhY2UsIGFheCwgYmF4LCAnYScsICdiJywgY29scyk7XG4gICAgfVxuXG4gICAgdmFyIGEgPSB0cmFjZS5fYSA9IHRyYWNlLl9hIHx8IHRyYWNlLmE7XG4gICAgdmFyIGIgPSB0cmFjZS5fYiA9IHRyYWNlLl9iIHx8IHRyYWNlLmI7XG4gICAgeCA9IHRyYWNlLl94IHx8IHRyYWNlLng7XG4gICAgeSA9IHRyYWNlLl95IHx8IHRyYWNlLnk7XG5cbiAgICB2YXIgdCA9IHt9O1xuXG4gICAgaWYodHJhY2UuX2NoZWF0ZXIpIHtcbiAgICAgICAgdmFyIGF2YWxzID0gYWF4LmNoZWF0ZXJ0eXBlID09PSAnaW5kZXgnID8gYS5sZW5ndGggOiBhO1xuICAgICAgICB2YXIgYnZhbHMgPSBiYXguY2hlYXRlcnR5cGUgPT09ICdpbmRleCcgPyBiLmxlbmd0aCA6IGI7XG4gICAgICAgIHggPSBjaGVhdGVyQmFzaXMoYXZhbHMsIGJ2YWxzLCB0cmFjZS5jaGVhdGVyc2xvcGUpO1xuICAgIH1cblxuICAgIHRyYWNlLl94ID0geCA9IGNsZWFuMmRBcnJheSh4KTtcbiAgICB0cmFjZS5feSA9IHkgPSBjbGVhbjJkQXJyYXkoeSk7XG5cbiAgICAvLyBGaWxsIGluIGFueSB1bmRlZmluZWQgdmFsdWVzIHdpdGggZWxsaXB0aWMgc21vb3RoaW5nLiBUaGlzIGRvZXNuJ3QgdGFrZVxuICAgIC8vIGludG8gYWNjb3VudCB0aGUgc3BhY2luZyBvZiB0aGUgdmFsdWVzLiBUaGF0IGlzLCB0aGUgZGVyaXZhdGl2ZXMgc2hvdWxkXG4gICAgLy8gYmUgbW9kaWZpZWQgdG8gdXNlIGEgYW5kIGIgdmFsdWVzLiBJdCdzIG5vdCB0aGF0IGhhcmQsIGJ1dCB0aGlzIGlzIGFscmVhZHlcbiAgICAvLyBtb2RlcmF0ZSBvdmVya2lsbCBmb3IganVzdCBmaWxsaW5nIGluIG1pc3NpbmcgdmFsdWVzLlxuICAgIHNtb290aEZpbGwyZEFycmF5KHgsIGEsIGIpO1xuICAgIHNtb290aEZpbGwyZEFycmF5KHksIGEsIGIpO1xuXG4gICAgc2V0Q29udmVydCh0cmFjZSk7XG5cbiAgICAvLyBjcmVhdGUgY29udmVyc2lvbiBmdW5jdGlvbnMgdGhhdCBkZXBlbmQgb24gdGhlIGRhdGFcbiAgICB0cmFjZS5zZXRTY2FsZSgpO1xuXG4gICAgLy8gVGhpcyBpcyBhIHJhdGhlciBleHBlbnNpdmUgc2Nhbi4gTm90aGluZyBndWFyYW50ZWVzIG1vbm90b25pY2l0eSxcbiAgICAvLyBzbyB3ZSBuZWVkIHRvIHNjYW4gdGhyb3VnaCBhbGwgZGF0YSB0byBnZXQgcHJvcGVyIHJhbmdlczpcbiAgICB2YXIgeHJhbmdlID0gYXJyYXlNaW5tYXgoeCk7XG4gICAgdmFyIHlyYW5nZSA9IGFycmF5TWlubWF4KHkpO1xuXG4gICAgdmFyIGR4ID0gMC41ICogKHhyYW5nZVsxXSAtIHhyYW5nZVswXSk7XG4gICAgdmFyIHhjID0gMC41ICogKHhyYW5nZVsxXSArIHhyYW5nZVswXSk7XG5cbiAgICB2YXIgZHkgPSAwLjUgKiAoeXJhbmdlWzFdIC0geXJhbmdlWzBdKTtcbiAgICB2YXIgeWMgPSAwLjUgKiAoeXJhbmdlWzFdICsgeXJhbmdlWzBdKTtcblxuICAgIC8vIEV4cGFuZCB0aGUgYXhlcyB0byBmaXQgdGhlIHBsb3QsIGV4Y2VwdCBqdXN0IGdyb3cgaXQgYnkgYSBmYWN0b3Igb2YgMS4zXG4gICAgLy8gYmVjYXVzZSB0aGUgbGFiZWxzIHNob3VsZCBiZSB0YWtlbiBpbnRvIGFjY291bnQgZXhjZXB0IHRoYXQncyBkaWZmaWN1bHRcbiAgICAvLyBoZW5jZSAxLjMuXG4gICAgdmFyIGdyb3cgPSAxLjM7XG4gICAgeHJhbmdlID0gW3hjIC0gZHggKiBncm93LCB4YyArIGR4ICogZ3Jvd107XG4gICAgeXJhbmdlID0gW3ljIC0gZHkgKiBncm93LCB5YyArIGR5ICogZ3Jvd107XG5cbiAgICB0cmFjZS5fZXh0cmVtZXNbeGEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHhhLCB4cmFuZ2UsIHtwYWRkZWQ6IHRydWV9KTtcbiAgICB0cmFjZS5fZXh0cmVtZXNbeWEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHlhLCB5cmFuZ2UsIHtwYWRkZWQ6IHRydWV9KTtcblxuICAgIC8vIEVudW1lcmF0ZSB0aGUgZ3JpZGxpbmVzLCBib3RoIG1ham9yIGFuZCBtaW5vciwgYW5kIHN0b3JlIHRoZW0gb24gdGhlIHRyYWNlXG4gICAgLy8gb2JqZWN0OlxuICAgIGNhbGNHcmlkbGluZXModHJhY2UsICdhJywgJ2InKTtcbiAgICBjYWxjR3JpZGxpbmVzKHRyYWNlLCAnYicsICdhJyk7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHRleHQgbGFiZWxzIGZvciBlYWNoIG1ham9yIGdyaWRsaW5lIGFuZCBzdG9yZSB0aGVtIG9uIHRoZVxuICAgIC8vIHRyYWNlIG9iamVjdDpcbiAgICBjYWxjTGFiZWxzKHRyYWNlLCBhYXgpO1xuICAgIGNhbGNMYWJlbHModHJhY2UsIGJheCk7XG5cbiAgICAvLyBUYWJ1bGF0ZSBwb2ludHMgZm9yIHRoZSBmb3VyIHNlZ21lbnRzIHRoYXQgYm91bmQgdGhlIGF4ZXMgc28gdGhhdCB3ZSBjYW5cbiAgICAvLyBtYXAgdG8gcGl4ZWwgY29vcmRpbmF0ZXMgaW4gdGhlIHBsb3QgZnVuY3Rpb24gYW5kIGNyZWF0ZSBhIGNsaXAgcmVjdDpcbiAgICB0LmNsaXBzZWdtZW50cyA9IGNhbGNDbGlwUGF0aCh0cmFjZS5feGN0cmwsIHRyYWNlLl95Y3RybCwgYWF4LCBiYXgpO1xuXG4gICAgdC54ID0geDtcbiAgICB0LnkgPSB5O1xuICAgIHQuYSA9IGE7XG4gICAgdC5iID0gYjtcblxuICAgIHJldHVybiBbdF07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUNsaXBQYXRoKHhjdHJsLCB5Y3RybCwgYWF4LCBiYXgpIHtcbiAgICB2YXIgaSwgeCwgeTtcbiAgICB2YXIgc2VnbWVudHMgPSBbXTtcblxuICAgIHZhciBhc21vb3RoaW5nID0gISFhYXguc21vb3RoaW5nO1xuICAgIHZhciBic21vb3RoaW5nID0gISFiYXguc21vb3RoaW5nO1xuICAgIHZhciBuZWExID0geGN0cmxbMF0ubGVuZ3RoIC0gMTtcbiAgICB2YXIgbmViMSA9IHhjdHJsLmxlbmd0aCAtIDE7XG5cbiAgICAvLyBBbG9uZyB0aGUgbG93ZXIgYSBheGlzOlxuICAgIGZvcihpID0gMCwgeCA9IFtdLCB5ID0gW107IGkgPD0gbmVhMTsgaSsrKSB7XG4gICAgICAgIHhbaV0gPSB4Y3RybFswXVtpXTtcbiAgICAgICAgeVtpXSA9IHljdHJsWzBdW2ldO1xuICAgIH1cbiAgICBzZWdtZW50cy5wdXNoKHt4OiB4LCB5OiB5LCBiaWN1YmljOiBhc21vb3RoaW5nfSk7XG5cbiAgICAvLyBBbG9uZyB0aGUgdXBwZXIgYiBheGlzOlxuICAgIGZvcihpID0gMCwgeCA9IFtdLCB5ID0gW107IGkgPD0gbmViMTsgaSsrKSB7XG4gICAgICAgIHhbaV0gPSB4Y3RybFtpXVtuZWExXTtcbiAgICAgICAgeVtpXSA9IHljdHJsW2ldW25lYTFdO1xuICAgIH1cbiAgICBzZWdtZW50cy5wdXNoKHt4OiB4LCB5OiB5LCBiaWN1YmljOiBic21vb3RoaW5nfSk7XG5cbiAgICAvLyBCYWNrd2FyZHMgYWxvbmcgdGhlIHVwcGVyIGEgYXhpczpcbiAgICBmb3IoaSA9IG5lYTEsIHggPSBbXSwgeSA9IFtdOyBpID49IDA7IGktLSkge1xuICAgICAgICB4W25lYTEgLSBpXSA9IHhjdHJsW25lYjFdW2ldO1xuICAgICAgICB5W25lYTEgLSBpXSA9IHljdHJsW25lYjFdW2ldO1xuICAgIH1cbiAgICBzZWdtZW50cy5wdXNoKHt4OiB4LCB5OiB5LCBiaWN1YmljOiBhc21vb3RoaW5nfSk7XG5cbiAgICAvLyBCYWNrd2FyZHMgYWxvbmcgdGhlIGxvd2VyIGIgYXhpczpcbiAgICBmb3IoaSA9IG5lYjEsIHggPSBbXSwgeSA9IFtdOyBpID49IDA7IGktLSkge1xuICAgICAgICB4W25lYjEgLSBpXSA9IHhjdHJsW2ldWzBdO1xuICAgICAgICB5W25lYjEgLSBpXSA9IHljdHJsW2ldWzBdO1xuICAgIH1cbiAgICBzZWdtZW50cy5wdXNoKHt4OiB4LCB5OiB5LCBiaWN1YmljOiBic21vb3RoaW5nfSk7XG5cbiAgICByZXR1cm4gc2VnbWVudHM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNHcmlkbGluZXModHJhY2UsIGF4aXNMZXR0ZXIsIGNyb3NzQXhpc0xldHRlcikge1xuICAgIHZhciBpLCBqLCBqMDtcbiAgICB2YXIgZXBzLCBib3VuZHMsIG4xLCBuMiwgbiwgdmFsdWUsIHY7XG4gICAgdmFyIGoxLCB2MCwgdjEsIGQ7XG5cbiAgICB2YXIgZGF0YSA9IHRyYWNlWydfJyArIGF4aXNMZXR0ZXJdO1xuICAgIHZhciBheGlzID0gdHJhY2VbYXhpc0xldHRlciArICdheGlzJ107XG5cbiAgICB2YXIgZ3JpZGxpbmVzID0gYXhpcy5fZ3JpZGxpbmVzID0gW107XG4gICAgdmFyIG1pbm9yZ3JpZGxpbmVzID0gYXhpcy5fbWlub3JncmlkbGluZXMgPSBbXTtcbiAgICB2YXIgYm91bmRhcnlsaW5lcyA9IGF4aXMuX2JvdW5kYXJ5bGluZXMgPSBbXTtcblxuICAgIHZhciBjcm9zc0RhdGEgPSB0cmFjZVsnXycgKyBjcm9zc0F4aXNMZXR0ZXJdO1xuICAgIHZhciBjcm9zc0F4aXMgPSB0cmFjZVtjcm9zc0F4aXNMZXR0ZXIgKyAnYXhpcyddO1xuXG4gICAgaWYoYXhpcy50aWNrbW9kZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICBheGlzLnRpY2t2YWxzID0gZGF0YS5zbGljZSgpO1xuICAgIH1cblxuICAgIHZhciB4Y3AgPSB0cmFjZS5feGN0cmw7XG4gICAgdmFyIHljcCA9IHRyYWNlLl95Y3RybDtcbiAgICB2YXIgbmVhID0geGNwWzBdLmxlbmd0aDtcbiAgICB2YXIgbmViID0geGNwLmxlbmd0aDtcbiAgICB2YXIgbmEgPSB0cmFjZS5fYS5sZW5ndGg7XG4gICAgdmFyIG5iID0gdHJhY2UuX2IubGVuZ3RoO1xuXG4gICAgQXhlcy5wcmVwVGlja3MoYXhpcyk7XG5cbiAgICAvLyBkb24ndCBsZWF2ZSB0aWNrdmFscyBpbiBheGlzIGxvb2tpbmcgbGlrZSBhbiBhdHRyaWJ1dGVcbiAgICBpZihheGlzLnRpY2ttb2RlID09PSAnYXJyYXknKSBkZWxldGUgYXhpcy50aWNrdmFscztcblxuICAgIC8vIFRoZSBkZWZhdWx0IGlzIGFuIGVtcHR5IGFycmF5IHRoYXQgd2lsbCBjYXVzZSB0aGUgam9pbiB0byByZW1vdmUgdGhlIGdyaWRsaW5lIGlmXG4gICAgLy8gaXQncyBqdXN0IGRpc2FwcGVhcmVkOlxuICAgIC8vIGF4aXMuX3N0YXJ0bGluZSA9IGF4aXMuX2VuZGxpbmUgPSBbXTtcblxuICAgIC8vIElmIHRoZSBjcm9zcyBheGlzIHVzZXMgYmljdWJpYyBpbnRlcnBvbGF0aW9uLCB0aGVuIHRoZSBncmlkXG4gICAgLy8gbGluZXMgZmFsbCBvbmNlIGV2ZXJ5IHRocmVlIGV4cGFuZGVkIGdyaWQgcm93L2NvbHM6XG4gICAgdmFyIHN0cmlkZSA9IGF4aXMuc21vb3RoaW5nID8gMyA6IDE7XG5cbiAgICBmdW5jdGlvbiBjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKHZhbHVlKSB7XG4gICAgICAgIHZhciBpLCBqLCBqMCwgdGosIHB4eSwgaTAsIHRpLCB4eSwgZHh5ZGkwLCBkeHlkaTEsIGR4eWRqMCwgZHh5ZGoxO1xuICAgICAgICB2YXIgeHBvaW50cyA9IFtdO1xuICAgICAgICB2YXIgeXBvaW50cyA9IFtdO1xuICAgICAgICB2YXIgcmV0ID0ge307XG4gICAgICAgIC8vIFNlYXJjaCBmb3IgdGhlIGZyYWN0aW9uYWwgZ3JpZCBpbmRleCBnaXZpbmcgdGhpcyBsaW5lOlxuICAgICAgICBpZihheGlzTGV0dGVyID09PSAnYicpIHtcbiAgICAgICAgICAgIC8vIEZvciB0aGUgcG9zaXRpb24gd2UgdXNlIGp1c3QgdGhlIGktaiBjb29yZGluYXRlczpcbiAgICAgICAgICAgIGogPSB0cmFjZS5iMmoodmFsdWUpO1xuXG4gICAgICAgICAgICAvLyBUaGUgZGVyaXZhdGl2ZXMgZm9yIGNhdG11bGwtcm9tIHNwbGluZXMgYXJlIGRpc2NvbnRpbnVvdXMgYWNyb3NzIGNlbGxcbiAgICAgICAgICAgIC8vIGJvdW5kYXJpZXMgdGhvdWdoLCBzbyB3ZSBuZWVkIHRvIHByb3ZpZGUgYm90aCB0aGUgY2VsbCBhbmQgdGhlIHBvc2l0aW9uXG4gICAgICAgICAgICAvLyB3aXRoaW4gdGhlIGNlbGwgc2VwYXJhdGVseTpcbiAgICAgICAgICAgIGowID0gTWF0aC5mbG9vcihNYXRoLm1heCgwLCBNYXRoLm1pbihuYiAtIDIsIGopKSk7XG4gICAgICAgICAgICB0aiA9IGogLSBqMDtcblxuICAgICAgICAgICAgcmV0Lmxlbmd0aCA9IG5iO1xuICAgICAgICAgICAgcmV0LmNyb3NzTGVuZ3RoID0gbmE7XG5cbiAgICAgICAgICAgIHJldC54eSA9IGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZXZhbHh5KFtdLCBpLCBqKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldC5keHkgPSBmdW5jdGlvbihpMCwgdGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZHh5ZGkoW10sIGkwLCBqMCwgdGksIHRqKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG5hOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpMCA9IE1hdGgubWluKG5hIC0gMiwgaSk7XG4gICAgICAgICAgICAgICAgdGkgPSBpIC0gaTA7XG4gICAgICAgICAgICAgICAgeHkgPSB0cmFjZS5ldmFseHkoW10sIGksIGopO1xuXG4gICAgICAgICAgICAgICAgaWYoY3Jvc3NBeGlzLnNtb290aGluZyAmJiBpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaXJzdCBjb250cm9sIHBvaW50OlxuICAgICAgICAgICAgICAgICAgICBkeHlkaTAgPSB0cmFjZS5keHlkaShbXSwgaSAtIDEsIGowLCAwLCB0aik7XG4gICAgICAgICAgICAgICAgICAgIHhwb2ludHMucHVzaChweHlbMF0gKyBkeHlkaTBbMF0gLyAzKTtcbiAgICAgICAgICAgICAgICAgICAgeXBvaW50cy5wdXNoKHB4eVsxXSArIGR4eWRpMFsxXSAvIDMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNlY29uZCBjb250cm9sIHBvaW50OlxuICAgICAgICAgICAgICAgICAgICBkeHlkaTEgPSB0cmFjZS5keHlkaShbXSwgaSAtIDEsIGowLCAxLCB0aik7XG4gICAgICAgICAgICAgICAgICAgIHhwb2ludHMucHVzaCh4eVswXSAtIGR4eWRpMVswXSAvIDMpO1xuICAgICAgICAgICAgICAgICAgICB5cG9pbnRzLnB1c2goeHlbMV0gLSBkeHlkaTFbMV0gLyAzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB4cG9pbnRzLnB1c2goeHlbMF0pO1xuICAgICAgICAgICAgICAgIHlwb2ludHMucHVzaCh4eVsxXSk7XG5cbiAgICAgICAgICAgICAgICBweHkgPSB4eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGkgPSB0cmFjZS5hMmkodmFsdWUpO1xuICAgICAgICAgICAgaTAgPSBNYXRoLmZsb29yKE1hdGgubWF4KDAsIE1hdGgubWluKG5hIC0gMiwgaSkpKTtcbiAgICAgICAgICAgIHRpID0gaSAtIGkwO1xuXG4gICAgICAgICAgICByZXQubGVuZ3RoID0gbmE7XG4gICAgICAgICAgICByZXQuY3Jvc3NMZW5ndGggPSBuYjtcblxuICAgICAgICAgICAgcmV0Lnh5ID0gZnVuY3Rpb24oaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS5ldmFseHkoW10sIGksIGopO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0LmR4eSA9IGZ1bmN0aW9uKGowLCB0aikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS5keHlkaihbXSwgaTAsIGowLCB0aSwgdGopO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbmI7IGorKykge1xuICAgICAgICAgICAgICAgIGowID0gTWF0aC5taW4obmIgLSAyLCBqKTtcbiAgICAgICAgICAgICAgICB0aiA9IGogLSBqMDtcbiAgICAgICAgICAgICAgICB4eSA9IHRyYWNlLmV2YWx4eShbXSwgaSwgaik7XG5cbiAgICAgICAgICAgICAgICBpZihjcm9zc0F4aXMuc21vb3RoaW5nICYmIGogPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcnN0IGNvbnRyb2wgcG9pbnQ6XG4gICAgICAgICAgICAgICAgICAgIGR4eWRqMCA9IHRyYWNlLmR4eWRqKFtdLCBpMCwgaiAtIDEsIHRpLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgeHBvaW50cy5wdXNoKHB4eVswXSArIGR4eWRqMFswXSAvIDMpO1xuICAgICAgICAgICAgICAgICAgICB5cG9pbnRzLnB1c2gocHh5WzFdICsgZHh5ZGowWzFdIC8gMyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2Vjb25kIGNvbnRyb2wgcG9pbnQ6XG4gICAgICAgICAgICAgICAgICAgIGR4eWRqMSA9IHRyYWNlLmR4eWRqKFtdLCBpMCwgaiAtIDEsIHRpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgeHBvaW50cy5wdXNoKHh5WzBdIC0gZHh5ZGoxWzBdIC8gMyk7XG4gICAgICAgICAgICAgICAgICAgIHlwb2ludHMucHVzaCh4eVsxXSAtIGR4eWRqMVsxXSAvIDMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHhwb2ludHMucHVzaCh4eVswXSk7XG4gICAgICAgICAgICAgICAgeXBvaW50cy5wdXNoKHh5WzFdKTtcblxuICAgICAgICAgICAgICAgIHB4eSA9IHh5O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0LmF4aXNMZXR0ZXIgPSBheGlzTGV0dGVyO1xuICAgICAgICByZXQuYXhpcyA9IGF4aXM7XG4gICAgICAgIHJldC5jcm9zc0F4aXMgPSBjcm9zc0F4aXM7XG4gICAgICAgIHJldC52YWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXQuY29uc3R2YXIgPSBjcm9zc0F4aXNMZXR0ZXI7XG4gICAgICAgIHJldC5pbmRleCA9IG47XG4gICAgICAgIHJldC54ID0geHBvaW50cztcbiAgICAgICAgcmV0LnkgPSB5cG9pbnRzO1xuICAgICAgICByZXQuc21vb3RoaW5nID0gY3Jvc3NBeGlzLnNtb290aGluZztcblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbnN0cnVjdEFycmF5R3JpZGxpbmUoaWR4KSB7XG4gICAgICAgIHZhciBqLCBpMCwgajAsIHRpLCB0ajtcbiAgICAgICAgdmFyIHhwb2ludHMgPSBbXTtcbiAgICAgICAgdmFyIHlwb2ludHMgPSBbXTtcbiAgICAgICAgdmFyIHJldCA9IHt9O1xuICAgICAgICByZXQubGVuZ3RoID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIHJldC5jcm9zc0xlbmd0aCA9IGNyb3NzRGF0YS5sZW5ndGg7XG5cbiAgICAgICAgaWYoYXhpc0xldHRlciA9PT0gJ2InKSB7XG4gICAgICAgICAgICBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKG5iIC0gMiwgaWR4KSk7XG4gICAgICAgICAgICB0aiA9IE1hdGgubWluKDEsIE1hdGgubWF4KDAsIGlkeCAtIGowKSk7XG5cbiAgICAgICAgICAgIHJldC54eSA9IGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZXZhbHh5KFtdLCBpLCBpZHgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0LmR4eSA9IGZ1bmN0aW9uKGkwLCB0aSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS5keHlkaShbXSwgaTAsIGowLCB0aSwgdGopO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gSW4gdGhlIHRpY2ttb2RlOiBhcnJheSBjYXNlLCB0aGlzIG9wZXJhdGlvbiBpcyBhIHNpbXBsZVxuICAgICAgICAgICAgLy8gdHJhbnNmZXIgb2YgZGF0YTpcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5lYTsgaisrKSB7XG4gICAgICAgICAgICAgICAgeHBvaW50c1tqXSA9IHhjcFtpZHggKiBzdHJpZGVdW2pdO1xuICAgICAgICAgICAgICAgIHlwb2ludHNbal0gPSB5Y3BbaWR4ICogc3RyaWRlXVtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obmEgLSAyLCBpZHgpKTtcbiAgICAgICAgICAgIHRpID0gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgaWR4IC0gaTApKTtcblxuICAgICAgICAgICAgcmV0Lnh5ID0gZnVuY3Rpb24oaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS5ldmFseHkoW10sIGlkeCwgaik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXQuZHh5ID0gZnVuY3Rpb24oajAsIHRqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNlLmR4eWRqKFtdLCBpMCwgajAsIHRpLCB0aik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBJbiB0aGUgdGlja21vZGU6IGFycmF5IGNhc2UsIHRoaXMgb3BlcmF0aW9uIGlzIGEgc2ltcGxlXG4gICAgICAgICAgICAvLyB0cmFuc2ZlciBvZiBkYXRhOlxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbmViOyBqKyspIHtcbiAgICAgICAgICAgICAgICB4cG9pbnRzW2pdID0geGNwW2pdW2lkeCAqIHN0cmlkZV07XG4gICAgICAgICAgICAgICAgeXBvaW50c1tqXSA9IHljcFtqXVtpZHggKiBzdHJpZGVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0LmF4aXNMZXR0ZXIgPSBheGlzTGV0dGVyO1xuICAgICAgICByZXQuYXhpcyA9IGF4aXM7XG4gICAgICAgIHJldC5jcm9zc0F4aXMgPSBjcm9zc0F4aXM7XG4gICAgICAgIHJldC52YWx1ZSA9IGRhdGFbaWR4XTtcbiAgICAgICAgcmV0LmNvbnN0dmFyID0gY3Jvc3NBeGlzTGV0dGVyO1xuICAgICAgICByZXQuaW5kZXggPSBpZHg7XG4gICAgICAgIHJldC54ID0geHBvaW50cztcbiAgICAgICAgcmV0LnkgPSB5cG9pbnRzO1xuICAgICAgICByZXQuc21vb3RoaW5nID0gY3Jvc3NBeGlzLnNtb290aGluZztcblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmKGF4aXMudGlja21vZGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgLy8gdmFyIGowID0gYXhpcy5zdGFydGxpbmUgPyAxIDogMDtcbiAgICAgICAgLy8gdmFyIGoxID0gZGF0YS5sZW5ndGggLSAoYXhpcy5lbmRsaW5lID8gMSA6IDApO1xuXG4gICAgICAgIGVwcyA9IDVlLTE1O1xuICAgICAgICBib3VuZHMgPSBbXG4gICAgICAgICAgICBNYXRoLmZsb29yKCgoZGF0YS5sZW5ndGggLSAxKSAtIGF4aXMuYXJyYXl0aWNrMCkgLyBheGlzLmFycmF5ZHRpY2sgKiAoMSArIGVwcykpLFxuICAgICAgICAgICAgTWF0aC5jZWlsKCgtIGF4aXMuYXJyYXl0aWNrMCkgLyBheGlzLmFycmF5ZHRpY2sgLyAoMSArIGVwcykpXG4gICAgICAgIF0uc29ydChmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGEgLSBiO30pO1xuXG4gICAgICAgIC8vIFVucGFjayBzb3J0ZWQgdmFsdWVzIHNvIHdlIGNhbiBiZSBzdXJlIHRvIGF2b2lkIGluZmluaXRlIGxvb3BzIGlmIHNvbWV0aGluZ1xuICAgICAgICAvLyBpcyBiYWNrd2FyZHM6XG4gICAgICAgIG4xID0gYm91bmRzWzBdIC0gMTtcbiAgICAgICAgbjIgPSBib3VuZHNbMV0gKyAxO1xuXG4gICAgICAgIC8vIElmIHRoZSBheGVzIGZhbGwgYWxvbmcgYXJyYXkgbGluZXMsIHRoZW4gdGhpcyBpcyBhIG11Y2ggc2ltcGxlciBwcm9jZXNzIHNpbmNlXG4gICAgICAgIC8vIHdlIGFscmVhZHkgaGF2ZSBhbGwgdGhlIGNvbnRyb2wgcG9pbnRzIHdlIG5lZWRcbiAgICAgICAgZm9yKG4gPSBuMTsgbiA8IG4yOyBuKyspIHtcbiAgICAgICAgICAgIGogPSBheGlzLmFycmF5dGljazAgKyBheGlzLmFycmF5ZHRpY2sgKiBuO1xuICAgICAgICAgICAgaWYoaiA8IDAgfHwgaiA+IGRhdGEubGVuZ3RoIC0gMSkgY29udGludWU7XG4gICAgICAgICAgICBncmlkbGluZXMucHVzaChleHRlbmRGbGF0KGNvbnN0cnVjdEFycmF5R3JpZGxpbmUoaiksIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogYXhpcy5ncmlkY29sb3IsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMuZ3JpZHdpZHRoXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IobiA9IG4xOyBuIDwgbjI7IG4rKykge1xuICAgICAgICAgICAgajAgPSBheGlzLmFycmF5dGljazAgKyBheGlzLmFycmF5ZHRpY2sgKiBuO1xuICAgICAgICAgICAgajEgPSBNYXRoLm1pbihqMCArIGF4aXMuYXJyYXlkdGljaywgZGF0YS5sZW5ndGggLSAxKTtcblxuICAgICAgICAgICAgLy8gVE9ETzogZml4IHRoZSBib3VuZHMgY29tcHV0YXRpb24gc28gd2UgZG9uJ3QgaGF2ZSB0byBkbyBhIGxhcmdlIHJhbmdlIGFuZCB0aGVuIHRocm93XG4gICAgICAgICAgICAvLyBvdXQgdW5uZWVkZWQgbnVtYmVyc1xuICAgICAgICAgICAgaWYoajAgPCAwIHx8IGowID4gZGF0YS5sZW5ndGggLSAxKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmKGoxIDwgMCB8fCBqMSA+IGRhdGEubGVuZ3RoIC0gMSkgY29udGludWU7XG5cbiAgICAgICAgICAgIHYwID0gZGF0YVtqMF07XG4gICAgICAgICAgICB2MSA9IGRhdGFbajFdO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheGlzLm1pbm9yZ3JpZGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBkID0gajEgLSBqMDtcblxuICAgICAgICAgICAgICAgIC8vIFRPRE86IGZpeCB0aGUgYm91bmRzIGNvbXB1dGF0aW9uIHNvIHdlIGRvbid0IGhhdmUgdG8gZG8gYSBsYXJnZSByYW5nZSBhbmQgdGhlbiB0aHJvd1xuICAgICAgICAgICAgICAgIC8vIG91dCB1bm5lZWRlZCBudW1iZXJzXG4gICAgICAgICAgICAgICAgaWYoZCA8PSAwKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIC8vIFhYWDogVGhpcyBjYWxjdWxhdGlvbiBpc24ndCBxdWl0ZSByaWdodC4gT2ZmIGJ5IG9uZSBzb21ld2hlcmU/XG4gICAgICAgICAgICAgICAgdiA9IHYwICsgKHYxIC0gdjApICogKGkgKyAxKSAvIChheGlzLm1pbm9yZ3JpZGNvdW50ICsgMSkgKiAoYXhpcy5hcnJheWR0aWNrIC8gZCk7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBmaXggdGhlIGJvdW5kcyBjb21wdXRhdGlvbiBzbyB3ZSBkb24ndCBoYXZlIHRvIGRvIGEgbGFyZ2UgcmFuZ2UgYW5kIHRoZW4gdGhyb3dcbiAgICAgICAgICAgICAgICAvLyBvdXQgdW5uZWVkZWQgbnVtYmVyc1xuICAgICAgICAgICAgICAgIGlmKHYgPCBkYXRhWzBdIHx8IHYgPiBkYXRhW2RhdGEubGVuZ3RoIC0gMV0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIG1pbm9yZ3JpZGxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKHYpLCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBheGlzLm1pbm9yZ3JpZGNvbG9yLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYXhpcy5taW5vcmdyaWR3aWR0aFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4aXMuc3RhcnRsaW5lKSB7XG4gICAgICAgICAgICBib3VuZGFyeWxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RBcnJheUdyaWRsaW5lKDApLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGF4aXMuc3RhcnRsaW5lY29sb3IsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMuc3RhcnRsaW5ld2lkdGhcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4aXMuZW5kbGluZSkge1xuICAgICAgICAgICAgYm91bmRhcnlsaW5lcy5wdXNoKGV4dGVuZEZsYXQoY29uc3RydWN0QXJyYXlHcmlkbGluZShkYXRhLmxlbmd0aCAtIDEpLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGF4aXMuZW5kbGluZWNvbG9yLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBheGlzLmVuZGxpbmV3aWR0aFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgdGhlIGxpbmVzIGRvIG5vdCBmYWxsIGFsb25nIHRoZSBheGVzLCB0aGVuIHdlIGhhdmUgdG8gaW50ZXJwb2xhdGVcbiAgICAgICAgLy8gdGhlIGNvbnRybyBwb2ludHMgYW5kIHNvIHNvbWUgbWF0aCB0byBmaWd1cmUgb3V0IHdoZXJlIHRoZSBsaW5lcyBhcmVcbiAgICAgICAgLy8gaW4gdGhlIGZpcnN0IHBsYWNlLlxuXG4gICAgICAgIC8vIENvbXB1dGUgdGhlIGludGVnZXIgYm91ZG5zIG9mIHRpY2swICsgbiAqIGR0aWNrIHRoYXQgZmFsbCB3aXRoaW4gdGhlIHJhbmdlXG4gICAgICAgIC8vIChyb3VnaGx5IHNwZWFraW5nKTpcbiAgICAgICAgLy8gR2l2ZSB0aGlzIGEgbmljZSBnZW5lcm91cyBlcHNpbG9uLiBXZSB1c2UgYXQgYXMgKiAoMSArIGVwcykgaW4gb3JkZXIgdG8gbWFrZVxuICAgICAgICAvLyBpbmVxdWFsaXRpZXMgYSBsaXR0bGUgdG9sZXJhbnQgaW4gYSBtb3JlIG9yIGxlc3MgY29ycmVjdCBtYW5uZXI6XG4gICAgICAgIGVwcyA9IDVlLTE1O1xuICAgICAgICBib3VuZHMgPSBbXG4gICAgICAgICAgICBNYXRoLmZsb29yKChkYXRhW2RhdGEubGVuZ3RoIC0gMV0gLSBheGlzLnRpY2swKSAvIGF4aXMuZHRpY2sgKiAoMSArIGVwcykpLFxuICAgICAgICAgICAgTWF0aC5jZWlsKChkYXRhWzBdIC0gYXhpcy50aWNrMCkgLyBheGlzLmR0aWNrIC8gKDEgKyBlcHMpKVxuICAgICAgICBdLnNvcnQoZnVuY3Rpb24oYSwgYikge3JldHVybiBhIC0gYjt9KTtcblxuICAgICAgICAvLyBVbnBhY2sgc29ydGVkIHZhbHVlcyBzbyB3ZSBjYW4gYmUgc3VyZSB0byBhdm9pZCBpbmZpbml0ZSBsb29wcyBpZiBzb21ldGhpbmdcbiAgICAgICAgLy8gaXMgYmFja3dhcmRzOlxuICAgICAgICBuMSA9IGJvdW5kc1swXTtcbiAgICAgICAgbjIgPSBib3VuZHNbMV07XG5cbiAgICAgICAgZm9yKG4gPSBuMTsgbiA8PSBuMjsgbisrKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGF4aXMudGljazAgKyBheGlzLmR0aWNrICogbjtcblxuICAgICAgICAgICAgZ3JpZGxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKHZhbHVlKSwge1xuICAgICAgICAgICAgICAgIGNvbG9yOiBheGlzLmdyaWRjb2xvcixcbiAgICAgICAgICAgICAgICB3aWR0aDogYXhpcy5ncmlkd2lkdGhcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihuID0gbjEgLSAxOyBuIDwgbjIgKyAxOyBuKyspIHtcbiAgICAgICAgICAgIHZhbHVlID0gYXhpcy50aWNrMCArIGF4aXMuZHRpY2sgKiBuO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheGlzLm1pbm9yZ3JpZGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICB2ID0gdmFsdWUgKyBheGlzLmR0aWNrICogKGkgKyAxKSAvIChheGlzLm1pbm9yZ3JpZGNvdW50ICsgMSk7XG4gICAgICAgICAgICAgICAgaWYodiA8IGRhdGFbMF0gfHwgdiA+IGRhdGFbZGF0YS5sZW5ndGggLSAxXSkgY29udGludWU7XG4gICAgICAgICAgICAgICAgbWlub3JncmlkbGluZXMucHVzaChleHRlbmRGbGF0KGNvbnN0cnVjdFZhbHVlR3JpZGxpbmUodiksIHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3I6IGF4aXMubWlub3JncmlkY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBheGlzLm1pbm9yZ3JpZHdpZHRoXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXhpcy5zdGFydGxpbmUpIHtcbiAgICAgICAgICAgIGJvdW5kYXJ5bGluZXMucHVzaChleHRlbmRGbGF0KGNvbnN0cnVjdFZhbHVlR3JpZGxpbmUoZGF0YVswXSksIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogYXhpcy5zdGFydGxpbmVjb2xvcixcbiAgICAgICAgICAgICAgICB3aWR0aDogYXhpcy5zdGFydGxpbmV3aWR0aFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXhpcy5lbmRsaW5lKSB7XG4gICAgICAgICAgICBib3VuZGFyeWxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKGRhdGFbZGF0YS5sZW5ndGggLSAxXSksIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogYXhpcy5lbmRsaW5lY29sb3IsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMuZW5kbGluZXdpZHRoXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNMYWJlbHModHJhY2UsIGF4aXMpIHtcbiAgICB2YXIgaSwgdG9iaiwgcHJlZml4LCBzdWZmaXgsIGdyaWRsaW5lO1xuXG4gICAgdmFyIGxhYmVscyA9IGF4aXMuX2xhYmVscyA9IFtdO1xuICAgIHZhciBncmlkbGluZXMgPSBheGlzLl9ncmlkbGluZXM7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBncmlkbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JpZGxpbmUgPSBncmlkbGluZXNbaV07XG5cbiAgICAgICAgaWYoWydzdGFydCcsICdib3RoJ10uaW5kZXhPZihheGlzLnNob3d0aWNrbGFiZWxzKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRvYmogPSBBeGVzLnRpY2tUZXh0KGF4aXMsIGdyaWRsaW5lLnZhbHVlKTtcblxuICAgICAgICAgICAgZXh0ZW5kRmxhdCh0b2JqLCB7XG4gICAgICAgICAgICAgICAgcHJlZml4OiBwcmVmaXgsXG4gICAgICAgICAgICAgICAgc3VmZml4OiBzdWZmaXgsXG4gICAgICAgICAgICAgICAgZW5kQW5jaG9yOiB0cnVlLFxuICAgICAgICAgICAgICAgIHh5OiBncmlkbGluZS54eSgwKSxcbiAgICAgICAgICAgICAgICBkeHk6IGdyaWRsaW5lLmR4eSgwLCAwKSxcbiAgICAgICAgICAgICAgICBheGlzOiBncmlkbGluZS5heGlzLFxuICAgICAgICAgICAgICAgIGxlbmd0aDogZ3JpZGxpbmUuY3Jvc3NBeGlzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBmb250OiBncmlkbGluZS5heGlzLnRpY2tmb250LFxuICAgICAgICAgICAgICAgIGlzRmlyc3Q6IGkgPT09IDAsXG4gICAgICAgICAgICAgICAgaXNMYXN0OiBpID09PSBncmlkbGluZXMubGVuZ3RoIC0gMVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxhYmVscy5wdXNoKHRvYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoWydlbmQnLCAnYm90aCddLmluZGV4T2YoYXhpcy5zaG93dGlja2xhYmVscykgIT09IC0xKSB7XG4gICAgICAgICAgICB0b2JqID0gQXhlcy50aWNrVGV4dChheGlzLCBncmlkbGluZS52YWx1ZSk7XG5cbiAgICAgICAgICAgIGV4dGVuZEZsYXQodG9iaiwge1xuICAgICAgICAgICAgICAgIGVuZEFuY2hvcjogZmFsc2UsXG4gICAgICAgICAgICAgICAgeHk6IGdyaWRsaW5lLnh5KGdyaWRsaW5lLmNyb3NzTGVuZ3RoIC0gMSksXG4gICAgICAgICAgICAgICAgZHh5OiBncmlkbGluZS5keHkoZ3JpZGxpbmUuY3Jvc3NMZW5ndGggLSAyLCAxKSxcbiAgICAgICAgICAgICAgICBheGlzOiBncmlkbGluZS5heGlzLFxuICAgICAgICAgICAgICAgIGxlbmd0aDogZ3JpZGxpbmUuY3Jvc3NBeGlzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBmb250OiBncmlkbGluZS5heGlzLnRpY2tmb250LFxuICAgICAgICAgICAgICAgIGlzRmlyc3Q6IGkgPT09IDAsXG4gICAgICAgICAgICAgICAgaXNMYXN0OiBpID09PSBncmlkbGluZXMubGVuZ3RoIC0gMVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxhYmVscy5wdXNoKHRvYmopO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLypcbiAqIENvbXB1dGUgdGhlIHRhbmdlbnQgdmVjdG9yIGFjY29yZGluZyB0byBjYXRtdWxsLXJvbSBjdWJpYyBzcGxpbmVzIChjZW50cmlwZXRhbCxcbiAqIEkgdGhpbmspLiBUaGF0IGRpZmZlcnMgZnJvbSB0aGUgY29udHJvbCBwb2ludCBpbiB0d28gd2F5czpcbiAqICAgMS4gSXQgaXMgYSB2ZWN0b3IsIG5vdCBhIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBwb2ludFxuICogICAyLiB0aGUgdmVjdG9yIGlzIGxvbmdlciB0aGFuIHRoZSBwb3NpdGlvbiByZWxhdGl2ZSB0byBwMSBieSBhIGZhY3RvciBvZiAzXG4gKlxuICogQ2xvc2UgdG8gdGhlIGJvdW5kYXJpZXMsIHdlJ2xsIHVzZSB0aGVzZSBhcyAqcXVhZHJhdGljIGNvbnRyb2wgcG9pbnRzLCBzbyB0aGF0XG4gKiB0byBtYWtlIGEgbmljZSBncmlkLCB3ZSdsbCBuZWVkIHRvIGRpdmlkZSB0aGUgdGFuZ2VudCBieSAyIGluc3RlYWQgb2YgMy4gKFRoZVxuICogbWF0aCB3b3JrcyBvdXQgdGhpcyB3YXkgaWYgeW91IHdvcmsgdGhyb3VnaCB0aGUgYmV6aWVyIGRlcml2YXRpdmVzKVxuICovXG52YXIgQ2F0bXVsbFJvbUV4cCA9IDAuNTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUNvbnRyb2xQb2ludHMocDAsIHAxLCBwMiwgc21vb3RobmVzcykge1xuICAgIHZhciBkMXggPSBwMFswXSAtIHAxWzBdLFxuICAgICAgICBkMXkgPSBwMFsxXSAtIHAxWzFdLFxuICAgICAgICBkMnggPSBwMlswXSAtIHAxWzBdLFxuICAgICAgICBkMnkgPSBwMlsxXSAtIHAxWzFdLFxuICAgICAgICBkMWEgPSBNYXRoLnBvdyhkMXggKiBkMXggKyBkMXkgKiBkMXksIENhdG11bGxSb21FeHAgLyAyKSxcbiAgICAgICAgZDJhID0gTWF0aC5wb3coZDJ4ICogZDJ4ICsgZDJ5ICogZDJ5LCBDYXRtdWxsUm9tRXhwIC8gMiksXG4gICAgICAgIG51bXggPSAoZDJhICogZDJhICogZDF4IC0gZDFhICogZDFhICogZDJ4KSAqIHNtb290aG5lc3MsXG4gICAgICAgIG51bXkgPSAoZDJhICogZDJhICogZDF5IC0gZDFhICogZDFhICogZDJ5KSAqIHNtb290aG5lc3MsXG4gICAgICAgIGRlbm9tMSA9IGQyYSAqIChkMWEgKyBkMmEpICogMyxcbiAgICAgICAgZGVub20yID0gZDFhICogKGQxYSArIGQyYSkgKiAzO1xuICAgIHJldHVybiBbW1xuICAgICAgICBwMVswXSArIChkZW5vbTEgJiYgbnVteCAvIGRlbm9tMSksXG4gICAgICAgIHAxWzFdICsgKGRlbm9tMSAmJiBudW15IC8gZGVub20xKVxuICAgIF0sIFtcbiAgICAgICAgcDFbMF0gLSAoZGVub20yICYmIG51bXggLyBkZW5vbTIpLFxuICAgICAgICBwMVsxXSAtIChkZW5vbTIgJiYgbnVteSAvIGRlbm9tMilcbiAgICBdXTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLypcbiAqIENvbnN0cnVjdCBhIDJEIGFycmF5IG9mIGNoZWF0ZXIgdmFsdWVzIGdpdmVuIGEsIGIsIGFuZCBhIHNsb3BlLlxuICogSWZcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhLCBiLCBjaGVhdGVyc2xvcGUpIHtcbiAgICB2YXIgaSwgaiwgYXNjYWwsIGJzY2FsLCBhdmFsLCBidmFsO1xuICAgIHZhciBkYXRhID0gW107XG5cbiAgICB2YXIgbmEgPSBpc0FycmF5T3JUeXBlZEFycmF5KGEpID8gYS5sZW5ndGggOiBhO1xuICAgIHZhciBuYiA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYikgPyBiLmxlbmd0aCA6IGI7XG4gICAgdmFyIGFkYXRhID0gaXNBcnJheU9yVHlwZWRBcnJheShhKSA/IGEgOiBudWxsO1xuICAgIHZhciBiZGF0YSA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYikgPyBiIDogbnVsbDtcblxuICAgIC8vIElmIHdlJ3JlIHVzaW5nIGRhdGEsIHNjYWxlIGl0IHNvIHRoYXQgZm9yIGRhdGEgdGhhdCdzIGp1c3QgYmFyZWx5XG4gICAgLy8gbm90IGV2ZW5seSBzcGFjZWQsIHRoZSBzd2l0Y2ggdG8gdmFsdWUtYmFzZWQgaW5kZXhpbmcgaXMgY29udGludW91cy5cbiAgICAvLyBUaGlzIG1lYW5zIGV2ZW5seSBzcGFjZWQgZGF0YSBzaG91bGQgbG9vayB0aGUgc2FtZSB3aGV0aGVyIHZhbHVlXG4gICAgLy8gb3IgaW5kZXggY2hlYXRlcnR5cGUuXG4gICAgaWYoYWRhdGEpIHtcbiAgICAgICAgYXNjYWwgPSAoYWRhdGEubGVuZ3RoIC0gMSkgLyAoYWRhdGFbYWRhdGEubGVuZ3RoIC0gMV0gLSBhZGF0YVswXSkgLyAobmEgLSAxKTtcbiAgICB9XG5cbiAgICBpZihiZGF0YSkge1xuICAgICAgICBic2NhbCA9IChiZGF0YS5sZW5ndGggLSAxKSAvIChiZGF0YVtiZGF0YS5sZW5ndGggLSAxXSAtIGJkYXRhWzBdKSAvIChuYiAtIDEpO1xuICAgIH1cblxuICAgIHZhciB4dmFsO1xuICAgIHZhciB4bWluID0gSW5maW5pdHk7XG4gICAgdmFyIHhtYXggPSAtSW5maW5pdHk7XG4gICAgZm9yKGogPSAwOyBqIDwgbmI7IGorKykge1xuICAgICAgICBkYXRhW2pdID0gW107XG4gICAgICAgIGJ2YWwgPSBiZGF0YSA/IChiZGF0YVtqXSAtIGJkYXRhWzBdKSAqIGJzY2FsIDogaiAvIChuYiAtIDEpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBuYTsgaSsrKSB7XG4gICAgICAgICAgICBhdmFsID0gYWRhdGEgPyAoYWRhdGFbaV0gLSBhZGF0YVswXSkgKiBhc2NhbCA6IGkgLyAobmEgLSAxKTtcbiAgICAgICAgICAgIHh2YWwgPSBhdmFsIC0gYnZhbCAqIGNoZWF0ZXJzbG9wZTtcbiAgICAgICAgICAgIHhtaW4gPSBNYXRoLm1pbih4dmFsLCB4bWluKTtcbiAgICAgICAgICAgIHhtYXggPSBNYXRoLm1heCh4dmFsLCB4bWF4KTtcbiAgICAgICAgICAgIGRhdGFbal1baV0gPSB4dmFsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTm9ybWFsaXplIGNoZWF0ZXIgdmFsdWVzIHRvIHRoZSAwLTEgcmFuZ2UuIFRoaXMgY29tZXMgaW50byBwbGF5IHdoZW4geW91IGhhdmVcbiAgICAvLyBtdWx0aXBsZSBjaGVhdGVyIHBsb3RzLiBBZnRlciBjYXJlZnVsIGNvbnNpZGVyYXRpb24sIGl0IHNlZW1zIGJldHRlciBpZiBjaGVhdGVyXG4gICAgLy8gdmFsdWVzIGFyZSBub3JtYWxpemVkIHRvIGEgY29uc2lzdGVudCByYW5nZS4gT3RoZXJ3aXNlIG9uZSBjaGVhdGVyIGFmZmVjdHMgdGhlXG4gICAgLy8gbGF5b3V0IG9mIG90aGVyIGNoZWF0ZXJzIG9uIHRoZSBzYW1lIGF4aXMuXG4gICAgdmFyIHNsb3BlID0gMS4wIC8gKHhtYXggLSB4bWluKTtcbiAgICB2YXIgb2Zmc2V0ID0gLXhtaW4gKiBzbG9wZTtcbiAgICBmb3IoaiA9IDA7IGogPCBuYjsgaisrKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG5hOyBpKyspIHtcbiAgICAgICAgICAgIGRhdGFbal1baV0gPSBzbG9wZSAqIGRhdGFbal1baV0gKyBvZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtYWtlQ29udHJvbFBvaW50cyA9IHJlcXVpcmUoJy4vY2F0bXVsbF9yb20nKTtcbnZhciBlbnN1cmVBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmVuc3VyZUFycmF5O1xuXG4vKlxuICogVHVybnMgYSBjb2Fyc2UgZ3JpZCBpbnRvIGEgZmluZSBncmlkIHdpdGggY29udHJvbCBwb2ludHMuXG4gKlxuICogSGVyZSdzIGFuIEFTQ0lJIHJlcHJlc2VudGF0aW9uOlxuICpcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIF4gIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICBiIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgICAgLS0tLS0tPlxuICogICAgICAgICAgIGFcbiAqXG4gKiBGaXJzdCBvZiBhbGwsIG5vdGUgdGhhdCB3ZSB3YW50IHRvIGRvIHRoaXMgaW4gKmNhcnRlc2lhbiogc3BhY2UuIFRoaXMgbWVhbnNcbiAqIHdlIG1pZ2h0IHJ1biBpbnRvIHByb2JsZW1zIHdoZW4gdGhlcmUgYXJlIGV4dHJlbWUgZGlmZmVyZW5jZXMgaW4geC95IHNjYWxpbmcsXG4gKiBidXQgdGhlIGFsdGVybmF0aXZlIGlzIHRoYXQgdGhlIHRvcG9sb2d5IG9mIHRoZSBjb250b3VycyBtaWdodCBhY3R1YWxseSBiZVxuICogdmlldy1kZXBlbmRlbnQsIHdoaWNoIHNlZW1zIHdvcnNlLiBBcyBhIGZhbGxiYWNrLCB0aGUgb25seSBwYXJhbWV0ZXIgdGhhdFxuICogYWN0dWFsbHkgYWZmZWN0cyB0aGUgcmVzdWx0IGlzIHRoZSAqYXNwZWN0IHJhdGlvKiwgc28gdGhhdCB3ZSBjYW4gYXQgbGVhc3RcbiAqIGltcHJvdmUgdGhlIHNpdHVhdGlvbiBhIGJpdCB3aXRob3V0IGdvaW5nIGFsbCB0aGUgd2F5IHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGZsYXR0ZW5zIHRoZSBwb2ludHMgKyB0YW5nZW50cyAgaW50byBhIHNsaWdodGx5IGRlbnNlciBncmlkIG9mXG4gKiAqY29udHJvbCBwb2ludHMqLiBUaGUgcmVzdWx0aW5nIGdyaWQgbG9va3MgbGlrZSB0aGlzOlxuICpcbiAqICAgICAgIDkgKy0tby1vLS0rIC1vLW8tLSstLW8tby0tK1xuICogICAgICAgOCBvICBvIG8gIG8gIG8gbyAgbyAgbyBvICBvXG4gKiAgICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIDcgbyAgbyBvICBvICBvIG8gIG8gIG8gbyAgb1xuICogICAgICAgNiArLS1vLW8tLSsgLW8tby0tKy0tby1vLS0rXG4gKiAgICAgICA1IG8gIG8gbyAgbyAgbyBvICBvICBvIG8gIG9cbiAqICAgICAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICogICAgXiAgNCBvICBvIG8gIG8gIG8gbyAgbyAgbyBvICBvXG4gKiAgICB8ICAzICstLW8tby0tKyAtby1vLS0rLS1vLW8tLStcbiAqICBiIHwgIDIgbyAgbyBvICBvICBvIG8gIG8gIG8gbyAgb1xuICogICAgfCAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gKiAgICB8ICAxIG8gIG8gbyAgbyAgbyBvICBvICBvIG8gIG9cbiAqICAgICAgIDAgKy0tby1vLS0rIC1vLW8tLSstLW8tby0tK1xuICogICAgICAgICAwICAxIDIgIDMgIDQgNSAgNiAgNyA4ICA5XG4gKiAgICAgICAgIC0tLS0tLT5cbiAqICAgICAgICAgICBhXG4gKlxuICogd2hlcmUgYG9gcyByZXByZXNlbnQgbmV3bHktY29tcHV0ZWQgY29udHJvbCBwb2ludHMuIHRoZSByZXN1bHRpbmcgZGltZW5zaW9uIGlzXG4gKlxuICogICAgIChtIC0gMSkgKiAzICsgMVxuICogICA9IDMgKiBtIC0gMlxuICpcbiAqIFdlIGNvdWxkIHNpbXBseSBzdG9yZSB0aGUgdGFuZ2VudHMgc2VwYXJhdGVseSwgYnV0IHRoYXQncyBhIG5pZ2h0bWFyZSB0byBvcmdhbml6ZVxuICogaW4gdHdvIGRpbWVuc2lvbnMgc2luY2Ugd2UnbGwgYmUgc2xpY2luZyBncmlkIGxpbmVzIGluIGJvdGggZGlyZWN0aW9ucyBhbmQgc2luY2VcbiAqIHRoYXQgYmFzaWNhbGx5IHJlcXVpcmVzIHZlcnkgbmVhcmx5IGp1c3QgYXMgbXVjaCBzdG9yYWdlIGFzIGp1c3Qgc3RvcmluZyB0aGUgZGVuc2VcbiAqIGdyaWQuXG4gKlxuICogV293IVxuICovXG5cblxuLypcbiAqIENhdG11bGwtcm9tIGlzIGJpYXNlZCBhdCB0aGUgYm91bmRhcmllcyB0b3dhcmQgdGhlIGludGVyaW9yIGFuZCB3ZSBhY3R1YWxseVxuICogY2FuJ3QgdXNlIGNhdG11bGwtcm9tIHRvIGNvbXB1dGUgdGhlIGNvbnRyb2wgcG9pbnQgY2xvc2VzdCB0byAoYnV0IGluc2lkZSlcbiAqIHRoZSBib3VuZGFyeS5cbiAqXG4gKiBBIG5vdGUgb24gcGxvdGx5J3Mgc3BsaW5lIGludGVycG9sYXRpb24uIEl0IHVzZXMgdGhlIGNhdG11bGwgcm9tIGNvbnRyb2wgcG9pbnRcbiAqIGNsb3Nlc3QgdG8gdGhlIGJvdW5kYXJ5ICphcyogYSBxdWFkcmF0aWMgY29udHJvbCBwb2ludC4gVGhpcyBzZWVtcyBpbmNvcnJlY3QsXG4gKiBzbyBJJ3ZlIGVsZWN0ZWQgbm90IHRvIGZvbGxvdyB0aGF0LiBHaXZlbiBjb250cm9sIHBvaW50cyAwIGFuZCAxLCByZWd1bGFyIHBsb3RseVxuICogc3BsaW5lcyBnaXZlICplcXVpdmFsZW50KiBjdWJpYyBjb250cm9sIHBvaW50czpcbiAqXG4gKiBJbnB1dDpcbiAqXG4gKiAgIGJvdW5kYXJ5XG4gKiAgICAgfCAgICAgICAgICAgICAgICAgICAgfFxuICogICAgIHAwICAgICAgICAgICBwMiAgICAgIHAzICAgIC0tPiBpbnRlcmlvclxuICogICAgIDAuMCAgICAgICAgICAwLjY2NyAgIDEuMFxuICogICAgIHwgICAgICAgICAgICAgICAgICAgIHxcbiAqXG4gKiBDdWJpYy1lcXVpdmFsZW50IG9mIHdoYXQgcGxvdGx5IHNwbGluZXMgZHJhdzo6XG4gKlxuICogICBib3VuZGFyeVxuICogICAgIHwgICAgICAgICAgICAgICAgICAgIHxcbiAqICAgICBwMCAgIHAxICAgICAgcDIgICAgICBwMyAgICAtLT4gaW50ZXJpb3JcbiAqICAgICAwLjAgIDAuNDQ0NCAgMC44ODg4ICAxLjBcbiAqICAgICB8ICAgICAgICAgICAgICAgICAgICB8XG4gKlxuICogV2hhdCB0aGlzIGZ1bmN0aW9uIGZpbGxzIGluOlxuICpcbiAqICAgYm91bmRhcnlcbiAqICAgICB8ICAgICAgICAgICAgICAgICAgICB8XG4gKiAgICAgcDAgICAgcDEgICAgIHAyICAgICAgcDMgICAgLS0+IGludGVyaW9yXG4gKiAgICAgMC4wICAgMC4zMzMgIDAuNjY3ICAgMS4wXG4gKiAgICAgfCAgICAgICAgICAgICAgICAgICAgfFxuICpcbiAqIFBhcmFtZXRlcnM6XG4gKiAgIHAwOiBib3VuZGFyeSBwb2ludFxuICogICBwMjogY2F0bXVsbCByb20gcG9pbnQgYmFzZWQgb24gY29tcHV0YXRpb24gYXQgcDNcbiAqICAgcDM6IGZpcnN0IGdyaWQgcG9pbnRcbiAqXG4gKiBPZiBjb3Vyc2UgaXQgd29ya3Mgd2hpY2hldmVyIHdheSBpdCdzIG9yaWVudGVkOyB5b3UganVzdCBuZWVkIHRvIGludGVycHJldCB0aGVcbiAqIGlucHV0L291dHB1dCBhY2NvcmRpbmdseS5cbiAqL1xuZnVuY3Rpb24gaW5mZXJDdWJpY0NvbnRyb2xQb2ludChwMCwgcDIsIHAzKSB7XG4gICAgLy8gRXh0ZW5kIHAxIGF3YXkgZnJvbSBwMCBieSA1MCUuIFRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgcXVhZHJhdGljIHBvaW50IHRoYXRcbiAgICAvLyB3b3VsZCBnaXZlIHRoZSBzYW1lIHNsb3BlIGFzIGNhdG11bGwgcm9tIGF0IHAwLlxuICAgIHZhciBwMmUwID0gLTAuNSAqIHAzWzBdICsgMS41ICogcDJbMF07XG4gICAgdmFyIHAyZTEgPSAtMC41ICogcDNbMV0gKyAxLjUgKiBwMlsxXTtcblxuICAgIHJldHVybiBbXG4gICAgICAgICgyICogcDJlMCArIHAwWzBdKSAvIDMsXG4gICAgICAgICgyICogcDJlMSArIHAwWzFdKSAvIDMsXG4gICAgXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb21wdXRlQ29udHJvbFBvaW50cyh4ZSwgeWUsIHgsIHksIGFzbW9vdGhpbmcsIGJzbW9vdGhpbmcpIHtcbiAgICB2YXIgaSwgaiwgaWUsIGplLCB4ZWosIHllaiwgeGosIHlqLCBjcCwgcDE7XG4gICAgLy8gQXQgdGhpcyBwb2ludCwgd2Uga25vdyB0aGVzZSBkaW1lbnNpb25zIGFyZSBjb3JyZWN0IGFuZCByZXByZXNlbnRhdGl2ZSBvZlxuICAgIC8vIHRoZSB3aG9sZSAyRCBhcnJheXM6XG4gICAgdmFyIG5hID0geFswXS5sZW5ndGg7XG4gICAgdmFyIG5iID0geC5sZW5ndGg7XG5cbiAgICAvLyAobil1bWJlciBvZiAoZSl4cGFuZGVkIHBvaW50czpcbiAgICB2YXIgbmVhID0gYXNtb290aGluZyA/IDMgKiBuYSAtIDIgOiBuYTtcbiAgICB2YXIgbmViID0gYnNtb290aGluZyA/IDMgKiBuYiAtIDIgOiBuYjtcblxuICAgIHhlID0gZW5zdXJlQXJyYXkoeGUsIG5lYik7XG4gICAgeWUgPSBlbnN1cmVBcnJheSh5ZSwgbmViKTtcblxuICAgIGZvcihpZSA9IDA7IGllIDwgbmViOyBpZSsrKSB7XG4gICAgICAgIHhlW2llXSA9IGVuc3VyZUFycmF5KHhlW2llXSwgbmVhKTtcbiAgICAgICAgeWVbaWVdID0gZW5zdXJlQXJyYXkoeWVbaWVdLCBuZWEpO1xuICAgIH1cblxuICAgIC8vIFRoaXMgbG9vcCBmaWxscyBpbiB0aGUgWCdkIHBvaW50czpcbiAgICAvL1xuICAgIC8vICAgIC4gICAgICAgLiAgICAgICAuICAgICAgIC5cbiAgICAvLyAgICAuICAgICAgIC4gICAgICAgLiAgICAgICAuXG4gICAgLy8gICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgIC8vICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAvLyAgICBYIC0tLS0tIFggLS0tLS0gWCAtLS0tLSBYXG4gICAgLy8gICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgIC8vICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAvLyAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgLy8gICAgWCAtLS0tLSBYIC0tLS0tIFggLS0tLS0gWFxuICAgIC8vXG4gICAgLy9cbiAgICAvLyBpZSA9IChpKSAoZSl4cGFuZGVkOlxuICAgIGZvcihqID0gMCwgamUgPSAwOyBqIDwgbmI7IGorKywgamUgKz0gYnNtb290aGluZyA/IDMgOiAxKSB7XG4gICAgICAgIHhlaiA9IHhlW2plXTtcbiAgICAgICAgeWVqID0geWVbamVdO1xuICAgICAgICB4aiA9IHhbal07XG4gICAgICAgIHlqID0geVtqXTtcblxuICAgICAgICAvLyBqZSA9IChqKSAoZSl4cGFuZGVkOlxuICAgICAgICBmb3IoaSA9IDAsIGllID0gMDsgaSA8IG5hOyBpKyssIGllICs9IGFzbW9vdGhpbmcgPyAzIDogMSkge1xuICAgICAgICAgICAgeGVqW2llXSA9IHhqW2ldO1xuICAgICAgICAgICAgeWVqW2llXSA9IHlqW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoYXNtb290aGluZykge1xuICAgICAgICAvLyBJZiB0aGVyZSdzIGEtc21vb3RoaW5nLCB0aGlzIGxvb3AgZmlsbHMgaW4gdGhlIFgnZCBwb2ludHMgd2l0aCBjYXRtdWxsLXJvbVxuICAgICAgICAvLyBjb250cm9sIHBvaW50cyBjb21wdXRlZCBhbG9uZyB0aGUgYS1heGlzOlxuICAgICAgICAvLyAgICAgLiAgICAgICAuICAgICAgIC4gICAgICAgLlxuICAgICAgICAvLyAgICAgLiAgICAgICAuICAgICAgIC4gICAgICAgLlxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgbyAtWS1YLSBvIC1YLVgtIG8gLVgtWS0gb1xuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgbyAtWS1YLSBvIC1YLVgtIG8gLVgtWS0gb1xuICAgICAgICAvL1xuICAgICAgICAvLyBpOiAgMCAgICAgICAxICAgICAgIDIgICAgICAgM1xuICAgICAgICAvLyBpZTogMCAgMSAzICAzICA0IDUgIDYgIDcgOCAgOVxuICAgICAgICAvL1xuICAgICAgICAvLyAgICAgICAgICAgLS0tLS0tPlxuICAgICAgICAvLyAgICAgICAgICAgICBhXG4gICAgICAgIC8vXG4gICAgICAgIGZvcihqID0gMCwgamUgPSAwOyBqIDwgbmI7IGorKywgamUgKz0gYnNtb290aGluZyA/IDMgOiAxKSB7XG4gICAgICAgICAgICAvLyBGaWxsIGluIHRoZSBwb2ludHMgbWFya2VkIFggZm9yIHRoaXMgYS1yb3c6XG4gICAgICAgICAgICBmb3IoaSA9IDEsIGllID0gMzsgaSA8IG5hIC0gMTsgaSsrLCBpZSArPSAzKSB7XG4gICAgICAgICAgICAgICAgY3AgPSBtYWtlQ29udHJvbFBvaW50cyhcbiAgICAgICAgICAgICAgICAgICAgW3hbal1baSAtIDFdLCB5W2pdW2kgLSAxXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4W2pdW2kgXSwgeVtqXVtpXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4W2pdW2kgKyAxXSwgeVtqXVtpICsgMV1dLFxuICAgICAgICAgICAgICAgICAgICBhc21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plXVtpZSAtIDFdID0gY3BbMF1bMF07XG4gICAgICAgICAgICAgICAgeWVbamVdW2llIC0gMV0gPSBjcFswXVsxXTtcbiAgICAgICAgICAgICAgICB4ZVtqZV1baWUgKyAxXSA9IGNwWzFdWzBdO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSArIDFdID0gY3BbMV1bMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZSB2ZXJ5IGZpcnN0IGN1YmljIGludGVycG9sYXRpb24gcG9pbnQgKHRvIHRoZSBsZWZ0IGZvciBpID0gMSBhYm92ZSkgaXNcbiAgICAgICAgICAgIC8vIHVzZWQgYXMgYSAqcXVhZHJhdGljKiBpbnRlcnBvbGF0aW9uIHBvaW50IGJ5IHRoZSBzcGxpbmUgZHJhd2luZyBmdW5jdGlvblxuICAgICAgICAgICAgLy8gd2hpY2ggaXNuJ3QgcmVhbGx5IGNvcnJlY3QuIEJ1dCBmb3IgdGhlIHNha2Ugb2YgY29uc2lzdGVuY3ksIHdlJ2xsIHVzZSBpdFxuICAgICAgICAgICAgLy8gYXMgc3VjaC4gU2luY2Ugd2UncmUgdXNpbmcgY3ViaWMgc3BsaW5lcywgdGhhdCBtZWFucyB3ZSBuZWVkIHRvIHNob3J0ZW4gdGhlXG4gICAgICAgICAgICAvLyB0YW5nZW50IGJ5IDEvMyBhbmQgYWxzbyBjb25zdHJ1Y3QgYSBuZXcgY3ViaWMgc3BsaW5lIGNvbnRyb2wgcG9pbnQgMS8zIGZyb21cbiAgICAgICAgICAgIC8vIHRoZSBvcmlnaW5hbCB0byB0aGUgaSA9IDAgcG9pbnQuXG4gICAgICAgICAgICBwMSA9IGluZmVyQ3ViaWNDb250cm9sUG9pbnQoXG4gICAgICAgICAgICAgICAgW3hlW2plXVswXSwgeWVbamVdWzBdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdWzJdLCB5ZVtqZV1bMl1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bM10sIHllW2plXVszXV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB4ZVtqZV1bMV0gPSBwMVswXTtcbiAgICAgICAgICAgIHllW2plXVsxXSA9IHAxWzFdO1xuXG4gICAgICAgICAgICAvLyBEaXR0byBsYXN0IHBvaW50cywgc2FucyBleHBsYW5hdGlvbjpcbiAgICAgICAgICAgIHAxID0gaW5mZXJDdWJpY0NvbnRyb2xQb2ludChcbiAgICAgICAgICAgICAgICBbeGVbamVdW25lYSAtIDFdLCB5ZVtqZV1bbmVhIC0gMV1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bbmVhIC0gM10sIHllW2plXVtuZWEgLSAzXV0sXG4gICAgICAgICAgICAgICAgW3hlW2plXVtuZWEgLSA0XSwgeWVbamVdW25lYSAtIDRdXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHhlW2plXVtuZWEgLSAyXSA9IHAxWzBdO1xuICAgICAgICAgICAgeWVbamVdW25lYSAtIDJdID0gcDFbMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihic21vb3RoaW5nKSB7XG4gICAgICAgIC8vIElmIHRoZXJlJ3MgYS1zbW9vdGhpbmcsIHRoaXMgbG9vcCBmaWxscyBpbiB0aGUgWCdkIHBvaW50cyB3aXRoIGNhdG11bGwtcm9tXG4gICAgICAgIC8vIGNvbnRyb2wgcG9pbnRzIGNvbXB1dGVkIGFsb25nIHRoZSBiLWF4aXM6XG4gICAgICAgIC8vICAgICAuICAgICAgIC4gICAgICAgLiAgICAgICAuXG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICBvIC1vLW8tIG8gLW8tby0gbyAtby1vLSBvXG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgICAgIC8vICAgICBZICBZIFkgIFkgIFkgWSAgWSAgWSBZICBZXG4gICAgICAgIC8vICAgICBvIC1vLW8tIG8gLW8tby0gbyAtby1vLSBvXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGk6ICAwICAgICAgIDEgICAgICAgMiAgICAgICAzXG4gICAgICAgIC8vIGllOiAwICAxIDMgIDMgIDQgNSAgNiAgNyA4ICA5XG4gICAgICAgIC8vXG4gICAgICAgIC8vICAgICAgICAgICAtLS0tLS0+XG4gICAgICAgIC8vICAgICAgICAgICAgIGFcbiAgICAgICAgLy9cbiAgICAgICAgZm9yKGllID0gMDsgaWUgPCBuZWE7IGllKyspIHtcbiAgICAgICAgICAgIGZvcihqZSA9IDM7IGplIDwgbmViIC0gMzsgamUgKz0gMykge1xuICAgICAgICAgICAgICAgIGNwID0gbWFrZUNvbnRyb2xQb2ludHMoXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZSAtIDNdW2llXSwgeWVbamUgLSAzXVtpZV1dLFxuICAgICAgICAgICAgICAgICAgICBbeGVbamVdW2llXSwgeWVbamVdW2llXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZSArIDNdW2llXSwgeWVbamUgKyAzXVtpZV1dLFxuICAgICAgICAgICAgICAgICAgICBic21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plIC0gMV1baWVdID0gY3BbMF1bMF07XG4gICAgICAgICAgICAgICAgeWVbamUgLSAxXVtpZV0gPSBjcFswXVsxXTtcbiAgICAgICAgICAgICAgICB4ZVtqZSArIDFdW2llXSA9IGNwWzFdWzBdO1xuICAgICAgICAgICAgICAgIHllW2plICsgMV1baWVdID0gY3BbMV1bMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEbyB0aGUgc2FtZSBib3VuZGFyeSBjb25kaXRpb24gbWFnaWMgZm9yIHRoZXNlIGNvbnRyb2wgcG9pbnRzIG1hcmtlZCBZIGFib3ZlOlxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVswXVtpZV0sIHllWzBdW2llXV0sXG4gICAgICAgICAgICAgICAgW3hlWzJdW2llXSwgeWVbMl1baWVdXSxcbiAgICAgICAgICAgICAgICBbeGVbM11baWVdLCB5ZVszXVtpZV1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbMV1baWVdID0gcDFbMF07XG4gICAgICAgICAgICB5ZVsxXVtpZV0gPSBwMVsxXTtcblxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVtuZWIgLSAxXVtpZV0sIHllW25lYiAtIDFdW2llXV0sXG4gICAgICAgICAgICAgICAgW3hlW25lYiAtIDNdW2llXSwgeWVbbmViIC0gM11baWVdXSxcbiAgICAgICAgICAgICAgICBbeGVbbmViIC0gNF1baWVdLCB5ZVtuZWIgLSA0XVtpZV1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbbmViIC0gMl1baWVdID0gcDFbMF07XG4gICAgICAgICAgICB5ZVtuZWIgLSAyXVtpZV0gPSBwMVsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGFzbW9vdGhpbmcgJiYgYnNtb290aGluZykge1xuICAgICAgICAvLyBEbyBvbmUgbW9yZSBwYXNzLCB0aGlzIHRpbWUgcmVjb21wdXRpbmcgZXhhY3RseSB3aGF0IHdlIGp1c3QgY29tcHV0ZWQuXG4gICAgICAgIC8vIEl0J3Mgb3ZlcmRldGVybWluZWQgc2luY2Ugd2UncmUgcGVmb3JtaW5nIGNhdG11bGwtcm9tIGluIHR3byBkaXJlY3Rpb25zLFxuICAgICAgICAvLyBzbyB3ZSdsbCBqdXN0IGF2ZXJhZ2UgdGhlIG92ZXJkZXRlcm1pbmVkLiBUaGVzZSBwb2ludHMgZG9uJ3QgbGllIGFsb25nIHRoZVxuICAgICAgICAvLyBncmlkIGxpbmVzLCBzbyBub3RlIHRoYXQgb25seSBncmlkIGxpbmVzIHdpbGwgZm9sbG93IG5vcm1hbCBwbG90bHkgc3BsaW5lXG4gICAgICAgIC8vIGludGVycG9sYXRpb24uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFVubGVzcyBvZiBjb3Vyc2UgdGhlcmUgd2FzIG5vIGIgc21vb3RoaW5nLiBUaGVuIHRoZXNlIGludGVybWVkaWF0ZSBwb2ludHNcbiAgICAgICAgLy8gZG9uJ3QgYWN0dWFsbHkgZXhpc3QgYW5kIHRoaXMgc2VjdGlvbiBpcyBieXBhc3NlZC5cbiAgICAgICAgLy8gICAgIC4gICAgICAgLiAgICAgICAuICAgICAgIC5cbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIG8gLW8tby0gbyAtby1vLSBvIC1vLW8tIG9cbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAgICAgLy8gICAgIG8gIFkgWSAgbyAgWSBZICBvICBZIFkgIG9cbiAgICAgICAgLy8gICAgIG8gLW8tby0gbyAtby1vLSBvIC1vLW8tIG9cbiAgICAgICAgLy9cbiAgICAgICAgLy8gaTogIDAgICAgICAgMSAgICAgICAyICAgICAgIDNcbiAgICAgICAgLy8gaWU6IDAgIDEgMyAgMyAgNCA1ICA2ICA3IDggIDlcbiAgICAgICAgLy9cbiAgICAgICAgLy8gICAgICAgICAgIC0tLS0tLT5cbiAgICAgICAgLy8gICAgICAgICAgICAgYVxuICAgICAgICAvL1xuICAgICAgICBmb3IoamUgPSAxOyBqZSA8IG5lYjsgamUgKz0gKGplICsgMSkgJSAzID09PSAwID8gMiA6IDEpIHtcbiAgICAgICAgICAgIC8vIEZpbGwgaW4gdGhlIHBvaW50cyBtYXJrZWQgWCBmb3IgdGhpcyBhLXJvdzpcbiAgICAgICAgICAgIGZvcihpZSA9IDM7IGllIDwgbmVhIC0gMzsgaWUgKz0gMykge1xuICAgICAgICAgICAgICAgIGNwID0gbWFrZUNvbnRyb2xQb2ludHMoXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZV1baWUgLSAzXSwgeWVbamVdW2llIC0gM11dLFxuICAgICAgICAgICAgICAgICAgICBbeGVbamVdW2llXSwgeWVbamVdW2llXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZV1baWUgKyAzXSwgeWVbamVdW2llICsgM11dLFxuICAgICAgICAgICAgICAgICAgICBhc21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plXVtpZSAtIDFdID0gMC41ICogKHhlW2plXVtpZSAtIDFdICsgY3BbMF1bMF0pO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSAtIDFdID0gMC41ICogKHllW2plXVtpZSAtIDFdICsgY3BbMF1bMV0pO1xuICAgICAgICAgICAgICAgIHhlW2plXVtpZSArIDFdID0gMC41ICogKHhlW2plXVtpZSArIDFdICsgY3BbMV1bMF0pO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSArIDFdID0gMC41ICogKHllW2plXVtpZSArIDFdICsgY3BbMV1bMV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUaGlzIGNhc2UgaXMganVzdCBzbGlnaHRseSBkaWZmZXJlbnQuIFRoZSBjb21wdXRhdGlvbiBpcyB0aGUgc2FtZSxcbiAgICAgICAgICAgIC8vIGJ1dCBoYXZpbmcgY29tcHV0ZWQgdGhpcywgd2UnbGwgYXZlcmFnZSB3aXRoIHRoZSBleGlzdGluZyByZXN1bHQuXG4gICAgICAgICAgICBwMSA9IGluZmVyQ3ViaWNDb250cm9sUG9pbnQoXG4gICAgICAgICAgICAgICAgW3hlW2plXVswXSwgeWVbamVdWzBdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdWzJdLCB5ZVtqZV1bMl1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bM10sIHllW2plXVszXV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB4ZVtqZV1bMV0gPSAwLjUgKiAoeGVbamVdWzFdICsgcDFbMF0pO1xuICAgICAgICAgICAgeWVbamVdWzFdID0gMC41ICogKHllW2plXVsxXSArIHAxWzFdKTtcblxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bbmVhIC0gMV0sIHllW2plXVtuZWEgLSAxXV0sXG4gICAgICAgICAgICAgICAgW3hlW2plXVtuZWEgLSAzXSwgeWVbamVdW25lYSAtIDNdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdW25lYSAtIDRdLCB5ZVtqZV1bbmVhIC0gNF1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbamVdW25lYSAtIDJdID0gMC41ICogKHhlW2plXVtuZWEgLSAyXSArIHAxWzBdKTtcbiAgICAgICAgICAgIHllW2plXVtuZWEgLSAyXSA9IDAuNSAqICh5ZVtqZV1bbmVhIC0gMl0gKyBwMVsxXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW3hlLCB5ZV07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFJFTEFUSVZFX0NVTExfVE9MRVJBTkNFOiAxZS02XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogRXZhbHVhdGVzIHRoZSBkZXJpdmF0aXZlIG9mIGEgbGlzdCBvZiBjb250cm9sIHBvaW50IGFycmF5cy4gVGhhdCBpcywgaXQgZXhwZWN0cyBhbiBhcnJheSBvciBhcnJheXNcbiAqIHRoYXQgYXJlIGV4cGFuZGVkIHJlbGF0aXZlIHRvIHRoZSByYXcgZGF0YSB0byBpbmNsdWRlIHRoZSBiaWN1YmljIGNvbnRyb2wgcG9pbnRzLCBpZiBhcHBsaWNhYmxlLiBJZlxuICogb25seSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBpcyBkZXNpcmVkLCB0aGVuIHRoZSBkYXRhIHBvaW50cyBjb3JyZXNwb25kIDEtMSBhbG9uZyB0aGF0IGF4aXMgdG8gdGhlXG4gKiBkYXRhIGl0c2VsZi4gU2luY2UgaXQncyBjYXRtdWxsLXJvbSBzcGxpbmVzIGluIGVpdGhlciBkaXJlY3Rpb24gbm90ZSBpbiBwYXJ0aWN1bGFyIHRoYXQgdGhlXG4gKiBkZXJpdmF0aXZlcyBhcmUgZGlzY29udGludW91cyBhY3Jvc3MgY2VsbCBib3VuZGFyaWVzLiBUaGF0J3MgdGhlIHJlYXNvbiB5b3UgbmVlZCBib3RoIHRoZSAqY2VsbCpcbiAqIGFuZCB0aGUgKnBvaW50IHdpdGhpbiB0aGUgY2VsbCouXG4gKlxuICogQWxzbyBub3RlIHRoYXQgdGhlIGRpc2NvbnRpbnVpdHkgb2YgdGhlIGRlcml2YXRpdmUgaXMgaW4gbWFnbml0dWRlIG9ubHkuIFRoZSBkaXJlY3Rpb24gKmlzKlxuICogY29udGludW91cyBhY3Jvc3MgY2VsbCBib3VuZGFyaWVzLlxuICpcbiAqIEZvciBleGFtcGxlLCB0byBjb21wdXRlIHRoZSBkZXJpdmF0aXZlIG9mIHRoZSB4Y29vcmRpbmF0ZSBoYWxmd2F5IGJldHdlbiB0aGUgNyBhbmQgOHRoIGktZ3JpZHBvaW50c1xuICogYW5kIHRoZSAxMHRoIGFuZCAxMXRoIGotZ3JpZHBvaW50cyBnaXZlbiBiaWN1YmljIHNtb290aGluZyBpbiBib3RoIGRpbWVuc2lvbnMsIHlvdSdkIHdyaXRlOlxuICpcbiAqICAgICB2YXIgZGVyaXYgPSBjcmVhdGVJRGVyaXZhdGl2ZUV2YWx1YXRvcihbeF0sIDEsIDEpO1xuICpcbiAqICAgICB2YXIgZHhkaSA9IGRlcml2KFtdLCA3LCAxMCwgMC41LCAwLjUpO1xuICogICAgIC8vID0+IFswLjEyMzQ1XVxuICpcbiAqIFNpbmNlIHRoZXJlJ2QgYmUgYSBidW5jaCBvZiBkdXBsaWNhdGUgY29tcHV0YXRpb24gdG8gY29tcHV0ZSBtdWx0aXBsZSBkZXJpdmF0aXZlcywgeW91IGNhbiBkb3VibGVcbiAqIHRoaXMgdXAgYnkgcHJvdmlkaW5nIG1vcmUgYXJyYXlzOlxuICpcbiAqICAgICB2YXIgZGVyaXYgPSBjcmVhdGVJRGVyaXZhdGl2ZUV2YWx1YXRvcihbeCwgeV0sIDEsIDEpO1xuICpcbiAqICAgICB2YXIgZHhkaSA9IGRlcml2KFtdLCA3LCAxMCwgMC41LCAwLjUpO1xuICogICAgIC8vID0+IFswLjEyMzQ1LCAwLjc4OTEwXVxuICpcbiAqIE5COiBJdCdzIHByZXN1bWVkIHRoYXQgYXQgdGhpcyBwb2ludCBhbGwgZGF0YSBoYXMgYmVlbiBzYW5pdGl6ZWQgYW5kIGlzIHZhbGlkIG51bWVyaWNhbCBkYXRhIGFycmF5c1xuICogb2YgdGhlIGNvcnJlY3QgZGltZW5zaW9uLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGFycmF5cywgYXNtb290aGluZywgYnNtb290aGluZykge1xuICAgIGlmKGFzbW9vdGhpbmcgJiYgYnNtb290aGluZykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpMCwgajAsIHUsIHYpIHtcbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgZjIsIGYzLCBhaywgaztcblxuICAgICAgICAgICAgLy8gU2luY2UgaXQncyBhIGdyaWQgb2YgY29udHJvbCBwb2ludHMsIHRoZSBhY3R1YWwgaW5kaWNlcyBhcmUgKiAzOlxuICAgICAgICAgICAgaTAgKj0gMztcbiAgICAgICAgICAgIGowICo9IDM7XG5cbiAgICAgICAgICAgIC8vIFByZWNvbXB1dGUgc29tZSBudW1iZXJzOlxuICAgICAgICAgICAgdmFyIHUyID0gdSAqIHU7XG4gICAgICAgICAgICB2YXIgb3UgPSAxIC0gdTtcbiAgICAgICAgICAgIHZhciBvdTIgPSBvdSAqIG91O1xuICAgICAgICAgICAgdmFyIG91dTIgPSBvdSAqIHUgKiAyO1xuICAgICAgICAgICAgdmFyIGEgPSAtMyAqIG91MjtcbiAgICAgICAgICAgIHZhciBiID0gMyAqIChvdTIgLSBvdXUyKTtcbiAgICAgICAgICAgIHZhciBjID0gMyAqIChvdXUyIC0gdTIpO1xuICAgICAgICAgICAgdmFyIGQgPSAzICogdTI7XG5cbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIHYzID0gdjIgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdjMgPSBvdjIgKiBvdjtcblxuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgZGVyaXZhdGl2ZXMgaW4gdGhlIHUtZGlyZWN0aW9uOlxuICAgICAgICAgICAgICAgIGYwID0gYSAqIGFrW2owIF1baTBdICsgYiAqIGFrW2owIF1baTAgKyAxXSArIGMgKiBha1tqMCBdW2kwICsgMl0gKyBkICogYWtbajAgXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYxID0gYSAqIGFrW2owICsgMV1baTBdICsgYiAqIGFrW2owICsgMV1baTAgKyAxXSArIGMgKiBha1tqMCArIDFdW2kwICsgMl0gKyBkICogYWtbajAgKyAxXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYyID0gYSAqIGFrW2owICsgMl1baTBdICsgYiAqIGFrW2owICsgMl1baTAgKyAxXSArIGMgKiBha1tqMCArIDJdW2kwICsgMl0gKyBkICogYWtbajAgKyAyXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYzID0gYSAqIGFrW2owICsgM11baTBdICsgYiAqIGFrW2owICsgM11baTAgKyAxXSArIGMgKiBha1tqMCArIDNdW2kwICsgMl0gKyBkICogYWtbajAgKyAzXVtpMCArIDNdO1xuXG4gICAgICAgICAgICAgICAgLy8gTm93IGp1c3QgaW50ZXJwb2xhdGUgaW4gdGhlIHYtZGlyZWN0aW9uIHNpbmNlIGl0J3MgYWxsIHNlcGFyYWJsZTpcbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGFzbW9vdGhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIHNtb290aCBpbiB0aGUgYS1kaXJlY3Rpb24gYnV0IGxpbmVhciBpbiB0aGUgYi1kaXJlY3Rpb24gYnkgcGVyZm9ybWluZyBmb3VyXG4gICAgICAgIC8vIGxpbmVhciBpbnRlcnBvbGF0aW9ucyBmb2xsb3dlZCBieSBvbmUgY3ViaWMgaW50ZXJwb2xhdGlvbiBvZiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBrLCBhaztcbiAgICAgICAgICAgIGkwICo9IDM7XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3V1MiA9IG91ICogdSAqIDI7XG4gICAgICAgICAgICB2YXIgYSA9IC0zICogb3UyO1xuICAgICAgICAgICAgdmFyIGIgPSAzICogKG91MiAtIG91dTIpO1xuICAgICAgICAgICAgdmFyIGMgPSAzICogKG91dTIgLSB1Mik7XG4gICAgICAgICAgICB2YXIgZCA9IDMgKiB1MjtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBhICogYWtbajAgXVtpMF0gKyBiICogYWtbajAgXVtpMCArIDFdICsgYyAqIGFrW2owIF1baTAgKyAyXSArIGQgKiBha1tqMCBdW2kwICsgM107XG4gICAgICAgICAgICAgICAgZjEgPSBhICogYWtbajAgKyAxXVtpMF0gKyBiICogYWtbajAgKyAxXVtpMCArIDFdICsgYyAqIGFrW2owICsgMV1baTAgKyAyXSArIGQgKiBha1tqMCArIDFdW2kwICsgM107XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdiAqIGYwICsgdiAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoYnNtb290aGluZykge1xuICAgICAgICAvLyBTYW1lIGFzIHRoZSBhYm92ZSBjYXNlLCBleGNlcHQgcmV2ZXJzZWQuIEkndmUgZGlzYWJsZWQgdGhlIG5vLXVudXNlZCB2YXJzIHJ1bGVcbiAgICAgICAgLy8gc28gdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIGZ1bGx5IGludGVycG9sYXRpb24tYWdub3N0aWMuIE90aGVyd2lzZSBpdCB3b3VsZCBuZWVkXG4gICAgICAgIC8vIHRvIGJlIGNhbGxlZCBkaWZmZXJlbnRseSBpbiBkaWZmZXJlbnQgY2FzZXMuIFdoaWNoIHdvdWxkbid0IGJlIHRoZSB3b3JzdCwgYnV0XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgICAgICAgICBpZighb3V0KSBvdXQgPSBbXTtcbiAgICAgICAgICAgIHZhciBmMCwgZjEsIGYyLCBmMywgaywgYWs7XG4gICAgICAgICAgICBqMCAqPSAzO1xuICAgICAgICAgICAgdmFyIHYyID0gdiAqIHY7XG4gICAgICAgICAgICB2YXIgdjMgPSB2MiAqIHY7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIHZhciBvdjIgPSBvdiAqIG92O1xuICAgICAgICAgICAgdmFyIG92MyA9IG92MiAqIG92O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMF1baTAgKyAxXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMCArIDFdW2kwXTtcbiAgICAgICAgICAgICAgICBmMiA9IGFrW2owICsgMl1baTAgKyAxXSAtIGFrW2owICsgMl1baTBdO1xuICAgICAgICAgICAgICAgIGYzID0gYWtbajAgKyAzXVtpMCArIDFdIC0gYWtbajAgKyAzXVtpMF07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZpbmFsbHksIGJvdGggZGlyZWN0aW9ucyBhcmUgbGluZWFyOlxuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpMCwgajAsIHUsIHYpIHtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBrLCBhaztcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMF1baTAgKyAxXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMCArIDFdW2kwXTtcblxuICAgICAgICAgICAgICAgIG91dFtrXSA9IG92ICogZjAgKyB2ICogZjE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYXJyYXlzLCBhc21vb3RoaW5nLCBic21vb3RoaW5nKSB7XG4gICAgaWYoYXNtb290aGluZyAmJiBic21vb3RoaW5nKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGFrLCBrO1xuXG4gICAgICAgICAgICAvLyBTaW5jZSBpdCdzIGEgZ3JpZCBvZiBjb250cm9sIHBvaW50cywgdGhlIGFjdHVhbCBpbmRpY2VzIGFyZSAqIDM6XG4gICAgICAgICAgICBpMCAqPSAzO1xuICAgICAgICAgICAgajAgKj0gMztcblxuICAgICAgICAgICAgLy8gUHJlY29tcHV0ZSBzb21lIG51bWJlcnM6XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciB1MyA9IHUyICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3UzID0gb3UyICogb3U7XG5cbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdnYyID0gb3YgKiB2ICogMjtcbiAgICAgICAgICAgIHZhciBhID0gLTMgKiBvdjI7XG4gICAgICAgICAgICB2YXIgYiA9IDMgKiAob3YyIC0gb3Z2Mik7XG4gICAgICAgICAgICB2YXIgYyA9IDMgKiAob3Z2MiAtIHYyKTtcbiAgICAgICAgICAgIHZhciBkID0gMyAqIHYyO1xuXG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCBhcnJheXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBhayA9IGFycmF5c1trXTtcblxuICAgICAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGRlcml2YXRpdmVzIGluIHRoZSB2LWRpcmVjdGlvbjpcbiAgICAgICAgICAgICAgICBmMCA9IGEgKiBha1tqMF1baTBdICsgYiAqIGFrW2owICsgMV1baTBdICsgYyAqIGFrW2owICsgMl1baTBdICsgZCAqIGFrW2owICsgM11baTBdO1xuICAgICAgICAgICAgICAgIGYxID0gYSAqIGFrW2owXVtpMCArIDFdICsgYiAqIGFrW2owICsgMV1baTAgKyAxXSArIGMgKiBha1tqMCArIDJdW2kwICsgMV0gKyBkICogYWtbajAgKyAzXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYyID0gYSAqIGFrW2owXVtpMCArIDJdICsgYiAqIGFrW2owICsgMV1baTAgKyAyXSArIGMgKiBha1tqMCArIDJdW2kwICsgMl0gKyBkICogYWtbajAgKyAzXVtpMCArIDJdO1xuICAgICAgICAgICAgICAgIGYzID0gYSAqIGFrW2owXVtpMCArIDNdICsgYiAqIGFrW2owICsgMV1baTAgKyAzXSArIGMgKiBha1tqMCArIDJdW2kwICsgM10gKyBkICogYWtbajAgKyAzXVtpMCArIDNdO1xuXG4gICAgICAgICAgICAgICAgLy8gTm93IGp1c3QgaW50ZXJwb2xhdGUgaW4gdGhlIHYtZGlyZWN0aW9uIHNpbmNlIGl0J3MgYWxsIHNlcGFyYWJsZTpcbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdTMgKiBmMCArIDMgKiAob3UyICogdSAqIGYxICsgb3UgKiB1MiAqIGYyKSArIHUzICogZjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGFzbW9vdGhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIHNtb290aCBpbiB0aGUgYS1kaXJlY3Rpb24gYnV0IGxpbmVhciBpbiB0aGUgYi1kaXJlY3Rpb24gYnkgcGVyZm9ybWluZyBmb3VyXG4gICAgICAgIC8vIGxpbmVhciBpbnRlcnBvbGF0aW9ucyBmb2xsb3dlZCBieSBvbmUgY3ViaWMgaW50ZXJwb2xhdGlvbiBvZiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdiwgdSkge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGssIGFrO1xuICAgICAgICAgICAgaTAgKj0gMztcbiAgICAgICAgICAgIHZhciB1MiA9IHUgKiB1O1xuICAgICAgICAgICAgdmFyIHUzID0gdTIgKiB1O1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgb3UyID0gb3UgKiBvdTtcbiAgICAgICAgICAgIHZhciBvdTMgPSBvdTIgKiBvdTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuXG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMCArIDFdW2kwXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMF1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMiA9IGFrW2owICsgMV1baTAgKyAyXSAtIGFrW2owXVtpMCArIDJdO1xuICAgICAgICAgICAgICAgIGYzID0gYWtbajAgKyAxXVtpMCArIDNdIC0gYWtbajBdW2kwICsgM107XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdTMgKiBmMCArIDMgKiAob3UyICogdSAqIGYxICsgb3UgKiB1MiAqIGYyKSArIHUzICogZjM7XG5cbiAgICAgICAgICAgICAgICAvLyBtYXRoZW1hdGljYWxseSBlcXVpdmFsZW50OlxuICAgICAgICAgICAgICAgIC8vIGYwID0gb3UzICogYWtbajAgICAgXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCAgICBdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgICAgXVtpMCArIDJdKSArIHUzICogYWtbajAgICAgXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIC8vIGYxID0gb3UzICogYWtbajAgKyAxXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCArIDFdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgKyAxXVtpMCArIDJdKSArIHUzICogYWtbajAgKyAxXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIC8vIG91dFtrXSA9IGYxIC0gZjA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihic21vb3RoaW5nKSB7XG4gICAgICAgIC8vIFNhbWUgYXMgdGhlIGFib3ZlIGNhc2UsIGV4Y2VwdCByZXZlcnNlZDpcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaTAsIGowLCB1LCB2KSB7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgaywgYWs7XG4gICAgICAgICAgICBqMCAqPSAzO1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgdjIgPSB2ICogdjtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgdmFyIG92MiA9IG92ICogb3Y7XG4gICAgICAgICAgICB2YXIgb3Z2MiA9IG92ICogdiAqIDI7XG4gICAgICAgICAgICB2YXIgYSA9IC0zICogb3YyO1xuICAgICAgICAgICAgdmFyIGIgPSAzICogKG92MiAtIG92djIpO1xuICAgICAgICAgICAgdmFyIGMgPSAzICogKG92djIgLSB2Mik7XG4gICAgICAgICAgICB2YXIgZCA9IDMgKiB2MjtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gYSAqIGFrW2owXVtpMF0gKyBiICogYWtbajAgKyAxXVtpMF0gKyBjICogYWtbajAgKyAyXVtpMF0gKyBkICogYWtbajAgKyAzXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBhICogYWtbajBdW2kwICsgMV0gKyBiICogYWtbajAgKyAxXVtpMCArIDFdICsgYyAqIGFrW2owICsgMl1baTAgKyAxXSArIGQgKiBha1tqMCArIDNdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdSAqIGYwICsgdSAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGaW5hbGx5LCBib3RoIGRpcmVjdGlvbnMgYXJlIGxpbmVhcjpcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaTAsIGowLCB2LCB1KSB7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgaywgYWs7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gYWtbajAgKyAxXVtpMF0gLSBha1tqMF1baTBdO1xuICAgICAgICAgICAgICAgIGYxID0gYWtbajAgKyAxXVtpMCArIDFdIC0gYWtbajBdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdiAqIGYwICsgdiAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9XG5cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBSZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGV2YWx1YXRlcyBhIHNldCBvZiBsaW5lYXIgb3IgYmljdWJpYyBjb250cm9sIHBvaW50cy5cbiAqIFRoaXMgd2lsbCBnZXQgZXZhbHVhdGVkIGEgbG90LCBzbyB3ZSdsbCBhdCBsZWFzdCBkbyBhIGJpdCBvZiBleHRyYSB3b3JrIHRvXG4gKiBmbGF0dGVuIHNvbWUgb2YgdGhlIGNob2ljZXMuIEluIHBhcnRpY3VsYXIsIHdlJ2xsIHVucm9sbCB0aGUgbGluZWFyL2JpY3ViaWNcbiAqIGNvbWJpbmF0aW9ucyBhbmQgd2UnbGwgYWxsb3cgY29tcHV0aW5nIHJlc3VsdHMgaW4gcGFyYWxsZWwgdG8gY3V0IGRvd25cbiAqIG9uIHJlcGVhdGVkIGFyaXRobWV0aWMuXG4gKlxuICogVGFrZSBub3RlIHRoYXQgd2UgZG9uJ3Qgc2VhcmNoIGZvciB0aGUgY29ycmVjdCByYW5nZSBpbiB0aGlzIGZ1bmN0aW9uLiBUaGVcbiAqIHJlYXNvbiBpcyBmb3IgY29uc2lzdGVuY3kgZHVlIHRvIHRoZSBjb3JycmVzcG9uZGluZyBkZXJpdmF0aXZlIGZ1bmN0aW9uLiBJblxuICogcGFydGljdWxhciwgdGhlIGRlcml2YXRpdmVzIGFyZW4ndCBjb250aW51b3VzIGFjcm9zcyBjZWxscywgc28gaXQncyBpbXBvcnRhbnRcbiAqIHRvIGJlIGFibGUgY29udHJvbCB3aGV0aGVyIHRoZSBkZXJpdmF0aXZlIGF0IGEgY2VsbCBib3VuZGFyeSBpcyBhcHByb2FjaGVkXG4gKiBmcm9tIG9uZSBzaWRlIG9yIHRoZSBvdGhlci5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhcnJheXMsIG5hLCBuYiwgYXNtb290aGluZywgYnNtb290aGluZykge1xuICAgIHZhciBpbWF4ID0gbmEgLSAyO1xuICAgIHZhciBqbWF4ID0gbmIgLSAyO1xuXG4gICAgaWYoYXNtb290aGluZyAmJiBic21vb3RoaW5nKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGksIGopIHtcbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgZjIsIGYzLCBhaywgaztcblxuICAgICAgICAgICAgdmFyIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oTWF0aC5mbG9vcihpKSwgaW1heCkpO1xuICAgICAgICAgICAgdmFyIGowID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oTWF0aC5mbG9vcihqKSwgam1heCkpO1xuICAgICAgICAgICAgdmFyIHUgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBpIC0gaTApKTtcbiAgICAgICAgICAgIHZhciB2ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaiAtIGowKSk7XG5cbiAgICAgICAgICAgIC8vIFNpbmNlIGl0J3MgYSBncmlkIG9mIGNvbnRyb2wgcG9pbnRzLCB0aGUgYWN0dWFsIGluZGljZXMgYXJlICogMzpcbiAgICAgICAgICAgIGkwICo9IDM7XG4gICAgICAgICAgICBqMCAqPSAzO1xuXG4gICAgICAgICAgICAvLyBQcmVjb21wdXRlIHNvbWUgbnVtYmVyczpcbiAgICAgICAgICAgIHZhciB1MiA9IHUgKiB1O1xuICAgICAgICAgICAgdmFyIHUzID0gdTIgKiB1O1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgb3UyID0gb3UgKiBvdTtcbiAgICAgICAgICAgIHZhciBvdTMgPSBvdTIgKiBvdTtcblxuICAgICAgICAgICAgdmFyIHYyID0gdiAqIHY7XG4gICAgICAgICAgICB2YXIgdjMgPSB2MiAqIHY7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIHZhciBvdjIgPSBvdiAqIG92O1xuICAgICAgICAgICAgdmFyIG92MyA9IG92MiAqIG92O1xuXG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCBhcnJheXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBhayA9IGFycmF5c1trXTtcbiAgICAgICAgICAgICAgICBmMCA9IG91MyAqIGFrW2owXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMF1baTAgKyAxXSArIG91ICogdTIgKiBha1tqMF1baTAgKyAyXSkgKyB1MyAqIGFrW2owXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYxID0gb3UzICogYWtbajAgKyAxXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCArIDFdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgKyAxXVtpMCArIDJdKSArIHUzICogYWtbajAgKyAxXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYyID0gb3UzICogYWtbajAgKyAyXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCArIDJdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgKyAyXVtpMCArIDJdKSArIHUzICogYWtbajAgKyAyXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYzID0gb3UzICogYWtbajAgKyAzXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCArIDNdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgKyAzXVtpMCArIDJdKSArIHUzICogYWtbajAgKyAzXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIG91dFtrXSA9IG92MyAqIGYwICsgMyAqIChvdjIgKiB2ICogZjEgKyBvdiAqIHYyICogZjIpICsgdjMgKiBmMztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoYXNtb290aGluZykge1xuICAgICAgICAvLyBIYW5kbGUgc21vb3RoIGluIHRoZSBhLWRpcmVjdGlvbiBidXQgbGluZWFyIGluIHRoZSBiLWRpcmVjdGlvbiBieSBwZXJmb3JtaW5nIGZvdXJcbiAgICAgICAgLy8gbGluZWFyIGludGVycG9sYXRpb25zIGZvbGxvd2VkIGJ5IG9uZSBjdWJpYyBpbnRlcnBvbGF0aW9uIG9mIHRoZSByZXN1bHRcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaSwgaikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG5cbiAgICAgICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaSksIGltYXgpKTtcbiAgICAgICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaiksIGptYXgpKTtcbiAgICAgICAgICAgIHZhciB1ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaSAtIGkwKSk7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGogLSBqMCkpO1xuXG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGssIGFrO1xuICAgICAgICAgICAgaTAgKj0gMztcbiAgICAgICAgICAgIHZhciB1MiA9IHUgKiB1O1xuICAgICAgICAgICAgdmFyIHUzID0gdTIgKiB1O1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgb3UyID0gb3UgKiBvdTtcbiAgICAgICAgICAgIHZhciBvdTMgPSBvdTIgKiBvdTtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBvdiAqIGFrW2owXVtpMF0gKyB2ICogYWtbajAgKyAxXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBvdiAqIGFrW2owXVtpMCArIDFdICsgdiAqIGFrW2owICsgMV1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMiA9IG92ICogYWtbajBdW2kwICsgMl0gKyB2ICogYWtbajAgKyAxXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYzID0gb3YgKiBha1tqMF1baTAgKyAzXSArIHYgKiBha1tqMCArIDFdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdTMgKiBmMCArIDMgKiAob3UyICogdSAqIGYxICsgb3UgKiB1MiAqIGYyKSArIHUzICogZjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihic21vb3RoaW5nKSB7XG4gICAgICAgIC8vIFNhbWUgYXMgdGhlIGFib3ZlIGNhc2UsIGV4Y2VwdCByZXZlcnNlZDpcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaSwgaikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG5cbiAgICAgICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaSksIGltYXgpKTtcbiAgICAgICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaiksIGptYXgpKTtcbiAgICAgICAgICAgIHZhciB1ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaSAtIGkwKSk7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGogLSBqMCkpO1xuXG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGssIGFrO1xuICAgICAgICAgICAgajAgKj0gMztcbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIHYzID0gdjIgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdjMgPSBvdjIgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBvdSAqIGFrW2owXVtpMF0gKyB1ICogYWtbajBdW2kwICsgMV07XG4gICAgICAgICAgICAgICAgZjEgPSBvdSAqIGFrW2owICsgMV1baTBdICsgdSAqIGFrW2owICsgMV1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMiA9IG91ICogYWtbajAgKyAyXVtpMF0gKyB1ICogYWtbajAgKyAyXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYzID0gb3UgKiBha1tqMCArIDNdW2kwXSArIHUgKiBha1tqMCArIDNdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZpbmFsbHksIGJvdGggZGlyZWN0aW9ucyBhcmUgbGluZWFyOlxuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpLCBqKSB7XG4gICAgICAgICAgICBpZighb3V0KSBvdXQgPSBbXTtcblxuICAgICAgICAgICAgdmFyIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oTWF0aC5mbG9vcihpKSwgaW1heCkpO1xuICAgICAgICAgICAgdmFyIGowID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oTWF0aC5mbG9vcihqKSwgam1heCkpO1xuICAgICAgICAgICAgdmFyIHUgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBpIC0gaTApKTtcbiAgICAgICAgICAgIHZhciB2ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaiAtIGowKSk7XG5cbiAgICAgICAgICAgIHZhciBmMCwgZjEsIGssIGFrO1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3UgPSAxIC0gdTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gb3UgKiBha1tqMF1baTBdICsgdSAqIGFrW2owXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYxID0gb3UgKiBha1tqMCArIDFdW2kwXSArIHUgKiBha1tqMCArIDFdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdiAqIGYwICsgdiAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9XG5cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZVhZRGVmYXVsdHMgPSByZXF1aXJlKCcuL3h5X2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQUJEZWZhdWx0cyA9IHJlcXVpcmUoJy4vYWJfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZmx0Q29sb3IsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX2NsaXBQYXRoSWQgPSAnY2xpcCcgKyB0cmFjZU91dC51aWQgKyAnY2FycGV0JztcblxuICAgIHZhciBkZWZhdWx0Q29sb3IgPSBjb2VyY2UoJ2NvbG9yJywgY29sb3JBdHRycy5kZWZhdWx0TGluZSk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnZm9udCcpO1xuXG4gICAgY29lcmNlKCdjYXJwZXQnKTtcblxuICAgIGhhbmRsZUFCRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGZ1bGxMYXlvdXQsIGNvZXJjZSwgZGVmYXVsdENvbG9yKTtcblxuICAgIGlmKCF0cmFjZU91dC5hIHx8ICF0cmFjZU91dC5iKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0LmEubGVuZ3RoIDwgMykge1xuICAgICAgICB0cmFjZU91dC5hYXhpcy5zbW9vdGhpbmcgPSAwO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0LmIubGVuZ3RoIDwgMykge1xuICAgICAgICB0cmFjZU91dC5iYXhpcy5zbW9vdGhpbmcgPSAwO1xuICAgIH1cblxuICAgIC8vIE5COiB0aGUgaW5wdXQgaXMgeC95IGFycmF5cy4gWW91IHNob3VsZCBrbm93IHRoYXQgdGhlICpmaXJzdCogZGltZW5zaW9uIG9mIHggYW5kIHlcbiAgICAvLyBjb3JyZXNwb25kcyB0byBiIGFuZCB0aGUgc2Vjb25kIHRvIGEuIFRoaXMgc291bmRzIGJhY2t3YXJkcyBidXQgZW5kcyB1cCBtYWtpbmcgc2Vuc2VcbiAgICAvLyB0aGUgaW1wb3J0YW50IHBhcnQgdG8ga25vdyBpcyB0aGF0IHdoZW4geW91IHdyaXRlIHlbal1baV0sIGogZ29lcyBmcm9tIDAgdG8gYi5sZW5ndGggLSAxXG4gICAgLy8gYW5kIGkgZ29lcyBmcm9tIDAgdG8gYS5sZW5ndGggLSAxLlxuICAgIHZhciB2YWxpZERhdGEgPSBoYW5kbGVYWURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgIGlmKCF2YWxpZERhdGEpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0Ll9jaGVhdGVyKSB7XG4gICAgICAgIGNvZXJjZSgnY2hlYXRlcnNsb3BlJyk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ2FycGV0ID0ge307XG5cbkNhcnBldC5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5DYXJwZXQuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5DYXJwZXQucGxvdCA9IHJlcXVpcmUoJy4vcGxvdCcpO1xuQ2FycGV0LmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKTtcbkNhcnBldC5hbmltYXRhYmxlID0gdHJ1ZTtcbkNhcnBldC5pc0NvbnRhaW5lciA9IHRydWU7IC8vIHNvIGNhcnBldCB0cmFjZXMgZ2V0IGBjYWxjYCBiZWZvcmUgb3RoZXIgdHJhY2VzXG5cbkNhcnBldC5tb2R1bGVUeXBlID0gJ3RyYWNlJztcbkNhcnBldC5uYW1lID0gJ2NhcnBldCc7XG5DYXJwZXQuYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcbkNhcnBldC5jYXRlZ29yaWVzID0gWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ2NhcnBldCcsICdjYXJwZXRBeGlzJywgJ25vdExlZ2VuZElzb2xhdGFibGUnXTtcbkNhcnBldC5tZXRhID0ge1xuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYXJwZXQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBHaXZlbiBhIHRyYWNlLCBsb29rIHVwIHRoZSBjYXJwZXQgYXhpcyBieSBjYXJwZXQuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZ2QsIHRyYWNlKSB7XG4gICAgdmFyIG4gPSBnZC5fZnVsbERhdGEubGVuZ3RoO1xuICAgIHZhciBmaXJzdEF4aXM7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICB2YXIgbWF5YmVDYXJwZXQgPSBnZC5fZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYobWF5YmVDYXJwZXQuaW5kZXggPT09IHRyYWNlLmluZGV4KSBjb250aW51ZTtcblxuICAgICAgICBpZihtYXliZUNhcnBldC50eXBlID09PSAnY2FycGV0Jykge1xuICAgICAgICAgICAgaWYoIWZpcnN0QXhpcykge1xuICAgICAgICAgICAgICAgIGZpcnN0QXhpcyA9IG1heWJlQ2FycGV0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihtYXliZUNhcnBldC5jYXJwZXQgPT09IHRyYWNlLmNhcnBldCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXliZUNhcnBldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaXJzdEF4aXM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VQYXRoKHhwLCB5cCwgaXNCaWN1YmljKSB7XG4gICAgLy8gUHJldmVudCBkMyBlcnJvcnMgdGhhdCB3b3VsZCByZXN1bHQgb3RoZXJ3aXNlOlxuICAgIGlmKHhwLmxlbmd0aCA9PT0gMCkgcmV0dXJuICcnO1xuXG4gICAgdmFyIGksIHBhdGggPSBbXTtcbiAgICB2YXIgc3RyaWRlID0gaXNCaWN1YmljID8gMyA6IDE7XG4gICAgZm9yKGkgPSAwOyBpIDwgeHAubGVuZ3RoOyBpICs9IHN0cmlkZSkge1xuICAgICAgICBwYXRoLnB1c2goeHBbaV0gKyAnLCcgKyB5cFtpXSk7XG5cbiAgICAgICAgaWYoaXNCaWN1YmljICYmIGkgPCB4cC5sZW5ndGggLSBzdHJpZGUpIHtcbiAgICAgICAgICAgIHBhdGgucHVzaCgnQycpO1xuICAgICAgICAgICAgcGF0aC5wdXNoKFtcbiAgICAgICAgICAgICAgICB4cFtpICsgMV0gKyAnLCcgKyB5cFtpICsgMV0sXG4gICAgICAgICAgICAgICAgeHBbaSArIDJdICsgJywnICsgeXBbaSArIDJdICsgJyAnLFxuICAgICAgICAgICAgXS5qb2luKCcgJykpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXRoLmpvaW4oaXNCaWN1YmljID8gJycgOiAnTCcpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9saWInKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG4vKlxuICogTWFwIGFuIGFycmF5IG9mIHggb3IgeSBjb29yZGluYXRlcyAoYykgdG8gc2NyZWVuLXNwYWNlIHBpeGVsIGNvb3JkaW5hdGVzIChwKS5cbiAqIFRoZSBvdXRwdXQgYXJyYXkgaXMgb3B0aW9uYWwsIGJ1dCBpZiBwcm92aWRlZCwgaXQgd2lsbCBiZSByZXVzZWQgd2l0aG91dFxuICogcmVhbGxvY2F0aW9uIHRvIHRoZSBleHRlbnQgcG9zc2libGUuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFwQXJyYXkob3V0LCBkYXRhLCBmdW5jKSB7XG4gICAgdmFyIGk7XG5cbiAgICBpZighaXNBcnJheU9yVHlwZWRBcnJheShvdXQpKSB7XG4gICAgICAgIC8vIElmIG5vdCBhbiBhcnJheSwgbWFrZSBpdCBhbiBhcnJheTpcbiAgICAgICAgb3V0ID0gW107XG4gICAgfSBlbHNlIGlmKG91dC5sZW5ndGggPiBkYXRhLmxlbmd0aCkge1xuICAgICAgICAvLyBJZiB0b28gbG9uZywgdHJ1bmNhdGUuIChJZiB0b28gc2hvcnQsIGl0IHdpbGwgZ3Jvd1xuICAgICAgICAvLyBhdXRvbWF0aWNhbGx5IHNvIHdlIGRvbid0IGNhcmUgYWJvdXQgdGhhdCBjYXNlKVxuICAgICAgICBvdXQgPSBvdXQuc2xpY2UoMCwgZGF0YS5sZW5ndGgpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gZnVuYyhkYXRhW2ldKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG9yaWVudFRleHQodHJhY2UsIHhheGlzLCB5YXhpcywgeHksIGR4eSwgcmVmRHh5KSB7XG4gICAgdmFyIGR4ID0gZHh5WzBdICogdHJhY2UuZHBkeCh4YXhpcyk7XG4gICAgdmFyIGR5ID0gZHh5WzFdICogdHJhY2UuZHBkeSh5YXhpcyk7XG4gICAgdmFyIGZsaXAgPSAxO1xuXG4gICAgdmFyIG9mZnNldE11bHRpcGxpZXIgPSAxLjA7XG4gICAgaWYocmVmRHh5KSB7XG4gICAgICAgIHZhciBsMSA9IE1hdGguc3FydChkeHlbMF0gKiBkeHlbMF0gKyBkeHlbMV0gKiBkeHlbMV0pO1xuICAgICAgICB2YXIgbDIgPSBNYXRoLnNxcnQocmVmRHh5WzBdICogcmVmRHh5WzBdICsgcmVmRHh5WzFdICogcmVmRHh5WzFdKTtcbiAgICAgICAgdmFyIGRvdCA9IChkeHlbMF0gKiByZWZEeHlbMF0gKyBkeHlbMV0gKiByZWZEeHlbMV0pIC8gbDEgLyBsMjtcbiAgICAgICAgb2Zmc2V0TXVsdGlwbGllciA9IE1hdGgubWF4KDAuMCwgZG90KTtcbiAgICB9XG5cbiAgICB2YXIgYW5nbGUgPSBNYXRoLmF0YW4yKGR5LCBkeCkgKiAxODAgLyBNYXRoLlBJO1xuICAgIGlmKGFuZ2xlIDwgLTkwKSB7XG4gICAgICAgIGFuZ2xlICs9IDE4MDtcbiAgICAgICAgZmxpcCA9IC1mbGlwO1xuICAgIH0gZWxzZSBpZihhbmdsZSA+IDkwKSB7XG4gICAgICAgIGFuZ2xlIC09IDE4MDtcbiAgICAgICAgZmxpcCA9IC1mbGlwO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGFuZ2xlOiBhbmdsZSxcbiAgICAgICAgZmxpcDogZmxpcCxcbiAgICAgICAgcDogdHJhY2UuYzJwKHh5LCB4YXhpcywgeWF4aXMpLFxuICAgICAgICBvZmZzZXRNdWx0cGxpZXI6IG9mZnNldE11bHRpcGxpZXJcbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBtYXAxZEFycmF5ID0gcmVxdWlyZSgnLi9tYXBfMWRfYXJyYXknKTtcbnZhciBtYWtlcGF0aCA9IHJlcXVpcmUoJy4vbWFrZXBhdGgnKTtcbnZhciBvcmllbnRUZXh0ID0gcmVxdWlyZSgnLi9vcmllbnRfdGV4dCcpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGFsaWdubWVudENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2RjYXJwZXQsIGNhcnBldExheWVyKSB7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2xpcExheWVyID0gZnVsbExheW91dC5fY2xpcHM7XG5cbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGNhcnBldExheWVyLCBjZGNhcnBldCwgJ3RyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgYXhpc0xheWVyID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIGFheCA9IHRyYWNlLmFheGlzO1xuICAgICAgICB2YXIgYmF4ID0gdHJhY2UuYmF4aXM7XG5cbiAgICAgICAgdmFyIG1pbm9yTGF5ZXIgPSBMaWIuZW5zdXJlU2luZ2xlKGF4aXNMYXllciwgJ2cnLCAnbWlub3JsYXllcicpO1xuICAgICAgICB2YXIgbWFqb3JMYXllciA9IExpYi5lbnN1cmVTaW5nbGUoYXhpc0xheWVyLCAnZycsICdtYWpvcmxheWVyJyk7XG4gICAgICAgIHZhciBib3VuZGFyeUxheWVyID0gTGliLmVuc3VyZVNpbmdsZShheGlzTGF5ZXIsICdnJywgJ2JvdW5kYXJ5bGF5ZXInKTtcbiAgICAgICAgdmFyIGxhYmVsTGF5ZXIgPSBMaWIuZW5zdXJlU2luZ2xlKGF4aXNMYXllciwgJ2cnLCAnbGFiZWxsYXllcicpO1xuXG4gICAgICAgIGF4aXNMYXllci5zdHlsZSgnb3BhY2l0eScsIHRyYWNlLm9wYWNpdHkpO1xuXG4gICAgICAgIGRyYXdHcmlkTGluZXMoeGEsIHlhLCBtYWpvckxheWVyLCBhYXgsICdhJywgYWF4Ll9ncmlkbGluZXMsIHRydWUpO1xuICAgICAgICBkcmF3R3JpZExpbmVzKHhhLCB5YSwgbWFqb3JMYXllciwgYmF4LCAnYicsIGJheC5fZ3JpZGxpbmVzLCB0cnVlKTtcbiAgICAgICAgZHJhd0dyaWRMaW5lcyh4YSwgeWEsIG1pbm9yTGF5ZXIsIGFheCwgJ2EnLCBhYXguX21pbm9yZ3JpZGxpbmVzLCB0cnVlKTtcbiAgICAgICAgZHJhd0dyaWRMaW5lcyh4YSwgeWEsIG1pbm9yTGF5ZXIsIGJheCwgJ2InLCBiYXguX21pbm9yZ3JpZGxpbmVzLCB0cnVlKTtcblxuICAgICAgICAvLyBOQjogVGhlc2UgYXJlIG5vdCBvbW1pdHRlZCBpZiB0aGUgbGluZXMgYXJlIG5vdCBhY3RpdmUuIFRoZSBqb2lucyBtdXN0IGJlIGV4ZWN1dGVkXG4gICAgICAgIC8vIGluIG9yZGVyIGZvciB0aGVtIHRvIGdldCBjbGVhbmVkIHVwIHdpdGhvdXQgYSBmdWxsIHJlZHJhd1xuICAgICAgICBkcmF3R3JpZExpbmVzKHhhLCB5YSwgYm91bmRhcnlMYXllciwgYWF4LCAnYS1ib3VuZGFyeScsIGFheC5fYm91bmRhcnlsaW5lcyk7XG4gICAgICAgIGRyYXdHcmlkTGluZXMoeGEsIHlhLCBib3VuZGFyeUxheWVyLCBiYXgsICdiLWJvdW5kYXJ5JywgYmF4Ll9ib3VuZGFyeWxpbmVzKTtcblxuICAgICAgICB2YXIgbGFiZWxPcmllbnRhdGlvbkEgPSBkcmF3QXhpc0xhYmVscyhnZCwgeGEsIHlhLCB0cmFjZSwgY2QwLCBsYWJlbExheWVyLCBhYXguX2xhYmVscywgJ2EtbGFiZWwnKTtcbiAgICAgICAgdmFyIGxhYmVsT3JpZW50YXRpb25CID0gZHJhd0F4aXNMYWJlbHMoZ2QsIHhhLCB5YSwgdHJhY2UsIGNkMCwgbGFiZWxMYXllciwgYmF4Ll9sYWJlbHMsICdiLWxhYmVsJyk7XG5cbiAgICAgICAgZHJhd0F4aXNUaXRsZXMoZ2QsIGxhYmVsTGF5ZXIsIHRyYWNlLCBjZDAsIHhhLCB5YSwgbGFiZWxPcmllbnRhdGlvbkEsIGxhYmVsT3JpZW50YXRpb25CKTtcblxuICAgICAgICBkcmF3Q2xpcFBhdGgodHJhY2UsIGNkMCwgY2xpcExheWVyLCB4YSwgeWEpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gZHJhd0NsaXBQYXRoKHRyYWNlLCB0LCBsYXllciwgeGF4aXMsIHlheGlzKSB7XG4gICAgdmFyIHNlZywgeHAsIHlwLCBpO1xuXG4gICAgdmFyIGNsaXAgPSBsYXllci5zZWxlY3QoJyMnICsgdHJhY2UuX2NsaXBQYXRoSWQpO1xuXG4gICAgaWYoIWNsaXAuc2l6ZSgpKSB7XG4gICAgICAgIGNsaXAgPSBsYXllci5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdjYXJwZXRjbGlwJywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdmFyIHBhdGggPSBMaWIuZW5zdXJlU2luZ2xlKGNsaXAsICdwYXRoJywgJ2NhcnBldGJvdW5kYXJ5Jyk7XG4gICAgdmFyIHNlZ21lbnRzID0gdC5jbGlwc2VnbWVudHM7XG4gICAgdmFyIHNlZ3MgPSBbXTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlZyA9IHNlZ21lbnRzW2ldO1xuICAgICAgICB4cCA9IG1hcDFkQXJyYXkoW10sIHNlZy54LCB4YXhpcy5jMnApO1xuICAgICAgICB5cCA9IG1hcDFkQXJyYXkoW10sIHNlZy55LCB5YXhpcy5jMnApO1xuICAgICAgICBzZWdzLnB1c2gobWFrZXBhdGgoeHAsIHlwLCBzZWcuYmljdWJpYykpO1xuICAgIH1cblxuICAgIC8vIFRoaXMgY291bGQgYmUgb3B0aW1pemVkIGV2ZXIgc28gc2xpZ2h0bHkgdG8gYXZvaWQgbm8tb3AgTCBzZWdtZW50c1xuICAgIC8vIGF0IHRoZSBjb3JuZXJzLCBidXQgaXQncyBzbyBuZWdsaWdpYmxlIHRoYXQgSSBkb24ndCB0aGluayBpdCdzIHdvcnRoXG4gICAgLy8gdGhlIGV4dHJhIGNvbXBsZXhpdHlcbiAgICB2YXIgY2xpcFBhdGhEYXRhID0gJ00nICsgc2Vncy5qb2luKCdMJykgKyAnWic7XG4gICAgY2xpcC5hdHRyKCdpZCcsIHRyYWNlLl9jbGlwUGF0aElkKTtcbiAgICBwYXRoLmF0dHIoJ2QnLCBjbGlwUGF0aERhdGEpO1xufVxuXG5mdW5jdGlvbiBkcmF3R3JpZExpbmVzKHhheGlzLCB5YXhpcywgbGF5ZXIsIGF4aXMsIGF4aXNMZXR0ZXIsIGdyaWRsaW5lcykge1xuICAgIHZhciBsaW5lQ2xhc3MgPSAnY29uc3QtJyArIGF4aXNMZXR0ZXIgKyAnLWxpbmVzJztcbiAgICB2YXIgZ3JpZEpvaW4gPSBsYXllci5zZWxlY3RBbGwoJy4nICsgbGluZUNsYXNzKS5kYXRhKGdyaWRsaW5lcyk7XG5cbiAgICBncmlkSm9pbi5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGxpbmVDbGFzcywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpO1xuXG4gICAgZ3JpZEpvaW4uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBncmlkbGluZSA9IGQ7XG4gICAgICAgIHZhciB4ID0gZ3JpZGxpbmUueDtcbiAgICAgICAgdmFyIHkgPSBncmlkbGluZS55O1xuXG4gICAgICAgIHZhciB4cCA9IG1hcDFkQXJyYXkoW10sIHgsIHhheGlzLmMycCk7XG4gICAgICAgIHZhciB5cCA9IG1hcDFkQXJyYXkoW10sIHksIHlheGlzLmMycCk7XG5cbiAgICAgICAgdmFyIHBhdGggPSAnTScgKyBtYWtlcGF0aCh4cCwgeXAsIGdyaWRsaW5lLnNtb290aGluZyk7XG5cbiAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGVsLmF0dHIoJ2QnLCBwYXRoKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBncmlkbGluZS53aWR0aClcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgZ3JpZGxpbmUuY29sb3IpXG4gICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpO1xuICAgIH0pO1xuXG4gICAgZ3JpZEpvaW4uZXhpdCgpLnJlbW92ZSgpO1xufVxuXG5mdW5jdGlvbiBkcmF3QXhpc0xhYmVscyhnZCwgeGF4aXMsIHlheGlzLCB0cmFjZSwgdCwgbGF5ZXIsIGxhYmVscywgbGFiZWxDbGFzcykge1xuICAgIHZhciBsYWJlbEpvaW4gPSBsYXllci5zZWxlY3RBbGwoJ3RleHQuJyArIGxhYmVsQ2xhc3MpLmRhdGEobGFiZWxzKTtcblxuICAgIGxhYmVsSm9pbi5lbnRlcigpLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5jbGFzc2VkKGxhYmVsQ2xhc3MsIHRydWUpO1xuXG4gICAgdmFyIG1heEV4dGVudCA9IDA7XG4gICAgdmFyIGxhYmVsT3JpZW50YXRpb24gPSB7fTtcblxuICAgIGxhYmVsSm9pbi5lYWNoKGZ1bmN0aW9uKGxhYmVsLCBpKSB7XG4gICAgICAgIC8vIE1vc3Qgb2YgdGhlIHBvc2l0aW9uaW5nIGlzIGRvbmUgaW4gY2FsY19sYWJlbHMuIE9ubHkgdGhlIHBhcnRzIHRoYXQgZGVwZW5kIHVwb25cbiAgICAgICAgLy8gdGhlIHNjcmVlbiBzcGFjZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgeCBhbmQgeSBheGVzIGFyZSBoZXJlOlxuICAgICAgICB2YXIgb3JpZW50YXRpb247XG4gICAgICAgIGlmKGxhYmVsLmF4aXMudGlja2FuZ2xlID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG9yaWVudGF0aW9uID0gb3JpZW50VGV4dCh0cmFjZSwgeGF4aXMsIHlheGlzLCBsYWJlbC54eSwgbGFiZWwuZHh5KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBhbmdsZSA9IChsYWJlbC5heGlzLnRpY2thbmdsZSArIDE4MC4wKSAqIE1hdGguUEkgLyAxODAuMDtcbiAgICAgICAgICAgIG9yaWVudGF0aW9uID0gb3JpZW50VGV4dCh0cmFjZSwgeGF4aXMsIHlheGlzLCBsYWJlbC54eSwgW01hdGguY29zKGFuZ2xlKSwgTWF0aC5zaW4oYW5nbGUpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZighaSkge1xuICAgICAgICAgICAgLy8gVE9ETzogb2Zmc2V0TXVsdGlwbGllcj8gTm90IGN1cnJlbnRseSB1c2VkIGFueXdoZXJlLi4uXG4gICAgICAgICAgICBsYWJlbE9yaWVudGF0aW9uID0ge2FuZ2xlOiBvcmllbnRhdGlvbi5hbmdsZSwgZmxpcDogb3JpZW50YXRpb24uZmxpcH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IChsYWJlbC5lbmRBbmNob3IgPyAtMSA6IDEpICogb3JpZW50YXRpb24uZmxpcDtcblxuICAgICAgICB2YXIgbGFiZWxFbCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IGRpcmVjdGlvbiA+IDAgPyAnc3RhcnQnIDogJ2VuZCcsXG4gICAgICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBsYWJlbC5mb250KVxuICAgICAgICAgICAgLnRleHQobGFiZWwudGV4dClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICB2YXIgYmJveCA9IERyYXdpbmcuYkJveCh0aGlzKTtcblxuICAgICAgICBsYWJlbEVsLmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgLy8gVHJhbnNsYXRlIHRvIHRoZSBjb3JyZWN0IHBvaW50OlxuICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIG9yaWVudGF0aW9uLnBbMF0gKyAnLCcgKyBvcmllbnRhdGlvbi5wWzFdICsgJykgJyArXG4gICAgICAgICAgICAgICAgLy8gUm90YXRlIHRvIGxpbmUgdXAgd2l0aCBncmlkIGxpbmUgdGFuZ2VudDpcbiAgICAgICAgICAgICAgICAncm90YXRlKCcgKyBvcmllbnRhdGlvbi5hbmdsZSArICcpJyArXG4gICAgICAgICAgICAgICAgLy8gQWRqdXN0IHRoZSBiYXNlbGluZSBhbmQgaW5kZW50YXRpb246XG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgbGFiZWwuYXhpcy5sYWJlbHBhZGRpbmcgKiBkaXJlY3Rpb24gKyAnLCcgKyBiYm94LmhlaWdodCAqIDAuMyArICcpJ1xuICAgICAgICAgICAgKTtcblxuICAgICAgICBtYXhFeHRlbnQgPSBNYXRoLm1heChtYXhFeHRlbnQsIGJib3gud2lkdGggKyBsYWJlbC5heGlzLmxhYmVscGFkZGluZyk7XG4gICAgfSk7XG5cbiAgICBsYWJlbEpvaW4uZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGFiZWxPcmllbnRhdGlvbi5tYXhFeHRlbnQgPSBtYXhFeHRlbnQ7XG4gICAgcmV0dXJuIGxhYmVsT3JpZW50YXRpb247XG59XG5cbmZ1bmN0aW9uIGRyYXdBeGlzVGl0bGVzKGdkLCBsYXllciwgdHJhY2UsIHQsIHhhLCB5YSwgbGFiZWxPcmllbnRhdGlvbkEsIGxhYmVsT3JpZW50YXRpb25CKSB7XG4gICAgdmFyIGEsIGIsIHh5LCBkeHk7XG5cbiAgICBhID0gMC41ICogKHRyYWNlLmFbMF0gKyB0cmFjZS5hW3RyYWNlLmEubGVuZ3RoIC0gMV0pO1xuICAgIGIgPSB0cmFjZS5iWzBdO1xuICAgIHh5ID0gdHJhY2UuYWIyeHkoYSwgYiwgdHJ1ZSk7XG4gICAgZHh5ID0gdHJhY2UuZHh5ZGFfcm91Z2goYSwgYik7XG4gICAgaWYobGFiZWxPcmllbnRhdGlvbkEuYW5nbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChsYWJlbE9yaWVudGF0aW9uQSwgb3JpZW50VGV4dCh0cmFjZSwgeGEsIHlhLCB4eSwgdHJhY2UuZHh5ZGJfcm91Z2goYSwgYikpKTtcbiAgICB9XG4gICAgZHJhd0F4aXNUaXRsZShnZCwgbGF5ZXIsIHRyYWNlLCB0LCB4eSwgZHh5LCB0cmFjZS5hYXhpcywgeGEsIHlhLCBsYWJlbE9yaWVudGF0aW9uQSwgJ2EtdGl0bGUnKTtcblxuICAgIGEgPSB0cmFjZS5hWzBdO1xuICAgIGIgPSAwLjUgKiAodHJhY2UuYlswXSArIHRyYWNlLmJbdHJhY2UuYi5sZW5ndGggLSAxXSk7XG4gICAgeHkgPSB0cmFjZS5hYjJ4eShhLCBiLCB0cnVlKTtcbiAgICBkeHkgPSB0cmFjZS5keHlkYl9yb3VnaChhLCBiKTtcbiAgICBpZihsYWJlbE9yaWVudGF0aW9uQi5hbmdsZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KGxhYmVsT3JpZW50YXRpb25CLCBvcmllbnRUZXh0KHRyYWNlLCB4YSwgeWEsIHh5LCB0cmFjZS5keHlkYV9yb3VnaChhLCBiKSkpO1xuICAgIH1cbiAgICBkcmF3QXhpc1RpdGxlKGdkLCBsYXllciwgdHJhY2UsIHQsIHh5LCBkeHksIHRyYWNlLmJheGlzLCB4YSwgeWEsIGxhYmVsT3JpZW50YXRpb25CLCAnYi10aXRsZScpO1xufVxuXG52YXIgbGluZVNwYWNpbmcgPSBhbGlnbm1lbnRDb25zdGFudHMuTElORV9TUEFDSU5HO1xudmFyIG1pZFNoaWZ0ID0gKCgxIC0gYWxpZ25tZW50Q29uc3RhbnRzLk1JRF9TSElGVCkgLyBsaW5lU3BhY2luZykgKyAxO1xuXG5mdW5jdGlvbiBkcmF3QXhpc1RpdGxlKGdkLCBsYXllciwgdHJhY2UsIHQsIHh5LCBkeHksIGF4aXMsIHhhLCB5YSwgbGFiZWxPcmllbnRhdGlvbiwgbGFiZWxDbGFzcykge1xuICAgIHZhciBkYXRhID0gW107XG4gICAgaWYoYXhpcy50aXRsZSkgZGF0YS5wdXNoKGF4aXMudGl0bGUpO1xuICAgIHZhciB0aXRsZUpvaW4gPSBsYXllci5zZWxlY3RBbGwoJ3RleHQuJyArIGxhYmVsQ2xhc3MpLmRhdGEoZGF0YSk7XG4gICAgdmFyIG9mZnNldCA9IGxhYmVsT3JpZW50YXRpb24ubWF4RXh0ZW50O1xuXG4gICAgdGl0bGVKb2luLmVudGVyKCkuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQobGFiZWxDbGFzcywgdHJ1ZSk7XG5cbiAgICAvLyBUaGVyZSdzIG9ubHkgb25lLCBidXQgd2UnbGwgZG8gaXQgYXMgYSBqb2luIHNvIGl0J3MgdXBkYXRlZCBuaWNlbHk6XG4gICAgdGl0bGVKb2luLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBvcmllbnRhdGlvbiA9IG9yaWVudFRleHQodHJhY2UsIHhhLCB5YSwgeHksIGR4eSk7XG5cbiAgICAgICAgaWYoWydzdGFydCcsICdib3RoJ10uaW5kZXhPZihheGlzLnNob3d0aWNrbGFiZWxzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJbiBhZGRpdGlvbiB0byB0aGUgc2l6ZSBvZiB0aGUgbGFiZWxzLCBhZGQgb24gc29tZSBleHRyYSBwYWRkaW5nOlxuICAgICAgICB2YXIgdGl0bGVTaXplID0gYXhpcy50aXRsZWZvbnQuc2l6ZTtcbiAgICAgICAgb2Zmc2V0ICs9IHRpdGxlU2l6ZSArIGF4aXMudGl0bGVvZmZzZXQ7XG5cbiAgICAgICAgdmFyIGxhYmVsTm9ybSA9IGxhYmVsT3JpZW50YXRpb24uYW5nbGUgKyAobGFiZWxPcmllbnRhdGlvbi5mbGlwIDwgMCA/IDE4MCA6IDApO1xuICAgICAgICB2YXIgYW5nbGVEaWZmID0gKGxhYmVsTm9ybSAtIG9yaWVudGF0aW9uLmFuZ2xlICsgNDUwKSAlIDM2MDtcbiAgICAgICAgdmFyIHJldmVyc2VUaXRsZSA9IGFuZ2xlRGlmZiA+IDkwICYmIGFuZ2xlRGlmZiA8IDI3MDtcblxuICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgZWwudGV4dChheGlzLnRpdGxlIHx8ICcnKVxuICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgIGlmKHJldmVyc2VUaXRsZSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gKC1zdmdUZXh0VXRpbHMubGluZUNvdW50KGVsKSArIG1pZFNoaWZ0KSAqIGxpbmVTcGFjaW5nICogdGl0bGVTaXplIC0gb2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgZWwuYXR0cigndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyBvcmllbnRhdGlvbi5wWzBdICsgJywnICsgb3JpZW50YXRpb24ucFsxXSArICcpICcgK1xuICAgICAgICAgICAgICAgICdyb3RhdGUoJyArIG9yaWVudGF0aW9uLmFuZ2xlICsgJykgJyArXG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgwLCcgKyBvZmZzZXQgKyAnKSdcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jbGFzc2VkKCd1c2VyLXNlbGVjdC1ub25lJywgdHJ1ZSlcbiAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBheGlzLnRpdGxlZm9udCk7XG4gICAgfSk7XG5cbiAgICB0aXRsZUpvaW4uZXhpdCgpLnJlbW92ZSgpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBzZWFyY2ggPSByZXF1aXJlKCcuLi8uLi9saWIvc2VhcmNoJykuZmluZEJpbjtcbnZhciBjb21wdXRlQ29udHJvbFBvaW50cyA9IHJlcXVpcmUoJy4vY29tcHV0ZV9jb250cm9sX3BvaW50cycpO1xudmFyIGNyZWF0ZVNwbGluZUV2YWx1YXRvciA9IHJlcXVpcmUoJy4vY3JlYXRlX3NwbGluZV9ldmFsdWF0b3InKTtcbnZhciBjcmVhdGVJRGVyaXZhdGl2ZUV2YWx1YXRvciA9IHJlcXVpcmUoJy4vY3JlYXRlX2lfZGVyaXZhdGl2ZV9ldmFsdWF0b3InKTtcbnZhciBjcmVhdGVKRGVyaXZhdGl2ZUV2YWx1YXRvciA9IHJlcXVpcmUoJy4vY3JlYXRlX2pfZGVyaXZhdGl2ZV9ldmFsdWF0b3InKTtcblxuLypcbiAqIENyZWF0ZSBjb252ZXJzaW9uIGZ1bmN0aW9ucyB0byBnbyBmcm9tIG9uZSBiYXNpcyB0byBhbm90aGVyLiBJbiBwYXJ0aWN1bGFyIHRoZSBsZXR0ZXJcbiAqIGFiYnJldmlhdGlvbnMgYXJlOlxuICpcbiAqICAgaTogaS9qIGNvb3JkaW5hdGVzIGFsb25nIHRoZSBncmlkLiBJbnRlZ2VyIHZhbHVlcyBjb3JyZXNwb25kIHRvIGRhdGEgcG9pbnRzXG4gKiAgIGE6IHJlYWwtdmFsdWVkIGNvb3JkaW5hdGVzIGFsb25nIHRoZSBhL2IgYXhlc1xuICogICBjOiBjYXJ0ZXNpYW4geC15IGNvb3JkaW5hdGVzXG4gKiAgIHA6IHNjcmVlbi1zcGFjZSBwaXhlbCBjb29yZGluYXRlc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNldENvbnZlcnQodHJhY2UpIHtcbiAgICB2YXIgYSA9IHRyYWNlLl9hO1xuICAgIHZhciBiID0gdHJhY2UuX2I7XG4gICAgdmFyIG5hID0gYS5sZW5ndGg7XG4gICAgdmFyIG5iID0gYi5sZW5ndGg7XG4gICAgdmFyIGFheCA9IHRyYWNlLmFheGlzO1xuICAgIHZhciBiYXggPSB0cmFjZS5iYXhpcztcblxuICAgIC8vIEdyYWIgdGhlIGxpbWl0cyBvbmNlIHJhdGhlciB0aGFuIHJlY29tcHV0aW5nIHRoZSBib3VuZHMgZm9yIGV2ZXJ5IHBvaW50XG4gICAgLy8gaW5kZXBlbmRlbnRseTpcbiAgICB2YXIgYW1pbiA9IGFbMF07XG4gICAgdmFyIGFtYXggPSBhW25hIC0gMV07XG4gICAgdmFyIGJtaW4gPSBiWzBdO1xuICAgIHZhciBibWF4ID0gYltuYiAtIDFdO1xuICAgIHZhciBhcmFuZ2UgPSBhW2EubGVuZ3RoIC0gMV0gLSBhWzBdO1xuICAgIHZhciBicmFuZ2UgPSBiW2IubGVuZ3RoIC0gMV0gLSBiWzBdO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgdG9sZXJhbmNlIHNvIHRoYXQgcG9pbnRzIGFyZSB2aXNpYmxlIHNsaWdodGx5IG91dHNpZGUgdGhlXG4gICAgLy8gZGVmaW5lZCBjYXJwZXQgYXhpczpcbiAgICB2YXIgYXRvbCA9IGFyYW5nZSAqIGNvbnN0YW50cy5SRUxBVElWRV9DVUxMX1RPTEVSQU5DRTtcbiAgICB2YXIgYnRvbCA9IGJyYW5nZSAqIGNvbnN0YW50cy5SRUxBVElWRV9DVUxMX1RPTEVSQU5DRTtcblxuICAgIC8vIEV4cGFuZCB0aGUgbGltaXRzIHRvIGluY2x1ZGUgdGhlIHJlbGF0aXZlIHRvbGVyYW5jZTpcbiAgICBhbWluIC09IGF0b2w7XG4gICAgYW1heCArPSBhdG9sO1xuICAgIGJtaW4gLT0gYnRvbDtcbiAgICBibWF4ICs9IGJ0b2w7XG5cbiAgICB0cmFjZS5pc1Zpc2libGUgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBhID4gYW1pbiAmJiBhIDwgYW1heCAmJiBiID4gYm1pbiAmJiBiIDwgYm1heDtcbiAgICB9O1xuXG4gICAgdHJhY2UuaXNPY2NsdWRlZCA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgPCBhbWluIHx8IGEgPiBhbWF4IHx8IGIgPCBibWluIHx8IGIgPiBibWF4O1xuICAgIH07XG5cbiAgICB0cmFjZS5zZXRTY2FsZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgeCA9IHRyYWNlLl94O1xuICAgICAgICB2YXIgeSA9IHRyYWNlLl95O1xuXG4gICAgICAgIC8vIFRoaXMgaXMgcG90ZW50aWFsbHkgYSB2ZXJ5IGV4cGVuc2l2ZSBzdGVwISBJdCBkb2VzIHRoZSBidWxrIG9mIHRoZSB3b3JrIG9mIGNvbnN0cnVjdGluZ1xuICAgICAgICAvLyBhbiBleHBhbmRlZCBiYXNpcyBvZiBjb250cm9sIHBvaW50cy4gTm90ZSBpbiBwYXJ0aWN1bGFyIHRoYXQgaXQgb3ZlcndyaXRlcyB0aGUgZXhpc3RpbmdcbiAgICAgICAgLy8gYmFzaXMgd2l0aG91dCBjcmVhdGluZyBhIG5ldyBhcnJheSBzaW5jZSB0aGF0IHdvdWxkIHBvdGVudGlhbGx5IHRocmFzaCB0aGUgZ2FyYmFnZVxuICAgICAgICAvLyBjb2xsZWN0b3IuXG4gICAgICAgIHZhciByZXN1bHQgPSBjb21wdXRlQ29udHJvbFBvaW50cyh0cmFjZS5feGN0cmwsIHRyYWNlLl95Y3RybCwgeCwgeSwgYWF4LnNtb290aGluZywgYmF4LnNtb290aGluZyk7XG4gICAgICAgIHRyYWNlLl94Y3RybCA9IHJlc3VsdFswXTtcbiAgICAgICAgdHJhY2UuX3ljdHJsID0gcmVzdWx0WzFdO1xuXG4gICAgICAgIC8vIFRoaXMgc3RlcCBpcyB0aGUgc2Vjb25kIHN0ZXAgaW4gdGhlIHByb2Nlc3MsIGJ1dCBpdCdzIHNvbWV3aGF0IHNpbXBsZXIuIEl0IGp1c3QgdW5yb2xsc1xuICAgICAgICAvLyBzb21lIGxvZ2ljIHNpbmNlIGl0IHdvdWxkIGJlIHVubmVjZXNzYXJpbHkgZXhwZW5zaXZlIHRvIGNvbXB1dGUgYm90aCBpbnRlcnBvbGF0aW9uc1xuICAgICAgICAvLyBuZWFybHkgaWRlbnRpY2FsbHkgYnV0IHNlcGFyYXRlbHkgYW5kIHRvIGluY2x1ZGUgYSBidW5jaCBvZiBsaW5lYXIgdnMuIGJpY3ViaWMgbG9naWMgaW5cbiAgICAgICAgLy8gZXZlcnkgc2luZ2xlIGNhbGwuXG4gICAgICAgIHRyYWNlLmV2YWx4eSA9IGNyZWF0ZVNwbGluZUV2YWx1YXRvcihbdHJhY2UuX3hjdHJsLCB0cmFjZS5feWN0cmxdLCBuYSwgbmIsIGFheC5zbW9vdGhpbmcsIGJheC5zbW9vdGhpbmcpO1xuXG4gICAgICAgIHRyYWNlLmR4eWRpID0gY3JlYXRlSURlcml2YXRpdmVFdmFsdWF0b3IoW3RyYWNlLl94Y3RybCwgdHJhY2UuX3ljdHJsXSwgYWF4LnNtb290aGluZywgYmF4LnNtb290aGluZyk7XG4gICAgICAgIHRyYWNlLmR4eWRqID0gY3JlYXRlSkRlcml2YXRpdmVFdmFsdWF0b3IoW3RyYWNlLl94Y3RybCwgdHJhY2UuX3ljdHJsXSwgYWF4LnNtb290aGluZywgYmF4LnNtb290aGluZyk7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBmcm9tIGkvaiBkYXRhIGdyaWQgY29vcmRpbmF0ZXMgdG8gYS9iIHZhbHVlcy4gTm90ZSBpbiBwYXJ0aWN1bGFyIHRoYXQgdGhpc1xuICAgICAqIGlzICpsaW5lYXIqIGludGVycG9sYXRpb24sIGV2ZW4gaWYgdGhlIGRhdGEgaXMgaW50ZXJwb2xhdGVkIGJpY3ViaWNhbGx5LlxuICAgICAqL1xuICAgIHRyYWNlLmkyYSA9IGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgdmFyIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihpWzBdKSwgbmEgLSAyKTtcbiAgICAgICAgdmFyIHRpID0gaVswXSAtIGkwO1xuICAgICAgICByZXR1cm4gKDEgLSB0aSkgKiBhW2kwXSArIHRpICogYVtpMCArIDFdO1xuICAgIH07XG5cbiAgICB0cmFjZS5qMmIgPSBmdW5jdGlvbihqKSB7XG4gICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoalsxXSksIG5hIC0gMik7XG4gICAgICAgIHZhciB0aiA9IGpbMV0gLSBqMDtcbiAgICAgICAgcmV0dXJuICgxIC0gdGopICogYltqMF0gKyB0aiAqIGJbajAgKyAxXTtcbiAgICB9O1xuXG4gICAgdHJhY2UuaWoyYWIgPSBmdW5jdGlvbihpaikge1xuICAgICAgICByZXR1cm4gW3RyYWNlLmkyYShpalswXSksIHRyYWNlLmoyYihpalsxXSldO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgZnJvbSBhL2IgY29vcmRpbmF0ZXMgdG8gaS9qIGdyaWQtbnVtYmVyZWQgY29vcmRpbmF0ZXMuIFRoaXMgcmVxdWlyZXMgc2VhcmNoaW5nXG4gICAgICogdGhyb3VnaCB0aGUgYS9iIGRhdGEgYXJyYXlzIGFuZCBhc3N1bWVzIHRoZXkgYXJlIG1vbm90b25pYywgd2hpY2ggaXMgcHJlc3VtZWQgdG8gaGF2ZVxuICAgICAqIGJlZW4gZW5mb3JjZWQgYWxyZWFkeS5cbiAgICAgKi9cbiAgICB0cmFjZS5hMmkgPSBmdW5jdGlvbihhdmFsKSB7XG4gICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKHNlYXJjaChhdmFsLCBhKSwgbmEgLSAyKSk7XG4gICAgICAgIHZhciBhMCA9IGFbaTBdO1xuICAgICAgICB2YXIgYTEgPSBhW2kwICsgMV07XG4gICAgICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbihuYSAtIDEsIGkwICsgKGF2YWwgLSBhMCkgLyAoYTEgLSBhMCkpKTtcbiAgICB9O1xuXG4gICAgdHJhY2UuYjJqID0gZnVuY3Rpb24oYnZhbCkge1xuICAgICAgICB2YXIgajAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihzZWFyY2goYnZhbCwgYiksIG5iIC0gMikpO1xuICAgICAgICB2YXIgYjAgPSBiW2owXTtcbiAgICAgICAgdmFyIGIxID0gYltqMCArIDFdO1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obmIgLSAxLCBqMCArIChidmFsIC0gYjApIC8gKGIxIC0gYjApKSk7XG4gICAgfTtcblxuICAgIHRyYWNlLmFiMmlqID0gZnVuY3Rpb24oYWIpIHtcbiAgICAgICAgcmV0dXJuIFt0cmFjZS5hMmkoYWJbMF0pLCB0cmFjZS5iMmooYWJbMV0pXTtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGZyb20gaS9qIGNvb3JkaW5hdGVzIHRvIHgveSBjYXJldGVzaWFuIGNvb3JkaW5hdGVzLiBUaGlzIG1lYW5zIGVpdGhlciBiaWxpbmVhclxuICAgICAqIG9yIGJpY3ViaWMgc3BsaW5lIGV2YWx1YXRpb24sIGJ1dCB0aGUgaGFyZCBwYXJ0IGlzIGFscmVhZHkgZG9uZSBhdCB0aGlzIHBvaW50LlxuICAgICAqL1xuICAgIHRyYWNlLmkyYyA9IGZ1bmN0aW9uKGksIGopIHtcbiAgICAgICAgcmV0dXJuIHRyYWNlLmV2YWx4eShbXSwgaSwgaik7XG4gICAgfTtcblxuICAgIHRyYWNlLmFiMnh5ID0gZnVuY3Rpb24oYXZhbCwgYnZhbCwgZXh0cmFwb2xhdGUpIHtcbiAgICAgICAgaWYoIWV4dHJhcG9sYXRlICYmIChhdmFsIDwgYVswXSB8fCBhdmFsID4gYVtuYSAtIDFdIHwgYnZhbCA8IGJbMF0gfHwgYnZhbCA+IGJbbmIgLSAxXSkpIHtcbiAgICAgICAgICAgIHJldHVybiBbZmFsc2UsIGZhbHNlXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHRyYWNlLmEyaShhdmFsKTtcbiAgICAgICAgdmFyIGogPSB0cmFjZS5iMmooYnZhbCk7XG5cbiAgICAgICAgdmFyIHB0ID0gdHJhY2UuZXZhbHh5KFtdLCBpLCBqKTtcblxuICAgICAgICBpZihleHRyYXBvbGF0ZSkge1xuICAgICAgICAgICAgLy8gVGhpcyBzZWN0aW9uIHVzZXMgdGhlIGJvdW5kYXJ5IGRlcml2YXRpdmVzIHRvIGV4dHJhcG9sYXRlIGxpbmVhcmx5IG91dHNpZGVcbiAgICAgICAgICAgIC8vIHRoZSBkZWZpbmVkIHJhbmdlLiBDb25zaWRlciBhIHNjYXR0ZXIgbGluZSB3aXRoIG9uZSBwb2ludCBpbnNpZGUgdGhlIGNhcnBldFxuICAgICAgICAgICAgLy8gYXhpcyBhbmQgb25lIHBvaW50IG91dHNpZGUuIElmIHdlIGRvbid0IGV4dHJhcG9sYXRlLCB3ZSBjYW4ndCBkcmF3IHRoZSBsaW5lXG4gICAgICAgICAgICAvLyBhdCBhbGwuXG4gICAgICAgICAgICB2YXIgaWV4ID0gMDtcbiAgICAgICAgICAgIHZhciBqZXggPSAwO1xuICAgICAgICAgICAgdmFyIGRlciA9IFtdO1xuXG4gICAgICAgICAgICB2YXIgaTAsIHRpLCBqMCwgdGo7XG4gICAgICAgICAgICBpZihhdmFsIDwgYVswXSkge1xuICAgICAgICAgICAgICAgIGkwID0gMDtcbiAgICAgICAgICAgICAgICB0aSA9IDA7XG4gICAgICAgICAgICAgICAgaWV4ID0gKGF2YWwgLSBhWzBdKSAvIChhWzFdIC0gYVswXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoYXZhbCA+IGFbbmEgLSAxXSkge1xuICAgICAgICAgICAgICAgIGkwID0gbmEgLSAyO1xuICAgICAgICAgICAgICAgIHRpID0gMTtcbiAgICAgICAgICAgICAgICBpZXggPSAoYXZhbCAtIGFbbmEgLSAxXSkgLyAoYVtuYSAtIDFdIC0gYVtuYSAtIDJdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaTAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihuYSAtIDIsIE1hdGguZmxvb3IoaSkpKTtcbiAgICAgICAgICAgICAgICB0aSA9IGkgLSBpMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoYnZhbCA8IGJbMF0pIHtcbiAgICAgICAgICAgICAgICBqMCA9IDA7XG4gICAgICAgICAgICAgICAgdGogPSAwO1xuICAgICAgICAgICAgICAgIGpleCA9IChidmFsIC0gYlswXSkgLyAoYlsxXSAtIGJbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGJ2YWwgPiBiW25iIC0gMV0pIHtcbiAgICAgICAgICAgICAgICBqMCA9IG5iIC0gMjtcbiAgICAgICAgICAgICAgICB0aiA9IDE7XG4gICAgICAgICAgICAgICAgamV4ID0gKGJ2YWwgLSBiW25iIC0gMV0pIC8gKGJbbmIgLSAxXSAtIGJbbmIgLSAyXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGowID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obmIgLSAyLCBNYXRoLmZsb29yKGopKSk7XG4gICAgICAgICAgICAgICAgdGogPSBqIC0gajA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlleCkge1xuICAgICAgICAgICAgICAgIHRyYWNlLmR4eWRpKGRlciwgaTAsIGowLCB0aSwgdGopO1xuICAgICAgICAgICAgICAgIHB0WzBdICs9IGRlclswXSAqIGlleDtcbiAgICAgICAgICAgICAgICBwdFsxXSArPSBkZXJbMV0gKiBpZXg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGpleCkge1xuICAgICAgICAgICAgICAgIHRyYWNlLmR4eWRqKGRlciwgaTAsIGowLCB0aSwgdGopO1xuICAgICAgICAgICAgICAgIHB0WzBdICs9IGRlclswXSAqIGpleDtcbiAgICAgICAgICAgICAgICBwdFsxXSArPSBkZXJbMV0gKiBqZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcHQ7XG4gICAgfTtcblxuXG4gICAgdHJhY2UuYzJwID0gZnVuY3Rpb24oeHksIHhhLCB5YSkge1xuICAgICAgICByZXR1cm4gW3hhLmMycCh4eVswXSksIHlhLmMycCh4eVsxXSldO1xuICAgIH07XG5cbiAgICB0cmFjZS5wMnggPSBmdW5jdGlvbihwLCB4YSwgeWEpIHtcbiAgICAgICAgcmV0dXJuIFt4YS5wMmMocFswXSksIHlhLnAyYyhwWzFdKV07XG4gICAgfTtcblxuICAgIHRyYWNlLmRhZGkgPSBmdW5jdGlvbihpIC8qICwgdSovKSB7XG4gICAgICAgIC8vIFJpZ2h0IG5vdyBvbmx5IGEgcGllY2V3aXNlIGxpbmVhciBhIG9yIGIgYmFzaXMgaXMgcGVybWl0dGVkIHNpbmNlIHNtb290aGVyIGludGVycG9sYXRpb25cbiAgICAgICAgLy8gd291bGQgY2F1c2UgbW9ub3RvbmljaXR5IHByb2JsZW1zLiBBcyBhIHJldHVsdCwgdSBpcyBlbnRpcmVseSBkaXNyZWdhcmRlZCBpbiB0aGlzXG4gICAgICAgIC8vIGNvbXB1dGF0aW9uLCB0aG91Z2ggd2UnbGwgc3BlY2lmeSBpdCBhcyBhIHBhcmFtZXRlciBmb3IgdGhlIHNha2Ugb2YgY29tcGxldGVuZXNzIGFuZFxuICAgICAgICAvLyBmdXR1cmUtcHJvb2ZpbmcuIEl0IHdvdWxkIGJlIHBvc3NpYmxlIHRvIHVzZSBtb25vdG9uaWMgY3ViaWMgaW50ZXJwb2xhdGlvbiwgZm9yIGV4YW1wbGUuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFNlZTogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9ub3RvbmVfY3ViaWNfaW50ZXJwb2xhdGlvblxuXG4gICAgICAgIC8vIHUgPSB1IHx8IDA7XG5cbiAgICAgICAgdmFyIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oYS5sZW5ndGggLSAyLCBpKSk7XG5cbiAgICAgICAgLy8gVGhlIHN0ZXAgKGRlbW9uaW5hdG9yKSBpcyBpbXBsaWNpdGx5IDEgc2luY2UgdGhhdCdzIHRoZSBncmlkIHNwYWNpbmcuXG4gICAgICAgIHJldHVybiBhW2kwICsgMV0gLSBhW2kwXTtcbiAgICB9O1xuXG4gICAgdHJhY2UuZGJkaiA9IGZ1bmN0aW9uKGogLyogLCB2Ki8pIHtcbiAgICAgICAgLy8gU2VlIGFib3ZlIGNhdmVhdHMgZm9yIGRhZGkgd2hpY2ggYWxzbyBhcHBseSBoZXJlXG4gICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGIubGVuZ3RoIC0gMiwgaikpO1xuXG4gICAgICAgIC8vIFRoZSBzdGVwIChkZW1vbmluYXRvcikgaXMgaW1wbGljaXRseSAxIHNpbmNlIHRoYXQncyB0aGUgZ3JpZCBzcGFjaW5nLlxuICAgICAgICByZXR1cm4gYltqMCArIDFdIC0gYltqMF07XG4gICAgfTtcblxuICAgIC8vIFRha2VzOiBncmlkIGNlbGwgY29vcmRpbmF0ZSAoaSwgaikgYW5kIGZyYWN0aW9uYWwgZ3JpZCBjZWxsIGNvb3JkaW5hdGVzICh1LCB2KVxuICAgIC8vIFJldHVybnM6IChkeC9kYSwgZHkvZGIpXG4gICAgLy9cbiAgICAvLyBOQjogc2VwYXJhdGUgZ3JpZCBjZWxsICsgZnJhY3Rpb25hbCBncmlkIGNlbGwgY29vcmRpbmF0ZSBmb3JtYXQgaXMgZHVlIHRvIHRoZSBkaXNjb250aW51b3VzXG4gICAgLy8gZGVyaXZhdGl2ZSwgYXMgZGVzY3JpYmVkIGJldHRlciBpbiBjcmVhdGVfaV9kZXJpdmF0aXZlX2V2YWx1YXRvci5qc1xuICAgIHRyYWNlLmR4eWRhID0gZnVuY3Rpb24oaTAsIGowLCB1LCB2KSB7XG4gICAgICAgIHZhciBkeHlkaSA9IHRyYWNlLmR4eWRpKG51bGwsIGkwLCBqMCwgdSwgdik7XG4gICAgICAgIHZhciBkYWRpID0gdHJhY2UuZGFkaShpMCwgdSk7XG5cbiAgICAgICAgcmV0dXJuIFtkeHlkaVswXSAvIGRhZGksIGR4eWRpWzFdIC8gZGFkaV07XG4gICAgfTtcblxuICAgIHRyYWNlLmR4eWRiID0gZnVuY3Rpb24oaTAsIGowLCB1LCB2KSB7XG4gICAgICAgIHZhciBkeHlkaiA9IHRyYWNlLmR4eWRqKG51bGwsIGkwLCBqMCwgdSwgdik7XG4gICAgICAgIHZhciBkYmRqID0gdHJhY2UuZGJkaihqMCwgdik7XG5cbiAgICAgICAgcmV0dXJuIFtkeHlkalswXSAvIGRiZGosIGR4eWRqWzFdIC8gZGJkal07XG4gICAgfTtcblxuICAgIC8vIFNvbWV0aW1lcyB3ZSBkb24ndCBjYXJlIGFib3V0IHByZWNpc2lvbiBhbmQgYWxsIHdlIHJlYWxseSB3YW50IGlzIGRlY2VudCByb3VnaFxuICAgIC8vIGRpcmVjdGlvbnMgKGFzIGlzIHRoZSBjYXNlIHdpdGggbGFiZWxzKS4gSW4gdGhhdCBjYXNlLCB3ZSBjYW4gZG8gYSB2ZXJ5IHJvdWdoIGZpbml0ZVxuICAgIC8vIGRpZmZlcmVuY2UgYW5kIHNwYXJlIGhhdmluZyB0byB3b3JyeSBhYm91dCBwcmVjaXNlIGdyaWQgY29vcmRpbmF0ZXM6XG4gICAgdHJhY2UuZHh5ZGFfcm91Z2ggPSBmdW5jdGlvbihhLCBiLCByZWxkaWZmKSB7XG4gICAgICAgIHZhciBoID0gYXJhbmdlICogKHJlbGRpZmYgfHwgMC4xKTtcbiAgICAgICAgdmFyIHBsdXMgPSB0cmFjZS5hYjJ4eShhICsgaCwgYiwgdHJ1ZSk7XG4gICAgICAgIHZhciBtaW51cyA9IHRyYWNlLmFiMnh5KGEgLSBoLCBiLCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgKHBsdXNbMF0gLSBtaW51c1swXSkgKiAwLjUgLyBoLFxuICAgICAgICAgICAgKHBsdXNbMV0gLSBtaW51c1sxXSkgKiAwLjUgLyBoXG4gICAgICAgIF07XG4gICAgfTtcblxuICAgIHRyYWNlLmR4eWRiX3JvdWdoID0gZnVuY3Rpb24oYSwgYiwgcmVsZGlmZikge1xuICAgICAgICB2YXIgaCA9IGJyYW5nZSAqIChyZWxkaWZmIHx8IDAuMSk7XG4gICAgICAgIHZhciBwbHVzID0gdHJhY2UuYWIyeHkoYSwgYiArIGgsIHRydWUpO1xuICAgICAgICB2YXIgbWludXMgPSB0cmFjZS5hYjJ4eShhLCBiIC0gaCwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIChwbHVzWzBdIC0gbWludXNbMF0pICogMC41IC8gaCxcbiAgICAgICAgICAgIChwbHVzWzFdIC0gbWludXNbMV0pICogMC41IC8gaFxuICAgICAgICBdO1xuICAgIH07XG5cbiAgICB0cmFjZS5kcGR4ID0gZnVuY3Rpb24oeGEpIHtcbiAgICAgICAgcmV0dXJuIHhhLl9tO1xuICAgIH07XG5cbiAgICB0cmFjZS5kcGR5ID0gZnVuY3Rpb24oeWEpIHtcbiAgICAgICAgcmV0dXJuIHlhLl9tO1xuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbi8qXG4gKiBHaXZlbiBhIDJEIGFycmF5IGFzIHdlbGwgYXMgYSBiYXNpcyBpbiBlaXRoZXIgZGlyZWN0aW9uLCB0aGlzIGZ1bmN0aW9uIGZpbGxzIGluIHRoZVxuICogMkQgYXJyYXkgdXNpbmcgYSBjb21iaW5hdGlvbiBvZiBzbW9vdGhpbmcgYW5kIGV4dHJhcG9sYXRpb24uIFRoaXMgaXMgcmF0aGVyIGltcG9ydGFudFxuICogZm9yIGNhcnBldCBwbG90cyBzaW5jZSBpdCdzIHVzZWQgZm9yIGxheW91dCBzbyB0aGF0IHdlIGNhbid0IHNpbXBseSBvbWl0IG9yIGJsYW5rIG91dFxuICogcG9pbnRzLiBXZSBuZWVkIGEgcmVhc29uYWJsZSBndWVzcyBzbyB0aGF0IHRoZSBpbnRlcnBvbGF0aW9uIHB1dHMgcG9pbnRzIHNvbWV3aGVyZVxuICogZXZlbiBpZiB3ZSB3ZXJlIHRvIHNvbWVob3cgcmVwcmVzZW50IHRoYXQgdGhlIGRhdGEgd2FzIG1pc3NpbmcgbGF0ZXIgb24uXG4gKlxuICogaW5wdXQ6XG4gKiAgLSBkYXRhOiAyRCBhcnJheSBvZiBhcnJheXNcbiAqICAtIGE6IGFycmF5IHN1Y2ggdGhhdCBhLmxlbmd0aCA9PT0gZGF0YVswXS5sZW5ndGhcbiAqICAtIGI6IGFycmF5IHN1Y2ggdGhhdCBiLmxlbmd0aCA9PT0gZGF0YS5sZW5ndGhcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzbW9vdGhGaWxsMmRBcnJheShkYXRhLCBhLCBiKSB7XG4gICAgdmFyIGksIGosIGs7XG4gICAgdmFyIGlwID0gW107XG4gICAgdmFyIGpwID0gW107XG4gICAgLy8gdmFyIG5laWdoYm9yQ250cyA9IFtdO1xuXG4gICAgdmFyIG5pID0gZGF0YVswXS5sZW5ndGg7XG4gICAgdmFyIG5qID0gZGF0YS5sZW5ndGg7XG5cbiAgICBmdW5jdGlvbiBhdmdTdXJyb3VuZGluZyhpLCBqKSB7XG4gICAgICAgIC8vIEFzIGEgbG93LXF1YWxpdHkgc3RhcnQsIHdlIGNhbiBzaW1wbHkgYXZlcmFnZSBzdXJyb3VuZGluZyBwb2ludHMgKGluIGEgbm90XG4gICAgICAgIC8vIG5vbi11bmlmb3JtIGdyaWQgYXdhcmUgbWFubmVyKTpcbiAgICAgICAgdmFyIHN1bSA9IDAuMDtcbiAgICAgICAgdmFyIHZhbDtcbiAgICAgICAgdmFyIGNudCA9IDA7XG4gICAgICAgIGlmKGkgPiAwICYmICh2YWwgPSBkYXRhW2pdW2kgLSAxXSkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY250Kys7XG4gICAgICAgICAgICBzdW0gKz0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIGlmKGkgPCBuaSAtIDEgJiYgKHZhbCA9IGRhdGFbal1baSArIDFdKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgIHN1bSArPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaiA+IDAgJiYgKHZhbCA9IGRhdGFbaiAtIDFdW2ldKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgIHN1bSArPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaiA8IG5qIC0gMSAmJiAodmFsID0gZGF0YVtqICsgMV1baV0pICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgc3VtICs9IHZhbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VtIC8gTWF0aC5tYXgoMSwgY250KTtcblxuICAgIH1cblxuICAgIC8vIFRoaXMgbG9vcCBpdGVyYXRlcyBvdmVyIGFsbCBjZWxscy4gQW55IGNlbGxzIHRoYXQgYXJlIG51bGwgd2lsbCBiZSBub3RlZCBhbmQgdGhvc2VcbiAgICAvLyBhcmUgdGhlIG9ubHkgcG9pbnRzIHdlIHdpbGwgbG9vcCBvdmVyIGFuZCB1cGRhdGUgdmlhIGxhcGxhY2UncyBlcXVhdGlvbi4gUG9pbnRzIHdpdGhcbiAgICAvLyBhbnkgbmVpZ2hib3JzIHdpbGwgcmVjZWl2ZSB0aGUgYXZlcmFnZS4gSWYgdGhlcmUgYXJlIG5vIG5laWdoYm9yaW5nIHBvaW50cywgdGhlbiB0aGV5XG4gICAgLy8gd2lsbCBiZSBzZXQgdG8gemVyby4gQWxzbyBhcyB3ZSBnbywgdHJhY2sgdGhlIG1heGltdW0gbWFnbml0dWRlIHNvIHRoYXQgd2UgY2FuIHNjYWxlXG4gICAgLy8gb3VyIHRvbGVyYW5jZSBhY2NvcmRpbmdseS5cbiAgICB2YXIgZG1heCA9IDAuMDtcbiAgICBmb3IoaSA9IDA7IGkgPCBuaTsgaSsrKSB7XG4gICAgICAgIGZvcihqID0gMDsgaiA8IG5qOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGRhdGFbal1baV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlwLnB1c2goaSk7XG4gICAgICAgICAgICAgICAganAucHVzaChqKTtcblxuICAgICAgICAgICAgICAgIGRhdGFbal1baV0gPSBhdmdTdXJyb3VuZGluZyhpLCBqKTtcbiAgICAgICAgICAgICAgICAvLyBuZWlnaGJvckNudHMucHVzaChyZXN1bHQubmVpZ2hib3JzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRtYXggPSBNYXRoLm1heChkbWF4LCBNYXRoLmFicyhkYXRhW2pdW2ldKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighaXAubGVuZ3RoKSByZXR1cm4gZGF0YTtcblxuICAgIC8vIFRoZSB0b2xlcmFuY2UgZG9lc24ndCBuZWVkIHRvIGJlIGV4Y2Vzc2l2ZS4gSXQncyBqdXN0IGZvciBkaXNwbGF5IHBvc2l0aW9uaW5nXG4gICAgdmFyIGR4cCwgZHhtLCBkYXAsIGRhbSwgZGJwLCBkYm0sIGMsIGQsIGRpZmYsIHJlbGRpZmYsIG92ZXJyZWxheGF0aW9uO1xuICAgIHZhciB0b2wgPSAxZS01O1xuICAgIHZhciByZXNpZCA9IDA7XG4gICAgdmFyIGl0ZXJtYXggPSAxMDA7XG4gICAgdmFyIGl0ZXIgPSAwO1xuICAgIHZhciBuID0gaXAubGVuZ3RoO1xuICAgIGRvIHtcbiAgICAgICAgcmVzaWQgPSAwO1xuICAgICAgICAvLyBOb3JtYWxseSB3ZSdkIGxvb3AgaW4gdHdvIGRpbWVuc2lvbnMsIGJ1dCBub3QgYWxsIHBvaW50cyBhcmUgYmxhbmsgYW5kIG5lZWRcbiAgICAgICAgLy8gYW4gdXBkYXRlLCBzbyB3ZSBpbnN0ZWFkIGxvb3Agb25seSBvdmVyIHRoZSBwb2ludHMgdGhhdCB3ZXJlIHRhYnVsYXRlZCBhYm92ZVxuICAgICAgICBmb3IoayA9IDA7IGsgPCBuOyBrKyspIHtcbiAgICAgICAgICAgIGkgPSBpcFtrXTtcbiAgICAgICAgICAgIGogPSBqcFtrXTtcbiAgICAgICAgICAgIC8vIG5laWdoYm9yQ250ID0gbmVpZ2hib3JDbnRzW2tdO1xuXG4gICAgICAgICAgICAvLyBUcmFjayBhIGNvdW50ZXIgZm9yIGhvdyBtYW55IGNvbnRyaWJ1dGlvbnMgdGhlcmUgYXJlLiBXZSdsbCB1c2UgdGhpcyBjb3VudGVyXG4gICAgICAgICAgICAvLyB0byBhdmVyYWdlIGF0IHRoZSBlbmQsIHdoaWNoIHJlZHVjZXMgdG8gbGFwbGFjZSdzIGVxdWF0aW9uIHdpdGggbmV1bWFubiBib3VuZGFyeVxuICAgICAgICAgICAgLy8gY29uZGl0aW9ucyBvbiB0aGUgZmlyc3QgZGVyaXZhdGl2ZSAoc2Vjb25kIGRlcml2YXRpdmUgaXMgemVybyBzbyB0aGF0IHdlIGdldFxuICAgICAgICAgICAgLy8gYSBuaWNlIGxpbmVhciBleHRyYXBvbGF0aW9uIGF0IHRoZSBib3VuZGFyaWVzKS5cbiAgICAgICAgICAgIHZhciBib3VuZGFyeUNudCA9IDA7XG4gICAgICAgICAgICB2YXIgbmV3VmFsID0gMDtcblxuICAgICAgICAgICAgdmFyIGQwLCBkMSwgeDAsIHgxLCBpMCwgajA7XG4gICAgICAgICAgICBpZihpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBsaWVzIGFsb25nIHRoZSBpID0gMCBib3VuZGFyeSwgZXh0cmFwb2xhdGUgZnJvbSB0aGUgdHdvIHBvaW50c1xuICAgICAgICAgICAgICAgIC8vIHRvIHRoZSByaWdodCBvZiB0aGlzIHBvaW50LiBOb3RlIHRoYXQgdGhlIGZpbml0ZSBkaWZmZXJlbmNlcyB0YWtlIGludG9cbiAgICAgICAgICAgICAgICAvLyBhY2NvdW50IG5vbi11bmlmb3JtIGdyaWQgc3BhY2luZzpcbiAgICAgICAgICAgICAgICBpMCA9IE1hdGgubWluKG5pIC0gMSwgMik7XG4gICAgICAgICAgICAgICAgeDAgPSBhW2kwXTtcbiAgICAgICAgICAgICAgICB4MSA9IGFbMV07XG4gICAgICAgICAgICAgICAgZDAgPSBkYXRhW2pdW2kwXTtcbiAgICAgICAgICAgICAgICBkMSA9IGRhdGFbal1bMV07XG4gICAgICAgICAgICAgICAgbmV3VmFsICs9IGQxICsgKGQxIC0gZDApICogKGFbMF0gLSB4MSkgLyAoeDEgLSB4MCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH0gZWxzZSBpZihpID09PSBuaSAtIDEpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBhbG9uZyB0aGUgaGlnaCBpIGJvdW5kYXJ5LCBleHRyYXBvbGF0ZSBmcm9tIHRoZSB0d28gcG9pbnRzIHRvIHRoZVxuICAgICAgICAgICAgICAgIC8vIGxlZnQgb2YgdGhpcyBwb2ludFxuICAgICAgICAgICAgICAgIGkwID0gTWF0aC5tYXgoMCwgbmkgLSAzKTtcbiAgICAgICAgICAgICAgICB4MCA9IGFbaTBdO1xuICAgICAgICAgICAgICAgIHgxID0gYVtuaSAtIDJdO1xuICAgICAgICAgICAgICAgIGQwID0gZGF0YVtqXVtpMF07XG4gICAgICAgICAgICAgICAgZDEgPSBkYXRhW2pdW25pIC0gMl07XG4gICAgICAgICAgICAgICAgbmV3VmFsICs9IGQxICsgKGQxIC0gZDApICogKGFbbmkgLSAxXSAtIHgxKSAvICh4MSAtIHgwKTtcbiAgICAgICAgICAgICAgICBib3VuZGFyeUNudCsrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZigoaSA9PT0gMCB8fCBpID09PSBuaSAtIDEpICYmIChqID4gMCAmJiBqIDwgbmogLSAxKSkge1xuICAgICAgICAgICAgICAgIC8vIElmIGFsb25nIHRoZSBtaW4oaSkgb3IgbWF4KGkpIGJvdW5kYXJpZXMsIGFsc28gc21vb3RoIHZlcnRpY2FsbHkgYXMgbG9uZ1xuICAgICAgICAgICAgICAgIC8vIGFzIHdlJ3JlIG5vdCBpbiBhIGNvcm5lci4gTm90ZSB0aGF0IHRoZSBmaW5pdGUgZGlmZmVyZW5jZXMgdXNlZCBoZXJlXG4gICAgICAgICAgICAgICAgLy8gYXJlIGFsc28gYXdhcmUgb2Ygbm9udW5pZm9ybSBncmlkIHNwYWNpbmc6XG4gICAgICAgICAgICAgICAgZHhwID0gYltqICsgMV0gLSBiW2pdO1xuICAgICAgICAgICAgICAgIGR4bSA9IGJbal0gLSBiW2ogLSAxXTtcbiAgICAgICAgICAgICAgICBuZXdWYWwgKz0gKGR4bSAqIGRhdGFbaiArIDFdW2ldICsgZHhwICogZGF0YVtqIC0gMV1baV0pIC8gKGR4bSArIGR4cCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIElmIGFsb25nIHRoZSBqID0gMCBib3VuZGFyeSwgZXh0cnBvbGF0ZSB0aGlzIHBvaW50IGZyb20gdGhlIHR3byBwb2ludHNcbiAgICAgICAgICAgICAgICAvLyBhYm92ZSBpdFxuICAgICAgICAgICAgICAgIGowID0gTWF0aC5taW4obmogLSAxLCAyKTtcbiAgICAgICAgICAgICAgICB4MCA9IGJbajBdO1xuICAgICAgICAgICAgICAgIHgxID0gYlsxXTtcbiAgICAgICAgICAgICAgICBkMCA9IGRhdGFbajBdW2ldO1xuICAgICAgICAgICAgICAgIGQxID0gZGF0YVsxXVtpXTtcbiAgICAgICAgICAgICAgICBuZXdWYWwgKz0gZDEgKyAoZDEgLSBkMCkgKiAoYlswXSAtIHgxKSAvICh4MSAtIHgwKTtcbiAgICAgICAgICAgICAgICBib3VuZGFyeUNudCsrO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGogPT09IG5qIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vIFNhbWUgZm9yIHRoZSBtYXggaiBib3VuZGFyeSBmcm9tIHRoZSBjZWxscyBiZWxvdyBpdDpcbiAgICAgICAgICAgICAgICBqMCA9IE1hdGgubWF4KDAsIG5qIC0gMyk7XG4gICAgICAgICAgICAgICAgeDAgPSBiW2owXTtcbiAgICAgICAgICAgICAgICB4MSA9IGJbbmogLSAyXTtcbiAgICAgICAgICAgICAgICBkMCA9IGRhdGFbajBdW2ldO1xuICAgICAgICAgICAgICAgIGQxID0gZGF0YVtuaiAtIDJdW2ldO1xuICAgICAgICAgICAgICAgIG5ld1ZhbCArPSBkMSArIChkMSAtIGQwKSAqIChiW25qIC0gMV0gLSB4MSkgLyAoeDEgLSB4MCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoKGogPT09IDAgfHwgaiA9PT0gbmogLSAxKSAmJiAoaSA+IDAgJiYgaSA8IG5pIC0gMSkpIHtcbiAgICAgICAgICAgICAgICAvLyBOb3cgYXZlcmFnZSBwb2ludHMgdG8gdGhlIGxlZnQvcmlnaHQgYXMgbG9uZyBhcyBub3QgaW4gYSBjb3JuZXI6XG4gICAgICAgICAgICAgICAgZHhwID0gYVtpICsgMV0gLSBhW2ldO1xuICAgICAgICAgICAgICAgIGR4bSA9IGFbaV0gLSBhW2kgLSAxXTtcbiAgICAgICAgICAgICAgICBuZXdWYWwgKz0gKGR4bSAqIGRhdGFbal1baSArIDFdICsgZHhwICogZGF0YVtqXVtpIC0gMV0pIC8gKGR4bSArIGR4cCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWJvdW5kYXJ5Q250KSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgbm9uZSBvZiB0aGUgYWJvdmUgY29uZGl0aW9ucyB3ZXJlIHRyaWdnZXJlZCwgdGhlbiB0aGlzIGlzIGFuIGludGVyaW9yXG4gICAgICAgICAgICAgICAgLy8gcG9pbnQgYW5kIHdlIGNhbiBqdXN0IGRvIGEgbGFwbGFjZSBlcXVhdGlvbiB1cGRhdGUuIEFzIGFib3ZlLCB0aGVzZSBkaWZmZXJlbmNlc1xuICAgICAgICAgICAgICAgIC8vIGFyZSBhd2FyZSBvZiBub251bmlmb3JtIGdyaWQgc3BhY2luZzpcbiAgICAgICAgICAgICAgICBkYXAgPSBhW2kgKyAxXSAtIGFbaV07XG4gICAgICAgICAgICAgICAgZGFtID0gYVtpXSAtIGFbaSAtIDFdO1xuICAgICAgICAgICAgICAgIGRicCA9IGJbaiArIDFdIC0gYltqXTtcbiAgICAgICAgICAgICAgICBkYm0gPSBiW2pdIC0gYltqIC0gMV07XG5cbiAgICAgICAgICAgICAgICAvLyBUaGVzZSBhcmUganVzdCBzb21lIHVzZWZ1bCBjb25zdGFudHMgZm9yIHRoZSBpdGVyYXRpb24sIHdoaWNoIGlzIHBlcmZlY3RseVxuICAgICAgICAgICAgICAgIC8vIHN0cmFpZ2h0Zm9yd2FyZCBidXQgYSBsaXR0bGUgbG9uZyB0byBkZXJpdmUgZnJvbSBmX3h4ICsgZl95eSA9IDAuXG4gICAgICAgICAgICAgICAgYyA9IGRhcCAqIGRhbSAqIChkYXAgKyBkYW0pO1xuICAgICAgICAgICAgICAgIGQgPSBkYnAgKiBkYm0gKiAoZGJwICsgZGJtKTtcblxuICAgICAgICAgICAgICAgIG5ld1ZhbCA9IChjICogKGRibSAqIGRhdGFbaiArIDFdW2ldICsgZGJwICogZGF0YVtqIC0gMV1baV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZCAqIChkYW0gKiBkYXRhW2pdW2kgKyAxXSArIGRhcCAqIGRhdGFbal1baSAtIDFdKSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAoZCAqIChkYW0gKyBkYXApICsgYyAqIChkYm0gKyBkYnApKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgd2UgZGlkIGhhdmUgY29udHJpYnV0aW9ucyBmcm9tIHRoZSBib3VuZGFyeSBjb25kaXRpb25zLCB0aGVuIGF2ZXJhZ2VcbiAgICAgICAgICAgICAgICAvLyB0aGUgcmVzdWx0IGZyb20gdGhlIHZhcmlvdXMgY29udHJpYnV0aW9uczpcbiAgICAgICAgICAgICAgICBuZXdWYWwgLz0gYm91bmRhcnlDbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEphY29iaSB1cGRhdGVzIGFyZSByaWRpY3Vsb3VzbHkgc2xvdyB0byBjb252ZXJnZSwgc28gdGhpcyBhcHByb2FjaCB1c2VzIGFcbiAgICAgICAgICAgIC8vIEdhdXNzLXNlaWRlbCBpdGVyYXRpb24gd2hpY2ggaXMgZHJhbWF0aWNhbGx5IGZhc3Rlci5cbiAgICAgICAgICAgIGRpZmYgPSBuZXdWYWwgLSBkYXRhW2pdW2ldO1xuICAgICAgICAgICAgcmVsZGlmZiA9IGRpZmYgLyBkbWF4O1xuICAgICAgICAgICAgcmVzaWQgKz0gcmVsZGlmZiAqIHJlbGRpZmY7XG5cbiAgICAgICAgICAgIC8vIEdhdXNzLVNlaWRlbC1pc2ggaXRlcmF0aW9uLCBvbWVnYSBjaG9zZW4gYmFzZWQgb24gaGV1cmlzdGljcyBhbmQgc29tZVxuICAgICAgICAgICAgLy8gcXVpY2sgdGVzdHMuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gTkI6IERvbid0IG92ZXJyZWxheCB0aGUgYm91bmRhcmllLiBPdGhlcndpc2Ugc2V0IGFuIG92ZXJyZWxheGF0aW9uIGZhY3RvclxuICAgICAgICAgICAgLy8gd2hpY2ggaXMgYSBsaXR0bGUgbG93IGJ1dCBzYWZlbHkgb3B0aW1hbC1pc2g6XG4gICAgICAgICAgICBvdmVycmVsYXhhdGlvbiA9IGJvdW5kYXJ5Q250ID8gMCA6IDAuODU7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBmb3VyIG5vbi1udWxsIG5laWdoYm9ycywgdGhlbiB3ZSB3YW50IGEgc2ltcGxlIGF2ZXJhZ2Ugd2l0aG91dFxuICAgICAgICAgICAgLy8gb3ZlcnJlbGF4YXRpb24uIElmIGFsbCB0aGUgc3Vycm91ZGluZyBwb2ludHMgYXJlIG51bGwsIHRoZW4gd2Ugd2FudCB0aGUgZnVsbFxuICAgICAgICAgICAgLy8gb3ZlcnJlbGF4YXRpb25cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBCYXNlZCBvbiBleHBlcmltZW50cywgdGhpcyBhY3R1YWxseSBzZWVtcyB0byBzbG93IGRvd24gY29udmVyZ2VuY2UganVzdCBhIGJpdC5cbiAgICAgICAgICAgIC8vIEknbGwgbGVhdmUgaXQgaGVyZSBmb3IgcmVmZXJlbmNlIGluIGNhc2UgdGhpcyBuZWVkcyB0byBiZSByZXZpc2l0ZWQsIGJ1dFxuICAgICAgICAgICAgLy8gaXQgc2VlbXMgdG8gd29yayBqdXN0IGZpbmUgd2l0aG91dCB0aGlzLlxuICAgICAgICAgICAgLy8gaWYgKG92ZXJyZWxheGF0aW9uKSBvdmVycmVsYXhhdGlvbiAqPSAoNCAtIG5laWdoYm9yQ250KSAvIDQ7XG5cbiAgICAgICAgICAgIGRhdGFbal1baV0gKz0gZGlmZiAqICgxICsgb3ZlcnJlbGF4YXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzaWQgPSBNYXRoLnNxcnQocmVzaWQpO1xuICAgIH0gd2hpbGUoaXRlcisrIDwgaXRlcm1heCAmJiByZXNpZCA+IHRvbCk7XG5cbiAgICBMaWIubG9nKCdTbW9vdGhlciBjb252ZXJnZWQgdG8nLCByZXNpZCwgJ2FmdGVyJywgaXRlciwgJ2l0ZXJhdGlvbnMnKTtcblxuICAgIHJldHVybiBkYXRhO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNBcnJheTFEID0gcmVxdWlyZSgnLi4vLi4vbGliJykuaXNBcnJheTFEO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIGhhc1ggPSB4ICYmIHgubGVuZ3RoO1xuICAgIHZhciB5ID0gY29lcmNlKCd5Jyk7XG4gICAgdmFyIGhhc1kgPSB5ICYmIHkubGVuZ3RoO1xuICAgIGlmKCFoYXNYICYmICFoYXNZKSByZXR1cm4gZmFsc2U7XG5cbiAgICB0cmFjZU91dC5fY2hlYXRlciA9ICF4O1xuXG4gICAgaWYoKCFoYXNYIHx8IGlzQXJyYXkxRCh4KSkgJiYgKCFoYXNZIHx8IGlzQXJyYXkxRCh5KSkpIHtcbiAgICAgICAgdmFyIGxlbiA9IGhhc1ggPyB4Lmxlbmd0aCA6IEluZmluaXR5O1xuICAgICAgICBpZihoYXNZKSBsZW4gPSBNYXRoLm1pbihsZW4sIHkubGVuZ3RoKTtcbiAgICAgICAgaWYodHJhY2VPdXQuYSAmJiB0cmFjZU91dC5hLmxlbmd0aCkgbGVuID0gTWF0aC5taW4obGVuLCB0cmFjZU91dC5hLmxlbmd0aCk7XG4gICAgICAgIGlmKHRyYWNlT3V0LmIgJiYgdHJhY2VPdXQuYi5sZW5ndGgpIGxlbiA9IE1hdGgubWluKGxlbiwgdHJhY2VPdXQuYi5sZW5ndGgpO1xuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuICAgIH1cbiAgICBlbHNlIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckdlb0F0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlcmdlby9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgc2NhdHRlckdlb01hcmtlckxpbmVBdHRycyA9IHNjYXR0ZXJHZW9BdHRycy5tYXJrZXIubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICBsb2NhdGlvbnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxvY2F0aW9ubW9kZTogc2NhdHRlckdlb0F0dHJzLmxvY2F0aW9ubW9kZSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyR2VvQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBtYXJrZXI6IHtcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IHNjYXR0ZXJHZW9NYXJrZXJMaW5lQXR0cnMuY29sb3IsXG4gICAgICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckdlb01hcmtlckxpbmVBdHRycy53aWR0aCwge2RmbHQ6IDF9KSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgb3BhY2l0eToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHNjYXR0ZXJHZW9BdHRycy5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHNjYXR0ZXJHZW9BdHRycy51bnNlbGVjdGVkLm1hcmtlci5vcGFjaXR5LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBmbGFnczogWydsb2NhdGlvbicsICd6JywgJ3RleHQnLCAnbmFtZSddXG4gICAgfSlcbn0sXG5cbiAgICBjb2xvcnNjYWxlQXR0cnMoJycsIHtcbiAgICAgICAgY0xldHRlcjogJ3onLFxuICAgICAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbiAgICB9KSxcbiAgICB7Y29sb3JiYXI6IGNvbG9yYmFyQXR0cnN9XG4pO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbnZhciBjb2xvcnNjYWxlQ2FsYyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBjYWxjVHJhY2UgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldID0ge307XG4gICAgICAgIHZhciBsb2MgPSB0cmFjZS5sb2NhdGlvbnNbaV07XG4gICAgICAgIHZhciB6ID0gdHJhY2UueltpXTtcblxuICAgICAgICBjYWxjUHQubG9jID0gdHlwZW9mIGxvYyA9PT0gJ3N0cmluZycgPyBsb2MgOiBudWxsO1xuICAgICAgICBjYWxjUHQueiA9IGlzTnVtZXJpYyh6KSA/IHogOiBCQUROVU07XG4gICAgfVxuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjYWxjVHJhY2UsIHRyYWNlKTtcbiAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UueiwgJycsICd6Jyk7XG4gICAgY2FsY1NlbGVjdGlvbihjYWxjVHJhY2UsIHRyYWNlKTtcblxuICAgIHJldHVybiBjYWxjVHJhY2U7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsb2NhdGlvbnMgPSBjb2VyY2UoJ2xvY2F0aW9ucycpO1xuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG5cbiAgICBpZighKGxvY2F0aW9ucyAmJiBsb2NhdGlvbnMubGVuZ3RoICYmIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHopICYmIHoubGVuZ3RoKSkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IE1hdGgubWluKGxvY2F0aW9ucy5sZW5ndGgsIHoubGVuZ3RoKTtcblxuICAgIGNvZXJjZSgnbG9jYXRpb25tb2RlJyk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcblxuICAgIGNvZXJjZSgnbWFya2VyLmxpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgY29lcmNlKCdtYXJrZXIub3BhY2l0eScpO1xuXG4gICAgY29sb3JzY2FsZURlZmF1bHRzKFxuICAgICAgICB0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICcnLCBjTGV0dGVyOiAneid9XG4gICAgKTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0KSB7XG4gICAgb3V0LmxvY2F0aW9uID0gcHQubG9jYXRpb247XG4gICAgb3V0LnogPSBwdC56O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBmaWxsSG92ZXJUZXh0ID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsX2hvdmVyX3RleHQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIGdlbyA9IHBvaW50RGF0YS5zdWJwbG90O1xuXG4gICAgdmFyIHB0LCBpLCBqLCBpc0luc2lkZTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHB0ID0gY2RbaV07XG4gICAgICAgIGlzSW5zaWRlID0gZmFsc2U7XG5cbiAgICAgICAgaWYocHQuX3BvbHlnb25zKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBwdC5fcG9seWdvbnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZihwdC5fcG9seWdvbnNbal0uY29udGFpbnMoW3h2YWwsIHl2YWxdKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0luc2lkZSA9ICFpc0luc2lkZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gZm9yIHBvbHlnb25zIHRoYXQgY3Jvc3MgYW50aW1lcmlkaWFuIGFzIHh2YWwgaXMgaW4gWy0xODAsIDE4MF1cbiAgICAgICAgICAgICAgICBpZihwdC5fcG9seWdvbnNbal0uY29udGFpbnMoW3h2YWwgKyAzNjAsIHl2YWxdKSkge1xuICAgICAgICAgICAgICAgICAgICBpc0luc2lkZSA9ICFpc0luc2lkZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzSW5zaWRlKSBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCFpc0luc2lkZSB8fCAhcHQpIHJldHVybjtcblxuICAgIHBvaW50RGF0YS54MCA9IHBvaW50RGF0YS54MSA9IHBvaW50RGF0YS54YS5jMnAocHQuY3QpO1xuICAgIHBvaW50RGF0YS55MCA9IHBvaW50RGF0YS55MSA9IHBvaW50RGF0YS55YS5jMnAocHQuY3QpO1xuXG4gICAgcG9pbnREYXRhLmluZGV4ID0gcHQuaW5kZXg7XG4gICAgcG9pbnREYXRhLmxvY2F0aW9uID0gcHQubG9jO1xuICAgIHBvaW50RGF0YS56ID0gcHQuejtcblxuICAgIG1ha2VIb3ZlckluZm8ocG9pbnREYXRhLCB0cmFjZSwgcHQsIGdlby5tb2NrQXhpcyk7XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59O1xuXG5mdW5jdGlvbiBtYWtlSG92ZXJJbmZvKHBvaW50RGF0YSwgdHJhY2UsIHB0LCBheGlzKSB7XG4gICAgdmFyIGhvdmVyaW5mbyA9IHB0LmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcblxuICAgIHZhciBwYXJ0cyA9IChob3ZlcmluZm8gPT09ICdhbGwnKSA/XG4gICAgICAgIGF0dHJpYnV0ZXMuaG92ZXJpbmZvLmZsYWdzIDpcbiAgICAgICAgaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG5cbiAgICB2YXIgaGFzTmFtZSA9IChwYXJ0cy5pbmRleE9mKCduYW1lJykgIT09IC0xKTtcbiAgICB2YXIgaGFzTG9jYXRpb24gPSAocGFydHMuaW5kZXhPZignbG9jYXRpb24nKSAhPT0gLTEpO1xuICAgIHZhciBoYXNaID0gKHBhcnRzLmluZGV4T2YoJ3onKSAhPT0gLTEpO1xuICAgIHZhciBoYXNUZXh0ID0gKHBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpO1xuICAgIHZhciBoYXNJZEFzTmFtZUxhYmVsID0gIWhhc05hbWUgJiYgaGFzTG9jYXRpb247XG5cbiAgICB2YXIgdGV4dCA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZm9ybWF0dGVyKHZhbCkge1xuICAgICAgICByZXR1cm4gQXhlcy50aWNrVGV4dChheGlzLCBheGlzLmMybCh2YWwpLCAnaG92ZXInKS50ZXh0O1xuICAgIH1cblxuICAgIGlmKGhhc0lkQXNOYW1lTGFiZWwpIHtcbiAgICAgICAgcG9pbnREYXRhLm5hbWVPdmVycmlkZSA9IHB0LmxvYztcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihoYXNOYW1lKSBwb2ludERhdGEubmFtZU92ZXJyaWRlID0gdHJhY2UubmFtZTtcbiAgICAgICAgaWYoaGFzTG9jYXRpb24pIHRleHQucHVzaChwdC5sb2MpO1xuICAgIH1cblxuICAgIGlmKGhhc1opIHRleHQucHVzaChmb3JtYXR0ZXIocHQueikpO1xuICAgIGlmKGhhc1RleHQpIHtcbiAgICAgICAgZmlsbEhvdmVyVGV4dChwdCwgdHJhY2UsIHRleHQpO1xuICAgIH1cblxuICAgIHBvaW50RGF0YS5leHRyYVRleHQgPSB0ZXh0LmpvaW4oJzxicj4nKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ2hvcm9wbGV0aCA9IHt9O1xuXG5DaG9yb3BsZXRoLmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbkNob3JvcGxldGguc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5DaG9yb3BsZXRoLmNvbG9yYmFyID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9jb2xvcmJhcicpO1xuQ2hvcm9wbGV0aC5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5DaG9yb3BsZXRoLnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcbkNob3JvcGxldGguc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJykuc3R5bGU7XG5DaG9yb3BsZXRoLnN0eWxlT25TZWxlY3QgPSByZXF1aXJlKCcuL3N0eWxlJykuc3R5bGVPblNlbGVjdDtcbkNob3JvcGxldGguaG92ZXJQb2ludHMgPSByZXF1aXJlKCcuL2hvdmVyJyk7XG5DaG9yb3BsZXRoLmV2ZW50RGF0YSA9IHJlcXVpcmUoJy4vZXZlbnRfZGF0YScpO1xuQ2hvcm9wbGV0aC5zZWxlY3RQb2ludHMgPSByZXF1aXJlKCcuL3NlbGVjdCcpO1xuXG5DaG9yb3BsZXRoLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuQ2hvcm9wbGV0aC5uYW1lID0gJ2Nob3JvcGxldGgnO1xuQ2hvcm9wbGV0aC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dlbycpO1xuQ2hvcm9wbGV0aC5jYXRlZ29yaWVzID0gWydnZW8nLCAnbm9PcGFjaXR5J107XG5DaG9yb3BsZXRoLm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENob3JvcGxldGg7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBwb2x5Z29uID0gcmVxdWlyZSgnLi4vLi4vbGliL3BvbHlnb24nKTtcblxudmFyIGdldFRvcG9qc29uRmVhdHVyZXMgPSByZXF1aXJlKCcuLi8uLi9saWIvdG9wb2pzb25fdXRpbHMnKS5nZXRUb3BvanNvbkZlYXR1cmVzO1xudmFyIGxvY2F0aW9uVG9GZWF0dXJlID0gcmVxdWlyZSgnLi4vLi4vbGliL2dlb19sb2NhdGlvbl91dGlscycpLmxvY2F0aW9uVG9GZWF0dXJlO1xudmFyIHN0eWxlID0gcmVxdWlyZSgnLi9zdHlsZScpLnN0eWxlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIGdlbywgY2FsY0RhdGEpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY2FsY0dlb0pTT04oY2FsY0RhdGFbaV0sIGdlby50b3BvanNvbik7XG4gICAgfVxuXG4gICAgdmFyIGNob3JvcGxldGhMYXllciA9IGdlby5sYXllcnMuYmFja3Bsb3Quc2VsZWN0KCcuY2hvcm9wbGV0aGxheWVyJyk7XG4gICAgTGliLm1ha2VUcmFjZUdyb3VwcyhjaG9yb3BsZXRoTGF5ZXIsIGNhbGNEYXRhLCAndHJhY2UgY2hvcm9wbGV0aCcpLmVhY2goZnVuY3Rpb24oY2FsY1RyYWNlKSB7XG4gICAgICAgIHZhciBzZWwgPSBjYWxjVHJhY2VbMF0ubm9kZTMgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgdmFyIHBhdGhzID0gc2VsLnNlbGVjdEFsbCgncGF0aC5jaG9yb3BsZXRobG9jYXRpb24nKVxuICAgICAgICAgICAgLmRhdGEoTGliLmlkZW50aXR5KTtcblxuICAgICAgICBwYXRocy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuY2xhc3NlZCgnY2hvcm9wbGV0aGxvY2F0aW9uJywgdHJ1ZSk7XG5cbiAgICAgICAgcGF0aHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIGNhbGwgc3R5bGUgaGVyZSB3aXRoaW4gdG9wb2pzb24gcmVxdWVzdCBjYWxsYmFja1xuICAgICAgICBzdHlsZShnZCwgY2FsY1RyYWNlKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGNhbGNHZW9KU09OKGNhbGNUcmFjZSwgdG9wb2pzb24pIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGxlbiA9IGNhbGNUcmFjZS5sZW5ndGg7XG4gICAgdmFyIGZlYXR1cmVzID0gZ2V0VG9wb2pzb25GZWF0dXJlcyh0cmFjZSwgdG9wb2pzb24pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV07XG4gICAgICAgIHZhciBmZWF0dXJlID0gbG9jYXRpb25Ub0ZlYXR1cmUodHJhY2UubG9jYXRpb25tb2RlLCBjYWxjUHQubG9jLCBmZWF0dXJlcyk7XG5cbiAgICAgICAgaWYoIWZlYXR1cmUpIHtcbiAgICAgICAgICAgIGNhbGNQdC5nZW9qc29uID0gbnVsbDtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cblxuICAgICAgICBjYWxjUHQuZ2VvanNvbiA9IGZlYXR1cmU7XG4gICAgICAgIGNhbGNQdC5jdCA9IGZlYXR1cmUucHJvcGVydGllcy5jdDtcbiAgICAgICAgY2FsY1B0LmluZGV4ID0gaTtcbiAgICAgICAgY2FsY1B0Ll9wb2x5Z29ucyA9IGZlYXR1cmUycG9seWdvbnMoZmVhdHVyZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmZWF0dXJlMnBvbHlnb25zKGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5O1xuICAgIHZhciBjb29yZHMgPSBnZW9tZXRyeS5jb29yZGluYXRlcztcbiAgICB2YXIgbG9jID0gZmVhdHVyZS5pZDtcblxuICAgIHZhciBwb2x5Z29ucyA9IFtdO1xuICAgIHZhciBhcHBlbmRQb2x5Z29uLCBqLCBrLCBtO1xuXG4gICAgZnVuY3Rpb24gZG9lc0Nyb3NzQW50aU1lcmRpYW4ocHRzKSB7XG4gICAgICAgIGZvcih2YXIgbCA9IDA7IGwgPCBwdHMubGVuZ3RoIC0gMTsgbCsrKSB7XG4gICAgICAgICAgICBpZihwdHNbbF1bMF0gPiAwICYmIHB0c1tsICsgMV1bMF0gPCAwKSByZXR1cm4gbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZihsb2MgPT09ICdSVVMnIHx8IGxvYyA9PT0gJ0ZKSScpIHtcbiAgICAgICAgLy8gUnVzc2lhIGFuZCBGaWppIGhhdmUgbGFuZG1hc3NlcyB0aGF0IGNyb3NzIHRoZSBhbnRpbWVyaWRpYW4sXG4gICAgICAgIC8vIHdlIG5lZWQgdG8gYWRkICszNjAgdG8gdGhlaXIgbG9uZ2l0dWRlIGNvb3JkaW5hdGVzLCBzbyB0aGF0XG4gICAgICAgIC8vIHBvbHlnb24gJ2NvbnRhaW5zJyBkb2Vzbid0IGdldCBjb25mdXNlZCB3aGVuIGNyb3NzaW5nIHRoZSBhbnRpbWVyaWRpYW4uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIE5vdGUgdGhhdCBvdGhlciBjb3VudHJpZXMgaGF2ZSBwb2x5Z29ucyBvbiBlaXRoZXIgc2lkZSBvZiB0aGUgYW50aW1lcmlkaWFuXG4gICAgICAgIC8vIChlLmcuIHNvbWUgQWxldXRpYW4gaXNsYW5kIGZvciB0aGUgVVNBKSwgYnV0IHRob3NlIGRvbid0IGNvbmZ1c2VcbiAgICAgICAgLy8gdGhlICdjb250YWlucycgbWV0aG9kOyB0aGVzZSBhcmUgc2tpcHBlZCBoZXJlLlxuICAgICAgICBhcHBlbmRQb2x5Z29uID0gZnVuY3Rpb24oX3B0cykge1xuICAgICAgICAgICAgdmFyIHB0cztcblxuICAgICAgICAgICAgaWYoZG9lc0Nyb3NzQW50aU1lcmRpYW4oX3B0cykgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBwdHMgPSBfcHRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwdHMgPSBuZXcgQXJyYXkoX3B0cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGZvcihtID0gMDsgbSA8IF9wdHMubGVuZ3RoOyBtKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZG8gbnV0IG11dGF0ZSBjYWxjZGF0YVtpXVtqXS5nZW9qc29uICEhXG4gICAgICAgICAgICAgICAgICAgIHB0c1ttXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9wdHNbbV1bMF0gPCAwID8gX3B0c1ttXVswXSArIDM2MCA6IF9wdHNbbV1bMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBfcHRzW21dWzFdXG4gICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwb2x5Z29ucy5wdXNoKHBvbHlnb24udGVzdGVyKHB0cykpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihsb2MgPT09ICdBVEEnKSB7XG4gICAgICAgIC8vIEFudGFyY3RpY2EgaGFzIGEgbGFuZG1hc3MgdGhhdCB3cmFwcyBhcm91bmQgZXZlcnkgbG9uZ2l0dWRlcyB3aGljaFxuICAgICAgICAvLyBjb25mdXNlcyB0aGUgJ2NvbnRhaW5zJyBtZXRob2RzLlxuICAgICAgICBhcHBlbmRQb2x5Z29uID0gZnVuY3Rpb24ocHRzKSB7XG4gICAgICAgICAgICB2YXIgY3Jvc3NBbnRpTWVyaWRpYW5JbmRleCA9IGRvZXNDcm9zc0FudGlNZXJkaWFuKHB0cyk7XG5cbiAgICAgICAgICAgIC8vIHBvbHlnb24gdGhhdCBkbyBub3QgY3Jvc3MgYW50aS1tZXJpZGlhbiBuZWVkIG5vIHNwZWNpYWwgaGFuZGxpbmdcbiAgICAgICAgICAgIGlmKGNyb3NzQW50aU1lcmlkaWFuSW5kZXggPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcG9seWdvbnMucHVzaChwb2x5Z29uLnRlc3RlcihwdHMpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gc3RpdGNoIHBvbHlnb24gYnkgYWRkaW5nIHB0IG92ZXIgU291dGggUG9sZSxcbiAgICAgICAgICAgIC8vIHNvIHRoYXQgaXQgY292ZXJzIHRoZSBwcm9qZWN0ZWQgcmVnaW9uIGNvdmVycyBhbGwgbGF0aXR1ZGVzXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHRoZSBhbGdvcml0aG0gYmVsb3cgb25seSB3b3JrcyBmb3IgcG9seWdvbnMgdGhhdFxuICAgICAgICAgICAgLy8gc3RhcnQgYW5kIGVuZCBvbiBsb25naXR1ZGUgLTE4MCAobGlrZSB0aGUgb25lcyBidWlsdCBieVxuICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2V0cGluYXJkL3NhbmUtdG9wb2pzb24pLlxuICAgICAgICAgICAgdmFyIHN0aXRjaCA9IG5ldyBBcnJheShwdHMubGVuZ3RoICsgMSk7XG4gICAgICAgICAgICB2YXIgc2kgPSAwO1xuXG4gICAgICAgICAgICBmb3IobSA9IDA7IG0gPCBwdHMubGVuZ3RoOyBtKyspIHtcbiAgICAgICAgICAgICAgICBpZihtID4gY3Jvc3NBbnRpTWVyaWRpYW5JbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBzdGl0Y2hbc2krK10gPSBbcHRzW21dWzBdICsgMzYwLCBwdHNbbV1bMV1dO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtID09PSBjcm9zc0FudGlNZXJpZGlhbkluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0aXRjaFtzaSsrXSA9IHB0c1ttXTtcbiAgICAgICAgICAgICAgICAgICAgc3RpdGNoW3NpKytdID0gW3B0c1ttXVswXSwgLTkwXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdGl0Y2hbc2krK10gPSBwdHNbbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBwb2x5Z29uLnRlc3RlciBieSBkZWZhdWx0IGFwcGVuZHMgcHRbMF0gdG8gdGhlIHBvaW50cyBsaXN0LFxuICAgICAgICAgICAgLy8gd2UgbXVzdCByZW1vdmUgaXQgaGVyZSwgdG8gYXZvaWQgYSBqdW1wIGluIGxvbmdpdHVkZSBmcm9tIDE4MCB0byAtMTgwLFxuICAgICAgICAgICAgLy8gdGhhdCB3b3VsZCBjb25mdXNlIHRoZSAnY29udGFpbnMnIG1ldGhvZFxuICAgICAgICAgICAgdmFyIHRlc3RlciA9IHBvbHlnb24udGVzdGVyKHN0aXRjaCk7XG4gICAgICAgICAgICB0ZXN0ZXIucHRzLnBvcCgpO1xuICAgICAgICAgICAgcG9seWdvbnMucHVzaCh0ZXN0ZXIpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSB1c2luZyBzYW1lIGFycmF5IHJlZiBpcyBmaW5lXG4gICAgICAgIGFwcGVuZFBvbHlnb24gPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgIHBvbHlnb25zLnB1c2gocG9seWdvbi50ZXN0ZXIocHRzKSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3dpdGNoKGdlb21ldHJ5LnR5cGUpIHtcbiAgICAgICAgY2FzZSAnTXVsdGlQb2x5Z29uJzpcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGNvb3Jkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGNvb3Jkc1tqXS5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBhcHBlbmRQb2x5Z29uKGNvb3Jkc1tqXVtrXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY29vcmRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgYXBwZW5kUG9seWdvbihjb29yZHNbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvbHlnb25zO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG5cbiAgICB2YXIgaSwgZGksIGN0LCB4LCB5O1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGRpID0gY2RbaV07XG4gICAgICAgICAgICBjdCA9IGRpLmN0O1xuXG4gICAgICAgICAgICBpZighY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB4ID0geGEuYzJwKGN0KTtcbiAgICAgICAgICAgIHkgPSB5YS5jMnAoY3QpO1xuXG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBudWxsLCBpLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnROdW1iZXI6IGksXG4gICAgICAgICAgICAgICAgICAgIGxvbjogY3RbMF0sXG4gICAgICAgICAgICAgICAgICAgIGxhdDogY3RbMV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG5cbmZ1bmN0aW9uIHN0eWxlKGdkLCBjYWxjVHJhY2UpIHtcbiAgICBpZihjYWxjVHJhY2UpIHN0eWxlVHJhY2UoZ2QsIGNhbGNUcmFjZSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlVHJhY2UoZ2QsIGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICB2YXIgcyA9IGNhbGNUcmFjZVswXS5ub2RlMztcbiAgICB2YXIgbG9jcyA9IHMuc2VsZWN0QWxsKCcuY2hvcm9wbGV0aGxvY2F0aW9uJyk7XG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgbWFya2VyTGluZSA9IG1hcmtlci5saW5lIHx8IHt9O1xuXG4gICAgdmFyIHNjbEZ1bmMgPSBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuYyhcbiAgICAgICAgQ29sb3JzY2FsZS5leHRyYWN0U2NhbGUoXG4gICAgICAgICAgICB0cmFjZS5jb2xvcnNjYWxlLFxuICAgICAgICAgICAgdHJhY2Uuem1pbixcbiAgICAgICAgICAgIHRyYWNlLnptYXhcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICBsb2NzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgIC5hdHRyKCdmaWxsJywgc2NsRnVuYyhkLnopKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBkLm1sYyB8fCBtYXJrZXJMaW5lLmNvbG9yKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5kYXNoTGluZSwgJycsIGQubWx3IHx8IG1hcmtlckxpbmUud2lkdGggfHwgMClcbiAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIG1hcmtlci5vcGFjaXR5KTtcbiAgICB9KTtcblxuICAgIERyYXdpbmcuc2VsZWN0ZWRQb2ludFN0eWxlKGxvY3MsIHRyYWNlLCBnZCk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT25TZWxlY3QoZ2QsIGNhbGNUcmFjZSkge1xuICAgIHZhciBzID0gY2FsY1RyYWNlWzBdLm5vZGUzO1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgIERyYXdpbmcuc2VsZWN0ZWRQb2ludFN0eWxlKHMuc2VsZWN0QWxsKCcuY2hvcm9wbGV0aGxvY2F0aW9uJyksIHRyYWNlLCBnZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3R5bGVUcmFjZShnZCwgY2FsY1RyYWNlKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBzdHlsZU9uU2VsZWN0XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG52YXIgbWVzaDNkQXR0cnMgPSByZXF1aXJlKCcuLi9tZXNoM2QvYXR0cmlidXRlcycpO1xudmFyIGJhc2VBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIGF0dHJzID0ge1xuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdzoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBUT0RPIGFkZCB3YXkgdG8gc3BlY2lmeSBjb25lIHBvc2l0aW9ucyBpbmRlcGVuZGVudGx5IG9mIHRoZSB2ZWN0b3IgZmllbGRcbiAgICAvLyBwcm92aWRlZCwgc2ltaWxhciB0byBNQVRMQUIncyBjb25lcGxvdCBDeC9DeS9DeiBtZXNoZ3JpZHMsXG4gICAgLy8gc2VlIGh0dHBzOi8vd3d3Lm1hdGh3b3Jrcy5jb20vaGVscC9tYXRsYWIvcmVmL2NvbmVwbG90Lmh0bWxcbiAgICAvL1xuICAgIC8vIEFsdGVybmF0aXZlbHksIGlmIG91ciBnb2FsIGlzIG9ubHkgdG8gJ2ZpbGwgaW4gZ2FwcycgaW4gdGhlIHZlY3RvciBkYXRhLFxuICAgIC8vIHdlIGNvdWxkIHRyeSB0byBleHRlbmQgdGhlIGhlYXRtYXAgJ2Nvbm5lY3RnYXBzJyBhbGdvcml0aG0gdG8gM0QuXG4gICAgLy8gRnJvbSBBSjogdGhpcyBwYXJ0aWN1bGFyIGFsZ29yaXRobSB3aGljaCBhbW91bnRzIHRvIGEgUG9pc3NvbiBlcXVhdGlvbixcbiAgICAvLyBib3RoIGZvciBpbnRlcnBvbGF0aW9uIGFuZCBleHRyYXBvbGF0aW9uIC0gaXMgdGhlIHJpZ2h0IG9uZSB0byB1c2UgZm9yXG4gICAgLy8gY29uZXMgdG9vLiAgSXQgbWFrZXMgYSBmaWVsZCB3aXRoIHplcm8gZGl2ZXJnZW5jZSwgd2hpY2ggaXMgYSBnb29kXG4gICAgLy8gYmFzZWxpbmUgYXNzdW1wdGlvbiBmb3IgdmVjdG9yIGZpZWxkcy5cbiAgICAvL1xuICAgIC8vIGNvbmVzOiB7XG4gICAgLy8gICAgIC8vIHBvdGVudGlhbCBhdHRyaWJ1dGVzIHRvIGFkZDpcbiAgICAvLyAgICAgLy9cbiAgICAvLyAgICAgLy8gLSBtZXNobW9kZTogJ2NhcnRlc2lhbi1wcm9kdWN0JywgJ3B0cycsICdncmlkJ1xuICAgIC8vICAgICAvL1xuICAgIC8vICAgICAvLyB1bmRlciBgbWVzaG1vZGU6ICdncmlkJ2BcbiAgICAvLyAgICAgLy8gLSAoeHx5fHopZ3JpZC5zdGFydFxuICAgIC8vICAgICAvLyAtICh4fHl8eilncmlkLmVuZFxuICAgIC8vICAgICAvLyAtICh4fHl8eilncmlkLnNpemVcbiAgICAvL1xuICAgIC8vICAgICB4OiB7XG4gICAgLy8gICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgLy8gICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIC8vICAgICAgICAgXG4gICAgLy8gICAgIH0sXG4gICAgLy8gICAgIHk6IHtcbiAgICAvLyAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAvLyAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgLy8gICAgICAgICBcbiAgICAvLyAgICAgfSxcbiAgICAvLyAgICAgejoge1xuICAgIC8vICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgIC8vICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAvLyAgICAgICAgIFxuICAgIC8vICAgICB9LFxuICAgIC8vXG4gICAgLy8gICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgLy8gICAgIFxuICAgIC8vIH0sXG5cbiAgICBzaXplbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzY2FsZWQnLCAnYWJzb2x1dGUnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGRmbHQ6ICdzY2FsZWQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNpemVyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RpcCcsICd0YWlsJywgJ2NtJywgJ2NlbnRlciddLFxuICAgICAgICBkZmx0OiAnY20nLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG5leHRlbmRGbGF0KGF0dHJzLCBjb2xvcnNjYWxlQXR0cnMoJycsIHtcbiAgICBjb2xvckF0dHI6ICd1L3YvdyBub3JtJyxcbiAgICBzaG93U2NhbGVEZmx0OiB0cnVlLFxuICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xufSksIHtcbiAgICBjb2xvcmJhcjogY29sb3JiYXJBdHRyc1xufSk7XG5cbnZhciBmcm9tTWVzaDNkID0gWydvcGFjaXR5JywgJ2xpZ2h0cG9zaXRpb24nLCAnbGlnaHRpbmcnXTtcblxuZnJvbU1lc2gzZC5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICBhdHRyc1trXSA9IG1lc2gzZEF0dHJzW2tdO1xufSk7XG5cbmF0dHJzLmhvdmVyaW5mbyA9IGV4dGVuZEZsYXQoe30sIGJhc2VBdHRycy5ob3ZlcmluZm8sIHtcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIGZsYWdzOiBbJ3gnLCAneScsICd6JywgJ3UnLCAndicsICd3JywgJ25vcm0nLCAndGV4dCcsICduYW1lJ10sXG4gICAgZGZsdDogJ3greSt6K25vcm0rdGV4dCtuYW1lJ1xufSk7XG5cbmF0dHJzLnRyYW5zZm9ybXMgPSB1bmRlZmluZWQ7XG5cbm1vZHVsZS5leHBvcnRzID0gYXR0cnM7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvcnNjYWxlQ2FsYyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgdSA9IHRyYWNlLnU7XG4gICAgdmFyIHYgPSB0cmFjZS52O1xuICAgIHZhciB3ID0gdHJhY2UudztcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oXG4gICAgICAgIHRyYWNlLngubGVuZ3RoLCB0cmFjZS55Lmxlbmd0aCwgdHJhY2Uuei5sZW5ndGgsXG4gICAgICAgIHUubGVuZ3RoLCB2Lmxlbmd0aCwgdy5sZW5ndGhcbiAgICApO1xuICAgIHZhciBub3JtTWF4ID0gLUluZmluaXR5O1xuICAgIHZhciBub3JtTWluID0gSW5maW5pdHk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHV1ID0gdVtpXTtcbiAgICAgICAgdmFyIHZ2ID0gdltpXTtcbiAgICAgICAgdmFyIHd3ID0gd1tpXTtcbiAgICAgICAgdmFyIG5vcm0gPSBNYXRoLnNxcnQodXUgKiB1dSArIHZ2ICogdnYgKyB3dyAqIHd3KTtcblxuICAgICAgICBub3JtTWF4ID0gTWF0aC5tYXgobm9ybU1heCwgbm9ybSk7XG4gICAgICAgIG5vcm1NaW4gPSBNYXRoLm1pbihub3JtTWluLCBub3JtKTtcbiAgICB9XG5cbiAgICB0cmFjZS5fbGVuID0gbGVuO1xuICAgIHRyYWNlLl9ub3JtTWF4ID0gbm9ybU1heDtcblxuICAgIGNvbG9yc2NhbGVDYWxjKHRyYWNlLCBbbm9ybU1pbiwgbm9ybU1heF0sICcnLCAnYycpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbmVQbG90ID0gcmVxdWlyZSgnZ2wtY29uZTNkJyk7XG52YXIgY3JlYXRlQ29uZU1lc2ggPSByZXF1aXJlKCdnbC1jb25lM2QnKS5jcmVhdGVDb25lTWVzaDtcblxudmFyIHNpbXBsZU1hcCA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLnNpbXBsZU1hcDtcbnZhciBwYXJzZUNvbG9yU2NhbGUgPSByZXF1aXJlKCcuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yJykucGFyc2VDb2xvclNjYWxlO1xudmFyIHppcDMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nbDNkL3ppcDMnKTtcblxuZnVuY3Rpb24gQ29uZShzY2VuZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMubWVzaCA9IG51bGw7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbn1cblxudmFyIHByb3RvID0gQ29uZS5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLm1lc2gpIHtcbiAgICAgICAgdmFyIHNlbGVjdEluZGV4ID0gc2VsZWN0aW9uLmluZGV4ID0gc2VsZWN0aW9uLmRhdGEuaW5kZXg7XG4gICAgICAgIHZhciB4eCA9IHRoaXMuZGF0YS54W3NlbGVjdEluZGV4XTtcbiAgICAgICAgdmFyIHl5ID0gdGhpcy5kYXRhLnlbc2VsZWN0SW5kZXhdO1xuICAgICAgICB2YXIgenogPSB0aGlzLmRhdGEueltzZWxlY3RJbmRleF07XG4gICAgICAgIHZhciB1dSA9IHRoaXMuZGF0YS51W3NlbGVjdEluZGV4XTtcbiAgICAgICAgdmFyIHZ2ID0gdGhpcy5kYXRhLnZbc2VsZWN0SW5kZXhdO1xuICAgICAgICB2YXIgd3cgPSB0aGlzLmRhdGEud1tzZWxlY3RJbmRleF07XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHh4LCB5eSwgenosXG4gICAgICAgICAgICB1dSwgdnYsIHd3LFxuICAgICAgICAgICAgTWF0aC5zcXJ0KHV1ICogdXUgKyB2diAqIHZ2ICsgd3cgKiB3dylcbiAgICAgICAgXTtcblxuICAgICAgICB2YXIgdGV4dCA9IHRoaXMuZGF0YS50ZXh0O1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHRleHQpICYmIHRleHRbc2VsZWN0SW5kZXhdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0ZXh0W3NlbGVjdEluZGV4XTtcbiAgICAgICAgfSBlbHNlIGlmKHRleHQpIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0ZXh0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufTtcblxudmFyIGF4aXNOYW1lMnNjYWxlSW5kZXggPSB7eGF4aXM6IDAsIHlheGlzOiAxLCB6YXhpczogMn07XG52YXIgYW5jaG9yMmNvbmVPZmZzZXQgPSB7dGlwOiAxLCB0YWlsOiAwLCBjbTogMC4yNSwgY2VudGVyOiAwLjV9O1xudmFyIGFuY2hvcjJjb25lU3BhbiA9IHt0aXA6IDEsIHRhaWw6IDEsIGNtOiAwLjc1LCBjZW50ZXI6IDAuNX07XG5cbmZ1bmN0aW9uIGNvbnZlcnQoc2NlbmUsIHRyYWNlKSB7XG4gICAgdmFyIHNjZW5lTGF5b3V0ID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuICAgIHZhciBkYXRhU2NhbGUgPSBzY2VuZS5kYXRhU2NhbGU7XG4gICAgdmFyIGNvbmVPcHRzID0ge307XG5cbiAgICBmdW5jdGlvbiB0b0RhdGFDb29yZHMoYXJyLCBheGlzTmFtZSkge1xuICAgICAgICB2YXIgYXggPSBzY2VuZUxheW91dFtheGlzTmFtZV07XG4gICAgICAgIHZhciBzY2FsZSA9IGRhdGFTY2FsZVtheGlzTmFtZTJzY2FsZUluZGV4W2F4aXNOYW1lXV07XG4gICAgICAgIHJldHVybiBzaW1wbGVNYXAoYXJyLCBmdW5jdGlvbih2KSB7IHJldHVybiBheC5kMmwodikgKiBzY2FsZTsgfSk7XG4gICAgfVxuXG4gICAgY29uZU9wdHMudmVjdG9ycyA9IHppcDMoXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS51LCAneGF4aXMnKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnYsICd5YXhpcycpLFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UudywgJ3pheGlzJyksXG4gICAgICAgIHRyYWNlLl9sZW5cbiAgICApO1xuXG4gICAgY29uZU9wdHMucG9zaXRpb25zID0gemlwMyhcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLngsICd4YXhpcycpLFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UueSwgJ3lheGlzJyksXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS56LCAnemF4aXMnKSxcbiAgICAgICAgdHJhY2UuX2xlblxuICAgICk7XG5cbiAgICBjb25lT3B0cy5jb2xvcm1hcCA9IHBhcnNlQ29sb3JTY2FsZSh0cmFjZS5jb2xvcnNjYWxlKTtcbiAgICBjb25lT3B0cy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHMgPSBbdHJhY2UuY21pbiAvIHRyYWNlLl9ub3JtTWF4LCB0cmFjZS5jbWF4IC8gdHJhY2UuX25vcm1NYXhdO1xuICAgIGNvbmVPcHRzLmNvbmVPZmZzZXQgPSBhbmNob3IyY29uZU9mZnNldFt0cmFjZS5hbmNob3JdO1xuXG4gICAgaWYodHJhY2Uuc2l6ZW1vZGUgPT09ICdzY2FsZWQnKSB7XG4gICAgICAgIC8vIHVuaXRsZXNzIHNpemVyZWZcbiAgICAgICAgY29uZU9wdHMuY29uZVNpemUgPSB0cmFjZS5zaXplcmVmIHx8IDAuNTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBzaXplcmVmIGhlcmUgaGFzIHVuaXQgb2YgdmVsb2NpdHlcbiAgICAgICAgY29uZU9wdHMuY29uZVNpemUgPSB0cmFjZS5zaXplcmVmICYmIHRyYWNlLl9ub3JtTWF4ID9cbiAgICAgICAgICAgIHRyYWNlLnNpemVyZWYgLyB0cmFjZS5fbm9ybU1heCA6XG4gICAgICAgICAgICAwLjU7XG4gICAgfVxuXG4gICAgdmFyIG1lc2hEYXRhID0gY29uZVBsb3QoY29uZU9wdHMpO1xuXG4gICAgLy8gcGFzcyBnbC1tZXNoM2QgbGlnaHRpbmcgYXR0cmlidXRlc1xuICAgIHZhciBscCA9IHRyYWNlLmxpZ2h0cG9zaXRpb247XG4gICAgbWVzaERhdGEubGlnaHRQb3NpdGlvbiA9IFtscC54LCBscC55LCBscC56XTtcbiAgICBtZXNoRGF0YS5hbWJpZW50ID0gdHJhY2UubGlnaHRpbmcuYW1iaWVudDtcbiAgICBtZXNoRGF0YS5kaWZmdXNlID0gdHJhY2UubGlnaHRpbmcuZGlmZnVzZTtcbiAgICBtZXNoRGF0YS5zcGVjdWxhciA9IHRyYWNlLmxpZ2h0aW5nLnNwZWN1bGFyO1xuICAgIG1lc2hEYXRhLnJvdWdobmVzcyA9IHRyYWNlLmxpZ2h0aW5nLnJvdWdobmVzcztcbiAgICBtZXNoRGF0YS5mcmVzbmVsID0gdHJhY2UubGlnaHRpbmcuZnJlc25lbDtcbiAgICBtZXNoRGF0YS5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eTtcblxuICAgIC8vIHN0YXNoIGF1dG9yYW5nZSBwYWQgdmFsdWVcbiAgICB0cmFjZS5fcGFkID0gYW5jaG9yMmNvbmVTcGFuW3RyYWNlLmFuY2hvcl0gKiBtZXNoRGF0YS52ZWN0b3JTY2FsZSAqIG1lc2hEYXRhLmNvbmVTY2FsZSAqIHRyYWNlLl9ub3JtTWF4O1xuXG4gICAgcmV0dXJuIG1lc2hEYXRhO1xufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdGhpcy5kYXRhID0gZGF0YTtcblxuICAgIHZhciBtZXNoRGF0YSA9IGNvbnZlcnQodGhpcy5zY2VuZSwgZGF0YSk7XG4gICAgdGhpcy5tZXNoLnVwZGF0ZShtZXNoRGF0YSk7XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMubWVzaCk7XG4gICAgdGhpcy5tZXNoLmRpc3Bvc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZUNvbmVUcmFjZShzY2VuZSwgZGF0YSkge1xuICAgIHZhciBnbCA9IHNjZW5lLmdscGxvdC5nbDtcblxuICAgIHZhciBtZXNoRGF0YSA9IGNvbnZlcnQoc2NlbmUsIGRhdGEpO1xuICAgIHZhciBtZXNoID0gY3JlYXRlQ29uZU1lc2goZ2wsIG1lc2hEYXRhKTtcblxuICAgIHZhciBjb25lID0gbmV3IENvbmUoc2NlbmUsIGRhdGEudWlkKTtcbiAgICBjb25lLm1lc2ggPSBtZXNoO1xuICAgIGNvbmUuZGF0YSA9IGRhdGE7XG4gICAgbWVzaC5fdHJhY2UgPSBjb25lO1xuXG4gICAgc2NlbmUuZ2xwbG90LmFkZChtZXNoKTtcblxuICAgIHJldHVybiBjb25lO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUNvbmVUcmFjZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB1ID0gY29lcmNlKCd1Jyk7XG4gICAgdmFyIHYgPSBjb2VyY2UoJ3YnKTtcbiAgICB2YXIgdyA9IGNvZXJjZSgndycpO1xuXG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG5cbiAgICBpZihcbiAgICAgICAgIXUgfHwgIXUubGVuZ3RoIHx8ICF2IHx8ICF2Lmxlbmd0aCB8fCAhdyB8fCAhdy5sZW5ndGggfHxcbiAgICAgICAgIXggfHwgIXgubGVuZ3RoIHx8ICF5IHx8ICF5Lmxlbmd0aCB8fCAheiB8fCAhei5sZW5ndGhcbiAgICApIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29lcmNlKCdzaXplcmVmJyk7XG4gICAgY29lcmNlKCdzaXplbW9kZScpO1xuXG4gICAgY29lcmNlKCdhbmNob3InKTtcblxuICAgIGNvZXJjZSgnbGlnaHRpbmcuYW1iaWVudCcpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuZGlmZnVzZScpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuc3BlY3VsYXInKTtcbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLnJvdWdobmVzcycpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuZnJlc25lbCcpO1xuICAgIGNvZXJjZSgnbGlnaHRwb3NpdGlvbi54Jyk7XG4gICAgY29lcmNlKCdsaWdodHBvc2l0aW9uLnknKTtcbiAgICBjb2VyY2UoJ2xpZ2h0cG9zaXRpb24ueicpO1xuXG4gICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICdjJ30pO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG5cbiAgICAvLyBkaXNhYmxlIDFEIHRyYW5zZm9ybXMgKGZvciBub3cpXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjb25lJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2wzZCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wzZCddLFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjoge1xuICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgbWF4OiAnY21heCdcbiAgICB9LFxuICAgIGNhbGM6IHJlcXVpcmUoJy4vY2FsYycpLFxuICAgIHBsb3Q6IHJlcXVpcmUoJy4vY29udmVydCcpLFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVhdG1hcEF0dHJzID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlckF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG52YXIgZGFzaCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZy9hdHRyaWJ1dGVzJykuZGFzaDtcbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBmaWx0ZXJPcHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvZmlsdGVyX29wcycpO1xudmFyIENPTVBBUklTT05fT1BTMiA9IGZpbHRlck9wcy5DT01QQVJJU09OX09QUzI7XG52YXIgSU5URVJWQUxfT1BTID0gZmlsdGVyT3BzLklOVEVSVkFMX09QUztcblxudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICB6OiBoZWF0bWFwQXR0cnMueixcbiAgICB4OiBoZWF0bWFwQXR0cnMueCxcbiAgICB4MDogaGVhdG1hcEF0dHJzLngwLFxuICAgIGR4OiBoZWF0bWFwQXR0cnMuZHgsXG4gICAgeTogaGVhdG1hcEF0dHJzLnksXG4gICAgeTA6IGhlYXRtYXBBdHRycy55MCxcbiAgICBkeTogaGVhdG1hcEF0dHJzLmR5LFxuICAgIHRleHQ6IGhlYXRtYXBBdHRycy50ZXh0LFxuICAgIHRyYW5zcG9zZTogaGVhdG1hcEF0dHJzLnRyYW5zcG9zZSxcbiAgICB4dHlwZTogaGVhdG1hcEF0dHJzLnh0eXBlLFxuICAgIHl0eXBlOiBoZWF0bWFwQXR0cnMueXR5cGUsXG4gICAgemhvdmVyZm9ybWF0OiBoZWF0bWFwQXR0cnMuemhvdmVyZm9ybWF0LFxuXG4gICAgY29ubmVjdGdhcHM6IGhlYXRtYXBBdHRycy5jb25uZWN0Z2FwcyxcblxuICAgIGZpbGxjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGF1dG9jb250b3VyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge1xuICAgICAgICAgICAgJ2NvbnRvdXJzLnN0YXJ0JzogdW5kZWZpbmVkLFxuICAgICAgICAgICAgJ2NvbnRvdXJzLmVuZCc6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICdjb250b3Vycy5zaXplJzogdW5kZWZpbmVkXG4gICAgICAgIH0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgbmNvbnRvdXJzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgZGZsdDogMTUsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjb250b3Vyczoge1xuICAgICAgICB0eXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnbGV2ZWxzJywgJ2NvbnN0cmFpbnQnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdsZXZlbHMnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBpbXBsaWVkRWRpdHM6IHsnXmF1dG9jb250b3VyJzogZmFsc2V9LFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVuZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hdXRvY29udG91cic6IGZhbHNlfSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBpbXBsaWVkRWRpdHM6IHsnXmF1dG9jb250b3VyJzogZmFsc2V9LFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yaW5nOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnZmlsbCcsICdoZWF0bWFwJywgJ2xpbmVzJywgJ25vbmUnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdmaWxsJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaG93bGluZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2hvd2xhYmVsczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbGFiZWxmb250OiBmb250QXR0cnMoe1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIGNvbG9yRWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGxhYmVsZm9ybWF0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG9wZXJhdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbXS5jb25jYXQoQ09NUEFSSVNPTl9PUFMyKS5jb25jYXQoSU5URVJWQUxfT1BTKSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJz0nLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czogeydhdXRvY29udG91cic6IGZhbHNlfVxuICAgIH0sXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLmNvbG9yLCB7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlK2NvbG9yYmFycycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLndpZHRoLCB7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlK2NvbG9yYmFycydcbiAgICAgICAgfSksXG4gICAgICAgIGRhc2g6IGRhc2gsXG4gICAgICAgIHNtb290aGluZzogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy5zbW9vdGhpbmcsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH1cbn0sXG4gICAgY29sb3JzY2FsZUF0dHJzKCcnLCB7XG4gICAgICAgIGNMZXR0ZXI6ICd6JyxcbiAgICAgICAgYXV0b0NvbG9yRGZsdDogZmFsc2UsXG4gICAgICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xuICAgIH0pLFxuICAgIHsgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMgfVxuKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVhdG1hcENhbGMgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NhbGMnKTtcbnZhciBzZXRDb250b3VycyA9IHJlcXVpcmUoJy4vc2V0X2NvbnRvdXJzJyk7XG5cbi8vIG1vc3QgaXMgdGhlIHNhbWUgYXMgaGVhdG1hcCBjYWxjLCB0aGVuIGFkanVzdCBpdFxuLy8gdGhvdWdoIGEgZmV3IHRoaW5ncyBpbnNpZGUgaGVhdG1hcCBjYWxjIHN0aWxsIGxvb2sgZm9yXG4vLyBjb250b3VyIG1hcHMsIGJlY2F1c2UgdGhlIG1ha2VCb3VuZEFycmF5IGNhbGxzIGFyZSB0b28gZW50YW5nbGVkXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGNkID0gaGVhdG1hcENhbGMoZ2QsIHRyYWNlKTtcbiAgICBzZXRDb250b3Vycyh0cmFjZSk7XG4gICAgcmV0dXJuIGNkO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihwYXRoaW5mbywgb3BlcmF0aW9uLCBwZXJpbWV0ZXIsIHRyYWNlKSB7XG4gICAgLy8gQWJhbmRvbiBhbGwgaG9wZSwgeWUgd2hvIGVudGVyIGhlcmUuXG4gICAgdmFyIGksIHYxLCB2MjtcbiAgICB2YXIgcGkwID0gcGF0aGluZm9bMF07XG4gICAgdmFyIG5hID0gcGkwLngubGVuZ3RoO1xuICAgIHZhciBuYiA9IHBpMC55Lmxlbmd0aDtcbiAgICB2YXIgeiA9IHBpMC56O1xuICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuXG4gICAgdmFyIGJvdW5kYXJ5TWF4ID0gLUluZmluaXR5O1xuICAgIHZhciBib3VuZGFyeU1pbiA9IEluZmluaXR5O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbmI7IGkrKykge1xuICAgICAgICBib3VuZGFyeU1pbiA9IE1hdGgubWluKGJvdW5kYXJ5TWluLCB6W2ldWzBdKTtcbiAgICAgICAgYm91bmRhcnlNaW4gPSBNYXRoLm1pbihib3VuZGFyeU1pbiwgeltpXVtuYSAtIDFdKTtcbiAgICAgICAgYm91bmRhcnlNYXggPSBNYXRoLm1heChib3VuZGFyeU1heCwgeltpXVswXSk7XG4gICAgICAgIGJvdW5kYXJ5TWF4ID0gTWF0aC5tYXgoYm91bmRhcnlNYXgsIHpbaV1bbmEgLSAxXSk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAxOyBpIDwgbmEgLSAxOyBpKyspIHtcbiAgICAgICAgYm91bmRhcnlNaW4gPSBNYXRoLm1pbihib3VuZGFyeU1pbiwgelswXVtpXSk7XG4gICAgICAgIGJvdW5kYXJ5TWluID0gTWF0aC5taW4oYm91bmRhcnlNaW4sIHpbbmIgLSAxXVtpXSk7XG4gICAgICAgIGJvdW5kYXJ5TWF4ID0gTWF0aC5tYXgoYm91bmRhcnlNYXgsIHpbMF1baV0pO1xuICAgICAgICBib3VuZGFyeU1heCA9IE1hdGgubWF4KGJvdW5kYXJ5TWF4LCB6W25iIC0gMV1baV0pO1xuICAgIH1cblxuICAgIHBpMC5wcmVmaXhCb3VuZGFyeSA9IGZhbHNlO1xuXG4gICAgc3dpdGNoKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlICc+JzpcbiAgICAgICAgICAgIGlmKGNvbnRvdXJzLnZhbHVlID4gYm91bmRhcnlNYXgpIHtcbiAgICAgICAgICAgICAgICBwaTAucHJlZml4Qm91bmRhcnkgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgICAgaWYoY29udG91cnMudmFsdWUgPCBib3VuZGFyeU1pbikge1xuICAgICAgICAgICAgICAgIHBpMC5wcmVmaXhCb3VuZGFyeSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnW10nOlxuICAgICAgICAgICAgdjEgPSBNYXRoLm1pbi5hcHBseShudWxsLCBjb250b3Vycy52YWx1ZSk7XG4gICAgICAgICAgICB2MiA9IE1hdGgubWF4LmFwcGx5KG51bGwsIGNvbnRvdXJzLnZhbHVlKTtcbiAgICAgICAgICAgIGlmKHYyIDwgYm91bmRhcnlNaW4gfHwgdjEgPiBib3VuZGFyeU1heCkge1xuICAgICAgICAgICAgICAgIHBpMC5wcmVmaXhCb3VuZGFyeSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnXVsnOlxuICAgICAgICAgICAgdjEgPSBNYXRoLm1pbi5hcHBseShudWxsLCBjb250b3Vycy52YWx1ZSk7XG4gICAgICAgICAgICB2MiA9IE1hdGgubWF4LmFwcGx5KG51bGwsIGNvbnRvdXJzLnZhbHVlKTtcbiAgICAgICAgICAgIGlmKHYxIDwgYm91bmRhcnlNaW4gJiYgdjIgPiBib3VuZGFyeU1heCkge1xuICAgICAgICAgICAgICAgIHBpMC5wcmVmaXhCb3VuZGFyeSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkcmF3Q29sb3JiYXIgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2RyYXcnKTtcblxudmFyIG1ha2VDb2xvck1hcCA9IHJlcXVpcmUoJy4vbWFrZV9jb2xvcl9tYXAnKTtcbnZhciBlbmRQbHVzID0gcmVxdWlyZSgnLi9lbmRfcGx1cycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29sb3JiYXIoZ2QsIGNkKSB7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIGNiSWQgPSAnY2InICsgdHJhY2UudWlkO1xuXG4gICAgZ2QuX2Z1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJy4nICsgY2JJZCkucmVtb3ZlKCk7XG5cbiAgICBpZighdHJhY2Uuc2hvd3NjYWxlKSByZXR1cm47XG5cbiAgICB2YXIgY2IgPSBjZFswXS50LmNiID0gZHJhd0NvbG9yYmFyKGdkLCBjYklkKTtcblxuICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgIHZhciBsaW5lID0gdHJhY2UubGluZTtcbiAgICB2YXIgY3MgPSBjb250b3Vycy5zaXplIHx8IDE7XG4gICAgdmFyIGNvbG9yaW5nID0gY29udG91cnMuY29sb3Jpbmc7XG5cbiAgICB2YXIgY29sb3JNYXAgPSBtYWtlQ29sb3JNYXAodHJhY2UsIHtpc0NvbG9yYmFyOiB0cnVlfSk7XG5cbiAgICBjYi5maWxsZ3JhZGllbnQoY29sb3JpbmcgPT09ICdoZWF0bWFwJyA/IHRyYWNlLmNvbG9yc2NhbGUgOiAnJylcbiAgICAgICAgLnpyYW5nZShjb2xvcmluZyA9PT0gJ2hlYXRtYXAnID8gW3RyYWNlLnptaW4sIHRyYWNlLnptYXhdIDogJycpXG4gICAgICAgIC5maWxsY29sb3IoKGNvbG9yaW5nID09PSAnZmlsbCcpID8gY29sb3JNYXAgOiAnJylcbiAgICAgICAgLmxpbmUoe1xuICAgICAgICAgICAgY29sb3I6IGNvbG9yaW5nID09PSAnbGluZXMnID8gY29sb3JNYXAgOiBsaW5lLmNvbG9yLFxuICAgICAgICAgICAgd2lkdGg6IGNvbnRvdXJzLnNob3dsaW5lcyAhPT0gZmFsc2UgPyBsaW5lLndpZHRoIDogMCxcbiAgICAgICAgICAgIGRhc2g6IGxpbmUuZGFzaFxuICAgICAgICB9KVxuICAgICAgICAubGV2ZWxzKHtcbiAgICAgICAgICAgIHN0YXJ0OiBjb250b3Vycy5zdGFydCxcbiAgICAgICAgICAgIGVuZDogZW5kUGx1cyhjb250b3VycyksXG4gICAgICAgICAgICBzaXplOiBjc1xuICAgICAgICB9KVxuICAgICAgICAub3B0aW9ucyh0cmFjZS5jb2xvcmJhcikoKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBzb21lIGNvbnN0YW50cyB0byBoZWxwIHdpdGggbWFyY2hpbmcgc3F1YXJlcyBhbGdvcml0aG1cbiAgICAvLyB3aGVyZSBkb2VzIHRoZSBwYXRoIHN0YXJ0IGZvciBlYWNoIGluZGV4P1xuICAgIEJPVFRPTVNUQVJUOiBbMSwgOSwgMTMsIDEwNCwgNzEzXSxcbiAgICBUT1BTVEFSVDogWzQsIDYsIDcsIDEwNCwgNzEzXSxcbiAgICBMRUZUU1RBUlQ6IFs4LCAxMiwgMTQsIDIwOCwgMTExNF0sXG4gICAgUklHSFRTVEFSVDogWzIsIDMsIDExLCAyMDgsIDExMTRdLFxuXG4gICAgLy8gd2hpY2ggd2F5IFtkeCxkeV0gZG8gd2UgbGVhdmUgYSBnaXZlbiBpbmRleD9cbiAgICAvLyBzYWRkbGVzIGFyZSBhbHJlYWR5IGRpc2FtYmlndWF0ZWRcbiAgICBORVdERUxUQTogW1xuICAgICAgICBudWxsLCBbLTEsIDBdLCBbMCwgLTFdLCBbLTEsIDBdLFxuICAgICAgICBbMSwgMF0sIG51bGwsIFswLCAtMV0sIFstMSwgMF0sXG4gICAgICAgIFswLCAxXSwgWzAsIDFdLCBudWxsLCBbMCwgMV0sXG4gICAgICAgIFsxLCAwXSwgWzEsIDBdLCBbMCwgLTFdXG4gICAgXSxcblxuICAgIC8vIGZvciBlYWNoIHNhZGRsZSwgdGhlIGZpcnN0IGluZGV4IGhlcmUgaXMgdXNlZFxuICAgIC8vIGZvciBkeHx8ZHk8MCwgdGhlIHNlY29uZCBmb3IgZHh8fGR5PjBcbiAgICBDSE9PU0VTQURETEU6IHtcbiAgICAgICAgMTA0OiBbNCwgMV0sXG4gICAgICAgIDIwODogWzIsIDhdLFxuICAgICAgICA3MTM6IFs3LCAxM10sXG4gICAgICAgIDExMTQ6IFsxMSwgMTRdXG4gICAgfSxcblxuICAgIC8vIGFmdGVyIG9uZSBpbmRleCBoYXMgYmVlbiB1c2VkIGZvciBhIHNhZGRsZSwgd2hpY2ggZG8gd2VcbiAgICAvLyBzdWJzdGl0dXRlIHRvIGJlIHVzZWQgdXAgbGF0ZXI/XG4gICAgU0FERExFUkVNQUlOREVSOiB7MTogNCwgMjogOCwgNDogMSwgNzogMTMsIDg6IDIsIDExOiAxNCwgMTM6IDcsIDE0OiAxMX0sXG5cbiAgICAvLyBsZW5ndGggb2YgYSBjb250b3VyLCBhcyBhIG11bHRpcGxlIG9mIHRoZSBwbG90IGFyZWEgZGlhZ29uYWwsIHBlciBsYWJlbFxuICAgIExBQkVMRElTVEFOQ0U6IDIsXG5cbiAgICAvLyBudW1iZXIgb2YgY29udG91ciBsZXZlbHMgYWZ0ZXIgd2hpY2ggd2Ugc3RhcnQgaW5jcmVhc2luZyB0aGUgbnVtYmVyIG9mXG4gICAgLy8gbGFiZWxzIHdlIGRyYXcuIE1hbnkgY29udG91cnMgbWVhbnMgdGhleSB3aWxsIGdlbmVyYWxseSBiZSBjbG9zZVxuICAgIC8vIHRvZ2V0aGVyLCBzbyBpdCB3aWxsIGJlIGhhcmRlciB0byBmb2xsb3cgYSBsb25nIHdheSB0byBmaW5kIGEgbGFiZWxcbiAgICBMQUJFTElOQ1JFQVNFOiAxMCxcblxuICAgIC8vIG1pbmltdW0gbGVuZ3RoIG9mIGEgY29udG91ciBsaW5lLCBhcyBhIG11bHRpcGxlIG9mIHRoZSBsYWJlbCBsZW5ndGgsXG4gICAgLy8gYXQgd2hpY2ggd2UgZHJhdyAqYW55KiBsYWJlbHNcbiAgICBMQUJFTE1JTjogMyxcblxuICAgIC8vIG1heCBudW1iZXIgb2YgbGFiZWxzIHRvIGRyYXcgb24gYSBzaW5nbGUgY29udG91ciBwYXRoLCBubyBtYXR0ZXIgaG93IGxvbmdcbiAgICBMQUJFTE1BWDogMTAsXG5cbiAgICAvLyBjb25zdGFudHMgZm9yIHRoZSBsYWJlbCBwb3NpdGlvbiBjb3N0IGZ1bmN0aW9uXG4gICAgTEFCRUxPUFRJTUlaRVI6IHtcbiAgICAgICAgLy8gd2VpZ2h0IGdpdmVuIHRvIGVkZ2UgcHJveGltaXR5XG4gICAgICAgIEVER0VDT1NUOiAxLFxuICAgICAgICAvLyB3ZWlnaHQgZ2l2ZW4gdG8gdGhlIGFuZ2xlIG9mZiBob3Jpem9udGFsXG4gICAgICAgIEFOR0xFQ09TVDogMSxcbiAgICAgICAgLy8gd2VpZ2h0IGdpdmVuIHRvIGRpc3RhbmNlIGZyb20gYWxyZWFkeS1wbGFjZWQgbGFiZWxzXG4gICAgICAgIE5FSUdIQk9SQ09TVDogNSxcbiAgICAgICAgLy8gY29zdCBtdWx0aXBsaWVyIGZvciBsYWJlbHMgb24gdGhlIHNhbWUgbGV2ZWxcbiAgICAgICAgU0FNRUxFVkVMRkFDVE9SOiAxMCxcbiAgICAgICAgLy8gbWluaW11bSBkaXN0YW5jZSAoYXMgYSBtdWx0aXBsZSBvZiB0aGUgbGFiZWwgbGVuZ3RoKVxuICAgICAgICAvLyBmb3IgbGFiZWxzIG9uIHRoZSBzYW1lIGxldmVsXG4gICAgICAgIFNBTUVMRVZFTERJU1RBTkNFOiA1LFxuICAgICAgICAvLyBtYXhpbXVtIGNvc3QgYmVmb3JlIHdlIHdvbid0IGV2ZW4gcGxhY2UgdGhlIGxhYmVsXG4gICAgICAgIE1BWENPU1Q6IDEwMCxcbiAgICAgICAgLy8gbnVtYmVyIG9mIGV2ZW5seSBzcGFjZWQgcG9pbnRzIHRvIGxvb2sgYXQgaW4gdGhlIGZpcnN0XG4gICAgICAgIC8vIGl0ZXJhdGlvbiBvZiB0aGUgc2VhcmNoXG4gICAgICAgIElOSVRJQUxTRUFSQ0hQT0lOVFM6IDEwLFxuICAgICAgICAvLyBudW1iZXIgb2YgYmluYXJ5IHNlYXJjaCBpdGVyYXRpb25zIGFmdGVyIHRoZSBpbml0aWFsIHdpZGUgc2VhcmNoXG4gICAgICAgIElURVJBVElPTlM6IDVcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIGhhbmRsZUxhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuL2xhYmVsX2RlZmF1bHRzJyk7XG5cbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBhZGRPcGFjaXR5ID0gQ29sb3IuYWRkT3BhY2l0eTtcbnZhciBvcGFjaXR5ID0gQ29sb3Iub3BhY2l0eTtcblxudmFyIGZpbHRlck9wcyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9maWx0ZXJfb3BzJyk7XG52YXIgQ09OU1RSQUlOVF9SRURVQ1RJT04gPSBmaWx0ZXJPcHMuQ09OU1RSQUlOVF9SRURVQ1RJT047XG52YXIgQ09NUEFSSVNPTl9PUFMyID0gZmlsdGVyT3BzLkNPTVBBUklTT05fT1BTMjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCBkZWZhdWx0Q29sb3IsIG9wdHMpIHtcbiAgICB2YXIgY29udG91cnMgPSB0cmFjZU91dC5jb250b3VycztcbiAgICB2YXIgc2hvd0xpbmVzLCBsaW5lQ29sb3IsIGZpbGxDb2xvcjtcblxuICAgIHZhciBvcGVyYXRpb24gPSBjb2VyY2UoJ2NvbnRvdXJzLm9wZXJhdGlvbicpO1xuICAgIGNvbnRvdXJzLl9vcGVyYXRpb24gPSBDT05TVFJBSU5UX1JFRFVDVElPTltvcGVyYXRpb25dO1xuXG4gICAgaGFuZGxlQ29uc3RyYWludFZhbHVlRGVmYXVsdHMoY29lcmNlLCBjb250b3Vycyk7XG5cbiAgICBpZihvcGVyYXRpb24gPT09ICc9Jykge1xuICAgICAgICBzaG93TGluZXMgPSBjb250b3Vycy5zaG93bGluZXMgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2hvd0xpbmVzID0gY29lcmNlKCdjb250b3Vycy5zaG93bGluZXMnKTtcbiAgICAgICAgZmlsbENvbG9yID0gY29lcmNlKCdmaWxsY29sb3InLCBhZGRPcGFjaXR5KFxuICAgICAgICAgICAgKHRyYWNlSW4ubGluZSB8fCB7fSkuY29sb3IgfHwgZGVmYXVsdENvbG9yLCAwLjVcbiAgICAgICAgKSk7XG4gICAgfVxuXG4gICAgaWYoc2hvd0xpbmVzKSB7XG4gICAgICAgIHZhciBsaW5lRGZsdENvbG9yID0gZmlsbENvbG9yICYmIG9wYWNpdHkoZmlsbENvbG9yKSA/XG4gICAgICAgICAgICBhZGRPcGFjaXR5KHRyYWNlT3V0LmZpbGxjb2xvciwgMSkgOlxuICAgICAgICAgICAgZGVmYXVsdENvbG9yO1xuICAgICAgICBsaW5lQ29sb3IgPSBjb2VyY2UoJ2xpbmUuY29sb3InLCBsaW5lRGZsdENvbG9yKTtcbiAgICAgICAgY29lcmNlKCdsaW5lLndpZHRoJywgMik7XG4gICAgICAgIGNvZXJjZSgnbGluZS5kYXNoJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdsaW5lLnNtb290aGluZycpO1xuXG4gICAgaGFuZGxlTGFiZWxEZWZhdWx0cyhjb2VyY2UsIGxheW91dCwgbGluZUNvbG9yLCBvcHRzKTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUNvbnN0cmFpbnRWYWx1ZURlZmF1bHRzKGNvZXJjZSwgY29udG91cnMpIHtcbiAgICB2YXIgenZhbHVlO1xuXG4gICAgaWYoQ09NUEFSSVNPTl9PUFMyLmluZGV4T2YoY29udG91cnMub3BlcmF0aW9uKSA9PT0gLTEpIHtcbiAgICAgICAgLy8gUmVxdWlyZXMgYW4gYXJyYXkgb2YgdHdvIG51bWJlcnM6XG4gICAgICAgIGNvZXJjZSgnY29udG91cnMudmFsdWUnLCBbMCwgMV0pO1xuXG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGNvbnRvdXJzLnZhbHVlKSkge1xuICAgICAgICAgICAgaWYoaXNOdW1lcmljKGNvbnRvdXJzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHp2YWx1ZSA9IHBhcnNlRmxvYXQoY29udG91cnMudmFsdWUpO1xuICAgICAgICAgICAgICAgIGNvbnRvdXJzLnZhbHVlID0gW3p2YWx1ZSwgenZhbHVlICsgMV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihjb250b3Vycy52YWx1ZS5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgICBjb250b3Vycy52YWx1ZSA9IGNvbnRvdXJzLnZhbHVlLnNsaWNlKDIpO1xuICAgICAgICB9IGVsc2UgaWYoY29udG91cnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBjb250b3Vycy52YWx1ZSA9IFswLCAxXTtcbiAgICAgICAgfSBlbHNlIGlmKGNvbnRvdXJzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHp2YWx1ZSA9IHBhcnNlRmxvYXQoY29udG91cnMudmFsdWVbMF0pO1xuICAgICAgICAgICAgY29udG91cnMudmFsdWUgPSBbenZhbHVlLCB6dmFsdWUgKyAxXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRvdXJzLnZhbHVlID0gW1xuICAgICAgICAgICAgICAgIHBhcnNlRmxvYXQoY29udG91cnMudmFsdWVbMF0pLFxuICAgICAgICAgICAgICAgIHBhcnNlRmxvYXQoY29udG91cnMudmFsdWVbMV0pXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmVxdWlyZXMgYSBzaW5nbGUgc2NhbGFyOlxuICAgICAgICBjb2VyY2UoJ2NvbnRvdXJzLnZhbHVlJywgMCk7XG5cbiAgICAgICAgaWYoIWlzTnVtZXJpYyhjb250b3Vycy52YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY29udG91cnMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgY29udG91cnMudmFsdWUgPSBwYXJzZUZsb2F0KGNvbnRvdXJzLnZhbHVlWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udG91cnMudmFsdWUgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZmlsdGVyT3BzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2ZpbHRlcl9vcHMnKTtcbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG4vLyBUaGlzIHN5bnRheCBjb25mb3JtcyB0byB0aGUgZXhpc3RpbmcgZmlsdGVyIHRyYW5zZm9ybSBzeW50YXgsIGJ1dCB3ZSBkb24ndCBjYXJlXG4vLyBhYm91dCBvcGVuIHZzLiBjbG9zZWQgaW50ZXJ2YWxzIGZvciBzaW1wbHkgZHJhd2luZyBjb250b3VycyBjb25zdHJhaW50czpcbm1vZHVsZS5leHBvcnRzID0ge1xuICAgICdbXSc6IG1ha2VSYW5nZVNldHRpbmdzKCdbXScpLFxuICAgICddWyc6IG1ha2VSYW5nZVNldHRpbmdzKCddWycpLFxuICAgICc+JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPicpLFxuICAgICc8JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPCcpLFxuICAgICc9JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPScpXG59O1xuXG4vLyBUaGlzIGRvZXMgbm90IGluIGFueSB3YXkgc2hhcGUgb3IgZm9ybSBzdXBwb3J0IGNhbGVuZGFycy4gSXQncyBhZGFwdGVkIGZyb21cbi8vIHRyYW5zZm9ybXMvZmlsdGVyLmpzLlxuZnVuY3Rpb24gY29lcmNlVmFsdWUob3BlcmF0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBoYXNBcnJheVZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG5cbiAgICB2YXIgY29lcmNlZFZhbHVlO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpc051bWVyaWModmFsdWUpID8gKCt2YWx1ZSkgOiBudWxsO1xuICAgIH1cblxuICAgIGlmKGZpbHRlck9wcy5DT01QQVJJU09OX09QUzIuaW5kZXhPZihvcGVyYXRpb24pICE9PSAtMSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID8gY29lcmNlKHZhbHVlWzBdKSA6IGNvZXJjZSh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmKGZpbHRlck9wcy5JTlRFUlZBTF9PUFMuaW5kZXhPZihvcGVyYXRpb24pICE9PSAtMSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID9cbiAgICAgICAgICAgIFtjb2VyY2UodmFsdWVbMF0pLCBjb2VyY2UodmFsdWVbMV0pXSA6XG4gICAgICAgICAgICBbY29lcmNlKHZhbHVlKSwgY29lcmNlKHZhbHVlKV07XG4gICAgfSBlbHNlIGlmKGZpbHRlck9wcy5TRVRfT1BTLmluZGV4T2Yob3BlcmF0aW9uKSAhPT0gLTEpIHtcbiAgICAgICAgY29lcmNlZFZhbHVlID0gaGFzQXJyYXlWYWx1ZSA/IHZhbHVlLm1hcChjb2VyY2UpIDogW2NvZXJjZSh2YWx1ZSldO1xuICAgIH1cblxuICAgIHJldHVybiBjb2VyY2VkVmFsdWU7XG59XG5cbi8vIFJldHVybnMgYSBwYXJhYm9sYSBzY2FsZWQgc28gdGhhdCB0aGUgbWluL21heCBpcyBlaXRoZXIgKy8tIDEgYW5kIHplcm8gYXQgdGhlIHR3byB2YWx1ZXNcbi8vIHByb3ZpZGVkLiBUaGUgZGF0YSBpcyBtYXBwZWQgYnkgdGhpcyBmdW5jdGlvbiB3aGVuIGNvbnN0cnVjdGluZyBpbnRlcnZhbHMgc28gdGhhdCBpdCdzXG4vLyB2ZXJ5IGVhc3kgdG8gY29uc3RydWN0IGNvbnRvdXJzIGFzIG5vcm1hbC5cbmZ1bmN0aW9uIG1ha2VSYW5nZVNldHRpbmdzKG9wZXJhdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB2YWx1ZSA9IGNvZXJjZVZhbHVlKG9wZXJhdGlvbiwgdmFsdWUpO1xuXG4gICAgICAgIC8vIEVuc3VyZSBwcm9wZXIgb3JkZXJpbmc6XG4gICAgICAgIHZhciBtaW4gPSBNYXRoLm1pbih2YWx1ZVswXSwgdmFsdWVbMV0pO1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXgodmFsdWVbMF0sIHZhbHVlWzFdKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IG1pbixcbiAgICAgICAgICAgIGVuZDogbWF4LFxuICAgICAgICAgICAgc2l6ZTogbWF4IC0gbWluXG4gICAgICAgIH07XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUluZXF1YWxpdHlTZXR0aW5ncyhvcGVyYXRpb24pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgdmFsdWUgPSBjb2VyY2VWYWx1ZShvcGVyYXRpb24sIHZhbHVlKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IHZhbHVlLFxuICAgICAgICAgICAgZW5kOiBJbmZpbml0eSxcbiAgICAgICAgICAgIHNpemU6IEluZmluaXR5XG4gICAgICAgIH07XG4gICAgfTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDb250b3VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgY29lcmNlMikge1xuICAgIHZhciBjb250b3VyU3RhcnQgPSBjb2VyY2UyKCdjb250b3Vycy5zdGFydCcpO1xuICAgIHZhciBjb250b3VyRW5kID0gY29lcmNlMignY29udG91cnMuZW5kJyk7XG4gICAgdmFyIG1pc3NpbmdFbmQgPSAoY29udG91clN0YXJ0ID09PSBmYWxzZSkgfHwgKGNvbnRvdXJFbmQgPT09IGZhbHNlKTtcblxuICAgIC8vIG5vcm1hbGx5IHdlIG9ubHkgbmVlZCBzaXplIGlmIGF1dG9jb250b3VyIGlzIG9mZi4gQnV0IGNvbnRvdXIuY2FsY1xuICAgIC8vIHB1c2hlcyBpdHMgY2FsY3VsYXRlZCBjb250b3VyIHNpemUgYmFjayB0byB0aGUgaW5wdXQgdHJhY2UsIHNvIGZvclxuICAgIC8vIHRoaW5ncyBsaWtlIHJlc3R5bGUgdGhhdCBjYW4gY2FsbCBzdXBwbHlEZWZhdWx0cyB3aXRob3V0IGNhbGNcbiAgICAvLyBhZnRlciB0aGUgaW5pdGlhbCBkcmF3LCB3ZSBjYW4ganVzdCByZXVzZSB0aGUgcHJldmlvdXMgY2FsY3VsYXRpb25cbiAgICB2YXIgY29udG91clNpemUgPSBjb2VyY2UoJ2NvbnRvdXJzLnNpemUnKTtcbiAgICB2YXIgYXV0b0NvbnRvdXI7XG5cbiAgICBpZihtaXNzaW5nRW5kKSBhdXRvQ29udG91ciA9IHRyYWNlT3V0LmF1dG9jb250b3VyID0gdHJ1ZTtcbiAgICBlbHNlIGF1dG9Db250b3VyID0gY29lcmNlKCdhdXRvY29udG91cicsIGZhbHNlKTtcblxuICAgIGlmKGF1dG9Db250b3VyIHx8ICFjb250b3VyU2l6ZSkgY29lcmNlKCduY29udG91cnMnKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLy8gVGhlIGNvbnRvdXIgZXh0cmFjdGlvbiBpcyBncmVhdCwgZXhjZXB0IGl0IHRvdGFsbHkgZmFpbHMgZm9yIGNvbnN0cmFpbnRzIGJlY2F1c2Ugd2Vcbi8vIG5lZWQgd2VpcmQgcmFuZ2UgbG9vcHMgYW5kIGZsaXBwZWQgY29udG91cnMgaW5zdGVhZCBvZiB0aGUgdXN1YWwgZm9ybWF0LiBUaGlzIGZ1bmN0aW9uXG4vLyBkb2VzIHNvbWUgd2VpcmQgbWFuaXB1bGF0aW9uIG9mIHRoZSBleHRyYWN0ZWQgcGF0aGluZm8gZGF0YSBzdWNoIHRoYXQgaXQgbWFnaWNhbGx5XG4vLyBkcmF3cyBjb250b3VycyBjb3JyZWN0bHkgKmFzKiBjb25zdHJhaW50cy5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ocGF0aGluZm8sIG9wZXJhdGlvbikge1xuICAgIHZhciBpLCBwaTAsIHBpMTtcblxuICAgIHZhciBvcDAgPSBmdW5jdGlvbihhcnIpIHsgcmV0dXJuIGFyci5yZXZlcnNlKCk7IH07XG4gICAgdmFyIG9wMSA9IGZ1bmN0aW9uKGFycikgeyByZXR1cm4gYXJyOyB9O1xuXG4gICAgc3dpdGNoKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlICc9JzpcbiAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgICAgICByZXR1cm4gcGF0aGluZm87XG4gICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgaWYocGF0aGluZm8ubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ0NvbnRvdXIgZGF0YSBpbnZhbGlkIGZvciB0aGUgc3BlY2lmaWVkIGluZXF1YWxpdHkgb3BlcmF0aW9uLicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJbiB0aGlzIGNhc2UgdGhlcmUgc2hvdWxkIGJlIGV4YWN0bHkgdHdvIGNvbnRvdXIgbGV2ZWxzIGluIHBhdGhpbmZvLiBXZVxuICAgICAgICAgICAgLy8gc2ltcGx5IGNvbmNhdGVuYXRlIHRoZSBpbmZvIGludG8gb25lIHBhdGhpbmZvIGFuZCBmbGlwIGFsbCBvZiB0aGUgZGF0YVxuICAgICAgICAgICAgLy8gaW4gb25lLiBUaGlzIHdpbGwgZHJhdyB0aGUgY29udG91ciBhcyBjbG9zZWQuXG4gICAgICAgICAgICBwaTAgPSBwYXRoaW5mb1swXTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkwLmVkZ2VwYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHBpMC5lZGdlcGF0aHNbaV0gPSBvcDAocGkwLmVkZ2VwYXRoc1tpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHBpMC5wYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHBpMC5wYXRoc1tpXSA9IG9wMChwaTAucGF0aHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBhdGhpbmZvO1xuICAgICAgICBjYXNlICddWyc6XG4gICAgICAgICAgICB2YXIgdG1wID0gb3AwO1xuICAgICAgICAgICAgb3AwID0gb3AxO1xuICAgICAgICAgICAgb3AxID0gdG1wO1xuICAgICAgICAgICAgLy8gSXQncyBhIG5pY2UgcnVsZSwgZXhjZXB0IHRoaXMgZGVmaW5pdGVseSAqaXMqIHdoYXQncyBpbnRlbmRlZCBoZXJlLlxuICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGU6IG5vLWZhbGx0aHJvdWdoICovXG4gICAgICAgIGNhc2UgJ1tdJzpcbiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGU6IG5vLWZhbGx0aHJvdWdoICovXG4gICAgICAgICAgICBpZihwYXRoaW5mby5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICBMaWIud2FybignQ29udG91ciBkYXRhIGludmFsaWQgZm9yIHRoZSBzcGVjaWZpZWQgaW5lcXVhbGl0eSByYW5nZSBvcGVyYXRpb24uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSB0aGVyZSBzaG91bGQgYmUgZXhhY3RseSB0d28gY29udG91ciBsZXZlbHMgaW4gcGF0aGluZm8uIFdlXG4gICAgICAgICAgICAvLyBzaW1wbHkgY29uY2F0ZW5hdGUgdGhlIGluZm8gaW50byBvbmUgcGF0aGluZm8gYW5kIGZsaXAgYWxsIG9mIHRoZSBkYXRhXG4gICAgICAgICAgICAvLyBpbiBvbmUuIFRoaXMgd2lsbCBkcmF3IHRoZSBjb250b3VyIGFzIGNsb3NlZC5cbiAgICAgICAgICAgIHBpMCA9IGNvcHlQYXRoaW5mbyhwYXRoaW5mb1swXSk7XG4gICAgICAgICAgICBwaTEgPSBjb3B5UGF0aGluZm8ocGF0aGluZm9bMV0pO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwaTAuZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGkwLmVkZ2VwYXRoc1tpXSA9IG9wMChwaTAuZWRnZXBhdGhzW2ldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkwLnBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGkwLnBhdGhzW2ldID0gb3AwKHBpMC5wYXRoc1tpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdoaWxlKHBpMS5lZGdlcGF0aHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcGkwLmVkZ2VwYXRocy5wdXNoKG9wMShwaTEuZWRnZXBhdGhzLnNoaWZ0KCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlKHBpMS5wYXRocy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBwaTAucGF0aHMucHVzaChvcDEocGkxLnBhdGhzLnNoaWZ0KCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbcGkwXTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb3B5UGF0aGluZm8ocGkpIHtcbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIHBpLCB7XG4gICAgICAgIGVkZ2VwYXRoczogTGliLmV4dGVuZERlZXAoW10sIHBpLmVkZ2VwYXRocyksXG4gICAgICAgIHBhdGhzOiBMaWIuZXh0ZW5kRGVlcChbXSwgcGkucGF0aHMpXG4gICAgfSk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlWFlaRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9oZWF0bWFwL3h5el9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyA9IHJlcXVpcmUoJy4vY29uc3RyYWludF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnRvdXJzRGVmYXVsdHMgPSByZXF1aXJlKCcuL2NvbnRvdXJzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4vc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICB2YXIgaXNDb25zdHJhaW50ID0gKGNvZXJjZSgnY29udG91cnMudHlwZScpID09PSAnY29uc3RyYWludCcpO1xuICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnLCBMaWIuaXNBcnJheTFEKHRyYWNlT3V0LnopKTtcblxuICAgIGlmKGlzQ29uc3RyYWludCkge1xuICAgICAgICBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCBkZWZhdWx0Q29sb3IpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaGFuZGxlQ29udG91cnNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBjb2VyY2UyKTtcbiAgICAgICAgaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBjb25zdHJhaW50TWFwcGluZyA9IHJlcXVpcmUoJy4vY29uc3RyYWludF9tYXBwaW5nJyk7XG52YXIgZW5kUGx1cyA9IHJlcXVpcmUoJy4vZW5kX3BsdXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlbXB0eVBhdGhpbmZvKGNvbnRvdXJzLCBwbG90aW5mbywgY2QwKSB7XG4gICAgdmFyIGNvbnRvdXJzRmluYWwgPSAoY29udG91cnMudHlwZSA9PT0gJ2NvbnN0cmFpbnQnKSA/XG4gICAgICAgIGNvbnN0cmFpbnRNYXBwaW5nW2NvbnRvdXJzLl9vcGVyYXRpb25dKGNvbnRvdXJzLnZhbHVlKSA6XG4gICAgICAgIGNvbnRvdXJzO1xuXG4gICAgdmFyIGNzID0gY29udG91cnNGaW5hbC5zaXplO1xuICAgIHZhciBwYXRoaW5mbyA9IFtdO1xuICAgIHZhciBlbmQgPSBlbmRQbHVzKGNvbnRvdXJzRmluYWwpO1xuXG4gICAgdmFyIGNhcnBldCA9IGNkMC50cmFjZS5fY2FycGV0VHJhY2U7XG5cbiAgICB2YXIgYmFzZVBhdGhpbmZvID0gY2FycGV0ID8ge1xuICAgICAgICAvLyBzdG9yZSBheGVzIHNvIHdlIGNhbiBjb252ZXJ0IHRvIHB4XG4gICAgICAgIHhheGlzOiBjYXJwZXQuYWF4aXMsXG4gICAgICAgIHlheGlzOiBjYXJwZXQuYmF4aXMsXG4gICAgICAgIC8vIGZ1bGwgZGF0YSBhcnJheXMgdG8gdXNlIGZvciBpbnRlcnBvbGF0aW9uXG4gICAgICAgIHg6IGNkMC5hLFxuICAgICAgICB5OiBjZDAuYlxuICAgIH0gOiB7XG4gICAgICAgIHhheGlzOiBwbG90aW5mby54YXhpcyxcbiAgICAgICAgeWF4aXM6IHBsb3RpbmZvLnlheGlzLFxuICAgICAgICB4OiBjZDAueCxcbiAgICAgICAgeTogY2QwLnlcbiAgICB9O1xuXG4gICAgZm9yKHZhciBjaSA9IGNvbnRvdXJzRmluYWwuc3RhcnQ7IGNpIDwgZW5kOyBjaSArPSBjcykge1xuICAgICAgICBwYXRoaW5mby5wdXNoKExpYi5leHRlbmRGbGF0KHtcbiAgICAgICAgICAgIGxldmVsOiBjaSxcbiAgICAgICAgICAgIC8vIGFsbCB0aGUgY2VsbHMgd2l0aCBub250cml2aWFsIG1hcmNoaW5nIGluZGV4XG4gICAgICAgICAgICBjcm9zc2luZ3M6IHt9LFxuICAgICAgICAgICAgLy8gc3RhcnRpbmcgcG9pbnRzIG9uIHRoZSBlZGdlcyBvZiB0aGUgbGF0dGljZSBmb3IgZWFjaCBjb250b3VyXG4gICAgICAgICAgICBzdGFydHM6IFtdLFxuICAgICAgICAgICAgLy8gYWxsIHVuY2xvc2VkIHBhdGhzIChtYXkgaGF2ZSBsZXNzIGl0ZW1zIHRoYW4gc3RhcnRzLFxuICAgICAgICAgICAgLy8gaWYgYSBwYXRoIGlzIGNsb3NlZCBieSByb3VuZGluZylcbiAgICAgICAgICAgIGVkZ2VwYXRoczogW10sXG4gICAgICAgICAgICAvLyBhbGwgY2xvc2VkIHBhdGhzXG4gICAgICAgICAgICBwYXRoczogW10sXG4gICAgICAgICAgICB6OiBjZDAueixcbiAgICAgICAgICAgIHNtb290aGluZzogY2QwLnRyYWNlLmxpbmUuc21vb3RoaW5nXG4gICAgICAgIH0sIGJhc2VQYXRoaW5mbykpO1xuXG4gICAgICAgIGlmKHBhdGhpbmZvLmxlbmd0aCA+IDEwMDApIHtcbiAgICAgICAgICAgIExpYi53YXJuKCdUb28gbWFueSBjb250b3VycywgY2xpcHBpbmcgYXQgMTAwMCcsIGNvbnRvdXJzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXRoaW5mbztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLypcbiAqIHRpbnkgaGVscGVyIHRvIG1vdmUgdGhlIGVuZCBvZiB0aGUgY29udG91cnMgYSBsaXR0bGUgdG8gcHJldmVudFxuICogbG9zaW5nIHRoZSBsYXN0IGNvbnRvdXIgdG8gcm91bmRpbmcgZXJyb3JzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZW5kUGx1cyhjb250b3Vycykge1xuICAgIHJldHVybiBjb250b3Vycy5lbmQgKyBjb250b3Vycy5zaXplIC8gMWU2O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmluZEFsbFBhdGhzKHBhdGhpbmZvLCB4dG9sLCB5dG9sKSB7XG4gICAgdmFyIGNudCxcbiAgICAgICAgc3RhcnRMb2MsXG4gICAgICAgIGksXG4gICAgICAgIHBpLFxuICAgICAgICBqO1xuXG4gICAgLy8gRGVmYXVsdCBqdXN0IHBhc3NlcyB0aGVzZSB2YWx1ZXMgdGhyb3VnaCBhcyB0aGV5IHdlcmUgYmVmb3JlOlxuICAgIHh0b2wgPSB4dG9sIHx8IDAuMDE7XG4gICAgeXRvbCA9IHl0b2wgfHwgMC4wMTtcblxuICAgIGZvcihpID0gMDsgaSA8IHBhdGhpbmZvLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBpID0gcGF0aGluZm9baV07XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgcGkuc3RhcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBzdGFydExvYyA9IHBpLnN0YXJ0c1tqXTtcbiAgICAgICAgICAgIG1ha2VQYXRoKHBpLCBzdGFydExvYywgJ2VkZ2UnLCB4dG9sLCB5dG9sKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNudCA9IDA7XG4gICAgICAgIHdoaWxlKE9iamVjdC5rZXlzKHBpLmNyb3NzaW5ncykubGVuZ3RoICYmIGNudCA8IDEwMDAwKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgIHN0YXJ0TG9jID0gT2JqZWN0LmtleXMocGkuY3Jvc3NpbmdzKVswXS5zcGxpdCgnLCcpLm1hcChOdW1iZXIpO1xuICAgICAgICAgICAgbWFrZVBhdGgocGksIHN0YXJ0TG9jLCB1bmRlZmluZWQsIHh0b2wsIHl0b2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGNudCA9PT0gMTAwMDApIExpYi5sb2coJ0luZmluaXRlIGxvb3AgaW4gY29udG91cj8nKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBlcXVhbFB0cyhwdDEsIHB0MiwgeHRvbCwgeXRvbCkge1xuICAgIHJldHVybiBNYXRoLmFicyhwdDFbMF0gLSBwdDJbMF0pIDwgeHRvbCAmJlxuICAgICAgICAgICBNYXRoLmFicyhwdDFbMV0gLSBwdDJbMV0pIDwgeXRvbDtcbn1cblxuLy8gZGlzdGFuY2UgaW4gaW5kZXggdW5pdHMgLSB1c2VzIHRoZSAzcmQgYW5kIDR0aCBpdGVtcyBpbiBwb2ludHNcbmZ1bmN0aW9uIHB0RGlzdChwdDEsIHB0Mikge1xuICAgIHZhciBkeCA9IHB0MVsyXSAtIHB0MlsyXSxcbiAgICAgICAgZHkgPSBwdDFbM10gLSBwdDJbM107XG4gICAgcmV0dXJuIE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VQYXRoKHBpLCBsb2MsIGVkZ2VmbGFnLCB4dG9sLCB5dG9sKSB7XG4gICAgdmFyIHN0YXJ0TG9jU3RyID0gbG9jLmpvaW4oJywnKTtcbiAgICB2YXIgbG9jU3RyID0gc3RhcnRMb2NTdHI7XG4gICAgdmFyIG1pID0gcGkuY3Jvc3NpbmdzW2xvY1N0cl07XG4gICAgdmFyIG1hcmNoU3RlcCA9IHN0YXJ0U3RlcChtaSwgZWRnZWZsYWcsIGxvYyk7XG4gICAgLy8gc3RhcnQgYnkgZ29pbmcgYmFja3dhcmQgYSBoYWxmIHN0ZXAgYW5kIGZpbmRpbmcgdGhlIGNyb3NzaW5nIHBvaW50XG4gICAgdmFyIHB0cyA9IFtnZXRJbnRlcnBQeChwaSwgbG9jLCBbLW1hcmNoU3RlcFswXSwgLW1hcmNoU3RlcFsxXV0pXTtcbiAgICB2YXIgc3RhcnRTdGVwU3RyID0gbWFyY2hTdGVwLmpvaW4oJywnKTtcbiAgICB2YXIgbSA9IHBpLnoubGVuZ3RoO1xuICAgIHZhciBuID0gcGkuelswXS5sZW5ndGg7XG4gICAgdmFyIGNudDtcblxuICAgIC8vIG5vdyBmb2xsb3cgdGhlIHBhdGhcbiAgICBmb3IoY250ID0gMDsgY250IDwgMTAwMDA7IGNudCsrKSB7IC8vIGp1c3QgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHNcbiAgICAgICAgaWYobWkgPiAyMCkge1xuICAgICAgICAgICAgbWkgPSBjb25zdGFudHMuQ0hPT1NFU0FERExFW21pXVsobWFyY2hTdGVwWzBdIHx8IG1hcmNoU3RlcFsxXSkgPCAwID8gMCA6IDFdO1xuICAgICAgICAgICAgcGkuY3Jvc3NpbmdzW2xvY1N0cl0gPSBjb25zdGFudHMuU0FERExFUkVNQUlOREVSW21pXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSBwaS5jcm9zc2luZ3NbbG9jU3RyXTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1hcmNoU3RlcCA9IGNvbnN0YW50cy5ORVdERUxUQVttaV07XG4gICAgICAgIGlmKCFtYXJjaFN0ZXApIHtcbiAgICAgICAgICAgIExpYi5sb2coJ0ZvdW5kIGJhZCBtYXJjaGluZyBpbmRleDonLCBtaSwgbG9jLCBwaS5sZXZlbCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpbmQgdGhlIGNyb3NzaW5nIGEgaGFsZiBzdGVwIGZvcndhcmQsIGFuZCB0aGVuIHRha2UgdGhlIGZ1bGwgc3RlcFxuICAgICAgICBwdHMucHVzaChnZXRJbnRlcnBQeChwaSwgbG9jLCBtYXJjaFN0ZXApKTtcbiAgICAgICAgbG9jWzBdICs9IG1hcmNoU3RlcFswXTtcbiAgICAgICAgbG9jWzFdICs9IG1hcmNoU3RlcFsxXTtcblxuICAgICAgICAvLyBkb24ndCBpbmNsdWRlIHRoZSBzYW1lIHBvaW50IG11bHRpcGxlIHRpbWVzXG4gICAgICAgIGlmKGVxdWFsUHRzKHB0c1twdHMubGVuZ3RoIC0gMV0sIHB0c1twdHMubGVuZ3RoIC0gMl0sIHh0b2wsIHl0b2wpKSBwdHMucG9wKCk7XG4gICAgICAgIGxvY1N0ciA9IGxvYy5qb2luKCcsJyk7XG5cbiAgICAgICAgdmFyIGF0RWRnZSA9IChtYXJjaFN0ZXBbMF0gJiYgKGxvY1swXSA8IDAgfHwgbG9jWzBdID4gbiAtIDIpKSB8fFxuICAgICAgICAgICAgICAgIChtYXJjaFN0ZXBbMV0gJiYgKGxvY1sxXSA8IDAgfHwgbG9jWzFdID4gbSAtIDIpKSxcbiAgICAgICAgICAgIGNsb3NlZExvb3AgPSAobG9jU3RyID09PSBzdGFydExvY1N0cikgJiYgKG1hcmNoU3RlcC5qb2luKCcsJykgPT09IHN0YXJ0U3RlcFN0cik7XG5cbiAgICAgICAgLy8gaGF2ZSB3ZSBjb21wbGV0ZWQgYSBsb29wLCBvciByZWFjaGVkIGFuIGVkZ2U/XG4gICAgICAgIGlmKChjbG9zZWRMb29wKSB8fCAoZWRnZWZsYWcgJiYgYXRFZGdlKSkgYnJlYWs7XG5cbiAgICAgICAgbWkgPSBwaS5jcm9zc2luZ3NbbG9jU3RyXTtcbiAgICB9XG5cbiAgICBpZihjbnQgPT09IDEwMDAwKSB7XG4gICAgICAgIExpYi5sb2coJ0luZmluaXRlIGxvb3AgaW4gY29udG91cj8nKTtcbiAgICB9XG4gICAgdmFyIGNsb3NlZHBhdGggPSBlcXVhbFB0cyhwdHNbMF0sIHB0c1twdHMubGVuZ3RoIC0gMV0sIHh0b2wsIHl0b2wpO1xuICAgIHZhciB0b3RhbGRpc3QgPSAwO1xuICAgIHZhciBkaXN0VGhyZXNob2xkRmFjdG9yID0gMC4yICogcGkuc21vb3RoaW5nO1xuICAgIHZhciBhbGxkaXN0cyA9IFtdO1xuICAgIHZhciBjcm9wc3RhcnQgPSAwO1xuICAgIHZhciBkaXN0Z3JvdXAsIGNudDIsIGNudDMsIG5ld3B0LCBwdGNudCwgcHRhdmcsIHRoaXNkaXN0LFxuICAgICAgICBpLCBqLCBlZGdlcGF0aGksIGVkZ2VwYXRoajtcblxuICAgIC8qXG4gICAgICogQ2hlY2sgZm9yIHBvaW50cyB0aGF0IGFyZSB0b28gY2xvc2UgdG9nZXRoZXIgKDwxLzUgdGhlIGF2ZXJhZ2UgZGlzdFxuICAgICAqICppbiBncmlkIGluZGV4IHVuaXRzKiAoaW1wb3J0YW50IGZvciBsb2cgYXhlcyBhbmQgbm9udW5pZm9ybSBncmlkcyksXG4gICAgICogbGVzcyBpZiBsZXNzIHNtb290aGVkKSBhbmQganVzdCB0YWtlIHRoZSBjZW50ZXIgKG9yIGF2ZyBvZiBjZW50ZXIgMikuXG4gICAgICogVGhpcyBjdXRzIGRvd24gb24gZnVubnkgYmVoYXZpb3Igd2hlbiBhIHBvaW50IGlzIHZlcnkgY2xvc2UgdG8gYVxuICAgICAqIGNvbnRvdXIgbGV2ZWwuXG4gICAgICovXG4gICAgZm9yKGNudCA9IDE7IGNudCA8IHB0cy5sZW5ndGg7IGNudCsrKSB7XG4gICAgICAgIHRoaXNkaXN0ID0gcHREaXN0KHB0c1tjbnRdLCBwdHNbY250IC0gMV0pO1xuICAgICAgICB0b3RhbGRpc3QgKz0gdGhpc2Rpc3Q7XG4gICAgICAgIGFsbGRpc3RzLnB1c2godGhpc2Rpc3QpO1xuICAgIH1cblxuICAgIHZhciBkaXN0VGhyZXNob2xkID0gdG90YWxkaXN0IC8gYWxsZGlzdHMubGVuZ3RoICogZGlzdFRocmVzaG9sZEZhY3RvcjtcblxuICAgIGZ1bmN0aW9uIGdldHB0KGkpIHsgcmV0dXJuIHB0c1tpICUgcHRzLmxlbmd0aF07IH1cblxuICAgIGZvcihjbnQgPSBwdHMubGVuZ3RoIC0gMjsgY250ID49IGNyb3BzdGFydDsgY250LS0pIHtcbiAgICAgICAgZGlzdGdyb3VwID0gYWxsZGlzdHNbY250XTtcbiAgICAgICAgaWYoZGlzdGdyb3VwIDwgZGlzdFRocmVzaG9sZCkge1xuICAgICAgICAgICAgY250MyA9IDA7XG4gICAgICAgICAgICBmb3IoY250MiA9IGNudCAtIDE7IGNudDIgPj0gY3JvcHN0YXJ0OyBjbnQyLS0pIHtcbiAgICAgICAgICAgICAgICBpZihkaXN0Z3JvdXAgKyBhbGxkaXN0c1tjbnQyXSA8IGRpc3RUaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGlzdGdyb3VwICs9IGFsbGRpc3RzW2NudDJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBjbG9zZWQgcGF0aCB3aXRoIGNsb3NlIHBvaW50cyB3cmFwcGluZyBhcm91bmQgdGhlIGJvdW5kYXJ5P1xuICAgICAgICAgICAgaWYoY2xvc2VkcGF0aCAmJiBjbnQgPT09IHB0cy5sZW5ndGggLSAyKSB7XG4gICAgICAgICAgICAgICAgZm9yKGNudDMgPSAwOyBjbnQzIDwgY250MjsgY250MysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRpc3Rncm91cCArIGFsbGRpc3RzW2NudDNdIDwgZGlzdFRocmVzaG9sZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGdyb3VwICs9IGFsbGRpc3RzW2NudDNdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHRjbnQgPSBjbnQgLSBjbnQyICsgY250MyArIDE7XG4gICAgICAgICAgICBwdGF2ZyA9IE1hdGguZmxvb3IoKGNudCArIGNudDIgKyBjbnQzICsgMikgLyAyKTtcblxuICAgICAgICAgICAgLy8gZWl0aGVyIGVuZHBvaW50IGluY2x1ZGVkOiBrZWVwIHRoZSBlbmRwb2ludFxuICAgICAgICAgICAgaWYoIWNsb3NlZHBhdGggJiYgY250ID09PSBwdHMubGVuZ3RoIC0gMikgbmV3cHQgPSBwdHNbcHRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgZWxzZSBpZighY2xvc2VkcGF0aCAmJiBjbnQyID09PSAtMSkgbmV3cHQgPSBwdHNbMF07XG5cbiAgICAgICAgICAgIC8vIG9kZCAjIG9mIHBvaW50cyAtIGp1c3QgdGFrZSB0aGUgY2VudHJhbCBvbmVcbiAgICAgICAgICAgIGVsc2UgaWYocHRjbnQgJSAyKSBuZXdwdCA9IGdldHB0KHB0YXZnKTtcblxuICAgICAgICAgICAgLy8gZXZlbiAjIG9mIHB0cyAtIGF2ZXJhZ2UgY2VudHJhbCB0d29cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld3B0ID0gWyhnZXRwdChwdGF2ZylbMF0gKyBnZXRwdChwdGF2ZyArIDEpWzBdKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIChnZXRwdChwdGF2ZylbMV0gKyBnZXRwdChwdGF2ZyArIDEpWzFdKSAvIDJdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwdHMuc3BsaWNlKGNudDIgKyAxLCBjbnQgLSBjbnQyICsgMSwgbmV3cHQpO1xuICAgICAgICAgICAgY250ID0gY250MiArIDE7XG4gICAgICAgICAgICBpZihjbnQzKSBjcm9wc3RhcnQgPSBjbnQzO1xuICAgICAgICAgICAgaWYoY2xvc2VkcGF0aCkge1xuICAgICAgICAgICAgICAgIGlmKGNudCA9PT0gcHRzLmxlbmd0aCAtIDIpIHB0c1tjbnQzXSA9IHB0c1twdHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgZWxzZSBpZihjbnQgPT09IDApIHB0c1twdHMubGVuZ3RoIC0gMV0gPSBwdHNbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHRzLnNwbGljZSgwLCBjcm9wc3RhcnQpO1xuXG4gICAgLy8gZG9uZSB3aXRoIHRoZSBpbmRleCBwYXJ0cyAtIHJlbW92ZSB0aGVtIHNvIHBhdGggZ2VuZXJhdGlvbiB3b3JrcyByaWdodFxuICAgIC8vIGJlY2F1c2UgaXQgZGVwZW5kcyBvbiBvbmx5IGhhdmluZyBbeHB4LCB5cHhdXG4gICAgZm9yKGNudCA9IDA7IGNudCA8IHB0cy5sZW5ndGg7IGNudCsrKSBwdHNbY250XS5sZW5ndGggPSAyO1xuXG4gICAgLy8gZG9uJ3QgcmV0dXJuIHNpbmdsZS1wb2ludCBwYXRocyAoaWUgYWxsIHBvaW50cyB3ZXJlIHRoZSBzYW1lXG4gICAgLy8gc28gdGhleSBnb3QgZGVsZXRlZD8pXG4gICAgaWYocHRzLmxlbmd0aCA8IDIpIHJldHVybjtcbiAgICBlbHNlIGlmKGNsb3NlZHBhdGgpIHtcbiAgICAgICAgcHRzLnBvcCgpO1xuICAgICAgICBwaS5wYXRocy5wdXNoKHB0cyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZighZWRnZWZsYWcpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ1VuY2xvc2VkIGludGVyaW9yIGNvbnRvdXI/JyxcbiAgICAgICAgICAgICAgICBwaS5sZXZlbCwgc3RhcnRMb2NTdHIsIHB0cy5qb2luKCdMJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZWRnZSBwYXRoIC0gZG9lcyBpdCBzdGFydCB3aGVyZSBhbiBleGlzdGluZyBlZGdlIHBhdGggZW5kcywgb3IgdmljZSB2ZXJzYT9cbiAgICAgICAgdmFyIG1lcmdlZCA9IGZhbHNlO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwaS5lZGdlcGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGVkZ2VwYXRoaSA9IHBpLmVkZ2VwYXRoc1tpXTtcbiAgICAgICAgICAgIGlmKCFtZXJnZWQgJiYgZXF1YWxQdHMoZWRnZXBhdGhpWzBdLCBwdHNbcHRzLmxlbmd0aCAtIDFdLCB4dG9sLCB5dG9sKSkge1xuICAgICAgICAgICAgICAgIHB0cy5wb3AoKTtcbiAgICAgICAgICAgICAgICBtZXJnZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgLy8gbm93IGRvZXMgaXQgQUxTTyBtZWV0IHRoZSBlbmQgb2YgYW5vdGhlciAob3IgdGhlIHNhbWUpIHBhdGg/XG4gICAgICAgICAgICAgICAgdmFyIGRvdWJsZW1lcmdlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHBpLmVkZ2VwYXRocy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBlZGdlcGF0aGogPSBwaS5lZGdlcGF0aHNbal07XG4gICAgICAgICAgICAgICAgICAgIGlmKGVxdWFsUHRzKGVkZ2VwYXRoaltlZGdlcGF0aGoubGVuZ3RoIC0gMV0sIHB0c1swXSwgeHRvbCwgeXRvbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvdWJsZW1lcmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdHMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBpLmVkZ2VwYXRocy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihqID09PSBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHBhdGggaXMgbm93IGNsb3NlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpLnBhdGhzLnB1c2gocHRzLmNvbmNhdChlZGdlcGF0aGopKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGogPiBpKSBqLS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGkuZWRnZXBhdGhzW2pdID0gZWRnZXBhdGhqLmNvbmNhdChwdHMsIGVkZ2VwYXRoaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZighZG91YmxlbWVyZ2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHBpLmVkZ2VwYXRoc1tpXSA9IHB0cy5jb25jYXQoZWRnZXBhdGhpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkuZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihtZXJnZWQpIGJyZWFrO1xuICAgICAgICAgICAgZWRnZXBhdGhpID0gcGkuZWRnZXBhdGhzW2ldO1xuICAgICAgICAgICAgaWYoZXF1YWxQdHMoZWRnZXBhdGhpW2VkZ2VwYXRoaS5sZW5ndGggLSAxXSwgcHRzWzBdLCB4dG9sLCB5dG9sKSkge1xuICAgICAgICAgICAgICAgIHB0cy5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIHBpLmVkZ2VwYXRoc1tpXSA9IGVkZ2VwYXRoaS5jb25jYXQocHRzKTtcbiAgICAgICAgICAgICAgICBtZXJnZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW1lcmdlZCkgcGkuZWRnZXBhdGhzLnB1c2gocHRzKTtcbiAgICB9XG59XG5cbi8vIHNwZWNpYWwgZnVuY3Rpb24gdG8gZ2V0IHRoZSBtYXJjaGluZyBzdGVwIG9mIHRoZVxuLy8gZmlyc3QgcG9pbnQgaW4gdGhlIHBhdGggKGxlYWRpbmcgdG8gbG9jKVxuZnVuY3Rpb24gc3RhcnRTdGVwKG1pLCBlZGdlZmxhZywgbG9jKSB7XG4gICAgdmFyIGR4ID0gMCxcbiAgICAgICAgZHkgPSAwO1xuICAgIGlmKG1pID4gMjAgJiYgZWRnZWZsYWcpIHtcbiAgICAgICAgLy8gdGhlc2Ugc2FkZGxlcyBzdGFydCBhdCArLy0geFxuICAgICAgICBpZihtaSA9PT0gMjA4IHx8IG1pID09PSAxMTE0KSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSdyZSBzdGFydGluZyBhdCB0aGUgbGVmdCBzaWRlLCB3ZSBtdXN0IGJlIGdvaW5nIHJpZ2h0XG4gICAgICAgICAgICBkeCA9IGxvY1swXSA9PT0gMCA/IDEgOiAtMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIHN0YXJ0aW5nIGF0IHRoZSBib3R0b20sIHdlIG11c3QgYmUgZ29pbmcgdXBcbiAgICAgICAgICAgIGR5ID0gbG9jWzFdID09PSAwID8gMSA6IC0xO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYoY29uc3RhbnRzLkJPVFRPTVNUQVJULmluZGV4T2YobWkpICE9PSAtMSkgZHkgPSAxO1xuICAgIGVsc2UgaWYoY29uc3RhbnRzLkxFRlRTVEFSVC5pbmRleE9mKG1pKSAhPT0gLTEpIGR4ID0gMTtcbiAgICBlbHNlIGlmKGNvbnN0YW50cy5UT1BTVEFSVC5pbmRleE9mKG1pKSAhPT0gLTEpIGR5ID0gLTE7XG4gICAgZWxzZSBkeCA9IC0xO1xuICAgIHJldHVybiBbZHgsIGR5XTtcbn1cblxuLypcbiAqIEZpbmQgdGhlIHBpeGVsIGNvb3JkaW5hdGVzIG9mIGEgcGFydGljdWxhciBjcm9zc2luZ1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwaTogdGhlIHBhdGhpbmZvIG9iamVjdCBhdCB0aGlzIGxldmVsXG4gKiBAcGFyYW0ge2FycmF5fSBsb2M6IHRoZSBncmlkIGluZGV4IFt4LCB5XSBvZiB0aGUgY3Jvc3NpbmdcbiAqIEBwYXJhbSB7YXJyYXl9IHN0ZXA6IHRoZSBkaXJlY3Rpb24gW2R4LCBkeV0gd2UncmUgbW92aW5nIG9uIHRoZSBncmlkXG4gKlxuICogQHJldHVybiB7YXJyYXl9IFt4cHgsIHlweCwgeGksIHlpXTogdGhlIGZpcnN0IHR3byBhcmUgdGhlIHBpeGVsIGxvY2F0aW9uLFxuICogICB0aGUgbmV4dCB0d28gYXJlIHRoZSBpbnRlcnBvbGF0ZWQgZ3JpZCBpbmRpY2VzLCB3aGljaCB3ZSB1c2UgZm9yXG4gKiAgIGRpc3RhbmNlIGNhbGN1bGF0aW9ucyB0byBkZWxldGUgcG9pbnRzIHRoYXQgYXJlIHRvbyBjbG9zZSB0b2dldGhlci5cbiAqICAgVGhpcyBpcyBpbXBvcnRhbnQgd2hlbiB0aGUgZ3JpZCBpcyBub251bmlmb3JtIChhbmQgbW9zdCBkcmFtYXRpY2FsbHkgd2hlblxuICogICB3ZSdyZSBvbiBsb2cgYXhlcyBhbmQgaW5jbHVkZSBpbnZhbGlkICgwIG9yIG5lZ2F0aXZlKSB2YWx1ZXMuXG4gKiAgIEl0J3MgY3J1Y2lhbCB0byBkZWxldGUgdGhlc2UgZXh0cmEgdHdvIGJlZm9yZSB0dXJuaW5nIGFuIGFycmF5IG9mIHRoZXNlXG4gKiAgIHBvaW50cyBpbnRvIGEgcGF0aCwgYmVjYXVzZSB0aG9zZSByb3V0aW5lcyByZXF1aXJlIGxlbmd0aC0yIHBvaW50cy5cbiAqL1xuZnVuY3Rpb24gZ2V0SW50ZXJwUHgocGksIGxvYywgc3RlcCkge1xuICAgIHZhciBsb2N4ID0gbG9jWzBdICsgTWF0aC5tYXgoc3RlcFswXSwgMCksXG4gICAgICAgIGxvY3kgPSBsb2NbMV0gKyBNYXRoLm1heChzdGVwWzFdLCAwKSxcbiAgICAgICAgenh5ID0gcGkueltsb2N5XVtsb2N4XSxcbiAgICAgICAgeGEgPSBwaS54YXhpcyxcbiAgICAgICAgeWEgPSBwaS55YXhpcztcblxuICAgIGlmKHN0ZXBbMV0pIHtcbiAgICAgICAgdmFyIGR4ID0gKHBpLmxldmVsIC0genh5KSAvIChwaS56W2xvY3ldW2xvY3ggKyAxXSAtIHp4eSk7XG5cbiAgICAgICAgcmV0dXJuIFt4YS5jMnAoKDEgLSBkeCkgKiBwaS54W2xvY3hdICsgZHggKiBwaS54W2xvY3ggKyAxXSwgdHJ1ZSksXG4gICAgICAgICAgICB5YS5jMnAocGkueVtsb2N5XSwgdHJ1ZSksXG4gICAgICAgICAgICBsb2N4ICsgZHgsIGxvY3ldO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGR5ID0gKHBpLmxldmVsIC0genh5KSAvIChwaS56W2xvY3kgKyAxXVtsb2N4XSAtIHp4eSk7XG4gICAgICAgIHJldHVybiBbeGEuYzJwKHBpLnhbbG9jeF0sIHRydWUpLFxuICAgICAgICAgICAgeWEuYzJwKCgxIC0gZHkpICogcGkueVtsb2N5XSArIGR5ICogcGkueVtsb2N5ICsgMV0sIHRydWUpLFxuICAgICAgICAgICAgbG9jeCwgbG9jeSArIGR5XTtcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgaGVhdG1hcEhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9ob3ZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlLCBob3ZlckxheWVyKSB7XG4gICAgdmFyIGhvdmVyRGF0YSA9IGhlYXRtYXBIb3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSwgaG92ZXJMYXllciwgdHJ1ZSk7XG5cbiAgICBpZihob3ZlckRhdGEpIHtcbiAgICAgICAgaG92ZXJEYXRhLmZvckVhY2goZnVuY3Rpb24oaG92ZXJQdCkge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gaG92ZXJQdC50cmFjZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLmNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLmZpbGxjb2xvciAmJiBDb2xvci5vcGFjaXR5KHRyYWNlLmZpbGxjb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJQdC5jb2xvciA9IENvbG9yLmFkZE9wYWNpdHkodHJhY2UuZmlsbGNvbG9yLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZih0cmFjZS5jb250b3Vycy5zaG93bGluZXMgJiYgQ29sb3Iub3BhY2l0eSh0cmFjZS5saW5lLmNvbG9yKSkge1xuICAgICAgICAgICAgICAgICAgICBob3ZlclB0LmNvbG9yID0gQ29sb3IuYWRkT3BhY2l0eSh0cmFjZS5saW5lLmNvbG9yLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBob3ZlckRhdGE7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBDb250b3VyID0ge307XG5cbkNvbnRvdXIuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuQ29udG91ci5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbkNvbnRvdXIuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuQ29udG91ci5wbG90ID0gcmVxdWlyZSgnLi9wbG90JykucGxvdDtcbkNvbnRvdXIuc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG5Db250b3VyLmNvbG9yYmFyID0gcmVxdWlyZSgnLi9jb2xvcmJhcicpO1xuQ29udG91ci5ob3ZlclBvaW50cyA9IHJlcXVpcmUoJy4vaG92ZXInKTtcblxuQ29udG91ci5tb2R1bGVUeXBlID0gJ3RyYWNlJztcbkNvbnRvdXIubmFtZSA9ICdjb250b3VyJztcbkNvbnRvdXIuYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcbkNvbnRvdXIuY2F0ZWdvcmllcyA9IFsnY2FydGVzaWFuJywgJ3N2ZycsICcyZE1hcCcsICdjb250b3VyJywgJ3Nob3dMZWdlbmQnXTtcbkNvbnRvdXIubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQ29udG91cjtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlTGFiZWxEZWZhdWx0cyhjb2VyY2UsIGxheW91dCwgbGluZUNvbG9yLCBvcHRzKSB7XG4gICAgaWYoIW9wdHMpIG9wdHMgPSB7fTtcbiAgICB2YXIgc2hvd0xhYmVscyA9IGNvZXJjZSgnY29udG91cnMuc2hvd2xhYmVscycpO1xuICAgIGlmKHNob3dMYWJlbHMpIHtcbiAgICAgICAgdmFyIGdsb2JhbEZvbnQgPSBsYXlvdXQuZm9udDtcbiAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnY29udG91cnMubGFiZWxmb250Jywge1xuICAgICAgICAgICAgZmFtaWx5OiBnbG9iYWxGb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IGdsb2JhbEZvbnQuc2l6ZSxcbiAgICAgICAgICAgIGNvbG9yOiBsaW5lQ29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgnY29udG91cnMubGFiZWxmb3JtYXQnKTtcbiAgICB9XG5cbiAgICBpZihvcHRzLmhhc0hvdmVyICE9PSBmYWxzZSkgY29lcmNlKCd6aG92ZXJmb3JtYXQnKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG52YXIgZW5kUGx1cyA9IHJlcXVpcmUoJy4vZW5kX3BsdXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQ29sb3JNYXAodHJhY2UpIHtcbiAgICB2YXIgY29udG91cnMgPSB0cmFjZS5jb250b3VycyxcbiAgICAgICAgc3RhcnQgPSBjb250b3Vycy5zdGFydCxcbiAgICAgICAgZW5kID0gZW5kUGx1cyhjb250b3VycyksXG4gICAgICAgIGNzID0gY29udG91cnMuc2l6ZSB8fCAxLFxuICAgICAgICBuYyA9IE1hdGguZmxvb3IoKGVuZCAtIHN0YXJ0KSAvIGNzKSArIDEsXG4gICAgICAgIGV4dHJhID0gY29udG91cnMuY29sb3JpbmcgPT09ICdsaW5lcycgPyAwIDogMTtcblxuICAgIGlmKCFpc0Zpbml0ZShjcykpIHtcbiAgICAgICAgY3MgPSAxO1xuICAgICAgICBuYyA9IDE7XG4gICAgfVxuXG4gICAgdmFyIHNjbCA9IHRyYWNlLmNvbG9yc2NhbGUsXG4gICAgICAgIGxlbiA9IHNjbC5sZW5ndGg7XG5cbiAgICB2YXIgZG9tYWluID0gbmV3IEFycmF5KGxlbiksXG4gICAgICAgIHJhbmdlID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICB2YXIgc2ksIGk7XG5cbiAgICBpZihjb250b3Vycy5jb2xvcmluZyA9PT0gJ2hlYXRtYXAnKSB7XG4gICAgICAgIGlmKHRyYWNlLnphdXRvICYmIHRyYWNlLmF1dG9jb250b3VyID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdHJhY2Uuem1pbiA9IHN0YXJ0IC0gY3MgLyAyO1xuICAgICAgICAgICAgdHJhY2Uuem1heCA9IHRyYWNlLnptaW4gKyBuYyAqIGNzO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHNpID0gc2NsW2ldO1xuXG4gICAgICAgICAgICBkb21haW5baV0gPSBzaVswXSAqICh0cmFjZS56bWF4IC0gdHJhY2Uuem1pbikgKyB0cmFjZS56bWluO1xuICAgICAgICAgICAgcmFuZ2VbaV0gPSBzaVsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvIHRoZSBjb250b3VycyBleHRlbmQgYmV5b25kIHRoZSBjb2xvcnNjYWxlP1xuICAgICAgICAvLyBpZiBzbywgZXh0ZW5kIHRoZSBjb2xvcnNjYWxlIHdpdGggY29uc3RhbnRzXG4gICAgICAgIHZhciB6UmFuZ2UgPSBkMy5leHRlbnQoW3RyYWNlLnptaW4sIHRyYWNlLnptYXgsIGNvbnRvdXJzLnN0YXJ0LFxuICAgICAgICAgICAgICAgIGNvbnRvdXJzLnN0YXJ0ICsgY3MgKiAobmMgLSAxKV0pLFxuICAgICAgICAgICAgem1pbiA9IHpSYW5nZVt0cmFjZS56bWluIDwgdHJhY2Uuem1heCA/IDAgOiAxXSxcbiAgICAgICAgICAgIHptYXggPSB6UmFuZ2VbdHJhY2Uuem1pbiA8IHRyYWNlLnptYXggPyAxIDogMF07XG5cbiAgICAgICAgaWYoem1pbiAhPT0gdHJhY2Uuem1pbikge1xuICAgICAgICAgICAgZG9tYWluLnNwbGljZSgwLCAwLCB6bWluKTtcbiAgICAgICAgICAgIHJhbmdlLnNwbGljZSgwLCAwLCBSYW5nZVswXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih6bWF4ICE9PSB0cmFjZS56bWF4KSB7XG4gICAgICAgICAgICBkb21haW4ucHVzaCh6bWF4KTtcbiAgICAgICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgc2kgPSBzY2xbaV07XG5cbiAgICAgICAgICAgIGRvbWFpbltpXSA9IChzaVswXSAqIChuYyArIGV4dHJhIC0gMSkgLSAoZXh0cmEgLyAyKSkgKiBjcyArIHN0YXJ0O1xuICAgICAgICAgICAgcmFuZ2VbaV0gPSBzaVsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuYyh7XG4gICAgICAgIGRvbWFpbjogZG9tYWluLFxuICAgICAgICByYW5nZTogcmFuZ2UsXG4gICAgfSwge1xuICAgICAgICBub051bWVyaWNDaGVjazogdHJ1ZVxuICAgIH0pO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbi8vIENhbGN1bGF0ZSBhbGwgdGhlIG1hcmNoaW5nIGluZGljZXMsIGZvciBBTEwgbGV2ZWxzIGF0IG9uY2UuXG4vLyBzaW5jZSB3ZSB3YW50IHRvIGJlIGV4aGF1c3RpdmUgd2UnbGwgY2hlY2sgZm9yIGNvbnRvdXIgY3Jvc3NpbmdzXG4vLyBhdCBldmVyeSBpbnRlcnNlY3Rpb24sIHJhdGhlciB0aGFuIGp1c3QgZm9sbG93aW5nIGEgcGF0aFxuLy8gVE9ETzogc2hvcnRlbiB0aGUgaW5uZXIgbG9vcCB0byBvbmx5IHRoZSByZWxldmFudCBsZXZlbHNcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUNyb3NzaW5ncyhwYXRoaW5mbykge1xuICAgIHZhciB6ID0gcGF0aGluZm9bMF0ueixcbiAgICAgICAgbSA9IHoubGVuZ3RoLFxuICAgICAgICBuID0gelswXS5sZW5ndGgsIC8vIHdlIGFscmVhZHkgbWFkZSBzdXJlIHogaXNuJ3QgcmFnZ2VkIGluIGludGVycDJkXG4gICAgICAgIHR3b1dpZGUgPSBtID09PSAyIHx8IG4gPT09IDIsXG4gICAgICAgIHhpLFxuICAgICAgICB5aSxcbiAgICAgICAgc3RhcnRJbmRpY2VzLFxuICAgICAgICB5c3RhcnRJbmRpY2VzLFxuICAgICAgICBsYWJlbCxcbiAgICAgICAgY29ybmVycyxcbiAgICAgICAgbWksXG4gICAgICAgIHBpLFxuICAgICAgICBpO1xuXG4gICAgZm9yKHlpID0gMDsgeWkgPCBtIC0gMTsgeWkrKykge1xuICAgICAgICB5c3RhcnRJbmRpY2VzID0gW107XG4gICAgICAgIGlmKHlpID09PSAwKSB5c3RhcnRJbmRpY2VzID0geXN0YXJ0SW5kaWNlcy5jb25jYXQoY29uc3RhbnRzLkJPVFRPTVNUQVJUKTtcbiAgICAgICAgaWYoeWkgPT09IG0gLSAyKSB5c3RhcnRJbmRpY2VzID0geXN0YXJ0SW5kaWNlcy5jb25jYXQoY29uc3RhbnRzLlRPUFNUQVJUKTtcblxuICAgICAgICBmb3IoeGkgPSAwOyB4aSA8IG4gLSAxOyB4aSsrKSB7XG4gICAgICAgICAgICBzdGFydEluZGljZXMgPSB5c3RhcnRJbmRpY2VzLnNsaWNlKCk7XG4gICAgICAgICAgICBpZih4aSA9PT0gMCkgc3RhcnRJbmRpY2VzID0gc3RhcnRJbmRpY2VzLmNvbmNhdChjb25zdGFudHMuTEVGVFNUQVJUKTtcbiAgICAgICAgICAgIGlmKHhpID09PSBuIC0gMikgc3RhcnRJbmRpY2VzID0gc3RhcnRJbmRpY2VzLmNvbmNhdChjb25zdGFudHMuUklHSFRTVEFSVCk7XG5cbiAgICAgICAgICAgIGxhYmVsID0geGkgKyAnLCcgKyB5aTtcbiAgICAgICAgICAgIGNvcm5lcnMgPSBbW3pbeWldW3hpXSwgelt5aV1beGkgKyAxXV0sXG4gICAgICAgICAgICAgICAgICAgICAgIFt6W3lpICsgMV1beGldLCB6W3lpICsgMV1beGkgKyAxXV1dO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGF0aGluZm8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwaSA9IHBhdGhpbmZvW2ldO1xuICAgICAgICAgICAgICAgIG1pID0gZ2V0TWFyY2hpbmdJbmRleChwaS5sZXZlbCwgY29ybmVycyk7XG4gICAgICAgICAgICAgICAgaWYoIW1pKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIHBpLmNyb3NzaW5nc1tsYWJlbF0gPSBtaTtcbiAgICAgICAgICAgICAgICBpZihzdGFydEluZGljZXMuaW5kZXhPZihtaSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHBpLnN0YXJ0cy5wdXNoKFt4aSwgeWldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodHdvV2lkZSAmJiBzdGFydEluZGljZXMuaW5kZXhPZihtaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydEluZGljZXMuaW5kZXhPZihtaSkgKyAxKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzYW1lIHNxdWFyZSBoYXMgc3RhcnRzIGZyb20gb3Bwb3NpdGUgc2lkZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0J3Mgbm90IHBvc3NpYmxlIHRvIGhhdmUgc3RhcnRzIG9uIG9wcG9zaXRlIGVkZ2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvZiBhIGNvcm5lciwgb25seSBhIHN0YXJ0IGFuZCBhbiBlbmQuLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBpZiB0aGUgYXJyYXkgaXMgb25seSB0d28gcG9pbnRzIHdpZGUgKGVpdGhlciB3YXkpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB5b3UgY2FuIGhhdmUgc3RhcnRzIG9uIG9wcG9zaXRlIHNpZGVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgcGkuc3RhcnRzLnB1c2goW3hpLCB5aV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuLy8gbW9kaWZpZWQgbWFyY2hpbmcgc3F1YXJlcyBhbGdvcml0aG0sXG4vLyBzbyB3ZSBkaXNhbWJpZ3VhdGUgdGhlIHNhZGRsZSBwb2ludHMgZnJvbSB0aGUgc3RhcnRcbi8vIGFuZCB3ZSBpZ25vcmUgdGhlIGNhc2VzIHdpdGggbm8gY3Jvc3NpbmdzXG4vLyB0aGUgaW5kZXggSSdtIHVzaW5nIGlzIGJhc2VkIG9uOlxuLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NYXJjaGluZ19zcXVhcmVzXG4vLyBleGNlcHQgdGhhdCB0aGUgc2FkZGxlcyBiaWZ1cmNhdGUgYW5kIEkgcmVwcmVzZW50IHRoZW1cbi8vIGFzIHRoZSBkZWNpbWFsIGNvbWJpbmF0aW9uIG9mIHRoZSB0d28gYXBwcm9wcmlhdGVcbi8vIG5vbi1zYWRkbGUgaW5kaWNlc1xuZnVuY3Rpb24gZ2V0TWFyY2hpbmdJbmRleCh2YWwsIGNvcm5lcnMpIHtcbiAgICB2YXIgbWkgPSAoY29ybmVyc1swXVswXSA+IHZhbCA/IDAgOiAxKSArXG4gICAgICAgICAgICAgKGNvcm5lcnNbMF1bMV0gPiB2YWwgPyAwIDogMikgK1xuICAgICAgICAgICAgIChjb3JuZXJzWzFdWzFdID4gdmFsID8gMCA6IDQpICtcbiAgICAgICAgICAgICAoY29ybmVyc1sxXVswXSA+IHZhbCA/IDAgOiA4KTtcbiAgICBpZihtaSA9PT0gNSB8fCBtaSA9PT0gMTApIHtcbiAgICAgICAgdmFyIGF2ZyA9IChjb3JuZXJzWzBdWzBdICsgY29ybmVyc1swXVsxXSArXG4gICAgICAgICAgICAgICAgICAgY29ybmVyc1sxXVswXSArIGNvcm5lcnNbMV1bMV0pIC8gNDtcbiAgICAgICAgLy8gdHdvIHBlYWtzIHdpdGggYSBiaWcgdmFsbGV5XG4gICAgICAgIGlmKHZhbCA+IGF2ZykgcmV0dXJuIChtaSA9PT0gNSkgPyA3MTMgOiAxMTE0O1xuICAgICAgICAvLyB0d28gdmFsbGV5cyB3aXRoIGEgYmlnIHJpZGdlXG4gICAgICAgIHJldHVybiAobWkgPT09IDUpID8gMTA0IDogMjA4O1xuICAgIH1cbiAgICByZXR1cm4gKG1pID09PSAxNSkgPyAwIDogbWk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSByZXF1aXJlKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBzZXRDb252ZXJ0ID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3NldF9jb252ZXJ0Jyk7XG5cbnZhciBoZWF0bWFwUGxvdCA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvcGxvdCcpO1xudmFyIG1ha2VDcm9zc2luZ3MgPSByZXF1aXJlKCcuL21ha2VfY3Jvc3NpbmdzJyk7XG52YXIgZmluZEFsbFBhdGhzID0gcmVxdWlyZSgnLi9maW5kX2FsbF9wYXRocycpO1xudmFyIGVtcHR5UGF0aGluZm8gPSByZXF1aXJlKCcuL2VtcHR5X3BhdGhpbmZvJyk7XG52YXIgY29udmVydFRvQ29uc3RyYWludHMgPSByZXF1aXJlKCcuL2NvbnZlcnRfdG9fY29uc3RyYWludHMnKTtcbnZhciBjbG9zZUJvdW5kYXJpZXMgPSByZXF1aXJlKCcuL2Nsb3NlX2JvdW5kYXJpZXMnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpO1xudmFyIGNvc3RDb25zdGFudHMgPSBjb25zdGFudHMuTEFCRUxPUFRJTUlaRVI7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZGNvbnRvdXJzLCBjb250b3VyTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyhjb250b3VyTGF5ZXIsIGNkY29udG91cnMsICdjb250b3VyJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIHggPSBjZDAueDtcbiAgICAgICAgdmFyIHkgPSBjZDAueTtcbiAgICAgICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG4gICAgICAgIHZhciBwYXRoaW5mbyA9IGVtcHR5UGF0aGluZm8oY29udG91cnMsIHBsb3RpbmZvLCBjZDApO1xuXG4gICAgICAgIC8vIHVzZSBhIGhlYXRtYXAgdG8gZmlsbCAtIGRyYXcgaXQgYmVoaW5kIHRoZSBsaW5lc1xuICAgICAgICB2YXIgaGVhdG1hcENvbG9yaW5nTGF5ZXIgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3RHcm91cCwgJ2cnLCAnaGVhdG1hcGNvbG9yaW5nJyk7XG4gICAgICAgIHZhciBjZGhlYXRtYXBzID0gW107XG4gICAgICAgIGlmKGNvbnRvdXJzLmNvbG9yaW5nID09PSAnaGVhdG1hcCcpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLnphdXRvICYmICh0cmFjZS5hdXRvY29udG91ciA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdHJhY2UuX2lucHV0LnptaW4gPSB0cmFjZS56bWluID1cbiAgICAgICAgICAgICAgICAgICAgY29udG91cnMuc3RhcnQgLSBjb250b3Vycy5zaXplIC8gMjtcbiAgICAgICAgICAgICAgICB0cmFjZS5faW5wdXQuem1heCA9IHRyYWNlLnptYXggPVxuICAgICAgICAgICAgICAgICAgICB0cmFjZS56bWluICsgcGF0aGluZm8ubGVuZ3RoICogY29udG91cnMuc2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNkaGVhdG1hcHMgPSBbY2RdO1xuICAgICAgICB9XG4gICAgICAgIGhlYXRtYXBQbG90KGdkLCBwbG90aW5mbywgY2RoZWF0bWFwcywgaGVhdG1hcENvbG9yaW5nTGF5ZXIpO1xuXG4gICAgICAgIG1ha2VDcm9zc2luZ3MocGF0aGluZm8pO1xuICAgICAgICBmaW5kQWxsUGF0aHMocGF0aGluZm8pO1xuXG4gICAgICAgIHZhciBsZWZ0ZWRnZSA9IHhhLmMycCh4WzBdLCB0cnVlKSxcbiAgICAgICAgICAgIHJpZ2h0ZWRnZSA9IHhhLmMycCh4W3gubGVuZ3RoIC0gMV0sIHRydWUpLFxuICAgICAgICAgICAgYm90dG9tZWRnZSA9IHlhLmMycCh5WzBdLCB0cnVlKSxcbiAgICAgICAgICAgIHRvcGVkZ2UgPSB5YS5jMnAoeVt5Lmxlbmd0aCAtIDFdLCB0cnVlKSxcbiAgICAgICAgICAgIHBlcmltZXRlciA9IFtcbiAgICAgICAgICAgICAgICBbbGVmdGVkZ2UsIHRvcGVkZ2VdLFxuICAgICAgICAgICAgICAgIFtyaWdodGVkZ2UsIHRvcGVkZ2VdLFxuICAgICAgICAgICAgICAgIFtyaWdodGVkZ2UsIGJvdHRvbWVkZ2VdLFxuICAgICAgICAgICAgICAgIFtsZWZ0ZWRnZSwgYm90dG9tZWRnZV1cbiAgICAgICAgICAgIF07XG5cbiAgICAgICAgdmFyIGZpbGxQYXRoaW5mbyA9IHBhdGhpbmZvO1xuICAgICAgICBpZihjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCcpIHtcbiAgICAgICAgICAgIGZpbGxQYXRoaW5mbyA9IGNvbnZlcnRUb0NvbnN0cmFpbnRzKHBhdGhpbmZvLCBjb250b3Vycy5fb3BlcmF0aW9uKTtcbiAgICAgICAgICAgIGNsb3NlQm91bmRhcmllcyhmaWxsUGF0aGluZm8sIGNvbnRvdXJzLl9vcGVyYXRpb24sIHBlcmltZXRlciwgdHJhY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZHJhdyBldmVyeXRoaW5nXG4gICAgICAgIG1ha2VCYWNrZ3JvdW5kKHBsb3RHcm91cCwgcGVyaW1ldGVyLCBjb250b3Vycyk7XG4gICAgICAgIG1ha2VGaWxscyhwbG90R3JvdXAsIGZpbGxQYXRoaW5mbywgcGVyaW1ldGVyLCBjb250b3Vycyk7XG4gICAgICAgIG1ha2VMaW5lc0FuZExhYmVscyhwbG90R3JvdXAsIHBhdGhpbmZvLCBnZCwgY2QwLCBjb250b3VycywgcGVyaW1ldGVyKTtcbiAgICAgICAgY2xpcEdhcHMocGxvdEdyb3VwLCBwbG90aW5mbywgZnVsbExheW91dC5fY2xpcHMsIGNkMCwgcGVyaW1ldGVyKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VCYWNrZ3JvdW5kKHBsb3Rncm91cCwgcGVyaW1ldGVyLCBjb250b3Vycykge1xuICAgIHZhciBiZ2dyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJiZycpO1xuXG4gICAgdmFyIGJnZmlsbCA9IGJnZ3JvdXAuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgLmRhdGEoY29udG91cnMuY29sb3JpbmcgPT09ICdmaWxsJyA/IFswXSA6IFtdKTtcbiAgICBiZ2ZpbGwuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcbiAgICBiZ2ZpbGwuZXhpdCgpLnJlbW92ZSgpO1xuICAgIGJnZmlsbFxuICAgICAgICAuYXR0cignZCcsICdNJyArIHBlcmltZXRlci5qb2luKCdMJykgKyAnWicpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgJ25vbmUnKTtcbn1cblxuZnVuY3Rpb24gbWFrZUZpbGxzKHBsb3Rncm91cCwgcGF0aGluZm8sIHBlcmltZXRlciwgY29udG91cnMpIHtcbiAgICB2YXIgZmlsbGdyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJmaWxsJyk7XG5cbiAgICB2YXIgZmlsbGl0ZW1zID0gZmlsbGdyb3VwLnNlbGVjdEFsbCgncGF0aCcpXG4gICAgICAgIC5kYXRhKGNvbnRvdXJzLmNvbG9yaW5nID09PSAnZmlsbCcgfHwgKGNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50JyAmJiBjb250b3Vycy5fb3BlcmF0aW9uICE9PSAnPScpID8gcGF0aGluZm8gOiBbXSk7XG4gICAgZmlsbGl0ZW1zLmVudGVyKCkuYXBwZW5kKCdwYXRoJyk7XG4gICAgZmlsbGl0ZW1zLmV4aXQoKS5yZW1vdmUoKTtcbiAgICBmaWxsaXRlbXMuZWFjaChmdW5jdGlvbihwaSkge1xuICAgICAgICAvLyBqb2luIGFsbCBwYXRocyBmb3IgdGhpcyBsZXZlbCB0b2dldGhlciBpbnRvIGEgc2luZ2xlIHBhdGhcbiAgICAgICAgLy8gZmlyc3QgZm9sbG93IGNsb2Nrd2lzZSBhcm91bmQgdGhlIHBlcmltZXRlciB0byBjbG9zZSBhbnkgb3BlbiBwYXRoc1xuICAgICAgICAvLyBpZiB0aGUgd2hvbGUgcGVyaW1ldGVyIGlzIGFib3ZlIHRoaXMgbGV2ZWwsIHN0YXJ0IHdpdGggYSBwYXRoXG4gICAgICAgIC8vIGVuY2xvc2luZyB0aGUgd2hvbGUgdGhpbmcuIFdpdGggYWxsIHRoYXQsIHRoZSBwYXJpdHkgc2hvdWxkIG1lYW5cbiAgICAgICAgLy8gdGhhdCB3ZSBhbHdheXMgZmlsbCBldmVyeXRoaW5nIGFib3ZlIHRoZSBjb250b3VyLCBub3RoaW5nIGJlbG93XG4gICAgICAgIHZhciBmdWxscGF0aCA9IGpvaW5BbGxQYXRocyhwaSwgcGVyaW1ldGVyKTtcblxuICAgICAgICBpZighZnVsbHBhdGgpIGQzLnNlbGVjdCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgZWxzZSBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsIGZ1bGxwYXRoKS5zdHlsZSgnc3Ryb2tlJywgJ25vbmUnKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdEZ1bGxQYXRoKHBpLCBwZXJpbWV0ZXIpIHtcbiAgICB2YXIgcHJlZml4Qm91bmRhcnkgPSBwaS5wcmVmaXhCb3VuZGFyeTtcbiAgICBpZihwcmVmaXhCb3VuZGFyeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBlZGdlVmFsMiA9IE1hdGgubWluKHBpLnpbMF1bMF0sIHBpLnpbMF1bMV0pO1xuICAgICAgICBwcmVmaXhCb3VuZGFyeSA9ICghcGkuZWRnZXBhdGhzLmxlbmd0aCAmJiBlZGdlVmFsMiA+IHBpLmxldmVsKTtcbiAgICB9XG5cbiAgICBpZihwcmVmaXhCb3VuZGFyeSkge1xuICAgICAgICAvLyBUT0RPOiB3aHkgZG9lcyBeXiBub3Qgd29yayBmb3IgY29uc3RyYWludHM/XG4gICAgICAgIC8vIHBpLnByZWZpeEJvdW5kYXJ5IGdldHMgc2V0IGJ5IGNsb3NlQm91bmRhcmllc1xuICAgICAgICByZXR1cm4gJ00nICsgcGVyaW1ldGVyLmpvaW4oJ0wnKSArICdaJztcbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBqb2luQWxsUGF0aHMocGksIHBlcmltZXRlcikge1xuICAgIHZhciBmdWxscGF0aCA9IGluaXRGdWxsUGF0aChwaSwgcGVyaW1ldGVyKSxcbiAgICAgICAgaSA9IDAsXG4gICAgICAgIHN0YXJ0c2xlZnQgPSBwaS5lZGdlcGF0aHMubWFwKGZ1bmN0aW9uKHYsIGkpIHsgcmV0dXJuIGk7IH0pLFxuICAgICAgICBuZXdsb29wID0gdHJ1ZSxcbiAgICAgICAgZW5kcHQsXG4gICAgICAgIG5ld2VuZHB0LFxuICAgICAgICBjbnQsXG4gICAgICAgIG5leHRpLFxuICAgICAgICBwb3NzaWJsZWksXG4gICAgICAgIGFkZHBhdGg7XG5cbiAgICBmdW5jdGlvbiBpc3RvcChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMV0gLSBwZXJpbWV0ZXJbMF1bMV0pIDwgMC4wMTsgfVxuICAgIGZ1bmN0aW9uIGlzYm90dG9tKHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFsxXSAtIHBlcmltZXRlclsyXVsxXSkgPCAwLjAxOyB9XG4gICAgZnVuY3Rpb24gaXNsZWZ0KHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFswXSAtIHBlcmltZXRlclswXVswXSkgPCAwLjAxOyB9XG4gICAgZnVuY3Rpb24gaXNyaWdodChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMF0gLSBwZXJpbWV0ZXJbMl1bMF0pIDwgMC4wMTsgfVxuXG4gICAgd2hpbGUoc3RhcnRzbGVmdC5sZW5ndGgpIHtcbiAgICAgICAgYWRkcGF0aCA9IERyYXdpbmcuc21vb3Rob3BlbihwaS5lZGdlcGF0aHNbaV0sIHBpLnNtb290aGluZyk7XG4gICAgICAgIGZ1bGxwYXRoICs9IG5ld2xvb3AgPyBhZGRwYXRoIDogYWRkcGF0aC5yZXBsYWNlKC9eTS8sICdMJyk7XG4gICAgICAgIHN0YXJ0c2xlZnQuc3BsaWNlKHN0YXJ0c2xlZnQuaW5kZXhPZihpKSwgMSk7XG4gICAgICAgIGVuZHB0ID0gcGkuZWRnZXBhdGhzW2ldW3BpLmVkZ2VwYXRoc1tpXS5sZW5ndGggLSAxXTtcbiAgICAgICAgbmV4dGkgPSAtMTtcblxuICAgICAgICAvLyBub3cgbG9vcCB0aHJvdWdoIHNpZGVzLCBtb3Zpbmcgb3VyIGVuZHBvaW50IHVudGlsIHdlIGZpbmQgYSBuZXcgc3RhcnRcbiAgICAgICAgZm9yKGNudCA9IDA7IGNudCA8IDQ7IGNudCsrKSB7IC8vIGp1c3QgdG8gcHJldmVudCBpbmZpbml0ZSBsb29wc1xuICAgICAgICAgICAgaWYoIWVuZHB0KSB7XG4gICAgICAgICAgICAgICAgTGliLmxvZygnTWlzc2luZyBlbmQ/JywgaSwgcGkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc3RvcChlbmRwdCkgJiYgIWlzcmlnaHQoZW5kcHQpKSBuZXdlbmRwdCA9IHBlcmltZXRlclsxXTsgLy8gcmlnaHQgdG9wXG4gICAgICAgICAgICBlbHNlIGlmKGlzbGVmdChlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzBdOyAvLyBsZWZ0IHRvcFxuICAgICAgICAgICAgZWxzZSBpZihpc2JvdHRvbShlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzNdOyAvLyByaWdodCBib3R0b21cbiAgICAgICAgICAgIGVsc2UgaWYoaXNyaWdodChlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzJdOyAvLyBsZWZ0IGJvdHRvbVxuXG4gICAgICAgICAgICBmb3IocG9zc2libGVpID0gMDsgcG9zc2libGVpIDwgcGkuZWRnZXBhdGhzLmxlbmd0aDsgcG9zc2libGVpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHROZXcgPSBwaS5lZGdlcGF0aHNbcG9zc2libGVpXVswXTtcbiAgICAgICAgICAgICAgICAvLyBpcyBwdE5ldyBvbiB0aGUgKGhvcnouIG9yIHZlcnQuKSBzZWdtZW50IGZyb20gZW5kcHQgdG8gbmV3ZW5kcHQ/XG4gICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZW5kcHRbMF0gLSBuZXdlbmRwdFswXSkgPCAwLjAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGVuZHB0WzBdIC0gcHROZXdbMF0pIDwgMC4wMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwdE5ld1sxXSAtIGVuZHB0WzFdKSAqIChuZXdlbmRwdFsxXSAtIHB0TmV3WzFdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHB0TmV3O1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dGkgPSBwb3NzaWJsZWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihNYXRoLmFicyhlbmRwdFsxXSAtIG5ld2VuZHB0WzFdKSA8IDAuMDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZW5kcHRbMV0gLSBwdE5ld1sxXSkgPCAwLjAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHB0TmV3WzBdIC0gZW5kcHRbMF0pICogKG5ld2VuZHB0WzBdIC0gcHROZXdbMF0pID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld2VuZHB0ID0gcHROZXc7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXh0aSA9IHBvc3NpYmxlaTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLmxvZygnZW5kcHQgdG8gbmV3ZW5kcHQgaXMgbm90IHZlcnQuIG9yIGhvcnouJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZHB0LCBuZXdlbmRwdCwgcHROZXcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZW5kcHQgPSBuZXdlbmRwdDtcblxuICAgICAgICAgICAgaWYobmV4dGkgPj0gMCkgYnJlYWs7XG4gICAgICAgICAgICBmdWxscGF0aCArPSAnTCcgKyBuZXdlbmRwdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG5leHRpID09PSBwaS5lZGdlcGF0aHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBMaWIubG9nKCd1bmNsb3NlZCBwZXJpbWV0ZXIgcGF0aCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpID0gbmV4dGk7XG5cbiAgICAgICAgLy8gaWYgd2UgY2xvc2VkIGJhY2sgb24gYSBsb29wIHdlIGFscmVhZHkgaW5jbHVkZWQsXG4gICAgICAgIC8vIGNsb3NlIGl0IGFuZCBzdGFydCBhIG5ldyBsb29wXG4gICAgICAgIG5ld2xvb3AgPSAoc3RhcnRzbGVmdC5pbmRleE9mKGkpID09PSAtMSk7XG4gICAgICAgIGlmKG5ld2xvb3ApIHtcbiAgICAgICAgICAgIGkgPSBzdGFydHNsZWZ0WzBdO1xuICAgICAgICAgICAgZnVsbHBhdGggKz0gJ1onO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZmluYWxseSBhZGQgdGhlIGludGVyaW9yIHBhdGhzXG4gICAgZm9yKGkgPSAwOyBpIDwgcGkucGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZnVsbHBhdGggKz0gRHJhd2luZy5zbW9vdGhjbG9zZWQocGkucGF0aHNbaV0sIHBpLnNtb290aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bGxwYXRoO1xufVxuXG5mdW5jdGlvbiBtYWtlTGluZXNBbmRMYWJlbHMocGxvdGdyb3VwLCBwYXRoaW5mbywgZ2QsIGNkMCwgY29udG91cnMsIHBlcmltZXRlcikge1xuICAgIHZhciBsaW5lQ29udGFpbmVyID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJsaW5lcycpO1xuICAgIHZhciBzaG93TGluZXMgPSBjb250b3Vycy5zaG93bGluZXMgIT09IGZhbHNlO1xuICAgIHZhciBzaG93TGFiZWxzID0gY29udG91cnMuc2hvd2xhYmVscztcbiAgICB2YXIgY2xpcExpbmVzRm9yTGFiZWxzID0gc2hvd0xpbmVzICYmIHNob3dMYWJlbHM7XG5cbiAgICAvLyBFdmVuIGlmIHdlJ3JlIG5vdCBnb2luZyB0byBzaG93IGxpbmVzLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGVtXG4gICAgLy8gaWYgd2UncmUgc2hvd2luZyBsYWJlbHMsIGJlY2F1c2UgdGhlIGZpbGwgcGF0aHMgaW5jbHVkZSB0aGUgcGVyaW1ldGVyXG4gICAgLy8gc28gY2FuJ3QgYmUgdXNlZCB0byBwb3NpdGlvbiB0aGUgbGFiZWxzIGNvcnJlY3RseS5cbiAgICAvLyBJbiB0aGlzIGNhc2Ugd2UnbGwgcmVtb3ZlIHRoZSBsaW5lcyBhZnRlciBtYWtpbmcgdGhlIGxhYmVscy5cbiAgICB2YXIgbGluZWdyb3VwID0gZXhwb3J0cy5jcmVhdGVMaW5lcyhsaW5lQ29udGFpbmVyLCBzaG93TGluZXMgfHwgc2hvd0xhYmVscywgcGF0aGluZm8pO1xuXG4gICAgdmFyIGxpbmVDbGlwID0gZXhwb3J0cy5jcmVhdGVMaW5lQ2xpcChsaW5lQ29udGFpbmVyLCBjbGlwTGluZXNGb3JMYWJlbHMsXG4gICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9jbGlwcywgY2QwLnRyYWNlLnVpZCk7XG5cbiAgICB2YXIgbGFiZWxHcm91cCA9IHBsb3Rncm91cC5zZWxlY3RBbGwoJ2cuY29udG91cmxhYmVscycpXG4gICAgICAgIC5kYXRhKHNob3dMYWJlbHMgPyBbMF0gOiBbXSk7XG5cbiAgICBsYWJlbEdyb3VwLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGxhYmVsR3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmxhYmVscycsIHRydWUpO1xuXG4gICAgaWYoc2hvd0xhYmVscykge1xuICAgICAgICB2YXIgbGFiZWxDbGlwUGF0aERhdGEgPSBbcGVyaW1ldGVyXTtcblxuICAgICAgICB2YXIgbGFiZWxEYXRhID0gW107XG5cbiAgICAgICAgLy8gaW52YWxpZGF0ZSB0aGUgZ2V0VGV4dExvY2F0aW9uIGNhY2hlIGluIGNhc2UgcGF0aHMgY2hhbmdlZFxuICAgICAgICBMaWIuY2xlYXJMb2NhdGlvbkNhY2hlKCk7XG5cbiAgICAgICAgdmFyIGNvbnRvdXJGb3JtYXQgPSBleHBvcnRzLmxhYmVsRm9ybWF0dGVyKGNvbnRvdXJzLCBjZDAudC5jYiwgZ2QuX2Z1bGxMYXlvdXQpO1xuXG4gICAgICAgIHZhciBkdW1teVRleHQgPSBEcmF3aW5nLnRlc3Rlci5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtbm90ZXgnLCAxKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBjb250b3Vycy5sYWJlbGZvbnQpO1xuXG4gICAgICAgIHZhciB4TGVuID0gcGF0aGluZm9bMF0ueGF4aXMuX2xlbmd0aDtcbiAgICAgICAgdmFyIHlMZW4gPSBwYXRoaW5mb1swXS55YXhpcy5fbGVuZ3RoO1xuXG4gICAgICAgIC8vIHZpc2libGUgYm91bmRzIG9mIHRoZSBjb250b3VyIHRyYWNlIChhbmQgdGhlIG1pZHBvaW50cywgdG9cbiAgICAgICAgLy8gaGVscCB3aXRoIGNvc3QgY2FsY3VsYXRpb25zKVxuICAgICAgICB2YXIgYm91bmRzID0ge1xuICAgICAgICAgICAgbGVmdDogTWF0aC5tYXgocGVyaW1ldGVyWzBdWzBdLCAwKSxcbiAgICAgICAgICAgIHJpZ2h0OiBNYXRoLm1pbihwZXJpbWV0ZXJbMl1bMF0sIHhMZW4pLFxuICAgICAgICAgICAgdG9wOiBNYXRoLm1heChwZXJpbWV0ZXJbMF1bMV0sIDApLFxuICAgICAgICAgICAgYm90dG9tOiBNYXRoLm1pbihwZXJpbWV0ZXJbMl1bMV0sIHlMZW4pXG4gICAgICAgIH07XG4gICAgICAgIGJvdW5kcy5taWRkbGUgPSAoYm91bmRzLnRvcCArIGJvdW5kcy5ib3R0b20pIC8gMjtcbiAgICAgICAgYm91bmRzLmNlbnRlciA9IChib3VuZHMubGVmdCArIGJvdW5kcy5yaWdodCkgLyAyO1xuXG4gICAgICAgIHZhciBwbG90RGlhZ29uYWwgPSBNYXRoLnNxcnQoeExlbiAqIHhMZW4gKyB5TGVuICogeUxlbik7XG5cbiAgICAgICAgLy8gdGhlIHBhdGggbGVuZ3RoIHRvIHVzZSB0byBzY2FsZSB0aGUgbnVtYmVyIG9mIGxhYmVscyB0byBkcmF3OlxuICAgICAgICB2YXIgbm9ybUxlbmd0aCA9IGNvbnN0YW50cy5MQUJFTERJU1RBTkNFICogcGxvdERpYWdvbmFsIC9cbiAgICAgICAgICAgIE1hdGgubWF4KDEsIHBhdGhpbmZvLmxlbmd0aCAvIGNvbnN0YW50cy5MQUJFTElOQ1JFQVNFKTtcblxuICAgICAgICBsaW5lZ3JvdXAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdGV4dE9wdHMgPSBleHBvcnRzLmNhbGNUZXh0T3B0cyhkLmxldmVsLCBjb250b3VyRm9ybWF0LCBkdW1teVRleHQsIGdkKTtcblxuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgncGF0aCcpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGggPSB0aGlzO1xuICAgICAgICAgICAgICAgIHZhciBwYXRoQm91bmRzID0gTGliLmdldFZpc2libGVTZWdtZW50KHBhdGgsIGJvdW5kcywgdGV4dE9wdHMuaGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgaWYoIXBhdGhCb3VuZHMpIHJldHVybjtcblxuICAgICAgICAgICAgICAgIGlmKHBhdGhCb3VuZHMubGVuIDwgKHRleHRPcHRzLndpZHRoICsgdGV4dE9wdHMuaGVpZ2h0KSAqIGNvbnN0YW50cy5MQUJFTE1JTikgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heExhYmVscyA9IE1hdGgubWluKE1hdGguY2VpbChwYXRoQm91bmRzLmxlbiAvIG5vcm1MZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuTEFCRUxNQVgpO1xuXG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG1heExhYmVsczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb2MgPSBleHBvcnRzLmZpbmRCZXN0VGV4dExvY2F0aW9uKHBhdGgsIHBhdGhCb3VuZHMsIHRleHRPcHRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxEYXRhLCBib3VuZHMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKCFsb2MpIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHMuYWRkTGFiZWxEYXRhKGxvYywgdGV4dE9wdHMsIGxhYmVsRGF0YSwgbGFiZWxDbGlwUGF0aERhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBkdW1teVRleHQucmVtb3ZlKCk7XG5cbiAgICAgICAgZXhwb3J0cy5kcmF3TGFiZWxzKGxhYmVsR3JvdXAsIGxhYmVsRGF0YSwgZ2QsIGxpbmVDbGlwLFxuICAgICAgICAgICAgY2xpcExpbmVzRm9yTGFiZWxzID8gbGFiZWxDbGlwUGF0aERhdGEgOiBudWxsKTtcbiAgICB9XG5cbiAgICBpZihzaG93TGFiZWxzICYmICFzaG93TGluZXMpIGxpbmVncm91cC5yZW1vdmUoKTtcbn1cblxuZXhwb3J0cy5jcmVhdGVMaW5lcyA9IGZ1bmN0aW9uKGxpbmVDb250YWluZXIsIG1ha2VMaW5lcywgcGF0aGluZm8pIHtcbiAgICB2YXIgc21vb3RoaW5nID0gcGF0aGluZm9bMF0uc21vb3RoaW5nO1xuXG4gICAgdmFyIGxpbmVncm91cCA9IGxpbmVDb250YWluZXIuc2VsZWN0QWxsKCdnLmNvbnRvdXJsZXZlbCcpXG4gICAgICAgIC5kYXRhKG1ha2VMaW5lcyA/IHBhdGhpbmZvIDogW10pO1xuXG4gICAgbGluZWdyb3VwLmV4aXQoKS5yZW1vdmUoKTtcbiAgICBsaW5lZ3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmxldmVsJywgdHJ1ZSk7XG5cbiAgICBpZihtYWtlTGluZXMpIHtcbiAgICAgICAgLy8gcGVkZ2VwYXRocyAvIHBwYXRocyBhcmUgdXNlZCBieSBjb250b3VyY2FycGV0LCBmb3IgdGhlIHBhdGhzIHRyYW5zZm9ybWVkIGZyb20gYS9iIHRvIHgveVxuICAgICAgICAvLyBlZGdlcGF0aHMgLyBwYXRocyBhcmUgdXNlZCBieSBjb250b3VyIHNpbmNlIGl0J3MgaW4geC95IGZyb20gdGhlIHN0YXJ0XG4gICAgICAgIHZhciBvcGVuY29udG91cmxpbmVzID0gbGluZWdyb3VwLnNlbGVjdEFsbCgncGF0aC5vcGVubGluZScpXG4gICAgICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7IHJldHVybiBkLnBlZGdlcGF0aHMgfHwgZC5lZGdlcGF0aHM7IH0pO1xuXG4gICAgICAgIG9wZW5jb250b3VybGluZXMuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICBvcGVuY29udG91cmxpbmVzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdvcGVubGluZScsIHRydWUpO1xuXG4gICAgICAgIG9wZW5jb250b3VybGluZXNcbiAgICAgICAgICAgIC5hdHRyKCdkJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEcmF3aW5nLnNtb290aG9wZW4oZCwgc21vb3RoaW5nKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSlcbiAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKTtcblxuICAgICAgICB2YXIgY2xvc2VkY29udG91cmxpbmVzID0gbGluZWdyb3VwLnNlbGVjdEFsbCgncGF0aC5jbG9zZWRsaW5lJylcbiAgICAgICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQucHBhdGhzIHx8IGQucGF0aHM7IH0pO1xuXG4gICAgICAgIGNsb3NlZGNvbnRvdXJsaW5lcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGNsb3NlZGNvbnRvdXJsaW5lcy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuY2xhc3NlZCgnY2xvc2VkbGluZScsIHRydWUpO1xuXG4gICAgICAgIGNsb3NlZGNvbnRvdXJsaW5lc1xuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3RoY2xvc2VkKGQsIHNtb290aGluZyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2UtbWl0ZXJsaW1pdCcsIDEpXG4gICAgICAgICAgICAuc3R5bGUoJ3ZlY3Rvci1lZmZlY3QnLCAnbm9uLXNjYWxpbmctc3Ryb2tlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpbmVncm91cDtcbn07XG5cbmV4cG9ydHMuY3JlYXRlTGluZUNsaXAgPSBmdW5jdGlvbihsaW5lQ29udGFpbmVyLCBjbGlwTGluZXNGb3JMYWJlbHMsIGNsaXBzLCB1aWQpIHtcbiAgICB2YXIgY2xpcElkID0gY2xpcExpbmVzRm9yTGFiZWxzID8gKCdjbGlwbGluZScgKyB1aWQpIDogbnVsbDtcblxuICAgIHZhciBsaW5lQ2xpcCA9IGNsaXBzLnNlbGVjdEFsbCgnIycgKyBjbGlwSWQpXG4gICAgICAgIC5kYXRhKGNsaXBMaW5lc0ZvckxhYmVscyA/IFswXSA6IFtdKTtcbiAgICBsaW5lQ2xpcC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBsaW5lQ2xpcC5lbnRlcigpLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmxpbmVjbGlwJywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgY2xpcElkKTtcblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChsaW5lQ29udGFpbmVyLCBjbGlwSWQpO1xuXG4gICAgcmV0dXJuIGxpbmVDbGlwO1xufTtcblxuZXhwb3J0cy5sYWJlbEZvcm1hdHRlciA9IGZ1bmN0aW9uKGNvbnRvdXJzLCBjb2xvcmJhciwgZnVsbExheW91dCkge1xuICAgIGlmKGNvbnRvdXJzLmxhYmVsZm9ybWF0KSB7XG4gICAgICAgIHJldHVybiBmdWxsTGF5b3V0Ll9kM2xvY2FsZS5udW1iZXJGb3JtYXQoY29udG91cnMubGFiZWxmb3JtYXQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGZvcm1hdEF4aXM7XG4gICAgICAgIGlmKGNvbG9yYmFyKSB7XG4gICAgICAgICAgICBmb3JtYXRBeGlzID0gY29sb3JiYXIuYXhpcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1hdEF4aXMgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgICAgICAgICAgX2lkOiAneWNvbnRvdXInLFxuICAgICAgICAgICAgICAgIHNob3dleHBvbmVudDogJ2FsbCcsXG4gICAgICAgICAgICAgICAgZXhwb25lbnRmb3JtYXQ6ICdCJ1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYoY29udG91cnMudHlwZSA9PT0gJ2NvbnN0cmFpbnQnKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gY29udG91cnMudmFsdWU7XG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybWF0QXhpcy5yYW5nZSA9IFt2YWx1ZVswXSwgdmFsdWVbdmFsdWUubGVuZ3RoIC0gMV1dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGZvcm1hdEF4aXMucmFuZ2UgPSBbdmFsdWUsIHZhbHVlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvcm1hdEF4aXMucmFuZ2UgPSBbY29udG91cnMuc3RhcnQsIGNvbnRvdXJzLmVuZF07XG4gICAgICAgICAgICAgICAgZm9ybWF0QXhpcy5udGlja3MgPSAoY29udG91cnMuZW5kIC0gY29udG91cnMuc3RhcnQpIC8gY29udG91cnMuc2l6ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZm9ybWF0QXhpcy5yYW5nZVswXSA9PT0gZm9ybWF0QXhpcy5yYW5nZVsxXSkge1xuICAgICAgICAgICAgICAgIGZvcm1hdEF4aXMucmFuZ2VbMV0gKz0gZm9ybWF0QXhpcy5yYW5nZVswXSB8fCAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIWZvcm1hdEF4aXMubnRpY2tzKSBmb3JtYXRBeGlzLm50aWNrcyA9IDEwMDA7XG5cbiAgICAgICAgICAgIHNldENvbnZlcnQoZm9ybWF0QXhpcywgZnVsbExheW91dCk7XG4gICAgICAgICAgICBBeGVzLnByZXBUaWNrcyhmb3JtYXRBeGlzKTtcbiAgICAgICAgICAgIGZvcm1hdEF4aXMuX3RtaW4gPSBudWxsO1xuICAgICAgICAgICAgZm9ybWF0QXhpcy5fdG1heCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiBBeGVzLnRpY2tUZXh0KGZvcm1hdEF4aXMsIHYpLnRleHQ7XG4gICAgICAgIH07XG4gICAgfVxufTtcblxuZXhwb3J0cy5jYWxjVGV4dE9wdHMgPSBmdW5jdGlvbihsZXZlbCwgY29udG91ckZvcm1hdCwgZHVtbXlUZXh0LCBnZCkge1xuICAgIHZhciB0ZXh0ID0gY29udG91ckZvcm1hdChsZXZlbCk7XG4gICAgZHVtbXlUZXh0LnRleHQodGV4dClcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgIHZhciBiQm94ID0gRHJhd2luZy5iQm94KGR1bW15VGV4dC5ub2RlKCksIHRydWUpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgd2lkdGg6IGJCb3gud2lkdGgsXG4gICAgICAgIGhlaWdodDogYkJveC5oZWlnaHQsXG4gICAgICAgIGxldmVsOiBsZXZlbCxcbiAgICAgICAgZHk6IChiQm94LnRvcCArIGJCb3guYm90dG9tKSAvIDJcbiAgICB9O1xufTtcblxuZXhwb3J0cy5maW5kQmVzdFRleHRMb2NhdGlvbiA9IGZ1bmN0aW9uKHBhdGgsIHBhdGhCb3VuZHMsIHRleHRPcHRzLCBsYWJlbERhdGEsIHBsb3RCb3VuZHMpIHtcbiAgICB2YXIgdGV4dFdpZHRoID0gdGV4dE9wdHMud2lkdGg7XG5cbiAgICB2YXIgcDAsIGRwLCBwTWF4LCBwTWluLCBsb2M7XG4gICAgaWYocGF0aEJvdW5kcy5pc0Nsb3NlZCkge1xuICAgICAgICBkcCA9IHBhdGhCb3VuZHMubGVuIC8gY29zdENvbnN0YW50cy5JTklUSUFMU0VBUkNIUE9JTlRTO1xuICAgICAgICBwMCA9IHBhdGhCb3VuZHMubWluICsgZHAgLyAyO1xuICAgICAgICBwTWF4ID0gcGF0aEJvdW5kcy5tYXg7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkcCA9IChwYXRoQm91bmRzLmxlbiAtIHRleHRXaWR0aCkgLyAoY29zdENvbnN0YW50cy5JTklUSUFMU0VBUkNIUE9JTlRTICsgMSk7XG4gICAgICAgIHAwID0gcGF0aEJvdW5kcy5taW4gKyBkcCArIHRleHRXaWR0aCAvIDI7XG4gICAgICAgIHBNYXggPSBwYXRoQm91bmRzLm1heCAtIChkcCArIHRleHRXaWR0aCkgLyAyO1xuICAgIH1cblxuICAgIHZhciBjb3N0ID0gSW5maW5pdHk7XG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGNvc3RDb25zdGFudHMuSVRFUkFUSU9OUzsgaisrKSB7XG4gICAgICAgIGZvcih2YXIgcCA9IHAwOyBwIDwgcE1heDsgcCArPSBkcCkge1xuICAgICAgICAgICAgdmFyIG5ld0xvY2F0aW9uID0gTGliLmdldFRleHRMb2NhdGlvbihwYXRoLCBwYXRoQm91bmRzLnRvdGFsLCBwLCB0ZXh0V2lkdGgpO1xuICAgICAgICAgICAgdmFyIG5ld0Nvc3QgPSBsb2NhdGlvbkNvc3QobmV3TG9jYXRpb24sIHRleHRPcHRzLCBsYWJlbERhdGEsIHBsb3RCb3VuZHMpO1xuICAgICAgICAgICAgaWYobmV3Q29zdCA8IGNvc3QpIHtcbiAgICAgICAgICAgICAgICBjb3N0ID0gbmV3Q29zdDtcbiAgICAgICAgICAgICAgICBsb2MgPSBuZXdMb2NhdGlvbjtcbiAgICAgICAgICAgICAgICBwTWluID0gcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZihjb3N0ID4gY29zdENvbnN0YW50cy5NQVhDT1NUICogMikgYnJlYWs7XG5cbiAgICAgICAgLy8gc3Vic2VxdWVudCBpdGVyYXRpb25zIGp1c3QgbG9vayBoYWxmIHN0ZXBzIGF3YXkgZnJvbSB0aGVcbiAgICAgICAgLy8gYmVzdCB3ZSBmb3VuZCBpbiB0aGUgcHJldmlvdXMgaXRlcmF0aW9uXG4gICAgICAgIGlmKGopIGRwIC89IDI7XG4gICAgICAgIHAwID0gcE1pbiAtIGRwIC8gMjtcbiAgICAgICAgcE1heCA9IHAwICsgZHAgKiAxLjU7XG4gICAgfVxuICAgIGlmKGNvc3QgPD0gY29zdENvbnN0YW50cy5NQVhDT1NUKSByZXR1cm4gbG9jO1xufTtcblxuLypcbiAqIGxvY2F0aW9uQ29zdDogYSBjb3N0IGZ1bmN0aW9uIGZvciBsYWJlbCBsb2NhdGlvbnNcbiAqIGNvbXBvc2VkIG9mIHRocmVlIGtpbmRzIG9mIHBlbmFsdHk6XG4gKiAtIGZvciBvcGVuIHBhdGhzLCBiZWluZyBjbG9zZSB0byB0aGUgZW5kIG9mIHRoZSBwYXRoXG4gKiAtIHRoZSBhbmdsZSBhd2F5IGZyb20gaG9yaXpvbnRhbFxuICogLSBiZWluZyB0b28gY2xvc2UgdG8gYWxyZWFkeSBwbGFjZWQgbmVpZ2hib3JzXG4gKi9cbmZ1bmN0aW9uIGxvY2F0aW9uQ29zdChsb2MsIHRleHRPcHRzLCBsYWJlbERhdGEsIGJvdW5kcykge1xuICAgIHZhciBoYWxmV2lkdGggPSB0ZXh0T3B0cy53aWR0aCAvIDI7XG4gICAgdmFyIGhhbGZIZWlnaHQgPSB0ZXh0T3B0cy5oZWlnaHQgLyAyO1xuICAgIHZhciB4ID0gbG9jLng7XG4gICAgdmFyIHkgPSBsb2MueTtcbiAgICB2YXIgdGhldGEgPSBsb2MudGhldGE7XG4gICAgdmFyIGR4ID0gTWF0aC5jb3ModGhldGEpICogaGFsZldpZHRoO1xuICAgIHZhciBkeSA9IE1hdGguc2luKHRoZXRhKSAqIGhhbGZXaWR0aDtcblxuICAgIC8vIGNvc3QgZm9yIGJlaW5nIG5lYXIgYW4gZWRnZVxuICAgIHZhciBub3JtWCA9ICgoeCA+IGJvdW5kcy5jZW50ZXIpID8gKGJvdW5kcy5yaWdodCAtIHgpIDogKHggLSBib3VuZHMubGVmdCkpIC9cbiAgICAgICAgKGR4ICsgTWF0aC5hYnMoTWF0aC5zaW4odGhldGEpICogaGFsZkhlaWdodCkpO1xuICAgIHZhciBub3JtWSA9ICgoeSA+IGJvdW5kcy5taWRkbGUpID8gKGJvdW5kcy5ib3R0b20gLSB5KSA6ICh5IC0gYm91bmRzLnRvcCkpIC9cbiAgICAgICAgKE1hdGguYWJzKGR5KSArIE1hdGguY29zKHRoZXRhKSAqIGhhbGZIZWlnaHQpO1xuICAgIGlmKG5vcm1YIDwgMSB8fCBub3JtWSA8IDEpIHJldHVybiBJbmZpbml0eTtcbiAgICB2YXIgY29zdCA9IGNvc3RDb25zdGFudHMuRURHRUNPU1QgKiAoMSAvIChub3JtWCAtIDEpICsgMSAvIChub3JtWSAtIDEpKTtcblxuICAgIC8vIGNvc3QgZm9yIG5vdCBiZWluZyBob3Jpem9udGFsXG4gICAgY29zdCArPSBjb3N0Q29uc3RhbnRzLkFOR0xFQ09TVCAqIHRoZXRhICogdGhldGE7XG5cbiAgICAvLyBjb3N0IGZvciBiZWluZyBjbG9zZSB0byBvdGhlciBsYWJlbHNcbiAgICB2YXIgeDEgPSB4IC0gZHg7XG4gICAgdmFyIHkxID0geSAtIGR5O1xuICAgIHZhciB4MiA9IHggKyBkeDtcbiAgICB2YXIgeTIgPSB5ICsgZHk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxhYmVsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGFiZWxpID0gbGFiZWxEYXRhW2ldO1xuICAgICAgICB2YXIgZHhkID0gTWF0aC5jb3MobGFiZWxpLnRoZXRhKSAqIGxhYmVsaS53aWR0aCAvIDI7XG4gICAgICAgIHZhciBkeWQgPSBNYXRoLnNpbihsYWJlbGkudGhldGEpICogbGFiZWxpLndpZHRoIC8gMjtcbiAgICAgICAgdmFyIGRpc3QgPSBMaWIuc2VnbWVudERpc3RhbmNlKFxuICAgICAgICAgICAgeDEsIHkxLFxuICAgICAgICAgICAgeDIsIHkyLFxuICAgICAgICAgICAgbGFiZWxpLnggLSBkeGQsIGxhYmVsaS55IC0gZHlkLFxuICAgICAgICAgICAgbGFiZWxpLnggKyBkeGQsIGxhYmVsaS55ICsgZHlkXG4gICAgICAgICkgKiAyIC8gKHRleHRPcHRzLmhlaWdodCArIGxhYmVsaS5oZWlnaHQpO1xuXG4gICAgICAgIHZhciBzYW1lTGV2ZWwgPSBsYWJlbGkubGV2ZWwgPT09IHRleHRPcHRzLmxldmVsO1xuICAgICAgICB2YXIgZGlzdE9mZnNldCA9IHNhbWVMZXZlbCA/IGNvc3RDb25zdGFudHMuU0FNRUxFVkVMRElTVEFOQ0UgOiAxO1xuXG4gICAgICAgIGlmKGRpc3QgPD0gZGlzdE9mZnNldCkgcmV0dXJuIEluZmluaXR5O1xuXG4gICAgICAgIHZhciBkaXN0RmFjdG9yID0gY29zdENvbnN0YW50cy5ORUlHSEJPUkNPU1QgKlxuICAgICAgICAgICAgKHNhbWVMZXZlbCA/IGNvc3RDb25zdGFudHMuU0FNRUxFVkVMRkFDVE9SIDogMSk7XG5cbiAgICAgICAgY29zdCArPSBkaXN0RmFjdG9yIC8gKGRpc3QgLSBkaXN0T2Zmc2V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29zdDtcbn1cblxuZXhwb3J0cy5hZGRMYWJlbERhdGEgPSBmdW5jdGlvbihsb2MsIHRleHRPcHRzLCBsYWJlbERhdGEsIGxhYmVsQ2xpcFBhdGhEYXRhKSB7XG4gICAgdmFyIGhhbGZXaWR0aCA9IHRleHRPcHRzLndpZHRoIC8gMjtcbiAgICB2YXIgaGFsZkhlaWdodCA9IHRleHRPcHRzLmhlaWdodCAvIDI7XG5cbiAgICB2YXIgeCA9IGxvYy54O1xuICAgIHZhciB5ID0gbG9jLnk7XG4gICAgdmFyIHRoZXRhID0gbG9jLnRoZXRhO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKHRoZXRhKTtcbiAgICB2YXIgY29zID0gTWF0aC5jb3ModGhldGEpO1xuICAgIHZhciBkeHcgPSBoYWxmV2lkdGggKiBjb3M7XG4gICAgdmFyIGR4aCA9IGhhbGZIZWlnaHQgKiBzaW47XG4gICAgdmFyIGR5dyA9IGhhbGZXaWR0aCAqIHNpbjtcbiAgICB2YXIgZHloID0gLWhhbGZIZWlnaHQgKiBjb3M7XG4gICAgdmFyIGJCb3hQdHMgPSBbXG4gICAgICAgIFt4IC0gZHh3IC0gZHhoLCB5IC0gZHl3IC0gZHloXSxcbiAgICAgICAgW3ggKyBkeHcgLSBkeGgsIHkgKyBkeXcgLSBkeWhdLFxuICAgICAgICBbeCArIGR4dyArIGR4aCwgeSArIGR5dyArIGR5aF0sXG4gICAgICAgIFt4IC0gZHh3ICsgZHhoLCB5IC0gZHl3ICsgZHloXSxcbiAgICBdO1xuXG4gICAgbGFiZWxEYXRhLnB1c2goe1xuICAgICAgICB0ZXh0OiB0ZXh0T3B0cy50ZXh0LFxuICAgICAgICB4OiB4LFxuICAgICAgICB5OiB5LFxuICAgICAgICBkeTogdGV4dE9wdHMuZHksXG4gICAgICAgIHRoZXRhOiB0aGV0YSxcbiAgICAgICAgbGV2ZWw6IHRleHRPcHRzLmxldmVsLFxuICAgICAgICB3aWR0aDogdGV4dE9wdHMud2lkdGgsXG4gICAgICAgIGhlaWdodDogdGV4dE9wdHMuaGVpZ2h0XG4gICAgfSk7XG5cbiAgICBsYWJlbENsaXBQYXRoRGF0YS5wdXNoKGJCb3hQdHMpO1xufTtcblxuZXhwb3J0cy5kcmF3TGFiZWxzID0gZnVuY3Rpb24obGFiZWxHcm91cCwgbGFiZWxEYXRhLCBnZCwgbGluZUNsaXAsIGxhYmVsQ2xpcFBhdGhEYXRhKSB7XG4gICAgdmFyIGxhYmVscyA9IGxhYmVsR3JvdXAuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgLmRhdGEobGFiZWxEYXRhLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC50ZXh0ICsgJywnICsgZC54ICsgJywnICsgZC55ICsgJywnICsgZC50aGV0YTtcbiAgICAgICAgfSk7XG5cbiAgICBsYWJlbHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGFiZWxzLmVudGVyKCkuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxLFxuICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHggPSBkLnggKyBNYXRoLnNpbihkLnRoZXRhKSAqIGQuZHk7XG4gICAgICAgICAgICB2YXIgeSA9IGQueSAtIE1hdGguY29zKGQudGhldGEpICogZC5keTtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgIC50ZXh0KGQudGV4dClcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICAgICAgICAgIHk6IHksXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3JvdGF0ZSgnICsgKDE4MCAqIGQudGhldGEgLyBNYXRoLlBJKSArICcgJyArIHggKyAnICcgKyB5ICsgJyknXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG4gICAgICAgIH0pO1xuXG4gICAgaWYobGFiZWxDbGlwUGF0aERhdGEpIHtcbiAgICAgICAgdmFyIGNsaXBQYXRoID0gJyc7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsYWJlbENsaXBQYXRoRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2xpcFBhdGggKz0gJ00nICsgbGFiZWxDbGlwUGF0aERhdGFbaV0uam9pbignTCcpICsgJ1onO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpbmVDbGlwUGF0aCA9IExpYi5lbnN1cmVTaW5nbGUobGluZUNsaXAsICdwYXRoJywgJycpO1xuICAgICAgICBsaW5lQ2xpcFBhdGguYXR0cignZCcsIGNsaXBQYXRoKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjbGlwR2FwcyhwbG90R3JvdXAsIHBsb3RpbmZvLCBjbGlwcywgY2QwLCBwZXJpbWV0ZXIpIHtcbiAgICB2YXIgY2xpcElkID0gJ2NsaXAnICsgY2QwLnRyYWNlLnVpZDtcblxuICAgIHZhciBjbGlwUGF0aCA9IGNsaXBzLnNlbGVjdEFsbCgnIycgKyBjbGlwSWQpXG4gICAgICAgIC5kYXRhKGNkMC50cmFjZS5jb25uZWN0Z2FwcyA/IFtdIDogWzBdKTtcbiAgICBjbGlwUGF0aC5lbnRlcigpLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmNsaXAnLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBjbGlwSWQpO1xuICAgIGNsaXBQYXRoLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGlmKGNkMC50cmFjZS5jb25uZWN0Z2FwcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgdmFyIGNsaXBQYXRoSW5mbyA9IHtcbiAgICAgICAgICAgIC8vIGZyYWN0aW9uIG9mIHRoZSB3YXkgZnJvbSBtaXNzaW5nIHRvIHByZXNlbnQgcG9pbnRcbiAgICAgICAgICAgIC8vIHRvIGRyYXcgdGhlIGJvdW5kYXJ5LlxuICAgICAgICAgICAgLy8gaWYgeW91IG1ha2UgdGhpcyAxIChvciAxLWVwc2lsb24pIHRoZW4gYSBwb2ludCBpblxuICAgICAgICAgICAgLy8gYSBzZWEgb2YgbWlzc2luZyBkYXRhIHdpbGwgZGlzYXBwZWFyIGVudGlyZWx5LlxuICAgICAgICAgICAgbGV2ZWw6IDAuOSxcbiAgICAgICAgICAgIGNyb3NzaW5nczoge30sXG4gICAgICAgICAgICBzdGFydHM6IFtdLFxuICAgICAgICAgICAgZWRnZXBhdGhzOiBbXSxcbiAgICAgICAgICAgIHBhdGhzOiBbXSxcbiAgICAgICAgICAgIHhheGlzOiBwbG90aW5mby54YXhpcyxcbiAgICAgICAgICAgIHlheGlzOiBwbG90aW5mby55YXhpcyxcbiAgICAgICAgICAgIHg6IGNkMC54LFxuICAgICAgICAgICAgeTogY2QwLnksXG4gICAgICAgICAgICAvLyAwID0gbm8gZGF0YSwgMSA9IGRhdGFcbiAgICAgICAgICAgIHo6IG1ha2VDbGlwTWFzayhjZDApLFxuICAgICAgICAgICAgc21vb3RoaW5nOiAwXG4gICAgICAgIH07XG5cbiAgICAgICAgbWFrZUNyb3NzaW5ncyhbY2xpcFBhdGhJbmZvXSk7XG4gICAgICAgIGZpbmRBbGxQYXRocyhbY2xpcFBhdGhJbmZvXSk7XG4gICAgICAgIHZhciBmdWxscGF0aCA9IGpvaW5BbGxQYXRocyhjbGlwUGF0aEluZm8sIHBlcmltZXRlcik7XG5cbiAgICAgICAgdmFyIHBhdGggPSBMaWIuZW5zdXJlU2luZ2xlKGNsaXBQYXRoLCAncGF0aCcsICcnKTtcbiAgICAgICAgcGF0aC5hdHRyKCdkJywgZnVsbHBhdGgpO1xuICAgIH1cbiAgICBlbHNlIGNsaXBJZCA9IG51bGw7XG5cbiAgICBwbG90R3JvdXAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGNsaXBJZCk7XG59XG5cbmZ1bmN0aW9uIG1ha2VDbGlwTWFzayhjZDApIHtcbiAgICB2YXIgZW1wdGllcyA9IGNkMC50cmFjZS5fZW1wdHlwb2ludHMsXG4gICAgICAgIHogPSBbXSxcbiAgICAgICAgbSA9IGNkMC56Lmxlbmd0aCxcbiAgICAgICAgbiA9IGNkMC56WzBdLmxlbmd0aCxcbiAgICAgICAgaSxcbiAgICAgICAgcm93ID0gW10sXG4gICAgICAgIGVtcHR5UG9pbnQ7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBuOyBpKyspIHJvdy5wdXNoKDEpO1xuICAgIGZvcihpID0gMDsgaSA8IG07IGkrKykgei5wdXNoKHJvdy5zbGljZSgpKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBlbXB0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVtcHR5UG9pbnQgPSBlbXB0aWVzW2ldO1xuICAgICAgICB6W2VtcHR5UG9pbnRbMF1dW2VtcHR5UG9pbnRbMV1dID0gMDtcbiAgICB9XG4gICAgLy8gc2F2ZSB0aGlzIG1hc2sgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdG8gc2hvdyB0aGlzIGRhdGEgaW4gaG92ZXJcbiAgICBjZDAuem1hc2sgPSB6O1xuICAgIHJldHVybiB6O1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNldENvbnRvdXJzKHRyYWNlKSB7XG4gICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG5cbiAgICAvLyBjaGVjayBpZiB3ZSBuZWVkIHRvIGF1dG8tY2hvb3NlIGNvbnRvdXIgbGV2ZWxzXG4gICAgaWYodHJhY2UuYXV0b2NvbnRvdXIpIHtcbiAgICAgICAgdmFyIHptaW4gPSB0cmFjZS56bWluO1xuICAgICAgICB2YXIgem1heCA9IHRyYWNlLnptYXg7XG4gICAgICAgIGlmKHptaW4gPT09IHVuZGVmaW5lZCB8fCB6bWF4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHptaW4gPSBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgdHJhY2UuX3opO1xuICAgICAgICAgICAgem1heCA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCB0cmFjZS5feik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGR1bW15QXggPSBhdXRvQ29udG91cnMoem1pbiwgem1heCwgdHJhY2UubmNvbnRvdXJzKTtcblxuICAgICAgICBjb250b3Vycy5zaXplID0gZHVtbXlBeC5kdGljaztcblxuICAgICAgICBjb250b3Vycy5zdGFydCA9IEF4ZXMudGlja0ZpcnN0KGR1bW15QXgpO1xuICAgICAgICBkdW1teUF4LnJhbmdlLnJldmVyc2UoKTtcbiAgICAgICAgY29udG91cnMuZW5kID0gQXhlcy50aWNrRmlyc3QoZHVtbXlBeCk7XG5cbiAgICAgICAgaWYoY29udG91cnMuc3RhcnQgPT09IHptaW4pIGNvbnRvdXJzLnN0YXJ0ICs9IGNvbnRvdXJzLnNpemU7XG4gICAgICAgIGlmKGNvbnRvdXJzLmVuZCA9PT0gem1heCkgY29udG91cnMuZW5kIC09IGNvbnRvdXJzLnNpemU7XG5cbiAgICAgICAgLy8gaWYgeW91IHNldCBhIHNtYWxsIG5jb250b3VycywgKmFuZCogdGhlIGVuZHMgYXJlIGV4YWN0bHkgb24gem1pbi96bWF4XG4gICAgICAgIC8vIHRoZXJlJ3MgYW4gZWRnZSBjYXNlIHdoZXJlIHN0YXJ0ID4gZW5kIG5vdy4gTWFrZSBzdXJlIHRoZXJlJ3MgYXQgbGVhc3RcbiAgICAgICAgLy8gb25lIG1lYW5pbmdmdWwgY29udG91ciwgcHV0IGl0IG1pZHdheSBiZXR3ZWVuIHRoZSBjcm9zc2VkIHZhbHVlc1xuICAgICAgICBpZihjb250b3Vycy5zdGFydCA+IGNvbnRvdXJzLmVuZCkge1xuICAgICAgICAgICAgY29udG91cnMuc3RhcnQgPSBjb250b3Vycy5lbmQgPSAoY29udG91cnMuc3RhcnQgKyBjb250b3Vycy5lbmQpIC8gMjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvcHkgYXV0by1jb250b3VyIGluZm8gYmFjayB0byB0aGUgc291cmNlIGRhdGEuXG4gICAgICAgIC8vIHByZXZpb3VzbHkgd2UgY29waWVkIHRoZSB3aG9sZSBjb250b3VycyBvYmplY3QgYmFjaywgYnV0IHRoYXQgaGFkXG4gICAgICAgIC8vIG90aGVyIGluZm8gKGNvbG9yaW5nLCBzaG93bGluZXMpIHRoYXQgc2hvdWxkIGJlIGxlZnQgdG8gc3VwcGx5RGVmYXVsdHNcbiAgICAgICAgaWYoIXRyYWNlLl9pbnB1dC5jb250b3VycykgdHJhY2UuX2lucHV0LmNvbnRvdXJzID0ge307XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHRyYWNlLl9pbnB1dC5jb250b3Vycywge1xuICAgICAgICAgICAgc3RhcnQ6IGNvbnRvdXJzLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBjb250b3Vycy5lbmQsXG4gICAgICAgICAgICBzaXplOiBjb250b3Vycy5zaXplXG4gICAgICAgIH0pO1xuICAgICAgICB0cmFjZS5faW5wdXQuYXV0b2NvbnRvdXIgPSB0cnVlO1xuICAgIH1cbiAgICBlbHNlIGlmKGNvbnRvdXJzLnR5cGUgIT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAvLyBzYW5pdHkgY2hlY2tzIG9uIG1hbnVhbGx5LXN1cHBsaWVkIHN0YXJ0L2VuZC9zaXplXG4gICAgICAgIHZhciBzdGFydCA9IGNvbnRvdXJzLnN0YXJ0LFxuICAgICAgICAgICAgZW5kID0gY29udG91cnMuZW5kLFxuICAgICAgICAgICAgaW5wdXRDb250b3VycyA9IHRyYWNlLl9pbnB1dC5jb250b3VycztcblxuICAgICAgICBpZihzdGFydCA+IGVuZCkge1xuICAgICAgICAgICAgY29udG91cnMuc3RhcnQgPSBpbnB1dENvbnRvdXJzLnN0YXJ0ID0gZW5kO1xuICAgICAgICAgICAgZW5kID0gY29udG91cnMuZW5kID0gaW5wdXRDb250b3Vycy5lbmQgPSBzdGFydDtcbiAgICAgICAgICAgIHN0YXJ0ID0gY29udG91cnMuc3RhcnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZighKGNvbnRvdXJzLnNpemUgPiAwKSkge1xuICAgICAgICAgICAgdmFyIHNpemVPdXQ7XG4gICAgICAgICAgICBpZihzdGFydCA9PT0gZW5kKSBzaXplT3V0ID0gMTtcbiAgICAgICAgICAgIGVsc2Ugc2l6ZU91dCA9IGF1dG9Db250b3VycyhzdGFydCwgZW5kLCB0cmFjZS5uY29udG91cnMpLmR0aWNrO1xuXG4gICAgICAgICAgICBpbnB1dENvbnRvdXJzLnNpemUgPSBjb250b3Vycy5zaXplID0gc2l6ZU91dDtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cblxuLypcbiAqIGF1dG9Db250b3VyczogbWFrZSBhIGR1bW15IGF4aXMgb2JqZWN0IHdpdGggZHRpY2sgd2UgY2FuIHVzZVxuICogYXMgY29udG91cnMuc2l6ZSwgYW5kIGlmIG5lZWRlZCB3ZSBjYW4gdXNlIEF4ZXMudGlja0ZpcnN0XG4gKiB3aXRoIHRoaXMgYXhpcyBvYmplY3QgdG8gY2FsY3VsYXRlIHRoZSBzdGFydCBhbmQgZW5kIHRvb1xuICpcbiAqIHN0YXJ0OiB0aGUgdmFsdWUgdG8gc3RhcnQgdGhlIGNvbnRvdXJzIGF0XG4gKiBlbmQ6IHRoZSB2YWx1ZSB0byBlbmQgYXQgKG11c3QgYmUgPiBzdGFydClcbiAqIG5jb250b3VyczogbWF4IG51bWJlciBvZiBjb250b3VycyB0byBtYWtlLCBsaWtlIHJvdWdoRFRpY2tcbiAqXG4gKiByZXR1cm5zOiBhbiBheGlzIG9iamVjdFxuICovXG5mdW5jdGlvbiBhdXRvQ29udG91cnMoc3RhcnQsIGVuZCwgbmNvbnRvdXJzKSB7XG4gICAgdmFyIGR1bW15QXggPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogW3N0YXJ0LCBlbmRdXG4gICAgfTtcblxuICAgIEF4ZXMuYXV0b1RpY2tzKFxuICAgICAgICBkdW1teUF4LFxuICAgICAgICAoZW5kIC0gc3RhcnQpIC8gKG5jb250b3VycyB8fCAxNSlcbiAgICApO1xuXG4gICAgcmV0dXJuIGR1bW15QXg7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBoZWF0bWFwU3R5bGUgPSByZXF1aXJlKCcuLi9oZWF0bWFwL3N0eWxlJyk7XG5cbnZhciBtYWtlQ29sb3JNYXAgPSByZXF1aXJlKCcuL21ha2VfY29sb3JfbWFwJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCkge1xuICAgIHZhciBjb250b3VycyA9IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLmNvbnRvdXInKTtcblxuICAgIGNvbnRvdXJzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5O1xuICAgIH0pO1xuXG4gICAgY29udG91cnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBjID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICB2YXIgY29udG91cnMgPSB0cmFjZS5jb250b3VycztcbiAgICAgICAgdmFyIGxpbmUgPSB0cmFjZS5saW5lO1xuICAgICAgICB2YXIgY3MgPSBjb250b3Vycy5zaXplIHx8IDE7XG4gICAgICAgIHZhciBzdGFydCA9IGNvbnRvdXJzLnN0YXJ0O1xuXG4gICAgICAgIC8vIGZvciBjb250b3VyY2FycGV0IG9ubHkgLSBpcyB0aGlzIGEgY29uc3RyYWludC10eXBlIGNvbnRvdXIgdHJhY2U/XG4gICAgICAgIHZhciBpc0NvbnN0cmFpbnRUeXBlID0gY29udG91cnMudHlwZSA9PT0gJ2NvbnN0cmFpbnQnO1xuICAgICAgICB2YXIgY29sb3JMaW5lcyA9ICFpc0NvbnN0cmFpbnRUeXBlICYmIGNvbnRvdXJzLmNvbG9yaW5nID09PSAnbGluZXMnO1xuICAgICAgICB2YXIgY29sb3JGaWxscyA9ICFpc0NvbnN0cmFpbnRUeXBlICYmIGNvbnRvdXJzLmNvbG9yaW5nID09PSAnZmlsbCc7XG5cbiAgICAgICAgdmFyIGNvbG9yTWFwID0gKGNvbG9yTGluZXMgfHwgY29sb3JGaWxscykgPyBtYWtlQ29sb3JNYXAodHJhY2UpIDogbnVsbDtcblxuICAgICAgICBjLnNlbGVjdEFsbCgnZy5jb250b3VybGV2ZWwnKS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcubGluZUdyb3VwU3R5bGUsXG4gICAgICAgICAgICAgICAgICAgIGxpbmUud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yTGluZXMgPyBjb2xvck1hcChkLmxldmVsKSA6IGxpbmUuY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGxpbmUuZGFzaCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBsYWJlbEZvbnQgPSBjb250b3Vycy5sYWJlbGZvbnQ7XG4gICAgICAgIGMuc2VsZWN0QWxsKCdnLmNvbnRvdXJsYWJlbHMgdGV4dCcpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgRHJhd2luZy5mb250KGQzLnNlbGVjdCh0aGlzKSwge1xuICAgICAgICAgICAgICAgIGZhbWlseTogbGFiZWxGb250LmZhbWlseSxcbiAgICAgICAgICAgICAgICBzaXplOiBsYWJlbEZvbnQuc2l6ZSxcbiAgICAgICAgICAgICAgICBjb2xvcjogbGFiZWxGb250LmNvbG9yIHx8IChjb2xvckxpbmVzID8gY29sb3JNYXAoZC5sZXZlbCkgOiBsaW5lLmNvbG9yKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGlzQ29uc3RyYWludFR5cGUpIHtcbiAgICAgICAgICAgIGMuc2VsZWN0QWxsKCdnLmNvbnRvdXJmaWxsIHBhdGgnKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnZmlsbCcsIHRyYWNlLmZpbGxjb2xvcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb2xvckZpbGxzKSB7XG4gICAgICAgICAgICB2YXIgZmlyc3RGaWxsO1xuXG4gICAgICAgICAgICBjLnNlbGVjdEFsbCgnZy5jb250b3VyZmlsbCBwYXRoJylcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGZpcnN0RmlsbCA9PT0gdW5kZWZpbmVkKSBmaXJzdEZpbGwgPSBkLmxldmVsO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sb3JNYXAoZC5sZXZlbCArIDAuNSAqIGNzKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYoZmlyc3RGaWxsID09PSB1bmRlZmluZWQpIGZpcnN0RmlsbCA9IHN0YXJ0O1xuXG4gICAgICAgICAgICBjLnNlbGVjdEFsbCgnZy5jb250b3VyYmcgcGF0aCcpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgY29sb3JNYXAoZmlyc3RGaWxsIC0gMC41ICogY3MpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaGVhdG1hcFN0eWxlKGdkKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuL2xhYmVsX2RlZmF1bHRzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCwgb3B0cykge1xuICAgIHZhciBjb2xvcmluZyA9IGNvZXJjZSgnY29udG91cnMuY29sb3JpbmcnKTtcblxuICAgIHZhciBzaG93TGluZXM7XG4gICAgdmFyIGxpbmVDb2xvciA9ICcnO1xuICAgIGlmKGNvbG9yaW5nID09PSAnZmlsbCcpIHNob3dMaW5lcyA9IGNvZXJjZSgnY29udG91cnMuc2hvd2xpbmVzJyk7XG5cbiAgICBpZihzaG93TGluZXMgIT09IGZhbHNlKSB7XG4gICAgICAgIGlmKGNvbG9yaW5nICE9PSAnbGluZXMnKSBsaW5lQ29sb3IgPSBjb2VyY2UoJ2xpbmUuY29sb3InLCAnIzAwMCcpO1xuICAgICAgICBjb2VyY2UoJ2xpbmUud2lkdGgnLCAwLjUpO1xuICAgICAgICBjb2VyY2UoJ2xpbmUuZGFzaCcpO1xuICAgIH1cblxuICAgIGlmKGNvbG9yaW5nICE9PSAnbm9uZScpIHtcbiAgICAgICAgLy8gcGxvdHMvcGxvdHMgYWx3YXlzIGNvZXJjZXMgc2hvd2xlZ2VuZCB0byB0cnVlLCBidXQgaW4gdGhpcyBjYXNlXG4gICAgICAgIC8vIHdlIGRlZmF1bHQgdG8gZmFsc2UgYW5kIChieSBkZWZhdWx0KSBzaG93IGEgY29sb3JiYXIgaW5zdGVhZFxuICAgICAgICBpZih0cmFjZUluLnNob3dsZWdlbmQgIT09IHRydWUpIHRyYWNlT3V0LnNob3dsZWdlbmQgPSBmYWxzZTtcbiAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gZmFsc2U7XG5cbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKFxuICAgICAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGluZS5zbW9vdGhpbmcnKTtcblxuICAgIGhhbmRsZUxhYmVsRGVmYXVsdHMoY29lcmNlLCBsYXlvdXQsIGxpbmVDb2xvciwgb3B0cyk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVhdG1hcEF0dHJzID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgY29udG91ckF0dHJzID0gcmVxdWlyZSgnLi4vY29udG91ci9hdHRyaWJ1dGVzJyk7XG52YXIgY29udG91ckNvbnRvdXJBdHRycyA9IGNvbnRvdXJBdHRycy5jb250b3VycztcbnZhciBzY2F0dGVyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcnNjYWxlQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yYmFyQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICBjYXJwZXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHo6IGhlYXRtYXBBdHRycy56LFxuICAgIGE6IGhlYXRtYXBBdHRycy54LFxuICAgIGEwOiBoZWF0bWFwQXR0cnMueDAsXG4gICAgZGE6IGhlYXRtYXBBdHRycy5keCxcbiAgICBiOiBoZWF0bWFwQXR0cnMueSxcbiAgICBiMDogaGVhdG1hcEF0dHJzLnkwLFxuICAgIGRiOiBoZWF0bWFwQXR0cnMuZHksXG4gICAgdGV4dDogaGVhdG1hcEF0dHJzLnRleHQsXG4gICAgdHJhbnNwb3NlOiBoZWF0bWFwQXR0cnMudHJhbnNwb3NlLFxuICAgIGF0eXBlOiBoZWF0bWFwQXR0cnMueHR5cGUsXG4gICAgYnR5cGU6IGhlYXRtYXBBdHRycy55dHlwZSxcblxuICAgIGZpbGxjb2xvcjogY29udG91ckF0dHJzLmZpbGxjb2xvcixcblxuICAgIGF1dG9jb250b3VyOiBjb250b3VyQXR0cnMuYXV0b2NvbnRvdXIsXG4gICAgbmNvbnRvdXJzOiBjb250b3VyQXR0cnMubmNvbnRvdXJzLFxuXG4gICAgY29udG91cnM6IHtcbiAgICAgICAgdHlwZTogY29udG91ckNvbnRvdXJBdHRycy50eXBlLFxuICAgICAgICBzdGFydDogY29udG91ckNvbnRvdXJBdHRycy5zdGFydCxcbiAgICAgICAgZW5kOiBjb250b3VyQ29udG91ckF0dHJzLmVuZCxcbiAgICAgICAgc2l6ZTogY29udG91ckNvbnRvdXJBdHRycy5zaXplLFxuICAgICAgICBjb2xvcmluZzoge1xuICAgICAgICAgICAgLy8gZnJvbSBjb250b3VyQXR0cnMuY29udG91cnMuY29sb3JpbmcgYnV0IG5vICdoZWF0bWFwJyBvcHRpb25cbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydmaWxsJywgJ2xpbmVzJywgJ25vbmUnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdmaWxsJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaG93bGluZXM6IGNvbnRvdXJDb250b3VyQXR0cnMuc2hvd2xpbmVzLFxuICAgICAgICBzaG93bGFiZWxzOiBjb250b3VyQ29udG91ckF0dHJzLnNob3dsYWJlbHMsXG4gICAgICAgIGxhYmVsZm9udDogY29udG91ckNvbnRvdXJBdHRycy5sYWJlbGZvbnQsXG4gICAgICAgIGxhYmVsZm9ybWF0OiBjb250b3VyQ29udG91ckF0dHJzLmxhYmVsZm9ybWF0LFxuICAgICAgICBvcGVyYXRpb246IGNvbnRvdXJDb250b3VyQXR0cnMub3BlcmF0aW9uLFxuICAgICAgICB2YWx1ZTogY29udG91ckNvbnRvdXJBdHRycy52YWx1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7J2F1dG9jb250b3VyJzogZmFsc2V9XG4gICAgfSxcblxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgd2lkdGg6IHNjYXR0ZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgIGRhc2g6IHNjYXR0ZXJMaW5lQXR0cnMuZGFzaCxcbiAgICAgICAgc21vb3RoaW5nOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLnNtb290aGluZywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICB0cmFuc2Zvcm1zOiB1bmRlZmluZWRcbn0sXG5cbiAgICBjb2xvcnNjYWxlQXR0cnMoJycsIHtcbiAgICAgICAgY0xldHRlcjogJ3onLFxuICAgICAgICBhdXRvQ29sb3JEZmx0OiBmYWxzZVxuICAgIH0pLFxuICAgIHsgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMgfVxuKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcbnZhciBpc0FycmF5MUQgPSByZXF1aXJlKCcuLi8uLi9saWInKS5pc0FycmF5MUQ7XG5cbnZhciBjb252ZXJ0Q29sdW1uRGF0YSA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvY29udmVydF9jb2x1bW5feHl6Jyk7XG52YXIgY2xlYW4yZEFycmF5ID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9jbGVhbl8yZF9hcnJheScpO1xudmFyIG1heFJvd0xlbmd0aCA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvbWF4X3Jvd19sZW5ndGgnKTtcbnZhciBpbnRlcnAyZCA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvaW50ZXJwMmQnKTtcbnZhciBmaW5kRW1wdGllcyA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvZmluZF9lbXB0aWVzJyk7XG52YXIgbWFrZUJvdW5kQXJyYXkgPSByZXF1aXJlKCcuLi9oZWF0bWFwL21ha2VfYm91bmRfYXJyYXknKTtcbnZhciBzdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbnZhciBsb29rdXBDYXJwZXQgPSByZXF1aXJlKCcuLi9jYXJwZXQvbG9va3VwX2NhcnBldGlkJyk7XG52YXIgc2V0Q29udG91cnMgPSByZXF1aXJlKCcuLi9jb250b3VyL3NldF9jb250b3VycycpO1xuXG4vLyBtb3N0IGlzIHRoZSBzYW1lIGFzIGhlYXRtYXAgY2FsYywgdGhlbiBhZGp1c3QgaXRcbi8vIHRob3VnaCBhIGZldyB0aGluZ3MgaW5zaWRlIGhlYXRtYXAgY2FsYyBzdGlsbCBsb29rIGZvclxuLy8gY29udG91ciBtYXBzLCBiZWNhdXNlIHRoZSBtYWtlQm91bmRBcnJheSBjYWxscyBhcmUgdG9vIGVudGFuZ2xlZFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBjYXJwZXQgPSB0cmFjZS5fY2FycGV0VHJhY2UgPSBsb29rdXBDYXJwZXQoZ2QsIHRyYWNlKTtcbiAgICBpZighY2FycGV0IHx8ICFjYXJwZXQudmlzaWJsZSB8fCBjYXJwZXQudmlzaWJsZSA9PT0gJ2xlZ2VuZG9ubHknKSByZXR1cm47XG5cbiAgICBpZighdHJhY2UuYSB8fCAhdHJhY2UuYikge1xuICAgICAgICAvLyBMb29rIHVwIHRoZSBvcmlnaW5hbCBpbmNvbWluZyBjYXJwZXQgZGF0YTpcbiAgICAgICAgdmFyIGNhcnBldGRhdGEgPSBnZC5kYXRhW2NhcnBldC5pbmRleF07XG5cbiAgICAgICAgLy8gTG9vayB1cCB0aGUgaW5jb21pbmcgdHJhY2UgZGF0YSwgKmV4Y2VwdCogcGVyZm9ybSBhIHNoYWxsb3dcbiAgICAgICAgLy8gY29weSBzbyB0aGF0IHdlJ3JlIG5vdCBhY3R1YWxseSBtb2RpZnlpbmcgaXQgd2hlbiB3ZSB1c2UgaXRcbiAgICAgICAgLy8gdG8gc3VwcGx5IGRlZmF1bHRzOlxuICAgICAgICB2YXIgdHJhY2VkYXRhID0gZ2QuZGF0YVt0cmFjZS5pbmRleF07XG4gICAgICAgIC8vIHZhciB0cmFjZWRhdGEgPSBleHRlbmRGbGF0KHt9LCBnZC5kYXRhW3RyYWNlLmluZGV4XSk7XG5cbiAgICAgICAgLy8gSWYgdGhlIGRhdGEgaXMgbm90IHNwZWNpZmllZFxuICAgICAgICBpZighdHJhY2VkYXRhLmEpIHRyYWNlZGF0YS5hID0gY2FycGV0ZGF0YS5hO1xuICAgICAgICBpZighdHJhY2VkYXRhLmIpIHRyYWNlZGF0YS5iID0gY2FycGV0ZGF0YS5iO1xuXG4gICAgICAgIHN1cHBseURlZmF1bHRzKHRyYWNlZGF0YSwgdHJhY2UsIHRyYWNlLl9kZWZhdWx0Q29sb3IsIGdkLl9mdWxsTGF5b3V0KTtcbiAgICB9XG5cbiAgICB2YXIgY2QgPSBoZWF0bWFwcGlzaENhbGMoZ2QsIHRyYWNlKTtcblxuICAgIHNldENvbnRvdXJzKHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG5cbmZ1bmN0aW9uIGhlYXRtYXBwaXNoQ2FsYyhnZCwgdHJhY2UpIHtcbiAgICAvLyBwcmVwYXJlIHRoZSByYXcgZGF0YVxuICAgIC8vIHJ1biBtYWtlQ2FsY2RhdGEgb24geCBhbmQgeSBldmVuIGZvciBoZWF0bWFwcywgaW4gY2FzZSBvZiBjYXRlZ29yeSBtYXBwaW5nc1xuICAgIHZhciBjYXJwZXQgPSB0cmFjZS5fY2FycGV0VHJhY2U7XG4gICAgdmFyIGFheCA9IGNhcnBldC5hYXhpcztcbiAgICB2YXIgYmF4ID0gY2FycGV0LmJheGlzO1xuICAgIHZhciBhLFxuICAgICAgICBhMCxcbiAgICAgICAgZGEsXG4gICAgICAgIGIsXG4gICAgICAgIGIwLFxuICAgICAgICBkYixcbiAgICAgICAgejtcblxuICAgIC8vIGNhbmNlbCBtaW5pbXVtIHRpY2sgc3BhY2luZ3MgKG9ubHkgYXBwbGllcyB0byBiYXJzIGFuZCBib3hlcylcbiAgICBhYXguX21pbkR0aWNrID0gMDtcbiAgICBiYXguX21pbkR0aWNrID0gMDtcblxuICAgIGlmKGlzQXJyYXkxRCh0cmFjZS56KSkgY29udmVydENvbHVtbkRhdGEodHJhY2UsIGFheCwgYmF4LCAnYScsICdiJywgWyd6J10pO1xuICAgIGEgPSB0cmFjZS5fYSA9IHRyYWNlLl9hIHx8IHRyYWNlLmE7XG4gICAgYiA9IHRyYWNlLl9iID0gdHJhY2UuX2IgfHwgdHJhY2UuYjtcblxuICAgIGEgPSBhID8gYWF4Lm1ha2VDYWxjZGF0YSh0cmFjZSwgJ19hJykgOiBbXTtcbiAgICBiID0gYiA/IGJheC5tYWtlQ2FsY2RhdGEodHJhY2UsICdfYicpIDogW107XG4gICAgYTAgPSB0cmFjZS5hMCB8fCAwO1xuICAgIGRhID0gdHJhY2UuZGEgfHwgMTtcbiAgICBiMCA9IHRyYWNlLmIwIHx8IDA7XG4gICAgZGIgPSB0cmFjZS5kYiB8fCAxO1xuXG4gICAgeiA9IHRyYWNlLl96ID0gY2xlYW4yZEFycmF5KHRyYWNlLl96IHx8IHRyYWNlLnosIHRyYWNlLnRyYW5zcG9zZSk7XG5cbiAgICB0cmFjZS5fZW1wdHlwb2ludHMgPSBmaW5kRW1wdGllcyh6KTtcbiAgICBpbnRlcnAyZCh6LCB0cmFjZS5fZW1wdHlwb2ludHMpO1xuXG4gICAgLy8gY3JlYXRlIGFycmF5cyBvZiBicmljayBib3VuZGFyaWVzLCB0byBiZSB1c2VkIGJ5IGF1dG9yYW5nZSBhbmQgaGVhdG1hcC5wbG90XG4gICAgdmFyIHhsZW4gPSBtYXhSb3dMZW5ndGgoeiksXG4gICAgICAgIHhJbiA9IHRyYWNlLnh0eXBlID09PSAnc2NhbGVkJyA/ICcnIDogYSxcbiAgICAgICAgeEFycmF5ID0gbWFrZUJvdW5kQXJyYXkodHJhY2UsIHhJbiwgYTAsIGRhLCB4bGVuLCBhYXgpLFxuICAgICAgICB5SW4gPSB0cmFjZS55dHlwZSA9PT0gJ3NjYWxlZCcgPyAnJyA6IGIsXG4gICAgICAgIHlBcnJheSA9IG1ha2VCb3VuZEFycmF5KHRyYWNlLCB5SW4sIGIwLCBkYiwgei5sZW5ndGgsIGJheCk7XG5cbiAgICB2YXIgY2QwID0ge1xuICAgICAgICBhOiB4QXJyYXksXG4gICAgICAgIGI6IHlBcnJheSxcbiAgICAgICAgejogeixcbiAgICB9O1xuXG4gICAgaWYodHJhY2UuY29udG91cnMudHlwZSA9PT0gJ2xldmVscycgJiYgdHJhY2UuY29udG91cnMuY29sb3JpbmcgIT09ICdub25lJykge1xuICAgICAgICAvLyBhdXRvLXogYW5kIGF1dG9jb2xvcnNjYWxlIGlmIGFwcGxpY2FibGVcbiAgICAgICAgY29sb3JzY2FsZUNhbGModHJhY2UsIHosICcnLCAneicpO1xuICAgIH1cblxuICAgIHJldHVybiBbY2QwXTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBoYW5kbGVYWVpEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2hlYXRtYXAveHl6X2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvY29uc3RyYWludF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnRvdXJzRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9jb250b3VyL2NvbnRvdXJzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvc3R5bGVfZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgY29lcmNlKCdjYXJwZXQnKTtcblxuICAgIC8vIElmIGVpdGhlciBhIG9yIGIgaXMgbm90IHByZXNlbnQsIHRoZW4gaXQncyBub3QgYSB2YWxpZCB0cmFjZSAqdW5sZXNzKiB0aGUgY2FycGV0XG4gICAgLy8gYXhpcyBoYXMgdGhlIGEgb3IgYiB2YWx1ZXMgd2UncmUgbG9va2luZyBmb3IuIFNvIGlmIHRoZXNlIGFyZSBub3QgZm91bmQsIGp1c3QgZGVmZXJcbiAgICAvLyB0aGF0IGRlY2lzaW9uIHVudGlsIHRoZSBjYWxjIHN0ZXAuXG4gICAgLy9cbiAgICAvLyBOQjogdGhlIGNhbGMgc3RlcCB3aWxsIG1vZGlmeSB0aGUgb3JpZ2luYWwgZGF0YSBpbnB1dCBieSBhc3NpZ25pbmcgd2hpY2hldmVyIG9mXG4gICAgLy8gYSBvciBiIGFyZSBtaXNzaW5nLiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHBhbm5pbmcgZ29lcyByaWdodCBmcm9tIHN1cHBseURlZmF1bHRzXG4gICAgLy8gdG8gcGxvdCAoc2tpcHBpbmcgY2FsYykuIFRoYXQgbWVhbnMgb24gc3Vic2VxdWVudCB1cGRhdGVzLCB0aGlzICp3aWxsKiBuZWVkIHRvIGJlXG4gICAgLy8gYWJsZSB0byBmaW5kIGEgYW5kIGIuXG4gICAgLy9cbiAgICAvLyBUaGUgbG9uZy10ZXJtIHByb3BlciBmaXggaXMgdGhhdCB0aGlzIHNob3VsZCBwZXJoYXBzIHVzZSB1bmRlcnNjb3JlZCBhdHRyaWJ1dGVzIHRvXG4gICAgLy8gYXQgbGVhc3QgbW9kaWZ5IHRoZSB1c2VyIGlucHV0IHRvIGEgc2xpZ2h0bHkgbGVzc2VyIGV4dGVudC4gRnVsbHkgcmVtb3ZpbmcgdGhlXG4gICAgLy8gaW5wdXQgbXV0YXRpb24gaXMgY2hhbGxlbmdpbmcuIFRoZSB1bmRlcnNjb3JlIGFwcHJvYWNoIGlzIG5vdCBjdXJyZW50bHkgdGFrZW4gc2luY2VcbiAgICAvLyBpdCByZXF1aXJlcyBtb2RpZmljYXRpb24gdG8gYWxsIG9mIHRoZSBmdW5jdGlvbnMgYmVsb3cgdGhhdCBleHBlY3QgdGhlIGNvZXJjZWRcbiAgICAvLyBhdHRyaWJ1dGUgbmFtZSB0byBtYXRjaCB0aGUgcHJvcGVydHkgbmFtZSAtLSBleGNlcHQgJ19hJyAhPT0gJ2EnIHNvIHRoYXQgaXMgbm90XG4gICAgLy8gc3RyYWlnaHRmb3J3YXJkLlxuICAgIGlmKHRyYWNlSW4uYSAmJiB0cmFjZUluLmIpIHtcblxuICAgICAgICB2YXIgbGVuID0gaGFuZGxlWFlaRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCAnYScsICdiJyk7XG5cbiAgICAgICAgaWYoIWxlbikge1xuICAgICAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgICAgIHZhciBpc0NvbnN0cmFpbnQgPSAoY29lcmNlKCdjb250b3Vycy50eXBlJykgPT09ICdjb25zdHJhaW50Jyk7XG5cbiAgICAgICAgaWYoaXNDb25zdHJhaW50KSB7XG4gICAgICAgICAgICBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCBkZWZhdWx0Q29sb3IsIHtoYXNIb3ZlcjogZmFsc2V9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhhbmRsZUNvbnRvdXJzRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgY29lcmNlMik7XG4gICAgICAgICAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCwge2hhc0hvdmVyOiBmYWxzZX0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdHJhY2VPdXQuX2RlZmF1bHRDb2xvciA9IGRlZmF1bHRDb2xvcjtcbiAgICAgICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRvdXJDYXJwZXQgPSB7fTtcblxuQ29udG91ckNhcnBldC5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5Db250b3VyQ2FycGV0LnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuQ29udG91ckNhcnBldC5jb2xvcmJhciA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvY29sb3JiYXInKTtcbkNvbnRvdXJDYXJwZXQuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuQ29udG91ckNhcnBldC5wbG90ID0gcmVxdWlyZSgnLi9wbG90Jyk7XG5Db250b3VyQ2FycGV0LnN0eWxlID0gcmVxdWlyZSgnLi4vY29udG91ci9zdHlsZScpO1xuXG5Db250b3VyQ2FycGV0Lm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuQ29udG91ckNhcnBldC5uYW1lID0gJ2NvbnRvdXJjYXJwZXQnO1xuQ29udG91ckNhcnBldC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpO1xuQ29udG91ckNhcnBldC5jYXRlZ29yaWVzID0gWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ2NhcnBldCcsICdjb250b3VyJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdoYXNMaW5lcycsICdjYXJwZXREZXBlbmRlbnQnXTtcbkNvbnRvdXJDYXJwZXQubWV0YSA9IHtcbiAgICBcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQ29udG91ckNhcnBldDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBheGlzQWxpZ25lZExpbmUgPSByZXF1aXJlKCcuLi9jYXJwZXQvYXhpc19hbGlnbmVkX2xpbmUnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBqb2luQWxsUGF0aHModHJhY2UsIHBpLCBwZXJpbWV0ZXIsIGFiMnAsIGNhcnBldCwgY2FycGV0Y2QsIHhhLCB5YSkge1xuICAgIHZhciBpO1xuICAgIHZhciBmdWxscGF0aCA9ICcnO1xuXG4gICAgdmFyIHN0YXJ0c2xlZnQgPSBwaS5lZGdlcGF0aHMubWFwKGZ1bmN0aW9uKHYsIGkpIHsgcmV0dXJuIGk7IH0pO1xuICAgIHZhciBuZXdsb29wID0gdHJ1ZTtcbiAgICB2YXIgZW5kcHQsIG5ld2VuZHB0LCBjbnQsIG5leHRpLCBwb3NzaWJsZWksIGFkZHBhdGg7XG5cbiAgICB2YXIgYXRvbCA9IE1hdGguYWJzKHBlcmltZXRlclswXVswXSAtIHBlcmltZXRlclsyXVswXSkgKiAxZS00O1xuICAgIHZhciBidG9sID0gTWF0aC5hYnMocGVyaW1ldGVyWzBdWzFdIC0gcGVyaW1ldGVyWzJdWzFdKSAqIDFlLTQ7XG5cbiAgICBmdW5jdGlvbiBpc3RvcChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMV0gLSBwZXJpbWV0ZXJbMF1bMV0pIDwgYnRvbDsgfVxuICAgIGZ1bmN0aW9uIGlzYm90dG9tKHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFsxXSAtIHBlcmltZXRlclsyXVsxXSkgPCBidG9sOyB9XG4gICAgZnVuY3Rpb24gaXNsZWZ0KHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFswXSAtIHBlcmltZXRlclswXVswXSkgPCBhdG9sOyB9XG4gICAgZnVuY3Rpb24gaXNyaWdodChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMF0gLSBwZXJpbWV0ZXJbMl1bMF0pIDwgYXRvbDsgfVxuXG4gICAgZnVuY3Rpb24gcGF0aHRvKHB0MCwgcHQxKSB7XG4gICAgICAgIHZhciBpLCBqLCBzZWdtZW50cywgYXhpcztcbiAgICAgICAgdmFyIHBhdGggPSAnJztcblxuICAgICAgICBpZigoaXN0b3AocHQwKSAmJiAhaXNyaWdodChwdDApKSB8fCAoaXNib3R0b20ocHQwKSAmJiAhaXNsZWZ0KHB0MCkpKSB7XG4gICAgICAgICAgICBheGlzID0gY2FycGV0LmFheGlzO1xuICAgICAgICAgICAgc2VnbWVudHMgPSBheGlzQWxpZ25lZExpbmUoY2FycGV0LCBjYXJwZXRjZCwgW3B0MFswXSwgcHQxWzBdXSwgMC41ICogKHB0MFsxXSArIHB0MVsxXSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXhpcyA9IGNhcnBldC5iYXhpcztcbiAgICAgICAgICAgIHNlZ21lbnRzID0gYXhpc0FsaWduZWRMaW5lKGNhcnBldCwgY2FycGV0Y2QsIDAuNSAqIChwdDBbMF0gKyBwdDFbMF0pLCBbcHQwWzFdLCBwdDFbMV1dKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gMTsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwYXRoICs9IGF4aXMuc21vb3RoaW5nID8gJ0MnIDogJ0wnO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgc2VnbWVudHNbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHQgPSBzZWdtZW50c1tpXVtqXTtcbiAgICAgICAgICAgICAgICBwYXRoICs9IFt4YS5jMnAocHRbMF0pLCB5YS5jMnAocHRbMV0pXSArICcgJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXRoO1xuICAgIH1cblxuICAgIGkgPSAwO1xuICAgIGVuZHB0ID0gbnVsbDtcbiAgICB3aGlsZShzdGFydHNsZWZ0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgc3RhcnRwdCA9IHBpLmVkZ2VwYXRoc1tpXVswXTtcblxuICAgICAgICBpZihlbmRwdCkge1xuICAgICAgICAgICAgZnVsbHBhdGggKz0gcGF0aHRvKGVuZHB0LCBzdGFydHB0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFkZHBhdGggPSBEcmF3aW5nLnNtb290aG9wZW4ocGkuZWRnZXBhdGhzW2ldLm1hcChhYjJwKSwgcGkuc21vb3RoaW5nKTtcbiAgICAgICAgZnVsbHBhdGggKz0gbmV3bG9vcCA/IGFkZHBhdGggOiBhZGRwYXRoLnJlcGxhY2UoL15NLywgJ0wnKTtcbiAgICAgICAgc3RhcnRzbGVmdC5zcGxpY2Uoc3RhcnRzbGVmdC5pbmRleE9mKGkpLCAxKTtcbiAgICAgICAgZW5kcHQgPSBwaS5lZGdlcGF0aHNbaV1bcGkuZWRnZXBhdGhzW2ldLmxlbmd0aCAtIDFdO1xuICAgICAgICBuZXh0aSA9IC0xO1xuXG4gICAgICAgIC8vIG5vdyBsb29wIHRocm91Z2ggc2lkZXMsIG1vdmluZyBvdXIgZW5kcG9pbnQgdW50aWwgd2UgZmluZCBhIG5ldyBzdGFydFxuICAgICAgICBmb3IoY250ID0gMDsgY250IDwgNDsgY250KyspIHsgLy8ganVzdCB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BzXG4gICAgICAgICAgICBpZighZW5kcHQpIHtcbiAgICAgICAgICAgICAgICBMaWIubG9nKCdNaXNzaW5nIGVuZD8nLCBpLCBwaSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzdG9wKGVuZHB0KSAmJiAhaXNyaWdodChlbmRwdCkpIHtcbiAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHBlcmltZXRlclsxXTsgLy8gbGVmdCB0b3AgLS0tPiByaWdodCB0b3BcbiAgICAgICAgICAgIH0gZWxzZSBpZihpc2xlZnQoZW5kcHQpKSB7XG4gICAgICAgICAgICAgICAgbmV3ZW5kcHQgPSBwZXJpbWV0ZXJbMF07IC8vIGxlZnQgYm90dG9tIC0tLT4gbGVmdCB0b3BcbiAgICAgICAgICAgIH0gZWxzZSBpZihpc2JvdHRvbShlbmRwdCkpIHtcbiAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHBlcmltZXRlclszXTsgLy8gcmlnaHQgYm90dG9tXG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNyaWdodChlbmRwdCkpIHtcbiAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHBlcmltZXRlclsyXTsgLy8gbGVmdCBib3R0b21cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yKHBvc3NpYmxlaSA9IDA7IHBvc3NpYmxlaSA8IHBpLmVkZ2VwYXRocy5sZW5ndGg7IHBvc3NpYmxlaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHB0TmV3ID0gcGkuZWRnZXBhdGhzW3Bvc3NpYmxlaV1bMF07XG4gICAgICAgICAgICAgICAgLy8gaXMgcHROZXcgb24gdGhlIChob3J6LiBvciB2ZXJ0Likgc2VnbWVudCBmcm9tIGVuZHB0IHRvIG5ld2VuZHB0P1xuICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGVuZHB0WzBdIC0gbmV3ZW5kcHRbMF0pIDwgYXRvbCkge1xuICAgICAgICAgICAgICAgICAgICBpZihNYXRoLmFicyhlbmRwdFswXSAtIHB0TmV3WzBdKSA8IGF0b2wgJiYgKHB0TmV3WzFdIC0gZW5kcHRbMV0pICogKG5ld2VuZHB0WzFdIC0gcHROZXdbMV0pID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld2VuZHB0ID0gcHROZXc7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXh0aSA9IHBvc3NpYmxlaTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihNYXRoLmFicyhlbmRwdFsxXSAtIG5ld2VuZHB0WzFdKSA8IGJ0b2wpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZW5kcHRbMV0gLSBwdE5ld1sxXSkgPCBidG9sICYmIChwdE5ld1swXSAtIGVuZHB0WzBdKSAqIChuZXdlbmRwdFswXSAtIHB0TmV3WzBdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHB0TmV3O1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dGkgPSBwb3NzaWJsZWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBMaWIubG9nKCdlbmRwdCB0byBuZXdlbmRwdCBpcyBub3QgdmVydC4gb3IgaG9yei4nLCBlbmRwdCwgbmV3ZW5kcHQsIHB0TmV3KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKG5leHRpID49IDApIGJyZWFrO1xuICAgICAgICAgICAgZnVsbHBhdGggKz0gcGF0aHRvKGVuZHB0LCBuZXdlbmRwdCk7XG4gICAgICAgICAgICBlbmRwdCA9IG5ld2VuZHB0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobmV4dGkgPT09IHBpLmVkZ2VwYXRocy5sZW5ndGgpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ3VuY2xvc2VkIHBlcmltZXRlciBwYXRoJyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGkgPSBuZXh0aTtcblxuICAgICAgICAvLyBpZiB3ZSBjbG9zZWQgYmFjayBvbiBhIGxvb3Agd2UgYWxyZWFkeSBpbmNsdWRlZCxcbiAgICAgICAgLy8gY2xvc2UgaXQgYW5kIHN0YXJ0IGEgbmV3IGxvb3BcbiAgICAgICAgbmV3bG9vcCA9IChzdGFydHNsZWZ0LmluZGV4T2YoaSkgPT09IC0xKTtcbiAgICAgICAgaWYobmV3bG9vcCkge1xuICAgICAgICAgICAgaSA9IHN0YXJ0c2xlZnRbMF07XG4gICAgICAgICAgICBmdWxscGF0aCArPSBwYXRodG8oZW5kcHQsIG5ld2VuZHB0KSArICdaJztcbiAgICAgICAgICAgIGVuZHB0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZpbmFsbHkgYWRkIHRoZSBpbnRlcmlvciBwYXRoc1xuICAgIGZvcihpID0gMDsgaSA8IHBpLnBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZ1bGxwYXRoICs9IERyYXdpbmcuc21vb3RoY2xvc2VkKHBpLnBhdGhzW2ldLm1hcChhYjJwKSwgcGkuc21vb3RoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVsbHBhdGg7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hcFBhdGhpbmZvKHBhdGhpbmZvLCBtYXApIHtcbiAgICB2YXIgaSwgaiwgaywgcGksIHBlZGdlcGF0aHMsIHBwYXRocywgcGVkZ2VwYXRoLCBwcGF0aCwgcGF0aDtcblxuICAgIGZvcihpID0gMDsgaSA8IHBhdGhpbmZvLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBpID0gcGF0aGluZm9baV07XG4gICAgICAgIHBlZGdlcGF0aHMgPSBwaS5wZWRnZXBhdGhzID0gW107XG4gICAgICAgIHBwYXRocyA9IHBpLnBwYXRocyA9IFtdO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5lZGdlcGF0aHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHBhdGggPSBwaS5lZGdlcGF0aHNbal07XG4gICAgICAgICAgICBwZWRnZXBhdGggPSBbXTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IHBhdGgubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBwZWRnZXBhdGhba10gPSBtYXAocGF0aFtrXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZWRnZXBhdGhzLnB1c2gocGVkZ2VwYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5wYXRocy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgcGF0aCA9IHBpLnBhdGhzW2pdO1xuICAgICAgICAgICAgcHBhdGggPSBbXTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IHBhdGgubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBwcGF0aFtrXSA9IG1hcChwYXRoW2tdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBwYXRocy5wdXNoKHBwYXRoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgbWFwMWRBcnJheSA9IHJlcXVpcmUoJy4uL2NhcnBldC9tYXBfMWRfYXJyYXknKTtcbnZhciBtYWtlcGF0aCA9IHJlcXVpcmUoJy4uL2NhcnBldC9tYWtlcGF0aCcpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIG1ha2VDcm9zc2luZ3MgPSByZXF1aXJlKCcuLi9jb250b3VyL21ha2VfY3Jvc3NpbmdzJyk7XG52YXIgZmluZEFsbFBhdGhzID0gcmVxdWlyZSgnLi4vY29udG91ci9maW5kX2FsbF9wYXRocycpO1xudmFyIGNvbnRvdXJQbG90ID0gcmVxdWlyZSgnLi4vY29udG91ci9wbG90Jyk7XG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vY29udG91ci9jb25zdGFudHMnKTtcbnZhciBjb252ZXJ0VG9Db25zdHJhaW50cyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvY29udmVydF90b19jb25zdHJhaW50cycpO1xudmFyIGpvaW5BbGxQYXRocyA9IHJlcXVpcmUoJy4vam9pbl9hbGxfcGF0aHMnKTtcbnZhciBlbXB0eVBhdGhpbmZvID0gcmVxdWlyZSgnLi4vY29udG91ci9lbXB0eV9wYXRoaW5mbycpO1xudmFyIG1hcFBhdGhpbmZvID0gcmVxdWlyZSgnLi9tYXBfcGF0aGluZm8nKTtcbnZhciBsb29rdXBDYXJwZXQgPSByZXF1aXJlKCcuLi9jYXJwZXQvbG9va3VwX2NhcnBldGlkJyk7XG52YXIgY2xvc2VCb3VuZGFyaWVzID0gcmVxdWlyZSgnLi4vY29udG91ci9jbG9zZV9ib3VuZGFyaWVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkY29udG91cnMsIGNvbnRvdXJjYXJwZXRMYXllcikge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyhjb250b3VyY2FycGV0TGF5ZXIsIGNkY29udG91cnMsICdjb250b3VyJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICB2YXIgY2FycGV0ID0gdHJhY2UuX2NhcnBldFRyYWNlID0gbG9va3VwQ2FycGV0KGdkLCB0cmFjZSk7XG4gICAgICAgIHZhciBjYXJwZXRjZCA9IGdkLmNhbGNkYXRhW2NhcnBldC5pbmRleF1bMF07XG5cbiAgICAgICAgaWYoIWNhcnBldC52aXNpYmxlIHx8IGNhcnBldC52aXNpYmxlID09PSAnbGVnZW5kb25seScpIHJldHVybjtcblxuICAgICAgICB2YXIgYSA9IGNkMC5hO1xuICAgICAgICB2YXIgYiA9IGNkMC5iO1xuICAgICAgICB2YXIgY29udG91cnMgPSB0cmFjZS5jb250b3VycztcbiAgICAgICAgdmFyIHBhdGhpbmZvID0gZW1wdHlQYXRoaW5mbyhjb250b3VycywgcGxvdGluZm8sIGNkMCk7XG4gICAgICAgIHZhciBpc0NvbnN0cmFpbnQgPSBjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCc7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSBjb250b3Vycy5fb3BlcmF0aW9uO1xuICAgICAgICB2YXIgY29sb3JpbmcgPSBpc0NvbnN0cmFpbnQgPyAob3BlcmF0aW9uID09PSAnPScgPyAnbGluZXMnIDogJ2ZpbGwnKSA6IGNvbnRvdXJzLmNvbG9yaW5nO1xuXG4gICAgICAgIC8vIE1hcCBbYSwgYl0gKGRhdGEpIC0tPiBbaSwgal0gKHBpeGVscylcbiAgICAgICAgZnVuY3Rpb24gYWIycChhYikge1xuICAgICAgICAgICAgdmFyIHB0ID0gY2FycGV0LmFiMnh5KGFiWzBdLCBhYlsxXSwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gW3hhLmMycChwdFswXSksIHlhLmMycChwdFsxXSldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIHRoZSBwZXJpbWV0ZXIgaW4gYS9iIGNvb3JkaW5hdGVzOlxuICAgICAgICB2YXIgcGVyaW1ldGVyID0gW1xuICAgICAgICAgICAgW2FbMF0sIGJbYi5sZW5ndGggLSAxXV0sXG4gICAgICAgICAgICBbYVthLmxlbmd0aCAtIDFdLCBiW2IubGVuZ3RoIC0gMV1dLFxuICAgICAgICAgICAgW2FbYS5sZW5ndGggLSAxXSwgYlswXV0sXG4gICAgICAgICAgICBbYVswXSwgYlswXV1cbiAgICAgICAgXTtcblxuICAgICAgICAvLyBFeHRyYWN0IHRoZSBjb250b3VyIGxldmVsczpcbiAgICAgICAgbWFrZUNyb3NzaW5ncyhwYXRoaW5mbyk7XG4gICAgICAgIHZhciBhdG9sID0gKGFbYS5sZW5ndGggLSAxXSAtIGFbMF0pICogMWUtODtcbiAgICAgICAgdmFyIGJ0b2wgPSAoYltiLmxlbmd0aCAtIDFdIC0gYlswXSkgKiAxZS04O1xuICAgICAgICBmaW5kQWxsUGF0aHMocGF0aGluZm8sIGF0b2wsIGJ0b2wpO1xuXG4gICAgICAgIC8vIENvbnN0cmFpbnRzIG1pZ2h0IG5lZWQgdG8gYmUgZHJhdyBpbnZlcnRlZCwgd2hpY2ggaXMgbm90IHNvbWV0aGluZyBjb250b3Vyc1xuICAgICAgICAvLyBoYW5kbGUgYnkgZGVmYXVsdCBzaW5jZSB0aGV5J3JlIGFzc3VtZWQgZnVsbHkgb3BhcXVlIHNvIHRoYXQgdGhleSBjYW4gYmVcbiAgICAgICAgLy8gZHJhd24gb3ZlcmxhcHBpbmcuIFRoaXMgZnVuY3Rpb24gZmxpcHMgdGhlIHBhdGhzIGFzIG5lY2Vzc2FyeSBzbyB0aGF0IHRoZXkncmVcbiAgICAgICAgLy8gZHJhd24gY29ycmVjdGx5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBUT0RPOiBQZXJoYXBzIHRoaXMgc2hvdWxkIGJlIGdlbmVyYWxpemVkIGFuZCAqYWxsKiBwYXRocyBzaG91bGQgYmUgZHJhd24gYXNcbiAgICAgICAgLy8gY2xvc2VkIHJlZ2lvbnMgc28gdGhhdCB0cmFuc2x1Y2VudCBjb250b3VyIGxldmVscyB3b3VsZCBiZSB2YWxpZC5cbiAgICAgICAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTM1NlxuICAgICAgICB2YXIgZmlsbFBhdGhpbmZvID0gcGF0aGluZm87XG4gICAgICAgIGlmKGNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAgICAgZmlsbFBhdGhpbmZvID0gY29udmVydFRvQ29uc3RyYWludHMocGF0aGluZm8sIG9wZXJhdGlvbik7XG4gICAgICAgICAgICBjbG9zZUJvdW5kYXJpZXMoZmlsbFBhdGhpbmZvLCBvcGVyYXRpb24sIHBlcmltZXRlciwgdHJhY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFwIHRoZSBwYXRocyBpbiBhL2IgY29vcmRpbmF0ZXMgdG8gcGl4ZWwgY29vcmRpbmF0ZXM6XG4gICAgICAgIG1hcFBhdGhpbmZvKHBhdGhpbmZvLCBhYjJwKTtcblxuICAgICAgICAvLyBkcmF3IGV2ZXJ5dGhpbmdcblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBib3VuZGFyeSBwYXRoXG4gICAgICAgIHZhciBzZWcsIHhwLCB5cCwgaTtcbiAgICAgICAgdmFyIHNlZ3MgPSBbXTtcbiAgICAgICAgZm9yKGkgPSBjYXJwZXRjZC5jbGlwc2VnbWVudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHNlZyA9IGNhcnBldGNkLmNsaXBzZWdtZW50c1tpXTtcbiAgICAgICAgICAgIHhwID0gbWFwMWRBcnJheShbXSwgc2VnLngsIHhhLmMycCk7XG4gICAgICAgICAgICB5cCA9IG1hcDFkQXJyYXkoW10sIHNlZy55LCB5YS5jMnApO1xuICAgICAgICAgICAgeHAucmV2ZXJzZSgpO1xuICAgICAgICAgICAgeXAucmV2ZXJzZSgpO1xuICAgICAgICAgICAgc2Vncy5wdXNoKG1ha2VwYXRoKHhwLCB5cCwgc2VnLmJpY3ViaWMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBib3VuZGFyeVBhdGggPSAnTScgKyBzZWdzLmpvaW4oJ0wnKSArICdaJztcblxuICAgICAgICAvLyBEcmF3IHRoZSBiYXNlbGluZSBiYWNrZ3JvdW5kIGZpbGwgdGhhdCBmaWxscyBpbiB0aGUgc3BhY2UgYmVoaW5kIGFueSBvdGhlclxuICAgICAgICAvLyBjb250b3VyIGxldmVsczpcbiAgICAgICAgbWFrZUJhY2tncm91bmQocGxvdEdyb3VwLCBjYXJwZXRjZC5jbGlwc2VnbWVudHMsIHhhLCB5YSwgaXNDb25zdHJhaW50LCBjb2xvcmluZyk7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgc3BlY2lmaWMgY29udG91ciBmaWxscy4gQXMgYSBzaW1wbGlmaWNhdGlvbiwgdGhleSdyZSBhc3N1bWVkIHRvIGJlXG4gICAgICAgIC8vIGZ1bGx5IG9wYXF1ZSBzbyB0aGF0IGl0J3MgZWFzeSB0byBkcmF3IHRoZW0gc2ltcGx5IG92ZXJsYXBwaW5nLiBUaGUgYWx0ZXJuYXRpdmVcbiAgICAgICAgLy8gd291bGQgYmUgdG8gZmxpcCBhZGphY2VudCBwYXRocyBhbmQgZHJhdyBjbG9zZWQgcGF0aHMgZm9yIGVhY2ggbGV2ZWwgaW5zdGVhZC5cbiAgICAgICAgbWFrZUZpbGxzKHRyYWNlLCBwbG90R3JvdXAsIHhhLCB5YSwgZmlsbFBhdGhpbmZvLCBwZXJpbWV0ZXIsIGFiMnAsIGNhcnBldCwgY2FycGV0Y2QsIGNvbG9yaW5nLCBib3VuZGFyeVBhdGgpO1xuXG4gICAgICAgIC8vIERyYXcgY29udG91ciBsaW5lczpcbiAgICAgICAgbWFrZUxpbmVzQW5kTGFiZWxzKHBsb3RHcm91cCwgcGF0aGluZm8sIGdkLCBjZDAsIGNvbnRvdXJzLCBwbG90aW5mbywgY2FycGV0KTtcblxuICAgICAgICAvLyBDbGlwIHRoZSBib3VuZGFyeSBvZiB0aGUgcGxvdFxuICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwocGxvdEdyb3VwLCBjYXJwZXQuX2NsaXBQYXRoSWQpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbWFrZUxpbmVzQW5kTGFiZWxzKHBsb3Rncm91cCwgcGF0aGluZm8sIGdkLCBjZDAsIGNvbnRvdXJzLCBwbG90aW5mbywgY2FycGV0KSB7XG4gICAgdmFyIGxpbmVDb250YWluZXIgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnY29udG91cmxpbmVzJyk7XG4gICAgdmFyIHNob3dMaW5lcyA9IGNvbnRvdXJzLnNob3dsaW5lcyAhPT0gZmFsc2U7XG4gICAgdmFyIHNob3dMYWJlbHMgPSBjb250b3Vycy5zaG93bGFiZWxzO1xuICAgIHZhciBjbGlwTGluZXNGb3JMYWJlbHMgPSBzaG93TGluZXMgJiYgc2hvd0xhYmVscztcblxuICAgIC8vIEV2ZW4gaWYgd2UncmUgbm90IGdvaW5nIHRvIHNob3cgbGluZXMsIHdlIG5lZWQgdG8gY3JlYXRlIHRoZW1cbiAgICAvLyBpZiB3ZSdyZSBzaG93aW5nIGxhYmVscywgYmVjYXVzZSB0aGUgZmlsbCBwYXRocyBpbmNsdWRlIHRoZSBwZXJpbWV0ZXJcbiAgICAvLyBzbyBjYW4ndCBiZSB1c2VkIHRvIHBvc2l0aW9uIHRoZSBsYWJlbHMgY29ycmVjdGx5LlxuICAgIC8vIEluIHRoaXMgY2FzZSB3ZSdsbCByZW1vdmUgdGhlIGxpbmVzIGFmdGVyIG1ha2luZyB0aGUgbGFiZWxzLlxuICAgIHZhciBsaW5lZ3JvdXAgPSBjb250b3VyUGxvdC5jcmVhdGVMaW5lcyhsaW5lQ29udGFpbmVyLCBzaG93TGluZXMgfHwgc2hvd0xhYmVscywgcGF0aGluZm8pO1xuXG4gICAgdmFyIGxpbmVDbGlwID0gY29udG91clBsb3QuY3JlYXRlTGluZUNsaXAobGluZUNvbnRhaW5lciwgY2xpcExpbmVzRm9yTGFiZWxzLFxuICAgICAgICBnZC5fZnVsbExheW91dC5fZGVmcywgY2QwLnRyYWNlLnVpZCk7XG5cbiAgICB2YXIgbGFiZWxHcm91cCA9IHBsb3Rncm91cC5zZWxlY3RBbGwoJ2cuY29udG91cmxhYmVscycpXG4gICAgICAgIC5kYXRhKHNob3dMYWJlbHMgPyBbMF0gOiBbXSk7XG5cbiAgICBsYWJlbEdyb3VwLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGxhYmVsR3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmxhYmVscycsIHRydWUpO1xuXG4gICAgaWYoc2hvd0xhYmVscykge1xuICAgICAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgICAgIHZhciB4TGVuID0geGEuX2xlbmd0aDtcbiAgICAgICAgdmFyIHlMZW4gPSB5YS5fbGVuZ3RoO1xuICAgICAgICAvLyBmb3Igc2ltcGxpY2l0eSB1c2UgdGhlIHh5IGJveCBmb3IgbGFiZWwgY2xpcHBpbmcgb3V0bGluZS5cbiAgICAgICAgdmFyIGxhYmVsQ2xpcFBhdGhEYXRhID0gW1tcbiAgICAgICAgICAgIFswLCAwXSxcbiAgICAgICAgICAgIFt4TGVuLCAwXSxcbiAgICAgICAgICAgIFt4TGVuLCB5TGVuXSxcbiAgICAgICAgICAgIFswLCB5TGVuXVxuICAgICAgICBdXTtcblxuXG4gICAgICAgIHZhciBsYWJlbERhdGEgPSBbXTtcblxuICAgICAgICAvLyBpbnZhbGlkYXRlIHRoZSBnZXRUZXh0TG9jYXRpb24gY2FjaGUgaW4gY2FzZSBwYXRocyBjaGFuZ2VkXG4gICAgICAgIExpYi5jbGVhckxvY2F0aW9uQ2FjaGUoKTtcblxuICAgICAgICB2YXIgY29udG91ckZvcm1hdCA9IGNvbnRvdXJQbG90LmxhYmVsRm9ybWF0dGVyKGNvbnRvdXJzLCBjZDAudC5jYiwgZ2QuX2Z1bGxMYXlvdXQpO1xuXG4gICAgICAgIHZhciBkdW1teVRleHQgPSBEcmF3aW5nLnRlc3Rlci5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtbm90ZXgnLCAxKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBjb250b3Vycy5sYWJlbGZvbnQpO1xuXG4gICAgICAgIC8vIHVzZSBgYm91bmRzYCBvbmx5IHRvIGtlZXAgbGFiZWxzIGF3YXkgZnJvbSB0aGUgeC95IGJvdW5kYXJpZXNcbiAgICAgICAgLy8gYGNvbnN0cmFpblRvQ2FycGV0YCBiZWxvdyBlbnN1cmVzIGxhYmVscyBkb24ndCBnbyBvZmYgdGhlXG4gICAgICAgIC8vIGNhcnBldCBlZGdlc1xuICAgICAgICB2YXIgYm91bmRzID0ge1xuICAgICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICAgIHJpZ2h0OiB4TGVuLFxuICAgICAgICAgICAgY2VudGVyOiB4TGVuIC8gMixcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIGJvdHRvbTogeUxlbixcbiAgICAgICAgICAgIG1pZGRsZTogeUxlbiAvIDJcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgcGxvdERpYWdvbmFsID0gTWF0aC5zcXJ0KHhMZW4gKiB4TGVuICsgeUxlbiAqIHlMZW4pO1xuXG4gICAgICAgIC8vIHRoZSBwYXRoIGxlbmd0aCB0byB1c2UgdG8gc2NhbGUgdGhlIG51bWJlciBvZiBsYWJlbHMgdG8gZHJhdzpcbiAgICAgICAgdmFyIG5vcm1MZW5ndGggPSBjb25zdGFudHMuTEFCRUxESVNUQU5DRSAqIHBsb3REaWFnb25hbCAvXG4gICAgICAgICAgICBNYXRoLm1heCgxLCBwYXRoaW5mby5sZW5ndGggLyBjb25zdGFudHMuTEFCRUxJTkNSRUFTRSk7XG5cbiAgICAgICAgbGluZWdyb3VwLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHRleHRPcHRzID0gY29udG91clBsb3QuY2FsY1RleHRPcHRzKGQubGV2ZWwsIGNvbnRvdXJGb3JtYXQsIGR1bW15VGV4dCwgZ2QpO1xuXG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoJykuZWFjaChmdW5jdGlvbihwYXRoRGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXRoID0gdGhpcztcbiAgICAgICAgICAgICAgICB2YXIgcGF0aEJvdW5kcyA9IExpYi5nZXRWaXNpYmxlU2VnbWVudChwYXRoLCBib3VuZHMsIHRleHRPcHRzLmhlaWdodCAvIDIpO1xuICAgICAgICAgICAgICAgIGlmKCFwYXRoQm91bmRzKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICBjb25zdHJhaW5Ub0NhcnBldChwYXRoLCBwYXRoRGF0YSwgZCwgcGF0aEJvdW5kcywgY2FycGV0LCB0ZXh0T3B0cy5oZWlnaHQpO1xuXG4gICAgICAgICAgICAgICAgaWYocGF0aEJvdW5kcy5sZW4gPCAodGV4dE9wdHMud2lkdGggKyB0ZXh0T3B0cy5oZWlnaHQpICogY29uc3RhbnRzLkxBQkVMTUlOKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4TGFiZWxzID0gTWF0aC5taW4oTWF0aC5jZWlsKHBhdGhCb3VuZHMubGVuIC8gbm9ybUxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0YW50cy5MQUJFTE1BWCk7XG5cbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWF4TGFiZWxzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvYyA9IGNvbnRvdXJQbG90LmZpbmRCZXN0VGV4dExvY2F0aW9uKHBhdGgsIHBhdGhCb3VuZHMsIHRleHRPcHRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxEYXRhLCBib3VuZHMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKCFsb2MpIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnRvdXJQbG90LmFkZExhYmVsRGF0YShsb2MsIHRleHRPcHRzLCBsYWJlbERhdGEsIGxhYmVsQ2xpcFBhdGhEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZHVtbXlUZXh0LnJlbW92ZSgpO1xuXG4gICAgICAgIGNvbnRvdXJQbG90LmRyYXdMYWJlbHMobGFiZWxHcm91cCwgbGFiZWxEYXRhLCBnZCwgbGluZUNsaXAsXG4gICAgICAgICAgICBjbGlwTGluZXNGb3JMYWJlbHMgPyBsYWJlbENsaXBQYXRoRGF0YSA6IG51bGwpO1xuICAgIH1cblxuICAgIGlmKHNob3dMYWJlbHMgJiYgIXNob3dMaW5lcykgbGluZWdyb3VwLnJlbW92ZSgpO1xufVxuXG4vLyBmaWd1cmUgb3V0IGlmIHRoaXMgcGF0aCBnb2VzIG9mZiB0aGUgZWRnZSBvZiB0aGUgY2FycGV0XG4vLyBhbmQgc2hvcnRlbiB0aGUgcGFydCB3ZSBjYWxsIHZpc2libGUgdG8ga2VlcCBsYWJlbHMgYXdheSBmcm9tIHRoZSBlZGdlXG5mdW5jdGlvbiBjb25zdHJhaW5Ub0NhcnBldChwYXRoLCBwYXRoRGF0YSwgbGV2ZWxEYXRhLCBwYXRoQm91bmRzLCBjYXJwZXQsIHRleHRIZWlnaHQpIHtcbiAgICB2YXIgcGF0aEFCRGF0YTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGV2ZWxEYXRhLnBlZGdlcGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYocGF0aERhdGEgPT09IGxldmVsRGF0YS5wZWRnZXBhdGhzW2ldKSB7XG4gICAgICAgICAgICBwYXRoQUJEYXRhID0gbGV2ZWxEYXRhLmVkZ2VwYXRoc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZighcGF0aEFCRGF0YSkgcmV0dXJuO1xuXG4gICAgdmFyIGFNaW4gPSBjYXJwZXQuYVswXTtcbiAgICB2YXIgYU1heCA9IGNhcnBldC5hW2NhcnBldC5hLmxlbmd0aCAtIDFdO1xuICAgIHZhciBiTWluID0gY2FycGV0LmJbMF07XG4gICAgdmFyIGJNYXggPSBjYXJwZXQuYltjYXJwZXQuYi5sZW5ndGggLSAxXTtcblxuICAgIGZ1bmN0aW9uIGdldE9mZnNldChhYlB0LCBwYXRoVmVjdG9yKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICB2YXIgZWRnZVZlY3RvcjtcbiAgICAgICAgdmFyIGRBQiA9IDAuMTtcbiAgICAgICAgaWYoTWF0aC5hYnMoYWJQdFswXSAtIGFNaW4pIDwgZEFCIHx8IE1hdGguYWJzKGFiUHRbMF0gLSBhTWF4KSA8IGRBQikge1xuICAgICAgICAgICAgZWRnZVZlY3RvciA9IG5vcm1hbGl6ZVZlY3RvcihjYXJwZXQuZHh5ZGJfcm91Z2goYWJQdFswXSwgYWJQdFsxXSwgZEFCKSk7XG4gICAgICAgICAgICBvZmZzZXQgPSBNYXRoLm1heChvZmZzZXQsIHRleHRIZWlnaHQgKiB2ZWN0b3JUYW4ocGF0aFZlY3RvciwgZWRnZVZlY3RvcikgLyAyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKE1hdGguYWJzKGFiUHRbMV0gLSBiTWluKSA8IGRBQiB8fCBNYXRoLmFicyhhYlB0WzFdIC0gYk1heCkgPCBkQUIpIHtcbiAgICAgICAgICAgIGVkZ2VWZWN0b3IgPSBub3JtYWxpemVWZWN0b3IoY2FycGV0LmR4eWRhX3JvdWdoKGFiUHRbMF0sIGFiUHRbMV0sIGRBQikpO1xuICAgICAgICAgICAgb2Zmc2V0ID0gTWF0aC5tYXgob2Zmc2V0LCB0ZXh0SGVpZ2h0ICogdmVjdG9yVGFuKHBhdGhWZWN0b3IsIGVkZ2VWZWN0b3IpIC8gMik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICB2YXIgc3RhcnRWZWN0b3IgPSBnZXRVbml0VmVjdG9yKHBhdGgsIDAsIDEpO1xuICAgIHZhciBlbmRWZWN0b3IgPSBnZXRVbml0VmVjdG9yKHBhdGgsIHBhdGhCb3VuZHMudG90YWwsIHBhdGhCb3VuZHMudG90YWwgLSAxKTtcbiAgICB2YXIgbWluU3RhcnQgPSBnZXRPZmZzZXQocGF0aEFCRGF0YVswXSwgc3RhcnRWZWN0b3IpO1xuICAgIHZhciBtYXhFbmQgPSBwYXRoQm91bmRzLnRvdGFsIC0gZ2V0T2Zmc2V0KHBhdGhBQkRhdGFbcGF0aEFCRGF0YS5sZW5ndGggLSAxXSwgZW5kVmVjdG9yKTtcblxuICAgIGlmKHBhdGhCb3VuZHMubWluIDwgbWluU3RhcnQpIHBhdGhCb3VuZHMubWluID0gbWluU3RhcnQ7XG4gICAgaWYocGF0aEJvdW5kcy5tYXggPiBtYXhFbmQpIHBhdGhCb3VuZHMubWF4ID0gbWF4RW5kO1xuXG4gICAgcGF0aEJvdW5kcy5sZW4gPSBwYXRoQm91bmRzLm1heCAtIHBhdGhCb3VuZHMubWluO1xufVxuXG5mdW5jdGlvbiBnZXRVbml0VmVjdG9yKHBhdGgsIHAwLCBwMSkge1xuICAgIHZhciBwdDAgPSBwYXRoLmdldFBvaW50QXRMZW5ndGgocDApO1xuICAgIHZhciBwdDEgPSBwYXRoLmdldFBvaW50QXRMZW5ndGgocDEpO1xuICAgIHZhciBkeCA9IHB0MS54IC0gcHQwLng7XG4gICAgdmFyIGR5ID0gcHQxLnkgLSBwdDAueTtcbiAgICB2YXIgbGVuID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICByZXR1cm4gW2R4IC8gbGVuLCBkeSAvIGxlbl07XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVZlY3Rvcih2KSB7XG4gICAgdmFyIGxlbiA9IE1hdGguc3FydCh2WzBdICogdlswXSArIHZbMV0gKiB2WzFdKTtcbiAgICByZXR1cm4gW3ZbMF0gLyBsZW4sIHZbMV0gLyBsZW5dO1xufVxuXG5mdW5jdGlvbiB2ZWN0b3JUYW4odjAsIHYxKSB7XG4gICAgdmFyIGNvcyA9IE1hdGguYWJzKHYwWzBdICogdjFbMF0gKyB2MFsxXSAqIHYxWzFdKTtcbiAgICB2YXIgc2luID0gTWF0aC5zcXJ0KDEgLSBjb3MgKiBjb3MpO1xuICAgIHJldHVybiBzaW4gLyBjb3M7XG59XG5cbmZ1bmN0aW9uIG1ha2VCYWNrZ3JvdW5kKHBsb3Rncm91cCwgY2xpcHNlZ21lbnRzLCB4YXhpcywgeWF4aXMsIGlzQ29uc3RyYWludCwgY29sb3JpbmcpIHtcbiAgICB2YXIgc2VnLCB4cCwgeXAsIGk7XG4gICAgdmFyIGJnZ3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnY29udG91cmJnJyk7XG5cbiAgICB2YXIgYmdmaWxsID0gYmdncm91cC5zZWxlY3RBbGwoJ3BhdGgnKVxuICAgICAgICAuZGF0YSgoY29sb3JpbmcgPT09ICdmaWxsJyAmJiAhaXNDb25zdHJhaW50KSA/IFswXSA6IFtdKTtcbiAgICBiZ2ZpbGwuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcbiAgICBiZ2ZpbGwuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIHNlZ3MgPSBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBjbGlwc2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc2VnID0gY2xpcHNlZ21lbnRzW2ldO1xuICAgICAgICB4cCA9IG1hcDFkQXJyYXkoW10sIHNlZy54LCB4YXhpcy5jMnApO1xuICAgICAgICB5cCA9IG1hcDFkQXJyYXkoW10sIHNlZy55LCB5YXhpcy5jMnApO1xuICAgICAgICBzZWdzLnB1c2gobWFrZXBhdGgoeHAsIHlwLCBzZWcuYmljdWJpYykpO1xuICAgIH1cblxuICAgIGJnZmlsbFxuICAgICAgICAuYXR0cignZCcsICdNJyArIHNlZ3Muam9pbignTCcpICsgJ1onKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZScsICdub25lJyk7XG59XG5cbmZ1bmN0aW9uIG1ha2VGaWxscyh0cmFjZSwgcGxvdGdyb3VwLCB4YSwgeWEsIHBhdGhpbmZvLCBwZXJpbWV0ZXIsIGFiMnAsIGNhcnBldCwgY2FycGV0Y2QsIGNvbG9yaW5nLCBib3VuZGFyeVBhdGgpIHtcbiAgICB2YXIgZmlsbGdyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJmaWxsJyk7XG5cbiAgICB2YXIgZmlsbGl0ZW1zID0gZmlsbGdyb3VwLnNlbGVjdEFsbCgncGF0aCcpXG4gICAgICAgIC5kYXRhKGNvbG9yaW5nID09PSAnZmlsbCcgPyBwYXRoaW5mbyA6IFtdKTtcbiAgICBmaWxsaXRlbXMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcbiAgICBmaWxsaXRlbXMuZXhpdCgpLnJlbW92ZSgpO1xuICAgIGZpbGxpdGVtcy5lYWNoKGZ1bmN0aW9uKHBpKSB7XG4gICAgICAgIC8vIGpvaW4gYWxsIHBhdGhzIGZvciB0aGlzIGxldmVsIHRvZ2V0aGVyIGludG8gYSBzaW5nbGUgcGF0aFxuICAgICAgICAvLyBmaXJzdCBmb2xsb3cgY2xvY2t3aXNlIGFyb3VuZCB0aGUgcGVyaW1ldGVyIHRvIGNsb3NlIGFueSBvcGVuIHBhdGhzXG4gICAgICAgIC8vIGlmIHRoZSB3aG9sZSBwZXJpbWV0ZXIgaXMgYWJvdmUgdGhpcyBsZXZlbCwgc3RhcnQgd2l0aCBhIHBhdGhcbiAgICAgICAgLy8gZW5jbG9zaW5nIHRoZSB3aG9sZSB0aGluZy4gV2l0aCBhbGwgdGhhdCwgdGhlIHBhcml0eSBzaG91bGQgbWVhblxuICAgICAgICAvLyB0aGF0IHdlIGFsd2F5cyBmaWxsIGV2ZXJ5dGhpbmcgYWJvdmUgdGhlIGNvbnRvdXIsIG5vdGhpbmcgYmVsb3dcbiAgICAgICAgdmFyIGZ1bGxwYXRoID0gam9pbkFsbFBhdGhzKHRyYWNlLCBwaSwgcGVyaW1ldGVyLCBhYjJwLCBjYXJwZXQsIGNhcnBldGNkLCB4YSwgeWEpO1xuXG4gICAgICAgIGlmKHBpLnByZWZpeEJvdW5kYXJ5KSB7XG4gICAgICAgICAgICBmdWxscGF0aCA9IGJvdW5kYXJ5UGF0aCArIGZ1bGxwYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZ1bGxwYXRoKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykucmVtb3ZlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAuYXR0cignZCcsIGZ1bGxwYXRoKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgJ25vbmUnKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdCh7XG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLngsIHtpbXBsaWVkRWRpdHM6IHt4dHlwZTogJ2FycmF5J319KSxcbiAgICB4MDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLngwLCB7aW1wbGllZEVkaXRzOiB7eHR5cGU6ICdzY2FsZWQnfX0pLFxuICAgIGR4OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuZHgsIHtpbXBsaWVkRWRpdHM6IHt4dHlwZTogJ3NjYWxlZCd9fSksXG4gICAgeTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnksIHtpbXBsaWVkRWRpdHM6IHt5dHlwZTogJ2FycmF5J319KSxcbiAgICB5MDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnkwLCB7aW1wbGllZEVkaXRzOiB7eXR5cGU6ICdzY2FsZWQnfX0pLFxuICAgIGR5OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuZHksIHtpbXBsaWVkRWRpdHM6IHt5dHlwZTogJ3NjYWxlZCd9fSksXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFuc3Bvc2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXJyYXknLCAnc2NhbGVkJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHl0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FycmF5JywgJ3NjYWxlZCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6c21vb3RoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2Zhc3QnLCAnYmVzdCcsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvbm5lY3RnYXBzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6aG92ZXJmb3JtYXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFuc2Zvcm1zOiB1bmRlZmluZWRcbn0sXG4gICAgY29sb3JzY2FsZUF0dHJzKCcnLCB7XG4gICAgICAgIGNMZXR0ZXI6ICd6JyxcbiAgICAgICAgYXV0b0NvbG9yRGZsdDogZmFsc2VcbiAgICB9KSxcbiAgICB7IGNvbG9yYmFyOiBjb2xvcmJhckF0dHJzIH1cbik7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGhpc3RvZ3JhbTJkQ2FsYyA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbTJkL2NhbGMnKTtcbnZhciBjb2xvcnNjYWxlQ2FsYyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG52YXIgY29udmVydENvbHVtbkRhdGEgPSByZXF1aXJlKCcuL2NvbnZlcnRfY29sdW1uX3h5eicpO1xudmFyIG1heFJvd0xlbmd0aCA9IHJlcXVpcmUoJy4vbWF4X3Jvd19sZW5ndGgnKTtcbnZhciBjbGVhbjJkQXJyYXkgPSByZXF1aXJlKCcuL2NsZWFuXzJkX2FycmF5Jyk7XG52YXIgaW50ZXJwMmQgPSByZXF1aXJlKCcuL2ludGVycDJkJyk7XG52YXIgZmluZEVtcHRpZXMgPSByZXF1aXJlKCcuL2ZpbmRfZW1wdGllcycpO1xudmFyIG1ha2VCb3VuZEFycmF5ID0gcmVxdWlyZSgnLi9tYWtlX2JvdW5kX2FycmF5Jyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIC8vIHByZXBhcmUgdGhlIHJhdyBkYXRhXG4gICAgLy8gcnVuIG1ha2VDYWxjZGF0YSBvbiB4IGFuZCB5IGV2ZW4gZm9yIGhlYXRtYXBzLCBpbiBjYXNlIG9mIGNhdGVnb3J5IG1hcHBpbmdzXG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzIHx8ICd4JyksXG4gICAgICAgIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnlheGlzIHx8ICd5JyksXG4gICAgICAgIGlzQ29udG91ciA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdjb250b3VyJyksXG4gICAgICAgIGlzSGlzdCA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdoaXN0b2dyYW0nKSxcbiAgICAgICAgaXNHTDJEID0gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2dsMmQnKSxcbiAgICAgICAgenNtb290aCA9IGlzQ29udG91ciA/ICdiZXN0JyA6IHRyYWNlLnpzbW9vdGgsXG4gICAgICAgIHgsXG4gICAgICAgIHgwLFxuICAgICAgICBkeCxcbiAgICAgICAgeSxcbiAgICAgICAgeTAsXG4gICAgICAgIGR5LFxuICAgICAgICB6LFxuICAgICAgICBpLFxuICAgICAgICBiaW5uZWQ7XG5cbiAgICAvLyBjYW5jZWwgbWluaW11bSB0aWNrIHNwYWNpbmdzIChvbmx5IGFwcGxpZXMgdG8gYmFycyBhbmQgYm94ZXMpXG4gICAgeGEuX21pbkR0aWNrID0gMDtcbiAgICB5YS5fbWluRHRpY2sgPSAwO1xuXG4gICAgaWYoaXNIaXN0KSB7XG4gICAgICAgIGJpbm5lZCA9IGhpc3RvZ3JhbTJkQ2FsYyhnZCwgdHJhY2UpO1xuICAgICAgICB4ID0gYmlubmVkLng7XG4gICAgICAgIHgwID0gYmlubmVkLngwO1xuICAgICAgICBkeCA9IGJpbm5lZC5keDtcbiAgICAgICAgeSA9IGJpbm5lZC55O1xuICAgICAgICB5MCA9IGJpbm5lZC55MDtcbiAgICAgICAgZHkgPSBiaW5uZWQuZHk7XG4gICAgICAgIHogPSBiaW5uZWQuejtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciB6SW4gPSB0cmFjZS56O1xuICAgICAgICBpZihMaWIuaXNBcnJheTFEKHpJbikpIHtcbiAgICAgICAgICAgIGNvbnZlcnRDb2x1bW5EYXRhKHRyYWNlLCB4YSwgeWEsICd4JywgJ3knLCBbJ3onXSk7XG4gICAgICAgICAgICB4ID0gdHJhY2UuX3g7XG4gICAgICAgICAgICB5ID0gdHJhY2UuX3k7XG4gICAgICAgICAgICB6SW4gPSB0cmFjZS5fejtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHggPSB0cmFjZS54ID8geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpIDogW107XG4gICAgICAgICAgICB5ID0gdHJhY2UueSA/IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKSA6IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgeDAgPSB0cmFjZS54MCB8fCAwO1xuICAgICAgICBkeCA9IHRyYWNlLmR4IHx8IDE7XG4gICAgICAgIHkwID0gdHJhY2UueTAgfHwgMDtcbiAgICAgICAgZHkgPSB0cmFjZS5keSB8fCAxO1xuXG4gICAgICAgIHogPSBjbGVhbjJkQXJyYXkoekluLCB0cmFjZS50cmFuc3Bvc2UpO1xuXG4gICAgICAgIGlmKGlzQ29udG91ciB8fCB0cmFjZS5jb25uZWN0Z2Fwcykge1xuICAgICAgICAgICAgdHJhY2UuX2VtcHR5cG9pbnRzID0gZmluZEVtcHRpZXMoeik7XG4gICAgICAgICAgICBpbnRlcnAyZCh6LCB0cmFjZS5fZW1wdHlwb2ludHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbm9ac21vb3RoKG1zZykge1xuICAgICAgICB6c21vb3RoID0gdHJhY2UuX2lucHV0LnpzbW9vdGggPSB0cmFjZS56c21vb3RoID0gZmFsc2U7XG4gICAgICAgIExpYi53YXJuKCdjYW5ub3QgdXNlIHpzbW9vdGg6IFwiZmFzdFwiOiAnICsgbXNnKTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayB3aGV0aGVyIHdlIHJlYWxseSBjYW4gc21vb3RoIChpZSBhbGwgYm94ZXMgYXJlIGFib3V0IHRoZSBzYW1lIHNpemUpXG4gICAgaWYoenNtb290aCA9PT0gJ2Zhc3QnKSB7XG4gICAgICAgIGlmKHhhLnR5cGUgPT09ICdsb2cnIHx8IHlhLnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgICAgICBub1pzbW9vdGgoJ2xvZyBheGlzIGZvdW5kJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZighaXNIaXN0KSB7XG4gICAgICAgICAgICBpZih4Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciBhdmdkeCA9ICh4W3gubGVuZ3RoIC0gMV0gLSB4WzBdKSAvICh4Lmxlbmd0aCAtIDEpLFxuICAgICAgICAgICAgICAgICAgICBtYXhFcnJYID0gTWF0aC5hYnMoYXZnZHggLyAxMDApO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHgubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKHhbaSArIDFdIC0geFtpXSAtIGF2Z2R4KSA+IG1heEVyclgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vWnNtb290aCgneCBzY2FsZSBpcyBub3QgbGluZWFyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHkubGVuZ3RoICYmIHpzbW9vdGggPT09ICdmYXN0Jykge1xuICAgICAgICAgICAgICAgIHZhciBhdmdkeSA9ICh5W3kubGVuZ3RoIC0gMV0gLSB5WzBdKSAvICh5Lmxlbmd0aCAtIDEpLFxuICAgICAgICAgICAgICAgICAgICBtYXhFcnJZID0gTWF0aC5hYnMoYXZnZHkgLyAxMDApO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHkubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKHlbaSArIDFdIC0geVtpXSAtIGF2Z2R5KSA+IG1heEVyclkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vWnNtb290aCgneSBzY2FsZSBpcyBub3QgbGluZWFyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBhcnJheXMgb2YgYnJpY2sgYm91bmRhcmllcywgdG8gYmUgdXNlZCBieSBhdXRvcmFuZ2UgYW5kIGhlYXRtYXAucGxvdFxuICAgIHZhciB4bGVuID0gbWF4Um93TGVuZ3RoKHopO1xuICAgIHZhciB4SW4gPSB0cmFjZS54dHlwZSA9PT0gJ3NjYWxlZCcgPyAnJyA6IHg7XG4gICAgdmFyIHhBcnJheSA9IG1ha2VCb3VuZEFycmF5KHRyYWNlLCB4SW4sIHgwLCBkeCwgeGxlbiwgeGEpO1xuICAgIHZhciB5SW4gPSB0cmFjZS55dHlwZSA9PT0gJ3NjYWxlZCcgPyAnJyA6IHk7XG4gICAgdmFyIHlBcnJheSA9IG1ha2VCb3VuZEFycmF5KHRyYWNlLCB5SW4sIHkwLCBkeSwgei5sZW5ndGgsIHlhKTtcblxuICAgIC8vIGhhbmRsZWQgaW4gZ2wyZCBjb252ZXJ0IHN0ZXBcbiAgICBpZighaXNHTDJEKSB7XG4gICAgICAgIHRyYWNlLl9leHRyZW1lc1t4YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeGEsIHhBcnJheSk7XG4gICAgICAgIHRyYWNlLl9leHRyZW1lc1t5YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeWEsIHlBcnJheSk7XG4gICAgfVxuXG4gICAgdmFyIGNkMCA9IHtcbiAgICAgICAgeDogeEFycmF5LFxuICAgICAgICB5OiB5QXJyYXksXG4gICAgICAgIHo6IHosXG4gICAgICAgIHRleHQ6IHRyYWNlLl90ZXh0IHx8IHRyYWNlLnRleHRcbiAgICB9O1xuXG4gICAgaWYoeEluICYmIHhJbi5sZW5ndGggPT09IHhBcnJheS5sZW5ndGggLSAxKSBjZDAueENlbnRlciA9IHhJbjtcbiAgICBpZih5SW4gJiYgeUluLmxlbmd0aCA9PT0geUFycmF5Lmxlbmd0aCAtIDEpIGNkMC55Q2VudGVyID0geUluO1xuXG4gICAgaWYoaXNIaXN0KSB7XG4gICAgICAgIGNkMC54UmFuZ2VzID0gYmlubmVkLnhSYW5nZXM7XG4gICAgICAgIGNkMC55UmFuZ2VzID0gYmlubmVkLnlSYW5nZXM7XG4gICAgICAgIGNkMC5wdHMgPSBiaW5uZWQucHRzO1xuICAgIH1cblxuICAgIC8vIGF1dG8teiBhbmQgYXV0b2NvbG9yc2NhbGUgaWYgYXBwbGljYWJsZVxuICAgIGlmKCFpc0NvbnRvdXIgfHwgdHJhY2UuY29udG91cnMudHlwZSAhPT0gJ2NvbnN0cmFpbnQnKSB7XG4gICAgICAgIGNvbG9yc2NhbGVDYWxjKHRyYWNlLCB6LCAnJywgJ3onKTtcbiAgICB9XG5cbiAgICBpZihpc0NvbnRvdXIgJiYgdHJhY2UuY29udG91cnMgJiYgdHJhY2UuY29udG91cnMuY29sb3JpbmcgPT09ICdoZWF0bWFwJykge1xuICAgICAgICB2YXIgZHVtbXlUcmFjZSA9IHtcbiAgICAgICAgICAgIHR5cGU6IHRyYWNlLnR5cGUgPT09ICdjb250b3VyJyA/ICdoZWF0bWFwJyA6ICdoaXN0b2dyYW0yZCcsXG4gICAgICAgICAgICB4Y2FsZW5kYXI6IHRyYWNlLnhjYWxlbmRhcixcbiAgICAgICAgICAgIHljYWxlbmRhcjogdHJhY2UueWNhbGVuZGFyXG4gICAgICAgIH07XG4gICAgICAgIGNkMC54ZmlsbCA9IG1ha2VCb3VuZEFycmF5KGR1bW15VHJhY2UsIHhJbiwgeDAsIGR4LCB4bGVuLCB4YSk7XG4gICAgICAgIGNkMC55ZmlsbCA9IG1ha2VCb3VuZEFycmF5KGR1bW15VHJhY2UsIHlJbiwgeTAsIGR5LCB6Lmxlbmd0aCwgeWEpO1xuICAgIH1cblxuICAgIHJldHVybiBbY2QwXTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsZWFuMmRBcnJheSh6T2xkLCB0cmFuc3Bvc2UpIHtcbiAgICB2YXIgcm93bGVuLCBjb2xsZW4sIGdldENvbGxlbiwgb2xkMm5ldywgaSwgajtcblxuICAgIGZ1bmN0aW9uIGNsZWFuWnZhbHVlKHYpIHtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyh2KSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuICt2O1xuICAgIH1cblxuICAgIGlmKHRyYW5zcG9zZSkge1xuICAgICAgICByb3dsZW4gPSAwO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB6T2xkLmxlbmd0aDsgaSsrKSByb3dsZW4gPSBNYXRoLm1heChyb3dsZW4sIHpPbGRbaV0ubGVuZ3RoKTtcbiAgICAgICAgaWYocm93bGVuID09PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGdldENvbGxlbiA9IGZ1bmN0aW9uKHpPbGQpIHsgcmV0dXJuIHpPbGQubGVuZ3RoOyB9O1xuICAgICAgICBvbGQybmV3ID0gZnVuY3Rpb24oek9sZCwgaSwgaikgeyByZXR1cm4gek9sZFtqXVtpXTsgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJvd2xlbiA9IHpPbGQubGVuZ3RoO1xuICAgICAgICBnZXRDb2xsZW4gPSBmdW5jdGlvbih6T2xkLCBpKSB7IHJldHVybiB6T2xkW2ldLmxlbmd0aDsgfTtcbiAgICAgICAgb2xkMm5ldyA9IGZ1bmN0aW9uKHpPbGQsIGksIGopIHsgcmV0dXJuIHpPbGRbaV1bal07IH07XG4gICAgfVxuXG4gICAgdmFyIHpOZXcgPSBuZXcgQXJyYXkocm93bGVuKTtcblxuICAgIGZvcihpID0gMDsgaSA8IHJvd2xlbjsgaSsrKSB7XG4gICAgICAgIGNvbGxlbiA9IGdldENvbGxlbih6T2xkLCBpKTtcbiAgICAgICAgek5ld1tpXSA9IG5ldyBBcnJheShjb2xsZW4pO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBjb2xsZW47IGorKykgek5ld1tpXVtqXSA9IGNsZWFuWnZhbHVlKG9sZDJuZXcoek9sZCwgaSwgaikpO1xuICAgIH1cblxuICAgIHJldHVybiB6TmV3O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbWluOiAnem1pbicsXG4gICAgbWF4OiAnem1heCdcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydENvbHVtbkRhdGEodHJhY2UsIGF4MSwgYXgyLCB2YXIxTmFtZSwgdmFyMk5hbWUsIGFycmF5VmFyTmFtZXMpIHtcbiAgICB2YXIgY29sTGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgY29sMSA9IHRyYWNlW3ZhcjFOYW1lXS5zbGljZSgwLCBjb2xMZW4pO1xuICAgIHZhciBjb2wyID0gdHJhY2VbdmFyMk5hbWVdLnNsaWNlKDAsIGNvbExlbik7XG4gICAgdmFyIHRleHRDb2wgPSB0cmFjZS50ZXh0O1xuICAgIHZhciBoYXNDb2x1bW5UZXh0ID0gKHRleHRDb2wgIT09IHVuZGVmaW5lZCAmJiBMaWIuaXNBcnJheTFEKHRleHRDb2wpKTtcbiAgICB2YXIgY29sMUNhbGVuZGFyID0gdHJhY2VbdmFyMU5hbWUgKyAnY2FsZW5kYXInXTtcbiAgICB2YXIgY29sMkNhbGVuZGFyID0gdHJhY2VbdmFyMk5hbWUgKyAnY2FsZW5kYXInXTtcblxuICAgIHZhciBpLCBqLCBhcnJheVZhciwgbmV3QXJyYXksIGFycmF5VmFyTmFtZTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbExlbjsgaSsrKSB7XG4gICAgICAgIGNvbDFbaV0gPSBheDEuZDJjKGNvbDFbaV0sIDAsIGNvbDFDYWxlbmRhcik7XG4gICAgICAgIGNvbDJbaV0gPSBheDIuZDJjKGNvbDJbaV0sIDAsIGNvbDJDYWxlbmRhcik7XG4gICAgfVxuXG4gICAgdmFyIGNvbDFkdiA9IExpYi5kaXN0aW5jdFZhbHMoY29sMSksXG4gICAgICAgIGNvbDF2YWxzID0gY29sMWR2LnZhbHMsXG4gICAgICAgIGNvbDJkdiA9IExpYi5kaXN0aW5jdFZhbHMoY29sMiksXG4gICAgICAgIGNvbDJ2YWxzID0gY29sMmR2LnZhbHMsXG4gICAgICAgIG5ld0FycmF5cyA9IFtdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXJyYXlWYXJOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBuZXdBcnJheXNbaV0gPSBMaWIuaW5pdDJkQXJyYXkoY29sMnZhbHMubGVuZ3RoLCBjb2wxdmFscy5sZW5ndGgpO1xuICAgIH1cblxuICAgIHZhciBpMSwgaTIsIHRleHQ7XG5cbiAgICBpZihoYXNDb2x1bW5UZXh0KSB0ZXh0ID0gTGliLmluaXQyZEFycmF5KGNvbDJ2YWxzLmxlbmd0aCwgY29sMXZhbHMubGVuZ3RoKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbExlbjsgaSsrKSB7XG4gICAgICAgIGlmKGNvbDFbaV0gIT09IEJBRE5VTSAmJiBjb2wyW2ldICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGkxID0gTGliLmZpbmRCaW4oY29sMVtpXSArIGNvbDFkdi5taW5EaWZmIC8gMiwgY29sMXZhbHMpO1xuICAgICAgICAgICAgaTIgPSBMaWIuZmluZEJpbihjb2wyW2ldICsgY29sMmR2Lm1pbkRpZmYgLyAyLCBjb2wydmFscyk7XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGFycmF5VmFyTmFtZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheVZhck5hbWUgPSBhcnJheVZhck5hbWVzW2pdO1xuICAgICAgICAgICAgICAgIGFycmF5VmFyID0gdHJhY2VbYXJyYXlWYXJOYW1lXTtcbiAgICAgICAgICAgICAgICBuZXdBcnJheSA9IG5ld0FycmF5c1tqXTtcbiAgICAgICAgICAgICAgICBuZXdBcnJheVtpMl1baTFdID0gYXJyYXlWYXJbaV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGhhc0NvbHVtblRleHQpIHRleHRbaTJdW2kxXSA9IHRleHRDb2xbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0cmFjZVsnXycgKyB2YXIxTmFtZV0gPSBjb2wxdmFscztcbiAgICB0cmFjZVsnXycgKyB2YXIyTmFtZV0gPSBjb2wydmFscztcbiAgICBmb3IoaiA9IDA7IGogPCBhcnJheVZhck5hbWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHRyYWNlWydfJyArIGFycmF5VmFyTmFtZXNbal1dID0gbmV3QXJyYXlzW2pdO1xuICAgIH1cbiAgICBpZihoYXNDb2x1bW5UZXh0KSB0cmFjZS5fdGV4dCA9IHRleHQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZVhZWkRlZmF1bHRzID0gcmVxdWlyZSgnLi94eXpfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVTdHlsZURlZmF1bHRzID0gcmVxdWlyZSgnLi9zdHlsZV9kZWZhdWx0cycpO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmFsaWREYXRhID0gaGFuZGxlWFlaRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZighdmFsaWREYXRhKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuXG4gICAgaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuXG4gICAgY29lcmNlKCdjb25uZWN0Z2FwcycsIExpYi5pc0FycmF5MUQodHJhY2VPdXQueikgJiYgKHRyYWNlT3V0LnpzbW9vdGggIT09IGZhbHNlKSk7XG5cbiAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbWF4Um93TGVuZ3RoID0gcmVxdWlyZSgnLi9tYXhfcm93X2xlbmd0aCcpO1xuXG4vKiBSZXR1cm4gYSBsaXN0IG9mIGVtcHR5IHBvaW50cyBpbiAyRCBhcnJheSB6XG4gKiBlYWNoIGVtcHR5IHBvaW50IHpbaV1bal0gZ2l2ZXMgYW4gYXJyYXkgW2ksIGosIG5laWdoYm9yQ291bnRdXG4gKiBuZWlnaGJvckNvdW50IGlzIHRoZSBjb3VudCBvZiA0IG5lYXJlc3QgbmVpZ2hib3JzIHRoYXQgRE8gZXhpc3RcbiAqIHRoaXMgaXMgdG8gZ2l2ZSB1cyBhbiBvcmRlciBvZiBwb2ludHMgdG8gZXZhbHVhdGUgZm9yIGludGVycG9sYXRpb24uXG4gKiBpZiBubyBuZWlnaGJvcnMgZXhpc3QsIHdlIGl0ZXJhdGl2ZWx5IGxvb2sgZm9yIG5laWdoYm9ycyB0aGF0IEhBVkVcbiAqIG5laWdoYm9ycywgYW5kIGFkZCBhIGZyYWN0aW9uYWwgbmVpZ2hib3JDb3VudFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGZpbmRFbXB0aWVzKHopIHtcbiAgICB2YXIgZW1wdGllcyA9IFtdLFxuICAgICAgICBuZWlnaGJvckhhc2ggPSB7fSxcbiAgICAgICAgbm9OZWlnaGJvckxpc3QgPSBbXSxcbiAgICAgICAgbmV4dFJvdyA9IHpbMF0sXG4gICAgICAgIHJvdyA9IFtdLFxuICAgICAgICBibGFuayA9IFswLCAwLCAwXSxcbiAgICAgICAgcm93TGVuZ3RoID0gbWF4Um93TGVuZ3RoKHopLFxuICAgICAgICBwcmV2Um93LFxuICAgICAgICBpLFxuICAgICAgICBqLFxuICAgICAgICB0aGlzUHQsXG4gICAgICAgIHAsXG4gICAgICAgIG5laWdoYm9yQ291bnQsXG4gICAgICAgIG5ld05laWdoYm9ySGFzaCxcbiAgICAgICAgZm91bmROZXdOZWlnaGJvcnM7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB6Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByZXZSb3cgPSByb3c7XG4gICAgICAgIHJvdyA9IG5leHRSb3c7XG4gICAgICAgIG5leHRSb3cgPSB6W2kgKyAxXSB8fCBbXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgcm93TGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKHJvd1tqXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbmVpZ2hib3JDb3VudCA9IChyb3dbaiAtIDFdICE9PSB1bmRlZmluZWQgPyAxIDogMCkgK1xuICAgICAgICAgICAgICAgICAgICAocm93W2ogKyAxXSAhPT0gdW5kZWZpbmVkID8gMSA6IDApICtcbiAgICAgICAgICAgICAgICAgICAgKHByZXZSb3dbal0gIT09IHVuZGVmaW5lZCA/IDEgOiAwKSArXG4gICAgICAgICAgICAgICAgICAgIChuZXh0Um93W2pdICE9PSB1bmRlZmluZWQgPyAxIDogMCk7XG5cbiAgICAgICAgICAgICAgICBpZihuZWlnaGJvckNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGZvciB0aGlzIHB1cnBvc2UsIGRvbid0IGNvdW50IG9mZi10aGUtZWRnZSBwb2ludHNcbiAgICAgICAgICAgICAgICAgICAgLy8gYXMgdW5kZWZpbmVkIG5laWdoYm9yc1xuICAgICAgICAgICAgICAgICAgICBpZihpID09PSAwKSBuZWlnaGJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIGlmKGogPT09IDApIG5laWdoYm9yQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgaWYoaSA9PT0gei5sZW5ndGggLSAxKSBuZWlnaGJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIGlmKGogPT09IHJvdy5sZW5ndGggLSAxKSBuZWlnaGJvckNvdW50Kys7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgYWxsIG5laWdoYm9ycyB0aGF0IGNvdWxkIGV4aXN0IGRvLCB3ZSBkb24ndFxuICAgICAgICAgICAgICAgICAgICAvLyBuZWVkIHRoaXMgZm9yIGZpbmRpbmcgZmFydGhlciBuZWlnaGJvcnNcbiAgICAgICAgICAgICAgICAgICAgaWYobmVpZ2hib3JDb3VudCA8IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5laWdoYm9ySGFzaFtbaSwgal1dID0gW2ksIGosIG5laWdoYm9yQ291bnRdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZW1wdGllcy5wdXNoKFtpLCBqLCBuZWlnaGJvckNvdW50XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Ugbm9OZWlnaGJvckxpc3QucHVzaChbaSwgal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgd2hpbGUobm9OZWlnaGJvckxpc3QubGVuZ3RoKSB7XG4gICAgICAgIG5ld05laWdoYm9ySGFzaCA9IHt9O1xuICAgICAgICBmb3VuZE5ld05laWdoYm9ycyA9IGZhbHNlO1xuXG4gICAgICAgIC8vIGxvb2sgZm9yIGNlbGxzIHRoYXQgbm93IGhhdmUgbmVpZ2hib3JzIGJ1dCBkaWRuJ3QgYmVmb3JlXG4gICAgICAgIGZvcihwID0gbm9OZWlnaGJvckxpc3QubGVuZ3RoIC0gMTsgcCA+PSAwOyBwLS0pIHtcbiAgICAgICAgICAgIHRoaXNQdCA9IG5vTmVpZ2hib3JMaXN0W3BdO1xuICAgICAgICAgICAgaSA9IHRoaXNQdFswXTtcbiAgICAgICAgICAgIGogPSB0aGlzUHRbMV07XG5cbiAgICAgICAgICAgIG5laWdoYm9yQ291bnQgPSAoKG5laWdoYm9ySGFzaFtbaSAtIDEsIGpdXSB8fCBibGFuaylbMl0gK1xuICAgICAgICAgICAgICAgIChuZWlnaGJvckhhc2hbW2kgKyAxLCBqXV0gfHwgYmxhbmspWzJdICtcbiAgICAgICAgICAgICAgICAobmVpZ2hib3JIYXNoW1tpLCBqIC0gMV1dIHx8IGJsYW5rKVsyXSArXG4gICAgICAgICAgICAgICAgKG5laWdoYm9ySGFzaFtbaSwgaiArIDFdXSB8fCBibGFuaylbMl0pIC8gMjA7XG5cbiAgICAgICAgICAgIGlmKG5laWdoYm9yQ291bnQpIHtcbiAgICAgICAgICAgICAgICBuZXdOZWlnaGJvckhhc2hbdGhpc1B0XSA9IFtpLCBqLCBuZWlnaGJvckNvdW50XTtcbiAgICAgICAgICAgICAgICBub05laWdoYm9yTGlzdC5zcGxpY2UocCwgMSk7XG4gICAgICAgICAgICAgICAgZm91bmROZXdOZWlnaGJvcnMgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZvdW5kTmV3TmVpZ2hib3JzKSB7XG4gICAgICAgICAgICB0aHJvdyAnZmluZEVtcHRpZXMgaXRlcmF0ZWQgd2l0aCBubyBuZXcgbmVpZ2hib3JzJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHB1dCB0aGVzZSBuZXcgY2VsbHMgaW50byB0aGUgbWFpbiBuZWlnaGJvciBsaXN0XG4gICAgICAgIGZvcih0aGlzUHQgaW4gbmV3TmVpZ2hib3JIYXNoKSB7XG4gICAgICAgICAgICBuZWlnaGJvckhhc2hbdGhpc1B0XSA9IG5ld05laWdoYm9ySGFzaFt0aGlzUHRdO1xuICAgICAgICAgICAgZW1wdGllcy5wdXNoKG5ld05laWdoYm9ySGFzaFt0aGlzUHRdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNvcnQgdGhlIGZ1bGwgbGlzdCBpbiBkZXNjZW5kaW5nIG9yZGVyIG9mIG5laWdoYm9yIGNvdW50XG4gICAgcmV0dXJuIGVtcHRpZXMuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBiWzJdIC0gYVsyXTsgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSwgaG92ZXJMYXllciwgY29udG91cikge1xuICAgIHZhciBjZDAgPSBwb2ludERhdGEuY2RbMF07XG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIHggPSBjZDAueDtcbiAgICB2YXIgeSA9IGNkMC55O1xuICAgIHZhciB6ID0gY2QwLno7XG4gICAgdmFyIHhjID0gY2QwLnhDZW50ZXI7XG4gICAgdmFyIHljID0gY2QwLnlDZW50ZXI7XG4gICAgdmFyIHptYXNrID0gY2QwLnptYXNrO1xuICAgIHZhciByYW5nZSA9IFt0cmFjZS56bWluLCB0cmFjZS56bWF4XTtcbiAgICB2YXIgemhvdmVyZm9ybWF0ID0gdHJhY2UuemhvdmVyZm9ybWF0O1xuICAgIHZhciB4MiA9IHg7XG4gICAgdmFyIHkyID0geTtcblxuICAgIHZhciB4bCwgeWwsIG54LCBueTtcblxuICAgIGlmKHBvaW50RGF0YS5pbmRleCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG54ID0gTWF0aC5yb3VuZChwb2ludERhdGEuaW5kZXhbMV0pO1xuICAgICAgICAgICAgbnkgPSBNYXRoLnJvdW5kKHBvaW50RGF0YS5pbmRleFswXSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2goZSkge1xuICAgICAgICAgICAgTGliLmVycm9yKCdFcnJvciBob3ZlcmluZyBvbiBoZWF0bWFwLCAnICtcbiAgICAgICAgICAgICAgICAncG9pbnROdW1iZXIgbXVzdCBiZSBbcm93LGNvbF0sIGZvdW5kOicsIHBvaW50RGF0YS5pbmRleCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYobnggPCAwIHx8IG54ID49IHpbMF0ubGVuZ3RoIHx8IG55IDwgMCB8fCBueSA+IHoubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZihGeC5pbmJveCh4dmFsIC0geFswXSwgeHZhbCAtIHhbeC5sZW5ndGggLSAxXSwgMCkgPiAwIHx8XG4gICAgICAgICAgICBGeC5pbmJveCh5dmFsIC0geVswXSwgeXZhbCAtIHlbeS5sZW5ndGggLSAxXSwgMCkgPiAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmKGNvbnRvdXIpIHtcbiAgICAgICAgICAgIHZhciBpMjtcbiAgICAgICAgICAgIHgyID0gWzIgKiB4WzBdIC0geFsxXV07XG5cbiAgICAgICAgICAgIGZvcihpMiA9IDE7IGkyIDwgeC5sZW5ndGg7IGkyKyspIHtcbiAgICAgICAgICAgICAgICB4Mi5wdXNoKCh4W2kyXSArIHhbaTIgLSAxXSkgLyAyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHgyLnB1c2goWzIgKiB4W3gubGVuZ3RoIC0gMV0gLSB4W3gubGVuZ3RoIC0gMl1dKTtcblxuICAgICAgICAgICAgeTIgPSBbMiAqIHlbMF0gLSB5WzFdXTtcbiAgICAgICAgICAgIGZvcihpMiA9IDE7IGkyIDwgeS5sZW5ndGg7IGkyKyspIHtcbiAgICAgICAgICAgICAgICB5Mi5wdXNoKCh5W2kyXSArIHlbaTIgLSAxXSkgLyAyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkyLnB1c2goWzIgKiB5W3kubGVuZ3RoIC0gMV0gLSB5W3kubGVuZ3RoIC0gMl1dKTtcbiAgICAgICAgfVxuICAgICAgICBueCA9IE1hdGgubWF4KDAsIE1hdGgubWluKHgyLmxlbmd0aCAtIDIsIExpYi5maW5kQmluKHh2YWwsIHgyKSkpO1xuICAgICAgICBueSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHkyLmxlbmd0aCAtIDIsIExpYi5maW5kQmluKHl2YWwsIHkyKSkpO1xuICAgIH1cblxuICAgIHZhciB4MCA9IHhhLmMycCh4W254XSksXG4gICAgICAgIHgxID0geGEuYzJwKHhbbnggKyAxXSksXG4gICAgICAgIHkwID0geWEuYzJwKHlbbnldKSxcbiAgICAgICAgeTEgPSB5YS5jMnAoeVtueSArIDFdKTtcblxuICAgIGlmKGNvbnRvdXIpIHtcbiAgICAgICAgeDEgPSB4MDtcbiAgICAgICAgeGwgPSB4W254XTtcbiAgICAgICAgeTEgPSB5MDtcbiAgICAgICAgeWwgPSB5W255XTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHhsID0geGMgPyB4Y1tueF0gOiAoKHhbbnhdICsgeFtueCArIDFdKSAvIDIpO1xuICAgICAgICB5bCA9IHljID8geWNbbnldIDogKCh5W255XSArIHlbbnkgKyAxXSkgLyAyKTtcbiAgICAgICAgaWYodHJhY2UuenNtb290aCkge1xuICAgICAgICAgICAgeDAgPSB4MSA9IHhhLmMycCh4bCk7XG4gICAgICAgICAgICB5MCA9IHkxID0geWEuYzJwKHlsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB6VmFsID0geltueV1bbnhdO1xuICAgIGlmKHptYXNrICYmICF6bWFza1tueV1bbnhdKSB6VmFsID0gdW5kZWZpbmVkO1xuXG4gICAgdmFyIHRleHQ7XG4gICAgaWYoQXJyYXkuaXNBcnJheShjZDAudGV4dCkgJiYgQXJyYXkuaXNBcnJheShjZDAudGV4dFtueV0pKSB7XG4gICAgICAgIHRleHQgPSBjZDAudGV4dFtueV1bbnhdO1xuICAgIH1cblxuICAgIHZhciB6TGFiZWw7XG4gICAgLy8gZHVtbXkgYXhpcyBmb3IgZm9ybWF0dGluZyB0aGUgeiB2YWx1ZVxuICAgIHZhciBkdW1teUF4ID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgcmFuZ2U6IHJhbmdlLFxuICAgICAgICBob3ZlcmZvcm1hdDogemhvdmVyZm9ybWF0LFxuICAgICAgICBfc2VwYXJhdG9yczogeGEuX3NlcGFyYXRvcnMsXG4gICAgICAgIF9udW1Gb3JtYXQ6IHhhLl9udW1Gb3JtYXRcbiAgICB9O1xuICAgIHZhciB6TGFiZWxPYmogPSBBeGVzLnRpY2tUZXh0KGR1bW15QXgsIHpWYWwsICdob3ZlcicpO1xuICAgIHpMYWJlbCA9IHpMYWJlbE9iai50ZXh0O1xuXG4gICAgcmV0dXJuIFtMaWIuZXh0ZW5kRmxhdChwb2ludERhdGEsIHtcbiAgICAgICAgaW5kZXg6IFtueSwgbnhdLFxuICAgICAgICAvLyBuZXZlciBsZXQgYSAyRCBvdmVycmlkZSAxRCB0eXBlIGFzIGNsb3Nlc3QgcG9pbnRcbiAgICAgICAgZGlzdGFuY2U6IHBvaW50RGF0YS5tYXhIb3ZlckRpc3RhbmNlLFxuICAgICAgICBzcGlrZURpc3RhbmNlOiBwb2ludERhdGEubWF4U3Bpa2VEaXN0YW5jZSxcbiAgICAgICAgeDA6IHgwLFxuICAgICAgICB4MTogeDEsXG4gICAgICAgIHkwOiB5MCxcbiAgICAgICAgeTE6IHkxLFxuICAgICAgICB4TGFiZWxWYWw6IHhsLFxuICAgICAgICB5TGFiZWxWYWw6IHlsLFxuICAgICAgICB6TGFiZWxWYWw6IHpWYWwsXG4gICAgICAgIHpMYWJlbDogekxhYmVsLFxuICAgICAgICB0ZXh0OiB0ZXh0XG4gICAgfSldO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgSGVhdG1hcCA9IHt9O1xuXG5IZWF0bWFwLmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbkhlYXRtYXAuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5IZWF0bWFwLmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKTtcbkhlYXRtYXAucGxvdCA9IHJlcXVpcmUoJy4vcGxvdCcpO1xuSGVhdG1hcC5jb2xvcmJhciA9IHJlcXVpcmUoJy4vY29sb3JiYXInKTtcbkhlYXRtYXAuc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG5IZWF0bWFwLmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuXG5IZWF0bWFwLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuSGVhdG1hcC5uYW1lID0gJ2hlYXRtYXAnO1xuSGVhdG1hcC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpO1xuSGVhdG1hcC5jYXRlZ29yaWVzID0gWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJzJkTWFwJ107XG5IZWF0bWFwLm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEhlYXRtYXA7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIElOVEVSUFRIUkVTSE9MRCA9IDFlLTI7XG52YXIgTkVJR0hCT1JTSElGVFMgPSBbWy0xLCAwXSwgWzEsIDBdLCBbMCwgLTFdLCBbMCwgMV1dO1xuXG5mdW5jdGlvbiBjb3JyZWN0aW9uT3ZlcnNob290KG1heEZyYWN0aW9uYWxDaGFuZ2UpIHtcbiAgICAvLyBzdGFydCB3aXRoIGxlc3Mgb3ZlcnNob290LCB1bnRpbCB3ZSBrbm93IGl0J3MgY29udmVyZ2luZyxcbiAgICAvLyB0aGVuIHJhbXAgdXAgdGhlIG92ZXJzaG9vdCBmb3IgZmFzdGVyIGNvbnZlcmdlbmNlXG4gICAgcmV0dXJuIDAuNSAtIDAuMjUgKiBNYXRoLm1pbigxLCBtYXhGcmFjdGlvbmFsQ2hhbmdlICogMC41KTtcbn1cblxuLypcbiAqIGludGVycDJkOiBGaWxsIGluIG1pc3NpbmcgZGF0YSBmcm9tIGEgMkQgYXJyYXkgdXNpbmcgYW4gaXRlcmF0aXZlXG4gKiAgIHBvaXNzb24gZXF1YXRpb24gc29sdmVyIHdpdGggemVyby1kZXJpdmF0aXZlIEJDIGF0IGVkZ2VzLlxuICogICBBbWF6aW5nbHksIHRoaXMganVzdCBhbW91bnRzIHRvIHJlcGVhdGVkbHkgYXZlcmFnaW5nIGFsbCB0aGUgZXhpc3RpbmdcbiAqICAgbmVhcmVzdCBuZWlnaGJvcnMsIGF0IGxlYXN0IGlmIHdlIGRvbid0IHRha2UgeC95IHNjYWxpbmcgaW50byBhY2NvdW50LFxuICogICB3aGljaCBpcyB0aGUgcmlnaHQgYXBwcm9hY2ggaGVyZSB3aGVyZSB4IGFuZCB5IG1heSBub3QgZXZlbiBoYXZlIHRoZVxuICogICBzYW1lIHVuaXRzLlxuICpcbiAqIEBwYXJhbSB7YXJyYXkgb2YgYXJyYXlzfSB6XG4gKiAgICAgIFRoZSAyRCBhcnJheSB0byBmaWxsIGluLiBXaWxsIGJlIG11dGF0ZWQgaGVyZS4gQXNzdW1lZCB0byBhbHJlYWR5IGJlXG4gKiAgICAgIGNsZWFuZWQsIHNvIGFsbCBlbnRyaWVzIGFyZSBudW1iZXJzIGV4Y2VwdCBnYXBzLCB3aGljaCBhcmUgYHVuZGVmaW5lZGAuXG4gKiBAcGFyYW0ge2FycmF5IG9mIGFycmF5c30gZW1wdHlQb2ludHNcbiAqICAgICAgRWFjaCBlbnRyeSBbaSwgaiwgbmVpZ2hib3JDb3VudF0gZm9yIGVtcHR5IHBvaW50cyB6W2ldW2pdIGFuZCB0aGUgbnVtYmVyXG4gKiAgICAgIG9mIG5laWdoYm9ycyB0aGF0IGFyZSAqbm90KiBtaXNzaW5nLiBBc3N1bWVkIHRvIGJlIHNvcnRlZCBmcm9tIG1vc3QgdG9cbiAqICAgICAgbGVhc3QgbmVpZ2hib3JzLCBhcyBwcm9kdWNlZCBieSBoZWF0bWFwL2ZpbmRfZW1wdGllcy5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbnRlcnAyZCh6LCBlbXB0eVBvaW50cykge1xuICAgIHZhciBtYXhGcmFjdGlvbmFsQ2hhbmdlID0gMTtcbiAgICB2YXIgaTtcblxuICAgIC8vIG9uZSBwYXNzIHRvIGZpbGwgaW4gYSBzdGFydGluZyB2YWx1ZSBmb3IgYWxsIHRoZSBlbXB0aWVzXG4gICAgaXRlcmF0ZUludGVycDJkKHosIGVtcHR5UG9pbnRzKTtcblxuICAgIC8vIHdlJ3JlIGRvbid0IG5lZWQgdG8gaXRlcmF0ZSBsb25lIGVtcHRpZXMgLSByZW1vdmUgdGhlbVxuICAgIGZvcihpID0gMDsgaSA8IGVtcHR5UG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGVtcHR5UG9pbnRzW2ldWzJdIDwgNCkgYnJlYWs7XG4gICAgfVxuICAgIC8vIGJ1dCBkb24ndCByZW1vdmUgdGhlc2UgcG9pbnRzIGZyb20gdGhlIG9yaWdpbmFsIGFycmF5LFxuICAgIC8vIHdlJ2xsIHVzZSB0aGVtIGZvciBtYXNraW5nLCBzbyBtYWtlIGEgY29weS5cbiAgICBlbXB0eVBvaW50cyA9IGVtcHR5UG9pbnRzLnNsaWNlKGkpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgMTAwICYmIG1heEZyYWN0aW9uYWxDaGFuZ2UgPiBJTlRFUlBUSFJFU0hPTEQ7IGkrKykge1xuICAgICAgICBtYXhGcmFjdGlvbmFsQ2hhbmdlID0gaXRlcmF0ZUludGVycDJkKHosIGVtcHR5UG9pbnRzLFxuICAgICAgICAgICAgY29ycmVjdGlvbk92ZXJzaG9vdChtYXhGcmFjdGlvbmFsQ2hhbmdlKSk7XG4gICAgfVxuICAgIGlmKG1heEZyYWN0aW9uYWxDaGFuZ2UgPiBJTlRFUlBUSFJFU0hPTEQpIHtcbiAgICAgICAgTGliLmxvZygnaW50ZXJwMmQgZGlkblxcJ3QgY29udmVyZ2UgcXVpY2tseScsIG1heEZyYWN0aW9uYWxDaGFuZ2UpO1xuICAgIH1cblxuICAgIHJldHVybiB6O1xufTtcblxuZnVuY3Rpb24gaXRlcmF0ZUludGVycDJkKHosIGVtcHR5UG9pbnRzLCBvdmVyc2hvb3QpIHtcbiAgICB2YXIgbWF4RnJhY3Rpb25hbENoYW5nZSA9IDAsXG4gICAgICAgIHRoaXNQdCxcbiAgICAgICAgaSxcbiAgICAgICAgaixcbiAgICAgICAgcCxcbiAgICAgICAgcSxcbiAgICAgICAgbmVpZ2hib3JTaGlmdCxcbiAgICAgICAgbmVpZ2hib3JSb3csXG4gICAgICAgIG5laWdoYm9yVmFsLFxuICAgICAgICBuZWlnaGJvckNvdW50LFxuICAgICAgICBuZWlnaGJvclN1bSxcbiAgICAgICAgaW5pdGlhbFZhbCxcbiAgICAgICAgbWluTmVpZ2hib3IsXG4gICAgICAgIG1heE5laWdoYm9yO1xuXG4gICAgZm9yKHAgPSAwOyBwIDwgZW1wdHlQb2ludHMubGVuZ3RoOyBwKyspIHtcbiAgICAgICAgdGhpc1B0ID0gZW1wdHlQb2ludHNbcF07XG4gICAgICAgIGkgPSB0aGlzUHRbMF07XG4gICAgICAgIGogPSB0aGlzUHRbMV07XG4gICAgICAgIGluaXRpYWxWYWwgPSB6W2ldW2pdO1xuICAgICAgICBuZWlnaGJvclN1bSA9IDA7XG4gICAgICAgIG5laWdoYm9yQ291bnQgPSAwO1xuXG4gICAgICAgIGZvcihxID0gMDsgcSA8IDQ7IHErKykge1xuICAgICAgICAgICAgbmVpZ2hib3JTaGlmdCA9IE5FSUdIQk9SU0hJRlRTW3FdO1xuICAgICAgICAgICAgbmVpZ2hib3JSb3cgPSB6W2kgKyBuZWlnaGJvclNoaWZ0WzBdXTtcbiAgICAgICAgICAgIGlmKCFuZWlnaGJvclJvdykgY29udGludWU7XG4gICAgICAgICAgICBuZWlnaGJvclZhbCA9IG5laWdoYm9yUm93W2ogKyBuZWlnaGJvclNoaWZ0WzFdXTtcbiAgICAgICAgICAgIGlmKG5laWdoYm9yVmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZihuZWlnaGJvclN1bSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBtaW5OZWlnaGJvciA9IG1heE5laWdoYm9yID0gbmVpZ2hib3JWYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtaW5OZWlnaGJvciA9IE1hdGgubWluKG1pbk5laWdoYm9yLCBuZWlnaGJvclZhbCk7XG4gICAgICAgICAgICAgICAgICAgIG1heE5laWdoYm9yID0gTWF0aC5tYXgobWF4TmVpZ2hib3IsIG5laWdoYm9yVmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmVpZ2hib3JDb3VudCsrO1xuICAgICAgICAgICAgICAgIG5laWdoYm9yU3VtICs9IG5laWdoYm9yVmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYobmVpZ2hib3JDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgJ2l0ZXJhdGVJbnRlcnAyZCBvcmRlciBpcyB3cm9uZzogbm8gZGVmaW5lZCBuZWlnaGJvcnMnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhpcyBpcyB0aGUgbGFwbGFjZSBlcXVhdGlvbiBpbnRlcnBvbGF0aW9uOlxuICAgICAgICAvLyBlYWNoIHBvaW50IGlzIGp1c3QgdGhlIGF2ZXJhZ2Ugb2YgaXRzIG5laWdoYm9yc1xuICAgICAgICAvLyBub3RlIHRoYXQgdGhpcyBpZ25vcmVzIGRpZmZlcmVudGlhbCB4L3kgc2NhbGluZ1xuICAgICAgICAvLyB3aGljaCBJIHRoaW5rIGlzIHRoZSByaWdodCBhcHByb2FjaCwgc2luY2Ugd2VcbiAgICAgICAgLy8gZG9uJ3Qga25vdyB3aGF0IHRoYXQgc2NhbGluZyBtZWFuc1xuICAgICAgICB6W2ldW2pdID0gbmVpZ2hib3JTdW0gLyBuZWlnaGJvckNvdW50O1xuXG4gICAgICAgIGlmKGluaXRpYWxWYWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYobmVpZ2hib3JDb3VudCA8IDQpIG1heEZyYWN0aW9uYWxDaGFuZ2UgPSAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gd2UgY2FuIG1ha2UgbGFyZ2UgZW1wdHkgcmVnaW9ucyBjb252ZXJnZSBmYXN0ZXJcbiAgICAgICAgICAgIC8vIGlmIHdlIG92ZXJzaG9vdCB0aGUgY2hhbmdlIHZzIHRoZSBwcmV2aW91cyB2YWx1ZVxuICAgICAgICAgICAgeltpXVtqXSA9ICgxICsgb3ZlcnNob290KSAqIHpbaV1bal0gLSBvdmVyc2hvb3QgKiBpbml0aWFsVmFsO1xuXG4gICAgICAgICAgICBpZihtYXhOZWlnaGJvciA+IG1pbk5laWdoYm9yKSB7XG4gICAgICAgICAgICAgICAgbWF4RnJhY3Rpb25hbENoYW5nZSA9IE1hdGgubWF4KG1heEZyYWN0aW9uYWxDaGFuZ2UsXG4gICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKHpbaV1bal0gLSBpbml0aWFsVmFsKSAvIChtYXhOZWlnaGJvciAtIG1pbk5laWdoYm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWF4RnJhY3Rpb25hbENoYW5nZTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQm91bmRBcnJheSh0cmFjZSwgYXJyYXlJbiwgdjBJbiwgZHZJbiwgbnVtYnJpY2tzLCBheCkge1xuICAgIHZhciBhcnJheU91dCA9IFtdLFxuICAgICAgICBpc0NvbnRvdXIgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnY29udG91cicpLFxuICAgICAgICBpc0hpc3QgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnaGlzdG9ncmFtJyksXG4gICAgICAgIGlzR0wyRCA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdnbDJkJyksXG4gICAgICAgIHYwLFxuICAgICAgICBkdixcbiAgICAgICAgaTtcblxuICAgIHZhciBpc0FycmF5T2ZUd29JdGVtc09yTW9yZSA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYXJyYXlJbikgJiYgYXJyYXlJbi5sZW5ndGggPiAxO1xuXG4gICAgaWYoaXNBcnJheU9mVHdvSXRlbXNPck1vcmUgJiYgIWlzSGlzdCAmJiAoYXgudHlwZSAhPT0gJ2NhdGVnb3J5JykpIHtcbiAgICAgICAgdmFyIGxlbiA9IGFycmF5SW4ubGVuZ3RoO1xuXG4gICAgICAgIC8vIGdpdmVuIHZhbHMgYXJlIGJyaWNrIGNlbnRlcnNcbiAgICAgICAgLy8gaG9wZWZ1bGx5IGxlbmd0aCA9PT0gbnVtYnJpY2tzLCBidXQgdXNlIHRoaXMgbWV0aG9kIGV2ZW4gaWYgdG9vIGZldyBhcmUgc3VwcGxpZWRcbiAgICAgICAgLy8gYW5kIGV4dGVuZCBpdCBsaW5lYXJseSBiYXNlZCBvbiB0aGUgbGFzdCB0d28gcG9pbnRzXG4gICAgICAgIGlmKGxlbiA8PSBudW1icmlja3MpIHtcbiAgICAgICAgICAgIC8vIGNvbnRvdXIgcGxvdHMgb25seSB3YW50IHRoZSBjZW50ZXJzXG4gICAgICAgICAgICBpZihpc0NvbnRvdXIgfHwgaXNHTDJEKSBhcnJheU91dCA9IGFycmF5SW4uc2xpY2UoMCwgbnVtYnJpY2tzKTtcbiAgICAgICAgICAgIGVsc2UgaWYobnVtYnJpY2tzID09PSAxKSB7XG4gICAgICAgICAgICAgICAgYXJyYXlPdXQgPSBbYXJyYXlJblswXSAtIDAuNSwgYXJyYXlJblswXSArIDAuNV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dCA9IFsxLjUgKiBhcnJheUluWzBdIC0gMC41ICogYXJyYXlJblsxXV07XG5cbiAgICAgICAgICAgICAgICBmb3IoaSA9IDE7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhcnJheU91dC5wdXNoKChhcnJheUluW2kgLSAxXSArIGFycmF5SW5baV0pICogMC41KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhcnJheU91dC5wdXNoKDEuNSAqIGFycmF5SW5bbGVuIC0gMV0gLSAwLjUgKiBhcnJheUluW2xlbiAtIDJdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYobGVuIDwgbnVtYnJpY2tzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RQdCA9IGFycmF5T3V0W2FycmF5T3V0Lmxlbmd0aCAtIDFdLFxuICAgICAgICAgICAgICAgICAgICBkZWx0YSA9IGxhc3RQdCAtIGFycmF5T3V0W2FycmF5T3V0Lmxlbmd0aCAtIDJdO1xuXG4gICAgICAgICAgICAgICAgZm9yKGkgPSBsZW47IGkgPCBudW1icmlja3M7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsYXN0UHQgKz0gZGVsdGE7XG4gICAgICAgICAgICAgICAgICAgIGFycmF5T3V0LnB1c2gobGFzdFB0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBob3BlZnVsbHkgbGVuZ3RoID09PSBudW1icmlja3MrMSwgYnV0IGRvIHNvbWV0aGluZyByZWdhcmRsZXNzOlxuICAgICAgICAgICAgLy8gZ2l2ZW4gdmFscyBhcmUgYnJpY2sgYm91bmRhcmllc1xuICAgICAgICAgICAgcmV0dXJuIGlzQ29udG91ciA/XG4gICAgICAgICAgICAgICAgYXJyYXlJbi5zbGljZSgwLCBudW1icmlja3MpIDogIC8vIHdlIG11c3QgYmUgc3RyaWN0IGZvciBjb250b3Vyc1xuICAgICAgICAgICAgICAgIGFycmF5SW4uc2xpY2UoMCwgbnVtYnJpY2tzICsgMSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGR2ID0gZHZJbiB8fCAxO1xuXG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRyYWNlW2F4Ll9pZC5jaGFyQXQoMCkgKyAnY2FsZW5kYXInXTtcblxuICAgICAgICBpZihpc0hpc3QgfHwgYXgudHlwZSA9PT0gJ2NhdGVnb3J5JykgdjAgPSBheC5yMmModjBJbiwgMCwgY2FsZW5kYXIpIHx8IDA7XG4gICAgICAgIGVsc2UgaWYoaXNBcnJheU9yVHlwZWRBcnJheShhcnJheUluKSAmJiBhcnJheUluLmxlbmd0aCA9PT0gMSkgdjAgPSBhcnJheUluWzBdO1xuICAgICAgICBlbHNlIGlmKHYwSW4gPT09IHVuZGVmaW5lZCkgdjAgPSAwO1xuICAgICAgICBlbHNlIHYwID0gYXguZDJjKHYwSW4sIDAsIGNhbGVuZGFyKTtcblxuICAgICAgICBmb3IoaSA9IChpc0NvbnRvdXIgfHwgaXNHTDJEKSA/IDAgOiAtMC41OyBpIDwgbnVtYnJpY2tzOyBpKyspIHtcbiAgICAgICAgICAgIGFycmF5T3V0LnB1c2godjAgKyBkdiAqIGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycmF5T3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1heFJvd0xlbmd0aCh6KSB7XG4gICAgdmFyIGxlbiA9IDA7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgei5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZW4gPSBNYXRoLm1heChsZW4sIHpbaV0ubGVuZ3RoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGVuO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIHRpbnljb2xvciA9IHJlcXVpcmUoJ3Rpbnljb2xvcjInKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcblxudmFyIG1heFJvd0xlbmd0aCA9IHJlcXVpcmUoJy4vbWF4X3Jvd19sZW5ndGgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnZCwgcGxvdGluZm8sIGNkaGVhdG1hcHMsIGhlYXRtYXBMYXllcikge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3VwcyhoZWF0bWFwTGF5ZXIsIGNkaGVhdG1hcHMsICdobScpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAgICAgdmFyIHogPSBjZDAuejtcbiAgICAgICAgdmFyIHggPSBjZDAueDtcbiAgICAgICAgdmFyIHkgPSBjZDAueTtcbiAgICAgICAgdmFyIHhjID0gY2QwLnhDZW50ZXI7XG4gICAgICAgIHZhciB5YyA9IGNkMC55Q2VudGVyO1xuICAgICAgICB2YXIgaXNDb250b3VyID0gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2NvbnRvdXInKTtcbiAgICAgICAgdmFyIHpzbW9vdGggPSBpc0NvbnRvdXIgPyAnYmVzdCcgOiB0cmFjZS56c21vb3RoO1xuXG4gICAgICAgIC8vIGdldCB6IGRpbXNcbiAgICAgICAgdmFyIG0gPSB6Lmxlbmd0aDtcbiAgICAgICAgdmFyIG4gPSBtYXhSb3dMZW5ndGgoeik7XG4gICAgICAgIHZhciB4cmV2ID0gZmFsc2U7XG4gICAgICAgIHZhciB5cmV2ID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIGxlZnQsIHJpZ2h0LCB0ZW1wLCB0b3AsIGJvdHRvbSwgaTtcblxuICAgICAgICAvLyBUT0RPOiBpZiB0aGVyZSBhcmUgbXVsdGlwbGUgb3ZlcmxhcHBpbmcgY2F0ZWdvcmljYWwgaGVhdG1hcHMsXG4gICAgICAgIC8vIG9yIGlmIHdlIGFsbG93IGNhdGVnb3J5IHNvcnRpbmcsIHRoZW4gdGhlIGNhdGVnb3JpZXMgbWF5IG5vdCBiZVxuICAgICAgICAvLyBzZXF1ZW50aWFsLi4uIG1heSBuZWVkIHRvIHJlb3JkZXIgYW5kL29yIGV4cGFuZCB6XG5cbiAgICAgICAgLy8gR2V0IGVkZ2VzIG9mIHBuZyBpbiBwaXhlbHMgKHhhLmMycCgpIG1hcHMgYXhlcyBjb29yZGluYXRlcyB0byBwaXhlbCBjb29yZGluYXRlcylcbiAgICAgICAgLy8gZmlndXJlIG91dCBpZiBlaXRoZXIgYXhpcyBpcyByZXZlcnNlZCAoeSBpcyB1c3VhbGx5IHJldmVyc2VkLCBpbiBwaXhlbCBjb29yZHMpXG4gICAgICAgIC8vIGFsc28gY2xpcCB0aGUgaW1hZ2UgdG8gbWF4aW11bSA1MCUgb3V0c2lkZSB0aGUgdmlzaWJsZSBwbG90IGFyZWFcbiAgICAgICAgLy8gYmlnZ2VyIGltYWdlIGxldHMgeW91IHBhbiBtb3JlIG5hdHVyYWxseSwgYnV0IHNsb3dzIHBlcmZvcm1hbmNlLlxuICAgICAgICAvLyBUT0RPOiB1c2UgbG93LXJlc29sdXRpb24gaW1hZ2VzIG91dHNpZGUgdGhlIHZpc2libGUgcGxvdCBmb3IgcGFubmluZ1xuICAgICAgICAvLyB0aGVzZSB3aGlsZSBsb29wcyBmaW5kIHRoZSBmaXJzdCBhbmQgbGFzdCBicmljayBib3VuZHMgdGhhdCBhcmUgZGVmaW5lZFxuICAgICAgICAvLyAoaW4gY2FzZSBvZiBsb2cgb2YgYSBuZWdhdGl2ZSlcbiAgICAgICAgaSA9IDA7XG4gICAgICAgIHdoaWxlKGxlZnQgPT09IHVuZGVmaW5lZCAmJiBpIDwgeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBsZWZ0ID0geGEuYzJwKHhbaV0pO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9XG4gICAgICAgIGkgPSB4Lmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlKHJpZ2h0ID09PSB1bmRlZmluZWQgJiYgaSA+IDApIHtcbiAgICAgICAgICAgIHJpZ2h0ID0geGEuYzJwKHhbaV0pO1xuICAgICAgICAgICAgaS0tO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYocmlnaHQgPCBsZWZ0KSB7XG4gICAgICAgICAgICB0ZW1wID0gcmlnaHQ7XG4gICAgICAgICAgICByaWdodCA9IGxlZnQ7XG4gICAgICAgICAgICBsZWZ0ID0gdGVtcDtcbiAgICAgICAgICAgIHhyZXYgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaSA9IDA7XG4gICAgICAgIHdoaWxlKHRvcCA9PT0gdW5kZWZpbmVkICYmIGkgPCB5Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHRvcCA9IHlhLmMycCh5W2ldKTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICBpID0geS5sZW5ndGggLSAxO1xuICAgICAgICB3aGlsZShib3R0b20gPT09IHVuZGVmaW5lZCAmJiBpID4gMCkge1xuICAgICAgICAgICAgYm90dG9tID0geWEuYzJwKHlbaV0pO1xuICAgICAgICAgICAgaS0tO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYm90dG9tIDwgdG9wKSB7XG4gICAgICAgICAgICB0ZW1wID0gdG9wO1xuICAgICAgICAgICAgdG9wID0gYm90dG9tO1xuICAgICAgICAgICAgYm90dG9tID0gdGVtcDtcbiAgICAgICAgICAgIHlyZXYgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZm9yIGNvbnRvdXJzIHdpdGggaGVhdG1hcCBmaWxsLCB3ZSBnZW5lcmF0ZSB0aGUgYm91bmRhcmllcyBiYXNlZCBvblxuICAgICAgICAvLyBicmljayBjZW50ZXJzIGJ1dCB0aGVuIHVzZSB0aGUgYnJpY2sgZWRnZXMgZm9yIGRyYXdpbmcgdGhlIGJyaWNrc1xuICAgICAgICBpZihpc0NvbnRvdXIpIHtcbiAgICAgICAgICAgIHhjID0geDtcbiAgICAgICAgICAgIHljID0geTtcbiAgICAgICAgICAgIHggPSBjZDAueGZpbGw7XG4gICAgICAgICAgICB5ID0gY2QwLnlmaWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbWFrZSBhbiBpbWFnZSB0aGF0IGdvZXMgYXQgbW9zdCBoYWxmIGEgc2NyZWVuIG9mZiBlaXRoZXIgc2lkZSwgdG8ga2VlcFxuICAgICAgICAvLyB0aW1lIHJlYXNvbmFibGUgd2hlbiB5b3Ugem9vbSBpbi4gaWYgenNtb290aCBpcyB0cnVlL2Zhc3QsIGRvbid0IHdvcnJ5XG4gICAgICAgIC8vIGFib3V0IHRoaXMsIGJlY2F1c2Ugem9vbWluZyBkb2Vzbid0IGluY3JlYXNlIG51bWJlciBvZiBwaXhlbHNcbiAgICAgICAgLy8gaWYgenNtb290aCBpcyBiZXN0LCBkb24ndCBpbmNsdWRlIGFueXRoaW5nIG9mZiBzY3JlZW4gYmVjYXVzZSBpdCB0YWtlcyB0b28gbG9uZ1xuICAgICAgICBpZih6c21vb3RoICE9PSAnZmFzdCcpIHtcbiAgICAgICAgICAgIHZhciBleHRyYSA9IHpzbW9vdGggPT09ICdiZXN0JyA/IDAgOiAwLjU7XG4gICAgICAgICAgICBsZWZ0ID0gTWF0aC5tYXgoLWV4dHJhICogeGEuX2xlbmd0aCwgbGVmdCk7XG4gICAgICAgICAgICByaWdodCA9IE1hdGgubWluKCgxICsgZXh0cmEpICogeGEuX2xlbmd0aCwgcmlnaHQpO1xuICAgICAgICAgICAgdG9wID0gTWF0aC5tYXgoLWV4dHJhICogeWEuX2xlbmd0aCwgdG9wKTtcbiAgICAgICAgICAgIGJvdHRvbSA9IE1hdGgubWluKCgxICsgZXh0cmEpICogeWEuX2xlbmd0aCwgYm90dG9tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpbWFnZVdpZHRoID0gTWF0aC5yb3VuZChyaWdodCAtIGxlZnQpLFxuICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBNYXRoLnJvdW5kKGJvdHRvbSAtIHRvcCk7XG5cbiAgICAgICAgLy8gc2V0dXAgaW1hZ2Ugbm9kZXNcblxuICAgICAgICAvLyBpZiBpbWFnZSBpcyBlbnRpcmVseSBvZmYtc2NyZWVuLCBkb24ndCBldmVuIGRyYXcgaXRcbiAgICAgICAgdmFyIGlzT2ZmU2NyZWVuID0gKGltYWdlV2lkdGggPD0gMCB8fCBpbWFnZUhlaWdodCA8PSAwKTtcblxuICAgICAgICBpZihpc09mZlNjcmVlbikge1xuICAgICAgICAgICAgdmFyIG5vSW1hZ2UgPSBwbG90R3JvdXAuc2VsZWN0QWxsKCdpbWFnZScpLmRhdGEoW10pO1xuICAgICAgICAgICAgbm9JbWFnZS5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBnZW5lcmF0ZSBpbWFnZSBkYXRhXG5cbiAgICAgICAgdmFyIGNhbnZhc1csIGNhbnZhc0g7XG4gICAgICAgIGlmKHpzbW9vdGggPT09ICdmYXN0Jykge1xuICAgICAgICAgICAgY2FudmFzVyA9IG47XG4gICAgICAgICAgICBjYW52YXNIID0gbTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbnZhc1cgPSBpbWFnZVdpZHRoO1xuICAgICAgICAgICAgY2FudmFzSCA9IGltYWdlSGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBjYW52YXNXO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gY2FudmFzSDtcbiAgICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgICB2YXIgc2NsRnVuYyA9IENvbG9yc2NhbGUubWFrZUNvbG9yU2NhbGVGdW5jKFxuICAgICAgICAgICAgQ29sb3JzY2FsZS5leHRyYWN0U2NhbGUoXG4gICAgICAgICAgICAgICAgdHJhY2UuY29sb3JzY2FsZSxcbiAgICAgICAgICAgICAgICB0cmFjZS56bWluLFxuICAgICAgICAgICAgICAgIHRyYWNlLnptYXhcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB7IG5vTnVtZXJpY0NoZWNrOiB0cnVlLCByZXR1cm5BcnJheTogdHJ1ZSB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gbWFwIGJyaWNrIGJvdW5kYXJpZXMgdG8gaW1hZ2UgcGl4ZWxzXG4gICAgICAgIHZhciB4cHgsXG4gICAgICAgICAgICB5cHg7XG4gICAgICAgIGlmKHpzbW9vdGggPT09ICdmYXN0Jykge1xuICAgICAgICAgICAgeHB4ID0geHJldiA/XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oaW5kZXgpIHsgcmV0dXJuIG4gLSAxIC0gaW5kZXg7IH0gOlxuICAgICAgICAgICAgICAgIExpYi5pZGVudGl0eTtcbiAgICAgICAgICAgIHlweCA9IHlyZXYgP1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGluZGV4KSB7IHJldHVybiBtIC0gMSAtIGluZGV4OyB9IDpcbiAgICAgICAgICAgICAgICBMaWIuaWRlbnRpdHk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB4cHggPSBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKE1hdGgucm91bmQoeGEuYzJwKHhbaW5kZXhdKSAtIGxlZnQpLFxuICAgICAgICAgICAgICAgICAgICAwLCBpbWFnZVdpZHRoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB5cHggPSBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKE1hdGgucm91bmQoeWEuYzJwKHlbaW5kZXhdKSAtIHRvcCksXG4gICAgICAgICAgICAgICAgICAgIDAsIGltYWdlSGVpZ2h0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBidWlsZCB0aGUgcGl4ZWwgbWFwIGJyaWNrLWJ5LWJyaWNrXG4gICAgICAgIC8vIGNydWlzZSB0aHJvdWdoIHotbWF0cml4IHJvdy1ieS1yb3dcbiAgICAgICAgLy8gYnVpbGQgYSBicmljayBhdCBlYWNoIHotbWF0cml4IHZhbHVlXG4gICAgICAgIHZhciB5aSA9IHlweCgwKTtcbiAgICAgICAgdmFyIHliID0gW3lpLCB5aV07XG4gICAgICAgIHZhciB4YmkgPSB4cmV2ID8gMCA6IDE7XG4gICAgICAgIHZhciB5YmkgPSB5cmV2ID8gMCA6IDE7XG4gICAgICAgIC8vIGZvciBjb2xsZWN0aW5nIGFuIGF2ZXJhZ2UgbHVtaW5vc2l0eSBvZiB0aGUgaGVhdG1hcFxuICAgICAgICB2YXIgcGl4Y291bnQgPSAwO1xuICAgICAgICB2YXIgcmNvdW50ID0gMDtcbiAgICAgICAgdmFyIGdjb3VudCA9IDA7XG4gICAgICAgIHZhciBiY291bnQgPSAwO1xuXG4gICAgICAgIHZhciB4YiwgaiwgeGksIHYsIHJvdywgYztcblxuICAgICAgICBmdW5jdGlvbiBzZXRDb2xvcih2LCBwaXhzaXplKSB7XG4gICAgICAgICAgICBpZih2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHNjbEZ1bmModik7XG4gICAgICAgICAgICAgICAgY1swXSA9IE1hdGgucm91bmQoY1swXSk7XG4gICAgICAgICAgICAgICAgY1sxXSA9IE1hdGgucm91bmQoY1sxXSk7XG4gICAgICAgICAgICAgICAgY1syXSA9IE1hdGgucm91bmQoY1syXSk7XG5cbiAgICAgICAgICAgICAgICBwaXhjb3VudCArPSBwaXhzaXplO1xuICAgICAgICAgICAgICAgIHJjb3VudCArPSBjWzBdICogcGl4c2l6ZTtcbiAgICAgICAgICAgICAgICBnY291bnQgKz0gY1sxXSAqIHBpeHNpemU7XG4gICAgICAgICAgICAgICAgYmNvdW50ICs9IGNbMl0gKiBwaXhzaXplO1xuICAgICAgICAgICAgICAgIHJldHVybiBjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFswLCAwLCAwLCAwXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGludGVycENvbG9yKHIwLCByMSwgeGludGVycCwgeWludGVycCkge1xuICAgICAgICAgICAgdmFyIHowMCA9IHIwW3hpbnRlcnAuYmluMF07XG4gICAgICAgICAgICBpZih6MDAgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHNldENvbG9yKHVuZGVmaW5lZCwgMSk7XG5cbiAgICAgICAgICAgIHZhciB6MDEgPSByMFt4aW50ZXJwLmJpbjFdLFxuICAgICAgICAgICAgICAgIHoxMCA9IHIxW3hpbnRlcnAuYmluMF0sXG4gICAgICAgICAgICAgICAgejExID0gcjFbeGludGVycC5iaW4xXSxcbiAgICAgICAgICAgICAgICBkeCA9ICh6MDEgLSB6MDApIHx8IDAsXG4gICAgICAgICAgICAgICAgZHkgPSAoejEwIC0gejAwKSB8fCAwLFxuICAgICAgICAgICAgICAgIGR4eTtcblxuICAgICAgICAgICAgLy8gdGhlIGJpbGluZWFyIGludGVycG9sYXRpb24gdGVybSBuZWVkcyBkaWZmZXJlbnQgY2FsY3VsYXRpb25zXG4gICAgICAgICAgICAvLyBmb3IgYWxsIHRoZSBkaWZmZXJlbnQgcGVybXV0YXRpb25zIG9mIG1pc3NpbmcgZGF0YVxuICAgICAgICAgICAgLy8gYW1vbmcgdGhlIG5laWdoYm9ycyBvZiB0aGUgbWFpbiBwb2ludCwgdG8gZW5zdXJlXG4gICAgICAgICAgICAvLyBjb250aW51aXR5IGFjcm9zcyBicmljayBib3VuZGFyaWVzLlxuICAgICAgICAgICAgaWYoejAxID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZih6MTEgPT09IHVuZGVmaW5lZCkgZHh5ID0gMDtcbiAgICAgICAgICAgICAgICBlbHNlIGlmKHoxMCA9PT0gdW5kZWZpbmVkKSBkeHkgPSAyICogKHoxMSAtIHowMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBkeHkgPSAoMiAqIHoxMSAtIHoxMCAtIHowMCkgKiAyIC8gMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoejExID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZih6MTAgPT09IHVuZGVmaW5lZCkgZHh5ID0gMDtcbiAgICAgICAgICAgICAgICBlbHNlIGR4eSA9ICgyICogejAwIC0gejAxIC0gejEwKSAqIDIgLyAzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZih6MTAgPT09IHVuZGVmaW5lZCkgZHh5ID0gKDIgKiB6MTEgLSB6MDEgLSB6MDApICogMiAvIDM7XG4gICAgICAgICAgICBlbHNlIGR4eSA9ICh6MTEgKyB6MDAgLSB6MDEgLSB6MTApO1xuXG4gICAgICAgICAgICByZXR1cm4gc2V0Q29sb3IoejAwICsgeGludGVycC5mcmFjICogZHggKyB5aW50ZXJwLmZyYWMgKiAoZHkgKyB4aW50ZXJwLmZyYWMgKiBkeHkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHpzbW9vdGgpIHsgLy8gYmVzdCBvciBmYXN0LCB3b3JrcyBmYXN0ZXN0IHdpdGggaW1hZ2VEYXRhXG4gICAgICAgICAgICB2YXIgcHhJbmRleCA9IDAsXG4gICAgICAgICAgICAgICAgcGl4ZWxzO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHBpeGVscyA9IG5ldyBVaW50OEFycmF5KGltYWdlV2lkdGggKiBpbWFnZUhlaWdodCAqIDQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2goZSkge1xuICAgICAgICAgICAgICAgIHBpeGVscyA9IG5ldyBBcnJheShpbWFnZVdpZHRoICogaW1hZ2VIZWlnaHQgKiA0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoenNtb290aCA9PT0gJ2Jlc3QnKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhGb3JQeCA9IHhjIHx8IHg7XG4gICAgICAgICAgICAgICAgdmFyIHlGb3JQeCA9IHljIHx8IHk7XG4gICAgICAgICAgICAgICAgdmFyIHhQaXhBcnJheSA9IG5ldyBBcnJheSh4Rm9yUHgubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB2YXIgeVBpeEFycmF5ID0gbmV3IEFycmF5KHlGb3JQeC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHZhciB4aW50ZXJwQXJyYXkgPSBuZXcgQXJyYXkoaW1hZ2VXaWR0aCk7XG4gICAgICAgICAgICAgICAgdmFyIGZpbmRJbnRlcnBYID0geGMgPyBmaW5kSW50ZXJwRnJvbUNlbnRlcnMgOiBmaW5kSW50ZXJwO1xuICAgICAgICAgICAgICAgIHZhciBmaW5kSW50ZXJwWSA9IHljID8gZmluZEludGVycEZyb21DZW50ZXJzIDogZmluZEludGVycDtcbiAgICAgICAgICAgICAgICB2YXIgeWludGVycCwgcjAsIHIxO1xuXG4gICAgICAgICAgICAgICAgLy8gZmlyc3QgbWFrZSBhcnJheXMgb2YgeCBhbmQgeSBwaXhlbCBsb2NhdGlvbnMgb2YgYnJpY2sgYm91bmRhcmllc1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHhGb3JQeC5sZW5ndGg7IGkrKykgeFBpeEFycmF5W2ldID0gTWF0aC5yb3VuZCh4YS5jMnAoeEZvclB4W2ldKSAtIGxlZnQpO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHlGb3JQeC5sZW5ndGg7IGkrKykgeVBpeEFycmF5W2ldID0gTWF0aC5yb3VuZCh5YS5jMnAoeUZvclB4W2ldKSAtIHRvcCk7XG5cbiAgICAgICAgICAgICAgICAvLyB0aGVuIG1ha2UgYXJyYXlzIG9mIGludGVycG9sYXRpb25zXG4gICAgICAgICAgICAgICAgLy8gKGJpbjA9Y2xvc2VzdCwgYmluMT1uZXh0LCBmcmFjPWZyYWN0aW9uYWwgZGlzdC4pXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW1hZ2VXaWR0aDsgaSsrKSB4aW50ZXJwQXJyYXlbaV0gPSBmaW5kSW50ZXJwWChpLCB4UGl4QXJyYXkpO1xuXG4gICAgICAgICAgICAgICAgLy8gbm93IGRvIHRoZSBpbnRlcnBvbGF0aW9ucyBhbmQgZmlsbCB0aGUgcG5nXG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgaW1hZ2VIZWlnaHQ7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB5aW50ZXJwID0gZmluZEludGVycFkoaiwgeVBpeEFycmF5KTtcbiAgICAgICAgICAgICAgICAgICAgcjAgPSB6W3lpbnRlcnAuYmluMF07XG4gICAgICAgICAgICAgICAgICAgIHIxID0gelt5aW50ZXJwLmJpbjFdO1xuICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbWFnZVdpZHRoOyBpKyssIHB4SW5kZXggKz0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9IGludGVycENvbG9yKHIwLCByMSwgeGludGVycEFycmF5W2ldLCB5aW50ZXJwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1dENvbG9yKHBpeGVscywgcHhJbmRleCwgYyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8genNtb290aCA9IGZhc3RcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBtOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0geltqXTtcbiAgICAgICAgICAgICAgICAgICAgeWIgPSB5cHgoaik7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGltYWdlV2lkdGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9IHNldENvbG9yKHJvd1tpXSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBweEluZGV4ID0gKHliICogaW1hZ2VXaWR0aCArIHhweChpKSkgKiA0O1xuICAgICAgICAgICAgICAgICAgICAgICAgcHV0Q29sb3IocGl4ZWxzLCBweEluZGV4LCBjKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGltYWdlRGF0YSA9IGNvbnRleHQuY3JlYXRlSW1hZ2VEYXRhKGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0KTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhLmRhdGEuc2V0KHBpeGVscyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHB4QXJyYXkgPSBpbWFnZURhdGEuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgZGxlbiA9IHB4QXJyYXkubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGRsZW47IGogKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcHhBcnJheVtqXSA9IHBpeGVsc1tqXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnRleHQucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgICAgIH0gZWxzZSB7IC8vIHpzbW9vdGggPSBmYWxzZSAtPiBmaWxsaW5nIHBvdGVudGlhbGx5IGxhcmdlIGJyaWNrcyB3b3JrcyBmYXN0ZXN0IHdpdGggZmlsbFJlY3RcblxuICAgICAgICAgICAgLy8gZ2FwcyBkbyBub3QgbmVlZCB0byBiZSBleGFjdCBpbnRlZ2VycywgYnV0IGlmIHRoZXkgKmFyZSogd2Ugd2lsbCBnZXRcbiAgICAgICAgICAgIC8vIGNsZWFuZXIgZWRnZXMgYnkgcm91bmRpbmcgYXQgbGVhc3Qgb25lIGVkZ2VcbiAgICAgICAgICAgIHZhciB4R2FwID0gdHJhY2UueGdhcDtcbiAgICAgICAgICAgIHZhciB5R2FwID0gdHJhY2UueWdhcDtcbiAgICAgICAgICAgIHZhciB4R2FwTGVmdCA9IE1hdGguZmxvb3IoeEdhcCAvIDIpO1xuICAgICAgICAgICAgdmFyIHlHYXBUb3AgPSBNYXRoLmZsb29yKHlHYXAgLyAyKTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbTsgaisrKSB7XG4gICAgICAgICAgICAgICAgcm93ID0geltqXTtcbiAgICAgICAgICAgICAgICB5Yi5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgeWJbeWJpXSA9IHlweChqICsgMSk7XG4gICAgICAgICAgICAgICAgaWYoeWJbMF0gPT09IHliWzFdIHx8IHliWzBdID09PSB1bmRlZmluZWQgfHwgeWJbMV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgeGkgPSB4cHgoMCk7XG4gICAgICAgICAgICAgICAgeGIgPSBbeGksIHhpXTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYnVpbGQgb25lIGNvbG9yIGJyaWNrIVxuICAgICAgICAgICAgICAgICAgICB4Yi5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgICAgIHhiW3hiaV0gPSB4cHgoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZih4YlswXSA9PT0geGJbMV0gfHwgeGJbMF0gPT09IHVuZGVmaW5lZCB8fCB4YlsxXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2ID0gcm93W2ldO1xuICAgICAgICAgICAgICAgICAgICBjID0gc2V0Q29sb3IodiwgKHhiWzFdIC0geGJbMF0pICogKHliWzFdIC0geWJbMF0pKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgYy5qb2luKCcsJykgKyAnKSc7XG5cbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5maWxsUmVjdCh4YlswXSArIHhHYXBMZWZ0LCB5YlswXSArIHlHYXBUb3AsXG4gICAgICAgICAgICAgICAgICAgICAgICB4YlsxXSAtIHhiWzBdIC0geEdhcCwgeWJbMV0gLSB5YlswXSAtIHlHYXApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJjb3VudCA9IE1hdGgucm91bmQocmNvdW50IC8gcGl4Y291bnQpO1xuICAgICAgICBnY291bnQgPSBNYXRoLnJvdW5kKGdjb3VudCAvIHBpeGNvdW50KTtcbiAgICAgICAgYmNvdW50ID0gTWF0aC5yb3VuZChiY291bnQgLyBwaXhjb3VudCk7XG4gICAgICAgIHZhciBhdmdDb2xvciA9IHRpbnljb2xvcigncmdiKCcgKyByY291bnQgKyAnLCcgKyBnY291bnQgKyAnLCcgKyBiY291bnQgKyAnKScpO1xuXG4gICAgICAgIGdkLl9obXBpeGNvdW50ID0gKGdkLl9obXBpeGNvdW50fHwwKSArIHBpeGNvdW50O1xuICAgICAgICBnZC5faG1sdW1jb3VudCA9IChnZC5faG1sdW1jb3VudHx8MCkgKyBwaXhjb3VudCAqIGF2Z0NvbG9yLmdldEx1bWluYW5jZSgpO1xuXG4gICAgICAgIHZhciBpbWFnZTMgPSBwbG90R3JvdXAuc2VsZWN0QWxsKCdpbWFnZScpXG4gICAgICAgICAgICAuZGF0YShjZCk7XG5cbiAgICAgICAgaW1hZ2UzLmVudGVyKCkuYXBwZW5kKCdzdmc6aW1hZ2UnKS5hdHRyKHtcbiAgICAgICAgICAgIHhtbG5zOiB4bWxuc05hbWVzcGFjZXMuc3ZnLFxuICAgICAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogJ25vbmUnXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGltYWdlMy5hdHRyKHtcbiAgICAgICAgICAgIGhlaWdodDogaW1hZ2VIZWlnaHQsXG4gICAgICAgICAgICB3aWR0aDogaW1hZ2VXaWR0aCxcbiAgICAgICAgICAgIHg6IGxlZnQsXG4gICAgICAgICAgICB5OiB0b3AsXG4gICAgICAgICAgICAneGxpbms6aHJlZic6IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpXG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuLy8gZ2V0IGludGVycG9sYXRlZCBiaW4gdmFsdWUuIFJldHVybnMge2JpbjA6Y2xvc2VzdCBiaW4sIGZyYWM6ZnJhY3Rpb25hbCBkaXN0IHRvIG5leHQsIGJpbjE6bmV4dCBiaW59XG5mdW5jdGlvbiBmaW5kSW50ZXJwKHBpeGVsLCBwaXhBcnJheSkge1xuICAgIHZhciBtYXhCaW4gPSBwaXhBcnJheS5sZW5ndGggLSAyO1xuICAgIHZhciBiaW4gPSBMaWIuY29uc3RyYWluKExpYi5maW5kQmluKHBpeGVsLCBwaXhBcnJheSksIDAsIG1heEJpbik7XG4gICAgdmFyIHBpeDAgPSBwaXhBcnJheVtiaW5dO1xuICAgIHZhciBwaXgxID0gcGl4QXJyYXlbYmluICsgMV07XG4gICAgdmFyIGludGVycCA9IExpYi5jb25zdHJhaW4oYmluICsgKHBpeGVsIC0gcGl4MCkgLyAocGl4MSAtIHBpeDApIC0gMC41LCAwLCBtYXhCaW4pO1xuICAgIHZhciBiaW4wID0gTWF0aC5yb3VuZChpbnRlcnApO1xuICAgIHZhciBmcmFjID0gTWF0aC5hYnMoaW50ZXJwIC0gYmluMCk7XG5cbiAgICBpZighaW50ZXJwIHx8IGludGVycCA9PT0gbWF4QmluIHx8ICFmcmFjKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBiaW4wOiBiaW4wLFxuICAgICAgICAgICAgYmluMTogYmluMCxcbiAgICAgICAgICAgIGZyYWM6IDBcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYmluMDogYmluMCxcbiAgICAgICAgZnJhYzogZnJhYyxcbiAgICAgICAgYmluMTogTWF0aC5yb3VuZChiaW4wICsgZnJhYyAvIChpbnRlcnAgLSBiaW4wKSlcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBmaW5kSW50ZXJwRnJvbUNlbnRlcnMocGl4ZWwsIGNlbnRlclBpeEFycmF5KSB7XG4gICAgdmFyIG1heEJpbiA9IGNlbnRlclBpeEFycmF5Lmxlbmd0aCAtIDE7XG4gICAgdmFyIGJpbiA9IExpYi5jb25zdHJhaW4oTGliLmZpbmRCaW4ocGl4ZWwsIGNlbnRlclBpeEFycmF5KSwgMCwgbWF4QmluKTtcbiAgICB2YXIgcGl4MCA9IGNlbnRlclBpeEFycmF5W2Jpbl07XG4gICAgdmFyIHBpeDEgPSBjZW50ZXJQaXhBcnJheVtiaW4gKyAxXTtcbiAgICB2YXIgZnJhYyA9ICgocGl4ZWwgLSBwaXgwKSAvIChwaXgxIC0gcGl4MCkpIHx8IDA7XG4gICAgaWYoZnJhYyA8PSAwKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBiaW4wOiBiaW4sXG4gICAgICAgICAgICBiaW4xOiBiaW4sXG4gICAgICAgICAgICBmcmFjOiAwXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmKGZyYWMgPCAwLjUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJpbjA6IGJpbixcbiAgICAgICAgICAgIGJpbjE6IGJpbiArIDEsXG4gICAgICAgICAgICBmcmFjOiBmcmFjXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIGJpbjA6IGJpbiArIDEsXG4gICAgICAgIGJpbjE6IGJpbixcbiAgICAgICAgZnJhYzogMSAtIGZyYWNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBwdXRDb2xvcihwaXhlbHMsIHB4SW5kZXgsIGMpIHtcbiAgICBwaXhlbHNbcHhJbmRleF0gPSBjWzBdO1xuICAgIHBpeGVsc1tweEluZGV4ICsgMV0gPSBjWzFdO1xuICAgIHBpeGVsc1tweEluZGV4ICsgMl0gPSBjWzJdO1xuICAgIHBpeGVsc1tweEluZGV4ICsgM10gPSBNYXRoLnJvdW5kKGNbM10gKiAyNTUpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3R5bGUoZ2QpIHtcbiAgICBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnLmhtIGltYWdlJylcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQudHJhY2Uub3BhY2l0eTtcbiAgICAgICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKSB7XG4gICAgdmFyIHpzbW9vdGggPSBjb2VyY2UoJ3pzbW9vdGgnKTtcbiAgICBpZih6c21vb3RoID09PSBmYWxzZSkge1xuICAgICAgICAvLyBlbnN1cmUgdGhhdCB4Z2FwIGFuZCB5Z2FwIGFyZSBjb2VyY2VkIG9ubHkgd2hlbiB6c21vb3RoIGFsbG93cyB0aGVtIHRvIGhhdmUgYW4gZWZmZWN0LlxuICAgICAgICBjb2VyY2UoJ3hnYXAnKTtcbiAgICAgICAgY29lcmNlKCd5Z2FwJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCd6aG92ZXJmb3JtYXQnKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlWFlaRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCB4TmFtZSwgeU5hbWUpIHtcbiAgICB2YXIgeiA9IGNvZXJjZSgneicpO1xuICAgIHhOYW1lID0geE5hbWUgfHwgJ3gnO1xuICAgIHlOYW1lID0geU5hbWUgfHwgJ3knO1xuICAgIHZhciB4LCB5O1xuXG4gICAgaWYoeiA9PT0gdW5kZWZpbmVkIHx8ICF6Lmxlbmd0aCkgcmV0dXJuIDA7XG5cbiAgICBpZihMaWIuaXNBcnJheTFEKHRyYWNlSW4ueikpIHtcbiAgICAgICAgeCA9IGNvZXJjZSh4TmFtZSk7XG4gICAgICAgIHkgPSBjb2VyY2UoeU5hbWUpO1xuXG4gICAgICAgIC8vIGNvbHVtbiB6IG11c3QgYmUgYWNjb21wYW5pZWQgYnkgeE5hbWUgYW5kIHlOYW1lIGFycmF5c1xuICAgICAgICBpZighKHggJiYgeC5sZW5ndGggJiYgeSAmJiB5Lmxlbmd0aCkpIHJldHVybiAwO1xuXG4gICAgICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBNYXRoLm1pbih4Lmxlbmd0aCwgeS5sZW5ndGgsIHoubGVuZ3RoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHggPSBjb29yZERlZmF1bHRzKHhOYW1lLCBjb2VyY2UpO1xuICAgICAgICB5ID0gY29vcmREZWZhdWx0cyh5TmFtZSwgY29lcmNlKTtcblxuICAgICAgICAvLyBUT0RPIHB1dCB6IHZhbGlkYXRpb24gZWxzZXdoZXJlXG4gICAgICAgIGlmKCFpc1ZhbGlkWih6KSkgcmV0dXJuIDA7XG5cbiAgICAgICAgY29lcmNlKCd0cmFuc3Bvc2UnKTtcblxuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbeE5hbWUsIHlOYW1lXSwgbGF5b3V0KTtcblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuZnVuY3Rpb24gY29vcmREZWZhdWx0cyhjb29yZFN0ciwgY29lcmNlKSB7XG4gICAgdmFyIGNvb3JkID0gY29lcmNlKGNvb3JkU3RyKSxcbiAgICAgICAgY29vcmRUeXBlID0gY29vcmQgP1xuICAgICAgICAgICAgY29lcmNlKGNvb3JkU3RyICsgJ3R5cGUnLCAnYXJyYXknKSA6XG4gICAgICAgICAgICAnc2NhbGVkJztcblxuICAgIGlmKGNvb3JkVHlwZSA9PT0gJ3NjYWxlZCcpIHtcbiAgICAgICAgY29lcmNlKGNvb3JkU3RyICsgJzAnKTtcbiAgICAgICAgY29lcmNlKCdkJyArIGNvb3JkU3RyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29vcmQ7XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWRaKHopIHtcbiAgICB2YXIgYWxsUm93c0FyZUFycmF5cyA9IHRydWUsXG4gICAgICAgIG9uZVJvd0lzRmlsbGVkID0gZmFsc2UsXG4gICAgICAgIGhhc09uZU51bWJlciA9IGZhbHNlLFxuICAgICAgICB6aTtcblxuICAgIC8qXG4gICAgICogV2l0aG91dCB0aGlzIHN0ZXA6XG4gICAgICpcbiAgICAgKiBoYXNPbmVOdW1iZXIgPSBmYWxzZSBicmVha3MgY29udG91ciBidXQgbm90IGhlYXRtYXBcbiAgICAgKiBhbGxSb3dzQXJlQXJyYXlzID0gZmFsc2UgYnJlYWtzIGNvbnRvdXIgYnV0IG5vdCBoZWF0bWFwXG4gICAgICogb25lUm93SXNGaWxsZWQgPSBmYWxzZSBicmVha3MgYm90aFxuICAgICAqL1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHoubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgemkgPSB6W2ldO1xuICAgICAgICBpZighTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoemkpKSB7XG4gICAgICAgICAgICBhbGxSb3dzQXJlQXJyYXlzID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZih6aS5sZW5ndGggPiAwKSBvbmVSb3dJc0ZpbGxlZCA9IHRydWU7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB6aS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYoaXNOdW1lcmljKHppW2pdKSkge1xuICAgICAgICAgICAgICAgIGhhc09uZU51bWJlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gKGFsbFJvd3NBcmVBcnJheXMgJiYgb25lUm93SXNGaWxsZWQgJiYgaGFzT25lTnVtYmVyKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgaGVhdG1hcEF0dHJzID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cblxudmFyIGNvbW1vbkxpc3QgPSBbXG4gICAgJ3onLFxuICAgICd4JywgJ3gwJywgJ2R4JyxcbiAgICAneScsICd5MCcsICdkeScsXG4gICAgJ3RleHQnLCAndHJhbnNwb3NlJyxcbiAgICAneHR5cGUnLCAneXR5cGUnXG5dO1xuXG52YXIgYXR0cnMgPSB7fTtcblxuZm9yKHZhciBpID0gMDsgaSA8IGNvbW1vbkxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgayA9IGNvbW1vbkxpc3RbaV07XG4gICAgYXR0cnNba10gPSBoZWF0bWFwQXR0cnNba107XG59XG5cbmV4dGVuZEZsYXQoXG4gICAgYXR0cnMsXG4gICAgY29sb3JzY2FsZUF0dHJzKCcnLCB7Y0xldHRlcjogJ3onLCBhdXRvQ29sb3JEZmx0OiBmYWxzZX0pLFxuICAgIHtjb2xvcmJhcjogY29sb3JiYXJBdHRyc31cbik7XG5cbm1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoYXR0cnMsICdjYWxjJywgJ25lc3RlZCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVIZWF0bWFwMkQgPSByZXF1aXJlKCdnbC1oZWF0bWFwMmQnKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBzdHIyUkdCQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG5cblxuZnVuY3Rpb24gSGVhdG1hcChzY2VuZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMudHlwZSA9ICdoZWF0bWFwZ2wnO1xuXG4gICAgdGhpcy5uYW1lID0gJyc7XG4gICAgdGhpcy5ob3ZlcmluZm8gPSAnYWxsJztcblxuICAgIHRoaXMueERhdGEgPSBbXTtcbiAgICB0aGlzLnlEYXRhID0gW107XG4gICAgdGhpcy56RGF0YSA9IFtdO1xuICAgIHRoaXMudGV4dExhYmVscyA9IFtdO1xuXG4gICAgdGhpcy5pZFRvSW5kZXggPSBbXTtcbiAgICB0aGlzLmJvdW5kcyA9IFswLCAwLCAwLCAwXTtcblxuICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgejogW10sXG4gICAgICAgIHg6IFtdLFxuICAgICAgICB5OiBbXSxcbiAgICAgICAgc2hhcGU6IFswLCAwXSxcbiAgICAgICAgY29sb3JMZXZlbHM6IFswXSxcbiAgICAgICAgY29sb3JWYWx1ZXM6IFswLCAwLCAwLCAxXVxuICAgIH07XG5cbiAgICB0aGlzLmhlYXRtYXAgPSBjcmVhdGVIZWF0bWFwMkQoc2NlbmUuZ2xwbG90LCB0aGlzLm9wdGlvbnMpO1xuICAgIHRoaXMuaGVhdG1hcC5fdHJhY2UgPSB0aGlzO1xufVxuXG52YXIgcHJvdG8gPSBIZWF0bWFwLnByb3RvdHlwZTtcblxucHJvdG8uaGFuZGxlUGljayA9IGZ1bmN0aW9uKHBpY2tSZXN1bHQpIHtcbiAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgc2hhcGUgPSBvcHRpb25zLnNoYXBlLFxuICAgICAgICBpbmRleCA9IHBpY2tSZXN1bHQucG9pbnRJZCxcbiAgICAgICAgeEluZGV4ID0gaW5kZXggJSBzaGFwZVswXSxcbiAgICAgICAgeUluZGV4ID0gTWF0aC5mbG9vcihpbmRleCAvIHNoYXBlWzBdKSxcbiAgICAgICAgekluZGV4ID0gaW5kZXg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0cmFjZTogdGhpcyxcbiAgICAgICAgZGF0YUNvb3JkOiBwaWNrUmVzdWx0LmRhdGFDb29yZCxcbiAgICAgICAgdHJhY2VDb29yZDogW1xuICAgICAgICAgICAgb3B0aW9ucy54W3hJbmRleF0sXG4gICAgICAgICAgICBvcHRpb25zLnlbeUluZGV4XSxcbiAgICAgICAgICAgIG9wdGlvbnMuelt6SW5kZXhdXG4gICAgICAgIF0sXG4gICAgICAgIHRleHRMYWJlbDogdGhpcy50ZXh0TGFiZWxzW2luZGV4XSxcbiAgICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgICBwb2ludEluZGV4OiBbeUluZGV4LCB4SW5kZXhdLFxuICAgICAgICBob3ZlcmluZm86IHRoaXMuaG92ZXJpbmZvXG4gICAgfTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGZ1bGxUcmFjZSwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIGNhbGNQdCA9IGNhbGNUcmFjZVswXTtcblxuICAgIHRoaXMuaW5kZXggPSBmdWxsVHJhY2UuaW5kZXg7XG4gICAgdGhpcy5uYW1lID0gZnVsbFRyYWNlLm5hbWU7XG4gICAgdGhpcy5ob3ZlcmluZm8gPSBmdWxsVHJhY2UuaG92ZXJpbmZvO1xuXG4gICAgLy8gY29udmVydCB6IGZyb20gMkQgLT4gMURcbiAgICB2YXIgeiA9IGNhbGNQdC56O1xuICAgIHRoaXMub3B0aW9ucy56ID0gW10uY29uY2F0LmFwcGx5KFtdLCB6KTtcblxuICAgIHZhciByb3dMZW4gPSB6WzBdLmxlbmd0aCxcbiAgICAgICAgY29sTGVuID0gei5sZW5ndGg7XG4gICAgdGhpcy5vcHRpb25zLnNoYXBlID0gW3Jvd0xlbiwgY29sTGVuXTtcblxuICAgIHRoaXMub3B0aW9ucy54ID0gY2FsY1B0Lng7XG4gICAgdGhpcy5vcHRpb25zLnkgPSBjYWxjUHQueTtcblxuICAgIHZhciBjb2xvck9wdGlvbnMgPSBjb252ZXJ0Q29sb3JzY2FsZShmdWxsVHJhY2UpO1xuICAgIHRoaXMub3B0aW9ucy5jb2xvckxldmVscyA9IGNvbG9yT3B0aW9ucy5jb2xvckxldmVscztcbiAgICB0aGlzLm9wdGlvbnMuY29sb3JWYWx1ZXMgPSBjb2xvck9wdGlvbnMuY29sb3JWYWx1ZXM7XG5cbiAgICAvLyBjb252ZXJ0IHRleHQgZnJvbSAyRCAtPiAxRFxuICAgIHRoaXMudGV4dExhYmVscyA9IFtdLmNvbmNhdC5hcHBseShbXSwgZnVsbFRyYWNlLnRleHQpO1xuXG4gICAgdGhpcy5oZWF0bWFwLnVwZGF0ZSh0aGlzLm9wdGlvbnMpO1xuXG4gICAgdmFyIHhhID0gdGhpcy5zY2VuZS54YXhpcztcbiAgICB2YXIgeWEgPSB0aGlzLnNjZW5lLnlheGlzO1xuICAgIGZ1bGxUcmFjZS5fZXh0cmVtZXNbeGEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHhhLCBjYWxjUHQueCk7XG4gICAgZnVsbFRyYWNlLl9leHRyZW1lc1t5YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeWEsIGNhbGNQdC55KTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmhlYXRtYXAuZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY29udmVydENvbG9yc2NhbGUoZnVsbFRyYWNlKSB7XG4gICAgdmFyIHNjbCA9IGZ1bGxUcmFjZS5jb2xvcnNjYWxlLFxuICAgICAgICB6bWluID0gZnVsbFRyYWNlLnptaW4sXG4gICAgICAgIHptYXggPSBmdWxsVHJhY2Uuem1heDtcblxuICAgIHZhciBOID0gc2NsLmxlbmd0aCxcbiAgICAgICAgZG9tYWluID0gbmV3IEFycmF5KE4pLFxuICAgICAgICByYW5nZSA9IG5ldyBBcnJheSg0ICogTik7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICAgIHZhciBzaSA9IHNjbFtpXTtcbiAgICAgICAgdmFyIGNvbG9yID0gc3RyMlJHQkFycmF5KHNpWzFdKTtcblxuICAgICAgICBkb21haW5baV0gPSB6bWluICsgc2lbMF0gKiAoem1heCAtIHptaW4pO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCA0OyBqKyspIHtcbiAgICAgICAgICAgIHJhbmdlWyg0ICogaSkgKyBqXSA9IGNvbG9yW2pdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sb3JMZXZlbHM6IGRvbWFpbixcbiAgICAgICAgY29sb3JWYWx1ZXM6IHJhbmdlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlSGVhdG1hcChzY2VuZSwgZnVsbFRyYWNlLCBjYWxjVHJhY2UpIHtcbiAgICB2YXIgcGxvdCA9IG5ldyBIZWF0bWFwKHNjZW5lLCBmdWxsVHJhY2UudWlkKTtcbiAgICBwbG90LnVwZGF0ZShmdWxsVHJhY2UsIGNhbGNUcmFjZSk7XG4gICAgcmV0dXJuIHBsb3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlSGVhdG1hcDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgSGVhdG1hcEdsID0ge307XG5cbkhlYXRtYXBHbC5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5IZWF0bWFwR2wuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2RlZmF1bHRzJyk7XG5IZWF0bWFwR2wuY29sb3JiYXIgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NvbG9yYmFyJyk7XG5cbkhlYXRtYXBHbC5jYWxjID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9jYWxjJyk7XG5IZWF0bWFwR2wucGxvdCA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xuXG5IZWF0bWFwR2wubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5IZWF0bWFwR2wubmFtZSA9ICdoZWF0bWFwZ2wnO1xuSGVhdG1hcEdsLmJhc2VQbG90TW9kdWxlID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2wyZCcpO1xuSGVhdG1hcEdsLmNhdGVnb3JpZXMgPSBbJ2dsJywgJ2dsMmQnLCAnMmRNYXAnXTtcbkhlYXRtYXBHbC5tZXRhID0ge1xuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBIZWF0bWFwR2w7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBiYXJBdHRycyA9IHJlcXVpcmUoJy4uL2Jhci9hdHRyaWJ1dGVzJyk7XG52YXIgbWFrZUJpbkF0dHJzID0gcmVxdWlyZSgnLi9iaW5fYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IGJhckF0dHJzLnRleHQsXG4gICAgb3JpZW50YXRpb246IGJhckF0dHJzLm9yaWVudGF0aW9uLFxuXG4gICAgaGlzdGZ1bmM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnY291bnQnLCAnc3VtJywgJ2F2ZycsICdtaW4nLCAnbWF4J10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnY291bnQnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhpc3Rub3JtOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJycsICdwZXJjZW50JywgJ3Byb2JhYmlsaXR5JywgJ2RlbnNpdHknLCAncHJvYmFiaWxpdHkgZGVuc2l0eSddLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjdW11bGF0aXZlOiB7XG4gICAgICAgIGVuYWJsZWQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgZGlyZWN0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnaW5jcmVhc2luZycsICdkZWNyZWFzaW5nJ10sXG4gICAgICAgICAgICBkZmx0OiAnaW5jcmVhc2luZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBjdXJyZW50YmluOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnaW5jbHVkZScsICdleGNsdWRlJywgJ2hhbGYnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdpbmNsdWRlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICBuYmluc3g6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhiaW5zOiBtYWtlQmluQXR0cnMoJ3gnLCB0cnVlKSxcblxuICAgIG5iaW5zeToge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWJpbnM6IG1ha2VCaW5BdHRycygneScsIHRydWUpLFxuICAgIGF1dG9iaW54OiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXV0b2Jpbnk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7XG4gICAgICAgICAgICAneWJpbnMuc3RhcnQnOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAneWJpbnMuZW5kJzogdW5kZWZpbmVkLFxuICAgICAgICAgICAgJ3liaW5zLnNpemUnOiB1bmRlZmluZWRcbiAgICAgICAgfSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIG1hcmtlcjogYmFyQXR0cnMubWFya2VyLFxuXG4gICAgc2VsZWN0ZWQ6IGJhckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IGJhckF0dHJzLnVuc2VsZWN0ZWQsXG5cbiAgICBfZGVwcmVjYXRlZDoge1xuICAgICAgICBiYXJkaXI6IGJhckF0dHJzLl9kZXByZWNhdGVkLmJhcmRpclxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRvQXZnKHNpemUsIGNvdW50cykge1xuICAgIHZhciBuTWF4ID0gc2l6ZS5sZW5ndGgsXG4gICAgICAgIHRvdGFsID0gMDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbk1heDsgaSsrKSB7XG4gICAgICAgIGlmKGNvdW50c1tpXSkge1xuICAgICAgICAgICAgc2l6ZVtpXSAvPSBjb3VudHNbaV07XG4gICAgICAgICAgICB0b3RhbCArPSBzaXplW2ldO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Ugc2l6ZVtpXSA9IG51bGw7XG4gICAgfVxuICAgIHJldHVybiB0b3RhbDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUJpbkF0dHJzKGF4TGV0dGVyLCBtYXRjaCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYW55JywgLy8gZm9yIGRhdGUgYXhlc1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVuZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2FueScsIC8vIGZvciBkYXRlIGF4ZXNcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYW55JywgLy8gZm9yIGRhdGUgYXhlc1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjb3VudDogZnVuY3Rpb24obiwgaSwgc2l6ZSkge1xuICAgICAgICBzaXplW25dKys7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH0sXG5cbiAgICBzdW06IGZ1bmN0aW9uKG4sIGksIHNpemUsIGNvdW50ZXJEYXRhKSB7XG4gICAgICAgIHZhciB2ID0gY291bnRlckRhdGFbaV07XG4gICAgICAgIGlmKGlzTnVtZXJpYyh2KSkge1xuICAgICAgICAgICAgdiA9IE51bWJlcih2KTtcbiAgICAgICAgICAgIHNpemVbbl0gKz0gdjtcbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH0sXG5cbiAgICBhdmc6IGZ1bmN0aW9uKG4sIGksIHNpemUsIGNvdW50ZXJEYXRhLCBjb3VudHMpIHtcbiAgICAgICAgdmFyIHYgPSBjb3VudGVyRGF0YVtpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKHYpKSB7XG4gICAgICAgICAgICB2ID0gTnVtYmVyKHYpO1xuICAgICAgICAgICAgc2l6ZVtuXSArPSB2O1xuICAgICAgICAgICAgY291bnRzW25dKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfSxcblxuICAgIG1pbjogZnVuY3Rpb24obiwgaSwgc2l6ZSwgY291bnRlckRhdGEpIHtcbiAgICAgICAgdmFyIHYgPSBjb3VudGVyRGF0YVtpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKHYpKSB7XG4gICAgICAgICAgICB2ID0gTnVtYmVyKHYpO1xuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhzaXplW25dKSkge1xuICAgICAgICAgICAgICAgIHNpemVbbl0gPSB2O1xuICAgICAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihzaXplW25dID4gdikge1xuICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHYgLSBzaXplW25dO1xuICAgICAgICAgICAgICAgIHNpemVbbl0gPSB2O1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWx0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9LFxuXG4gICAgbWF4OiBmdW5jdGlvbihuLCBpLCBzaXplLCBjb3VudGVyRGF0YSkge1xuICAgICAgICB2YXIgdiA9IGNvdW50ZXJEYXRhW2ldO1xuICAgICAgICBpZihpc051bWVyaWModikpIHtcbiAgICAgICAgICAgIHYgPSBOdW1iZXIodik7XG4gICAgICAgICAgICBpZighaXNOdW1lcmljKHNpemVbbl0pKSB7XG4gICAgICAgICAgICAgICAgc2l6ZVtuXSA9IHY7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHNpemVbbl0gPCB2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlbHRhID0gdiAtIHNpemVbbl07XG4gICAgICAgICAgICAgICAgc2l6ZVtuXSA9IHY7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlbHRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG51bUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcbnZhciBvbmVZZWFyID0gbnVtQ29uc3RhbnRzLk9ORUFWR1lFQVI7XG52YXIgb25lTW9udGggPSBudW1Db25zdGFudHMuT05FQVZHTU9OVEg7XG52YXIgb25lRGF5ID0gbnVtQ29uc3RhbnRzLk9ORURBWTtcbnZhciBvbmVIb3VyID0gbnVtQ29uc3RhbnRzLk9ORUhPVVI7XG52YXIgb25lTWluID0gbnVtQ29uc3RhbnRzLk9ORU1JTjtcbnZhciBvbmVTZWMgPSBudW1Db25zdGFudHMuT05FU0VDO1xudmFyIHRpY2tJbmNyZW1lbnQgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLnRpY2tJbmNyZW1lbnQ7XG5cblxuLypcbiAqIG1ha2UgYSBmdW5jdGlvbiB0aGF0IHdpbGwgZmluZCByb3VuZGVkIGJpbiBlZGdlc1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnRHYXA6IGhvdyBmYXIgZnJvbSB0aGUgbGVmdCBlZGdlIG9mIGFueSBiaW4gaXMgdGhlIGNsb3Nlc3QgZGF0YSB2YWx1ZT9cbiAqIEBwYXJhbSB7bnVtYmVyfSByaWdodEdhcDogaG93IGZhciBmcm9tIHRoZSByaWdodCBlZGdlIG9mIGFueSBiaW4gaXMgdGhlIGNsb3Nlc3QgZGF0YSB2YWx1ZT9cbiAqIEBwYXJhbSB7QXJyYXlbbnVtYmVyXX0gYmluRWRnZXM6IHRoZSBhY3R1YWwgZWRnZSB2YWx1ZXMgdXNlZCBpbiBiaW5uaW5nXG4gKiBAcGFyYW0ge29iamVjdH0gcGE6IHRoZSBwb3NpdGlvbiBheGlzXG4gKiBAcGFyYW0ge3N0cmluZ30gY2FsZW5kYXI6IHRoZSBkYXRhIGNhbGVuZGFyXG4gKlxuICogQHJldHVybiB7ZnVuY3Rpb24odiwgaXNSaWdodEVkZ2UpfTpcbiAqICAgZmluZCB0aGUgc3RhcnQgKGlzUmlnaHRFZGdlIGlzIGZhbHN5KSBvciBlbmQgKHRydXRoeSkgbGFiZWwgdmFsdWUgZm9yIGEgYmluIGVkZ2UgYHZgXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0QmluU3BhbkxhYmVsUm91bmQobGVmdEdhcCwgcmlnaHRHYXAsIGJpbkVkZ2VzLCBwYSwgY2FsZW5kYXIpIHtcbiAgICAvLyB0aGUgcm91bmRpbmcgZGlnaXQgaXMgdGhlIGxhcmdlc3QgZGlnaXQgdGhhdCBjaGFuZ2VzIGluICphbGwqIG9mIDQgcmVnaW9uczpcbiAgICAvLyAtIGluc2lkZSB0aGUgcmlnaHRHYXAgYmVmb3JlIGJpbkVkZ2VzWzBdIChzaGlmdGVkIDEwJSB0byB0aGUgbGVmdClcbiAgICAvLyAtIGluc2lkZSB0aGUgbGVmdEdhcCBhZnRlciBiaW5FZGdlc1swXSAoZXhwYW5kZWQgYnkgMTAlIG9mIHJpZ2h0R2FwIG9uIGVhY2ggZW5kKVxuICAgIC8vIC0gc2FtZSBmb3IgYmluRWRnZXNbMV1cbiAgICB2YXIgZHYwID0gLTEuMSAqIHJpZ2h0R2FwO1xuICAgIHZhciBkdjEgPSAtMC4xICogcmlnaHRHYXA7XG4gICAgdmFyIGR2MiA9IGxlZnRHYXAgLSBkdjE7XG4gICAgdmFyIGVkZ2UwID0gYmluRWRnZXNbMF07XG4gICAgdmFyIGVkZ2UxID0gYmluRWRnZXNbMV07XG4gICAgdmFyIGxlZnREaWdpdCA9IE1hdGgubWluKFxuICAgICAgICBiaWdnZXN0RGlnaXRDaGFuZ2VkKGVkZ2UwICsgZHYxLCBlZGdlMCArIGR2MiwgcGEsIGNhbGVuZGFyKSxcbiAgICAgICAgYmlnZ2VzdERpZ2l0Q2hhbmdlZChlZGdlMSArIGR2MSwgZWRnZTEgKyBkdjIsIHBhLCBjYWxlbmRhcilcbiAgICApO1xuICAgIHZhciByaWdodERpZ2l0ID0gTWF0aC5taW4oXG4gICAgICAgIGJpZ2dlc3REaWdpdENoYW5nZWQoZWRnZTAgKyBkdjAsIGVkZ2UwICsgZHYxLCBwYSwgY2FsZW5kYXIpLFxuICAgICAgICBiaWdnZXN0RGlnaXRDaGFuZ2VkKGVkZ2UxICsgZHYwLCBlZGdlMSArIGR2MSwgcGEsIGNhbGVuZGFyKVxuICAgICk7XG5cbiAgICAvLyBub3JtYWxseSB3ZSB0cnkgdG8gbWFrZSB0aGUgbGFiZWwgZm9yIHRoZSByaWdodCBlZGdlIGRpZmZlcmVudCBmcm9tXG4gICAgLy8gdGhlIGxlZnQgZWRnZSBsYWJlbCwgc28gaXQncyB1bmFtYmlndW91cyB3aGljaCBiaW4gZ2V0cyBkYXRhIG9uIHRoZSBlZGdlLlxuICAgIC8vIGJ1dCBpZiB0aGlzIHJlc3VsdHMgaW4gbW9yZSB0aGFuIDMgZXh0cmEgZGlnaXRzIChvciBmb3IgZGF0ZXMsIG1vcmUgdGhhblxuICAgIC8vIDIgZmllbGRzIGllIGhyJm1pbiBvciBtaW4mc2VjLCB3aGljaCBpcyAzNjAweCksIGl0J2xsIGJlIG1vcmUgY2x1dHRlciB0aGFuXG4gICAgLy8gdXNlZnVsIHNvIGtlZXAgdGhlIGxhYmVsIGNsZWFuZXIgaW5zdGVhZFxuICAgIHZhciBkaWdpdCwgZGlzYW1iaWd1YXRlRWRnZXM7XG4gICAgaWYobGVmdERpZ2l0ID4gcmlnaHREaWdpdCAmJiByaWdodERpZ2l0IDwgTWF0aC5hYnMoZWRnZTEgLSBlZGdlMCkgLyA0MDAwKSB7XG4gICAgICAgIGRpZ2l0ID0gbGVmdERpZ2l0O1xuICAgICAgICBkaXNhbWJpZ3VhdGVFZGdlcyA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGlnaXQgPSBNYXRoLm1pbihsZWZ0RGlnaXQsIHJpZ2h0RGlnaXQpO1xuICAgICAgICBkaXNhbWJpZ3VhdGVFZGdlcyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYocGEudHlwZSA9PT0gJ2RhdGUnICYmIGRpZ2l0ID4gb25lRGF5KSB7XG4gICAgICAgIHZhciBkYXNoRXhjbHVkZSA9IChkaWdpdCA9PT0gb25lWWVhcikgPyAxIDogNjtcbiAgICAgICAgdmFyIGluY3JlbWVudCA9IChkaWdpdCA9PT0gb25lWWVhcikgPyAnTTEyJyA6ICdNMSc7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYsIGlzUmlnaHRFZGdlKSB7XG4gICAgICAgICAgICB2YXIgZGF0ZVN0ciA9IHBhLmMyZCh2LCBvbmVZZWFyLCBjYWxlbmRhcik7XG4gICAgICAgICAgICB2YXIgZGFzaFBvcyA9IGRhdGVTdHIuaW5kZXhPZignLScsIGRhc2hFeGNsdWRlKTtcbiAgICAgICAgICAgIGlmKGRhc2hQb3MgPiAwKSBkYXRlU3RyID0gZGF0ZVN0ci5zdWJzdHIoMCwgZGFzaFBvcyk7XG4gICAgICAgICAgICB2YXIgcm91bmRlZFYgPSBwYS5kMmMoZGF0ZVN0ciwgMCwgY2FsZW5kYXIpO1xuXG4gICAgICAgICAgICBpZihyb3VuZGVkViA8IHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dFYgPSB0aWNrSW5jcmVtZW50KHJvdW5kZWRWLCBpbmNyZW1lbnQsIGZhbHNlLCBjYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgaWYoKHJvdW5kZWRWICsgbmV4dFYpIC8gMiA8IHYgKyBsZWZ0R2FwKSByb3VuZGVkViA9IG5leHRWO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc1JpZ2h0RWRnZSAmJiBkaXNhbWJpZ3VhdGVFZGdlcykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aWNrSW5jcmVtZW50KHJvdW5kZWRWLCBpbmNyZW1lbnQsIHRydWUsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJvdW5kZWRWO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbih2LCBpc1JpZ2h0RWRnZSkge1xuICAgICAgICB2YXIgcm91bmRlZFYgPSBkaWdpdCAqIE1hdGgucm91bmQodiAvIGRpZ2l0KTtcbiAgICAgICAgLy8gaWYgd2Ugcm91bmRlZCBkb3duIGFuZCB3ZSBjb3VsZCByb3VuZCB1cCBhbmQgc3RpbGwgYmUgPCBsZWZ0R2FwXG4gICAgICAgIC8vIChvciB3aGF0IGxlZnRHYXAgdmFsdWVzIHJvdW5kIHRvKSwgZG8gdGhhdFxuICAgICAgICBpZihyb3VuZGVkViArIChkaWdpdCAvIDEwKSA8IHYgJiYgcm91bmRlZFYgKyAoZGlnaXQgKiAwLjkpIDwgdiArIGxlZnRHYXApIHtcbiAgICAgICAgICAgIHJvdW5kZWRWICs9IGRpZ2l0O1xuICAgICAgICB9XG4gICAgICAgIC8vIGZpbmFsbHkgZm9yIHRoZSByaWdodCBlZGdlIGJhY2sgb2ZmIG9uZSBkaWdpdCAtIGJ1dCBvbmx5IGlmIHdlIGNhbiBkbyB0aGF0XG4gICAgICAgIC8vIGFuZCBub3QgY2xpcCBvZmYgYW55IGRhdGEgdGhhdCdzIHBvdGVudGlhbGx5IGluIHRoZSBiaW5cbiAgICAgICAgaWYoaXNSaWdodEVkZ2UgJiYgZGlzYW1iaWd1YXRlRWRnZXMpIHtcbiAgICAgICAgICAgIHJvdW5kZWRWIC09IGRpZ2l0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3VuZGVkVjtcbiAgICB9O1xufTtcblxuLypcbiAqIEZpbmQgdGhlIGxhcmdlc3QgZGlnaXQgdGhhdCBjaGFuZ2VzIHdpdGhpbiBhIChjYWxjZGF0YSkgcmVnaW9uIFt2MSwgdjJdXG4gKiBpZiBkYXRlcywgXCJkaWdpdFwiIG1lYW5zIGRhdGUvdGltZSBwYXJ0IHdoZW4gaXQncyBiaWdnZXIgdGhhbiBhIHNlY29uZFxuICogcmV0dXJucyB0aGUgdW5pdCB2YWx1ZSB0byByb3VuZCB0byB0aGlzIGRpZ2l0LCBlZyAwLjAxIHRvIHJvdW5kIHRvIGh1bmRyZWR0aHMsIG9yXG4gKiAxMDAgdG8gcm91bmQgdG8gaHVuZHJlZHMuIHJldHVybnMgb25lTW9udGggb3Igb25lWWVhciBmb3IgbW9udGggb3IgeWVhciByb3VuZGluZyxcbiAqIHNvIHRoYXQgTWF0aC5taW4gd2lsbCB3b3JrLCByYXRoZXIgdGhhbiAnTTEnIGFuZCAnTTEyJ1xuICovXG5mdW5jdGlvbiBiaWdnZXN0RGlnaXRDaGFuZ2VkKHYxLCB2MiwgcGEsIGNhbGVuZGFyKSB7XG4gICAgLy8gYXJlIHdlIGNyb3NzaW5nIHplcm8/IGNhbid0IHNheSBhbnl0aGluZy5cbiAgICAvLyBpbiBwcmluY2lwbGUgdGhpcyBkb2Vzbid0IGFwcGx5IHRvIGRhdGVzIGJ1dCB0dXJucyBvdXQgdGhpcyBkb2Vzbid0IG1hdHRlci5cbiAgICBpZih2MSAqIHYyIDw9IDApIHJldHVybiBJbmZpbml0eTtcblxuICAgIHZhciBkdiA9IE1hdGguYWJzKHYyIC0gdjEpO1xuICAgIHZhciBpc0RhdGUgPSBwYS50eXBlID09PSAnZGF0ZSc7XG4gICAgdmFyIGRpZ2l0ID0gYmlnZ2VzdEd1YXJhbnRlZWREaWdpdENoYW5nZWQoZHYsIGlzRGF0ZSk7XG4gICAgLy8gc2VlIGlmIGEgbGFyZ2VyIGRpZ2l0IGFsc28gY2hhbmdlZFxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAxMDsgaSsrKSB7XG4gICAgICAgIC8vIG51bWJlcnM6IG5leHQgZGlnaXQgbmVlZHMgdG8gYmUgPjEweCBidXQgPDEwMHggdGhlbiBnZXRzIHJvdW5kZWQgZG93bi5cbiAgICAgICAgLy8gZGF0ZXM6IG5leHQgZGlnaXQgY2FuIGJlIGFzIG11Y2ggYXMgNjB4ICh0aGVuIHJvdW5kZWQgZG93bilcbiAgICAgICAgdmFyIG5leHREaWdpdCA9IGJpZ2dlc3RHdWFyYW50ZWVkRGlnaXRDaGFuZ2VkKGRpZ2l0ICogODAsIGlzRGF0ZSk7XG4gICAgICAgIC8vIGlmIHdlIGdldCB0byB5ZWFycywgdGhlIGNoYWluIHN0b3BzXG4gICAgICAgIGlmKGRpZ2l0ID09PSBuZXh0RGlnaXQpIGJyZWFrO1xuICAgICAgICBpZihkaWREaWdpdENoYW5nZShuZXh0RGlnaXQsIHYxLCB2MiwgaXNEYXRlLCBwYSwgY2FsZW5kYXIpKSBkaWdpdCA9IG5leHREaWdpdDtcbiAgICAgICAgZWxzZSBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIGRpZ2l0O1xufVxuXG4vKlxuICogRmluZCB0aGUgbGFyZ2VzdCBkaWdpdCB0aGF0ICpkZWZpbml0ZWx5KiBjaGFuZ2VzIGluIGEgcmVnaW9uIFt2LCB2ICsgZHZdIGZvciBhbnkgdlxuICogZm9yIG5vbnVuaWZvcm0gZGF0ZSByZWdpb25zIChtb250aHMveWVhcnMpIHBpY2sgdGhlIGxhcmdlc3RcbiAqL1xuZnVuY3Rpb24gYmlnZ2VzdEd1YXJhbnRlZWREaWdpdENoYW5nZWQoZHYsIGlzRGF0ZSkge1xuICAgIGlmKGlzRGF0ZSAmJiBkdiA+IG9uZVNlYykge1xuICAgICAgICAvLyB0aGlzIGlzIHN1cHBvc2VkIHRvIGJlIHRoZSBiaWdnZXN0ICpndWFyYW50ZWVkKiBjaGFuZ2VcbiAgICAgICAgLy8gc28gY29tcGFyZSB0byB0aGUgbG9uZ2VzdCBtb250aCBhbmQgeWVhciBhY3Jvc3MgYW55IGNhbGVuZGFyLFxuICAgICAgICAvLyBhbmQgd2UnbGwgaXRlcmF0ZSBiYWNrIHVwIGxhdGVyXG4gICAgICAgIC8vIG5vdGU6IGRvZXMgbm90IHN1cHBvcnQgcm91bmRpbmcgbGFyZ2VyIHRoYW4gb25lIHllYXIuIFdlIGNvdWxkIGFkZFxuICAgICAgICAvLyB0aGF0IGlmIGFueW9uZSB3YW50cyBpdCwgYnV0IHNlZW1zIHVudXN1YWwgYW5kIG5vdCBzdHJpY3RseSBuZWNlc3NhcnkuXG4gICAgICAgIGlmKGR2ID4gb25lRGF5KSB7XG4gICAgICAgICAgICBpZihkdiA+IG9uZVllYXIgKiAxLjEpIHJldHVybiBvbmVZZWFyO1xuICAgICAgICAgICAgaWYoZHYgPiBvbmVNb250aCAqIDEuMSkgcmV0dXJuIG9uZU1vbnRoO1xuICAgICAgICAgICAgcmV0dXJuIG9uZURheTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGR2ID4gb25lSG91cikgcmV0dXJuIG9uZUhvdXI7XG4gICAgICAgIGlmKGR2ID4gb25lTWluKSByZXR1cm4gb25lTWluO1xuICAgICAgICByZXR1cm4gb25lU2VjO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIE1hdGguZmxvb3IoTWF0aC5sb2coZHYpIC8gTWF0aC5MTjEwKSk7XG59XG5cbmZ1bmN0aW9uIGRpZERpZ2l0Q2hhbmdlKGRpZ2l0LCB2MSwgdjIsIGlzRGF0ZSwgcGEsIGNhbGVuZGFyKSB7XG4gICAgaWYoaXNEYXRlICYmIGRpZ2l0ID4gb25lRGF5KSB7XG4gICAgICAgIHZhciBkYXRlUGFydHMxID0gZGF0ZVBhcnRzKHYxLCBwYSwgY2FsZW5kYXIpO1xuICAgICAgICB2YXIgZGF0ZVBhcnRzMiA9IGRhdGVQYXJ0cyh2MiwgcGEsIGNhbGVuZGFyKTtcbiAgICAgICAgdmFyIHBhcnRpID0gKGRpZ2l0ID09PSBvbmVZZWFyKSA/IDAgOiAxO1xuICAgICAgICByZXR1cm4gZGF0ZVBhcnRzMVtwYXJ0aV0gIT09IGRhdGVQYXJ0czJbcGFydGldO1xuXG4gICAgfVxuICAgIHJldHVybiBNYXRoLmZsb29yKHYyIC8gZGlnaXQpIC0gTWF0aC5mbG9vcih2MSAvIGRpZ2l0KSA+IDAuMTtcbn1cblxuZnVuY3Rpb24gZGF0ZVBhcnRzKHYsIHBhLCBjYWxlbmRhcikge1xuICAgIHZhciBwYXJ0cyA9IHBhLmMyZCh2LCBvbmVZZWFyLCBjYWxlbmRhcikuc3BsaXQoJy0nKTtcbiAgICBpZihwYXJ0c1swXSA9PT0gJycpIHtcbiAgICAgICAgcGFydHMudW5zaGlmdCgpO1xuICAgICAgICBwYXJ0c1swXSA9ICctJyArIHBhcnRzWzBdO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHM7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSByZXF1aXJlKCcuLi9iYXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgYmluRnVuY3Rpb25zID0gcmVxdWlyZSgnLi9iaW5fZnVuY3Rpb25zJyk7XG52YXIgbm9ybUZ1bmN0aW9ucyA9IHJlcXVpcmUoJy4vbm9ybV9mdW5jdGlvbnMnKTtcbnZhciBkb0F2ZyA9IHJlcXVpcmUoJy4vYXZlcmFnZScpO1xudmFyIGdldEJpblNwYW5MYWJlbFJvdW5kID0gcmVxdWlyZSgnLi9iaW5fbGFiZWxfdmFscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgLy8gaWdub3JlIGFzIG11Y2ggcHJvY2Vzc2luZyBhcyBwb3NzaWJsZSAoYW5kIGluY2x1ZGluZyBpbiBhdXRvcmFuZ2UpIGlmIG5vdCB2aXNpYmxlXG4gICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSkgcmV0dXJuO1xuXG4gICAgLy8gZGVwZW5kaW5nIG9uIG9yaWVudGF0aW9uLCBzZXQgcG9zaXRpb24gYW5kIHNpemUgYXhlcyBhbmQgZGF0YSByYW5nZXNcbiAgICAvLyBub3RlOiB0aGlzIGxvZ2ljIGZvciBjaG9vc2luZyBvcmllbnRhdGlvbiBpcyBkdXBsaWNhdGVkIGluIGdyYXBoX29iai0+c2V0c3R5bGVzXG4gICAgdmFyIHBvcyA9IFtdO1xuICAgIHZhciBzaXplID0gW107XG4gICAgdmFyIHBhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcgP1xuICAgICAgICAodHJhY2UueWF4aXMgfHwgJ3knKSA6ICh0cmFjZS54YXhpcyB8fCAneCcpKTtcbiAgICB2YXIgbWFpbkRhdGEgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8gJ3knIDogJ3gnO1xuICAgIHZhciBjb3VudGVyRGF0YSA9IHt4OiAneScsIHk6ICd4J31bbWFpbkRhdGFdO1xuICAgIHZhciBjYWxlbmRhciA9IHRyYWNlW21haW5EYXRhICsgJ2NhbGVuZGFyJ107XG4gICAgdmFyIGN1bXVsYXRpdmVTcGVjID0gdHJhY2UuY3VtdWxhdGl2ZTtcbiAgICB2YXIgaTtcblxuICAgIHZhciBiaW5zQW5kUG9zID0gY2FsY0FsbEF1dG9CaW5zKGdkLCB0cmFjZSwgcGEsIG1haW5EYXRhKTtcbiAgICB2YXIgYmluU3BlYyA9IGJpbnNBbmRQb3NbMF07XG4gICAgdmFyIHBvczAgPSBiaW5zQW5kUG9zWzFdO1xuXG4gICAgdmFyIG5vbnVuaWZvcm1CaW5zID0gdHlwZW9mIGJpblNwZWMuc2l6ZSA9PT0gJ3N0cmluZyc7XG4gICAgdmFyIGJpbkVkZ2VzID0gW107XG4gICAgdmFyIGJpbnMgPSBub251bmlmb3JtQmlucyA/IGJpbkVkZ2VzIDogYmluU3BlYztcbiAgICAvLyBtYWtlIHRoZSBlbXB0eSBiaW4gYXJyYXlcbiAgICB2YXIgaW5jID0gW107XG4gICAgdmFyIGNvdW50cyA9IFtdO1xuICAgIHZhciBpbnB1dFBvaW50cyA9IFtdO1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgdmFyIG5vcm0gPSB0cmFjZS5oaXN0bm9ybTtcbiAgICB2YXIgZnVuYyA9IHRyYWNlLmhpc3RmdW5jO1xuICAgIHZhciBkZW5zaXR5Tm9ybSA9IG5vcm0uaW5kZXhPZignZGVuc2l0eScpICE9PSAtMTtcbiAgICB2YXIgaTIsIGJpbkVuZCwgbjtcblxuICAgIGlmKGN1bXVsYXRpdmVTcGVjLmVuYWJsZWQgJiYgZGVuc2l0eU5vcm0pIHtcbiAgICAgICAgLy8gd2UgdHJlYXQgXCJjdW11bGF0aXZlXCIgbGlrZSBpdCBtZWFucyBcImludGVncmFsXCIgaWYgeW91IHVzZSBhIGRlbnNpdHkgbm9ybSxcbiAgICAgICAgLy8gd2hpY2ggaW4gdGhlIGVuZCBtZWFucyBpdCdzIHRoZSBzYW1lIGFzIHdpdGhvdXQgXCJkZW5zaXR5XCJcbiAgICAgICAgbm9ybSA9IG5vcm0ucmVwbGFjZSgvID9kZW5zaXR5JC8sICcnKTtcbiAgICAgICAgZGVuc2l0eU5vcm0gPSBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZXh0cmVtZUZ1bmMgPSBmdW5jID09PSAnbWF4JyB8fCBmdW5jID09PSAnbWluJztcbiAgICB2YXIgc2l6ZUluaXQgPSBleHRyZW1lRnVuYyA/IG51bGwgOiAwO1xuICAgIHZhciBiaW5GdW5jID0gYmluRnVuY3Rpb25zLmNvdW50O1xuICAgIHZhciBub3JtRnVuYyA9IG5vcm1GdW5jdGlvbnNbbm9ybV07XG4gICAgdmFyIGlzQXZnID0gZmFsc2U7XG4gICAgdmFyIHByMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiBwYS5yMmModiwgMCwgY2FsZW5kYXIpOyB9O1xuICAgIHZhciByYXdDb3VudGVyRGF0YTtcblxuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlW2NvdW50ZXJEYXRhXSkgJiYgZnVuYyAhPT0gJ2NvdW50Jykge1xuICAgICAgICByYXdDb3VudGVyRGF0YSA9IHRyYWNlW2NvdW50ZXJEYXRhXTtcbiAgICAgICAgaXNBdmcgPSBmdW5jID09PSAnYXZnJztcbiAgICAgICAgYmluRnVuYyA9IGJpbkZ1bmN0aW9uc1tmdW5jXTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIGJpbnMgKGFuZCBhbnkgZXh0cmEgYXJyYXlzIG5lZWRlZClcbiAgICAvLyBhc3N1bWUgbW9yZSB0aGFuIDFlNiBiaW5zIGlzIGFuIGVycm9yLCBzbyB3ZSBkb24ndCBjcmFzaCB0aGUgYnJvd3NlclxuICAgIGkgPSBwcjJjKGJpblNwZWMuc3RhcnQpO1xuXG4gICAgLy8gZGVjcmVhc2UgZW5kIGEgbGl0dGxlIGluIGNhc2Ugb2Ygcm91bmRpbmcgZXJyb3JzXG4gICAgYmluRW5kID0gcHIyYyhiaW5TcGVjLmVuZCkgKyAoaSAtIEF4ZXMudGlja0luY3JlbWVudChpLCBiaW5TcGVjLnNpemUsIGZhbHNlLCBjYWxlbmRhcikpIC8gMWU2O1xuXG4gICAgd2hpbGUoaSA8IGJpbkVuZCAmJiBwb3MubGVuZ3RoIDwgMWU2KSB7XG4gICAgICAgIGkyID0gQXhlcy50aWNrSW5jcmVtZW50KGksIGJpblNwZWMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyKTtcbiAgICAgICAgcG9zLnB1c2goKGkgKyBpMikgLyAyKTtcbiAgICAgICAgc2l6ZS5wdXNoKHNpemVJbml0KTtcbiAgICAgICAgaW5wdXRQb2ludHMucHVzaChbXSk7XG4gICAgICAgIC8vIG5vbnVuaWZvcm0gYmlucyAobGlrZSBtb250aHMpIHdlIG5lZWQgdG8gc2VhcmNoLFxuICAgICAgICAvLyByYXRoZXIgdGhhbiBzdHJhaWdodCBjYWxjdWxhdGUgdGhlIGJpbiB3ZSdyZSBpblxuICAgICAgICBiaW5FZGdlcy5wdXNoKGkpO1xuICAgICAgICAvLyBub251bmlmb3JtIGJpbnMgYWxzbyBuZWVkIG5vbnVuaWZvcm0gbm9ybWFsaXphdGlvbiBmYWN0b3JzXG4gICAgICAgIGlmKGRlbnNpdHlOb3JtKSBpbmMucHVzaCgxIC8gKGkyIC0gaSkpO1xuICAgICAgICBpZihpc0F2ZykgY291bnRzLnB1c2goMCk7XG4gICAgICAgIC8vIGJyZWFrIHRvIGF2b2lkIGluZmluaXRlIGxvb3BzXG4gICAgICAgIGlmKGkyIDw9IGkpIGJyZWFrO1xuICAgICAgICBpID0gaTI7XG4gICAgfVxuICAgIGJpbkVkZ2VzLnB1c2goaSk7XG5cbiAgICAvLyBmb3IgZGF0ZSBheGVzIHdlIG5lZWQgYmluIGJvdW5kcyB0byBiZSBjYWxjZGF0YS4gRm9yIG5vbnVuaWZvcm0gYmluc1xuICAgIC8vIHdlIGFscmVhZHkgaGF2ZSB0aGlzLCBidXQgdW5pZm9ybSB3aXRoIHN0YXJ0L2VuZC9zaXplIHRoZXkncmUgc3RpbGwgc3RyaW5ncy5cbiAgICBpZighbm9udW5pZm9ybUJpbnMgJiYgcGEudHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIGJpbnMgPSB7XG4gICAgICAgICAgICBzdGFydDogcHIyYyhiaW5zLnN0YXJ0KSxcbiAgICAgICAgICAgIGVuZDogcHIyYyhiaW5zLmVuZCksXG4gICAgICAgICAgICBzaXplOiBiaW5zLnNpemVcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBiaW4gdGhlIGRhdGFcbiAgICAvLyBhbmQgbWFrZSBoaXN0b2dyYW0tc3BlY2lmaWMgcHQtbnVtYmVyLXRvLWNkLWluZGV4IG1hcCBvYmplY3RcbiAgICB2YXIgbk1heCA9IHNpemUubGVuZ3RoO1xuICAgIHZhciB1bmlxdWVWYWxzUGVyQmluID0gdHJ1ZTtcbiAgICB2YXIgbGVmdEdhcCA9IEluZmluaXR5O1xuICAgIHZhciByaWdodEdhcCA9IEluZmluaXR5O1xuICAgIHZhciBwdE51bWJlcjJjZEluZGV4ID0ge307XG4gICAgZm9yKGkgPSAwOyBpIDwgcG9zMC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcG9zaSA9IHBvczBbaV07XG4gICAgICAgIG4gPSBMaWIuZmluZEJpbihwb3NpLCBiaW5zKTtcbiAgICAgICAgaWYobiA+PSAwICYmIG4gPCBuTWF4KSB7XG4gICAgICAgICAgICB0b3RhbCArPSBiaW5GdW5jKG4sIGksIHNpemUsIHJhd0NvdW50ZXJEYXRhLCBjb3VudHMpO1xuICAgICAgICAgICAgaWYodW5pcXVlVmFsc1BlckJpbiAmJiBpbnB1dFBvaW50c1tuXS5sZW5ndGggJiYgcG9zaSAhPT0gcG9zMFtpbnB1dFBvaW50c1tuXVswXV0pIHtcbiAgICAgICAgICAgICAgICB1bmlxdWVWYWxzUGVyQmluID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbnB1dFBvaW50c1tuXS5wdXNoKGkpO1xuICAgICAgICAgICAgcHROdW1iZXIyY2RJbmRleFtpXSA9IG47XG5cbiAgICAgICAgICAgIGxlZnRHYXAgPSBNYXRoLm1pbihsZWZ0R2FwLCBwb3NpIC0gYmluRWRnZXNbbl0pO1xuICAgICAgICAgICAgcmlnaHRHYXAgPSBNYXRoLm1pbihyaWdodEdhcCwgYmluRWRnZXNbbiArIDFdIC0gcG9zaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcm91bmRGbjtcbiAgICBpZighdW5pcXVlVmFsc1BlckJpbikge1xuICAgICAgICByb3VuZEZuID0gZ2V0QmluU3BhbkxhYmVsUm91bmQobGVmdEdhcCwgcmlnaHRHYXAsIGJpbkVkZ2VzLCBwYSwgY2FsZW5kYXIpO1xuICAgIH1cblxuICAgIC8vIGF2ZXJhZ2UgYW5kL29yIG5vcm1hbGl6ZSB0aGUgZGF0YSwgaWYgbmVlZGVkXG4gICAgaWYoaXNBdmcpIHRvdGFsID0gZG9Bdmcoc2l6ZSwgY291bnRzKTtcbiAgICBpZihub3JtRnVuYykgbm9ybUZ1bmMoc2l6ZSwgdG90YWwsIGluYyk7XG5cbiAgICAvLyBhZnRlciBhbGwgbm9ybWFsaXphdGlvbiBldGMsIG5vdyB3ZSBjYW4gYWNjdW11bGF0ZSBpZiBkZXNpcmVkXG4gICAgaWYoY3VtdWxhdGl2ZVNwZWMuZW5hYmxlZCkgY2RmKHNpemUsIGN1bXVsYXRpdmVTcGVjLmRpcmVjdGlvbiwgY3VtdWxhdGl2ZVNwZWMuY3VycmVudGJpbik7XG5cblxuICAgIHZhciBzZXJpZXNMZW4gPSBNYXRoLm1pbihwb3MubGVuZ3RoLCBzaXplLmxlbmd0aCk7XG4gICAgdmFyIGNkID0gW107XG4gICAgdmFyIGZpcnN0Tm9uemVybyA9IDA7XG4gICAgdmFyIGxhc3ROb256ZXJvID0gc2VyaWVzTGVuIC0gMTtcblxuICAgIC8vIGxvb2sgZm9yIGVtcHR5IGJpbnMgYXQgdGhlIGVuZHMgdG8gcmVtb3ZlLCBzbyBhdXRvc2NhbGUgb21pdHMgdGhlbVxuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc0xlbjsgaSsrKSB7XG4gICAgICAgIGlmKHNpemVbaV0pIHtcbiAgICAgICAgICAgIGZpcnN0Tm9uemVybyA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IoaSA9IHNlcmllc0xlbiAtIDE7IGkgPj0gZmlyc3ROb256ZXJvOyBpLS0pIHtcbiAgICAgICAgaWYoc2l6ZVtpXSkge1xuICAgICAgICAgICAgbGFzdE5vbnplcm8gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIFwiY2FsY3VsYXRlZCBkYXRhXCIgdG8gcGxvdFxuICAgIGZvcihpID0gZmlyc3ROb256ZXJvOyBpIDw9IGxhc3ROb256ZXJvOyBpKyspIHtcbiAgICAgICAgaWYoKGlzTnVtZXJpYyhwb3NbaV0pICYmIGlzTnVtZXJpYyhzaXplW2ldKSkpIHtcbiAgICAgICAgICAgIHZhciBjZGkgPSB7XG4gICAgICAgICAgICAgICAgcDogcG9zW2ldLFxuICAgICAgICAgICAgICAgIHM6IHNpemVbaV0sXG4gICAgICAgICAgICAgICAgYjogMFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gc2V0dXAgaG92ZXIgYW5kIGV2ZW50IGRhdGEgZmllbGRzLFxuICAgICAgICAgICAgLy8gTi5CLiBwdHMgYW5kIFwiaG92ZXJcIiBwb3NpdGlvbnMgcGgwL3BoMSBkb24ndCBzZWVtIHRvIG1ha2UgbXVjaCBzZW5zZVxuICAgICAgICAgICAgLy8gZm9yIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uc1xuICAgICAgICAgICAgaWYoIWN1bXVsYXRpdmVTcGVjLmVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBjZGkucHRzID0gaW5wdXRQb2ludHNbaV07XG4gICAgICAgICAgICAgICAgaWYodW5pcXVlVmFsc1BlckJpbikge1xuICAgICAgICAgICAgICAgICAgICBjZGkucGgwID0gY2RpLnBoMSA9IChpbnB1dFBvaW50c1tpXS5sZW5ndGgpID8gcG9zMFtpbnB1dFBvaW50c1tpXVswXV0gOiBwb3NbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjZGkucGgwID0gcm91bmRGbihiaW5FZGdlc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIGNkaS5waDEgPSByb3VuZEZuKGJpbkVkZ2VzW2kgKyAxXSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2QucHVzaChjZGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoY2QubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8vIHdoZW4gd2UgY29sbGFwc2UgdG8gYSBzaW5nbGUgYmluLCBjYWxjZGF0YSBubyBsb25nZXIgZGVzY3JpYmVzIGJpbiBzaXplXG4gICAgICAgIC8vIHNvIHdlIG5lZWQgdG8gZXhwbGljaXRseSBzcGVjaWZ5IGl0XG4gICAgICAgIGNkWzBdLndpZHRoMSA9IEF4ZXMudGlja0luY3JlbWVudChjZFswXS5wLCBiaW5TcGVjLnNpemUsIGZhbHNlLCBjYWxlbmRhcikgLSBjZFswXS5wO1xuICAgIH1cblxuICAgIGFycmF5c1RvQ2FsY2RhdGEoY2QsIHRyYWNlKTtcblxuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlLnNlbGVjdGVkcG9pbnRzKSkge1xuICAgICAgICBMaWIudGFnU2VsZWN0ZWQoY2QsIHRyYWNlLCBwdE51bWJlcjJjZEluZGV4KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG4vKlxuICogY2FsY0FsbEF1dG9CaW5zOiB3ZSB3YW50IGFsbCBoaXN0b2dyYW1zIG9uIHRoZSBzYW1lIGF4ZXMgdG8gc2hhcmUgYmluIHNwZWNzXG4gKiBpZiB0aGV5J3JlIGdyb3VwZWQgb3Igc3RhY2tlZC4gSWYgdGhlIHVzZXIgaGFzIGV4cGxpY2l0bHkgc3BlY2lmaWVkIGRpZmZlcmluZ1xuICogYmluIHNwZWNzLCB0aGVyZSdzIG5vdGhpbmcgd2UgY2FuIGRvLCBidXQgaWYgcG9zc2libGUgd2Ugd2lsbCB0cnkgdG8gdXNlIHRoZVxuICogc21hbGxlc3QgYmlucyBvZiBhbnkgb2YgdGhlIGF1dG8gdmFsdWVzIGZvciBhbGwgaGlzdG9ncmFtcyBncm91cGVkL3N0YWNrZWRcbiAqIHRvZ2V0aGVyLlxuICovXG5mdW5jdGlvbiBjYWxjQWxsQXV0b0JpbnMoZ2QsIHRyYWNlLCBwYSwgbWFpbkRhdGEsIF9vdmVybGF5RWRnZUNhc2UpIHtcbiAgICB2YXIgYmluQXR0ciA9IG1haW5EYXRhICsgJ2JpbnMnO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGlzT3ZlcmxheSA9IGZ1bGxMYXlvdXQuYmFybW9kZSA9PT0gJ292ZXJsYXknO1xuICAgIHZhciBpLCB0cmFjZXMsIHRyYWNlaSwgY2FsZW5kYXIsIHBvczAsIGF1dG9WYWxzLCBjdW11bGF0aXZlU3BlYztcblxuICAgIHZhciBjbGVhbkJvdW5kID0gKHBhLnR5cGUgPT09ICdkYXRlJykgP1xuICAgICAgICBmdW5jdGlvbih2KSB7IHJldHVybiAodiB8fCB2ID09PSAwKSA/IExpYi5jbGVhbkRhdGUodiwgbnVsbCwgcGEuY2FsZW5kYXIpIDogbnVsbDsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGlzTnVtZXJpYyh2KSA/IE51bWJlcih2KSA6IG51bGw7IH07XG5cbiAgICBmdW5jdGlvbiBzZXRCb3VuZChhdHRyLCBiaW5zLCBuZXdCaW5zKSB7XG4gICAgICAgIGlmKGJpbnNbYXR0ciArICdGb3VuZCddKSB7XG4gICAgICAgICAgICBiaW5zW2F0dHJdID0gY2xlYW5Cb3VuZChiaW5zW2F0dHJdKTtcbiAgICAgICAgICAgIGlmKGJpbnNbYXR0cl0gPT09IG51bGwpIGJpbnNbYXR0cl0gPSBuZXdCaW5zW2F0dHJdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXV0b1ZhbHNbYXR0cl0gPSBiaW5zW2F0dHJdID0gbmV3Qmluc1thdHRyXTtcbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZXNbMF0sIGJpbkF0dHIgKyAnLicgKyBhdHRyKS5zZXQobmV3Qmluc1thdHRyXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgYmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHNbdHJhY2UuX2dyb3VwTmFtZV07XG5cbiAgICAvLyBhbGwgYnV0IHRoZSBmaXJzdCB0cmFjZSBpbiB0aGlzIGdyb3VwIGhhcyBhbHJlYWR5IGJlZW4gbWFya2VkIGZpbmlzaGVkXG4gICAgLy8gY2xlYXIgdGhpcyBmbGFnLCBzbyBuZXh0IHRpbWUgd2UgcnVuIGNhbGMgd2Ugd2lsbCBydW4gYXV0b2JpbiBhZ2FpblxuICAgIGlmKHRyYWNlLl9hdXRvQmluRmluaXNoZWQpIHtcbiAgICAgICAgZGVsZXRlIHRyYWNlLl9hdXRvQmluRmluaXNoZWQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0cmFjZXMgPSBiaW5PcHRzLnRyYWNlcztcbiAgICAgICAgdmFyIHNpemVGb3VuZCA9IGJpbk9wdHMuc2l6ZUZvdW5kO1xuICAgICAgICB2YXIgYWxsUG9zID0gW107XG4gICAgICAgIGF1dG9WYWxzID0gdHJhY2VzWzBdLl9hdXRvQmluID0ge307XG4gICAgICAgIC8vIE5vdGU6IHdlJ3JlIGluY2x1ZGluZyBgbGVnZW5kb25seWAgdHJhY2VzIGhlcmUgZm9yIGF1dG9iaW4gcHVycG9zZXMsXG4gICAgICAgIC8vIHNvIHRoYXQgc2hvd2luZyAmIGhpZGluZyBmcm9tIHRoZSBsZWdlbmQgd29uJ3QgYWZmZWN0IGJpbnMuXG4gICAgICAgIC8vIEJ1dCB0aGlzIGNvbXBsaWNhdGVzIHRoaW5ncyBhIGJpdCBzaW5jZSB0aG9zZSB0cmFjZXMgZG9uJ3QgYGNhbGNgLFxuICAgICAgICAvLyBoZW5jZSBgaXNGaXJzdFZpc2libGVgLlxuICAgICAgICB2YXIgaXNGaXJzdFZpc2libGUgPSB0cnVlO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYWNlaSA9IHRyYWNlc1tpXTtcbiAgICAgICAgICAgIHBvczAgPSB0cmFjZWkuX3BvczAgPSBwYS5tYWtlQ2FsY2RhdGEodHJhY2VpLCBtYWluRGF0YSk7XG4gICAgICAgICAgICBhbGxQb3MgPSBMaWIuY29uY2F0KGFsbFBvcywgcG9zMCk7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2VpLl9hdXRvQmluRmluaXNoZWQ7XG4gICAgICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNGaXJzdFZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNGaXJzdFZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0cmFjZWkuX2F1dG9CaW47XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlaS5fYXV0b0JpbkZpbmlzaGVkID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2FsZW5kYXIgPSB0cmFjZXNbMF1bbWFpbkRhdGEgKyAnY2FsZW5kYXInXTtcbiAgICAgICAgdmFyIG5ld0JpblNwZWMgPSBBeGVzLmF1dG9CaW4oXG4gICAgICAgICAgICBhbGxQb3MsIHBhLCBiaW5PcHRzLm5iaW5zLCBmYWxzZSwgY2FsZW5kYXIsIHNpemVGb3VuZCAmJiBiaW5PcHRzLnNpemUpO1xuXG4gICAgICAgIC8vIEVkZ2UgY2FzZTogc2luZ2xlLXZhbHVlZCBoaXN0b2dyYW0gb3ZlcmxheWluZyBvdGhlcnNcbiAgICAgICAgLy8gVXNlIHRoZW0gYWxsIHRvZ2V0aGVyIHRvIGNhbGN1bGF0ZSB0aGUgYmluIHNpemUgZm9yIHRoZSBzaW5nbGUtdmFsdWVkIG9uZVxuICAgICAgICBpZihpc092ZXJsYXkgJiYgbmV3QmluU3BlYy5fZGF0YVNwYW4gPT09IDAgJiYgcGEudHlwZSAhPT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICAgICAgLy8gU2V2ZXJhbCBzaW5nbGUtdmFsdWVkIGhpc3RvZ3JhbXMhIFN0b3AgaW5maW5pdGUgcmVjdXJzaW9uLFxuICAgICAgICAgICAgLy8ganVzdCByZXR1cm4gYW4gZXh0cmEgZmxhZyB0aGF0IHRlbGxzIGhhbmRsZVNpbmdsZVZhbHVlT3ZlcmxheXNcbiAgICAgICAgICAgIC8vIHRvIHNvcnQgb3V0IHRoaXMgdHJhY2UgdG9vXG4gICAgICAgICAgICBpZihfb3ZlcmxheUVkZ2VDYXNlKSByZXR1cm4gW25ld0JpblNwZWMsIHBvczAsIHRydWVdO1xuXG4gICAgICAgICAgICBuZXdCaW5TcGVjID0gaGFuZGxlU2luZ2xlVmFsdWVPdmVybGF5cyhnZCwgdHJhY2UsIHBhLCBtYWluRGF0YSwgYmluQXR0cik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGp1c3QgZm9yIENERiBlZGdlIGNhc2VzXG4gICAgICAgIGN1bXVsYXRpdmVTcGVjID0gdHJhY2VpLmN1bXVsYXRpdmU7XG4gICAgICAgIGlmKGN1bXVsYXRpdmVTcGVjLmVuYWJsZWQgJiYgKGN1bXVsYXRpdmVTcGVjLmN1cnJlbnRiaW4gIT09ICdpbmNsdWRlJykpIHtcbiAgICAgICAgICAgIGlmKGN1bXVsYXRpdmVTcGVjLmRpcmVjdGlvbiA9PT0gJ2RlY3JlYXNpbmcnKSB7XG4gICAgICAgICAgICAgICAgbmV3QmluU3BlYy5zdGFydCA9IHBhLmMycihBeGVzLnRpY2tJbmNyZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgIHBhLnIyYyhuZXdCaW5TcGVjLnN0YXJ0LCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICAgICAgICAgIG5ld0JpblNwZWMuc2l6ZSwgdHJ1ZSwgY2FsZW5kYXJcbiAgICAgICAgICAgICAgICApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld0JpblNwZWMuZW5kID0gcGEuYzJyKEF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgICAgICAgICAgcGEucjJjKG5ld0JpblNwZWMuZW5kLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICAgICAgICAgIG5ld0JpblNwZWMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyXG4gICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBiaW5PcHRzLnNpemUgPSBuZXdCaW5TcGVjLnNpemU7XG4gICAgICAgIGlmKCFzaXplRm91bmQpIHtcbiAgICAgICAgICAgIGF1dG9WYWxzLnNpemUgPSBuZXdCaW5TcGVjLnNpemU7XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkodHJhY2VzWzBdLCBiaW5BdHRyICsgJy5zaXplJykuc2V0KG5ld0JpblNwZWMuc2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRCb3VuZCgnc3RhcnQnLCBiaW5PcHRzLCBuZXdCaW5TcGVjKTtcbiAgICAgICAgc2V0Qm91bmQoJ2VuZCcsIGJpbk9wdHMsIG5ld0JpblNwZWMpO1xuICAgIH1cblxuICAgIHBvczAgPSB0cmFjZS5fcG9zMDtcbiAgICBkZWxldGUgdHJhY2UuX3BvczA7XG5cbiAgICAvLyBFYWNoIHRyYWNlIGNhbiBzcGVjaWZ5IGl0cyBvd24gc3RhcnQvZW5kLCBvciBpZiBvbWl0dGVkXG4gICAgLy8gd2UgZW5zdXJlIHRoZXkncmUgYmV5b25kIHRoZSBib3VuZHMgb2YgdGhpcyB0cmFjZSdzIGRhdGEsXG4gICAgLy8gYW5kIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHN0YXJ0IGlzIGFsaWduZWQgd2l0aCB0aGUgbWFpbiBzdGFydFxuICAgIHZhciB0cmFjZUlucHV0QmlucyA9IHRyYWNlLl9pbnB1dFtiaW5BdHRyXSB8fCB7fTtcbiAgICB2YXIgdHJhY2VCaW5PcHRzQ2FsYyA9IExpYi5leHRlbmRGbGF0KHt9LCBiaW5PcHRzKTtcbiAgICB2YXIgbWFpblN0YXJ0ID0gYmluT3B0cy5zdGFydDtcbiAgICB2YXIgc3RhcnRJbiA9IHBhLnIybCh0cmFjZUlucHV0Qmlucy5zdGFydCk7XG4gICAgdmFyIGhhc1N0YXJ0ID0gc3RhcnRJbiAhPT0gdW5kZWZpbmVkO1xuICAgIGlmKChiaW5PcHRzLnN0YXJ0Rm91bmQgfHwgaGFzU3RhcnQpICYmIHN0YXJ0SW4gIT09IHBhLnIybChtYWluU3RhcnQpKSB7XG4gICAgICAgIC8vIFdlIGhhdmUgYW4gZXhwbGljaXQgc3RhcnQgdG8gcmVjb25jaWxlIGFjcm9zcyB0cmFjZXNcbiAgICAgICAgLy8gaWYgdGhpcyB0cmFjZSBoYXMgYW4gZXhwbGljaXQgc3RhcnQsIHNoaWZ0IGl0IGRvd24gdG8gYSBiaW4gZWRnZVxuICAgICAgICAvLyBpZiBhbm90aGVyIHRyYWNlIGhhZCBhbiBleHBsaWNpdCBzdGFydCwgc2hpZnQgaXQgZG93biB0byBhXG4gICAgICAgIC8vIGJpbiBlZGdlIHBhc3Qgb3VyIGRhdGFcbiAgICAgICAgdmFyIHRyYWNlU3RhcnQgPSBoYXNTdGFydCA/XG4gICAgICAgICAgICBzdGFydEluIDpcbiAgICAgICAgICAgIExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCBwb3MwKTtcblxuICAgICAgICB2YXIgZHVtbXlBeCA9IHtcbiAgICAgICAgICAgIHR5cGU6IHBhLnR5cGUgPT09ICdjYXRlZ29yeScgPyAnbGluZWFyJyA6IHBhLnR5cGUsXG4gICAgICAgICAgICByMmw6IHBhLnIybCxcbiAgICAgICAgICAgIGR0aWNrOiBiaW5PcHRzLnNpemUsXG4gICAgICAgICAgICB0aWNrMDogbWFpblN0YXJ0LFxuICAgICAgICAgICAgY2FsZW5kYXI6IGNhbGVuZGFyLFxuICAgICAgICAgICAgcmFuZ2U6IChbdHJhY2VTdGFydCwgQXhlcy50aWNrSW5jcmVtZW50KHRyYWNlU3RhcnQsIGJpbk9wdHMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyKV0pLm1hcChwYS5sMnIpXG4gICAgICAgIH07XG4gICAgICAgIHZhciBuZXdTdGFydCA9IEF4ZXMudGlja0ZpcnN0KGR1bW15QXgpO1xuICAgICAgICBpZihuZXdTdGFydCA+IHBhLnIybCh0cmFjZVN0YXJ0KSkge1xuICAgICAgICAgICAgbmV3U3RhcnQgPSBBeGVzLnRpY2tJbmNyZW1lbnQobmV3U3RhcnQsIGJpbk9wdHMuc2l6ZSwgdHJ1ZSwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgICAgIHRyYWNlQmluT3B0c0NhbGMuc3RhcnQgPSBwYS5sMnIobmV3U3RhcnQpO1xuICAgICAgICBpZighaGFzU3RhcnQpIExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYmluQXR0ciArICcuc3RhcnQnKS5zZXQodHJhY2VCaW5PcHRzQ2FsYy5zdGFydCk7XG4gICAgfVxuXG4gICAgdmFyIG1haW5FbmQgPSBiaW5PcHRzLmVuZDtcbiAgICB2YXIgZW5kSW4gPSBwYS5yMmwodHJhY2VJbnB1dEJpbnMuZW5kKTtcbiAgICB2YXIgaGFzRW5kID0gZW5kSW4gIT09IHVuZGVmaW5lZDtcbiAgICBpZigoYmluT3B0cy5lbmRGb3VuZCB8fCBoYXNFbmQpICYmIGVuZEluICE9PSBwYS5yMmwobWFpbkVuZCkpIHtcbiAgICAgICAgLy8gUmVjb25jaWxpbmcgYW4gZXhwbGljaXQgZW5kIGlzIGVhc2llciwgYXMgaXQgZG9lc24ndCBuZWVkIHRvXG4gICAgICAgIC8vIG1hdGNoIGJpbiBlZGdlc1xuICAgICAgICB2YXIgdHJhY2VFbmQgPSBoYXNFbmQgP1xuICAgICAgICAgICAgZW5kSW4gOlxuICAgICAgICAgICAgTGliLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIHBvczApO1xuXG4gICAgICAgIHRyYWNlQmluT3B0c0NhbGMuZW5kID0gcGEubDJyKHRyYWNlRW5kKTtcbiAgICAgICAgaWYoIWhhc0VuZCkgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBiaW5BdHRyICsgJy5zdGFydCcpLnNldCh0cmFjZUJpbk9wdHNDYWxjLmVuZCk7XG4gICAgfVxuXG4gICAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eSBmb3Igb25lLXRpbWUgYXV0b2Jpbm5pbmcuXG4gICAgLy8gYXV0b2JpbjogdHJ1ZSBpcyBoYW5kbGVkIGluIGNsZWFuRGF0YSwgYnV0IGF1dG9iaW46IGZhbHNlXG4gICAgLy8gbmVlZHMgdG8gYmUgaGVyZSB3aGVyZSB3ZSBoYXZlIGRldGVybWluZWQgdGhlIHZhbHVlcy5cbiAgICB2YXIgYXV0b0JpbkF0dHIgPSAnYXV0b2JpbicgKyBtYWluRGF0YTtcbiAgICBpZih0cmFjZS5faW5wdXRbYXV0b0JpbkF0dHJdID09PSBmYWxzZSkge1xuICAgICAgICB0cmFjZS5faW5wdXRbYmluQXR0cl0gPSBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhY2VbYmluQXR0cl0gfHwge30pO1xuICAgICAgICBkZWxldGUgdHJhY2UuX2lucHV0W2F1dG9CaW5BdHRyXTtcbiAgICAgICAgZGVsZXRlIHRyYWNlW2F1dG9CaW5BdHRyXTtcbiAgICB9XG5cbiAgICByZXR1cm4gW3RyYWNlQmluT3B0c0NhbGMsIHBvczBdO1xufVxuXG4vKlxuICogQWRqdXN0IHNpbmdsZS12YWx1ZSBoaXN0b2dyYW1zIGluIG92ZXJsYXkgbW9kZSB0byBtYWtlIGFzIGdvb2QgYVxuICogZ3Vlc3MgYXMgd2UgY2FuIGF0IGF1dG9iaW4gdmFsdWVzIHRoZSB1c2VyIHdvdWxkIGxpa2UuXG4gKlxuICogUmV0dXJucyB0aGUgYmluU3BlYyBmb3IgdGhlIHRyYWNlIHRoYXQgc3BhcmtlZCBhbGwgdGhpc1xuICovXG5mdW5jdGlvbiBoYW5kbGVTaW5nbGVWYWx1ZU92ZXJsYXlzKGdkLCB0cmFjZSwgcGEsIG1haW5EYXRhLCBiaW5BdHRyKSB7XG4gICAgdmFyIG92ZXJsYWlkVHJhY2VHcm91cCA9IGdldENvbm5lY3RlZEhpc3RvZ3JhbXMoZ2QsIHRyYWNlKTtcbiAgICB2YXIgcGFzdFRoaXNUcmFjZSA9IGZhbHNlO1xuICAgIHZhciBtaW5TaXplID0gSW5maW5pdHk7XG4gICAgdmFyIHNpbmdsZVZhbHVlZFRyYWNlcyA9IFt0cmFjZV07XG4gICAgdmFyIGksIHRyYWNlaTtcblxuICAgIC8vIGZpcnN0IGNvbGxlY3QgYWxsIHRoZTpcbiAgICAvLyAtIG1pbiBiaW4gc2l6ZSBmcm9tIGFsbCBtdWx0aS12YWx1ZWQgdHJhY2VzXG4gICAgLy8gLSBzaW5nbGUtdmFsdWVkIHRyYWNlc1xuICAgIGZvcihpID0gMDsgaSA8IG92ZXJsYWlkVHJhY2VHcm91cC5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZWkgPSBvdmVybGFpZFRyYWNlR3JvdXBbaV07XG4gICAgICAgIGlmKHRyYWNlaSA9PT0gdHJhY2UpIHBhc3RUaGlzVHJhY2UgPSB0cnVlO1xuICAgICAgICBlbHNlIGlmKCFwYXN0VGhpc1RyYWNlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIHRyYWNlIGhhcyBhbHJlYWR5IGhhZCBpdHMgYXV0b2JpbnMgY2FsY3VsYXRlZFxuICAgICAgICAgICAgLy8gKHNvIG11c3Qgbm90IGhhdmUgYmVlbiBzaW5nbGUtdmFsdWVkKS5cbiAgICAgICAgICAgIG1pblNpemUgPSBNYXRoLm1pbihtaW5TaXplLCB0cmFjZWlbYmluQXR0cl0uc2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0aSA9IGNhbGNBbGxBdXRvQmlucyhnZCwgdHJhY2VpLCBwYSwgbWFpbkRhdGEsIHRydWUpO1xuICAgICAgICAgICAgdmFyIGJpblNwZWNpID0gcmVzdWx0aVswXTtcbiAgICAgICAgICAgIHZhciBpc1NpbmdsZVZhbHVlZCA9IHJlc3VsdGlbMl07XG5cbiAgICAgICAgICAgIC8vIHNvIHdlIGNhbiB1c2UgdGhpcyByZXN1bHQgd2hlbiB3ZSBnZXQgdG8gdHJhY2VpIGluIHRoZSBub3JtYWxcbiAgICAgICAgICAgIC8vIGNvdXJzZSBvZiBldmVudHMsIG1hcmsgaXQgYXMgZG9uZSBhbmQgcHV0IF9wb3MwIGJhY2tcbiAgICAgICAgICAgIHRyYWNlaS5fYXV0b0JpbkZpbmlzaGVkID0gMTtcbiAgICAgICAgICAgIHRyYWNlaS5fcG9zMCA9IHJlc3VsdGlbMV07XG5cbiAgICAgICAgICAgIGlmKGlzU2luZ2xlVmFsdWVkKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlVmFsdWVkVHJhY2VzLnB1c2godHJhY2VpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1pblNpemUgPSBNYXRoLm1pbihtaW5TaXplLCBiaW5TcGVjaS5zaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZpbmQgdGhlIHJlYWwgZGF0YSB2YWx1ZXMgZm9yIGVhY2ggc2luZ2xlLXZhbHVlZCB0cmFjZVxuICAgIC8vIGh1bnQgdGhyb3VnaCBwb3MwIGZvciB0aGUgZmlyc3QgdmFsaWQgdmFsdWVcbiAgICB2YXIgZGF0YVZhbHMgPSBuZXcgQXJyYXkoc2luZ2xlVmFsdWVkVHJhY2VzLmxlbmd0aCk7XG4gICAgZm9yKGkgPSAwOyBpIDwgc2luZ2xlVmFsdWVkVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwb3MwID0gc2luZ2xlVmFsdWVkVHJhY2VzW2ldLl9wb3MwO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgcG9zMC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYocG9zMFtqXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZGF0YVZhbHNbaV0gPSBwb3MwW2pdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gYXJlIEFMTCB0cmFjZXMgYXJlIHNpbmdsZS12YWx1ZWQ/IHVzZSB0aGUgbWluIGRpZmZlcmVuY2UgYmV0d2VlblxuICAgIC8vIGFsbCBvZiB0aGVpciB2YWx1ZXMgKHdoaWNoIGRlZmF1bHRzIHRvIDEgaWYgdGhlcmUncyBzdGlsbCBvbmx5IG9uZSlcbiAgICBpZighaXNGaW5pdGUobWluU2l6ZSkpIHtcbiAgICAgICAgbWluU2l6ZSA9IExpYi5kaXN0aW5jdFZhbHMoZGF0YVZhbHMpLm1pbkRpZmY7XG4gICAgfVxuXG4gICAgLy8gbm93IGFwcGx5IHRoZSBtaW4gc2l6ZSB3ZSBmb3VuZCB0byBhbGwgc2luZ2xlLXZhbHVlZCB0cmFjZXNcbiAgICBmb3IoaSA9IDA7IGkgPCBzaW5nbGVWYWx1ZWRUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2VpID0gc2luZ2xlVmFsdWVkVHJhY2VzW2ldO1xuICAgICAgICB2YXIgY2FsZW5kYXIgPSB0cmFjZWlbbWFpbkRhdGEgKyAnY2FsZW5kYXInXTtcblxuICAgICAgICB0cmFjZWkuX2lucHV0W2JpbkF0dHJdID0gdHJhY2VpW2JpbkF0dHJdID0ge1xuICAgICAgICAgICAgc3RhcnQ6IHBhLmMycihkYXRhVmFsc1tpXSAtIG1pblNpemUgLyAyLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICBlbmQ6IHBhLmMycihkYXRhVmFsc1tpXSArIG1pblNpemUgLyAyLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICBzaXplOiBtaW5TaXplXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYWNlW2JpbkF0dHJdO1xufVxuXG4vKlxuICogUmV0dXJuIGFuIGFycmF5IG9mIGhpc3RvZ3JhbXMgdGhhdCBzaGFyZSBheGVzIGFuZCBvcmllbnRhdGlvbi5cbiAqXG4gKiBPbmx5IGNvbnNpZGVycyBoaXN0b2dyYW1zLiBJbiBwcmluY2lwbGUgd2UgY291bGQgaW5jbHVkZSBiYXJzIGluIGFcbiAqIHNpbWlsYXIgd2F5IHRvIGhvdyB3ZSBkbyBtYW51YWxseSBiaW5uZWQgaGlzdG9ncmFtcywgdGhvdWdoIHRoaXNcbiAqIHdvdWxkIGhhdmUgdG9ucyBvZiBlZGdlIGNhc2VzIGFuZCB2YWx1ZSBqdWRnbWVudHMgdG8gbWFrZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q29ubmVjdGVkSGlzdG9ncmFtcyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgeGlkID0gdHJhY2UueGF4aXM7XG4gICAgdmFyIHlpZCA9IHRyYWNlLnlheGlzO1xuICAgIHZhciBvcmllbnRhdGlvbiA9IHRyYWNlLm9yaWVudGF0aW9uO1xuXG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlaSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBpZih0cmFjZWkudHlwZSA9PT0gJ2hpc3RvZ3JhbScgJiZcbiAgICAgICAgICAgIHRyYWNlaS52aXNpYmxlID09PSB0cnVlICYmXG4gICAgICAgICAgICB0cmFjZWkub3JpZW50YXRpb24gPT09IG9yaWVudGF0aW9uICYmXG4gICAgICAgICAgICB0cmFjZWkueGF4aXMgPT09IHhpZCAmJiB0cmFjZWkueWF4aXMgPT09IHlpZFxuICAgICAgICApIHtcbiAgICAgICAgICAgIG91dC5wdXNoKHRyYWNlaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5cbmZ1bmN0aW9uIGNkZihzaXplLCBkaXJlY3Rpb24sIGN1cnJlbnRCaW4pIHtcbiAgICB2YXIgaSwgdmksIHByZXZTdW07XG5cbiAgICBmdW5jdGlvbiBmaXJzdEhhbGZQb2ludChpKSB7XG4gICAgICAgIHByZXZTdW0gPSBzaXplW2ldO1xuICAgICAgICBzaXplW2ldIC89IDI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV4dEhhbGZQb2ludChpKSB7XG4gICAgICAgIHZpID0gc2l6ZVtpXTtcbiAgICAgICAgc2l6ZVtpXSA9IHByZXZTdW0gKyB2aSAvIDI7XG4gICAgICAgIHByZXZTdW0gKz0gdmk7XG4gICAgfVxuXG4gICAgaWYoY3VycmVudEJpbiA9PT0gJ2hhbGYnKSB7XG5cbiAgICAgICAgaWYoZGlyZWN0aW9uID09PSAnaW5jcmVhc2luZycpIHtcbiAgICAgICAgICAgIGZpcnN0SGFsZlBvaW50KDApO1xuICAgICAgICAgICAgZm9yKGkgPSAxOyBpIDwgc2l6ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG5leHRIYWxmUG9pbnQoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmaXJzdEhhbGZQb2ludChzaXplLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgZm9yKGkgPSBzaXplLmxlbmd0aCAtIDI7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgbmV4dEhhbGZQb2ludChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmKGRpcmVjdGlvbiA9PT0gJ2luY3JlYXNpbmcnKSB7XG4gICAgICAgIGZvcihpID0gMTsgaSA8IHNpemUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNpemVbaV0gKz0gc2l6ZVtpIC0gMV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyAnZXhjbHVkZScgaXMgaWRlbnRpY2FsIHRvICdpbmNsdWRlJyBqdXN0IHNoaWZ0ZWQgb25lIGJpbiBvdmVyXG4gICAgICAgIGlmKGN1cnJlbnRCaW4gPT09ICdleGNsdWRlJykge1xuICAgICAgICAgICAgc2l6ZS51bnNoaWZ0KDApO1xuICAgICAgICAgICAgc2l6ZS5wb3AoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSBzaXplLmxlbmd0aCAtIDI7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBzaXplW2ldICs9IHNpemVbaSArIDFdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY3VycmVudEJpbiA9PT0gJ2V4Y2x1ZGUnKSB7XG4gICAgICAgICAgICBzaXplLnB1c2goMCk7XG4gICAgICAgICAgICBzaXplLnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIG5lc3RlZFByb3BlcnR5ID0gTGliLm5lc3RlZFByb3BlcnR5O1xuXG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG52YXIgQklOQVRUUlMgPSB7XG4gICAgeDogW1xuICAgICAgICB7YVN0cjogJ3hiaW5zLnN0YXJ0JywgbmFtZTogJ3N0YXJ0J30sXG4gICAgICAgIHthU3RyOiAneGJpbnMuZW5kJywgbmFtZTogJ2VuZCd9LFxuICAgICAgICB7YVN0cjogJ3hiaW5zLnNpemUnLCBuYW1lOiAnc2l6ZSd9LFxuICAgICAgICB7YVN0cjogJ25iaW5zeCcsIG5hbWU6ICduYmlucyd9XG4gICAgXSxcbiAgICB5OiBbXG4gICAgICAgIHthU3RyOiAneWJpbnMuc3RhcnQnLCBuYW1lOiAnc3RhcnQnfSxcbiAgICAgICAge2FTdHI6ICd5Ymlucy5lbmQnLCBuYW1lOiAnZW5kJ30sXG4gICAgICAgIHthU3RyOiAneWJpbnMuc2l6ZScsIG5hbWU6ICdzaXplJ30sXG4gICAgICAgIHthU3RyOiAnbmJpbnN5JywgbmFtZTogJ25iaW5zJ31cbiAgICBdXG59O1xuXG4vLyBoYW5kbGUgYmluIGF0dHJzIGFuZCByZWxpbmsgYXV0by1kZXRlcm1pbmVkIHZhbHVlcyBzbyBmdWxsRGF0YSBpcyBjb21wbGV0ZVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcm9zc1RyYWNlRGVmYXVsdHMoZnVsbERhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgYWxsQmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHMgPSB7fTtcbiAgICB2YXIgaXNPdmVybGF5ID0gZnVsbExheW91dC5iYXJtb2RlID09PSAnb3ZlcmxheSc7XG4gICAgdmFyIGksIGosIHRyYWNlT3V0LCB0cmFjZUluLCBiaW5EaXJlY3Rpb24sIGdyb3VwLCBiaW5PcHRzO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VPdXQuX2lucHV0LCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2VPdXQgPSBmdWxsRGF0YVtpXTtcbiAgICAgICAgaWYodHJhY2VPdXQudHlwZSAhPT0gJ2hpc3RvZ3JhbScpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkbid0IGJlIHJlbGlua2VkIGFzIGl0J3Mgb25seSB1c2VkIHdpdGhpbiBjYWxjXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy83NDlcbiAgICAgICAgZGVsZXRlIHRyYWNlT3V0Ll9hdXRvQmluRmluaXNoZWQ7XG5cbiAgICAgICAgYmluRGlyZWN0aW9uID0gdHJhY2VPdXQub3JpZW50YXRpb24gPT09ICd2JyA/ICd4JyA6ICd5JztcbiAgICAgICAgLy8gaW4gb3ZlcmxheSBtb2RlIG1ha2UgYSBzZXBhcmF0ZSBncm91cCBmb3IgZWFjaCB0cmFjZVxuICAgICAgICAvLyBvdGhlcndpc2UgY29sbGVjdCBhbGwgdHJhY2VzIG9mIHRoZSBzYW1lIHN1YnBsb3QgJiBvcmllbnRhdGlvblxuICAgICAgICBncm91cCA9IGlzT3ZlcmxheSA/IHRyYWNlT3V0LnVpZCA6ICh0cmFjZU91dC54YXhpcyArIHRyYWNlT3V0LnlheGlzICsgYmluRGlyZWN0aW9uKTtcbiAgICAgICAgdHJhY2VPdXQuX2dyb3VwTmFtZSA9IGdyb3VwO1xuXG4gICAgICAgIGJpbk9wdHMgPSBhbGxCaW5PcHRzW2dyb3VwXTtcblxuICAgICAgICBpZihiaW5PcHRzKSB7XG4gICAgICAgICAgICBiaW5PcHRzLnRyYWNlcy5wdXNoKHRyYWNlT3V0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGJpbk9wdHMgPSBhbGxCaW5PcHRzW2dyb3VwXSA9IHtcbiAgICAgICAgICAgICAgICB0cmFjZXM6IFt0cmFjZU91dF0sXG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uOiBiaW5EaXJlY3Rpb25cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoZ3JvdXAgaW4gYWxsQmluT3B0cykge1xuICAgICAgICBiaW5PcHRzID0gYWxsQmluT3B0c1tncm91cF07XG4gICAgICAgIGJpbkRpcmVjdGlvbiA9IGJpbk9wdHMuZGlyZWN0aW9uO1xuICAgICAgICB2YXIgYXR0cnMgPSBCSU5BVFRSU1tiaW5EaXJlY3Rpb25dO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBhdHRycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGF0dHJTcGVjID0gYXR0cnNbal07XG4gICAgICAgICAgICB2YXIgYXR0ciA9IGF0dHJTcGVjLm5hbWU7XG5cbiAgICAgICAgICAgIC8vIG5iaW5zKHh8eSkgaXMgbW9vdCBpZiB3ZSBoYXZlIGEgc2l6ZS4gVGhpcyBkZXBlbmRzIG9uXG4gICAgICAgICAgICAvLyBuYmlucyBjb21pbmcgYWZ0ZXIgc2l6ZSBpbiBiaW5BdHRycy5cbiAgICAgICAgICAgIGlmKGF0dHIgPT09ICduYmlucycgJiYgYmluT3B0cy5zaXplRm91bmQpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgYVN0ciA9IGF0dHJTcGVjLmFTdHI7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBiaW5PcHRzLnRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRyYWNlT3V0ID0gYmluT3B0cy50cmFjZXNbaV07XG4gICAgICAgICAgICAgICAgdHJhY2VJbiA9IHRyYWNlT3V0Ll9pbnB1dDtcbiAgICAgICAgICAgICAgICBpZihuZXN0ZWRQcm9wZXJ0eSh0cmFjZUluLCBhU3RyKS5nZXQoKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpbk9wdHNbYXR0cl0gPSBjb2VyY2UoYVN0cik7XG4gICAgICAgICAgICAgICAgICAgIGJpbk9wdHNbYXR0ciArICdGb3VuZCddID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBhdXRvVmFscyA9IHRyYWNlT3V0Ll9hdXRvQmluO1xuICAgICAgICAgICAgICAgIGlmKGF1dG9WYWxzICYmIGF1dG9WYWxzW2F0dHJdKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoaXMgaXMgdGhlICpmaXJzdCogYXV0b3ZhbFxuICAgICAgICAgICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eSh0cmFjZU91dCwgYVN0cikuc2V0KGF1dG9WYWxzW2F0dHJdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBzdGFydCBhbmQgZW5kIHdlIG5lZWQgdG8gY29lcmNlIGFueXdheSwgYWZ0ZXIgaGF2aW5nIGNvbGxlY3RlZCB0aGVcbiAgICAgICAgICAgIC8vIGZpcnN0IG9mIGVhY2ggaW50byBiaW5PcHRzLCBpbiBjYXNlIGEgdHJhY2Ugd2FudHMgdG8gcmVzdHJpY3QgaXRzXG4gICAgICAgICAgICAvLyBkYXRhIHRvIGEgY2VydGFpbiByYW5nZVxuICAgICAgICAgICAgaWYoYXR0ciA9PT0gJ3N0YXJ0JyB8fCBhdHRyID09PSAnZW5kJykge1xuICAgICAgICAgICAgICAgIGZvcig7IGkgPCBiaW5PcHRzLnRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZU91dCA9IGJpbk9wdHMudHJhY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICBjb2VyY2UoYVN0ciwgKHRyYWNlT3V0Ll9hdXRvQmluIHx8IHt9KVthdHRyXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihhdHRyID09PSAnbmJpbnMnICYmICFiaW5PcHRzLnNpemVGb3VuZCAmJiAhYmluT3B0cy5uYmluc0ZvdW5kKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VPdXQgPSBiaW5PcHRzLnRyYWNlc1swXTtcbiAgICAgICAgICAgICAgICBiaW5PcHRzW2F0dHJdID0gY29lcmNlKGFTdHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2Jhci9zdHlsZV9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuXG4gICAgdmFyIGN1bXVsYXRpdmUgPSBjb2VyY2UoJ2N1bXVsYXRpdmUuZW5hYmxlZCcpO1xuICAgIGlmKGN1bXVsYXRpdmUpIHtcbiAgICAgICAgY29lcmNlKCdjdW11bGF0aXZlLmRpcmVjdGlvbicpO1xuICAgICAgICBjb2VyY2UoJ2N1bXVsYXRpdmUuY3VycmVudGJpbicpO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuXG4gICAgdmFyIG9yaWVudGF0aW9uID0gY29lcmNlKCdvcmllbnRhdGlvbicsICh5ICYmICF4KSA/ICdoJyA6ICd2Jyk7XG4gICAgdmFyIHNhbXBsZUxldHRlciA9IG9yaWVudGF0aW9uID09PSAndicgPyAneCcgOiAneSc7XG4gICAgdmFyIGFnZ0xldHRlciA9IG9yaWVudGF0aW9uID09PSAndicgPyAneScgOiAneCc7XG5cbiAgICB2YXIgbGVuID0gKHggJiYgeSkgPyBNYXRoLm1pbih4Lmxlbmd0aCAmJiB5Lmxlbmd0aCkgOiAodHJhY2VPdXRbc2FtcGxlTGV0dGVyXSB8fCBbXSkubGVuZ3RoO1xuXG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4JywgJ3knXSwgbGF5b3V0KTtcblxuICAgIHZhciBoYXNBZ2dyZWdhdGlvbkRhdGEgPSB0cmFjZU91dFthZ2dMZXR0ZXJdO1xuICAgIGlmKGhhc0FnZ3JlZ2F0aW9uRGF0YSkgY29lcmNlKCdoaXN0ZnVuYycpO1xuICAgIGNvZXJjZSgnaGlzdG5vcm0nKTtcblxuICAgIC8vIE5vdGU6IGJpbiBkZWZhdWx0cyBhcmUgbm93IGhhbmRsZWQgaW4gSGlzdG9ncmFtLmNyb3NzVHJhY2VEZWZhdWx0c1xuICAgIC8vIGF1dG9iaW4oeHx5KSBhcmUgb25seSBpbmNsdWRlZCBoZXJlIHRvIGFwcGVhc2UgUGxvdGx5LnZhbGlkYXRlXG4gICAgY29lcmNlKCdhdXRvYmluJyArIHNhbXBsZUxldHRlcik7XG5cbiAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KTtcblxuICAgIC8vIG92ZXJyaWRlIGRlZmF1bHRDb2xvciBmb3IgZXJyb3IgYmFycyB3aXRoIGRlZmF1bHRMaW5lXG4gICAgdmFyIGVycm9yQmFyc1N1cHBseURlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3VwcGx5RGVmYXVsdHMnKTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneSd9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneCcsIGluaGVyaXQ6ICd5J30pO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0LCB0cmFjZSwgY2QsIHBvaW50TnVtYmVyKSB7XG4gICAgLy8gc3RhbmRhcmQgY2FydGVzaWFuIGV2ZW50IGRhdGFcbiAgICBvdXQueCA9ICd4VmFsJyBpbiBwdCA/IHB0LnhWYWwgOiBwdC54O1xuICAgIG91dC55ID0gJ3lWYWwnIGluIHB0ID8gcHQueVZhbCA6IHB0Lnk7XG5cbiAgICBpZihwdC54YSkgb3V0LnhheGlzID0gcHQueGE7XG4gICAgaWYocHQueWEpIG91dC55YXhpcyA9IHB0LnlhO1xuXG4gICAgLy8gc3BlY2lmaWMgdG8gaGlzdG9ncmFtIC0gQ0RGcyBkbyBub3QgaGF2ZSBwdHMgKHlldD8pXG4gICAgaWYoISh0cmFjZS5jdW11bGF0aXZlIHx8IHt9KS5lbmFibGVkKSB7XG4gICAgICAgIHZhciBwdHMgPSBBcnJheS5pc0FycmF5KHBvaW50TnVtYmVyKSA/XG4gICAgICAgICAgICBjZFswXS5wdHNbcG9pbnROdW1iZXJbMF1dW3BvaW50TnVtYmVyWzFdXSA6XG4gICAgICAgICAgICBjZFtwb2ludE51bWJlcl0ucHRzO1xuXG4gICAgICAgIG91dC5wb2ludE51bWJlcnMgPSBwdHM7XG4gICAgICAgIG91dC5iaW5OdW1iZXIgPSBvdXQucG9pbnROdW1iZXI7XG4gICAgICAgIGRlbGV0ZSBvdXQucG9pbnROdW1iZXI7XG4gICAgICAgIGRlbGV0ZSBvdXQucG9pbnRJbmRleDtcblxuICAgICAgICB2YXIgcG9pbnRJbmRpY2VzO1xuICAgICAgICBpZih0cmFjZS5faW5kZXhUb1BvaW50cykge1xuICAgICAgICAgICAgcG9pbnRJbmRpY2VzID0gW107XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRJbmRpY2VzID0gcG9pbnRJbmRpY2VzLmNvbmNhdCh0cmFjZS5faW5kZXhUb1BvaW50c1twdHNbaV1dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBvaW50SW5kaWNlcyA9IHB0cztcbiAgICAgICAgfVxuXG4gICAgICAgIG91dC5wb2ludEluZGljZXMgPSBwb2ludEluZGljZXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGJhckhvdmVyID0gcmVxdWlyZSgnLi4vYmFyL2hvdmVyJykuaG92ZXJQb2ludHM7XG52YXIgaG92ZXJMYWJlbFRleHQgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLmhvdmVyTGFiZWxUZXh0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIHB0cyA9IGJhckhvdmVyKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcblxuICAgIGlmKCFwdHMpIHJldHVybjtcblxuICAgIHBvaW50RGF0YSA9IHB0c1swXTtcbiAgICB2YXIgZGkgPSBwb2ludERhdGEuY2RbcG9pbnREYXRhLmluZGV4XTtcbiAgICB2YXIgdHJhY2UgPSBwb2ludERhdGEuY2RbMF0udHJhY2U7XG5cbiAgICBpZighdHJhY2UuY3VtdWxhdGl2ZS5lbmFibGVkKSB7XG4gICAgICAgIHZhciBwb3NMZXR0ZXIgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8gJ3knIDogJ3gnO1xuXG4gICAgICAgIHBvaW50RGF0YVtwb3NMZXR0ZXIgKyAnTGFiZWwnXSA9IGhvdmVyTGFiZWxUZXh0KHBvaW50RGF0YVtwb3NMZXR0ZXIgKyAnYSddLCBkaS5waDAsIGRpLnBoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHB0cztcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBIaXN0b2dyYW0gaGFzIGl0cyBvd24gYXR0cmlidXRlLCBkZWZhdWx0cyBhbmQgY2FsYyBzdGVwcyxcbiAqIGJ1dCB1c2VzIGJhcidzIHBsb3QgdG8gZGlzcGxheVxuICogYW5kIGJhcidzIGNyb3NzVHJhY2VDYWxjIChmb3JtZXJseSBrbm93biBhcyBzZXRQb3NpdGlvbnMpIGZvciBzdGFja2luZyBhbmQgZ3JvdXBpbmdcbiAqL1xuXG4vKipcbiAqIGhpc3RvZ3JhbSBlcnJvckJhcnNPSyBpcyBkZWJhdGFibGUsIGJ1dCBpdCdzIHB1dCBpbiBmb3IgYmFja3dhcmQgY29tcGF0LlxuICogdGhlcmUgYXJlIHVzZSBjYXNlcyBmb3IgaXQgLSBzcXJ0IGZvciBhIHNpbXBsZSBoaXN0b2dyYW0gd29ya3MgcmlnaHQgbm93LFxuICogY29uc3RhbnQgYW5kICUgd29yayBidXQgdGhleSdyZSBub3Qgc28gbWVhbmluZ2Z1bC4gSSBndWVzcyBpdCBjb3VsZCBiZSBjb29sXG4gKiB0byBhbGxvdyBxdWFkcmF0dXJlIGNvbWJpbmF0aW9uIG9mIGVycm9ycyBpbiBzdW1tZWQgaGlzdG9ncmFtcy4uLlxuICovXG5cblxudmFyIEhpc3RvZ3JhbSA9IHt9O1xuXG5IaXN0b2dyYW0uYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuSGlzdG9ncmFtLmxheW91dEF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi9iYXIvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbkhpc3RvZ3JhbS5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbkhpc3RvZ3JhbS5jcm9zc1RyYWNlRGVmYXVsdHMgPSByZXF1aXJlKCcuL2Nyb3NzX3RyYWNlX2RlZmF1bHRzJyk7XG5IaXN0b2dyYW0uc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSByZXF1aXJlKCcuLi9iYXIvbGF5b3V0X2RlZmF1bHRzJyk7XG5IaXN0b2dyYW0uY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuSGlzdG9ncmFtLmNyb3NzVHJhY2VDYWxjID0gcmVxdWlyZSgnLi4vYmFyL2Nyb3NzX3RyYWNlX2NhbGMnKS5jcm9zc1RyYWNlQ2FsYztcbkhpc3RvZ3JhbS5wbG90ID0gcmVxdWlyZSgnLi4vYmFyL3Bsb3QnKTtcbkhpc3RvZ3JhbS5sYXllck5hbWUgPSAnYmFybGF5ZXInO1xuSGlzdG9ncmFtLnN0eWxlID0gcmVxdWlyZSgnLi4vYmFyL3N0eWxlJykuc3R5bGU7XG5IaXN0b2dyYW0uc3R5bGVPblNlbGVjdCA9IHJlcXVpcmUoJy4uL2Jhci9zdHlsZScpLnN0eWxlT25TZWxlY3Q7XG5IaXN0b2dyYW0uY29sb3JiYXIgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpO1xuSGlzdG9ncmFtLmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuSGlzdG9ncmFtLnNlbGVjdFBvaW50cyA9IHJlcXVpcmUoJy4uL2Jhci9zZWxlY3QnKTtcbkhpc3RvZ3JhbS5ldmVudERhdGEgPSByZXF1aXJlKCcuL2V2ZW50X2RhdGEnKTtcblxuSGlzdG9ncmFtLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuSGlzdG9ncmFtLm5hbWUgPSAnaGlzdG9ncmFtJztcbkhpc3RvZ3JhbS5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpO1xuSGlzdG9ncmFtLmNhdGVnb3JpZXMgPSBbJ2NhcnRlc2lhbicsICdzdmcnLCAnYmFyJywgJ2hpc3RvZ3JhbScsICdvcmllbnRlZCcsICdlcnJvckJhcnNPSycsICdzaG93TGVnZW5kJ107XG5IaXN0b2dyYW0ubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSGlzdG9ncmFtO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcGVyY2VudDogZnVuY3Rpb24oc2l6ZSwgdG90YWwpIHtcbiAgICAgICAgdmFyIG5NYXggPSBzaXplLmxlbmd0aCxcbiAgICAgICAgICAgIG5vcm0gPSAxMDAgLyB0b3RhbDtcbiAgICAgICAgZm9yKHZhciBuID0gMDsgbiA8IG5NYXg7IG4rKykgc2l6ZVtuXSAqPSBub3JtO1xuICAgIH0sXG4gICAgcHJvYmFiaWxpdHk6IGZ1bmN0aW9uKHNpemUsIHRvdGFsKSB7XG4gICAgICAgIHZhciBuTWF4ID0gc2l6ZS5sZW5ndGg7XG4gICAgICAgIGZvcih2YXIgbiA9IDA7IG4gPCBuTWF4OyBuKyspIHNpemVbbl0gLz0gdG90YWw7XG4gICAgfSxcbiAgICBkZW5zaXR5OiBmdW5jdGlvbihzaXplLCB0b3RhbCwgaW5jLCB5aW5jKSB7XG4gICAgICAgIHZhciBuTWF4ID0gc2l6ZS5sZW5ndGg7XG4gICAgICAgIHlpbmMgPSB5aW5jIHx8IDE7XG4gICAgICAgIGZvcih2YXIgbiA9IDA7IG4gPCBuTWF4OyBuKyspIHNpemVbbl0gKj0gaW5jW25dICogeWluYztcbiAgICB9LFxuICAgICdwcm9iYWJpbGl0eSBkZW5zaXR5JzogZnVuY3Rpb24oc2l6ZSwgdG90YWwsIGluYywgeWluYykge1xuICAgICAgICB2YXIgbk1heCA9IHNpemUubGVuZ3RoO1xuICAgICAgICBpZih5aW5jKSB0b3RhbCAvPSB5aW5jO1xuICAgICAgICBmb3IodmFyIG4gPSAwOyBuIDwgbk1heDsgbisrKSBzaXplW25dICo9IGluY1tuXSAvIHRvdGFsO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoaXN0b2dyYW1BdHRycyA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbS9hdHRyaWJ1dGVzJyk7XG52YXIgbWFrZUJpbkF0dHJzID0gcmVxdWlyZSgnLi4vaGlzdG9ncmFtL2Jpbl9hdHRyaWJ1dGVzJyk7XG52YXIgaGVhdG1hcEF0dHJzID0gcmVxdWlyZSgnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdChcbiAgICB7XG4gICAgICAgIHg6IGhpc3RvZ3JhbUF0dHJzLngsXG4gICAgICAgIHk6IGhpc3RvZ3JhbUF0dHJzLnksXG5cbiAgICAgICAgejoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuXG4gICAgICAgIGhpc3Rub3JtOiBoaXN0b2dyYW1BdHRycy5oaXN0bm9ybSxcbiAgICAgICAgaGlzdGZ1bmM6IGhpc3RvZ3JhbUF0dHJzLmhpc3RmdW5jLFxuICAgICAgICBuYmluc3g6IGhpc3RvZ3JhbUF0dHJzLm5iaW5zeCxcbiAgICAgICAgeGJpbnM6IG1ha2VCaW5BdHRycygneCcpLFxuICAgICAgICBuYmluc3k6IGhpc3RvZ3JhbUF0dHJzLm5iaW5zeSxcbiAgICAgICAgeWJpbnM6IG1ha2VCaW5BdHRycygneScpLFxuICAgICAgICBhdXRvYmlueDogaGlzdG9ncmFtQXR0cnMuYXV0b2JpbngsXG4gICAgICAgIGF1dG9iaW55OiBoaXN0b2dyYW1BdHRycy5hdXRvYmlueSxcblxuICAgICAgICB4Z2FwOiBoZWF0bWFwQXR0cnMueGdhcCxcbiAgICAgICAgeWdhcDogaGVhdG1hcEF0dHJzLnlnYXAsXG4gICAgICAgIHpzbW9vdGg6IGhlYXRtYXBBdHRycy56c21vb3RoLFxuICAgICAgICB6aG92ZXJmb3JtYXQ6IGhlYXRtYXBBdHRycy56aG92ZXJmb3JtYXRcbiAgICB9LFxuICAgIGNvbG9yc2NhbGVBdHRycygnJywge1xuICAgICAgICBjTGV0dGVyOiAneicsXG4gICAgICAgIGF1dG9Db2xvckRmbHQ6IGZhbHNlXG4gICAgfSksXG4gICAgeyBjb2xvcmJhcjogY29sb3JiYXJBdHRycyB9XG4pO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGJpbkZ1bmN0aW9ucyA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbS9iaW5fZnVuY3Rpb25zJyk7XG52YXIgbm9ybUZ1bmN0aW9ucyA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbS9ub3JtX2Z1bmN0aW9ucycpO1xudmFyIGRvQXZnID0gcmVxdWlyZSgnLi4vaGlzdG9ncmFtL2F2ZXJhZ2UnKTtcbnZhciBnZXRCaW5TcGFuTGFiZWxSb3VuZCA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbS9iaW5fbGFiZWxfdmFscycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICB2YXIgeCA9IHRyYWNlLnggPyB4YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd4JykgOiBbXTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICB2YXIgeSA9IHRyYWNlLnkgPyB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd5JykgOiBbXTtcbiAgICB2YXIgeGNhbGVuZGFyID0gdHJhY2UueGNhbGVuZGFyO1xuICAgIHZhciB5Y2FsZW5kYXIgPSB0cmFjZS55Y2FsZW5kYXI7XG4gICAgdmFyIHhyMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiB4YS5yMmModiwgMCwgeGNhbGVuZGFyKTsgfTtcbiAgICB2YXIgeXIyYyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHlhLnIyYyh2LCAwLCB5Y2FsZW5kYXIpOyB9O1xuICAgIHZhciB4YzJyID0gZnVuY3Rpb24odikgeyByZXR1cm4geGEuYzJyKHYsIDAsIHhjYWxlbmRhcik7IH07XG4gICAgdmFyIHljMnIgPSBmdW5jdGlvbih2KSB7IHJldHVybiB5YS5jMnIodiwgMCwgeWNhbGVuZGFyKTsgfTtcblxuICAgIHZhciBpLCBqLCBuLCBtO1xuXG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgaWYoeC5sZW5ndGggPiBzZXJpZXNsZW4pIHguc3BsaWNlKHNlcmllc2xlbiwgeC5sZW5ndGggLSBzZXJpZXNsZW4pO1xuICAgIGlmKHkubGVuZ3RoID4gc2VyaWVzbGVuKSB5LnNwbGljZShzZXJpZXNsZW4sIHkubGVuZ3RoIC0gc2VyaWVzbGVuKTtcblxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgYmluc1xuICAgIGRvQXV0b0Jpbih0cmFjZSwgJ3gnLCB4LCB4YSwgeHIyYywgeGMyciwgeGNhbGVuZGFyKTtcbiAgICBkb0F1dG9CaW4odHJhY2UsICd5JywgeSwgeWEsIHlyMmMsIHljMnIsIHljYWxlbmRhcik7XG5cbiAgICAvLyBtYWtlIHRoZSBlbXB0eSBiaW4gYXJyYXkgJiBzY2FsZSB0aGUgbWFwXG4gICAgdmFyIHogPSBbXTtcbiAgICB2YXIgb25lY29sID0gW107XG4gICAgdmFyIHplcm9jb2wgPSBbXTtcbiAgICB2YXIgbm9udW5pZm9ybUJpbnNYID0gKHR5cGVvZih0cmFjZS54Ymlucy5zaXplKSA9PT0gJ3N0cmluZycpO1xuICAgIHZhciBub251bmlmb3JtQmluc1kgPSAodHlwZW9mKHRyYWNlLnliaW5zLnNpemUpID09PSAnc3RyaW5nJyk7XG4gICAgdmFyIHhFZGdlcyA9IFtdO1xuICAgIHZhciB5RWRnZXMgPSBbXTtcbiAgICB2YXIgeGJpbnMgPSBub251bmlmb3JtQmluc1ggPyB4RWRnZXMgOiB0cmFjZS54YmlucztcbiAgICB2YXIgeWJpbnMgPSBub251bmlmb3JtQmluc1kgPyB5RWRnZXMgOiB0cmFjZS55YmlucztcbiAgICB2YXIgdG90YWwgPSAwO1xuICAgIHZhciBjb3VudHMgPSBbXTtcbiAgICB2YXIgaW5wdXRQb2ludHMgPSBbXTtcbiAgICB2YXIgbm9ybSA9IHRyYWNlLmhpc3Rub3JtO1xuICAgIHZhciBmdW5jID0gdHJhY2UuaGlzdGZ1bmM7XG4gICAgdmFyIGRlbnNpdHlub3JtID0gKG5vcm0uaW5kZXhPZignZGVuc2l0eScpICE9PSAtMSk7XG4gICAgdmFyIGV4dHJlbWVmdW5jID0gKGZ1bmMgPT09ICdtYXgnIHx8IGZ1bmMgPT09ICdtaW4nKTtcbiAgICB2YXIgc2l6ZWluaXQgPSAoZXh0cmVtZWZ1bmMgPyBudWxsIDogMCk7XG4gICAgdmFyIGJpbmZ1bmMgPSBiaW5GdW5jdGlvbnMuY291bnQ7XG4gICAgdmFyIG5vcm1mdW5jID0gbm9ybUZ1bmN0aW9uc1tub3JtXTtcbiAgICB2YXIgZG9hdmcgPSBmYWxzZTtcbiAgICB2YXIgeGluYyA9IFtdO1xuICAgIHZhciB5aW5jID0gW107XG5cbiAgICAvLyBzZXQgYSBiaW5uaW5nIGZ1bmN0aW9uIG90aGVyIHRoYW4gY291bnQ/XG4gICAgLy8gZm9yIGJpbm5pbmcgZnVuY3Rpb25zOiBjaGVjayBmaXJzdCBmb3IgJ3onLFxuICAgIC8vIHRoZW4gJ21jJyBpbiBjYXNlIHdlIGhhZCBhIGNvbG9yZWQgc2NhdHRlciBwbG90XG4gICAgLy8gYW5kIHdhbnQgdG8gdHJhbnNmZXIgdGhlc2UgY29sb3JzIHRvIHRoZSAyRCBoaXN0b1xuICAgIC8vIFRPRE86IGF4ZSB0aGlzLCBtYWtlIGl0IHRoZSByZXNwb25zaWJpbGl0eSBvZiB0aGUgYXBwIGNoYW5naW5nIHR5cGU/IG9yIGFuIGltcGxpZWRFZGl0P1xuICAgIHZhciByYXdDb3VudGVyRGF0YSA9ICgneicgaW4gdHJhY2UpID9cbiAgICAgICAgdHJhY2UueiA6XG4gICAgICAgICgoJ21hcmtlcicgaW4gdHJhY2UgJiYgQXJyYXkuaXNBcnJheSh0cmFjZS5tYXJrZXIuY29sb3IpKSA/XG4gICAgICAgICAgICB0cmFjZS5tYXJrZXIuY29sb3IgOiAnJyk7XG4gICAgaWYocmF3Q291bnRlckRhdGEgJiYgZnVuYyAhPT0gJ2NvdW50Jykge1xuICAgICAgICBkb2F2ZyA9IGZ1bmMgPT09ICdhdmcnO1xuICAgICAgICBiaW5mdW5jID0gYmluRnVuY3Rpb25zW2Z1bmNdO1xuICAgIH1cblxuICAgIC8vIGRlY3JlYXNlIGVuZCBhIGxpdHRsZSBpbiBjYXNlIG9mIHJvdW5kaW5nIGVycm9yc1xuICAgIHZhciBiaW5TcGVjID0gdHJhY2UueGJpbnMsXG4gICAgICAgIGJpblN0YXJ0ID0geHIyYyhiaW5TcGVjLnN0YXJ0KSxcbiAgICAgICAgYmluRW5kID0geHIyYyhiaW5TcGVjLmVuZCkgK1xuICAgICAgICAgICAgKGJpblN0YXJ0IC0gQXhlcy50aWNrSW5jcmVtZW50KGJpblN0YXJ0LCBiaW5TcGVjLnNpemUsIGZhbHNlLCB4Y2FsZW5kYXIpKSAvIDFlNjtcblxuICAgIGZvcihpID0gYmluU3RhcnQ7IGkgPCBiaW5FbmQ7IGkgPSBBeGVzLnRpY2tJbmNyZW1lbnQoaSwgYmluU3BlYy5zaXplLCBmYWxzZSwgeGNhbGVuZGFyKSkge1xuICAgICAgICBvbmVjb2wucHVzaChzaXplaW5pdCk7XG4gICAgICAgIHhFZGdlcy5wdXNoKGkpO1xuICAgICAgICBpZihkb2F2ZykgemVyb2NvbC5wdXNoKDApO1xuICAgIH1cbiAgICB4RWRnZXMucHVzaChpKTtcblxuICAgIHZhciBueCA9IG9uZWNvbC5sZW5ndGg7XG4gICAgdmFyIHgwYyA9IHhyMmModHJhY2UueGJpbnMuc3RhcnQpO1xuICAgIHZhciBkeCA9IChpIC0geDBjKSAvIG54O1xuICAgIHZhciB4MCA9IHhjMnIoeDBjICsgZHggLyAyKTtcblxuICAgIGJpblNwZWMgPSB0cmFjZS55YmlucztcbiAgICBiaW5TdGFydCA9IHlyMmMoYmluU3BlYy5zdGFydCk7XG4gICAgYmluRW5kID0geXIyYyhiaW5TcGVjLmVuZCkgK1xuICAgICAgICAoYmluU3RhcnQgLSBBeGVzLnRpY2tJbmNyZW1lbnQoYmluU3RhcnQsIGJpblNwZWMuc2l6ZSwgZmFsc2UsIHljYWxlbmRhcikpIC8gMWU2O1xuXG4gICAgZm9yKGkgPSBiaW5TdGFydDsgaSA8IGJpbkVuZDsgaSA9IEF4ZXMudGlja0luY3JlbWVudChpLCBiaW5TcGVjLnNpemUsIGZhbHNlLCB5Y2FsZW5kYXIpKSB7XG4gICAgICAgIHoucHVzaChvbmVjb2wuc2xpY2UoKSk7XG4gICAgICAgIHlFZGdlcy5wdXNoKGkpO1xuICAgICAgICB2YXIgaXBDb2wgPSBuZXcgQXJyYXkobngpO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBueDsgaisrKSBpcENvbFtqXSA9IFtdO1xuICAgICAgICBpbnB1dFBvaW50cy5wdXNoKGlwQ29sKTtcbiAgICAgICAgaWYoZG9hdmcpIGNvdW50cy5wdXNoKHplcm9jb2wuc2xpY2UoKSk7XG4gICAgfVxuICAgIHlFZGdlcy5wdXNoKGkpO1xuXG4gICAgdmFyIG55ID0gei5sZW5ndGg7XG4gICAgdmFyIHkwYyA9IHlyMmModHJhY2UueWJpbnMuc3RhcnQpO1xuICAgIHZhciBkeSA9IChpIC0geTBjKSAvIG55O1xuICAgIHZhciB5MCA9IHljMnIoeTBjICsgZHkgLyAyKTtcblxuICAgIGlmKGRlbnNpdHlub3JtKSB7XG4gICAgICAgIHhpbmMgPSBtYWtlSW5jcmVtZW50cyhvbmVjb2wubGVuZ3RoLCB4YmlucywgZHgsIG5vbnVuaWZvcm1CaW5zWCk7XG4gICAgICAgIHlpbmMgPSBtYWtlSW5jcmVtZW50cyh6Lmxlbmd0aCwgeWJpbnMsIGR5LCBub251bmlmb3JtQmluc1kpO1xuICAgIH1cblxuICAgIC8vIGZvciBkYXRlIGF4ZXMgd2UgbmVlZCBiaW4gYm91bmRzIHRvIGJlIGNhbGNkYXRhLiBGb3Igbm9udW5pZm9ybSBiaW5zXG4gICAgLy8gd2UgYWxyZWFkeSBoYXZlIHRoaXMsIGJ1dCB1bmlmb3JtIHdpdGggc3RhcnQvZW5kL3NpemUgdGhleSdyZSBzdGlsbCBzdHJpbmdzLlxuICAgIGlmKCFub251bmlmb3JtQmluc1ggJiYgeGEudHlwZSA9PT0gJ2RhdGUnKSB4YmlucyA9IGJpbnNUb0NhbGMoeHIyYywgeGJpbnMpO1xuICAgIGlmKCFub251bmlmb3JtQmluc1kgJiYgeWEudHlwZSA9PT0gJ2RhdGUnKSB5YmlucyA9IGJpbnNUb0NhbGMoeXIyYywgeWJpbnMpO1xuXG4gICAgLy8gcHV0IGRhdGEgaW50byBiaW5zXG4gICAgdmFyIHVuaXF1ZVZhbHNQZXJYID0gdHJ1ZTtcbiAgICB2YXIgdW5pcXVlVmFsc1BlclkgPSB0cnVlO1xuICAgIHZhciB4VmFscyA9IG5ldyBBcnJheShueCk7XG4gICAgdmFyIHlWYWxzID0gbmV3IEFycmF5KG55KTtcbiAgICB2YXIgeEdhcExvdyA9IEluZmluaXR5O1xuICAgIHZhciB4R2FwSGlnaCA9IEluZmluaXR5O1xuICAgIHZhciB5R2FwTG93ID0gSW5maW5pdHk7XG4gICAgdmFyIHlHYXBIaWdoID0gSW5maW5pdHk7XG4gICAgZm9yKGkgPSAwOyBpIDwgc2VyaWVzbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHhpID0geFtpXTtcbiAgICAgICAgdmFyIHlpID0geVtpXTtcbiAgICAgICAgbiA9IExpYi5maW5kQmluKHhpLCB4Ymlucyk7XG4gICAgICAgIG0gPSBMaWIuZmluZEJpbih5aSwgeWJpbnMpO1xuICAgICAgICBpZihuID49IDAgJiYgbiA8IG54ICYmIG0gPj0gMCAmJiBtIDwgbnkpIHtcbiAgICAgICAgICAgIHRvdGFsICs9IGJpbmZ1bmMobiwgaSwgelttXSwgcmF3Q291bnRlckRhdGEsIGNvdW50c1ttXSk7XG4gICAgICAgICAgICBpbnB1dFBvaW50c1ttXVtuXS5wdXNoKGkpO1xuXG4gICAgICAgICAgICBpZih1bmlxdWVWYWxzUGVyWCkge1xuICAgICAgICAgICAgICAgIGlmKHhWYWxzW25dID09PSB1bmRlZmluZWQpIHhWYWxzW25dID0geGk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZih4VmFsc1tuXSAhPT0geGkpIHVuaXF1ZVZhbHNQZXJYID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih1bmlxdWVWYWxzUGVyWSkge1xuICAgICAgICAgICAgICAgIGlmKHlWYWxzW25dID09PSB1bmRlZmluZWQpIHlWYWxzW25dID0geWk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZih5VmFsc1tuXSAhPT0geWkpIHVuaXF1ZVZhbHNQZXJZID0gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHhHYXBMb3cgPSBNYXRoLm1pbih4R2FwTG93LCB4aSAtIHhFZGdlc1tuXSk7XG4gICAgICAgICAgICB4R2FwSGlnaCA9IE1hdGgubWluKHhHYXBIaWdoLCB4RWRnZXNbbiArIDFdIC0geGkpO1xuICAgICAgICAgICAgeUdhcExvdyA9IE1hdGgubWluKHlHYXBMb3csIHlpIC0geUVkZ2VzW21dKTtcbiAgICAgICAgICAgIHlHYXBIaWdoID0gTWF0aC5taW4oeUdhcEhpZ2gsIHlFZGdlc1ttICsgMV0gLSB5aSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gbm9ybWFsaXplLCBpZiBuZWVkZWRcbiAgICBpZihkb2F2Zykge1xuICAgICAgICBmb3IobSA9IDA7IG0gPCBueTsgbSsrKSB0b3RhbCArPSBkb0F2Zyh6W21dLCBjb3VudHNbbV0pO1xuICAgIH1cbiAgICBpZihub3JtZnVuYykge1xuICAgICAgICBmb3IobSA9IDA7IG0gPCBueTsgbSsrKSBub3JtZnVuYyh6W21dLCB0b3RhbCwgeGluYywgeWluY1ttXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogeCxcbiAgICAgICAgeFJhbmdlczogZ2V0UmFuZ2VzKHhFZGdlcywgdW5pcXVlVmFsc1BlclggJiYgeFZhbHMsIHhHYXBMb3csIHhHYXBIaWdoLCB4YSwgeGNhbGVuZGFyKSxcbiAgICAgICAgeDA6IHgwLFxuICAgICAgICBkeDogZHgsXG4gICAgICAgIHk6IHksXG4gICAgICAgIHlSYW5nZXM6IGdldFJhbmdlcyh5RWRnZXMsIHVuaXF1ZVZhbHNQZXJZICYmIHlWYWxzLCB5R2FwTG93LCB5R2FwSGlnaCwgeWEsIHljYWxlbmRhciksXG4gICAgICAgIHkwOiB5MCxcbiAgICAgICAgZHk6IGR5LFxuICAgICAgICB6OiB6LFxuICAgICAgICBwdHM6IGlucHV0UG9pbnRzXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIGRvQXV0b0Jpbih0cmFjZSwgYXhMZXR0ZXIsIGRhdGEsIGF4LCByMmMsIGMyciwgY2FsZW5kYXIpIHtcbiAgICB2YXIgYmluQXR0ciA9IGF4TGV0dGVyICsgJ2JpbnMnO1xuICAgIHZhciBiaW5TcGVjID0gdHJhY2VbYmluQXR0cl07XG4gICAgaWYoIWJpblNwZWMpIGJpblNwZWMgPSB0cmFjZVtiaW5BdHRyXSA9IHt9O1xuICAgIHZhciBpbnB1dEJpblNwZWMgPSB0cmFjZS5faW5wdXRbYmluQXR0cl0gfHwge307XG4gICAgdmFyIGF1dG9CaW4gPSB0cmFjZS5fYXV0b0JpbiA9IHt9O1xuXG4gICAgLy8gY2xlYXIgb3V0IGFueSBwcmV2aW91c2x5IGFkZGVkIGF1dG9iaW4gaW5mb1xuICAgIGlmKCFpbnB1dEJpblNwZWMuc2l6ZSkgZGVsZXRlIGJpblNwZWMuc2l6ZTtcbiAgICBpZihpbnB1dEJpblNwZWMuc3RhcnQgPT09IHVuZGVmaW5lZCkgZGVsZXRlIGJpblNwZWMuc3RhcnQ7XG4gICAgaWYoaW5wdXRCaW5TcGVjLmVuZCA9PT0gdW5kZWZpbmVkKSBkZWxldGUgYmluU3BlYy5lbmQ7XG5cbiAgICB2YXIgYXV0b1NpemUgPSAhYmluU3BlYy5zaXplO1xuICAgIHZhciBhdXRvU3RhcnQgPSBiaW5TcGVjLnN0YXJ0ID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIGF1dG9FbmQgPSBiaW5TcGVjLmVuZCA9PT0gdW5kZWZpbmVkO1xuXG4gICAgaWYoYXV0b1NpemUgfHwgYXV0b1N0YXJ0IHx8IGF1dG9FbmQpIHtcbiAgICAgICAgdmFyIG5ld0JpblNwZWMgPSBBeGVzLmF1dG9CaW4oZGF0YSwgYXgsIHRyYWNlWyduYmlucycgKyBheExldHRlcl0sICcyZCcsIGNhbGVuZGFyLCBiaW5TcGVjLnNpemUpO1xuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnaGlzdG9ncmFtMmRjb250b3VyJykge1xuICAgICAgICAgICAgLy8gdGhlIFwidHJ1ZVwiIDJuZCBhcmd1bWVudCByZXZlcnNlcyB0aGUgdGljayBkaXJlY3Rpb24gKHdoaWNoIHdlIGNhbid0XG4gICAgICAgICAgICAvLyBqdXN0IGRvIHdpdGggYSBtaW51cyBzaWduIGJlY2F1c2Ugb2YgbW9udGggYmlucylcbiAgICAgICAgICAgIGlmKGF1dG9TdGFydCkge1xuICAgICAgICAgICAgICAgIG5ld0JpblNwZWMuc3RhcnQgPSBjMnIoQXhlcy50aWNrSW5jcmVtZW50KFxuICAgICAgICAgICAgICAgICAgICByMmMobmV3QmluU3BlYy5zdGFydCksIG5ld0JpblNwZWMuc2l6ZSwgdHJ1ZSwgY2FsZW5kYXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGF1dG9FbmQpIHtcbiAgICAgICAgICAgICAgICBuZXdCaW5TcGVjLmVuZCA9IGMycihBeGVzLnRpY2tJbmNyZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgIHIyYyhuZXdCaW5TcGVjLmVuZCksIG5ld0JpblNwZWMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoYXV0b1NpemUpIGJpblNwZWMuc2l6ZSA9IGF1dG9CaW4uc2l6ZSA9IG5ld0JpblNwZWMuc2l6ZTtcbiAgICAgICAgaWYoYXV0b1N0YXJ0KSBiaW5TcGVjLnN0YXJ0ID0gYXV0b0Jpbi5zdGFydCA9IG5ld0JpblNwZWMuc3RhcnQ7XG4gICAgICAgIGlmKGF1dG9FbmQpIGJpblNwZWMuZW5kID0gYXV0b0Jpbi5lbmQgPSBuZXdCaW5TcGVjLmVuZDtcbiAgICB9XG5cbiAgICAvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5IGZvciBvbmUtdGltZSBhdXRvYmlubmluZy5cbiAgICAvLyBhdXRvYmluOiB0cnVlIGlzIGhhbmRsZWQgaW4gY2xlYW5EYXRhLCBidXQgYXV0b2JpbjogZmFsc2VcbiAgICAvLyBuZWVkcyB0byBiZSBoZXJlIHdoZXJlIHdlIGhhdmUgZGV0ZXJtaW5lZCB0aGUgdmFsdWVzLlxuICAgIHZhciBhdXRvQmluQXR0ciA9ICdhdXRvYmluJyArIGF4TGV0dGVyO1xuICAgIGlmKHRyYWNlLl9pbnB1dFthdXRvQmluQXR0cl0gPT09IGZhbHNlKSB7XG4gICAgICAgIHRyYWNlLl9pbnB1dFtiaW5BdHRyXSA9IExpYi5leHRlbmRGbGF0KHt9LCBiaW5TcGVjKTtcbiAgICAgICAgZGVsZXRlIHRyYWNlLl9pbnB1dFthdXRvQmluQXR0cl07XG4gICAgICAgIGRlbGV0ZSB0cmFjZVthdXRvQmluQXR0cl07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtYWtlSW5jcmVtZW50cyhsZW4sIGJpbnMsIGR2LCBub251bmlmb3JtKSB7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBpO1xuICAgIGlmKG5vbnVuaWZvcm0pIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dFtpXSA9IDEgLyAoYmluc1tpICsgMV0gLSBiaW5zW2ldKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBpbmMgPSAxIC8gZHY7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSBvdXRbaV0gPSBpbmM7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGJpbnNUb0NhbGMocjJjLCBiaW5zKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHIyYyhiaW5zLnN0YXJ0KSxcbiAgICAgICAgZW5kOiByMmMoYmlucy5lbmQpLFxuICAgICAgICBzaXplOiBiaW5zLnNpemVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRSYW5nZXMoZWRnZXMsIHVuaXF1ZVZhbHMsIGdhcExvdywgZ2FwSGlnaCwgYXgsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIGxlbiA9IGVkZ2VzLmxlbmd0aCAtIDE7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIGlmKHVuaXF1ZVZhbHMpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dFtpXSA9IFt1bmlxdWVWYWxzW2ldLCB1bmlxdWVWYWxzW2ldXTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciByb3VuZEZuID0gZ2V0QmluU3BhbkxhYmVsUm91bmQoZ2FwTG93LCBnYXBIaWdoLCBlZGdlcywgYXgsIGNhbGVuZGFyKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dFtpXSA9IFtyb3VuZEZuKGVkZ2VzW2ldKSwgcm91bmRGbihlZGdlc1tpICsgMV0sIHRydWUpXTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcbnZhciBheGlzSWRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbnZhciBCSU5ESVJFQ1RJT05TID0gWyd4JywgJ3knXTtcblxuLy8gSGFuZGxlIGJpbiBhdHRycyBhbmQgcmVsaW5rIGF1dG8tZGV0ZXJtaW5lZCB2YWx1ZXMgc28gZnVsbERhdGEgaXMgY29tcGxldGVcbi8vIGRvZXMgbm90IGhhdmUgY3Jvc3MtdHJhY2UgY291cGxpbmcsIGJ1dCBtb3ZlZCBvdXQgaGVyZSBzbyB3ZSBoYXZlIGF4aXMgdHlwZXNcbi8vIGFuZCByZWxpbmtlZCB0cmFjZS5fYXV0b0JpblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcm9zc1RyYWNlRGVmYXVsdHMoZnVsbERhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaSwgaiwgdHJhY2VPdXQsIGJpbkRpcmVjdGlvbjtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlT3V0Ll9pbnB1dCwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlT3V0ID0gZnVsbERhdGFbaV07XG4gICAgICAgIHZhciB0eXBlID0gdHJhY2VPdXQudHlwZTtcbiAgICAgICAgaWYodHlwZSAhPT0gJ2hpc3RvZ3JhbTJkJyAmJiB0eXBlICE9PSAnaGlzdG9ncmFtMmRjb250b3VyJykgY29udGludWU7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgQklORElSRUNUSU9OUy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgYmluRGlyZWN0aW9uID0gQklORElSRUNUSU9OU1tqXTtcbiAgICAgICAgICAgIHZhciBiaW5BdHRyID0gYmluRGlyZWN0aW9uICsgJ2JpbnMnO1xuICAgICAgICAgICAgdmFyIGF1dG9CaW5zID0gKHRyYWNlT3V0Ll9hdXRvQmluIHx8IHt9KVtiaW5EaXJlY3Rpb25dIHx8IHt9O1xuICAgICAgICAgICAgY29lcmNlKGJpbkF0dHIgKyAnLnN0YXJ0JywgYXV0b0JpbnMuc3RhcnQpO1xuICAgICAgICAgICAgY29lcmNlKGJpbkF0dHIgKyAnLmVuZCcsIGF1dG9CaW5zLmVuZCk7XG4gICAgICAgICAgICBjb2VyY2UoYmluQXR0ciArICcuc2l6ZScsIGF1dG9CaW5zLnNpemUpO1xuXG4gICAgICAgICAgICBjbGVhbkJpbnModHJhY2VPdXQsIGJpbkRpcmVjdGlvbiwgZnVsbExheW91dCwgYXV0b0JpbnMpO1xuXG4gICAgICAgICAgICBpZighKHRyYWNlT3V0W2JpbkF0dHJdIHx8IHt9KS5zaXplKSBjb2VyY2UoJ25iaW5zJyArIGJpbkRpcmVjdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjbGVhbkJpbnModHJhY2UsIGJpbkRpcmVjdGlvbiwgZnVsbExheW91dCwgYXV0b0JpbnMpIHtcbiAgICB2YXIgYXggPSBmdWxsTGF5b3V0W2F4aXNJZHMuaWQybmFtZSh0cmFjZVtiaW5EaXJlY3Rpb24gKyAnYXhpcyddKV07XG4gICAgdmFyIGF4VHlwZSA9IGF4LnR5cGU7XG4gICAgdmFyIGJpbkF0dHIgPSBiaW5EaXJlY3Rpb24gKyAnYmlucyc7XG4gICAgdmFyIGJpbnMgPSB0cmFjZVtiaW5BdHRyXTtcbiAgICB2YXIgY2FsZW5kYXIgPSB0cmFjZVtiaW5EaXJlY3Rpb24gKyAnY2FsZW5kYXInXTtcblxuICAgIGlmKCFiaW5zKSBiaW5zID0gdHJhY2VbYmluQXR0cl0gPSB7fTtcblxuICAgIHZhciBjbGVhbkJvdW5kID0gKGF4VHlwZSA9PT0gJ2RhdGUnKSA/XG4gICAgICAgIGZ1bmN0aW9uKHYsIGRmbHQpIHsgcmV0dXJuICh2IHx8IHYgPT09IDApID8gTGliLmNsZWFuRGF0ZSh2LCBCQUROVU0sIGNhbGVuZGFyKSA6IGRmbHQ7IH0gOlxuICAgICAgICBmdW5jdGlvbih2LCBkZmx0KSB7IHJldHVybiBpc051bWVyaWModikgPyBOdW1iZXIodikgOiBkZmx0OyB9O1xuXG4gICAgYmlucy5zdGFydCA9IGNsZWFuQm91bmQoYmlucy5zdGFydCwgYXV0b0JpbnMuc3RhcnQpO1xuICAgIGJpbnMuZW5kID0gY2xlYW5Cb3VuZChiaW5zLmVuZCwgYXV0b0JpbnMuZW5kKTtcblxuICAgIC8vIGxvZ2ljIGZvciBiaW4gc2l6ZSBpcyB2ZXJ5IHNpbWlsYXIgdG8gZHRpY2sgKGNhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzKVxuICAgIC8vIGJ1dCB3aXRob3V0IHRoZSBleHRyYSBzdHJpbmcgb3B0aW9ucyBmb3IgbG9nIGF4ZXNcbiAgICAvLyBpZSB0aGUgb25seSBzdHJpbmdzIHdlIGFjY2VwdCBhcmUgTTxuPiBmb3IgbW9udGhzXG4gICAgdmFyIHNpemVEZmx0ID0gYXV0b0JpbnMuc2l6ZTtcbiAgICB2YXIgYmluU2l6ZSA9IGJpbnMuc2l6ZTtcblxuICAgIGlmKGlzTnVtZXJpYyhiaW5TaXplKSkge1xuICAgICAgICBiaW5zLnNpemUgPSAoYmluU2l6ZSA+IDApID8gTnVtYmVyKGJpblNpemUpIDogc2l6ZURmbHQ7XG4gICAgfVxuICAgIGVsc2UgaWYodHlwZW9mIGJpblNpemUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGJpbnMuc2l6ZSA9IHNpemVEZmx0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gZGF0ZSBzcGVjaWFsIGNhc2U6IFwiTTxuPlwiIGdpdmVzIGJpbnMgZXZlcnkgKGludGVnZXIpIG4gbW9udGhzXG4gICAgICAgIHZhciBwcmVmaXggPSBiaW5TaXplLmNoYXJBdCgwKTtcbiAgICAgICAgdmFyIHNpemVOdW0gPSBiaW5TaXplLnN1YnN0cigxKTtcblxuICAgICAgICBzaXplTnVtID0gaXNOdW1lcmljKHNpemVOdW0pID8gTnVtYmVyKHNpemVOdW0pIDogMDtcbiAgICAgICAgaWYoKHNpemVOdW0gPD0gMCkgfHwgIShcbiAgICAgICAgICAgICAgICBheFR5cGUgPT09ICdkYXRlJyAmJiBwcmVmaXggPT09ICdNJyAmJiBzaXplTnVtID09PSBNYXRoLnJvdW5kKHNpemVOdW0pXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgICBiaW5zLnNpemUgPSBzaXplRGZsdDtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBoYW5kbGVTYW1wbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4vc2FtcGxlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgaGFuZGxlU2FtcGxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZih0cmFjZU91dC52aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuICAgIGNvbG9yc2NhbGVEZWZhdWx0cyhcbiAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfVxuICAgICk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoZWF0bWFwSG92ZXIgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2hvdmVyJyk7XG52YXIgaG92ZXJMYWJlbFRleHQgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLmhvdmVyTGFiZWxUZXh0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlLCBob3ZlckxheWVyLCBjb250b3VyKSB7XG4gICAgdmFyIHB0cyA9IGhlYXRtYXBIb3Zlcihwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSwgaG92ZXJMYXllciwgY29udG91cik7XG5cbiAgICBpZighcHRzKSByZXR1cm47XG5cbiAgICBwb2ludERhdGEgPSBwdHNbMF07XG4gICAgdmFyIGluZGljZXMgPSBwb2ludERhdGEuaW5kZXg7XG4gICAgdmFyIG55ID0gaW5kaWNlc1swXTtcbiAgICB2YXIgbnggPSBpbmRpY2VzWzFdO1xuICAgIHZhciBjZDAgPSBwb2ludERhdGEuY2RbMF07XG4gICAgdmFyIHhSYW5nZSA9IGNkMC54UmFuZ2VzW254XTtcbiAgICB2YXIgeVJhbmdlID0gY2QwLnlSYW5nZXNbbnldO1xuXG4gICAgcG9pbnREYXRhLnhMYWJlbCA9IGhvdmVyTGFiZWxUZXh0KHBvaW50RGF0YS54YSwgeFJhbmdlWzBdLCB4UmFuZ2VbMV0pO1xuICAgIHBvaW50RGF0YS55TGFiZWwgPSBob3ZlckxhYmVsVGV4dChwb2ludERhdGEueWEsIHlSYW5nZVswXSwgeVJhbmdlWzFdKTtcblxuICAgIHJldHVybiBwdHM7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBIaXN0b2dyYW0yRCA9IHt9O1xuXG5IaXN0b2dyYW0yRC5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5IaXN0b2dyYW0yRC5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbkhpc3RvZ3JhbTJELmNyb3NzVHJhY2VEZWZhdWx0cyA9IHJlcXVpcmUoJy4vY3Jvc3NfdHJhY2VfZGVmYXVsdHMnKTtcbkhpc3RvZ3JhbTJELmNhbGMgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NhbGMnKTtcbkhpc3RvZ3JhbTJELnBsb3QgPSByZXF1aXJlKCcuLi9oZWF0bWFwL3Bsb3QnKTtcbkhpc3RvZ3JhbTJELmxheWVyTmFtZSA9ICdoZWF0bWFwbGF5ZXInO1xuSGlzdG9ncmFtMkQuY29sb3JiYXIgPSByZXF1aXJlKCcuLi9oZWF0bWFwL2NvbG9yYmFyJyk7XG5IaXN0b2dyYW0yRC5zdHlsZSA9IHJlcXVpcmUoJy4uL2hlYXRtYXAvc3R5bGUnKTtcbkhpc3RvZ3JhbTJELmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuSGlzdG9ncmFtMkQuZXZlbnREYXRhID0gcmVxdWlyZSgnLi4vaGlzdG9ncmFtL2V2ZW50X2RhdGEnKTtcblxuSGlzdG9ncmFtMkQubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5IaXN0b2dyYW0yRC5uYW1lID0gJ2hpc3RvZ3JhbTJkJztcbkhpc3RvZ3JhbTJELmJhc2VQbG90TW9kdWxlID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyk7XG5IaXN0b2dyYW0yRC5jYXRlZ29yaWVzID0gWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJzJkTWFwJywgJ2hpc3RvZ3JhbSddO1xuSGlzdG9ncmFtMkQubWV0YSA9IHtcbiAgICBcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSGlzdG9ncmFtMkQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTYW1wbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpIHtcbiAgICB2YXIgeCA9IGNvZXJjZSgneCcpO1xuICAgIHZhciB5ID0gY29lcmNlKCd5Jyk7XG5cbiAgICAvLyB3ZSBjb3VsZCB0cnkgdG8gYWNjZXB0IHgwIGFuZCBkeCwgZXRjLi4uXG4gICAgLy8gYnV0IHRoYXQncyBhIHByZXR0eSB3ZWlyZCB1c2UgY2FzZS5cbiAgICAvLyBmb3Igbm93IHJlcXVpcmUgYm90aCB4IGFuZCB5IGV4cGxpY2l0bHkgc3BlY2lmaWVkLlxuICAgIGlmKCEoeCAmJiB4Lmxlbmd0aCAmJiB5ICYmIHkubGVuZ3RoKSkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gTWF0aC5taW4oeC5sZW5ndGgsIHkubGVuZ3RoKTtcblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5J10sIGxheW91dCk7XG5cbiAgICAvLyBpZiBtYXJrZXIuY29sb3IgaXMgYW4gYXJyYXksIHdlIGNhbiB1c2UgaXQgaW4gYWdncmVnYXRpb24gaW5zdGVhZCBvZiB6XG4gICAgdmFyIGhhc0FnZ3JlZ2F0aW9uRGF0YSA9IGNvZXJjZSgneicpIHx8IGNvZXJjZSgnbWFya2VyLmNvbG9yJyk7XG5cbiAgICBpZihoYXNBZ2dyZWdhdGlvbkRhdGEpIGNvZXJjZSgnaGlzdGZ1bmMnKTtcbiAgICBjb2VyY2UoJ2hpc3Rub3JtJyk7XG5cbiAgICAvLyBOb3RlOiBiaW4gZGVmYXVsdHMgYXJlIG5vdyBoYW5kbGVkIGluIEhpc3RvZ3JhbTJELmNyb3NzVHJhY2VEZWZhdWx0c1xuICAgIC8vIGF1dG9iaW4oeHx5KSBhcmUgb25seSBpbmNsdWRlZCBoZXJlIHRvIGFwcGVhc2UgUGxvdGx5LnZhbGlkYXRlXG4gICAgY29lcmNlKCdhdXRvYmlueCcpO1xuICAgIGNvZXJjZSgnYXV0b2JpbnknKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoaXN0b2dyYW0yZEF0dHJzID0gcmVxdWlyZSgnLi4vaGlzdG9ncmFtMmQvYXR0cmlidXRlcycpO1xudmFyIGNvbnRvdXJBdHRycyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yc2NhbGVBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JiYXJBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JiYXIvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dGVuZEZsYXQoe1xuICAgIHg6IGhpc3RvZ3JhbTJkQXR0cnMueCxcbiAgICB5OiBoaXN0b2dyYW0yZEF0dHJzLnksXG4gICAgejogaGlzdG9ncmFtMmRBdHRycy56LFxuICAgIG1hcmtlcjogaGlzdG9ncmFtMmRBdHRycy5tYXJrZXIsXG5cbiAgICBoaXN0bm9ybTogaGlzdG9ncmFtMmRBdHRycy5oaXN0bm9ybSxcbiAgICBoaXN0ZnVuYzogaGlzdG9ncmFtMmRBdHRycy5oaXN0ZnVuYyxcbiAgICBuYmluc3g6IGhpc3RvZ3JhbTJkQXR0cnMubmJpbnN4LFxuICAgIHhiaW5zOiBoaXN0b2dyYW0yZEF0dHJzLnhiaW5zLFxuICAgIG5iaW5zeTogaGlzdG9ncmFtMmRBdHRycy5uYmluc3ksXG4gICAgeWJpbnM6IGhpc3RvZ3JhbTJkQXR0cnMueWJpbnMsXG4gICAgYXV0b2Jpbng6IGhpc3RvZ3JhbTJkQXR0cnMuYXV0b2JpbngsXG4gICAgYXV0b2Jpbnk6IGhpc3RvZ3JhbTJkQXR0cnMuYXV0b2JpbnksXG5cbiAgICBhdXRvY29udG91cjogY29udG91ckF0dHJzLmF1dG9jb250b3VyLFxuICAgIG5jb250b3VyczogY29udG91ckF0dHJzLm5jb250b3VycyxcbiAgICBjb250b3VyczogY29udG91ckF0dHJzLmNvbnRvdXJzLFxuICAgIGxpbmU6IGNvbnRvdXJBdHRycy5saW5lLFxuICAgIHpob3ZlcmZvcm1hdDogaGlzdG9ncmFtMmRBdHRycy56aG92ZXJmb3JtYXRcbn0sXG4gICAgY29sb3JzY2FsZUF0dHJzKCcnLCB7XG4gICAgICAgIGNMZXR0ZXI6ICd6JyxcbiAgICAgICAgZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnXG4gICAgfSksXG4gICAgeyBjb2xvcmJhcjogY29sb3JiYXJBdHRycyB9XG4pO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZVNhbXBsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vaGlzdG9ncmFtMmQvc2FtcGxlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQ29udG91cnNEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvY29udG91cnNfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVTdHlsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vY29udG91ci9zdHlsZV9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UyKGF0dHIpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UyKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyKTtcbiAgICB9XG5cbiAgICBoYW5kbGVTYW1wbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuICAgIGlmKHRyYWNlT3V0LnZpc2libGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICBoYW5kbGVDb250b3Vyc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGNvZXJjZTIpO1xuICAgIGhhbmRsZVN0eWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEhpc3RvZ3JhbTJkQ29udG91ciA9IHt9O1xuXG5IaXN0b2dyYW0yZENvbnRvdXIuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuSGlzdG9ncmFtMmRDb250b3VyLnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuSGlzdG9ncmFtMmRDb250b3VyLmNyb3NzVHJhY2VEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2hpc3RvZ3JhbTJkL2Nyb3NzX3RyYWNlX2RlZmF1bHRzJyk7XG5IaXN0b2dyYW0yZENvbnRvdXIuY2FsYyA9IHJlcXVpcmUoJy4uL2NvbnRvdXIvY2FsYycpO1xuSGlzdG9ncmFtMmRDb250b3VyLnBsb3QgPSByZXF1aXJlKCcuLi9jb250b3VyL3Bsb3QnKS5wbG90O1xuSGlzdG9ncmFtMmRDb250b3VyLmxheWVyTmFtZSA9ICdjb250b3VybGF5ZXInO1xuSGlzdG9ncmFtMmRDb250b3VyLnN0eWxlID0gcmVxdWlyZSgnLi4vY29udG91ci9zdHlsZScpO1xuSGlzdG9ncmFtMmRDb250b3VyLmNvbG9yYmFyID0gcmVxdWlyZSgnLi4vY29udG91ci9jb2xvcmJhcicpO1xuSGlzdG9ncmFtMmRDb250b3VyLmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi4vY29udG91ci9ob3ZlcicpO1xuXG5IaXN0b2dyYW0yZENvbnRvdXIubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5IaXN0b2dyYW0yZENvbnRvdXIubmFtZSA9ICdoaXN0b2dyYW0yZGNvbnRvdXInO1xuSGlzdG9ncmFtMmRDb250b3VyLmJhc2VQbG90TW9kdWxlID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyk7XG5IaXN0b2dyYW0yZENvbnRvdXIuY2F0ZWdvcmllcyA9IFsnY2FydGVzaWFuJywgJ3N2ZycsICcyZE1hcCcsICdjb250b3VyJywgJ2hpc3RvZ3JhbScsICdzaG93TGVnZW5kJ107XG5IaXN0b2dyYW0yZENvbnRvdXIubWV0YSA9IHtcbiAgICBcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSGlzdG9ncmFtMmRDb250b3VyO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG52YXIgc3VyZmFjZUF0dHMgPSByZXF1aXJlKCcuLi9zdXJmYWNlL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdCh7XG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBpOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBqOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG5cbiAgICB9LFxuICAgIGs6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcblxuICAgIH0sXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBkZWxhdW5heWF4aXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbICd4JywgJ3knLCAneicgXSxcbiAgICAgICAgZGZsdDogJ3onLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYWxwaGFodWxsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogLTEsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBpbnRlbnNpdHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgLy8gQ29sb3IgZmllbGRcbiAgICBjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB2ZXJ0ZXhjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZhY2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRyYW5zZm9ybXM6IHVuZGVmaW5lZFxufSxcblxuY29sb3JzY2FsZUF0dHJzKCcnLCB7XG4gICAgY29sb3JBdHRyOiAnYGludGVuc2l0eWAnLFxuICAgIHNob3dTY2FsZURmbHQ6IHRydWUsXG4gICAgZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnXG59KSwge1xuXG4gICAgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMsXG5cbiAgICBvcGFjaXR5OiBzdXJmYWNlQXR0cy5vcGFjaXR5LFxuXG4gICAgLy8gRmxhdCBzaGFkZWQgbW9kZVxuICAgIGZsYXRzaGFkaW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgY29udG91cjoge1xuICAgICAgICBzaG93OiBleHRlbmRGbGF0KHt9LCBzdXJmYWNlQXR0cy5jb250b3Vycy54LnNob3csIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgY29sb3I6IHN1cmZhY2VBdHRzLmNvbnRvdXJzLnguY29sb3IsXG4gICAgICAgIHdpZHRoOiBzdXJmYWNlQXR0cy5jb250b3Vycy54LndpZHRoLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIGxpZ2h0cG9zaXRpb246IHtcbiAgICAgICAgeDogZXh0ZW5kRmxhdCh7fSwgc3VyZmFjZUF0dHMubGlnaHRwb3NpdGlvbi54LCB7ZGZsdDogMWU1fSksXG4gICAgICAgIHk6IGV4dGVuZEZsYXQoe30sIHN1cmZhY2VBdHRzLmxpZ2h0cG9zaXRpb24ueSwge2RmbHQ6IDFlNX0pLFxuICAgICAgICB6OiBleHRlbmRGbGF0KHt9LCBzdXJmYWNlQXR0cy5saWdodHBvc2l0aW9uLnosIHtkZmx0OiAwfSksXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGxpZ2h0aW5nOiBleHRlbmRGbGF0KHtcbiAgICAgICAgdmVydGV4bm9ybWFsc2Vwc2lsb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxZS0xMiwgLy8gb3RoZXJ3aXNlIGZpbmVseSB0ZXNzZWxsYXRlZCB0aGluZ3MgZWcuIHRoZSBicmFpbiB3aWxsIGhhdmUgbm8gc3BlY3VsYXIgbGlnaHQgcmVmbGVjdGlvblxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmYWNlbm9ybWFsc2Vwc2lsb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxZS02LCAvLyBldmVuIHRoZSBicmFpbiBtb2RlbCBkb2Vzbid0IGFwcGVhciB0byBuZWVkIGZpbmVyIHRoYW4gdGhpc1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSwgc3VyZmFjZUF0dHMubGlnaHRpbmcpLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBiYXNlQXR0cnMuaG92ZXJpbmZvLCB7ZWRpdFR5cGU6ICdjYWxjJ30pXG59KTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIGlmKHRyYWNlLmludGVuc2l0eSkge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UuaW50ZW5zaXR5LCAnJywgJ2MnKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVNZXNoID0gcmVxdWlyZSgnZ2wtbWVzaDNkJyk7XG52YXIgdHJpYW5ndWxhdGUgPSByZXF1aXJlKCdkZWxhdW5heS10cmlhbmd1bGF0ZScpO1xudmFyIGFscGhhU2hhcGUgPSByZXF1aXJlKCdhbHBoYS1zaGFwZScpO1xudmFyIGNvbnZleEh1bGwgPSByZXF1aXJlKCdjb252ZXgtaHVsbCcpO1xuXG52YXIgcGFyc2VDb2xvclNjYWxlID0gcmVxdWlyZSgnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLnBhcnNlQ29sb3JTY2FsZTtcbnZhciBzdHIyUmdiYUFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIHppcDMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nbDNkL3ppcDMnKTtcblxuZnVuY3Rpb24gTWVzaDNEVHJhY2Uoc2NlbmUsIG1lc2gsIHVpZCkge1xuICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB0aGlzLnVpZCA9IHVpZDtcbiAgICB0aGlzLm1lc2ggPSBtZXNoO1xuICAgIHRoaXMubmFtZSA9ICcnO1xuICAgIHRoaXMuY29sb3IgPSAnI2ZmZic7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbiAgICB0aGlzLnNob3dDb250b3VyID0gZmFsc2U7XG59XG5cbnZhciBwcm90byA9IE1lc2gzRFRyYWNlLnByb3RvdHlwZTtcblxucHJvdG8uaGFuZGxlUGljayA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICAgIGlmKHNlbGVjdGlvbi5vYmplY3QgPT09IHRoaXMubWVzaCkge1xuICAgICAgICB2YXIgc2VsZWN0SW5kZXggPSBzZWxlY3Rpb24uaW5kZXggPSBzZWxlY3Rpb24uZGF0YS5pbmRleDtcblxuICAgICAgICBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlID0gW1xuICAgICAgICAgICAgdGhpcy5kYXRhLnhbc2VsZWN0SW5kZXhdLFxuICAgICAgICAgICAgdGhpcy5kYXRhLnlbc2VsZWN0SW5kZXhdLFxuICAgICAgICAgICAgdGhpcy5kYXRhLnpbc2VsZWN0SW5kZXhdXG4gICAgICAgIF07XG5cbiAgICAgICAgdmFyIHRleHQgPSB0aGlzLmRhdGEudGV4dDtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0ZXh0KSAmJiB0ZXh0W3NlbGVjdEluZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dFtzZWxlY3RJbmRleF07XG4gICAgICAgIH0gZWxzZSBpZih0ZXh0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3JBcnJheShjb2xvcnMpIHtcbiAgICByZXR1cm4gY29sb3JzLm1hcChzdHIyUmdiYUFycmF5KTtcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHZhciBzY2VuZSA9IHRoaXMuc2NlbmUsXG4gICAgICAgIGxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dDtcblxuICAgIHRoaXMuZGF0YSA9IGRhdGE7XG5cbiAgICAvLyBVbnBhY2sgcG9zaXRpb24gZGF0YVxuICAgIGZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhheGlzLCBjb29yZCwgc2NhbGUsIGNhbGVuZGFyKSB7XG4gICAgICAgIHJldHVybiBjb29yZC5tYXAoZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgcmV0dXJuIGF4aXMuZDJsKHgsIDAsIGNhbGVuZGFyKSAqIHNjYWxlO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcG9zaXRpb25zID0gemlwMyhcbiAgICAgICAgdG9EYXRhQ29vcmRzKGxheW91dC54YXhpcywgZGF0YS54LCBzY2VuZS5kYXRhU2NhbGVbMF0sIGRhdGEueGNhbGVuZGFyKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKGxheW91dC55YXhpcywgZGF0YS55LCBzY2VuZS5kYXRhU2NhbGVbMV0sIGRhdGEueWNhbGVuZGFyKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKGxheW91dC56YXhpcywgZGF0YS56LCBzY2VuZS5kYXRhU2NhbGVbMl0sIGRhdGEuemNhbGVuZGFyKSk7XG5cbiAgICB2YXIgY2VsbHM7XG4gICAgaWYoZGF0YS5pICYmIGRhdGEuaiAmJiBkYXRhLmspIHtcbiAgICAgICAgY2VsbHMgPSB6aXAzKGRhdGEuaSwgZGF0YS5qLCBkYXRhLmspO1xuICAgIH1cbiAgICBlbHNlIGlmKGRhdGEuYWxwaGFodWxsID09PSAwKSB7XG4gICAgICAgIGNlbGxzID0gY29udmV4SHVsbChwb3NpdGlvbnMpO1xuICAgIH1cbiAgICBlbHNlIGlmKGRhdGEuYWxwaGFodWxsID4gMCkge1xuICAgICAgICBjZWxscyA9IGFscGhhU2hhcGUoZGF0YS5hbHBoYWh1bGwsIHBvc2l0aW9ucyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgZCA9IFsneCcsICd5JywgJ3onXS5pbmRleE9mKGRhdGEuZGVsYXVuYXlheGlzKTtcbiAgICAgICAgY2VsbHMgPSB0cmlhbmd1bGF0ZShwb3NpdGlvbnMubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgICAgIHJldHVybiBbY1soZCArIDEpICUgM10sIGNbKGQgKyAyKSAlIDNdXTtcbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIHBvc2l0aW9uczogcG9zaXRpb25zLFxuICAgICAgICBjZWxsczogY2VsbHMsXG4gICAgICAgIGxpZ2h0UG9zaXRpb246IFtkYXRhLmxpZ2h0cG9zaXRpb24ueCwgZGF0YS5saWdodHBvc2l0aW9uLnksIGRhdGEubGlnaHRwb3NpdGlvbi56XSxcbiAgICAgICAgYW1iaWVudDogZGF0YS5saWdodGluZy5hbWJpZW50LFxuICAgICAgICBkaWZmdXNlOiBkYXRhLmxpZ2h0aW5nLmRpZmZ1c2UsXG4gICAgICAgIHNwZWN1bGFyOiBkYXRhLmxpZ2h0aW5nLnNwZWN1bGFyLFxuICAgICAgICByb3VnaG5lc3M6IGRhdGEubGlnaHRpbmcucm91Z2huZXNzLFxuICAgICAgICBmcmVzbmVsOiBkYXRhLmxpZ2h0aW5nLmZyZXNuZWwsXG4gICAgICAgIHZlcnRleE5vcm1hbHNFcHNpbG9uOiBkYXRhLmxpZ2h0aW5nLnZlcnRleG5vcm1hbHNlcHNpbG9uLFxuICAgICAgICBmYWNlTm9ybWFsc0Vwc2lsb246IGRhdGEubGlnaHRpbmcuZmFjZW5vcm1hbHNlcHNpbG9uLFxuICAgICAgICBvcGFjaXR5OiBkYXRhLm9wYWNpdHksXG4gICAgICAgIGNvbnRvdXJFbmFibGU6IGRhdGEuY29udG91ci5zaG93LFxuICAgICAgICBjb250b3VyQ29sb3I6IHN0cjJSZ2JhQXJyYXkoZGF0YS5jb250b3VyLmNvbG9yKS5zbGljZSgwLCAzKSxcbiAgICAgICAgY29udG91cldpZHRoOiBkYXRhLmNvbnRvdXIud2lkdGgsXG4gICAgICAgIHVzZUZhY2V0Tm9ybWFsczogZGF0YS5mbGF0c2hhZGluZ1xuICAgIH07XG5cbiAgICBpZihkYXRhLmludGVuc2l0eSkge1xuICAgICAgICB0aGlzLmNvbG9yID0gJyNmZmYnO1xuICAgICAgICBjb25maWcudmVydGV4SW50ZW5zaXR5ID0gZGF0YS5pbnRlbnNpdHk7XG4gICAgICAgIGNvbmZpZy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHMgPSBbZGF0YS5jbWluLCBkYXRhLmNtYXhdO1xuICAgICAgICBjb25maWcuY29sb3JtYXAgPSBwYXJzZUNvbG9yU2NhbGUoZGF0YS5jb2xvcnNjYWxlKTtcbiAgICB9XG4gICAgZWxzZSBpZihkYXRhLnZlcnRleGNvbG9yKSB7XG4gICAgICAgIHRoaXMuY29sb3IgPSBkYXRhLnZlcnRleGNvbG9yWzBdO1xuICAgICAgICBjb25maWcudmVydGV4Q29sb3JzID0gcGFyc2VDb2xvckFycmF5KGRhdGEudmVydGV4Y29sb3IpO1xuICAgIH1cbiAgICBlbHNlIGlmKGRhdGEuZmFjZWNvbG9yKSB7XG4gICAgICAgIHRoaXMuY29sb3IgPSBkYXRhLmZhY2Vjb2xvclswXTtcbiAgICAgICAgY29uZmlnLmNlbGxDb2xvcnMgPSBwYXJzZUNvbG9yQXJyYXkoZGF0YS5mYWNlY29sb3IpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5jb2xvciA9IGRhdGEuY29sb3I7XG4gICAgICAgIGNvbmZpZy5tZXNoQ29sb3IgPSBzdHIyUmdiYUFycmF5KGRhdGEuY29sb3IpO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBtZXNoXG4gICAgdGhpcy5tZXNoLnVwZGF0ZShjb25maWcpO1xufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLm1lc2gpO1xuICAgIHRoaXMubWVzaC5kaXNwb3NlKCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVNZXNoM0RUcmFjZShzY2VuZSwgZGF0YSkge1xuICAgIHZhciBnbCA9IHNjZW5lLmdscGxvdC5nbDtcbiAgICB2YXIgbWVzaCA9IGNyZWF0ZU1lc2goe2dsOiBnbH0pO1xuICAgIHZhciByZXN1bHQgPSBuZXcgTWVzaDNEVHJhY2Uoc2NlbmUsIG1lc2gsIGRhdGEudWlkKTtcbiAgICBtZXNoLl90cmFjZSA9IHJlc3VsdDtcbiAgICByZXN1bHQudXBkYXRlKGRhdGEpO1xuICAgIHNjZW5lLmdscGxvdC5hZGQobWVzaCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNZXNoM0RUcmFjZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgLy8gcmVhZCBpbiBmYWNlL3ZlcnRleCBwcm9wZXJ0aWVzXG4gICAgZnVuY3Rpb24gcmVhZENvbXBvbmVudHMoYXJyYXkpIHtcbiAgICAgICAgdmFyIHJldCA9IGFycmF5Lm1hcChmdW5jdGlvbihhdHRyKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gY29lcmNlKGF0dHIpO1xuXG4gICAgICAgICAgICBpZihyZXN1bHQgJiYgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkocmVzdWx0KSkgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmV0LmV2ZXJ5KGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgICAgIHJldHVybiB4ICYmIHgubGVuZ3RoID09PSByZXRbMF0ubGVuZ3RoO1xuICAgICAgICB9KSAmJiByZXQ7XG4gICAgfVxuXG4gICAgdmFyIGNvb3JkcyA9IHJlYWRDb21wb25lbnRzKFsneCcsICd5JywgJ3onXSk7XG4gICAgdmFyIGluZGljZXMgPSByZWFkQ29tcG9uZW50cyhbJ2knLCAnaicsICdrJ10pO1xuXG4gICAgaWYoIWNvb3Jkcykge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZihpbmRpY2VzKSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgY29udmVydCBhbGwgZmFjZSBpbmRpY2VzIHRvIGludHNcbiAgICAgICAgaW5kaWNlcy5mb3JFYWNoKGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kZXgubGVuZ3RoOyArK2kpIGluZGV4W2ldIHw9IDA7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5JywgJ3onXSwgbGF5b3V0KTtcblxuICAgIC8vIENvZXJjZSByZW1haW5pbmcgcHJvcGVydGllc1xuICAgIFtcbiAgICAgICAgJ2xpZ2h0aW5nLmFtYmllbnQnLFxuICAgICAgICAnbGlnaHRpbmcuZGlmZnVzZScsXG4gICAgICAgICdsaWdodGluZy5zcGVjdWxhcicsXG4gICAgICAgICdsaWdodGluZy5yb3VnaG5lc3MnLFxuICAgICAgICAnbGlnaHRpbmcuZnJlc25lbCcsXG4gICAgICAgICdsaWdodGluZy52ZXJ0ZXhub3JtYWxzZXBzaWxvbicsXG4gICAgICAgICdsaWdodGluZy5mYWNlbm9ybWFsc2Vwc2lsb24nLFxuICAgICAgICAnbGlnaHRwb3NpdGlvbi54JyxcbiAgICAgICAgJ2xpZ2h0cG9zaXRpb24ueScsXG4gICAgICAgICdsaWdodHBvc2l0aW9uLnonLFxuICAgICAgICAnY29udG91ci5zaG93JyxcbiAgICAgICAgJ2NvbnRvdXIuY29sb3InLFxuICAgICAgICAnY29udG91ci53aWR0aCcsXG4gICAgICAgICdjb2xvcnNjYWxlJyxcbiAgICAgICAgJ3JldmVyc2VzY2FsZScsXG4gICAgICAgICdmbGF0c2hhZGluZycsXG4gICAgICAgICdhbHBoYWh1bGwnLFxuICAgICAgICAnZGVsYXVuYXlheGlzJyxcbiAgICAgICAgJ29wYWNpdHknXG4gICAgXS5mb3JFYWNoKGZ1bmN0aW9uKHgpIHsgY29lcmNlKHgpOyB9KTtcblxuICAgIGlmKCdpbnRlbnNpdHknIGluIHRyYWNlSW4pIHtcbiAgICAgICAgY29lcmNlKCdpbnRlbnNpdHknKTtcbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICdjJ30pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYWNlT3V0LnNob3dzY2FsZSA9IGZhbHNlO1xuXG4gICAgICAgIGlmKCdmYWNlY29sb3InIGluIHRyYWNlSW4pIGNvZXJjZSgnZmFjZWNvbG9yJyk7XG4gICAgICAgIGVsc2UgaWYoJ3ZlcnRleGNvbG9yJyBpbiB0cmFjZUluKSBjb2VyY2UoJ3ZlcnRleGNvbG9yJyk7XG4gICAgICAgIGVsc2UgY29lcmNlKCdjb2xvcicsIGRlZmF1bHRDb2xvcik7XG4gICAgfVxuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG5cbiAgICAvLyBkaXNhYmxlIDFEIHRyYW5zZm9ybXNcbiAgICAvLyB4L3kveiBzaG91bGQgbWF0Y2ggbGVuZ3RocywgYW5kIGkvai9rIHNob3VsZCBtYXRjaCBhcyB3ZWxsLCBidXRcbiAgICAvLyB0aGUgdHdvIHNldHMgaGF2ZSBkaWZmZXJlbnQgbGVuZ3RocyBzbyB0cmFuc2Zvcm1zIHdvdWxkbid0IHdvcmsuXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBNZXNoM0QgPSB7fTtcblxuTWVzaDNELmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbk1lc2gzRC5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcbk1lc2gzRC5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5NZXNoM0QuY29sb3JiYXIgPSB7XG4gICAgbWluOiAnY21pbicsXG4gICAgbWF4OiAnY21heCdcbn07XG5NZXNoM0QucGxvdCA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xuXG5NZXNoM0QubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5NZXNoM0QubmFtZSA9ICdtZXNoM2QnLFxuTWVzaDNELmJhc2VQbG90TW9kdWxlID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2wzZCcpO1xuTWVzaDNELmNhdGVnb3JpZXMgPSBbJ2dsM2QnXTtcbk1lc2gzRC5tZXRhID0ge1xuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNZXNoM0Q7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWInKS5leHRlbmRGbGF0O1xudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGRhc2ggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG52YXIgZnhBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngvYXR0cmlidXRlcycpO1xuXG52YXIgSU5DUkVBU0lOR19DT0xPUiA9ICcjM0Q5OTcwJztcbnZhciBERUNSRUFTSU5HX0NPTE9SID0gJyNGRjQxMzYnO1xuXG52YXIgbGluZUF0dHJzID0gc2NhdHRlckF0dHJzLmxpbmU7XG5cbmZ1bmN0aW9uIGRpcmVjdGlvbkF0dHJzKGxpbmVDb2xvckRlZmF1bHQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgbGluZUF0dHJzLmNvbG9yLCB7ZGZsdDogbGluZUNvbG9yRGVmYXVsdH0pLFxuICAgICAgICAgICAgd2lkdGg6IGxpbmVBdHRycy53aWR0aCxcbiAgICAgICAgICAgIGRhc2g6IGRhc2gsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBvcGVuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGhpZ2g6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbG93OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGNsb3NlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGxpbmU6IHtcbiAgICAgICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIGxpbmVBdHRycy53aWR0aCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBkYXNoOiBleHRlbmRGbGF0KHt9LCBkYXNoLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIGluY3JlYXNpbmc6IGRpcmVjdGlvbkF0dHJzKElOQ1JFQVNJTkdfQ09MT1IpLFxuXG4gICAgZGVjcmVhc2luZzogZGlyZWN0aW9uQXR0cnMoREVDUkVBU0lOR19DT0xPUiksXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0aWNrd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAwLjUsXG4gICAgICAgIGRmbHQ6IDAuMyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBob3ZlcmxhYmVsOiBleHRlbmRGbGF0KHt9LCBmeEF0dHJzLmhvdmVybGFiZWwsIHtcbiAgICAgICAgc3BsaXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSksXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgXyA9IExpYi5fO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbmZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuXG4gICAgdmFyIHRpY2tMZW4gPSBjb252ZXJ0VGlja1dpZHRoKGdkLCB4YSwgdHJhY2UpO1xuICAgIHZhciBtaW5EaWZmID0gdHJhY2UuX21pbkRpZmY7XG4gICAgdHJhY2UuX21pbkRpZmYgPSBudWxsO1xuICAgIHZhciB4ID0gdHJhY2UuX3hjYWxjO1xuICAgIHRyYWNlLl94Y2FsYyA9IG51bGw7XG5cbiAgICB2YXIgY2QgPSBjYWxjQ29tbW9uKGdkLCB0cmFjZSwgeCwgeWEsIHB0RnVuYyk7XG5cbiAgICB0cmFjZS5fZXh0cmVtZXNbeGEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHhhLCB4LCB7dnBhZDogbWluRGlmZiAvIDJ9KTtcbiAgICBpZihjZC5sZW5ndGgpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoY2RbMF0udCwge1xuICAgICAgICAgICAgd0hvdmVyOiBtaW5EaWZmIC8gMixcbiAgICAgICAgICAgIHRpY2tMZW46IHRpY2tMZW5cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW3t0OiB7ZW1wdHk6IHRydWV9fV07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwdEZ1bmMobywgaCwgbCwgYykge1xuICAgIHJldHVybiB7XG4gICAgICAgIG86IG8sXG4gICAgICAgIGg6IGgsXG4gICAgICAgIGw6IGwsXG4gICAgICAgIGM6IGNcbiAgICB9O1xufVxuXG5cbi8vIHNoYXJlZCBiZXR3ZWVuIE9ITEMgYW5kIGNhbmRsZXN0aWNrXG4vLyBwdEZ1bmMgbWFrZXMgYSBjYWxjZGF0YSBwb2ludCBzcGVjaWZpYyB0byBlYWNoIHRyYWNlIHR5cGUsIGZyb20gb2ksIGhpLCBsaSwgY2lcbmZ1bmN0aW9uIGNhbGNDb21tb24oZ2QsIHRyYWNlLCB4LCB5YSwgcHRGdW5jKSB7XG4gICAgdmFyIG8gPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICdvcGVuJyk7XG4gICAgdmFyIGggPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICdoaWdoJyk7XG4gICAgdmFyIGwgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICdsb3cnKTtcbiAgICB2YXIgYyA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ2Nsb3NlJyk7XG5cbiAgICB2YXIgaGFzVGV4dEFycmF5ID0gQXJyYXkuaXNBcnJheSh0cmFjZS50ZXh0KTtcblxuICAgIC8vIHdlJ3JlIG9wdGltaXN0cyAtIGJlZm9yZSB3ZSBoYXZlIGFueSBjaGFuZ2luZyBkYXRhLCBhc3N1bWUgaW5jcmVhc2luZ1xuICAgIHZhciBpbmNyZWFzaW5nID0gdHJ1ZTtcbiAgICB2YXIgY1ByZXYgPSBudWxsO1xuXG4gICAgdmFyIGNkID0gW107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHhpID0geFtpXTtcbiAgICAgICAgdmFyIG9pID0gb1tpXTtcbiAgICAgICAgdmFyIGhpID0gaFtpXTtcbiAgICAgICAgdmFyIGxpID0gbFtpXTtcbiAgICAgICAgdmFyIGNpID0gY1tpXTtcblxuICAgICAgICBpZih4aSAhPT0gQkFETlVNICYmIG9pICE9PSBCQUROVU0gJiYgaGkgIT09IEJBRE5VTSAmJiBsaSAhPT0gQkFETlVNICYmIGNpICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGlmKGNpID09PSBvaSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIG9wZW4gPT0gY2xvc2UsIGxvb2sgZm9yIGEgY2hhbmdlIGZyb20gdGhlIHByZXZpb3VzIGNsb3NlXG4gICAgICAgICAgICAgICAgaWYoY1ByZXYgIT09IG51bGwgJiYgY2kgIT09IGNQcmV2KSBpbmNyZWFzaW5nID0gY2kgPiBjUHJldjtcbiAgICAgICAgICAgICAgICAvLyBlbHNlIChjID09PSBjUHJldiBvciBjUHJldiBpcyBudWxsKSBubyBjaGFuZ2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaW5jcmVhc2luZyA9IGNpID4gb2k7XG5cbiAgICAgICAgICAgIGNQcmV2ID0gY2k7XG5cbiAgICAgICAgICAgIHZhciBwdCA9IHB0RnVuYyhvaSwgaGksIGxpLCBjaSk7XG5cbiAgICAgICAgICAgIHB0LnBvcyA9IHhpO1xuICAgICAgICAgICAgcHQueWMgPSAob2kgKyBjaSkgLyAyO1xuICAgICAgICAgICAgcHQuaSA9IGk7XG4gICAgICAgICAgICBwdC5kaXIgPSBpbmNyZWFzaW5nID8gJ2luY3JlYXNpbmcnIDogJ2RlY3JlYXNpbmcnO1xuXG4gICAgICAgICAgICBpZihoYXNUZXh0QXJyYXkpIHB0LnR4ID0gdHJhY2UudGV4dFtpXTtcblxuICAgICAgICAgICAgY2QucHVzaChwdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0cmFjZS5fZXh0cmVtZXNbeWEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHlhLCBsLmNvbmNhdChoKSwge3BhZGRlZDogdHJ1ZX0pO1xuXG4gICAgaWYoY2QubGVuZ3RoKSB7XG4gICAgICAgIGNkWzBdLnQgPSB7XG4gICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICBvcGVuOiBfKGdkLCAnb3BlbjonKSArICcgJyxcbiAgICAgICAgICAgICAgICBoaWdoOiBfKGdkLCAnaGlnaDonKSArICcgJyxcbiAgICAgICAgICAgICAgICBsb3c6IF8oZ2QsICdsb3c6JykgKyAnICcsXG4gICAgICAgICAgICAgICAgY2xvc2U6IF8oZ2QsICdjbG9zZTonKSArICcgJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBjZDtcbn1cblxuLypcbiAqIGZpbmQgbWluIHgtY29vcmRpbmF0ZXMgZGlmZmVyZW5jZSBvZiBhbGwgdHJhY2VzXG4gKiBhdHRhY2hlZCB0byB0aGlzIHgtYXhpcyBhbmQgc3Rhc2ggdGhlIHJlc3VsdCBpbiBfbWluRGlmZlxuICogaW4gYWxsIHRyYWNlczsgd2hlbiBhIHRyYWNlIHVzZXMgdGhpcyBpbiBpdHNcbiAqIGNhbGMgc3RlcCBpdCBkZWxldGVzIF9taW5EaWZmLCBzbyB0aGF0IG5leHQgY2FsYyB0aGlzIGlzXG4gKiBkb25lIGFnYWluIGluIGNhc2UgdGhlIGRhdGEgY2hhbmdlZC5cbiAqIGFsc28gc2luY2Ugd2UgbmVlZCBpdCBoZXJlLCBzdGFzaCBfeGNhbGMgb24gdGhlIHRyYWNlXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUaWNrV2lkdGgoZ2QsIHhhLCB0cmFjZSkge1xuICAgIHZhciBtaW5EaWZmID0gdHJhY2UuX21pbkRpZmY7XG5cbiAgICBpZighbWluRGlmZikge1xuICAgICAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGEsXG4gICAgICAgICAgICBvaGxjVHJhY2VzT25UaGlzWGF4aXMgPSBbXTtcblxuICAgICAgICBtaW5EaWZmID0gSW5maW5pdHk7XG5cbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZWkgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICAgICAgaWYodHJhY2VpLnR5cGUgPT09ICdvaGxjJyAmJlxuICAgICAgICAgICAgICAgIHRyYWNlaS52aXNpYmxlID09PSB0cnVlICYmXG4gICAgICAgICAgICAgICAgdHJhY2VpLnhheGlzID09PSB4YS5faWRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIG9obGNUcmFjZXNPblRoaXNYYXhpcy5wdXNoKHRyYWNlaSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgeGNhbGMgPSB4YS5tYWtlQ2FsY2RhdGEodHJhY2VpLCAneCcpO1xuICAgICAgICAgICAgICAgIHRyYWNlaS5feGNhbGMgPSB4Y2FsYztcblxuICAgICAgICAgICAgICAgIHZhciBfbWluRGlmZiA9IExpYi5kaXN0aW5jdFZhbHMoeGNhbGMpLm1pbkRpZmY7XG4gICAgICAgICAgICAgICAgaWYoX21pbkRpZmYgJiYgaXNGaW5pdGUoX21pbkRpZmYpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkRpZmYgPSBNYXRoLm1pbihtaW5EaWZmLCBfbWluRGlmZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgbWluRGlmZiBpcyBzdGlsbCBJbmZpbml0eSBoZXJlLCBzZXQgaXQgdG8gMVxuICAgICAgICBpZihtaW5EaWZmID09PSBJbmZpbml0eSkgbWluRGlmZiA9IDE7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb2hsY1RyYWNlc09uVGhpc1hheGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBvaGxjVHJhY2VzT25UaGlzWGF4aXNbaV0uX21pbkRpZmYgPSBtaW5EaWZmO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pbkRpZmYgKiB0cmFjZS50aWNrd2lkdGg7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhbGM6IGNhbGMsXG4gICAgY2FsY0NvbW1vbjogY2FsY0NvbW1vblxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgaGFuZGxlT0hMQyA9IHJlcXVpcmUoJy4vb2hsY19kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZU9ITEModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnbGluZS5kYXNoJyk7XG5cbiAgICBoYW5kbGVEaXJlY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgJ2luY3JlYXNpbmcnKTtcbiAgICBoYW5kbGVEaXJlY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgJ2RlY3JlYXNpbmcnKTtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgndGlja3dpZHRoJyk7XG5cbiAgICBsYXlvdXQuX3JlcXVlc3RSYW5nZXNsaWRlclt0cmFjZU91dC54YXhpc10gPSB0cnVlO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlRGlyZWN0aW9uKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRpcmVjdGlvbikge1xuICAgIGNvZXJjZShkaXJlY3Rpb24gKyAnLmxpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5saW5lLndpZHRoJywgdHJhY2VPdXQubGluZS53aWR0aCk7XG4gICAgY29lcmNlKGRpcmVjdGlvbiArICcubGluZS5kYXNoJywgdHJhY2VPdXQubGluZS5kYXNoKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGZpbGxIb3ZlclRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dCcpO1xuXG52YXIgRElSU1lNQk9MID0ge1xuICAgIGluY3JlYXNpbmc6ICfilrInLFxuICAgIGRlY3JlYXNpbmc6ICfilrwnXG59O1xuXG5mdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgIGlmKHRyYWNlLmhvdmVybGFiZWwuc3BsaXQpIHtcbiAgICAgICAgcmV0dXJuIGhvdmVyU3BsaXQocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIH1cblxuICAgIHJldHVybiBob3Zlck9uUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2xvc2VzdFBvaW50KHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgdCA9IGNkWzBdLnQ7XG5cbiAgICB2YXIgdHlwZSA9IHRyYWNlLnR5cGU7XG4gICAgdmFyIG1pbkF0dHIgPSB0eXBlID09PSAnb2hsYycgPyAnbCcgOiAnbWluJztcbiAgICB2YXIgbWF4QXR0ciA9IHR5cGUgPT09ICdvaGxjJyA/ICdoJyA6ICdtYXgnO1xuXG4gICAgdmFyIGhvdmVyUHNldWRvRGlzdGFuY2UsIHNwaWtlUHNldWRvRGlzdGFuY2U7XG5cbiAgICAvLyBwb3RlbnRpYWxseSBzaGlmdCB4dmFsIGZvciBncm91cGVkIGNhbmRsZXN0aWNrc1xuICAgIHZhciBjZW50ZXJTaGlmdCA9IHQuYlBvcyB8fCAwO1xuICAgIHZhciBzaGlmdFBvcyA9IGZ1bmN0aW9uKGRpKSB7IHJldHVybiBkaS5wb3MgKyBjZW50ZXJTaGlmdCAtIHh2YWw7IH07XG5cbiAgICAvLyBvaGxjIGFuZCBjYW5kbGVzdGljayBjYWxsIGRpc3BsYXlIYWxmV2lkdGggZGlmZmVyZW50IHRoaW5ncy4uLlxuICAgIHZhciBkaXNwbGF5SGFsZldpZHRoID0gdC5iZFBvcyB8fCB0LnRpY2tMZW47XG4gICAgdmFyIGhvdmVySGFsZldpZHRoID0gdC53SG92ZXI7XG5cbiAgICAvLyBpZiB0d28gZmlndXJlcyBhcmUgb3ZlcmxheWluZywgbGV0IHRoZSBuYXJyb3dlc3Qgb25lIHdpblxuICAgIHZhciBwc2V1ZG9EaXN0YW5jZSA9IE1hdGgubWluKDEsIGRpc3BsYXlIYWxmV2lkdGggLyBNYXRoLmFicyh4YS5yMmMoeGEucmFuZ2VbMV0pIC0geGEucjJjKHhhLnJhbmdlWzBdKSkpO1xuICAgIGhvdmVyUHNldWRvRGlzdGFuY2UgPSBwb2ludERhdGEubWF4SG92ZXJEaXN0YW5jZSAtIHBzZXVkb0Rpc3RhbmNlO1xuICAgIHNwaWtlUHNldWRvRGlzdGFuY2UgPSBwb2ludERhdGEubWF4U3Bpa2VEaXN0YW5jZSAtIHBzZXVkb0Rpc3RhbmNlO1xuXG4gICAgZnVuY3Rpb24gZHgoZGkpIHtcbiAgICAgICAgdmFyIHBvcyA9IHNoaWZ0UG9zKGRpKTtcbiAgICAgICAgcmV0dXJuIEZ4LmluYm94KHBvcyAtIGhvdmVySGFsZldpZHRoLCBwb3MgKyBob3ZlckhhbGZXaWR0aCwgaG92ZXJQc2V1ZG9EaXN0YW5jZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHkoZGkpIHtcbiAgICAgICAgcmV0dXJuIEZ4LmluYm94KGRpW21pbkF0dHJdIC0geXZhbCwgZGlbbWF4QXR0cl0gLSB5dmFsLCBob3ZlclBzZXVkb0Rpc3RhbmNlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkeHkoZGkpIHsgcmV0dXJuIChkeChkaSkgKyBkeShkaSkpIC8gMjsgfVxuXG4gICAgdmFyIGRpc3RmbiA9IEZ4LmdldERpc3RhbmNlRnVuY3Rpb24oaG92ZXJtb2RlLCBkeCwgZHksIGR4eSk7XG4gICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdGZuLCBwb2ludERhdGEpO1xuXG4gICAgaWYocG9pbnREYXRhLmluZGV4ID09PSBmYWxzZSkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciBkaXIgPSBkaS5kaXI7XG4gICAgdmFyIGNvbnRhaW5lciA9IHRyYWNlW2Rpcl07XG4gICAgdmFyIGxjID0gY29udGFpbmVyLmxpbmUuY29sb3I7XG5cbiAgICBpZihDb2xvci5vcGFjaXR5KGxjKSAmJiBjb250YWluZXIubGluZS53aWR0aCkgcG9pbnREYXRhLmNvbG9yID0gbGM7XG4gICAgZWxzZSBwb2ludERhdGEuY29sb3IgPSBjb250YWluZXIuZmlsbGNvbG9yO1xuXG4gICAgcG9pbnREYXRhLngwID0geGEuYzJwKGRpLnBvcyArIGNlbnRlclNoaWZ0IC0gZGlzcGxheUhhbGZXaWR0aCwgdHJ1ZSk7XG4gICAgcG9pbnREYXRhLngxID0geGEuYzJwKGRpLnBvcyArIGNlbnRlclNoaWZ0ICsgZGlzcGxheUhhbGZXaWR0aCwgdHJ1ZSk7XG5cbiAgICBwb2ludERhdGEueExhYmVsVmFsID0gZGkucG9zO1xuXG4gICAgcG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSBkeHkoZGkpICogc3Bpa2VQc2V1ZG9EaXN0YW5jZSAvIGhvdmVyUHNldWRvRGlzdGFuY2U7XG4gICAgcG9pbnREYXRhLnhTcGlrZSA9IHhhLmMycChkaS5wb3MsIHRydWUpO1xuXG4gICAgcmV0dXJuIHBvaW50RGF0YTtcbn1cblxuZnVuY3Rpb24gaG92ZXJTcGxpdChwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHQgPSBjZFswXS50O1xuICAgIHZhciBjbG9zZUJveERhdGEgPSBbXTtcblxuICAgIHZhciBjbG9zZXN0UG9pbnQgPSBnZXRDbG9zZXN0UG9pbnQocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgaWYoIWNsb3Nlc3RQb2ludCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIGNkSW5kZXggPSBjbG9zZXN0UG9pbnQuaW5kZXg7XG4gICAgdmFyIGRpID0gY2RbY2RJbmRleF07XG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgaG92ZXJQYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgIHZhciBpc0FsbCA9IGhvdmVyaW5mbyA9PT0gJ2FsbCc7XG4gICAgdmFyIGhhc1kgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3knKSAhPT0gLTE7XG5cbiAgICAvLyBzaW1pbGFyIHRvIGhvdmVyT25Qb2ludHMsIHdlIHJldHVybiBub3RoaW5nXG4gICAgLy8gaWYgYWxsIG9yIHkgaXMgbm90IHByZXNlbnQuXG4gICAgaWYoIWhhc1kpIHJldHVybiBbXTtcblxuICAgIHZhciBhdHRycyA9IFsnaGlnaCcsICdvcGVuJywgJ2Nsb3NlJywgJ2xvdyddO1xuXG4gICAgLy8gc2V2ZXJhbCBhdHRyaWJ1dGVzIGNhbiBoYXZlIHRoZSBzYW1lIHktY29vcmRpbmF0ZS4gV2Ugd2lsbFxuICAgIC8vIGJ1bmNoIHRoZW0gdG9nZXRoZXIgaW4gYSBzaW5nbGUgdGV4dCBibG9jay4gRm9yIHRoaXMsIHdlIGtlZXBcbiAgICAvLyBhIGRpY3Rpb25hcnkgbWFwcGluZyB5LWNvb3JkIC0+IHBvaW50IGRhdGEuXG4gICAgdmFyIHVzZWRWYWxzID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1tpXTtcblxuICAgICAgICB2YXIgdmFsID0gdHJhY2VbYXR0cl1bY2xvc2VzdFBvaW50LmluZGV4XTtcbiAgICAgICAgdmFyIHZhbFB4ID0geWEuYzJwKHZhbCwgdHJ1ZSk7XG4gICAgICAgIHZhciBwb2ludERhdGEyO1xuICAgICAgICBpZih2YWwgaW4gdXNlZFZhbHMpIHtcbiAgICAgICAgICAgIHBvaW50RGF0YTIgPSB1c2VkVmFsc1t2YWxdO1xuICAgICAgICAgICAgcG9pbnREYXRhMi55TGFiZWwgKz0gJzxicj4nICsgdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB2YWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gY29weSBvdXQgdG8gYSBuZXcgb2JqZWN0IGZvciBlYWNoIG5ldyB5LXZhbHVlIHRvIGxhYmVsXG4gICAgICAgICAgICBwb2ludERhdGEyID0gTGliLmV4dGVuZEZsYXQoe30sIGNsb3Nlc3RQb2ludCk7XG5cbiAgICAgICAgICAgIHBvaW50RGF0YTIueTAgPSBwb2ludERhdGEyLnkxID0gdmFsUHg7XG4gICAgICAgICAgICBwb2ludERhdGEyLnlMYWJlbFZhbCA9IHZhbDtcbiAgICAgICAgICAgIHBvaW50RGF0YTIueUxhYmVsID0gdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB2YWwpO1xuXG4gICAgICAgICAgICBwb2ludERhdGEyLm5hbWUgPSAnJztcblxuICAgICAgICAgICAgY2xvc2VCb3hEYXRhLnB1c2gocG9pbnREYXRhMik7XG4gICAgICAgICAgICB1c2VkVmFsc1t2YWxdID0gcG9pbnREYXRhMjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjbG9zZUJveERhdGE7XG59XG5cbmZ1bmN0aW9uIGhvdmVyT25Qb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB0ID0gY2RbMF0udDtcblxuICAgIHZhciBjbG9zZXN0UG9pbnQgPSBnZXRDbG9zZXN0UG9pbnQocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgaWYoIWNsb3Nlc3RQb2ludCkgcmV0dXJuIFtdO1xuXG4gICAgLy8gd2UgZG9uJ3QgbWFrZSBhIGNhbGNkYXRhIHBvaW50IGlmIHdlJ3JlIG1pc3NpbmcgYW55IHBpZWNlICh4L28vaC9sL2MpXG4gICAgLy8gc28gd2UgbmVlZCB0byBmaXggdGhlIGluZGV4IGhlcmUgdG8gcG9pbnQgdG8gdGhlIGRhdGEgYXJyYXlzXG4gICAgdmFyIGNkSW5kZXggPSBjbG9zZXN0UG9pbnQuaW5kZXg7XG4gICAgdmFyIGRpID0gY2RbY2RJbmRleF07XG4gICAgdmFyIGkgPSBjbG9zZXN0UG9pbnQuaW5kZXggPSBkaS5pO1xuICAgIHZhciBkaXIgPSBkaS5kaXI7XG5cbiAgICBmdW5jdGlvbiBnZXRMYWJlbExpbmUoYXR0cikge1xuICAgICAgICByZXR1cm4gdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB0cmFjZVthdHRyXVtpXSk7XG4gICAgfVxuXG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgaG92ZXJQYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgIHZhciBpc0FsbCA9IGhvdmVyaW5mbyA9PT0gJ2FsbCc7XG4gICAgdmFyIGhhc1kgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3knKSAhPT0gLTE7XG4gICAgdmFyIGhhc1RleHQgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTE7XG5cbiAgICB2YXIgdGV4dFBhcnRzID0gaGFzWSA/IFtcbiAgICAgICAgZ2V0TGFiZWxMaW5lKCdvcGVuJyksXG4gICAgICAgIGdldExhYmVsTGluZSgnaGlnaCcpLFxuICAgICAgICBnZXRMYWJlbExpbmUoJ2xvdycpLFxuICAgICAgICBnZXRMYWJlbExpbmUoJ2Nsb3NlJykgKyAnICAnICsgRElSU1lNQk9MW2Rpcl1cbiAgICBdIDogW107XG4gICAgaWYoaGFzVGV4dCkgZmlsbEhvdmVyVGV4dChkaSwgdHJhY2UsIHRleHRQYXJ0cyk7XG5cbiAgICAvLyBkb24ndCBtYWtlIC55TGFiZWxWYWwgb3IgLnRleHQsIHNpbmNlIHdlJ3JlIG1hbmFnaW5nIGhvdmVyaW5mb1xuICAgIC8vIHB1dCBpdCBhbGwgaW4gLmV4dHJhVGV4dFxuICAgIGNsb3Nlc3RQb2ludC5leHRyYVRleHQgPSB0ZXh0UGFydHMuam9pbignPGJyPicpO1xuXG4gICAgLy8gdGhpcyBwdXRzIHRoZSBsYWJlbCAqYW5kIHRoZSBzcGlrZSogYXQgdGhlIG1pZHBvaW50IG9mIHRoZSBib3gsIGllXG4gICAgLy8gaGFsZndheSBiZXR3ZWVuIG9wZW4gYW5kIGNsb3NlLCBub3QgYmV0d2VlbiBoaWdoIGFuZCBsb3cuXG4gICAgY2xvc2VzdFBvaW50LnkwID0gY2xvc2VzdFBvaW50LnkxID0geWEuYzJwKGRpLnljLCB0cnVlKTtcblxuICAgIHJldHVybiBbY2xvc2VzdFBvaW50XTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIGhvdmVyU3BsaXQ6IGhvdmVyU3BsaXQsXG4gICAgaG92ZXJPblBvaW50czogaG92ZXJPblBvaW50c1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnb2hsYycsXG4gICAgYmFzZVBsb3RNb2R1bGU6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnY2FydGVzaWFuJywgJ3N2ZycsICdzaG93TGVnZW5kJ10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9LFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBjYWxjOiByZXF1aXJlKCcuL2NhbGMnKS5jYWxjLFxuICAgIHBsb3Q6IHJlcXVpcmUoJy4vcGxvdCcpLFxuICAgIHN0eWxlOiByZXF1aXJlKCcuL3N0eWxlJyksXG4gICAgaG92ZXJQb2ludHM6IHJlcXVpcmUoJy4vaG92ZXInKS5ob3ZlclBvaW50cyxcbiAgICBzZWxlY3RQb2ludHM6IHJlcXVpcmUoJy4vc2VsZWN0Jylcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZU9ITEModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KSB7XG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICB2YXIgb3BlbiA9IGNvZXJjZSgnb3BlbicpO1xuICAgIHZhciBoaWdoID0gY29lcmNlKCdoaWdoJyk7XG4gICAgdmFyIGxvdyA9IGNvZXJjZSgnbG93Jyk7XG4gICAgdmFyIGNsb3NlID0gY29lcmNlKCdjbG9zZScpO1xuXG4gICAgY29lcmNlKCdob3ZlcmxhYmVsLnNwbGl0Jyk7XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbJ3gnXSwgbGF5b3V0KTtcblxuICAgIGlmKCEob3BlbiAmJiBoaWdoICYmIGxvdyAmJiBjbG9zZSkpIHJldHVybjtcblxuICAgIHZhciBsZW4gPSBNYXRoLm1pbihvcGVuLmxlbmd0aCwgaGlnaC5sZW5ndGgsIGxvdy5sZW5ndGgsIGNsb3NlLmxlbmd0aCk7XG5cbiAgICBpZih4KSBsZW4gPSBNYXRoLm1pbihsZW4sIHgubGVuZ3RoKTtcblxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG5cbiAgICByZXR1cm4gbGVuO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZE9ITEMsIG9obGNMYXllcikge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3VwcyhvaGxjTGF5ZXIsIGNkT0hMQywgJ3RyYWNlIG9obGMnKS5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgIHZhciBwbG90R3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgdmFyIHQgPSBjZDAudDtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgICAgICBpZighcGxvdGluZm8uaXNSYW5nZVBsb3QpIGNkMC5ub2RlMyA9IHBsb3RHcm91cDtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IHQuZW1wdHkpIHtcbiAgICAgICAgICAgIHBsb3RHcm91cC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0aWNrTGVuID0gdC50aWNrTGVuO1xuXG4gICAgICAgIHZhciBwYXRocyA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ3BhdGgnKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcblxuICAgICAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgcGF0aHMuYXR0cignZCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB4ID0geGEuYzJwKGQucG9zLCB0cnVlKTtcbiAgICAgICAgICAgIHZhciB4byA9IHhhLmMycChkLnBvcyAtIHRpY2tMZW4sIHRydWUpO1xuICAgICAgICAgICAgdmFyIHhjID0geGEuYzJwKGQucG9zICsgdGlja0xlbiwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIHZhciB5byA9IHlhLmMycChkLm8sIHRydWUpO1xuICAgICAgICAgICAgdmFyIHloID0geWEuYzJwKGQuaCwgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgeWwgPSB5YS5jMnAoZC5sLCB0cnVlKTtcbiAgICAgICAgICAgIHZhciB5YyA9IHlhLmMycChkLmMsIHRydWUpO1xuXG4gICAgICAgICAgICByZXR1cm4gJ00nICsgeG8gKyAnLCcgKyB5byArICdIJyArIHggK1xuICAgICAgICAgICAgICAgICdNJyArIHggKyAnLCcgKyB5aCArICdWJyArIHlsICtcbiAgICAgICAgICAgICAgICAnTScgKyB4YyArICcsJyArIHljICsgJ0gnICsgeDtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGk7XG4gICAgLy8gZm9yIChwb3RlbnRpYWxseSBncm91cGVkKSBjYW5kbGVzdGlja3NcbiAgICB2YXIgcG9zT2Zmc2V0ID0gY2RbMF0udC5iUG9zIHx8IDA7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuXG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3hhLmMycChkaS5wb3MgKyBwb3NPZmZzZXQpLCB5YS5jMnAoZGkueWMpXSwgbnVsbCwgZGkuaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyOiBkaS5pLFxuICAgICAgICAgICAgICAgICAgICB4OiB4YS5jMmQoZGkucG9zKSxcbiAgICAgICAgICAgICAgICAgICAgeTogeWEuYzJkKGRpLnljKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKGdkLCBjZCkge1xuICAgIHZhciBzID0gY2QgPyBjZFswXS5ub2RlMyA6IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLm9obGNsYXllcicpLnNlbGVjdEFsbCgnZy50cmFjZScpO1xuXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGRbMF0udHJhY2Uub3BhY2l0eTtcbiAgICB9KTtcblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG5cbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgncGF0aCcpLmVhY2goZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHZhciBkaXJMaW5lID0gdHJhY2VbZGkuZGlyXS5saW5lO1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgZGlyTGluZS5jb2xvcilcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCBkaXJMaW5lLmRhc2gsIGRpckxpbmUud2lkdGgpXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogY3VzdG9tIHNlbGVjdGlvbiBzdHlsZSBmb3IgT0hMQ1xuICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIHRyYWNlLnNlbGVjdGVkcG9pbnRzICYmICFkaS5zZWxlY3RlZCA/IDAuMyA6IDEpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgcGxvdEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgZG9tYWluQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG5cbnZhciBsaW5lID0gZXh0ZW5kRmxhdCh7XG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSwgY29sb3JBdHRyaWJ1dGVzKCdsaW5lJywge2VkaXRUeXBlOiAnY2FsYyd9KSxcbiAgICB7XG4gICAgICAgIHNob3dzY2FsZTogc2NhdHRlckxpbmVBdHRycy5zaG93c2NhbGUsXG4gICAgICAgIGNvbG9yYmFyOiBjb2xvcmJhckF0dHJzLFxuICAgICAgICBzaGFwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xpbmVhcicsICdoc3BsaW5lJ10sXG4gICAgICAgICAgICBkZmx0OiAnbGluZWFyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdwYXJjYXRzJywgdHJhY2U6IHRydWUsIGVkaXRUeXBlOiAnY2FsYyd9KSxcbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnY291bnQnLCAncHJvYmFiaWxpdHknXSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgYXJyYXlPazogZmFsc2VcbiAgICAgICAgLy8gcGxvdEF0dHJzLmhvdmVyaW5mbyBkZXNjcmlwdGlvbiBpcyBhcHByb3ByaWF0ZVxuICAgIH0pLFxuICAgIGhvdmVyb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnY2F0ZWdvcnknLCAnY29sb3InLCAnZGltZW5zaW9uJ10sXG4gICAgICAgIGRmbHQ6ICdjYXRlZ29yeScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycmFuZ2VtZW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3BlcnBlbmRpY3VsYXInLCAnZnJlZWZvcm0nLCAnZml4ZWQnXSxcbiAgICAgICAgZGZsdDogJ3BlcnBlbmRpY3VsYXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBidW5kbGVjb2xvcnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzb3J0cGF0aHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZm9yd2FyZCcsICdiYWNrd2FyZCddLFxuICAgICAgICBkZmx0OiAnZm9yd2FyZCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVsZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICB0aWNrZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBkaW1lbnNpb25zOiB7XG4gICAgICAgIF9pc0xpbmtlZFRvQXJyYXk6ICdkaW1lbnNpb24nLFxuICAgICAgICBsYWJlbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY2F0ZWdvcnlvcmRlcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAgICAgJ3RyYWNlJywgJ2NhdGVnb3J5IGFzY2VuZGluZycsICdjYXRlZ29yeSBkZXNjZW5kaW5nJywgJ2FycmF5J1xuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGRmbHQ6ICd0cmFjZScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY2F0ZWdvcnlhcnJheToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpY2t0ZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdmFsdWVzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkaXNwbGF5aW5kZXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxpbmU6IGxpbmUsXG4gICAgY291bnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgLy8gSGlkZSB1bnN1cHBvcnRlZCB0b3AtbGV2ZWwgcHJvcGVydGllcyBmcm9tIHBsb3Qtc2NoZW1hXG4gICAgY3VzdG9tZGF0YTogdW5kZWZpbmVkLFxuICAgIGhvdmVybGFiZWw6IHVuZGVmaW5lZCxcbiAgICBpZHM6IHVuZGVmaW5lZCxcbiAgICBsZWdlbmRncm91cDogdW5kZWZpbmVkLFxuICAgIG9wYWNpdHk6IHVuZGVmaW5lZCxcbiAgICBzZWxlY3RlZHBvaW50czogdW5kZWZpbmVkLFxuICAgIHNob3dsZWdlbmQ6IHVuZGVmaW5lZFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcbnZhciBwYXJjYXRzUGxvdCA9IHJlcXVpcmUoJy4vcGxvdCcpO1xuXG52YXIgUEFSQ0FUUyA9ICdwYXJjYXRzJztcbmV4cG9ydHMubmFtZSA9IFBBUkNBVFM7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkLCB0cmFjZXMsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG5cbiAgICB2YXIgY2RNb2R1bGVBbmRPdGhlcnMgPSBnZXRNb2R1bGVDYWxjRGF0YShnZC5jYWxjZGF0YSwgUEFSQ0FUUyk7XG5cbiAgICBpZihjZE1vZHVsZUFuZE90aGVycy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGNhbGNEYXRhID0gY2RNb2R1bGVBbmRPdGhlcnNbMF07XG4gICAgICAgIHBhcmNhdHNQbG90KGdkLCBjYWxjRGF0YSwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkVGFibGUgPSAob2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcygncGFyY2F0cycpKTtcbiAgICB2YXIgaGFzVGFibGUgPSAobmV3RnVsbExheW91dC5faGFzICYmIG5ld0Z1bGxMYXlvdXQuX2hhcygncGFyY2F0cycpKTtcblxuICAgIGlmKGhhZFRhYmxlICYmICFoYXNUYWJsZSkge1xuICAgICAgICBvbGRGdWxsTGF5b3V0Ll9wYXBlcmRpdi5zZWxlY3RBbGwoJy5wYXJjYXRzJykucmVtb3ZlKCk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gUmVxdWlyZW1lbnRzXG4vLyA9PT09PT09PT09PT1cbnZhciB3cmFwID0gcmVxdWlyZSgnLi4vLi4vbGliL2d1cCcpLndyYXA7XG52YXIgaGFzQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oYXNfY29sb3JzY2FsZScpO1xudmFyIGNvbG9yc2NhbGVDYWxjID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcbnZhciBmaWx0ZXJVbmlxdWUgPSByZXF1aXJlKCcuLi8uLi9saWIvZmlsdGVyX3VuaXF1ZS5qcycpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLyoqXG4gKiBDcmVhdGUgYSB3cmFwcGVkIFBhcmNhdHNNb2RlbCBvYmplY3QgZnJvbSB0cmFjZVxuICpcbiAqIE5vdGU6IHRyYWNlIGRlZmF1bHRzIGhhdmUgYWxyZWFkeSBiZWVuIGFwcGxpZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBnZFxuICogQHBhcmFtIHtPYmplY3R9IHRyYWNlXG4gKiBAcmV0dXJuIHtBcnJheS48UGFyY2F0c01vZGVsPn1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciB2aXNpYmxlRGltcyA9IExpYi5maWx0ZXJWaXNpYmxlKHRyYWNlLmRpbWVuc2lvbnMpO1xuXG4gICAgaWYodmlzaWJsZURpbXMubGVuZ3RoID09PSAwKSByZXR1cm4gW107XG5cbiAgICB2YXIgdW5pcXVlSW5mb0RpbXMgPSB2aXNpYmxlRGltcy5tYXAoZnVuY3Rpb24oZGltKSB7XG4gICAgICAgIHZhciBjYXRlZ29yeVZhbHVlcztcbiAgICAgICAgaWYoZGltLmNhdGVnb3J5b3JkZXIgPT09ICd0cmFjZScpIHtcbiAgICAgICAgICAgIC8vIFVzZSBvcmRlciBvZiBmaXJzdCBvY2N1cnJlbmNlIGluIHRyYWNlXG4gICAgICAgICAgICBjYXRlZ29yeVZhbHVlcyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZihkaW0uY2F0ZWdvcnlvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgLy8gVXNlIGNhdGVnb3JpZXMgc3BlY2lmaWVkIGluIGBjYXRlZ29yeWFycmF5YCBmaXJzdCxcbiAgICAgICAgICAgIC8vIHRoZW4gYWRkIGV4dHJhIHRvIHRoZSBlbmQgaW4gdHJhY2Ugb3JkZXJcbiAgICAgICAgICAgIGNhdGVnb3J5VmFsdWVzID0gZGltLmNhdGVnb3J5YXJyYXk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBHZXQgYWxsIGNhdGVnb3JpZXMgdXAgZnJvbnQgc28gd2UgY2FuIG9yZGVyIHRoZW1cbiAgICAgICAgICAgIC8vIFNob3VsZCB3ZSBjaGVjayBmb3IgbnVtYmVycyBhcyBzb3J0IG51bWVyaWNhbGx5P1xuICAgICAgICAgICAgY2F0ZWdvcnlWYWx1ZXMgPSBmaWx0ZXJVbmlxdWUoZGltLnZhbHVlcykuc29ydCgpO1xuICAgICAgICAgICAgaWYoZGltLmNhdGVnb3J5b3JkZXIgPT09ICdjYXRlZ29yeSBkZXNjZW5kaW5nJykge1xuICAgICAgICAgICAgICAgIGNhdGVnb3J5VmFsdWVzID0gY2F0ZWdvcnlWYWx1ZXMucmV2ZXJzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnZXRVbmlxdWVJbmZvKGRpbS52YWx1ZXMsIGNhdGVnb3J5VmFsdWVzKTtcbiAgICB9KTtcblxuICAgIHZhciBjb3VudHMsXG4gICAgICAgIGNvdW50LFxuICAgICAgICB0b3RhbENvdW50O1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlLmNvdW50cykpIHtcbiAgICAgICAgY291bnRzID0gdHJhY2UuY291bnRzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvdW50cyA9IFt0cmFjZS5jb3VudHNdO1xuICAgIH1cblxuICAgIHZhbGlkYXRlRGltZW5zaW9uRGlzcGxheUluZHModmlzaWJsZURpbXMpO1xuXG4gICAgdmlzaWJsZURpbXMuZm9yRWFjaChmdW5jdGlvbihkaW0sIGRpbUluZCkge1xuICAgICAgICB2YWxpZGF0ZUNhdGVnb3J5UHJvcGVydGllcyhkaW0sIHVuaXF1ZUluZm9EaW1zW2RpbUluZF0pO1xuICAgIH0pO1xuXG4gICAgLy8gSGFuZGxlIHBhdGggY29sb3JzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIGxpbmUgPSB0cmFjZS5saW5lO1xuICAgIHZhciBtYXJrZXJDb2xvcnNjYWxlO1xuXG4gICAgLy8gUHJvY2VzcyBjb2xvcnNjYWxlXG4gICAgaWYobGluZSkge1xuICAgICAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbGluZScpKSB7XG4gICAgICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UubGluZS5jb2xvciwgJ2xpbmUnLCAnYycpO1xuICAgICAgICB9XG4gICAgICAgIG1hcmtlckNvbG9yc2NhbGUgPSBEcmF3aW5nLnRyeUNvbG9yc2NhbGUobGluZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFya2VyQ29sb3JzY2FsZSA9IExpYi5pZGVudGl0eTtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCBjb2xvciBnZW5lcmF0aW9uIGZ1bmN0aW9uXG4gICAgZnVuY3Rpb24gZ2V0TWFya2VyQ29sb3JJbmZvKGluZGV4KSB7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobGluZS5jb2xvcikpIHtcbiAgICAgICAgICAgIHZhbHVlID0gbGluZS5jb2xvcltpbmRleCAlIGxpbmUuY29sb3IubGVuZ3RoXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gbGluZS5jb2xvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7Y29sb3I6IG1hcmtlckNvbG9yc2NhbGUodmFsdWUpLCByYXdDb2xvcjogdmFsdWV9O1xuICAgIH1cblxuICAgIC8vIE51bWJlciBvZiB2YWx1ZXMgYW5kIGNvdW50c1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciBudW1WYWx1ZXMgPSB2aXNpYmxlRGltc1swXS52YWx1ZXMubGVuZ3RoO1xuXG4gICAgLy8gQnVpbGQgcGF0aCBpbmZvXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gTWFwcGluZyBmcm9tIGNhdGVnb3J5IGluZHMgdG8gUGF0aE1vZGVsIG9iamVjdHNcbiAgICB2YXIgcGF0aE1vZGVscyA9IHt9O1xuXG4gICAgLy8gQ2F0ZWdvcnkgaW5kcyBhcnJheSBmb3IgZWFjaCBkaW1lbnNpb25cbiAgICB2YXIgY2F0ZWdvcnlJbmRzRGltcyA9IHVuaXF1ZUluZm9EaW1zLm1hcChmdW5jdGlvbihkaSkge3JldHVybiBkaS5pbmRzO30pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0b3RhbCBjb3VudFxuICAgIHRvdGFsQ291bnQgPSAwO1xuICAgIHZhciB2YWx1ZUluZDtcbiAgICB2YXIgZDtcblxuICAgIGZvcih2YWx1ZUluZCA9IDA7IHZhbHVlSW5kIDwgbnVtVmFsdWVzOyB2YWx1ZUluZCsrKSB7XG5cbiAgICAgICAgLy8gQ2F0ZWdvcnkgaW5kcyBmb3IgdGhpcyBpbnB1dCB2YWx1ZSBhY3Jvc3MgZGltZW5zaW9uc1xuICAgICAgICB2YXIgY2F0ZWdvcnlJbmRzUGF0aCA9IFtdO1xuICAgICAgICBmb3IoZCA9IDA7IGQgPCBjYXRlZ29yeUluZHNEaW1zLmxlbmd0aDsgZCsrKSB7XG4gICAgICAgICAgICBjYXRlZ29yeUluZHNQYXRoLnB1c2goY2F0ZWdvcnlJbmRzRGltc1tkXVt2YWx1ZUluZF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ291bnRcbiAgICAgICAgY291bnQgPSBjb3VudHNbdmFsdWVJbmQgJSBjb3VudHMubGVuZ3RoXTtcblxuICAgICAgICAvLyBVcGRhdGUgdG90YWwgY291bnRcbiAgICAgICAgdG90YWxDb3VudCArPSBjb3VudDtcblxuICAgICAgICAvLyBQYXRoIGNvbG9yXG4gICAgICAgIHZhciBwYXRoQ29sb3JJbmZvID0gZ2V0TWFya2VyQ29sb3JJbmZvKHZhbHVlSW5kKTtcblxuICAgICAgICAvLyBwYXRoIGtleVxuICAgICAgICB2YXIgcGF0aEtleSA9IGNhdGVnb3J5SW5kc1BhdGggKyAnLScgKyBwYXRoQ29sb3JJbmZvLnJhd0NvbG9yO1xuXG4gICAgICAgIC8vIENyZWF0ZSAvIFVwZGF0ZSBQYXRoTW9kZWxcbiAgICAgICAgaWYocGF0aE1vZGVsc1twYXRoS2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBwYXRoTW9kZWxzW3BhdGhLZXldID0gY3JlYXRlUGF0aE1vZGVsKGNhdGVnb3J5SW5kc1BhdGgsXG4gICAgICAgICAgICAgICAgcGF0aENvbG9ySW5mby5jb2xvcixcbiAgICAgICAgICAgICAgICBwYXRoQ29sb3JJbmZvLnJhd0NvbG9yKTtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVQYXRoTW9kZWwocGF0aE1vZGVsc1twYXRoS2V5XSwgdmFsdWVJbmQsIGNvdW50KTtcbiAgICB9XG5cbiAgICB2YXIgZGltZW5zaW9uTW9kZWxzID0gdmlzaWJsZURpbXMubWFwKGZ1bmN0aW9uKGRpLCBpKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEaW1lbnNpb25Nb2RlbChpLCBkaS5faW5kZXgsIGRpLl9kaXNwbGF5aW5kZXgsIGRpLmxhYmVsLCB0b3RhbENvdW50KTtcbiAgICB9KTtcblxuXG4gICAgZm9yKHZhbHVlSW5kID0gMDsgdmFsdWVJbmQgPCBudW1WYWx1ZXM7IHZhbHVlSW5kKyspIHtcblxuICAgICAgICBjb3VudCA9IGNvdW50c1t2YWx1ZUluZCAlIGNvdW50cy5sZW5ndGhdO1xuXG4gICAgICAgIGZvcihkID0gMDsgZCA8IGRpbWVuc2lvbk1vZGVscy5sZW5ndGg7IGQrKykge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lckluZCA9IGRpbWVuc2lvbk1vZGVsc1tkXS5jb250YWluZXJJbmQ7XG4gICAgICAgICAgICB2YXIgY2F0SW5kID0gdW5pcXVlSW5mb0RpbXNbZF0uaW5kc1t2YWx1ZUluZF07XG4gICAgICAgICAgICB2YXIgY2F0cyA9IGRpbWVuc2lvbk1vZGVsc1tkXS5jYXRlZ29yaWVzO1xuXG4gICAgICAgICAgICBpZihjYXRzW2NhdEluZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZhciBjYXRWYWx1ZSA9IHRyYWNlLmRpbWVuc2lvbnNbY29udGFpbmVySW5kXS5fY2F0ZWdvcnlhcnJheVtjYXRJbmRdO1xuICAgICAgICAgICAgICAgIHZhciBjYXRMYWJlbCA9IHRyYWNlLmRpbWVuc2lvbnNbY29udGFpbmVySW5kXS5fdGlja3RleHRbY2F0SW5kXTtcbiAgICAgICAgICAgICAgICBjYXRzW2NhdEluZF0gPSBjcmVhdGVDYXRlZ29yeU1vZGVsKGQsIGNhdEluZCwgY2F0VmFsdWUsIGNhdExhYmVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdXBkYXRlQ2F0ZWdvcnlNb2RlbChjYXRzW2NhdEluZF0sIHZhbHVlSW5kLCBjb3VudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIHVuaXF1ZVxuICAgIHJldHVybiB3cmFwKGNyZWF0ZVBhcmNhdHNNb2RlbChkaW1lbnNpb25Nb2RlbHMsIHBhdGhNb2RlbHMsIHRvdGFsQ291bnQpKTtcbn07XG5cbi8vIE1vZGVsc1xuLy8gPT09PT09XG5cbi8vIFBhcmNhdHMgTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS1cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGFyY2F0c01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBpbmZvcm1hdGlvbiBhYm91dCBhIHBhcmNhdHMgdHJhY2VcbiAqXG4gKiBAcHJvcGVydHkge0FycmF5LjxEaW1lbnNpb25Nb2RlbD59IGRpbWVuc2lvbnNcbiAqICBBcnJheSBvZiBkaW1lbnNpb24gbW9kZWxzXG4gKiBAcHJvcGVydHkge09iamVjdC48c3RyaW5nLFBhdGhNb2RlbD59IHBhdGhzXG4gKiAgRGljdGlvbmFyeSBmcm9tIGNhdGVnb3J5IGluZHMgc3RyaW5nIChlLmcuIFwiMSwyLDEsMVwiKSB0byBwYXRoIG1vZGVsXG4gKiBAcHJvcGVydHkge051bWJlcn0gbWF4Q2F0c1xuICogIFRoZSBtYXhpbXVtIG51bWJlciBvZiBjYXRlZ29yaWVzIG9mIGFueSBkaW1lbnNpb24gaW4gdGhlIGRpYWdyYW1cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRvdGFsIG51bWJlciBvZiBpbnB1dCB2YWx1ZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB0cmFjZVxuICovXG5cbi8qKlxuICogQ3JlYXRlIGFuZCBuZXcgUGFyY2F0c01vZGVsIG9iamVjdFxuICogQHBhcmFtIHtBcnJheS48RGltZW5zaW9uTW9kZWw+fSBkaW1lbnNpb25zXG4gKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLFBhdGhNb2RlbD59IHBhdGhzXG4gKiBAcGFyYW0ge051bWJlcn0gY291bnRcbiAqIEByZXR1cm4ge1BhcmNhdHNNb2RlbH1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlUGFyY2F0c01vZGVsKGRpbWVuc2lvbnMsIHBhdGhzLCBjb3VudCkge1xuICAgIHZhciBtYXhDYXRzID0gZGltZW5zaW9uc1xuICAgICAgICAubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jYXRlZ29yaWVzLmxlbmd0aDt9KVxuICAgICAgICAucmVkdWNlKGZ1bmN0aW9uKHYxLCB2Mikge3JldHVybiBNYXRoLm1heCh2MSwgdjIpO30pO1xuICAgIHJldHVybiB7ZGltZW5zaW9uczogZGltZW5zaW9ucywgcGF0aHM6IHBhdGhzLCB0cmFjZTogdW5kZWZpbmVkLCBtYXhDYXRzOiBtYXhDYXRzLCBjb3VudDogY291bnR9O1xufVxuXG4vLyBEaW1lbnNpb24gTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS0tLVxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEaW1lbnNpb25Nb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgaW5mb3JtYXRpb24gYWJvdXQgYSBzaW5nbGUgZGltZW5zaW9uXG4gKlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGRpbWVuc2lvbkluZFxuICogIFRoZSBpbmRleCBvZiB0aGlzIGRpbWVuc2lvbiBhbW9uZyB0aGUgKnZpc2libGUqIGRpbWVuc2lvbnNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb250YWluZXJJbmRcbiAqICBUaGUgaW5kZXggb2YgdGhpcyBkaW1lbnNpb24gaW4gdGhlIG9yaWdpbmFsIGRpbWVuc2lvbnMgY29udGFpbmVyLFxuICogIGlycmVzcGVjdGl2ZSBvZiBkaW1lbnNpb24gdmlzaWJpbGl0eVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGRpc3BsYXlJbmRcbiAqICBUaGUgZGlzcGxheSBpbmRleCBvZiB0aGlzIGRpbWVuc2lvbiAod2hlcmUgMCBpcyB0aGUgbGVmdCBtb3N0IGRpbWVuc2lvbilcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkaW1lbnNpb25MYWJlbFxuICogIFRoZSBsYWJlbCBvZiB0aGlzIGRpbWVuc2lvblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNvdW50XG4gKiAgVG90YWwgbnVtYmVyIG9mIGlucHV0IHZhbHVlc1xuICogQHByb3BlcnR5IHtBcnJheS48Q2F0ZWdvcnlNb2RlbD59IGNhdGVnb3JpZXNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfG51bGx9IGRyYWdYXG4gKiAgVGhlIHggcG9zaXRpb24gb2YgZGltZW5zaW9uIHRoYXQgaXMgY3VycmVudGx5IGJlaW5nIGRyYWdnZWQuIG51bGwgaWYgbm90IGJlaW5nIGRyYWdnZWRcbiAqL1xuXG4vKipcbiAqIENyZWF0ZSBhbmQgbmV3IERpbWVuc2lvbk1vZGVsIG9iamVjdCB3aXRoIGFuIGVtcHR5IGNhdGVnb3JpZXMgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaW1lbnNpb25JbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb250YWluZXJJbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXNwbGF5SW5kXG4gKiBAcGFyYW0ge1N0cmluZ30gZGltZW5zaW9uTGFiZWxcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudFxuICogIFRvdGFsIG51bWJlciBvZiBpbnB1dCB2YWx1ZXNcbiAqIEByZXR1cm4ge0RpbWVuc2lvbk1vZGVsfVxuICovXG5mdW5jdGlvbiBjcmVhdGVEaW1lbnNpb25Nb2RlbChkaW1lbnNpb25JbmQsIGNvbnRhaW5lckluZCwgZGlzcGxheUluZCwgZGltZW5zaW9uTGFiZWwsIGNvdW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGltZW5zaW9uSW5kOiBkaW1lbnNpb25JbmQsXG4gICAgICAgIGNvbnRhaW5lckluZDogY29udGFpbmVySW5kLFxuICAgICAgICBkaXNwbGF5SW5kOiBkaXNwbGF5SW5kLFxuICAgICAgICBkaW1lbnNpb25MYWJlbDogZGltZW5zaW9uTGFiZWwsXG4gICAgICAgIGNvdW50OiBjb3VudCxcbiAgICAgICAgY2F0ZWdvcmllczogW10sXG4gICAgICAgIGRyYWdYOiBudWxsXG4gICAgfTtcbn1cblxuLy8gQ2F0ZWdvcnkgTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS0tXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENhdGVnb3J5TW9kZWxcbiAqICBPYmplY3QgY29udGFpbmluZyBjYWxjdWxhdGVkIGluZm9ybWF0aW9uIGFib3V0IGEgc2luZ2xlIGNhdGVnb3J5LlxuICpcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBkaW1lbnNpb25JbmRcbiAqICBUaGUgaW5kZXggb2YgdGhpcyBjYXRlZ29yaWVzIGRpbWVuc2lvblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNhdGVnb3J5SW5kXG4gKiAgVGhlIGluZGV4IG9mIHRoaXMgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBkaXNwbGF5SW5kXG4gKiAgVGhlIGRpc3BsYXkgaW5kZXggb2YgdGhpcyBjYXRlZ29yeSAod2hlcmUgMCBpcyB0aGUgdG9wbW9zdCBjYXRlZ29yeSlcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjYXRlZ29yeUxhYmVsXG4gKiAgVGhlIG5hbWUgb2YgdGhpcyBjYXRlZ29yeVxuICogQHByb3BlcnR5IGNhdGVnb3J5VmFsdWU6IFJhdyB2YWx1ZSBvZiB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHZhbHVlSW5kc1xuICogIEFycmF5IG9mIGluZGljZXMgKGludG8gdGhlIG9yaWdpbmFsIHZhbHVlIGFycmF5KSBvZiBhbGwgc2FtcGxlcyBpbiB0aGlzIGNhdGVnb3J5XG4gKiBAcHJvcGVydHkge051bWJlcn0gY291bnRcbiAqICBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIGZyb20gdGhlIG9yaWdpbmFsIGFycmF5IGluIHRoaXMgcGF0aFxuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ1lcbiAqICBUaGUgeSBwb3NpdGlvbiBvZiBjYXRlZ29yeSB0aGF0IGlzIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiBudWxsIGlmIG5vdCBiZWluZyBkcmFnZ2VkXG4gKi9cblxuLyoqXG4gKiBDcmVhdGUgYW5kIHJldHVybiBhIG5ldyBDYXRlZ29yeU1vZGVsIG9iamVjdFxuICogQHBhcmFtIHtOdW1iZXJ9IGRpbWVuc2lvbkluZFxuICogQHBhcmFtIHtOdW1iZXJ9IGNhdGVnb3J5SW5kXG4gKiAgVGhlIGRpc3BsYXkgaW5kZXggb2YgdGhpcyBjYXRlZ29yeSAod2hlcmUgMCBpcyB0aGUgdG9wbW9zdCBjYXRlZ29yeSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBjYXRlZ29yeVZhbHVlXG4gKiBAcGFyYW0ge1N0cmluZ30gY2F0ZWdvcnlMYWJlbFxuICogQHJldHVybiB7Q2F0ZWdvcnlNb2RlbH1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlQ2F0ZWdvcnlNb2RlbChkaW1lbnNpb25JbmQsIGNhdGVnb3J5SW5kLCBjYXRlZ29yeVZhbHVlLCBjYXRlZ29yeUxhYmVsKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGltZW5zaW9uSW5kOiBkaW1lbnNpb25JbmQsXG4gICAgICAgIGNhdGVnb3J5SW5kOiBjYXRlZ29yeUluZCxcbiAgICAgICAgY2F0ZWdvcnlWYWx1ZTogY2F0ZWdvcnlWYWx1ZSxcbiAgICAgICAgZGlzcGxheUluZDogY2F0ZWdvcnlJbmQsXG4gICAgICAgIGNhdGVnb3J5TGFiZWw6IGNhdGVnb3J5TGFiZWwsXG4gICAgICAgIHZhbHVlSW5kczogW10sXG4gICAgICAgIGNvdW50OiAwLFxuICAgICAgICBkcmFnWTogbnVsbFxuICAgIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGEgQ2F0ZWdvcnlNb2RlbCBvYmplY3Qgd2l0aCBhIG5ldyB2YWx1ZSBpbmRleFxuICogTm90ZTogVGhlIGNhbGxpbmcgcGFyYW1ldGVyIGlzIG1vZGlmaWVkIGluIHBsYWNlLlxuICpcbiAqIEBwYXJhbSB7Q2F0ZWdvcnlNb2RlbH0gY2F0ZWdvcnlNb2RlbFxuICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlSW5kXG4gKiBAcGFyYW0ge051bWJlcn0gY291bnRcbiAqL1xuZnVuY3Rpb24gdXBkYXRlQ2F0ZWdvcnlNb2RlbChjYXRlZ29yeU1vZGVsLCB2YWx1ZUluZCwgY291bnQpIHtcbiAgICBjYXRlZ29yeU1vZGVsLnZhbHVlSW5kcy5wdXNoKHZhbHVlSW5kKTtcbiAgICBjYXRlZ29yeU1vZGVsLmNvdW50ICs9IGNvdW50O1xufVxuXG5cbi8vIFBhdGggTW9kZWxcbi8vIC0tLS0tLS0tLS1cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGF0aE1vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc2FtcGxlcyBpbiBhIHBhdGguXG4gKlxuICogQHByb3BlcnR5IHtBcnJheX0gY2F0ZWdvcnlJbmRzXG4gKiAgQXJyYXkgb2YgY2F0ZWdvcnkgaW5kaWNlcyBmb3IgZWFjaCBkaW1lbnNpb24gKGxlbmd0aCBgbnVtRGltZW5zaW9uc2ApXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aENvbG9yXG4gKiAgQ29sb3Igb2YgdGhpcyBwYXRoLiAoTm90ZTogQW55IGNvbG9yc2NhbGluZyBoYXMgYWxyZWFkeSB0YWtlbiBwbGFjZSlcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHZhbHVlSW5kc1xuICogIEFycmF5IG9mIGluZGljZXMgKGludG8gdGhlIG9yaWdpbmFsIHZhbHVlIGFycmF5KSBvZiBhbGwgc2FtcGxlcyBpbiB0aGlzIHBhdGhcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgZnJvbSB0aGUgb3JpZ2luYWwgYXJyYXkgaW4gdGhpcyBwYXRoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sb3JcbiAqICBUaGUgcGF0aCdzIGNvbG9yIChhc3MgQ1NTIGNvbG9yIHN0cmluZylcbiAqIEBwcm9wZXJ0eSByYXdDb2xvclxuICogIFRoZSByYXcgY29sb3IgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZSB1c2VyLiBNYXkgYmUgYSBDU1MgY29sb3Igc3RyaW5nIG9yIGEgTnVtYmVyXG4gKi9cblxuLyoqXG4gKiBDcmVhdGUgYW5kIHJldHVybiBhIG5ldyBQYXRoTW9kZWwgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5fSBjYXRlZ29yeUluZHNcbiAqIEBwYXJhbSBjb2xvclxuICogQHBhcmFtIHJhd0NvbG9yXG4gKiBAcmV0dXJuIHtQYXRoTW9kZWx9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBhdGhNb2RlbChjYXRlZ29yeUluZHMsIGNvbG9yLCByYXdDb2xvcikge1xuICAgIHJldHVybiB7XG4gICAgICAgIGNhdGVnb3J5SW5kczogY2F0ZWdvcnlJbmRzLFxuICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgIHJhd0NvbG9yOiByYXdDb2xvcixcbiAgICAgICAgdmFsdWVJbmRzOiBbXSxcbiAgICAgICAgY291bnQ6IDBcbiAgICB9O1xufVxuXG4vKipcbiAqIFVwZGF0ZSBhIFBhdGhNb2RlbCBvYmplY3Qgd2l0aCBhIG5ldyB2YWx1ZSBpbmRleFxuICogTm90ZTogVGhlIGNhbGxpbmcgcGFyYW1ldGVyIGlzIG1vZGlmaWVkIGluIHBsYWNlLlxuICpcbiAqIEBwYXJhbSB7UGF0aE1vZGVsfSBwYXRoTW9kZWxcbiAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZUluZFxuICogQHBhcmFtIHtOdW1iZXJ9IGNvdW50XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVBhdGhNb2RlbChwYXRoTW9kZWwsIHZhbHVlSW5kLCBjb3VudCkge1xuICAgIHBhdGhNb2RlbC52YWx1ZUluZHMucHVzaCh2YWx1ZUluZCk7XG4gICAgcGF0aE1vZGVsLmNvdW50ICs9IGNvdW50O1xufVxuXG4vLyBVbmlxdWUgY2FsY3VsYXRpb25zXG4vLyA9PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFVuaXF1ZUluZm9cbiAqICBPYmplY3QgY29udGFpbmluZyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdW5pcXVlIHZhbHVlcyBvZiBhbiBpbnB1dCBhcnJheVxuICpcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHVuaXF1ZVZhbHVlc1xuICogIFRoZSB1bmlxdWUgdmFsdWVzIGluIHRoZSBpbnB1dCBhcnJheVxuICogQHByb3BlcnR5IHtBcnJheX0gdW5pcXVlQ291bnRzXG4gKiAgVGhlIG51bWJlciBvZiB0aW1lcyBlYWNoIGVudHJ5IGluIHVuaXF1ZVZhbHVlcyBvY2N1cnMgaW4gaW5wdXQgYXJyYXkuXG4gKiAgVGhpcyBoYXMgdGhlIHNhbWUgbGVuZ3RoIGFzIGB1bmlxdWVWYWx1ZXNgXG4gKiBAcHJvcGVydHkge0FycmF5fSBpbmRzXG4gKiAgSW5kaWNlcyBpbnRvIHVuaXF1ZVZhbHVlcyB0aGF0IHdvdWxkIHJlcHJvZHVjZSBvcmlnaW5hbCBpbnB1dCBhcnJheVxuICovXG5cbi8qKlxuICogQ29tcHV0ZSB1bmlxdWUgdmFsdWUgaW5mb3JtYXRpb24gZm9yIGFuIGFycmF5XG4gKlxuICogSU1QT1JUQU5UOiBOb3RlIHRoYXQgdmFsdWVzIGFyZSBjb25zaWRlcmVkIHVuaXF1ZVxuICogaWYgdGhlaXIgc3RyaW5nIHJlcHJlc2VudGF0aW9ucyBhcmUgdW5pcXVlLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlc1xuICogQHBhcmFtIHtBcnJheXx1bmRlZmluZWR9IHVuaXF1ZVZhbHVlc1xuICogIEFycmF5IG9mIGV4cGVjdGVkIHVuaXF1ZSB2YWx1ZXMuIFRoZSB1bmlxdWVWYWx1ZXMgcHJvcGVydHkgb2YgdGhlIHJlc3VsdGluZyBVbmlxdWVJbmZvIG9iamVjdCB3aWxsIGJlZ2luIHdpdGhcbiAqICB0aGVzZSBlbnRyaWVzLiBFbnRyaWVzIGFyZSBpbmNsdWRlZCBldmVuIGlmIHRoZXJlIGFyZSB6ZXJvIG9jY3VycmVuY2VzIGluIHRoZSB2YWx1ZXMgYXJyYXkuIEVudHJpZXMgZm91bmQgaW5cbiAqICB0aGUgdmFsdWVzIGFycmF5IHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIHVuaXF1ZVZhbHVlcyB3aWxsIGJlIGluY2x1ZGVkIGF0IHRoZSBlbmQgb2YgdGhlIGFycmF5IGluIHRoZVxuICogIFVuaXF1ZUluZm8gb2JqZWN0LlxuICogQHJldHVybiB7VW5pcXVlSW5mb31cbiAqL1xuZnVuY3Rpb24gZ2V0VW5pcXVlSW5mbyh2YWx1ZXMsIHVuaXF1ZVZhbHVlcykge1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB1bmlxdWVWYWx1ZXMgaWYgbm90IHNwZWNpZmllZFxuICAgIGlmKHVuaXF1ZVZhbHVlcyA9PT0gdW5kZWZpbmVkIHx8IHVuaXF1ZVZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgICB1bmlxdWVWYWx1ZXMgPSBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBTaGFsbG93IGNvcHkgc28gYXBwZW5kIGJlbG93IGRvZXNuJ3QgYWx0ZXIgaW5wdXQgYXJyYXlcbiAgICAgICAgdW5pcXVlVmFsdWVzID0gdW5pcXVlVmFsdWVzLm1hcChmdW5jdGlvbihlKSB7cmV0dXJuIGU7fSk7XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBWYXJpYWJsZXNcbiAgICB2YXIgdW5pcXVlVmFsdWVDb3VudHMgPSB7fSxcbiAgICAgICAgdW5pcXVlVmFsdWVJbmRzID0ge30sXG4gICAgICAgIGluZHMgPSBbXTtcblxuICAgIC8vIEluaXRpYWxpemUgdW5pcXVlVmFsdWVDb3VudHMgYW5kXG4gICAgdW5pcXVlVmFsdWVzLmZvckVhY2goZnVuY3Rpb24odW5pcXVlVmFsLCB2YWxJbmQpIHtcbiAgICAgICAgdW5pcXVlVmFsdWVDb3VudHNbdW5pcXVlVmFsXSA9IDA7XG4gICAgICAgIHVuaXF1ZVZhbHVlSW5kc1t1bmlxdWVWYWxdID0gdmFsSW5kO1xuICAgIH0pO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgbmVjZXNzYXJ5IHVuaXF1ZSBpbmZvIGluIGEgc2luZ2xlIHBhc3NcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gdmFsdWVzW2ldO1xuICAgICAgICB2YXIgaXRlbUluZDtcblxuICAgICAgICBpZih1bmlxdWVWYWx1ZUNvdW50c1tpdGVtXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGl0ZW0gaGFzIGEgcHJldmlvdXNseSB1bnNlZW4gdmFsdWVcbiAgICAgICAgICAgIHVuaXF1ZVZhbHVlQ291bnRzW2l0ZW1dID0gMTtcbiAgICAgICAgICAgIGl0ZW1JbmQgPSB1bmlxdWVWYWx1ZXMucHVzaChpdGVtKSAtIDE7XG4gICAgICAgICAgICB1bmlxdWVWYWx1ZUluZHNbaXRlbV0gPSBpdGVtSW5kO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSW5jcmVtZW50IGNvdW50IGZvciB0aGlzIGl0ZW1cbiAgICAgICAgICAgIHVuaXF1ZVZhbHVlQ291bnRzW2l0ZW1dKys7XG4gICAgICAgICAgICBpdGVtSW5kID0gdW5pcXVlVmFsdWVJbmRzW2l0ZW1dO1xuICAgICAgICB9XG4gICAgICAgIGluZHMucHVzaChpdGVtSW5kKTtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCBVbmlxdWVJbmZvXG4gICAgdmFyIHVuaXF1ZUNvdW50cyA9IHVuaXF1ZVZhbHVlcy5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gdW5pcXVlVmFsdWVDb3VudHNbdl07IH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdW5pcXVlVmFsdWVzOiB1bmlxdWVWYWx1ZXMsXG4gICAgICAgIHVuaXF1ZUNvdW50czogdW5pcXVlQ291bnRzLFxuICAgICAgICBpbmRzOiBpbmRzXG4gICAgfTtcbn1cblxuXG4vKipcbiAqIFZhbGlkYXRlIHRoZSByZXF1ZXN0ZWQgZGlzcGxheSBvcmRlciBmb3IgdGhlIGRpbWVuc2lvbnMuXG4gKiBJZiB0aGUgZGlzcGxheSBvcmRlciBpcyBhIHBlcm11dGF0aW9uIG9mIDAgdGhyb3VnaCBkaW1lbnNpb25zLmxlbmd0aCAtIDEsIGxpbmsgdG8gX2Rpc3BsYXlpbmRleFxuICogT3RoZXJ3aXNlLCByZXBsYWNlIHRoZSBkaXNwbGF5IG9yZGVyIHdpdGggdGhlIGRpbWVuc2lvbiBvcmRlclxuICogQHBhcmFtIHtPYmplY3R9IHRyYWNlXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlRGltZW5zaW9uRGlzcGxheUluZHModmlzaWJsZURpbXMpIHtcbiAgICB2YXIgZGlzcGxheUluZHMgPSB2aXNpYmxlRGltcy5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5kaXNwbGF5aW5kZXg7IH0pO1xuICAgIHZhciBpO1xuXG4gICAgaWYoaXNSYW5nZVBlcm11dGF0aW9uKGRpc3BsYXlJbmRzKSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB2aXNpYmxlRGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmlzaWJsZURpbXNbaV0uX2Rpc3BsYXlpbmRleCA9IHZpc2libGVEaW1zW2ldLmRpc3BsYXlpbmRleDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHZpc2libGVEaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2aXNpYmxlRGltc1tpXS5fZGlzcGxheWluZGV4ID0gaTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG4vKipcbiAqIFVwZGF0ZSBjYXRlZ29yeSBwcm9wZXJ0aWVzIGJhc2VkIG9uIHRoZSB1bmlxdWUgdmFsdWVzIGZvdW5kIGZvciB0aGlzIGRpbWVuc2lvblxuICogQHBhcmFtIHtPYmplY3R9IGRpbVxuICogQHBhcmFtIHtVbmlxdWVJbmZvfSB1bmlxdWVJbmZvRGltXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlQ2F0ZWdvcnlQcm9wZXJ0aWVzKGRpbSwgdW5pcXVlSW5mb0RpbSkge1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5YXJyYXlcbiAgICBkaW0uX2NhdGVnb3J5YXJyYXkgPSB1bmlxdWVJbmZvRGltLnVuaXF1ZVZhbHVlcztcblxuICAgIC8vIEhhbmRsZSB0aWNrdGV4dFxuICAgIGlmKGRpbS50aWNrdGV4dCA9PT0gbnVsbCB8fCBkaW0udGlja3RleHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkaW0uX3RpY2t0ZXh0ID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gU2hhbGxvdyBjb3B5IHRvIGF2b2lkIG1vZGlmeWluZyBpbnB1dCBhcnJheVxuICAgICAgICBkaW0uX3RpY2t0ZXh0ID0gZGltLnRpY2t0ZXh0LnNsaWNlKCk7XG4gICAgfVxuXG4gICAgLy8gRXh0ZW5kIHRpY2t0ZXh0IHdpdGggZWxlbWVudHMgZnJvbSB1bmlxdWVJbmZvRGltLnVuaXF1ZVZhbHVlc1xuICAgIGZvcih2YXIgaSA9IGRpbS5fdGlja3RleHQubGVuZ3RoOyBpIDwgdW5pcXVlSW5mb0RpbS51bmlxdWVWYWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGltLl90aWNrdGV4dC5wdXNoKHVuaXF1ZUluZm9EaW0udW5pcXVlVmFsdWVzW2ldKTtcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgYW4gYXJyYXkgY29udGFpbnMgYSBwZXJtdXRhdGlvbiBvZiB0aGUgaW50ZWdlcnMgZnJvbSAwIHRvIHRoZSBhcnJheSdzIGxlbmd0aCAtIDFcbiAqIEBwYXJhbSB7QXJyYXl9IGluZHNcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzUmFuZ2VQZXJtdXRhdGlvbihpbmRzKSB7XG4gICAgdmFyIGluZHNTcGVjaWZpZWQgPSBuZXcgQXJyYXkoaW5kcy5sZW5ndGgpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGluZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgLy8gQ2hlY2sgZm9yIG91dCBvZiBib3VuZHNcbiAgICAgICAgaWYoaW5kc1tpXSA8IDAgfHwgaW5kc1tpXSA+PSBpbmRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yIGNvbGxpc2lvbnMgd2l0aCBhbHJlYWR5IHNwZWNpZmllZCBpbmRleFxuICAgICAgICBpZihpbmRzU3BlY2lmaWVkW2luZHNbaV1dICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluZHNTcGVjaWZpZWRbaW5kc1tpXV0gPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIE5vdGhpbmcgb3V0IG9mIGJvdW5kcyBhbmQgbm8gY29sbGlzaW9ucy4gV2UgaGF2ZSBhIHBlcm11dGF0aW9uXG4gICAgcmV0dXJuIHRydWU7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hhc19jb2xvcnNjYWxlJyk7XG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgbWVyZ2VMZW5ndGggPSByZXF1aXJlKCcuLi9wYXJjb29yZHMvbWVyZ2VfbGVuZ3RoJyk7XG5cbmZ1bmN0aW9uIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSkge1xuXG4gICAgY29lcmNlKCdsaW5lLnNoYXBlJyk7XG4gICAgdmFyIGxpbmVDb2xvciA9IGNvZXJjZSgnbGluZS5jb2xvcicsIGxheW91dC5jb2xvcndheVswXSk7XG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbGluZScpICYmIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGxpbmVDb2xvcikpIHtcbiAgICAgICAgaWYobGluZUNvbG9yLmxlbmd0aCkge1xuICAgICAgICAgICAgY29lcmNlKCdsaW5lLmNvbG9yc2NhbGUnKTtcbiAgICAgICAgICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdsaW5lLicsIGNMZXR0ZXI6ICdjJ30pO1xuICAgICAgICAgICAgcmV0dXJuIGxpbmVDb2xvci5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0cmFjZU91dC5saW5lLmNvbG9yID0gZGVmYXVsdENvbG9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJbmZpbml0eTtcbn1cblxuZnVuY3Rpb24gZGltZW5zaW9uRGVmYXVsdHMoZGltZW5zaW9uSW4sIGRpbWVuc2lvbk91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGRpbWVuc2lvbkluLCBkaW1lbnNpb25PdXQsIGF0dHJpYnV0ZXMuZGltZW5zaW9ucywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlcyA9IGNvZXJjZSgndmFsdWVzJyk7XG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICBpZighKHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKSkge1xuICAgICAgICB2aXNpYmxlID0gZGltZW5zaW9uT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgIC8vIERpbWVuc2lvbiBsZXZlbFxuICAgICAgICBjb2VyY2UoJ2xhYmVsJyk7XG4gICAgICAgIGNvZXJjZSgnZGlzcGxheWluZGV4JywgZGltZW5zaW9uT3V0Ll9pbmRleCk7XG5cbiAgICAgICAgLy8gQ2F0ZWdvcnkgbGV2ZWxcbiAgICAgICAgdmFyIGFycmF5SW4gPSBkaW1lbnNpb25Jbi5jYXRlZ29yeWFycmF5O1xuICAgICAgICB2YXIgaXNWYWxpZEFycmF5ID0gKEFycmF5LmlzQXJyYXkoYXJyYXlJbikgJiYgYXJyYXlJbi5sZW5ndGggPiAwKTtcblxuICAgICAgICB2YXIgb3JkZXJEZWZhdWx0O1xuICAgICAgICBpZihpc1ZhbGlkQXJyYXkpIG9yZGVyRGVmYXVsdCA9ICdhcnJheSc7XG4gICAgICAgIHZhciBvcmRlciA9IGNvZXJjZSgnY2F0ZWdvcnlvcmRlcicsIG9yZGVyRGVmYXVsdCk7XG5cbiAgICAgICAgLy8gY29lcmNlICdjYXRlZ29yeWFycmF5JyBvbmx5IGluIGFycmF5IG9yZGVyIGNhc2VcbiAgICAgICAgaWYob3JkZXIgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnY2F0ZWdvcnlhcnJheScpO1xuICAgICAgICAgICAgY29lcmNlKCd0aWNrdGV4dCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIGRpbWVuc2lvbkluLmNhdGVnb3J5YXJyYXk7XG4gICAgICAgICAgICBkZWxldGUgZGltZW5zaW9uSW4udGlja3RleHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjYW5ub3Qgc2V0ICdjYXRlZ29yeW9yZGVyJyB0byAnYXJyYXknIHdpdGggYW4gaW52YWxpZCAnY2F0ZWdvcnlhcnJheSdcbiAgICAgICAgaWYoIWlzVmFsaWRBcnJheSAmJiBvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgZGltZW5zaW9uT3V0LmNhdGVnb3J5b3JkZXIgPSAndHJhY2UnO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb25zID0gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwge1xuICAgICAgICBuYW1lOiAnZGltZW5zaW9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogZGltZW5zaW9uRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIHZhciBsZW4gPSBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgaGFuZGxlRG9tYWluRGVmYXVsdHModHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGRpbWVuc2lvbnMpIHx8ICFkaW1lbnNpb25zLmxlbmd0aCkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgbWVyZ2VMZW5ndGgodHJhY2VPdXQsIGRpbWVuc2lvbnMsICd2YWx1ZXMnLCBsZW4pO1xuXG4gICAgY29lcmNlKCdob3Zlcm9uJyk7XG4gICAgY29lcmNlKCdhcnJhbmdlbWVudCcpO1xuICAgIGNvZXJjZSgnYnVuZGxlY29sb3JzJyk7XG4gICAgY29lcmNlKCdzb3J0cGF0aHMnKTtcbiAgICBjb2VyY2UoJ2NvdW50cycpO1xuXG4gICAgdmFyIGxhYmVsZm9udERmbHQgPSB7XG4gICAgICAgIGZhbWlseTogbGF5b3V0LmZvbnQuZmFtaWx5LFxuICAgICAgICBzaXplOiBNYXRoLnJvdW5kKGxheW91dC5mb250LnNpemUpLFxuICAgICAgICBjb2xvcjogbGF5b3V0LmZvbnQuY29sb3JcbiAgICB9O1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnbGFiZWxmb250JywgbGFiZWxmb250RGZsdCk7XG5cbiAgICB2YXIgY2F0ZWdvcnlmb250RGVmYXVsdCA9IHtcbiAgICAgICAgZmFtaWx5OiBsYXlvdXQuZm9udC5mYW1pbHksXG4gICAgICAgIHNpemU6IE1hdGgucm91bmQobGF5b3V0LmZvbnQuc2l6ZSAvIDEuMiksXG4gICAgICAgIGNvbG9yOiBsYXlvdXQuZm9udC5jb2xvclxuICAgIH07XG5cbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aWNrZm9udCcsIGNhdGVnb3J5Zm9udERlZmF1bHQpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFBhcmNhdHMgPSB7fTtcblxuUGFyY2F0cy5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5QYXJjYXRzLnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuUGFyY2F0cy5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5QYXJjYXRzLnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcblBhcmNhdHMuY29sb3JiYXIgPSB7XG4gICAgY29udGFpbmVyOiAnbGluZScsXG4gICAgbWluOiAnY21pbicsXG4gICAgbWF4OiAnY21heCdcbn07XG5cblBhcmNhdHMubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5QYXJjYXRzLm5hbWUgPSAncGFyY2F0cyc7XG5QYXJjYXRzLmJhc2VQbG90TW9kdWxlID0gcmVxdWlyZSgnLi9iYXNlX3Bsb3QnKTtcblBhcmNhdHMuY2F0ZWdvcmllcyA9IFsnbm9PcGFjaXR5J107XG5QYXJjYXRzLm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBhcmNhdHM7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgUGxvdGx5ID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvcGxvdF9hcGknKTtcbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xudmFyIHN2Z1RleHRVdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG5mdW5jdGlvbiBwZXJmb3JtUGxvdChwYXJjYXRzTW9kZWxzLCBncmFwaERpdiwgbGF5b3V0LCBzdmcpIHtcblxuICAgIHZhciB2aWV3TW9kZWxzID0gcGFyY2F0c01vZGVscy5tYXAoY3JlYXRlUGFyY2F0c1ZpZXdNb2RlbC5iaW5kKDAsIGdyYXBoRGl2LCBsYXlvdXQpKTtcblxuICAgIC8vIEdldCAocG90ZW50aWFsbHkgZW1wdHkpIHBhcmNhdHNsYXllciBzZWxlY3Rpb24gd2l0aCBib3VuZCBkYXRhIHRvIHNpbmdsZSBlbGVtZW50IGFycmF5XG4gICAgdmFyIGxheWVyU2VsZWN0aW9uID0gc3ZnLnNlbGVjdEFsbCgnZy5wYXJjYXRzbGF5ZXInKS5kYXRhKFtudWxsXSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHNpbmdsZSBwYXJjYXRzbGF5ZXIgZ3JvdXAgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgIGxheWVyU2VsZWN0aW9uLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdwYXJjYXRzbGF5ZXInKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuXG4gICAgLy8gQmluZCBkYXRhIHRvIGNoaWxkcmVuIG9mIGxheWVyU2VsZWN0aW9uIGFuZCBnZXQgcmVmZXJlbmNlIHRvIHRyYWNlU2VsZWN0aW9uXG4gICAgdmFyIHRyYWNlU2VsZWN0aW9uID0gbGF5ZXJTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgnZy50cmFjZS5wYXJjYXRzJylcbiAgICAgICAgLmRhdGEodmlld01vZGVscywga2V5KTtcblxuICAgIC8vIEluaXRpYWxpemUgZ3JvdXAgZm9yIGVhY2ggdHJhY2UvZGltZW5zaW9uc1xuICAgIHZhciB0cmFjZUVudGVyID0gdHJhY2VTZWxlY3Rpb24uZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3RyYWNlIHBhcmNhdHMnKTtcblxuICAgIC8vIFVwZGF0ZSBwcm9wZXJ0aWVzIGZvciBlYWNoIHRyYWNlXG4gICAgdHJhY2VTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnggKyAnLCAnICsgZC55ICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgcGF0aHMgZ3JvdXBcbiAgICB0cmFjZUVudGVyXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAncGF0aHMnKTtcblxuICAgIC8vIFVwZGF0ZSBwYXRocyB0cmFuc2Zvcm1cbiAgICB2YXIgcGF0aHNTZWxlY3Rpb24gPSB0cmFjZVNlbGVjdGlvblxuICAgICAgICAuc2VsZWN0KCdnLnBhdGhzJyk7XG5cbiAgICAvLyBHZXQgcGF0aHMgc2VsZWN0aW9uXG4gICAgdmFyIHBhdGhTZWxlY3Rpb24gPSBwYXRoc1NlbGVjdGlvblxuICAgICAgICAuc2VsZWN0QWxsKCdwYXRoLnBhdGgnKVxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5wYXRocztcbiAgICAgICAgfSwga2V5KTtcblxuICAgIC8vIFVwZGF0ZSBleGlzdGluZyBwYXRoIGNvbG9yc1xuICAgIHBhdGhTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5tb2RlbC5jb2xvcjtcbiAgICAgICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgcGF0aHNcbiAgICB2YXIgcGF0aFNlbGVjdGlvbkVudGVyID0gcGF0aFNlbGVjdGlvblxuICAgICAgICAuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3BhdGgnKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAwKVxuICAgICAgICAuYXR0cignZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLm1vZGVsLmNvbG9yO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMCk7XG5cbiAgICBzdHlsZVBhdGhzTm9Ib3ZlcihwYXRoU2VsZWN0aW9uRW50ZXIpO1xuXG4gICAgLy8gU2V0IHBhdGggZ2VvbWV0cnlcbiAgICBwYXRoU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdkJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuc3ZnRDtcbiAgICAgICAgfSk7XG5cbiAgICAvLyBzb3J0IHBhdGhzXG4gICAgaWYoIXBhdGhTZWxlY3Rpb25FbnRlci5lbXB0eSgpKSB7XG4gICAgICAgIC8vIE9ubHkgc29ydCBwYXRocyBpZiB0aGVyZSBoYXMgYmVlbiBhIGNoYW5nZS5cbiAgICAgICAgLy8gT3RoZXJ3aXNlIHBhdGhzIGFyZSBhbHJlYWR5IHNvcnRlZCBvciBhIGhvdmVyIG9wZXJhdGlvbiBtYXkgYmUgaW4gcHJvZ3Jlc3NcbiAgICAgICAgcGF0aFNlbGVjdGlvbi5zb3J0KGNvbXBhcmVSYXdDb2xvcik7XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGFueSBvbGQgcGF0aHNcbiAgICBwYXRoU2VsZWN0aW9uLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIC8vIFBhdGggaG92ZXJcbiAgICBwYXRoU2VsZWN0aW9uXG4gICAgICAgIC5vbignbW91c2VvdmVyJywgbW91c2VvdmVyUGF0aClcbiAgICAgICAgLm9uKCdtb3VzZW91dCcsIG1vdXNlb3V0UGF0aClcbiAgICAgICAgLm9uKCdjbGljaycsIGNsaWNrUGF0aCk7XG5cbiAgICAvLyBJbml0aWFsaXplIGRpbWVuc2lvbnMgZ3JvdXBcbiAgICB0cmFjZUVudGVyLmFwcGVuZCgnZycpLmF0dHIoJ2NsYXNzJywgJ2RpbWVuc2lvbnMnKTtcblxuICAgIC8vIFVwZGF0ZSBkaW1lbnNpb25zIHRyYW5zZm9ybVxuICAgIHZhciBkaW1lbnNpb25zU2VsZWN0aW9uID0gdHJhY2VTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdCgnZy5kaW1lbnNpb25zJyk7XG5cbiAgICAvLyBHZXQgZGltZW5zaW9uIHNlbGVjdGlvblxuICAgIHZhciBkaW1lbnNpb25TZWxlY3Rpb24gPSBkaW1lbnNpb25zU2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cuZGltZW5zaW9uJylcbiAgICAgICAgLmRhdGEoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuZGltZW5zaW9ucztcbiAgICAgICAgfSwga2V5KTtcblxuICAgIC8vIENyZWF0ZSBkaW1lbnNpb24gZ3JvdXBzXG4gICAgZGltZW5zaW9uU2VsZWN0aW9uLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdkaW1lbnNpb24nKTtcblxuICAgIC8vIFVwZGF0ZSBkaW1lbnNpb24gZ3JvdXAgdHJhbnNmb3Jtc1xuICAgIGRpbWVuc2lvblNlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnggKyAnLCAwKSc7XG4gICAgfSk7XG5cbiAgICAvLyBSZW1vdmUgYW55IG9sZCBkaW1lbnNpb25zXG4gICAgZGltZW5zaW9uU2VsZWN0aW9uLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIC8vIEdldCBjYXRlZ29yeSBzZWxlY3Rpb25cbiAgICB2YXIgY2F0ZWdvcnlTZWxlY3Rpb24gPSBkaW1lbnNpb25TZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgnZy5jYXRlZ29yeScpXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmNhdGVnb3JpZXM7XG4gICAgICAgIH0sIGtleSk7XG5cbiAgICAvLyBJbml0aWFsaXplIGNhdGVnb3J5IGdyb3Vwc1xuICAgIHZhciBjYXRlZ29yeUdyb3VwRW50ZXJTZWxlY3Rpb24gPSBjYXRlZ29yeVNlbGVjdGlvblxuICAgICAgICAuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2NhdGVnb3J5Jyk7XG5cbiAgICAvLyBVcGRhdGUgY2F0ZWdvcnkgdHJhbnNmb3Jtc1xuICAgIGNhdGVnb3J5U2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgwLCAnICsgZC55ICsgJyknO1xuICAgICAgICB9KTtcblxuXG4gICAgLy8gSW5pdGlhbGl6ZSByZWN0YW5nbGVcbiAgICBjYXRlZ29yeUdyb3VwRW50ZXJTZWxlY3Rpb25cbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdjYXRyZWN0JylcbiAgICAgICAgLmF0dHIoJ3BvaW50ZXItZXZlbnRzJywgJ25vbmUnKTtcblxuXG4gICAgLy8gVXBkYXRlIHJlY3RhbmdsZVxuICAgIGNhdGVnb3J5U2VsZWN0aW9uLnNlbGVjdCgncmVjdC5jYXRyZWN0JylcbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCAnbm9uZScpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLndpZHRoO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuaGVpZ2h0O1xuICAgICAgICB9KTtcblxuICAgIHN0eWxlQ2F0ZWdvcmllc05vSG92ZXIoY2F0ZWdvcnlHcm91cEVudGVyU2VsZWN0aW9uKTtcblxuICAgIC8vIEluaXRpYWxpemUgY29sb3IgYmFuZCByZWN0c1xuICAgIHZhciBiYW5kU2VsZWN0aW9uID0gY2F0ZWdvcnlTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgIC5kYXRhKFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7Q2F0ZWdvcnlWaWV3TW9kZWx9IGNhdFZpZXdNb2RlbCovXG4gICAgICAgICAgICBmdW5jdGlvbihjYXRWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2F0Vmlld01vZGVsLmJhbmRzO1xuICAgICAgICAgICAgfSwga2V5KTtcblxuICAgIC8vIFJhaXNlIGFsbCB1cGRhdGUgYmFuZHMgdG8gdGhlIHRvcCBzbyB0aGF0IGZhZGluZyBlbnRlci9leGl0IGJhbmRzIHdpbGwgYmUgYmVoaW5kXG4gICAgYmFuZFNlbGVjdGlvbi5lYWNoKGZ1bmN0aW9uKCkge0xpYi5yYWlzZVRvVG9wKHRoaXMpO30pO1xuXG4gICAgLy8gVXBkYXRlIGJhbmQgY29sb3JcbiAgICBiYW5kU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY29sb3I7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIGJhbmRzU2VsZWN0aW9uRW50ZXIgPSBiYW5kU2VsZWN0aW9uLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdiYW5kcmVjdCcpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDApXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY29sb3I7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdmaWxsLW9wYWNpdHknLCAwKTtcblxuICAgIGJhbmRTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jb2xvcjtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQud2lkdGg7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5oZWlnaHQ7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQueTtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2N1cnNvcicsXG4gICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGJhbmRNb2RlbCovXG4gICAgICAgICAgICBmdW5jdGlvbihiYW5kTW9kZWwpIHtcbiAgICAgICAgICAgICAgICBpZihiYW5kTW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ2ZpeGVkJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2RlZmF1bHQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihiYW5kTW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ3BlcnBlbmRpY3VsYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnbnMtcmVzaXplJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ21vdmUnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgc3R5bGVCYW5kc05vSG92ZXIoYmFuZHNTZWxlY3Rpb25FbnRlcik7XG5cbiAgICBiYW5kU2VsZWN0aW9uLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIC8vIEluaXRpYWxpemUgY2F0ZWdvcnkgbGFiZWxcbiAgICBjYXRlZ29yeUdyb3VwRW50ZXJTZWxlY3Rpb25cbiAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdjYXRsYWJlbCcpXG4gICAgICAgIC5hdHRyKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG5cbiAgICB2YXIgcGFwZXJDb2xvciA9IGdyYXBoRGl2Ll9mdWxsTGF5b3V0LnBhcGVyX2JnY29sb3I7XG5cbiAgICAvLyBVcGRhdGUgY2F0ZWdvcnkgbGFiZWxcbiAgICBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3QoJ3RleHQuY2F0bGFiZWwnKVxuICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLFxuICAgICAgICAgICAgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGlmKGNhdEluUmlnaHREaW0oZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIHJpZ2h0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnc3RhcnQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSBsZWZ0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZW5kJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAuYXR0cignYWxpZ25tZW50LWJhc2VsaW5lJywgJ21pZGRsZScpXG5cbiAgICAgICAgLnN0eWxlKCd0ZXh0LXNoYWRvdycsXG4gICAgICAgICAgICBwYXBlckNvbG9yICsgJyAtMXB4ICAxcHggMnB4LCAnICtcbiAgICAgICAgICAgIHBhcGVyQ29sb3IgKyAnIDFweCAgMXB4IDJweCwgJyArXG4gICAgICAgICAgICBwYXBlckNvbG9yICsgJyAgMXB4IC0xcHggMnB4LCAnICtcbiAgICAgICAgICAgIHBhcGVyQ29sb3IgKyAnIC0xcHggLTFweCAycHgnKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAncmdiKDAsIDAsIDApJylcbiAgICAgICAgLmF0dHIoJ3gnLFxuICAgICAgICAgICAgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGlmKGNhdEluUmlnaHREaW0oZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIHJpZ2h0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkLndpZHRoICsgNTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgbGVmdCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3knLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5oZWlnaHQgLyAyO1xuICAgICAgICB9KVxuICAgICAgICAudGV4dChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5tb2RlbC5jYXRlZ29yeUxhYmVsO1xuICAgICAgICB9KVxuICAgICAgICAuZWFjaChcbiAgICAgICAgICAgIC8qKiBAcGFyYW0ge0NhdGVnb3J5Vmlld01vZGVsfSBjYXRNb2RlbCovXG4gICAgICAgICAgICBmdW5jdGlvbihjYXRNb2RlbCkge1xuICAgICAgICAgICAgICAgIERyYXdpbmcuZm9udChkMy5zZWxlY3QodGhpcyksIGNhdE1vZGVsLnBhcmNhdHNWaWV3TW9kZWwuY2F0ZWdvcnlsYWJlbGZvbnQpO1xuICAgICAgICAgICAgICAgIHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMoZDMuc2VsZWN0KHRoaXMpLCBncmFwaERpdik7XG4gICAgICAgICAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgZGltZW5zaW9uIGxhYmVsXG4gICAgY2F0ZWdvcnlHcm91cEVudGVyU2VsZWN0aW9uXG4gICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnZGltbGFiZWwnKTtcblxuICAgIC8vIFVwZGF0ZSBkaW1lbnNpb24gbGFiZWxcbiAgICBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3QoJ3RleHQuZGltbGFiZWwnKVxuICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCAnbWlkZGxlJylcbiAgICAgICAgLmF0dHIoJ2FsaWdubWVudC1iYXNlbGluZScsICdiYXNlbGluZScpXG4gICAgICAgIC5hdHRyKCdjdXJzb3InLFxuICAgICAgICAgICAgIC8qKiBAcGFyYW0ge0NhdGVnb3J5Vmlld01vZGVsfSBjYXRNb2RlbCovXG4gICAgICAgICAgICBmdW5jdGlvbihjYXRNb2RlbCkge1xuICAgICAgICAgICAgICAgIGlmKGNhdE1vZGVsLnBhcmNhdHNWaWV3TW9kZWwuYXJyYW5nZW1lbnQgPT09ICdmaXhlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdkZWZhdWx0JztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2V3LXJlc2l6ZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3gnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC53aWR0aCAvIDI7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd5JywgLTUpXG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIGlmKGkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBBZGQgZGltZW5zaW9uIGxhYmVsIGFib3ZlIHRvcG1vc3QgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICByZXR1cm4gZC5wYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnNbZC5tb2RlbC5kaW1lbnNpb25JbmRdLmRpbWVuc2lvbkxhYmVsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goXG4gICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0TW9kZWwqL1xuICAgICAgICAgICAgZnVuY3Rpb24oY2F0TW9kZWwpIHtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLmZvbnQoZDMuc2VsZWN0KHRoaXMpLCBjYXRNb2RlbC5wYXJjYXRzVmlld01vZGVsLmxhYmVsZm9udCk7XG4gICAgICAgICAgICB9KTtcblxuICAgIC8vIENhdGVnb3J5IGhvdmVyXG4gICAgLy8gY2F0ZWdvcnlTZWxlY3Rpb24uc2VsZWN0KCdyZWN0LmNhdHJlY3QnKVxuICAgIGNhdGVnb3J5U2VsZWN0aW9uLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgIC5vbignbW91c2VvdmVyJywgbW91c2VvdmVyQ2F0ZWdvcnlCYW5kKVxuICAgICAgICAub24oJ21vdXNlb3V0JywgbW91c2VvdXRDYXRlZ29yeSk7XG5cbiAgICAvLyBSZW1vdmUgdW51c2VkIGNhdGVnb3JpZXNcbiAgICBjYXRlZ29yeVNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBTZXR1cCBkcmFnXG4gICAgZGltZW5zaW9uU2VsZWN0aW9uLmNhbGwoZDMuYmVoYXZpb3IuZHJhZygpXG4gICAgICAgIC5vcmlnaW4oZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIHt4OiBkLngsIHk6IDB9O1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2RyYWdzdGFydCcsIGRyYWdEaW1lbnNpb25TdGFydClcbiAgICAgICAgLm9uKCdkcmFnJywgZHJhZ0RpbWVuc2lvbilcbiAgICAgICAgLm9uKCdkcmFnZW5kJywgZHJhZ0RpbWVuc2lvbkVuZCkpO1xuXG5cbiAgICAvLyBTYXZlIG9mZiBzZWxlY3Rpb25zIHRvIHZpZXcgbW9kZWxzXG4gICAgdHJhY2VTZWxlY3Rpb24uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIGQudHJhY2VTZWxlY3Rpb24gPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIGQucGF0aFNlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cucGF0aHMnKS5zZWxlY3RBbGwoJ3BhdGgucGF0aCcpO1xuICAgICAgICBkLmRpbWVuc2lvblNlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cuZGltZW5zaW9ucycpLnNlbGVjdEFsbCgnZy5kaW1lbnNpb24nKTtcbiAgICB9KTtcblxuICAgIC8vIFJlbW92ZSBhbnkgb3JwaGFuIHRyYWNlc1xuICAgIHRyYWNlU2VsZWN0aW9uLmV4aXQoKS5yZW1vdmUoKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgLyB1cGRhdGUgcGFyY2F0IHRyYWNlc1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBncmFwaERpdlxuICogQHBhcmFtIHtPYmplY3R9IHN2Z1xuICogQHBhcmFtIHtBcnJheS48UGFyY2F0c01vZGVsPn0gcGFyY2F0c01vZGVsc1xuICogQHBhcmFtIHtMYXlvdXR9IGxheW91dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdyYXBoRGl2LCBzdmcsIHBhcmNhdHNNb2RlbHMsIGxheW91dCkge1xuICAgIHBlcmZvcm1QbG90KHBhcmNhdHNNb2RlbHMsIGdyYXBoRGl2LCBsYXlvdXQsIHN2Zyk7XG59O1xuXG4vKipcbiAqIEZ1bmN0aW9uIHRoZSByZXR1cm5zIHRoZSBrZXkgcHJvcGVydHkgb2YgYW4gb2JqZWN0IGZvciB1c2Ugd2l0aCBhcyBEMyBqb2luIGZ1bmN0aW9uXG4gKiBAcGFyYW0gZFxuICovXG5mdW5jdGlvbiBrZXkoZCkge1xuICAgIHJldHVybiBkLmtleTtcbn1cblxuIC8qKiBUcnVlIGlmIGEgY2F0ZWdvcnkgdmlldyBtb2RlbCBpcyBpbiB0aGUgcmlnaHQtbW9zdCBkaXNwbGF5IGRpbWVuc2lvblxuICAqIEBwYXJhbSB7Q2F0ZWdvcnlWaWV3TW9kZWx9IGQgKi9cbmZ1bmN0aW9uIGNhdEluUmlnaHREaW0oZCkge1xuICAgIHZhciBudW1EaW1zID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnMubGVuZ3RoLFxuICAgICAgICBsZWZ0RGltSW5kID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbbnVtRGltcyAtIDFdLm1vZGVsLmRpbWVuc2lvbkluZDtcbiAgICByZXR1cm4gZC5tb2RlbC5kaW1lbnNpb25JbmQgPT09IGxlZnREaW1JbmQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBhXG4gKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IGJcbiAqL1xuZnVuY3Rpb24gY29tcGFyZVJhd0NvbG9yKGEsIGIpIHtcbiAgICBpZihhLm1vZGVsLnJhd0NvbG9yID4gYi5tb2RlbC5yYXdDb2xvcikge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYoYS5tb2RlbC5yYXdDb2xvciA8IGIubW9kZWwucmF3Q29sb3IpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbn1cblxuLyoqXG4gKiBIYW5kbGUgcGF0aCBtb3VzZW92ZXJcbiAqIEBwYXJhbSB7UGF0aFZpZXdNb2RlbH0gZFxuICovXG5mdW5jdGlvbiBtb3VzZW92ZXJQYXRoKGQpIHtcblxuICAgIGlmKCFkLnBhcmNhdHNWaWV3TW9kZWwuZHJhZ0RpbWVuc2lvbikge1xuICAgICAgICAvLyBXZSdyZSBub3QgY3VycmVudGx5IGRyYWdnaW5nXG5cbiAgICAgICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGhvdmVyaW5mbyBpcyBub3Qgc2tpcCwgc28gd2UgYXQgbGVhc3Qgc3R5bGUgdGhlIHBhdGhzIGFuZCBlbWl0IGludGVyYWN0aW9uIGV2ZW50c1xuXG4gICAgICAgICAgICAvLyBSYWlzZSBwYXRoIHRvIHRvcFxuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG5cbiAgICAgICAgICAgIHN0eWxlUGF0aHNIb3ZlcihkMy5zZWxlY3QodGhpcykpO1xuXG4gICAgICAgICAgICAvLyBFbWl0IGhvdmVyIGV2ZW50XG4gICAgICAgICAgICB2YXIgcG9pbnRzID0gYnVpbGRQb2ludHNBcnJheUZvclBhdGgoZCk7XG4gICAgICAgICAgICBkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X2hvdmVyJywge3BvaW50czogcG9pbnRzLCBldmVudDogZDMuZXZlbnR9KTtcblxuICAgICAgICAgICAgLy8gSGFuZGxlIGhvdmVyIGxhYmVsXG4gICAgICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignbm9uZScpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIC8vIGhvdmVyaW5mbyBpcyBhIGNvbWJpbmF0aW9uIG9mICdjb3VudCcgYW5kICdwcm9iYWJpbGl0eSdcblxuICAgICAgICAgICAgICAgIC8vIE1vdXNlXG4gICAgICAgICAgICAgICAgdmFyIGhvdmVyWCA9IGQzLm1vdXNlKHRoaXMpWzBdO1xuXG4gICAgICAgICAgICAgICAgLy8gTGFiZWxcbiAgICAgICAgICAgICAgICB2YXIgZ2QgPSBkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXY7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgICAgICAgICB2YXIgcm9vdEJCb3ggPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIGdyYXBoRGl2QkJveCA9IGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmQgcGF0aCBjZW50ZXIgaW4gcGF0aCBjb29yZGluYXRlc1xuICAgICAgICAgICAgICAgIHZhciBwYXRoQ2VudGVyWCxcbiAgICAgICAgICAgICAgICAgICAgcGF0aENlbnRlclksXG4gICAgICAgICAgICAgICAgICAgIGRpbUluZDtcblxuICAgICAgICAgICAgICAgIGZvcihkaW1JbmQgPSAwOyBkaW1JbmQgPCAoZC5sZWZ0WHMubGVuZ3RoIC0gMSk7IGRpbUluZCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGQubGVmdFhzW2RpbUluZF0gKyBkLmRpbVdpZHRoc1tkaW1JbmRdIC0gMiA8PSBob3ZlclggJiYgaG92ZXJYIDw9IGQubGVmdFhzW2RpbUluZCArIDFdICsgMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnREaW0gPSBkLnBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uc1tkaW1JbmRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0RGltID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbZGltSW5kICsgMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRoQ2VudGVyWCA9IChsZWZ0RGltLnggKyBsZWZ0RGltLndpZHRoICsgcmlnaHREaW0ueCkgLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aENlbnRlclkgPSAoZC50b3BZc1tkaW1JbmRdICsgZC50b3BZc1tkaW1JbmQgKyAxXSArIGQuaGVpZ2h0KSAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEZpbmQgcGF0aCBjZW50ZXIgaW4gcm9vdCBjb29yZGluYXRlc1xuICAgICAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclggPSBkLnBhcmNhdHNWaWV3TW9kZWwueCArIHBhdGhDZW50ZXJYO1xuICAgICAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclkgPSBkLnBhcmNhdHNWaWV3TW9kZWwueSArIHBhdGhDZW50ZXJZO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRleHRDb2xvciA9IHRpbnljb2xvci5tb3N0UmVhZGFibGUoZC5tb2RlbC5jb2xvciwgWydibGFjaycsICd3aGl0ZSddKTtcblxuICAgICAgICAgICAgICAgIC8vIEJ1aWxkIGhvdmVyIHRleHRcbiAgICAgICAgICAgICAgICB2YXIgaG92ZXJ0ZXh0UGFydHMgPSBbXTtcbiAgICAgICAgICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignY291bnQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJ0ZXh0UGFydHMucHVzaChbJ0NvdW50OicsIGQubW9kZWwuY291bnRdLmpvaW4oJyAnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdwcm9iYWJpbGl0eScpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBob3ZlcnRleHRQYXJ0cy5wdXNoKFsnUDonLCAoZC5tb2RlbC5jb3VudCAvIGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudCkudG9GaXhlZCgzKV0uam9pbignICcpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaG92ZXJ0ZXh0ID0gaG92ZXJ0ZXh0UGFydHMuam9pbignPGJyPicpO1xuICAgICAgICAgICAgICAgIHZhciBtb3VzZVggPSBkMy5tb3VzZShnZClbMF07XG5cbiAgICAgICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgICAgICB4OiBob3ZlckNlbnRlclggLSByb290QkJveC5sZWZ0ICsgZ3JhcGhEaXZCQm94LmxlZnQsXG4gICAgICAgICAgICAgICAgICAgIHk6IGhvdmVyQ2VudGVyWSAtIHJvb3RCQm94LnRvcCArIGdyYXBoRGl2QkJveC50b3AsXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IGhvdmVydGV4dCxcbiAgICAgICAgICAgICAgICAgICAgY29sb3I6IGQubW9kZWwuY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiAnYmxhY2snLFxuICAgICAgICAgICAgICAgICAgICBmb250RmFtaWx5OiAnTW9uYWNvLCBcIkNvdXJpZXIgTmV3XCIsIG1vbm9zcGFjZScsXG4gICAgICAgICAgICAgICAgICAgIGZvbnRTaXplOiAxMCxcbiAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiB0ZXh0Q29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGlkZWFsQWxpZ246IG1vdXNlWCA8IGhvdmVyQ2VudGVyWCA/ICdyaWdodCcgOiAnbGVmdCdcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgIG91dGVyQ29udGFpbmVyOiBmdWxsTGF5b3V0Ll9wYXBlci5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgIGdkOiBnZFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEhhbmRsZSBwYXRoIG1vdXNlb3V0XG4gKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gbW91c2VvdXRQYXRoKGQpIHtcbiAgICBpZighZC5wYXJjYXRzVmlld01vZGVsLmRyYWdEaW1lbnNpb24pIHtcbiAgICAgICAgLy8gV2UncmUgbm90IGN1cnJlbnRseSBkcmFnZ2luZ1xuICAgICAgICBzdHlsZVBhdGhzTm9Ib3ZlcihkMy5zZWxlY3QodGhpcykpO1xuXG4gICAgICAgIC8vIFJlbW92ZSBhbmQgaG92ZXIgbGFiZWxcbiAgICAgICAgRngubG9uZVVuaG92ZXIoZC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2Ll9mdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSk7XG5cbiAgICAgICAgLy8gUmVzdG9yZSBwYXRoIG9yZGVyXG4gICAgICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uLnNvcnQoY29tcGFyZVJhd0NvbG9yKTtcblxuICAgICAgICAvLyBFbWl0IHVuaG92ZXIgZXZlbnRcbiAgICAgICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZhciBwb2ludHMgPSBidWlsZFBvaW50c0FycmF5Rm9yUGF0aChkKTtcbiAgICAgICAgICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5lbWl0KCdwbG90bHlfdW5ob3ZlcicsIHtwb2ludHM6IHBvaW50cywgZXZlbnQ6IGQzLmV2ZW50fSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQnVpbGQgYXJyYXkgb2YgcG9pbnQgb2JqZWN0cyBmb3IgYSBwYXRoXG4gKlxuICogRm9yIHVzZSBpbiBjbGljay9ob3ZlciBldmVudHNcbiAqIEBwYXJhbSB7UGF0aFZpZXdNb2RlbH0gZFxuICovXG5mdW5jdGlvbiBidWlsZFBvaW50c0FycmF5Rm9yUGF0aChkKSB7XG4gICAgdmFyIHBvaW50cyA9IFtdO1xuICAgIHZhciBjdXJ2ZU51bWJlciA9IGdldFRyYWNlSW5kZXgoZC5wYXJjYXRzVmlld01vZGVsKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkLm1vZGVsLnZhbHVlSW5kcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcG9pbnROdW1iZXIgPSBkLm1vZGVsLnZhbHVlSW5kc1tpXTtcbiAgICAgICAgcG9pbnRzLnB1c2goe1xuICAgICAgICAgICAgY3VydmVOdW1iZXI6IGN1cnZlTnVtYmVyLFxuICAgICAgICAgICAgcG9pbnROdW1iZXI6IHBvaW50TnVtYmVyXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzO1xufVxuXG4vKipcbiAqIEhhbmRsZSBwYXRoIGNsaWNrXG4gKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gY2xpY2tQYXRoKGQpIHtcbiAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignc2tpcCcpID09PSAtMSkge1xuICAgICAgICAvLyBob3ZlcmluZm8gaXQncyBza2lwLCBzbyBpbnRlcmFjdGlvbiBldmVudHMgYXJlbid0IGRpc2FibGVkXG4gICAgICAgIHZhciBwb2ludHMgPSBidWlsZFBvaW50c0FycmF5Rm9yUGF0aChkKTtcbiAgICAgICAgZC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2LmVtaXQoJ3Bsb3RseV9jbGljaycsIHtwb2ludHM6IHBvaW50cywgZXZlbnQ6IGQzLmV2ZW50fSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzdHlsZVBhdGhzTm9Ib3ZlcihwYXRoU2VsZWN0aW9uKSB7XG4gICAgcGF0aFNlbGVjdGlvblxuICAgICAgICAuYXR0cignZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLm1vZGVsLmNvbG9yO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMC42KVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2xpZ2h0Z3JheScpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCAwLjIpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDEuMCk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlUGF0aHNIb3ZlcihwYXRoU2VsZWN0aW9uKSB7XG4gICAgcGF0aFNlbGVjdGlvblxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMC44KVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRpbnljb2xvci5tb3N0UmVhZGFibGUoZC5tb2RlbC5jb2xvciwgWydibGFjaycsICd3aGl0ZSddKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDAuMyk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlQ2F0ZWdvcnlIb3ZlcihjYXRlZ29yeVNlbGVjdGlvbikge1xuICAgIGNhdGVnb3J5U2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3QoJ3JlY3QuY2F0cmVjdCcpXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMi41KTtcbn1cblxuZnVuY3Rpb24gc3R5bGVDYXRlZ29yaWVzTm9Ib3ZlcihjYXRlZ29yeVNlbGVjdGlvbikge1xuICAgIGNhdGVnb3J5U2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3QoJ3JlY3QuY2F0cmVjdCcpXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1vcGFjaXR5JywgMSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlQmFuZHNIb3ZlcihiYW5kc1NlbGVjdGlvbikge1xuICAgIGJhbmRzU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMS41KTtcbn1cblxuZnVuY3Rpb24gc3R5bGVCYW5kc05vSG92ZXIoYmFuZHNTZWxlY3Rpb24pIHtcbiAgICBiYW5kc1NlbGVjdGlvblxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDAuMilcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1vcGFjaXR5JywgMS4wKVxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMS4wKTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gc2VsZWN0aW9uIG9mIGFsbCBwYXRocyB0aGF0IHBhc3MgdGhyb3VnaCB0aGUgc3BlY2lmaWVkIGNhdGVnb3J5XG4gKiBAcGFyYW0ge0NhdGVnb3J5QmFuZFZpZXdNb2RlbH0gY2F0QmFuZFZpZXdNb2RlbFxuICovXG5mdW5jdGlvbiBzZWxlY3RQYXRoc1Rocm91Z2hDYXRlZ29yeUJhbmRDb2xvcihjYXRCYW5kVmlld01vZGVsKSB7XG5cbiAgICB2YXIgYWxsUGF0aHMgPSBjYXRCYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwucGF0aFNlbGVjdGlvbjtcbiAgICB2YXIgZGltSW5kID0gY2F0QmFuZFZpZXdNb2RlbC5jYXRlZ29yeVZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25JbmQ7XG4gICAgdmFyIGNhdEluZCA9IGNhdEJhbmRWaWV3TW9kZWwuY2F0ZWdvcnlWaWV3TW9kZWwubW9kZWwuY2F0ZWdvcnlJbmQ7XG5cbiAgICByZXR1cm4gYWxsUGF0aHNcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgIC8qKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IHBhdGhWaWV3TW9kZWwgKi9cbiAgICAgICAgICAgIGZ1bmN0aW9uKHBhdGhWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0aFZpZXdNb2RlbC5tb2RlbC5jYXRlZ29yeUluZHNbZGltSW5kXSA9PT0gY2F0SW5kICYmXG4gICAgICAgICAgICAgICAgICAgIHBhdGhWaWV3TW9kZWwubW9kZWwuY29sb3IgPT09IGNhdEJhbmRWaWV3TW9kZWwuY29sb3I7XG4gICAgICAgICAgICB9KTtcbn1cblxuXG4vKipcbiAqIFBlcmZvcm0gaG92ZXIgc3R5bGluZyBmb3IgYWxsIHBhdGhzIHRoYXQgcGFzcyB0aG91Z2ggdGhlIHNwZWNpZmllZCBiYW5kIGVsZW1lbnQncyBjYXRlZ29yeVxuICpcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBzdHlsZUZvckNhdGVnb3J5SG92ZXJtb2RlKGJhbmRFbGVtZW50KSB7XG5cbiAgICAvLyBHZXQgYWxsIGJhbmRzIGluIHRoZSBjdXJyZW50IGNhdGVnb3J5XG4gICAgdmFyIGJhbmRTZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSkuc2VsZWN0QWxsKCdyZWN0LmJhbmRyZWN0Jyk7XG5cbiAgICAvLyBSYWlzZSBhbmQgc3R5bGUgcGF0aHNcbiAgICBiYW5kU2VsLmVhY2goZnVuY3Rpb24oYnZtKSB7XG4gICAgICAgIHZhciBwYXRocyA9IHNlbGVjdFBhdGhzVGhyb3VnaENhdGVnb3J5QmFuZENvbG9yKGJ2bSk7XG4gICAgICAgIHN0eWxlUGF0aHNIb3ZlcihwYXRocyk7XG4gICAgICAgIHBhdGhzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBSYWlzZSBwYXRoIHRvIHRvcFxuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gU3R5bGUgY2F0ZWdvcnlcbiAgICBzdHlsZUNhdGVnb3J5SG92ZXIoZDMuc2VsZWN0KGJhbmRFbGVtZW50LnBhcmVudE5vZGUpKTtcbn1cblxuLyoqXG4gKiBQZXJmb3JtIGhvdmVyIHN0eWxpbmcgZm9yIGFsbCBwYXRocyB0aGF0IHBhc3MgdGhvdWdoIHRoZSBjYXRlZ29yeSBvZiB0aGUgc3BlY2lmaWVkIGJhbmQgZWxlbWVudCBhbmQgc2hhcmUgdGhlXG4gKiBzYW1lIGNvbG9yXG4gKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gYmFuZEVsZW1lbnRcbiAqICBIVE1MIGVsZW1lbnQgZm9yIGJhbmRcbiAqXG4gKi9cbmZ1bmN0aW9uIHN0eWxlRm9yQ29sb3JIb3Zlcm1vZGUoYmFuZEVsZW1lbnQpIHtcbiAgICB2YXIgYmFuZFZpZXdNb2RlbCA9IGQzLnNlbGVjdChiYW5kRWxlbWVudCkuZGF0dW0oKTtcbiAgICB2YXIgY2F0UGF0aHMgPSBzZWxlY3RQYXRoc1Rocm91Z2hDYXRlZ29yeUJhbmRDb2xvcihiYW5kVmlld01vZGVsKTtcbiAgICBzdHlsZVBhdGhzSG92ZXIoY2F0UGF0aHMpO1xuICAgIGNhdFBhdGhzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIFJhaXNlIHBhdGggdG8gdG9wXG4gICAgICAgIExpYi5yYWlzZVRvVG9wKHRoaXMpO1xuICAgIH0pO1xuXG4gICAgLy8gU3R5bGUgY2F0ZWdvcnkgZm9yIGRyYWdcbiAgICBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSlcbiAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oYikge3JldHVybiBiLmNvbG9yID09PSBiYW5kVmlld01vZGVsLmNvbG9yO30pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG4gICAgICAgICAgICBzdHlsZUJhbmRzSG92ZXIoZDMuc2VsZWN0KHRoaXMpKTtcbiAgICAgICAgfSk7XG59XG5cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBiYW5kRWxlbWVudFxuICogIEhUTUwgZWxlbWVudCBmb3IgYmFuZFxuICogQHBhcmFtIGV2ZW50TmFtZVxuICogIEV2ZW50IG5hbWUgKHBsb3RseV9ob3ZlciBvciBwbG90bHlfY2xpY2spXG4gKiBAcGFyYW0gZXZlbnRcbiAqICBNb3VzZSBFdmVudFxuICovXG5mdW5jdGlvbiBlbWl0UG9pbnRzRXZlbnRDYXRlZ29yeUhvdmVybW9kZShiYW5kRWxlbWVudCwgZXZlbnROYW1lLCBldmVudCkge1xuICAgIC8vIEdldCBhbGwgYmFuZHMgaW4gdGhlIGN1cnJlbnQgY2F0ZWdvcnlcbiAgICB2YXIgYmFuZFZpZXdNb2RlbCA9IGQzLnNlbGVjdChiYW5kRWxlbWVudCkuZGF0dW0oKTtcbiAgICB2YXIgZ2QgPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXY7XG4gICAgdmFyIGJhbmRTZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSkuc2VsZWN0QWxsKCdyZWN0LmJhbmRyZWN0Jyk7XG5cbiAgICB2YXIgcG9pbnRzID0gW107XG4gICAgYmFuZFNlbC5lYWNoKGZ1bmN0aW9uKGJ2bSkge1xuICAgICAgICB2YXIgcGF0aHMgPSBzZWxlY3RQYXRoc1Rocm91Z2hDYXRlZ29yeUJhbmRDb2xvcihidm0pO1xuICAgICAgICBwYXRocy5lYWNoKGZ1bmN0aW9uKHBhdGhWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgIC8vIEV4dGVuZCBwb2ludHMgYXJyYXlcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHBvaW50cywgYnVpbGRQb2ludHNBcnJheUZvclBhdGgocGF0aFZpZXdNb2RlbCkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIGdkLmVtaXQoZXZlbnROYW1lLCB7cG9pbnRzOiBwb2ludHMsIGV2ZW50OiBldmVudH0pO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKiBAcGFyYW0gZXZlbnROYW1lXG4gKiAgRXZlbnQgbmFtZSAocGxvdGx5X2hvdmVyIG9yIHBsb3RseV9jbGljaylcbiAqIEBwYXJhbSBldmVudFxuICogIE1vdXNlIEV2ZW50XG4gKi9cbmZ1bmN0aW9uIGVtaXRQb2ludHNFdmVudENvbG9ySG92ZXJtb2RlKGJhbmRFbGVtZW50LCBldmVudE5hbWUsIGV2ZW50KSB7XG4gICAgdmFyIGJhbmRWaWV3TW9kZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQpLmRhdHVtKCk7XG4gICAgdmFyIGdkID0gYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2O1xuICAgIHZhciBwYXRocyA9IHNlbGVjdFBhdGhzVGhyb3VnaENhdGVnb3J5QmFuZENvbG9yKGJhbmRWaWV3TW9kZWwpO1xuXG4gICAgdmFyIHBvaW50cyA9IFtdO1xuICAgIHBhdGhzLmVhY2goZnVuY3Rpb24ocGF0aFZpZXdNb2RlbCkge1xuICAgICAgICAvLyBFeHRlbmQgcG9pbnRzIGFycmF5XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHBvaW50cywgYnVpbGRQb2ludHNBcnJheUZvclBhdGgocGF0aFZpZXdNb2RlbCkpO1xuICAgIH0pO1xuXG4gICAgZ2QuZW1pdChldmVudE5hbWUsIHtwb2ludHM6IHBvaW50cywgZXZlbnQ6IGV2ZW50fSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGhvdmVyIGxhYmVsIGZvciBhIGJhbmQgZWxlbWVudCdzIGNhdGVnb3J5IChmb3IgdXNlIHdoZW4gaG92ZXJvbiA9PT0gJ2NhdGVnb3J5JylcbiAqXG4gKiBAcGFyYW0ge0NsaWVudFJlY3R9IHJvb3RCQm94XG4gKiAgQ2xpZW50IGJvdW5kaW5nIGJveCBmb3Igcm9vdCBvZiBmaWd1cmVcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBjcmVhdGVIb3ZlckxhYmVsRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KSB7XG4gICAgLy8gU2VsZWN0aW9uc1xuICAgIHZhciByZWN0U2VsZWN0aW9uID0gZDMuc2VsZWN0KGJhbmRFbGVtZW50LnBhcmVudE5vZGUpLnNlbGVjdCgncmVjdC5jYXRyZWN0Jyk7XG4gICAgdmFyIHJlY3RCb3VuZGluZ0JveCA9IHJlY3RTZWxlY3Rpb24ubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgLy8gTW9kZWxzXG4gICAgLyoqIEB0eXBlIHtDYXRlZ29yeVZpZXdNb2RlbH0gKi9cbiAgICB2YXIgY2F0Vmlld01vZGVsID0gcmVjdFNlbGVjdGlvbi5kYXR1bSgpO1xuICAgIHZhciBwYXJjYXRzVmlld01vZGVsID0gY2F0Vmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWw7XG4gICAgdmFyIGRpbWVuc2lvbk1vZGVsID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zW2NhdFZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25JbmRdO1xuXG4gICAgLy8gUG9zaXRpb25zXG4gICAgdmFyIGhvdmVyQ2VudGVyWSA9IHJlY3RCb3VuZGluZ0JveC50b3AgKyByZWN0Qm91bmRpbmdCb3guaGVpZ2h0IC8gMjtcbiAgICB2YXIgaG92ZXJDZW50ZXJYLFxuICAgICAgICBob3ZlckxhYmVsSWRlYWxBbGlnbjtcblxuICAgIGlmKHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucy5sZW5ndGggPiAxICYmXG4gICAgICAgIGRpbWVuc2lvbk1vZGVsLmRpc3BsYXlJbmQgPT09IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucy5sZW5ndGggLSAxKSB7XG5cbiAgICAgICAgLy8gcmlnaHQgbW9zdCBkaW1lbnNpb25cbiAgICAgICAgaG92ZXJDZW50ZXJYID0gcmVjdEJvdW5kaW5nQm94LmxlZnQ7XG4gICAgICAgIGhvdmVyTGFiZWxJZGVhbEFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvdmVyQ2VudGVyWCA9IHJlY3RCb3VuZGluZ0JveC5sZWZ0ICsgcmVjdEJvdW5kaW5nQm94LndpZHRoO1xuICAgICAgICBob3ZlckxhYmVsSWRlYWxBbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuXG4gICAgLy8gSG92ZXIgbGFiZWwgdGV4dFxuICAgIHZhciBob3ZlcmluZm9QYXJ0cyA9IFtdO1xuICAgIGlmKGNhdFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ2NvdW50JykgIT09IC0xKSB7XG4gICAgICAgIGhvdmVyaW5mb1BhcnRzLnB1c2goWydDb3VudDonLCBjYXRWaWV3TW9kZWwubW9kZWwuY291bnRdLmpvaW4oJyAnKSk7XG4gICAgfVxuICAgIGlmKGNhdFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3Byb2JhYmlsaXR5JykgIT09IC0xKSB7XG4gICAgICAgIGhvdmVyaW5mb1BhcnRzLnB1c2goW1xuICAgICAgICAgICAgJ1AoJyArIGNhdFZpZXdNb2RlbC5tb2RlbC5jYXRlZ29yeUxhYmVsICsgJyk6JyxcbiAgICAgICAgICAgIChjYXRWaWV3TW9kZWwubW9kZWwuY291bnQgLyBjYXRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudCkudG9GaXhlZCgzKV0uam9pbignICcpKTtcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJ0ZXh0ID0gaG92ZXJpbmZvUGFydHMuam9pbignPGJyPicpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IGhvdmVyQ2VudGVyWCAtIHJvb3RCQm94LmxlZnQsXG4gICAgICAgIHk6IGhvdmVyQ2VudGVyWSAtIHJvb3RCQm94LnRvcCxcbiAgICAgICAgdGV4dDogaG92ZXJ0ZXh0LFxuICAgICAgICBjb2xvcjogJ2xpZ2h0Z3JheScsXG4gICAgICAgIGJvcmRlckNvbG9yOiAnYmxhY2snLFxuICAgICAgICBmb250RmFtaWx5OiAnTW9uYWNvLCBcIkNvdXJpZXIgTmV3XCIsIG1vbm9zcGFjZScsXG4gICAgICAgIGZvbnRTaXplOiAxMixcbiAgICAgICAgZm9udENvbG9yOiAnYmxhY2snLFxuICAgICAgICBpZGVhbEFsaWduOiBob3ZlckxhYmVsSWRlYWxBbGlnblxuICAgIH07XG59XG5cbi8qKlxuICogQ3JlYXRlIGhvdmVyIGxhYmVsIGZvciBhIGJhbmQgZWxlbWVudCdzIGNhdGVnb3J5IChmb3IgdXNlIHdoZW4gaG92ZXJvbiA9PT0gJ2NhdGVnb3J5JylcbiAqXG4gKiBAcGFyYW0ge0NsaWVudFJlY3R9IHJvb3RCQm94XG4gKiAgQ2xpZW50IGJvdW5kaW5nIGJveCBmb3Igcm9vdCBvZiBmaWd1cmVcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBjcmVhdGVIb3ZlckxhYmVsRm9yRGltZW5zaW9uSG92ZXJtb2RlKHJvb3RCQm94LCBiYW5kRWxlbWVudCkge1xuXG4gICAgdmFyIGFsbEhvdmVybGFiZWxzID0gW107XG5cbiAgICBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlKVxuICAgICAgICAuc2VsZWN0QWxsKCdnLmNhdGVnb3J5JylcbiAgICAgICAgLnNlbGVjdCgncmVjdC5jYXRyZWN0JylcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgYmFuZE5vZGUgPSB0aGlzO1xuICAgICAgICAgICAgYWxsSG92ZXJsYWJlbHMucHVzaChjcmVhdGVIb3ZlckxhYmVsRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmROb2RlKSk7XG4gICAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGFsbEhvdmVybGFiZWxzO1xufVxuXG4vKipcbiAqIENyZWF0ZSBob3ZlciBsYWJlbHMgZm9yIGEgYmFuZCBlbGVtZW50J3MgY2F0ZWdvcnkgKGZvciB1c2Ugd2hlbiBob3Zlcm9uID09PSAnZGltZW5zaW9uJylcbiAqXG4gKiBAcGFyYW0ge0NsaWVudFJlY3R9IHJvb3RCQm94XG4gKiAgQ2xpZW50IGJvdW5kaW5nIGJveCBmb3Igcm9vdCBvZiBmaWd1cmVcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBjcmVhdGVIb3ZlckxhYmVsRm9yQ29sb3JIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KSB7XG5cbiAgICB2YXIgYmFuZEJvdW5kaW5nQm94ID0gYmFuZEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAvLyBNb2RlbHNcbiAgICAvKiogQHR5cGUge0NhdGVnb3J5QmFuZFZpZXdNb2RlbH0gKi9cbiAgICB2YXIgYmFuZFZpZXdNb2RlbCA9IGQzLnNlbGVjdChiYW5kRWxlbWVudCkuZGF0dW0oKTtcbiAgICB2YXIgY2F0Vmlld01vZGVsID0gYmFuZFZpZXdNb2RlbC5jYXRlZ29yeVZpZXdNb2RlbDtcbiAgICB2YXIgcGFyY2F0c1ZpZXdNb2RlbCA9IGNhdFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsO1xuICAgIHZhciBkaW1lbnNpb25Nb2RlbCA9IHBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9uc1tjYXRWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9uSW5kXTtcblxuICAgIC8vIHBvc2l0aW9uc1xuICAgIHZhciBob3ZlckNlbnRlclkgPSBiYW5kQm91bmRpbmdCb3gueSArIGJhbmRCb3VuZGluZ0JveC5oZWlnaHQgLyAyO1xuXG4gICAgdmFyIGhvdmVyQ2VudGVyWCxcbiAgICAgICAgaG92ZXJMYWJlbElkZWFsQWxpZ247XG4gICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgZGltZW5zaW9uTW9kZWwuZGlzcGxheUluZCA9PT0gcGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgLy8gcmlnaHQgbW9zdCBkaW1lbnNpb25cbiAgICAgICAgaG92ZXJDZW50ZXJYID0gYmFuZEJvdW5kaW5nQm94LmxlZnQ7XG4gICAgICAgIGhvdmVyTGFiZWxJZGVhbEFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvdmVyQ2VudGVyWCA9IGJhbmRCb3VuZGluZ0JveC5sZWZ0ICsgYmFuZEJvdW5kaW5nQm94LndpZHRoO1xuICAgICAgICBob3ZlckxhYmVsSWRlYWxBbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuXG4gICAgLy8gTGFiZWxzXG4gICAgdmFyIGNhdExhYmVsID0gY2F0Vmlld01vZGVsLm1vZGVsLmNhdGVnb3J5TGFiZWw7XG5cbiAgICAvLyBDb3VudHNcbiAgICB2YXIgdG90YWxDb3VudCA9IGJhbmRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudDtcblxuICAgIHZhciBiYW5kQ29sb3JDb3VudCA9IDA7XG4gICAgYmFuZFZpZXdNb2RlbC5jYXRlZ29yeVZpZXdNb2RlbC5iYW5kcy5mb3JFYWNoKGZ1bmN0aW9uKGIpIHtcbiAgICAgICAgaWYoYi5jb2xvciA9PT0gYmFuZFZpZXdNb2RlbC5jb2xvcikge1xuICAgICAgICAgICAgYmFuZENvbG9yQ291bnQgKz0gYi5jb3VudDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGNhdENvdW50ID0gY2F0Vmlld01vZGVsLm1vZGVsLmNvdW50O1xuXG4gICAgdmFyIGNvbG9yQ291bnQgPSAwO1xuICAgIHBhcmNhdHNWaWV3TW9kZWwucGF0aFNlbGVjdGlvbi5lYWNoKFxuICAgICAgICAvKiogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBwYXRoVmlld01vZGVsICovXG4gICAgICAgIGZ1bmN0aW9uKHBhdGhWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgIGlmKHBhdGhWaWV3TW9kZWwubW9kZWwuY29sb3IgPT09IGJhbmRWaWV3TW9kZWwuY29sb3IpIHtcbiAgICAgICAgICAgICAgICBjb2xvckNvdW50ICs9IHBhdGhWaWV3TW9kZWwubW9kZWwuY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgLy8gSG92ZXIgbGFiZWwgdGV4dFxuICAgIHZhciBob3ZlcmluZm9QYXJ0cyA9IFtdO1xuICAgIGlmKGNhdFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ2NvdW50JykgIT09IC0xKSB7XG4gICAgICAgIGhvdmVyaW5mb1BhcnRzLnB1c2goWydDb3VudDonLCBiYW5kQ29sb3JDb3VudF0uam9pbignICcpKTtcbiAgICB9XG4gICAgaWYoY2F0Vmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZigncHJvYmFiaWxpdHknKSAhPT0gLTEpIHtcbiAgICAgICAgdmFyIHBDb2xvckFuZENhdExhYmxlID0gJ1AoY29sb3Ig4oipICcgKyBjYXRMYWJlbCArICcpOiAnO1xuICAgICAgICB2YXIgcENvbG9yQW5kQ2F0VmFsdWUgPSAoYmFuZENvbG9yQ291bnQgLyB0b3RhbENvdW50KS50b0ZpeGVkKDMpO1xuICAgICAgICB2YXIgcENvbG9yQW5kQ2F0Um93ID0gcENvbG9yQW5kQ2F0TGFibGUgKyBwQ29sb3JBbmRDYXRWYWx1ZTtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaChwQ29sb3JBbmRDYXRSb3cpO1xuXG4gICAgICAgIHZhciBwQ2F0R2l2ZW5Db2xvckxhYmVsID0gJ1AoJyArIGNhdExhYmVsICsgJyB8IGNvbG9yKTogJztcbiAgICAgICAgdmFyIHBDYXRHaXZlbkNvbG9yVmFsdWUgPSAoYmFuZENvbG9yQ291bnQgLyBjb2xvckNvdW50KS50b0ZpeGVkKDMpO1xuICAgICAgICB2YXIgcENhdEdpdmVuQ29sb3JSb3cgPSBwQ2F0R2l2ZW5Db2xvckxhYmVsICsgcENhdEdpdmVuQ29sb3JWYWx1ZTtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaChwQ2F0R2l2ZW5Db2xvclJvdyk7XG5cbiAgICAgICAgdmFyIHBDb2xvckdpdmVuQ2F0TGFiZWwgPSAnUChjb2xvciB8ICcgKyBjYXRMYWJlbCArICcpOiAnO1xuICAgICAgICB2YXIgcENvbG9yR2l2ZW5DYXRWYWx1ZSA9IChiYW5kQ29sb3JDb3VudCAvIGNhdENvdW50KS50b0ZpeGVkKDMpO1xuICAgICAgICB2YXIgcENvbG9yR2l2ZW5DYXRSb3cgPSBwQ29sb3JHaXZlbkNhdExhYmVsICsgcENvbG9yR2l2ZW5DYXRWYWx1ZTtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaChwQ29sb3JHaXZlbkNhdFJvdyk7XG4gICAgfVxuXG4gICAgdmFyIGhvdmVydGV4dCA9IGhvdmVyaW5mb1BhcnRzLmpvaW4oJzxicj4nKTtcblxuICAgIC8vIENvbXB1dGUgdGV4dCBjb2xvclxuICAgIHZhciB0ZXh0Q29sb3IgPSB0aW55Y29sb3IubW9zdFJlYWRhYmxlKGJhbmRWaWV3TW9kZWwuY29sb3IsIFsnYmxhY2snLCAnd2hpdGUnXSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBob3ZlckNlbnRlclggLSByb290QkJveC5sZWZ0LFxuICAgICAgICB5OiBob3ZlckNlbnRlclkgLSByb290QkJveC50b3AsXG4gICAgICAgIC8vIG5hbWU6ICdOQU1FJyxcbiAgICAgICAgdGV4dDogaG92ZXJ0ZXh0LFxuICAgICAgICBjb2xvcjogYmFuZFZpZXdNb2RlbC5jb2xvcixcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdibGFjaycsXG4gICAgICAgIGZvbnRGYW1pbHk6ICdNb25hY28sIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlJyxcbiAgICAgICAgZm9udENvbG9yOiB0ZXh0Q29sb3IsXG4gICAgICAgIGZvbnRTaXplOiAxMCxcbiAgICAgICAgaWRlYWxBbGlnbjogaG92ZXJMYWJlbElkZWFsQWxpZ25cbiAgICB9O1xufVxuXG4vKipcbiAqIEhhbmRsZSBkaW1lbnNpb24gbW91c2VvdmVyXG4gKiBAcGFyYW0ge0NhdGVnb3J5QmFuZFZpZXdNb2RlbH0gYmFuZFZpZXdNb2RlbFxuICovXG5mdW5jdGlvbiBtb3VzZW92ZXJDYXRlZ29yeUJhbmQoYmFuZFZpZXdNb2RlbCkge1xuICAgIGlmKCFiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuZHJhZ0RpbWVuc2lvbikge1xuICAgICAgICAvLyBXZSdyZSBub3QgY3VycmVudGx5IGRyYWdnaW5nXG5cbiAgICAgICAgaWYoYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGhvdmVyaW5mbyBpcyBub3Qgc2tpcCwgc28gd2UgYXQgbGVhc3Qgc3R5bGUgdGhlIGJhbmRzIGFuZCBlbWl0IGludGVyYWN0aW9uIGV2ZW50c1xuXG4gICAgICAgICAgICAvLyBNb3VzZVxuICAgICAgICAgICAgdmFyIG1vdXNlWSA9IGQzLm1vdXNlKHRoaXMpWzFdO1xuICAgICAgICAgICAgaWYobW91c2VZIDwgLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBIb3ZlciBpcyBhYm92ZSBhYm92ZSB0aGUgY2F0ZWdvcnkgcmVjdGFuZ2xlIChwcm9iYWJseSB0aGUgZGltZW5zaW9uIHRpdGxlIHRleHQpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZ2QgPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXY7XG4gICAgICAgICAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICAgICAgdmFyIHJvb3RCQm94ID0gZnVsbExheW91dC5fcGFwZXJkaXYubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgdmFyIGhvdmVyb24gPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJvbjtcblxuICAgICAgICAgICAgLyoqIEB0eXBlIHtIVE1MRWxlbWVudH0gKi9cbiAgICAgICAgICAgIHZhciBiYW5kRWxlbWVudCA9IHRoaXM7XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBzdHlsZSBhbmQgZXZlbnRzXG4gICAgICAgICAgICBpZihob3Zlcm9uID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgc3R5bGVGb3JDb2xvckhvdmVybW9kZShiYW5kRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgZW1pdFBvaW50c0V2ZW50Q29sb3JIb3Zlcm1vZGUoYmFuZEVsZW1lbnQsICdwbG90bHlfaG92ZXInLCBkMy5ldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0eWxlRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUoYmFuZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENhdGVnb3J5SG92ZXJtb2RlKGJhbmRFbGVtZW50LCAncGxvdGx5X2hvdmVyJywgZDMuZXZlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIYW5kbGUgaG92ZXIgbGFiZWxcbiAgICAgICAgICAgIGlmKGJhbmRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdub25lJykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhvdmVySXRlbXM7XG4gICAgICAgICAgICAgICAgaWYoaG92ZXJvbiA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICAgICAgICAgICAgICBob3Zlckl0ZW1zID0gY3JlYXRlSG92ZXJMYWJlbEZvckNhdGVnb3J5SG92ZXJtb2RlKHJvb3RCQm94LCBiYW5kRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGhvdmVyb24gPT09ICdjb2xvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJJdGVtcyA9IGNyZWF0ZUhvdmVyTGFiZWxGb3JDb2xvckhvdmVybW9kZShyb290QkJveCwgYmFuZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihob3Zlcm9uID09PSAnZGltZW5zaW9uJykge1xuICAgICAgICAgICAgICAgICAgICBob3Zlckl0ZW1zID0gY3JlYXRlSG92ZXJMYWJlbEZvckRpbWVuc2lvbkhvdmVybW9kZShyb290QkJveCwgYmFuZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGhvdmVySXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgRngubXVsdGlIb3ZlcnMoaG92ZXJJdGVtcywge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dGVyQ29udGFpbmVyOiBmdWxsTGF5b3V0Ll9wYXBlci5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZDogZ2RcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5cbi8qKlxuICogSGFuZGxlIGRpbWVuc2lvbiBtb3VzZW92ZXJcbiAqIEBwYXJhbSB7Q2F0ZWdvcnlCYW5kVmlld01vZGVsfSBiYW5kVmlld01vZGVsXG4gKi9cbmZ1bmN0aW9uIG1vdXNlb3V0Q2F0ZWdvcnkoYmFuZFZpZXdNb2RlbCkge1xuXG4gICAgdmFyIHBhcmNhdHNWaWV3TW9kZWwgPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWw7XG5cbiAgICBpZighcGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uKSB7XG4gICAgICAgIC8vIFdlJ3JlIG5vdCBkcmFnZ2luZyBhbnl0aGluZ1xuXG4gICAgICAgIC8vIFJlc2V0IHVuaG92ZXJlZCBzdHlsZXNcbiAgICAgICAgc3R5bGVQYXRoc05vSG92ZXIocGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uKTtcbiAgICAgICAgc3R5bGVDYXRlZ29yaWVzTm9Ib3ZlcihwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvbi5zZWxlY3RBbGwoJ2cuY2F0ZWdvcnknKSk7XG4gICAgICAgIHN0eWxlQmFuZHNOb0hvdmVyKHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uU2VsZWN0aW9uLnNlbGVjdEFsbCgnZy5jYXRlZ29yeScpLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpKTtcblxuICAgICAgICAvLyBSZW1vdmUgaG92ZXIgbGFiZWxcbiAgICAgICAgRngubG9uZVVuaG92ZXIocGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5fZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuXG4gICAgICAgIC8vIFJlc3RvcmUgcGF0aCBvcmRlclxuICAgICAgICBwYXJjYXRzVmlld01vZGVsLnBhdGhTZWxlY3Rpb24uc29ydChjb21wYXJlUmF3Q29sb3IpO1xuXG4gICAgICAgIC8vIEVtaXQgdW5ob3ZlciBldmVudFxuICAgICAgICBpZihwYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcblxuICAgICAgICAgICAgdmFyIGhvdmVyb24gPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJvbjtcbiAgICAgICAgICAgIHZhciBiYW5kRWxlbWVudCA9IHRoaXM7XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBzdHlsZSBhbmQgZXZlbnRzXG4gICAgICAgICAgICBpZihob3Zlcm9uID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgZW1pdFBvaW50c0V2ZW50Q29sb3JIb3Zlcm1vZGUoYmFuZEVsZW1lbnQsICdwbG90bHlfdW5ob3ZlcicsIGQzLmV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZW1pdFBvaW50c0V2ZW50Q2F0ZWdvcnlIb3Zlcm1vZGUoYmFuZEVsZW1lbnQsICdwbG90bHlfdW5ob3ZlcicsIGQzLmV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG4vKipcbiAqIEhhbmRsZSBkaW1lbnNpb24gZHJhZyBzdGFydFxuICogQHBhcmFtIHtEaW1lbnNpb25WaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gZHJhZ0RpbWVuc2lvblN0YXJ0KGQpIHtcblxuICAgIC8vIENoZWNrIGlmIGRyYWdnaW5nIGlzIHN1cHBvcnRlZFxuICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ2ZpeGVkJykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gU2F2ZSBvZmYgaW5pdGlhbCBkcmFnIGluZGV4ZXMgZm9yIGRpbWVuc2lvblxuICAgIGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQgPSBkLm1vZGVsLmRpc3BsYXlJbmQ7XG4gICAgZC5pbml0aWFsRHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRzID0gZC5wYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnMubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5kaXNwbGF5SW5kO30pO1xuICAgIGQuZHJhZ0hhc01vdmVkID0gZmFsc2U7XG5cbiAgICAvLyBDaGVjayBmb3IgY2F0ZWdvcnkgaGl0XG4gICAgZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kID0gbnVsbDtcbiAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgLnNlbGVjdEFsbCgnZy5jYXRlZ29yeScpXG4gICAgICAgIC5zZWxlY3QoJ3JlY3QuY2F0cmVjdCcpXG4gICAgICAgIC5lYWNoKFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7Q2F0ZWdvcnlWaWV3TW9kZWx9IGNhdFZpZXdNb2RlbCAqL1xuICAgICAgICAgICAgZnVuY3Rpb24oY2F0Vmlld01vZGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhdE1vdXNlWCA9IGQzLm1vdXNlKHRoaXMpWzBdO1xuICAgICAgICAgICAgICAgIHZhciBjYXRNb3VzZVkgPSBkMy5tb3VzZSh0aGlzKVsxXTtcblxuXG4gICAgICAgICAgICAgICAgaWYoLTIgPD0gY2F0TW91c2VYICYmIGNhdE1vdXNlWCA8PSBjYXRWaWV3TW9kZWwud2lkdGggKyAyICYmXG4gICAgICAgICAgICAgICAgICAgIC0yIDw9IGNhdE1vdXNlWSAmJiBjYXRNb3VzZVkgPD0gY2F0Vmlld01vZGVsLmhlaWdodCArIDIpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTYXZlIG9mZiBpbml0aWFsIGRyYWcgaW5kZXhlcyBmb3IgY2F0ZWdvcmllc1xuICAgICAgICAgICAgICAgICAgICBkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgPSBjYXRWaWV3TW9kZWwubW9kZWwuZGlzcGxheUluZDtcbiAgICAgICAgICAgICAgICAgICAgZC5pbml0aWFsRHJhZ0NhdGVnb3J5RGlzcGxheUluZHMgPSBkLm1vZGVsLmNhdGVnb3JpZXMubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjLmRpc3BsYXlJbmQ7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgY2F0ZWdvcmllcyBkcmFnWSB0byBiZSB0aGUgY3VycmVudCB5IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNhdFZpZXdNb2RlbC5tb2RlbC5kcmFnWSA9IGNhdFZpZXdNb2RlbC55O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJhaXNlIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIExpYi5yYWlzZVRvVG9wKHRoaXMucGFyZW50Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IGJhbmQgZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcy5wYXJlbnROb2RlKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGJhbmRWaWV3TW9kZWwgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGJhbmRWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihiYW5kVmlld01vZGVsLnkgPCBjYXRNb3VzZVkgJiYgY2F0TW91c2VZIDw9IGJhbmRWaWV3TW9kZWwueSArIGJhbmRWaWV3TW9kZWwuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQucG90ZW50aWFsQ2xpY2tCYW5kID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSB0b3BsZXZlbCBkcmFnIGRpbWVuc2lvblxuICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uID0gZDtcblxuICAgIC8vIFJlbW92ZSBob3ZlciBsYWJlbCBpZiBhbnlcbiAgICBGeC5sb25lVW5ob3ZlcihkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpKTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIGRyYWdcbiAqIEBwYXJhbSB7RGltZW5zaW9uVmlld01vZGVsfSBkXG4gKi9cbmZ1bmN0aW9uIGRyYWdEaW1lbnNpb24oZCkge1xuXG4gICAgLy8gQ2hlY2sgaWYgZHJhZ2dpbmcgaXMgc3VwcG9ydGVkXG4gICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBkLmRyYWdIYXNNb3ZlZCA9IHRydWU7XG5cbiAgICBpZihkLmRyYWdEaW1lbnNpb25EaXNwbGF5SW5kID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgZHJhZ0RpbUluZCA9IGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQsXG4gICAgICAgIHByZXZEaW1JbmQgPSBkcmFnRGltSW5kIC0gMSxcbiAgICAgICAgbmV4dERpbUluZCA9IGRyYWdEaW1JbmQgKyAxO1xuXG4gICAgdmFyIGRyYWdEaW1lbnNpb24gPSBkLnBhcmNhdHNWaWV3TW9kZWxcbiAgICAgICAgLmRpbWVuc2lvbnNbZHJhZ0RpbUluZF07XG5cbiAgICAvLyBVcGRhdGUgY2F0ZWdvcnlcbiAgICBpZihkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgIT09IG51bGwpIHtcblxuICAgICAgICB2YXIgZHJhZ0NhdGVnb3J5ID0gZHJhZ0RpbWVuc2lvbi5jYXRlZ29yaWVzW2QuZHJhZ0NhdGVnb3J5RGlzcGxheUluZF07XG5cbiAgICAgICAgLy8gVXBkYXRlIGRyYWdZIGJ5IGR5XG4gICAgICAgIGRyYWdDYXRlZ29yeS5tb2RlbC5kcmFnWSArPSBkMy5ldmVudC5keTtcbiAgICAgICAgdmFyIGNhdGVnb3J5WSA9IGRyYWdDYXRlZ29yeS5tb2RlbC5kcmFnWTtcblxuICAgICAgICAvLyBDaGVjayBmb3IgY2F0ZWdvcnkgZHJhZyBzd2Fwc1xuICAgICAgICB2YXIgY2F0RGlzcGxheUluZCA9IGRyYWdDYXRlZ29yeS5tb2RlbC5kaXNwbGF5SW5kO1xuICAgICAgICB2YXIgZGltQ2F0ZWdvcnlWaWV3cyA9IGRyYWdEaW1lbnNpb24uY2F0ZWdvcmllcztcblxuICAgICAgICB2YXIgY2F0QWJvdmUgPSBkaW1DYXRlZ29yeVZpZXdzW2NhdERpc3BsYXlJbmQgLSAxXTtcbiAgICAgICAgdmFyIGNhdEJlbG93ID0gZGltQ2F0ZWdvcnlWaWV3c1tjYXREaXNwbGF5SW5kICsgMV07XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yIG92ZXJsYXAgYWJvdmVcbiAgICAgICAgaWYoY2F0QWJvdmUgIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICBpZihjYXRlZ29yeVkgPCAoY2F0QWJvdmUueSArIGNhdEFib3ZlLmhlaWdodCAvIDIuMCkpIHtcblxuICAgICAgICAgICAgICAgIC8vIFN3YXAgZGlzcGxheSBpbmRzXG4gICAgICAgICAgICAgICAgZHJhZ0NhdGVnb3J5Lm1vZGVsLmRpc3BsYXlJbmQgPSBjYXRBYm92ZS5tb2RlbC5kaXNwbGF5SW5kO1xuICAgICAgICAgICAgICAgIGNhdEFib3ZlLm1vZGVsLmRpc3BsYXlJbmQgPSBjYXREaXNwbGF5SW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoY2F0QmVsb3cgIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICBpZigoY2F0ZWdvcnlZICsgZHJhZ0NhdGVnb3J5LmhlaWdodCkgPiAoY2F0QmVsb3cueSArIGNhdEJlbG93LmhlaWdodCAvIDIuMCkpIHtcblxuICAgICAgICAgICAgICAgIC8vIFN3YXAgZGlzcGxheSBpbmRzXG4gICAgICAgICAgICAgICAgZHJhZ0NhdGVnb3J5Lm1vZGVsLmRpc3BsYXlJbmQgPSBjYXRCZWxvdy5tb2RlbC5kaXNwbGF5SW5kO1xuICAgICAgICAgICAgICAgIGNhdEJlbG93Lm1vZGVsLmRpc3BsYXlJbmQgPSBjYXREaXNwbGF5SW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhdGVnb3J5IGRyYWcgZGlzcGxheSBpbmRleFxuICAgICAgICBkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgPSBkcmFnQ2F0ZWdvcnkubW9kZWwuZGlzcGxheUluZDtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9uIHBvc2l0aW9uXG4gICAgaWYoZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kID09PSBudWxsIHx8IGQucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ2ZyZWVmb3JtJykge1xuICAgICAgICBkcmFnRGltZW5zaW9uLm1vZGVsLmRyYWdYID0gZDMuZXZlbnQueDtcblxuICAgICAgICAvLyBDaGVjayBmb3IgZGltZW5zaW9uIHN3YXBzXG4gICAgICAgIHZhciBwcmV2RGltZW5zaW9uID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbcHJldkRpbUluZF07XG4gICAgICAgIHZhciBuZXh0RGltZW5zaW9uID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbbmV4dERpbUluZF07XG5cbiAgICAgICAgaWYocHJldkRpbWVuc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihkcmFnRGltZW5zaW9uLm1vZGVsLmRyYWdYIDwgKHByZXZEaW1lbnNpb24ueCArIHByZXZEaW1lbnNpb24ud2lkdGgpKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBTd2FwIGRpc3BsYXkgaW5kc1xuICAgICAgICAgICAgICAgIGRyYWdEaW1lbnNpb24ubW9kZWwuZGlzcGxheUluZCA9IHByZXZEaW1lbnNpb24ubW9kZWwuZGlzcGxheUluZDtcbiAgICAgICAgICAgICAgICBwcmV2RGltZW5zaW9uLm1vZGVsLmRpc3BsYXlJbmQgPSBkcmFnRGltSW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYobmV4dERpbWVuc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZigoZHJhZ0RpbWVuc2lvbi5tb2RlbC5kcmFnWCArIGRyYWdEaW1lbnNpb24ud2lkdGgpID4gbmV4dERpbWVuc2lvbi54KSB7XG5cbiAgICAgICAgICAgICAgICAvLyBTd2FwIGRpc3BsYXkgaW5kc1xuICAgICAgICAgICAgICAgIGRyYWdEaW1lbnNpb24ubW9kZWwuZGlzcGxheUluZCA9IG5leHREaW1lbnNpb24ubW9kZWwuZGlzcGxheUluZDtcbiAgICAgICAgICAgICAgICBuZXh0RGltZW5zaW9uLm1vZGVsLmRpc3BsYXlJbmQgPSBkLmRyYWdEaW1lbnNpb25EaXNwbGF5SW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGRyYWcgZGlzcGxheSBpbmRleFxuICAgICAgICBkLmRyYWdEaW1lbnNpb25EaXNwbGF5SW5kID0gZHJhZ0RpbWVuc2lvbi5tb2RlbC5kaXNwbGF5SW5kO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSB2aWV3IG1vZGVsc1xuICAgIHVwZGF0ZURpbWVuc2lvblZpZXdNb2RlbHMoZC5wYXJjYXRzVmlld01vZGVsKTtcbiAgICB1cGRhdGVQYXRoVmlld01vZGVscyhkLnBhcmNhdHNWaWV3TW9kZWwpO1xuXG4gICAgLy8gVXBkYXRlIHN2ZyBnZW9tZXRyeVxuICAgIHVwZGF0ZVN2Z0NhdGVnb3JpZXMoZC5wYXJjYXRzVmlld01vZGVsKTtcbiAgICB1cGRhdGVTdmdQYXRocyhkLnBhcmNhdHNWaWV3TW9kZWwpO1xufVxuXG5cbi8qKlxuICogSGFuZGxlIGRpbWVuc2lvbiBkcmFnIGVuZFxuICogQHBhcmFtIHtEaW1lbnNpb25WaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gZHJhZ0RpbWVuc2lvbkVuZChkKSB7XG5cbiAgICAvLyBDaGVjayBpZiBkcmFnZ2luZyBpcyBzdXBwb3J0ZWRcbiAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuYXJyYW5nZW1lbnQgPT09ICdmaXhlZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3RleHQnKS5hdHRyKCdmb250LXdlaWdodCcsICdub3JtYWwnKTtcblxuICAgIC8vIENvbXB1dGUgcmVzdHlsZSBjb21tYW5kXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB2YXIgcmVzdHlsZURhdGEgPSB7fTtcbiAgICB2YXIgdHJhY2VJbmQgPSBnZXRUcmFjZUluZGV4KGQucGFyY2F0c1ZpZXdNb2RlbCk7XG5cbiAgICAvLyAjIyMgSGFuZGxlIGRpbWVuc2lvbiByZW9yZGVyaW5nICMjI1xuICAgIHZhciBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcyA9IGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zLm1hcChmdW5jdGlvbihkKSB7cmV0dXJuIGQuZGlzcGxheUluZDt9KTtcbiAgICB2YXIgYW55RGltc1Jlb3JkZXJlZCA9IGQuaW5pdGlhbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcy5zb21lKGZ1bmN0aW9uKGluaXREaW1EaXNwbGF5LCBkaW1JbmQpIHtcbiAgICAgICAgcmV0dXJuIGluaXREaW1EaXNwbGF5ICE9PSBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kc1tkaW1JbmRdO1xuICAgIH0pO1xuXG4gICAgaWYoYW55RGltc1Jlb3JkZXJlZCkge1xuICAgICAgICBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcy5mb3JFYWNoKGZ1bmN0aW9uKGZpbmFsRGltRGlzcGxheSwgZGltSW5kKSB7XG4gICAgICAgICAgICB2YXIgY29udGFpbmVySW5kID0gZC5wYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnNbZGltSW5kXS5jb250YWluZXJJbmQ7XG4gICAgICAgICAgICByZXN0eWxlRGF0YVsnZGltZW5zaW9uc1snICsgY29udGFpbmVySW5kICsgJ10uZGlzcGxheWluZGV4J10gPSBmaW5hbERpbURpc3BsYXk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vICMjIyBIYW5kbGUgY2F0ZWdvcnkgcmVvcmRlcmluZyAjIyNcbiAgICB2YXIgYW55Q2F0c1Jlb3JkZXJlZCA9IGZhbHNlO1xuICAgIGlmKGQuZHJhZ0NhdGVnb3J5RGlzcGxheUluZCAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgZmluYWxEcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kcyA9IGQubW9kZWwuY2F0ZWdvcmllcy5tYXAoZnVuY3Rpb24oYykge1xuICAgICAgICAgICAgcmV0dXJuIGMuZGlzcGxheUluZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYW55Q2F0c1Jlb3JkZXJlZCA9IGQuaW5pdGlhbERyYWdDYXRlZ29yeURpc3BsYXlJbmRzLnNvbWUoZnVuY3Rpb24oaW5pdENhdERpc3BsYXksIGNhdEluZCkge1xuICAgICAgICAgICAgcmV0dXJuIGluaXRDYXREaXNwbGF5ICE9PSBmaW5hbERyYWdDYXRlZ29yeURpc3BsYXlJbmRzW2NhdEluZF07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGFueUNhdHNSZW9yZGVyZWQpIHtcblxuICAgICAgICAgICAgLy8gU29ydCBhIHNoYWxsb3cgY29weSBvZiB0aGUgY2F0ZWdvcnkgbW9kZWxzIGJ5IGRpc3BsYXkgaW5kZXhcbiAgICAgICAgICAgIHZhciBzb3J0ZWRDYXRlZ29yeU1vZGVscyA9IGQubW9kZWwuY2F0ZWdvcmllcy5zbGljZSgpLnNvcnQoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYS5kaXNwbGF5SW5kIC0gYi5kaXNwbGF5SW5kOyB9KTtcblxuICAgICAgICAgICAgLy8gR2V0IG5ldyBjYXRlZ29yeWFycmF5IGFuZCB0aWNrdGV4dCB2YWx1ZXNcbiAgICAgICAgICAgIHZhciBuZXdDYXRlZ29yeUFycmF5ID0gc29ydGVkQ2F0ZWdvcnlNb2RlbHMubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYuY2F0ZWdvcnlWYWx1ZTsgfSk7XG4gICAgICAgICAgICB2YXIgbmV3Q2F0ZWdvcnlMYWJlbHMgPSBzb3J0ZWRDYXRlZ29yeU1vZGVscy5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gdi5jYXRlZ29yeUxhYmVsOyB9KTtcblxuICAgICAgICAgICAgcmVzdHlsZURhdGFbJ2RpbWVuc2lvbnNbJyArIGQubW9kZWwuY29udGFpbmVySW5kICsgJ10uY2F0ZWdvcnlhcnJheSddID0gW25ld0NhdGVnb3J5QXJyYXldO1xuICAgICAgICAgICAgcmVzdHlsZURhdGFbJ2RpbWVuc2lvbnNbJyArIGQubW9kZWwuY29udGFpbmVySW5kICsgJ10udGlja3RleHQnXSA9IFtuZXdDYXRlZ29yeUxhYmVsc107XG4gICAgICAgICAgICByZXN0eWxlRGF0YVsnZGltZW5zaW9uc1snICsgZC5tb2RlbC5jb250YWluZXJJbmQgKyAnXS5jYXRlZ29yeW9yZGVyJ10gPSAnYXJyYXknO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHBvdGVudGlhbCBjbGljayBldmVudFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignc2tpcCcpID09PSAtMSkge1xuICAgICAgICBpZighZC5kcmFnSGFzTW92ZWQgJiYgZC5wb3RlbnRpYWxDbGlja0JhbmQpIHtcbiAgICAgICAgICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5ob3Zlcm9uID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgZW1pdFBvaW50c0V2ZW50Q29sb3JIb3Zlcm1vZGUoZC5wb3RlbnRpYWxDbGlja0JhbmQsICdwbG90bHlfY2xpY2snLCBkMy5ldmVudC5zb3VyY2VFdmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENhdGVnb3J5SG92ZXJtb2RlKGQucG90ZW50aWFsQ2xpY2tCYW5kLCAncGxvdGx5X2NsaWNrJywgZDMuZXZlbnQuc291cmNlRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTnVsbGlmeSBkcmFnIHN0YXRlc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBkLm1vZGVsLmRyYWdYID0gbnVsbDtcbiAgICBpZihkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgIT09IG51bGwpIHtcbiAgICAgICAgdmFyIGRyYWdDYXRlZ29yeSA9IGQucGFyY2F0c1ZpZXdNb2RlbFxuICAgICAgICAgICAgLmRpbWVuc2lvbnNbZC5kcmFnRGltZW5zaW9uRGlzcGxheUluZF1cbiAgICAgICAgICAgIC5jYXRlZ29yaWVzW2QuZHJhZ0NhdGVnb3J5RGlzcGxheUluZF07XG5cbiAgICAgICAgZHJhZ0NhdGVnb3J5Lm1vZGVsLmRyYWdZID0gbnVsbDtcbiAgICAgICAgZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kID0gbnVsbDtcbiAgICB9XG5cbiAgICBkLmRyYWdEaW1lbnNpb25EaXNwbGF5SW5kID0gbnVsbDtcbiAgICBkLnBhcmNhdHNWaWV3TW9kZWwuZHJhZ0RpbWVuc2lvbiA9IG51bGw7XG4gICAgZC5kcmFnSGFzTW92ZWQgPSBudWxsO1xuICAgIGQucG90ZW50aWFsQ2xpY2tCYW5kID0gbnVsbDtcblxuICAgIC8vIFVwZGF0ZSB2aWV3IG1vZGVsc1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHVwZGF0ZURpbWVuc2lvblZpZXdNb2RlbHMoZC5wYXJjYXRzVmlld01vZGVsKTtcbiAgICB1cGRhdGVQYXRoVmlld01vZGVscyhkLnBhcmNhdHNWaWV3TW9kZWwpO1xuXG4gICAgLy8gUGVyZm9ybSB0cmFuc2l0aW9uXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIHRyYW5zaXRpb24gPSBkMy50cmFuc2l0aW9uKClcbiAgICAgICAgLmR1cmF0aW9uKDMwMClcbiAgICAgICAgLmVhc2UoJ2N1YmljLWluLW91dCcpO1xuXG4gICAgdHJhbnNpdGlvblxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHVwZGF0ZVN2Z0NhdGVnb3JpZXMoZC5wYXJjYXRzVmlld01vZGVsLCB0cnVlKTtcbiAgICAgICAgICAgIHVwZGF0ZVN2Z1BhdGhzKGQucGFyY2F0c1ZpZXdNb2RlbCwgdHJ1ZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmKGFueURpbXNSZW9yZGVyZWQgfHwgYW55Q2F0c1Jlb3JkZXJlZCkge1xuICAgICAgICAgICAgICAgIC8vIFBlcmZvcm0gcmVzdHlsZSBpZiB0aGUgb3JkZXIgb2YgY2F0ZWdvcmllcyBvciBkaW1lbnNpb25zIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBQbG90bHkucmVzdHlsZShkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYsIHJlc3R5bGVEYXRhLCBbdHJhY2VJbmRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICovXG5mdW5jdGlvbiBnZXRUcmFjZUluZGV4KHBhcmNhdHNWaWV3TW9kZWwpIHtcbiAgICB2YXIgdHJhY2VJbmQ7XG4gICAgdmFyIGFsbFRyYWNlcyA9IHBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYuX2Z1bGxEYXRhO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbGxUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5rZXkgPT09IGFsbFRyYWNlc1tpXS51aWQpIHtcbiAgICAgICAgICAgIHRyYWNlSW5kID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cmFjZUluZDtcbn1cblxuLyoqIFVwZGF0ZSB0aGUgc3ZnIHBhdGhzIGZvciB2aWV3IG1vZGVsXG4gKiBAcGFyYW0ge1BhcmNhdHNWaWV3TW9kZWx9IHBhcmNhdHNWaWV3TW9kZWxcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaGFzVHJhbnNpdGlvbiBXaGV0aGVyIHRvIHVwZGF0ZSBlbGVtZW50IHdpdGggdHJhbnNpdGlvblxuICovXG5mdW5jdGlvbiB1cGRhdGVTdmdQYXRocyhwYXJjYXRzVmlld01vZGVsLCBoYXNUcmFuc2l0aW9uKSB7XG5cbiAgICBpZihoYXNUcmFuc2l0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaGFzVHJhbnNpdGlvbiA9IGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zaXRpb24oc2VsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBoYXNUcmFuc2l0aW9uID8gc2VsZWN0aW9uLnRyYW5zaXRpb24oKSA6IHNlbGVjdGlvbjtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgYmluZGluZ1xuICAgIHBhcmNhdHNWaWV3TW9kZWwucGF0aFNlbGVjdGlvbi5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQucGF0aHM7XG4gICAgfSwga2V5KTtcblxuICAgIC8vIFVwZGF0ZSBwYXRoc1xuICAgIHRyYW5zaXRpb24ocGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uKS5hdHRyKCdkJywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZC5zdmdEO1xuICAgIH0pO1xufVxuXG4vKiogVXBkYXRlIHRoZSBzdmcgcGF0aHMgZm9yIHZpZXcgbW9kZWxcbiAqIEBwYXJhbSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogQHBhcmFtIHtib29sZWFufSBoYXNUcmFuc2l0aW9uIFdoZXRoZXIgdG8gdXBkYXRlIGVsZW1lbnQgd2l0aCB0cmFuc2l0aW9uXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVN2Z0NhdGVnb3JpZXMocGFyY2F0c1ZpZXdNb2RlbCwgaGFzVHJhbnNpdGlvbikge1xuXG4gICAgaWYoaGFzVHJhbnNpdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGhhc1RyYW5zaXRpb24gPSBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uKHNlbGVjdGlvbikge1xuICAgICAgICByZXR1cm4gaGFzVHJhbnNpdGlvbiA/IHNlbGVjdGlvbi50cmFuc2l0aW9uKCkgOiBzZWxlY3Rpb247XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIGJpbmRpbmdcbiAgICBwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvblxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5kaW1lbnNpb25zO30sIGtleSk7XG5cbiAgICB2YXIgY2F0ZWdvcnlTZWxlY3Rpb24gPSBwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvblxuICAgICAgICAuc2VsZWN0QWxsKCdnLmNhdGVnb3J5JylcbiAgICAgICAgLmRhdGEoZnVuY3Rpb24oZCkge3JldHVybiBkLmNhdGVnb3JpZXM7fSwga2V5KTtcblxuICAgIC8vIFVwZGF0ZSBkaW1lbnNpb24gcG9zaXRpb25cbiAgICB0cmFuc2l0aW9uKHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uU2VsZWN0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQueCArICcsIDApJztcbiAgICAgICAgfSk7XG5cbiAgICAvLyBVcGRhdGUgY2F0ZWdvcnkgcG9zaXRpb25cbiAgICB0cmFuc2l0aW9uKGNhdGVnb3J5U2VsZWN0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoMCwgJyArIGQueSArICcpJztcbiAgICAgICAgfSk7XG5cbiAgICB2YXIgZGltTGFiZWxTZWxlY3Rpb24gPSBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3QoJy5kaW1sYWJlbCcpO1xuXG4gICAgLy8gIyMjIFVwZGF0ZSBkaW1lbnNpb24gbGFiZWxcbiAgICAvLyBPbmx5IHRoZSB0b3AtbW9zdCBkaXNwbGF5IGNhdGVnb3J5IHNob3VsZCBoYXZlIHRoZSBkaW1lbnNpb24gbGFiZWxcbiAgICBkaW1MYWJlbFNlbGVjdGlvblxuICAgICAgICAudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICBpZihpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGRpbWVuc2lvbiBsYWJlbCBhYm92ZSB0b3Btb3N0IGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zW2QubW9kZWwuZGltZW5zaW9uSW5kXS5kaW1lbnNpb25MYWJlbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5IGxhYmVsXG4gICAgLy8gQ2F0ZWdvcmllcyBpbiB0aGUgcmlnaHQtbW9zdCBkaXNwbGF5IGRpbWVuc2lvbiBoYXZlIHRoZWlyIGxhYmVscyBvblxuICAgIC8vIHRoZSByaWdodCwgYWxsIG90aGVycyBvbiB0aGUgbGVmdFxuICAgIHZhciBjYXRMYWJlbFNlbGVjdGlvbiA9IGNhdGVnb3J5U2VsZWN0aW9uLnNlbGVjdCgnLmNhdGxhYmVsJyk7XG4gICAgY2F0TGFiZWxTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihjYXRJblJpZ2h0RGltKGQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSByaWdodCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3N0YXJ0JztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgbGVmdCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2VuZCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3gnLFxuICAgICAgICAgICAgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGlmKGNhdEluUmlnaHREaW0oZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIHJpZ2h0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkLndpZHRoICsgNTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgbGVmdCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgLy8gVXBkYXRlIGF0dHJpdWJ1dGVzIG9mIDx0c3Bhbj4gZWxlbWVudHNcbiAgICAgICAgICAgIHZhciBuZXdYO1xuICAgICAgICAgICAgdmFyIG5ld0FuY2hvcjtcbiAgICAgICAgICAgIGlmKGNhdEluUmlnaHREaW0oZCkpIHtcbiAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgcmlnaHQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICBuZXdYID0gZC53aWR0aCArIDU7XG4gICAgICAgICAgICAgICAgbmV3QW5jaG9yID0gJ3N0YXJ0JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIGxlZnQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICBuZXdYID0gLTU7XG4gICAgICAgICAgICAgICAgbmV3QW5jaG9yID0gJ2VuZCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCd0c3BhbicpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ3gnLCBuZXdYKVxuICAgICAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsIG5ld0FuY2hvcik7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlIGJhbmRzXG4gICAgLy8gSW5pdGlhbGl6ZSBjb2xvciBiYW5kIHJlY3RzXG4gICAgdmFyIGJhbmRTZWxlY3Rpb24gPSBjYXRlZ29yeVNlbGVjdGlvblxuICAgICAgICAuc2VsZWN0QWxsKCdyZWN0LmJhbmRyZWN0JylcbiAgICAgICAgLmRhdGEoXG4gICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0Vmlld01vZGVsKi9cbiAgICAgICAgICAgIGZ1bmN0aW9uKGNhdFZpZXdNb2RlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYXRWaWV3TW9kZWwuYmFuZHM7XG4gICAgICAgICAgICB9LCBrZXkpO1xuXG4gICAgdmFyIGJhbmRzU2VsZWN0aW9uRW50ZXIgPSBiYW5kU2VsZWN0aW9uLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdiYW5kcmVjdCcpXG4gICAgICAgIC5hdHRyKCdjdXJzb3InLCAnbW92ZScpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDApXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY29sb3I7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdmaWxsLW9wYWNpdHknLCAwKTtcblxuICAgIGJhbmRTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jb2xvcjtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQud2lkdGg7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5oZWlnaHQ7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQueTtcbiAgICAgICAgfSk7XG5cbiAgICBzdHlsZUJhbmRzTm9Ib3ZlcihiYW5kc1NlbGVjdGlvbkVudGVyKTtcblxuICAgIC8vIFJhaXNlIGJhbmRzIHRvIHRoZSB0b3BcbiAgICBiYW5kU2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oKSB7TGliLnJhaXNlVG9Ub3AodGhpcyk7fSk7XG5cbiAgICAvLyBSZW1vdmUgdW51c2VkIGJhbmRzXG4gICAgYmFuZFNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgUGFyY2F0c1ZpZXdNb2RlbCB0cmFjZXNcbiAqIEBwYXJhbSB7T2JqZWN0fSBncmFwaERpdlxuICogIFRvcC1sZXZlbCBncmFwaCBkaXYgZWxlbWVudFxuICogQHBhcmFtIHtMYXlvdXR9IGxheW91dFxuICogIFNWRyBsYXlvdXQgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5LjxQYXJjYXRzTW9kZWw+fSB3cmFwcGVkUGFyY2F0c01vZGVsXG4gKiAgV3JhcHBlZCBQYXJjYXRzTW9kZWwgZm9yIHRoaXMgdHJhY2VcbiAqIEByZXR1cm4ge1BhcmNhdHNWaWV3TW9kZWx9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBhcmNhdHNWaWV3TW9kZWwoZ3JhcGhEaXYsIGxheW91dCwgd3JhcHBlZFBhcmNhdHNNb2RlbCkge1xuICAgIC8vIFVud3JhcCBtb2RlbFxuICAgIHZhciBwYXJjYXRzTW9kZWwgPSB3cmFwcGVkUGFyY2F0c01vZGVsWzBdO1xuXG4gICAgLy8gQ29tcHV0ZSBtYXJnaW5cbiAgICB2YXIgbWFyZ2luID0gbGF5b3V0Lm1hcmdpbiB8fCB7bDogODAsIHI6IDgwLCB0OiAxMDAsIGI6IDgwfTtcblxuICAgIC8vIENvbXB1dGUgcGl4ZWwgcG9zaXRpb24vZXh0ZW50c1xuICAgIHZhciB0cmFjZSA9IHBhcmNhdHNNb2RlbC50cmFjZSxcbiAgICAgICAgZG9tYWluID0gdHJhY2UuZG9tYWluLFxuICAgICAgICBmaWd1cmVXaWR0aCA9IGxheW91dC53aWR0aCxcbiAgICAgICAgZmlndXJlSGVpZ2h0ID0gbGF5b3V0LmhlaWdodCxcbiAgICAgICAgdHJhY2VXaWR0aCA9IE1hdGguZmxvb3IoZmlndXJlV2lkdGggKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpLFxuICAgICAgICB0cmFjZUhlaWdodCA9IE1hdGguZmxvb3IoZmlndXJlSGVpZ2h0ICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pKSxcbiAgICAgICAgdHJhY2VYID0gZG9tYWluLnhbMF0gKiBmaWd1cmVXaWR0aCArIG1hcmdpbi5sLFxuICAgICAgICB0cmFjZVkgPSBsYXlvdXQuaGVpZ2h0IC0gZG9tYWluLnlbMV0gKiBsYXlvdXQuaGVpZ2h0ICsgbWFyZ2luLnQ7XG5cbiAgICAvLyBIYW5kbGUgcGF0aCBzaGFwZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIHBhdGhTaGFwZSA9IHRyYWNlLmxpbmUuc2hhcGU7XG5cbiAgICAvLyBIYW5kbGUgaG92ZXIgaW5mb1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIGhvdmVyaW5mb0l0ZW1zO1xuICAgIGlmKHRyYWNlLmhvdmVyaW5mbyA9PT0gJ2FsbCcpIHtcbiAgICAgICAgaG92ZXJpbmZvSXRlbXMgPSBbJ2NvdW50JywgJ3Byb2JhYmlsaXR5J107XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaG92ZXJpbmZvSXRlbXMgPSB0cmFjZS5ob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICB9XG5cbiAgICAvLyBDb25zdHJ1Y3QgcGFyY2F0c1ZpZXdNb2RlbFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIHBhcmNhdHNWaWV3TW9kZWwgPSB7XG4gICAgICAgIGtleTogdHJhY2UudWlkLFxuICAgICAgICBtb2RlbDogcGFyY2F0c01vZGVsLFxuICAgICAgICB4OiB0cmFjZVgsXG4gICAgICAgIHk6IHRyYWNlWSxcbiAgICAgICAgd2lkdGg6IHRyYWNlV2lkdGgsXG4gICAgICAgIGhlaWdodDogdHJhY2VIZWlnaHQsXG4gICAgICAgIGhvdmVyb246IHRyYWNlLmhvdmVyb24sXG4gICAgICAgIGhvdmVyaW5mb0l0ZW1zOiBob3ZlcmluZm9JdGVtcyxcbiAgICAgICAgYXJyYW5nZW1lbnQ6IHRyYWNlLmFycmFuZ2VtZW50LFxuICAgICAgICBidW5kbGVjb2xvcnM6IHRyYWNlLmJ1bmRsZWNvbG9ycyxcbiAgICAgICAgc29ydHBhdGhzOiB0cmFjZS5zb3J0cGF0aHMsXG4gICAgICAgIGxhYmVsZm9udDogdHJhY2UubGFiZWxmb250LFxuICAgICAgICBjYXRlZ29yeWxhYmVsZm9udDogdHJhY2UudGlja2ZvbnQsXG4gICAgICAgIHBhdGhTaGFwZTogcGF0aFNoYXBlLFxuICAgICAgICBkcmFnRGltZW5zaW9uOiBudWxsLFxuICAgICAgICBtYXJnaW46IG1hcmdpbixcbiAgICAgICAgcGF0aHM6IFtdLFxuICAgICAgICBkaW1lbnNpb25zOiBbXSxcbiAgICAgICAgZ3JhcGhEaXY6IGdyYXBoRGl2LFxuICAgICAgICB0cmFjZVNlbGVjdGlvbjogbnVsbCxcbiAgICAgICAgcGF0aFNlbGVjdGlvbjogbnVsbCxcbiAgICAgICAgZGltZW5zaW9uU2VsZWN0aW9uOiBudWxsXG4gICAgfTtcblxuICAgIC8vIFVwZGF0ZSBkaW1lbnNpb24gdmlldyBtb2RlbHMgaWYgd2UgaGF2ZSBhdCBsZWFzdCAxIGRpbWVuc2lvblxuICAgIGlmKHBhcmNhdHNNb2RlbC5kaW1lbnNpb25zKSB7XG4gICAgICAgIHVwZGF0ZURpbWVuc2lvblZpZXdNb2RlbHMocGFyY2F0c1ZpZXdNb2RlbCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHBhdGggdmlldyBtb2RlbHMgaWYgd2UgaGF2ZSBhdCBsZWFzdCAyIGRpbWVuc2lvbnNcbiAgICAgICAgdXBkYXRlUGF0aFZpZXdNb2RlbHMocGFyY2F0c1ZpZXdNb2RlbCk7XG4gICAgfVxuICAgIC8vIEluc2lkZSBhIGNhdGVnb3JpZXMgdmlldyBtb2RlbFxuICAgIHJldHVybiBwYXJjYXRzVmlld01vZGVsO1xufVxuXG4vKipcbiAqIEJ1aWxkIHRoZSBTVkcgc3RyaW5nIHRvIHJlcHJlc2VudHMgYSBwYXJhbGxlbCBjYXRlZ29yaWVzIHBhdGhcbiAqIEBwYXJhbSB7QXJyYXkuPE51bWJlcj59IGxlZnRYUG9zaXRpb25zXG4gKiAgQXJyYXkgb2YgdGhlIHggcG9zaXRpb25zIG9mIHRoZSBsZWZ0IGVkZ2Ugb2YgZWFjaCBkaW1lbnNpb24gKGluIGRpc3BsYXkgb3JkZXIpXG4gKiBAcGFyYW0ge0FycmF5LjxOdW1iZXI+fSBwYXRoWXNcbiAqICBBcnJheSBvZiB0aGUgeSBwb3NpdGlvbnMgb2YgdGhlIHRvcCBvZiB0aGUgcGF0aCBhdCBlYWNoIGRpbWVuc2lvbiAoaW4gZGlzcGxheSBvcmRlcilcbiAqIEBwYXJhbSB7QXJyYXkuPE51bWJlcj59IGRpbVdpZHRoc1xuICogIEFycmF5IG9mIHRoZSB3aWR0aHMgb2YgZWFjaCBkaW1lbnNpb24gaW4gZGlzcGxheSBvcmRlclxuICogQHBhcmFtIHtOdW1iZXJ9IHBhdGhIZWlnaHRcbiAqICBUaGUgaGVpZ2h0IG9mIHRoZSBwYXRoIGluIHBpeGVsc1xuICogQHBhcmFtIHtOdW1iZXJ9IGN1cnZhdHVyZVxuICogIFRoZSBjdXJ2YXR1cmUgZmFjdG9yIGZvciB0aGUgcGF0aC4gMCByZXN1bHRzIGluIGEgc3RyYWlnaHQgbGluZSBhbmQgdmFsdWVzIGdyZWF0ZXIgdGhhbiB6ZXJvIHJlc3VsdCBpbiBjdXJ2ZWQgcGF0aHNcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gYnVpbGRTdmdQYXRoKGxlZnRYUG9zaXRpb25zLCBwYXRoWXMsIGRpbVdpZHRocywgcGF0aEhlaWdodCwgY3VydmF0dXJlKSB7XG5cbiAgICAvLyBDb21wdXRlIHRoZSB4IG1pZHBvaW50IG9mIGVhY2ggcGF0aCBzZWdtZW50XG4gICAgdmFyIHhSZWZQb2ludHMxID0gW10sXG4gICAgICAgIHhSZWZQb2ludHMyID0gW10sXG4gICAgICAgIHJlZkludGVycG9sYXRvcixcbiAgICAgICAgZDtcblxuICAgIGZvcihkID0gMDsgZCA8IGRpbVdpZHRocy5sZW5ndGggLSAxOyBkKyspIHtcbiAgICAgICAgcmVmSW50ZXJwb2xhdG9yID0gZDMuaW50ZXJwb2xhdGVOdW1iZXIoZGltV2lkdGhzW2RdICsgbGVmdFhQb3NpdGlvbnNbZF0sIGxlZnRYUG9zaXRpb25zW2QgKyAxXSk7XG4gICAgICAgIHhSZWZQb2ludHMxLnB1c2gocmVmSW50ZXJwb2xhdG9yKGN1cnZhdHVyZSkpO1xuICAgICAgICB4UmVmUG9pbnRzMi5wdXNoKHJlZkludGVycG9sYXRvcigxIC0gY3VydmF0dXJlKSk7XG4gICAgfVxuXG4gICAgLy8gTW92ZSB0byB0b3Agb2YgcGF0aCBvbiBsZWZ0IGVkZ2Ugb2YgbGVmdC1tb3N0IGNhdGVnb3J5XG4gICAgdmFyIHN2Z0QgPSAnTSAnICsgbGVmdFhQb3NpdGlvbnNbMF0gKyAnLCcgKyBwYXRoWXNbMF07XG5cbiAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgIHN2Z0QgKz0gJ2wnICsgZGltV2lkdGhzWzBdICsgJywwICc7XG5cbiAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgIGZvcihkID0gMTsgZCA8IGRpbVdpZHRocy5sZW5ndGg7IGQrKykge1xuXG4gICAgICAgIC8vIEN1cnZlIHRvIGxlZnQgZWRnZSBvZiBjYXRlZ29yeVxuICAgICAgICBzdmdEICs9ICdDJyArIHhSZWZQb2ludHMxW2QgLSAxXSArICcsJyArIHBhdGhZc1tkIC0gMV0gK1xuICAgICAgICAgICAgICAnICcgKyB4UmVmUG9pbnRzMltkIC0gMV0gKyAnLCcgKyBwYXRoWXNbZF0gK1xuICAgICAgICAgICAgICAnICcgKyBsZWZ0WFBvc2l0aW9uc1tkXSArICcsJyArIHBhdGhZc1tkXTtcblxuICAgICAgICAvLyBzdmdEICs9ICdMJyArIGxlZnRYUG9zaXRpb25zW2RdICsgJywnICsgcGF0aFlzW2RdO1xuXG4gICAgICAgIC8vIEhvcml6b250YWwgbGluZSB0byByaWdodCBlZGdlXG4gICAgICAgIHN2Z0QgKz0gJ2wnICsgZGltV2lkdGhzW2RdICsgJywwICc7XG4gICAgfVxuXG4gICAgLy8gTGluZSBkb3duXG4gICAgc3ZnRCArPSAnbCcgKyAnMCwnICsgcGF0aEhlaWdodCArICcgJztcblxuICAgIC8vIExpbmUgdG8gbGVmdCBlZGdlIG9mIHJpZ2h0LW1vc3QgY2F0ZWdvcnlcbiAgICBzdmdEICs9ICdsIC0nICsgZGltV2lkdGhzW2RpbVdpZHRocy5sZW5ndGggLSAxXSArICcsMCAnO1xuXG4gICAgZm9yKGQgPSBkaW1XaWR0aHMubGVuZ3RoIC0gMjsgZCA+PSAwOyBkLS0pIHtcblxuICAgICAgICAvLyBDdXJ2ZSB0byByaWdodCBlZGdlIG9mIGNhdGVnb3J5XG4gICAgICAgIHN2Z0QgKz0gJ0MnICsgeFJlZlBvaW50czJbZF0gKyAnLCcgKyAocGF0aFlzW2QgKyAxXSArIHBhdGhIZWlnaHQpICtcbiAgICAgICAgICAgICAnICcgKyB4UmVmUG9pbnRzMVtkXSArICcsJyArIChwYXRoWXNbZF0gKyBwYXRoSGVpZ2h0KSArXG4gICAgICAgICAgICAgJyAnICsgKGxlZnRYUG9zaXRpb25zW2RdICsgZGltV2lkdGhzW2RdKSArICcsJyArIChwYXRoWXNbZF0gKyBwYXRoSGVpZ2h0KTtcblxuICAgICAgICAvLyBzdmdEICs9ICdMJyArIChsZWZ0WFBvc2l0aW9uc1tkXSArIGRpbVdpZHRoc1tkXSkgKyAnLCcgKyAocGF0aFlzW2RdICsgcGF0aEhlaWdodCk7XG5cbiAgICAgICAgLy8gSG9yaXpvbnRhbCBsaW5lIHRvIHJpZ2h0IGVkZ2VcbiAgICAgICAgc3ZnRCArPSAnbC0nICsgZGltV2lkdGhzW2RdICsgJywwICc7XG4gICAgfVxuXG4gICAgLy8gQ2xvc2UgcGF0aFxuICAgIHN2Z0QgKz0gJ1onO1xuICAgIHJldHVybiBzdmdEO1xufVxuXG4vKipcbiAqIFVwZGF0ZSB0aGUgcGF0aCB2aWV3IG1vZGVscyBiYXNlZCBvbiB0aGUgZGltZW5zaW9uIHZpZXcgbW9kZWxzIGluIGEgUGFyY2F0c1ZpZXdNb2RlbFxuICpcbiAqIEBwYXJhbSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFZpZXcgbW9kZWwgZm9yIHRyYWNlXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVBhdGhWaWV3TW9kZWxzKHBhcmNhdHNWaWV3TW9kZWwpIHtcblxuICAgIC8vIEluaXRpYWxpemUgYW4gYXJyYXkgb2YgdGhlIHkgcG9zaXRpb24gb2YgdGhlIHRvcCBvZiB0aGUgbmV4dCBwYXRoIHRvIGJlIGFkZGVkIHRvIGVhY2ggY2F0ZWdvcnkuXG4gICAgLy9cbiAgICAvLyBuZXh0WVBvc2l0aW9uc1tkXVtjXSBpcyB0aGUgeSBwb3NpdGlvbiBvZiB0aGUgbmV4dCBwYXRoIHRocm91Z2ggY2F0ZWdvcnkgd2l0aCBpbmRleCBjIG9mIGRpbWVuc2lvbiB3aXRoIGluZGV4IGRcbiAgICB2YXIgZGltZW5zaW9uVmlld01vZGVscyA9IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucztcbiAgICB2YXIgcGFyY2F0c01vZGVsID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbDtcbiAgICB2YXIgbmV4dFlQb3NpdGlvbnMgPSBkaW1lbnNpb25WaWV3TW9kZWxzLm1hcChcbiAgICAgICAgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY2F0ZWdvcmllcy5tYXAoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oYykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYy55O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgIC8vIEFycmF5IGZyb20gY2F0ZWdvcnkgaW5kZXggdG8gY2F0ZWdvcnkgZGlzcGxheSBpbmRleCBmb3IgZWFjaCB0cnVlIGRpbWVuc2lvbiBpbmRleFxuICAgIHZhciBjYXRUb0Rpc3BsYXlJbmRQZXJEaW0gPSBwYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnMubWFwKFxuICAgICAgICBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jYXRlZ29yaWVzLm1hcChmdW5jdGlvbihjKSB7cmV0dXJuIGMuZGlzcGxheUluZDt9KTtcbiAgICAgICAgfSk7XG5cbiAgICAvLyBBcnJheSBmcm9tIHRydWUgZGltZW5zaW9uIGluZGV4IHRvIGRpbWVuc2lvbiBkaXNwbGF5IGluZGV4XG4gICAgdmFyIGRpbVRvRGlzcGxheUluZCA9IHBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkLmRpc3BsYXlJbmQ7fSk7XG4gICAgdmFyIGRpc3BsYXlUb0RpbUluZCA9IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkLm1vZGVsLmRpbWVuc2lvbkluZDt9KTtcblxuICAgIC8vIEFycmF5IG9mIHRoZSB4IHBvc2l0aW9uIG9mIHRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIHJlY3RhbmdsZXMgZm9yIGVhY2ggZGltZW5zaW9uXG4gICAgdmFyIGxlZnRYUG9zaXRpb25zID0gZGltZW5zaW9uVmlld01vZGVscy5tYXAoXG4gICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLng7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gQ29tcHV0ZSBkaW1lbnNpb24gd2lkdGhzXG4gICAgdmFyIGRpbVdpZHRocyA9IGRpbWVuc2lvblZpZXdNb2RlbHMubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC53aWR0aDt9KTtcblxuICAgIC8vIEJ1aWxkIHNvcnRlZCBBcnJheSBvZiBQYXRoTW9kZWwgb2JqZWN0c1xuICAgIHZhciBwYXRoTW9kZWxzID0gW107XG4gICAgZm9yKHZhciBwIGluIHBhcmNhdHNNb2RlbC5wYXRocykge1xuICAgICAgICBpZihwYXJjYXRzTW9kZWwucGF0aHMuaGFzT3duUHJvcGVydHkocCkpIHtcbiAgICAgICAgICAgIHBhdGhNb2RlbHMucHVzaChwYXJjYXRzTW9kZWwucGF0aHNbcF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBjYXRlZ29yeSBkaXNwbGF5IGluZHMgdG8gdXNlIGZvciBzb3J0aW5nIHBhdGhzXG4gICAgZnVuY3Rpb24gcGF0aERpc3BsYXlDYXRlZ29yeUluZHMocGF0aE1vZGVsKSB7XG4gICAgICAgIHZhciBkaW1lbnNpb25JbmRzID0gcGF0aE1vZGVsLmNhdGVnb3J5SW5kcy5tYXAoZnVuY3Rpb24oY2F0SW5kLCBkaW1JbmQpIHtyZXR1cm4gY2F0VG9EaXNwbGF5SW5kUGVyRGltW2RpbUluZF1bY2F0SW5kXTt9KTtcbiAgICAgICAgdmFyIGRpc3BsYXlJbmRzID0gZGlzcGxheVRvRGltSW5kLm1hcChmdW5jdGlvbihkaW1JbmQpIHtcbiAgICAgICAgICAgIHJldHVybiBkaW1lbnNpb25JbmRzW2RpbUluZF07XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZGlzcGxheUluZHM7XG4gICAgfVxuXG4gICAgLy8gU29ydCBpbiBhc2NlbmRpbmcgb3JkZXIgYnkgZGlzcGxheSBpbmRleCBhcnJheVxuICAgIHBhdGhNb2RlbHMuc29ydChmdW5jdGlvbih2MSwgdjIpIHtcblxuICAgICAgICAvLyBCdWlsZCBkaXNwbGF5IGluZHMgZm9yIGVhY2ggcGF0aFxuICAgICAgICB2YXIgc29ydEFycmF5MSA9IHBhdGhEaXNwbGF5Q2F0ZWdvcnlJbmRzKHYxKTtcbiAgICAgICAgdmFyIHNvcnRBcnJheTIgPSBwYXRoRGlzcGxheUNhdGVnb3J5SW5kcyh2Mik7XG5cbiAgICAgICAgLy8gSGFuZGxlIHBhdGggc29ydCBvcmRlclxuICAgICAgICBpZihwYXJjYXRzVmlld01vZGVsLnNvcnRwYXRocyA9PT0gJ2JhY2t3YXJkJykge1xuICAgICAgICAgICAgc29ydEFycmF5MS5yZXZlcnNlKCk7XG4gICAgICAgICAgICBzb3J0QXJyYXkyLnJldmVyc2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFwcGVuZCB0aGUgZmlyc3QgdmFsdWUgaW5kZXggb2YgdGhlIHBhdGggdG8gYnJlYWsgdGllc1xuICAgICAgICBzb3J0QXJyYXkxLnB1c2godjEudmFsdWVJbmRzWzBdKTtcbiAgICAgICAgc29ydEFycmF5Mi5wdXNoKHYyLnZhbHVlSW5kc1swXSk7XG5cbiAgICAgICAgLy8gSGFuZGxlIGNvbG9yIGJ1bmRsaW5nXG4gICAgICAgIGlmKHBhcmNhdHNWaWV3TW9kZWwuYnVuZGxlY29sb3JzKSB7XG4gICAgICAgICAgICAvLyBQcmVwZW5kIHNvcnQgYXJyYXkgd2l0aCB0aGUgcmF3IGNvbG9yIHZhbHVlXG4gICAgICAgICAgICBzb3J0QXJyYXkxLnVuc2hpZnQodjEucmF3Q29sb3IpO1xuICAgICAgICAgICAgc29ydEFycmF5Mi51bnNoaWZ0KHYyLnJhd0NvbG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvbG9ycyBlcXVhbCwgc29ydCBieSBkaXNwbGF5IGNhdGVnb3JpZXNcbiAgICAgICAgaWYoc29ydEFycmF5MSA8IHNvcnRBcnJheTIpIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBpZihzb3J0QXJyYXkxID4gc29ydEFycmF5Mikge1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gMDtcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBwYXRoIG1vZGVsc1xuICAgIHZhciBwYXRoVmlld01vZGVscyA9IG5ldyBBcnJheShwYXRoTW9kZWxzLmxlbmd0aCksXG4gICAgICAgIHRvdGFsQ291bnQgPSBkaW1lbnNpb25WaWV3TW9kZWxzWzBdLm1vZGVsLmNvdW50LFxuICAgICAgICB0b3RhbEhlaWdodCA9IGRpbWVuc2lvblZpZXdNb2RlbHNbMF0uY2F0ZWdvcmllc1xuICAgICAgICAgICAgLm1hcChmdW5jdGlvbihjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGMuaGVpZ2h0O30pLnJlZHVjZShcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24odjEsIHYyKSB7cmV0dXJuIHYxICsgdjI7fSk7XG5cblxuICAgIGZvcih2YXIgcGF0aE51bWJlciA9IDA7IHBhdGhOdW1iZXIgPCBwYXRoTW9kZWxzLmxlbmd0aDsgcGF0aE51bWJlcisrKSB7XG4gICAgICAgIHZhciBwYXRoTW9kZWwgPSBwYXRoTW9kZWxzW3BhdGhOdW1iZXJdO1xuXG4gICAgICAgIHZhciBwYXRoSGVpZ2h0O1xuICAgICAgICBpZih0b3RhbENvdW50ID4gMCkge1xuICAgICAgICAgICAgcGF0aEhlaWdodCA9IHRvdGFsSGVpZ2h0ICogKHBhdGhNb2RlbC5jb3VudCAvIHRvdGFsQ291bnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGF0aEhlaWdodCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCdWlsZCBwYXRoIHkgY29vcmRzXG4gICAgICAgIHZhciBwYXRoWXMgPSBuZXcgQXJyYXkobmV4dFlQb3NpdGlvbnMubGVuZ3RoKTtcbiAgICAgICAgZm9yKHZhciBkID0gMDsgZCA8IHBhdGhNb2RlbC5jYXRlZ29yeUluZHMubGVuZ3RoOyBkKyspIHtcbiAgICAgICAgICAgIHZhciBjYXRJbmQgPSBwYXRoTW9kZWwuY2F0ZWdvcnlJbmRzW2RdO1xuICAgICAgICAgICAgdmFyIGNhdERpc3BsYXlJbmQgPSBjYXRUb0Rpc3BsYXlJbmRQZXJEaW1bZF1bY2F0SW5kXTtcbiAgICAgICAgICAgIHZhciBkaW1EaXNwbGF5SW5kID0gZGltVG9EaXNwbGF5SW5kW2RdO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgbmV4dCB5IHBvc2l0aW9uXG4gICAgICAgICAgICBwYXRoWXNbZGltRGlzcGxheUluZF0gPSBuZXh0WVBvc2l0aW9uc1tkaW1EaXNwbGF5SW5kXVtjYXREaXNwbGF5SW5kXTtcbiAgICAgICAgICAgIG5leHRZUG9zaXRpb25zW2RpbURpc3BsYXlJbmRdW2NhdERpc3BsYXlJbmRdICs9IHBhdGhIZWlnaHQ7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSBjYXRlZ29yeSBjb2xvciBpbmZvcm1hdGlvblxuICAgICAgICAgICAgdmFyIGNhdFZpZXdNb2RsZSA9IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uc1tkaW1EaXNwbGF5SW5kXS5jYXRlZ29yaWVzW2NhdERpc3BsYXlJbmRdO1xuICAgICAgICAgICAgdmFyIG51bUJhbmRzID0gY2F0Vmlld01vZGxlLmJhbmRzLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBsYXN0Q2F0QmFuZCA9IGNhdFZpZXdNb2RsZS5iYW5kc1tudW1CYW5kcyAtIDFdO1xuXG4gICAgICAgICAgICBpZihsYXN0Q2F0QmFuZCA9PT0gdW5kZWZpbmVkIHx8IHBhdGhNb2RlbC5yYXdDb2xvciAhPT0gbGFzdENhdEJhbmQucmF3Q29sb3IpIHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBuZXcgYmFuZFxuICAgICAgICAgICAgICAgIHZhciBiYW5kWSA9IGxhc3RDYXRCYW5kID09PSB1bmRlZmluZWQgPyAwIDogbGFzdENhdEJhbmQueSArIGxhc3RDYXRCYW5kLmhlaWdodDtcbiAgICAgICAgICAgICAgICBjYXRWaWV3TW9kbGUuYmFuZHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGtleTogYmFuZFksXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBwYXRoTW9kZWwuY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIHJhd0NvbG9yOiBwYXRoTW9kZWwucmF3Q29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogcGF0aEhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGNhdFZpZXdNb2RsZS53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgY291bnQ6IHBhdGhNb2RlbC5jb3VudCxcbiAgICAgICAgICAgICAgICAgICAgeTogYmFuZFksXG4gICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5Vmlld01vZGVsOiBjYXRWaWV3TW9kbGUsXG4gICAgICAgICAgICAgICAgICAgIHBhcmNhdHNWaWV3TW9kZWw6IHBhcmNhdHNWaWV3TW9kZWxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRXh0ZW5kIGN1cnJlbnQgYmFuZFxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50QmFuZCA9IGNhdFZpZXdNb2RsZS5iYW5kc1tudW1CYW5kcyAtIDFdO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCYW5kLmhlaWdodCArPSBwYXRoSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCYW5kLmNvdW50ICs9IHBhdGhNb2RlbC5jb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJ1aWxkIHN2ZyBwYXRoXG4gICAgICAgIHZhciBzdmdEO1xuICAgICAgICBpZihwYXJjYXRzVmlld01vZGVsLnBhdGhTaGFwZSA9PT0gJ2hzcGxpbmUnKSB7XG4gICAgICAgICAgICBzdmdEID0gYnVpbGRTdmdQYXRoKGxlZnRYUG9zaXRpb25zLCBwYXRoWXMsIGRpbVdpZHRocywgcGF0aEhlaWdodCwgMC41KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN2Z0QgPSBidWlsZFN2Z1BhdGgobGVmdFhQb3NpdGlvbnMsIHBhdGhZcywgZGltV2lkdGhzLCBwYXRoSGVpZ2h0LCAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhdGhWaWV3TW9kZWxzW3BhdGhOdW1iZXJdID0ge1xuICAgICAgICAgICAga2V5OiBwYXRoTW9kZWwudmFsdWVJbmRzWzBdLFxuICAgICAgICAgICAgbW9kZWw6IHBhdGhNb2RlbCxcbiAgICAgICAgICAgIGhlaWdodDogcGF0aEhlaWdodCxcbiAgICAgICAgICAgIGxlZnRYczogbGVmdFhQb3NpdGlvbnMsXG4gICAgICAgICAgICB0b3BZczogcGF0aFlzLFxuICAgICAgICAgICAgZGltV2lkdGhzOiBkaW1XaWR0aHMsXG4gICAgICAgICAgICBzdmdEOiBzdmdELFxuICAgICAgICAgICAgcGFyY2F0c1ZpZXdNb2RlbDogcGFyY2F0c1ZpZXdNb2RlbFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHBhcmNhdHNWaWV3TW9kZWwucGF0aHMgPSBwYXRoVmlld01vZGVscztcblxuIC8vICogQHByb3BlcnR5IGtleVxuIC8vICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAvLyAqIEBwcm9wZXJ0eSB7UGF0aE1vZGVsfSBtb2RlbFxuIC8vICogIFNvdXJjZSBwYXRoIG1vZGVsXG4gLy8gKiBAcHJvcGVydHkge051bWJlcn0gaGVpZ2h0XG4gLy8gKiAgSGVpZ2h0IG9mIHRoaXMgcGF0aCAocGl4ZWxzKVxuIC8vICogQHByb3BlcnR5IHtTdHJpbmd9IHN2Z0RcbiAvLyAqICBTVkcgcGF0aCBcImRcIiBhdHRyaWJ1dGUgc3RyaW5nXG59XG5cbi8qKlxuICogVXBkYXRlIHRoZSBkaW1lbnNpb24gdmlldyBtb2RlbHMgYmFzZWQgb24gdGhlIGRpbWVuc2lvbiBtb2RlbHMgaW4gYSBQYXJjYXRzVmlld01vZGVsXG4gKlxuICogQHBhcmFtIHtQYXJjYXRzVmlld01vZGVsfSBwYXJjYXRzVmlld01vZGVsXG4gKiAgVmlldyBtb2RlbCBmb3IgdHJhY2VcbiAqL1xuZnVuY3Rpb24gdXBkYXRlRGltZW5zaW9uVmlld01vZGVscyhwYXJjYXRzVmlld01vZGVsKSB7XG5cbiAgICAvLyBDb21wdXRlIGRpbWVuc2lvbiBvcmRlcmluZ1xuICAgIHZhciBkaW1lbnNpb25zSW5kSW5mbyA9IHBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4ge2Rpc3BsYXlJbmQ6IGQuZGlzcGxheUluZCwgZGltZW5zaW9uSW5kOiBkLmRpbWVuc2lvbkluZH07XG4gICAgfSk7XG5cbiAgICBkaW1lbnNpb25zSW5kSW5mby5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEuZGlzcGxheUluZCAtIGIuZGlzcGxheUluZDtcbiAgICB9KTtcblxuICAgIHZhciBkaW1lbnNpb25zID0gW107XG4gICAgZm9yKHZhciBkaXNwbGF5SW5kIGluIGRpbWVuc2lvbnNJbmRJbmZvKSB7XG4gICAgICAgIHZhciBkaW1lbnNpb25JbmQgPSBkaW1lbnNpb25zSW5kSW5mb1tkaXNwbGF5SW5kXS5kaW1lbnNpb25JbmQ7XG4gICAgICAgIHZhciBkaW1Nb2RlbCA9IHBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9uc1tkaW1lbnNpb25JbmRdO1xuICAgICAgICBkaW1lbnNpb25zLnB1c2goY3JlYXRlRGltZW5zaW9uVmlld01vZGVsKHBhcmNhdHNWaWV3TW9kZWwsIGRpbU1vZGVsKSk7XG4gICAgfVxuXG4gICAgcGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zID0gZGltZW5zaW9ucztcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBwYXJjYXRzIERpbWVuc2lvblZpZXdNb2RlbFxuICpcbiAqIEBwYXJhbSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFZpZXcgbW9kZWwgZm9yIHRyYWNlXG4gKiBAcGFyYW0ge0RpbWVuc2lvbk1vZGVsfSBkaW1lbnNpb25Nb2RlbFxuICogQHJldHVybiB7RGltZW5zaW9uVmlld01vZGVsfVxuICovXG5mdW5jdGlvbiBjcmVhdGVEaW1lbnNpb25WaWV3TW9kZWwocGFyY2F0c1ZpZXdNb2RlbCwgZGltZW5zaW9uTW9kZWwpIHtcblxuICAgIC8vIENvbXB1dGUgZGltZW5zaW9uIHggcG9zaXRpb25cbiAgICB2YXIgY2F0ZWdvcnlMYWJlbFBhZCA9IDQwLFxuICAgICAgICBkaW1XaWR0aCA9IDE2LFxuICAgICAgICBudW1EaW1lbnNpb25zID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zLmxlbmd0aCxcbiAgICAgICAgZGlzcGxheUluZCA9IGRpbWVuc2lvbk1vZGVsLmRpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIHggY29vcmRpbmF0ZSB2YWx1ZXNcbiAgICB2YXIgZGltRHgsXG4gICAgICAgIGRpbVgwLFxuICAgICAgICBkaW1YO1xuXG4gICAgaWYobnVtRGltZW5zaW9ucyA+IDEpIHtcbiAgICAgICAgZGltRHggPSAocGFyY2F0c1ZpZXdNb2RlbC53aWR0aCAtIDIgKiBjYXRlZ29yeUxhYmVsUGFkIC0gZGltV2lkdGgpIC8gKG51bURpbWVuc2lvbnMgLSAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkaW1EeCA9IDA7XG4gICAgfVxuICAgIGRpbVgwID0gY2F0ZWdvcnlMYWJlbFBhZDtcbiAgICBkaW1YID0gZGltWDAgKyBkaW1EeCAqIGRpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIGNhdGVnb3JpZXNcbiAgICB2YXIgY2F0ZWdvcmllcyA9IFtdLFxuICAgICAgICBtYXhDYXRzID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5tYXhDYXRzLFxuICAgICAgICBudW1DYXRzID0gZGltZW5zaW9uTW9kZWwuY2F0ZWdvcmllcy5sZW5ndGgsXG4gICAgICAgIGNhdFNwYWNpbmcgPSA4LFxuICAgICAgICB0b3RhbENvdW50ID0gZGltZW5zaW9uTW9kZWwuY291bnQsXG4gICAgICAgIHRvdGFsSGVpZ2h0ID0gcGFyY2F0c1ZpZXdNb2RlbC5oZWlnaHQgLSBjYXRTcGFjaW5nICogKG1heENhdHMgLSAxKSxcbiAgICAgICAgbmV4dENhdEhlaWdodCxcbiAgICAgICAgbmV4dENhdE1vZGVsLFxuICAgICAgICBuZXh0Q2F0LFxuICAgICAgICBjYXRJbmQsXG4gICAgICAgIGNhdERpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIHN0YXJ0aW5nIFkgb2Zmc2V0XG4gICAgdmFyIG5leHRDYXRZID0gKG1heENhdHMgLSBudW1DYXRzKSAqIGNhdFNwYWNpbmcgLyAyLjA7XG5cbiAgICAvLyBDb21wdXRlIGNhdGVnb3J5IG9yZGVyaW5nXG4gICAgdmFyIGNhdGVnb3J5SW5kSW5mbyA9IGRpbWVuc2lvbk1vZGVsLmNhdGVnb3JpZXMubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIHtkaXNwbGF5SW5kOiBjLmRpc3BsYXlJbmQsIGNhdGVnb3J5SW5kOiBjLmNhdGVnb3J5SW5kfTtcbiAgICB9KTtcblxuICAgIGNhdGVnb3J5SW5kSW5mby5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEuZGlzcGxheUluZCAtIGIuZGlzcGxheUluZDtcbiAgICB9KTtcblxuICAgIGZvcihjYXREaXNwbGF5SW5kID0gMDsgY2F0RGlzcGxheUluZCA8IG51bUNhdHM7IGNhdERpc3BsYXlJbmQrKykge1xuICAgICAgICBjYXRJbmQgPSBjYXRlZ29yeUluZEluZm9bY2F0RGlzcGxheUluZF0uY2F0ZWdvcnlJbmQ7XG4gICAgICAgIG5leHRDYXRNb2RlbCA9IGRpbWVuc2lvbk1vZGVsLmNhdGVnb3JpZXNbY2F0SW5kXTtcblxuICAgICAgICBpZih0b3RhbENvdW50ID4gMCkge1xuICAgICAgICAgICAgbmV4dENhdEhlaWdodCA9IChuZXh0Q2F0TW9kZWwuY291bnQgLyB0b3RhbENvdW50KSAqIHRvdGFsSGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV4dENhdEhlaWdodCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0Q2F0ID0ge1xuICAgICAgICAgICAga2V5OiBuZXh0Q2F0TW9kZWwudmFsdWVJbmRzWzBdLFxuICAgICAgICAgICAgbW9kZWw6IG5leHRDYXRNb2RlbCxcbiAgICAgICAgICAgIHdpZHRoOiBkaW1XaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogbmV4dENhdEhlaWdodCxcbiAgICAgICAgICAgIHk6IG5leHRDYXRNb2RlbC5kcmFnWSAhPT0gbnVsbCA/IG5leHRDYXRNb2RlbC5kcmFnWSA6IG5leHRDYXRZLFxuICAgICAgICAgICAgYmFuZHM6IFtdLFxuICAgICAgICAgICAgcGFyY2F0c1ZpZXdNb2RlbDogcGFyY2F0c1ZpZXdNb2RlbFxuICAgICAgICB9O1xuXG4gICAgICAgIG5leHRDYXRZID0gbmV4dENhdFkgKyBuZXh0Q2F0SGVpZ2h0ICsgY2F0U3BhY2luZztcbiAgICAgICAgY2F0ZWdvcmllcy5wdXNoKG5leHRDYXQpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleTogZGltZW5zaW9uTW9kZWwuZGltZW5zaW9uSW5kLFxuICAgICAgICB4OiBkaW1lbnNpb25Nb2RlbC5kcmFnWCAhPT0gbnVsbCA/IGRpbWVuc2lvbk1vZGVsLmRyYWdYIDogZGltWCxcbiAgICAgICAgeTogMCxcbiAgICAgICAgd2lkdGg6IGRpbVdpZHRoLFxuICAgICAgICBtb2RlbDogZGltZW5zaW9uTW9kZWwsXG4gICAgICAgIGNhdGVnb3JpZXM6IGNhdGVnb3JpZXMsXG4gICAgICAgIHBhcmNhdHNWaWV3TW9kZWw6IHBhcmNhdHNWaWV3TW9kZWwsXG4gICAgICAgIGRyYWdDYXRlZ29yeURpc3BsYXlJbmQ6IG51bGwsXG4gICAgICAgIGRyYWdEaW1lbnNpb25EaXNwbGF5SW5kOiBudWxsLFxuICAgICAgICBpbml0aWFsRHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRzOiBudWxsLFxuICAgICAgICBpbml0aWFsRHJhZ0NhdGVnb3J5RGlzcGxheUluZHM6IG51bGwsXG4gICAgICAgIGRyYWdIYXNNb3ZlZDogbnVsbCxcbiAgICAgICAgcG90ZW50aWFsQ2xpY2tCYW5kOiBudWxsXG4gICAgfTtcbn1cblxuLy8gSlNEb2MgdHlwZWRlZnNcbi8vID09PT09PT09PT09PT09XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IExheW91dFxuICogIE9iamVjdCBjb250YWluaW5nIHN2ZyBsYXlvdXQgaW5mb3JtYXRpb25cbiAqXG4gKiBAcHJvcGVydHkge051bWJlcn0gd2lkdGggKHBpeGVscylcbiAqICBVc2FibGUgd2lkdGggZm9yIEZpZ3VyZSAoYWZ0ZXIgbWFyZ2lucyBhcmUgcmVtb3ZlZClcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHQgKHBpeGVscylcbiAqICBVc2FibGUgaGVpZ2h0IGZvciBGaWd1cmUgKGFmdGVyIG1hcmdpbnMgYXJlIHJlbW92ZWQpXG4gKiBAcHJvcGVydHkge01hcmdpbn0gbWFyZ2luXG4gKiAgTWFyZ2luIGFyb3VuZCB0aGUgRmlndXJlIChwaXhlbHMpXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNYXJnaW5cbiAqICBPYmplY3QgY29udGFpbmluZyBwYWRkaW5nIGluZm9ybWF0aW9uIGluIHBpeGVsc1xuICpcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB0XG4gKiAgVG9wIG1hcmdpblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHJcbiAqICBSaWdodCBtYXJnaW5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBiXG4gKiAgQm90dG9tIG1hcmdpblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGxcbiAqICBMZWZ0IG1hcmdpblxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gRm9udFxuICogIE9iamVjdCBjb250YWluaW5nIGZvbnQgaW5mb3JtYXRpb25cbiAqXG4gKiBAcHJvcGVydHkge051bWJlcn0gc2l6ZTogRm9udCBzaXplXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sb3I6IEZvbnQgY29sb3JcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBmYW1pbHk6IEZvbnQgZmFtaWx5XG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQYXJjYXRzVmlld01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBwYXJjYXRzIHZpZXcgaW5mb3JtYXRpb25cbiAqXG4gKiAgVGhlc2UgYXJlIHF1YW50aXRpZXMgdGhhdCByZXF1aXJlIExheW91dCBpbmZvcm1hdGlvbiB0byBjYWxjdWxhdGVcbiAqIEBwcm9wZXJ0eSBrZXlcbiAqICBVbmlxdWUga2V5IGZvciB0aGlzIG1vZGVsXG4gKiBAcHJvcGVydHkge1BhcmNhdHNNb2RlbH0gbW9kZWxcbiAqICBTb3VyY2UgcGFyY2F0cyBtb2RlbFxuICogQHByb3BlcnR5IHtBcnJheS48RGltZW5zaW9uVmlld01vZGVsPn0gZGltZW5zaW9uc1xuICogIEFycmF5IG9mIGRpbWVuc2lvbiB2aWV3IG1vZGVsc1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgV2lkdGggZm9yIHRoaXMgdHJhY2UgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHRcbiAqICBIZWlnaHQgZm9yIHRoaXMgdHJhY2UgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB4XG4gKiAgWCBwb3NpdGlvbiBvZiB0aGlzIHRyYWNlIHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0geVxuICogIFkgcG9zaXRpb24gb2YgdGhpcyB0cmFjZSB3aXRoIHJlc3BlY3QgdG8gdGhlIEZpZ3VyZSAocGl4ZWxzKVxuICogQHByb3BlcnR5IHtTdHJpbmd9IGhvdmVyb25cbiAqICBIb3ZlciBpbnRlcmFjdGlvbiBtb2RlLiBPbmUgb2Y6ICdjYXRlZ29yeScsICdjb2xvcicsIG9yICdkaW1lbnNpb24nXG4gKiBAcHJvcGVydHkge0FycmF5LjxTdHJpbmc+fSBob3ZlcmluZm9JdGVtc1xuICogIEluZm8gdG8gZGlzcGxheSBvbiBob3Zlci4gQXJyYXkgd2l0aCBhIGNvbWJpbmF0aW9uIG9mICdjb3VudHMnIGFuZC9vciAncHJvYmFiaWxpdGllcycsIG9yICdub25lJywgb3IgJ3NraXAnXG4gKiBAcHJvcGVydHkge1N0cmluZ30gYXJyYW5nZW1lbnRcbiAqICBDYXRlZ29yeSBhcnJhbmdlbWVudC4gT25lIG9mOiAncGVycGVuZGljdWxhcicsICdmcmVlZm9ybScsIG9yICdmaXhlZCdcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gYnVuZGxlY29sb3JzXG4gKiAgV2hldGhlciBwYXRocyBzaG91bGQgYmUgc29ydGVkIHNvIHRoYXQgbGlrZSBjb2xvcnMgYXJlIGJ1bmRsZWQgdG9nZXRoZXIgYXMgdGhleSBwYXNzIHRocm91Z2ggY2F0ZWdvcmllc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHNvcnRwYXRoc1xuICogIElmICdmb3J3YXJkJyB0aGVuIHNvcnQgcGF0aHMgYmFzZWQgb24gZGltZW5zaW9ucyBmcm9tIGxlZnQgdG8gcmlnaHQuIElmICdiYWNrd2FyZCcgc29ydCBiYXNlZCBvbiBkaW1lbnNpb25zXG4gKiAgZnJvbSByaWdodCB0byBsZWZ0XG4gKiBAcHJvcGVydHkge0ZvbnR9IGxhYmVsZm9udFxuICogIEZvbnQgZm9yIHRoZSBkaW1lbnNpb24gbGFiZWxzXG4gKiBAcHJvcGVydHkge0ZvbnR9IGNhdGVnb3J5bGFiZWxmb250XG4gKiAgRm9udCBmb3IgdGhlIGNhdGVnb3J5IGxhYmVsc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHBhdGhTaGFwZVxuICogIFRoZSBzaGFwZSBvZiB0aGUgcGF0aHMuIEVpdGhlciAnbGluZWFyJyBvciAnaHNwbGluZScuXG4gKiBAcHJvcGVydHkge0RpbWVuc2lvblZpZXdNb2RlbHxudWxsfSBkcmFnRGltZW5zaW9uXG4gKiAgRGltZW5zaW9uIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiBOdWxsIGlmIG5vIGRyYWcgaW4gcHJvZ3Jlc3NcbiAqIEBwcm9wZXJ0eSB7TWFyZ2lufSBtYXJnaW5cbiAqICBNYXJnaW4gYXJvdW5kIHRoZSBGaWd1cmVcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBncmFwaERpdlxuICogIFRvcC1sZXZlbCBncmFwaCBkaXYgZWxlbWVudFxuICogQHByb3BlcnR5IHtPYmplY3R9IHRyYWNlU2VsZWN0aW9uXG4gKiAgRDMgc2VsZWN0aW9uIG9mIHRoaXMgdmlldyBtb2RlbHMgdHJhY2UgZ3JvdXAgZWxlbWVudFxuICogQHByb3BlcnR5IHtPYmplY3R9IHBhdGhTZWxlY3Rpb25cbiAqICBEMyBzZWxlY3Rpb24gb2YgdGhpcyB2aWV3IG1vZGVscyBwYXRoIGVsZW1lbnRzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGltZW5zaW9uU2VsZWN0aW9uXG4gKiAgRDMgc2VsZWN0aW9uIG9mIHRoaXMgdmlldyBtb2RlbHMgZGltZW5zaW9uIGdyb3VwIGVsZW1lbnRcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IERpbWVuc2lvblZpZXdNb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgcGFyY2F0cyBkaW1lbnNpb24gdmlldyBpbmZvcm1hdGlvblxuICpcbiAqICBUaGVzZSBhcmUgcXVhbnRpdGllcyB0aGF0IHJlcXVpcmUgTGF5b3V0IGluZm9ybWF0aW9uIHRvIGNhbGN1bGF0ZVxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7RGltZW5zaW9uTW9kZWx9IG1vZGVsXG4gKiAgU291cmNlIGRpbWVuc2lvbiBtb2RlbFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHhcbiAqICBYIHBvc2l0aW9uIG9mIHRoZSBjZW50ZXIgb2YgdGhpcyBkaW1lbnNpb24gd2l0aCByZXNwZWN0IHRvIHRoZSBGaWd1cmUgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB5XG4gKiAgWSBwb3NpdGlvbiBvZiB0aGUgdG9wIG9mIHRoaXMgZGltZW5zaW9uIHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0gd2lkdGhcbiAqICBXaWR0aCBvZiBjYXRlZ29yaWVzIGluIHRoaXMgZGltZW5zaW9uIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge1BhcmNhdHNWaWV3TW9kZWx9IHBhcmNhdHNWaWV3TW9kZWxcbiAqICBUaGUgcGFyZW50IHRyYWNlJ3MgdmlldyBtb2RlbFxuICogQHByb3BlcnR5IHtBcnJheS48Q2F0ZWdvcnlWaWV3TW9kZWw+fSBjYXRlZ29yaWVzXG4gKiAgRGltZW5zaW9ucyBjYXRlZ29yeSB2aWV3IG1vZGVsc1xuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ0NhdGVnb3J5RGlzcGxheUluZFxuICogIERpc3BsYXkgaW5kZXggb2YgY2F0ZWdvcnkgY3VycmVudGx5IGJlaW5nIGRyYWdnZWQuIG51bGwgaWYgbm8gY2F0ZWdvcnkgaXMgYmVpbmcgZHJhZ2dlZFxuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRcbiAqICBEaXNwbGF5IGluZGV4IG9mIHRoZSBkaW1lbnNpb24gYmVpbmcgZHJhZ2dlZC4gbnVsbCBpZiBubyBkaW1lbnNpb24gaXMgYmVpbmcgZHJhZ2dlZFxuICogQHByb3BlcnR5IHtBcnJheS48TnVtYmVyPnxudWxsfSBpbml0aWFsRHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRzXG4gKiAgRGltZW5zaW9ucyBkaXNwbGF5IGluZGV4ZXMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgY3VycmVudCBkcmFnLiBudWxsIGlmIG5vIGRpbWVuc2lvbiBpcyBiZWluZyBkcmFnZ2VkXG4gKiBAcHJvcGVydHkge0FycmF5LjxOdW1iZXI+fG51bGx9IGluaXRpYWxEcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kc1xuICogIENhdGVnb3J5IGRpc3BsYXkgaW5kZXhlcyBmb3IgdGhlIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGN1cnJlbnQgZHJhZy4gbnVsbCBpZiBubyBjYXRlZ29yeSBpcyBiZWluZyBkcmFnZ2VkXG4gKiBAcHJvcGVydHkge0hUTUxFbGVtZW50fSBwb3RlbnRpYWxDbGlja0JhbmRcbiAqICBCYW5kIHVuZGVyIG1vdXNlIHdoZW4gY3VycmVudCBkcmFnIGJlZ2FuLiBJZiBubyBkcmFnIG1vdmVtZW50IHRha2VzIHBsYWNlIHRoZW4gYSBjbGljayB3aWxsIGJlIGVtaXR0ZWQgZm9yIHRoaXNcbiAqICBiYW5kLiBOdWxsIGlmIG5vdCBkcmFnIGluIHByb2dyZXNzLlxuICogQHByb3BlcnR5IHtCb29sZWFufSBkcmFnSGFzTW92ZWRcbiAqICBUcnVlIGlmIHRoZXJlIGlzIGFuIGFjdGl2ZSBkcmFnIGFuZCB0aGUgZHJhZyBoYXMgbW92ZWQuIElmIGRyYWcgZG9lc24ndCBtb3ZlIGJlZm9yZSBiZWluZyBlbmRlZCB0aGVuXG4gKiAgdGhpcyBtYXkgYmUgaW50ZXJwcmV0ZWQgYXMgYSBjbGljay4gTnVsbCBpZiBubyBkcmFnIGluIHByb2dyZXNzXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYXRlZ29yeVZpZXdNb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgcGFyY2F0cyBjYXRlZ29yeSB2aWV3IGluZm9ybWF0aW9uXG4gKlxuICogIFRoZXNlIGFyZSBxdWFudGl0aWVzIHRoYXQgcmVxdWlyZSBMYXlvdXQgaW5mb3JtYXRpb24gdG8gY2FsY3VsYXRlXG4gKiBAcHJvcGVydHkga2V5XG4gKiAgVW5pcXVlIGtleSBmb3IgdGhpcyBtb2RlbFxuICogQHByb3BlcnR5IHtDYXRlZ29yeU1vZGVsfSBtb2RlbFxuICogIFNvdXJjZSBjYXRlZ29yeSBtb2RlbFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgV2lkdGggZm9yIHRoaXMgY2F0ZWdvcnkgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHRcbiAqICBIZWlnaHQgZm9yIHRoaXMgY2F0ZWdvcnkgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB5XG4gKiAgWSBwb3NpdGlvbiBvZiB0aGlzIGNhdGVvZ3J5IHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge0FycmF5LjxDYXRlZ29yeUJhbmRWaWV3TW9kZWw+fSBiYW5kc1xuICogIEFycmF5IG9mIGNvbG9yIGJhbmRzIGluc2lkZSB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYXRlZ29yeUJhbmRWaWV3TW9kZWxcbiAqICBPYmplY3QgY29udGFpbmluZyBjYWxjdWxhdGVkIGNhdGVnb3J5IGJhbmQgaW5mb3JtYXRpb24uIEEgY2F0ZWdvcnkgYmFuZCBpcyBhIHJlZ2lvbiBpbnNpZGUgYSBjYXRlZ29yeSBjb3ZlcmluZ1xuICogIHBhdGhzIG9mIGEgc2luZ2xlIGNvbG9yXG4gKlxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSBjb2xvclxuICogIEJhbmQgY29sb3JcbiAqIEBwcm9wZXJ0eSByYXdDb2xvclxuICogIFJhdyBjb2xvciB2YWx1ZSBmb3IgYmFuZFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgQmFuZCB3aWR0aFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGhlaWdodFxuICogIEJhbmQgaGVpZ2h0XG4gKiBAcHJvcGVydHkge051bWJlcn0geVxuICogIFkgcG9zaXRpb24gb2YgdG9wIG9mIHRoZSBiYW5kIHdpdGggcmVzcGVjdCB0byB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRoZSBudW1iZXIgb2Ygc2FtcGxlcyByZXByZXNlbnRlZCBieSB0aGUgYmFuZFxuICogQHByb3BlcnR5IHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0ZWdvcnlWaWV3TW9kZWxcbiAqICBUaGUgcGFyZW50IGNhdGVnb3JpZSdzIHZpZXcgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQYXRoVmlld01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBwYXJjYXRzIHBhdGggdmlldyBpbmZvcm1hdGlvblxuICpcbiAqICBUaGVzZSBhcmUgcXVhbnRpdGllcyB0aGF0IHJlcXVpcmUgTGF5b3V0IGluZm9ybWF0aW9uIHRvIGNhbGN1bGF0ZVxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7UGF0aE1vZGVsfSBtb2RlbFxuICogIFNvdXJjZSBwYXRoIG1vZGVsXG4gKiBAcHJvcGVydHkge051bWJlcn0gaGVpZ2h0XG4gKiAgSGVpZ2h0IG9mIHRoaXMgcGF0aCAocGl4ZWxzKVxuICogQHByb3BlcnR5IHtBcnJheS48TnVtYmVyPn0gbGVmdFhzXG4gKiAgVGhlIHggcG9zaXRpb24gb2YgdGhlIGxlZnQgZWRnZSBvZiBlYWNoIGRpc3BsYXkgZGltZW5zaW9uXG4gKiBAcHJvcGVydHkge0FycmF5LjxOdW1iZXI+fSB0b3BZc1xuICogIFRoZSB5IHBvc2l0aW9uIG9mIHRoZSB0b3Agb2YgdGhlIHBhdGggZm9yIGVhY2ggZGlzcGxheSBkaW1lbnNpb25cbiAqIEBwcm9wZXJ0eSB7QXJyYXkuPE51bWJlcj59IGRpbVdpZHRoc1xuICogIFRoZSB3aWR0aCBvZiBlYWNoIGRpc3BsYXkgZGltZW5zaW9uXG4gKiBAcHJvcGVydHkge1N0cmluZ30gc3ZnRFxuICogIFNWRyBwYXRoIFwiZFwiIGF0dHJpYnV0ZSBzdHJpbmdcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgcGFyY2F0cyA9IHJlcXVpcmUoJy4vcGFyY2F0cycpO1xuXG4vKipcbiAqIENyZWF0ZSAvIHVwZGF0ZSBwYXJjYXQgdHJhY2VzXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGdyYXBoRGl2XG4gKiBAcGFyYW0ge0FycmF5LjxQYXJjYXRzTW9kZWw+fSBwYXJjYXRzTW9kZWxzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChncmFwaERpdiwgcGFyY2F0c01vZGVscywgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdyYXBoRGl2Ll9mdWxsTGF5b3V0LFxuICAgICAgICBzdmcgPSBmdWxsTGF5b3V0Ll9wYXBlcixcbiAgICAgICAgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICBwYXJjYXRzKFxuICAgICAgICBncmFwaERpdixcbiAgICAgICAgc3ZnLFxuICAgICAgICBwYXJjYXRzTW9kZWxzLFxuICAgICAgICB7XG4gICAgICAgICAgICB3aWR0aDogc2l6ZS53LFxuICAgICAgICAgICAgaGVpZ2h0OiBzaXplLmgsXG4gICAgICAgICAgICBtYXJnaW46IHtcbiAgICAgICAgICAgICAgICB0OiBzaXplLnQsXG4gICAgICAgICAgICAgICAgcjogc2l6ZS5yLFxuICAgICAgICAgICAgICAgIGI6IHNpemUuYixcbiAgICAgICAgICAgICAgICBsOiBzaXplLmxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNpdGlvbk9wdHMsXG4gICAgICAgIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2tcbiAgICApO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yQXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JiYXJBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JiYXIvYXR0cmlidXRlcycpO1xudmFyIGF4ZXNBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3BhcmNvb3JkcycsIHRyYWNlOiB0cnVlLCBlZGl0VHlwZTogJ2NhbGMnfSksXG5cbiAgICBob3ZlcmxhYmVsOiB1bmRlZmluZWQsXG5cbiAgICBsYWJlbGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIHRpY2tmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICByYW5nZWZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgZGltZW5zaW9uczogdGVtcGxhdGVkQXJyYXkoJ2RpbWVuc2lvbicsIHtcbiAgICAgICAgbGFiZWw6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIC8vIFRPRE86IGJldHRlciB3YXkgdG8gZGV0ZXJtaW5lIG9yZGluYWwgdnMgY29udGludW91cyBheGVzLFxuICAgICAgICAvLyBzbyB1c2VycyBjYW4gdXNlIHRpY2t2YWxzL3RpY2t0ZXh0IHdpdGggYSBjb250aW51b3VzIGF4aXMuXG4gICAgICAgIHRpY2t2YWxzOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMudGlja3ZhbHMsIHtlZGl0VHlwZTogJ2NhbGMnfSksXG4gICAgICAgIHRpY2t0ZXh0OiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMudGlja3RleHQsIHtlZGl0VHlwZTogJ2NhbGMnfSksXG4gICAgICAgIHRpY2tmb3JtYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGZsdDogJzNzJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJhbmdlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBlZGl0VHlwZTogJ2NhbGMnfSxcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAnY2FsYyd9XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBjb25zdHJhaW50cmFuZ2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZnJlZUxlbmd0aDogdHJ1ZSxcbiAgICAgICAgICAgIGRpbWVuc2lvbnM6ICcxLTInLFxuICAgICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAnY2FsYyd9LFxuICAgICAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJywgZWRpdFR5cGU6ICdjYWxjJ31cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG11bHRpc2VsZWN0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgbGluZTogZXh0ZW5kRmxhdChcbiAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdsaW5lJywge1xuICAgICAgICAgICAgLy8gdGhlIGRlZmF1bHQgYXV0b2NvbG9yc2NhbGUgaXNuJ3QgcXVpdGUgdXNhYmxlIGZvciBwYXJjb29yZHMgZHVlIHRvIGNvbnRleHQgYW1iaWd1aXR5IGFyb3VuZCAwIChncmV5LCBvZmYtd2hpdGUpXG4gICAgICAgICAgICAvLyBhdXRvY29sb3JzY2FsZSB0aGVyZWZvcmUgZGVmYXVsdHMgdG8gZmFsc2UgdG9vLCB0byBhdm9pZCBiZWluZyBvdmVycmlkZGVuIGJ5IHRoZSAgYmx1ZS13aGl0ZS1yZWQgYXV0b2NvbG9yIHBhbGV0dGVcbiAgICAgICAgICAgIGNvbG9yc2NhbGVEZmx0OiAnVmlyaWRpcycsXG4gICAgICAgICAgICBhdXRvQ29sb3JEZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xuICAgICAgICB9KSwge1xuICAgICAgICAgICAgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgICAgIH0pXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGtleUZ1biA9IHJlcXVpcmUoJy4uLy4uL2xpYi9ndXAnKS5rZXlGdW47XG52YXIgcmVwZWF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2d1cCcpLnJlcGVhdDtcbnZhciBzb3J0QXNjID0gcmVxdWlyZSgnLi4vLi4vbGliJykuc29ydGVyQXNjO1xuXG52YXIgc25hcFJhdGlvID0gYy5iYXIuc25hcFJhdGlvO1xuZnVuY3Rpb24gc25hcE92ZXJzaG9vdCh2LCB2QWRqYWNlbnQpIHsgcmV0dXJuIHYgKiAoMSAtIHNuYXBSYXRpbykgKyB2QWRqYWNlbnQgKiBzbmFwUmF0aW87IH1cblxudmFyIHNuYXBDbG9zZSA9IGMuYmFyLnNuYXBDbG9zZTtcbmZ1bmN0aW9uIGNsb3NlVG9Db3ZlcmluZyh2LCB2QWRqYWNlbnQpIHsgcmV0dXJuIHYgKiAoMSAtIHNuYXBDbG9zZSkgKyB2QWRqYWNlbnQgKiBzbmFwQ2xvc2U7IH1cblxuLy8gc25hcCBmb3IgdGhlIGxvdyBlbmQgb2YgYSByYW5nZSBvbiBhbiBvcmRpbmFsIHNjYWxlXG4vLyBvbiBhbiBvcmRpbmFsIHNjYWxlLCBhbHdheXMgc2hvdyBzb21lIG92ZXJzaG9vdCBmcm9tIHRoZSBleGFjdCB2YWx1ZSxcbi8vIHNvIGl0J3MgY2xlYXIgd2UncmUgY292ZXJpbmcgaXRcbi8vIGZpbmQgdGhlIGludGVydmFsIHdlJ3JlIGluLCBhbmQgc25hcCB0byAxLzQgdGhlIGRpc3RhbmNlIHRvIHRoZSBuZXh0XG4vLyB0aGVzZSB0d28gY291bGQgYmUgdW5pZmllZCBhdCBhIHNsaWdodCBsb3NzIG9mIHJlYWRhYmlsaXR5IC8gcGVyZlxuZnVuY3Rpb24gb3JkaW5hbFNjYWxlU25hcExvKGEsIHYsIGV4aXN0aW5nUmFuZ2VzKSB7XG4gICAgaWYob3ZlcmxhcHBpbmdFeGlzdGluZyh2LCBleGlzdGluZ1JhbmdlcykpIHJldHVybiB2O1xuXG4gICAgdmFyIGFQcmV2ID0gYVswXTtcbiAgICB2YXIgYVByZXZQcmV2ID0gYVByZXY7XG4gICAgZm9yKHZhciBpID0gMTsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFOZXh0ID0gYVtpXTtcblxuICAgICAgICAvLyB2ZXJ5IGNsb3NlIHRvIHRoZSBwcmV2aW91cyAtIHNuYXAgZG93biB0byBpdFxuICAgICAgICBpZih2IDwgY2xvc2VUb0NvdmVyaW5nKGFQcmV2LCBhTmV4dCkpIHJldHVybiBzbmFwT3ZlcnNob290KGFQcmV2LCBhUHJldlByZXYpO1xuICAgICAgICBpZih2IDwgYU5leHQgfHwgaSA9PT0gYS5sZW5ndGggLSAxKSByZXR1cm4gc25hcE92ZXJzaG9vdChhTmV4dCwgYVByZXYpO1xuXG4gICAgICAgIGFQcmV2UHJldiA9IGFQcmV2O1xuICAgICAgICBhUHJldiA9IGFOZXh0O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gb3JkaW5hbFNjYWxlU25hcEhpKGEsIHYsIGV4aXN0aW5nUmFuZ2VzKSB7XG4gICAgaWYob3ZlcmxhcHBpbmdFeGlzdGluZyh2LCBleGlzdGluZ1JhbmdlcykpIHJldHVybiB2O1xuXG4gICAgdmFyIGFQcmV2ID0gYVthLmxlbmd0aCAtIDFdO1xuICAgIHZhciBhUHJldlByZXYgPSBhUHJldjtcbiAgICBmb3IodmFyIGkgPSBhLmxlbmd0aCAtIDI7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHZhciBhTmV4dCA9IGFbaV07XG5cbiAgICAgICAgLy8gdmVyeSBjbG9zZSB0byB0aGUgcHJldmlvdXMgLSBzbmFwIGRvd24gdG8gaXRcbiAgICAgICAgaWYodiA+IGNsb3NlVG9Db3ZlcmluZyhhUHJldiwgYU5leHQpKSByZXR1cm4gc25hcE92ZXJzaG9vdChhUHJldiwgYVByZXZQcmV2KTtcbiAgICAgICAgaWYodiA+IGFOZXh0IHx8IGkgPT09IGEubGVuZ3RoIC0gMSkgcmV0dXJuIHNuYXBPdmVyc2hvb3QoYU5leHQsIGFQcmV2KTtcblxuICAgICAgICBhUHJldlByZXYgPSBhUHJldjtcbiAgICAgICAgYVByZXYgPSBhTmV4dDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG92ZXJsYXBwaW5nRXhpc3RpbmcodiwgZXhpc3RpbmdSYW5nZXMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZXhpc3RpbmdSYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodiA+PSBleGlzdGluZ1Jhbmdlc1tpXVswXSAmJiB2IDw9IGV4aXN0aW5nUmFuZ2VzW2ldWzFdKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBiYXJIb3Jpem9udGFsU2V0dXAoc2VsZWN0aW9uKSB7XG4gICAgc2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCd4JywgLWMuYmFyLmNhcHR1cmVXaWR0aCAvIDIpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGMuYmFyLmNhcHR1cmVXaWR0aCk7XG59XG5cbmZ1bmN0aW9uIGJhY2tncm91bmRCYXJIb3Jpem9udGFsU2V0dXAoc2VsZWN0aW9uKSB7XG4gICAgc2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCd2aXNpYmlsaXR5JywgJ3Zpc2libGUnKVxuICAgICAgICAuc3R5bGUoJ3Zpc2liaWxpdHknLCAndmlzaWJsZScpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ3llbGxvdycpXG4gICAgICAgIC5hdHRyKCdvcGFjaXR5JywgMCk7XG59XG5cbmZ1bmN0aW9uIHNldEhpZ2hsaWdodChkKSB7XG4gICAgaWYoIWQuYnJ1c2guZmlsdGVyU3BlY2lmaWVkKSB7XG4gICAgICAgIHJldHVybiAnMCwnICsgZC5oZWlnaHQ7XG4gICAgfVxuICAgIHZhciBwaXhlbFJhbmdlcyA9IHVuaXRUb1B4KGQuYnJ1c2guZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpLCBkLmhlaWdodCk7XG4gICAgdmFyIGRhc2hBcnJheSA9IFswXTsgLy8gd2Ugc3RhcnQgd2l0aCBhIDAgbGVuZ3RoIHNlbGVjdGlvbiBhcyBmaWx0ZXIgcmFuZ2VzIGFyZSBpbmNsdXNpdmUsIG5vdCBleGNsdXNpdmVcbiAgICB2YXIgcCwgc2VjdGlvbkhlaWdodCwgaU5leHQ7XG4gICAgdmFyIGN1cnJlbnRHYXAgPSBwaXhlbFJhbmdlcy5sZW5ndGggPyBwaXhlbFJhbmdlc1swXVswXSA6IG51bGw7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBpeGVsUmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHAgPSBwaXhlbFJhbmdlc1tpXTtcbiAgICAgICAgc2VjdGlvbkhlaWdodCA9IHBbMV0gLSBwWzBdO1xuICAgICAgICBkYXNoQXJyYXkucHVzaChjdXJyZW50R2FwKTtcbiAgICAgICAgZGFzaEFycmF5LnB1c2goc2VjdGlvbkhlaWdodCk7XG4gICAgICAgIGlOZXh0ID0gaSArIDE7XG4gICAgICAgIGlmKGlOZXh0IDwgcGl4ZWxSYW5nZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjdXJyZW50R2FwID0gcGl4ZWxSYW5nZXNbaU5leHRdWzBdIC0gcFsxXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkYXNoQXJyYXkucHVzaChkLmhlaWdodCk7XG4gICAgLy8gZC5oZWlnaHQgaXMgYWRkZWQgYXQgdGhlIGVuZCB0byBlbnN1cmUgdGhhdCAoMSkgd2UgaGF2ZSBhbiBldmVuIG51bWJlciBvZiBkYXNoYXJyYXkgcG9pbnRzLCBNRE4gcGFnZSBzYXlzXG4gICAgLy8gXCJJZiBhbiBvZGQgbnVtYmVyIG9mIHZhbHVlcyBpcyBwcm92aWRlZCwgdGhlbiB0aGUgbGlzdCBvZiB2YWx1ZXMgaXMgcmVwZWF0ZWQgdG8geWllbGQgYW4gZXZlbiBudW1iZXIgb2YgdmFsdWVzLlwiXG4gICAgLy8gYW5kICgyKSBpdCdzIF9hdCBsZWFzdF8gYXMgbG9uZyBhcyB0aGUgZnVsbCBoZWlnaHQgKGV2ZW4gaWYgcmFuZ2UgaXMgbWludXNjdWxlIGFuZCBhdCB0aGUgYm90dG9tKSB0aG91Z2ggdGhpc1xuICAgIC8vIG1heSBub3QgYmUgbmVjZXNzYXJ5LCBtYXliZSBkdXBsaWNhdGluZyB0aGUgbGFzdCBwb2ludCB3b3VsZCBkbyB0b28uIEJ1dCBubyBoYXJtIGluIGEgbG9uZ2VyIGRhc2hhcnJheSB0aGFuIGxpbmUuXG4gICAgcmV0dXJuIGRhc2hBcnJheTtcbn1cblxuZnVuY3Rpb24gdW5pdFRvUHgodW5pdFJhbmdlcywgaGVpZ2h0KSB7XG4gICAgcmV0dXJuIHVuaXRSYW5nZXMubWFwKGZ1bmN0aW9uKHByKSB7XG4gICAgICAgIHJldHVybiBwci5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gdiAqIGhlaWdodDsgfSkuc29ydChzb3J0QXNjKTtcbiAgICB9KTtcbn1cblxuLy8gaXMgdGhlIGN1cnNvciBvdmVyIHRoZSBub3J0aCwgbWlkZGxlLCBvciBzb3V0aCBvZiBhIGJhcj9cbi8vIHRoZSBlbmQgaGFuZGxlcyBleHRlbmQgb3ZlciB0aGUgbGFzdCAxMCUgb2YgdGhlIGJhclxuZnVuY3Rpb24gZ2V0UmVnaW9uKGZQaXgsIHkpIHtcbiAgICB2YXIgcGFkID0gYy5iYXIuaGFuZGxlSGVpZ2h0O1xuICAgIGlmKHkgPiBmUGl4WzFdICsgcGFkIHx8IHkgPCBmUGl4WzBdIC0gcGFkKSByZXR1cm47XG4gICAgaWYoeSA+PSAwLjkgKiBmUGl4WzFdICsgMC4xICogZlBpeFswXSkgcmV0dXJuICduJztcbiAgICBpZih5IDw9IDAuOSAqIGZQaXhbMF0gKyAwLjEgKiBmUGl4WzFdKSByZXR1cm4gJ3MnO1xuICAgIHJldHVybiAnbnMnO1xufVxuXG5mdW5jdGlvbiBjbGVhckN1cnNvcigpIHtcbiAgICBkMy5zZWxlY3QoZG9jdW1lbnQuYm9keSlcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCBudWxsKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVIaWdobGlnaHQoc2VsZWN0aW9uKSB7XG4gICAgLy8gc3Ryb2tlLWRhc2hhcnJheSBpcyB1c2VkIHRvIG1pbmltaXplIHRoZSBudW1iZXIgb2YgY3JlYXRlZCBET00gbm9kZXMsIGJlY2F1c2UgdGhlIHJlcXVpcmVtZW50IGNhbGxzIGZvciB1cCB0b1xuICAgIC8vIDEwMDAgaW5kaXZpZHVhbCBzZWxlY3Rpb25zIG9uIGFuIGF4aXMsIGFuZCB0aGVyZSBjYW4gYmUgNjAgYXhlcyBwZXIgcGFyY29vcmRzLCBhbmQgbXVsdGlwbGUgcGFyY29vcmRzIHBlclxuICAgIC8vIGRhc2hib2FyZC4gVGhlIHRlY2huaXF1ZSBpcyBzaW1pbGFyIHRvIGh0dHBzOi8vY29kZXBlbi5pby9tb25mZXJhL3Blbi9yTFlxV1IgYW5kIHVzaW5nIGEgYHBvbHlsaW5lYCB3aXRoXG4gICAgLy8gbXVsdGlwbGUgc2VjdGlvbnMsIG9yIGEgYHBhdGhgIGVsZW1lbnQgdmlhIGl0cyBgZGAgYXR0cmlidXRlIHdvdWxkIGFsc28gYmUgRE9NLXNwYXJpbmcgYWx0ZXJuYXRpdmVzLlxuICAgIHNlbGVjdGlvbi5hdHRyKCdzdHJva2UtZGFzaGFycmF5Jywgc2V0SGlnaGxpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVySGlnaGxpZ2h0KHJvb3QsIHR3ZWVuQ2FsbGJhY2spIHtcbiAgICB2YXIgYmFyID0gZDMuc2VsZWN0KHJvb3QpLnNlbGVjdEFsbCgnLmhpZ2hsaWdodCwgLmhpZ2hsaWdodC1zaGFkb3cnKTtcbiAgICB2YXIgYmFyVG9TdHlsZSA9IHR3ZWVuQ2FsbGJhY2sgPyBiYXIudHJhbnNpdGlvbigpLmR1cmF0aW9uKGMuYmFyLnNuYXBEdXJhdGlvbikuZWFjaCgnZW5kJywgdHdlZW5DYWxsYmFjaykgOiBiYXI7XG4gICAgc3R5bGVIaWdobGlnaHQoYmFyVG9TdHlsZSk7XG59XG5cbmZ1bmN0aW9uIGdldEludGVydmFsKGQsIHkpIHtcbiAgICB2YXIgYiA9IGQuYnJ1c2g7XG4gICAgdmFyIGFjdGl2ZSA9IGIuZmlsdGVyU3BlY2lmaWVkO1xuICAgIHZhciBjbG9zZXN0SW50ZXJ2YWwgPSBOYU47XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIHZhciBpO1xuXG4gICAgaWYoYWN0aXZlKSB7XG4gICAgICAgIHZhciBoZWlnaHQgPSBkLmhlaWdodDtcbiAgICAgICAgdmFyIGludGVydmFscyA9IGIuZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpO1xuICAgICAgICB2YXIgcGl4SW50ZXJ2YWxzID0gdW5pdFRvUHgoaW50ZXJ2YWxzLCBoZWlnaHQpO1xuICAgICAgICB2YXIgaG92ZXJlZEludGVydmFsID0gTmFOO1xuICAgICAgICB2YXIgcHJldmlvdXNJbnRlcnZhbCA9IE5hTjtcbiAgICAgICAgdmFyIG5leHRJbnRlcnZhbCA9IE5hTjtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDw9IHBpeEludGVydmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHAgPSBwaXhJbnRlcnZhbHNbaV07XG4gICAgICAgICAgICBpZihwICYmIHBbMF0gPD0geSAmJiB5IDw9IHBbMV0pIHtcbiAgICAgICAgICAgICAgICAvLyBvdmVyIGEgYmFyXG4gICAgICAgICAgICAgICAgaG92ZXJlZEludGVydmFsID0gaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gYmV0d2VlbiBiYXJzLCBvciBiZWZvcmUvYWZ0ZXIgdGhlIGZpcnN0L2xhc3QgYmFyXG4gICAgICAgICAgICAgICAgcHJldmlvdXNJbnRlcnZhbCA9IGkgPyBpIC0gMSA6IE5hTjtcbiAgICAgICAgICAgICAgICBpZihwICYmIHBbMF0gPiB5KSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRJbnRlcnZhbCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrOyAvLyBubyBwb2ludCBjb250aW51aW5nIGFzIGludGVydmFscyBhcmUgbm9uLW92ZXJsYXBwaW5nIGFuZCBzb3J0ZWQ7IGNvdWxkIHVzZSBsb2cgc2VhcmNoXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2xvc2VzdEludGVydmFsID0gaG92ZXJlZEludGVydmFsO1xuICAgICAgICBpZihpc05hTihjbG9zZXN0SW50ZXJ2YWwpKSB7XG4gICAgICAgICAgICBpZihpc05hTihwcmV2aW91c0ludGVydmFsKSB8fCBpc05hTihuZXh0SW50ZXJ2YWwpKSB7XG4gICAgICAgICAgICAgICAgY2xvc2VzdEludGVydmFsID0gaXNOYU4ocHJldmlvdXNJbnRlcnZhbCkgPyBuZXh0SW50ZXJ2YWwgOiBwcmV2aW91c0ludGVydmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY2xvc2VzdEludGVydmFsID0gKHkgLSBwaXhJbnRlcnZhbHNbcHJldmlvdXNJbnRlcnZhbF1bMV0gPCBwaXhJbnRlcnZhbHNbbmV4dEludGVydmFsXVswXSAtIHkpID9cbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNJbnRlcnZhbCA6IG5leHRJbnRlcnZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFpc05hTihjbG9zZXN0SW50ZXJ2YWwpKSB7XG4gICAgICAgICAgICB2YXIgZlBpeCA9IHBpeEludGVydmFsc1tjbG9zZXN0SW50ZXJ2YWxdO1xuICAgICAgICAgICAgdmFyIHJlZ2lvbiA9IGdldFJlZ2lvbihmUGl4LCB5KTtcblxuICAgICAgICAgICAgaWYocmVnaW9uKSB7XG4gICAgICAgICAgICAgICAgb3V0LmludGVydmFsID0gaW50ZXJ2YWxzW2Nsb3Nlc3RJbnRlcnZhbF07XG4gICAgICAgICAgICAgICAgb3V0LmludGVydmFsUGl4ID0gZlBpeDtcbiAgICAgICAgICAgICAgICBvdXQucmVnaW9uID0gcmVnaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZC5vcmRpbmFsICYmICFvdXQucmVnaW9uKSB7XG4gICAgICAgIHZhciBhID0gZC51bml0VGlja3ZhbHM7XG4gICAgICAgIHZhciB1bml0TG9jYXRpb24gPSBkLnVuaXRUb1BhZGRlZFB4LmludmVydCh5KTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHJhbmdlaSA9IFtcbiAgICAgICAgICAgICAgICBhW01hdGgubWF4KGkgLSAxLCAwKV0gKiAwLjI1ICsgYVtpXSAqIDAuNzUsXG4gICAgICAgICAgICAgICAgYVtNYXRoLm1pbihpICsgMSwgYS5sZW5ndGggLSAxKV0gKiAwLjI1ICsgYVtpXSAqIDAuNzVcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZih1bml0TG9jYXRpb24gPj0gcmFuZ2VpWzBdICYmIHVuaXRMb2NhdGlvbiA8PSByYW5nZWlbMV0pIHtcbiAgICAgICAgICAgICAgICBvdXQuY2xpY2thYmxlT3JkaW5hbFJhbmdlID0gcmFuZ2VpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gYXR0YWNoRHJhZ0JlaGF2aW9yKHNlbGVjdGlvbikge1xuICAgIC8vIFRoZXJlJ3Mgc29tZSBmaWRkbGluZyB3aXRoIHBvaW50ZXIgY3Vyc29yIHN0eWxpbmcgc28gdGhhdCB0aGUgY3Vyc29yIHByZXNlcnZlcyBpdHMgc2hhcGUgd2hpbGUgZHJhZ2dpbmcgYSBicnVzaFxuICAgIC8vIGV2ZW4gaWYgdGhlIGN1cnNvciBzdHJheXMgZnJvbSB0aGUgaW50ZXJhY3RpbmcgYmFyLCB3aGljaCBpcyBib3VuZCB0byBoYXBwZW4gYXMgYmFycyBhcmUgdGhpbiBhbmQgdGhlIHVzZXJcbiAgICAvLyB3aWxsIGluZXZpdGFibHkgbGVhdmUgdGhlIGhvdHNwb3Qgc3RyaXAuIEluIHRoaXMgcmVnYXJkLCBpdCBkb2VzIHNvbWV0aGluZyBzaW1pbGFyIHRvIHdoYXQgdGhlIEQzIGJydXNoIHdvdWxkIGRvLlxuICAgIHNlbGVjdGlvblxuICAgICAgICAub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGQzLmV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBpZighZC5wYXJlbnQuaW5CcnVzaERyYWcpIHtcbiAgICAgICAgICAgICAgICB2YXIgeSA9IGQuaGVpZ2h0IC0gZDMubW91c2UodGhpcylbMV0gLSAyICogYy52ZXJ0aWNhbFBhZGRpbmc7XG4gICAgICAgICAgICAgICAgdmFyIGludGVydmFsID0gZ2V0SW50ZXJ2YWwoZCwgeSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY3Vyc29yID0gJ2Nyb3NzaGFpcic7XG4gICAgICAgICAgICAgICAgaWYoaW50ZXJ2YWwuY2xpY2thYmxlT3JkaW5hbFJhbmdlKSBjdXJzb3IgPSAncG9pbnRlcic7XG4gICAgICAgICAgICAgICAgZWxzZSBpZihpbnRlcnZhbC5yZWdpb24pIGN1cnNvciA9IGludGVydmFsLnJlZ2lvbiArICctcmVzaXplJztcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QoZG9jdW1lbnQuYm9keSlcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdjdXJzb3InLCBjdXJzb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ21vdXNlbGVhdmUnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZighZC5wYXJlbnQuaW5CcnVzaERyYWcpIGNsZWFyQ3Vyc29yKCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc291cmNlRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgdmFyIHkgPSBkLmhlaWdodCAtIGQzLm1vdXNlKHRoaXMpWzFdIC0gMiAqIGMudmVydGljYWxQYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciB1bml0TG9jYXRpb24gPSBkLnVuaXRUb1BhZGRlZFB4LmludmVydCh5KTtcbiAgICAgICAgICAgICAgICB2YXIgYiA9IGQuYnJ1c2g7XG4gICAgICAgICAgICAgICAgdmFyIGludGVydmFsID0gZ2V0SW50ZXJ2YWwoZCwgeSk7XG4gICAgICAgICAgICAgICAgdmFyIHVuaXRSYW5nZSA9IGludGVydmFsLmludGVydmFsO1xuICAgICAgICAgICAgICAgIHZhciBzID0gYi5zdmdCcnVzaDtcbiAgICAgICAgICAgICAgICBzLndhc0RyYWdnZWQgPSBmYWxzZTsgLy8gd2Ugc3RhcnQgYXNzdW1pbmcgdGhlcmUgd29uJ3QgYmUgYSBkcmFnIC0gdXNlZnVsIGZvciByZXNldFxuICAgICAgICAgICAgICAgIHMuZ3JhYmJpbmdCYXIgPSBpbnRlcnZhbC5yZWdpb24gPT09ICducyc7XG4gICAgICAgICAgICAgICAgaWYocy5ncmFiYmluZ0Jhcikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGl4ZWxSYW5nZSA9IHVuaXRSYW5nZS5tYXAoZC51bml0VG9QYWRkZWRQeCk7XG4gICAgICAgICAgICAgICAgICAgIHMuZ3JhYlBvaW50ID0geSAtIHBpeGVsUmFuZ2VbMF0gLSBjLnZlcnRpY2FsUGFkZGluZztcbiAgICAgICAgICAgICAgICAgICAgcy5iYXJMZW5ndGggPSBwaXhlbFJhbmdlWzFdIC0gcGl4ZWxSYW5nZVswXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcy5jbGlja2FibGVPcmRpbmFsUmFuZ2UgPSBpbnRlcnZhbC5jbGlja2FibGVPcmRpbmFsUmFuZ2U7XG4gICAgICAgICAgICAgICAgcy5zdGF5aW5nSW50ZXJ2YWxzID0gKGQubXVsdGlzZWxlY3QgJiYgYi5maWx0ZXJTcGVjaWZpZWQpID8gYi5maWx0ZXIuZ2V0Q29uc29saWRhdGVkKCkgOiBbXTtcbiAgICAgICAgICAgICAgICBpZih1bml0UmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcy5zdGF5aW5nSW50ZXJ2YWxzID0gcy5zdGF5aW5nSW50ZXJ2YWxzLmZpbHRlcihmdW5jdGlvbihpbnQyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW50MlswXSAhPT0gdW5pdFJhbmdlWzBdICYmIGludDJbMV0gIT09IHVuaXRSYW5nZVsxXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHMuc3RhcnRFeHRlbnQgPSBpbnRlcnZhbC5yZWdpb24gPyB1bml0UmFuZ2VbaW50ZXJ2YWwucmVnaW9uID09PSAncycgPyAxIDogMF0gOiB1bml0TG9jYXRpb247XG4gICAgICAgICAgICAgICAgZC5wYXJlbnQuaW5CcnVzaERyYWcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHMuYnJ1c2hTdGFydENhbGxiYWNrKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdkcmFnJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGQzLmV2ZW50LnNvdXJjZUV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIHZhciB5ID0gZC5oZWlnaHQgLSBkMy5tb3VzZSh0aGlzKVsxXSAtIDIgKiBjLnZlcnRpY2FsUGFkZGluZztcbiAgICAgICAgICAgICAgICB2YXIgcyA9IGQuYnJ1c2guc3ZnQnJ1c2g7XG4gICAgICAgICAgICAgICAgcy53YXNEcmFnZ2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIGlmKHMuZ3JhYmJpbmdCYXIpIHsgLy8gbW92aW5nIHRoZSBiYXJcbiAgICAgICAgICAgICAgICAgICAgcy5uZXdFeHRlbnQgPSBbeSAtIHMuZ3JhYlBvaW50LCB5ICsgcy5iYXJMZW5ndGggLSBzLmdyYWJQb2ludF0ubWFwKGQudW5pdFRvUGFkZGVkUHguaW52ZXJ0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyBzb3V0aC9ub3J0aCBkcmFnIG9yIG5ldyBiYXIgY3JlYXRpb25cbiAgICAgICAgICAgICAgICAgICAgcy5uZXdFeHRlbnQgPSBbcy5zdGFydEV4dGVudCwgZC51bml0VG9QYWRkZWRQeC5pbnZlcnQoeSldLnNvcnQoc29ydEFzYyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gdGFrZSBjYXJlIG9mIHRoZSBwYXJjb29yZHMgYXhpcyBoZWlnaHQgY29uc3RyYWludDogYmFyIGNhbid0IGJyZWFjaCBpdFxuICAgICAgICAgICAgICAgIHZhciBib3R0b21WaW9sYXRpb24gPSBNYXRoLm1heCgwLCAtcy5uZXdFeHRlbnRbMF0pO1xuICAgICAgICAgICAgICAgIHZhciB0b3BWaW9sYXRpb24gPSBNYXRoLm1heCgwLCBzLm5ld0V4dGVudFsxXSAtIDEpO1xuICAgICAgICAgICAgICAgIHMubmV3RXh0ZW50WzBdICs9IGJvdHRvbVZpb2xhdGlvbjtcbiAgICAgICAgICAgICAgICBzLm5ld0V4dGVudFsxXSAtPSB0b3BWaW9sYXRpb247XG4gICAgICAgICAgICAgICAgaWYocy5ncmFiYmluZ0Jhcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIG9mIGJhciBkcmFnZ2luZyAobm9uLXJlc2l6aW5nIGludGVyYWN0aW9uLCB1bmxpa2Ugbm9ydGgvc291dGggcmVzaXplIG9yIG5ldyBiYXIgY3JlYXRpb24pXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBjb25zdHJhaW50IGFkanVzdG1lbnQgbXVzdCBhcHBseSB0byB0aGUgb3RoZXIgZW5kIG9mIHRoZSBiYXIgYXMgd2VsbCwgb3RoZXJ3aXNlIGl0J2RcbiAgICAgICAgICAgICAgICAgICAgLy8gc2hvcnRlbiBvciBsZW5ndGhlblxuICAgICAgICAgICAgICAgICAgICBzLm5ld0V4dGVudFsxXSArPSBib3R0b21WaW9sYXRpb247XG4gICAgICAgICAgICAgICAgICAgIHMubmV3RXh0ZW50WzBdIC09IHRvcFZpb2xhdGlvbjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkLmJydXNoLmZpbHRlclNwZWNpZmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcy5leHRlbnQgPSBzLnN0YXlpbmdJbnRlcnZhbHMuY29uY2F0KFtzLm5ld0V4dGVudF0pO1xuICAgICAgICAgICAgICAgIHMuYnJ1c2hDYWxsYmFjayhkKTtcbiAgICAgICAgICAgICAgICByZW5kZXJIaWdobGlnaHQodGhpcy5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGUgPSBkMy5ldmVudDtcbiAgICAgICAgICAgICAgICBlLnNvdXJjZUV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIHZhciBicnVzaCA9IGQuYnJ1c2g7XG4gICAgICAgICAgICAgICAgdmFyIGZpbHRlciA9IGJydXNoLmZpbHRlcjtcbiAgICAgICAgICAgICAgICB2YXIgcyA9IGJydXNoLnN2Z0JydXNoO1xuICAgICAgICAgICAgICAgIHZhciBncmFiYmluZ0JhciA9IHMuZ3JhYmJpbmdCYXI7XG4gICAgICAgICAgICAgICAgcy5ncmFiYmluZ0JhciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHMuZ3JhYkxvY2F0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGQucGFyZW50LmluQnJ1c2hEcmFnID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY2xlYXJDdXJzb3IoKTsgLy8gaW5zdGVhZCBvZiBjbGVhcmluZywgYSBuaWNlciB0aGluZyB3b3VsZCBiZSB0byBzZXQgaXQgYWNjb3JkaW5nIHRvIGN1cnJlbnQgbG9jYXRpb25cbiAgICAgICAgICAgICAgICBpZighcy53YXNEcmFnZ2VkKSB7IC8vIGEgY2xpY2srcmVsZWFzZSBvbiB0aGUgc2FtZSBzcG90IChpZS4gdy9vIGRyYWdnaW5nKSBtZWFucyBhIGJhciBvciBmdWxsIHJlc2V0XG4gICAgICAgICAgICAgICAgICAgIHMud2FzRHJhZ2dlZCA9IHVuZGVmaW5lZDsgLy8gbG9naWMtd2lzZSB1bm5lZWRlZCwganVzdCBzaG93cyBgd2FzRHJhZ2dlZGAgaGFzIG5vIGxvbmdlciBhIG1lYW5pbmdcbiAgICAgICAgICAgICAgICAgICAgaWYocy5jbGlja2FibGVPcmRpbmFsUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGJydXNoLmZpbHRlclNwZWNpZmllZCAmJiBkLm11bHRpc2VsZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcy5leHRlbnQucHVzaChzLmNsaWNrYWJsZU9yZGluYWxSYW5nZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzLmV4dGVudCA9IFtzLmNsaWNrYWJsZU9yZGluYWxSYW5nZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJ1c2guZmlsdGVyU3BlY2lmaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKGdyYWJiaW5nQmFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzLmV4dGVudCA9IHMuc3RheWluZ0ludGVydmFscztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHMuZXh0ZW50Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJydXNoQ2xlYXIoYnJ1c2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJ1c2hDbGVhcihicnVzaCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcy5icnVzaENhbGxiYWNrKGQpO1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJIaWdobGlnaHQodGhpcy5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgcy5icnVzaEVuZENhbGxiYWNrKGJydXNoLmZpbHRlclNwZWNpZmllZCA/IGZpbHRlci5nZXRDb25zb2xpZGF0ZWQoKSA6IFtdKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBubyBuZWVkIHRvIGZ1c2UgaW50ZXJ2YWxzIG9yIHNuYXAgdG8gb3JkaW5hbHMsIHNvIHdlIGNhbiBiYWlsIGVhcmx5XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1lcmdlSW50ZXJ2YWxzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEtleSBwaWVjZSBvZiBsb2dpYzogb25jZSB0aGUgYnV0dG9uIGlzIHJlbGVhc2VkLCBwb3NzaWJseSBvdmVybGFwcGluZyBpbnRlcnZhbHMgd2lsbCBiZSBmdXNlZDpcbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSBpdCdzIGRvbmUgaW1tZWRpYXRlbHkgb24gY2xpY2sgcmVsZWFzZSB3aGlsZSBvbiBvcmRpbmFsIHNuYXAgdHJhbnNpdGlvbiBpdCdzIGRvbmUgYXQgdGhlIGVuZFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIuc2V0KGZpbHRlci5nZXRDb25zb2xpZGF0ZWQoKSk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGlmKGQub3JkaW5hbCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IGQudW5pdFRpY2t2YWxzO1xuICAgICAgICAgICAgICAgICAgICBpZihhW2EubGVuZ3RoIC0gMV0gPCBhWzBdKSBhLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcy5uZXdFeHRlbnQgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmRpbmFsU2NhbGVTbmFwTG8oYSwgcy5uZXdFeHRlbnRbMF0sIHMuc3RheWluZ0ludGVydmFscyksXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmRpbmFsU2NhbGVTbmFwSGkoYSwgcy5uZXdFeHRlbnRbMV0sIHMuc3RheWluZ0ludGVydmFscylcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhhc05ld0V4dGVudCA9IHMubmV3RXh0ZW50WzFdID4gcy5uZXdFeHRlbnRbMF07XG4gICAgICAgICAgICAgICAgICAgIHMuZXh0ZW50ID0gcy5zdGF5aW5nSW50ZXJ2YWxzLmNvbmNhdChoYXNOZXdFeHRlbnQgPyBbcy5uZXdFeHRlbnRdIDogW10pO1xuICAgICAgICAgICAgICAgICAgICBpZighcy5leHRlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicnVzaENsZWFyKGJydXNoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzLmJydXNoQ2FsbGJhY2soZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGhhc05ld0V4dGVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVyZ2luZyBpbnRlcnZhbHMgcG9zdCB0aGUgc25hcCB0d2VlblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVySGlnaGxpZ2h0KHRoaXMucGFyZW50Tm9kZSwgbWVyZ2VJbnRlcnZhbHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgbm8gbmV3IGludGVydmFsLCBkb24ndCBhbmltYXRlLCBqdXN0IHJlZHJhdyB0aGUgaGlnaGxpZ2h0IGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXJnZUludGVydmFscygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVySGlnaGxpZ2h0KHRoaXMucGFyZW50Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZXJnZUludGVydmFscygpOyAvLyBtZXJnaW5nIGludGVydmFscyBpbW1lZGlhdGVseVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzLmJydXNoRW5kQ2FsbGJhY2soYnJ1c2guZmlsdGVyU3BlY2lmaWVkID8gZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpIDogW10pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRBc2MoYSwgYikgeyByZXR1cm4gYVswXSAtIGJbMF07IH1cblxuZnVuY3Rpb24gcmVuZGVyQXhpc0JydXNoKGF4aXNCcnVzaCkge1xuXG4gICAgdmFyIGJhY2tncm91bmQgPSBheGlzQnJ1c2guc2VsZWN0QWxsKCcuYmFja2dyb3VuZCcpLmRhdGEocmVwZWF0KTtcblxuICAgIGJhY2tncm91bmQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdyZWN0JylcbiAgICAgICAgLmNsYXNzZWQoJ2JhY2tncm91bmQnLCB0cnVlKVxuICAgICAgICAuY2FsbChiYXJIb3Jpem9udGFsU2V0dXApXG4gICAgICAgIC5jYWxsKGJhY2tncm91bmRCYXJIb3Jpem9udGFsU2V0dXApXG4gICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYXV0bycpIC8vIHBhcmVudCBwb2ludGVyIGV2ZW50cyBhcmUgZGlzYWJsZWQ7IHdlIG11c3QgaGF2ZSBpdCB0byByZWdpc3RlciBldmVudHNcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCAnICsgYy52ZXJ0aWNhbFBhZGRpbmcgKyAnKScpO1xuXG4gICAgYmFja2dyb3VuZFxuICAgICAgICAuY2FsbChhdHRhY2hEcmFnQmVoYXZpb3IpXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5oZWlnaHQgLSBjLnZlcnRpY2FsUGFkZGluZztcbiAgICAgICAgfSk7XG5cbiAgICB2YXIgaGlnaGxpZ2h0U2hhZG93ID0gYXhpc0JydXNoLnNlbGVjdEFsbCgnLmhpZ2hsaWdodC1zaGFkb3cnKS5kYXRhKHJlcGVhdCk7IC8vIHdlIGhhdmUgYSBzZXQgaGVyZSwgY2FuJ3QgY2FsbCBpdCBgZXh0ZW50YFxuXG4gICAgaGlnaGxpZ2h0U2hhZG93LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnbGluZScpXG4gICAgICAgIC5jbGFzc2VkKCdoaWdobGlnaHQtc2hhZG93JywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3gnLCAtYy5iYXIud2lkdGggLyAyKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYy5iYXIud2lkdGggKyBjLmJhci5zdHJva2VXaWR0aClcbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsIGMuYmFyLnN0cm9rZUNvbG9yKVxuICAgICAgICAuYXR0cignb3BhY2l0eScsIGMuYmFyLnN0cm9rZU9wYWNpdHkpXG4gICAgICAgIC5hdHRyKCdzdHJva2UtbGluZWNhcCcsICdidXR0Jyk7XG5cbiAgICBoaWdobGlnaHRTaGFkb3dcbiAgICAgICAgLmF0dHIoJ3kxJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5oZWlnaHQ7IH0pXG4gICAgICAgIC5jYWxsKHN0eWxlSGlnaGxpZ2h0KTtcblxuICAgIHZhciBoaWdobGlnaHQgPSBheGlzQnJ1c2guc2VsZWN0QWxsKCcuaGlnaGxpZ2h0JykuZGF0YShyZXBlYXQpOyAvLyB3ZSBoYXZlIGEgc2V0IGhlcmUsIGNhbid0IGNhbGwgaXQgYGV4dGVudGBcblxuICAgIGhpZ2hsaWdodC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAuY2xhc3NlZCgnaGlnaGxpZ2h0JywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3gnLCAtYy5iYXIud2lkdGggLyAyKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYy5iYXIud2lkdGggLSBjLmJhci5zdHJva2VXaWR0aClcbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsIGMuYmFyLmZpbGxDb2xvcilcbiAgICAgICAgLmF0dHIoJ29wYWNpdHknLCBjLmJhci5maWxsT3BhY2l0eSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1saW5lY2FwJywgJ2J1dHQnKTtcblxuICAgIGhpZ2hsaWdodFxuICAgICAgICAuYXR0cigneTEnLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmhlaWdodDsgfSlcbiAgICAgICAgLmNhbGwoc3R5bGVIaWdobGlnaHQpO1xufVxuXG5mdW5jdGlvbiBlbnN1cmVBeGlzQnJ1c2goYXhpc092ZXJsYXlzKSB7XG4gICAgdmFyIGF4aXNCcnVzaCA9IGF4aXNPdmVybGF5cy5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzQnJ1c2gpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNCcnVzaC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXNCcnVzaCwgdHJ1ZSk7XG5cbiAgICByZW5kZXJBeGlzQnJ1c2goYXhpc0JydXNoKTtcbn1cblxuZnVuY3Rpb24gZ2V0QnJ1c2hFeHRlbnQoYnJ1c2gpIHtcbiAgICByZXR1cm4gYnJ1c2guc3ZnQnJ1c2guZXh0ZW50Lm1hcChmdW5jdGlvbihlKSB7cmV0dXJuIGUuc2xpY2UoKTt9KTtcbn1cblxuZnVuY3Rpb24gYnJ1c2hDbGVhcihicnVzaCkge1xuICAgIGJydXNoLmZpbHRlclNwZWNpZmllZCA9IGZhbHNlO1xuICAgIGJydXNoLnN2Z0JydXNoLmV4dGVudCA9IFtbMCwgMV1dO1xufVxuXG5mdW5jdGlvbiBheGlzQnJ1c2hNb3ZlZChjYWxsYmFjaykge1xuICAgIHJldHVybiBmdW5jdGlvbiBheGlzQnJ1c2hNb3ZlZChkaW1lbnNpb24pIHtcbiAgICAgICAgdmFyIGJydXNoID0gZGltZW5zaW9uLmJydXNoO1xuICAgICAgICB2YXIgZXh0ZW50ID0gZ2V0QnJ1c2hFeHRlbnQoYnJ1c2gpO1xuICAgICAgICB2YXIgbmV3RXh0ZW50ID0gZXh0ZW50LnNsaWNlKCk7XG4gICAgICAgIGJydXNoLmZpbHRlci5zZXQobmV3RXh0ZW50KTtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBkZWR1cGVSZWFsUmFuZ2VzKGludGVydmFscykge1xuICAgIC8vIEZ1c2VzIGVsZW1lbnRzIG9mIGludGVydmFscyBpZiB0aGV5IG92ZXJsYXAsIHlpZWxkaW5nIGRpc2NvbnRpZ3VvdXMgaW50ZXJ2YWxzLCByZXN1bHRzLmxlbmd0aCA8PSBpbnRlcnZhbHMubGVuZ3RoXG4gICAgLy8gQ3VycmVudGx5IHVzZXMgY2xvc2VkIGludGVydmFscywgaWUuIGRlZHVwZVJlYWxSYW5nZXMoW1s0MDAsIDgwMF0sIFszMDAsIDQwMF1dKSAtPiBbMzAwLCA4MDBdXG4gICAgdmFyIHF1ZXVlID0gaW50ZXJ2YWxzLnNsaWNlKCk7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIHZhciBjdXJyZW50SW50ZXJ2YWw7XG4gICAgdmFyIGN1cnJlbnQgPSBxdWV1ZS5zaGlmdCgpO1xuICAgIHdoaWxlKGN1cnJlbnQpIHsgLy8gW10uc2hpZnQgPT09IHVuZGVmaW5lZCwgc28gd2UgZG9uJ3QgZGVzY2VuZCBpbnRvIGFuIGVtcHR5IGFycmF5XG4gICAgICAgIGN1cnJlbnRJbnRlcnZhbCA9IGN1cnJlbnQuc2xpY2UoKTtcbiAgICAgICAgd2hpbGUoKGN1cnJlbnQgPSBxdWV1ZS5zaGlmdCgpKSAmJiBjdXJyZW50WzBdIDw9IC8qIHJpZ2h0LW9wZW4gaW50ZXJ2YWwgd291bGQgbmVlZCBgPGAgKi8gY3VycmVudEludGVydmFsWzFdKSB7XG4gICAgICAgICAgICBjdXJyZW50SW50ZXJ2YWxbMV0gPSBNYXRoLm1heChjdXJyZW50SW50ZXJ2YWxbMV0sIGN1cnJlbnRbMV0pO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnRJbnRlcnZhbCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIG1ha2VGaWx0ZXIoKSB7XG4gICAgdmFyIGZpbHRlciA9IFtdO1xuICAgIHZhciBjb25zb2xpZGF0ZWQ7XG4gICAgdmFyIGJvdW5kcztcbiAgICByZXR1cm4ge1xuICAgICAgICBzZXQ6IGZ1bmN0aW9uKGEpIHtcbiAgICAgICAgICAgIGZpbHRlciA9IGFcbiAgICAgICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuc2xpY2UoKS5zb3J0KHNvcnRBc2MpOyB9KVxuICAgICAgICAgICAgICAgIC5zb3J0KHN0YXJ0QXNjKTtcbiAgICAgICAgICAgIGNvbnNvbGlkYXRlZCA9IGRlZHVwZVJlYWxSYW5nZXMoZmlsdGVyKTtcbiAgICAgICAgICAgIGJvdW5kcyA9IGZpbHRlci5yZWR1Y2UoZnVuY3Rpb24ocCwgbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBbTWF0aC5taW4ocFswXSwgblswXSksIE1hdGgubWF4KHBbMV0sIG5bMV0pXTtcbiAgICAgICAgICAgIH0sIFtJbmZpbml0eSwgLUluZmluaXR5XSk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBmaWx0ZXIuc2xpY2UoKTsgfSxcbiAgICAgICAgZ2V0Q29uc29saWRhdGVkOiBmdW5jdGlvbigpIHsgcmV0dXJuIGNvbnNvbGlkYXRlZDsgfSxcbiAgICAgICAgZ2V0Qm91bmRzOiBmdW5jdGlvbigpIHsgcmV0dXJuIGJvdW5kczsgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIG1ha2VCcnVzaChzdGF0ZSwgcmFuZ2VTcGVjaWZpZWQsIGluaXRpYWxSYW5nZSwgYnJ1c2hTdGFydENhbGxiYWNrLCBicnVzaENhbGxiYWNrLCBicnVzaEVuZENhbGxiYWNrKSB7XG4gICAgdmFyIGZpbHRlciA9IG1ha2VGaWx0ZXIoKTtcbiAgICBmaWx0ZXIuc2V0KGluaXRpYWxSYW5nZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsdGVyOiBmaWx0ZXIsXG4gICAgICAgIGZpbHRlclNwZWNpZmllZDogcmFuZ2VTcGVjaWZpZWQsIC8vIHRoZXJlJ3MgYSBkaWZmZXJlbmNlIGJldHdlZW4gbm90IGZpbHRlcmluZyBhbmQgZmlsdGVyaW5nIGEgbm9uLXByb3BlciBzdWJzZXRcbiAgICAgICAgc3ZnQnJ1c2g6IHtcbiAgICAgICAgICAgIGV4dGVudDogW10sIC8vIHRoaXMgaXMgd2hlcmUgdGhlIHN2Z0JydXNoIHdyaXRlcyBjb250ZW50cyBpbnRvXG4gICAgICAgICAgICBicnVzaFN0YXJ0Q2FsbGJhY2s6IGJydXNoU3RhcnRDYWxsYmFjayxcbiAgICAgICAgICAgIGJydXNoQ2FsbGJhY2s6IGF4aXNCcnVzaE1vdmVkKGJydXNoQ2FsbGJhY2spLFxuICAgICAgICAgICAgYnJ1c2hFbmRDYWxsYmFjazogYnJ1c2hFbmRDYWxsYmFja1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuLy8gZm9yIHVzZSBieSBzdXBwbHlEZWZhdWx0cywgYnV0IGl0IG5lZWRlZCB0b25zIG9mIHBpZWNlcyBmcm9tIGhlcmUgc29cbi8vIHNlZW1lZCB0byBtYWtlIG1vcmUgc2Vuc2UganVzdCB0byBwdXQgdGhlIHdob2xlIHJvdXRpbmUgaGVyZVxuZnVuY3Rpb24gY2xlYW5SYW5nZXMocmFuZ2VzLCBkaW1lbnNpb24pIHtcbiAgICBpZihBcnJheS5pc0FycmF5KHJhbmdlc1swXSkpIHtcbiAgICAgICAgcmFuZ2VzID0gcmFuZ2VzLm1hcChmdW5jdGlvbihyaSkgeyByZXR1cm4gcmkuc29ydChzb3J0QXNjKTsgfSk7XG5cbiAgICAgICAgaWYoIWRpbWVuc2lvbi5tdWx0aXNlbGVjdCkgcmFuZ2VzID0gW3Jhbmdlc1swXV07XG4gICAgICAgIGVsc2UgcmFuZ2VzID0gZGVkdXBlUmVhbFJhbmdlcyhyYW5nZXMuc29ydChzdGFydEFzYykpO1xuICAgIH1cbiAgICBlbHNlIHJhbmdlcyA9IFtyYW5nZXMuc29ydChzb3J0QXNjKV07XG5cbiAgICAvLyBvcmRpbmFsIHNuYXBwaW5nXG4gICAgaWYoZGltZW5zaW9uLnRpY2t2YWxzKSB7XG4gICAgICAgIHZhciBzb3J0ZWRUaWNrVmFscyA9IGRpbWVuc2lvbi50aWNrdmFscy5zbGljZSgpLnNvcnQoc29ydEFzYyk7XG4gICAgICAgIHJhbmdlcyA9IHJhbmdlcy5tYXAoZnVuY3Rpb24ocmkpIHtcbiAgICAgICAgICAgIHZhciByU25hcHBlZCA9IFtcbiAgICAgICAgICAgICAgICBvcmRpbmFsU2NhbGVTbmFwTG8oc29ydGVkVGlja1ZhbHMsIHJpWzBdLCBbXSksXG4gICAgICAgICAgICAgICAgb3JkaW5hbFNjYWxlU25hcEhpKHNvcnRlZFRpY2tWYWxzLCByaVsxXSwgW10pXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYoclNuYXBwZWRbMV0gPiByU25hcHBlZFswXSkgcmV0dXJuIHJTbmFwcGVkO1xuICAgICAgICB9KVxuICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKHJpKSB7IHJldHVybiByaTsgfSk7XG5cbiAgICAgICAgaWYoIXJhbmdlcy5sZW5ndGgpIHJldHVybjtcbiAgICB9XG4gICAgcmV0dXJuIHJhbmdlcy5sZW5ndGggPiAxID8gcmFuZ2VzIDogcmFuZ2VzWzBdO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtYWtlQnJ1c2g6IG1ha2VCcnVzaCxcbiAgICBlbnN1cmVBeGlzQnJ1c2g6IGVuc3VyZUF4aXNCcnVzaCxcbiAgICBjbGVhblJhbmdlczogY2xlYW5SYW5nZXNcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgZ2V0TW9kdWxlQ2FsY0RhdGEgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldE1vZHVsZUNhbGNEYXRhO1xudmFyIHBhcmNvb3Jkc1Bsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcbnZhciB4bWxuc05hbWVzcGFjZXMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xuXG52YXIgUEFSQ09PUkRTID0gJ3BhcmNvb3Jkcyc7XG5cbmV4cG9ydHMubmFtZSA9IFBBUkNPT1JEUztcblxuZXhwb3J0cy5wbG90ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgY2FsY0RhdGEgPSBnZXRNb2R1bGVDYWxjRGF0YShnZC5jYWxjZGF0YSwgUEFSQ09PUkRTKVswXTtcbiAgICBpZihjYWxjRGF0YS5sZW5ndGgpIHBhcmNvb3Jkc1Bsb3QoZ2QsIGNhbGNEYXRhKTtcbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkUGFyY29vcmRzID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoUEFSQ09PUkRTKSk7XG4gICAgdmFyIGhhc1BhcmNvb3JkcyA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKFBBUkNPT1JEUykpO1xuXG4gICAgaWYoaGFkUGFyY29vcmRzICYmICFoYXNQYXJjb29yZHMpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fcGFwZXJkaXYuc2VsZWN0QWxsKCcucGFyY29vcmRzJykucmVtb3ZlKCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX2dsaW1hZ2VzLnNlbGVjdEFsbCgnKicpLnJlbW92ZSgpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMudG9TVkcgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBpbWFnZVJvb3QgPSBnZC5fZnVsbExheW91dC5fZ2xpbWFnZXM7XG4gICAgdmFyIHJvb3QgPSBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnLnN2Zy1jb250YWluZXInKTtcbiAgICB2YXIgY2FudmFzZXMgPSByb290LmZpbHRlcihmdW5jdGlvbihkLCBpKSB7cmV0dXJuIGkgPT09IHJvb3Quc2l6ZSgpIC0gMTt9KVxuICAgICAgICAuc2VsZWN0QWxsKCcuZ2wtY2FudmFzLWNvbnRleHQsIC5nbC1jYW52YXMtZm9jdXMnKTtcblxuICAgIGZ1bmN0aW9uIGNhbnZhc1RvSW1hZ2UoKSB7XG4gICAgICAgIHZhciBjYW52YXMgPSB0aGlzO1xuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGltYWdlUm9vdC5hcHBlbmQoJ3N2ZzppbWFnZScpO1xuXG4gICAgICAgIGltYWdlLmF0dHIoe1xuICAgICAgICAgICAgeG1sbnM6IHhtbG5zTmFtZXNwYWNlcy5zdmcsXG4gICAgICAgICAgICAneGxpbms6aHJlZic6IGltYWdlRGF0YSxcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICdub25lJyxcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgd2lkdGg6IGNhbnZhcy53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogY2FudmFzLmhlaWdodFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjYW52YXNlcy5lYWNoKGNhbnZhc1RvSW1hZ2UpO1xuXG4gICAgLy8gQ2hyb21lIC8gU2FmYXJpIGJ1ZyB3b3JrYXJvdW5kIC0gYnJvd3NlciBhcHBhcmVudGx5IGxvc2VzIGNvbm5lY3Rpb24gdG8gdGhlIGRlZmluZWQgcGF0dGVyblxuICAgIC8vIFdpdGhvdXQgdGhlIHdvcmthcm91bmQsIHRoZXNlIGJyb3dzZXJzICdsb3NlJyB0aGUgZmlsdGVyIGJydXNoIHN0eWxpbmcgKGNvbG9yIGV0Yy4pIGFmdGVyIGEgc25hcHNob3RcbiAgICAvLyBvbiBhIHN1YnNlcXVlbnQgaW50ZXJhY3Rpb24uXG4gICAgLy8gRmlyZWZveCB3b3JrcyBmaW5lIHdpdGhvdXQgdGhpcyB3b3JrYXJvdW5kXG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIGQzLnNlbGVjdEFsbCgnI2ZpbHRlckJhclBhdHRlcm4nKVxuICAgICAgICAgICAgLmF0dHIoJ2lkJywgJ2ZpbHRlckJhclBhdHRlcm4nKTtcbiAgICB9LCA2MCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGFzQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oYXNfY29sb3JzY2FsZScpO1xudmFyIGNhbGNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciB3cmFwID0gcmVxdWlyZSgnLi4vLi4vbGliL2d1cCcpLndyYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY3MgPSAhIXRyYWNlLmxpbmUuY29sb3JzY2FsZSAmJiBMaWIuaXNBcnJheU9yVHlwZWRBcnJheSh0cmFjZS5saW5lLmNvbG9yKTtcbiAgICB2YXIgY29sb3IgPSBjcyA/IHRyYWNlLmxpbmUuY29sb3IgOiBjb25zdEhhbGYodHJhY2UuX2xlbmd0aCk7XG4gICAgdmFyIGNzY2FsZSA9IGNzID8gdHJhY2UubGluZS5jb2xvcnNjYWxlIDogW1swLCB0cmFjZS5saW5lLmNvbG9yXSwgWzEsIHRyYWNlLmxpbmUuY29sb3JdXTtcblxuICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2UsICdsaW5lJykpIHtcbiAgICAgICAgY2FsY0NvbG9yc2NhbGUodHJhY2UsIGNvbG9yLCAnbGluZScsICdjJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdyYXAoe1xuICAgICAgICBsaW5lQ29sb3I6IGNvbG9yLFxuICAgICAgICBjc2NhbGU6IGNzY2FsZVxuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gY29uc3RIYWxmKGxlbikge1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gMC41O1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1heERpbWVuc2lvbkNvdW50OiA2MCwgLy8gdGhpcyBjYW5ub3QgYmUgaW5jcmVhc2VkIHdpdGhvdXQgV2ViR0wgY29kZSByZWZhY3RvcmluZ1xuICAgIG92ZXJkcmFnOiA0NSxcbiAgICB2ZXJ0aWNhbFBhZGRpbmc6IDIsIC8vIG90aGVyd2lzZSwgaG9yaXpvbnRhbCBsaW5lcyBvbiB0b3Agb3IgYm90dG9tIGFyZSBvZiBsb3dlciB3aWR0aFxuICAgIHRpY2tEaXN0YW5jZTogNTAsXG4gICAgY2FudmFzUGl4ZWxSYXRpbzogMSxcbiAgICBibG9ja0xpbmVDb3VudDogNTAwMCxcbiAgICBsYXllcnM6IFsnY29udGV4dExpbmVMYXllcicsICdmb2N1c0xpbmVMYXllcicsICdwaWNrTGluZUxheWVyJ10sXG4gICAgYXhpc1RpdGxlT2Zmc2V0OiAyOCxcbiAgICBheGlzRXh0ZW50T2Zmc2V0OiAxMCxcbiAgICBiYXI6IHtcbiAgICAgICAgd2lkdGg6IDQsIC8vIFZpc2libGUgd2lkdGggb2YgdGhlIGZpbHRlciBiYXJcbiAgICAgICAgY2FwdHVyZVdpZHRoOiAxMCwgLy8gTW91c2Utc2Vuc2l0aXZlIHdpZHRoIGZvciBpbnRlcmFjdGlvbiAoRml0dHMgbGF3KVxuICAgICAgICBmaWxsQ29sb3I6ICdtYWdlbnRhJywgLy8gQ29sb3Igb2YgdGhlIGZpbHRlciBiYXIgZmlsbFxuICAgICAgICBmaWxsT3BhY2l0eTogMSwgLy8gRmlsdGVyIGJhciBmaWxsIG9wYWNpdHlcbiAgICAgICAgc25hcER1cmF0aW9uOiAxNTAsIC8vIHR3ZWVuIGR1cmF0aW9uIGluIG1zIGZvciBicnVzaCBzbmFwIGZvciBvcmRpbmFsIGF4ZXNcbiAgICAgICAgc25hcFJhdGlvOiAwLjI1LCAvLyByYXRpbyBvZiBiYXIgZXh0ZW5zaW9uIHJlbGF0aXZlIHRvIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBhZGphY2VudCBvcmRpbmFsIHZhbHVlc1xuICAgICAgICBzbmFwQ2xvc2U6IDAuMDEsIC8vIGZyYWN0aW9uIG9mIGludGVyLXZhbHVlIGRpc3RhbmNlIHRvIHNuYXAgdG8gdGhlIGNsb3NlciBvbmUsIGV2ZW4gaWYgeW91J3JlIG5vdCBvdmVyIGl0XG4gICAgICAgIHN0cm9rZUNvbG9yOiAnd2hpdGUnLCAvLyBDb2xvciBvZiB0aGUgZmlsdGVyIGJhciBzaWRlIGxpbmVzXG4gICAgICAgIHN0cm9rZU9wYWNpdHk6IDEsIC8vIEZpbHRlciBiYXIgc2lkZSBzdHJva2Ugb3BhY2l0eVxuICAgICAgICBzdHJva2VXaWR0aDogMSwgLy8gRmlsdGVyIGJhciBzaWRlIHN0cm9rZSB3aWR0aCBpbiBwaXhlbHNcbiAgICAgICAgaGFuZGxlSGVpZ2h0OiA4LCAvLyBIZWlnaHQgb2YgdGhlIGZpbHRlciBiYXIgdmVydGljYWwgcmVzaXplIGFyZWFzIG9uIHRvcCBhbmQgYm90dG9tXG4gICAgICAgIGhhbmRsZU9wYWNpdHk6IDEsIC8vIE9wYWNpdHkgb2YgdGhlIGZpbHRlciBiYXIgdmVydGljYWwgcmVzaXplIGFyZWFzIG9uIHRvcCBhbmQgYm90dG9tXG4gICAgICAgIGhhbmRsZU92ZXJsYXA6IDAgLy8gQSBsYXJnZXIgdGhhbiAwIHZhbHVlIGNhdXNlcyBvdmVybGFwcyB3aXRoIHRoZSBmaWx0ZXIgYmFyLCByZXByZXNlbnRlZCBhcyBwaXhlbHNcbiAgICB9LFxuICAgIGNuOiB7XG4gICAgICAgIGF4aXNFeHRlbnRUZXh0OiAnYXhpcy1leHRlbnQtdGV4dCcsXG4gICAgICAgIHBhcmNvb3Jkc0xpbmVMYXllcnM6ICdwYXJjb29yZHMtbGluZS1sYXllcnMnLFxuICAgICAgICBwYXJjb29yZHNMaW5lTGF5ZXI6ICdwYXJjb29yZHMtbGluZXMnLFxuICAgICAgICBwYXJjb29yZHM6ICdwYXJjb29yZHMnLFxuICAgICAgICBwYXJjb29yZHNDb250cm9sVmlldzogJ3BhcmNvb3Jkcy1jb250cm9sLXZpZXcnLFxuICAgICAgICB5QXhpczogJ3ktYXhpcycsXG4gICAgICAgIGF4aXNPdmVybGF5czogJ2F4aXMtb3ZlcmxheXMnLFxuICAgICAgICBheGlzOiAnYXhpcycsXG4gICAgICAgIGF4aXNIZWFkaW5nOiAnYXhpcy1oZWFkaW5nJyxcbiAgICAgICAgYXhpc1RpdGxlOiAnYXhpcy10aXRsZScsXG4gICAgICAgIGF4aXNFeHRlbnQ6ICdheGlzLWV4dGVudCcsXG4gICAgICAgIGF4aXNFeHRlbnRUb3A6ICdheGlzLWV4dGVudC10b3AnLFxuICAgICAgICBheGlzRXh0ZW50VG9wVGV4dDogJ2F4aXMtZXh0ZW50LXRvcC10ZXh0JyxcbiAgICAgICAgYXhpc0V4dGVudEJvdHRvbTogJ2F4aXMtZXh0ZW50LWJvdHRvbScsXG4gICAgICAgIGF4aXNFeHRlbnRCb3R0b21UZXh0OiAnYXhpcy1leHRlbnQtYm90dG9tLXRleHQnLFxuICAgICAgICBheGlzQnJ1c2g6ICdheGlzLWJydXNoJ1xuICAgIH0sXG4gICAgaWQ6IHtcbiAgICAgICAgZmlsdGVyQmFyUGF0dGVybjogJ2ZpbHRlci1iYXItcGF0dGVybidcblxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hhc19jb2xvcnNjYWxlJyk7XG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgYXhpc0JydXNoID0gcmVxdWlyZSgnLi9heGlzYnJ1c2gnKTtcbnZhciBtYXhEaW1lbnNpb25Db3VudCA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJykubWF4RGltZW5zaW9uQ291bnQ7XG52YXIgbWVyZ2VMZW5ndGggPSByZXF1aXJlKCcuL21lcmdlX2xlbmd0aCcpO1xuXG5mdW5jdGlvbiBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlKCdsaW5lLmNvbG9yJywgZGVmYXVsdENvbG9yKTtcblxuICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2VJbiwgJ2xpbmUnKSAmJiBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShsaW5lQ29sb3IpKSB7XG4gICAgICAgIGlmKGxpbmVDb2xvci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnbGluZS5jb2xvcnNjYWxlJyk7XG4gICAgICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbGluZS4nLCBjTGV0dGVyOiAnYyd9KTtcbiAgICAgICAgICAgIC8vIFRPRE86IEkgdGhpbmsgaXQgd291bGQgYmUgYmV0dGVyIHRvIGtlZXAgc2hvd2luZyBsaW5lcyBiZXlvbmQgdGhlIGxhc3QgbGluZSBjb2xvclxuICAgICAgICAgICAgLy8gYnV0IEknbSBub3Qgc3VyZSB3aGF0IGNvbG9yIHRvIGdpdmUgdGhlc2UgbGluZXMgLSBwcm9iYWJseSBibGFjayBvciB3aGl0ZVxuICAgICAgICAgICAgLy8gZGVwZW5kaW5nIG9uIHRoZSBiYWNrZ3JvdW5kIGNvbG9yP1xuICAgICAgICAgICAgcmV0dXJuIGxpbmVDb2xvci5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0cmFjZU91dC5saW5lLmNvbG9yID0gZGVmYXVsdENvbG9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJbmZpbml0eTtcbn1cblxuZnVuY3Rpb24gZGltZW5zaW9uRGVmYXVsdHMoZGltZW5zaW9uSW4sIGRpbWVuc2lvbk91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGRpbWVuc2lvbkluLCBkaW1lbnNpb25PdXQsIGF0dHJpYnV0ZXMuZGltZW5zaW9ucywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlcyA9IGNvZXJjZSgndmFsdWVzJyk7XG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICBpZighKHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKSkge1xuICAgICAgICB2aXNpYmxlID0gZGltZW5zaW9uT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICAgICAgY29lcmNlKCd0aWNrdmFscycpO1xuICAgICAgICBjb2VyY2UoJ3RpY2t0ZXh0Jyk7XG4gICAgICAgIGNvZXJjZSgndGlja2Zvcm1hdCcpO1xuICAgICAgICBjb2VyY2UoJ3JhbmdlJyk7XG5cbiAgICAgICAgY29lcmNlKCdtdWx0aXNlbGVjdCcpO1xuICAgICAgICB2YXIgY29uc3RyYWludFJhbmdlID0gY29lcmNlKCdjb25zdHJhaW50cmFuZ2UnKTtcbiAgICAgICAgaWYoY29uc3RyYWludFJhbmdlKSB7XG4gICAgICAgICAgICBkaW1lbnNpb25PdXQuY29uc3RyYWludHJhbmdlID0gYXhpc0JydXNoLmNsZWFuUmFuZ2VzKGNvbnN0cmFpbnRSYW5nZSwgZGltZW5zaW9uT3V0KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGRpbWVuc2lvbnNJbiA9IHRyYWNlSW4uZGltZW5zaW9ucztcbiAgICBpZihBcnJheS5pc0FycmF5KGRpbWVuc2lvbnNJbikgJiYgZGltZW5zaW9uc0luLmxlbmd0aCA+IG1heERpbWVuc2lvbkNvdW50KSB7XG4gICAgICAgIExpYi5sb2coJ3BhcmNvb3JkcyB0cmFjZXMgc3VwcG9ydCB1cCB0byAnICsgbWF4RGltZW5zaW9uQ291bnQgKyAnIGRpbWVuc2lvbnMgYXQgdGhlIG1vbWVudCcpO1xuICAgICAgICBkaW1lbnNpb25zSW4uc3BsaWNlKG1heERpbWVuc2lvbkNvdW50KTtcbiAgICB9XG5cbiAgICB2YXIgZGltZW5zaW9ucyA9IGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIHtcbiAgICAgICAgbmFtZTogJ2RpbWVuc2lvbnMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGRpbWVuc2lvbkRlZmF1bHRzXG4gICAgfSk7XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShkaW1lbnNpb25zKSB8fCAhZGltZW5zaW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIG1lcmdlTGVuZ3RoKHRyYWNlT3V0LCBkaW1lbnNpb25zLCAndmFsdWVzJywgbGVuKTtcblxuICAgIC8vIG1ha2UgZGVmYXVsdCBmb250IHNpemUgMTBweCAoZGVmYXVsdCBpcyAxMiksXG4gICAgLy8gc2NhbGUgbGluZWFybHkgd2l0aCBnbG9iYWwgZm9udCBzaXplXG4gICAgdmFyIGZvbnREZmx0ID0ge1xuICAgICAgICBmYW1pbHk6IGxheW91dC5mb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChsYXlvdXQuZm9udC5zaXplIC8gMS4yKSxcbiAgICAgICAgY29sb3I6IGxheW91dC5mb250LmNvbG9yXG4gICAgfTtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2xhYmVsZm9udCcsIGZvbnREZmx0KTtcbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aWNrZm9udCcsIGZvbnREZmx0KTtcbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdyYW5nZWZvbnQnLCBmb250RGZsdCk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUGFyY29vcmRzID0ge307XG5cblBhcmNvb3Jkcy5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5QYXJjb29yZHMuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5QYXJjb29yZHMuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuUGFyY29vcmRzLnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcblBhcmNvb3Jkcy5jb2xvcmJhciA9IHtcbiAgICBjb250YWluZXI6ICdsaW5lJyxcbiAgICBtaW46ICdjbWluJyxcbiAgICBtYXg6ICdjbWF4J1xufTtcblxuUGFyY29vcmRzLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuUGFyY29vcmRzLm5hbWUgPSAncGFyY29vcmRzJztcblBhcmNvb3Jkcy5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4vYmFzZV9wbG90Jyk7XG5QYXJjb29yZHMuY2F0ZWdvcmllcyA9IFsnZ2wnLCAncmVnbCcsICdub09wYWNpdHknXTtcblBhcmNvb3Jkcy5tZXRhID0ge1xuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBQYXJjb29yZHM7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBnbHNsaWZ5ID0gcmVxdWlyZSgnZ2xzbGlmeScpO1xudmFyIHZlcnRleFNoYWRlclNvdXJjZSA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzQgcDAsIHAxLCBwMiwgcDMsXFxuICAgICAgICAgICAgICAgcDQsIHA1LCBwNiwgcDcsXFxuICAgICAgICAgICAgICAgcDgsIHA5LCBwYSwgcGIsXFxuICAgICAgICAgICAgICAgcGMsIHBkLCBwZTtcXG5cXG5hdHRyaWJ1dGUgdmVjNCBwZjtcXG5cXG51bmlmb3JtIG1hdDQgZGltMUEsIGRpbTJBLCBkaW0xQiwgZGltMkIsIGRpbTFDLCBkaW0yQywgZGltMUQsIGRpbTJELFxcbiAgICAgICAgICAgICBsb0EsIGhpQSwgbG9CLCBoaUIsIGxvQywgaGlDLCBsb0QsIGhpRDtcXG5cXG51bmlmb3JtIHZlYzIgcmVzb2x1dGlvbixcXG4gICAgICAgICAgICAgdmlld0JveFBvc2l0aW9uLFxcbiAgICAgICAgICAgICB2aWV3Qm94U2l6ZTtcXG5cXG51bmlmb3JtIHNhbXBsZXIyRCBwYWxldHRlO1xcbnVuaWZvcm0gc2FtcGxlcjJEIG1hc2s7XFxudW5pZm9ybSBmbG9hdCBtYXNrSGVpZ2h0O1xcblxcbnVuaWZvcm0gdmVjMiBjb2xvckNsYW1wO1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudmVjNCB1bml0XzEgPSB2ZWM0KDEsIDEsIDEsIDEpO1xcblxcbmZsb2F0IHZhbChtYXQ0IHAsIG1hdDQgdikge1xcbiAgICByZXR1cm4gZG90KG1hdHJpeENvbXBNdWx0KHAsIHYpICogdW5pdF8xLCB1bml0XzEpO1xcbn1cXG5cXG5mbG9hdCBheGlzWShcXG4gICAgICAgIGZsb2F0IHgsXFxuICAgICAgICBtYXQ0IGRbNF0sXFxuICAgICAgICBtYXQ0IGRpbTFBLCBtYXQ0IGRpbTJBLCBtYXQ0IGRpbTFCLCBtYXQ0IGRpbTJCLCBtYXQ0IGRpbTFDLCBtYXQ0IGRpbTJDLCBtYXQ0IGRpbTFELCBtYXQ0IGRpbTJEXFxuICAgICkge1xcblxcbiAgICBmbG9hdCB5MSA9IHZhbChkWzBdLCBkaW0xQSkgKyB2YWwoZFsxXSwgZGltMUIpICsgdmFsKGRbMl0sIGRpbTFDKSArIHZhbChkWzNdLCBkaW0xRCk7XFxuICAgIGZsb2F0IHkyID0gdmFsKGRbMF0sIGRpbTJBKSArIHZhbChkWzFdLCBkaW0yQikgKyB2YWwoZFsyXSwgZGltMkMpICsgdmFsKGRbM10sIGRpbTJEKTtcXG4gICAgcmV0dXJuIHkxICogKDEuMCAtIHgpICsgeTIgKiB4O1xcbn1cXG5cXG5jb25zdCBpbnQgYml0c1BlckJ5dGUgPSA4O1xcblxcbmludCBtb2QyKGludCBhKSB7XFxuICAgIHJldHVybiBhIC0gMiAqIChhIC8gMik7XFxufVxcblxcbmludCBtb2Q4KGludCBhKSB7XFxuICAgIHJldHVybiBhIC0gOCAqIChhIC8gOCk7XFxufVxcblxcbnZlYzQgemVybyA9IHZlYzQoMCwgMCwgMCwgMCk7XFxudmVjNCB1bml0XzAgPSB2ZWM0KDEsIDEsIDEsIDEpO1xcbnZlYzIgeHlQcm9qZWN0aW9uID0gdmVjMigxLCAxKTtcXG5cXG5tYXQ0IG1jbGFtcChtYXQ0IG0sIG1hdDQgbG8sIG1hdDQgaGkpIHtcXG4gICAgcmV0dXJuIG1hdDQoY2xhbXAobVswXSwgbG9bMF0sIGhpWzBdKSxcXG4gICAgICAgICAgICAgICAgY2xhbXAobVsxXSwgbG9bMV0sIGhpWzFdKSxcXG4gICAgICAgICAgICAgICAgY2xhbXAobVsyXSwgbG9bMl0sIGhpWzJdKSxcXG4gICAgICAgICAgICAgICAgY2xhbXAobVszXSwgbG9bM10sIGhpWzNdKSk7XFxufVxcblxcbmJvb2wgbXNob3cobWF0NCBwLCBtYXQ0IGxvLCBtYXQ0IGhpKSB7XFxuICAgIHJldHVybiBtY2xhbXAocCwgbG8sIGhpKSA9PSBwO1xcbn1cXG5cXG5ib29sIHdpdGhpbkJvdW5kaW5nQm94KFxcbiAgICAgICAgbWF0NCBkWzRdLFxcbiAgICAgICAgbWF0NCBsb0EsIG1hdDQgaGlBLCBtYXQ0IGxvQiwgbWF0NCBoaUIsIG1hdDQgbG9DLCBtYXQ0IGhpQywgbWF0NCBsb0QsIG1hdDQgaGlEXFxuICAgICkge1xcblxcbiAgICByZXR1cm4gbXNob3coZFswXSwgbG9BLCBoaUEpICYmXFxuICAgICAgICAgICBtc2hvdyhkWzFdLCBsb0IsIGhpQikgJiZcXG4gICAgICAgICAgIG1zaG93KGRbMl0sIGxvQywgaGlDKSAmJlxcbiAgICAgICAgICAgbXNob3coZFszXSwgbG9ELCBoaUQpO1xcbn1cXG5cXG5ib29sIHdpdGhpblJhc3Rlck1hc2sobWF0NCBkWzRdLCBzYW1wbGVyMkQgbWFzaywgZmxvYXQgaGVpZ2h0KSB7XFxuICAgIGJvb2wgcmVzdWx0ID0gdHJ1ZTtcXG4gICAgaW50IGJpdEluQnl0ZVN0ZXBwZXI7XFxuICAgIGZsb2F0IHZhbFksIHZhbHVlWSwgc2NhbGVYO1xcbiAgICBpbnQgaGl0LCBiaXRtYXNrLCB2YWxYO1xcbiAgICBmb3IoaW50IGkgPSAwOyBpIDwgNDsgaSsrKSB7XFxuICAgICAgICBmb3IoaW50IGogPSAwOyBqIDwgNDsgaisrKSB7XFxuICAgICAgICAgICAgZm9yKGludCBrID0gMDsgayA8IDQ7IGsrKykge1xcbiAgICAgICAgICAgICAgICBiaXRJbkJ5dGVTdGVwcGVyID0gbW9kOChqICogNCArIGspO1xcbiAgICAgICAgICAgICAgICB2YWxYID0gaSAqIDIgKyBqIC8gMjtcXG4gICAgICAgICAgICAgICAgdmFsWSA9IGRbaV1bal1ba107XFxuICAgICAgICAgICAgICAgIHZhbHVlWSA9IHZhbFkgKiAoaGVpZ2h0IC0gMS4wKSArIDAuNTtcXG4gICAgICAgICAgICAgICAgc2NhbGVYID0gKGZsb2F0KHZhbFgpICsgMC41KSAvIDguMDtcXG4gICAgICAgICAgICAgICAgaGl0ID0gaW50KHRleHR1cmUyRChtYXNrLCB2ZWMyKHNjYWxlWCwgKHZhbHVlWSArIDAuNSkgLyBoZWlnaHQpKVszXSAqIDI1NS4wKSAvIGludChwb3coMi4wLCBmbG9hdChiaXRJbkJ5dGVTdGVwcGVyKSkpO1xcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQgJiYgbW9kMihoaXQpID09IDE7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIHJldHVybiByZXN1bHQ7XFxufVxcblxcbnZlYzQgcG9zaXRpb24oXFxuICAgICAgICBmbG9hdCBkZXB0aCxcXG4gICAgICAgIHZlYzIgcmVzb2x1dGlvbiwgdmVjMiB2aWV3Qm94UG9zaXRpb24sIHZlYzIgdmlld0JveFNpemUsXFxuICAgICAgICBtYXQ0IGRpbXNbNF0sXFxuICAgICAgICBmbG9hdCBzaWdudW0sXFxuICAgICAgICBtYXQ0IGRpbTFBLCBtYXQ0IGRpbTJBLCBtYXQ0IGRpbTFCLCBtYXQ0IGRpbTJCLCBtYXQ0IGRpbTFDLCBtYXQ0IGRpbTJDLCBtYXQ0IGRpbTFELCBtYXQ0IGRpbTJELFxcbiAgICAgICAgbWF0NCBsb0EsIG1hdDQgaGlBLCBtYXQ0IGxvQiwgbWF0NCBoaUIsIG1hdDQgbG9DLCBtYXQ0IGhpQywgbWF0NCBsb0QsIG1hdDQgaGlELFxcbiAgICAgICAgc2FtcGxlcjJEIG1hc2ssIGZsb2F0IG1hc2tIZWlnaHRcXG4gICAgKSB7XFxuXFxuICAgIGZsb2F0IHggPSAwLjUgKiBzaWdudW0gKyAwLjU7XFxuICAgIGZsb2F0IHkgPSBheGlzWSh4LCBkaW1zLCBkaW0xQSwgZGltMkEsIGRpbTFCLCBkaW0yQiwgZGltMUMsIGRpbTJDLCBkaW0xRCwgZGltMkQpO1xcblxcbiAgICBmbG9hdCBzaG93ID0gZmxvYXQoXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpdGhpbkJvdW5kaW5nQm94KGRpbXMsIGxvQSwgaGlBLCBsb0IsIGhpQiwgbG9DLCBoaUMsIGxvRCwgaGlEKVxcbiAgICAgICAgICAgICAgICAgICAgICAgICAmJiB3aXRoaW5SYXN0ZXJNYXNrKGRpbXMsIG1hc2ssIG1hc2tIZWlnaHQpXFxuICAgICAgICAgICAgICAgICAgICAgICk7XFxuXFxuICAgIHZlYzIgdmlld0JveFhZID0gdmlld0JveFBvc2l0aW9uICsgdmlld0JveFNpemUgKiB2ZWMyKHgsIHkpO1xcbiAgICBmbG9hdCBkZXB0aE9ySGlkZSA9IGRlcHRoICsgMi4wICogKDEuMCAtIHNob3cpO1xcblxcbiAgICByZXR1cm4gdmVjNChcXG4gICAgICAgIHh5UHJvamVjdGlvbiAqICgyLjAgKiB2aWV3Qm94WFkgLyByZXNvbHV0aW9uIC0gMS4wKSxcXG4gICAgICAgIGRlcHRoT3JIaWRlLFxcbiAgICAgICAgMS4wXFxuICAgICk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG5cXG4gICAgZmxvYXQgcHJvbWluZW5jZSA9IGFicyhwZlszXSk7XFxuXFxuICAgIG1hdDQgcFs0XTtcXG4gICAgcFswXSA9IG1hdDQocDAsIHAxLCBwMiwgcDMpO1xcbiAgICBwWzFdID0gbWF0NChwNCwgcDUsIHA2LCBwNyk7XFxuICAgIHBbMl0gPSBtYXQ0KHA4LCBwOSwgcGEsIHBiKTtcXG4gICAgcFszXSA9IG1hdDQocGMsIHBkLCBwZSwgYWJzKHBmKSk7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gcG9zaXRpb24oXFxuICAgICAgICAxLjAgLSBwcm9taW5lbmNlLFxcbiAgICAgICAgcmVzb2x1dGlvbiwgdmlld0JveFBvc2l0aW9uLCB2aWV3Qm94U2l6ZSxcXG4gICAgICAgIHAsXFxuICAgICAgICBzaWduKHBmWzNdKSxcXG4gICAgICAgIGRpbTFBLCBkaW0yQSwgZGltMUIsIGRpbTJCLCBkaW0xQywgZGltMkMsIGRpbTFELCBkaW0yRCxcXG4gICAgICAgIGxvQSwgaGlBLCBsb0IsIGhpQiwgbG9DLCBoaUMsIGxvRCwgaGlELFxcbiAgICAgICAgbWFzaywgbWFza0hlaWdodFxcbiAgICApO1xcblxcbiAgICBmbG9hdCBjbGFtcGVkQ29sb3JJbmRleCA9IGNsYW1wKChwcm9taW5lbmNlIC0gY29sb3JDbGFtcFswXSkgLyAoY29sb3JDbGFtcFsxXSAtIGNvbG9yQ2xhbXBbMF0pLCAwLjAsIDEuMCk7XFxuICAgIGZyYWdDb2xvciA9IHRleHR1cmUyRChwYWxldHRlLCB2ZWMyKChjbGFtcGVkQ29sb3JJbmRleCAqIDI1NS4wICsgMC41KSAvIDI1Ni4wLCAwLjUpKTtcXG59XFxuXCJdKTtcbnZhciBjb250ZXh0U2hhZGVyU291cmNlID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjNCBwMCwgcDEsIHAyLCBwMyxcXG4gICAgICAgICAgICAgICBwNCwgcDUsIHA2LCBwNyxcXG4gICAgICAgICAgICAgICBwOCwgcDksIHBhLCBwYixcXG4gICAgICAgICAgICAgICBwYywgcGQsIHBlO1xcblxcbmF0dHJpYnV0ZSB2ZWM0IHBmO1xcblxcbnVuaWZvcm0gbWF0NCBkaW0xQSwgZGltMkEsIGRpbTFCLCBkaW0yQiwgZGltMUMsIGRpbTJDLCBkaW0xRCwgZGltMkQ7XFxuXFxudW5pZm9ybSB2ZWMyIHJlc29sdXRpb24sXFxuICAgICAgICAgICAgIHZpZXdCb3hQb3NpdGlvbixcXG4gICAgICAgICAgICAgdmlld0JveFNpemU7XFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgcGFsZXR0ZTtcXG5cXG51bmlmb3JtIHZlYzIgY29sb3JDbGFtcDtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZlYzIgeHlQcm9qZWN0aW9uID0gdmVjMigxLCAxKTtcXG5cXG52ZWM0IHVuaXQgPSB2ZWM0KDEsIDEsIDEsIDEpO1xcblxcbmZsb2F0IHZhbChtYXQ0IHAsIG1hdDQgdikge1xcbiAgICByZXR1cm4gZG90KG1hdHJpeENvbXBNdWx0KHAsIHYpICogdW5pdCwgdW5pdCk7XFxufVxcblxcbmZsb2F0IGF4aXNZKFxcbiAgICAgICAgZmxvYXQgeCxcXG4gICAgICAgIG1hdDQgZFs0XSxcXG4gICAgICAgIG1hdDQgZGltMUEsIG1hdDQgZGltMkEsIG1hdDQgZGltMUIsIG1hdDQgZGltMkIsIG1hdDQgZGltMUMsIG1hdDQgZGltMkMsIG1hdDQgZGltMUQsIG1hdDQgZGltMkRcXG4gICAgKSB7XFxuXFxuICAgIGZsb2F0IHkxID0gdmFsKGRbMF0sIGRpbTFBKSArIHZhbChkWzFdLCBkaW0xQikgKyB2YWwoZFsyXSwgZGltMUMpICsgdmFsKGRbM10sIGRpbTFEKTtcXG4gICAgZmxvYXQgeTIgPSB2YWwoZFswXSwgZGltMkEpICsgdmFsKGRbMV0sIGRpbTJCKSArIHZhbChkWzJdLCBkaW0yQykgKyB2YWwoZFszXSwgZGltMkQpO1xcbiAgICByZXR1cm4geTEgKiAoMS4wIC0geCkgKyB5MiAqIHg7XFxufVxcblxcbnZlYzQgcG9zaXRpb24oXFxuICAgICAgICBmbG9hdCBkZXB0aCxcXG4gICAgICAgIHZlYzIgcmVzb2x1dGlvbiwgdmVjMiB2aWV3Qm94UG9zaXRpb24sIHZlYzIgdmlld0JveFNpemUsXFxuICAgICAgICBtYXQ0IGRpbXNbNF0sXFxuICAgICAgICBmbG9hdCBzaWdudW0sXFxuICAgICAgICBtYXQ0IGRpbTFBLCBtYXQ0IGRpbTJBLCBtYXQ0IGRpbTFCLCBtYXQ0IGRpbTJCLCBtYXQ0IGRpbTFDLCBtYXQ0IGRpbTJDLCBtYXQ0IGRpbTFELCBtYXQ0IGRpbTJEXFxuICAgICkge1xcblxcbiAgICBmbG9hdCB4ID0gMC41ICogc2lnbnVtICsgMC41O1xcbiAgICBmbG9hdCB5ID0gYXhpc1koeCwgZGltcywgZGltMUEsIGRpbTJBLCBkaW0xQiwgZGltMkIsIGRpbTFDLCBkaW0yQywgZGltMUQsIGRpbTJEKTtcXG5cXG4gICAgdmVjMiB2aWV3Qm94WFkgPSB2aWV3Qm94UG9zaXRpb24gKyB2aWV3Qm94U2l6ZSAqIHZlYzIoeCwgeSk7XFxuXFxuICAgIHJldHVybiB2ZWM0KFxcbiAgICAgICAgeHlQcm9qZWN0aW9uICogKDIuMCAqIHZpZXdCb3hYWSAvIHJlc29sdXRpb24gLSAxLjApLFxcbiAgICAgICAgZGVwdGgsXFxuICAgICAgICAxLjBcXG4gICAgKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcblxcbiAgICBmbG9hdCBwcm9taW5lbmNlID0gYWJzKHBmWzNdKTtcXG5cXG4gICAgbWF0NCBwWzRdO1xcbiAgICBwWzBdID0gbWF0NChwMCwgcDEsIHAyLCBwMyk7XFxuICAgIHBbMV0gPSBtYXQ0KHA0LCBwNSwgcDYsIHA3KTtcXG4gICAgcFsyXSA9IG1hdDQocDgsIHA5LCBwYSwgcGIpO1xcbiAgICBwWzNdID0gbWF0NChwYywgcGQsIHBlLCBhYnMocGYpKTtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSBwb3NpdGlvbihcXG4gICAgICAgIDEuMCAtIHByb21pbmVuY2UsXFxuICAgICAgICByZXNvbHV0aW9uLCB2aWV3Qm94UG9zaXRpb24sIHZpZXdCb3hTaXplLFxcbiAgICAgICAgcCxcXG4gICAgICAgIHNpZ24ocGZbM10pLFxcbiAgICAgICAgZGltMUEsIGRpbTJBLCBkaW0xQiwgZGltMkIsIGRpbTFDLCBkaW0yQywgZGltMUQsIGRpbTJEXFxuICAgICk7XFxuXFxuICAgIGZsb2F0IGNsYW1wZWRDb2xvckluZGV4ID0gY2xhbXAoKHByb21pbmVuY2UgLSBjb2xvckNsYW1wWzBdKSAvIChjb2xvckNsYW1wWzFdIC0gY29sb3JDbGFtcFswXSksIDAuMCwgMS4wKTtcXG4gICAgZnJhZ0NvbG9yID0gdGV4dHVyZTJEKHBhbGV0dGUsIHZlYzIoKGNsYW1wZWRDb2xvckluZGV4ICogMjU1LjAgKyAwLjUpIC8gMjU2LjAsIDAuNSkpO1xcbn1cXG5cIl0pO1xudmFyIHBpY2tWZXJ0ZXhTaGFkZXJTb3VyY2UgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHAwLCBwMSwgcDIsIHAzLFxcbiAgICAgICAgICAgICAgIHA0LCBwNSwgcDYsIHA3LFxcbiAgICAgICAgICAgICAgIHA4LCBwOSwgcGEsIHBiLFxcbiAgICAgICAgICAgICAgIHBjLCBwZCwgcGU7XFxuXFxuYXR0cmlidXRlIHZlYzQgcGY7XFxuXFxudW5pZm9ybSBtYXQ0IGRpbTFBLCBkaW0yQSwgZGltMUIsIGRpbTJCLCBkaW0xQywgZGltMkMsIGRpbTFELCBkaW0yRCxcXG4gICAgICAgICAgICAgbG9BLCBoaUEsIGxvQiwgaGlCLCBsb0MsIGhpQywgbG9ELCBoaUQ7XFxuXFxudW5pZm9ybSB2ZWMyIHJlc29sdXRpb24sXFxuICAgICAgICAgICAgIHZpZXdCb3hQb3NpdGlvbixcXG4gICAgICAgICAgICAgdmlld0JveFNpemU7XFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgbWFzaztcXG51bmlmb3JtIGZsb2F0IG1hc2tIZWlnaHQ7XFxuXFxudW5pZm9ybSB2ZWMyIGNvbG9yQ2xhbXA7XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG52ZWM0IHVuaXRfMSA9IHZlYzQoMSwgMSwgMSwgMSk7XFxuXFxuZmxvYXQgdmFsKG1hdDQgcCwgbWF0NCB2KSB7XFxuICAgIHJldHVybiBkb3QobWF0cml4Q29tcE11bHQocCwgdikgKiB1bml0XzEsIHVuaXRfMSk7XFxufVxcblxcbmZsb2F0IGF4aXNZKFxcbiAgICAgICAgZmxvYXQgeCxcXG4gICAgICAgIG1hdDQgZFs0XSxcXG4gICAgICAgIG1hdDQgZGltMUEsIG1hdDQgZGltMkEsIG1hdDQgZGltMUIsIG1hdDQgZGltMkIsIG1hdDQgZGltMUMsIG1hdDQgZGltMkMsIG1hdDQgZGltMUQsIG1hdDQgZGltMkRcXG4gICAgKSB7XFxuXFxuICAgIGZsb2F0IHkxID0gdmFsKGRbMF0sIGRpbTFBKSArIHZhbChkWzFdLCBkaW0xQikgKyB2YWwoZFsyXSwgZGltMUMpICsgdmFsKGRbM10sIGRpbTFEKTtcXG4gICAgZmxvYXQgeTIgPSB2YWwoZFswXSwgZGltMkEpICsgdmFsKGRbMV0sIGRpbTJCKSArIHZhbChkWzJdLCBkaW0yQykgKyB2YWwoZFszXSwgZGltMkQpO1xcbiAgICByZXR1cm4geTEgKiAoMS4wIC0geCkgKyB5MiAqIHg7XFxufVxcblxcbmNvbnN0IGludCBiaXRzUGVyQnl0ZSA9IDg7XFxuXFxuaW50IG1vZDIoaW50IGEpIHtcXG4gICAgcmV0dXJuIGEgLSAyICogKGEgLyAyKTtcXG59XFxuXFxuaW50IG1vZDgoaW50IGEpIHtcXG4gICAgcmV0dXJuIGEgLSA4ICogKGEgLyA4KTtcXG59XFxuXFxudmVjNCB6ZXJvID0gdmVjNCgwLCAwLCAwLCAwKTtcXG52ZWM0IHVuaXRfMCA9IHZlYzQoMSwgMSwgMSwgMSk7XFxudmVjMiB4eVByb2plY3Rpb24gPSB2ZWMyKDEsIDEpO1xcblxcbm1hdDQgbWNsYW1wKG1hdDQgbSwgbWF0NCBsbywgbWF0NCBoaSkge1xcbiAgICByZXR1cm4gbWF0NChjbGFtcChtWzBdLCBsb1swXSwgaGlbMF0pLFxcbiAgICAgICAgICAgICAgICBjbGFtcChtWzFdLCBsb1sxXSwgaGlbMV0pLFxcbiAgICAgICAgICAgICAgICBjbGFtcChtWzJdLCBsb1syXSwgaGlbMl0pLFxcbiAgICAgICAgICAgICAgICBjbGFtcChtWzNdLCBsb1szXSwgaGlbM10pKTtcXG59XFxuXFxuYm9vbCBtc2hvdyhtYXQ0IHAsIG1hdDQgbG8sIG1hdDQgaGkpIHtcXG4gICAgcmV0dXJuIG1jbGFtcChwLCBsbywgaGkpID09IHA7XFxufVxcblxcbmJvb2wgd2l0aGluQm91bmRpbmdCb3goXFxuICAgICAgICBtYXQ0IGRbNF0sXFxuICAgICAgICBtYXQ0IGxvQSwgbWF0NCBoaUEsIG1hdDQgbG9CLCBtYXQ0IGhpQiwgbWF0NCBsb0MsIG1hdDQgaGlDLCBtYXQ0IGxvRCwgbWF0NCBoaURcXG4gICAgKSB7XFxuXFxuICAgIHJldHVybiBtc2hvdyhkWzBdLCBsb0EsIGhpQSkgJiZcXG4gICAgICAgICAgIG1zaG93KGRbMV0sIGxvQiwgaGlCKSAmJlxcbiAgICAgICAgICAgbXNob3coZFsyXSwgbG9DLCBoaUMpICYmXFxuICAgICAgICAgICBtc2hvdyhkWzNdLCBsb0QsIGhpRCk7XFxufVxcblxcbmJvb2wgd2l0aGluUmFzdGVyTWFzayhtYXQ0IGRbNF0sIHNhbXBsZXIyRCBtYXNrLCBmbG9hdCBoZWlnaHQpIHtcXG4gICAgYm9vbCByZXN1bHQgPSB0cnVlO1xcbiAgICBpbnQgYml0SW5CeXRlU3RlcHBlcjtcXG4gICAgZmxvYXQgdmFsWSwgdmFsdWVZLCBzY2FsZVg7XFxuICAgIGludCBoaXQsIGJpdG1hc2ssIHZhbFg7XFxuICAgIGZvcihpbnQgaSA9IDA7IGkgPCA0OyBpKyspIHtcXG4gICAgICAgIGZvcihpbnQgaiA9IDA7IGogPCA0OyBqKyspIHtcXG4gICAgICAgICAgICBmb3IoaW50IGsgPSAwOyBrIDwgNDsgaysrKSB7XFxuICAgICAgICAgICAgICAgIGJpdEluQnl0ZVN0ZXBwZXIgPSBtb2Q4KGogKiA0ICsgayk7XFxuICAgICAgICAgICAgICAgIHZhbFggPSBpICogMiArIGogLyAyO1xcbiAgICAgICAgICAgICAgICB2YWxZID0gZFtpXVtqXVtrXTtcXG4gICAgICAgICAgICAgICAgdmFsdWVZID0gdmFsWSAqIChoZWlnaHQgLSAxLjApICsgMC41O1xcbiAgICAgICAgICAgICAgICBzY2FsZVggPSAoZmxvYXQodmFsWCkgKyAwLjUpIC8gOC4wO1xcbiAgICAgICAgICAgICAgICBoaXQgPSBpbnQodGV4dHVyZTJEKG1hc2ssIHZlYzIoc2NhbGVYLCAodmFsdWVZICsgMC41KSAvIGhlaWdodCkpWzNdICogMjU1LjApIC8gaW50KHBvdygyLjAsIGZsb2F0KGJpdEluQnl0ZVN0ZXBwZXIpKSk7XFxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdCAmJiBtb2QyKGhpdCkgPT0gMTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9XFxuICAgIH1cXG4gICAgcmV0dXJuIHJlc3VsdDtcXG59XFxuXFxudmVjNCBwb3NpdGlvbihcXG4gICAgICAgIGZsb2F0IGRlcHRoLFxcbiAgICAgICAgdmVjMiByZXNvbHV0aW9uLCB2ZWMyIHZpZXdCb3hQb3NpdGlvbiwgdmVjMiB2aWV3Qm94U2l6ZSxcXG4gICAgICAgIG1hdDQgZGltc1s0XSxcXG4gICAgICAgIGZsb2F0IHNpZ251bSxcXG4gICAgICAgIG1hdDQgZGltMUEsIG1hdDQgZGltMkEsIG1hdDQgZGltMUIsIG1hdDQgZGltMkIsIG1hdDQgZGltMUMsIG1hdDQgZGltMkMsIG1hdDQgZGltMUQsIG1hdDQgZGltMkQsXFxuICAgICAgICBtYXQ0IGxvQSwgbWF0NCBoaUEsIG1hdDQgbG9CLCBtYXQ0IGhpQiwgbWF0NCBsb0MsIG1hdDQgaGlDLCBtYXQ0IGxvRCwgbWF0NCBoaUQsXFxuICAgICAgICBzYW1wbGVyMkQgbWFzaywgZmxvYXQgbWFza0hlaWdodFxcbiAgICApIHtcXG5cXG4gICAgZmxvYXQgeCA9IDAuNSAqIHNpZ251bSArIDAuNTtcXG4gICAgZmxvYXQgeSA9IGF4aXNZKHgsIGRpbXMsIGRpbTFBLCBkaW0yQSwgZGltMUIsIGRpbTJCLCBkaW0xQywgZGltMkMsIGRpbTFELCBkaW0yRCk7XFxuXFxuICAgIGZsb2F0IHNob3cgPSBmbG9hdChcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2l0aGluQm91bmRpbmdCb3goZGltcywgbG9BLCBoaUEsIGxvQiwgaGlCLCBsb0MsIGhpQywgbG9ELCBoaUQpXFxuICAgICAgICAgICAgICAgICAgICAgICAgICYmIHdpdGhpblJhc3Rlck1hc2soZGltcywgbWFzaywgbWFza0hlaWdodClcXG4gICAgICAgICAgICAgICAgICAgICAgKTtcXG5cXG4gICAgdmVjMiB2aWV3Qm94WFkgPSB2aWV3Qm94UG9zaXRpb24gKyB2aWV3Qm94U2l6ZSAqIHZlYzIoeCwgeSk7XFxuICAgIGZsb2F0IGRlcHRoT3JIaWRlID0gZGVwdGggKyAyLjAgKiAoMS4wIC0gc2hvdyk7XFxuXFxuICAgIHJldHVybiB2ZWM0KFxcbiAgICAgICAgeHlQcm9qZWN0aW9uICogKDIuMCAqIHZpZXdCb3hYWSAvIHJlc29sdXRpb24gLSAxLjApLFxcbiAgICAgICAgZGVwdGhPckhpZGUsXFxuICAgICAgICAxLjBcXG4gICAgKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcblxcbiAgICBmbG9hdCBwcm9taW5lbmNlID0gYWJzKHBmWzNdKTtcXG5cXG4gICAgbWF0NCBwWzRdO1xcbiAgICBwWzBdID0gbWF0NChwMCwgcDEsIHAyLCBwMyk7XFxuICAgIHBbMV0gPSBtYXQ0KHA0LCBwNSwgcDYsIHA3KTtcXG4gICAgcFsyXSA9IG1hdDQocDgsIHA5LCBwYSwgcGIpO1xcbiAgICBwWzNdID0gbWF0NChwYywgcGQsIHBlLCBhYnMocGYpKTtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSBwb3NpdGlvbihcXG4gICAgICAgIDEuMCAtIHByb21pbmVuY2UsXFxuICAgICAgICByZXNvbHV0aW9uLCB2aWV3Qm94UG9zaXRpb24sIHZpZXdCb3hTaXplLFxcbiAgICAgICAgcCxcXG4gICAgICAgIHNpZ24ocGZbM10pLFxcbiAgICAgICAgZGltMUEsIGRpbTJBLCBkaW0xQiwgZGltMkIsIGRpbTFDLCBkaW0yQywgZGltMUQsIGRpbTJELFxcbiAgICAgICAgbG9BLCBoaUEsIGxvQiwgaGlCLCBsb0MsIGhpQywgbG9ELCBoaUQsXFxuICAgICAgICBtYXNrLCBtYXNrSGVpZ2h0XFxuICAgICk7XFxuXFxuICAgIGZyYWdDb2xvciA9IHZlYzQocGYucmdiLCAxLjApO1xcbn1cXG5cIl0pO1xudmFyIGZyYWdtZW50U2hhZGVyU291cmNlID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgICBnbF9GcmFnQ29sb3IgPSBmcmFnQ29sb3I7XFxufVxcblwiXSk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLy8gZG9uJ3QgY2hhbmdlOyBvdGhlcndpc2UgbmVhci9mYXIgcGxhbmUgbGluZXMgYXJlIGxvc3RcbnZhciBkZXB0aExpbWl0RXBzaWxvbiA9IDFlLTY7XG4vLyBqdXN0IGVub3VnaCBidWZmZXIgZm9yIGFuIGV4dHJhIGJpdCBhdCBzaW5nbGUtcHJlY2lzaW9uIGZsb2F0aW5nIHBvaW50XG4vLyB3aGljaCBvbiBbMCwgMV0gaXMgNmUtOCAoMS8yXjI0KVxudmFyIGZpbHRlckVwc2lsb24gPSAxZS03O1xuXG4vLyBwcmVjaXNpb24gb2YgbXVsdGlzZWxlY3QgaXMgdGhlIGZ1bGwgcmFuZ2UgZGl2aWRlZCBpbnRvIHRoaXMgbWFueSBwYXJ0c1xudmFyIG1hc2tIZWlnaHQgPSAyMDQ4O1xuXG52YXIgZ3B1RGltZW5zaW9uQ291bnQgPSA2NDtcbnZhciBzZWN0aW9uVmVydGV4Q291bnQgPSAyO1xudmFyIHZlYzROdW1iZXJDb3VudCA9IDQ7XG52YXIgYml0c1BlckJ5dGUgPSA4O1xudmFyIGNoYW5uZWxDb3VudCA9IGdwdURpbWVuc2lvbkNvdW50IC8gYml0c1BlckJ5dGU7IC8vID09IDggYnl0ZXMgbmVlZGVkIHRvIGhhdmUgNjQgYml0c1xuXG52YXIgY29udGV4dENvbG9yID0gWzExOSwgMTE5LCAxMTldOyAvLyBtaWRkbGUgZ3JheSB0byBub3QgZHJhd24gdGhlIGZvY3VzOyBsb29rcyBnb29kIG9uIGEgYmxhY2sgb3Igd2hpdGUgYmFja2dyb3VuZFxuXG52YXIgZHVtbXlQaXhlbCA9IG5ldyBVaW50OEFycmF5KDQpO1xudmFyIHBpY2tQaXhlbCA9IG5ldyBVaW50OEFycmF5KDQpO1xuXG52YXIgcGFsZXR0ZVRleHR1cmVDb25maWcgPSB7XG4gICAgc2hhcGU6IFsyNTYsIDFdLFxuICAgIGZvcm1hdDogJ3JnYmEnLFxuICAgIHR5cGU6ICd1aW50OCcsXG4gICAgbWFnOiAnbmVhcmVzdCcsXG4gICAgbWluOiAnbmVhcmVzdCdcbn07XG5cbmZ1bmN0aW9uIGVuc3VyZURyYXcocmVnbCkge1xuICAgIHJlZ2wucmVhZCh7XG4gICAgICAgIHg6IDAsXG4gICAgICAgIHk6IDAsXG4gICAgICAgIHdpZHRoOiAxLFxuICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgIGRhdGE6IGR1bW15UGl4ZWxcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gY2xlYXIocmVnbCwgeCwgeSwgd2lkdGgsIGhlaWdodCkge1xuICAgIHZhciBnbCA9IHJlZ2wuX2dsO1xuICAgIGdsLmVuYWJsZShnbC5TQ0lTU09SX1RFU1QpO1xuICAgIGdsLnNjaXNzb3IoeCwgeSwgd2lkdGgsIGhlaWdodCk7XG4gICAgcmVnbC5jbGVhcih7Y29sb3I6IFswLCAwLCAwLCAwXSwgZGVwdGg6IDF9KTsgLy8gY2xlYXJpbmcgaXMgZG9uZSBpbiBzY2lzc29yZWQgcGFuZWwgb25seVxufVxuXG5mdW5jdGlvbiByZW5kZXJCbG9jayhyZWdsLCBnbEFlcywgcmVuZGVyU3RhdGUsIGJsb2NrTGluZUNvdW50LCBzYW1wbGVDb3VudCwgaXRlbSkge1xuXG4gICAgdmFyIHJhZktleSA9IGl0ZW0ua2V5O1xuXG4gICAgZnVuY3Rpb24gcmVuZGVyKGJsb2NrTnVtYmVyKSB7XG5cbiAgICAgICAgdmFyIGNvdW50O1xuXG4gICAgICAgIGNvdW50ID0gTWF0aC5taW4oYmxvY2tMaW5lQ291bnQsIHNhbXBsZUNvdW50IC0gYmxvY2tOdW1iZXIgKiBibG9ja0xpbmVDb3VudCk7XG5cbiAgICAgICAgaXRlbS5vZmZzZXQgPSBzZWN0aW9uVmVydGV4Q291bnQgKiBibG9ja051bWJlciAqIGJsb2NrTGluZUNvdW50O1xuICAgICAgICBpdGVtLmNvdW50ID0gc2VjdGlvblZlcnRleENvdW50ICogY291bnQ7XG4gICAgICAgIGlmKGJsb2NrTnVtYmVyID09PSAwKSB7XG4gICAgICAgICAgICAvLyBzdG9wIGRyYXdpbmcgcG9zc2libHkgc3RhbGUgZ2x5cGhzIGJlZm9yZSBjbGVhcmluZ1xuICAgICAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKHJlbmRlclN0YXRlLmN1cnJlbnRSYWZzW3JhZktleV0pO1xuICAgICAgICAgICAgZGVsZXRlIHJlbmRlclN0YXRlLmN1cnJlbnRSYWZzW3JhZktleV07XG4gICAgICAgICAgICBjbGVhcihyZWdsLCBpdGVtLnNjaXNzb3JYLCBpdGVtLnNjaXNzb3JZLCBpdGVtLnNjaXNzb3JXaWR0aCwgaXRlbS52aWV3Qm94U2l6ZVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihyZW5kZXJTdGF0ZS5jbGVhck9ubHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGdsQWVzKGl0ZW0pO1xuXG4gICAgICAgIGlmKGJsb2NrTnVtYmVyICogYmxvY2tMaW5lQ291bnQgKyBjb3VudCA8IHNhbXBsZUNvdW50KSB7XG4gICAgICAgICAgICByZW5kZXJTdGF0ZS5jdXJyZW50UmFmc1tyYWZLZXldID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZW5kZXIoYmxvY2tOdW1iZXIgKyAxKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVuZGVyU3RhdGUuZHJhd0NvbXBsZXRlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKCFyZW5kZXJTdGF0ZS5kcmF3Q29tcGxldGVkKSB7XG4gICAgICAgIGVuc3VyZURyYXcocmVnbCk7XG4gICAgICAgIHJlbmRlclN0YXRlLmRyYXdDb21wbGV0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIHN0YXJ0IHdpdGggcmVuZGVyaW5nIGl0ZW0gMDsgcmVjdXJzaW9uIGhhbmRsZXMgdGhlIHJlc3RcbiAgICByZW5kZXIoMCk7XG59XG5cbmZ1bmN0aW9uIGFkanVzdERlcHRoKGQpIHtcbiAgICAvLyBXZWJHTCBtYXRyaXggb3BlcmF0aW9ucyB1c2UgZmxvYXRzIHdpdGggbGltaXRlZCBwcmVjaXNpb24sIHBvdGVudGlhbGx5IGNhdXNpbmcgYSBudW1iZXIgbmVhciBhIGJvcmRlciBvZiBbMCwgMV1cbiAgICAvLyB0byBlbmQgdXAgc2xpZ2h0bHkgb3V0c2lkZSB0aGUgYm9yZGVyLiBXaXRoIGFuIGVwc2lsb24sIHdlIHJlZHVjZSB0aGUgY2hhbmNlIHRoYXQgYSBsaW5lIGdldHMgY2xpcHBlZCBieSB0aGVcbiAgICAvLyBuZWFyIG9yIHRoZSBmYXIgcGxhbmUuXG4gICAgcmV0dXJuIE1hdGgubWF4KGRlcHRoTGltaXRFcHNpbG9uLCBNYXRoLm1pbigxIC0gZGVwdGhMaW1pdEVwc2lsb24sIGQpKTtcbn1cblxuZnVuY3Rpb24gcGFsZXR0ZSh1bml0VG9Db2xvciwgY29udGV4dCwgb3BhY2l0eSkge1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICBmb3IodmFyIGogPSAwOyBqIDwgMjU2OyBqKyspIHtcbiAgICAgICAgdmFyIGMgPSB1bml0VG9Db2xvcihqIC8gMjU1KTtcbiAgICAgICAgcmVzdWx0LnB1c2goKGNvbnRleHQgPyBjb250ZXh0Q29sb3IgOiBjKS5jb25jYXQob3BhY2l0eSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8vIE1hcHMgdGhlIHNhbXBsZSBpbmRleCBbMC4uLnNhbXBsZUNvdW50IC0gMV0gdG8gYSByYW5nZSBvZiBbMCwgMV0gYXMgdGhlIHNoYWRlciBleHBlY3RzIGNvbG9ycyBpbiB0aGUgWzAsIDFdIHJhbmdlLlxuLy8gYnV0IGZpcnN0IGl0IHNoaWZ0cyB0aGUgc2FtcGxlIGluZGV4IGJ5IDAsIDggb3IgMTYgYml0cyBkZXBlbmRpbmcgb24gcmdiSW5kZXggWzAuLjJdXG4vLyB3aXRoIHRoZSBlbmQgcmVzdWx0IHRoYXQgZWFjaCBsaW5lIHdpbGwgYmUgb2YgYSB1bmlxdWUgY29sb3IsIG1ha2luZyBpdCBwb3NzaWJsZSBmb3IgdGhlIHBpY2sgaGFuZGxlclxuLy8gdG8gdW5pcXVlbHkgaWRlbnRpZnkgd2hpY2ggbGluZSBpcyBob3ZlcmVkIG92ZXIgKGJpamVjdGl2ZSBtYXBwaW5nKS5cbi8vIFRoZSBpbnZlcnNlLCBpLmUuIHJlYWRQaXhlbCBpcyBpbnZva2VkIGZyb20gJ3BhcmNvb3Jkcy5qcydcbmZ1bmN0aW9uIGNhbGNQaWNrQ29sb3IoaiwgcmdiSW5kZXgpIHtcbiAgICByZXR1cm4gKGogPj4+IDggKiByZ2JJbmRleCkgJSAyNTYgLyAyNTU7XG59XG5cbmZ1bmN0aW9uIG1ha2VQb2ludHMoc2FtcGxlQ291bnQsIGRpbWVuc2lvbnMsIGNvbG9yKSB7XG4gICAgdmFyIGRpbWVuc2lvbkNvdW50ID0gZGltZW5zaW9ucy5sZW5ndGg7XG5cbiAgICB2YXIgcG9pbnRzID0gW107XG4gICAgZm9yKHZhciBqID0gMDsgaiA8IHNhbXBsZUNvdW50OyBqKyspIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGdwdURpbWVuc2lvbkNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIHBvaW50cy5wdXNoKGkgPCBkaW1lbnNpb25Db3VudCA/XG4gICAgICAgICAgICAgICAgZGltZW5zaW9uc1tpXS5wYWRkZWRVbml0VmFsdWVzW2pdIDpcbiAgICAgICAgICAgICAgICBpID09PSAoZ3B1RGltZW5zaW9uQ291bnQgLSAxKSA/XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdERlcHRoKGNvbG9yW2pdKSA6XG4gICAgICAgICAgICAgICAgICAgIGkgPj0gZ3B1RGltZW5zaW9uQ291bnQgLSA0ID9cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGNQaWNrQ29sb3IoaiwgZ3B1RGltZW5zaW9uQ291bnQgLSAyIC0gaSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgMC41KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwb2ludHM7XG59XG5cbmZ1bmN0aW9uIG1ha2VWZWNBdHRyKHNhbXBsZUNvdW50LCBwb2ludHMsIHZlY0luZGV4KSB7XG4gICAgdmFyIGksIGosIGs7XG4gICAgdmFyIHBvaW50UGFpcnMgPSBbXTtcblxuICAgIGZvcihqID0gMDsgaiA8IHNhbXBsZUNvdW50OyBqKyspIHtcbiAgICAgICAgZm9yKGsgPSAwOyBrIDwgc2VjdGlvblZlcnRleENvdW50OyBrKyspIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHZlYzROdW1iZXJDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRQYWlycy5wdXNoKHBvaW50c1tqICogZ3B1RGltZW5zaW9uQ291bnQgKyB2ZWNJbmRleCAqIHZlYzROdW1iZXJDb3VudCArIGldKTtcbiAgICAgICAgICAgICAgICBpZih2ZWNJbmRleCAqIHZlYzROdW1iZXJDb3VudCArIGkgPT09IGdwdURpbWVuc2lvbkNvdW50IC0gMSAmJiBrICUgMiA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludFBhaXJzW3BvaW50UGFpcnMubGVuZ3RoIC0gMV0gKj0gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvaW50UGFpcnM7XG59XG5cbmZ1bmN0aW9uIHNldEF0dHJpYnV0ZXMoYXR0cmlidXRlcywgc2FtcGxlQ291bnQsIHBvaW50cykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICAgIGF0dHJpYnV0ZXNbJ3AnICsgaS50b1N0cmluZygxNildKG1ha2VWZWNBdHRyKHNhbXBsZUNvdW50LCBwb2ludHMsIGkpKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGVtcHR5QXR0cmlidXRlcyhyZWdsKSB7XG4gICAgdmFyIGF0dHJpYnV0ZXMgPSB7fTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICBhdHRyaWJ1dGVzWydwJyArIGkudG9TdHJpbmcoMTYpXSA9IHJlZ2wuYnVmZmVyKHt1c2FnZTogJ2R5bmFtaWMnLCB0eXBlOiAnZmxvYXQnLCBkYXRhOiBuZXcgVWludDhBcnJheSgwKX0pO1xuICAgIH1cbiAgICByZXR1cm4gYXR0cmlidXRlcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihjYW52YXNHTCwgZCkge1xuICAgIC8vIGNvbnRleHQgJiBwaWNrIGRlc2NyaWJlIHdoaWNoIGNhbnZhcyB3ZSdyZSB0YWxraW5nIGFib3V0IC0gd29uJ3QgY2hhbmdlIHdpdGggbmV3IGRhdGFcbiAgICB2YXIgY29udGV4dCA9IGQuY29udGV4dDtcbiAgICB2YXIgcGljayA9IGQucGljaztcblxuICAgIHZhciByZWdsID0gZC5yZWdsO1xuXG4gICAgdmFyIHJlbmRlclN0YXRlID0ge1xuICAgICAgICBjdXJyZW50UmFmczoge30sXG4gICAgICAgIGRyYXdDb21wbGV0ZWQ6IHRydWUsXG4gICAgICAgIGNsZWFyT25seTogZmFsc2VcbiAgICB9O1xuXG4gICAgLy8gc3RhdGUgdG8gYmUgc2V0IGJ5IHVwZGF0ZSBhbmQgdXNlZCBsYXRlclxuICAgIHZhciBtb2RlbDtcbiAgICB2YXIgdm07XG4gICAgdmFyIGluaXRpYWxEaW1zO1xuICAgIHZhciBzYW1wbGVDb3VudDtcbiAgICB2YXIgYXR0cmlidXRlcyA9IGVtcHR5QXR0cmlidXRlcyhyZWdsKTtcbiAgICB2YXIgbWFza1RleHR1cmU7XG4gICAgdmFyIHBhbGV0dGVUZXh0dXJlID0gcmVnbC50ZXh0dXJlKHBhbGV0dGVUZXh0dXJlQ29uZmlnKTtcblxuICAgIHVwZGF0ZShkKTtcblxuICAgIHZhciBnbEFlcyA9IHJlZ2woe1xuXG4gICAgICAgIHByb2ZpbGU6IGZhbHNlLFxuXG4gICAgICAgIGJsZW5kOiB7XG4gICAgICAgICAgICBlbmFibGU6IGNvbnRleHQsXG4gICAgICAgICAgICBmdW5jOiB7XG4gICAgICAgICAgICAgICAgc3JjUkdCOiAnc3JjIGFscGhhJyxcbiAgICAgICAgICAgICAgICBkc3RSR0I6ICdvbmUgbWludXMgc3JjIGFscGhhJyxcbiAgICAgICAgICAgICAgICBzcmNBbHBoYTogMSxcbiAgICAgICAgICAgICAgICBkc3RBbHBoYTogMSAvLyAnb25lIG1pbnVzIHNyYyBhbHBoYSdcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcXVhdGlvbjoge1xuICAgICAgICAgICAgICAgIHJnYjogJ2FkZCcsXG4gICAgICAgICAgICAgICAgYWxwaGE6ICdhZGQnXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IFswLCAwLCAwLCAwXVxuICAgICAgICB9LFxuXG4gICAgICAgIGRlcHRoOiB7XG4gICAgICAgICAgICBlbmFibGU6ICFjb250ZXh0LFxuICAgICAgICAgICAgbWFzazogdHJ1ZSxcbiAgICAgICAgICAgIGZ1bmM6ICdsZXNzJyxcbiAgICAgICAgICAgIHJhbmdlOiBbMCwgMV1cbiAgICAgICAgfSxcblxuICAgICAgICAvLyBmb3IgcG9seWdvbnNcbiAgICAgICAgY3VsbDoge1xuICAgICAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICAgICAgZmFjZTogJ2JhY2snXG4gICAgICAgIH0sXG5cbiAgICAgICAgc2Npc3Nvcjoge1xuICAgICAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICAgICAgYm94OiB7XG4gICAgICAgICAgICAgICAgeDogcmVnbC5wcm9wKCdzY2lzc29yWCcpLFxuICAgICAgICAgICAgICAgIHk6IHJlZ2wucHJvcCgnc2Npc3NvclknKSxcbiAgICAgICAgICAgICAgICB3aWR0aDogcmVnbC5wcm9wKCdzY2lzc29yV2lkdGgnKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHJlZ2wucHJvcCgnc2Npc3NvckhlaWdodCcpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgdmlld3BvcnQ6IHtcbiAgICAgICAgICAgIHg6IHJlZ2wucHJvcCgndmlld3BvcnRYJyksXG4gICAgICAgICAgICB5OiByZWdsLnByb3AoJ3ZpZXdwb3J0WScpLFxuICAgICAgICAgICAgd2lkdGg6IHJlZ2wucHJvcCgndmlld3BvcnRXaWR0aCcpLFxuICAgICAgICAgICAgaGVpZ2h0OiByZWdsLnByb3AoJ3ZpZXdwb3J0SGVpZ2h0JylcbiAgICAgICAgfSxcblxuICAgICAgICBkaXRoZXI6IGZhbHNlLFxuXG4gICAgICAgIHZlcnQ6IHBpY2sgPyBwaWNrVmVydGV4U2hhZGVyU291cmNlIDogY29udGV4dCA/IGNvbnRleHRTaGFkZXJTb3VyY2UgOiB2ZXJ0ZXhTaGFkZXJTb3VyY2UsXG5cbiAgICAgICAgZnJhZzogZnJhZ21lbnRTaGFkZXJTb3VyY2UsXG5cbiAgICAgICAgcHJpbWl0aXZlOiAnbGluZXMnLFxuICAgICAgICBsaW5lV2lkdGg6IDEsXG4gICAgICAgIGF0dHJpYnV0ZXM6IGF0dHJpYnV0ZXMsXG4gICAgICAgIHVuaWZvcm1zOiB7XG4gICAgICAgICAgICByZXNvbHV0aW9uOiByZWdsLnByb3AoJ3Jlc29sdXRpb24nKSxcbiAgICAgICAgICAgIHZpZXdCb3hQb3NpdGlvbjogcmVnbC5wcm9wKCd2aWV3Qm94UG9zaXRpb24nKSxcbiAgICAgICAgICAgIHZpZXdCb3hTaXplOiByZWdsLnByb3AoJ3ZpZXdCb3hTaXplJyksXG4gICAgICAgICAgICBkaW0xQTogcmVnbC5wcm9wKCdkaW0xQScpLFxuICAgICAgICAgICAgZGltMkE6IHJlZ2wucHJvcCgnZGltMkEnKSxcbiAgICAgICAgICAgIGRpbTFCOiByZWdsLnByb3AoJ2RpbTFCJyksXG4gICAgICAgICAgICBkaW0yQjogcmVnbC5wcm9wKCdkaW0yQicpLFxuICAgICAgICAgICAgZGltMUM6IHJlZ2wucHJvcCgnZGltMUMnKSxcbiAgICAgICAgICAgIGRpbTJDOiByZWdsLnByb3AoJ2RpbTJDJyksXG4gICAgICAgICAgICBkaW0xRDogcmVnbC5wcm9wKCdkaW0xRCcpLFxuICAgICAgICAgICAgZGltMkQ6IHJlZ2wucHJvcCgnZGltMkQnKSxcbiAgICAgICAgICAgIGxvQTogcmVnbC5wcm9wKCdsb0EnKSxcbiAgICAgICAgICAgIGhpQTogcmVnbC5wcm9wKCdoaUEnKSxcbiAgICAgICAgICAgIGxvQjogcmVnbC5wcm9wKCdsb0InKSxcbiAgICAgICAgICAgIGhpQjogcmVnbC5wcm9wKCdoaUInKSxcbiAgICAgICAgICAgIGxvQzogcmVnbC5wcm9wKCdsb0MnKSxcbiAgICAgICAgICAgIGhpQzogcmVnbC5wcm9wKCdoaUMnKSxcbiAgICAgICAgICAgIGxvRDogcmVnbC5wcm9wKCdsb0QnKSxcbiAgICAgICAgICAgIGhpRDogcmVnbC5wcm9wKCdoaUQnKSxcbiAgICAgICAgICAgIHBhbGV0dGU6IHBhbGV0dGVUZXh0dXJlLFxuICAgICAgICAgICAgbWFzazogcmVnbC5wcm9wKCdtYXNrVGV4dHVyZScpLFxuICAgICAgICAgICAgbWFza0hlaWdodDogcmVnbC5wcm9wKCdtYXNrSGVpZ2h0JyksXG4gICAgICAgICAgICBjb2xvckNsYW1wOiByZWdsLnByb3AoJ2NvbG9yQ2xhbXAnKVxuICAgICAgICB9LFxuICAgICAgICBvZmZzZXQ6IHJlZ2wucHJvcCgnb2Zmc2V0JyksXG4gICAgICAgIGNvdW50OiByZWdsLnByb3AoJ2NvdW50JylcbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZShkTmV3KSB7XG4gICAgICAgIG1vZGVsID0gZE5ldy5tb2RlbDtcbiAgICAgICAgdm0gPSBkTmV3LnZpZXdNb2RlbDtcbiAgICAgICAgaW5pdGlhbERpbXMgPSB2bS5kaW1lbnNpb25zLnNsaWNlKCk7XG4gICAgICAgIHNhbXBsZUNvdW50ID0gaW5pdGlhbERpbXNbMF0gPyBpbml0aWFsRGltc1swXS52YWx1ZXMubGVuZ3RoIDogMDtcblxuICAgICAgICB2YXIgbGluZXMgPSBtb2RlbC5saW5lcztcbiAgICAgICAgdmFyIGNvbG9yID0gcGljayA/IGxpbmVzLmNvbG9yLm1hcChmdW5jdGlvbihfLCBpKSB7cmV0dXJuIGkgLyBsaW5lcy5jb2xvci5sZW5ndGg7fSkgOiBsaW5lcy5jb2xvcjtcbiAgICAgICAgdmFyIGNvbnRleHRPcGFjaXR5ID0gTWF0aC5tYXgoMSAvIDI1NSwgTWF0aC5wb3coMSAvIGNvbG9yLmxlbmd0aCwgMSAvIDMpKTtcblxuICAgICAgICB2YXIgcG9pbnRzID0gbWFrZVBvaW50cyhzYW1wbGVDb3VudCwgaW5pdGlhbERpbXMsIGNvbG9yKTtcbiAgICAgICAgc2V0QXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBzYW1wbGVDb3VudCwgcG9pbnRzKTtcblxuICAgICAgICBwYWxldHRlVGV4dHVyZSA9IHJlZ2wudGV4dHVyZShMaWIuZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICBkYXRhOiBwYWxldHRlKG1vZGVsLnVuaXRUb0NvbG9yLCBjb250ZXh0LCBNYXRoLnJvdW5kKChjb250ZXh0ID8gY29udGV4dE9wYWNpdHkgOiAxKSAqIDI1NSkpXG4gICAgICAgIH0sIHBhbGV0dGVUZXh0dXJlQ29uZmlnKSk7XG4gICAgfVxuXG4gICAgdmFyIGNvbG9yQ2xhbXAgPSBbMCwgMV07XG5cbiAgICBmdW5jdGlvbiBzZXRDb2xvckRvbWFpbih1bml0RG9tYWluKSB7XG4gICAgICAgIGNvbG9yQ2xhbXBbMF0gPSB1bml0RG9tYWluWzBdO1xuICAgICAgICBjb2xvckNsYW1wWzFdID0gdW5pdERvbWFpblsxXTtcbiAgICB9XG5cbiAgICB2YXIgcHJldmlvdXNBeGlzT3JkZXIgPSBbXTtcblxuICAgIGZ1bmN0aW9uIG1ha2VJdGVtKGksIGlpLCB4LCB5LCBwYW5lbFNpemVYLCBjYW52YXNQYW5lbFNpemVZLCBjcm9zc2ZpbHRlckRpbWVuc2lvbkluZGV4LCBJLCBsZWZ0bW9zdCwgcmlnaHRtb3N0LCBjb25zdHJhaW50cykge1xuICAgICAgICB2YXIgbG9IaSwgYWJjZCwgZCwgaW5kZXg7XG4gICAgICAgIHZhciBsZWZ0UmlnaHQgPSBbaSwgaWldO1xuXG4gICAgICAgIHZhciBkaW1zID0gWzAsIDFdLm1hcChmdW5jdGlvbigpIHtyZXR1cm4gWzAsIDEsIDIsIDNdLm1hcChmdW5jdGlvbigpIHtyZXR1cm4gbmV3IEZsb2F0MzJBcnJheSgxNik7fSk7fSk7XG5cbiAgICAgICAgZm9yKGxvSGkgPSAwOyBsb0hpIDwgMjsgbG9IaSsrKSB7XG4gICAgICAgICAgICBpbmRleCA9IGxlZnRSaWdodFtsb0hpXTtcbiAgICAgICAgICAgIGZvcihhYmNkID0gMDsgYWJjZCA8IDQ7IGFiY2QrKykge1xuICAgICAgICAgICAgICAgIGZvcihkID0gMDsgZCA8IDE2OyBkKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZGltc1tsb0hpXVthYmNkXVtkXSA9IGQgKyAxNiAqIGFiY2QgPT09IGluZGV4ID8gMSA6IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG92ZXJkcmFnID0gbW9kZWwubGluZXMuY2FudmFzT3ZlcmRyYWc7XG4gICAgICAgIHZhciBkb21haW4gPSBtb2RlbC5kb21haW47XG4gICAgICAgIHZhciBjYW52YXNXaWR0aCA9IG1vZGVsLmNhbnZhc1dpZHRoO1xuICAgICAgICB2YXIgY2FudmFzSGVpZ2h0ID0gbW9kZWwuY2FudmFzSGVpZ2h0O1xuXG4gICAgICAgIHZhciBpdGVtTW9kZWwgPSBMaWIuZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICBrZXk6IGNyb3NzZmlsdGVyRGltZW5zaW9uSW5kZXgsXG4gICAgICAgICAgICByZXNvbHV0aW9uOiBbY2FudmFzV2lkdGgsIGNhbnZhc0hlaWdodF0sXG4gICAgICAgICAgICB2aWV3Qm94UG9zaXRpb246IFt4ICsgb3ZlcmRyYWcsIHldLFxuICAgICAgICAgICAgdmlld0JveFNpemU6IFtwYW5lbFNpemVYLCBjYW52YXNQYW5lbFNpemVZXSxcbiAgICAgICAgICAgIGk6IGksXG4gICAgICAgICAgICBpaTogaWksXG5cbiAgICAgICAgICAgIGRpbTFBOiBkaW1zWzBdWzBdLFxuICAgICAgICAgICAgZGltMUI6IGRpbXNbMF1bMV0sXG4gICAgICAgICAgICBkaW0xQzogZGltc1swXVsyXSxcbiAgICAgICAgICAgIGRpbTFEOiBkaW1zWzBdWzNdLFxuICAgICAgICAgICAgZGltMkE6IGRpbXNbMV1bMF0sXG4gICAgICAgICAgICBkaW0yQjogZGltc1sxXVsxXSxcbiAgICAgICAgICAgIGRpbTJDOiBkaW1zWzFdWzJdLFxuICAgICAgICAgICAgZGltMkQ6IGRpbXNbMV1bM10sXG5cbiAgICAgICAgICAgIGNvbG9yQ2xhbXA6IGNvbG9yQ2xhbXAsXG5cbiAgICAgICAgICAgIHNjaXNzb3JYOiAoSSA9PT0gbGVmdG1vc3QgPyAwIDogeCArIG92ZXJkcmFnKSArIChtb2RlbC5wYWQubCAtIG92ZXJkcmFnKSArIG1vZGVsLmxheW91dFdpZHRoICogZG9tYWluLnhbMF0sXG4gICAgICAgICAgICBzY2lzc29yV2lkdGg6IChJID09PSByaWdodG1vc3QgPyBjYW52YXNXaWR0aCAtIHggKyBvdmVyZHJhZyA6IHBhbmVsU2l6ZVggKyAwLjUpICsgKEkgPT09IGxlZnRtb3N0ID8geCArIG92ZXJkcmFnIDogMCksXG4gICAgICAgICAgICBzY2lzc29yWTogeSArIG1vZGVsLnBhZC5iICsgbW9kZWwubGF5b3V0SGVpZ2h0ICogZG9tYWluLnlbMF0sXG4gICAgICAgICAgICBzY2lzc29ySGVpZ2h0OiBjYW52YXNQYW5lbFNpemVZLFxuXG4gICAgICAgICAgICB2aWV3cG9ydFg6IG1vZGVsLnBhZC5sIC0gb3ZlcmRyYWcgKyBtb2RlbC5sYXlvdXRXaWR0aCAqIGRvbWFpbi54WzBdLFxuICAgICAgICAgICAgdmlld3BvcnRZOiBtb2RlbC5wYWQuYiArIG1vZGVsLmxheW91dEhlaWdodCAqIGRvbWFpbi55WzBdLFxuICAgICAgICAgICAgdmlld3BvcnRXaWR0aDogY2FudmFzV2lkdGgsXG4gICAgICAgICAgICB2aWV3cG9ydEhlaWdodDogY2FudmFzSGVpZ2h0XG4gICAgICAgIH0sIGNvbnN0cmFpbnRzKTtcblxuICAgICAgICByZXR1cm4gaXRlbU1vZGVsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VDb25zdHJhaW50cygpIHtcbiAgICAgICAgdmFyIGxvSGksIGFiY2QsIGQ7XG5cbiAgICAgICAgdmFyIGxpbXMgPSBbMCwgMV0ubWFwKGZ1bmN0aW9uKCkge3JldHVybiBbMCwgMSwgMiwgM10ubWFwKGZ1bmN0aW9uKCkge3JldHVybiBuZXcgRmxvYXQzMkFycmF5KDE2KTt9KTt9KTtcblxuICAgICAgICBmb3IobG9IaSA9IDA7IGxvSGkgPCAyOyBsb0hpKyspIHtcbiAgICAgICAgICAgIGZvcihhYmNkID0gMDsgYWJjZCA8IDQ7IGFiY2QrKykge1xuICAgICAgICAgICAgICAgIGZvcihkID0gMDsgZCA8IDE2OyBkKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpbVAgPSBkICsgMTYgKiBhYmNkO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGltO1xuICAgICAgICAgICAgICAgICAgICBpZihkaW1QIDwgaW5pdGlhbERpbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW0gPSBpbml0aWFsRGltc1tkaW1QXS5icnVzaC5maWx0ZXIuZ2V0Qm91bmRzKClbbG9IaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBsaW0gPSBsb0hpO1xuICAgICAgICAgICAgICAgICAgICBsaW1zW2xvSGldW2FiY2RdW2RdID0gbGltICsgKDIgKiBsb0hpIC0gMSkgKiBmaWx0ZXJFcHNpbG9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGV4cGFuZGVkUGl4ZWxSYW5nZShkaW0sIGJvdW5kcykge1xuICAgICAgICAgICAgdmFyIG1hc2tITWludXMgPSBtYXNrSGVpZ2h0IC0gMTtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihib3VuZHNbMF0gKiBtYXNrSE1pbnVzKSksXG4gICAgICAgICAgICAgICAgTWF0aC5taW4obWFza0hNaW51cywgTWF0aC5jZWlsKGJvdW5kc1sxXSAqIG1hc2tITWludXMpKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtYXNrID0gQXJyYXkuYXBwbHkobnVsbCwgbmV3IEFycmF5KG1hc2tIZWlnaHQgKiBjaGFubmVsQ291bnQpKS5tYXAoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gMjU1O1xuICAgICAgICB9KTtcbiAgICAgICAgZm9yKHZhciBkaW1JbmRleCA9IDA7IGRpbUluZGV4IDwgaW5pdGlhbERpbXMubGVuZ3RoOyBkaW1JbmRleCsrKSB7XG4gICAgICAgICAgICB2YXIgYml0SW5kZXggPSBkaW1JbmRleCAlIGJpdHNQZXJCeXRlO1xuICAgICAgICAgICAgdmFyIGJ5dGVJbmRleCA9IChkaW1JbmRleCAtIGJpdEluZGV4KSAvIGJpdHNQZXJCeXRlO1xuICAgICAgICAgICAgdmFyIGJpdE1hc2sgPSBNYXRoLnBvdygyLCBiaXRJbmRleCk7XG4gICAgICAgICAgICB2YXIgZGltID0gaW5pdGlhbERpbXNbZGltSW5kZXhdO1xuICAgICAgICAgICAgdmFyIHJhbmdlcyA9IGRpbS5icnVzaC5maWx0ZXIuZ2V0KCk7XG4gICAgICAgICAgICBpZihyYW5nZXMubGVuZ3RoIDwgMikgY29udGludWU7IC8vIGJhaWwgaWYgdGhlIGJvdW5kaW5nIGJveCBiYXNlZCBmaWx0ZXIgaXMgc3VmZmljaWVudFxuXG4gICAgICAgICAgICB2YXIgcHJldkVuZCA9IGV4cGFuZGVkUGl4ZWxSYW5nZShkaW0sIHJhbmdlc1swXSlbMV07XG4gICAgICAgICAgICBmb3IodmFyIHJpID0gMTsgcmkgPCByYW5nZXMubGVuZ3RoOyByaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHRSYW5nZSA9IGV4cGFuZGVkUGl4ZWxSYW5nZShkaW0sIHJhbmdlc1tyaV0pO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgcGkgPSBwcmV2RW5kICsgMTsgcGkgPCBuZXh0UmFuZ2VbMF07IHBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza1twaSAqIGNoYW5uZWxDb3VudCArIGJ5dGVJbmRleF0gJj0gfmJpdE1hc2s7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXZFbmQgPSBNYXRoLm1heChwcmV2RW5kLCBuZXh0UmFuZ2VbMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRleHR1cmVEYXRhID0ge1xuICAgICAgICAgICAgLy8gOCB1bml0cyB4IDggYml0cyA9IDY0IGJpdHMsIGp1c3Qgc3VmZmljaWVudCBmb3IgdGhlIGFsbW9zdCA2NCBkaW1lbnNpb25zIHdlIHN1cHBvcnRcbiAgICAgICAgICAgIHNoYXBlOiBbY2hhbm5lbENvdW50LCBtYXNrSGVpZ2h0XSxcbiAgICAgICAgICAgIGZvcm1hdDogJ2FscGhhJyxcbiAgICAgICAgICAgIHR5cGU6ICd1aW50OCcsXG4gICAgICAgICAgICBtYWc6ICduZWFyZXN0JyxcbiAgICAgICAgICAgIG1pbjogJ25lYXJlc3QnLFxuICAgICAgICAgICAgZGF0YTogbWFza1xuICAgICAgICB9O1xuICAgICAgICBpZihtYXNrVGV4dHVyZSkgbWFza1RleHR1cmUodGV4dHVyZURhdGEpO1xuICAgICAgICBlbHNlIG1hc2tUZXh0dXJlID0gcmVnbC50ZXh0dXJlKHRleHR1cmVEYXRhKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWFza1RleHR1cmU6IG1hc2tUZXh0dXJlLFxuICAgICAgICAgICAgbWFza0hlaWdodDogbWFza0hlaWdodCxcbiAgICAgICAgICAgIGxvQTogbGltc1swXVswXSxcbiAgICAgICAgICAgIGxvQjogbGltc1swXVsxXSxcbiAgICAgICAgICAgIGxvQzogbGltc1swXVsyXSxcbiAgICAgICAgICAgIGxvRDogbGltc1swXVszXSxcbiAgICAgICAgICAgIGhpQTogbGltc1sxXVswXSxcbiAgICAgICAgICAgIGhpQjogbGltc1sxXVsxXSxcbiAgICAgICAgICAgIGhpQzogbGltc1sxXVsyXSxcbiAgICAgICAgICAgIGhpRDogbGltc1sxXVszXVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbmRlckdMUGFyY29vcmRzKHBhbmVscywgc2V0Q2hhbmdlZCwgY2xlYXJPbmx5KSB7XG4gICAgICAgIHZhciBwYW5lbENvdW50ID0gcGFuZWxzLmxlbmd0aDtcbiAgICAgICAgdmFyIEk7XG5cbiAgICAgICAgdmFyIGxlZnRtb3N0LCByaWdodG1vc3QsIGxvd2VzdFggPSBJbmZpbml0eSwgaGlnaGVzdFggPSAtSW5maW5pdHk7XG5cbiAgICAgICAgZm9yKEkgPSAwOyBJIDwgcGFuZWxDb3VudDsgSSsrKSB7XG4gICAgICAgICAgICBpZihwYW5lbHNbSV0uZGltMi5jYW52YXNYID4gaGlnaGVzdFgpIHtcbiAgICAgICAgICAgICAgICBoaWdoZXN0WCA9IHBhbmVsc1tJXS5kaW0yLmNhbnZhc1g7XG4gICAgICAgICAgICAgICAgcmlnaHRtb3N0ID0gSTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHBhbmVsc1tJXS5kaW0xLmNhbnZhc1ggPCBsb3dlc3RYKSB7XG4gICAgICAgICAgICAgICAgbG93ZXN0WCA9IHBhbmVsc1tJXS5kaW0xLmNhbnZhc1g7XG4gICAgICAgICAgICAgICAgbGVmdG1vc3QgPSBJO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYocGFuZWxDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgLy8gY2xlYXIgY2FudmFzIGhlcmUsIGFzIHRoZSBwYW5lbCBpdGVyYXRpb24gYmVsb3cgd2lsbCBub3QgZW50ZXIgdGhlIGxvb3AgYm9keVxuICAgICAgICAgICAgY2xlYXIocmVnbCwgMCwgMCwgbW9kZWwuY2FudmFzV2lkdGgsIG1vZGVsLmNhbnZhc0hlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbnN0cmFpbnRzID0gY29udGV4dCA/IHt9IDogbWFrZUNvbnN0cmFpbnRzKCk7XG5cbiAgICAgICAgZm9yKEkgPSAwOyBJIDwgcGFuZWxDb3VudDsgSSsrKSB7XG4gICAgICAgICAgICB2YXIgcGFuZWwgPSBwYW5lbHNbSV07XG4gICAgICAgICAgICB2YXIgZGltMSA9IHBhbmVsLmRpbTE7XG4gICAgICAgICAgICB2YXIgaSA9IGRpbTEuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleDtcbiAgICAgICAgICAgIHZhciB4ID0gcGFuZWwuY2FudmFzWDtcbiAgICAgICAgICAgIHZhciB5ID0gcGFuZWwuY2FudmFzWTtcbiAgICAgICAgICAgIHZhciBkaW0yID0gcGFuZWwuZGltMjtcbiAgICAgICAgICAgIHZhciBpaSA9IGRpbTIuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleDtcbiAgICAgICAgICAgIHZhciBwYW5lbFNpemVYID0gcGFuZWwucGFuZWxTaXplWDtcbiAgICAgICAgICAgIHZhciBwYW5lbFNpemVZID0gcGFuZWwucGFuZWxTaXplWTtcbiAgICAgICAgICAgIHZhciB4VG8gPSB4ICsgcGFuZWxTaXplWDtcbiAgICAgICAgICAgIGlmKHNldENoYW5nZWQgfHwgIXByZXZpb3VzQXhpc09yZGVyW2ldIHx8IHByZXZpb3VzQXhpc09yZGVyW2ldWzBdICE9PSB4IHx8IHByZXZpb3VzQXhpc09yZGVyW2ldWzFdICE9PSB4VG8pIHtcbiAgICAgICAgICAgICAgICBwcmV2aW91c0F4aXNPcmRlcltpXSA9IFt4LCB4VG9dO1xuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gbWFrZUl0ZW0oaSwgaWksIHgsIHksIHBhbmVsU2l6ZVgsIHBhbmVsU2l6ZVksIGRpbTEuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleCwgSSwgbGVmdG1vc3QsIHJpZ2h0bW9zdCwgY29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgIHJlbmRlclN0YXRlLmNsZWFyT25seSA9IGNsZWFyT25seTtcbiAgICAgICAgICAgICAgICByZW5kZXJCbG9jayhyZWdsLCBnbEFlcywgcmVuZGVyU3RhdGUsIHNldENoYW5nZWQgPyBtb2RlbC5saW5lcy5ibG9ja0xpbmVDb3VudCA6IHNhbXBsZUNvdW50LCBzYW1wbGVDb3VudCwgaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWFkUGl4ZWwoY2FudmFzWCwgY2FudmFzWSkge1xuICAgICAgICByZWdsLnJlYWQoe1xuICAgICAgICAgICAgeDogY2FudmFzWCxcbiAgICAgICAgICAgIHk6IGNhbnZhc1ksXG4gICAgICAgICAgICB3aWR0aDogMSxcbiAgICAgICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgICAgIGRhdGE6IHBpY2tQaXhlbFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHBpY2tQaXhlbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWFkUGl4ZWxzKGNhbnZhc1gsIGNhbnZhc1ksIHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgdmFyIHBpeGVsQXJyYXkgPSBuZXcgVWludDhBcnJheSg0ICogd2lkdGggKiBoZWlnaHQpO1xuICAgICAgICByZWdsLnJlYWQoe1xuICAgICAgICAgICAgeDogY2FudmFzWCxcbiAgICAgICAgICAgIHk6IGNhbnZhc1ksXG4gICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIGRhdGE6IHBpeGVsQXJyYXlcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBwaXhlbEFycmF5O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgIGNhbnZhc0dMLnN0eWxlWydwb2ludGVyLWV2ZW50cyddID0gJ25vbmUnO1xuICAgICAgICBwYWxldHRlVGV4dHVyZS5kZXN0cm95KCk7XG4gICAgICAgIGlmKG1hc2tUZXh0dXJlKSBtYXNrVGV4dHVyZS5kZXN0cm95KCk7XG4gICAgICAgIGZvcih2YXIgayBpbiBhdHRyaWJ1dGVzKSBhdHRyaWJ1dGVzW2tdLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBzZXRDb2xvckRvbWFpbjogc2V0Q29sb3JEb21haW4sXG4gICAgICAgIHJlbmRlcjogcmVuZGVyR0xQYXJjb29yZHMsXG4gICAgICAgIHJlYWRQaXhlbDogcmVhZFBpeGVsLFxuICAgICAgICByZWFkUGl4ZWxzOiByZWFkUGl4ZWxzLFxuICAgICAgICBkZXN0cm95OiBkZXN0cm95LFxuICAgICAgICB1cGRhdGU6IHVwZGF0ZVxuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIG1lcmdlTGVuZ3RoOiBzZXQgdHJhY2UgbGVuZ3RoIGFzIHRoZSBtaW5pbXVtIG9mIGFsbCBkaW1lbnNpb24gZGF0YSBsZW5ndGhzXG4gKiAgICAgYW5kIHByb3BhZ2F0ZXMgdGhpcyBsZW5ndGggaW50byBlYWNoIGRpbWVuc2lvblxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZU91dDogdGhlIGZ1bGxEYXRhIHRyYWNlXG4gKiBAcGFyYW0ge0FycmF5KG9iamVjdCl9IGRpbWVuc2lvbnM6IGFycmF5IG9mIGRpbWVuc2lvbiBvYmplY3RzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUF0dHI6IHRoZSBhdHRyaWJ1dGUgb2YgZWFjaCBkaW1lbnNpb24gY29udGFpbmluZyB0aGUgZGF0YVxuICogQHBhcmFtIHtpbnRlZ2VyfSBsZW46IGFuIGFscmVhZHktZXhpc3RpbmcgbGVuZ3RoIGZyb20gb3RoZXIgYXR0cmlidXRlc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHRyYWNlT3V0LCBkaW1lbnNpb25zLCBkYXRhQXR0ciwgbGVuKSB7XG4gICAgaWYoIWxlbikgbGVuID0gSW5maW5pdHk7XG4gICAgdmFyIGksIGRpbWk7XG4gICAgZm9yKGkgPSAwOyBpIDwgZGltZW5zaW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaW1pID0gZGltZW5zaW9uc1tpXTtcbiAgICAgICAgaWYoZGltaS52aXNpYmxlKSBsZW4gPSBNYXRoLm1pbihsZW4sIGRpbWlbZGF0YUF0dHJdLmxlbmd0aCk7XG4gICAgfVxuICAgIGlmKGxlbiA9PT0gSW5maW5pdHkpIGxlbiA9IDA7XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuICAgIGZvcihpID0gMDsgaSA8IGRpbWVuc2lvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGltaSA9IGRpbWVuc2lvbnNbaV07XG4gICAgICAgIGlmKGRpbWkudmlzaWJsZSkgZGltaS5fbGVuZ3RoID0gbGVuO1xuICAgIH1cblxuICAgIHJldHVybiBsZW47XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbGluZUxheWVyTWFrZXIgPSByZXF1aXJlKCcuL2xpbmVzJyk7XG52YXIgYyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBndXAgPSByZXF1aXJlKCcuLi8uLi9saWIvZ3VwJyk7XG52YXIga2V5RnVuID0gZ3VwLmtleUZ1bjtcbnZhciByZXBlYXQgPSBndXAucmVwZWF0O1xudmFyIHVud3JhcCA9IGd1cC51bndyYXA7XG52YXIgYnJ1c2ggPSByZXF1aXJlKCcuL2F4aXNicnVzaCcpO1xuXG5mdW5jdGlvbiB2aXNpYmxlKGRpbWVuc2lvbikgeyByZXR1cm4gISgndmlzaWJsZScgaW4gZGltZW5zaW9uKSB8fCBkaW1lbnNpb24udmlzaWJsZTsgfVxuXG5mdW5jdGlvbiBkaW1lbnNpb25FeHRlbnQoZGltZW5zaW9uKSB7XG5cbiAgICB2YXIgbG8gPSBkaW1lbnNpb24ucmFuZ2UgPyBkaW1lbnNpb24ucmFuZ2VbMF0gOiBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgZGltZW5zaW9uLnZhbHVlcywgZGltZW5zaW9uLl9sZW5ndGgpO1xuICAgIHZhciBoaSA9IGRpbWVuc2lvbi5yYW5nZSA/IGRpbWVuc2lvbi5yYW5nZVsxXSA6IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCBkaW1lbnNpb24udmFsdWVzLCBkaW1lbnNpb24uX2xlbmd0aCk7XG5cbiAgICBpZihpc05hTihsbykgfHwgIWlzRmluaXRlKGxvKSkge1xuICAgICAgICBsbyA9IDA7XG4gICAgfVxuXG4gICAgaWYoaXNOYU4oaGkpIHx8ICFpc0Zpbml0ZShoaSkpIHtcbiAgICAgICAgaGkgPSAwO1xuICAgIH1cblxuICAgIC8vIGF2b2lkIGEgZGVnZW5lcmF0ZSAoemVyby13aWR0aCkgZG9tYWluXG4gICAgaWYobG8gPT09IGhpKSB7XG4gICAgICAgIGlmKGxvID09PSAwKSB7XG4gICAgICAgICAgICAvLyBubyB1c2UgdG8gbXVsdGlwbHlpbmcgemVybywgc28gYWRkL3N1YnRyYWN0IGluIHRoaXMgY2FzZVxuICAgICAgICAgICAgbG8gLT0gMTtcbiAgICAgICAgICAgIGhpICs9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0aGlzIGtlZXBzIHRoZSByYW5nZSBpbiB0aGUgb3JkZXIgb2YgbWFnbml0dWRlIG9mIHRoZSBkYXRhXG4gICAgICAgICAgICBsbyAqPSAwLjk7XG4gICAgICAgICAgICBoaSAqPSAxLjE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW2xvLCBoaV07XG59XG5cbmZ1bmN0aW9uIHRvVGV4dChmb3JtYXR0ZXIsIHRleHRzKSB7XG4gICAgaWYodGV4dHMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYsIGkpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0ID0gdGV4dHNbaV07XG4gICAgICAgICAgICBpZih0ZXh0ID09PSBudWxsIHx8IHRleHQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZvcm1hdHRlcih2KTtcbiAgICAgICAgICAgIHJldHVybiB0ZXh0O1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0dGVyO1xufVxuXG5mdW5jdGlvbiBkb21haW5TY2FsZShoZWlnaHQsIHBhZGRpbmcsIGRpbWVuc2lvbiwgdGlja3ZhbHMsIHRpY2t0ZXh0KSB7XG4gICAgdmFyIGV4dGVudCA9IGRpbWVuc2lvbkV4dGVudChkaW1lbnNpb24pO1xuICAgIGlmKHRpY2t2YWxzKSB7XG4gICAgICAgIHJldHVybiBkMy5zY2FsZS5vcmRpbmFsKClcbiAgICAgICAgICAgIC5kb21haW4odGlja3ZhbHMubWFwKHRvVGV4dChkMy5mb3JtYXQoZGltZW5zaW9uLnRpY2tmb3JtYXQpLCB0aWNrdGV4dCkpKVxuICAgICAgICAgICAgLnJhbmdlKHRpY2t2YWxzXG4gICAgICAgICAgICAgICAgLm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bml0VmFsID0gKGQgLSBleHRlbnRbMF0pIC8gKGV4dGVudFsxXSAtIGV4dGVudFswXSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoaGVpZ2h0IC0gcGFkZGluZyArIHVuaXRWYWwgKiAoMiAqIHBhZGRpbmcgLSBoZWlnaHQpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGQzLnNjYWxlLmxpbmVhcigpXG4gICAgICAgIC5kb21haW4oZXh0ZW50KVxuICAgICAgICAucmFuZ2UoW2hlaWdodCAtIHBhZGRpbmcsIHBhZGRpbmddKTtcbn1cblxuZnVuY3Rpb24gdW5pdFRvUGFkZGVkUHgoaGVpZ2h0LCBwYWRkaW5nKSB7IHJldHVybiBkMy5zY2FsZS5saW5lYXIoKS5yYW5nZShbcGFkZGluZywgaGVpZ2h0IC0gcGFkZGluZ10pOyB9XG5cbmZ1bmN0aW9uIGRvbWFpblRvUGFkZGVkVW5pdFNjYWxlKGRpbWVuc2lvbiwgcGFkRnJhY3Rpb24pIHtcbiAgICByZXR1cm4gZDMuc2NhbGUubGluZWFyKClcbiAgICAgICAgLmRvbWFpbihkaW1lbnNpb25FeHRlbnQoZGltZW5zaW9uKSlcbiAgICAgICAgLnJhbmdlKFtwYWRGcmFjdGlvbiwgMSAtIHBhZEZyYWN0aW9uXSk7XG59XG5cbmZ1bmN0aW9uIG9yZGluYWxTY2FsZShkaW1lbnNpb24pIHtcbiAgICBpZighZGltZW5zaW9uLnRpY2t2YWxzKSByZXR1cm47XG5cbiAgICB2YXIgZXh0ZW50ID0gZGltZW5zaW9uRXh0ZW50KGRpbWVuc2lvbik7XG4gICAgcmV0dXJuIGQzLnNjYWxlLm9yZGluYWwoKVxuICAgICAgICAuZG9tYWluKGRpbWVuc2lvbi50aWNrdmFscylcbiAgICAgICAgLnJhbmdlKGRpbWVuc2lvbi50aWNrdmFscy5tYXAoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIChkIC0gZXh0ZW50WzBdKSAvIChleHRlbnRbMV0gLSBleHRlbnRbMF0pO1xuICAgICAgICB9KSk7XG59XG5cbmZ1bmN0aW9uIHVuaXRUb0NvbG9yU2NhbGUoY3NjYWxlKSB7XG5cbiAgICB2YXIgY29sb3JTdG9wcyA9IGNzY2FsZS5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZFswXTsgfSk7XG4gICAgdmFyIGNvbG9yVHVwbGVzID0gY3NjYWxlLm1hcChmdW5jdGlvbihkKSB7IHJldHVybiBkMy5yZ2IoZFsxXSk7IH0pO1xuICAgIHZhciBwcm9wID0gZnVuY3Rpb24obikgeyByZXR1cm4gZnVuY3Rpb24obykgeyByZXR1cm4gb1tuXTsgfTsgfTtcblxuICAgIC8vIFdlIGNhbid0IHVzZSBkMyBjb2xvciBpbnRlcnBvbGF0aW9uIGFzIHdlIG1heSBoYXZlIG5vbi11bmlmb3JtIGNvbG9yIHBhbGV0dGUgcmFzdGVyXG4gICAgLy8gKHZhcmlvdXMgY29sb3Igc3RvcCBkaXN0YW5jZXMpLlxuICAgIHZhciBwb2x5bGluZWFyVW5pdFNjYWxlcyA9ICdyZ2InLnNwbGl0KCcnKS5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIHJldHVybiBkMy5zY2FsZS5saW5lYXIoKVxuICAgICAgICAgICAgLmNsYW1wKHRydWUpXG4gICAgICAgICAgICAuZG9tYWluKGNvbG9yU3RvcHMpXG4gICAgICAgICAgICAucmFuZ2UoY29sb3JUdXBsZXMubWFwKHByb3Aoa2V5KSkpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIHBvbHlsaW5lYXJVbml0U2NhbGVzLm1hcChmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICByZXR1cm4gcyhkKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gc29tZUZpbHRlcnNBY3RpdmUodmlldykge1xuICAgIHJldHVybiB2aWV3LmRpbWVuc2lvbnMuc29tZShmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiBwLmJydXNoLmZpbHRlclNwZWNpZmllZDtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gbW9kZWwobGF5b3V0LCBkLCBpKSB7XG4gICAgdmFyIGNkMCA9IHVud3JhcChkKSxcbiAgICAgICAgdHJhY2UgPSBjZDAudHJhY2UsXG4gICAgICAgIGxpbmVDb2xvciA9IGNkMC5saW5lQ29sb3IsXG4gICAgICAgIGNzY2FsZSA9IGNkMC5jc2NhbGUsXG4gICAgICAgIGxpbmUgPSB0cmFjZS5saW5lLFxuICAgICAgICBkb21haW4gPSB0cmFjZS5kb21haW4sXG4gICAgICAgIGRpbWVuc2lvbnMgPSB0cmFjZS5kaW1lbnNpb25zLFxuICAgICAgICB3aWR0aCA9IGxheW91dC53aWR0aCxcbiAgICAgICAgbGFiZWxGb250ID0gdHJhY2UubGFiZWxmb250LFxuICAgICAgICB0aWNrRm9udCA9IHRyYWNlLnRpY2tmb250LFxuICAgICAgICByYW5nZUZvbnQgPSB0cmFjZS5yYW5nZWZvbnQ7XG5cbiAgICB2YXIgbGluZXMgPSBMaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKHt9LCBsaW5lLCB7XG4gICAgICAgIGNvbG9yOiBsaW5lQ29sb3IubWFwKGQzLnNjYWxlLmxpbmVhcigpLmRvbWFpbihkaW1lbnNpb25FeHRlbnQoe1xuICAgICAgICAgICAgdmFsdWVzOiBsaW5lQ29sb3IsXG4gICAgICAgICAgICByYW5nZTogW2xpbmUuY21pbiwgbGluZS5jbWF4XSxcbiAgICAgICAgICAgIF9sZW5ndGg6IHRyYWNlLl9sZW5ndGhcbiAgICAgICAgfSkpKSxcbiAgICAgICAgYmxvY2tMaW5lQ291bnQ6IGMuYmxvY2tMaW5lQ291bnQsXG4gICAgICAgIGNhbnZhc092ZXJkcmFnOiBjLm92ZXJkcmFnICogYy5jYW52YXNQaXhlbFJhdGlvXG4gICAgfSk7XG5cbiAgICB2YXIgZ3JvdXBXaWR0aCA9IE1hdGguZmxvb3Iod2lkdGggKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpO1xuICAgIHZhciBncm91cEhlaWdodCA9IE1hdGguZmxvb3IobGF5b3V0LmhlaWdodCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSk7XG5cbiAgICB2YXIgcGFkID0gbGF5b3V0Lm1hcmdpbiB8fCB7bDogODAsIHI6IDgwLCB0OiAxMDAsIGI6IDgwfTtcbiAgICB2YXIgcm93Q29udGVudFdpZHRoID0gZ3JvdXBXaWR0aDtcbiAgICB2YXIgcm93SGVpZ2h0ID0gZ3JvdXBIZWlnaHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGksXG4gICAgICAgIGNvbENvdW50OiBkaW1lbnNpb25zLmZpbHRlcih2aXNpYmxlKS5sZW5ndGgsXG4gICAgICAgIGRpbWVuc2lvbnM6IGRpbWVuc2lvbnMsXG4gICAgICAgIHRpY2tEaXN0YW5jZTogYy50aWNrRGlzdGFuY2UsXG4gICAgICAgIHVuaXRUb0NvbG9yOiB1bml0VG9Db2xvclNjYWxlKGNzY2FsZSksXG4gICAgICAgIGxpbmVzOiBsaW5lcyxcbiAgICAgICAgbGFiZWxGb250OiBsYWJlbEZvbnQsXG4gICAgICAgIHRpY2tGb250OiB0aWNrRm9udCxcbiAgICAgICAgcmFuZ2VGb250OiByYW5nZUZvbnQsXG4gICAgICAgIGxheW91dFdpZHRoOiB3aWR0aCxcbiAgICAgICAgbGF5b3V0SGVpZ2h0OiBsYXlvdXQuaGVpZ2h0LFxuICAgICAgICBkb21haW46IGRvbWFpbixcbiAgICAgICAgdHJhbnNsYXRlWDogZG9tYWluLnhbMF0gKiB3aWR0aCxcbiAgICAgICAgdHJhbnNsYXRlWTogbGF5b3V0LmhlaWdodCAtIGRvbWFpbi55WzFdICogbGF5b3V0LmhlaWdodCxcbiAgICAgICAgcGFkOiBwYWQsXG4gICAgICAgIGNhbnZhc1dpZHRoOiByb3dDb250ZW50V2lkdGggKiBjLmNhbnZhc1BpeGVsUmF0aW8gKyAyICogbGluZXMuY2FudmFzT3ZlcmRyYWcsXG4gICAgICAgIGNhbnZhc0hlaWdodDogcm93SGVpZ2h0ICogYy5jYW52YXNQaXhlbFJhdGlvLFxuICAgICAgICB3aWR0aDogcm93Q29udGVudFdpZHRoLFxuICAgICAgICBoZWlnaHQ6IHJvd0hlaWdodCxcbiAgICAgICAgY2FudmFzUGl4ZWxSYXRpbzogYy5jYW52YXNQaXhlbFJhdGlvXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gdmlld01vZGVsKHN0YXRlLCBjYWxsYmFja3MsIG1vZGVsKSB7XG5cbiAgICB2YXIgd2lkdGggPSBtb2RlbC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gbW9kZWwuaGVpZ2h0O1xuICAgIHZhciBkaW1lbnNpb25zID0gbW9kZWwuZGltZW5zaW9ucztcbiAgICB2YXIgY2FudmFzUGl4ZWxSYXRpbyA9IG1vZGVsLmNhbnZhc1BpeGVsUmF0aW87XG5cbiAgICB2YXIgeFNjYWxlID0gZnVuY3Rpb24oZCkge3JldHVybiB3aWR0aCAqIGQgLyBNYXRoLm1heCgxLCBtb2RlbC5jb2xDb3VudCAtIDEpO307XG5cbiAgICB2YXIgdW5pdFBhZCA9IGMudmVydGljYWxQYWRkaW5nIC8gaGVpZ2h0O1xuICAgIHZhciBfdW5pdFRvUGFkZGVkUHggPSB1bml0VG9QYWRkZWRQeChoZWlnaHQsIGMudmVydGljYWxQYWRkaW5nKTtcblxuICAgIHZhciB2aWV3TW9kZWwgPSB7XG4gICAgICAgIGtleTogbW9kZWwua2V5LFxuICAgICAgICB4U2NhbGU6IHhTY2FsZSxcbiAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICBpbkJydXNoRHJhZzogZmFsc2UgLy8gY29uc2lkZXIgZmFjdG9yaW5nIGl0IG91dCBhbmQgcHV0dGluZyBpdCBpbiBhIGNlbnRyYWxpemVkIGdsb2JhbC1pc2ggZ2VzdHVyZSBzdGF0ZSBvYmplY3RcbiAgICB9O1xuXG4gICAgdmFyIHVuaXF1ZUtleXMgPSB7fTtcblxuICAgIHZpZXdNb2RlbC5kaW1lbnNpb25zID0gZGltZW5zaW9ucy5maWx0ZXIodmlzaWJsZSkubWFwKGZ1bmN0aW9uKGRpbWVuc2lvbiwgaSkge1xuICAgICAgICB2YXIgZG9tYWluVG9QYWRkZWRVbml0ID0gZG9tYWluVG9QYWRkZWRVbml0U2NhbGUoZGltZW5zaW9uLCB1bml0UGFkKTtcbiAgICAgICAgdmFyIGZvdW5kS2V5ID0gdW5pcXVlS2V5c1tkaW1lbnNpb24ubGFiZWxdO1xuICAgICAgICB1bmlxdWVLZXlzW2RpbWVuc2lvbi5sYWJlbF0gPSAoZm91bmRLZXkgfHwgMCkgKyAxO1xuICAgICAgICB2YXIga2V5ID0gZGltZW5zaW9uLmxhYmVsICsgKGZvdW5kS2V5ID8gJ19fJyArIGZvdW5kS2V5IDogJycpO1xuICAgICAgICB2YXIgc3BlY2lmaWVkQ29uc3RyYWludCA9IGRpbWVuc2lvbi5jb25zdHJhaW50cmFuZ2U7XG4gICAgICAgIHZhciBmaWx0ZXJSYW5nZVNwZWNpZmllZCA9IHNwZWNpZmllZENvbnN0cmFpbnQgJiYgc3BlY2lmaWVkQ29uc3RyYWludC5sZW5ndGg7XG4gICAgICAgIGlmKGZpbHRlclJhbmdlU3BlY2lmaWVkICYmICFBcnJheS5pc0FycmF5KHNwZWNpZmllZENvbnN0cmFpbnRbMF0pKSB7XG4gICAgICAgICAgICBzcGVjaWZpZWRDb25zdHJhaW50ID0gW3NwZWNpZmllZENvbnN0cmFpbnRdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmaWx0ZXJSYW5nZSA9IGZpbHRlclJhbmdlU3BlY2lmaWVkID9cbiAgICAgICAgICAgIHNwZWNpZmllZENvbnN0cmFpbnQubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQubWFwKGRvbWFpblRvUGFkZGVkVW5pdCk7IH0pIDpcbiAgICAgICAgICAgIFtbMCwgMV1dO1xuICAgICAgICB2YXIgYnJ1c2hNb3ZlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgcCA9IHZpZXdNb2RlbDtcbiAgICAgICAgICAgIHAuZm9jdXNMYXllciAmJiBwLmZvY3VzTGF5ZXIucmVuZGVyKHAucGFuZWxzLCB0cnVlKTtcbiAgICAgICAgICAgIHZhciBmaWx0ZXJzQWN0aXZlID0gc29tZUZpbHRlcnNBY3RpdmUocCk7XG4gICAgICAgICAgICBpZighc3RhdGUuY29udGV4dFNob3duKCkgJiYgZmlsdGVyc0FjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHAuY29udGV4dExheWVyICYmIHAuY29udGV4dExheWVyLnJlbmRlcihwLnBhbmVscywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgc3RhdGUuY29udGV4dFNob3duKHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHN0YXRlLmNvbnRleHRTaG93bigpICYmICFmaWx0ZXJzQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgcC5jb250ZXh0TGF5ZXIgJiYgcC5jb250ZXh0TGF5ZXIucmVuZGVyKHAucGFuZWxzLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5jb250ZXh0U2hvd24oZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciB0cnVuY2F0ZWRWYWx1ZXMgPSBkaW1lbnNpb24udmFsdWVzO1xuICAgICAgICBpZih0cnVuY2F0ZWRWYWx1ZXMubGVuZ3RoID4gZGltZW5zaW9uLl9sZW5ndGgpIHtcbiAgICAgICAgICAgIHRydW5jYXRlZFZhbHVlcyA9IHRydW5jYXRlZFZhbHVlcy5zbGljZSgwLCBkaW1lbnNpb24uX2xlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGlja3ZhbHMgPSBkaW1lbnNpb24udGlja3ZhbHM7XG4gICAgICAgIHZhciB0aWNrdGV4dDtcbiAgICAgICAgZnVuY3Rpb24gbWFrZVRpY2tJdGVtKHYsIGkpIHsgcmV0dXJuIHt2YWw6IHYsIHRleHQ6IHRpY2t0ZXh0W2ldfTsgfVxuICAgICAgICBmdW5jdGlvbiBzb3J0VGlja0l0ZW0oYSwgYikgeyByZXR1cm4gYS52YWwgLSBiLnZhbDsgfVxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHRpY2t2YWxzKSAmJiB0aWNrdmFscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRpY2t0ZXh0ID0gZGltZW5zaW9uLnRpY2t0ZXh0O1xuXG4gICAgICAgICAgICAvLyBlbnN1cmUgdGlja3RleHQgYW5kIHRpY2t2YWxzIGhhdmUgc2FtZSBsZW5ndGhcbiAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KHRpY2t0ZXh0KSB8fCAhdGlja3RleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlja3RleHQgPSB0aWNrdmFscy5tYXAoZDMuZm9ybWF0KGRpbWVuc2lvbi50aWNrZm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHRpY2t0ZXh0Lmxlbmd0aCA+IHRpY2t2YWxzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpY2t0ZXh0ID0gdGlja3RleHQuc2xpY2UoMCwgdGlja3ZhbHMubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYodGlja3ZhbHMubGVuZ3RoID4gdGlja3RleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlja3ZhbHMgPSB0aWNrdmFscy5zbGljZSgwLCB0aWNrdGV4dC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBjaGVjayBpZiB3ZSBuZWVkIHRvIHNvcnQgdGlja3ZhbHMvdGlja3RleHRcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDE7IGogPCB0aWNrdmFscy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKHRpY2t2YWxzW2pdIDwgdGlja3ZhbHNbaiAtIDFdKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aWNrSXRlbXMgPSB0aWNrdmFscy5tYXAobWFrZVRpY2tJdGVtKS5zb3J0KHNvcnRUaWNrSXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCB0aWNrdmFscy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja3ZhbHNba10gPSB0aWNrSXRlbXNba10udmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja3RleHRba10gPSB0aWNrSXRlbXNba10udGV4dDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB0aWNrdmFscyA9IHVuZGVmaW5lZDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgICBsYWJlbDogZGltZW5zaW9uLmxhYmVsLFxuICAgICAgICAgICAgdGlja0Zvcm1hdDogZGltZW5zaW9uLnRpY2tmb3JtYXQsXG4gICAgICAgICAgICB0aWNrdmFsczogdGlja3ZhbHMsXG4gICAgICAgICAgICB0aWNrdGV4dDogdGlja3RleHQsXG4gICAgICAgICAgICBvcmRpbmFsOiAhIXRpY2t2YWxzLFxuICAgICAgICAgICAgbXVsdGlzZWxlY3Q6IGRpbWVuc2lvbi5tdWx0aXNlbGVjdCxcbiAgICAgICAgICAgIHhJbmRleDogaSxcbiAgICAgICAgICAgIGNyb3NzZmlsdGVyRGltZW5zaW9uSW5kZXg6IGksXG4gICAgICAgICAgICB2aXNpYmxlSW5kZXg6IGRpbWVuc2lvbi5faW5kZXgsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHZhbHVlczogdHJ1bmNhdGVkVmFsdWVzLFxuICAgICAgICAgICAgcGFkZGVkVW5pdFZhbHVlczogdHJ1bmNhdGVkVmFsdWVzLm1hcChkb21haW5Ub1BhZGRlZFVuaXQpLFxuICAgICAgICAgICAgdW5pdFRpY2t2YWxzOiB0aWNrdmFscyAmJiB0aWNrdmFscy5tYXAoZG9tYWluVG9QYWRkZWRVbml0KSxcbiAgICAgICAgICAgIHhTY2FsZTogeFNjYWxlLFxuICAgICAgICAgICAgeDogeFNjYWxlKGkpLFxuICAgICAgICAgICAgY2FudmFzWDogeFNjYWxlKGkpICogY2FudmFzUGl4ZWxSYXRpbyxcbiAgICAgICAgICAgIHVuaXRUb1BhZGRlZFB4OiBfdW5pdFRvUGFkZGVkUHgsXG4gICAgICAgICAgICBkb21haW5TY2FsZTogZG9tYWluU2NhbGUoaGVpZ2h0LCBjLnZlcnRpY2FsUGFkZGluZywgZGltZW5zaW9uLCB0aWNrdmFscywgdGlja3RleHQpLFxuICAgICAgICAgICAgb3JkaW5hbFNjYWxlOiBvcmRpbmFsU2NhbGUoZGltZW5zaW9uKSxcbiAgICAgICAgICAgIHBhcmVudDogdmlld01vZGVsLFxuICAgICAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICAgICAgYnJ1c2g6IGJydXNoLm1ha2VCcnVzaChcbiAgICAgICAgICAgICAgICBzdGF0ZSxcbiAgICAgICAgICAgICAgICBmaWx0ZXJSYW5nZVNwZWNpZmllZCxcbiAgICAgICAgICAgICAgICBmaWx0ZXJSYW5nZSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGUubGluZVBpY2tBY3RpdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYnJ1c2hNb3ZlLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGYpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHAgPSB2aWV3TW9kZWw7XG4gICAgICAgICAgICAgICAgICAgIHAuZm9jdXNMYXllci5yZW5kZXIocC5wYW5lbHMsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBwLnBpY2tMYXllciAmJiBwLnBpY2tMYXllci5yZW5kZXIocC5wYW5lbHMsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZS5saW5lUGlja0FjdGl2ZSh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoY2FsbGJhY2tzICYmIGNhbGxiYWNrcy5maWx0ZXJDaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW52U2NhbGUgPSBkb21haW5Ub1BhZGRlZFVuaXQuaW52ZXJ0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB1cGRhdGUgZ2QuZGF0YSBhcyBpZiBhIFBsb3RseS5yZXN0eWxlIHdlcmUgZmlyZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdSYW5nZXMgPSBmLm1hcChmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHIubWFwKGludlNjYWxlKS5zb3J0KExpYi5zb3J0ZXJBc2MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhWzBdIC0gYlswXTsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFja3MuZmlsdGVyQ2hhbmdlZChwLmtleSwgZGltZW5zaW9uLl9pbmRleCwgbmV3UmFuZ2VzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgfTtcbiAgICB9KTtcblxuICAgIHJldHVybiB2aWV3TW9kZWw7XG59XG5cbmZ1bmN0aW9uIHN0eWxlRXh0ZW50VGV4dHMoc2VsZWN0aW9uKSB7XG4gICAgc2VsZWN0aW9uXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0V4dGVudFRleHQsIHRydWUpXG4gICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsICdkZWZhdWx0JylcbiAgICAgICAgLnN0eWxlKCd1c2VyLXNlbGVjdCcsICdub25lJyk7XG59XG5cbmZ1bmN0aW9uIHBhcmNvb3Jkc0ludGVyYWN0aW9uU3RhdGUoKSB7XG4gICAgdmFyIGxpbmVQaWNrQWN0aXZlID0gdHJ1ZTtcbiAgICB2YXIgY29udGV4dFNob3duID0gZmFsc2U7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGluZVBpY2tBY3RpdmU6IGZ1bmN0aW9uKHZhbCkge3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gbGluZVBpY2tBY3RpdmUgPSAhIXZhbCA6IGxpbmVQaWNrQWN0aXZlO30sXG4gICAgICAgIGNvbnRleHRTaG93bjogZnVuY3Rpb24odmFsKSB7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyBjb250ZXh0U2hvd24gPSAhIXZhbCA6IGNvbnRleHRTaG93bjt9XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihyb290LCBzdmcsIHBhcmNvb3Jkc0xpbmVMYXllcnMsIHN0eWxlZERhdGEsIGxheW91dCwgY2FsbGJhY2tzKSB7XG5cbiAgICB2YXIgc3RhdGUgPSBwYXJjb29yZHNJbnRlcmFjdGlvblN0YXRlKCk7XG5cbiAgICB2YXIgdm0gPSBzdHlsZWREYXRhXG4gICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oZCkgeyByZXR1cm4gdW53cmFwKGQpLnRyYWNlLnZpc2libGU7IH0pXG4gICAgICAgIC5tYXAobW9kZWwuYmluZCgwLCBsYXlvdXQpKVxuICAgICAgICAubWFwKHZpZXdNb2RlbC5iaW5kKDAsIHN0YXRlLCBjYWxsYmFja3MpKTtcblxuICAgIHBhcmNvb3Jkc0xpbmVMYXllcnMuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHJldHVybiBMaWIuZXh0ZW5kRmxhdChkLCB2bVtpXSk7XG4gICAgfSk7XG5cbiAgICB2YXIgcGFyY29vcmRzTGluZUxheWVyID0gcGFyY29vcmRzTGluZUxheWVycy5zZWxlY3RBbGwoJy5nbC1jYW52YXMnKVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAvLyBGSVhNRTogZmlndXJlIG91dCBob3cgdG8gaGFuZGxlIG11bHRpcGxlIGluc3RhbmNlc1xuICAgICAgICAgICAgZC52aWV3TW9kZWwgPSB2bVswXTtcbiAgICAgICAgICAgIGQubW9kZWwgPSBkLnZpZXdNb2RlbCA/IGQudmlld01vZGVsLm1vZGVsIDogbnVsbDtcbiAgICAgICAgfSk7XG5cbiAgICB2YXIgbGFzdEhvdmVyZWQgPSBudWxsO1xuXG4gICAgdmFyIHBpY2tMYXllciA9IHBhcmNvb3Jkc0xpbmVMYXllci5maWx0ZXIoZnVuY3Rpb24oZCkge3JldHVybiBkLnBpY2s7fSk7XG5cbiAgICAvLyBlbWl0IGhvdmVyIC8gdW5ob3ZlciBldmVudFxuICAgIHBpY2tMYXllclxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2F1dG8nKVxuICAgICAgICAub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKHN0YXRlLmxpbmVQaWNrQWN0aXZlKCkgJiYgZC5saW5lTGF5ZXIgJiYgY2FsbGJhY2tzICYmIGNhbGxiYWNrcy5ob3Zlcikge1xuICAgICAgICAgICAgICAgIHZhciBldmVudCA9IGQzLmV2ZW50O1xuICAgICAgICAgICAgICAgIHZhciBjdyA9IHRoaXMud2lkdGg7XG4gICAgICAgICAgICAgICAgdmFyIGNoID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgdmFyIHBvaW50ZXIgPSBkMy5tb3VzZSh0aGlzKTtcbiAgICAgICAgICAgICAgICB2YXIgeCA9IHBvaW50ZXJbMF07XG4gICAgICAgICAgICAgICAgdmFyIHkgPSBwb2ludGVyWzFdO1xuXG4gICAgICAgICAgICAgICAgaWYoeCA8IDAgfHwgeSA8IDAgfHwgeCA+PSBjdyB8fCB5ID49IGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHBpeGVsID0gZC5saW5lTGF5ZXIucmVhZFBpeGVsKHgsIGNoIC0gMSAtIHkpO1xuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IHBpeGVsWzNdICE9PSAwO1xuICAgICAgICAgICAgICAgIC8vIGludmVyc2Ugb2YgdGhlIGNhbGNQaWNrQ29sb3IgaW4gYGxpbmVzLmpzYDsgZGV0YWlsZWQgY29tbWVudCB0aGVyZVxuICAgICAgICAgICAgICAgIHZhciBjdXJ2ZU51bWJlciA9IGZvdW5kID8gcGl4ZWxbMl0gKyAyNTYgKiAocGl4ZWxbMV0gKyAyNTYgKiBwaXhlbFswXSkgOiBudWxsO1xuICAgICAgICAgICAgICAgIHZhciBldmVudERhdGEgPSB7XG4gICAgICAgICAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICAgICAgICAgIHk6IHksXG4gICAgICAgICAgICAgICAgICAgIGNsaWVudFg6IGV2ZW50LmNsaWVudFgsXG4gICAgICAgICAgICAgICAgICAgIGNsaWVudFk6IGV2ZW50LmNsaWVudFksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFJbmRleDogZC5tb2RlbC5rZXksXG4gICAgICAgICAgICAgICAgICAgIGN1cnZlTnVtYmVyOiBjdXJ2ZU51bWJlclxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYoY3VydmVOdW1iZXIgIT09IGxhc3RIb3ZlcmVkKSB7IC8vIGRvbid0IHVubmVjZXNzYXJpbHkgcmVwZWF0IHRoZSBzYW1lIGhpdCAob3IgbWlzcylcbiAgICAgICAgICAgICAgICAgICAgaWYoZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrcy5ob3ZlcihldmVudERhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoY2FsbGJhY2tzLnVuaG92ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrcy51bmhvdmVyKGV2ZW50RGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGFzdEhvdmVyZWQgPSBjdXJ2ZU51bWJlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgcGFyY29vcmRzTGluZUxheWVyXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5waWNrID8gMC4wMSA6IDE7fSk7XG5cbiAgICBzdmcuc3R5bGUoJ2JhY2tncm91bmQnLCAncmdiYSgyNTUsIDI1NSwgMjU1LCAwKScpO1xuICAgIHZhciBwYXJjb29yZHNDb250cm9sT3ZlcmxheSA9IHN2Zy5zZWxlY3RBbGwoJy4nICsgYy5jbi5wYXJjb29yZHMpXG4gICAgICAgIC5kYXRhKHZtLCBrZXlGdW4pO1xuXG4gICAgcGFyY29vcmRzQ29udHJvbE92ZXJsYXkuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgcGFyY29vcmRzQ29udHJvbE92ZXJsYXkuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5wYXJjb29yZHMsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnc2hhcGUtcmVuZGVyaW5nJywgJ2NyaXNwRWRnZXMnKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ25vbmUnKTtcblxuICAgIHBhcmNvb3Jkc0NvbnRyb2xPdmVybGF5LmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQubW9kZWwudHJhbnNsYXRlWCArICcsJyArIGQubW9kZWwudHJhbnNsYXRlWSArICcpJztcbiAgICB9KTtcblxuICAgIHZhciBwYXJjb29yZHNDb250cm9sVmlldyA9IHBhcmNvb3Jkc0NvbnRyb2xPdmVybGF5LnNlbGVjdEFsbCgnLicgKyBjLmNuLnBhcmNvb3Jkc0NvbnRyb2xWaWV3KVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBwYXJjb29yZHNDb250cm9sVmlldy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnBhcmNvb3Jkc0NvbnRyb2xWaWV3LCB0cnVlKTtcblxuICAgIHBhcmNvb3Jkc0NvbnRyb2xWaWV3LmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQubW9kZWwucGFkLmwgKyAnLCcgKyBkLm1vZGVsLnBhZC50ICsgJyknO1xuICAgIH0pO1xuXG4gICAgdmFyIHlBeGlzID0gcGFyY29vcmRzQ29udHJvbFZpZXcuc2VsZWN0QWxsKCcuJyArIGMuY24ueUF4aXMpXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKHZtKSB7IHJldHVybiB2bS5kaW1lbnNpb25zOyB9LCBrZXlGdW4pO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlUGFuZWxMYXlvdXQoeUF4aXMsIHZtKSB7XG4gICAgICAgIHZhciBwYW5lbHMgPSB2bS5wYW5lbHMgfHwgKHZtLnBhbmVscyA9IFtdKTtcbiAgICAgICAgdmFyIGRpbURhdGEgPSB5QXhpcy5kYXRhKCk7XG4gICAgICAgIHZhciBwYW5lbENvdW50ID0gZGltRGF0YS5sZW5ndGggLSAxO1xuICAgICAgICBmb3IodmFyIHAgPSAwOyBwIDwgcGFuZWxDb3VudDsgcCsrKSB7XG4gICAgICAgICAgICB2YXIgcGFuZWwgPSBwYW5lbHNbcF0gfHwgKHBhbmVsc1twXSA9IHt9KTtcbiAgICAgICAgICAgIHZhciBkaW0xID0gZGltRGF0YVtwXTtcbiAgICAgICAgICAgIHZhciBkaW0yID0gZGltRGF0YVtwICsgMV07XG4gICAgICAgICAgICBwYW5lbC5kaW0xID0gZGltMTtcbiAgICAgICAgICAgIHBhbmVsLmRpbTIgPSBkaW0yO1xuICAgICAgICAgICAgcGFuZWwuY2FudmFzWCA9IGRpbTEuY2FudmFzWDtcbiAgICAgICAgICAgIHBhbmVsLnBhbmVsU2l6ZVggPSBkaW0yLmNhbnZhc1ggLSBkaW0xLmNhbnZhc1g7XG4gICAgICAgICAgICBwYW5lbC5wYW5lbFNpemVZID0gdm0ubW9kZWwuY2FudmFzSGVpZ2h0O1xuICAgICAgICAgICAgcGFuZWwueSA9IDA7XG4gICAgICAgICAgICBwYW5lbC5jYW52YXNZID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHlBeGlzLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ueUF4aXMsIHRydWUpO1xuXG4gICAgcGFyY29vcmRzQ29udHJvbFZpZXcuZWFjaChmdW5jdGlvbih2bSkge1xuICAgICAgICB1cGRhdGVQYW5lbExheW91dCh5QXhpcywgdm0pO1xuICAgIH0pO1xuXG4gICAgcGFyY29vcmRzTGluZUxheWVyXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKGQudmlld01vZGVsKSB7XG4gICAgICAgICAgICAgICAgaWYoIWQubGluZUxheWVyIHx8IGNhbGxiYWNrcykgeyAvLyByZWNyZWF0ZSBpbiBjYXNlIG9mIGhhdmluZyBjYWxsYmFja3MgZS5nLiByZXN0eWxlLiBTaG91bGQgd2UgdGVzdCBmb3IgY2FsbGJhY2sgdG8gYmUgYSByZXN0eWxlP1xuICAgICAgICAgICAgICAgICAgICBkLmxpbmVMYXllciA9IGxpbmVMYXllck1ha2VyKHRoaXMsIGQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBkLmxpbmVMYXllci51cGRhdGUoZCk7XG5cbiAgICAgICAgICAgICAgICBpZihkLmtleSB8fCBkLmtleSA9PT0gMCkgZC52aWV3TW9kZWxbZC5rZXldID0gZC5saW5lTGF5ZXI7XG5cbiAgICAgICAgICAgICAgICB2YXIgc2V0Q2hhbmdlZCA9ICghZC5jb250ZXh0IHx8IC8vIGRvbid0IHVwZGF0ZSBiYWNrZ3JvdW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tzKTsgICAvLyB1bmxlc3MgdGhlcmUgaXMgYSBjYWxsYmFjayBvbiB0aGUgY29udGV4dCBsYXllci4gU2hvdWxkIHdlIHRlc3QgdGhlIGNhbGxiYWNrP1xuXG4gICAgICAgICAgICAgICAgZC5saW5lTGF5ZXIucmVuZGVyKGQudmlld01vZGVsLnBhbmVscywgc2V0Q2hhbmdlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgeUF4aXMuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC54U2NhbGUoZC54SW5kZXgpICsgJywgMCknO1xuICAgIH0pO1xuXG4gICAgLy8gZHJhZyBjb2x1bW4gZm9yIHJlb3JkZXJpbmcgY29sdW1uc1xuICAgIHlBeGlzLmNhbGwoZDMuYmVoYXZpb3IuZHJhZygpXG4gICAgICAgIC5vcmlnaW4oZnVuY3Rpb24oZCkgeyByZXR1cm4gZDsgfSlcbiAgICAgICAgLm9uKCdkcmFnJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHAgPSBkLnBhcmVudDtcbiAgICAgICAgICAgIHN0YXRlLmxpbmVQaWNrQWN0aXZlKGZhbHNlKTtcbiAgICAgICAgICAgIGQueCA9IE1hdGgubWF4KC1jLm92ZXJkcmFnLCBNYXRoLm1pbihkLm1vZGVsLndpZHRoICsgYy5vdmVyZHJhZywgZDMuZXZlbnQueCkpO1xuICAgICAgICAgICAgZC5jYW52YXNYID0gZC54ICogZC5tb2RlbC5jYW52YXNQaXhlbFJhdGlvO1xuICAgICAgICAgICAgeUF4aXNcbiAgICAgICAgICAgICAgICAuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhLnggLSBiLng7IH0pXG4gICAgICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24oZGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGQueEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZGQueCA9IGQgPT09IGRkID8gZGQueCA6IGRkLnhTY2FsZShkZC54SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBkZC5jYW52YXNYID0gZGQueCAqIGRkLm1vZGVsLmNhbnZhc1BpeGVsUmF0aW87XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHVwZGF0ZVBhbmVsTGF5b3V0KHlBeGlzLCBwKTtcblxuICAgICAgICAgICAgeUF4aXMuZmlsdGVyKGZ1bmN0aW9uKGRkKSB7IHJldHVybiBNYXRoLmFicyhkLnhJbmRleCAtIGRkLnhJbmRleCkgIT09IDA7IH0pXG4gICAgICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQueFNjYWxlKGQueEluZGV4KSArICcsIDApJzsgfSk7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgZC54ICsgJywgMCknKTtcbiAgICAgICAgICAgIHlBeGlzLmVhY2goZnVuY3Rpb24oZGQsIGksIGlpKSB7IGlmKGlpID09PSBkLnBhcmVudC5rZXkpIHAuZGltZW5zaW9uc1tpXSA9IGRkOyB9KTtcbiAgICAgICAgICAgIHAuY29udGV4dExheWVyICYmIHAuY29udGV4dExheWVyLnJlbmRlcihwLnBhbmVscywgZmFsc2UsICFzb21lRmlsdGVyc0FjdGl2ZShwKSk7XG4gICAgICAgICAgICBwLmZvY3VzTGF5ZXIucmVuZGVyICYmIHAuZm9jdXNMYXllci5yZW5kZXIocC5wYW5lbHMpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGQucGFyZW50O1xuICAgICAgICAgICAgZC54ID0gZC54U2NhbGUoZC54SW5kZXgpO1xuICAgICAgICAgICAgZC5jYW52YXNYID0gZC54ICogZC5tb2RlbC5jYW52YXNQaXhlbFJhdGlvO1xuICAgICAgICAgICAgdXBkYXRlUGFuZWxMYXlvdXQoeUF4aXMsIHApO1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQueCArICcsIDApJzsgfSk7XG4gICAgICAgICAgICBwLmNvbnRleHRMYXllciAmJiBwLmNvbnRleHRMYXllci5yZW5kZXIocC5wYW5lbHMsIGZhbHNlLCAhc29tZUZpbHRlcnNBY3RpdmUocCkpO1xuICAgICAgICAgICAgcC5mb2N1c0xheWVyICYmIHAuZm9jdXNMYXllci5yZW5kZXIocC5wYW5lbHMpO1xuICAgICAgICAgICAgcC5waWNrTGF5ZXIgJiYgcC5waWNrTGF5ZXIucmVuZGVyKHAucGFuZWxzLCB0cnVlKTtcbiAgICAgICAgICAgIHN0YXRlLmxpbmVQaWNrQWN0aXZlKHRydWUpO1xuXG4gICAgICAgICAgICBpZihjYWxsYmFja3MgJiYgY2FsbGJhY2tzLmF4ZXNNb3ZlZCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrcy5heGVzTW92ZWQocC5rZXksIHAuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZGQuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleDt9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIHlBeGlzLmV4aXQoKVxuICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICB2YXIgYXhpc092ZXJsYXlzID0geUF4aXMuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc092ZXJsYXlzKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBheGlzT3ZlcmxheXMuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzT3ZlcmxheXMsIHRydWUpO1xuXG4gICAgYXhpc092ZXJsYXlzLnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXMpLnJlbW92ZSgpO1xuXG4gICAgdmFyIGF4aXMgPSBheGlzT3ZlcmxheXMuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpcylcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpcy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXMsIHRydWUpO1xuXG4gICAgYXhpc1xuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgd2FudGVkVGlja0NvdW50ID0gZC5tb2RlbC5oZWlnaHQgLyBkLm1vZGVsLnRpY2tEaXN0YW5jZTtcbiAgICAgICAgICAgIHZhciBzY2FsZSA9IGQuZG9tYWluU2NhbGU7XG4gICAgICAgICAgICB2YXIgc2RvbSA9IHNjYWxlLmRvbWFpbigpO1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLmNhbGwoZDMuc3ZnLmF4aXMoKVxuICAgICAgICAgICAgICAgICAgICAub3JpZW50KCdsZWZ0JylcbiAgICAgICAgICAgICAgICAgICAgLnRpY2tTaXplKDQpXG4gICAgICAgICAgICAgICAgICAgIC5vdXRlclRpY2tTaXplKDIpXG4gICAgICAgICAgICAgICAgICAgIC50aWNrcyh3YW50ZWRUaWNrQ291bnQsIGQudGlja0Zvcm1hdCkgLy8gd29ya3MgZm9yIGNvbnRpbnVvdXMgc2NhbGVzIG9ubHkuLi5cbiAgICAgICAgICAgICAgICAgICAgLnRpY2tWYWx1ZXMoZC5vcmRpbmFsID8gLy8gYW5kIHRoaXMgd29ya3MgZm9yIG9yZGluYWwgc2NhbGVzXG4gICAgICAgICAgICAgICAgICAgICAgICBzZG9tIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bGwpXG4gICAgICAgICAgICAgICAgICAgIC50aWNrRm9ybWF0KGQub3JkaW5hbCA/IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQ7IH0gOiBudWxsKVxuICAgICAgICAgICAgICAgICAgICAuc2NhbGUoc2NhbGUpKTtcbiAgICAgICAgICAgIERyYXdpbmcuZm9udChheGlzLnNlbGVjdEFsbCgndGV4dCcpLCBkLm1vZGVsLnRpY2tGb250KTtcbiAgICAgICAgfSk7XG5cbiAgICBheGlzLnNlbGVjdEFsbCgnLmRvbWFpbiwgLnRpY2s+bGluZScpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1vcGFjaXR5JywgMC4yNSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsICcxcHgnKTtcblxuICAgIGF4aXMuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgLnN0eWxlKCd0ZXh0LXNoYWRvdycsICcxcHggMXB4IDFweCAjZmZmLCAtMXB4IC0xcHggMXB4ICNmZmYsIDFweCAtMXB4IDFweCAjZmZmLCAtMXB4IDFweCAxcHggI2ZmZicpXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgJ2RlZmF1bHQnKVxuICAgICAgICAuc3R5bGUoJ3VzZXItc2VsZWN0JywgJ25vbmUnKTtcblxuICAgIHZhciBheGlzSGVhZGluZyA9IGF4aXNPdmVybGF5cy5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzSGVhZGluZylcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc0hlYWRpbmcuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzSGVhZGluZywgdHJ1ZSk7XG5cbiAgICB2YXIgYXhpc1RpdGxlID0gYXhpc0hlYWRpbmcuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc1RpdGxlKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBheGlzVGl0bGUuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzVGl0bGUsIHRydWUpXG4gICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsICdldy1yZXNpemUnKVxuICAgICAgICAuc3R5bGUoJ3VzZXItc2VsZWN0JywgJ25vbmUnKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2F1dG8nKTtcblxuICAgIGF4aXNUaXRsZVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcgKyAtYy5heGlzVGl0bGVPZmZzZXQgKyAnKScpXG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQubGFiZWw7IH0pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHsgRHJhd2luZy5mb250KGQzLnNlbGVjdCh0aGlzKSwgZC5tb2RlbC5sYWJlbEZvbnQpOyB9KTtcblxuICAgIHZhciBheGlzRXh0ZW50ID0gYXhpc092ZXJsYXlzLnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXNFeHRlbnQpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNFeHRlbnQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzRXh0ZW50LCB0cnVlKTtcblxuICAgIHZhciBheGlzRXh0ZW50VG9wID0gYXhpc0V4dGVudC5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzRXh0ZW50VG9wKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBheGlzRXh0ZW50VG9wLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0V4dGVudFRvcCwgdHJ1ZSk7XG5cbiAgICBheGlzRXh0ZW50VG9wXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyAwICsgJywnICsgLWMuYXhpc0V4dGVudE9mZnNldCArICcpJyk7XG5cbiAgICB2YXIgYXhpc0V4dGVudFRvcFRleHQgPSBheGlzRXh0ZW50VG9wLnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXNFeHRlbnRUb3BUZXh0KVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBmdW5jdGlvbiBleHRyZW1lVGV4dChkLCBpc1RvcCkge1xuICAgICAgICBpZihkLm9yZGluYWwpIHJldHVybiAnJztcbiAgICAgICAgdmFyIGRvbWFpbiA9IGQuZG9tYWluU2NhbGUuZG9tYWluKCk7XG4gICAgICAgIHJldHVybiBkMy5mb3JtYXQoZC50aWNrRm9ybWF0KShkb21haW5baXNUb3AgPyBkb21haW4ubGVuZ3RoIC0gMSA6IDBdKTtcbiAgICB9XG5cbiAgICBheGlzRXh0ZW50VG9wVGV4dC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXNFeHRlbnRUb3BUZXh0LCB0cnVlKVxuICAgICAgICAuY2FsbChzdHlsZUV4dGVudFRleHRzKTtcblxuICAgIGF4aXNFeHRlbnRUb3BUZXh0XG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGV4dHJlbWVUZXh0KGQsIHRydWUpOyB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7IERyYXdpbmcuZm9udChkMy5zZWxlY3QodGhpcyksIGQubW9kZWwucmFuZ2VGb250KTsgfSk7XG5cbiAgICB2YXIgYXhpc0V4dGVudEJvdHRvbSA9IGF4aXNFeHRlbnQuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc0V4dGVudEJvdHRvbSlcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc0V4dGVudEJvdHRvbS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXNFeHRlbnRCb3R0b20sIHRydWUpO1xuXG4gICAgYXhpc0V4dGVudEJvdHRvbVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIDAgKyAnLCcgKyAoZC5tb2RlbC5oZWlnaHQgKyBjLmF4aXNFeHRlbnRPZmZzZXQpICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIHZhciBheGlzRXh0ZW50Qm90dG9tVGV4dCA9IGF4aXNFeHRlbnRCb3R0b20uc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc0V4dGVudEJvdHRvbVRleHQpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNFeHRlbnRCb3R0b21UZXh0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0V4dGVudEJvdHRvbVRleHQsIHRydWUpXG4gICAgICAgIC5hdHRyKCdkeScsICcwLjc1ZW0nKVxuICAgICAgICAuY2FsbChzdHlsZUV4dGVudFRleHRzKTtcblxuICAgIGF4aXNFeHRlbnRCb3R0b21UZXh0XG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGV4dHJlbWVUZXh0KGQpOyB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7IERyYXdpbmcuZm9udChkMy5zZWxlY3QodGhpcyksIGQubW9kZWwucmFuZ2VGb250KTsgfSk7XG5cbiAgICBicnVzaC5lbnN1cmVBeGlzQnJ1c2goYXhpc092ZXJsYXlzKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwYXJjb29yZHMgPSByZXF1aXJlKCcuL3BhcmNvb3JkcycpO1xudmFyIHByZXBhcmVSZWdsID0gcmVxdWlyZSgnLi4vLi4vbGliL3ByZXBhcmVfcmVnbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIGNkcGFyY29vcmRzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3ZnID0gZnVsbExheW91dC5fdG9wcGFwZXI7XG4gICAgdmFyIHJvb3QgPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdjtcbiAgICB2YXIgY29udGFpbmVyID0gZnVsbExheW91dC5fZ2xjb250YWluZXI7XG5cbiAgICB2YXIgc3VjY2VzcyA9IHByZXBhcmVSZWdsKGdkKTtcbiAgICBpZighc3VjY2VzcykgcmV0dXJuO1xuXG4gICAgdmFyIGdkRGltZW5zaW9ucyA9IHt9O1xuICAgIHZhciBnZERpbWVuc2lvbnNPcmlnaW5hbE9yZGVyID0ge307XG5cbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICBjZHBhcmNvb3Jkcy5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgZ2REaW1lbnNpb25zW2ldID0gZ2QuZGF0YVtpXS5kaW1lbnNpb25zO1xuICAgICAgICBnZERpbWVuc2lvbnNPcmlnaW5hbE9yZGVyW2ldID0gZ2QuZGF0YVtpXS5kaW1lbnNpb25zLnNsaWNlKCk7XG4gICAgfSk7XG5cbiAgICB2YXIgZmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uKGksIG9yaWdpbmFsRGltZW5zaW9uSW5kZXgsIG5ld1Jhbmdlcykge1xuXG4gICAgICAgIC8vIEhhdmUgdXBkYXRlZCBgY29uc3RyYWludHJhbmdlYCBkYXRhIG9uIGBnZC5kYXRhYCBhbmQgcmFpc2UgYFBsb3RseS5yZXN0eWxlYCBldmVudFxuICAgICAgICAvLyB3aXRob3V0IGhhdmluZyB0byBpbmN1ciBoZWF2eSBVSSBibG9ja2luZyBkdWUgdG8gYW4gYWN0dWFsIGBQbG90bHkucmVzdHlsZWAgY2FsbFxuXG4gICAgICAgIHZhciBnZERpbWVuc2lvbiA9IGdkRGltZW5zaW9uc09yaWdpbmFsT3JkZXJbaV1bb3JpZ2luYWxEaW1lbnNpb25JbmRleF07XG4gICAgICAgIHZhciBuZXdDb25zdHJhaW50cyA9IG5ld1Jhbmdlcy5tYXAoZnVuY3Rpb24ocikgeyByZXR1cm4gci5zbGljZSgpOyB9KTtcbiAgICAgICAgaWYoIW5ld0NvbnN0cmFpbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgZGVsZXRlIGdkRGltZW5zaW9uLmNvbnN0cmFpbnRyYW5nZTtcbiAgICAgICAgICAgIG5ld0NvbnN0cmFpbnRzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmKG5ld0NvbnN0cmFpbnRzLmxlbmd0aCA9PT0gMSkgbmV3Q29uc3RyYWludHMgPSBuZXdDb25zdHJhaW50c1swXTtcbiAgICAgICAgICAgIGdkRGltZW5zaW9uLmNvbnN0cmFpbnRyYW5nZSA9IG5ld0NvbnN0cmFpbnRzO1xuICAgICAgICAgICAgLy8gd3JhcCBpbiBhbm90aGVyIGFycmF5IGZvciByZXN0eWxlIGV2ZW50IGRhdGFcbiAgICAgICAgICAgIG5ld0NvbnN0cmFpbnRzID0gW25ld0NvbnN0cmFpbnRzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXN0eWxlRGF0YSA9IHt9O1xuICAgICAgICB2YXIgYVN0ciA9ICdkaW1lbnNpb25zWycgKyBvcmlnaW5hbERpbWVuc2lvbkluZGV4ICsgJ10uY29uc3RyYWludHJhbmdlJztcbiAgICAgICAgcmVzdHlsZURhdGFbYVN0cl0gPSBuZXdDb25zdHJhaW50cztcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3Jlc3R5bGUnLCBbcmVzdHlsZURhdGEsIFtpXV0pO1xuICAgIH07XG5cbiAgICB2YXIgaG92ZXIgPSBmdW5jdGlvbihldmVudERhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2hvdmVyJywgZXZlbnREYXRhKTtcbiAgICB9O1xuXG4gICAgdmFyIHVuaG92ZXIgPSBmdW5jdGlvbihldmVudERhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCBldmVudERhdGEpO1xuICAgIH07XG5cbiAgICB2YXIgYXhlc01vdmVkID0gZnVuY3Rpb24oaSwgdmlzaWJsZUluZGljZXMpIHtcblxuICAgICAgICAvLyBIYXZlIHVwZGF0ZWQgb3JkZXIgZGF0YSBvbiBgZ2QuZGF0YWAgYW5kIHJhaXNlIGBQbG90bHkucmVzdHlsZWAgZXZlbnRcbiAgICAgICAgLy8gd2l0aG91dCBoYXZpbmcgdG8gaW5jdXIgaGVhdnkgVUkgYmxvY2tpbmcgZHVlIHRvIGFuIGFjdHVhbCBgUGxvdGx5LnJlc3R5bGVgIGNhbGxcblxuICAgICAgICBmdW5jdGlvbiB2aXNpYmxlKGRpbWVuc2lvbikge3JldHVybiAhKCd2aXNpYmxlJyBpbiBkaW1lbnNpb24pIHx8IGRpbWVuc2lvbi52aXNpYmxlO31cblxuICAgICAgICBmdW5jdGlvbiBuZXdJZHgodmlzaWJsZUluZGljZXMsIG9yaWcsIGRpbSkge1xuICAgICAgICAgICAgdmFyIG9yaWdJbmRleCA9IG9yaWcuaW5kZXhPZihkaW0pO1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleCA9IHZpc2libGVJbmRpY2VzLmluZGV4T2Yob3JpZ0luZGV4KTtcbiAgICAgICAgICAgIGlmKGN1cnJlbnRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBpbnZpc2libGUgZGltZW5zaW9ucyBpbml0aWFsbHkgZ28gdG8gdGhlIGVuZFxuICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCArPSBvcmlnLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50SW5kZXg7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzb3J0ZXIob3JpZykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHNvcnRlcihkMSwgZDIpIHtcbiAgICAgICAgICAgICAgICB2YXIgaTEgPSBuZXdJZHgodmlzaWJsZUluZGljZXMsIG9yaWcsIGQxKTtcbiAgICAgICAgICAgICAgICB2YXIgaTIgPSBuZXdJZHgodmlzaWJsZUluZGljZXMsIG9yaWcsIGQyKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTEgLSBpMjtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkcmFnJmRyb3Agc29ydGluZyBvZiB0aGUgdmlzaWJsZSBkaW1lbnNpb25zXG4gICAgICAgIHZhciBvcmlnID0gc29ydGVyKGdkRGltZW5zaW9uc09yaWdpbmFsT3JkZXJbaV0uZmlsdGVyKHZpc2libGUpKTtcbiAgICAgICAgZ2REaW1lbnNpb25zW2ldLnNvcnQob3JpZyk7XG5cbiAgICAgICAgLy8gaW52aXNpYmxlIGRpbWVuc2lvbnMgYXJlIG5vdCBpbnRlcnByZXRlZCBpbiB0aGUgY29udGV4dCBvZiBkcmFnJmRyb3Agc29ydGluZyBhcyBhbiBpbnZpc2libGUgZGltZW5zaW9uXG4gICAgICAgIC8vIGNhbm5vdCBiZSBkcmFnZ2VkOyB0aGV5J3JlIGludGVyc3BlcnNlZCBpbnRvIHRoZWlyIG9yaWdpbmFsIHBvc2l0aW9ucyBieSB0aGlzIHN1YnNlcXVlbnQgbWVyZ2luZyBzdGVwXG4gICAgICAgIGdkRGltZW5zaW9uc09yaWdpbmFsT3JkZXJbaV0uZmlsdGVyKGZ1bmN0aW9uKGQpIHtyZXR1cm4gIXZpc2libGUoZCk7fSlcbiAgICAgICAgICAgICAuc29ydChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgIC8vIHN1YnNlcXVlbnQgc3BsaWNpbmcgdG8gYmUgZG9uZSBsZWZ0IHRvIHJpZ2h0LCBvdGhlcndpc2UgaW5kaWNlcyBtYXkgYmUgaW5jb3JyZWN0XG4gICAgICAgICAgICAgICAgIHJldHVybiBnZERpbWVuc2lvbnNPcmlnaW5hbE9yZGVyW2ldLmluZGV4T2YoZCk7XG4gICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBnZERpbWVuc2lvbnNbaV0uc3BsaWNlKGdkRGltZW5zaW9uc1tpXS5pbmRleE9mKGQpLCAxKTsgLy8gcmVtb3ZlIGZyb20gdGhlIGVuZFxuICAgICAgICAgICAgICAgIGdkRGltZW5zaW9uc1tpXS5zcGxpY2UoZ2REaW1lbnNpb25zT3JpZ2luYWxPcmRlcltpXS5pbmRleE9mKGQpLCAwLCBkKTsgLy8gaW5zZXJ0IGF0IG9yaWdpbmFsIGluZGV4XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVzdHlsZScpO1xuICAgIH07XG5cbiAgICBwYXJjb29yZHMoXG4gICAgICAgIHJvb3QsXG4gICAgICAgIHN2ZyxcbiAgICAgICAgY29udGFpbmVyLFxuICAgICAgICBjZHBhcmNvb3JkcyxcbiAgICAgICAge1xuICAgICAgICAgICAgd2lkdGg6IHNpemUudyxcbiAgICAgICAgICAgIGhlaWdodDogc2l6ZS5oLFxuICAgICAgICAgICAgbWFyZ2luOiB7XG4gICAgICAgICAgICAgICAgdDogc2l6ZS50LFxuICAgICAgICAgICAgICAgIHI6IHNpemUucixcbiAgICAgICAgICAgICAgICBiOiBzaXplLmIsXG4gICAgICAgICAgICAgICAgbDogc2l6ZS5sXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIGZpbHRlckNoYW5nZWQ6IGZpbHRlckNoYW5nZWQsXG4gICAgICAgICAgICBob3ZlcjogaG92ZXIsXG4gICAgICAgICAgICB1bmhvdmVyOiB1bmhvdmVyLFxuICAgICAgICAgICAgYXhlc01vdmVkOiBheGVzTW92ZWRcbiAgICAgICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciB0ZXh0Rm9udEF0dHJzID0gZm9udEF0dHJzKHtcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIGFycmF5T2s6IHRydWUsXG4gICAgY29sb3JFZGl0VHlwZTogJ3Bsb3QnLFxuICAgIFxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGxhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gZXF1aXZhbGVudCBvZiB4MCBhbmQgZHgsIGlmIGxhYmVsIGlzIG1pc3NpbmdcbiAgICBsYWJlbDA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRsYWJlbDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB2YWx1ZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGNvbG9yczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLCAgLy8gVE9ETyAnY29sb3JfYXJyYXknID9cbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuXG4vLyAnc2VlIGVnOidcbi8vICdodHRwczovL3d3dy5lLWVkdWNhdGlvbi5wc3UuZWR1L25hdHVyZW9mZ2VvaW5mby9zaXRlcy93d3cuZS1lZHVjYXRpb24ucHN1LmVkdS5uYXR1cmVvZmdlb2luZm8vZmlsZXMvaW1hZ2UvaGlzcF9waWVzLmdpZicsXG4vLyAnKHRoaXMgZXhhbXBsZSBpbnZvbHZlcyBhIG1hcCB0b28gLSBtYXkgc29tZWRheSBiZSBhIHdob2xlIHRyYWNlIHR5cGUnLFxuLy8gJ29mIGl0cyBvd24uIGJ1dCB0aGUgcG9pbnQgaXMgdGhlIHNpemUgb2YgdGhlIHdob2xlIHBpZSBpcyBpbXBvcnRhbnQuKSdcbiAgICBzY2FsZWdyb3VwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBsYWJlbHMgKGxlZ2VuZCBpcyBoYW5kbGVkIGJ5IHBsb3RzLmF0dHJpYnV0ZXMuc2hvd2xlZ2VuZCBhbmQgbGF5b3V0LmhpZGRlbmxhYmVscylcbiAgICB0ZXh0aW5mbzoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBcbiAgICAgICAgZmxhZ3M6IFsnbGFiZWwnLCAndGV4dCcsICd2YWx1ZScsICdwZXJjZW50J10sXG4gICAgICAgIGV4dHJhczogWydub25lJ10sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2xhYmVsJywgJ3RleHQnLCAndmFsdWUnLCAncGVyY2VudCcsICduYW1lJ11cbiAgICB9KSxcbiAgICB0ZXh0cG9zaXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2luc2lkZScsICdvdXRzaWRlJywgJ2F1dG8nLCAnbm9uZSddLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGV4dGZvbnQ6IGV4dGVuZEZsYXQoe30sIHRleHRGb250QXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgaW5zaWRldGV4dGZvbnQ6IGV4dGVuZEZsYXQoe30sIHRleHRGb250QXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgb3V0c2lkZXRleHRmb250OiBleHRlbmRGbGF0KHt9LCB0ZXh0Rm9udEF0dHJzLCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgdGl0bGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aXRsZXBvc2l0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAndG9wIGxlZnQnLCAndG9wIGNlbnRlcicsICd0b3AgcmlnaHQnLFxuICAgICAgICAgICAgJ21pZGRsZSBjZW50ZXInLFxuICAgICAgICAgICAgJ2JvdHRvbSBsZWZ0JywgJ2JvdHRvbSBjZW50ZXInLCAnYm90dG9tIHJpZ2h0J1xuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aXRsZWZvbnQ6IGV4dGVuZEZsYXQoe30sIHRleHRGb250QXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICAvLyBwb3NpdGlvbiBhbmQgc2hhcGVcbiAgICBkb21haW46IGRvbWFpbkF0dHJzKHtuYW1lOiAncGllJywgdHJhY2U6IHRydWUsIGVkaXRUeXBlOiAnY2FsYyd9KSxcblxuICAgIGhvbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIG9yZGVyaW5nIGFuZCBkaXJlY3Rpb25cbiAgICBzb3J0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGlyZWN0aW9uOiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiB0aGVyZSBhcmUgdHdvIGNvbW1vbiBjb252ZW50aW9ucywgYm90aCBvZiB3aGljaCBwbGFjZSB0aGUgZmlyc3RcbiAgICAgICAgICogKGxhcmdlc3QsIGlmIHNvcnRlZCkgc2xpY2Ugd2l0aCBpdHMgbGVmdCBlZGdlIGF0IDEyIG8nY2xvY2sgYnV0XG4gICAgICAgICAqIHN1Y2NlZWRpbmcgc2xpY2VzIGZvbGxvdyBlaXRoZXIgY3cgb3IgY2N3IGZyb20gdGhlcmUuXG4gICAgICAgICAqXG4gICAgICAgICAqIHNlZSBodHRwOi8vdmlzYWdlLmNvL2RhdGEtdmlzdWFsaXphdGlvbi0xMDEtcGllLWNoYXJ0cy9cbiAgICAgICAgICovXG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2Nsb2Nrd2lzZScsICdjb3VudGVyY2xvY2t3aXNlJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnY291bnRlcmNsb2Nrd2lzZScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcm90YXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IC0zNjAsXG4gICAgICAgIG1heDogMzYwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcHVsbDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcblxuZXhwb3J0cy5uYW1lID0gJ3BpZSc7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIFBpZSA9IFJlZ2lzdHJ5LmdldE1vZHVsZSgncGllJyk7XG4gICAgdmFyIGNkUGllID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsIFBpZSlbMF07XG5cbiAgICBpZihjZFBpZS5sZW5ndGgpIFBpZS5wbG90KGdkLCBjZFBpZSk7XG59O1xuXG5leHBvcnRzLmNsZWFuID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGhhZFBpZSA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKCdwaWUnKSk7XG4gICAgdmFyIGhhc1BpZSA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdwaWUnKSk7XG5cbiAgICBpZihoYWRQaWUgJiYgIWhhc1BpZSkge1xuICAgICAgICBvbGRGdWxsTGF5b3V0Ll9waWVsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG5cbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cbmV4cG9ydHMuY2FsYyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHZhbHMgPSB0cmFjZS52YWx1ZXM7XG4gICAgdmFyIGhhc1ZhbHMgPSBpc0FycmF5T3JUeXBlZEFycmF5KHZhbHMpICYmIHZhbHMubGVuZ3RoO1xuICAgIHZhciBsYWJlbHMgPSB0cmFjZS5sYWJlbHM7XG4gICAgdmFyIGNvbG9ycyA9IHRyYWNlLm1hcmtlci5jb2xvcnMgfHwgW107XG4gICAgdmFyIGNkID0gW107XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY29sb3JNYXAgPSBmdWxsTGF5b3V0Ll9waWVjb2xvcm1hcDtcbiAgICB2YXIgYWxsVGhpc1RyYWNlTGFiZWxzID0ge307XG4gICAgdmFyIHZUb3RhbCA9IDA7XG4gICAgdmFyIGhpZGRlbkxhYmVscyA9IGZ1bGxMYXlvdXQuaGlkZGVubGFiZWxzIHx8IFtdO1xuXG4gICAgdmFyIGksIHYsIGxhYmVsLCBoaWRkZW4sIHB0O1xuXG4gICAgaWYodHJhY2UuZGxhYmVsKSB7XG4gICAgICAgIGxhYmVscyA9IG5ldyBBcnJheSh2YWxzLmxlbmd0aCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHZhbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxhYmVsc1tpXSA9IFN0cmluZyh0cmFjZS5sYWJlbDAgKyBpICogdHJhY2UuZGxhYmVsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHB1bGxDb2xvcihjb2xvciwgbGFiZWwpIHtcbiAgICAgICAgaWYoIWNvbG9yKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgY29sb3IgPSB0aW55Y29sb3IoY29sb3IpO1xuICAgICAgICBpZighY29sb3IuaXNWYWxpZCgpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgY29sb3IgPSBDb2xvci5hZGRPcGFjaXR5KGNvbG9yLCBjb2xvci5nZXRBbHBoYSgpKTtcbiAgICAgICAgaWYoIWNvbG9yTWFwW2xhYmVsXSkgY29sb3JNYXBbbGFiZWxdID0gY29sb3I7XG5cbiAgICAgICAgcmV0dXJuIGNvbG9yO1xuICAgIH1cblxuICAgIHZhciBzZXJpZXNMZW4gPSAoaGFzVmFscyA/IHZhbHMgOiBsYWJlbHMpLmxlbmd0aDtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc0xlbjsgaSsrKSB7XG4gICAgICAgIGlmKGhhc1ZhbHMpIHtcbiAgICAgICAgICAgIHYgPSB2YWxzW2ldO1xuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyh2KSkgY29udGludWU7XG4gICAgICAgICAgICB2ID0gK3Y7XG4gICAgICAgICAgICBpZih2IDwgMCkgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB2ID0gMTtcblxuICAgICAgICBsYWJlbCA9IGxhYmVsc1tpXTtcbiAgICAgICAgaWYobGFiZWwgPT09IHVuZGVmaW5lZCB8fCBsYWJlbCA9PT0gJycpIGxhYmVsID0gaTtcbiAgICAgICAgbGFiZWwgPSBTdHJpbmcobGFiZWwpO1xuXG4gICAgICAgIHZhciB0aGlzTGFiZWxJbmRleCA9IGFsbFRoaXNUcmFjZUxhYmVsc1tsYWJlbF07XG4gICAgICAgIGlmKHRoaXNMYWJlbEluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGFsbFRoaXNUcmFjZUxhYmVsc1tsYWJlbF0gPSBjZC5sZW5ndGg7XG5cbiAgICAgICAgICAgIGhpZGRlbiA9IGhpZGRlbkxhYmVscy5pbmRleE9mKGxhYmVsKSAhPT0gLTE7XG5cbiAgICAgICAgICAgIGlmKCFoaWRkZW4pIHZUb3RhbCArPSB2O1xuXG4gICAgICAgICAgICBjZC5wdXNoKHtcbiAgICAgICAgICAgICAgICB2OiB2LFxuICAgICAgICAgICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgICAgICAgICBjb2xvcjogcHVsbENvbG9yKGNvbG9yc1tpXSwgbGFiZWwpLFxuICAgICAgICAgICAgICAgIGk6IGksXG4gICAgICAgICAgICAgICAgcHRzOiBbaV0sXG4gICAgICAgICAgICAgICAgaGlkZGVuOiBoaWRkZW5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcHQgPSBjZFt0aGlzTGFiZWxJbmRleF07XG4gICAgICAgICAgICBwdC52ICs9IHY7XG4gICAgICAgICAgICBwdC5wdHMucHVzaChpKTtcbiAgICAgICAgICAgIGlmKCFwdC5oaWRkZW4pIHZUb3RhbCArPSB2O1xuXG4gICAgICAgICAgICBpZihwdC5jb2xvciA9PT0gZmFsc2UgJiYgY29sb3JzW2ldKSB7XG4gICAgICAgICAgICAgICAgcHQuY29sb3IgPSBwdWxsQ29sb3IoY29sb3JzW2ldLCBsYWJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih0cmFjZS5zb3J0KSBjZC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGIudiAtIGEudjsgfSk7XG5cbiAgICAvLyBpbmNsdWRlIHRoZSBzdW0gb2YgYWxsIHZhbHVlcyBpbiB0aGUgZmlyc3QgcG9pbnRcbiAgICBpZihjZFswXSkgY2RbMF0udlRvdGFsID0gdlRvdGFsO1xuXG4gICAgLy8gbm93IGluc2VydCB0ZXh0XG4gICAgaWYodHJhY2UudGV4dGluZm8gJiYgdHJhY2UudGV4dGluZm8gIT09ICdub25lJykge1xuICAgICAgICB2YXIgaGFzTGFiZWwgPSB0cmFjZS50ZXh0aW5mby5pbmRleE9mKCdsYWJlbCcpICE9PSAtMTtcbiAgICAgICAgdmFyIGhhc1RleHQgPSB0cmFjZS50ZXh0aW5mby5pbmRleE9mKCd0ZXh0JykgIT09IC0xO1xuICAgICAgICB2YXIgaGFzVmFsdWUgPSB0cmFjZS50ZXh0aW5mby5pbmRleE9mKCd2YWx1ZScpICE9PSAtMTtcbiAgICAgICAgdmFyIGhhc1BlcmNlbnQgPSB0cmFjZS50ZXh0aW5mby5pbmRleE9mKCdwZXJjZW50JykgIT09IC0xO1xuICAgICAgICB2YXIgc2VwYXJhdG9ycyA9IGZ1bGxMYXlvdXQuc2VwYXJhdG9ycztcblxuICAgICAgICB2YXIgdGhpc1RleHQ7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHB0ID0gY2RbaV07XG4gICAgICAgICAgICB0aGlzVGV4dCA9IGhhc0xhYmVsID8gW3B0LmxhYmVsXSA6IFtdO1xuICAgICAgICAgICAgaWYoaGFzVGV4dCkge1xuICAgICAgICAgICAgICAgIHZhciB0ZXh0aSA9IGhlbHBlcnMuZ2V0Rmlyc3RGaWxsZWQodHJhY2UudGV4dCwgcHQucHRzKTtcbiAgICAgICAgICAgICAgICBpZih0ZXh0aSkgdGhpc1RleHQucHVzaCh0ZXh0aSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihoYXNWYWx1ZSkgdGhpc1RleHQucHVzaChoZWxwZXJzLmZvcm1hdFBpZVZhbHVlKHB0LnYsIHNlcGFyYXRvcnMpKTtcbiAgICAgICAgICAgIGlmKGhhc1BlcmNlbnQpIHRoaXNUZXh0LnB1c2goaGVscGVycy5mb3JtYXRQaWVQZXJjZW50KHB0LnYgLyB2VG90YWwsIHNlcGFyYXRvcnMpKTtcbiAgICAgICAgICAgIHB0LnRleHQgPSB0aGlzVGV4dC5qb2luKCc8YnI+Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG4vKlxuICogYGNhbGNgIGZpbGxlZCBpbiAoYW5kIGNvbGxhdGVkKSBleHBsaWNpdCBjb2xvcnMuXG4gKiBOb3cgd2UgbmVlZCB0byBwcm9wYWdhdGUgdGhlc2UgZXhwbGljaXQgY29sb3JzIHRvIG90aGVyIHRyYWNlcyxcbiAqIGFuZCBmaWxsIGluIGRlZmF1bHQgY29sb3JzLlxuICogVGhpcyBpcyBkb25lIGFmdGVyIHNvcnRpbmcsIHNvIHdlIHBpY2sgZGVmYXVsdHNcbiAqIGluIHRoZSBvcmRlciBzbGljZXMgd2lsbCBiZSBkaXNwbGF5ZWRcbiAqL1xuZXhwb3J0cy5jcm9zc1RyYWNlQ2FsYyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgcGllQ29sb3JXYXkgPSBmdWxsTGF5b3V0LnBpZWNvbG9yd2F5O1xuICAgIHZhciBjb2xvck1hcCA9IGZ1bGxMYXlvdXQuX3BpZWNvbG9ybWFwO1xuXG4gICAgaWYoZnVsbExheW91dC5leHRlbmRwaWVjb2xvcnMpIHtcbiAgICAgICAgcGllQ29sb3JXYXkgPSBnZW5lcmF0ZUV4dGVuZGVkQ29sb3JzKHBpZUNvbG9yV2F5KTtcbiAgICB9XG4gICAgdmFyIGRmbHRDb2xvckNvdW50ID0gMDtcblxuICAgIHZhciBpLCBqLCBjZCwgcHQ7XG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY2QgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgaWYoY2RbMF0udHJhY2UudHlwZSAhPT0gJ3BpZScpIGNvbnRpbnVlO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBwdCA9IGNkW2pdO1xuICAgICAgICAgICAgaWYocHQuY29sb3IgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgLy8gaGF2ZSB3ZSBzZWVuIHRoaXMgbGFiZWwgYW5kIGFzc2lnbmVkIGEgY29sb3IgdG8gaXQgaW4gYSBwcmV2aW91cyB0cmFjZT9cbiAgICAgICAgICAgICAgICBpZihjb2xvck1hcFtwdC5sYWJlbF0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHQuY29sb3IgPSBjb2xvck1hcFtwdC5sYWJlbF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb2xvck1hcFtwdC5sYWJlbF0gPSBwdC5jb2xvciA9IHBpZUNvbG9yV2F5W2RmbHRDb2xvckNvdW50ICUgcGllQ29sb3JXYXkubGVuZ3RoXTtcbiAgICAgICAgICAgICAgICAgICAgZGZsdENvbG9yQ291bnQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKipcbiAqIHBpY2sgYSBkZWZhdWx0IGNvbG9yIGZyb20gdGhlIG1haW4gZGVmYXVsdCBzZXQsIGF1Z21lbnRlZCBieVxuICogaXRzZWxmIGxpZ2h0ZXIgdGhlbiBkYXJrZXIgYmVmb3JlIHJlcGVhdGluZ1xuICovXG52YXIgZXh0ZW5kZWRDb2xvcldheXMgPSB7fTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVFeHRlbmRlZENvbG9ycyhjb2xvckxpc3QpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgY29sb3JTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShjb2xvckxpc3QpO1xuICAgIHZhciBwaWVDb2xvcnMgPSBleHRlbmRlZENvbG9yV2F5c1tjb2xvclN0cmluZ107XG4gICAgaWYoIXBpZUNvbG9ycykge1xuICAgICAgICBwaWVDb2xvcnMgPSBjb2xvckxpc3Quc2xpY2UoKTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb2xvckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHBpZUNvbG9ycy5wdXNoKHRpbnljb2xvcihjb2xvckxpc3RbaV0pLmxpZ2h0ZW4oMjApLnRvSGV4U3RyaW5nKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY29sb3JMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwaWVDb2xvcnMucHVzaCh0aW55Y29sb3IoY29sb3JMaXN0W2ldKS5kYXJrZW4oMjApLnRvSGV4U3RyaW5nKCkpO1xuICAgICAgICB9XG4gICAgICAgIGV4dGVuZGVkQ29sb3JXYXlzW2NvbG9yU3RyaW5nXSA9IHBpZUNvbG9ycztcbiAgICB9XG5cbiAgICByZXR1cm4gcGllQ29sb3JzO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZG9tYWluJykuZGVmYXVsdHM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBjb2VyY2VGb250ID0gTGliLmNvZXJjZUZvbnQ7XG4gICAgdmFyIGxlbjtcblxuICAgIHZhciB2YWxzID0gY29lcmNlKCd2YWx1ZXMnKTtcbiAgICB2YXIgaGFzVmFscyA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHZhbHMpO1xuICAgIHZhciBsYWJlbHMgPSBjb2VyY2UoJ2xhYmVscycpO1xuICAgIGlmKEFycmF5LmlzQXJyYXkobGFiZWxzKSkge1xuICAgICAgICBsZW4gPSBsYWJlbHMubGVuZ3RoO1xuICAgICAgICBpZihoYXNWYWxzKSBsZW4gPSBNYXRoLm1pbihsZW4sIHZhbHMubGVuZ3RoKTtcbiAgICB9XG4gICAgZWxzZSBpZihoYXNWYWxzKSB7XG4gICAgICAgIGxlbiA9IHZhbHMubGVuZ3RoO1xuXG4gICAgICAgIGNvZXJjZSgnbGFiZWwwJyk7XG4gICAgICAgIGNvZXJjZSgnZGxhYmVsJyk7XG4gICAgfVxuXG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgaWYobGluZVdpZHRoKSBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJyk7XG5cbiAgICBjb2VyY2UoJ21hcmtlci5jb2xvcnMnKTtcblxuICAgIGNvZXJjZSgnc2NhbGVncm91cCcpO1xuICAgIC8vIFRPRE86IGhvbGUgbmVlZHMgdG8gYmUgY29lcmNlZCB0byB0aGUgc2FtZSB2YWx1ZSB3aXRoaW4gYSBzY2FsZWVncm91cFxuXG4gICAgdmFyIHRleHREYXRhID0gY29lcmNlKCd0ZXh0Jyk7XG4gICAgdmFyIHRleHRJbmZvID0gY29lcmNlKCd0ZXh0aW5mbycsIEFycmF5LmlzQXJyYXkodGV4dERhdGEpID8gJ3RleHQrcGVyY2VudCcgOiAncGVyY2VudCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG5cbiAgICBpZih0ZXh0SW5mbyAmJiB0ZXh0SW5mbyAhPT0gJ25vbmUnKSB7XG4gICAgICAgIHZhciB0ZXh0UG9zaXRpb24gPSBjb2VyY2UoJ3RleHRwb3NpdGlvbicpLFxuICAgICAgICAgICAgaGFzQm90aCA9IEFycmF5LmlzQXJyYXkodGV4dFBvc2l0aW9uKSB8fCB0ZXh0UG9zaXRpb24gPT09ICdhdXRvJyxcbiAgICAgICAgICAgIGhhc0luc2lkZSA9IGhhc0JvdGggfHwgdGV4dFBvc2l0aW9uID09PSAnaW5zaWRlJyxcbiAgICAgICAgICAgIGhhc091dHNpZGUgPSBoYXNCb3RoIHx8IHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnO1xuXG4gICAgICAgIGlmKGhhc0luc2lkZSB8fCBoYXNPdXRzaWRlKSB7XG4gICAgICAgICAgICB2YXIgZGZsdEZvbnQgPSBjb2VyY2VGb250KGNvZXJjZSwgJ3RleHRmb250JywgbGF5b3V0LmZvbnQpO1xuICAgICAgICAgICAgaWYoaGFzSW5zaWRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluc2lkZVRleHRGb250RGVmYXVsdCA9IExpYi5leHRlbmRGbGF0KHt9LCBkZmx0Rm9udCk7XG4gICAgICAgICAgICAgICAgdmFyIGlzVHJhY2VUZXh0Zm9udENvbG9yU2V0ID0gdHJhY2VJbi50ZXh0Zm9udCAmJiB0cmFjZUluLnRleHRmb250LmNvbG9yO1xuICAgICAgICAgICAgICAgIHZhciBpc0NvbG9ySW5oZXJpdGVkRnJvbUxheW91dEZvbnQgPSAhaXNUcmFjZVRleHRmb250Q29sb3JTZXQ7XG4gICAgICAgICAgICAgICAgaWYoaXNDb2xvckluaGVyaXRlZEZyb21MYXlvdXRGb250KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBpbnNpZGVUZXh0Rm9udERlZmF1bHQuY29sb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvZXJjZUZvbnQoY29lcmNlLCAnaW5zaWRldGV4dGZvbnQnLCBpbnNpZGVUZXh0Rm9udERlZmF1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaGFzT3V0c2lkZSkgY29lcmNlRm9udChjb2VyY2UsICdvdXRzaWRldGV4dGZvbnQnLCBkZmx0Rm9udCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBoYW5kbGVEb21haW5EZWZhdWx0cyh0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgdmFyIGhvbGUgPSBjb2VyY2UoJ2hvbGUnKTtcbiAgICB2YXIgdGl0bGUgPSBjb2VyY2UoJ3RpdGxlJyk7XG4gICAgaWYodGl0bGUpIHtcbiAgICAgICAgdmFyIHRpdGxlUG9zaXRpb24gPSBjb2VyY2UoJ3RpdGxlcG9zaXRpb24nLCBob2xlID8gJ21pZGRsZSBjZW50ZXInIDogJ3RvcCBjZW50ZXInKTtcbiAgICAgICAgaWYoIWhvbGUgJiYgdGl0bGVQb3NpdGlvbiA9PT0gJ21pZGRsZSBjZW50ZXInKSB0cmFjZU91dC50aXRsZXBvc2l0aW9uID0gJ3RvcCBjZW50ZXInO1xuICAgICAgICBjb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlZm9udCcsIGxheW91dC5mb250KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3NvcnQnKTtcbiAgICBjb2VyY2UoJ2RpcmVjdGlvbicpO1xuICAgIGNvZXJjZSgncm90YXRpb24nKTtcblxuICAgIGNvZXJjZSgncHVsbCcpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXBwZW5kQXJyYXlNdWx0aVBvaW50VmFsdWVzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meC9oZWxwZXJzJykuYXBwZW5kQXJyYXlNdWx0aVBvaW50VmFsdWVzO1xuXG5cbi8vIE5vdGU6IGxpa2Ugb3RoZXIgZXZlbnREYXRhIHJvdXRpbmVzLCB0aGlzIGNyZWF0ZXMgdGhlIGRhdGEgZm9yIGhvdmVyL3VuaG92ZXIvY2xpY2sgZXZlbnRzXG4vLyBidXQgaXQgaGFzIGEgZGlmZmVyZW50IEFQSSBhbmQgZ29lcyB0aHJvdWdoIGEgdG90YWxseSBkaWZmZXJlbnQgcGF0aHdheS5cbi8vIFNvIHRvIGVuc3VyZSBpdCBkb2Vzbid0IGdldCBtaXN1c2VkLCBpdCdzIG5vdCBhdHRhY2hlZCB0byB0aGUgUGllIG1vZHVsZS5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXZlbnREYXRhKHB0LCB0cmFjZSkge1xuICAgIHZhciBvdXQgPSB7XG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgcG9pbnROdW1iZXJzOiBwdC5wdHMsXG4gICAgICAgIGRhdGE6IHRyYWNlLl9pbnB1dCxcbiAgICAgICAgZnVsbERhdGE6IHRyYWNlLFxuICAgICAgICBsYWJlbDogcHQubGFiZWwsXG4gICAgICAgIGNvbG9yOiBwdC5jb2xvcixcbiAgICAgICAgdmFsdWU6IHB0LnYsXG5cbiAgICAgICAgLy8gcHQudiAoYW5kIHB0LmkgYmVsb3cpIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICAgIHY6IHB0LnZcbiAgICB9O1xuXG4gICAgLy8gT25seSBpbmNsdWRlIHBvaW50TnVtYmVyIGlmIGl0J3MgdW5hbWJpZ3VvdXNcbiAgICBpZihwdC5wdHMubGVuZ3RoID09PSAxKSBvdXQucG9pbnROdW1iZXIgPSBvdXQuaSA9IHB0LnB0c1swXTtcblxuICAgIC8vIEFkZCBleHRyYSBkYXRhIGFycmF5cyB0byB0aGUgb3V0cHV0XG4gICAgLy8gbm90aWNlIHRoYXQgdGhpcyBpcyB0aGUgbXVsdGktcG9pbnQgdmVyc2lvbiAoJ3MnIG9uIHRoZSBlbmQhKVxuICAgIC8vIHNvIGFkZGVkIGRhdGEgd2lsbCBiZSBhcnJheXMgbWF0Y2hpbmcgdGhlIHBvaW50TnVtYmVycyBhcnJheS5cbiAgICBhcHBlbmRBcnJheU11bHRpUG9pbnRWYWx1ZXMob3V0LCB0cmFjZSwgcHQucHRzKTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbmV4cG9ydHMuZm9ybWF0UGllUGVyY2VudCA9IGZ1bmN0aW9uIGZvcm1hdFBpZVBlcmNlbnQodiwgc2VwYXJhdG9ycykge1xuICAgIHZhciB2Um91bmRlZCA9ICh2ICogMTAwKS50b1ByZWNpc2lvbigzKTtcbiAgICBpZih2Um91bmRlZC5sYXN0SW5kZXhPZignLicpICE9PSAtMSkge1xuICAgICAgICB2Um91bmRlZCA9IHZSb3VuZGVkLnJlcGxhY2UoL1suXT8wKyQvLCAnJyk7XG4gICAgfVxuICAgIHJldHVybiBMaWIubnVtU2VwYXJhdGUodlJvdW5kZWQsIHNlcGFyYXRvcnMpICsgJyUnO1xufTtcblxuZXhwb3J0cy5mb3JtYXRQaWVWYWx1ZSA9IGZ1bmN0aW9uIGZvcm1hdFBpZVZhbHVlKHYsIHNlcGFyYXRvcnMpIHtcbiAgICB2YXIgdlJvdW5kZWQgPSB2LnRvUHJlY2lzaW9uKDEwKTtcbiAgICBpZih2Um91bmRlZC5sYXN0SW5kZXhPZignLicpICE9PSAtMSkge1xuICAgICAgICB2Um91bmRlZCA9IHZSb3VuZGVkLnJlcGxhY2UoL1suXT8wKyQvLCAnJyk7XG4gICAgfVxuICAgIHJldHVybiBMaWIubnVtU2VwYXJhdGUodlJvdW5kZWQsIHNlcGFyYXRvcnMpO1xufTtcblxuZXhwb3J0cy5nZXRGaXJzdEZpbGxlZCA9IGZ1bmN0aW9uIGdldEZpcnN0RmlsbGVkKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgaWYoIUFycmF5LmlzQXJyYXkoYXJyYXkpKSByZXR1cm47XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHYgPSBhcnJheVtpbmRpY2VzW2ldXTtcbiAgICAgICAgaWYodiB8fCB2ID09PSAwKSByZXR1cm4gdjtcbiAgICB9XG59O1xuXG5leHBvcnRzLmNhc3RPcHRpb24gPSBmdW5jdGlvbiBjYXN0T3B0aW9uKGl0ZW0sIGluZGljZXMpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KGl0ZW0pKSByZXR1cm4gZXhwb3J0cy5nZXRGaXJzdEZpbGxlZChpdGVtLCBpbmRpY2VzKTtcbiAgICBlbHNlIGlmKGl0ZW0pIHJldHVybiBpdGVtO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFBpZSA9IHt9O1xuXG5QaWUuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuUGllLnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuUGllLnN1cHBseUxheW91dERlZmF1bHRzID0gcmVxdWlyZSgnLi9sYXlvdXRfZGVmYXVsdHMnKTtcblBpZS5sYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgY2FsY01vZHVsZSA9IHJlcXVpcmUoJy4vY2FsYycpO1xuUGllLmNhbGMgPSBjYWxjTW9kdWxlLmNhbGM7XG5QaWUuY3Jvc3NUcmFjZUNhbGMgPSBjYWxjTW9kdWxlLmNyb3NzVHJhY2VDYWxjO1xuXG5QaWUucGxvdCA9IHJlcXVpcmUoJy4vcGxvdCcpO1xuUGllLnN0eWxlID0gcmVxdWlyZSgnLi9zdHlsZScpO1xuUGllLnN0eWxlT25lID0gcmVxdWlyZSgnLi9zdHlsZV9vbmUnKTtcblxuUGllLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuUGllLm5hbWUgPSAncGllJztcblBpZS5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4vYmFzZV9wbG90Jyk7XG5QaWUuY2F0ZWdvcmllcyA9IFsncGllJywgJ3Nob3dMZWdlbmQnXTtcblBpZS5tZXRhID0ge1xuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBQaWU7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIGhpZGRlbmxhYmVscyBpcyB0aGUgcGllIGNoYXJ0IGFuYWxvZyBvZiB2aXNpYmxlOidsZWdlbmRvbmx5J1xuICAgICAqIGJ1dCBpdCBjYW4gY29udGFpbiBtYW55IGxhYmVscywgYW5kIGNhbiBoaWRlIHNsaWNlc1xuICAgICAqIGZyb20gc2V2ZXJhbCBwaWVzIHNpbXVsdGFuZW91c2x5XG4gICAgICovXG4gICAgaGlkZGVubGFiZWxzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgcGllY29sb3J3YXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9ybGlzdCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGV4dGVuZHBpZWNvbG9yczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXlvdXRJbiwgbGF5b3V0T3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG4gICAgY29lcmNlKCdoaWRkZW5sYWJlbHMnKTtcbiAgICBjb2VyY2UoJ3BpZWNvbG9yd2F5JywgbGF5b3V0T3V0LmNvbG9yd2F5KTtcbiAgICBjb2VyY2UoJ2V4dGVuZHBpZWNvbG9ycycpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBzdmdUZXh0VXRpbHMgPSByZXF1aXJlKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcblxudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBldmVudERhdGEgPSByZXF1aXJlKCcuL2V2ZW50X2RhdGEnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBjZHBpZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBwcmVyZW5kZXJUaXRsZXMoY2RwaWUsIGdkKTtcbiAgICBzY2FsZVBpZXMoY2RwaWUsIGZ1bGxMYXlvdXQuX3NpemUpO1xuXG4gICAgdmFyIHBpZUdyb3VwcyA9IExpYi5tYWtlVHJhY2VHcm91cHMoZnVsbExheW91dC5fcGllbGF5ZXIsIGNkcGllLCAndHJhY2UnKS5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgIHZhciBwaWVHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAgICAgc2V0Q29vcmRzKGNkKTtcblxuICAgICAgICAvLyBUT0RPOiBtaXRlciBtaWdodCBsb29rIGJldHRlciBidXQgY2FuIHNvbWV0aW1lcyBjYXVzZSBwcm9ibGVtc1xuICAgICAgICAvLyBtYXliZSBtaXRlciB3aXRoIGEgc21hbGwtaXNoIHN0cm9rZS1taXRlcmxpbWl0P1xuICAgICAgICBwaWVHcm91cC5hdHRyKCdzdHJva2UtbGluZWpvaW4nLCAncm91bmQnKTtcblxuICAgICAgICBwaWVHcm91cC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHNsaWNlcyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cuc2xpY2UnKS5kYXRhKGNkKTtcblxuICAgICAgICAgICAgc2xpY2VzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc2xpY2UnLCB0cnVlKTtcbiAgICAgICAgICAgIHNsaWNlcy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIHZhciBxdWFkcmFudHMgPSBbXG4gICAgICAgICAgICAgICAgW1tdLCBbXV0sIC8vIHk8MDogeDwwLCB4Pj0wXG4gICAgICAgICAgICAgICAgW1tdLCBbXV0gLy8geT49MDogeDwwLCB4Pj0wXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgdmFyIGhhc091dHNpZGVUZXh0ID0gZmFsc2U7XG5cbiAgICAgICAgICAgIHNsaWNlcy5lYWNoKGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgICAgICAgICAgaWYocHQuaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3BhdGgsZycpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gdG8gaGF2ZSBjb25zaXN0ZW50IGV2ZW50IGRhdGEgY29tcGFyZWQgdG8gb3RoZXIgdHJhY2VzXG4gICAgICAgICAgICAgICAgcHQucG9pbnROdW1iZXIgPSBwdC5pO1xuICAgICAgICAgICAgICAgIHB0LmN1cnZlTnVtYmVyID0gdHJhY2UuaW5kZXg7XG5cbiAgICAgICAgICAgICAgICBxdWFkcmFudHNbcHQucHhtaWRbMV0gPCAwID8gMCA6IDFdW3B0LnB4bWlkWzBdIDwgMCA/IDAgOiAxXS5wdXNoKHB0KTtcblxuICAgICAgICAgICAgICAgIHZhciBjeCA9IGNkMC5jeDtcbiAgICAgICAgICAgICAgICB2YXIgY3kgPSBjZDAuY3k7XG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlVG9wID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBzbGljZVBhdGggPSBzbGljZVRvcC5zZWxlY3RBbGwoJ3BhdGguc3VyZmFjZScpLmRhdGEoW3B0XSk7XG5cbiAgICAgICAgICAgICAgICAvLyBob3ZlciBzdGF0ZSB2YXJzXG4gICAgICAgICAgICAgICAgLy8gaGF2ZSB3ZSBkcmF3biBhIGhvdmVyIGxhYmVsLCBzbyBpdCBzaG91bGQgYmUgY2xlYXJlZCBsYXRlclxuICAgICAgICAgICAgICAgIHZhciBoYXNIb3ZlckxhYmVsID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgLy8gaGF2ZSB3ZSBlbWl0dGVkIGEgaG92ZXIgZXZlbnQsIHNvIGxhdGVyIGFuIHVuaG92ZXIgZXZlbnQgc2hvdWxkIGJlIGVtaXR0ZWRcbiAgICAgICAgICAgICAgICAvLyBub3RlIHRoYXQgY2xpY2sgZXZlbnRzIGRvIG5vdCBkZXBlbmQgb24gdGhpcyAtIHlvdSBjYW4gc3RpbGwgZ2V0IHRoZW1cbiAgICAgICAgICAgICAgICAvLyB3aXRoIGhvdmVybW9kZTogZmFsc2Ugb3IgaWYgeW91IHdlcmUgZWFybGllciBkcmFnZ2luZywgdGhlbiBjbGlja2VkXG4gICAgICAgICAgICAgICAgLy8gaW4gdGhlIHNhbWUgc2xpY2UgdGhhdCB5b3UgbW91c2VkIHVwIGluXG4gICAgICAgICAgICAgICAgdmFyIGhhc0hvdmVyRXZlbnQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZU1vdXNlT3ZlcigpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gY2FzZSBmdWxsTGF5b3V0IG9yIGZ1bGxEYXRhIGhhcyBjaGFuZ2VkIHdpdGhvdXQgYSByZXBsb3RcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGdkLl9kcmFnZ2luZyB8fCBmdWxsTGF5b3V0Mi5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGhvdmVyaW5mbyA9IHRyYWNlMi5ob3ZlcmluZm87XG4gICAgICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoaG92ZXJpbmZvKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3VwZXIgaGFja3k6IHdlIG5lZWQgdG8gcHVsbCBvdXQgdGhlICpmaXJzdCogaG92ZXJpbmZvIGZyb21cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHB0LnB0cywgdGhlbiBwdXQgaXQgYmFjayBpbnRvIGFuIGFycmF5IGluIGEgZHVtbXkgdHJhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCBjYWxsIGNhc3RIb3ZlcmluZm8gb24gdGhhdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGRvIHdlIHdhbnQgdG8gaGF2ZSBGeC5jYXN0SG92ZXJpbmZvIHNvbWVob3cgaGFuZGxlIHRoaXM/XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpdCBhbHJlYWR5IHRha2VzIGFuIGFycmF5IGZvciBpbmRleCwgZm9yIDJELCBzbyB0aGlzIHNlZW1zIHRyaWNreS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGhvdmVyaW5mbyA9IEZ4LmNhc3RIb3ZlcmluZm8oe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdmVyaW5mbzogW2hlbHBlcnMuY2FzdE9wdGlvbihob3ZlcmluZm8sIHB0LnB0cyldLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9tb2R1bGU6IHRyYWNlLl9tb2R1bGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bGxMYXlvdXQyLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKGhvdmVyaW5mbyA9PT0gJ2FsbCcpIGhvdmVyaW5mbyA9ICdsYWJlbCt0ZXh0K3ZhbHVlK3BlcmNlbnQrbmFtZSc7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gY2FzZSB3ZSBkcmFnZ2VkIG92ZXIgdGhlIHBpZSBmcm9tIGFub3RoZXIgc3VicGxvdCxcbiAgICAgICAgICAgICAgICAgICAgLy8gb3IgaWYgaG92ZXIgaXMgdHVybmVkIG9mZlxuICAgICAgICAgICAgICAgICAgICBpZihob3ZlcmluZm8gIT09ICdub25lJyAmJiBob3ZlcmluZm8gIT09ICdza2lwJyAmJiBob3ZlcmluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBySW5zY3JpYmVkID0gZ2V0SW5zY3JpYmVkUmFkaXVzRnJhY3Rpb24ocHQsIGNkMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXJYID0gY3ggKyBwdC5weG1pZFswXSAqICgxIC0gckluc2NyaWJlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXJZID0gY3kgKyBwdC5weG1pZFsxXSAqICgxIC0gckluc2NyaWJlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VwYXJhdG9ycyA9IGZ1bGxMYXlvdXQuc2VwYXJhdG9ycztcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aGlzVGV4dCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihob3ZlcmluZm8uaW5kZXhPZignbGFiZWwnKSAhPT0gLTEpIHRoaXNUZXh0LnB1c2gocHQubGFiZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaG92ZXJpbmZvLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGV4dGkgPSBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UyLmhvdmVydGV4dCB8fCB0cmFjZTIudGV4dCwgcHQucHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih0ZXh0aSkgdGhpc1RleHQucHVzaCh0ZXh0aSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihob3ZlcmluZm8uaW5kZXhPZigndmFsdWUnKSAhPT0gLTEpIHRoaXNUZXh0LnB1c2goaGVscGVycy5mb3JtYXRQaWVWYWx1ZShwdC52LCBzZXBhcmF0b3JzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihob3ZlcmluZm8uaW5kZXhPZigncGVyY2VudCcpICE9PSAtMSkgdGhpc1RleHQucHVzaChoZWxwZXJzLmZvcm1hdFBpZVBlcmNlbnQocHQudiAvIGNkMC52VG90YWwsIHNlcGFyYXRvcnMpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhvdmVyTGFiZWwgPSB0cmFjZS5ob3ZlcmxhYmVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhvdmVyRm9udCA9IGhvdmVyTGFiZWwuZm9udDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MDogaG92ZXJDZW50ZXJYIC0gckluc2NyaWJlZCAqIGNkMC5yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgxOiBob3ZlckNlbnRlclggKyBySW5zY3JpYmVkICogY2QwLnIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeTogaG92ZXJDZW50ZXJZLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IHRoaXNUZXh0LmpvaW4oJzxicj4nKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBob3ZlcmluZm8uaW5kZXhPZignbmFtZScpICE9PSAtMSA/IHRyYWNlMi5uYW1lIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZWFsQWxpZ246IHB0LnB4bWlkWzBdIDwgMCA/ICdsZWZ0JyA6ICdyaWdodCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IGhlbHBlcnMuY2FzdE9wdGlvbihob3ZlckxhYmVsLmJnY29sb3IsIHB0LnB0cykgfHwgcHQuY29sb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6IGhlbHBlcnMuY2FzdE9wdGlvbihob3ZlckxhYmVsLmJvcmRlcmNvbG9yLCBwdC5wdHMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRGYW1pbHk6IGhlbHBlcnMuY2FzdE9wdGlvbihob3ZlckZvbnQuZmFtaWx5LCBwdC5wdHMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRTaXplOiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJGb250LnNpemUsIHB0LnB0cyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJGb250LmNvbG9yLCBwdC5wdHMpXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Mi5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0ZXJDb250YWluZXI6IGZ1bGxMYXlvdXQyLl9wYXBlci5ub2RlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzSG92ZXJMYWJlbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfaG92ZXInLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludHM6IFtldmVudERhdGEocHQsIHRyYWNlMildLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBoYXNIb3ZlckV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVNb3VzZU91dChldnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGhhc0hvdmVyRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2dC5vcmlnaW5hbEV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfdW5ob3ZlcicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHM6IFtldmVudERhdGEocHQsIHRyYWNlMildLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50OiBkMy5ldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNIb3ZlckV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZihoYXNIb3ZlckxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBGeC5sb25lVW5ob3ZlcihmdWxsTGF5b3V0Mi5faG92ZXJsYXllci5ub2RlKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzSG92ZXJMYWJlbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlQ2xpY2soKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAgICAgICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgcGllIHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgICAgICAgICAgICAgIC8vIG1hcGJveCBldmVudCBiaW5kaW5nLiBPciBwZXJoYXBzIGJldHRlciwgbWFrZSBhIHNpbXBsZSB3cmFwcGVyIHdpdGggdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgICAgICAgICAgICAgLy8gbWFwYm94IHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGdkLl9kcmFnZ2luZyB8fCBmdWxsTGF5b3V0Mi5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICAgICAgZ2QuX2hvdmVyZGF0YSA9IFtldmVudERhdGEocHQsIHRyYWNlMildO1xuICAgICAgICAgICAgICAgICAgICBGeC5jbGljayhnZCwgZDMuZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNsaWNlUGF0aC5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzdXJmYWNlJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKHsncG9pbnRlci1ldmVudHMnOiAnYWxsJ30pO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUb3Auc2VsZWN0KCdwYXRoLnRleHRsaW5lJykucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgICAgICBzbGljZVRvcFxuICAgICAgICAgICAgICAgICAgICAub24oJ21vdXNlb3ZlcicsIGhhbmRsZU1vdXNlT3ZlcilcbiAgICAgICAgICAgICAgICAgICAgLm9uKCdtb3VzZW91dCcsIGhhbmRsZU1vdXNlT3V0KVxuICAgICAgICAgICAgICAgICAgICAub24oJ2NsaWNrJywgaGFuZGxlQ2xpY2spO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2UucHVsbCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHVsbCA9ICtoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UucHVsbCwgcHQucHRzKSB8fCAwO1xuICAgICAgICAgICAgICAgICAgICBpZihwdWxsID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3ggKz0gcHVsbCAqIHB0LnB4bWlkWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY3kgKz0gcHVsbCAqIHB0LnB4bWlkWzFdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHQuY3hGaW5hbCA9IGN4O1xuICAgICAgICAgICAgICAgIHB0LmN5RmluYWwgPSBjeTtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGFyYyhzdGFydCwgZmluaXNoLCBjdywgc2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdhJyArIChzY2FsZSAqIGNkMC5yKSArICcsJyArIChzY2FsZSAqIGNkMC5yKSArICcgMCAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0LmxhcmdlQXJjICsgKGN3ID8gJyAxICcgOiAnIDAgJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgKHNjYWxlICogKGZpbmlzaFswXSAtIHN0YXJ0WzBdKSkgKyAnLCcgKyAoc2NhbGUgKiAoZmluaXNoWzFdIC0gc3RhcnRbMV0pKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaG9sZSA9IHRyYWNlLmhvbGU7XG4gICAgICAgICAgICAgICAgaWYocHQudiA9PT0gY2QwLnZUb3RhbCkgeyAvLyAxMDAlIGZhaWxzIGJjcyBhcmMgc3RhcnQgYW5kIGVuZCBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRlckNpcmNsZSA9ICdNJyArIChjeCArIHB0LnB4MFswXSkgKyAnLCcgKyAoY3kgKyBwdC5weDBbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weDAsIHB0LnB4bWlkLCB0cnVlLCAxKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmMocHQucHhtaWQsIHB0LnB4MCwgdHJ1ZSwgMSkgKyAnWic7XG4gICAgICAgICAgICAgICAgICAgIGlmKGhvbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWNlUGF0aC5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTScgKyAoY3ggKyBob2xlICogcHQucHgwWzBdKSArICcsJyArIChjeSArIGhvbGUgKiBwdC5weDBbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmMocHQucHgwLCBwdC5weG1pZCwgZmFsc2UsIGhvbGUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmMocHQucHhtaWQsIHB0LnB4MCwgZmFsc2UsIGhvbGUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnWicgKyBvdXRlckNpcmNsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBzbGljZVBhdGguYXR0cignZCcsIG91dGVyQ2lyY2xlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRlckFyYyA9IGFyYyhwdC5weDAsIHB0LnB4MSwgdHJ1ZSwgMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaG9sZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJpbSA9IDEgLSBob2xlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpY2VQYXRoLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdNJyArIChjeCArIGhvbGUgKiBwdC5weDFbMF0pICsgJywnICsgKGN5ICsgaG9sZSAqIHB0LnB4MVsxXSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weDEsIHB0LnB4MCwgZmFsc2UsIGhvbGUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbCcgKyAocmltICogcHQucHgwWzBdKSArICcsJyArIChyaW0gKiBwdC5weDBbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRlckFyYyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1onKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWNlUGF0aC5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTScgKyBjeCArICcsJyArIGN5ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbCcgKyBwdC5weDBbMF0gKyAnLCcgKyBwdC5weDBbMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGVyQXJjICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnWicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYWRkIHRleHRcbiAgICAgICAgICAgICAgICB2YXIgdGV4dFBvc2l0aW9uID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLnRleHRwb3NpdGlvbiwgcHQucHRzKTtcbiAgICAgICAgICAgICAgICB2YXIgc2xpY2VUZXh0R3JvdXAgPSBzbGljZVRvcC5zZWxlY3RBbGwoJ2cuc2xpY2V0ZXh0JylcbiAgICAgICAgICAgICAgICAgICAgLmRhdGEocHQudGV4dCAmJiAodGV4dFBvc2l0aW9uICE9PSAnbm9uZScpID8gWzBdIDogW10pO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc2xpY2V0ZXh0JywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNsaWNlVGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoZDMuc2VsZWN0KHRoaXMpLCAndGV4dCcsICcnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9oaWJpdCB0ZXggaW50ZXJwcmV0YXRpb24gdW50aWwgd2UgY2FuIGhhbmRsZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGV4IGFuZCByZWd1bGFyIHRleHQgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHMuYXR0cignZGF0YS1ub3RleCcsIDEpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBzbGljZVRleHQudGV4dChwdC50ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdzbGljZXRleHQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGV0ZXJtaW5lT3V0c2lkZVRleHRGb250KHRyYWNlLCBwdCwgZ2QuX2Z1bGxMYXlvdXQuZm9udCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmVJbnNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGdkLl9mdWxsTGF5b3V0LmZvbnQpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHBvc2l0aW9uIHRoZSB0ZXh0IHJlbGF0aXZlIHRvIHRoZSBzbGljZVxuICAgICAgICAgICAgICAgICAgICB2YXIgdGV4dEJCID0gRHJhd2luZy5iQm94KHNsaWNlVGV4dC5ub2RlKCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJhbnNmb3JtO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm1PdXRzaWRlVGV4dCh0ZXh0QkIsIHB0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybUluc2lkZVRleHQodGV4dEJCLCBwdCwgY2QwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ2F1dG8nICYmIHRyYW5zZm9ybS5zY2FsZSA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGljZVRleHQuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLm91dHNpZGV0ZXh0Zm9udCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhY2Uub3V0c2lkZXRleHRmb250LmZhbWlseSAhPT0gdHJhY2UuaW5zaWRldGV4dGZvbnQuZmFtaWx5IHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZS5vdXRzaWRldGV4dGZvbnQuc2l6ZSAhPT0gdHJhY2UuaW5zaWRldGV4dGZvbnQuc2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0QkIgPSBEcmF3aW5nLmJCb3goc2xpY2VUZXh0Lm5vZGUoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybU91dHNpZGVUZXh0KHRleHRCQiwgcHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zbGF0ZVggPSBjeCArIHB0LnB4bWlkWzBdICogdHJhbnNmb3JtLnJDZW50ZXIgKyAodHJhbnNmb3JtLnggfHwgMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2xhdGVZID0gY3kgKyBwdC5weG1pZFsxXSAqIHRyYW5zZm9ybS5yQ2VudGVyICsgKHRyYW5zZm9ybS55IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHNhdmUgc29tZSBzdHVmZiB0byB1c2UgbGF0ZXIgZW5zdXJlIG5vIGxhYmVscyBvdmVybGFwXG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYW5zZm9ybS5vdXRzaWRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdC55TGFiZWxNaW4gPSB0cmFuc2xhdGVZIC0gdGV4dEJCLmhlaWdodCAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdC55TGFiZWxNaWQgPSB0cmFuc2xhdGVZO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQueUxhYmVsTWF4ID0gdHJhbnNsYXRlWSArIHRleHRCQi5oZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQubGFiZWxFeHRyYVggPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQubGFiZWxFeHRyYVkgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzT3V0c2lkZVRleHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2VUZXh0LmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB0cmFuc2xhdGVYICsgJywnICsgdHJhbnNsYXRlWSArICcpJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAodHJhbnNmb3JtLnNjYWxlIDwgMSA/ICgnc2NhbGUoJyArIHRyYW5zZm9ybS5zY2FsZSArICcpJykgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgKHRyYW5zZm9ybS5yb3RhdGUgPyAoJ3JvdGF0ZSgnICsgdHJhbnNmb3JtLnJvdGF0ZSArICcpJykgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoLSh0ZXh0QkIubGVmdCArIHRleHRCQi5yaWdodCkgLyAyKSArICcsJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKC0odGV4dEJCLnRvcCArIHRleHRCQi5ib3R0b20pIC8gMikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJyknKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBhZGQgdGhlIHRpdGxlXG4gICAgICAgICAgICB2YXIgdGl0bGVUZXh0R3JvdXAgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLnRpdGxldGV4dCcpXG4gICAgICAgICAgICAgICAgLmRhdGEodHJhY2UudGl0bGUgPyBbMF0gOiBbXSk7XG5cbiAgICAgICAgICAgIHRpdGxlVGV4dEdyb3VwLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgndGl0bGV0ZXh0JywgdHJ1ZSk7XG4gICAgICAgICAgICB0aXRsZVRleHRHcm91cC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIHRpdGxlVGV4dEdyb3VwLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRpdGxlVGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoZDMuc2VsZWN0KHRoaXMpLCAndGV4dCcsICcnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiBhcyBhYm92ZVxuICAgICAgICAgICAgICAgICAgICBzLmF0dHIoJ2RhdGEtbm90ZXgnLCAxKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRpdGxlVGV4dC50ZXh0KHRyYWNlLnRpdGxlKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAndGl0bGV0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiAnbWlkZGxlJyxcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLnRpdGxlZm9udClcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgdHJhbnNmb3JtO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2UudGl0bGVwb3NpdGlvbiA9PT0gJ21pZGRsZSBjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHBvc2l0aW9uVGl0bGVJbnNpZGUoY2QwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBwb3NpdGlvblRpdGxlT3V0c2lkZShjZDAsIGZ1bGxMYXlvdXQuX3NpemUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRpdGxlVGV4dC5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB0cmFuc2Zvcm0ueCArICcsJyArIHRyYW5zZm9ybS55ICsgJyknICtcbiAgICAgICAgICAgICAgICAgICAgKHRyYW5zZm9ybS5zY2FsZSA8IDEgPyAoJ3NjYWxlKCcgKyB0cmFuc2Zvcm0uc2NhbGUgKyAnKScpIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgdHJhbnNmb3JtLnR4ICsgJywnICsgdHJhbnNmb3JtLnR5ICsgJyknKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBub3cgbWFrZSBzdXJlIG5vIGxhYmVscyBvdmVybGFwIChhdCBsZWFzdCB3aXRoaW4gb25lIHBpZSlcbiAgICAgICAgICAgIGlmKGhhc091dHNpZGVUZXh0KSBzY29vdExhYmVscyhxdWFkcmFudHMsIHRyYWNlKTtcbiAgICAgICAgICAgIHNsaWNlcy5lYWNoKGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgICAgICAgICAgaWYocHQubGFiZWxFeHRyYVggfHwgcHQubGFiZWxFeHRyYVkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZmlyc3QgbW92ZSB0aGUgdGV4dCB0byBpdHMgbmV3IGxvY2F0aW9uXG4gICAgICAgICAgICAgICAgICAgIHZhciBzbGljZVRvcCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNsaWNlVGV4dCA9IHNsaWNlVG9wLnNlbGVjdCgnZy5zbGljZXRleHQgdGV4dCcpO1xuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlVGV4dC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBwdC5sYWJlbEV4dHJhWCArICcsJyArIHB0LmxhYmVsRXh0cmFZICsgJyknICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWNlVGV4dC5hdHRyKCd0cmFuc2Zvcm0nKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlbiBhZGQgYSBsaW5lIHRvIHRoZSBuZXcgbG9jYXRpb25cbiAgICAgICAgICAgICAgICAgICAgdmFyIGxpbmVTdGFydFggPSBwdC5jeEZpbmFsICsgcHQucHhtaWRbMF07XG4gICAgICAgICAgICAgICAgICAgIHZhciBsaW5lU3RhcnRZID0gcHQuY3lGaW5hbCArIHB0LnB4bWlkWzFdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGV4dExpbmVQYXRoID0gJ00nICsgbGluZVN0YXJ0WCArICcsJyArIGxpbmVTdGFydFk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaW5hbFggPSAocHQueUxhYmVsTWF4IC0gcHQueUxhYmVsTWluKSAqIChwdC5weG1pZFswXSA8IDAgPyAtMSA6IDEpIC8gNDtcblxuICAgICAgICAgICAgICAgICAgICBpZihwdC5sYWJlbEV4dHJhWCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHlGcm9tWCA9IHB0LmxhYmVsRXh0cmFYICogcHQucHhtaWRbMV0gLyBwdC5weG1pZFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB5TmV0ID0gcHQueUxhYmVsTWlkICsgcHQubGFiZWxFeHRyYVkgLSAocHQuY3lGaW5hbCArIHB0LnB4bWlkWzFdKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoeUZyb21YKSA+IE1hdGguYWJzKHlOZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dExpbmVQYXRoICs9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdsJyArICh5TmV0ICogcHQucHhtaWRbMF0gLyBwdC5weG1pZFsxXSkgKyAnLCcgKyB5TmV0ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0gnICsgKGxpbmVTdGFydFggKyBwdC5sYWJlbEV4dHJhWCArIGZpbmFsWCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRMaW5lUGF0aCArPSAnbCcgKyBwdC5sYWJlbEV4dHJhWCArICcsJyArIHlGcm9tWCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd2JyArICh5TmV0IC0geUZyb21YKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdoJyArIGZpbmFsWDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRMaW5lUGF0aCArPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdWJyArIChwdC55TGFiZWxNaWQgKyBwdC5sYWJlbEV4dHJhWSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdoJyArIGZpbmFsWDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlVG9wLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgndGV4dGxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCB0cmFjZS5vdXRzaWRldGV4dGZvbnQuY29sb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IE1hdGgubWluKDIsIHRyYWNlLm91dHNpZGV0ZXh0Zm9udC5zaXplIC8gOCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZDogdGV4dExpbmVQYXRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw6ICdub25lJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gVGhpcyBpcyBmb3IgYSBidWcgaW4gQ2hyb21lIChhcyBvZiAyMDE1LTA3LTIyLCBhbmQgZG9lcyBub3QgYWZmZWN0IEZGKVxuICAgIC8vIGlmIGluc2lkZXRleHRmb250IGFuZCBvdXRzaWRldGV4dGZvbnQgYXJlIGRpZmZlcmVudCBzaXplcywgc29tZXRpbWVzIHRoZSBzaXplXG4gICAgLy8gb2YgYW4gXCJlbVwiIGdldHMgdGFrZW4gZnJvbSB0aGUgd3JvbmcgZWxlbWVudCBhdCBmaXJzdCBzbyBsaW5lcyBhcmVcbiAgICAvLyBzcGFjZWQgd3JvbmcuIFlvdSBqdXN0IGhhdmUgdG8gdGVsbCBpdCB0byB0cnkgYWdhaW4gbGF0ZXIgYW5kIGl0IGdldHMgZml4ZWQuXG4gICAgLy8gSSBoYXZlIG5vIGlkZWEgd2h5IHdlIGhhdmVuJ3Qgc2VlbiB0aGlzIGluIG90aGVyIGNvbnRleHRzLiBBbHNvLCBzb21ldGltZXNcbiAgICAvLyBpdCBnZXRzIHRoZSBpbml0aWFsIGRyYXcgY29ycmVjdCBidXQgb24gcmVkcmF3IGl0IGdldHMgY29uZnVzZWQuXG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgcGllR3JvdXBzLnNlbGVjdEFsbCgndHNwYW4nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHMgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBpZihzLmF0dHIoJ2R5JykpIHMuYXR0cignZHknLCBzLmF0dHIoJ2R5JykpO1xuICAgICAgICB9KTtcbiAgICB9LCAwKTtcbn07XG5cbmZ1bmN0aW9uIGRldGVybWluZU91dHNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGxheW91dEZvbnQpIHtcbiAgICB2YXIgY29sb3IgPSBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2Uub3V0c2lkZXRleHRmb250LmNvbG9yLCBwdC5wdHMpIHx8XG4gICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UudGV4dGZvbnQuY29sb3IsIHB0LnB0cykgfHxcbiAgICAgIGxheW91dEZvbnQuY29sb3I7XG5cbiAgICB2YXIgZmFtaWx5ID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLm91dHNpZGV0ZXh0Zm9udC5mYW1pbHksIHB0LnB0cykgfHxcbiAgICAgIGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS50ZXh0Zm9udC5mYW1pbHksIHB0LnB0cykgfHxcbiAgICAgIGxheW91dEZvbnQuZmFtaWx5O1xuXG4gICAgdmFyIHNpemUgPSBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2Uub3V0c2lkZXRleHRmb250LnNpemUsIHB0LnB0cykgfHxcbiAgICAgIGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS50ZXh0Zm9udC5zaXplLCBwdC5wdHMpIHx8XG4gICAgICBsYXlvdXRGb250LnNpemU7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgIGZhbWlseTogZmFtaWx5LFxuICAgICAgICBzaXplOiBzaXplXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZGV0ZXJtaW5lSW5zaWRlVGV4dEZvbnQodHJhY2UsIHB0LCBsYXlvdXRGb250KSB7XG4gICAgdmFyIGN1c3RvbUNvbG9yID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLmluc2lkZXRleHRmb250LmNvbG9yLCBwdC5wdHMpO1xuICAgIGlmKCFjdXN0b21Db2xvciAmJiB0cmFjZS5faW5wdXQudGV4dGZvbnQpIHtcblxuICAgICAgICAvLyBXaHkgbm90IHNpbXBseSB1c2luZyB0cmFjZS50ZXh0Zm9udD8gQmVjYXVzZSBpZiBub3Qgc2V0LCBpdFxuICAgICAgICAvLyBkZWZhdWx0cyB0byBsYXlvdXQuZm9udCB3aGljaCBoYXMgYSBkZWZhdWx0IGNvbG9yLiBCdXQgaWZcbiAgICAgICAgLy8gdGV4dGZvbnQuY29sb3IgYW5kIGluc2lkZXRleHRmb250LmNvbG9yIGRvbid0IHN1cHBseSBhIHZhbHVlLFxuICAgICAgICAvLyBhIGNvbnRyYXN0aW5nIGNvbG9yIHNoYWxsIGJlIHVzZWQuXG4gICAgICAgIGN1c3RvbUNvbG9yID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLl9pbnB1dC50ZXh0Zm9udC5jb2xvciwgcHQucHRzKTtcbiAgICB9XG5cbiAgICB2YXIgZmFtaWx5ID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLmluc2lkZXRleHRmb250LmZhbWlseSwgcHQucHRzKSB8fFxuICAgICAgaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLnRleHRmb250LmZhbWlseSwgcHQucHRzKSB8fFxuICAgICAgbGF5b3V0Rm9udC5mYW1pbHk7XG5cbiAgICB2YXIgc2l6ZSA9IGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5pbnNpZGV0ZXh0Zm9udC5zaXplLCBwdC5wdHMpIHx8XG4gICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UudGV4dGZvbnQuc2l6ZSwgcHQucHRzKSB8fFxuICAgICAgbGF5b3V0Rm9udC5zaXplO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sb3I6IGN1c3RvbUNvbG9yIHx8IENvbG9yLmNvbnRyYXN0KHB0LmNvbG9yKSxcbiAgICAgICAgZmFtaWx5OiBmYW1pbHksXG4gICAgICAgIHNpemU6IHNpemVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBwcmVyZW5kZXJUaXRsZXMoY2RwaWUsIGdkKSB7XG4gICAgdmFyIGNkMCwgdHJhY2U7XG4gICAgLy8gRGV0ZXJtaW5lIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSB0aXRsZSBmb3IgZWFjaCBwaWUuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNkcGllLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkMCA9IGNkcGllW2ldWzBdO1xuICAgICAgICB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBpZih0cmFjZS50aXRsZSkge1xuICAgICAgICAgICAgdmFyIGR1bW15VGl0bGUgPSBEcmF3aW5nLnRlc3Rlci5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgICAgICAuYXR0cignZGF0YS1ub3RleCcsIDEpXG4gICAgICAgICAgICAgIC50ZXh0KHRyYWNlLnRpdGxlKVxuICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLnRpdGxlZm9udClcbiAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgICAgICAgICAgdmFyIGJCb3ggPSBEcmF3aW5nLmJCb3goZHVtbXlUaXRsZS5ub2RlKCksIHRydWUpO1xuICAgICAgICAgICAgY2QwLnRpdGxlQm94ID0ge1xuICAgICAgICAgICAgICAgIHdpZHRoOiBiQm94LndpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogYkJveC5oZWlnaHQsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZHVtbXlUaXRsZS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gdHJhbnNmb3JtSW5zaWRlVGV4dCh0ZXh0QkIsIHB0LCBjZDApIHtcbiAgICB2YXIgdGV4dERpYW1ldGVyID0gTWF0aC5zcXJ0KHRleHRCQi53aWR0aCAqIHRleHRCQi53aWR0aCArIHRleHRCQi5oZWlnaHQgKiB0ZXh0QkIuaGVpZ2h0KTtcbiAgICB2YXIgdGV4dEFzcGVjdCA9IHRleHRCQi53aWR0aCAvIHRleHRCQi5oZWlnaHQ7XG4gICAgdmFyIGhhbGZBbmdsZSA9IE1hdGguUEkgKiBNYXRoLm1pbihwdC52IC8gY2QwLnZUb3RhbCwgMC41KTtcbiAgICB2YXIgcmluZyA9IDEgLSBjZDAudHJhY2UuaG9sZTtcbiAgICB2YXIgckluc2NyaWJlZCA9IGdldEluc2NyaWJlZFJhZGl1c0ZyYWN0aW9uKHB0LCBjZDApLFxuXG4gICAgICAgIC8vIG1heCBzaXplIHRleHQgY2FuIGJlIGluc2VydGVkIGluc2lkZSB3aXRob3V0IHJvdGF0aW5nIGl0XG4gICAgICAgIC8vIHRoaXMgaW5zY3JpYmVzIHRoZSB0ZXh0IHJlY3RhbmdsZSBpbiBhIGNpcmNsZSwgd2hpY2ggaXMgdGhlbiBpbnNjcmliZWRcbiAgICAgICAgLy8gaW4gdGhlIHNsaWNlLCBzbyBpdCB3aWxsIGJlIGFuIHVuZGVyZXN0aW1hdGUsIHdoaWNoIHNvbWUgZGF5IHdlIG1heSB3YW50XG4gICAgICAgIC8vIHRvIGltcHJvdmUgc28gdGhpcyBjYXNlIGNhbiBnZXQgbW9yZSB1c2VcbiAgICAgICAgdHJhbnNmb3JtID0ge1xuICAgICAgICAgICAgc2NhbGU6IHJJbnNjcmliZWQgKiBjZDAuciAqIDIgLyB0ZXh0RGlhbWV0ZXIsXG5cbiAgICAgICAgICAgIC8vIGFuZCB0aGUgY2VudGVyIHBvc2l0aW9uIGFuZCByb3RhdGlvbiBpbiB0aGlzIGNhc2VcbiAgICAgICAgICAgIHJDZW50ZXI6IDEgLSBySW5zY3JpYmVkLFxuICAgICAgICAgICAgcm90YXRlOiAwXG4gICAgICAgIH07XG5cbiAgICBpZih0cmFuc2Zvcm0uc2NhbGUgPj0gMSkgcmV0dXJuIHRyYW5zZm9ybTtcblxuICAgICAgICAvLyBtYXggc2l6ZSBpZiB0ZXh0IGlzIHJvdGF0ZWQgcmFkaWFsbHlcbiAgICB2YXIgUXIgPSB0ZXh0QXNwZWN0ICsgMSAvICgyICogTWF0aC50YW4oaGFsZkFuZ2xlKSk7XG4gICAgdmFyIG1heEhhbGZIZWlnaHRSb3RSYWRpYWwgPSBjZDAuciAqIE1hdGgubWluKFxuICAgICAgICAxIC8gKE1hdGguc3FydChRciAqIFFyICsgMC41KSArIFFyKSxcbiAgICAgICAgcmluZyAvIChNYXRoLnNxcnQodGV4dEFzcGVjdCAqIHRleHRBc3BlY3QgKyByaW5nIC8gMikgKyB0ZXh0QXNwZWN0KVxuICAgICk7XG4gICAgdmFyIHJhZGlhbFRyYW5zZm9ybSA9IHtcbiAgICAgICAgc2NhbGU6IG1heEhhbGZIZWlnaHRSb3RSYWRpYWwgKiAyIC8gdGV4dEJCLmhlaWdodCxcbiAgICAgICAgckNlbnRlcjogTWF0aC5jb3MobWF4SGFsZkhlaWdodFJvdFJhZGlhbCAvIGNkMC5yKSAtXG4gICAgICAgICAgICBtYXhIYWxmSGVpZ2h0Um90UmFkaWFsICogdGV4dEFzcGVjdCAvIGNkMC5yLFxuICAgICAgICByb3RhdGU6ICgxODAgLyBNYXRoLlBJICogcHQubWlkYW5nbGUgKyA3MjApICUgMTgwIC0gOTBcbiAgICB9O1xuXG4gICAgICAgIC8vIG1heCBzaXplIGlmIHRleHQgaXMgcm90YXRlZCB0YW5nZW50aWFsbHlcbiAgICB2YXIgYXNwZWN0SW52ID0gMSAvIHRleHRBc3BlY3Q7XG4gICAgdmFyIFF0ID0gYXNwZWN0SW52ICsgMSAvICgyICogTWF0aC50YW4oaGFsZkFuZ2xlKSk7XG4gICAgdmFyIG1heEhhbGZXaWR0aFRhbmdlbnRpYWwgPSBjZDAuciAqIE1hdGgubWluKFxuICAgICAgICAxIC8gKE1hdGguc3FydChRdCAqIFF0ICsgMC41KSArIFF0KSxcbiAgICAgICAgcmluZyAvIChNYXRoLnNxcnQoYXNwZWN0SW52ICogYXNwZWN0SW52ICsgcmluZyAvIDIpICsgYXNwZWN0SW52KVxuICAgICk7XG4gICAgdmFyIHRhbmdlbnRpYWxUcmFuc2Zvcm0gPSB7XG4gICAgICAgIHNjYWxlOiBtYXhIYWxmV2lkdGhUYW5nZW50aWFsICogMiAvIHRleHRCQi53aWR0aCxcbiAgICAgICAgckNlbnRlcjogTWF0aC5jb3MobWF4SGFsZldpZHRoVGFuZ2VudGlhbCAvIGNkMC5yKSAtXG4gICAgICAgICAgICBtYXhIYWxmV2lkdGhUYW5nZW50aWFsIC8gdGV4dEFzcGVjdCAvIGNkMC5yLFxuICAgICAgICByb3RhdGU6ICgxODAgLyBNYXRoLlBJICogcHQubWlkYW5nbGUgKyA4MTApICUgMTgwIC0gOTBcbiAgICB9O1xuICAgIC8vIGlmIHdlIG5lZWQgYSByb3RhdGVkIHRyYW5zZm9ybSwgcGljayB0aGUgYmlnZ2VzdCBvbmVcbiAgICAvLyBldmVuIGlmIGJvdGggYXJlIGJpZ2dlciB0aGFuIDFcbiAgICB2YXIgcm90YXRlZFRyYW5zZm9ybSA9IHRhbmdlbnRpYWxUcmFuc2Zvcm0uc2NhbGUgPiByYWRpYWxUcmFuc2Zvcm0uc2NhbGUgP1xuICAgICAgICAgICAgdGFuZ2VudGlhbFRyYW5zZm9ybSA6IHJhZGlhbFRyYW5zZm9ybTtcblxuICAgIGlmKHRyYW5zZm9ybS5zY2FsZSA8IDEgJiYgcm90YXRlZFRyYW5zZm9ybS5zY2FsZSA+IHRyYW5zZm9ybS5zY2FsZSkgcmV0dXJuIHJvdGF0ZWRUcmFuc2Zvcm07XG4gICAgcmV0dXJuIHRyYW5zZm9ybTtcbn1cblxuZnVuY3Rpb24gZ2V0SW5zY3JpYmVkUmFkaXVzRnJhY3Rpb24ocHQsIGNkMCkge1xuICAgIGlmKHB0LnYgPT09IGNkMC52VG90YWwgJiYgIWNkMC50cmFjZS5ob2xlKSByZXR1cm4gMTsvLyBzcGVjaWFsIGNhc2Ugb2YgMTAwJSB3aXRoIG5vIGhvbGVcblxuICAgIHZhciBoYWxmQW5nbGUgPSBNYXRoLlBJICogTWF0aC5taW4ocHQudiAvIGNkMC52VG90YWwsIDAuNSk7XG4gICAgcmV0dXJuIE1hdGgubWluKDEgLyAoMSArIDEgLyBNYXRoLnNpbihoYWxmQW5nbGUpKSwgKDEgLSBjZDAudHJhY2UuaG9sZSkgLyAyKTtcbn1cblxuZnVuY3Rpb24gdHJhbnNmb3JtT3V0c2lkZVRleHQodGV4dEJCLCBwdCkge1xuICAgIHZhciB4ID0gcHQucHhtaWRbMF07XG4gICAgdmFyIHkgPSBwdC5weG1pZFsxXTtcbiAgICB2YXIgZHggPSB0ZXh0QkIud2lkdGggLyAyO1xuICAgIHZhciBkeSA9IHRleHRCQi5oZWlnaHQgLyAyO1xuXG4gICAgaWYoeCA8IDApIGR4ICo9IC0xO1xuICAgIGlmKHkgPCAwKSBkeSAqPSAtMTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNjYWxlOiAxLFxuICAgICAgICByQ2VudGVyOiAxLFxuICAgICAgICByb3RhdGU6IDAsXG4gICAgICAgIHg6IGR4ICsgTWF0aC5hYnMoZHkpICogKGR4ID4gMCA/IDEgOiAtMSkgLyAyLFxuICAgICAgICB5OiBkeSAvICgxICsgeCAqIHggLyAoeSAqIHkpKSxcbiAgICAgICAgb3V0c2lkZTogdHJ1ZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHBvc2l0aW9uVGl0bGVJbnNpZGUoY2QwKSB7XG4gICAgdmFyIHRleHREaWFtZXRlciA9XG4gICAgICAgIE1hdGguc3FydChjZDAudGl0bGVCb3gud2lkdGggKiBjZDAudGl0bGVCb3gud2lkdGggKyBjZDAudGl0bGVCb3guaGVpZ2h0ICogY2QwLnRpdGxlQm94LmhlaWdodCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogY2QwLmN4LFxuICAgICAgICB5OiBjZDAuY3ksXG4gICAgICAgIHNjYWxlOiBjZDAudHJhY2UuaG9sZSAqIGNkMC5yICogMiAvIHRleHREaWFtZXRlcixcbiAgICAgICAgdHg6IDAsXG4gICAgICAgIHR5OiAtIGNkMC50aXRsZUJveC5oZWlnaHQgLyAyICsgY2QwLnRyYWNlLnRpdGxlZm9udC5zaXplXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcG9zaXRpb25UaXRsZU91dHNpZGUoY2QwLCBwbG90U2l6ZSkge1xuICAgIHZhciBzY2FsZVggPSAxLCBzY2FsZVkgPSAxLCBtYXhXaWR0aCwgbWF4UHVsbDtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgLy8gcG9zaXRpb24gb2YgdGhlIGJhc2VsaW5lIHBvaW50IG9mIHRoZSB0ZXh0IGJveCBpbiB0aGUgcGxvdCwgYmVmb3JlIHNjYWxpbmcuXG4gICAgLy8gd2UgYW5jaG9yZWQgdGhlIHRleHQgaW4gdGhlIG1pZGRsZSwgc28gdGhlIGJhc2VsaW5lIGlzIG9uIHRoZSBib3R0b20gbWlkZGxlXG4gICAgLy8gb2YgdGhlIGZpcnN0IGxpbmUgb2YgdGV4dC5cbiAgICB2YXIgdG9wTWlkZGxlID0ge1xuICAgICAgICB4OiBjZDAuY3gsXG4gICAgICAgIHk6IGNkMC5jeVxuICAgIH07XG4gICAgLy8gcmVsYXRpdmUgdHJhbnNsYXRpb24gb2YgdGhlIHRleHQgYm94IGFmdGVyIHNjYWxpbmdcbiAgICB2YXIgdHJhbnNsYXRlID0ge1xuICAgICAgICB0eDogMCxcbiAgICAgICAgdHk6IDBcbiAgICB9O1xuXG4gICAgLy8gd2UgcmVhc29uIGJlbG93IGFzIGlmIHRoZSBiYXNlbGluZSBpcyB0aGUgdG9wIG1pZGRsZSBwb2ludCBvZiB0aGUgdGV4dCBib3guXG4gICAgLy8gc28gd2UgbXVzdCBhZGQgdGhlIGZvbnQgc2l6ZSB0byBhcHByb3hpbWF0ZSB0aGUgeS1jb29yZC4gb2YgdGhlIHRvcC5cbiAgICAvLyBub3RlIHRoYXQgdGhpcyBjb3JyZWN0aW9uIG11c3QgaGFwcGVuIGFmdGVyIHNjYWxpbmcuXG4gICAgdHJhbnNsYXRlLnR5ICs9IHRyYWNlLnRpdGxlZm9udC5zaXplO1xuICAgIG1heFB1bGwgPSBnZXRNYXhQdWxsKHRyYWNlKTtcblxuICAgIGlmKHRyYWNlLnRpdGxlcG9zaXRpb24uaW5kZXhPZigndG9wJykgIT09IC0xKSB7XG4gICAgICAgIHRvcE1pZGRsZS55IC09ICgxICsgbWF4UHVsbCkgKiBjZDAucjtcbiAgICAgICAgdHJhbnNsYXRlLnR5IC09IGNkMC50aXRsZUJveC5oZWlnaHQ7XG4gICAgfVxuICAgIGVsc2UgaWYodHJhY2UudGl0bGVwb3NpdGlvbi5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEpIHtcbiAgICAgICAgdG9wTWlkZGxlLnkgKz0gKDEgKyBtYXhQdWxsKSAqIGNkMC5yO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLnRpdGxlcG9zaXRpb24uaW5kZXhPZignbGVmdCcpICE9PSAtMSkge1xuICAgICAgICAvLyB3ZSBzdGFydCB0aGUgdGV4dCBhdCB0aGUgbGVmdCBlZGdlIG9mIHRoZSBwaWVcbiAgICAgICAgbWF4V2lkdGggPSBwbG90U2l6ZS53ICogKHRyYWNlLmRvbWFpbi54WzFdIC0gdHJhY2UuZG9tYWluLnhbMF0pIC8gMiArIGNkMC5yO1xuICAgICAgICB0b3BNaWRkbGUueCAtPSAoMSArIG1heFB1bGwpICogY2QwLnI7XG4gICAgICAgIHRyYW5zbGF0ZS50eCArPSBjZDAudGl0bGVCb3gud2lkdGggLyAyO1xuICAgIH0gZWxzZSBpZih0cmFjZS50aXRsZXBvc2l0aW9uLmluZGV4T2YoJ2NlbnRlcicpICE9PSAtMSkge1xuICAgICAgICBtYXhXaWR0aCA9IHBsb3RTaXplLncgKiAodHJhY2UuZG9tYWluLnhbMV0gLSB0cmFjZS5kb21haW4ueFswXSk7XG4gICAgfSBlbHNlIGlmKHRyYWNlLnRpdGxlcG9zaXRpb24uaW5kZXhPZigncmlnaHQnKSAhPT0gLTEpIHtcbiAgICAgICAgbWF4V2lkdGggPSBwbG90U2l6ZS53ICogKHRyYWNlLmRvbWFpbi54WzFdIC0gdHJhY2UuZG9tYWluLnhbMF0pIC8gMiArIGNkMC5yO1xuICAgICAgICB0b3BNaWRkbGUueCArPSAoMSArIG1heFB1bGwpICogY2QwLnI7XG4gICAgICAgIHRyYW5zbGF0ZS50eCAtPSBjZDAudGl0bGVCb3gud2lkdGggLyAyO1xuICAgIH1cbiAgICBzY2FsZVggPSBtYXhXaWR0aCAvIGNkMC50aXRsZUJveC53aWR0aDtcbiAgICBzY2FsZVkgPSBnZXRUaXRsZVNwYWNlKGNkMCwgcGxvdFNpemUpIC8gY2QwLnRpdGxlQm94LmhlaWdodDtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiB0b3BNaWRkbGUueCxcbiAgICAgICAgeTogdG9wTWlkZGxlLnksXG4gICAgICAgIHNjYWxlOiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSksXG4gICAgICAgIHR4OiB0cmFuc2xhdGUudHgsXG4gICAgICAgIHR5OiB0cmFuc2xhdGUudHlcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRUaXRsZVNwYWNlKGNkMCwgcGxvdFNpemUpIHtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgdmFyIHBpZUJveEhlaWdodCA9IHBsb3RTaXplLmggKiAodHJhY2UuZG9tYWluLnlbMV0gLSB0cmFjZS5kb21haW4ueVswXSk7XG4gICAgLy8gdXNlIGF0IG1vc3QgaGFsZiBvZiB0aGUgcGxvdCBmb3IgdGhlIHRpdGxlXG4gICAgcmV0dXJuIE1hdGgubWluKGNkMC50aXRsZUJveC5oZWlnaHQsIHBpZUJveEhlaWdodCAvIDIpO1xufVxuXG5mdW5jdGlvbiBnZXRNYXhQdWxsKHRyYWNlKSB7XG4gICAgdmFyIG1heFB1bGwgPSB0cmFjZS5wdWxsLCBqO1xuICAgIGlmKEFycmF5LmlzQXJyYXkobWF4UHVsbCkpIHtcbiAgICAgICAgbWF4UHVsbCA9IDA7XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHRyYWNlLnB1bGwubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLnB1bGxbal0gPiBtYXhQdWxsKSBtYXhQdWxsID0gdHJhY2UucHVsbFtqXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbWF4UHVsbDtcbn1cblxuZnVuY3Rpb24gc2Nvb3RMYWJlbHMocXVhZHJhbnRzLCB0cmFjZSkge1xuICAgIHZhciB4SGFsZiwgeUhhbGYsIGVxdWF0b3JGaXJzdCwgZmFydGhlc3RYLCBmYXJ0aGVzdFksXG4gICAgICAgIHhEaWZmU2lnbiwgeURpZmZTaWduLCB0aGlzUXVhZCwgb3Bwb3NpdGVRdWFkLFxuICAgICAgICB3aG9sZVNpZGUsIGksIHRoaXNRdWFkT3V0c2lkZSwgZmlyc3RPcHBvc2l0ZU91dHNpZGVQdDtcblxuICAgIGZ1bmN0aW9uIHRvcEZpcnN0KGEsIGIpIHsgcmV0dXJuIGEucHhtaWRbMV0gLSBiLnB4bWlkWzFdOyB9XG4gICAgZnVuY3Rpb24gYm90dG9tRmlyc3QoYSwgYikgeyByZXR1cm4gYi5weG1pZFsxXSAtIGEucHhtaWRbMV07IH1cblxuICAgIGZ1bmN0aW9uIHNjb290T25lTGFiZWwodGhpc1B0LCBwcmV2UHQpIHtcbiAgICAgICAgaWYoIXByZXZQdCkgcHJldlB0ID0ge307XG5cbiAgICAgICAgdmFyIHByZXZPdXRlclkgPSBwcmV2UHQubGFiZWxFeHRyYVkgKyAoeUhhbGYgPyBwcmV2UHQueUxhYmVsTWF4IDogcHJldlB0LnlMYWJlbE1pbik7XG4gICAgICAgIHZhciB0aGlzSW5uZXJZID0geUhhbGYgPyB0aGlzUHQueUxhYmVsTWluIDogdGhpc1B0LnlMYWJlbE1heDtcbiAgICAgICAgdmFyIHRoaXNPdXRlclkgPSB5SGFsZiA/IHRoaXNQdC55TGFiZWxNYXggOiB0aGlzUHQueUxhYmVsTWluO1xuICAgICAgICB2YXIgdGhpc1NsaWNlT3V0ZXJZID0gdGhpc1B0LmN5RmluYWwgKyBmYXJ0aGVzdFkodGhpc1B0LnB4MFsxXSwgdGhpc1B0LnB4MVsxXSk7XG4gICAgICAgIHZhciBuZXdFeHRyYVkgPSBwcmV2T3V0ZXJZIC0gdGhpc0lubmVyWTtcblxuICAgICAgICB2YXIgeEJ1ZmZlciwgaSwgb3RoZXJQdCwgb3RoZXJPdXRlclksIG90aGVyT3V0ZXJYLCBuZXdFeHRyYVg7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoaXMgbGFiZWwgZG9lc24ndCBvdmVybGFwIG90aGVyIGxhYmVsc1xuICAgICAgICAvLyB0aGlzICpvbmx5KiBoYXMgdXMgbW92ZSB0aGVzZSBsYWJlbHMgdmVydGljYWxseVxuICAgICAgICBpZihuZXdFeHRyYVkgKiB5RGlmZlNpZ24gPiAwKSB0aGlzUHQubGFiZWxFeHRyYVkgPSBuZXdFeHRyYVk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoaXMgbGFiZWwgZG9lc24ndCBvdmVybGFwIGFueSBzbGljZXNcbiAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodHJhY2UucHVsbCkpIHJldHVybjsgLy8gdGhpcyBjYW4gb25seSBoYXBwZW4gd2l0aCBhcnJheSBwdWxsc1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHdob2xlU2lkZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3RoZXJQdCA9IHdob2xlU2lkZVtpXTtcblxuICAgICAgICAgICAgLy8gb3ZlcmxhcCBjYW4gb25seSBoYXBwZW4gaWYgdGhlIG90aGVyIHBvaW50IGlzIHB1bGxlZCBtb3JlIHRoYW4gdGhpcyBvbmVcbiAgICAgICAgICAgIGlmKG90aGVyUHQgPT09IHRoaXNQdCB8fCAoXG4gICAgICAgICAgICAgICAgKGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5wdWxsLCB0aGlzUHQucHRzKSB8fCAwKSA+PVxuICAgICAgICAgICAgICAgIChoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UucHVsbCwgb3RoZXJQdC5wdHMpIHx8IDApKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCh0aGlzUHQucHhtaWRbMV0gLSBvdGhlclB0LnB4bWlkWzFdKSAqIHlEaWZmU2lnbiA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBjbG9zZXIgdG8gdGhlIGVxdWF0b3IgLSBieSBjb25zdHJ1Y3Rpb24gYWxsIG9mIHRoZXNlIGhhcHBlbiBmaXJzdFxuICAgICAgICAgICAgICAgIC8vIG1vdmUgdGhlIHRleHQgdmVydGljYWxseSB0byBnZXQgYXdheSBmcm9tIHRoZXNlIHNsaWNlc1xuICAgICAgICAgICAgICAgIG90aGVyT3V0ZXJZID0gb3RoZXJQdC5jeUZpbmFsICsgZmFydGhlc3RZKG90aGVyUHQucHgwWzFdLCBvdGhlclB0LnB4MVsxXSk7XG4gICAgICAgICAgICAgICAgbmV3RXh0cmFZID0gb3RoZXJPdXRlclkgLSB0aGlzSW5uZXJZIC0gdGhpc1B0LmxhYmVsRXh0cmFZO1xuXG4gICAgICAgICAgICAgICAgaWYobmV3RXh0cmFZICogeURpZmZTaWduID4gMCkgdGhpc1B0LmxhYmVsRXh0cmFZICs9IG5ld0V4dHJhWTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmKCh0aGlzT3V0ZXJZICsgdGhpc1B0LmxhYmVsRXh0cmFZIC0gdGhpc1NsaWNlT3V0ZXJZKSAqIHlEaWZmU2lnbiA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBmYXJ0aGVyIGZyb20gdGhlIGVxdWF0b3IgLSBoYXBwZW5zIGFmdGVyIHdlJ3ZlIGRvbmUgYWxsIHRoZVxuICAgICAgICAgICAgICAgIC8vIHZlcnRpY2FsIG1vdmluZyB3ZSdyZSBnb2luZyB0byBkb1xuICAgICAgICAgICAgICAgIC8vIG1vdmUgaG9yaXpvbnRhbGx5IHRvIGdldCBhd2F5IGZyb20gdGhlc2UgbW9yZSBwb2xhciBzbGljZXNcblxuICAgICAgICAgICAgICAgIC8vIGlmIHdlJ3JlIG1vdmluZyBob3J6LiBiYXNlZCBvbiBhIHNsaWNlIHRoYXQncyBzZXZlcmFsIHNsaWNlcyBhd2F5IGZyb20gdGhpcyBvbmVcbiAgICAgICAgICAgICAgICAvLyB0aGVuIHdlIG5lZWQgc29tZSBleHRyYSBzcGFjZSBmb3IgdGhlIGxpbmVzIHRvIGxhYmVscyBiZXR3ZWVuIHRoZW1cbiAgICAgICAgICAgICAgICB4QnVmZmVyID0gMyAqIHhEaWZmU2lnbiAqIE1hdGguYWJzKGkgLSB3aG9sZVNpZGUuaW5kZXhPZih0aGlzUHQpKTtcblxuICAgICAgICAgICAgICAgIG90aGVyT3V0ZXJYID0gb3RoZXJQdC5jeEZpbmFsICsgZmFydGhlc3RYKG90aGVyUHQucHgwWzBdLCBvdGhlclB0LnB4MVswXSk7XG4gICAgICAgICAgICAgICAgbmV3RXh0cmFYID0gb3RoZXJPdXRlclggKyB4QnVmZmVyIC0gKHRoaXNQdC5jeEZpbmFsICsgdGhpc1B0LnB4bWlkWzBdKSAtIHRoaXNQdC5sYWJlbEV4dHJhWDtcblxuICAgICAgICAgICAgICAgIGlmKG5ld0V4dHJhWCAqIHhEaWZmU2lnbiA+IDApIHRoaXNQdC5sYWJlbEV4dHJhWCArPSBuZXdFeHRyYVg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoeUhhbGYgPSAwOyB5SGFsZiA8IDI7IHlIYWxmKyspIHtcbiAgICAgICAgZXF1YXRvckZpcnN0ID0geUhhbGYgPyB0b3BGaXJzdCA6IGJvdHRvbUZpcnN0O1xuICAgICAgICBmYXJ0aGVzdFkgPSB5SGFsZiA/IE1hdGgubWF4IDogTWF0aC5taW47XG4gICAgICAgIHlEaWZmU2lnbiA9IHlIYWxmID8gMSA6IC0xO1xuXG4gICAgICAgIGZvcih4SGFsZiA9IDA7IHhIYWxmIDwgMjsgeEhhbGYrKykge1xuICAgICAgICAgICAgZmFydGhlc3RYID0geEhhbGYgPyBNYXRoLm1heCA6IE1hdGgubWluO1xuICAgICAgICAgICAgeERpZmZTaWduID0geEhhbGYgPyAxIDogLTE7XG5cbiAgICAgICAgICAgIC8vIGZpcnN0IHNvcnQgdGhlIGFycmF5XG4gICAgICAgICAgICAvLyBub3RlIHRoaXMgaXMgYSBjb3B5IG9mIGNkLCBzbyBjZCBpdHNlbGYgZG9lc24ndCBnZXQgc29ydGVkXG4gICAgICAgICAgICAvLyBidXQgd2UgY2FuIHN0aWxsIG1vZGlmeSBwb2ludHMgaW4gcGxhY2UuXG4gICAgICAgICAgICB0aGlzUXVhZCA9IHF1YWRyYW50c1t5SGFsZl1beEhhbGZdO1xuICAgICAgICAgICAgdGhpc1F1YWQuc29ydChlcXVhdG9yRmlyc3QpO1xuXG4gICAgICAgICAgICBvcHBvc2l0ZVF1YWQgPSBxdWFkcmFudHNbMSAtIHlIYWxmXVt4SGFsZl07XG4gICAgICAgICAgICB3aG9sZVNpZGUgPSBvcHBvc2l0ZVF1YWQuY29uY2F0KHRoaXNRdWFkKTtcblxuICAgICAgICAgICAgdGhpc1F1YWRPdXRzaWRlID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0aGlzUXVhZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKHRoaXNRdWFkW2ldLnlMYWJlbE1pZCAhPT0gdW5kZWZpbmVkKSB0aGlzUXVhZE91dHNpZGUucHVzaCh0aGlzUXVhZFtpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgeUhhbGYgJiYgaSA8IG9wcG9zaXRlUXVhZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKG9wcG9zaXRlUXVhZFtpXS55TGFiZWxNaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdE9wcG9zaXRlT3V0c2lkZVB0ID0gb3Bwb3NpdGVRdWFkW2ldO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGVhY2ggbmVlZHMgdG8gYXZvaWQgdGhlIHByZXZpb3VzXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0aGlzUXVhZE91dHNpZGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldlB0ID0gaSAmJiB0aGlzUXVhZE91dHNpZGVbaSAtIDFdO1xuICAgICAgICAgICAgICAgIC8vIGJvdHRvbSBoYWxmIG5lZWRzIHRvIGF2b2lkIHRoZSBmaXJzdCBsYWJlbCBvZiB0aGUgdG9wIGhhbGZcbiAgICAgICAgICAgICAgICAvLyB0b3AgaGFsZiB3ZSBzdGlsbCBuZWVkIHRvIGNhbGwgc2Nvb3RPbmVMYWJlbCBvbiB0aGUgZmlyc3Qgc2xpY2VcbiAgICAgICAgICAgICAgICAvLyBzbyB3ZSBjYW4gYXZvaWQgb3RoZXIgc2xpY2VzLCBidXQgd2UgZG9uJ3QgcGFzcyBhIHByZXZQdFxuICAgICAgICAgICAgICAgIGlmKGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQgJiYgIWkpIHByZXZQdCA9IGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQ7XG4gICAgICAgICAgICAgICAgc2Nvb3RPbmVMYWJlbCh0aGlzUXVhZE91dHNpZGVbaV0sIHByZXZQdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNjYWxlUGllcyhjZHBpZSwgcGxvdFNpemUpIHtcbiAgICB2YXIgc2NhbGVHcm91cHMgPSBbXTtcblxuICAgIHZhciBwaWVCb3hXaWR0aCwgcGllQm94SGVpZ2h0LCBpLCBqLCBjZDAsIHRyYWNlLFxuICAgICAgICBtYXhQdWxsLCBzY2FsZUdyb3VwLCBtaW5QeFBlclZhbFVuaXQ7XG5cbiAgICAvLyBmaXJzdCBmaWd1cmUgb3V0IHRoZSBjZW50ZXIgYW5kIG1heGltdW0gcmFkaXVzIGZvciBlYWNoIHBpZVxuICAgIGZvcihpID0gMDsgaSA8IGNkcGllLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkMCA9IGNkcGllW2ldWzBdO1xuICAgICAgICB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBwaWVCb3hXaWR0aCA9IHBsb3RTaXplLncgKiAodHJhY2UuZG9tYWluLnhbMV0gLSB0cmFjZS5kb21haW4ueFswXSk7XG4gICAgICAgIHBpZUJveEhlaWdodCA9IHBsb3RTaXplLmggKiAodHJhY2UuZG9tYWluLnlbMV0gLSB0cmFjZS5kb21haW4ueVswXSk7XG4gICAgICAgIC8vIGxlYXZlIHNvbWUgc3BhY2UgZm9yIHRoZSB0aXRsZSwgaWYgaXQgd2lsbCBiZSBkaXNwbGF5ZWQgb3V0c2lkZVxuICAgICAgICBpZih0cmFjZS50aXRsZSAmJiB0cmFjZS50aXRsZXBvc2l0aW9uICE9PSAnbWlkZGxlIGNlbnRlcicpIHtcbiAgICAgICAgICAgIHBpZUJveEhlaWdodCAtPSBnZXRUaXRsZVNwYWNlKGNkMCwgcGxvdFNpemUpO1xuICAgICAgICB9XG5cbiAgICAgICAgbWF4UHVsbCA9IGdldE1heFB1bGwodHJhY2UpO1xuXG4gICAgICAgIGNkMC5yID0gTWF0aC5taW4ocGllQm94V2lkdGgsIHBpZUJveEhlaWdodCkgLyAoMiArIDIgKiBtYXhQdWxsKTtcblxuICAgICAgICBjZDAuY3ggPSBwbG90U2l6ZS5sICsgcGxvdFNpemUudyAqICh0cmFjZS5kb21haW4ueFsxXSArIHRyYWNlLmRvbWFpbi54WzBdKSAvIDI7XG4gICAgICAgIGNkMC5jeSA9IHBsb3RTaXplLnQgKyBwbG90U2l6ZS5oICogKDEgLSB0cmFjZS5kb21haW4ueVswXSkgLSBwaWVCb3hIZWlnaHQgLyAyO1xuICAgICAgICBpZih0cmFjZS50aXRsZSAmJiB0cmFjZS50aXRsZXBvc2l0aW9uLmluZGV4T2YoJ2JvdHRvbScpICE9PSAtMSkge1xuICAgICAgICAgICAgY2QwLmN5IC09IGdldFRpdGxlU3BhY2UoY2QwLCBwbG90U2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0cmFjZS5zY2FsZWdyb3VwICYmIHNjYWxlR3JvdXBzLmluZGV4T2YodHJhY2Uuc2NhbGVncm91cCkgPT09IC0xKSB7XG4gICAgICAgICAgICBzY2FsZUdyb3Vwcy5wdXNoKHRyYWNlLnNjYWxlZ3JvdXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhlbiBzY2FsZSBhbnkgcGllcyB0aGF0IGFyZSBncm91cGVkXG4gICAgZm9yKGogPSAwOyBqIDwgc2NhbGVHcm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgbWluUHhQZXJWYWxVbml0ID0gSW5maW5pdHk7XG4gICAgICAgIHNjYWxlR3JvdXAgPSBzY2FsZUdyb3Vwc1tqXTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZHBpZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QwID0gY2RwaWVbaV1bMF07XG4gICAgICAgICAgICBpZihjZDAudHJhY2Uuc2NhbGVncm91cCA9PT0gc2NhbGVHcm91cCkge1xuICAgICAgICAgICAgICAgIG1pblB4UGVyVmFsVW5pdCA9IE1hdGgubWluKG1pblB4UGVyVmFsVW5pdCxcbiAgICAgICAgICAgICAgICAgICAgY2QwLnIgKiBjZDAuciAvIGNkMC52VG90YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2RwaWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNkMCA9IGNkcGllW2ldWzBdO1xuICAgICAgICAgICAgaWYoY2QwLnRyYWNlLnNjYWxlZ3JvdXAgPT09IHNjYWxlR3JvdXApIHtcbiAgICAgICAgICAgICAgICBjZDAuciA9IE1hdGguc3FydChtaW5QeFBlclZhbFVuaXQgKiBjZDAudlRvdGFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxufVxuXG5mdW5jdGlvbiBzZXRDb29yZHMoY2QpIHtcbiAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIHZhciBjdXJyZW50QW5nbGUgPSB0cmFjZS5yb3RhdGlvbiAqIE1hdGguUEkgLyAxODA7XG4gICAgdmFyIGFuZ2xlRmFjdG9yID0gMiAqIE1hdGguUEkgLyBjZDAudlRvdGFsO1xuICAgIHZhciBmaXJzdFB0ID0gJ3B4MCc7XG4gICAgdmFyIGxhc3RQdCA9ICdweDEnO1xuXG4gICAgdmFyIGksIGNkaSwgY3VycmVudENvb3JkcztcblxuICAgIGlmKHRyYWNlLmRpcmVjdGlvbiA9PT0gJ2NvdW50ZXJjbG9ja3dpc2UnKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZighY2RbaV0uaGlkZGVuKSBicmVhazsgLy8gZmluZCB0aGUgZmlyc3Qgbm9uLWhpZGRlbiBzbGljZVxuICAgICAgICB9XG4gICAgICAgIGlmKGkgPT09IGNkLmxlbmd0aCkgcmV0dXJuOyAvLyBhbGwgc2xpY2VzIGhpZGRlblxuXG4gICAgICAgIGN1cnJlbnRBbmdsZSArPSBhbmdsZUZhY3RvciAqIGNkW2ldLnY7XG4gICAgICAgIGFuZ2xlRmFjdG9yICo9IC0xO1xuICAgICAgICBmaXJzdFB0ID0gJ3B4MSc7XG4gICAgICAgIGxhc3RQdCA9ICdweDAnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldENvb3JkcyhhbmdsZSkge1xuICAgICAgICByZXR1cm4gW2NkMC5yICogTWF0aC5zaW4oYW5nbGUpLCAtY2QwLnIgKiBNYXRoLmNvcyhhbmdsZSldO1xuICAgIH1cblxuICAgIGN1cnJlbnRDb29yZHMgPSBnZXRDb29yZHMoY3VycmVudEFuZ2xlKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkaSA9IGNkW2ldO1xuICAgICAgICBpZihjZGkuaGlkZGVuKSBjb250aW51ZTtcblxuICAgICAgICBjZGlbZmlyc3RQdF0gPSBjdXJyZW50Q29vcmRzO1xuXG4gICAgICAgIGN1cnJlbnRBbmdsZSArPSBhbmdsZUZhY3RvciAqIGNkaS52IC8gMjtcbiAgICAgICAgY2RpLnB4bWlkID0gZ2V0Q29vcmRzKGN1cnJlbnRBbmdsZSk7XG4gICAgICAgIGNkaS5taWRhbmdsZSA9IGN1cnJlbnRBbmdsZTtcblxuICAgICAgICBjdXJyZW50QW5nbGUgKz0gYW5nbGVGYWN0b3IgKiBjZGkudiAvIDI7XG4gICAgICAgIGN1cnJlbnRDb29yZHMgPSBnZXRDb29yZHMoY3VycmVudEFuZ2xlKTtcblxuICAgICAgICBjZGlbbGFzdFB0XSA9IGN1cnJlbnRDb29yZHM7XG5cbiAgICAgICAgY2RpLmxhcmdlQXJjID0gKGNkaS52ID4gY2QwLnZUb3RhbCAvIDIpID8gMSA6IDA7XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xuXG52YXIgc3R5bGVPbmUgPSByZXF1aXJlKCcuL3N0eWxlX29uZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKGdkKSB7XG4gICAgZ2QuX2Z1bGxMYXlvdXQuX3BpZWxheWVyLnNlbGVjdEFsbCgnLnRyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIHRyYWNlU2VsZWN0aW9uID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHRyYWNlU2VsZWN0aW9uLnN0eWxlKHtvcGFjaXR5OiB0cmFjZS5vcGFjaXR5fSk7XG5cbiAgICAgICAgdHJhY2VTZWxlY3Rpb24uc2VsZWN0QWxsKCdwYXRoLnN1cmZhY2UnKS5lYWNoKGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuY2FsbChzdHlsZU9uZSwgcHQsIHRyYWNlKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgY2FzdE9wdGlvbiA9IHJlcXVpcmUoJy4vaGVscGVycycpLmNhc3RPcHRpb247XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3R5bGVPbmUocywgcHQsIHRyYWNlKSB7XG4gICAgdmFyIGxpbmUgPSB0cmFjZS5tYXJrZXIubGluZTtcbiAgICB2YXIgbGluZUNvbG9yID0gY2FzdE9wdGlvbihsaW5lLmNvbG9yLCBwdC5wdHMpIHx8IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgIHZhciBsaW5lV2lkdGggPSBjYXN0T3B0aW9uKGxpbmUud2lkdGgsIHB0LnB0cykgfHwgMDtcblxuICAgIHMuc3R5bGUoeydzdHJva2Utd2lkdGgnOiBsaW5lV2lkdGh9KVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBwdC5jb2xvcilcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBsaW5lQ29sb3IpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJnbEF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHg6IHNjYXR0ZXJnbEF0dHJzLngsXG4gICAgeTogc2NhdHRlcmdsQXR0cnMueSxcbiAgICB4eToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaW5kaWNlczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGJvdW5kczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWJvdW5kczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGV4dDogc2NhdHRlcmdsQXR0cnMudGV4dCxcbiAgICBtYXJrZXI6IHtcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBibGVuZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplbWluOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMC4xLFxuICAgICAgICAgICAgbWF4OiAyLFxuICAgICAgICAgICAgZGZsdDogMC41LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemVtYXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLjEsXG4gICAgICAgICAgICBkZmx0OiAyMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBib3JkZXI6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFyZWFyYXRpbzoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdHJhbnNmb3JtczogdW5kZWZpbmVkXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlUG9pbnRDbG91ZFJlbmRlcmVyID0gcmVxdWlyZSgnZ2wtcG9pbnRjbG91ZDJkJyk7XG5cbnZhciBzdHIyUkdCQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG52YXIgZmluZEV4dHJlbWVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F1dG9yYW5nZScpLmZpbmRFeHRyZW1lcztcbnZhciBnZXRUcmFjZUNvbG9yID0gcmVxdWlyZSgnLi4vc2NhdHRlci9nZXRfdHJhY2VfY29sb3InKTtcblxuZnVuY3Rpb24gUG9pbnRjbG91ZChzY2VuZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMudHlwZSA9ICdwb2ludGNsb3VkJztcblxuICAgIHRoaXMucGlja1hEYXRhID0gW107XG4gICAgdGhpcy5waWNrWURhdGEgPSBbXTtcbiAgICB0aGlzLnhEYXRhID0gW107XG4gICAgdGhpcy55RGF0YSA9IFtdO1xuICAgIHRoaXMudGV4dExhYmVscyA9IFtdO1xuICAgIHRoaXMuY29sb3IgPSAncmdiKDAsIDAsIDApJztcbiAgICB0aGlzLm5hbWUgPSAnJztcbiAgICB0aGlzLmhvdmVyaW5mbyA9ICdhbGwnO1xuXG4gICAgdGhpcy5pZFRvSW5kZXggPSBuZXcgSW50MzJBcnJheSgwKTtcbiAgICB0aGlzLmJvdW5kcyA9IFswLCAwLCAwLCAwXTtcblxuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMgPSB7XG4gICAgICAgIHBvc2l0aW9uczogbmV3IEZsb2F0MzJBcnJheSgwKSxcbiAgICAgICAgaWRUb0luZGV4OiB0aGlzLmlkVG9JbmRleCxcbiAgICAgICAgc2l6ZW1pbjogMC41LFxuICAgICAgICBzaXplbWF4OiAxMixcbiAgICAgICAgY29sb3I6IFswLCAwLCAwLCAxXSxcbiAgICAgICAgYXJlYVJhdGlvOiAxLFxuICAgICAgICBib3JkZXJDb2xvcjogWzAsIDAsIDAsIDFdXG4gICAgfTtcbiAgICB0aGlzLnBvaW50Y2xvdWQgPSBjcmVhdGVQb2ludENsb3VkUmVuZGVyZXIoc2NlbmUuZ2xwbG90LCB0aGlzLnBvaW50Y2xvdWRPcHRpb25zKTtcbiAgICB0aGlzLnBvaW50Y2xvdWQuX3RyYWNlID0gdGhpczsgLy8gc2NlbmUyZCByZXF1aXJlcyB0aGlzIHByb3Bcbn1cblxudmFyIHByb3RvID0gUG9pbnRjbG91ZC5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihwaWNrUmVzdWx0KSB7XG4gICAgdmFyIGluZGV4ID0gdGhpcy5pZFRvSW5kZXhbcGlja1Jlc3VsdC5wb2ludElkXTtcblxuICAgIC8vIHByZWZlciB0aGUgcmVhZG91dCBmcm9tIFhZLCBpZiBwcmVzZW50XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHJhY2U6IHRoaXMsXG4gICAgICAgIGRhdGFDb29yZDogcGlja1Jlc3VsdC5kYXRhQ29vcmQsXG4gICAgICAgIHRyYWNlQ29vcmQ6IHRoaXMucGlja1hZRGF0YSA/XG4gICAgICAgICAgICBbdGhpcy5waWNrWFlEYXRhW2luZGV4ICogMl0sIHRoaXMucGlja1hZRGF0YVtpbmRleCAqIDIgKyAxXV0gOlxuICAgICAgICAgICAgW3RoaXMucGlja1hEYXRhW2luZGV4XSwgdGhpcy5waWNrWURhdGFbaW5kZXhdXSxcbiAgICAgICAgdGV4dExhYmVsOiBBcnJheS5pc0FycmF5KHRoaXMudGV4dExhYmVscykgP1xuICAgICAgICAgICAgdGhpcy50ZXh0TGFiZWxzW2luZGV4XSA6XG4gICAgICAgICAgICB0aGlzLnRleHRMYWJlbHMsXG4gICAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLFxuICAgICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICAgIHBvaW50SW5kZXg6IGluZGV4LFxuICAgICAgICBob3ZlcmluZm86IHRoaXMuaG92ZXJpbmZvXG4gICAgfTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICB0aGlzLmluZGV4ID0gb3B0aW9ucy5pbmRleDtcbiAgICB0aGlzLnRleHRMYWJlbHMgPSBvcHRpb25zLnRleHQ7XG4gICAgdGhpcy5uYW1lID0gb3B0aW9ucy5uYW1lO1xuICAgIHRoaXMuaG92ZXJpbmZvID0gb3B0aW9ucy5ob3ZlcmluZm87XG4gICAgdGhpcy5ib3VuZHMgPSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07XG5cbiAgICB0aGlzLnVwZGF0ZUZhc3Qob3B0aW9ucyk7XG5cbiAgICB0aGlzLmNvbG9yID0gZ2V0VHJhY2VDb2xvcihvcHRpb25zLCB7fSk7XG59O1xuXG5wcm90by51cGRhdGVGYXN0ID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciB4ID0gdGhpcy54RGF0YSA9IHRoaXMucGlja1hEYXRhID0gb3B0aW9ucy54O1xuICAgIHZhciB5ID0gdGhpcy55RGF0YSA9IHRoaXMucGlja1lEYXRhID0gb3B0aW9ucy55O1xuICAgIHZhciB4eSA9IHRoaXMucGlja1hZRGF0YSA9IG9wdGlvbnMueHk7XG5cbiAgICB2YXIgdXNlckJvdW5kcyA9IG9wdGlvbnMueGJvdW5kcyAmJiBvcHRpb25zLnlib3VuZHM7XG4gICAgdmFyIGluZGV4ID0gb3B0aW9ucy5pbmRpY2VzO1xuXG4gICAgdmFyIGxlbixcbiAgICAgICAgaWRUb0luZGV4LFxuICAgICAgICBwb3NpdGlvbnMsXG4gICAgICAgIGJvdW5kcyA9IHRoaXMuYm91bmRzO1xuXG4gICAgdmFyIHh4LCB5eSwgaTtcblxuICAgIGlmKHh5KSB7XG5cbiAgICAgICAgcG9zaXRpb25zID0geHk7XG5cbiAgICAgICAgLy8gZGl2aWRpbmcgeHkubGVuZ3RoIGJ5IDIgYW5kIHRydW5jYXRpbmcgdG8gaW50ZWdlciBpZiB4eS5sZW5ndGggd2FzIG5vdCBldmVuXG4gICAgICAgIGxlbiA9IHh5Lmxlbmd0aCA+Pj4gMTtcblxuICAgICAgICBpZih1c2VyQm91bmRzKSB7XG5cbiAgICAgICAgICAgIGJvdW5kc1swXSA9IG9wdGlvbnMueGJvdW5kc1swXTtcbiAgICAgICAgICAgIGJvdW5kc1syXSA9IG9wdGlvbnMueGJvdW5kc1sxXTtcbiAgICAgICAgICAgIGJvdW5kc1sxXSA9IG9wdGlvbnMueWJvdW5kc1swXTtcbiAgICAgICAgICAgIGJvdW5kc1szXSA9IG9wdGlvbnMueWJvdW5kc1sxXTtcblxuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgeHggPSBwb3NpdGlvbnNbaSAqIDJdO1xuICAgICAgICAgICAgICAgIHl5ID0gcG9zaXRpb25zW2kgKiAyICsgMV07XG5cbiAgICAgICAgICAgICAgICBpZih4eCA8IGJvdW5kc1swXSkgYm91bmRzWzBdID0geHg7XG4gICAgICAgICAgICAgICAgaWYoeHggPiBib3VuZHNbMl0pIGJvdW5kc1syXSA9IHh4O1xuICAgICAgICAgICAgICAgIGlmKHl5IDwgYm91bmRzWzFdKSBib3VuZHNbMV0gPSB5eTtcbiAgICAgICAgICAgICAgICBpZih5eSA+IGJvdW5kc1szXSkgYm91bmRzWzNdID0geXk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGluZGV4KSB7XG5cbiAgICAgICAgICAgIGlkVG9JbmRleCA9IGluZGV4O1xuXG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGlkVG9JbmRleCA9IG5ldyBJbnQzMkFycmF5KGxlbik7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBpZFRvSW5kZXhbaV0gPSBpO1xuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIHtcblxuICAgICAgICBsZW4gPSB4Lmxlbmd0aDtcblxuICAgICAgICBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KDIgKiBsZW4pO1xuICAgICAgICBpZFRvSW5kZXggPSBuZXcgSW50MzJBcnJheShsZW4pO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB4eCA9IHhbaV07XG4gICAgICAgICAgICB5eSA9IHlbaV07XG5cbiAgICAgICAgICAgIGlkVG9JbmRleFtpXSA9IGk7XG5cbiAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMl0gPSB4eDtcbiAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMiArIDFdID0geXk7XG5cbiAgICAgICAgICAgIGlmKHh4IDwgYm91bmRzWzBdKSBib3VuZHNbMF0gPSB4eDtcbiAgICAgICAgICAgIGlmKHh4ID4gYm91bmRzWzJdKSBib3VuZHNbMl0gPSB4eDtcbiAgICAgICAgICAgIGlmKHl5IDwgYm91bmRzWzFdKSBib3VuZHNbMV0gPSB5eTtcbiAgICAgICAgICAgIGlmKHl5ID4gYm91bmRzWzNdKSBib3VuZHNbM10gPSB5eTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgdGhpcy5pZFRvSW5kZXggPSBpZFRvSW5kZXg7XG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5pZFRvSW5kZXggPSBpZFRvSW5kZXg7XG5cbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcblxuICAgIHZhciBtYXJrZXJDb2xvciA9IHN0cjJSR0JBcnJheShvcHRpb25zLm1hcmtlci5jb2xvciksXG4gICAgICAgIGJvcmRlckNvbG9yID0gc3RyMlJHQkFycmF5KG9wdGlvbnMubWFya2VyLmJvcmRlci5jb2xvciksXG4gICAgICAgIG9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHkgKiBvcHRpb25zLm1hcmtlci5vcGFjaXR5O1xuXG4gICAgbWFya2VyQ29sb3JbM10gKj0gb3BhY2l0eTtcbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zLmNvbG9yID0gbWFya2VyQ29sb3I7XG5cbiAgICAvLyBkZXRlY3QgYmxlbmRpbmcgZnJvbSB0aGUgbnVtYmVyIG9mIHBvaW50cywgaWYgdW5kZWZpbmVkXG4gICAgLy8gYmVjYXVzZSBsYXJnZSBkYXRhIHdpdGggYmxlbmRpbmcgaGl0cyBwZXJmb3JtYW5jZVxuICAgIHZhciBibGVuZCA9IG9wdGlvbnMubWFya2VyLmJsZW5kO1xuICAgIGlmKGJsZW5kID09PSBudWxsKSB7XG4gICAgICAgIHZhciBtYXhQb2ludHMgPSAxMDA7XG4gICAgICAgIGJsZW5kID0geC5sZW5ndGggPCBtYXhQb2ludHMgfHwgeS5sZW5ndGggPCBtYXhQb2ludHM7XG4gICAgfVxuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMuYmxlbmQgPSBibGVuZDtcblxuICAgIGJvcmRlckNvbG9yWzNdICo9IG9wYWNpdHk7XG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5ib3JkZXJDb2xvciA9IGJvcmRlckNvbG9yO1xuXG4gICAgdmFyIG1hcmtlclNpemVNaW4gPSBvcHRpb25zLm1hcmtlci5zaXplbWluO1xuICAgIHZhciBtYXJrZXJTaXplTWF4ID0gTWF0aC5tYXgob3B0aW9ucy5tYXJrZXIuc2l6ZW1heCwgb3B0aW9ucy5tYXJrZXIuc2l6ZW1pbik7XG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5zaXplTWluID0gbWFya2VyU2l6ZU1pbjtcbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zLnNpemVNYXggPSBtYXJrZXJTaXplTWF4O1xuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMuYXJlYVJhdGlvID0gb3B0aW9ucy5tYXJrZXIuYm9yZGVyLmFyZWFyYXRpbztcblxuICAgIHRoaXMucG9pbnRjbG91ZC51cGRhdGUodGhpcy5wb2ludGNsb3VkT3B0aW9ucyk7XG5cbiAgICAvLyBhZGQgaXRlbSBmb3IgYXV0b3JhbmdlIHJvdXRpbmVcbiAgICB2YXIgeGEgPSB0aGlzLnNjZW5lLnhheGlzO1xuICAgIHZhciB5YSA9IHRoaXMuc2NlbmUueWF4aXM7XG4gICAgdmFyIHBhZCA9IG1hcmtlclNpemVNYXggLyAyIHx8IDAuNTtcbiAgICBvcHRpb25zLl9leHRyZW1lc1t4YS5faWRdID0gZmluZEV4dHJlbWVzKHhhLCBbYm91bmRzWzBdLCBib3VuZHNbMl1dLCB7cHBhZDogcGFkfSk7XG4gICAgb3B0aW9ucy5fZXh0cmVtZXNbeWEuX2lkXSA9IGZpbmRFeHRyZW1lcyh5YSwgW2JvdW5kc1sxXSwgYm91bmRzWzNdXSwge3BwYWQ6IHBhZH0pO1xufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMucG9pbnRjbG91ZC5kaXNwb3NlKCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVQb2ludGNsb3VkKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIHBsb3QgPSBuZXcgUG9pbnRjbG91ZChzY2VuZSwgZGF0YS51aWQpO1xuICAgIHBsb3QudXBkYXRlKGRhdGEpO1xuICAgIHJldHVybiBwbG90O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVBvaW50Y2xvdWQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCd4Jyk7XG4gICAgY29lcmNlKCd5Jyk7XG5cbiAgICBjb2VyY2UoJ3hib3VuZHMnKTtcbiAgICBjb2VyY2UoJ3lib3VuZHMnKTtcblxuICAgIGlmKHRyYWNlSW4ueHkgJiYgdHJhY2VJbi54eSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSkge1xuICAgICAgICB0cmFjZU91dC54eSA9IHRyYWNlSW4ueHk7XG4gICAgfVxuXG4gICAgaWYodHJhY2VJbi5pbmRpY2VzICYmIHRyYWNlSW4uaW5kaWNlcyBpbnN0YW5jZW9mIEludDMyQXJyYXkpIHtcbiAgICAgICAgdHJhY2VPdXQuaW5kaWNlcyA9IHRyYWNlSW4uaW5kaWNlcztcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ21hcmtlci5jb2xvcicsIGRlZmF1bHRDb2xvcik7XG4gICAgY29lcmNlKCdtYXJrZXIub3BhY2l0eScpO1xuICAgIGNvZXJjZSgnbWFya2VyLmJsZW5kJyk7XG4gICAgY29lcmNlKCdtYXJrZXIuc2l6ZW1pbicpO1xuICAgIGNvZXJjZSgnbWFya2VyLnNpemVtYXgnKTtcbiAgICBjb2VyY2UoJ21hcmtlci5ib3JkZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuICAgIGNvZXJjZSgnbWFya2VyLmJvcmRlci5hcmVhcmF0aW8nKTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3JtcyAtIHRoYXQgd291bGQgZGVmZWF0IHRoZSBwdXJwb3NlIG9mIHRoaXMgdHJhY2UgdHlwZSwgcGVyZm9ybWFuY2UhXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcG9pbnRjbG91ZCA9IHt9O1xuXG5wb2ludGNsb3VkLmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnBvaW50Y2xvdWQuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5cbi8vIHJldXNlIHRoZSBTY2F0dGVyM0QgJ2R1bW15JyBjYWxjIHN0ZXAgc28gdGhhdCBsZWdlbmRzIGtub3cgd2hhdCB0byBkb1xucG9pbnRjbG91ZC5jYWxjID0gcmVxdWlyZSgnLi4vc2NhdHRlcjNkL2NhbGMnKTtcbnBvaW50Y2xvdWQucGxvdCA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xuXG5wb2ludGNsb3VkLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xucG9pbnRjbG91ZC5uYW1lID0gJ3BvaW50Y2xvdWQnO1xucG9pbnRjbG91ZC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dsMmQnKTtcbnBvaW50Y2xvdWQuY2F0ZWdvcmllcyA9IFsnZ2wnLCAnZ2wyZCcsICdzaG93TGVnZW5kJ107XG5wb2ludGNsb3VkLm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHBvaW50Y2xvdWQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBwbG90QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGZ4QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4L2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogW10sXG4gICAgICAgIGFycmF5T2s6IGZhbHNlLFxuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcmxhYmVsOiBmeEF0dHJzLmhvdmVybGFiZWwsXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3NhbmtleScsIHRyYWNlOiB0cnVlfSksXG5cbiAgICBvcmllbnRhdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd2JywgJ2gnXSxcbiAgICAgICAgZGZsdDogJ2gnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHZhbHVlZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnLjNzJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB2YWx1ZXN1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYXJyYW5nZW1lbnQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc25hcCcsICdwZXJwZW5kaWN1bGFyJywgJ2ZyZWVmb3JtJywgJ2ZpeGVkJ10sXG4gICAgICAgIGRmbHQ6ICdzbmFwJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0Zm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBub2RlOiB7XG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMC41LFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHBhZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDIwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGhpY2tuZXNzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGFycmF5T2s6IGZhbHNlLFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgZGZsdDogMjAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBob3ZlcmluZm86IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydhbGwnLCAnbm9uZScsICdza2lwJ10sXG4gICAgICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhvdmVybGFiZWw6IGZ4QXR0cnMuaG92ZXJsYWJlbCwgLy8gbmVlZHMgZWRpdFR5cGUgb3ZlcnJpZGUsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsaW5rOiB7XG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzb3VyY2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGFyZ2V0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhvdmVyaW5mbzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdub25lJywgJ3NraXAnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgaG92ZXJsYWJlbDogZnhBdHRycy5ob3ZlcmxhYmVsLCAvLyBuZWVkcyBlZGl0VHlwZSBvdmVycmlkZSxcbiAgICAgICAgXG4gICAgfVxufSwgJ2NhbGMnLCAnbmVzdGVkJyk7XG5hdHRycy50cmFuc2Zvcm1zID0gdW5kZWZpbmVkO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG52YXIgZ2V0TW9kdWxlQ2FsY0RhdGEgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldE1vZHVsZUNhbGNEYXRhO1xudmFyIHBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcbnZhciBmeEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meC9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgU0FOS0VZID0gJ3NhbmtleSc7XG5cbmV4cG9ydHMubmFtZSA9IFNBTktFWTtcblxuZXhwb3J0cy5iYXNlTGF5b3V0QXR0ck92ZXJyaWRlcyA9IG92ZXJyaWRlQWxsKHtcbiAgICBob3ZlcmxhYmVsOiBmeEF0dHJzLmhvdmVybGFiZWxcbn0sICdwbG90JywgJ25lc3RlZCcpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBjYWxjRGF0YSA9IGdldE1vZHVsZUNhbGNEYXRhKGdkLmNhbGNkYXRhLCBTQU5LRVkpWzBdO1xuICAgIHBsb3QoZ2QsIGNhbGNEYXRhKTtcbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkUGxvdCA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKFNBTktFWSkpO1xuICAgIHZhciBoYXNQbG90ID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoU0FOS0VZKSk7XG5cbiAgICBpZihoYWRQbG90ICYmICFoYXNQbG90KSB7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLnNhbmtleScpLnJlbW92ZSgpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0YXJqYW4gPSByZXF1aXJlKCdzdHJvbmdseS1jb25uZWN0ZWQtY29tcG9uZW50cycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHdyYXAgPSByZXF1aXJlKCcuLi8uLi9saWIvZ3VwJykud3JhcDtcblxuZnVuY3Rpb24gY2lyY3VsYXJpdHlQcmVzZW50KG5vZGVMaXN0LCBzb3VyY2VzLCB0YXJnZXRzKSB7XG5cbiAgICB2YXIgbm9kZUxlbiA9IG5vZGVMaXN0Lmxlbmd0aDtcbiAgICB2YXIgbm9kZXMgPSBMaWIuaW5pdDJkQXJyYXkobm9kZUxlbiwgMCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgTWF0aC5taW4oc291cmNlcy5sZW5ndGgsIHRhcmdldHMubGVuZ3RoKTsgaSsrKSB7XG4gICAgICAgIGlmKExpYi5pc0luZGV4KHNvdXJjZXNbaV0sIG5vZGVMZW4pICYmIExpYi5pc0luZGV4KHRhcmdldHNbaV0sIG5vZGVMZW4pKSB7XG4gICAgICAgICAgICBpZihzb3VyY2VzW2ldID09PSB0YXJnZXRzW2ldKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7IC8vIHNlbGYtbGluayB3aGljaCBpcyBhbHNvIGEgc2NjIG9mIG9uZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZXNbc291cmNlc1tpXV0ucHVzaCh0YXJnZXRzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzY2MgPSB0YXJqYW4obm9kZXMpO1xuXG4gICAgLy8gVGFyasOhbidzIHN0cm9uZ2x5IGNvbm5lY3RlZCBjb21wb25lbnRzIGFsZ29yaXRobSBjb2RlZCBieSBNaWtvbGEgTHlzZW5rb1xuICAgIC8vIHJldHVybnMgYXQgbGVhc3Qgb25lIG5vbi1zaW5ndWxhciBjb21wb25lbnQgaWYgdGhlcmUncyBjaXJjdWxhcml0eSBpbiB0aGUgZ3JhcGhcbiAgICByZXR1cm4gc2NjLmNvbXBvbmVudHMuc29tZShmdW5jdGlvbihjKSB7XG4gICAgICAgIHJldHVybiBjLmxlbmd0aCA+IDE7XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcblxuICAgIGlmKGNpcmN1bGFyaXR5UHJlc2VudCh0cmFjZS5ub2RlLmxhYmVsLCB0cmFjZS5saW5rLnNvdXJjZSwgdHJhY2UubGluay50YXJnZXQpKSB7XG4gICAgICAgIExpYi5lcnJvcignQ2lyY3VsYXJpdHkgaXMgcHJlc2VudCBpbiB0aGUgU2Fua2V5IGRhdGEuIFJlbW92aW5nIGFsbCBub2RlcyBhbmQgbGlua3MuJyk7XG4gICAgICAgIHRyYWNlLmxpbmsubGFiZWwgPSBbXTtcbiAgICAgICAgdHJhY2UubGluay5zb3VyY2UgPSBbXTtcbiAgICAgICAgdHJhY2UubGluay50YXJnZXQgPSBbXTtcbiAgICAgICAgdHJhY2UubGluay52YWx1ZSA9IFtdO1xuICAgICAgICB0cmFjZS5saW5rLmNvbG9yID0gW107XG4gICAgICAgIHRyYWNlLm5vZGUubGFiZWwgPSBbXTtcbiAgICAgICAgdHJhY2Uubm9kZS5jb2xvciA9IFtdO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwKHtcbiAgICAgICAgbGluazogdHJhY2UubGluayxcbiAgICAgICAgbm9kZTogdHJhY2Uubm9kZVxuICAgIH0pO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbm9kZVRleHRPZmZzZXRIb3Jpem9udGFsOiA0LFxuICAgIG5vZGVUZXh0T2Zmc2V0VmVydGljYWw6IDMsXG4gICAgbm9kZVBhZEFjcm9zczogMTAsXG4gICAgc2Fua2V5SXRlcmF0aW9uczogNTAsXG4gICAgZm9yY2VJdGVyYXRpb25zOiA1LFxuICAgIGZvcmNlVGlja3NQZXJGcmFtZTogMTAsXG4gICAgZHVyYXRpb246IDUwMCxcbiAgICBlYXNlOiAnY3ViaWMtaW4tb3V0JyxcbiAgICBjbjoge1xuICAgICAgICBzYW5rZXk6ICdzYW5rZXknLFxuICAgICAgICBzYW5rZXlMaW5rczogJ3NhbmtleS1saW5rcycsXG4gICAgICAgIHNhbmtleUxpbms6ICdzYW5rZXktbGluaycsXG4gICAgICAgIHNhbmtleU5vZGVTZXQ6ICdzYW5rZXktbm9kZS1zZXQnLFxuICAgICAgICBzYW5rZXlOb2RlOiAnc2Fua2V5LW5vZGUnLFxuICAgICAgICBub2RlUmVjdDogJ25vZGUtcmVjdCcsXG4gICAgICAgIG5vZGVDYXB0dXJlOiAnbm9kZS1jYXB0dXJlJyxcbiAgICAgICAgbm9kZUNlbnRlcmVkOiAnbm9kZS1lbnRlcmVkJyxcbiAgICAgICAgbm9kZUxhYmVsR3VpZGU6ICdub2RlLWxhYmVsLWd1aWRlJyxcbiAgICAgICAgbm9kZUxhYmVsOiAnbm9kZS1sYWJlbCcsXG4gICAgICAgIG5vZGVMYWJlbFRleHRQYXRoOiAnbm9kZS1sYWJlbC10ZXh0LXBhdGgnXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciB0aW55Y29sb3IgPSByZXF1aXJlKCd0aW55Y29sb3IyJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVybGFiZWxfZGVmYXVsdHMnKTtcbnZhciBUZW1wbGF0ZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGhvdmVybGFiZWxEZWZhdWx0ID0gTGliLmV4dGVuZERlZXAobGF5b3V0LmhvdmVybGFiZWwsIHRyYWNlSW4uaG92ZXJsYWJlbCk7XG5cbiAgICAvLyBub2RlIGF0dHJpYnV0ZXNcbiAgICB2YXIgbm9kZUluID0gdHJhY2VJbi5ub2RlLCBub2RlT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKHRyYWNlT3V0LCAnbm9kZScpO1xuICAgIGZ1bmN0aW9uIGNvZXJjZU5vZGUoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShub2RlSW4sIG5vZGVPdXQsIGF0dHJpYnV0ZXMubm9kZSwgYXR0ciwgZGZsdCk7XG4gICAgfVxuICAgIGNvZXJjZU5vZGUoJ2xhYmVsJyk7XG4gICAgY29lcmNlTm9kZSgncGFkJyk7XG4gICAgY29lcmNlTm9kZSgndGhpY2tuZXNzJyk7XG4gICAgY29lcmNlTm9kZSgnbGluZS5jb2xvcicpO1xuICAgIGNvZXJjZU5vZGUoJ2xpbmUud2lkdGgnKTtcbiAgICBjb2VyY2VOb2RlKCdob3ZlcmluZm8nLCB0cmFjZUluLmhvdmVyaW5mbyk7XG4gICAgaGFuZGxlSG92ZXJMYWJlbERlZmF1bHRzKG5vZGVJbiwgbm9kZU91dCwgY29lcmNlTm9kZSwgaG92ZXJsYWJlbERlZmF1bHQpO1xuXG4gICAgdmFyIGNvbG9ycyA9IGxheW91dC5jb2xvcndheTtcblxuICAgIHZhciBkZWZhdWx0Tm9kZVBhbGV0dGUgPSBmdW5jdGlvbihpKSB7cmV0dXJuIGNvbG9yc1tpICUgY29sb3JzLmxlbmd0aF07fTtcblxuICAgIGNvZXJjZU5vZGUoJ2NvbG9yJywgbm9kZU91dC5sYWJlbC5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gQ29sb3IuYWRkT3BhY2l0eShkZWZhdWx0Tm9kZVBhbGV0dGUoaSksIDAuOCk7XG4gICAgfSkpO1xuXG4gICAgLy8gbGluayBhdHRyaWJ1dGVzXG4gICAgdmFyIGxpbmtJbiA9IHRyYWNlSW4ubGluaywgbGlua091dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcih0cmFjZU91dCwgJ2xpbmsnKTtcbiAgICBmdW5jdGlvbiBjb2VyY2VMaW5rKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGlua0luLCBsaW5rT3V0LCBhdHRyaWJ1dGVzLmxpbmssIGF0dHIsIGRmbHQpO1xuICAgIH1cbiAgICBjb2VyY2VMaW5rKCdsYWJlbCcpO1xuICAgIGNvZXJjZUxpbmsoJ3NvdXJjZScpO1xuICAgIGNvZXJjZUxpbmsoJ3RhcmdldCcpO1xuICAgIGNvZXJjZUxpbmsoJ3ZhbHVlJyk7XG4gICAgY29lcmNlTGluaygnbGluZS5jb2xvcicpO1xuICAgIGNvZXJjZUxpbmsoJ2xpbmUud2lkdGgnKTtcbiAgICBjb2VyY2VMaW5rKCdob3ZlcmluZm8nLCB0cmFjZUluLmhvdmVyaW5mbyk7XG4gICAgaGFuZGxlSG92ZXJMYWJlbERlZmF1bHRzKGxpbmtJbiwgbGlua091dCwgY29lcmNlTGluaywgaG92ZXJsYWJlbERlZmF1bHQpO1xuXG4gICAgdmFyIGRlZmF1bHRMaW5rQ29sb3IgPSB0aW55Y29sb3IobGF5b3V0LnBhcGVyX2JnY29sb3IpLmdldEx1bWluYW5jZSgpIDwgMC4zMzMgP1xuICAgICAgICAgICAgICAgICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNiknIDpcbiAgICAgICAgICAgICAgICAncmdiYSgwLCAwLCAwLCAwLjIpJztcblxuICAgIGNvZXJjZUxpbmsoJ2NvbG9yJywgTGliLnJlcGVhdChkZWZhdWx0TGlua0NvbG9yLCBsaW5rT3V0LnZhbHVlLmxlbmd0aCkpO1xuXG4gICAgaGFuZGxlRG9tYWluRGVmYXVsdHModHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcblxuICAgIGNvZXJjZSgnb3JpZW50YXRpb24nKTtcbiAgICBjb2VyY2UoJ3ZhbHVlZm9ybWF0Jyk7XG4gICAgY29lcmNlKCd2YWx1ZXN1ZmZpeCcpO1xuICAgIGNvZXJjZSgnYXJyYW5nZW1lbnQnKTtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RleHRmb250JywgTGliLmV4dGVuZEZsYXQoe30sIGxheW91dC5mb250KSk7XG5cbiAgICAvLyBkaXNhYmxlIDFEIHRyYW5zZm9ybXMgLSBhcnJheXMgaGVyZSBhcmUgMUQgYnV0IHRoZWlyIGxlbmd0aHMvbWVhbmluZ3NcbiAgICAvLyBkb24ndCBtYXRjaCwgYmV0d2VlbiBub2RlcyBhbmQgbGlua3NcbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBQbG90ID0ge307XG5cblBsb3QuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuUGxvdC5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcblBsb3QuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuUGxvdC5wbG90ID0gcmVxdWlyZSgnLi9wbG90Jyk7XG5cblBsb3QubW9kdWxlVHlwZSA9ICd0cmFjZSc7XG5QbG90Lm5hbWUgPSAnc2Fua2V5JztcblBsb3QuYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuL2Jhc2VfcGxvdCcpO1xuUGxvdC5jYXRlZ29yaWVzID0gWydub09wYWNpdHknXTtcblBsb3QubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gUGxvdDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciByZW5kZXIgPSByZXF1aXJlKCcuL3JlbmRlcicpO1xudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGNuID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKS5jbjtcblxudmFyIF8gPSBMaWIuXztcblxuZnVuY3Rpb24gcmVuZGVyYWJsZVZhbHVlUHJlc2VudChkKSB7cmV0dXJuIGQgIT09ICcnO31cblxuZnVuY3Rpb24gb3duVHJhY2Uoc2VsZWN0aW9uLCBkKSB7XG4gICAgcmV0dXJuIHNlbGVjdGlvbi5maWx0ZXIoZnVuY3Rpb24ocykge3JldHVybiBzLmtleSA9PT0gZC50cmFjZUlkO30pO1xufVxuXG5mdW5jdGlvbiBtYWtlVHJhbnNsdWNlbnQoZWxlbWVudCwgYWxwaGEpIHtcbiAgICBkMy5zZWxlY3QoZWxlbWVudClcbiAgICAgICAgLnNlbGVjdCgncGF0aCcpXG4gICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgYWxwaGEpO1xuICAgIGQzLnNlbGVjdChlbGVtZW50KVxuICAgICAgICAuc2VsZWN0KCdyZWN0JylcbiAgICAgICAgLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBhbHBoYSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VUZXh0Q29udHJhc3R5KGVsZW1lbnQpIHtcbiAgICBkMy5zZWxlY3QoZWxlbWVudClcbiAgICAgICAgLnNlbGVjdCgndGV4dC5uYW1lJylcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgJ2JsYWNrJyk7XG59XG5cbmZ1bmN0aW9uIHJlbGF0ZWRMaW5rcyhkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGwpIHtcbiAgICAgICAgcmV0dXJuIGQubm9kZS5zb3VyY2VMaW5rcy5pbmRleE9mKGwubGluaykgIT09IC0xIHx8IGQubm9kZS50YXJnZXRMaW5rcy5pbmRleE9mKGwubGluaykgIT09IC0xO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHJlbGF0ZWROb2RlcyhsKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQubm9kZS5zb3VyY2VMaW5rcy5pbmRleE9mKGwubGluaykgIT09IC0xIHx8IGQubm9kZS50YXJnZXRMaW5rcy5pbmRleE9mKGwubGluaykgIT09IC0xO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIG5vZGVIb3ZlcmVkU3R5bGUoc2Fua2V5Tm9kZSwgZCwgc2Fua2V5KSB7XG4gICAgaWYoZCAmJiBzYW5rZXkpIHtcbiAgICAgICAgb3duVHJhY2Uoc2Fua2V5LCBkKVxuICAgICAgICAgICAgLnNlbGVjdEFsbCgnLicgKyBjbi5zYW5rZXlMaW5rKVxuICAgICAgICAgICAgLmZpbHRlcihyZWxhdGVkTGlua3MoZCkpXG4gICAgICAgICAgICAuY2FsbChsaW5rSG92ZXJlZFN0eWxlLmJpbmQoMCwgZCwgc2Fua2V5LCBmYWxzZSkpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gbm9kZU5vbkhvdmVyZWRTdHlsZShzYW5rZXlOb2RlLCBkLCBzYW5rZXkpIHtcbiAgICBpZihkICYmIHNhbmtleSkge1xuICAgICAgICBvd25UcmFjZShzYW5rZXksIGQpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGNuLnNhbmtleUxpbmspXG4gICAgICAgICAgICAuZmlsdGVyKHJlbGF0ZWRMaW5rcyhkKSlcbiAgICAgICAgICAgIC5jYWxsKGxpbmtOb25Ib3ZlcmVkU3R5bGUuYmluZCgwLCBkLCBzYW5rZXksIGZhbHNlKSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBsaW5rSG92ZXJlZFN0eWxlKGQsIHNhbmtleSwgdmlzaXROb2Rlcywgc2Fua2V5TGluaykge1xuXG4gICAgdmFyIGxhYmVsID0gc2Fua2V5TGluay5kYXR1bSgpLmxpbmsubGFiZWw7XG5cbiAgICBzYW5rZXlMaW5rLnN0eWxlKCdmaWxsLW9wYWNpdHknLCAwLjQpO1xuXG4gICAgaWYobGFiZWwpIHtcbiAgICAgICAgb3duVHJhY2Uoc2Fua2V5LCBkKVxuICAgICAgICAgICAgLnNlbGVjdEFsbCgnLicgKyBjbi5zYW5rZXlMaW5rKVxuICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihsKSB7cmV0dXJuIGwubGluay5sYWJlbCA9PT0gbGFiZWw7fSlcbiAgICAgICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgMC40KTtcbiAgICB9XG5cbiAgICBpZih2aXNpdE5vZGVzKSB7XG4gICAgICAgIG93blRyYWNlKHNhbmtleSwgZClcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY24uc2Fua2V5Tm9kZSlcbiAgICAgICAgICAgIC5maWx0ZXIocmVsYXRlZE5vZGVzKGQpKVxuICAgICAgICAgICAgLmNhbGwobm9kZUhvdmVyZWRTdHlsZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBsaW5rTm9uSG92ZXJlZFN0eWxlKGQsIHNhbmtleSwgdmlzaXROb2Rlcywgc2Fua2V5TGluaykge1xuXG4gICAgdmFyIGxhYmVsID0gc2Fua2V5TGluay5kYXR1bSgpLmxpbmsubGFiZWw7XG5cbiAgICBzYW5rZXlMaW5rLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudGlueUNvbG9yQWxwaGE7fSk7XG5cbiAgICBpZihsYWJlbCkge1xuICAgICAgICBvd25UcmFjZShzYW5rZXksIGQpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGNuLnNhbmtleUxpbmspXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKGwpIHtyZXR1cm4gbC5saW5rLmxhYmVsID09PSBsYWJlbDt9KVxuICAgICAgICAgICAgLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudGlueUNvbG9yQWxwaGE7fSk7XG4gICAgfVxuXG4gICAgaWYodmlzaXROb2Rlcykge1xuICAgICAgICBvd25UcmFjZShzYW5rZXksIGQpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKGNuLnNhbmtleU5vZGUpXG4gICAgICAgICAgICAuZmlsdGVyKHJlbGF0ZWROb2RlcyhkKSlcbiAgICAgICAgICAgIC5jYWxsKG5vZGVOb25Ib3ZlcmVkU3R5bGUpO1xuICAgIH1cbn1cblxuLy8gZG9lcyBub3Qgc3VwcG9ydCBhcnJheSB2YWx1ZXMgZm9yIG5vd1xuZnVuY3Rpb24gY2FzdEhvdmVyT3B0aW9uKHRyYWNlLCBhdHRyKSB7XG4gICAgdmFyIGxhYmVsT3B0cyA9IHRyYWNlLmhvdmVybGFiZWwgfHwge307XG4gICAgdmFyIHZhbCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShsYWJlbE9wdHMsIGF0dHIpLmdldCgpO1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbCkgPyBmYWxzZSA6IHZhbDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBjYWxjRGF0YSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN2ZyA9IGZ1bGxMYXlvdXQuX3BhcGVyO1xuICAgIHZhciBzaXplID0gZnVsbExheW91dC5fc2l6ZTtcblxuICAgIHZhciBsaW5rU2VsZWN0ID0gZnVuY3Rpb24oZWxlbWVudCwgZCkge1xuICAgICAgICB2YXIgZXZ0ID0gZC5saW5rO1xuICAgICAgICBldnQub3JpZ2luYWxFdmVudCA9IGQzLmV2ZW50O1xuICAgICAgICBnZC5faG92ZXJkYXRhID0gW2V2dF07XG4gICAgICAgIEZ4LmNsaWNrKGdkLCB7IHRhcmdldDogdHJ1ZSB9KTtcbiAgICB9O1xuXG4gICAgdmFyIGxpbmtIb3ZlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKGxpbmtIb3ZlcmVkU3R5bGUuYmluZCgwLCBkLCBzYW5rZXksIHRydWUpKTtcbiAgICAgICAgaWYoZC5saW5rLnRyYWNlLmxpbmsuaG92ZXJpbmZvICE9PSAnc2tpcCcpIHtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9ob3ZlcicsIHtcbiAgICAgICAgICAgICAgICBldmVudDogZDMuZXZlbnQsXG4gICAgICAgICAgICAgICAgcG9pbnRzOiBbZC5saW5rXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgIH07XG5cbiAgICB2YXIgc291cmNlTGFiZWwgPSBfKGdkLCAnc291cmNlOicpICsgJyAnO1xuICAgIHZhciB0YXJnZXRMYWJlbCA9IF8oZ2QsICd0YXJnZXQ6JykgKyAnICc7XG4gICAgdmFyIGluY29taW5nTGFiZWwgPSBfKGdkLCAnaW5jb21pbmcgZmxvdyBjb3VudDonKSArICcgJztcbiAgICB2YXIgb3V0Z29pbmdMYWJlbCA9IF8oZ2QsICdvdXRnb2luZyBmbG93IGNvdW50OicpICsgJyAnO1xuXG4gICAgdmFyIGxpbmtIb3ZlckZvbGxvdyA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQpIHtcbiAgICAgICAgaWYoZ2QuX2Z1bGxMYXlvdXQuaG92ZXJtb2RlID09PSBmYWxzZSkgcmV0dXJuO1xuICAgICAgICB2YXIgb2JqID0gZC5saW5rLnRyYWNlLmxpbms7XG4gICAgICAgIGlmKG9iai5ob3ZlcmluZm8gPT09ICdub25lJyB8fCBvYmouaG92ZXJpbmZvID09PSAnc2tpcCcpIHJldHVybjtcbiAgICAgICAgdmFyIHJvb3RCQm94ID0gZ2QuX2Z1bGxMYXlvdXQuX3BhcGVyZGl2Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIGJvdW5kaW5nQm94ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIGhvdmVyQ2VudGVyWCA9IGJvdW5kaW5nQm94LmxlZnQgKyBib3VuZGluZ0JveC53aWR0aCAvIDI7XG4gICAgICAgIHZhciBob3ZlckNlbnRlclkgPSBib3VuZGluZ0JveC50b3AgKyBib3VuZGluZ0JveC5oZWlnaHQgLyAyO1xuXG4gICAgICAgIHZhciB0b29sdGlwID0gRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgIHg6IGhvdmVyQ2VudGVyWCAtIHJvb3RCQm94LmxlZnQsXG4gICAgICAgICAgICB5OiBob3ZlckNlbnRlclkgLSByb290QkJveC50b3AsXG4gICAgICAgICAgICBuYW1lOiBkMy5mb3JtYXQoZC52YWx1ZUZvcm1hdCkoZC5saW5rLnZhbHVlKSArIGQudmFsdWVTdWZmaXgsXG4gICAgICAgICAgICB0ZXh0OiBbXG4gICAgICAgICAgICAgICAgZC5saW5rLmxhYmVsIHx8ICcnLFxuICAgICAgICAgICAgICAgIHNvdXJjZUxhYmVsICsgZC5saW5rLnNvdXJjZS5sYWJlbCxcbiAgICAgICAgICAgICAgICB0YXJnZXRMYWJlbCArIGQubGluay50YXJnZXQubGFiZWxcbiAgICAgICAgICAgIF0uZmlsdGVyKHJlbmRlcmFibGVWYWx1ZVByZXNlbnQpLmpvaW4oJzxicj4nKSxcbiAgICAgICAgICAgIGNvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnYmdjb2xvcicpIHx8IENvbG9yLmFkZE9wYWNpdHkoZC50aW55Q29sb3JIdWUsIDEpLFxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IGNhc3RIb3Zlck9wdGlvbihvYmosICdib3JkZXJjb2xvcicpLFxuICAgICAgICAgICAgZm9udEZhbWlseTogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuZmFtaWx5JyksXG4gICAgICAgICAgICBmb250U2l6ZTogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuc2l6ZScpLFxuICAgICAgICAgICAgZm9udENvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnZm9udC5jb2xvcicpLFxuICAgICAgICAgICAgaWRlYWxBbGlnbjogZDMuZXZlbnQueCA8IGhvdmVyQ2VudGVyWCA/ICdyaWdodCcgOiAnbGVmdCdcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSxcbiAgICAgICAgICAgIG91dGVyQ29udGFpbmVyOiBmdWxsTGF5b3V0Ll9wYXBlci5ub2RlKCksXG4gICAgICAgICAgICBnZDogZ2RcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbWFrZVRyYW5zbHVjZW50KHRvb2x0aXAsIDAuNjUpO1xuICAgICAgICBtYWtlVGV4dENvbnRyYXN0eSh0b29sdGlwKTtcbiAgICB9O1xuXG4gICAgdmFyIGxpbmtVbmhvdmVyID0gZnVuY3Rpb24oZWxlbWVudCwgZCwgc2Fua2V5KSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcbiAgICAgICAgZDMuc2VsZWN0KGVsZW1lbnQpLmNhbGwobGlua05vbkhvdmVyZWRTdHlsZS5iaW5kKDAsIGQsIHNhbmtleSwgdHJ1ZSkpO1xuICAgICAgICBpZihkLmxpbmsudHJhY2UubGluay5ob3ZlcmluZm8gIT09ICdza2lwJykge1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7XG4gICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50LFxuICAgICAgICAgICAgICAgIHBvaW50czogW2QubGlua11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuICAgIH07XG5cbiAgICB2YXIgbm9kZVNlbGVjdCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICB2YXIgZXZ0ID0gZC5ub2RlO1xuICAgICAgICBldnQub3JpZ2luYWxFdmVudCA9IGQzLmV2ZW50O1xuICAgICAgICBnZC5faG92ZXJkYXRhID0gW2V2dF07XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVOb25Ib3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIEZ4LmNsaWNrKGdkLCB7IHRhcmdldDogdHJ1ZSB9KTtcbiAgICB9O1xuXG4gICAgdmFyIG5vZGVIb3ZlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVIb3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIGlmKGQubm9kZS50cmFjZS5ub2RlLmhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfaG92ZXInLCB7XG4gICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50LFxuICAgICAgICAgICAgICAgIHBvaW50czogW2Qubm9kZV1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBub2RlSG92ZXJGb2xsb3cgPSBmdW5jdGlvbihlbGVtZW50LCBkKSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgICAgICB2YXIgb2JqID0gZC5ub2RlLnRyYWNlLm5vZGU7XG4gICAgICAgIGlmKG9iai5ob3ZlcmluZm8gPT09ICdub25lJyB8fCBvYmouaG92ZXJpbmZvID09PSAnc2tpcCcpIHJldHVybjtcbiAgICAgICAgdmFyIG5vZGVSZWN0ID0gZDMuc2VsZWN0KGVsZW1lbnQpLnNlbGVjdCgnLicgKyBjbi5ub2RlUmVjdCk7XG4gICAgICAgIHZhciByb290QkJveCA9IGdkLl9mdWxsTGF5b3V0Ll9wYXBlcmRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBib3VuZGluZ0JveCA9IG5vZGVSZWN0Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIGhvdmVyQ2VudGVyWDAgPSBib3VuZGluZ0JveC5sZWZ0IC0gMiAtIHJvb3RCQm94LmxlZnQ7XG4gICAgICAgIHZhciBob3ZlckNlbnRlclgxID0gYm91bmRpbmdCb3gucmlnaHQgKyAyIC0gcm9vdEJCb3gubGVmdDtcbiAgICAgICAgdmFyIGhvdmVyQ2VudGVyWSA9IGJvdW5kaW5nQm94LnRvcCArIGJvdW5kaW5nQm94LmhlaWdodCAvIDQgLSByb290QkJveC50b3A7XG5cbiAgICAgICAgdmFyIHRvb2x0aXAgPSBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgeDA6IGhvdmVyQ2VudGVyWDAsXG4gICAgICAgICAgICB4MTogaG92ZXJDZW50ZXJYMSxcbiAgICAgICAgICAgIHk6IGhvdmVyQ2VudGVyWSxcbiAgICAgICAgICAgIG5hbWU6IGQzLmZvcm1hdChkLnZhbHVlRm9ybWF0KShkLm5vZGUudmFsdWUpICsgZC52YWx1ZVN1ZmZpeCxcbiAgICAgICAgICAgIHRleHQ6IFtcbiAgICAgICAgICAgICAgICBkLm5vZGUubGFiZWwsXG4gICAgICAgICAgICAgICAgaW5jb21pbmdMYWJlbCArIGQubm9kZS50YXJnZXRMaW5rcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgb3V0Z29pbmdMYWJlbCArIGQubm9kZS5zb3VyY2VMaW5rcy5sZW5ndGhcbiAgICAgICAgICAgIF0uZmlsdGVyKHJlbmRlcmFibGVWYWx1ZVByZXNlbnQpLmpvaW4oJzxicj4nKSxcbiAgICAgICAgICAgIGNvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnYmdjb2xvcicpIHx8IGQudGlueUNvbG9ySHVlLFxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IGNhc3RIb3Zlck9wdGlvbihvYmosICdib3JkZXJjb2xvcicpLFxuICAgICAgICAgICAgZm9udEZhbWlseTogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuZmFtaWx5JyksXG4gICAgICAgICAgICBmb250U2l6ZTogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuc2l6ZScpLFxuICAgICAgICAgICAgZm9udENvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnZm9udC5jb2xvcicpLFxuICAgICAgICAgICAgaWRlYWxBbGlnbjogJ2xlZnQnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXIubm9kZSgpLFxuICAgICAgICAgICAgZ2Q6IGdkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1ha2VUcmFuc2x1Y2VudCh0b29sdGlwLCAwLjg1KTtcbiAgICAgICAgbWFrZVRleHRDb250cmFzdHkodG9vbHRpcCk7XG4gICAgfTtcblxuICAgIHZhciBub2RlVW5ob3ZlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVOb25Ib3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIGlmKGQubm9kZS50cmFjZS5ub2RlLmhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfdW5ob3ZlcicsIHtcbiAgICAgICAgICAgICAgICBldmVudDogZDMuZXZlbnQsXG4gICAgICAgICAgICAgICAgcG9pbnRzOiBbZC5ub2RlXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBGeC5sb25lVW5ob3ZlcihmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSk7XG4gICAgfTtcblxuICAgIHJlbmRlcihcbiAgICAgICAgc3ZnLFxuICAgICAgICBjYWxjRGF0YSxcbiAgICAgICAge1xuICAgICAgICAgICAgd2lkdGg6IHNpemUudyxcbiAgICAgICAgICAgIGhlaWdodDogc2l6ZS5oLFxuICAgICAgICAgICAgbWFyZ2luOiB7XG4gICAgICAgICAgICAgICAgdDogc2l6ZS50LFxuICAgICAgICAgICAgICAgIHI6IHNpemUucixcbiAgICAgICAgICAgICAgICBiOiBzaXplLmIsXG4gICAgICAgICAgICAgICAgbDogc2l6ZS5sXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIGxpbmtFdmVudHM6IHtcbiAgICAgICAgICAgICAgICBob3ZlcjogbGlua0hvdmVyLFxuICAgICAgICAgICAgICAgIGZvbGxvdzogbGlua0hvdmVyRm9sbG93LFxuICAgICAgICAgICAgICAgIHVuaG92ZXI6IGxpbmtVbmhvdmVyLFxuICAgICAgICAgICAgICAgIHNlbGVjdDogbGlua1NlbGVjdFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5vZGVFdmVudHM6IHtcbiAgICAgICAgICAgICAgICBob3Zlcjogbm9kZUhvdmVyLFxuICAgICAgICAgICAgICAgIGZvbGxvdzogbm9kZUhvdmVyRm9sbG93LFxuICAgICAgICAgICAgICAgIHVuaG92ZXI6IG5vZGVVbmhvdmVyLFxuICAgICAgICAgICAgICAgIHNlbGVjdDogbm9kZVNlbGVjdFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgdGlueWNvbG9yID0gcmVxdWlyZSgndGlueWNvbG9yMicpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBkM3NhbmtleSA9IHJlcXVpcmUoJ0BwbG90bHkvZDMtc2Fua2V5Jykuc2Fua2V5O1xudmFyIGQzRm9yY2UgPSByZXF1aXJlKCdkMy1mb3JjZScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBpc0luZGV4ID0gTGliLmlzSW5kZXg7XG52YXIgZ3VwID0gcmVxdWlyZSgnLi4vLi4vbGliL2d1cCcpO1xudmFyIGtleUZ1biA9IGd1cC5rZXlGdW47XG52YXIgcmVwZWF0ID0gZ3VwLnJlcGVhdDtcbnZhciB1bndyYXAgPSBndXAudW53cmFwO1xuXG4vLyBiYXNpYyBkYXRhIHV0aWxpdGllc1xuXG5mdW5jdGlvbiBwZXJzaXN0T3JpZ2luYWxQbGFjZShub2Rlcykge1xuICAgIHZhciBpLCBkaXN0aW5jdExheWVyUG9zaXRpb25zID0gW107XG4gICAgZm9yKGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbm9kZXNbaV0ub3JpZ2luYWxYID0gbm9kZXNbaV0ueDtcbiAgICAgICAgbm9kZXNbaV0ub3JpZ2luYWxZID0gbm9kZXNbaV0ueTtcbiAgICAgICAgaWYoZGlzdGluY3RMYXllclBvc2l0aW9ucy5pbmRleE9mKG5vZGVzW2ldLngpID09PSAtMSkge1xuICAgICAgICAgICAgZGlzdGluY3RMYXllclBvc2l0aW9ucy5wdXNoKG5vZGVzW2ldLngpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGRpc3RpbmN0TGF5ZXJQb3NpdGlvbnMuc29ydChmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGEgLSBiO30pO1xuICAgIGZvcihpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5vZGVzW2ldLm9yaWdpbmFsTGF5ZXJJbmRleCA9IGRpc3RpbmN0TGF5ZXJQb3NpdGlvbnMuaW5kZXhPZihub2Rlc1tpXS5vcmlnaW5hbFgpO1xuICAgICAgICBub2Rlc1tpXS5vcmlnaW5hbExheWVyID0gbm9kZXNbaV0ub3JpZ2luYWxMYXllckluZGV4IC8gKGRpc3RpbmN0TGF5ZXJQb3NpdGlvbnMubGVuZ3RoIC0gMSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzYXZlQ3VycmVudERyYWdQb3NpdGlvbihkKSB7XG4gICAgZC5sYXN0RHJhZ2dlZFggPSBkLng7XG4gICAgZC5sYXN0RHJhZ2dlZFkgPSBkLnk7XG59XG5cbmZ1bmN0aW9uIHNhbWVMYXllcihkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG4pIHtyZXR1cm4gbi5ub2RlLm9yaWdpbmFsWCA9PT0gZC5ub2RlLm9yaWdpbmFsWDt9O1xufVxuXG5mdW5jdGlvbiBzd2l0Y2hUb0ZvcmNlRm9ybWF0KG5vZGVzKSB7XG4gICAgLy8gZm9yY2UgdXNlcyB4LCB5IGFzIGNlbnRlcnNcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbm9kZXNbaV0ueSA9IG5vZGVzW2ldLnkgKyBub2Rlc1tpXS5keSAvIDI7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzd2l0Y2hUb1NhbmtleUZvcm1hdChub2Rlcykge1xuICAgIC8vIHNhbmtleSB1c2VzIHgsIHkgYXMgdG9wIGxlZnRcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbm9kZXNbaV0ueSA9IG5vZGVzW2ldLnkgLSBub2Rlc1tpXS5keSAvIDI7XG4gICAgfVxufVxuXG4vLyB2aWV3IG1vZGVsc1xuXG5mdW5jdGlvbiBzYW5rZXlNb2RlbChsYXlvdXQsIGQsIHRyYWNlSW5kZXgpIHtcbiAgICB2YXIgdHJhY2UgPSB1bndyYXAoZCkudHJhY2U7XG4gICAgdmFyIGRvbWFpbiA9IHRyYWNlLmRvbWFpbjtcbiAgICB2YXIgbm9kZVNwZWMgPSB0cmFjZS5ub2RlO1xuICAgIHZhciBsaW5rU3BlYyA9IHRyYWNlLmxpbms7XG4gICAgdmFyIGFycmFuZ2VtZW50ID0gdHJhY2UuYXJyYW5nZW1lbnQ7XG4gICAgdmFyIGhvcml6b250YWwgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnO1xuICAgIHZhciBub2RlUGFkID0gdHJhY2Uubm9kZS5wYWQ7XG4gICAgdmFyIG5vZGVUaGlja25lc3MgPSB0cmFjZS5ub2RlLnRoaWNrbmVzcztcbiAgICB2YXIgbm9kZUxpbmVDb2xvciA9IHRyYWNlLm5vZGUubGluZS5jb2xvcjtcbiAgICB2YXIgbm9kZUxpbmVXaWR0aCA9IHRyYWNlLm5vZGUubGluZS53aWR0aDtcbiAgICB2YXIgbGlua0xpbmVDb2xvciA9IHRyYWNlLmxpbmsubGluZS5jb2xvcjtcbiAgICB2YXIgbGlua0xpbmVXaWR0aCA9IHRyYWNlLmxpbmsubGluZS53aWR0aDtcbiAgICB2YXIgdmFsdWVGb3JtYXQgPSB0cmFjZS52YWx1ZWZvcm1hdDtcbiAgICB2YXIgdmFsdWVTdWZmaXggPSB0cmFjZS52YWx1ZXN1ZmZpeDtcbiAgICB2YXIgdGV4dEZvbnQgPSB0cmFjZS50ZXh0Zm9udDtcblxuICAgIHZhciB3aWR0aCA9IGxheW91dC53aWR0aCAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKTtcbiAgICB2YXIgaGVpZ2h0ID0gbGF5b3V0LmhlaWdodCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcblxuICAgIHZhciBsaW5rcyA9IFtdO1xuICAgIHZhciBoYXNMaW5rQ29sb3JBcnJheSA9IGlzQXJyYXlPclR5cGVkQXJyYXkobGlua1NwZWMuY29sb3IpO1xuICAgIHZhciBsaW5rZWROb2RlcyA9IHt9O1xuXG4gICAgdmFyIG5vZGVDb3VudCA9IG5vZGVTcGVjLmxhYmVsLmxlbmd0aDtcbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsaW5rU3BlYy52YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdmFsID0gbGlua1NwZWMudmFsdWVbaV07XG4gICAgICAgIC8vIHJlbW92ZSBuZWdhdGl2ZSB2YWx1ZXMsIGJ1dCBrZWVwIHplcm9zIHdpdGggc3BlY2lhbCB0cmVhdG1lbnRcbiAgICAgICAgdmFyIHNvdXJjZSA9IGxpbmtTcGVjLnNvdXJjZVtpXTtcbiAgICAgICAgdmFyIHRhcmdldCA9IGxpbmtTcGVjLnRhcmdldFtpXTtcbiAgICAgICAgaWYoISh2YWwgPiAwICYmIGlzSW5kZXgoc291cmNlLCBub2RlQ291bnQpICYmIGlzSW5kZXgodGFyZ2V0LCBub2RlQ291bnQpKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBzb3VyY2UgPSArc291cmNlO1xuICAgICAgICB0YXJnZXQgPSArdGFyZ2V0O1xuICAgICAgICBsaW5rZWROb2Rlc1tzb3VyY2VdID0gbGlua2VkTm9kZXNbdGFyZ2V0XSA9IHRydWU7XG5cbiAgICAgICAgbGlua3MucHVzaCh7XG4gICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgIGxhYmVsOiBsaW5rU3BlYy5sYWJlbFtpXSxcbiAgICAgICAgICAgIGNvbG9yOiBoYXNMaW5rQ29sb3JBcnJheSA/IGxpbmtTcGVjLmNvbG9yW2ldIDogbGlua1NwZWMuY29sb3IsXG4gICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgIHRhcmdldDogdGFyZ2V0LFxuICAgICAgICAgICAgdmFsdWU6ICt2YWxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGhhc05vZGVDb2xvckFycmF5ID0gaXNBcnJheU9yVHlwZWRBcnJheShub2RlU3BlYy5jb2xvcik7XG4gICAgdmFyIG5vZGVzID0gW107XG4gICAgdmFyIHJlbW92ZWROb2RlcyA9IGZhbHNlO1xuICAgIHZhciBub2RlSW5kaWNlcyA9IHt9O1xuICAgIGZvcihpID0gMDsgaSA8IG5vZGVDb3VudDsgaSsrKSB7XG4gICAgICAgIGlmKGxpbmtlZE5vZGVzW2ldKSB7XG4gICAgICAgICAgICB2YXIgbCA9IG5vZGVTcGVjLmxhYmVsW2ldO1xuICAgICAgICAgICAgbm9kZUluZGljZXNbaV0gPSBub2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICBsYWJlbDogbCxcbiAgICAgICAgICAgICAgICBjb2xvcjogaGFzTm9kZUNvbG9yQXJyYXkgPyBub2RlU3BlYy5jb2xvcltpXSA6IG5vZGVTcGVjLmNvbG9yXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHJlbW92ZWROb2RlcyA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gbmVlZCB0byByZS1pbmRleCBsaW5rcyBub3csIHNpbmNlIHdlIGRpZG4ndCBwdXQgYWxsIHRoZSBub2RlcyBpblxuICAgIGlmKHJlbW92ZWROb2Rlcykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsaW5rcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlua3NbaV0uc291cmNlID0gbm9kZUluZGljZXNbbGlua3NbaV0uc291cmNlXTtcbiAgICAgICAgICAgIGxpbmtzW2ldLnRhcmdldCA9IG5vZGVJbmRpY2VzW2xpbmtzW2ldLnRhcmdldF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2Fua2V5ID0gZDNzYW5rZXkoKVxuICAgICAgICAuc2l6ZShob3Jpem9udGFsID8gW3dpZHRoLCBoZWlnaHRdIDogW2hlaWdodCwgd2lkdGhdKVxuICAgICAgICAubm9kZVdpZHRoKG5vZGVUaGlja25lc3MpXG4gICAgICAgIC5ub2RlUGFkZGluZyhub2RlUGFkKVxuICAgICAgICAubm9kZXMobm9kZXMpXG4gICAgICAgIC5saW5rcyhsaW5rcylcbiAgICAgICAgLmxheW91dChjLnNhbmtleUl0ZXJhdGlvbnMpO1xuXG4gICAgaWYoc2Fua2V5Lm5vZGVQYWRkaW5nKCkgPCBub2RlUGFkKSB7XG4gICAgICAgIExpYi53YXJuKCdub2RlLnBhZCB3YXMgcmVkdWNlZCB0byAnLCBzYW5rZXkubm9kZVBhZGRpbmcoKSwgJyB0byBmaXQgd2l0aGluIHRoZSBmaWd1cmUuJyk7XG4gICAgfVxuXG4gICAgdmFyIG5vZGUsIHNhbmtleU5vZGVzID0gc2Fua2V5Lm5vZGVzKCk7XG4gICAgZm9yKHZhciBuID0gMDsgbiA8IHNhbmtleU5vZGVzLmxlbmd0aDsgbisrKSB7XG4gICAgICAgIG5vZGUgPSBzYW5rZXlOb2Rlc1tuXTtcbiAgICAgICAgbm9kZS53aWR0aCA9IHdpZHRoO1xuICAgICAgICBub2RlLmhlaWdodCA9IGhlaWdodDtcbiAgICB9XG5cbiAgICBzd2l0Y2hUb0ZvcmNlRm9ybWF0KG5vZGVzKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleTogdHJhY2VJbmRleCxcbiAgICAgICAgdHJhY2U6IHRyYWNlLFxuICAgICAgICBndWlkOiBNYXRoLmZsb29yKDFlMTIgKiAoMSArIE1hdGgucmFuZG9tKCkpKSxcbiAgICAgICAgaG9yaXpvbnRhbDogaG9yaXpvbnRhbCxcbiAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgbm9kZVBhZDogbm9kZVBhZCxcbiAgICAgICAgbm9kZUxpbmVDb2xvcjogbm9kZUxpbmVDb2xvcixcbiAgICAgICAgbm9kZUxpbmVXaWR0aDogbm9kZUxpbmVXaWR0aCxcbiAgICAgICAgbGlua0xpbmVDb2xvcjogbGlua0xpbmVDb2xvcixcbiAgICAgICAgbGlua0xpbmVXaWR0aDogbGlua0xpbmVXaWR0aCxcbiAgICAgICAgdmFsdWVGb3JtYXQ6IHZhbHVlRm9ybWF0LFxuICAgICAgICB2YWx1ZVN1ZmZpeDogdmFsdWVTdWZmaXgsXG4gICAgICAgIHRleHRGb250OiB0ZXh0Rm9udCxcbiAgICAgICAgdHJhbnNsYXRlWDogZG9tYWluLnhbMF0gKiBsYXlvdXQud2lkdGggKyBsYXlvdXQubWFyZ2luLmwsXG4gICAgICAgIHRyYW5zbGF0ZVk6IGxheW91dC5oZWlnaHQgLSBkb21haW4ueVsxXSAqIGxheW91dC5oZWlnaHQgKyBsYXlvdXQubWFyZ2luLnQsXG4gICAgICAgIGRyYWdQYXJhbGxlbDogaG9yaXpvbnRhbCA/IGhlaWdodCA6IHdpZHRoLFxuICAgICAgICBkcmFnUGVycGVuZGljdWxhcjogaG9yaXpvbnRhbCA/IHdpZHRoIDogaGVpZ2h0LFxuICAgICAgICBub2Rlczogbm9kZXMsXG4gICAgICAgIGxpbmtzOiBsaW5rcyxcbiAgICAgICAgYXJyYW5nZW1lbnQ6IGFycmFuZ2VtZW50LFxuICAgICAgICBzYW5rZXk6IHNhbmtleSxcbiAgICAgICAgZm9yY2VMYXlvdXRzOiB7fSxcbiAgICAgICAgaW50ZXJhY3Rpb25TdGF0ZToge1xuICAgICAgICAgICAgZHJhZ0luUHJvZ3Jlc3M6IGZhbHNlLFxuICAgICAgICAgICAgaG92ZXJlZDogZmFsc2VcbiAgICAgICAgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGxpbmtNb2RlbCh1bmlxdWVLZXlzLCBkLCBsKSB7XG4gICAgdmFyIHRjID0gdGlueWNvbG9yKGwuY29sb3IpO1xuICAgIHZhciBiYXNpY0tleSA9IGwuc291cmNlLmxhYmVsICsgJ3wnICsgbC50YXJnZXQubGFiZWw7XG4gICAgdmFyIGZvdW5kS2V5ID0gdW5pcXVlS2V5c1tiYXNpY0tleV07XG4gICAgdW5pcXVlS2V5c1tiYXNpY0tleV0gPSAoZm91bmRLZXkgfHwgMCkgKyAxO1xuICAgIHZhciBrZXkgPSBiYXNpY0tleSArICdfXycgKyB1bmlxdWVLZXlzW2Jhc2ljS2V5XTtcblxuICAgIC8vIGZvciBldmVudCBkYXRhXG4gICAgbC50cmFjZSA9IGQudHJhY2U7XG4gICAgbC5jdXJ2ZU51bWJlciA9IGQudHJhY2UuaW5kZXg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgdHJhY2VJZDogZC5rZXksXG4gICAgICAgIGxpbms6IGwsXG4gICAgICAgIHRpbnlDb2xvckh1ZTogQ29sb3IudGlueVJHQih0YyksXG4gICAgICAgIHRpbnlDb2xvckFscGhhOiB0Yy5nZXRBbHBoYSgpLFxuICAgICAgICBsaW5rTGluZUNvbG9yOiBkLmxpbmtMaW5lQ29sb3IsXG4gICAgICAgIGxpbmtMaW5lV2lkdGg6IGQubGlua0xpbmVXaWR0aCxcbiAgICAgICAgdmFsdWVGb3JtYXQ6IGQudmFsdWVGb3JtYXQsXG4gICAgICAgIHZhbHVlU3VmZml4OiBkLnZhbHVlU3VmZml4LFxuICAgICAgICBzYW5rZXk6IGQuc2Fua2V5LFxuICAgICAgICBpbnRlcmFjdGlvblN0YXRlOiBkLmludGVyYWN0aW9uU3RhdGVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBub2RlTW9kZWwodW5pcXVlS2V5cywgZCwgbikge1xuICAgIHZhciB0YyA9IHRpbnljb2xvcihuLmNvbG9yKSxcbiAgICAgICAgem9uZVRoaWNrbmVzc1BhZCA9IGMubm9kZVBhZEFjcm9zcyxcbiAgICAgICAgem9uZUxlbmd0aFBhZCA9IGQubm9kZVBhZCAvIDIsXG4gICAgICAgIHZpc2libGVUaGlja25lc3MgPSBuLmR4LFxuICAgICAgICB2aXNpYmxlTGVuZ3RoID0gTWF0aC5tYXgoMC41LCBuLmR5KTtcblxuICAgIHZhciBiYXNpY0tleSA9IG4ubGFiZWw7XG4gICAgdmFyIGZvdW5kS2V5ID0gdW5pcXVlS2V5c1tiYXNpY0tleV07XG4gICAgdW5pcXVlS2V5c1tiYXNpY0tleV0gPSAoZm91bmRLZXkgfHwgMCkgKyAxO1xuICAgIHZhciBrZXkgPSBiYXNpY0tleSArICdfXycgKyB1bmlxdWVLZXlzW2Jhc2ljS2V5XTtcblxuICAgIC8vIGZvciBldmVudCBkYXRhXG4gICAgbi50cmFjZSA9IGQudHJhY2U7XG4gICAgbi5jdXJ2ZU51bWJlciA9IGQudHJhY2UuaW5kZXg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgdHJhY2VJZDogZC5rZXksXG4gICAgICAgIG5vZGU6IG4sXG4gICAgICAgIG5vZGVQYWQ6IGQubm9kZVBhZCxcbiAgICAgICAgbm9kZUxpbmVDb2xvcjogZC5ub2RlTGluZUNvbG9yLFxuICAgICAgICBub2RlTGluZVdpZHRoOiBkLm5vZGVMaW5lV2lkdGgsXG4gICAgICAgIHRleHRGb250OiBkLnRleHRGb250LFxuICAgICAgICBzaXplOiBkLmhvcml6b250YWwgPyBkLmhlaWdodCA6IGQud2lkdGgsXG4gICAgICAgIHZpc2libGVXaWR0aDogTWF0aC5jZWlsKHZpc2libGVUaGlja25lc3MpLFxuICAgICAgICB2aXNpYmxlSGVpZ2h0OiB2aXNpYmxlTGVuZ3RoLFxuICAgICAgICB6b25lWDogLXpvbmVUaGlja25lc3NQYWQsXG4gICAgICAgIHpvbmVZOiAtem9uZUxlbmd0aFBhZCxcbiAgICAgICAgem9uZVdpZHRoOiB2aXNpYmxlVGhpY2tuZXNzICsgMiAqIHpvbmVUaGlja25lc3NQYWQsXG4gICAgICAgIHpvbmVIZWlnaHQ6IHZpc2libGVMZW5ndGggKyAyICogem9uZUxlbmd0aFBhZCxcbiAgICAgICAgbGFiZWxZOiBkLmhvcml6b250YWwgPyBuLmR5IC8gMiArIDEgOiBuLmR4IC8gMiArIDEsXG4gICAgICAgIGxlZnQ6IG4ub3JpZ2luYWxMYXllciA9PT0gMSxcbiAgICAgICAgc2l6ZUFjcm9zczogZC53aWR0aCxcbiAgICAgICAgZm9yY2VMYXlvdXRzOiBkLmZvcmNlTGF5b3V0cyxcbiAgICAgICAgaG9yaXpvbnRhbDogZC5ob3Jpem9udGFsLFxuICAgICAgICBkYXJrQmFja2dyb3VuZDogdGMuZ2V0QnJpZ2h0bmVzcygpIDw9IDEyOCxcbiAgICAgICAgdGlueUNvbG9ySHVlOiBDb2xvci50aW55UkdCKHRjKSxcbiAgICAgICAgdGlueUNvbG9yQWxwaGE6IHRjLmdldEFscGhhKCksXG4gICAgICAgIHZhbHVlRm9ybWF0OiBkLnZhbHVlRm9ybWF0LFxuICAgICAgICB2YWx1ZVN1ZmZpeDogZC52YWx1ZVN1ZmZpeCxcbiAgICAgICAgc2Fua2V5OiBkLnNhbmtleSxcbiAgICAgICAgYXJyYW5nZW1lbnQ6IGQuYXJyYW5nZW1lbnQsXG4gICAgICAgIHVuaXF1ZU5vZGVMYWJlbFBhdGhJZDogW2QuZ3VpZCwgZC5rZXksIGtleV0uam9pbignICcpLFxuICAgICAgICBpbnRlcmFjdGlvblN0YXRlOiBkLmludGVyYWN0aW9uU3RhdGVcbiAgICB9O1xufVxuXG4vLyByZW5kZXJpbmcgc25pcHBldHNcblxuZnVuY3Rpb24gdXBkYXRlTm9kZVBvc2l0aW9ucyhzYW5rZXlOb2RlKSB7XG4gICAgc2Fua2V5Tm9kZVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQubm9kZS54LnRvRml4ZWQoMykgKyAnLCAnICsgKGQubm9kZS55IC0gZC5ub2RlLmR5IC8gMikudG9GaXhlZCgzKSArICcpJztcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIGxpbmtQYXRoKGQpIHtcbiAgICB2YXIgbm9kZXMgPSBkLnNhbmtleS5ub2RlcygpO1xuICAgIHN3aXRjaFRvU2Fua2V5Rm9ybWF0KG5vZGVzKTtcbiAgICB2YXIgcmVzdWx0ID0gZC5zYW5rZXkubGluaygpKGQubGluayk7XG4gICAgc3dpdGNoVG9Gb3JjZUZvcm1hdChub2Rlcyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gdXBkYXRlTm9kZVNoYXBlcyhzYW5rZXlOb2RlKSB7XG4gICAgc2Fua2V5Tm9kZS5jYWxsKHVwZGF0ZU5vZGVQb3NpdGlvbnMpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaGFwZXMoc2Fua2V5Tm9kZSwgc2Fua2V5TGluaykge1xuICAgIHNhbmtleU5vZGUuY2FsbCh1cGRhdGVOb2RlU2hhcGVzKTtcbiAgICBzYW5rZXlMaW5rLmF0dHIoJ2QnLCBsaW5rUGF0aCk7XG59XG5cbmZ1bmN0aW9uIHNpemVOb2RlKHJlY3QpIHtcbiAgICByZWN0LmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLnZpc2libGVXaWR0aDt9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge3JldHVybiBkLnZpc2libGVIZWlnaHQ7fSk7XG59XG5cbmZ1bmN0aW9uIHNhbGllbnRFbm91Z2goZCkge3JldHVybiBkLmxpbmsuZHkgPiAxIHx8IGQubGlua0xpbmVXaWR0aCA+IDA7fVxuXG5mdW5jdGlvbiBzYW5rZXlUcmFuc2Zvcm0oZCkge1xuICAgIHZhciBvZmZzZXQgPSAndHJhbnNsYXRlKCcgKyBkLnRyYW5zbGF0ZVggKyAnLCcgKyBkLnRyYW5zbGF0ZVkgKyAnKSc7XG4gICAgcmV0dXJuIG9mZnNldCArIChkLmhvcml6b250YWwgPyAnbWF0cml4KDEgMCAwIDEgMCAwKScgOiAnbWF0cml4KDAgMSAxIDAgMCAwKScpO1xufVxuXG5mdW5jdGlvbiBub2RlQ2VudGVyaW5nKGQpIHtcbiAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgKGQuaG9yaXpvbnRhbCA/IDAgOiBkLmxhYmVsWSkgKyAnICcgKyAoZC5ob3Jpem9udGFsID8gZC5sYWJlbFkgOiAwKSArICcpJztcbn1cblxuZnVuY3Rpb24gdGV4dEd1aWRlUGF0aChkKSB7XG4gICAgcmV0dXJuIGQzLnN2Zy5saW5lKCkoW1xuICAgICAgICBbZC5ob3Jpem9udGFsID8gKGQubGVmdCA/IC1kLnNpemVBY3Jvc3MgOiBkLnZpc2libGVXaWR0aCArIGMubm9kZVRleHRPZmZzZXRIb3Jpem9udGFsKSA6IGMubm9kZVRleHRPZmZzZXRIb3Jpem9udGFsLCAwXSxcbiAgICAgICAgW2QuaG9yaXpvbnRhbCA/IChkLmxlZnQgPyAtIGMubm9kZVRleHRPZmZzZXRIb3Jpem9udGFsIDogZC5zaXplQWNyb3NzKSA6IGQudmlzaWJsZUhlaWdodCAtIGMubm9kZVRleHRPZmZzZXRIb3Jpem9udGFsLCAwXVxuICAgIF0pO31cblxuZnVuY3Rpb24gc2Fua2V5SW52ZXJzZVRyYW5zZm9ybShkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCA/ICdtYXRyaXgoMSAwIDAgMSAwIDApJyA6ICdtYXRyaXgoMCAxIDEgMCAwIDApJzt9XG5mdW5jdGlvbiB0ZXh0RmxpcChkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCA/ICdzY2FsZSgxIDEpJyA6ICdzY2FsZSgtMSAxKSc7fVxuZnVuY3Rpb24gbm9kZVRleHRDb2xvcihkKSB7cmV0dXJuIGQuZGFya0JhY2tncm91bmQgJiYgIWQuaG9yaXpvbnRhbCA/ICdyZ2IoMjU1LDI1NSwyNTUpJyA6ICdyZ2IoMCwwLDApJzt9XG5mdW5jdGlvbiBub2RlVGV4dE9mZnNldChkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCAmJiBkLmxlZnQgPyAnMTAwJScgOiAnMCUnO31cblxuLy8gZXZlbnQgaGFuZGxpbmdcblxuZnVuY3Rpb24gYXR0YWNoUG9pbnRlckV2ZW50cyhzZWxlY3Rpb24sIHNhbmtleSwgZXZlbnRTZXQpIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLm9uKCcuYmFzaWMnLCBudWxsKSAvLyByZW1vdmUgYW55IHByZWV4aXN0aW5nIGhhbmRsZXJzXG4gICAgICAgIC5vbignbW91c2VvdmVyLmJhc2ljJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoIWQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIGV2ZW50U2V0LmhvdmVyKHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICAgICAgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQgPSBbdGhpcywgZF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignbW91c2Vtb3ZlLmJhc2ljJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoIWQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIGV2ZW50U2V0LmZvbGxvdyh0aGlzLCBkKTtcbiAgICAgICAgICAgICAgICBkLmludGVyYWN0aW9uU3RhdGUuaG92ZXJlZCA9IFt0aGlzLCBkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW91dC5iYXNpYycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKCFkLmludGVyYWN0aW9uU3RhdGUuZHJhZ0luUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICBldmVudFNldC51bmhvdmVyKHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICAgICAgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdjbGljay5iYXNpYycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRTZXQudW5ob3Zlcih0aGlzLCBkLCBzYW5rZXkpO1xuICAgICAgICAgICAgICAgIGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZighZC5pbnRlcmFjdGlvblN0YXRlLmRyYWdJblByb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRTZXQuc2VsZWN0KHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhdHRhY2hEcmFnSGFuZGxlcihzYW5rZXlOb2RlLCBzYW5rZXlMaW5rLCBjYWxsYmFja3MpIHtcblxuICAgIHZhciBkcmFnQmVoYXZpb3IgPSBkMy5iZWhhdmlvci5kcmFnKClcblxuICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5ub2RlO30pXG5cbiAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSByZXR1cm47XG4gICAgICAgICAgICBMaWIucmFpc2VUb1RvcCh0aGlzKTtcbiAgICAgICAgICAgIGQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcyA9IGQubm9kZTtcbiAgICAgICAgICAgIHNhdmVDdXJyZW50RHJhZ1Bvc2l0aW9uKGQubm9kZSk7XG4gICAgICAgICAgICBpZihkLmludGVyYWN0aW9uU3RhdGUuaG92ZXJlZCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrcy5ub2RlRXZlbnRzLnVuaG92ZXIuYXBwbHkoMCwgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQpO1xuICAgICAgICAgICAgICAgIGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnc25hcCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm9yY2VLZXkgPSBkLnRyYWNlSWQgKyAnfCcgKyBNYXRoLmZsb29yKGQubm9kZS5vcmlnaW5hbFgpO1xuICAgICAgICAgICAgICAgIGlmKGQuZm9yY2VMYXlvdXRzW2ZvcmNlS2V5XSkge1xuICAgICAgICAgICAgICAgICAgICBkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0uYWxwaGEoMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gbWFrZSBhIGZvcmNlTGF5b3V0IGlmZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgYXR0YWNoRm9yY2Uoc2Fua2V5Tm9kZSwgZm9yY2VLZXksIGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdGFydEZvcmNlKHNhbmtleU5vZGUsIHNhbmtleUxpbmssIGQsIGZvcmNlS2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcblxuICAgICAgICAub24oJ2RyYWcnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSByZXR1cm47XG4gICAgICAgICAgICB2YXIgeCA9IGQzLmV2ZW50Lng7XG4gICAgICAgICAgICB2YXIgeSA9IGQzLmV2ZW50Lnk7XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnc25hcCcpIHtcbiAgICAgICAgICAgICAgICBkLm5vZGUueCA9IHg7XG4gICAgICAgICAgICAgICAgZC5ub2RlLnkgPSB5O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnZnJlZWZvcm0nKSB7XG4gICAgICAgICAgICAgICAgICAgIGQubm9kZS54ID0geDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZC5ub2RlLnkgPSBNYXRoLm1heChkLm5vZGUuZHkgLyAyLCBNYXRoLm1pbihkLnNpemUgLSBkLm5vZGUuZHkgLyAyLCB5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzYXZlQ3VycmVudERyYWdQb3NpdGlvbihkLm5vZGUpO1xuICAgICAgICAgICAgaWYoZC5hcnJhbmdlbWVudCAhPT0gJ3NuYXAnKSB7XG4gICAgICAgICAgICAgICAgZC5zYW5rZXkucmVsYXlvdXQoKTtcbiAgICAgICAgICAgICAgICB1cGRhdGVTaGFwZXMoc2Fua2V5Tm9kZS5maWx0ZXIoc2FtZUxheWVyKGQpKSwgc2Fua2V5TGluayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgLm9uKCdkcmFnZW5kJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgZC5pbnRlcmFjdGlvblN0YXRlLmRyYWdJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgIH0pO1xuXG4gICAgc2Fua2V5Tm9kZVxuICAgICAgICAub24oJy5kcmFnJywgbnVsbCkgLy8gcmVtb3ZlIHBvc3NpYmxlIHByZXZpb3VzIGhhbmRsZXJzXG4gICAgICAgIC5jYWxsKGRyYWdCZWhhdmlvcik7XG59XG5cbmZ1bmN0aW9uIGF0dGFjaEZvcmNlKHNhbmtleU5vZGUsIGZvcmNlS2V5LCBkKSB7XG4gICAgdmFyIG5vZGVzID0gZC5zYW5rZXkubm9kZXMoKS5maWx0ZXIoZnVuY3Rpb24obikge3JldHVybiBuLm9yaWdpbmFsWCA9PT0gZC5ub2RlLm9yaWdpbmFsWDt9KTtcbiAgICBkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0gPSBkM0ZvcmNlLmZvcmNlU2ltdWxhdGlvbihub2RlcylcbiAgICAgICAgLmFscGhhRGVjYXkoMClcbiAgICAgICAgLmZvcmNlKCdjb2xsaWRlJywgZDNGb3JjZS5mb3JjZUNvbGxpZGUoKVxuICAgICAgICAgICAgLnJhZGl1cyhmdW5jdGlvbihuKSB7cmV0dXJuIG4uZHkgLyAyICsgZC5ub2RlUGFkIC8gMjt9KVxuICAgICAgICAgICAgLnN0cmVuZ3RoKDEpXG4gICAgICAgICAgICAuaXRlcmF0aW9ucyhjLmZvcmNlSXRlcmF0aW9ucykpXG4gICAgICAgIC5mb3JjZSgnY29uc3RyYWluJywgc25hcHBpbmdGb3JjZShzYW5rZXlOb2RlLCBmb3JjZUtleSwgbm9kZXMsIGQpKVxuICAgICAgICAuc3RvcCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydEZvcmNlKHNhbmtleU5vZGUsIHNhbmtleUxpbmssIGQsIGZvcmNlS2V5KSB7XG4gICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShmdW5jdGlvbiBmYXN0ZXIoKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjLmZvcmNlVGlja3NQZXJGcmFtZTsgaSsrKSB7XG4gICAgICAgICAgICBkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0udGljaygpO1xuICAgICAgICB9XG4gICAgICAgIGQuc2Fua2V5LnJlbGF5b3V0KCk7XG4gICAgICAgIHVwZGF0ZVNoYXBlcyhzYW5rZXlOb2RlLmZpbHRlcihzYW1lTGF5ZXIoZCkpLCBzYW5rZXlMaW5rKTtcbiAgICAgICAgaWYoZC5mb3JjZUxheW91dHNbZm9yY2VLZXldLmFscGhhKCkgPiAwKSB7XG4gICAgICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZhc3Rlcik7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc25hcHBpbmdGb3JjZShzYW5rZXlOb2RlLCBmb3JjZUtleSwgbm9kZXMsIGQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gX3NuYXBwaW5nRm9yY2UoKSB7XG4gICAgICAgIHZhciBtYXhWZWxvY2l0eSA9IDA7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIG4gPSBub2Rlc1tpXTtcbiAgICAgICAgICAgIGlmKG4gPT09IGQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcykgeyAvLyBjb25zdHJhaW4gbm9kZSBwb3NpdGlvbiB0byB0aGUgZHJhZ2dpbmcgcG9pbnRlclxuICAgICAgICAgICAgICAgIG4ueCA9IG4ubGFzdERyYWdnZWRYO1xuICAgICAgICAgICAgICAgIG4ueSA9IG4ubGFzdERyYWdnZWRZO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuLnZ4ID0gKG4ub3JpZ2luYWxYIC0gbi54KSAvIGMuZm9yY2VUaWNrc1BlckZyYW1lOyAvLyBzbmFwIHRvIGxheWVyXG4gICAgICAgICAgICAgICAgbi55ID0gTWF0aC5taW4oZC5zaXplIC0gbi5keSAvIDIsIE1hdGgubWF4KG4uZHkgLyAyLCBuLnkpKTsgLy8gY29uc3RyYWluIHRvIGV4dGVudFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWF4VmVsb2NpdHkgPSBNYXRoLm1heChtYXhWZWxvY2l0eSwgTWF0aC5hYnMobi52eCksIE1hdGguYWJzKG4udnkpKTtcbiAgICAgICAgfVxuICAgICAgICBpZighZC5pbnRlcmFjdGlvblN0YXRlLmRyYWdJblByb2dyZXNzICYmIG1heFZlbG9jaXR5IDwgMC4xICYmIGQuZm9yY2VMYXlvdXRzW2ZvcmNlS2V5XS5hbHBoYSgpID4gMCkge1xuICAgICAgICAgICAgZC5mb3JjZUxheW91dHNbZm9yY2VLZXldLmFscGhhKDApO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuLy8gc2NlbmUgZ3JhcGhcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3ZnLCBzdHlsZWREYXRhLCBsYXlvdXQsIGNhbGxiYWNrcykge1xuICAgIHZhciBzYW5rZXkgPSBzdmcuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Fua2V5KVxuICAgICAgICAuZGF0YShzdHlsZWREYXRhXG4gICAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihkKSB7cmV0dXJuIHVud3JhcChkKS50cmFjZS52aXNpYmxlO30pXG4gICAgICAgICAgICAgICAgLm1hcChzYW5rZXlNb2RlbC5iaW5kKG51bGwsIGxheW91dCkpLFxuICAgICAgICAgICAga2V5RnVuKTtcblxuICAgIHNhbmtleS5leGl0KClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgc2Fua2V5LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5LCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ2JveC1zaXppbmcnLCAnY29udGVudC1ib3gnKVxuICAgICAgICAuc3R5bGUoJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJylcbiAgICAgICAgLnN0eWxlKCdsZWZ0JywgMClcbiAgICAgICAgLnN0eWxlKCdzaGFwZS1yZW5kZXJpbmcnLCAnZ2VvbWV0cmljUHJlY2lzaW9uJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhdXRvJylcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleVRyYW5zZm9ybSk7XG5cbiAgICBzYW5rZXkudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleVRyYW5zZm9ybSk7XG5cbiAgICB2YXIgc2Fua2V5TGlua3MgPSBzYW5rZXkuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Fua2V5TGlua3MpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIHNhbmtleUxpbmtzLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5TGlua3MsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsICdub25lJyk7XG5cbiAgICB2YXIgc2Fua2V5TGluayA9IHNhbmtleUxpbmtzLnNlbGVjdEFsbCgnLicgKyBjLmNuLnNhbmtleUxpbmspXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB1bmlxdWVLZXlzID0ge307XG4gICAgICAgICAgICByZXR1cm4gZC5zYW5rZXkubGlua3MoKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24obCkge3JldHVybiBsLnZhbHVlO30pXG4gICAgICAgICAgICAgICAgLm1hcChsaW5rTW9kZWwuYmluZChudWxsLCB1bmlxdWVLZXlzLCBkKSk7XG4gICAgICAgIH0sIGtleUZ1bik7XG5cbiAgICBzYW5rZXlMaW5rLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5TGluaywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2QnLCBsaW5rUGF0aClcbiAgICAgICAgLmNhbGwoYXR0YWNoUG9pbnRlckV2ZW50cywgc2Fua2V5LCBjYWxsYmFja3MubGlua0V2ZW50cyk7XG5cbiAgICBzYW5rZXlMaW5rXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbGllbnRFbm91Z2goZCkgPyBDb2xvci50aW55UkdCKHRpbnljb2xvcihkLmxpbmtMaW5lQ29sb3IpKSA6IGQudGlueUNvbG9ySHVlO1xuICAgICAgICB9KVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS1vcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbGllbnRFbm91Z2goZCkgPyBDb2xvci5vcGFjaXR5KGQubGlua0xpbmVDb2xvcikgOiBkLnRpbnlDb2xvckFscGhhO1xuICAgICAgICB9KVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gc2FsaWVudEVub3VnaChkKSA/IGQubGlua0xpbmVXaWR0aCA6IDE7fSlcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgZnVuY3Rpb24oZCkge3JldHVybiBkLnRpbnlDb2xvckh1ZTt9KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwtb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC50aW55Q29sb3JBbHBoYTt9KTtcblxuICAgIHNhbmtleUxpbmsudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmF0dHIoJ2QnLCBsaW5rUGF0aCk7XG5cbiAgICBzYW5rZXlMaW5rLmV4aXQoKS50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICB2YXIgc2Fua2V5Tm9kZVNldCA9IHNhbmtleS5zZWxlY3RBbGwoJy4nICsgYy5jbi5zYW5rZXlOb2RlU2V0KVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBzYW5rZXlOb2RlU2V0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5Tm9kZVNldCwgdHJ1ZSk7XG5cbiAgICBzYW5rZXlOb2RlU2V0XG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgc3dpdGNoKGQuYXJyYW5nZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdmaXhlZCc6IHJldHVybiAnZGVmYXVsdCc7XG4gICAgICAgICAgICAgICAgY2FzZSAncGVycGVuZGljdWxhcic6IHJldHVybiAnbnMtcmVzaXplJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gJ21vdmUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHZhciBzYW5rZXlOb2RlID0gc2Fua2V5Tm9kZVNldC5zZWxlY3RBbGwoJy4nICsgYy5jbi5zYW5rZXlOb2RlKVxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgbm9kZXMgPSBkLnNhbmtleS5ub2RlcygpO1xuICAgICAgICAgICAgdmFyIHVuaXF1ZUtleXMgPSB7fTtcbiAgICAgICAgICAgIHBlcnNpc3RPcmlnaW5hbFBsYWNlKG5vZGVzKTtcbiAgICAgICAgICAgIHJldHVybiBub2Rlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24obikge3JldHVybiBuLnZhbHVlO30pXG4gICAgICAgICAgICAgICAgLm1hcChub2RlTW9kZWwuYmluZChudWxsLCB1bmlxdWVLZXlzLCBkKSk7XG4gICAgICAgIH0sIGtleUZ1bik7XG5cbiAgICBzYW5rZXlOb2RlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5Tm9kZSwgdHJ1ZSlcbiAgICAgICAgLmNhbGwodXBkYXRlTm9kZVBvc2l0aW9ucylcbiAgICAgICAgLmNhbGwoYXR0YWNoUG9pbnRlckV2ZW50cywgc2Fua2V5LCBjYWxsYmFja3Mubm9kZUV2ZW50cyk7XG5cbiAgICBzYW5rZXlOb2RlXG4gICAgICAgIC5jYWxsKGF0dGFjaERyYWdIYW5kbGVyLCBzYW5rZXlMaW5rLCBjYWxsYmFja3MpOyAvLyBoYXMgdG8gYmUgaGVyZSBhcyBpdCBiaW5kcyBzYW5rZXlMaW5rXG5cbiAgICBzYW5rZXlOb2RlLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5jYWxsKHVwZGF0ZU5vZGVQb3NpdGlvbnMpO1xuXG4gICAgc2Fua2V5Tm9kZS5leGl0KCkudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgdmFyIG5vZGVSZWN0ID0gc2Fua2V5Tm9kZS5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlUmVjdClcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVSZWN0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZVJlY3QsIHRydWUpXG4gICAgICAgIC5jYWxsKHNpemVOb2RlKTtcblxuICAgIG5vZGVSZWN0XG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLm5vZGVMaW5lV2lkdGg7fSlcbiAgICAgICAgLnN0eWxlKCdzdHJva2UnLCBmdW5jdGlvbihkKSB7cmV0dXJuIENvbG9yLnRpbnlSR0IodGlueWNvbG9yKGQubm9kZUxpbmVDb2xvcikpO30pXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLW9wYWNpdHknLCBmdW5jdGlvbihkKSB7cmV0dXJuIENvbG9yLm9wYWNpdHkoZC5ub2RlTGluZUNvbG9yKTt9KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudGlueUNvbG9ySHVlO30pXG4gICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgZnVuY3Rpb24oZCkge3JldHVybiBkLnRpbnlDb2xvckFscGhhO30pO1xuXG4gICAgbm9kZVJlY3QudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmNhbGwoc2l6ZU5vZGUpO1xuXG4gICAgdmFyIG5vZGVDYXB0dXJlID0gc2Fua2V5Tm9kZS5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlQ2FwdHVyZSlcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVDYXB0dXJlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZUNhcHR1cmUsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgMCk7XG5cbiAgICBub2RlQ2FwdHVyZVxuICAgICAgICAuYXR0cigneCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC56b25lWDt9KVxuICAgICAgICAuYXR0cigneScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC56b25lWTt9KVxuICAgICAgICAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuem9uZVdpZHRoO30pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuem9uZUhlaWdodDt9KTtcblxuICAgIHZhciBub2RlQ2VudGVyZWQgPSBzYW5rZXlOb2RlLnNlbGVjdEFsbCgnLicgKyBjLmNuLm5vZGVDZW50ZXJlZClcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVDZW50ZXJlZC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLm5vZGVDZW50ZXJlZCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIG5vZGVDZW50ZXJpbmcpO1xuXG4gICAgbm9kZUNlbnRlcmVkXG4gICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgbm9kZUNlbnRlcmluZyk7XG5cbiAgICB2YXIgbm9kZUxhYmVsR3VpZGUgPSBub2RlQ2VudGVyZWQuc2VsZWN0QWxsKCcuJyArIGMuY24ubm9kZUxhYmVsR3VpZGUpXG4gICAgICAgIC5kYXRhKHJlcGVhdCk7XG5cbiAgICBub2RlTGFiZWxHdWlkZS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLm5vZGVMYWJlbEd1aWRlLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudW5pcXVlTm9kZUxhYmVsUGF0aElkO30pXG4gICAgICAgIC5hdHRyKCdkJywgdGV4dEd1aWRlUGF0aClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleUludmVyc2VUcmFuc2Zvcm0pO1xuXG4gICAgbm9kZUxhYmVsR3VpZGVcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCdkJywgdGV4dEd1aWRlUGF0aClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleUludmVyc2VUcmFuc2Zvcm0pO1xuXG4gICAgdmFyIG5vZGVMYWJlbCA9IG5vZGVDZW50ZXJlZC5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlTGFiZWwpXG4gICAgICAgIC5kYXRhKHJlcGVhdCk7XG5cbiAgICBub2RlTGFiZWwuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5ub2RlTGFiZWwsIHRydWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCB0ZXh0RmxpcClcbiAgICAgICAgLnN0eWxlKCd1c2VyLXNlbGVjdCcsICdub25lJylcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCAnZGVmYXVsdCcpXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsICdibGFjaycpO1xuXG4gICAgbm9kZUxhYmVsXG4gICAgICAgIC5zdHlsZSgndGV4dC1zaGFkb3cnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5ob3Jpem9udGFsID8gJy0xcHggMXB4IDFweCAjZmZmLCAxcHggMXB4IDFweCAjZmZmLCAxcHggLTFweCAxcHggI2ZmZiwgLTFweCAtMXB4IDFweCAjZmZmJyA6ICdub25lJztcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge0RyYXdpbmcuZm9udChub2RlTGFiZWwsIGQudGV4dEZvbnQpO30pO1xuXG4gICAgbm9kZUxhYmVsXG4gICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgdGV4dEZsaXApO1xuXG4gICAgdmFyIG5vZGVMYWJlbFRleHRQYXRoID0gbm9kZUxhYmVsLnNlbGVjdEFsbCgnLicgKyBjLmNuLm5vZGVMYWJlbFRleHRQYXRoKVxuICAgICAgICAuZGF0YShyZXBlYXQpO1xuXG4gICAgbm9kZUxhYmVsVGV4dFBhdGguZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0UGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZUxhYmVsVGV4dFBhdGgsIHRydWUpXG4gICAgICAgIC5hdHRyKCdhbGlnbm1lbnQtYmFzZWxpbmUnLCAnbWlkZGxlJylcbiAgICAgICAgLmF0dHIoJ3hsaW5rOmhyZWYnLCBmdW5jdGlvbihkKSB7cmV0dXJuICcjJyArIGQudW5pcXVlTm9kZUxhYmVsUGF0aElkO30pXG4gICAgICAgIC5hdHRyKCdzdGFydE9mZnNldCcsIG5vZGVUZXh0T2Zmc2V0KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBub2RlVGV4dENvbG9yKTtcblxuICAgIG5vZGVMYWJlbFRleHRQYXRoXG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5ob3Jpem9udGFsIHx8IGQubm9kZS5keSA+IDUgPyBkLm5vZGUubGFiZWwgOiAnJzt9KVxuICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCAmJiBkLmxlZnQgPyAnZW5kJyA6ICdzdGFydCc7fSk7XG5cbiAgICBub2RlTGFiZWxUZXh0UGF0aFxuICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmF0dHIoJ3N0YXJ0T2Zmc2V0Jywgbm9kZVRleHRPZmZzZXQpXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsIG5vZGVUZXh0Q29sb3IpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cblxuLy8gYXJyYXlPayBhdHRyaWJ1dGVzLCBtZXJnZSB0aGVtIGludG8gY2FsY2RhdGEgYXJyYXlcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpIHtcblxuICAgIC8vIHNvIGVhY2ggcG9pbnQga25vd3Mgd2hpY2ggaW5kZXggaXQgb3JpZ2luYWxseSBjYW1lIGZyb21cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIGNkW2ldLmkgPSBpO1xuXG4gICAgTGliLm1lcmdlQXJyYXkodHJhY2UudGV4dCwgY2QsICd0eCcpO1xuICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLmhvdmVydGV4dCwgY2QsICdodHgnKTtcbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS5jdXN0b21kYXRhLCBjZCwgJ2RhdGEnKTtcbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS50ZXh0cG9zaXRpb24sIGNkLCAndHAnKTtcbiAgICBpZih0cmFjZS50ZXh0Zm9udCkge1xuICAgICAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS50ZXh0Zm9udC5zaXplLCBjZCwgJ3RzJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLnRleHRmb250LmNvbG9yLCBjZCwgJ3RjJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLnRleHRmb250LmZhbWlseSwgY2QsICd0ZicpO1xuICAgIH1cblxuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgaWYobWFya2VyKSB7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlci5zaXplLCBjZCwgJ21zJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlci5vcGFjaXR5LCBjZCwgJ21vJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlci5zeW1ib2wsIGNkLCAnbXgnKTtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLmNvbG9yLCBjZCwgJ21jJyk7XG5cbiAgICAgICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcbiAgICAgICAgaWYobWFya2VyLmxpbmUpIHtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlckxpbmUuY29sb3IsIGNkLCAnbWxjJyk7XG4gICAgICAgICAgICBMaWIubWVyZ2VBcnJheShtYXJrZXJMaW5lLndpZHRoLCBjZCwgJ21sdycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1hcmtlckdyYWRpZW50ID0gbWFya2VyLmdyYWRpZW50O1xuICAgICAgICBpZihtYXJrZXJHcmFkaWVudCAmJiBtYXJrZXJHcmFkaWVudC50eXBlICE9PSAnbm9uZScpIHtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlckdyYWRpZW50LnR5cGUsIGNkLCAnbWd0Jyk7XG4gICAgICAgICAgICBMaWIubWVyZ2VBcnJheShtYXJrZXJHcmFkaWVudC5jb2xvciwgY2QsICdtZ2MnKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvckF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yYmFyQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMnKTtcbnZhciBmb250QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBkYXNoID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXMnKS5kYXNoO1xuXG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4MDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHkwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkeToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzdGFja2dyb3VwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgb3JpZW50YXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ3YnLCAnaCddLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyb3Vwbm9ybToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWycnLCAnZnJhY3Rpb24nLCAncGVyY2VudCddLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhY2tnYXBzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2luZmVyIHplcm8nLCAnaW50ZXJwb2xhdGUnXSxcbiAgICAgICAgZGZsdDogJ2luZmVyIHplcm8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcnRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydsaW5lcycsICdtYXJrZXJzJywgJ3RleHQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydwb2ludHMnLCAnZmlsbHMnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAyLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2hhcGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydsaW5lYXInLCAnc3BsaW5lJywgJ2h2JywgJ3ZoJywgJ2h2aCcsICd2aHYnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdsaW5lYXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNtb290aGluZzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEuMyxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZGFzaDogZXh0ZW5kRmxhdCh7fSwgZGFzaCwge2VkaXRUeXBlOiAnc3R5bGUnfSksXG4gICAgICAgIHNpbXBsaWZ5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgY29ubmVjdGdhcHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY2xpcG9uYXhpczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgZmlsbDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydub25lJywgJ3RvemVyb3knLCAndG96ZXJveCcsICd0b25leHR5JywgJ3RvbmV4dHgnLCAndG9zZWxmJywgJ3RvbmV4dCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmaWxsY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1hcmtlcjogZXh0ZW5kRmxhdCh7XG4gICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBEcmF3aW5nLnN5bWJvbExpc3QsXG4gICAgICAgICAgICBkZmx0OiAnY2lyY2xlJyxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogNixcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG1heGRpc3BsYXllZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemVyZWY6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplbWluOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2l6ZW1vZGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydkaWFtZXRlcicsICdhcmVhJ10sXG4gICAgICAgICAgICBkZmx0OiAnZGlhbWV0ZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMsXG5cbiAgICAgICAgbGluZTogZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScsIHthbmltOiB0cnVlfSlcbiAgICAgICAgKSxcbiAgICAgICAgZ3JhZGllbnQ6IHtcbiAgICAgICAgICAgIHR5cGU6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBbJ3JhZGlhbCcsICdob3Jpem9udGFsJywgJ3ZlcnRpY2FsJywgJ25vbmUnXSxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdub25lJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXInLCB7YW5pbTogdHJ1ZX0pXG4gICAgKSxcbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaXplOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIHRleHRmb250OiB7XG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9LFxuICAgIHVuc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2l6ZToge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICB0ZXh0Zm9udDoge1xuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIHRleHRwb3NpdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3RvcCBsZWZ0JywgJ3RvcCBjZW50ZXInLCAndG9wIHJpZ2h0JyxcbiAgICAgICAgICAgICdtaWRkbGUgbGVmdCcsICdtaWRkbGUgY2VudGVyJywgJ21pZGRsZSByaWdodCcsXG4gICAgICAgICAgICAnYm90dG9tIGxlZnQnLCAnYm90dG9tIGNlbnRlcicsICdib3R0b20gcmlnaHQnXG4gICAgICAgIF0sXG4gICAgICAgIGRmbHQ6ICdtaWRkbGUgY2VudGVyJyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGV4dGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGNvbG9yRWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgcjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi9zdWJ0eXBlcycpO1xudmFyIGNhbGNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi9jb2xvcnNjYWxlX2NhbGMnKTtcbnZhciBhcnJheXNUb0NhbGNkYXRhID0gcmVxdWlyZSgnLi9hcnJheXNfdG9fY2FsY2RhdGEnKTtcbnZhciBjYWxjU2VsZWN0aW9uID0gcmVxdWlyZSgnLi9jYWxjX3NlbGVjdGlvbicpO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzIHx8ICd4Jyk7XG4gICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnlheGlzIHx8ICd5Jyk7XG4gICAgdmFyIHggPSB4YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd4Jyk7XG4gICAgdmFyIHkgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd5Jyk7XG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgdmFyIGlkcyA9IHRyYWNlLmlkcztcbiAgICB2YXIgc3RhY2tHcm91cE9wdHMgPSBnZXRTdGFja09wdHModHJhY2UsIGZ1bGxMYXlvdXQsIHhhLCB5YSk7XG4gICAgdmFyIGludGVycG9sYXRlR2FwcyA9IGZhbHNlO1xuICAgIHZhciBpc1YsIGksIGosIGssIGludGVycG9sYXRlLCB2YWxpO1xuXG4gICAgc2V0Rmlyc3RTY2F0dGVyKGZ1bGxMYXlvdXQsIHRyYWNlKTtcblxuICAgIHZhciB4QXR0ciA9ICd4JztcbiAgICB2YXIgeUF0dHIgPSAneSc7XG4gICAgdmFyIHBvc0F0dHI7XG4gICAgaWYoc3RhY2tHcm91cE9wdHMpIHtcbiAgICAgICAgc3RhY2tHcm91cE9wdHMudHJhY2VJbmRpY2VzLnB1c2godHJhY2UuaW5kZXgpO1xuICAgICAgICBpc1YgPSBzdGFja0dyb3VwT3B0cy5vcmllbnRhdGlvbiA9PT0gJ3YnO1xuICAgICAgICAvLyBzaXplLCBsaWtlIHdlIHVzZSBmb3IgYmFyXG4gICAgICAgIGlmKGlzVikge1xuICAgICAgICAgICAgeUF0dHIgPSAncyc7XG4gICAgICAgICAgICBwb3NBdHRyID0gJ3gnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgeEF0dHIgPSAncyc7XG4gICAgICAgICAgICBwb3NBdHRyID0gJ3knO1xuICAgICAgICB9XG4gICAgICAgIGludGVycG9sYXRlID0gc3RhY2tHcm91cE9wdHMuc3RhY2tnYXBzID09PSAnaW50ZXJwb2xhdGUnO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHBwYWQgPSBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgc2VyaWVzbGVuKTtcbiAgICAgICAgY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc2xlbjsgaSsrKSB7XG4gICAgICAgIHZhciBjZGkgPSBjZFtpXSA9IHt9O1xuICAgICAgICB2YXIgeFZhbGlkID0gaXNOdW1lcmljKHhbaV0pO1xuICAgICAgICB2YXIgeVZhbGlkID0gaXNOdW1lcmljKHlbaV0pO1xuICAgICAgICBpZih4VmFsaWQgJiYgeVZhbGlkKSB7XG4gICAgICAgICAgICBjZGlbeEF0dHJdID0geFtpXTtcbiAgICAgICAgICAgIGNkaVt5QXR0cl0gPSB5W2ldO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlJ3JlIHN0YWNraW5nIHdlIG5lZWQgdG8gaG9sZCBvbiB0byBhbGwgdmFsaWQgcG9zaXRpb25zXG4gICAgICAgIC8vIGV2ZW4gd2l0aCBpbnZhbGlkIHNpemVzXG4gICAgICAgIGVsc2UgaWYoc3RhY2tHcm91cE9wdHMgJiYgKGlzViA/IHhWYWxpZCA6IHlWYWxpZCkpIHtcbiAgICAgICAgICAgIGNkaVtwb3NBdHRyXSA9IGlzViA/IHhbaV0gOiB5W2ldO1xuICAgICAgICAgICAgY2RpLmdhcCA9IHRydWU7XG4gICAgICAgICAgICBpZihpbnRlcnBvbGF0ZSkge1xuICAgICAgICAgICAgICAgIGNkaS5zID0gQkFETlVNO1xuICAgICAgICAgICAgICAgIGludGVycG9sYXRlR2FwcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjZGkucyA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjZGlbeEF0dHJdID0gY2RpW3lBdHRyXSA9IEJBRE5VTTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGlkcykge1xuICAgICAgICAgICAgY2RpLmlkID0gU3RyaW5nKGlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY0NvbG9yc2NhbGUodHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIGlmKHN0YWNrR3JvdXBPcHRzKSB7XG4gICAgICAgIC8vIHJlbW92ZSBiYWQgcG9zaXRpb25zIGFuZCBzb3J0XG4gICAgICAgIC8vIG5vdGUgdGhhdCBvcmlnaW5hbCBpbmRpY2VzIGdldCBhZGRlZCB0byBjZCBpbiBhcnJheXNUb0NhbGNkYXRhXG4gICAgICAgIGkgPSAwO1xuICAgICAgICB3aGlsZShpIDwgY2QubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZihjZFtpXVtwb3NBdHRyXSA9PT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgY2Quc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpKys7XG4gICAgICAgIH1cblxuICAgICAgICBMaWIuc29ydChjZCwgZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIChhW3Bvc0F0dHJdIC0gYltwb3NBdHRyXSkgfHwgKGEuaSAtIGIuaSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGludGVycG9sYXRlR2Fwcykge1xuICAgICAgICAgICAgLy8gZmlyc3QgZmlsbCB0aGUgYmVnaW5uaW5nIHdpdGggY29uc3RhbnQgZnJvbSB0aGUgZmlyc3QgcG9pbnRcbiAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgd2hpbGUoaSA8IGNkLmxlbmd0aCAtIDEgJiYgY2RbaV0uZ2FwKSB7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsaSA9IGNkW2ldLnM7XG4gICAgICAgICAgICBpZighdmFsaSkgdmFsaSA9IGNkW2ldLnMgPSAwOyAvLyBpbiBjYXNlIG9mIG5vIGRhdGEgQVQgQUxMIGluIHRoaXMgdHJhY2UgLSB1c2UgMFxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgaTsgaisrKSB7XG4gICAgICAgICAgICAgICAgY2Rbal0ucyA9IHZhbGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0aGVuIGZpbGwgdGhlIGVuZCB3aXRoIGNvbnN0YW50IGZyb20gdGhlIGxhc3QgcG9pbnRcbiAgICAgICAgICAgIGsgPSBjZC5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUoayA+IGkgJiYgY2Rba10uZ2FwKSB7XG4gICAgICAgICAgICAgICAgay0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsaSA9IGNkW2tdLnM7XG4gICAgICAgICAgICBmb3IoaiA9IGNkLmxlbmd0aCAtIDE7IGogPiBrOyBqLS0pIHtcbiAgICAgICAgICAgICAgICBjZFtqXS5zID0gdmFsaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5vdyBpbnRlcnBvbGF0ZSBpbnRlcm5hbCBnYXBzIGxpbmVhcmx5XG4gICAgICAgICAgICB3aGlsZShpIDwgaykge1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICBpZihjZFtpXS5nYXApIHtcbiAgICAgICAgICAgICAgICAgICAgaiA9IGkgKyAxO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShjZFtqXS5nYXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zMCA9IGNkW2kgLSAxXVtwb3NBdHRyXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNpemUwID0gY2RbaSAtIDFdLnM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtID0gKGNkW2pdLnMgLSBzaXplMCkgLyAoY2Rbal1bcG9zQXR0cl0gLSBwb3MwKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoaSA8IGopIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNkW2ldLnMgPSBzaXplMCArIChjZFtpXVtwb3NBdHRyXSAtIHBvczApICogbTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjZDtcbn1cblxuZnVuY3Rpb24gY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpIHtcbiAgICB2YXIgc2VyaWVzbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4SWQgPSB4YS5faWQ7XG4gICAgdmFyIHlJZCA9IHlhLl9pZDtcbiAgICB2YXIgZmlyc3RTY2F0dGVyID0gZnVsbExheW91dC5fZmlyc3RTY2F0dGVyW2ZpcnN0U2NhdHRlckdyb3VwKHRyYWNlKV0gPT09IHRyYWNlLnVpZDtcbiAgICB2YXIgc3RhY2tPcmllbnRhdGlvbiA9IChnZXRTdGFja09wdHModHJhY2UsIGZ1bGxMYXlvdXQsIHhhLCB5YSkgfHwge30pLm9yaWVudGF0aW9uO1xuICAgIHZhciBmaWxsID0gdHJhY2UuZmlsbDtcblxuICAgIC8vIGNhbmNlbCBtaW5pbXVtIHRpY2sgc3BhY2luZ3MgKG9ubHkgYXBwbGllcyB0byBiYXJzIGFuZCBib3hlcylcbiAgICB4YS5fbWluRHRpY2sgPSAwO1xuICAgIHlhLl9taW5EdGljayA9IDA7XG5cbiAgICAvLyBjaGVjayB3aGV0aGVyIGJvdW5kcyBzaG91bGQgYmUgdGlnaHQsIHBhZGRlZCwgZXh0ZW5kZWQgdG8gemVyby4uLlxuICAgIC8vIG1vc3QgY2FzZXMgYm90aCBzaG91bGQgYmUgcGFkZGVkIG9uIGJvdGggZW5kcywgc28gc3RhcnQgd2l0aCB0aGF0LlxuICAgIHZhciB4T3B0aW9ucyA9IHtwYWRkZWQ6IHRydWV9O1xuICAgIHZhciB5T3B0aW9ucyA9IHtwYWRkZWQ6IHRydWV9O1xuXG4gICAgaWYocHBhZCkge1xuICAgICAgICB4T3B0aW9ucy5wcGFkID0geU9wdGlvbnMucHBhZCA9IHBwYWQ7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogdGV4dCBzaXplXG5cbiAgICB2YXIgb3BlbkVuZGVkID0gc2VyaWVzbGVuIDwgMiB8fCAoeFswXSAhPT0geFtzZXJpZXNsZW4gLSAxXSkgfHwgKHlbMF0gIT09IHlbc2VyaWVzbGVuIC0gMV0pO1xuXG4gICAgLy8gaW5jbHVkZSB6ZXJvICh0aWdodCkgYW5kIGV4dHJlbWVzIChwYWRkZWQpIGlmIGZpbGwgdG8gemVyb1xuICAgIC8vICh1bmxlc3MgdGhlIHNoYXBlIGlzIGNsb3NlZCwgdGhlbiBpdCdzIGp1c3QgZmlsbGluZyB0aGUgc2hhcGUgcmVnYXJkbGVzcylcbiAgICBpZihvcGVuRW5kZWQgJiYgKFxuICAgICAgICAoZmlsbCA9PT0gJ3RvemVyb3gnKSB8fFxuICAgICAgICAoKGZpbGwgPT09ICd0b25leHR4JykgJiYgKGZpcnN0U2NhdHRlciB8fCBzdGFja09yaWVudGF0aW9uID09PSAnaCcpKVxuICAgICkpIHtcbiAgICAgICAgeE9wdGlvbnMudG96ZXJvID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBpZiBubyBlcnJvciBiYXJzLCBtYXJrZXJzIG9yIHRleHQsIG9yIGZpbGwgdG8geT0wIHJlbW92ZSB4IHBhZGRpbmdcbiAgICBlbHNlIGlmKCEodHJhY2UuZXJyb3JfeSB8fCB7fSkudmlzaWJsZSAmJiAoXG4gICAgICAgICAgICAoZmlsbCA9PT0gJ3RvbmV4dHknIHx8IGZpbGwgPT09ICd0b3plcm95JykgfHxcbiAgICAgICAgICAgICghc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgJiYgIXN1YlR5cGVzLmhhc1RleHQodHJhY2UpKVxuICAgICAgICApKSB7XG4gICAgICAgIHhPcHRpb25zLnBhZGRlZCA9IGZhbHNlO1xuICAgICAgICB4T3B0aW9ucy5wcGFkID0gMDtcbiAgICB9XG5cbiAgICAvLyBub3cgY2hlY2sgZm9yIHkgLSByYXRoZXIgZGlmZmVyZW50IGxvZ2ljLCB0aG91Z2ggc3RpbGwgbW9zdGx5IHBhZGRlZCBib3RoIGVuZHNcbiAgICAvLyBpbmNsdWRlIHplcm8gKHRpZ2h0KSBhbmQgZXh0cmVtZXMgKHBhZGRlZCkgaWYgZmlsbCB0byB6ZXJvXG4gICAgLy8gKHVubGVzcyB0aGUgc2hhcGUgaXMgY2xvc2VkLCB0aGVuIGl0J3MganVzdCBmaWxsaW5nIHRoZSBzaGFwZSByZWdhcmRsZXNzKVxuICAgIGlmKG9wZW5FbmRlZCAmJiAoXG4gICAgICAgIChmaWxsID09PSAndG96ZXJveScpIHx8XG4gICAgICAgICgoZmlsbCA9PT0gJ3RvbmV4dHknKSAmJiAoZmlyc3RTY2F0dGVyIHx8IHN0YWNrT3JpZW50YXRpb24gPT09ICd2JykpXG4gICAgKSkge1xuICAgICAgICB5T3B0aW9ucy50b3plcm8gPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIHRpZ2h0IHk6IGFueSB4IGZpbGxcbiAgICBlbHNlIGlmKGZpbGwgPT09ICd0b25leHR4JyB8fCBmaWxsID09PSAndG96ZXJveCcpIHtcbiAgICAgICAgeU9wdGlvbnMucGFkZGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gTi5CLiBhc3ltbWV0cmljIHNwbG9tIHRyYWNlcyBjYWxsIHRoaXMgd2l0aCBibGFuayB7fSB4YSBvciB5YVxuICAgIGlmKHhJZCkgdHJhY2UuX2V4dHJlbWVzW3hJZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyh4YSwgeCwgeE9wdGlvbnMpO1xuICAgIGlmKHlJZCkgdHJhY2UuX2V4dHJlbWVzW3lJZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyh5YSwgeSwgeU9wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgc2VyaWVzbGVuKSB7XG4gICAgaWYoIXN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpKSByZXR1cm47XG5cbiAgICAvLyBUcmVhdCBzaXplIGxpa2UgeCBvciB5IGFycmF5cyAtLS0gUnVuIGQyY1xuICAgIC8vIHRoaXMgbmVlZHMgdG8gZ28gYmVmb3JlIHBwYWQgY29tcHV0YXRpb25cbiAgICB2YXIgbWFya2VyID0gdHJhY2UubWFya2VyO1xuICAgIHZhciBzaXplcmVmID0gMS42ICogKHRyYWNlLm1hcmtlci5zaXplcmVmIHx8IDEpO1xuICAgIHZhciBtYXJrZXJUcmFucztcblxuICAgIGlmKHRyYWNlLm1hcmtlci5zaXplbW9kZSA9PT0gJ2FyZWEnKSB7XG4gICAgICAgIG1hcmtlclRyYW5zID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KE1hdGguc3FydCgodiB8fCAwKSAvIHNpemVyZWYpLCAzKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYXJrZXJUcmFucyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgodiB8fCAwKSAvIHNpemVyZWYsIDMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5zaXplKSkge1xuICAgICAgICAvLyBJIHRyaWVkIGF1dG8tdHlwZSBidXQgY2F0ZWdvcnkgYW5kIGRhdGVzIGRvbnQgbWFrZSBtdWNoIHNlbnNlLlxuICAgICAgICB2YXIgYXggPSB7dHlwZTogJ2xpbmVhcid9O1xuICAgICAgICBBeGVzLnNldENvbnZlcnQoYXgpO1xuXG4gICAgICAgIHZhciBzID0gYXgubWFrZUNhbGNkYXRhKHRyYWNlLm1hcmtlciwgJ3NpemUnKTtcblxuICAgICAgICB2YXIgc2l6ZU91dCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VyaWVzbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHNpemVPdXRbaV0gPSBtYXJrZXJUcmFucyhzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2l6ZU91dDtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBtYXJrZXJUcmFucyhtYXJrZXIuc2l6ZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIG1hcmsgdGhlIGZpcnN0IHNjYXR0ZXIgdHJhY2UgZm9yIGVhY2ggc3VicGxvdFxuICogbm90ZSB0aGF0IHNjYXR0ZXIgYW5kIHNjYXR0ZXJnbCBlYWNoIGdldCB0aGVpciBvd24gZmlyc3QgdHJhY2VcbiAqIG5vdGUgYWxzbyB0aGF0IEknbSBkb2luZyB0aGlzIGR1cmluZyBjYWxjIHJhdGhlciB0aGFuIHN1cHBseURlZmF1bHRzXG4gKiBzbyBJIGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQgdHJhbnNmb3JtcywgYnV0IGlmIHdlIGV2ZXIgZG9cbiAqIHBlci10cmFjZSBjYWxjIHRoaXMgd2lsbCBnZXQgY29uZnVzZWQuXG4gKi9cbmZ1bmN0aW9uIHNldEZpcnN0U2NhdHRlcihmdWxsTGF5b3V0LCB0cmFjZSkge1xuICAgIHZhciBncm91cCA9IGZpcnN0U2NhdHRlckdyb3VwKHRyYWNlKTtcbiAgICB2YXIgZmlyc3RTY2F0dGVyID0gZnVsbExheW91dC5fZmlyc3RTY2F0dGVyO1xuICAgIGlmKCFmaXJzdFNjYXR0ZXJbZ3JvdXBdKSBmaXJzdFNjYXR0ZXJbZ3JvdXBdID0gdHJhY2UudWlkO1xufVxuXG5mdW5jdGlvbiBmaXJzdFNjYXR0ZXJHcm91cCh0cmFjZSkge1xuICAgIHZhciBzdGFja0dyb3VwID0gdHJhY2Uuc3RhY2tncm91cDtcbiAgICByZXR1cm4gdHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcyArIHRyYWNlLnR5cGUgK1xuICAgICAgICAoc3RhY2tHcm91cCA/ICctJyArIHN0YWNrR3JvdXAgOiAnJyk7XG59XG5cbmZ1bmN0aW9uIGdldFN0YWNrT3B0cyh0cmFjZSwgZnVsbExheW91dCwgeGEsIHlhKSB7XG4gICAgdmFyIHN0YWNrR3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwO1xuICAgIGlmKCFzdGFja0dyb3VwKSByZXR1cm47XG4gICAgdmFyIHN0YWNrT3B0cyA9IGZ1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHNbeGEuX2lkICsgeWEuX2lkXVtzdGFja0dyb3VwXTtcbiAgICB2YXIgc3RhY2tBeCA9IHN0YWNrT3B0cy5vcmllbnRhdGlvbiA9PT0gJ3YnID8geWEgOiB4YTtcbiAgICAvLyBBbGxvdyBzdGFja2luZyBvbmx5IG9uIG51bWVyaWMgYXhlc1xuICAgIC8vIGNhbGMgaXMgYSBsaXR0bGUgbGF0ZSB0byBiZSBmaWd1cmluZyB0aGlzIG91dCwgYnV0IGR1cmluZyBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIHdlIGRvbid0IGtub3cgdGhlIGF4aXMgdHlwZSB5ZXRcbiAgICBpZihzdGFja0F4LnR5cGUgPT09ICdsaW5lYXInIHx8IHN0YWNrQXgudHlwZSA9PT0gJ2xvZycpIHJldHVybiBzdGFja09wdHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhbGM6IGNhbGMsXG4gICAgY2FsY01hcmtlclNpemU6IGNhbGNNYXJrZXJTaXplLFxuICAgIGNhbGNBeGlzRXhwYW5zaW9uOiBjYWxjQXhpc0V4cGFuc2lvbixcbiAgICBzZXRGaXJzdFNjYXR0ZXI6IHNldEZpcnN0U2NhdHRlcixcbiAgICBnZXRTdGFja09wdHM6IGdldFN0YWNrT3B0c1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKSB7XG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2Uuc2VsZWN0ZWRwb2ludHMpKSB7XG4gICAgICAgIExpYi50YWdTZWxlY3RlZChjZCwgdHJhY2UpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhhc0NvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGFzX2NvbG9yc2NhbGUnKTtcbnZhciBjYWxjQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG5cbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4vc3VidHlwZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNNYXJrZXJDb2xvcnNjYWxlKHRyYWNlKSB7XG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2UpICYmIGhhc0NvbG9yc2NhbGUodHJhY2UsICdsaW5lJykpIHtcbiAgICAgICAgY2FsY0NvbG9yc2NhbGUodHJhY2UsIHRyYWNlLmxpbmUuY29sb3IsICdsaW5lJywgJ2MnKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKSkge1xuICAgICAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyJykpIHtcbiAgICAgICAgICAgIGNhbGNDb2xvcnNjYWxlKHRyYWNlLCB0cmFjZS5tYXJrZXIuY29sb3IsICdtYXJrZXInLCAnYycpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2UsICdtYXJrZXIubGluZScpKSB7XG4gICAgICAgICAgICBjYWxjQ29sb3JzY2FsZSh0cmFjZSwgdHJhY2UubWFya2VyLmxpbmUuY29sb3IsICdtYXJrZXIubGluZScsICdjJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFBUU19MSU5FU09OTFk6IDIwLFxuXG4gICAgLy8gZml4ZWQgcGFyYW1ldGVycyBvZiBjbHVzdGVyaW5nIGFuZCBjbGlwcGluZyBhbGdvcml0aG1zXG5cbiAgICAvLyBmcmFjdGlvbiBvZiBjbHVzdGVyaW5nIHRvbGVyYW5jZSBcInNvIGNsb3NlIHdlIGRvbid0IGV2ZW4gY29uc2lkZXIgaXQgYSBuZXcgcG9pbnRcIlxuICAgIG1pblRvbGVyYW5jZTogMC4yLFxuICAgIC8vIGhvdyBmYXN0IGRvZXMgY2x1c3RlcmluZyB0b2xlcmFuY2UgaW5jcmVhc2UgYXMgeW91IGdldCBhd2F5IGZyb20gdGhlIHZpc2libGUgcmVnaW9uXG4gICAgdG9sZXJhbmNlR3Jvd3RoOiAxMCxcblxuICAgIC8vIG51bWJlciBvZiB2aWV3cG9ydCBzaXplcyBhd2F5IGZyb20gdGhlIHZpc2libGUgcmVnaW9uXG4gICAgLy8gYXQgd2hpY2ggd2UgY2xpcCBhbGwgbGluZXMgdG8gdGhlIHBlcmltZXRlclxuICAgIG1heFNjcmVlbnNBd2F5OiAyMFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuXG4vKlxuICogU2NhdHRlciBzdGFja2luZyAmIG5vcm1hbGl6YXRpb24gY2FsY3VsYXRpb25zXG4gKiBydW5zIHBlciBzdWJwbG90LCBhbmQgY2FuIGhhbmRsZSBtdWx0aXBsZSBzdGFja2luZyBncm91cHNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyb3NzVHJhY2VDYWxjKGdkLCBwbG90aW5mbykge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuICAgIHZhciBzdWJwbG90ID0geGEuX2lkICsgeWEuX2lkO1xuXG4gICAgdmFyIHN1YnBsb3RTdGFja09wdHMgPSBnZC5fZnVsbExheW91dC5fc2NhdHRlclN0YWNrT3B0c1tzdWJwbG90XTtcbiAgICBpZighc3VicGxvdFN0YWNrT3B0cykgcmV0dXJuO1xuXG4gICAgdmFyIGNhbGNUcmFjZXMgPSBnZC5jYWxjZGF0YTtcblxuICAgIHZhciBpLCBqLCBrLCBpMiwgY2QsIGNkMCwgcG9zaiwgc3Vtaiwgbm9ybTtcbiAgICB2YXIgZ3JvdXBPcHRzLCBpbnRlcnBvbGF0ZSwgZ3JvdXBub3JtLCBwb3NBdHRyLCB2YWxBdHRyO1xuICAgIHZhciBoYXNBbnlCbGFua3M7XG5cbiAgICBmb3IodmFyIHN0YWNrR3JvdXAgaW4gc3VicGxvdFN0YWNrT3B0cykge1xuICAgICAgICBncm91cE9wdHMgPSBzdWJwbG90U3RhY2tPcHRzW3N0YWNrR3JvdXBdO1xuICAgICAgICB2YXIgaW5kaWNlcyA9IGdyb3VwT3B0cy50cmFjZUluZGljZXM7XG5cbiAgICAgICAgLy8gY2FuIGdldCBoZXJlIHdpdGggbm8gaW5kaWNlcyBpZiB0aGUgc3RhY2sgYXhpcyBpcyBub24tbnVtZXJpY1xuICAgICAgICBpZighaW5kaWNlcy5sZW5ndGgpIGNvbnRpbnVlO1xuXG4gICAgICAgIGludGVycG9sYXRlID0gZ3JvdXBPcHRzLnN0YWNrZ2FwcyA9PT0gJ2ludGVycG9sYXRlJztcbiAgICAgICAgZ3JvdXBub3JtID0gZ3JvdXBPcHRzLmdyb3Vwbm9ybTtcbiAgICAgICAgaWYoZ3JvdXBPcHRzLm9yaWVudGF0aW9uID09PSAndicpIHtcbiAgICAgICAgICAgIHBvc0F0dHIgPSAneCc7XG4gICAgICAgICAgICB2YWxBdHRyID0gJ3knO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcG9zQXR0ciA9ICd5JztcbiAgICAgICAgICAgIHZhbEF0dHIgPSAneCc7XG4gICAgICAgIH1cbiAgICAgICAgaGFzQW55QmxhbmtzID0gbmV3IEFycmF5KGluZGljZXMubGVuZ3RoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaGFzQW55QmxhbmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBoYXNBbnlCbGFua3NbaV0gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbGxlY3QgdGhlIGNvbXBsZXRlIHNldCBvZiBhbGwgcG9zaXRpb25zIGFjcm9zcyBBTEwgdHJhY2VzLlxuICAgICAgICAvLyBTdGFydCB3aXRoIHRoZSBmaXJzdCB0cmFjZSwgdGhlbiBpbnRlcmxlYXZlIGl0ZW1zIGZyb20gbGF0ZXIgdHJhY2VzXG4gICAgICAgIC8vIGFzIG5lZWRlZC5cbiAgICAgICAgLy8gRmlsbCBpbiBtaXNpbmcgaXRlbXMgYXMgd2UgZ28uXG4gICAgICAgIGNkMCA9IGNhbGNUcmFjZXNbaW5kaWNlc1swXV07XG4gICAgICAgIHZhciBhbGxQb3NpdGlvbnMgPSBuZXcgQXJyYXkoY2QwLmxlbmd0aCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkMC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYWxsUG9zaXRpb25zW2ldID0gY2QwW2ldW3Bvc0F0dHJdO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuXG4gICAgICAgICAgICBmb3IoaiA9IGsgPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwb3NqID0gY2Rbal1bcG9zQXR0cl07XG4gICAgICAgICAgICAgICAgZm9yKDsgcG9zaiA+IGFsbFBvc2l0aW9uc1trXSAmJiBrIDwgYWxsUG9zaXRpb25zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBjdXJyZW50IHRyYWNlIGlzIG1pc3NpbmcgYSBwb3NpdGlvbiBmcm9tIHNvbWUgcHJldmlvdXMgdHJhY2UocylcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0QmxhbmsoY2QsIGosIGFsbFBvc2l0aW9uc1trXSwgaSwgaGFzQW55QmxhbmtzLCBpbnRlcnBvbGF0ZSwgcG9zQXR0cik7XG4gICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYocG9zaiAhPT0gYWxsUG9zaXRpb25zW2tdKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHByZXZpb3VzIHRyYWNlKHMpIGFyZSBtaXNzaW5nIGEgcG9zaXRpb24gZnJvbSB0aGUgY3VycmVudCB0cmFjZVxuICAgICAgICAgICAgICAgICAgICBmb3IoaTIgPSAwOyBpMiA8IGk7IGkyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydEJsYW5rKGNhbGNUcmFjZXNbaW5kaWNlc1tpMl1dLCBrLCBwb3NqLCBpMiwgaGFzQW55QmxhbmtzLCBpbnRlcnBvbGF0ZSwgcG9zQXR0cik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYWxsUG9zaXRpb25zLnNwbGljZShrLCAwLCBwb3NqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKDsgayA8IGFsbFBvc2l0aW9ucy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGluc2VydEJsYW5rKGNkLCBqLCBhbGxQb3NpdGlvbnNba10sIGksIGhhc0FueUJsYW5rcywgaW50ZXJwb2xhdGUsIHBvc0F0dHIpO1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZXJpZXNsZW4gPSBhbGxQb3NpdGlvbnMubGVuZ3RoO1xuXG4gICAgICAgIC8vIHN0YWNrIChhbmQgbm9ybWFsaXplKSFcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QwLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBzdW1qID0gY2QwW2pdW3ZhbEF0dHJdID0gY2QwW2pdLnM7XG4gICAgICAgICAgICBmb3IoaSA9IDE7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuICAgICAgICAgICAgICAgIGNkWzBdLnRyYWNlLl9yYXdMZW5ndGggPSBjZFswXS50cmFjZS5fbGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNkWzBdLnRyYWNlLl9sZW5ndGggPSBzZXJpZXNsZW47XG4gICAgICAgICAgICAgICAgc3VtaiArPSBjZFtqXS5zO1xuICAgICAgICAgICAgICAgIGNkW2pdW3ZhbEF0dHJdID0gc3VtajtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZ3JvdXBub3JtKSB7XG4gICAgICAgICAgICAgICAgbm9ybSA9ICgoZ3JvdXBub3JtID09PSAnZnJhY3Rpb24nKSA/IHN1bWogOiAoc3VtaiAvIDEwMCkpIHx8IDE7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2RqID0gY2FsY1RyYWNlc1tpbmRpY2VzW2ldXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgY2RqW3ZhbEF0dHJdIC89IG5vcm07XG4gICAgICAgICAgICAgICAgICAgIGNkai5zTm9ybSA9IGNkai5zIC8gbm9ybTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhdXRvcmFuZ2VcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB2YXIgcHBhZCA9IGNhbGMuY2FsY01hcmtlclNpemUodHJhY2UsIHRyYWNlLl9yYXdMZW5ndGgpO1xuICAgICAgICAgICAgdmFyIGFycmF5UGFkID0gQXJyYXkuaXNBcnJheShwcGFkKTtcbiAgICAgICAgICAgIGlmKChwcGFkICYmIGhhc0FueUJsYW5rc1tpXSkgfHwgYXJyYXlQYWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHBhZFJhdyA9IHBwYWQ7XG4gICAgICAgICAgICAgICAgcHBhZCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHNlcmllc2xlbjsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBwYWRbal0gPSBjZFtqXS5nYXAgPyAwIDogKGFycmF5UGFkID8gcHBhZFJhd1tjZFtqXS5pXSA6IHBwYWRSYXcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB4ID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgICAgICAgICB2YXIgeSA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgc2VyaWVzbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICB4W2pdID0gY2Rbal0ueDtcbiAgICAgICAgICAgICAgICB5W2pdID0gY2Rbal0ueTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGMuY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpO1xuXG4gICAgICAgICAgICAvLyB3aGlsZSB3ZSdyZSBoZXJlIChpbiBhIGxvb3Agb3ZlciBhbGwgdHJhY2VzIGluIHRoZSBzdGFjaylcbiAgICAgICAgICAgIC8vIHJlY29yZCB0aGUgb3JpZW50YXRpb24sIHNvIGhvdmVyIGNhbiBmaW5kIGl0IGVhc2lseVxuICAgICAgICAgICAgY2RbMF0udC5vcmllbnRhdGlvbiA9IGdyb3VwT3B0cy5vcmllbnRhdGlvbjtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGluc2VydEJsYW5rKGNhbGNUcmFjZSwgaW5kZXgsIHBvc2l0aW9uLCB0cmFjZUluZGV4LCBoYXNBbnlCbGFua3MsIGludGVycG9sYXRlLCBwb3NBdHRyKSB7XG4gICAgaGFzQW55QmxhbmtzW3RyYWNlSW5kZXhdID0gdHJ1ZTtcbiAgICB2YXIgbmV3RW50cnkgPSB7XG4gICAgICAgIGk6IG51bGwsXG4gICAgICAgIGdhcDogdHJ1ZSxcbiAgICAgICAgczogMFxuICAgIH07XG4gICAgbmV3RW50cnlbcG9zQXR0cl0gPSBwb3NpdGlvbjtcbiAgICBjYWxjVHJhY2Uuc3BsaWNlKGluZGV4LCAwLCBuZXdFbnRyeSk7XG4gICAgLy8gRXZlbiBpZiB3ZSdyZSBub3QgaW50ZXJwb2xhdGluZywgaWYgb25lIHRyYWNlIGhhcyBtdWx0aXBsZVxuICAgIC8vIHZhbHVlcyBhdCB0aGUgc2FtZSBwb3NpdGlvbiBhbmQgdGhpcyB0cmFjZSBvbmx5IGhhcyBvbmUgdmFsdWUgdGhlcmUsXG4gICAgLy8gd2UganVzdCBkdXBsaWNhdGUgdGhhdCBvbmUgdmFsdWUgcmF0aGVyIHRoYW4gaW5zZXJ0IGEgemVyby5cbiAgICAvLyBXZSBhbHNvIG1ha2UgaXQgbG9vayBsaWtlIGEgcmVhbCBwb2ludCAtIGJlY2F1c2UgaXQncyBhbWJpZ3VvdXMgd2hpY2hcbiAgICAvLyBvbmUgcmVhbGx5IGlzIHRoZSByZWFsIG9uZSFcbiAgICBpZihpbmRleCAmJiBwb3NpdGlvbiA9PT0gY2FsY1RyYWNlW2luZGV4IC0gMV1bcG9zQXR0cl0pIHtcbiAgICAgICAgdmFyIHByZXZFbnRyeSA9IGNhbGNUcmFjZVtpbmRleCAtIDFdO1xuICAgICAgICBuZXdFbnRyeS5zID0gcHJldkVudHJ5LnM7XG4gICAgICAgIC8vIFRPRE8gaXMgaXQgZ29pbmcgdG8gY2F1c2UgYW55IHByb2JsZW1zIHRvIGhhdmUgbXVsdGlwbGVcbiAgICAgICAgLy8gY2FsY2RhdGEgcG9pbnRzIHdpdGggdGhlIHNhbWUgaW5kZXg/XG4gICAgICAgIG5ld0VudHJ5LmkgPSBwcmV2RW50cnkuaTtcbiAgICAgICAgbmV3RW50cnkuZ2FwID0gcHJldkVudHJ5LmdhcDtcbiAgICB9XG4gICAgZWxzZSBpZihpbnRlcnBvbGF0ZSkge1xuICAgICAgICBuZXdFbnRyeS5zID0gZ2V0SW50ZXJwKGNhbGNUcmFjZSwgaW5kZXgsIHBvc2l0aW9uLCBwb3NBdHRyKTtcbiAgICB9XG4gICAgaWYoIWluZGV4KSB7XG4gICAgICAgIC8vIHQgYW5kIHRyYWNlIG5lZWQgdG8gc3RheSBvbiB0aGUgZmlyc3QgY2QgZW50cnlcbiAgICAgICAgY2FsY1RyYWNlWzBdLnQgPSBjYWxjVHJhY2VbMV0udDtcbiAgICAgICAgY2FsY1RyYWNlWzBdLnRyYWNlID0gY2FsY1RyYWNlWzFdLnRyYWNlO1xuICAgICAgICBkZWxldGUgY2FsY1RyYWNlWzFdLnQ7XG4gICAgICAgIGRlbGV0ZSBjYWxjVHJhY2VbMV0udHJhY2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRJbnRlcnAoY2FsY1RyYWNlLCBpbmRleCwgcG9zaXRpb24sIHBvc0F0dHIpIHtcbiAgICB2YXIgcHQwID0gY2FsY1RyYWNlW2luZGV4IC0gMV07XG4gICAgdmFyIHB0MSA9IGNhbGNUcmFjZVtpbmRleCArIDFdO1xuICAgIGlmKCFwdDEpIHJldHVybiBwdDAucztcbiAgICBpZighcHQwKSByZXR1cm4gcHQxLnM7XG4gICAgcmV0dXJuIHB0MC5zICsgKHB0MS5zIC0gcHQwLnMpICogKHBvc2l0aW9uIC0gcHQwW3Bvc0F0dHJdKSAvIChwdDFbcG9zQXR0cl0gLSBwdDBbcG9zQXR0cl0pO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuLy8gcmVtb3ZlIG9wYWNpdHkgZm9yIGFueSB0cmFjZSB0aGF0IGhhcyBhIGZpbGwgb3IgaXMgZmlsbGVkIHRvXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyb3NzVHJhY2VEZWZhdWx0cyhmdWxsRGF0YSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2VpID0gZnVsbERhdGFbaV07XG4gICAgICAgIGlmKHRyYWNlaS50eXBlICE9PSAnc2NhdHRlcicpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBmaWxsaSA9IHRyYWNlaS5maWxsO1xuICAgICAgICBpZihmaWxsaSA9PT0gJ25vbmUnIHx8IGZpbGxpID09PSAndG9zZWxmJykgY29udGludWU7XG5cbiAgICAgICAgdHJhY2VpLm9wYWNpdHkgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYoZmlsbGkgPT09ICd0b25leHR5JyB8fCBmaWxsaSA9PT0gJ3RvbmV4dHgnKSB7XG4gICAgICAgICAgICBmb3IodmFyIGogPSBpIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICB2YXIgdHJhY2VqID0gZnVsbERhdGFbal07XG5cbiAgICAgICAgICAgICAgICBpZigodHJhY2VqLnR5cGUgPT09ICdzY2F0dGVyJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICh0cmFjZWoueGF4aXMgPT09IHRyYWNlaS54YXhpcykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICh0cmFjZWoueWF4aXMgPT09IHRyYWNlaS55YXhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VqLm9wYWNpdHkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4vc3VidHlwZXMnKTtcbnZhciBoYW5kbGVYWURlZmF1bHRzID0gcmVxdWlyZSgnLi94eV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVN0YWNrRGVmYXVsdHMgPSByZXF1aXJlKCcuL3N0YWNrX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSByZXF1aXJlKCcuL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IHJlcXVpcmUoJy4vbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzID0gcmVxdWlyZSgnLi9saW5lX3NoYXBlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGV4dERlZmF1bHRzID0gcmVxdWlyZSgnLi90ZXh0X2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHMgPSByZXF1aXJlKCcuL2ZpbGxjb2xvcl9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlWFlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIGlmKCFsZW4pIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcblxuICAgIGlmKCF0cmFjZU91dC52aXNpYmxlKSByZXR1cm47XG5cbiAgICB2YXIgc3RhY2tHcm91cE9wdHMgPSBoYW5kbGVTdGFja0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICB2YXIgZGVmYXVsdE1vZGUgPSAhc3RhY2tHcm91cE9wdHMgJiYgKGxlbiA8IGNvbnN0YW50cy5QVFNfTElORVNPTkxZKSA/XG4gICAgICAgICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcyc7XG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ21vZGUnLCBkZWZhdWx0TW9kZSk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICAgICAgY29lcmNlKCdsaW5lLnNpbXBsaWZ5Jyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtncmFkaWVudDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIHZhciBkZmx0SG92ZXJPbiA9IFtdO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkgfHwgc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgY29lcmNlKCdjbGlwb25heGlzJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLm1heGRpc3BsYXllZCcpO1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdwb2ludHMnKTtcbiAgICB9XG5cbiAgICAvLyBJdCdzIHBvc3NpYmxlIGZvciB0aGlzIGRlZmF1bHQgdG8gYmUgY2hhbmdlZCBieSBhIGxhdGVyIHRyYWNlLlxuICAgIC8vIFdlIGhhbmRsZSB0aGF0IGNhc2UgaW4gc29tZSBoYWNreSBjb2RlIGluc2lkZSBoYW5kbGVTdGFja0RlZmF1bHRzLlxuICAgIGNvZXJjZSgnZmlsbCcsIHN0YWNrR3JvdXBPcHRzID8gc3RhY2tHcm91cE9wdHMuZmlsbERmbHQgOiAnbm9uZScpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgICAgICBpZighc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZih0cmFjZU91dC5maWxsID09PSAndG9uZXh0JyB8fCB0cmFjZU91dC5maWxsID09PSAndG9zZWxmJykge1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdmaWxscycpO1xuICAgIH1cbiAgICBjb2VyY2UoJ2hvdmVyb24nLCBkZmx0SG92ZXJPbi5qb2luKCcrJykgfHwgJ3BvaW50cycpO1xuXG4gICAgdmFyIGVycm9yQmFyc1N1cHBseURlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3VwcGx5RGVmYXVsdHMnKTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3knfSk7XG4gICAgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwge2F4aXM6ICd4JywgaW5oZXJpdDogJ3knfSk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLyoqIEZpbGwgaG92ZXIgJ3BvaW50RGF0YScgY29udGFpbmVyIHdpdGggJ2NvcnJlY3QnIGhvdmVyIHRleHQgdmFsdWVcbiAqXG4gKiAtIElmIHRyYWNlIGhvdmVyaW5mbyBjb250YWlucyBhICd0ZXh0JyBmbGFnIGFuZCBob3ZlcnRleHQgaXMgbm90IHNldCxcbiAqICAgdGhlIHRleHQgZWxlbWVudHMgd2lsbCBiZSBzZWVuIGluIHRoZSBob3ZlciBsYWJlbHMuXG4gKlxuICogLSBJZiB0cmFjZSBob3ZlcmluZm8gY29udGFpbnMgYSAndGV4dCcgZmxhZyBhbmQgaG92ZXJ0ZXh0IGlzIHNldCxcbiAqICAgaG92ZXJ0ZXh0IHRha2VzIHByZWNlZGVuY2Ugb3ZlciB0ZXh0XG4gKiAgIGkuZS4gdGhlIGhvdmVyaW5mbyBlbGVtZW50cyB3aWxsIGJlIHNlZW4gaW4gdGhlIGhvdmVyIGxhYmVsc1xuICpcbiAqICBAcGFyYW0ge29iamVjdH0gY2FsY1B0XG4gKiAgQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiAgQHBhcmFtIHtvYmplY3QgfHwgYXJyYXl9IGNvbnRPdXQgKG11dGF0ZWQgaGVyZSlcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWxsSG92ZXJUZXh0KGNhbGNQdCwgdHJhY2UsIGNvbnRPdXQpIHtcbiAgICB2YXIgZmlsbCA9IEFycmF5LmlzQXJyYXkoY29udE91dCkgP1xuICAgICAgICBmdW5jdGlvbih2KSB7IGNvbnRPdXQucHVzaCh2KTsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKHYpIHsgY29udE91dC50ZXh0ID0gdjsgfTtcblxuICAgIHZhciBodHggPSBMaWIuZXh0cmFjdE9wdGlvbihjYWxjUHQsIHRyYWNlLCAnaHR4JywgJ2hvdmVydGV4dCcpO1xuICAgIGlmKGlzVmFsaWQoaHR4KSkgcmV0dXJuIGZpbGwoaHR4KTtcblxuICAgIHZhciB0eCA9IExpYi5leHRyYWN0T3B0aW9uKGNhbGNQdCwgdHJhY2UsICd0eCcsICd0ZXh0Jyk7XG4gICAgaWYoaXNWYWxpZCh0eCkpIHJldHVybiBmaWxsKHR4KTtcbn07XG5cbi8vIGFjY2VwdCBhbGwgdHJ1dGh5IHZhbHVlcyBhbmQgMCAod2hpY2ggZ2V0cyBjYXN0IHRvICcwJyBpbiB0aGUgaG92ZXIgbGFiZWxzKVxuZnVuY3Rpb24gaXNWYWxpZCh2KSB7XG4gICAgcmV0dXJuIHYgfHwgdiA9PT0gMDtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmlsbENvbG9yRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgY29lcmNlKSB7XG4gICAgdmFyIGluaGVyaXRDb2xvckZyb21NYXJrZXIgPSBmYWxzZTtcblxuICAgIGlmKHRyYWNlT3V0Lm1hcmtlcikge1xuICAgICAgICAvLyBkb24ndCB0cnkgdG8gaW5oZXJpdCBhIGNvbG9yIGFycmF5XG4gICAgICAgIHZhciBtYXJrZXJDb2xvciA9IHRyYWNlT3V0Lm1hcmtlci5jb2xvcixcbiAgICAgICAgICAgIG1hcmtlckxpbmVDb2xvciA9ICh0cmFjZU91dC5tYXJrZXIubGluZSB8fCB7fSkuY29sb3I7XG5cbiAgICAgICAgaWYobWFya2VyQ29sb3IgJiYgIWlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyQ29sb3IpKSB7XG4gICAgICAgICAgICBpbmhlcml0Q29sb3JGcm9tTWFya2VyID0gbWFya2VyQ29sb3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihtYXJrZXJMaW5lQ29sb3IgJiYgIWlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyTGluZUNvbG9yKSkge1xuICAgICAgICAgICAgaW5oZXJpdENvbG9yRnJvbU1hcmtlciA9IG1hcmtlckxpbmVDb2xvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvZXJjZSgnZmlsbGNvbG9yJywgQ29sb3IuYWRkT3BhY2l0eShcbiAgICAgICAgKHRyYWNlT3V0LmxpbmUgfHwge30pLmNvbG9yIHx8XG4gICAgICAgIGluaGVyaXRDb2xvckZyb21NYXJrZXIgfHxcbiAgICAgICAgZGVmYXVsdENvbG9yLCAwLjVcbiAgICApKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIHN1YnR5cGVzID0gcmVxdWlyZSgnLi9zdWJ0eXBlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpIHtcbiAgICB2YXIgbGMsIHRjO1xuXG4gICAgLy8gVE9ETzogdGV4dCBtb2Rlc1xuXG4gICAgaWYodHJhY2UubW9kZSA9PT0gJ2xpbmVzJykge1xuICAgICAgICBsYyA9IHRyYWNlLmxpbmUuY29sb3I7XG4gICAgICAgIHJldHVybiAobGMgJiYgQ29sb3Iub3BhY2l0eShsYykpID9cbiAgICAgICAgICAgIGxjIDogdHJhY2UuZmlsbGNvbG9yO1xuICAgIH1cbiAgICBlbHNlIGlmKHRyYWNlLm1vZGUgPT09ICdub25lJykge1xuICAgICAgICByZXR1cm4gdHJhY2UuZmlsbCA/IHRyYWNlLmZpbGxjb2xvciA6ICcnO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIG1jID0gZGkubWNjIHx8ICh0cmFjZS5tYXJrZXIgfHwge30pLmNvbG9yLFxuICAgICAgICAgICAgbWxjID0gZGkubWxjYyB8fCAoKHRyYWNlLm1hcmtlciB8fCB7fSkubGluZSB8fCB7fSkuY29sb3I7XG5cbiAgICAgICAgdGMgPSAobWMgJiYgQ29sb3Iub3BhY2l0eShtYykpID8gbWMgOlxuICAgICAgICAgICAgKG1sYyAmJiBDb2xvci5vcGFjaXR5KG1sYykgJiZcbiAgICAgICAgICAgICAgICAoZGkubWx3IHx8ICgodHJhY2UubWFya2VyIHx8IHt9KS5saW5lIHx8IHt9KS53aWR0aCkpID8gbWxjIDogJyc7XG5cbiAgICAgICAgaWYodGMpIHtcbiAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSB0aGUgcG9pbnRzIGFyZW4ndCBUT08gdHJhbnNwYXJlbnRcbiAgICAgICAgICAgIGlmKENvbG9yLm9wYWNpdHkodGMpIDwgMC4zKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIENvbG9yLmFkZE9wYWNpdHkodGMsIDAuMyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHJldHVybiB0YztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxjID0gKHRyYWNlLmxpbmUgfHwge30pLmNvbG9yO1xuICAgICAgICAgICAgcmV0dXJuIChsYyAmJiBDb2xvci5vcGFjaXR5KGxjKSAmJlxuICAgICAgICAgICAgICAgIHN1YnR5cGVzLmhhc0xpbmVzKHRyYWNlKSAmJiB0cmFjZS5saW5lLndpZHRoKSA/XG4gICAgICAgICAgICAgICAgICAgIGxjIDogdHJhY2UuZmlsbGNvbG9yO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEZ4ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBnZXRUcmFjZUNvbG9yID0gcmVxdWlyZSgnLi9nZXRfdHJhY2VfY29sb3InKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBmaWxsSG92ZXJUZXh0ID0gcmVxdWlyZSgnLi9maWxsX2hvdmVyX3RleHQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB4cHggPSB4YS5jMnAoeHZhbCk7XG4gICAgdmFyIHlweCA9IHlhLmMycCh5dmFsKTtcbiAgICB2YXIgcHQgPSBbeHB4LCB5cHhdO1xuICAgIHZhciBob3Zlcm9uID0gdHJhY2UuaG92ZXJvbiB8fCAnJztcbiAgICB2YXIgbWluUmFkID0gKHRyYWNlLm1vZGUuaW5kZXhPZignbWFya2VycycpICE9PSAtMSkgPyAzIDogMC41O1xuXG4gICAgLy8gbG9vayBmb3IgcG9pbnRzIHRvIGhvdmVyIG9uIGZpcnN0LCB0aGVuIHRha2UgZmlsbHMgb25seSBpZiB3ZVxuICAgIC8vIGRpZG4ndCBmaW5kIGEgcG9pbnRcbiAgICBpZihob3Zlcm9uLmluZGV4T2YoJ3BvaW50cycpICE9PSAtMSkge1xuICAgICAgICB2YXIgZHggPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgLy8gZHggYW5kIGR5IGFyZSB1c2VkIGluIGNvbXBhcmUgbW9kZXMgLSBoZXJlIHdlIHdhbnQgdG8gYWx3YXlzXG4gICAgICAgICAgICAvLyBwcmlvcml0aXplIHRoZSBjbG9zZXN0IGRhdGEgcG9pbnQsIGF0IGxlYXN0IGFzIGxvbmcgYXMgbWFya2VycyBhcmVcbiAgICAgICAgICAgIC8vIHRoZSBzYW1lIHNpemUgb3Igbm9uZXhpc3RlbnQsIGJ1dCBzdGlsbCB0cnkgdG8gcHJpb3JpdGl6ZSBzbWFsbCBtYXJrZXJzIHRvby5cbiAgICAgICAgICAgIHZhciByYWQgPSBNYXRoLm1heCgzLCBkaS5tcmMgfHwgMCk7XG4gICAgICAgICAgICB2YXIga2luayA9IDEgLSAxIC8gcmFkO1xuICAgICAgICAgICAgdmFyIGR4UmF3ID0gTWF0aC5hYnMoeGEuYzJwKGRpLngpIC0geHB4KTtcbiAgICAgICAgICAgIHZhciBkID0gKGR4UmF3IDwgcmFkKSA/IChraW5rICogZHhSYXcgLyByYWQpIDogKGR4UmF3IC0gcmFkICsga2luayk7XG4gICAgICAgICAgICByZXR1cm4gZDtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGR5ID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHZhciByYWQgPSBNYXRoLm1heCgzLCBkaS5tcmMgfHwgMCk7XG4gICAgICAgICAgICB2YXIga2luayA9IDEgLSAxIC8gcmFkO1xuICAgICAgICAgICAgdmFyIGR5UmF3ID0gTWF0aC5hYnMoeWEuYzJwKGRpLnkpIC0geXB4KTtcbiAgICAgICAgICAgIHJldHVybiAoZHlSYXcgPCByYWQpID8gKGtpbmsgKiBkeVJhdyAvIHJhZCkgOiAoZHlSYXcgLSByYWQgKyBraW5rKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGR4eSA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICAvLyBzY2F0dGVyIHBvaW50czogZC5tcmMgaXMgdGhlIGNhbGN1bGF0ZWQgbWFya2VyIHJhZGl1c1xuICAgICAgICAgICAgLy8gYWRqdXN0IHRoZSBkaXN0YW5jZSBzbyBpZiB5b3UncmUgaW5zaWRlIHRoZSBtYXJrZXIgaXRcbiAgICAgICAgICAgIC8vIGFsd2F5cyB3aWxsIHNob3cgdXAgcmVnYXJkbGVzcyBvZiBwb2ludCBzaXplLCBidXRcbiAgICAgICAgICAgIC8vIHByaW9yaXRpemUgc21hbGxlciBwb2ludHNcbiAgICAgICAgICAgIHZhciByYWQgPSBNYXRoLm1heChtaW5SYWQsIGRpLm1yYyB8fCAwKTtcbiAgICAgICAgICAgIHZhciBkeCA9IHhhLmMycChkaS54KSAtIHhweDtcbiAgICAgICAgICAgIHZhciBkeSA9IHlhLmMycChkaS55KSAtIHlweDtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpIC0gcmFkLCAxIC0gbWluUmFkIC8gcmFkKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGRpc3RmbiA9IEZ4LmdldERpc3RhbmNlRnVuY3Rpb24oaG92ZXJtb2RlLCBkeCwgZHksIGR4eSk7XG5cbiAgICAgICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdGZuLCBwb2ludERhdGEpO1xuXG4gICAgICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgICAgIGlmKHBvaW50RGF0YS5pbmRleCAhPT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgLy8gdGhlIGNsb3Nlc3QgZGF0YSBwb2ludFxuICAgICAgICAgICAgdmFyIGRpID0gY2RbcG9pbnREYXRhLmluZGV4XTtcbiAgICAgICAgICAgIHZhciB4YyA9IHhhLmMycChkaS54LCB0cnVlKTtcbiAgICAgICAgICAgIHZhciB5YyA9IHlhLmMycChkaS55LCB0cnVlKTtcbiAgICAgICAgICAgIHZhciByYWQgPSBkaS5tcmMgfHwgMTtcblxuICAgICAgICAgICAgLy8gbm93IHdlJ3JlIGRvbmUgdXNpbmcgdGhlIHdob2xlIGBjYWxjZGF0YWAgYXJyYXksIHJlcGxhY2UgdGhlXG4gICAgICAgICAgICAvLyBpbmRleCB3aXRoIHRoZSBvcmlnaW5hbCBpbmRleCAoaW4gY2FzZSBvZiBpbnNlcnRlZCBwb2ludCBmcm9tXG4gICAgICAgICAgICAvLyBzdGFja2VkIGFyZWEpXG4gICAgICAgICAgICBwb2ludERhdGEuaW5kZXggPSBkaS5pO1xuXG4gICAgICAgICAgICB2YXIgb3JpZW50YXRpb24gPSBjZFswXS50Lm9yaWVudGF0aW9uO1xuICAgICAgICAgICAgLy8gVE9ETzogZm9yIHNjYXR0ZXIgYW5kIGJhciwgb3B0aW9uIHRvIHNob3cgKHN1Yil0b3RhbHMgYW5kXG4gICAgICAgICAgICAvLyByYXcgZGF0YT8gQ3VycmVudGx5IHN0YWNrZWQgYW5kL29yIG5vcm1hbGl6ZWQgYmFycyBqdXN0IHNob3dcbiAgICAgICAgICAgIC8vIHRoZSBub3JtYWxpemVkIGluZGl2aWR1YWwgc2l6ZXMsIHNvIHRoYXQncyB3aGF0IEknbSBkb2luZyBoZXJlXG4gICAgICAgICAgICAvLyBmb3Igbm93LlxuICAgICAgICAgICAgdmFyIHNpemVWYWwgPSBvcmllbnRhdGlvbiAmJiAoZGkuc05vcm0gfHwgZGkucyk7XG4gICAgICAgICAgICB2YXIgeExhYmVsVmFsID0gKG9yaWVudGF0aW9uID09PSAnaCcpID8gc2l6ZVZhbCA6IGRpLng7XG4gICAgICAgICAgICB2YXIgeUxhYmVsVmFsID0gKG9yaWVudGF0aW9uID09PSAndicpID8gc2l6ZVZhbCA6IGRpLnk7XG5cbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHBvaW50RGF0YSwge1xuICAgICAgICAgICAgICAgIGNvbG9yOiBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSksXG5cbiAgICAgICAgICAgICAgICB4MDogeGMgLSByYWQsXG4gICAgICAgICAgICAgICAgeDE6IHhjICsgcmFkLFxuICAgICAgICAgICAgICAgIHhMYWJlbFZhbDogeExhYmVsVmFsLFxuXG4gICAgICAgICAgICAgICAgeTA6IHljIC0gcmFkLFxuICAgICAgICAgICAgICAgIHkxOiB5YyArIHJhZCxcbiAgICAgICAgICAgICAgICB5TGFiZWxWYWw6IHlMYWJlbFZhbCxcblxuICAgICAgICAgICAgICAgIHNwaWtlRGlzdGFuY2U6IGR4eShkaSlcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBmaWxsSG92ZXJUZXh0KGRpLCB0cmFjZSwgcG9pbnREYXRhKTtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZXJyb3JiYXJzJywgJ2hvdmVySW5mbycpKGRpLCB0cmFjZSwgcG9pbnREYXRhKTtcblxuICAgICAgICAgICAgcmV0dXJuIFtwb2ludERhdGFdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZXZlbiBpZiBob3Zlcm9uIGlzICdmaWxscycsIG9ubHkgdXNlIGl0IGlmIHdlIGhhdmUgcG9seWdvbnMgdG9vXG4gICAgaWYoaG92ZXJvbi5pbmRleE9mKCdmaWxscycpICE9PSAtMSAmJiB0cmFjZS5fcG9seWdvbnMpIHtcbiAgICAgICAgdmFyIHBvbHlnb25zID0gdHJhY2UuX3BvbHlnb25zO1xuICAgICAgICB2YXIgcG9seWdvbnNJbiA9IFtdO1xuICAgICAgICB2YXIgaW5zaWRlID0gZmFsc2U7XG4gICAgICAgIHZhciB4bWluID0gSW5maW5pdHk7XG4gICAgICAgIHZhciB4bWF4ID0gLUluZmluaXR5O1xuICAgICAgICB2YXIgeW1pbiA9IEluZmluaXR5O1xuICAgICAgICB2YXIgeW1heCA9IC1JbmZpbml0eTtcblxuICAgICAgICB2YXIgaSwgaiwgcG9seWdvbiwgcHRzLCB4Q3Jvc3MsIHgwLCB4MSwgeTAsIHkxO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHBvbHlnb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwb2x5Z29uID0gcG9seWdvbnNbaV07XG4gICAgICAgICAgICAvLyBUT0RPOiB0aGlzIGlzIG5vdCBnb2luZyB0byB3b3JrIHJpZ2h0IGZvciBjdXJ2ZWQgZWRnZXMsIGl0IHdpbGxcbiAgICAgICAgICAgIC8vIGFjdCBhcyB0aG91Z2ggdGhleSdyZSBzdHJhaWdodC4gVGhhdCdzIHByb2JhYmx5IGdvaW5nIHRvIG5lZWRcbiAgICAgICAgICAgIC8vIHRoZSBlbGVtZW50cyB0aGVtc2VsdmVzIHRvIGNhcHR1cmUgdGhlIGV2ZW50cy4gV29ydGggaXQ/XG4gICAgICAgICAgICBpZihwb2x5Z29uLmNvbnRhaW5zKHB0KSkge1xuICAgICAgICAgICAgICAgIGluc2lkZSA9ICFpbnNpZGU7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogbmVlZCBiZXR0ZXIgdGhhbiBqdXN0IHRoZSBvdmVyYWxsIGJvdW5kaW5nIGJveFxuICAgICAgICAgICAgICAgIHBvbHlnb25zSW4ucHVzaChwb2x5Z29uKTtcbiAgICAgICAgICAgICAgICB5bWluID0gTWF0aC5taW4oeW1pbiwgcG9seWdvbi55bWluKTtcbiAgICAgICAgICAgICAgICB5bWF4ID0gTWF0aC5tYXgoeW1heCwgcG9seWdvbi55bWF4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGluc2lkZSkge1xuICAgICAgICAgICAgLy8gY29uc3RyYWluIHltaW4vbWF4IHRvIHRoZSB2aXNpYmxlIHBsb3QsIHNvIHRoZSBsYWJlbCBnb2VzXG4gICAgICAgICAgICAvLyBhdCB0aGUgbWlkZGxlIG9mIHRoZSBwaWVjZSB5b3UgY2FuIHNlZVxuICAgICAgICAgICAgeW1pbiA9IE1hdGgubWF4KHltaW4sIDApO1xuICAgICAgICAgICAgeW1heCA9IE1hdGgubWluKHltYXgsIHlhLl9sZW5ndGgpO1xuXG4gICAgICAgICAgICAvLyBmaW5kIHRoZSBvdmVyYWxsIGxlZnQtbW9zdCBhbmQgcmlnaHQtbW9zdCBwb2ludHMgb2YgdGhlXG4gICAgICAgICAgICAvLyBwb2x5Z29uKHMpIHdlJ3JlIGluc2lkZSBhdCB0aGVpciBjb21iaW5lZCB2ZXJ0aWNhbCBtaWRwb2ludC5cbiAgICAgICAgICAgIC8vIFRoaXMgaXMgd2hlcmUgd2Ugd2lsbCBkcmF3IHRoZSBob3ZlciBsYWJlbC5cbiAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIG1pZ2h0IG5vdCBiZSB0aGUgdmVydGljYWwgbWlkcG9pbnQgb2YgdGhlXG4gICAgICAgICAgICAvLyB3aG9sZSB0cmFjZSwgaWYgaXQncyBkaXNqb2ludC5cbiAgICAgICAgICAgIHZhciB5QXZnID0gKHltaW4gKyB5bWF4KSAvIDI7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwb2x5Z29uc0luLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHRzID0gcG9seWdvbnNJbltpXS5wdHM7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAxOyBqIDwgcHRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHkwID0gcHRzW2ogLSAxXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgeTEgPSBwdHNbal1bMV07XG4gICAgICAgICAgICAgICAgICAgIGlmKCh5MCA+IHlBdmcpICE9PSAoeTEgPj0geUF2ZykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgwID0gcHRzW2ogLSAxXVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgxID0gcHRzW2pdWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoeTEgLSB5MCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhDcm9zcyA9IHgwICsgKHgxIC0geDApICogKHlBdmcgLSB5MCkgLyAoeTEgLSB5MCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1pbiA9IE1hdGgubWluKHhtaW4sIHhDcm9zcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1heCA9IE1hdGgubWF4KHhtYXgsIHhDcm9zcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGNvbnN0cmFpbiB4bWluL21heCB0byB0aGUgdmlzaWJsZSBwbG90IG5vdyB0b29cbiAgICAgICAgICAgIHhtaW4gPSBNYXRoLm1heCh4bWluLCAwKTtcbiAgICAgICAgICAgIHhtYXggPSBNYXRoLm1pbih4bWF4LCB4YS5fbGVuZ3RoKTtcblxuICAgICAgICAgICAgLy8gZ2V0IG9ubHkgZmlsbCBvciBsaW5lIGNvbG9yIGZvciB0aGUgaG92ZXIgY29sb3JcbiAgICAgICAgICAgIHZhciBjb2xvciA9IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICAgICAgaWYoQ29sb3Iub3BhY2l0eSh0cmFjZS5maWxsY29sb3IpKSBjb2xvciA9IHRyYWNlLmZpbGxjb2xvcjtcbiAgICAgICAgICAgIGVsc2UgaWYoQ29sb3Iub3BhY2l0eSgodHJhY2UubGluZSB8fCB7fSkuY29sb3IpKSB7XG4gICAgICAgICAgICAgICAgY29sb3IgPSB0cmFjZS5saW5lLmNvbG9yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChwb2ludERhdGEsIHtcbiAgICAgICAgICAgICAgICAvLyBuZXZlciBsZXQgYSAyRCBvdmVycmlkZSAxRCB0eXBlIGFzIGNsb3Nlc3QgcG9pbnRcbiAgICAgICAgICAgICAgICAvLyBhbHNvOiBubyBzcGlrZURpc3RhbmNlLCBpdCdzIG5vdCBhbGxvd2VkIGZvciBmaWxsc1xuICAgICAgICAgICAgICAgIGRpc3RhbmNlOiBwb2ludERhdGEubWF4SG92ZXJEaXN0YW5jZSxcbiAgICAgICAgICAgICAgICB4MDogeG1pbixcbiAgICAgICAgICAgICAgICB4MTogeG1heCxcbiAgICAgICAgICAgICAgICB5MDogeUF2ZyxcbiAgICAgICAgICAgICAgICB5MTogeUF2ZyxcbiAgICAgICAgICAgICAgICBjb2xvcjogY29sb3JcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBkZWxldGUgcG9pbnREYXRhLmluZGV4O1xuXG4gICAgICAgICAgICBpZih0cmFjZS50ZXh0ICYmICFBcnJheS5pc0FycmF5KHRyYWNlLnRleHQpKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLnRleHQgPSBTdHJpbmcodHJhY2UudGV4dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHBvaW50RGF0YS50ZXh0ID0gdHJhY2UubmFtZTtcblxuICAgICAgICAgICAgcmV0dXJuIFtwb2ludERhdGFdO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2NhdHRlciA9IHt9O1xuXG52YXIgc3VidHlwZXMgPSByZXF1aXJlKCcuL3N1YnR5cGVzJyk7XG5TY2F0dGVyLmhhc0xpbmVzID0gc3VidHlwZXMuaGFzTGluZXM7XG5TY2F0dGVyLmhhc01hcmtlcnMgPSBzdWJ0eXBlcy5oYXNNYXJrZXJzO1xuU2NhdHRlci5oYXNUZXh0ID0gc3VidHlwZXMuaGFzVGV4dDtcblNjYXR0ZXIuaXNCdWJibGUgPSBzdWJ0eXBlcy5pc0J1YmJsZTtcblxuU2NhdHRlci5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5TY2F0dGVyLnN1cHBseURlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuU2NhdHRlci5jcm9zc1RyYWNlRGVmYXVsdHMgPSByZXF1aXJlKCcuL2Nyb3NzX3RyYWNlX2RlZmF1bHRzJyk7XG5TY2F0dGVyLmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKS5jYWxjO1xuU2NhdHRlci5jcm9zc1RyYWNlQ2FsYyA9IHJlcXVpcmUoJy4vY3Jvc3NfdHJhY2VfY2FsYycpO1xuU2NhdHRlci5hcnJheXNUb0NhbGNkYXRhID0gcmVxdWlyZSgnLi9hcnJheXNfdG9fY2FsY2RhdGEnKTtcblNjYXR0ZXIucGxvdCA9IHJlcXVpcmUoJy4vcGxvdCcpO1xuU2NhdHRlci5jb2xvcmJhciA9IHJlcXVpcmUoJy4vbWFya2VyX2NvbG9yYmFyJyk7XG5TY2F0dGVyLnN0eWxlID0gcmVxdWlyZSgnLi9zdHlsZScpLnN0eWxlO1xuU2NhdHRlci5zdHlsZU9uU2VsZWN0ID0gcmVxdWlyZSgnLi9zdHlsZScpLnN0eWxlT25TZWxlY3Q7XG5TY2F0dGVyLmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuU2NhdHRlci5zZWxlY3RQb2ludHMgPSByZXF1aXJlKCcuL3NlbGVjdCcpO1xuU2NhdHRlci5hbmltYXRhYmxlID0gdHJ1ZTtcblxuU2NhdHRlci5tb2R1bGVUeXBlID0gJ3RyYWNlJztcblNjYXR0ZXIubmFtZSA9ICdzY2F0dGVyJztcblNjYXR0ZXIuYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcblNjYXR0ZXIuY2F0ZWdvcmllcyA9IFtcbiAgICAnY2FydGVzaWFuJywgJ3N2ZycsICdzeW1ib2xzJywgJ2Vycm9yQmFyc09LJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlci1saWtlJyxcbiAgICAnem9vbVNjYWxlJ1xuXTtcblNjYXR0ZXIubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU2NhdHRlcjtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9saWInKS5pc0FycmF5T3JUeXBlZEFycmF5O1xudmFyIGhhc0NvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGFzX2NvbG9yc2NhbGUnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBsaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICB2YXIgbWFya2VyQ29sb3IgPSAodHJhY2VJbi5tYXJrZXIgfHwge30pLmNvbG9yO1xuXG4gICAgY29lcmNlKCdsaW5lLmNvbG9yJywgZGVmYXVsdENvbG9yKTtcblxuICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2VJbiwgJ2xpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbGluZS4nLCBjTGV0dGVyOiAnYycsIG5vU2NhbGU6IHRydWV9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbGluZUNvbG9yRGZsdCA9IChpc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlckNvbG9yKSA/IGZhbHNlIDogbWFya2VyQ29sb3IpIHx8IGRlZmF1bHRDb2xvcjtcbiAgICAgICAgY29lcmNlKCdsaW5lLmNvbG9yJywgbGluZUNvbG9yRGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdsaW5lLndpZHRoJyk7XG4gICAgaWYoIShvcHRzIHx8IHt9KS5ub0Rhc2gpIGNvZXJjZSgnbGluZS5kYXNoJyk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBudW1Db25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJyk7XG52YXIgQkFETlVNID0gbnVtQ29uc3RhbnRzLkJBRE5VTTtcbnZhciBMT0dfQ0xJUCA9IG51bUNvbnN0YW50cy5MT0dfQ0xJUDtcbnZhciBMT0dfQ0xJUF9QTFVTID0gTE9HX0NMSVAgKyAwLjU7XG52YXIgTE9HX0NMSVBfTUlOVVMgPSBMT0dfQ0xJUCAtIDAuNTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBzZWdtZW50c0ludGVyc2VjdCA9IExpYi5zZWdtZW50c0ludGVyc2VjdDtcbnZhciBjb25zdHJhaW4gPSBMaWIuY29uc3RyYWluO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBsaW5lUG9pbnRzKGQsIG9wdHMpIHtcbiAgICB2YXIgeGEgPSBvcHRzLnhheGlzO1xuICAgIHZhciB5YSA9IG9wdHMueWF4aXM7XG4gICAgdmFyIHhMb2cgPSB4YS50eXBlID09PSAnbG9nJztcbiAgICB2YXIgeUxvZyA9IHlhLnR5cGUgPT09ICdsb2cnO1xuICAgIHZhciB4TGVuID0geGEuX2xlbmd0aDtcbiAgICB2YXIgeUxlbiA9IHlhLl9sZW5ndGg7XG4gICAgdmFyIGNvbm5lY3RHYXBzID0gb3B0cy5jb25uZWN0R2FwcztcbiAgICB2YXIgYmFzZVRvbGVyYW5jZSA9IG9wdHMuYmFzZVRvbGVyYW5jZTtcbiAgICB2YXIgc2hhcGUgPSBvcHRzLnNoYXBlO1xuICAgIHZhciBsaW5lYXIgPSBzaGFwZSA9PT0gJ2xpbmVhcic7XG4gICAgdmFyIHNlZ21lbnRzID0gW107XG4gICAgdmFyIG1pblRvbGVyYW5jZSA9IGNvbnN0YW50cy5taW5Ub2xlcmFuY2U7XG4gICAgdmFyIHB0cyA9IG5ldyBBcnJheShkLmxlbmd0aCk7XG4gICAgdmFyIHB0aSA9IDA7XG5cbiAgICB2YXIgaTtcblxuICAgIC8vIHB0IHZhcmlhYmxlcyBhcmUgcGl4ZWwgY29vcmRpbmF0ZXMgW3gseV0gb2Ygb25lIHBvaW50XG4gICAgLy8gdGhlc2UgZm91ciBhcmUgdGhlIG91dHB1dHMgb2YgY2x1c3RlcmluZyBvbiBhIGxpbmVcbiAgICB2YXIgY2x1c3RlclN0YXJ0UHQsIGNsdXN0ZXJFbmRQdCwgY2x1c3RlckhpZ2hQdCwgY2x1c3Rlckxvd1B0O1xuXG4gICAgLy8gXCJ0aGlzXCIgaXMgdGhlIG5leHQgcG9pbnQgd2UncmUgY29uc2lkZXJpbmcgYWRkaW5nIHRvIHRoZSBjbHVzdGVyXG4gICAgdmFyIHRoaXNQdDtcblxuICAgIC8vIGRpZCB3ZSBlbmNvdW50ZXIgdGhlIGhpZ2ggcG9pbnQgZmlyc3QsIHRoZW4gYSBsb3cgcG9pbnQsIG9yIHZpY2UgdmVyc2E/XG4gICAgdmFyIGNsdXN0ZXJIaWdoRmlyc3Q7XG5cbiAgICAvLyB0aGUgZmlyc3QgdHdvIHBvaW50cyBpbiB0aGUgY2x1c3RlciBkZXRlcm1pbmUgaXRzIHVuaXQgdmVjdG9yXG4gICAgLy8gc28gdGhlIHNlY29uZCBpcyBhbHdheXMgaW4gdGhlIFwiSGlnaFwiIGRpcmVjdGlvblxuICAgIHZhciBjbHVzdGVyVW5pdFZlY3RvcjtcblxuICAgIC8vIHRoZSBwaXhlbCBkZWx0YSBmcm9tIGNsdXN0ZXJTdGFydFB0XG4gICAgdmFyIHRoaXNWZWN0b3I7XG5cbiAgICAvLyB2YWwgdmFyaWFibGVzIGFyZSAoc2lnbmVkKSBwaXhlbCBkaXN0YW5jZXMgYWxvbmcgdGhlIGNsdXN0ZXIgdmVjdG9yXG4gICAgdmFyIGNsdXN0ZXJSZWZEaXN0LCBjbHVzdGVySGlnaFZhbCwgY2x1c3Rlckxvd1ZhbCwgdGhpc1ZhbDtcblxuICAgIC8vIGRldmlhdGlvbiB2YXJpYWJsZXMgYXJlIChzaWduZWQpIHBpeGVsIGRpc3RhbmNlcyBub3JtYWwgdG8gdGhlIGNsdXN0ZXIgdmVjdG9yXG4gICAgdmFyIGNsdXN0ZXJNaW5EZXZpYXRpb24sIGNsdXN0ZXJNYXhEZXZpYXRpb24sIHRoaXNEZXZpYXRpb247XG5cbiAgICAvLyB0dXJuIG9uZSBjYWxjZGF0YSBwb2ludCBpbnRvIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgZnVuY3Rpb24gZ2V0UHQoaW5kZXgpIHtcbiAgICAgICAgdmFyIGRpID0gZFtpbmRleF07XG4gICAgICAgIGlmKCFkaSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgeCA9IHhhLmMycChkaS54KTtcbiAgICAgICAgdmFyIHkgPSB5YS5jMnAoZGkueSk7XG5cbiAgICAgICAgLy8gaWYgbm9uLXBvc2l0aXZlIGxvZyB2YWx1ZXMsIHNldCB0aGVtIFZFUlkgZmFyIG9mZi1zY3JlZW5cbiAgICAgICAgLy8gc28gdGhlIGxpbmUgbG9va3MgZXNzZW50aWFsbHkgc3RyYWlnaHQgZnJvbSB0aGUgcHJldmlvdXMgcG9pbnQuXG4gICAgICAgIGlmKHggPT09IEJBRE5VTSkge1xuICAgICAgICAgICAgaWYoeExvZykgeCA9IHhhLmMycChkaS54LCB0cnVlKTtcbiAgICAgICAgICAgIGlmKHggPT09IEJBRE5VTSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgLy8gSWYgQk9USCB3ZXJlIGJhZCBsb2cgdmFsdWVzLCBtYWtlIHRoZSBsaW5lIGZvbGxvdyBhIGNvbnN0YW50XG4gICAgICAgICAgICAvLyBleHBvbmVudCByYXRoZXIgdGhhbiBhIGNvbnN0YW50IHNsb3BlXG4gICAgICAgICAgICBpZih5TG9nICYmIHkgPT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgIHggKj0gTWF0aC5hYnMoeGEuX20gKiB5TGVuICogKHhhLl9tID4gMCA/IExPR19DTElQX1BMVVMgOiBMT0dfQ0xJUF9NSU5VUykgL1xuICAgICAgICAgICAgICAgICAgICAoeWEuX20gKiB4TGVuICogKHlhLl9tID4gMCA/IExPR19DTElQX1BMVVMgOiBMT0dfQ0xJUF9NSU5VUykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHggKj0gMTAwMDtcbiAgICAgICAgfVxuICAgICAgICBpZih5ID09PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGlmKHlMb2cpIHkgPSB5YS5jMnAoZGkueSwgdHJ1ZSk7XG4gICAgICAgICAgICBpZih5ID09PSBCQUROVU0pIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHkgKj0gMTAwMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW3gsIHldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyb3NzZXNWaWV3cG9ydCh4RnJhYzAsIHlGcmFjMCwgeEZyYWMxLCB5RnJhYzEpIHtcbiAgICAgICAgdmFyIGR4ID0geEZyYWMxIC0geEZyYWMwO1xuICAgICAgICB2YXIgZHkgPSB5RnJhYzEgLSB5RnJhYzA7XG4gICAgICAgIHZhciBkeDAgPSAwLjUgLSB4RnJhYzA7XG4gICAgICAgIHZhciBkeTAgPSAwLjUgLSB5RnJhYzA7XG4gICAgICAgIHZhciBub3JtMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICB2YXIgZG90ID0gZHggKiBkeDAgKyBkeSAqIGR5MDtcbiAgICAgICAgaWYoZG90ID4gMCAmJiBkb3QgPCBub3JtMikge1xuICAgICAgICAgICAgdmFyIGNyb3NzID0gZHgwICogZHkgLSBkeTAgKiBkeDtcbiAgICAgICAgICAgIGlmKGNyb3NzICogY3Jvc3MgPCBub3JtMikgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGF0ZXN0WEZyYWMsIGxhdGVzdFlGcmFjO1xuICAgIC8vIGlmIHdlJ3JlIG9mZi1zY3JlZW4sIGluY3JlYXNlIHRvbGVyYW5jZSBvdmVyIGJhc2VUb2xlcmFuY2VcbiAgICBmdW5jdGlvbiBnZXRUb2xlcmFuY2UocHQsIG5leHRQdCkge1xuICAgICAgICB2YXIgeEZyYWMgPSBwdFswXSAvIHhMZW47XG4gICAgICAgIHZhciB5RnJhYyA9IHB0WzFdIC8geUxlbjtcbiAgICAgICAgdmFyIG9mZlNjcmVlbkZyYWN0aW9uID0gTWF0aC5tYXgoMCwgLXhGcmFjLCB4RnJhYyAtIDEsIC15RnJhYywgeUZyYWMgLSAxKTtcbiAgICAgICAgaWYob2ZmU2NyZWVuRnJhY3Rpb24gJiYgKGxhdGVzdFhGcmFjICE9PSB1bmRlZmluZWQpICYmXG4gICAgICAgICAgICBjcm9zc2VzVmlld3BvcnQoeEZyYWMsIHlGcmFjLCBsYXRlc3RYRnJhYywgbGF0ZXN0WUZyYWMpXG4gICAgICAgICkge1xuICAgICAgICAgICAgb2ZmU2NyZWVuRnJhY3Rpb24gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmKG9mZlNjcmVlbkZyYWN0aW9uICYmIG5leHRQdCAmJlxuICAgICAgICAgICAgY3Jvc3Nlc1ZpZXdwb3J0KHhGcmFjLCB5RnJhYywgbmV4dFB0WzBdIC8geExlbiwgbmV4dFB0WzFdIC8geUxlbilcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBvZmZTY3JlZW5GcmFjdGlvbiA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKDEgKyBjb25zdGFudHMudG9sZXJhbmNlR3Jvd3RoICogb2ZmU2NyZWVuRnJhY3Rpb24pICogYmFzZVRvbGVyYW5jZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwdERpc3QocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIGR4ID0gcHQxWzBdIC0gcHQyWzBdO1xuICAgICAgICB2YXIgZHkgPSBwdDFbMV0gLSBwdDJbMV07XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgIH1cblxuICAgIC8vIGxhc3QgYml0IG9mIGZpbHRlcmluZzogY2xpcCBwYXRocyB0aGF0IGFyZSBWRVJZIGZhciBvZmYtc2NyZWVuXG4gICAgLy8gc28gd2UgZG9uJ3QgZ2V0IG5lYXIgdGhlIGJyb3dzZXIncyBoYXJkIGxpbWl0ICgrLy0gMl4yOSBweCBpbiBDaHJvbWUgYW5kIEZGKVxuXG4gICAgdmFyIG1heFNjcmVlbnNBd2F5ID0gY29uc3RhbnRzLm1heFNjcmVlbnNBd2F5O1xuXG4gICAgLy8gZmluZCB0aGUgaW50ZXJzZWN0aW9ucyBiZXR3ZWVuIHRoZSBzZWdtZW50IGZyb20gcHQxIHRvIHB0MlxuICAgIC8vIGFuZCB0aGUgbGFyZ2UgcmVjdGFuZ2xlIG1heFNjcmVlbnNBd2F5IGFyb3VuZCB0aGUgdmlld3BvcnRcbiAgICAvLyBpZiBvbmUgb2YgcHQxIGFuZCBwdDIgaXMgaW5zaWRlIGFuZCB0aGUgb3RoZXIgb3V0c2lkZSwgdGhlcmVcbiAgICAvLyB3aWxsIGJlIG9ubHkgb25lIGludGVyc2VjdGlvbi5cbiAgICAvLyBpZiBib3RoIGFyZSBvdXRzaWRlIHRoZXJlIHdpbGwgYmUgMCBvciAyIGludGVyc2VjdGlvbnNcbiAgICAvLyAob3IgMSBpZiBpdCdzIHJpZ2h0IGF0IGEgY29ybmVyIC0gd2UnbGwgdHJlYXQgdGhhdCBsaWtlIDApXG4gICAgLy8gcmV0dXJucyBhbiBhcnJheSBvZiBpbnRlcnNlY3Rpb24gcHRzXG4gICAgdmFyIHhFZGdlMCA9IC14TGVuICogbWF4U2NyZWVuc0F3YXk7XG4gICAgdmFyIHhFZGdlMSA9IHhMZW4gKiAoMSArIG1heFNjcmVlbnNBd2F5KTtcbiAgICB2YXIgeUVkZ2UwID0gLXlMZW4gKiBtYXhTY3JlZW5zQXdheTtcbiAgICB2YXIgeUVkZ2UxID0geUxlbiAqICgxICsgbWF4U2NyZWVuc0F3YXkpO1xuICAgIHZhciBlZGdlcyA9IFtcbiAgICAgICAgW3hFZGdlMCwgeUVkZ2UwLCB4RWRnZTEsIHlFZGdlMF0sXG4gICAgICAgIFt4RWRnZTEsIHlFZGdlMCwgeEVkZ2UxLCB5RWRnZTFdLFxuICAgICAgICBbeEVkZ2UxLCB5RWRnZTEsIHhFZGdlMCwgeUVkZ2UxXSxcbiAgICAgICAgW3hFZGdlMCwgeUVkZ2UxLCB4RWRnZTAsIHlFZGdlMF1cbiAgICBdO1xuICAgIHZhciB4RWRnZSwgeUVkZ2UsIGxhc3RYRWRnZSwgbGFzdFlFZGdlLCBsYXN0RmFyUHQsIGVkZ2VQdDtcblxuICAgIC8vIGZvciBsaW5lYXIgbGluZSBzaGFwZSwgZWRnZSBpbnRlcnNlY3Rpb25zIHNob3VsZCBiZSBsaW5lYXJseSBpbnRlcnBvbGF0ZWRcbiAgICAvLyBzcGxpbmUgdXNlcyB0aGlzIHRvbywgd2hpY2ggaXNuJ3QgcHJlY2lzZWx5IGNvcnJlY3QgYnV0IGlzIGFjdHVhbGx5IHByZXR0eVxuICAgIC8vIGdvb2QsIGJlY2F1c2UgQ2F0bXVsbC1Sb20gd2VpZ2h0cyBmYXItYXdheSBwb2ludHMgbGVzcyBpbiBjcmVhdGluZyB0aGUgY3VydmF0dXJlXG4gICAgZnVuY3Rpb24gZ2V0TGluZWFyRWRnZUludGVyc2VjdGlvbnMocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIG91dCA9IFtdO1xuICAgICAgICB2YXIgcHRDb3VudCA9IDA7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgIHZhciBlZGdlID0gZWRnZXNbaV07XG4gICAgICAgICAgICB2YXIgcHRJbnQgPSBzZWdtZW50c0ludGVyc2VjdChwdDFbMF0sIHB0MVsxXSwgcHQyWzBdLCBwdDJbMV0sXG4gICAgICAgICAgICAgICAgZWRnZVswXSwgZWRnZVsxXSwgZWRnZVsyXSwgZWRnZVszXSk7XG4gICAgICAgICAgICBpZihwdEludCAmJiAoIXB0Q291bnQgfHxcbiAgICAgICAgICAgICAgICBNYXRoLmFicyhwdEludC54IC0gb3V0WzBdWzBdKSA+IDEgfHxcbiAgICAgICAgICAgICAgICBNYXRoLmFicyhwdEludC55IC0gb3V0WzBdWzFdKSA+IDFcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgICAgICBwdEludCA9IFtwdEludC54LCBwdEludC55XTtcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSBoYXZlIDIgaW50ZXJzZWN0aW9ucywgbWFrZSBzdXJlIHRoZSBjbG9zZXN0IG9uZSB0byBwdDEgY29tZXMgZmlyc3RcbiAgICAgICAgICAgICAgICBpZihwdENvdW50ICYmIHB0RGlzdChwdEludCwgcHQxKSA8IHB0RGlzdChvdXRbMF0sIHB0MSkpIG91dC51bnNoaWZ0KHB0SW50KTtcbiAgICAgICAgICAgICAgICBlbHNlIG91dC5wdXNoKHB0SW50KTtcbiAgICAgICAgICAgICAgICBwdENvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbmx5Q29uc3RyYWluZWRQb2ludChwdCkge1xuICAgICAgICBpZihwdFswXSA8IHhFZGdlMCB8fCBwdFswXSA+IHhFZGdlMSB8fCBwdFsxXSA8IHlFZGdlMCB8fCBwdFsxXSA+IHlFZGdlMSkge1xuICAgICAgICAgICAgcmV0dXJuIFtjb25zdHJhaW4ocHRbMF0sIHhFZGdlMCwgeEVkZ2UxKSwgY29uc3RyYWluKHB0WzFdLCB5RWRnZTAsIHlFZGdlMSldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2FtZUVkZ2UocHQxLCBwdDIpIHtcbiAgICAgICAgaWYocHQxWzBdID09PSBwdDJbMF0gJiYgKHB0MVswXSA9PT0geEVkZ2UwIHx8IHB0MVswXSA9PT0geEVkZ2UxKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmKHB0MVsxXSA9PT0gcHQyWzFdICYmIChwdDFbMV0gPT09IHlFZGdlMCB8fCBwdDFbMV0gPT09IHlFZGdlMSkpIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIGZvciBsaW5lIHNoYXBlcyBodiBhbmQgdmgsIG1vdmVtZW50IGluIHRoZSB0d28gZGltZW5zaW9ucyBpcyBkZWNvdXBsZWQsXG4gICAgLy8gc28gYWxsIHdlIG5lZWQgdG8gZG8gaXMgY29uc3RyYWluIGVhY2ggZGltZW5zaW9uIGluZGVwZW5kZW50bHlcbiAgICBmdW5jdGlvbiBnZXRIVkVkZ2VJbnRlcnNlY3Rpb25zKHB0MSwgcHQyKSB7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgICAgdmFyIHB0SW50MSA9IG9ubHlDb25zdHJhaW5lZFBvaW50KHB0MSk7XG4gICAgICAgIHZhciBwdEludDIgPSBvbmx5Q29uc3RyYWluZWRQb2ludChwdDIpO1xuICAgICAgICBpZihwdEludDEgJiYgcHRJbnQyICYmIHNhbWVFZGdlKHB0SW50MSwgcHRJbnQyKSkgcmV0dXJuIG91dDtcblxuICAgICAgICBpZihwdEludDEpIG91dC5wdXNoKHB0SW50MSk7XG4gICAgICAgIGlmKHB0SW50Mikgb3V0LnB1c2gocHRJbnQyKTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyBodmggYW5kIHZodiB3ZSBzb21ldGltZXMgaGF2ZSB0byBtb3ZlIG9uZSBvZiB0aGUgaW50ZXJzZWN0aW9uIHBvaW50c1xuICAgIC8vIG91dCBCRVlPTkQgdGhlIGNsaXBwaW5nIHJlY3QsIGJ5IGEgbWF4aW11bSBvZiBhIGZhY3RvciBvZiAyLCBzbyB0aGF0XG4gICAgLy8gdGhlIG1pZHBvaW50IGxpbmUgaXMgZHJhd24gaW4gdGhlIHJpZ2h0IHBsYWNlXG4gICAgZnVuY3Rpb24gZ2V0QUJBRWRnZUludGVyc2VjdGlvbnMoZGltLCBsaW1pdDAsIGxpbWl0MSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ocHQxLCBwdDIpIHtcbiAgICAgICAgICAgIHZhciBwdEludDEgPSBvbmx5Q29uc3RyYWluZWRQb2ludChwdDEpO1xuICAgICAgICAgICAgdmFyIHB0SW50MiA9IG9ubHlDb25zdHJhaW5lZFBvaW50KHB0Mik7XG5cbiAgICAgICAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgICAgICAgIGlmKHB0SW50MSAmJiBwdEludDIgJiYgc2FtZUVkZ2UocHRJbnQxLCBwdEludDIpKSByZXR1cm4gb3V0O1xuXG4gICAgICAgICAgICBpZihwdEludDEpIG91dC5wdXNoKHB0SW50MSk7XG4gICAgICAgICAgICBpZihwdEludDIpIG91dC5wdXNoKHB0SW50Mik7XG5cbiAgICAgICAgICAgIHZhciBtaWRTaGlmdCA9IDIgKiBMaWIuY29uc3RyYWluKChwdDFbZGltXSArIHB0MltkaW1dKSAvIDIsIGxpbWl0MCwgbGltaXQxKSAtXG4gICAgICAgICAgICAgICAgKChwdEludDEgfHwgcHQxKVtkaW1dICsgKHB0SW50MiB8fCBwdDIpW2RpbV0pO1xuICAgICAgICAgICAgaWYobWlkU2hpZnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHRUb0FsdGVyO1xuICAgICAgICAgICAgICAgIGlmKHB0SW50MSAmJiBwdEludDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcHRUb0FsdGVyID0gKG1pZFNoaWZ0ID4gMCA9PT0gcHRJbnQxW2RpbV0gPiBwdEludDJbZGltXSkgPyBwdEludDEgOiBwdEludDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgcHRUb0FsdGVyID0gcHRJbnQxIHx8IHB0SW50MjtcblxuICAgICAgICAgICAgICAgIHB0VG9BbHRlcltkaW1dICs9IG1pZFNoaWZ0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBnZXRFZGdlSW50ZXJzZWN0aW9ucztcbiAgICBpZihzaGFwZSA9PT0gJ2xpbmVhcicgfHwgc2hhcGUgPT09ICdzcGxpbmUnKSB7XG4gICAgICAgIGdldEVkZ2VJbnRlcnNlY3Rpb25zID0gZ2V0TGluZWFyRWRnZUludGVyc2VjdGlvbnM7XG4gICAgfVxuICAgIGVsc2UgaWYoc2hhcGUgPT09ICdodicgfHwgc2hhcGUgPT09ICd2aCcpIHtcbiAgICAgICAgZ2V0RWRnZUludGVyc2VjdGlvbnMgPSBnZXRIVkVkZ2VJbnRlcnNlY3Rpb25zO1xuICAgIH1cbiAgICBlbHNlIGlmKHNoYXBlID09PSAnaHZoJykgZ2V0RWRnZUludGVyc2VjdGlvbnMgPSBnZXRBQkFFZGdlSW50ZXJzZWN0aW9ucygwLCB4RWRnZTAsIHhFZGdlMSk7XG4gICAgZWxzZSBpZihzaGFwZSA9PT0gJ3ZodicpIGdldEVkZ2VJbnRlcnNlY3Rpb25zID0gZ2V0QUJBRWRnZUludGVyc2VjdGlvbnMoMSwgeUVkZ2UwLCB5RWRnZTEpO1xuXG4gICAgLy8gYSBzZWdtZW50IHB0MS0+cHQyIGVudGlyZWx5IG91dHNpZGUgdGhlIG5lYXJieSByZWdpb246XG4gICAgLy8gZmluZCB0aGUgY29ybmVyIGl0IGdldHMgY2xvc2VzdCB0byB0b3VjaGluZ1xuICAgIGZ1bmN0aW9uIGdldENsb3Nlc3RDb3JuZXIocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIGR4ID0gcHQyWzBdIC0gcHQxWzBdO1xuICAgICAgICB2YXIgbSA9IChwdDJbMV0gLSBwdDFbMV0pIC8gZHg7XG4gICAgICAgIHZhciBiID0gKHB0MVsxXSAqIHB0MlswXSAtIHB0MlsxXSAqIHB0MVswXSkgLyBkeDtcblxuICAgICAgICBpZihiID4gMCkgcmV0dXJuIFttID4gMCA/IHhFZGdlMCA6IHhFZGdlMSwgeUVkZ2UxXTtcbiAgICAgICAgZWxzZSByZXR1cm4gW20gPiAwID8geEVkZ2UxIDogeEVkZ2UwLCB5RWRnZTBdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUVkZ2UocHQpIHtcbiAgICAgICAgdmFyIHggPSBwdFswXTtcbiAgICAgICAgdmFyIHkgPSBwdFsxXTtcbiAgICAgICAgdmFyIHhTYW1lID0geCA9PT0gcHRzW3B0aSAtIDFdWzBdO1xuICAgICAgICB2YXIgeVNhbWUgPSB5ID09PSBwdHNbcHRpIC0gMV1bMV07XG4gICAgICAgIC8vIGR1cGxpY2F0ZSBwb2ludD9cbiAgICAgICAgaWYoeFNhbWUgJiYgeVNhbWUpIHJldHVybjtcbiAgICAgICAgaWYocHRpID4gMSkge1xuICAgICAgICAgICAgLy8gYmFja3RyYWNraW5nIGFsb25nIGFuIGVkZ2U/XG4gICAgICAgICAgICB2YXIgeFNhbWUyID0geCA9PT0gcHRzW3B0aSAtIDJdWzBdO1xuICAgICAgICAgICAgdmFyIHlTYW1lMiA9IHkgPT09IHB0c1twdGkgLSAyXVsxXTtcbiAgICAgICAgICAgIGlmKHhTYW1lICYmICh4ID09PSB4RWRnZTAgfHwgeCA9PT0geEVkZ2UxKSAmJiB4U2FtZTIpIHtcbiAgICAgICAgICAgICAgICBpZih5U2FtZTIpIHB0aS0tOyAvLyBiYWNrdHJhY2tpbmcgZXhhY3RseSAtIGRyb3AgcHJldiBwdCBhbmQgZG9uJ3QgYWRkXG4gICAgICAgICAgICAgICAgZWxzZSBwdHNbcHRpIC0gMV0gPSBwdDsgLy8gbm90IGV4YWN0OiByZXBsYWNlIHRoZSBwcmV2IHB0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKHlTYW1lICYmICh5ID09PSB5RWRnZTAgfHwgeSA9PT0geUVkZ2UxKSAmJiB5U2FtZTIpIHtcbiAgICAgICAgICAgICAgICBpZih4U2FtZTIpIHB0aS0tO1xuICAgICAgICAgICAgICAgIGVsc2UgcHRzW3B0aSAtIDFdID0gcHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHB0c1twdGkrK10gPSBwdDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHB0c1twdGkrK10gPSBwdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVFZGdlc0ZvclJlZW50cnkocHQpIHtcbiAgICAgICAgLy8gaWYgd2UncmUgb3V0c2lkZSB0aGUgbmVhcmJ5IHJlZ2lvbiBhbmQgZ29pbmcgYmFjayBpbixcbiAgICAgICAgLy8gd2UgbWF5IG5lZWQgdG8gbG9vcCBhcm91bmQgYSBjb3JuZXIgcG9pbnRcbiAgICAgICAgaWYocHRzW3B0aSAtIDFdWzBdICE9PSBwdFswXSAmJiBwdHNbcHRpIC0gMV1bMV0gIT09IHB0WzFdKSB7XG4gICAgICAgICAgICB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UsIGxhc3RZRWRnZV0pO1xuICAgICAgICB9XG4gICAgICAgIHVwZGF0ZUVkZ2UocHQpO1xuICAgICAgICBsYXN0RmFyUHQgPSBudWxsO1xuICAgICAgICBsYXN0WEVkZ2UgPSBsYXN0WUVkZ2UgPSAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFB0KHB0KSB7XG4gICAgICAgIGxhdGVzdFhGcmFjID0gcHRbMF0gLyB4TGVuO1xuICAgICAgICBsYXRlc3RZRnJhYyA9IHB0WzFdIC8geUxlbjtcbiAgICAgICAgLy8gQXJlIHdlIG1vcmUgdGhhbiBtYXhTY3JlZW5zQXdheSBvZmYtc2NyZWVuIGFueSBkaXJlY3Rpb24/XG4gICAgICAgIC8vIGlmIHNvLCBjbGlwIHRvIHRoaXMgYm94LCBidXQgaW4gc3VjaCBhIHdheSB0aGF0IG9uLXNjcmVlblxuICAgICAgICAvLyBkcmF3aW5nIGlzIHVuY2hhbmdlZFxuICAgICAgICB4RWRnZSA9IChwdFswXSA8IHhFZGdlMCkgPyB4RWRnZTAgOiAocHRbMF0gPiB4RWRnZTEpID8geEVkZ2UxIDogMDtcbiAgICAgICAgeUVkZ2UgPSAocHRbMV0gPCB5RWRnZTApID8geUVkZ2UwIDogKHB0WzFdID4geUVkZ2UxKSA/IHlFZGdlMSA6IDA7XG4gICAgICAgIGlmKHhFZGdlIHx8IHlFZGdlKSB7XG4gICAgICAgICAgICAvLyB0byBnZXQgZmlsbHMgcmlnaHQgLSBpZiBmaXJzdCBwb2ludCBpcyBmYXIsIHB1c2ggaXQgdG93YXJkIHRoZVxuICAgICAgICAgICAgLy8gc2NyZWVuIGluIHdoaWNoZXZlciBkaXJlY3Rpb24ocykgYXJlIGZhclxuICAgICAgICAgICAgaWYoIXB0aSkge1xuICAgICAgICAgICAgICAgIHB0c1twdGkrK10gPSBbeEVkZ2UgfHwgcHRbMF0sIHlFZGdlIHx8IHB0WzFdXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYobGFzdEZhclB0KSB7XG4gICAgICAgICAgICAgICAgLy8gYm90aCB0aGlzIHBvaW50IGFuZCB0aGUgbGFzdCBhcmUgb3V0c2lkZSB0aGUgbmVhcmJ5IHJlZ2lvblxuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIHdlJ3JlIGNyb3NzaW5nIHRoZSBuZWFyYnkgcmVnaW9uXG4gICAgICAgICAgICAgICAgdmFyIGludGVyc2VjdGlvbnMgPSBnZXRFZGdlSW50ZXJzZWN0aW9ucyhsYXN0RmFyUHQsIHB0KTtcbiAgICAgICAgICAgICAgICBpZihpbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlRWRnZXNGb3JSZWVudHJ5KGludGVyc2VjdGlvbnNbMF0pO1xuICAgICAgICAgICAgICAgICAgICBwdHNbcHRpKytdID0gaW50ZXJzZWN0aW9uc1sxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB3ZSdyZSBsZWF2aW5nIHRoZSBuZWFyYnkgcmVnaW9uIC0gYWRkIHRoZSBwb2ludCB3aGVyZSB3ZSBsZWZ0IGl0XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlZGdlUHQgPSBnZXRFZGdlSW50ZXJzZWN0aW9ucyhwdHNbcHRpIC0gMV0sIHB0KVswXTtcbiAgICAgICAgICAgICAgICBwdHNbcHRpKytdID0gZWRnZVB0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbGFzdFB0ID0gcHRzW3B0aSAtIDFdO1xuICAgICAgICAgICAgaWYoeEVkZ2UgJiYgeUVkZ2UgJiYgKGxhc3RQdFswXSAhPT0geEVkZ2UgfHwgbGFzdFB0WzFdICE9PSB5RWRnZSkpIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSd2ZSBnb25lIG91dCBiZXlvbmQgYSBuZXcgY29ybmVyOiBhZGQgdGhlIGNvcm5lciB0b29cbiAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IHRoZSBuZXh0IHBvaW50IHdpbGwgdGFrZSB0aGUgcmlnaHQgd2luZGluZ1xuICAgICAgICAgICAgICAgIGlmKGxhc3RGYXJQdCkge1xuICAgICAgICAgICAgICAgICAgICBpZihsYXN0WEVkZ2UgIT09IHhFZGdlICYmIGxhc3RZRWRnZSAhPT0geUVkZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGxhc3RYRWRnZSAmJiBsYXN0WUVkZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSd2ZSBnb25lIGFyb3VuZCB0byBhbiBvcHBvc2l0ZSBjb3JuZXIgLSB3ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gYWRkIHRoZSBjb3JyZWN0IGV4dHJhIGNvcm5lclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIG9yZGVyIHRvIGdldCB0aGUgcmlnaHQgd2luZGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZUVkZ2UoZ2V0Q2xvc2VzdENvcm5lcihsYXN0RmFyUHQsIHB0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSdyZSBjb21pbmcgZnJvbSBhIGZhciBlZGdlIC0gdGhlIGV4dHJhIGNvcm5lclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIG5lZWQgaXMgZGV0ZXJtaW5lZCB1bmlxdWVseSBieSB0aGUgc2VjdG9yc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZUVkZ2UoW2xhc3RYRWRnZSB8fCB4RWRnZSwgbGFzdFlFZGdlIHx8IHlFZGdlXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZihsYXN0WEVkZ2UgJiYgbGFzdFlFZGdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UsIGxhc3RZRWRnZV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHVwZGF0ZUVkZ2UoW3hFZGdlLCB5RWRnZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZigobGFzdFhFZGdlIC0geEVkZ2UpICYmIChsYXN0WUVkZ2UgLSB5RWRnZSkpIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSdyZSBjb21pbmcgZnJvbSBhbiBlZGdlIG9yIGZhciBjb3JuZXIgdG8gYW4gZWRnZSAtIGFnYWluIHRoZVxuICAgICAgICAgICAgICAgIC8vIGV4dHJhIGNvcm5lciB3ZSBuZWVkIGlzIHVuaXF1ZWx5IGRldGVybWluZWQgYnkgdGhlIHNlY3RvcnNcbiAgICAgICAgICAgICAgICB1cGRhdGVFZGdlKFt4RWRnZSB8fCBsYXN0WEVkZ2UsIHlFZGdlIHx8IGxhc3RZRWRnZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFzdEZhclB0ID0gcHQ7XG4gICAgICAgICAgICBsYXN0WEVkZ2UgPSB4RWRnZTtcbiAgICAgICAgICAgIGxhc3RZRWRnZSA9IHlFZGdlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYobGFzdEZhclB0KSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBwb2ludCBpcyBpbiByYW5nZSBidXQgdGhlIHByZXZpb3VzIHdhc24ndDogYWRkIGl0cyBlbnRyeSBwdCBmaXJzdFxuICAgICAgICAgICAgICAgIHVwZGF0ZUVkZ2VzRm9yUmVlbnRyeShnZXRFZGdlSW50ZXJzZWN0aW9ucyhsYXN0RmFyUHQsIHB0KVswXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHB0c1twdGkrK10gPSBwdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGxvb3Agb3ZlciBBTEwgcG9pbnRzIGluIHRoaXMgdHJhY2VcbiAgICBmb3IoaSA9IDA7IGkgPCBkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNsdXN0ZXJTdGFydFB0ID0gZ2V0UHQoaSk7XG4gICAgICAgIGlmKCFjbHVzdGVyU3RhcnRQdCkgY29udGludWU7XG5cbiAgICAgICAgcHRpID0gMDtcbiAgICAgICAgbGFzdEZhclB0ID0gbnVsbDtcbiAgICAgICAgYWRkUHQoY2x1c3RlclN0YXJ0UHQpO1xuXG4gICAgICAgIC8vIGxvb3Agb3ZlciBvbmUgc2VnbWVudCBvZiB0aGUgdHJhY2VcbiAgICAgICAgZm9yKGkrKzsgaSA8IGQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNsdXN0ZXJIaWdoUHQgPSBnZXRQdChpKTtcbiAgICAgICAgICAgIGlmKCFjbHVzdGVySGlnaFB0KSB7XG4gICAgICAgICAgICAgICAgaWYoY29ubmVjdEdhcHMpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGVsc2UgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGNhbid0IGRlY2ltYXRlIGlmIG5vbmxpbmVhciBsaW5lIHNoYXBlXG4gICAgICAgICAgICAvLyBUT0RPOiB3ZSAqY291bGQqIGRlY2ltYXRlIFtodl17MiwzfSBzaGFwZXMgaWYgd2UgcmVzdHJpY3RlZCBjbHVzdGVycyB0byBob3J6IG9yIHZlcnQgYWdhaW5cbiAgICAgICAgICAgIC8vIGJ1dCBzcGxpbmUgd291bGQgYmUgdmVycnJ5IGF3a3dhcmQgdG8gZGVjaW1hdGVcbiAgICAgICAgICAgIGlmKCFsaW5lYXIgfHwgIW9wdHMuc2ltcGxpZnkpIHtcbiAgICAgICAgICAgICAgICBhZGRQdChjbHVzdGVySGlnaFB0KTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG5leHRQdCA9IGdldFB0KGkgKyAxKTtcblxuICAgICAgICAgICAgY2x1c3RlclJlZkRpc3QgPSBwdERpc3QoY2x1c3RlckhpZ2hQdCwgY2x1c3RlclN0YXJ0UHQpO1xuXG4gICAgICAgICAgICBpZihjbHVzdGVyUmVmRGlzdCA8IGdldFRvbGVyYW5jZShjbHVzdGVySGlnaFB0LCBuZXh0UHQpICogbWluVG9sZXJhbmNlKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY2x1c3RlclVuaXRWZWN0b3IgPSBbXG4gICAgICAgICAgICAgICAgKGNsdXN0ZXJIaWdoUHRbMF0gLSBjbHVzdGVyU3RhcnRQdFswXSkgLyBjbHVzdGVyUmVmRGlzdCxcbiAgICAgICAgICAgICAgICAoY2x1c3RlckhpZ2hQdFsxXSAtIGNsdXN0ZXJTdGFydFB0WzFdKSAvIGNsdXN0ZXJSZWZEaXN0XG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBjbHVzdGVyTG93UHQgPSBjbHVzdGVyU3RhcnRQdDtcbiAgICAgICAgICAgIGNsdXN0ZXJIaWdoVmFsID0gY2x1c3RlclJlZkRpc3Q7XG4gICAgICAgICAgICBjbHVzdGVyTG93VmFsID0gY2x1c3Rlck1pbkRldmlhdGlvbiA9IGNsdXN0ZXJNYXhEZXZpYXRpb24gPSAwO1xuICAgICAgICAgICAgY2x1c3RlckhpZ2hGaXJzdCA9IGZhbHNlO1xuICAgICAgICAgICAgY2x1c3RlckVuZFB0ID0gY2x1c3RlckhpZ2hQdDtcblxuICAgICAgICAgICAgLy8gbG9vcCBvdmVyIG9uZSBjbHVzdGVyIG9mIHBvaW50cyB0aGF0IGNvbGxhcHNlIG9udG8gb25lIGxpbmVcbiAgICAgICAgICAgIGZvcihpKys7IGkgPCBkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpc1B0ID0gbmV4dFB0O1xuICAgICAgICAgICAgICAgIG5leHRQdCA9IGdldFB0KGkgKyAxKTtcbiAgICAgICAgICAgICAgICBpZighdGhpc1B0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNvbm5lY3RHYXBzKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpc1ZlY3RvciA9IFtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1B0WzBdIC0gY2x1c3RlclN0YXJ0UHRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHRoaXNQdFsxXSAtIGNsdXN0ZXJTdGFydFB0WzFdXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAvLyBjcm9zcyBwcm9kdWN0IChvciBkb3Qgd2l0aCBub3JtYWwgdG8gdGhlIGNsdXN0ZXIgdmVjdG9yKVxuICAgICAgICAgICAgICAgIHRoaXNEZXZpYXRpb24gPSB0aGlzVmVjdG9yWzBdICogY2x1c3RlclVuaXRWZWN0b3JbMV0gLSB0aGlzVmVjdG9yWzFdICogY2x1c3RlclVuaXRWZWN0b3JbMF07XG4gICAgICAgICAgICAgICAgY2x1c3Rlck1pbkRldmlhdGlvbiA9IE1hdGgubWluKGNsdXN0ZXJNaW5EZXZpYXRpb24sIHRoaXNEZXZpYXRpb24pO1xuICAgICAgICAgICAgICAgIGNsdXN0ZXJNYXhEZXZpYXRpb24gPSBNYXRoLm1heChjbHVzdGVyTWF4RGV2aWF0aW9uLCB0aGlzRGV2aWF0aW9uKTtcblxuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJNYXhEZXZpYXRpb24gLSBjbHVzdGVyTWluRGV2aWF0aW9uID4gZ2V0VG9sZXJhbmNlKHRoaXNQdCwgbmV4dFB0KSkgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjbHVzdGVyRW5kUHQgPSB0aGlzUHQ7XG4gICAgICAgICAgICAgICAgdGhpc1ZhbCA9IHRoaXNWZWN0b3JbMF0gKiBjbHVzdGVyVW5pdFZlY3RvclswXSArIHRoaXNWZWN0b3JbMV0gKiBjbHVzdGVyVW5pdFZlY3RvclsxXTtcblxuICAgICAgICAgICAgICAgIGlmKHRoaXNWYWwgPiBjbHVzdGVySGlnaFZhbCkge1xuICAgICAgICAgICAgICAgICAgICBjbHVzdGVySGlnaFZhbCA9IHRoaXNWYWw7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJIaWdoUHQgPSB0aGlzUHQ7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJIaWdoRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodGhpc1ZhbCA8IGNsdXN0ZXJMb3dWYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2x1c3Rlckxvd1ZhbCA9IHRoaXNWYWw7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJMb3dQdCA9IHRoaXNQdDtcbiAgICAgICAgICAgICAgICAgICAgY2x1c3RlckhpZ2hGaXJzdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpbnNlcnQgdGhpcyBjbHVzdGVyIGludG8gcHRzXG4gICAgICAgICAgICAvLyB3ZSd2ZSBhbHJlYWR5IGluc2VydGVkIHRoZSBzdGFydCBwdCwgbm93IGNoZWNrIGlmIHdlIGhhdmUgaGlnaCBhbmQgbG93IHB0c1xuICAgICAgICAgICAgaWYoY2x1c3RlckhpZ2hGaXJzdCkge1xuICAgICAgICAgICAgICAgIGFkZFB0KGNsdXN0ZXJIaWdoUHQpO1xuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJFbmRQdCAhPT0gY2x1c3Rlckxvd1B0KSBhZGRQdChjbHVzdGVyTG93UHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihjbHVzdGVyTG93UHQgIT09IGNsdXN0ZXJTdGFydFB0KSBhZGRQdChjbHVzdGVyTG93UHQpO1xuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJFbmRQdCAhPT0gY2x1c3RlckhpZ2hQdCkgYWRkUHQoY2x1c3RlckhpZ2hQdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhbmQgZmluYWxseSBpbnNlcnQgdGhlIGVuZCBwdFxuICAgICAgICAgICAgYWRkUHQoY2x1c3RlckVuZFB0KTtcblxuICAgICAgICAgICAgLy8gaGF2ZSB3ZSByZWFjaGVkIHRoZSBlbmQgb2YgdGhpcyBzZWdtZW50P1xuICAgICAgICAgICAgaWYoaSA+PSBkLmxlbmd0aCB8fCAhdGhpc1B0KSBicmVhaztcblxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIGhhdmUgYW4gb3V0LW9mLWNsdXN0ZXIgcG9pbnQgdG8gaW5zZXJ0IGFzIG5leHQgY2x1c3RlclN0YXJ0UHRcbiAgICAgICAgICAgIGFkZFB0KHRoaXNQdCk7XG4gICAgICAgICAgICBjbHVzdGVyU3RhcnRQdCA9IHRoaXNQdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRvIGdldCBmaWxscyByaWdodCAtIHJlcGVhdCB3aGF0IHdlIGRpZCBhdCB0aGUgc3RhcnRcbiAgICAgICAgaWYobGFzdEZhclB0KSB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UgfHwgbGFzdEZhclB0WzBdLCBsYXN0WUVkZ2UgfHwgbGFzdEZhclB0WzFdXSk7XG5cbiAgICAgICAgc2VnbWVudHMucHVzaChwdHMuc2xpY2UoMCwgcHRpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlZ21lbnRzO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbi8vIGNvbW1vbiB0byAnc2NhdHRlcicgYW5kICdzY2F0dGVydGVybmFyeSdcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciBzaGFwZSA9IGNvZXJjZSgnbGluZS5zaGFwZScpO1xuICAgIGlmKHNoYXBlID09PSAnc3BsaW5lJykgY29lcmNlKCdsaW5lLnNtb290aGluZycpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExJTktFREZJTExTID0ge3RvbmV4dHg6IDEsIHRvbmV4dHk6IDEsIHRvbmV4dDogMX07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbGlua1RyYWNlcyhnZCwgcGxvdGluZm8sIGNkc2NhdHRlcikge1xuICAgIHZhciB0cmFjZSwgaSwgZ3JvdXAsIHByZXZ0cmFjZSwgZ3JvdXBJbmRleDtcblxuICAgIC8vIGZpcnN0IHNvcnQgdHJhY2VzIHRvIGtlZXAgc3RhY2tzICYgZmlsbGVkLXRvZ2V0aGVyIGdyb3VwcyB0b2dldGhlclxuICAgIHZhciBncm91cEluZGljZXMgPSB7fTtcbiAgICB2YXIgbmVlZHNTb3J0ID0gZmFsc2U7XG4gICAgdmFyIHByZXZHcm91cEluZGV4ID0gLTE7XG4gICAgdmFyIG5leHRHcm91cEluZGV4ID0gMDtcbiAgICB2YXIgcHJldlVuc3RhY2tlZEdyb3VwSW5kZXggPSAtMTtcbiAgICBmb3IoaSA9IDA7IGkgPCBjZHNjYXR0ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2UgPSBjZHNjYXR0ZXJbaV1bMF0udHJhY2U7XG4gICAgICAgIGdyb3VwID0gdHJhY2Uuc3RhY2tncm91cCB8fCAnJztcbiAgICAgICAgaWYoZ3JvdXApIHtcbiAgICAgICAgICAgIGlmKGdyb3VwIGluIGdyb3VwSW5kaWNlcykge1xuICAgICAgICAgICAgICAgIGdyb3VwSW5kZXggPSBncm91cEluZGljZXNbZ3JvdXBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBJbmRleCA9IGdyb3VwSW5kaWNlc1tncm91cF0gPSBuZXh0R3JvdXBJbmRleDtcbiAgICAgICAgICAgICAgICBuZXh0R3JvdXBJbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYodHJhY2UuZmlsbCBpbiBMSU5LRURGSUxMUyAmJiBwcmV2VW5zdGFja2VkR3JvdXBJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICBncm91cEluZGV4ID0gcHJldlVuc3RhY2tlZEdyb3VwSW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBncm91cEluZGV4ID0gcHJldlVuc3RhY2tlZEdyb3VwSW5kZXggPSBuZXh0R3JvdXBJbmRleDtcbiAgICAgICAgICAgIG5leHRHcm91cEluZGV4Kys7XG4gICAgICAgIH1cblxuICAgICAgICBpZihncm91cEluZGV4IDwgcHJldkdyb3VwSW5kZXgpIG5lZWRzU29ydCA9IHRydWU7XG4gICAgICAgIHRyYWNlLl9ncm91cEluZGV4ID0gcHJldkdyb3VwSW5kZXggPSBncm91cEluZGV4O1xuICAgIH1cblxuICAgIHZhciBjZHNjYXR0ZXJTb3J0ZWQgPSBjZHNjYXR0ZXIuc2xpY2UoKTtcbiAgICBpZihuZWVkc1NvcnQpIHtcbiAgICAgICAgY2RzY2F0dGVyU29ydGVkLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgdmFyIHRyYWNlQSA9IGFbMF0udHJhY2U7XG4gICAgICAgICAgICB2YXIgdHJhY2VCID0gYlswXS50cmFjZTtcbiAgICAgICAgICAgIHJldHVybiAodHJhY2VBLl9ncm91cEluZGV4IC0gdHJhY2VCLl9ncm91cEluZGV4KSB8fFxuICAgICAgICAgICAgICAgICh0cmFjZUEuaW5kZXggLSB0cmFjZUIuaW5kZXgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBub3cgbGluayB0cmFjZXMgdG8gZWFjaCBvdGhlclxuICAgIHZhciBwcmV2dHJhY2VzID0ge307XG4gICAgZm9yKGkgPSAwOyBpIDwgY2RzY2F0dGVyU29ydGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gY2RzY2F0dGVyU29ydGVkW2ldWzBdLnRyYWNlO1xuICAgICAgICBncm91cCA9IHRyYWNlLnN0YWNrZ3JvdXAgfHwgJyc7XG5cbiAgICAgICAgLy8gTm90ZTogVGhlIGNoZWNrIHdoaWNoIGVuc3VyZXMgYWxsIGNkc2NhdHRlciBoZXJlIGFyZSBmb3IgdGhlIHNhbWUgYXhpcyBhbmRcbiAgICAgICAgLy8gYXJlIGVpdGhlciBjYXJ0ZXNpYW4gb3Igc2NhdHRlcnRlcm5hcnkgaGFzIGJlZW4gcmVtb3ZlZC4gVGhpcyBjb2RlIGFzc3VtZXNcbiAgICAgICAgLy8gdGhlIHBhc3NlZCBzY2F0dGVydHJhY2VzIGhhdmUgYmVlbiBmaWx0ZXJlZCB0byB0aGUgcHJvcGVyIHBsb3QgdHlwZXMgYW5kXG4gICAgICAgIC8vIHRoZSBwcm9wZXIgc3VicGxvdHMuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRyYWNlLl9uZXh0dHJhY2UgPSBudWxsO1xuXG4gICAgICAgICAgICBpZih0cmFjZS5maWxsIGluIExJTktFREZJTExTKSB7XG4gICAgICAgICAgICAgICAgcHJldnRyYWNlID0gcHJldnRyYWNlc1tncm91cF07XG4gICAgICAgICAgICAgICAgdHJhY2UuX3ByZXZ0cmFjZSA9IHByZXZ0cmFjZSB8fCBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYocHJldnRyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZ0cmFjZS5fbmV4dHRyYWNlID0gdHJhY2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cmFjZS5fb3duZmlsbCA9ICh0cmFjZS5maWxsICYmIChcbiAgICAgICAgICAgICAgICB0cmFjZS5maWxsLnN1YnN0cigwLCA2KSA9PT0gJ3RvemVybycgfHxcbiAgICAgICAgICAgICAgICB0cmFjZS5maWxsID09PSAndG9zZWxmJyB8fFxuICAgICAgICAgICAgICAgICh0cmFjZS5maWxsLnN1YnN0cigwLCAyKSA9PT0gJ3RvJyAmJiAhdHJhY2UuX3ByZXZ0cmFjZSlcbiAgICAgICAgICAgICkpO1xuXG4gICAgICAgICAgICBwcmV2dHJhY2VzW2dyb3VwXSA9IHRyYWNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhY2UuX3ByZXZ0cmFjZSA9IHRyYWNlLl9uZXh0dHJhY2UgPSB0cmFjZS5fb3duZmlsbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2RzY2F0dGVyU29ydGVkO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxuXG4vLyB1c2VkIGluIHRoZSBkcmF3aW5nIHN0ZXAgZm9yICdzY2F0dGVyJyBhbmQgJ3NjYXR0ZWdlbycgYW5kXG4vLyBpbiB0aGUgY29udmVydCBzdGVwIGZvciAnc2NhdHRlcjNkJ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQnViYmxlU2l6ZUZuKHRyYWNlKSB7XG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlcixcbiAgICAgICAgc2l6ZVJlZiA9IG1hcmtlci5zaXplcmVmIHx8IDEsXG4gICAgICAgIHNpemVNaW4gPSBtYXJrZXIuc2l6ZW1pbiB8fCAwO1xuXG4gICAgLy8gZm9yIGJ1YmJsZSBjaGFydHMsIGFsbG93IHNjYWxpbmcgdGhlIHByb3ZpZGVkIHZhbHVlIGxpbmVhcmx5XG4gICAgLy8gYW5kIGJ5IGFyZWEgb3IgZGlhbWV0ZXIuXG4gICAgLy8gTm90ZSB0aGlzIG9ubHkgYXBwbGllcyB0byB0aGUgYXJyYXktdmFsdWUgc2l6ZXNcblxuICAgIHZhciBiYXNlRm4gPSAobWFya2VyLnNpemVtb2RlID09PSAnYXJlYScpID9cbiAgICAgICAgICAgIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIE1hdGguc3FydCh2IC8gc2l6ZVJlZik7IH0gOlxuICAgICAgICAgICAgZnVuY3Rpb24odikgeyByZXR1cm4gdiAvIHNpemVSZWY7IH07XG5cbiAgICAvLyBUT0RPIGFkZCBzdXBwb3J0IGZvciBwb3NpdGlvbi9uZWdhdGl2ZSBidWJibGVzP1xuICAgIC8vIFRPRE8gYWRkICdzaXplb2Zmc2V0JyBhdHRyaWJ1dGU/XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgdmFyIGJhc2VTaXplID0gYmFzZUZuKHYgLyAyKTtcblxuICAgICAgICAvLyBkb24ndCBzaG93IG5vbi1udW1lcmljIGFuZCBuZWdhdGl2ZSBzaXplc1xuICAgICAgICByZXR1cm4gKGlzTnVtZXJpYyhiYXNlU2l6ZSkgJiYgKGJhc2VTaXplID4gMCkpID9cbiAgICAgICAgICAgIE1hdGgubWF4KGJhc2VTaXplLCBzaXplTWluKSA6XG4gICAgICAgICAgICAwO1xuICAgIH07XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNvbnRhaW5lcjogJ21hcmtlcicsXG4gICAgbWluOiAnY21pbicsXG4gICAgbWF4OiAnY21heCdcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGhhc0NvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGFzX2NvbG9yc2NhbGUnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcblxudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi9zdWJ0eXBlcycpO1xuXG4vKlxuICogb3B0czogb2JqZWN0IG9mIGZsYWdzIHRvIGNvbnRyb2wgZmVhdHVyZXMgbm90IGFsbCBtYXJrZXIgdXNlcnMgc3VwcG9ydFxuICogICBub0xpbmU6IGNhbGxlciBkb2VzIG5vdCBzdXBwb3J0IG1hcmtlciBsaW5lc1xuICogICBncmFkaWVudDogY2FsbGVyIHN1cHBvcnRzIGdyYWRpZW50c1xuICogICBub1NlbGVjdDogY2FsbGVyIGRvZXMgbm90IHN1cHBvcnQgc2VsZWN0ZWQvdW5zZWxlY3RlZCBhdHRyaWJ1dGUgY29udGFpbmVyc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgdmFyIGlzQnViYmxlID0gc3ViVHlwZXMuaXNCdWJibGUodHJhY2VJbiksXG4gICAgICAgIGxpbmVDb2xvciA9ICh0cmFjZUluLmxpbmUgfHwge30pLmNvbG9yLFxuICAgICAgICBkZWZhdWx0TUxDO1xuXG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICAvLyBtYXJrZXIuY29sb3IgaW5oZXJpdCBmcm9tIGxpbmUuY29sb3IgKGV2ZW4gaWYgbGluZS5jb2xvciBpcyBhbiBhcnJheSlcbiAgICBpZihsaW5lQ29sb3IpIGRlZmF1bHRDb2xvciA9IGxpbmVDb2xvcjtcblxuICAgIGNvZXJjZSgnbWFya2VyLnN5bWJvbCcpO1xuICAgIGNvZXJjZSgnbWFya2VyLm9wYWNpdHknLCBpc0J1YmJsZSA/IDAuNyA6IDEpO1xuICAgIGNvZXJjZSgnbWFya2VyLnNpemUnKTtcblxuICAgIGNvZXJjZSgnbWFya2VyLmNvbG9yJywgZGVmYXVsdENvbG9yKTtcbiAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlSW4sICdtYXJrZXInKSkge1xuICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbWFya2VyLicsIGNMZXR0ZXI6ICdjJ30pO1xuICAgIH1cblxuICAgIGlmKCFvcHRzLm5vU2VsZWN0KSB7XG4gICAgICAgIGNvZXJjZSgnc2VsZWN0ZWQubWFya2VyLmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdzZWxlY3RlZC5tYXJrZXIuc2l6ZScpO1xuICAgICAgICBjb2VyY2UoJ3Vuc2VsZWN0ZWQubWFya2VyLnNpemUnKTtcbiAgICB9XG5cbiAgICBpZighb3B0cy5ub0xpbmUpIHtcbiAgICAgICAgLy8gaWYgdGhlcmUncyBhIGxpbmUgd2l0aCBhIGRpZmZlcmVudCBjb2xvciB0aGFuIHRoZSBtYXJrZXIsIHVzZVxuICAgICAgICAvLyB0aGF0IGxpbmUgY29sb3IgYXMgdGhlIGRlZmF1bHQgbWFya2VyIGxpbmUgY29sb3JcbiAgICAgICAgLy8gKGV4Y2VwdCB3aGVuIGl0J3MgYW4gYXJyYXkpXG4gICAgICAgIC8vIG1vc3RseSB0aGlzIGlzIGZvciB0cmFuc3BhcmVudCBtYXJrZXJzIHRvIGJlaGF2ZSBuaWNlbHlcbiAgICAgICAgaWYobGluZUNvbG9yICYmICFBcnJheS5pc0FycmF5KGxpbmVDb2xvcikgJiYgKHRyYWNlT3V0Lm1hcmtlci5jb2xvciAhPT0gbGluZUNvbG9yKSkge1xuICAgICAgICAgICAgZGVmYXVsdE1MQyA9IGxpbmVDb2xvcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGlzQnViYmxlKSBkZWZhdWx0TUxDID0gQ29sb3IuYmFja2dyb3VuZDtcbiAgICAgICAgZWxzZSBkZWZhdWx0TUxDID0gQ29sb3IuZGVmYXVsdExpbmU7XG5cbiAgICAgICAgY29lcmNlKCdtYXJrZXIubGluZS5jb2xvcicsIGRlZmF1bHRNTEMpO1xuICAgICAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlSW4sICdtYXJrZXIubGluZScpKSB7XG4gICAgICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbWFya2VyLmxpbmUuJywgY0xldHRlcjogJ2MnfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJywgaXNCdWJibGUgPyAxIDogMCk7XG4gICAgfVxuXG4gICAgaWYoaXNCdWJibGUpIHtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIuc2l6ZXJlZicpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5zaXplbWluJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLnNpemVtb2RlJyk7XG4gICAgfVxuXG4gICAgaWYob3B0cy5ncmFkaWVudCkge1xuICAgICAgICB2YXIgZ3JhZGllbnRUeXBlID0gY29lcmNlKCdtYXJrZXIuZ3JhZGllbnQudHlwZScpO1xuICAgICAgICBpZihncmFkaWVudFR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgY29lcmNlKCdtYXJrZXIuZ3JhZGllbnQuY29sb3InKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBlbnN1cmVTaW5nbGUgPSBMaWIuZW5zdXJlU2luZ2xlO1xudmFyIGlkZW50aXR5ID0gTGliLmlkZW50aXR5O1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcblxudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi9zdWJ0eXBlcycpO1xudmFyIGxpbmVQb2ludHMgPSByZXF1aXJlKCcuL2xpbmVfcG9pbnRzJyk7XG52YXIgbGlua1RyYWNlcyA9IHJlcXVpcmUoJy4vbGlua190cmFjZXMnKTtcbnZhciBwb2x5Z29uVGVzdGVyID0gcmVxdWlyZSgnLi4vLi4vbGliL3BvbHlnb24nKS50ZXN0ZXI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkc2NhdHRlciwgc2NhdHRlckxheWVyLCB0cmFuc2l0aW9uT3B0cywgbWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgIHZhciBqb2luLCBvbkNvbXBsZXRlO1xuXG4gICAgLy8gSWYgdHJhbnNpdGlvbiBjb25maWcgaXMgcHJvdmlkZWQsIHRoZW4gaXQgaXMgb25seSBhIHBhcnRpYWwgcmVwbG90IGFuZCB0cmFjZXMgbm90XG4gICAgLy8gdXBkYXRlZCBhcmUgcmVtb3ZlZC5cbiAgICB2YXIgaXNGdWxsUmVwbG90ID0gIXRyYW5zaXRpb25PcHRzO1xuICAgIHZhciBoYXNUcmFuc2l0aW9uID0gISF0cmFuc2l0aW9uT3B0cyAmJiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDA7XG5cbiAgICAvLyBMaW5rIHRyYWNlcyBzbyB0aGUgei1vcmRlciBvZiBmaWxsIGxheWVycyBpcyBjb3JyZWN0XG4gICAgdmFyIGNkc2NhdHRlclNvcnRlZCA9IGxpbmtUcmFjZXMoZ2QsIHBsb3RpbmZvLCBjZHNjYXR0ZXIpO1xuXG4gICAgam9pbiA9IHNjYXR0ZXJMYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnKVxuICAgICAgICAuZGF0YShjZHNjYXR0ZXJTb3J0ZWQsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF0udHJhY2UudWlkOyB9KTtcblxuICAgIC8vIEFwcGVuZCBuZXcgdHJhY2VzOlxuICAgIGpvaW4uZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYWNlIHNjYXR0ZXIgdHJhY2UnICsgZFswXS50cmFjZS51aWQ7XG4gICAgICAgIH0pXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLW1pdGVybGltaXQnLCAyKTtcbiAgICBqb2luLm9yZGVyKCk7XG5cbiAgICBjcmVhdGVGaWxscyhnZCwgam9pbiwgcGxvdGluZm8pO1xuXG4gICAgaWYoaGFzVHJhbnNpdGlvbikge1xuICAgICAgICBpZihtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICAvLyBJZiBpdCB3YXMgcGFzc2VkIGEgY2FsbGJhY2sgdG8gcmVnaXN0ZXIgY29tcGxldGlvbiwgbWFrZSBhIGNhbGxiYWNrLiBJZlxuICAgICAgICAgICAgLy8gdGhpcyBpcyBjcmVhdGVkLCB0aGVuIGl0IG11c3QgYmUgZXhlY3V0ZWQgb24gY29tcGxldGlvbiwgb3RoZXJ3aXNlIHRoZVxuICAgICAgICAgICAgLy8gcG9zLXRyYW5zaXRpb24gcmVkcmF3IHdpbGwgbm90IGV4ZWN1dGU6XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gbWFrZU9uQ29tcGxldGVDYWxsYmFjaygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyYW5zaXRpb24gPSBkMy50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5kdXJhdGlvbih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbilcbiAgICAgICAgICAgIC5lYXNlKHRyYW5zaXRpb25PcHRzLmVhc2luZylcbiAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuZWFjaCgnaW50ZXJydXB0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB0cmFuc2l0aW9uLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBNdXN0IHJ1biB0aGUgc2VsZWN0aW9uIGFnYWluIHNpbmNlIG90aGVyd2lzZSBlbnRlcnMvdXBkYXRlcyBnZXQgZ3JvdXBlZCB0b2dldGhlclxuICAgICAgICAgICAgLy8gYW5kIHRoZXNlIGdldCBleGVjdXRlZCBvdXQgb2Ygb3JkZXIuIEV4Y2VwdCB3ZSBuZWVkIHRoZW0gaW4gb3JkZXIhXG4gICAgICAgICAgICBzY2F0dGVyTGF5ZXIuc2VsZWN0QWxsKCdnLnRyYWNlJykuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcGxvdE9uZShnZCwgaSwgcGxvdGluZm8sIGQsIGNkc2NhdHRlclNvcnRlZCwgdGhpcywgdHJhbnNpdGlvbk9wdHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGpvaW4uZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICBwbG90T25lKGdkLCBpLCBwbG90aW5mbywgZCwgY2RzY2F0dGVyU29ydGVkLCB0aGlzLCB0cmFuc2l0aW9uT3B0cyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGlzRnVsbFJlcGxvdCkge1xuICAgICAgICBqb2luLmV4aXQoKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICAvLyByZW1vdmUgcGF0aHMgdGhhdCBkaWRuJ3QgZ2V0IHVzZWRcbiAgICBzY2F0dGVyTGF5ZXIuc2VsZWN0QWxsKCdwYXRoOm5vdChbZF0pJykucmVtb3ZlKCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVGaWxscyhnZCwgdHJhY2VKb2luLCBwbG90aW5mbykge1xuICAgIHRyYWNlSm9pbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGZpbGxzID0gZW5zdXJlU2luZ2xlKGQzLnNlbGVjdCh0aGlzKSwgJ2cnLCAnZmlsbHMnKTtcbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKGZpbGxzLCBwbG90aW5mby5sYXllckNsaXBJZCk7XG5cbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgZmlsbERhdGEgPSBbXTtcbiAgICAgICAgaWYodHJhY2UuX293bmZpbGwpIGZpbGxEYXRhLnB1c2goJ19vd25GaWxsJyk7XG4gICAgICAgIGlmKHRyYWNlLl9uZXh0dHJhY2UpIGZpbGxEYXRhLnB1c2goJ19uZXh0RmlsbCcpO1xuXG4gICAgICAgIHZhciBmaWxsSm9pbiA9IGZpbGxzLnNlbGVjdEFsbCgnZycpLmRhdGEoZmlsbERhdGEsIGlkZW50aXR5KTtcblxuICAgICAgICBmaWxsSm9pbi5lbnRlcigpLmFwcGVuZCgnZycpO1xuXG4gICAgICAgIGZpbGxKb2luLmV4aXQoKVxuICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkgeyB0cmFjZVtkXSA9IG51bGw7IH0pXG4gICAgICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICAgICAgZmlsbEpvaW4ub3JkZXIoKS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIC8vIG1ha2UgYSBwYXRoIGVsZW1lbnQgaW5zaWRlIHRoZSBmaWxsIGdyb3VwLCBqdXN0IHNvXG4gICAgICAgICAgICAvLyB3ZSBjYW4gZ2l2ZSBpdCBpdHMgb3duIGRhdGEgbGF0ZXIgb24gYW5kIHRoZSBncm91cCBjYW5cbiAgICAgICAgICAgIC8vIGtlZXAgaXRzIHNpbXBsZSAnXypGaWxsJyBkYXRhXG4gICAgICAgICAgICB0cmFjZVtkXSA9IGVuc3VyZVNpbmdsZShkMy5zZWxlY3QodGhpcyksICdwYXRoJywgJ2pzLWZpbGwnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHBsb3RPbmUoZ2QsIGlkeCwgcGxvdGluZm8sIGNkc2NhdHRlciwgY2RzY2F0dGVyQWxsLCBlbGVtZW50LCB0cmFuc2l0aW9uT3B0cykge1xuICAgIHZhciBpO1xuXG4gICAgLy8gU2luY2UgdGhpcyBoYXMgYmVlbiByZW9yZ2FuaXplZCBhbmQgd2UncmUgZXhlY3V0aW5nIHRoaXMgb24gaW5kaXZpZHVhbCB0cmFjZXMsXG4gICAgLy8gd2UgbmVlZCB0byBwYXNzIGl0IHRoZSBmdWxsIGxpc3Qgb2YgY2RzY2F0dGVyIGFzIHdlbGwgYXMgdGhpcyB0cmFjZSdzIGluZGV4IChpZHgpXG4gICAgLy8gc2luY2UgaXQgZG9lcyBhbiBpbnRlcm5hbCBuXjIgbG9vcCBvdmVyIGNvbXBhcmlzb25zIHdpdGggb3RoZXIgdHJhY2VzOlxuICAgIHNlbGVjdE1hcmtlcnMoZ2QsIGlkeCwgcGxvdGluZm8sIGNkc2NhdHRlciwgY2RzY2F0dGVyQWxsKTtcblxuICAgIHZhciBoYXNUcmFuc2l0aW9uID0gISF0cmFuc2l0aW9uT3B0cyAmJiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDA7XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uKHNlbGVjdGlvbikge1xuICAgICAgICByZXR1cm4gaGFzVHJhbnNpdGlvbiA/IHNlbGVjdGlvbi50cmFuc2l0aW9uKCkgOiBzZWxlY3Rpb247XG4gICAgfVxuXG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXMsXG4gICAgICAgIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICB2YXIgdHJhY2UgPSBjZHNjYXR0ZXJbMF0udHJhY2U7XG4gICAgdmFyIGxpbmUgPSB0cmFjZS5saW5lO1xuICAgIHZhciB0ciA9IGQzLnNlbGVjdChlbGVtZW50KTtcblxuICAgIHZhciBlcnJvckJhckdyb3VwID0gZW5zdXJlU2luZ2xlKHRyLCAnZycsICdlcnJvcmJhcnMnKTtcbiAgICB2YXIgbGluZXMgPSBlbnN1cmVTaW5nbGUodHIsICdnJywgJ2xpbmVzJyk7XG4gICAgdmFyIHBvaW50cyA9IGVuc3VyZVNpbmdsZSh0ciwgJ2cnLCAncG9pbnRzJyk7XG4gICAgdmFyIHRleHQgPSBlbnN1cmVTaW5nbGUodHIsICdnJywgJ3RleHQnKTtcblxuICAgIC8vIGVycm9yIGJhcnMgYXJlIGF0IHRoZSBib3R0b21cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdwbG90JykoZXJyb3JCYXJHcm91cCwgcGxvdGluZm8sIHRyYW5zaXRpb25PcHRzKTtcblxuICAgIGlmKHRyYWNlLnZpc2libGUgIT09IHRydWUpIHJldHVybjtcblxuICAgIHRyYW5zaXRpb24odHIpLnN0eWxlKCdvcGFjaXR5JywgdHJhY2Uub3BhY2l0eSk7XG5cbiAgICAvLyBCVUlMRCBMSU5FUyBBTkQgRklMTFNcbiAgICB2YXIgb3duRmlsbEVsMywgdG9uZXh0O1xuICAgIHZhciBvd25GaWxsRGlyID0gdHJhY2UuZmlsbC5jaGFyQXQodHJhY2UuZmlsbC5sZW5ndGggLSAxKTtcbiAgICBpZihvd25GaWxsRGlyICE9PSAneCcgJiYgb3duRmlsbERpciAhPT0gJ3knKSBvd25GaWxsRGlyID0gJyc7XG5cbiAgICAvLyBzdG9yZSBub2RlIGZvciB0d2Vha2luZyBieSBzZWxlY3RQb2ludHNcbiAgICBpZighcGxvdGluZm8uaXNSYW5nZVBsb3QpIGNkc2NhdHRlclswXS5ub2RlMyA9IHRyO1xuXG4gICAgdmFyIHByZXZSZXZwYXRoID0gJyc7XG4gICAgdmFyIHByZXZQb2x5Z29ucyA9IFtdO1xuICAgIHZhciBwcmV2dHJhY2UgPSB0cmFjZS5fcHJldnRyYWNlO1xuXG4gICAgaWYocHJldnRyYWNlKSB7XG4gICAgICAgIHByZXZSZXZwYXRoID0gcHJldnRyYWNlLl9wcmV2UmV2cGF0aCB8fCAnJztcbiAgICAgICAgdG9uZXh0ID0gcHJldnRyYWNlLl9uZXh0RmlsbDtcbiAgICAgICAgcHJldlBvbHlnb25zID0gcHJldnRyYWNlLl9wb2x5Z29ucztcbiAgICB9XG5cbiAgICB2YXIgdGhpc3BhdGgsXG4gICAgICAgIHRoaXNyZXZwYXRoLFxuICAgICAgICAvLyBmdWxscGF0aCBpcyBhbGwgcGF0aHMgZm9yIHRoaXMgY3VydmUsIGpvaW5lZCB0b2dldGhlciBzdHJhaWdodFxuICAgICAgICAvLyBhY3Jvc3MgZ2FwcywgZm9yIGZpbGxpbmdcbiAgICAgICAgZnVsbHBhdGggPSAnJyxcbiAgICAgICAgLy8gcmV2cGF0aCBpcyBmdWxscGF0aCByZXZlcnNlZCwgZm9yIGZpbGwtdG8tbmV4dFxuICAgICAgICByZXZwYXRoID0gJycsXG4gICAgICAgIC8vIGZ1bmN0aW9ucyBmb3IgY29udmVydGluZyBhIHBvaW50IGFycmF5IHRvIGEgcGF0aFxuICAgICAgICBwYXRoZm4sIHJldnBhdGhiYXNlLCByZXZwYXRoZm4sXG4gICAgICAgIC8vIHZhcmlhYmxlcyB1c2VkIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGRhdGEgam9pblxuICAgICAgICBwdDAsIGxhc3RTZWdtZW50LCBwdDEsIHRoaXNQb2x5Z29ucztcblxuICAgIC8vIGluaXRpYWxpemUgbGluZSBqb2luIGRhdGEgLyBtZXRob2RcbiAgICB2YXIgc2VnbWVudHMgPSBbXSxcbiAgICAgICAgbWFrZVVwZGF0ZSA9IExpYi5ub29wO1xuXG4gICAgb3duRmlsbEVsMyA9IHRyYWNlLl9vd25GaWxsO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2UpIHx8IHRyYWNlLmZpbGwgIT09ICdub25lJykge1xuXG4gICAgICAgIGlmKHRvbmV4dCkge1xuICAgICAgICAgICAgLy8gVGhpcyB0ZWxscyAuc3R5bGUgd2hpY2ggdHJhY2UgdG8gdXNlIGZvciBmaWxsIGluZm9ybWF0aW9uOlxuICAgICAgICAgICAgdG9uZXh0LmRhdHVtKGNkc2NhdHRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihbJ2h2JywgJ3ZoJywgJ2h2aCcsICd2aHYnXS5pbmRleE9mKGxpbmUuc2hhcGUpICE9PSAtMSkge1xuICAgICAgICAgICAgcGF0aGZuID0gRHJhd2luZy5zdGVwcyhsaW5lLnNoYXBlKTtcbiAgICAgICAgICAgIHJldnBhdGhiYXNlID0gRHJhd2luZy5zdGVwcyhcbiAgICAgICAgICAgICAgICBsaW5lLnNoYXBlLnNwbGl0KCcnKS5yZXZlcnNlKCkuam9pbignJylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihsaW5lLnNoYXBlID09PSAnc3BsaW5lJykge1xuICAgICAgICAgICAgcGF0aGZuID0gcmV2cGF0aGJhc2UgPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcExhc3QgPSBwdHNbcHRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIGlmKHB0cy5sZW5ndGggPiAxICYmIHB0c1swXVswXSA9PT0gcExhc3RbMF0gJiYgcHRzWzBdWzFdID09PSBwTGFzdFsxXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZGVudGljYWwgc3RhcnQgYW5kIGVuZCBwb2ludHM6IHRyZWF0IGl0IGFzIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xvc2VkIGN1cnZlIHNvIHdlIGRvbid0IGdldCBhIGtpbmtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3RoY2xvc2VkKHB0cy5zbGljZSgxKSwgbGluZS5zbW9vdGhpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3Rob3BlbihwdHMsIGxpbmUuc21vb3RoaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcGF0aGZuID0gcmV2cGF0aGJhc2UgPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ00nICsgcHRzLmpvaW4oJ0wnKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXZwYXRoZm4gPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgIC8vIG5vdGU6IHRoaXMgaXMgZGVzdHJ1Y3RpdmUgKHJldmVyc2VzIHB0cyBpbiBwbGFjZSkgc28gY2FuJ3QgdXNlIHB0cyBhZnRlciB0aGlzXG4gICAgICAgICAgICByZXR1cm4gcmV2cGF0aGJhc2UocHRzLnJldmVyc2UoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2VnbWVudHMgPSBsaW5lUG9pbnRzKGNkc2NhdHRlciwge1xuICAgICAgICAgICAgeGF4aXM6IHhhLFxuICAgICAgICAgICAgeWF4aXM6IHlhLFxuICAgICAgICAgICAgY29ubmVjdEdhcHM6IHRyYWNlLmNvbm5lY3RnYXBzLFxuICAgICAgICAgICAgYmFzZVRvbGVyYW5jZTogTWF0aC5tYXgobGluZS53aWR0aCB8fCAxLCAzKSAvIDQsXG4gICAgICAgICAgICBzaGFwZTogbGluZS5zaGFwZSxcbiAgICAgICAgICAgIHNpbXBsaWZ5OiBsaW5lLnNpbXBsaWZ5XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHNpbmNlIHdlIGFscmVhZHkgaGF2ZSB0aGUgcGl4ZWwgc2VnbWVudHMgaGVyZSwgdXNlIHRoZW0gdG8gbWFrZVxuICAgICAgICAvLyBwb2x5Z29ucyBmb3IgaG92ZXIgb24gZmlsbFxuICAgICAgICAvLyBUT0RPOiBjYW4gd2Ugc2tpcCB0aGlzIGlmIGhvdmVyb24hPWZpbGxzPyBUaGF0IHdvdWxkIG1lYW4gd2VcbiAgICAgICAgLy8gbmVlZCB0byByZWRyYXcgd2hlbiB5b3UgY2hhbmdlIGhvdmVyb24uLi5cbiAgICAgICAgdGhpc1BvbHlnb25zID0gdHJhY2UuX3BvbHlnb25zID0gbmV3IEFycmF5KHNlZ21lbnRzLmxlbmd0aCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0cmFjZS5fcG9seWdvbnNbaV0gPSBwb2x5Z29uVGVzdGVyKHNlZ21lbnRzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcHQwID0gc2VnbWVudHNbMF1bMF07XG4gICAgICAgICAgICBsYXN0U2VnbWVudCA9IHNlZ21lbnRzW3NlZ21lbnRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgcHQxID0gbGFzdFNlZ21lbnRbbGFzdFNlZ21lbnQubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cblxuICAgICAgICBtYWtlVXBkYXRlID0gZnVuY3Rpb24oaXNFbnRlcikge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHB0cykge1xuICAgICAgICAgICAgICAgIHRoaXNwYXRoID0gcGF0aGZuKHB0cyk7XG4gICAgICAgICAgICAgICAgdGhpc3JldnBhdGggPSByZXZwYXRoZm4ocHRzKTtcbiAgICAgICAgICAgICAgICBpZighZnVsbHBhdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbHBhdGggPSB0aGlzcGF0aDtcbiAgICAgICAgICAgICAgICAgICAgcmV2cGF0aCA9IHRoaXNyZXZwYXRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKG93bkZpbGxEaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbHBhdGggKz0gJ0wnICsgdGhpc3BhdGguc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICAgICByZXZwYXRoID0gdGhpc3JldnBhdGggKyAoJ0wnICsgcmV2cGF0aC5zdWJzdHIoMSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbHBhdGggKz0gJ1onICsgdGhpc3BhdGg7XG4gICAgICAgICAgICAgICAgICAgIHJldnBhdGggPSB0aGlzcmV2cGF0aCArICdaJyArIHJldnBhdGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2UpICYmIHB0cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG1ha2VzIHRoZSBjb2xvcmluZyB3b3JrIGNvcnJlY3RseTpcbiAgICAgICAgICAgICAgICAgICAgZWwuZGF0dW0oY2RzY2F0dGVyKTtcblxuICAgICAgICAgICAgICAgICAgICBpZihpc0VudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uKGVsLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXR0cignZCcsIHRoaXNwYXRoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcubGluZUdyb3VwU3R5bGUpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWwgPSB0cmFuc2l0aW9uKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5hdHRyKCdkJywgdGhpc3BhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRHJhd2luZy5zaW5nbGVMaW5lU3R5bGUoY2RzY2F0dGVyLCBzZWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgbGluZUpvaW4gPSBsaW5lcy5zZWxlY3RBbGwoJy5qcy1saW5lJykuZGF0YShzZWdtZW50cyk7XG5cbiAgICB0cmFuc2l0aW9uKGxpbmVKb2luLmV4aXQoKSlcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgbGluZUpvaW4uZWFjaChtYWtlVXBkYXRlKGZhbHNlKSk7XG5cbiAgICBsaW5lSm9pbi5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKCdqcy1saW5lJywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpXG4gICAgICAgIC5jYWxsKERyYXdpbmcubGluZUdyb3VwU3R5bGUpXG4gICAgICAgIC5lYWNoKG1ha2VVcGRhdGUodHJ1ZSkpO1xuXG4gICAgRHJhd2luZy5zZXRDbGlwVXJsKGxpbmVKb2luLCBwbG90aW5mby5sYXllckNsaXBJZCk7XG5cbiAgICBmdW5jdGlvbiBjbGVhckZpbGwoc2VsZWN0aW9uKSB7XG4gICAgICAgIHRyYW5zaXRpb24oc2VsZWN0aW9uKS5hdHRyKCdkJywgJ00wLDBaJyk7XG4gICAgfVxuXG4gICAgaWYoc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIGlmKG93bkZpbGxFbDMpIHtcbiAgICAgICAgICAgIG93bkZpbGxFbDMuZGF0dW0oY2RzY2F0dGVyKTtcbiAgICAgICAgICAgIGlmKHB0MCAmJiBwdDEpIHtcbiAgICAgICAgICAgICAgICBpZihvd25GaWxsRGlyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKG93bkZpbGxEaXIgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQwWzFdID0gcHQxWzFdID0geWEuYzJwKDAsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYob3duRmlsbERpciA9PT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdDBbMF0gPSBwdDFbMF0gPSB4YS5jMnAoMCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBmaWxsIHRvIHplcm86IGZ1bGwgdHJhY2UgcGF0aCwgcGx1cyBleHRlbnNpb24gb2ZcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGVuZHBvaW50cyB0byB0aGUgYXBwcm9wcmlhdGUgYXhpc1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3IgdGhlIHNha2Ugb2YgYW5pbWF0aW9ucywgd3JhcCB0aGUgcG9pbnRzIGFyb3VuZCBzbyB0aGF0XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBwb2ludHMgb24gdGhlIGF4ZXMgYXJlIHRoZSBmaXJzdCB0d28gcG9pbnRzLiBPdGhlcndpc2VcbiAgICAgICAgICAgICAgICAgICAgLy8gYW5pbWF0aW9ucyBnZXQgYSBsaXR0bGUgY3JhenkgaWYgdGhlIG51bWJlciBvZiBwb2ludHMgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbihvd25GaWxsRWwzKS5hdHRyKCdkJywgJ00nICsgcHQxICsgJ0wnICsgcHQwICsgJ0wnICsgZnVsbHBhdGguc3Vic3RyKDEpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zaW5nbGVGaWxsU3R5bGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGZpbGwgdG8gc2VsZjoganVzdCBqb2luIHRoZSBwYXRoIHRvIGl0c2VsZlxuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uKG93bkZpbGxFbDMpLmF0dHIoJ2QnLCBmdWxscGF0aCArICdaJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2luZ2xlRmlsbFN0eWxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih0b25leHQpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLmZpbGwuc3Vic3RyKDAsIDYpID09PSAndG9uZXh0JyAmJiBmdWxscGF0aCAmJiBwcmV2UmV2cGF0aCkge1xuICAgICAgICAgICAgICAgIC8vIGZpbGwgdG8gbmV4dDogZnVsbCB0cmFjZSBwYXRoLCBwbHVzIHRoZSBwcmV2aW91cyBwYXRoIHJldmVyc2VkXG4gICAgICAgICAgICAgICAgaWYodHJhY2UuZmlsbCA9PT0gJ3RvbmV4dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdG9uZXh0OiBmb3IgdXNlIGJ5IGNvbmNlbnRyaWMgc2hhcGVzLCBsaWtlIG1hbnVhbGx5IGNvbnN0cnVjdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnRvdXJzLCB3ZSBqdXN0IGFkZCB0aGUgdHdvIHBhdGhzIGNsb3NlZCBvbiB0aGVtc2VsdmVzLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG1ha2VzIHN0cmFuZ2UgcmVzdWx0cyBpZiBvbmUgcGF0aCBpcyAqbm90KiBlbnRpcmVseVxuICAgICAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdGhlIG90aGVyLCBidXQgdGhlbiB0aGF0IGlzIGEgc3RyYW5nZSB1c2FnZS5cbiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbih0b25leHQpLmF0dHIoJ2QnLCBmdWxscGF0aCArICdaJyArIHByZXZSZXZwYXRoICsgJ1onKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zaW5nbGVGaWxsU3R5bGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdG9uZXh0eC95OiBmb3Igbm93IGp1c3QgY29ubmVjdCBlbmRwb2ludHMgd2l0aCBsaW5lcy4gVGhpcyBpc1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY29ycmVjdCBiZWhhdmlvciBpZiB0aGUgZW5kcG9pbnRzIGFyZSBhdCB0aGUgc2FtZSB2YWx1ZSBvZlxuICAgICAgICAgICAgICAgICAgICAvLyB5L3gsIGJ1dCBpZiB0aGV5ICphcmVuJ3QqLCB3ZSBzaG91bGQgaWRlYWxseSBkbyBtb3JlIGNvbXBsaWNhdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaW5ncyBkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgbmV3IGVuZHBvaW50IHByb2plY3RzIG9udG8gdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIGV4aXN0aW5nIGN1cnZlIG9yIG9mZiB0aGUgZW5kIG9mIGl0XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24odG9uZXh0KS5hdHRyKCdkJywgZnVsbHBhdGggKyAnTCcgKyBwcmV2UmV2cGF0aC5zdWJzdHIoMSkgKyAnWicpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNpbmdsZUZpbGxTdHlsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyYWNlLl9wb2x5Z29ucyA9IHRyYWNlLl9wb2x5Z29ucy5jb25jYXQocHJldlBvbHlnb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNsZWFyRmlsbCh0b25leHQpO1xuICAgICAgICAgICAgICAgIHRyYWNlLl9wb2x5Z29ucyA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2UuX3ByZXZSZXZwYXRoID0gcmV2cGF0aDtcbiAgICAgICAgdHJhY2UuX3ByZXZQb2x5Z29ucyA9IHRoaXNQb2x5Z29ucztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmKG93bkZpbGxFbDMpIGNsZWFyRmlsbChvd25GaWxsRWwzKTtcbiAgICAgICAgZWxzZSBpZih0b25leHQpIGNsZWFyRmlsbCh0b25leHQpO1xuICAgICAgICB0cmFjZS5fcG9seWdvbnMgPSB0cmFjZS5fcHJldlJldnBhdGggPSB0cmFjZS5fcHJldlBvbHlnb25zID0gbnVsbDtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIHZpc0ZpbHRlcihkKSB7XG4gICAgICAgIHJldHVybiBkLmZpbHRlcihmdW5jdGlvbih2KSB7IHJldHVybiAhdi5nYXAgJiYgdi52aXM7IH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZpc0ZpbHRlcldpdGhHYXBzKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZmlsdGVyKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYudmlzOyB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnYXBGaWx0ZXIoZCkge1xuICAgICAgICByZXR1cm4gZC5maWx0ZXIoZnVuY3Rpb24odikgeyByZXR1cm4gIXYuZ2FwOyB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBrZXlGdW5jKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuaWQ7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIGlmIHRoZSB0cmFjZSBpcyBrZXllZCwgb3RoZXJ3aXNlIHJldHVybnMgdW5kZWZpbmVkXG4gICAgZnVuY3Rpb24gZ2V0S2V5RnVuYyh0cmFjZSkge1xuICAgICAgICBpZih0cmFjZS5pZHMpIHtcbiAgICAgICAgICAgIHJldHVybiBrZXlGdW5jO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGlkZUZpbHRlcigpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VQb2ludHMocG9pbnRzLCB0ZXh0LCBjZHNjYXR0ZXIpIHtcbiAgICAgICAgdmFyIGpvaW4sIHNlbGVjdGlvbiwgaGFzTm9kZTtcblxuICAgICAgICB2YXIgdHJhY2UgPSBjZHNjYXR0ZXJbMF0udHJhY2U7XG4gICAgICAgIHZhciBzaG93TWFya2VycyA9IHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpO1xuICAgICAgICB2YXIgc2hvd1RleHQgPSBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKTtcblxuICAgICAgICB2YXIga2V5RnVuYyA9IGdldEtleUZ1bmModHJhY2UpO1xuICAgICAgICB2YXIgbWFya2VyRmlsdGVyID0gaGlkZUZpbHRlcjtcbiAgICAgICAgdmFyIHRleHRGaWx0ZXIgPSBoaWRlRmlsdGVyO1xuXG4gICAgICAgIGlmKHNob3dNYXJrZXJzIHx8IHNob3dUZXh0KSB7XG4gICAgICAgICAgICB2YXIgc2hvd0ZpbHRlciA9IGlkZW50aXR5O1xuICAgICAgICAgICAgLy8gaWYgd2UncmUgc3RhY2tpbmcsIFwiaW5mZXIgemVyb1wiIGdhcCBtb2RlIGdldHMgbWFya2VycyBpbiB0aGVcbiAgICAgICAgICAgIC8vIGdhcCBwb2ludHMgLSBiZWNhdXNlIHdlJ3ZlIGluZmVycmVkIGEgemVybyB0aGVyZSAtIGJ1dCBvdGhlclxuICAgICAgICAgICAgLy8gbW9kZXMgKGN1cnJlbnRseSBcImludGVycG9sYXRlXCIsIGxhdGVyIFwiaW50ZXJydXB0XCIgaG9wZWZ1bGx5KVxuICAgICAgICAgICAgLy8gd2UgZG9uJ3QgZHJhdyBnZW5lcmF0ZWQgbWFya2Vyc1xuICAgICAgICAgICAgdmFyIHN0YWNrR3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwO1xuICAgICAgICAgICAgdmFyIGlzSW5mZXJaZXJvID0gc3RhY2tHcm91cCAmJiAoXG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHNbeGEuX2lkICsgeWEuX2lkXVtzdGFja0dyb3VwXS5zdGFja2dhcHMgPT09ICdpbmZlciB6ZXJvJyk7XG4gICAgICAgICAgICBpZih0cmFjZS5tYXJrZXIubWF4ZGlzcGxheWVkIHx8IHRyYWNlLl9uZWVkc0N1bGwpIHtcbiAgICAgICAgICAgICAgICBzaG93RmlsdGVyID0gaXNJbmZlclplcm8gPyB2aXNGaWx0ZXJXaXRoR2FwcyA6IHZpc0ZpbHRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoc3RhY2tHcm91cCAmJiAhaXNJbmZlclplcm8pIHtcbiAgICAgICAgICAgICAgICBzaG93RmlsdGVyID0gZ2FwRmlsdGVyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihzaG93TWFya2VycykgbWFya2VyRmlsdGVyID0gc2hvd0ZpbHRlcjtcbiAgICAgICAgICAgIGlmKHNob3dUZXh0KSB0ZXh0RmlsdGVyID0gc2hvd0ZpbHRlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1hcmtlciBwb2ludHNcblxuICAgICAgICBzZWxlY3Rpb24gPSBwb2ludHMuc2VsZWN0QWxsKCdwYXRoLnBvaW50Jyk7XG5cbiAgICAgICAgam9pbiA9IHNlbGVjdGlvbi5kYXRhKG1hcmtlckZpbHRlciwga2V5RnVuYyk7XG5cbiAgICAgICAgdmFyIGVudGVyID0gam9pbi5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuY2xhc3NlZCgncG9pbnQnLCB0cnVlKTtcblxuICAgICAgICBpZihoYXNUcmFuc2l0aW9uKSB7XG4gICAgICAgICAgICBlbnRlclxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcucG9pbnRTdHlsZSwgdHJhY2UsIGdkKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcudHJhbnNsYXRlUG9pbnRzLCB4YSwgeWEpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSk7XG4gICAgICAgIH1cblxuICAgICAgICBqb2luLm9yZGVyKCk7XG5cbiAgICAgICAgdmFyIHN0eWxlRm5zO1xuICAgICAgICBpZihzaG93TWFya2Vycykge1xuICAgICAgICAgICAgc3R5bGVGbnMgPSBEcmF3aW5nLm1ha2VQb2ludFN0eWxlRm5zKHRyYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGpvaW4uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgc2VsID0gdHJhbnNpdGlvbihlbCk7XG4gICAgICAgICAgICBoYXNOb2RlID0gRHJhd2luZy50cmFuc2xhdGVQb2ludChkLCBzZWwsIHhhLCB5YSk7XG5cbiAgICAgICAgICAgIGlmKGhhc05vZGUpIHtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLnNpbmdsZVBvaW50U3R5bGUoZCwgc2VsLCB0cmFjZSwgc3R5bGVGbnMsIGdkKTtcblxuICAgICAgICAgICAgICAgIGlmKHBsb3RpbmZvLmxheWVyQ2xpcElkKSB7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50KGQsIHNlbCwgeGEsIHlhLCB0cmFjZS54Y2FsZW5kYXIsIHRyYWNlLnljYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYodHJhY2UuY3VzdG9tZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBlbC5jbGFzc2VkKCdwbG90bHktY3VzdG9tZGF0YScsIGQuZGF0YSAhPT0gbnVsbCAmJiBkLmRhdGEgIT09IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWwucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGhhc1RyYW5zaXRpb24pIHtcbiAgICAgICAgICAgIGpvaW4uZXhpdCgpLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAgICAgICAgICAgLnJlbW92ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgam9pbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0ZXh0IHBvaW50c1xuICAgICAgICBzZWxlY3Rpb24gPSB0ZXh0LnNlbGVjdEFsbCgnZycpO1xuICAgICAgICBqb2luID0gc2VsZWN0aW9uLmRhdGEodGV4dEZpbHRlciwga2V5RnVuYyk7XG5cbiAgICAgICAgLy8gZWFjaCB0ZXh0IG5lZWRzIHRvIGdvIGluIGl0cyBvd24gJ2cnIGluIGNhc2VcbiAgICAgICAgLy8gaXQgZ2V0cyBjb252ZXJ0ZWQgdG8gbWF0aGpheFxuICAgICAgICBqb2luLmVudGVyKCkuYXBwZW5kKCdnJykuY2xhc3NlZCgndGV4dHBvaW50JywgdHJ1ZSkuYXBwZW5kKCd0ZXh0Jyk7XG5cbiAgICAgICAgam9pbi5vcmRlcigpO1xuXG4gICAgICAgIGpvaW4uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgZyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBzZWwgPSB0cmFuc2l0aW9uKGcuc2VsZWN0KCd0ZXh0JykpO1xuICAgICAgICAgICAgaGFzTm9kZSA9IERyYXdpbmcudHJhbnNsYXRlUG9pbnQoZCwgc2VsLCB4YSwgeWEpO1xuXG4gICAgICAgICAgICBpZihoYXNOb2RlKSB7XG4gICAgICAgICAgICAgICAgaWYocGxvdGluZm8ubGF5ZXJDbGlwSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgRHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnQoZCwgZywgeGEsIHlhLCB0cmFjZS54Y2FsZW5kYXIsIHRyYWNlLnljYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBnLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBqb2luLnNlbGVjdEFsbCgndGV4dCcpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnRleHRQb2ludFN0eWxlLCB0cmFjZSwgZ2QpXG4gICAgICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBqdXN0ICpoYXMqIHRvIGJlIHRvdGFsbHkgY3VzdG9tIGJlY3Vhc2Ugb2YgU1ZHIHRleHQgcG9zaXRpb25pbmcgOihcbiAgICAgICAgICAgICAgICAvLyBJdCdzIG9idmlvdXNseSBjb3BpZWQgZnJvbSB0cmFuc2xhdGVQb2ludDsgd2UganVzdCBjYW4ndCB1c2UgdGhhdFxuICAgICAgICAgICAgICAgIHZhciB4ID0geGEuYzJwKGQueCk7XG4gICAgICAgICAgICAgICAgdmFyIHkgPSB5YS5jMnAoZC55KTtcblxuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3RzcGFuLmxpbmUnKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uKGQzLnNlbGVjdCh0aGlzKSkuYXR0cih7eDogeCwgeTogeX0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgam9pbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgcG9pbnRzLmRhdHVtKGNkc2NhdHRlcik7XG4gICAgdGV4dC5kYXR1bShjZHNjYXR0ZXIpO1xuICAgIG1ha2VQb2ludHMocG9pbnRzLCB0ZXh0LCBjZHNjYXR0ZXIpO1xuXG4gICAgLy8gbGFzdGx5LCBjbGlwIHBvaW50cyBncm91cHMgb2YgYGNsaXBvbmF4aXMgIT09IGZhbHNlYCB0cmFjZXNcbiAgICAvLyBvbiBgcGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSA9PT0gdHJ1ZWAgc3VicGxvdHNcbiAgICB2YXIgaGFzQ2xpcE9uQXhpc0ZhbHNlID0gdHJhY2UuY2xpcG9uYXhpcyA9PT0gZmFsc2U7XG4gICAgdmFyIGNsaXBVcmwgPSBoYXNDbGlwT25BeGlzRmFsc2UgPyBudWxsIDogcGxvdGluZm8ubGF5ZXJDbGlwSWQ7XG4gICAgRHJhd2luZy5zZXRDbGlwVXJsKHBvaW50cywgY2xpcFVybCk7XG4gICAgRHJhd2luZy5zZXRDbGlwVXJsKHRleHQsIGNsaXBVcmwpO1xufVxuXG5mdW5jdGlvbiBzZWxlY3RNYXJrZXJzKGdkLCBpZHgsIHBsb3RpbmZvLCBjZHNjYXR0ZXIsIGNkc2NhdHRlckFsbCkge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzLFxuICAgICAgICB5YSA9IHBsb3RpbmZvLnlheGlzLFxuICAgICAgICB4ciA9IGQzLmV4dGVudChMaWIuc2ltcGxlTWFwKHhhLnJhbmdlLCB4YS5yMmMpKSxcbiAgICAgICAgeXIgPSBkMy5leHRlbnQoTGliLnNpbXBsZU1hcCh5YS5yYW5nZSwgeWEucjJjKSk7XG5cbiAgICB2YXIgdHJhY2UgPSBjZHNjYXR0ZXJbMF0udHJhY2U7XG4gICAgaWYoIXN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpKSByZXR1cm47XG4gICAgLy8gaWYgbWFya2VyLm1heGRpc3BsYXllZCBpcyB1c2VkLCBzZWxlY3QgYSBtYXhpbXVtIG9mXG4gICAgLy8gbW51bSBtYXJrZXJzIHRvIHNob3csIGZyb20gdGhlIHNldCB0aGF0IGFyZSBpbiB0aGUgdmlld3BvcnRcbiAgICB2YXIgbW51bSA9IHRyYWNlLm1hcmtlci5tYXhkaXNwbGF5ZWQ7XG5cbiAgICAvLyBUT0RPOiByZW1vdmUgc29tZSBhcyB3ZSBnZXQgYXdheSBmcm9tIHRoZSB2aWV3cG9ydD9cbiAgICBpZihtbnVtID09PSAwKSByZXR1cm47XG5cbiAgICB2YXIgY2QgPSBjZHNjYXR0ZXIuZmlsdGVyKGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiB2LnggPj0geHJbMF0gJiYgdi54IDw9IHhyWzFdICYmIHYueSA+PSB5clswXSAmJiB2LnkgPD0geXJbMV07XG4gICAgICAgIH0pLFxuICAgICAgICBpbmMgPSBNYXRoLmNlaWwoY2QubGVuZ3RoIC8gbW51bSksXG4gICAgICAgIHRudW0gPSAwO1xuICAgIGNkc2NhdHRlckFsbC5mb3JFYWNoKGZ1bmN0aW9uKGNkaiwgaikge1xuICAgICAgICB2YXIgdHJhY2VpID0gY2RqWzBdLnRyYWNlO1xuICAgICAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlaSkgJiZcbiAgICAgICAgICAgICAgICB0cmFjZWkubWFya2VyLm1heGRpc3BsYXllZCA+IDAgJiYgaiA8IGlkeCkge1xuICAgICAgICAgICAgdG51bSsrO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBpZiBtdWx0aXBsZSB0cmFjZXMgdXNlIG1heGRpc3BsYXllZCwgc3RhZ2dlciB3aGljaCBtYXJrZXJzIHdlXG4gICAgLy8gZGlzcGxheSB0aGlzIGZvcm11bGEgb2Zmc2V0cyBzdWNjZXNzaXZlIHRyYWNlcyBieSAxLzMgb2YgdGhlXG4gICAgLy8gaW5jcmVtZW50LCBhZGRpbmcgYW4gZXh0cmEgc21hbGwgYW1vdW50IGFmdGVyIGVhY2ggdHJpcGxldCBzb1xuICAgIC8vIGl0J3Mgbm90IHF1aXRlIHBlcmlvZGljXG4gICAgdmFyIGkwID0gTWF0aC5yb3VuZCh0bnVtICogaW5jIC8gMyArIE1hdGguZmxvb3IodG51bSAvIDMpICogaW5jIC8gNy4xKTtcblxuICAgIC8vIGZvciBlcnJvciBiYXJzOiBzYXZlIGluIGNkIHdoaWNoIG1hcmtlcnMgdG8gc2hvd1xuICAgIC8vIHNvIHdlIGRvbid0IGhhdmUgdG8gcmVwZWF0IHRoaXNcbiAgICBjZHNjYXR0ZXIuZm9yRWFjaChmdW5jdGlvbih2KSB7IGRlbGV0ZSB2LnZpczsgfSk7XG4gICAgY2QuZm9yRWFjaChmdW5jdGlvbih2LCBpKSB7XG4gICAgICAgIGlmKE1hdGgucm91bmQoKGkgKyBpMCkgJSBpbmMpID09PSAwKSB2LnZpcyA9IHRydWU7XG4gICAgfSk7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHN1YnR5cGVzID0gcmVxdWlyZSgnLi9zdWJ0eXBlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkLFxuICAgICAgICB4YSA9IHNlYXJjaEluZm8ueGF4aXMsXG4gICAgICAgIHlhID0gc2VhcmNoSW5mby55YXhpcyxcbiAgICAgICAgc2VsZWN0aW9uID0gW10sXG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2UsXG4gICAgICAgIGksXG4gICAgICAgIGRpLFxuICAgICAgICB4LFxuICAgICAgICB5O1xuXG4gICAgdmFyIGhhc09ubHlMaW5lcyA9ICghc3VidHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgJiYgIXN1YnR5cGVzLmhhc1RleHQodHJhY2UpKTtcbiAgICBpZihoYXNPbmx5TGluZXMpIHJldHVybiBbXTtcblxuICAgIGlmKHNlbGVjdGlvblRlc3RlciA9PT0gZmFsc2UpIHsgLy8gY2xlYXIgc2VsZWN0aW9uXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjZFtpXS5zZWxlY3RlZCA9IDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBkaSA9IGNkW2ldO1xuICAgICAgICAgICAgeCA9IHhhLmMycChkaS54KTtcbiAgICAgICAgICAgIHkgPSB5YS5jMnAoZGkueSk7XG5cbiAgICAgICAgICAgIGlmKChkaS5pICE9PSBudWxsKSAmJiBzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBmYWxzZSwgaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyOiBkaS5pLFxuICAgICAgICAgICAgICAgICAgICB4OiB4YS5jMmQoZGkueCksXG4gICAgICAgICAgICAgICAgICAgIHk6IHlhLmMyZChkaS55KVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwZXJTdGFja0F0dHJzID0gWydvcmllbnRhdGlvbicsICdncm91cG5vcm0nLCAnc3RhY2tnYXBzJ107XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlU3RhY2tEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgc3RhY2tPcHRzID0gbGF5b3V0Ll9zY2F0dGVyU3RhY2tPcHRzO1xuXG4gICAgdmFyIHN0YWNrR3JvdXAgPSBjb2VyY2UoJ3N0YWNrZ3JvdXAnKTtcbiAgICBpZihzdGFja0dyb3VwKSB7XG4gICAgICAgIC8vIHVzZSBpbmRlcGVuZGVudCBzdGFja2luZyBvcHRpb25zIHBlciBzdWJwbG90XG4gICAgICAgIHZhciBzdWJwbG90ID0gdHJhY2VPdXQueGF4aXMgKyB0cmFjZU91dC55YXhpcztcbiAgICAgICAgdmFyIHN1YnBsb3RTdGFja09wdHMgPSBzdGFja09wdHNbc3VicGxvdF07XG4gICAgICAgIGlmKCFzdWJwbG90U3RhY2tPcHRzKSBzdWJwbG90U3RhY2tPcHRzID0gc3RhY2tPcHRzW3N1YnBsb3RdID0ge307XG5cbiAgICAgICAgdmFyIGdyb3VwT3B0cyA9IHN1YnBsb3RTdGFja09wdHNbc3RhY2tHcm91cF07XG4gICAgICAgIHZhciBmaXJzdFRyYWNlID0gZmFsc2U7XG4gICAgICAgIGlmKGdyb3VwT3B0cykge1xuICAgICAgICAgICAgZ3JvdXBPcHRzLnRyYWNlcy5wdXNoKHRyYWNlT3V0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdyb3VwT3B0cyA9IHN1YnBsb3RTdGFja09wdHNbc3RhY2tHcm91cF0gPSB7XG4gICAgICAgICAgICAgICAgLy8ga2VlcCB0cmFjayBvZiB0cmFjZSBpbmRpY2VzIGZvciB1c2UgZHVyaW5nIHN0YWNraW5nIGNhbGN1bGF0aW9uc1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgd2lsbCBiZSBmaWxsZWQgaW4gZHVyaW5nIGBjYWxjYCBhbmQgdXNlZCBkdXJpbmcgYGNyb3NzVHJhY2VDYWxjYFxuICAgICAgICAgICAgICAgIC8vIHNvIGl0J3MgT0sgaWYgd2UgZG9uJ3QgcmVjcmVhdGUgaXQgZHVyaW5nIGEgbm9uLWNhbGMgZWRpdFxuICAgICAgICAgICAgICAgIHRyYWNlSW5kaWNlczogW10sXG4gICAgICAgICAgICAgICAgLy8gSG9sZCBvbiB0byB0aGUgd2hvbGUgc2V0IG9mIHByaW9yIHRyYWNlc1xuICAgICAgICAgICAgICAgIC8vIEZpcnN0IG9uZSBpcyBtb3N0IGltcG9ydGFudCwgc28gd2UgY2FuIGNsZWFyIGRlZmF1bHRzXG4gICAgICAgICAgICAgICAgLy8gdGhlcmUgaWYgd2UgZmluZCBleHBsaWNpdCB2YWx1ZXMgb25seSBpbiBsYXRlciB0cmFjZXMuXG4gICAgICAgICAgICAgICAgLy8gV2UncmUgb25seSBnb2luZyB0byAqdXNlKiB0aGUgdmFsdWVzIHN0b3JlZCBpbiBncm91cE9wdHMsXG4gICAgICAgICAgICAgICAgLy8gYnV0IGZvciB0aGUgZWRpdG9yIGFuZCB2YWxpZGF0ZSB3ZSB3YW50IHRoaW5ncyBzZWxmLWNvbnNpc3RlbnRcbiAgICAgICAgICAgICAgICAvLyBUaGUgZnVsbCBzZXQgb2YgdHJhY2VzIGlzIHVzZWQgb25seSB0byBmaXggYGZpbGxgIGRlZmF1bHQgaWZcbiAgICAgICAgICAgICAgICAvLyB3ZSBmaW5kIGBvcmllbnRhdGlvbjogJ2gnYCBiZXlvbmQgdGhlIGZpcnN0IHRyYWNlXG4gICAgICAgICAgICAgICAgdHJhY2VzOiBbdHJhY2VPdXRdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZmlyc3RUcmFjZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogaG93IGlzIHRoaXMgZ29pbmcgdG8gd29yayB3aXRoIGdyb3VwYnkgdHJhbnNmb3Jtcz9cbiAgICAgICAgLy8gaW4gcHJpbmNpcGxlIGl0IHNob3VsZCBiZSBPSyBJIGd1ZXNzLCBhcyBsb25nIGFzIGV4cGxpY2l0IGdyb3VwIHN0eWxlc1xuICAgICAgICAvLyBkb24ndCBvdmVycmlkZSBleHBsaWNpdCBiYXNlLXRyYWNlIHN0eWxlcz9cblxuICAgICAgICB2YXIgZGZsdHMgPSB7XG4gICAgICAgICAgICBvcmllbnRhdGlvbjogKHRyYWNlT3V0LnggJiYgIXRyYWNlT3V0LnkpID8gJ2gnIDogJ3YnXG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHBlclN0YWNrQXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBhdHRyID0gcGVyU3RhY2tBdHRyc1tpXTtcbiAgICAgICAgICAgIHZhciBhdHRyRm91bmQgPSBhdHRyICsgJ0ZvdW5kJztcbiAgICAgICAgICAgIGlmKCFncm91cE9wdHNbYXR0ckZvdW5kXSkge1xuICAgICAgICAgICAgICAgIHZhciB0cmFjZUhhc0F0dHIgPSB0cmFjZUluW2F0dHJdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdmFyIGlzT3JpZW50YXRpb24gPSBhdHRyID09PSAnb3JpZW50YXRpb24nO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlSGFzQXR0ciB8fCBmaXJzdFRyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwT3B0c1thdHRyXSA9IGNvZXJjZShhdHRyLCBkZmx0c1thdHRyXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaXNPcmllbnRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBPcHRzLmZpbGxEZmx0ID0gZ3JvdXBPcHRzW2F0dHJdID09PSAnaCcgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0b25leHR4JyA6ICd0b25leHR5JztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlSGFzQXR0cikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogdGhpcyB3aWxsIHNob3cgYSB2YWx1ZSBoZXJlIGV2ZW4gaWYgaXQncyBpbnZhbGlkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiB3aGljaCBjYXNlIGl0IHdpbGwgcmV2ZXJ0IHRvIGRlZmF1bHQuXG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cE9wdHNbYXR0ckZvdW5kXSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IG9ubHkgb25lIHRyYWNlIGluIHRoZSBzdGFjayB3aWxsIGdldCBhIF9mdWxsRGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW50cnkgZm9yIGEgZ2l2ZW4gc3RhY2std2lkZSBhdHRyaWJ1dGUuIElmIG5vIHRyYWNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKG9yIHRoZSBmaXJzdCB0cmFjZSkgc3BlY2lmeSB0aGF0IGF0dHJpYnV0ZSwgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaXJzdCB0cmFjZSB3aWxsIGdldCBpdC4gSWYgdGhlIGZpcnN0IHRyYWNlIGRvZXMgTk9UXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzcGVjaWZ5IGl0IGJ1dCBzb21lIGxhdGVyIHRyYWNlIGRvZXMsIHRoZW4gaXQgZ2V0c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlZCBmcm9tIHRoZSBmaXJzdCB0cmFjZSBhbmQgb25seSBpbmNsdWRlZCBpbiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9uZSB0aGF0IHNwZWNpZmllZCBpdC4gVGhpcyBpcyBtb3N0bHkgaW1wb3J0YW50IGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZWRpdG9ycyAodGhhdCB3YW50IHRvIHNlZSB0aGUgZnVsbCB2YWx1ZXMgdG8ga25vd1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hhdCBzZXR0aW5ncyBhcmUgYXZhaWxhYmxlKSBhbmQgUGxvdGx5LnJlYWN0IGRpZmZpbmcuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFZGl0b3JzIG1heSB3YW50IHRvIHVzZSBmdWxsTGF5b3V0Ll9zY2F0dGVyU3RhY2tPcHRzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkaXJlY3RseSBhbmQgbWFrZSB0aGVzZSBzZXR0aW5ncyBhdmFpbGFibGUgZnJvbSBhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyYWNlcyBpbiB0aGUgc3RhY2suLi4gdGhlbiBzZXQgdGhlIG5ldyB2YWx1ZSBpbnRvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZmlyc3QgdHJhY2UsIGFuZCBjbGVhciBhbGwgbGF0ZXIgdHJhY2VzLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIWZpcnN0VHJhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZ3JvdXBPcHRzLnRyYWNlc1swXVthdHRyXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yaWVudGF0aW9uIGNhbiBhZmZlY3QgZGVmYXVsdCBmaWxsIG9mIHByZXZpb3VzIHRyYWNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzT3JpZW50YXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGdyb3VwT3B0cy50cmFjZXMubGVuZ3RoIC0gMTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2UyID0gZ3JvdXBPcHRzLnRyYWNlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlMi5faW5wdXQuZmlsbCAhPT0gdHJhY2UyLmZpbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZTIuZmlsbCA9IGdyb3VwT3B0cy5maWxsRGZsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ3JvdXBPcHRzO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5mdW5jdGlvbiBzdHlsZShnZCwgY2QpIHtcbiAgICB2YXIgcyA9IGNkID8gY2RbMF0ubm9kZTMgOiBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnZy50cmFjZS5zY2F0dGVyJyk7XG5cbiAgICBzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5O1xuICAgIH0pO1xuXG4gICAgcy5zZWxlY3RBbGwoJ2cucG9pbnRzJykuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0cmFjZSA9IGQudHJhY2UgfHwgZFswXS50cmFjZTtcbiAgICAgICAgc3R5bGVQb2ludHMoc2VsLCB0cmFjZSwgZ2QpO1xuICAgIH0pO1xuXG4gICAgcy5zZWxlY3RBbGwoJ2cudGV4dCcpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBkLnRyYWNlIHx8IGRbMF0udHJhY2U7XG4gICAgICAgIHN0eWxlVGV4dChzZWwsIHRyYWNlLCBnZCk7XG4gICAgfSk7XG5cbiAgICBzLnNlbGVjdEFsbCgnZy50cmFjZSBwYXRoLmpzLWxpbmUnKVxuICAgICAgICAuY2FsbChEcmF3aW5nLmxpbmVHcm91cFN0eWxlKTtcblxuICAgIHMuc2VsZWN0QWxsKCdnLnRyYWNlIHBhdGguanMtZmlsbCcpXG4gICAgICAgIC5jYWxsKERyYXdpbmcuZmlsbEdyb3VwU3R5bGUpO1xuXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3R5bGUnKShzKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVQb2ludHMoc2VsLCB0cmFjZSwgZ2QpIHtcbiAgICBEcmF3aW5nLnBvaW50U3R5bGUoc2VsLnNlbGVjdEFsbCgncGF0aC5wb2ludCcpLCB0cmFjZSwgZ2QpO1xufVxuXG5mdW5jdGlvbiBzdHlsZVRleHQoc2VsLCB0cmFjZSwgZ2QpIHtcbiAgICBEcmF3aW5nLnRleHRQb2ludFN0eWxlKHNlbC5zZWxlY3RBbGwoJ3RleHQnKSwgdHJhY2UsIGdkKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVPblNlbGVjdChnZCwgY2QpIHtcbiAgICB2YXIgcyA9IGNkWzBdLm5vZGUzO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgRHJhd2luZy5zZWxlY3RlZFBvaW50U3R5bGUocy5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKSwgdHJhY2UpO1xuICAgICAgICBEcmF3aW5nLnNlbGVjdGVkVGV4dFN0eWxlKHMuc2VsZWN0QWxsKCd0ZXh0JyksIHRyYWNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzdHlsZVBvaW50cyhzLCB0cmFjZSwgZ2QpO1xuICAgICAgICBzdHlsZVRleHQocywgdHJhY2UsIGdkKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZVBvaW50czogc3R5bGVQb2ludHMsXG4gICAgc3R5bGVUZXh0OiBzdHlsZVRleHQsXG4gICAgc3R5bGVPblNlbGVjdDogc3R5bGVPblNlbGVjdFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhhc0xpbmVzOiBmdW5jdGlvbih0cmFjZSkge1xuICAgICAgICByZXR1cm4gdHJhY2UudmlzaWJsZSAmJiB0cmFjZS5tb2RlICYmXG4gICAgICAgICAgICB0cmFjZS5tb2RlLmluZGV4T2YoJ2xpbmVzJykgIT09IC0xO1xuICAgIH0sXG5cbiAgICBoYXNNYXJrZXJzOiBmdW5jdGlvbih0cmFjZSkge1xuICAgICAgICByZXR1cm4gdHJhY2UudmlzaWJsZSAmJiAoXG4gICAgICAgICAgICAodHJhY2UubW9kZSAmJiB0cmFjZS5tb2RlLmluZGV4T2YoJ21hcmtlcnMnKSAhPT0gLTEpIHx8XG4gICAgICAgICAgICAvLyB1bnRpbCBzcGxvbSBpbXBsZW1lbnRzICdtb2RlJ1xuICAgICAgICAgICAgdHJhY2UudHlwZSA9PT0gJ3NwbG9tJ1xuICAgICAgICApO1xuICAgIH0sXG5cbiAgICBoYXNUZXh0OiBmdW5jdGlvbih0cmFjZSkge1xuICAgICAgICByZXR1cm4gdHJhY2UudmlzaWJsZSAmJiB0cmFjZS5tb2RlICYmXG4gICAgICAgICAgICB0cmFjZS5tb2RlLmluZGV4T2YoJ3RleHQnKSAhPT0gLTE7XG4gICAgfSxcblxuICAgIGlzQnViYmxlOiBmdW5jdGlvbih0cmFjZSkge1xuICAgICAgICByZXR1cm4gTGliLmlzUGxhaW5PYmplY3QodHJhY2UubWFya2VyKSAmJlxuICAgICAgICAgICAgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2UubWFya2VyLnNpemUpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG4vKlxuICogb3B0czogb2JqZWN0IG9mIGZsYWdzIHRvIGNvbnRyb2wgZmVhdHVyZXMgbm90IGFsbCB0ZXh0IHVzZXJzIHN1cHBvcnRcbiAqICAgbm9TZWxlY3Q6IGNhbGxlciBkb2VzIG5vdCBzdXBwb3J0IHNlbGVjdGVkL3Vuc2VsZWN0ZWQgYXR0cmlidXRlIGNvbnRhaW5lcnNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIGNvZXJjZSgndGV4dHBvc2l0aW9uJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGV4dGZvbnQnLCBsYXlvdXQuZm9udCk7XG5cbiAgICBpZighb3B0cy5ub1NlbGVjdCkge1xuICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkLnRleHRmb250LmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgndW5zZWxlY3RlZC50ZXh0Zm9udC5jb2xvcicpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKSB7XG4gICAgdmFyIGxlbixcbiAgICAgICAgeCA9IGNvZXJjZSgneCcpLFxuICAgICAgICB5ID0gY29lcmNlKCd5Jyk7XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbJ3gnLCAneSddLCBsYXlvdXQpO1xuXG4gICAgaWYoeCkge1xuICAgICAgICBpZih5KSB7XG4gICAgICAgICAgICBsZW4gPSBNYXRoLm1pbih4Lmxlbmd0aCwgeS5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbGVuID0geC5sZW5ndGg7XG4gICAgICAgICAgICBjb2VyY2UoJ3kwJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ2R5Jyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmKCF5KSByZXR1cm4gMDtcblxuICAgICAgICBsZW4gPSB0cmFjZU91dC55Lmxlbmd0aDtcbiAgICAgICAgY29lcmNlKCd4MCcpO1xuICAgICAgICBjb2VyY2UoJ2R4Jyk7XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHJldHVybiBsZW47XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgREFTSEVTID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2dsM2RfZGFzaGVzJyk7XG5cbnZhciBNQVJLRVJfU1lNQk9MUyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnMnKTtcbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBzY2F0dGVyTGluZUF0dHJzID0gc2NhdHRlckF0dHJzLmxpbmU7XG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbnZhciBsaW5lQXR0cnMgPSBleHRlbmRGbGF0KHtcbiAgICB3aWR0aDogc2NhdHRlckxpbmVBdHRycy53aWR0aCxcbiAgICBkYXNoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBPYmplY3Qua2V5cyhEQVNIRVMpLFxuICAgICAgICBkZmx0OiAnc29saWQnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufSwgY29sb3JBdHRyaWJ1dGVzKCdsaW5lJykpO1xuLy8gbm90IHlldCBpbXBsZW1lbnRlZFxuZGVsZXRlIGxpbmVBdHRycy5zaG93c2NhbGU7XG5kZWxldGUgbGluZUF0dHJzLmNvbG9yYmFyO1xuXG5mdW5jdGlvbiBtYWtlUHJvamVjdGlvbkF0dHIoYXhMZXR0ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzaG93OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNjYWxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxMCxcbiAgICAgICAgICAgIGRmbHQ6IDIgLyAzLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgYXR0cnMgPSBtb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICB4OiBzY2F0dGVyQXR0cnMueCxcbiAgICB5OiBzY2F0dGVyQXR0cnMueSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGhvdmVydGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG1vZGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5tb2RlLCAgLy8gc2hvdWxkbid0IHRoaXMgYmUgb24tcGFyIHdpdGggMkQ/XG4gICAgICAgIHtkZmx0OiAnbGluZXMrbWFya2Vycyd9KSxcbiAgICBzdXJmYWNlYXhpczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFstMSwgMCwgMSwgMl0sXG4gICAgICAgIGRmbHQ6IC0xLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1cmZhY2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBwcm9qZWN0aW9uOiB7XG4gICAgICAgIHg6IG1ha2VQcm9qZWN0aW9uQXR0cigneCcpLFxuICAgICAgICB5OiBtYWtlUHJvamVjdGlvbkF0dHIoJ3knKSxcbiAgICAgICAgejogbWFrZVByb2plY3Rpb25BdHRyKCd6JylcbiAgICB9LFxuXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcbiAgICBsaW5lOiBsaW5lQXR0cnMsXG5cbiAgICBtYXJrZXI6IGV4dGVuZEZsYXQoeyAgLy8gUGFyaXR5IHdpdGggc2NhdHRlci5qcz9cbiAgICAgICAgc3ltYm9sOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IE9iamVjdC5rZXlzKE1BUktFUl9TWU1CT0xTKSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ2NpcmNsZScsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLCB7ZGZsdDogOH0pLFxuICAgICAgICBzaXplcmVmOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZXJlZixcbiAgICAgICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgICAgIHNpemVtb2RlOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1vZGUsXG4gICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5vcGFjaXR5LCB7XG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgY29sb3JiYXI6IHNjYXR0ZXJNYXJrZXJBdHRycy5jb2xvcmJhcixcblxuICAgICAgICBsaW5lOiBleHRlbmRGbGF0KHtcbiAgICAgICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLCB7YXJyYXlPazogZmFsc2V9KVxuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScpXG4gICAgICAgIClcbiAgICB9LFxuICAgICAgICBjb2xvckF0dHJpYnV0ZXMoJ21hcmtlcicpXG4gICAgKSxcblxuICAgIHRleHRwb3NpdGlvbjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnRleHRwb3NpdGlvbiwge2RmbHQ6ICd0b3AgY2VudGVyJywgYXJyYXlPazogZmFsc2V9KSxcbiAgICB0ZXh0Zm9udDoge1xuICAgICAgICBjb2xvcjogc2NhdHRlckF0dHJzLnRleHRmb250LmNvbG9yLFxuICAgICAgICBzaXplOiBzY2F0dGVyQXR0cnMudGV4dGZvbnQuc2l6ZSxcbiAgICAgICAgZmFtaWx5OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMudGV4dGZvbnQuZmFtaWx5LCB7YXJyYXlPazogZmFsc2V9KVxuICAgIH0sXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIGJhc2VBdHRycy5ob3ZlcmluZm8pXG59LCAnY2FsYycsICduZXN0ZWQnKTtcblxuYXR0cnMueC5lZGl0VHlwZSA9IGF0dHJzLnkuZWRpdFR5cGUgPSBhdHRycy56LmVkaXRUeXBlID0gJ2NhbGMrY2xlYXJBeGlzVHlwZXMnO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY0NvbG9yc2NhbGVzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGMnKTtcblxuXG4vKipcbiAqIFRoaXMgaXMgYSBrbHVkZ2UgdG8gcHV0IHRoZSBhcnJheSBhdHRyaWJ1dGVzIGludG9cbiAqIGNhbGNkYXRhIHRoZSB3YXkgU2NhdHRlci5wbG90IGRvZXMsIHNvIHRoYXQgbGVnZW5kcyBhbmRcbiAqIHBvcG92ZXJzIGtub3cgd2hhdCB0byBkbyB3aXRoIHRoZW0uXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2QgPSBbe3g6IGZhbHNlLCB5OiBmYWxzZSwgdHJhY2U6IHRyYWNlLCB0OiB7fX1dO1xuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNDb2xvcnNjYWxlcyh0cmFjZSk7XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5mdW5jdGlvbiBjYWxjdWxhdGVBeGlzRXJyb3JzKGRhdGEsIHBhcmFtcywgc2NhbGVGYWN0b3IsIGF4aXMpIHtcbiAgICBpZighcGFyYW1zIHx8ICFwYXJhbXMudmlzaWJsZSkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgY29tcHV0ZUVycm9yID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnbWFrZUNvbXB1dGVFcnJvcicpKHBhcmFtcyk7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShkYXRhLmxlbmd0aCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZXJyb3JzID0gY29tcHV0ZUVycm9yKCtkYXRhW2ldLCBpKTtcblxuICAgICAgICBpZihheGlzLnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgICAgICB2YXIgcG9pbnQgPSBheGlzLmMybChkYXRhW2ldKTtcbiAgICAgICAgICAgIHZhciBtaW4gPSBkYXRhW2ldIC0gZXJyb3JzWzBdLFxuICAgICAgICAgICAgICAgIG1heCA9IGRhdGFbaV0gKyBlcnJvcnNbMV07XG5cbiAgICAgICAgICAgIHJlc3VsdFtpXSA9IFtcbiAgICAgICAgICAgICAgICAoYXhpcy5jMmwobWluLCB0cnVlKSAtIHBvaW50KSAqIHNjYWxlRmFjdG9yLFxuICAgICAgICAgICAgICAgIChheGlzLmMybChtYXgsIHRydWUpIC0gcG9pbnQpICogc2NhbGVGYWN0b3JcbiAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgIC8vIEtlZXAgdHJhY2sgb2YgdGhlIGxvd2VyIGVycm9yIGJvdW5kIHdoaWNoIGlzbid0IG5lZ2F0aXZlIVxuICAgICAgICAgICAgaWYobWluID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciBsb3dlciA9IGF4aXMuYzJsKG1pbik7XG4gICAgICAgICAgICAgICAgaWYoIWF4aXMuX2xvd2VyTG9nRXJyb3JCb3VuZCkgYXhpcy5fbG93ZXJMb2dFcnJvckJvdW5kID0gbG93ZXI7XG4gICAgICAgICAgICAgICAgYXhpcy5fbG93ZXJFcnJvckJvdW5kID0gTWF0aC5taW4oYXhpcy5fbG93ZXJMb2dFcnJvckJvdW5kLCBsb3dlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRbaV0gPSBbXG4gICAgICAgICAgICAgICAgLWVycm9yc1swXSAqIHNjYWxlRmFjdG9yLFxuICAgICAgICAgICAgICAgIGVycm9yc1sxXSAqIHNjYWxlRmFjdG9yXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gZGF0YUxlbmd0aChhcnJheSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihhcnJheVtpXSkgcmV0dXJuIGFycmF5W2ldLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUVycm9ycyhkYXRhLCBzY2FsZUZhY3Rvciwgc2NlbmVMYXlvdXQpIHtcbiAgICB2YXIgZXJyb3JzID0gW1xuICAgICAgICBjYWxjdWxhdGVBeGlzRXJyb3JzKGRhdGEueCwgZGF0YS5lcnJvcl94LCBzY2FsZUZhY3RvclswXSwgc2NlbmVMYXlvdXQueGF4aXMpLFxuICAgICAgICBjYWxjdWxhdGVBeGlzRXJyb3JzKGRhdGEueSwgZGF0YS5lcnJvcl95LCBzY2FsZUZhY3RvclsxXSwgc2NlbmVMYXlvdXQueWF4aXMpLFxuICAgICAgICBjYWxjdWxhdGVBeGlzRXJyb3JzKGRhdGEueiwgZGF0YS5lcnJvcl96LCBzY2FsZUZhY3RvclsyXSwgc2NlbmVMYXlvdXQuemF4aXMpXG4gICAgXTtcblxuICAgIHZhciBuID0gZGF0YUxlbmd0aChlcnJvcnMpO1xuICAgIGlmKG4gPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgdmFyIGVycm9yQm91bmRzID0gbmV3IEFycmF5KG4pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICB2YXIgYm91bmQgPSBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCAzOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGVycm9yc1tqXSkge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCAyOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYm91bmRba11bal0gPSBlcnJvcnNbal1baV1ba107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZXJyb3JCb3VuZHNbaV0gPSBib3VuZDtcbiAgICB9XG5cbiAgICByZXR1cm4gZXJyb3JCb3VuZHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2FsY3VsYXRlRXJyb3JzO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVMaW5lUGxvdCA9IHJlcXVpcmUoJ2dsLWxpbmUzZCcpO1xudmFyIGNyZWF0ZVNjYXR0ZXJQbG90ID0gcmVxdWlyZSgnZ2wtc2NhdHRlcjNkJyk7XG52YXIgY3JlYXRlRXJyb3JCYXJzID0gcmVxdWlyZSgnZ2wtZXJyb3IzZCcpO1xudmFyIGNyZWF0ZU1lc2ggPSByZXF1aXJlKCdnbC1tZXNoM2QnKTtcbnZhciB0cmlhbmd1bGF0ZSA9IHJlcXVpcmUoJ2RlbGF1bmF5LXRyaWFuZ3VsYXRlJyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBzdHIyUmdiYUFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIGZvcm1hdENvbG9yID0gcmVxdWlyZSgnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLmZvcm1hdENvbG9yO1xudmFyIG1ha2VCdWJibGVTaXplRm4gPSByZXF1aXJlKCcuLi9zY2F0dGVyL21ha2VfYnViYmxlX3NpemVfZnVuYycpO1xudmFyIERBU0hfUEFUVEVSTlMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvZ2wzZF9kYXNoZXMnKTtcbnZhciBNQVJLRVJfU1lNQk9MUyA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnMnKTtcblxudmFyIGNhbGN1bGF0ZUVycm9yID0gcmVxdWlyZSgnLi9jYWxjX2Vycm9ycycpO1xuXG5mdW5jdGlvbiBMaW5lV2l0aE1hcmtlcnMoc2NlbmUsIHVpZCkge1xuICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB0aGlzLnVpZCA9IHVpZDtcbiAgICB0aGlzLmxpbmVQbG90ID0gbnVsbDtcbiAgICB0aGlzLnNjYXR0ZXJQbG90ID0gbnVsbDtcbiAgICB0aGlzLmVycm9yQmFycyA9IG51bGw7XG4gICAgdGhpcy50ZXh0TWFya2VycyA9IG51bGw7XG4gICAgdGhpcy5kZWxhdW5heU1lc2ggPSBudWxsO1xuICAgIHRoaXMuY29sb3IgPSBudWxsO1xuICAgIHRoaXMubW9kZSA9ICcnO1xuICAgIHRoaXMuZGF0YVBvaW50cyA9IFtdO1xuICAgIHRoaXMuYXhlc0JvdW5kcyA9IFtcbiAgICAgICAgWy1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldLFxuICAgICAgICBbSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV1cbiAgICBdO1xuICAgIHRoaXMudGV4dExhYmVscyA9IG51bGw7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbn1cblxudmFyIHByb3RvID0gTGluZVdpdGhNYXJrZXJzLnByb3RvdHlwZTtcblxucHJvdG8uaGFuZGxlUGljayA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICAgIGlmKHNlbGVjdGlvbi5vYmplY3QgJiZcbiAgICAgICAgKHNlbGVjdGlvbi5vYmplY3QgPT09IHRoaXMubGluZVBsb3QgfHxcbiAgICAgICAgIHNlbGVjdGlvbi5vYmplY3QgPT09IHRoaXMuZGVsYXVuYXlNZXNoIHx8XG4gICAgICAgICBzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLnRleHRNYXJrZXJzIHx8XG4gICAgICAgICBzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLnNjYXR0ZXJQbG90KVxuICAgICkge1xuICAgICAgICB2YXIgaW5kID0gc2VsZWN0aW9uLmluZGV4ID0gc2VsZWN0aW9uLmRhdGEuaW5kZXg7XG5cbiAgICAgICAgaWYoc2VsZWN0aW9uLm9iamVjdC5oaWdobGlnaHQpIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi5vYmplY3QuaGlnaGxpZ2h0KG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHRoaXMuc2NhdHRlclBsb3QpIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi5vYmplY3QgPSB0aGlzLnNjYXR0ZXJQbG90O1xuICAgICAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5oaWdobGlnaHQoc2VsZWN0aW9uLmRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9ICcnO1xuICAgICAgICBpZih0aGlzLnRleHRMYWJlbHMpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGhpcy50ZXh0TGFiZWxzKSkge1xuICAgICAgICAgICAgICAgIGlmKHRoaXMudGV4dExhYmVsc1tpbmRdIHx8IHRoaXMudGV4dExhYmVsc1tpbmRdID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0aGlzLnRleHRMYWJlbHNbaW5kXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0aGlzLnRleHRMYWJlbHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlID0gW1xuICAgICAgICAgICAgdGhpcy5kYXRhLnhbaW5kXSxcbiAgICAgICAgICAgIHRoaXMuZGF0YS55W2luZF0sXG4gICAgICAgICAgICB0aGlzLmRhdGEueltpbmRdXG4gICAgICAgIF07XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY29uc3RydWN0RGVsYXVuYXkocG9pbnRzLCBjb2xvciwgYXhpcykge1xuICAgIHZhciB1ID0gKGF4aXMgKyAxKSAlIDM7XG4gICAgdmFyIHYgPSAoYXhpcyArIDIpICUgMztcbiAgICB2YXIgZmlsdGVyZWRQb2ludHMgPSBbXTtcbiAgICB2YXIgZmlsdGVyZWRJZHMgPSBbXTtcbiAgICB2YXIgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgcCA9IHBvaW50c1tpXTtcbiAgICAgICAgaWYoaXNOYU4ocFt1XSkgfHwgIWlzRmluaXRlKHBbdV0pIHx8XG4gICAgICAgICAgIGlzTmFOKHBbdl0pIHx8ICFpc0Zpbml0ZShwW3ZdKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgZmlsdGVyZWRQb2ludHMucHVzaChbcFt1XSwgcFt2XV0pO1xuICAgICAgICBmaWx0ZXJlZElkcy5wdXNoKGkpO1xuICAgIH1cbiAgICB2YXIgY2VsbHMgPSB0cmlhbmd1bGF0ZShmaWx0ZXJlZFBvaW50cyk7XG4gICAgZm9yKGkgPSAwOyBpIDwgY2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGMgPSBjZWxsc1tpXTtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgIGNbal0gPSBmaWx0ZXJlZElkc1tjW2pdXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBwb3NpdGlvbnM6IHBvaW50cyxcbiAgICAgICAgY2VsbHM6IGNlbGxzLFxuICAgICAgICBtZXNoQ29sb3I6IGNvbG9yXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlRXJyb3JQYXJhbXMoZXJyb3JzKSB7XG4gICAgdmFyIGNhcFNpemUgPSBbMC4wLCAwLjAsIDAuMF0sXG4gICAgICAgIGNvbG9yID0gW1swLCAwLCAwXSwgWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxuICAgICAgICBsaW5lV2lkdGggPSBbMS4wLCAxLjAsIDEuMF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgIHZhciBlID0gZXJyb3JzW2ldO1xuXG4gICAgICAgIGlmKGUgJiYgZS5jb3B5X3pzdHlsZSAhPT0gZmFsc2UgJiYgZXJyb3JzWzJdLnZpc2libGUgIT09IGZhbHNlKSBlID0gZXJyb3JzWzJdO1xuICAgICAgICBpZighZSB8fCAhZS52aXNpYmxlKSBjb250aW51ZTtcblxuICAgICAgICBjYXBTaXplW2ldID0gZS53aWR0aCAvIDI7ICAvLyBiYWxscGFyayByZXNjYWxpbmdcbiAgICAgICAgY29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGUuY29sb3IpO1xuICAgICAgICBsaW5lV2lkdGhbaV0gPSBlLnRoaWNrbmVzcztcblxuICAgIH1cblxuICAgIHJldHVybiB7Y2FwU2l6ZTogY2FwU2l6ZSwgY29sb3I6IGNvbG9yLCBsaW5lV2lkdGg6IGxpbmVXaWR0aH07XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZVRleHRPZmZzZXQodHApIHtcbiAgICAvLyBSZWFkIG91dCB0ZXh0IHByb3BlcnRpZXNcbiAgICB2YXIgdGV4dE9mZnNldCA9IFswLCAwXTtcbiAgICBpZihBcnJheS5pc0FycmF5KHRwKSkgcmV0dXJuIFswLCAtMV07XG4gICAgaWYodHAuaW5kZXhPZignYm90dG9tJykgPj0gMCkgdGV4dE9mZnNldFsxXSArPSAxO1xuICAgIGlmKHRwLmluZGV4T2YoJ3RvcCcpID49IDApIHRleHRPZmZzZXRbMV0gLT0gMTtcbiAgICBpZih0cC5pbmRleE9mKCdsZWZ0JykgPj0gMCkgdGV4dE9mZnNldFswXSAtPSAxO1xuICAgIGlmKHRwLmluZGV4T2YoJ3JpZ2h0JykgPj0gMCkgdGV4dE9mZnNldFswXSArPSAxO1xuICAgIHJldHVybiB0ZXh0T2Zmc2V0O1xufVxuXG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZVNpemUoc2l6ZUluLCBzaXplRm4pIHtcbiAgICAvLyByb3VnaCBwYXJpdHkgd2l0aCBQbG90bHkgMkQgbWFya2Vyc1xuICAgIHJldHVybiBzaXplRm4oc2l6ZUluICogNCk7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZVN5bWJvbChzeW1ib2xJbikge1xuICAgIHJldHVybiBNQVJLRVJfU1lNQk9MU1tzeW1ib2xJbl07XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFBhcmFtKHBhcmFtSW4sIGxlbiwgY2FsY3VsYXRlLCBkZmx0LCBleHRyYUZuKSB7XG4gICAgdmFyIHBhcmFtT3V0ID0gbnVsbDtcblxuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHBhcmFtSW4pKSB7XG4gICAgICAgIHBhcmFtT3V0ID0gW107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZihwYXJhbUluW2ldID09PSB1bmRlZmluZWQpIHBhcmFtT3V0W2ldID0gZGZsdDtcbiAgICAgICAgICAgIGVsc2UgcGFyYW1PdXRbaV0gPSBjYWxjdWxhdGUocGFyYW1JbltpXSwgZXh0cmFGbik7XG4gICAgICAgIH1cblxuICAgIH1cbiAgICBlbHNlIHBhcmFtT3V0ID0gY2FsY3VsYXRlKHBhcmFtSW4sIExpYi5pZGVudGl0eSk7XG5cbiAgICByZXR1cm4gcGFyYW1PdXQ7XG59XG5cblxuZnVuY3Rpb24gY29udmVydFBsb3RseU9wdGlvbnMoc2NlbmUsIGRhdGEpIHtcbiAgICB2YXIgcGFyYW1zLCBpLFxuICAgICAgICBwb2ludHMgPSBbXSxcbiAgICAgICAgc2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQsXG4gICAgICAgIHNjYWxlRmFjdG9yID0gc2NlbmUuZGF0YVNjYWxlLFxuICAgICAgICB4YXhpcyA9IHNjZW5lTGF5b3V0LnhheGlzLFxuICAgICAgICB5YXhpcyA9IHNjZW5lTGF5b3V0LnlheGlzLFxuICAgICAgICB6YXhpcyA9IHNjZW5lTGF5b3V0LnpheGlzLFxuICAgICAgICBtYXJrZXIgPSBkYXRhLm1hcmtlcixcbiAgICAgICAgbGluZSA9IGRhdGEubGluZSxcbiAgICAgICAgeGMsIHggPSBkYXRhLnggfHwgW10sXG4gICAgICAgIHljLCB5ID0gZGF0YS55IHx8IFtdLFxuICAgICAgICB6YywgeiA9IGRhdGEueiB8fCBbXSxcbiAgICAgICAgbGVuID0geC5sZW5ndGgsXG4gICAgICAgIHhjYWxlbmRhciA9IGRhdGEueGNhbGVuZGFyLFxuICAgICAgICB5Y2FsZW5kYXIgPSBkYXRhLnljYWxlbmRhcixcbiAgICAgICAgemNhbGVuZGFyID0gZGF0YS56Y2FsZW5kYXIsXG4gICAgICAgIHRleHQ7XG5cbiAgICAvLyBDb252ZXJ0IHBvaW50c1xuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIC8vIHNhbml0aXplIG51bWJlcnMgYW5kIGFwcGx5IHRyYW5zZm9ybXMgYmFzZWQgb24gYXhlcy50eXBlXG4gICAgICAgIHhjID0geGF4aXMuZDJsKHhbaV0sIDAsIHhjYWxlbmRhcikgKiBzY2FsZUZhY3RvclswXTtcbiAgICAgICAgeWMgPSB5YXhpcy5kMmwoeVtpXSwgMCwgeWNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzFdO1xuICAgICAgICB6YyA9IHpheGlzLmQybCh6W2ldLCAwLCB6Y2FsZW5kYXIpICogc2NhbGVGYWN0b3JbMl07XG5cbiAgICAgICAgcG9pbnRzW2ldID0gW3hjLCB5YywgemNdO1xuICAgIH1cblxuICAgIC8vIGNvbnZlcnQgdGV4dFxuICAgIGlmKEFycmF5LmlzQXJyYXkoZGF0YS50ZXh0KSkgdGV4dCA9IGRhdGEudGV4dDtcbiAgICBlbHNlIGlmKGRhdGEudGV4dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRleHQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHRleHRbaV0gPSBkYXRhLnRleHQ7XG4gICAgfVxuXG4gICAgLy8gQnVpbGQgb2JqZWN0IHBhcmFtZXRlcnNcbiAgICBwYXJhbXMgPSB7XG4gICAgICAgIHBvc2l0aW9uOiBwb2ludHMsXG4gICAgICAgIG1vZGU6IGRhdGEubW9kZSxcbiAgICAgICAgdGV4dDogdGV4dFxuICAgIH07XG5cbiAgICBpZignbGluZScgaW4gZGF0YSkge1xuICAgICAgICBwYXJhbXMubGluZUNvbG9yID0gZm9ybWF0Q29sb3IobGluZSwgMSwgbGVuKTtcbiAgICAgICAgcGFyYW1zLmxpbmVXaWR0aCA9IGxpbmUud2lkdGg7XG4gICAgICAgIHBhcmFtcy5saW5lRGFzaGVzID0gbGluZS5kYXNoO1xuICAgIH1cblxuICAgIGlmKCdtYXJrZXInIGluIGRhdGEpIHtcbiAgICAgICAgdmFyIHNpemVGbiA9IG1ha2VCdWJibGVTaXplRm4oZGF0YSk7XG5cbiAgICAgICAgcGFyYW1zLnNjYXR0ZXJDb2xvciA9IGZvcm1hdENvbG9yKG1hcmtlciwgMSwgbGVuKTtcbiAgICAgICAgcGFyYW1zLnNjYXR0ZXJTaXplID0gZm9ybWF0UGFyYW0obWFya2VyLnNpemUsIGxlbiwgY2FsY3VsYXRlU2l6ZSwgMjAsIHNpemVGbik7XG4gICAgICAgIHBhcmFtcy5zY2F0dGVyTWFya2VyID0gZm9ybWF0UGFyYW0obWFya2VyLnN5bWJvbCwgbGVuLCBjYWxjdWxhdGVTeW1ib2wsICfil48nKTtcbiAgICAgICAgcGFyYW1zLnNjYXR0ZXJMaW5lV2lkdGggPSBtYXJrZXIubGluZS53aWR0aDsgIC8vIGFycmF5T2sgPT09IGZhbHNlXG4gICAgICAgIHBhcmFtcy5zY2F0dGVyTGluZUNvbG9yID0gZm9ybWF0Q29sb3IobWFya2VyLmxpbmUsIDEsIGxlbik7XG4gICAgICAgIHBhcmFtcy5zY2F0dGVyQW5nbGUgPSAwO1xuICAgIH1cblxuICAgIGlmKCd0ZXh0cG9zaXRpb24nIGluIGRhdGEpIHtcbiAgICAgICAgcGFyYW1zLnRleHRPZmZzZXQgPSBjYWxjdWxhdGVUZXh0T2Zmc2V0KGRhdGEudGV4dHBvc2l0aW9uKTsgIC8vIGFycmF5T2sgPT09IGZhbHNlXG4gICAgICAgIHBhcmFtcy50ZXh0Q29sb3IgPSBmb3JtYXRDb2xvcihkYXRhLnRleHRmb250LCAxLCBsZW4pO1xuICAgICAgICBwYXJhbXMudGV4dFNpemUgPSBmb3JtYXRQYXJhbShkYXRhLnRleHRmb250LnNpemUsIGxlbiwgTGliLmlkZW50aXR5LCAxMik7XG4gICAgICAgIHBhcmFtcy50ZXh0Rm9udCA9IGRhdGEudGV4dGZvbnQuZmFtaWx5OyAgLy8gYXJyYXlPayA9PT0gZmFsc2VcbiAgICAgICAgcGFyYW1zLnRleHRBbmdsZSA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG4gICAgcGFyYW1zLnByb2plY3QgPSBbZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgcGFyYW1zLnByb2plY3RTY2FsZSA9IFsxLCAxLCAxXTtcbiAgICBwYXJhbXMucHJvamVjdE9wYWNpdHkgPSBbMSwgMSwgMV07XG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIHZhciBwcm9qZWN0aW9uID0gZGF0YS5wcm9qZWN0aW9uW2RpbXNbaV1dO1xuICAgICAgICBpZigocGFyYW1zLnByb2plY3RbaV0gPSBwcm9qZWN0aW9uLnNob3cpKSB7XG4gICAgICAgICAgICBwYXJhbXMucHJvamVjdE9wYWNpdHlbaV0gPSBwcm9qZWN0aW9uLm9wYWNpdHk7XG4gICAgICAgICAgICBwYXJhbXMucHJvamVjdFNjYWxlW2ldID0gcHJvamVjdGlvbi5zY2FsZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHBhcmFtcy5lcnJvckJvdW5kcyA9IGNhbGN1bGF0ZUVycm9yKGRhdGEsIHNjYWxlRmFjdG9yLCBzY2VuZUxheW91dCk7XG5cbiAgICB2YXIgZXJyb3JQYXJhbXMgPSBjYWxjdWxhdGVFcnJvclBhcmFtcyhbZGF0YS5lcnJvcl94LCBkYXRhLmVycm9yX3ksIGRhdGEuZXJyb3Jfel0pO1xuICAgIHBhcmFtcy5lcnJvckNvbG9yID0gZXJyb3JQYXJhbXMuY29sb3I7XG4gICAgcGFyYW1zLmVycm9yTGluZVdpZHRoID0gZXJyb3JQYXJhbXMubGluZVdpZHRoO1xuICAgIHBhcmFtcy5lcnJvckNhcFNpemUgPSBlcnJvclBhcmFtcy5jYXBTaXplO1xuXG4gICAgcGFyYW1zLmRlbGF1bmF5QXhpcyA9IGRhdGEuc3VyZmFjZWF4aXM7XG4gICAgcGFyYW1zLmRlbGF1bmF5Q29sb3IgPSBzdHIyUmdiYUFycmF5KGRhdGEuc3VyZmFjZWNvbG9yKTtcblxuICAgIHJldHVybiBwYXJhbXM7XG59XG5cbmZ1bmN0aW9uIGFycmF5VG9Db2xvcihjb2xvcikge1xuICAgIGlmKEFycmF5LmlzQXJyYXkoY29sb3IpKSB7XG4gICAgICAgIHZhciBjID0gY29sb3JbMF07XG5cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShjKSkgY29sb3IgPSBjO1xuXG4gICAgICAgIHJldHVybiAncmdiKCcgKyBjb2xvci5zbGljZSgwLCAzKS5tYXAoZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoeCAqIDI1NSk7XG4gICAgICAgIH0pICsgJyknO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIGdsID0gdGhpcy5zY2VuZS5nbHBsb3QuZ2wsXG4gICAgICAgIGxpbmVPcHRpb25zLFxuICAgICAgICBzY2F0dGVyT3B0aW9ucyxcbiAgICAgICAgZXJyb3JPcHRpb25zLFxuICAgICAgICB0ZXh0T3B0aW9ucyxcbiAgICAgICAgZGFzaFBhdHRlcm4gPSBEQVNIX1BBVFRFUk5TLnNvbGlkO1xuXG4gICAgLy8gU2F2ZSBkYXRhXG4gICAgdGhpcy5kYXRhID0gZGF0YTtcblxuICAgIC8vIFJ1biBkYXRhIGNvbnZlcnNpb25cbiAgICB2YXIgb3B0aW9ucyA9IGNvbnZlcnRQbG90bHlPcHRpb25zKHRoaXMuc2NlbmUsIGRhdGEpO1xuXG4gICAgaWYoJ21vZGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5tb2RlID0gb3B0aW9ucy5tb2RlO1xuICAgIH1cbiAgICBpZignbGluZURhc2hlcycgaW4gb3B0aW9ucykge1xuICAgICAgICBpZihvcHRpb25zLmxpbmVEYXNoZXMgaW4gREFTSF9QQVRURVJOUykge1xuICAgICAgICAgICAgZGFzaFBhdHRlcm4gPSBEQVNIX1BBVFRFUk5TW29wdGlvbnMubGluZURhc2hlc107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNvbG9yID0gYXJyYXlUb0NvbG9yKG9wdGlvbnMuc2NhdHRlckNvbG9yKSB8fFxuICAgICAgICAgICAgICAgICBhcnJheVRvQ29sb3Iob3B0aW9ucy5saW5lQ29sb3IpO1xuXG4gICAgLy8gU2F2ZSBkYXRhIHBvaW50c1xuICAgIHRoaXMuZGF0YVBvaW50cyA9IG9wdGlvbnMucG9zaXRpb247XG5cbiAgICBsaW5lT3B0aW9ucyA9IHtcbiAgICAgICAgZ2w6IGdsLFxuICAgICAgICBwb3NpdGlvbjogb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgY29sb3I6IG9wdGlvbnMubGluZUNvbG9yLFxuICAgICAgICBsaW5lV2lkdGg6IG9wdGlvbnMubGluZVdpZHRoIHx8IDEsXG4gICAgICAgIGRhc2hlczogZGFzaFBhdHRlcm5bMF0sXG4gICAgICAgIGRhc2hTY2FsZTogZGFzaFBhdHRlcm5bMV0sXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eSxcbiAgICAgICAgY29ubmVjdEdhcHM6IGRhdGEuY29ubmVjdGdhcHNcbiAgICB9O1xuXG4gICAgaWYodGhpcy5tb2RlLmluZGV4T2YoJ2xpbmVzJykgIT09IC0xKSB7XG4gICAgICAgIGlmKHRoaXMubGluZVBsb3QpIHRoaXMubGluZVBsb3QudXBkYXRlKGxpbmVPcHRpb25zKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxpbmVQbG90ID0gY3JlYXRlTGluZVBsb3QobGluZU9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5saW5lUGxvdC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMubGluZVBsb3QpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKHRoaXMubGluZVBsb3QpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMubGluZVBsb3QpO1xuICAgICAgICB0aGlzLmxpbmVQbG90LmRpc3Bvc2UoKTtcbiAgICAgICAgdGhpcy5saW5lUGxvdCA9IG51bGw7XG4gICAgfVxuXG4gICAgLy8gTi5CLiBtYXJrZXIub3BhY2l0eSBtdXN0IGJlIGEgc2NhbGFyIGZvciBwZXJmb3JtYW5jZVxuICAgIHZhciBzY2F0dGVyT3BhY2l0eSA9IGRhdGEub3BhY2l0eTtcbiAgICBpZihkYXRhLm1hcmtlciAmJiBkYXRhLm1hcmtlci5vcGFjaXR5KSBzY2F0dGVyT3BhY2l0eSAqPSBkYXRhLm1hcmtlci5vcGFjaXR5O1xuXG4gICAgc2NhdHRlck9wdGlvbnMgPSB7XG4gICAgICAgIGdsOiBnbCxcbiAgICAgICAgcG9zaXRpb246IG9wdGlvbnMucG9zaXRpb24sXG4gICAgICAgIGNvbG9yOiBvcHRpb25zLnNjYXR0ZXJDb2xvcixcbiAgICAgICAgc2l6ZTogb3B0aW9ucy5zY2F0dGVyU2l6ZSxcbiAgICAgICAgZ2x5cGg6IG9wdGlvbnMuc2NhdHRlck1hcmtlcixcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck9wYWNpdHksXG4gICAgICAgIG9ydGhvZ3JhcGhpYzogdHJ1ZSxcbiAgICAgICAgbGluZVdpZHRoOiBvcHRpb25zLnNjYXR0ZXJMaW5lV2lkdGgsXG4gICAgICAgIGxpbmVDb2xvcjogb3B0aW9ucy5zY2F0dGVyTGluZUNvbG9yLFxuICAgICAgICBwcm9qZWN0OiBvcHRpb25zLnByb2plY3QsXG4gICAgICAgIHByb2plY3RTY2FsZTogb3B0aW9ucy5wcm9qZWN0U2NhbGUsXG4gICAgICAgIHByb2plY3RPcGFjaXR5OiBvcHRpb25zLnByb2plY3RPcGFjaXR5XG4gICAgfTtcblxuICAgIGlmKHRoaXMubW9kZS5pbmRleE9mKCdtYXJrZXJzJykgIT09IC0xKSB7XG4gICAgICAgIGlmKHRoaXMuc2NhdHRlclBsb3QpIHRoaXMuc2NhdHRlclBsb3QudXBkYXRlKHNjYXR0ZXJPcHRpb25zKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNjYXR0ZXJQbG90ID0gY3JlYXRlU2NhdHRlclBsb3Qoc2NhdHRlck9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5oaWdobGlnaHRTY2FsZSA9IDE7XG4gICAgICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5hZGQodGhpcy5zY2F0dGVyUGxvdCk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYodGhpcy5zY2F0dGVyUGxvdCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5zY2F0dGVyUGxvdCk7XG4gICAgICAgIHRoaXMuc2NhdHRlclBsb3QuZGlzcG9zZSgpO1xuICAgICAgICB0aGlzLnNjYXR0ZXJQbG90ID0gbnVsbDtcbiAgICB9XG5cbiAgICB0ZXh0T3B0aW9ucyA9IHtcbiAgICAgICAgZ2w6IGdsLFxuICAgICAgICBwb3NpdGlvbjogb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgZ2x5cGg6IG9wdGlvbnMudGV4dCxcbiAgICAgICAgY29sb3I6IG9wdGlvbnMudGV4dENvbG9yLFxuICAgICAgICBzaXplOiBvcHRpb25zLnRleHRTaXplLFxuICAgICAgICBhbmdsZTogb3B0aW9ucy50ZXh0QW5nbGUsXG4gICAgICAgIGFsaWdubWVudDogb3B0aW9ucy50ZXh0T2Zmc2V0LFxuICAgICAgICBmb250OiBvcHRpb25zLnRleHRGb250LFxuICAgICAgICBvcnRob2dyYXBoaWM6IHRydWUsXG4gICAgICAgIGxpbmVXaWR0aDogMCxcbiAgICAgICAgcHJvamVjdDogZmFsc2UsXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eVxuICAgIH07XG5cbiAgICB0aGlzLnRleHRMYWJlbHMgPSBkYXRhLmhvdmVydGV4dCB8fCBkYXRhLnRleHQ7XG5cbiAgICBpZih0aGlzLm1vZGUuaW5kZXhPZigndGV4dCcpICE9PSAtMSkge1xuICAgICAgICBpZih0aGlzLnRleHRNYXJrZXJzKSB0aGlzLnRleHRNYXJrZXJzLnVwZGF0ZSh0ZXh0T3B0aW9ucyk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy50ZXh0TWFya2VycyA9IGNyZWF0ZVNjYXR0ZXJQbG90KHRleHRPcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMudGV4dE1hcmtlcnMuX3RyYWNlID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMudGV4dE1hcmtlcnMuaGlnaGxpZ2h0U2NhbGUgPSAxO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMudGV4dE1hcmtlcnMpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKHRoaXMudGV4dE1hcmtlcnMpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMudGV4dE1hcmtlcnMpO1xuICAgICAgICB0aGlzLnRleHRNYXJrZXJzLmRpc3Bvc2UoKTtcbiAgICAgICAgdGhpcy50ZXh0TWFya2VycyA9IG51bGw7XG4gICAgfVxuXG4gICAgZXJyb3JPcHRpb25zID0ge1xuICAgICAgICBnbDogZ2wsXG4gICAgICAgIHBvc2l0aW9uOiBvcHRpb25zLnBvc2l0aW9uLFxuICAgICAgICBjb2xvcjogb3B0aW9ucy5lcnJvckNvbG9yLFxuICAgICAgICBlcnJvcjogb3B0aW9ucy5lcnJvckJvdW5kcyxcbiAgICAgICAgbGluZVdpZHRoOiBvcHRpb25zLmVycm9yTGluZVdpZHRoLFxuICAgICAgICBjYXBTaXplOiBvcHRpb25zLmVycm9yQ2FwU2l6ZSxcbiAgICAgICAgb3BhY2l0eTogZGF0YS5vcGFjaXR5XG4gICAgfTtcbiAgICBpZih0aGlzLmVycm9yQmFycykge1xuICAgICAgICBpZihvcHRpb25zLmVycm9yQm91bmRzKSB7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycy51cGRhdGUoZXJyb3JPcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLmVycm9yQmFycyk7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycy5kaXNwb3NlKCk7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycyA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYob3B0aW9ucy5lcnJvckJvdW5kcykge1xuICAgICAgICB0aGlzLmVycm9yQmFycyA9IGNyZWF0ZUVycm9yQmFycyhlcnJvck9wdGlvbnMpO1xuICAgICAgICB0aGlzLmVycm9yQmFycy5fdHJhY2UgPSB0aGlzO1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5hZGQodGhpcy5lcnJvckJhcnMpO1xuICAgIH1cblxuICAgIGlmKG9wdGlvbnMuZGVsYXVuYXlBeGlzID49IDApIHtcbiAgICAgICAgdmFyIGRlbGF1bmF5T3B0aW9ucyA9IGNvbnN0cnVjdERlbGF1bmF5KFxuICAgICAgICAgICAgb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgICAgIG9wdGlvbnMuZGVsYXVuYXlDb2xvcixcbiAgICAgICAgICAgIG9wdGlvbnMuZGVsYXVuYXlBeGlzXG4gICAgICAgICk7XG4gICAgICAgIGRlbGF1bmF5T3B0aW9ucy5vcGFjaXR5ID0gZGF0YS5vcGFjaXR5O1xuXG4gICAgICAgIGlmKHRoaXMuZGVsYXVuYXlNZXNoKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC51cGRhdGUoZGVsYXVuYXlPcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGF1bmF5T3B0aW9ucy5nbCA9IGdsO1xuICAgICAgICAgICAgdGhpcy5kZWxhdW5heU1lc2ggPSBjcmVhdGVNZXNoKGRlbGF1bmF5T3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMuZGVsYXVuYXlNZXNoKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZih0aGlzLmRlbGF1bmF5TWVzaCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5kZWxhdW5heU1lc2gpO1xuICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5kaXNwb3NlKCk7XG4gICAgICAgIHRoaXMuZGVsYXVuYXlNZXNoID0gbnVsbDtcbiAgICB9XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5saW5lUGxvdCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5saW5lUGxvdCk7XG4gICAgICAgIHRoaXMubGluZVBsb3QuZGlzcG9zZSgpO1xuICAgIH1cbiAgICBpZih0aGlzLnNjYXR0ZXJQbG90KSB7XG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLnNjYXR0ZXJQbG90KTtcbiAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5kaXNwb3NlKCk7XG4gICAgfVxuICAgIGlmKHRoaXMuZXJyb3JCYXJzKSB7XG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLmVycm9yQmFycyk7XG4gICAgICAgIHRoaXMuZXJyb3JCYXJzLmRpc3Bvc2UoKTtcbiAgICB9XG4gICAgaWYodGhpcy50ZXh0TWFya2Vycykge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy50ZXh0TWFya2Vycyk7XG4gICAgICAgIHRoaXMudGV4dE1hcmtlcnMuZGlzcG9zZSgpO1xuICAgIH1cbiAgICBpZih0aGlzLmRlbGF1bmF5TWVzaCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5kZWxhdW5heU1lc2gpO1xuICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5kaXNwb3NlKCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY3JlYXRlTGluZVdpdGhNYXJrZXJzKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIHBsb3QgPSBuZXcgTGluZVdpdGhNYXJrZXJzKHNjZW5lLCBkYXRhLnVpZCk7XG4gICAgcGxvdC51cGRhdGUoZGF0YSk7XG4gICAgcmV0dXJuIHBsb3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlTGluZVdpdGhNYXJrZXJzO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGV4dERlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci90ZXh0X2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnbW9kZScpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge25vU2VsZWN0OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge25vU2VsZWN0OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgdmFyIGxpbmVDb2xvciA9ICh0cmFjZU91dC5saW5lIHx8IHt9KS5jb2xvcixcbiAgICAgICAgbWFya2VyQ29sb3IgPSAodHJhY2VPdXQubWFya2VyIHx8IHt9KS5jb2xvcjtcbiAgICBpZihjb2VyY2UoJ3N1cmZhY2VheGlzJykgPj0gMCkgY29lcmNlKCdzdXJmYWNlY29sb3InLCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IpO1xuXG4gICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgcHJvamVjdGlvbiA9ICdwcm9qZWN0aW9uLicgKyBkaW1zW2ldO1xuICAgICAgICBpZihjb2VyY2UocHJvamVjdGlvbiArICcuc2hvdycpKSB7XG4gICAgICAgICAgICBjb2VyY2UocHJvamVjdGlvbiArICcub3BhY2l0eScpO1xuICAgICAgICAgICAgY29lcmNlKHByb2plY3Rpb24gKyAnLnNjYWxlJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIHtheGlzOiAneid9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3knLCBpbmhlcml0OiAneid9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneid9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCkge1xuICAgIHZhciBsZW4gPSAwLFxuICAgICAgICB4ID0gY29lcmNlKCd4JyksXG4gICAgICAgIHkgPSBjb2VyY2UoJ3knKSxcbiAgICAgICAgeiA9IGNvZXJjZSgneicpO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4JywgJ3knLCAneiddLCBsYXlvdXQpO1xuXG4gICAgaWYoeCAmJiB5ICYmIHopIHtcbiAgICAgICAgLy8gVE9ETzogd2hhdCBoYXBwZW5zIGlmIG9uZSBpcyBtaXNzaW5nP1xuICAgICAgICBsZW4gPSBNYXRoLm1pbih4Lmxlbmd0aCwgeS5sZW5ndGgsIHoubGVuZ3RoKTtcbiAgICAgICAgdHJhY2VPdXQuX2xlbmd0aCA9IHRyYWNlT3V0Ll94bGVuZ3RoID0gdHJhY2VPdXQuX3lsZW5ndGggPSB0cmFjZU91dC5femxlbmd0aCA9IGxlbjtcbiAgICB9XG5cbiAgICByZXR1cm4gbGVuO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2NhdHRlcjNEID0ge307XG5cblNjYXR0ZXIzRC5wbG90ID0gcmVxdWlyZSgnLi9jb252ZXJ0Jyk7XG5TY2F0dGVyM0QuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuU2NhdHRlcjNELm1hcmtlclN5bWJvbHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvZ2wzZF9tYXJrZXJzJyk7XG5TY2F0dGVyM0Quc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5TY2F0dGVyM0QuY29sb3JiYXIgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpO1xuU2NhdHRlcjNELmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKTtcblxuU2NhdHRlcjNELm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuU2NhdHRlcjNELm5hbWUgPSAnc2NhdHRlcjNkJztcblNjYXR0ZXIzRC5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dsM2QnKTtcblNjYXR0ZXIzRC5jYXRlZ29yaWVzID0gWydnbDNkJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCddO1xuU2NhdHRlcjNELm1ldGEgPSB7XG4gICAgXG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNjYXR0ZXIzRDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yYmFyQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHNjYXR0ZXJNYXJrZXJBdHRycyA9IHNjYXR0ZXJBdHRycy5tYXJrZXIsXG4gICAgc2NhdHRlckxpbmVBdHRycyA9IHNjYXR0ZXJBdHRycy5saW5lLFxuICAgIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2FycGV0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtb2RlOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMubW9kZSwge2RmbHQ6ICdtYXJrZXJzJ30pLFxuICAgIHRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBzY2F0dGVyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICBkYXNoOiBzY2F0dGVyTGluZUF0dHJzLmRhc2gsXG4gICAgICAgIHNoYXBlOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLnNoYXBlLFxuICAgICAgICAgICAge3ZhbHVlczogWydsaW5lYXInLCAnc3BsaW5lJ119KSxcbiAgICAgICAgc21vb3RoaW5nOiBzY2F0dGVyTGluZUF0dHJzLnNtb290aGluZyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcbiAgICBmaWxsOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuZmlsbCwge1xuICAgICAgICB2YWx1ZXM6IFsnbm9uZScsICd0b3NlbGYnLCAndG9uZXh0J10sXG4gICAgICAgIGRmbHQ6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyQXR0cnMuZmlsbGNvbG9yLFxuICAgIG1hcmtlcjogZXh0ZW5kRmxhdCh7XG4gICAgICAgIHN5bWJvbDogc2NhdHRlck1hcmtlckF0dHJzLnN5bWJvbCxcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck1hcmtlckF0dHJzLm9wYWNpdHksXG4gICAgICAgIG1heGRpc3BsYXllZDogc2NhdHRlck1hcmtlckF0dHJzLm1heGRpc3BsYXllZCxcbiAgICAgICAgc2l6ZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemUsXG4gICAgICAgIHNpemVyZWY6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1pbixcbiAgICAgICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICAgICAgbGluZTogZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICB3aWR0aDogc2NhdHRlck1hcmtlckxpbmVBdHRycy53aWR0aCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yQXR0cmlidXRlcygnbWFya2VyLmxpbmUnKVxuICAgICAgICApLFxuICAgICAgICBncmFkaWVudDogc2NhdHRlck1hcmtlckF0dHJzLmdyYWRpZW50LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSwgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXInKSwge1xuICAgICAgICBjb2xvcmJhcjogY29sb3JiYXJBdHRyc1xuICAgIH0pLFxuXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udCxcbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJBdHRycy50ZXh0cG9zaXRpb24sXG5cbiAgICBzZWxlY3RlZDogc2NhdHRlckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2EnLCAnYicsICd0ZXh0JywgJ25hbWUnXVxuICAgIH0pLFxuICAgIGhvdmVyb246IHNjYXR0ZXJBdHRycy5ob3Zlcm9uLFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIGNhbGNDb2xvcnNjYWxlID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGMnKTtcbnZhciBhcnJheXNUb0NhbGNkYXRhID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGEnKTtcbnZhciBjYWxjU2VsZWN0aW9uID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvbicpO1xudmFyIGNhbGNNYXJrZXJTaXplID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jYWxjJykuY2FsY01hcmtlclNpemU7XG52YXIgbG9va3VwQ2FycGV0ID0gcmVxdWlyZSgnLi4vY2FycGV0L2xvb2t1cF9jYXJwZXRpZCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGNhcnBldCA9IHRyYWNlLl9jYXJwZXRUcmFjZSA9IGxvb2t1cENhcnBldChnZCwgdHJhY2UpO1xuICAgIGlmKCFjYXJwZXQgfHwgIWNhcnBldC52aXNpYmxlIHx8IGNhcnBldC52aXNpYmxlID09PSAnbGVnZW5kb25seScpIHJldHVybjtcbiAgICB2YXIgaTtcblxuICAgIC8vIFRyYW5zZmVyIHRoaXMgb3ZlciBmcm9tIGNhcnBldCBiZWZvcmUgcGxvdHRpbmcgc2luY2UgdGhpcyBpcyBhIG5lY2Vzc2FyeVxuICAgIC8vIGNvbmRpdGlvbiBpbiBvcmRlciBmb3IgY2FydGVzaWFuIHRvIGFjdHVhbGx5IHBsb3QgdGhpcyB0cmFjZTpcbiAgICB0cmFjZS54YXhpcyA9IGNhcnBldC54YXhpcztcbiAgICB0cmFjZS55YXhpcyA9IGNhcnBldC55YXhpcztcblxuICAgIC8vIG1ha2UgdGhlIGNhbGNkYXRhIGFycmF5XG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgdmFyIGEsIGI7XG4gICAgdmFyIG5lZWRzQ3VsbCA9IGZhbHNlO1xuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc2xlbjsgaSsrKSB7XG4gICAgICAgIGEgPSB0cmFjZS5hW2ldO1xuICAgICAgICBiID0gdHJhY2UuYltpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKGEpICYmIGlzTnVtZXJpYyhiKSkge1xuICAgICAgICAgICAgdmFyIHh5ID0gY2FycGV0LmFiMnh5KCthLCArYiwgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgdmlzaWJsZSA9IGNhcnBldC5pc1Zpc2libGUoK2EsICtiKTtcbiAgICAgICAgICAgIGlmKCF2aXNpYmxlKSBuZWVkc0N1bGwgPSB0cnVlO1xuICAgICAgICAgICAgY2RbaV0gPSB7eDogeHlbMF0sIHk6IHh5WzFdLCBhOiBhLCBiOiBiLCB2aXM6IHZpc2libGV9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgY2RbaV0gPSB7eDogZmFsc2UsIHk6IGZhbHNlfTtcbiAgICB9XG5cbiAgICB0cmFjZS5fbmVlZHNDdWxsID0gbmVlZHNDdWxsO1xuXG4gICAgY2RbMF0uY2FycGV0ID0gY2FycGV0O1xuICAgIGNkWzBdLnRyYWNlID0gdHJhY2U7XG5cbiAgICBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgc2VyaWVzbGVuKTtcbiAgICBjYWxjQ29sb3JzY2FsZSh0cmFjZSk7XG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb25zdGFudHMnKTtcbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2xpbmVfc2hhcGVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUZXh0RGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnY2FycGV0Jyk7XG5cbiAgICAvLyBYWFg6IERvbid0IGhhcmQgY29kZSB0aGlzXG4gICAgdHJhY2VPdXQueGF4aXMgPSAneCc7XG4gICAgdHJhY2VPdXQueWF4aXMgPSAneSc7XG5cbiAgICB2YXIgYSA9IGNvZXJjZSgnYScpO1xuICAgIHZhciBiID0gY29lcmNlKCdiJyk7XG4gICAgdmFyIGxlbiA9IE1hdGgubWluKGEubGVuZ3RoLCBiLmxlbmd0aCk7XG5cbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcblxuICAgIHZhciBkZWZhdWx0TW9kZSA9IGxlbiA8IGNvbnN0YW50cy5QVFNfTElORVNPTkxZID8gJ2xpbmVzK21hcmtlcnMnIDogJ2xpbmVzJztcbiAgICBjb2VyY2UoJ21vZGUnLCBkZWZhdWx0TW9kZSk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge2dyYWRpZW50OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgdmFyIGRmbHRIb3Zlck9uID0gW107XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSB8fCBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5tYXhkaXNwbGF5ZWQnKTtcbiAgICAgICAgZGZsdEhvdmVyT24ucHVzaCgncG9pbnRzJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsJyk7XG4gICAgaWYodHJhY2VPdXQuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGNvZXJjZSk7XG4gICAgICAgIGlmKCFzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0LmZpbGwgPT09ICd0b25leHQnIHx8IHRyYWNlT3V0LmZpbGwgPT09ICd0b3NlbGYnKSB7XG4gICAgICAgIGRmbHRIb3Zlck9uLnB1c2goJ2ZpbGxzJyk7XG4gICAgfVxuICAgIGNvZXJjZSgnaG92ZXJvbicsIGRmbHRIb3Zlck9uLmpvaW4oJysnKSB8fCAncG9pbnRzJyk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXZlbnREYXRhKG91dCwgcHQsIHRyYWNlLCBjZCwgcG9pbnROdW1iZXIpIHtcbiAgICB2YXIgY2RpID0gY2RbcG9pbnROdW1iZXJdO1xuXG4gICAgb3V0LmEgPSBjZGkuYTtcbiAgICBvdXQuYiA9IGNkaS5iO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJIb3ZlciA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvaG92ZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBzY2F0dGVyUG9pbnREYXRhID0gc2NhdHRlckhvdmVyKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcbiAgICBpZighc2NhdHRlclBvaW50RGF0YSB8fCBzY2F0dGVyUG9pbnREYXRhWzBdLmluZGV4ID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIG5ld1BvaW50RGF0YSA9IHNjYXR0ZXJQb2ludERhdGFbMF07XG5cbiAgICAvLyBpZiBob3ZlcmluZyBvbiBhIGZpbGwsIHdlIGRvbid0IHNob3cgYW55IHBvaW50IGRhdGEgc28gdGhlIGxhYmVsIGlzXG4gICAgLy8gdW5jaGFuZ2VkIGZyb20gd2hhdCBzY2F0dGVyIGdpdmVzIHVzIC0gZXhjZXB0IHRoYXQgaXQgbmVlZHMgdG9cbiAgICAvLyBiZSBjb25zdHJhaW5lZCB0byB0aGUgdHJpYW5nbHVsYXIgcGxvdCBhcmVhLCBub3QganVzdCB0aGUgcmVjdGFuZ3VsYXJcbiAgICAvLyBhcmVhIGRlZmluZWQgYnkgdGhlIHN5bnRoZXRpYyB4IGFuZCB5IGF4ZXNcbiAgICAvLyBUT0RPOiBpbiBzb21lIGNhc2VzIHRoZSB2ZXJ0aWNhbCBtaWRkbGUgb2YgdGhlIHNoYXBlIGlzIG5vdCB3aXRoaW5cbiAgICAvLyB0aGUgdHJpYW5ndWxhciB2aWV3cG9ydCBhdCBhbGwsIHNvIHRoZSBsYWJlbCBjYW4gYmVjb21lIGRpc2Nvbm5lY3RlZFxuICAgIC8vIGZyb20gdGhlIHNoYXBlIGVudGlyZWx5LiBCdXQgY2FsY3VsYXRpbmcgd2hhdCBwb3J0aW9uIG9mIHRoZSBzaGFwZVxuICAgIC8vIGlzIGFjdHVhbGx5IHZpc2libGUsIGFzIGNvbnN0cmFpbmVkIGJ5IHRoZSBkaWFnb25hbCBheGlzIGxpbmVzLCBpcyBub3RcbiAgICAvLyBzbyBlYXN5IGFuZCBhbnl3YXkgd2UgbG9zdCB0aGUgaW5mb3JtYXRpb24gd2Ugd291bGQgaGF2ZSBuZWVkZWQgdG8gZG9cbiAgICAvLyB0aGlzIGluc2lkZSBzY2F0dGVySG92ZXIuXG4gICAgaWYobmV3UG9pbnREYXRhLmluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIHlGcmFjVXAgPSAxIC0gKG5ld1BvaW50RGF0YS55MCAvIHBvaW50RGF0YS55YS5fbGVuZ3RoKSxcbiAgICAgICAgICAgIHhMZW4gPSBwb2ludERhdGEueGEuX2xlbmd0aCxcbiAgICAgICAgICAgIHhNaW4gPSB4TGVuICogeUZyYWNVcCAvIDIsXG4gICAgICAgICAgICB4TWF4ID0geExlbiAtIHhNaW47XG4gICAgICAgIG5ld1BvaW50RGF0YS54MCA9IE1hdGgubWF4KE1hdGgubWluKG5ld1BvaW50RGF0YS54MCwgeE1heCksIHhNaW4pO1xuICAgICAgICBuZXdQb2ludERhdGEueDEgPSBNYXRoLm1heChNYXRoLm1pbihuZXdQb2ludERhdGEueDEsIHhNYXgpLCB4TWluKTtcbiAgICAgICAgcmV0dXJuIHNjYXR0ZXJQb2ludERhdGE7XG4gICAgfVxuXG4gICAgdmFyIGNkaSA9IG5ld1BvaW50RGF0YS5jZFtuZXdQb2ludERhdGEuaW5kZXhdO1xuXG4gICAgbmV3UG9pbnREYXRhLmEgPSBjZGkuYTtcbiAgICBuZXdQb2ludERhdGEuYiA9IGNkaS5iO1xuXG4gICAgbmV3UG9pbnREYXRhLnhMYWJlbFZhbCA9IHVuZGVmaW5lZDtcbiAgICBuZXdQb2ludERhdGEueUxhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIC8vIFRPRE86IG5pY2UgZm9ybWF0dGluZywgYW5kIGxhYmVsIGJ5IGF4aXMgdGl0bGUsIGZvciBhLCBiLCBhbmQgYz9cblxuICAgIHZhciB0cmFjZSA9IG5ld1BvaW50RGF0YS50cmFjZTtcbiAgICB2YXIgY2FycGV0ID0gdHJhY2UuX2NhcnBldDtcbiAgICB2YXIgaG92ZXJpbmZvID0gY2RpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICB2YXIgdGV4dCA9IFtdO1xuXG4gICAgZnVuY3Rpb24gdGV4dFBhcnQoYXgsIHZhbCkge1xuICAgICAgICB2YXIgcHJlZml4O1xuXG4gICAgICAgIGlmKGF4LmxhYmVscHJlZml4ICYmIGF4LmxhYmVscHJlZml4Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHByZWZpeCA9IGF4LmxhYmVscHJlZml4LnJlcGxhY2UoLyA9ICQvLCAnJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcmVmaXggPSBheC5faG92ZXJ0aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRleHQucHVzaChwcmVmaXggKyAnOiAnICsgdmFsLnRvRml4ZWQoMykgKyBheC5sYWJlbHN1ZmZpeCk7XG4gICAgfVxuXG4gICAgaWYocGFydHMuaW5kZXhPZignYWxsJykgIT09IC0xKSBwYXJ0cyA9IFsnYScsICdiJ107XG4gICAgaWYocGFydHMuaW5kZXhPZignYScpICE9PSAtMSkgdGV4dFBhcnQoY2FycGV0LmFheGlzLCBjZGkuYSk7XG4gICAgaWYocGFydHMuaW5kZXhPZignYicpICE9PSAtMSkgdGV4dFBhcnQoY2FycGV0LmJheGlzLCBjZGkuYik7XG5cbiAgICB2YXIgaWogPSBjYXJwZXQuYWIyaWooW2NkaS5hLCBjZGkuYl0pO1xuICAgIHZhciBpMCA9IE1hdGguZmxvb3IoaWpbMF0pO1xuICAgIHZhciB0aSA9IGlqWzBdIC0gaTA7XG5cbiAgICB2YXIgajAgPSBNYXRoLmZsb29yKGlqWzFdKTtcbiAgICB2YXIgdGogPSBpalsxXSAtIGowO1xuXG4gICAgdmFyIHh5ID0gY2FycGV0LmV2YWx4eShbXSwgaTAsIGowLCB0aSwgdGopO1xuICAgIHRleHQucHVzaCgneTogJyArIHh5WzFdLnRvRml4ZWQoMykpO1xuXG4gICAgbmV3UG9pbnREYXRhLmV4dHJhVGV4dCA9IHRleHQuam9pbignPGJyPicpO1xuXG4gICAgcmV0dXJuIHNjYXR0ZXJQb2ludERhdGE7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2NhdHRlckNhcnBldCA9IHt9O1xuXG5TY2F0dGVyQ2FycGV0LmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblNjYXR0ZXJDYXJwZXQuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5TY2F0dGVyQ2FycGV0LmNvbG9yYmFyID0gcmVxdWlyZSgnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKTtcblNjYXR0ZXJDYXJwZXQuY2FsYyA9IHJlcXVpcmUoJy4vY2FsYycpO1xuU2NhdHRlckNhcnBldC5wbG90ID0gcmVxdWlyZSgnLi9wbG90Jyk7XG5TY2F0dGVyQ2FycGV0LnN0eWxlID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdHlsZScpLnN0eWxlO1xuU2NhdHRlckNhcnBldC5zdHlsZU9uU2VsZWN0ID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdHlsZScpLnN0eWxlT25TZWxlY3Q7XG5TY2F0dGVyQ2FycGV0LmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuU2NhdHRlckNhcnBldC5zZWxlY3RQb2ludHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3NlbGVjdCcpO1xuU2NhdHRlckNhcnBldC5ldmVudERhdGEgPSByZXF1aXJlKCcuL2V2ZW50X2RhdGEnKTtcblxuU2NhdHRlckNhcnBldC5tb2R1bGVUeXBlID0gJ3RyYWNlJztcblNjYXR0ZXJDYXJwZXQubmFtZSA9ICdzY2F0dGVyY2FycGV0JztcblNjYXR0ZXJDYXJwZXQuYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcblNjYXR0ZXJDYXJwZXQuY2F0ZWdvcmllcyA9IFsnc3ZnJywgJ2NhcnBldCcsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnY2FycGV0RGVwZW5kZW50JywgJ3pvb21TY2FsZSddO1xuU2NhdHRlckNhcnBldC5tZXRhID0ge1xuICAgIFxuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTY2F0dGVyQ2FycGV0O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyUGxvdCA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvcGxvdCcpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIERyYXdpbmcgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mb3Byb3h5LCBkYXRhLCBsYXllcikge1xuICAgIHZhciBpLCB0cmFjZSwgbm9kZTtcblxuICAgIHZhciBjYXJwZXQgPSBkYXRhWzBdWzBdLmNhcnBldDtcbiAgICAvLyBtaW1pYyBjYXJ0ZXNpYW4gcGxvdGluZm9cbiAgICB2YXIgcGxvdGluZm8gPSB7XG4gICAgICAgIHhheGlzOiBBeGVzLmdldEZyb21JZChnZCwgY2FycGV0LnhheGlzIHx8ICd4JyksXG4gICAgICAgIHlheGlzOiBBeGVzLmdldEZyb21JZChnZCwgY2FycGV0LnlheGlzIHx8ICd5JyksXG4gICAgICAgIHBsb3Q6IHBsb3RpbmZvcHJveHkucGxvdCxcbiAgICB9O1xuXG4gICAgc2NhdHRlclBsb3QoZ2QsIHBsb3RpbmZvLCBkYXRhLCBsYXllcik7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gZGF0YVtpXVswXS50cmFjZTtcblxuICAgICAgICAvLyBOb3RlOiAuc2VsZWN0IGlzIGFkZXF1YXRlIGJ1dCBzZWVtcyB0byBtdXRhdGUgdGhlIG5vZGUgZGF0YSxcbiAgICAgICAgLy8gd2hpY2ggaXMgYXQgbGVhc3QgYSBiaXQgc3VwcmlzaW5nIGFuZCBjYXVzZXMgcHJvYmxlbXMgZWxzZXdoZXJlXG4gICAgICAgIG5vZGUgPSBsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnICsgdHJhY2UudWlkICsgJyAuanMtbGluZScpO1xuXG4gICAgICAgIC8vIE5vdGU6IGl0IHdvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGlmIHRoaXMgZGlkbid0IG5lZWQgdG8gYmUgYXBwbGllZFxuICAgICAgICAvLyBzZXBhcmF0ZWx5IHRvIGFsbCBzY2F0dGVyY2FycGV0IHRyYWNlcywgYnV0IHRoYXQgd291bGQgcmVxdWlyZVxuICAgICAgICAvLyBsb3RzIG9mIHJlb3JnYW5pemF0aW9uIG9mIHNjYXR0ZXIgdHJhY2VzIHRoYXQgaXMgb3RoZXJ3aXNlIG5vdFxuICAgICAgICAvLyBuZWNlc3NhcnkuIFRoYXQgbWFrZXMgdGhpcyBhIHBvdGVudGlhbCBvcHRpbWl6YXRpb24uXG4gICAgICAgIERyYXdpbmcuc2V0Q2xpcFVybChub2RlLCBjYXJwZXQuX2NsaXBQYXRoSWQpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBwbG90QXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBkYXNoID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXMnKS5kYXNoO1xuXG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcixcbiAgICBzY2F0dGVyTGluZUF0dHJzID0gc2NhdHRlckF0dHJzLmxpbmUsXG4gICAgc2NhdHRlck1hcmtlckxpbmVBdHRycyA9IHNjYXR0ZXJNYXJrZXJBdHRycy5saW5lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICBsb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhdDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsb2NhdGlvbnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxvY2F0aW9ubW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydJU08tMycsICdVU0Etc3RhdGVzJywgJ2NvdW50cnkgbmFtZXMnXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdJU08tMycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBtb2RlOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMubW9kZSwge2RmbHQ6ICdtYXJrZXJzJ30pLFxuXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgaG92ZXJ0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuaG92ZXJ0ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udCxcbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJBdHRycy50ZXh0cG9zaXRpb24sXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBzY2F0dGVyTGluZUF0dHJzLmNvbG9yLFxuICAgICAgICB3aWR0aDogc2NhdHRlckxpbmVBdHRycy53aWR0aCxcbiAgICAgICAgZGFzaDogZGFzaFxuICAgIH0sXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcblxuICAgIG1hcmtlcjogZXh0ZW5kRmxhdCh7XG4gICAgICAgIHN5bWJvbDogc2NhdHRlck1hcmtlckF0dHJzLnN5bWJvbCxcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck1hcmtlckF0dHJzLm9wYWNpdHksXG4gICAgICAgIHNpemU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLFxuICAgICAgICBzaXplcmVmOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZXJlZixcbiAgICAgICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgICAgIHNpemVtb2RlOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1vZGUsXG4gICAgICAgIGNvbG9yYmFyOiBzY2F0dGVyTWFya2VyQXR0cnMuY29sb3JiYXIsXG4gICAgICAgIGxpbmU6IGV4dGVuZEZsYXQoe1xuICAgICAgICAgICAgd2lkdGg6IHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMud2lkdGhcbiAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yQXR0cmlidXRlcygnbWFya2VyLmxpbmUnKVxuICAgICAgICApLFxuICAgICAgICBncmFkaWVudDogc2NhdHRlck1hcmtlckF0dHJzLmdyYWRpZW50XG4gICAgfSxcbiAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXInKVxuICAgICksXG5cbiAgICBmaWxsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ25vbmUnLCAndG9zZWxmJ10sXG4gICAgICAgIGRmbHQ6ICdub25lJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyQXR0cnMuZmlsbGNvbG9yLFxuXG4gICAgc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZCxcbiAgICB1bnNlbGVjdGVkOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZCxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydsb24nLCAnbGF0JywgJ2xvY2F0aW9uJywgJ3RleHQnLCAnbmFtZSddXG4gICAgfSlcbn0sICdjYWxjJywgJ25lc3RlZCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSByZXF1aXJlKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbnZhciBjYWxjTWFya2VyQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcblxudmFyIF8gPSByZXF1aXJlKCcuLi8uLi9saWInKS5fO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGhhc0xvY2F0aW9uRGF0YSA9IEFycmF5LmlzQXJyYXkodHJhY2UubG9jYXRpb25zKTtcbiAgICB2YXIgbGVuID0gaGFzTG9jYXRpb25EYXRhID8gdHJhY2UubG9jYXRpb25zLmxlbmd0aCA6IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNhbGNUcmFjZSA9IG5ldyBBcnJheShsZW4pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV0gPSB7fTtcblxuICAgICAgICBpZihoYXNMb2NhdGlvbkRhdGEpIHtcbiAgICAgICAgICAgIHZhciBsb2MgPSB0cmFjZS5sb2NhdGlvbnNbaV07XG4gICAgICAgICAgICBjYWxjUHQubG9jID0gdHlwZW9mIGxvYyA9PT0gJ3N0cmluZycgPyBsb2MgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGxvbiA9IHRyYWNlLmxvbltpXTtcbiAgICAgICAgICAgIHZhciBsYXQgPSB0cmFjZS5sYXRbaV07XG5cbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhsb24pICYmIGlzTnVtZXJpYyhsYXQpKSBjYWxjUHQubG9ubGF0ID0gWytsb24sICtsYXRdO1xuICAgICAgICAgICAgZWxzZSBjYWxjUHQubG9ubGF0ID0gW0JBRE5VTSwgQkFETlVNXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFycmF5c1RvQ2FsY2RhdGEoY2FsY1RyYWNlLCB0cmFjZSk7XG4gICAgY2FsY01hcmtlckNvbG9yc2NhbGUodHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2FsY1RyYWNlLCB0cmFjZSk7XG5cbiAgICBpZihsZW4pIHtcbiAgICAgICAgY2FsY1RyYWNlWzBdLnQgPSB7XG4gICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICBsYXQ6IF8oZ2QsICdsYXQ6JykgKyAnICcsXG4gICAgICAgICAgICAgICAgbG9uOiBfKGdkLCAnbG9uOicpICsgJyAnXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNhbGNUcmFjZTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlTG9uTGF0TG9jRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnbW9kZScpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge2dyYWRpZW50OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsJyk7XG4gICAgaWYodHJhY2VPdXQuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVMb25MYXRMb2NEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKSB7XG4gICAgdmFyIGxlbiA9IDAsXG4gICAgICAgIGxvY2F0aW9ucyA9IGNvZXJjZSgnbG9jYXRpb25zJyk7XG5cbiAgICB2YXIgbG9uLCBsYXQ7XG5cbiAgICBpZihsb2NhdGlvbnMpIHtcbiAgICAgICAgY29lcmNlKCdsb2NhdGlvbm1vZGUnKTtcbiAgICAgICAgbGVuID0gbG9jYXRpb25zLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIGxlbjtcbiAgICB9XG5cbiAgICBsb24gPSBjb2VyY2UoJ2xvbicpIHx8IFtdO1xuICAgIGxhdCA9IGNvZXJjZSgnbGF0JykgfHwgW107XG4gICAgbGVuID0gTWF0aC5taW4obG9uLmxlbmd0aCwgbGF0Lmxlbmd0aCk7XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHJldHVybiBsZW47XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0KSB7XG4gICAgb3V0LmxvbiA9IHB0LmxvbjtcbiAgICBvdXQubGF0ID0gcHQubGF0O1xuICAgIG91dC5sb2NhdGlvbiA9IHB0LmxvYyA/IHB0LmxvYyA6IG51bGw7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRnggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIGdldFRyYWNlQ29sb3IgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2dldF90cmFjZV9jb2xvcicpO1xudmFyIGZpbGxIb3ZlclRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxfaG92ZXJfdGV4dCcpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgZ2VvID0gcG9pbnREYXRhLnN1YnBsb3Q7XG5cbiAgICB2YXIgaXNMb25MYXRPdmVyRWRnZXMgPSBnZW8ucHJvamVjdGlvbi5pc0xvbkxhdE92ZXJFZGdlcztcbiAgICB2YXIgcHJvamVjdCA9IGdlby5wcm9qZWN0O1xuXG4gICAgZnVuY3Rpb24gZGlzdEZuKGQpIHtcbiAgICAgICAgdmFyIGxvbmxhdCA9IGQubG9ubGF0O1xuXG4gICAgICAgIGlmKGxvbmxhdFswXSA9PT0gQkFETlVNKSByZXR1cm4gSW5maW5pdHk7XG4gICAgICAgIGlmKGlzTG9uTGF0T3ZlckVkZ2VzKGxvbmxhdCkpIHJldHVybiBJbmZpbml0eTtcblxuICAgICAgICB2YXIgcHQgPSBwcm9qZWN0KGxvbmxhdCk7XG4gICAgICAgIHZhciBweCA9IHByb2plY3QoW3h2YWwsIHl2YWxdKTtcbiAgICAgICAgdmFyIGR4ID0gTWF0aC5hYnMocHRbMF0gLSBweFswXSk7XG4gICAgICAgIHZhciBkeSA9IE1hdGguYWJzKHB0WzFdIC0gcHhbMV0pO1xuICAgICAgICB2YXIgcmFkID0gTWF0aC5tYXgoMywgZC5tcmMgfHwgMCk7XG5cbiAgICAgICAgLy8gTi5CLiBkLm1yYyBpcyB0aGUgY2FsY3VsYXRlZCBtYXJrZXIgcmFkaXVzXG4gICAgICAgIC8vIHdoaWNoIGlzIG9ubHkgc2V0IGZvciB0cmFjZSB3aXRoICdtYXJrZXJzJyBtb2RlLlxuXG4gICAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpIC0gcmFkLCAxIC0gMyAvIHJhZCk7XG4gICAgfVxuXG4gICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdEZuLCBwb2ludERhdGEpO1xuXG4gICAgLy8gc2tpcCB0aGUgcmVzdCAoZm9yIHRoaXMgdHJhY2UpIGlmIHdlIGRpZG4ndCBmaW5kIGEgY2xvc2UgcG9pbnRcbiAgICBpZihwb2ludERhdGEuaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciBsb25sYXQgPSBkaS5sb25sYXQ7XG4gICAgdmFyIHBvcyA9IFt4YS5jMnAobG9ubGF0KSwgeWEuYzJwKGxvbmxhdCldO1xuICAgIHZhciByYWQgPSBkaS5tcmMgfHwgMTtcblxuICAgIHBvaW50RGF0YS54MCA9IHBvc1swXSAtIHJhZDtcbiAgICBwb2ludERhdGEueDEgPSBwb3NbMF0gKyByYWQ7XG4gICAgcG9pbnREYXRhLnkwID0gcG9zWzFdIC0gcmFkO1xuICAgIHBvaW50RGF0YS55MSA9IHBvc1sxXSArIHJhZDtcblxuICAgIHBvaW50RGF0YS5sb2MgPSBkaS5sb2M7XG4gICAgcG9pbnREYXRhLmxvbiA9IGxvbmxhdFswXTtcbiAgICBwb2ludERhdGEubGF0ID0gbG9ubGF0WzFdO1xuXG4gICAgcG9pbnREYXRhLmNvbG9yID0gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpO1xuICAgIHBvaW50RGF0YS5leHRyYVRleHQgPSBnZXRFeHRyYVRleHQodHJhY2UsIGRpLCBnZW8ubW9ja0F4aXMsIGNkWzBdLnQubGFiZWxzKTtcblxuICAgIHJldHVybiBbcG9pbnREYXRhXTtcbn07XG5cbmZ1bmN0aW9uIGdldEV4dHJhVGV4dCh0cmFjZSwgcHQsIGF4aXMsIGxhYmVscykge1xuICAgIHZhciBob3ZlcmluZm8gPSBwdC5oaSB8fCB0cmFjZS5ob3ZlcmluZm87XG5cbiAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8gPT09ICdhbGwnID9cbiAgICAgICAgYXR0cmlidXRlcy5ob3ZlcmluZm8uZmxhZ3MgOlxuICAgICAgICBob3ZlcmluZm8uc3BsaXQoJysnKTtcblxuICAgIHZhciBoYXNMb2NhdGlvbiA9IHBhcnRzLmluZGV4T2YoJ2xvY2F0aW9uJykgIT09IC0xICYmIEFycmF5LmlzQXJyYXkodHJhY2UubG9jYXRpb25zKTtcbiAgICB2YXIgaGFzTG9uID0gKHBhcnRzLmluZGV4T2YoJ2xvbicpICE9PSAtMSk7XG4gICAgdmFyIGhhc0xhdCA9IChwYXJ0cy5pbmRleE9mKCdsYXQnKSAhPT0gLTEpO1xuICAgIHZhciBoYXNUZXh0ID0gKHBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpO1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICBmdW5jdGlvbiBmb3JtYXQodmFsKSB7XG4gICAgICAgIHJldHVybiBBeGVzLnRpY2tUZXh0KGF4aXMsIGF4aXMuYzJsKHZhbCksICdob3ZlcicpLnRleHQgKyAnXFx1MDBCMCc7XG4gICAgfVxuXG4gICAgaWYoaGFzTG9jYXRpb24pIHtcbiAgICAgICAgdGV4dC5wdXNoKHB0LmxvYyk7XG4gICAgfSBlbHNlIGlmKGhhc0xvbiAmJiBoYXNMYXQpIHtcbiAgICAgICAgdGV4dC5wdXNoKCcoJyArIGZvcm1hdChwdC5sb25sYXRbMF0pICsgJywgJyArIGZvcm1hdChwdC5sb25sYXRbMV0pICsgJyknKTtcbiAgICB9IGVsc2UgaWYoaGFzTG9uKSB7XG4gICAgICAgIHRleHQucHVzaChsYWJlbHMubG9uICsgZm9ybWF0KHB0LmxvbmxhdFswXSkpO1xuICAgIH0gZWxzZSBpZihoYXNMYXQpIHtcbiAgICAgICAgdGV4dC5wdXNoKGxhYmVscy5sYXQgKyBmb3JtYXQocHQubG9ubGF0WzFdKSk7XG4gICAgfVxuXG4gICAgaWYoaGFzVGV4dCkge1xuICAgICAgICBmaWxsSG92ZXJUZXh0KHB0LCB0cmFjZSwgdGV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRleHQuam9pbignPGJyPicpO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBTY2F0dGVyR2VvID0ge307XG5cblNjYXR0ZXJHZW8uYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuU2NhdHRlckdlby5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcblNjYXR0ZXJHZW8uY29sb3JiYXIgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpO1xuU2NhdHRlckdlby5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5TY2F0dGVyR2VvLnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcblNjYXR0ZXJHZW8uc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG5TY2F0dGVyR2VvLnN0eWxlT25TZWxlY3QgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N0eWxlJykuc3R5bGVPblNlbGVjdDtcblNjYXR0ZXJHZW8uaG92ZXJQb2ludHMgPSByZXF1aXJlKCcuL2hvdmVyJyk7XG5TY2F0dGVyR2VvLmV2ZW50RGF0YSA9IHJlcXVpcmUoJy4vZXZlbnRfZGF0YScpO1xuU2NhdHRlckdlby5zZWxlY3RQb2ludHMgPSByZXF1aXJlKCcuL3NlbGVjdCcpO1xuXG5TY2F0dGVyR2VvLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuU2NhdHRlckdlby5uYW1lID0gJ3NjYXR0ZXJnZW8nO1xuU2NhdHRlckdlby5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dlbycpO1xuU2NhdHRlckdlby5jYXRlZ29yaWVzID0gWydnZW8nLCAnc3ltYm9scycsICdzaG93TGVnZW5kJywgJ3NjYXR0ZXItbGlrZSddO1xuU2NhdHRlckdlby5tZXRhID0ge1xuICAgIFxuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTY2F0dGVyR2VvO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xudmFyIGdldFRvcG9qc29uRmVhdHVyZXMgPSByZXF1aXJlKCcuLi8uLi9saWIvdG9wb2pzb25fdXRpbHMnKS5nZXRUb3BvanNvbkZlYXR1cmVzO1xudmFyIGxvY2F0aW9uVG9GZWF0dXJlID0gcmVxdWlyZSgnLi4vLi4vbGliL2dlb19sb2NhdGlvbl91dGlscycpLmxvY2F0aW9uVG9GZWF0dXJlO1xudmFyIGdlb0pzb25VdGlscyA9IHJlcXVpcmUoJy4uLy4uL2xpYi9nZW9qc29uX3V0aWxzJyk7XG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgZ2VvLCBjYWxjRGF0YSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYWxjR2VvSlNPTihjYWxjRGF0YVtpXSwgZ2VvLnRvcG9qc29uKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVCQUROVU0oZCwgbm9kZSkge1xuICAgICAgICBpZihkLmxvbmxhdFswXSA9PT0gQkFETlVNKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3Qobm9kZSkucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2NhdHRlckxheWVyID0gZ2VvLmxheWVycy5mcm9udHBsb3Quc2VsZWN0KCcuc2NhdHRlcmxheWVyJyk7XG4gICAgdmFyIGdUcmFjZXMgPSBMaWIubWFrZVRyYWNlR3JvdXBzKHNjYXR0ZXJMYXllciwgY2FsY0RhdGEsICd0cmFjZSBzY2F0dGVyZ2VvJyk7XG5cbiAgICAvLyBUT0RPIGZpbmQgYSB3YXkgdG8gb3JkZXIgdGhlIGlubmVyIG5vZGVzIG9uIHVwZGF0ZVxuICAgIGdUcmFjZXMuc2VsZWN0QWxsKCcqJykucmVtb3ZlKCk7XG5cbiAgICBnVHJhY2VzLmVhY2goZnVuY3Rpb24oY2FsY1RyYWNlKSB7XG4gICAgICAgIHZhciBzID0gY2FsY1RyYWNlWzBdLm5vZGUzID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICAgICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2UpIHx8IHRyYWNlLmZpbGwgIT09ICdub25lJykge1xuICAgICAgICAgICAgdmFyIGxpbmVDb29yZHMgPSBnZW9Kc29uVXRpbHMuY2FsY1RyYWNlVG9MaW5lQ29vcmRzKGNhbGNUcmFjZSk7XG5cbiAgICAgICAgICAgIHZhciBsaW5lRGF0YSA9ICh0cmFjZS5maWxsICE9PSAnbm9uZScpID9cbiAgICAgICAgICAgICAgICBnZW9Kc29uVXRpbHMubWFrZVBvbHlnb24obGluZUNvb3JkcykgOlxuICAgICAgICAgICAgICAgIGdlb0pzb25VdGlscy5tYWtlTGluZShsaW5lQ29vcmRzKTtcblxuICAgICAgICAgICAgcy5zZWxlY3RBbGwoJ3BhdGguanMtbGluZScpXG4gICAgICAgICAgICAgICAgLmRhdGEoW3tnZW9qc29uOiBsaW5lRGF0YSwgdHJhY2U6IHRyYWNlfV0pXG4gICAgICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2pzLWxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLW1pdGVybGltaXQnLCAyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpKSB7XG4gICAgICAgICAgICBzLnNlbGVjdEFsbCgncGF0aC5wb2ludCcpXG4gICAgICAgICAgICAgICAgLmRhdGEoTGliLmlkZW50aXR5KVxuICAgICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3BvaW50JywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbihjYWxjUHQpIHsgcmVtb3ZlQkFETlVNKGNhbGNQdCwgdGhpcyk7IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZSkpIHtcbiAgICAgICAgICAgIHMuc2VsZWN0QWxsKCdnJylcbiAgICAgICAgICAgICAgICAuZGF0YShMaWIuaWRlbnRpdHkpXG4gICAgICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24oY2FsY1B0KSB7IHJlbW92ZUJBRE5VTShjYWxjUHQsIHRoaXMpOyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNhbGwgc3R5bGUgaGVyZSB3aXRoaW4gdG9wb2pzb24gcmVxdWVzdCBjYWxsYmFja1xuICAgICAgICBzdHlsZShnZCwgY2FsY1RyYWNlKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGNhbGNHZW9KU09OKGNhbGNUcmFjZSwgdG9wb2pzb24pIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheSh0cmFjZS5sb2NhdGlvbnMpKSByZXR1cm47XG5cbiAgICB2YXIgZmVhdHVyZXMgPSBnZXRUb3BvanNvbkZlYXR1cmVzKHRyYWNlLCB0b3BvanNvbik7XG4gICAgdmFyIGxvY2F0aW9ubW9kZSA9IHRyYWNlLmxvY2F0aW9ubW9kZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2UubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNQdCA9IGNhbGNUcmFjZVtpXTtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBsb2NhdGlvblRvRmVhdHVyZShsb2NhdGlvbm1vZGUsIGNhbGNQdC5sb2MsIGZlYXR1cmVzKTtcblxuICAgICAgICBjYWxjUHQubG9ubGF0ID0gZmVhdHVyZSA/IGZlYXR1cmUucHJvcGVydGllcy5jdCA6IFtCQUROVU0sIEJBRE5VTV07XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3VidHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZWxlY3RQb2ludHMoc2VhcmNoSW5mbywgc2VsZWN0aW9uVGVzdGVyKSB7XG4gICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICB2YXIgeGEgPSBzZWFyY2hJbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHNlYXJjaEluZm8ueWF4aXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgdmFyIGRpLCBsb25sYXQsIHgsIHksIGk7XG5cbiAgICB2YXIgaGFzT25seUxpbmVzID0gKCFzdWJ0eXBlcy5oYXNNYXJrZXJzKHRyYWNlKSAmJiAhc3VidHlwZXMuaGFzVGV4dCh0cmFjZSkpO1xuICAgIGlmKGhhc09ubHlMaW5lcykgcmV0dXJuIFtdO1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGRpID0gY2RbaV07XG4gICAgICAgICAgICBsb25sYXQgPSBkaS5sb25sYXQ7XG5cbiAgICAgICAgICAgIC8vIHNvbWUgcHJvamVjdGlvbiB0eXBlcyBjYW4ndCBoYW5kbGUgQkFETlVNc1xuICAgICAgICAgICAgaWYobG9ubGF0WzBdID09PSBCQUROVU0pIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB4ID0geGEuYzJwKGxvbmxhdCk7XG4gICAgICAgICAgICB5ID0geWEuYzJwKGxvbmxhdCk7XG5cbiAgICAgICAgICAgIGlmKHNlbGVjdGlvblRlc3Rlci5jb250YWlucyhbeCwgeV0sIG51bGwsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgbG9uOiBsb25sYXRbMF0sXG4gICAgICAgICAgICAgICAgICAgIGxhdDogbG9ubGF0WzFdXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gcmVxdWlyZShcIi9ob21lL2NpcmNsZWNpL3Bsb3RseS5qcy90ZXN0L2ltYWdlL3N0cmljdC1kMy5qc1wiKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciBzY2F0dGVyU3R5bGUgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N0eWxlJyk7XG52YXIgc3R5bGVQb2ludHMgPSBzY2F0dGVyU3R5bGUuc3R5bGVQb2ludHM7XG52YXIgc3R5bGVUZXh0ID0gc2NhdHRlclN0eWxlLnN0eWxlVGV4dDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCwgY2FsY1RyYWNlKSB7XG4gICAgaWYoY2FsY1RyYWNlKSBzdHlsZVRyYWNlKGdkLCBjYWxjVHJhY2UpO1xufTtcblxuZnVuY3Rpb24gc3R5bGVUcmFjZShnZCwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBzID0gY2FsY1RyYWNlWzBdLm5vZGUzO1xuXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGNhbGNUcmFjZVswXS50cmFjZS5vcGFjaXR5KTtcblxuICAgIHN0eWxlUG9pbnRzKHMsIHRyYWNlLCBnZCk7XG4gICAgc3R5bGVUZXh0KHMsIHRyYWNlLCBnZCk7XG5cbiAgICAvLyB0aGlzIHBhcnQgaXMgaW5jb21wYXRpYmxlIHdpdGggRHJhd2luZy5saW5lR3JvdXBTdHlsZVxuICAgIHMuc2VsZWN0QWxsKCdwYXRoLmpzLWxpbmUnKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBwYXRoID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gZC50cmFjZTtcbiAgICAgICAgICAgIHZhciBsaW5lID0gdHJhY2UubGluZSB8fCB7fTtcblxuICAgICAgICAgICAgcGF0aC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZS5jb2xvcilcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCBsaW5lLmRhc2ggfHwgJycsIGxpbmUud2lkdGggfHwgMCk7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLmZpbGwgIT09ICdub25lJykge1xuICAgICAgICAgICAgICAgIHBhdGguY2FsbChDb2xvci5maWxsLCB0cmFjZS5maWxsY29sb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHBsb3RBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBzY2F0dGVyQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciBEQVNIRVMgPSByZXF1aXJlKCcuL2NvbnN0YW50cycpLkRBU0hFUztcblxudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxudmFyIGF0dHJzID0gbW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgeDogc2NhdHRlckF0dHJzLngsXG4gICAgeDA6IHNjYXR0ZXJBdHRycy54MCxcbiAgICBkeDogc2NhdHRlckF0dHJzLmR4LFxuICAgIHk6IHNjYXR0ZXJBdHRycy55LFxuICAgIHkwOiBzY2F0dGVyQXR0cnMueTAsXG4gICAgZHk6IHNjYXR0ZXJBdHRycy5keSxcblxuICAgIHRleHQ6IHNjYXR0ZXJBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogc2NhdHRlckF0dHJzLmhvdmVydGV4dCxcblxuICAgIHRleHRwb3NpdGlvbjogc2NhdHRlckF0dHJzLnRleHRwb3NpdGlvbixcbiAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnRleHRmb250LFxuXG4gICAgbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydsaW5lcycsICdtYXJrZXJzJywgJ3RleHQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGluZToge1xuICAgICAgICBjb2xvcjogc2NhdHRlckxpbmVBdHRycy5jb2xvcixcbiAgICAgICAgd2lkdGg6IHNjYXR0ZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgIHNoYXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnbGluZWFyJywgJ2h2JywgJ3ZoJywgJ2h2aCcsICd2aHYnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdsaW5lYXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGRhc2g6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogT2JqZWN0LmtleXMoREFTSEVTKSxcbiAgICAgICAgICAgIGRmbHQ6ICdzb2xpZCcsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcbiAgICBtYXJrZXI6IGV4dGVuZEZsYXQoe30sIGNvbG9yQXR0cnMoJ21hcmtlcicpLCB7XG4gICAgICAgIHN5bWJvbDogc2NhdHRlck1hcmtlckF0dHJzLnN5bWJvbCxcbiAgICAgICAgc2l6ZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemUsXG4gICAgICAgIHNpemVyZWY6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1pbixcbiAgICAgICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck1hcmtlckF0dHJzLm9wYWNpdHksXG4gICAgICAgIGNvbG9yYmFyOiBzY2F0dGVyTWFya2VyQXR0cnMuY29sb3JiYXIsXG4gICAgICAgIGxpbmU6IGV4dGVuZEZsYXQoe30sIGNvbG9yQXR0cnMoJ21hcmtlci5saW5lJyksIHtcbiAgICAgICAgICAgIHdpZHRoOiBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoXG4gICAgICAgIH0pXG4gICAgfSksXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcbiAgICBmaWxsOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuZmlsbCwge2RmbHQ6ICdub25lJ30pLFxuICAgIGZpbGxjb2xvcjogc2NhdHRlckF0dHJzLmZpbGxjb2xvcixcblxuICAgIC8vIG5vIGhvdmVyb25cblxuICAgIHNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZC50ZXh0Zm9udFxuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLnRleHRmb250XG4gICAgfSxcblxuICAgIG9wYWNpdHk6IHBsb3RBdHRycy5vcGFjaXR5XG5cbn0sICdjYWxjJywgJ25lc3RlZCcpO1xuXG5hdHRycy54LmVkaXRUeXBlID0gYXR0cnMueS5lZGl0VHlwZSA9IGF0dHJzLngwLmVkaXRUeXBlID0gYXR0cnMueTAuZWRpdFR5cGUgPSAnY2FsYytjbGVhckF4aXNUeXBlcyc7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBTWU1CT0xfU0laRSA9IDIwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBUT09fTUFOWV9QT0lOVFM6IDFlNSxcblxuICAgIFNZTUJPTF9TREZfU0laRTogMjAwLFxuICAgIFNZTUJPTF9TSVpFOiBTWU1CT0xfU0laRSxcbiAgICBTWU1CT0xfU1RST0tFOiBTWU1CT0xfU0laRSAvIDIwLFxuXG4gICAgRE9UX1JFOiAvLWRvdC8sXG4gICAgT1BFTl9SRTogLy1vcGVuLyxcblxuICAgIERBU0hFUzoge1xuICAgICAgICBzb2xpZDogWzFdLFxuICAgICAgICBkb3Q6IFsxLCAxXSxcbiAgICAgICAgZGFzaDogWzQsIDFdLFxuICAgICAgICBsb25nZGFzaDogWzgsIDFdLFxuICAgICAgICBkYXNoZG90OiBbNCwgMSwgMSwgMV0sXG4gICAgICAgIGxvbmdkYXNoZG90OiBbOCwgMSwgMSwgMV1cbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciBzdmdTZGYgPSByZXF1aXJlKCdzdmctcGF0aC1zZGYnKTtcbnZhciByZ2JhID0gcmVxdWlyZSgnY29sb3Itbm9ybWFsaXplJyk7XG5cbnZhciBSZWdpc3RyeSA9IHJlcXVpcmUoJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIEF4aXNJRHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcblxudmFyIGZvcm1hdENvbG9yID0gcmVxdWlyZSgnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLmZvcm1hdENvbG9yO1xudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIG1ha2VCdWJibGVTaXplRm4gPSByZXF1aXJlKCcuLi9zY2F0dGVyL21ha2VfYnViYmxlX3NpemVfZnVuYycpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKTtcbnZhciBERVNFTEVDVERJTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnMnKS5ERVNFTEVDVERJTTtcblxudmFyIFRFWFRPRkZTRVRTSUdOID0ge1xuICAgIHN0YXJ0OiAxLCBsZWZ0OiAxLCBlbmQ6IC0xLCByaWdodDogLTEsIG1pZGRsZTogMCwgY2VudGVyOiAwLCBib3R0b206IDEsIHRvcDogLTFcbn07XG5cbmZ1bmN0aW9uIGNvbnZlcnRTdHlsZShnZCwgdHJhY2UpIHtcbiAgICB2YXIgaTtcblxuICAgIHZhciBvcHRzID0ge1xuICAgICAgICBtYXJrZXI6IHVuZGVmaW5lZCxcbiAgICAgICAgbWFya2VyU2VsOiB1bmRlZmluZWQsXG4gICAgICAgIG1hcmtlclVuc2VsOiB1bmRlZmluZWQsXG4gICAgICAgIGxpbmU6IHVuZGVmaW5lZCxcbiAgICAgICAgZmlsbDogdW5kZWZpbmVkLFxuICAgICAgICBlcnJvclg6IHVuZGVmaW5lZCxcbiAgICAgICAgZXJyb3JZOiB1bmRlZmluZWQsXG4gICAgICAgIHRleHQ6IHVuZGVmaW5lZCxcbiAgICAgICAgdGV4dFNlbDogdW5kZWZpbmVkLFxuICAgICAgICB0ZXh0VW5zZWw6IHVuZGVmaW5lZFxuICAgIH07XG5cbiAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlKSByZXR1cm4gb3B0cztcblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2UpKSB7XG4gICAgICAgIG9wdHMudGV4dCA9IGNvbnZlcnRUZXh0U3R5bGUodHJhY2UpO1xuICAgICAgICBvcHRzLnRleHRTZWwgPSBjb252ZXJ0VGV4dFNlbGVjdGlvbih0cmFjZSwgdHJhY2Uuc2VsZWN0ZWQpO1xuICAgICAgICBvcHRzLnRleHRVbnNlbCA9IGNvbnZlcnRUZXh0U2VsZWN0aW9uKHRyYWNlLCB0cmFjZS51bnNlbGVjdGVkKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKSkge1xuICAgICAgICBvcHRzLm1hcmtlciA9IGNvbnZlcnRNYXJrZXJTdHlsZSh0cmFjZSk7XG4gICAgICAgIG9wdHMubWFya2VyU2VsID0gY29udmVydE1hcmtlclNlbGVjdGlvbih0cmFjZSwgdHJhY2Uuc2VsZWN0ZWQpO1xuICAgICAgICBvcHRzLm1hcmtlclVuc2VsID0gY29udmVydE1hcmtlclNlbGVjdGlvbih0cmFjZSwgdHJhY2UudW5zZWxlY3RlZCk7XG5cbiAgICAgICAgaWYoIXRyYWNlLnVuc2VsZWN0ZWQgJiYgQXJyYXkuaXNBcnJheSh0cmFjZS5tYXJrZXIub3BhY2l0eSkpIHtcbiAgICAgICAgICAgIHZhciBtbyA9IHRyYWNlLm1hcmtlci5vcGFjaXR5O1xuICAgICAgICAgICAgb3B0cy5tYXJrZXJVbnNlbC5vcGFjaXR5ID0gbmV3IEFycmF5KG1vLmxlbmd0aCk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBtby5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG9wdHMubWFya2VyVW5zZWwub3BhY2l0eVtpXSA9IERFU0VMRUNURElNICogbW9baV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSkpIHtcbiAgICAgICAgb3B0cy5saW5lID0ge1xuICAgICAgICAgICAgb3ZlcmxheTogdHJ1ZSxcbiAgICAgICAgICAgIHRoaWNrbmVzczogdHJhY2UubGluZS53aWR0aCxcbiAgICAgICAgICAgIGNvbG9yOiB0cmFjZS5saW5lLmNvbG9yLFxuICAgICAgICAgICAgb3BhY2l0eTogdHJhY2Uub3BhY2l0eVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBkYXNoZXMgPSAoY29uc3RhbnRzLkRBU0hFU1t0cmFjZS5saW5lLmRhc2hdIHx8IFsxXSkuc2xpY2UoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZGFzaGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBkYXNoZXNbaV0gKj0gdHJhY2UubGluZS53aWR0aDtcbiAgICAgICAgfVxuICAgICAgICBvcHRzLmxpbmUuZGFzaGVzID0gZGFzaGVzO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLmVycm9yX3ggJiYgdHJhY2UuZXJyb3JfeC52aXNpYmxlKSB7XG4gICAgICAgIG9wdHMuZXJyb3JYID0gY29udmVydEVycm9yQmFyU3R5bGUodHJhY2UsIHRyYWNlLmVycm9yX3gpO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLmVycm9yX3kgJiYgdHJhY2UuZXJyb3JfeS52aXNpYmxlKSB7XG4gICAgICAgIG9wdHMuZXJyb3JZID0gY29udmVydEVycm9yQmFyU3R5bGUodHJhY2UsIHRyYWNlLmVycm9yX3kpO1xuICAgIH1cblxuICAgIGlmKCEhdHJhY2UuZmlsbCAmJiB0cmFjZS5maWxsICE9PSAnbm9uZScpIHtcbiAgICAgICAgb3B0cy5maWxsID0ge1xuICAgICAgICAgICAgY2xvc2VkOiB0cnVlLFxuICAgICAgICAgICAgZmlsbDogdHJhY2UuZmlsbGNvbG9yLFxuICAgICAgICAgICAgdGhpY2tuZXNzOiAwXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHM7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRUZXh0U3R5bGUodHJhY2UpIHtcbiAgICB2YXIgY291bnQgPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciB0ZXh0Zm9udEluID0gdHJhY2UudGV4dGZvbnQ7XG4gICAgdmFyIHRleHRwb3NpdGlvbkluID0gdHJhY2UudGV4dHBvc2l0aW9uO1xuICAgIHZhciB0ZXh0UG9zID0gQXJyYXkuaXNBcnJheSh0ZXh0cG9zaXRpb25JbikgPyB0ZXh0cG9zaXRpb25JbiA6IFt0ZXh0cG9zaXRpb25Jbl07XG4gICAgdmFyIHRmYyA9IHRleHRmb250SW4uY29sb3I7XG4gICAgdmFyIHRmcyA9IHRleHRmb250SW4uc2l6ZTtcbiAgICB2YXIgdGZmID0gdGV4dGZvbnRJbi5mYW1pbHk7XG4gICAgdmFyIG9wdHNPdXQgPSB7fTtcbiAgICB2YXIgaTtcblxuICAgIG9wdHNPdXQudGV4dCA9IHRyYWNlLnRleHQ7XG4gICAgb3B0c091dC5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eTtcbiAgICBvcHRzT3V0LmZvbnQgPSB7fTtcbiAgICBvcHRzT3V0LmFsaWduID0gW107XG4gICAgb3B0c091dC5iYXNlbGluZSA9IFtdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgdGV4dFBvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHAgPSB0ZXh0UG9zW2ldLnNwbGl0KC9cXHMrLyk7XG5cbiAgICAgICAgc3dpdGNoKHRwWzFdKSB7XG4gICAgICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgICAgICAgICBvcHRzT3V0LmFsaWduLnB1c2goJ3JpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgICAgICAgICAgb3B0c091dC5hbGlnbi5wdXNoKCdsZWZ0Jyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG9wdHNPdXQuYWxpZ24ucHVzaCh0cFsxXSk7XG4gICAgICAgIH1cbiAgICAgICAgc3dpdGNoKHRwWzBdKSB7XG4gICAgICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgICAgICAgIG9wdHNPdXQuYmFzZWxpbmUucHVzaCgnYm90dG9tJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdib3R0b20nOlxuICAgICAgICAgICAgICAgIG9wdHNPdXQuYmFzZWxpbmUucHVzaCgndG9wJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG9wdHNPdXQuYmFzZWxpbmUucHVzaCh0cFswXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KHRmYykpIHtcbiAgICAgICAgb3B0c091dC5jb2xvciA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIG9wdHNPdXQuY29sb3JbaV0gPSB0ZmNbaV07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LmNvbG9yID0gdGZjO1xuICAgIH1cblxuICAgIGlmKEFycmF5LmlzQXJyYXkodGZzKSB8fCBBcnJheS5pc0FycmF5KHRmZikpIHtcbiAgICAgICAgLy8gaWYgYW55IHRleHRmb250IHBhcmFtIGlzIGFycmF5IC0gbWFrZSByZW5kZXIgYSBiYXRjaFxuICAgICAgICBvcHRzT3V0LmZvbnQgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZm9udGkgPSBvcHRzT3V0LmZvbnRbaV0gPSB7fTtcblxuICAgICAgICAgICAgZm9udGkuc2l6ZSA9IEFycmF5LmlzQXJyYXkodGZzKSA/XG4gICAgICAgICAgICAgICAgKGlzTnVtZXJpYyh0ZnNbaV0pID8gdGZzW2ldIDogMCkgOlxuICAgICAgICAgICAgICAgIHRmcztcblxuICAgICAgICAgICAgZm9udGkuZmFtaWx5ID0gQXJyYXkuaXNBcnJheSh0ZmYpID8gdGZmW2ldIDogdGZmO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaWYgYm90aCBhcmUgc2luZ2xlIHZhbHVlcywgbWFrZSByZW5kZXIgZmFzdCBzaW5nbGUtdmFsdWVcbiAgICAgICAgb3B0c091dC5mb250ID0ge3NpemU6IHRmcywgZmFtaWx5OiB0ZmZ9O1xuICAgIH1cblxuICAgIHJldHVybiBvcHRzT3V0O1xufVxuXG5cbmZ1bmN0aW9uIGNvbnZlcnRNYXJrZXJTdHlsZSh0cmFjZSkge1xuICAgIHZhciBjb3VudCA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIG9wdHNJbiA9IHRyYWNlLm1hcmtlcjtcbiAgICB2YXIgb3B0c091dCA9IHt9O1xuICAgIHZhciBpO1xuXG4gICAgdmFyIG11bHRpU3ltYm9sID0gQXJyYXkuaXNBcnJheShvcHRzSW4uc3ltYm9sKTtcbiAgICB2YXIgbXVsdGlDb2xvciA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG9wdHNJbi5jb2xvcik7XG4gICAgdmFyIG11bHRpTGluZUNvbG9yID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkob3B0c0luLmxpbmUuY29sb3IpO1xuICAgIHZhciBtdWx0aU9wYWNpdHkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShvcHRzSW4ub3BhY2l0eSk7XG4gICAgdmFyIG11bHRpU2l6ZSA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG9wdHNJbi5zaXplKTtcbiAgICB2YXIgbXVsdGlMaW5lV2lkdGggPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShvcHRzSW4ubGluZS53aWR0aCk7XG5cbiAgICB2YXIgaXNPcGVuO1xuICAgIGlmKCFtdWx0aVN5bWJvbCkgaXNPcGVuID0gY29uc3RhbnRzLk9QRU5fUkUudGVzdChvcHRzSW4uc3ltYm9sKTtcblxuICAgIC8vIHByZXBhcmUgY29sb3JzXG4gICAgaWYobXVsdGlTeW1ib2wgfHwgbXVsdGlDb2xvciB8fCBtdWx0aUxpbmVDb2xvciB8fCBtdWx0aU9wYWNpdHkpIHtcbiAgICAgICAgb3B0c091dC5jb2xvcnMgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBvcHRzT3V0LmJvcmRlckNvbG9ycyA9IG5ldyBBcnJheShjb3VudCk7XG5cbiAgICAgICAgdmFyIGNvbG9ycyA9IGZvcm1hdENvbG9yKG9wdHNJbiwgb3B0c0luLm9wYWNpdHksIGNvdW50KTtcbiAgICAgICAgdmFyIGJvcmRlckNvbG9ycyA9IGZvcm1hdENvbG9yKG9wdHNJbi5saW5lLCBvcHRzSW4ub3BhY2l0eSwgY291bnQpO1xuXG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGJvcmRlckNvbG9yc1swXSkpIHtcbiAgICAgICAgICAgIHZhciBib3JkZXJDb2xvciA9IGJvcmRlckNvbG9ycztcbiAgICAgICAgICAgIGJvcmRlckNvbG9ycyA9IEFycmF5KGNvdW50KTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBib3JkZXJDb2xvcnNbaV0gPSBib3JkZXJDb2xvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZighQXJyYXkuaXNBcnJheShjb2xvcnNbMF0pKSB7XG4gICAgICAgICAgICB2YXIgY29sb3IgPSBjb2xvcnM7XG4gICAgICAgICAgICBjb2xvcnMgPSBBcnJheShjb3VudCk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29sb3JzW2ldID0gY29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvcHRzT3V0LmNvbG9ycyA9IGNvbG9ycztcbiAgICAgICAgb3B0c091dC5ib3JkZXJDb2xvcnMgPSBib3JkZXJDb2xvcnM7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgaWYobXVsdGlTeW1ib2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3ltYm9sID0gb3B0c0luLnN5bWJvbFtpXTtcbiAgICAgICAgICAgICAgICBpc09wZW4gPSBjb25zdGFudHMuT1BFTl9SRS50ZXN0KHN5bWJvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihpc09wZW4pIHtcbiAgICAgICAgICAgICAgICBib3JkZXJDb2xvcnNbaV0gPSBjb2xvcnNbaV0uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICBjb2xvcnNbaV0gPSBjb2xvcnNbaV0uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICBjb2xvcnNbaV1bM10gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgb3B0c091dC5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihpc09wZW4pIHtcbiAgICAgICAgICAgIG9wdHNPdXQuY29sb3IgPSByZ2JhKG9wdHNJbi5jb2xvciwgJ3VpbnQ4Jyk7XG4gICAgICAgICAgICBvcHRzT3V0LmNvbG9yWzNdID0gMDtcbiAgICAgICAgICAgIG9wdHNPdXQuYm9yZGVyQ29sb3IgPSByZ2JhKG9wdHNJbi5jb2xvciwgJ3VpbnQ4Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRzT3V0LmNvbG9yID0gcmdiYShvcHRzSW4uY29sb3IsICd1aW50OCcpO1xuICAgICAgICAgICAgb3B0c091dC5ib3JkZXJDb2xvciA9IHJnYmEob3B0c0luLmxpbmUuY29sb3IsICd1aW50OCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0c091dC5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eSAqIG9wdHNJbi5vcGFjaXR5O1xuICAgIH1cblxuICAgIC8vIHByZXBhcmUgc3ltYm9sc1xuICAgIGlmKG11bHRpU3ltYm9sKSB7XG4gICAgICAgIG9wdHNPdXQubWFya2VycyA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIG9wdHNPdXQubWFya2Vyc1tpXSA9IGdldFN5bWJvbFNkZihvcHRzSW4uc3ltYm9sW2ldKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdHNPdXQubWFya2VyID0gZ2V0U3ltYm9sU2RmKG9wdHNJbi5zeW1ib2wpO1xuICAgIH1cblxuICAgIC8vIHByZXBhcmUgc2l6ZXNcbiAgICB2YXIgbWFya2VyU2l6ZUZ1bmMgPSBtYWtlQnViYmxlU2l6ZUZuKHRyYWNlKTtcbiAgICB2YXIgcztcblxuICAgIGlmKG11bHRpU2l6ZSB8fCBtdWx0aUxpbmVXaWR0aCkge1xuICAgICAgICB2YXIgc2l6ZXMgPSBvcHRzT3V0LnNpemVzID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgdmFyIGJvcmRlclNpemVzID0gb3B0c091dC5ib3JkZXJTaXplcyA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgIHZhciBzaXplVG90YWwgPSAwO1xuICAgICAgICB2YXIgc2l6ZUF2ZztcblxuICAgICAgICBpZihtdWx0aVNpemUpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaXplc1tpXSA9IG1hcmtlclNpemVGdW5jKG9wdHNJbi5zaXplW2ldKTtcbiAgICAgICAgICAgICAgICBzaXplVG90YWwgKz0gc2l6ZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaXplQXZnID0gc2l6ZVRvdGFsIC8gY291bnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzID0gbWFya2VyU2l6ZUZ1bmMob3B0c0luLnNpemUpO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHNpemVzW2ldID0gcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNlZSAgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvcHVsbC8xNzgxI2Rpc2N1c3Npb25fcjEyMTgyMDc5OFxuICAgICAgICBpZihtdWx0aUxpbmVXaWR0aCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGJvcmRlclNpemVzW2ldID0gb3B0c0luLmxpbmUud2lkdGhbaV0gLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcyA9IG9wdHNJbi5saW5lLndpZHRoIC8gMjtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBib3JkZXJTaXplc1tpXSA9IHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvcHRzT3V0LnNpemVBdmcgPSBzaXplQXZnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdHNPdXQuc2l6ZSA9IG1hcmtlclNpemVGdW5jKG9wdHNJbiAmJiBvcHRzSW4uc2l6ZSB8fCAxMCk7XG4gICAgICAgIG9wdHNPdXQuYm9yZGVyU2l6ZXMgPSBtYXJrZXJTaXplRnVuYyhvcHRzSW4ubGluZS53aWR0aCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHNPdXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRhcmdldCkge1xuICAgIHZhciBvcHRzSW4gPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIG9wdHNPdXQgPSB7fTtcblxuICAgIGlmKCF0YXJnZXQpIHJldHVybiBvcHRzT3V0O1xuXG4gICAgaWYodGFyZ2V0Lm1hcmtlciAmJiB0YXJnZXQubWFya2VyLnN5bWJvbCkge1xuICAgICAgICBvcHRzT3V0ID0gY29udmVydE1hcmtlclN0eWxlKExpYi5leHRlbmRGbGF0KHt9LCBvcHRzSW4sIHRhcmdldC5tYXJrZXIpKTtcbiAgICB9IGVsc2UgaWYodGFyZ2V0Lm1hcmtlcikge1xuICAgICAgICBpZih0YXJnZXQubWFya2VyLnNpemUpIG9wdHNPdXQuc2l6ZSA9IHRhcmdldC5tYXJrZXIuc2l6ZSAvIDI7XG4gICAgICAgIGlmKHRhcmdldC5tYXJrZXIuY29sb3IpIG9wdHNPdXQuY29sb3JzID0gdGFyZ2V0Lm1hcmtlci5jb2xvcjtcbiAgICAgICAgaWYodGFyZ2V0Lm1hcmtlci5vcGFjaXR5ICE9PSB1bmRlZmluZWQpIG9wdHNPdXQub3BhY2l0eSA9IHRhcmdldC5tYXJrZXIub3BhY2l0eTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0c091dDtcbn1cblxuZnVuY3Rpb24gY29udmVydFRleHRTZWxlY3Rpb24odHJhY2UsIHRhcmdldCkge1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBpZighdGFyZ2V0KSByZXR1cm4gb3B0c091dDtcblxuICAgIGlmKHRhcmdldC50ZXh0Zm9udCkge1xuICAgICAgICB2YXIgb3B0c0luID0ge1xuICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgIHRleHQ6IHRyYWNlLnRleHQsXG4gICAgICAgICAgICB0ZXh0cG9zaXRpb246IHRyYWNlLnRleHRwb3NpdGlvbixcbiAgICAgICAgICAgIHRleHRmb250OiBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhY2UudGV4dGZvbnQpXG4gICAgICAgIH07XG4gICAgICAgIGlmKHRhcmdldC50ZXh0Zm9udCkge1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQob3B0c0luLnRleHRmb250LCB0YXJnZXQudGV4dGZvbnQpO1xuICAgICAgICB9XG4gICAgICAgIG9wdHNPdXQgPSBjb252ZXJ0VGV4dFN0eWxlKG9wdHNJbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHNPdXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRFcnJvckJhclN0eWxlKHRyYWNlLCB0YXJnZXQpIHtcbiAgICB2YXIgb3B0c091dCA9IHtcbiAgICAgICAgY2FwU2l6ZTogdGFyZ2V0LndpZHRoICogMixcbiAgICAgICAgbGluZVdpZHRoOiB0YXJnZXQudGhpY2tuZXNzLFxuICAgICAgICBjb2xvcjogdGFyZ2V0LmNvbG9yXG4gICAgfTtcblxuICAgIGlmKHRhcmdldC5jb3B5X3lzdHlsZSkge1xuICAgICAgICBvcHRzT3V0ID0gdHJhY2UuZXJyb3JfeTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0c091dDtcbn1cblxudmFyIFNZTUJPTF9TREZfU0laRSA9IGNvbnN0YW50cy5TWU1CT0xfU0RGX1NJWkU7XG52YXIgU1lNQk9MX1NJWkUgPSBjb25zdGFudHMuU1lNQk9MX1NJWkU7XG52YXIgU1lNQk9MX1NUUk9LRSA9IGNvbnN0YW50cy5TWU1CT0xfU1RST0tFO1xudmFyIFNZTUJPTF9TREYgPSB7fTtcbnZhciBTWU1CT0xfU1ZHX0NJUkNMRSA9IERyYXdpbmcuc3ltYm9sRnVuY3NbMF0oU1lNQk9MX1NJWkUgKiAwLjA1KTtcblxuZnVuY3Rpb24gZ2V0U3ltYm9sU2RmKHN5bWJvbCkge1xuICAgIGlmKHN5bWJvbCA9PT0gJ2NpcmNsZScpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIHN5bWJvbFBhdGgsIHN5bWJvbFNkZjtcbiAgICB2YXIgc3ltYm9sTnVtYmVyID0gRHJhd2luZy5zeW1ib2xOdW1iZXIoc3ltYm9sKTtcbiAgICB2YXIgc3ltYm9sRnVuYyA9IERyYXdpbmcuc3ltYm9sRnVuY3Nbc3ltYm9sTnVtYmVyICUgMTAwXTtcbiAgICB2YXIgc3ltYm9sTm9Eb3QgPSAhIURyYXdpbmcuc3ltYm9sTm9Eb3Rbc3ltYm9sTnVtYmVyICUgMTAwXTtcbiAgICB2YXIgc3ltYm9sTm9GaWxsID0gISFEcmF3aW5nLnN5bWJvbE5vRmlsbFtzeW1ib2xOdW1iZXIgJSAxMDBdO1xuXG4gICAgdmFyIGlzRG90ID0gY29uc3RhbnRzLkRPVF9SRS50ZXN0KHN5bWJvbCk7XG5cbiAgICAvLyBnZXQgc3ltYm9sIHNkZiBmcm9tIGNhY2hlIG9yIGdlbmVyYXRlIGl0XG4gICAgaWYoU1lNQk9MX1NERltzeW1ib2xdKSByZXR1cm4gU1lNQk9MX1NERltzeW1ib2xdO1xuXG4gICAgaWYoaXNEb3QgJiYgIXN5bWJvbE5vRG90KSB7XG4gICAgICAgIHN5bWJvbFBhdGggPSBzeW1ib2xGdW5jKFNZTUJPTF9TSVpFICogMS4xKSArIFNZTUJPTF9TVkdfQ0lSQ0xFO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc3ltYm9sUGF0aCA9IHN5bWJvbEZ1bmMoU1lNQk9MX1NJWkUpO1xuICAgIH1cblxuICAgIHN5bWJvbFNkZiA9IHN2Z1NkZihzeW1ib2xQYXRoLCB7XG4gICAgICAgIHc6IFNZTUJPTF9TREZfU0laRSxcbiAgICAgICAgaDogU1lNQk9MX1NERl9TSVpFLFxuICAgICAgICB2aWV3Qm94OiBbLVNZTUJPTF9TSVpFLCAtU1lNQk9MX1NJWkUsIFNZTUJPTF9TSVpFLCBTWU1CT0xfU0laRV0sXG4gICAgICAgIHN0cm9rZTogc3ltYm9sTm9GaWxsID8gU1lNQk9MX1NUUk9LRSA6IC1TWU1CT0xfU1RST0tFXG4gICAgfSk7XG4gICAgU1lNQk9MX1NERltzeW1ib2xdID0gc3ltYm9sU2RmO1xuXG4gICAgcmV0dXJuIHN5bWJvbFNkZiB8fCBudWxsO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0TGluZVBvc2l0aW9ucyhnZCwgdHJhY2UsIHBvc2l0aW9ucykge1xuICAgIHZhciBsZW4gPSBwb3NpdGlvbnMubGVuZ3RoO1xuICAgIHZhciBjb3VudCA9IGxlbiAvIDI7XG4gICAgdmFyIGxpbmVQb3NpdGlvbnM7XG4gICAgdmFyIGk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSkgJiYgY291bnQpIHtcbiAgICAgICAgaWYodHJhY2UubGluZS5zaGFwZSA9PT0gJ2h2Jykge1xuICAgICAgICAgICAgbGluZVBvc2l0aW9ucyA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQgLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZihpc05hTihwb3NpdGlvbnNbaSAqIDJdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOLCBOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tpICogMl0sIHBvc2l0aW9uc1tpICogMiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIWlzTmFOKHBvc2l0aW9uc1tpICogMiArIDJdKSAmJiAhaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgM10pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2kgKiAyICsgMl0sIHBvc2l0aW9uc1tpICogMiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2xlbiAtIDJdLCBwb3NpdGlvbnNbbGVuIC0gMV0pO1xuICAgICAgICB9IGVsc2UgaWYodHJhY2UubGluZS5zaGFwZSA9PT0gJ2h2aCcpIHtcbiAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50IC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNOYU4ocG9zaXRpb25zW2kgKiAyXSkgfHwgaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgMV0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDJdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAzXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIWlzTmFOKHBvc2l0aW9uc1tpICogMl0pICYmICFpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbaSAqIDJdLCBwb3NpdGlvbnNbaSAqIDIgKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goTmFOLCBOYU4pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWlkUHRYID0gKHBvc2l0aW9uc1tpICogMl0gKyBwb3NpdGlvbnNbaSAqIDIgKyAyXSkgLyAyO1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zW2kgKiAyICsgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWRQdFgsXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDIgKyAxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pZFB0WCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMiArIDNdXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tsZW4gLSAyXSwgcG9zaXRpb25zW2xlbiAtIDFdKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLmxpbmUuc2hhcGUgPT09ICd2aHYnKSB7XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKHBvc2l0aW9uc1tpICogMl0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDFdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAyXSkgfHwgaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgM10pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTihwb3NpdGlvbnNbaSAqIDJdKSAmJiAhaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2kgKiAyXSwgcG9zaXRpb25zW2kgKiAyICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goTmFOLCBOYU4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pZFB0WSA9IChwb3NpdGlvbnNbaSAqIDIgKyAxXSArIHBvc2l0aW9uc1tpICogMiArIDNdKSAvIDI7XG4gICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDIgKyAxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWRQdFksXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDIgKyAyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pZFB0WVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbbGVuIC0gMl0sIHBvc2l0aW9uc1tsZW4gLSAxXSk7XG4gICAgICAgIH0gZWxzZSBpZih0cmFjZS5saW5lLnNoYXBlID09PSAndmgnKSB7XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKHBvc2l0aW9uc1tpICogMl0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goTmFOLCBOYU4sIE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbaSAqIDJdLCBwb3NpdGlvbnNbaSAqIDIgKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAyXSkgJiYgIWlzTmFOKHBvc2l0aW9uc1tpICogMiArIDNdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tpICogMl0sIHBvc2l0aW9uc1tpICogMiArIDNdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2xlbiAtIDJdLCBwb3NpdGlvbnNbbGVuIC0gMV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGluZVBvc2l0aW9ucyA9IHBvc2l0aW9ucztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIElmIHdlIGhhdmUgZGF0YSB3aXRoIGdhcHMsIHdlIG91Z2h0IHRvIHVzZSByZWN0IGpvaW5zXG4gICAgLy8gRklYTUU6IGdldCByaWQgb2YgdGhpc1xuICAgIHZhciBoYXNOYU4gPSBmYWxzZTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsaW5lUG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGlzTmFOKGxpbmVQb3NpdGlvbnNbaV0pKSB7XG4gICAgICAgICAgICBoYXNOYU4gPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgam9pbiA9IChoYXNOYU4gfHwgbGluZVBvc2l0aW9ucy5sZW5ndGggPiBjb25zdGFudHMuVE9PX01BTllfUE9JTlRTKSA/ICdyZWN0JyA6XG4gICAgICAgIHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpID8gJ3JlY3QnIDogJ3JvdW5kJztcblxuICAgIC8vIGZpbGwgZ2Fwc1xuICAgIGlmKGhhc05hTiAmJiB0cmFjZS5jb25uZWN0Z2Fwcykge1xuICAgICAgICB2YXIgbGFzdFggPSBsaW5lUG9zaXRpb25zWzBdO1xuICAgICAgICB2YXIgbGFzdFkgPSBsaW5lUG9zaXRpb25zWzFdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxpbmVQb3NpdGlvbnMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgICAgIGlmKGlzTmFOKGxpbmVQb3NpdGlvbnNbaV0pIHx8IGlzTmFOKGxpbmVQb3NpdGlvbnNbaSArIDFdKSkge1xuICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnNbaV0gPSBsYXN0WDtcbiAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zW2kgKyAxXSA9IGxhc3RZO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGFzdFggPSBsaW5lUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgIGxhc3RZID0gbGluZVBvc2l0aW9uc1tpICsgMV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBqb2luOiBqb2luLFxuICAgICAgICBwb3NpdGlvbnM6IGxpbmVQb3NpdGlvbnNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0RXJyb3JCYXJQb3NpdGlvbnMoZ2QsIHRyYWNlLCBwb3NpdGlvbnMsIHgsIHkpIHtcbiAgICB2YXIgbWFrZUNvbXB1dGVFcnJvciA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZXJyb3JiYXJzJywgJ21ha2VDb21wdXRlRXJyb3InKTtcbiAgICB2YXIgeGEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMpO1xuICAgIHZhciB5YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyk7XG4gICAgdmFyIGNvdW50ID0gcG9zaXRpb25zLmxlbmd0aCAvIDI7XG4gICAgdmFyIG91dCA9IHt9O1xuXG4gICAgZnVuY3Rpb24gY29udmVydE9uZUF4aXMoY29vcmRzLCBheCkge1xuICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApO1xuICAgICAgICB2YXIgb3B0cyA9IHRyYWNlWydlcnJvcl8nICsgYXhMZXR0ZXJdO1xuXG4gICAgICAgIGlmKG9wdHMgJiYgb3B0cy52aXNpYmxlICYmIChheC50eXBlID09PSAnbGluZWFyJyB8fCBheC50eXBlID09PSAnbG9nJykpIHtcbiAgICAgICAgICAgIHZhciBjb21wdXRlRXJyb3IgPSBtYWtlQ29tcHV0ZUVycm9yKG9wdHMpO1xuICAgICAgICAgICAgdmFyIHBPZmZzZXQgPSB7eDogMCwgeTogMX1bYXhMZXR0ZXJdO1xuICAgICAgICAgICAgdmFyIGVPZmZzZXQgPSB7eDogWzAsIDEsIDIsIDNdLCB5OiBbMiwgMywgMCwgMV19W2F4TGV0dGVyXTtcbiAgICAgICAgICAgIHZhciBlcnJvcnMgPSBuZXcgRmxvYXQ2NEFycmF5KDQgKiBjb3VudCk7XG4gICAgICAgICAgICB2YXIgbWluU2hvZSA9IEluZmluaXR5O1xuICAgICAgICAgICAgdmFyIG1heEhhdCA9IC1JbmZpbml0eTtcblxuICAgICAgICAgICAgZm9yKHZhciBpID0gMCwgaiA9IDA7IGkgPCBjb3VudDsgaSsrLCBqICs9IDQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGMgPSBjb29yZHNbaV07XG5cbiAgICAgICAgICAgICAgICBpZihpc051bWVyaWMoZGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkbCA9IHBvc2l0aW9uc1tpICogMiArIHBPZmZzZXRdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFscyA9IGNvbXB1dGVFcnJvcihkYywgaSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsdiA9IHZhbHNbMF07XG4gICAgICAgICAgICAgICAgICAgIHZhciBodiA9IHZhbHNbMV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKGx2KSAmJiBpc051bWVyaWMoaHYpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2hvZSA9IGRjIC0gbHY7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaGF0ID0gZGMgKyBodjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzW2ogKyBlT2Zmc2V0WzBdXSA9IGRsIC0gYXguYzJsKHNob2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzW2ogKyBlT2Zmc2V0WzFdXSA9IGF4LmMybChoYXQpIC0gZGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnNbaiArIGVPZmZzZXRbMl1dID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yc1tqICsgZU9mZnNldFszXV0gPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5TaG9lID0gTWF0aC5taW4obWluU2hvZSwgZGMgLSBsdik7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhIYXQgPSBNYXRoLm1heChtYXhIYXQsIGRjICsgaHYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvdXRbYXhMZXR0ZXJdID0ge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uczogcG9zaXRpb25zLFxuICAgICAgICAgICAgICAgIGVycm9yczogZXJyb3JzLFxuICAgICAgICAgICAgICAgIF9ibmRzOiBbbWluU2hvZSwgbWF4SGF0XVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnZlcnRPbmVBeGlzKHgsIHhhKTtcbiAgICBjb252ZXJ0T25lQXhpcyh5LCB5YSk7XG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gY29udmVydFRleHRQb3NpdGlvbihnZCwgdHJhY2UsIHRleHRPcHRzLCBtYXJrZXJPcHRzKSB7XG4gICAgdmFyIGNvdW50ID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgb3V0ID0ge307XG4gICAgdmFyIGk7XG5cbiAgICAvLyBjb3JyZXNwb25kcyB0byB0ZXh0UG9pbnRQb3NpdGlvbiBmcm9tIGNvbXBvbmVudC5kcmF3aW5nXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkpIHtcbiAgICAgICAgdmFyIGZvbnRPcHRzID0gdGV4dE9wdHMuZm9udDtcbiAgICAgICAgdmFyIGFsaWduID0gdGV4dE9wdHMuYWxpZ247XG4gICAgICAgIHZhciBiYXNlbGluZSA9IHRleHRPcHRzLmJhc2VsaW5lO1xuICAgICAgICBvdXQub2Zmc2V0ID0gbmV3IEFycmF5KGNvdW50KTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbXMgPSBtYXJrZXJPcHRzLnNpemVzID8gbWFya2VyT3B0cy5zaXplc1tpXSA6IG1hcmtlck9wdHMuc2l6ZTtcbiAgICAgICAgICAgIHZhciBmcyA9IEFycmF5LmlzQXJyYXkoZm9udE9wdHMpID8gZm9udE9wdHNbaV0uc2l6ZSA6IGZvbnRPcHRzLnNpemU7XG5cbiAgICAgICAgICAgIHZhciBhID0gQXJyYXkuaXNBcnJheShhbGlnbikgP1xuICAgICAgICAgICAgICAgIChhbGlnbi5sZW5ndGggPiAxID8gYWxpZ25baV0gOiBhbGlnblswXSkgOlxuICAgICAgICAgICAgICAgIGFsaWduO1xuICAgICAgICAgICAgdmFyIGIgPSBBcnJheS5pc0FycmF5KGJhc2VsaW5lKSA/XG4gICAgICAgICAgICAgICAgKGJhc2VsaW5lLmxlbmd0aCA+IDEgPyBiYXNlbGluZVtpXSA6IGJhc2VsaW5lWzBdKSA6XG4gICAgICAgICAgICAgICAgYmFzZWxpbmU7XG5cbiAgICAgICAgICAgIHZhciBoU2lnbiA9IFRFWFRPRkZTRVRTSUdOW2FdO1xuICAgICAgICAgICAgdmFyIHZTaWduID0gVEVYVE9GRlNFVFNJR05bYl07XG4gICAgICAgICAgICB2YXIgeFBhZCA9IG1zID8gbXMgLyAwLjggKyAxIDogMDtcbiAgICAgICAgICAgIHZhciB5UGFkID0gLXZTaWduICogeFBhZCAtIHZTaWduICogMC41O1xuICAgICAgICAgICAgb3V0Lm9mZnNldFtpXSA9IFtoU2lnbiAqIHhQYWQgLyBmcywgeVBhZCAvIGZzXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBjb252ZXJ0U3R5bGUsXG5cbiAgICBtYXJrZXJTdHlsZTogY29udmVydE1hcmtlclN0eWxlLFxuICAgIG1hcmtlclNlbGVjdGlvbjogY29udmVydE1hcmtlclNlbGVjdGlvbixcblxuICAgIGxpbmVQb3NpdGlvbnM6IGNvbnZlcnRMaW5lUG9zaXRpb25zLFxuICAgIGVycm9yQmFyUG9zaXRpb25zOiBjb252ZXJ0RXJyb3JCYXJQb3NpdGlvbnMsXG4gICAgdGV4dFBvc2l0aW9uOiBjb252ZXJ0VGV4dFBvc2l0aW9uXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xudmFyIGNvbnN0YW50cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29uc3RhbnRzJyk7XG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlWFlEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIveHlfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2ZpbGxjb2xvcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgaXNPcGVuID0gdHJhY2VJbi5tYXJrZXIgPyAvLW9wZW4vLnRlc3QodHJhY2VJbi5tYXJrZXIuc3ltYm9sKSA6IGZhbHNlO1xuICAgIHZhciBpc0J1YmJsZSA9IHN1YlR5cGVzLmlzQnViYmxlKHRyYWNlSW4pO1xuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgZGVmYXVsdE1vZGUgPSBsZW4gPCBjb25zdGFudHMuUFRTX0xJTkVTT05MWSA/ICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcyc7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnbW9kZScsIGRlZmF1bHRNb2RlKTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkge1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnbGluZS5zaGFwZScpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcsIGlzT3BlbiB8fCBpc0J1YmJsZSA/IDEgOiAwKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2ZpbGwnKTtcbiAgICBpZih0cmFjZU91dC5maWxsICE9PSAnbm9uZScpIHtcbiAgICAgICAgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgY29lcmNlKTtcbiAgICB9XG5cbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIHtheGlzOiAneSd9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneSd9KTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZVNjYXR0ZXIgPSByZXF1aXJlKCdyZWdsLXNjYXR0ZXIyZCcpO1xudmFyIGNyZWF0ZUxpbmUgPSByZXF1aXJlKCdyZWdsLWxpbmUyZCcpO1xudmFyIGNyZWF0ZUVycm9yID0gcmVxdWlyZSgncmVnbC1lcnJvcjJkJyk7XG52YXIgY2x1c3RlciA9IHJlcXVpcmUoJ3BvaW50LWNsdXN0ZXInKTtcbnZhciBhcnJheVJhbmdlID0gcmVxdWlyZSgnYXJyYXktcmFuZ2UnKTtcbnZhciBUZXh0ID0gcmVxdWlyZSgnZ2wtdGV4dCcpO1xuXG52YXIgUmVnaXN0cnkgPSByZXF1aXJlKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHByZXBhcmVSZWdsID0gcmVxdWlyZSgnLi4vLi4vbGliL3ByZXBhcmVfcmVnbCcpO1xudmFyIEF4aXNJRHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcbnZhciBmaW5kRXh0cmVtZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXV0b3JhbmdlJykuZmluZEV4dHJlbWVzO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgc2NhdHRlckNhbGMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2NhbGMnKTtcbnZhciBjYWxjTWFya2VyU2l6ZSA9IHNjYXR0ZXJDYWxjLmNhbGNNYXJrZXJTaXplO1xudmFyIGNhbGNBeGlzRXhwYW5zaW9uID0gc2NhdHRlckNhbGMuY2FsY0F4aXNFeHBhbnNpb247XG52YXIgc2V0Rmlyc3RTY2F0dGVyID0gc2NhdHRlckNhbGMuc2V0Rmlyc3RTY2F0dGVyO1xudmFyIGNhbGNDb2xvcnNjYWxlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgbGlua1RyYWNlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGlua190cmFjZXMnKTtcbnZhciBnZXRUcmFjZUNvbG9yID0gcmVxdWlyZSgnLi4vc2NhdHRlci9nZXRfdHJhY2VfY29sb3InKTtcbnZhciBmaWxsSG92ZXJUZXh0ID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsX2hvdmVyX3RleHQnKTtcbnZhciBjb252ZXJ0ID0gcmVxdWlyZSgnLi9jb252ZXJ0Jyk7XG5cbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xudmFyIFRPT19NQU5ZX1BPSU5UUyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJykuVE9PX01BTllfUE9JTlRTO1xudmFyIERFU0VMRUNURElNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpLkRFU0VMRUNURElNO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHhhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuICAgIHZhciBzdWJwbG90ID0gZnVsbExheW91dC5fcGxvdHNbdHJhY2UueGF4aXMgKyB0cmFjZS55YXhpc107XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGxlbjIgPSBsZW4gKiAyO1xuICAgIHZhciBzdGFzaCA9IHt9O1xuICAgIHZhciBpLCB4eCwgeXk7XG5cbiAgICB2YXIgeCA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKTtcbiAgICB2YXIgeSA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKTtcblxuICAgIC8vIHdlIG5lZWQgaGktcHJlY2lzaW9uIGZvciBzY2F0dGVyMmQsXG4gICAgLy8gcmVnbC1zY2F0dGVyMmQgdXNlcyBOYU5zIGZvciBiYWQvbWlzc2luZyB2YWx1ZXNcbiAgICB2YXIgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbjIpO1xuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHh4ID0geFtpXTtcbiAgICAgICAgeXkgPSB5W2ldO1xuICAgICAgICBwb3NpdGlvbnNbaSAqIDJdID0geHggPT09IEJBRE5VTSA/IE5hTiA6IHh4O1xuICAgICAgICBwb3NpdGlvbnNbaSAqIDIgKyAxXSA9IHl5ID09PSBCQUROVU0gPyBOYU4gOiB5eTtcbiAgICB9XG5cbiAgICBpZih4YS50eXBlID09PSAnbG9nJykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW4yOyBpICs9IDIpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IHhhLmMybChwb3NpdGlvbnNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmKHlhLnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgIGZvcihpID0gMTsgaSA8IGxlbjI7IGkgKz0gMikge1xuICAgICAgICAgICAgcG9zaXRpb25zW2ldID0geWEuYzJsKHBvc2l0aW9uc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB3ZSBkb24ndCBidWlsZCBhIHRyZWUgZm9yIGxvZyBheGVzIHNpbmNlIGl0IHRha2VzIGxvbmcgdG8gY29udmVydCBsb2cycHhcbiAgICAvLyBhbmQgaXQgaXMgYWxzb1xuICAgIGlmKHhhLnR5cGUgIT09ICdsb2cnICYmIHlhLnR5cGUgIT09ICdsb2cnKSB7XG4gICAgICAgIC8vIEZJWE1FOiBkZWxlZ2F0ZSB0aGlzIHRvIHdlYndvcmtlclxuICAgICAgICBzdGFzaC50cmVlID0gY2x1c3Rlcihwb3NpdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBpZHMgPSBzdGFzaC5pZHMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlkc1tpXSA9IGk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgc2NlbmUgb3B0aW9ucyBhbmQgc2NlbmVcbiAgICBjYWxjQ29sb3JzY2FsZXModHJhY2UpO1xuICAgIHZhciBvcHRzID0gc2NlbmVPcHRpb25zKGdkLCBzdWJwbG90LCB0cmFjZSwgcG9zaXRpb25zLCB4LCB5KTtcbiAgICB2YXIgc2NlbmUgPSBzY2VuZVVwZGF0ZShnZCwgc3VicGxvdCk7XG5cbiAgICAvLyBSZXVzZSBTVkcgc2NhdHRlciBheGlzIGV4cGFuc2lvbiByb3V0aW5lLlxuICAgIC8vIEZvciBncmFwaHMgd2l0aCB2ZXJ5IGxhcmdlIG51bWJlciBvZiBwb2ludHMgYW5kIGFycmF5IG1hcmtlci5zaXplLFxuICAgIC8vIHVzZSBhdmVyYWdlIG1hcmtlciBzaXplIGluc3RlYWQgdG8gc3BlZWQgdGhpbmdzIHVwLlxuICAgIHNldEZpcnN0U2NhdHRlcihmdWxsTGF5b3V0LCB0cmFjZSk7XG4gICAgdmFyIHBwYWQgPSBsZW4gPCBUT09fTUFOWV9QT0lOVFMgP1xuICAgICAgICBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgbGVuKSA6XG4gICAgICAgIDIgKiAob3B0cy5tYXJrZXIuc2l6ZUF2ZyB8fCBNYXRoLm1heChvcHRzLm1hcmtlci5zaXplLCAzKSk7XG4gICAgY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpO1xuICAgIGlmKG9wdHMuZXJyb3JYKSBleHBhbmRGb3JFcnJvckJhcnModHJhY2UsIHhhLCBvcHRzLmVycm9yWCk7XG4gICAgaWYob3B0cy5lcnJvclkpIGV4cGFuZEZvckVycm9yQmFycyh0cmFjZSwgeWEsIG9wdHMuZXJyb3JZKTtcblxuICAgIC8vIHNldCBmbGFncyB0byBjcmVhdGUgc2NlbmUgcmVuZGVyZXJzXG4gICAgaWYob3B0cy5maWxsICYmICFzY2VuZS5maWxsMmQpIHNjZW5lLmZpbGwyZCA9IHRydWU7XG4gICAgaWYob3B0cy5tYXJrZXIgJiYgIXNjZW5lLnNjYXR0ZXIyZCkgc2NlbmUuc2NhdHRlcjJkID0gdHJ1ZTtcbiAgICBpZihvcHRzLmxpbmUgJiYgIXNjZW5lLmxpbmUyZCkgc2NlbmUubGluZTJkID0gdHJ1ZTtcbiAgICBpZigob3B0cy5lcnJvclggfHwgb3B0cy5lcnJvclkpICYmICFzY2VuZS5lcnJvcjJkKSBzY2VuZS5lcnJvcjJkID0gdHJ1ZTtcbiAgICBpZihvcHRzLnRleHQgJiYgIXNjZW5lLmdsVGV4dCkgc2NlbmUuZ2xUZXh0ID0gdHJ1ZTtcblxuICAgIC8vIEZJWE1FOiBvcmdhbml6ZSBpdCBpbiBhIG1vcmUgYXBwcm9wcmlhdGUgbWFubmVyLCBwcm9iYWJseSBpbiBzY2VuZU9wdGlvbnNcbiAgICAvLyBwdXQgcG9pbnQtY2x1c3RlciBpbnN0YW5jZSBmb3Igb3B0aW1pemVkIHJlZ2wgY2FsY1xuICAgIGlmKG9wdHMubWFya2VyICYmIGxlbiA+PSBUT09fTUFOWV9QT0lOVFMpIHtcbiAgICAgICAgb3B0cy5tYXJrZXIuY2x1c3RlciA9IHN0YXNoLnRyZWU7XG4gICAgfVxuXG4gICAgLy8gc2F2ZSBzY2VuZSBvcHRzIGJhdGNoXG4gICAgc2NlbmUubGluZU9wdGlvbnMucHVzaChvcHRzLmxpbmUpO1xuICAgIHNjZW5lLmVycm9yWE9wdGlvbnMucHVzaChvcHRzLmVycm9yWCk7XG4gICAgc2NlbmUuZXJyb3JZT3B0aW9ucy5wdXNoKG9wdHMuZXJyb3JZKTtcbiAgICBzY2VuZS5maWxsT3B0aW9ucy5wdXNoKG9wdHMuZmlsbCk7XG4gICAgc2NlbmUubWFya2VyT3B0aW9ucy5wdXNoKG9wdHMubWFya2VyKTtcbiAgICBzY2VuZS5tYXJrZXJTZWxlY3RlZE9wdGlvbnMucHVzaChvcHRzLm1hcmtlclNlbCk7XG4gICAgc2NlbmUubWFya2VyVW5zZWxlY3RlZE9wdGlvbnMucHVzaChvcHRzLm1hcmtlclVuc2VsKTtcbiAgICBzY2VuZS50ZXh0T3B0aW9ucy5wdXNoKG9wdHMudGV4dCk7XG4gICAgc2NlbmUudGV4dFNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMudGV4dFNlbCk7XG4gICAgc2NlbmUudGV4dFVuc2VsZWN0ZWRPcHRpb25zLnB1c2gob3B0cy50ZXh0VW5zZWwpO1xuXG4gICAgLy8gc3Rhc2ggc2NlbmUgcmVmXG4gICAgc3Rhc2guX3NjZW5lID0gc2NlbmU7XG4gICAgc3Rhc2guaW5kZXggPSBzY2VuZS5jb3VudDtcbiAgICBzdGFzaC54ID0geDtcbiAgICBzdGFzaC55ID0geTtcbiAgICBzdGFzaC5wb3NpdGlvbnMgPSBwb3NpdGlvbnM7XG4gICAgc2NlbmUuY291bnQrKztcblxuICAgIHJldHVybiBbe3g6IGZhbHNlLCB5OiBmYWxzZSwgdDogc3Rhc2gsIHRyYWNlOiB0cmFjZX1dO1xufVxuXG5mdW5jdGlvbiBleHBhbmRGb3JFcnJvckJhcnModHJhY2UsIGF4LCBvcHRzKSB7XG4gICAgdmFyIGV4dHJlbWVzID0gdHJhY2UuX2V4dHJlbWVzW2F4Ll9pZF07XG4gICAgdmFyIGVyckV4dCA9IGZpbmRFeHRyZW1lcyhheCwgb3B0cy5fYm5kcywge3BhZGRlZDogdHJ1ZX0pO1xuICAgIGV4dHJlbWVzLm1pbiA9IGV4dHJlbWVzLm1pbi5jb25jYXQoZXJyRXh0Lm1pbik7XG4gICAgZXh0cmVtZXMubWF4ID0gZXh0cmVtZXMubWF4LmNvbmNhdChlcnJFeHQubWF4KTtcbn1cblxuLy8gY3JlYXRlIHNjZW5lIG9wdGlvbnNcbmZ1bmN0aW9uIHNjZW5lT3B0aW9ucyhnZCwgc3VicGxvdCwgdHJhY2UsIHBvc2l0aW9ucywgeCwgeSkge1xuICAgIHZhciBvcHRzID0gY29udmVydC5zdHlsZShnZCwgdHJhY2UpO1xuXG4gICAgaWYob3B0cy5tYXJrZXIpIHtcbiAgICAgICAgb3B0cy5tYXJrZXIucG9zaXRpb25zID0gcG9zaXRpb25zO1xuICAgIH1cblxuICAgIGlmKG9wdHMubGluZSAmJiBwb3NpdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgIG9wdHMubGluZSxcbiAgICAgICAgICAgIGNvbnZlcnQubGluZVBvc2l0aW9ucyhnZCwgdHJhY2UsIHBvc2l0aW9ucylcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBpZihvcHRzLmVycm9yWCB8fCBvcHRzLmVycm9yWSkge1xuICAgICAgICB2YXIgZXJyb3JzID0gY29udmVydC5lcnJvckJhclBvc2l0aW9ucyhnZCwgdHJhY2UsIHBvc2l0aW9ucywgeCwgeSk7XG5cbiAgICAgICAgaWYob3B0cy5lcnJvclgpIHtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KG9wdHMuZXJyb3JYLCBlcnJvcnMueCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYob3B0cy5lcnJvclkpIHtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KG9wdHMuZXJyb3JZLCBlcnJvcnMueSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihvcHRzLnRleHQpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICBvcHRzLnRleHQsXG4gICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgY29udmVydC50ZXh0UG9zaXRpb24oZ2QsIHRyYWNlLCBvcHRzLnRleHQsIG9wdHMubWFya2VyKVxuICAgICAgICApO1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgIG9wdHMudGV4dFNlbCxcbiAgICAgICAgICAgIHtwb3NpdGlvbnM6IHBvc2l0aW9uc30sXG4gICAgICAgICAgICBjb252ZXJ0LnRleHRQb3NpdGlvbihnZCwgdHJhY2UsIG9wdHMudGV4dCwgb3B0cy5tYXJrZXJTZWwpXG4gICAgICAgICk7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KFxuICAgICAgICAgICAgb3B0cy50ZXh0VW5zZWwsXG4gICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgY29udmVydC50ZXh0UG9zaXRpb24oZ2QsIHRyYWNlLCBvcHRzLnRleHQsIG9wdHMubWFya2VyVW5zZWwpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHM7XG59XG5cblxuLy8gbWFrZSBzdXJlIHNjZW5lIGV4aXN0cyBvbiBzdWJwbG90LCByZXR1cm4gaXRcbmZ1bmN0aW9uIHNjZW5lVXBkYXRlKGdkLCBzdWJwbG90KSB7XG4gICAgdmFyIHNjZW5lID0gc3VicGxvdC5fc2NlbmU7XG5cbiAgICB2YXIgcmVzZXRPcHRzID0ge1xuICAgICAgICAvLyBudW1iZXIgb2YgdHJhY2VzIGluIHN1YnBsb3QsIHNpbmNlIHNjZW5lOnN1YnBsb3Qg4oaSIDE6MVxuICAgICAgICBjb3VudDogMCxcbiAgICAgICAgLy8gd2hldGhlciBzY2VuZSByZXF1aXJlcyBpbml0IGhvb2sgaW4gcGxvdCBjYWxsIChkaXJ0eSBwbG90IGNhbGwpXG4gICAgICAgIGRpcnR5OiB0cnVlLFxuICAgICAgICAvLyBsYXN0IHVzZWQgb3B0aW9uc1xuICAgICAgICBsaW5lT3B0aW9uczogW10sXG4gICAgICAgIGZpbGxPcHRpb25zOiBbXSxcbiAgICAgICAgbWFya2VyT3B0aW9uczogW10sXG4gICAgICAgIG1hcmtlclNlbGVjdGVkT3B0aW9uczogW10sXG4gICAgICAgIG1hcmtlclVuc2VsZWN0ZWRPcHRpb25zOiBbXSxcbiAgICAgICAgZXJyb3JYT3B0aW9uczogW10sXG4gICAgICAgIGVycm9yWU9wdGlvbnM6IFtdLFxuICAgICAgICB0ZXh0T3B0aW9uczogW10sXG4gICAgICAgIHRleHRTZWxlY3RlZE9wdGlvbnM6IFtdLFxuICAgICAgICB0ZXh0VW5zZWxlY3RlZE9wdGlvbnM6IFtdXG4gICAgfTtcblxuICAgIHZhciBpbml0T3B0cyA9IHtcbiAgICAgICAgc2VsZWN0QmF0Y2g6IG51bGwsXG4gICAgICAgIHVuc2VsZWN0QmF0Y2g6IG51bGwsXG4gICAgICAgIC8vIHJlZ2wtIGNvbXBvbmVudCBzdHVicywgaW5pdGlhbGl6ZWQgaW4gZGlydHkgcGxvdCBjYWxsXG4gICAgICAgIGZpbGwyZDogZmFsc2UsXG4gICAgICAgIHNjYXR0ZXIyZDogZmFsc2UsXG4gICAgICAgIGVycm9yMmQ6IGZhbHNlLFxuICAgICAgICBsaW5lMmQ6IGZhbHNlLFxuICAgICAgICBnbFRleHQ6IGZhbHNlLFxuICAgICAgICBzZWxlY3QyZDogbnVsbFxuICAgIH07XG5cbiAgICBpZighc3VicGxvdC5fc2NlbmUpIHtcbiAgICAgICAgc2NlbmUgPSBzdWJwbG90Ll9zY2VuZSA9IHt9O1xuXG4gICAgICAgIHNjZW5lLmluaXQgPSBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoc2NlbmUsIGluaXRPcHRzLCByZXNldE9wdHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNjZW5lLmluaXQoKTtcblxuICAgICAgICAvLyBhcHBseSBuZXcgb3B0aW9uIHRvIGFsbCByZWdsIGNvbXBvbmVudHMgKHVzZWQgb24gZHJhZylcbiAgICAgICAgc2NlbmUudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKG9wdCkge1xuICAgICAgICAgICAgdmFyIG9wdHMgPSBMaWIucmVwZWF0KG9wdCwgc2NlbmUuY291bnQpO1xuXG4gICAgICAgICAgICBpZihzY2VuZS5maWxsMmQpIHNjZW5lLmZpbGwyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQpIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5saW5lMmQpIHNjZW5lLmxpbmUyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5lcnJvcjJkKSBzY2VuZS5lcnJvcjJkLnVwZGF0ZShvcHRzLmNvbmNhdChvcHRzKSk7XG4gICAgICAgICAgICBpZihzY2VuZS5zZWxlY3QyZCkgc2NlbmUuc2VsZWN0MmQudXBkYXRlKG9wdHMpO1xuICAgICAgICAgICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lLmNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUuZ2xUZXh0W2ldLnVwZGF0ZShvcHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBkcmF3IHRyYWNlcyBpbiBwcm9wZXIgb3JkZXJcbiAgICAgICAgc2NlbmUuZHJhdyA9IGZ1bmN0aW9uIGRyYXcoKSB7XG4gICAgICAgICAgICB2YXIgY291bnQgPSBzY2VuZS5jb3VudDtcbiAgICAgICAgICAgIHZhciBmaWxsMmQgPSBzY2VuZS5maWxsMmQ7XG4gICAgICAgICAgICB2YXIgZXJyb3IyZCA9IHNjZW5lLmVycm9yMmQ7XG4gICAgICAgICAgICB2YXIgbGluZTJkID0gc2NlbmUubGluZTJkO1xuICAgICAgICAgICAgdmFyIHNjYXR0ZXIyZCA9IHNjZW5lLnNjYXR0ZXIyZDtcbiAgICAgICAgICAgIHZhciBnbFRleHQgPSBzY2VuZS5nbFRleHQ7XG4gICAgICAgICAgICB2YXIgc2VsZWN0MmQgPSBzY2VuZS5zZWxlY3QyZDtcbiAgICAgICAgICAgIHZhciBzZWxlY3RCYXRjaCA9IHNjZW5lLnNlbGVjdEJhdGNoO1xuICAgICAgICAgICAgdmFyIHVuc2VsZWN0QmF0Y2ggPSBzY2VuZS51bnNlbGVjdEJhdGNoO1xuXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGZpbGwyZCAmJiBzY2VuZS5maWxsT3JkZXJbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDJkLmRyYXcoc2NlbmUuZmlsbE9yZGVyW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYobGluZTJkICYmIHNjZW5lLmxpbmVPcHRpb25zW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUyZC5kcmF3KGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihlcnJvcjJkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNjZW5lLmVycm9yWE9wdGlvbnNbaV0pIGVycm9yMmQuZHJhdyhpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2NlbmUuZXJyb3JZT3B0aW9uc1tpXSkgZXJyb3IyZC5kcmF3KGkgKyBjb3VudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHNjYXR0ZXIyZCAmJiBzY2VuZS5tYXJrZXJPcHRpb25zW2ldICYmICghc2VsZWN0QmF0Y2ggfHwgIXNlbGVjdEJhdGNoW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICBzY2F0dGVyMmQuZHJhdyhpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoZ2xUZXh0W2ldICYmIHNjZW5lLnRleHRPcHRpb25zW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGdsVGV4dFtpXS5yZW5kZXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNjYXR0ZXIyZCAmJiBzZWxlY3QyZCAmJiBzZWxlY3RCYXRjaCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdDJkLmRyYXcoc2VsZWN0QmF0Y2gpO1xuICAgICAgICAgICAgICAgIHNjYXR0ZXIyZC5kcmF3KHVuc2VsZWN0QmF0Y2gpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzY2VuZS5kaXJ0eSA9IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHJlbW92ZSBzY2VuZSByZXNvdXJjZXNcbiAgICAgICAgc2NlbmUuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgICBpZihzY2VuZS5maWxsMmQgJiYgc2NlbmUuZmlsbDJkLmRlc3Ryb3kpIHNjZW5lLmZpbGwyZC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQgJiYgc2NlbmUuc2NhdHRlcjJkLmRlc3Ryb3kpIHNjZW5lLnNjYXR0ZXIyZC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZihzY2VuZS5lcnJvcjJkICYmIHNjZW5lLmVycm9yMmQuZGVzdHJveSkgc2NlbmUuZXJyb3IyZC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZihzY2VuZS5saW5lMmQgJiYgc2NlbmUubGluZTJkLmRlc3Ryb3kpIHNjZW5lLmxpbmUyZC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZihzY2VuZS5zZWxlY3QyZCAmJiBzY2VuZS5zZWxlY3QyZC5kZXN0cm95KSBzY2VuZS5zZWxlY3QyZC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZihzY2VuZS5nbFRleHQpIHtcbiAgICAgICAgICAgICAgICBzY2VuZS5nbFRleHQuZm9yRWFjaChmdW5jdGlvbih0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHRleHQuZGVzdHJveSkgdGV4dC5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNjZW5lLmxpbmVPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLmZpbGxPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLm1hcmtlck9wdGlvbnMgPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUubWFya2VyU2VsZWN0ZWRPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLm1hcmtlclVuc2VsZWN0ZWRPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLmVycm9yWE9wdGlvbnMgPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUuZXJyb3JZT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS50ZXh0T3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS50ZXh0U2VsZWN0ZWRPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnRleHRVbnNlbGVjdGVkT3B0aW9ucyA9IG51bGw7XG5cbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBudWxsO1xuXG4gICAgICAgICAgICAvLyB3ZSBjYW4ndCBqdXN0IGRlbGV0ZSBfc2NlbmUsIGJlY2F1c2UgYGRlc3Ryb3lgIGlzIGNhbGxlZCBpbiB0aGVcbiAgICAgICAgICAgIC8vIG1pZGRsZSBvZiBzdXBwbHlEZWZhdWx0cywgYmVmb3JlIHJlbGlua1ByaXZhdGVLZXlzIHdoaWNoIHdpbGwgcHV0IGl0IGJhY2suXG4gICAgICAgICAgICBzdWJwbG90Ll9zY2VuZSA9IG51bGw7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSW4gY2FzZSBpZiB3ZSBoYXZlIHNjZW5lIGZyb20gdGhlIGxhc3QgY2FsYyAtIHJlc2V0IGRhdGFcbiAgICBpZighc2NlbmUuZGlydHkpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoc2NlbmUsIHJlc2V0T3B0cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjZW5lO1xufVxuXG5mdW5jdGlvbiBnZXRWaWV3cG9ydChmdWxsTGF5b3V0LCB4YXhpcywgeWF4aXMpIHtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciB3aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGg7XG4gICAgdmFyIGhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuICAgIHJldHVybiBbXG4gICAgICAgIGdzLmwgKyB4YXhpcy5kb21haW5bMF0gKiBncy53LFxuICAgICAgICBncy5iICsgeWF4aXMuZG9tYWluWzBdICogZ3MuaCxcbiAgICAgICAgKHdpZHRoIC0gZ3MucikgLSAoMSAtIHhheGlzLmRvbWFpblsxXSkgKiBncy53LFxuICAgICAgICAoaGVpZ2h0IC0gZ3MudCkgLSAoMSAtIHlheGlzLmRvbWFpblsxXSkgKiBncy5oXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gcGxvdChnZCwgc3VicGxvdCwgY2RhdGEpIHtcbiAgICBpZighY2RhdGEubGVuZ3RoKSByZXR1cm47XG5cbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZSA9IHN1YnBsb3QuX3NjZW5lO1xuICAgIHZhciB4YXhpcyA9IHN1YnBsb3QueGF4aXM7XG4gICAgdmFyIHlheGlzID0gc3VicGxvdC55YXhpcztcbiAgICB2YXIgaSwgajtcblxuICAgIC8vIHdlIG1heSBoYXZlIG1vcmUgc3VicGxvdHMgdGhhbiBpbml0aWFsaXplZCBkYXRhIGR1ZSB0byBBeGVzLmdldFN1YnBsb3RzIG1ldGhvZFxuICAgIGlmKCFzY2VuZSkgcmV0dXJuO1xuXG4gICAgdmFyIHN1Y2Nlc3MgPSBwcmVwYXJlUmVnbChnZCwgWydBTkdMRV9pbnN0YW5jZWRfYXJyYXlzJywgJ09FU19lbGVtZW50X2luZGV4X3VpbnQnXSk7XG4gICAgaWYoIXN1Y2Nlc3MpIHtcbiAgICAgICAgc2NlbmUuaW5pdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHJlZ2wgPSBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5kYXRhKClbMF0ucmVnbDtcblxuICAgIC8vIHRoYXQgaXMgbmVlZGVkIGZvciBmaWxsc1xuICAgIGxpbmtUcmFjZXMoZ2QsIHN1YnBsb3QsIGNkYXRhKTtcblxuICAgIGlmKHNjZW5lLmRpcnR5KSB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSBzY2VuZXMgYXJlIGNyZWF0ZWRcbiAgICAgICAgaWYoc2NlbmUuZXJyb3IyZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUuZXJyb3IyZCA9IGNyZWF0ZUVycm9yKHJlZ2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmxpbmUyZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUubGluZTJkID0gY3JlYXRlTGluZShyZWdsKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHNjZW5lLnNjYXR0ZXIyZCA9IGNyZWF0ZVNjYXR0ZXIocmVnbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2NlbmUuZmlsbDJkID09PSB0cnVlKSB7XG4gICAgICAgICAgICBzY2VuZS5maWxsMmQgPSBjcmVhdGVMaW5lKHJlZ2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmdsVGV4dCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUuZ2xUZXh0ID0gbmV3IEFycmF5KHNjZW5lLmNvdW50KTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHNjZW5lLmNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBzY2VuZS5nbFRleHRbaV0gPSBuZXcgVGV4dChyZWdsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSBtYWluIG1hcmtlciBvcHRpb25zXG4gICAgICAgIGlmKHNjZW5lLmdsVGV4dCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2NlbmUuY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHNjZW5lLmdsVGV4dFtpXS51cGRhdGUoc2NlbmUudGV4dE9wdGlvbnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmxpbmUyZCkge1xuICAgICAgICAgICAgc2NlbmUubGluZTJkLnVwZGF0ZShzY2VuZS5saW5lT3B0aW9ucyk7XG4gICAgICAgICAgICBzY2VuZS5saW5lT3B0aW9ucyA9IHNjZW5lLmxpbmVPcHRpb25zLm1hcChmdW5jdGlvbihsaW5lT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmKGxpbmVPcHRpb25zICYmIGxpbmVPcHRpb25zLnBvc2l0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3JjUG9zID0gbGluZU9wdGlvbnMucG9zaXRpb25zO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBmaXJzdHB0ZGVmID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoZmlyc3RwdGRlZiA8IHNyY1Bvcy5sZW5ndGggJiYgKGlzTmFOKHNyY1Bvc1tmaXJzdHB0ZGVmXSkgfHwgaXNOYU4oc3JjUG9zW2ZpcnN0cHRkZWYgKyAxXSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaXJzdHB0ZGVmICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGxhc3RwdGRlZiA9IHNyY1Bvcy5sZW5ndGggLSAyO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShsYXN0cHRkZWYgPiBmaXJzdHB0ZGVmICYmIChpc05hTihzcmNQb3NbbGFzdHB0ZGVmXSkgfHwgaXNOYU4oc3JjUG9zW2xhc3RwdGRlZiArIDFdKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RwdGRlZiAtPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxpbmVPcHRpb25zLnBvc2l0aW9ucyA9IHNyY1Bvcy5zbGljZShmaXJzdHB0ZGVmLCBsYXN0cHRkZWYgKyAyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmVPcHRpb25zO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzY2VuZS5saW5lMmQudXBkYXRlKHNjZW5lLmxpbmVPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzY2VuZS5lcnJvcjJkKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3JCYXRjaCA9IChzY2VuZS5lcnJvclhPcHRpb25zIHx8IFtdKS5jb25jYXQoc2NlbmUuZXJyb3JZT3B0aW9ucyB8fCBbXSk7XG4gICAgICAgICAgICBzY2VuZS5lcnJvcjJkLnVwZGF0ZShlcnJvckJhdGNoKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQpIHtcbiAgICAgICAgICAgIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUoc2NlbmUubWFya2VyT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaWxsIHJlcXVpcmVzIGxpbmtlZCB0cmFjZXMsIHNvIHdlIGdlbmVyYXRlIGl0J3MgcG9zaXRpb25zIGhlcmVcbiAgICAgICAgc2NlbmUuZmlsbE9yZGVyID0gTGliLnJlcGVhdChudWxsLCBzY2VuZS5jb3VudCk7XG4gICAgICAgIGlmKHNjZW5lLmZpbGwyZCkge1xuICAgICAgICAgICAgc2NlbmUuZmlsbE9wdGlvbnMgPSBzY2VuZS5maWxsT3B0aW9ucy5tYXAoZnVuY3Rpb24oZmlsbE9wdGlvbnMsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2RzY2F0dGVyID0gY2RhdGFbaV07XG4gICAgICAgICAgICAgICAgaWYoIWZpbGxPcHRpb25zIHx8ICFjZHNjYXR0ZXIgfHwgIWNkc2NhdHRlclswXSB8fCAhY2RzY2F0dGVyWzBdLnRyYWNlKSByZXR1cm47XG4gICAgICAgICAgICAgICAgdmFyIGNkID0gY2RzY2F0dGVyWzBdO1xuICAgICAgICAgICAgICAgIHZhciB0cmFjZSA9IGNkLnRyYWNlO1xuICAgICAgICAgICAgICAgIHZhciBzdGFzaCA9IGNkLnQ7XG4gICAgICAgICAgICAgICAgdmFyIGxpbmVPcHRpb25zID0gc2NlbmUubGluZU9wdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgdmFyIGxhc3QsIGo7XG5cbiAgICAgICAgICAgICAgICB2YXIgZmlsbERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5fb3duZmlsbCkgZmlsbERhdGEucHVzaChpKTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5fbmV4dHRyYWNlKSBmaWxsRGF0YS5wdXNoKGkgKyAxKTtcbiAgICAgICAgICAgICAgICBpZihmaWxsRGF0YS5sZW5ndGgpIHNjZW5lLmZpbGxPcmRlcltpXSA9IGZpbGxEYXRhO1xuXG4gICAgICAgICAgICAgICAgdmFyIHBvcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzcmNQb3MgPSAobGluZU9wdGlvbnMgJiYgbGluZU9wdGlvbnMucG9zaXRpb25zKSB8fCBzdGFzaC5wb3NpdGlvbnM7XG4gICAgICAgICAgICAgICAgdmFyIGZpcnN0cHRkZWYsIGxhc3RwdGRlZjtcblxuICAgICAgICAgICAgICAgIGlmKHRyYWNlLmZpbGwgPT09ICd0b3plcm95Jykge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdHB0ZGVmID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoZmlyc3RwdGRlZiA8IHNyY1Bvcy5sZW5ndGggJiYgaXNOYU4oc3JjUG9zW2ZpcnN0cHRkZWYgKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0cHRkZWYgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsYXN0cHRkZWYgPSBzcmNQb3MubGVuZ3RoIC0gMjtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUobGFzdHB0ZGVmID4gZmlyc3RwdGRlZiAmJiBpc05hTihzcmNQb3NbbGFzdHB0ZGVmICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0cHRkZWYgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZihzcmNQb3NbZmlyc3RwdGRlZiArIDFdICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBbc3JjUG9zW2ZpcnN0cHRkZWZdLCAwXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwb3MgPSBwb3MuY29uY2F0KHNyY1Bvcy5zbGljZShmaXJzdHB0ZGVmLCBsYXN0cHRkZWYgKyAyKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNyY1Bvc1tsYXN0cHRkZWYgKyAxXSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChbc3JjUG9zW2xhc3RwdGRlZl0sIDBdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKHRyYWNlLmZpbGwgPT09ICd0b3plcm94Jykge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdHB0ZGVmID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoZmlyc3RwdGRlZiA8IHNyY1Bvcy5sZW5ndGggJiYgaXNOYU4oc3JjUG9zW2ZpcnN0cHRkZWZdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RwdGRlZiArPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxhc3RwdGRlZiA9IHNyY1Bvcy5sZW5ndGggLSAyO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShsYXN0cHRkZWYgPiBmaXJzdHB0ZGVmICYmIGlzTmFOKHNyY1Bvc1tsYXN0cHRkZWZdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdHB0ZGVmIC09IDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYoc3JjUG9zW2ZpcnN0cHRkZWZdICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBbMCwgc3JjUG9zW2ZpcnN0cHRkZWYgKyAxXV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChzcmNQb3Muc2xpY2UoZmlyc3RwdGRlZiwgbGFzdHB0ZGVmICsgMikpO1xuICAgICAgICAgICAgICAgICAgICBpZihzcmNQb3NbbGFzdHB0ZGVmXSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChbIDAsIHNyY1Bvc1tsYXN0cHRkZWYgKyAxXV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYodHJhY2UuZmlsbCA9PT0gJ3Rvc2VsZicgfHwgdHJhY2UuZmlsbCA9PT0gJ3RvbmV4dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zID0gW107XG4gICAgICAgICAgICAgICAgICAgIGxhc3QgPSAwO1xuICAgICAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBzcmNQb3MubGVuZ3RoOyBqICs9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTmFOKHNyY1Bvc1tqXSkgfHwgaXNOYU4oc3JjUG9zW2ogKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBwb3MuY29uY2F0KHNyY1Bvcy5zbGljZShsYXN0LCBqKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLnB1c2goc3JjUG9zW2xhc3RdLCBzcmNQb3NbbGFzdCArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0ID0gaiArIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChzcmNQb3Muc2xpY2UobGFzdCkpO1xuICAgICAgICAgICAgICAgICAgICBpZihsYXN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MucHVzaChzcmNQb3NbbGFzdF0sIHNyY1Bvc1tsYXN0ICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFRyYWNlID0gdHJhY2UuX25leHR0cmFjZTtcblxuICAgICAgICAgICAgICAgICAgICBpZihuZXh0VHJhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0T3B0aW9ucyA9IHNjZW5lLmxpbmVPcHRpb25zW2kgKyAxXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYobmV4dE9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFBvcyA9IG5leHRPcHRpb25zLnBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih0cmFjZS5maWxsID09PSAndG9uZXh0eScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gc3JjUG9zLnNsaWNlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGkgPSBNYXRoLmZsb29yKG5leHRQb3MubGVuZ3RoIC8gMik7IGktLTspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB4eCA9IG5leHRQb3NbaSAqIDJdLCB5eSA9IG5leHRQb3NbaSAqIDIgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTmFOKHh4KSB8fCBpc05hTih5eSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLnB1c2goeHgsIHl5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsT3B0aW9ucy5maWxsID0gbmV4dFRyYWNlLmZpbGxjb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBkZXRlY3QgcHJldiB0cmFjZSBwb3NpdGlvbnMgdG8gZXhjbHVkZSBmcm9tIGN1cnJlbnQgZmlsbFxuICAgICAgICAgICAgICAgIGlmKHRyYWNlLl9wcmV2dHJhY2UgJiYgdHJhY2UuX3ByZXZ0cmFjZS5maWxsID09PSAndG9uZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldkxpbmVQb3MgPSBzY2VuZS5saW5lT3B0aW9uc1tpIC0gMV0ucG9zaXRpb25zO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBsaWtlbHkgdGhpcyBsb2dpYyBzaG91bGQgYmUgdGVzdGVkIGJldHRlclxuICAgICAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gcG9zLmxlbmd0aCAvIDI7XG4gICAgICAgICAgICAgICAgICAgIGxhc3QgPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBob2xlID0gW2xhc3RdO1xuICAgICAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBwcmV2TGluZVBvcy5sZW5ndGg7IGogKz0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaXNOYU4ocHJldkxpbmVQb3Nbal0pIHx8IGlzTmFOKHByZXZMaW5lUG9zW2ogKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob2xlLnB1c2goaiAvIDIgKyBvZmZzZXQgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0ID0gaiArIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwb3MgPSBwb3MuY29uY2F0KHByZXZMaW5lUG9zKTtcbiAgICAgICAgICAgICAgICAgICAgZmlsbE9wdGlvbnMuaG9sZSA9IGhvbGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpbGxPcHRpb25zLmZpbGxtb2RlID0gdHJhY2UuZmlsbDtcbiAgICAgICAgICAgICAgICBmaWxsT3B0aW9ucy5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eTtcbiAgICAgICAgICAgICAgICBmaWxsT3B0aW9ucy5wb3NpdGlvbnMgPSBwb3M7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmlsbE9wdGlvbnM7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc2NlbmUuZmlsbDJkLnVwZGF0ZShzY2VuZS5maWxsT3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmb3JtIGJhdGNoIGFycmF5cywgYW5kIGNoZWNrIGZvciBzZWxlY3RlZCBwb2ludHNcbiAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IG51bGw7XG4gICAgc2NlbmUudW5zZWxlY3RCYXRjaCA9IG51bGw7XG4gICAgdmFyIGRyYWdtb2RlID0gZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICB2YXIgc2VsZWN0TW9kZSA9IGRyYWdtb2RlID09PSAnbGFzc28nIHx8IGRyYWdtb2RlID09PSAnc2VsZWN0JztcbiAgICB2YXIgY2xpY2tTZWxlY3RFbmFibGVkID0gZnVsbExheW91dC5jbGlja21vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZDAgPSBjZGF0YVtpXVswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgICAgICB2YXIgc3Rhc2ggPSBjZDAudDtcbiAgICAgICAgdmFyIGluZGV4ID0gc3Rhc2guaW5kZXg7XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgICAgICB2YXIgeCA9IHN0YXNoLng7XG4gICAgICAgIHZhciB5ID0gc3Rhc2gueTtcblxuICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cyB8fCBzZWxlY3RNb2RlIHx8IGNsaWNrU2VsZWN0RW5hYmxlZCkge1xuICAgICAgICAgICAgaWYoIXNlbGVjdE1vZGUpIHNlbGVjdE1vZGUgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZighc2NlbmUuc2VsZWN0QmF0Y2gpIHtcbiAgICAgICAgICAgICAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IFtdO1xuICAgICAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcmVnZW5lcmF0ZSBzY2VuZSBiYXRjaCwgaWYgdHJhY2VzIG51bWJlciBjaGFuZ2VkIGR1cmluZyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbFB0cyA9IHNjZW5lLnNlbGVjdEJhdGNoW2luZGV4XSA9IExpYi5zZWxJbmRpY2VzMnNlbFBvaW50cyh0cmFjZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgc2VsRGljdCA9IHt9O1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHNlbFB0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBzZWxEaWN0W3NlbFB0c1tqXV0gPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdW5zZWxQdHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpZighc2VsRGljdFtqXSkgdW5zZWxQdHMucHVzaChqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2NlbmUudW5zZWxlY3RCYXRjaFtpbmRleF0gPSB1bnNlbFB0cztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcHJlY2FsY3VsYXRlIHB4IGNvb3JkcyBzaW5jZSB3ZSBhcmUgbm90IGdvaW5nIHRvIHBhbiBkdXJpbmcgc2VsZWN0XG4gICAgICAgICAgICAvLyBUT0RPLCBjb3VsZCBkbyBiZXR0ZXIgaGVyZSBlLmcuXG4gICAgICAgICAgICAvLyAtIHNwaW4gdGhhdCBpbiBhIHdlYndvcmtlclxuICAgICAgICAgICAgLy8gLSBjb21wdXRlIHNlbGVjdGlvbiBmcm9tIHBvbHlnb25zIGluIGRhdGEgY29vcmRpbmF0ZXNcbiAgICAgICAgICAgIC8vICAgKG1heWJlIGp1c3QgZm9yIGxpbmVhciBheGVzKVxuICAgICAgICAgICAgdmFyIHhweCA9IHN0YXNoLnhweCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgdmFyIHlweCA9IHN0YXNoLnlweCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICB4cHhbal0gPSB4YXhpcy5jMnAoeFtqXSk7XG4gICAgICAgICAgICAgICAgeXB4W2pdID0geWF4aXMuYzJwKHlbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3Rhc2gueHB4ID0gc3Rhc2gueXB4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgaWYoc2VsZWN0TW9kZSkge1xuICAgICAgICAvLyBjcmVhdGUgc2VsZWN0MmRcbiAgICAgICAgaWYoIXNjZW5lLnNlbGVjdDJkKSB7XG4gICAgICAgICAgICAvLyBjcmVhdGUgc2NhdHRlciBpbnN0YW5jZSBieSBjbG9uaW5nIHNjYXR0ZXIyZFxuICAgICAgICAgICAgc2NlbmUuc2VsZWN0MmQgPSBjcmVhdGVTY2F0dGVyKGZ1bGxMYXlvdXQuX2dsY2FudmFzLmRhdGEoKVsxXS5yZWdsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNjZW5lLnNjYXR0ZXIyZCAmJiBzY2VuZS5zZWxlY3RCYXRjaCAmJiBzY2VuZS5zZWxlY3RCYXRjaC5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHVwZGF0ZSBvbmx5IHRyYWNlcyB3aXRoIHNlbGVjdGlvblxuICAgICAgICAgICAgc2NlbmUuc2NhdHRlcjJkLnVwZGF0ZShzY2VuZS5tYXJrZXJVbnNlbGVjdGVkT3B0aW9ucy5tYXAoZnVuY3Rpb24ob3B0cywgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzY2VuZS5zZWxlY3RCYXRjaFtpXSA/IG9wdHMgOiBudWxsO1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc2NlbmUuc2VsZWN0MmQpIHtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdDJkLnVwZGF0ZShzY2VuZS5tYXJrZXJPcHRpb25zKTtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdDJkLnVwZGF0ZShzY2VuZS5tYXJrZXJTZWxlY3RlZE9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgICAgICBjZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGNkc2NhdHRlcikge1xuICAgICAgICAgICAgICAgIGlmKGNkc2NhdHRlciAmJiBjZHNjYXR0ZXJbMF0gJiYgY2RzY2F0dGVyWzBdLnRyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlVGV4dFNlbGVjdGlvbihjZHNjYXR0ZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoc2NlbmUuc2NhdHRlcjJkKSB7XG4gICAgICAgICAgICAvLyByZXNldCBzY2F0dGVyMmQgb3B0cyB0byBiYXNlIG9wdHMsXG4gICAgICAgICAgICAvLyB0aHVzIHVuc2V0dGluZyBtYXJrZXJVbnNlbGVjdGVkT3B0aW9ucyBmcm9tIHNlbGVjdGlvblxuICAgICAgICAgICAgc2NlbmUuc2NhdHRlcjJkLnVwZGF0ZShzY2VuZS5tYXJrZXJPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHByb3ZpZGUgdmlld3BvcnQgYW5kIHJhbmdlXG4gICAgdmFyIHZwUmFuZ2UwID0ge1xuICAgICAgICB2aWV3cG9ydDogZ2V0Vmlld3BvcnQoZnVsbExheW91dCwgeGF4aXMsIHlheGlzKSxcbiAgICAgICAgLy8gVE9ETyBkbyB3ZSBuZWVkIHRob3NlIGZhbGxiYWNrcz9cbiAgICAgICAgcmFuZ2U6IFtcbiAgICAgICAgICAgICh4YXhpcy5fcmwgfHwgeGF4aXMucmFuZ2UpWzBdLFxuICAgICAgICAgICAgKHlheGlzLl9ybCB8fCB5YXhpcy5yYW5nZSlbMF0sXG4gICAgICAgICAgICAoeGF4aXMuX3JsIHx8IHhheGlzLnJhbmdlKVsxXSxcbiAgICAgICAgICAgICh5YXhpcy5fcmwgfHwgeWF4aXMucmFuZ2UpWzFdXG4gICAgICAgIF1cbiAgICB9O1xuICAgIHZhciB2cFJhbmdlID0gTGliLnJlcGVhdCh2cFJhbmdlMCwgc2NlbmUuY291bnQpO1xuXG4gICAgLy8gdXBsb2FkIHZpZXdwb3J0L3JhbmdlIGRhdGEgdG8gR1BVXG4gICAgaWYoc2NlbmUuZmlsbDJkKSB7XG4gICAgICAgIHNjZW5lLmZpbGwyZC51cGRhdGUodnBSYW5nZSk7XG4gICAgfVxuICAgIGlmKHNjZW5lLmxpbmUyZCkge1xuICAgICAgICBzY2VuZS5saW5lMmQudXBkYXRlKHZwUmFuZ2UpO1xuICAgIH1cbiAgICBpZihzY2VuZS5lcnJvcjJkKSB7XG4gICAgICAgIHNjZW5lLmVycm9yMmQudXBkYXRlKHZwUmFuZ2UuY29uY2F0KHZwUmFuZ2UpKTtcbiAgICB9XG4gICAgaWYoc2NlbmUuc2NhdHRlcjJkKSB7XG4gICAgICAgIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUodnBSYW5nZSk7XG4gICAgfVxuICAgIGlmKHNjZW5lLnNlbGVjdDJkKSB7XG4gICAgICAgIHNjZW5lLnNlbGVjdDJkLnVwZGF0ZSh2cFJhbmdlKTtcbiAgICB9XG4gICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgIHNjZW5lLmdsVGV4dC5mb3JFYWNoKGZ1bmN0aW9uKHRleHQpIHsgdGV4dC51cGRhdGUodnBSYW5nZTApOyB9KTtcbiAgICB9XG59XG5cblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHN0YXNoID0gY2RbMF0udDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB4ID0gc3Rhc2gueDtcbiAgICB2YXIgeSA9IHN0YXNoLnk7XG4gICAgdmFyIHhweCA9IHhhLmMycCh4dmFsKTtcbiAgICB2YXIgeXB4ID0geWEuYzJwKHl2YWwpO1xuICAgIHZhciBtYXhEaXN0YW5jZSA9IHBvaW50RGF0YS5kaXN0YW5jZTtcbiAgICB2YXIgaWRzO1xuXG4gICAgLy8gRklYTUU6IG1ha2Ugc3VyZSB0aGlzIGlzIGEgcHJvcGVyIHdheSB0byBjYWxjIHNlYXJjaCByYWRpdXNcbiAgICBpZihzdGFzaC50cmVlKSB7XG4gICAgICAgIHZhciB4bCA9IHhhLnAyYyh4cHggLSBtYXhEaXN0YW5jZSk7XG4gICAgICAgIHZhciB4ciA9IHhhLnAyYyh4cHggKyBtYXhEaXN0YW5jZSk7XG4gICAgICAgIHZhciB5bCA9IHlhLnAyYyh5cHggLSBtYXhEaXN0YW5jZSk7XG4gICAgICAgIHZhciB5ciA9IHlhLnAyYyh5cHggKyBtYXhEaXN0YW5jZSk7XG5cbiAgICAgICAgaWYoaG92ZXJtb2RlID09PSAneCcpIHtcbiAgICAgICAgICAgIGlkcyA9IHN0YXNoLnRyZWUucmFuZ2UoXG4gICAgICAgICAgICAgICAgTWF0aC5taW4oeGwsIHhyKSwgTWF0aC5taW4oeWEuX3JsWzBdLCB5YS5fcmxbMV0pLFxuICAgICAgICAgICAgICAgIE1hdGgubWF4KHhsLCB4ciksIE1hdGgubWF4KHlhLl9ybFswXSwgeWEuX3JsWzFdKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlkcyA9IHN0YXNoLnRyZWUucmFuZ2UoXG4gICAgICAgICAgICAgICAgTWF0aC5taW4oeGwsIHhyKSwgTWF0aC5taW4oeWwsIHlyKSxcbiAgICAgICAgICAgICAgICBNYXRoLm1heCh4bCwgeHIpLCBNYXRoLm1heCh5bCwgeXIpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYoc3Rhc2guaWRzKSB7XG4gICAgICAgIGlkcyA9IHN0YXNoLmlkcztcbiAgICB9XG4gICAgZWxzZSByZXR1cm4gW3BvaW50RGF0YV07XG5cbiAgICAvLyBwaWNrIHRoZSBpZCBjbG9zZXN0IHRvIHRoZSBwb2ludFxuICAgIC8vIG5vdGUgdGhhdCBwb2ludCBwb3NzaWJseSBtYXkgbm90IGJlIGZvdW5kXG4gICAgdmFyIGlkLCBwdHgsIHB0eSwgaSwgZHgsIGR5LCBkaXN0LCBkeHk7XG5cbiAgICB2YXIgbWluRGlzdCA9IG1heERpc3RhbmNlO1xuICAgIGlmKGhvdmVybW9kZSA9PT0gJ3gnKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcHR4ID0geFtpZHNbaV1dO1xuICAgICAgICAgICAgZHggPSBNYXRoLmFicyh4YS5jMnAocHR4KSAtIHhweCk7XG4gICAgICAgICAgICBpZihkeCA8IG1pbkRpc3QpIHtcbiAgICAgICAgICAgICAgICBtaW5EaXN0ID0gZHg7XG4gICAgICAgICAgICAgICAgZHkgPSB5YS5jMnAoeVtpZHNbaV1dKSAtIHlweDtcbiAgICAgICAgICAgICAgICBkeHkgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgICAgICAgICAgICAgIGlkID0gaWRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHB0eCA9IHhbaWRzW2ldXTtcbiAgICAgICAgICAgIHB0eSA9IHlbaWRzW2ldXTtcbiAgICAgICAgICAgIGR4ID0geGEuYzJwKHB0eCkgLSB4cHg7XG4gICAgICAgICAgICBkeSA9IHlhLmMycChwdHkpIC0geXB4O1xuXG4gICAgICAgICAgICBkaXN0ID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICAgICAgICAgIGlmKGRpc3QgPCBtaW5EaXN0KSB7XG4gICAgICAgICAgICAgICAgbWluRGlzdCA9IGR4eSA9IGRpc3Q7XG4gICAgICAgICAgICAgICAgaWQgPSBpZHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwb2ludERhdGEuaW5kZXggPSBpZDtcbiAgICBwb2ludERhdGEuZGlzdGFuY2UgPSBtaW5EaXN0O1xuICAgIHBvaW50RGF0YS5keHkgPSBkeHk7XG5cbiAgICBpZihpZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gW3BvaW50RGF0YV07XG5cbiAgICBjYWxjSG92ZXIocG9pbnREYXRhLCB4LCB5LCB0cmFjZSk7XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59XG5cblxuZnVuY3Rpb24gY2FsY0hvdmVyKHBvaW50RGF0YSwgeCwgeSwgdHJhY2UpIHtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciBtaW5EaXN0ID0gcG9pbnREYXRhLmRpc3RhbmNlO1xuICAgIHZhciBkeHkgPSBwb2ludERhdGEuZHh5O1xuICAgIHZhciBpZCA9IHBvaW50RGF0YS5pbmRleDtcblxuICAgIC8vIHRoZSBjbG9zZXN0IGRhdGEgcG9pbnRcbiAgICB2YXIgZGkgPSB7XG4gICAgICAgIHBvaW50TnVtYmVyOiBpZCxcbiAgICAgICAgeDogeFtpZF0sXG4gICAgICAgIHk6IHlbaWRdXG4gICAgfTtcblxuICAgIC8vIHRoYXQgaXMgc2luZ2xlLWl0ZW0gYXJyYXlzX3RvX2NhbGNkYXRhIGV4Y2VycHQsIHNpbmNlIHdlIGFyZSBkb2luZyBpdCBmb3IgYSBzaW5nbGUgcG9pbnQgYW5kIHdlIGRvbid0IGhhdmUgdG8gZG8gaXQgYmVmb3JlaGVhZCBmb3IgMWU2IHBvaW50c1xuICAgIGRpLnR4ID0gQXJyYXkuaXNBcnJheSh0cmFjZS50ZXh0KSA/IHRyYWNlLnRleHRbaWRdIDogdHJhY2UudGV4dDtcbiAgICBkaS5odHggPSBBcnJheS5pc0FycmF5KHRyYWNlLmhvdmVydGV4dCkgPyB0cmFjZS5ob3ZlcnRleHRbaWRdIDogdHJhY2UuaG92ZXJ0ZXh0O1xuICAgIGRpLmRhdGEgPSBBcnJheS5pc0FycmF5KHRyYWNlLmN1c3RvbWRhdGEpID8gdHJhY2UuY3VzdG9tZGF0YVtpZF0gOiB0cmFjZS5jdXN0b21kYXRhO1xuICAgIGRpLnRwID0gQXJyYXkuaXNBcnJheSh0cmFjZS50ZXh0cG9zaXRpb24pID8gdHJhY2UudGV4dHBvc2l0aW9uW2lkXSA6IHRyYWNlLnRleHRwb3NpdGlvbjtcblxuICAgIHZhciBmb250ID0gdHJhY2UudGV4dGZvbnQ7XG4gICAgaWYoZm9udCkge1xuICAgICAgICBkaS50cyA9IEFycmF5LmlzQXJyYXkoZm9udC5zaXplKSA/IGZvbnQuc2l6ZVtpZF0gOiBmb250LnNpemU7XG4gICAgICAgIGRpLnRjID0gQXJyYXkuaXNBcnJheShmb250LmNvbG9yKSA/IGZvbnQuY29sb3JbaWRdIDogZm9udC5jb2xvcjtcbiAgICAgICAgZGkudGYgPSBBcnJheS5pc0FycmF5KGZvbnQuZmFtaWx5KSA/IGZvbnQuZmFtaWx5W2lkXSA6IGZvbnQuZmFtaWx5O1xuICAgIH1cblxuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgaWYobWFya2VyKSB7XG4gICAgICAgIGRpLm1zID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLnNpemUpID8gbWFya2VyLnNpemVbaWRdIDogbWFya2VyLnNpemU7XG4gICAgICAgIGRpLm1vID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLm9wYWNpdHkpID8gbWFya2VyLm9wYWNpdHlbaWRdIDogbWFya2VyLm9wYWNpdHk7XG4gICAgICAgIGRpLm14ID0gQXJyYXkuaXNBcnJheShtYXJrZXIuc3ltYm9sKSA/IG1hcmtlci5zeW1ib2xbaWRdIDogbWFya2VyLnN5bWJvbDtcbiAgICAgICAgZGkubWMgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIuY29sb3IpID8gbWFya2VyLmNvbG9yW2lkXSA6IG1hcmtlci5jb2xvcjtcbiAgICB9XG5cbiAgICB2YXIgbGluZSA9IG1hcmtlciAmJiBtYXJrZXIubGluZTtcbiAgICBpZihsaW5lKSB7XG4gICAgICAgIGRpLm1sYyA9IEFycmF5LmlzQXJyYXkobGluZS5jb2xvcikgPyBsaW5lLmNvbG9yW2lkXSA6IGxpbmUuY29sb3I7XG4gICAgICAgIGRpLm1sdyA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGxpbmUud2lkdGgpID8gbGluZS53aWR0aFtpZF0gOiBsaW5lLndpZHRoO1xuICAgIH1cblxuICAgIHZhciBncmFkID0gbWFya2VyICYmIG1hcmtlci5ncmFkaWVudDtcbiAgICBpZihncmFkICYmIGdyYWQudHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGRpLm1ndCA9IEFycmF5LmlzQXJyYXkoZ3JhZC50eXBlKSA/IGdyYWQudHlwZVtpZF0gOiBncmFkLnR5cGU7XG4gICAgICAgIGRpLm1nYyA9IEFycmF5LmlzQXJyYXkoZ3JhZC5jb2xvcikgPyBncmFkLmNvbG9yW2lkXSA6IGdyYWQuY29sb3I7XG4gICAgfVxuXG4gICAgdmFyIHhwID0geGEuYzJwKGRpLngsIHRydWUpO1xuICAgIHZhciB5cCA9IHlhLmMycChkaS55LCB0cnVlKTtcbiAgICB2YXIgcmFkID0gZGkubXJjIHx8IDE7XG5cbiAgICB2YXIgaG92ZXJsYWJlbCA9IHRyYWNlLmhvdmVybGFiZWw7XG5cbiAgICBpZihob3ZlcmxhYmVsKSB7XG4gICAgICAgIGRpLmhiZyA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5iZ2NvbG9yKSA/IGhvdmVybGFiZWwuYmdjb2xvcltpZF0gOiBob3ZlcmxhYmVsLmJnY29sb3I7XG4gICAgICAgIGRpLmhiYyA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5ib3JkZXJjb2xvcikgPyBob3ZlcmxhYmVsLmJvcmRlcmNvbG9yW2lkXSA6IGhvdmVybGFiZWwuYm9yZGVyY29sb3I7XG4gICAgICAgIGRpLmh0cyA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5mb250LnNpemUpID8gaG92ZXJsYWJlbC5mb250LnNpemVbaWRdIDogaG92ZXJsYWJlbC5mb250LnNpemU7XG4gICAgICAgIGRpLmh0YyA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5mb250LmNvbG9yKSA/IGhvdmVybGFiZWwuZm9udC5jb2xvcltpZF0gOiBob3ZlcmxhYmVsLmZvbnQuY29sb3I7XG4gICAgICAgIGRpLmh0ZiA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5mb250LmZhbWlseSkgPyBob3ZlcmxhYmVsLmZvbnQuZmFtaWx5W2lkXSA6IGhvdmVybGFiZWwuZm9udC5mYW1pbHk7XG4gICAgICAgIGRpLmhubCA9IEFycmF5LmlzQXJyYXkoaG92ZXJsYWJlbC5uYW1lbGVuZ3RoKSA/IGhvdmVybGFiZWwubmFtZWxlbmd0aFtpZF0gOiBob3ZlcmxhYmVsLm5hbWVsZW5ndGg7XG4gICAgfVxuICAgIHZhciBob3ZlcmluZm8gPSB0cmFjZS5ob3ZlcmluZm87XG4gICAgaWYoaG92ZXJpbmZvKSB7XG4gICAgICAgIGRpLmhpID0gQXJyYXkuaXNBcnJheShob3ZlcmluZm8pID8gaG92ZXJpbmZvW2lkXSA6IGhvdmVyaW5mbztcbiAgICB9XG5cbiAgICB2YXIgZmFrZUNkID0ge307XG4gICAgZmFrZUNkW3BvaW50RGF0YS5pbmRleF0gPSBkaTtcblxuICAgIExpYi5leHRlbmRGbGF0KHBvaW50RGF0YSwge1xuICAgICAgICBjb2xvcjogZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpLFxuXG4gICAgICAgIHgwOiB4cCAtIHJhZCxcbiAgICAgICAgeDE6IHhwICsgcmFkLFxuICAgICAgICB4TGFiZWxWYWw6IGRpLngsXG5cbiAgICAgICAgeTA6IHlwIC0gcmFkLFxuICAgICAgICB5MTogeXAgKyByYWQsXG4gICAgICAgIHlMYWJlbFZhbDogZGkueSxcblxuICAgICAgICBjZDogZmFrZUNkLFxuICAgICAgICBkaXN0YW5jZTogbWluRGlzdCxcbiAgICAgICAgc3Bpa2VEaXN0YW5jZTogZHh5XG4gICAgfSk7XG5cbiAgICBpZihkaS5odHgpIHBvaW50RGF0YS50ZXh0ID0gZGkuaHR4O1xuICAgIGVsc2UgaWYoZGkudHgpIHBvaW50RGF0YS50ZXh0ID0gZGkudHg7XG4gICAgZWxzZSBpZih0cmFjZS50ZXh0KSBwb2ludERhdGEudGV4dCA9IHRyYWNlLnRleHQ7XG5cbiAgICBmaWxsSG92ZXJUZXh0KGRpLCB0cmFjZSwgcG9pbnREYXRhKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdob3ZlckluZm8nKShkaSwgdHJhY2UsIHBvaW50RGF0YSk7XG5cbiAgICByZXR1cm4gcG9pbnREYXRhO1xufVxuXG5cbmZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgc3Rhc2ggPSBjZFswXS50O1xuICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciB4ID0gc3Rhc2gueDtcbiAgICB2YXIgeSA9IHN0YXNoLnk7XG4gICAgdmFyIHNjZW5lID0gc3Rhc2guX3NjZW5lO1xuXG4gICAgaWYoIXNjZW5lKSByZXR1cm4gc2VsZWN0aW9uO1xuXG4gICAgdmFyIGhhc1RleHQgPSBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKTtcbiAgICB2YXIgaGFzTWFya2VycyA9IHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpO1xuICAgIHZhciBoYXNPbmx5TGluZXMgPSAhaGFzTWFya2VycyAmJiAhaGFzVGV4dDtcbiAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IGhhc09ubHlMaW5lcykgcmV0dXJuIHNlbGVjdGlvbjtcblxuICAgIC8vIGRlZ2VuZXJhdGUgcG9seWdvbiBkb2VzIG5vdCBlbmFibGUgc2VsZWN0aW9uXG4gICAgLy8gZmlsdGVyIG91dCBwb2ludHMgYnkgdmlzaWJsZSBzY2F0dGVyIG9uZXNcbiAgICB2YXIgZWxzID0gbnVsbDtcbiAgICB2YXIgdW5lbHMgPSBudWxsO1xuICAgIC8vIEZJWE1FOiBjbGVhcmluZyBzZWxlY3Rpb24gZG9lcyBub3Qgd29yayBoZXJlXG4gICAgdmFyIGk7XG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyICE9PSBmYWxzZSAmJiAhc2VsZWN0aW9uVGVzdGVyLmRlZ2VuZXJhdGUpIHtcbiAgICAgICAgZWxzID0gW10sIHVuZWxzID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3N0YXNoLnhweFtpXSwgc3Rhc2gueXB4W2ldXSwgZmFsc2UsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgZWxzLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgeDogeFtpXSxcbiAgICAgICAgICAgICAgICAgICAgeTogeVtpXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdW5lbHMucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuZWxzID0gYXJyYXlSYW5nZShsZW4pO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSBzZWxlY3RCYXRjaCBpcyBjcmVhdGVkXG4gICAgaWYoIXNjZW5lLnNlbGVjdEJhdGNoKSB7XG4gICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoID0gW107XG4gICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBbXTtcbiAgICB9XG5cbiAgICBpZighc2NlbmUuc2VsZWN0QmF0Y2hbc3Rhc2guaW5kZXhdKSB7XG4gICAgICAgIC8vIGVudGVyIGV2ZXJ5IHRyYWNlIHNlbGVjdCBtb2RlXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNjZW5lLmNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoW2ldID0gW107XG4gICAgICAgICAgICBzY2VuZS51bnNlbGVjdEJhdGNoW2ldID0gW107XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2Ugc2hvdWxkIHR1cm4gc2NhdHRlcjJkIGludG8gdW5zZWxlY3RlZCBvbmNlIHdlIGhhdmUgYW55IHBvaW50cyBzZWxlY3RlZFxuICAgICAgICBpZihoYXNNYXJrZXJzKSB7XG4gICAgICAgICAgICBzY2VuZS5zY2F0dGVyMmQudXBkYXRlKHNjZW5lLm1hcmtlclVuc2VsZWN0ZWRPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNjZW5lLnNlbGVjdEJhdGNoW3N0YXNoLmluZGV4XSA9IGVscztcbiAgICBzY2VuZS51bnNlbGVjdEJhdGNoW3N0YXNoLmluZGV4XSA9IHVuZWxzO1xuXG4gICAgLy8gdXBkYXRlIHRleHQgb3B0aW9uc1xuICAgIGlmKGhhc1RleHQpIHtcbiAgICAgICAgc3R5bGVUZXh0U2VsZWN0aW9uKGNkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufVxuXG5mdW5jdGlvbiBzdHlsZVRleHRTZWxlY3Rpb24oY2QpIHtcbiAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIHZhciBzdGFzaCA9IGNkMC50O1xuICAgIHZhciBzY2VuZSA9IHN0YXNoLl9zY2VuZTtcbiAgICB2YXIgaW5kZXggPSBzdGFzaC5pbmRleDtcbiAgICB2YXIgZWxzID0gc2NlbmUuc2VsZWN0QmF0Y2hbaW5kZXhdO1xuICAgIHZhciB1bmVscyA9IHNjZW5lLnVuc2VsZWN0QmF0Y2hbaW5kZXhdO1xuICAgIHZhciBiYXNlT3B0cyA9IHNjZW5lLnRleHRPcHRpb25zW2luZGV4XTtcbiAgICB2YXIgc2VsT3B0cyA9IHNjZW5lLnRleHRTZWxlY3RlZE9wdGlvbnNbaW5kZXhdIHx8IHt9O1xuICAgIHZhciB1bnNlbE9wdHMgPSBzY2VuZS50ZXh0VW5zZWxlY3RlZE9wdGlvbnNbaW5kZXhdIHx8IHt9O1xuICAgIHZhciBvcHRzID0gTGliLmV4dGVuZEZsYXQoe30sIGJhc2VPcHRzKTtcbiAgICB2YXIgaSwgajtcblxuICAgIGlmKGVscyAmJiB1bmVscykge1xuICAgICAgICB2YXIgc3RjID0gc2VsT3B0cy5jb2xvcjtcbiAgICAgICAgdmFyIHV0YyA9IHVuc2VsT3B0cy5jb2xvcjtcbiAgICAgICAgdmFyIGJhc2UgPSBiYXNlT3B0cy5jb2xvcjtcbiAgICAgICAgdmFyIGhhc0FycmF5QmFzZSA9IEFycmF5LmlzQXJyYXkoYmFzZSk7XG4gICAgICAgIG9wdHMuY29sb3IgPSBuZXcgQXJyYXkodHJhY2UuX2xlbmd0aCk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBqID0gZWxzW2ldO1xuICAgICAgICAgICAgb3B0cy5jb2xvcltqXSA9IHN0YyB8fCAoaGFzQXJyYXlCYXNlID8gYmFzZVtqXSA6IGJhc2UpO1xuICAgICAgICB9XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHVuZWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBqID0gdW5lbHNbaV07XG4gICAgICAgICAgICB2YXIgYmFzZWogPSBoYXNBcnJheUJhc2UgPyBiYXNlW2pdIDogYmFzZTtcbiAgICAgICAgICAgIG9wdHMuY29sb3Jbal0gPSB1dGMgPyB1dGMgOlxuICAgICAgICAgICAgICAgIHN0YyA/IGJhc2VqIDogQ29sb3IuYWRkT3BhY2l0eShiYXNlaiwgREVTRUxFQ1RESU0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2NlbmUuZ2xUZXh0W2luZGV4XS51cGRhdGUob3B0cyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3NjYXR0ZXJnbCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wnLCAncmVnbCcsICdjYXJ0ZXNpYW4nLCAnc3ltYm9scycsICdlcnJvckJhcnNPSycsICdzaG93TGVnZW5kJywgJ3NjYXR0ZXItbGlrZSddLFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY3Jvc3NfdHJhY2VfZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogcmVxdWlyZSgnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKSxcbiAgICBjYWxjOiBjYWxjLFxuICAgIHBsb3Q6IHBsb3QsXG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogc2VsZWN0UG9pbnRzLFxuXG4gICAgc2NlbmVVcGRhdGU6IHNjZW5lVXBkYXRlLFxuICAgIGNhbGNIb3ZlcjogY2FsY0hvdmVyLFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJHZW9BdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJnZW8vYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIG1hcGJveEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvbWFwYm94L2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yYmFyQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yYmFyL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIGxpbmVBdHRycyA9IHNjYXR0ZXJHZW9BdHRycy5saW5lO1xudmFyIG1hcmtlckF0dHJzID0gc2NhdHRlckdlb0F0dHJzLm1hcmtlcjtcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgbG9uOiBzY2F0dGVyR2VvQXR0cnMubG9uLFxuICAgIGxhdDogc2NhdHRlckdlb0F0dHJzLmxhdCxcblxuICAgIC8vIGxvY2F0aW9uc1xuICAgIC8vIGxvY2F0aW9ubW9kZVxuXG4gICAgbW9kZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLm1vZGUsIHtcbiAgICAgICAgZGZsdDogJ21hcmtlcnMnLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIHRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGhvdmVydGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IGxpbmVBdHRycy5jb2xvcixcbiAgICAgICAgd2lkdGg6IGxpbmVBdHRycy53aWR0aFxuXG4gICAgICAgIC8vIFRPRE9cbiAgICAgICAgLy8gZGFzaDogZGFzaFxuICAgIH0sXG5cbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckF0dHJzLmNvbm5lY3RnYXBzLFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnY2lyY2xlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiBtYXJrZXJBdHRycy5vcGFjaXR5LFxuICAgICAgICBzaXplOiBtYXJrZXJBdHRycy5zaXplLFxuICAgICAgICBzaXplcmVmOiBtYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBtYXJrZXJBdHRycy5zaXplbWluLFxuICAgICAgICBzaXplbW9kZTogbWFya2VyQXR0cnMuc2l6ZW1vZGUsXG4gICAgICAgIGNvbG9yOiBtYXJrZXJBdHRycy5jb2xvcixcbiAgICAgICAgY29sb3JzY2FsZTogbWFya2VyQXR0cnMuY29sb3JzY2FsZSxcbiAgICAgICAgY2F1dG86IG1hcmtlckF0dHJzLmNhdXRvLFxuICAgICAgICBjbWF4OiBtYXJrZXJBdHRycy5jbWF4LFxuICAgICAgICBjbWluOiBtYXJrZXJBdHRycy5jbWluLFxuICAgICAgICBhdXRvY29sb3JzY2FsZTogbWFya2VyQXR0cnMuYXV0b2NvbG9yc2NhbGUsXG4gICAgICAgIHJldmVyc2VzY2FsZTogbWFya2VyQXR0cnMucmV2ZXJzZXNjYWxlLFxuICAgICAgICBzaG93c2NhbGU6IG1hcmtlckF0dHJzLnNob3dzY2FsZSxcbiAgICAgICAgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnMsXG5cbiAgICAgICAgLy8gbGluZVxuICAgIH0sXG5cbiAgICBmaWxsOiBzY2F0dGVyR2VvQXR0cnMuZmlsbCxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG5cbiAgICB0ZXh0Zm9udDogbWFwYm94QXR0cnMubGF5ZXJzLnN5bWJvbC50ZXh0Zm9udCxcbiAgICB0ZXh0cG9zaXRpb246IG1hcGJveEF0dHJzLmxheWVycy5zeW1ib2wudGV4dHBvc2l0aW9uLFxuXG4gICAgc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQubWFya2VyXG4gICAgfSxcbiAgICB1bnNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQubWFya2VyXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydsb24nLCAnbGF0JywgJ3RleHQnLCAnbmFtZSddXG4gICAgfSlcbn0sICdjYWxjJywgJ25lc3RlZCcpO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG52YXIgZ2VvSnNvblV0aWxzID0gcmVxdWlyZSgnLi4vLi4vbGliL2dlb2pzb25fdXRpbHMnKTtcblxudmFyIENvbG9yc2NhbGUgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgbWFrZUJ1YmJsZVNpemVGbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFrZV9idWJibGVfc2l6ZV9mdW5jJyk7XG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgY29udmVydFRleHRPcHRzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvbWFwYm94L2NvbnZlcnRfdGV4dF9vcHRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICB2YXIgaXNWaXNpYmxlID0gKHRyYWNlLnZpc2libGUgPT09IHRydWUpO1xuICAgIHZhciBoYXNGaWxsID0gKHRyYWNlLmZpbGwgIT09ICdub25lJyk7XG4gICAgdmFyIGhhc0xpbmVzID0gc3ViVHlwZXMuaGFzTGluZXModHJhY2UpO1xuICAgIHZhciBoYXNNYXJrZXJzID0gc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSk7XG4gICAgdmFyIGhhc1RleHQgPSBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKTtcbiAgICB2YXIgaGFzQ2lyY2xlcyA9IChoYXNNYXJrZXJzICYmIHRyYWNlLm1hcmtlci5zeW1ib2wgPT09ICdjaXJjbGUnKTtcbiAgICB2YXIgaGFzU3ltYm9scyA9IChoYXNNYXJrZXJzICYmIHRyYWNlLm1hcmtlci5zeW1ib2wgIT09ICdjaXJjbGUnKTtcblxuICAgIHZhciBmaWxsID0gaW5pdENvbnRhaW5lcigpO1xuICAgIHZhciBsaW5lID0gaW5pdENvbnRhaW5lcigpO1xuICAgIHZhciBjaXJjbGUgPSBpbml0Q29udGFpbmVyKCk7XG4gICAgdmFyIHN5bWJvbCA9IGluaXRDb250YWluZXIoKTtcblxuICAgIHZhciBvcHRzID0ge1xuICAgICAgICBmaWxsOiBmaWxsLFxuICAgICAgICBsaW5lOiBsaW5lLFxuICAgICAgICBjaXJjbGU6IGNpcmNsZSxcbiAgICAgICAgc3ltYm9sOiBzeW1ib2xcbiAgICB9O1xuXG4gICAgLy8gZWFybHkgcmV0dXJuIGlmIG5vdCB2aXNpYmxlIG9yIHBsYWNlaG9sZGVyXG4gICAgaWYoIWlzVmlzaWJsZSkgcmV0dXJuIG9wdHM7XG5cbiAgICAvLyBmaWxsIGxheWVyIGFuZCBsaW5lIGxheWVyIHVzZSB0aGUgc2FtZSBjb29yZHNcbiAgICB2YXIgbGluZUNvb3JkcztcbiAgICBpZihoYXNGaWxsIHx8IGhhc0xpbmVzKSB7XG4gICAgICAgIGxpbmVDb29yZHMgPSBnZW9Kc29uVXRpbHMuY2FsY1RyYWNlVG9MaW5lQ29vcmRzKGNhbGNUcmFjZSk7XG4gICAgfVxuXG4gICAgaWYoaGFzRmlsbCkge1xuICAgICAgICBmaWxsLmdlb2pzb24gPSBnZW9Kc29uVXRpbHMubWFrZVBvbHlnb24obGluZUNvb3Jkcyk7XG4gICAgICAgIGZpbGwubGF5b3V0LnZpc2liaWxpdHkgPSAndmlzaWJsZSc7XG5cbiAgICAgICAgTGliLmV4dGVuZEZsYXQoZmlsbC5wYWludCwge1xuICAgICAgICAgICAgJ2ZpbGwtY29sb3InOiB0cmFjZS5maWxsY29sb3JcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYoaGFzTGluZXMpIHtcbiAgICAgICAgbGluZS5nZW9qc29uID0gZ2VvSnNvblV0aWxzLm1ha2VMaW5lKGxpbmVDb29yZHMpO1xuICAgICAgICBsaW5lLmxheW91dC52aXNpYmlsaXR5ID0gJ3Zpc2libGUnO1xuXG4gICAgICAgIExpYi5leHRlbmRGbGF0KGxpbmUucGFpbnQsIHtcbiAgICAgICAgICAgICdsaW5lLXdpZHRoJzogdHJhY2UubGluZS53aWR0aCxcbiAgICAgICAgICAgICdsaW5lLWNvbG9yJzogdHJhY2UubGluZS5jb2xvcixcbiAgICAgICAgICAgICdsaW5lLW9wYWNpdHknOiB0cmFjZS5vcGFjaXR5XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRPRE8gY29udmVydCBsaW5lLmRhc2ggaW50byBsaW5lLWRhc2hhcnJheVxuICAgIH1cblxuICAgIGlmKGhhc0NpcmNsZXMpIHtcbiAgICAgICAgdmFyIGNpcmNsZU9wdHMgPSBtYWtlQ2lyY2xlT3B0cyhjYWxjVHJhY2UpO1xuICAgICAgICBjaXJjbGUuZ2VvanNvbiA9IGNpcmNsZU9wdHMuZ2VvanNvbjtcbiAgICAgICAgY2lyY2xlLmxheW91dC52aXNpYmlsaXR5ID0gJ3Zpc2libGUnO1xuXG4gICAgICAgIExpYi5leHRlbmRGbGF0KGNpcmNsZS5wYWludCwge1xuICAgICAgICAgICAgJ2NpcmNsZS1jb2xvcic6IGNpcmNsZU9wdHMubWNjLFxuICAgICAgICAgICAgJ2NpcmNsZS1yYWRpdXMnOiBjaXJjbGVPcHRzLm1yYyxcbiAgICAgICAgICAgICdjaXJjbGUtb3BhY2l0eSc6IGNpcmNsZU9wdHMubW9cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYoaGFzU3ltYm9scyB8fCBoYXNUZXh0KSB7XG4gICAgICAgIHN5bWJvbC5nZW9qc29uID0gbWFrZVN5bWJvbEdlb0pTT04oY2FsY1RyYWNlKTtcblxuICAgICAgICBMaWIuZXh0ZW5kRmxhdChzeW1ib2wubGF5b3V0LCB7XG4gICAgICAgICAgICB2aXNpYmlsaXR5OiAndmlzaWJsZScsXG4gICAgICAgICAgICAnaWNvbi1pbWFnZSc6ICd7c3ltYm9sfS0xNScsXG4gICAgICAgICAgICAndGV4dC1maWVsZCc6ICd7dGV4dH0nXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGhhc1N5bWJvbHMpIHtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHN5bWJvbC5sYXlvdXQsIHtcbiAgICAgICAgICAgICAgICAnaWNvbi1zaXplJzogdHJhY2UubWFya2VyLnNpemUgLyAxMFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHN5bWJvbC5wYWludCwge1xuICAgICAgICAgICAgICAgICdpY29uLW9wYWNpdHknOiB0cmFjZS5vcGFjaXR5ICogdHJhY2UubWFya2VyLm9wYWNpdHksXG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIGRvZXMgbm90IHdvcmsgPz9cbiAgICAgICAgICAgICAgICAnaWNvbi1jb2xvcic6IHRyYWNlLm1hcmtlci5jb2xvclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNUZXh0KSB7XG4gICAgICAgICAgICB2YXIgaWNvblNpemUgPSAodHJhY2UubWFya2VyIHx8IHt9KS5zaXplLFxuICAgICAgICAgICAgICAgIHRleHRPcHRzID0gY29udmVydFRleHRPcHRzKHRyYWNlLnRleHRwb3NpdGlvbiwgaWNvblNpemUpO1xuXG4gICAgICAgICAgICAvLyBhbGwgZGF0YS1kcml2ZW4gYmVsb3cgISFcblxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoc3ltYm9sLmxheW91dCwge1xuICAgICAgICAgICAgICAgICd0ZXh0LXNpemUnOiB0cmFjZS50ZXh0Zm9udC5zaXplLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IHRleHRPcHRzLmFuY2hvcixcbiAgICAgICAgICAgICAgICAndGV4dC1vZmZzZXQnOiB0ZXh0T3B0cy5vZmZzZXRcblxuICAgICAgICAgICAgICAgIC8vIFRPRE8gZm9udCBmYW1pbHlcbiAgICAgICAgICAgICAgICAvLyAndGV4dC1mb250Jzogc3ltYm9sLnRleHRmb250LmZhbWlseS5zcGxpdCgnLCAnKSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChzeW1ib2wucGFpbnQsIHtcbiAgICAgICAgICAgICAgICAndGV4dC1jb2xvcic6IHRyYWNlLnRleHRmb250LmNvbG9yLFxuICAgICAgICAgICAgICAgICd0ZXh0LW9wYWNpdHknOiB0cmFjZS5vcGFjaXR5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvcHRzO1xufTtcblxuZnVuY3Rpb24gaW5pdENvbnRhaW5lcigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBnZW9qc29uOiBnZW9Kc29uVXRpbHMubWFrZUJsYW5rKCksXG4gICAgICAgIGxheW91dDogeyB2aXNpYmlsaXR5OiAnbm9uZScgfSxcbiAgICAgICAgcGFpbnQ6IHt9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUNpcmNsZU9wdHMoY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIHNlbGVjdGVkcG9pbnRzID0gdHJhY2Uuc2VsZWN0ZWRwb2ludHM7XG4gICAgdmFyIGFycmF5Q29sb3IgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIuY29sb3IpO1xuICAgIHZhciBhcnJheVNpemUgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIuc2l6ZSk7XG4gICAgdmFyIGFycmF5T3BhY2l0eSA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5vcGFjaXR5KTtcbiAgICB2YXIgaTtcblxuICAgIGZ1bmN0aW9uIGFkZFRyYWNlT3BhY2l0eShvKSB7IHJldHVybiB0cmFjZS5vcGFjaXR5ICogbzsgfVxuXG4gICAgZnVuY3Rpb24gc2l6ZTJyYWRpdXMocykgeyByZXR1cm4gcyAvIDI7IH1cblxuICAgIHZhciBjb2xvckZuO1xuICAgIGlmKGFycmF5Q29sb3IpIHtcbiAgICAgICAgaWYoQ29sb3JzY2FsZS5oYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyJykpIHtcbiAgICAgICAgICAgIGNvbG9yRm4gPSBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuYyhcbiAgICAgICAgICAgICAgICAgQ29sb3JzY2FsZS5leHRyYWN0U2NhbGUobWFya2VyLmNvbG9yc2NhbGUsIG1hcmtlci5jbWluLCBtYXJrZXIuY21heClcbiAgICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29sb3JGbiA9IExpYi5pZGVudGl0eTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzaXplRm47XG4gICAgaWYoYXJyYXlTaXplKSB7XG4gICAgICAgIHNpemVGbiA9IG1ha2VCdWJibGVTaXplRm4odHJhY2UpO1xuICAgIH1cblxuICAgIHZhciBvcGFjaXR5Rm47XG4gICAgaWYoYXJyYXlPcGFjaXR5KSB7XG4gICAgICAgIG9wYWNpdHlGbiA9IGZ1bmN0aW9uKG1vKSB7XG4gICAgICAgICAgICB2YXIgbW8yID0gaXNOdW1lcmljKG1vKSA/ICtMaWIuY29uc3RyYWluKG1vLCAwLCAxKSA6IDA7XG4gICAgICAgICAgICByZXR1cm4gYWRkVHJhY2VPcGFjaXR5KG1vMik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGZlYXR1cmVzID0gW107XG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV07XG4gICAgICAgIHZhciBsb25sYXQgPSBjYWxjUHQubG9ubGF0O1xuXG4gICAgICAgIGlmKGlzQkFETlVNKGxvbmxhdCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBwcm9wcyA9IHt9O1xuICAgICAgICBpZihjb2xvckZuKSBwcm9wcy5tY2MgPSBjYWxjUHQubWNjID0gY29sb3JGbihjYWxjUHQubWMpO1xuICAgICAgICBpZihzaXplRm4pIHByb3BzLm1yYyA9IGNhbGNQdC5tcmMgPSBzaXplRm4oY2FsY1B0Lm1zKTtcbiAgICAgICAgaWYob3BhY2l0eUZuKSBwcm9wcy5tbyA9IG9wYWNpdHlGbihjYWxjUHQubW8pO1xuICAgICAgICBpZihzZWxlY3RlZHBvaW50cykgcHJvcHMuc2VsZWN0ZWQgPSBjYWxjUHQuc2VsZWN0ZWQgfHwgMDtcblxuICAgICAgICBmZWF0dXJlcy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6ICdGZWF0dXJlJyxcbiAgICAgICAgICAgIGdlb21ldHJ5OiB7dHlwZTogJ1BvaW50JywgY29vcmRpbmF0ZXM6IGxvbmxhdH0sXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgZm5zO1xuICAgIGlmKHNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgIGZucyA9IERyYXdpbmcubWFrZVNlbGVjdGVkUG9pbnRTdHlsZUZucyh0cmFjZSk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkID0gZmVhdHVyZXNbaV0ucHJvcGVydGllcztcblxuICAgICAgICAgICAgaWYoZm5zLnNlbGVjdGVkT3BhY2l0eUZuKSB7XG4gICAgICAgICAgICAgICAgZC5tbyA9IGFkZFRyYWNlT3BhY2l0eShmbnMuc2VsZWN0ZWRPcGFjaXR5Rm4oZCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZm5zLnNlbGVjdGVkQ29sb3JGbikge1xuICAgICAgICAgICAgICAgIGQubWNjID0gZm5zLnNlbGVjdGVkQ29sb3JGbihkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGZucy5zZWxlY3RlZFNpemVGbikge1xuICAgICAgICAgICAgICAgIGQubXJjID0gZm5zLnNlbGVjdGVkU2l6ZUZuKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2VvanNvbjoge3R5cGU6ICdGZWF0dXJlQ29sbGVjdGlvbicsIGZlYXR1cmVzOiBmZWF0dXJlc30sXG4gICAgICAgIG1jYzogYXJyYXlDb2xvciB8fCAoZm5zICYmIGZucy5zZWxlY3RlZENvbG9yRm4pID9cbiAgICAgICAgICAgIHt0eXBlOiAnaWRlbnRpdHknLCBwcm9wZXJ0eTogJ21jYyd9IDpcbiAgICAgICAgICAgIG1hcmtlci5jb2xvcixcbiAgICAgICAgbXJjOiBhcnJheVNpemUgfHwgKGZucyAmJiBmbnMuc2VsZWN0ZWRTaXplRm4pID9cbiAgICAgICAgICAgIHt0eXBlOiAnaWRlbnRpdHknLCBwcm9wZXJ0eTogJ21yYyd9IDpcbiAgICAgICAgICAgIHNpemUycmFkaXVzKG1hcmtlci5zaXplKSxcbiAgICAgICAgbW86IGFycmF5T3BhY2l0eSB8fCAoZm5zICYmIGZucy5zZWxlY3RlZE9wYWNpdHlGbikgP1xuICAgICAgICAgICAge3R5cGU6ICdpZGVudGl0eScsIHByb3BlcnR5OiAnbW8nfSA6XG4gICAgICAgICAgICBhZGRUcmFjZU9wYWNpdHkobWFya2VyLm9wYWNpdHkpXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZVN5bWJvbEdlb0pTT04oY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlciB8fCB7fSxcbiAgICAgICAgc3ltYm9sID0gbWFya2VyLnN5bWJvbCxcbiAgICAgICAgdGV4dCA9IHRyYWNlLnRleHQ7XG5cbiAgICB2YXIgZmlsbFN5bWJvbCA9IChzeW1ib2wgIT09ICdjaXJjbGUnKSA/XG4gICAgICAgICAgICBnZXRGaWxsRnVuYyhzeW1ib2wpIDpcbiAgICAgICAgICAgIGJsYW5rRmlsbEZ1bmM7XG5cbiAgICB2YXIgZmlsbFRleHQgPSBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSA/XG4gICAgICAgICAgICBnZXRGaWxsRnVuYyh0ZXh0KSA6XG4gICAgICAgICAgICBibGFua0ZpbGxGdW5jO1xuXG4gICAgdmFyIGZlYXR1cmVzID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV07XG5cbiAgICAgICAgaWYoaXNCQUROVU0oY2FsY1B0LmxvbmxhdCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGZlYXR1cmVzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogJ0ZlYXR1cmUnLFxuICAgICAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjYWxjUHQubG9ubGF0XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHN5bWJvbDogZmlsbFN5bWJvbChjYWxjUHQubXgpLFxuICAgICAgICAgICAgICAgIHRleHQ6IGZpbGxUZXh0KGNhbGNQdC50eClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcbiAgICAgICAgZmVhdHVyZXM6IGZlYXR1cmVzXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0RmlsbEZ1bmMoYXR0cikge1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGF0dHIpKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7IHJldHVybiB2OyB9O1xuICAgIH1cbiAgICBlbHNlIGlmKGF0dHIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyByZXR1cm4gYXR0cjsgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBibGFua0ZpbGxGdW5jO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gYmxhbmtGaWxsRnVuYygpIHsgcmV0dXJuICcnOyB9XG5cbi8vIG9ubHkgbmVlZCB0byBjaGVjayBsb24gKE9SIGxhdClcbmZ1bmN0aW9uIGlzQkFETlVNKGxvbmxhdCkge1xuICAgIHJldHVybiBsb25sYXRbMF0gPT09IEJBRE5VTTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVMb25MYXREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdtb2RlJyk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlLCB7bm9EYXNoOiB0cnVlfSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge25vTGluZTogdHJ1ZX0pO1xuXG4gICAgICAgIC8vIGFycmF5IG1hcmtlci5zaXplIGFuZCBtYXJrZXIuY29sb3IgYXJlIG9ubHkgc3VwcG9ydGVkIHdpdGggY2lyY2xlc1xuICAgICAgICB2YXIgbWFya2VyID0gdHJhY2VPdXQubWFya2VyO1xuICAgICAgICBpZihtYXJrZXIuc3ltYm9sICE9PSAnY2lyY2xlJykge1xuICAgICAgICAgICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLnNpemUpKSBtYXJrZXIuc2l6ZSA9IG1hcmtlci5zaXplWzBdO1xuICAgICAgICAgICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLmNvbG9yKSkgbWFya2VyLmNvbG9yID0gbWFya2VyLmNvbG9yWzBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge25vU2VsZWN0OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsJyk7XG4gICAgaWYodHJhY2VPdXQuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVMb25MYXREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKSB7XG4gICAgdmFyIGxvbiA9IGNvZXJjZSgnbG9uJykgfHwgW107XG4gICAgdmFyIGxhdCA9IGNvZXJjZSgnbGF0JykgfHwgW107XG4gICAgdmFyIGxlbiA9IE1hdGgubWluKGxvbi5sZW5ndGgsIGxhdC5sZW5ndGgpO1xuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG5cbiAgICByZXR1cm4gbGVuO1xufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBldmVudERhdGEob3V0LCBwdCkge1xuICAgIG91dC5sb24gPSBwdC5sb247XG4gICAgb3V0LmxhdCA9IHB0LmxhdDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBGeCA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBnZXRUcmFjZUNvbG9yID0gcmVxdWlyZSgnLi4vc2NhdHRlci9nZXRfdHJhY2VfY29sb3InKTtcbnZhciBmaWxsSG92ZXJUZXh0ID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsX2hvdmVyX3RleHQnKTtcbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciBzdWJwbG90ID0gcG9pbnREYXRhLnN1YnBsb3Q7XG5cbiAgICAvLyBjb21wdXRlIHdpbmRpbmcgbnVtYmVyIGFib3V0IFstMTgwLCAxODBdIGdsb2JlXG4gICAgdmFyIHdpbmRpbmcgPSAoeHZhbCA+PSAwKSA/XG4gICAgICAgIE1hdGguZmxvb3IoKHh2YWwgKyAxODApIC8gMzYwKSA6XG4gICAgICAgIE1hdGguY2VpbCgoeHZhbCAtIDE4MCkgLyAzNjApO1xuXG4gICAgLy8gc2hpZnQgbG9uZ2l0dWRlIHRvIFstMTgwLCAxODBdIHRvIGRldGVybWluZSBjbG9zZXN0IHBvaW50XG4gICAgdmFyIGxvblNoaWZ0ID0gd2luZGluZyAqIDM2MDtcbiAgICB2YXIgeHZhbDIgPSB4dmFsIC0gbG9uU2hpZnQ7XG5cbiAgICBmdW5jdGlvbiBkaXN0Rm4oZCkge1xuICAgICAgICB2YXIgbG9ubGF0ID0gZC5sb25sYXQ7XG4gICAgICAgIGlmKGxvbmxhdFswXSA9PT0gQkFETlVNKSByZXR1cm4gSW5maW5pdHk7XG5cbiAgICAgICAgdmFyIGxvbiA9IExpYi5tb2RIYWxmKGxvbmxhdFswXSwgMzYwKTtcbiAgICAgICAgdmFyIGxhdCA9IGxvbmxhdFsxXTtcbiAgICAgICAgdmFyIHB0ID0gc3VicGxvdC5wcm9qZWN0KFtsb24sIGxhdF0pO1xuICAgICAgICB2YXIgZHggPSBwdC54IC0geGEuYzJwKFt4dmFsMiwgbGF0XSk7XG4gICAgICAgIHZhciBkeSA9IHB0LnkgLSB5YS5jMnAoW2xvbiwgeXZhbF0pO1xuICAgICAgICB2YXIgcmFkID0gTWF0aC5tYXgoMywgZC5tcmMgfHwgMCk7XG5cbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSkgLSByYWQsIDEgLSAzIC8gcmFkKTtcbiAgICB9XG5cbiAgICBGeC5nZXRDbG9zZXN0KGNkLCBkaXN0Rm4sIHBvaW50RGF0YSk7XG5cbiAgICAvLyBza2lwIHRoZSByZXN0IChmb3IgdGhpcyB0cmFjZSkgaWYgd2UgZGlkbid0IGZpbmQgYSBjbG9zZSBwb2ludFxuICAgIGlmKHBvaW50RGF0YS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIHZhciBkaSA9IGNkW3BvaW50RGF0YS5pbmRleF07XG4gICAgdmFyIGxvbmxhdCA9IGRpLmxvbmxhdDtcbiAgICB2YXIgbG9ubGF0U2hpZnRlZCA9IFtMaWIubW9kSGFsZihsb25sYXRbMF0sIDM2MCkgKyBsb25TaGlmdCwgbG9ubGF0WzFdXTtcblxuICAgIC8vIHNoaWZ0IGxhYmVscyBiYWNrIHRvIG9yaWdpbmFsIHdpbmRlZCBnbG9iZVxuICAgIHZhciB4YyA9IHhhLmMycChsb25sYXRTaGlmdGVkKTtcbiAgICB2YXIgeWMgPSB5YS5jMnAobG9ubGF0U2hpZnRlZCk7XG4gICAgdmFyIHJhZCA9IGRpLm1yYyB8fCAxO1xuXG4gICAgcG9pbnREYXRhLngwID0geGMgLSByYWQ7XG4gICAgcG9pbnREYXRhLngxID0geGMgKyByYWQ7XG4gICAgcG9pbnREYXRhLnkwID0geWMgLSByYWQ7XG4gICAgcG9pbnREYXRhLnkxID0geWMgKyByYWQ7XG5cbiAgICBwb2ludERhdGEuY29sb3IgPSBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSk7XG4gICAgcG9pbnREYXRhLmV4dHJhVGV4dCA9IGdldEV4dHJhVGV4dCh0cmFjZSwgZGksIGNkWzBdLnQubGFiZWxzKTtcblxuICAgIHJldHVybiBbcG9pbnREYXRhXTtcbn07XG5cbmZ1bmN0aW9uIGdldEV4dHJhVGV4dCh0cmFjZSwgZGksIGxhYmVscykge1xuICAgIHZhciBob3ZlcmluZm8gPSBkaS5oaSB8fCB0cmFjZS5ob3ZlcmluZm87XG4gICAgdmFyIHBhcnRzID0gaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgdmFyIGlzQWxsID0gcGFydHMuaW5kZXhPZignYWxsJykgIT09IC0xO1xuICAgIHZhciBoYXNMb24gPSBwYXJ0cy5pbmRleE9mKCdsb24nKSAhPT0gLTE7XG4gICAgdmFyIGhhc0xhdCA9IHBhcnRzLmluZGV4T2YoJ2xhdCcpICE9PSAtMTtcbiAgICB2YXIgbG9ubGF0ID0gZGkubG9ubGF0O1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICAvLyBUT0RPIHNob3VsZCB3ZSB1c2UgYSBtb2NrIGF4aXMgdG8gZm9ybWF0IGhvdmVyP1xuICAgIC8vIElmIHNvLCB3ZSdsbCBuZWVkIHRvIG1ha2UgcHJlY2lzaW9uIGJlIHpvb20tbGV2ZWwgZGVwZW5kZW50XG4gICAgZnVuY3Rpb24gZm9ybWF0KHYpIHtcbiAgICAgICAgcmV0dXJuIHYgKyAnXFx1MDBCMCc7XG4gICAgfVxuXG4gICAgaWYoaXNBbGwgfHwgKGhhc0xvbiAmJiBoYXNMYXQpKSB7XG4gICAgICAgIHRleHQucHVzaCgnKCcgKyBmb3JtYXQobG9ubGF0WzBdKSArICcsICcgKyBmb3JtYXQobG9ubGF0WzFdKSArICcpJyk7XG4gICAgfSBlbHNlIGlmKGhhc0xvbikge1xuICAgICAgICB0ZXh0LnB1c2gobGFiZWxzLmxvbiArIGZvcm1hdChsb25sYXRbMF0pKTtcbiAgICB9IGVsc2UgaWYoaGFzTGF0KSB7XG4gICAgICAgIHRleHQucHVzaChsYWJlbHMubGF0ICsgZm9ybWF0KGxvbmxhdFsxXSkpO1xuICAgIH1cblxuICAgIGlmKGlzQWxsIHx8IHBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpIHtcbiAgICAgICAgZmlsbEhvdmVyVGV4dChkaSwgdHJhY2UsIHRleHQpO1xuICAgIH1cblxuICAgIHJldHVybiB0ZXh0LmpvaW4oJzxicj4nKTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgU2NhdHRlck1hcGJveCA9IHt9O1xuXG5TY2F0dGVyTWFwYm94LmF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblNjYXR0ZXJNYXBib3guc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5TY2F0dGVyTWFwYm94LmNvbG9yYmFyID0gcmVxdWlyZSgnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKTtcblNjYXR0ZXJNYXBib3guY2FsYyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJnZW8vY2FsYycpO1xuU2NhdHRlck1hcGJveC5wbG90ID0gcmVxdWlyZSgnLi9wbG90Jyk7XG5TY2F0dGVyTWFwYm94LmhvdmVyUG9pbnRzID0gcmVxdWlyZSgnLi9ob3ZlcicpO1xuU2NhdHRlck1hcGJveC5ldmVudERhdGEgPSByZXF1aXJlKCcuL2V2ZW50X2RhdGEnKTtcblNjYXR0ZXJNYXBib3guc2VsZWN0UG9pbnRzID0gcmVxdWlyZSgnLi9zZWxlY3QnKTtcblxuU2NhdHRlck1hcGJveC5zdHlsZSA9IGZ1bmN0aW9uKF8sIGNkKSB7XG4gICAgaWYoY2QpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgIHRyYWNlLl9nbFRyYWNlLnVwZGF0ZShjZCk7XG4gICAgfVxufTtcblxuU2NhdHRlck1hcGJveC5tb2R1bGVUeXBlID0gJ3RyYWNlJztcblNjYXR0ZXJNYXBib3gubmFtZSA9ICdzY2F0dGVybWFwYm94JztcblNjYXR0ZXJNYXBib3guYmFzZVBsb3RNb2R1bGUgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9tYXBib3gnKTtcblNjYXR0ZXJNYXBib3guY2F0ZWdvcmllcyA9IFsnbWFwYm94JywgJ2dsJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdzY2F0dGVybGlrZSddO1xuU2NhdHRlck1hcGJveC5tZXRhID0ge1xuICAgIFxuICAgIFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTY2F0dGVyTWFwYm94O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xuXG5mdW5jdGlvbiBTY2F0dGVyTWFwYm94KHN1YnBsb3QsIHVpZCkge1xuICAgIHRoaXMuc3VicGxvdCA9IHN1YnBsb3Q7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG5cbiAgICB0aGlzLnNvdXJjZUlkcyA9IHtcbiAgICAgICAgZmlsbDogdWlkICsgJy1zb3VyY2UtZmlsbCcsXG4gICAgICAgIGxpbmU6IHVpZCArICctc291cmNlLWxpbmUnLFxuICAgICAgICBjaXJjbGU6IHVpZCArICctc291cmNlLWNpcmNsZScsXG4gICAgICAgIHN5bWJvbDogdWlkICsgJy1zb3VyY2Utc3ltYm9sJ1xuICAgIH07XG5cbiAgICB0aGlzLmxheWVySWRzID0ge1xuICAgICAgICBmaWxsOiB1aWQgKyAnLWxheWVyLWZpbGwnLFxuICAgICAgICBsaW5lOiB1aWQgKyAnLWxheWVyLWxpbmUnLFxuICAgICAgICBjaXJjbGU6IHVpZCArICctbGF5ZXItY2lyY2xlJyxcbiAgICAgICAgc3ltYm9sOiB1aWQgKyAnLWxheWVyLXN5bWJvbCdcbiAgICB9O1xuXG4gICAgdGhpcy5vcmRlciA9IFsnZmlsbCcsICdsaW5lJywgJ2NpcmNsZScsICdzeW1ib2wnXTtcblxuICAgIC8vIFdlIGNvdWxkIG1lcmdlIHRoZSAnZmlsbCcgc291cmNlIHdpdGggdGhlICdsaW5lJyBzb3VyY2UgYW5kXG4gICAgLy8gdGhlICdjaXJjbGUnIHNvdXJjZSB3aXRoIHRoZSAnc3ltYm9sJyBzb3VyY2UgaWYgZXZlciBoYXZpbmdcbiAgICAvLyBmb3IgdXAtdG8gNCBzb3VyY2VzIHBlciAnc2NhdHRlcm1hcGJveCcgdHJhY2VzIGJlY29tZXMgYSBwcm9ibGVtLlxufVxuXG52YXIgcHJvdG8gPSBTY2F0dGVyTWFwYm94LnByb3RvdHlwZTtcblxucHJvdG8uYWRkU291cmNlID0gZnVuY3Rpb24oaywgb3B0cykge1xuICAgIHRoaXMuc3VicGxvdC5tYXAuYWRkU291cmNlKHRoaXMuc291cmNlSWRzW2tdLCB7XG4gICAgICAgIHR5cGU6ICdnZW9qc29uJyxcbiAgICAgICAgZGF0YTogb3B0cy5nZW9qc29uXG4gICAgfSk7XG59O1xuXG5wcm90by5zZXRTb3VyY2VEYXRhID0gZnVuY3Rpb24oaywgb3B0cykge1xuICAgIHRoaXMuc3VicGxvdC5tYXBcbiAgICAgICAgLmdldFNvdXJjZSh0aGlzLnNvdXJjZUlkc1trXSlcbiAgICAgICAgLnNldERhdGEob3B0cy5nZW9qc29uKTtcbn07XG5cbnByb3RvLmFkZExheWVyID0gZnVuY3Rpb24oaywgb3B0cykge1xuICAgIHRoaXMuc3VicGxvdC5tYXAuYWRkTGF5ZXIoe1xuICAgICAgICB0eXBlOiBrLFxuICAgICAgICBpZDogdGhpcy5sYXllcklkc1trXSxcbiAgICAgICAgc291cmNlOiB0aGlzLnNvdXJjZUlkc1trXSxcbiAgICAgICAgbGF5b3V0OiBvcHRzLmxheW91dCxcbiAgICAgICAgcGFpbnQ6IG9wdHMucGFpbnRcbiAgICB9KTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShjYWxjVHJhY2UpIHtcbiAgICB2YXIgc3VicGxvdCA9IHRoaXMuc3VicGxvdDtcbiAgICB2YXIgb3B0c0FsbCA9IGNvbnZlcnQoY2FsY1RyYWNlKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzLm9yZGVyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrID0gdGhpcy5vcmRlcltpXTtcbiAgICAgICAgdmFyIG9wdHMgPSBvcHRzQWxsW2tdO1xuXG4gICAgICAgIHN1YnBsb3Quc2V0T3B0aW9ucyh0aGlzLmxheWVySWRzW2tdLCAnc2V0TGF5b3V0UHJvcGVydHknLCBvcHRzLmxheW91dCk7XG5cbiAgICAgICAgaWYob3B0cy5sYXlvdXQudmlzaWJpbGl0eSA9PT0gJ3Zpc2libGUnKSB7XG4gICAgICAgICAgICB0aGlzLnNldFNvdXJjZURhdGEoaywgb3B0cyk7XG4gICAgICAgICAgICBzdWJwbG90LnNldE9wdGlvbnModGhpcy5sYXllcklkc1trXSwgJ3NldFBhaW50UHJvcGVydHknLCBvcHRzLnBhaW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGxpbmsgcmVmIGZvciBxdWljayB1cGRhdGUgZHVyaW5nIHNlbGVjdGlvbnNcbiAgICBjYWxjVHJhY2VbMF0udHJhY2UuX2dsVHJhY2UgPSB0aGlzO1xufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgdmFyIG1hcCA9IHRoaXMuc3VicGxvdC5tYXA7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5vcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgayA9IHRoaXMub3JkZXJbaV07XG4gICAgICAgIG1hcC5yZW1vdmVMYXllcih0aGlzLmxheWVySWRzW2tdKTtcbiAgICAgICAgbWFwLnJlbW92ZVNvdXJjZSh0aGlzLnNvdXJjZUlkc1trXSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVTY2F0dGVyTWFwYm94KHN1YnBsb3QsIGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICB2YXIgc2NhdHRlck1hcGJveCA9IG5ldyBTY2F0dGVyTWFwYm94KHN1YnBsb3QsIHRyYWNlLnVpZCk7XG4gICAgdmFyIG9wdHNBbGwgPSBjb252ZXJ0KGNhbGNUcmFjZSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2NhdHRlck1hcGJveC5vcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgayA9IHNjYXR0ZXJNYXBib3gub3JkZXJbaV07XG4gICAgICAgIHZhciBvcHRzID0gb3B0c0FsbFtrXTtcblxuICAgICAgICBzY2F0dGVyTWFwYm94LmFkZFNvdXJjZShrLCBvcHRzKTtcbiAgICAgICAgc2NhdHRlck1hcGJveC5hZGRMYXllcihrLCBvcHRzKTtcbiAgICB9XG5cbiAgICAvLyBsaW5rIHJlZiBmb3IgcXVpY2sgdXBkYXRlIGR1cmluZyBzZWxlY3Rpb25zXG4gICAgY2FsY1RyYWNlWzBdLnRyYWNlLl9nbFRyYWNlID0gc2NhdHRlck1hcGJveDtcblxuICAgIHJldHVybiBzY2F0dGVyTWFwYm94O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIHN1YnR5cGVzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHhhID0gc2VhcmNoSW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBzZWFyY2hJbmZvLnlheGlzO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgaTtcblxuICAgIGlmKCFzdWJ0eXBlcy5oYXNNYXJrZXJzKHRyYWNlKSkgcmV0dXJuIFtdO1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuICAgICAgICAgICAgdmFyIGxvbmxhdCA9IGRpLmxvbmxhdDtcblxuICAgICAgICAgICAgaWYobG9ubGF0WzBdICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICB2YXIgbG9ubGF0MiA9IFtMaWIubW9kSGFsZihsb25sYXRbMF0sIDM2MCksIGxvbmxhdFsxXV07XG4gICAgICAgICAgICAgICAgdmFyIHh5ID0gW3hhLmMycChsb25sYXQyKSwgeWEuYzJwKGxvbmxhdDIpXTtcblxuICAgICAgICAgICAgICAgIGlmKHNlbGVjdGlvblRlc3Rlci5jb250YWlucyh4eSwgbnVsbCwgaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnROdW1iZXI6IGksXG4gICAgICAgICAgICAgICAgICAgICAgICBsb246IGxvbmxhdFswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhdDogbG9ubGF0WzFdXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBsaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kZTogc2NhdHRlckF0dHJzLm1vZGUsXG5cbiAgICByOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRoZXRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHIwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkcjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0aGV0YTA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGR0aGV0YToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0aGV0YXVuaXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsncmFkaWFucycsICdkZWdyZWVzJywgJ2dyYWRpYW5zJ10sXG4gICAgICAgIGRmbHQ6ICdkZWdyZWVzJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0OiBzY2F0dGVyQXR0cnMudGV4dCxcbiAgICBob3ZlcnRleHQ6IHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBsaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBsaW5lQXR0cnMud2lkdGgsXG4gICAgICAgIGRhc2g6IGxpbmVBdHRycy5kYXNoLFxuICAgICAgICBzaGFwZTogZXh0ZW5kRmxhdCh7fSwgbGluZUF0dHJzLnNoYXBlLCB7XG4gICAgICAgICAgICB2YWx1ZXM6IFsnbGluZWFyJywgJ3NwbGluZSddXG4gICAgICAgIH0pLFxuICAgICAgICBzbW9vdGhpbmc6IGxpbmVBdHRycy5zbW9vdGhpbmcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGNvbm5lY3RnYXBzOiBzY2F0dGVyQXR0cnMuY29ubmVjdGdhcHMsXG5cbiAgICBtYXJrZXI6IHNjYXR0ZXJBdHRycy5tYXJrZXIsXG4gICAgY2xpcG9uYXhpczogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmNsaXBvbmF4aXMsIHtkZmx0OiBmYWxzZX0pLFxuXG4gICAgdGV4dHBvc2l0aW9uOiBzY2F0dGVyQXR0cnMudGV4dHBvc2l0aW9uLFxuICAgIHRleHRmb250OiBzY2F0dGVyQXR0cnMudGV4dGZvbnQsXG5cbiAgICBmaWxsOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuZmlsbCwge1xuICAgICAgICB2YWx1ZXM6IFsnbm9uZScsICd0b3NlbGYnLCAndG9uZXh0J10sXG4gICAgICAgIGRmbHQ6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyQXR0cnMuZmlsbGNvbG9yLFxuXG4gICAgLy8gVE9ETyBlcnJvciBiYXJzXG4gICAgLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzI2NTk3NDg3LzQwNjg0OTJcbiAgICAvLyBlcnJvcl94IChlcnJvcl9yLCBlcnJvcl90aGV0YSlcbiAgICAvLyBlcnJvcl95XG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsncicsICd0aGV0YScsICd0ZXh0JywgJ25hbWUnXVxuICAgIH0pLFxuICAgIGhvdmVyb246IHNjYXR0ZXJBdHRycy5ob3Zlcm9uLFxuXG4gICAgc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZCxcbiAgICB1bnNlbGVjdGVkOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZFxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBjYWxjQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcbnZhciBjYWxjTWFya2VyU2l6ZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNNYXJrZXJTaXplO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkID0gdHJhY2Uuc3VicGxvdDtcbiAgICB2YXIgcmFkaWFsQXhpcyA9IGZ1bGxMYXlvdXRbc3VicGxvdElkXS5yYWRpYWxheGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IGZ1bGxMYXlvdXRbc3VicGxvdElkXS5hbmd1bGFyYXhpcztcbiAgICB2YXIgckFycmF5ID0gcmFkaWFsQXhpcy5tYWtlQ2FsY2RhdGEodHJhY2UsICdyJyk7XG4gICAgdmFyIHRoZXRhQXJyYXkgPSBhbmd1bGFyQXhpcy5tYWtlQ2FsY2RhdGEodHJhY2UsICd0aGV0YScpO1xuICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBjZCA9IG5ldyBBcnJheShsZW4pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciByID0gckFycmF5W2ldO1xuICAgICAgICB2YXIgdGhldGEgPSB0aGV0YUFycmF5W2ldO1xuICAgICAgICB2YXIgY2RpID0gY2RbaV0gPSB7fTtcblxuICAgICAgICBpZihpc051bWVyaWMocikgJiYgaXNOdW1lcmljKHRoZXRhKSkge1xuICAgICAgICAgICAgY2RpLnIgPSByO1xuICAgICAgICAgICAgY2RpLnRoZXRhID0gdGhldGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjZGkuciA9IEJBRE5VTTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBwcGFkID0gY2FsY01hcmtlclNpemUodHJhY2UsIGxlbik7XG4gICAgdHJhY2UuX2V4dHJlbWVzLnggPSBBeGVzLmZpbmRFeHRyZW1lcyhyYWRpYWxBeGlzLCByQXJyYXksIHtwcGFkOiBwcGFkfSk7XG5cbiAgICBjYWxjQ29sb3JzY2FsZSh0cmFjZSk7XG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZU1hcmtlckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9tYXJrZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGluZV9zaGFwZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcbnZhciBQVFNfTElORVNPTkxZID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb25zdGFudHMnKS5QVFNfTElORVNPTkxZO1xuXG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5mdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVJUaGV0YURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RoZXRhdW5pdCcpO1xuICAgIGNvZXJjZSgnbW9kZScsIGxlbiA8IFBUU19MSU5FU09OTFkgPyAnbGluZXMrbWFya2VycycgOiAnbGluZXMnKTtcbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtncmFkaWVudDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIHZhciBkZmx0SG92ZXJPbiA9IFtdO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkgfHwgc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgY29lcmNlKCdjbGlwb25heGlzJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLm1heGRpc3BsYXllZCcpO1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdwb2ludHMnKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2ZpbGwnKTtcblxuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgICAgICBpZighc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZih0cmFjZU91dC5maWxsID09PSAndG9uZXh0JyB8fCB0cmFjZU91dC5maWxsID09PSAndG9zZWxmJykge1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdmaWxscycpO1xuICAgIH1cbiAgICBjb2VyY2UoJ2hvdmVyb24nLCBkZmx0SG92ZXJPbi5qb2luKCcrJykgfHwgJ3BvaW50cycpO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVJUaGV0YURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSkge1xuICAgIHZhciByID0gY29lcmNlKCdyJyk7XG4gICAgdmFyIHRoZXRhID0gY29lcmNlKCd0aGV0YScpO1xuICAgIHZhciBsZW47XG5cbiAgICBpZihyKSB7XG4gICAgICAgIGlmKHRoZXRhKSB7XG4gICAgICAgICAgICBsZW4gPSBNYXRoLm1pbihyLmxlbmd0aCwgdGhldGEubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlbiA9IHIubGVuZ3RoO1xuICAgICAgICAgICAgY29lcmNlKCd0aGV0YTAnKTtcbiAgICAgICAgICAgIGNvZXJjZSgnZHRoZXRhJyk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZighdGhldGEpIHJldHVybiAwO1xuICAgICAgICBsZW4gPSB0cmFjZU91dC50aGV0YS5sZW5ndGg7XG4gICAgICAgIGNvZXJjZSgncjAnKTtcbiAgICAgICAgY29lcmNlKCdkcicpO1xuICAgIH1cblxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG4gICAgcmV0dXJuIGxlbjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaGFuZGxlUlRoZXRhRGVmYXVsdHM6IGhhbmRsZVJUaGV0YURlZmF1bHRzLFxuICAgIHN1cHBseURlZmF1bHRzOiBzdXBwbHlEZWZhdWx0c1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJIb3ZlciA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvaG92ZXInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgc2NhdHRlclBvaW50RGF0YSA9IHNjYXR0ZXJIb3Zlcihwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG4gICAgaWYoIXNjYXR0ZXJQb2ludERhdGEgfHwgc2NhdHRlclBvaW50RGF0YVswXS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIHZhciBuZXdQb2ludERhdGEgPSBzY2F0dGVyUG9pbnREYXRhWzBdO1xuXG4gICAgLy8gaG92ZXJpbmcgb24gZmlsbCBjYXNlXG4gICAgaWYobmV3UG9pbnREYXRhLmluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHNjYXR0ZXJQb2ludERhdGE7XG4gICAgfVxuXG4gICAgdmFyIHN1YnBsb3QgPSBwb2ludERhdGEuc3VicGxvdDtcbiAgICB2YXIgY2RpID0gbmV3UG9pbnREYXRhLmNkW25ld1BvaW50RGF0YS5pbmRleF07XG4gICAgdmFyIHRyYWNlID0gbmV3UG9pbnREYXRhLnRyYWNlO1xuXG4gICAgaWYoIXN1YnBsb3QuaXNQdEluc2lkZShjZGkpKSByZXR1cm47XG5cbiAgICBuZXdQb2ludERhdGEueExhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIG5ld1BvaW50RGF0YS55TGFiZWxWYWwgPSB1bmRlZmluZWQ7XG4gICAgbWFrZUhvdmVyUG9pbnRUZXh0KGNkaSwgdHJhY2UsIHN1YnBsb3QsIG5ld1BvaW50RGF0YSk7XG5cbiAgICByZXR1cm4gc2NhdHRlclBvaW50RGF0YTtcbn1cblxuZnVuY3Rpb24gbWFrZUhvdmVyUG9pbnRUZXh0KGNkaSwgdHJhY2UsIHN1YnBsb3QsIHBvaW50RGF0YSkge1xuICAgIHZhciByYWRpYWxBeGlzID0gc3VicGxvdC5yYWRpYWxBeGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IHN1YnBsb3QuYW5ndWxhckF4aXM7XG4gICAgdmFyIGhvdmVyaW5mbyA9IGNkaS5oaSB8fCB0cmFjZS5ob3ZlcmluZm87XG4gICAgdmFyIHBhcnRzID0gaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgdmFyIHRleHQgPSBbXTtcblxuICAgIHJhZGlhbEF4aXMuX2hvdmVydGl0bGUgPSAncic7XG4gICAgYW5ndWxhckF4aXMuX2hvdmVydGl0bGUgPSAnzrgnO1xuXG4gICAgZnVuY3Rpb24gdGV4dFBhcnQoYXgsIHZhbCkge1xuICAgICAgICB0ZXh0LnB1c2goYXguX2hvdmVydGl0bGUgKyAnOiAnICsgQXhlcy50aWNrVGV4dChheCwgdmFsLCAnaG92ZXInKS50ZXh0KTtcbiAgICB9XG5cbiAgICBpZihwYXJ0cy5pbmRleE9mKCdhbGwnKSAhPT0gLTEpIHBhcnRzID0gWydyJywgJ3RoZXRhJywgJ3RleHQnXTtcbiAgICBpZihwYXJ0cy5pbmRleE9mKCdyJykgIT09IC0xKSB7XG4gICAgICAgIHRleHRQYXJ0KHJhZGlhbEF4aXMsIHJhZGlhbEF4aXMuYzJsKGNkaS5yKSk7XG4gICAgfVxuICAgIGlmKHBhcnRzLmluZGV4T2YoJ3RoZXRhJykgIT09IC0xKSB7XG4gICAgICAgIHZhciB0aGV0YSA9IGNkaS50aGV0YTtcbiAgICAgICAgdGV4dFBhcnQoXG4gICAgICAgICAgICBhbmd1bGFyQXhpcyxcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzLnRoZXRhdW5pdCA9PT0gJ2RlZ3JlZXMnID8gTGliLnJhZDJkZWcodGhldGEpIDogdGhldGFcbiAgICAgICAgKTtcbiAgICB9XG4gICAgaWYocGFydHMuaW5kZXhPZigndGV4dCcpICE9PSAtMSAmJiBwb2ludERhdGEudGV4dCkge1xuICAgICAgICB0ZXh0LnB1c2gocG9pbnREYXRhLnRleHQpO1xuICAgICAgICBkZWxldGUgcG9pbnREYXRhLnRleHQ7XG4gICAgfVxuXG4gICAgcG9pbnREYXRhLmV4dHJhVGV4dCA9IHRleHQuam9pbignPGJyPicpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBob3ZlclBvaW50czogaG92ZXJQb2ludHMsXG4gICAgbWFrZUhvdmVyUG9pbnRUZXh0OiBtYWtlSG92ZXJQb2ludFRleHRcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3NjYXR0ZXJwb2xhcicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3BvbGFyJyksXG4gICAgY2F0ZWdvcmllczogWydwb2xhcicsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlci1saWtlJ10sXG5cbiAgICBhdHRyaWJ1dGVzOiByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLnN1cHBseURlZmF1bHRzLFxuICAgIGNvbG9yYmFyOiByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuICAgIGNhbGM6IHJlcXVpcmUoJy4vY2FsYycpLFxuICAgIHBsb3Q6IHJlcXVpcmUoJy4vcGxvdCcpLFxuICAgIHN0eWxlOiByZXF1aXJlKCcuLi9zY2F0dGVyL3N0eWxlJykuc3R5bGUsXG4gICAgaG92ZXJQb2ludHM6IHJlcXVpcmUoJy4vaG92ZXInKS5ob3ZlclBvaW50cyxcbiAgICBzZWxlY3RQb2ludHM6IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc2VsZWN0JyksXG5cbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlclBsb3QgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3Bsb3QnKTtcbnZhciBCQUROVU0gPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHN1YnBsb3QsIG1vZHVsZUNhbGNEYXRhKSB7XG4gICAgdmFyIG1sYXllciA9IHN1YnBsb3QubGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJ2cuc2NhdHRlcmxheWVyJyk7XG5cbiAgICB2YXIgcGxvdGluZm8gPSB7XG4gICAgICAgIHhheGlzOiBzdWJwbG90LnhheGlzLFxuICAgICAgICB5YXhpczogc3VicGxvdC55YXhpcyxcbiAgICAgICAgcGxvdDogc3VicGxvdC5mcmFtZXdvcmssXG4gICAgICAgIGxheWVyQ2xpcElkOiBzdWJwbG90Ll9oYXNDbGlwT25BeGlzRmFsc2UgPyBzdWJwbG90LmNsaXBJZHMuZm9yVHJhY2VzIDogbnVsbFxuICAgIH07XG5cbiAgICB2YXIgcmFkaWFsQXhpcyA9IHN1YnBsb3QucmFkaWFsQXhpcztcbiAgICB2YXIgYW5ndWxhckF4aXMgPSBzdWJwbG90LmFuZ3VsYXJBeGlzO1xuXG4gICAgLy8gY29udmVydDpcbiAgICAvLyAnYycgKHIsdGhldGEpIC0+ICdnZW9tZXRyaWMnIChyLHRoZXRhKSAtPiAoeCx5KVxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtb2R1bGVDYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2RpID0gbW9kdWxlQ2FsY0RhdGFbaV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNkaS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGNkID0gY2RpW2pdO1xuICAgICAgICAgICAgdmFyIHIgPSBjZC5yO1xuXG4gICAgICAgICAgICBpZihyID09PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICBjZC54ID0gY2QueSA9IEJBRE5VTTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHJnID0gcmFkaWFsQXhpcy5jMmcocik7XG4gICAgICAgICAgICAgICAgdmFyIHRoZXRhZyA9IGFuZ3VsYXJBeGlzLmMyZyhjZC50aGV0YSk7XG4gICAgICAgICAgICAgICAgY2QueCA9IHJnICogTWF0aC5jb3ModGhldGFnKTtcbiAgICAgICAgICAgICAgICBjZC55ID0gcmcgKiBNYXRoLnNpbih0aGV0YWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2NhdHRlclBsb3QoZ2QsIHBsb3RpbmZvLCBtb2R1bGVDYWxjRGF0YSwgbWxheWVyKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyUG9sYXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJwb2xhci9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlckdsQXR0cnMgPSByZXF1aXJlKCcuLi9zY2F0dGVyZ2wvYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2RlOiBzY2F0dGVyUG9sYXJBdHRycy5tb2RlLFxuICAgIHI6IHNjYXR0ZXJQb2xhckF0dHJzLnIsXG4gICAgdGhldGE6IHNjYXR0ZXJQb2xhckF0dHJzLnRoZXRhLFxuICAgIHIwOiBzY2F0dGVyUG9sYXJBdHRycy5yMCxcbiAgICBkcjogc2NhdHRlclBvbGFyQXR0cnMuZHIsXG4gICAgdGhldGEwOiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YTAsXG4gICAgZHRoZXRhOiBzY2F0dGVyUG9sYXJBdHRycy5kdGhldGEsXG4gICAgdGhldGF1bml0OiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YXVuaXQsXG5cbiAgICB0ZXh0OiBzY2F0dGVyUG9sYXJBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogc2NhdHRlclBvbGFyQXR0cnMuaG92ZXJ0ZXh0LFxuXG4gICAgbGluZTogc2NhdHRlckdsQXR0cnMubGluZSxcbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckdsQXR0cnMuY29ubmVjdGdhcHMsXG5cbiAgICBtYXJrZXI6IHNjYXR0ZXJHbEF0dHJzLm1hcmtlcixcbiAgICAvLyBubyBjbGlwb25heGlzXG5cbiAgICBmaWxsOiBzY2F0dGVyR2xBdHRycy5maWxsLFxuICAgIGZpbGxjb2xvcjogc2NhdHRlckdsQXR0cnMuZmlsbGNvbG9yLFxuXG4gICAgdGV4dHBvc2l0aW9uOiBzY2F0dGVyR2xBdHRycy50ZXh0cG9zaXRpb24sXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJHbEF0dHJzLnRleHRmb250LFxuXG4gICAgaG92ZXJpbmZvOiBzY2F0dGVyUG9sYXJBdHRycy5ob3ZlcmluZm8sXG4gICAgLy8gbm8gaG92ZXJvblxuXG4gICAgc2VsZWN0ZWQ6IHNjYXR0ZXJQb2xhckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IHNjYXR0ZXJQb2xhckF0dHJzLnVuc2VsZWN0ZWRcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIHN1YlR5cGVzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZVJUaGV0YURlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlcnBvbGFyL2RlZmF1bHRzJykuaGFuZGxlUlRoZXRhRGVmYXVsdHM7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcbnZhciBQVFNfTElORVNPTkxZID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb25zdGFudHMnKS5QVFNfTElORVNPTkxZO1xuXG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlUlRoZXRhRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGhldGF1bml0Jyk7XG4gICAgY29lcmNlKCdtb2RlJywgbGVuIDwgUFRTX0xJTkVTT05MWSA/ICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcycpO1xuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdjb25uZWN0Z2FwcycpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2ZpbGwnKTtcbiAgICBpZih0cmFjZU91dC5maWxsICE9PSAnbm9uZScpIHtcbiAgICAgICAgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjbHVzdGVyID0gcmVxdWlyZSgncG9pbnQtY2x1c3RlcicpO1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBTY2F0dGVyR2wgPSByZXF1aXJlKCcuLi9zY2F0dGVyZ2wnKTtcbnZhciBjYWxjQ29sb3JzY2FsZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGNhbGNNYXJrZXJTaXplID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jYWxjJykuY2FsY01hcmtlclNpemU7XG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJnbC9jb252ZXJ0Jyk7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBtYWtlSG92ZXJQb2ludFRleHQgPSByZXF1aXJlKCcuLi9zY2F0dGVycG9sYXIvaG92ZXInKS5tYWtlSG92ZXJQb2ludFRleHQ7XG5cbnZhciBUT09fTUFOWV9QT0lOVFMgPSByZXF1aXJlKCcuLi9zY2F0dGVyZ2wvY29uc3RhbnRzJykuVE9PX01BTllfUE9JTlRTO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZCA9IHRyYWNlLnN1YnBsb3Q7XG4gICAgdmFyIHJhZGlhbEF4aXMgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZF0ucmFkaWFsYXhpcztcbiAgICB2YXIgYW5ndWxhckF4aXMgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZF0uYW5ndWxhcmF4aXM7XG4gICAgdmFyIHJBcnJheSA9IHJhZGlhbEF4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCAncicpO1xuICAgIHZhciB0aGV0YUFycmF5ID0gYW5ndWxhckF4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCAndGhldGEnKTtcbiAgICB2YXIgbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgc3Rhc2ggPSB7fTtcblxuICAgIGlmKGxlbiA8IHJBcnJheS5sZW5ndGgpIHJBcnJheSA9IHJBcnJheS5zbGljZSgwLCBsZW4pO1xuICAgIGlmKGxlbiA8IHRoZXRhQXJyYXkubGVuZ3RoKSB0aGV0YUFycmF5ID0gdGhldGFBcnJheS5zbGljZSgwLCBsZW4pO1xuXG4gICAgc3Rhc2guciA9IHJBcnJheTtcbiAgICBzdGFzaC50aGV0YSA9IHRoZXRhQXJyYXk7XG5cbiAgICBjYWxjQ29sb3JzY2FsZXModHJhY2UpO1xuXG4gICAgLy8gb25seSBjb21wdXRlICdzdHlsZScgb3B0aW9ucyBpbiBjYWxjLCBhcyBwb3NpdGlvbiBvcHRpb25zXG4gICAgLy8gZGVwZW5kIG9uIHRoZSByYWRpYWwgcmFuZ2UgYW5kIG11c3QgYmUgc2V0IGluIHBsb3RcbiAgICB2YXIgb3B0cyA9IHN0YXNoLm9wdHMgPSBjb252ZXJ0LnN0eWxlKGdkLCB0cmFjZSk7XG5cbiAgICAvLyBGb3IgZ3JhcGhzIHdpdGggdmVyeSBsYXJnZSBudW1iZXIgb2YgcG9pbnRzIGFuZCBhcnJheSBtYXJrZXIuc2l6ZSxcbiAgICAvLyB1c2UgYXZlcmFnZSBtYXJrZXIgc2l6ZSBpbnN0ZWFkIHRvIHNwZWVkIHRoaW5ncyB1cC5cbiAgICB2YXIgcHBhZCA9IGxlbiA8IFRPT19NQU5ZX1BPSU5UUyA/XG4gICAgICAgIGNhbGNNYXJrZXJTaXplKHRyYWNlLCBsZW4pIDpcbiAgICAgICAgMiAqIChvcHRzLm1hcmtlci5zaXplQXZnIHx8IE1hdGgubWF4KG9wdHMubWFya2VyLnNpemUsIDMpKTtcbiAgICB0cmFjZS5fZXh0cmVtZXMueCA9IEF4ZXMuZmluZEV4dHJlbWVzKHJhZGlhbEF4aXMsIHJBcnJheSwge3BwYWQ6IHBwYWR9KTtcblxuICAgIHJldHVybiBbe3g6IGZhbHNlLCB5OiBmYWxzZSwgdDogc3Rhc2gsIHRyYWNlOiB0cmFjZX1dO1xufVxuXG5mdW5jdGlvbiBwbG90KGdkLCBzdWJwbG90LCBjZGF0YSkge1xuICAgIGlmKCFjZGF0YS5sZW5ndGgpIHJldHVybjtcblxuICAgIHZhciByYWRpYWxBeGlzID0gc3VicGxvdC5yYWRpYWxBeGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IHN1YnBsb3QuYW5ndWxhckF4aXM7XG4gICAgdmFyIHNjZW5lID0gU2NhdHRlckdsLnNjZW5lVXBkYXRlKGdkLCBzdWJwbG90KTtcblxuICAgIGNkYXRhLmZvckVhY2goZnVuY3Rpb24oY2RzY2F0dGVyKSB7XG4gICAgICAgIGlmKCFjZHNjYXR0ZXIgfHwgIWNkc2NhdHRlclswXSB8fCAhY2RzY2F0dGVyWzBdLnRyYWNlKSByZXR1cm47XG4gICAgICAgIHZhciBjZCA9IGNkc2NhdHRlclswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QudHJhY2U7XG4gICAgICAgIHZhciBzdGFzaCA9IGNkLnQ7XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgICAgICB2YXIgckFycmF5ID0gc3Rhc2gucjtcbiAgICAgICAgdmFyIHRoZXRhQXJyYXkgPSBzdGFzaC50aGV0YTtcbiAgICAgICAgdmFyIG9wdHMgPSBzdGFzaC5vcHRzO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICB2YXIgc3ViUkFycmF5ID0gckFycmF5LnNsaWNlKCk7XG4gICAgICAgIHZhciBzdWJUaGV0YUFycmF5ID0gdGhldGFBcnJheS5zbGljZSgpO1xuXG4gICAgICAgIC8vIGZpbHRlciBvdXQgYnkgcmFuZ2VcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgckFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZighc3VicGxvdC5pc1B0SW5zaWRlKHtyOiByQXJyYXlbaV0sIHRoZXRhOiB0aGV0YUFycmF5W2ldfSkpIHtcbiAgICAgICAgICAgICAgICBzdWJSQXJyYXlbaV0gPSBOYU47XG4gICAgICAgICAgICAgICAgc3ViVGhldGFBcnJheVtpXSA9IE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuICogMik7XG4gICAgICAgIHZhciB4ID0gQXJyYXkobGVuKTtcbiAgICAgICAgdmFyIHkgPSBBcnJheShsZW4pO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgciA9IHN1YlJBcnJheVtpXTtcbiAgICAgICAgICAgIHZhciB4eCwgeXk7XG5cbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhyKSkge1xuICAgICAgICAgICAgICAgIHZhciByZyA9IHJhZGlhbEF4aXMuYzJnKHIpO1xuICAgICAgICAgICAgICAgIHZhciB0aGV0YWcgPSBhbmd1bGFyQXhpcy5jMmcoc3ViVGhldGFBcnJheVtpXSwgdHJhY2UudGhldGF1bml0KTtcbiAgICAgICAgICAgICAgICB4eCA9IHJnICogTWF0aC5jb3ModGhldGFnKTtcbiAgICAgICAgICAgICAgICB5eSA9IHJnICogTWF0aC5zaW4odGhldGFnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeHggPSB5eSA9IE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHhbaV0gPSBwb3NpdGlvbnNbaSAqIDJdID0geHg7XG4gICAgICAgICAgICB5W2ldID0gcG9zaXRpb25zW2kgKiAyICsgMV0gPSB5eTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXNoLnRyZWUgPSBjbHVzdGVyKHBvc2l0aW9ucyk7XG5cbiAgICAgICAgLy8gRklYTUU6IHNlZSBzY2F0dGVyZ2wuanMjMTA5XG4gICAgICAgIGlmKG9wdHMubWFya2VyICYmIGxlbiA+PSBUT09fTUFOWV9QT0lOVFMpIHtcbiAgICAgICAgICAgIG9wdHMubWFya2VyLmNsdXN0ZXIgPSBzdGFzaC50cmVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob3B0cy5tYXJrZXIpIHtcbiAgICAgICAgICAgIG9wdHMubWFya2VyU2VsLnBvc2l0aW9ucyA9IG9wdHMubWFya2VyVW5zZWwucG9zaXRpb25zID0gb3B0cy5tYXJrZXIucG9zaXRpb25zID0gcG9zaXRpb25zO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob3B0cy5saW5lICYmIHBvc2l0aW9ucy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgICAgICBvcHRzLmxpbmUsXG4gICAgICAgICAgICAgICAgY29udmVydC5saW5lUG9zaXRpb25zKGdkLCB0cmFjZSwgcG9zaXRpb25zKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9wdHMudGV4dCkge1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICAgICAgb3B0cy50ZXh0LFxuICAgICAgICAgICAgICAgIHtwb3NpdGlvbnM6IHBvc2l0aW9uc30sXG4gICAgICAgICAgICAgICAgY29udmVydC50ZXh0UG9zaXRpb24oZ2QsIHRyYWNlLCBvcHRzLnRleHQsIG9wdHMubWFya2VyKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KFxuICAgICAgICAgICAgICAgIG9wdHMudGV4dFNlbCxcbiAgICAgICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgICAgIGNvbnZlcnQudGV4dFBvc2l0aW9uKGdkLCB0cmFjZSwgb3B0cy50ZXh0LCBvcHRzLm1hcmtlclNlbClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgICAgICBvcHRzLnRleHRVbnNlbCxcbiAgICAgICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgICAgIGNvbnZlcnQudGV4dFBvc2l0aW9uKGdkLCB0cmFjZSwgb3B0cy50ZXh0LCBvcHRzLm1hcmtlclVuc2VsKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9wdHMuZmlsbCAmJiAhc2NlbmUuZmlsbDJkKSBzY2VuZS5maWxsMmQgPSB0cnVlO1xuICAgICAgICBpZihvcHRzLm1hcmtlciAmJiAhc2NlbmUuc2NhdHRlcjJkKSBzY2VuZS5zY2F0dGVyMmQgPSB0cnVlO1xuICAgICAgICBpZihvcHRzLmxpbmUgJiYgIXNjZW5lLmxpbmUyZCkgc2NlbmUubGluZTJkID0gdHJ1ZTtcbiAgICAgICAgaWYob3B0cy50ZXh0ICYmICFzY2VuZS5nbFRleHQpIHNjZW5lLmdsVGV4dCA9IHRydWU7XG5cbiAgICAgICAgc2NlbmUubGluZU9wdGlvbnMucHVzaChvcHRzLmxpbmUpO1xuICAgICAgICBzY2VuZS5maWxsT3B0aW9ucy5wdXNoKG9wdHMuZmlsbCk7XG4gICAgICAgIHNjZW5lLm1hcmtlck9wdGlvbnMucHVzaChvcHRzLm1hcmtlcik7XG4gICAgICAgIHNjZW5lLm1hcmtlclNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMubWFya2VyU2VsKTtcbiAgICAgICAgc2NlbmUubWFya2VyVW5zZWxlY3RlZE9wdGlvbnMucHVzaChvcHRzLm1hcmtlclVuc2VsKTtcbiAgICAgICAgc2NlbmUudGV4dE9wdGlvbnMucHVzaChvcHRzLnRleHQpO1xuICAgICAgICBzY2VuZS50ZXh0U2VsZWN0ZWRPcHRpb25zLnB1c2gob3B0cy50ZXh0U2VsKTtcbiAgICAgICAgc2NlbmUudGV4dFVuc2VsZWN0ZWRPcHRpb25zLnB1c2gob3B0cy50ZXh0VW5zZWwpO1xuXG4gICAgICAgIHN0YXNoLnggPSB4O1xuICAgICAgICBzdGFzaC55ID0geTtcbiAgICAgICAgc3Rhc2gucmF3eCA9IHg7XG4gICAgICAgIHN0YXNoLnJhd3kgPSB5O1xuICAgICAgICBzdGFzaC5yID0gckFycmF5O1xuICAgICAgICBzdGFzaC50aGV0YSA9IHRoZXRhQXJyYXk7XG4gICAgICAgIHN0YXNoLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcbiAgICAgICAgc3Rhc2guX3NjZW5lID0gc2NlbmU7XG4gICAgICAgIHN0YXNoLmluZGV4ID0gc2NlbmUuY291bnQ7XG4gICAgICAgIHNjZW5lLmNvdW50Kys7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gU2NhdHRlckdsLnBsb3QoZ2QsIHN1YnBsb3QsIGNkYXRhKTtcbn1cblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHN0YXNoID0gY2RbMF0udDtcbiAgICB2YXIgckFycmF5ID0gc3Rhc2gucjtcbiAgICB2YXIgdGhldGFBcnJheSA9IHN0YXNoLnRoZXRhO1xuXG4gICAgdmFyIHNjYXR0ZXJQb2ludERhdGEgPSBTY2F0dGVyR2wuaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIGlmKCFzY2F0dGVyUG9pbnREYXRhIHx8IHNjYXR0ZXJQb2ludERhdGFbMF0uaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgbmV3UG9pbnREYXRhID0gc2NhdHRlclBvaW50RGF0YVswXTtcblxuICAgIGlmKG5ld1BvaW50RGF0YS5pbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xuICAgIH1cblxuICAgIHZhciBzdWJwbG90ID0gcG9pbnREYXRhLnN1YnBsb3Q7XG4gICAgdmFyIGNkaSA9IG5ld1BvaW50RGF0YS5jZFtuZXdQb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciB0cmFjZSA9IG5ld1BvaW50RGF0YS50cmFjZTtcblxuICAgIC8vIGF1Z21lbnQgcG9pbnREYXRhIHdpdGggci90aGV0YSBwYXJhbVxuICAgIGNkaS5yID0gckFycmF5W25ld1BvaW50RGF0YS5pbmRleF07XG4gICAgY2RpLnRoZXRhID0gdGhldGFBcnJheVtuZXdQb2ludERhdGEuaW5kZXhdO1xuXG4gICAgaWYoIXN1YnBsb3QuaXNQdEluc2lkZShjZGkpKSByZXR1cm47XG5cbiAgICBuZXdQb2ludERhdGEueExhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIG5ld1BvaW50RGF0YS55TGFiZWxWYWwgPSB1bmRlZmluZWQ7XG4gICAgbWFrZUhvdmVyUG9pbnRUZXh0KGNkaSwgdHJhY2UsIHN1YnBsb3QsIG5ld1BvaW50RGF0YSk7XG5cbiAgICByZXR1cm4gc2NhdHRlclBvaW50RGF0YTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcnBvbGFyZ2wnLFxuICAgIGJhc2VQbG90TW9kdWxlOiByZXF1aXJlKCcuLi8uLi9wbG90cy9wb2xhcicpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wnLCAncmVnbCcsICdwb2xhcicsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlci1saWtlJ10sXG5cbiAgICBhdHRyaWJ1dGVzOiByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiByZXF1aXJlKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuXG4gICAgY2FsYzogY2FsYyxcbiAgICBwbG90OiBwbG90LFxuICAgIGhvdmVyUG9pbnRzOiBob3ZlclBvaW50cyxcbiAgICBzZWxlY3RQb2ludHM6IFNjYXR0ZXJHbC5zZWxlY3RQb2ludHMsXG5cbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cmlidXRlcyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JiYXJBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JiYXIvYXR0cmlidXRlcycpO1xudmFyIGRhc2ggPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyLFxuICAgIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZSxcbiAgICBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGE6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1bToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtb2RlOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMubW9kZSwge2RmbHQ6ICdtYXJrZXJzJ30pLFxuICAgIHRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGhvdmVydGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBzY2F0dGVyTGluZUF0dHJzLmNvbG9yLFxuICAgICAgICB3aWR0aDogc2NhdHRlckxpbmVBdHRycy53aWR0aCxcbiAgICAgICAgZGFzaDogZGFzaCxcbiAgICAgICAgc2hhcGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJMaW5lQXR0cnMuc2hhcGUsXG4gICAgICAgICAgICB7dmFsdWVzOiBbJ2xpbmVhcicsICdzcGxpbmUnXX0pLFxuICAgICAgICBzbW9vdGhpbmc6IHNjYXR0ZXJMaW5lQXR0cnMuc21vb3RoaW5nLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckF0dHJzLmNvbm5lY3RnYXBzLFxuICAgIGNsaXBvbmF4aXM6IHNjYXR0ZXJBdHRycy5jbGlwb25heGlzLFxuICAgIGZpbGw6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5maWxsLCB7XG4gICAgICAgIHZhbHVlczogWydub25lJywgJ3Rvc2VsZicsICd0b25leHQnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG4gICAgbWFya2VyOiBleHRlbmRGbGF0KHtcbiAgICAgICAgc3ltYm9sOiBzY2F0dGVyTWFya2VyQXR0cnMuc3ltYm9sLFxuICAgICAgICBvcGFjaXR5OiBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSxcbiAgICAgICAgbWF4ZGlzcGxheWVkOiBzY2F0dGVyTWFya2VyQXR0cnMubWF4ZGlzcGxheWVkLFxuICAgICAgICBzaXplOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZSxcbiAgICAgICAgc2l6ZXJlZjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVyZWYsXG4gICAgICAgIHNpemVtaW46IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbWluLFxuICAgICAgICBzaXplbW9kZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtb2RlLFxuICAgICAgICBsaW5lOiBleHRlbmRGbGF0KHtcbiAgICAgICAgICAgIHdpZHRoOiBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScpXG4gICAgICAgICksXG4gICAgICAgIGdyYWRpZW50OiBzY2F0dGVyTWFya2VyQXR0cnMuZ3JhZGllbnQsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LCBjb2xvckF0dHJpYnV0ZXMoJ21hcmtlcicpLCB7XG4gICAgICAgIGNvbG9yYmFyOiBjb2xvcmJhckF0dHJzXG4gICAgfSksXG5cbiAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnRleHRmb250LFxuICAgIHRleHRwb3NpdGlvbjogc2NhdHRlckF0dHJzLnRleHRwb3NpdGlvbixcblxuICAgIHNlbGVjdGVkOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQsXG4gICAgdW5zZWxlY3RlZDogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQsXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnYScsICdiJywgJ2MnLCAndGV4dCcsICduYW1lJ11cbiAgICB9KSxcbiAgICBob3Zlcm9uOiBzY2F0dGVyQXR0cnMuaG92ZXJvbixcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBjYWxjQ29sb3JzY2FsZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcbnZhciBjYWxjTWFya2VyU2l6ZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNNYXJrZXJTaXplO1xuXG52YXIgZGF0YUFycmF5cyA9IFsnYScsICdiJywgJ2MnXTtcbnZhciBhcnJheXNUb0ZpbGwgPSB7YTogWydiJywgJ2MnXSwgYjogWydhJywgJ2MnXSwgYzogWydhJywgJ2InXX07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgdGVybmFyeSA9IGdkLl9mdWxsTGF5b3V0W3RyYWNlLnN1YnBsb3RdO1xuICAgIHZhciBkaXNwbGF5U3VtID0gdGVybmFyeS5zdW07XG4gICAgdmFyIG5vcm1TdW0gPSB0cmFjZS5zdW0gfHwgZGlzcGxheVN1bTtcbiAgICB2YXIgYXJyYXlzID0ge2E6IHRyYWNlLmEsIGI6IHRyYWNlLmIsIGM6IHRyYWNlLmN9O1xuXG4gICAgdmFyIGksIGosIGRhdGFBcnJheSwgbmV3QXJyYXksIGZpbGxBcnJheTEsIGZpbGxBcnJheTI7XG5cbiAgICAvLyBmaWxsIGluIG9uZSBtaXNzaW5nIGNvbXBvbmVudFxuICAgIGZvcihpID0gMDsgaSA8IGRhdGFBcnJheXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGF0YUFycmF5ID0gZGF0YUFycmF5c1tpXTtcbiAgICAgICAgaWYoYXJyYXlzW2RhdGFBcnJheV0pIGNvbnRpbnVlO1xuXG4gICAgICAgIGZpbGxBcnJheTEgPSBhcnJheXNbYXJyYXlzVG9GaWxsW2RhdGFBcnJheV1bMF1dO1xuICAgICAgICBmaWxsQXJyYXkyID0gYXJyYXlzW2FycmF5c1RvRmlsbFtkYXRhQXJyYXldWzFdXTtcbiAgICAgICAgbmV3QXJyYXkgPSBuZXcgQXJyYXkoZmlsbEFycmF5MS5sZW5ndGgpO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBmaWxsQXJyYXkxLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBuZXdBcnJheVtqXSA9IG5vcm1TdW0gLSBmaWxsQXJyYXkxW2pdIC0gZmlsbEFycmF5MltqXTtcbiAgICAgICAgfVxuICAgICAgICBhcnJheXNbZGF0YUFycmF5XSA9IG5ld0FycmF5O1xuICAgIH1cblxuICAgIC8vIG1ha2UgdGhlIGNhbGNkYXRhIGFycmF5XG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgdmFyIGEsIGIsIGMsIG5vcm0sIHgsIHk7XG4gICAgZm9yKGkgPSAwOyBpIDwgc2VyaWVzbGVuOyBpKyspIHtcbiAgICAgICAgYSA9IGFycmF5cy5hW2ldO1xuICAgICAgICBiID0gYXJyYXlzLmJbaV07XG4gICAgICAgIGMgPSBhcnJheXMuY1tpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKGEpICYmIGlzTnVtZXJpYyhiKSAmJiBpc051bWVyaWMoYykpIHtcbiAgICAgICAgICAgIGEgPSArYTtcbiAgICAgICAgICAgIGIgPSArYjtcbiAgICAgICAgICAgIGMgPSArYztcbiAgICAgICAgICAgIG5vcm0gPSBkaXNwbGF5U3VtIC8gKGEgKyBiICsgYyk7XG4gICAgICAgICAgICBpZihub3JtICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgYSAqPSBub3JtO1xuICAgICAgICAgICAgICAgIGIgKj0gbm9ybTtcbiAgICAgICAgICAgICAgICBjICo9IG5vcm07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBtYXAgYSwgYiwgYyBvbnRvIHggYW5kIHkgd2hlcmUgdGhlIGZ1bGwgc2NhbGUgb2YgeVxuICAgICAgICAgICAgLy8gaXMgWzAsIHN1bV0sIGFuZCB4IGlzIFstc3VtLCBzdW1dXG4gICAgICAgICAgICAvLyBUT0RPOiB0aGlzIG1ha2VzIGBhYCBhbHdheXMgdGhlIHRvcCwgYGJgIHRoZSBib3R0b20gbGVmdCxcbiAgICAgICAgICAgIC8vIGFuZCBgY2AgdGhlIGJvdHRvbSByaWdodC4gRG8gd2Ugd2FudCBvcHRpb25zIHRvIHJlYXJyYW5nZVxuICAgICAgICAgICAgLy8gdGhlc2U/XG4gICAgICAgICAgICB5ID0gYTtcbiAgICAgICAgICAgIHggPSBjIC0gYjtcbiAgICAgICAgICAgIGNkW2ldID0ge3g6IHgsIHk6IHksIGE6IGEsIGI6IGIsIGM6IGN9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgY2RbaV0gPSB7eDogZmFsc2UsIHk6IGZhbHNlfTtcbiAgICB9XG5cbiAgICBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgc2VyaWVzbGVuKTtcbiAgICBjYWxjQ29sb3JzY2FsZSh0cmFjZSk7XG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xuXG52YXIgY29uc3RhbnRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9jb25zdGFudHMnKTtcbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2xpbmVfc2hhcGVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUZXh0RGVmYXVsdHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGEgPSBjb2VyY2UoJ2EnKSxcbiAgICAgICAgYiA9IGNvZXJjZSgnYicpLFxuICAgICAgICBjID0gY29lcmNlKCdjJyksXG4gICAgICAgIGxlbjtcblxuICAgIC8vIGFsbG93IGFueSBvbmUgYXJyYXkgdG8gYmUgbWlzc2luZywgbGVuIGlzIHRoZSBtaW5pbXVtIGxlbmd0aCBvZiB0aG9zZVxuICAgIC8vIHByZXNlbnQuIE5vdGUgdGhhdCBhZnRlciBjb2VyY2UgZGF0YV9hcnJheSdzIGFyZSBlaXRoZXIgQXJyYXlzICh3aGljaFxuICAgIC8vIGFyZSB0cnV0aHkgZXZlbiBpZiBlbXB0eSkgb3IgdW5kZWZpbmVkLiBBcyBpbiBzY2F0dGVyLCBhbiBlbXB0eSBhcnJheVxuICAgIC8vIGlzIGRpZmZlcmVudCBmcm9tIHVuZGVmaW5lZCwgYmVjYXVzZSBpdCBjYW4gc2lnbmlmeSB0aGF0IHRoaXMgZGF0YSBpc1xuICAgIC8vIG5vdCBrbm93biB5ZXQgYnV0IGV4cGVjdGVkIGluIHRoZSBmdXR1cmVcbiAgICBpZihhKSB7XG4gICAgICAgIGxlbiA9IGEubGVuZ3RoO1xuICAgICAgICBpZihiKSB7XG4gICAgICAgICAgICBsZW4gPSBNYXRoLm1pbihsZW4sIGIubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKGMpIGxlbiA9IE1hdGgubWluKGxlbiwgYy5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoYykgbGVuID0gTWF0aC5taW4obGVuLCBjLmxlbmd0aCk7XG4gICAgICAgIGVsc2UgbGVuID0gMDtcbiAgICB9XG4gICAgZWxzZSBpZihiICYmIGMpIHtcbiAgICAgICAgbGVuID0gTWF0aC5taW4oYi5sZW5ndGgsIGMubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG5cbiAgICBjb2VyY2UoJ3N1bScpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcblxuICAgIHZhciBkZWZhdWx0TW9kZSA9IGxlbiA8IGNvbnN0YW50cy5QVFNfTElORVNPTkxZID8gJ2xpbmVzK21hcmtlcnMnIDogJ2xpbmVzJztcbiAgICBjb2VyY2UoJ21vZGUnLCBkZWZhdWx0TW9kZSk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge2dyYWRpZW50OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgdmFyIGRmbHRIb3Zlck9uID0gW107XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSB8fCBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBjb2VyY2UoJ2NsaXBvbmF4aXMnKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIubWF4ZGlzcGxheWVkJyk7XG4gICAgICAgIGRmbHRIb3Zlck9uLnB1c2goJ3BvaW50cycpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnZmlsbCcpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgICAgICBpZighc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZih0cmFjZU91dC5maWxsID09PSAndG9uZXh0JyB8fCB0cmFjZU91dC5maWxsID09PSAndG9zZWxmJykge1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdmaWxscycpO1xuICAgIH1cbiAgICBjb2VyY2UoJ2hvdmVyb24nLCBkZmx0SG92ZXJPbi5qb2luKCcrJykgfHwgJ3BvaW50cycpO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0LCB0cmFjZSwgY2QsIHBvaW50TnVtYmVyKSB7XG4gICAgaWYocHQueGEpIG91dC54YXhpcyA9IHB0LnhhO1xuICAgIGlmKHB0LnlhKSBvdXQueWF4aXMgPSBwdC55YTtcblxuICAgIGlmKGNkW3BvaW50TnVtYmVyXSkge1xuICAgICAgICB2YXIgY2RpID0gY2RbcG9pbnROdW1iZXJdO1xuXG4gICAgICAgIC8vIE4uQi4gVGhlc2UgYXJlIHRoZSBub3JtYWxpemVkIGNvb3JkaW5hdGVzLlxuICAgICAgICBvdXQuYSA9IGNkaS5hO1xuICAgICAgICBvdXQuYiA9IGNkaS5iO1xuICAgICAgICBvdXQuYyA9IGNkaS5jO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGZvciBmaWxsLWhvdmVyIG9ubHlcbiAgICAgICAgb3V0LmEgPSBwdC5hO1xuICAgICAgICBvdXQuYiA9IHB0LmI7XG4gICAgICAgIG91dC5jID0gcHQuYztcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckhvdmVyID0gcmVxdWlyZSgnLi4vc2NhdHRlci9ob3ZlcicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgc2NhdHRlclBvaW50RGF0YSA9IHNjYXR0ZXJIb3Zlcihwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG4gICAgaWYoIXNjYXR0ZXJQb2ludERhdGEgfHwgc2NhdHRlclBvaW50RGF0YVswXS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIHZhciBuZXdQb2ludERhdGEgPSBzY2F0dGVyUG9pbnREYXRhWzBdO1xuXG4gICAgLy8gaWYgaG92ZXJpbmcgb24gYSBmaWxsLCB3ZSBkb24ndCBzaG93IGFueSBwb2ludCBkYXRhIHNvIHRoZSBsYWJlbCBpc1xuICAgIC8vIHVuY2hhbmdlZCBmcm9tIHdoYXQgc2NhdHRlciBnaXZlcyB1cyAtIGV4Y2VwdCB0aGF0IGl0IG5lZWRzIHRvXG4gICAgLy8gYmUgY29uc3RyYWluZWQgdG8gdGhlIHRyaWFuZ2x1bGFyIHBsb3QgYXJlYSwgbm90IGp1c3QgdGhlIHJlY3Rhbmd1bGFyXG4gICAgLy8gYXJlYSBkZWZpbmVkIGJ5IHRoZSBzeW50aGV0aWMgeCBhbmQgeSBheGVzXG4gICAgLy8gVE9ETzogaW4gc29tZSBjYXNlcyB0aGUgdmVydGljYWwgbWlkZGxlIG9mIHRoZSBzaGFwZSBpcyBub3Qgd2l0aGluXG4gICAgLy8gdGhlIHRyaWFuZ3VsYXIgdmlld3BvcnQgYXQgYWxsLCBzbyB0aGUgbGFiZWwgY2FuIGJlY29tZSBkaXNjb25uZWN0ZWRcbiAgICAvLyBmcm9tIHRoZSBzaGFwZSBlbnRpcmVseS4gQnV0IGNhbGN1bGF0aW5nIHdoYXQgcG9ydGlvbiBvZiB0aGUgc2hhcGVcbiAgICAvLyBpcyBhY3R1YWxseSB2aXNpYmxlLCBhcyBjb25zdHJhaW5lZCBieSB0aGUgZGlhZ29uYWwgYXhpcyBsaW5lcywgaXMgbm90XG4gICAgLy8gc28gZWFzeSBhbmQgYW55d2F5IHdlIGxvc3QgdGhlIGluZm9ybWF0aW9uIHdlIHdvdWxkIGhhdmUgbmVlZGVkIHRvIGRvXG4gICAgLy8gdGhpcyBpbnNpZGUgc2NhdHRlckhvdmVyLlxuICAgIGlmKG5ld1BvaW50RGF0YS5pbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciB5RnJhY1VwID0gMSAtIChuZXdQb2ludERhdGEueTAgLyBwb2ludERhdGEueWEuX2xlbmd0aCksXG4gICAgICAgICAgICB4TGVuID0gcG9pbnREYXRhLnhhLl9sZW5ndGgsXG4gICAgICAgICAgICB4TWluID0geExlbiAqIHlGcmFjVXAgLyAyLFxuICAgICAgICAgICAgeE1heCA9IHhMZW4gLSB4TWluO1xuICAgICAgICBuZXdQb2ludERhdGEueDAgPSBNYXRoLm1heChNYXRoLm1pbihuZXdQb2ludERhdGEueDAsIHhNYXgpLCB4TWluKTtcbiAgICAgICAgbmV3UG9pbnREYXRhLngxID0gTWF0aC5tYXgoTWF0aC5taW4obmV3UG9pbnREYXRhLngxLCB4TWF4KSwgeE1pbik7XG4gICAgICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xuICAgIH1cblxuICAgIHZhciBjZGkgPSBuZXdQb2ludERhdGEuY2RbbmV3UG9pbnREYXRhLmluZGV4XTtcblxuICAgIG5ld1BvaW50RGF0YS5hID0gY2RpLmE7XG4gICAgbmV3UG9pbnREYXRhLmIgPSBjZGkuYjtcbiAgICBuZXdQb2ludERhdGEuYyA9IGNkaS5jO1xuXG4gICAgbmV3UG9pbnREYXRhLnhMYWJlbFZhbCA9IHVuZGVmaW5lZDtcbiAgICBuZXdQb2ludERhdGEueUxhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIC8vIFRPRE86IG5pY2UgZm9ybWF0dGluZywgYW5kIGxhYmVsIGJ5IGF4aXMgdGl0bGUsIGZvciBhLCBiLCBhbmQgYz9cblxuICAgIHZhciB0cmFjZSA9IG5ld1BvaW50RGF0YS50cmFjZTtcbiAgICB2YXIgdGVybmFyeSA9IG5ld1BvaW50RGF0YS5zdWJwbG90O1xuICAgIHZhciBob3ZlcmluZm8gPSBjZGkuaGkgfHwgdHJhY2UuaG92ZXJpbmZvO1xuICAgIHZhciBwYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICBmdW5jdGlvbiB0ZXh0UGFydChheCwgdmFsKSB7XG4gICAgICAgIHRleHQucHVzaChheC5faG92ZXJ0aXRsZSArICc6ICcgKyBBeGVzLnRpY2tUZXh0KGF4LCB2YWwsICdob3ZlcicpLnRleHQpO1xuICAgIH1cblxuICAgIGlmKHBhcnRzLmluZGV4T2YoJ2FsbCcpICE9PSAtMSkgcGFydHMgPSBbJ2EnLCAnYicsICdjJ107XG4gICAgaWYocGFydHMuaW5kZXhPZignYScpICE9PSAtMSkgdGV4dFBhcnQodGVybmFyeS5hYXhpcywgY2RpLmEpO1xuICAgIGlmKHBhcnRzLmluZGV4T2YoJ2InKSAhPT0gLTEpIHRleHRQYXJ0KHRlcm5hcnkuYmF4aXMsIGNkaS5iKTtcbiAgICBpZihwYXJ0cy5pbmRleE9mKCdjJykgIT09IC0xKSB0ZXh0UGFydCh0ZXJuYXJ5LmNheGlzLCBjZGkuYyk7XG5cbiAgICBuZXdQb2ludERhdGEuZXh0cmFUZXh0ID0gdGV4dC5qb2luKCc8YnI+Jyk7XG5cbiAgICByZXR1cm4gc2NhdHRlclBvaW50RGF0YTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBTY2F0dGVyVGVybmFyeSA9IHt9O1xuXG5TY2F0dGVyVGVybmFyeS5hdHRyaWJ1dGVzID0gcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyk7XG5TY2F0dGVyVGVybmFyeS5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcblNjYXR0ZXJUZXJuYXJ5LmNvbG9yYmFyID0gcmVxdWlyZSgnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKTtcblNjYXR0ZXJUZXJuYXJ5LmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKTtcblNjYXR0ZXJUZXJuYXJ5LnBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcblNjYXR0ZXJUZXJuYXJ5LnN0eWxlID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdHlsZScpLnN0eWxlO1xuU2NhdHRlclRlcm5hcnkuc3R5bGVPblNlbGVjdCA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZU9uU2VsZWN0O1xuU2NhdHRlclRlcm5hcnkuaG92ZXJQb2ludHMgPSByZXF1aXJlKCcuL2hvdmVyJyk7XG5TY2F0dGVyVGVybmFyeS5zZWxlY3RQb2ludHMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3NlbGVjdCcpO1xuU2NhdHRlclRlcm5hcnkuZXZlbnREYXRhID0gcmVxdWlyZSgnLi9ldmVudF9kYXRhJyk7XG5cblNjYXR0ZXJUZXJuYXJ5Lm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuU2NhdHRlclRlcm5hcnkubmFtZSA9ICdzY2F0dGVydGVybmFyeSc7XG5TY2F0dGVyVGVybmFyeS5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL3Rlcm5hcnknKTtcblNjYXR0ZXJUZXJuYXJ5LmNhdGVnb3JpZXMgPSBbJ3Rlcm5hcnknLCAnc3ltYm9scycsICdzaG93TGVnZW5kJywgJ3NjYXR0ZXItbGlrZSddO1xuU2NhdHRlclRlcm5hcnkubWV0YSA9IHtcbiAgICBcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU2NhdHRlclRlcm5hcnk7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJQbG90ID0gcmVxdWlyZSgnLi4vc2NhdHRlci9wbG90Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgdGVybmFyeSwgbW9kdWxlQ2FsY0RhdGEpIHtcbiAgICB2YXIgcGxvdENvbnRhaW5lciA9IHRlcm5hcnkucGxvdENvbnRhaW5lcjtcblxuICAgIC8vIHJlbW92ZSBhbGwgbm9kZXMgaW5zaWRlIHRoZSBzY2F0dGVyIGxheWVyXG4gICAgcGxvdENvbnRhaW5lci5zZWxlY3QoJy5zY2F0dGVybGF5ZXInKS5zZWxlY3RBbGwoJyonKS5yZW1vdmUoKTtcblxuICAgIC8vIG1pbWljIGNhcnRlc2lhbiBwbG90aW5mb1xuICAgIHZhciBwbG90aW5mbyA9IHtcbiAgICAgICAgeGF4aXM6IHRlcm5hcnkueGF4aXMsXG4gICAgICAgIHlheGlzOiB0ZXJuYXJ5LnlheGlzLFxuICAgICAgICBwbG90OiBwbG90Q29udGFpbmVyLFxuICAgICAgICBsYXllckNsaXBJZDogdGVybmFyeS5faGFzQ2xpcE9uQXhpc0ZhbHNlID8gdGVybmFyeS5jbGlwSWRSZWxhdGl2ZSA6IG51bGxcbiAgICB9O1xuXG4gICAgdmFyIHNjYXR0ZXJMYXllciA9IHRlcm5hcnkubGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJ2cuc2NhdHRlcmxheWVyJyk7XG5cbiAgICBzY2F0dGVyUGxvdChnZCwgcGxvdGluZm8sIG1vZHVsZUNhbGNEYXRhLCBzY2F0dGVyTGF5ZXIpO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJBdHRycyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJHbEF0dHJzID0gcmVxdWlyZSgnLi4vc2NhdHRlcmdsL2F0dHJpYnV0ZXMnKTtcbnZhciBjYXJ0ZXNpYW5JZFJlZ2V4ID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpLmlkUmVnZXg7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSByZXF1aXJlKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbnZhciBtYXJrZXJMaW5lQXR0cnMgPSBleHRlbmRGbGF0KGNvbG9yQXR0cnMoJ21hcmtlci5saW5lJywge2VkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ30pLCB7XG4gICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMud2lkdGgsIHtlZGl0VHlwZTogJ2NhbGMnfSksXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSk7XG5cbnZhciBtYXJrZXJBdHRycyA9IGV4dGVuZEZsYXQoY29sb3JBdHRycygnbWFya2VyJyksIHtcbiAgICBzeW1ib2w6IHNjYXR0ZXJNYXJrZXJBdHRycy5zeW1ib2wsXG4gICAgc2l6ZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLnNpemUsIHtlZGl0VHlwZTogJ21hcmtlclNpemUnfSksXG4gICAgc2l6ZXJlZjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVyZWYsXG4gICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICBvcGFjaXR5OiBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSxcbiAgICBjb2xvcmJhcjogc2NhdHRlck1hcmtlckF0dHJzLmNvbG9yYmFyLFxuICAgIGxpbmU6IG1hcmtlckxpbmVBdHRycyxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59KTtcblxubWFya2VyQXR0cnMuY29sb3IuZWRpdFR5cGUgPSBtYXJrZXJBdHRycy5jbWluLmVkaXRUeXBlID0gbWFya2VyQXR0cnMuY21heC5lZGl0VHlwZSA9ICdzdHlsZSc7XG5cbmZ1bmN0aW9uIG1ha2VBeGVzVmFsT2JqZWN0KGF4TGV0dGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaXRlbXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICAgICAgcmVnZXg6IGNhcnRlc2lhbklkUmVnZXhbYXhMZXR0ZXJdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBcbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBkaW1lbnNpb25zOiB0ZW1wbGF0ZWRBcnJheSgnZGltZW5zaW9uJywge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGF4aXM6IHtcbiAgICAgICAgICAgIHR5cGU6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBbJ2xpbmVhcicsICdsb2cnLCAnZGF0ZScsICdjYXRlZ29yeSddLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnXG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8gVE9ETyBzaG91bGQgYWRkIGFuIGF0dHJpYnV0ZSB0byBwaW4gZG93biB4IG9ubHkgdmFycyBhbmQgeSBvbmx5IHZhcnNcbiAgICAgICAgLy8gbGlrZSBodHRwczovL3NlYWJvcm4ucHlkYXRhLm9yZy9nZW5lcmF0ZWQvc2VhYm9ybi5wYWlycGxvdC5odG1sXG4gICAgICAgIC8vIHhfdmFycyBhbmQgeV92YXJzXG5cbiAgICAgICAgLy8gbWF5YmUgbW9yZSBheGlzIGRlZmF1bHRpbmcgb3B0aW9uIGUuZy4gYHNob3dncmlkOiBmYWxzZWBcblxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnXG4gICAgfSksXG5cbiAgICAvLyBtb2RlOiB7fSwgKG9ubHkgJ21hcmtlcnMnIGZvciBub3cpXG5cbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyR2xBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgbWFya2VyOiBtYXJrZXJBdHRycyxcblxuICAgIHhheGVzOiBtYWtlQXhlc1ZhbE9iamVjdCgneCcpLFxuICAgIHlheGVzOiBtYWtlQXhlc1ZhbE9iamVjdCgneScpLFxuXG4gICAgZGlhZ29uYWw6IHtcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIHR5cGU6ICdzY2F0dGVyZ2wnIHwgJ2hpc3RvZ3JhbScgfCAnYm94JyB8ICd2aW9saW4nXG4gICAgICAgIC8vIC4uLlxuICAgICAgICAvLyBtb3JlIG9wdGlvbnNcblxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIHNob3d1cHBlcmhhbGY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93bG93ZXJoYWxmOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJHbEF0dHJzLnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJHbEF0dHJzLnVuc2VsZWN0ZWQubWFya2VyLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIG9wYWNpdHk6IHNjYXR0ZXJHbEF0dHJzLm9wYWNpdHlcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVMaW5lID0gcmVxdWlyZSgncmVnbC1saW5lMmQnKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBwcmVwYXJlUmVnbCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9wcmVwYXJlX3JlZ2wnKTtcbnZhciBnZXRNb2R1bGVDYWxjRGF0YSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dldF9kYXRhJykuZ2V0TW9kdWxlQ2FsY0RhdGE7XG52YXIgQ2FydGVzaWFuID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyk7XG52YXIgZ2V0RnJvbUlkID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJykuZ2V0RnJvbUlkO1xudmFyIHNob3VsZFNob3daZXJvTGluZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJykuc2hvdWxkU2hvd1plcm9MaW5lO1xuXG52YXIgU1BMT00gPSAnc3Bsb20nO1xuXG5mdW5jdGlvbiBwbG90KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgX21vZHVsZSA9IFJlZ2lzdHJ5LmdldE1vZHVsZShTUExPTSk7XG4gICAgdmFyIHNwbG9tQ2FsY0RhdGEgPSBnZXRNb2R1bGVDYWxjRGF0YShnZC5jYWxjZGF0YSwgX21vZHVsZSlbMF07XG5cbiAgICB2YXIgc3VjY2VzcyA9IHByZXBhcmVSZWdsKGdkLCBbJ0FOR0xFX2luc3RhbmNlZF9hcnJheXMnLCAnT0VTX2VsZW1lbnRfaW5kZXhfdWludCddKTtcbiAgICBpZighc3VjY2VzcykgcmV0dXJuO1xuXG4gICAgaWYoZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgIHVwZGF0ZUdyaWQoZ2QpO1xuICAgIH1cblxuICAgIF9tb2R1bGUucGxvdChnZCwge30sIHNwbG9tQ2FsY0RhdGEpO1xufVxuXG5mdW5jdGlvbiBkcmFnKGdkKSB7XG4gICAgdmFyIGNkID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIGlmKGZ1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICB1cGRhdGVHcmlkKGdkKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkMCA9IGNkW2ldWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIHZhciBzY2VuZSA9IGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG5cbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3NwbG9tJyAmJiBzY2VuZSAmJiBzY2VuZS5tYXRyaXgpIHtcbiAgICAgICAgICAgIGRyYWdPbmUoZ2QsIHRyYWNlLCBzY2VuZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWdPbmUoZ2QsIHRyYWNlLCBzY2VuZSkge1xuICAgIHZhciB2aXNpYmxlTGVuZ3RoID0gc2NlbmUubWF0cml4T3B0aW9ucy5kYXRhLmxlbmd0aDtcbiAgICB2YXIgdmlzaWJsZURpbXMgPSB0cmFjZS5fdmlzaWJsZURpbXM7XG4gICAgdmFyIHJhbmdlcyA9IHNjZW5lLnZpZXdPcHRzLnJhbmdlcyA9IG5ldyBBcnJheSh2aXNpYmxlTGVuZ3RoKTtcblxuICAgIGZvcih2YXIgayA9IDA7IGsgPCB2aXNpYmxlRGltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICB2YXIgaSA9IHZpc2libGVEaW1zW2tdO1xuICAgICAgICB2YXIgcm5nID0gcmFuZ2VzW2tdID0gbmV3IEFycmF5KDQpO1xuXG4gICAgICAgIHZhciB4YSA9IGdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMF0pO1xuICAgICAgICBpZih4YSkge1xuICAgICAgICAgICAgcm5nWzBdID0geGEucjJsKHhhLnJhbmdlWzBdKTtcbiAgICAgICAgICAgIHJuZ1syXSA9IHhhLnIybCh4YS5yYW5nZVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeWEgPSBnZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzFdKTtcbiAgICAgICAgaWYoeWEpIHtcbiAgICAgICAgICAgIHJuZ1sxXSA9IHlhLnIybCh5YS5yYW5nZVswXSk7XG4gICAgICAgICAgICBybmdbM10gPSB5YS5yMmwoeWEucmFuZ2VbMV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoc2NlbmUuc2VsZWN0QmF0Y2gpIHtcbiAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZSh7cmFuZ2VzOiByYW5nZXN9LCB7cmFuZ2VzOiByYW5nZXN9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKHtyYW5nZXM6IHJhbmdlc30pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlR3JpZChnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHJlZ2wgPSBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5kYXRhKClbMF0ucmVnbDtcbiAgICB2YXIgc3Bsb21HcmlkID0gZnVsbExheW91dC5fc3Bsb21HcmlkO1xuXG4gICAgaWYoIXNwbG9tR3JpZCkge1xuICAgICAgICBzcGxvbUdyaWQgPSBmdWxsTGF5b3V0Ll9zcGxvbUdyaWQgPSBjcmVhdGVMaW5lKHJlZ2wpO1xuICAgIH1cbiAgICBzcGxvbUdyaWQudXBkYXRlKG1ha2VHcmlkRGF0YShnZCkpO1xufVxuXG5mdW5jdGlvbiBtYWtlR3JpZERhdGEoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGZ1bGxWaWV3ID0gWzAsIDAsIGZ1bGxMYXlvdXQud2lkdGgsIGZ1bGxMYXlvdXQuaGVpZ2h0XTtcbiAgICB2YXIgbG9va3VwID0ge307XG4gICAgdmFyIGs7XG5cbiAgICBmdW5jdGlvbiBwdXNoKHByZWZpeCwgYXgsIHgwLCB4MSwgeTAsIHkxKSB7XG4gICAgICAgIHZhciBsY29sb3IgPSBheFtwcmVmaXggKyAnY29sb3InXTtcbiAgICAgICAgdmFyIGx3aWR0aCA9IGF4W3ByZWZpeCArICd3aWR0aCddO1xuICAgICAgICB2YXIga2V5ID0gU3RyaW5nKGxjb2xvciArIGx3aWR0aCk7XG5cbiAgICAgICAgaWYoa2V5IGluIGxvb2t1cCkge1xuICAgICAgICAgICAgbG9va3VwW2tleV0uZGF0YS5wdXNoKE5hTiwgTmFOLCB4MCwgeDEsIHkwLCB5MSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb29rdXBba2V5XSA9IHtcbiAgICAgICAgICAgICAgICBkYXRhOiBbeDAsIHgxLCB5MCwgeTFdLFxuICAgICAgICAgICAgICAgIGpvaW46ICdyZWN0JyxcbiAgICAgICAgICAgICAgICB0aGlja25lc3M6IGx3aWR0aCxcbiAgICAgICAgICAgICAgICBjb2xvcjogbGNvbG9yLFxuICAgICAgICAgICAgICAgIHZpZXdwb3J0OiBmdWxsVmlldyxcbiAgICAgICAgICAgICAgICByYW5nZTogZnVsbFZpZXcsXG4gICAgICAgICAgICAgICAgb3ZlcmxheTogZmFsc2VcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoayBpbiBmdWxsTGF5b3V0Ll9zcGxvbVN1YnBsb3RzKSB7XG4gICAgICAgIHZhciBzcCA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2tdO1xuICAgICAgICB2YXIgeGEgPSBzcC54YXhpcztcbiAgICAgICAgdmFyIHlhID0gc3AueWF4aXM7XG4gICAgICAgIHZhciB4VmFscyA9IHhhLl92YWxzO1xuICAgICAgICB2YXIgeVZhbHMgPSB5YS5fdmFscztcbiAgICAgICAgLy8geWEubDJwIGFzc3VtZXMgdG9wLXRvLWJvdHRvbSBjb29yZGluYXRlIHN5c3RlbSAoYSBsYSBTVkcpLFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIGNvbXB1dGUgYm90dG9tLXRvLXRvcCBvZmZzZXRzIGFuZCBzbG9wZXM6XG4gICAgICAgIHZhciB5T2Zmc2V0ID0gZ3MuYiArIHlhLmRvbWFpblswXSAqIGdzLmg7XG4gICAgICAgIHZhciB5bSA9IC15YS5fbTtcbiAgICAgICAgdmFyIHliID0gLXltICogeWEucjJsKHlhLnJhbmdlWzBdLCB5YS5jYWxlbmRhcik7XG4gICAgICAgIHZhciB4LCB5O1xuXG4gICAgICAgIGlmKHhhLnNob3dncmlkKSB7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCB4VmFscy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHggPSB4YS5fb2Zmc2V0ICsgeGEubDJwKHhWYWxzW2tdLngpO1xuICAgICAgICAgICAgICAgIHB1c2goJ2dyaWQnLCB4YSwgeCwgeU9mZnNldCwgeCwgeU9mZnNldCArIHlhLl9sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKHlhLnNob3dncmlkKSB7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCB5VmFscy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHkgPSB5T2Zmc2V0ICsgeWIgKyB5bSAqIHlWYWxzW2tdLng7XG4gICAgICAgICAgICAgICAgcHVzaCgnZ3JpZCcsIHlhLCB4YS5fb2Zmc2V0LCB5LCB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCwgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2hvdWxkU2hvd1plcm9MaW5lKGdkLCB4YSwgeWEpKSB7XG4gICAgICAgICAgICB4ID0geGEuX29mZnNldCArIHhhLmwycCgwKTtcbiAgICAgICAgICAgIHB1c2goJ3plcm9saW5lJywgeGEsIHgsIHlPZmZzZXQsIHgsIHlPZmZzZXQgKyB5YS5fbGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzaG91bGRTaG93WmVyb0xpbmUoZ2QsIHlhLCB4YSkpIHtcbiAgICAgICAgICAgIHkgPSB5T2Zmc2V0ICsgeWIgKyAwO1xuICAgICAgICAgICAgcHVzaCgnemVyb2xpbmUnLCB5YSwgeGEuX29mZnNldCwgeSwgeGEuX29mZnNldCArIHhhLl9sZW5ndGgsIHkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGdyaWRCYXRjaGVzID0gW107XG4gICAgZm9yKGsgaW4gbG9va3VwKSB7XG4gICAgICAgIGdyaWRCYXRjaGVzLnB1c2gobG9va3VwW2tdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JpZEJhdGNoZXM7XG59XG5cbmZ1bmN0aW9uIGNsZWFuKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBsb29rdXAgPSB7fTtcbiAgICB2YXIgaTtcblxuICAgIGlmKG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG5ld0Z1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbmV3VHJhY2UgPSBuZXdGdWxsRGF0YVtpXTtcbiAgICAgICAgICAgIGlmKG5ld1RyYWNlLnR5cGUgPT09ICdzcGxvbScpIHtcbiAgICAgICAgICAgICAgICBsb29rdXBbbmV3VHJhY2UudWlkXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb2xkRnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBvbGRUcmFjZSA9IG9sZEZ1bGxEYXRhW2ldO1xuICAgICAgICAgICAgaWYoIWxvb2t1cFtvbGRUcmFjZS51aWRdKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjZW5lID0gb2xkRnVsbExheW91dC5fc3Bsb21TY2VuZXNbb2xkVHJhY2UudWlkXTtcbiAgICAgICAgICAgICAgICBpZihzY2VuZSAmJiBzY2VuZS5kZXN0cm95KSBzY2VuZS5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgLy8gbXVzdCBmaXJzdCBzZXQgc2NlbmUgdG8gbnVsbCBpbiBvcmRlciB0byBnZXQgZ2FyYmFnZSBjb2xsZWN0ZWRcbiAgICAgICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9zcGxvbVNjZW5lc1tvbGRUcmFjZS51aWRdID0gbnVsbDtcbiAgICAgICAgICAgICAgICBkZWxldGUgb2xkRnVsbExheW91dC5fc3Bsb21TY2VuZXNbb2xkVHJhY2UudWlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKE9iamVjdC5rZXlzKG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzIHx8IHt9KS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzO1xuICAgIH1cblxuICAgIGlmKG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZCAmJlxuICAgICAgICAoIW5ld0Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMpKSB7XG4gICAgICAgIC8vIG11c3QgZmlyc3Qgc2V0IHNjZW5lIHRvIG51bGwgaW4gb3JkZXIgdG8gZ2V0IGdhcmJhZ2UgY29sbGVjdGVkXG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZC5kZXN0cm95KCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZCA9IG51bGw7XG4gICAgICAgIGRlbGV0ZSBvbGRGdWxsTGF5b3V0Ll9zcGxvbUdyaWQ7XG4gICAgfVxuXG4gICAgQ2FydGVzaWFuLmNsZWFuKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUZ4KGdkKSB7XG4gICAgQ2FydGVzaWFuLnVwZGF0ZUZ4KGdkKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGRyYWdtb2RlID0gZnVsbExheW91dC5kcmFnbW9kZTtcblxuICAgIC8vIHVuc2V0IHNlbGVjdGlvbiBzdHlsZXMgd2hlbiBjb21pbmcgb3V0IG9mIGEgc2VsZWN0aW9uIG1vZGVcbiAgICBpZihkcmFnbW9kZSA9PT0gJ3pvb20nIHx8IGRyYWdtb2RlID09PSAncGFuJykge1xuICAgICAgICB2YXIgY2QgPSBnZC5jYWxjZGF0YTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjZDAgPSBjZFtpXVswXTtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3NwbG9tJykge1xuICAgICAgICAgICAgICAgIHZhciBzY2VuZSA9IGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG4gICAgICAgICAgICAgICAgaWYoc2NlbmUuc2VsZWN0QmF0Y2ggPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZShzY2VuZS5tYXRyaXhPcHRpb25zLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG5hbWU6IFNQTE9NLFxuICAgIGF0dHI6IENhcnRlc2lhbi5hdHRyLFxuICAgIGF0dHJSZWdleDogQ2FydGVzaWFuLmF0dHJSZWdleCxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBDYXJ0ZXNpYW4ubGF5b3V0QXR0cmlidXRlcyxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogQ2FydGVzaWFuLnN1cHBseUxheW91dERlZmF1bHRzLFxuICAgIGRyYXdGcmFtZXdvcms6IENhcnRlc2lhbi5kcmF3RnJhbWV3b3JrLFxuICAgIHBsb3Q6IHBsb3QsXG4gICAgZHJhZzogZHJhZyxcbiAgICB1cGRhdGVHcmlkOiB1cGRhdGVHcmlkLFxuICAgIGNsZWFuOiBjbGVhbixcbiAgICB1cGRhdGVGeDogdXBkYXRlRngsXG4gICAgdG9TVkc6IENhcnRlc2lhbi50b1NWR1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBzdWJUeXBlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgbWVyZ2VMZW5ndGggPSByZXF1aXJlKCcuLi9wYXJjb29yZHMvbWVyZ2VfbGVuZ3RoJyk7XG52YXIgT1BFTl9SRSA9IC8tb3Blbi87XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb25zID0gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwge1xuICAgICAgICBuYW1lOiAnZGltZW5zaW9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogZGltZW5zaW9uRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIHZhciBzaG93RGlhZyA9IGNvZXJjZSgnZGlhZ29uYWwudmlzaWJsZScpO1xuICAgIHZhciBzaG93VXBwZXIgPSBjb2VyY2UoJ3Nob3d1cHBlcmhhbGYnKTtcbiAgICB2YXIgc2hvd0xvd2VyID0gY29lcmNlKCdzaG93bG93ZXJoYWxmJyk7XG5cbiAgICB2YXIgZGltTGVuZ3RoID0gbWVyZ2VMZW5ndGgodHJhY2VPdXQsIGRpbWVuc2lvbnMsICd2YWx1ZXMnKTtcblxuICAgIGlmKCFkaW1MZW5ndGggfHwgKCFzaG93RGlhZyAmJiAhc2hvd1VwcGVyICYmICFzaG93TG93ZXIpKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuXG4gICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgdmFyIGlzT3BlbiA9IE9QRU5fUkUudGVzdCh0cmFjZU91dC5tYXJrZXIuc3ltYm9sKTtcbiAgICB2YXIgaXNCdWJibGUgPSBzdWJUeXBlcy5pc0J1YmJsZSh0cmFjZU91dCk7XG4gICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcsIGlzT3BlbiB8fCBpc0J1YmJsZSA/IDEgOiAwKTtcblxuICAgIGhhbmRsZUF4aXNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG5mdW5jdGlvbiBkaW1lbnNpb25EZWZhdWx0cyhkaW1JbiwgZGltT3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoZGltSW4sIGRpbU91dCwgYXR0cmlidXRlcy5kaW1lbnNpb25zLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2xhYmVsJyk7XG4gICAgdmFyIHZhbHVlcyA9IGNvZXJjZSgndmFsdWVzJyk7XG5cbiAgICBpZighKHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKSkgZGltT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICBlbHNlIGNvZXJjZSgndmlzaWJsZScpO1xuXG4gICAgY29lcmNlKCdheGlzLnR5cGUnKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlQXhpc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSkge1xuICAgIHZhciBkaW1lbnNpb25zID0gdHJhY2VPdXQuZGltZW5zaW9ucztcbiAgICB2YXIgZGltTGVuZ3RoID0gZGltZW5zaW9ucy5sZW5ndGg7XG4gICAgdmFyIHNob3dVcHBlciA9IHRyYWNlT3V0LnNob3d1cHBlcmhhbGY7XG4gICAgdmFyIHNob3dMb3dlciA9IHRyYWNlT3V0LnNob3dsb3dlcmhhbGY7XG4gICAgdmFyIHNob3dEaWFnID0gdHJhY2VPdXQuZGlhZ29uYWwudmlzaWJsZTtcbiAgICB2YXIgaSwgajtcblxuICAgIHZhciB4QXhlc0RmbHQgPSBuZXcgQXJyYXkoZGltTGVuZ3RoKTtcbiAgICB2YXIgeUF4ZXNEZmx0ID0gbmV3IEFycmF5KGRpbUxlbmd0aCk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBkaW1MZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VmZml4ID0gaSA/IGkgKyAxIDogJyc7XG4gICAgICAgIHhBeGVzRGZsdFtpXSA9ICd4JyArIHN1ZmZpeDtcbiAgICAgICAgeUF4ZXNEZmx0W2ldID0gJ3knICsgc3VmZml4O1xuICAgIH1cblxuICAgIHZhciB4YXhlcyA9IGNvZXJjZSgneGF4ZXMnLCB4QXhlc0RmbHQpO1xuICAgIHZhciB5YXhlcyA9IGNvZXJjZSgneWF4ZXMnLCB5QXhlc0RmbHQpO1xuXG4gICAgLy8gYnVpbGQgbGlzdCBvZiBbeCx5XSBheGlzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCBkaW1lbnNpb25zW2ldLFxuICAgIC8vIHZlcnkgdXNlZnVsIGZvciBwYXNzaW5nIG9wdGlvbnMgdG8gcmVnbC1zcGxvbVxuICAgIHZhciBkaWFnID0gdHJhY2VPdXQuX2RpYWcgPSBuZXcgQXJyYXkoZGltTGVuZ3RoKTtcblxuICAgIC8vIGxvb2t1cCBmb3IgJ2RyYXduJyB4fHkgYXhlcywgdG8gYXZvaWQgY29zdGx5IGluZGV4T2YgZG93bnN0cmVhbVxuICAgIHRyYWNlT3V0Ll94YXhlcyA9IHt9O1xuICAgIHRyYWNlT3V0Ll95YXhlcyA9IHt9O1xuXG4gICAgLy8gbGlzdCBvZiAnZHJhd24nIHh8eSBheGVzLCB1c2UgdG8gZ2VuZXJhdGUgbGlzdCBvZiBzdWJwbG90c1xuICAgIHZhciB4TGlzdCA9IFtdO1xuICAgIHZhciB5TGlzdCA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZmlsbEF4aXNTdGFzaGVzKGF4SWQsIGRpbSwgbGlzdCkge1xuICAgICAgICBpZighYXhJZCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBheExldHRlciA9IGF4SWQuY2hhckF0KDApO1xuICAgICAgICB2YXIgc3Rhc2ggPSBsYXlvdXQuX3NwbG9tQXhlc1theExldHRlcl07XG5cbiAgICAgICAgdHJhY2VPdXRbJ18nICsgYXhMZXR0ZXIgKyAnYXhlcyddW2F4SWRdID0gMTtcbiAgICAgICAgbGlzdC5wdXNoKGF4SWQpO1xuXG4gICAgICAgIGlmKCEoYXhJZCBpbiBzdGFzaCkpIHtcbiAgICAgICAgICAgIHZhciBzID0gc3Rhc2hbYXhJZF0gPSB7fTtcbiAgICAgICAgICAgIGlmKGRpbSkge1xuICAgICAgICAgICAgICAgIHMubGFiZWwgPSBkaW0ubGFiZWwgfHwgJyc7XG4gICAgICAgICAgICAgICAgaWYoZGltLnZpc2libGUgJiYgZGltLmF4aXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcy50eXBlID0gZGltLmF4aXMudHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjYXNlcyB3aGVyZSBzaG93RGlhZyBhbmQgc2hvd0xvd2VyIG9yIHNob3dVcHBlciBhcmUgZmFsc2VcbiAgICAvLyBubyBzcGVjaWFsIHRyZWF0bWVudCBhcyB0aGUgJ2RyYXduJyB4LWF4ZXMgYW5kIHktYXhlcyBubyBsb25nZXIgbWF0Y2hcbiAgICAvLyB0aGUgZGltZW5zaW9ucyBpdGVtcyBhbmQgeGF4ZXN8eWF4ZXMgMS10by0xXG4gICAgdmFyIG11c3RTaGlmdFggPSAhc2hvd0RpYWcgJiYgIXNob3dMb3dlcjtcbiAgICB2YXIgbXVzdFNoaWZ0WSA9ICFzaG93RGlhZyAmJiAhc2hvd1VwcGVyO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgZGltTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGRpbSA9IGRpbWVuc2lvbnNbaV07XG4gICAgICAgIHZhciBpMCA9IGkgPT09IDA7XG4gICAgICAgIHZhciBpTiA9IGkgPT09IGRpbUxlbmd0aCAtIDE7XG5cbiAgICAgICAgdmFyIHhhSWQgPSAoaTAgJiYgbXVzdFNoaWZ0WCkgfHwgKGlOICYmIG11c3RTaGlmdFkpID9cbiAgICAgICAgICAgIHVuZGVmaW5lZCA6XG4gICAgICAgICAgICB4YXhlc1tpXTtcblxuICAgICAgICB2YXIgeWFJZCA9IChpMCAmJiBtdXN0U2hpZnRZKSB8fCAoaU4gJiYgbXVzdFNoaWZ0WCkgP1xuICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgIHlheGVzW2ldO1xuXG4gICAgICAgIGZpbGxBeGlzU3Rhc2hlcyh4YUlkLCBkaW0sIHhMaXN0KTtcbiAgICAgICAgZmlsbEF4aXNTdGFzaGVzKHlhSWQsIGRpbSwgeUxpc3QpO1xuICAgICAgICBkaWFnW2ldID0gW3hhSWQsIHlhSWRdO1xuICAgIH1cblxuICAgIC8vIGZpbGwgaW4gc3Bsb20gc3VicGxvdCBrZXlzXG4gICAgZm9yKGkgPSAwOyBpIDwgeExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgeUxpc3QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBpZCA9IHhMaXN0W2ldICsgeUxpc3Rbal07XG5cbiAgICAgICAgICAgIGlmKGkgPiBqICYmIHNob3dVcHBlcikge1xuICAgICAgICAgICAgICAgIGxheW91dC5fc3Bsb21TdWJwbG90c1tpZF0gPSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGkgPCBqICYmIHNob3dMb3dlcikge1xuICAgICAgICAgICAgICAgIGxheW91dC5fc3Bsb21TdWJwbG90c1tpZF0gPSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGkgPT09IGogJiYgKHNob3dEaWFnIHx8ICFzaG93TG93ZXIgfHwgIXNob3dVcHBlcikpIHtcbiAgICAgICAgICAgICAgICAvLyBuZWVkIHRvIGluY2x1ZGUgZGlhZ29uYWwgc3VicGxvdHMgd2hlblxuICAgICAgICAgICAgICAgIC8vIGhpZGluZyBvbmUgaGFsZiBhbmQgdGhlIGRpYWdvbmFsXG4gICAgICAgICAgICAgICAgbGF5b3V0Ll9zcGxvbVN1YnBsb3RzW2lkXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB3aGVuIGxvd2VyIGhhbGYgaXMgb21pdHRlZCwgb3Igd2hlbiBqdXN0IHRoZSBkaWFnb25hbCBpcyBnb25lLFxuICAgIC8vIG92ZXJyaWRlIGdyaWQgZGVmYXVsdCB0byBtYWtlIHN1cmUgYXhlcyByZW1haW4gb25cbiAgICAvLyB0aGUgbGVmdC9ib3R0b20gb2YgdGhlIHBsb3QgYXJlYVxuICAgIGlmKCFzaG93TG93ZXIgfHwgKCFzaG93RGlhZyAmJiBzaG93VXBwZXIgJiYgc2hvd0xvd2VyKSkge1xuICAgICAgICBsYXlvdXQuX3NwbG9tR3JpZERmbHQueHNpZGUgPSAnYm90dG9tJztcbiAgICAgICAgbGF5b3V0Ll9zcGxvbUdyaWREZmx0LnlzaWRlID0gJ2xlZnQnO1xuICAgIH1cbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZU1hdHJpeCA9IHJlcXVpcmUoJ3JlZ2wtc3Bsb20nKTtcbnZhciBhcnJheVJhbmdlID0gcmVxdWlyZSgnYXJyYXktcmFuZ2UnKTtcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBHcmlkID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9ncmlkJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhpc0lEcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpO1xuXG52YXIgc3ViVHlwZXMgPSByZXF1aXJlKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgY2FsY01hcmtlclNpemUgPSByZXF1aXJlKCcuLi9zY2F0dGVyL2NhbGMnKS5jYWxjTWFya2VyU2l6ZTtcbnZhciBjYWxjQXhpc0V4cGFuc2lvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNBeGlzRXhwYW5zaW9uO1xudmFyIGNhbGNDb2xvcnNjYWxlcyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgY29udmVydE1hcmtlclNlbGVjdGlvbiA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJnbC9jb252ZXJ0JykubWFya2VyU2VsZWN0aW9uO1xudmFyIGNvbnZlcnRNYXJrZXJTdHlsZSA9IHJlcXVpcmUoJy4uL3NjYXR0ZXJnbC9jb252ZXJ0JykubWFya2VyU3R5bGU7XG52YXIgY2FsY0hvdmVyID0gcmVxdWlyZSgnLi4vc2NhdHRlcmdsJykuY2FsY0hvdmVyO1xuXG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcbnZhciBUT09fTUFOWV9QT0lOVFMgPSByZXF1aXJlKCcuLi9zY2F0dGVyZ2wvY29uc3RhbnRzJykuVE9PX01BTllfUE9JTlRTO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBkaW1lbnNpb25zID0gdHJhY2UuZGltZW5zaW9ucztcbiAgICB2YXIgY29tbW9uTGVuZ3RoID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgb3B0cyA9IHt9O1xuICAgIC8vICdjJyBmb3IgY2FsY3VsYXRlZCwgJ2wnIGZvciBsaW5lYXIsXG4gICAgLy8gb25seSBkaWZmZXIgaGVyZSBmb3IgbG9nIGF4ZXMsIHBhc3MgbGRhdGEgdG8gY3JlYXRlTWF0cml4IGFzICdkYXRhJ1xuICAgIHZhciBjZGF0YSA9IG9wdHMuY2RhdGEgPSBbXTtcbiAgICB2YXIgbGRhdGEgPSBvcHRzLmRhdGEgPSBbXTtcbiAgICAvLyBrZWVwIHRyYWNrIG9mIHZpc2libGUgZGltZW5zaW9uc1xuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcyA9IFtdO1xuICAgIHZhciBpLCBrLCBkaW0sIHhhLCB5YTtcblxuICAgIGZ1bmN0aW9uIG1ha2VDYWxjZGF0YShheCwgZGltKSB7XG4gICAgICAgIC8vIGNhbGwgbWFrZUNhbGNkYXRhIHdpdGggZmFrZSBpbnB1dFxuICAgICAgICB2YXIgY2NvbCA9IGF4Lm1ha2VDYWxjZGF0YSh7XG4gICAgICAgICAgICB2OiBkaW0udmFsdWVzLFxuICAgICAgICAgICAgdmNhbGVuZGFyOiB0cmFjZS5jYWxlbmRhclxuICAgICAgICB9LCAndicpO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjY29sLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBjY29sW2pdID0gY2NvbFtqXSA9PT0gQkFETlVNID8gTmFOIDogY2NvbFtqXTtcbiAgICAgICAgfVxuICAgICAgICBjZGF0YS5wdXNoKGNjb2wpO1xuICAgICAgICBsZGF0YS5wdXNoKGF4LnR5cGUgPT09ICdsb2cnID8gTGliLnNpbXBsZU1hcChjY29sLCBheC5jMmwpIDogY2NvbCk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZGltZW5zaW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaW0gPSBkaW1lbnNpb25zW2ldO1xuXG4gICAgICAgIGlmKGRpbS52aXNpYmxlKSB7XG4gICAgICAgICAgICB4YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVswXSk7XG4gICAgICAgICAgICB5YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVsxXSk7XG5cbiAgICAgICAgICAgIC8vIGlmIGNvcnJlc3BvbmRpbmcgeCAmIHkgYXhlcyBkb24ndCBoYXZlIG1hdGNoaW5nIHR5cGVzLCBza2lwIGRpbVxuICAgICAgICAgICAgaWYoeGEgJiYgeWEgJiYgeGEudHlwZSAhPT0geWEudHlwZSkge1xuICAgICAgICAgICAgICAgIExpYi5sb2coJ1NraXBwaW5nIHNwbG9tIGRpbWVuc2lvbiAnICsgaSArICcgd2l0aCBjb25mbGljdGluZyBheGlzIHR5cGVzJyk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHhhKSB7XG4gICAgICAgICAgICAgICAgbWFrZUNhbGNkYXRhKHhhLCBkaW0pO1xuICAgICAgICAgICAgICAgIGlmKHlhICYmIHlhLnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgICAgICAgICAgeWEuX2NhdGVnb3JpZXMgPSB4YS5fY2F0ZWdvcmllcy5zbGljZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gc2hvdWxkIG5vdCBtYWtlIGl0IGhlcmUsIGlmIGJvdGggeGEgYW5kIHlhIHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIG1ha2VDYWxjZGF0YSh5YSwgZGltKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmlzaWJsZURpbXMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNhbGNDb2xvcnNjYWxlcyh0cmFjZSk7XG4gICAgTGliLmV4dGVuZEZsYXQob3B0cywgY29udmVydE1hcmtlclN0eWxlKHRyYWNlKSk7XG5cbiAgICB2YXIgdmlzaWJsZUxlbmd0aCA9IGNkYXRhLmxlbmd0aDtcbiAgICB2YXIgaGFzVG9vTWFueVBvaW50cyA9ICh2aXNpYmxlTGVuZ3RoICogY29tbW9uTGVuZ3RoKSA+IFRPT19NQU5ZX1BPSU5UUztcblxuICAgIC8vIFJldXNlIFNWRyBzY2F0dGVyIGF4aXMgZXhwYW5zaW9uIHJvdXRpbmUuXG4gICAgLy8gRm9yIGdyYXBocyB3aXRoIHZlcnkgbGFyZ2UgbnVtYmVyIG9mIHBvaW50cyBhbmQgYXJyYXkgbWFya2VyLnNpemUsXG4gICAgLy8gdXNlIGF2ZXJhZ2UgbWFya2VyIHNpemUgaW5zdGVhZCB0byBzcGVlZCB0aGluZ3MgdXAuXG4gICAgdmFyIHBwYWQ7XG4gICAgaWYoaGFzVG9vTWFueVBvaW50cykge1xuICAgICAgICBwcGFkID0gMiAqIChvcHRzLnNpemVBdmcgfHwgTWF0aC5tYXgob3B0cy5zaXplLCAzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcHBhZCA9IGNhbGNNYXJrZXJTaXplKHRyYWNlLCBjb21tb25MZW5ndGgpO1xuICAgIH1cblxuICAgIGZvcihrID0gMDsgayA8IHZpc2libGVEaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGkgPSB2aXNpYmxlRGltc1trXTtcbiAgICAgICAgZGltID0gZGltZW5zaW9uc1tpXTtcbiAgICAgICAgeGEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMF0pIHx8IHt9O1xuICAgICAgICB5YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVsxXSkgfHwge307XG4gICAgICAgIGNhbGNBeGlzRXhwYW5zaW9uKGdkLCB0cmFjZSwgeGEsIHlhLCBjZGF0YVtrXSwgY2RhdGFba10sIHBwYWQpO1xuICAgIH1cblxuICAgIHZhciBzY2VuZSA9IHNjZW5lVXBkYXRlKGdkLCB0cmFjZSk7XG4gICAgaWYoIXNjZW5lLm1hdHJpeCkgc2NlbmUubWF0cml4ID0gdHJ1ZTtcbiAgICBzY2VuZS5tYXRyaXhPcHRpb25zID0gb3B0cztcblxuICAgIHNjZW5lLnNlbGVjdGVkT3B0aW9ucyA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnNlbGVjdGVkKTtcbiAgICBzY2VuZS51bnNlbGVjdGVkT3B0aW9ucyA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnVuc2VsZWN0ZWQpO1xuXG4gICAgcmV0dXJuIFt7eDogZmFsc2UsIHk6IGZhbHNlLCB0OiB7fSwgdHJhY2U6IHRyYWNlfV07XG59XG5cbmZ1bmN0aW9uIHNjZW5lVXBkYXRlKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHVpZCA9IHRyYWNlLnVpZDtcblxuICAgIC8vIG11c3QgcGxhY2UgcmVmIHRvICdzY2VuZScgaW4gZnVsbExheW91dCwgc28gdGhhdDpcbiAgICAvLyAtIGl0IGNhbiBiZSByZWxpbmtlZCBwcm9wZXJseSBvbiB1cGRhdGVzXG4gICAgLy8gLSBpdCBjYW4gYmUgZGVzdHJveWVkIHByb3Blcmx5IHdoZW4gbmVlZGVkXG4gICAgdmFyIHNwbG9tU2NlbmVzID0gZnVsbExheW91dC5fc3Bsb21TY2VuZXM7XG4gICAgaWYoIXNwbG9tU2NlbmVzKSBzcGxvbVNjZW5lcyA9IGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzID0ge307XG5cbiAgICB2YXIgcmVzZXQgPSB7ZGlydHk6IHRydWV9O1xuXG4gICAgdmFyIGZpcnN0ID0ge1xuICAgICAgICBzZWxlY3RCYXRjaDogbnVsbCxcbiAgICAgICAgdW5zZWxlY3RCYXRjaDogbnVsbCxcbiAgICAgICAgbWF0cml4OiBmYWxzZSxcbiAgICAgICAgc2VsZWN0OiBudWxsXG4gICAgfTtcblxuICAgIHZhciBzY2VuZSA9IHNwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG5cbiAgICBpZighc2NlbmUpIHtcbiAgICAgICAgc2NlbmUgPSBzcGxvbVNjZW5lc1t1aWRdID0gTGliLmV4dGVuZEZsYXQoe30sIHJlc2V0LCBmaXJzdCk7XG5cbiAgICAgICAgc2NlbmUuZHJhdyA9IGZ1bmN0aW9uIGRyYXcoKSB7XG4gICAgICAgICAgICBpZihzY2VuZS5tYXRyaXggJiYgc2NlbmUubWF0cml4LmRyYXcpIHtcbiAgICAgICAgICAgICAgICBpZihzY2VuZS5zZWxlY3RCYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBzY2VuZS5tYXRyaXguZHJhdyhzY2VuZS51bnNlbGVjdEJhdGNoLCBzY2VuZS5zZWxlY3RCYXRjaCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUubWF0cml4LmRyYXcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNjZW5lLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNjZW5lIHJlc291cmNlc1xuICAgICAgICBzY2VuZS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICAgIGlmKHNjZW5lLm1hdHJpeCAmJiBzY2VuZS5tYXRyaXguZGVzdHJveSkge1xuICAgICAgICAgICAgICAgIHNjZW5lLm1hdHJpeC5kZXN0cm95KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzY2VuZS5tYXRyaXhPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUgPSBudWxsO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIEluIGNhc2UgaWYgd2UgaGF2ZSBzY2VuZSBmcm9tIHRoZSBsYXN0IGNhbGMgLSByZXNldCBkYXRhXG4gICAgaWYoIXNjZW5lLmRpcnR5KSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHNjZW5lLCByZXNldCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjZW5lO1xufVxuXG5mdW5jdGlvbiBwbG90KGdkLCBfLCBzcGxvbUNhbGNEYXRhKSB7XG4gICAgaWYoIXNwbG9tQ2FsY0RhdGEubGVuZ3RoKSByZXR1cm47XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3Bsb21DYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBwbG90T25lKGdkLCBzcGxvbUNhbGNEYXRhW2ldWzBdKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHBsb3RPbmUoZ2QsIGNkMCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgdmFyIHN0YXNoID0gY2QwLnQ7XG4gICAgdmFyIHNjZW5lID0gZnVsbExheW91dC5fc3Bsb21TY2VuZXNbdHJhY2UudWlkXTtcbiAgICB2YXIgbWF0cml4T3B0cyA9IHNjZW5lLm1hdHJpeE9wdGlvbnM7XG4gICAgdmFyIGNkYXRhID0gbWF0cml4T3B0cy5jZGF0YTtcbiAgICB2YXIgcmVnbCA9IGZ1bGxMYXlvdXQuX2dsY2FudmFzLmRhdGEoKVswXS5yZWdsO1xuICAgIHZhciBkcmFnbW9kZSA9IGZ1bGxMYXlvdXQuZHJhZ21vZGU7XG4gICAgdmFyIHhhLCB5YTtcbiAgICB2YXIgaSwgaiwgaztcblxuICAgIGlmKGNkYXRhLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgLy8gYXVnbWVudCBvcHRpb25zIHdpdGggcHJvcGVyIHVwcGVyL2xvd2VyIGhhbHZlc1xuICAgIC8vIHJlZ2wtc3Bsb20ncyBkZWZhdWx0IGdyaWQgc3RhcnRzIGZyb20gYm90dG9tLWxlZnRcbiAgICBtYXRyaXhPcHRzLmxvd2VyID0gdHJhY2Uuc2hvd3VwcGVyaGFsZjtcbiAgICBtYXRyaXhPcHRzLnVwcGVyID0gdHJhY2Uuc2hvd2xvd2VyaGFsZjtcbiAgICBtYXRyaXhPcHRzLmRpYWdvbmFsID0gdHJhY2UuZGlhZ29uYWwudmlzaWJsZTtcblxuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcztcbiAgICB2YXIgdmlzaWJsZUxlbmd0aCA9IGNkYXRhLmxlbmd0aDtcbiAgICB2YXIgdmlld09wdHMgPSBzY2VuZS52aWV3T3B0cyA9IHt9O1xuICAgIHZpZXdPcHRzLnJhbmdlcyA9IG5ldyBBcnJheSh2aXNpYmxlTGVuZ3RoKTtcbiAgICB2aWV3T3B0cy5kb21haW5zID0gbmV3IEFycmF5KHZpc2libGVMZW5ndGgpO1xuXG4gICAgZm9yKGsgPSAwOyBrIDwgdmlzaWJsZURpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgaSA9IHZpc2libGVEaW1zW2tdO1xuXG4gICAgICAgIHZhciBybmcgPSB2aWV3T3B0cy5yYW5nZXNba10gPSBuZXcgQXJyYXkoNCk7XG4gICAgICAgIHZhciBkbW4gPSB2aWV3T3B0cy5kb21haW5zW2tdID0gbmV3IEFycmF5KDQpO1xuXG4gICAgICAgIHhhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzBdKTtcbiAgICAgICAgaWYoeGEpIHtcbiAgICAgICAgICAgIHJuZ1swXSA9IHhhLl9ybFswXTtcbiAgICAgICAgICAgIHJuZ1syXSA9IHhhLl9ybFsxXTtcbiAgICAgICAgICAgIGRtblswXSA9IHhhLmRvbWFpblswXTtcbiAgICAgICAgICAgIGRtblsyXSA9IHhhLmRvbWFpblsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHlhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzFdKTtcbiAgICAgICAgaWYoeWEpIHtcbiAgICAgICAgICAgIHJuZ1sxXSA9IHlhLl9ybFswXTtcbiAgICAgICAgICAgIHJuZ1szXSA9IHlhLl9ybFsxXTtcbiAgICAgICAgICAgIGRtblsxXSA9IHlhLmRvbWFpblswXTtcbiAgICAgICAgICAgIGRtblszXSA9IHlhLmRvbWFpblsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZpZXdPcHRzLnZpZXdwb3J0ID0gW2dzLmwsIGdzLmIsIGdzLncgKyBncy5sLCBncy5oICsgZ3MuYl07XG5cbiAgICBpZihzY2VuZS5tYXRyaXggPT09IHRydWUpIHtcbiAgICAgICAgc2NlbmUubWF0cml4ID0gY3JlYXRlTWF0cml4KHJlZ2wpO1xuICAgIH1cblxuICAgIHZhciBjbGlja1NlbGVjdEVuYWJsZWQgPSBmdWxsTGF5b3V0LmNsaWNrbW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xO1xuICAgIHZhciBzZWxlY3RNb2RlID0gZHJhZ21vZGUgPT09ICdsYXNzbycgfHwgZHJhZ21vZGUgPT09ICdzZWxlY3QnIHx8XG4gICAgICAhIXRyYWNlLnNlbGVjdGVkcG9pbnRzIHx8IGNsaWNrU2VsZWN0RW5hYmxlZDtcbiAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IG51bGw7XG4gICAgc2NlbmUudW5zZWxlY3RCYXRjaCA9IG51bGw7XG5cbiAgICBpZihzZWxlY3RNb2RlKSB7XG4gICAgICAgIHZhciBjb21tb25MZW5ndGggPSB0cmFjZS5fbGVuZ3RoO1xuXG4gICAgICAgIGlmKCFzY2VuZS5zZWxlY3RCYXRjaCkge1xuICAgICAgICAgICAgc2NlbmUuc2VsZWN0QmF0Y2ggPSBbXTtcbiAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlZ2VuZXJhdGUgc2NlbmUgYmF0Y2gsIGlmIHRyYWNlcyBudW1iZXIgY2hhbmdlZCBkdXJpbmcgc2VsZWN0aW9uXG4gICAgICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgICAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IHRyYWNlLnNlbGVjdGVkcG9pbnRzO1xuXG4gICAgICAgICAgICB2YXIgc2VsUHRzID0gdHJhY2Uuc2VsZWN0ZWRwb2ludHM7XG4gICAgICAgICAgICB2YXIgc2VsRGljdCA9IHt9O1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VsUHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2VsRGljdFtzZWxQdHNbaV1dID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB1bnNlbFB0cyA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY29tbW9uTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZighc2VsRGljdFtpXSkgdW5zZWxQdHMucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSB1bnNlbFB0cztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByZWNhbGN1bGF0ZSBweCBjb29yZHMgc2luY2Ugd2UgYXJlIG5vdCBnb2luZyB0byBwYW4gZHVyaW5nIHNlbGVjdFxuICAgICAgICB2YXIgeHB4ID0gc3Rhc2gueHB4ID0gbmV3IEFycmF5KHZpc2libGVMZW5ndGgpO1xuICAgICAgICB2YXIgeXB4ID0gc3Rhc2gueXB4ID0gbmV3IEFycmF5KHZpc2libGVMZW5ndGgpO1xuXG4gICAgICAgIGZvcihrID0gMDsgayA8IHZpc2libGVEaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBpID0gdmlzaWJsZURpbXNba107XG5cbiAgICAgICAgICAgIHhhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzBdKTtcbiAgICAgICAgICAgIGlmKHhhKSB7XG4gICAgICAgICAgICAgICAgeHB4W2tdID0gbmV3IEFycmF5KGNvbW1vbkxlbmd0aCk7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY29tbW9uTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeHB4W2tdW2pdID0geGEuYzJwKGNkYXRhW2tdW2pdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHlhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzFdKTtcbiAgICAgICAgICAgIGlmKHlhKSB7XG4gICAgICAgICAgICAgICAgeXB4W2tdID0gbmV3IEFycmF5KGNvbW1vbkxlbmd0aCk7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY29tbW9uTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeXB4W2tdW2pdID0geWEuYzJwKGNkYXRhW2tdW2pdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihzY2VuZS5zZWxlY3RCYXRjaCkge1xuICAgICAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZShtYXRyaXhPcHRzLCBtYXRyaXhPcHRzKTtcbiAgICAgICAgICAgIHNjZW5lLm1hdHJpeC51cGRhdGUoc2NlbmUudW5zZWxlY3RlZE9wdGlvbnMsIHNjZW5lLnNlbGVjdGVkT3B0aW9ucyk7XG4gICAgICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKHZpZXdPcHRzLCB2aWV3T3B0cyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBkZWxldGUgc2VsZWN0aW9uIHBhc3NcbiAgICAgICAgICAgIHNjZW5lLm1hdHJpeC51cGRhdGUodmlld09wdHMsIG51bGwpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgb3B0cyA9IExpYi5leHRlbmRGbGF0KHt9LCBtYXRyaXhPcHRzLCB2aWV3T3B0cyk7XG4gICAgICAgIHNjZW5lLm1hdHJpeC51cGRhdGUob3B0cywgbnVsbCk7XG4gICAgICAgIHN0YXNoLnhweCA9IHN0YXNoLnlweCA9IG51bGw7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlZGl0U3R5bGUoZ2QsIGNkMCkge1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICB2YXIgc2NlbmUgPSBnZC5fZnVsbExheW91dC5fc3Bsb21TY2VuZXNbdHJhY2UudWlkXTtcblxuICAgIGlmKHNjZW5lKSB7XG4gICAgICAgIGNhbGNDb2xvcnNjYWxlcyh0cmFjZSk7XG5cbiAgICAgICAgTGliLmV4dGVuZEZsYXQoc2NlbmUubWF0cml4T3B0aW9ucywgY29udmVydE1hcmtlclN0eWxlKHRyYWNlKSk7XG4gICAgICAgIC8vIFRPRE8gW3VuXXNlbGVjdGVkIHN0eWxlcz9cblxuICAgICAgICB2YXIgb3B0cyA9IExpYi5leHRlbmRGbGF0KHt9LCBzY2VuZS5tYXRyaXhPcHRpb25zLCBzY2VuZS52aWV3T3B0cyk7XG5cbiAgICAgICAgLy8gVE9ETyB0aGlzIGlzIHRvbyBsb25nIGZvciBhcnJheU9rIGF0dHJpYnV0ZXMhXG4gICAgICAgIHNjZW5lLm1hdHJpeC51cGRhdGUob3B0cywgbnVsbCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHNjZW5lID0gcG9pbnREYXRhLnNjZW5lO1xuICAgIHZhciBjZGF0YSA9IHNjZW5lLm1hdHJpeE9wdGlvbnMuY2RhdGE7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgeHB4ID0geGEuYzJwKHh2YWwpO1xuICAgIHZhciB5cHggPSB5YS5jMnAoeXZhbCk7XG4gICAgdmFyIG1heERpc3RhbmNlID0gcG9pbnREYXRhLmRpc3RhbmNlO1xuXG4gICAgdmFyIHhpID0gZ2V0RGltSW5kZXgodHJhY2UsIHhhKTtcbiAgICB2YXIgeWkgPSBnZXREaW1JbmRleCh0cmFjZSwgeWEpO1xuICAgIGlmKHhpID09PSBmYWxzZSB8fCB5aSA9PT0gZmFsc2UpIHJldHVybiBbcG9pbnREYXRhXTtcblxuICAgIHZhciB4ID0gY2RhdGFbeGldO1xuICAgIHZhciB5ID0gY2RhdGFbeWldO1xuXG4gICAgdmFyIGlkLCBkeHk7XG4gICAgdmFyIG1pbkRpc3QgPSBtYXhEaXN0YW5jZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwdHggPSB4W2ldO1xuICAgICAgICB2YXIgcHR5ID0geVtpXTtcbiAgICAgICAgdmFyIGR4ID0geGEuYzJwKHB0eCkgLSB4cHg7XG4gICAgICAgIHZhciBkeSA9IHlhLmMycChwdHkpIC0geXB4O1xuICAgICAgICB2YXIgZGlzdCA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG5cbiAgICAgICAgaWYoZGlzdCA8IG1pbkRpc3QpIHtcbiAgICAgICAgICAgIG1pbkRpc3QgPSBkeHkgPSBkaXN0O1xuICAgICAgICAgICAgaWQgPSBpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcG9pbnREYXRhLmluZGV4ID0gaWQ7XG4gICAgcG9pbnREYXRhLmRpc3RhbmNlID0gbWluRGlzdDtcbiAgICBwb2ludERhdGEuZHh5ID0gZHh5O1xuXG4gICAgaWYoaWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFtwb2ludERhdGFdO1xuXG4gICAgY2FsY0hvdmVyKHBvaW50RGF0YSwgeCwgeSwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIFtwb2ludERhdGFdO1xufVxuXG5mdW5jdGlvbiBzZWxlY3RQb2ludHMoc2VhcmNoSW5mbywgc2VsZWN0aW9uVGVzdGVyKSB7XG4gICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgc3Rhc2ggPSBjZFswXS50O1xuICAgIHZhciBzY2VuZSA9IHNlYXJjaEluZm8uc2NlbmU7XG4gICAgdmFyIGNkYXRhID0gc2NlbmUubWF0cml4T3B0aW9ucy5jZGF0YTtcbiAgICB2YXIgeGEgPSBzZWFyY2hJbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHNlYXJjaEluZm8ueWF4aXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuICAgIHZhciBpO1xuXG4gICAgaWYoIXNjZW5lKSByZXR1cm4gc2VsZWN0aW9uO1xuXG4gICAgdmFyIGhhc09ubHlMaW5lcyA9ICghc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgJiYgIXN1YlR5cGVzLmhhc1RleHQodHJhY2UpKTtcbiAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IGhhc09ubHlMaW5lcykgcmV0dXJuIHNlbGVjdGlvbjtcblxuICAgIHZhciB4aSA9IGdldERpbUluZGV4KHRyYWNlLCB4YSk7XG4gICAgdmFyIHlpID0gZ2V0RGltSW5kZXgodHJhY2UsIHlhKTtcbiAgICBpZih4aSA9PT0gZmFsc2UgfHwgeWkgPT09IGZhbHNlKSByZXR1cm4gc2VsZWN0aW9uO1xuXG4gICAgdmFyIHhweCA9IHN0YXNoLnhweFt4aV07XG4gICAgdmFyIHlweCA9IHN0YXNoLnlweFt5aV07XG4gICAgdmFyIHggPSBjZGF0YVt4aV07XG4gICAgdmFyIHkgPSBjZGF0YVt5aV07XG5cbiAgICAvLyBkZWdlbmVyYXRlIHBvbHlnb24gZG9lcyBub3QgZW5hYmxlIHNlbGVjdGlvblxuICAgIC8vIGZpbHRlciBvdXQgcG9pbnRzIGJ5IHZpc2libGUgc2NhdHRlciBvbmVzXG4gICAgdmFyIGVscyA9IG51bGw7XG4gICAgdmFyIHVuZWxzID0gbnVsbDtcbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgIT09IGZhbHNlICYmICFzZWxlY3Rpb25UZXN0ZXIuZGVnZW5lcmF0ZSkge1xuICAgICAgICBlbHMgPSBbXSwgdW5lbHMgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoc2VsZWN0aW9uVGVzdGVyLmNvbnRhaW5zKFt4cHhbaV0sIHlweFtpXV0sIG51bGwsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgZWxzLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgeDogeFtpXSxcbiAgICAgICAgICAgICAgICAgICAgeTogeVtpXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdW5lbHMucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuZWxzID0gYXJyYXlSYW5nZShzdGFzaC5jb3VudCk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIHNlbGVjdEJhdGNoIGlzIGNyZWF0ZWRcbiAgICBpZighc2NlbmUuc2VsZWN0QmF0Y2gpIHtcbiAgICAgICAgc2NlbmUuc2VsZWN0QmF0Y2ggPSBbXTtcbiAgICAgICAgc2NlbmUudW5zZWxlY3RCYXRjaCA9IFtdO1xuICAgIH1cblxuICAgIGlmKCFzY2VuZS5zZWxlY3RCYXRjaCkge1xuICAgICAgICAvLyBlbnRlciBldmVyeSB0cmFjZSBzZWxlY3QgbW9kZVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzY2VuZS5jb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IFtdO1xuICAgICAgICAgICAgc2NlbmUudW5zZWxlY3RCYXRjaCA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIHNob3VsZCB0dXJuIHNjYXR0ZXIyZCBpbnRvIHVuc2VsZWN0ZWQgb25jZSB3ZSBoYXZlIGFueSBwb2ludHMgc2VsZWN0ZWRcbiAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZShzY2VuZS51bnNlbGVjdGVkT3B0aW9ucywgc2NlbmUuc2VsZWN0ZWRPcHRpb25zKTtcbiAgICB9XG5cbiAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IGVscztcbiAgICBzY2VuZS51bnNlbGVjdEJhdGNoID0gdW5lbHM7XG5cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIGdldERpbUluZGV4KHRyYWNlLCBheCkge1xuICAgIHZhciBheElkID0gYXguX2lkO1xuICAgIHZhciBheExldHRlciA9IGF4SWQuY2hhckF0KDApO1xuICAgIHZhciBpbmQgPSB7eDogMCwgeTogMX1bYXhMZXR0ZXJdO1xuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcztcblxuICAgIGZvcih2YXIgayA9IDA7IGsgPCB2aXNpYmxlRGltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICB2YXIgaSA9IHZpc2libGVEaW1zW2tdO1xuICAgICAgICBpZih0cmFjZS5fZGlhZ1tpXVtpbmRdID09PSBheElkKSByZXR1cm4gaztcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdzcGxvbScsXG5cbiAgICBiYXNlUGxvdE1vZHVsZTogcmVxdWlyZSgnLi9iYXNlX3Bsb3QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2dsJywgJ3JlZ2wnLCAnY2FydGVzaWFuJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdzY2F0dGVyLWxpa2UnXSxcblxuICAgIGF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiByZXF1aXJlKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyJyksXG5cbiAgICBjYWxjOiBjYWxjLFxuICAgIHBsb3Q6IHBsb3QsXG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogc2VsZWN0UG9pbnRzLFxuICAgIGVkaXRTdHlsZTogZWRpdFN0eWxlLFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG4vLyBzcGxvbSB0cmFjZXMgdXNlIHRoZSAnZ3JpZCcgY29tcG9uZW50IHRvIGdlbmVyYXRlIHRoZWlyIGF4ZXMsXG4vLyByZWdpc3RlciBpdCBoZXJlXG5SZWdpc3RyeS5yZWdpc3RlcihHcmlkKTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JiYXJBdHRycyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JiYXIvYXR0cmlidXRlcycpO1xudmFyIG1lc2gzZEF0dHJzID0gcmVxdWlyZSgnLi4vbWVzaDNkL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSByZXF1aXJlKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBhdHRycyA9IHtcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHo6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHc6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc3RhcnRzOiB7XG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgeToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB6OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuXG4gICAgbWF4ZGlzcGxheWVkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMDAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIFRPRE9cbiAgICAvL1xuICAgIC8vIFNob3VsZCBhZGQgJ2Fic29sdXRlJyAobGlrZSBjb25lIHRyYWNlcyBoYXZlKSwgYnV0IGN1cnJlbnRseSBnbC1zdHJlYW10dWJlM2Qnc1xuICAgIC8vIGBhYnNvbHV0ZVR1YmVTaXplYCBkb2Vzbid0IGJlaGF2ZSB3ZWxsIGVub3VnaCBmb3Igb3VyIG5lZWRzLlxuICAgIC8vXG4gICAgLy8gJ2ZpeGVkJyB3b3VsZCBiZSBhIG5pY2UgYWRkaXRpb24gdG8gcGxvdCBzdHJlYW0gJ2xpbmVzJywgc2VlXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvY29tbWl0LzgxMmJlMjA3NTBlMjFlMGExODMxOTc1MDAxYzI0OGQzNjU4NTBmNzMjcjI5MTI5ODc3XG4gICAgLy9cbiAgICAvLyBzaXplbW9kZToge1xuICAgIC8vICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgLy8gICAgIHZhbHVlczogWydzY2FsZWQnLCAnYWJzb2x1dGUnLCAnZml4ZWQnXSxcbiAgICAvLyAgICAgZGZsdDogJ3NjYWxlZCcsXG4gICAgLy8gICAgIFxuICAgIC8vICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIC8vICAgICBcbiAgICAvLyB9LFxuXG4gICAgc2l6ZXJlZjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxuZXh0ZW5kRmxhdChhdHRycywgY29sb3JzY2FsZUF0dHJzKCcnLCB7XG4gICAgY29sb3JBdHRyOiAndS92L3cgbm9ybScsXG4gICAgc2hvd1NjYWxlRGZsdDogdHJ1ZSxcbiAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbn0pLCB7XG4gICAgY29sb3JiYXI6IGNvbG9yYmFyQXR0cnNcbn0pO1xuXG52YXIgZnJvbU1lc2gzZCA9IFsnb3BhY2l0eScsICdsaWdodHBvc2l0aW9uJywgJ2xpZ2h0aW5nJ107XG5mcm9tTWVzaDNkLmZvckVhY2goZnVuY3Rpb24oaykge1xuICAgIGF0dHJzW2tdID0gbWVzaDNkQXR0cnNba107XG59KTtcblxuYXR0cnMuaG92ZXJpbmZvID0gZXh0ZW5kRmxhdCh7fSwgYmFzZUF0dHJzLmhvdmVyaW5mbywge1xuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgZmxhZ3M6IFsneCcsICd5JywgJ3onLCAndScsICd2JywgJ3cnLCAnbm9ybScsICdkaXZlcmdlbmNlJywgJ3RleHQnLCAnbmFtZSddLFxuICAgIGRmbHQ6ICd4K3kreitub3JtK3RleHQrbmFtZSdcbn0pO1xuXG5hdHRycy50cmFuc2Zvcm1zID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGF0dHJzO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JzY2FsZUNhbGMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGk7XG5cbiAgICB2YXIgdSA9IHRyYWNlLnU7XG4gICAgdmFyIHYgPSB0cmFjZS52O1xuICAgIHZhciB3ID0gdHJhY2UudztcbiAgICB2YXIgeCA9IHRyYWNlLng7XG4gICAgdmFyIHkgPSB0cmFjZS55O1xuICAgIHZhciB6ID0gdHJhY2UuejtcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oeC5sZW5ndGgsIHkubGVuZ3RoLCB6Lmxlbmd0aCwgdS5sZW5ndGgsIHYubGVuZ3RoLCB3Lmxlbmd0aCk7XG5cbiAgICB2YXIgc2xlbiA9IDA7XG4gICAgdmFyIHN0YXJ0eCwgc3RhcnR5LCBzdGFydHo7XG4gICAgaWYodHJhY2Uuc3RhcnRzKSB7XG4gICAgICAgIHN0YXJ0eCA9IHRyYWNlLnN0YXJ0cy54IHx8IFtdO1xuICAgICAgICBzdGFydHkgPSB0cmFjZS5zdGFydHMueSB8fCBbXTtcbiAgICAgICAgc3RhcnR6ID0gdHJhY2Uuc3RhcnRzLnogfHwgW107XG4gICAgICAgIHNsZW4gPSBNYXRoLm1pbihzdGFydHgubGVuZ3RoLCBzdGFydHkubGVuZ3RoLCBzdGFydHoubGVuZ3RoKTtcbiAgICB9XG5cbiAgICB2YXIgbm9ybU1heCA9IDA7XG4gICAgdmFyIG5vcm1NaW4gPSBJbmZpbml0eTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciB1dSA9IHVbaV07XG4gICAgICAgIHZhciB2diA9IHZbaV07XG4gICAgICAgIHZhciB3dyA9IHdbaV07XG4gICAgICAgIHZhciBub3JtID0gTWF0aC5zcXJ0KHV1ICogdXUgKyB2diAqIHZ2ICsgd3cgKiB3dyk7XG5cbiAgICAgICAgbm9ybU1heCA9IE1hdGgubWF4KG5vcm1NYXgsIG5vcm0pO1xuICAgICAgICBub3JtTWluID0gTWF0aC5taW4obm9ybU1pbiwgbm9ybSk7XG4gICAgfVxuXG4gICAgY29sb3JzY2FsZUNhbGModHJhY2UsIFtub3JtTWluLCBub3JtTWF4XSwgJycsICdjJyk7XG5cbiAgICB2YXIgeE1heCA9IC1JbmZpbml0eTtcbiAgICB2YXIgeE1pbiA9IEluZmluaXR5O1xuICAgIHZhciB5TWF4ID0gLUluZmluaXR5O1xuICAgIHZhciB5TWluID0gSW5maW5pdHk7XG4gICAgdmFyIHpNYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIHpNaW4gPSBJbmZpbml0eTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciB4eCA9IHhbaV07XG4gICAgICAgIHhNYXggPSBNYXRoLm1heCh4TWF4LCB4eCk7XG4gICAgICAgIHhNaW4gPSBNYXRoLm1pbih4TWluLCB4eCk7XG5cbiAgICAgICAgdmFyIHl5ID0geVtpXTtcbiAgICAgICAgeU1heCA9IE1hdGgubWF4KHlNYXgsIHl5KTtcbiAgICAgICAgeU1pbiA9IE1hdGgubWluKHlNaW4sIHl5KTtcblxuICAgICAgICB2YXIgenogPSB6W2ldO1xuICAgICAgICB6TWF4ID0gTWF0aC5tYXgoek1heCwgenopO1xuICAgICAgICB6TWluID0gTWF0aC5taW4oek1pbiwgenopO1xuICAgIH1cbiAgICBmb3IoaSA9IDA7IGkgPCBzbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHN4ID0gc3RhcnR4W2ldO1xuICAgICAgICB4TWF4ID0gTWF0aC5tYXgoeE1heCwgc3gpO1xuICAgICAgICB4TWluID0gTWF0aC5taW4oeE1pbiwgc3gpO1xuXG4gICAgICAgIHZhciBzeSA9IHN0YXJ0eVtpXTtcbiAgICAgICAgeU1heCA9IE1hdGgubWF4KHlNYXgsIHN5KTtcbiAgICAgICAgeU1pbiA9IE1hdGgubWluKHlNaW4sIHN5KTtcblxuICAgICAgICB2YXIgc3ogPSBzdGFydHpbaV07XG4gICAgICAgIHpNYXggPSBNYXRoLm1heCh6TWF4LCBzeik7XG4gICAgICAgIHpNaW4gPSBNYXRoLm1pbih6TWluLCBzeik7XG4gICAgfVxuXG4gICAgdHJhY2UuX2xlbiA9IGxlbjtcbiAgICB0cmFjZS5fc2xlbiA9IHNsZW47XG4gICAgdHJhY2UuX25vcm1NYXggPSBub3JtTWF4O1xuICAgIHRyYWNlLl94Ym5kcyA9IFt4TWluLCB4TWF4XTtcbiAgICB0cmFjZS5feWJuZHMgPSBbeU1pbiwgeU1heF07XG4gICAgdHJhY2UuX3pibmRzID0gW3pNaW4sIHpNYXhdO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHR1YmUybWVzaCA9IHJlcXVpcmUoJ2dsLXN0cmVhbXR1YmUzZCcpO1xudmFyIGNyZWF0ZVR1YmVNZXNoID0gdHViZTJtZXNoLmNyZWF0ZVR1YmVNZXNoO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgcGFyc2VDb2xvclNjYWxlID0gcmVxdWlyZSgnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLnBhcnNlQ29sb3JTY2FsZTtcbnZhciB6aXAzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2wzZC96aXAzJyk7XG5cbnZhciBheGlzTmFtZTJzY2FsZUluZGV4ID0ge3hheGlzOiAwLCB5YXhpczogMSwgemF4aXM6IDJ9O1xuXG5mdW5jdGlvbiBTdHJlYW10dWJlKHNjZW5lLCB1aWQpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG4gICAgdGhpcy5tZXNoID0gbnVsbDtcbiAgICB0aGlzLmRhdGEgPSBudWxsO1xufVxuXG52YXIgcHJvdG8gPSBTdHJlYW10dWJlLnByb3RvdHlwZTtcblxucHJvdG8uaGFuZGxlUGljayA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICAgIHZhciBzY2VuZUxheW91dCA9IHRoaXMuc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuICAgIHZhciBkYXRhU2NhbGUgPSB0aGlzLnNjZW5lLmRhdGFTY2FsZTtcblxuICAgIGZ1bmN0aW9uIGZyb21EYXRhU2NhbGUodiwgYXhpc05hbWUpIHtcbiAgICAgICAgdmFyIGF4ID0gc2NlbmVMYXlvdXRbYXhpc05hbWVdO1xuICAgICAgICB2YXIgc2NhbGUgPSBkYXRhU2NhbGVbYXhpc05hbWUyc2NhbGVJbmRleFtheGlzTmFtZV1dO1xuICAgICAgICByZXR1cm4gYXgubDJjKHYpIC8gc2NhbGU7XG4gICAgfVxuXG4gICAgaWYoc2VsZWN0aW9uLm9iamVjdCA9PT0gdGhpcy5tZXNoKSB7XG4gICAgICAgIHZhciBwb3MgPSBzZWxlY3Rpb24uZGF0YS5wb3NpdGlvbjtcbiAgICAgICAgdmFyIHV2eCA9IHNlbGVjdGlvbi5kYXRhLnZlbG9jaXR5O1xuXG4gICAgICAgIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGUgPSBbXG4gICAgICAgICAgICBmcm9tRGF0YVNjYWxlKHBvc1swXSwgJ3hheGlzJyksXG4gICAgICAgICAgICBmcm9tRGF0YVNjYWxlKHBvc1sxXSwgJ3lheGlzJyksXG4gICAgICAgICAgICBmcm9tRGF0YVNjYWxlKHBvc1syXSwgJ3pheGlzJyksXG5cbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUodXZ4WzBdLCAneGF4aXMnKSxcbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUodXZ4WzFdLCAneWF4aXMnKSxcbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUodXZ4WzJdLCAnemF4aXMnKSxcblxuICAgICAgICAgICAgLy8gdS92L3cgbm9ybVxuICAgICAgICAgICAgc2VsZWN0aW9uLmRhdGEuaW50ZW5zaXR5ICogdGhpcy5kYXRhLl9ub3JtTWF4LFxuICAgICAgICAgICAgLy8gZGl2ZXJnZW5jZVxuICAgICAgICAgICAgc2VsZWN0aW9uLmRhdGEuZGl2ZXJnZW5jZVxuICAgICAgICBdO1xuXG4gICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0aGlzLmRhdGEudGV4dDtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBkaXN0aW5jdFZhbHMoY29sKSB7XG4gICAgcmV0dXJuIExpYi5kaXN0aW5jdFZhbHMoY29sKS52YWxzO1xufVxuXG5mdW5jdGlvbiBnZXREZmx0U3RhcnRpbmdQb3NpdGlvbnModmVjKSB7XG4gICAgdmFyIGxlbiA9IHZlYy5sZW5ndGg7XG4gICAgdmFyIHM7XG5cbiAgICBpZihsZW4gPiAyKSB7XG4gICAgICAgIHMgPSB2ZWMuc2xpY2UoMSwgbGVuIC0gMSk7XG4gICAgfSBlbHNlIGlmKGxlbiA9PT0gMikge1xuICAgICAgICBzID0gWyh2ZWNbMF0gKyB2ZWNbMV0pIC8gMl07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcyA9IHZlYztcbiAgICB9XG4gICAgcmV0dXJuIHM7XG59XG5cbmZ1bmN0aW9uIGdldEJvdW5kUGFkcyh2ZWMpIHtcbiAgICB2YXIgbGVuID0gdmVjLmxlbmd0aDtcbiAgICBpZihsZW4gPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIFswLjUsIDAuNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFt2ZWNbMV0gLSB2ZWNbMF0sIHZlY1tsZW4gLSAxXSAtIHZlY1tsZW4gLSAyXV07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjb252ZXJ0KHNjZW5lLCB0cmFjZSkge1xuICAgIHZhciBzY2VuZUxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dDtcbiAgICB2YXIgZGF0YVNjYWxlID0gc2NlbmUuZGF0YVNjYWxlO1xuICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuO1xuICAgIHZhciB0dWJlT3B0cyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gdG9EYXRhQ29vcmRzKGFyciwgYXhpc05hbWUpIHtcbiAgICAgICAgdmFyIGF4ID0gc2NlbmVMYXlvdXRbYXhpc05hbWVdO1xuICAgICAgICB2YXIgc2NhbGUgPSBkYXRhU2NhbGVbYXhpc05hbWUyc2NhbGVJbmRleFtheGlzTmFtZV1dO1xuICAgICAgICByZXR1cm4gTGliLnNpbXBsZU1hcChhcnIsIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGF4LmQybCh2KSAqIHNjYWxlOyB9KTtcbiAgICB9XG5cbiAgICB0dWJlT3B0cy52ZWN0b3JzID0gemlwMyhcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnUsICd4YXhpcycpLFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UudiwgJ3lheGlzJyksXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS53LCAnemF4aXMnKSxcbiAgICAgICAgbGVuXG4gICAgKTtcblxuICAgIHZhciB2YWxzeCA9IGRpc3RpbmN0VmFscyh0cmFjZS54LnNsaWNlKDAsIGxlbikpO1xuICAgIHZhciB2YWxzeSA9IGRpc3RpbmN0VmFscyh0cmFjZS55LnNsaWNlKDAsIGxlbikpO1xuICAgIHZhciB2YWxzeiA9IGRpc3RpbmN0VmFscyh0cmFjZS56LnNsaWNlKDAsIGxlbikpO1xuXG4gICAgLy8gT3Zlci1zcGVjaWZpZWQgbWVzaCBjYXNlLCB0aGlzIHdvdWxkIGVycm9yIGluIHR1YmUybWVzaFxuICAgIGlmKHZhbHN4Lmxlbmd0aCAqIHZhbHN5Lmxlbmd0aCAqIHZhbHN6Lmxlbmd0aCA+IGxlbikge1xuICAgICAgICByZXR1cm4ge3Bvc2l0aW9uczogW10sIGNlbGxzOiBbXX07XG4gICAgfVxuXG4gICAgdmFyIG1lc2h4ID0gdG9EYXRhQ29vcmRzKHZhbHN4LCAneGF4aXMnKTtcbiAgICB2YXIgbWVzaHkgPSB0b0RhdGFDb29yZHModmFsc3ksICd5YXhpcycpO1xuICAgIHZhciBtZXNoeiA9IHRvRGF0YUNvb3Jkcyh2YWxzeiwgJ3pheGlzJyk7XG5cbiAgICB0dWJlT3B0cy5tZXNoZ3JpZCA9IFttZXNoeCwgbWVzaHksIG1lc2h6XTtcblxuICAgIGlmKHRyYWNlLnN0YXJ0cykge1xuICAgICAgICB2YXIgc2xlbiA9IHRyYWNlLl9zbGVuO1xuICAgICAgICB0dWJlT3B0cy5zdGFydGluZ1Bvc2l0aW9ucyA9IHppcDMoXG4gICAgICAgICAgICB0b0RhdGFDb29yZHModHJhY2Uuc3RhcnRzLnguc2xpY2UoMCwgc2xlbiksICd4YXhpcycpLFxuICAgICAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnN0YXJ0cy55LnNsaWNlKDAsIHNsZW4pLCAneWF4aXMnKSxcbiAgICAgICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS5zdGFydHMuei5zbGljZSgwLCBzbGVuKSwgJ3pheGlzJylcbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEZWZhdWx0IHN0YXJ0aW5nIHBvc2l0aW9uczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gaWYgbGVuPjIsIGN1dCB4eiBwbGFuZSBhdCBtaW4teSxcbiAgICAgICAgLy8gdGFrZXMgYWxsIHgveS96IHB0cyBvbiB0aGF0IHBsYW5lIGV4Y2VwdCB0aG9zZSBvbiB0aGUgZWRnZXNcbiAgICAgICAgLy8gdG8gZ2VuZXJhdGUgXCJ3ZWxsLWRlZmluZWRcIiB0dWJlcyxcbiAgICAgICAgLy9cbiAgICAgICAgLy8gaWYgbGVuPTIsIHRha2UgcG9zaXRpb24gaGFsZndheSBiZXR3ZWVuIHR3byB0aGUgcHRzLFxuICAgICAgICAvL1xuICAgICAgICAvLyBpZiBsZW49MSwgdGFrZSB0aGF0IHB0XG4gICAgICAgIHZhciBzeTAgPSBtZXNoeVswXTtcbiAgICAgICAgdmFyIHN4ID0gZ2V0RGZsdFN0YXJ0aW5nUG9zaXRpb25zKG1lc2h4KTtcbiAgICAgICAgdmFyIHN6ID0gZ2V0RGZsdFN0YXJ0aW5nUG9zaXRpb25zKG1lc2h6KTtcbiAgICAgICAgdmFyIHN0YXJ0aW5nUG9zaXRpb25zID0gbmV3IEFycmF5KHN4Lmxlbmd0aCAqIHN6Lmxlbmd0aCk7XG4gICAgICAgIHZhciBtID0gMDtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3gubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCBzei5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHN0YXJ0aW5nUG9zaXRpb25zW20rK10gPSBbc3hbaV0sIHN5MCwgc3pba11dO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHR1YmVPcHRzLnN0YXJ0aW5nUG9zaXRpb25zID0gc3RhcnRpbmdQb3NpdGlvbnM7XG4gICAgfVxuXG4gICAgdHViZU9wdHMuY29sb3JtYXAgPSBwYXJzZUNvbG9yU2NhbGUodHJhY2UuY29sb3JzY2FsZSk7XG4gICAgdHViZU9wdHMudHViZVNpemUgPSB0cmFjZS5zaXplcmVmO1xuICAgIHR1YmVPcHRzLm1heExlbmd0aCA9IHRyYWNlLm1heGRpc3BsYXllZDtcblxuICAgIC8vIGFkZCBzb21lIHBhZGRpbmcgYXJvdW5kIHRoZSBib3VuZHNcbiAgICAvLyB0byBlLmcuIGFsbG93IHR1YmVzIHN0YXJ0aW5nIGZyb20gYSBzbGljZSBvZiB0aGUgeC95L3ogbWVzaFxuICAgIC8vIHRvIGdvIGJleW9uZCBib3VuZHMgYSBsaXR0bGUgYml0IHcvbyBnZXR0aW5nIGNsaXBwZWRcbiAgICB2YXIgeGJuZHMgPSB0b0RhdGFDb29yZHModHJhY2UuX3hibmRzLCAneGF4aXMnKTtcbiAgICB2YXIgeWJuZHMgPSB0b0RhdGFDb29yZHModHJhY2UuX3libmRzLCAneWF4aXMnKTtcbiAgICB2YXIgemJuZHMgPSB0b0RhdGFDb29yZHModHJhY2UuX3pibmRzLCAnemF4aXMnKTtcbiAgICB2YXIgeHBhZHMgPSBnZXRCb3VuZFBhZHMobWVzaHgpO1xuICAgIHZhciB5cGFkcyA9IGdldEJvdW5kUGFkcyhtZXNoeSk7XG4gICAgdmFyIHpwYWRzID0gZ2V0Qm91bmRQYWRzKG1lc2h6KTtcblxuICAgIHZhciBib3VuZHMgPSBbXG4gICAgICAgIFt4Ym5kc1swXSAtIHhwYWRzWzBdLCB5Ym5kc1swXSAtIHlwYWRzWzBdLCB6Ym5kc1swXSAtIHpwYWRzWzBdXSxcbiAgICAgICAgW3hibmRzWzFdICsgeHBhZHNbMV0sIHlibmRzWzFdICsgeXBhZHNbMV0sIHpibmRzWzFdICsgenBhZHNbMV1dXG4gICAgXTtcblxuICAgIHZhciBtZXNoRGF0YSA9IHR1YmUybWVzaCh0dWJlT3B0cywgYm91bmRzKTtcblxuICAgIC8vIE4uQi4gY21pbi9jbWF4IGNvcnJlc3BvbmQgdG8gdGhlIG1pbi9tYXggdmVjdG9yIG5vcm1cbiAgICAvLyBpbiB0aGUgdS92L3cgYXJyYXlzLCB3aGljaCBpbiBnZW5lcmFsIGlzIE5PVCBlcXVhbCB0byBtYXhcbiAgICAvLyBpbnRlbnNpdHkgdGhhdCBjb2xvcnMgdGhlIHR1YmVzLlxuICAgIG1lc2hEYXRhLnZlcnRleEludGVuc2l0eUJvdW5kcyA9IFt0cmFjZS5jbWluIC8gdHJhY2UuX25vcm1NYXgsIHRyYWNlLmNtYXggLyB0cmFjZS5fbm9ybU1heF07XG5cbiAgICAvLyBwYXNzIGdsLW1lc2gzZCBsaWdodGluZyBhdHRyaWJ1dGVzXG4gICAgdmFyIGxwID0gdHJhY2UubGlnaHRwb3NpdGlvbjtcbiAgICBtZXNoRGF0YS5saWdodFBvc2l0aW9uID0gW2xwLngsIGxwLnksIGxwLnpdO1xuICAgIG1lc2hEYXRhLmFtYmllbnQgPSB0cmFjZS5saWdodGluZy5hbWJpZW50O1xuICAgIG1lc2hEYXRhLmRpZmZ1c2UgPSB0cmFjZS5saWdodGluZy5kaWZmdXNlO1xuICAgIG1lc2hEYXRhLnNwZWN1bGFyID0gdHJhY2UubGlnaHRpbmcuc3BlY3VsYXI7XG4gICAgbWVzaERhdGEucm91Z2huZXNzID0gdHJhY2UubGlnaHRpbmcucm91Z2huZXNzO1xuICAgIG1lc2hEYXRhLmZyZXNuZWwgPSB0cmFjZS5saWdodGluZy5mcmVzbmVsO1xuICAgIG1lc2hEYXRhLm9wYWNpdHkgPSB0cmFjZS5vcGFjaXR5O1xuXG4gICAgLy8gc3Rhc2ggYXV0b3JhbmdlIHBhZCB2YWx1ZVxuICAgIHRyYWNlLl9wYWQgPSBtZXNoRGF0YS50dWJlU2NhbGUgKiB0cmFjZS5zaXplcmVmICogMjtcblxuICAgIHJldHVybiBtZXNoRGF0YTtcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHRoaXMuZGF0YSA9IGRhdGE7XG5cbiAgICB2YXIgbWVzaERhdGEgPSBjb252ZXJ0KHRoaXMuc2NlbmUsIGRhdGEpO1xuICAgIHRoaXMubWVzaC51cGRhdGUobWVzaERhdGEpO1xufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLm1lc2gpO1xuICAgIHRoaXMubWVzaC5kaXNwb3NlKCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVTdHJlYW10dWJlVHJhY2Uoc2NlbmUsIGRhdGEpIHtcbiAgICB2YXIgZ2wgPSBzY2VuZS5nbHBsb3QuZ2w7XG5cbiAgICB2YXIgbWVzaERhdGEgPSBjb252ZXJ0KHNjZW5lLCBkYXRhKTtcbiAgICB2YXIgbWVzaCA9IGNyZWF0ZVR1YmVNZXNoKGdsLCBtZXNoRGF0YSk7XG5cbiAgICB2YXIgc3RyZWFtdHViZSA9IG5ldyBTdHJlYW10dWJlKHNjZW5lLCBkYXRhLnVpZCk7XG4gICAgc3RyZWFtdHViZS5tZXNoID0gbWVzaDtcbiAgICBzdHJlYW10dWJlLmRhdGEgPSBkYXRhO1xuICAgIG1lc2guX3RyYWNlID0gc3RyZWFtdHViZTtcblxuICAgIHNjZW5lLmdscGxvdC5hZGQobWVzaCk7XG5cbiAgICByZXR1cm4gc3RyZWFtdHViZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTdHJlYW10dWJlVHJhY2U7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHUgPSBjb2VyY2UoJ3UnKTtcbiAgICB2YXIgdiA9IGNvZXJjZSgndicpO1xuICAgIHZhciB3ID0gY29lcmNlKCd3Jyk7XG5cbiAgICB2YXIgeCA9IGNvZXJjZSgneCcpO1xuICAgIHZhciB5ID0gY29lcmNlKCd5Jyk7XG4gICAgdmFyIHogPSBjb2VyY2UoJ3onKTtcblxuICAgIGlmKFxuICAgICAgICAhdSB8fCAhdS5sZW5ndGggfHwgIXYgfHwgIXYubGVuZ3RoIHx8ICF3IHx8ICF3Lmxlbmd0aCB8fFxuICAgICAgICAheCB8fCAheC5sZW5ndGggfHwgIXkgfHwgIXkubGVuZ3RoIHx8ICF6IHx8ICF6Lmxlbmd0aFxuICAgICkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3N0YXJ0cy54Jyk7XG4gICAgY29lcmNlKCdzdGFydHMueScpO1xuICAgIGNvZXJjZSgnc3RhcnRzLnonKTtcblxuICAgIGNvZXJjZSgnbWF4ZGlzcGxheWVkJyk7XG4gICAgY29lcmNlKCdzaXplcmVmJyk7XG5cbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLmFtYmllbnQnKTtcbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLmRpZmZ1c2UnKTtcbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLnNwZWN1bGFyJyk7XG4gICAgY29lcmNlKCdsaWdodGluZy5yb3VnaG5lc3MnKTtcbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLmZyZXNuZWwnKTtcbiAgICBjb2VyY2UoJ2xpZ2h0cG9zaXRpb24ueCcpO1xuICAgIGNvZXJjZSgnbGlnaHRwb3NpdGlvbi55Jyk7XG4gICAgY29lcmNlKCdsaWdodHBvc2l0aW9uLnonKTtcblxuICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICcnLCBjTGV0dGVyOiAnYyd9KTtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuXG4gICAgLy8gZGlzYWJsZSAxRCB0cmFuc2Zvcm1zIChmb3Igbm93KVxuICAgIC8vIHgveS96IGFuZCB1L3YvdyBoYXZlIG1hdGNoaW5nIGxlbmd0aHMsXG4gICAgLy8gYnV0IHRoZXkgZG9uJ3QgaGF2ZSB0byBtYXRjaCB3aXRoIHN0YXJ0cy4oeHx5fHopXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdzdHJlYW10dWJlJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2wzZCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wzZCddLFxuXG4gICAgYXR0cmlidXRlczogcmVxdWlyZSgnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IHJlcXVpcmUoJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjoge1xuICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgbWF4OiAnY21heCdcbiAgICB9LFxuICAgIGNhbGM6IHJlcXVpcmUoJy4vY2FsYycpLFxuICAgIHBsb3Q6IHJlcXVpcmUoJy4vY29udmVydCcpLFxuICAgIGV2ZW50RGF0YTogZnVuY3Rpb24ob3V0LCBwdCkge1xuICAgICAgICBvdXQudHViZXggPSBvdXQueDtcbiAgICAgICAgb3V0LnR1YmV5ID0gb3V0Lnk7XG4gICAgICAgIG91dC50dWJleiA9IG91dC56O1xuXG4gICAgICAgIG91dC50dWJldSA9IHB0LnRyYWNlQ29vcmRpbmF0ZVszXTtcbiAgICAgICAgb3V0LnR1YmV2ID0gcHQudHJhY2VDb29yZGluYXRlWzRdO1xuICAgICAgICBvdXQudHViZXcgPSBwdC50cmFjZUNvb3JkaW5hdGVbNV07XG5cbiAgICAgICAgb3V0Lm5vcm0gPSBwdC50cmFjZUNvb3JkaW5hdGVbNl07XG4gICAgICAgIG91dC5kaXZlcmdlbmNlID0gcHQudHJhY2VDb29yZGluYXRlWzddO1xuXG4gICAgICAgIC8vIERvZXMgbm90IGNvcnJlc3BvbmQgdG8gaW5wdXQgeC95L3osIHNvIGRlbGV0ZSB0aGVtXG4gICAgICAgIGRlbGV0ZSBvdXQueDtcbiAgICAgICAgZGVsZXRlIG91dC55O1xuICAgICAgICBkZWxldGUgb3V0Lno7XG5cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9LFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgY29sb3JzY2FsZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcmJhckF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcmJhci9hdHRyaWJ1dGVzJyk7XG52YXIgYmFzZUF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG5mdW5jdGlvbiBtYWtlQ29udG91clByb2pBdHRyKGF4TGV0dGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIG1ha2VDb250b3VyQXR0cihheExldHRlcikge1xuICAgIHJldHVybiB7XG4gICAgICAgIHNob3c6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcHJvamVjdDoge1xuICAgICAgICAgICAgeDogbWFrZUNvbnRvdXJQcm9qQXR0cigneCcpLFxuICAgICAgICAgICAgeTogbWFrZUNvbnRvdXJQcm9qQXR0cigneScpLFxuICAgICAgICAgICAgejogbWFrZUNvbnRvdXJQcm9qQXR0cigneicpXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB1c2Vjb2xvcm1hcDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMSxcbiAgICAgICAgICAgIG1heDogMTYsXG4gICAgICAgICAgICBkZmx0OiAyLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhpZ2hsaWdodDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhpZ2hsaWdodGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBoaWdobGlnaHR3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMSxcbiAgICAgICAgICAgIG1heDogMTYsXG4gICAgICAgICAgICBkZmx0OiAyLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgYXR0cnMgPSBtb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKGV4dGVuZEZsYXQoe1xuICAgIHo6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc3VyZmFjZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgfSxcbn0sXG5cbmNvbG9yc2NhbGVBdHRycygnJywge1xuICAgIGNvbG9yQXR0cjogJ3ogb3Igc3VyZmFjZWNvbG9yJyxcbiAgICBzaG93U2NhbGVEZmx0OiB0cnVlLFxuICAgIGF1dG9Db2xvckRmbHQ6IGZhbHNlLFxuICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xufSksIHtcbiAgICBjb2xvcmJhcjogY29sb3JiYXJBdHRycyxcblxuICAgIGNvbnRvdXJzOiB7XG4gICAgICAgIHg6IG1ha2VDb250b3VyQXR0cigneCcpLFxuICAgICAgICB5OiBtYWtlQ29udG91ckF0dHIoJ3knKSxcbiAgICAgICAgejogbWFrZUNvbnRvdXJBdHRyKCd6JylcbiAgICB9LFxuICAgIGhpZGVzdXJmYWNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGlnaHRwb3NpdGlvbjoge1xuICAgICAgICB4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAtMWU1LFxuICAgICAgICAgICAgbWF4OiAxZTUsXG4gICAgICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAtMWU1LFxuICAgICAgICAgICAgbWF4OiAxZTUsXG4gICAgICAgICAgICBkZmx0OiAxZTQsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgejoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogLTFlNSxcbiAgICAgICAgICAgIG1heDogMWU1LFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxpZ2h0aW5nOiB7XG4gICAgICAgIGFtYmllbnQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEuMCxcbiAgICAgICAgICAgIGRmbHQ6IDAuOCxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkaWZmdXNlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLjAwLFxuICAgICAgICAgICAgbWF4OiAxLjAwLFxuICAgICAgICAgICAgZGZsdDogMC44LFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNwZWN1bGFyOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLjAwLFxuICAgICAgICAgICAgbWF4OiAyLjAwLFxuICAgICAgICAgICAgZGZsdDogMC4wNSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICByb3VnaG5lc3M6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEuMDAsXG4gICAgICAgICAgICBkZmx0OiAwLjUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZnJlc25lbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMC4wMCxcbiAgICAgICAgICAgIG1heDogNS4wMCxcbiAgICAgICAgICAgIGRmbHQ6IDAuMixcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIG9wYWNpdHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIHphdXRvOiBleHRlbmRGbGF0KHt9LCBjb2xvcnNjYWxlQXR0cnMuemF1dG8sIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgem1pbjogZXh0ZW5kRmxhdCh7fSwgY29sb3JzY2FsZUF0dHJzLnptaW4sIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgem1heDogZXh0ZW5kRmxhdCh7fSwgY29sb3JzY2FsZUF0dHJzLnptYXgsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KVxuICAgIH0sXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIGJhc2VBdHRycy5ob3ZlcmluZm8pXG59KSwgJ2NhbGMnLCAnbmVzdGVkJyk7XG5cbmF0dHJzLnguZWRpdFR5cGUgPSBhdHRycy55LmVkaXRUeXBlID0gYXR0cnMuei5lZGl0VHlwZSA9ICdjYWxjK2NsZWFyQXhpc1R5cGVzJztcbmF0dHJzLnRyYW5zZm9ybXMgPSB1bmRlZmluZWQ7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcblxuXG4vLyBDb21wdXRlIGF1dG8teiBhbmQgYXV0b2NvbG9yc2NhbGUgaWYgYXBwbGljYWJsZVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIGlmKHRyYWNlLnN1cmZhY2Vjb2xvcikge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2Uuc3VyZmFjZWNvbG9yLCAnJywgJ2MnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyh0cmFjZSwgdHJhY2UueiwgJycsICdjJyk7XG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlU3VyZmFjZSA9IHJlcXVpcmUoJ2dsLXN1cmZhY2UzZCcpO1xudmFyIG5kYXJyYXkgPSByZXF1aXJlKCduZGFycmF5Jyk7XG52YXIgaG9tb2dyYXBoeSA9IHJlcXVpcmUoJ25kYXJyYXktaG9tb2dyYXBoeScpO1xudmFyIGZpbGwgPSByZXF1aXJlKCduZGFycmF5LWZpbGwnKTtcbnZhciBvcHMgPSByZXF1aXJlKCduZGFycmF5LW9wcycpO1xuXG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG52YXIgcGFyc2VDb2xvclNjYWxlID0gcmVxdWlyZSgnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLnBhcnNlQ29sb3JTY2FsZTtcbnZhciBzdHIyUmdiYUFycmF5ID0gcmVxdWlyZSgnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xuXG52YXIgTUlOX1JFU09MVVRJT04gPSAxMjg7XG5cbmZ1bmN0aW9uIFN1cmZhY2VUcmFjZShzY2VuZSwgc3VyZmFjZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMuc3VyZmFjZSA9IHN1cmZhY2U7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbiAgICB0aGlzLnNob3dDb250b3VyID0gW2ZhbHNlLCBmYWxzZSwgZmFsc2VdO1xuICAgIHRoaXMuZGF0YVNjYWxlID0gMS4wO1xufVxuXG52YXIgcHJvdG8gPSBTdXJmYWNlVHJhY2UucHJvdG90eXBlO1xuXG5wcm90by5oYW5kbGVQaWNrID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gICAgaWYoc2VsZWN0aW9uLm9iamVjdCA9PT0gdGhpcy5zdXJmYWNlKSB7XG4gICAgICAgIHZhciBzZWxlY3RJbmRleCA9IHNlbGVjdGlvbi5pbmRleCA9IFtcbiAgICAgICAgICAgIE1hdGgubWluKFxuICAgICAgICAgICAgICAgIE1hdGgucm91bmQoc2VsZWN0aW9uLmRhdGEuaW5kZXhbMF0gLyB0aGlzLmRhdGFTY2FsZSAtIDEpfDAsXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhLnpbMF0ubGVuZ3RoIC0gMVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIE1hdGgubWluKFxuICAgICAgICAgICAgICAgIE1hdGgucm91bmQoc2VsZWN0aW9uLmRhdGEuaW5kZXhbMV0gLyB0aGlzLmRhdGFTY2FsZSAtIDEpfDAsXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhLnoubGVuZ3RoIC0gMVxuICAgICAgICAgICAgKVxuICAgICAgICBdO1xuICAgICAgICB2YXIgdHJhY2VDb29yZGluYXRlID0gWzAsIDAsIDBdO1xuXG4gICAgICAgIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS54KSkge1xuICAgICAgICAgICAgdHJhY2VDb29yZGluYXRlWzBdID0gc2VsZWN0SW5kZXhbMF07XG4gICAgICAgIH0gZWxzZSBpZihpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS54WzBdKSkge1xuICAgICAgICAgICAgdHJhY2VDb29yZGluYXRlWzBdID0gdGhpcy5kYXRhLnhbc2VsZWN0SW5kZXhbMV1dW3NlbGVjdEluZGV4WzBdXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyYWNlQ29vcmRpbmF0ZVswXSA9IHRoaXMuZGF0YS54W3NlbGVjdEluZGV4WzBdXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS55KSkge1xuICAgICAgICAgICAgdHJhY2VDb29yZGluYXRlWzFdID0gc2VsZWN0SW5kZXhbMV07XG4gICAgICAgIH0gZWxzZSBpZihpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS55WzBdKSkge1xuICAgICAgICAgICAgdHJhY2VDb29yZGluYXRlWzFdID0gdGhpcy5kYXRhLnlbc2VsZWN0SW5kZXhbMV1dW3NlbGVjdEluZGV4WzBdXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyYWNlQ29vcmRpbmF0ZVsxXSA9IHRoaXMuZGF0YS55W3NlbGVjdEluZGV4WzFdXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyYWNlQ29vcmRpbmF0ZVsyXSA9IHRoaXMuZGF0YS56W3NlbGVjdEluZGV4WzFdXVtzZWxlY3RJbmRleFswXV07XG4gICAgICAgIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGUgPSB0cmFjZUNvb3JkaW5hdGU7XG5cbiAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gdGhpcy5zY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgICAgIHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHNjZW5lTGF5b3V0LnhheGlzLmQybCh0cmFjZUNvb3JkaW5hdGVbMF0sIDAsIHRoaXMuZGF0YS54Y2FsZW5kYXIpICogdGhpcy5zY2VuZS5kYXRhU2NhbGVbMF0sXG4gICAgICAgICAgICBzY2VuZUxheW91dC55YXhpcy5kMmwodHJhY2VDb29yZGluYXRlWzFdLCAwLCB0aGlzLmRhdGEueWNhbGVuZGFyKSAqIHRoaXMuc2NlbmUuZGF0YVNjYWxlWzFdLFxuICAgICAgICAgICAgc2NlbmVMYXlvdXQuemF4aXMuZDJsKHRyYWNlQ29vcmRpbmF0ZVsyXSwgMCwgdGhpcy5kYXRhLnpjYWxlbmRhcikgKiB0aGlzLnNjZW5lLmRhdGFTY2FsZVsyXVxuICAgICAgICBdO1xuXG4gICAgICAgIHZhciB0ZXh0ID0gdGhpcy5kYXRhLnRleHQ7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGV4dCkgJiYgdGV4dFtzZWxlY3RJbmRleFsxXV0gJiYgdGV4dFtzZWxlY3RJbmRleFsxXV1bc2VsZWN0SW5kZXhbMF1dICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSB0ZXh0W3NlbGVjdEluZGV4WzFdXVtzZWxlY3RJbmRleFswXV07XG4gICAgICAgIH0gZWxzZSBpZih0ZXh0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGVjdGlvbi5kYXRhLmRhdGFDb29yZGluYXRlID0gc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlLnNsaWNlKCk7XG5cbiAgICAgICAgdGhpcy5zdXJmYWNlLmhpZ2hsaWdodChzZWxlY3Rpb24uZGF0YSk7XG5cbiAgICAgICAgLy8gU25hcCBzcGlrZXMgdG8gZGF0YSBjb29yZGluYXRlXG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnNwaWtlcy5wb3NpdGlvbiA9IHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpc0NvbG9ybWFwQ2lyY3VsYXIoY29sb3JtYXApIHtcbiAgICB2YXIgZmlyc3QgPSBjb2xvcm1hcFswXS5yZ2IsXG4gICAgICAgIGxhc3QgPSBjb2xvcm1hcFtjb2xvcm1hcC5sZW5ndGggLSAxXS5yZ2I7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICBmaXJzdFswXSA9PT0gbGFzdFswXSAmJlxuICAgICAgICBmaXJzdFsxXSA9PT0gbGFzdFsxXSAmJlxuICAgICAgICBmaXJzdFsyXSA9PT0gbGFzdFsyXSAmJlxuICAgICAgICBmaXJzdFszXSA9PT0gbGFzdFszXVxuICAgICk7XG59XG5cbi8vIFBhZCBjb29yZHMgYnkgKzFcbmZ1bmN0aW9uIHBhZEZpZWxkKGZpZWxkKSB7XG4gICAgdmFyIHNoYXBlID0gZmllbGQuc2hhcGU7XG4gICAgdmFyIG5zaGFwZSA9IFtzaGFwZVswXSArIDIsIHNoYXBlWzFdICsgMl07XG4gICAgdmFyIG5maWVsZCA9IG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheShuc2hhcGVbMF0gKiBuc2hhcGVbMV0pLCBuc2hhcGUpO1xuXG4gICAgLy8gQ2VudGVyXG4gICAgb3BzLmFzc2lnbihuZmllbGQubG8oMSwgMSkuaGkoc2hhcGVbMF0sIHNoYXBlWzFdKSwgZmllbGQpO1xuXG4gICAgLy8gRWRnZXNcbiAgICBvcHMuYXNzaWduKG5maWVsZC5sbygxKS5oaShzaGFwZVswXSwgMSksXG4gICAgICAgICAgICAgICAgZmllbGQuaGkoc2hhcGVbMF0sIDEpKTtcbiAgICBvcHMuYXNzaWduKG5maWVsZC5sbygxLCBuc2hhcGVbMV0gLSAxKS5oaShzaGFwZVswXSwgMSksXG4gICAgICAgICAgICAgICAgZmllbGQubG8oMCwgc2hhcGVbMV0gLSAxKS5oaShzaGFwZVswXSwgMSkpO1xuICAgIG9wcy5hc3NpZ24obmZpZWxkLmxvKDAsIDEpLmhpKDEsIHNoYXBlWzFdKSxcbiAgICAgICAgICAgICAgICBmaWVsZC5oaSgxKSk7XG4gICAgb3BzLmFzc2lnbihuZmllbGQubG8obnNoYXBlWzBdIC0gMSwgMSkuaGkoMSwgc2hhcGVbMV0pLFxuICAgICAgICAgICAgICAgIGZpZWxkLmxvKHNoYXBlWzBdIC0gMSkpO1xuXG4gICAgLy8gQ29ybmVyc1xuICAgIG5maWVsZC5zZXQoMCwgMCwgZmllbGQuZ2V0KDAsIDApKTtcbiAgICBuZmllbGQuc2V0KDAsIG5zaGFwZVsxXSAtIDEsIGZpZWxkLmdldCgwLCBzaGFwZVsxXSAtIDEpKTtcbiAgICBuZmllbGQuc2V0KG5zaGFwZVswXSAtIDEsIDAsIGZpZWxkLmdldChzaGFwZVswXSAtIDEsIDApKTtcbiAgICBuZmllbGQuc2V0KG5zaGFwZVswXSAtIDEsIG5zaGFwZVsxXSAtIDEsIGZpZWxkLmdldChzaGFwZVswXSAtIDEsIHNoYXBlWzFdIC0gMSkpO1xuXG4gICAgcmV0dXJuIG5maWVsZDtcbn1cblxuZnVuY3Rpb24gcmVmaW5lKGNvb3Jkcykge1xuICAgIHZhciBtaW5TY2FsZSA9IE1hdGgubWF4KGNvb3Jkc1swXS5zaGFwZVswXSwgY29vcmRzWzBdLnNoYXBlWzFdKTtcblxuICAgIGlmKG1pblNjYWxlIDwgTUlOX1JFU09MVVRJT04pIHtcbiAgICAgICAgdmFyIHNjYWxlRiA9IE1JTl9SRVNPTFVUSU9OIC8gbWluU2NhbGU7XG4gICAgICAgIHZhciBuc2hhcGUgPSBbXG4gICAgICAgICAgICBNYXRoLmZsb29yKChjb29yZHNbMF0uc2hhcGVbMF0pICogc2NhbGVGICsgMSl8MCxcbiAgICAgICAgICAgIE1hdGguZmxvb3IoKGNvb3Jkc1swXS5zaGFwZVsxXSkgKiBzY2FsZUYgKyAxKXwwIF07XG4gICAgICAgIHZhciBuc2l6ZSA9IG5zaGFwZVswXSAqIG5zaGFwZVsxXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICB2YXIgcGFkSW1nID0gcGFkRmllbGQoY29vcmRzW2ldKTtcbiAgICAgICAgICAgIHZhciBzY2FsZWRJbWcgPSBuZGFycmF5KG5ldyBGbG9hdDMyQXJyYXkobnNpemUpLCBuc2hhcGUpO1xuICAgICAgICAgICAgaG9tb2dyYXBoeShzY2FsZWRJbWcsIHBhZEltZywgW3NjYWxlRiwgMCwgMCxcbiAgICAgICAgICAgICAgICAwLCBzY2FsZUYsIDAsXG4gICAgICAgICAgICAgICAgMCwgMCwgMV0pO1xuICAgICAgICAgICAgY29vcmRzW2ldID0gc2NhbGVkSW1nO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNjYWxlRjtcbiAgICB9XG5cbiAgICByZXR1cm4gMS4wO1xufVxuXG5wcm90by5zZXRDb250b3VyTGV2ZWxzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG5sZXZlbHMgPSBbW10sIFtdLCBbXV07XG4gICAgdmFyIG5lZWRzVXBkYXRlID0gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGlmKHRoaXMuc2hvd0NvbnRvdXJbaV0pIHtcbiAgICAgICAgICAgIG5lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIG5sZXZlbHNbaV0gPSB0aGlzLnNjZW5lLmNvbnRvdXJMZXZlbHNbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihuZWVkc1VwZGF0ZSkge1xuICAgICAgICB0aGlzLnN1cmZhY2UudXBkYXRlKHsgbGV2ZWxzOiBubGV2ZWxzIH0pO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgc2NlbmUgPSB0aGlzLnNjZW5lLFxuICAgICAgICBzY2VuZUxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dCxcbiAgICAgICAgc3VyZmFjZSA9IHRoaXMuc3VyZmFjZSxcbiAgICAgICAgYWxwaGEgPSBkYXRhLm9wYWNpdHksXG4gICAgICAgIGNvbG9ybWFwID0gcGFyc2VDb2xvclNjYWxlKGRhdGEuY29sb3JzY2FsZSwgYWxwaGEpLFxuICAgICAgICB6ID0gZGF0YS56LFxuICAgICAgICB4ID0gZGF0YS54LFxuICAgICAgICB5ID0gZGF0YS55LFxuICAgICAgICB4YXhpcyA9IHNjZW5lTGF5b3V0LnhheGlzLFxuICAgICAgICB5YXhpcyA9IHNjZW5lTGF5b3V0LnlheGlzLFxuICAgICAgICB6YXhpcyA9IHNjZW5lTGF5b3V0LnpheGlzLFxuICAgICAgICBzY2FsZUZhY3RvciA9IHNjZW5lLmRhdGFTY2FsZSxcbiAgICAgICAgeGxlbiA9IHpbMF0ubGVuZ3RoLFxuICAgICAgICB5bGVuID0gZGF0YS5feWxlbmd0aCxcbiAgICAgICAgY29vcmRzID0gW1xuICAgICAgICAgICAgbmRhcnJheShuZXcgRmxvYXQzMkFycmF5KHhsZW4gKiB5bGVuKSwgW3hsZW4sIHlsZW5dKSxcbiAgICAgICAgICAgIG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheSh4bGVuICogeWxlbiksIFt4bGVuLCB5bGVuXSksXG4gICAgICAgICAgICBuZGFycmF5KG5ldyBGbG9hdDMyQXJyYXkoeGxlbiAqIHlsZW4pLCBbeGxlbiwgeWxlbl0pXG4gICAgICAgIF0sXG4gICAgICAgIHhjID0gY29vcmRzWzBdLFxuICAgICAgICB5YyA9IGNvb3Jkc1sxXSxcbiAgICAgICAgY29udG91ckxldmVscyA9IHNjZW5lLmNvbnRvdXJMZXZlbHM7XG5cbiAgICAvLyBTYXZlIGRhdGFcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuXG4gICAgLypcbiAgICAgKiBGaWxsIGFuZCB0cmFuc3Bvc2UgemRhdGEuXG4gICAgICogQ29uc2lzdGVudCB3aXRoICdoZWF0bWFwJyBhbmQgJ2NvbnRvdXInLCBwbG90bHkgJ3N1cmZhY2UnXG4gICAgICogJ3onIGFyZSBzdWNoIHRoYXQgc3ViLWFycmF5cyBjb3JyZXNwb25kIHRvIHktY29vcmRzXG4gICAgICogYW5kIHRoYXQgdGhlIHN1Yi1hcnJheSBlbnRyaWVzIGNvcnJlc3BvbmQgdG8gYSB4LWNvb3JkcyxcbiAgICAgKiB3aGljaCBpcyB0aGUgdHJhbnNwb3NlIG9mICdnbC1zdXJmYWNlLXBsb3QnLlxuICAgICAqL1xuXG4gICAgdmFyIHhjYWxlbmRhciA9IGRhdGEueGNhbGVuZGFyLFxuICAgICAgICB5Y2FsZW5kYXIgPSBkYXRhLnljYWxlbmRhcixcbiAgICAgICAgemNhbGVuZGFyID0gZGF0YS56Y2FsZW5kYXI7XG5cbiAgICBmaWxsKGNvb3Jkc1syXSwgZnVuY3Rpb24ocm93LCBjb2wpIHtcbiAgICAgICAgcmV0dXJuIHpheGlzLmQybCh6W2NvbF1bcm93XSwgMCwgemNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzJdO1xuICAgIH0pO1xuXG4gICAgLy8gY29vcmRzIHhcbiAgICBpZighaXNBcnJheU9yVHlwZWRBcnJheSh4KSkge1xuICAgICAgICBmaWxsKHhjLCBmdW5jdGlvbihyb3cpIHtcbiAgICAgICAgICAgIHJldHVybiB4YXhpcy5kMmwocm93LCAwLCB4Y2FsZW5kYXIpICogc2NhbGVGYWN0b3JbMF07XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZihpc0FycmF5T3JUeXBlZEFycmF5KHhbMF0pKSB7XG4gICAgICAgIGZpbGwoeGMsIGZ1bmN0aW9uKHJvdywgY29sKSB7XG4gICAgICAgICAgICByZXR1cm4geGF4aXMuZDJsKHhbY29sXVtyb3ddLCAwLCB4Y2FsZW5kYXIpICogc2NhbGVGYWN0b3JbMF07XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRpY2tzIHhcbiAgICAgICAgZmlsbCh4YywgZnVuY3Rpb24ocm93KSB7XG4gICAgICAgICAgICByZXR1cm4geGF4aXMuZDJsKHhbcm93XSwgMCwgeGNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzBdO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBjb29yZHMgeVxuICAgIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KHgpKSB7XG4gICAgICAgIGZpbGwoeWMsIGZ1bmN0aW9uKHJvdywgY29sKSB7XG4gICAgICAgICAgICByZXR1cm4geWF4aXMuZDJsKGNvbCwgMCwgeGNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzFdO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYoaXNBcnJheU9yVHlwZWRBcnJheSh5WzBdKSkge1xuICAgICAgICBmaWxsKHljLCBmdW5jdGlvbihyb3csIGNvbCkge1xuICAgICAgICAgICAgcmV0dXJuIHlheGlzLmQybCh5W2NvbF1bcm93XSwgMCwgeWNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzFdO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aWNrcyB5XG4gICAgICAgIGZpbGwoeWMsIGZ1bmN0aW9uKHJvdywgY29sKSB7XG4gICAgICAgICAgICByZXR1cm4geWF4aXMuZDJsKHlbY29sXSwgMCwgeWNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzFdO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBjb2xvcm1hcDogY29sb3JtYXAsXG4gICAgICAgIGxldmVsczogW1tdLCBbXSwgW11dLFxuICAgICAgICBzaG93Q29udG91cjogW3RydWUsIHRydWUsIHRydWVdLFxuICAgICAgICBzaG93U3VyZmFjZTogIWRhdGEuaGlkZXN1cmZhY2UsXG4gICAgICAgIGNvbnRvdXJQcm9qZWN0OiBbXG4gICAgICAgICAgICBbZmFsc2UsIGZhbHNlLCBmYWxzZV0sXG4gICAgICAgICAgICBbZmFsc2UsIGZhbHNlLCBmYWxzZV0sXG4gICAgICAgICAgICBbZmFsc2UsIGZhbHNlLCBmYWxzZV1cbiAgICAgICAgXSxcbiAgICAgICAgY29udG91cldpZHRoOiBbMSwgMSwgMV0sXG4gICAgICAgIGNvbnRvdXJDb2xvcjogW1sxLCAxLCAxLCAxXSwgWzEsIDEsIDEsIDFdLCBbMSwgMSwgMSwgMV1dLFxuICAgICAgICBjb250b3VyVGludDogWzEsIDEsIDFdLFxuICAgICAgICBkeW5hbWljQ29sb3I6IFtbMSwgMSwgMSwgMV0sIFsxLCAxLCAxLCAxXSwgWzEsIDEsIDEsIDFdXSxcbiAgICAgICAgZHluYW1pY1dpZHRoOiBbMSwgMSwgMV0sXG4gICAgICAgIGR5bmFtaWNUaW50OiBbMSwgMSwgMV0sXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eVxuICAgIH07XG5cbiAgICBwYXJhbXMuaW50ZW5zaXR5Qm91bmRzID0gW2RhdGEuY21pbiwgZGF0YS5jbWF4XTtcblxuICAgIC8vIFJlZmluZSBpZiBuZWNlc3NhcnlcbiAgICBpZihkYXRhLnN1cmZhY2Vjb2xvcikge1xuICAgICAgICB2YXIgaW50ZW5zaXR5ID0gbmRhcnJheShuZXcgRmxvYXQzMkFycmF5KHhsZW4gKiB5bGVuKSwgW3hsZW4sIHlsZW5dKTtcblxuICAgICAgICBmaWxsKGludGVuc2l0eSwgZnVuY3Rpb24ocm93LCBjb2wpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhLnN1cmZhY2Vjb2xvcltjb2xdW3Jvd107XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvb3Jkcy5wdXNoKGludGVuc2l0eSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyB3aGVuICd6JyBpcyB1c2VkIGFzICdpbnRlbnNpdHknLFxuICAgICAgICAvLyB3ZSBtdXN0IHNjYWxlIGl0cyB2YWx1ZVxuICAgICAgICBwYXJhbXMuaW50ZW5zaXR5Qm91bmRzWzBdICo9IHNjYWxlRmFjdG9yWzJdO1xuICAgICAgICBwYXJhbXMuaW50ZW5zaXR5Qm91bmRzWzFdICo9IHNjYWxlRmFjdG9yWzJdO1xuICAgIH1cblxuICAgIHRoaXMuZGF0YVNjYWxlID0gcmVmaW5lKGNvb3Jkcyk7XG5cbiAgICBpZihkYXRhLnN1cmZhY2Vjb2xvcikge1xuICAgICAgICBwYXJhbXMuaW50ZW5zaXR5ID0gY29vcmRzLnBvcCgpO1xuICAgIH1cblxuICAgIHZhciBoaWdobGlnaHRFbmFibGUgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZV07XG4gICAgdmFyIGF4aXMgPSBbJ3gnLCAneScsICd6J107XG5cbiAgICBmb3IoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgdmFyIGNvbnRvdXJQYXJhbXMgPSBkYXRhLmNvbnRvdXJzW2F4aXNbaV1dO1xuICAgICAgICBoaWdobGlnaHRFbmFibGVbaV0gPSBjb250b3VyUGFyYW1zLmhpZ2hsaWdodDtcblxuICAgICAgICBwYXJhbXMuc2hvd0NvbnRvdXJbaV0gPSBjb250b3VyUGFyYW1zLnNob3cgfHwgY29udG91clBhcmFtcy5oaWdobGlnaHQ7XG4gICAgICAgIGlmKCFwYXJhbXMuc2hvd0NvbnRvdXJbaV0pIGNvbnRpbnVlO1xuXG4gICAgICAgIHBhcmFtcy5jb250b3VyUHJvamVjdFtpXSA9IFtcbiAgICAgICAgICAgIGNvbnRvdXJQYXJhbXMucHJvamVjdC54LFxuICAgICAgICAgICAgY29udG91clBhcmFtcy5wcm9qZWN0LnksXG4gICAgICAgICAgICBjb250b3VyUGFyYW1zLnByb2plY3QuelxuICAgICAgICBdO1xuXG4gICAgICAgIGlmKGNvbnRvdXJQYXJhbXMuc2hvdykge1xuICAgICAgICAgICAgdGhpcy5zaG93Q29udG91cltpXSA9IHRydWU7XG4gICAgICAgICAgICBwYXJhbXMubGV2ZWxzW2ldID0gY29udG91ckxldmVsc1tpXTtcbiAgICAgICAgICAgIHN1cmZhY2UuaGlnaGxpZ2h0Q29sb3JbaV0gPSBwYXJhbXMuY29udG91ckNvbG9yW2ldID0gc3RyMlJnYmFBcnJheShjb250b3VyUGFyYW1zLmNvbG9yKTtcblxuICAgICAgICAgICAgaWYoY29udG91clBhcmFtcy51c2Vjb2xvcm1hcCkge1xuICAgICAgICAgICAgICAgIHN1cmZhY2UuaGlnaGxpZ2h0VGludFtpXSA9IHBhcmFtcy5jb250b3VyVGludFtpXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdXJmYWNlLmhpZ2hsaWdodFRpbnRbaV0gPSBwYXJhbXMuY29udG91clRpbnRbaV0gPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyYW1zLmNvbnRvdXJXaWR0aFtpXSA9IGNvbnRvdXJQYXJhbXMud2lkdGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNob3dDb250b3VyW2ldID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjb250b3VyUGFyYW1zLmhpZ2hsaWdodCkge1xuICAgICAgICAgICAgcGFyYW1zLmR5bmFtaWNDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoY29udG91clBhcmFtcy5oaWdobGlnaHRjb2xvcik7XG4gICAgICAgICAgICBwYXJhbXMuZHluYW1pY1dpZHRoW2ldID0gY29udG91clBhcmFtcy5oaWdobGlnaHR3aWR0aDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvOTQwXG4gICAgaWYoaXNDb2xvcm1hcENpcmN1bGFyKGNvbG9ybWFwKSkge1xuICAgICAgICBwYXJhbXMudmVydGV4Q29sb3IgPSB0cnVlO1xuICAgIH1cblxuICAgIHBhcmFtcy5jb29yZHMgPSBjb29yZHM7XG5cbiAgICBzdXJmYWNlLnVwZGF0ZShwYXJhbXMpO1xuXG4gICAgc3VyZmFjZS52aXNpYmxlID0gZGF0YS52aXNpYmxlO1xuICAgIHN1cmZhY2UuZW5hYmxlRHluYW1pYyA9IGhpZ2hsaWdodEVuYWJsZTtcbiAgICBzdXJmYWNlLmVuYWJsZUhpZ2hsaWdodCA9IGhpZ2hsaWdodEVuYWJsZTtcblxuICAgIHN1cmZhY2Uuc25hcFRvRGF0YSA9IHRydWU7XG5cbiAgICBpZignbGlnaHRpbmcnIGluIGRhdGEpIHtcbiAgICAgICAgc3VyZmFjZS5hbWJpZW50TGlnaHQgPSBkYXRhLmxpZ2h0aW5nLmFtYmllbnQ7XG4gICAgICAgIHN1cmZhY2UuZGlmZnVzZUxpZ2h0ID0gZGF0YS5saWdodGluZy5kaWZmdXNlO1xuICAgICAgICBzdXJmYWNlLnNwZWN1bGFyTGlnaHQgPSBkYXRhLmxpZ2h0aW5nLnNwZWN1bGFyO1xuICAgICAgICBzdXJmYWNlLnJvdWdobmVzcyA9IGRhdGEubGlnaHRpbmcucm91Z2huZXNzO1xuICAgICAgICBzdXJmYWNlLmZyZXNuZWwgPSBkYXRhLmxpZ2h0aW5nLmZyZXNuZWw7XG4gICAgfVxuXG4gICAgaWYoJ2xpZ2h0cG9zaXRpb24nIGluIGRhdGEpIHtcbiAgICAgICAgc3VyZmFjZS5saWdodFBvc2l0aW9uID0gW2RhdGEubGlnaHRwb3NpdGlvbi54LCBkYXRhLmxpZ2h0cG9zaXRpb24ueSwgZGF0YS5saWdodHBvc2l0aW9uLnpdO1xuICAgIH1cblxuICAgIGlmKGFscGhhICYmIGFscGhhIDwgMSkge1xuICAgICAgICBzdXJmYWNlLnN1cHBvcnRzVHJhbnNwYXJlbmN5ID0gdHJ1ZTtcbiAgICB9XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMuc3VyZmFjZSk7XG4gICAgdGhpcy5zdXJmYWNlLmRpc3Bvc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZVN1cmZhY2VUcmFjZShzY2VuZSwgZGF0YSkge1xuICAgIHZhciBnbCA9IHNjZW5lLmdscGxvdC5nbDtcbiAgICB2YXIgc3VyZmFjZSA9IGNyZWF0ZVN1cmZhY2UoeyBnbDogZ2wgfSk7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBTdXJmYWNlVHJhY2Uoc2NlbmUsIHN1cmZhY2UsIGRhdGEudWlkKTtcbiAgICBzdXJmYWNlLl90cmFjZSA9IHJlc3VsdDtcbiAgICByZXN1bHQudXBkYXRlKGRhdGEpO1xuICAgIHNjZW5lLmdscGxvdC5hZGQoc3VyZmFjZSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTdXJmYWNlVHJhY2U7XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIHZhciBpLCBqO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG4gICAgaWYoIXopIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICBjb2VyY2UoJ3knKTtcblxuICAgIHRyYWNlT3V0Ll94bGVuZ3RoID0gKEFycmF5LmlzQXJyYXkoeCkgJiYgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoeFswXSkpID8gei5sZW5ndGggOiB6WzBdLmxlbmd0aDtcbiAgICB0cmFjZU91dC5feWxlbmd0aCA9IHoubGVuZ3RoO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4JywgJ3knLCAneiddLCBsYXlvdXQpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG5cbiAgICAvLyBDb2VyY2UgcmVtYWluaW5nIHByb3BlcnRpZXNcbiAgICBbXG4gICAgICAgICdsaWdodGluZy5hbWJpZW50JyxcbiAgICAgICAgJ2xpZ2h0aW5nLmRpZmZ1c2UnLFxuICAgICAgICAnbGlnaHRpbmcuc3BlY3VsYXInLFxuICAgICAgICAnbGlnaHRpbmcucm91Z2huZXNzJyxcbiAgICAgICAgJ2xpZ2h0aW5nLmZyZXNuZWwnLFxuICAgICAgICAnbGlnaHRwb3NpdGlvbi54JyxcbiAgICAgICAgJ2xpZ2h0cG9zaXRpb24ueScsXG4gICAgICAgICdsaWdodHBvc2l0aW9uLnonLFxuICAgICAgICAnaGlkZXN1cmZhY2UnLFxuICAgICAgICAnb3BhY2l0eSdcbiAgICBdLmZvckVhY2goZnVuY3Rpb24oeCkgeyBjb2VyY2UoeCk7IH0pO1xuXG4gICAgdmFyIHN1cmZhY2VDb2xvciA9IGNvZXJjZSgnc3VyZmFjZWNvbG9yJyk7XG5cbiAgICBjb2VyY2UoJ2NvbG9yc2NhbGUnKTtcblxuICAgIHZhciBkaW1zID0gWyd4JywgJ3knLCAneiddO1xuICAgIGZvcihpID0gMDsgaSA8IDM7ICsraSkge1xuXG4gICAgICAgIHZhciBjb250b3VyRGltID0gJ2NvbnRvdXJzLicgKyBkaW1zW2ldO1xuICAgICAgICB2YXIgc2hvdyA9IGNvZXJjZShjb250b3VyRGltICsgJy5zaG93Jyk7XG4gICAgICAgIHZhciBoaWdobGlnaHQgPSBjb2VyY2UoY29udG91ckRpbSArICcuaGlnaGxpZ2h0Jyk7XG5cbiAgICAgICAgaWYoc2hvdyB8fCBoaWdobGlnaHQpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICAgICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5wcm9qZWN0LicgKyBkaW1zW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNob3cpIHtcbiAgICAgICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5jb2xvcicpO1xuICAgICAgICAgICAgY29lcmNlKGNvbnRvdXJEaW0gKyAnLndpZHRoJyk7XG4gICAgICAgICAgICBjb2VyY2UoY29udG91ckRpbSArICcudXNlY29sb3JtYXAnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhpZ2hsaWdodCkge1xuICAgICAgICAgICAgY29lcmNlKGNvbnRvdXJEaW0gKyAnLmhpZ2hsaWdodGNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoY29udG91ckRpbSArICcuaGlnaGxpZ2h0d2lkdGgnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgYmxvY2tcbiAgICBpZighc3VyZmFjZUNvbG9yKSB7XG4gICAgICAgIG1hcExlZ2FjeSh0cmFjZUluLCAnem1pbicsICdjbWluJyk7XG4gICAgICAgIG1hcExlZ2FjeSh0cmFjZUluLCAnem1heCcsICdjbWF4Jyk7XG4gICAgICAgIG1hcExlZ2FjeSh0cmFjZUluLCAnemF1dG8nLCAnY2F1dG8nKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIGlmIGNvbnRvdXJzLj8udXNlY29sb3JtYXAgYXJlIGZhbHNlIGFuZCBoaWRlc3VyZmFjZSBpcyB0cnVlXG4gICAgLy8gdGhlIGNvbG9yYmFyIHNob3VsZG4ndCBiZSBzaG93biBieSBkZWZhdWx0XG5cbiAgICBjb2xvcnNjYWxlRGVmYXVsdHMoXG4gICAgICAgIHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICdjJ31cbiAgICApO1xuXG4gICAgLy8gZGlzYWJsZSAxRCB0cmFuc2Zvcm1zIC0gY3VycmVudGx5IHN1cmZhY2UgZG9lcyBOT1Qgc3VwcG9ydCBjb2x1bW4gZGF0YSBsaWtlIGhlYXRtYXAgZG9lc1xuICAgIC8vIHlvdSBjYW4gdXNlIG1lc2gzZCBmb3IgdGhpcyB1c2UgY2FzZSwgYnV0IG5vdCBzdXJmYWNlXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuXG5mdW5jdGlvbiBtYXBMZWdhY3kodHJhY2VJbiwgb2xkQXR0ciwgbmV3QXR0cikge1xuICAgIGlmKG9sZEF0dHIgaW4gdHJhY2VJbiAmJiAhKG5ld0F0dHIgaW4gdHJhY2VJbikpIHtcbiAgICAgICAgdHJhY2VJbltuZXdBdHRyXSA9IHRyYWNlSW5bb2xkQXR0cl07XG4gICAgfVxufVxuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBTdXJmYWNlID0ge307XG5cblN1cmZhY2UuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuU3VyZmFjZS5zdXBwbHlEZWZhdWx0cyA9IHJlcXVpcmUoJy4vZGVmYXVsdHMnKTtcblN1cmZhY2UuY29sb3JiYXIgPSB7XG4gICAgbWluOiAnY21pbicsXG4gICAgbWF4OiAnY21heCdcbn07XG5TdXJmYWNlLmNhbGMgPSByZXF1aXJlKCcuL2NhbGMnKTtcblN1cmZhY2UucGxvdCA9IHJlcXVpcmUoJy4vY29udmVydCcpO1xuXG5TdXJmYWNlLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuU3VyZmFjZS5uYW1lID0gJ3N1cmZhY2UnO1xuU3VyZmFjZS5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2dsM2QnKTtcblN1cmZhY2UuY2F0ZWdvcmllcyA9IFsnZ2wzZCcsICcyZE1hcCcsICdub09wYWNpdHknXTtcblN1cmZhY2UubWV0YSA9IHtcbiAgICBcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU3VyZmFjZTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGFubkF0dHJzID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9hbm5vdGF0aW9ucy9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gcmVxdWlyZSgnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGZvbnRBdHRycyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcblxudmFyIGF0dHJzID0gbW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3RhYmxlJywgdHJhY2U6IHRydWV9KSxcblxuICAgIGNvbHVtbndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGNvbHVtbm9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBoZWFkZXI6IHtcblxuICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBmb3JtYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBwcmVmaXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHN1ZmZpeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IDI4LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBhbGlnbjogZXh0ZW5kRmxhdCh7fSwgYW5uQXR0cnMuYWxpZ24sIHthcnJheU9rOiB0cnVlfSksXG5cbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgZGZsdDogJ2dyZXknLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGZpbGw6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICd3aGl0ZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZm9udDogZXh0ZW5kRmxhdCh7fSwgZm9udEF0dHJzKHthcnJheU9rOiB0cnVlfSkpXG4gICAgfSxcblxuICAgIGNlbGxzOiB7XG5cbiAgICAgICAgdmFsdWVzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgcHJlZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBzdWZmaXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGhlaWdodDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAyMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgYWxpZ246IGV4dGVuZEZsYXQoe30sIGFubkF0dHJzLmFsaWduLCB7YXJyYXlPazogdHJ1ZX0pLFxuXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdncmV5JyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiAnd2hpdGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGZvbnQ6IGV4dGVuZEZsYXQoe30sIGZvbnRBdHRycyh7YXJyYXlPazogdHJ1ZX0pKVxuICAgIH1cbn0sICdjYWxjJywgJ2Zyb20tcm9vdCcpO1xuYXR0cnMudHJhbnNmb3JtcyA9IHVuZGVmaW5lZDtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gcmVxdWlyZSgnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcbnZhciB0YWJsZVBsb3QgPSByZXF1aXJlKCcuL3Bsb3QnKTtcblxudmFyIFRBQkxFID0gJ3RhYmxlJztcblxuZXhwb3J0cy5uYW1lID0gVEFCTEU7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsIFRBQkxFKVswXTtcbiAgICBpZihjYWxjRGF0YS5sZW5ndGgpIHRhYmxlUGxvdChnZCwgY2FsY0RhdGEpO1xufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBoYWRUYWJsZSA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKFRBQkxFKSk7XG4gICAgdmFyIGhhc1RhYmxlID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoVEFCTEUpKTtcblxuICAgIGlmKGhhZFRhYmxlICYmICFoYXNUYWJsZSkge1xuICAgICAgICBvbGRGdWxsTGF5b3V0Ll9wYXBlcmRpdi5zZWxlY3RBbGwoJy50YWJsZScpLnJlbW92ZSgpO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB3cmFwID0gcmVxdWlyZSgnLi4vLi4vbGliL2d1cCcpLndyYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYygpIHtcbiAgICAvLyB3ZSBkb24ndCBhY3R1YWxseSBuZWVkIHRvIGluY2x1ZGUgdGhlIHRyYWNlIGhlcmUsIHNpbmNlIHRoYXQgd2lsbCBiZSBhZGRlZFxuICAgIC8vIGJ5IFBsb3RzLmRvQ2FsY2RhdGEsIGFuZCB0aGF0J3MgYWxsIHdlIGFjdHVhbGx5IG5lZWQgbGF0ZXIuXG4gICAgcmV0dXJuIHdyYXAoe30pO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2VsbFBhZDogOCxcbiAgICBjb2x1bW5FeHRlbnRPZmZzZXQ6IDEwLFxuICAgIGNvbHVtblRpdGxlT2Zmc2V0OiAyOCxcbiAgICBlbXB0eUhlYWRlckhlaWdodDogMTYsXG4gICAgbGF0ZXhDaGVjazogL15cXCQuKlxcJCQvLFxuICAgIGdvbGRlblJhdGlvOiAxLjYxOCxcbiAgICBsaW5lQnJlYWtlcjogJzxicj4nLFxuICAgIG1heERpbWVuc2lvbkNvdW50OiA2MCxcbiAgICBvdmVyZHJhZzogNDUsXG4gICAgcmVsZWFzZVRyYW5zaXRpb25EdXJhdGlvbjogMTIwLFxuICAgIHJlbGVhc2VUcmFuc2l0aW9uRWFzZTogJ2N1YmljLW91dCcsXG4gICAgc2Nyb2xsYmFyQ2FwdHVyZVdpZHRoOiAxOCxcbiAgICBzY3JvbGxiYXJIaWRlRGVsYXk6IDEwMDAsXG4gICAgc2Nyb2xsYmFySGlkZUR1cmF0aW9uOiAxMDAwLFxuICAgIHNjcm9sbGJhck9mZnNldDogNSxcbiAgICBzY3JvbGxiYXJXaWR0aDogOCxcbiAgICB0cmFuc2l0aW9uRHVyYXRpb246IDEwMCxcbiAgICB0cmFuc2l0aW9uRWFzZTogJ2N1YmljLW91dCcsXG4gICAgdXBsaWZ0OiA1LFxuICAgIHdyYXBTcGFjZXI6ICcgJyxcbiAgICB3cmFwU3BsaXRDaGFyYWN0ZXI6ICcgJyxcbiAgICBjbjoge1xuICAgICAgICAvLyBnZW5lcmFsIGNsYXNzIG5hbWVzXG4gICAgICAgIHRhYmxlOiAndGFibGUnLFxuICAgICAgICB0YWJsZUNvbnRyb2xWaWV3OiAndGFibGUtY29udHJvbC12aWV3JyxcbiAgICAgICAgc2Nyb2xsQmFja2dyb3VuZDogJ3Njcm9sbC1iYWNrZ3JvdW5kJyxcbiAgICAgICAgeUNvbHVtbjogJ3ktY29sdW1uJyxcbiAgICAgICAgY29sdW1uQmxvY2s6ICdjb2x1bW4tYmxvY2snLFxuICAgICAgICBzY3JvbGxBcmVhQ2xpcDogJ3Njcm9sbC1hcmVhLWNsaXAnLFxuICAgICAgICBzY3JvbGxBcmVhQ2xpcFJlY3Q6ICdzY3JvbGwtYXJlYS1jbGlwLXJlY3QnLFxuICAgICAgICBjb2x1bW5Cb3VuZGFyeTogJ2NvbHVtbi1ib3VuZGFyeScsXG4gICAgICAgIGNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGg6ICdjb2x1bW4tYm91bmRhcnktY2xpcHBhdGgnLFxuICAgICAgICBjb2x1bW5Cb3VuZGFyeVJlY3Q6ICdjb2x1bW4tYm91bmRhcnktcmVjdCcsXG4gICAgICAgIGNvbHVtbkNlbGxzOiAnY29sdW1uLWNlbGxzJyxcbiAgICAgICAgY29sdW1uQ2VsbDogJ2NvbHVtbi1jZWxsJyxcbiAgICAgICAgY2VsbFJlY3Q6ICdjZWxsLXJlY3QnLFxuICAgICAgICBjZWxsVGV4dDogJ2NlbGwtdGV4dCcsXG4gICAgICAgIGNlbGxUZXh0SG9sZGVyOiAnY2VsbC10ZXh0LWhvbGRlcicsXG5cbiAgICAgICAgLy8gc2Nyb2xsIHJlbGF0ZWQgY2xhc3MgbmFtZXNcbiAgICAgICAgc2Nyb2xsYmFyS2l0OiAnc2Nyb2xsYmFyLWtpdCcsXG4gICAgICAgIHNjcm9sbGJhcjogJ3Njcm9sbGJhcicsXG4gICAgICAgIHNjcm9sbGJhclNsaWRlcjogJ3Njcm9sbGJhci1zbGlkZXInLFxuICAgICAgICBzY3JvbGxiYXJHbHlwaDogJ3Njcm9sbGJhci1nbHlwaCcsXG4gICAgICAgIHNjcm9sbGJhckNhcHR1cmVab25lOiAnc2Nyb2xsYmFyLWNhcHR1cmUtem9uZSdcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIGlzTnVtZXJpYyA9IHJlcXVpcmUoJ2Zhc3QtaXNudW1lcmljJyk7XG5cbi8vIHB1cmUgZnVuY3Rpb25zLCBkb24ndCBhbHRlciBidXQgcGFzc2VzIG9uIGBnZGAgYW5kIHBhcnRzIG9mIGB0cmFjZWAgd2l0aG91dCBkZWVwIGNvcHlpbmdcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2VsbHNWYWx1ZXMgPSBzcXVhcmVTdHJpbmdNYXRyaXgodHJhY2UuY2VsbHMudmFsdWVzKTtcbiAgICB2YXIgc2xpY2VyID0gZnVuY3Rpb24oYSkge1xuICAgICAgICByZXR1cm4gYS5zbGljZSh0cmFjZS5oZWFkZXIudmFsdWVzLmxlbmd0aCwgYS5sZW5ndGgpO1xuICAgIH07XG4gICAgdmFyIGhlYWRlclZhbHVlc0luID0gc3F1YXJlU3RyaW5nTWF0cml4KHRyYWNlLmhlYWRlci52YWx1ZXMpO1xuICAgIGlmKGhlYWRlclZhbHVlc0luLmxlbmd0aCAmJiAhaGVhZGVyVmFsdWVzSW5bMF0ubGVuZ3RoKSB7XG4gICAgICAgIGhlYWRlclZhbHVlc0luWzBdID0gWycnXTtcbiAgICAgICAgaGVhZGVyVmFsdWVzSW4gPSBzcXVhcmVTdHJpbmdNYXRyaXgoaGVhZGVyVmFsdWVzSW4pO1xuICAgIH1cbiAgICB2YXIgaGVhZGVyVmFsdWVzID0gaGVhZGVyVmFsdWVzSW5cbiAgICAgICAgLmNvbmNhdChzbGljZXIoY2VsbHNWYWx1ZXMpLm1hcChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBlbXB0eVN0cmluZ3MoKGhlYWRlclZhbHVlc0luWzBdIHx8IFsnJ10pLmxlbmd0aCk7XG4gICAgICAgIH0pKTtcblxuICAgIHZhciBkb21haW4gPSB0cmFjZS5kb21haW47XG4gICAgdmFyIGdyb3VwV2lkdGggPSBNYXRoLmZsb29yKGdkLl9mdWxsTGF5b3V0Ll9zaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpO1xuICAgIHZhciBncm91cEhlaWdodCA9IE1hdGguZmxvb3IoZ2QuX2Z1bGxMYXlvdXQuX3NpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSk7XG4gICAgdmFyIGhlYWRlclJvd0hlaWdodHMgPSB0cmFjZS5oZWFkZXIudmFsdWVzLmxlbmd0aCA/XG4gICAgICAgIGhlYWRlclZhbHVlc1swXS5tYXAoZnVuY3Rpb24oKSB7IHJldHVybiB0cmFjZS5oZWFkZXIuaGVpZ2h0OyB9KSA6XG4gICAgICAgIFtjLmVtcHR5SGVhZGVySGVpZ2h0XTtcbiAgICB2YXIgcm93SGVpZ2h0cyA9IGNlbGxzVmFsdWVzLmxlbmd0aCA/IGNlbGxzVmFsdWVzWzBdLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHRyYWNlLmNlbGxzLmhlaWdodDsgfSkgOiBbXTtcbiAgICB2YXIgaGVhZGVySGVpZ2h0ID0gaGVhZGVyUm93SGVpZ2h0cy5yZWR1Y2Uoc3VtLCAwKTtcbiAgICB2YXIgc2Nyb2xsSGVpZ2h0ID0gZ3JvdXBIZWlnaHQgLSBoZWFkZXJIZWlnaHQ7XG4gICAgdmFyIG1pbmltdW1GaWxsSGVpZ2h0ID0gc2Nyb2xsSGVpZ2h0ICsgYy51cGxpZnQ7XG4gICAgdmFyIGFuY2hvclRvUm93QmxvY2sgPSBtYWtlQW5jaG9yVG9Sb3dCbG9jayhyb3dIZWlnaHRzLCBtaW5pbXVtRmlsbEhlaWdodCk7XG4gICAgdmFyIGFuY2hvclRvSGVhZGVyUm93QmxvY2sgPSBtYWtlQW5jaG9yVG9Sb3dCbG9jayhoZWFkZXJSb3dIZWlnaHRzLCBoZWFkZXJIZWlnaHQpO1xuICAgIHZhciBoZWFkZXJSb3dCbG9ja3MgPSBtYWtlUm93QmxvY2soYW5jaG9yVG9IZWFkZXJSb3dCbG9jaywgW10pO1xuICAgIHZhciByb3dCbG9ja3MgPSBtYWtlUm93QmxvY2soYW5jaG9yVG9Sb3dCbG9jaywgaGVhZGVyUm93QmxvY2tzKTtcbiAgICB2YXIgdW5pcXVlS2V5cyA9IHt9O1xuICAgIHZhciBjb2x1bW5PcmRlciA9IHRyYWNlLl9mdWxsSW5wdXQuY29sdW1ub3JkZXIuY29uY2F0KHNsaWNlcihjZWxsc1ZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge3JldHVybiBpO30pKSk7XG4gICAgdmFyIGNvbHVtbldpZHRocyA9IGhlYWRlclZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBBcnJheS5pc0FycmF5KHRyYWNlLmNvbHVtbndpZHRoKSA/XG4gICAgICAgICAgICB0cmFjZS5jb2x1bW53aWR0aFtNYXRoLm1pbihpLCB0cmFjZS5jb2x1bW53aWR0aC5sZW5ndGggLSAxKV0gOlxuICAgICAgICAgICAgdHJhY2UuY29sdW1ud2lkdGg7XG4gICAgICAgIHJldHVybiBpc051bWVyaWModmFsdWUpID8gTnVtYmVyKHZhbHVlKSA6IDE7XG4gICAgfSk7XG4gICAgdmFyIHRvdGFsQ29sdW1uV2lkdGhzID0gY29sdW1uV2lkdGhzLnJlZHVjZShzdW0sIDApO1xuXG4gICAgLy8gZml0IGNvbHVtbnMgaW4gdGhlIGF2YWlsYWJsZSB2ZXJ0aWNhbCBzcGFjZSBhcyB0aGVyZSdzIG5vIHZlcnRpY2FsIHNjcm9sbGluZyBub3dcbiAgICBjb2x1bW5XaWR0aHMgPSBjb2x1bW5XaWR0aHMubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQgLyB0b3RhbENvbHVtbldpZHRocyAqIGdyb3VwV2lkdGg7IH0pO1xuXG4gICAgdmFyIG1heExpbmVXaWR0aCA9IE1hdGgubWF4KGFycmF5TWF4KHRyYWNlLmhlYWRlci5saW5lLndpZHRoKSwgYXJyYXlNYXgodHJhY2UuY2VsbHMubGluZS53aWR0aCkpO1xuXG4gICAgdmFyIGNhbGNkYXRhID0ge1xuICAgICAgICBrZXk6IHRyYWNlLmluZGV4LFxuICAgICAgICB0cmFuc2xhdGVYOiBkb21haW4ueFswXSAqIGdkLl9mdWxsTGF5b3V0Ll9zaXplLncsXG4gICAgICAgIHRyYW5zbGF0ZVk6IGdkLl9mdWxsTGF5b3V0Ll9zaXplLmggKiAoMSAtIGRvbWFpbi55WzFdKSxcbiAgICAgICAgc2l6ZTogZ2QuX2Z1bGxMYXlvdXQuX3NpemUsXG4gICAgICAgIHdpZHRoOiBncm91cFdpZHRoLFxuICAgICAgICBtYXhMaW5lV2lkdGg6IG1heExpbmVXaWR0aCxcbiAgICAgICAgaGVpZ2h0OiBncm91cEhlaWdodCxcbiAgICAgICAgY29sdW1uT3JkZXI6IGNvbHVtbk9yZGVyLCAvLyB3aWxsIGJlIG11dGF0ZWQgb24gY29sdW1uIG1vdmUsIHRvZG8gdXNlIGluIGNhbGxiYWNrXG4gICAgICAgIGdyb3VwSGVpZ2h0OiBncm91cEhlaWdodCxcbiAgICAgICAgcm93QmxvY2tzOiByb3dCbG9ja3MsXG4gICAgICAgIGhlYWRlclJvd0Jsb2NrczogaGVhZGVyUm93QmxvY2tzLFxuICAgICAgICBzY3JvbGxZOiAwLCAvLyB3aWxsIGJlIG11dGF0ZWQgb24gc2Nyb2xsXG4gICAgICAgIGNlbGxzOiBleHRlbmRGbGF0KHt9LCB0cmFjZS5jZWxscywge3ZhbHVlczogY2VsbHNWYWx1ZXN9KSxcbiAgICAgICAgaGVhZGVyQ2VsbHM6IGV4dGVuZEZsYXQoe30sIHRyYWNlLmhlYWRlciwge3ZhbHVlczogaGVhZGVyVmFsdWVzfSksXG4gICAgICAgIGdkQ29sdW1uczogaGVhZGVyVmFsdWVzLm1hcChmdW5jdGlvbihkKSB7cmV0dXJuIGRbMF07fSksXG4gICAgICAgIGdkQ29sdW1uc09yaWdpbmFsT3JkZXI6IGhlYWRlclZhbHVlcy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkWzBdO30pLFxuICAgICAgICBwcmV2UGFnZXM6IFswLCAwXSxcbiAgICAgICAgc2Nyb2xsYmFyU3RhdGU6IHtzY3JvbGxiYXJTY3JvbGxJblByb2dyZXNzOiBmYWxzZX0sXG4gICAgICAgIGNvbHVtbnM6IGhlYWRlclZhbHVlcy5tYXAoZnVuY3Rpb24obGFiZWwsIGkpIHtcbiAgICAgICAgICAgIHZhciBmb3VuZEtleSA9IHVuaXF1ZUtleXNbbGFiZWxdO1xuICAgICAgICAgICAgdW5pcXVlS2V5c1tsYWJlbF0gPSAoZm91bmRLZXkgfHwgMCkgKyAxO1xuICAgICAgICAgICAgdmFyIGtleSA9IGxhYmVsICsgJ19fJyArIHVuaXF1ZUtleXNbbGFiZWxdO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgICBsYWJlbDogbGFiZWwsXG4gICAgICAgICAgICAgICAgc3BlY0luZGV4OiBpLFxuICAgICAgICAgICAgICAgIHhJbmRleDogY29sdW1uT3JkZXJbaV0sXG4gICAgICAgICAgICAgICAgeFNjYWxlOiB4U2NhbGUsXG4gICAgICAgICAgICAgICAgeDogdW5kZWZpbmVkLCAvLyBpbml0aWFsaXplZCBiZWxvd1xuICAgICAgICAgICAgICAgIGNhbGNkYXRhOiB1bmRlZmluZWQsIC8vIGluaXRpYWxpemVkIGJlbG93XG4gICAgICAgICAgICAgICAgY29sdW1uV2lkdGg6IGNvbHVtbldpZHRoc1tpXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSlcbiAgICB9O1xuXG4gICAgY2FsY2RhdGEuY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uKGNvbCkge1xuICAgICAgICBjb2wuY2FsY2RhdGEgPSBjYWxjZGF0YTtcbiAgICAgICAgY29sLnggPSB4U2NhbGUoY29sKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBjYWxjZGF0YTtcbn07XG5cbmZ1bmN0aW9uIGFycmF5TWF4KG1heWJlQXJyYXkpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KG1heWJlQXJyYXkpKSB7XG4gICAgICAgIHZhciBtYXggPSAwO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWF5YmVBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCBhcnJheU1heChtYXliZUFycmF5W2ldKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1heDtcbiAgICB9XG4gICAgcmV0dXJuIG1heWJlQXJyYXk7XG59XG5cbmZ1bmN0aW9uIHN1bShhLCBiKSB7IHJldHVybiBhICsgYjsgfVxuXG4vLyBmaWxsIG1hdHJpeCBpbiBwbGFjZSB0byBlcXVhbCBsZW5ndGhzXG4vLyBhbmQgZW5zdXJlIGl0J3MgdW5pZm9ybWx5IDJEXG5mdW5jdGlvbiBzcXVhcmVTdHJpbmdNYXRyaXgobWF0cml4SW4pIHtcbiAgICB2YXIgbWF0cml4ID0gbWF0cml4SW4uc2xpY2UoKTtcbiAgICB2YXIgbWluTGVuID0gSW5maW5pdHk7XG4gICAgdmFyIG1heExlbiA9IDA7XG4gICAgdmFyIGk7XG4gICAgZm9yKGkgPSAwOyBpIDwgbWF0cml4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KG1hdHJpeFtpXSkpIG1hdHJpeFtpXSA9IFttYXRyaXhbaV1dO1xuICAgICAgICBtaW5MZW4gPSBNYXRoLm1pbihtaW5MZW4sIG1hdHJpeFtpXS5sZW5ndGgpO1xuICAgICAgICBtYXhMZW4gPSBNYXRoLm1heChtYXhMZW4sIG1hdHJpeFtpXS5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmKG1pbkxlbiAhPT0gbWF4TGVuKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG1hdHJpeC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBhZExlbiA9IG1heExlbiAtIG1hdHJpeFtpXS5sZW5ndGg7XG4gICAgICAgICAgICBpZihwYWRMZW4pIG1hdHJpeFtpXSA9IG1hdHJpeFtpXS5jb25jYXQoZW1wdHlTdHJpbmdzKHBhZExlbikpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtYXRyaXg7XG59XG5cbmZ1bmN0aW9uIGVtcHR5U3RyaW5ncyhsZW4pIHtcbiAgICB2YXIgcGFkQXJyYXkgPSBuZXcgQXJyYXkobGVuKTtcbiAgICBmb3IodmFyIGogPSAwOyBqIDwgbGVuOyBqKyspIHBhZEFycmF5W2pdID0gJyc7XG4gICAgcmV0dXJuIHBhZEFycmF5O1xufVxuXG5mdW5jdGlvbiB4U2NhbGUoZCkge1xuICAgIHJldHVybiBkLmNhbGNkYXRhLmNvbHVtbnMucmVkdWNlKGZ1bmN0aW9uKHByZXYsIG5leHQpIHtcbiAgICAgICAgcmV0dXJuIG5leHQueEluZGV4IDwgZC54SW5kZXggPyBwcmV2ICsgbmV4dC5jb2x1bW5XaWR0aCA6IHByZXY7XG4gICAgfSwgMCk7XG59XG5cbmZ1bmN0aW9uIG1ha2VSb3dCbG9jayhhbmNob3JUb1Jvd0Jsb2NrLCBhdXhpbGlhcnkpIHtcbiAgICB2YXIgYmxvY2tBbmNob3JLZXlzID0gT2JqZWN0LmtleXMoYW5jaG9yVG9Sb3dCbG9jayk7XG4gICAgcmV0dXJuIGJsb2NrQW5jaG9yS2V5cy5tYXAoZnVuY3Rpb24oaykge3JldHVybiBleHRlbmRGbGF0KHt9LCBhbmNob3JUb1Jvd0Jsb2NrW2tdLCB7YXV4aWxpYXJ5QmxvY2tzOiBhdXhpbGlhcnl9KTt9KTtcbn1cblxuZnVuY3Rpb24gbWFrZUFuY2hvclRvUm93QmxvY2socm93SGVpZ2h0cywgbWluaW11bUZpbGxIZWlnaHQpIHtcblxuICAgIHZhciBhbmNob3JUb1Jvd0Jsb2NrID0ge307XG4gICAgdmFyIGN1cnJlbnRSb3dIZWlnaHQ7XG4gICAgdmFyIGN1cnJlbnRBbmNob3IgPSAwO1xuICAgIHZhciBjdXJyZW50QmxvY2tIZWlnaHQgPSAwO1xuICAgIHZhciBjdXJyZW50QmxvY2sgPSBtYWtlSWRlbnRpdHkoKTtcbiAgICB2YXIgY3VycmVudEZpcnN0Um93SW5kZXggPSAwO1xuICAgIHZhciBibG9ja0NvdW50ZXIgPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCByb3dIZWlnaHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGN1cnJlbnRSb3dIZWlnaHQgPSByb3dIZWlnaHRzW2ldO1xuICAgICAgICBjdXJyZW50QmxvY2sucm93cy5wdXNoKHtcbiAgICAgICAgICAgIHJvd0luZGV4OiBpLFxuICAgICAgICAgICAgcm93SGVpZ2h0OiBjdXJyZW50Um93SGVpZ2h0XG4gICAgICAgIH0pO1xuICAgICAgICBjdXJyZW50QmxvY2tIZWlnaHQgKz0gY3VycmVudFJvd0hlaWdodDtcbiAgICAgICAgaWYoY3VycmVudEJsb2NrSGVpZ2h0ID49IG1pbmltdW1GaWxsSGVpZ2h0IHx8IGkgPT09IHJvd0hlaWdodHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgYW5jaG9yVG9Sb3dCbG9ja1tjdXJyZW50QW5jaG9yXSA9IGN1cnJlbnRCbG9jaztcbiAgICAgICAgICAgIGN1cnJlbnRCbG9jay5rZXkgPSBibG9ja0NvdW50ZXIrKztcbiAgICAgICAgICAgIGN1cnJlbnRCbG9jay5maXJzdFJvd0luZGV4ID0gY3VycmVudEZpcnN0Um93SW5kZXg7XG4gICAgICAgICAgICBjdXJyZW50QmxvY2subGFzdFJvd0luZGV4ID0gaTtcbiAgICAgICAgICAgIGN1cnJlbnRCbG9jayA9IG1ha2VJZGVudGl0eSgpO1xuICAgICAgICAgICAgY3VycmVudEFuY2hvciArPSBjdXJyZW50QmxvY2tIZWlnaHQ7XG4gICAgICAgICAgICBjdXJyZW50Rmlyc3RSb3dJbmRleCA9IGkgKyAxO1xuICAgICAgICAgICAgY3VycmVudEJsb2NrSGVpZ2h0ID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbmNob3JUb1Jvd0Jsb2NrO1xufVxuXG5mdW5jdGlvbiBtYWtlSWRlbnRpdHkoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlyc3RSb3dJbmRleDogbnVsbCxcbiAgICAgICAgbGFzdFJvd0luZGV4OiBudWxsLFxuICAgICAgICByb3dzOiBbXVxuICAgIH07XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbi8vIHB1cmUgZnVuY3Rpb25zLCBkb24ndCBhbHRlciBidXQgcGFzc2VzIG9uIGBnZGAgYW5kIHBhcnRzIG9mIGB0cmFjZWAgd2l0aG91dCBkZWVwIGNvcHlpbmdcblxuZXhwb3J0cy5zcGxpdFRvUGFuZWxzID0gZnVuY3Rpb24oZCkge1xuICAgIHZhciBwcmV2UGFnZXMgPSBbMCwgMF07XG4gICAgdmFyIGhlYWRlclBhbmVsID0gZXh0ZW5kRmxhdCh7fSwgZCwge1xuICAgICAgICBrZXk6ICdoZWFkZXInLFxuICAgICAgICB0eXBlOiAnaGVhZGVyJyxcbiAgICAgICAgcGFnZTogMCxcbiAgICAgICAgcHJldlBhZ2VzOiBwcmV2UGFnZXMsXG4gICAgICAgIGN1cnJlbnRSZXBhaW50OiBbbnVsbCwgbnVsbF0sXG4gICAgICAgIGRyYWdIYW5kbGU6IHRydWUsXG4gICAgICAgIHZhbHVlczogZC5jYWxjZGF0YS5oZWFkZXJDZWxscy52YWx1ZXNbZC5zcGVjSW5kZXhdLFxuICAgICAgICByb3dCbG9ja3M6IGQuY2FsY2RhdGEuaGVhZGVyUm93QmxvY2tzLFxuICAgICAgICBjYWxjZGF0YTogZXh0ZW5kRmxhdCh7fSwgZC5jYWxjZGF0YSwge2NlbGxzOiBkLmNhbGNkYXRhLmhlYWRlckNlbGxzfSlcbiAgICB9KTtcbiAgICB2YXIgcmV2b2x2ZXJQYW5lbDEgPSBleHRlbmRGbGF0KHt9LCBkLCB7XG4gICAgICAgIGtleTogJ2NlbGxzMScsXG4gICAgICAgIHR5cGU6ICdjZWxscycsXG4gICAgICAgIHBhZ2U6IDAsXG4gICAgICAgIHByZXZQYWdlczogcHJldlBhZ2VzLFxuICAgICAgICBjdXJyZW50UmVwYWludDogW251bGwsIG51bGxdLFxuICAgICAgICBkcmFnSGFuZGxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWVzOiBkLmNhbGNkYXRhLmNlbGxzLnZhbHVlc1tkLnNwZWNJbmRleF0sXG4gICAgICAgIHJvd0Jsb2NrczogZC5jYWxjZGF0YS5yb3dCbG9ja3NcbiAgICB9KTtcbiAgICB2YXIgcmV2b2x2ZXJQYW5lbDIgPSBleHRlbmRGbGF0KHt9LCBkLCB7XG4gICAgICAgIGtleTogJ2NlbGxzMicsXG4gICAgICAgIHR5cGU6ICdjZWxscycsXG4gICAgICAgIHBhZ2U6IDEsXG4gICAgICAgIHByZXZQYWdlczogcHJldlBhZ2VzLFxuICAgICAgICBjdXJyZW50UmVwYWludDogW251bGwsIG51bGxdLFxuICAgICAgICBkcmFnSGFuZGxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWVzOiBkLmNhbGNkYXRhLmNlbGxzLnZhbHVlc1tkLnNwZWNJbmRleF0sXG4gICAgICAgIHJvd0Jsb2NrczogZC5jYWxjZGF0YS5yb3dCbG9ja3NcbiAgICB9KTtcbiAgICAvLyBvcmRlciBkdWUgdG8gU1ZHIHVzaW5nIHBhaW50ZXIncyBhbGdvOlxuICAgIHJldHVybiBbcmV2b2x2ZXJQYW5lbDEsIHJldm9sdmVyUGFuZWwyLCBoZWFkZXJQYW5lbF07XG59O1xuXG5leHBvcnRzLnNwbGl0VG9DZWxscyA9IGZ1bmN0aW9uKGQpIHtcbiAgICB2YXIgZnJvbVRvID0gcm93RnJvbVRvKGQpO1xuICAgIHJldHVybiAoZC52YWx1ZXMgfHwgW10pLnNsaWNlKGZyb21Ub1swXSwgZnJvbVRvWzFdKS5tYXAoZnVuY3Rpb24odiwgaSkge1xuICAgICAgICAvLyBCeSBrZWVwaW5nIGlkZW50aWNhbCBrZXksIGEgRE9NIG5vZGUgcmVtb3ZhbCwgY3JlYXRpb24gYW5kIGFkZGl0aW9uIGlzIHNwYXJlZCwgaW1wb3J0YW50IHdoZW4gdmlzaWJsZVxuICAgICAgICAvLyBncmlkIGhhcyBhIGxvdCBvZiBlbGVtZW50cyAocXVhZHJhdGljIHdpdGggeGNvbC95Y29sIGNvdW50KS5cbiAgICAgICAgLy8gQnV0IGl0IGhhcyB0byBiZSBidXN0ZWQgd2hlbiBgc3ZnVXRpbC5jb252ZXJ0VG9Uc3BhbnNgIGlzIHVzZWQgYXMgaXQgcmVzaGFwZXMgY2VsbCBzdWJ0cmVlcyBhc3luY2hyb25vdXNseSxcbiAgICAgICAgLy8gYW5kIGJ5IHRoYXQgdGltZSB0aGUgdXNlciBtYXkgaGF2ZSBzY3JvbGxlZCBhd2F5LCByZXN1bHRpbmcgaW4gc3RhbGUgb3ZlcndyaXRlcy4gVGhlIHJlYWwgc29sdXRpb24gd2lsbCBiZVxuICAgICAgICAvLyB0byB0dXJuIGBzdmdVdGlsLmNvbnZlcnRUb1RzcGFuc2AgaW50byBhIGNhbmNlbGFibGUgcmVxdWVzdCwgaW4gd2hpY2ggY2FzZSBubyBrZXkgYnVzdGluZyBpcyBuZWVkZWQuXG4gICAgICAgIHZhciBidXN0ZXIgPSAodHlwZW9mIHYgPT09ICdzdHJpbmcnKSAmJiB2Lm1hdGNoKC9bPCQmPiBdLykgPyAnX2tleWJ1c3Rlcl8nICsgTWF0aC5yYW5kb20oKSA6ICcnO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLy8ga2V5V2l0aGluQmxvY2s6IC8qZnJvbVRvWzBdICsgKi9pLCAvLyBvcHRpbWl6ZWQgZnV0dXJlIHZlcnNpb24gLSBubyBidXN0aW5nXG4gICAgICAgICAgICAvLyBrZXlXaXRoaW5CbG9jazogZnJvbVRvWzBdICsgaSwgLy8gaW5pdGlhbCBhbHdheXMtdW5vcHRpbWl6ZWQgdmVyc2lvbiAtIGphbmt5IHNjcm9sbGluZyB3aXRoIDUrIGNvbHVtbnNcbiAgICAgICAgICAgIGtleVdpdGhpbkJsb2NrOiBpICsgYnVzdGVyLCAvLyBjdXJyZW50IGNvbXByb21pc2U6IHJlZ3VsYXIgY29udGVudCBpcyB2ZXJ5IGZhc3Q7IGFzeW5jIGNvbnRlbnQgaXMgcG9zc2libGVcbiAgICAgICAgICAgIGtleTogZnJvbVRvWzBdICsgaSxcbiAgICAgICAgICAgIGNvbHVtbjogZCxcbiAgICAgICAgICAgIGNhbGNkYXRhOiBkLmNhbGNkYXRhLFxuICAgICAgICAgICAgcGFnZTogZC5wYWdlLFxuICAgICAgICAgICAgcm93QmxvY2tzOiBkLnJvd0Jsb2NrcyxcbiAgICAgICAgICAgIHZhbHVlOiB2XG4gICAgICAgIH07XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiByb3dGcm9tVG8oZCkge1xuICAgIHZhciByb3dCbG9jayA9IGQucm93QmxvY2tzW2QucGFnZV07XG4gICAgLy8gZml4bWUgcm93QmxvY2sgdHJ1dGhpbmVzcyBjaGVjayBpcyBkdWUgdG8gdWdseSBoYWNrIG9mIHBsYWNpbmcgMm5kIHBhbmVsIGFzIGQucGFnZSA9IC0xXG4gICAgdmFyIHJvd0Zyb20gPSByb3dCbG9jayA/IHJvd0Jsb2NrLnJvd3NbMF0ucm93SW5kZXggOiAwO1xuICAgIHZhciByb3dUbyA9IHJvd0Jsb2NrID8gcm93RnJvbSArIHJvd0Jsb2NrLnJvd3MubGVuZ3RoIDogMDtcbiAgICByZXR1cm4gW3Jvd0Zyb20sIHJvd1RvXTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uLy4uL2xpYicpO1xudmFyIGF0dHJpYnV0ZXMgPSByZXF1aXJlKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBoYW5kbGVEb21haW5EZWZhdWx0cyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmRlZmF1bHRzO1xuXG5mdW5jdGlvbiBkZWZhdWx0Q29sdW1uT3JkZXIodHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciBzcGVjaWZpZWRDb2x1bW5PcmRlciA9IHRyYWNlT3V0LmNvbHVtbm9yZGVyIHx8IFtdO1xuICAgIHZhciBjb21tb25MZW5ndGggPSB0cmFjZU91dC5oZWFkZXIudmFsdWVzLmxlbmd0aDtcbiAgICB2YXIgdHJ1bmNhdGVkID0gc3BlY2lmaWVkQ29sdW1uT3JkZXIuc2xpY2UoMCwgY29tbW9uTGVuZ3RoKTtcbiAgICB2YXIgc29ydGVkID0gdHJ1bmNhdGVkLnNsaWNlKCkuc29ydChmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGEgLSBiO30pO1xuICAgIHZhciBvbmVTdGVwcGVkID0gdHJ1bmNhdGVkLm1hcChmdW5jdGlvbihkKSB7cmV0dXJuIHNvcnRlZC5pbmRleE9mKGQpO30pO1xuICAgIGZvcih2YXIgaSA9IG9uZVN0ZXBwZWQubGVuZ3RoOyBpIDwgY29tbW9uTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb25lU3RlcHBlZC5wdXNoKGkpO1xuICAgIH1cbiAgICBjb2VyY2UoJ2NvbHVtbm9yZGVyJywgb25lU3RlcHBlZCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBjb2VyY2UoJ2NvbHVtbndpZHRoJyk7XG5cbiAgICBjb2VyY2UoJ2hlYWRlci52YWx1ZXMnKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5mb3JtYXQnKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5hbGlnbicpO1xuXG4gICAgY29lcmNlKCdoZWFkZXIucHJlZml4Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIuc3VmZml4Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIuaGVpZ2h0Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIubGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnaGVhZGVyLmxpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5maWxsLmNvbG9yJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnaGVhZGVyLmZvbnQnLCBMaWIuZXh0ZW5kRmxhdCh7fSwgbGF5b3V0LmZvbnQpKTtcblxuICAgIGRlZmF1bHRDb2x1bW5PcmRlcih0cmFjZU91dCwgY29lcmNlKTtcblxuICAgIGNvZXJjZSgnY2VsbHMudmFsdWVzJyk7XG4gICAgY29lcmNlKCdjZWxscy5mb3JtYXQnKTtcbiAgICBjb2VyY2UoJ2NlbGxzLmFsaWduJyk7XG4gICAgY29lcmNlKCdjZWxscy5wcmVmaXgnKTtcbiAgICBjb2VyY2UoJ2NlbGxzLnN1ZmZpeCcpO1xuICAgIGNvZXJjZSgnY2VsbHMuaGVpZ2h0Jyk7XG4gICAgY29lcmNlKCdjZWxscy5saW5lLndpZHRoJyk7XG4gICAgY29lcmNlKCdjZWxscy5saW5lLmNvbG9yJyk7XG4gICAgY29lcmNlKCdjZWxscy5maWxsLmNvbG9yJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnY2VsbHMuZm9udCcsIExpYi5leHRlbmRGbGF0KHt9LCBsYXlvdXQuZm9udCkpO1xuXG4gICAgLy8gZGlzYWJsZSAxRCB0cmFuc2Zvcm1zXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgVGFibGUgPSB7fTtcblxuVGFibGUuYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuVGFibGUuc3VwcGx5RGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5UYWJsZS5jYWxjID0gcmVxdWlyZSgnLi9jYWxjJyk7XG5UYWJsZS5wbG90ID0gcmVxdWlyZSgnLi9wbG90Jyk7XG5cblRhYmxlLm1vZHVsZVR5cGUgPSAndHJhY2UnO1xuVGFibGUubmFtZSA9ICd0YWJsZSc7XG5UYWJsZS5iYXNlUGxvdE1vZHVsZSA9IHJlcXVpcmUoJy4vYmFzZV9wbG90Jyk7XG5UYWJsZS5jYXRlZ29yaWVzID0gWydub09wYWNpdHknXTtcblRhYmxlLm1ldGEgPSB7XG4gICAgXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFRhYmxlO1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIGd1cCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9ndXAnKTtcbnZhciBEcmF3aW5nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgc3ZnVXRpbCA9IHJlcXVpcmUoJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIHJhaXNlVG9Ub3AgPSByZXF1aXJlKCcuLi8uLi9saWInKS5yYWlzZVRvVG9wO1xudmFyIGNhbmNlbEVlYXNlQ29sdW1uID0gcmVxdWlyZSgnLi4vLi4vbGliJykuY2FuY2VsVHJhbnNpdGlvbjtcbnZhciBwcmVwYXJlRGF0YSA9IHJlcXVpcmUoJy4vZGF0YV9wcmVwYXJhdGlvbl9oZWxwZXInKTtcbnZhciBzcGxpdERhdGEgPSByZXF1aXJlKCcuL2RhdGFfc3BsaXRfaGVscGVycycpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHdyYXBwZWRUcmFjZUhvbGRlcnMpIHtcblxuICAgIHZhciB0YWJsZSA9IGdkLl9mdWxsTGF5b3V0Ll9wYXBlci5zZWxlY3RBbGwoJy4nICsgYy5jbi50YWJsZSlcbiAgICAgICAgLmRhdGEod3JhcHBlZFRyYWNlSG9sZGVycy5tYXAoZnVuY3Rpb24od3JhcHBlZFRyYWNlSG9sZGVyKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VIb2xkZXIgPSBndXAudW53cmFwKHdyYXBwZWRUcmFjZUhvbGRlcik7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSB0cmFjZUhvbGRlci50cmFjZTtcbiAgICAgICAgICAgIHJldHVybiBwcmVwYXJlRGF0YShnZCwgdHJhY2UpO1xuICAgICAgICB9KSwgZ3VwLmtleUZ1bik7XG5cbiAgICB0YWJsZS5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICB0YWJsZS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnRhYmxlLCB0cnVlKVxuICAgICAgICAuYXR0cignb3ZlcmZsb3cnLCAndmlzaWJsZScpXG4gICAgICAgIC5zdHlsZSgnYm94LXNpemluZycsICdjb250ZW50LWJveCcpXG4gICAgICAgIC5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKVxuICAgICAgICAuc3R5bGUoJ2xlZnQnLCAwKVxuICAgICAgICAuc3R5bGUoJ292ZXJmbG93JywgJ3Zpc2libGUnKVxuICAgICAgICAuc3R5bGUoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKTtcblxuICAgIHRhYmxlXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC53aWR0aCArIGQuc2l6ZS5sICsgZC5zaXplLnI7fSlcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5oZWlnaHQgKyBkLnNpemUudCArIGQuc2l6ZS5iO30pXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC50cmFuc2xhdGVYICsgJywnICsgZC50cmFuc2xhdGVZICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIHZhciB0YWJsZUNvbnRyb2xWaWV3ID0gdGFibGUuc2VsZWN0QWxsKCcuJyArIGMuY24udGFibGVDb250cm9sVmlldylcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICB0YWJsZUNvbnRyb2xWaWV3LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24udGFibGVDb250cm9sVmlldywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdib3gtc2l6aW5nJywgJ2NvbnRlbnQtYm94JylcbiAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihkKSB7dGFibGVDb250cm9sVmlldy5maWx0ZXIoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZCA9PT0gZGQ7fSkuY2FsbChyZW5kZXJTY3JvbGxiYXJLaXQsIGdkKTt9KVxuICAgICAgICAub24oJ21vdXNld2hlZWwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLnNjcm9sbGJhclN0YXRlLndoZWVsaW5nKSByZXR1cm47XG4gICAgICAgICAgICBkLnNjcm9sbGJhclN0YXRlLndoZWVsaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGQzLmV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIG1ha2VEcmFnUm93KGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBudWxsLCBkLnNjcm9sbFkgKyBkMy5ldmVudC5kZWx0YVkpKGQpO1xuICAgICAgICAgICAgZC5zY3JvbGxiYXJTdGF0ZS53aGVlbGluZyA9IGZhbHNlO1xuICAgICAgICB9KVxuICAgICAgICAuY2FsbChyZW5kZXJTY3JvbGxiYXJLaXQsIGdkLCB0cnVlKTtcblxuICAgIHRhYmxlQ29udHJvbFZpZXdcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC5zaXplLmwgKyAnICcgKyBkLnNpemUudCArICcpJzt9KTtcblxuICAgIC8vIHNjcm9sbEJhY2tncm91bmQgbWVyZWx5IGVuc3VyZXMgdGhhdCBtb3VzZSBldmVudHMgYXJlIGNhcHR1cmVkIGV2ZW4gb24gY3JhenkgZmFzdCBzY3JvbGx3aGVlbGluZ1xuICAgIC8vIG90aGVyd2lzZSByZW5kZXJpbmcgZ2xpdGNoZXMgbWF5IG9jY3VyXG4gICAgdmFyIHNjcm9sbEJhY2tncm91bmQgPSB0YWJsZUNvbnRyb2xWaWV3LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbEJhY2tncm91bmQpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgc2Nyb2xsQmFja2dyb3VuZC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbEJhY2tncm91bmQsIHRydWUpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKTtcblxuICAgIHNjcm9sbEJhY2tncm91bmRcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLndpZHRoO30pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaGVpZ2h0O30pO1xuXG4gICAgdGFibGVDb250cm9sVmlld1xuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7RHJhd2luZy5zZXRDbGlwVXJsKGQzLnNlbGVjdCh0aGlzKSwgc2Nyb2xsQXJlYUJvdHRvbUNsaXBLZXkoZ2QsIGQpKTt9KTtcblxuICAgIHZhciB5Q29sdW1uID0gdGFibGVDb250cm9sVmlldy5zZWxlY3RBbGwoJy4nICsgYy5jbi55Q29sdW1uKVxuICAgICAgICAuZGF0YShmdW5jdGlvbih2bSkge3JldHVybiB2bS5jb2x1bW5zO30sIGd1cC5rZXlGdW4pO1xuXG4gICAgeUNvbHVtbi5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnlDb2x1bW4sIHRydWUpO1xuXG4gICAgeUNvbHVtbi5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICB5Q29sdW1uXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7cmV0dXJuICd0cmFuc2xhdGUoJyArIGQueCArICcgMCknO30pXG4gICAgICAgIC5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9yaWdpbihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1vdmVkQ29sdW1uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIGVhc2VDb2x1bW4obW92ZWRDb2x1bW4sIGQsIC1jLnVwbGlmdCk7XG4gICAgICAgICAgICAgICAgcmFpc2VUb1RvcCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkLmNhbGNkYXRhLmNvbHVtbkRyYWdJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJTY3JvbGxiYXJLaXQodGFibGVDb250cm9sVmlldy5maWx0ZXIoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZC5jYWxjZGF0YS5rZXkgPT09IGRkLmtleTt9KSwgZ2QpO1xuICAgICAgICAgICAgICAgIHJldHVybiBkO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignZHJhZycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbW92ZWRDb2x1bW4gPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICAgICAgdmFyIGdldHRlciA9IGZ1bmN0aW9uKGRkKSB7cmV0dXJuIChkID09PSBkZCA/IGQzLmV2ZW50LnggOiBkZC54KSArIGRkLmNvbHVtbldpZHRoIC8gMjt9O1xuICAgICAgICAgICAgICAgIGQueCA9IE1hdGgubWF4KC1jLm92ZXJkcmFnLCBNYXRoLm1pbihkLmNhbGNkYXRhLndpZHRoICsgYy5vdmVyZHJhZyAtIGQuY29sdW1uV2lkdGgsIGQzLmV2ZW50LngpKTtcblxuICAgICAgICAgICAgICAgIHZhciBzb3J0YWJsZUNvbHVtbnMgPSBmbGF0RGF0YSh5Q29sdW1uKS5maWx0ZXIoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZGQuY2FsY2RhdGEua2V5ID09PSBkLmNhbGNkYXRhLmtleTt9KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3T3JkZXIgPSBzb3J0YWJsZUNvbHVtbnMuc29ydChmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGdldHRlcihhKSAtIGdldHRlcihiKTt9KTtcbiAgICAgICAgICAgICAgICBuZXdPcmRlci5mb3JFYWNoKGZ1bmN0aW9uKGRkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRkLnhJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGRkLnggPSBkID09PSBkZCA/IGRkLnggOiBkZC54U2NhbGUoZGQpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgeUNvbHVtbi5maWx0ZXIoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZCAhPT0gZGQ7fSlcbiAgICAgICAgICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAuZWFzZShjLnRyYW5zaXRpb25FYXNlKVxuICAgICAgICAgICAgICAgICAgICAuZHVyYXRpb24oYy50cmFuc2l0aW9uRHVyYXRpb24pXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7cmV0dXJuICd0cmFuc2xhdGUoJyArIGQueCArICcgMCknO30pO1xuICAgICAgICAgICAgICAgIG1vdmVkQ29sdW1uXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKGNhbmNlbEVlYXNlQ29sdW1uKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgZC54ICsgJyAtJyArIGMudXBsaWZ0ICsgJyApJyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdkcmFnZW5kJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHZhciBtb3ZlZENvbHVtbiA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2YXIgcCA9IGQuY2FsY2RhdGE7XG4gICAgICAgICAgICAgICAgZC54ID0gZC54U2NhbGUoZCk7XG4gICAgICAgICAgICAgICAgZC5jYWxjZGF0YS5jb2x1bW5EcmFnSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGVhc2VDb2x1bW4obW92ZWRDb2x1bW4sIGQsIDApO1xuICAgICAgICAgICAgICAgIGNvbHVtbk1vdmVkKGdkLCBwLCBwLmNvbHVtbnMubWFwKGZ1bmN0aW9uKGRkKSB7cmV0dXJuIGRkLnhJbmRleDt9KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgeUNvbHVtbi5lYWNoKGZ1bmN0aW9uKGQpIHtEcmF3aW5nLnNldENsaXBVcmwoZDMuc2VsZWN0KHRoaXMpLCBjb2x1bW5Cb3VuZGFyeUNsaXBLZXkoZ2QsIGQpKTt9KTtcblxuICAgIHZhciBjb2x1bW5CbG9jayA9IHlDb2x1bW4uc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQmxvY2spXG4gICAgICAgIC5kYXRhKHNwbGl0RGF0YS5zcGxpdFRvUGFuZWxzLCBndXAua2V5RnVuKTtcblxuICAgIGNvbHVtbkJsb2NrLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uY29sdW1uQmxvY2ssIHRydWUpXG4gICAgICAgIC5hdHRyKCdpZCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5rZXk7fSk7XG5cbiAgICBjb2x1bW5CbG9ja1xuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmRyYWdIYW5kbGUgPyAnZXctcmVzaXplJyA6IGQuY2FsY2RhdGEuc2Nyb2xsYmFyU3RhdGUuYmFyV2lnZ2xlUm9vbSA/ICducy1yZXNpemUnIDogJ2RlZmF1bHQnO1xuICAgICAgICB9KTtcblxuICAgIHZhciBoZWFkZXJDb2x1bW5CbG9jayA9IGNvbHVtbkJsb2NrLmZpbHRlcihoZWFkZXJCbG9jayk7XG4gICAgdmFyIGNlbGxzQ29sdW1uQmxvY2sgPSBjb2x1bW5CbG9jay5maWx0ZXIoY2VsbHNCbG9jayk7XG5cbiAgICBjZWxsc0NvbHVtbkJsb2NrXG4gICAgICAgIC5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9yaWdpbihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdkcmFnJywgbWFrZURyYWdSb3coZ2QsIHRhYmxlQ29udHJvbFZpZXcsIC0xKSlcbiAgICAgICAgICAgIC5vbignZHJhZ2VuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIC8vIGZpeG1lIGVtaXQgcGxvdGx5IG5vdGlmaWNhdGlvblxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgIC8vIGluaXRpYWwgcmVuZGVyaW5nOiBoZWFkZXIgaXMgcmVuZGVyZWQgZmlyc3QsIGFzIGl0IG1heSBtYXkgaGF2ZSBhc3luYyBMYVRlWCAoc2hvdyBoZWFkZXIgZmlyc3QpXG4gICAgLy8gYnV0IGJsb2NrcyBhcmUgX2VudGVyZWRfIHRoZSB3YXkgdGhleSBhcmUgZHVlIHRvIHBhaW50ZXIncyBhbGdvIChoZWFkZXIgb24gdG9wKVxuICAgIHJlbmRlckNvbHVtbkNlbGxUcmVlKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBoZWFkZXJDb2x1bW5CbG9jaywgY29sdW1uQmxvY2spO1xuICAgIHJlbmRlckNvbHVtbkNlbGxUcmVlKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBjZWxsc0NvbHVtbkJsb2NrLCBjb2x1bW5CbG9jayk7XG5cbiAgICB2YXIgc2Nyb2xsQXJlYUNsaXAgPSB0YWJsZUNvbnRyb2xWaWV3LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbEFyZWFDbGlwKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbEFyZWFDbGlwLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbEFyZWFDbGlwLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIHNjcm9sbEFyZWFCb3R0b21DbGlwS2V5KGdkLCBkKTt9KTtcblxuICAgIHZhciBzY3JvbGxBcmVhQ2xpcFJlY3QgPSBzY3JvbGxBcmVhQ2xpcC5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxBcmVhQ2xpcFJlY3QpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgc2Nyb2xsQXJlYUNsaXBSZWN0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Nyb2xsQXJlYUNsaXBSZWN0LCB0cnVlKVxuICAgICAgICAuYXR0cigneCcsIC1jLm92ZXJkcmFnKVxuICAgICAgICAuYXR0cigneScsIC1jLnVwbGlmdClcbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCAnbm9uZScpO1xuXG4gICAgc2Nyb2xsQXJlYUNsaXBSZWN0XG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC53aWR0aCArIDIgKiBjLm92ZXJkcmFnO30pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaGVpZ2h0ICsgYy51cGxpZnQ7fSk7XG5cbiAgICB2YXIgY29sdW1uQm91bmRhcnkgPSB5Q29sdW1uLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNvbHVtbkJvdW5kYXJ5KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIGNvbHVtbkJvdW5kYXJ5LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uY29sdW1uQm91bmRhcnksIHRydWUpO1xuXG4gICAgdmFyIGNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGggPSB5Q29sdW1uLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGgpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgLy8gU1ZHIHNwZWMgZG9lc24ndCBtYW5kYXRlIHdyYXBwaW5nIGludG8gYSA8ZGVmcz4gYW5kIGRvZXNuJ3Qgc2VlbSB0byBjYXVzZSBhIHNwZWVkIGRpZmZlcmVuY2VcbiAgICBjb2x1bW5Cb3VuZGFyeUNsaXBwYXRoLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGgsIHRydWUpO1xuXG4gICAgY29sdW1uQm91bmRhcnlDbGlwcGF0aFxuICAgICAgICAuYXR0cignaWQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGNvbHVtbkJvdW5kYXJ5Q2xpcEtleShnZCwgZCk7fSk7XG5cbiAgICB2YXIgY29sdW1uQm91bmRhcnlSZWN0ID0gY29sdW1uQm91bmRhcnlDbGlwcGF0aC5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5Cb3VuZGFyeVJlY3QpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgY29sdW1uQm91bmRhcnlSZWN0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uY29sdW1uQm91bmRhcnlSZWN0LCB0cnVlKVxuICAgICAgICAuYXR0cignZmlsbCcsICdub25lJyk7XG5cbiAgICBjb2x1bW5Cb3VuZGFyeVJlY3RcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5jb2x1bW5XaWR0aCArIDIgKiByb3VuZEhhbGZXaWR0aChkKTsgfSlcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jYWxjZGF0YS5oZWlnaHQgKyAyICogcm91bmRIYWxmV2lkdGgoZCkgKyBjLnVwbGlmdDt9KVxuICAgICAgICAuYXR0cigneCcsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIC1yb3VuZEhhbGZXaWR0aChkKTsgfSlcbiAgICAgICAgLmF0dHIoJ3knLCBmdW5jdGlvbihkKSB7IHJldHVybiAtcm91bmRIYWxmV2lkdGgoZCk7IH0pO1xuXG4gICAgdXBkYXRlQmxvY2tZUG9zaXRpb24obnVsbCwgY2VsbHNDb2x1bW5CbG9jaywgdGFibGVDb250cm9sVmlldyk7XG59O1xuXG5mdW5jdGlvbiByb3VuZEhhbGZXaWR0aChkKSB7XG4gICAgcmV0dXJuIE1hdGguY2VpbChkLmNhbGNkYXRhLm1heExpbmVXaWR0aCAvIDIpO1xufVxuXG5mdW5jdGlvbiBzY3JvbGxBcmVhQm90dG9tQ2xpcEtleShnZCwgZCkge1xuICAgIHJldHVybiAnY2xpcCcgKyBnZC5fZnVsbExheW91dC5fdWlkICsgJ19zY3JvbGxBcmVhQm90dG9tQ2xpcF8nICsgZC5rZXk7XG59XG5cbmZ1bmN0aW9uIGNvbHVtbkJvdW5kYXJ5Q2xpcEtleShnZCwgZCkge1xuICAgIHJldHVybiAnY2xpcCcgKyBnZC5fZnVsbExheW91dC5fdWlkICsgJ19jb2x1bW5Cb3VuZGFyeUNsaXBwYXRoXycgKyBkLmNhbGNkYXRhLmtleSArICdfJyArIGQuc3BlY0luZGV4O1xufVxuXG5mdW5jdGlvbiBmbGF0RGF0YShzZWxlY3Rpb24pIHtcbiAgICByZXR1cm4gW10uY29uY2F0LmFwcGx5KFtdLCBzZWxlY3Rpb24ubWFwKGZ1bmN0aW9uKGcpIHtyZXR1cm4gZzt9KSlcbiAgICAgICAgLm1hcChmdW5jdGlvbihnKSB7cmV0dXJuIGcuX19kYXRhX187fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclNjcm9sbGJhcktpdCh0YWJsZUNvbnRyb2xWaWV3LCBnZCwgYnlwYXNzVmlzaWJsZUJhcikge1xuXG4gICAgZnVuY3Rpb24gY2FsY1RvdGFsSGVpZ2h0KGQpIHtcbiAgICAgICAgdmFyIGJsb2NrcyA9IGQucm93QmxvY2tzO1xuICAgICAgICByZXR1cm4gZmlyc3RSb3dBbmNob3IoYmxvY2tzLCBibG9ja3MubGVuZ3RoIC0gMSkgKyAoYmxvY2tzLmxlbmd0aCA/IHJvd3NIZWlnaHQoYmxvY2tzW2Jsb2Nrcy5sZW5ndGggLSAxXSwgSW5maW5pdHkpIDogMSk7XG4gICAgfVxuXG4gICAgdmFyIHNjcm9sbGJhcktpdCA9IHRhYmxlQ29udHJvbFZpZXcuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Nyb2xsYmFyS2l0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbGJhcktpdC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbGJhcktpdCwgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdzaGFwZS1yZW5kZXJpbmcnLCAnZ2VvbWV0cmljUHJlY2lzaW9uJyk7XG5cbiAgICBzY3JvbGxiYXJLaXRcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHMgPSBkLnNjcm9sbGJhclN0YXRlO1xuICAgICAgICAgICAgcy50b3RhbEhlaWdodCA9IGNhbGNUb3RhbEhlaWdodChkKTtcbiAgICAgICAgICAgIHMuc2Nyb2xsYWJsZUFyZWFIZWlnaHQgPSBkLmdyb3VwSGVpZ2h0IC0gaGVhZGVySGVpZ2h0KGQpO1xuICAgICAgICAgICAgcy5jdXJyZW50bHlWaXNpYmxlSGVpZ2h0ID0gTWF0aC5taW4ocy50b3RhbEhlaWdodCwgcy5zY3JvbGxhYmxlQXJlYUhlaWdodCk7XG4gICAgICAgICAgICBzLnJhdGlvID0gcy5jdXJyZW50bHlWaXNpYmxlSGVpZ2h0IC8gcy50b3RhbEhlaWdodDtcbiAgICAgICAgICAgIHMuYmFyTGVuZ3RoID0gTWF0aC5tYXgocy5yYXRpbyAqIHMuY3VycmVudGx5VmlzaWJsZUhlaWdodCwgYy5nb2xkZW5SYXRpbyAqIGMuc2Nyb2xsYmFyV2lkdGgpO1xuICAgICAgICAgICAgcy5iYXJXaWdnbGVSb29tID0gcy5jdXJyZW50bHlWaXNpYmxlSGVpZ2h0IC0gcy5iYXJMZW5ndGg7XG4gICAgICAgICAgICBzLndpZ2dsZVJvb20gPSBNYXRoLm1heCgwLCBzLnRvdGFsSGVpZ2h0IC0gcy5zY3JvbGxhYmxlQXJlYUhlaWdodCk7XG4gICAgICAgICAgICBzLnRvcFkgPSBzLmJhcldpZ2dsZVJvb20gPT09IDAgPyAwIDogKGQuc2Nyb2xsWSAvIHMud2lnZ2xlUm9vbSkgKiBzLmJhcldpZ2dsZVJvb207XG4gICAgICAgICAgICBzLmJvdHRvbVkgPSBzLnRvcFkgKyBzLmJhckxlbmd0aDtcbiAgICAgICAgICAgIHMuZHJhZ011bHRpcGxpZXIgPSBzLndpZ2dsZVJvb20gLyBzLmJhcldpZ2dsZVJvb207XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgeFBvc2l0aW9uID0gZC53aWR0aCArIGMuc2Nyb2xsYmFyV2lkdGggLyAyICsgYy5zY3JvbGxiYXJPZmZzZXQ7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgeFBvc2l0aW9uICsgJyAnICsgaGVhZGVySGVpZ2h0KGQpICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIHZhciBzY3JvbGxiYXIgPSBzY3JvbGxiYXJLaXQuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Nyb2xsYmFyKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbGJhci5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbGJhciwgdHJ1ZSk7XG5cbiAgICB2YXIgc2Nyb2xsYmFyU2xpZGVyID0gc2Nyb2xsYmFyLnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbGJhclNsaWRlcilcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICBzY3JvbGxiYXJTbGlkZXIuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5zY3JvbGxiYXJTbGlkZXIsIHRydWUpO1xuXG4gICAgc2Nyb2xsYmFyU2xpZGVyXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgwICcgKyAoZC5zY3JvbGxiYXJTdGF0ZS50b3BZIHx8IDApICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIHZhciBzY3JvbGxiYXJHbHlwaCA9IHNjcm9sbGJhclNsaWRlci5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxiYXJHbHlwaClcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICBzY3JvbGxiYXJHbHlwaC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbGJhckdseXBoLCB0cnVlKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGMuc2Nyb2xsYmFyV2lkdGgpXG4gICAgICAgIC5hdHRyKCdzdHJva2UtbGluZWNhcCcsICdyb3VuZCcpXG4gICAgICAgIC5hdHRyKCd5MScsIGMuc2Nyb2xsYmFyV2lkdGggLyAyKTtcblxuICAgIHNjcm9sbGJhckdseXBoXG4gICAgICAgIC5hdHRyKCd5MicsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnNjcm9sbGJhclN0YXRlLmJhckxlbmd0aCAtIGMuc2Nyb2xsYmFyV2lkdGggLyAyO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jb2x1bW5EcmFnSW5Qcm9ncmVzcyB8fCAhZC5zY3JvbGxiYXJTdGF0ZS5iYXJXaWdnbGVSb29tIHx8IGJ5cGFzc1Zpc2libGVCYXIgPyAwIDogMC40O1xuICAgICAgICB9KTtcblxuICAgIC8vIGNhbmNlbCB0cmFuc2l0aW9uOiBwb3NzaWJsZSBwZW5kaW5nIChhbHNvLCBkZWxheWVkKSB0cmFuc2l0aW9uXG4gICAgc2Nyb2xsYmFyR2x5cGhcbiAgICAgICAgLnRyYW5zaXRpb24oKS5kZWxheSgwKS5kdXJhdGlvbigwKTtcblxuICAgIHNjcm9sbGJhckdseXBoXG4gICAgICAgIC50cmFuc2l0aW9uKCkuZGVsYXkoYy5zY3JvbGxiYXJIaWRlRGVsYXkpLmR1cmF0aW9uKGMuc2Nyb2xsYmFySGlkZUR1cmF0aW9uKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAwKTtcblxuICAgIHZhciBzY3JvbGxiYXJDYXB0dXJlWm9uZSA9IHNjcm9sbGJhci5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxiYXJDYXB0dXJlWm9uZSlcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICBzY3JvbGxiYXJDYXB0dXJlWm9uZS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbGJhckNhcHR1cmVab25lLCB0cnVlKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ3doaXRlJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1vcGFjaXR5JywgMC4wMSkgLy8gc29tZSBicm93c2VyIG1pZ2h0IGdldCByaWQgb2YgYSAwIG9wYWNpdHkgZWxlbWVudFxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYy5zY3JvbGxiYXJDYXB0dXJlV2lkdGgpXG4gICAgICAgIC5hdHRyKCdzdHJva2UtbGluZWNhcCcsICdidXR0JylcbiAgICAgICAgLmF0dHIoJ3kxJywgMClcbiAgICAgICAgLm9uKCdtb3VzZWRvd24nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgeSA9IGQzLmV2ZW50Lnk7XG4gICAgICAgICAgICB2YXIgYmJveCA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB2YXIgcyA9IGQuc2Nyb2xsYmFyU3RhdGU7XG4gICAgICAgICAgICB2YXIgcGl4ZWxWYWwgPSB5IC0gYmJveC50b3A7XG4gICAgICAgICAgICB2YXIgaW52ZXJzZVNjYWxlID0gZDMuc2NhbGUubGluZWFyKCkuZG9tYWluKFswLCBzLnNjcm9sbGFibGVBcmVhSGVpZ2h0XSkucmFuZ2UoWzAsIHMudG90YWxIZWlnaHRdKS5jbGFtcCh0cnVlKTtcbiAgICAgICAgICAgIGlmKCEocy50b3BZIDw9IHBpeGVsVmFsICYmIHBpeGVsVmFsIDw9IHMuYm90dG9tWSkpIHtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ1JvdyhnZCwgdGFibGVDb250cm9sVmlldywgbnVsbCwgaW52ZXJzZVNjYWxlKHBpeGVsVmFsIC0gcy5iYXJMZW5ndGggLyAyKSkoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9yaWdpbihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgZC5zY3JvbGxiYXJTdGF0ZS5zY3JvbGxiYXJTY3JvbGxJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZDtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2RyYWcnLCBtYWtlRHJhZ1JvdyhnZCwgdGFibGVDb250cm9sVmlldykpXG4gICAgICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXhtZSBlbWl0IFBsb3RseSBldmVudFxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgIHNjcm9sbGJhckNhcHR1cmVab25lXG4gICAgICAgIC5hdHRyKCd5MicsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnNjcm9sbGJhclN0YXRlLnNjcm9sbGFibGVBcmVhSGVpZ2h0O1xuICAgICAgICB9KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQ29sdW1uQ2VsbFRyZWUoZ2QsIHRhYmxlQ29udHJvbFZpZXcsIGNvbHVtbkJsb2NrLCBhbGxDb2x1bW5CbG9jaykge1xuICAgIC8vIGZpeG1lIHRoaXMgcGVyZiBob3RzcG90XG4gICAgLy8gdGhpcyBpcyBwZXJmb3JtYW5jZSBjcml0aWNhbCBjb2RlIGFzIHNjcm9sbGluZyBjYWxscyBpdCBvbiBldmVyeSByZXZvbHZlciBzd2l0Y2hcbiAgICAvLyBpdCBhcHBlYXJzIHN1ZmZpY2llbnRseSBmYXN0IGJ1dCB0aGVyZSBhcmUgcGxlbnR5IG9mIGxvdy1oYW5naW5nIGZydWl0cyBmb3IgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uXG5cbiAgICB2YXIgY29sdW1uQ2VsbHMgPSByZW5kZXJDb2x1bW5DZWxscyhjb2x1bW5CbG9jayk7XG5cbiAgICB2YXIgY29sdW1uQ2VsbCA9IHJlbmRlckNvbHVtbkNlbGwoY29sdW1uQ2VsbHMpO1xuXG4gICAgc3VwcGx5U3R5bGluZ1ZhbHVlcyhjb2x1bW5DZWxsKTtcblxuICAgIHZhciBjZWxsUmVjdCA9IHJlbmRlckNlbGxSZWN0KGNvbHVtbkNlbGwpO1xuXG4gICAgc2l6ZUFuZFN0eWxlUmVjdChjZWxsUmVjdCk7XG5cbiAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSByZW5kZXJDZWxsVGV4dEhvbGRlcihjb2x1bW5DZWxsKTtcblxuICAgIHZhciBjZWxsVGV4dCA9IHJlbmRlckNlbGxUZXh0KGNlbGxUZXh0SG9sZGVyKTtcblxuICAgIHNldEZvbnQoY2VsbFRleHQpO1xuICAgIHBvcHVsYXRlQ2VsbFRleHQoY2VsbFRleHQsIHRhYmxlQ29udHJvbFZpZXcsIGFsbENvbHVtbkJsb2NrLCBnZCk7XG5cbiAgICAvLyBkb2luZyB0aGlzIGF0IHRoZSBlbmQgd2hlbiB0ZXh0LCBhbmQgdGV4dCBzdGx5aW5nIGFyZSBzZXRcbiAgICBzZXRDZWxsSGVpZ2h0QW5kUG9zaXRpb25ZKGNvbHVtbkNlbGwpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJDb2x1bW5DZWxscyhjb2x1bW5CbG9jaykge1xuXG4gICAgdmFyIGNvbHVtbkNlbGxzID0gY29sdW1uQmxvY2suc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQ2VsbHMpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgY29sdW1uQ2VsbHMuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jb2x1bW5DZWxscywgdHJ1ZSk7XG5cbiAgICBjb2x1bW5DZWxscy5leGl0KClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgcmV0dXJuIGNvbHVtbkNlbGxzO1xufVxuXG5mdW5jdGlvbiByZW5kZXJDb2x1bW5DZWxsKGNvbHVtbkNlbGxzKSB7XG5cbiAgICB2YXIgY29sdW1uQ2VsbCA9IGNvbHVtbkNlbGxzLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNvbHVtbkNlbGwpXG4gICAgICAgIC5kYXRhKHNwbGl0RGF0YS5zcGxpdFRvQ2VsbHMsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5rZXlXaXRoaW5CbG9jazt9KTtcblxuICAgIGNvbHVtbkNlbGwuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jb2x1bW5DZWxsLCB0cnVlKTtcblxuICAgIGNvbHVtbkNlbGwuZXhpdCgpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHJldHVybiBjb2x1bW5DZWxsO1xufVxuXG5mdW5jdGlvbiByZW5kZXJDZWxsUmVjdChjb2x1bW5DZWxsKSB7XG5cbiAgICB2YXIgY2VsbFJlY3QgPSBjb2x1bW5DZWxsLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNlbGxSZWN0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBmdW5jdGlvbihkKSB7cmV0dXJuIGQua2V5V2l0aGluQmxvY2s7fSk7XG5cbiAgICBjZWxsUmVjdC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNlbGxSZWN0LCB0cnVlKTtcblxuICAgIHJldHVybiBjZWxsUmVjdDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQ2VsbFRleHQoY2VsbFRleHRIb2xkZXIpIHtcblxuICAgIHZhciBjZWxsVGV4dCA9IGNlbGxUZXh0SG9sZGVyLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNlbGxUZXh0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBmdW5jdGlvbihkKSB7cmV0dXJuIGQua2V5V2l0aGluQmxvY2s7fSk7XG5cbiAgICBjZWxsVGV4dC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNlbGxUZXh0LCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsIGZ1bmN0aW9uKCkge3JldHVybiAnYXV0byc7fSlcbiAgICAgICAgLm9uKCdtb3VzZWRvd24nLCBmdW5jdGlvbigpIHtkMy5ldmVudC5zdG9wUHJvcGFnYXRpb24oKTt9KTtcblxuICAgIHJldHVybiBjZWxsVGV4dDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQ2VsbFRleHRIb2xkZXIoY29sdW1uQ2VsbCkge1xuXG4gICAgdmFyIGNlbGxUZXh0SG9sZGVyID0gY29sdW1uQ2VsbC5zZWxlY3RBbGwoJy4nICsgYy5jbi5jZWxsVGV4dEhvbGRlcilcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZnVuY3Rpb24oZCkge3JldHVybiBkLmtleVdpdGhpbkJsb2NrO30pO1xuXG4gICAgY2VsbFRleHRIb2xkZXIuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jZWxsVGV4dEhvbGRlciwgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdzaGFwZS1yZW5kZXJpbmcnLCAnZ2VvbWV0cmljUHJlY2lzaW9uJyk7XG5cbiAgICByZXR1cm4gY2VsbFRleHRIb2xkZXI7XG59XG5cbmZ1bmN0aW9uIHN1cHBseVN0eWxpbmdWYWx1ZXMoY29sdW1uQ2VsbCkge1xuICAgIGNvbHVtbkNlbGxcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgdmFyIHNwZWMgPSBkLmNhbGNkYXRhLmNlbGxzLmZvbnQ7XG4gICAgICAgICAgICB2YXIgY29sID0gZC5jb2x1bW4uc3BlY0luZGV4O1xuICAgICAgICAgICAgdmFyIGZvbnQgPSB7XG4gICAgICAgICAgICAgICAgc2l6ZTogZ3JpZFBpY2soc3BlYy5zaXplLCBjb2wsIGkpLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBncmlkUGljayhzcGVjLmNvbG9yLCBjb2wsIGkpLFxuICAgICAgICAgICAgICAgIGZhbWlseTogZ3JpZFBpY2soc3BlYy5mYW1pbHksIGNvbCwgaSlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBkLnJvd051bWJlciA9IGQua2V5O1xuICAgICAgICAgICAgZC5hbGlnbiA9IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMuYWxpZ24sIGNvbCwgaSk7XG4gICAgICAgICAgICBkLmNlbGxCb3JkZXJXaWR0aCA9IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMubGluZS53aWR0aCwgY29sLCBpKTtcbiAgICAgICAgICAgIGQuZm9udCA9IGZvbnQ7XG4gICAgICAgIH0pO1xufVxuXG5mdW5jdGlvbiBzZXRGb250KGNlbGxUZXh0KSB7XG4gICAgY2VsbFRleHRcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgRHJhd2luZy5mb250KGQzLnNlbGVjdCh0aGlzKSwgZC5mb250KTtcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemVBbmRTdHlsZVJlY3QoY2VsbFJlY3QpIHtcbiAgICBjZWxsUmVjdFxuICAgICAgICAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuY29sdW1uLmNvbHVtbldpZHRoO30pXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuY2VsbEJvcmRlcldpZHRoO30pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBhdG9taWNTZWxlY3Rpb24gPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBDb2xvci5zdHJva2UoYXRvbWljU2VsZWN0aW9uLCBncmlkUGljayhkLmNhbGNkYXRhLmNlbGxzLmxpbmUuY29sb3IsIGQuY29sdW1uLnNwZWNJbmRleCwgZC5yb3dOdW1iZXIpKTtcbiAgICAgICAgICAgIENvbG9yLmZpbGwoYXRvbWljU2VsZWN0aW9uLCBncmlkUGljayhkLmNhbGNkYXRhLmNlbGxzLmZpbGwuY29sb3IsIGQuY29sdW1uLnNwZWNJbmRleCwgZC5yb3dOdW1iZXIpKTtcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIHBvcHVsYXRlQ2VsbFRleHQoY2VsbFRleHQsIHRhYmxlQ29udHJvbFZpZXcsIGFsbENvbHVtbkJsb2NrLCBnZCkge1xuICAgIGNlbGxUZXh0XG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHtcblxuICAgICAgICAgICAgdmFyIGNvbCA9IGQuY29sdW1uLnNwZWNJbmRleDtcbiAgICAgICAgICAgIHZhciByb3cgPSBkLnJvd051bWJlcjtcblxuICAgICAgICAgICAgdmFyIHVzZXJTdXBwbGllZENvbnRlbnQgPSBkLnZhbHVlO1xuICAgICAgICAgICAgdmFyIHN0cmluZ1N1cHBsaWVkID0gKHR5cGVvZiB1c2VyU3VwcGxpZWRDb250ZW50ID09PSAnc3RyaW5nJyk7XG4gICAgICAgICAgICB2YXIgaGFzQnJlYWtzID0gc3RyaW5nU3VwcGxpZWQgJiYgdXNlclN1cHBsaWVkQ29udGVudC5tYXRjaCgvPGJyPi9pKTtcbiAgICAgICAgICAgIHZhciB1c2VyQnJva2VuVGV4dCA9ICFzdHJpbmdTdXBwbGllZCB8fCBoYXNCcmVha3M7XG4gICAgICAgICAgICBkLm1heUhhdmVNYXJrdXAgPSBzdHJpbmdTdXBwbGllZCAmJiB1c2VyU3VwcGxpZWRDb250ZW50Lm1hdGNoKC9bPCY+XS8pO1xuXG4gICAgICAgICAgICB2YXIgbGF0ZXggPSBpc0xhdGV4KHVzZXJTdXBwbGllZENvbnRlbnQpO1xuICAgICAgICAgICAgZC5sYXRleCA9IGxhdGV4O1xuXG4gICAgICAgICAgICB2YXIgcHJlZml4ID0gbGF0ZXggPyAnJyA6IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMucHJlZml4LCBjb2wsIHJvdykgfHwgJyc7XG4gICAgICAgICAgICB2YXIgc3VmZml4ID0gbGF0ZXggPyAnJyA6IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMuc3VmZml4LCBjb2wsIHJvdykgfHwgJyc7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gbGF0ZXggPyBudWxsIDogZ3JpZFBpY2soZC5jYWxjZGF0YS5jZWxscy5mb3JtYXQsIGNvbCwgcm93KSB8fCBudWxsO1xuXG4gICAgICAgICAgICB2YXIgcHJlZml4U3VmZml4ZWRUZXh0ID0gcHJlZml4ICsgKGZvcm1hdCA/IGQzLmZvcm1hdChmb3JtYXQpKGQudmFsdWUpIDogZC52YWx1ZSkgKyBzdWZmaXg7XG5cbiAgICAgICAgICAgIHZhciBoYXNXcmFwU3BsaXRDaGFyYWN0ZXI7XG4gICAgICAgICAgICBkLndyYXBwaW5nTmVlZGVkID0gIWQud3JhcHBlZCAmJiAhdXNlckJyb2tlblRleHQgJiYgIWxhdGV4ICYmIChoYXNXcmFwU3BsaXRDaGFyYWN0ZXIgPSBoYXNXcmFwQ2hhcmFjdGVyKHByZWZpeFN1ZmZpeGVkVGV4dCkpO1xuICAgICAgICAgICAgZC5jZWxsSGVpZ2h0TWF5SW5jcmVhc2UgPSBoYXNCcmVha3MgfHwgbGF0ZXggfHwgZC5tYXlIYXZlTWFya3VwIHx8IChoYXNXcmFwU3BsaXRDaGFyYWN0ZXIgPT09IHZvaWQoMCkgPyBoYXNXcmFwQ2hhcmFjdGVyKHByZWZpeFN1ZmZpeGVkVGV4dCkgOiBoYXNXcmFwU3BsaXRDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgZC5uZWVkc0NvbnZlcnRUb1RzcGFucyA9IGQubWF5SGF2ZU1hcmt1cCB8fCBkLndyYXBwaW5nTmVlZGVkIHx8IGQubGF0ZXg7XG5cbiAgICAgICAgICAgIHZhciB0ZXh0VG9SZW5kZXI7XG4gICAgICAgICAgICBpZihkLndyYXBwaW5nTmVlZGVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhyZWZQcmVzZXJ2ZWRUZXh0ID0gYy53cmFwU3BsaXRDaGFyYWN0ZXIgPT09ICcgJyA/IHByZWZpeFN1ZmZpeGVkVGV4dC5yZXBsYWNlKC88YSBocmVmPS9pZywgJzxhX2hyZWY9JykgOiBwcmVmaXhTdWZmaXhlZFRleHQ7XG4gICAgICAgICAgICAgICAgdmFyIGZyYWdtZW50cyA9IGhyZWZQcmVzZXJ2ZWRUZXh0LnNwbGl0KGMud3JhcFNwbGl0Q2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICB2YXIgaHJlZlJlc3RvcmVkRnJhZ21lbnRzID0gYy53cmFwU3BsaXRDaGFyYWN0ZXIgPT09ICcgJyA/IGZyYWdtZW50cy5tYXAoZnVuY3Rpb24oZnJhZykge3JldHVybiBmcmFnLnJlcGxhY2UoLzxhX2hyZWY9L2lnLCAnPGEgaHJlZj0nKTt9KSA6IGZyYWdtZW50cztcbiAgICAgICAgICAgICAgICBkLmZyYWdtZW50cyA9IGhyZWZSZXN0b3JlZEZyYWdtZW50cy5tYXAoZnVuY3Rpb24oZikge3JldHVybiB7dGV4dDogZiwgd2lkdGg6IG51bGx9O30pO1xuICAgICAgICAgICAgICAgIGQuZnJhZ21lbnRzLnB1c2goe2ZyYWdtZW50OiBjLndyYXBTcGFjZXIsIHdpZHRoOiBudWxsfSk7XG4gICAgICAgICAgICAgICAgdGV4dFRvUmVuZGVyID0gaHJlZlJlc3RvcmVkRnJhZ21lbnRzLmpvaW4oYy5saW5lQnJlYWtlcikgKyBjLmxpbmVCcmVha2VyICsgYy53cmFwU3BhY2VyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgZC5mcmFnbWVudHM7XG4gICAgICAgICAgICAgICAgdGV4dFRvUmVuZGVyID0gcHJlZml4U3VmZml4ZWRUZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGV4dFRvUmVuZGVyO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZHknLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5uZWVkc0NvbnZlcnRUb1RzcGFucyA/IDAgOiAnMC43NWVtJztcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuXG4gICAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgc2VsZWN0aW9uID0gZDMuc2VsZWN0KGVsZW1lbnQpO1xuXG4gICAgICAgICAgICAvLyBmaW5hbGl6ZSB3aGF0J3MgaW4gdGhlIERPTVxuXG4gICAgICAgICAgICB2YXIgcmVuZGVyQ2FsbGJhY2sgPSBkLndyYXBwaW5nTmVlZGVkID8gd3JhcFRleHRNYWtlciA6IHVwZGF0ZVlQb3NpdGlvbk1ha2VyO1xuICAgICAgICAgICAgaWYoZC5uZWVkc0NvbnZlcnRUb1RzcGFucykge1xuICAgICAgICAgICAgICAgIHN2Z1V0aWwuY29udmVydFRvVHNwYW5zKHNlbGVjdGlvbiwgZ2QsIHJlbmRlckNhbGxiYWNrKGFsbENvbHVtbkJsb2NrLCBlbGVtZW50LCB0YWJsZUNvbnRyb2xWaWV3LCBnZCwgZCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKVxuICAgICAgICAgICAgICAgICAgICAvLyBiYXNpYyBjZWxsIGFkanVzdG1lbnQgLSBjb21wbGlhbmNlIHdpdGggYGNlbGxQYWRgXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7cmV0dXJuICd0cmFuc2xhdGUoJyArIHhQb3NpdGlvbihkKSArICcgJyArIGMuY2VsbFBhZCArICcpJzt9KVxuICAgICAgICAgICAgICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiAnc3RhcnQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbnRlcjogJ21pZGRsZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQ6ICdlbmQnXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVtkLmFsaWduXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xufVxuXG5mdW5jdGlvbiBpc0xhdGV4KGNvbnRlbnQpIHtcbiAgICByZXR1cm4gdHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnICYmIGNvbnRlbnQubWF0Y2goYy5sYXRleENoZWNrKTtcbn1cblxuZnVuY3Rpb24gaGFzV3JhcENoYXJhY3Rlcih0ZXh0KSB7cmV0dXJuIHRleHQuaW5kZXhPZihjLndyYXBTcGxpdENoYXJhY3RlcikgIT09IC0xO31cblxuZnVuY3Rpb24gY29sdW1uTW92ZWQoZ2QsIGNhbGNkYXRhLCBpbmRpY2VzKSB7XG4gICAgdmFyIG8gPSBjYWxjZGF0YS5nZENvbHVtbnNPcmlnaW5hbE9yZGVyO1xuICAgIGNhbGNkYXRhLmdkQ29sdW1ucy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGluZGljZXNbby5pbmRleE9mKGEpXSAtIGluZGljZXNbby5pbmRleE9mKGIpXTtcbiAgICB9KTtcblxuICAgIGNhbGNkYXRhLmNvbHVtbm9yZGVyID0gaW5kaWNlcztcblxuICAgIGdkLmVtaXQoJ3Bsb3RseV9yZXN0eWxlJyk7XG59XG5cbmZ1bmN0aW9uIGdyaWRQaWNrKHNwZWMsIGNvbCwgcm93KSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShzcGVjKSkge1xuICAgICAgICB2YXIgY29sdW1uID0gc3BlY1tNYXRoLm1pbihjb2wsIHNwZWMubGVuZ3RoIC0gMSldO1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KGNvbHVtbikpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW5bTWF0aC5taW4ocm93LCBjb2x1bW4ubGVuZ3RoIC0gMSldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbjtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBzcGVjO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZWFzZUNvbHVtbihzZWxlY3Rpb24sIGQsIHkpIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLnJlbGVhc2VUcmFuc2l0aW9uRWFzZSlcbiAgICAgICAgLmR1cmF0aW9uKGMucmVsZWFzZVRyYW5zaXRpb25EdXJhdGlvbilcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGQueCArICcgJyArIHkgKyAnKScpO1xufVxuXG5mdW5jdGlvbiBjZWxsc0Jsb2NrKGQpIHtyZXR1cm4gZC50eXBlID09PSAnY2VsbHMnO31cbmZ1bmN0aW9uIGhlYWRlckJsb2NrKGQpIHtyZXR1cm4gZC50eXBlID09PSAnaGVhZGVyJzt9XG5cbi8qKlxuICogUmV2b2x2ZXIgcGFuZWwgYW5kIGNlbGwgY29udGVudHMgbGF5b3V0aW5nXG4gKi9cblxuZnVuY3Rpb24gaGVhZGVySGVpZ2h0KGQpIHtcbiAgICB2YXIgaGVhZGVyQmxvY2tzID0gZC5yb3dCbG9ja3MubGVuZ3RoID8gZC5yb3dCbG9ja3NbMF0uYXV4aWxpYXJ5QmxvY2tzIDogW107XG4gICAgcmV0dXJuIGhlYWRlckJsb2Nrcy5yZWR1Y2UoZnVuY3Rpb24ocCwgbikge3JldHVybiBwICsgcm93c0hlaWdodChuLCBJbmZpbml0eSk7fSwgMCk7XG59XG5cbmZ1bmN0aW9uIGZpbmRQYWdlc0FuZENhY2hlSGVpZ2h0cyhibG9ja3MsIHNjcm9sbFksIHNjcm9sbEhlaWdodCkge1xuXG4gICAgdmFyIHBhZ2VzID0gW107XG4gICAgdmFyIHBUb3AgPSAwO1xuXG4gICAgZm9yKHZhciBibG9ja0luZGV4ID0gMDsgYmxvY2tJbmRleCA8IGJsb2Nrcy5sZW5ndGg7IGJsb2NrSW5kZXgrKykge1xuXG4gICAgICAgIHZhciBibG9jayA9IGJsb2Nrc1tibG9ja0luZGV4XTtcbiAgICAgICAgdmFyIGJsb2NrUm93cyA9IGJsb2NrLnJvd3M7XG4gICAgICAgIHZhciByb3dzSGVpZ2h0ID0gMDtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGJsb2NrUm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcm93c0hlaWdodCArPSBibG9ja1Jvd3NbaV0ucm93SGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2FjaGluZyBhbGxSb3dzSGVpZ2h0IG9uIHRoZSBibG9jayAtIGl0J3Mgc2FmZSBhcyB0aGlzIGZ1bmN0aW9uIGlzIGFsd2F5cyBjYWxsZWQgZnJvbSB3aXRoaW4gdGhlIGNvZGUgcGFydFxuICAgICAgICAvLyB0aGF0IGhhbmRsZXMgaW5jcmVhc2VzIHRvIHJvdyBoZWlnaHRzXG4gICAgICAgIGJsb2NrLmFsbFJvd3NIZWlnaHQgPSByb3dzSGVpZ2h0O1xuXG4gICAgICAgIHZhciBwQm90dG9tID0gcFRvcCArIHJvd3NIZWlnaHQ7XG4gICAgICAgIHZhciB3aW5kb3dUb3AgPSBzY3JvbGxZO1xuICAgICAgICB2YXIgd2luZG93Qm90dG9tID0gd2luZG93VG9wICsgc2Nyb2xsSGVpZ2h0O1xuICAgICAgICBpZih3aW5kb3dUb3AgPCBwQm90dG9tICYmIHdpbmRvd0JvdHRvbSA+IHBUb3ApIHtcbiAgICAgICAgICAgIHBhZ2VzLnB1c2goYmxvY2tJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgcFRvcCArPSByb3dzSGVpZ2h0O1xuXG4gICAgICAgIC8vIGNvbnNpZGVyIHRoaXMgbmljZSBmaW5hbCBvcHRpbWl6YXRpb247IHB1dCBpdCBpbiBgZm9yYCBjb25kaXRpb24gLSBjYXZlYXQsIGN1cnJlbnRseSB0aGVcbiAgICAgICAgLy8gYmxvY2suYWxsUm93c0hlaWdodCByZWxpZXMgb24gYmVpbmcgaW52YWxpZGF0ZWQsIHNvIGVuYWJsaW5nIHRoaXMgb3B0IG1heSBub3QgYmUgc2FmZVxuICAgICAgICAvLyBpZihwYWdlcy5sZW5ndGggPiAxKSBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gcGFnZXM7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUJsb2NrWVBvc2l0aW9uKGdkLCBjZWxsc0NvbHVtbkJsb2NrLCB0YWJsZUNvbnRyb2xWaWV3KSB7XG4gICAgdmFyIGQgPSBmbGF0RGF0YShjZWxsc0NvbHVtbkJsb2NrKVswXTtcbiAgICBpZihkID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICB2YXIgYmxvY2tzID0gZC5yb3dCbG9ja3M7XG4gICAgdmFyIGNhbGNkYXRhID0gZC5jYWxjZGF0YTtcblxuICAgIHZhciBib3R0b20gPSBmaXJzdFJvd0FuY2hvcihibG9ja3MsIGJsb2Nrcy5sZW5ndGgpO1xuICAgIHZhciBzY3JvbGxIZWlnaHQgPSBkLmNhbGNkYXRhLmdyb3VwSGVpZ2h0IC0gaGVhZGVySGVpZ2h0KGQpO1xuICAgIHZhciBzY3JvbGxZID0gY2FsY2RhdGEuc2Nyb2xsWSA9IE1hdGgubWF4KDAsIE1hdGgubWluKGJvdHRvbSAtIHNjcm9sbEhlaWdodCwgY2FsY2RhdGEuc2Nyb2xsWSkpO1xuXG4gICAgdmFyIHBhZ2VzID0gZmluZFBhZ2VzQW5kQ2FjaGVIZWlnaHRzKGJsb2Nrcywgc2Nyb2xsWSwgc2Nyb2xsSGVpZ2h0KTtcbiAgICBpZihwYWdlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgaWYocGFnZXNbMF0gPT09IGJsb2Nrcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBwYWdlcy51bnNoaWZ0KHBhZ2VzWzBdIC0gMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYWdlcy5wdXNoKHBhZ2VzWzBdICsgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtYWtlIHBoYXNlZCBvdXQgcGFnZSBqdW1wIGJ5IDIgd2hpbGUgbGVhdmluZyBzdGF0aW9uYXJ5IHBhZ2UgaW50YWN0XG4gICAgaWYocGFnZXNbMF0gJSAyKSB7XG4gICAgICAgIHBhZ2VzLnJldmVyc2UoKTtcbiAgICB9XG5cbiAgICBjZWxsc0NvbHVtbkJsb2NrXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIC8vIHRoZXNlIHZhbHVlcyB3aWxsIGFsc28gYmUgbmVlZGVkIHdoZW4gYSBibG9jayBpcyB0cmFuc2xhdGVkIGFnYWluIGR1ZSB0byBncm93aW5nIGNlbGwgaGVpZ2h0XG4gICAgICAgICAgICBkLnBhZ2UgPSBwYWdlc1tpXTtcbiAgICAgICAgICAgIGQuc2Nyb2xsWSA9IHNjcm9sbFk7XG4gICAgICAgIH0pO1xuXG4gICAgY2VsbHNDb2x1bW5CbG9ja1xuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHlUcmFuc2xhdGUgPSBmaXJzdFJvd0FuY2hvcihkLnJvd0Jsb2NrcywgZC5wYWdlKSAtIGQuc2Nyb2xsWTtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKDAgJyArIHlUcmFuc2xhdGUgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gY29uZGl0aW9uYWxseSByZXJlbmRlcmluZyBwYW5lbCAwIGFuZCAxXG4gICAgaWYoZ2QpIHtcbiAgICAgICAgY29uZGl0aW9uYWxQYW5lbFJlcmVuZGVyKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBjZWxsc0NvbHVtbkJsb2NrLCBwYWdlcywgZC5wcmV2UGFnZXMsIGQsIDApO1xuICAgICAgICBjb25kaXRpb25hbFBhbmVsUmVyZW5kZXIoZ2QsIHRhYmxlQ29udHJvbFZpZXcsIGNlbGxzQ29sdW1uQmxvY2ssIHBhZ2VzLCBkLnByZXZQYWdlcywgZCwgMSk7XG4gICAgICAgIHJlbmRlclNjcm9sbGJhcktpdCh0YWJsZUNvbnRyb2xWaWV3LCBnZCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtYWtlRHJhZ1JvdyhnZCwgYWxsVGFibGVDb250cm9sVmlldywgb3B0aW9uYWxNdWx0aXBsaWVyLCBvcHRpb25hbFBvc2l0aW9uKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGRyYWdSb3coZXZlbnREKSB7XG4gICAgICAgIC8vIG1heSBjb21lIGZyb20gd2hpY2V2ZXIgRE9NIGV2ZW50IHRhcmdldDogZHJhZywgd2hlZWwsIGJhci4uLiBldmVudEQgY29ycmVzcG9uZHMgdG8gZXZlbnQgdGFyZ2V0XG4gICAgICAgIHZhciBkID0gZXZlbnRELmNhbGNkYXRhID8gZXZlbnRELmNhbGNkYXRhIDogZXZlbnREO1xuICAgICAgICB2YXIgdGFibGVDb250cm9sVmlldyA9IGFsbFRhYmxlQ29udHJvbFZpZXcuZmlsdGVyKGZ1bmN0aW9uKGRkKSB7cmV0dXJuIGQua2V5ID09PSBkZC5rZXk7fSk7XG4gICAgICAgIHZhciBtdWx0aXBsaWVyID0gb3B0aW9uYWxNdWx0aXBsaWVyIHx8IGQuc2Nyb2xsYmFyU3RhdGUuZHJhZ011bHRpcGxpZXI7XG4gICAgICAgIGQuc2Nyb2xsWSA9IG9wdGlvbmFsUG9zaXRpb24gPT09IHZvaWQoMCkgPyBkLnNjcm9sbFkgKyBtdWx0aXBsaWVyICogZDMuZXZlbnQuZHkgOiBvcHRpb25hbFBvc2l0aW9uO1xuICAgICAgICB2YXIgY2VsbHNDb2x1bW5CbG9jayA9IHRhYmxlQ29udHJvbFZpZXcuc2VsZWN0QWxsKCcuJyArIGMuY24ueUNvbHVtbikuc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQmxvY2spLmZpbHRlcihjZWxsc0Jsb2NrKTtcbiAgICAgICAgdXBkYXRlQmxvY2tZUG9zaXRpb24oZ2QsIGNlbGxzQ29sdW1uQmxvY2ssIHRhYmxlQ29udHJvbFZpZXcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNvbmRpdGlvbmFsUGFuZWxSZXJlbmRlcihnZCwgdGFibGVDb250cm9sVmlldywgY2VsbHNDb2x1bW5CbG9jaywgcGFnZXMsIHByZXZQYWdlcywgZCwgcmV2b2x2ZXJJbmRleCkge1xuICAgIHZhciBzaG91bGRDb21wb25lbnRVcGRhdGUgPSBwYWdlc1tyZXZvbHZlckluZGV4XSAhPT0gcHJldlBhZ2VzW3Jldm9sdmVySW5kZXhdO1xuICAgIGlmKHNob3VsZENvbXBvbmVudFVwZGF0ZSkge1xuICAgICAgICBjbGVhclRpbWVvdXQoZC5jdXJyZW50UmVwYWludFtyZXZvbHZlckluZGV4XSk7XG4gICAgICAgIGQuY3VycmVudFJlcGFpbnRbcmV2b2x2ZXJJbmRleF0gPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgLy8gc2V0VGltZW91dCBtaWdodCBsYWcgcmVuZGVyaW5nIGJ1dCB5aWVsZHMgYSBzbW9vdGhlciBzY3JvbGwsIGJlY2F1c2UgZmFzdCBzY3JvbGxpbmcgbWFrZXNcbiAgICAgICAgICAgIC8vIHNvbWUgcmVwYWludHMgaW52aXNpYmxlIGllLiB3YXN0ZWZ1bCAoRE9NIHdvcmsgYmxvY2tzIHRoZSBtYWluIHRocmVhZClcbiAgICAgICAgICAgIHZhciB0b1JlcmVuZGVyID0gY2VsbHNDb2x1bW5CbG9jay5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge3JldHVybiBpID09PSByZXZvbHZlckluZGV4ICYmIHBhZ2VzW2ldICE9PSBwcmV2UGFnZXNbaV07fSk7XG4gICAgICAgICAgICByZW5kZXJDb2x1bW5DZWxsVHJlZShnZCwgdGFibGVDb250cm9sVmlldywgdG9SZXJlbmRlciwgY2VsbHNDb2x1bW5CbG9jayk7XG4gICAgICAgICAgICBwcmV2UGFnZXNbcmV2b2x2ZXJJbmRleF0gPSBwYWdlc1tyZXZvbHZlckluZGV4XTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB3cmFwVGV4dE1ha2VyKGNvbHVtbkJsb2NrLCBlbGVtZW50LCB0YWJsZUNvbnRyb2xWaWV3KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHdyYXBUZXh0KCkge1xuICAgICAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICAgICAgY2VsbFRleHRIb2xkZXJcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnJhZ21lbnRzID0gZC5mcmFnbWVudHM7XG4gICAgICAgICAgICAgICAgY2VsbFRleHRIb2xkZXIuc2VsZWN0QWxsKCd0c3Bhbi5saW5lJykuZWFjaChmdW5jdGlvbihkZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBmcmFnbWVudHNbaV0ud2lkdGggPSB0aGlzLmdldENvbXB1dGVkVGV4dExlbmd0aCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIGxhc3QgZWxlbWVudCBpcyBvbmx5IGZvciBtZWFzdXJpbmcgdGhlIHNlcGFyYXRvciBjaGFyYWN0ZXIsIHNvIGl0J3MgaWdub3JlZDpcbiAgICAgICAgICAgICAgICB2YXIgc2VwYXJhdG9yTGVuZ3RoID0gZnJhZ21lbnRzW2ZyYWdtZW50cy5sZW5ndGggLSAxXS53aWR0aDtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdCA9IGZyYWdtZW50cy5zbGljZSgwLCAtMSk7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3cgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEFkZGl0aW9uLCBjdXJyZW50QWRkaXRpb25MZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3dMZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByb3dMZW5ndGhMaW1pdCA9IGQuY29sdW1uLmNvbHVtbldpZHRoIC0gMiAqIGMuY2VsbFBhZDtcbiAgICAgICAgICAgICAgICBkLnZhbHVlID0gJyc7XG4gICAgICAgICAgICAgICAgd2hpbGUocmVzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEFkZGl0aW9uID0gcmVzdC5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50QWRkaXRpb25MZW5ndGggPSBjdXJyZW50QWRkaXRpb24ud2lkdGggKyBzZXBhcmF0b3JMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRSb3dMZW5ndGggKyBjdXJyZW50QWRkaXRpb25MZW5ndGggPiByb3dMZW5ndGhMaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZC52YWx1ZSArPSBjdXJyZW50Um93LmpvaW4oYy53cmFwU3BhY2VyKSArIGMubGluZUJyZWFrZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93TGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93LnB1c2goY3VycmVudEFkZGl0aW9uLnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93TGVuZ3RoICs9IGN1cnJlbnRBZGRpdGlvbkxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoY3VycmVudFJvd0xlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBkLnZhbHVlICs9IGN1cnJlbnRSb3cuam9pbihjLndyYXBTcGFjZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkLndyYXBwZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gdGhlIHByZS13cmFwcGVkIHRleHQgd2FzIHJlbmRlcmVkIG9ubHkgZm9yIHRoZSB0ZXh0IG1lYXN1cmVtZW50c1xuICAgICAgICBjZWxsVGV4dEhvbGRlci5zZWxlY3RBbGwoJ3RzcGFuLmxpbmUnKS5yZW1vdmUoKTtcblxuICAgICAgICAvLyByZXN1cHBseSB0ZXh0LCBub3cgd3JhcHBlZFxuICAgICAgICBwb3B1bGF0ZUNlbGxUZXh0KGNlbGxUZXh0SG9sZGVyLnNlbGVjdCgnLicgKyBjLmNuLmNlbGxUZXh0KSwgdGFibGVDb250cm9sVmlldywgY29sdW1uQmxvY2spO1xuICAgICAgICBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlLnBhcmVudE5vZGUpLmNhbGwoc2V0Q2VsbEhlaWdodEFuZFBvc2l0aW9uWSk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlWVBvc2l0aW9uTWFrZXIoY29sdW1uQmxvY2ssIGVsZW1lbnQsIHRhYmxlQ29udHJvbFZpZXcsIGdkLCBkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHVwZGF0ZVlQb3NpdGlvbigpIHtcbiAgICAgICAgaWYoZC5zZXR0bGVkWSkgcmV0dXJuO1xuICAgICAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICAgICAgdmFyIGwgPSBnZXRCbG9jayhkKTtcbiAgICAgICAgdmFyIHJvd0luZGV4ID0gZC5rZXkgLSBsLmZpcnN0Um93SW5kZXg7XG5cbiAgICAgICAgdmFyIGRlY2xhcmVkUm93SGVpZ2h0ID0gbC5yb3dzW3Jvd0luZGV4XS5yb3dIZWlnaHQ7XG5cbiAgICAgICAgdmFyIHJlcXVpcmVkSGVpZ2h0ID0gZC5jZWxsSGVpZ2h0TWF5SW5jcmVhc2UgPyBlbGVtZW50LnBhcmVudE5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0ICsgMiAqIGMuY2VsbFBhZCA6IGRlY2xhcmVkUm93SGVpZ2h0O1xuXG4gICAgICAgIHZhciBmaW5hbEhlaWdodCA9IE1hdGgubWF4KHJlcXVpcmVkSGVpZ2h0LCBkZWNsYXJlZFJvd0hlaWdodCk7XG4gICAgICAgIHZhciBpbmNyZWFzZSA9IGZpbmFsSGVpZ2h0IC0gbC5yb3dzW3Jvd0luZGV4XS5yb3dIZWlnaHQ7XG5cbiAgICAgICAgaWYoaW5jcmVhc2UpIHtcblxuICAgICAgICAgICAgLy8gY3VycmVudCByb3cgaGVpZ2h0IGluY3JlYXNlZFxuICAgICAgICAgICAgbC5yb3dzW3Jvd0luZGV4XS5yb3dIZWlnaHQgPSBmaW5hbEhlaWdodDtcblxuICAgICAgICAgICAgY29sdW1uQmxvY2tcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQ2VsbClcbiAgICAgICAgICAgICAgICAuY2FsbChzZXRDZWxsSGVpZ2h0QW5kUG9zaXRpb25ZKTtcblxuICAgICAgICAgICAgdXBkYXRlQmxvY2tZUG9zaXRpb24obnVsbCwgY29sdW1uQmxvY2suZmlsdGVyKGNlbGxzQmxvY2spLCAwKTtcblxuICAgICAgICAgICAgLy8gaWYgZC5jb2x1bW4udHlwZSA9PT0gJ2hlYWRlcicsIHRoZW4gdGhlIHNjcm9sbGJhciBoYXMgdG8gYmUgcHVzaGVkIGRvd253YXJkIHRvIHRoZSBzY3JvbGxhYmxlIGFyZWFcbiAgICAgICAgICAgIC8vIGlmIGQuY29sdW1uLnR5cGUgPT09ICdjZWxscycsIGl0IGNhbiBzdGlsbCBiZSByZWxldmFudCBpZiB0b3RhbCBzY3JvbGxpbmcgY29udGVudCBoZWlnaHQgaXMgbGVzcyB0aGFuIHRoZVxuICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsYWJsZSB3aW5kb3csIGFzIGluY3JlYXNlcyB0byByb3cgaGVpZ2h0cyBtYXkgbmVlZCBzY3JvbGxiYXIgdXBkYXRlc1xuICAgICAgICAgICAgcmVuZGVyU2Nyb2xsYmFyS2l0KHRhYmxlQ29udHJvbFZpZXcsIGdkLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNlbGxUZXh0SG9sZGVyXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBjb2RlIGJsb2NrIGlzIG9ubHkgaW52b2tlZCBmb3IgaXRlbXMgd2hlcmUgZC5jZWxsSGVpZ2h0TWF5SW5jcmVhc2UgaXMgdHJ1dGh5XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5DZWxsRWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgYm94ID0gY29sdW1uQ2VsbEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHJlY3RCb3ggPSBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKS5zZWxlY3QoJy4nICsgYy5jbi5jZWxsUmVjdCkubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50VHJhbnNmb3JtID0gZWxlbWVudC50cmFuc2Zvcm0uYmFzZVZhbC5jb25zb2xpZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHZhciB5UG9zaXRpb24gPSByZWN0Qm94LnRvcCAtIGJveC50b3AgKyAoY3VycmVudFRyYW5zZm9ybSA/IGN1cnJlbnRUcmFuc2Zvcm0ubWF0cml4LmYgOiBjLmNlbGxQYWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyB4UG9zaXRpb24oZCwgZDMuc2VsZWN0KGVsZW1lbnQucGFyZW50Tm9kZSkuc2VsZWN0KCcuJyArIGMuY24uY2VsbFRleHRIb2xkZXIpLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCkgKyAnICcgKyB5UG9zaXRpb24gKyAnKSc7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBkLnNldHRsZWRZID0gdHJ1ZTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB4UG9zaXRpb24oZCwgb3B0aW9uYWxXaWR0aCkge1xuICAgIHN3aXRjaChkLmFsaWduKSB7XG4gICAgICAgIGNhc2UgJ2xlZnQnOiByZXR1cm4gYy5jZWxsUGFkO1xuICAgICAgICBjYXNlICdyaWdodCc6IHJldHVybiBkLmNvbHVtbi5jb2x1bW5XaWR0aCAtIChvcHRpb25hbFdpZHRoIHx8IDApIC0gYy5jZWxsUGFkO1xuICAgICAgICBjYXNlICdjZW50ZXInOiByZXR1cm4gKGQuY29sdW1uLmNvbHVtbldpZHRoIC0gKG9wdGlvbmFsV2lkdGggfHwgMCkpIC8gMjtcbiAgICAgICAgZGVmYXVsdDogcmV0dXJuIGMuY2VsbFBhZDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldENlbGxIZWlnaHRBbmRQb3NpdGlvblkoY29sdW1uQ2VsbCkge1xuICAgIGNvbHVtbkNlbGxcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBoZWFkZXJIZWlnaHQgPSBkLnJvd0Jsb2Nrc1swXS5hdXhpbGlhcnlCbG9ja3MucmVkdWNlKGZ1bmN0aW9uKHAsIG4pIHtyZXR1cm4gcCArIHJvd3NIZWlnaHQobiwgSW5maW5pdHkpO30sIDApO1xuICAgICAgICAgICAgdmFyIGwgPSBnZXRCbG9jayhkKTtcbiAgICAgICAgICAgIHZhciByb3dBbmNob3IgPSByb3dzSGVpZ2h0KGwsIGQua2V5KTtcbiAgICAgICAgICAgIHZhciB5T2Zmc2V0ID0gcm93QW5jaG9yICsgaGVhZGVySGVpZ2h0O1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoMCAnICsgeU9mZnNldCArICcpJztcbiAgICAgICAgfSlcbiAgICAgICAgLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNlbGxSZWN0KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge3JldHVybiBnZXRSb3coZ2V0QmxvY2soZCksIGQua2V5KS5yb3dIZWlnaHQ7fSk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0Um93QW5jaG9yKGJsb2NrcywgcGFnZSkge1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgZm9yKHZhciBpID0gcGFnZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHRvdGFsICs9IGFsbFJvd3NIZWlnaHQoYmxvY2tzW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuXG5mdW5jdGlvbiByb3dzSGVpZ2h0KHJvd0Jsb2NrLCBrZXkpIHtcbiAgICB2YXIgdG90YWwgPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCByb3dCbG9jay5yb3dzLmxlbmd0aCAmJiByb3dCbG9jay5yb3dzW2ldLnJvd0luZGV4IDwga2V5OyBpKyspIHtcbiAgICAgICAgdG90YWwgKz0gcm93QmxvY2sucm93c1tpXS5yb3dIZWlnaHQ7XG4gICAgfVxuICAgIHJldHVybiB0b3RhbDtcbn1cblxuZnVuY3Rpb24gYWxsUm93c0hlaWdodChyb3dCbG9jaykge1xuICAgIHZhciBjYWNoZWQgPSByb3dCbG9jay5hbGxSb3dzSGVpZ2h0O1xuXG4gICAgaWYoY2FjaGVkICE9PSB2b2lkKDApKSB7XG4gICAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgdmFyIHRvdGFsID0gMDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcm93QmxvY2sucm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0b3RhbCArPSByb3dCbG9jay5yb3dzW2ldLnJvd0hlaWdodDtcbiAgICB9XG4gICAgcm93QmxvY2suYWxsUm93c0hlaWdodCA9IHRvdGFsO1xuXG4gICAgcmV0dXJuIHRvdGFsO1xufVxuXG5mdW5jdGlvbiBnZXRCbG9jayhkKSB7cmV0dXJuIGQucm93QmxvY2tzW2QucGFnZV07fVxuZnVuY3Rpb24gZ2V0Um93KGwsIGkpIHtyZXR1cm4gbC5yb3dzW2kgLSBsLmZpcnN0Um93SW5kZXhdO31cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGJveEF0dHJzID0gcmVxdWlyZSgnLi4vYm94L2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gcmVxdWlyZSgnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHk6IGJveEF0dHJzLnksXG4gICAgeDogYm94QXR0cnMueCxcbiAgICB4MDogYm94QXR0cnMueDAsXG4gICAgeTA6IGJveEF0dHJzLnkwLFxuICAgIG5hbWU6IGJveEF0dHJzLm5hbWUsXG4gICAgb3JpZW50YXRpb246IGV4dGVuZEZsYXQoe30sIGJveEF0dHJzLm9yaWVudGF0aW9uLCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgYmFuZHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2NhbGVncm91cDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNjYWxlbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd3aWR0aCcsICdjb3VudCddLFxuICAgICAgICBkZmx0OiAnd2lkdGgnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNwYW5tb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3NvZnQnLCAnaGFyZCcsICdtYW51YWwnXSxcbiAgICAgICAgZGZsdDogJ3NvZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGFuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdjYWxjJ30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAnY2FsYyd9XG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGluZToge1xuICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAyLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG4gICAgZmlsbGNvbG9yOiBib3hBdHRycy5maWxsY29sb3IsXG5cbiAgICBwb2ludHM6IGV4dGVuZEZsYXQoe30sIGJveEF0dHJzLmJveHBvaW50cywge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBqaXR0ZXI6IGV4dGVuZEZsYXQoe30sIGJveEF0dHJzLmppdHRlciwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBwb2ludHBvczogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMucG9pbnRwb3MsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgbWFya2VyOiBib3hBdHRycy5tYXJrZXIsXG4gICAgdGV4dDogYm94QXR0cnMudGV4dCxcblxuICAgIGJveDoge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAwLjI1LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZpbGxjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgbWVhbmxpbmU6IHtcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG5cbiAgICBzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2JvdGgnLCAncG9zaXRpdmUnLCAnbmVnYXRpdmUnXSxcbiAgICAgICAgZGZsdDogJ2JvdGgnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNlbGVjdGVkOiBib3hBdHRycy5zZWxlY3RlZCxcbiAgICB1bnNlbGVjdGVkOiBib3hBdHRycy51bnNlbGVjdGVkLFxuXG4gICAgaG92ZXJvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWyd2aW9saW5zJywgJ3BvaW50cycsICdrZGUnXSxcbiAgICAgICAgZGZsdDogJ3Zpb2xpbnMrcG9pbnRzK2tkZScsXG4gICAgICAgIGV4dHJhczogWydhbGwnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgYm94Q2FsYyA9IHJlcXVpcmUoJy4uL2JveC9jYWxjJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xudmFyIEJBRE5VTSA9IHJlcXVpcmUoJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2QgPSBib3hDYWxjKGdkLCB0cmFjZSk7XG5cbiAgICBpZihjZFswXS50LmVtcHR5KSByZXR1cm4gY2Q7XG5cbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB2YWxBeGlzID0gQXhlcy5nZXRGcm9tSWQoXG4gICAgICAgIGdkLFxuICAgICAgICB0cmFjZVt0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8gJ3hheGlzJyA6ICd5YXhpcyddXG4gICAgKTtcblxuICAgIHZhciB2aW9saW5TY2FsZUdyb3VwU3RhdHMgPSBmdWxsTGF5b3V0Ll92aW9saW5TY2FsZUdyb3VwU3RhdHM7XG4gICAgdmFyIHNjYWxlR3JvdXAgPSB0cmFjZS5zY2FsZWdyb3VwO1xuICAgIHZhciBncm91cFN0YXRzID0gdmlvbGluU2NhbGVHcm91cFN0YXRzW3NjYWxlR3JvdXBdO1xuICAgIGlmKCFncm91cFN0YXRzKSB7XG4gICAgICAgIGdyb3VwU3RhdHMgPSB2aW9saW5TY2FsZUdyb3VwU3RhdHNbc2NhbGVHcm91cF0gPSB7XG4gICAgICAgICAgICBtYXhXaWR0aDogMCxcbiAgICAgICAgICAgIG1heENvdW50OiAwXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHNwYW5NaW4gPSBJbmZpbml0eTtcbiAgICB2YXIgc3Bhbk1heCA9IC1JbmZpbml0eTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2RpID0gY2RbaV07XG4gICAgICAgIHZhciB2YWxzID0gY2RpLnB0cy5tYXAoaGVscGVycy5leHRyYWN0VmFsKTtcblxuICAgICAgICB2YXIgYmFuZHdpZHRoID0gY2RpLmJhbmR3aWR0aCA9IGNhbGNCYW5kd2lkdGgodHJhY2UsIGNkaSwgdmFscyk7XG4gICAgICAgIHZhciBzcGFuID0gY2RpLnNwYW4gPSBjYWxjU3Bhbih0cmFjZSwgY2RpLCB2YWxBeGlzLCBiYW5kd2lkdGgpO1xuXG4gICAgICAgIC8vIHN0ZXAgdGhhdCB3ZWxsIGNvdmVycyB0aGUgYmFuZHdpZHRoIGFuZCBpcyBtdWx0aXBsZSBvZiBzcGFuIGRpc3RhbmNlXG4gICAgICAgIHZhciBkaXN0ID0gc3BhblsxXSAtIHNwYW5bMF07XG4gICAgICAgIHZhciBuID0gTWF0aC5jZWlsKGRpc3QgLyAoYmFuZHdpZHRoIC8gMykpO1xuICAgICAgICB2YXIgc3RlcCA9IGRpc3QgLyBuO1xuXG4gICAgICAgIGlmKCFpc0Zpbml0ZShzdGVwKSB8fCAhaXNGaW5pdGUobikpIHtcbiAgICAgICAgICAgIExpYi5lcnJvcignU29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCBjb21wdXRpbmcgdGhlIHZpb2xpbiBzcGFuJyk7XG4gICAgICAgICAgICBjZFswXS50LmVtcHR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBjZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBrZGUgPSBoZWxwZXJzLm1ha2VLREUoY2RpLCB0cmFjZSwgdmFscyk7XG4gICAgICAgIGNkaS5kZW5zaXR5ID0gbmV3IEFycmF5KG4pO1xuXG4gICAgICAgIGZvcih2YXIgayA9IDAsIHQgPSBzcGFuWzBdOyB0IDwgKHNwYW5bMV0gKyBzdGVwIC8gMik7IGsrKywgdCArPSBzdGVwKSB7XG4gICAgICAgICAgICB2YXIgdiA9IGtkZSh0KTtcbiAgICAgICAgICAgIGdyb3VwU3RhdHMubWF4V2lkdGggPSBNYXRoLm1heChncm91cFN0YXRzLm1heFdpZHRoLCB2KTtcbiAgICAgICAgICAgIGNkaS5kZW5zaXR5W2tdID0ge3Y6IHYsIHQ6IHR9O1xuICAgICAgICB9XG5cbiAgICAgICAgZ3JvdXBTdGF0cy5tYXhDb3VudCA9IE1hdGgubWF4KGdyb3VwU3RhdHMubWF4Q291bnQsIHZhbHMubGVuZ3RoKTtcblxuICAgICAgICBzcGFuTWluID0gTWF0aC5taW4oc3Bhbk1pbiwgc3BhblswXSk7XG4gICAgICAgIHNwYW5NYXggPSBNYXRoLm1heChzcGFuTWF4LCBzcGFuWzFdKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0cmVtZXMgPSBBeGVzLmZpbmRFeHRyZW1lcyh2YWxBeGlzLCBbc3Bhbk1pbiwgc3Bhbk1heF0sIHtwYWRkZWQ6IHRydWV9KTtcbiAgICB0cmFjZS5fZXh0cmVtZXNbdmFsQXhpcy5faWRdID0gZXh0cmVtZXM7XG5cbiAgICBjZFswXS50LmxhYmVscy5rZGUgPSBMaWIuXyhnZCwgJ2tkZTonKTtcblxuICAgIHJldHVybiBjZDtcbn07XG5cbi8vIERlZmF1bHQgdG8gU2lsdmVtYW4ncyBydWxlIG9mIHRodW1iXG4vLyAtIGh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vYS82NjcxXG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0tlcm5lbF9kZW5zaXR5X2VzdGltYXRpb24jQV9ydWxlLW9mLXRodW1iX2JhbmR3aWR0aF9lc3RpbWF0b3Jcbi8vIC0gaHR0cHM6Ly9naXRodWIuY29tL3N0YXRzbW9kZWxzL3N0YXRzbW9kZWxzL2Jsb2IvbWFzdGVyL3N0YXRzbW9kZWxzL25vbnBhcmFtZXRyaWMvYmFuZHdpZHRocy5weVxuZnVuY3Rpb24gc2lsdmVybWFuUnVsZShsZW4sIHNzZCwgaXFyKSB7XG4gICAgdmFyIGEgPSBNYXRoLm1pbihzc2QsIGlxciAvIDEuMzQ5KTtcbiAgICByZXR1cm4gMS4wNTkgKiBhICogTWF0aC5wb3cobGVuLCAtMC4yKTtcbn1cblxuZnVuY3Rpb24gY2FsY0JhbmR3aWR0aCh0cmFjZSwgY2RpLCB2YWxzKSB7XG4gICAgdmFyIHNwYW4gPSBjZGkubWF4IC0gY2RpLm1pbjtcblxuICAgIC8vIHBsb3Qgc2luZ2xlLXZhbHVlIHZpb2xpbiB3aXRoIGJhbmR3aWR0aCBvZiAxXG4gICAgaWYoIXNwYW4pIHJldHVybiAxO1xuXG4gICAgLy8gTGltaXQgaG93IHNtYWxsIHRoZSBiYW5kd2lkdGggY2FuIGJlLlxuICAgIC8vXG4gICAgLy8gU2lsdmVybWFuJ3MgcnVsZSBvZiB0aHVtYiBjYW4gYmUgXCJ2ZXJ5XCIgc21hbGxcbiAgICAvLyB3aGVuIElRUiBkb2VzIGEgcG9vciBqb2IgYXQgZGVzY3JpYmluZyB0aGUgc3ByZWFkXG4gICAgLy8gb2YgdGhlIGRpc3RyaWJ1dGlvbi5cbiAgICAvLyBXZSBhbHNvIHdhbnQgdG8gbGltaXQgY3VzdG9tIGJhbmR3aWR0aHNcbiAgICAvLyB0byBub3QgYmxvdyB1cCBrZGUgY29tcHV0YXRpb25zLlxuXG4gICAgaWYodHJhY2UuYmFuZHdpZHRoKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heCh0cmFjZS5iYW5kd2lkdGgsIHNwYW4gLyAxZTQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBsZW4gPSB2YWxzLmxlbmd0aDtcbiAgICAgICAgdmFyIHNzZCA9IExpYi5zdGRldih2YWxzLCBsZW4gLSAxLCBjZGkubWVhbik7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChcbiAgICAgICAgICAgIHNpbHZlcm1hblJ1bGUobGVuLCBzc2QsIGNkaS5xMyAtIGNkaS5xMSksXG4gICAgICAgICAgICBzcGFuIC8gMTAwXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjYWxjU3Bhbih0cmFjZSwgY2RpLCB2YWxBeGlzLCBiYW5kd2lkdGgpIHtcbiAgICB2YXIgc3Bhbm1vZGUgPSB0cmFjZS5zcGFubW9kZTtcbiAgICB2YXIgc3BhbkluID0gdHJhY2Uuc3BhbiB8fCBbXTtcbiAgICB2YXIgc3BhblRpZ2h0ID0gW2NkaS5taW4sIGNkaS5tYXhdO1xuICAgIHZhciBzcGFuTG9vc2UgPSBbY2RpLm1pbiAtIDIgKiBiYW5kd2lkdGgsIGNkaS5tYXggKyAyICogYmFuZHdpZHRoXTtcbiAgICB2YXIgc3Bhbk91dDtcblxuICAgIGZ1bmN0aW9uIGNhbGNTcGFuSXRlbShpbmRleCkge1xuICAgICAgICB2YXIgcyA9IHNwYW5JbltpbmRleF07XG4gICAgICAgIHZhciBzYyA9IHZhbEF4aXMuZDJjKHMsIDAsIHRyYWNlW2NkaS52YWxMZXR0ZXIgKyAnY2FsZW5kYXInXSk7XG4gICAgICAgIHJldHVybiBzYyA9PT0gQkFETlVNID8gc3Bhbkxvb3NlW2luZGV4XSA6IHNjO1xuICAgIH1cblxuICAgIGlmKHNwYW5tb2RlID09PSAnc29mdCcpIHtcbiAgICAgICAgc3Bhbk91dCA9IHNwYW5Mb29zZTtcbiAgICB9IGVsc2UgaWYoc3Bhbm1vZGUgPT09ICdoYXJkJykge1xuICAgICAgICBzcGFuT3V0ID0gc3BhblRpZ2h0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNwYW5PdXQgPSBbY2FsY1NwYW5JdGVtKDApLCBjYWxjU3Bhbkl0ZW0oMSldO1xuICAgIH1cblxuICAgIC8vIHRvIHJldXNlIHRoZSBlcXVhbC1yYW5nZS1pdGVtIGJsb2NrXG4gICAgdmFyIGR1bW15QXggPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogc3Bhbk91dFxuICAgIH07XG4gICAgQXhlcy5zZXRDb252ZXJ0KGR1bW15QXgpO1xuICAgIGR1bW15QXguY2xlYW5SYW5nZSgpO1xuXG4gICAgcmV0dXJuIHNwYW5PdXQ7XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzZXRQb3NpdGlvbk9mZnNldCA9IHJlcXVpcmUoJy4uL2JveC9jcm9zc190cmFjZV9jYWxjJykuc2V0UG9zaXRpb25PZmZzZXQ7XG52YXIgb3JpZW50YXRpb25zID0gWyd2JywgJ2gnXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCwgcGxvdGluZm8pIHtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvcmllbnRhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9yaWVudGF0aW9uID0gb3JpZW50YXRpb25zW2ldO1xuICAgICAgICB2YXIgcG9zQXhpcyA9IG9yaWVudGF0aW9uID09PSAnaCcgPyB5YSA6IHhhO1xuICAgICAgICB2YXIgdmlvbGluTGlzdCA9IFtdO1xuICAgICAgICB2YXIgbWluUGFkID0gMDtcbiAgICAgICAgdmFyIG1heFBhZCA9IDA7XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNhbGNkYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2QgPSBjYWxjZGF0YVtqXTtcbiAgICAgICAgICAgIHZhciB0ID0gY2RbMF0udDtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlICYmIHRyYWNlLnR5cGUgPT09ICd2aW9saW4nICYmXG4gICAgICAgICAgICAgICAgICAgICF0LmVtcHR5ICYmXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLm9yaWVudGF0aW9uID09PSBvcmllbnRhdGlvbiAmJlxuICAgICAgICAgICAgICAgICAgICB0cmFjZS54YXhpcyA9PT0geGEuX2lkICYmXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLnlheGlzID09PSB5YS5faWRcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmlvbGluTGlzdC5wdXNoKGopO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2UucG9pbnRzICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5QYWQgPSBNYXRoLm1heChtaW5QYWQsIHRyYWNlLmppdHRlciAtIHRyYWNlLnBvaW50cG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIG1heFBhZCA9IE1hdGgubWF4KG1heFBhZCwgdHJhY2Uuaml0dGVyICsgdHJhY2UucG9pbnRwb3MgLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXRQb3NpdGlvbk9mZnNldCgndmlvbGluJywgZ2QsIHZpb2xpbkxpc3QsIHBvc0F4aXMsIFttaW5QYWQsIG1heFBhZF0pO1xuICAgIH1cbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxudmFyIGJveERlZmF1bHRzID0gcmVxdWlyZSgnLi4vYm94L2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgYm94RGVmYXVsdHMuaGFuZGxlU2FtcGxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZih0cmFjZU91dC52aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKCdiYW5kd2lkdGgnKTtcbiAgICBjb2VyY2UoJ3NjYWxlZ3JvdXAnLCB0cmFjZU91dC5uYW1lKTtcbiAgICBjb2VyY2UoJ3NjYWxlbW9kZScpO1xuICAgIGNvZXJjZSgnc2lkZScpO1xuXG4gICAgdmFyIHNwYW4gPSBjb2VyY2UoJ3NwYW4nKTtcbiAgICB2YXIgc3Bhbm1vZGVEZmx0O1xuICAgIGlmKEFycmF5LmlzQXJyYXkoc3BhbikpIHNwYW5tb2RlRGZsdCA9ICdtYW51YWwnO1xuICAgIGNvZXJjZSgnc3Bhbm1vZGUnLCBzcGFubW9kZURmbHQpO1xuXG4gICAgdmFyIGxpbmVDb2xvciA9IGNvZXJjZSgnbGluZS5jb2xvcicsICh0cmFjZUluLm1hcmtlciB8fCB7fSkuY29sb3IgfHwgZGVmYXVsdENvbG9yKTtcbiAgICB2YXIgbGluZVdpZHRoID0gY29lcmNlKCdsaW5lLndpZHRoJyk7XG4gICAgdmFyIGZpbGxDb2xvciA9IGNvZXJjZSgnZmlsbGNvbG9yJywgQ29sb3IuYWRkT3BhY2l0eSh0cmFjZU91dC5saW5lLmNvbG9yLCAwLjUpKTtcblxuICAgIGJveERlZmF1bHRzLmhhbmRsZVBvaW50c0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIHtwcmVmaXg6ICcnfSk7XG5cbiAgICB2YXIgYm94V2lkdGggPSBjb2VyY2UyKCdib3gud2lkdGgnKTtcbiAgICB2YXIgYm94RmlsbENvbG9yID0gY29lcmNlMignYm94LmZpbGxjb2xvcicsIGZpbGxDb2xvcik7XG4gICAgdmFyIGJveExpbmVDb2xvciA9IGNvZXJjZTIoJ2JveC5saW5lLmNvbG9yJywgbGluZUNvbG9yKTtcbiAgICB2YXIgYm94TGluZVdpZHRoID0gY29lcmNlMignYm94LmxpbmUud2lkdGgnLCBsaW5lV2lkdGgpO1xuICAgIHZhciBib3hWaXNpYmxlID0gY29lcmNlKCdib3gudmlzaWJsZScsIEJvb2xlYW4oYm94V2lkdGggfHwgYm94RmlsbENvbG9yIHx8IGJveExpbmVDb2xvciB8fCBib3hMaW5lV2lkdGgpKTtcbiAgICBpZighYm94VmlzaWJsZSkgdHJhY2VPdXQuYm94ID0ge3Zpc2libGU6IGZhbHNlfTtcblxuICAgIHZhciBtZWFuTGluZUNvbG9yID0gY29lcmNlMignbWVhbmxpbmUuY29sb3InLCBsaW5lQ29sb3IpO1xuICAgIHZhciBtZWFuTGluZVdpZHRoID0gY29lcmNlMignbWVhbmxpbmUud2lkdGgnLCBsaW5lV2lkdGgpO1xuICAgIHZhciBtZWFuTGluZVZpc2libGUgPSBjb2VyY2UoJ21lYW5saW5lLnZpc2libGUnLCBCb29sZWFuKG1lYW5MaW5lQ29sb3IgfHwgbWVhbkxpbmVXaWR0aCkpO1xuICAgIGlmKCFtZWFuTGluZVZpc2libGUpIHRyYWNlT3V0Lm1lYW5saW5lID0ge3Zpc2libGU6IGZhbHNlfTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi8uLi9saWInKTtcblxuLy8gTWF5YmUgYWRkIGtlcm5lbHMgbW9yZSBkb3duIHRoZSByb2FkLFxuLy8gYnV0IG5vdGUgdGhhdCB0aGUgZGVmYXVsdCBgc3Bhbm1vZGU6ICdzb2Z0J2AgYm91bmRzIG1pZ2h0IGhhdmVcbi8vIHRvIGJlY29tZSBrZXJuZWwtZGVwZW5kZW50XG52YXIga2VybmVscyA9IHtcbiAgICBnYXVzc2lhbjogZnVuY3Rpb24odikge1xuICAgICAgICByZXR1cm4gKDEgLyBNYXRoLnNxcnQoMiAqIE1hdGguUEkpKSAqIE1hdGguZXhwKC0wLjUgKiB2ICogdik7XG4gICAgfVxufTtcblxuZXhwb3J0cy5tYWtlS0RFID0gZnVuY3Rpb24oY2FsY0l0ZW0sIHRyYWNlLCB2YWxzKSB7XG4gICAgdmFyIGxlbiA9IHZhbHMubGVuZ3RoO1xuICAgIHZhciBrZXJuZWwgPSBrZXJuZWxzLmdhdXNzaWFuO1xuICAgIHZhciBiYW5kd2lkdGggPSBjYWxjSXRlbS5iYW5kd2lkdGg7XG4gICAgdmFyIGZhY3RvciA9IDEgLyAobGVuICogYmFuZHdpZHRoKTtcblxuICAgIC8vIGRvbid0IHVzZSBMaWIuYWdnTnVtcyB0byBza2lwIGlzTnVtZXJpYyBjaGVja3NcbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgICB2YXIgc3VtID0gMDtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBzdW0gKz0ga2VybmVsKCh4IC0gdmFsc1tpXSkgLyBiYW5kd2lkdGgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWN0b3IgKiBzdW07XG4gICAgfTtcbn07XG5cbmV4cG9ydHMuZ2V0UG9zaXRpb25PbktkZVBhdGggPSBmdW5jdGlvbihjYWxjSXRlbSwgdHJhY2UsIHZhbHVlUHgpIHtcbiAgICB2YXIgcG9zTGV0dGVyLCB2YWxMZXR0ZXI7XG5cbiAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgIHBvc0xldHRlciA9ICd5JztcbiAgICAgICAgdmFsTGV0dGVyID0gJ3gnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBvc0xldHRlciA9ICd4JztcbiAgICAgICAgdmFsTGV0dGVyID0gJ3knO1xuICAgIH1cblxuICAgIHZhciBwb2ludE9uUGF0aCA9IExpYi5maW5kUG9pbnRPblBhdGgoXG4gICAgICAgIGNhbGNJdGVtLnBhdGgsXG4gICAgICAgIHZhbHVlUHgsXG4gICAgICAgIHZhbExldHRlcixcbiAgICAgICAge3BhdGhMZW5ndGg6IGNhbGNJdGVtLnBhdGhMZW5ndGh9XG4gICAgKTtcblxuICAgIHZhciBwb3NDZW50ZXJQeCA9IGNhbGNJdGVtLnBvc0NlbnRlclB4O1xuICAgIHZhciBwb3NPblBhdGgwID0gcG9pbnRPblBhdGhbcG9zTGV0dGVyXTtcbiAgICB2YXIgcG9zT25QYXRoMSA9IHRyYWNlLnNpZGUgPT09ICdib3RoJyA/XG4gICAgICAgIDIgKiBwb3NDZW50ZXJQeCAtIHBvc09uUGF0aDAgOlxuICAgICAgICBwb3NDZW50ZXJQeDtcblxuICAgIHJldHVybiBbcG9zT25QYXRoMCwgcG9zT25QYXRoMV07XG59O1xuXG5leHBvcnRzLmdldEtkZVZhbHVlID0gZnVuY3Rpb24oY2FsY0l0ZW0sIHRyYWNlLCB2YWx1ZURpc3QpIHtcbiAgICB2YXIgdmFscyA9IGNhbGNJdGVtLnB0cy5tYXAoZXhwb3J0cy5leHRyYWN0VmFsKTtcbiAgICB2YXIga2RlID0gZXhwb3J0cy5tYWtlS0RFKGNhbGNJdGVtLCB0cmFjZSwgdmFscyk7XG4gICAgcmV0dXJuIGtkZSh2YWx1ZURpc3QpIC8gY2FsY0l0ZW0ucG9zRGVuc2l0eVNjYWxlO1xufTtcblxuZXhwb3J0cy5leHRyYWN0VmFsID0gZnVuY3Rpb24obykgeyByZXR1cm4gby52OyB9O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgYm94SG92ZXJQb2ludHMgPSByZXF1aXJlKCcuLi9ib3gvaG92ZXInKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUsIGhvdmVyTGF5ZXIpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIGhvdmVyb24gPSB0cmFjZS5ob3Zlcm9uO1xuICAgIHZhciBoYXNIb3Zlcm9uVmlvbGlucyA9IGhvdmVyb24uaW5kZXhPZigndmlvbGlucycpICE9PSAtMTtcbiAgICB2YXIgaGFzSG92ZXJvbktERSA9IGhvdmVyb24uaW5kZXhPZigna2RlJykgIT09IC0xO1xuICAgIHZhciBjbG9zZURhdGEgPSBbXTtcbiAgICB2YXIgY2xvc2VQdERhdGE7XG4gICAgdmFyIHZpb2xpbkxpbmVBdHRycztcblxuICAgIGlmKGhhc0hvdmVyb25WaW9saW5zIHx8IGhhc0hvdmVyb25LREUpIHtcbiAgICAgICAgdmFyIGNsb3NlQm94RGF0YSA9IGJveEhvdmVyUG9pbnRzLmhvdmVyT25Cb3hlcyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG5cbiAgICAgICAgaWYoaGFzSG92ZXJvblZpb2xpbnMpIHtcbiAgICAgICAgICAgIGNsb3NlRGF0YSA9IGNsb3NlRGF0YS5jb25jYXQoY2xvc2VCb3hEYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhhc0hvdmVyb25LREUgJiYgY2xvc2VCb3hEYXRhLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICAgICAgICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICAgICAgICAgIHZhciBwTGV0dGVyLCB2TGV0dGVyLCBwQXhpcywgdkF4aXMsIHZWYWw7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICB2VmFsID0geHZhbDtcbiAgICAgICAgICAgICAgICBwTGV0dGVyID0gJ3knO1xuICAgICAgICAgICAgICAgIHBBeGlzID0geWE7XG4gICAgICAgICAgICAgICAgdkxldHRlciA9ICd4JztcbiAgICAgICAgICAgICAgICB2QXhpcyA9IHhhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2VmFsID0geXZhbDtcbiAgICAgICAgICAgICAgICBwTGV0dGVyID0gJ3gnO1xuICAgICAgICAgICAgICAgIHBBeGlzID0geGE7XG4gICAgICAgICAgICAgICAgdkxldHRlciA9ICd5JztcbiAgICAgICAgICAgICAgICB2QXhpcyA9IHlhO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuXG4gICAgICAgICAgICBpZih2VmFsID49IGRpLnNwYW5bMF0gJiYgdlZhbCA8PSBkaS5zcGFuWzFdKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtkZVBvaW50RGF0YSA9IExpYi5leHRlbmRGbGF0KHt9LCBwb2ludERhdGEpO1xuICAgICAgICAgICAgICAgIHZhciB2VmFsUHggPSB2QXhpcy5jMnAodlZhbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgdmFyIGtkZVZhbCA9IGhlbHBlcnMuZ2V0S2RlVmFsdWUoZGksIHRyYWNlLCB2VmFsKTtcbiAgICAgICAgICAgICAgICB2YXIgcE9uUGF0aCA9IGhlbHBlcnMuZ2V0UG9zaXRpb25PbktkZVBhdGgoZGksIHRyYWNlLCB2VmFsUHgpO1xuICAgICAgICAgICAgICAgIHZhciBwYU9mZnNldCA9IHBBeGlzLl9vZmZzZXQ7XG4gICAgICAgICAgICAgICAgdmFyIHBhTGVuZ3RoID0gcEF4aXMuX2xlbmd0aDtcblxuICAgICAgICAgICAgICAgIGtkZVBvaW50RGF0YVtwTGV0dGVyICsgJzAnXSA9IHBPblBhdGhbMF07XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3BMZXR0ZXIgKyAnMSddID0gcE9uUGF0aFsxXTtcbiAgICAgICAgICAgICAgICBrZGVQb2ludERhdGFbdkxldHRlciArICcwJ10gPSBrZGVQb2ludERhdGFbdkxldHRlciArICcxJ10gPSB2VmFsUHg7XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3ZMZXR0ZXIgKyAnTGFiZWwnXSA9IHZMZXR0ZXIgKyAnOiAnICsgQXhlcy5ob3ZlckxhYmVsVGV4dCh2QXhpcywgdlZhbCkgKyAnLCAnICsgY2RbMF0udC5sYWJlbHMua2RlICsgJyAnICsga2RlVmFsLnRvRml4ZWQoMyk7XG5cbiAgICAgICAgICAgICAgICAvLyBtb3ZlIHRoZSBzcGlrZSB0byB0aGUgS0RFIHBvaW50XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSBjbG9zZUJveERhdGFbMF0uc3Bpa2VEaXN0YW5jZTtcbiAgICAgICAgICAgICAgICB2YXIgc3Bpa2VQb3NBdHRyID0gcExldHRlciArICdTcGlrZSc7XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3NwaWtlUG9zQXR0cl0gPSBjbG9zZUJveERhdGFbMF1bc3Bpa2VQb3NBdHRyXTtcbiAgICAgICAgICAgICAgICBjbG9zZUJveERhdGFbMF0uc3Bpa2VEaXN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBjbG9zZUJveERhdGFbMF1bc3Bpa2VQb3NBdHRyXSA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGNsb3NlRGF0YS5wdXNoKGtkZVBvaW50RGF0YSk7XG5cbiAgICAgICAgICAgICAgICB2aW9saW5MaW5lQXR0cnMgPSB7c3Ryb2tlOiBwb2ludERhdGEuY29sb3J9O1xuICAgICAgICAgICAgICAgIHZpb2xpbkxpbmVBdHRyc1twTGV0dGVyICsgJzEnXSA9IExpYi5jb25zdHJhaW4ocGFPZmZzZXQgKyBwT25QYXRoWzBdLCBwYU9mZnNldCwgcGFPZmZzZXQgKyBwYUxlbmd0aCk7XG4gICAgICAgICAgICAgICAgdmlvbGluTGluZUF0dHJzW3BMZXR0ZXIgKyAnMiddID0gTGliLmNvbnN0cmFpbihwYU9mZnNldCArIHBPblBhdGhbMV0sIHBhT2Zmc2V0LCBwYU9mZnNldCArIHBhTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB2aW9saW5MaW5lQXR0cnNbdkxldHRlciArICcxJ10gPSB2aW9saW5MaW5lQXR0cnNbdkxldHRlciArICcyJ10gPSB2QXhpcy5fb2Zmc2V0ICsgdlZhbFB4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaG92ZXJvbi5pbmRleE9mKCdwb2ludHMnKSAhPT0gLTEpIHtcbiAgICAgICAgY2xvc2VQdERhdGEgPSBib3hIb3ZlclBvaW50cy5ob3Zlck9uUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIHZpb2xpbiBsaW5lIChpZiBhbnkpXG4gICAgdmFyIHZpb2xpbkxpbmUgPSBob3ZlckxheWVyLnNlbGVjdEFsbCgnLnZpb2xpbmxpbmUtJyArIHRyYWNlLnVpZClcbiAgICAgICAgLmRhdGEodmlvbGluTGluZUF0dHJzID8gWzBdIDogW10pO1xuICAgIHZpb2xpbkxpbmUuZW50ZXIoKS5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAuY2xhc3NlZCgndmlvbGlubGluZS0nICsgdHJhY2UudWlkLCB0cnVlKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMS41KTtcbiAgICB2aW9saW5MaW5lLmV4aXQoKS5yZW1vdmUoKTtcbiAgICB2aW9saW5MaW5lLmF0dHIodmlvbGluTGluZUF0dHJzKTtcblxuICAgIC8vIHNhbWUgY29tYmluZSBsb2dpYyBhcyBib3ggaG92ZXJQb2ludHNcbiAgICBpZihob3Zlcm1vZGUgPT09ICdjbG9zZXN0Jykge1xuICAgICAgICBpZihjbG9zZVB0RGF0YSkgcmV0dXJuIFtjbG9zZVB0RGF0YV07XG4gICAgICAgIHJldHVybiBjbG9zZURhdGE7XG4gICAgfVxuICAgIGlmKGNsb3NlUHREYXRhKSB7XG4gICAgICAgIGNsb3NlRGF0YS5wdXNoKGNsb3NlUHREYXRhKTtcbiAgICAgICAgcmV0dXJuIGNsb3NlRGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIGNsb3NlRGF0YTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vYXR0cmlidXRlcycpLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogcmVxdWlyZSgnLi9kZWZhdWx0cycpLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiByZXF1aXJlKCcuL2xheW91dF9kZWZhdWx0cycpLFxuICAgIGNhbGM6IHJlcXVpcmUoJy4vY2FsYycpLFxuICAgIGNyb3NzVHJhY2VDYWxjOiByZXF1aXJlKCcuL2Nyb3NzX3RyYWNlX2NhbGMnKSxcbiAgICBwbG90OiByZXF1aXJlKCcuL3Bsb3QnKSxcbiAgICBzdHlsZTogcmVxdWlyZSgnLi9zdHlsZScpLFxuICAgIHN0eWxlT25TZWxlY3Q6IHJlcXVpcmUoJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGhvdmVyUG9pbnRzOiByZXF1aXJlKCcuL2hvdmVyJyksXG4gICAgc2VsZWN0UG9pbnRzOiByZXF1aXJlKCcuLi9ib3gvc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICd2aW9saW4nLFxuICAgIGJhc2VQbG90TW9kdWxlOiByZXF1aXJlKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2NhcnRlc2lhbicsICdzdmcnLCAnc3ltYm9scycsICdvcmllbnRlZCcsICdib3gtdmlvbGluJywgJ3Nob3dMZWdlbmQnLCAndmlvbGluTGF5b3V0JywgJ3pvb21TY2FsZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGJveExheW91dEF0dHJzID0gcmVxdWlyZSgnLi4vYm94L2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IHJlcXVpcmUoJy4uLy4uL2xpYicpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHZpb2xpbm1vZGU6IGV4dGVuZEZsYXQoe30sIGJveExheW91dEF0dHJzLmJveG1vZGUsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdmlvbGluZ2FwOiBleHRlbmRGbGF0KHt9LCBib3hMYXlvdXRBdHRycy5ib3hnYXAsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdmlvbGluZ3JvdXBnYXA6IGV4dGVuZEZsYXQoe30sIGJveExheW91dEF0dHJzLmJveGdyb3VwZ2FwLCB7XG4gICAgICAgIFxuICAgIH0pXG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IHJlcXVpcmUoJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBib3hMYXlvdXREZWZhdWx0cyA9IHJlcXVpcmUoJy4uL2JveC9sYXlvdXRfZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cbiAgICBib3hMYXlvdXREZWZhdWx0cy5fc3VwcGx5KGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCBjb2VyY2UsICd2aW9saW4nKTtcbn07XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoXCIvaG9tZS9jaXJjbGVjaS9wbG90bHkuanMvdGVzdC9pbWFnZS9zdHJpY3QtZDMuanNcIik7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xuXG52YXIgYm94UGxvdCA9IHJlcXVpcmUoJy4uL2JveC9wbG90Jyk7XG52YXIgbGluZVBvaW50cyA9IHJlcXVpcmUoJy4uL3NjYXR0ZXIvbGluZV9wb2ludHMnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkVmlvbGlucywgdmlvbGluTGF5ZXIpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgZnVuY3Rpb24gbWFrZVBhdGgocHRzKSB7XG4gICAgICAgIHZhciBzZWdtZW50cyA9IGxpbmVQb2ludHMocHRzLCB7XG4gICAgICAgICAgICB4YXhpczogeGEsXG4gICAgICAgICAgICB5YXhpczogeWEsXG4gICAgICAgICAgICBjb25uZWN0R2FwczogdHJ1ZSxcbiAgICAgICAgICAgIGJhc2VUb2xlcmFuY2U6IDAuNzUsXG4gICAgICAgICAgICBzaGFwZTogJ3NwbGluZScsXG4gICAgICAgICAgICBzaW1wbGlmeTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3Rob3BlbihzZWdtZW50c1swXSwgMSk7XG4gICAgfVxuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyh2aW9saW5MYXllciwgY2RWaW9saW5zLCAndHJhY2UgdmlvbGlucycpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdCA9IGNkMC50O1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIGlmKCFwbG90aW5mby5pc1JhbmdlUGxvdCkgY2QwLm5vZGUzID0gcGxvdEdyb3VwO1xuICAgICAgICB2YXIgbnVtVmlvbGlucyA9IGZ1bGxMYXlvdXQuX251bVZpb2xpbnM7XG4gICAgICAgIHZhciBncm91cCA9IChmdWxsTGF5b3V0LnZpb2xpbm1vZGUgPT09ICdncm91cCcgJiYgbnVtVmlvbGlucyA+IDEpO1xuICAgICAgICB2YXIgZ3JvdXBGcmFjdGlvbiA9IDEgLSBmdWxsTGF5b3V0LnZpb2xpbmdhcDtcbiAgICAgICAgLy8gdmlvbGluIG1heCBoYWxmIHdpZHRoXG4gICAgICAgIHZhciBiZFBvcyA9IHQuYmRQb3MgPSB0LmRQb3MgKiBncm91cEZyYWN0aW9uICogKDEgLSBmdWxsTGF5b3V0LnZpb2xpbmdyb3VwZ2FwKSAvIChncm91cCA/IG51bVZpb2xpbnMgOiAxKTtcbiAgICAgICAgLy8gdmlvbGluIGNlbnRlciBvZmZzZXRcbiAgICAgICAgdmFyIGJQb3MgPSB0LmJQb3MgPSBncm91cCA/IDIgKiB0LmRQb3MgKiAoLTAuNSArICh0Lm51bSArIDAuNSkgLyBudW1WaW9saW5zKSAqIGdyb3VwRnJhY3Rpb24gOiAwO1xuICAgICAgICAvLyBoYWxmLXdpZHRoIHdpdGhpbiB3aGljaCB0byBhY2NlcHQgaG92ZXIgZm9yIHRoaXMgdmlvbGluXG4gICAgICAgIC8vIGFsd2F5cyBzcGxpdCB0aGUgZGlzdGFuY2UgdG8gdGhlIGNsb3Nlc3QgdmlvbGluXG4gICAgICAgIHQud0hvdmVyID0gdC5kUG9zICogKGdyb3VwID8gZ3JvdXBGcmFjdGlvbiAvIG51bVZpb2xpbnMgOiAxKTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IHQuZW1wdHkpIHtcbiAgICAgICAgICAgIHBsb3RHcm91cC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YWxBeGlzID0gcGxvdGluZm9bdC52YWxMZXR0ZXIgKyAnYXhpcyddO1xuICAgICAgICB2YXIgcG9zQXhpcyA9IHBsb3RpbmZvW3QucG9zTGV0dGVyICsgJ2F4aXMnXTtcbiAgICAgICAgdmFyIGhhc0JvdGhTaWRlcyA9IHRyYWNlLnNpZGUgPT09ICdib3RoJztcbiAgICAgICAgdmFyIGhhc1Bvc2l0aXZlU2lkZSA9IGhhc0JvdGhTaWRlcyB8fCB0cmFjZS5zaWRlID09PSAncG9zaXRpdmUnO1xuICAgICAgICB2YXIgaGFzTmVnYXRpdmVTaWRlID0gaGFzQm90aFNpZGVzIHx8IHRyYWNlLnNpZGUgPT09ICduZWdhdGl2ZSc7XG4gICAgICAgIHZhciBncm91cFN0YXRzID0gZnVsbExheW91dC5fdmlvbGluU2NhbGVHcm91cFN0YXRzW3RyYWNlLnNjYWxlZ3JvdXBdO1xuXG4gICAgICAgIHZhciB2aW9saW5zID0gcGxvdEdyb3VwLnNlbGVjdEFsbCgncGF0aC52aW9saW4nKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgdmlvbGlucy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuc3R5bGUoJ3ZlY3Rvci1lZmZlY3QnLCAnbm9uLXNjYWxpbmctc3Ryb2tlJylcbiAgICAgICAgICAgIC5hdHRyKCdjbGFzcycsICd2aW9saW4nKTtcblxuICAgICAgICB2aW9saW5zLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICB2aW9saW5zLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHBhdGhTZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgZGVuc2l0eSA9IGQuZGVuc2l0eTtcbiAgICAgICAgICAgIHZhciBsZW4gPSBkZW5zaXR5Lmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBwb3NDZW50ZXIgPSBkLnBvcyArIGJQb3M7XG4gICAgICAgICAgICB2YXIgcG9zQ2VudGVyUHggPSBwb3NBeGlzLmMycChwb3NDZW50ZXIpO1xuICAgICAgICAgICAgdmFyIHNjYWxlO1xuXG4gICAgICAgICAgICBzd2l0Y2godHJhY2Uuc2NhbGVtb2RlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnd2lkdGgnOlxuICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IGdyb3VwU3RhdHMubWF4V2lkdGggLyBiZFBvcztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY291bnQnOlxuICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IChncm91cFN0YXRzLm1heFdpZHRoIC8gYmRQb3MpICogKGdyb3VwU3RhdHMubWF4Q291bnQgLyBkLnB0cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhdGhQb3MsIHBhdGhOZWcsIHBhdGg7XG4gICAgICAgICAgICB2YXIgaSwgaywgcHRzLCBwdDtcblxuICAgICAgICAgICAgaWYoaGFzUG9zaXRpdmVTaWRlKSB7XG4gICAgICAgICAgICAgICAgcHRzID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcHQgPSBwdHNbaV0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC5wb3NMZXR0ZXJdID0gcG9zQ2VudGVyICsgKGRlbnNpdHlbaV0udiAvIHNjYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC52YWxMZXR0ZXJdID0gZGVuc2l0eVtpXS50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXRoUG9zID0gbWFrZVBhdGgocHRzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzTmVnYXRpdmVTaWRlKSB7XG4gICAgICAgICAgICAgICAgcHRzID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgICAgICAgICAgZm9yKGsgPSAwLCBpID0gbGVuIC0gMTsgayA8IGxlbjsgaysrLCBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHQgPSBwdHNba10gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC5wb3NMZXR0ZXJdID0gcG9zQ2VudGVyIC0gKGRlbnNpdHlbaV0udiAvIHNjYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC52YWxMZXR0ZXJdID0gZGVuc2l0eVtpXS50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXRoTmVnID0gbWFrZVBhdGgocHRzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzQm90aFNpZGVzKSB7XG4gICAgICAgICAgICAgICAgcGF0aCA9IHBhdGhQb3MgKyAnTCcgKyBwYXRoTmVnLnN1YnN0cigxKSArICdaJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzdGFydFB0ID0gW3Bvc0NlbnRlclB4LCB2YWxBeGlzLmMycChkZW5zaXR5WzBdLnQpXTtcbiAgICAgICAgICAgICAgICB2YXIgZW5kUHQgPSBbcG9zQ2VudGVyUHgsIHZhbEF4aXMuYzJwKGRlbnNpdHlbbGVuIC0gMV0udCldO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgICAgICAgICBzdGFydFB0LnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgZW5kUHQucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGhhc1Bvc2l0aXZlU2lkZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRoID0gJ00nICsgc3RhcnRQdCArICdMJyArIHBhdGhQb3Muc3Vic3RyKDEpICsgJ0wnICsgZW5kUHQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aCA9ICdNJyArIGVuZFB0ICsgJ0wnICsgcGF0aE5lZy5zdWJzdHIoMSkgKyAnTCcgKyBzdGFydFB0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhdGhTZWwuYXR0cignZCcsIHBhdGgpO1xuXG4gICAgICAgICAgICAvLyBzYXZlIGEgZmV3IHRoaW5ncyB1c2VkIGluIGdldFBvc2l0aW9uT25LZGVQYXRoLCBnZXRLZGVWYWx1ZVxuICAgICAgICAgICAgLy8gb24gaG92ZXIgYW5kIGZvciBtZWFubGluZSBkcmF3IGJsb2NrIGJlbG93XG4gICAgICAgICAgICBkLnBvc0NlbnRlclB4ID0gcG9zQ2VudGVyUHg7XG4gICAgICAgICAgICBkLnBvc0RlbnNpdHlTY2FsZSA9IHNjYWxlICogYmRQb3M7XG4gICAgICAgICAgICBkLnBhdGggPSBwYXRoU2VsLm5vZGUoKTtcbiAgICAgICAgICAgIGQucGF0aExlbmd0aCA9IGQucGF0aC5nZXRUb3RhbExlbmd0aCgpIC8gKGhhc0JvdGhTaWRlcyA/IDIgOiAxKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGJveEF0dHJzID0gdHJhY2UuYm94O1xuICAgICAgICB2YXIgYm94V2lkdGggPSBib3hBdHRycy53aWR0aDtcbiAgICAgICAgdmFyIGJveExpbmVXaWR0aCA9IChib3hBdHRycy5saW5lIHx8IHt9KS53aWR0aDtcbiAgICAgICAgdmFyIGJkUG9zU2NhbGVkO1xuICAgICAgICB2YXIgYlBvc1B4T2Zmc2V0O1xuXG4gICAgICAgIGlmKGhhc0JvdGhTaWRlcykge1xuICAgICAgICAgICAgYmRQb3NTY2FsZWQgPSBiZFBvcyAqIGJveFdpZHRoO1xuICAgICAgICAgICAgYlBvc1B4T2Zmc2V0ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmKGhhc1Bvc2l0aXZlU2lkZSkge1xuICAgICAgICAgICAgYmRQb3NTY2FsZWQgPSBbMCwgYmRQb3MgKiBib3hXaWR0aCAvIDJdO1xuICAgICAgICAgICAgYlBvc1B4T2Zmc2V0ID0gLWJveExpbmVXaWR0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJkUG9zU2NhbGVkID0gW2JkUG9zICogYm94V2lkdGggLyAyLCAwXTtcbiAgICAgICAgICAgIGJQb3NQeE9mZnNldCA9IGJveExpbmVXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlubmVyIGJveFxuICAgICAgICBib3hQbG90LnBsb3RCb3hBbmRXaGlza2VycyhwbG90R3JvdXAsIHtwb3M6IHBvc0F4aXMsIHZhbDogdmFsQXhpc30sIHRyYWNlLCB7XG4gICAgICAgICAgICBiUG9zOiBiUG9zLFxuICAgICAgICAgICAgYmRQb3M6IGJkUG9zU2NhbGVkLFxuICAgICAgICAgICAgYlBvc1B4T2Zmc2V0OiBiUG9zUHhPZmZzZXRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gbWVhbmxpbmUgaW5zaWRlciBib3hcbiAgICAgICAgYm94UGxvdC5wbG90Qm94TWVhbihwbG90R3JvdXAsIHtwb3M6IHBvc0F4aXMsIHZhbDogdmFsQXhpc30sIHRyYWNlLCB7XG4gICAgICAgICAgICBiUG9zOiBiUG9zLFxuICAgICAgICAgICAgYmRQb3M6IGJkUG9zU2NhbGVkLFxuICAgICAgICAgICAgYlBvc1B4T2Zmc2V0OiBiUG9zUHhPZmZzZXRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGZuO1xuICAgICAgICBpZighdHJhY2UuYm94LnZpc2libGUgJiYgdHJhY2UubWVhbmxpbmUudmlzaWJsZSkge1xuICAgICAgICAgICAgZm4gPSBMaWIuaWRlbnRpdHk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOLkIuIHVzZSBkaWZmZXJlbnQgY2xhc3MgbmFtZSB0aGFuIGJveFBsb3QucGxvdEJveE1lYW4sXG4gICAgICAgIC8vIHRvIGF2b2lkIHNlbGVjdEFsbCBjb25mbGljdFxuICAgICAgICB2YXIgbWVhblBhdGhzID0gcGxvdEdyb3VwLnNlbGVjdEFsbCgncGF0aC5tZWFubGluZScpLmRhdGEoZm4gfHwgW10pO1xuICAgICAgICBtZWFuUGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ21lYW5saW5lJylcbiAgICAgICAgICAgIC5zdHlsZSgnZmlsbCcsICdub25lJylcbiAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKTtcbiAgICAgICAgbWVhblBhdGhzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgbWVhblBhdGhzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHYgPSB2YWxBeGlzLmMycChkLm1lYW4sIHRydWUpO1xuICAgICAgICAgICAgdmFyIHAgPSBoZWxwZXJzLmdldFBvc2l0aW9uT25LZGVQYXRoKGQsIHRyYWNlLCB2KTtcblxuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgIHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcgP1xuICAgICAgICAgICAgICAgICAgICAnTScgKyB2ICsgJywnICsgcFswXSArICdWJyArIHBbMV0gOlxuICAgICAgICAgICAgICAgICAgICAnTScgKyBwWzBdICsgJywnICsgdiArICdIJyArIHBbMV1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGJveFBsb3QucGxvdFBvaW50cyhwbG90R3JvdXAsIHt4OiB4YSwgeTogeWF9LCB0cmFjZSwgdCk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSByZXF1aXJlKFwiL2hvbWUvY2lyY2xlY2kvcGxvdGx5LmpzL3Rlc3QvaW1hZ2Uvc3RyaWN0LWQzLmpzXCIpO1xudmFyIENvbG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIHN0eWxlUG9pbnRzID0gcmVxdWlyZSgnLi4vc2NhdHRlci9zdHlsZScpLnN0eWxlUG9pbnRzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKGdkLCBjZCkge1xuICAgIHZhciBzID0gY2QgPyBjZFswXS5ub2RlMyA6IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLnRyYWNlLnZpb2xpbnMnKTtcblxuICAgIHMuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihkKSB7IHJldHVybiBkWzBdLnRyYWNlLm9wYWNpdHk7IH0pO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcbiAgICAgICAgdmFyIHNlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGJveCA9IHRyYWNlLmJveCB8fCB7fTtcbiAgICAgICAgdmFyIGJveExpbmUgPSBib3gubGluZSB8fCB7fTtcbiAgICAgICAgdmFyIG1lYW5saW5lID0gdHJhY2UubWVhbmxpbmUgfHwge307XG4gICAgICAgIHZhciBtZWFuTGluZVdpZHRoID0gbWVhbmxpbmUud2lkdGg7XG5cbiAgICAgICAgc2VsLnNlbGVjdEFsbCgncGF0aC52aW9saW4nKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB0cmFjZS5saW5lLndpZHRoICsgJ3B4JylcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgdHJhY2UubGluZS5jb2xvcilcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIHRyYWNlLmZpbGxjb2xvcik7XG5cbiAgICAgICAgc2VsLnNlbGVjdEFsbCgncGF0aC5ib3gnKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBib3hMaW5lLndpZHRoICsgJ3B4JylcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYm94TGluZS5jb2xvcilcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGJveC5maWxsY29sb3IpO1xuXG4gICAgICAgIHZhciBtZWFuTGluZVN0eWxlID0ge1xuICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IG1lYW5MaW5lV2lkdGggKyAncHgnLFxuICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiAoMiAqIG1lYW5MaW5lV2lkdGgpICsgJ3B4LCcgKyBtZWFuTGluZVdpZHRoICsgJ3B4J1xuICAgICAgICB9O1xuXG4gICAgICAgIHNlbC5zZWxlY3RBbGwoJ3BhdGgubWVhbicpXG4gICAgICAgICAgICAuc3R5bGUobWVhbkxpbmVTdHlsZSlcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgbWVhbmxpbmUuY29sb3IpO1xuXG4gICAgICAgIHNlbC5zZWxlY3RBbGwoJ3BhdGgubWVhbmxpbmUnKVxuICAgICAgICAgICAgLnN0eWxlKG1lYW5MaW5lU3R5bGUpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIG1lYW5saW5lLmNvbG9yKTtcblxuICAgICAgICBzdHlsZVBvaW50cyhzZWwsIHRyYWNlLCBnZCk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTgsIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IHJlcXVpcmUoJy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gcmVxdWlyZSgnLi4vbGliJyk7XG52YXIgUGxvdFNjaGVtYSA9IHJlcXVpcmUoJy4uL3Bsb3RfYXBpL3Bsb3Rfc2NoZW1hJyk7XG52YXIgcG9pbnRzQWNjZXNzb3JGdW5jdGlvbiA9IHJlcXVpcmUoJy4vaGVscGVycycpLnBvaW50c0FjY2Vzc29yRnVuY3Rpb247XG52YXIgQkFETlVNID0gcmVxdWlyZSgnLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxuZXhwb3J0cy5tb2R1bGVUeXBlID0gJ3RyYW5zZm9ybSc7XG5cbmV4cG9ydHMubmFtZSA9ICdhZ2dyZWdhdGUnO1xuXG52YXIgYXR0cnMgPSBleHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgZW5hYmxlZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyb3Vwczoge1xuICAgICAgICAvLyBUT0RPOiBncm91cGJ5IHNob3VsZCBzdXBwb3J0IHN0cmluZyBvciBhcnJheSBncm91cGluZyB0aGlzIHdheSB0b29cbiAgICAgICAgLy8gY3VycmVudGx5IGdyb3VwYnkgb25seSBhbGxvd3MgYSBncm91cGluZyBhcnJheVxuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiAneCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFnZ3JlZ2F0aW9uczoge1xuICAgICAgICBfaXNMaW5rZWRUb0FycmF5OiAnYWdncmVnYXRpb24nLFxuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydjb3VudCcsICdzdW0nLCAnYXZnJywgJ21lZGlhbicsICdtb2RlJywgJ3JtcycsICdzdGRkZXYnLCAnbWluJywgJ21heCcsICdmaXJzdCcsICdsYXN0JywgJ2NoYW5nZScsICdyYW5nZSddLFxuICAgICAgICAgICAgZGZsdDogJ2ZpcnN0JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmdW5jbW9kZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ3NhbXBsZScsICdwb3B1bGF0aW9uJ10sXG4gICAgICAgICAgICBkZmx0OiAnc2FtcGxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlbmFibGVkOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn07XG5cbnZhciBhZ2dBdHRycyA9IGF0dHJzLmFnZ3JlZ2F0aW9ucztcblxuLyoqXG4gKiBTdXBwbHkgdHJhbnNmb3JtIGF0dHJpYnV0ZXMgZGVmYXVsdHNcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhbnNmb3JtSW5cbiAqICBvYmplY3QgbGlua2VkIHRvIHRyYWNlLnRyYW5zZm9ybXNbaV0gd2l0aCAnZnVuYycgc2V0IHRvIGV4cG9ydHMubmFtZVxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlT3V0XG4gKiAgdGhlIF9mdWxsRGF0YSB0cmFjZSB0aGlzIHRyYW5zZm9ybSBhcHBsaWVzIHRvXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0XG4gKiAgdGhlIHBsb3QncyAobm90LXNvLWZ1bGwpIGxheW91dFxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlSW5cbiAqICB0aGUgaW5wdXQgZGF0YSB0cmFjZSB0aGlzIHRyYW5zZm9ybSBhcHBsaWVzIHRvXG4gKlxuICogQHJldHVybiB7b2JqZWN0fSB0cmFuc2Zvcm1PdXRcbiAqICBjb3B5IG9mIHRyYW5zZm9ybUluIHRoYXQgY29udGFpbnMgYXR0cmlidXRlIGRlZmF1bHRzXG4gKi9cbmV4cG9ydHMuc3VwcGx5RGVmYXVsdHMgPSBmdW5jdGlvbih0cmFuc2Zvcm1JbiwgdHJhY2VPdXQpIHtcbiAgICB2YXIgdHJhbnNmb3JtT3V0ID0ge307XG4gICAgdmFyIGk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFuc2Zvcm1JbiwgdHJhbnNmb3JtT3V0LCBhdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGVuYWJsZWQgPSBjb2VyY2UoJ2VuYWJsZWQnKTtcblxuICAgIGlmKCFlbmFibGVkKSByZXR1cm4gdHJhbnNmb3JtT3V0O1xuXG4gICAgLypcbiAgICAgKiBOb3JtYWxseSBfYXJyYXlBdHRycyBpcyBjYWxjdWxhdGVkIGR1cmluZyBkb0NhbGMsIGJ1dCB0aGF0IGNvbWVzIGxhdGVyLlxuICAgICAqIEFueXdheSB0aGlzIGNhbiBjaGFuZ2UgZHVlIHRvICpjb3VudCogYWdncmVnYXRpb25zIChzZWUgYmVsb3cpIHNvIGl0J3Mgbm90XG4gICAgICogbmVjZXNzYXJpbHkgdGhlIHNhbWUgc2V0LlxuICAgICAqXG4gICAgICogRm9yIHBlcmZvcm1hbmNlIHdlIHR1cm4gaXQgaW50byBhbiBvYmplY3Qgb2YgdHJ1dGh5IHZhbHVlc1xuICAgICAqIHdlJ2xsIHVzZSAxIGZvciBhcnJheXMgd2UgaGF2ZW4ndCBhZ2dyZWdhdGVkIHlldCwgMCBmb3IgZmluaXNoZWQgYXJyYXlzLFxuICAgICAqIGFzIGRpc3RpbmN0IGZyb20gdW5kZWZpbmVkIHdoaWNoIG1lYW5zIHRoaXMgYXJyYXkgaXNuJ3QgcHJlc2VudCBpbiB0aGUgaW5wdXRcbiAgICAgKiBtaXNzaW5nIGFycmF5cyBjYW4gc3RpbGwgYmUgYWdncmVnYXRlIG91dHB1dHMgZm9yICpjb3VudCogYWdncmVnYXRpb25zLlxuICAgICAqL1xuICAgIHZhciBhcnJheUF0dHJBcnJheSA9IFBsb3RTY2hlbWEuZmluZEFycmF5QXR0cmlidXRlcyh0cmFjZU91dCk7XG4gICAgdmFyIGFycmF5QXR0cnMgPSB7fTtcbiAgICBmb3IoaSA9IDA7IGkgPCBhcnJheUF0dHJBcnJheS5sZW5ndGg7IGkrKykgYXJyYXlBdHRyc1thcnJheUF0dHJBcnJheVtpXV0gPSAxO1xuXG4gICAgdmFyIGdyb3VwcyA9IGNvZXJjZSgnZ3JvdXBzJyk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShncm91cHMpKSB7XG4gICAgICAgIGlmKCFhcnJheUF0dHJzW2dyb3Vwc10pIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybU91dC5lbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtT3V0O1xuICAgICAgICB9XG4gICAgICAgIGFycmF5QXR0cnNbZ3JvdXBzXSA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGFnZ3JlZ2F0aW9uc0luID0gdHJhbnNmb3JtSW4uYWdncmVnYXRpb25zIHx8IFtdO1xuICAgIHZhciBhZ2dyZWdhdGlvbnNPdXQgPSB0cmFuc2Zvcm1PdXQuYWdncmVnYXRpb25zID0gbmV3IEFycmF5KGFnZ3JlZ2F0aW9uc0luLmxlbmd0aCk7XG4gICAgdmFyIGFnZ3JlZ2F0aW9uT3V0O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlaShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGFnZ3JlZ2F0aW9uc0luW2ldLCBhZ2dyZWdhdGlvbk91dCwgYWdnQXR0cnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGFnZ3JlZ2F0aW9uc0luLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFnZ3JlZ2F0aW9uT3V0ID0ge19pbmRleDogaX07XG4gICAgICAgIHZhciB0YXJnZXQgPSBjb2VyY2VpKCd0YXJnZXQnKTtcbiAgICAgICAgdmFyIGZ1bmMgPSBjb2VyY2VpKCdmdW5jJyk7XG4gICAgICAgIHZhciBlbmFibGVkaSA9IGNvZXJjZWkoJ2VuYWJsZWQnKTtcblxuICAgICAgICAvLyBhZGQgdGhpcyBhZ2dyZWdhdGlvbiB0byB0aGUgb3V0cHV0IG9ubHkgaWYgaXQncyB0aGUgZmlyc3QgaW5zdGFuY2VcbiAgICAgICAgLy8gb2YgYSB2YWxpZCB0YXJnZXQgYXR0cmlidXRlIC0gb3IgYW4gdW51c2VkIHRhcmdldCBhdHRyaWJ1dGUgd2l0aCBcImNvdW50XCJcbiAgICAgICAgaWYoZW5hYmxlZGkgJiYgdGFyZ2V0ICYmIChhcnJheUF0dHJzW3RhcmdldF0gfHwgKGZ1bmMgPT09ICdjb3VudCcgJiYgYXJyYXlBdHRyc1t0YXJnZXRdID09PSB1bmRlZmluZWQpKSkge1xuICAgICAgICAgICAgaWYoZnVuYyA9PT0gJ3N0ZGRldicpIGNvZXJjZWkoJ2Z1bmNtb2RlJyk7XG5cbiAgICAgICAgICAgIGFycmF5QXR0cnNbdGFyZ2V0XSA9IDA7XG4gICAgICAgICAgICBhZ2dyZWdhdGlvbnNPdXRbaV0gPSBhZ2dyZWdhdGlvbk91dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGFnZ3JlZ2F0aW9uc091dFtpXSA9IHtlbmFibGVkOiBmYWxzZSwgX2luZGV4OiBpfTtcbiAgICB9XG5cbiAgICAvLyBhbnkgYXJyYXkgYXR0cmlidXRlcyB3ZSBoYXZlbid0IHlldCBjb3ZlcmVkLCBmaWxsIHRoZW0gd2l0aCB0aGUgZGVmYXVsdCBhZ2dyZWdhdGlvblxuICAgIGZvcihpID0gMDsgaSA8IGFycmF5QXR0ckFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGFycmF5QXR0cnNbYXJyYXlBdHRyQXJyYXlbaV1dKSB7XG4gICAgICAgICAgICBhZ2dyZWdhdGlvbnNPdXQucHVzaCh7XG4gICAgICAgICAgICAgICAgdGFyZ2V0OiBhcnJheUF0dHJBcnJheVtpXSxcbiAgICAgICAgICAgICAgICBmdW5jOiBhZ2dBdHRycy5mdW5jLmRmbHQsXG4gICAgICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBfaW5kZXg6IC0xXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG59O1xuXG5cbmV4cG9ydHMuY2FsY1RyYW5zZm9ybSA9IGZ1bmN0aW9uKGdkLCB0cmFjZSwgb3B0cykge1xuICAgIGlmKCFvcHRzLmVuYWJsZWQpIHJldHVybjtcblxuICAgIHZhciBncm91cHMgPSBvcHRzLmdyb3VwcztcblxuICAgIHZhciBncm91cEFycmF5ID0gTGliLmdldFRhcmdldEFycmF5KHRyYWNlLCB7dGFyZ2V0OiBncm91cHN9KTtcbiAgICBpZighZ3JvdXBBcnJheSkgcmV0dXJuO1xuXG4gICAgdmFyIGksIHZpLCBncm91cEluZGV4LCBuZXdHcm91cGluZztcblxuICAgIHZhciBncm91cEluZGljZXMgPSB7fTtcbiAgICB2YXIgaW5kZXhUb1BvaW50cyA9IHt9O1xuICAgIHZhciBncm91cGluZ3MgPSBbXTtcblxuICAgIHZhciBvcmlnaW5hbFBvaW50c0FjY2Vzc29yID0gcG9pbnRzQWNjZXNzb3JGdW5jdGlvbih0cmFjZS50cmFuc2Zvcm1zLCBvcHRzKTtcblxuICAgIHZhciBsZW4gPSBncm91cEFycmF5Lmxlbmd0aDtcbiAgICBpZih0cmFjZS5fbGVuZ3RoKSBsZW4gPSBNYXRoLm1pbihsZW4sIHRyYWNlLl9sZW5ndGgpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmkgPSBncm91cEFycmF5W2ldO1xuICAgICAgICBncm91cEluZGV4ID0gZ3JvdXBJbmRpY2VzW3ZpXTtcbiAgICAgICAgaWYoZ3JvdXBJbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBncm91cEluZGljZXNbdmldID0gZ3JvdXBpbmdzLmxlbmd0aDtcbiAgICAgICAgICAgIG5ld0dyb3VwaW5nID0gW2ldO1xuICAgICAgICAgICAgZ3JvdXBpbmdzLnB1c2gobmV3R3JvdXBpbmcpO1xuICAgICAgICAgICAgaW5kZXhUb1BvaW50c1tncm91cEluZGljZXNbdmldXSA9IG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBncm91cGluZ3NbZ3JvdXBJbmRleF0ucHVzaChpKTtcbiAgICAgICAgICAgIGluZGV4VG9Qb2ludHNbZ3JvdXBJbmRpY2VzW3ZpXV0gPSAoaW5kZXhUb1BvaW50c1tncm91cEluZGljZXNbdmldXSB8fCBbXSkuY29uY2F0KG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IoaSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb3B0cy5faW5kZXhUb1BvaW50cyA9IGluZGV4VG9Qb2ludHM7XG5cbiAgICB2YXIgYWdncmVnYXRpb25zID0gb3B0cy5hZ2dyZWdhdGlvbnM7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBhZ2dyZWdhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYWdncmVnYXRlT25lQXJyYXkoZ2QsIHRyYWNlLCBncm91cGluZ3MsIGFnZ3JlZ2F0aW9uc1tpXSk7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIGdyb3VwcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgYWdncmVnYXRlT25lQXJyYXkoZ2QsIHRyYWNlLCBncm91cGluZ3MsIHtcbiAgICAgICAgICAgIHRhcmdldDogZ3JvdXBzLFxuICAgICAgICAgICAgZnVuYzogJ2ZpcnN0JyxcbiAgICAgICAgICAgIGVuYWJsZWQ6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdHJhY2UuX2xlbmd0aCA9IGdyb3VwaW5ncy5sZW5ndGg7XG59O1xuXG5mdW5jdGlvbiBhZ2dyZWdhdGVPbmVBcnJheShnZCwgdHJhY2UsIGdyb3VwaW5ncywgYWdncmVnYXRpb24pIHtcbiAgICBpZighYWdncmVnYXRpb24uZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgdmFyIGF0dHIgPSBhZ2dyZWdhdGlvbi50YXJnZXQ7XG4gICAgdmFyIHRhcmdldE5QID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhdHRyKTtcbiAgICB2YXIgYXJyYXlJbiA9IHRhcmdldE5QLmdldCgpO1xuICAgIHZhciBjb252ZXJzaW9ucyA9IEF4ZXMuZ2V0RGF0YUNvbnZlcnNpb25zKGdkLCB0cmFjZSwgYXR0ciwgYXJyYXlJbik7XG4gICAgdmFyIGZ1bmMgPSBnZXRBZ2dyZWdhdGVGdW5jdGlvbihhZ2dyZWdhdGlvbiwgY29udmVyc2lvbnMpO1xuXG4gICAgdmFyIGFycmF5T3V0ID0gbmV3IEFycmF5KGdyb3VwaW5ncy5sZW5ndGgpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBncm91cGluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXJyYXlPdXRbaV0gPSBmdW5jKGFycmF5SW4sIGdyb3VwaW5nc1tpXSk7XG4gICAgfVxuICAgIHRhcmdldE5QLnNldChhcnJheU91dCk7XG5cbiAgICBpZihhZ2dyZWdhdGlvbi5mdW5jID09PSAnY291bnQnKSB7XG4gICAgICAgIC8vIGNvdW50IGRvZXMgbm90IGRlcGVuZCBvbiBhbiBpbnB1dCBhcnJheSwgc28gaXQncyBsaWtlbHkgbm90IHBhcnQgb2YgX2FycmF5QXR0cnMgeWV0XG4gICAgICAgIC8vIGJ1dCBhZnRlciB0aGlzIHRyYW5zZm9ybSBpdCBtb3N0IGRlZmluaXRlbHkgKmlzKiBhbiBhcnJheSBhdHRyaWJ1dGUuXG4gICAgICAgIExpYi5wdXNoVW5pcXVlKHRyYWNlLl9hcnJheUF0dHJzLCBhdHRyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEFnZ3JlZ2F0ZUZ1bmN0aW9uKG9wdHMsIGNvbnZlcnNpb25zKSB7XG4gICAgdmFyIGZ1bmMgPSBvcHRzLmZ1bmM7XG4gICAgdmFyIGQyYyA9IGNvbnZlcnNpb25zLmQyYztcbiAgICB2YXIgYzJkID0gY29udmVyc2lvbnMuYzJkO1xuXG4gICAgc3dpdGNoKGZ1bmMpIHtcbiAgICAgICAgLy8gY291bnQsIGZpcnN0LCBhbmQgbGFzdCBkb24ndCBkZXBlbmQgb24gYW55dGhpbmcgYWJvdXQgdGhlIGRhdGFcbiAgICAgICAgLy8gcG9pbnQgYmFjayB0byBwdXJlIGZ1bmN0aW9ucyBmb3IgcGVyZm9ybWFuY2VcbiAgICAgICAgY2FzZSAnY291bnQnOlxuICAgICAgICAgICAgcmV0dXJuIGNvdW50O1xuICAgICAgICBjYXNlICdmaXJzdCc6XG4gICAgICAgICAgICByZXR1cm4gZmlyc3Q7XG4gICAgICAgIGNhc2UgJ2xhc3QnOlxuICAgICAgICAgICAgcmV0dXJuIGxhc3Q7XG5cbiAgICAgICAgY2FzZSAnc3VtJzpcbiAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBwcm9kdWNlIG91dHB1dCBpbiBhbGwgY2FzZXMgZXZlbiB0aG91Z2ggaXQncyBub25zZW5zaWNhbFxuICAgICAgICAgICAgLy8gZm9yIGRhdGUgb3IgY2F0ZWdvcnkgZGF0YS5cbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpID0gZDJjKGFycmF5W2luZGljZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodmkgIT09IEJBRE5VTSkgdG90YWwgKz0gdmk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjMmQodG90YWwpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdhdmcnOlxuICAgICAgICAgICAgLy8gR2VuZXJhbGx5IG1lYW5pbmdsZXNzIGZvciBjYXRlZ29yeSBkYXRhIGJ1dCBpdCBzdGlsbCBkb2VzIHNvbWV0aGluZy5cbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGNudCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpID0gZDJjKGFycmF5W2luZGljZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodmkgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG90YWwgKz0gdmk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gY250ID8gYzJkKHRvdGFsIC8gY250KSA6IEJBRE5VTTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnbWluJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciBvdXQgPSBJbmZpbml0eTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSBvdXQgPSBNYXRoLm1pbihvdXQsIHZpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIChvdXQgPT09IEluZmluaXR5KSA/IEJBRE5VTSA6IGMyZChvdXQpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdtYXgnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dCA9IC1JbmZpbml0eTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSBvdXQgPSBNYXRoLm1heChvdXQsIHZpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIChvdXQgPT09IC1JbmZpbml0eSkgPyBCQUROVU0gOiBjMmQob3V0KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAncmFuZ2UnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgICAgICAgICAgICAgIHZhciBtYXggPSAtSW5maW5pdHk7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpID0gZDJjKGFycmF5W2luZGljZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodmkgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gTWF0aC5taW4obWluLCB2aSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIHZpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKG1heCA9PT0gLUluZmluaXR5IHx8IG1pbiA9PT0gSW5maW5pdHkpID8gQkFETlVNIDogYzJkKG1heCAtIG1pbik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ2NoYW5nZSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlyc3QgPSBkMmMoYXJyYXlbaW5kaWNlc1swXV0pO1xuICAgICAgICAgICAgICAgIHZhciBsYXN0ID0gZDJjKGFycmF5W2luZGljZXNbaW5kaWNlcy5sZW5ndGggLSAxXV0pO1xuICAgICAgICAgICAgICAgIHJldHVybiAoZmlyc3QgPT09IEJBRE5VTSB8fCBsYXN0ID09PSBCQUROVU0pID8gQkFETlVNIDogYzJkKGxhc3QgLSBmaXJzdCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ21lZGlhbic6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgc29ydENhbGMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSBzb3J0Q2FsYy5wdXNoKHZpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoIXNvcnRDYWxjLmxlbmd0aCkgcmV0dXJuIEJBRE5VTTtcbiAgICAgICAgICAgICAgICBzb3J0Q2FsYy5zb3J0KCk7XG4gICAgICAgICAgICAgICAgdmFyIG1pZCA9IChzb3J0Q2FsYy5sZW5ndGggLSAxKSAvIDI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGMyZCgoc29ydENhbGNbTWF0aC5mbG9vcihtaWQpXSArIHNvcnRDYWxjW01hdGguY2VpbChtaWQpXSkgLyAyKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnbW9kZSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY291bnRzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG1heENudCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG91dCA9IEJBRE5VTTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY291bnRpID0gY291bnRzW3ZpXSA9IChjb3VudHNbdmldIHx8IDApICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGNvdW50aSA+IG1heENudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heENudCA9IGNvdW50aTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSB2aTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWF4Q250ID8gYzJkKG91dCkgOiBCQUROVU07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ3Jtcyc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG90YWwgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBjbnQgPSAwO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsICs9IHZpICogdmk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gY250ID8gYzJkKE1hdGguc3FydCh0b3RhbCAvIGNudCkpIDogQkFETlVNO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdzdGRkZXYnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgLy8gYmFsYW5jZSBudW1lcmljYWwgc3RhYmlsaXR5IHdpdGggcGVyZm9ybWFuY2U6XG4gICAgICAgICAgICAgICAgLy8gc28gdGhhdCB3ZSBjYWxsIGQyYyBvbmNlIHBlciBlbGVtZW50IGJ1dCBkb24ndCBuZWVkIHRvXG4gICAgICAgICAgICAgICAgLy8gc3RvcmUgdGhlbSwgcmVmZXJlbmNlIGFsbCB0byB0aGUgZmlyc3QgZWxlbWVudFxuICAgICAgICAgICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHRvdGFsMiA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGNudCA9IDE7XG4gICAgICAgICAgICAgICAgdmFyIHYwID0gQkFETlVNO1xuICAgICAgICAgICAgICAgIHZhciBpO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoICYmIHYwID09PSBCQUROVU07IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2MCA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHYwID09PSBCQUROVU0pIHJldHVybiBCQUROVU07XG5cbiAgICAgICAgICAgICAgICBmb3IoOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZHYgPSB2aSAtIHYwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdG90YWwgKz0gZHY7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3RhbDIgKz0gZHYgKiBkdjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBwb3B1bGF0aW9uIHN0ZCBkZXYsIGlmIHdlIHdhbnQgc2FtcGxlIHN0ZCBkZXZcbiAgICAgICAgICAgICAgICAvLyB3ZSB3b3VsZCBuZWVkICguLi4pIC8gKGNudCAtIDEpXG4gICAgICAgICAgICAgICAgLy8gQWxzbyBub3RlIHRoZXJlJ3Mgbm8gYzJkIGhlcmUgLSB0aGF0IG1lYW5zIGZvciBkYXRlcyB0aGUgcmVzdWx0XG4gICAgICAgICAgICAgICAgLy8gaXMgYSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLCBhbmQgZm9yIGNhdGVnb3JpZXMgaXQncyBhIG51bWJlclxuICAgICAgICAgICAgICAgIC8vIG9mIGNhdGVnb3J5IGRpZmZlcmVuY2VzLCB3aGljaCBpcyBub3QgZ2VuZXJpY2FsbHkgbWVhbmluZ2Z1bCBidXRcbiAgICAgICAgICAgICAgICAvLyBhcyBpbiBvdGhlciBjYXNlcyB3ZSBkb24ndCBmb3JiaWQgaXQuXG4gICAgICAgICAgICAgICAgdmFyIG5vcm0gPSAob3B0cy5mdW5jbW9kZSA9PT0gJ3NhbXBsZScpID8gKGNudCAtIDEpIDogY250O1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgZGViYXRhYmxlOiBzaG91bGQgYSBjb3VudCBvZiAxIHJldHVybiBzYW1wbGUgc3RkZGV2IG9mXG4gICAgICAgICAgICAgICAgLy8gMCBvciB1bmRlZmluZWQ/XG4gICAgICAgICAgICAgICAgaWYoIW5vcm0pIHJldHVybiAwO1xuICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLnNxcnQoKHRvdGFsMiAtICh0b3RhbCAqIHRvdGFsIC8gY250KSkgLyBub3JtKTtcbiAgICAgICAgICAgIH07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjb3VudChhcnJheSwgaW5kaWNlcykge1xuICAgIHJldHVybiBpbmRpY2VzLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gZmlyc3QoYXJyYXksIGluZGljZXMpIHtcbiAgICByZXR1cm4gYXJyYXlbaW5kaWNlc1swXV07XG59XG5cbmZ1bmN0aW9uIGxhc3QoYXJyYXksIGluZGljZXMpIHtcbiAgICByZXR1cm4gYXJyYXlbaW5kaWNlc1tpbmRpY2VzLmxlbmd0aCAtIDFdXTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi4vcmVnaXN0cnknKTtcbnZhciBBeGVzID0gcmVxdWlyZSgnLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBwb2ludHNBY2Nlc3NvckZ1bmN0aW9uID0gcmVxdWlyZSgnLi9oZWxwZXJzJykucG9pbnRzQWNjZXNzb3JGdW5jdGlvbjtcblxudmFyIGZpbHRlck9wcyA9IHJlcXVpcmUoJy4uL2NvbnN0YW50cy9maWx0ZXJfb3BzJyk7XG52YXIgQ09NUEFSSVNPTl9PUFMgPSBmaWx0ZXJPcHMuQ09NUEFSSVNPTl9PUFM7XG52YXIgSU5URVJWQUxfT1BTID0gZmlsdGVyT3BzLklOVEVSVkFMX09QUztcbnZhciBTRVRfT1BTID0gZmlsdGVyT3BzLlNFVF9PUFM7XG5cbmV4cG9ydHMubW9kdWxlVHlwZSA9ICd0cmFuc2Zvcm0nO1xuXG5leHBvcnRzLm5hbWUgPSAnZmlsdGVyJztcblxuZXhwb3J0cy5hdHRyaWJ1dGVzID0ge1xuICAgIGVuYWJsZWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0YXJnZXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIHN0cmljdDogdHJ1ZSxcbiAgICAgICAgbm9CbGFuazogdHJ1ZSxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgZGZsdDogJ3gnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBvcGVyYXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtdXG4gICAgICAgICAgICAuY29uY2F0KENPTVBBUklTT05fT1BTKVxuICAgICAgICAgICAgLmNvbmNhdChJTlRFUlZBTF9PUFMpXG4gICAgICAgICAgICAuY29uY2F0KFNFVF9PUFMpLFxuICAgICAgICBkZmx0OiAnPScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHZhbHVlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBwcmVzZXJ2ZWdhcHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufTtcblxuZXhwb3J0cy5zdXBwbHlEZWZhdWx0cyA9IGZ1bmN0aW9uKHRyYW5zZm9ybUluKSB7XG4gICAgdmFyIHRyYW5zZm9ybU91dCA9IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhbnNmb3JtSW4sIHRyYW5zZm9ybU91dCwgZXhwb3J0cy5hdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZW5hYmxlZCA9IGNvZXJjZSgnZW5hYmxlZCcpO1xuXG4gICAgaWYoZW5hYmxlZCkge1xuICAgICAgICBjb2VyY2UoJ3ByZXNlcnZlZ2FwcycpO1xuICAgICAgICBjb2VyY2UoJ29wZXJhdGlvbicpO1xuICAgICAgICBjb2VyY2UoJ3ZhbHVlJyk7XG4gICAgICAgIGNvZXJjZSgndGFyZ2V0Jyk7XG5cbiAgICAgICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVEZWZhdWx0cycpO1xuICAgICAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYW5zZm9ybUluLCB0cmFuc2Zvcm1PdXQsICd2YWx1ZWNhbGVuZGFyJywgbnVsbCk7XG4gICAgICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhbnNmb3JtSW4sIHRyYW5zZm9ybU91dCwgJ3RhcmdldGNhbGVuZGFyJywgbnVsbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zZm9ybU91dDtcbn07XG5cbmV4cG9ydHMuY2FsY1RyYW5zZm9ybSA9IGZ1bmN0aW9uKGdkLCB0cmFjZSwgb3B0cykge1xuICAgIGlmKCFvcHRzLmVuYWJsZWQpIHJldHVybjtcblxuICAgIHZhciB0YXJnZXRBcnJheSA9IExpYi5nZXRUYXJnZXRBcnJheSh0cmFjZSwgb3B0cyk7XG4gICAgaWYoIXRhcmdldEFycmF5KSByZXR1cm47XG5cbiAgICB2YXIgdGFyZ2V0ID0gb3B0cy50YXJnZXQ7XG5cbiAgICB2YXIgbGVuID0gdGFyZ2V0QXJyYXkubGVuZ3RoO1xuICAgIGlmKHRyYWNlLl9sZW5ndGgpIGxlbiA9IE1hdGgubWluKGxlbiwgdHJhY2UuX2xlbmd0aCk7XG5cbiAgICB2YXIgdGFyZ2V0Q2FsZW5kYXIgPSBvcHRzLnRhcmdldGNhbGVuZGFyO1xuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG4gICAgdmFyIHByZXNlcnZlZ2FwcyA9IG9wdHMucHJlc2VydmVnYXBzO1xuXG4gICAgLy8gZXZlbiBpZiB5b3UgcHJvdmlkZSB0YXJnZXRjYWxlbmRhciwgaWYgdGFyZ2V0IGlzIGEgc3RyaW5nIGFuZCB0aGVyZVxuICAgIC8vIGlzIGEgY2FsZW5kYXIgYXR0cmlidXRlIG1hdGNoaW5nIHRhcmdldCBpdCB3aWxsIGdldCB1c2VkIGluc3RlYWQuXG4gICAgaWYodHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIGF0dHJUYXJnZXRDYWxlbmRhciA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgdGFyZ2V0ICsgJ2NhbGVuZGFyJykuZ2V0KCk7XG4gICAgICAgIGlmKGF0dHJUYXJnZXRDYWxlbmRhcikgdGFyZ2V0Q2FsZW5kYXIgPSBhdHRyVGFyZ2V0Q2FsZW5kYXI7XG4gICAgfVxuXG4gICAgdmFyIGQyYyA9IEF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jKGdkLCB0cmFjZSwgdGFyZ2V0LCB0YXJnZXRBcnJheSk7XG4gICAgdmFyIGZpbHRlckZ1bmMgPSBnZXRGaWx0ZXJGdW5jKG9wdHMsIGQyYywgdGFyZ2V0Q2FsZW5kYXIpO1xuICAgIHZhciBvcmlnaW5hbEFycmF5cyA9IHt9O1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0ge307XG4gICAgdmFyIGluZGV4ID0gMDtcblxuICAgIGZ1bmN0aW9uIGZvckFsbEF0dHJzKGZuLCBpbmRleCkge1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYXJyYXlBdHRycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIG5wID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhcnJheUF0dHJzW2pdKTtcbiAgICAgICAgICAgIGZuKG5wLCBpbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW5pdEZuO1xuICAgIHZhciBmaWxsRm47XG4gICAgaWYocHJlc2VydmVnYXBzKSB7XG4gICAgICAgIGluaXRGbiA9IGZ1bmN0aW9uKG5wKSB7XG4gICAgICAgICAgICBvcmlnaW5hbEFycmF5c1tucC5hc3RyXSA9IExpYi5leHRlbmREZWVwKFtdLCBucC5nZXQoKSk7XG4gICAgICAgICAgICBucC5zZXQobmV3IEFycmF5KGxlbikpO1xuICAgICAgICB9O1xuICAgICAgICBmaWxsRm4gPSBmdW5jdGlvbihucCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciB2YWwgPSBvcmlnaW5hbEFycmF5c1tucC5hc3RyXVtpbmRleF07XG4gICAgICAgICAgICBucC5nZXQoKVtpbmRleF0gPSB2YWw7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdEZuID0gZnVuY3Rpb24obnApIHtcbiAgICAgICAgICAgIG9yaWdpbmFsQXJyYXlzW25wLmFzdHJdID0gTGliLmV4dGVuZERlZXAoW10sIG5wLmdldCgpKTtcbiAgICAgICAgICAgIG5wLnNldChbXSk7XG4gICAgICAgIH07XG4gICAgICAgIGZpbGxGbiA9IGZ1bmN0aW9uKG5wLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IG9yaWdpbmFsQXJyYXlzW25wLmFzdHJdW2luZGV4XTtcbiAgICAgICAgICAgIG5wLmdldCgpLnB1c2godmFsKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBjb3B5IGFsbCBvcmlnaW5hbCBhcnJheSBhdHRyaWJ1dGUgdmFsdWVzLCBhbmQgY2xlYXIgYXJyYXlzIGluIHRyYWNlXG4gICAgZm9yQWxsQXR0cnMoaW5pdEZuKTtcblxuICAgIHZhciBvcmlnaW5hbFBvaW50c0FjY2Vzc29yID0gcG9pbnRzQWNjZXNzb3JGdW5jdGlvbih0cmFjZS50cmFuc2Zvcm1zLCBvcHRzKTtcblxuICAgIC8vIGxvb3AgdGhyb3VnaCBmaWx0ZXIgYXJyYXksIGZpbGwgdHJhY2UgYXJyYXlzIGlmIHBhc3NlZFxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgcGFzc2VkID0gZmlsdGVyRnVuYyh0YXJnZXRBcnJheVtpXSk7XG4gICAgICAgIGlmKHBhc3NlZCkge1xuICAgICAgICAgICAgZm9yQWxsQXR0cnMoZmlsbEZuLCBpKTtcbiAgICAgICAgICAgIGluZGV4VG9Qb2ludHNbaW5kZXgrK10gPSBvcmlnaW5hbFBvaW50c0FjY2Vzc29yKGkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocHJlc2VydmVnYXBzKSBpbmRleCsrO1xuICAgIH1cblxuICAgIG9wdHMuX2luZGV4VG9Qb2ludHMgPSBpbmRleFRvUG9pbnRzO1xuICAgIHRyYWNlLl9sZW5ndGggPSBpbmRleDtcbn07XG5cbmZ1bmN0aW9uIGdldEZpbHRlckZ1bmMob3B0cywgZDJjLCB0YXJnZXRDYWxlbmRhcikge1xuICAgIHZhciBvcGVyYXRpb24gPSBvcHRzLm9wZXJhdGlvbixcbiAgICAgICAgdmFsdWUgPSBvcHRzLnZhbHVlLFxuICAgICAgICBoYXNBcnJheVZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG5cbiAgICBmdW5jdGlvbiBpc09wZXJhdGlvbkluKGFycmF5KSB7XG4gICAgICAgIHJldHVybiBhcnJheS5pbmRleE9mKG9wZXJhdGlvbikgIT09IC0xO1xuICAgIH1cblxuICAgIHZhciBkMmNWYWx1ZSA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyYyh2LCAwLCBvcHRzLnZhbHVlY2FsZW5kYXIpOyB9LFxuICAgICAgICBkMmNUYXJnZXQgPSBmdW5jdGlvbih2KSB7IHJldHVybiBkMmModiwgMCwgdGFyZ2V0Q2FsZW5kYXIpOyB9O1xuXG4gICAgdmFyIGNvZXJjZWRWYWx1ZTtcblxuICAgIGlmKGlzT3BlcmF0aW9uSW4oQ09NUEFSSVNPTl9PUFMpKSB7XG4gICAgICAgIGNvZXJjZWRWYWx1ZSA9IGhhc0FycmF5VmFsdWUgPyBkMmNWYWx1ZSh2YWx1ZVswXSkgOiBkMmNWYWx1ZSh2YWx1ZSk7XG4gICAgfVxuICAgIGVsc2UgaWYoaXNPcGVyYXRpb25JbihJTlRFUlZBTF9PUFMpKSB7XG4gICAgICAgIGNvZXJjZWRWYWx1ZSA9IGhhc0FycmF5VmFsdWUgP1xuICAgICAgICAgICAgW2QyY1ZhbHVlKHZhbHVlWzBdKSwgZDJjVmFsdWUodmFsdWVbMV0pXSA6XG4gICAgICAgICAgICBbZDJjVmFsdWUodmFsdWUpLCBkMmNWYWx1ZSh2YWx1ZSldO1xuICAgIH1cbiAgICBlbHNlIGlmKGlzT3BlcmF0aW9uSW4oU0VUX09QUykpIHtcbiAgICAgICAgY29lcmNlZFZhbHVlID0gaGFzQXJyYXlWYWx1ZSA/IHZhbHVlLm1hcChkMmNWYWx1ZSkgOiBbZDJjVmFsdWUodmFsdWUpXTtcbiAgICB9XG5cbiAgICBzd2l0Y2gob3BlcmF0aW9uKSB7XG5cbiAgICAgICAgY2FzZSAnPSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gZDJjVGFyZ2V0KHYpID09PSBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSAhPT0gY29lcmNlZFZhbHVlOyB9O1xuXG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSA8IGNvZXJjZWRWYWx1ZTsgfTtcblxuICAgICAgICBjYXNlICc8PSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gZDJjVGFyZ2V0KHYpIDw9IGNvZXJjZWRWYWx1ZTsgfTtcblxuICAgICAgICBjYXNlICc+JzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7IHJldHVybiBkMmNUYXJnZXQodikgPiBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSA+PSBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnW10nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID49IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8PSBjb2VyY2VkVmFsdWVbMV07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJygpJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGN2ID0gZDJjVGFyZ2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjdiA+IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnWyknOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID49IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnKF0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID4gY29lcmNlZFZhbHVlWzBdICYmIGN2IDw9IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnXVsnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDw9IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+PSBjb2VyY2VkVmFsdWVbMV07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJykoJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGN2ID0gZDJjVGFyZ2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjdiA8IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnXSgnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDw9IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnKVsnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDwgY29lcmNlZFZhbHVlWzBdIHx8IGN2ID49IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAne30nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29lcmNlZFZhbHVlLmluZGV4T2YoZDJjVGFyZ2V0KHYpKSAhPT0gLTE7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ317JzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZXJjZWRWYWx1ZS5pbmRleE9mKGQyY1RhcmdldCh2KSkgPT09IC0xO1xuICAgICAgICAgICAgfTtcbiAgICB9XG59XG4iLCIvKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOCwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSByZXF1aXJlKCcuLi9saWInKTtcbnZhciBQbG90U2NoZW1hID0gcmVxdWlyZSgnLi4vcGxvdF9hcGkvcGxvdF9zY2hlbWEnKTtcbnZhciBQbG90cyA9IHJlcXVpcmUoJy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgcG9pbnRzQWNjZXNzb3JGdW5jdGlvbiA9IHJlcXVpcmUoJy4vaGVscGVycycpLnBvaW50c0FjY2Vzc29yRnVuY3Rpb247XG5cbmV4cG9ydHMubW9kdWxlVHlwZSA9ICd0cmFuc2Zvcm0nO1xuXG5leHBvcnRzLm5hbWUgPSAnZ3JvdXBieSc7XG5cbmV4cG9ydHMuYXR0cmlidXRlcyA9IHtcbiAgICBlbmFibGVkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JvdXBzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZGZsdDogW10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG5hbWVmb3JtYXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0eWxlczoge1xuICAgICAgICBfaXNMaW5rZWRUb0FycmF5OiAnc3R5bGUnLFxuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDoge30sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBfY29tcGFyZUFzSlNPTjogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG4vKipcbiAqIFN1cHBseSB0cmFuc2Zvcm0gYXR0cmlidXRlcyBkZWZhdWx0c1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFuc2Zvcm1JblxuICogIG9iamVjdCBsaW5rZWQgdG8gdHJhY2UudHJhbnNmb3Jtc1tpXSB3aXRoICd0eXBlJyBzZXQgdG8gZXhwb3J0cy5uYW1lXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VPdXRcbiAqICB0aGUgX2Z1bGxEYXRhIHRyYWNlIHRoaXMgdHJhbnNmb3JtIGFwcGxpZXMgdG9cbiAqIEBwYXJhbSB7b2JqZWN0fSBsYXlvdXRcbiAqICB0aGUgcGxvdCdzIChub3Qtc28tZnVsbCkgbGF5b3V0XG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VJblxuICogIHRoZSBpbnB1dCBkYXRhIHRyYWNlIHRoaXMgdHJhbnNmb3JtIGFwcGxpZXMgdG9cbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IHRyYW5zZm9ybU91dFxuICogIGNvcHkgb2YgdHJhbnNmb3JtSW4gdGhhdCBjb250YWlucyBhdHRyaWJ1dGUgZGVmYXVsdHNcbiAqL1xuZXhwb3J0cy5zdXBwbHlEZWZhdWx0cyA9IGZ1bmN0aW9uKHRyYW5zZm9ybUluLCB0cmFjZU91dCwgbGF5b3V0KSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIHRyYW5zZm9ybU91dCA9IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhbnNmb3JtSW4sIHRyYW5zZm9ybU91dCwgZXhwb3J0cy5hdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZW5hYmxlZCA9IGNvZXJjZSgnZW5hYmxlZCcpO1xuXG4gICAgaWYoIWVuYWJsZWQpIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG5cbiAgICBjb2VyY2UoJ2dyb3VwcycpO1xuICAgIGNvZXJjZSgnbmFtZWZvcm1hdCcsIGxheW91dC5fZGF0YUxlbmd0aCA+IDEgPyAnJXtncm91cH0gKCV7dHJhY2V9KScgOiAnJXtncm91cH0nKTtcblxuICAgIHZhciBzdHlsZUluID0gdHJhbnNmb3JtSW4uc3R5bGVzO1xuICAgIHZhciBzdHlsZU91dCA9IHRyYW5zZm9ybU91dC5zdHlsZXMgPSBbXTtcblxuICAgIGlmKHN0eWxlSW4pIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3R5bGVJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRoaXNTdHlsZSA9IHN0eWxlT3V0W2ldID0ge307XG4gICAgICAgICAgICBMaWIuY29lcmNlKHN0eWxlSW5baV0sIHN0eWxlT3V0W2ldLCBleHBvcnRzLmF0dHJpYnV0ZXMuc3R5bGVzLCAndGFyZ2V0Jyk7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBMaWIuY29lcmNlKHN0eWxlSW5baV0sIHN0eWxlT3V0W2ldLCBleHBvcnRzLmF0dHJpYnV0ZXMuc3R5bGVzLCAndmFsdWUnKTtcblxuICAgICAgICAgICAgLy8gc28gdGhhdCB5b3UgY2FuIGVkaXQgdmFsdWUgaW4gcGxhY2UgYW5kIGhhdmUgUGxvdGx5LnJlYWN0IG5vdGljZSBpdCwgb3JcbiAgICAgICAgICAgIC8vIHJlYnVpbGQgaXQgZXZlcnkgdGltZSBhbmQgaGF2ZSBQbG90bHkucmVhY3QgTk9UIHRoaW5rIGl0IGNoYW5nZWQ6XG4gICAgICAgICAgICAvLyB1c2UgX2NvbXBhcmVBc0pTT04gdG8gc2F5IHdlIHNob3VsZCBkaWZmIHRoZSBfSlNPTl92YWx1ZVxuICAgICAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QodmFsdWUpKSB0aGlzU3R5bGUudmFsdWUgPSBMaWIuZXh0ZW5kRGVlcCh7fSwgdmFsdWUpO1xuICAgICAgICAgICAgZWxzZSBpZih2YWx1ZSkgZGVsZXRlIHRoaXNTdHlsZS52YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG59O1xuXG5cbi8qKlxuICogQXBwbHkgdHJhbnNmb3JtICEhIVxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGRhdGFcbiAqICBhcnJheSBvZiB0cmFuc2Zvcm1lZCB0cmFjZXMgKGlzIFtmdWxsVHJhY2VdIHVwb24gZmlyc3QgdHJhbnNmb3JtKVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogIHN0YXRlIG9iamVjdCB3aGljaCBpbmNsdWRlczpcbiAqICAgICAgLSB0cmFuc2Zvcm0ge29iamVjdH0gZnVsbCB0cmFuc2Zvcm0gYXR0cmlidXRlc1xuICogICAgICAtIGZ1bGxUcmFjZSB7b2JqZWN0fSBmdWxsIHRyYWNlIG9iamVjdCB3aGljaCBpcyBiZWluZyB0cmFuc2Zvcm1lZFxuICogICAgICAtIGZ1bGxEYXRhIHthcnJheX0gZnVsbCBwcmUtdHJhbnNmb3JtKHMpIGRhdGEgYXJyYXlcbiAqICAgICAgLSBsYXlvdXQge29iamVjdH0gdGhlIHBsb3QncyAobm90LXNvLWZ1bGwpIGxheW91dFxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gbmV3RGF0YVxuICogIGFycmF5IG9mIHRyYW5zZm9ybWVkIHRyYWNlc1xuICovXG5leHBvcnRzLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKGRhdGEsIHN0YXRlKSB7XG4gICAgdmFyIG5ld1RyYWNlcywgaSwgajtcbiAgICB2YXIgbmV3RGF0YSA9IFtdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBuZXdUcmFjZXMgPSB0cmFuc2Zvcm1PbmUoZGF0YVtpXSwgc3RhdGUpO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IG5ld1RyYWNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgbmV3RGF0YS5wdXNoKG5ld1RyYWNlc1tqXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV3RGF0YTtcbn07XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybU9uZSh0cmFjZSwgc3RhdGUpIHtcbiAgICB2YXIgaSwgaiwgaywgYXR0ciwgc3JjQXJyYXksIGdyb3VwTmFtZSwgbmV3VHJhY2UsIHRyYW5zZm9ybXMsIGFycmF5TG9va3VwO1xuICAgIHZhciBncm91cE5hbWVPYmo7XG5cbiAgICB2YXIgb3B0cyA9IHN0YXRlLnRyYW5zZm9ybTtcbiAgICB2YXIgdHJhbnNmb3JtSW5kZXggPSBzdGF0ZS50cmFuc2Zvcm1JbmRleDtcbiAgICB2YXIgZ3JvdXBzID0gdHJhY2UudHJhbnNmb3Jtc1t0cmFuc2Zvcm1JbmRleF0uZ3JvdXBzO1xuICAgIHZhciBvcmlnaW5hbFBvaW50c0FjY2Vzc29yID0gcG9pbnRzQWNjZXNzb3JGdW5jdGlvbih0cmFjZS50cmFuc2Zvcm1zLCBvcHRzKTtcblxuICAgIGlmKCEoQXJyYXkuaXNBcnJheShncm91cHMpKSB8fCBncm91cHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBbdHJhY2VdO1xuICAgIH1cblxuICAgIHZhciBncm91cE5hbWVzID0gTGliLmZpbHRlclVuaXF1ZShncm91cHMpLFxuICAgICAgICBuZXdEYXRhID0gbmV3IEFycmF5KGdyb3VwTmFtZXMubGVuZ3RoKSxcbiAgICAgICAgbGVuID0gZ3JvdXBzLmxlbmd0aDtcblxuICAgIHZhciBhcnJheUF0dHJzID0gUGxvdFNjaGVtYS5maW5kQXJyYXlBdHRyaWJ1dGVzKHRyYWNlKTtcblxuICAgIHZhciBzdHlsZXMgPSBvcHRzLnN0eWxlcyB8fCBbXTtcbiAgICB2YXIgc3R5bGVMb29rdXAgPSB7fTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzdHlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3R5bGVMb29rdXBbc3R5bGVzW2ldLnRhcmdldF0gPSBzdHlsZXNbaV0udmFsdWU7XG4gICAgfVxuXG4gICAgaWYob3B0cy5zdHlsZXMpIHtcbiAgICAgICAgZ3JvdXBOYW1lT2JqID0gTGliLmtleWVkQ29udGFpbmVyKG9wdHMsICdzdHlsZXMnLCAndGFyZ2V0JywgJ3ZhbHVlLm5hbWUnKTtcbiAgICB9XG5cbiAgICAvLyBBbiBpbmRleCB0byBtYXAgZ3JvdXAgbmFtZSAtLT4gZXhwYW5kZWQgdHJhY2UgaW5kZXhcbiAgICB2YXIgaW5kZXhMb29rdXAgPSB7fTtcbiAgICB2YXIgaW5kZXhDbnRzID0ge307XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBncm91cE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdyb3VwTmFtZSA9IGdyb3VwTmFtZXNbaV07XG4gICAgICAgIGluZGV4TG9va3VwW2dyb3VwTmFtZV0gPSBpO1xuICAgICAgICBpbmRleENudHNbZ3JvdXBOYW1lXSA9IDA7XG5cbiAgICAgICAgLy8gU3RhcnQgd2l0aCBhIGRlZXAgZXh0ZW5kIHRoYXQganVzdCBjb3BpZXMgYXJyYXkgcmVmZXJlbmNlcy5cbiAgICAgICAgbmV3VHJhY2UgPSBuZXdEYXRhW2ldID0gTGliLmV4dGVuZERlZXBOb0FycmF5cyh7fSwgdHJhY2UpO1xuICAgICAgICBuZXdUcmFjZS5fZ3JvdXAgPSBncm91cE5hbWU7XG4gICAgICAgIC8vIGhlbHBlciBmdW5jdGlvbiBmb3Igd2hlbiB3ZSBuZWVkIHRvIHB1c2ggdXBkYXRlcyBiYWNrIHRvIHRoZSBpbnB1dCxcbiAgICAgICAgLy8gb3V0c2lkZSBvZiB0aGUgbm9ybWFsIHJlc3R5bGUvcmVsYXlvdXQgcGF0aHdheSwgbGlrZSBmaWxsaW5nIGluIGF1dG8gdmFsdWVzXG4gICAgICAgIG5ld1RyYWNlLnVwZGF0ZVN0eWxlID0gc3R5bGVVcGRhdGVyKGdyb3VwTmFtZSwgdHJhbnNmb3JtSW5kZXgpO1xuICAgICAgICBuZXdUcmFjZS50cmFuc2Zvcm1zW3RyYW5zZm9ybUluZGV4XS5faW5kZXhUb1BvaW50cyA9IHt9O1xuXG4gICAgICAgIHZhciBzdXBwbGllZE5hbWUgPSBudWxsO1xuICAgICAgICBpZihncm91cE5hbWVPYmopIHtcbiAgICAgICAgICAgIHN1cHBsaWVkTmFtZSA9IGdyb3VwTmFtZU9iai5nZXQoZ3JvdXBOYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHN1cHBsaWVkTmFtZSB8fCBzdXBwbGllZE5hbWUgPT09ICcnKSB7XG4gICAgICAgICAgICBuZXdUcmFjZS5uYW1lID0gc3VwcGxpZWROYW1lO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3VHJhY2UubmFtZSA9IExpYi50ZW1wbGF0ZVN0cmluZyhvcHRzLm5hbWVmb3JtYXQsIHtcbiAgICAgICAgICAgICAgICB0cmFjZTogdHJhY2UubmFtZSxcbiAgICAgICAgICAgICAgICBncm91cDogZ3JvdXBOYW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIG9yZGVyIGZvciBncm91cHMgdG8gYXBwbHkgY29ycmVjdGx5IHRvIG90aGVyIHRyYW5zZm9ybSBkYXRhIChlLmcuXG4gICAgICAgIC8vIGEgZmlsdGVyIHRyYW5zZm9ybSksIHdlIGhhdmUgdG8gYnJlYWsgdGhlIGNvbm5lY3Rpb24gYW5kIGNsb25lIHRoZVxuICAgICAgICAvLyB0cmFuc2Zvcm1zIHNvIHRoYXQgZWFjaCBncm91cCB3cml0ZXMgZ3JvdXBlZCB2YWx1ZXMgaW50byBhIGRpZmZlcmVudFxuICAgICAgICAvLyBkZXN0aW5hdGlvbi4gVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBicmVhayB0aGUgYXJyYXkgcmVmZXJlbmNlXG4gICAgICAgIC8vIGNvbm5lY3Rpb24gYmV0d2VlbiB0aGUgc3BsaXQgdHJhbnNmb3JtcyBpdCBjcmVhdGVzLiBUaGF0J3MgaGFuZGxlZCBpblxuICAgICAgICAvLyBpbml0aWFsaXplLCB3aGljaCBjcmVhdGVzIGEgbmV3IGVtcHR5IGFycmF5IGZvciBlYWNoIGFycmF5QXR0ci5cbiAgICAgICAgdHJhbnNmb3JtcyA9IG5ld1RyYWNlLnRyYW5zZm9ybXM7XG4gICAgICAgIG5ld1RyYWNlLnRyYW5zZm9ybXMgPSBbXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgbmV3VHJhY2UudHJhbnNmb3Jtc1tqXSA9IExpYi5leHRlbmREZWVwTm9BcnJheXMoe30sIHRyYW5zZm9ybXNbal0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBlbXB0eSBhcnJheXMgZm9yIHRoZSBhcnJheUF0dHJzLCB0byBiZSBzcGxpdCBpbiB0aGUgbmV4dCBzdGVwXG4gICAgICAgIGZvcihqID0gMDsgaiA8IGFycmF5QXR0cnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdUcmFjZSwgYXJyYXlBdHRyc1tqXSkuc2V0KFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZvciBlYWNoIGFycmF5IGF0dHJpYnV0ZSBpbmNsdWRpbmcgdGhvc2UgbmVzdGVkIGluc2lkZSB0aGlzIGFuZCBvdGhlclxuICAgIC8vIHRyYW5zZm9ybXMgKHNtYWxsIG5vdGUgdGhhdCB3ZSB0ZWNobmljYWxseSBvbmx5IG5lZWQgdG8gZG8gdGhpcyBmb3JcbiAgICAvLyB0cmFuc2Zvcm1zIHRoYXQgaGF2ZSBub3QgeWV0IGJlZW4gYXBwbGllZCk6XG4gICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlBdHRycy5sZW5ndGg7IGsrKykge1xuICAgICAgICBhdHRyID0gYXJyYXlBdHRyc1trXTtcblxuICAgICAgICAvLyBDYWNoZSBhbGwgdGhlIGFycmF5cyB0byB3aGljaCB3ZSdsbCBwdXNoOlxuICAgICAgICBmb3IoaiA9IDAsIGFycmF5TG9va3VwID0gW107IGogPCBncm91cE5hbWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBhcnJheUxvb2t1cFtqXSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdEYXRhW2pdLCBhdHRyKS5nZXQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgaW5wdXQgZGF0YTpcbiAgICAgICAgc3JjQXJyYXkgPSBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGF0dHIpLmdldCgpO1xuXG4gICAgICAgIC8vIFNlbmQgZWFjaCBkYXRhIHBvaW50IHRvIHRoZSBhcHByb3ByaWF0ZSBleHBhbmRlZCB0cmFjZTpcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgIC8vIE1hcCBncm91cCBkYXRhIC0tPiB0cmFjZSBpbmRleCAtLT4gYXJyYXkgYW5kIHB1c2ggZGF0YSBvbnRvIGl0XG4gICAgICAgICAgICBhcnJheUxvb2t1cFtpbmRleExvb2t1cFtncm91cHNbal1dXS5wdXNoKHNyY0FycmF5W2pdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihqID0gMDsgaiA8IGxlbjsgaisrKSB7XG4gICAgICAgIG5ld1RyYWNlID0gbmV3RGF0YVtpbmRleExvb2t1cFtncm91cHNbal1dXTtcblxuICAgICAgICB2YXIgaW5kZXhUb1BvaW50cyA9IG5ld1RyYWNlLnRyYW5zZm9ybXNbdHJhbnNmb3JtSW5kZXhdLl9pbmRleFRvUG9pbnRzO1xuICAgICAgICBpbmRleFRvUG9pbnRzW2luZGV4Q250c1tncm91cHNbal1dXSA9IG9yaWdpbmFsUG9pbnRzQWNjZXNzb3Ioaik7XG4gICAgICAgIGluZGV4Q250c1tncm91cHNbal1dKys7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZ3JvdXBOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBncm91cE5hbWUgPSBncm91cE5hbWVzW2ldO1xuICAgICAgICBuZXdUcmFjZSA9IG5ld0RhdGFbaV07XG5cbiAgICAgICAgUGxvdHMuY2xlYXJFeHBhbmRlZFRyYWNlRGVmYXVsdENvbG9ycyhuZXdUcmFjZSk7XG5cbiAgICAgICAgLy8gdGhlcmUncyBubyBuZWVkIHRvIGNvZXJjZSBzdHlsZUxvb2t1cFtncm91cE5hbWVdIGhlcmVcbiAgICAgICAgLy8gYXMgYW5vdGhlciByb3VuZCBvZiBzdXBwbHlEZWZhdWx0cyBpcyBkb25lIG9uIHRoZSB0cmFuc2Zvcm1lZCB0cmFjZXNcbiAgICAgICAgbmV3VHJhY2UgPSBMaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKG5ld1RyYWNlLCBzdHlsZUxvb2t1cFtncm91cE5hbWVdIHx8IHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3RGF0YTtcbn1cblxuZnVuY3Rpb24gc3R5bGVVcGRhdGVyKGdyb3VwTmFtZSwgdHJhbnNmb3JtSW5kZXgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odHJhY2UsIGF0dHIsIHZhbHVlKSB7XG4gICAgICAgIExpYi5rZXllZENvbnRhaW5lcihcbiAgICAgICAgICAgIHRyYWNlLFxuICAgICAgICAgICAgJ3RyYW5zZm9ybXNbJyArIHRyYW5zZm9ybUluZGV4ICsgJ10uc3R5bGVzJyxcbiAgICAgICAgICAgICd0YXJnZXQnLFxuICAgICAgICAgICAgJ3ZhbHVlLicgKyBhdHRyXG4gICAgICAgICkuc2V0KFN0cmluZyhncm91cE5hbWUpLCB2YWx1ZSk7XG4gICAgfTtcbn1cbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5wb2ludHNBY2Nlc3NvckZ1bmN0aW9uID0gZnVuY3Rpb24odHJhbnNmb3Jtcywgb3B0cykge1xuICAgIHZhciB0cjtcbiAgICB2YXIgcHJldkluZGV4VG9Qb2ludHM7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHIgPSB0cmFuc2Zvcm1zW2ldO1xuICAgICAgICBpZih0ciA9PT0gb3B0cykgYnJlYWs7XG4gICAgICAgIGlmKCF0ci5faW5kZXhUb1BvaW50cyB8fCB0ci5lbmFibGVkID09PSBmYWxzZSkgY29udGludWU7XG4gICAgICAgIHByZXZJbmRleFRvUG9pbnRzID0gdHIuX2luZGV4VG9Qb2ludHM7XG4gICAgfVxuICAgIHZhciBvcmlnaW5hbFBvaW50c0FjY2Vzc29yID0gcHJldkluZGV4VG9Qb2ludHMgP1xuICAgICAgICBmdW5jdGlvbihpKSB7cmV0dXJuIHByZXZJbmRleFRvUG9pbnRzW2ldO30gOlxuICAgICAgICBmdW5jdGlvbihpKSB7cmV0dXJuIFtpXTt9O1xuICAgIHJldHVybiBvcmlnaW5hbFBvaW50c0FjY2Vzc29yO1xufTtcbiIsIi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE4LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IHJlcXVpcmUoJy4uL2xpYicpO1xudmFyIEF4ZXMgPSByZXF1aXJlKCcuLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIHBvaW50c0FjY2Vzc29yRnVuY3Rpb24gPSByZXF1aXJlKCcuL2hlbHBlcnMnKS5wb2ludHNBY2Nlc3NvckZ1bmN0aW9uO1xuXG5leHBvcnRzLm1vZHVsZVR5cGUgPSAndHJhbnNmb3JtJztcblxuZXhwb3J0cy5uYW1lID0gJ3NvcnQnO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgZW5hYmxlZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRhcmdldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiAneCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FzY2VuZGluZycsICdkZXNjZW5kaW5nJ10sXG4gICAgICAgIGRmbHQ6ICdhc2NlbmRpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHBvcnRzLnN1cHBseURlZmF1bHRzID0gZnVuY3Rpb24odHJhbnNmb3JtSW4pIHtcbiAgICB2YXIgdHJhbnNmb3JtT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFuc2Zvcm1JbiwgdHJhbnNmb3JtT3V0LCBleHBvcnRzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBlbmFibGVkID0gY29lcmNlKCdlbmFibGVkJyk7XG5cbiAgICBpZihlbmFibGVkKSB7XG4gICAgICAgIGNvZXJjZSgndGFyZ2V0Jyk7XG4gICAgICAgIGNvZXJjZSgnb3JkZXInKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtT3V0O1xufTtcblxuZXhwb3J0cy5jYWxjVHJhbnNmb3JtID0gZnVuY3Rpb24oZ2QsIHRyYWNlLCBvcHRzKSB7XG4gICAgaWYoIW9wdHMuZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgdmFyIHRhcmdldEFycmF5ID0gTGliLmdldFRhcmdldEFycmF5KHRyYWNlLCBvcHRzKTtcbiAgICBpZighdGFyZ2V0QXJyYXkpIHJldHVybjtcblxuICAgIHZhciB0YXJnZXQgPSBvcHRzLnRhcmdldDtcblxuICAgIHZhciBsZW4gPSB0YXJnZXRBcnJheS5sZW5ndGg7XG4gICAgaWYodHJhY2UuX2xlbmd0aCkgbGVuID0gTWF0aC5taW4obGVuLCB0cmFjZS5fbGVuZ3RoKTtcblxuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG4gICAgdmFyIGQyYyA9IEF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jKGdkLCB0cmFjZSwgdGFyZ2V0LCB0YXJnZXRBcnJheSk7XG4gICAgdmFyIGluZGljZXMgPSBnZXRJbmRpY2VzKG9wdHMsIHRhcmdldEFycmF5LCBkMmMsIGxlbik7XG4gICAgdmFyIG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IgPSBwb2ludHNBY2Nlc3NvckZ1bmN0aW9uKHRyYWNlLnRyYW5zZm9ybXMsIG9wdHMpO1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0ge307XG4gICAgdmFyIGksIGo7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBhcnJheUF0dHJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBucCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXJyYXlBdHRyc1tpXSk7XG4gICAgICAgIHZhciBhcnJheU9sZCA9IG5wLmdldCgpO1xuICAgICAgICB2YXIgYXJyYXlOZXcgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgYXJyYXlOZXdbal0gPSBhcnJheU9sZFtpbmRpY2VzW2pdXTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5wLnNldChhcnJheU5ldyk7XG4gICAgfVxuXG4gICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgaW5kZXhUb1BvaW50c1tqXSA9IG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IoaW5kaWNlc1tqXSk7XG4gICAgfVxuXG4gICAgb3B0cy5faW5kZXhUb1BvaW50cyA9IGluZGV4VG9Qb2ludHM7XG4gICAgdHJhY2UuX2xlbmd0aCA9IGxlbjtcbn07XG5cbmZ1bmN0aW9uIGdldEluZGljZXMob3B0cywgdGFyZ2V0QXJyYXksIGQyYywgbGVuKSB7XG4gICAgdmFyIHNvcnRlZEFycmF5ID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIGluZGljZXMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICB2YXIgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHNvcnRlZEFycmF5W2ldID0ge3Y6IHRhcmdldEFycmF5W2ldLCBpOiBpfTtcbiAgICB9XG5cbiAgICBzb3J0ZWRBcnJheS5zb3J0KGdldFNvcnRGdW5jKG9wdHMsIGQyYykpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaW5kaWNlc1tpXSA9IHNvcnRlZEFycmF5W2ldLmk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGljZXM7XG59XG5cbmZ1bmN0aW9uIGdldFNvcnRGdW5jKG9wdHMsIGQyYykge1xuICAgIHN3aXRjaChvcHRzLm9yZGVyKSB7XG4gICAgICAgIGNhc2UgJ2FzY2VuZGluZyc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gZDJjKGEudikgLSBkMmMoYi52KTsgfTtcbiAgICAgICAgY2FzZSAnZGVzY2VuZGluZyc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gZDJjKGIudikgLSBkMmMoYS52KTsgfTtcbiAgICB9XG59XG4iLCIvKlxuICogc3RyaWN0LWQzOiB3cmFwIHNlbGVjdGlvbi5zdHlsZSB0byBwcm9oaWJpdCBzcGVjaWZpYyBpbmNvcnJlY3Qgc3R5bGUgdmFsdWVzXG4gKiB0aGF0IGFyZSBrbm93biB0byBjYXVzZSBwcm9ibGVtcyBpbiBJRSAoYXQgbGVhc3QgSUU5KVxuICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IHJlcXVpcmUoJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gcmVxdWlyZSgnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIHNlbFByb3RvID0gZDMuc2VsZWN0aW9uLnByb3RvdHlwZTtcbnZhciBvcmlnaW5hbFNlbEF0dHIgPSBzZWxQcm90by5hdHRyO1xudmFyIG9yaWdpbmFsU2VsU3R5bGUgPSBzZWxQcm90by5zdHlsZTtcblxuc2VsUHJvdG8uYXR0ciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzZWwgPSB0aGlzO1xuICAgIHZhciBvYmogPSBhcmd1bWVudHNbMF07XG5cbiAgICBpZihzZWwuc2l6ZSgpKSB7XG4gICAgICAgIGlmKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjaGVja0F0dHJWYWwoc2VsLCBvYmosIGFyZ3VtZW50c1sxXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7IGNoZWNrQXR0clZhbChzZWwsIGtleSwgb2JqW2tleV0pOyB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvcmlnaW5hbFNlbEF0dHIuYXBwbHkoc2VsLCBhcmd1bWVudHMpO1xufTtcblxuc2VsUHJvdG8uc3R5bGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2VsID0gdGhpcztcbiAgICB2YXIgb2JqID0gYXJndW1lbnRzWzBdO1xuXG4gICAgaWYoc2VsLnNpemUoKSkge1xuICAgICAgICBpZih0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSAmJiAhZDMuZXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2QzIHNlbGVjdGlvbi5zdHlsZSBjYWxsZWQgYXMgZ2V0dGVyOiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ2Rpc2FsbG93ZWQgb3V0c2lkZSBldmVudCBoYW5kbGVycyBhcyBpdCBjYW4gZmFpbCBmb3IgJyArXG4gICAgICAgICAgICAgICAgICAgICd1bmF0dGFjaGVkIGVsZW1lbnRzLiBVc2Ugbm9kZS5zdHlsZS5hdHRyaWJ1dGUgaW5zdGVhZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrU3R5bGVWYWwoc2VsLCBvYmosIGFyZ3VtZW50c1sxXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7IGNoZWNrU3R5bGVWYWwoc2VsLCBrZXksIG9ialtrZXldKTsgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3JpZ2luYWxTZWxTdHlsZS5hcHBseShzZWwsIGFyZ3VtZW50cyk7XG59O1xuXG5mdW5jdGlvbiBjaGVja0F0dHJWYWwoc2VsLCBrZXksIHZhbCkge1xuICAgIC8vIHNldHRpbmcgdGhlIHRyYW5zZm9ybSBhdHRyaWJ1dGUgb24gYSA8Y2xpcFBhdGg+IGRvZXMgbm90XG4gICAgLy8gd29yayBpbiBDaHJvbWUsIElFIGFuZCBFZGdlXG4gICAgaWYoc2VsLm5vZGUoKS5ub2RlTmFtZSA9PT0gJ2NsaXBQYXRoJyAmJiBrZXkgPT09ICd0cmFuc2Zvcm0nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZDMgc2VsZWN0aW9uLmF0dHIgY2FsbGVkIHdpdGgga2V5IFxcJ3RyYW5zZm9ybVxcJyBvbiBhIGNsaXBQYXRoIG5vZGUnKTtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgbm8gZG91YmxlLW5lZ2F0aXZlIHN0cmluZyBnZXQgaW50byB0aGUgRE9NLFxuICAgIC8vIHRoZWlyIGhhbmRsaW5nIGRpZmZlcnMgZnJvbSBicm93c2VycyB0byBicm93c2Vyc1xuICAgIGlmKC8tLS8udGVzdCh2YWwpICYmIGlzTnVtZXJpYyh2YWwuc3BsaXQoJy0tJylbMV0uY2hhckF0KDApKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2QzIHNlbGVjdGlvbi5hdHRyIGNhbGxlZCB3aXRoIHZhbHVlICcgKyB2YWwgKyAnIHdoaWNoIGluY2x1ZGVzIGEgZG91YmxlIG5lZ2F0aXZlJyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjaGVja1N0eWxlVmFsKHNlbCwga2V5LCB2YWwpIHtcbiAgICBpZih0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgICAgICAvLyBpbiBjYXNlIG9mIG11bHRpcGFydCBzdHlsZXMgKHN0cm9rZS1kYXNoYXJyYXksIG1hcmdpbnMsIGV0YylcbiAgICAgICAgLy8gdGVzdCBlYWNoIHBhcnQgc2VwYXJhdGVseVxuICAgICAgICB2YWwuc3BsaXQoL1ssIF0vZykuZm9yRWFjaChmdW5jdGlvbih2YWxQYXJ0KSB7XG4gICAgICAgICAgICB2YXIgcHhTcGxpdCA9IHZhbFBhcnQubGVuZ3RoIC0gMjtcbiAgICAgICAgICAgIGlmKHZhbFBhcnQuc3Vic3RyKHB4U3BsaXQpID09PSAncHgnICYmICFpc051bWVyaWModmFsUGFydC5zdWJzdHIoMCwgcHhTcGxpdCkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkMyBzZWxlY3Rpb24uc3R5bGUgY2FsbGVkIHdpdGggdmFsdWU6ICcgKyB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBNaWNyb3NvZnQgYnJvd3NlcnMgaW5jbC4gXCJFZGdlXCIgZG9uJ3Qgc3VwcG9ydCBDU1MgdHJhbnNmb3JtIG9uIFNWRyBlbGVtZW50c1xuICAgIGlmKGtleSA9PT0gJ3RyYW5zZm9ybScgJiYgc2VsLm5vZGUoKSBpbnN0YW5jZW9mIFNWR0VsZW1lbnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkMyBzZWxlY3Rpb24uc3R5bGUgY2FsbGVkIG9uIGFuIFNWRyBlbGVtZW50IHdpdGgga2V5OiAnICsga2V5KTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZDM7XG4iXX0= diff --git a/dash_core_components/plotly-18863-45646037.js b/dash_core_components/plotly-18863-45646037.js new file mode 100644 index 000000000..e4044b47c --- /dev/null +++ b/dash_core_components/plotly-18863-45646037.js @@ -0,0 +1 @@ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Plotly=t()}}(function(){return function(){return function t(e,r,n){function i(o,s){if(!r[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(a)return a(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var u=r[o]={exports:{}};e[o][0].call(u.exports,function(t){return i(e[o][1][t]||t)},u,u.exports,t,e,r,n)}return r[o].exports}for(var a="function"==typeof require&&require,o=0;oplotly-logomark"}}},{}],3:[function(t,e,r){"use strict";e.exports=t("../src/transforms/aggregate")},{"../src/transforms/aggregate":1155}],4:[function(t,e,r){"use strict";e.exports=t("../src/traces/bar")},{"../src/traces/bar":843}],5:[function(t,e,r){"use strict";e.exports=t("../src/traces/barpolar")},{"../src/traces/barpolar":855}],6:[function(t,e,r){"use strict";e.exports=t("../src/traces/box")},{"../src/traces/box":865}],7:[function(t,e,r){"use strict";e.exports=t("../src/components/calendars")},{"../src/components/calendars":568}],8:[function(t,e,r){"use strict";e.exports=t("../src/traces/candlestick")},{"../src/traces/candlestick":874}],9:[function(t,e,r){"use strict";e.exports=t("../src/traces/carpet")},{"../src/traces/carpet":893}],10:[function(t,e,r){"use strict";e.exports=t("../src/traces/choropleth")},{"../src/traces/choropleth":907}],11:[function(t,e,r){"use strict";e.exports=t("../src/traces/cone")},{"../src/traces/cone":915}],12:[function(t,e,r){"use strict";e.exports=t("../src/traces/contour")},{"../src/traces/contour":930}],13:[function(t,e,r){"use strict";e.exports=t("../src/traces/contourcarpet")},{"../src/traces/contourcarpet":941}],14:[function(t,e,r){"use strict";e.exports=t("../src/core")},{"../src/core":675}],15:[function(t,e,r){"use strict";e.exports=t("../src/transforms/filter")},{"../src/transforms/filter":1156}],16:[function(t,e,r){"use strict";e.exports=t("../src/transforms/groupby")},{"../src/transforms/groupby":1157}],17:[function(t,e,r){"use strict";e.exports=t("../src/traces/heatmap")},{"../src/traces/heatmap":953}],18:[function(t,e,r){"use strict";e.exports=t("../src/traces/heatmapgl")},{"../src/traces/heatmapgl":963}],19:[function(t,e,r){"use strict";e.exports=t("../src/traces/histogram")},{"../src/traces/histogram":974}],20:[function(t,e,r){"use strict";e.exports=t("../src/traces/histogram2d")},{"../src/traces/histogram2d":981}],21:[function(t,e,r){"use strict";e.exports=t("../src/traces/histogram2dcontour")},{"../src/traces/histogram2dcontour":985}],22:[function(t,e,r){"use strict";var n=t("./core");n.register([t("./bar"),t("./box"),t("./heatmap"),t("./histogram"),t("./histogram2d"),t("./histogram2dcontour"),t("./pie"),t("./contour"),t("./scatterternary"),t("./violin"),t("./scatter3d"),t("./surface"),t("./mesh3d"),t("./cone"),t("./streamtube"),t("./scattergeo"),t("./choropleth"),t("./scattergl"),t("./splom"),t("./pointcloud"),t("./heatmapgl"),t("./parcoords"),t("./parcats"),t("./scattermapbox"),t("./sankey"),t("./table"),t("./carpet"),t("./scattercarpet"),t("./contourcarpet"),t("./ohlc"),t("./candlestick"),t("./scatterpolar"),t("./scatterpolargl"),t("./barpolar")]),n.register([t("./aggregate"),t("./filter"),t("./groupby"),t("./sort")]),n.register([t("./calendars")]),e.exports=n},{"./aggregate":3,"./bar":4,"./barpolar":5,"./box":6,"./calendars":7,"./candlestick":8,"./carpet":9,"./choropleth":10,"./cone":11,"./contour":12,"./contourcarpet":13,"./core":14,"./filter":15,"./groupby":16,"./heatmap":17,"./heatmapgl":18,"./histogram":19,"./histogram2d":20,"./histogram2dcontour":21,"./mesh3d":23,"./ohlc":24,"./parcats":25,"./parcoords":26,"./pie":27,"./pointcloud":28,"./sankey":29,"./scatter3d":30,"./scattercarpet":31,"./scattergeo":32,"./scattergl":33,"./scattermapbox":34,"./scatterpolar":35,"./scatterpolargl":36,"./scatterternary":37,"./sort":38,"./splom":39,"./streamtube":40,"./surface":41,"./table":42,"./violin":43}],23:[function(t,e,r){"use strict";e.exports=t("../src/traces/mesh3d")},{"../src/traces/mesh3d":990}],24:[function(t,e,r){"use strict";e.exports=t("../src/traces/ohlc")},{"../src/traces/ohlc":995}],25:[function(t,e,r){"use strict";e.exports=t("../src/traces/parcats")},{"../src/traces/parcats":1004}],26:[function(t,e,r){"use strict";e.exports=t("../src/traces/parcoords")},{"../src/traces/parcoords":1013}],27:[function(t,e,r){"use strict";e.exports=t("../src/traces/pie")},{"../src/traces/pie":1024}],28:[function(t,e,r){"use strict";e.exports=t("../src/traces/pointcloud")},{"../src/traces/pointcloud":1033}],29:[function(t,e,r){"use strict";e.exports=t("../src/traces/sankey")},{"../src/traces/sankey":1039}],30:[function(t,e,r){"use strict";e.exports=t("../src/traces/scatter3d")},{"../src/traces/scatter3d":1075}],31:[function(t,e,r){"use strict";e.exports=t("../src/traces/scattercarpet")},{"../src/traces/scattercarpet":1081}],32:[function(t,e,r){"use strict";e.exports=t("../src/traces/scattergeo")},{"../src/traces/scattergeo":1088}],33:[function(t,e,r){"use strict";e.exports=t("../src/traces/scattergl")},{"../src/traces/scattergl":1096}],34:[function(t,e,r){"use strict";e.exports=t("../src/traces/scattermapbox")},{"../src/traces/scattermapbox":1102}],35:[function(t,e,r){"use strict";e.exports=t("../src/traces/scatterpolar")},{"../src/traces/scatterpolar":1109}],36:[function(t,e,r){"use strict";e.exports=t("../src/traces/scatterpolargl")},{"../src/traces/scatterpolargl":1113}],37:[function(t,e,r){"use strict";e.exports=t("../src/traces/scatterternary")},{"../src/traces/scatterternary":1119}],38:[function(t,e,r){"use strict";e.exports=t("../src/transforms/sort")},{"../src/transforms/sort":1159}],39:[function(t,e,r){"use strict";e.exports=t("../src/traces/splom")},{"../src/traces/splom":1124}],40:[function(t,e,r){"use strict";e.exports=t("../src/traces/streamtube")},{"../src/traces/streamtube":1129}],41:[function(t,e,r){"use strict";e.exports=t("../src/traces/surface")},{"../src/traces/surface":1134}],42:[function(t,e,r){"use strict";e.exports=t("../src/traces/table")},{"../src/traces/table":1142}],43:[function(t,e,r){"use strict";e.exports=t("../src/traces/violin")},{"../src/traces/violin":1150}],44:[function(t,e,r){"use strict";e.exports=function(t,e){t=t||document.body,e=e||{};var r=[.01,1/0];"distanceLimits"in e&&(r[0]=e.distanceLimits[0],r[1]=e.distanceLimits[1]);"zoomMin"in e&&(r[0]=e.zoomMin);"zoomMax"in e&&(r[1]=e.zoomMax);var c=i({center:e.center||[0,0,0],up:e.up||[0,1,0],eye:e.eye||[0,0,10],mode:e.mode||"orbit",distanceLimits:r}),u=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],f=0,h=t.clientWidth,p=t.clientHeight,d={view:c,element:t,delay:e.delay||16,rotateSpeed:e.rotateSpeed||1,zoomSpeed:e.zoomSpeed||1,translateSpeed:e.translateSpeed||1,flipX:!!e.flipX,flipY:!!e.flipY,modes:c.modes,tick:function(){var e=n(),r=this.delay;c.idle(e-r),c.flush(e-(100+2*r));var i=e-2*r;c.recalcMatrix(i);for(var a=!0,o=c.computedMatrix,s=0;s<16;++s)a=a&&u[s]===o[s],u[s]=o[s];var l=t.clientWidth===h&&t.clientHeight===p;return h=t.clientWidth,p=t.clientHeight,a?!l:(f=Math.exp(c.computedRadius[0]),!0)},lookAt:function(t,e,r){c.lookAt(c.lastT(),t,e,r)},rotate:function(t,e,r){c.rotate(c.lastT(),t,e,r)},pan:function(t,e,r){c.pan(c.lastT(),t,e,r)},translate:function(t,e,r){c.translate(c.lastT(),t,e,r)}};Object.defineProperties(d,{matrix:{get:function(){return c.computedMatrix},set:function(t){return c.setMatrix(c.lastT(),t),c.computedMatrix},enumerable:!0},mode:{get:function(){return c.getMode()},set:function(t){return c.setMode(t),c.getMode()},enumerable:!0},center:{get:function(){return c.computedCenter},set:function(t){return c.lookAt(c.lastT(),t),c.computedCenter},enumerable:!0},eye:{get:function(){return c.computedEye},set:function(t){return c.lookAt(c.lastT(),null,t),c.computedEye},enumerable:!0},up:{get:function(){return c.computedUp},set:function(t){return c.lookAt(c.lastT(),null,null,t),c.computedUp},enumerable:!0},distance:{get:function(){return f},set:function(t){return c.setDistance(c.lastT(),t),t},enumerable:!0},distanceLimits:{get:function(){return c.getDistanceLimits(r)},set:function(t){return c.setDistanceLimits(t),t},enumerable:!0}}),t.addEventListener("contextmenu",function(t){return t.preventDefault(),!1});var m=0,g=0,v={shift:!1,control:!1,alt:!1,meta:!1};function y(e,r,i,a){var o=1/t.clientHeight,s=o*(r-m),l=o*(i-g),u=d.flipX?1:-1,h=d.flipY?1:-1,p=Math.PI*d.rotateSpeed,y=n();if(1&e)a.shift?c.rotate(y,0,0,-s*p):c.rotate(y,u*p*s,-h*p*l,0);else if(2&e)c.pan(y,-d.translateSpeed*s*f,d.translateSpeed*l*f,0);else if(4&e){var x=d.zoomSpeed*l/window.innerHeight*(y-c.lastT())*50;c.pan(y,0,0,f*(Math.exp(x)-1))}m=r,g=i,v=a}return a(t,y),t.addEventListener("touchstart",function(e){var r=s(e.changedTouches[0],t);y(0,r[0],r[1],v),y(1,r[0],r[1],v),e.preventDefault()},!!l&&{passive:!1}),t.addEventListener("touchmove",function(e){var r=s(e.changedTouches[0],t);y(1,r[0],r[1],v),e.preventDefault()},!!l&&{passive:!1}),t.addEventListener("touchend",function(e){s(e.changedTouches[0],t),y(0,m,g,v),e.preventDefault()},!!l&&{passive:!1}),o(t,function(t,e,r){var i=d.flipX?1:-1,a=d.flipY?1:-1,o=n();if(Math.abs(t)>Math.abs(e))c.rotate(o,0,0,-t*i*Math.PI*d.rotateSpeed/window.innerWidth);else{var s=d.zoomSpeed*a*e/window.innerHeight*(o-c.lastT())/100;c.pan(o,0,0,f*(Math.exp(s)-1))}},!0),d};var n=t("right-now"),i=t("3d-view"),a=t("mouse-change"),o=t("mouse-wheel"),s=t("mouse-event-offset"),l=t("has-passive-events")},{"3d-view":45,"has-passive-events":394,"mouse-change":418,"mouse-event-offset":419,"mouse-wheel":421,"right-now":480}],45:[function(t,e,r){"use strict";e.exports=function(t){var e=(t=t||{}).eye||[0,0,1],r=t.center||[0,0,0],s=t.up||[0,1,0],l=t.distanceLimits||[0,1/0],c=t.mode||"turntable",u=n(),f=i(),h=a();return u.setDistanceLimits(l[0],l[1]),u.lookAt(0,e,r,s),f.setDistanceLimits(l[0],l[1]),f.lookAt(0,e,r,s),h.setDistanceLimits(l[0],l[1]),h.lookAt(0,e,r,s),new o({turntable:u,orbit:f,matrix:h},c)};var n=t("turntable-camera-controller"),i=t("orbit-camera-controller"),a=t("matrix-camera-controller");function o(t,e){this._controllerNames=Object.keys(t),this._controllerList=this._controllerNames.map(function(e){return t[e]}),this._mode=e,this._active=t[e],this._active||(this._mode="turntable",this._active=t.turntable),this.modes=this._controllerNames,this.computedMatrix=this._active.computedMatrix,this.computedEye=this._active.computedEye,this.computedUp=this._active.computedUp,this.computedCenter=this._active.computedCenter,this.computedRadius=this._active.computedRadius}var s=o.prototype;[["flush",1],["idle",1],["lookAt",4],["rotate",4],["pan",4],["translate",4],["setMatrix",2],["setDistanceLimits",2],["setDistance",2]].forEach(function(t){for(var e=t[0],r=[],n=0;nr&&(a=r);var i=e.min(n,function(t){return(o[1]-(t.length-1)*a)/e.sum(t,h)});n.forEach(function(t){t.forEach(function(t,e){t.y=e,t.dy=t.value*i})}),l.forEach(function(t){t.dy=t.value*i})})(),d();for(var i=1;t>0;--t)p(i*=.99),d(),u(i),d();function u(t){function r(t){return f(t.source)*t.value}n.forEach(function(n){n.forEach(function(n){if(n.targetLinks.length){var i=e.sum(n.targetLinks,r)/e.sum(n.targetLinks,h);n.y+=(i-f(n))*t}})})}function p(t){function r(t){return f(t.target)*t.value}n.slice().reverse().forEach(function(n){n.forEach(function(n){if(n.sourceLinks.length){var i=e.sum(n.sourceLinks,r)/e.sum(n.sourceLinks,h);n.y+=(i-f(n))*t}})})}function d(){n.forEach(function(t){var e,r,n,i=0,s=t.length;for(t.sort(m),n=0;n0&&(e.y+=r),i=e.y+e.dy+a;if((r=i-a-o[1])>0)for(i=e.y-=r,n=s-2;n>=0;--n)e=t[n],(r=e.y+e.dy+a-i)>0&&(e.y-=r),i=e.y})}function m(t,e){return t.y-e.y}}(n),u(),t},t.relayout=function(){return u(),t},t.link=function(){var t=.5;function e(e){var r=e.source.x+e.source.dx,i=e.target.x,a=n.interpolateNumber(r,i),o=a(t),s=a(1-t),l=e.source.y+e.sy,c=l+e.dy,u=e.target.y+e.ty,f=u+e.dy;return"M"+r+","+l+"C"+o+","+l+" "+s+","+u+" "+i+","+u+"L"+i+","+f+"C"+s+","+f+" "+o+","+c+" "+r+","+c+"Z"}return e.curvature=function(r){return arguments.length?(t=+r,e):t},e},t},Object.defineProperty(t,"__esModule",{value:!0})},"object"==typeof r&&"undefined"!=typeof e?i(r,t("d3-array"),t("d3-collection"),t("d3-interpolate")):i(n.d3=n.d3||{},n.d3,n.d3,n.d3)},{"d3-array":140,"d3-collection":141,"d3-interpolate":145}],47:[function(t,e,r){"use strict";var n="undefined"==typeof WeakMap?t("weak-map"):WeakMap,i=t("gl-buffer"),a=t("gl-vao"),o=new n;e.exports=function(t){var e=o.get(t),r=e&&(e._triangleBuffer.handle||e._triangleBuffer.buffer);if(!r||!t.isBuffer(r)){var n=i(t,new Float32Array([-1,-1,-1,4,4,-1]));(e=a(t,[{buffer:n,type:t.FLOAT,size:2}]))._triangleBuffer=n,o.set(t,e)}e.bind(),t.drawArrays(t.TRIANGLES,0,3),e.unbind()}},{"gl-buffer":230,"gl-vao":310,"weak-map":529}],48:[function(t,e,r){e.exports=function(t){var e=0,r=0,n=0,i=0;return t.map(function(t){var a=(t=t.slice())[0],o=a.toUpperCase();if(a!=o)switch(t[0]=o,a){case"a":t[6]+=n,t[7]+=i;break;case"v":t[1]+=i;break;case"h":t[1]+=n;break;default:for(var s=1;si&&(i=t[o]),t[o]=0;c--)if(u[c]!==f[c])return!1;for(c=u.length-1;c>=0;c--)if(l=u[c],!y(t[l],e[l],r,n))return!1;return!0}(t,e,r,o))}return r?t===e:t==e}function x(t){return"[object Arguments]"==Object.prototype.toString.call(t)}function b(t,e){if(!t||!e)return!1;if("[object RegExp]"==Object.prototype.toString.call(e))return e.test(t);try{if(t instanceof e)return!0}catch(t){}return!Error.isPrototypeOf(e)&&!0===e.call({},t)}function _(t,e,r,n){var i;if("function"!=typeof e)throw new TypeError('"block" argument must be a function');"string"==typeof r&&(n=r,r=null),i=function(t){var e;try{t()}catch(t){e=t}return e}(e),n=(r&&r.name?" ("+r.name+").":".")+(n?" "+n:"."),t&&!i&&g(i,r,"Missing expected exception"+n);var o="string"==typeof n,s=!t&&i&&!r;if((!t&&a.isError(i)&&o&&b(i,r)||s)&&g(i,r,"Got unwanted exception"+n),t&&i&&r&&!b(i,r)||!t&&i)throw i}f.AssertionError=function(t){var e;this.name="AssertionError",this.actual=t.actual,this.expected=t.expected,this.operator=t.operator,t.message?(this.message=t.message,this.generatedMessage=!1):(this.message=d(m((e=this).actual),128)+" "+e.operator+" "+d(m(e.expected),128),this.generatedMessage=!0);var r=t.stackStartFunction||g;if(Error.captureStackTrace)Error.captureStackTrace(this,r);else{var n=new Error;if(n.stack){var i=n.stack,a=p(r),o=i.indexOf("\n"+a);if(o>=0){var s=i.indexOf("\n",o+1);i=i.substring(s+1)}this.stack=i}}},a.inherits(f.AssertionError,Error),f.fail=g,f.ok=v,f.equal=function(t,e,r){t!=e&&g(t,e,r,"==",f.equal)},f.notEqual=function(t,e,r){t==e&&g(t,e,r,"!=",f.notEqual)},f.deepEqual=function(t,e,r){y(t,e,!1)||g(t,e,r,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(t,e,r){y(t,e,!0)||g(t,e,r,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(t,e,r){y(t,e,!1)&&g(t,e,r,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function t(e,r,n){y(e,r,!0)&&g(e,r,n,"notDeepStrictEqual",t)},f.strictEqual=function(t,e,r){t!==e&&g(t,e,r,"===",f.strictEqual)},f.notStrictEqual=function(t,e,r){t===e&&g(t,e,r,"!==",f.notStrictEqual)},f.throws=function(t,e,r){_(!0,t,e,r)},f.doesNotThrow=function(t,e,r){_(!1,t,e,r)},f.ifError=function(t){if(t)throw t};var w=Object.keys||function(t){var e=[];for(var r in t)o.call(t,r)&&e.push(r);return e}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"util/":59}],57:[function(t,e,r){"function"==typeof Object.create?e.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}},{}],58:[function(t,e,r){e.exports=function(t){return t&&"object"==typeof t&&"function"==typeof t.copy&&"function"==typeof t.fill&&"function"==typeof t.readUInt8}},{}],59:[function(t,e,r){(function(e,n){var i=/%[sdj%]/g;r.format=function(t){if(!v(t)){for(var e=[],r=0;r=a)return t;switch(t){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(t){return"[Circular]"}default:return t}}),l=n[r];r=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),d(e)?n.showHidden=e:e&&r._extend(n,e),y(n.showHidden)&&(n.showHidden=!1),y(n.depth)&&(n.depth=2),y(n.colors)&&(n.colors=!1),y(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=l),u(n,t,n.depth)}function l(t,e){var r=s.styles[e];return r?"\x1b["+s.colors[r][0]+"m"+t+"\x1b["+s.colors[r][1]+"m":t}function c(t,e){return t}function u(t,e,n){if(t.customInspect&&e&&k(e.inspect)&&e.inspect!==r.inspect&&(!e.constructor||e.constructor.prototype!==e)){var i=e.inspect(n,t);return v(i)||(i=u(t,i,n)),i}var a=function(t,e){if(y(e))return t.stylize("undefined","undefined");if(v(e)){var r="'"+JSON.stringify(e).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return t.stylize(r,"string")}if(g(e))return t.stylize(""+e,"number");if(d(e))return t.stylize(""+e,"boolean");if(m(e))return t.stylize("null","null")}(t,e);if(a)return a;var o=Object.keys(e),s=function(t){var e={};return t.forEach(function(t,r){e[t]=!0}),e}(o);if(t.showHidden&&(o=Object.getOwnPropertyNames(e)),w(e)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return f(e);if(0===o.length){if(k(e)){var l=e.name?": "+e.name:"";return t.stylize("[Function"+l+"]","special")}if(x(e))return t.stylize(RegExp.prototype.toString.call(e),"regexp");if(_(e))return t.stylize(Date.prototype.toString.call(e),"date");if(w(e))return f(e)}var c,b="",M=!1,A=["{","}"];(p(e)&&(M=!0,A=["[","]"]),k(e))&&(b=" [Function"+(e.name?": "+e.name:"")+"]");return x(e)&&(b=" "+RegExp.prototype.toString.call(e)),_(e)&&(b=" "+Date.prototype.toUTCString.call(e)),w(e)&&(b=" "+f(e)),0!==o.length||M&&0!=e.length?n<0?x(e)?t.stylize(RegExp.prototype.toString.call(e),"regexp"):t.stylize("[Object]","special"):(t.seen.push(e),c=M?function(t,e,r,n,i){for(var a=[],o=0,s=e.length;o=0&&0,t+e.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return r[0]+(""===e?"":e+"\n ")+" "+t.join(",\n ")+" "+r[1];return r[0]+e+" "+t.join(", ")+" "+r[1]}(c,b,A)):A[0]+b+A[1]}function f(t){return"["+Error.prototype.toString.call(t)+"]"}function h(t,e,r,n,i,a){var o,s,l;if((l=Object.getOwnPropertyDescriptor(e,i)||{value:e[i]}).get?s=l.set?t.stylize("[Getter/Setter]","special"):t.stylize("[Getter]","special"):l.set&&(s=t.stylize("[Setter]","special")),S(n,i)||(o="["+i+"]"),s||(t.seen.indexOf(l.value)<0?(s=m(r)?u(t,l.value,null):u(t,l.value,r-1)).indexOf("\n")>-1&&(s=a?s.split("\n").map(function(t){return" "+t}).join("\n").substr(2):"\n"+s.split("\n").map(function(t){return" "+t}).join("\n")):s=t.stylize("[Circular]","special")),y(o)){if(a&&i.match(/^\d+$/))return s;(o=JSON.stringify(""+i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=t.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=t.stylize(o,"string"))}return o+": "+s}function p(t){return Array.isArray(t)}function d(t){return"boolean"==typeof t}function m(t){return null===t}function g(t){return"number"==typeof t}function v(t){return"string"==typeof t}function y(t){return void 0===t}function x(t){return b(t)&&"[object RegExp]"===M(t)}function b(t){return"object"==typeof t&&null!==t}function _(t){return b(t)&&"[object Date]"===M(t)}function w(t){return b(t)&&("[object Error]"===M(t)||t instanceof Error)}function k(t){return"function"==typeof t}function M(t){return Object.prototype.toString.call(t)}function A(t){return t<10?"0"+t.toString(10):t.toString(10)}r.debuglog=function(t){if(y(a)&&(a=e.env.NODE_DEBUG||""),t=t.toUpperCase(),!o[t])if(new RegExp("\\b"+t+"\\b","i").test(a)){var n=e.pid;o[t]=function(){var e=r.format.apply(r,arguments);console.error("%s %d: %s",t,n,e)}}else o[t]=function(){};return o[t]},r.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=p,r.isBoolean=d,r.isNull=m,r.isNullOrUndefined=function(t){return null==t},r.isNumber=g,r.isString=v,r.isSymbol=function(t){return"symbol"==typeof t},r.isUndefined=y,r.isRegExp=x,r.isObject=b,r.isDate=_,r.isError=w,r.isFunction=k,r.isPrimitive=function(t){return null===t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||"symbol"==typeof t||"undefined"==typeof t},r.isBuffer=t("./support/isBuffer");var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function S(t,e){return Object.prototype.hasOwnProperty.call(t,e)}r.log=function(){var t,e;console.log("%s - %s",(t=new Date,e=[A(t.getHours()),A(t.getMinutes()),A(t.getSeconds())].join(":"),[t.getDate(),T[t.getMonth()],e].join(" ")),r.format.apply(r,arguments))},r.inherits=t("inherits"),r._extend=function(t,e){if(!e||!b(e))return t;for(var r=Object.keys(e),n=r.length;n--;)t[r[n]]=e[r[n]];return t}}).call(this,t("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":58,_process:465,inherits:57}],60:[function(t,e,r){e.exports=function(t){return atob(t)}},{}],61:[function(t,e,r){"use strict";e.exports=function(t,e){for(var r=e.length,a=new Array(r+1),o=0;o0?n-4:n,f=0;f>16&255,s[l++]=e>>8&255,s[l++]=255&e;2===o&&(e=i[t.charCodeAt(f)]<<2|i[t.charCodeAt(f+1)]>>4,s[l++]=255&e);1===o&&(e=i[t.charCodeAt(f)]<<10|i[t.charCodeAt(f+1)]<<4|i[t.charCodeAt(f+2)]>>2,s[l++]=e>>8&255,s[l++]=255&e);return s},r.fromByteArray=function(t){for(var e,r=t.length,i=r%3,a=[],o=0,s=r-i;os?s:o+16383));1===i?(e=t[r-1],a.push(n[e>>2]+n[e<<4&63]+"==")):2===i&&(e=(t[r-2]<<8)+t[r-1],a.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return a.join("")};for(var n=[],i=[],a="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,l=o.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return-1===r&&(r=e),[r,r===e?0:4-r%4]}function u(t,e,r){for(var i,a,o=[],s=e;s>18&63]+n[a>>12&63]+n[a>>6&63]+n[63&a]);return o.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},{}],63:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]).add(e[0].mul(t[1])),t[1].mul(e[1]))}},{"./lib/rationalize":73}],64:[function(t,e,r){"use strict";e.exports=function(t,e){return t[0].mul(e[1]).cmp(e[0].mul(t[1]))}},{}],65:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]),t[1].mul(e[0]))}},{"./lib/rationalize":73}],66:[function(t,e,r){"use strict";var n=t("./is-rat"),i=t("./lib/is-bn"),a=t("./lib/num-to-bn"),o=t("./lib/str-to-bn"),s=t("./lib/rationalize"),l=t("./div");e.exports=function t(e,r){if(n(e))return r?l(e,t(r)):[e[0].clone(),e[1].clone()];var c=0;var u,f;if(i(e))u=e.clone();else if("string"==typeof e)u=o(e);else{if(0===e)return[a(0),a(1)];if(e===Math.floor(e))u=a(e);else{for(;e!==Math.floor(e);)e*=Math.pow(2,256),c-=256;u=a(e)}}if(n(r))u.mul(r[1]),f=r[0].clone();else if(i(r))f=r.clone();else if("string"==typeof r)f=o(r);else if(r)if(r===Math.floor(r))f=a(r);else{for(;r!==Math.floor(r);)r*=Math.pow(2,256),c+=256;f=a(r)}else f=a(1);c>0?u=u.ushln(c):c<0&&(f=f.ushln(-c));return s(u,f)}},{"./div":65,"./is-rat":67,"./lib/is-bn":71,"./lib/num-to-bn":72,"./lib/rationalize":73,"./lib/str-to-bn":74}],67:[function(t,e,r){"use strict";var n=t("./lib/is-bn");e.exports=function(t){return Array.isArray(t)&&2===t.length&&n(t[0])&&n(t[1])}},{"./lib/is-bn":71}],68:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return t.cmp(new n(0))}},{"bn.js":82}],69:[function(t,e,r){"use strict";var n=t("./bn-sign");e.exports=function(t){var e=t.length,r=t.words,i=0;if(1===e)i=r[0];else if(2===e)i=r[0]+67108864*r[1];else for(var a=0;a20)return 52;return r+32}},{"bit-twiddle":80,"double-bits":152}],71:[function(t,e,r){"use strict";t("bn.js");e.exports=function(t){return t&&"object"==typeof t&&Boolean(t.words)}},{"bn.js":82}],72:[function(t,e,r){"use strict";var n=t("bn.js"),i=t("double-bits");e.exports=function(t){var e=i.exponent(t);return e<52?new n(t):new n(t*Math.pow(2,52-e)).ushln(e-52)}},{"bn.js":82,"double-bits":152}],73:[function(t,e,r){"use strict";var n=t("./num-to-bn"),i=t("./bn-sign");e.exports=function(t,e){var r=i(t),a=i(e);if(0===r)return[n(0),n(1)];if(0===a)return[n(0),n(0)];a<0&&(t=t.neg(),e=e.neg());var o=t.gcd(e);if(o.cmpn(1))return[t.div(o),e.div(o)];return[t,e]}},{"./bn-sign":68,"./num-to-bn":72}],74:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return new n(t)}},{"bn.js":82}],75:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[0]),t[1].mul(e[1]))}},{"./lib/rationalize":73}],76:[function(t,e,r){"use strict";var n=t("./lib/bn-sign");e.exports=function(t){return n(t[0])*n(t[1])}},{"./lib/bn-sign":68}],77:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]).sub(t[1].mul(e[0])),t[1].mul(e[1]))}},{"./lib/rationalize":73}],78:[function(t,e,r){"use strict";var n=t("./lib/bn-to-num"),i=t("./lib/ctz");e.exports=function(t){var e=t[0],r=t[1];if(0===e.cmpn(0))return 0;var a=e.abs().divmod(r.abs()),o=a.div,s=n(o),l=a.mod,c=e.negative!==r.negative?-1:1;if(0===l.cmpn(0))return c*s;if(s){var u=i(s)+4,f=n(l.ushln(u).divRound(r));return c*(s+f*Math.pow(2,-u))}var h=r.bitLength()-l.bitLength()+53,f=n(l.ushln(h).divRound(r));return h<1023?c*f*Math.pow(2,-h):(f*=Math.pow(2,-1023),c*f*Math.pow(2,1023-h))}},{"./lib/bn-to-num":69,"./lib/ctz":70}],79:[function(t,e,r){"use strict";function n(t,e,r,n,i,a){var o=["function ",t,"(a,l,h,",n.join(","),"){",a?"":"var i=",r?"l-1":"h+1",";while(l<=h){var m=(l+h)>>>1,x=a",i?".get(m)":"[m]"];return a?e.indexOf("c")<0?o.push(";if(x===y){return m}else if(x<=y){"):o.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){"):o.push(";if(",e,"){i=m;"),r?o.push("l=m+1}else{h=m-1}"):o.push("h=m-1}else{l=m+1}"),o.push("}"),a?o.push("return -1};"):o.push("return i};"),o.join("")}function i(t,e,r,i){return new Function([n("A","x"+t+"y",e,["y"],!1,i),n("B","x"+t+"y",e,["y"],!0,i),n("P","c(x,y)"+t+"0",e,["y","c"],!1,i),n("Q","c(x,y)"+t+"0",e,["y","c"],!0,i),"function dispatchBsearch",r,"(a,y,c,l,h){if(a.shape){if(typeof(c)==='function'){return Q(a,(l===undefined)?0:l|0,(h===undefined)?a.shape[0]-1:h|0,y,c)}else{return B(a,(c===undefined)?0:c|0,(l===undefined)?a.shape[0]-1:l|0,y)}}else{if(typeof(c)==='function'){return P(a,(l===undefined)?0:l|0,(h===undefined)?a.length-1:h|0,y,c)}else{return A(a,(c===undefined)?0:c|0,(l===undefined)?a.length-1:l|0,y)}}}return dispatchBsearch",r].join(""))()}e.exports={ge:i(">=",!1,"GE"),gt:i(">",!1,"GT"),lt:i("<",!0,"LT"),le:i("<=",!0,"LE"),eq:i("-",!0,"EQ",!0)}},{}],80:[function(t,e,r){"use strict";function n(t){var e=32;return(t&=-t)&&e--,65535&t&&(e-=16),16711935&t&&(e-=8),252645135&t&&(e-=4),858993459&t&&(e-=2),1431655765&t&&(e-=1),e}r.INT_BITS=32,r.INT_MAX=2147483647,r.INT_MIN=-1<<31,r.sign=function(t){return(t>0)-(t<0)},r.abs=function(t){var e=t>>31;return(t^e)-e},r.min=function(t,e){return e^(t^e)&-(t65535)<<4,e|=r=((t>>>=e)>255)<<3,e|=r=((t>>>=r)>15)<<2,(e|=r=((t>>>=r)>3)<<1)|(t>>>=r)>>1},r.log10=function(t){return t>=1e9?9:t>=1e8?8:t>=1e7?7:t>=1e6?6:t>=1e5?5:t>=1e4?4:t>=1e3?3:t>=100?2:t>=10?1:0},r.popCount=function(t){return 16843009*((t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135)>>>24},r.countTrailingZeros=n,r.nextPow2=function(t){return t+=0===t,--t,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)+1},r.prevPow2=function(t){return t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)-(t>>>1)},r.parity=function(t){return t^=t>>>16,t^=t>>>8,t^=t>>>4,27030>>>(t&=15)&1};var i=new Array(256);!function(t){for(var e=0;e<256;++e){var r=e,n=e,i=7;for(r>>>=1;r;r>>>=1)n<<=1,n|=1&r,--i;t[e]=n<>>8&255]<<16|i[t>>>16&255]<<8|i[t>>>24&255]},r.interleave2=function(t,e){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t&=65535)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e&=65535)|e<<8))|e<<4))|e<<2))|e<<1))<<1},r.deinterleave2=function(t,e){return(t=65535&((t=16711935&((t=252645135&((t=858993459&((t=t>>>e&1431655765)|t>>>1))|t>>>2))|t>>>4))|t>>>16))<<16>>16},r.interleave3=function(t,e,r){return t=1227133513&((t=3272356035&((t=251719695&((t=4278190335&((t&=1023)|t<<16))|t<<8))|t<<4))|t<<2),(t|=(e=1227133513&((e=3272356035&((e=251719695&((e=4278190335&((e&=1023)|e<<16))|e<<8))|e<<4))|e<<2))<<1)|(r=1227133513&((r=3272356035&((r=251719695&((r=4278190335&((r&=1023)|r<<16))|r<<8))|r<<4))|r<<2))<<2},r.deinterleave3=function(t,e){return(t=1023&((t=4278190335&((t=251719695&((t=3272356035&((t=t>>>e&1227133513)|t>>>2))|t>>>4))|t>>>8))|t>>>16))<<22>>22},r.nextCombination=function(t){var e=t|t-1;return e+1|(~e&-~e)-1>>>n(t)+1}},{}],81:[function(t,e,r){"use strict";var n=t("clamp");e.exports=function(t,e){e||(e={});var r,o,s,l,c,u,f,h,p,d,m,g=null==e.cutoff?.25:e.cutoff,v=null==e.radius?8:e.radius,y=e.channel||0;if(ArrayBuffer.isView(t)||Array.isArray(t)){if(!e.width||!e.height)throw Error("For raw data width and height should be provided by options");r=e.width,o=e.height,l=t,u=e.stride?e.stride:Math.floor(t.length/r/o)}else window.HTMLCanvasElement&&t instanceof window.HTMLCanvasElement?(f=(h=t).getContext("2d"),r=h.width,o=h.height,p=f.getImageData(0,0,r,o),l=p.data,u=4):window.CanvasRenderingContext2D&&t instanceof window.CanvasRenderingContext2D?(h=t.canvas,f=t,r=h.width,o=h.height,p=f.getImageData(0,0,r,o),l=p.data,u=4):window.ImageData&&t instanceof window.ImageData&&(p=t,r=t.width,o=t.height,l=p.data,u=4);if(s=Math.max(r,o),window.Uint8ClampedArray&&l instanceof window.Uint8ClampedArray||window.Uint8Array&&l instanceof window.Uint8Array)for(c=l,l=Array(r*o),d=0,m=c.length;d=49&&o<=54?o-49+10:o>=17&&o<=22?o-17+10:15&o}return n}function l(t,e,r,n){for(var i=0,a=Math.min(t.length,r),o=e;o=49?s-49+10:s>=17?s-17+10:s}return i}a.isBN=function(t){return t instanceof a||null!==t&&"object"==typeof t&&t.constructor.wordSize===a.wordSize&&Array.isArray(t.words)},a.max=function(t,e){return t.cmp(e)>0?t:e},a.min=function(t,e){return t.cmp(e)<0?t:e},a.prototype._init=function(t,e,r){if("number"==typeof t)return this._initNumber(t,e,r);if("object"==typeof t)return this._initArray(t,e,r);"hex"===e&&(e=16),n(e===(0|e)&&e>=2&&e<=36);var i=0;"-"===(t=t.toString().replace(/\s+/g,""))[0]&&i++,16===e?this._parseHex(t,i):this._parseBase(t,e,i),"-"===t[0]&&(this.negative=1),this.strip(),"le"===r&&this._initArray(this.toArray(),e,r)},a.prototype._initNumber=function(t,e,r){t<0&&(this.negative=1,t=-t),t<67108864?(this.words=[67108863&t],this.length=1):t<4503599627370496?(this.words=[67108863&t,t/67108864&67108863],this.length=2):(n(t<9007199254740992),this.words=[67108863&t,t/67108864&67108863,1],this.length=3),"le"===r&&this._initArray(this.toArray(),e,r)},a.prototype._initArray=function(t,e,r){if(n("number"==typeof t.length),t.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(t.length/3),this.words=new Array(this.length);for(var i=0;i=0;i-=3)o=t[i]|t[i-1]<<8|t[i-2]<<16,this.words[a]|=o<>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);else if("le"===r)for(i=0,a=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);return this.strip()},a.prototype._parseHex=function(t,e){this.length=Math.ceil((t.length-e)/6),this.words=new Array(this.length);for(var r=0;r=e;r-=6)i=s(t,r,r+6),this.words[n]|=i<>>26-a&4194303,(a+=24)>=26&&(a-=26,n++);r+6!==e&&(i=s(t,e,r+6),this.words[n]|=i<>>26-a&4194303),this.strip()},a.prototype._parseBase=function(t,e,r){this.words=[0],this.length=1;for(var n=0,i=1;i<=67108863;i*=e)n++;n--,i=i/e|0;for(var a=t.length-r,o=a%n,s=Math.min(a,a-o)+r,c=0,u=r;u1&&0===this.words[this.length-1];)this.length--;return this._normSign()},a.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},a.prototype.inspect=function(){return(this.red?""};var c=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],u=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],f=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function h(t,e,r){r.negative=e.negative^t.negative;var n=t.length+e.length|0;r.length=n,n=n-1|0;var i=0|t.words[0],a=0|e.words[0],o=i*a,s=67108863&o,l=o/67108864|0;r.words[0]=s;for(var c=1;c>>26,f=67108863&l,h=Math.min(c,e.length-1),p=Math.max(0,c-t.length+1);p<=h;p++){var d=c-p|0;u+=(o=(i=0|t.words[d])*(a=0|e.words[p])+f)/67108864|0,f=67108863&o}r.words[c]=0|f,l=0|u}return 0!==l?r.words[c]=0|l:r.length--,r.strip()}a.prototype.toString=function(t,e){var r;if(e=0|e||1,16===(t=t||10)||"hex"===t){r="";for(var i=0,a=0,o=0;o>>24-i&16777215)||o!==this.length-1?c[6-l.length]+l+r:l+r,(i+=2)>=26&&(i-=26,o--)}for(0!==a&&(r=a.toString(16)+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}if(t===(0|t)&&t>=2&&t<=36){var h=u[t],p=f[t];r="";var d=this.clone();for(d.negative=0;!d.isZero();){var m=d.modn(p).toString(t);r=(d=d.idivn(p)).isZero()?m+r:c[h-m.length]+m+r}for(this.isZero()&&(r="0"+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}n(!1,"Base should be between 2 and 36")},a.prototype.toNumber=function(){var t=this.words[0];return 2===this.length?t+=67108864*this.words[1]:3===this.length&&1===this.words[2]?t+=4503599627370496+67108864*this.words[1]:this.length>2&&n(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-t:t},a.prototype.toJSON=function(){return this.toString(16)},a.prototype.toBuffer=function(t,e){return n("undefined"!=typeof o),this.toArrayLike(o,t,e)},a.prototype.toArray=function(t,e){return this.toArrayLike(Array,t,e)},a.prototype.toArrayLike=function(t,e,r){var i=this.byteLength(),a=r||Math.max(1,i);n(i<=a,"byte array longer than desired length"),n(a>0,"Requested array length <= 0"),this.strip();var o,s,l="le"===e,c=new t(a),u=this.clone();if(l){for(s=0;!u.isZero();s++)o=u.andln(255),u.iushrn(8),c[s]=o;for(;s=4096&&(r+=13,e>>>=13),e>=64&&(r+=7,e>>>=7),e>=8&&(r+=4,e>>>=4),e>=2&&(r+=2,e>>>=2),r+e},a.prototype._zeroBits=function(t){if(0===t)return 26;var e=t,r=0;return 0==(8191&e)&&(r+=13,e>>>=13),0==(127&e)&&(r+=7,e>>>=7),0==(15&e)&&(r+=4,e>>>=4),0==(3&e)&&(r+=2,e>>>=2),0==(1&e)&&r++,r},a.prototype.bitLength=function(){var t=this.words[this.length-1],e=this._countBits(t);return 26*(this.length-1)+e},a.prototype.zeroBits=function(){if(this.isZero())return 0;for(var t=0,e=0;et.length?this.clone().ior(t):t.clone().ior(this)},a.prototype.uor=function(t){return this.length>t.length?this.clone().iuor(t):t.clone().iuor(this)},a.prototype.iuand=function(t){var e;e=this.length>t.length?t:this;for(var r=0;rt.length?this.clone().iand(t):t.clone().iand(this)},a.prototype.uand=function(t){return this.length>t.length?this.clone().iuand(t):t.clone().iuand(this)},a.prototype.iuxor=function(t){var e,r;this.length>t.length?(e=this,r=t):(e=t,r=this);for(var n=0;nt.length?this.clone().ixor(t):t.clone().ixor(this)},a.prototype.uxor=function(t){return this.length>t.length?this.clone().iuxor(t):t.clone().iuxor(this)},a.prototype.inotn=function(t){n("number"==typeof t&&t>=0);var e=0|Math.ceil(t/26),r=t%26;this._expand(e),r>0&&e--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-r),this.strip()},a.prototype.notn=function(t){return this.clone().inotn(t)},a.prototype.setn=function(t,e){n("number"==typeof t&&t>=0);var r=t/26|0,i=t%26;return this._expand(r+1),this.words[r]=e?this.words[r]|1<t.length?(r=this,n=t):(r=t,n=this);for(var i=0,a=0;a>>26;for(;0!==i&&a>>26;if(this.length=r.length,0!==i)this.words[this.length]=i,this.length++;else if(r!==this)for(;at.length?this.clone().iadd(t):t.clone().iadd(this)},a.prototype.isub=function(t){if(0!==t.negative){t.negative=0;var e=this.iadd(t);return t.negative=1,e._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(t),this.negative=1,this._normSign();var r,n,i=this.cmp(t);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(r=this,n=t):(r=t,n=this);for(var a=0,o=0;o>26,this.words[o]=67108863&e;for(;0!==a&&o>26,this.words[o]=67108863&e;if(0===a&&o>>13,p=0|o[1],d=8191&p,m=p>>>13,g=0|o[2],v=8191&g,y=g>>>13,x=0|o[3],b=8191&x,_=x>>>13,w=0|o[4],k=8191&w,M=w>>>13,A=0|o[5],T=8191&A,S=A>>>13,E=0|o[6],C=8191&E,L=E>>>13,z=0|o[7],O=8191&z,I=z>>>13,P=0|o[8],D=8191&P,R=P>>>13,B=0|o[9],F=8191&B,N=B>>>13,j=0|s[0],V=8191&j,U=j>>>13,q=0|s[1],H=8191&q,G=q>>>13,W=0|s[2],Y=8191&W,X=W>>>13,Z=0|s[3],$=8191&Z,J=Z>>>13,K=0|s[4],Q=8191&K,tt=K>>>13,et=0|s[5],rt=8191&et,nt=et>>>13,it=0|s[6],at=8191&it,ot=it>>>13,st=0|s[7],lt=8191&st,ct=st>>>13,ut=0|s[8],ft=8191&ut,ht=ut>>>13,pt=0|s[9],dt=8191&pt,mt=pt>>>13;r.negative=t.negative^e.negative,r.length=19;var gt=(c+(n=Math.imul(f,V))|0)+((8191&(i=(i=Math.imul(f,U))+Math.imul(h,V)|0))<<13)|0;c=((a=Math.imul(h,U))+(i>>>13)|0)+(gt>>>26)|0,gt&=67108863,n=Math.imul(d,V),i=(i=Math.imul(d,U))+Math.imul(m,V)|0,a=Math.imul(m,U);var vt=(c+(n=n+Math.imul(f,H)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,H)|0))<<13)|0;c=((a=a+Math.imul(h,G)|0)+(i>>>13)|0)+(vt>>>26)|0,vt&=67108863,n=Math.imul(v,V),i=(i=Math.imul(v,U))+Math.imul(y,V)|0,a=Math.imul(y,U),n=n+Math.imul(d,H)|0,i=(i=i+Math.imul(d,G)|0)+Math.imul(m,H)|0,a=a+Math.imul(m,G)|0;var yt=(c+(n=n+Math.imul(f,Y)|0)|0)+((8191&(i=(i=i+Math.imul(f,X)|0)+Math.imul(h,Y)|0))<<13)|0;c=((a=a+Math.imul(h,X)|0)+(i>>>13)|0)+(yt>>>26)|0,yt&=67108863,n=Math.imul(b,V),i=(i=Math.imul(b,U))+Math.imul(_,V)|0,a=Math.imul(_,U),n=n+Math.imul(v,H)|0,i=(i=i+Math.imul(v,G)|0)+Math.imul(y,H)|0,a=a+Math.imul(y,G)|0,n=n+Math.imul(d,Y)|0,i=(i=i+Math.imul(d,X)|0)+Math.imul(m,Y)|0,a=a+Math.imul(m,X)|0;var xt=(c+(n=n+Math.imul(f,$)|0)|0)+((8191&(i=(i=i+Math.imul(f,J)|0)+Math.imul(h,$)|0))<<13)|0;c=((a=a+Math.imul(h,J)|0)+(i>>>13)|0)+(xt>>>26)|0,xt&=67108863,n=Math.imul(k,V),i=(i=Math.imul(k,U))+Math.imul(M,V)|0,a=Math.imul(M,U),n=n+Math.imul(b,H)|0,i=(i=i+Math.imul(b,G)|0)+Math.imul(_,H)|0,a=a+Math.imul(_,G)|0,n=n+Math.imul(v,Y)|0,i=(i=i+Math.imul(v,X)|0)+Math.imul(y,Y)|0,a=a+Math.imul(y,X)|0,n=n+Math.imul(d,$)|0,i=(i=i+Math.imul(d,J)|0)+Math.imul(m,$)|0,a=a+Math.imul(m,J)|0;var bt=(c+(n=n+Math.imul(f,Q)|0)|0)+((8191&(i=(i=i+Math.imul(f,tt)|0)+Math.imul(h,Q)|0))<<13)|0;c=((a=a+Math.imul(h,tt)|0)+(i>>>13)|0)+(bt>>>26)|0,bt&=67108863,n=Math.imul(T,V),i=(i=Math.imul(T,U))+Math.imul(S,V)|0,a=Math.imul(S,U),n=n+Math.imul(k,H)|0,i=(i=i+Math.imul(k,G)|0)+Math.imul(M,H)|0,a=a+Math.imul(M,G)|0,n=n+Math.imul(b,Y)|0,i=(i=i+Math.imul(b,X)|0)+Math.imul(_,Y)|0,a=a+Math.imul(_,X)|0,n=n+Math.imul(v,$)|0,i=(i=i+Math.imul(v,J)|0)+Math.imul(y,$)|0,a=a+Math.imul(y,J)|0,n=n+Math.imul(d,Q)|0,i=(i=i+Math.imul(d,tt)|0)+Math.imul(m,Q)|0,a=a+Math.imul(m,tt)|0;var _t=(c+(n=n+Math.imul(f,rt)|0)|0)+((8191&(i=(i=i+Math.imul(f,nt)|0)+Math.imul(h,rt)|0))<<13)|0;c=((a=a+Math.imul(h,nt)|0)+(i>>>13)|0)+(_t>>>26)|0,_t&=67108863,n=Math.imul(C,V),i=(i=Math.imul(C,U))+Math.imul(L,V)|0,a=Math.imul(L,U),n=n+Math.imul(T,H)|0,i=(i=i+Math.imul(T,G)|0)+Math.imul(S,H)|0,a=a+Math.imul(S,G)|0,n=n+Math.imul(k,Y)|0,i=(i=i+Math.imul(k,X)|0)+Math.imul(M,Y)|0,a=a+Math.imul(M,X)|0,n=n+Math.imul(b,$)|0,i=(i=i+Math.imul(b,J)|0)+Math.imul(_,$)|0,a=a+Math.imul(_,J)|0,n=n+Math.imul(v,Q)|0,i=(i=i+Math.imul(v,tt)|0)+Math.imul(y,Q)|0,a=a+Math.imul(y,tt)|0,n=n+Math.imul(d,rt)|0,i=(i=i+Math.imul(d,nt)|0)+Math.imul(m,rt)|0,a=a+Math.imul(m,nt)|0;var wt=(c+(n=n+Math.imul(f,at)|0)|0)+((8191&(i=(i=i+Math.imul(f,ot)|0)+Math.imul(h,at)|0))<<13)|0;c=((a=a+Math.imul(h,ot)|0)+(i>>>13)|0)+(wt>>>26)|0,wt&=67108863,n=Math.imul(O,V),i=(i=Math.imul(O,U))+Math.imul(I,V)|0,a=Math.imul(I,U),n=n+Math.imul(C,H)|0,i=(i=i+Math.imul(C,G)|0)+Math.imul(L,H)|0,a=a+Math.imul(L,G)|0,n=n+Math.imul(T,Y)|0,i=(i=i+Math.imul(T,X)|0)+Math.imul(S,Y)|0,a=a+Math.imul(S,X)|0,n=n+Math.imul(k,$)|0,i=(i=i+Math.imul(k,J)|0)+Math.imul(M,$)|0,a=a+Math.imul(M,J)|0,n=n+Math.imul(b,Q)|0,i=(i=i+Math.imul(b,tt)|0)+Math.imul(_,Q)|0,a=a+Math.imul(_,tt)|0,n=n+Math.imul(v,rt)|0,i=(i=i+Math.imul(v,nt)|0)+Math.imul(y,rt)|0,a=a+Math.imul(y,nt)|0,n=n+Math.imul(d,at)|0,i=(i=i+Math.imul(d,ot)|0)+Math.imul(m,at)|0,a=a+Math.imul(m,ot)|0;var kt=(c+(n=n+Math.imul(f,lt)|0)|0)+((8191&(i=(i=i+Math.imul(f,ct)|0)+Math.imul(h,lt)|0))<<13)|0;c=((a=a+Math.imul(h,ct)|0)+(i>>>13)|0)+(kt>>>26)|0,kt&=67108863,n=Math.imul(D,V),i=(i=Math.imul(D,U))+Math.imul(R,V)|0,a=Math.imul(R,U),n=n+Math.imul(O,H)|0,i=(i=i+Math.imul(O,G)|0)+Math.imul(I,H)|0,a=a+Math.imul(I,G)|0,n=n+Math.imul(C,Y)|0,i=(i=i+Math.imul(C,X)|0)+Math.imul(L,Y)|0,a=a+Math.imul(L,X)|0,n=n+Math.imul(T,$)|0,i=(i=i+Math.imul(T,J)|0)+Math.imul(S,$)|0,a=a+Math.imul(S,J)|0,n=n+Math.imul(k,Q)|0,i=(i=i+Math.imul(k,tt)|0)+Math.imul(M,Q)|0,a=a+Math.imul(M,tt)|0,n=n+Math.imul(b,rt)|0,i=(i=i+Math.imul(b,nt)|0)+Math.imul(_,rt)|0,a=a+Math.imul(_,nt)|0,n=n+Math.imul(v,at)|0,i=(i=i+Math.imul(v,ot)|0)+Math.imul(y,at)|0,a=a+Math.imul(y,ot)|0,n=n+Math.imul(d,lt)|0,i=(i=i+Math.imul(d,ct)|0)+Math.imul(m,lt)|0,a=a+Math.imul(m,ct)|0;var Mt=(c+(n=n+Math.imul(f,ft)|0)|0)+((8191&(i=(i=i+Math.imul(f,ht)|0)+Math.imul(h,ft)|0))<<13)|0;c=((a=a+Math.imul(h,ht)|0)+(i>>>13)|0)+(Mt>>>26)|0,Mt&=67108863,n=Math.imul(F,V),i=(i=Math.imul(F,U))+Math.imul(N,V)|0,a=Math.imul(N,U),n=n+Math.imul(D,H)|0,i=(i=i+Math.imul(D,G)|0)+Math.imul(R,H)|0,a=a+Math.imul(R,G)|0,n=n+Math.imul(O,Y)|0,i=(i=i+Math.imul(O,X)|0)+Math.imul(I,Y)|0,a=a+Math.imul(I,X)|0,n=n+Math.imul(C,$)|0,i=(i=i+Math.imul(C,J)|0)+Math.imul(L,$)|0,a=a+Math.imul(L,J)|0,n=n+Math.imul(T,Q)|0,i=(i=i+Math.imul(T,tt)|0)+Math.imul(S,Q)|0,a=a+Math.imul(S,tt)|0,n=n+Math.imul(k,rt)|0,i=(i=i+Math.imul(k,nt)|0)+Math.imul(M,rt)|0,a=a+Math.imul(M,nt)|0,n=n+Math.imul(b,at)|0,i=(i=i+Math.imul(b,ot)|0)+Math.imul(_,at)|0,a=a+Math.imul(_,ot)|0,n=n+Math.imul(v,lt)|0,i=(i=i+Math.imul(v,ct)|0)+Math.imul(y,lt)|0,a=a+Math.imul(y,ct)|0,n=n+Math.imul(d,ft)|0,i=(i=i+Math.imul(d,ht)|0)+Math.imul(m,ft)|0,a=a+Math.imul(m,ht)|0;var At=(c+(n=n+Math.imul(f,dt)|0)|0)+((8191&(i=(i=i+Math.imul(f,mt)|0)+Math.imul(h,dt)|0))<<13)|0;c=((a=a+Math.imul(h,mt)|0)+(i>>>13)|0)+(At>>>26)|0,At&=67108863,n=Math.imul(F,H),i=(i=Math.imul(F,G))+Math.imul(N,H)|0,a=Math.imul(N,G),n=n+Math.imul(D,Y)|0,i=(i=i+Math.imul(D,X)|0)+Math.imul(R,Y)|0,a=a+Math.imul(R,X)|0,n=n+Math.imul(O,$)|0,i=(i=i+Math.imul(O,J)|0)+Math.imul(I,$)|0,a=a+Math.imul(I,J)|0,n=n+Math.imul(C,Q)|0,i=(i=i+Math.imul(C,tt)|0)+Math.imul(L,Q)|0,a=a+Math.imul(L,tt)|0,n=n+Math.imul(T,rt)|0,i=(i=i+Math.imul(T,nt)|0)+Math.imul(S,rt)|0,a=a+Math.imul(S,nt)|0,n=n+Math.imul(k,at)|0,i=(i=i+Math.imul(k,ot)|0)+Math.imul(M,at)|0,a=a+Math.imul(M,ot)|0,n=n+Math.imul(b,lt)|0,i=(i=i+Math.imul(b,ct)|0)+Math.imul(_,lt)|0,a=a+Math.imul(_,ct)|0,n=n+Math.imul(v,ft)|0,i=(i=i+Math.imul(v,ht)|0)+Math.imul(y,ft)|0,a=a+Math.imul(y,ht)|0;var Tt=(c+(n=n+Math.imul(d,dt)|0)|0)+((8191&(i=(i=i+Math.imul(d,mt)|0)+Math.imul(m,dt)|0))<<13)|0;c=((a=a+Math.imul(m,mt)|0)+(i>>>13)|0)+(Tt>>>26)|0,Tt&=67108863,n=Math.imul(F,Y),i=(i=Math.imul(F,X))+Math.imul(N,Y)|0,a=Math.imul(N,X),n=n+Math.imul(D,$)|0,i=(i=i+Math.imul(D,J)|0)+Math.imul(R,$)|0,a=a+Math.imul(R,J)|0,n=n+Math.imul(O,Q)|0,i=(i=i+Math.imul(O,tt)|0)+Math.imul(I,Q)|0,a=a+Math.imul(I,tt)|0,n=n+Math.imul(C,rt)|0,i=(i=i+Math.imul(C,nt)|0)+Math.imul(L,rt)|0,a=a+Math.imul(L,nt)|0,n=n+Math.imul(T,at)|0,i=(i=i+Math.imul(T,ot)|0)+Math.imul(S,at)|0,a=a+Math.imul(S,ot)|0,n=n+Math.imul(k,lt)|0,i=(i=i+Math.imul(k,ct)|0)+Math.imul(M,lt)|0,a=a+Math.imul(M,ct)|0,n=n+Math.imul(b,ft)|0,i=(i=i+Math.imul(b,ht)|0)+Math.imul(_,ft)|0,a=a+Math.imul(_,ht)|0;var St=(c+(n=n+Math.imul(v,dt)|0)|0)+((8191&(i=(i=i+Math.imul(v,mt)|0)+Math.imul(y,dt)|0))<<13)|0;c=((a=a+Math.imul(y,mt)|0)+(i>>>13)|0)+(St>>>26)|0,St&=67108863,n=Math.imul(F,$),i=(i=Math.imul(F,J))+Math.imul(N,$)|0,a=Math.imul(N,J),n=n+Math.imul(D,Q)|0,i=(i=i+Math.imul(D,tt)|0)+Math.imul(R,Q)|0,a=a+Math.imul(R,tt)|0,n=n+Math.imul(O,rt)|0,i=(i=i+Math.imul(O,nt)|0)+Math.imul(I,rt)|0,a=a+Math.imul(I,nt)|0,n=n+Math.imul(C,at)|0,i=(i=i+Math.imul(C,ot)|0)+Math.imul(L,at)|0,a=a+Math.imul(L,ot)|0,n=n+Math.imul(T,lt)|0,i=(i=i+Math.imul(T,ct)|0)+Math.imul(S,lt)|0,a=a+Math.imul(S,ct)|0,n=n+Math.imul(k,ft)|0,i=(i=i+Math.imul(k,ht)|0)+Math.imul(M,ft)|0,a=a+Math.imul(M,ht)|0;var Et=(c+(n=n+Math.imul(b,dt)|0)|0)+((8191&(i=(i=i+Math.imul(b,mt)|0)+Math.imul(_,dt)|0))<<13)|0;c=((a=a+Math.imul(_,mt)|0)+(i>>>13)|0)+(Et>>>26)|0,Et&=67108863,n=Math.imul(F,Q),i=(i=Math.imul(F,tt))+Math.imul(N,Q)|0,a=Math.imul(N,tt),n=n+Math.imul(D,rt)|0,i=(i=i+Math.imul(D,nt)|0)+Math.imul(R,rt)|0,a=a+Math.imul(R,nt)|0,n=n+Math.imul(O,at)|0,i=(i=i+Math.imul(O,ot)|0)+Math.imul(I,at)|0,a=a+Math.imul(I,ot)|0,n=n+Math.imul(C,lt)|0,i=(i=i+Math.imul(C,ct)|0)+Math.imul(L,lt)|0,a=a+Math.imul(L,ct)|0,n=n+Math.imul(T,ft)|0,i=(i=i+Math.imul(T,ht)|0)+Math.imul(S,ft)|0,a=a+Math.imul(S,ht)|0;var Ct=(c+(n=n+Math.imul(k,dt)|0)|0)+((8191&(i=(i=i+Math.imul(k,mt)|0)+Math.imul(M,dt)|0))<<13)|0;c=((a=a+Math.imul(M,mt)|0)+(i>>>13)|0)+(Ct>>>26)|0,Ct&=67108863,n=Math.imul(F,rt),i=(i=Math.imul(F,nt))+Math.imul(N,rt)|0,a=Math.imul(N,nt),n=n+Math.imul(D,at)|0,i=(i=i+Math.imul(D,ot)|0)+Math.imul(R,at)|0,a=a+Math.imul(R,ot)|0,n=n+Math.imul(O,lt)|0,i=(i=i+Math.imul(O,ct)|0)+Math.imul(I,lt)|0,a=a+Math.imul(I,ct)|0,n=n+Math.imul(C,ft)|0,i=(i=i+Math.imul(C,ht)|0)+Math.imul(L,ft)|0,a=a+Math.imul(L,ht)|0;var Lt=(c+(n=n+Math.imul(T,dt)|0)|0)+((8191&(i=(i=i+Math.imul(T,mt)|0)+Math.imul(S,dt)|0))<<13)|0;c=((a=a+Math.imul(S,mt)|0)+(i>>>13)|0)+(Lt>>>26)|0,Lt&=67108863,n=Math.imul(F,at),i=(i=Math.imul(F,ot))+Math.imul(N,at)|0,a=Math.imul(N,ot),n=n+Math.imul(D,lt)|0,i=(i=i+Math.imul(D,ct)|0)+Math.imul(R,lt)|0,a=a+Math.imul(R,ct)|0,n=n+Math.imul(O,ft)|0,i=(i=i+Math.imul(O,ht)|0)+Math.imul(I,ft)|0,a=a+Math.imul(I,ht)|0;var zt=(c+(n=n+Math.imul(C,dt)|0)|0)+((8191&(i=(i=i+Math.imul(C,mt)|0)+Math.imul(L,dt)|0))<<13)|0;c=((a=a+Math.imul(L,mt)|0)+(i>>>13)|0)+(zt>>>26)|0,zt&=67108863,n=Math.imul(F,lt),i=(i=Math.imul(F,ct))+Math.imul(N,lt)|0,a=Math.imul(N,ct),n=n+Math.imul(D,ft)|0,i=(i=i+Math.imul(D,ht)|0)+Math.imul(R,ft)|0,a=a+Math.imul(R,ht)|0;var Ot=(c+(n=n+Math.imul(O,dt)|0)|0)+((8191&(i=(i=i+Math.imul(O,mt)|0)+Math.imul(I,dt)|0))<<13)|0;c=((a=a+Math.imul(I,mt)|0)+(i>>>13)|0)+(Ot>>>26)|0,Ot&=67108863,n=Math.imul(F,ft),i=(i=Math.imul(F,ht))+Math.imul(N,ft)|0,a=Math.imul(N,ht);var It=(c+(n=n+Math.imul(D,dt)|0)|0)+((8191&(i=(i=i+Math.imul(D,mt)|0)+Math.imul(R,dt)|0))<<13)|0;c=((a=a+Math.imul(R,mt)|0)+(i>>>13)|0)+(It>>>26)|0,It&=67108863;var Pt=(c+(n=Math.imul(F,dt))|0)+((8191&(i=(i=Math.imul(F,mt))+Math.imul(N,dt)|0))<<13)|0;return c=((a=Math.imul(N,mt))+(i>>>13)|0)+(Pt>>>26)|0,Pt&=67108863,l[0]=gt,l[1]=vt,l[2]=yt,l[3]=xt,l[4]=bt,l[5]=_t,l[6]=wt,l[7]=kt,l[8]=Mt,l[9]=At,l[10]=Tt,l[11]=St,l[12]=Et,l[13]=Ct,l[14]=Lt,l[15]=zt,l[16]=Ot,l[17]=It,l[18]=Pt,0!==c&&(l[19]=c,r.length++),r};function d(t,e,r){return(new m).mulp(t,e,r)}function m(t,e){this.x=t,this.y=e}Math.imul||(p=h),a.prototype.mulTo=function(t,e){var r=this.length+t.length;return 10===this.length&&10===t.length?p(this,t,e):r<63?h(this,t,e):r<1024?function(t,e,r){r.negative=e.negative^t.negative,r.length=t.length+e.length;for(var n=0,i=0,a=0;a>>26)|0)>>>26,o&=67108863}r.words[a]=s,n=o,o=i}return 0!==n?r.words[a]=n:r.length--,r.strip()}(this,t,e):d(this,t,e)},m.prototype.makeRBT=function(t){for(var e=new Array(t),r=a.prototype._countBits(t)-1,n=0;n>=1;return n},m.prototype.permute=function(t,e,r,n,i,a){for(var o=0;o>>=1)i++;return 1<>>=13,r[2*o+1]=8191&a,a>>>=13;for(o=2*e;o>=26,e+=i/67108864|0,e+=a>>>26,this.words[r]=67108863&a}return 0!==e&&(this.words[r]=e,this.length++),this},a.prototype.muln=function(t){return this.clone().imuln(t)},a.prototype.sqr=function(){return this.mul(this)},a.prototype.isqr=function(){return this.imul(this.clone())},a.prototype.pow=function(t){var e=function(t){for(var e=new Array(t.bitLength()),r=0;r>>i}return e}(t);if(0===e.length)return new a(1);for(var r=this,n=0;n=0);var e,r=t%26,i=(t-r)/26,a=67108863>>>26-r<<26-r;if(0!==r){var o=0;for(e=0;e>>26-r}o&&(this.words[e]=o,this.length++)}if(0!==i){for(e=this.length-1;e>=0;e--)this.words[e+i]=this.words[e];for(e=0;e=0),i=e?(e-e%26)/26:0;var a=t%26,o=Math.min((t-a)/26,this.length),s=67108863^67108863>>>a<o)for(this.length-=o,c=0;c=0&&(0!==u||c>=i);c--){var f=0|this.words[c];this.words[c]=u<<26-a|f>>>a,u=f&s}return l&&0!==u&&(l.words[l.length++]=u),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},a.prototype.ishrn=function(t,e,r){return n(0===this.negative),this.iushrn(t,e,r)},a.prototype.shln=function(t){return this.clone().ishln(t)},a.prototype.ushln=function(t){return this.clone().iushln(t)},a.prototype.shrn=function(t){return this.clone().ishrn(t)},a.prototype.ushrn=function(t){return this.clone().iushrn(t)},a.prototype.testn=function(t){n("number"==typeof t&&t>=0);var e=t%26,r=(t-e)/26,i=1<=0);var e=t%26,r=(t-e)/26;if(n(0===this.negative,"imaskn works only with positive numbers"),this.length<=r)return this;if(0!==e&&r++,this.length=Math.min(r,this.length),0!==e){var i=67108863^67108863>>>e<=67108864;e++)this.words[e]-=67108864,e===this.length-1?this.words[e+1]=1:this.words[e+1]++;return this.length=Math.max(this.length,e+1),this},a.prototype.isubn=function(t){if(n("number"==typeof t),n(t<67108864),t<0)return this.iaddn(-t);if(0!==this.negative)return this.negative=0,this.iaddn(t),this.negative=1,this;if(this.words[0]-=t,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var e=0;e>26)-(l/67108864|0),this.words[i+r]=67108863&a}for(;i>26,this.words[i+r]=67108863&a;if(0===s)return this.strip();for(n(-1===s),s=0,i=0;i>26,this.words[i]=67108863&a;return this.negative=1,this.strip()},a.prototype._wordDiv=function(t,e){var r=(this.length,t.length),n=this.clone(),i=t,o=0|i.words[i.length-1];0!==(r=26-this._countBits(o))&&(i=i.ushln(r),n.iushln(r),o=0|i.words[i.length-1]);var s,l=n.length-i.length;if("mod"!==e){(s=new a(null)).length=l+1,s.words=new Array(s.length);for(var c=0;c=0;f--){var h=67108864*(0|n.words[i.length+f])+(0|n.words[i.length+f-1]);for(h=Math.min(h/o|0,67108863),n._ishlnsubmul(i,h,f);0!==n.negative;)h--,n.negative=0,n._ishlnsubmul(i,1,f),n.isZero()||(n.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),n.strip(),"div"!==e&&0!==r&&n.iushrn(r),{div:s||null,mod:n}},a.prototype.divmod=function(t,e,r){return n(!t.isZero()),this.isZero()?{div:new a(0),mod:new a(0)}:0!==this.negative&&0===t.negative?(s=this.neg().divmod(t,e),"mod"!==e&&(i=s.div.neg()),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.iadd(t)),{div:i,mod:o}):0===this.negative&&0!==t.negative?(s=this.divmod(t.neg(),e),"mod"!==e&&(i=s.div.neg()),{div:i,mod:s.mod}):0!=(this.negative&t.negative)?(s=this.neg().divmod(t.neg(),e),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.isub(t)),{div:s.div,mod:o}):t.length>this.length||this.cmp(t)<0?{div:new a(0),mod:this}:1===t.length?"div"===e?{div:this.divn(t.words[0]),mod:null}:"mod"===e?{div:null,mod:new a(this.modn(t.words[0]))}:{div:this.divn(t.words[0]),mod:new a(this.modn(t.words[0]))}:this._wordDiv(t,e);var i,o,s},a.prototype.div=function(t){return this.divmod(t,"div",!1).div},a.prototype.mod=function(t){return this.divmod(t,"mod",!1).mod},a.prototype.umod=function(t){return this.divmod(t,"mod",!0).mod},a.prototype.divRound=function(t){var e=this.divmod(t);if(e.mod.isZero())return e.div;var r=0!==e.div.negative?e.mod.isub(t):e.mod,n=t.ushrn(1),i=t.andln(1),a=r.cmp(n);return a<0||1===i&&0===a?e.div:0!==e.div.negative?e.div.isubn(1):e.div.iaddn(1)},a.prototype.modn=function(t){n(t<=67108863);for(var e=(1<<26)%t,r=0,i=this.length-1;i>=0;i--)r=(e*r+(0|this.words[i]))%t;return r},a.prototype.idivn=function(t){n(t<=67108863);for(var e=0,r=this.length-1;r>=0;r--){var i=(0|this.words[r])+67108864*e;this.words[r]=i/t|0,e=i%t}return this.strip()},a.prototype.divn=function(t){return this.clone().idivn(t)},a.prototype.egcd=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i=new a(1),o=new a(0),s=new a(0),l=new a(1),c=0;e.isEven()&&r.isEven();)e.iushrn(1),r.iushrn(1),++c;for(var u=r.clone(),f=e.clone();!e.isZero();){for(var h=0,p=1;0==(e.words[0]&p)&&h<26;++h,p<<=1);if(h>0)for(e.iushrn(h);h-- >0;)(i.isOdd()||o.isOdd())&&(i.iadd(u),o.isub(f)),i.iushrn(1),o.iushrn(1);for(var d=0,m=1;0==(r.words[0]&m)&&d<26;++d,m<<=1);if(d>0)for(r.iushrn(d);d-- >0;)(s.isOdd()||l.isOdd())&&(s.iadd(u),l.isub(f)),s.iushrn(1),l.iushrn(1);e.cmp(r)>=0?(e.isub(r),i.isub(s),o.isub(l)):(r.isub(e),s.isub(i),l.isub(o))}return{a:s,b:l,gcd:r.iushln(c)}},a.prototype._invmp=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i,o=new a(1),s=new a(0),l=r.clone();e.cmpn(1)>0&&r.cmpn(1)>0;){for(var c=0,u=1;0==(e.words[0]&u)&&c<26;++c,u<<=1);if(c>0)for(e.iushrn(c);c-- >0;)o.isOdd()&&o.iadd(l),o.iushrn(1);for(var f=0,h=1;0==(r.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(r.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(l),s.iushrn(1);e.cmp(r)>=0?(e.isub(r),o.isub(s)):(r.isub(e),s.isub(o))}return(i=0===e.cmpn(1)?o:s).cmpn(0)<0&&i.iadd(t),i},a.prototype.gcd=function(t){if(this.isZero())return t.abs();if(t.isZero())return this.abs();var e=this.clone(),r=t.clone();e.negative=0,r.negative=0;for(var n=0;e.isEven()&&r.isEven();n++)e.iushrn(1),r.iushrn(1);for(;;){for(;e.isEven();)e.iushrn(1);for(;r.isEven();)r.iushrn(1);var i=e.cmp(r);if(i<0){var a=e;e=r,r=a}else if(0===i||0===r.cmpn(1))break;e.isub(r)}return r.iushln(n)},a.prototype.invm=function(t){return this.egcd(t).a.umod(t)},a.prototype.isEven=function(){return 0==(1&this.words[0])},a.prototype.isOdd=function(){return 1==(1&this.words[0])},a.prototype.andln=function(t){return this.words[0]&t},a.prototype.bincn=function(t){n("number"==typeof t);var e=t%26,r=(t-e)/26,i=1<>>26,s&=67108863,this.words[o]=s}return 0!==a&&(this.words[o]=a,this.length++),this},a.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},a.prototype.cmpn=function(t){var e,r=t<0;if(0!==this.negative&&!r)return-1;if(0===this.negative&&r)return 1;if(this.strip(),this.length>1)e=1;else{r&&(t=-t),n(t<=67108863,"Number is too big");var i=0|this.words[0];e=i===t?0:it.length)return 1;if(this.length=0;r--){var n=0|this.words[r],i=0|t.words[r];if(n!==i){ni&&(e=1);break}}return e},a.prototype.gtn=function(t){return 1===this.cmpn(t)},a.prototype.gt=function(t){return 1===this.cmp(t)},a.prototype.gten=function(t){return this.cmpn(t)>=0},a.prototype.gte=function(t){return this.cmp(t)>=0},a.prototype.ltn=function(t){return-1===this.cmpn(t)},a.prototype.lt=function(t){return-1===this.cmp(t)},a.prototype.lten=function(t){return this.cmpn(t)<=0},a.prototype.lte=function(t){return this.cmp(t)<=0},a.prototype.eqn=function(t){return 0===this.cmpn(t)},a.prototype.eq=function(t){return 0===this.cmp(t)},a.red=function(t){return new w(t)},a.prototype.toRed=function(t){return n(!this.red,"Already a number in reduction context"),n(0===this.negative,"red works only with positives"),t.convertTo(this)._forceRed(t)},a.prototype.fromRed=function(){return n(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},a.prototype._forceRed=function(t){return this.red=t,this},a.prototype.forceRed=function(t){return n(!this.red,"Already a number in reduction context"),this._forceRed(t)},a.prototype.redAdd=function(t){return n(this.red,"redAdd works only with red numbers"),this.red.add(this,t)},a.prototype.redIAdd=function(t){return n(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,t)},a.prototype.redSub=function(t){return n(this.red,"redSub works only with red numbers"),this.red.sub(this,t)},a.prototype.redISub=function(t){return n(this.red,"redISub works only with red numbers"),this.red.isub(this,t)},a.prototype.redShl=function(t){return n(this.red,"redShl works only with red numbers"),this.red.shl(this,t)},a.prototype.redMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.mul(this,t)},a.prototype.redIMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.imul(this,t)},a.prototype.redSqr=function(){return n(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},a.prototype.redISqr=function(){return n(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},a.prototype.redSqrt=function(){return n(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},a.prototype.redInvm=function(){return n(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},a.prototype.redNeg=function(){return n(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},a.prototype.redPow=function(t){return n(this.red&&!t.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,t)};var g={k256:null,p224:null,p192:null,p25519:null};function v(t,e){this.name=t,this.p=new a(e,16),this.n=this.p.bitLength(),this.k=new a(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function y(){v.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function x(){v.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function b(){v.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function _(){v.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function w(t){if("string"==typeof t){var e=a._prime(t);this.m=e.p,this.prime=e}else n(t.gtn(1),"modulus must be greater than 1"),this.m=t,this.prime=null}function k(t){w.call(this,t),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new a(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}v.prototype._tmp=function(){var t=new a(null);return t.words=new Array(Math.ceil(this.n/13)),t},v.prototype.ireduce=function(t){var e,r=t;do{this.split(r,this.tmp),e=(r=(r=this.imulK(r)).iadd(this.tmp)).bitLength()}while(e>this.n);var n=e0?r.isub(this.p):r.strip(),r},v.prototype.split=function(t,e){t.iushrn(this.n,0,e)},v.prototype.imulK=function(t){return t.imul(this.k)},i(y,v),y.prototype.split=function(t,e){for(var r=Math.min(t.length,9),n=0;n>>22,i=a}i>>>=22,t.words[n-10]=i,0===i&&t.length>10?t.length-=10:t.length-=9},y.prototype.imulK=function(t){t.words[t.length]=0,t.words[t.length+1]=0,t.length+=2;for(var e=0,r=0;r>>=26,t.words[r]=i,e=n}return 0!==e&&(t.words[t.length++]=e),t},a._prime=function(t){if(g[t])return g[t];var e;if("k256"===t)e=new y;else if("p224"===t)e=new x;else if("p192"===t)e=new b;else{if("p25519"!==t)throw new Error("Unknown prime "+t);e=new _}return g[t]=e,e},w.prototype._verify1=function(t){n(0===t.negative,"red works only with positives"),n(t.red,"red works only with red numbers")},w.prototype._verify2=function(t,e){n(0==(t.negative|e.negative),"red works only with positives"),n(t.red&&t.red===e.red,"red works only with red numbers")},w.prototype.imod=function(t){return this.prime?this.prime.ireduce(t)._forceRed(this):t.umod(this.m)._forceRed(this)},w.prototype.neg=function(t){return t.isZero()?t.clone():this.m.sub(t)._forceRed(this)},w.prototype.add=function(t,e){this._verify2(t,e);var r=t.add(e);return r.cmp(this.m)>=0&&r.isub(this.m),r._forceRed(this)},w.prototype.iadd=function(t,e){this._verify2(t,e);var r=t.iadd(e);return r.cmp(this.m)>=0&&r.isub(this.m),r},w.prototype.sub=function(t,e){this._verify2(t,e);var r=t.sub(e);return r.cmpn(0)<0&&r.iadd(this.m),r._forceRed(this)},w.prototype.isub=function(t,e){this._verify2(t,e);var r=t.isub(e);return r.cmpn(0)<0&&r.iadd(this.m),r},w.prototype.shl=function(t,e){return this._verify1(t),this.imod(t.ushln(e))},w.prototype.imul=function(t,e){return this._verify2(t,e),this.imod(t.imul(e))},w.prototype.mul=function(t,e){return this._verify2(t,e),this.imod(t.mul(e))},w.prototype.isqr=function(t){return this.imul(t,t.clone())},w.prototype.sqr=function(t){return this.mul(t,t)},w.prototype.sqrt=function(t){if(t.isZero())return t.clone();var e=this.m.andln(3);if(n(e%2==1),3===e){var r=this.m.add(new a(1)).iushrn(2);return this.pow(t,r)}for(var i=this.m.subn(1),o=0;!i.isZero()&&0===i.andln(1);)o++,i.iushrn(1);n(!i.isZero());var s=new a(1).toRed(this),l=s.redNeg(),c=this.m.subn(1).iushrn(1),u=this.m.bitLength();for(u=new a(2*u*u).toRed(this);0!==this.pow(u,c).cmp(l);)u.redIAdd(l);for(var f=this.pow(u,i),h=this.pow(t,i.addn(1).iushrn(1)),p=this.pow(t,i),d=o;0!==p.cmp(s);){for(var m=p,g=0;0!==m.cmp(s);g++)m=m.redSqr();n(g=0;n--){for(var c=e.words[n],u=l-1;u>=0;u--){var f=c>>u&1;i!==r[0]&&(i=this.sqr(i)),0!==f||0!==o?(o<<=1,o|=f,(4===++s||0===n&&0===u)&&(i=this.mul(i,r[o]),s=0,o=0)):s=0}l=26}return i},w.prototype.convertTo=function(t){var e=t.umod(this.m);return e===t?e.clone():e},w.prototype.convertFrom=function(t){var e=t.clone();return e.red=null,e},a.mont=function(t){return new k(t)},i(k,w),k.prototype.convertTo=function(t){return this.imod(t.ushln(this.shift))},k.prototype.convertFrom=function(t){var e=this.imod(t.mul(this.rinv));return e.red=null,e},k.prototype.imul=function(t,e){if(t.isZero()||e.isZero())return t.words[0]=0,t.length=1,t;var r=t.imul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},k.prototype.mul=function(t,e){if(t.isZero()||e.isZero())return new a(0)._forceRed(this);var r=t.mul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},k.prototype.invm=function(t){return this.imod(t._invmp(this.m).mul(this.r2))._forceRed(this)}}("undefined"==typeof e||e,this)},{buffer:91}],83:[function(t,e,r){"use strict";e.exports=function(t){var e,r,n,i=t.length,a=0;for(e=0;e>>1;if(!(u<=0)){var f,h=i.mallocDouble(2*u*s),p=i.mallocInt32(s);if((s=l(t,u,h,p))>0){if(1===u&&n)a.init(s),f=a.sweepComplete(u,r,0,s,h,p,0,s,h,p);else{var d=i.mallocDouble(2*u*c),m=i.mallocInt32(c);(c=l(e,u,d,m))>0&&(a.init(s+c),f=1===u?a.sweepBipartite(u,r,0,s,h,p,0,c,d,m):o(u,r,n,s,h,p,c,d,m),i.free(d),i.free(m))}i.free(h),i.free(p)}return f}}}function u(t,e){n.push([t,e])}},{"./lib/intersect":86,"./lib/sweep":90,"typedarray-pool":522}],85:[function(t,e,r){"use strict";var n="d",i="ax",a="vv",o="fp",s="es",l="rs",c="re",u="rb",f="ri",h="rp",p="bs",d="be",m="bb",g="bi",v="bp",y="rv",x="Q",b=[n,i,a,l,c,u,f,p,d,m,g];function _(t){var e="bruteForce"+(t?"Full":"Partial"),r=[],_=b.slice();t||_.splice(3,0,o);var w=["function "+e+"("+_.join()+"){"];function k(e,o){var _=function(t,e,r){var o="bruteForce"+(t?"Red":"Blue")+(e?"Flip":"")+(r?"Full":""),_=["function ",o,"(",b.join(),"){","var ",s,"=2*",n,";"],w="for(var i="+l+","+h+"="+s+"*"+l+";i<"+c+";++i,"+h+"+="+s+"){var x0="+u+"["+i+"+"+h+"],x1="+u+"["+i+"+"+h+"+"+n+"],xi="+f+"[i];",k="for(var j="+p+","+v+"="+s+"*"+p+";j<"+d+";++j,"+v+"+="+s+"){var y0="+m+"["+i+"+"+v+"],"+(r?"y1="+m+"["+i+"+"+v+"+"+n+"],":"")+"yi="+g+"[j];";return t?_.push(w,x,":",k):_.push(k,x,":",w),r?_.push("if(y1"+d+"-"+p+"){"),t?(k(!0,!1),w.push("}else{"),k(!1,!1)):(w.push("if("+o+"){"),k(!0,!0),w.push("}else{"),k(!0,!1),w.push("}}else{if("+o+"){"),k(!1,!0),w.push("}else{"),k(!1,!1),w.push("}")),w.push("}}return "+e);var M=r.join("")+w.join("");return new Function(M)()}r.partial=_(!1),r.full=_(!0)},{}],86:[function(t,e,r){"use strict";e.exports=function(t,e,r,a,u,S,E,C,L){!function(t,e){var r=8*i.log2(e+1)*(t+1)|0,a=i.nextPow2(b*r);w.length0;){var P=(O-=1)*b,D=w[P],R=w[P+1],B=w[P+2],F=w[P+3],N=w[P+4],j=w[P+5],V=O*_,U=k[V],q=k[V+1],H=1&j,G=!!(16&j),W=u,Y=S,X=C,Z=L;if(H&&(W=C,Y=L,X=u,Z=S),!(2&j&&(B=g(t,D,R,B,W,Y,q),R>=B)||4&j&&(R=v(t,D,R,B,W,Y,U))>=B)){var $=B-R,J=N-F;if(G){if(t*$*($+J)=p0)&&!(p1>=hi)",["p0","p1"]),m=u("lo===p0",["p0"]),g=u("lo>>1,h=2*t,p=f,d=s[h*f+e];for(;c=x?(p=y,d=x):v>=_?(p=g,d=v):(p=b,d=_):x>=_?(p=y,d=x):_>=v?(p=g,d=v):(p=b,d=_);for(var w=h*(u-1),k=h*p,M=0;Mr&&i[f+e]>c;--u,f-=o){for(var h=f,p=f+o,d=0;d=0&&i.push("lo=e[k+n]");t.indexOf("hi")>=0&&i.push("hi=e[k+o]");return r.push(n.replace("_",i.join()).replace("$",t)),Function.apply(void 0,r)};var n="for(var j=2*a,k=j*c,l=k,m=c,n=b,o=a+b,p=c;d>p;++p,k+=j){var _;if($)if(m===p)m+=1,l+=j;else{for(var s=0;j>s;++s){var t=e[k+s];e[k+s]=e[l],e[l++]=t}var u=f[p];f[p]=f[m],f[m++]=u}}return m"},{}],89:[function(t,e,r){"use strict";e.exports=function(t,e){e<=4*n?i(0,e-1,t):function t(e,r,f){var h=(r-e+1)/6|0,p=e+h,d=r-h,m=e+r>>1,g=m-h,v=m+h,y=p,x=g,b=m,_=v,w=d,k=e+1,M=r-1,A=0;c(y,x,f)&&(A=y,y=x,x=A);c(_,w,f)&&(A=_,_=w,w=A);c(y,b,f)&&(A=y,y=b,b=A);c(x,b,f)&&(A=x,x=b,b=A);c(y,_,f)&&(A=y,y=_,_=A);c(b,_,f)&&(A=b,b=_,_=A);c(x,w,f)&&(A=x,x=w,w=A);c(x,b,f)&&(A=x,x=b,b=A);c(_,w,f)&&(A=_,_=w,w=A);var T=f[2*x];var S=f[2*x+1];var E=f[2*_];var C=f[2*_+1];var L=2*y;var z=2*b;var O=2*w;var I=2*p;var P=2*m;var D=2*d;for(var R=0;R<2;++R){var B=f[L+R],F=f[z+R],N=f[O+R];f[I+R]=B,f[P+R]=F,f[D+R]=N}o(g,e,f);o(v,r,f);for(var j=k;j<=M;++j)if(u(j,T,S,f))j!==k&&a(j,k,f),++k;else if(!u(j,E,C,f))for(;;){if(u(M,E,C,f)){u(M,T,S,f)?(s(j,k,M,f),++k,--M):(a(j,M,f),--M);break}if(--Mt;){var c=r[l-2],u=r[l-1];if(cr[e+1])}function u(t,e,r,n){var i=n[t*=2];return i>>1;a(p,S);for(var E=0,C=0,k=0;k=o)d(c,u,C--,L=L-o|0);else if(L>=0)d(s,l,E--,L);else if(L<=-o){L=-L-o|0;for(var z=0;z>>1;a(p,E);for(var C=0,L=0,z=0,M=0;M>1==p[2*M+3]>>1&&(I=2,M+=1),O<0){for(var P=-(O>>1)-1,D=0;D>1)-1;0===I?d(s,l,C--,P):1===I?d(c,u,L--,P):2===I&&d(f,h,z--,P)}}},scanBipartite:function(t,e,r,n,i,c,u,f,h,g,v,y){var x=0,b=2*t,_=e,w=e+t,k=1,M=1;n?M=o:k=o;for(var A=i;A>>1;a(p,C);for(var L=0,A=0;A=o?(O=!n,T-=o):(O=!!n,T-=1),O)m(s,l,L++,T);else{var I=y[T],P=b*T,D=v[P+e+1],R=v[P+e+1+t];t:for(var B=0;B>>1;a(p,k);for(var M=0,x=0;x=o)s[M++]=b-o;else{var T=d[b-=1],S=g*b,E=h[S+e+1],C=h[S+e+1+t];t:for(var L=0;L=0;--L)if(s[L]===b){for(var P=L+1;P0&&s.length>a){s.warned=!0;var l=new Error("Possible EventEmitter memory leak detected. "+s.length+' "'+String(e)+'" listeners added. Use emitter.setMaxListeners() to increase limit.');l.name="MaxListenersExceededWarning",l.emitter=t,l.type=e,l.count=s.length,"object"==typeof console&&console.warn&&console.warn("%s: %s",l.name,l.message)}}else s=o[e]=r,++t._eventsCount;return t}function h(){if(!this.fired)switch(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:for(var t=new Array(arguments.length),e=0;e1&&(e=arguments[1]),e instanceof Error)throw e;var l=new Error('Unhandled "error" event. ('+e+")");throw l.context=e,l}if(!(r=o[t]))return!1;var c="function"==typeof r;switch(n=arguments.length){case 1:!function(t,e,r){if(e)t.call(r);else for(var n=t.length,i=g(t,n),a=0;a=0;o--)if(r[o]===e||r[o].listener===e){s=r[o].listener,a=o;break}if(a<0)return this;0===a?r.shift():function(t,e){for(var r=e,n=r+1,i=t.length;n=0;a--)this.removeListener(t,e[a]);return this},o.prototype.listeners=function(t){return d(this,t,!0)},o.prototype.rawListeners=function(t){return d(this,t,!1)},o.listenerCount=function(t,e){return"function"==typeof t.listenerCount?t.listenerCount(e):m.call(t,e)},o.prototype.listenerCount=m,o.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]}},{}],93:[function(t,e,r){"use strict";var n=t("base64-js"),i=t("ieee754");r.Buffer=s,r.SlowBuffer=function(t){+t!=t&&(t=0);return s.alloc(+t)},r.INSPECT_MAX_BYTES=50;var a=2147483647;function o(t){if(t>a)throw new RangeError('The value "'+t+'" is invalid for option "size"');var e=new Uint8Array(t);return e.__proto__=s.prototype,e}function s(t,e,r){if("number"==typeof t){if("string"==typeof e)throw new TypeError('The "string" argument must be of type string. Received type number');return u(t)}return l(t,e,r)}function l(t,e,r){if("string"==typeof t)return function(t,e){"string"==typeof e&&""!==e||(e="utf8");if(!s.isEncoding(e))throw new TypeError("Unknown encoding: "+e);var r=0|p(t,e),n=o(r),i=n.write(t,e);i!==r&&(n=n.slice(0,i));return n}(t,e);if(ArrayBuffer.isView(t))return f(t);if(null==t)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(j(t,ArrayBuffer)||t&&j(t.buffer,ArrayBuffer))return function(t,e,r){if(e<0||t.byteLength=a)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a.toString(16)+" bytes");return 0|t}function p(t,e){if(s.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||j(t,ArrayBuffer))return t.byteLength;if("string"!=typeof t)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);var r=t.length,n=arguments.length>2&&!0===arguments[2];if(!n&&0===r)return 0;for(var i=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":return B(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return F(t).length;default:if(i)return n?-1:B(t).length;e=(""+e).toLowerCase(),i=!0}}function d(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function m(t,e,r,n,i){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),V(r=+r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return-1;r=t.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof e&&(e=s.from(e,n)),s.isBuffer(e))return 0===e.length?-1:g(t,e,r,n,i);if("number"==typeof e)return e&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):g(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function g(t,e,r,n,i){var a,o=1,s=t.length,l=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;o=2,s/=2,l/=2,r/=2}function c(t,e){return 1===o?t[e]:t.readUInt16BE(e*o)}if(i){var u=-1;for(a=r;as&&(r=s-l),a=r;a>=0;a--){for(var f=!0,h=0;hi&&(n=i):n=i;var a=e.length;n>a/2&&(n=a/2);for(var o=0;o>8,i=r%256,a.push(i),a.push(n);return a}(e,t.length-r),t,r,n)}function k(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function M(t,e,r){r=Math.min(t.length,r);for(var n=[],i=e;i239?4:c>223?3:c>191?2:1;if(i+f<=r)switch(f){case 1:c<128&&(u=c);break;case 2:128==(192&(a=t[i+1]))&&(l=(31&c)<<6|63&a)>127&&(u=l);break;case 3:a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&(l=(15&c)<<12|(63&a)<<6|63&o)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&(l=(15&c)<<18|(63&a)<<12|(63&o)<<6|63&s)>65535&&l<1114112&&(u=l)}null===u?(u=65533,f=1):u>65535&&(u-=65536,n.push(u>>>10&1023|55296),u=56320|1023&u),n.push(u),i+=f}return function(t){var e=t.length;if(e<=A)return String.fromCharCode.apply(String,t);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return E(this,e,r);case"utf8":case"utf-8":return M(this,e,r);case"ascii":return T(this,e,r);case"latin1":case"binary":return S(this,e,r);case"base64":return k(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},s.prototype.toLocaleString=s.prototype.toString,s.prototype.equals=function(t){if(!s.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===s.compare(this,t)},s.prototype.inspect=function(){var t="",e=r.INSPECT_MAX_BYTES;return t=this.toString("hex",0,e).replace(/(.{2})/g,"$1 ").trim(),this.length>e&&(t+=" ... "),""},s.prototype.compare=function(t,e,r,n,i){if(j(t,Uint8Array)&&(t=s.from(t,t.offset,t.byteLength)),!s.isBuffer(t))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof t);if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),e<0||r>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&e>=r)return 0;if(n>=i)return-1;if(e>=r)return 1;if(this===t)return 0;for(var a=(i>>>=0)-(n>>>=0),o=(r>>>=0)-(e>>>=0),l=Math.min(a,o),c=this.slice(n,i),u=t.slice(e,r),f=0;f>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-e;if((void 0===r||r>i)&&(r=i),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var a=!1;;)switch(n){case"hex":return v(this,t,e,r);case"utf8":case"utf-8":return y(this,t,e,r);case"ascii":return x(this,t,e,r);case"latin1":case"binary":return b(this,t,e,r);case"base64":return _(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return w(this,t,e,r);default:if(a)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),a=!0}},s.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var A=4096;function T(t,e,r){var n="";r=Math.min(t.length,r);for(var i=e;in)&&(r=n);for(var i="",a=e;ar)throw new RangeError("Trying to access beyond buffer length")}function z(t,e,r,n,i,a){if(!s.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||et.length)throw new RangeError("Index out of range")}function O(t,e,r,n,i,a){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function I(t,e,r,n,a){return e=+e,r>>>=0,a||O(t,0,r,4),i.write(t,e,r,n,23,4),r+4}function P(t,e,r,n,a){return e=+e,r>>>=0,a||O(t,0,r,8),i.write(t,e,r,n,52,8),r+8}s.prototype.slice=function(t,e){var r=this.length;(t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e>>=0,e>>>=0,r||L(t,e,this.length);for(var n=this[t],i=1,a=0;++a>>=0,e>>>=0,r||L(t,e,this.length);for(var n=this[t+--e],i=1;e>0&&(i*=256);)n+=this[t+--e]*i;return n},s.prototype.readUInt8=function(t,e){return t>>>=0,e||L(t,1,this.length),this[t]},s.prototype.readUInt16LE=function(t,e){return t>>>=0,e||L(t,2,this.length),this[t]|this[t+1]<<8},s.prototype.readUInt16BE=function(t,e){return t>>>=0,e||L(t,2,this.length),this[t]<<8|this[t+1]},s.prototype.readUInt32LE=function(t,e){return t>>>=0,e||L(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},s.prototype.readUInt32BE=function(t,e){return t>>>=0,e||L(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},s.prototype.readIntLE=function(t,e,r){t>>>=0,e>>>=0,r||L(t,e,this.length);for(var n=this[t],i=1,a=0;++a=(i*=128)&&(n-=Math.pow(2,8*e)),n},s.prototype.readIntBE=function(t,e,r){t>>>=0,e>>>=0,r||L(t,e,this.length);for(var n=e,i=1,a=this[t+--n];n>0&&(i*=256);)a+=this[t+--n]*i;return a>=(i*=128)&&(a-=Math.pow(2,8*e)),a},s.prototype.readInt8=function(t,e){return t>>>=0,e||L(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},s.prototype.readInt16LE=function(t,e){t>>>=0,e||L(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},s.prototype.readInt16BE=function(t,e){t>>>=0,e||L(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},s.prototype.readInt32LE=function(t,e){return t>>>=0,e||L(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},s.prototype.readInt32BE=function(t,e){return t>>>=0,e||L(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},s.prototype.readFloatLE=function(t,e){return t>>>=0,e||L(t,4,this.length),i.read(this,t,!0,23,4)},s.prototype.readFloatBE=function(t,e){return t>>>=0,e||L(t,4,this.length),i.read(this,t,!1,23,4)},s.prototype.readDoubleLE=function(t,e){return t>>>=0,e||L(t,8,this.length),i.read(this,t,!0,52,8)},s.prototype.readDoubleBE=function(t,e){return t>>>=0,e||L(t,8,this.length),i.read(this,t,!1,52,8)},s.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e>>>=0,r>>>=0,n)||z(this,t,e,r,Math.pow(2,8*r)-1,0);var i=1,a=0;for(this[e]=255&t;++a>>=0,r>>>=0,n)||z(this,t,e,r,Math.pow(2,8*r)-1,0);var i=r-1,a=1;for(this[e+i]=255&t;--i>=0&&(a*=256);)this[e+i]=t/a&255;return e+r},s.prototype.writeUInt8=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,1,255,0),this[e]=255&t,e+1},s.prototype.writeUInt16LE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,2,65535,0),this[e]=255&t,this[e+1]=t>>>8,e+2},s.prototype.writeUInt16BE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=255&t,e+2},s.prototype.writeUInt32LE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t,e+4},s.prototype.writeUInt32BE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},s.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);z(this,t,e,r,i-1,-i)}var a=0,o=1,s=0;for(this[e]=255&t;++a>0)-s&255;return e+r},s.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);z(this,t,e,r,i-1,-i)}var a=r-1,o=1,s=0;for(this[e+a]=255&t;--a>=0&&(o*=256);)t<0&&0===s&&0!==this[e+a+1]&&(s=1),this[e+a]=(t/o>>0)-s&255;return e+r},s.prototype.writeInt8=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=255&t,e+1},s.prototype.writeInt16LE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,2,32767,-32768),this[e]=255&t,this[e+1]=t>>>8,e+2},s.prototype.writeInt16BE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=255&t,e+2},s.prototype.writeInt32LE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,4,2147483647,-2147483648),this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},s.prototype.writeInt32BE=function(t,e,r){return t=+t,e>>>=0,r||z(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},s.prototype.writeFloatLE=function(t,e,r){return I(this,t,e,!0,r)},s.prototype.writeFloatBE=function(t,e,r){return I(this,t,e,!1,r)},s.prototype.writeDoubleLE=function(t,e,r){return P(this,t,e,!0,r)},s.prototype.writeDoubleBE=function(t,e,r){return P(this,t,e,!1,r)},s.prototype.copy=function(t,e,r,n){if(!s.isBuffer(t))throw new TypeError("argument should be a Buffer");if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e=0;--a)t[a+e]=this[a+r];else Uint8Array.prototype.set.call(t,this.subarray(r,n),e);return i},s.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!s.isEncoding(n))throw new TypeError("Unknown encoding: "+n);if(1===t.length){var i=t.charCodeAt(0);("utf8"===n&&i<128||"latin1"===n)&&(t=i)}}else"number"==typeof t&&(t&=255);if(e<0||this.length>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(a=e;a55295&&r<57344){if(!i){if(r>56319){(e-=3)>-1&&a.push(239,191,189);continue}if(o+1===n){(e-=3)>-1&&a.push(239,191,189);continue}i=r;continue}if(r<56320){(e-=3)>-1&&a.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(e-=3)>-1&&a.push(239,191,189);if(i=null,r<128){if((e-=1)<0)break;a.push(r)}else if(r<2048){if((e-=2)<0)break;a.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;a.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;a.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return a}function F(t){return n.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(D,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function N(t,e,r,n){for(var i=0;i=e.length||i>=t.length);++i)e[i+r]=t[i];return i}function j(t,e){return t instanceof e||null!=t&&null!=t.constructor&&null!=t.constructor.name&&t.constructor.name===e.name}function V(t){return t!=t}},{"base64-js":62,ieee754:395}],94:[function(t,e,r){"use strict";var n=t("./lib/monotone"),i=t("./lib/triangulation"),a=t("./lib/delaunay"),o=t("./lib/filter");function s(t){return[Math.min(t[0],t[1]),Math.max(t[0],t[1])]}function l(t,e){return t[0]-e[0]||t[1]-e[1]}function c(t,e,r){return e in t?t[e]:r}e.exports=function(t,e,r){Array.isArray(e)?(r=r||{},e=e||[]):(r=e||{},e=[]);var u=!!c(r,"delaunay",!0),f=!!c(r,"interior",!0),h=!!c(r,"exterior",!0),p=!!c(r,"infinity",!1);if(!f&&!h||0===t.length)return[];var d=n(t,e);if(u||f!==h||p){for(var m=i(t.length,function(t){return t.map(s).sort(l)}(e)),g=0;g0;){for(var u=r.pop(),s=r.pop(),f=-1,h=-1,l=o[s],d=1;d=0||(e.flip(s,u),i(t,e,r,f,s,h),i(t,e,r,s,h,f),i(t,e,r,h,u,f),i(t,e,r,u,f,h)))}}},{"binary-search-bounds":99,"robust-in-sphere":484}],96:[function(t,e,r){"use strict";var n,i=t("binary-search-bounds");function a(t,e,r,n,i,a,o){this.cells=t,this.neighbor=e,this.flags=n,this.constraint=r,this.active=i,this.next=a,this.boundary=o}function o(t,e){return t[0]-e[0]||t[1]-e[1]||t[2]-e[2]}e.exports=function(t,e,r){var n=function(t,e){for(var r=t.cells(),n=r.length,i=0;i0||l.length>0;){for(;s.length>0;){var p=s.pop();if(c[p]!==-i){c[p]=i;u[p];for(var d=0;d<3;++d){var m=h[3*p+d];m>=0&&0===c[m]&&(f[3*p+d]?l.push(m):(s.push(m),c[m]=i))}}}var g=l;l=s,s=g,l.length=0,i=-i}var v=function(t,e,r){for(var n=0,i=0;i1&&i(r[h[p-2]],r[h[p-1]],a)>0;)t.push([h[p-1],h[p-2],o]),p-=1;h.length=p,h.push(o);var d=u.upperIds;for(p=d.length;p>1&&i(r[d[p-2]],r[d[p-1]],a)<0;)t.push([d[p-2],d[p-1],o]),p-=1;d.length=p,d.push(o)}}function p(t,e){var r;return(r=t.a[0]v[0]&&i.push(new c(v,g,s,f),new c(g,v,o,f))}i.sort(u);for(var y=i[0].a[0]-(1+Math.abs(i[0].a[0]))*Math.pow(2,-52),x=[new l([y,1],[y,0],-1,[],[],[],[])],b=[],f=0,_=i.length;f<_;++f){var w=i[f],k=w.type;k===a?h(b,x,t,w.a,w.idx):k===s?d(x,t,w):m(x,t,w)}return b}},{"binary-search-bounds":99,"robust-orientation":486}],98:[function(t,e,r){"use strict";var n=t("binary-search-bounds");function i(t,e){this.stars=t,this.edges=e}e.exports=function(t,e){for(var r=new Array(t),n=0;n=0}}(),a.removeTriangle=function(t,e,r){var n=this.stars;o(n[t],e,r),o(n[e],r,t),o(n[r],t,e)},a.addTriangle=function(t,e,r){var n=this.stars;n[t].push(e,r),n[e].push(r,t),n[r].push(t,e)},a.opposite=function(t,e){for(var r=this.stars[e],n=1,i=r.length;n>>1,x=a[m]"];return i?e.indexOf("c")<0?a.push(";if(x===y){return m}else if(x<=y){"):a.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){"):a.push(";if(",e,"){i=m;"),r?a.push("l=m+1}else{h=m-1}"):a.push("h=m-1}else{l=m+1}"),a.push("}"),i?a.push("return -1};"):a.push("return i};"),a.join("")}function i(t,e,r,i){return new Function([n("A","x"+t+"y",e,["y"],i),n("P","c(x,y)"+t+"0",e,["y","c"],i),"function dispatchBsearch",r,"(a,y,c,l,h){if(typeof(c)==='function'){return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)}else{return A(a,(c===void 0)?0:c|0,(l===void 0)?a.length-1:l|0,y)}}return dispatchBsearch",r].join(""))()}e.exports={ge:i(">=",!1,"GE"),gt:i(">",!1,"GT"),lt:i("<",!0,"LT"),le:i("<=",!0,"LE"),eq:i("-",!0,"EQ",!0)}},{}],100:[function(t,e,r){"use strict";e.exports=function(t){for(var e=1,r=1;rr?r:t:te?e:t}},{}],104:[function(t,e,r){"use strict";e.exports=function(t,e,r){var n;if(r){n=e;for(var i=new Array(e.length),a=0;ae[2]?1:0)}function v(t,e,r){if(0!==t.length){if(e)for(var n=0;n=0;--a){var x=e[u=(S=n[a])[0]],b=x[0],_=x[1],w=t[b],k=t[_];if((w[0]-k[0]||w[1]-k[1])<0){var M=b;b=_,_=M}x[0]=b;var A,T=x[1]=S[1];for(i&&(A=x[2]);a>0&&n[a-1][0]===u;){var S,E=(S=n[--a])[1];i?e.push([T,E,A]):e.push([T,E]),T=E}i?e.push([T,_,A]):e.push([T,_])}return h}(t,e,h,g,r));return v(e,y,r),!!y||(h.length>0||g.length>0)}},{"./lib/rat-seg-intersect":105,"big-rat":66,"big-rat/cmp":64,"big-rat/to-float":78,"box-intersect":84,nextafter:434,"rat-vec":469,"robust-segment-intersect":489,"union-find":523}],105:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var a=s(e,t),f=s(n,r),h=u(a,f);if(0===o(h))return null;var p=s(t,r),d=u(f,p),m=i(d,h),g=c(a,m);return l(t,g)};var n=t("big-rat/mul"),i=t("big-rat/div"),a=t("big-rat/sub"),o=t("big-rat/sign"),s=t("rat-vec/sub"),l=t("rat-vec/add"),c=t("rat-vec/muls");function u(t,e){return a(n(t[0],e[1]),n(t[1],e[0]))}},{"big-rat/div":65,"big-rat/mul":75,"big-rat/sign":76,"big-rat/sub":77,"rat-vec/add":468,"rat-vec/muls":470,"rat-vec/sub":471}],106:[function(t,e,r){"use strict";var n=t("clamp");function i(t,e){null==e&&(e=!0);var r=t[0],i=t[1],a=t[2],o=t[3];return null==o&&(o=e?1:255),e&&(r*=255,i*=255,a*=255,o*=255),16777216*(r=255&n(r,0,255))+((i=255&n(i,0,255))<<16)+((a=255&n(a,0,255))<<8)+(o=255&n(o,0,255))}e.exports=i,e.exports.to=i,e.exports.from=function(t,e){var r=(t=+t)>>>24,n=(16711680&t)>>>16,i=(65280&t)>>>8,a=255&t;return!1===e?[r,n,i,a]:[r/255,n/255,i/255,a/255]}},{clamp:103}],107:[function(t,e,r){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],108:[function(t,e,r){"use strict";var n=t("color-rgba"),i=t("clamp"),a=t("dtype");e.exports=function(t,e){"float"!==e&&e||(e="array"),"uint"===e&&(e="uint8"),"uint_clamped"===e&&(e="uint8_clamped");var r=new(a(e))(4),o="uint8"!==e&&"uint8_clamped"!==e;return t.length&&"string"!=typeof t||((t=n(t))[0]/=255,t[1]/=255,t[2]/=255),function(t){return t instanceof Uint8Array||t instanceof Uint8ClampedArray||!!(Array.isArray(t)&&(t[0]>1||0===t[0])&&(t[1]>1||0===t[1])&&(t[2]>1||0===t[2])&&(!t[3]||t[3]>1))}(t)?(r[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=null!=t[3]?t[3]:255,o&&(r[0]/=255,r[1]/=255,r[2]/=255,r[3]/=255),r):(o?(r[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=null!=t[3]?t[3]:1):(r[0]=i(Math.floor(255*t[0]),0,255),r[1]=i(Math.floor(255*t[1]),0,255),r[2]=i(Math.floor(255*t[2]),0,255),r[3]=null==t[3]?255:i(Math.floor(255*t[3]),0,255)),r)}},{clamp:103,"color-rgba":110,dtype:154}],109:[function(t,e,r){(function(r){"use strict";var n=t("color-name"),i=t("is-plain-obj"),a=t("defined");e.exports=function(t){var e,s,l=[],c=1;if("string"==typeof t)if(n[t])l=n[t].slice(),s="rgb";else if("transparent"===t)c=0,s="rgb",l=[0,0,0];else if(/^#[A-Fa-f0-9]+$/.test(t)){var u=t.slice(1),f=u.length,h=f<=4;c=1,h?(l=[parseInt(u[0]+u[0],16),parseInt(u[1]+u[1],16),parseInt(u[2]+u[2],16)],4===f&&(c=parseInt(u[3]+u[3],16)/255)):(l=[parseInt(u[0]+u[1],16),parseInt(u[2]+u[3],16),parseInt(u[4]+u[5],16)],8===f&&(c=parseInt(u[6]+u[7],16)/255)),l[0]||(l[0]=0),l[1]||(l[1]=0),l[2]||(l[2]=0),s="rgb"}else if(e=/^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\s*\(([^\)]*)\)/.exec(t)){var p=e[1],u=p.replace(/a$/,"");s=u;var f="cmyk"===u?4:"gray"===u?1:3;l=e[2].trim().split(/\s*,\s*/).map(function(t,e){if(/%$/.test(t))return e===f?parseFloat(t)/100:"rgb"===u?255*parseFloat(t)/100:parseFloat(t);if("h"===u[e]){if(/deg$/.test(t))return parseFloat(t);if(void 0!==o[t])return o[t]}return parseFloat(t)}),p===u&&l.push(1),c=void 0===l[f]?1:l[f],l=l.slice(0,f)}else t.length>10&&/[0-9](?:\s|\/)/.test(t)&&(l=t.match(/([0-9]+)/g).map(function(t){return parseFloat(t)}),s=t.match(/([a-z])/gi).join("").toLowerCase());else if(isNaN(t))if(i(t)){var d=a(t.r,t.red,t.R,null);null!==d?(s="rgb",l=[d,a(t.g,t.green,t.G),a(t.b,t.blue,t.B)]):(s="hsl",l=[a(t.h,t.hue,t.H),a(t.s,t.saturation,t.S),a(t.l,t.lightness,t.L,t.b,t.brightness)]),c=a(t.a,t.alpha,t.opacity,1),null!=t.opacity&&(c/=100)}else(Array.isArray(t)||r.ArrayBuffer&&ArrayBuffer.isView&&ArrayBuffer.isView(t))&&(l=[t[0],t[1],t[2]],s="rgb",c=4===t.length?t[3]:1);else s="rgb",l=[t>>>16,(65280&t)>>>8,255&t];return{space:s,values:l,alpha:c}};var o={red:0,orange:60,yellow:120,green:180,blue:240,purple:300}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"color-name":107,defined:149,"is-plain-obj":405}],110:[function(t,e,r){"use strict";var n=t("color-parse"),i=t("color-space/hsl"),a=t("clamp");e.exports=function(t){var e,r=n(t);return r.space?((e=Array(3))[0]=a(r.values[0],0,255),e[1]=a(r.values[1],0,255),e[2]=a(r.values[2],0,255),"h"===r.space[0]&&(e=i.rgb(e)),e.push(a(r.alpha,0,1)),e):[]}},{clamp:103,"color-parse":109,"color-space/hsl":111}],111:[function(t,e,r){"use strict";var n=t("./rgb");e.exports={name:"hsl",min:[0,0,0],max:[360,100,100],channel:["hue","saturation","lightness"],alias:["HSL"],rgb:function(t){var e,r,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0===s)return[a=255*l,a,a];e=2*l-(r=l<.5?l*(1+s):l+s-l*s),i=[0,0,0];for(var c=0;c<3;c++)(n=o+1/3*-(c-1))<0?n++:n>1&&n--,a=6*n<1?e+6*(r-e)*n:2*n<1?r:3*n<2?e+(r-e)*(2/3-n)*6:e,i[c]=255*a;return i}},n.hsl=function(t){var e,r,n=t[0]/255,i=t[1]/255,a=t[2]/255,o=Math.min(n,i,a),s=Math.max(n,i,a),l=s-o;return s===o?e=0:n===s?e=(i-a)/l:i===s?e=2+(a-n)/l:a===s&&(e=4+(n-i)/l),(e=Math.min(60*e,360))<0&&(e+=360),r=(o+s)/2,[e,100*(s===o?0:r<=.5?l/(s+o):l/(2-s-o)),100*r]}},{"./rgb":112}],112:[function(t,e,r){"use strict";e.exports={name:"rgb",min:[0,0,0],max:[255,255,255],channel:["red","green","blue"],alias:["RGB"]}},{}],113:[function(t,e,r){e.exports={jet:[{index:0,rgb:[0,0,131]},{index:.125,rgb:[0,60,170]},{index:.375,rgb:[5,255,255]},{index:.625,rgb:[255,255,0]},{index:.875,rgb:[250,0,0]},{index:1,rgb:[128,0,0]}],hsv:[{index:0,rgb:[255,0,0]},{index:.169,rgb:[253,255,2]},{index:.173,rgb:[247,255,2]},{index:.337,rgb:[0,252,4]},{index:.341,rgb:[0,252,10]},{index:.506,rgb:[1,249,255]},{index:.671,rgb:[2,0,253]},{index:.675,rgb:[8,0,253]},{index:.839,rgb:[255,0,251]},{index:.843,rgb:[255,0,245]},{index:1,rgb:[255,0,6]}],hot:[{index:0,rgb:[0,0,0]},{index:.3,rgb:[230,0,0]},{index:.6,rgb:[255,210,0]},{index:1,rgb:[255,255,255]}],cool:[{index:0,rgb:[0,255,255]},{index:1,rgb:[255,0,255]}],spring:[{index:0,rgb:[255,0,255]},{index:1,rgb:[255,255,0]}],summer:[{index:0,rgb:[0,128,102]},{index:1,rgb:[255,255,102]}],autumn:[{index:0,rgb:[255,0,0]},{index:1,rgb:[255,255,0]}],winter:[{index:0,rgb:[0,0,255]},{index:1,rgb:[0,255,128]}],bone:[{index:0,rgb:[0,0,0]},{index:.376,rgb:[84,84,116]},{index:.753,rgb:[169,200,200]},{index:1,rgb:[255,255,255]}],copper:[{index:0,rgb:[0,0,0]},{index:.804,rgb:[255,160,102]},{index:1,rgb:[255,199,127]}],greys:[{index:0,rgb:[0,0,0]},{index:1,rgb:[255,255,255]}],yignbu:[{index:0,rgb:[8,29,88]},{index:.125,rgb:[37,52,148]},{index:.25,rgb:[34,94,168]},{index:.375,rgb:[29,145,192]},{index:.5,rgb:[65,182,196]},{index:.625,rgb:[127,205,187]},{index:.75,rgb:[199,233,180]},{index:.875,rgb:[237,248,217]},{index:1,rgb:[255,255,217]}],greens:[{index:0,rgb:[0,68,27]},{index:.125,rgb:[0,109,44]},{index:.25,rgb:[35,139,69]},{index:.375,rgb:[65,171,93]},{index:.5,rgb:[116,196,118]},{index:.625,rgb:[161,217,155]},{index:.75,rgb:[199,233,192]},{index:.875,rgb:[229,245,224]},{index:1,rgb:[247,252,245]}],yiorrd:[{index:0,rgb:[128,0,38]},{index:.125,rgb:[189,0,38]},{index:.25,rgb:[227,26,28]},{index:.375,rgb:[252,78,42]},{index:.5,rgb:[253,141,60]},{index:.625,rgb:[254,178,76]},{index:.75,rgb:[254,217,118]},{index:.875,rgb:[255,237,160]},{index:1,rgb:[255,255,204]}],bluered:[{index:0,rgb:[0,0,255]},{index:1,rgb:[255,0,0]}],rdbu:[{index:0,rgb:[5,10,172]},{index:.35,rgb:[106,137,247]},{index:.5,rgb:[190,190,190]},{index:.6,rgb:[220,170,132]},{index:.7,rgb:[230,145,90]},{index:1,rgb:[178,10,28]}],picnic:[{index:0,rgb:[0,0,255]},{index:.1,rgb:[51,153,255]},{index:.2,rgb:[102,204,255]},{index:.3,rgb:[153,204,255]},{index:.4,rgb:[204,204,255]},{index:.5,rgb:[255,255,255]},{index:.6,rgb:[255,204,255]},{index:.7,rgb:[255,153,255]},{index:.8,rgb:[255,102,204]},{index:.9,rgb:[255,102,102]},{index:1,rgb:[255,0,0]}],rainbow:[{index:0,rgb:[150,0,90]},{index:.125,rgb:[0,0,200]},{index:.25,rgb:[0,25,255]},{index:.375,rgb:[0,152,255]},{index:.5,rgb:[44,255,150]},{index:.625,rgb:[151,255,0]},{index:.75,rgb:[255,234,0]},{index:.875,rgb:[255,111,0]},{index:1,rgb:[255,0,0]}],portland:[{index:0,rgb:[12,51,131]},{index:.25,rgb:[10,136,186]},{index:.5,rgb:[242,211,56]},{index:.75,rgb:[242,143,56]},{index:1,rgb:[217,30,30]}],blackbody:[{index:0,rgb:[0,0,0]},{index:.2,rgb:[230,0,0]},{index:.4,rgb:[230,210,0]},{index:.7,rgb:[255,255,255]},{index:1,rgb:[160,200,255]}],earth:[{index:0,rgb:[0,0,130]},{index:.1,rgb:[0,180,180]},{index:.2,rgb:[40,210,40]},{index:.4,rgb:[230,230,50]},{index:.6,rgb:[120,70,20]},{index:1,rgb:[255,255,255]}],electric:[{index:0,rgb:[0,0,0]},{index:.15,rgb:[30,0,100]},{index:.4,rgb:[120,0,100]},{index:.6,rgb:[160,90,0]},{index:.8,rgb:[230,200,0]},{index:1,rgb:[255,250,220]}],alpha:[{index:0,rgb:[255,255,255,0]},{index:1,rgb:[255,255,255,1]}],viridis:[{index:0,rgb:[68,1,84]},{index:.13,rgb:[71,44,122]},{index:.25,rgb:[59,81,139]},{index:.38,rgb:[44,113,142]},{index:.5,rgb:[33,144,141]},{index:.63,rgb:[39,173,129]},{index:.75,rgb:[92,200,99]},{index:.88,rgb:[170,220,50]},{index:1,rgb:[253,231,37]}],inferno:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[31,12,72]},{index:.25,rgb:[85,15,109]},{index:.38,rgb:[136,34,106]},{index:.5,rgb:[186,54,85]},{index:.63,rgb:[227,89,51]},{index:.75,rgb:[249,140,10]},{index:.88,rgb:[249,201,50]},{index:1,rgb:[252,255,164]}],magma:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[28,16,68]},{index:.25,rgb:[79,18,123]},{index:.38,rgb:[129,37,129]},{index:.5,rgb:[181,54,122]},{index:.63,rgb:[229,80,100]},{index:.75,rgb:[251,135,97]},{index:.88,rgb:[254,194,135]},{index:1,rgb:[252,253,191]}],plasma:[{index:0,rgb:[13,8,135]},{index:.13,rgb:[75,3,161]},{index:.25,rgb:[125,3,168]},{index:.38,rgb:[168,34,150]},{index:.5,rgb:[203,70,121]},{index:.63,rgb:[229,107,93]},{index:.75,rgb:[248,148,65]},{index:.88,rgb:[253,195,40]},{index:1,rgb:[240,249,33]}],warm:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[172,0,187]},{index:.25,rgb:[219,0,170]},{index:.38,rgb:[255,0,130]},{index:.5,rgb:[255,63,74]},{index:.63,rgb:[255,123,0]},{index:.75,rgb:[234,176,0]},{index:.88,rgb:[190,228,0]},{index:1,rgb:[147,255,0]}],cool:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[116,0,218]},{index:.25,rgb:[98,74,237]},{index:.38,rgb:[68,146,231]},{index:.5,rgb:[0,204,197]},{index:.63,rgb:[0,247,146]},{index:.75,rgb:[0,255,88]},{index:.88,rgb:[40,255,8]},{index:1,rgb:[147,255,0]}],"rainbow-soft":[{index:0,rgb:[125,0,179]},{index:.1,rgb:[199,0,180]},{index:.2,rgb:[255,0,121]},{index:.3,rgb:[255,108,0]},{index:.4,rgb:[222,194,0]},{index:.5,rgb:[150,255,0]},{index:.6,rgb:[0,255,55]},{index:.7,rgb:[0,246,150]},{index:.8,rgb:[50,167,222]},{index:.9,rgb:[103,51,235]},{index:1,rgb:[124,0,186]}],bathymetry:[{index:0,rgb:[40,26,44]},{index:.13,rgb:[59,49,90]},{index:.25,rgb:[64,76,139]},{index:.38,rgb:[63,110,151]},{index:.5,rgb:[72,142,158]},{index:.63,rgb:[85,174,163]},{index:.75,rgb:[120,206,163]},{index:.88,rgb:[187,230,172]},{index:1,rgb:[253,254,204]}],cdom:[{index:0,rgb:[47,15,62]},{index:.13,rgb:[87,23,86]},{index:.25,rgb:[130,28,99]},{index:.38,rgb:[171,41,96]},{index:.5,rgb:[206,67,86]},{index:.63,rgb:[230,106,84]},{index:.75,rgb:[242,149,103]},{index:.88,rgb:[249,193,135]},{index:1,rgb:[254,237,176]}],chlorophyll:[{index:0,rgb:[18,36,20]},{index:.13,rgb:[25,63,41]},{index:.25,rgb:[24,91,59]},{index:.38,rgb:[13,119,72]},{index:.5,rgb:[18,148,80]},{index:.63,rgb:[80,173,89]},{index:.75,rgb:[132,196,122]},{index:.88,rgb:[175,221,162]},{index:1,rgb:[215,249,208]}],density:[{index:0,rgb:[54,14,36]},{index:.13,rgb:[89,23,80]},{index:.25,rgb:[110,45,132]},{index:.38,rgb:[120,77,178]},{index:.5,rgb:[120,113,213]},{index:.63,rgb:[115,151,228]},{index:.75,rgb:[134,185,227]},{index:.88,rgb:[177,214,227]},{index:1,rgb:[230,241,241]}],"freesurface-blue":[{index:0,rgb:[30,4,110]},{index:.13,rgb:[47,14,176]},{index:.25,rgb:[41,45,236]},{index:.38,rgb:[25,99,212]},{index:.5,rgb:[68,131,200]},{index:.63,rgb:[114,156,197]},{index:.75,rgb:[157,181,203]},{index:.88,rgb:[200,208,216]},{index:1,rgb:[241,237,236]}],"freesurface-red":[{index:0,rgb:[60,9,18]},{index:.13,rgb:[100,17,27]},{index:.25,rgb:[142,20,29]},{index:.38,rgb:[177,43,27]},{index:.5,rgb:[192,87,63]},{index:.63,rgb:[205,125,105]},{index:.75,rgb:[216,162,148]},{index:.88,rgb:[227,199,193]},{index:1,rgb:[241,237,236]}],oxygen:[{index:0,rgb:[64,5,5]},{index:.13,rgb:[106,6,15]},{index:.25,rgb:[144,26,7]},{index:.38,rgb:[168,64,3]},{index:.5,rgb:[188,100,4]},{index:.63,rgb:[206,136,11]},{index:.75,rgb:[220,174,25]},{index:.88,rgb:[231,215,44]},{index:1,rgb:[248,254,105]}],par:[{index:0,rgb:[51,20,24]},{index:.13,rgb:[90,32,35]},{index:.25,rgb:[129,44,34]},{index:.38,rgb:[159,68,25]},{index:.5,rgb:[182,99,19]},{index:.63,rgb:[199,134,22]},{index:.75,rgb:[212,171,35]},{index:.88,rgb:[221,210,54]},{index:1,rgb:[225,253,75]}],phase:[{index:0,rgb:[145,105,18]},{index:.13,rgb:[184,71,38]},{index:.25,rgb:[186,58,115]},{index:.38,rgb:[160,71,185]},{index:.5,rgb:[110,97,218]},{index:.63,rgb:[50,123,164]},{index:.75,rgb:[31,131,110]},{index:.88,rgb:[77,129,34]},{index:1,rgb:[145,105,18]}],salinity:[{index:0,rgb:[42,24,108]},{index:.13,rgb:[33,50,162]},{index:.25,rgb:[15,90,145]},{index:.38,rgb:[40,118,137]},{index:.5,rgb:[59,146,135]},{index:.63,rgb:[79,175,126]},{index:.75,rgb:[120,203,104]},{index:.88,rgb:[193,221,100]},{index:1,rgb:[253,239,154]}],temperature:[{index:0,rgb:[4,35,51]},{index:.13,rgb:[23,51,122]},{index:.25,rgb:[85,59,157]},{index:.38,rgb:[129,79,143]},{index:.5,rgb:[175,95,130]},{index:.63,rgb:[222,112,101]},{index:.75,rgb:[249,146,66]},{index:.88,rgb:[249,196,65]},{index:1,rgb:[232,250,91]}],turbidity:[{index:0,rgb:[34,31,27]},{index:.13,rgb:[65,50,41]},{index:.25,rgb:[98,69,52]},{index:.38,rgb:[131,89,57]},{index:.5,rgb:[161,112,59]},{index:.63,rgb:[185,140,66]},{index:.75,rgb:[202,174,88]},{index:.88,rgb:[216,209,126]},{index:1,rgb:[233,246,171]}],"velocity-blue":[{index:0,rgb:[17,32,64]},{index:.13,rgb:[35,52,116]},{index:.25,rgb:[29,81,156]},{index:.38,rgb:[31,113,162]},{index:.5,rgb:[50,144,169]},{index:.63,rgb:[87,173,176]},{index:.75,rgb:[149,196,189]},{index:.88,rgb:[203,221,211]},{index:1,rgb:[254,251,230]}],"velocity-green":[{index:0,rgb:[23,35,19]},{index:.13,rgb:[24,64,38]},{index:.25,rgb:[11,95,45]},{index:.38,rgb:[39,123,35]},{index:.5,rgb:[95,146,12]},{index:.63,rgb:[152,165,18]},{index:.75,rgb:[201,186,69]},{index:.88,rgb:[233,216,137]},{index:1,rgb:[255,253,205]}],cubehelix:[{index:0,rgb:[0,0,0]},{index:.07,rgb:[22,5,59]},{index:.13,rgb:[60,4,105]},{index:.2,rgb:[109,1,135]},{index:.27,rgb:[161,0,147]},{index:.33,rgb:[210,2,142]},{index:.4,rgb:[251,11,123]},{index:.47,rgb:[255,29,97]},{index:.53,rgb:[255,54,69]},{index:.6,rgb:[255,85,46]},{index:.67,rgb:[255,120,34]},{index:.73,rgb:[255,157,37]},{index:.8,rgb:[241,191,57]},{index:.87,rgb:[224,220,93]},{index:.93,rgb:[218,241,142]},{index:1,rgb:[227,253,198]}]}},{}],114:[function(t,e,r){"use strict";var n=t("./colorScale"),i=t("lerp");function a(t){return[t[0]/255,t[1]/255,t[2]/255,t[3]]}function o(t){for(var e,r="#",n=0;n<3;++n)r+=("00"+(e=(e=t[n]).toString(16))).substr(e.length);return r}function s(t){return"rgba("+t.join(",")+")"}e.exports=function(t){var e,r,l,c,u,f,h,p,d,m;t||(t={});p=(t.nshades||72)-1,h=t.format||"hex",(f=t.colormap)||(f="jet");if("string"==typeof f){if(f=f.toLowerCase(),!n[f])throw Error(f+" not a supported colorscale");u=n[f]}else{if(!Array.isArray(f))throw Error("unsupported colormap option",f);u=f.slice()}if(u.length>p)throw new Error(f+" map requires nshades to be at least size "+u.length);d=Array.isArray(t.alpha)?2!==t.alpha.length?[1,1]:t.alpha.slice():"number"==typeof t.alpha?[t.alpha,t.alpha]:[1,1];e=u.map(function(t){return Math.round(t.index*p)}),d[0]=Math.min(Math.max(d[0],0),1),d[1]=Math.min(Math.max(d[1],0),1);var g=u.map(function(t,e){var r=u[e].index,n=u[e].rgb.slice();return 4===n.length&&n[3]>=0&&n[3]<=1?n:(n[3]=d[0]+(d[1]-d[0])*r,n)}),v=[];for(m=0;m0?-1:l(t,e,a)?-1:1:0===s?c>0?1:l(t,e,r)?1:-1:i(c-s)}var h=n(t,e,r);if(h>0)return o>0&&n(t,e,a)>0?1:-1;if(h<0)return o>0||n(t,e,a)>0?1:-1;var p=n(t,e,a);return p>0?1:l(t,e,r)?1:-1};var n=t("robust-orientation"),i=t("signum"),a=t("two-sum"),o=t("robust-product"),s=t("robust-sum");function l(t,e,r){var n=a(t[0],-e[0]),i=a(t[1],-e[1]),l=a(r[0],-e[0]),c=a(r[1],-e[1]),u=s(o(n,l),o(i,c));return u[u.length-1]>=0}},{"robust-orientation":486,"robust-product":487,"robust-sum":491,signum:492,"two-sum":521}],116:[function(t,e,r){e.exports=function(t,e){var r=t.length,a=t.length-e.length;if(a)return a;switch(r){case 0:return 0;case 1:return t[0]-e[0];case 2:return t[0]+t[1]-e[0]-e[1]||n(t[0],t[1])-n(e[0],e[1]);case 3:var o=t[0]+t[1],s=e[0]+e[1];if(a=o+t[2]-(s+e[2]))return a;var l=n(t[0],t[1]),c=n(e[0],e[1]);return n(l,t[2])-n(c,e[2])||n(l+t[2],o)-n(c+e[2],s);case 4:var u=t[0],f=t[1],h=t[2],p=t[3],d=e[0],m=e[1],g=e[2],v=e[3];return u+f+h+p-(d+m+g+v)||n(u,f,h,p)-n(d,m,g,v,d)||n(u+f,u+h,u+p,f+h,f+p,h+p)-n(d+m,d+g,d+v,m+g,m+v,g+v)||n(u+f+h,u+f+p,u+h+p,f+h+p)-n(d+m+g,d+m+v,d+g+v,m+g+v);default:for(var y=t.slice().sort(i),x=e.slice().sort(i),b=0;bt[r][0]&&(r=n);return er?[[r],[e]]:[[e]]}},{}],120:[function(t,e,r){"use strict";e.exports=function(t){var e=n(t),r=e.length;if(r<=2)return[];for(var i=new Array(r),a=e[r-1],o=0;o=e[l]&&(s+=1);a[o]=s}}return t}(o,r)}};var n=t("incremental-convex-hull"),i=t("affine-hull")},{"affine-hull":50,"incremental-convex-hull":396}],122:[function(t,e,r){e.exports={AFG:"afghan",ALA:"\\b\\wland",ALB:"albania",DZA:"algeria",ASM:"^(?=.*americ).*samoa",AND:"andorra",AGO:"angola",AIA:"anguill?a",ATA:"antarctica",ATG:"antigua",ARG:"argentin",ARM:"armenia",ABW:"^(?!.*bonaire).*\\baruba",AUS:"australia",AUT:"^(?!.*hungary).*austria|\\baustri.*\\bemp",AZE:"azerbaijan",BHS:"bahamas",BHR:"bahrain",BGD:"bangladesh|^(?=.*east).*paki?stan",BRB:"barbados",BLR:"belarus|byelo",BEL:"^(?!.*luxem).*belgium",BLZ:"belize|^(?=.*british).*honduras",BEN:"benin|dahome",BMU:"bermuda",BTN:"bhutan",BOL:"bolivia",BES:"^(?=.*bonaire).*eustatius|^(?=.*carib).*netherlands|\\bbes.?islands",BIH:"herzegovina|bosnia",BWA:"botswana|bechuana",BVT:"bouvet",BRA:"brazil",IOT:"british.?indian.?ocean",BRN:"brunei",BGR:"bulgaria",BFA:"burkina|\\bfaso|upper.?volta",BDI:"burundi",CPV:"verde",KHM:"cambodia|kampuchea|khmer",CMR:"cameroon",CAN:"canada",CYM:"cayman",CAF:"\\bcentral.african.republic",TCD:"\\bchad",CHL:"\\bchile",CHN:"^(?!.*\\bmac)(?!.*\\bhong)(?!.*\\btai)(?!.*\\brep).*china|^(?=.*peo)(?=.*rep).*china",CXR:"christmas",CCK:"\\bcocos|keeling",COL:"colombia",COM:"comoro",COG:"^(?!.*\\bdem)(?!.*\\bd[\\.]?r)(?!.*kinshasa)(?!.*zaire)(?!.*belg)(?!.*l.opoldville)(?!.*free).*\\bcongo",COK:"\\bcook",CRI:"costa.?rica",CIV:"ivoire|ivory",HRV:"croatia",CUB:"\\bcuba",CUW:"^(?!.*bonaire).*\\bcura(c|\xe7)ao",CYP:"cyprus",CSK:"czechoslovakia",CZE:"^(?=.*rep).*czech|czechia|bohemia",COD:"\\bdem.*congo|congo.*\\bdem|congo.*\\bd[\\.]?r|\\bd[\\.]?r.*congo|belgian.?congo|congo.?free.?state|kinshasa|zaire|l.opoldville|drc|droc|rdc",DNK:"denmark",DJI:"djibouti",DMA:"dominica(?!n)",DOM:"dominican.rep",ECU:"ecuador",EGY:"egypt",SLV:"el.?salvador",GNQ:"guine.*eq|eq.*guine|^(?=.*span).*guinea",ERI:"eritrea",EST:"estonia",ETH:"ethiopia|abyssinia",FLK:"falkland|malvinas",FRO:"faroe|faeroe",FJI:"fiji",FIN:"finland",FRA:"^(?!.*\\bdep)(?!.*martinique).*france|french.?republic|\\bgaul",GUF:"^(?=.*french).*guiana",PYF:"french.?polynesia|tahiti",ATF:"french.?southern",GAB:"gabon",GMB:"gambia",GEO:"^(?!.*south).*georgia",DDR:"german.?democratic.?republic|democratic.?republic.*germany|east.germany",DEU:"^(?!.*east).*germany|^(?=.*\\bfed.*\\brep).*german",GHA:"ghana|gold.?coast",GIB:"gibraltar",GRC:"greece|hellenic|hellas",GRL:"greenland",GRD:"grenada",GLP:"guadeloupe",GUM:"\\bguam",GTM:"guatemala",GGY:"guernsey",GIN:"^(?!.*eq)(?!.*span)(?!.*bissau)(?!.*portu)(?!.*new).*guinea",GNB:"bissau|^(?=.*portu).*guinea",GUY:"guyana|british.?guiana",HTI:"haiti",HMD:"heard.*mcdonald",VAT:"holy.?see|vatican|papal.?st",HND:"^(?!.*brit).*honduras",HKG:"hong.?kong",HUN:"^(?!.*austr).*hungary",ISL:"iceland",IND:"india(?!.*ocea)",IDN:"indonesia",IRN:"\\biran|persia",IRQ:"\\biraq|mesopotamia",IRL:"(^ireland)|(^republic.*ireland)",IMN:"^(?=.*isle).*\\bman",ISR:"israel",ITA:"italy",JAM:"jamaica",JPN:"japan",JEY:"jersey",JOR:"jordan",KAZ:"kazak",KEN:"kenya|british.?east.?africa|east.?africa.?prot",KIR:"kiribati",PRK:"^(?=.*democrat|people|north|d.*p.*.r).*\\bkorea|dprk|korea.*(d.*p.*r)",KWT:"kuwait",KGZ:"kyrgyz|kirghiz",LAO:"\\blaos?\\b",LVA:"latvia",LBN:"lebanon",LSO:"lesotho|basuto",LBR:"liberia",LBY:"libya",LIE:"liechtenstein",LTU:"lithuania",LUX:"^(?!.*belg).*luxem",MAC:"maca(o|u)",MDG:"madagascar|malagasy",MWI:"malawi|nyasa",MYS:"malaysia",MDV:"maldive",MLI:"\\bmali\\b",MLT:"\\bmalta",MHL:"marshall",MTQ:"martinique",MRT:"mauritania",MUS:"mauritius",MYT:"\\bmayotte",MEX:"\\bmexic",FSM:"fed.*micronesia|micronesia.*fed",MCO:"monaco",MNG:"mongolia",MNE:"^(?!.*serbia).*montenegro",MSR:"montserrat",MAR:"morocco|\\bmaroc",MOZ:"mozambique",MMR:"myanmar|burma",NAM:"namibia",NRU:"nauru",NPL:"nepal",NLD:"^(?!.*\\bant)(?!.*\\bcarib).*netherlands",ANT:"^(?=.*\\bant).*(nether|dutch)",NCL:"new.?caledonia",NZL:"new.?zealand",NIC:"nicaragua",NER:"\\bniger(?!ia)",NGA:"nigeria",NIU:"niue",NFK:"norfolk",MNP:"mariana",NOR:"norway",OMN:"\\boman|trucial",PAK:"^(?!.*east).*paki?stan",PLW:"palau",PSE:"palestin|\\bgaza|west.?bank",PAN:"panama",PNG:"papua|new.?guinea",PRY:"paraguay",PER:"peru",PHL:"philippines",PCN:"pitcairn",POL:"poland",PRT:"portugal",PRI:"puerto.?rico",QAT:"qatar",KOR:"^(?!.*d.*p.*r)(?!.*democrat)(?!.*people)(?!.*north).*\\bkorea(?!.*d.*p.*r)",MDA:"moldov|b(a|e)ssarabia",REU:"r(e|\xe9)union",ROU:"r(o|u|ou)mania",RUS:"\\brussia|soviet.?union|u\\.?s\\.?s\\.?r|socialist.?republics",RWA:"rwanda",BLM:"barth(e|\xe9)lemy",SHN:"helena",KNA:"kitts|\\bnevis",LCA:"\\blucia",MAF:"^(?=.*collectivity).*martin|^(?=.*france).*martin(?!ique)|^(?=.*french).*martin(?!ique)",SPM:"miquelon",VCT:"vincent",WSM:"^(?!.*amer).*samoa",SMR:"san.?marino",STP:"\\bs(a|\xe3)o.?tom(e|\xe9)",SAU:"\\bsa\\w*.?arabia",SEN:"senegal",SRB:"^(?!.*monte).*serbia",SYC:"seychell",SLE:"sierra",SGP:"singapore",SXM:"^(?!.*martin)(?!.*saba).*maarten",SVK:"^(?!.*cze).*slovak",SVN:"slovenia",SLB:"solomon",SOM:"somali",ZAF:"south.africa|s\\\\..?africa",SGS:"south.?georgia|sandwich",SSD:"\\bs\\w*.?sudan",ESP:"spain",LKA:"sri.?lanka|ceylon",SDN:"^(?!.*\\bs(?!u)).*sudan",SUR:"surinam|dutch.?guiana",SJM:"svalbard",SWZ:"swaziland",SWE:"sweden",CHE:"switz|swiss",SYR:"syria",TWN:"taiwan|taipei|formosa|^(?!.*peo)(?=.*rep).*china",TJK:"tajik",THA:"thailand|\\bsiam",MKD:"macedonia|fyrom",TLS:"^(?=.*leste).*timor|^(?=.*east).*timor",TGO:"togo",TKL:"tokelau",TON:"tonga",TTO:"trinidad|tobago",TUN:"tunisia",TUR:"turkey",TKM:"turkmen",TCA:"turks",TUV:"tuvalu",UGA:"uganda",UKR:"ukrain",ARE:"emirates|^u\\.?a\\.?e\\.?$|united.?arab.?em",GBR:"united.?kingdom|britain|^u\\.?k\\.?$",TZA:"tanzania",USA:"united.?states\\b(?!.*islands)|\\bu\\.?s\\.?a\\.?\\b|^\\s*u\\.?s\\.?\\b(?!.*islands)",UMI:"minor.?outlying.?is",URY:"uruguay",UZB:"uzbek",VUT:"vanuatu|new.?hebrides",VEN:"venezuela",VNM:"^(?!.*republic).*viet.?nam|^(?=.*socialist).*viet.?nam",VGB:"^(?=.*\\bu\\.?\\s?k).*virgin|^(?=.*brit).*virgin|^(?=.*kingdom).*virgin",VIR:"^(?=.*\\bu\\.?\\s?s).*virgin|^(?=.*states).*virgin",WLF:"futuna|wallis",ESH:"western.sahara",YEM:"^(?!.*arab)(?!.*north)(?!.*sana)(?!.*peo)(?!.*dem)(?!.*south)(?!.*aden)(?!.*\\bp\\.?d\\.?r).*yemen",YMD:"^(?=.*peo).*yemen|^(?!.*rep)(?=.*dem).*yemen|^(?=.*south).*yemen|^(?=.*aden).*yemen|^(?=.*\\bp\\.?d\\.?r).*yemen",YUG:"yugoslavia",ZMB:"zambia|northern.?rhodesia",EAZ:"zanzibar",ZWE:"zimbabwe|^(?!.*northern).*rhodesia"}},{}],123:[function(t,e,r){e.exports=["xx-small","x-small","small","medium","large","x-large","xx-large","larger","smaller"]},{}],124:[function(t,e,r){e.exports=["normal","condensed","semi-condensed","extra-condensed","ultra-condensed","expanded","semi-expanded","extra-expanded","ultra-expanded"]},{}],125:[function(t,e,r){e.exports=["normal","italic","oblique"]},{}],126:[function(t,e,r){e.exports=["normal","bold","bolder","lighter","100","200","300","400","500","600","700","800","900"]},{}],127:[function(t,e,r){"use strict";e.exports={parse:t("./parse"),stringify:t("./stringify")}},{"./parse":129,"./stringify":130}],128:[function(t,e,r){"use strict";var n=t("css-font-size-keywords");e.exports={isSize:function(t){return/^[\d\.]/.test(t)||-1!==t.indexOf("/")||-1!==n.indexOf(t)}}},{"css-font-size-keywords":123}],129:[function(t,e,r){"use strict";var n=t("unquote"),i=t("css-global-keywords"),a=t("css-system-font-keywords"),o=t("css-font-weight-keywords"),s=t("css-font-style-keywords"),l=t("css-font-stretch-keywords"),c=t("string-split-by"),u=t("./lib/util").isSize;e.exports=h;var f=h.cache={};function h(t){if("string"!=typeof t)throw new Error("Font argument must be a string.");if(f[t])return f[t];if(""===t)throw new Error("Cannot parse an empty string.");if(-1!==a.indexOf(t))return f[t]={system:t};for(var e,r={style:"normal",variant:"normal",weight:"normal",stretch:"normal",lineHeight:"normal",size:"1rem",family:["serif"]},h=c(t,/\s+/);e=h.shift();){if(-1!==i.indexOf(e))return["style","variant","weight","stretch"].forEach(function(t){r[t]=e}),f[t]=r;if(-1===s.indexOf(e))if("normal"!==e&&"small-caps"!==e)if(-1===l.indexOf(e)){if(-1===o.indexOf(e)){if(u(e)){var d=c(e,"/");if(r.size=d[0],null!=d[1]?r.lineHeight=p(d[1]):"/"===h[0]&&(h.shift(),r.lineHeight=p(h.shift())),!h.length)throw new Error("Missing required font-family.");return r.family=c(h.join(" "),/\s*,\s*/).map(n),f[t]=r}throw new Error("Unknown or unsupported font token: "+e)}r.weight=e}else r.stretch=e;else r.variant=e;else r.style=e}throw new Error("Missing required font-size.")}function p(t){var e=parseFloat(t);return e.toString()===t?e:t}},{"./lib/util":128,"css-font-stretch-keywords":124,"css-font-style-keywords":125,"css-font-weight-keywords":126,"css-global-keywords":131,"css-system-font-keywords":132,"string-split-by":505,unquote:525}],130:[function(t,e,r){"use strict";var n=t("pick-by-alias"),i=t("./lib/util").isSize,a=m(t("css-global-keywords")),o=m(t("css-system-font-keywords")),s=m(t("css-font-weight-keywords")),l=m(t("css-font-style-keywords")),c=m(t("css-font-stretch-keywords")),u={normal:1,"small-caps":1},f={serif:1,"sans-serif":1,monospace:1,cursive:1,fantasy:1,"system-ui":1},h="1rem",p="serif";function d(t,e){if(t&&!e[t]&&!a[t])throw Error("Unknown keyword `"+t+"`");return t}function m(t){for(var e={},r=0;r=0;--p)a[p]=c*t[p]+u*e[p]+f*r[p]+h*n[p];return a}return c*t+u*e+f*r+h*n},e.exports.derivative=function(t,e,r,n,i,a){var o=6*i*i-6*i,s=3*i*i-4*i+1,l=-6*i*i+6*i,c=3*i*i-2*i;if(t.length){a||(a=new Array(t.length));for(var u=t.length-1;u>=0;--u)a[u]=o*t[u]+s*e[u]+l*r[u]+c*n[u];return a}return o*t+s*e+l*r[u]+c*n}},{}],134:[function(t,e,r){"use strict";var n=t("./lib/thunk.js");function i(){this.argTypes=[],this.shimArgs=[],this.arrayArgs=[],this.arrayBlockIndices=[],this.scalarArgs=[],this.offsetArgs=[],this.offsetArgIndex=[],this.indexArgs=[],this.shapeArgs=[],this.funcName="",this.pre=null,this.body=null,this.post=null,this.debug=!1}e.exports=function(t){var e=new i;e.pre=t.pre,e.body=t.body,e.post=t.post;var r=t.args.slice(0);e.argTypes=r;for(var a=0;a0)throw new Error("cwise: pre() block may not reference array args");if(a0)throw new Error("cwise: post() block may not reference array args")}else if("scalar"===o)e.scalarArgs.push(a),e.shimArgs.push("scalar"+a);else if("index"===o){if(e.indexArgs.push(a),a0)throw new Error("cwise: pre() block may not reference array index");if(a0)throw new Error("cwise: post() block may not reference array index")}else if("shape"===o){if(e.shapeArgs.push(a),ar.length)throw new Error("cwise: Too many arguments in pre() block");if(e.body.args.length>r.length)throw new Error("cwise: Too many arguments in body() block");if(e.post.args.length>r.length)throw new Error("cwise: Too many arguments in post() block");return e.debug=!!t.printCode||!!t.debug,e.funcName=t.funcName||"cwise",e.blockSize=t.blockSize||64,n(e)}},{"./lib/thunk.js":136}],135:[function(t,e,r){"use strict";var n=t("uniq");function i(t,e,r){var n,i,a=t.length,o=e.arrayArgs.length,s=e.indexArgs.length>0,l=[],c=[],u=0,f=0;for(n=0;n0&&l.push("var "+c.join(",")),n=a-1;n>=0;--n)u=t[n],l.push(["for(i",n,"=0;i",n,"0&&l.push(["index[",f,"]-=s",f].join("")),l.push(["++index[",u,"]"].join(""))),l.push("}")}return l.join("\n")}function a(t,e,r){for(var n=t.body,i=[],a=[],o=0;o0&&y.push("shape=SS.slice(0)"),t.indexArgs.length>0){var x=new Array(r);for(l=0;l0&&v.push("var "+y.join(",")),l=0;l3&&v.push(a(t.pre,t,s));var k=a(t.body,t,s),M=function(t){for(var e=0,r=t[0].length;e0,c=[],u=0;u0;){"].join("")),c.push(["if(j",u,"<",s,"){"].join("")),c.push(["s",e[u],"=j",u].join("")),c.push(["j",u,"=0"].join("")),c.push(["}else{s",e[u],"=",s].join("")),c.push(["j",u,"-=",s,"}"].join("")),l&&c.push(["index[",e[u],"]=j",u].join(""));for(u=0;u3&&v.push(a(t.post,t,s)),t.debug&&console.log("-----Generated cwise routine for ",e,":\n"+v.join("\n")+"\n----------");var A=[t.funcName||"unnamed","_cwise_loop_",o[0].join("s"),"m",M,function(t){for(var e=new Array(t.length),r=!0,n=0;n0&&(r=r&&e[n]===e[n-1])}return r?e[0]:e.join("")}(s)].join("");return new Function(["function ",A,"(",g.join(","),"){",v.join("\n"),"} return ",A].join(""))()}},{uniq:524}],136:[function(t,e,r){"use strict";var n=t("./compile.js");e.exports=function(t){var e=["'use strict'","var CACHED={}"],r=[],i=t.funcName+"_cwise_thunk";e.push(["return function ",i,"(",t.shimArgs.join(","),"){"].join(""));for(var a=[],o=[],s=[["array",t.arrayArgs[0],".shape.slice(",Math.max(0,t.arrayBlockIndices[0]),t.arrayBlockIndices[0]<0?","+t.arrayBlockIndices[0]+")":")"].join("")],l=[],c=[],u=0;u0&&(l.push("array"+t.arrayArgs[0]+".shape.length===array"+f+".shape.length+"+(Math.abs(t.arrayBlockIndices[0])-Math.abs(t.arrayBlockIndices[u]))),c.push("array"+t.arrayArgs[0]+".shape[shapeIndex+"+Math.max(0,t.arrayBlockIndices[0])+"]===array"+f+".shape[shapeIndex+"+Math.max(0,t.arrayBlockIndices[u])+"]"))}for(t.arrayArgs.length>1&&(e.push("if (!("+l.join(" && ")+")) throw new Error('cwise: Arrays do not all have the same dimensionality!')"),e.push("for(var shapeIndex=array"+t.arrayArgs[0]+".shape.length-"+Math.abs(t.arrayBlockIndices[0])+"; shapeIndex--\x3e0;) {"),e.push("if (!("+c.join(" && ")+")) throw new Error('cwise: Arrays do not all have the same shape!')"),e.push("}")),u=0;ue?1:t>=e?0:NaN}function r(t){var r;return 1===t.length&&(r=t,t=function(t,n){return e(r(t),n)}),{left:function(e,r,n,i){for(null==n&&(n=0),null==i&&(i=e.length);n>>1;t(e[a],r)<0?n=a+1:i=a}return n},right:function(e,r,n,i){for(null==n&&(n=0),null==i&&(i=e.length);n>>1;t(e[a],r)>0?i=a:n=a+1}return n}}}var n=r(e),i=n.right,a=n.left;function o(t,e){return[t,e]}function s(t){return null===t?NaN:+t}function l(t,e){var r,n,i=t.length,a=0,o=-1,l=0,c=0;if(null==e)for(;++o1)return c/(a-1)}function c(t,e){var r=l(t,e);return r?Math.sqrt(r):r}function u(t,e){var r,n,i,a=t.length,o=-1;if(null==e){for(;++o=r)for(n=i=r;++or&&(n=r),i=r)for(n=i=r;++or&&(n=r),i=0?(a>=v?10:a>=y?5:a>=x?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=v?10:a>=y?5:a>=x?2:1)}function _(t,e,r){var n=Math.abs(e-t)/Math.max(0,r),i=Math.pow(10,Math.floor(Math.log(n)/Math.LN10)),a=n/i;return a>=v?i*=10:a>=y?i*=5:a>=x&&(i*=2),e=1)return+r(t[n-1],n-1,t);var n,i=(n-1)*e,a=Math.floor(i),o=+r(t[a],a,t);return o+(+r(t[a+1],a+1,t)-o)*(i-a)}}function M(t,e){var r,n,i=t.length,a=-1;if(null==e){for(;++a=r)for(n=r;++ar&&(n=r)}else for(;++a=r)for(n=r;++ar&&(n=r);return n}function A(t){if(!(i=t.length))return[];for(var e=-1,r=M(t,T),n=new Array(r);++et?1:e>=t?0:NaN},t.deviation=c,t.extent=u,t.histogram=function(){var t=m,e=u,r=w;function n(n){var a,o,s=n.length,l=new Array(s);for(a=0;af;)h.pop(),--p;var d,m=new Array(p+1);for(a=0;a<=p;++a)(d=m[a]=[]).x0=a>0?h[a-1]:u,d.x1=a=r)for(n=r;++an&&(n=r)}else for(;++a=r)for(n=r;++an&&(n=r);return n},t.mean=function(t,e){var r,n=t.length,i=n,a=-1,o=0;if(null==e)for(;++a=0;)for(e=(n=t[i]).length;--e>=0;)r[--o]=n[e];return r},t.min=M,t.pairs=function(t,e){null==e&&(e=o);for(var r=0,n=t.length-1,i=t[0],a=new Array(n<0?0:n);r0)return[t];if((n=e0)for(t=Math.ceil(t/o),e=Math.floor(e/o),a=new Array(i=Math.ceil(e-t+1));++s=l.length)return null!=t&&n.sort(t),null!=e?e(n):n;for(var s,c,f,h=-1,p=n.length,d=l[i++],m=r(),g=a();++hl.length)return r;var i,a=c[n-1];return null!=e&&n>=l.length?i=r.entries():(i=[],r.each(function(e,r){i.push({key:r,values:t(e,n)})})),null!=a?i.sort(function(t,e){return a(t.key,e.key)}):i}(u(t,0,a,o),0)},key:function(t){return l.push(t),s},sortKeys:function(t){return c[l.length-1]=t,s},sortValues:function(e){return t=e,s},rollup:function(t){return e=t,s}}},t.set=c,t.map=r,t.keys=function(t){var e=[];for(var r in t)e.push(r);return e},t.values=function(t){var e=[];for(var r in t)e.push(t[r]);return e},t.entries=function(t){var e=[];for(var r in t)e.push({key:r,value:t[r]});return e},Object.defineProperty(t,"__esModule",{value:!0})}("object"==typeof r&&"undefined"!=typeof e?r:n.d3=n.d3||{})},{}],142:[function(t,e,r){var n;n=this,function(t){"use strict";function e(t,e,r){t.prototype=e.prototype=r,r.constructor=t}function r(t,e){var r=Object.create(t.prototype);for(var n in e)r[n]=e[n];return r}function n(){}var i="\\s*([+-]?\\d+)\\s*",a="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",o="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",s=/^#([0-9a-f]{3})$/,l=/^#([0-9a-f]{6})$/,c=new RegExp("^rgb\\("+[i,i,i]+"\\)$"),u=new RegExp("^rgb\\("+[o,o,o]+"\\)$"),f=new RegExp("^rgba\\("+[i,i,i,a]+"\\)$"),h=new RegExp("^rgba\\("+[o,o,o,a]+"\\)$"),p=new RegExp("^hsl\\("+[a,o,o]+"\\)$"),d=new RegExp("^hsla\\("+[a,o,o,a]+"\\)$"),m={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function g(t){var e;return t=(t+"").trim().toLowerCase(),(e=s.exec(t))?new _((e=parseInt(e[1],16))>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):(e=l.exec(t))?v(parseInt(e[1],16)):(e=c.exec(t))?new _(e[1],e[2],e[3],1):(e=u.exec(t))?new _(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=f.exec(t))?y(e[1],e[2],e[3],e[4]):(e=h.exec(t))?y(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=p.exec(t))?k(e[1],e[2]/100,e[3]/100,1):(e=d.exec(t))?k(e[1],e[2]/100,e[3]/100,e[4]):m.hasOwnProperty(t)?v(m[t]):"transparent"===t?new _(NaN,NaN,NaN,0):null}function v(t){return new _(t>>16&255,t>>8&255,255&t,1)}function y(t,e,r,n){return n<=0&&(t=e=r=NaN),new _(t,e,r,n)}function x(t){return t instanceof n||(t=g(t)),t?new _((t=t.rgb()).r,t.g,t.b,t.opacity):new _}function b(t,e,r,n){return 1===arguments.length?x(t):new _(t,e,r,null==n?1:n)}function _(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}function w(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function k(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new A(t,e,r,n)}function M(t,e,r,i){return 1===arguments.length?function(t){if(t instanceof A)return new A(t.h,t.s,t.l,t.opacity);if(t instanceof n||(t=g(t)),!t)return new A;if(t instanceof A)return t;var e=(t=t.rgb()).r/255,r=t.g/255,i=t.b/255,a=Math.min(e,r,i),o=Math.max(e,r,i),s=NaN,l=o-a,c=(o+a)/2;return l?(s=e===o?(r-i)/l+6*(r0&&c<1?0:s,new A(s,l,c,t.opacity)}(t):new A(t,e,r,null==i?1:i)}function A(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}function T(t,e,r){return 255*(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)}e(n,g,{displayable:function(){return this.rgb().displayable()},hex:function(){return this.rgb().hex()},toString:function(){return this.rgb()+""}}),e(_,b,r(n,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new _(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new _(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},hex:function(){return"#"+w(this.r)+w(this.g)+w(this.b)},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),e(A,M,r(n,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new A(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new A(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,i=2*r-n;return new _(T(t>=240?t-240:t+120,i,n),T(t,i,n),T(t<120?t+240:t-120,i,n),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var S=Math.PI/180,E=180/Math.PI,C=.96422,L=1,z=.82521,O=4/29,I=6/29,P=3*I*I,D=I*I*I;function R(t){if(t instanceof F)return new F(t.l,t.a,t.b,t.opacity);if(t instanceof G){if(isNaN(t.h))return new F(t.l,0,0,t.opacity);var e=t.h*S;return new F(t.l,Math.cos(e)*t.c,Math.sin(e)*t.c,t.opacity)}t instanceof _||(t=x(t));var r,n,i=U(t.r),a=U(t.g),o=U(t.b),s=N((.2225045*i+.7168786*a+.0606169*o)/L);return i===a&&a===o?r=n=s:(r=N((.4360747*i+.3850649*a+.1430804*o)/C),n=N((.0139322*i+.0971045*a+.7141733*o)/z)),new F(116*s-16,500*(r-s),200*(s-n),t.opacity)}function B(t,e,r,n){return 1===arguments.length?R(t):new F(t,e,r,null==n?1:n)}function F(t,e,r,n){this.l=+t,this.a=+e,this.b=+r,this.opacity=+n}function N(t){return t>D?Math.pow(t,1/3):t/P+O}function j(t){return t>I?t*t*t:P*(t-O)}function V(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function U(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function q(t){if(t instanceof G)return new G(t.h,t.c,t.l,t.opacity);if(t instanceof F||(t=R(t)),0===t.a&&0===t.b)return new G(NaN,0,t.l,t.opacity);var e=Math.atan2(t.b,t.a)*E;return new G(e<0?e+360:e,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function H(t,e,r,n){return 1===arguments.length?q(t):new G(t,e,r,null==n?1:n)}function G(t,e,r,n){this.h=+t,this.c=+e,this.l=+r,this.opacity=+n}e(F,B,r(n,{brighter:function(t){return new F(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new F(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,r=isNaN(this.b)?t:t-this.b/200;return new _(V(3.1338561*(e=C*j(e))-1.6168667*(t=L*j(t))-.4906146*(r=z*j(r))),V(-.9787684*e+1.9161415*t+.033454*r),V(.0719453*e-.2289914*t+1.4052427*r),this.opacity)}})),e(G,H,r(n,{brighter:function(t){return new G(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new G(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return R(this).rgb()}}));var W=-.14861,Y=1.78277,X=-.29227,Z=-.90649,$=1.97294,J=$*Z,K=$*Y,Q=Y*X-Z*W;function tt(t,e,r,n){return 1===arguments.length?function(t){if(t instanceof et)return new et(t.h,t.s,t.l,t.opacity);t instanceof _||(t=x(t));var e=t.r/255,r=t.g/255,n=t.b/255,i=(Q*n+J*e-K*r)/(Q+J-K),a=n-i,o=($*(r-i)-X*a)/Z,s=Math.sqrt(o*o+a*a)/($*i*(1-i)),l=s?Math.atan2(o,a)*E-120:NaN;return new et(l<0?l+360:l,s,i,t.opacity)}(t):new et(t,e,r,null==n?1:n)}function et(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}e(et,tt,r(n,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new et(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new et(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*S,e=+this.l,r=isNaN(this.s)?0:this.s*e*(1-e),n=Math.cos(t),i=Math.sin(t);return new _(255*(e+r*(W*n+Y*i)),255*(e+r*(X*n+Z*i)),255*(e+r*($*n)),this.opacity)}})),t.color=g,t.rgb=b,t.hsl=M,t.lab=B,t.hcl=H,t.lch=function(t,e,r,n){return 1===arguments.length?q(t):new G(r,e,t,null==n?1:n)},t.gray=function(t,e){return new F(t,0,0,null==e?1:e)},t.cubehelix=tt,Object.defineProperty(t,"__esModule",{value:!0})}("object"==typeof r&&"undefined"!=typeof e?r:n.d3=n.d3||{})},{}],143:[function(t,e,r){var n;n=this,function(t){"use strict";var e={value:function(){}};function r(){for(var t,e=0,r=arguments.length,i={};e=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})),l=-1,c=s.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++l0)for(var r,n,i=new Array(r),a=0;ah+c||np+c||au.index){var f=h-s.x-s.vx,g=p-s.y-s.vy,v=f*f+g*g;vt.r&&(t.r=t[e].r)}function h(){if(r){var e,i,a=r.length;for(n=new Array(a),e=0;e=c)){(t.data!==r||t.next)&&(0===f&&(d+=(f=o())*f),0===h&&(d+=(h=o())*h),d1?(null==r?u.remove(t):u.set(t,y(r)),e):u.get(t)},find:function(e,r,n){var i,a,o,s,l,c=0,u=t.length;for(null==n?n=1/0:n*=n,c=0;c1?(h.on(t,r),e):h.on(t)}}},t.forceX=function(t){var e,r,n,i=a(.1);function o(t){for(var i,a=0,o=e.length;a=1?(n=1,e-1):Math.floor(n*e),a=t[i],o=t[i+1],s=i>0?t[i-1]:2*a-o,l=i180||r<-180?r-360*Math.round(r/360):r):a(isNaN(t)?e:t)}function l(t){return 1==(t=+t)?c:function(e,r){return r-e?function(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}(e,r,t):a(isNaN(e)?r:e)}}function c(t,e){var r=e-t;return r?o(t,r):a(isNaN(t)?e:t)}var u=function t(r){var n=l(r);function i(t,r){var i=n((t=e.rgb(t)).r,(r=e.rgb(r)).r),a=n(t.g,r.g),o=n(t.b,r.b),s=c(t.opacity,r.opacity);return function(e){return t.r=i(e),t.g=a(e),t.b=o(e),t.opacity=s(e),t+""}}return i.gamma=t,i}(1);function f(t){return function(r){var n,i,a=r.length,o=new Array(a),s=new Array(a),l=new Array(a);for(n=0;na&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(r=r[0])===(n=n[0])?s[o]?s[o]+=n:s[++o]=n:(s[++o]=null,l.push({i:o,x:g(r,n)})),a=x.lastIndex;return a180?e+=360:e-t>180&&(t+=360),a.push({i:r.push(i(r)+"rotate(",null,n)-2,x:g(t,e)})):e&&r.push(i(r)+"rotate("+e+n)}(a.rotate,o.rotate,s,l),function(t,e,r,a){t!==e?a.push({i:r.push(i(r)+"skewX(",null,n)-2,x:g(t,e)}):e&&r.push(i(r)+"skewX("+e+n)}(a.skewX,o.skewX,s,l),function(t,e,r,n,a,o){if(t!==r||e!==n){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:g(t,r)},{i:s-2,x:g(e,n)})}else 1===r&&1===n||a.push(i(a)+"scale("+r+","+n+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,l),a=o=null,function(t){for(var e,r=-1,n=l.length;++r=(a=(m+v)/2))?m=a:v=a,(u=r>=(o=(g+y)/2))?g=o:y=o,i=p,!(p=p[f=u<<1|c]))return i[f]=d,t;if(s=+t._x.call(null,p.data),l=+t._y.call(null,p.data),e===s&&r===l)return d.next=p,i?i[f]=d:t._root=d,t;do{i=i?i[f]=new Array(4):t._root=new Array(4),(c=e>=(a=(m+v)/2))?m=a:v=a,(u=r>=(o=(g+y)/2))?g=o:y=o}while((f=u<<1|c)==(h=(l>=o)<<1|s>=a));return i[h]=p,i[f]=d,t}var r=function(t,e,r,n,i){this.node=t,this.x0=e,this.y0=r,this.x1=n,this.y1=i};function n(t){return t[0]}function i(t){return t[1]}function a(t,e,r){var a=new o(null==e?n:e,null==r?i:r,NaN,NaN,NaN,NaN);return null==t?a:a.addAll(t)}function o(t,e,r,n,i,a){this._x=t,this._y=e,this._x0=r,this._y0=n,this._x1=i,this._y1=a,this._root=void 0}function s(t){for(var e={data:t.data},r=e;t=t.next;)r=r.next={data:t.data};return e}var l=a.prototype=o.prototype;l.copy=function(){var t,e,r=new o(this._x,this._y,this._x0,this._y0,this._x1,this._y1),n=this._root;if(!n)return r;if(!n.length)return r._root=s(n),r;for(t=[{source:n,target:r._root=new Array(4)}];n=t.pop();)for(var i=0;i<4;++i)(e=n.source[i])&&(e.length?t.push({source:e,target:n.target[i]=new Array(4)}):n.target[i]=s(e));return r},l.add=function(t){var r=+this._x.call(null,t),n=+this._y.call(null,t);return e(this.cover(r,n),r,n,t)},l.addAll=function(t){var r,n,i,a,o=t.length,s=new Array(o),l=new Array(o),c=1/0,u=1/0,f=-1/0,h=-1/0;for(n=0;nf&&(f=i),ah&&(h=a));for(ft||t>i||n>e||e>a))return this;var o,s,l=i-r,c=this._root;switch(s=(e<(n+a)/2)<<1|t<(r+i)/2){case 0:do{(o=new Array(4))[s]=c,c=o}while(a=n+(l*=2),t>(i=r+l)||e>a);break;case 1:do{(o=new Array(4))[s]=c,c=o}while(a=n+(l*=2),(r=i-l)>t||e>a);break;case 2:do{(o=new Array(4))[s]=c,c=o}while(n=a-(l*=2),t>(i=r+l)||n>e);break;case 3:do{(o=new Array(4))[s]=c,c=o}while(n=a-(l*=2),(r=i-l)>t||n>e)}this._root&&this._root.length&&(this._root=c)}return this._x0=r,this._y0=n,this._x1=i,this._y1=a,this},l.data=function(){var t=[];return this.visit(function(e){if(!e.length)do{t.push(e.data)}while(e=e.next)}),t},l.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},l.find=function(t,e,n){var i,a,o,s,l,c,u,f=this._x0,h=this._y0,p=this._x1,d=this._y1,m=[],g=this._root;for(g&&m.push(new r(g,f,h,p,d)),null==n?n=1/0:(f=t-n,h=e-n,p=t+n,d=e+n,n*=n);c=m.pop();)if(!(!(g=c.node)||(a=c.x0)>p||(o=c.y0)>d||(s=c.x1)=y)<<1|t>=v)&&(c=m[m.length-1],m[m.length-1]=m[m.length-1-u],m[m.length-1-u]=c)}else{var x=t-+this._x.call(null,g.data),b=e-+this._y.call(null,g.data),_=x*x+b*b;if(_=(s=(d+g)/2))?d=s:g=s,(u=o>=(l=(m+v)/2))?m=l:v=l,e=p,!(p=p[f=u<<1|c]))return this;if(!p.length)break;(e[f+1&3]||e[f+2&3]||e[f+3&3])&&(r=e,h=f)}for(;p.data!==t;)if(n=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,n?(i?n.next=i:delete n.next,this):e?(i?e[f]=i:delete e[f],(p=e[0]||e[1]||e[2]||e[3])&&p===(e[3]||e[2]||e[1]||e[0])&&!p.length&&(r?r[h]=p:this._root=p),this):(this._root=i,this)},l.removeAll=function(t){for(var e=0,r=t.length;e=0&&r._call.call(null,t),r=r._next;--n}function v(){l=(s=u.now())+c,n=i=0;try{g()}finally{n=0,function(){var t,n,i=e,a=1/0;for(;i;)i._call?(a>i._time&&(a=i._time),t=i,i=i._next):(n=i._next,i._next=null,i=t?t._next=n:e=n);r=t,x(a)}(),l=0}}function y(){var t=u.now(),e=t-s;e>o&&(c-=e,s=t)}function x(t){n||(i&&(i=clearTimeout(i)),t-l>24?(t<1/0&&(i=setTimeout(v,t-u.now()-c)),a&&(a=clearInterval(a))):(a||(s=u.now(),a=setInterval(y,o)),n=1,f(v)))}d.prototype=m.prototype={constructor:d,restart:function(t,n,i){if("function"!=typeof t)throw new TypeError("callback is not a function");i=(null==i?h():+i)+(null==n?0:+n),this._next||r===this||(r?r._next=this:e=this,r=this),this._call=t,this._time=i,x()},stop:function(){this._call&&(this._call=null,this._time=1/0,x())}};t.now=h,t.timer=m,t.timerFlush=g,t.timeout=function(t,e,r){var n=new d;return e=null==e?0:+e,n.restart(function(r){n.stop(),t(r+e)},e,r),n},t.interval=function(t,e,r){var n=new d,i=e;return null==e?(n.restart(t,e,r),n):(e=+e,r=null==r?h():+r,n.restart(function a(o){o+=i,n.restart(a,i+=e,r),t(o)},e,r),n)},Object.defineProperty(t,"__esModule",{value:!0})}("object"==typeof r&&"undefined"!=typeof e?r:n.d3=n.d3||{})},{}],148:[function(t,e,r){!function(){var t={version:"3.5.17"},r=[].slice,n=function(t){return r.call(t)},i=this.document;function a(t){return t&&(t.ownerDocument||t.document||t).documentElement}function o(t){return t&&(t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView)}if(i)try{n(i.documentElement.childNodes)[0].nodeType}catch(t){n=function(t){for(var e=t.length,r=new Array(e);e--;)r[e]=t[e];return r}}if(Date.now||(Date.now=function(){return+new Date}),i)try{i.createElement("DIV").style.setProperty("opacity",0,"")}catch(t){var s=this.Element.prototype,l=s.setAttribute,c=s.setAttributeNS,u=this.CSSStyleDeclaration.prototype,f=u.setProperty;s.setAttribute=function(t,e){l.call(this,t,e+"")},s.setAttributeNS=function(t,e,r){c.call(this,t,e,r+"")},u.setProperty=function(t,e,r){f.call(this,t,e+"",r)}}function h(t,e){return te?1:t>=e?0:NaN}function p(t){return null===t?NaN:+t}function d(t){return!isNaN(t)}function m(t){return{left:function(e,r,n,i){for(arguments.length<3&&(n=0),arguments.length<4&&(i=e.length);n>>1;t(e[a],r)<0?n=a+1:i=a}return n},right:function(e,r,n,i){for(arguments.length<3&&(n=0),arguments.length<4&&(i=e.length);n>>1;t(e[a],r)>0?i=a:n=a+1}return n}}}t.ascending=h,t.descending=function(t,e){return et?1:e>=t?0:NaN},t.min=function(t,e){var r,n,i=-1,a=t.length;if(1===arguments.length){for(;++i=n){r=n;break}for(;++in&&(r=n)}else{for(;++i=n){r=n;break}for(;++in&&(r=n)}return r},t.max=function(t,e){var r,n,i=-1,a=t.length;if(1===arguments.length){for(;++i=n){r=n;break}for(;++ir&&(r=n)}else{for(;++i=n){r=n;break}for(;++ir&&(r=n)}return r},t.extent=function(t,e){var r,n,i,a=-1,o=t.length;if(1===arguments.length){for(;++a=n){r=i=n;break}for(;++an&&(r=n),i=n){r=i=n;break}for(;++an&&(r=n),i1)return o/(l-1)},t.deviation=function(){var e=t.variance.apply(this,arguments);return e?Math.sqrt(e):e};var g=m(h);function v(t){return t.length}t.bisectLeft=g.left,t.bisect=t.bisectRight=g.right,t.bisector=function(t){return m(1===t.length?function(e,r){return h(t(e),r)}:t)},t.shuffle=function(t,e,r){(a=arguments.length)<3&&(r=t.length,a<2&&(e=0));for(var n,i,a=r-e;a;)i=Math.random()*a--|0,n=t[a+e],t[a+e]=t[i+e],t[i+e]=n;return t},t.permute=function(t,e){for(var r=e.length,n=new Array(r);r--;)n[r]=t[e[r]];return n},t.pairs=function(t){for(var e=0,r=t.length-1,n=t[0],i=new Array(r<0?0:r);e=0;)for(e=(n=t[i]).length;--e>=0;)r[--o]=n[e];return r};var y=Math.abs;function x(t,e){for(var r in e)Object.defineProperty(t.prototype,r,{value:e[r],enumerable:!1})}function b(){this._=Object.create(null)}t.range=function(t,e,r){if(arguments.length<3&&(r=1,arguments.length<2&&(e=t,t=0)),(e-t)/r==1/0)throw new Error("infinite range");var n,i=[],a=function(t){var e=1;for(;t*e%1;)e*=10;return e}(y(r)),o=-1;if(t*=a,e*=a,(r*=a)<0)for(;(n=t+r*++o)>e;)i.push(n/a);else for(;(n=t+r*++o)=i.length)return r?r.call(n,a):e?a.sort(e):a;for(var l,c,u,f,h=-1,p=a.length,d=i[s++],m=new b;++h=i.length)return e;var n=[],o=a[r++];return e.forEach(function(e,i){n.push({key:e,values:t(i,r)})}),o?n.sort(function(t,e){return o(t.key,e.key)}):n}(o(t.map,e,0),0)},n.key=function(t){return i.push(t),n},n.sortKeys=function(t){return a[i.length-1]=t,n},n.sortValues=function(t){return e=t,n},n.rollup=function(t){return r=t,n},n},t.set=function(t){var e=new L;if(t)for(var r=0,n=t.length;r=0&&(n=t.slice(r+1),t=t.slice(0,r)),t)return arguments.length<2?this[t].on(n):this[t].on(n,e);if(2===arguments.length){if(null==e)for(t in this)this.hasOwnProperty(t)&&this[t].on(n,null);return this}},t.event=null,t.requote=function(t){return t.replace(V,"\\$&")};var V=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,U={}.__proto__?function(t,e){t.__proto__=e}:function(t,e){for(var r in e)t[r]=e[r]};function q(t){return U(t,Y),t}var H=function(t,e){return e.querySelector(t)},G=function(t,e){return e.querySelectorAll(t)},W=function(t,e){var r=t.matches||t[I(t,"matchesSelector")];return(W=function(t,e){return r.call(t,e)})(t,e)};"function"==typeof Sizzle&&(H=function(t,e){return Sizzle(t,e)[0]||null},G=Sizzle,W=Sizzle.matchesSelector),t.selection=function(){return t.select(i.documentElement)};var Y=t.selection.prototype=[];function X(t){return"function"==typeof t?t:function(){return H(t,this)}}function Z(t){return"function"==typeof t?t:function(){return G(t,this)}}Y.select=function(t){var e,r,n,i,a=[];t=X(t);for(var o=-1,s=this.length;++o=0&&"xmlns"!==(r=t.slice(0,e))&&(t=t.slice(e+1)),J.hasOwnProperty(r)?{space:J[r],local:t}:t}},Y.attr=function(e,r){if(arguments.length<2){if("string"==typeof e){var n=this.node();return(e=t.ns.qualify(e)).local?n.getAttributeNS(e.space,e.local):n.getAttribute(e)}for(r in e)this.each(K(r,e[r]));return this}return this.each(K(e,r))},Y.classed=function(t,e){if(arguments.length<2){if("string"==typeof t){var r=this.node(),n=(t=et(t)).length,i=-1;if(e=r.classList){for(;++i=0;)(r=n[i])&&(a&&a!==r.nextSibling&&a.parentNode.insertBefore(r,a),a=r);return this},Y.sort=function(t){t=function(t){arguments.length||(t=h);return function(e,r){return e&&r?t(e.__data__,r.__data__):!e-!r}}.apply(this,arguments);for(var e=-1,r=this.length;++e0&&(e=e.slice(0,o));var l=dt.get(e);function c(){var t=this[a];t&&(this.removeEventListener(e,t,t.$),delete this[a])}return l&&(e=l,s=gt),o?r?function(){var t=s(r,n(arguments));c.call(this),this.addEventListener(e,this[a]=t,t.$=i),t._=r}:c:r?D:function(){var r,n=new RegExp("^__on([^.]+)"+t.requote(e)+"$");for(var i in this)if(r=i.match(n)){var a=this[i];this.removeEventListener(r[1],a,a.$),delete this[i]}}}t.selection.enter=ft,t.selection.enter.prototype=ht,ht.append=Y.append,ht.empty=Y.empty,ht.node=Y.node,ht.call=Y.call,ht.size=Y.size,ht.select=function(t){for(var e,r,n,i,a,o=[],s=-1,l=this.length;++s=n&&(n=e+1);!(o=s[n])&&++n0?1:t<0?-1:0}function Ot(t,e,r){return(e[0]-t[0])*(r[1]-t[1])-(e[1]-t[1])*(r[0]-t[0])}function It(t){return t>1?0:t<-1?At:Math.acos(t)}function Pt(t){return t>1?Et:t<-1?-Et:Math.asin(t)}function Dt(t){return((t=Math.exp(t))+1/t)/2}function Rt(t){return(t=Math.sin(t/2))*t}var Bt=Math.SQRT2;t.interpolateZoom=function(t,e){var r,n,i=t[0],a=t[1],o=t[2],s=e[0],l=e[1],c=e[2],u=s-i,f=l-a,h=u*u+f*f;if(h0&&(e=e.transition().duration(m)),e.call(w.event)}function S(){c&&c.domain(l.range().map(function(t){return(t-h.x)/h.k}).map(l.invert)),f&&f.domain(u.range().map(function(t){return(t-h.y)/h.k}).map(u.invert))}function E(t){g++||t({type:"zoomstart"})}function C(t){S(),t({type:"zoom",scale:h.k,translate:[h.x,h.y]})}function L(t){--g||(t({type:"zoomend"}),r=null)}function z(){var e=this,r=_.of(e,arguments),n=0,i=t.select(o(e)).on(y,function(){n=1,A(t.mouse(e),a),C(r)}).on(x,function(){i.on(y,null).on(x,null),s(n),L(r)}),a=k(t.mouse(e)),s=xt(e);fs.call(e),E(r)}function O(){var e,r=this,n=_.of(r,arguments),i={},a=0,o=".zoom-"+t.event.changedTouches[0].identifier,l="touchmove"+o,c="touchend"+o,u=[],f=t.select(r),p=xt(r);function d(){var n=t.touches(r);return e=h.k,n.forEach(function(t){t.identifier in i&&(i[t.identifier]=k(t))}),n}function m(){var e=t.event.target;t.select(e).on(l,g).on(c,y),u.push(e);for(var n=t.event.changedTouches,o=0,f=n.length;o1){v=p[0];var x=p[1],b=v[0]-x[0],_=v[1]-x[1];a=b*b+_*_}}function g(){var o,l,c,u,f=t.touches(r);fs.call(r);for(var h=0,p=f.length;h360?t-=360:t<0&&(t+=360),t<60?n+(i-n)*t/60:t<180?i:t<240?n+(i-n)*(240-t)/60:n}(t))}return t=isNaN(t)?0:(t%=360)<0?t+360:t,e=isNaN(e)?0:e<0?0:e>1?1:e,n=2*(r=r<0?0:r>1?1:r)-(i=r<=.5?r*(1+e):r+e-r*e),new ae(a(t+120),a(t),a(t-120))}function Gt(e,r,n){return this instanceof Gt?(this.h=+e,this.c=+r,void(this.l=+n)):arguments.length<2?e instanceof Gt?new Gt(e.h,e.c,e.l):ee(e instanceof Xt?e.l:(e=he((e=t.rgb(e)).r,e.g,e.b)).l,e.a,e.b):new Gt(e,r,n)}qt.brighter=function(t){return t=Math.pow(.7,arguments.length?t:1),new Ut(this.h,this.s,this.l/t)},qt.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),new Ut(this.h,this.s,t*this.l)},qt.rgb=function(){return Ht(this.h,this.s,this.l)},t.hcl=Gt;var Wt=Gt.prototype=new Vt;function Yt(t,e,r){return isNaN(t)&&(t=0),isNaN(e)&&(e=0),new Xt(r,Math.cos(t*=Ct)*e,Math.sin(t)*e)}function Xt(t,e,r){return this instanceof Xt?(this.l=+t,this.a=+e,void(this.b=+r)):arguments.length<2?t instanceof Xt?new Xt(t.l,t.a,t.b):t instanceof Gt?Yt(t.h,t.c,t.l):he((t=ae(t)).r,t.g,t.b):new Xt(t,e,r)}Wt.brighter=function(t){return new Gt(this.h,this.c,Math.min(100,this.l+Zt*(arguments.length?t:1)))},Wt.darker=function(t){return new Gt(this.h,this.c,Math.max(0,this.l-Zt*(arguments.length?t:1)))},Wt.rgb=function(){return Yt(this.h,this.c,this.l).rgb()},t.lab=Xt;var Zt=18,$t=.95047,Jt=1,Kt=1.08883,Qt=Xt.prototype=new Vt;function te(t,e,r){var n=(t+16)/116,i=n+e/500,a=n-r/200;return new ae(ie(3.2404542*(i=re(i)*$t)-1.5371385*(n=re(n)*Jt)-.4985314*(a=re(a)*Kt)),ie(-.969266*i+1.8760108*n+.041556*a),ie(.0556434*i-.2040259*n+1.0572252*a))}function ee(t,e,r){return t>0?new Gt(Math.atan2(r,e)*Lt,Math.sqrt(e*e+r*r),t):new Gt(NaN,NaN,t)}function re(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function ne(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function ie(t){return Math.round(255*(t<=.00304?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function ae(t,e,r){return this instanceof ae?(this.r=~~t,this.g=~~e,void(this.b=~~r)):arguments.length<2?t instanceof ae?new ae(t.r,t.g,t.b):ue(""+t,ae,Ht):new ae(t,e,r)}function oe(t){return new ae(t>>16,t>>8&255,255&t)}function se(t){return oe(t)+""}Qt.brighter=function(t){return new Xt(Math.min(100,this.l+Zt*(arguments.length?t:1)),this.a,this.b)},Qt.darker=function(t){return new Xt(Math.max(0,this.l-Zt*(arguments.length?t:1)),this.a,this.b)},Qt.rgb=function(){return te(this.l,this.a,this.b)},t.rgb=ae;var le=ae.prototype=new Vt;function ce(t){return t<16?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function ue(t,e,r){var n,i,a,o=0,s=0,l=0;if(n=/([a-z]+)\((.*)\)/.exec(t=t.toLowerCase()))switch(i=n[2].split(","),n[1]){case"hsl":return r(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return e(de(i[0]),de(i[1]),de(i[2]))}return(a=me.get(t))?e(a.r,a.g,a.b):(null==t||"#"!==t.charAt(0)||isNaN(a=parseInt(t.slice(1),16))||(4===t.length?(o=(3840&a)>>4,o|=o>>4,s=240&a,s|=s>>4,l=15&a,l|=l<<4):7===t.length&&(o=(16711680&a)>>16,s=(65280&a)>>8,l=255&a)),e(o,s,l))}function fe(t,e,r){var n,i,a=Math.min(t/=255,e/=255,r/=255),o=Math.max(t,e,r),s=o-a,l=(o+a)/2;return s?(i=l<.5?s/(o+a):s/(2-o-a),n=t==o?(e-r)/s+(e0&&l<1?0:n),new Ut(n,i,l)}function he(t,e,r){var n=ne((.4124564*(t=pe(t))+.3575761*(e=pe(e))+.1804375*(r=pe(r)))/$t),i=ne((.2126729*t+.7151522*e+.072175*r)/Jt);return Xt(116*i-16,500*(n-i),200*(i-ne((.0193339*t+.119192*e+.9503041*r)/Kt)))}function pe(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function de(t){var e=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*e):e}le.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var e=this.r,r=this.g,n=this.b,i=30;return e||r||n?(e&&e=200&&e<300||304===e){try{t=i.call(o,c)}catch(t){return void s.error.call(o,t)}s.load.call(o,t)}else s.error.call(o,c)}return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(e)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=f:c.onreadystatechange=function(){c.readyState>3&&f()},c.onprogress=function(e){var r=t.event;t.event=e;try{s.progress.call(o,c)}finally{t.event=r}},o.header=function(t,e){return t=(t+"").toLowerCase(),arguments.length<2?l[t]:(null==e?delete l[t]:l[t]=e+"",o)},o.mimeType=function(t){return arguments.length?(r=null==t?null:t+"",o):r},o.responseType=function(t){return arguments.length?(u=t,o):u},o.response=function(t){return i=t,o},["get","post"].forEach(function(t){o[t]=function(){return o.send.apply(o,[t].concat(n(arguments)))}}),o.send=function(t,n,i){if(2===arguments.length&&"function"==typeof n&&(i=n,n=null),c.open(t,e,!0),null==r||"accept"in l||(l.accept=r+",*/*"),c.setRequestHeader)for(var a in l)c.setRequestHeader(a,l[a]);return null!=r&&c.overrideMimeType&&c.overrideMimeType(r),null!=u&&(c.responseType=u),null!=i&&o.on("error",i).on("load",function(t){i(null,t)}),s.beforesend.call(o,c),c.send(null==n?null:n),o},o.abort=function(){return c.abort(),o},t.rebind(o,s,"on"),null==a?o:o.get(function(t){return 1===t.length?function(e,r){t(null==e?r:null)}:t}(a))}me.forEach(function(t,e){me.set(t,oe(e))}),t.functor=ge,t.xhr=ve(z),t.dsv=function(t,e){var r=new RegExp('["'+t+"\n]"),n=t.charCodeAt(0);function i(t,r,n){arguments.length<3&&(n=r,r=null);var i=ye(t,e,null==r?a:o(r),n);return i.row=function(t){return arguments.length?i.response(null==(r=t)?a:o(t)):r},i}function a(t){return i.parse(t.responseText)}function o(t){return function(e){return i.parse(e.responseText,t)}}function s(e){return e.map(l).join(t)}function l(t){return r.test(t)?'"'+t.replace(/\"/g,'""')+'"':t}return i.parse=function(t,e){var r;return i.parseRows(t,function(t,n){if(r)return r(t,n-1);var i=new Function("d","return {"+t.map(function(t,e){return JSON.stringify(t)+": d["+e+"]"}).join(",")+"}");r=e?function(t,r){return e(i(t),r)}:i})},i.parseRows=function(t,e){var r,i,a={},o={},s=[],l=t.length,c=0,u=0;function f(){if(c>=l)return o;if(i)return i=!1,a;var e=c;if(34===t.charCodeAt(e)){for(var r=e;r++24?(isFinite(e)&&(clearTimeout(we),we=setTimeout(Ae,e)),_e=0):(_e=1,ke(Ae))}function Te(){for(var t=Date.now(),e=xe;e;)t>=e.t&&e.c(t-e.t)&&(e.c=null),e=e.n;return t}function Se(){for(var t,e=xe,r=1/0;e;)e.c?(e.t8?function(t){return t/r}:function(t){return t*r},symbol:t}});t.formatPrefix=function(e,r){var n=0;return(e=+e)&&(e<0&&(e*=-1),r&&(e=t.round(e,Ee(e,r))),n=1+Math.floor(1e-12+Math.log(e)/Math.LN10),n=Math.max(-24,Math.min(24,3*Math.floor((n-1)/3)))),Ce[8+n/3]};var Le=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,ze=t.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,e){return t.toPrecision(e)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},r:function(e,r){return(e=t.round(e,Ee(e,r))).toFixed(Math.max(0,Math.min(20,Ee(e*(1+1e-15),r))))}});function Oe(t){return t+""}var Ie=t.time={},Pe=Date;function De(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}De.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){Re.setUTCDate.apply(this._,arguments)},setDay:function(){Re.setUTCDay.apply(this._,arguments)},setFullYear:function(){Re.setUTCFullYear.apply(this._,arguments)},setHours:function(){Re.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){Re.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){Re.setUTCMinutes.apply(this._,arguments)},setMonth:function(){Re.setUTCMonth.apply(this._,arguments)},setSeconds:function(){Re.setUTCSeconds.apply(this._,arguments)},setTime:function(){Re.setTime.apply(this._,arguments)}};var Re=Date.prototype;function Be(t,e,r){function n(e){var r=t(e),n=a(r,1);return e-r1)for(;o68?1900:2e3),r+i[0].length):-1}function $e(t,e,r){return/^[+-]\d{4}$/.test(e=e.slice(r,r+5))?(t.Z=-e,r+5):-1}function Je(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Ke(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function Qe(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+3));return n?(t.j=+n[0],r+n[0].length):-1}function tr(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function er(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function rr(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function nr(t,e,r){je.lastIndex=0;var n=je.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function ir(t){var e=t.getTimezoneOffset(),r=e>0?"-":"+",n=y(e)/60|0,i=y(e)%60;return r+Ue(n,"0",2)+Ue(i,"0",2)}function ar(t,e,r){Ve.lastIndex=0;var n=Ve.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function or(t){for(var e=t.length,r=-1;++r0&&s>0&&(l+s+1>e&&(s=Math.max(1,e-l)),a.push(t.substring(r-=s,r+s)),!((l+=s+1)>e));)s=i[o=(o+1)%i.length];return a.reverse().join(n)}:z;return function(e){var n=Le.exec(e),i=n[1]||" ",s=n[2]||">",l=n[3]||"-",c=n[4]||"",u=n[5],f=+n[6],h=n[7],p=n[8],d=n[9],m=1,g="",v="",y=!1,x=!0;switch(p&&(p=+p.substring(1)),(u||"0"===i&&"="===s)&&(u=i="0",s="="),d){case"n":h=!0,d="g";break;case"%":m=100,v="%",d="f";break;case"p":m=100,v="%",d="r";break;case"b":case"o":case"x":case"X":"#"===c&&(g="0"+d.toLowerCase());case"c":x=!1;case"d":y=!0,p=0;break;case"s":m=-1,d="r"}"$"===c&&(g=a[0],v=a[1]),"r"!=d||p||(d="g"),null!=p&&("g"==d?p=Math.max(1,Math.min(21,p)):"e"!=d&&"f"!=d||(p=Math.max(0,Math.min(20,p)))),d=ze.get(d)||Oe;var b=u&&h;return function(e){var n=v;if(y&&e%1)return"";var a=e<0||0===e&&1/e<0?(e=-e,"-"):"-"===l?"":l;if(m<0){var c=t.formatPrefix(e,p);e=c.scale(e),n=c.symbol+v}else e*=m;var _,w,k=(e=d(e,p)).lastIndexOf(".");if(k<0){var M=x?e.lastIndexOf("e"):-1;M<0?(_=e,w=""):(_=e.substring(0,M),w=e.substring(M))}else _=e.substring(0,k),w=r+e.substring(k+1);!u&&h&&(_=o(_,1/0));var A=g.length+_.length+w.length+(b?0:a.length),T=A"===s?T+a+e:"^"===s?T.substring(0,A>>=1)+a+e+T.substring(A):a+(b?e:T+e))+n}}}(e),timeFormat:function(e){var r=e.dateTime,n=e.date,i=e.time,a=e.periods,o=e.days,s=e.shortDays,l=e.months,c=e.shortMonths;function u(t){var e=t.length;function r(r){for(var n,i,a,o=[],s=-1,l=0;++s=c)return-1;if(37===(i=e.charCodeAt(s++))){if(o=e.charAt(s++),!(a=w[o in Ne?e.charAt(s++):o])||(n=a(t,r,n))<0)return-1}else if(i!=r.charCodeAt(n++))return-1}return n}u.utc=function(t){var e=u(t);function r(t){try{var r=new(Pe=De);return r._=t,e(r)}finally{Pe=Date}}return r.parse=function(t){try{Pe=De;var r=e.parse(t);return r&&r._}finally{Pe=Date}},r.toString=e.toString,r},u.multi=u.utc.multi=or;var h=t.map(),p=qe(o),d=He(o),m=qe(s),g=He(s),v=qe(l),y=He(l),x=qe(c),b=He(c);a.forEach(function(t,e){h.set(t.toLowerCase(),e)});var _={a:function(t){return s[t.getDay()]},A:function(t){return o[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return l[t.getMonth()]},c:u(r),d:function(t,e){return Ue(t.getDate(),e,2)},e:function(t,e){return Ue(t.getDate(),e,2)},H:function(t,e){return Ue(t.getHours(),e,2)},I:function(t,e){return Ue(t.getHours()%12||12,e,2)},j:function(t,e){return Ue(1+Ie.dayOfYear(t),e,3)},L:function(t,e){return Ue(t.getMilliseconds(),e,3)},m:function(t,e){return Ue(t.getMonth()+1,e,2)},M:function(t,e){return Ue(t.getMinutes(),e,2)},p:function(t){return a[+(t.getHours()>=12)]},S:function(t,e){return Ue(t.getSeconds(),e,2)},U:function(t,e){return Ue(Ie.sundayOfYear(t),e,2)},w:function(t){return t.getDay()},W:function(t,e){return Ue(Ie.mondayOfYear(t),e,2)},x:u(n),X:u(i),y:function(t,e){return Ue(t.getFullYear()%100,e,2)},Y:function(t,e){return Ue(t.getFullYear()%1e4,e,4)},Z:ir,"%":function(){return"%"}},w={a:function(t,e,r){m.lastIndex=0;var n=m.exec(e.slice(r));return n?(t.w=g.get(n[0].toLowerCase()),r+n[0].length):-1},A:function(t,e,r){p.lastIndex=0;var n=p.exec(e.slice(r));return n?(t.w=d.get(n[0].toLowerCase()),r+n[0].length):-1},b:function(t,e,r){x.lastIndex=0;var n=x.exec(e.slice(r));return n?(t.m=b.get(n[0].toLowerCase()),r+n[0].length):-1},B:function(t,e,r){v.lastIndex=0;var n=v.exec(e.slice(r));return n?(t.m=y.get(n[0].toLowerCase()),r+n[0].length):-1},c:function(t,e,r){return f(t,_.c.toString(),e,r)},d:Ke,e:Ke,H:tr,I:tr,j:Qe,L:nr,m:Je,M:er,p:function(t,e,r){var n=h.get(e.slice(r,r+=2).toLowerCase());return null==n?-1:(t.p=n,r)},S:rr,U:We,w:Ge,W:Ye,x:function(t,e,r){return f(t,_.x.toString(),e,r)},X:function(t,e,r){return f(t,_.X.toString(),e,r)},y:Ze,Y:Xe,Z:$e,"%":ar};return u}(e)}};var sr=t.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function lr(){}t.format=sr.numberFormat,t.geo={},lr.prototype={s:0,t:0,add:function(t){ur(t,this.t,cr),ur(cr.s,this.s,this),this.s?this.t+=cr.t:this.s=cr.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cr=new lr;function ur(t,e,r){var n=r.s=t+e,i=n-t,a=n-i;r.t=t-a+(e-i)}function fr(t,e){t&&pr.hasOwnProperty(t.type)&&pr[t.type](t,e)}t.geo.stream=function(t,e){t&&hr.hasOwnProperty(t.type)?hr[t.type](t,e):fr(t,e)};var hr={Feature:function(t,e){fr(t.geometry,e)},FeatureCollection:function(t,e){for(var r=t.features,n=-1,i=r.length;++n=0?1:-1,s=o*a,l=Math.cos(e),c=Math.sin(e),u=i*c,f=n*l+u*Math.cos(s),h=u*o*Math.sin(s);Er.add(Math.atan2(h,f)),r=t,n=l,i=c}Cr.point=function(o,s){Cr.point=a,r=(t=o)*Ct,n=Math.cos(s=(e=s)*Ct/2+At/4),i=Math.sin(s)},Cr.lineEnd=function(){a(t,e)}}function zr(t){var e=t[0],r=t[1],n=Math.cos(r);return[n*Math.cos(e),n*Math.sin(e),Math.sin(r)]}function Or(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Ir(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function Pr(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function Dr(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function Rr(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function Br(t){return[Math.atan2(t[1],t[0]),Pt(t[2])]}function Fr(t,e){return y(t[0]-e[0])kt?i=90:c<-kt&&(r=-90),f[0]=e,f[1]=n}};function p(t,a){u.push(f=[e=t,n=t]),ai&&(i=a)}function d(t,o){var s=zr([t*Ct,o*Ct]);if(l){var c=Ir(l,s),u=Ir([c[1],-c[0],0],c);Rr(u),u=Br(u);var f=t-a,h=f>0?1:-1,d=u[0]*Lt*h,m=y(f)>180;if(m^(h*ai&&(i=g);else if(m^(h*a<(d=(d+360)%360-180)&&di&&(i=o);m?t_(e,n)&&(n=t):_(t,n)>_(e,n)&&(e=t):n>=e?(tn&&(n=t)):t>a?_(e,t)>_(e,n)&&(n=t):_(t,n)>_(e,n)&&(e=t)}else p(t,o);l=s,a=t}function m(){h.point=d}function g(){f[0]=e,f[1]=n,h.point=p,l=null}function v(t,e){if(l){var r=t-a;c+=y(r)>180?r+(r>0?360:-360):r}else o=t,s=e;Cr.point(t,e),d(t,e)}function x(){Cr.lineStart()}function b(){v(o,s),Cr.lineEnd(),y(c)>kt&&(e=-(n=180)),f[0]=e,f[1]=n,l=null}function _(t,e){return(e-=t)<0?e+360:e}function w(t,e){return t[0]-e[0]}function k(t,e){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:t_(m[0],m[1])&&(m[1]=p[1]),_(p[0],m[1])>_(m[0],m[1])&&(m[0]=p[0])):s.push(m=p);for(var l,c,p,d=-1/0,m=(o=0,s[c=s.length-1]);o<=c;m=p,++o)p=s[o],(l=_(m[1],p[0]))>d&&(d=l,e=p[0],n=m[1])}return u=f=null,e===1/0||r===1/0?[[NaN,NaN],[NaN,NaN]]:[[e,r],[n,i]]}}(),t.geo.centroid=function(e){vr=yr=xr=br=_r=wr=kr=Mr=Ar=Tr=Sr=0,t.geo.stream(e,Nr);var r=Ar,n=Tr,i=Sr,a=r*r+n*n+i*i;return a=0;--s)i.point((f=u[s])[0],f[1]);else n(p.x,p.p.x,-1,i);p=p.p}u=(p=p.o).z,d=!d}while(!p.v);i.lineEnd()}}}function Xr(t){if(e=t.length){for(var e,r,n=0,i=t[0];++n=0?1:-1,k=w*_,M=k>At,A=d*x;if(Er.add(Math.atan2(A*w*Math.sin(k),m*b+A*Math.cos(k))),a+=M?_+w*Tt:_,M^h>=r^v>=r){var T=Ir(zr(f),zr(t));Rr(T);var S=Ir(i,T);Rr(S);var E=(M^_>=0?-1:1)*Pt(S[2]);(n>E||n===E&&(T[0]||T[1]))&&(o+=M^_>=0?1:-1)}if(!g++)break;h=v,d=x,m=b,f=t}}return(a<-kt||a0){for(x||(o.polygonStart(),x=!0),o.lineStart();++a1&&2&e&&r.push(r.pop().concat(r.shift())),s.push(r.filter(Jr))}return u}}function Jr(t){return t.length>1}function Kr(){var t,e=[];return{lineStart:function(){e.push(t=[])},point:function(e,r){t.push([e,r])},lineEnd:D,buffer:function(){var r=e;return e=[],t=null,r},rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))}}}function Qr(t,e){return((t=t.x)[0]<0?t[1]-Et-kt:Et-t[1])-((e=e.x)[0]<0?e[1]-Et-kt:Et-e[1])}var tn=$r(Wr,function(t){var e,r=NaN,n=NaN,i=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(a,o){var s=a>0?At:-At,l=y(a-r);y(l-At)0?Et:-Et),t.point(i,n),t.lineEnd(),t.lineStart(),t.point(s,n),t.point(a,n),e=0):i!==s&&l>=At&&(y(r-i)kt?Math.atan((Math.sin(e)*(a=Math.cos(n))*Math.sin(r)-Math.sin(n)*(i=Math.cos(e))*Math.sin(t))/(i*a*o)):(e+n)/2}(r,n,a,o),t.point(i,n),t.lineEnd(),t.lineStart(),t.point(s,n),e=0),t.point(r=a,n=o),i=s},lineEnd:function(){t.lineEnd(),r=n=NaN},clean:function(){return 2-e}}},function(t,e,r,n){var i;if(null==t)i=r*Et,n.point(-At,i),n.point(0,i),n.point(At,i),n.point(At,0),n.point(At,-i),n.point(0,-i),n.point(-At,-i),n.point(-At,0),n.point(-At,i);else if(y(t[0]-e[0])>kt){var a=t[0]0)){if(a/=h,h<0){if(a0){if(a>f)return;a>u&&(u=a)}if(a=r-l,h||!(a<0)){if(a/=h,h<0){if(a>f)return;a>u&&(u=a)}else if(h>0){if(a0)){if(a/=p,p<0){if(a0){if(a>f)return;a>u&&(u=a)}if(a=n-c,p||!(a<0)){if(a/=p,p<0){if(a>f)return;a>u&&(u=a)}else if(p>0){if(a0&&(i.a={x:l+u*h,y:c+u*p}),f<1&&(i.b={x:l+f*h,y:c+f*p}),i}}}}}}var rn=1e9;function nn(e,r,n,i){return function(l){var c,u,f,h,p,d,m,g,v,y,x,b=l,_=Kr(),w=en(e,r,n,i),k={point:T,lineStart:function(){k.point=S,u&&u.push(f=[]);y=!0,v=!1,m=g=NaN},lineEnd:function(){c&&(S(h,p),d&&v&&_.rejoin(),c.push(_.buffer()));k.point=T,v&&l.lineEnd()},polygonStart:function(){l=_,c=[],u=[],x=!0},polygonEnd:function(){l=b,c=t.merge(c);var r=function(t){for(var e=0,r=u.length,n=t[1],i=0;in&&Ot(c,a,t)>0&&++e:a[1]<=n&&Ot(c,a,t)<0&&--e,c=a;return 0!==e}([e,i]),n=x&&r,a=c.length;(n||a)&&(l.polygonStart(),n&&(l.lineStart(),M(null,null,1,l),l.lineEnd()),a&&Yr(c,o,r,M,l),l.polygonEnd()),c=u=f=null}};function M(t,o,l,c){var u=0,f=0;if(null==t||(u=a(t,l))!==(f=a(o,l))||s(t,o)<0^l>0)do{c.point(0===u||3===u?e:n,u>1?i:r)}while((u=(u+l+4)%4)!==f);else c.point(o[0],o[1])}function A(t,a){return e<=t&&t<=n&&r<=a&&a<=i}function T(t,e){A(t,e)&&l.point(t,e)}function S(t,e){var r=A(t=Math.max(-rn,Math.min(rn,t)),e=Math.max(-rn,Math.min(rn,e)));if(u&&f.push([t,e]),y)h=t,p=e,d=r,y=!1,r&&(l.lineStart(),l.point(t,e));else if(r&&v)l.point(t,e);else{var n={a:{x:m,y:g},b:{x:t,y:e}};w(n)?(v||(l.lineStart(),l.point(n.a.x,n.a.y)),l.point(n.b.x,n.b.y),r||l.lineEnd(),x=!1):r&&(l.lineStart(),l.point(t,e),x=!1)}m=t,g=e,v=r}return k};function a(t,i){return y(t[0]-e)0?0:3:y(t[0]-n)0?2:1:y(t[1]-r)0?1:0:i>0?3:2}function o(t,e){return s(t.x,e.x)}function s(t,e){var r=a(t,1),n=a(e,1);return r!==n?r-n:0===r?e[1]-t[1]:1===r?t[0]-e[0]:2===r?t[1]-e[1]:e[0]-t[0]}}function an(t){var e=0,r=At/3,n=Cn(t),i=n(e,r);return i.parallels=function(t){return arguments.length?n(e=t[0]*At/180,r=t[1]*At/180):[e/At*180,r/At*180]},i}function on(t,e){var r=Math.sin(t),n=(r+Math.sin(e))/2,i=1+r*(2*n-r),a=Math.sqrt(i)/n;function o(t,e){var r=Math.sqrt(i-2*n*Math.sin(e))/n;return[r*Math.sin(t*=n),a-r*Math.cos(t)]}return o.invert=function(t,e){var r=a-e;return[Math.atan2(t,r)/n,Pt((i-(t*t+r*r)*n*n)/(2*n))]},o}t.geo.clipExtent=function(){var t,e,r,n,i,a,o={stream:function(t){return i&&(i.valid=!1),(i=a(t)).valid=!0,i},extent:function(s){return arguments.length?(a=nn(t=+s[0][0],e=+s[0][1],r=+s[1][0],n=+s[1][1]),i&&(i.valid=!1,i=null),o):[[t,e],[r,n]]}};return o.extent([[0,0],[960,500]])},(t.geo.conicEqualArea=function(){return an(on)}).raw=on,t.geo.albers=function(){return t.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},t.geo.albersUsa=function(){var e,r,n,i,a=t.geo.albers(),o=t.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),s=t.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,r){e=[t,r]}};function c(t){var a=t[0],o=t[1];return e=null,r(a,o),e||(n(a,o),e)||i(a,o),e}return c.invert=function(t){var e=a.scale(),r=a.translate(),n=(t[0]-r[0])/e,i=(t[1]-r[1])/e;return(i>=.12&&i<.234&&n>=-.425&&n<-.214?o:i>=.166&&i<.234&&n>=-.214&&n<-.115?s:a).invert(t)},c.stream=function(t){var e=a.stream(t),r=o.stream(t),n=s.stream(t);return{point:function(t,i){e.point(t,i),r.point(t,i),n.point(t,i)},sphere:function(){e.sphere(),r.sphere(),n.sphere()},lineStart:function(){e.lineStart(),r.lineStart(),n.lineStart()},lineEnd:function(){e.lineEnd(),r.lineEnd(),n.lineEnd()},polygonStart:function(){e.polygonStart(),r.polygonStart(),n.polygonStart()},polygonEnd:function(){e.polygonEnd(),r.polygonEnd(),n.polygonEnd()}}},c.precision=function(t){return arguments.length?(a.precision(t),o.precision(t),s.precision(t),c):a.precision()},c.scale=function(t){return arguments.length?(a.scale(t),o.scale(.35*t),s.scale(t),c.translate(a.translate())):a.scale()},c.translate=function(t){if(!arguments.length)return a.translate();var e=a.scale(),u=+t[0],f=+t[1];return r=a.translate(t).clipExtent([[u-.455*e,f-.238*e],[u+.455*e,f+.238*e]]).stream(l).point,n=o.translate([u-.307*e,f+.201*e]).clipExtent([[u-.425*e+kt,f+.12*e+kt],[u-.214*e-kt,f+.234*e-kt]]).stream(l).point,i=s.translate([u-.205*e,f+.212*e]).clipExtent([[u-.214*e+kt,f+.166*e+kt],[u-.115*e-kt,f+.234*e-kt]]).stream(l).point,c},c.scale(1070)};var sn,ln,cn,un,fn,hn,pn={point:D,lineStart:D,lineEnd:D,polygonStart:function(){ln=0,pn.lineStart=dn},polygonEnd:function(){pn.lineStart=pn.lineEnd=pn.point=D,sn+=y(ln/2)}};function dn(){var t,e,r,n;function i(t,e){ln+=n*t-r*e,r=t,n=e}pn.point=function(a,o){pn.point=i,t=r=a,e=n=o},pn.lineEnd=function(){i(t,e)}}var mn={point:function(t,e){tfn&&(fn=t);ehn&&(hn=e)},lineStart:D,lineEnd:D,polygonStart:D,polygonEnd:D};function gn(){var t=vn(4.5),e=[],r={point:n,lineStart:function(){r.point=i},lineEnd:o,polygonStart:function(){r.lineEnd=s},polygonEnd:function(){r.lineEnd=o,r.point=n},pointRadius:function(e){return t=vn(e),r},result:function(){if(e.length){var t=e.join("");return e=[],t}}};function n(r,n){e.push("M",r,",",n,t)}function i(t,n){e.push("M",t,",",n),r.point=a}function a(t,r){e.push("L",t,",",r)}function o(){r.point=n}function s(){e.push("Z")}return r}function vn(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}var yn,xn={point:bn,lineStart:_n,lineEnd:wn,polygonStart:function(){xn.lineStart=kn},polygonEnd:function(){xn.point=bn,xn.lineStart=_n,xn.lineEnd=wn}};function bn(t,e){xr+=t,br+=e,++_r}function _n(){var t,e;function r(r,n){var i=r-t,a=n-e,o=Math.sqrt(i*i+a*a);wr+=o*(t+r)/2,kr+=o*(e+n)/2,Mr+=o,bn(t=r,e=n)}xn.point=function(n,i){xn.point=r,bn(t=n,e=i)}}function wn(){xn.point=bn}function kn(){var t,e,r,n;function i(t,e){var i=t-r,a=e-n,o=Math.sqrt(i*i+a*a);wr+=o*(r+t)/2,kr+=o*(n+e)/2,Mr+=o,Ar+=(o=n*t-r*e)*(r+t),Tr+=o*(n+e),Sr+=3*o,bn(r=t,n=e)}xn.point=function(a,o){xn.point=i,bn(t=r=a,e=n=o)},xn.lineEnd=function(){i(t,e)}}function Mn(t){var e=4.5,r={point:n,lineStart:function(){r.point=i},lineEnd:o,polygonStart:function(){r.lineEnd=s},polygonEnd:function(){r.lineEnd=o,r.point=n},pointRadius:function(t){return e=t,r},result:D};function n(r,n){t.moveTo(r+e,n),t.arc(r,n,e,0,Tt)}function i(e,n){t.moveTo(e,n),r.point=a}function a(e,r){t.lineTo(e,r)}function o(){r.point=n}function s(){t.closePath()}return r}function An(t){var e=.5,r=Math.cos(30*Ct),n=16;function i(e){return(n?function(e){var r,i,o,s,l,c,u,f,h,p,d,m,g={point:v,lineStart:y,lineEnd:b,polygonStart:function(){e.polygonStart(),g.lineStart=_},polygonEnd:function(){e.polygonEnd(),g.lineStart=y}};function v(r,n){r=t(r,n),e.point(r[0],r[1])}function y(){f=NaN,g.point=x,e.lineStart()}function x(r,i){var o=zr([r,i]),s=t(r,i);a(f,h,u,p,d,m,f=s[0],h=s[1],u=r,p=o[0],d=o[1],m=o[2],n,e),e.point(f,h)}function b(){g.point=v,e.lineEnd()}function _(){y(),g.point=w,g.lineEnd=k}function w(t,e){x(r=t,e),i=f,o=h,s=p,l=d,c=m,g.point=x}function k(){a(f,h,u,p,d,m,i,o,r,s,l,c,n,e),g.lineEnd=b,b()}return g}:function(e){return Sn(e,function(r,n){r=t(r,n),e.point(r[0],r[1])})})(e)}function a(n,i,o,s,l,c,u,f,h,p,d,m,g,v){var x=u-n,b=f-i,_=x*x+b*b;if(_>4*e&&g--){var w=s+p,k=l+d,M=c+m,A=Math.sqrt(w*w+k*k+M*M),T=Math.asin(M/=A),S=y(y(M)-1)e||y((x*z+b*O)/_-.5)>.3||s*p+l*d+c*m0&&16,i):Math.sqrt(e)},i}function Tn(t){this.stream=t}function Sn(t,e){return{point:e,sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function En(t){return Cn(function(){return t})()}function Cn(e){var r,n,i,a,o,s,l=An(function(t,e){return[(t=r(t,e))[0]*c+a,o-t[1]*c]}),c=150,u=480,f=250,h=0,p=0,d=0,m=0,g=0,v=tn,x=z,b=null,_=null;function w(t){return[(t=i(t[0]*Ct,t[1]*Ct))[0]*c+a,o-t[1]*c]}function k(t){return(t=i.invert((t[0]-a)/c,(o-t[1])/c))&&[t[0]*Lt,t[1]*Lt]}function M(){i=Gr(n=In(d,m,g),r);var t=r(h,p);return a=u-t[0]*c,o=f+t[1]*c,A()}function A(){return s&&(s.valid=!1,s=null),w}return w.stream=function(t){return s&&(s.valid=!1),(s=Ln(v(n,l(x(t))))).valid=!0,s},w.clipAngle=function(t){return arguments.length?(v=null==t?(b=t,tn):function(t){var e=Math.cos(t),r=e>0,n=y(e)>kt;return $r(i,function(t){var e,s,l,c,u;return{lineStart:function(){c=l=!1,u=1},point:function(f,h){var p,d=[f,h],m=i(f,h),g=r?m?0:o(f,h):m?o(f+(f<0?At:-At),h):0;if(!e&&(c=l=m)&&t.lineStart(),m!==l&&(p=a(e,d),(Fr(e,p)||Fr(d,p))&&(d[0]+=kt,d[1]+=kt,m=i(d[0],d[1]))),m!==l)u=0,m?(t.lineStart(),p=a(d,e),t.point(p[0],p[1])):(p=a(e,d),t.point(p[0],p[1]),t.lineEnd()),e=p;else if(n&&e&&r^m){var v;g&s||!(v=a(d,e,!0))||(u=0,r?(t.lineStart(),t.point(v[0][0],v[0][1]),t.point(v[1][0],v[1][1]),t.lineEnd()):(t.point(v[1][0],v[1][1]),t.lineEnd(),t.lineStart(),t.point(v[0][0],v[0][1])))}!m||e&&Fr(e,d)||t.point(d[0],d[1]),e=d,l=m,s=g},lineEnd:function(){l&&t.lineEnd(),e=null},clean:function(){return u|(c&&l)<<1}}},Bn(t,6*Ct),r?[0,-t]:[-At,t-At]);function i(t,r){return Math.cos(t)*Math.cos(r)>e}function a(t,r,n){var i=[1,0,0],a=Ir(zr(t),zr(r)),o=Or(a,a),s=a[0],l=o-s*s;if(!l)return!n&&t;var c=e*o/l,u=-e*s/l,f=Ir(i,a),h=Dr(i,c);Pr(h,Dr(a,u));var p=f,d=Or(h,p),m=Or(p,p),g=d*d-m*(Or(h,h)-1);if(!(g<0)){var v=Math.sqrt(g),x=Dr(p,(-d-v)/m);if(Pr(x,h),x=Br(x),!n)return x;var b,_=t[0],w=r[0],k=t[1],M=r[1];w<_&&(b=_,_=w,w=b);var A=w-_,T=y(A-At)0^x[1]<(y(x[0]-_)At^(_<=x[0]&&x[0]<=w)){var S=Dr(p,(-d+v)/m);return Pr(S,h),[x,Br(S)]}}}function o(e,n){var i=r?t:At-t,a=0;return e<-i?a|=1:e>i&&(a|=2),n<-i?a|=4:n>i&&(a|=8),a}}((b=+t)*Ct),A()):b},w.clipExtent=function(t){return arguments.length?(_=t,x=t?nn(t[0][0],t[0][1],t[1][0],t[1][1]):z,A()):_},w.scale=function(t){return arguments.length?(c=+t,M()):c},w.translate=function(t){return arguments.length?(u=+t[0],f=+t[1],M()):[u,f]},w.center=function(t){return arguments.length?(h=t[0]%360*Ct,p=t[1]%360*Ct,M()):[h*Lt,p*Lt]},w.rotate=function(t){return arguments.length?(d=t[0]%360*Ct,m=t[1]%360*Ct,g=t.length>2?t[2]%360*Ct:0,M()):[d*Lt,m*Lt,g*Lt]},t.rebind(w,l,"precision"),function(){return r=e.apply(this,arguments),w.invert=r.invert&&k,M()}}function Ln(t){return Sn(t,function(e,r){t.point(e*Ct,r*Ct)})}function zn(t,e){return[t,e]}function On(t,e){return[t>At?t-Tt:t<-At?t+Tt:t,e]}function In(t,e,r){return t?e||r?Gr(Dn(t),Rn(e,r)):Dn(t):e||r?Rn(e,r):On}function Pn(t){return function(e,r){return[(e+=t)>At?e-Tt:e<-At?e+Tt:e,r]}}function Dn(t){var e=Pn(t);return e.invert=Pn(-t),e}function Rn(t,e){var r=Math.cos(t),n=Math.sin(t),i=Math.cos(e),a=Math.sin(e);function o(t,e){var o=Math.cos(e),s=Math.cos(t)*o,l=Math.sin(t)*o,c=Math.sin(e),u=c*r+s*n;return[Math.atan2(l*i-u*a,s*r-c*n),Pt(u*i+l*a)]}return o.invert=function(t,e){var o=Math.cos(e),s=Math.cos(t)*o,l=Math.sin(t)*o,c=Math.sin(e),u=c*i-l*a;return[Math.atan2(l*i+c*a,s*r+u*n),Pt(u*r-s*n)]},o}function Bn(t,e){var r=Math.cos(t),n=Math.sin(t);return function(i,a,o,s){var l=o*e;null!=i?(i=Fn(r,i),a=Fn(r,a),(o>0?ia)&&(i+=o*Tt)):(i=t+o*Tt,a=t-.5*l);for(var c,u=i;o>0?u>a:u2?t[2]*Ct:0),e.invert=function(e){return(e=t.invert(e[0]*Ct,e[1]*Ct))[0]*=Lt,e[1]*=Lt,e},e},On.invert=zn,t.geo.circle=function(){var t,e,r=[0,0],n=6;function i(){var t="function"==typeof r?r.apply(this,arguments):r,n=In(-t[0]*Ct,-t[1]*Ct,0).invert,i=[];return e(null,null,1,{point:function(t,e){i.push(t=n(t,e)),t[0]*=Lt,t[1]*=Lt}}),{type:"Polygon",coordinates:[i]}}return i.origin=function(t){return arguments.length?(r=t,i):r},i.angle=function(r){return arguments.length?(e=Bn((t=+r)*Ct,n*Ct),i):t},i.precision=function(r){return arguments.length?(e=Bn(t*Ct,(n=+r)*Ct),i):n},i.angle(90)},t.geo.distance=function(t,e){var r,n=(e[0]-t[0])*Ct,i=t[1]*Ct,a=e[1]*Ct,o=Math.sin(n),s=Math.cos(n),l=Math.sin(i),c=Math.cos(i),u=Math.sin(a),f=Math.cos(a);return Math.atan2(Math.sqrt((r=f*o)*r+(r=c*u-l*f*s)*r),l*u+c*f*s)},t.geo.graticule=function(){var e,r,n,i,a,o,s,l,c,u,f,h,p=10,d=p,m=90,g=360,v=2.5;function x(){return{type:"MultiLineString",coordinates:b()}}function b(){return t.range(Math.ceil(i/m)*m,n,m).map(f).concat(t.range(Math.ceil(l/g)*g,s,g).map(h)).concat(t.range(Math.ceil(r/p)*p,e,p).filter(function(t){return y(t%m)>kt}).map(c)).concat(t.range(Math.ceil(o/d)*d,a,d).filter(function(t){return y(t%g)>kt}).map(u))}return x.lines=function(){return b().map(function(t){return{type:"LineString",coordinates:t}})},x.outline=function(){return{type:"Polygon",coordinates:[f(i).concat(h(s).slice(1),f(n).reverse().slice(1),h(l).reverse().slice(1))]}},x.extent=function(t){return arguments.length?x.majorExtent(t).minorExtent(t):x.minorExtent()},x.majorExtent=function(t){return arguments.length?(i=+t[0][0],n=+t[1][0],l=+t[0][1],s=+t[1][1],i>n&&(t=i,i=n,n=t),l>s&&(t=l,l=s,s=t),x.precision(v)):[[i,l],[n,s]]},x.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),x.precision(v)):[[r,o],[e,a]]},x.step=function(t){return arguments.length?x.majorStep(t).minorStep(t):x.minorStep()},x.majorStep=function(t){return arguments.length?(m=+t[0],g=+t[1],x):[m,g]},x.minorStep=function(t){return arguments.length?(p=+t[0],d=+t[1],x):[p,d]},x.precision=function(t){return arguments.length?(v=+t,c=Nn(o,a,90),u=jn(r,e,v),f=Nn(l,s,90),h=jn(i,n,v),x):v},x.majorExtent([[-180,-90+kt],[180,90-kt]]).minorExtent([[-180,-80-kt],[180,80+kt]])},t.geo.greatArc=function(){var e,r,n=Vn,i=Un;function a(){return{type:"LineString",coordinates:[e||n.apply(this,arguments),r||i.apply(this,arguments)]}}return a.distance=function(){return t.geo.distance(e||n.apply(this,arguments),r||i.apply(this,arguments))},a.source=function(t){return arguments.length?(n=t,e="function"==typeof t?null:t,a):n},a.target=function(t){return arguments.length?(i=t,r="function"==typeof t?null:t,a):i},a.precision=function(){return arguments.length?a:0},a},t.geo.interpolate=function(t,e){return r=t[0]*Ct,n=t[1]*Ct,i=e[0]*Ct,a=e[1]*Ct,o=Math.cos(n),s=Math.sin(n),l=Math.cos(a),c=Math.sin(a),u=o*Math.cos(r),f=o*Math.sin(r),h=l*Math.cos(i),p=l*Math.sin(i),d=2*Math.asin(Math.sqrt(Rt(a-n)+o*l*Rt(i-r))),m=1/Math.sin(d),(g=d?function(t){var e=Math.sin(t*=d)*m,r=Math.sin(d-t)*m,n=r*u+e*h,i=r*f+e*p,a=r*s+e*c;return[Math.atan2(i,n)*Lt,Math.atan2(a,Math.sqrt(n*n+i*i))*Lt]}:function(){return[r*Lt,n*Lt]}).distance=d,g;var r,n,i,a,o,s,l,c,u,f,h,p,d,m,g},t.geo.length=function(e){return yn=0,t.geo.stream(e,qn),yn};var qn={sphere:D,point:D,lineStart:function(){var t,e,r;function n(n,i){var a=Math.sin(i*=Ct),o=Math.cos(i),s=y((n*=Ct)-t),l=Math.cos(s);yn+=Math.atan2(Math.sqrt((s=o*Math.sin(s))*s+(s=r*a-e*o*l)*s),e*a+r*o*l),t=n,e=a,r=o}qn.point=function(i,a){t=i*Ct,e=Math.sin(a*=Ct),r=Math.cos(a),qn.point=n},qn.lineEnd=function(){qn.point=qn.lineEnd=D}},lineEnd:D,polygonStart:D,polygonEnd:D};function Hn(t,e){function r(e,r){var n=Math.cos(e),i=Math.cos(r),a=t(n*i);return[a*i*Math.sin(e),a*Math.sin(r)]}return r.invert=function(t,r){var n=Math.sqrt(t*t+r*r),i=e(n),a=Math.sin(i),o=Math.cos(i);return[Math.atan2(t*a,n*o),Math.asin(n&&r*a/n)]},r}var Gn=Hn(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(t.geo.azimuthalEqualArea=function(){return En(Gn)}).raw=Gn;var Wn=Hn(function(t){var e=Math.acos(t);return e&&e/Math.sin(e)},z);function Yn(t,e){var r=Math.cos(t),n=function(t){return Math.tan(At/4+t/2)},i=t===e?Math.sin(t):Math.log(r/Math.cos(e))/Math.log(n(e)/n(t)),a=r*Math.pow(n(t),i)/i;if(!i)return $n;function o(t,e){a>0?e<-Et+kt&&(e=-Et+kt):e>Et-kt&&(e=Et-kt);var r=a/Math.pow(n(e),i);return[r*Math.sin(i*t),a-r*Math.cos(i*t)]}return o.invert=function(t,e){var r=a-e,n=zt(i)*Math.sqrt(t*t+r*r);return[Math.atan2(t,r)/i,2*Math.atan(Math.pow(a/n,1/i))-Et]},o}function Xn(t,e){var r=Math.cos(t),n=t===e?Math.sin(t):(r-Math.cos(e))/(e-t),i=r/n+t;if(y(n)1&&Ot(t[r[n-2]],t[r[n-1]],t[i])<=0;)--n;r[n++]=i}return r.slice(0,n)}function ii(t,e){return t[0]-e[0]||t[1]-e[1]}(t.geo.stereographic=function(){return En(Qn)}).raw=Qn,ti.invert=function(t,e){return[-e,2*Math.atan(Math.exp(t))-Et]},(t.geo.transverseMercator=function(){var t=Jn(ti),e=t.center,r=t.rotate;return t.center=function(t){return t?e([-t[1],t[0]]):[(t=e())[1],-t[0]]},t.rotate=function(t){return t?r([t[0],t[1],t.length>2?t[2]+90:90]):[(t=r())[0],t[1],t[2]-90]},r([0,0,90])}).raw=ti,t.geom={},t.geom.hull=function(t){var e=ei,r=ri;if(arguments.length)return n(t);function n(t){if(t.length<3)return[];var n,i=ge(e),a=ge(r),o=t.length,s=[],l=[];for(n=0;n=0;--n)p.push(t[s[c[n]][2]]);for(n=+f;nkt)s=s.L;else{if(!((i=a-wi(s,o))>kt)){n>-kt?(e=s.P,r=s):i>-kt?(e=s,r=s.N):e=r=s;break}if(!s.R){e=s;break}s=s.R}var l=vi(t);if(fi.insert(e,l),e||r){if(e===r)return Si(e),r=vi(e.site),fi.insert(l,r),l.edge=r.edge=Li(e.site,l.site),Ti(e),void Ti(r);if(r){Si(e),Si(r);var c=e.site,u=c.x,f=c.y,h=t.x-u,p=t.y-f,d=r.site,m=d.x-u,g=d.y-f,v=2*(h*g-p*m),y=h*h+p*p,x=m*m+g*g,b={x:(g*y-p*x)/v+u,y:(h*x-m*y)/v+f};zi(r.edge,c,d,b),l.edge=Li(c,t,null,b),r.edge=Li(t,d,null,b),Ti(e),Ti(r)}else l.edge=Li(e.site,l.site)}}function _i(t,e){var r=t.site,n=r.x,i=r.y,a=i-e;if(!a)return n;var o=t.P;if(!o)return-1/0;var s=(r=o.site).x,l=r.y,c=l-e;if(!c)return s;var u=s-n,f=1/a-1/c,h=u/c;return f?(-h+Math.sqrt(h*h-2*f*(u*u/(-2*c)-l+c/2+i-a/2)))/f+n:(n+s)/2}function wi(t,e){var r=t.N;if(r)return _i(r,e);var n=t.site;return n.y===e?n.x:1/0}function ki(t){this.site=t,this.edges=[]}function Mi(t,e){return e.angle-t.angle}function Ai(){Pi(this),this.x=this.y=this.arc=this.site=this.cy=null}function Ti(t){var e=t.P,r=t.N;if(e&&r){var n=e.site,i=t.site,a=r.site;if(n!==a){var o=i.x,s=i.y,l=n.x-o,c=n.y-s,u=a.x-o,f=2*(l*(g=a.y-s)-c*u);if(!(f>=-Mt)){var h=l*l+c*c,p=u*u+g*g,d=(g*h-c*p)/f,m=(l*p-u*h)/f,g=m+s,v=mi.pop()||new Ai;v.arc=t,v.site=i,v.x=d+o,v.y=g+Math.sqrt(d*d+m*m),v.cy=g,t.circle=v;for(var y=null,x=pi._;x;)if(v.y=s)return;if(h>d){if(a){if(a.y>=c)return}else a={x:g,y:l};r={x:g,y:c}}else{if(a){if(a.y1)if(h>d){if(a){if(a.y>=c)return}else a={x:(l-i)/n,y:l};r={x:(c-i)/n,y:c}}else{if(a){if(a.y=s)return}else a={x:o,y:n*o+i};r={x:s,y:n*s+i}}else{if(a){if(a.xkt||y(i-r)>kt)&&(s.splice(o,0,new Oi((v=a.site,x=u,b=y(n-f)kt?{x:f,y:y(e-f)kt?{x:y(r-d)kt?{x:h,y:y(e-h)kt?{x:y(r-p)=r&&c.x<=i&&c.y>=n&&c.y<=o?[[r,o],[i,o],[i,n],[r,n]]:[]).point=t[s]}),e}function s(t){return t.map(function(t,e){return{x:Math.round(n(t,e)/kt)*kt,y:Math.round(i(t,e)/kt)*kt,i:e}})}return o.links=function(t){return Fi(s(t)).edges.filter(function(t){return t.l&&t.r}).map(function(e){return{source:t[e.l.i],target:t[e.r.i]}})},o.triangles=function(t){var e=[];return Fi(s(t)).cells.forEach(function(r,n){for(var i,a,o,s,l=r.site,c=r.edges.sort(Mi),u=-1,f=c.length,h=c[f-1].edge,p=h.l===l?h.r:h.l;++ua&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(r=r[0])===(n=n[0])?s[o]?s[o]+=n:s[++o]=n:(s[++o]=null,l.push({i:o,x:Gi(r,n)})),a=Xi.lastIndex;return am&&(m=l.x),l.y>g&&(g=l.y),c.push(l.x),u.push(l.y);else for(f=0;fm&&(m=b),_>g&&(g=_),c.push(b),u.push(_)}var w=m-p,k=g-d;function M(t,e,r,n,i,a,o,s){if(!isNaN(r)&&!isNaN(n))if(t.leaf){var l=t.x,c=t.y;if(null!=l)if(y(l-r)+y(c-n)<.01)A(t,e,r,n,i,a,o,s);else{var u=t.point;t.x=t.y=t.point=null,A(t,u,l,c,i,a,o,s),A(t,e,r,n,i,a,o,s)}else t.x=r,t.y=n,t.point=e}else A(t,e,r,n,i,a,o,s)}function A(t,e,r,n,i,a,o,s){var l=.5*(i+o),c=.5*(a+s),u=r>=l,f=n>=c,h=f<<1|u;t.leaf=!1,u?i=l:o=l,f?a=c:s=c,M(t=t.nodes[h]||(t.nodes[h]={leaf:!0,nodes:[],point:null,x:null,y:null,add:function(t){M(T,t,+v(t,++f),+x(t,f),p,d,m,g)}}),e,r,n,i,a,o,s)}w>k?g=d+w:m=p+k;var T={leaf:!0,nodes:[],point:null,x:null,y:null,add:function(t){M(T,t,+v(t,++f),+x(t,f),p,d,m,g)}};if(T.visit=function(t){!function t(e,r,n,i,a,o){if(!e(r,n,i,a,o)){var s=.5*(n+a),l=.5*(i+o),c=r.nodes;c[0]&&t(e,c[0],n,i,s,l),c[1]&&t(e,c[1],s,i,a,l),c[2]&&t(e,c[2],n,l,s,o),c[3]&&t(e,c[3],s,l,a,o)}}(t,T,p,d,m,g)},T.find=function(t){return function(t,e,r,n,i,a,o){var s,l=1/0;return function t(c,u,f,h,p){if(!(u>a||f>o||h=_)<<1|e>=b,k=w+4;w=0&&!(n=t.interpolators[i](e,r)););return n}function $i(t,e){var r,n=[],i=[],a=t.length,o=e.length,s=Math.min(t.length,e.length);for(r=0;r=1)return 1;var e=t*t,r=e*t;return 4*(t<.5?r:3*(t-e)+r-.75)}function aa(t){return 1-Math.cos(t*Et)}function oa(t){return Math.pow(2,10*(t-1))}function sa(t){return 1-Math.sqrt(1-t*t)}function la(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function ca(t,e){return e-=t,function(r){return Math.round(t+e*r)}}function ua(t){var e,r,n,i=[t.a,t.b],a=[t.c,t.d],o=ha(i),s=fa(i,a),l=ha(((e=a)[0]+=(n=-s)*(r=i)[0],e[1]+=n*r[1],e))||0;i[0]*a[1]=0?t.slice(0,n):t,a=n>=0?t.slice(n+1):"in";return i=Ki.get(i)||Ji,a=Qi.get(a)||z,e=a(i.apply(null,r.call(arguments,1))),function(t){return t<=0?0:t>=1?1:e(t)}},t.interpolateHcl=function(e,r){e=t.hcl(e),r=t.hcl(r);var n=e.h,i=e.c,a=e.l,o=r.h-n,s=r.c-i,l=r.l-a;isNaN(s)&&(s=0,i=isNaN(i)?r.c:i);isNaN(o)?(o=0,n=isNaN(n)?r.h:n):o>180?o-=360:o<-180&&(o+=360);return function(t){return Yt(n+o*t,i+s*t,a+l*t)+""}},t.interpolateHsl=function(e,r){e=t.hsl(e),r=t.hsl(r);var n=e.h,i=e.s,a=e.l,o=r.h-n,s=r.s-i,l=r.l-a;isNaN(s)&&(s=0,i=isNaN(i)?r.s:i);isNaN(o)?(o=0,n=isNaN(n)?r.h:n):o>180?o-=360:o<-180&&(o+=360);return function(t){return Ht(n+o*t,i+s*t,a+l*t)+""}},t.interpolateLab=function(e,r){e=t.lab(e),r=t.lab(r);var n=e.l,i=e.a,a=e.b,o=r.l-n,s=r.a-i,l=r.b-a;return function(t){return te(n+o*t,i+s*t,a+l*t)+""}},t.interpolateRound=ca,t.transform=function(e){var r=i.createElementNS(t.ns.prefix.svg,"g");return(t.transform=function(t){if(null!=t){r.setAttribute("transform",t);var e=r.transform.baseVal.consolidate()}return new ua(e?e.matrix:pa)})(e)},ua.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var pa={a:1,b:0,c:0,d:1,e:0,f:0};function da(t){return t.length?t.pop()+",":""}function ma(e,r){var n=[],i=[];return e=t.transform(e),r=t.transform(r),function(t,e,r,n){if(t[0]!==e[0]||t[1]!==e[1]){var i=r.push("translate(",null,",",null,")");n.push({i:i-4,x:Gi(t[0],e[0])},{i:i-2,x:Gi(t[1],e[1])})}else(e[0]||e[1])&&r.push("translate("+e+")")}(e.translate,r.translate,n,i),function(t,e,r,n){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),n.push({i:r.push(da(r)+"rotate(",null,")")-2,x:Gi(t,e)})):e&&r.push(da(r)+"rotate("+e+")")}(e.rotate,r.rotate,n,i),function(t,e,r,n){t!==e?n.push({i:r.push(da(r)+"skewX(",null,")")-2,x:Gi(t,e)}):e&&r.push(da(r)+"skewX("+e+")")}(e.skew,r.skew,n,i),function(t,e,r,n){if(t[0]!==e[0]||t[1]!==e[1]){var i=r.push(da(r)+"scale(",null,",",null,")");n.push({i:i-4,x:Gi(t[0],e[0])},{i:i-2,x:Gi(t[1],e[1])})}else 1===e[0]&&1===e[1]||r.push(da(r)+"scale("+e+")")}(e.scale,r.scale,n,i),e=r=null,function(t){for(var e,r=-1,a=i.length;++r0?n=t:(e.c=null,e.t=NaN,e=null,l.end({type:"end",alpha:n=0})):t>0&&(l.start({type:"start",alpha:n=t}),e=Me(s.tick)),s):n},s.start=function(){var t,e,r,n=v.length,l=y.length,u=c[0],d=c[1];for(t=0;t=0;)r.push(i[n])}function Ca(t,e){for(var r=[t],n=[];null!=(t=r.pop());)if(n.push(t),(a=t.children)&&(i=a.length))for(var i,a,o=-1;++o=0;)o.push(u=c[l]),u.parent=a,u.depth=a.depth+1;r&&(a.value=0),a.children=c}else r&&(a.value=+r.call(n,a,a.depth)||0),delete a.children;return Ca(i,function(e){var n,i;t&&(n=e.children)&&n.sort(t),r&&(i=e.parent)&&(i.value+=e.value)}),s}return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ea(t,function(t){t.children&&(t.value=0)}),Ca(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},t.layout.partition=function(){var e=t.layout.hierarchy(),r=[1,1];function n(t,n){var i=e.call(this,t,n);return function t(e,r,n,i){var a=e.children;if(e.x=r,e.y=e.depth*i,e.dx=n,e.dy=i,a&&(o=a.length)){var o,s,l,c=-1;for(n=e.value?n/e.value:0;++cs&&(s=n),o.push(n)}for(r=0;ri&&(n=r,i=e);return n}function qa(t){return t.reduce(Ha,0)}function Ha(t,e){return t+e[1]}function Ga(t,e){return Wa(t,Math.ceil(Math.log(e.length)/Math.LN2+1))}function Wa(t,e){for(var r=-1,n=+t[0],i=(t[1]-n)/e,a=[];++r<=e;)a[r]=i*r+n;return a}function Ya(e){return[t.min(e),t.max(e)]}function Xa(t,e){return t.value-e.value}function Za(t,e){var r=t._pack_next;t._pack_next=e,e._pack_prev=t,e._pack_next=r,r._pack_prev=e}function $a(t,e){t._pack_next=e,e._pack_prev=t}function Ja(t,e){var r=e.x-t.x,n=e.y-t.y,i=t.r+e.r;return.999*i*i>r*r+n*n}function Ka(t){if((e=t.children)&&(l=e.length)){var e,r,n,i,a,o,s,l,c=1/0,u=-1/0,f=1/0,h=-1/0;if(e.forEach(Qa),(r=e[0]).x=-r.r,r.y=0,x(r),l>1&&((n=e[1]).x=n.r,n.y=0,x(n),l>2))for(eo(r,n,i=e[2]),x(i),Za(r,i),r._pack_prev=i,Za(i,n),n=r._pack_next,a=3;a0)for(o=-1;++o=f[0]&&l<=f[1]&&((s=c[t.bisect(h,l,1,d)-1]).y+=m,s.push(a[o]));return c}return a.value=function(t){return arguments.length?(r=t,a):r},a.range=function(t){return arguments.length?(n=ge(t),a):n},a.bins=function(t){return arguments.length?(i="number"==typeof t?function(e){return Wa(e,t)}:ge(t),a):i},a.frequency=function(t){return arguments.length?(e=!!t,a):e},a},t.layout.pack=function(){var e,r=t.layout.hierarchy().sort(Xa),n=0,i=[1,1];function a(t,a){var o=r.call(this,t,a),s=o[0],l=i[0],c=i[1],u=null==e?Math.sqrt:"function"==typeof e?e:function(){return e};if(s.x=s.y=0,Ca(s,function(t){t.r=+u(t.value)}),Ca(s,Ka),n){var f=n*(e?1:Math.max(2*s.r/l,2*s.r/c))/2;Ca(s,function(t){t.r+=f}),Ca(s,Ka),Ca(s,function(t){t.r-=f})}return function t(e,r,n,i){var a=e.children;e.x=r+=i*e.x;e.y=n+=i*e.y;e.r*=i;if(a)for(var o=-1,s=a.length;++op.x&&(p=t),t.depth>d.depth&&(d=t)});var m=r(h,p)/2-h.x,g=n[0]/(p.x+r(p,h)/2+m),v=n[1]/(d.depth||1);Ea(u,function(t){t.x=(t.x+m)*g,t.y=t.depth*v})}return c}function o(t){var e=t.children,n=t.parent.children,i=t.i?n[t.i-1]:null;if(e.length){!function(t){var e,r=0,n=0,i=t.children,a=i.length;for(;--a>=0;)(e=i[a]).z+=r,e.m+=r,r+=e.s+(n+=e.c)}(t);var a=(e[0].z+e[e.length-1].z)/2;i?(t.z=i.z+r(t._,i._),t.m=t.z-a):t.z=a}else i&&(t.z=i.z+r(t._,i._));t.parent.A=function(t,e,n){if(e){for(var i,a=t,o=t,s=e,l=a.parent.children[0],c=a.m,u=o.m,f=s.m,h=l.m;s=io(s),a=no(a),s&&a;)l=no(l),(o=io(o)).a=t,(i=s.z+f-a.z-c+r(s._,a._))>0&&(ao(oo(s,t,n),t,i),c+=i,u+=i),f+=s.m,c+=a.m,h+=l.m,u+=o.m;s&&!io(o)&&(o.t=s,o.m+=f-u),a&&!no(l)&&(l.t=a,l.m+=c-h,n=t)}return n}(t,i,t.parent.A||n[0])}function s(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function l(t){t.x*=n[0],t.y=t.depth*n[1]}return a.separation=function(t){return arguments.length?(r=t,a):r},a.size=function(t){return arguments.length?(i=null==(n=t)?l:null,a):i?null:n},a.nodeSize=function(t){return arguments.length?(i=null==(n=t)?null:l,a):i?n:null},Sa(a,e)},t.layout.cluster=function(){var e=t.layout.hierarchy().sort(null).value(null),r=ro,n=[1,1],i=!1;function a(a,o){var s,l=e.call(this,a,o),c=l[0],u=0;Ca(c,function(e){var n=e.children;n&&n.length?(e.x=function(t){return t.reduce(function(t,e){return t+e.x},0)/t.length}(n),e.y=function(e){return 1+t.max(e,function(t){return t.y})}(n)):(e.x=s?u+=r(e,s):0,e.y=0,s=e)});var f=function t(e){var r=e.children;return r&&r.length?t(r[0]):e}(c),h=function t(e){var r,n=e.children;return n&&(r=n.length)?t(n[r-1]):e}(c),p=f.x-r(f,h)/2,d=h.x+r(h,f)/2;return Ca(c,i?function(t){t.x=(t.x-c.x)*n[0],t.y=(c.y-t.y)*n[1]}:function(t){t.x=(t.x-p)/(d-p)*n[0],t.y=(1-(c.y?t.y/c.y:1))*n[1]}),l}return a.separation=function(t){return arguments.length?(r=t,a):r},a.size=function(t){return arguments.length?(i=null==(n=t),a):i?null:n},a.nodeSize=function(t){return arguments.length?(i=null!=(n=t),a):i?n:null},Sa(a,e)},t.layout.treemap=function(){var e,r=t.layout.hierarchy(),n=Math.round,i=[1,1],a=null,o=so,s=!1,l="squarify",c=.5*(1+Math.sqrt(5));function u(t,e){for(var r,n,i=-1,a=t.length;++i0;)s.push(r=c[i-1]),s.area+=r.area,"squarify"!==l||(n=p(s,m))<=h?(c.pop(),h=n):(s.area-=s.pop().area,d(s,m,a,!1),m=Math.min(a.dx,a.dy),s.length=s.area=0,h=1/0);s.length&&(d(s,m,a,!0),s.length=s.area=0),e.forEach(f)}}function h(t){var e=t.children;if(e&&e.length){var r,n=o(t),i=e.slice(),a=[];for(u(i,n.dx*n.dy/t.value),a.area=0;r=i.pop();)a.push(r),a.area+=r.area,null!=r.z&&(d(a,r.z?n.dx:n.dy,n,!i.length),a.length=a.area=0);e.forEach(h)}}function p(t,e){for(var r,n=t.area,i=0,a=1/0,o=-1,s=t.length;++oi&&(i=r));return e*=e,(n*=n)?Math.max(e*i*c/n,n/(e*a*c)):1/0}function d(t,e,r,i){var a,o=-1,s=t.length,l=r.x,c=r.y,u=e?n(t.area/e):0;if(e==r.dx){for((i||u>r.dy)&&(u=r.dy);++or.dx)&&(u=r.dx);++o1);return t+e*r*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var e=t.random.normal.apply(t,arguments);return function(){return Math.exp(e())}},bates:function(e){var r=t.random.irwinHall(e);return function(){return r()/e}},irwinHall:function(t){return function(){for(var e=0,r=0;r2?go:fo,s=i?va:ga;return a=t(e,r,s,n),o=t(r,e,s,Zi),l}function l(t){return a(t)}l.invert=function(t){return o(t)};l.domain=function(t){return arguments.length?(e=t.map(Number),s()):e};l.range=function(t){return arguments.length?(r=t,s()):r};l.rangeRound=function(t){return l.range(t).interpolate(ca)};l.clamp=function(t){return arguments.length?(i=t,s()):i};l.interpolate=function(t){return arguments.length?(n=t,s()):n};l.ticks=function(t){return bo(e,t)};l.tickFormat=function(t,r){return _o(e,t,r)};l.nice=function(t){return yo(e,t),s()};l.copy=function(){return t(e,r,n,i)};return s()}([0,1],[0,1],Zi,!1)};var wo={s:1,g:1,p:1,r:1,e:1};function ko(t){return-Math.floor(Math.log(t)/Math.LN10+.01)}t.scale.log=function(){return function e(r,n,i,a){function o(t){return(i?Math.log(t<0?0:t):-Math.log(t>0?0:-t))/Math.log(n)}function s(t){return i?Math.pow(n,t):-Math.pow(n,-t)}function l(t){return r(o(t))}l.invert=function(t){return s(r.invert(t))};l.domain=function(t){return arguments.length?(i=t[0]>=0,r.domain((a=t.map(Number)).map(o)),l):a};l.base=function(t){return arguments.length?(n=+t,r.domain(a.map(o)),l):n};l.nice=function(){var t=ho(a.map(o),i?Math:Ao);return r.domain(t),a=t.map(s),l};l.ticks=function(){var t=co(a),e=[],r=t[0],l=t[1],c=Math.floor(o(r)),u=Math.ceil(o(l)),f=n%1?2:n;if(isFinite(u-c)){if(i){for(;c0;h--)e.push(s(c)*h);for(c=0;e[c]l;u--);e=e.slice(c,u)}return e};l.tickFormat=function(e,r){if(!arguments.length)return Mo;arguments.length<2?r=Mo:"function"!=typeof r&&(r=t.format(r));var i=Math.max(1,n*e/l.ticks().length);return function(t){var e=t/s(Math.round(o(t)));return e*n0?i[t-1]:r[0],tf?0:1;if(c=St)return l(c,p)+(s?l(s,1-p):"")+"Z";var d,m,g,v,y,x,b,_,w,k,M,A,T=0,S=0,E=[];if((v=(+o.apply(this,arguments)||0)/2)&&(g=n===Oo?Math.sqrt(s*s+c*c):+n.apply(this,arguments),p||(S*=-1),c&&(S=Pt(g/c*Math.sin(v))),s&&(T=Pt(g/s*Math.sin(v)))),c){y=c*Math.cos(u+S),x=c*Math.sin(u+S),b=c*Math.cos(f-S),_=c*Math.sin(f-S);var C=Math.abs(f-u-2*S)<=At?0:1;if(S&&Fo(y,x,b,_)===p^C){var L=(u+f)/2;y=c*Math.cos(L),x=c*Math.sin(L),b=_=null}}else y=x=0;if(s){w=s*Math.cos(f-T),k=s*Math.sin(f-T),M=s*Math.cos(u+T),A=s*Math.sin(u+T);var z=Math.abs(u-f+2*T)<=At?0:1;if(T&&Fo(w,k,M,A)===1-p^z){var O=(u+f)/2;w=s*Math.cos(O),k=s*Math.sin(O),M=A=null}}else w=k=0;if(h>kt&&(d=Math.min(Math.abs(c-s)/2,+r.apply(this,arguments)))>.001){m=s0?0:1}function No(t,e,r,n,i){var a=t[0]-e[0],o=t[1]-e[1],s=(i?n:-n)/Math.sqrt(a*a+o*o),l=s*o,c=-s*a,u=t[0]+l,f=t[1]+c,h=e[0]+l,p=e[1]+c,d=(u+h)/2,m=(f+p)/2,g=h-u,v=p-f,y=g*g+v*v,x=r-n,b=u*p-h*f,_=(v<0?-1:1)*Math.sqrt(Math.max(0,x*x*y-b*b)),w=(b*v-g*_)/y,k=(-b*g-v*_)/y,M=(b*v+g*_)/y,A=(-b*g+v*_)/y,T=w-d,S=k-m,E=M-d,C=A-m;return T*T+S*S>E*E+C*C&&(w=M,k=A),[[w-l,k-c],[w*r/x,k*r/x]]}function jo(t){var e=ei,r=ri,n=Wr,i=Uo,a=i.key,o=.7;function s(a){var s,l=[],c=[],u=-1,f=a.length,h=ge(e),p=ge(r);function d(){l.push("M",i(t(c),o))}for(;++u1&&i.push("H",n[0]);return i.join("")},"step-before":Ho,"step-after":Go,basis:Xo,"basis-open":function(t){if(t.length<4)return Uo(t);var e,r=[],n=-1,i=t.length,a=[0],o=[0];for(;++n<3;)e=t[n],a.push(e[0]),o.push(e[1]);r.push(Zo(Ko,a)+","+Zo(Ko,o)),--n;for(;++n9&&(i=3*e/Math.sqrt(i),o[s]=i*r,o[s+1]=i*n));s=-1;for(;++s<=l;)i=(t[Math.min(l,s+1)][0]-t[Math.max(0,s-1)][0])/(6*(1+o[s]*o[s])),a.push([i||0,o[s]*i||0]);return a}(t))}});function Uo(t){return t.length>1?t.join("L"):t+"Z"}function qo(t){return t.join("L")+"Z"}function Ho(t){for(var e=0,r=t.length,n=t[0],i=[n[0],",",n[1]];++e1){s=e[1],a=t[l],l++,n+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(a[0]-s[0])+","+(a[1]-s[1])+","+a[0]+","+a[1];for(var c=2;cAt)+",1 "+e}function l(t,e,r,n){return"Q 0,0 "+n}return a.radius=function(t){return arguments.length?(r=ge(t),a):r},a.source=function(e){return arguments.length?(t=ge(e),a):t},a.target=function(t){return arguments.length?(e=ge(t),a):e},a.startAngle=function(t){return arguments.length?(n=ge(t),a):n},a.endAngle=function(t){return arguments.length?(i=ge(t),a):i},a},t.svg.diagonal=function(){var t=Vn,e=Un,r=is;function n(n,i){var a=t.call(this,n,i),o=e.call(this,n,i),s=(a.y+o.y)/2,l=[a,{x:a.x,y:s},{x:o.x,y:s},o];return"M"+(l=l.map(r))[0]+"C"+l[1]+" "+l[2]+" "+l[3]}return n.source=function(e){return arguments.length?(t=ge(e),n):t},n.target=function(t){return arguments.length?(e=ge(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},t.svg.diagonal.radial=function(){var e=t.svg.diagonal(),r=is,n=e.projection;return e.projection=function(t){return arguments.length?n(function(t){return function(){var e=t.apply(this,arguments),r=e[0],n=e[1]-Et;return[r*Math.cos(n),r*Math.sin(n)]}}(r=t)):r},e},t.svg.symbol=function(){var t=os,e=as;function r(r,n){return(ls.get(t.call(this,r,n))||ss)(e.call(this,r,n))}return r.type=function(e){return arguments.length?(t=ge(e),r):t},r.size=function(t){return arguments.length?(e=ge(t),r):e},r};var ls=t.map({circle:ss,cross:function(t){var e=Math.sqrt(t/5)/2;return"M"+-3*e+","+-e+"H"+-e+"V"+-3*e+"H"+e+"V"+-e+"H"+3*e+"V"+e+"H"+e+"V"+3*e+"H"+-e+"V"+e+"H"+-3*e+"Z"},diamond:function(t){var e=Math.sqrt(t/(2*us)),r=e*us;return"M0,"+-e+"L"+r+",0 0,"+e+" "+-r+",0Z"},square:function(t){var e=Math.sqrt(t)/2;return"M"+-e+","+-e+"L"+e+","+-e+" "+e+","+e+" "+-e+","+e+"Z"},"triangle-down":function(t){var e=Math.sqrt(t/cs),r=e*cs/2;return"M0,"+r+"L"+e+","+-r+" "+-e+","+-r+"Z"},"triangle-up":function(t){var e=Math.sqrt(t/cs),r=e*cs/2;return"M0,"+-r+"L"+e+","+r+" "+-e+","+r+"Z"}});t.svg.symbolTypes=ls.keys();var cs=Math.sqrt(3),us=Math.tan(30*Ct);Y.transition=function(t){for(var e,r,n=ds||++vs,i=bs(t),a=[],o=ms||{time:Date.now(),ease:ia,delay:0,duration:250},s=-1,l=this.length;++s0;)c[--h].call(t,o);if(a>=1)return f.event&&f.event.end.call(t,t.__data__,e),--u.count?delete u[n]:delete t[r],1}f||(a=i.time,o=Me(function(t){var e=f.delay;if(o.t=e+a,e<=t)return h(t-e);o.c=h},0,a),f=u[n]={tween:new b,time:a,timer:o,delay:i.delay,duration:i.duration,ease:i.ease,index:e},i=null,++u.count)}gs.call=Y.call,gs.empty=Y.empty,gs.node=Y.node,gs.size=Y.size,t.transition=function(e,r){return e&&e.transition?ds?e.transition(r):e:t.selection().transition(e)},t.transition.prototype=gs,gs.select=function(t){var e,r,n,i=this.id,a=this.namespace,o=[];t=X(t);for(var s=-1,l=this.length;++srect,.s>rect").attr("width",s[1]-s[0])}function m(t){t.select(".extent").attr("y",l[0]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",l[1]-l[0])}function g(){var f,g,v=this,y=t.select(t.event.target),x=n.of(v,arguments),b=t.select(v),_=y.datum(),w=!/^(n|s)$/.test(_)&&i,k=!/^(e|w)$/.test(_)&&a,M=y.classed("extent"),A=xt(v),T=t.mouse(v),S=t.select(o(v)).on("keydown.brush",function(){32==t.event.keyCode&&(M||(f=null,T[0]-=s[1],T[1]-=l[1],M=2),F())}).on("keyup.brush",function(){32==t.event.keyCode&&2==M&&(T[0]+=s[1],T[1]+=l[1],M=0,F())});if(t.event.changedTouches?S.on("touchmove.brush",L).on("touchend.brush",O):S.on("mousemove.brush",L).on("mouseup.brush",O),b.interrupt().selectAll("*").interrupt(),M)T[0]=s[0]-T[0],T[1]=l[0]-T[1];else if(_){var E=+/w$/.test(_),C=+/^n/.test(_);g=[s[1-E]-T[0],l[1-C]-T[1]],T[0]=s[E],T[1]=l[C]}else t.event.altKey&&(f=T.slice());function L(){var e=t.mouse(v),r=!1;g&&(e[0]+=g[0],e[1]+=g[1]),M||(t.event.altKey?(f||(f=[(s[0]+s[1])/2,(l[0]+l[1])/2]),T[0]=s[+(e[0]1?{floor:function(e){for(;s(e=t.floor(e));)e=Is(e-1);return e},ceil:function(e){for(;s(e=t.ceil(e));)e=Is(+e+1);return e}}:t))},i.ticks=function(t,e){var r=co(i.domain()),n=null==t?a(r,10):"number"==typeof t?a(r,t):!t.range&&[{range:t},e];return n&&(t=n[0],e=n[1]),t.range(r[0],Is(+r[1]+1),e<1?1:e)},i.tickFormat=function(){return n},i.copy=function(){return Os(e.copy(),r,n)},vo(i,e)}function Is(t){return new Date(t)}Es.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?zs:Ls,zs.parse=function(t){var e=new Date(t);return isNaN(e)?null:e},zs.toString=Ls.toString,Ie.second=Be(function(t){return new Pe(1e3*Math.floor(t/1e3))},function(t,e){t.setTime(t.getTime()+1e3*Math.floor(e))},function(t){return t.getSeconds()}),Ie.seconds=Ie.second.range,Ie.seconds.utc=Ie.second.utc.range,Ie.minute=Be(function(t){return new Pe(6e4*Math.floor(t/6e4))},function(t,e){t.setTime(t.getTime()+6e4*Math.floor(e))},function(t){return t.getMinutes()}),Ie.minutes=Ie.minute.range,Ie.minutes.utc=Ie.minute.utc.range,Ie.hour=Be(function(t){var e=t.getTimezoneOffset()/60;return new Pe(36e5*(Math.floor(t/36e5-e)+e))},function(t,e){t.setTime(t.getTime()+36e5*Math.floor(e))},function(t){return t.getHours()}),Ie.hours=Ie.hour.range,Ie.hours.utc=Ie.hour.utc.range,Ie.month=Be(function(t){return(t=Ie.day(t)).setDate(1),t},function(t,e){t.setMonth(t.getMonth()+e)},function(t){return t.getMonth()}),Ie.months=Ie.month.range,Ie.months.utc=Ie.month.utc.range;var Ps=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ds=[[Ie.second,1],[Ie.second,5],[Ie.second,15],[Ie.second,30],[Ie.minute,1],[Ie.minute,5],[Ie.minute,15],[Ie.minute,30],[Ie.hour,1],[Ie.hour,3],[Ie.hour,6],[Ie.hour,12],[Ie.day,1],[Ie.day,2],[Ie.week,1],[Ie.month,1],[Ie.month,3],[Ie.year,1]],Rs=Es.multi([[".%L",function(t){return t.getMilliseconds()}],[":%S",function(t){return t.getSeconds()}],["%I:%M",function(t){return t.getMinutes()}],["%I %p",function(t){return t.getHours()}],["%a %d",function(t){return t.getDay()&&1!=t.getDate()}],["%b %d",function(t){return 1!=t.getDate()}],["%B",function(t){return t.getMonth()}],["%Y",Wr]]),Bs={range:function(e,r,n){return t.range(Math.ceil(e/n)*n,+r,n).map(Is)},floor:z,ceil:z};Ds.year=Ie.year,Ie.scale=function(){return Os(t.scale.linear(),Ds,Rs)};var Fs=Ds.map(function(t){return[t[0].utc,t[1]]}),Ns=Cs.multi([[".%L",function(t){return t.getUTCMilliseconds()}],[":%S",function(t){return t.getUTCSeconds()}],["%I:%M",function(t){return t.getUTCMinutes()}],["%I %p",function(t){return t.getUTCHours()}],["%a %d",function(t){return t.getUTCDay()&&1!=t.getUTCDate()}],["%b %d",function(t){return 1!=t.getUTCDate()}],["%B",function(t){return t.getUTCMonth()}],["%Y",Wr]]);function js(t){return JSON.parse(t.responseText)}function Vs(t){var e=i.createRange();return e.selectNode(i.body),e.createContextualFragment(t.responseText)}Fs.year=Ie.year.utc,Ie.scale.utc=function(){return Os(t.scale.linear(),Fs,Ns)},t.text=ve(function(t){return t.responseText}),t.json=function(t,e){return ye(t,"application/json",js,e)},t.html=function(t,e){return ye(t,"text/html",Vs,e)},t.xml=ve(function(t){return t.responseXML}),"object"==typeof e&&e.exports?e.exports=t:this.d3=t}()},{}],149:[function(t,e,r){e.exports=function(){for(var t=0;t=2)return!1;t[r]=n}return!0}):_.filter(function(t){for(var e=0;e<=s;++e){var r=v[t[e]];if(r<0)return!1;t[e]=r}return!0});if(1&s)for(var u=0;u<_.length;++u){var b=_[u],h=b[0];b[0]=b[1],b[1]=h}return _}},{"incremental-convex-hull":396,uniq:524}],151:[function(t,e,r){"use strict";e.exports=a;var n=(a.canvas=document.createElement("canvas")).getContext("2d"),i=o([32,126]);function a(t,e){Array.isArray(t)&&(t=t.join(", "));var r,a={},s=16,l=.05;e&&(2===e.length&&"number"==typeof e[0]?r=o(e):Array.isArray(e)?r=e:(e.o?r=o(e.o):e.pairs&&(r=e.pairs),e.fontSize&&(s=e.fontSize),null!=e.threshold&&(l=e.threshold))),r||(r=i),n.font=s+"px "+t;for(var c=0;cs*l){var p=(h-f)/s;a[u]=1e3*p}}return a}function o(t){for(var e=[],r=t[0];r<=t[1];r++)for(var n=String.fromCharCode(r),i=t[0];i>>31},e.exports.exponent=function(t){return(e.exports.hi(t)<<1>>>21)-1023},e.exports.fraction=function(t){var r=e.exports.lo(t),n=e.exports.hi(t),i=1048575&n;return 2146435072&n&&(i+=1<<20),[r,i]},e.exports.denormalized=function(t){return!(2146435072&e.exports.hi(t))}}).call(this,t("buffer").Buffer)},{buffer:93}],153:[function(t,e,r){var n=t("abs-svg-path"),i=t("normalize-svg-path"),a={M:"moveTo",C:"bezierCurveTo"};e.exports=function(t,e){t.beginPath(),i(n(e)).forEach(function(e){var r=e[0],n=e.slice(1);t[a[r]].apply(t,n)}),t.closePath()}},{"abs-svg-path":48,"normalize-svg-path":435}],154:[function(t,e,r){e.exports=function(t){switch(t){case"int8":return Int8Array;case"int16":return Int16Array;case"int32":return Int32Array;case"uint8":return Uint8Array;case"uint16":return Uint16Array;case"uint32":return Uint32Array;case"float32":return Float32Array;case"float64":return Float64Array;case"array":return Array;case"uint8_clamped":return Uint8ClampedArray}}},{}],155:[function(t,e,r){"use strict";e.exports=function(t,e){switch("undefined"==typeof e&&(e=0),typeof t){case"number":if(t>0)return function(t,e){var r,n;for(r=new Array(t),n=0;n80*r){n=l=t[0],s=c=t[1];for(var b=r;bl&&(l=u),p>c&&(c=p);m=0!==(m=Math.max(l-n,c-s))?1/m:0}return o(y,x,r,n,s,m),x}function i(t,e,r,n,i){var a,o;if(i===A(t,e,r,n)>0)for(a=e;a=e;a-=n)o=w(a,t[a],t[a+1],o);return o&&y(o,o.next)&&(k(o),o=o.next),o}function a(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!y(n,n.next)&&0!==v(n.prev,n,n.next))n=n.next;else{if(k(n),(n=e=n.prev)===n.next)break;r=!0}}while(r||n!==e);return e}function o(t,e,r,n,i,f,h){if(t){!h&&f&&function(t,e,r,n){var i=t;do{null===i.z&&(i.z=p(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,function(t){var e,r,n,i,a,o,s,l,c=1;do{for(r=t,t=null,a=null,o=0;r;){for(o++,n=r,s=0,e=0;e0||l>0&&n;)0!==s&&(0===l||!n||r.z<=n.z)?(i=r,r=r.nextZ,s--):(i=n,n=n.nextZ,l--),a?a.nextZ=i:t=i,i.prevZ=a,a=i;r=n}a.nextZ=null,c*=2}while(o>1)}(i)}(t,n,i,f);for(var d,m,g=t;t.prev!==t.next;)if(d=t.prev,m=t.next,f?l(t,n,i,f):s(t))e.push(d.i/r),e.push(t.i/r),e.push(m.i/r),k(t),t=m.next,g=m.next;else if((t=m)===g){h?1===h?o(t=c(t,e,r),e,r,n,i,f,2):2===h&&u(t,e,r,n,i,f):o(a(t),e,r,n,i,f,1);break}}}function s(t){var e=t.prev,r=t,n=t.next;if(v(e,r,n)>=0)return!1;for(var i=t.next.next;i!==t.prev;){if(m(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&v(i.prev,i,i.next)>=0)return!1;i=i.next}return!0}function l(t,e,r,n){var i=t.prev,a=t,o=t.next;if(v(i,a,o)>=0)return!1;for(var s=i.xa.x?i.x>o.x?i.x:o.x:a.x>o.x?a.x:o.x,u=i.y>a.y?i.y>o.y?i.y:o.y:a.y>o.y?a.y:o.y,f=p(s,l,e,r,n),h=p(c,u,e,r,n),d=t.prevZ,g=t.nextZ;d&&d.z>=f&&g&&g.z<=h;){if(d!==t.prev&&d!==t.next&&m(i.x,i.y,a.x,a.y,o.x,o.y,d.x,d.y)&&v(d.prev,d,d.next)>=0)return!1;if(d=d.prevZ,g!==t.prev&&g!==t.next&&m(i.x,i.y,a.x,a.y,o.x,o.y,g.x,g.y)&&v(g.prev,g,g.next)>=0)return!1;g=g.nextZ}for(;d&&d.z>=f;){if(d!==t.prev&&d!==t.next&&m(i.x,i.y,a.x,a.y,o.x,o.y,d.x,d.y)&&v(d.prev,d,d.next)>=0)return!1;d=d.prevZ}for(;g&&g.z<=h;){if(g!==t.prev&&g!==t.next&&m(i.x,i.y,a.x,a.y,o.x,o.y,g.x,g.y)&&v(g.prev,g,g.next)>=0)return!1;g=g.nextZ}return!0}function c(t,e,r){var n=t;do{var i=n.prev,a=n.next.next;!y(i,a)&&x(i,n,n.next,a)&&b(i,a)&&b(a,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(a.i/r),k(n),k(n.next),n=t=a),n=n.next}while(n!==t);return n}function u(t,e,r,n,i,s){var l=t;do{for(var c=l.next.next;c!==l.prev;){if(l.i!==c.i&&g(l,c)){var u=_(l,c);return l=a(l,l.next),u=a(u,u.next),o(l,e,r,n,i,s),void o(u,e,r,n,i,s)}c=c.next}l=l.next}while(l!==t)}function f(t,e){return t.x-e.x}function h(t,e){if(e=function(t,e){var r,n=e,i=t.x,a=t.y,o=-1/0;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){var s=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(s<=i&&s>o){if(o=s,s===i){if(a===n.y)return n;if(a===n.next.y)return n.next}r=n.x=n.x&&n.x>=u&&i!==n.x&&m(ar.x)&&b(n,t)&&(r=n,h=l),n=n.next;return r}(t,e)){var r=_(e,t);a(r,r.next)}}function p(t,e,r,n,i){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*i)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*i)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function d(t){var e=t,r=t;do{e.x=0&&(t-o)*(n-s)-(r-o)*(e-s)>=0&&(r-o)*(a-s)-(i-o)*(n-s)>=0}function g(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&x(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}(t,e)&&b(t,e)&&b(e,t)&&function(t,e){var r=t,n=!1,i=(t.x+e.x)/2,a=(t.y+e.y)/2;do{r.y>a!=r.next.y>a&&r.next.y!==r.y&&i<(r.next.x-r.x)*(a-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next}while(r!==t);return n}(t,e)}function v(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function y(t,e){return t.x===e.x&&t.y===e.y}function x(t,e,r,n){return!!(y(t,e)&&y(r,n)||y(t,n)&&y(r,e))||v(t,e,r)>0!=v(t,e,n)>0&&v(r,n,t)>0!=v(r,n,e)>0}function b(t,e){return v(t.prev,t,t.next)<0?v(t,e,t.next)>=0&&v(t,t.prev,e)>=0:v(t,e,t.prev)<0||v(t,t.next,e)<0}function _(t,e){var r=new M(t.i,t.x,t.y),n=new M(e.i,e.x,e.y),i=t.next,a=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,a.next=n,n.prev=a,n}function w(t,e,r,n){var i=new M(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function k(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function M(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}function A(t,e,r,n){for(var i=0,a=e,o=r-n;a0&&(n+=t[i-1].length,r.holes.push(n))}return r}},{}],157:[function(t,e,r){"use strict";e.exports=function(t,e){var r=t.length;if("number"!=typeof e){e=0;for(var i=0;i=55296&&y<=56319&&(w+=t[++r]),w=k?h.call(k,M,w,m):w,e?(p.value=w,d(g,m,p)):g[m]=w,++m;v=m}if(void 0===v)for(v=o(t.length),e&&(g=new e(v)),r=0;r0?1:-1}},{}],168:[function(t,e,r){"use strict";var n=t("../math/sign"),i=Math.abs,a=Math.floor;e.exports=function(t){return isNaN(t)?0:0!==(t=Number(t))&&isFinite(t)?n(t)*a(i(t)):t}},{"../math/sign":165}],169:[function(t,e,r){"use strict";var n=t("./to-integer"),i=Math.max;e.exports=function(t){return i(0,n(t))}},{"./to-integer":168}],170:[function(t,e,r){"use strict";var n=t("./valid-callable"),i=t("./valid-value"),a=Function.prototype.bind,o=Function.prototype.call,s=Object.keys,l=Object.prototype.propertyIsEnumerable;e.exports=function(t,e){return function(r,c){var u,f=arguments[2],h=arguments[3];return r=Object(i(r)),n(c),u=s(r),h&&u.sort("function"==typeof h?a.call(h,r):void 0),"function"!=typeof t&&(t=u[t]),o.call(t,u,function(t,n){return l.call(r,t)?o.call(c,f,r[t],t,r,n):e})}}},{"./valid-callable":188,"./valid-value":190}],171:[function(t,e,r){"use strict";e.exports=t("./is-implemented")()?Object.assign:t("./shim")},{"./is-implemented":172,"./shim":173}],172:[function(t,e,r){"use strict";e.exports=function(){var t,e=Object.assign;return"function"==typeof e&&(e(t={foo:"raz"},{bar:"dwa"},{trzy:"trzy"}),t.foo+t.bar+t.trzy==="razdwatrzy")}},{}],173:[function(t,e,r){"use strict";var n=t("../keys"),i=t("../valid-value"),a=Math.max;e.exports=function(t,e){var r,o,s,l=a(arguments.length,2);for(t=Object(i(t)),s=function(n){try{t[n]=e[n]}catch(t){r||(r=t)}},o=1;o-1}},{}],194:[function(t,e,r){"use strict";var n=Object.prototype.toString,i=n.call("");e.exports=function(t){return"string"==typeof t||t&&"object"==typeof t&&(t instanceof String||n.call(t)===i)||!1}},{}],195:[function(t,e,r){"use strict";var n=Object.create(null),i=Math.random;e.exports=function(){var t;do{t=i().toString(36).slice(2)}while(n[t]);return t}},{}],196:[function(t,e,r){"use strict";var n,i=t("es5-ext/object/set-prototype-of"),a=t("es5-ext/string/#/contains"),o=t("d"),s=t("es6-symbol"),l=t("./"),c=Object.defineProperty;n=e.exports=function(t,e){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");l.call(this,t),e=e?a.call(e,"key+value")?"key+value":a.call(e,"key")?"key":"value":"value",c(this,"__kind__",o("",e))},i&&i(n,l),delete n.prototype.constructor,n.prototype=Object.create(l.prototype,{_resolve:o(function(t){return"value"===this.__kind__?this.__list__[t]:"key+value"===this.__kind__?[t,this.__list__[t]]:t})}),c(n.prototype,s.toStringTag,o("c","Array Iterator"))},{"./":199,d:139,"es5-ext/object/set-prototype-of":185,"es5-ext/string/#/contains":191,"es6-symbol":204}],197:[function(t,e,r){"use strict";var n=t("es5-ext/function/is-arguments"),i=t("es5-ext/object/valid-callable"),a=t("es5-ext/string/is-string"),o=t("./get"),s=Array.isArray,l=Function.prototype.call,c=Array.prototype.some;e.exports=function(t,e){var r,u,f,h,p,d,m,g,v=arguments[2];if(s(t)||n(t)?r="array":a(t)?r="string":t=o(t),i(e),f=function(){h=!0},"array"!==r)if("string"!==r)for(u=t.next();!u.done;){if(l.call(e,v,u.value,f),h)return;u=t.next()}else for(d=t.length,p=0;p=55296&&g<=56319&&(m+=t[++p]),l.call(e,v,m,f),!h);++p);else c.call(t,function(t){return l.call(e,v,t,f),h})}},{"./get":198,"es5-ext/function/is-arguments":162,"es5-ext/object/valid-callable":188,"es5-ext/string/is-string":194}],198:[function(t,e,r){"use strict";var n=t("es5-ext/function/is-arguments"),i=t("es5-ext/string/is-string"),a=t("./array"),o=t("./string"),s=t("./valid-iterable"),l=t("es6-symbol").iterator;e.exports=function(t){return"function"==typeof s(t)[l]?t[l]():n(t)?new a(t):i(t)?new o(t):new a(t)}},{"./array":196,"./string":201,"./valid-iterable":202,"es5-ext/function/is-arguments":162,"es5-ext/string/is-string":194,"es6-symbol":204}],199:[function(t,e,r){"use strict";var n,i=t("es5-ext/array/#/clear"),a=t("es5-ext/object/assign"),o=t("es5-ext/object/valid-callable"),s=t("es5-ext/object/valid-value"),l=t("d"),c=t("d/auto-bind"),u=t("es6-symbol"),f=Object.defineProperty,h=Object.defineProperties;e.exports=n=function(t,e){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");h(this,{__list__:l("w",s(t)),__context__:l("w",e),__nextIndex__:l("w",0)}),e&&(o(e.on),e.on("_add",this._onAdd),e.on("_delete",this._onDelete),e.on("_clear",this._onClear))},delete n.prototype.constructor,h(n.prototype,a({_next:l(function(){var t;if(this.__list__)return this.__redo__&&void 0!==(t=this.__redo__.shift())?t:this.__nextIndex__=this.__nextIndex__||(++this.__nextIndex__,this.__redo__?(this.__redo__.forEach(function(e,r){e>=t&&(this.__redo__[r]=++e)},this),this.__redo__.push(t)):f(this,"__redo__",l("c",[t])))}),_onDelete:l(function(t){var e;t>=this.__nextIndex__||(--this.__nextIndex__,this.__redo__&&(-1!==(e=this.__redo__.indexOf(t))&&this.__redo__.splice(e,1),this.__redo__.forEach(function(e,r){e>t&&(this.__redo__[r]=--e)},this)))}),_onClear:l(function(){this.__redo__&&i.call(this.__redo__),this.__nextIndex__=0})}))),f(n.prototype,u.iterator,l(function(){return this}))},{d:139,"d/auto-bind":138,"es5-ext/array/#/clear":158,"es5-ext/object/assign":171,"es5-ext/object/valid-callable":188,"es5-ext/object/valid-value":190,"es6-symbol":204}],200:[function(t,e,r){"use strict";var n=t("es5-ext/function/is-arguments"),i=t("es5-ext/object/is-value"),a=t("es5-ext/string/is-string"),o=t("es6-symbol").iterator,s=Array.isArray;e.exports=function(t){return!!i(t)&&(!!s(t)||(!!a(t)||(!!n(t)||"function"==typeof t[o])))}},{"es5-ext/function/is-arguments":162,"es5-ext/object/is-value":179,"es5-ext/string/is-string":194,"es6-symbol":204}],201:[function(t,e,r){"use strict";var n,i=t("es5-ext/object/set-prototype-of"),a=t("d"),o=t("es6-symbol"),s=t("./"),l=Object.defineProperty;n=e.exports=function(t){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");t=String(t),s.call(this,t),l(this,"__length__",a("",t.length))},i&&i(n,s),delete n.prototype.constructor,n.prototype=Object.create(s.prototype,{_next:a(function(){if(this.__list__)return this.__nextIndex__=55296&&e<=56319?r+this.__list__[this.__nextIndex__++]:r})}),l(n.prototype,o.toStringTag,a("c","String Iterator"))},{"./":199,d:139,"es5-ext/object/set-prototype-of":185,"es6-symbol":204}],202:[function(t,e,r){"use strict";var n=t("./is-iterable");e.exports=function(t){if(!n(t))throw new TypeError(t+" is not iterable");return t}},{"./is-iterable":200}],203:[function(t,e,r){(function(n,i){!function(t,n){"object"==typeof r&&"undefined"!=typeof e?e.exports=n():t.ES6Promise=n()}(this,function(){"use strict";function e(t){return"function"==typeof t}var r=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},a=0,o=void 0,s=void 0,l=function(t,e){m[a]=t,m[a+1]=e,2===(a+=2)&&(s?s(g):_())};var c="undefined"!=typeof window?window:void 0,u=c||{},f=u.MutationObserver||u.WebKitMutationObserver,h="undefined"==typeof self&&"undefined"!=typeof n&&"[object process]"==={}.toString.call(n),p="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function d(){var t=setTimeout;return function(){return t(g,1)}}var m=new Array(1e3);function g(){for(var t=0;t=r-1){h=l.length-1;var d=t-e[r-1];for(p=0;p=r-1)for(var u=s.length-1,f=(e[r-1],0);f=0;--r)if(t[--e])return!1;return!0},s.jump=function(t){var e=this.lastT(),r=this.dimension;if(!(t0;--f)n.push(a(l[f-1],c[f-1],arguments[f])),i.push(0)}},s.push=function(t){var e=this.lastT(),r=this.dimension;if(!(t1e-6?1/s:0;this._time.push(t);for(var h=r;h>0;--h){var p=a(c[h-1],u[h-1],arguments[h]);n.push(p),i.push((p-n[o++])*f)}}},s.set=function(t){var e=this.dimension;if(!(t0;--l)r.push(a(o[l-1],s[l-1],arguments[l])),n.push(0)}},s.move=function(t){var e=this.lastT(),r=this.dimension;if(!(t<=e||arguments.length!==r+1)){var n=this._state,i=this._velocity,o=n.length-this.dimension,s=this.bounds,l=s[0],c=s[1],u=t-e,f=u>1e-6?1/u:0;this._time.push(t);for(var h=r;h>0;--h){var p=arguments[h];n.push(a(l[h-1],c[h-1],n[o++]+p)),i.push(p*f)}}},s.idle=function(t){var e=this.lastT();if(!(t=0;--f)n.push(a(l[f],c[f],n[o]+u*i[o])),i.push(0),o+=1}}},{"binary-search-bounds":79,"cubic-hermite":133}],216:[function(t,e,r){var n=t("dtype");e.exports=function(t,e,r){if(!t)throw new TypeError("must specify data as first parameter");if(r=0|+(r||0),Array.isArray(t)&&t[0]&&"number"==typeof t[0][0]){var i,a,o,s,l=t[0].length,c=t.length*l;e&&"string"!=typeof e||(e=new(n(e||"float32"))(c+r));var u=e.length-r;if(c!==u)throw new Error("source length "+c+" ("+l+"x"+t.length+") does not match destination length "+u);for(i=0,o=r;ie[0]-o[0]/2&&(h=o[0]/2,p+=o[1]);return r}},{"css-font/stringify":130}],218:[function(t,e,r){"use strict";function n(t,e){e||(e={}),("string"==typeof t||Array.isArray(t))&&(e.family=t);var r=Array.isArray(e.family)?e.family.join(", "):e.family;if(!r)throw Error("`family` must be defined");var s=e.size||e.fontSize||e.em||48,l=e.weight||e.fontWeight||"",c=(t=[e.style||e.fontStyle||"",l,s].join(" ")+"px "+r,e.origin||"top");if(n.cache[r]&&s<=n.cache[r].em)return i(n.cache[r],c);var u=e.canvas||n.canvas,f=u.getContext("2d"),h={upper:void 0!==e.upper?e.upper:"H",lower:void 0!==e.lower?e.lower:"x",descent:void 0!==e.descent?e.descent:"p",ascent:void 0!==e.ascent?e.ascent:"h",tittle:void 0!==e.tittle?e.tittle:"i",overshoot:void 0!==e.overshoot?e.overshoot:"O"},p=Math.ceil(1.5*s);u.height=p,u.width=.5*p,f.font=t;var d={top:0};f.clearRect(0,0,p,p),f.textBaseline="top",f.fillStyle="black",f.fillText("H",0,0);var m=a(f.getImageData(0,0,p,p));f.clearRect(0,0,p,p),f.textBaseline="bottom",f.fillText("H",0,p);var g=a(f.getImageData(0,0,p,p));d.lineHeight=d.bottom=p-g+m,f.clearRect(0,0,p,p),f.textBaseline="alphabetic",f.fillText("H",0,p);var v=p-a(f.getImageData(0,0,p,p))-1+m;d.baseline=d.alphabetic=v,f.clearRect(0,0,p,p),f.textBaseline="middle",f.fillText("H",0,.5*p);var y=a(f.getImageData(0,0,p,p));d.median=d.middle=p-y-1+m-.5*p,f.clearRect(0,0,p,p),f.textBaseline="hanging",f.fillText("H",0,.5*p);var x=a(f.getImageData(0,0,p,p));d.hanging=p-x-1+m-.5*p,f.clearRect(0,0,p,p),f.textBaseline="ideographic",f.fillText("H",0,p);var b=a(f.getImageData(0,0,p,p));if(d.ideographic=p-b-1+m,h.upper&&(f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.upper,0,0),d.upper=a(f.getImageData(0,0,p,p)),d.capHeight=d.baseline-d.upper),h.lower&&(f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.lower,0,0),d.lower=a(f.getImageData(0,0,p,p)),d.xHeight=d.baseline-d.lower),h.tittle&&(f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.tittle,0,0),d.tittle=a(f.getImageData(0,0,p,p))),h.ascent&&(f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.ascent,0,0),d.ascent=a(f.getImageData(0,0,p,p))),h.descent&&(f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.descent,0,0),d.descent=o(f.getImageData(0,0,p,p))),h.overshoot){f.clearRect(0,0,p,p),f.textBaseline="top",f.fillText(h.overshoot,0,0);var _=o(f.getImageData(0,0,p,p));d.overshoot=_-v}for(var w in d)d[w]/=s;return d.em=s,n.cache[r]=d,i(d,c)}function i(t,e){var r={};for(var n in"string"==typeof e&&(e=t[e]),t)"em"!==n&&(r[n]=t[n]-e);return r}function a(t){for(var e=t.height,r=t.data,n=3;n0;n-=4)if(0!==r[n])return Math.floor(.25*(n-3)/e)}e.exports=n,n.canvas=document.createElement("canvas"),n.cache={}},{}],219:[function(t,e,r){"use strict";e.exports=function(t){return new c(t||d,null)};var n=0,i=1;function a(t,e,r,n,i,a){this._color=t,this.key=e,this.value=r,this.left=n,this.right=i,this._count=a}function o(t){return new a(t._color,t.key,t.value,t.left,t.right,t._count)}function s(t,e){return new a(t,e.key,e.value,e.left,e.right,e._count)}function l(t){t._count=1+(t.left?t.left._count:0)+(t.right?t.right._count:0)}function c(t,e){this._compare=t,this.root=e}var u=c.prototype;function f(t,e){this.tree=t,this._stack=e}Object.defineProperty(u,"keys",{get:function(){var t=[];return this.forEach(function(e,r){t.push(e)}),t}}),Object.defineProperty(u,"values",{get:function(){var t=[];return this.forEach(function(e,r){t.push(r)}),t}}),Object.defineProperty(u,"length",{get:function(){return this.root?this.root._count:0}}),u.insert=function(t,e){for(var r=this._compare,o=this.root,u=[],f=[];o;){var h=r(t,o.key);u.push(o),f.push(h),o=h<=0?o.left:o.right}u.push(new a(n,t,e,null,null,1));for(var p=u.length-2;p>=0;--p){o=u[p];f[p]<=0?u[p]=new a(o._color,o.key,o.value,u[p+1],o.right,o._count+1):u[p]=new a(o._color,o.key,o.value,o.left,u[p+1],o._count+1)}for(p=u.length-1;p>1;--p){var d=u[p-1];o=u[p];if(d._color===i||o._color===i)break;var m=u[p-2];if(m.left===d)if(d.left===o){if(!(g=m.right)||g._color!==n){if(m._color=n,m.left=d.right,d._color=i,d.right=m,u[p-2]=d,u[p-1]=o,l(m),l(d),p>=3)(v=u[p-3]).left===m?v.left=d:v.right=d;break}d._color=i,m.right=s(i,g),m._color=n,p-=1}else{if(!(g=m.right)||g._color!==n){if(d.right=o.left,m._color=n,m.left=o.right,o._color=i,o.left=d,o.right=m,u[p-2]=o,u[p-1]=d,l(m),l(d),l(o),p>=3)(v=u[p-3]).left===m?v.left=o:v.right=o;break}d._color=i,m.right=s(i,g),m._color=n,p-=1}else if(d.right===o){if(!(g=m.left)||g._color!==n){if(m._color=n,m.right=d.left,d._color=i,d.left=m,u[p-2]=d,u[p-1]=o,l(m),l(d),p>=3)(v=u[p-3]).right===m?v.right=d:v.left=d;break}d._color=i,m.left=s(i,g),m._color=n,p-=1}else{var g;if(!(g=m.left)||g._color!==n){var v;if(d.left=o.right,m._color=n,m.right=o.left,o._color=i,o.right=d,o.left=m,u[p-2]=o,u[p-1]=d,l(m),l(d),l(o),p>=3)(v=u[p-3]).right===m?v.right=o:v.left=o;break}d._color=i,m.left=s(i,g),m._color=n,p-=1}}return u[0]._color=i,new c(r,u[0])},u.forEach=function(t,e,r){if(this.root)switch(arguments.length){case 1:return function t(e,r){var n;if(r.left&&(n=t(e,r.left)))return n;return(n=e(r.key,r.value))||(r.right?t(e,r.right):void 0)}(t,this.root);case 2:return function t(e,r,n,i){if(r(e,i.key)<=0){var a;if(i.left&&(a=t(e,r,n,i.left)))return a;if(a=n(i.key,i.value))return a}if(i.right)return t(e,r,n,i.right)}(e,this._compare,t,this.root);case 3:if(this._compare(e,r)>=0)return;return function t(e,r,n,i,a){var o,s=n(e,a.key),l=n(r,a.key);if(s<=0){if(a.left&&(o=t(e,r,n,i,a.left)))return o;if(l>0&&(o=i(a.key,a.value)))return o}if(l>0&&a.right)return t(e,r,n,i,a.right)}(e,r,this._compare,t,this.root)}},Object.defineProperty(u,"begin",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.left;return new f(this,t)}}),Object.defineProperty(u,"end",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.right;return new f(this,t)}}),u.at=function(t){if(t<0)return new f(this,[]);for(var e=this.root,r=[];;){if(r.push(e),e.left){if(t=e.right._count)break;e=e.right}return new f(this,[])},u.ge=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<=0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new f(this,n)},u.gt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new f(this,n)},u.lt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new f(this,n)},u.le=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>=0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new f(this,n)},u.find=function(t){for(var e=this._compare,r=this.root,n=[];r;){var i=e(t,r.key);if(n.push(r),0===i)return new f(this,n);r=i<=0?r.left:r.right}return new f(this,[])},u.remove=function(t){var e=this.find(t);return e?e.remove():this},u.get=function(t){for(var e=this._compare,r=this.root;r;){var n=e(t,r.key);if(0===n)return r.value;r=n<=0?r.left:r.right}};var h=f.prototype;function p(t,e){t.key=e.key,t.value=e.value,t.left=e.left,t.right=e.right,t._color=e._color,t._count=e._count}function d(t,e){return te?1:0}Object.defineProperty(h,"valid",{get:function(){return this._stack.length>0}}),Object.defineProperty(h,"node",{get:function(){return this._stack.length>0?this._stack[this._stack.length-1]:null},enumerable:!0}),h.clone=function(){return new f(this.tree,this._stack.slice())},h.remove=function(){var t=this._stack;if(0===t.length)return this.tree;var e=new Array(t.length),r=t[t.length-1];e[e.length-1]=new a(r._color,r.key,r.value,r.left,r.right,r._count);for(var u=t.length-2;u>=0;--u){(r=t[u]).left===t[u+1]?e[u]=new a(r._color,r.key,r.value,e[u+1],r.right,r._count):e[u]=new a(r._color,r.key,r.value,r.left,e[u+1],r._count)}if((r=e[e.length-1]).left&&r.right){var f=e.length;for(r=r.left;r.right;)e.push(r),r=r.right;var h=e[f-1];e.push(new a(r._color,h.key,h.value,r.left,r.right,r._count)),e[f-1].key=r.key,e[f-1].value=r.value;for(u=e.length-2;u>=f;--u)r=e[u],e[u]=new a(r._color,r.key,r.value,r.left,e[u+1],r._count);e[f-1].left=e[f]}if((r=e[e.length-1])._color===n){var d=e[e.length-2];d.left===r?d.left=null:d.right===r&&(d.right=null),e.pop();for(u=0;u=0;--u){if(e=t[u],0===u)return void(e._color=i);if((r=t[u-1]).left===e){if((a=r.right).right&&a.right._color===n)return c=(a=r.right=o(a)).right=o(a.right),r.right=a.left,a.left=r,a.right=c,a._color=r._color,e._color=i,r._color=i,c._color=i,l(r),l(a),u>1&&((f=t[u-2]).left===r?f.left=a:f.right=a),void(t[u-1]=a);if(a.left&&a.left._color===n)return c=(a=r.right=o(a)).left=o(a.left),r.right=c.left,a.left=c.right,c.left=r,c.right=a,c._color=r._color,r._color=i,a._color=i,e._color=i,l(r),l(a),l(c),u>1&&((f=t[u-2]).left===r?f.left=c:f.right=c),void(t[u-1]=c);if(a._color===i){if(r._color===n)return r._color=i,void(r.right=s(n,a));r.right=s(n,a);continue}a=o(a),r.right=a.left,a.left=r,a._color=r._color,r._color=n,l(r),l(a),u>1&&((f=t[u-2]).left===r?f.left=a:f.right=a),t[u-1]=a,t[u]=r,u+11&&((f=t[u-2]).right===r?f.right=a:f.left=a),void(t[u-1]=a);if(a.right&&a.right._color===n)return c=(a=r.left=o(a)).right=o(a.right),r.left=c.right,a.right=c.left,c.right=r,c.left=a,c._color=r._color,r._color=i,a._color=i,e._color=i,l(r),l(a),l(c),u>1&&((f=t[u-2]).right===r?f.right=c:f.left=c),void(t[u-1]=c);if(a._color===i){if(r._color===n)return r._color=i,void(r.left=s(n,a));r.left=s(n,a);continue}var f;a=o(a),r.left=a.right,a.right=r,a._color=r._color,r._color=n,l(r),l(a),u>1&&((f=t[u-2]).right===r?f.right=a:f.left=a),t[u-1]=a,t[u]=r,u+10)return this._stack[this._stack.length-1].key},enumerable:!0}),Object.defineProperty(h,"value",{get:function(){if(this._stack.length>0)return this._stack[this._stack.length-1].value},enumerable:!0}),Object.defineProperty(h,"index",{get:function(){var t=0,e=this._stack;if(0===e.length){var r=this.tree.root;return r?r._count:0}e[e.length-1].left&&(t=e[e.length-1].left._count);for(var n=e.length-2;n>=0;--n)e[n+1]===e[n].right&&(++t,e[n].left&&(t+=e[n].left._count));return t},enumerable:!0}),h.next=function(){var t=this._stack;if(0!==t.length){var e=t[t.length-1];if(e.right)for(e=e.right;e;)t.push(e),e=e.left;else for(t.pop();t.length>0&&t[t.length-1].right===e;)e=t[t.length-1],t.pop()}},Object.defineProperty(h,"hasNext",{get:function(){var t=this._stack;if(0===t.length)return!1;if(t[t.length-1].right)return!0;for(var e=t.length-1;e>0;--e)if(t[e-1].left===t[e])return!0;return!1}}),h.update=function(t){var e=this._stack;if(0===e.length)throw new Error("Can't update empty node!");var r=new Array(e.length),n=e[e.length-1];r[r.length-1]=new a(n._color,n.key,t,n.left,n.right,n._count);for(var i=e.length-2;i>=0;--i)(n=e[i]).left===e[i+1]?r[i]=new a(n._color,n.key,n.value,r[i+1],n.right,n._count):r[i]=new a(n._color,n.key,n.value,n.left,r[i+1],n._count);return new c(this.tree._compare,r[0])},h.prev=function(){var t=this._stack;if(0!==t.length){var e=t[t.length-1];if(e.left)for(e=e.left;e;)t.push(e),e=e.right;else for(t.pop();t.length>0&&t[t.length-1].left===e;)e=t[t.length-1],t.pop()}},Object.defineProperty(h,"hasPrev",{get:function(){var t=this._stack;if(0===t.length)return!1;if(t[t.length-1].left)return!0;for(var e=t.length-1;e>0;--e)if(t[e-1].right===t[e])return!0;return!1}})},{}],220:[function(t,e,r){var n=[.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-176.6150291621406,12.507343278686905,-.13857109526572012,9984369578019572e-21,1.5056327351493116e-7],i=607/128,a=[.9999999999999971,57.15623566586292,-59.59796035547549,14.136097974741746,-.4919138160976202,3399464998481189e-20,4652362892704858e-20,-9837447530487956e-20,.0001580887032249125,-.00021026444172410488,.00021743961811521265,-.0001643181065367639,8441822398385275e-20,-26190838401581408e-21,36899182659531625e-22];function o(t){if(t<0)return Number("0/0");for(var e=a[0],r=a.length-1;r>0;--r)e+=a[r]/(t+r);var n=t+i+.5;return.5*Math.log(2*Math.PI)+(t+.5)*Math.log(n)-n+Math.log(e)-Math.log(t)}e.exports=function t(e){if(e<.5)return Math.PI/(Math.sin(Math.PI*e)*t(1-e));if(e>100)return Math.exp(o(e));e-=1;for(var r=n[0],i=1;i<9;i++)r+=n[i]/(e+i);var a=e+7+.5;return Math.sqrt(2*Math.PI)*Math.pow(a,e+.5)*Math.exp(-a)*r},e.exports.log=o},{}],221:[function(t,e,r){e.exports=function(t,e){if("string"!=typeof t)throw new TypeError("must specify type string");if(e=e||{},"undefined"==typeof document&&!e.canvas)return null;var r=e.canvas||document.createElement("canvas");"number"==typeof e.width&&(r.width=e.width);"number"==typeof e.height&&(r.height=e.height);var n,i=e;try{var a=[t];0===t.indexOf("webgl")&&a.push("experimental-"+t);for(var o=0;o0?(p[u]=-1,d[u]=0):(p[u]=0,d[u]=1)}}var m=[0,0,0],g={model:l,view:l,projection:l};f.isOpaque=function(){return!0},f.isTransparent=function(){return!1},f.drawTransparent=function(t){};var v=[0,0,0],y=[0,0,0],x=[0,0,0];f.draw=function(t){t=t||g;for(var e=this.gl,r=t.model||l,n=t.view||l,i=t.projection||l,a=this.bounds,s=o(r,n,i,a),u=s.cubeEdges,f=s.axis,h=n[12],b=n[13],_=n[14],w=n[15],k=this.pixelRatio*(i[3]*h+i[7]*b+i[11]*_+i[15]*w)/e.drawingBufferHeight,M=0;M<3;++M)this.lastCubeProps.cubeEdges[M]=u[M],this.lastCubeProps.axis[M]=f[M];var A=p;for(M=0;M<3;++M)d(p[M],M,this.bounds,u,f);e=this.gl;var T,S=m;for(M=0;M<3;++M)this.backgroundEnable[M]?S[M]=f[M]:S[M]=0;this._background.draw(r,n,i,a,S,this.backgroundColor),this._lines.bind(r,n,i,this);for(M=0;M<3;++M){var E=[0,0,0];f[M]>0?E[M]=a[1][M]:E[M]=a[0][M];for(var C=0;C<2;++C){var L=(M+1+C)%3,z=(M+1+(1^C))%3;this.gridEnable[L]&&this._lines.drawGrid(L,z,this.bounds,E,this.gridColor[L],this.gridWidth[L]*this.pixelRatio)}for(C=0;C<2;++C){L=(M+1+C)%3,z=(M+1+(1^C))%3;this.zeroEnable[z]&&Math.min(a[0][z],a[1][z])<=0&&Math.max(a[0][z],a[1][z])>=0&&this._lines.drawZero(L,z,this.bounds,E,this.zeroLineColor[z],this.zeroLineWidth[z]*this.pixelRatio)}}for(M=0;M<3;++M){this.lineEnable[M]&&this._lines.drawAxisLine(M,this.bounds,A[M].primalOffset,this.lineColor[M],this.lineWidth[M]*this.pixelRatio),this.lineMirror[M]&&this._lines.drawAxisLine(M,this.bounds,A[M].mirrorOffset,this.lineColor[M],this.lineWidth[M]*this.pixelRatio);var O=c(v,A[M].primalMinor),I=c(y,A[M].mirrorMinor),P=this.lineTickLength;for(C=0;C<3;++C){var D=k/r[5*C];O[C]*=P[C]*D,I[C]*=P[C]*D}this.lineTickEnable[M]&&this._lines.drawAxisTicks(M,A[M].primalOffset,O,this.lineTickColor[M],this.lineTickWidth[M]*this.pixelRatio),this.lineTickMirror[M]&&this._lines.drawAxisTicks(M,A[M].mirrorOffset,I,this.lineTickColor[M],this.lineTickWidth[M]*this.pixelRatio)}this._lines.unbind(),this._text.bind(r,n,i,this.pixelRatio);var R,B;function F(t){(B=[0,0,0])[t]=1}function N(t,e,r){var n=(t+1)%3,i=(t+2)%3,a=e[n],o=e[i],s=r[n],l=r[i];a>0&&l>0?F(n):a>0&&l<0?F(n):a<0&&l>0?F(n):a<0&&l<0?F(n):o>0&&s>0?F(i):o>0&&s<0?F(i):o<0&&s>0?F(i):o<0&&s<0&&F(i)}for(M=0;M<3;++M){var j=A[M].primalMinor,V=A[M].mirrorMinor,U=c(x,A[M].primalOffset);for(C=0;C<3;++C)this.lineTickEnable[M]&&(U[C]+=k*j[C]*Math.max(this.lineTickLength[C],0)/r[5*C]);var q=[0,0,0];if(q[M]=1,this.tickEnable[M]){-3600===this.tickAngle[M]?(this.tickAngle[M]=0,this._tickAlign[M]="auto"):this._tickAlign[M]=-1,R=1,"auto"===(T=[this._tickAlign[M],.5,R])[0]?T[0]=0:T[0]=parseInt(""+T[0]),B=[0,0,0],N(M,j,V);for(C=0;C<3;++C)U[C]+=k*j[C]*this.tickPad[C]/r[5*C];this._text.drawTicks(M,this.tickSize[M],this.tickAngle[M],U,this.tickColor[M],q,B,T)}if(this.labelEnable[M]){R=0,B=[0,0,0],this.labels[M].length>4&&(F(M),R=1),"auto"===(T=[this._labelAlign[M],.5,R])[0]?T[0]=0:T[0]=parseInt(""+T[0]);for(C=0;C<3;++C)U[C]+=k*j[C]*this.labelPad[C]/r[5*C];U[M]+=.5*(a[0][M]+a[1][M]),this._text.drawLabel(M,this.labelSize[M],this._labelAngle[M],U,this.labelColor[M],[0,0,0],B,T)}}this._text.unbind()},f.dispose=function(){this._text.dispose(),this._lines.dispose(),this._background.dispose(),this._lines=null,this._text=null,this._background=null,this.gl=null}},{"./lib/background.js":223,"./lib/cube.js":224,"./lib/lines.js":225,"./lib/text.js":227,"./lib/ticks.js":228}],223:[function(t,e,r){"use strict";e.exports=function(t){for(var e=[],r=[],s=0,l=0;l<3;++l)for(var c=(l+1)%3,u=(l+2)%3,f=[0,0,0],h=[0,0,0],p=-1;p<=1;p+=2){r.push(s,s+2,s+1,s+1,s+2,s+3),f[l]=p,h[l]=p;for(var d=-1;d<=1;d+=2){f[c]=d;for(var m=-1;m<=1;m+=2)f[u]=m,e.push(f[0],f[1],f[2],h[0],h[1],h[2]),s+=1}var g=c;c=u,u=g}var v=n(t,new Float32Array(e)),y=n(t,new Uint16Array(r),t.ELEMENT_ARRAY_BUFFER),x=i(t,[{buffer:v,type:t.FLOAT,size:3,offset:0,stride:24},{buffer:v,type:t.FLOAT,size:3,offset:12,stride:24}],y),b=a(t);return b.attributes.position.location=0,b.attributes.normal.location=1,new o(t,v,x,b)};var n=t("gl-buffer"),i=t("gl-vao"),a=t("./shaders").bg;function o(t,e,r,n){this.gl=t,this.buffer=e,this.vao=r,this.shader=n}var s=o.prototype;s.draw=function(t,e,r,n,i,a){for(var o=!1,s=0;s<3;++s)o=o||i[s];if(o){var l=this.gl;l.enable(l.POLYGON_OFFSET_FILL),l.polygonOffset(1,2),this.shader.bind(),this.shader.uniforms={model:t,view:e,projection:r,bounds:n,enable:i,colors:a},this.vao.bind(),this.vao.draw(this.gl.TRIANGLES,36),this.vao.unbind(),l.disable(l.POLYGON_OFFSET_FILL)}},s.dispose=function(){this.vao.dispose(),this.buffer.dispose(),this.shader.dispose()}},{"./shaders":226,"gl-buffer":230,"gl-vao":310}],224:[function(t,e,r){"use strict";e.exports=function(t,e,r,a){i(s,e,t),i(s,r,s);for(var p=0,y=0;y<2;++y){u[2]=a[y][2];for(var x=0;x<2;++x){u[1]=a[x][1];for(var b=0;b<2;++b)u[0]=a[b][0],h(l[p],u,s),p+=1}}for(var _=-1,y=0;y<8;++y){for(var w=l[y][3],k=0;k<3;++k)c[y][k]=l[y][k]/w;w<0&&(_<0?_=y:c[y][2]S&&(_|=1<S&&(_|=1<c[y][1]&&(D=y));for(var R=-1,y=0;y<3;++y){var B=D^1<c[F][0]&&(F=B)}}var N=m;N[0]=N[1]=N[2]=0,N[n.log2(R^D)]=D&R,N[n.log2(D^F)]=D&F;var j=7^F;j===_||j===P?(j=7^R,N[n.log2(F^j)]=j&F):N[n.log2(R^j)]=j&R;for(var V=g,U=_,M=0;M<3;++M)V[M]=U&1< HALF_PI) && (b <= ONE_AND_HALF_PI)) ?\n b - PI :\n b;\n}\n\nfloat look_horizontal_or_vertical(float a, float ratio) {\n // ratio controls the ratio between being horizontal to (vertical + horizontal)\n // if ratio is set to 0.5 then it is 50%, 50%.\n // when using a higher ratio e.g. 0.75 the result would\n // likely be more horizontal than vertical.\n\n float b = positive_angle(a);\n\n return\n (b < ( ratio) * HALF_PI) ? 0.0 :\n (b < (2.0 - ratio) * HALF_PI) ? -HALF_PI :\n (b < (2.0 + ratio) * HALF_PI) ? 0.0 :\n (b < (4.0 - ratio) * HALF_PI) ? HALF_PI :\n 0.0;\n}\n\nfloat roundTo(float a, float b) {\n return float(b * floor((a + 0.5 * b) / b));\n}\n\nfloat look_round_n_directions(float a, int n) {\n float b = positive_angle(a);\n float div = TWO_PI / float(n);\n float c = roundTo(b, div);\n return look_upwards(c);\n}\n\nfloat applyAlignOption(float rawAngle, float delta) {\n return\n (option > 2) ? look_round_n_directions(rawAngle + delta, option) : // option 3-n: round to n directions\n (option == 2) ? look_horizontal_or_vertical(rawAngle + delta, hv_ratio) : // horizontal or vertical\n (option == 1) ? rawAngle + delta : // use free angle, and flip to align with one direction of the axis\n (option == 0) ? look_upwards(rawAngle) : // use free angle, and stay upwards\n (option ==-1) ? 0.0 : // useful for backward compatibility, all texts remains horizontal\n rawAngle; // otherwise return back raw input angle\n}\n\nbool isAxisTitle = (axis.x == 0.0) &&\n (axis.y == 0.0) &&\n (axis.z == 0.0);\n\nvoid main() {\n //Compute world offset\n float axisDistance = position.z;\n vec3 dataPosition = axisDistance * axis + offset;\n\n float beta = angle; // i.e. user defined attributes for each tick\n\n float axisAngle;\n float clipAngle;\n float flip;\n\n if (enableAlign) {\n axisAngle = (isAxisTitle) ? HALF_PI :\n computeViewAngle(dataPosition, dataPosition + axis);\n clipAngle = computeViewAngle(dataPosition, dataPosition + alignDir);\n\n axisAngle += (sin(axisAngle) < 0.0) ? PI : 0.0;\n clipAngle += (sin(clipAngle) < 0.0) ? PI : 0.0;\n\n flip = (dot(vec2(cos(axisAngle), sin(axisAngle)),\n vec2(sin(clipAngle),-cos(clipAngle))) > 0.0) ? 1.0 : 0.0;\n\n beta += applyAlignOption(clipAngle, flip * PI);\n }\n\n //Compute plane offset\n vec2 planeCoord = position.xy * pixelScale;\n\n mat2 planeXform = scale * mat2(\n cos(beta), sin(beta),\n -sin(beta), cos(beta)\n );\n\n vec2 viewOffset = 2.0 * planeXform * planeCoord / resolution;\n\n //Compute clip position\n vec3 clipPosition = project(dataPosition);\n\n //Apply text offset in clip coordinates\n clipPosition += vec3(viewOffset, 0.0);\n\n //Done\n gl_Position = vec4(clipPosition, 1.0);\n}"]),l=n(["precision mediump float;\n#define GLSLIFY 1\nuniform vec4 color;\nvoid main() {\n gl_FragColor = color;\n}"]);r.text=function(t){return i(t,s,l,null,[{name:"position",type:"vec3"}])};var c=n(["#define GLSLIFY 1\nattribute vec3 position;\nattribute vec3 normal;\n\nuniform mat4 model, view, projection;\nuniform vec3 enable;\nuniform vec3 bounds[2];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n\n vec3 signAxis = sign(bounds[1] - bounds[0]);\n\n vec3 realNormal = signAxis * normal;\n\n if(dot(realNormal, enable) > 0.0) {\n vec3 minRange = min(bounds[0], bounds[1]);\n vec3 maxRange = max(bounds[0], bounds[1]);\n vec3 nPosition = mix(minRange, maxRange, 0.5 * (position + 1.0));\n gl_Position = projection * view * model * vec4(nPosition, 1.0);\n } else {\n gl_Position = vec4(0,0,0,0);\n }\n\n colorChannel = abs(realNormal);\n}"]),u=n(["precision mediump float;\n#define GLSLIFY 1\n\nuniform vec4 colors[3];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n gl_FragColor = colorChannel.x * colors[0] +\n colorChannel.y * colors[1] +\n colorChannel.z * colors[2];\n}"]);r.bg=function(t){return i(t,c,u,null,[{name:"position",type:"vec3"},{name:"normal",type:"vec3"}])}},{"gl-shader":288,glslify:392}],227:[function(t,e,r){(function(r){"use strict";e.exports=function(t,e,r,a,s,l){var u=n(t),f=i(t,[{buffer:u,size:3}]),h=o(t);h.attributes.position.location=0;var p=new c(t,h,u,f);return p.update(e,r,a,s,l),p};var n=t("gl-buffer"),i=t("gl-vao"),a=t("vectorize-text"),o=t("./shaders").text,s=window||r.global||{},l=s.__TEXT_CACHE||{};s.__TEXT_CACHE={};function c(t,e,r,n){this.gl=t,this.shader=e,this.buffer=r,this.vao=n,this.tickOffset=this.tickCount=this.labelOffset=this.labelCount=null}var u=c.prototype,f=[0,0];u.bind=function(t,e,r,n){this.vao.bind(),this.shader.bind();var i=this.shader.uniforms;i.model=t,i.view=e,i.projection=r,i.pixelScale=n,f[0]=this.gl.drawingBufferWidth,f[1]=this.gl.drawingBufferHeight,this.shader.uniforms.resolution=f},u.unbind=function(){this.vao.unbind()},u.update=function(t,e,r,n,i){this.gl;var o=[];function s(t,e,r,n){var i=l[r];i||(i=l[r]={});var s=i[e];s||(s=i[e]=function(t,e){try{return a(t,e)}catch(t){return console.warn("error vectorizing text:",t),{cells:[],positions:[]}}}(e,{triangles:!0,font:r,textAlign:"center",textBaseline:"middle"}));for(var c=(n||12)/12,u=s.positions,f=s.cells,h=0,p=f.length;h=0;--m){var g=u[d[m]];o.push(c*g[0],-c*g[1],t)}}for(var c=[0,0,0],u=[0,0,0],f=[0,0,0],h=[0,0,0],p=0;p<3;++p){f[p]=o.length/3|0,s(.5*(t[0][p]+t[1][p]),e[p],r),h[p]=(o.length/3|0)-f[p],c[p]=o.length/3|0;for(var d=0;d=0&&(i=r.length-n-1);var a=Math.pow(10,i),o=Math.round(t*e*a),s=o+"";if(s.indexOf("e")>=0)return s;var l=o/a,c=o%a;o<0?(l=0|-Math.ceil(l),c=0|-c):(l=0|Math.floor(l),c|=0);var u=""+l;if(o<0&&(u="-"+u),i){for(var f=""+c;f.length=t[0][i];--o)a.push({x:o*e[i],text:n(e[i],o)});r.push(a)}return r},r.equal=function(t,e){for(var r=0;r<3;++r){if(t[r].length!==e[r].length)return!1;for(var n=0;nr)throw new Error("gl-buffer: If resizing buffer, must not specify offset");return t.bufferSubData(e,a,i),r}function u(t,e){for(var r=n.malloc(t.length,e),i=t.length,a=0;a=0;--n){if(e[n]!==r)return!1;r*=t[n]}return!0}(t.shape,t.stride))0===t.offset&&t.data.length===t.shape[0]?this.length=c(this.gl,this.type,this.length,this.usage,t.data,e):this.length=c(this.gl,this.type,this.length,this.usage,t.data.subarray(t.offset,t.shape[0]),e);else{var s=n.malloc(t.size,r),l=a(s,t.shape);i.assign(l,t),this.length=c(this.gl,this.type,this.length,this.usage,e<0?s:s.subarray(0,t.size),e),n.free(s)}}else if(Array.isArray(t)){var f;f=this.type===this.gl.ELEMENT_ARRAY_BUFFER?u(t,"uint16"):u(t,"float32"),this.length=c(this.gl,this.type,this.length,this.usage,e<0?f:f.subarray(0,t.length),e),n.free(f)}else if("object"==typeof t&&"number"==typeof t.length)this.length=c(this.gl,this.type,this.length,this.usage,t,e);else{if("number"!=typeof t&&void 0!==t)throw new Error("gl-buffer: Invalid data type");if(e>=0)throw new Error("gl-buffer: Cannot specify offset when resizing buffer");(t|=0)<=0&&(t=1),this.gl.bufferData(this.type,0|t,this.usage),this.length=t}},e.exports=function(t,e,r,n){if(r=r||t.ARRAY_BUFFER,n=n||t.DYNAMIC_DRAW,r!==t.ARRAY_BUFFER&&r!==t.ELEMENT_ARRAY_BUFFER)throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER");if(n!==t.DYNAMIC_DRAW&&n!==t.STATIC_DRAW&&n!==t.STREAM_DRAW)throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW");var i=t.createBuffer(),a=new s(t,r,i,0,n);return a.update(e),a}},{ndarray:433,"ndarray-ops":427,"typedarray-pool":522}],231:[function(t,e,r){"use strict";var n=t("gl-vec3"),i=(t("gl-vec4"),function(t,e){for(var r=0;r=e)return r-1;return r}),a=n.create(),o=n.create(),s=function(t,e,r){return tr?r:t},l=function(t,e,r,l){var c=t[0],u=t[1],f=t[2],h=r[0].length,p=r[1].length,d=r[2].length,m=i(r[0],c),g=i(r[1],u),v=i(r[2],f),y=m+1,x=g+1,b=v+1;if(l&&(m=s(m,0,h-1),y=s(y,0,h-1),g=s(g,0,p-1),x=s(x,0,p-1),v=s(v,0,d-1),b=s(b,0,d-1)),m<0||g<0||v<0||y>=h||x>=p||b>=d)return n.create();var _=(c-r[0][m])/(r[0][y]-r[0][m]),w=(u-r[1][g])/(r[1][x]-r[1][g]),k=(f-r[2][v])/(r[2][b]-r[2][v]);(_<0||_>1||isNaN(_))&&(_=0),(w<0||w>1||isNaN(w))&&(w=0),(k<0||k>1||isNaN(k))&&(k=0);var M=v*h*p,A=b*h*p,T=g*h,S=x*h,E=m,C=y,L=e[T+M+E],z=e[T+M+C],O=e[S+M+E],I=e[S+M+C],P=e[T+A+E],D=e[T+A+C],R=e[S+A+E],B=e[S+A+C],F=n.create();return n.lerp(F,L,z,_),n.lerp(a,O,I,_),n.lerp(F,F,a,w),n.lerp(a,P,D,_),n.lerp(o,R,B,_),n.lerp(a,a,o,w),n.lerp(F,F,a,k),F};e.exports=function(t,e){var r;r=t.positions?t.positions:function(t){for(var e=t[0],r=t[1],n=t[2],i=[],a=0;as&&(s=n.length(b)),x&&(y=Math.min(y,2*n.distance(m,_)/(n.length(g)+n.length(b)))),m=_,g=b,v.push(b)}var w=[c,f,p],k=[u,h,d];e&&(e[0]=w,e[1]=k),0===s&&(s=1);var M=1/s;isFinite(y)&&!isNaN(y)||(y=1),o.vectorScale=y;var A=function(t,e,r){var i=n.create();return void 0!==t&&n.set(i,t,e,r),i}(0,1,0),T=t.coneSize||.5;t.absoluteConeSize&&(T=t.absoluteConeSize*M),o.coneScale=T;x=0;for(var S=0;x1.0001)return null;g+=m[u]}if(Math.abs(g-1)>.001)return null;return[f,function(t,e){for(var r=[0,0,0],n=0;n=1},x.isTransparent=function(){return this.opacity<1},x.pickSlots=1,x.setPickBase=function(t){this.pickId=t},x.highlight=function(t){if(t&&this.contourEnable){for(var e=h(this.cells,this.intensity,t.intensity),r=e.cells,n=e.vertexIds,i=e.vertexWeights,a=r.length,o=p.mallocFloat32(6*a),s=0,l=0;l0&&((f=this.triShader).bind(),f.uniforms=s,this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind());this.edgeCount>0&&this.lineWidth>0&&((f=this.lineShader).bind(),f.uniforms=s,this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind());this.pointCount>0&&((f=this.pointShader).bind(),f.uniforms=s,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind());this.contourEnable&&this.contourCount>0&&this.contourLineWidth>0&&((f=this.contourShader).bind(),f.uniforms=s,this.contourVAO.bind(),e.drawArrays(e.LINES,0,this.contourCount),this.contourVAO.unbind())},x.drawPick=function(t){t=t||{};for(var e=this.gl,r=t.model||v,n=t.view||v,i=t.projection||v,a=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],o=0;o<3;++o)a[0][o]=Math.max(a[0][o],this.clipBounds[0][o]),a[1][o]=Math.min(a[1][o],this.clipBounds[1][o]);this._model=[].slice.call(r),this._view=[].slice.call(n),this._projection=[].slice.call(i),this._resolution=[e.drawingBufferWidth,e.drawingBufferHeight];var s,l={model:r,view:n,projection:i,clipBounds:a,vectorScale:this.vectorScale,coneScale:this.coneScale,coneOffset:this.coneOffset,pickId:this.pickId/255};((s=this.pickShader).bind(),s.uniforms=l,this.triangleCount>0&&(this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind()),this.edgeCount>0&&(this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind()),this.pointCount>0)&&((s=this.pointPickShader).bind(),s.uniforms=l,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind())},x.pick=function(t){if(!t)return null;if(t.id!==this.pickId)return null;var e=t.value[0]+256*t.value[1]+65536*t.value[2],r=this.cells[e],n=this.positions[r[1]].slice(0,3);return{index:Math.floor(r[1]/48),position:n,dataCoordinate:n}},x.dispose=function(){this.texture.dispose(),this.triShader.dispose(),this.pickShader.dispose(),this.triangleVAO.dispose(),this.trianglePositions.dispose(),this.triangleVectors.dispose(),this.triangleColors.dispose(),this.triangleUVs.dispose(),this.triangleNormals.dispose(),this.triangleIds.dispose(),this.edgeVAO.dispose(),this.edgePositions.dispose(),this.edgeColors.dispose(),this.edgeUVs.dispose(),this.edgeIds.dispose(),this.pointVAO.dispose(),this.pointPositions.dispose(),this.pointColors.dispose(),this.pointUVs.dispose(),this.pointSizes.dispose(),this.pointIds.dispose(),this.contourVAO.dispose(),this.contourPositions.dispose()},e.exports=function(t,e){1===arguments.length&&(t=(e=t).gl);var r=e.triShader||function(t){var e=n(t,m.vertex,m.fragment,null,m.attributes);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e.attributes.vector.location=5,e}(t),s=b(t),l=o(t,u(new Uint8Array([255,255,255,255]),[1,1,4]));l.generateMipmap(),l.minFilter=t.LINEAR_MIPMAP_LINEAR,l.magFilter=t.LINEAR;var c=i(t),f=i(t),h=i(t),p=i(t),d=i(t),g=i(t),v=a(t,[{buffer:c,type:t.FLOAT,size:4},{buffer:g,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:h,type:t.FLOAT,size:4},{buffer:p,type:t.FLOAT,size:2},{buffer:d,type:t.FLOAT,size:3},{buffer:f,type:t.FLOAT,size:3}]),x=i(t),_=i(t),w=i(t),k=i(t),M=a(t,[{buffer:x,type:t.FLOAT,size:3},{buffer:k,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:_,type:t.FLOAT,size:4},{buffer:w,type:t.FLOAT,size:2}]),A=i(t),T=i(t),S=i(t),E=i(t),C=i(t),L=a(t,[{buffer:A,type:t.FLOAT,size:3},{buffer:C,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:T,type:t.FLOAT,size:4},{buffer:S,type:t.FLOAT,size:2},{buffer:E,type:t.FLOAT,size:1}]),z=i(t),O=new y(t,l,r,null,null,s,null,null,c,f,g,h,p,d,v,x,k,_,w,M,A,C,T,S,E,L,z,a(t,[{buffer:z,type:t.FLOAT,size:3}]));return O.update(e),O}},{"./closest-point":232,"./shaders":234,colormap:114,"gl-buffer":230,"gl-mat4/invert":254,"gl-mat4/multiply":256,"gl-shader":288,"gl-texture2d":305,"gl-vao":310,ndarray:433,normals:436,"simplicial-complex-contour":494,"typedarray-pool":522}],234:[function(t,e,r){var n=t("glslify"),i=n(["precision mediump float;\n#define GLSLIFY 1\n\nfloat inverse(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float index, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n index = mod(index, segmentCount * 6.0);\n\n float segment = floor(index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex == 3.0) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n // angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)\n float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex <= 2.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float vectorScale;\nuniform float coneScale;\n\nuniform float coneOffset;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n normal = normalize(normal * inverse(mat3(model)));\n\n // vec4 m_position = model * vec4(conePosition, 1.0);\n vec4 t_position = view * conePosition;\n gl_Position = projection * t_position;\n f_color = color; //vec4(position.w, color.r, 0, 0);\n f_normal = normal;\n f_data = conePosition.xyz;\n f_position = position.xyz;\n f_eyeDirection = eyePosition - conePosition.xyz;\n f_lightDirection = lightPosition - conePosition.xyz;\n f_uv = uv;\n}\n"]),a=n(["precision mediump float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}"]),o=n(["precision mediump float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float index, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n index = mod(index, segmentCount * 6.0);\n\n float segment = floor(index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex == 3.0) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n // angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)\n float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex <= 2.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nuniform float vectorScale;\nuniform float coneScale;\nuniform float coneOffset;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n gl_Position = projection * view * conePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]),s=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec4"},{name:"normal",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"vector",type:"vec3"}]},r.pickShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec4"},{name:"id",type:"vec4"},{name:"vector",type:"vec3"}]}},{glslify:392}],235:[function(t,e,r){e.exports={0:"NONE",1:"ONE",2:"LINE_LOOP",3:"LINE_STRIP",4:"TRIANGLES",5:"TRIANGLE_STRIP",6:"TRIANGLE_FAN",256:"DEPTH_BUFFER_BIT",512:"NEVER",513:"LESS",514:"EQUAL",515:"LEQUAL",516:"GREATER",517:"NOTEQUAL",518:"GEQUAL",519:"ALWAYS",768:"SRC_COLOR",769:"ONE_MINUS_SRC_COLOR",770:"SRC_ALPHA",771:"ONE_MINUS_SRC_ALPHA",772:"DST_ALPHA",773:"ONE_MINUS_DST_ALPHA",774:"DST_COLOR",775:"ONE_MINUS_DST_COLOR",776:"SRC_ALPHA_SATURATE",1024:"STENCIL_BUFFER_BIT",1028:"FRONT",1029:"BACK",1032:"FRONT_AND_BACK",1280:"INVALID_ENUM",1281:"INVALID_VALUE",1282:"INVALID_OPERATION",1285:"OUT_OF_MEMORY",1286:"INVALID_FRAMEBUFFER_OPERATION",2304:"CW",2305:"CCW",2849:"LINE_WIDTH",2884:"CULL_FACE",2885:"CULL_FACE_MODE",2886:"FRONT_FACE",2928:"DEPTH_RANGE",2929:"DEPTH_TEST",2930:"DEPTH_WRITEMASK",2931:"DEPTH_CLEAR_VALUE",2932:"DEPTH_FUNC",2960:"STENCIL_TEST",2961:"STENCIL_CLEAR_VALUE",2962:"STENCIL_FUNC",2963:"STENCIL_VALUE_MASK",2964:"STENCIL_FAIL",2965:"STENCIL_PASS_DEPTH_FAIL",2966:"STENCIL_PASS_DEPTH_PASS",2967:"STENCIL_REF",2968:"STENCIL_WRITEMASK",2978:"VIEWPORT",3024:"DITHER",3042:"BLEND",3088:"SCISSOR_BOX",3089:"SCISSOR_TEST",3106:"COLOR_CLEAR_VALUE",3107:"COLOR_WRITEMASK",3317:"UNPACK_ALIGNMENT",3333:"PACK_ALIGNMENT",3379:"MAX_TEXTURE_SIZE",3386:"MAX_VIEWPORT_DIMS",3408:"SUBPIXEL_BITS",3410:"RED_BITS",3411:"GREEN_BITS",3412:"BLUE_BITS",3413:"ALPHA_BITS",3414:"DEPTH_BITS",3415:"STENCIL_BITS",3553:"TEXTURE_2D",4352:"DONT_CARE",4353:"FASTEST",4354:"NICEST",5120:"BYTE",5121:"UNSIGNED_BYTE",5122:"SHORT",5123:"UNSIGNED_SHORT",5124:"INT",5125:"UNSIGNED_INT",5126:"FLOAT",5386:"INVERT",5890:"TEXTURE",6401:"STENCIL_INDEX",6402:"DEPTH_COMPONENT",6406:"ALPHA",6407:"RGB",6408:"RGBA",6409:"LUMINANCE",6410:"LUMINANCE_ALPHA",7680:"KEEP",7681:"REPLACE",7682:"INCR",7683:"DECR",7936:"VENDOR",7937:"RENDERER",7938:"VERSION",9728:"NEAREST",9729:"LINEAR",9984:"NEAREST_MIPMAP_NEAREST",9985:"LINEAR_MIPMAP_NEAREST",9986:"NEAREST_MIPMAP_LINEAR",9987:"LINEAR_MIPMAP_LINEAR",10240:"TEXTURE_MAG_FILTER",10241:"TEXTURE_MIN_FILTER",10242:"TEXTURE_WRAP_S",10243:"TEXTURE_WRAP_T",10497:"REPEAT",10752:"POLYGON_OFFSET_UNITS",16384:"COLOR_BUFFER_BIT",32769:"CONSTANT_COLOR",32770:"ONE_MINUS_CONSTANT_COLOR",32771:"CONSTANT_ALPHA",32772:"ONE_MINUS_CONSTANT_ALPHA",32773:"BLEND_COLOR",32774:"FUNC_ADD",32777:"BLEND_EQUATION_RGB",32778:"FUNC_SUBTRACT",32779:"FUNC_REVERSE_SUBTRACT",32819:"UNSIGNED_SHORT_4_4_4_4",32820:"UNSIGNED_SHORT_5_5_5_1",32823:"POLYGON_OFFSET_FILL",32824:"POLYGON_OFFSET_FACTOR",32854:"RGBA4",32855:"RGB5_A1",32873:"TEXTURE_BINDING_2D",32926:"SAMPLE_ALPHA_TO_COVERAGE",32928:"SAMPLE_COVERAGE",32936:"SAMPLE_BUFFERS",32937:"SAMPLES",32938:"SAMPLE_COVERAGE_VALUE",32939:"SAMPLE_COVERAGE_INVERT",32968:"BLEND_DST_RGB",32969:"BLEND_SRC_RGB",32970:"BLEND_DST_ALPHA",32971:"BLEND_SRC_ALPHA",33071:"CLAMP_TO_EDGE",33170:"GENERATE_MIPMAP_HINT",33189:"DEPTH_COMPONENT16",33306:"DEPTH_STENCIL_ATTACHMENT",33635:"UNSIGNED_SHORT_5_6_5",33648:"MIRRORED_REPEAT",33901:"ALIASED_POINT_SIZE_RANGE",33902:"ALIASED_LINE_WIDTH_RANGE",33984:"TEXTURE0",33985:"TEXTURE1",33986:"TEXTURE2",33987:"TEXTURE3",33988:"TEXTURE4",33989:"TEXTURE5",33990:"TEXTURE6",33991:"TEXTURE7",33992:"TEXTURE8",33993:"TEXTURE9",33994:"TEXTURE10",33995:"TEXTURE11",33996:"TEXTURE12",33997:"TEXTURE13",33998:"TEXTURE14",33999:"TEXTURE15",34000:"TEXTURE16",34001:"TEXTURE17",34002:"TEXTURE18",34003:"TEXTURE19",34004:"TEXTURE20",34005:"TEXTURE21",34006:"TEXTURE22",34007:"TEXTURE23",34008:"TEXTURE24",34009:"TEXTURE25",34010:"TEXTURE26",34011:"TEXTURE27",34012:"TEXTURE28",34013:"TEXTURE29",34014:"TEXTURE30",34015:"TEXTURE31",34016:"ACTIVE_TEXTURE",34024:"MAX_RENDERBUFFER_SIZE",34041:"DEPTH_STENCIL",34055:"INCR_WRAP",34056:"DECR_WRAP",34067:"TEXTURE_CUBE_MAP",34068:"TEXTURE_BINDING_CUBE_MAP",34069:"TEXTURE_CUBE_MAP_POSITIVE_X",34070:"TEXTURE_CUBE_MAP_NEGATIVE_X",34071:"TEXTURE_CUBE_MAP_POSITIVE_Y",34072:"TEXTURE_CUBE_MAP_NEGATIVE_Y",34073:"TEXTURE_CUBE_MAP_POSITIVE_Z",34074:"TEXTURE_CUBE_MAP_NEGATIVE_Z",34076:"MAX_CUBE_MAP_TEXTURE_SIZE",34338:"VERTEX_ATTRIB_ARRAY_ENABLED",34339:"VERTEX_ATTRIB_ARRAY_SIZE",34340:"VERTEX_ATTRIB_ARRAY_STRIDE",34341:"VERTEX_ATTRIB_ARRAY_TYPE",34342:"CURRENT_VERTEX_ATTRIB",34373:"VERTEX_ATTRIB_ARRAY_POINTER",34466:"NUM_COMPRESSED_TEXTURE_FORMATS",34467:"COMPRESSED_TEXTURE_FORMATS",34660:"BUFFER_SIZE",34661:"BUFFER_USAGE",34816:"STENCIL_BACK_FUNC",34817:"STENCIL_BACK_FAIL",34818:"STENCIL_BACK_PASS_DEPTH_FAIL",34819:"STENCIL_BACK_PASS_DEPTH_PASS",34877:"BLEND_EQUATION_ALPHA",34921:"MAX_VERTEX_ATTRIBS",34922:"VERTEX_ATTRIB_ARRAY_NORMALIZED",34930:"MAX_TEXTURE_IMAGE_UNITS",34962:"ARRAY_BUFFER",34963:"ELEMENT_ARRAY_BUFFER",34964:"ARRAY_BUFFER_BINDING",34965:"ELEMENT_ARRAY_BUFFER_BINDING",34975:"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",35040:"STREAM_DRAW",35044:"STATIC_DRAW",35048:"DYNAMIC_DRAW",35632:"FRAGMENT_SHADER",35633:"VERTEX_SHADER",35660:"MAX_VERTEX_TEXTURE_IMAGE_UNITS",35661:"MAX_COMBINED_TEXTURE_IMAGE_UNITS",35663:"SHADER_TYPE",35664:"FLOAT_VEC2",35665:"FLOAT_VEC3",35666:"FLOAT_VEC4",35667:"INT_VEC2",35668:"INT_VEC3",35669:"INT_VEC4",35670:"BOOL",35671:"BOOL_VEC2",35672:"BOOL_VEC3",35673:"BOOL_VEC4",35674:"FLOAT_MAT2",35675:"FLOAT_MAT3",35676:"FLOAT_MAT4",35678:"SAMPLER_2D",35680:"SAMPLER_CUBE",35712:"DELETE_STATUS",35713:"COMPILE_STATUS",35714:"LINK_STATUS",35715:"VALIDATE_STATUS",35716:"INFO_LOG_LENGTH",35717:"ATTACHED_SHADERS",35718:"ACTIVE_UNIFORMS",35719:"ACTIVE_UNIFORM_MAX_LENGTH",35720:"SHADER_SOURCE_LENGTH",35721:"ACTIVE_ATTRIBUTES",35722:"ACTIVE_ATTRIBUTE_MAX_LENGTH",35724:"SHADING_LANGUAGE_VERSION",35725:"CURRENT_PROGRAM",36003:"STENCIL_BACK_REF",36004:"STENCIL_BACK_VALUE_MASK",36005:"STENCIL_BACK_WRITEMASK",36006:"FRAMEBUFFER_BINDING",36007:"RENDERBUFFER_BINDING",36048:"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",36049:"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",36050:"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",36051:"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",36053:"FRAMEBUFFER_COMPLETE",36054:"FRAMEBUFFER_INCOMPLETE_ATTACHMENT",36055:"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",36057:"FRAMEBUFFER_INCOMPLETE_DIMENSIONS",36061:"FRAMEBUFFER_UNSUPPORTED",36064:"COLOR_ATTACHMENT0",36096:"DEPTH_ATTACHMENT",36128:"STENCIL_ATTACHMENT",36160:"FRAMEBUFFER",36161:"RENDERBUFFER",36162:"RENDERBUFFER_WIDTH",36163:"RENDERBUFFER_HEIGHT",36164:"RENDERBUFFER_INTERNAL_FORMAT",36168:"STENCIL_INDEX8",36176:"RENDERBUFFER_RED_SIZE",36177:"RENDERBUFFER_GREEN_SIZE",36178:"RENDERBUFFER_BLUE_SIZE",36179:"RENDERBUFFER_ALPHA_SIZE",36180:"RENDERBUFFER_DEPTH_SIZE",36181:"RENDERBUFFER_STENCIL_SIZE",36194:"RGB565",36336:"LOW_FLOAT",36337:"MEDIUM_FLOAT",36338:"HIGH_FLOAT",36339:"LOW_INT",36340:"MEDIUM_INT",36341:"HIGH_INT",36346:"SHADER_COMPILER",36347:"MAX_VERTEX_UNIFORM_VECTORS",36348:"MAX_VARYING_VECTORS",36349:"MAX_FRAGMENT_UNIFORM_VECTORS",37440:"UNPACK_FLIP_Y_WEBGL",37441:"UNPACK_PREMULTIPLY_ALPHA_WEBGL",37442:"CONTEXT_LOST_WEBGL",37443:"UNPACK_COLORSPACE_CONVERSION_WEBGL",37444:"BROWSER_DEFAULT_WEBGL"}},{}],236:[function(t,e,r){var n=t("./1.0/numbers");e.exports=function(t){return n[t]}},{"./1.0/numbers":235}],237:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl,r=n(e),o=i(e,[{buffer:r,type:e.FLOAT,size:3,offset:0,stride:40},{buffer:r,type:e.FLOAT,size:4,offset:12,stride:40},{buffer:r,type:e.FLOAT,size:3,offset:28,stride:40}]),l=a(e);l.attributes.position.location=0,l.attributes.color.location=1,l.attributes.offset.location=2;var c=new s(e,r,o,l);return c.update(t),c};var n=t("gl-buffer"),i=t("gl-vao"),a=t("./shaders/index"),o=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function s(t,e,r,n){this.gl=t,this.shader=n,this.buffer=e,this.vao=r,this.pixelRatio=1,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.lineWidth=[1,1,1],this.capSize=[10,10,10],this.lineCount=[0,0,0],this.lineOffset=[0,0,0],this.opacity=1}var l=s.prototype;function c(t,e){for(var r=0;r<3;++r)t[0][r]=Math.min(t[0][r],e[r]),t[1][r]=Math.max(t[1][r],e[r])}l.isOpaque=function(){return this.opacity>=1},l.isTransparent=function(){return this.opacity<1},l.drawTransparent=l.draw=function(t){var e=this.gl,r=this.shader.uniforms;this.shader.bind();var n=r.view=t.view||o,i=r.projection=t.projection||o;r.model=t.model||o,r.clipBounds=this.clipBounds,r.opacity=this.opacity;var a=n[12],s=n[13],l=n[14],c=n[15],u=this.pixelRatio*(i[3]*a+i[7]*s+i[11]*l+i[15]*c)/e.drawingBufferHeight;this.vao.bind();for(var f=0;f<3;++f)e.lineWidth(this.lineWidth[f]),r.capSize=this.capSize[f]*u,this.lineCount[f]&&e.drawArrays(e.LINES,this.lineOffset[f],this.lineCount[f]);this.vao.unbind()};var u=function(){for(var t=new Array(3),e=0;e<3;++e){for(var r=[],n=1;n<=2;++n)for(var i=-1;i<=1;i+=2){var a=[0,0,0];a[(n+e)%3]=i,r.push(a)}t[e]=r}return t}();function f(t,e,r,n){for(var i=u[n],a=0;a0)(m=u.slice())[s]+=p[1][s],i.push(u[0],u[1],u[2],d[0],d[1],d[2],d[3],0,0,0,m[0],m[1],m[2],d[0],d[1],d[2],d[3],0,0,0),c(this.bounds,m),o+=2+f(i,m,d,s)}}this.lineCount[s]=o-this.lineOffset[s]}this.buffer.update(i)}},l.dispose=function(){this.shader.dispose(),this.buffer.dispose(),this.vao.dispose()}},{"./shaders/index":238,"gl-buffer":230,"gl-vao":310}],238:[function(t,e,r){"use strict";var n=t("glslify"),i=t("gl-shader"),a=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}"]),o=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], fragPosition)) discard;\n\n gl_FragColor = opacity * fragColor;\n}"]);e.exports=function(t){return i(t,a,o,null,[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"offset",type:"vec3"}])}},{"gl-shader":288,glslify:392}],239:[function(t,e,r){"use strict";var n=t("gl-texture2d");e.exports=function(t,e,r,n){i||(i=t.FRAMEBUFFER_UNSUPPORTED,a=t.FRAMEBUFFER_INCOMPLETE_ATTACHMENT,o=t.FRAMEBUFFER_INCOMPLETE_DIMENSIONS,s=t.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);var c=t.getExtension("WEBGL_draw_buffers");!l&&c&&function(t,e){var r=t.getParameter(e.MAX_COLOR_ATTACHMENTS_WEBGL);l=new Array(r+1);for(var n=0;n<=r;++n){for(var i=new Array(r),a=0;au||r<0||r>u)throw new Error("gl-fbo: Parameters are too large for FBO");var f=1;if("color"in(n=n||{})){if((f=Math.max(0|n.color,0))<0)throw new Error("gl-fbo: Must specify a nonnegative number of colors");if(f>1){if(!c)throw new Error("gl-fbo: Multiple draw buffer extension not supported");if(f>t.getParameter(c.MAX_COLOR_ATTACHMENTS_WEBGL))throw new Error("gl-fbo: Context does not support "+f+" draw buffers")}}var h=t.UNSIGNED_BYTE,p=t.getExtension("OES_texture_float");if(n.float&&f>0){if(!p)throw new Error("gl-fbo: Context does not support floating point textures");h=t.FLOAT}else n.preferFloat&&f>0&&p&&(h=t.FLOAT);var m=!0;"depth"in n&&(m=!!n.depth);var g=!1;"stencil"in n&&(g=!!n.stencil);return new d(t,e,r,h,f,m,g,c)};var i,a,o,s,l=null;function c(t){return[t.getParameter(t.FRAMEBUFFER_BINDING),t.getParameter(t.RENDERBUFFER_BINDING),t.getParameter(t.TEXTURE_BINDING_2D)]}function u(t,e){t.bindFramebuffer(t.FRAMEBUFFER,e[0]),t.bindRenderbuffer(t.RENDERBUFFER,e[1]),t.bindTexture(t.TEXTURE_2D,e[2])}function f(t){switch(t){case i:throw new Error("gl-fbo: Framebuffer unsupported");case a:throw new Error("gl-fbo: Framebuffer incomplete attachment");case o:throw new Error("gl-fbo: Framebuffer incomplete dimensions");case s:throw new Error("gl-fbo: Framebuffer incomplete missing attachment");default:throw new Error("gl-fbo: Framebuffer failed for unspecified reason")}}function h(t,e,r,i,a,o){if(!i)return null;var s=n(t,e,r,a,i);return s.magFilter=t.NEAREST,s.minFilter=t.NEAREST,s.mipSamples=1,s.bind(),t.framebufferTexture2D(t.FRAMEBUFFER,o,t.TEXTURE_2D,s.handle,0),s}function p(t,e,r,n,i){var a=t.createRenderbuffer();return t.bindRenderbuffer(t.RENDERBUFFER,a),t.renderbufferStorage(t.RENDERBUFFER,n,e,r),t.framebufferRenderbuffer(t.FRAMEBUFFER,i,t.RENDERBUFFER,a),a}function d(t,e,r,n,i,a,o,s){this.gl=t,this._shape=[0|e,0|r],this._destroyed=!1,this._ext=s,this.color=new Array(i);for(var d=0;d1&&s.drawBuffersWEBGL(l[o]);var y=r.getExtension("WEBGL_depth_texture");y?d?t.depth=h(r,i,a,y.UNSIGNED_INT_24_8_WEBGL,r.DEPTH_STENCIL,r.DEPTH_STENCIL_ATTACHMENT):m&&(t.depth=h(r,i,a,r.UNSIGNED_SHORT,r.DEPTH_COMPONENT,r.DEPTH_ATTACHMENT)):m&&d?t._depth_rb=p(r,i,a,r.DEPTH_STENCIL,r.DEPTH_STENCIL_ATTACHMENT):m?t._depth_rb=p(r,i,a,r.DEPTH_COMPONENT16,r.DEPTH_ATTACHMENT):d&&(t._depth_rb=p(r,i,a,r.STENCIL_INDEX,r.STENCIL_ATTACHMENT));var x=r.checkFramebufferStatus(r.FRAMEBUFFER);if(x!==r.FRAMEBUFFER_COMPLETE){for(t._destroyed=!0,r.bindFramebuffer(r.FRAMEBUFFER,null),r.deleteFramebuffer(t.handle),t.handle=null,t.depth&&(t.depth.dispose(),t.depth=null),t._depth_rb&&(r.deleteRenderbuffer(t._depth_rb),t._depth_rb=null),v=0;vi||r<0||r>i)throw new Error("gl-fbo: Can't resize FBO, invalid dimensions");t._shape[0]=e,t._shape[1]=r;for(var a=c(n),o=0;o>8*p&255;this.pickOffset=r,i.bind();var d=i.uniforms;d.viewTransform=t,d.pickOffset=e,d.shape=this.shape;var m=i.attributes;return this.positionBuffer.bind(),m.position.pointer(),this.weightBuffer.bind(),m.weight.pointer(s.UNSIGNED_BYTE,!1),this.idBuffer.bind(),m.pickId.pointer(s.UNSIGNED_BYTE,!1),s.drawArrays(s.TRIANGLES,0,o),r+this.shape[0]*this.shape[1]}}}(),f.pick=function(t,e,r){var n=this.pickOffset,i=this.shape[0]*this.shape[1];if(r=n+i)return null;var a=r-n,o=this.xData,s=this.yData;return{object:this,pointId:a,dataCoord:[o[a%this.shape[0]],s[a/this.shape[0]|0]]}},f.update=function(t){var e=(t=t||{}).shape||[0,0],r=t.x||i(e[0]),o=t.y||i(e[1]),s=t.z||new Float32Array(e[0]*e[1]);this.xData=r,this.yData=o;var l=t.colorLevels||[0],c=t.colorValues||[0,0,0,1],u=l.length,f=this.bounds,p=f[0]=r[0],d=f[1]=o[0],m=1/((f[2]=r[r.length-1])-p),g=1/((f[3]=o[o.length-1])-d),v=e[0],y=e[1];this.shape=[v,y];var x=(v-1)*(y-1)*(h.length>>>1);this.numVertices=x;for(var b=a.mallocUint8(4*x),_=a.mallocFloat32(2*x),w=a.mallocUint8(2*x),k=a.mallocUint32(x),M=0,A=0;A max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D dashTexture;\nuniform float dashScale;\nuniform float opacity;\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n float dashWeight = texture2D(dashTexture, vec2(dashScale * pixelArcLength, 0)).r;\n if(dashWeight < 0.5) {\n discard;\n }\n gl_FragColor = fragColor * opacity;\n}\n"]),s=n(["precision mediump float;\n#define GLSLIFY 1\n\n#define FLOAT_MAX 1.70141184e38\n#define FLOAT_MIN 1.17549435e-38\n\nlowp vec4 encode_float_1540259130(highp float v) {\n highp float av = abs(v);\n\n //Handle special cases\n if(av < FLOAT_MIN) {\n return vec4(0.0, 0.0, 0.0, 0.0);\n } else if(v > FLOAT_MAX) {\n return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;\n } else if(v < -FLOAT_MAX) {\n return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;\n }\n\n highp vec4 c = vec4(0,0,0,0);\n\n //Compute exponent and mantissa\n highp float e = floor(log2(av));\n highp float m = av * pow(2.0, -e) - 1.0;\n \n //Unpack mantissa\n c[1] = floor(128.0 * m);\n m -= c[1] / 128.0;\n c[2] = floor(32768.0 * m);\n m -= c[2] / 32768.0;\n c[3] = floor(8388608.0 * m);\n \n //Unpack exponent\n highp float ebias = e + 127.0;\n c[0] = floor(ebias / 2.0);\n ebias -= c[0] * 2.0;\n c[1] += floor(ebias) * 128.0; \n\n //Unpack sign bit\n c[0] += 128.0 * step(0.0, -v);\n\n //Scale back to range\n return c / 255.0;\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform float pickId;\nuniform vec3 clipBounds[2];\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n gl_FragColor = vec4(pickId/255.0, encode_float_1540259130(pixelArcLength).xyz);\n}"]),l=[{name:"position",type:"vec3"},{name:"nextPosition",type:"vec3"},{name:"arcLength",type:"float"},{name:"lineWidth",type:"float"},{name:"color",type:"vec4"}];r.createShader=function(t){return i(t,a,o,null,l)},r.createPickShader=function(t){return i(t,a,s,null,l)}},{"gl-shader":288,glslify:392}],245:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl||t.scene&&t.scene.gl,r=u(e);r.attributes.position.location=0,r.attributes.nextPosition.location=1,r.attributes.arcLength.location=2,r.attributes.lineWidth.location=3,r.attributes.color.location=4;var o=f(e);o.attributes.position.location=0,o.attributes.nextPosition.location=1,o.attributes.arcLength.location=2,o.attributes.lineWidth.location=3,o.attributes.color.location=4;for(var s=n(e),c=i(e,[{buffer:s,size:3,offset:0,stride:48},{buffer:s,size:3,offset:12,stride:48},{buffer:s,size:1,offset:24,stride:48},{buffer:s,size:1,offset:28,stride:48},{buffer:s,size:4,offset:32,stride:48}]),h=l(new Array(1024),[256,1,4]),p=0;p<1024;++p)h.data[p]=255;var d=a(e,h);d.wrap=e.REPEAT;var m=new g(e,r,o,s,c,d);return m.update(t),m};var n=t("gl-buffer"),i=t("gl-vao"),a=t("gl-texture2d"),o=t("glsl-read-float"),s=t("binary-search-bounds"),l=t("ndarray"),c=t("./lib/shaders"),u=c.createShader,f=c.createPickShader,h=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function p(t,e){for(var r=0,n=0;n<3;++n){var i=t[n]-e[n];r+=i*i}return Math.sqrt(r)}function d(t){for(var e=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],r=0;r<3;++r)e[0][r]=Math.max(t[0][r],e[0][r]),e[1][r]=Math.min(t[1][r],e[1][r]);return e}function m(t,e,r,n){this.arcLength=t,this.position=e,this.index=r,this.dataCoordinate=n}function g(t,e,r,n,i,a){this.gl=t,this.shader=e,this.pickShader=r,this.buffer=n,this.vao=i,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.points=[],this.arcLength=[],this.vertexCount=0,this.bounds=[[0,0,0],[0,0,0]],this.pickId=0,this.lineWidth=1,this.texture=a,this.dashScale=1,this.opacity=1,this.dirty=!0,this.pixelRatio=1}var v=g.prototype;v.isTransparent=function(){return this.opacity<1},v.isOpaque=function(){return this.opacity>=1},v.pickSlots=1,v.setPickBase=function(t){this.pickId=t},v.drawTransparent=v.draw=function(t){if(this.vertexCount){var e=this.gl,r=this.shader,n=this.vao;r.bind(),r.uniforms={model:t.model||h,view:t.view||h,projection:t.projection||h,clipBounds:d(this.clipBounds),dashTexture:this.texture.bind(),dashScale:this.dashScale/this.arcLength[this.arcLength.length-1],opacity:this.opacity,screenShape:[e.drawingBufferWidth,e.drawingBufferHeight],pixelRatio:this.pixelRatio},n.bind(),n.draw(e.TRIANGLE_STRIP,this.vertexCount),n.unbind()}},v.drawPick=function(t){if(this.vertexCount){var e=this.gl,r=this.pickShader,n=this.vao;r.bind(),r.uniforms={model:t.model||h,view:t.view||h,projection:t.projection||h,pickId:this.pickId,clipBounds:d(this.clipBounds),screenShape:[e.drawingBufferWidth,e.drawingBufferHeight],pixelRatio:this.pixelRatio},n.bind(),n.draw(e.TRIANGLE_STRIP,this.vertexCount),n.unbind()}},v.update=function(t){var e,r;this.dirty=!0;var n=!!t.connectGaps;"dashScale"in t&&(this.dashScale=t.dashScale),"opacity"in t&&(this.opacity=+t.opacity);var i=[],a=[],o=[],c=0,u=0,f=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],h=t.position||t.positions;if(h){var d=t.color||t.colors||[0,0,0,1],m=t.lineWidth||1,g=!1;t:for(e=1;e0){for(var w=0;w<24;++w)i.push(i[i.length-12]);u+=2,g=!0}continue t}f[0][r]=Math.min(f[0][r],b[r],_[r]),f[1][r]=Math.max(f[1][r],b[r],_[r])}Array.isArray(d[0])?(v=d.length>e-1?d[e-1]:d.length>0?d[d.length-1]:[0,0,0,1],y=d.length>e?d[e]:d.length>0?d[d.length-1]:[0,0,0,1]):v=y=d,3===v.length&&(v=[v[0],v[1],v[2],1]),3===y.length&&(y=[y[0],y[1],y[2],1]),x=Array.isArray(m)?m.length>e-1?m[e-1]:m.length>0?m[m.length-1]:[0,0,0,1]:m;var k=c;if(c+=p(b,_),g){for(r=0;r<2;++r)i.push(b[0],b[1],b[2],_[0],_[1],_[2],k,x,v[0],v[1],v[2],v[3]);u+=2,g=!1}i.push(b[0],b[1],b[2],_[0],_[1],_[2],k,x,v[0],v[1],v[2],v[3],b[0],b[1],b[2],_[0],_[1],_[2],k,-x,v[0],v[1],v[2],v[3],_[0],_[1],_[2],b[0],b[1],b[2],c,-x,y[0],y[1],y[2],y[3],_[0],_[1],_[2],b[0],b[1],b[2],c,x,y[0],y[1],y[2],y[3]),u+=4}}if(this.buffer.update(i),a.push(c),o.push(h[h.length-1].slice()),this.bounds=f,this.vertexCount=u,this.points=o,this.arcLength=a,"dashes"in t){var M=t.dashes.slice();for(M.unshift(0),e=1;e max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n vec3 normal = normals(f_data);\n\n if (dot(N, normal) < 0.0) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]),o=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}"]),s=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]),l=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}"]),c=n(["precision mediump float;\n#define GLSLIFY 1\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5,0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]),u=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}"]),f=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]),h=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}"]),p=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}"]),d=n(["precision mediump float;\n#define GLSLIFY 1\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor,1);\n}\n"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec3"},{name:"normal",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"}]},r.wireShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"}]},r.pointShader={vertex:l,fragment:c,attributes:[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"pointSize",type:"float"}]},r.pickShader={vertex:u,fragment:f,attributes:[{name:"position",type:"vec3"},{name:"id",type:"vec4"}]},r.pointPickShader={vertex:h,fragment:f,attributes:[{name:"position",type:"vec3"},{name:"pointSize",type:"float"},{name:"id",type:"vec4"}]},r.contourShader={vertex:p,fragment:d,attributes:[{name:"position",type:"vec3"}]}},{glslify:392}],268:[function(t,e,r){"use strict";var n=t("gl-shader"),i=t("gl-buffer"),a=t("gl-vao"),o=t("gl-texture2d"),s=t("normals"),l=t("gl-mat4/multiply"),c=t("gl-mat4/invert"),u=t("ndarray"),f=t("colormap"),h=t("simplicial-complex-contour"),p=t("typedarray-pool"),d=t("./lib/shaders"),m=t("./lib/closest-point"),g=d.meshShader,v=d.wireShader,y=d.pointShader,x=d.pickShader,b=d.pointPickShader,_=d.contourShader,w=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function k(t,e,r,n,i,a,o,s,l,c,u,f,h,p,d,m,g,v,y,x,b,_,k,M,A,T,S){this.gl=t,this.cells=[],this.positions=[],this.intensity=[],this.texture=e,this.dirty=!0,this.triShader=r,this.lineShader=n,this.pointShader=i,this.pickShader=a,this.pointPickShader=o,this.contourShader=s,this.trianglePositions=l,this.triangleColors=u,this.triangleNormals=h,this.triangleUVs=f,this.triangleIds=c,this.triangleVAO=p,this.triangleCount=0,this.lineWidth=1,this.edgePositions=d,this.edgeColors=g,this.edgeUVs=v,this.edgeIds=m,this.edgeVAO=y,this.edgeCount=0,this.pointPositions=x,this.pointColors=_,this.pointUVs=k,this.pointSizes=M,this.pointIds=b,this.pointVAO=A,this.pointCount=0,this.contourLineWidth=1,this.contourPositions=T,this.contourVAO=S,this.contourCount=0,this.contourColor=[0,0,0],this.contourEnable=!0,this.pickId=1,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.lightPosition=[1e5,1e5,0],this.ambientLight=.8,this.diffuseLight=.8,this.specularLight=2,this.roughness=.5,this.fresnel=1.5,this.opacity=1,this._model=w,this._view=w,this._projection=w,this._resolution=[1,1]}var M=k.prototype;function A(t){var e=n(t,y.vertex,y.fragment);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e.attributes.pointSize.location=4,e}function T(t){var e=n(t,x.vertex,x.fragment);return e.attributes.position.location=0,e.attributes.id.location=1,e}function S(t){var e=n(t,b.vertex,b.fragment);return e.attributes.position.location=0,e.attributes.id.location=1,e.attributes.pointSize.location=4,e}function E(t){var e=n(t,_.vertex,_.fragment);return e.attributes.position.location=0,e}M.isOpaque=function(){return this.opacity>=1},M.isTransparent=function(){return this.opacity<1},M.pickSlots=1,M.setPickBase=function(t){this.pickId=t},M.highlight=function(t){if(t&&this.contourEnable){for(var e=h(this.cells,this.intensity,t.intensity),r=e.cells,n=e.vertexIds,i=e.vertexWeights,a=r.length,o=p.mallocFloat32(6*a),s=0,l=0;l0&&((f=this.triShader).bind(),f.uniforms=s,this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind());this.edgeCount>0&&this.lineWidth>0&&((f=this.lineShader).bind(),f.uniforms=s,this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind());this.pointCount>0&&((f=this.pointShader).bind(),f.uniforms=s,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind());this.contourEnable&&this.contourCount>0&&this.contourLineWidth>0&&((f=this.contourShader).bind(),f.uniforms=s,this.contourVAO.bind(),e.drawArrays(e.LINES,0,this.contourCount),this.contourVAO.unbind())},M.drawPick=function(t){t=t||{};for(var e=this.gl,r=t.model||w,n=t.view||w,i=t.projection||w,a=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],o=0;o<3;++o)a[0][o]=Math.max(a[0][o],this.clipBounds[0][o]),a[1][o]=Math.min(a[1][o],this.clipBounds[1][o]);this._model=[].slice.call(r),this._view=[].slice.call(n),this._projection=[].slice.call(i),this._resolution=[e.drawingBufferWidth,e.drawingBufferHeight];var s,l={model:r,view:n,projection:i,clipBounds:a,pickId:this.pickId/255};((s=this.pickShader).bind(),s.uniforms=l,this.triangleCount>0&&(this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind()),this.edgeCount>0&&(this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind()),this.pointCount>0)&&((s=this.pointPickShader).bind(),s.uniforms=l,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind())},M.pick=function(t){if(!t)return null;if(t.id!==this.pickId)return null;for(var e=t.value[0]+256*t.value[1]+65536*t.value[2],r=this.cells[e],n=this.positions,i=new Array(r.length),a=0;ai[M]&&(r.uniforms.dataAxis=c,r.uniforms.screenOffset=u,r.uniforms.color=g[t],r.uniforms.angle=v[t],a.drawArrays(a.TRIANGLES,i[M],i[A]-i[M]))),y[t]&&k&&(u[1^t]-=T*p*x[t],r.uniforms.dataAxis=f,r.uniforms.screenOffset=u,r.uniforms.color=b[t],r.uniforms.angle=_[t],a.drawArrays(a.TRIANGLES,w,k)),u[1^t]=T*s[2+(1^t)]-1,d[t+2]&&(u[1^t]+=T*p*m[t+2],Mi[M]&&(r.uniforms.dataAxis=c,r.uniforms.screenOffset=u,r.uniforms.color=g[t+2],r.uniforms.angle=v[t+2],a.drawArrays(a.TRIANGLES,i[M],i[A]-i[M]))),y[t+2]&&k&&(u[1^t]+=T*p*x[t+2],r.uniforms.dataAxis=f,r.uniforms.screenOffset=u,r.uniforms.color=b[t+2],r.uniforms.angle=_[t+2],a.drawArrays(a.TRIANGLES,w,k))}),m.drawTitle=function(){var t=[0,0],e=[0,0];return function(){var r=this.plot,n=this.shader,i=r.gl,a=r.screenBox,o=r.titleCenter,s=r.titleAngle,l=r.titleColor,c=r.pixelRatio;if(this.titleCount){for(var u=0;u<2;++u)e[u]=2*(o[u]*c-a[u])/(a[2+u]-a[u])-1;n.bind(),n.uniforms.dataAxis=t,n.uniforms.screenOffset=e,n.uniforms.angle=s,n.uniforms.color=l,i.drawArrays(i.TRIANGLES,this.titleOffset,this.titleCount)}}}(),m.bind=(h=[0,0],p=[0,0],d=[0,0],function(){var t=this.plot,e=this.shader,r=t._tickBounds,n=t.dataBox,i=t.screenBox,a=t.viewBox;e.bind();for(var o=0;o<2;++o){var s=r[o],l=r[o+2]-s,c=.5*(n[o+2]+n[o]),u=n[o+2]-n[o],f=a[o],m=a[o+2]-f,g=i[o],v=i[o+2]-g;p[o]=2*l/u*m/v,h[o]=2*(s-c)/u*m/v}d[1]=2*t.pixelRatio/(i[3]-i[1]),d[0]=d[1]*(i[3]-i[1])/(i[2]-i[0]),e.uniforms.dataScale=p,e.uniforms.dataShift=h,e.uniforms.textScale=d,this.vbo.bind(),e.attributes.textCoordinate.pointer()}),m.update=function(t){var e,r,n,i,o,s=[],l=t.ticks,c=t.bounds;for(o=0;o<2;++o){var u=[Math.floor(s.length/3)],f=[-1/0],h=l[o];for(e=0;e=0){var m=e[d]-n[d]*(e[d+2]-e[d])/(n[d+2]-n[d]);0===d?o.drawLine(m,e[1],m,e[3],p[d],h[d]):o.drawLine(e[0],m,e[2],m,p[d],h[d])}}for(d=0;d=0;--t)this.objects[t].dispose();this.objects.length=0;for(t=this.overlays.length-1;t>=0;--t)this.overlays[t].dispose();this.overlays.length=0,this.gl=null},c.addObject=function(t){this.objects.indexOf(t)<0&&(this.objects.push(t),this.setDirty())},c.removeObject=function(t){for(var e=this.objects,r=0;r0&&0===L[e-1];)L.pop(),z.pop().dispose()}window.addEventListener("resize",j),F.update=function(t){e||(t=t||{},O=!0,I=!0)},F.add=function(t){e||(t.axes=A,E.push(t),C.push(-1),O=!0,I=!0,V())},F.remove=function(t){if(!e){var r=E.indexOf(t);r<0||(E.splice(r,1),C.pop(),O=!0,I=!0,V())}},F.dispose=function(){if(!e&&(e=!0,window.removeEventListener("resize",j),r.removeEventListener("webglcontextlost",H),F.mouseListener.enabled=!1,!F.contextLost)){A.dispose(),S.dispose();for(var t=0;tb.distance)continue;for(var u=0;u0){r=Math.round(Math.pow(10,e));return Math.ceil(t/r)*r}return Math.ceil(t)}function g(t){return"boolean"!=typeof t||t}},{"./lib/shader":276,"3d-view-controls":44,"a-big-triangle":47,"gl-axes3d":222,"gl-axes3d/properties":229,"gl-fbo":239,"gl-mat4/perspective":257,"gl-select-static":287,"gl-spikes3d":297,"is-mobile":403,"mouse-change":418}],278:[function(t,e,r){var n=t("glslify");r.pointVertex=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\n\nuniform mat3 matrix;\nuniform float pointSize;\nuniform float pointCloud;\n\nhighp float rand(vec2 co) {\n highp float a = 12.9898;\n highp float b = 78.233;\n highp float c = 43758.5453;\n highp float d = dot(co.xy, vec2(a, b));\n highp float e = mod(d, 3.14);\n return fract(sin(e) * c);\n}\n\nvoid main() {\n vec3 hgPosition = matrix * vec3(position, 1);\n gl_Position = vec4(hgPosition.xy, 0, hgPosition.z);\n // if we don't jitter the point size a bit, overall point cloud\n // saturation 'jumps' on zooming, which is disturbing and confusing\n gl_PointSize = pointSize * ((19.5 + rand(position)) / 20.0);\n if(pointCloud != 0.0) { // pointCloud is truthy\n // get the same square surface as circle would be\n gl_PointSize *= 0.886;\n }\n}"]),r.pointFragment=n(["precision mediump float;\n#define GLSLIFY 1\n\nuniform vec4 color, borderColor;\nuniform float centerFraction;\nuniform float pointCloud;\n\nvoid main() {\n float radius;\n vec4 baseColor;\n if(pointCloud != 0.0) { // pointCloud is truthy\n if(centerFraction == 1.0) {\n gl_FragColor = color;\n } else {\n gl_FragColor = mix(borderColor, color, centerFraction);\n }\n } else {\n radius = length(2.0 * gl_PointCoord.xy - 1.0);\n if(radius > 1.0) {\n discard;\n }\n baseColor = mix(borderColor, color, step(radius, centerFraction));\n gl_FragColor = vec4(baseColor.rgb * baseColor.a, baseColor.a);\n }\n}\n"]),r.pickVertex=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\n\nuniform mat3 matrix;\nuniform float pointSize;\nuniform vec4 pickOffset;\n\nvarying vec4 fragId;\n\nvoid main() {\n vec3 hgPosition = matrix * vec3(position, 1);\n gl_Position = vec4(hgPosition.xy, 0, hgPosition.z);\n gl_PointSize = pointSize;\n\n vec4 id = pickId + pickOffset;\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n fragId = id;\n}\n"]),r.pickFragment=n(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\n\nvoid main() {\n float radius = length(2.0 * gl_PointCoord.xy - 1.0);\n if(radius > 1.0) {\n discard;\n }\n gl_FragColor = fragId / 255.0;\n}\n"])},{glslify:392}],279:[function(t,e,r){"use strict";var n=t("gl-shader"),i=t("gl-buffer"),a=t("typedarray-pool"),o=t("./lib/shader");function s(t,e,r,n,i){this.plot=t,this.offsetBuffer=e,this.pickBuffer=r,this.shader=n,this.pickShader=i,this.sizeMin=.5,this.sizeMinCap=2,this.sizeMax=20,this.areaRatio=1,this.pointCount=0,this.color=[1,0,0,1],this.borderColor=[0,0,0,1],this.blend=!1,this.pickOffset=0,this.points=null}e.exports=function(t,e){var r=t.gl,a=i(r),l=i(r),c=n(r,o.pointVertex,o.pointFragment),u=n(r,o.pickVertex,o.pickFragment),f=new s(t,a,l,c,u);return f.update(e),t.addObject(f),f};var l,c,u=s.prototype;u.dispose=function(){this.shader.dispose(),this.pickShader.dispose(),this.offsetBuffer.dispose(),this.pickBuffer.dispose(),this.plot.removeObject(this)},u.update=function(t){var e;function r(e,r){return e in t?t[e]:r}t=t||{},this.sizeMin=r("sizeMin",.5),this.sizeMax=r("sizeMax",20),this.color=r("color",[1,0,0,1]).slice(),this.areaRatio=r("areaRatio",1),this.borderColor=r("borderColor",[0,0,0,1]).slice(),this.blend=r("blend",!1);var n=t.positions.length>>>1,i=t.positions instanceof Float32Array,o=t.idToIndex instanceof Int32Array&&t.idToIndex.length>=n,s=t.positions,l=i?s:a.mallocFloat32(s.length),c=o?t.idToIndex:a.mallocInt32(n);if(i||l.set(s),!o)for(l.set(s),e=0;e>>1;for(r=0;r=e[0]&&a<=e[2]&&o>=e[1]&&o<=e[3]&&n++}return n}(this.points,i),u=this.plot.pickPixelRatio*Math.max(Math.min(this.sizeMinCap,this.sizeMin),Math.min(this.sizeMax,this.sizeMax/Math.pow(s,.33333)));l[0]=2/a,l[4]=2/o,l[6]=-2*i[0]/a-1,l[7]=-2*i[1]/o-1,this.offsetBuffer.bind(),r.bind(),r.attributes.position.pointer(),r.uniforms.matrix=l,r.uniforms.color=this.color,r.uniforms.borderColor=this.borderColor,r.uniforms.pointCloud=u<5,r.uniforms.pointSize=u,r.uniforms.centerFraction=Math.min(1,Math.max(0,Math.sqrt(1-this.areaRatio))),e&&(c[0]=255&t,c[1]=t>>8&255,c[2]=t>>16&255,c[3]=t>>24&255,this.pickBuffer.bind(),r.attributes.pickId.pointer(n.UNSIGNED_BYTE),r.uniforms.pickOffset=c,this.pickOffset=t);var f=n.getParameter(n.BLEND),h=n.getParameter(n.DITHER);return f&&!this.blend&&n.disable(n.BLEND),h&&n.disable(n.DITHER),n.drawArrays(n.POINTS,0,this.pointCount),f&&!this.blend&&n.enable(n.BLEND),h&&n.enable(n.DITHER),t+this.pointCount}),u.draw=u.unifiedDraw,u.drawPick=u.unifiedDraw,u.pick=function(t,e,r){var n=this.pickOffset,i=this.pointCount;if(r=n+i)return null;var a=r-n,o=this.points;return{object:this,pointId:a,dataCoord:[o[2*a],o[2*a+1]]}}},{"./lib/shader":278,"gl-buffer":230,"gl-shader":288,"typedarray-pool":522}],280:[function(t,e,r){e.exports=function(t,e,r,n){var i,a,o,s,l,c=e[0],u=e[1],f=e[2],h=e[3],p=r[0],d=r[1],m=r[2],g=r[3];(a=c*p+u*d+f*m+h*g)<0&&(a=-a,p=-p,d=-d,m=-m,g=-g);1-a>1e-6?(i=Math.acos(a),o=Math.sin(i),s=Math.sin((1-n)*i)/o,l=Math.sin(n*i)/o):(s=1-n,l=n);return t[0]=s*c+l*p,t[1]=s*u+l*d,t[2]=s*f+l*m,t[3]=s*h+l*g,t}},{}],281:[function(t,e,r){"use strict";e.exports=function(t){return t||0===t?t.toString():""}},{}],282:[function(t,e,r){"use strict";var n=t("vectorize-text");e.exports=function(t,e){var r=i[e];r||(r=i[e]={});if(t in r)return r[t];for(var a=n(t,{textAlign:"center",textBaseline:"middle",lineHeight:1,font:e}),o=n(t,{triangles:!0,textAlign:"center",textBaseline:"middle",lineHeight:1,font:e}),s=[[1/0,1/0],[-1/0,-1/0]],l=0;l max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform vec4 highlightId;\nuniform float highlightScale;\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = 1.0;\n if(distance(highlightId, id) < 0.0001) {\n scale = highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1);\n vec4 viewPosition = view * worldPosition;\n viewPosition = viewPosition / viewPosition.w;\n vec4 clipPosition = projection * (viewPosition + scale * vec4(glyph.x, -glyph.y, 0, 0));\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]),o=i(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float highlightScale, pixelRatio;\nuniform vec4 highlightId;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = pixelRatio;\n if(distance(highlightId.bgr, id.bgr) < 0.001) {\n scale *= highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1.0);\n vec4 viewPosition = view * worldPosition;\n vec4 clipPosition = projection * viewPosition;\n clipPosition /= clipPosition.w;\n\n gl_Position = clipPosition + vec4(screenSize * scale * vec2(glyph.x, -glyph.y), 0.0, 0.0);\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]),s=i(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform float highlightScale;\nuniform vec4 highlightId;\nuniform vec3 axes[2];\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float scale, pixelRatio;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float lscale = pixelRatio * scale;\n if(distance(highlightId, id) < 0.0001) {\n lscale *= highlightScale;\n }\n\n vec4 clipCenter = projection * view * model * vec4(position, 1);\n vec3 dataPosition = position + 0.5*lscale*(axes[0] * glyph.x + axes[1] * glyph.y) * clipCenter.w * screenSize.y;\n vec4 clipPosition = projection * view * model * vec4(dataPosition, 1);\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = dataPosition;\n }\n}\n"]),l=i(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float opacity;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = interpColor * opacity;\n}\n"]),c=i(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float pickGroup;\n\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = vec4(pickGroup, pickId.bgr);\n}"]),u=[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"glyph",type:"vec2"},{name:"id",type:"vec4"}],f={vertex:a,fragment:l,attributes:u},h={vertex:o,fragment:l,attributes:u},p={vertex:s,fragment:l,attributes:u},d={vertex:a,fragment:c,attributes:u},m={vertex:o,fragment:c,attributes:u},g={vertex:s,fragment:c,attributes:u};function v(t,e){var r=n(t,e),i=r.attributes;return i.position.location=0,i.color.location=1,i.glyph.location=2,i.id.location=3,r}r.createPerspective=function(t){return v(t,f)},r.createOrtho=function(t){return v(t,h)},r.createProject=function(t){return v(t,p)},r.createPickPerspective=function(t){return v(t,d)},r.createPickOrtho=function(t){return v(t,m)},r.createPickProject=function(t){return v(t,g)}},{"gl-shader":288,glslify:392}],284:[function(t,e,r){"use strict";var n=t("is-string-blank"),i=t("gl-buffer"),a=t("gl-vao"),o=t("typedarray-pool"),s=t("gl-mat4/multiply"),l=t("./lib/shaders"),c=t("./lib/glyphs"),u=t("./lib/get-simple-string"),f=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function h(t,e){var r=t[0],n=t[1],i=t[2],a=t[3];return t[0]=e[0]*r+e[4]*n+e[8]*i+e[12]*a,t[1]=e[1]*r+e[5]*n+e[9]*i+e[13]*a,t[2]=e[2]*r+e[6]*n+e[10]*i+e[14]*a,t[3]=e[3]*r+e[7]*n+e[11]*i+e[15]*a,t}function p(t,e,r,n){return h(n,n),h(n,n),h(n,n)}function d(t,e){this.index=t,this.dataCoordinate=this.position=e}function m(t,e,r,n,i,a,o,s,l,c,u,f){this.gl=t,this.pixelRatio=1,this.shader=e,this.orthoShader=r,this.projectShader=n,this.pointBuffer=i,this.colorBuffer=a,this.glyphBuffer=o,this.idBuffer=s,this.vao=l,this.vertexCount=0,this.lineVertexCount=0,this.opacity=1,this.lineWidth=0,this.projectScale=[2/3,2/3,2/3],this.projectOpacity=[1,1,1],this.pickId=0,this.pickPerspectiveShader=c,this.pickOrthoShader=u,this.pickProjectShader=f,this.points=[],this._selectResult=new d(0,[0,0,0]),this.useOrtho=!0,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.axesProject=[!0,!0,!0],this.axesBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.highlightId=[1,1,1,1],this.highlightScale=2,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.dirty=!0}e.exports=function(t){var e=t.gl,r=l.createPerspective(e),n=l.createOrtho(e),o=l.createProject(e),s=l.createPickPerspective(e),c=l.createPickOrtho(e),u=l.createPickProject(e),f=i(e),h=i(e),p=i(e),d=i(e),g=a(e,[{buffer:f,size:3,type:e.FLOAT},{buffer:h,size:4,type:e.FLOAT},{buffer:p,size:2,type:e.FLOAT},{buffer:d,size:4,type:e.UNSIGNED_BYTE,normalized:!0}]),v=new m(e,r,n,o,f,h,p,d,g,s,c,u);return v.update(t),v};var g=m.prototype;g.pickSlots=1,g.setPickBase=function(t){this.pickId=t},g.isTransparent=function(){if(this.opacity<1)return!0;for(var t=0;t<3;++t)if(this.axesProject[t]&&this.projectOpacity[t]<1)return!0;return!1},g.isOpaque=function(){if(this.opacity>=1)return!0;for(var t=0;t<3;++t)if(this.axesProject[t]&&this.projectOpacity[t]>=1)return!0;return!1};var v=[0,0],y=[0,0,0],x=[0,0,0],b=[0,0,0,1],_=[0,0,0,1],w=f.slice(),k=[0,0,0],M=[[0,0,0],[0,0,0]];function A(t){return t[0]=t[1]=t[2]=0,t}function T(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=1,t}function S(t,e,r,n){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[r]=n,t}function E(t,e,r,n,i){var a,o=e.axesProject,l=e.gl,c=t.uniforms,u=r.model||f,h=r.view||f,d=r.projection||f,m=e.axesBounds,g=function(t){for(var e=M,r=0;r<2;++r)for(var n=0;n<3;++n)e[r][n]=Math.max(Math.min(t[r][n],1e8),-1e8);return e}(e.clipBounds);a=e.axes&&e.axes.lastCubeProps?e.axes.lastCubeProps.axis:[1,1,1],v[0]=2/l.drawingBufferWidth,v[1]=2/l.drawingBufferHeight,t.bind(),c.view=h,c.projection=d,c.screenSize=v,c.highlightId=e.highlightId,c.highlightScale=e.highlightScale,c.clipBounds=g,c.pickGroup=e.pickId/255,c.pixelRatio=e.pixelRatio;for(var E=0;E<3;++E)if(o[E]&&e.projectOpacity[E]<1===n){c.scale=e.projectScale[E],c.opacity=e.projectOpacity[E];for(var C=w,L=0;L<16;++L)C[L]=0;for(L=0;L<4;++L)C[5*L]=1;C[5*E]=0,a[E]<0?C[12+E]=m[0][E]:C[12+E]=m[1][E],s(C,u,C),c.model=C;var z=(E+1)%3,O=(E+2)%3,I=A(y),P=A(x);I[z]=1,P[O]=1;var D=p(0,0,0,T(b,I)),R=p(0,0,0,T(_,P));if(Math.abs(D[1])>Math.abs(R[1])){var B=D;D=R,R=B,B=I,I=P,P=B;var F=z;z=O,O=F}D[0]<0&&(I[z]=-1),R[1]>0&&(P[O]=-1);var N=0,j=0;for(L=0;L<4;++L)N+=Math.pow(u[4*z+L],2),j+=Math.pow(u[4*O+L],2);I[z]/=Math.sqrt(N),P[O]/=Math.sqrt(j),c.axes[0]=I,c.axes[1]=P,c.fragClipBounds[0]=S(k,g[0],E,-1e8),c.fragClipBounds[1]=S(k,g[1],E,1e8),e.vao.draw(l.TRIANGLES,e.vertexCount),e.lineWidth>0&&(l.lineWidth(e.lineWidth),e.vao.draw(l.LINES,e.lineVertexCount,e.vertexCount))}}var C=[[-1e8,-1e8,-1e8],[1e8,1e8,1e8]];function L(t,e,r,n,i,a){var o=r.gl;if(r.vao.bind(),i===r.opacity<1||a){t.bind();var s=t.uniforms;s.model=n.model||f,s.view=n.view||f,s.projection=n.projection||f,v[0]=2/o.drawingBufferWidth,v[1]=2/o.drawingBufferHeight,s.screenSize=v,s.highlightId=r.highlightId,s.highlightScale=r.highlightScale,s.fragClipBounds=C,s.clipBounds=r.axes.bounds,s.opacity=r.opacity,s.pickGroup=r.pickId/255,s.pixelRatio=r.pixelRatio,r.vao.draw(o.TRIANGLES,r.vertexCount),r.lineWidth>0&&(o.lineWidth(r.lineWidth),r.vao.draw(o.LINES,r.lineVertexCount,r.vertexCount))}E(e,r,n,i),r.vao.unbind()}function z(t,e,r){var i;i=Array.isArray(t)?e=this.pointCount||e<0)return null;var r=this.points[e],n=this._selectResult;n.index=e;for(var i=0;i<3;++i)n.position[i]=n.dataCoordinate[i]=r[i];return n},g.highlight=function(t){if(t){var e=t.index,r=255&e,n=e>>8&255,i=e>>16&255;this.highlightId=[r/255,n/255,i/255,0]}else this.highlightId=[1,1,1,1]},g.update=function(t){if("perspective"in(t=t||{})&&(this.useOrtho=!t.perspective),"orthographic"in t&&(this.useOrtho=!!t.orthographic),"lineWidth"in t&&(this.lineWidth=t.lineWidth),"project"in t)if(Array.isArray(t.project))this.axesProject=t.project;else{var e=!!t.project;this.axesProject=[e,e,e]}if("projectScale"in t)if(Array.isArray(t.projectScale))this.projectScale=t.projectScale.slice();else{var r=+t.projectScale;this.projectScale=[r,r,r]}if("projectOpacity"in t)if(Array.isArray(t.projectOpacity))this.projectOpacity=t.projectOpacity.slice();else{r=+t.projectOpacity;this.projectOpacity=[r,r,r]}"opacity"in t&&(this.opacity=t.opacity),this.dirty=!0;var n,i,a=t.position,s=t.font||"normal",l=t.alignment||[0,0];if(2===l.length)n=l[0],i=l[1];else{n=[],i=[];for(var c=0;c0){var O=0,I=y,P=[0,0,0,1],D=[0,0,0,1],R=Array.isArray(p)&&Array.isArray(p[0]),B=Array.isArray(g)&&Array.isArray(g[0]);t:for(c=0;c0?1-A[0][0]:G<0?1+A[1][0]:1,W*=W>0?1-A[0][1]:W<0?1+A[1][1]:1],X=k.cells||[],Z=k.positions||[];for(w=0;w0){var v=r*u;o.drawBox(f-v,h-v,p+v,h+v,a),o.drawBox(f-v,d-v,p+v,d+v,a),o.drawBox(f-v,h-v,f+v,d+v,a),o.drawBox(p-v,h-v,p+v,d+v,a)}}}},s.update=function(t){t=t||{},this.innerFill=!!t.innerFill,this.outerFill=!!t.outerFill,this.innerColor=(t.innerColor||[0,0,0,.5]).slice(),this.outerColor=(t.outerColor||[0,0,0,.5]).slice(),this.borderColor=(t.borderColor||[0,0,0,1]).slice(),this.borderWidth=t.borderWidth||0,this.selectBox=(t.selectBox||this.selectBox).slice()},s.dispose=function(){this.boxBuffer.dispose(),this.boxShader.dispose(),this.plot.removeOverlay(this)}},{"./lib/shaders":285,"gl-buffer":230,"gl-shader":288}],287:[function(t,e,r){"use strict";e.exports=function(t,e){var r=n(t,e),a=i.mallocUint8(e[0]*e[1]*4);return new c(t,r,a)};var n=t("gl-fbo"),i=t("typedarray-pool"),a=t("ndarray"),o=t("bit-twiddle").nextPow2,s=t("cwise/lib/wrapper")({args:["array",{offset:[0,0,1],array:0},{offset:[0,0,2],array:0},{offset:[0,0,3],array:0},"scalar","scalar","index"],pre:{body:"{this_closestD2=1e8,this_closestX=-1,this_closestY=-1}",args:[],thisVars:["this_closestD2","this_closestX","this_closestY"],localVars:[]},body:{body:"{if(_inline_16_arg0_<255||_inline_16_arg1_<255||_inline_16_arg2_<255||_inline_16_arg3_<255){var _inline_16_l=_inline_16_arg4_-_inline_16_arg6_[0],_inline_16_a=_inline_16_arg5_-_inline_16_arg6_[1],_inline_16_f=_inline_16_l*_inline_16_l+_inline_16_a*_inline_16_a;_inline_16_fthis.buffer.length){i.free(this.buffer);for(var n=this.buffer=i.mallocUint8(o(r*e*4)),a=0;ar)for(t=r;te)for(t=e;t=0){for(var k=0|w.type.charAt(w.type.length-1),M=new Array(k),A=0;A=0;)T+=1;_[y]=T}var S=new Array(r.length);function E(){h.program=o.program(p,h._vref,h._fref,b,_);for(var t=0;t=0){var d=h.charCodeAt(h.length-1)-48;if(d<2||d>4)throw new n("","Invalid data type for attribute "+f+": "+h);o(t,e,p[0],i,d,a,f)}else{if(!(h.indexOf("mat")>=0))throw new n("","Unknown data type for attribute "+f+": "+h);var d=h.charCodeAt(h.length-1)-48;if(d<2||d>4)throw new n("","Invalid data type for attribute "+f+": "+h);s(t,e,p,i,d,a,f)}}}return a};var n=t("./GLError");function i(t,e,r,n,i,a){this._gl=t,this._wrapper=e,this._index=r,this._locations=n,this._dimension=i,this._constFunc=a}var a=i.prototype;function o(t,e,r,n,a,o,s){for(var l=["gl","v"],c=[],u=0;u4)throw new i("","Invalid uniform dimension type for matrix "+name+": "+r);return"gl.uniformMatrix"+a+"fv(locations["+e+"],false,obj"+t+")"}throw new i("","Unknown uniform data type for "+name+": "+r)}var a=r.charCodeAt(r.length-1)-48;if(a<2||a>4)throw new i("","Invalid data type");switch(r.charAt(0)){case"b":case"i":return"gl.uniform"+a+"iv(locations["+e+"],obj"+t+")";case"v":return"gl.uniform"+a+"fv(locations["+e+"],obj"+t+")";default:throw new i("","Unrecognized data type for vector "+name+": "+r)}}}function c(e){for(var n=["return function updateProperty(obj){"],i=function t(e,r){if("object"!=typeof r)return[[e,r]];var n=[];for(var i in r){var a=r[i],o=e;parseInt(i)+""===i?o+="["+i+"]":o+="."+i,"object"==typeof a?n.push.apply(n,t(o,a)):n.push([o,a])}return n}("",e),a=0;a4)throw new i("","Invalid data type");return"b"===t.charAt(0)?o(r,!1):o(r,0)}if(0===t.indexOf("mat")&&4===t.length){var r=t.charCodeAt(t.length-1)-48;if(r<2||r>4)throw new i("","Invalid uniform dimension type for matrix "+name+": "+t);return o(r*r,0)}throw new i("","Unknown uniform data type for "+name+": "+t)}}(r[u].type);var p}function f(t){var e;if(Array.isArray(t)){e=new Array(t.length);for(var r=0;r1){l[0]in o||(o[l[0]]=[]),o=o[l[0]];for(var c=1;c1)for(var l=0;l 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float tubeScale;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n normal = normalize(normal * inverse(mat3(model)));\n\n gl_Position = projection * view * tubePosition;\n f_color = color;\n f_normal = normal;\n f_data = tubePosition.xyz;\n f_position = position.xyz;\n f_eyeDirection = eyePosition - tubePosition.xyz;\n f_lightDirection = lightPosition - tubePosition.xyz;\n f_uv = uv;\n}\n"]),a=n(["precision mediump float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}"]),o=n(["precision mediump float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform float tubeScale;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n gl_Position = projection * view * tubePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]),s=n(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec4"},{name:"normal",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"vector",type:"vec4"}]},r.pickShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec4"},{name:"id",type:"vec4"},{name:"vector",type:"vec4"}]}},{glslify:392}],300:[function(t,e,r){"use strict";var n=t("gl-shader"),i=t("gl-buffer"),a=t("gl-vao"),o=t("gl-texture2d"),s=t("normals"),l=t("gl-mat4/multiply"),c=t("gl-mat4/invert"),u=t("ndarray"),f=t("colormap"),h=t("simplicial-complex-contour"),p=t("typedarray-pool"),d=t("./shaders"),m=(t("./closest-point"),d.meshShader),g=d.pickShader,v=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function y(t,e,r,n,i,a,o,s,l,c,u,f,h,p,d,m,g,y,x,b,_,w,k,M,A,T,S,E){this.gl=t,this.cells=[],this.positions=[],this.intensity=[],this.texture=e,this.dirty=!0,this.triShader=r,this.lineShader=n,this.pointShader=i,this.pickShader=a,this.pointPickShader=o,this.contourShader=s,this.trianglePositions=l,this.triangleVectors=c,this.triangleColors=f,this.triangleNormals=p,this.triangleUVs=h,this.triangleIds=u,this.triangleVAO=d,this.triangleCount=0,this.lineWidth=1,this.edgePositions=m,this.edgeColors=y,this.edgeUVs=x,this.edgeIds=g,this.edgeVAO=b,this.edgeCount=0,this.pointPositions=_,this.pointColors=k,this.pointUVs=M,this.pointSizes=A,this.pointIds=w,this.pointVAO=T,this.pointCount=0,this.contourLineWidth=1,this.contourPositions=S,this.contourVAO=E,this.contourCount=0,this.contourColor=[0,0,0],this.contourEnable=!1,this.pickId=1,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.lightPosition=[1e5,1e5,0],this.ambientLight=.8,this.diffuseLight=.8,this.specularLight=2,this.roughness=.5,this.fresnel=1.5,this.opacity=1,this.tubeScale=1,this._model=v,this._view=v,this._projection=v,this._resolution=[1,1]}var x=y.prototype;function b(t){var e=n(t,g.vertex,g.fragment,null,g.attributes);return e.attributes.position.location=0,e.attributes.id.location=1,e.attributes.vector.location=5,e}x.isOpaque=function(){return this.opacity>=1},x.isTransparent=function(){return this.opacity<1},x.pickSlots=1,x.setPickBase=function(t){this.pickId=t},x.highlight=function(t){if(t&&this.contourEnable){for(var e=h(this.cells,this.intensity,t.intensity),r=e.cells,n=e.vertexIds,i=e.vertexWeights,a=r.length,o=p.mallocFloat32(6*a),s=0,l=0;l0&&((f=this.triShader).bind(),f.uniforms=s,this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind());this.edgeCount>0&&this.lineWidth>0&&((f=this.lineShader).bind(),f.uniforms=s,this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind());this.pointCount>0&&((f=this.pointShader).bind(),f.uniforms=s,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind());this.contourEnable&&this.contourCount>0&&this.contourLineWidth>0&&((f=this.contourShader).bind(),f.uniforms=s,this.contourVAO.bind(),e.drawArrays(e.LINES,0,this.contourCount),this.contourVAO.unbind())},x.drawPick=function(t){t=t||{};for(var e=this.gl,r=t.model||v,n=t.view||v,i=t.projection||v,a=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],o=0;o<3;++o)a[0][o]=Math.max(a[0][o],this.clipBounds[0][o]),a[1][o]=Math.min(a[1][o],this.clipBounds[1][o]);this._model=[].slice.call(r),this._view=[].slice.call(n),this._projection=[].slice.call(i),this._resolution=[e.drawingBufferWidth,e.drawingBufferHeight];var s,l={model:r,view:n,projection:i,clipBounds:a,tubeScale:this.tubeScale,pickId:this.pickId/255};((s=this.pickShader).bind(),s.uniforms=l,this.triangleCount>0&&(this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind()),this.edgeCount>0&&(this.edgeVAO.bind(),e.lineWidth(this.lineWidth),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind()),this.pointCount>0)&&((s=this.pointPickShader).bind(),s.uniforms=l,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind())},x.pick=function(t){if(!t)return null;if(t.id!==this.pickId)return null;var e=t.value[0]+256*t.value[1]+65536*t.value[2],r=this.cells[e],n=this.positions[r[1]].slice(0,3);return{index:e,position:n,intensity:this.intensity[r[1]],velocity:this.vectors[r[1]].slice(0,3),divergence:this.vectors[r[1]][3],dataCoordinate:n}},x.dispose=function(){this.texture.dispose(),this.triShader.dispose(),this.pickShader.dispose(),this.triangleVAO.dispose(),this.trianglePositions.dispose(),this.triangleVectors.dispose(),this.triangleColors.dispose(),this.triangleUVs.dispose(),this.triangleNormals.dispose(),this.triangleIds.dispose(),this.edgeVAO.dispose(),this.edgePositions.dispose(),this.edgeColors.dispose(),this.edgeUVs.dispose(),this.edgeIds.dispose(),this.pointVAO.dispose(),this.pointPositions.dispose(),this.pointColors.dispose(),this.pointUVs.dispose(),this.pointSizes.dispose(),this.pointIds.dispose(),this.contourVAO.dispose(),this.contourPositions.dispose()},e.exports=function(t,e){1===arguments.length&&(t=(e=t).gl);var r=e.triShader||function(t){var e=n(t,m.vertex,m.fragment,null,m.attributes);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e.attributes.vector.location=5,e}(t),s=b(t),l=o(t,u(new Uint8Array([255,255,255,255]),[1,1,4]));l.generateMipmap(),l.minFilter=t.LINEAR_MIPMAP_LINEAR,l.magFilter=t.LINEAR;var c=i(t),f=i(t),h=i(t),p=i(t),d=i(t),g=i(t),v=a(t,[{buffer:c,type:t.FLOAT,size:4},{buffer:g,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:h,type:t.FLOAT,size:4},{buffer:p,type:t.FLOAT,size:2},{buffer:d,type:t.FLOAT,size:3},{buffer:f,type:t.FLOAT,size:4}]),x=i(t),_=i(t),w=i(t),k=i(t),M=a(t,[{buffer:x,type:t.FLOAT,size:3},{buffer:k,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:_,type:t.FLOAT,size:4},{buffer:w,type:t.FLOAT,size:2}]),A=i(t),T=i(t),S=i(t),E=i(t),C=i(t),L=a(t,[{buffer:A,type:t.FLOAT,size:3},{buffer:C,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:T,type:t.FLOAT,size:4},{buffer:S,type:t.FLOAT,size:2},{buffer:E,type:t.FLOAT,size:1}]),z=i(t),O=new y(t,l,r,null,null,s,null,null,c,f,g,h,p,d,v,x,k,_,w,M,A,C,T,S,E,L,z,a(t,[{buffer:z,type:t.FLOAT,size:3}]));return O.update(e),O}},{"./closest-point":298,"./shaders":299,colormap:114,"gl-buffer":230,"gl-mat4/invert":254,"gl-mat4/multiply":256,"gl-shader":288,"gl-texture2d":305,"gl-vao":310,ndarray:433,normals:436,"simplicial-complex-contour":494,"typedarray-pool":522}],301:[function(t,e,r){"use strict";var n=t("gl-vec3"),i=t("gl-vec4"),a=function(t,e,r,a){for(var o=0,s=0;so&&(o=u)}var f=t.map(function(t){return function(t,e,r,a){var o,s,l,c=t.points,u=t.velocities,f=t.divergences;n.set(n.create(),0,1,0),n.create(),n.create();n.create();for(var h=[],p=[],d=[],m=[],g=[],v=[],y=0,x=0,b=i.create(),_=i.create(),w=0;w0)for(k=0;k<8;k++){var M=(k+1)%8;h.push(m[k],g[k],g[M],g[M],m[M],m[k]),d.push(_,b,b,b,_,_),v.push(y,x,x,x,y,y),p.push([h.length-6,h.length-5,h.length-4],[h.length-3,h.length-2,h.length-1])}var A=m;m=g,g=A,A=_,_=b,b=A,A=y,y=x,x=A}return{positions:h,cells:p,vectors:d,vertexIntensity:v}}(t,r,a,o)}),h=[],p=[],d=[],m=[];for(s=0;se)return r-1}return r},c=n.create(),u=n.create(),f=function(t,e,r){return tr?r:t},h=function(t,e,r,i){var a=t[0],o=t[1],s=t[2],h=r[0].length,p=r[1].length,d=r[2].length,m=l(r[0],a),g=l(r[1],o),v=l(r[2],s),y=m+1,x=g+1,b=v+1;if(r[0][m]===a&&(y=m),r[1][g]===o&&(x=g),r[2][v]===s&&(b=v),i&&(m=f(m,0,h-1),y=f(y,0,h-1),g=f(g,0,p-1),x=f(x,0,p-1),v=f(v,0,d-1),b=f(b,0,d-1)),m<0||g<0||v<0||y>=h||x>=p||b>=d)return n.create();var _=(a-r[0][m])/(r[0][y]-r[0][m]),w=(o-r[1][g])/(r[1][x]-r[1][g]),k=(s-r[2][v])/(r[2][b]-r[2][v]);(_<0||_>1||isNaN(_))&&(_=0),(w<0||w>1||isNaN(w))&&(w=0),(k<0||k>1||isNaN(k))&&(k=0);var M=v*h*p,A=b*h*p,T=g*h,S=x*h,E=m,C=y,L=e[T+M+E],z=e[T+M+C],O=e[S+M+E],I=e[S+M+C],P=e[T+A+E],D=e[T+A+C],R=e[S+A+E],B=e[S+A+C],F=n.create();return n.lerp(F,L,z,_),n.lerp(c,O,I,_),n.lerp(F,F,c,w),n.lerp(c,P,D,_),n.lerp(u,R,B,_),n.lerp(c,c,u,w),n.lerp(F,F,c,k),F},p=function(t){var e=1/0;t.sort(function(t,e){return t-e});for(var r=1;r=f&&r<=m&&n>=h&&n<=g&&i>=d&&i<=v},x=10*n.distance(e[0],e[1])/i,b=x*x,_=1,w=0;n.create();r.length>=2&&(_=function(t){for(var e=[],r=[],n=[],i={},a={},o={},s=0;sw&&!isNaN(P)&&isFinite(P)&&(w=P),C.push(P),u.push({points:A,velocities:T,divergences:C});for(var z=0;z<100*i&&A.lengthb&&n.scale(O,O,x/Math.sqrt(I)),n.add(O,O,M),S=t.getVelocity(O),n.squaredDistance(E,O)-b>-1e-4*b){A.push(O),E=O,T.push(S);L=t.getDivergence(O,S);(P=n.length(L))>w&&!isNaN(P)&&isFinite(P)&&(w=P),C.push(P)}M=O}}for(k=0;k max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 lowerBound, upperBound;\nuniform float contourTint;\nuniform vec4 contourColor;\nuniform sampler2D colormap;\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform float vertexColor;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec3 N = normalize(surfaceNormal);\n vec3 V = normalize(eyeDirection);\n vec3 L = normalize(lightDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = max(beckmannSpecular(L, V, N, roughness), 0.);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n //decide how to interpolate color \u2014 in vertex or in fragment\n vec4 surfaceColor = step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) + step(.5, vertexColor) * vColor;\n\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = mix(litColor, contourColor, contourTint) * opacity;\n}\n"]),s=i(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec4 uv;\nattribute float f;\n\nuniform mat3 permutation;\nuniform mat4 model, view, projection;\nuniform float height, zOffset;\nuniform sampler2D colormap;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n vec3 dataCoordinate = permutation * vec3(uv.xy, height);\n vec4 worldPosition = model * vec4(dataCoordinate, 1.0);\n\n vec4 clipPosition = projection * view * worldPosition;\n clipPosition.z = clipPosition.z + zOffset;\n\n gl_Position = clipPosition;\n value = f;\n kill = -1.0;\n worldCoordinate = dataCoordinate;\n planeCoordinate = uv.zw;\n\n vColor = texture2D(colormap, vec2(value, value));\n\n //Don't do lighting for contours\n surfaceNormal = vec3(1,0,0);\n eyeDirection = vec3(0,1,0);\n lightDirection = vec3(0,0,1);\n}\n"]),l=i(["precision mediump float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec2 shape;\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 surfaceNormal;\n\nvec2 splitFloat(float v) {\n float vh = 255.0 * v;\n float upper = floor(vh);\n float lower = fract(vh);\n return vec2(upper / 255.0, floor(lower * 16.0) / 16.0);\n}\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec2 ux = splitFloat(planeCoordinate.x / shape.x);\n vec2 uy = splitFloat(planeCoordinate.y / shape.y);\n gl_FragColor = vec4(pickId, ux.x, uy.x, ux.y + (uy.y/16.0));\n}\n"]);r.createShader=function(t){var e=n(t,a,o,null,[{name:"uv",type:"vec4"},{name:"f",type:"vec3"},{name:"normal",type:"vec3"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e.attributes.normal.location=2,e},r.createPickShader=function(t){var e=n(t,a,l,null,[{name:"uv",type:"vec4"},{name:"f",type:"vec3"},{name:"normal",type:"vec3"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e.attributes.normal.location=2,e},r.createContourShader=function(t){var e=n(t,s,o,null,[{name:"uv",type:"vec4"},{name:"f",type:"float"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e},r.createPickContourShader=function(t){var e=n(t,s,l,null,[{name:"uv",type:"vec4"},{name:"f",type:"float"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e}},{"gl-shader":288,glslify:392}],303:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl,r=y(e),n=b(e),s=x(e),l=_(e),c=i(e),u=a(e,[{buffer:c,size:4,stride:w,offset:0},{buffer:c,size:3,stride:w,offset:16},{buffer:c,size:3,stride:w,offset:28}]),f=i(e),h=a(e,[{buffer:f,size:4,stride:20,offset:0},{buffer:f,size:1,stride:20,offset:16}]),p=i(e),d=a(e,[{buffer:p,size:2,type:e.FLOAT}]),m=o(e,1,S,e.RGBA,e.UNSIGNED_BYTE);m.minFilter=e.LINEAR,m.magFilter=e.LINEAR;var g=new E(e,[0,0],[[0,0,0],[0,0,0]],r,n,c,u,m,s,l,f,h,p,d),v={levels:[[],[],[]]};for(var k in t)v[k]=t[k];return v.colormap=v.colormap||"jet",g.update(v),g};var n=t("bit-twiddle"),i=t("gl-buffer"),a=t("gl-vao"),o=t("gl-texture2d"),s=t("typedarray-pool"),l=t("colormap"),c=t("ndarray-ops"),u=t("ndarray-pack"),f=t("ndarray"),h=t("surface-nets"),p=t("gl-mat4/multiply"),d=t("gl-mat4/invert"),m=t("binary-search-bounds"),g=t("ndarray-gradient"),v=t("./lib/shaders"),y=v.createShader,x=v.createContourShader,b=v.createPickShader,_=v.createPickContourShader,w=40,k=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],M=[[0,0],[0,1],[1,0],[1,1],[1,0],[0,1]],A=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];function T(t,e,r,n,i){this.position=t,this.index=e,this.uv=r,this.level=n,this.dataCoordinate=i}!function(){for(var t=0;t<3;++t){var e=A[t],r=(t+2)%3;e[(t+1)%3+0]=1,e[r+3]=1,e[t+6]=1}}();var S=256;function E(t,e,r,n,i,a,o,l,c,u,h,p,d,m){this.gl=t,this.shape=e,this.bounds=r,this.intensityBounds=[],this._shader=n,this._pickShader=i,this._coordinateBuffer=a,this._vao=o,this._colorMap=l,this._contourShader=c,this._contourPickShader=u,this._contourBuffer=h,this._contourVAO=p,this._contourOffsets=[[],[],[]],this._contourCounts=[[],[],[]],this._vertexCount=0,this._pickResult=new T([0,0,0],[0,0],[0,0],[0,0,0],[0,0,0]),this._dynamicBuffer=d,this._dynamicVAO=m,this._dynamicOffsets=[0,0,0],this._dynamicCounts=[0,0,0],this.contourWidth=[1,1,1],this.contourLevels=[[1],[1],[1]],this.contourTint=[0,0,0],this.contourColor=[[.5,.5,.5,1],[.5,.5,.5,1],[.5,.5,.5,1]],this.showContour=!0,this.showSurface=!0,this.enableHighlight=[!0,!0,!0],this.highlightColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.highlightTint=[1,1,1],this.highlightLevel=[-1,-1,-1],this.enableDynamic=[!0,!0,!0],this.dynamicLevel=[NaN,NaN,NaN],this.dynamicColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.dynamicTint=[1,1,1],this.dynamicWidth=[1,1,1],this.axesBounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.surfaceProject=[!1,!1,!1],this.contourProject=[[!1,!1,!1],[!1,!1,!1],[!1,!1,!1]],this.colorBounds=[!1,!1],this._field=[f(s.mallocFloat(1024),[0,0]),f(s.mallocFloat(1024),[0,0]),f(s.mallocFloat(1024),[0,0])],this.pickId=1,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.snapToData=!1,this.opacity=1,this.lightPosition=[10,1e4,0],this.ambientLight=.8,this.diffuseLight=.8,this.specularLight=2,this.roughness=.5,this.fresnel=1.5,this.vertexColor=0,this.dirty=!0}var C=E.prototype;C.isTransparent=function(){return this.opacity<1},C.isOpaque=function(){if(this.opacity>=1)return!0;for(var t=0;t<3;++t)if(this._contourCounts[t].length>0||this._dynamicCounts[t]>0)return!0;return!1},C.pickSlots=1,C.setPickBase=function(t){this.pickId=t};var L=[0,0,0],z={showSurface:!1,showContour:!1,projections:[k.slice(),k.slice(),k.slice()],clipBounds:[[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]]]};function O(t,e){var r,n,i,a=e.axes&&e.axes.lastCubeProps.axis||L,o=e.showSurface,s=e.showContour;for(r=0;r<3;++r)for(o=o||e.surfaceProject[r],n=0;n<3;++n)s=s||e.contourProject[r][n];for(r=0;r<3;++r){var l=z.projections[r];for(n=0;n<16;++n)l[n]=0;for(n=0;n<4;++n)l[5*n]=1;l[5*r]=0,l[12+r]=e.axesBounds[+(a[r]>0)][r],p(l,t.model,l);var c=z.clipBounds[r];for(i=0;i<2;++i)for(n=0;n<3;++n)c[i][n]=t.clipBounds[i][n];c[0][r]=-1e8,c[1][r]=1e8}return z.showSurface=o,z.showContour=s,z}var I={model:k,view:k,projection:k,inverseModel:k.slice(),lowerBound:[0,0,0],upperBound:[0,0,0],colorMap:0,clipBounds:[[0,0,0],[0,0,0]],height:0,contourTint:0,contourColor:[0,0,0,1],permutation:[1,0,0,0,1,0,0,0,1],zOffset:-1e-4,kambient:1,kdiffuse:1,kspecular:1,lightPosition:[1e3,1e3,1e3],eyePosition:[0,0,0],roughness:1,fresnel:1,opacity:1,vertexColor:0},P=k.slice(),D=[1,0,0,0,1,0,0,0,1];function R(t,e){t=t||{};var r=this.gl;r.disable(r.CULL_FACE),this._colorMap.bind(0);var n=I;n.model=t.model||k,n.view=t.view||k,n.projection=t.projection||k,n.lowerBound=[this.bounds[0][0],this.bounds[0][1],this.colorBounds[0]||this.bounds[0][2]],n.upperBound=[this.bounds[1][0],this.bounds[1][1],this.colorBounds[1]||this.bounds[1][2]],n.contourColor=this.contourColor[0],n.inverseModel=d(n.inverseModel,n.model);for(var i=0;i<2;++i)for(var a=n.clipBounds[i],o=0;o<3;++o)a[o]=Math.min(Math.max(this.clipBounds[i][o],-1e8),1e8);n.kambient=this.ambientLight,n.kdiffuse=this.diffuseLight,n.kspecular=this.specularLight,n.roughness=this.roughness,n.fresnel=this.fresnel,n.opacity=this.opacity,n.height=0,n.permutation=D,n.vertexColor=this.vertexColor;var s=P;for(p(s,n.view,n.model),p(s,n.projection,s),d(s,s),i=0;i<3;++i)n.eyePosition[i]=s[12+i]/s[15];var l=s[15];for(i=0;i<3;++i)l+=this.lightPosition[i]*s[4*i+3];for(i=0;i<3;++i){var c=s[12+i];for(o=0;o<3;++o)c+=s[4*o+i]*this.lightPosition[o];n.lightPosition[i]=c/l}var u=O(n,this);if(u.showSurface&&e===this.opacity<1){for(this._shader.bind(),this._shader.uniforms=n,this._vao.bind(),this.showSurface&&this._vertexCount&&this._vao.draw(r.TRIANGLES,this._vertexCount),i=0;i<3;++i)this.surfaceProject[i]&&this.vertexCount&&(this._shader.uniforms.model=u.projections[i],this._shader.uniforms.clipBounds=u.clipBounds[i],this._vao.draw(r.TRIANGLES,this._vertexCount));this._vao.unbind()}if(u.showContour&&!e){var f=this._contourShader;n.kambient=1,n.kdiffuse=0,n.kspecular=0,n.opacity=1,f.bind(),f.uniforms=n;var h=this._contourVAO;for(h.bind(),i=0;i<3;++i)for(f.uniforms.permutation=A[i],r.lineWidth(this.contourWidth[i]),o=0;o>4)/16)/255,i=Math.floor(n),a=n-i,o=e[1]*(t.value[1]+(15&t.value[2])/16)/255,s=Math.floor(o),l=o-s;i+=1,s+=1;var c=r.position;c[0]=c[1]=c[2]=0;for(var u=0;u<2;++u)for(var f=u?a:1-a,h=0;h<2;++h)for(var p=i+u,d=s+h,g=f*(h?l:1-l),v=0;v<3;++v)c[v]+=this._field[v].get(p,d)*g;for(var y=this._pickResult.level,x=0;x<3;++x)if(y[x]=m.le(this.contourLevels[x],c[x]),y[x]<0)this.contourLevels[x].length>0&&(y[x]=0);else if(y[x]Math.abs(_-c[x])&&(y[x]+=1)}for(r.index[0]=a<.5?i:i+1,r.index[1]=l<.5?s:s+1,r.uv[0]=n/e[0],r.uv[1]=o/e[1],v=0;v<3;++v)r.dataCoordinate[v]=this._field[v].get(r.index[0],r.index[1]);return r},C.update=function(t){t=t||{},this.dirty=!0,"contourWidth"in t&&(this.contourWidth=N(t.contourWidth,Number)),"showContour"in t&&(this.showContour=N(t.showContour,Boolean)),"showSurface"in t&&(this.showSurface=!!t.showSurface),"contourTint"in t&&(this.contourTint=N(t.contourTint,Boolean)),"contourColor"in t&&(this.contourColor=V(t.contourColor)),"contourProject"in t&&(this.contourProject=N(t.contourProject,function(t){return N(t,Boolean)})),"surfaceProject"in t&&(this.surfaceProject=t.surfaceProject),"dynamicColor"in t&&(this.dynamicColor=V(t.dynamicColor)),"dynamicTint"in t&&(this.dynamicTint=N(t.dynamicTint,Number)),"dynamicWidth"in t&&(this.dynamicWidth=N(t.dynamicWidth,Number)),"opacity"in t&&(this.opacity=t.opacity),"colorBounds"in t&&(this.colorBounds=t.colorBounds),"vertexColor"in t&&(this.vertexColor=t.vertexColor?1:0);var e=t.field||t.coords&&t.coords[2]||null,r=!1;if(e||(e=this._field[2].shape[0]||this._field[2].shape[2]?this._field[2].lo(1,1).hi(this._field[2].shape[0]-2,this._field[2].shape[1]-2):this._field[2].hi(0,0)),"field"in t||"coords"in t){var i=(e.shape[0]+2)*(e.shape[1]+2);i>this._field[2].data.length&&(s.freeFloat(this._field[2].data),this._field[2].data=s.mallocFloat(n.nextPow2(i))),this._field[2]=f(this._field[2].data,[e.shape[0]+2,e.shape[1]+2]),F(this._field[2],e),this.shape=e.shape.slice();for(var a=this.shape,o=0;o<2;++o)this._field[2].size>this._field[o].data.length&&(s.freeFloat(this._field[o].data),this._field[o].data=s.mallocFloat(this._field[2].size)),this._field[o]=f(this._field[o].data,[a[0]+2,a[1]+2]);if(t.coords){var p=t.coords;if(!Array.isArray(p)||3!==p.length)throw new Error("gl-surface: invalid coordinates for x/y");for(o=0;o<2;++o){var d=p[o];for(b=0;b<2;++b)if(d.shape[b]!==a[b])throw new Error("gl-surface: coords have incorrect shape");F(this._field[o],d)}}else if(t.ticks){var m=t.ticks;if(!Array.isArray(m)||2!==m.length)throw new Error("gl-surface: invalid ticks");for(o=0;o<2;++o){var v=m[o];if((Array.isArray(v)||v.length)&&(v=f(v)),v.shape[0]!==a[o])throw new Error("gl-surface: invalid tick length");var y=f(v.data,a);y.stride[o]=v.stride[0],y.stride[1^o]=0,F(this._field[o],y)}}else{for(o=0;o<2;++o){var x=[0,0];x[o]=1,this._field[o]=f(this._field[o].data,[a[0]+2,a[1]+2],x,0)}this._field[0].set(0,0,0);for(var b=0;b0){for(var kt=0;kt<5;++kt)nt.pop();W-=1}continue t}nt.push(st[0],st[1],ut[0],ut[1],st[2]),W+=1}}ot.push(W)}this._contourOffsets[it]=at,this._contourCounts[it]=ot}var Mt=s.mallocFloat(nt.length);for(o=0;o halfCharStep + halfCharWidth ||\n\t\t\t\t\tfloor(uv.x) < halfCharStep - halfCharWidth) return;\n\n\t\t\t\tuv += charId * charStep;\n\t\t\t\tuv = uv / atlasSize;\n\n\t\t\t\tvec4 color = fontColor;\n\t\t\t\tvec4 mask = texture2D(atlas, uv);\n\n\t\t\t\tfloat maskY = lightness(mask);\n\t\t\t\t// float colorY = lightness(color);\n\t\t\t\tcolor.a *= maskY;\n\t\t\t\tcolor.a *= opacity;\n\n\t\t\t\t// color.a += .1;\n\n\t\t\t\t// antialiasing, see yiq color space y-channel formula\n\t\t\t\t// color.rgb += (1. - color.rgb) * (1. - mask.rgb);\n\n\t\t\t\tgl_FragColor = color;\n\t\t\t}"});return{regl:t,draw:e,atlas:{}}},k.prototype.update=function(t){var e=this;if("string"==typeof t)t={text:t};else if(!t)return;null!=(t=i(t,{position:"position positions coord coords coordinates",font:"font fontFace fontface typeface cssFont css-font family fontFamily",fontSize:"fontSize fontsize size font-size",text:"text texts chars characters value values symbols",align:"align alignment textAlign textbaseline",baseline:"baseline textBaseline textbaseline",direction:"dir direction textDirection",color:"color colour fill fill-color fillColor textColor textcolor",kerning:"kerning kern",range:"range dataBox",viewport:"vp viewport viewBox viewbox viewPort",opacity:"opacity alpha transparency visible visibility opaque",offset:"offset positionOffset padding shift indent indentation"},!0)).opacity&&(Array.isArray(t.opacity)?this.opacity=t.opacity.map(function(t){return parseFloat(t)}):this.opacity=parseFloat(t.opacity)),null!=t.viewport&&(this.viewport=f(t.viewport),k.normalViewport&&(this.viewport.y=this.canvas.height-this.viewport.y-this.viewport.height),this.viewportArray=[this.viewport.x,this.viewport.y,this.viewport.width,this.viewport.height]),null==this.viewport&&(this.viewport={x:0,y:0,width:this.gl.drawingBufferWidth,height:this.gl.drawingBufferHeight},this.viewportArray=[this.viewport.x,this.viewport.y,this.viewport.width,this.viewport.height]),null!=t.kerning&&(this.kerning=t.kerning),null!=t.offset&&("number"==typeof t.offset&&(t.offset=[t.offset,0]),this.positionOffset=y(t.offset)),t.direction&&(this.direction=t.direction),t.range&&(this.range=t.range,this.scale=[1/(t.range[2]-t.range[0]),1/(t.range[3]-t.range[1])],this.translate=[-t.range[0],-t.range[1]]),t.scale&&(this.scale=t.scale),t.translate&&(this.translate=t.translate),this.scale||(this.scale=[1/this.viewport.width,1/this.viewport.height]),this.translate||(this.translate=[0,0]),this.font.length||t.font||(t.font=k.baseFontSize+"px sans-serif");var r,a=!1,o=!1;if(t.font&&(Array.isArray(t.font)?t.font:[t.font]).forEach(function(t,r){if("string"==typeof t)try{t=n.parse(t)}catch(e){t=n.parse(k.baseFontSize+"px "+t)}else t=n.parse(n.stringify(t));var i=n.stringify({size:k.baseFontSize,family:t.family,stretch:_?t.stretch:void 0,variant:t.variant,weight:t.weight,style:t.style}),s=p(t.size),l=Math.round(s[0]*d(s[1]));if(l!==e.fontSize[r]&&(o=!0,e.fontSize[r]=l),!(e.font[r]&&i==e.font[r].baseString||(a=!0,e.font[r]=k.fonts[i],e.font[r]))){var c=t.family.join(", "),u=[t.style];t.style!=t.variant&&u.push(t.variant),t.variant!=t.weight&&u.push(t.weight),_&&t.weight!=t.stretch&&u.push(t.stretch),e.font[r]={baseString:i,family:c,weight:t.weight,stretch:t.stretch,style:t.style,variant:t.variant,width:{},kerning:{},metrics:v(c,{origin:"top",fontSize:k.baseFontSize,fontStyle:u.join(" ")})},k.fonts[i]=e.font[r]}}),(a||o)&&this.font.forEach(function(r,i){var a=n.stringify({size:e.fontSize[i],family:r.family,stretch:_?r.stretch:void 0,variant:r.variant,weight:r.weight,style:r.style});if(e.fontAtlas[i]=e.shader.atlas[a],!e.fontAtlas[i]){var o=r.metrics;e.shader.atlas[a]=e.fontAtlas[i]={fontString:a,step:2*Math.ceil(e.fontSize[i]*o.bottom*.5),em:e.fontSize[i],cols:0,rows:0,height:0,width:0,chars:[],ids:{},texture:e.regl.texture()}}null==t.text&&(t.text=e.text)}),"string"==typeof t.text&&t.position&&t.position.length>2){for(var s=Array(.5*t.position.length),h=0;h2){for(var w=!t.position[0].length,M=u.mallocFloat(2*this.count),A=0,T=0;A1?e.align[r]:e.align[0]:e.align;if("number"==typeof n)return n;switch(n){case"right":case"end":return-t;case"center":case"centre":case"middle":return.5*-t}return 0})),null==this.baseline&&null==t.baseline&&(t.baseline=0),null!=t.baseline&&(this.baseline=t.baseline,Array.isArray(this.baseline)||(this.baseline=[this.baseline]),this.baselineOffset=this.baseline.map(function(t,r){var n=(e.font[r]||e.font[0]).metrics,i=0;return i+=.5*n.bottom,i+="number"==typeof t?t-n.baseline:-n[t],k.normalViewport||(i*=-1),i})),null!=t.color)if(t.color||(t.color="transparent"),"string"!=typeof t.color&&isNaN(t.color)){var H;if("number"==typeof t.color[0]&&t.color.length>this.counts.length){var G=t.color.length;H=u.mallocUint8(G);for(var W=(t.color.subarray||t.color.slice).bind(t.color),Y=0;Y4||this.baselineOffset.length>1||this.align&&this.align.length>1||this.fontAtlas.length>1||this.positionOffset.length>2){var $=Math.max(.5*this.position.length||0,.25*this.color.length||0,this.baselineOffset.length||0,this.alignOffset.length||0,this.font.length||0,this.opacity.length||0,.5*this.positionOffset.length||0);this.batch=Array($);for(var J=0;J1?e.counts[J]:e.counts[0],offset:e.textOffsets.length>1?e.textOffsets[J]:e.textOffsets[0],color:e.color?e.color.length<=4?e.color:e.color.subarray(4*J,4*J+4):[0,0,0,255],opacity:Array.isArray(e.opacity)?e.opacity[J]:e.opacity,baseline:null!=e.baselineOffset[J]?e.baselineOffset[J]:e.baselineOffset[0],align:e.align?null!=e.alignOffset[J]?e.alignOffset[J]:e.alignOffset[0]:0,atlas:e.fontAtlas[J]||e.fontAtlas[0],positionOffset:e.positionOffset.length>2?e.positionOffset.subarray(2*J,2*J+2):e.positionOffset}}else this.count?this.batch=[{count:this.count,offset:0,color:this.color||[0,0,0,255],opacity:Array.isArray(this.opacity)?this.opacity[0]:this.opacity,baseline:this.baselineOffset[0],align:this.alignOffset?this.alignOffset[0]:0,atlas:this.fontAtlas[0],positionOffset:this.positionOffset}]:this.batch=[]},k.prototype.destroy=function(){},k.prototype.kerning=!0,k.prototype.position={constant:new Float32Array(2)},k.prototype.translate=null,k.prototype.scale=null,k.prototype.font=null,k.prototype.text="",k.prototype.positionOffset=[0,0],k.prototype.opacity=1,k.prototype.color=new Uint8Array([0,0,0,255]),k.prototype.alignOffset=[0,0],k.normalViewport=!1,k.maxAtlasSize=1024,k.atlasCanvas=document.createElement("canvas"),k.atlasContext=k.atlasCanvas.getContext("2d",{alpha:!1}),k.baseFontSize=64,k.fonts={},e.exports=k},{"bit-twiddle":80,"color-normalize":108,"css-font":127,"detect-kerning":151,"es6-weak-map":209,"flatten-vertex-data":216,"font-atlas":217,"font-measure":218,"gl-util/context":306,"is-plain-obj":405,"object-assign":437,"parse-rect":442,"parse-unit":444,"pick-by-alias":448,regl:478,"to-px":516,"typedarray-pool":522}],305:[function(t,e,r){"use strict";var n=t("ndarray"),i=t("ndarray-ops"),a=t("typedarray-pool");e.exports=function(t){if(arguments.length<=1)throw new Error("gl-texture2d: Missing arguments for texture2d constructor");o||function(t){o=[t.LINEAR,t.NEAREST_MIPMAP_LINEAR,t.LINEAR_MIPMAP_NEAREST,t.LINEAR_MIPMAP_NEAREST],s=[t.NEAREST,t.LINEAR,t.NEAREST_MIPMAP_NEAREST,t.NEAREST_MIPMAP_LINEAR,t.LINEAR_MIPMAP_NEAREST,t.LINEAR_MIPMAP_LINEAR],l=[t.REPEAT,t.CLAMP_TO_EDGE,t.MIRRORED_REPEAT]}(t);if("number"==typeof arguments[1])return g(t,arguments[1],arguments[2],arguments[3]||t.RGBA,arguments[4]||t.UNSIGNED_BYTE);if(Array.isArray(arguments[1]))return g(t,0|arguments[1][0],0|arguments[1][1],arguments[2]||t.RGBA,arguments[3]||t.UNSIGNED_BYTE);if("object"==typeof arguments[1]){var e=arguments[1],r=c(e)?e:e.raw;if(r)return function(t,e,r,n,i,a){var o=m(t);return t.texImage2D(t.TEXTURE_2D,0,i,i,a,e),new h(t,o,r,n,i,a)}(t,r,0|e.width,0|e.height,arguments[2]||t.RGBA,arguments[3]||t.UNSIGNED_BYTE);if(e.shape&&e.data&&e.stride)return function(t,e){var r=e.dtype,o=e.shape.slice(),s=t.getParameter(t.MAX_TEXTURE_SIZE);if(o[0]<0||o[0]>s||o[1]<0||o[1]>s)throw new Error("gl-texture2d: Invalid texture size");var l=d(o,e.stride.slice()),c=0;"float32"===r?c=t.FLOAT:"float64"===r?(c=t.FLOAT,l=!1,r="float32"):"uint8"===r?c=t.UNSIGNED_BYTE:(c=t.UNSIGNED_BYTE,l=!1,r="uint8");var f,p,g=0;if(2===o.length)g=t.LUMINANCE,o=[o[0],o[1],1],e=n(e.data,o,[e.stride[0],e.stride[1],1],e.offset);else{if(3!==o.length)throw new Error("gl-texture2d: Invalid shape for texture");if(1===o[2])g=t.ALPHA;else if(2===o[2])g=t.LUMINANCE_ALPHA;else if(3===o[2])g=t.RGB;else{if(4!==o[2])throw new Error("gl-texture2d: Invalid shape for pixel coords");g=t.RGBA}}c!==t.FLOAT||t.getExtension("OES_texture_float")||(c=t.UNSIGNED_BYTE,l=!1);var v=e.size;if(l)f=0===e.offset&&e.data.length===v?e.data:e.data.subarray(e.offset,e.offset+v);else{var y=[o[2],o[2]*o[0],1];p=a.malloc(v,r);var x=n(p,o,y,0);"float32"!==r&&"float64"!==r||c!==t.UNSIGNED_BYTE?i.assign(x,e):u(x,e),f=p.subarray(0,v)}var b=m(t);t.texImage2D(t.TEXTURE_2D,0,g,o[0],o[1],0,g,c,f),l||a.free(p);return new h(t,b,o[0],o[1],g,c)}(t,e)}throw new Error("gl-texture2d: Invalid arguments for texture2d constructor")};var o=null,s=null,l=null;function c(t){return"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLVideoElement&&t instanceof HTMLVideoElement||"undefined"!=typeof ImageData&&t instanceof ImageData}var u=function(t,e){i.muls(t,e,255)};function f(t,e,r){var n=t.gl,i=n.getParameter(n.MAX_TEXTURE_SIZE);if(e<0||e>i||r<0||r>i)throw new Error("gl-texture2d: Invalid texture size");return t._shape=[e,r],t.bind(),n.texImage2D(n.TEXTURE_2D,0,t.format,e,r,0,t.format,t.type,null),t._mipLevels=[0],t}function h(t,e,r,n,i,a){this.gl=t,this.handle=e,this.format=i,this.type=a,this._shape=[r,n],this._mipLevels=[0],this._magFilter=t.NEAREST,this._minFilter=t.NEAREST,this._wrapS=t.CLAMP_TO_EDGE,this._wrapT=t.CLAMP_TO_EDGE,this._anisoSamples=1;var o=this,s=[this._wrapS,this._wrapT];Object.defineProperties(s,[{get:function(){return o._wrapS},set:function(t){return o.wrapS=t}},{get:function(){return o._wrapT},set:function(t){return o.wrapT=t}}]),this._wrapVector=s;var l=[this._shape[0],this._shape[1]];Object.defineProperties(l,[{get:function(){return o._shape[0]},set:function(t){return o.width=t}},{get:function(){return o._shape[1]},set:function(t){return o.height=t}}]),this._shapeVector=l}var p=h.prototype;function d(t,e){return 3===t.length?1===e[2]&&e[1]===t[0]*t[2]&&e[0]===t[2]:1===e[0]&&e[1]===t[0]}function m(t){var e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),e}function g(t,e,r,n,i){var a=t.getParameter(t.MAX_TEXTURE_SIZE);if(e<0||e>a||r<0||r>a)throw new Error("gl-texture2d: Invalid texture shape");if(i===t.FLOAT&&!t.getExtension("OES_texture_float"))throw new Error("gl-texture2d: Floating point textures not supported on this platform");var o=m(t);return t.texImage2D(t.TEXTURE_2D,0,n,e,r,0,n,i,null),new h(t,o,e,r,n,i)}Object.defineProperties(p,{minFilter:{get:function(){return this._minFilter},set:function(t){this.bind();var e=this.gl;if(this.type===e.FLOAT&&o.indexOf(t)>=0&&(e.getExtension("OES_texture_float_linear")||(t=e.NEAREST)),s.indexOf(t)<0)throw new Error("gl-texture2d: Unknown filter mode "+t);return e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t),this._minFilter=t}},magFilter:{get:function(){return this._magFilter},set:function(t){this.bind();var e=this.gl;if(this.type===e.FLOAT&&o.indexOf(t)>=0&&(e.getExtension("OES_texture_float_linear")||(t=e.NEAREST)),s.indexOf(t)<0)throw new Error("gl-texture2d: Unknown filter mode "+t);return e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t),this._magFilter=t}},mipSamples:{get:function(){return this._anisoSamples},set:function(t){var e=this._anisoSamples;if(this._anisoSamples=0|Math.max(t,1),e!==this._anisoSamples){var r=this.gl.getExtension("EXT_texture_filter_anisotropic");r&&this.gl.texParameterf(this.gl.TEXTURE_2D,r.TEXTURE_MAX_ANISOTROPY_EXT,this._anisoSamples)}return this._anisoSamples}},wrapS:{get:function(){return this._wrapS},set:function(t){if(this.bind(),l.indexOf(t)<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);return this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,t),this._wrapS=t}},wrapT:{get:function(){return this._wrapT},set:function(t){if(this.bind(),l.indexOf(t)<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);return this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,t),this._wrapT=t}},wrap:{get:function(){return this._wrapVector},set:function(t){if(Array.isArray(t)||(t=[t,t]),2!==t.length)throw new Error("gl-texture2d: Must specify wrap mode for rows and columns");for(var e=0;e<2;++e)if(l.indexOf(t[e])<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);this._wrapS=t[0],this._wrapT=t[1];var r=this.gl;return this.bind(),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,this._wrapS),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,this._wrapT),t}},shape:{get:function(){return this._shapeVector},set:function(t){if(Array.isArray(t)){if(2!==t.length)throw new Error("gl-texture2d: Invalid texture shape")}else t=[0|t,0|t];return f(this,0|t[0],0|t[1]),[0|t[0],0|t[1]]}},width:{get:function(){return this._shape[0]},set:function(t){return f(this,t|=0,this._shape[1]),t}},height:{get:function(){return this._shape[1]},set:function(t){return t|=0,f(this,this._shape[0],t),t}}}),p.bind=function(t){var e=this.gl;return void 0!==t&&e.activeTexture(e.TEXTURE0+(0|t)),e.bindTexture(e.TEXTURE_2D,this.handle),void 0!==t?0|t:e.getParameter(e.ACTIVE_TEXTURE)-e.TEXTURE0},p.dispose=function(){this.gl.deleteTexture(this.handle)},p.generateMipmap=function(){this.bind(),this.gl.generateMipmap(this.gl.TEXTURE_2D);for(var t=Math.min(this._shape[0],this._shape[1]),e=0;t>0;++e,t>>>=1)this._mipLevels.indexOf(e)<0&&this._mipLevels.push(e)},p.setPixels=function(t,e,r,o){var s=this.gl;this.bind(),Array.isArray(e)?(o=r,r=0|e[1],e=0|e[0]):(e=e||0,r=r||0),o=o||0;var l=c(t)?t:t.raw;if(l){this._mipLevels.indexOf(o)<0?(s.texImage2D(s.TEXTURE_2D,0,this.format,this.format,this.type,l),this._mipLevels.push(o)):s.texSubImage2D(s.TEXTURE_2D,o,e,r,this.format,this.type,l)}else{if(!(t.shape&&t.stride&&t.data))throw new Error("gl-texture2d: Unsupported data type");if(t.shape.length<2||e+t.shape[1]>this._shape[1]>>>o||r+t.shape[0]>this._shape[0]>>>o||e<0||r<0)throw new Error("gl-texture2d: Texture dimensions are out of bounds");!function(t,e,r,o,s,l,c,f){var h=f.dtype,p=f.shape.slice();if(p.length<2||p.length>3)throw new Error("gl-texture2d: Invalid ndarray, must be 2d or 3d");var m=0,g=0,v=d(p,f.stride.slice());"float32"===h?m=t.FLOAT:"float64"===h?(m=t.FLOAT,v=!1,h="float32"):"uint8"===h?m=t.UNSIGNED_BYTE:(m=t.UNSIGNED_BYTE,v=!1,h="uint8");if(2===p.length)g=t.LUMINANCE,p=[p[0],p[1],1],f=n(f.data,p,[f.stride[0],f.stride[1],1],f.offset);else{if(3!==p.length)throw new Error("gl-texture2d: Invalid shape for texture");if(1===p[2])g=t.ALPHA;else if(2===p[2])g=t.LUMINANCE_ALPHA;else if(3===p[2])g=t.RGB;else{if(4!==p[2])throw new Error("gl-texture2d: Invalid shape for pixel coords");g=t.RGBA}p[2]}g!==t.LUMINANCE&&g!==t.ALPHA||s!==t.LUMINANCE&&s!==t.ALPHA||(g=s);if(g!==s)throw new Error("gl-texture2d: Incompatible texture format for setPixels");var y=f.size,x=c.indexOf(o)<0;x&&c.push(o);if(m===l&&v)0===f.offset&&f.data.length===y?x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,f.data):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,f.data):x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,f.data.subarray(f.offset,f.offset+y)):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,f.data.subarray(f.offset,f.offset+y));else{var b;b=l===t.FLOAT?a.mallocFloat32(y):a.mallocUint8(y);var _=n(b,p,[p[2],p[2]*p[0],1]);m===t.FLOAT&&l===t.UNSIGNED_BYTE?u(_,f):i.assign(_,f),x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,b.subarray(0,y)):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,b.subarray(0,y)),l===t.FLOAT?a.freeFloat32(b):a.freeUint8(b)}}(s,e,r,o,this.format,this.type,this._mipLevels,t)}}},{ndarray:433,"ndarray-ops":427,"typedarray-pool":522}],306:[function(t,e,r){"use strict";var n=t("pick-by-alias");function i(t){if(t.container)if(t.container==document.body)document.body.style.width||(t.canvas.width=t.width||t.pixelRatio*window.innerWidth),document.body.style.height||(t.canvas.height=t.height||t.pixelRatio*window.innerHeight);else{var e=t.container.getBoundingClientRect();t.canvas.width=t.width||e.right-e.left,t.canvas.height=t.height||e.bottom-e.top}}function a(t){return"function"==typeof t.getContext&&"width"in t&&"height"in t}e.exports=function(t){var e;if(t?"string"==typeof t&&(t={container:t}):t={},a(t)?t={container:t}:t="string"==typeof(e=t).nodeName&&"function"==typeof e.appendChild&&"function"==typeof e.getBoundingClientRect?{container:t}:function(t){return"function"==typeof t.drawArrays||"function"==typeof t.drawElements}(t)?{gl:t}:n(t,{container:"container target element el canvas holder parent parentNode wrapper use ref root node",gl:"gl context webgl glContext",attrs:"attributes attrs contextAttributes",pixelRatio:"pixelRatio pxRatio px ratio pxratio pixelratio"},!0),t.pixelRatio||(t.pixelRatio=window.pixelRatio||1),t.gl)return t.gl;if(t.canvas&&(t.container=t.canvas.parentNode),t.container){if("string"==typeof t.container){var r=document.querySelector(t.container);if(!r)throw Error("Element "+t.container+" is not found");t.container=r}a(t.container)?(t.canvas=t.container,t.container=t.canvas.parentNode):t.canvas||(t.canvas=document.createElement("canvas"),t.container.appendChild(t.canvas),i(t))}else t.canvas||(t.container=document.body||document.documentElement,t.canvas=document.createElement("canvas"),t.canvas.style.position="absolute",t.canvas.style.top=0,t.canvas.style.left=0,t.container.appendChild(t.canvas),i(t));if(!t.gl)try{t.gl=t.canvas.getContext("webgl",t.attrs)}catch(e){try{t.gl=t.canvas.getContext("experimental-webgl",t.attrs)}catch(e){t.gl=t.canvas.getContext("webgl-experimental",t.attrs)}}return t.gl}},{"pick-by-alias":448}],307:[function(t,e,r){"use strict";e.exports=function(t,e,r){e?e.bind():t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null);var n=0|t.getParameter(t.MAX_VERTEX_ATTRIBS);if(r){if(r.length>n)throw new Error("gl-vao: Too many vertex attributes");for(var i=0;i1?0:Math.acos(s)};var n=t("./fromValues"),i=t("./normalize"),a=t("./dot")},{"./dot":322,"./fromValues":328,"./normalize":339}],313:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2]),t}},{}],314:[function(t,e,r){e.exports=function(t){var e=new Float32Array(3);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e}},{}],315:[function(t,e,r){e.exports=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}},{}],316:[function(t,e,r){e.exports=function(){var t=new Float32Array(3);return t[0]=0,t[1]=0,t[2]=0,t}},{}],317:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2];return t[0]=i*l-a*s,t[1]=a*o-n*l,t[2]=n*s-i*o,t}},{}],318:[function(t,e,r){e.exports=t("./distance")},{"./distance":319}],319:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2];return Math.sqrt(r*r+n*n+i*i)}},{}],320:[function(t,e,r){e.exports=t("./divide")},{"./divide":321}],321:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]/r[0],t[1]=e[1]/r[1],t[2]=e[2]/r[2],t}},{}],322:[function(t,e,r){e.exports=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}},{}],323:[function(t,e,r){e.exports=1e-6},{}],324:[function(t,e,r){e.exports=function(t,e){var r=t[0],i=t[1],a=t[2],o=e[0],s=e[1],l=e[2];return Math.abs(r-o)<=n*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(i-s)<=n*Math.max(1,Math.abs(i),Math.abs(s))&&Math.abs(a-l)<=n*Math.max(1,Math.abs(a),Math.abs(l))};var n=t("./epsilon")},{"./epsilon":323}],325:[function(t,e,r){e.exports=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]}},{}],326:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2]),t}},{}],327:[function(t,e,r){e.exports=function(t,e,r,i,a,o){var s,l;e||(e=3);r||(r=0);l=i?Math.min(i*e+r,t.length):t.length;for(s=r;s0&&(a=1/Math.sqrt(a),t[0]=e[0]*a,t[1]=e[1]*a,t[2]=e[2]*a);return t}},{}],340:[function(t,e,r){e.exports=function(t,e){e=e||1;var r=2*Math.random()*Math.PI,n=2*Math.random()-1,i=Math.sqrt(1-n*n)*e;return t[0]=Math.cos(r)*i,t[1]=Math.sin(r)*i,t[2]=n*e,t}},{}],341:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[1],a=r[2],o=e[1]-i,s=e[2]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=e[0],t[1]=i+o*c-s*l,t[2]=a+o*l+s*c,t}},{}],342:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[0],a=r[2],o=e[0]-i,s=e[2]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=i+s*l+o*c,t[1]=e[1],t[2]=a+s*c-o*l,t}},{}],343:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[0],a=r[1],o=e[0]-i,s=e[1]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=i+o*c-s*l,t[1]=a+o*l+s*c,t[2]=e[2],t}},{}],344:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t[2]=Math.round(e[2]),t}},{}],345:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r,t[1]=e[1]*r,t[2]=e[2]*r,t}},{}],346:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e[0]+r[0]*n,t[1]=e[1]+r[1]*n,t[2]=e[2]+r[2]*n,t}},{}],347:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e,t[1]=r,t[2]=n,t}},{}],348:[function(t,e,r){e.exports=t("./squaredDistance")},{"./squaredDistance":350}],349:[function(t,e,r){e.exports=t("./squaredLength")},{"./squaredLength":351}],350:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2];return r*r+n*n+i*i}},{}],351:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2];return e*e+r*r+n*n}},{}],352:[function(t,e,r){e.exports=t("./subtract")},{"./subtract":353}],353:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]-r[0],t[1]=e[1]-r[1],t[2]=e[2]-r[2],t}},{}],354:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2];return t[0]=n*r[0]+i*r[3]+a*r[6],t[1]=n*r[1]+i*r[4]+a*r[7],t[2]=n*r[2]+i*r[5]+a*r[8],t}},{}],355:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[3]*n+r[7]*i+r[11]*a+r[15];return o=o||1,t[0]=(r[0]*n+r[4]*i+r[8]*a+r[12])/o,t[1]=(r[1]*n+r[5]*i+r[9]*a+r[13])/o,t[2]=(r[2]*n+r[6]*i+r[10]*a+r[14])/o,t}},{}],356:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2],c=r[3],u=c*n+s*a-l*i,f=c*i+l*n-o*a,h=c*a+o*i-s*n,p=-o*n-s*i-l*a;return t[0]=u*c+p*-o+f*-l-h*-s,t[1]=f*c+p*-s+h*-o-u*-l,t[2]=h*c+p*-l+u*-s-f*-o,t}},{}],357:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]+r[0],t[1]=e[1]+r[1],t[2]=e[2]+r[2],t[3]=e[3]+r[3],t}},{}],358:[function(t,e,r){e.exports=function(t){var e=new Float32Array(4);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e}},{}],359:[function(t,e,r){e.exports=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}},{}],360:[function(t,e,r){e.exports=function(){var t=new Float32Array(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t}},{}],361:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2],a=e[3]-t[3];return Math.sqrt(r*r+n*n+i*i+a*a)}},{}],362:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]/r[0],t[1]=e[1]/r[1],t[2]=e[2]/r[2],t[3]=e[3]/r[3],t}},{}],363:[function(t,e,r){e.exports=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3]}},{}],364:[function(t,e,r){e.exports=function(t,e,r,n){var i=new Float32Array(4);return i[0]=t,i[1]=e,i[2]=r,i[3]=n,i}},{}],365:[function(t,e,r){e.exports={create:t("./create"),clone:t("./clone"),fromValues:t("./fromValues"),copy:t("./copy"),set:t("./set"),add:t("./add"),subtract:t("./subtract"),multiply:t("./multiply"),divide:t("./divide"),min:t("./min"),max:t("./max"),scale:t("./scale"),scaleAndAdd:t("./scaleAndAdd"),distance:t("./distance"),squaredDistance:t("./squaredDistance"),length:t("./length"),squaredLength:t("./squaredLength"),negate:t("./negate"),inverse:t("./inverse"),normalize:t("./normalize"),dot:t("./dot"),lerp:t("./lerp"),random:t("./random"),transformMat4:t("./transformMat4"),transformQuat:t("./transformQuat")}},{"./add":357,"./clone":358,"./copy":359,"./create":360,"./distance":361,"./divide":362,"./dot":363,"./fromValues":364,"./inverse":366,"./length":367,"./lerp":368,"./max":369,"./min":370,"./multiply":371,"./negate":372,"./normalize":373,"./random":374,"./scale":375,"./scaleAndAdd":376,"./set":377,"./squaredDistance":378,"./squaredLength":379,"./subtract":380,"./transformMat4":381,"./transformQuat":382}],366:[function(t,e,r){e.exports=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t[2]=1/e[2],t[3]=1/e[3],t}},{}],367:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2],i=t[3];return Math.sqrt(e*e+r*r+n*n+i*i)}},{}],368:[function(t,e,r){e.exports=function(t,e,r,n){var i=e[0],a=e[1],o=e[2],s=e[3];return t[0]=i+n*(r[0]-i),t[1]=a+n*(r[1]-a),t[2]=o+n*(r[2]-o),t[3]=s+n*(r[3]-s),t}},{}],369:[function(t,e,r){e.exports=function(t,e,r){return t[0]=Math.max(e[0],r[0]),t[1]=Math.max(e[1],r[1]),t[2]=Math.max(e[2],r[2]),t[3]=Math.max(e[3],r[3]),t}},{}],370:[function(t,e,r){e.exports=function(t,e,r){return t[0]=Math.min(e[0],r[0]),t[1]=Math.min(e[1],r[1]),t[2]=Math.min(e[2],r[2]),t[3]=Math.min(e[3],r[3]),t}},{}],371:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r[0],t[1]=e[1]*r[1],t[2]=e[2]*r[2],t[3]=e[3]*r[3],t}},{}],372:[function(t,e,r){e.exports=function(t,e){return t[0]=-e[0],t[1]=-e[1],t[2]=-e[2],t[3]=-e[3],t}},{}],373:[function(t,e,r){e.exports=function(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=r*r+n*n+i*i+a*a;o>0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=n*o,t[2]=i*o,t[3]=a*o);return t}},{}],374:[function(t,e,r){var n=t("./normalize"),i=t("./scale");e.exports=function(t,e){return e=e||1,t[0]=Math.random(),t[1]=Math.random(),t[2]=Math.random(),t[3]=Math.random(),n(t,t),i(t,t,e),t}},{"./normalize":373,"./scale":375}],375:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r,t[1]=e[1]*r,t[2]=e[2]*r,t[3]=e[3]*r,t}},{}],376:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e[0]+r[0]*n,t[1]=e[1]+r[1]*n,t[2]=e[2]+r[2]*n,t[3]=e[3]+r[3]*n,t}},{}],377:[function(t,e,r){e.exports=function(t,e,r,n,i){return t[0]=e,t[1]=r,t[2]=n,t[3]=i,t}},{}],378:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2],a=e[3]-t[3];return r*r+n*n+i*i+a*a}},{}],379:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2],i=t[3];return e*e+r*r+n*n+i*i}},{}],380:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]-r[0],t[1]=e[1]-r[1],t[2]=e[2]-r[2],t[3]=e[3]-r[3],t}},{}],381:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3];return t[0]=r[0]*n+r[4]*i+r[8]*a+r[12]*o,t[1]=r[1]*n+r[5]*i+r[9]*a+r[13]*o,t[2]=r[2]*n+r[6]*i+r[10]*a+r[14]*o,t[3]=r[3]*n+r[7]*i+r[11]*a+r[15]*o,t}},{}],382:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2],c=r[3],u=c*n+s*a-l*i,f=c*i+l*n-o*a,h=c*a+o*i-s*n,p=-o*n-s*i-l*a;return t[0]=u*c+p*-o+f*-l-h*-s,t[1]=f*c+p*-s+h*-o-u*-l,t[2]=h*c+p*-l+u*-s-f*-o,t[3]=e[3],t}},{}],383:[function(t,e,r){e.exports=function(t,e,r,a){return n[0]=a,n[1]=r,n[2]=e,n[3]=t,i[0]};var n=new Uint8Array(4),i=new Float32Array(n.buffer)},{}],384:[function(t,e,r){var n=t("glsl-tokenizer"),i=t("atob-lite");e.exports=function(t){for(var e=Array.isArray(t)?t:n(t),r=0;r0)continue;r=t.slice(0,1).join("")}return B(r),z+=r.length,(S=S.slice(r.length)).length}}function H(){return/[^a-fA-F0-9]/.test(e)?(B(S.join("")),T=l,M):(S.push(e),r=e,M+1)}function G(){return"."===e?(S.push(e),T=m,r=e,M+1):/[eE]/.test(e)?(S.push(e),T=m,r=e,M+1):"x"===e&&1===S.length&&"0"===S[0]?(T=_,S.push(e),r=e,M+1):/[^\d]/.test(e)?(B(S.join("")),T=l,M):(S.push(e),r=e,M+1)}function W(){return"f"===e&&(S.push(e),r=e,M+=1),/[eE]/.test(e)?(S.push(e),r=e,M+1):"-"===e&&/[eE]/.test(r)?(S.push(e),r=e,M+1):/[^\d]/.test(e)?(B(S.join("")),T=l,M):(S.push(e),r=e,M+1)}function Y(){if(/[^\d\w_]/.test(e)){var t=S.join("");return T=R.indexOf(t)>-1?y:D.indexOf(t)>-1?v:g,B(S.join("")),T=l,M}return S.push(e),r=e,M+1}};var n=t("./lib/literals"),i=t("./lib/operators"),a=t("./lib/builtins"),o=t("./lib/literals-300es"),s=t("./lib/builtins-300es"),l=999,c=9999,u=0,f=1,h=2,p=3,d=4,m=5,g=6,v=7,y=8,x=9,b=10,_=11,w=["block-comment","line-comment","preprocessor","operator","integer","float","ident","builtin","keyword","whitespace","eof","integer"]},{"./lib/builtins":387,"./lib/builtins-300es":386,"./lib/literals":389,"./lib/literals-300es":388,"./lib/operators":390}],386:[function(t,e,r){var n=t("./builtins");n=n.slice().filter(function(t){return!/^(gl\_|texture)/.test(t)}),e.exports=n.concat(["gl_VertexID","gl_InstanceID","gl_Position","gl_PointSize","gl_FragCoord","gl_FrontFacing","gl_FragDepth","gl_PointCoord","gl_MaxVertexAttribs","gl_MaxVertexUniformVectors","gl_MaxVertexOutputVectors","gl_MaxFragmentInputVectors","gl_MaxVertexTextureImageUnits","gl_MaxCombinedTextureImageUnits","gl_MaxTextureImageUnits","gl_MaxFragmentUniformVectors","gl_MaxDrawBuffers","gl_MinProgramTexelOffset","gl_MaxProgramTexelOffset","gl_DepthRangeParameters","gl_DepthRange","trunc","round","roundEven","isnan","isinf","floatBitsToInt","floatBitsToUint","intBitsToFloat","uintBitsToFloat","packSnorm2x16","unpackSnorm2x16","packUnorm2x16","unpackUnorm2x16","packHalf2x16","unpackHalf2x16","outerProduct","transpose","determinant","inverse","texture","textureSize","textureProj","textureLod","textureOffset","texelFetch","texelFetchOffset","textureProjOffset","textureLodOffset","textureProjLod","textureProjLodOffset","textureGrad","textureGradOffset","textureProjGrad","textureProjGradOffset"])},{"./builtins":387}],387:[function(t,e,r){e.exports=["abs","acos","all","any","asin","atan","ceil","clamp","cos","cross","dFdx","dFdy","degrees","distance","dot","equal","exp","exp2","faceforward","floor","fract","gl_BackColor","gl_BackLightModelProduct","gl_BackLightProduct","gl_BackMaterial","gl_BackSecondaryColor","gl_ClipPlane","gl_ClipVertex","gl_Color","gl_DepthRange","gl_DepthRangeParameters","gl_EyePlaneQ","gl_EyePlaneR","gl_EyePlaneS","gl_EyePlaneT","gl_Fog","gl_FogCoord","gl_FogFragCoord","gl_FogParameters","gl_FragColor","gl_FragCoord","gl_FragData","gl_FragDepth","gl_FragDepthEXT","gl_FrontColor","gl_FrontFacing","gl_FrontLightModelProduct","gl_FrontLightProduct","gl_FrontMaterial","gl_FrontSecondaryColor","gl_LightModel","gl_LightModelParameters","gl_LightModelProducts","gl_LightProducts","gl_LightSource","gl_LightSourceParameters","gl_MaterialParameters","gl_MaxClipPlanes","gl_MaxCombinedTextureImageUnits","gl_MaxDrawBuffers","gl_MaxFragmentUniformComponents","gl_MaxLights","gl_MaxTextureCoords","gl_MaxTextureImageUnits","gl_MaxTextureUnits","gl_MaxVaryingFloats","gl_MaxVertexAttribs","gl_MaxVertexTextureImageUnits","gl_MaxVertexUniformComponents","gl_ModelViewMatrix","gl_ModelViewMatrixInverse","gl_ModelViewMatrixInverseTranspose","gl_ModelViewMatrixTranspose","gl_ModelViewProjectionMatrix","gl_ModelViewProjectionMatrixInverse","gl_ModelViewProjectionMatrixInverseTranspose","gl_ModelViewProjectionMatrixTranspose","gl_MultiTexCoord0","gl_MultiTexCoord1","gl_MultiTexCoord2","gl_MultiTexCoord3","gl_MultiTexCoord4","gl_MultiTexCoord5","gl_MultiTexCoord6","gl_MultiTexCoord7","gl_Normal","gl_NormalMatrix","gl_NormalScale","gl_ObjectPlaneQ","gl_ObjectPlaneR","gl_ObjectPlaneS","gl_ObjectPlaneT","gl_Point","gl_PointCoord","gl_PointParameters","gl_PointSize","gl_Position","gl_ProjectionMatrix","gl_ProjectionMatrixInverse","gl_ProjectionMatrixInverseTranspose","gl_ProjectionMatrixTranspose","gl_SecondaryColor","gl_TexCoord","gl_TextureEnvColor","gl_TextureMatrix","gl_TextureMatrixInverse","gl_TextureMatrixInverseTranspose","gl_TextureMatrixTranspose","gl_Vertex","greaterThan","greaterThanEqual","inversesqrt","length","lessThan","lessThanEqual","log","log2","matrixCompMult","max","min","mix","mod","normalize","not","notEqual","pow","radians","reflect","refract","sign","sin","smoothstep","sqrt","step","tan","texture2D","texture2DLod","texture2DProj","texture2DProjLod","textureCube","textureCubeLod","texture2DLodEXT","texture2DProjLodEXT","textureCubeLodEXT","texture2DGradEXT","texture2DProjGradEXT","textureCubeGradEXT"]},{}],388:[function(t,e,r){var n=t("./literals");e.exports=n.slice().concat(["layout","centroid","smooth","case","mat2x2","mat2x3","mat2x4","mat3x2","mat3x3","mat3x4","mat4x2","mat4x3","mat4x4","uint","uvec2","uvec3","uvec4","samplerCubeShadow","sampler2DArray","sampler2DArrayShadow","isampler2D","isampler3D","isamplerCube","isampler2DArray","usampler2D","usampler3D","usamplerCube","usampler2DArray","coherent","restrict","readonly","writeonly","resource","atomic_uint","noperspective","patch","sample","subroutine","common","partition","active","filter","image1D","image2D","image3D","imageCube","iimage1D","iimage2D","iimage3D","iimageCube","uimage1D","uimage2D","uimage3D","uimageCube","image1DArray","image2DArray","iimage1DArray","iimage2DArray","uimage1DArray","uimage2DArray","image1DShadow","image2DShadow","image1DArrayShadow","image2DArrayShadow","imageBuffer","iimageBuffer","uimageBuffer","sampler1DArray","sampler1DArrayShadow","isampler1D","isampler1DArray","usampler1D","usampler1DArray","isampler2DRect","usampler2DRect","samplerBuffer","isamplerBuffer","usamplerBuffer","sampler2DMS","isampler2DMS","usampler2DMS","sampler2DMSArray","isampler2DMSArray","usampler2DMSArray"])},{"./literals":389}],389:[function(t,e,r){e.exports=["precision","highp","mediump","lowp","attribute","const","uniform","varying","break","continue","do","for","while","if","else","in","out","inout","float","int","void","bool","true","false","discard","return","mat2","mat3","mat4","vec2","vec3","vec4","ivec2","ivec3","ivec4","bvec2","bvec3","bvec4","sampler1D","sampler2D","sampler3D","samplerCube","sampler1DShadow","sampler2DShadow","struct","asm","class","union","enum","typedef","template","this","packed","goto","switch","default","inline","noinline","volatile","public","static","extern","external","interface","long","short","double","half","fixed","unsigned","input","output","hvec2","hvec3","hvec4","dvec2","dvec3","dvec4","fvec2","fvec3","fvec4","sampler2DRect","sampler3DRect","sampler2DRectShadow","sizeof","cast","namespace","using"]},{}],390:[function(t,e,r){e.exports=["<<=",">>=","++","--","<<",">>","<=",">=","==","!=","&&","||","+=","-=","*=","/=","%=","&=","^^","^=","|=","(",")","[","]",".","!","~","*","/","%","+","-","<",">","&","^","|","?",":","=",",",";","{","}"]},{}],391:[function(t,e,r){var n=t("./index");e.exports=function(t,e){var r=n(e),i=[];return i=(i=i.concat(r(t))).concat(r(null))}},{"./index":385}],392:[function(t,e,r){e.exports=function(t){"string"==typeof t&&(t=[t]);for(var e=[].slice.call(arguments,1),r=[],n=0;n>1,u=-7,f=r?i-1:0,h=r?-1:1,p=t[e+f];for(f+=h,a=p&(1<<-u)-1,p>>=-u,u+=s;u>0;a=256*a+t[e+f],f+=h,u-=8);for(o=a&(1<<-u)-1,a>>=-u,u+=n;u>0;o=256*o+t[e+f],f+=h,u-=8);if(0===a)a=1-c;else{if(a===l)return o?NaN:1/0*(p?-1:1);o+=Math.pow(2,n),a-=c}return(p?-1:1)*o*Math.pow(2,a-n)},r.write=function(t,e,r,n,i,a){var o,s,l,c=8*a-i-1,u=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:a-1,d=n?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,o=u):(o=Math.floor(Math.log(e)/Math.LN2),e*(l=Math.pow(2,-o))<1&&(o--,l*=2),(e+=o+f>=1?h/l:h*Math.pow(2,1-f))*l>=2&&(o++,l/=2),o+f>=u?(s=0,o=u):o+f>=1?(s=(e*l-1)*Math.pow(2,i),o+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,i),o=0));i>=8;t[r+p]=255&s,p+=d,s/=256,i-=8);for(o=o<0;t[r+p]=255&o,p+=d,o/=256,c-=8);t[r+p-d]|=128*m}},{}],396:[function(t,e,r){"use strict";e.exports=function(t,e){var r=t.length;if(0===r)throw new Error("Must have at least d+1 points");var i=t[0].length;if(r<=i)throw new Error("Must input at least d+1 points");var o=t.slice(0,i+1),s=n.apply(void 0,o);if(0===s)throw new Error("Input not in general position");for(var l=new Array(i+1),u=0;u<=i;++u)l[u]=u;s<0&&(l[0]=1,l[1]=0);for(var f=new a(l,new Array(i+1),!1),h=f.adjacent,p=new Array(i+2),u=0;u<=i;++u){for(var d=l.slice(),m=0;m<=i;++m)m===u&&(d[m]=-1);var g=d[0];d[0]=d[1],d[1]=g;var v=new a(d,new Array(i+1),!0);h[u]=v,p[u]=v}p[i+1]=f;for(var u=0;u<=i;++u)for(var d=h[u].vertices,y=h[u].adjacent,m=0;m<=i;++m){var x=d[m];if(x<0)y[m]=f;else for(var b=0;b<=i;++b)h[b].vertices.indexOf(x)<0&&(y[m]=h[b])}for(var _=new c(i,o,p),w=!!e,u=i+1;u0&&e.push(","),e.push("tuple[",r,"]");e.push(")}return orient");var i=new Function("test",e.join("")),a=n[t+1];return a||(a=n),i(a)}(t)),this.orient=a}var u=c.prototype;u.handleBoundaryDegeneracy=function(t,e){var r=this.dimension,n=this.vertices.length-1,i=this.tuple,a=this.vertices,o=[t];for(t.lastVisited=-n;o.length>0;){(t=o.pop()).vertices;for(var s=t.adjacent,l=0;l<=r;++l){var c=s[l];if(c.boundary&&!(c.lastVisited<=-n)){for(var u=c.vertices,f=0;f<=r;++f){var h=u[f];i[f]=h<0?e:a[h]}var p=this.orient();if(p>0)return c;c.lastVisited=-n,0===p&&o.push(c)}}}return null},u.walk=function(t,e){var r=this.vertices.length-1,n=this.dimension,i=this.vertices,a=this.tuple,o=e?this.interior.length*Math.random()|0:this.interior.length-1,s=this.interior[o];t:for(;!s.boundary;){for(var l=s.vertices,c=s.adjacent,u=0;u<=n;++u)a[u]=i[l[u]];s.lastVisited=r;for(u=0;u<=n;++u){var f=c[u];if(!(f.lastVisited>=r)){var h=a[u];a[u]=t;var p=this.orient();if(a[u]=h,p<0){s=f;continue t}f.boundary?f.lastVisited=-r:f.lastVisited=r}}return}return s},u.addPeaks=function(t,e){var r=this.vertices.length-1,n=this.dimension,i=this.vertices,l=this.tuple,c=this.interior,u=this.simplices,f=[e];e.lastVisited=r,e.vertices[e.vertices.indexOf(-1)]=r,e.boundary=!1,c.push(e);for(var h=[];f.length>0;){var p=(e=f.pop()).vertices,d=e.adjacent,m=p.indexOf(r);if(!(m<0))for(var g=0;g<=n;++g)if(g!==m){var v=d[g];if(v.boundary&&!(v.lastVisited>=r)){var y=v.vertices;if(v.lastVisited!==-r){for(var x=0,b=0;b<=n;++b)y[b]<0?(x=b,l[b]=t):l[b]=i[y[b]];if(this.orient()>0){y[x]=r,v.boundary=!1,c.push(v),f.push(v),v.lastVisited=r;continue}v.lastVisited=-r}var _=v.adjacent,w=p.slice(),k=d.slice(),M=new a(w,k,!0);u.push(M);var A=_.indexOf(e);if(!(A<0)){_[A]=M,k[m]=v,w[g]=-1,k[g]=e,d[g]=M,M.flip();for(b=0;b<=n;++b){var T=w[b];if(!(T<0||T===r)){for(var S=new Array(n-1),E=0,C=0;C<=n;++C){var L=w[C];L<0||C===b||(S[E++]=L)}h.push(new o(S,M,b))}}}}}}h.sort(s);for(g=0;g+1=0?o[l++]=s[u]:c=1&u;if(c===(1&t)){var f=o[0];o[0]=o[1],o[1]=f}e.push(o)}}return e}},{"robust-orientation":486,"simplicial-complex":496}],397:[function(t,e,r){"use strict";var n=t("binary-search-bounds"),i=0,a=1;function o(t,e,r,n,i){this.mid=t,this.left=e,this.right=r,this.leftPoints=n,this.rightPoints=i,this.count=(e?e.count:0)+(r?r.count:0)+n.length}e.exports=function(t){if(!t||0===t.length)return new x(null);return new x(y(t))};var s=o.prototype;function l(t,e){t.mid=e.mid,t.left=e.left,t.right=e.right,t.leftPoints=e.leftPoints,t.rightPoints=e.rightPoints,t.count=e.count}function c(t,e){var r=y(e);t.mid=r.mid,t.left=r.left,t.right=r.right,t.leftPoints=r.leftPoints,t.rightPoints=r.rightPoints,t.count=r.count}function u(t,e){var r=t.intervals([]);r.push(e),c(t,r)}function f(t,e){var r=t.intervals([]),n=r.indexOf(e);return n<0?i:(r.splice(n,1),c(t,r),a)}function h(t,e,r){for(var n=0;n=0&&t[n][1]>=e;--n){var i=r(t[n]);if(i)return i}}function d(t,e){for(var r=0;r>1],i=[],a=[],s=[];for(r=0;r3*(e+1)?u(this,t):this.left.insert(t):this.left=y([t]);else if(t[0]>this.mid)this.right?4*(this.right.count+1)>3*(e+1)?u(this,t):this.right.insert(t):this.right=y([t]);else{var r=n.ge(this.leftPoints,t,g),i=n.ge(this.rightPoints,t,v);this.leftPoints.splice(r,0,t),this.rightPoints.splice(i,0,t)}},s.remove=function(t){var e=this.count-this.leftPoints;if(t[1]3*(e-1)?f(this,t):2===(c=this.left.remove(t))?(this.left=null,this.count-=1,a):(c===a&&(this.count-=1),c):i;if(t[0]>this.mid)return this.right?4*(this.left?this.left.count:0)>3*(e-1)?f(this,t):2===(c=this.right.remove(t))?(this.right=null,this.count-=1,a):(c===a&&(this.count-=1),c):i;if(1===this.count)return this.leftPoints[0]===t?2:i;if(1===this.leftPoints.length&&this.leftPoints[0]===t){if(this.left&&this.right){for(var r=this,o=this.left;o.right;)r=o,o=o.right;if(r===this)o.right=this.right;else{var s=this.left,c=this.right;r.count-=o.count,r.right=o.left,o.left=s,o.right=c}l(this,o),this.count=(this.left?this.left.count:0)+(this.right?this.right.count:0)+this.leftPoints.length}else this.left?l(this,this.left):l(this,this.right);return a}for(s=n.ge(this.leftPoints,t,g);sthis.mid){var r;if(this.right)if(r=this.right.queryPoint(t,e))return r;return p(this.rightPoints,t,e)}return d(this.leftPoints,e)},s.queryInterval=function(t,e,r){var n;if(tthis.mid&&this.right&&(n=this.right.queryInterval(t,e,r)))return n;return ethis.mid?p(this.rightPoints,t,r):d(this.leftPoints,r)};var b=x.prototype;b.insert=function(t){this.root?this.root.insert(t):this.root=new o(t[0],null,null,[t],[t])},b.remove=function(t){if(this.root){var e=this.root.remove(t);return 2===e&&(this.root=null),e!==i}return!1},b.queryPoint=function(t,e){if(this.root)return this.root.queryPoint(t,e)},b.queryInterval=function(t,e,r){if(t<=e&&this.root)return this.root.queryInterval(t,e,r)},Object.defineProperty(b,"count",{get:function(){return this.root?this.root.count:0}}),Object.defineProperty(b,"intervals",{get:function(){return this.root?this.root.intervals([]):[]}})},{"binary-search-bounds":79}],398:[function(t,e,r){"use strict";e.exports=function(t,e){e=e||new Array(t.length);for(var r=0;r13)&&32!==e&&133!==e&&160!==e&&5760!==e&&6158!==e&&(e<8192||e>8205)&&8232!==e&&8233!==e&&8239!==e&&8287!==e&&8288!==e&&12288!==e&&65279!==e)return!1;return!0}},{}],407:[function(t,e,r){"use strict";e.exports=function(t){return"string"==typeof t&&(t=t.trim(),!!(/^[mzlhvcsqta]\s*[-+.0-9][^mlhvzcsqta]+/i.test(t)&&/[\dz]$/i.test(t)&&t.length>4))}},{}],408:[function(t,e,r){e.exports=function(t,e,r){return t*(1-r)+e*r}},{}],409:[function(t,e,r){(function(t){!function(t,n){"object"==typeof r&&"undefined"!=typeof e?e.exports=n():t.mapboxgl=n()}(this,function(){"use strict";var e,r,n;function i(t,i){if(e)if(r){var a="var sharedChunk = {}; ("+e+")(sharedChunk); ("+r+")(sharedChunk);",o={};e(o),(n=i(o)).workerUrl=window.URL.createObjectURL(new Blob([a],{type:"text/javascript"}))}else r=i;else e=i}return i(0,function(e){var r="undefined"!=typeof window?window:"undefined"!=typeof t?t:"undefined"!=typeof self?self:{};function n(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function i(t,e){return t(e={exports:{}},e.exports),e.exports}var a=o;function o(t,e,r,n){this.cx=3*t,this.bx=3*(r-t)-this.cx,this.ax=1-this.cx-this.bx,this.cy=3*e,this.by=3*(n-e)-this.cy,this.ay=1-this.cy-this.by,this.p1x=t,this.p1y=n,this.p2x=r,this.p2y=n}o.prototype.sampleCurveX=function(t){return((this.ax*t+this.bx)*t+this.cx)*t},o.prototype.sampleCurveY=function(t){return((this.ay*t+this.by)*t+this.cy)*t},o.prototype.sampleCurveDerivativeX=function(t){return(3*this.ax*t+2*this.bx)*t+this.cx},o.prototype.solveCurveX=function(t,e){var r,n,i,a,o;for(void 0===e&&(e=1e-6),i=t,o=0;o<8;o++){if(a=this.sampleCurveX(i)-t,Math.abs(a)(n=1))return n;for(;ra?r=i:n=i,i=.5*(n-r)+r}return i},o.prototype.solve=function(t,e){return this.sampleCurveY(this.solveCurveX(t,e))};var s=function(t,e,r){this.column=t,this.row=e,this.zoom=r};s.prototype.clone=function(){return new s(this.column,this.row,this.zoom)},s.prototype.zoomTo=function(t){return this.clone()._zoomTo(t)},s.prototype.sub=function(t){return this.clone()._sub(t)},s.prototype._zoomTo=function(t){var e=Math.pow(2,t-this.zoom);return this.column*=e,this.row*=e,this.zoom=t,this},s.prototype._sub=function(t){return t=t.zoomTo(this.zoom),this.column-=t.column,this.row-=t.row,this};var l=c;function c(t,e){this.x=t,this.y=e}function u(t,e,r,n){var i=new a(t,e,r,n);return function(t){return i.solve(t)}}c.prototype={clone:function(){return new c(this.x,this.y)},add:function(t){return this.clone()._add(t)},sub:function(t){return this.clone()._sub(t)},multByPoint:function(t){return this.clone()._multByPoint(t)},divByPoint:function(t){return this.clone()._divByPoint(t)},mult:function(t){return this.clone()._mult(t)},div:function(t){return this.clone()._div(t)},rotate:function(t){return this.clone()._rotate(t)},rotateAround:function(t,e){return this.clone()._rotateAround(t,e)},matMult:function(t){return this.clone()._matMult(t)},unit:function(){return this.clone()._unit()},perp:function(){return this.clone()._perp()},round:function(){return this.clone()._round()},mag:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},equals:function(t){return this.x===t.x&&this.y===t.y},dist:function(t){return Math.sqrt(this.distSqr(t))},distSqr:function(t){var e=t.x-this.x,r=t.y-this.y;return e*e+r*r},angle:function(){return Math.atan2(this.y,this.x)},angleTo:function(t){return Math.atan2(this.y-t.y,this.x-t.x)},angleWith:function(t){return this.angleWithSep(t.x,t.y)},angleWithSep:function(t,e){return Math.atan2(this.x*e-this.y*t,this.x*t+this.y*e)},_matMult:function(t){var e=t[0]*this.x+t[1]*this.y,r=t[2]*this.x+t[3]*this.y;return this.x=e,this.y=r,this},_add:function(t){return this.x+=t.x,this.y+=t.y,this},_sub:function(t){return this.x-=t.x,this.y-=t.y,this},_mult:function(t){return this.x*=t,this.y*=t,this},_div:function(t){return this.x/=t,this.y/=t,this},_multByPoint:function(t){return this.x*=t.x,this.y*=t.y,this},_divByPoint:function(t){return this.x/=t.x,this.y/=t.y,this},_unit:function(){return this._div(this.mag()),this},_perp:function(){var t=this.y;return this.y=this.x,this.x=-t,this},_rotate:function(t){var e=Math.cos(t),r=Math.sin(t),n=e*this.x-r*this.y,i=r*this.x+e*this.y;return this.x=n,this.y=i,this},_rotateAround:function(t,e){var r=Math.cos(t),n=Math.sin(t),i=e.x+r*(this.x-e.x)-n*(this.y-e.y),a=e.y+n*(this.x-e.x)+r*(this.y-e.y);return this.x=i,this.y=a,this},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}},c.convert=function(t){return t instanceof c?t:Array.isArray(t)?new c(t[0],t[1]):t};var f=u(.25,.1,.25,1);function h(t,e,r){return Math.min(r,Math.max(e,t))}function p(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];for(var n=0,i=e;n(e.y-t.y)*(r.x-t.x)}function k(t){for(var e=0,r=0,n=t.length,i=n-1,a=void 0,o=void 0;r=200&&r.status<300&&r.response?e(null,{data:n,cacheControl:r.getResponseHeader("Cache-Control"),expires:r.getResponseHeader("Expires")}):e(new A(r.statusText,r.status,t.url))},r.send(),r};function E(t,e,r){r[t]=r[t]||[],r[t].push(e)}function C(t,e,r){if(r&&r[t]){var n=r[t].indexOf(e);-1!==n&&r[t].splice(n,1)}}var L=function(t,e){void 0===e&&(e={}),p(this,e),this.type=t},z=function(t){function e(e,r){void 0===r&&(r={}),t.call(this,"error",p({error:e},r))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(L),O=function(){};O.prototype.on=function(t,e){return this._listeners=this._listeners||{},E(t,e,this._listeners),this},O.prototype.off=function(t,e){return C(t,e,this._listeners),C(t,e,this._oneTimeListeners),this},O.prototype.once=function(t,e){return this._oneTimeListeners=this._oneTimeListeners||{},E(t,e,this._oneTimeListeners),this},O.prototype.fire=function(t){"string"==typeof t&&(t=new L(t,arguments[1]||{}));var e=t.type;if(this.listens(e)){t.target=this;for(var r=0,n=this._listeners&&this._listeners[e]?this._listeners[e].slice():[];r0||this._oneTimeListeners&&this._oneTimeListeners[t]&&this._oneTimeListeners[t].length>0||this._eventedParent&&this._eventedParent.listens(t)},O.prototype.setEventedParent=function(t,e){return this._eventedParent=t,this._eventedParentData=e,this};var I={$version:8,$root:{version:{required:!0,type:"enum",values:[8]},name:{type:"string"},metadata:{type:"*"},center:{type:"array",value:"number"},zoom:{type:"number"},bearing:{type:"number",default:0,period:360,units:"degrees"},pitch:{type:"number",default:0,units:"degrees"},light:{type:"light"},sources:{required:!0,type:"sources"},sprite:{type:"string"},glyphs:{type:"string"},transition:{type:"transition"},layers:{required:!0,type:"array",value:"layer"}},sources:{"*":{type:"source"}},source:["source_vector","source_raster","source_raster_dem","source_geojson","source_video","source_image"],source_vector:{type:{required:!0,type:"enum",values:{vector:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},attribution:{type:"string"},"*":{type:"*"}},source_raster:{type:{required:!0,type:"enum",values:{raster:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},scheme:{type:"enum",values:{xyz:{},tms:{}},default:"xyz"},attribution:{type:"string"},"*":{type:"*"}},source_raster_dem:{type:{required:!0,type:"enum",values:{"raster-dem":{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.0511,180,85.0511]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},attribution:{type:"string"},encoding:{type:"enum",values:{terrarium:{},mapbox:{}},default:"mapbox"},"*":{type:"*"}},source_geojson:{type:{required:!0,type:"enum",values:{geojson:{}}},data:{type:"*"},maxzoom:{type:"number",default:18},buffer:{type:"number",default:128,maximum:512,minimum:0},tolerance:{type:"number",default:.375},cluster:{type:"boolean",default:!1},clusterRadius:{type:"number",default:50,minimum:0},clusterMaxZoom:{type:"number"},lineMetrics:{type:"boolean",default:!1}},source_video:{type:{required:!0,type:"enum",values:{video:{}}},urls:{required:!0,type:"array",value:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},source_image:{type:{required:!0,type:"enum",values:{image:{}}},url:{required:!0,type:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},layer:{id:{type:"string",required:!0},type:{type:"enum",values:{fill:{},line:{},symbol:{},circle:{},heatmap:{},"fill-extrusion":{},raster:{},hillshade:{},background:{}},required:!0},metadata:{type:"*"},source:{type:"string"},"source-layer":{type:"string"},minzoom:{type:"number",minimum:0,maximum:24},maxzoom:{type:"number",minimum:0,maximum:24},filter:{type:"filter"},layout:{type:"layout"},paint:{type:"paint"}},layout:["layout_fill","layout_line","layout_circle","layout_heatmap","layout_fill-extrusion","layout_symbol","layout_raster","layout_hillshade","layout_background"],layout_background:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_fill:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_circle:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_heatmap:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_line:{"line-cap":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{butt:{},round:{},square:{}},default:"butt"},"line-join":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{bevel:{},round:{},miter:{}},default:"miter"},"line-miter-limit":{type:"number",default:2,function:"interpolated","zoom-function":!0,requires:[{"line-join":"miter"}]},"line-round-limit":{type:"number",default:1.05,function:"interpolated","zoom-function":!0,requires:[{"line-join":"round"}]},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_symbol:{"symbol-placement":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{point:{},line:{}},default:"point"},"symbol-spacing":{type:"number",default:250,minimum:1,function:"interpolated","zoom-function":!0,units:"pixels",requires:[{"symbol-placement":"line"}]},"symbol-avoid-edges":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1},"icon-allow-overlap":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image"]},"icon-ignore-placement":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image"]},"icon-optional":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image","text-field"]},"icon-rotation-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"]},"icon-size":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,units:"factor of the original icon size",requires:["icon-image"]},"icon-text-fit":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{none:{},width:{},height:{},both:{}},default:"none",requires:["icon-image","text-field"]},"icon-text-fit-padding":{type:"array",value:"number",length:4,default:[0,0,0,0],units:"pixels",function:"interpolated","zoom-function":!0,requires:["icon-image","text-field",{"icon-text-fit":["both","width","height"]}]},"icon-image":{type:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,tokens:!0},"icon-rotate":{type:"number",default:0,period:360,function:"interpolated","zoom-function":!0,"property-function":!0,units:"degrees",requires:["icon-image"]},"icon-padding":{type:"number",default:2,minimum:0,function:"interpolated","zoom-function":!0,units:"pixels",requires:["icon-image"]},"icon-keep-upright":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["icon-image",{"icon-rotation-alignment":"map"},{"symbol-placement":"line"}]},"icon-offset":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,"property-function":!0,requires:["icon-image"]},"icon-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",requires:["icon-image"]},"icon-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"]},"text-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"]},"text-rotation-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"]},"text-field":{type:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,default:"",tokens:!0},"text-font":{type:"array",value:"string",function:"piecewise-constant","zoom-function":!0,"property-function":!0,default:["Open Sans Regular","Arial Unicode MS Regular"],requires:["text-field"]},"text-size":{type:"number",default:16,minimum:0,units:"pixels",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-max-width":{type:"number",default:10,minimum:0,units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-line-height":{type:"number",default:1.2,units:"ems",function:"interpolated","zoom-function":!0,requires:["text-field"]},"text-letter-spacing":{type:"number",default:0,units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-justify":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{left:{},center:{},right:{}},default:"center",requires:["text-field"]},"text-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",requires:["text-field"]},"text-max-angle":{type:"number",default:45,units:"degrees",function:"interpolated","zoom-function":!0,requires:["text-field",{"symbol-placement":"line"}]},"text-rotate":{type:"number",default:0,period:360,units:"degrees",function:"interpolated","zoom-function":!0,"property-function":!0,requires:["text-field"]},"text-padding":{type:"number",default:2,minimum:0,units:"pixels",function:"interpolated","zoom-function":!0,requires:["text-field"]},"text-keep-upright":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!0,requires:["text-field",{"text-rotation-alignment":"map"},{"symbol-placement":"line"}]},"text-transform":{type:"enum",function:"piecewise-constant","zoom-function":!0,"property-function":!0,values:{none:{},uppercase:{},lowercase:{}},default:"none",requires:["text-field"]},"text-offset":{type:"array",value:"number",units:"ems",function:"interpolated","zoom-function":!0,"property-function":!0,length:2,default:[0,0],requires:["text-field"]},"text-allow-overlap":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field"]},"text-ignore-placement":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field"]},"text-optional":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!1,requires:["text-field","icon-image"]},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_raster:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},layout_hillshade:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},filter:{type:"array",value:"*"},filter_operator:{type:"enum",values:{"==":{},"!=":{},">":{},">=":{},"<":{},"<=":{},in:{},"!in":{},all:{},any:{},none:{},has:{},"!has":{}}},geometry_type:{type:"enum",values:{Point:{},LineString:{},Polygon:{}}},function_stop:{type:"array",minimum:0,maximum:22,value:["number","color"],length:2},expression:{type:"array",value:"*",minimum:1},expression_name:{type:"enum",values:{let:{group:"Variable binding"},var:{group:"Variable binding"},literal:{group:"Types"},array:{group:"Types"},at:{group:"Lookup"},case:{group:"Decision"},match:{group:"Decision"},coalesce:{group:"Decision"},step:{group:"Ramps, scales, curves"},interpolate:{group:"Ramps, scales, curves"},ln2:{group:"Math"},pi:{group:"Math"},e:{group:"Math"},typeof:{group:"Types"},string:{group:"Types"},number:{group:"Types"},boolean:{group:"Types"},object:{group:"Types"},collator:{group:"Types"},"to-string":{group:"Types"},"to-number":{group:"Types"},"to-boolean":{group:"Types"},"to-rgba":{group:"Color"},"to-color":{group:"Types"},rgb:{group:"Color"},rgba:{group:"Color"},get:{group:"Lookup"},has:{group:"Lookup"},length:{group:"Lookup"},properties:{group:"Feature data"},"geometry-type":{group:"Feature data"},id:{group:"Feature data"},zoom:{group:"Zoom"},"heatmap-density":{group:"Heatmap"},"line-progress":{group:"Heatmap"},"+":{group:"Math"},"*":{group:"Math"},"-":{group:"Math"},"/":{group:"Math"},"%":{group:"Math"},"^":{group:"Math"},sqrt:{group:"Math"},log10:{group:"Math"},ln:{group:"Math"},log2:{group:"Math"},sin:{group:"Math"},cos:{group:"Math"},tan:{group:"Math"},asin:{group:"Math"},acos:{group:"Math"},atan:{group:"Math"},min:{group:"Math"},max:{group:"Math"},round:{group:"Math"},abs:{group:"Math"},ceil:{group:"Math"},floor:{group:"Math"},"==":{group:"Decision"},"!=":{group:"Decision"},">":{group:"Decision"},"<":{group:"Decision"},">=":{group:"Decision"},"<=":{group:"Decision"},all:{group:"Decision"},any:{group:"Decision"},"!":{group:"Decision"},"is-supported-script":{group:"String"},upcase:{group:"String"},downcase:{group:"String"},concat:{group:"String"},"resolved-locale":{group:"String"}}},light:{anchor:{type:"enum",default:"viewport",values:{map:{},viewport:{}},transition:!1,"zoom-function":!0,"property-function":!1,function:"piecewise-constant"},position:{type:"array",default:[1.15,210,30],length:3,value:"number",transition:!0,function:"interpolated","zoom-function":!0,"property-function":!1},color:{type:"color",default:"#ffffff",function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0},intensity:{type:"number",default:.5,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0}},paint:["paint_fill","paint_line","paint_circle","paint_heatmap","paint_fill-extrusion","paint_symbol","paint_raster","paint_hillshade","paint_background"],paint_fill:{"fill-antialias":{type:"boolean",function:"piecewise-constant","zoom-function":!0,default:!0},"fill-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:1,minimum:0,maximum:1,transition:!0},"fill-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-pattern"}]},"fill-outline-color":{type:"color",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-pattern"},{"fill-antialias":!0}]},"fill-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"fill-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["fill-translate"]},"fill-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0}},paint_line:{"line-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:1,minimum:0,maximum:1,transition:!0},"line-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"line-pattern"}]},"line-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"line-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["line-translate"]},"line-width":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-gap-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-offset":{type:"number",default:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"line-dasharray":{type:"array",value:"number",function:"piecewise-constant","zoom-function":!0,minimum:0,transition:!0,units:"line widths",requires:[{"!":"line-pattern"}]},"line-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"line-gradient":{type:"color",function:"interpolated","zoom-function":!1,"property-function":!1,transition:!1,requires:[{"!":"line-dasharray"},{"!":"line-pattern"},{source:"geojson",has:{lineMetrics:!0}}]}},paint_circle:{"circle-radius":{type:"number",default:5,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"circle-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-blur":{type:"number",default:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"circle-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["circle-translate"]},"circle-pitch-scale":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map"},"circle-pitch-alignment":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"viewport"},"circle-stroke-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"circle-stroke-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0},"circle-stroke-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0}},paint_heatmap:{"heatmap-radius":{type:"number",default:30,minimum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels"},"heatmap-weight":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!1},"heatmap-intensity":{type:"number",default:1,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0},"heatmap-color":{type:"color",default:["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",.1,"royalblue",.3,"cyan",.5,"lime",.7,"yellow",1,"red"],function:"interpolated","zoom-function":!1,"property-function":!1,transition:!1},"heatmap-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!1,transition:!0}},paint_symbol:{"icon-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["icon-image"]},"icon-halo-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-halo-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels",requires:["icon-image"]},"icon-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["icon-image","icon-translate"]},"text-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:["text-field"]},"text-halo-width":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-halo-blur":{type:"number",default:0,minimum:0,function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels",requires:["text-field"]},"text-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["text-field","text-translate"]}},paint_raster:{"raster-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-hue-rotate":{type:"number",default:0,period:360,function:"interpolated","zoom-function":!0,transition:!0,units:"degrees"},"raster-brightness-min":{type:"number",function:"interpolated","zoom-function":!0,default:0,minimum:0,maximum:1,transition:!0},"raster-brightness-max":{type:"number",function:"interpolated","zoom-function":!0,default:1,minimum:0,maximum:1,transition:!0},"raster-saturation":{type:"number",default:0,minimum:-1,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-contrast":{type:"number",default:0,minimum:-1,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"raster-fade-duration":{type:"number",default:300,minimum:0,function:"interpolated","zoom-function":!0,transition:!1,units:"milliseconds"}},paint_hillshade:{"hillshade-illumination-direction":{type:"number",default:335,minimum:0,maximum:359,function:"interpolated","zoom-function":!0,transition:!1},"hillshade-illumination-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"viewport"},"hillshade-exaggeration":{type:"number",default:.5,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0},"hillshade-shadow-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0},"hillshade-highlight-color":{type:"color",default:"#FFFFFF",function:"interpolated","zoom-function":!0,transition:!0},"hillshade-accent-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0}},paint_background:{"background-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,transition:!0,requires:[{"!":"background-pattern"}]},"background-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"background-opacity":{type:"number",default:1,minimum:0,maximum:1,function:"interpolated","zoom-function":!0,transition:!0}},transition:{duration:{type:"number",default:300,minimum:0,units:"milliseconds"},delay:{type:"number",default:0,minimum:0,units:"milliseconds"}},"layout_fill-extrusion":{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible"}},function:{expression:{type:"expression"},stops:{type:"array",value:"function_stop"},base:{type:"number",default:1,minimum:0},property:{type:"string",default:"$zoom"},type:{type:"enum",values:{identity:{},exponential:{},interval:{},categorical:{}},default:"exponential"},colorSpace:{type:"enum",values:{rgb:{},lab:{},hcl:{}},default:"rgb"},default:{type:"*",required:!1}},"paint_fill-extrusion":{"fill-extrusion-opacity":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!1,default:1,minimum:0,maximum:1,transition:!0},"fill-extrusion-color":{type:"color",default:"#000000",function:"interpolated","zoom-function":!0,"property-function":!0,transition:!0,requires:[{"!":"fill-extrusion-pattern"}]},"fill-extrusion-translate":{type:"array",value:"number",length:2,default:[0,0],function:"interpolated","zoom-function":!0,transition:!0,units:"pixels"},"fill-extrusion-translate-anchor":{type:"enum",function:"piecewise-constant","zoom-function":!0,values:{map:{},viewport:{}},default:"map",requires:["fill-extrusion-translate"]},"fill-extrusion-pattern":{type:"string",function:"piecewise-constant","zoom-function":!0,transition:!0},"fill-extrusion-height":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:0,minimum:0,units:"meters",transition:!0},"fill-extrusion-base":{type:"number",function:"interpolated","zoom-function":!0,"property-function":!0,default:0,minimum:0,units:"meters",transition:!0,requires:["fill-extrusion-height"]}}},P=function(t,e,r,n){this.message=(t?t+": ":"")+r,n&&(this.identifier=n),null!=e&&e.__line__&&(this.line=e.__line__)};function D(t){var e=t.key,r=t.value;return r?[new P(e,r,"constants have been deprecated as of v8")]:[]}function R(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];for(var n=0,i=e;n":"value"===t.itemType.kind?"array":"array<"+e+">"}return t.kind}var J=[V,U,q,H,G,W,Z(Y)];function K(t,e){if("error"===e.kind)return null;if("array"===t.kind){if("array"===e.kind&&!K(t.itemType,e.itemType)&&("number"!=typeof t.N||t.N===e.N))return null}else{if(t.kind===e.kind)return null;if("value"===t.kind)for(var r=0,n=J;r255?255:t}function i(t){return t<0?0:t>1?1:t}function a(t){return"%"===t[t.length-1]?n(parseFloat(t)/100*255):n(parseInt(t))}function o(t){return"%"===t[t.length-1]?i(parseFloat(t)/100):i(parseFloat(t))}function s(t,e,r){return r<0?r+=1:r>1&&(r-=1),6*r<1?t+(e-t)*r*6:2*r<1?e:3*r<2?t+(e-t)*(2/3-r)*6:t}try{e.parseCSSColor=function(t){var e,i=t.replace(/ /g,"").toLowerCase();if(i in r)return r[i].slice();if("#"===i[0])return 4===i.length?(e=parseInt(i.substr(1),16))>=0&&e<=4095?[(3840&e)>>4|(3840&e)>>8,240&e|(240&e)>>4,15&e|(15&e)<<4,1]:null:7===i.length&&(e=parseInt(i.substr(1),16))>=0&&e<=16777215?[(16711680&e)>>16,(65280&e)>>8,255&e,1]:null;var l=i.indexOf("("),c=i.indexOf(")");if(-1!==l&&c+1===i.length){var u=i.substr(0,l),f=i.substr(l+1,c-(l+1)).split(","),h=1;switch(u){case"rgba":if(4!==f.length)return null;h=o(f.pop());case"rgb":return 3!==f.length?null:[a(f[0]),a(f[1]),a(f[2]),h];case"hsla":if(4!==f.length)return null;h=o(f.pop());case"hsl":if(3!==f.length)return null;var p=(parseFloat(f[0])%360+360)%360/360,d=o(f[1]),m=o(f[2]),g=m<=.5?m*(d+1):m+d-m*d,v=2*m-g;return[n(255*s(v,g,p+1/3)),n(255*s(v,g,p)),n(255*s(v,g,p-1/3)),h];default:return null}}return null}}catch(t){}}).parseCSSColor,tt=function(t,e,r,n){void 0===n&&(n=1),this.r=t,this.g=e,this.b=r,this.a=n};tt.parse=function(t){if(t){if(t instanceof tt)return t;if("string"==typeof t){var e=Q(t);if(e)return new tt(e[0]/255*e[3],e[1]/255*e[3],e[2]/255*e[3],e[3])}}},tt.prototype.toString=function(){var t=this.toArray(),e=t[0],r=t[1],n=t[2],i=t[3];return"rgba("+Math.round(e)+","+Math.round(r)+","+Math.round(n)+","+i+")"},tt.prototype.toArray=function(){var t=this.r,e=this.g,r=this.b,n=this.a;return 0===n?[0,0,0,0]:[255*t/n,255*e/n,255*r/n,n]},tt.black=new tt(0,0,0,1),tt.white=new tt(1,1,1,1),tt.transparent=new tt(0,0,0,0);var et=function(t,e,r){this.sensitivity=t?e?"variant":"case":e?"accent":"base",this.locale=r,this.collator=new Intl.Collator(this.locale?this.locale:[],{sensitivity:this.sensitivity,usage:"search"})};et.prototype.compare=function(t,e){return this.collator.compare(t,e)},et.prototype.resolvedLocale=function(){return new Intl.Collator(this.locale?this.locale:[]).resolvedOptions().locale};var rt=function(t,e,r){this.type=X,this.locale=r,this.caseSensitive=t,this.diacriticSensitive=e};function nt(t,e,r,n){return"number"==typeof t&&t>=0&&t<=255&&"number"==typeof e&&e>=0&&e<=255&&"number"==typeof r&&r>=0&&r<=255?void 0===n||"number"==typeof n&&n>=0&&n<=1?null:"Invalid rgba value ["+[t,e,r,n].join(", ")+"]: 'a' must be between 0 and 1.":"Invalid rgba value ["+("number"==typeof n?[t,e,r,n]:[t,e,r]).join(", ")+"]: 'r', 'g', and 'b' must be between 0 and 255."}function it(t){if(null===t)return V;if("string"==typeof t)return q;if("boolean"==typeof t)return H;if("number"==typeof t)return U;if(t instanceof tt)return G;if(t instanceof et)return X;if(Array.isArray(t)){for(var e,r=t.length,n=0,i=t;n4)return e.error("Expected 1, 2, or 3 arguments, but found "+(t.length-1)+" instead.");var r,n;if(t.length>2){var i=t[1];if("string"!=typeof i||!(i in ct))return e.error('The item type argument of "array" must be one of string, number, boolean',1);r=ct[i]}else r=Y;if(t.length>3){if("number"!=typeof t[2]||t[2]<0||t[2]!==Math.floor(t[2]))return e.error('The length argument to "array" must be a positive integer literal',2);n=t[2]}var a=Z(r,n),o=e.parse(t[t.length-1],t.length-1,Y);return o?new ut(a,o):null},ut.prototype.evaluate=function(t){var e=this.input.evaluate(t);if(K(this.type,it(e)))throw new ot("Expected value to be of type "+$(this.type)+", but found "+$(it(e))+" instead.");return e},ut.prototype.eachChild=function(t){t(this.input)},ut.prototype.possibleOutputs=function(){return this.input.possibleOutputs()},ut.prototype.serialize=function(){var t=["array"],e=this.type.itemType;if("string"===e.kind||"number"===e.kind||"boolean"===e.kind){t.push(e.kind);var r=this.type.N;"number"==typeof r&&t.push(r)}return t.push(this.input.serialize()),t};var ft={"to-number":U,"to-color":G},ht=function(t,e){this.type=t,this.args=e};ht.parse=function(t,e){if(t.length<2)return e.error("Expected at least one argument.");for(var r=t[0],n=ft[r],i=[],a=1;a4?"Invalid rbga value "+JSON.stringify(e)+": expected an array containing either three or four numeric values.":nt(e[0],e[1],e[2],e[3])))return new tt(e[0]/255,e[1]/255,e[2]/255,e[3]);throw new ot(r||"Could not parse color from value '"+("string"==typeof e?e:JSON.stringify(e))+"'")}for(var o=null,s=0,l=this.args;s=0)return!1;var r=!0;return t.eachChild(function(t){r&&!vt(t,e)&&(r=!1)}),r}mt.prototype.evaluate=function(t){return this._evaluate(t,this.args)},mt.prototype.eachChild=function(t){this.args.forEach(t)},mt.prototype.possibleOutputs=function(){return[void 0]},mt.prototype.serialize=function(){return[this.name].concat(this.args.map(function(t){return t.serialize()}))},mt.parse=function(t,e){var r=t[0],n=mt.definitions[r];if(!n)return e.error('Unknown expression "'+r+'". If you wanted a literal array, use ["literal", [...]].',0);for(var i=Array.isArray(n)?n[0]:n.type,a=Array.isArray(n)?[[n[1],n[2]]]:n.overloads,o=a.filter(function(e){var r=e[0];return!Array.isArray(r)||r.length===t.length-1}),s=[],l=1;lr&&ee))throw new ot("Input is not a number.");a=o-1}}return Math.max(o-1,0)}xt.prototype.parse=function(t,e,r,n,i){return void 0===i&&(i={}),e?this.concat(e,r,n)._parse(t,i):this._parse(t,i)},xt.prototype._parse=function(t,e){if(null!==t&&"string"!=typeof t&&"boolean"!=typeof t&&"number"!=typeof t||(t=["literal",t]),Array.isArray(t)){if(0===t.length)return this.error('Expected an array with at least one element. If you wanted a literal array, use ["literal", []].');var r=t[0];if("string"!=typeof r)return this.error("Expression name must be a string, but found "+typeof r+' instead. If you wanted a literal array, use ["literal", [...]].',0),null;var n=this.registry[r];if(n){var i=n.parse(t,this);if(!i)return null;if(this.expectedType){var a=this.expectedType,o=i.type;if("string"!==a.kind&&"number"!==a.kind&&"boolean"!==a.kind&&"object"!==a.kind||"value"!==o.kind)if("array"===a.kind&&"value"===o.kind)e.omitTypeAnnotations||(i=new ut(a,i));else if("color"!==a.kind||"value"!==o.kind&&"string"!==o.kind){if(this.checkSubtype(this.expectedType,i.type))return null}else e.omitTypeAnnotations||(i=new ht(a,[i]));else e.omitTypeAnnotations||(i=new lt(a,[i]))}if(!(i instanceof at)&&function t(e){if(e instanceof yt)return t(e.boundExpression);if(e instanceof mt&&"error"===e.name)return!1;if(e instanceof rt)return!1;var r=e instanceof ht||e instanceof lt||e instanceof ut,n=!0;return e.eachChild(function(e){n=r?n&&t(e):n&&e instanceof at}),!!n&&(gt(e)&&vt(e,["zoom","heatmap-density","line-progress","is-supported-script"]))}(i)){var s=new dt;try{i=new at(i.type,i.evaluate(s))}catch(t){return this.error(t.message),null}}return i}return this.error('Unknown expression "'+r+'". If you wanted a literal array, use ["literal", [...]].',0)}return void 0===t?this.error("'undefined' value invalid. Use null instead."):"object"==typeof t?this.error('Bare objects invalid. Use ["literal", {...}] instead.'):this.error("Expected an array, but found "+typeof t+" instead.")},xt.prototype.concat=function(t,e,r){var n="number"==typeof t?this.path.concat(t):this.path,i=r?this.scope.concat(r):this.scope;return new xt(this.registry,n,e||null,i,this.errors)},xt.prototype.error=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];var n=""+this.key+e.map(function(t){return"["+t+"]"}).join("");this.errors.push(new N(n,t))},xt.prototype.checkSubtype=function(t,e){var r=K(t,e);return r&&this.error(r),r};var _t=function(t,e,r){this.type=t,this.input=e,this.labels=[],this.outputs=[];for(var n=0,i=r;n=s)return e.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.',c);var f=e.parse(l,u,a);if(!f)return null;a=a||f.type,i.push([s,f])}return new _t(a,r,i)},_t.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;return n>=e[i-1]?r[i-1].evaluate(t):r[bt(e,n)].evaluate(t)},_t.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e0&&t.push(this.labels[e]),t.push(this.outputs[e].serialize());return t};var kt=Object.freeze({number:wt,color:function(t,e,r){return new tt(wt(t.r,e.r,r),wt(t.g,e.g,r),wt(t.b,e.b,r),wt(t.a,e.a,r))},array:function(t,e,r){return t.map(function(t,n){return wt(t,e[n],r)})}}),Mt=function(t,e,r,n){this.type=t,this.interpolation=e,this.input=r,this.labels=[],this.outputs=[];for(var i=0,a=n;i1}))return e.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.",1);r={name:"cubic-bezier",controlPoints:o}}if(t.length-1<4)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if((t.length-1)%2!=0)return e.error("Expected an even number of arguments.");if(!(n=e.parse(n,2,U)))return null;var s=[],l=null;e.expectedType&&"value"!==e.expectedType.kind&&(l=e.expectedType);for(var c=0;c=u)return e.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.',h);var d=e.parse(f,p,l);if(!d)return null;l=l||d.type,s.push([u,d])}return"number"===l.kind||"color"===l.kind||"array"===l.kind&&"number"===l.itemType.kind&&"number"==typeof l.N?new Mt(l,r,n,s):e.error("Type "+$(l)+" is not interpolatable.")},Mt.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;if(n>=e[i-1])return r[i-1].evaluate(t);var a=bt(e,n),o=e[a],s=e[a+1],l=Mt.interpolationFactor(this.interpolation,n,o,s),c=r[a].evaluate(t),u=r[a+1].evaluate(t);return kt[this.type.kind.toLowerCase()](c,u,l)},Mt.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e=r.length)throw new ot("Array index out of bounds: "+e+" > "+(r.length-1)+".");if(e!==Math.floor(e))throw new ot("Array index must be an integer, but found "+e+" instead.");return r[e]},Et.prototype.eachChild=function(t){t(this.index),t(this.input)},Et.prototype.possibleOutputs=function(){return[void 0]},Et.prototype.serialize=function(){return["at",this.index.serialize(),this.input.serialize()]};var Ct=function(t,e,r,n,i,a){this.inputType=t,this.type=e,this.input=r,this.cases=n,this.outputs=i,this.otherwise=a};Ct.parse=function(t,e){if(t.length<5)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if(t.length%2!=1)return e.error("Expected an even number of arguments.");var r,n;e.expectedType&&"value"!==e.expectedType.kind&&(n=e.expectedType);for(var i={},a=[],o=2;oNumber.MAX_SAFE_INTEGER)return c.error("Branch labels must be integers no larger than "+Number.MAX_SAFE_INTEGER+".");if("number"==typeof h&&Math.floor(h)!==h)return c.error("Numeric branch labels must be integer values.");if(r){if(c.checkSubtype(r,it(h)))return null}else r=it(h);if(void 0!==i[String(h)])return c.error("Branch labels must be unique.");i[String(h)]=a.length}var p=e.parse(l,o,n);if(!p)return null;n=n||p.type,a.push(p)}var d=e.parse(t[1],1,r);if(!d)return null;var m=e.parse(t[t.length-1],t.length-1,n);return m?new Ct(r,n,d,i,a,m):null},Ct.prototype.evaluate=function(t){var e=this.input.evaluate(t);return(this.outputs[this.cases[e]]||this.otherwise).evaluate(t)},Ct.prototype.eachChild=function(t){t(this.input),this.outputs.forEach(t),t(this.otherwise)},Ct.prototype.possibleOutputs=function(){return(t=[]).concat.apply(t,this.outputs.map(function(t){return t.possibleOutputs()})).concat(this.otherwise.possibleOutputs());var t},Ct.prototype.serialize=function(){for(var t=this,e=["match",this.input.serialize()],r=[],n={},i=0,a=Object.keys(this.cases).sort();in.evaluate(t)}function Ut(t,e){var r=e[0],n=e[1];return r.evaluate(t)<=n.evaluate(t)}function qt(t,e){var r=e[0],n=e[1];return r.evaluate(t)>=n.evaluate(t)}function Ht(t){return{type:t}}function Gt(t){return{result:"success",value:t}}function Wt(t){return{result:"error",value:t}}mt.register(Rt,{error:[{kind:"error"},[q],function(t,e){var r=e[0];throw new ot(r.evaluate(t))}],typeof:[q,[Y],function(t,e){return $(it(e[0].evaluate(t)))}],"to-string":[q,[Y],function(t,e){var r=e[0],n=typeof(r=r.evaluate(t));return null===r?"":"string"===n||"number"===n||"boolean"===n?String(r):r instanceof tt?r.toString():JSON.stringify(r)}],"to-boolean":[H,[Y],function(t,e){var r=e[0];return Boolean(r.evaluate(t))}],"to-rgba":[Z(U,4),[G],function(t,e){return e[0].evaluate(t).toArray()}],rgb:[G,[U,U,U],Bt],rgba:[G,[U,U,U,U],Bt],has:{type:H,overloads:[[[q],function(t,e){return Ft(e[0].evaluate(t),t.properties())}],[[q,W],function(t,e){var r=e[0],n=e[1];return Ft(r.evaluate(t),n.evaluate(t))}]]},get:{type:Y,overloads:[[[q],function(t,e){return Nt(e[0].evaluate(t),t.properties())}],[[q,W],function(t,e){var r=e[0],n=e[1];return Nt(r.evaluate(t),n.evaluate(t))}]]},properties:[W,[],function(t){return t.properties()}],"geometry-type":[q,[],function(t){return t.geometryType()}],id:[Y,[],function(t){return t.id()}],zoom:[U,[],function(t){return t.globals.zoom}],"heatmap-density":[U,[],function(t){return t.globals.heatmapDensity||0}],"line-progress":[U,[],function(t){return t.globals.lineProgress||0}],"+":[U,Ht(U),function(t,e){for(var r=0,n=0,i=e;n":[H,[q,Y],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i>a}],"filter-id->":[H,[Y],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>i}],"filter-<=":[H,[q,Y],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i<=a}],"filter-id-<=":[H,[Y],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n<=i}],"filter->=":[H,[q,Y],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i>=a}],"filter-id->=":[H,[Y],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>=i}],"filter-has":[H,[Y],function(t,e){return e[0].value in t.properties()}],"filter-has-id":[H,[],function(t){return null!==t.id()}],"filter-type-in":[H,[Z(q)],function(t,e){return e[0].value.indexOf(t.geometryType())>=0}],"filter-id-in":[H,[Z(Y)],function(t,e){return e[0].value.indexOf(t.id())>=0}],"filter-in-small":[H,[q,Z(Y)],function(t,e){var r=e[0];return e[1].value.indexOf(t.properties()[r.value])>=0}],"filter-in-large":[H,[q,Z(Y)],function(t,e){var r=e[0],n=e[1];return function(t,e,r,n){for(;r<=n;){var i=r+n>>1;if(e[i]===t)return!0;e[i]>t?n=i-1:r=i+1}return!1}(t.properties()[r.value],n.value,0,n.value.length-1)}],">":{type:H,overloads:[[[U,U],Vt],[[q,q],Vt],[[q,q,X],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))>0}]]},"<":{type:H,overloads:[[[U,U],jt],[[q,q],jt],[[q,q,X],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))<0}]]},">=":{type:H,overloads:[[[U,U],qt],[[q,q],qt],[[q,q,X],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))>=0}]]},"<=":{type:H,overloads:[[[U,U],Ut],[[q,q],Ut],[[q,q,X],function(t,e){var r=e[0],n=e[1];return e[2].evaluate(t).compare(r.evaluate(t),n.evaluate(t))<=0}]]},all:{type:H,overloads:[[[H,H],function(t,e){var r=e[0],n=e[1];return r.evaluate(t)&&n.evaluate(t)}],[Ht(H),function(t,e){for(var r=0,n=e;rQt?Math.pow(t,1/3):t/Kt+$t}function ne(t){return t>Jt?t*t*t:Kt*(t-$t)}function ie(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function ae(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function oe(t){var e=ae(t.r),r=ae(t.g),n=ae(t.b),i=re((.4124564*e+.3575761*r+.1804375*n)/Yt),a=re((.2126729*e+.7151522*r+.072175*n)/Xt);return{l:116*a-16,a:500*(i-a),b:200*(a-re((.0193339*e+.119192*r+.9503041*n)/Zt)),alpha:t.a}}function se(t){var e=(t.l+16)/116,r=isNaN(t.a)?e:e+t.a/500,n=isNaN(t.b)?e:e-t.b/200;return e=Xt*ne(e),r=Yt*ne(r),n=Zt*ne(n),new tt(ie(3.2404542*r-1.5371385*e-.4985314*n),ie(-.969266*r+1.8760108*e+.041556*n),ie(.0556434*r-.2040259*e+1.0572252*n),t.alpha)}var le={forward:oe,reverse:se,interpolate:function(t,e,r){return{l:wt(t.l,e.l,r),a:wt(t.a,e.a,r),b:wt(t.b,e.b,r),alpha:wt(t.alpha,e.alpha,r)}}},ce={forward:function(t){var e=oe(t),r=e.l,n=e.a,i=e.b,a=Math.atan2(i,n)*ee;return{h:a<0?a+360:a,c:Math.sqrt(n*n+i*i),l:r,alpha:t.a}},reverse:function(t){var e=t.h*te,r=t.c;return se({l:t.l,a:Math.cos(e)*r,b:Math.sin(e)*r,alpha:t.alpha})},interpolate:function(t,e,r){return{h:function(t,e,r){var n=e-t;return t+r*(n>180||n<-180?n-360*Math.round(n/360):n)}(t.h,e.h,r),c:wt(t.c,e.c,r),l:wt(t.l,e.l,r),alpha:wt(t.alpha,e.alpha,r)}}},ue=Object.freeze({lab:le,hcl:ce});function fe(t){return t instanceof Number?"number":t instanceof String?"string":t instanceof Boolean?"boolean":Array.isArray(t)?"array":null===t?"null":typeof t}function he(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function pe(t){return t}function de(t,e,r){return void 0!==t?t:void 0!==e?e:void 0!==r?r:void 0}function me(t,e,r,n,i){return de(typeof r===i?n[r]:void 0,t.default,e.default)}function ge(t,e,r){if("number"!==fe(r))return de(t.default,e.default);var n=t.stops.length;if(1===n)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[n-1][0])return t.stops[n-1][1];var i=xe(t.stops,r);return t.stops[i][1]}function ve(t,e,r){var n=void 0!==t.base?t.base:1;if("number"!==fe(r))return de(t.default,e.default);var i=t.stops.length;if(1===i)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[i-1][0])return t.stops[i-1][1];var a=xe(t.stops,r),o=function(t,e,r,n){var i=n-r,a=t-r;return 0===i?0:1===e?a/i:(Math.pow(e,a)-1)/(Math.pow(e,i)-1)}(r,n,t.stops[a][0],t.stops[a+1][0]),s=t.stops[a][1],l=t.stops[a+1][1],c=kt[e.type]||pe;if(t.colorSpace&&"rgb"!==t.colorSpace){var u=ue[t.colorSpace];c=function(t,e){return u.reverse(u.interpolate(u.forward(t),u.forward(e),o))}}return"function"==typeof s.evaluate?{evaluate:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var r=s.evaluate.apply(void 0,t),n=l.evaluate.apply(void 0,t);if(void 0!==r&&void 0!==n)return c(r,n,o)}}:c(s,l,o)}function ye(t,e,r){return"color"===e.type?r=tt.parse(r):fe(r)===e.type||"enum"===e.type&&e.values[r]||(r=void 0),de(r,t.default,e.default)}function xe(t,e){for(var r,n,i=0,a=t.length-1,o=0;i<=a;){if(r=t[o=Math.floor((i+a)/2)][0],n=t[o+1][0],e===r||e>r&&ee&&(a=o-1)}return Math.max(o-1,0)}var be=function(t,e){var r;this.expression=t,this._warningHistory={},this._defaultValue="color"===(r=e).type&&he(r.default)?new tt(0,0,0,0):"color"===r.type?tt.parse(r.default)||null:void 0===r.default?null:r.default,"enum"===e.type&&(this._enumValues=e.values)};function _e(t){return Array.isArray(t)&&t.length>0&&"string"==typeof t[0]&&t[0]in Rt}function we(t,e){var r=new xt(Rt,[],function(t){var e={color:G,string:q,number:U,enum:q,boolean:H};return"array"===t.type?Z(e[t.value]||Y,t.length):e[t.type]||null}(e)),n=r.parse(t);return n?Gt(new be(n,e)):Wt(r.errors)}be.prototype.evaluateWithoutErrorHandling=function(t,e){return this._evaluator||(this._evaluator=new dt),this._evaluator.globals=t,this._evaluator.feature=e,this.expression.evaluate(this._evaluator)},be.prototype.evaluate=function(t,e){this._evaluator||(this._evaluator=new dt),this._evaluator.globals=t,this._evaluator.feature=e;try{var r=this.expression.evaluate(this._evaluator);if(null==r)return this._defaultValue;if(this._enumValues&&!(r in this._enumValues))throw new ot("Expected value to be one of "+Object.keys(this._enumValues).map(function(t){return JSON.stringify(t)}).join(", ")+", but found "+JSON.stringify(r)+" instead.");return r}catch(t){return this._warningHistory[t.message]||(this._warningHistory[t.message]=!0,"undefined"!=typeof console&&console.warn(t.message)),this._defaultValue}};var ke=function(t,e){this.kind=t,this._styleExpression=e};ke.prototype.evaluateWithoutErrorHandling=function(t,e){return this._styleExpression.evaluateWithoutErrorHandling(t,e)},ke.prototype.evaluate=function(t,e){return this._styleExpression.evaluate(t,e)};var Me=function(t,e,r){this.kind=t,this.zoomStops=r.labels,this._styleExpression=e,r instanceof Mt&&(this._interpolationType=r.interpolation)};function Ae(t,e){if("error"===(t=we(t,e)).result)return t;var r=t.value.expression,n=gt(r);if(!n&&!e["property-function"])return Wt([new N("","property expressions not supported")]);var i=vt(r,["zoom"]);if(!i&&!1===e["zoom-function"])return Wt([new N("","zoom expressions not supported")]);var a=function t(e){var r=null;if(e instanceof St)r=t(e.result);else if(e instanceof Tt)for(var n=0,i=e.args;nn.maximum?[new P(e,r,r+" is greater than the maximum value "+n.maximum)]:[]}function ze(t){var e,r,n,i=t.valueSpec,a=B(t.value.type),o={},s="categorical"!==a&&void 0===t.value.property,l=!s,c="array"===fe(t.value.stops)&&"array"===fe(t.value.stops[0])&&"object"===fe(t.value.stops[0][0]),u=Ee({key:t.key,value:t.value,valueSpec:t.styleSpec.function,style:t.style,styleSpec:t.styleSpec,objectElementValidators:{stops:function(t){if("identity"===a)return[new P(t.key,t.value,'identity function may not have a "stops" property')];var e=[],r=t.value;return e=e.concat(Ce({key:t.key,value:r,valueSpec:t.valueSpec,style:t.style,styleSpec:t.styleSpec,arrayElementValidator:f})),"array"===fe(r)&&0===r.length&&e.push(new P(t.key,r,"array must have at least one stop")),e},default:function(t){return Ke({key:t.key,value:t.value,valueSpec:i,style:t.style,styleSpec:t.styleSpec})}}});return"identity"===a&&s&&u.push(new P(t.key,t.value,'missing required property "property"')),"identity"===a||t.value.stops||u.push(new P(t.key,t.value,'missing required property "stops"')),"exponential"===a&&"piecewise-constant"===t.valueSpec.function&&u.push(new P(t.key,t.value,"exponential functions not supported")),t.styleSpec.$version>=8&&(l&&!t.valueSpec["property-function"]?u.push(new P(t.key,t.value,"property functions not supported")):s&&!t.valueSpec["zoom-function"]&&"heatmap-color"!==t.objectKey&&"line-gradient"!==t.objectKey&&u.push(new P(t.key,t.value,"zoom functions not supported"))),"categorical"!==a&&!c||void 0!==t.value.property||u.push(new P(t.key,t.value,'"property" property is required')),u;function f(t){var e=[],a=t.value,s=t.key;if("array"!==fe(a))return[new P(s,a,"array expected, "+fe(a)+" found")];if(2!==a.length)return[new P(s,a,"array length 2 expected, length "+a.length+" found")];if(c){if("object"!==fe(a[0]))return[new P(s,a,"object expected, "+fe(a[0])+" found")];if(void 0===a[0].zoom)return[new P(s,a,"object stop key must have zoom")];if(void 0===a[0].value)return[new P(s,a,"object stop key must have value")];if(n&&n>B(a[0].zoom))return[new P(s,a[0].zoom,"stop zoom values must appear in ascending order")];B(a[0].zoom)!==n&&(n=B(a[0].zoom),r=void 0,o={}),e=e.concat(Ee({key:s+"[0]",value:a[0],valueSpec:{zoom:{}},style:t.style,styleSpec:t.styleSpec,objectElementValidators:{zoom:Le,value:h}}))}else e=e.concat(h({key:s+"[0]",value:a[0],valueSpec:{},style:t.style,styleSpec:t.styleSpec},a));return e.concat(Ke({key:s+"[1]",value:a[1],valueSpec:i,style:t.style,styleSpec:t.styleSpec}))}function h(t,n){var s=fe(t.value),l=B(t.value),c=null!==t.value?t.value:n;if(e){if(s!==e)return[new P(t.key,c,s+" stop domain type must match previous stop domain type "+e)]}else e=s;if("number"!==s&&"string"!==s&&"boolean"!==s)return[new P(t.key,c,"stop domain value must be a number, string, or boolean")];if("number"!==s&&"categorical"!==a){var u="number expected, "+s+" found";return i["property-function"]&&void 0===a&&(u+='\nIf you intended to use a categorical function, specify `"type": "categorical"`.'),[new P(t.key,c,u)]}return"categorical"!==a||"number"!==s||isFinite(l)&&Math.floor(l)===l?"categorical"!==a&&"number"===s&&void 0!==r&&l=2&&"$id"!==t[1]&&"$type"!==t[1];case"in":case"!in":case"!has":case"none":return!1;case"==":case"!=":case">":case">=":case"<":case"<=":return 3===t.length&&(Array.isArray(t[1])||Array.isArray(t[2]));case"any":case"all":for(var e=0,r=t.slice(1);ee?1:0}function Fe(t){if(!t)return!0;var e,r=t[0];return t.length<=1?"any"!==r:"=="===r?Ne(t[1],t[2],"=="):"!="===r?Ue(Ne(t[1],t[2],"==")):"<"===r||">"===r||"<="===r||">="===r?Ne(t[1],t[2],r):"any"===r?(e=t.slice(1),["any"].concat(e.map(Fe))):"all"===r?["all"].concat(t.slice(1).map(Fe)):"none"===r?["all"].concat(t.slice(1).map(Fe).map(Ue)):"in"===r?je(t[1],t.slice(2)):"!in"===r?Ue(je(t[1],t.slice(2))):"has"===r?Ve(t[1]):"!has"!==r||Ue(Ve(t[1]))}function Ne(t,e,r){switch(t){case"$type":return["filter-type-"+r,e];case"$id":return["filter-id-"+r,e];default:return["filter-"+r,t,e]}}function je(t,e){if(0===e.length)return!1;switch(t){case"$type":return["filter-type-in",["literal",e]];case"$id":return["filter-id-in",["literal",e]];default:return e.length>200&&!e.some(function(t){return typeof t!=typeof e[0]})?["filter-in-large",t,["literal",e.sort(Be)]]:["filter-in-small",t,["literal",e]]}}function Ve(t){switch(t){case"$type":return!0;case"$id":return["filter-has-id"];default:return["filter-has",t]}}function Ue(t){return["!",t]}function qe(t){return Pe(F(t.value))?Oe(R({},t,{expressionContext:"filter",valueSpec:{value:"boolean"}})):function t(e){var r=e.value,n=e.key;if("array"!==fe(r))return[new P(n,r,"array expected, "+fe(r)+" found")];var i,a=e.styleSpec,o=[];if(r.length<1)return[new P(n,r,"filter array must have at least 1 element")];switch(o=o.concat(Ie({key:n+"[0]",value:r[0],valueSpec:a.filter_operator,style:e.style,styleSpec:e.styleSpec})),B(r[0])){case"<":case"<=":case">":case">=":r.length>=2&&"$type"===B(r[1])&&o.push(new P(n,r,'"$type" cannot be use with operator "'+r[0]+'"'));case"==":case"!=":3!==r.length&&o.push(new P(n,r,'filter array for operator "'+r[0]+'" must have 3 elements'));case"in":case"!in":r.length>=2&&"string"!==(i=fe(r[1]))&&o.push(new P(n+"[1]",r[1],"string expected, "+i+" found"));for(var s=2;s=c[h+0]&&n>=c[h+1]?(o[f]=!0,a.push(l[f])):o[f]=!1}}},ur.prototype._forEachCell=function(t,e,r,n,i,a,o){for(var s=this._convertToCellCoord(t),l=this._convertToCellCoord(e),c=this._convertToCellCoord(r),u=this._convertToCellCoord(n),f=s;f<=c;f++)for(var h=l;h<=u;h++){var p=this.d*h+f;if(i.call(this,t,e,r,n,p,a,o))return}},ur.prototype._convertToCellCoord=function(t){return Math.max(0,Math.min(this.d-1,Math.floor(t*this.scale)+this.padding))},ur.prototype.toArrayBuffer=function(){if(this.arrayBuffer)return this.arrayBuffer;for(var t=this.cells,e=cr+this.cells.length+1+1,r=0,n=0;n=0)){var f=t[u];c[u]=hr[l].shallow.indexOf(u)>=0?f:mr(f,e)}t instanceof Error&&(c.message=t.message)}return{name:l,properties:c}}throw new Error("can't serialize object of type "+typeof t)}function gr(t){if(null==t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||t instanceof Boolean||t instanceof Number||t instanceof String||t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||ArrayBuffer.isView(t)||t instanceof fr)return t;if(Array.isArray(t))return t.map(function(t){return gr(t)});if("object"==typeof t){var e=t,r=e.name,n=e.properties;if(!r)throw new Error("can't deserialize object of anonymous class");var i=hr[r].klass;if(!i)throw new Error("can't deserialize unregistered class "+r);if(i.deserialize)return i.deserialize(n._serialized);for(var a=Object.create(i.prototype),o=0,s=Object.keys(n);o=0?n[l]:gr(n[l])}return a}throw new Error("can't deserialize object of type "+typeof t)}var vr=function(){this.first=!0};vr.prototype.update=function(t,e){var r=Math.floor(t);return this.first?(this.first=!1,this.lastIntegerZoom=r,this.lastIntegerZoomTime=0,this.lastZoom=t,this.lastFloorZoom=r,!0):(this.lastFloorZoom>r?(this.lastIntegerZoom=r+1,this.lastIntegerZoomTime=e):this.lastFloorZoom=128&&t<=255},Arabic:function(t){return t>=1536&&t<=1791},"Arabic Supplement":function(t){return t>=1872&&t<=1919},"Arabic Extended-A":function(t){return t>=2208&&t<=2303},"Hangul Jamo":function(t){return t>=4352&&t<=4607},"Unified Canadian Aboriginal Syllabics":function(t){return t>=5120&&t<=5759},Khmer:function(t){return t>=6016&&t<=6143},"Unified Canadian Aboriginal Syllabics Extended":function(t){return t>=6320&&t<=6399},"General Punctuation":function(t){return t>=8192&&t<=8303},"Letterlike Symbols":function(t){return t>=8448&&t<=8527},"Number Forms":function(t){return t>=8528&&t<=8591},"Miscellaneous Technical":function(t){return t>=8960&&t<=9215},"Control Pictures":function(t){return t>=9216&&t<=9279},"Optical Character Recognition":function(t){return t>=9280&&t<=9311},"Enclosed Alphanumerics":function(t){return t>=9312&&t<=9471},"Geometric Shapes":function(t){return t>=9632&&t<=9727},"Miscellaneous Symbols":function(t){return t>=9728&&t<=9983},"Miscellaneous Symbols and Arrows":function(t){return t>=11008&&t<=11263},"CJK Radicals Supplement":function(t){return t>=11904&&t<=12031},"Kangxi Radicals":function(t){return t>=12032&&t<=12255},"Ideographic Description Characters":function(t){return t>=12272&&t<=12287},"CJK Symbols and Punctuation":function(t){return t>=12288&&t<=12351},Hiragana:function(t){return t>=12352&&t<=12447},Katakana:function(t){return t>=12448&&t<=12543},Bopomofo:function(t){return t>=12544&&t<=12591},"Hangul Compatibility Jamo":function(t){return t>=12592&&t<=12687},Kanbun:function(t){return t>=12688&&t<=12703},"Bopomofo Extended":function(t){return t>=12704&&t<=12735},"CJK Strokes":function(t){return t>=12736&&t<=12783},"Katakana Phonetic Extensions":function(t){return t>=12784&&t<=12799},"Enclosed CJK Letters and Months":function(t){return t>=12800&&t<=13055},"CJK Compatibility":function(t){return t>=13056&&t<=13311},"CJK Unified Ideographs Extension A":function(t){return t>=13312&&t<=19903},"Yijing Hexagram Symbols":function(t){return t>=19904&&t<=19967},"CJK Unified Ideographs":function(t){return t>=19968&&t<=40959},"Yi Syllables":function(t){return t>=40960&&t<=42127},"Yi Radicals":function(t){return t>=42128&&t<=42191},"Hangul Jamo Extended-A":function(t){return t>=43360&&t<=43391},"Hangul Syllables":function(t){return t>=44032&&t<=55215},"Hangul Jamo Extended-B":function(t){return t>=55216&&t<=55295},"Private Use Area":function(t){return t>=57344&&t<=63743},"CJK Compatibility Ideographs":function(t){return t>=63744&&t<=64255},"Arabic Presentation Forms-A":function(t){return t>=64336&&t<=65023},"Vertical Forms":function(t){return t>=65040&&t<=65055},"CJK Compatibility Forms":function(t){return t>=65072&&t<=65103},"Small Form Variants":function(t){return t>=65104&&t<=65135},"Arabic Presentation Forms-B":function(t){return t>=65136&&t<=65279},"Halfwidth and Fullwidth Forms":function(t){return t>=65280&&t<=65519}};function xr(t){for(var e=0,r=t;e=65097&&t<=65103)||yr["CJK Compatibility Ideographs"](t)||yr["CJK Compatibility"](t)||yr["CJK Radicals Supplement"](t)||yr["CJK Strokes"](t)||!(!yr["CJK Symbols and Punctuation"](t)||t>=12296&&t<=12305||t>=12308&&t<=12319||12336===t)||yr["CJK Unified Ideographs Extension A"](t)||yr["CJK Unified Ideographs"](t)||yr["Enclosed CJK Letters and Months"](t)||yr["Hangul Compatibility Jamo"](t)||yr["Hangul Jamo Extended-A"](t)||yr["Hangul Jamo Extended-B"](t)||yr["Hangul Jamo"](t)||yr["Hangul Syllables"](t)||yr.Hiragana(t)||yr["Ideographic Description Characters"](t)||yr.Kanbun(t)||yr["Kangxi Radicals"](t)||yr["Katakana Phonetic Extensions"](t)||yr.Katakana(t)&&12540!==t||!(!yr["Halfwidth and Fullwidth Forms"](t)||65288===t||65289===t||65293===t||t>=65306&&t<=65310||65339===t||65341===t||65343===t||t>=65371&&t<=65503||65507===t||t>=65512&&t<=65519)||!(!yr["Small Form Variants"](t)||t>=65112&&t<=65118||t>=65123&&t<=65126)||yr["Unified Canadian Aboriginal Syllabics"](t)||yr["Unified Canadian Aboriginal Syllabics Extended"](t)||yr["Vertical Forms"](t)||yr["Yijing Hexagram Symbols"](t)||yr["Yi Syllables"](t)||yr["Yi Radicals"](t)))}function wr(t){return!(_r(t)||function(t){return!!(yr["Latin-1 Supplement"](t)&&(167===t||169===t||174===t||177===t||188===t||189===t||190===t||215===t||247===t)||yr["General Punctuation"](t)&&(8214===t||8224===t||8225===t||8240===t||8241===t||8251===t||8252===t||8258===t||8263===t||8264===t||8265===t||8273===t)||yr["Letterlike Symbols"](t)||yr["Number Forms"](t)||yr["Miscellaneous Technical"](t)&&(t>=8960&&t<=8967||t>=8972&&t<=8991||t>=8996&&t<=9e3||9003===t||t>=9085&&t<=9114||t>=9150&&t<=9165||9167===t||t>=9169&&t<=9179||t>=9186&&t<=9215)||yr["Control Pictures"](t)&&9251!==t||yr["Optical Character Recognition"](t)||yr["Enclosed Alphanumerics"](t)||yr["Geometric Shapes"](t)||yr["Miscellaneous Symbols"](t)&&!(t>=9754&&t<=9759)||yr["Miscellaneous Symbols and Arrows"](t)&&(t>=11026&&t<=11055||t>=11088&&t<=11097||t>=11192&&t<=11243)||yr["CJK Symbols and Punctuation"](t)||yr.Katakana(t)||yr["Private Use Area"](t)||yr["CJK Compatibility Forms"](t)||yr["Small Form Variants"](t)||yr["Halfwidth and Fullwidth Forms"](t)||8734===t||8756===t||8757===t||t>=9984&&t<=10087||t>=10102&&t<=10131||65532===t||65533===t)}(t))}function kr(t,e){return!(!e&&(t>=1424&&t<=2303||yr["Arabic Presentation Forms-A"](t)||yr["Arabic Presentation Forms-B"](t))||t>=2304&&t<=3583||t>=3840&&t<=4255||yr.Khmer(t))}var Mr,Ar=!1,Tr=null,Sr=!1,Er=new O,Cr={applyArabicShaping:null,processBidirectionalText:null,isLoaded:function(){return Sr||null!=Cr.applyArabicShaping}},Lr=function(t,e){this.zoom=t,e?(this.now=e.now,this.fadeDuration=e.fadeDuration,this.zoomHistory=e.zoomHistory,this.transition=e.transition):(this.now=0,this.fadeDuration=0,this.zoomHistory=new vr,this.transition={})};Lr.prototype.isSupportedScript=function(t){return function(t,e){for(var r=0,n=t;rthis.end)return this.prior=null,r;if(this.value.isDataDriven())return this.prior=null,r;if(e=1)return 1;var e=i*i,r=e*i;return 4*(i<.5?r:3*(i-e)+r-.75)}())}return r};var Dr=function(t){this._properties=t,this._values=Object.create(t.defaultTransitioningPropertyValues)};Dr.prototype.possiblyEvaluate=function(t){for(var e=new Fr(this._properties),r=0,n=Object.keys(this._values);rn.zoomHistory.lastIntegerZoom?{from:t,to:e,fromScale:2,toScale:1,t:a+(1-a)*o}:{from:r,to:e,fromScale:.5,toScale:1,t:1-(1-o)*a}},Vr.prototype.interpolate=function(t){return t};var Ur=function(t){this.specification=t};Ur.prototype.possiblyEvaluate=function(t,e){return!!t.expression.evaluate(e)},Ur.prototype.interpolate=function(){return!1};var qr=function(t){for(var e in this.properties=t,this.defaultPropertyValues={},this.defaultTransitionablePropertyValues={},this.defaultTransitioningPropertyValues={},this.defaultPossiblyEvaluatedValues={},t){var r=t[e],n=this.defaultPropertyValues[e]=new zr(r,void 0),i=this.defaultTransitionablePropertyValues[e]=new Or(r);this.defaultTransitioningPropertyValues[e]=i.untransitioned(),this.defaultPossiblyEvaluatedValues[e]=n.possiblyEvaluate({})}};pr("DataDrivenProperty",jr),pr("DataConstantProperty",Nr),pr("CrossFadedProperty",Vr),pr("ColorRampProperty",Ur);var Hr=function(t){function e(e,r){for(var n in t.call(this),this.id=e.id,this.metadata=e.metadata,this.type=e.type,this.minzoom=e.minzoom,this.maxzoom=e.maxzoom,this.visibility="visible","background"!==e.type&&(this.source=e.source,this.sourceLayer=e["source-layer"],this.filter=e.filter),this._featureFilter=function(){return!0},r.layout&&(this._unevaluatedLayout=new Rr(r.layout)),this._transitionablePaint=new Ir(r.paint),e.paint)this.setPaintProperty(n,e.paint[n],{validate:!1});for(var i in e.layout)this.setLayoutProperty(i,e.layout[i],{validate:!1});this._transitioningPaint=this._transitionablePaint.untransitioned()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getLayoutProperty=function(t){return"visibility"===t?this.visibility:this._unevaluatedLayout.getValue(t)},e.prototype.setLayoutProperty=function(t,e,r){if(null!=e){var n="layers."+this.id+".layout."+t;if(this._validate(or,n,t,e,r))return}"visibility"!==t?this._unevaluatedLayout.setValue(t,e):this.visibility="none"===e?e:"visible"},e.prototype.getPaintProperty=function(t){return g(t,"-transition")?this._transitionablePaint.getTransition(t.slice(0,-"-transition".length)):this._transitionablePaint.getValue(t)},e.prototype.setPaintProperty=function(t,e,r){if(null!=e){var n="layers."+this.id+".paint."+t;if(this._validate(ar,n,t,e,r))return}g(t,"-transition")?this._transitionablePaint.setTransition(t.slice(0,-"-transition".length),e||void 0):this._transitionablePaint.setValue(t,e)},e.prototype.isHidden=function(t){return!!(this.minzoom&&t=this.maxzoom)||"none"===this.visibility},e.prototype.updateTransitions=function(t){this._transitioningPaint=this._transitionablePaint.transitioned(t,this._transitioningPaint)},e.prototype.hasTransition=function(){return this._transitioningPaint.hasTransition()},e.prototype.recalculate=function(t){this._unevaluatedLayout&&(this.layout=this._unevaluatedLayout.possiblyEvaluate(t)),this.paint=this._transitioningPaint.possiblyEvaluate(t)},e.prototype.serialize=function(){var t={id:this.id,type:this.type,source:this.source,"source-layer":this.sourceLayer,metadata:this.metadata,minzoom:this.minzoom,maxzoom:this.maxzoom,filter:this.filter,layout:this._unevaluatedLayout&&this._unevaluatedLayout.serialize(),paint:this._transitionablePaint&&this._transitionablePaint.serialize()};return"none"===this.visibility&&(t.layout=t.layout||{},t.layout.visibility="none"),y(t,function(t,e){return!(void 0===t||"layout"===e&&!Object.keys(t).length||"paint"===e&&!Object.keys(t).length)})},e.prototype._validate=function(t,e,r,n,i){return(!i||!1!==i.validate)&&sr(this,t.call(nr,{key:e,layerType:this.type,objectKey:r,value:n,styleSpec:I,style:{glyphs:!0,sprite:!0}}))},e.prototype.hasOffscreenPass=function(){return!1},e.prototype.resize=function(){},e}(O),Gr={Int8:Int8Array,Uint8:Uint8Array,Int16:Int16Array,Uint16:Uint16Array,Int32:Int32Array,Uint32:Uint32Array,Float32:Float32Array},Wr=function(t,e){this._structArray=t,this._pos1=e*this.size,this._pos2=this._pos1/2,this._pos4=this._pos1/4,this._pos8=this._pos1/8},Yr=function(){this.isTransferred=!1,this.capacity=-1,this.resize(0)};function Xr(t,e){void 0===e&&(e=1);var r=0,n=0;return{members:t.map(function(t){var i,a=(i=t.type,Gr[i].BYTES_PER_ELEMENT),o=r=Zr(r,Math.max(e,a)),s=t.components||1;return n=Math.max(n,a),r+=a*s,{name:t.name,type:t.type,components:s,offset:o}}),size:Zr(r,Math.max(n,e)),alignment:e}}function Zr(t,e){return Math.ceil(t/e)*e}Yr.serialize=function(t,e){return t._trim(),e&&(t.isTransferred=!0,e.push(t.arrayBuffer)),{length:t.length,arrayBuffer:t.arrayBuffer}},Yr.deserialize=function(t){var e=Object.create(this.prototype);return e.arrayBuffer=t.arrayBuffer,e.length=t.length,e.capacity=t.arrayBuffer.byteLength/e.bytesPerElement,e._refreshViews(),e},Yr.prototype._trim=function(){this.length!==this.capacity&&(this.capacity=this.length,this.arrayBuffer=this.arrayBuffer.slice(0,this.length*this.bytesPerElement),this._refreshViews())},Yr.prototype.clear=function(){this.length=0},Yr.prototype.resize=function(t){this.reserve(t),this.length=t},Yr.prototype.reserve=function(t){if(t>this.capacity){this.capacity=Math.max(t,Math.floor(5*this.capacity),128),this.arrayBuffer=new ArrayBuffer(this.capacity*this.bytesPerElement);var e=this.uint8;this._refreshViews(),e&&this.uint8.set(e)}},Yr.prototype._refreshViews=function(){throw new Error("_refreshViews() must be implemented by each concrete StructArray layout")};var $r=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.int16[n+0]=t,this.int16[n+1]=e,r},e}(Yr);$r.prototype.bytesPerElement=4,pr("StructArrayLayout2i4",$r);var Jr=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;this.resize(i+1);var a=4*i;return this.int16[a+0]=t,this.int16[a+1]=e,this.int16[a+2]=r,this.int16[a+3]=n,i},e}(Yr);Jr.prototype.bytesPerElement=8,pr("StructArrayLayout4i8",Jr);var Kr=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a){var o=this.length;this.resize(o+1);var s=6*o;return this.int16[s+0]=t,this.int16[s+1]=e,this.int16[s+2]=r,this.int16[s+3]=n,this.int16[s+4]=i,this.int16[s+5]=a,o},e}(Yr);Kr.prototype.bytesPerElement=12,pr("StructArrayLayout2i4i12",Kr);var Qr=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s){var l=this.length;this.resize(l+1);var c=6*l,u=12*l;return this.int16[c+0]=t,this.int16[c+1]=e,this.int16[c+2]=r,this.int16[c+3]=n,this.uint8[u+8]=i,this.uint8[u+9]=a,this.uint8[u+10]=o,this.uint8[u+11]=s,l},e}(Yr);Qr.prototype.bytesPerElement=12,pr("StructArrayLayout4i4ub12",Qr);var tn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s){var l=this.length;this.resize(l+1);var c=8*l;return this.int16[c+0]=t,this.int16[c+1]=e,this.int16[c+2]=r,this.int16[c+3]=n,this.uint16[c+4]=i,this.uint16[c+5]=a,this.uint16[c+6]=o,this.uint16[c+7]=s,l},e}(Yr);tn.prototype.bytesPerElement=16,pr("StructArrayLayout4i4ui16",tn);var en=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.float32[i+0]=t,this.float32[i+1]=e,this.float32[i+2]=r,n},e}(Yr);en.prototype.bytesPerElement=12,pr("StructArrayLayout3f12",en);var rn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t){var e=this.length;this.resize(e+1);var r=1*e;return this.uint32[r+0]=t,e},e}(Yr);rn.prototype.bytesPerElement=4,pr("StructArrayLayout1ul4",rn);var nn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s,l,c,u){var f=this.length;this.resize(f+1);var h=12*f,p=6*f;return this.int16[h+0]=t,this.int16[h+1]=e,this.int16[h+2]=r,this.int16[h+3]=n,this.int16[h+4]=i,this.int16[h+5]=a,this.uint32[p+3]=o,this.uint16[h+8]=s,this.uint16[h+9]=l,this.int16[h+10]=c,this.int16[h+11]=u,f},e}(Yr);nn.prototype.bytesPerElement=24,pr("StructArrayLayout6i1ul2ui2i24",nn);var an=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a){var o=this.length;this.resize(o+1);var s=6*o;return this.int16[s+0]=t,this.int16[s+1]=e,this.int16[s+2]=r,this.int16[s+3]=n,this.int16[s+4]=i,this.int16[s+5]=a,o},e}(Yr);an.prototype.bytesPerElement=12,pr("StructArrayLayout2i2i2i12",an);var on=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=4*r;return this.uint8[n+0]=t,this.uint8[n+1]=e,r},e}(Yr);on.prototype.bytesPerElement=4,pr("StructArrayLayout2ub4",on);var sn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s,l,c,u,f,h,p){var d=this.length;this.resize(d+1);var m=20*d,g=10*d,v=40*d;return this.int16[m+0]=t,this.int16[m+1]=e,this.uint16[m+2]=r,this.uint16[m+3]=n,this.uint32[g+2]=i,this.uint32[g+3]=a,this.uint32[g+4]=o,this.uint16[m+10]=s,this.uint16[m+11]=l,this.uint16[m+12]=c,this.float32[g+7]=u,this.float32[g+8]=f,this.uint8[v+36]=h,this.uint8[v+37]=p,d},e}(Yr);sn.prototype.bytesPerElement=40,pr("StructArrayLayout2i2ui3ul3ui2f2ub40",sn);var ln=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t){var e=this.length;this.resize(e+1);var r=1*e;return this.float32[r+0]=t,e},e}(Yr);ln.prototype.bytesPerElement=4,pr("StructArrayLayout1f4",ln);var cn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.int16[i+0]=t,this.int16[i+1]=e,this.int16[i+2]=r,n},e}(Yr);cn.prototype.bytesPerElement=6,pr("StructArrayLayout3i6",cn);var un=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=2*n,a=4*n;return this.uint32[i+0]=t,this.uint16[a+2]=e,this.uint16[a+3]=r,n},e}(Yr);un.prototype.bytesPerElement=8,pr("StructArrayLayout1ul2ui8",un);var fn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r){var n=this.length;this.resize(n+1);var i=3*n;return this.uint16[i+0]=t,this.uint16[i+1]=e,this.uint16[i+2]=r,n},e}(Yr);fn.prototype.bytesPerElement=6,pr("StructArrayLayout3ui6",fn);var hn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.uint16[n+0]=t,this.uint16[n+1]=e,r},e}(Yr);hn.prototype.bytesPerElement=4,pr("StructArrayLayout2ui4",hn);var pn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e){var r=this.length;this.resize(r+1);var n=2*r;return this.float32[n+0]=t,this.float32[n+1]=e,r},e}(Yr);pn.prototype.bytesPerElement=8,pr("StructArrayLayout2f8",pn);var dn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer)},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;this.resize(i+1);var a=4*i;return this.float32[a+0]=t,this.float32[a+1]=e,this.float32[a+2]=r,this.float32[a+3]=n,i},e}(Yr);dn.prototype.bytesPerElement=16,pr("StructArrayLayout4f16",dn);var mn=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorPointX:{configurable:!0},anchorPointY:{configurable:!0},x1:{configurable:!0},y1:{configurable:!0},x2:{configurable:!0},y2:{configurable:!0},featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0},radius:{configurable:!0},signedDistanceFromAnchor:{configurable:!0},anchorPoint:{configurable:!0}};return r.anchorPointX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorPointX.set=function(t){this._structArray.int16[this._pos2+0]=t},r.anchorPointY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorPointY.set=function(t){this._structArray.int16[this._pos2+1]=t},r.x1.get=function(){return this._structArray.int16[this._pos2+2]},r.x1.set=function(t){this._structArray.int16[this._pos2+2]=t},r.y1.get=function(){return this._structArray.int16[this._pos2+3]},r.y1.set=function(t){this._structArray.int16[this._pos2+3]=t},r.x2.get=function(){return this._structArray.int16[this._pos2+4]},r.x2.set=function(t){this._structArray.int16[this._pos2+4]=t},r.y2.get=function(){return this._structArray.int16[this._pos2+5]},r.y2.set=function(t){this._structArray.int16[this._pos2+5]=t},r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+8]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+8]=t},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+9]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+9]=t},r.radius.get=function(){return this._structArray.int16[this._pos2+10]},r.radius.set=function(t){this._structArray.int16[this._pos2+10]=t},r.signedDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+11]},r.signedDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+11]=t},r.anchorPoint.get=function(){return new l(this.anchorPointX,this.anchorPointY)},Object.defineProperties(e.prototype,r),e}(Wr);mn.prototype.size=24;var gn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new mn(this,t)},e}(nn);pr("CollisionBoxArray",gn);var vn=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorX:{configurable:!0},anchorY:{configurable:!0},glyphStartIndex:{configurable:!0},numGlyphs:{configurable:!0},vertexStartIndex:{configurable:!0},lineStartIndex:{configurable:!0},lineLength:{configurable:!0},segment:{configurable:!0},lowerSize:{configurable:!0},upperSize:{configurable:!0},lineOffsetX:{configurable:!0},lineOffsetY:{configurable:!0},writingMode:{configurable:!0},hidden:{configurable:!0}};return r.anchorX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorX.set=function(t){this._structArray.int16[this._pos2+0]=t},r.anchorY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorY.set=function(t){this._structArray.int16[this._pos2+1]=t},r.glyphStartIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.glyphStartIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t},r.numGlyphs.get=function(){return this._structArray.uint16[this._pos2+3]},r.numGlyphs.set=function(t){this._structArray.uint16[this._pos2+3]=t},r.vertexStartIndex.get=function(){return this._structArray.uint32[this._pos4+2]},r.vertexStartIndex.set=function(t){this._structArray.uint32[this._pos4+2]=t},r.lineStartIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.lineStartIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t},r.lineLength.get=function(){return this._structArray.uint32[this._pos4+4]},r.lineLength.set=function(t){this._structArray.uint32[this._pos4+4]=t},r.segment.get=function(){return this._structArray.uint16[this._pos2+10]},r.segment.set=function(t){this._structArray.uint16[this._pos2+10]=t},r.lowerSize.get=function(){return this._structArray.uint16[this._pos2+11]},r.lowerSize.set=function(t){this._structArray.uint16[this._pos2+11]=t},r.upperSize.get=function(){return this._structArray.uint16[this._pos2+12]},r.upperSize.set=function(t){this._structArray.uint16[this._pos2+12]=t},r.lineOffsetX.get=function(){return this._structArray.float32[this._pos4+7]},r.lineOffsetX.set=function(t){this._structArray.float32[this._pos4+7]=t},r.lineOffsetY.get=function(){return this._structArray.float32[this._pos4+8]},r.lineOffsetY.set=function(t){this._structArray.float32[this._pos4+8]=t},r.writingMode.get=function(){return this._structArray.uint8[this._pos1+36]},r.writingMode.set=function(t){this._structArray.uint8[this._pos1+36]=t},r.hidden.get=function(){return this._structArray.uint8[this._pos1+37]},r.hidden.set=function(t){this._structArray.uint8[this._pos1+37]=t},Object.defineProperties(e.prototype,r),e}(Wr);vn.prototype.size=40;var yn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new vn(this,t)},e}(sn);pr("PlacedSymbolArray",yn);var xn=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={offsetX:{configurable:!0}};return r.offsetX.get=function(){return this._structArray.float32[this._pos4+0]},r.offsetX.set=function(t){this._structArray.float32[this._pos4+0]=t},Object.defineProperties(e.prototype,r),e}(Wr);xn.prototype.size=4;var bn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getoffsetX=function(t){return this.float32[1*t+0]},e.prototype.get=function(t){return new xn(this,t)},e}(ln);pr("GlyphOffsetArray",bn);var _n=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={x:{configurable:!0},y:{configurable:!0},tileUnitDistanceFromAnchor:{configurable:!0}};return r.x.get=function(){return this._structArray.int16[this._pos2+0]},r.x.set=function(t){this._structArray.int16[this._pos2+0]=t},r.y.get=function(){return this._structArray.int16[this._pos2+1]},r.y.set=function(t){this._structArray.int16[this._pos2+1]=t},r.tileUnitDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+2]},r.tileUnitDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+2]=t},Object.defineProperties(e.prototype,r),e}(Wr);_n.prototype.size=6;var wn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getx=function(t){return this.int16[3*t+0]},e.prototype.gety=function(t){return this.int16[3*t+1]},e.prototype.gettileUnitDistanceFromAnchor=function(t){return this.int16[3*t+2]},e.prototype.get=function(t){return new _n(this,t)},e}(cn);pr("SymbolLineVertexArray",wn);var kn=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0}};return r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+0]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+0]=t},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+3]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+3]=t},Object.defineProperties(e.prototype,r),e}(Wr);kn.prototype.size=8;var Mn=function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new kn(this,t)},e}(un);pr("FeatureIndexArray",Mn);var An=Xr([{name:"a_pos",components:2,type:"Int16"}],4).members,Tn=function(t){void 0===t&&(t=[]),this.segments=t};Tn.prototype.prepareSegment=function(t,e,r){var n=this.segments[this.segments.length-1];return t>Tn.MAX_VERTEX_ARRAY_LENGTH&&_("Max vertices per segment is "+Tn.MAX_VERTEX_ARRAY_LENGTH+": bucket requested "+t),(!n||n.vertexLength+t>Tn.MAX_VERTEX_ARRAY_LENGTH)&&(n={vertexOffset:e.length,primitiveOffset:r.length,vertexLength:0,primitiveLength:0},this.segments.push(n)),n},Tn.prototype.get=function(){return this.segments},Tn.prototype.destroy=function(){for(var t=0,e=this.segments;tRn.max||o.yRn.max)&&_("Geometry exceeds allowed extent, reduce your vector tile buffer size")}return r}function Fn(t,e,r,n,i){t.emplaceBack(2*e+(n+1)/2,2*r+(i+1)/2)}var Nn=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.layoutVertexArray=new $r,this.indexArray=new fn,this.segments=new Tn,this.programConfigurations=new In(An,t.layers,t.zoom)};function jn(t,e,r){for(var n=0;n=3)for(var s=0;s1){if(Hn(t,e))return!0;for(var n=0;n1?t.distSqr(r):t.distSqr(r.sub(e)._mult(i)._add(e))}function Xn(t,e){for(var r,n,i,a=!1,o=0;oe.y!=i.y>e.y&&e.x<(i.x-n.x)*(e.y-n.y)/(i.y-n.y)+n.x&&(a=!a);return a}function Zn(t,e){for(var r=!1,n=0,i=t.length-1;ne.y!=o.y>e.y&&e.x<(o.x-a.x)*(e.y-a.y)/(o.y-a.y)+a.x&&(r=!r)}return r}function $n(t,e,r){var n=e.paint.get(t).value;return"constant"===n.kind?n.value:r.programConfigurations.get(e.id).binders[t].statistics.max}function Jn(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])}function Kn(t,e,r,n,i){if(!e[0]&&!e[1])return t;var a=l.convert(e);"viewport"===r&&a._rotate(-n);for(var o=[],s=0;s=Dn||l<0||l>=Dn)){var c=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray),u=c.vertexLength;Fn(this.layoutVertexArray,s,l,-1,-1),Fn(this.layoutVertexArray,s,l,1,-1),Fn(this.layoutVertexArray,s,l,1,1),Fn(this.layoutVertexArray,s,l,-1,1),this.indexArray.emplaceBack(u,u+1,u+2),this.indexArray.emplaceBack(u,u+3,u+2),c.vertexLength+=4,c.primitiveLength+=2}}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,t)},pr("CircleBucket",Nn,{omit:["layers"]});var Qn={paint:new qr({"circle-radius":new jr(I.paint_circle["circle-radius"]),"circle-color":new jr(I.paint_circle["circle-color"]),"circle-blur":new jr(I.paint_circle["circle-blur"]),"circle-opacity":new jr(I.paint_circle["circle-opacity"]),"circle-translate":new Nr(I.paint_circle["circle-translate"]),"circle-translate-anchor":new Nr(I.paint_circle["circle-translate-anchor"]),"circle-pitch-scale":new Nr(I.paint_circle["circle-pitch-scale"]),"circle-pitch-alignment":new Nr(I.paint_circle["circle-pitch-alignment"]),"circle-stroke-width":new jr(I.paint_circle["circle-stroke-width"]),"circle-stroke-color":new jr(I.paint_circle["circle-stroke-color"]),"circle-stroke-opacity":new jr(I.paint_circle["circle-stroke-opacity"])})},ti=i(function(t,e){var r;t.exports=((r=new Float32Array(3))[0]=0,r[1]=0,r[2]=0,function(){var t=new Float32Array(4);t[0]=0,t[1]=0,t[2]=0,t[3]=0}(),{vec3:{transformMat3:function(t,e,r){var n=e[0],i=e[1],a=e[2];return t[0]=n*r[0]+i*r[3]+a*r[6],t[1]=n*r[1]+i*r[4]+a*r[7],t[2]=n*r[2]+i*r[5]+a*r[8],t}},vec4:{transformMat4:function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3];return t[0]=r[0]*n+r[4]*i+r[8]*a+r[12]*o,t[1]=r[1]*n+r[5]*i+r[9]*a+r[13]*o,t[2]=r[2]*n+r[6]*i+r[10]*a+r[14]*o,t[3]=r[3]*n+r[7]*i+r[11]*a+r[15]*o,t}},mat2:{create:function(){var t=new Float32Array(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},rotate:function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3],s=Math.sin(r),l=Math.cos(r);return t[0]=n*l+a*s,t[1]=i*l+o*s,t[2]=n*-s+a*l,t[3]=i*-s+o*l,t},scale:function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3],s=r[0],l=r[1];return t[0]=n*s,t[1]=i*s,t[2]=a*l,t[3]=o*l,t}},mat3:{create:function(){var t=new Float32Array(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromRotation:function(t,e){var r=Math.sin(e),n=Math.cos(e);return t[0]=n,t[1]=r,t[2]=0,t[3]=-r,t[4]=n,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}},mat4:{create:function(){var t=new Float32Array(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},translate:function(t,e,r){var n,i,a,o,s,l,c,u,f,h,p,d,m=r[0],g=r[1],v=r[2];return e===t?(t[12]=e[0]*m+e[4]*g+e[8]*v+e[12],t[13]=e[1]*m+e[5]*g+e[9]*v+e[13],t[14]=e[2]*m+e[6]*g+e[10]*v+e[14],t[15]=e[3]*m+e[7]*g+e[11]*v+e[15]):(n=e[0],i=e[1],a=e[2],o=e[3],s=e[4],l=e[5],c=e[6],u=e[7],f=e[8],h=e[9],p=e[10],d=e[11],t[0]=n,t[1]=i,t[2]=a,t[3]=o,t[4]=s,t[5]=l,t[6]=c,t[7]=u,t[8]=f,t[9]=h,t[10]=p,t[11]=d,t[12]=n*m+s*g+f*v+e[12],t[13]=i*m+l*g+h*v+e[13],t[14]=a*m+c*g+p*v+e[14],t[15]=o*m+u*g+d*v+e[15]),t},scale:function(t,e,r){var n=r[0],i=r[1],a=r[2];return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t[3]=e[3]*n,t[4]=e[4]*i,t[5]=e[5]*i,t[6]=e[6]*i,t[7]=e[7]*i,t[8]=e[8]*a,t[9]=e[9]*a,t[10]=e[10]*a,t[11]=e[11]*a,t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t},multiply:function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3],s=e[4],l=e[5],c=e[6],u=e[7],f=e[8],h=e[9],p=e[10],d=e[11],m=e[12],g=e[13],v=e[14],y=e[15],x=r[0],b=r[1],_=r[2],w=r[3];return t[0]=x*n+b*s+_*f+w*m,t[1]=x*i+b*l+_*h+w*g,t[2]=x*a+b*c+_*p+w*v,t[3]=x*o+b*u+_*d+w*y,x=r[4],b=r[5],_=r[6],w=r[7],t[4]=x*n+b*s+_*f+w*m,t[5]=x*i+b*l+_*h+w*g,t[6]=x*a+b*c+_*p+w*v,t[7]=x*o+b*u+_*d+w*y,x=r[8],b=r[9],_=r[10],w=r[11],t[8]=x*n+b*s+_*f+w*m,t[9]=x*i+b*l+_*h+w*g,t[10]=x*a+b*c+_*p+w*v,t[11]=x*o+b*u+_*d+w*y,x=r[12],b=r[13],_=r[14],w=r[15],t[12]=x*n+b*s+_*f+w*m,t[13]=x*i+b*l+_*h+w*g,t[14]=x*a+b*c+_*p+w*v,t[15]=x*o+b*u+_*d+w*y,t},perspective:function(t,e,r,n,i){var a=1/Math.tan(e/2),o=1/(n-i);return t[0]=a/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=a,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(i+n)*o,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*i*n*o,t[15]=0,t},rotateX:function(t,e,r){var n=Math.sin(r),i=Math.cos(r),a=e[4],o=e[5],s=e[6],l=e[7],c=e[8],u=e[9],f=e[10],h=e[11];return e!==t&&(t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[4]=a*i+c*n,t[5]=o*i+u*n,t[6]=s*i+f*n,t[7]=l*i+h*n,t[8]=c*i-a*n,t[9]=u*i-o*n,t[10]=f*i-s*n,t[11]=h*i-l*n,t},rotateZ:function(t,e,r){var n=Math.sin(r),i=Math.cos(r),a=e[0],o=e[1],s=e[2],l=e[3],c=e[4],u=e[5],f=e[6],h=e[7];return e!==t&&(t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[0]=a*i+c*n,t[1]=o*i+u*n,t[2]=s*i+f*n,t[3]=l*i+h*n,t[4]=c*i-a*n,t[5]=u*i-o*n,t[6]=f*i-s*n,t[7]=h*i-l*n,t},invert:function(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=e[4],s=e[5],l=e[6],c=e[7],u=e[8],f=e[9],h=e[10],p=e[11],d=e[12],m=e[13],g=e[14],v=e[15],y=r*s-n*o,x=r*l-i*o,b=r*c-a*o,_=n*l-i*s,w=n*c-a*s,k=i*c-a*l,M=u*m-f*d,A=u*g-h*d,T=u*v-p*d,S=f*g-h*m,E=f*v-p*m,C=h*v-p*g,L=y*C-x*E+b*S+_*T-w*A+k*M;return L?(L=1/L,t[0]=(s*C-l*E+c*S)*L,t[1]=(i*E-n*C-a*S)*L,t[2]=(m*k-g*w+v*_)*L,t[3]=(h*w-f*k-p*_)*L,t[4]=(l*T-o*C-c*A)*L,t[5]=(r*C-i*T+a*A)*L,t[6]=(g*b-d*k-v*x)*L,t[7]=(u*k-h*b+p*x)*L,t[8]=(o*E-s*T+c*M)*L,t[9]=(n*T-r*E-a*M)*L,t[10]=(d*w-m*b+v*y)*L,t[11]=(f*b-u*w-p*y)*L,t[12]=(s*A-o*S-l*M)*L,t[13]=(r*S-n*A+i*M)*L,t[14]=(m*x-d*_-g*y)*L,t[15]=(u*_-f*x+h*y)*L,t):null},ortho:function(t,e,r,n,i,a,o){var s=1/(e-r),l=1/(n-i),c=1/(a-o);return t[0]=-2*s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*l,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(e+r)*s,t[13]=(i+n)*l,t[14]=(o+a)*c,t[15]=1,t}}})}),ei=(ti.vec3,ti.vec4),ri=(ti.mat2,ti.mat3,ti.mat4),ni=function(t){function e(e){t.call(this,e,Qn)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.createBucket=function(t){return new Nn(t)},e.prototype.queryRadius=function(t){var e=t;return $n("circle-radius",this,e)+$n("circle-stroke-width",this,e)+Jn(this.paint.get("circle-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,i,a,o){for(var s=Kn(t,this.paint.get("circle-translate"),this.paint.get("circle-translate-anchor"),i.angle,a),l=this.paint.get("circle-radius").evaluate(e)+this.paint.get("circle-stroke-width").evaluate(e),c="map"===this.paint.get("circle-pitch-alignment"),u=c?s:function(t,e,r){return s.map(function(t){return t.map(function(t){return ii(t,e,r)})})}(0,o,i),f=c?l*a:l,h=0,p=r;ht.width||i.height>t.height||r.x>t.width-i.width||r.y>t.height-i.height)throw new RangeError("out of range source coordinates for image copy");if(i.width>e.width||i.height>e.height||n.x>e.width-i.width||n.y>e.height-i.height)throw new RangeError("out of range destination coordinates for image copy");for(var o=t.data,s=e.data,l=0;l80*r){n=a=t[0],i=o=t[1];for(var d=r;da&&(a=s),l>o&&(o=l);c=0!==(c=Math.max(a-n,o-i))?1/c:0}return wi(h,p,r,n,i,c),p}function bi(t,e,r,n,i){var a,o;if(i===Vi(t,e,r,n)>0)for(a=e;a=e;a-=n)o=Fi(a,t[a],t[a+1],o);return o&&Pi(o,o.next)&&(Ni(o),o=o.next),o}function _i(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!Pi(n,n.next)&&0!==Ii(n.prev,n,n.next))n=n.next;else{if(Ni(n),(n=e=n.prev)===n.next)break;r=!0}}while(r||n!==e);return e}function wi(t,e,r,n,i,a,o){if(t){!o&&a&&function(t,e,r,n){var i=t;do{null===i.z&&(i.z=Ci(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,function(t){var e,r,n,i,a,o,s,l,c=1;do{for(r=t,t=null,a=null,o=0;r;){for(o++,n=r,s=0,e=0;e0||l>0&&n;)0!==s&&(0===l||!n||r.z<=n.z)?(i=r,r=r.nextZ,s--):(i=n,n=n.nextZ,l--),a?a.nextZ=i:t=i,i.prevZ=a,a=i;r=n}a.nextZ=null,c*=2}while(o>1)}(i)}(t,n,i,a);for(var s,l,c=t;t.prev!==t.next;)if(s=t.prev,l=t.next,a?Mi(t,n,i,a):ki(t))e.push(s.i/r),e.push(t.i/r),e.push(l.i/r),Ni(t),t=l.next,c=l.next;else if((t=l)===c){o?1===o?wi(t=Ai(t,e,r),e,r,n,i,a,2):2===o&&Ti(t,e,r,n,i,a):wi(_i(t),e,r,n,i,a,1);break}}}function ki(t){var e=t.prev,r=t,n=t.next;if(Ii(e,r,n)>=0)return!1;for(var i=t.next.next;i!==t.prev;){if(zi(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&Ii(i.prev,i,i.next)>=0)return!1;i=i.next}return!0}function Mi(t,e,r,n){var i=t.prev,a=t,o=t.next;if(Ii(i,a,o)>=0)return!1;for(var s=i.xa.x?i.x>o.x?i.x:o.x:a.x>o.x?a.x:o.x,u=i.y>a.y?i.y>o.y?i.y:o.y:a.y>o.y?a.y:o.y,f=Ci(s,l,e,r,n),h=Ci(c,u,e,r,n),p=t.prevZ,d=t.nextZ;p&&p.z>=f&&d&&d.z<=h;){if(p!==t.prev&&p!==t.next&&zi(i.x,i.y,a.x,a.y,o.x,o.y,p.x,p.y)&&Ii(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,d!==t.prev&&d!==t.next&&zi(i.x,i.y,a.x,a.y,o.x,o.y,d.x,d.y)&&Ii(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(;p&&p.z>=f;){if(p!==t.prev&&p!==t.next&&zi(i.x,i.y,a.x,a.y,o.x,o.y,p.x,p.y)&&Ii(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;d&&d.z<=h;){if(d!==t.prev&&d!==t.next&&zi(i.x,i.y,a.x,a.y,o.x,o.y,d.x,d.y)&&Ii(d.prev,d,d.next)>=0)return!1;d=d.nextZ}return!0}function Ai(t,e,r){var n=t;do{var i=n.prev,a=n.next.next;!Pi(i,a)&&Di(i,n,n.next,a)&&Ri(i,a)&&Ri(a,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(a.i/r),Ni(n),Ni(n.next),n=t=a),n=n.next}while(n!==t);return n}function Ti(t,e,r,n,i,a){var o=t;do{for(var s=o.next.next;s!==o.prev;){if(o.i!==s.i&&Oi(o,s)){var l=Bi(o,s);return o=_i(o,o.next),l=_i(l,l.next),wi(o,e,r,n,i,a),void wi(l,e,r,n,i,a)}s=s.next}o=o.next}while(o!==t)}function Si(t,e){return t.x-e.x}function Ei(t,e){if(e=function(t,e){var r,n=e,i=t.x,a=t.y,o=-1/0;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){var s=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(s<=i&&s>o){if(o=s,s===i){if(a===n.y)return n;if(a===n.next.y)return n.next}r=n.x=n.x&&n.x>=u&&i!==n.x&&zi(ar.x)&&Ri(n,t)&&(r=n,h=l),n=n.next;return r}(t,e)){var r=Bi(e,t);_i(r,r.next)}}function Ci(t,e,r,n,i){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*i)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*i)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Li(t){var e=t,r=t;do{e.x=0&&(t-o)*(n-s)-(r-o)*(e-s)>=0&&(r-o)*(a-s)-(i-o)*(n-s)>=0}function Oi(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&Di(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}(t,e)&&Ri(t,e)&&Ri(e,t)&&function(t,e){var r=t,n=!1,i=(t.x+e.x)/2,a=(t.y+e.y)/2;do{r.y>a!=r.next.y>a&&r.next.y!==r.y&&i<(r.next.x-r.x)*(a-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next}while(r!==t);return n}(t,e)}function Ii(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function Pi(t,e){return t.x===e.x&&t.y===e.y}function Di(t,e,r,n){return!!(Pi(t,e)&&Pi(r,n)||Pi(t,n)&&Pi(r,e))||Ii(t,e,r)>0!=Ii(t,e,n)>0&&Ii(r,n,t)>0!=Ii(r,n,e)>0}function Ri(t,e){return Ii(t.prev,t,t.next)<0?Ii(t,e,t.next)>=0&&Ii(t,t.prev,e)>=0:Ii(t,e,t.prev)<0||Ii(t,t.next,e)<0}function Bi(t,e){var r=new ji(t.i,t.x,t.y),n=new ji(e.i,e.x,e.y),i=t.next,a=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,a.next=n,n.prev=a,n}function Fi(t,e,r,n){var i=new ji(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function Ni(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function ji(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}function Vi(t,e,r,n){for(var i=0,a=e,o=r-n;a0&&(n+=t[i-1].length,r.holes.push(n))}return r},vi.default=yi;var Ui=Hi,qi=Hi;function Hi(t,e,r,n,i){!function t(e,r,n,i,a){for(;i>n;){if(i-n>600){var o=i-n+1,s=r-n+1,l=Math.log(o),c=.5*Math.exp(2*l/3),u=.5*Math.sqrt(l*c*(o-c)/o)*(s-o/2<0?-1:1);t(e,r,Math.max(n,Math.floor(r-s*c/o+u)),Math.min(i,Math.floor(r+(o-s)*c/o+u)),a)}var f=e[r],h=n,p=i;for(Gi(e,n,r),a(e[i],f)>0&&Gi(e,n,i);h0;)p--}0===a(e[n],f)?Gi(e,n,p):Gi(e,++p,i),p<=r&&(n=p+1),r<=p&&(i=p-1)}}(t,e,r||0,n||t.length-1,i||Wi)}function Gi(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function Wi(t,e){return te?1:0}function Yi(t,e){var r=t.length;if(r<=1)return[t];for(var n,i,a=[],o=0;o1)for(var l=0;lDn)||t.y===e.y&&(t.y<0||t.y>Dn)}function na(t){return t.every(function(t){return t.x<0})||t.every(function(t){return t.x>Dn})||t.every(function(t){return t.y<0})||t.every(function(t){return t.y>Dn})}ea.prototype.populate=function(t,e){for(var r=0,n=t;r=1){var m=f[p-1];if(!ra(d,m)){l.vertexLength+4>Tn.MAX_VERTEX_ARRAY_LENGTH&&(l=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray));var g=d.sub(m)._perp()._unit(),v=m.dist(d);h+v>32768&&(h=0),ta(this.layoutVertexArray,d.x,d.y,g.x,g.y,0,0,h),ta(this.layoutVertexArray,d.x,d.y,g.x,g.y,0,1,h),h+=v,ta(this.layoutVertexArray,m.x,m.y,g.x,g.y,0,0,h),ta(this.layoutVertexArray,m.x,m.y,g.x,g.y,0,1,h);var y=l.vertexLength;this.indexArray.emplaceBack(y,y+1,y+2),this.indexArray.emplaceBack(y+1,y+2,y+3),l.vertexLength+=4,l.primitiveLength+=2}}}}l.vertexLength+a>Tn.MAX_VERTEX_ARRAY_LENGTH&&(l=this.segments.prepareSegment(a,this.layoutVertexArray,this.indexArray));for(var x=[],b=[],_=l.vertexLength,w=0,k=i;w>3}if(i--,1===n||2===n)a+=t.readSVarint(),o+=t.readSVarint(),1===n&&(e&&s.push(e),e=[]),e.push(new l(a,o));else{if(7!==n)throw new Error("unknown command "+n);e&&e.push(e[0].clone())}}return e&&s.push(e),s},la.prototype.bbox=function(){var t=this._pbf;t.pos=this._geometry;for(var e=t.readVarint()+t.pos,r=1,n=0,i=0,a=0,o=1/0,s=-1/0,l=1/0,c=-1/0;t.pos>3}if(n--,1===r||2===r)(i+=t.readSVarint())s&&(s=i),(a+=t.readSVarint())c&&(c=a);else if(7!==r)throw new Error("unknown command "+r)}return[o,l,s,c]},la.prototype.toGeoJSON=function(t,e,r){var n,i,a=this.extent*Math.pow(2,r),o=this.extent*t,s=this.extent*e,l=this.loadGeometry(),c=la.types[this.type];function u(t){for(var e=0;e>3;e=1===n?t.readString():2===n?t.readFloat():3===n?t.readDouble():4===n?t.readVarint64():5===n?t.readVarint():6===n?t.readSVarint():7===n?t.readBoolean():null}return e}(r))}function da(t,e,r){if(3===t){var n=new fa(r,r.readVarint()+r.pos);n.length&&(e[n.name]=n)}}ha.prototype.feature=function(t){if(t<0||t>=this._features.length)throw new Error("feature index out of bounds");this._pbf.pos=this._features[t];var e=this._pbf.readVarint()+this._pbf.pos;return new sa(this._pbf,e,this.extent,this._keys,this._values)};var ma={VectorTile:function(t,e){this.layers=t.readFields(da,{},e)},VectorTileFeature:sa,VectorTileLayer:fa},ga=ma.VectorTileFeature.types,va=63,ya=Math.cos(Math.PI/180*37.5),xa=.5,ba=Math.pow(2,14)/xa;function _a(t,e,r,n,i,a,o){t.emplaceBack(e.x,e.y,n?1:0,i?1:-1,Math.round(va*r.x)+128,Math.round(va*r.y)+128,1+(0===a?0:a<0?-1:1)|(o*xa&63)<<2,o*xa>>6)}var wa=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.layoutVertexArray=new Qr,this.indexArray=new fn,this.programConfigurations=new In(oa,t.layers,t.zoom),this.segments=new Tn};function ka(t,e){return(t/e.tileTotal*(e.end-e.start)+e.start)*(ba-1)}wa.prototype.populate=function(t,e){for(var r=0,n=t;r=2&&t[l-1].equals(t[l-2]);)l--;for(var c=0;cc){var E=p.dist(x);if(E>2*u){var C=p.sub(p.sub(x)._mult(u/E)._round());this.distance+=C.dist(x),this.addCurrentVertex(C,this.distance,_.mult(1),0,0,!1,h,o),x=C}}var L=x&&b,z=L?r:b?g:v;if(L&&"round"===z&&(Ti&&(z="bevel"),"bevel"===z&&(T>2&&(z="flipbevel"),T100)M=w.clone().mult(-1);else{var O=_.x*w.y-_.y*w.x>0?-1:1,I=T*_.add(w).mag()/_.sub(w).mag();M._perp()._mult(I*O)}this.addCurrentVertex(p,this.distance,M,0,0,!1,h,o),this.addCurrentVertex(p,this.distance,M.mult(-1),0,0,!1,h,o)}else if("bevel"===z||"fakeround"===z){var P=_.x*w.y-_.y*w.x>0,D=-Math.sqrt(T*T-1);if(P?(m=0,d=D):(d=0,m=D),y||this.addCurrentVertex(p,this.distance,_,d,m,!1,h,o),"fakeround"===z){for(var R=Math.floor(8*(.5-(A-.5))),B=void 0,F=0;F=0;N--)B=_.mult((N+1)/(R+1))._add(w)._unit(),this.addPieSliceVertex(p,this.distance,B,P,h,o)}b&&this.addCurrentVertex(p,this.distance,w,-d,-m,!1,h,o)}else"butt"===z?(y||this.addCurrentVertex(p,this.distance,_,0,0,!1,h,o),b&&this.addCurrentVertex(p,this.distance,w,0,0,!1,h,o)):"square"===z?(y||(this.addCurrentVertex(p,this.distance,_,1,1,!1,h,o),this.e1=this.e2=-1),b&&this.addCurrentVertex(p,this.distance,w,-1,-1,!1,h,o)):"round"===z&&(y||(this.addCurrentVertex(p,this.distance,_,0,0,!1,h,o),this.addCurrentVertex(p,this.distance,_,1,1,!0,h,o),this.e1=this.e2=-1),b&&(this.addCurrentVertex(p,this.distance,w,-1,-1,!0,h,o),this.addCurrentVertex(p,this.distance,w,0,0,!1,h,o)));if(S&&k2*u){var V=p.add(b.sub(p)._mult(u/j)._round());this.distance+=V.dist(p),this.addCurrentVertex(V,this.distance,w.mult(1),0,0,!1,h,o),p=V}}y=!1}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,e)}},wa.prototype.addCurrentVertex=function(t,e,r,n,i,a,o,s){var l,c=this.layoutVertexArray,u=this.indexArray;s&&(e=ka(e,s)),l=r.clone(),n&&l._sub(r.perp()._mult(n)),_a(c,t,l,a,!1,n,e),this.e3=o.vertexLength++,this.e1>=0&&this.e2>=0&&(u.emplaceBack(this.e1,this.e2,this.e3),o.primitiveLength++),this.e1=this.e2,this.e2=this.e3,l=r.mult(-1),i&&l._sub(r.perp()._mult(i)),_a(c,t,l,a,!0,-i,e),this.e3=o.vertexLength++,this.e1>=0&&this.e2>=0&&(u.emplaceBack(this.e1,this.e2,this.e3),o.primitiveLength++),this.e1=this.e2,this.e2=this.e3,e>ba/2&&!s&&(this.distance=0,this.addCurrentVertex(t,this.distance,r,n,i,a,o))},wa.prototype.addPieSliceVertex=function(t,e,r,n,i,a){r=r.mult(n?-1:1);var o=this.layoutVertexArray,s=this.indexArray;a&&(e=ka(e,a)),_a(o,t,r,!1,n,0,e),this.e3=i.vertexLength++,this.e1>=0&&this.e2>=0&&(s.emplaceBack(this.e1,this.e2,this.e3),i.primitiveLength++),n?this.e2=this.e3:this.e1=this.e3},pr("LineBucket",wa,{omit:["layers"]});var Ma=new qr({"line-cap":new Nr(I.layout_line["line-cap"]),"line-join":new jr(I.layout_line["line-join"]),"line-miter-limit":new Nr(I.layout_line["line-miter-limit"]),"line-round-limit":new Nr(I.layout_line["line-round-limit"])}),Aa={paint:new qr({"line-opacity":new jr(I.paint_line["line-opacity"]),"line-color":new jr(I.paint_line["line-color"]),"line-translate":new Nr(I.paint_line["line-translate"]),"line-translate-anchor":new Nr(I.paint_line["line-translate-anchor"]),"line-width":new jr(I.paint_line["line-width"]),"line-gap-width":new jr(I.paint_line["line-gap-width"]),"line-offset":new jr(I.paint_line["line-offset"]),"line-blur":new jr(I.paint_line["line-blur"]),"line-dasharray":new Vr(I.paint_line["line-dasharray"]),"line-pattern":new Vr(I.paint_line["line-pattern"]),"line-gradient":new Ur(I.paint_line["line-gradient"])}),layout:Ma},Ta=new(function(t){function e(){t.apply(this,arguments)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.possiblyEvaluate=function(e,r){return r=new Lr(Math.floor(r.zoom),{now:r.now,fadeDuration:r.fadeDuration,zoomHistory:r.zoomHistory,transition:r.transition}),t.prototype.possiblyEvaluate.call(this,e,r)},e.prototype.evaluate=function(e,r,n){return r=p({},r,{zoom:Math.floor(r.zoom)}),t.prototype.evaluate.call(this,e,r,n)},e}(jr))(Aa.paint.properties["line-width"].specification);Ta.useIntegerZoom=!0;var Sa=function(t){function e(e){t.call(this,e,Aa)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setPaintProperty=function(e,r,n){t.prototype.setPaintProperty.call(this,e,r,n),"line-gradient"===e&&this._updateGradient()},e.prototype._updateGradient=function(){var t=this._transitionablePaint._values["line-gradient"].value.expression;this.gradient=hi(t,"lineProgress"),this.gradientTexture=null},e.prototype.recalculate=function(e){t.prototype.recalculate.call(this,e),this.paint._values["line-floorwidth"]=Ta.possiblyEvaluate(this._transitioningPaint._values["line-width"].value,e)},e.prototype.createBucket=function(t){return new wa(t)},e.prototype.queryRadius=function(t){var e=t,r=Ea($n("line-width",this,e),$n("line-gap-width",this,e)),n=$n("line-offset",this,e);return r/2+Math.abs(n)+Jn(this.paint.get("line-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,i,a){var o=Kn(t,this.paint.get("line-translate"),this.paint.get("line-translate-anchor"),i.angle,a),s=a/2*Ea(this.paint.get("line-width").evaluate(e),this.paint.get("line-gap-width").evaluate(e)),c=this.paint.get("line-offset").evaluate(e);return c&&(r=function(t,e){for(var r=[],n=new l(0,0),i=0;i0?e+2*t:t}var Ca=Xr([{name:"a_pos_offset",components:4,type:"Int16"},{name:"a_data",components:4,type:"Uint16"}]),La=Xr([{name:"a_projected_pos",components:3,type:"Float32"}],4),za=(Xr([{name:"a_fade_opacity",components:1,type:"Uint32"}],4),Xr([{name:"a_placed",components:2,type:"Uint8"}],4)),Oa=(Xr([{type:"Int16",name:"anchorPointX"},{type:"Int16",name:"anchorPointY"},{type:"Int16",name:"x1"},{type:"Int16",name:"y1"},{type:"Int16",name:"x2"},{type:"Int16",name:"y2"},{type:"Uint32",name:"featureIndex"},{type:"Uint16",name:"sourceLayerIndex"},{type:"Uint16",name:"bucketIndex"},{type:"Int16",name:"radius"},{type:"Int16",name:"signedDistanceFromAnchor"}]),Xr([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4)),Ia=Xr([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4);function Pa(t,e,r){var n=e.layout.get("text-transform").evaluate(r);return"uppercase"===n?t=t.toLocaleUpperCase():"lowercase"===n&&(t=t.toLocaleLowerCase()),Cr.applyArabicShaping&&(t=Cr.applyArabicShaping(t)),t}Xr([{type:"Int16",name:"anchorX"},{type:"Int16",name:"anchorY"},{type:"Uint16",name:"glyphStartIndex"},{type:"Uint16",name:"numGlyphs"},{type:"Uint32",name:"vertexStartIndex"},{type:"Uint32",name:"lineStartIndex"},{type:"Uint32",name:"lineLength"},{type:"Uint16",name:"segment"},{type:"Uint16",name:"lowerSize"},{type:"Uint16",name:"upperSize"},{type:"Float32",name:"lineOffsetX"},{type:"Float32",name:"lineOffsetY"},{type:"Uint8",name:"writingMode"},{type:"Uint8",name:"hidden"}]),Xr([{type:"Float32",name:"offsetX"}]),Xr([{type:"Int16",name:"x"},{type:"Int16",name:"y"},{type:"Int16",name:"tileUnitDistanceFromAnchor"}]);var Da={"!":"\ufe15","#":"\uff03",$:"\uff04","%":"\uff05","&":"\uff06","(":"\ufe35",")":"\ufe36","*":"\uff0a","+":"\uff0b",",":"\ufe10","-":"\ufe32",".":"\u30fb","/":"\uff0f",":":"\ufe13",";":"\ufe14","<":"\ufe3f","=":"\uff1d",">":"\ufe40","?":"\ufe16","@":"\uff20","[":"\ufe47","\\":"\uff3c","]":"\ufe48","^":"\uff3e",_:"\ufe33","`":"\uff40","{":"\ufe37","|":"\u2015","}":"\ufe38","~":"\uff5e","\xa2":"\uffe0","\xa3":"\uffe1","\xa5":"\uffe5","\xa6":"\uffe4","\xac":"\uffe2","\xaf":"\uffe3","\u2013":"\ufe32","\u2014":"\ufe31","\u2018":"\ufe43","\u2019":"\ufe44","\u201c":"\ufe41","\u201d":"\ufe42","\u2026":"\ufe19","\u2027":"\u30fb","\u20a9":"\uffe6","\u3001":"\ufe11","\u3002":"\ufe12","\u3008":"\ufe3f","\u3009":"\ufe40","\u300a":"\ufe3d","\u300b":"\ufe3e","\u300c":"\ufe41","\u300d":"\ufe42","\u300e":"\ufe43","\u300f":"\ufe44","\u3010":"\ufe3b","\u3011":"\ufe3c","\u3014":"\ufe39","\u3015":"\ufe3a","\u3016":"\ufe17","\u3017":"\ufe18","\uff01":"\ufe15","\uff08":"\ufe35","\uff09":"\ufe36","\uff0c":"\ufe10","\uff0d":"\ufe32","\uff0e":"\u30fb","\uff1a":"\ufe13","\uff1b":"\ufe14","\uff1c":"\ufe3f","\uff1e":"\ufe40","\uff1f":"\ufe16","\uff3b":"\ufe47","\uff3d":"\ufe48","\uff3f":"\ufe33","\uff5b":"\ufe37","\uff5c":"\u2015","\uff5d":"\ufe38","\uff5f":"\ufe35","\uff60":"\ufe36","\uff61":"\ufe12","\uff62":"\ufe41","\uff63":"\ufe42"},Ra=function(t){function e(e,r,n,i){t.call(this,e,r),this.angle=n,void 0!==i&&(this.segment=i)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.clone=function(){return new e(this.x,this.y,this.angle,this.segment)},e}(l);function Ba(t,e){var r=e.expression;if("constant"===r.kind)return{functionType:"constant",layoutSize:r.evaluate(new Lr(t+1))};if("source"===r.kind)return{functionType:"source"};for(var n=r.zoomStops,i=0;i0)&&("constant"!==i.value.kind||i.value.value.length>0),l="constant"!==o.value.kind||o.value.value&&o.value.value.length>0;if(this.features=[],s||l){for(var c=e.iconDependencies,u=e.glyphDependencies,f=new Lr(this.zoom),h=0,p=t;h=0;s--)a[s]={x:e[s].x,y:e[s].y,tileUnitDistanceFromAnchor:i},s>0&&(i+=e[s-1].dist(e[s]));for(var l=0;l0;this.addCollisionDebugVertices(s,l,c,u,f?this.collisionCircle:this.collisionBox,o.anchorPoint,r,f)}}}},Ha.prototype.deserializeCollisionBoxes=function(t,e,r,n,i){for(var a={},o=e;o0},Ha.prototype.hasIconData=function(){return this.icon.segments.get().length>0},Ha.prototype.hasCollisionBoxData=function(){return this.collisionBox.segments.get().length>0},Ha.prototype.hasCollisionCircleData=function(){return this.collisionCircle.segments.get().length>0},Ha.prototype.sortFeatures=function(t){var e=this;if(this.sortFeaturesByY&&this.sortedAngle!==t&&(this.sortedAngle=t,!(this.text.segments.get().length>1||this.icon.segments.get().length>1))){for(var r=[],n=0;ni.maxh||t>i.maxw||r<=i.maxh&&t<=i.maxw&&(o=i.maxw*i.maxh-t*r)a.free)){if(r===a.h)return this.allocShelf(s,t,r,n);r>a.h||ru)&&(f=2*Math.max(t,u)),(ll)&&(c=2*Math.max(r,l)),this.resize(f,c),this.packOne(t,r,n)):null},t.prototype.allocFreebin=function(t,e,r,n){var i=this.freebins.splice(t,1)[0];return i.id=n,i.w=e,i.h=r,i.refcount=0,this.bins[n]=i,this.ref(i),i},t.prototype.allocShelf=function(t,e,r,n){var i=this.shelves[t].alloc(e,r,n);return this.bins[n]=i,this.ref(i),i},t.prototype.shrink=function(){if(this.shelves.length>0){for(var t=0,e=0,r=0;rthis.free||e>this.h)return null;var n=this.x;return this.x+=t,this.free-=t,new function(t,e,r,n,i,a,o){this.id=t,this.x=e,this.y=r,this.w=n,this.h=i,this.maxw=a||n,this.maxh=o||i,this.refcount=0}(r,n,this.y,t,e,t,this.h)},e.prototype.resize=function(t){return this.free+=t-this.w,this.w=t,!0},t}()}),Qa=function(t,e){var r=e.pixelRatio;this.paddedRect=t,this.pixelRatio=r},to={tl:{configurable:!0},br:{configurable:!0},displaySize:{configurable:!0}};to.tl.get=function(){return[this.paddedRect.x+1,this.paddedRect.y+1]},to.br.get=function(){return[this.paddedRect.x+this.paddedRect.w-1,this.paddedRect.y+this.paddedRect.h-1]},to.displaySize.get=function(){return[(this.paddedRect.w-2)/this.pixelRatio,(this.paddedRect.h-2)/this.pixelRatio]},Object.defineProperties(Qa.prototype,to);var eo=function(t){var e=new ui({width:0,height:0}),r={},n=new Ka(0,0,{autoResize:!0});for(var i in t){var a=t[i],o=n.packOne(a.data.width+2,a.data.height+2);e.resize({width:n.w,height:n.h}),ui.copy(a.data,e,{x:0,y:0},{x:o.x+1,y:o.y+1},a.data),r[i]=new Qa(o,a)}n.shrink(),e.resize({width:n.w,height:n.h}),this.image=e,this.positions=r};pr("ImagePosition",Qa),pr("ImageAtlas",eo);var ro=function(t,e,r,n,i){var a,o,s=8*i-n-1,l=(1<>1,u=-7,f=r?i-1:0,h=r?-1:1,p=t[e+f];for(f+=h,a=p&(1<<-u)-1,p>>=-u,u+=s;u>0;a=256*a+t[e+f],f+=h,u-=8);for(o=a&(1<<-u)-1,a>>=-u,u+=n;u>0;o=256*o+t[e+f],f+=h,u-=8);if(0===a)a=1-c;else{if(a===l)return o?NaN:1/0*(p?-1:1);o+=Math.pow(2,n),a-=c}return(p?-1:1)*o*Math.pow(2,a-n)},no=function(t,e,r,n,i,a){var o,s,l,c=8*a-i-1,u=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:a-1,d=n?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,o=u):(o=Math.floor(Math.log(e)/Math.LN2),e*(l=Math.pow(2,-o))<1&&(o--,l*=2),(e+=o+f>=1?h/l:h*Math.pow(2,1-f))*l>=2&&(o++,l/=2),o+f>=u?(s=0,o=u):o+f>=1?(s=(e*l-1)*Math.pow(2,i),o+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,i),o=0));i>=8;t[r+p]=255&s,p+=d,s/=256,i-=8);for(o=o<0;t[r+p]=255&o,p+=d,o/=256,c-=8);t[r+p-d]|=128*m},io=ao;function ao(t){this.buf=ArrayBuffer.isView&&ArrayBuffer.isView(t)?t:new Uint8Array(t||0),this.pos=0,this.type=0,this.length=this.buf.length}function oo(t){return t.type===ao.Bytes?t.readVarint()+t.pos:t.pos+1}function so(t,e,r){return r?4294967296*e+(t>>>0):4294967296*(e>>>0)+(t>>>0)}function lo(t,e,r){var n=e<=16383?1:e<=2097151?2:e<=268435455?3:Math.ceil(Math.log(e)/(7*Math.LN2));r.realloc(n);for(var i=r.pos-1;i>=t;i--)r.buf[i+n]=r.buf[i]}function co(t,e){for(var r=0;r>>8,t[r+2]=e>>>16,t[r+3]=e>>>24}function _o(t,e){return(t[e]|t[e+1]<<8|t[e+2]<<16)+(t[e+3]<<24)}ao.Varint=0,ao.Fixed64=1,ao.Bytes=2,ao.Fixed32=5,ao.prototype={destroy:function(){this.buf=null},readFields:function(t,e,r){for(r=r||this.length;this.pos>3,a=this.pos;this.type=7&n,t(i,e,this),this.pos===a&&this.skip(n)}return e},readMessage:function(t,e){return this.readFields(t,e,this.readVarint()+this.pos)},readFixed32:function(){var t=xo(this.buf,this.pos);return this.pos+=4,t},readSFixed32:function(){var t=_o(this.buf,this.pos);return this.pos+=4,t},readFixed64:function(){var t=xo(this.buf,this.pos)+4294967296*xo(this.buf,this.pos+4);return this.pos+=8,t},readSFixed64:function(){var t=xo(this.buf,this.pos)+4294967296*_o(this.buf,this.pos+4);return this.pos+=8,t},readFloat:function(){var t=ro(this.buf,this.pos,!0,23,4);return this.pos+=4,t},readDouble:function(){var t=ro(this.buf,this.pos,!0,52,8);return this.pos+=8,t},readVarint:function(t){var e,r,n=this.buf;return e=127&(r=n[this.pos++]),r<128?e:(e|=(127&(r=n[this.pos++]))<<7,r<128?e:(e|=(127&(r=n[this.pos++]))<<14,r<128?e:(e|=(127&(r=n[this.pos++]))<<21,r<128?e:function(t,e,r){var n,i,a=r.buf;if(n=(112&(i=a[r.pos++]))>>4,i<128)return so(t,n,e);if(n|=(127&(i=a[r.pos++]))<<3,i<128)return so(t,n,e);if(n|=(127&(i=a[r.pos++]))<<10,i<128)return so(t,n,e);if(n|=(127&(i=a[r.pos++]))<<17,i<128)return so(t,n,e);if(n|=(127&(i=a[r.pos++]))<<24,i<128)return so(t,n,e);if(n|=(1&(i=a[r.pos++]))<<31,i<128)return so(t,n,e);throw new Error("Expected varint not more than 10 bytes")}(e|=(15&(r=n[this.pos]))<<28,t,this))))},readVarint64:function(){return this.readVarint(!0)},readSVarint:function(){var t=this.readVarint();return t%2==1?(t+1)/-2:t/2},readBoolean:function(){return Boolean(this.readVarint())},readString:function(){var t=this.readVarint()+this.pos,e=function(t,e,r){for(var n="",i=e;i239?4:l>223?3:l>191?2:1;if(i+u>r)break;1===u?l<128&&(c=l):2===u?128==(192&(a=t[i+1]))&&(c=(31&l)<<6|63&a)<=127&&(c=null):3===u?(a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&((c=(15&l)<<12|(63&a)<<6|63&o)<=2047||c>=55296&&c<=57343)&&(c=null)):4===u&&(a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&((c=(15&l)<<18|(63&a)<<12|(63&o)<<6|63&s)<=65535||c>=1114112)&&(c=null)),null===c?(c=65533,u=1):c>65535&&(c-=65536,n+=String.fromCharCode(c>>>10&1023|55296),c=56320|1023&c),n+=String.fromCharCode(c),i+=u}return n}(this.buf,this.pos,t);return this.pos=t,e},readBytes:function(){var t=this.readVarint()+this.pos,e=this.buf.subarray(this.pos,t);return this.pos=t,e},readPackedVarint:function(t,e){var r=oo(this);for(t=t||[];this.pos127;);else if(e===ao.Bytes)this.pos=this.readVarint()+this.pos;else if(e===ao.Fixed32)this.pos+=4;else{if(e!==ao.Fixed64)throw new Error("Unimplemented type: "+e);this.pos+=8}},writeTag:function(t,e){this.writeVarint(t<<3|e)},realloc:function(t){for(var e=this.length||16;e268435455||t<0?function(t,e){var r,n;if(t>=0?(r=t%4294967296|0,n=t/4294967296|0):(n=~(-t/4294967296),4294967295^(r=~(-t%4294967296))?r=r+1|0:(r=0,n=n+1|0)),t>=0x10000000000000000||t<-0x10000000000000000)throw new Error("Given varint doesn't fit into 10 bytes");e.realloc(10),function(t,e,r){r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos]=127&t}(r,0,e),function(t,e){var r=(7&t)<<4;e.buf[e.pos++]|=r|((t>>>=3)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t)))))}(n,e)}(t,this):(this.realloc(4),this.buf[this.pos++]=127&t|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=t>>>7&127))))},writeSVarint:function(t){this.writeVarint(t<0?2*-t-1:2*t)},writeBoolean:function(t){this.writeVarint(Boolean(t))},writeString:function(t){t=String(t),this.realloc(4*t.length),this.pos++;var e=this.pos;this.pos=function(t,e,r){for(var n,i,a=0;a55295&&n<57344){if(!i){n>56319||a+1===e.length?(t[r++]=239,t[r++]=191,t[r++]=189):i=n;continue}if(n<56320){t[r++]=239,t[r++]=191,t[r++]=189,i=n;continue}n=i-55296<<10|n-56320|65536,i=null}else i&&(t[r++]=239,t[r++]=191,t[r++]=189,i=null);n<128?t[r++]=n:(n<2048?t[r++]=n>>6|192:(n<65536?t[r++]=n>>12|224:(t[r++]=n>>18|240,t[r++]=n>>12&63|128),t[r++]=n>>6&63|128),t[r++]=63&n|128)}return r}(this.buf,t,this.pos);var r=this.pos-e;r>=128&&lo(e,r,this),this.pos=e-1,this.writeVarint(r),this.pos+=r},writeFloat:function(t){this.realloc(4),no(this.buf,t,this.pos,!0,23,4),this.pos+=4},writeDouble:function(t){this.realloc(8),no(this.buf,t,this.pos,!0,52,8),this.pos+=8},writeBytes:function(t){var e=t.length;this.writeVarint(e),this.realloc(e);for(var r=0;r=128&&lo(r,n,this),this.pos=r-1,this.writeVarint(n),this.pos+=n},writeMessage:function(t,e,r){this.writeTag(t,ao.Bytes),this.writeRawMessage(e,r)},writePackedVarint:function(t,e){this.writeMessage(t,co,e)},writePackedSVarint:function(t,e){this.writeMessage(t,uo,e)},writePackedBoolean:function(t,e){this.writeMessage(t,po,e)},writePackedFloat:function(t,e){this.writeMessage(t,fo,e)},writePackedDouble:function(t,e){this.writeMessage(t,ho,e)},writePackedFixed32:function(t,e){this.writeMessage(t,mo,e)},writePackedSFixed32:function(t,e){this.writeMessage(t,go,e)},writePackedFixed64:function(t,e){this.writeMessage(t,vo,e)},writePackedSFixed64:function(t,e){this.writeMessage(t,yo,e)},writeBytesField:function(t,e){this.writeTag(t,ao.Bytes),this.writeBytes(e)},writeFixed32Field:function(t,e){this.writeTag(t,ao.Fixed32),this.writeFixed32(e)},writeSFixed32Field:function(t,e){this.writeTag(t,ao.Fixed32),this.writeSFixed32(e)},writeFixed64Field:function(t,e){this.writeTag(t,ao.Fixed64),this.writeFixed64(e)},writeSFixed64Field:function(t,e){this.writeTag(t,ao.Fixed64),this.writeSFixed64(e)},writeVarintField:function(t,e){this.writeTag(t,ao.Varint),this.writeVarint(e)},writeSVarintField:function(t,e){this.writeTag(t,ao.Varint),this.writeSVarint(e)},writeStringField:function(t,e){this.writeTag(t,ao.Bytes),this.writeString(e)},writeFloatField:function(t,e){this.writeTag(t,ao.Fixed32),this.writeFloat(e)},writeDoubleField:function(t,e){this.writeTag(t,ao.Fixed64),this.writeDouble(e)},writeBooleanField:function(t,e){this.writeVarintField(t,Boolean(e))}};var wo=3;function ko(t,e,r){1===t&&r.readMessage(Mo,e)}function Mo(t,e,r){if(3===t){var n=r.readMessage(Ao,{}),i=n.id,a=n.bitmap,o=n.width,s=n.height,l=n.left,c=n.top,u=n.advance;e.push({id:i,bitmap:new ci({width:o+2*wo,height:s+2*wo},a),metrics:{width:o,height:s,left:l,top:c,advance:u}})}}function Ao(t,e,r){1===t?e.id=r.readVarint():2===t?e.bitmap=r.readBytes():3===t?e.width=r.readVarint():4===t?e.height=r.readVarint():5===t?e.left=r.readSVarint():6===t?e.top=r.readSVarint():7===t&&(e.advance=r.readVarint())}var To=wo,So=function(t,e,r){this.target=t,this.parent=e,this.mapId=r,this.callbacks={},this.callbackID=0,m(["receive"],this),this.target.addEventListener("message",this.receive,!1)};So.prototype.send=function(t,e,r,n){var i=r?this.mapId+":"+this.callbackID++:null;r&&(this.callbacks[i]=r);var a=[];this.target.postMessage({targetMapId:n,sourceMapId:this.mapId,type:t,id:String(i),data:mr(e,a)},a)},So.prototype.receive=function(t){var e,r=this,n=t.data,i=n.id;if(!n.targetMapId||this.mapId===n.targetMapId){var a=function(t,e){var n=[];r.target.postMessage({sourceMapId:r.mapId,type:"",id:String(i),error:t?mr(t):null,data:mr(e,n)},n)};if(""===n.type)e=this.callbacks[n.id],delete this.callbacks[n.id],e&&n.error?e(gr(n.error)):e&&e(null,gr(n.data));else if(void 0!==n.id&&this.parent[n.type])this.parent[n.type](n.sourceMapId,gr(n.data),a);else if(void 0!==n.id&&this.parent.getWorkerSource){var o=n.type.split(".");this.parent.getWorkerSource(n.sourceMapId,o[0],o[1])[o[2]](gr(n.data),a)}else this.parent[n.type](gr(n.data))}},So.prototype.remove=function(){this.target.removeEventListener("message",this.receive,!1)};var Eo=n(i(function(t,e){!function(t){function e(t,e,n){var i=r(256*t,256*(e=Math.pow(2,n)-e-1),n),a=r(256*(t+1),256*(e+1),n);return i[0]+","+i[1]+","+a[0]+","+a[1]}function r(t,e,r){var n=2*Math.PI*6378137/256/Math.pow(2,r);return[t*n-2*Math.PI*6378137/2,e*n-2*Math.PI*6378137/2]}t.getURL=function(t,r,n,i,a,o){return o=o||{},t+"?"+["bbox="+e(n,i,a),"format="+(o.format||"image/png"),"service="+(o.service||"WMS"),"version="+(o.version||"1.1.1"),"request="+(o.request||"GetMap"),"srs="+(o.srs||"EPSG:3857"),"width="+(o.width||256),"height="+(o.height||256),"layers="+r].join("&")},t.getTileBBox=e,t.getMercCoords=r,Object.defineProperty(t,"__esModule",{value:!0})}(e)})),Co=function(t,e,r){this.z=t,this.x=e,this.y=r,this.key=Oo(0,t,e,r)};Co.prototype.equals=function(t){return this.z===t.z&&this.x===t.x&&this.y===t.y},Co.prototype.url=function(t,e){var r=Eo.getTileBBox(this.x,this.y,this.z),n=function(t,e,r){for(var n,i="",a=t;a>0;a--)i+=(e&(n=1<this.canonical.z?new zo(t,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y):new zo(t,this.wrap,t,this.canonical.x>>e,this.canonical.y>>e)},zo.prototype.isChildOf=function(t){var e=this.canonical.z-t.canonical.z;return 0===t.overscaledZ||t.overscaledZ>e&&t.canonical.y===this.canonical.y>>e},zo.prototype.children=function(t){if(this.overscaledZ>=t)return[new zo(this.overscaledZ+1,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y)];var e=this.canonical.z+1,r=2*this.canonical.x,n=2*this.canonical.y;return[new zo(e,this.wrap,e,r,n),new zo(e,this.wrap,e,r+1,n),new zo(e,this.wrap,e,r,n+1),new zo(e,this.wrap,e,r+1,n+1)]},zo.prototype.isLessThan=function(t){return this.wrapt.wrap)&&(this.overscaledZt.overscaledZ)&&(this.canonical.xt.canonical.x)&&this.canonical.y=this.dim+this.border||e<-this.border||e>=this.dim+this.border)throw new RangeError("out of range source coordinates for DEM data");return(e+this.border)*this.stride+(t+this.border)},pr("Level",Io);var Po=function(t,e,r){this.uid=t,this.scale=e||1,this.level=r||new Io(256,512),this.loaded=!!r};Po.prototype.loadFromImage=function(t,e){if(t.height!==t.width)throw new RangeError("DEM tiles must be square");if(e&&"mapbox"!==e&&"terrarium"!==e)return _('"'+e+'" is not a valid encoding type. Valid types include "mapbox" and "terrarium".');var r=this.level=new Io(t.width,t.width/2),n=t.data;this._unpackData(r,n,e||"mapbox");for(var i=0;i=0&&l[3]>=0&&this.grid.insert(a,l[0],l[1],l[2],l[3])}},Fo.prototype.loadVTLayers=function(){return this.vtLayers||(this.vtLayers=new ma.VectorTile(new io(this.rawTileData)).layers,this.sourceLayerCoder=new Do(this.vtLayers?Object.keys(this.vtLayers).sort():["_geojsonTileLayer"])),this.vtLayers},Fo.prototype.query=function(t,e){var r=this;this.loadVTLayers();for(var n=t.params||{},i=Dn/t.tileSize/t.scale,a=Re(n.filter),o=t.queryGeometry,s=t.queryPadding*i,l=1/0,c=1/0,u=-1/0,f=-1/0,h=0;h=0)return!0;return!1}(a,l)){var c=this.sourceLayerCoder.decode(r),u=this.vtLayers[c].feature(n);if(i(new Lr(this.tileID.overscaledZ),u))for(var f=0;f=200&&r.status<300&&r.response){var n;try{n=JSON.parse(r.response)}catch(t){return e(t)}e(null,n)}else 401===r.status&&t.url.match(/mapbox.com/)?e(new A(r.statusText+": you may have provided an invalid Mapbox access token. See https://www.mapbox.com/api-documentation/#access-tokens",r.status,t.url)):e(new A(r.statusText,r.status,t.url))},r.send(),r},e.getImage=function(t,e){return S(t,function(t,r){if(t)e(t);else if(r){var n=new self.Image,i=self.URL||self.webkitURL;n.onload=function(){e(null,n),i.revokeObjectURL(n.src)};var a=new self.Blob([new Uint8Array(r.data)],{type:"image/png"});n.cacheControl=r.cacheControl,n.expires=r.expires,n.src=r.data.byteLength?i.createObjectURL(a):"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII="}})},e.ResourceType=M,e.RGBAImage=ui,e.default$2=Ka,e.ImagePosition=Qa,e.getArrayBuffer=S,e.default$3=function(t){return new io(t).readFields(ko,[])},e.default$4=yr,e.asyncAll=function(t,e,r){if(!t.length)return r(null,[]);var n=t.length,i=new Array(t.length),a=null;t.forEach(function(t,o){e(t,function(t,e){t&&(a=t),i[o]=e,0==--n&&r(a,i)})})},e.AlphaImage=ci,e.default$5=I,e.endsWith=g,e.extend=p,e.sphericalToCartesian=function(t){var e=t[0],r=t[1],n=t[2];return r+=90,r*=Math.PI/180,n*=Math.PI/180,{x:e*Math.cos(r)*Math.sin(n),y:e*Math.sin(r)*Math.sin(n),z:e*Math.cos(n)}},e.Evented=O,e.validateStyle=nr,e.validateLight=ir,e.emitValidationErrors=sr,e.default$6=tt,e.number=wt,e.Properties=qr,e.Transitionable=Ir,e.Transitioning=Dr,e.PossiblyEvaluated=Fr,e.DataConstantProperty=Nr,e.warnOnce=_,e.uniqueId=function(){return d++},e.default$7=So,e.pick=function(t,e){for(var r={},n=0;n@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g,function(t,r,n,i){var a=n||i;return e[r]=!a||a.toLowerCase(),""}),e["max-age"]){var r=parseInt(e["max-age"],10);isNaN(r)?delete e["max-age"]:e["max-age"]=r}return e},e.default$11=Fo,e.default$12=Ro,e.default$13=Re,e.default$14=Ha,e.CollisionBoxArray=gn,e.default$15=Tn,e.TriangleIndexArray=fn,e.default$16=Lr,e.default$17=s,e.keysDifference=function(t,e){var r=[];for(var n in t)n in e||r.push(n);return r},e.default$18=["type","source","source-layer","minzoom","maxzoom","filter","layout"],e.mat4=ri,e.vec4=ei,e.getSizeData=Ba,e.evaluateSizeForFeature=function(t,e,r){var n=e;return"source"===t.functionType?r.lowerSize/10:"composite"===t.functionType?wt(r.lowerSize/10,r.upperSize/10,n.uSizeT):n.uSize},e.evaluateSizeForZoom=function(t,e,r){if("constant"===t.functionType)return{uSizeT:0,uSize:t.layoutSize};if("source"===t.functionType)return{uSizeT:0,uSize:0};if("camera"===t.functionType){var n=t.propertyValue,i=t.zoomRange,a=t.sizeRange,o=h(Se(n,r.specification).interpolationFactor(e,i.min,i.max),0,1);return{uSizeT:0,uSize:a.min+o*(a.max-a.min)}}var s=t.propertyValue,l=t.zoomRange;return{uSizeT:h(Se(s,r.specification).interpolationFactor(e,l.min,l.max),0,1),uSize:0}},e.addDynamicAttributes=Va,e.default$19=Wa,e.WritingMode=jo,e.multiPolygonIntersectsBufferedPoint=jn,e.multiPolygonIntersectsMultiPolygon=Vn,e.multiPolygonIntersectsBufferedMultiLine=Un,e.polygonIntersectsPolygon=function(t,e){for(var r=0;r-r/2;){if(--o<0)return!1;s-=t[o].dist(a),a=t[o]}s+=t[o].dist(t[o+1]),o++;for(var l=[],c=0;sn;)c-=l.shift().angleDelta;if(c>i)return!1;o++,s+=f.dist(h)}return!0}function a(e,r,n,a,o,s,l,c,u){var f=a?.6*s*l:0,h=Math.max(a?a.right-a.left:0,o?o.right-o.left:0),p=0===e[0].x||e[0].x===u||0===e[0].y||e[0].y===u;return r-h*l=0&&M=0&&A=0&&g+h<=p){var T=new t.default$25(M,A,w,y);T._round(),o&&!i(r,T,l,o,s)||v.push(T)}}m+=_}return u||v.length||c||(v=e(r,m/2,a,o,s,l,c,!0,f)),v}(e,p?r/2*c%r:(h/2+2*s)*l*c%r,r,f,n,h*l,p,!1,u)}n.prototype.replace=function(t){this._layerConfigs={},this._layers={},this.update(t,[])},n.prototype.update=function(e,n){for(var i=this,a=0,o=e;a0&&(m=Math.max(10*s,m),this._addLineCollisionCircles(t,e,r,r.segment,g,m,n,i,a,u))}else t.emplaceBack(r.x,r.y,p,f,d,h,n,i,a,0,0);this.boxEndIndex=t.length};s.prototype._addLineCollisionCircles=function(t,e,r,n,i,a,o,s,l,c){var u=a/2,f=Math.floor(i/u),h=1+.4*Math.log(c)/Math.LN2,p=Math.floor(f*h/2),d=-a/2,m=r,g=n+1,v=d,y=-i/2,x=y-i/4;do{if(--g<0){if(v>y)return;g=0;break}v-=e[g].dist(m),m=e[g]}while(v>x);for(var b=e[g].dist(e[g+1]),_=-p;_i&&(k+=w-i),!(k=e.length)return;b=e[g].dist(e[g+1])}var M=k-v,A=e[g],T=e[g+1].sub(A)._unit()._mult(M)._add(A)._round(),S=Math.abs(k-d)0)for(var r=(this.length>>1)-1;r>=0;r--)this._down(r)}function f(t,e){return te?1:0}function h(e,r,n){void 0===r&&(r=1),void 0===n&&(n=!1);for(var i=1/0,a=1/0,o=-1/0,s=-1/0,c=e[0],u=0;uo)&&(o=f.x),(!u||f.y>s)&&(s=f.y)}var h=o-i,m=s-a,g=Math.min(h,m),v=g/2,y=new l(null,p);if(0===g)return new t.default$1(i,a);for(var x=i;x_.d||!_.d)&&(_=k,n&&console.log("found best %d after %d probes",Math.round(1e4*k.d)/1e4,w)),k.max-_.d<=r||(v=k.h/2,y.push(new d(k.p.x-v,k.p.y-v,v,e)),y.push(new d(k.p.x+v,k.p.y-v,v,e)),y.push(new d(k.p.x-v,k.p.y+v,v,e)),y.push(new d(k.p.x+v,k.p.y+v,v,e)),w+=4)}return n&&(console.log("num probes: "+w),console.log("best distance: "+_.d)),_.p}function p(t,e){return e.max-t.max}function d(e,r,n,i){this.p=new t.default$1(e,r),this.h=n,this.d=function(e,r){for(var n=!1,i=1/0,a=0;ae.y!=f.y>e.y&&e.x<(f.x-u.x)*(e.y-u.y)/(f.y-u.y)+u.x&&(n=!n),i=Math.min(i,t.distToSegmentSquared(e,u,f))}return(n?1:-1)*Math.sqrt(i)}(this.p,i),this.max=this.d+this.h*Math.SQRT2}function m(e,r,n,i,a,o){e.createArrays(),e.symbolInstances=[];var s=512*e.overscaling;e.tilePixelRatio=t.default$8/s,e.compareText={},e.iconsNeedLinear=!1;var l=e.layers[0].layout,c=e.layers[0]._unevaluatedLayout._values,u={};if("composite"===e.textSizeData.functionType){var f=e.textSizeData.zoomRange,h=f.min,p=f.max;u.compositeTextSizes=[c["text-size"].possiblyEvaluate(new t.default$16(h)),c["text-size"].possiblyEvaluate(new t.default$16(p))]}if("composite"===e.iconSizeData.functionType){var d=e.iconSizeData.zoomRange,m=d.min,v=d.max;u.compositeIconSizes=[c["icon-size"].possiblyEvaluate(new t.default$16(m)),c["icon-size"].possiblyEvaluate(new t.default$16(v))]}u.layoutTextSize=c["text-size"].possiblyEvaluate(new t.default$16(e.zoom+1)),u.layoutIconSize=c["icon-size"].possiblyEvaluate(new t.default$16(e.zoom+1)),u.textMaxSize=c["text-size"].possiblyEvaluate(new t.default$16(18));for(var y=24*l.get("text-line-height"),x="map"===l.get("text-rotation-alignment")&&"line"===l.get("symbol-placement"),b=l.get("text-keep-upright"),_=0,w=e.features;_=t.default$8||u.y<0||u.y>=t.default$8||e.symbolInstances.push(function(e,r,n,i,a,l,c,u,f,h,p,d,m,g,y,x,b,_,w,k,M){var A,T,S=e.addToLineVertexArray(r,n),E=0,C=0,L=0,z=i.horizontal?i.horizontal.text:"",O=[];i.horizontal&&(A=new s(c,n,r,u,f,h,i.horizontal,p,d,m,e.overscaling),C+=v(e,r,i.horizontal,l,m,w,g,S,i.vertical?t.WritingMode.horizontal:t.WritingMode.horizontalOnly,O,k,M),i.vertical&&(L+=v(e,r,i.vertical,l,m,w,g,S,t.WritingMode.vertical,O,k,M)));var I=A?A.boxStartIndex:e.collisionBoxArray.length,P=A?A.boxEndIndex:e.collisionBoxArray.length;if(a){var D=function(e,r,n,i,a,o){var s,l,c,u,f=r.image,h=n.layout,p=r.top-1/f.pixelRatio,d=r.left-1/f.pixelRatio,m=r.bottom+1/f.pixelRatio,g=r.right+1/f.pixelRatio;if("none"!==h.get("icon-text-fit")&&a){var v=g-d,y=m-p,x=h.get("text-size").evaluate(o)/24,b=a.left*x,_=a.right*x,w=a.top*x,k=_-b,M=a.bottom*x-w,A=h.get("icon-text-fit-padding")[0],T=h.get("icon-text-fit-padding")[1],S=h.get("icon-text-fit-padding")[2],E=h.get("icon-text-fit-padding")[3],C="width"===h.get("icon-text-fit")?.5*(M-y):0,L="height"===h.get("icon-text-fit")?.5*(k-v):0,z="width"===h.get("icon-text-fit")||"both"===h.get("icon-text-fit")?k:v,O="height"===h.get("icon-text-fit")||"both"===h.get("icon-text-fit")?M:y;s=new t.default$1(b+L-E,w+C-A),l=new t.default$1(b+L+T+z,w+C-A),c=new t.default$1(b+L+T+z,w+C+S+O),u=new t.default$1(b+L-E,w+C+S+O)}else s=new t.default$1(d,p),l=new t.default$1(g,p),c=new t.default$1(g,m),u=new t.default$1(d,m);var I=n.layout.get("icon-rotate").evaluate(o)*Math.PI/180;if(I){var P=Math.sin(I),D=Math.cos(I),R=[D,-P,P,D];s._matMult(R),l._matMult(R),u._matMult(R),c._matMult(R)}return[{tl:s,tr:l,bl:u,br:c,tex:f.paddedRect,writingMode:void 0,glyphOffset:[0,0]}]}(0,a,l,0,i.horizontal,w);T=new s(c,n,r,u,f,h,a,y,x,!1,e.overscaling),E=4*D.length;var R=e.iconSizeData,B=null;"source"===R.functionType?B=[10*l.layout.get("icon-size").evaluate(w)]:"composite"===R.functionType&&(B=[10*M.compositeIconSizes[0].evaluate(w),10*M.compositeIconSizes[1].evaluate(w)]),e.addSymbols(e.icon,D,B,_,b,w,!1,r,S.lineStartIndex,S.lineLength)}var F=T?T.boxStartIndex:e.collisionBoxArray.length,N=T?T.boxEndIndex:e.collisionBoxArray.length;return e.glyphOffsetArray.length>=t.default$14.MAX_GLYPHS&&t.warnOnce("Too many glyphs being rendered in a tile. See https://github.com/mapbox/mapbox-gl-js/issues/2907"),{key:z,textBoxStartIndex:I,textBoxEndIndex:P,iconBoxStartIndex:F,iconBoxEndIndex:N,textOffset:g,iconOffset:_,anchor:r,line:n,featureIndex:u,feature:w,numGlyphVertices:C,numVerticalGlyphVertices:L,numIconVertices:E,textOpacityState:new o,iconOpacityState:new o,isDuplicate:!1,placedTextSymbolIndices:O,crossTileID:0}}(e,u,a,n,i,e.layers[0],e.collisionBoxArray,r.index,r.sourceLayerIndex,e.index,b,M,S,m,w,A,E,g,r,l,c))};if("line"===d.get("symbol-placement"))for(var z=0,O=function(e,r,n,i,a){for(var o=[],s=0;s=i&&h.x>=i||(f.x>=i?f=new t.default$1(i,f.y+(h.y-f.y)*((i-f.x)/(h.x-f.x)))._round():h.x>=i&&(h=new t.default$1(i,f.y+(h.y-f.y)*((i-f.x)/(h.x-f.x)))._round()),f.y>=a&&h.y>=a||(f.y>=a?f=new t.default$1(f.x+(h.x-f.x)*((a-f.y)/(h.y-f.y)),a)._round():h.y>=a&&(h=new t.default$1(f.x+(h.x-f.x)*((a-f.y)/(h.y-f.y)),a)._round()),c&&f.equals(c[c.length-1])||(c=[f],o.push(c)),c.push(h)))))}return o}(r.geometry,0,0,t.default$8,t.default$8);z=0;o--)if(n.dist(a[o])0&&(this.data[0]=this.data[this.length],this._down(0)),this.data.pop(),t}},peek:function(){return this.data[0]},_up:function(t){for(var e=this.data,r=this.compare,n=e[t];t>0;){var i=t-1>>1,a=e[i];if(r(n,a)>=0)break;e[t]=a,t=i}e[t]=n},_down:function(t){for(var e=this.data,r=this.compare,n=this.length>>1,i=e[t];t=0)break;e[t]=s,t=a}e[t]=i}},l.default=c;var x=function(e){var r=new t.AlphaImage({width:0,height:0}),n={},i=new t.default$2(0,0,{autoResize:!0});for(var a in e){var o=e[a],s=n[a]={};for(var l in o){var c=o[+l];if(c&&0!==c.bitmap.width&&0!==c.bitmap.height){var u=i.packOne(c.bitmap.width+2,c.bitmap.height+2);r.resize({width:i.w,height:i.h}),t.AlphaImage.copy(c.bitmap,r,{x:0,y:0},{x:u.x+1,y:u.y+1},c.bitmap),s[l]={rect:u,metrics:c.metrics}}}}i.shrink(),r.resize({width:i.w,height:i.h}),this.image=r,this.positions=n};t.register("GlyphAtlas",x);var b=function(e){this.tileID=new t.OverscaledTileID(e.tileID.overscaledZ,e.tileID.wrap,e.tileID.canonical.z,e.tileID.canonical.x,e.tileID.canonical.y),this.uid=e.uid,this.zoom=e.zoom,this.pixelRatio=e.pixelRatio,this.tileSize=e.tileSize,this.source=e.source,this.overscaling=this.tileID.overscaleFactor(),this.showCollisionBoxes=e.showCollisionBoxes,this.collectResourceTiming=!!e.collectResourceTiming};function _(e,r){for(var n=new t.default$16(r),i=0,a=e;i=T.maxzoom||"none"!==T.visibility&&(_(A,a.zoom),(f[T.id]=T.createBucket({index:s.bucketLayerIDs.length,layers:A,zoom:a.zoom,pixelRatio:a.pixelRatio,overscaling:a.overscaling,collisionBoxArray:a.collisionBoxArray,sourceLayerIndex:v})).populate(y,h),s.bucketLayerIDs.push(A.map(function(t){return t.id})))}}}var S=t.mapObject(h.glyphDependencies,function(t){return Object.keys(t).map(Number)});Object.keys(S).length?n.send("getGlyphs",{uid:this.uid,stacks:S},function(t,e){l||(l=t,c=e,C.call(a))}):c={};var E=Object.keys(h.iconDependencies);function C(){if(l)return i(l);if(c&&u){var e=new x(c),r=new t.default$28(u);for(var n in f){var a=f[n];a instanceof t.default$14&&(_(a.layers,this.zoom),m(a,c,e.positions,u,r.positions,this.showCollisionBoxes))}this.status="done",i(null,{buckets:t.values(f).filter(function(t){return!t.isEmpty()}),featureIndex:s,collisionBoxArray:this.collisionBoxArray,glyphAtlasImage:e.image,iconAtlasImage:r.image})}}E.length?n.send("getImages",{icons:E},function(t,e){l||(l=t,u=e,C.call(a))}):u={},C.call(this)};var w=function(t){return!(!performance||!performance.getEntriesByName)&&performance.getEntriesByName(t)};function k(e,r){var n=t.getArrayBuffer(e.request,function(e,n){e?r(e):n&&r(null,{vectorTile:new t.default$29.VectorTile(new t.default$30(n.data)),rawData:n.data,cacheControl:n.cacheControl,expires:n.expires})});return function(){n.abort(),r()}}var M=function(t,e,r){this.actor=t,this.layerIndex=e,this.loadVectorData=r||k,this.loading={},this.loaded={}};M.prototype.loadTile=function(e,r){var n=this,i=e.uid;this.loading||(this.loading={});var a=this.loading[i]=new b(e);a.abort=this.loadVectorData(e,function(o,s){if(delete n.loading[i],o||!s)return r(o);var l=s.rawData,c={};s.expires&&(c.expires=s.expires),s.cacheControl&&(c.cacheControl=s.cacheControl);var u={};if(e.request&&e.request.collectResourceTiming){var f=w(e.request.url);f&&(u.resourceTiming=JSON.parse(JSON.stringify(f)))}a.vectorTile=s.vectorTile,a.parse(s.vectorTile,n.layerIndex,n.actor,function(e,n){if(e||!n)return r(e);r(null,t.extend({rawTileData:l.slice(0)},n,c,u))}),n.loaded=n.loaded||{},n.loaded[i]=a})},M.prototype.reloadTile=function(t,e){var r=this.loaded,n=t.uid,i=this;if(r&&r[n]){var a=r[n];a.showCollisionBoxes=t.showCollisionBoxes;var o=function(t,r){var n=a.reloadCallback;n&&(delete a.reloadCallback,a.parse(a.vectorTile,i.layerIndex,i.actor,n)),e(t,r)};"parsing"===a.status?a.reloadCallback=o:"done"===a.status&&a.parse(a.vectorTile,this.layerIndex,this.actor,o)}},M.prototype.abortTile=function(t,e){var r=this.loading,n=t.uid;r&&r[n]&&r[n].abort&&(r[n].abort(),delete r[n]),e()},M.prototype.removeTile=function(t,e){var r=this.loaded,n=t.uid;r&&r[n]&&delete r[n],e()};var A=function(){this.loading={},this.loaded={}};A.prototype.loadTile=function(e,r){var n=e.uid,i=e.encoding,a=new t.default$31(n);this.loading[n]=a,a.loadFromImage(e.rawImageData,i),delete this.loading[n],this.loaded=this.loaded||{},this.loaded[n]=a,r(null,a)},A.prototype.removeTile=function(t){var e=this.loaded,r=t.uid;e&&e[r]&&delete e[r]};var T={RADIUS:6378137,FLATTENING:1/298.257223563,POLAR_RADIUS:6356752.3142};function S(t){var e=0;if(t&&t.length>0){e+=Math.abs(E(t[0]));for(var r=1;r2){for(o=0;o=0}(t)===e?t:t.reverse()}var P=t.default$29.VectorTileFeature.prototype.toGeoJSON,D=function(e){this._feature=e,this.extent=t.default$8,this.type=e.type,this.properties=e.tags,"id"in e&&!isNaN(e.id)&&(this.id=parseInt(e.id,10))};D.prototype.loadGeometry=function(){if(1===this._feature.type){for(var e=[],r=0,n=this._feature.geometry;r>31}function $(t,e){for(var r=t.loadGeometry(),n=t.type,i=0,a=0,o=r.length,s=0;si;){if(a-i>600){var s=a-i+1,l=n-i+1,c=Math.log(s),u=.5*Math.exp(2*c/3),f=.5*Math.sqrt(c*u*(s-u)/s)*(l-s/2<0?-1:1);t(e,r,n,Math.max(i,Math.floor(n-l*u/s+f)),Math.min(a,Math.floor(n+(s-l)*u/s+f)),o)}var h=r[2*n+o],p=i,d=a;for(Q(e,r,i,n),r[2*a+o]>h&&Q(e,r,i,a);ph;)d--}r[2*i+o]===h?Q(e,r,i,d):Q(e,r,++d,a),d<=n&&(i=d+1),n<=d&&(a=d-1)}}(e,r,s,i,a,o%2),t(e,r,n,i,s-1,o+1),t(e,r,n,s+1,a,o+1)}};function Q(t,e,r,n){tt(t,r,n),tt(e,2*r,2*n),tt(e,2*r+1,2*n+1)}function tt(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function et(t,e,r,n){var i=t-r,a=e-n;return i*i+a*a}var rt=function(t,e,r,n,i){return new nt(t,e,r,n,i)};function nt(t,e,r,n,i){e=e||it,r=r||at,i=i||Array,this.nodeSize=n||64,this.points=t,this.ids=new i(t.length),this.coords=new i(2*t.length);for(var a=0;a=r&&s<=i&&l>=n&&l<=a&&u.push(t[d]);else{var m=Math.floor((p+h)/2);s=e[2*m],l=e[2*m+1],s>=r&&s<=i&&l>=n&&l<=a&&u.push(t[m]);var g=(f+1)%2;(0===f?r<=s:n<=l)&&(c.push(p),c.push(m-1),c.push(g)),(0===f?i>=s:a>=l)&&(c.push(m+1),c.push(h),c.push(g))}}return u}(this.ids,this.coords,t,e,r,n,this.nodeSize)},within:function(t,e,r){return function(t,e,r,n,i,a){for(var o=[0,t.length-1,0],s=[],l=i*i;o.length;){var c=o.pop(),u=o.pop(),f=o.pop();if(u-f<=a)for(var h=f;h<=u;h++)et(e[2*h],e[2*h+1],r,n)<=l&&s.push(t[h]);else{var p=Math.floor((f+u)/2),d=e[2*p],m=e[2*p+1];et(d,m,r,n)<=l&&s.push(t[p]);var g=(c+1)%2;(0===c?r-i<=d:n-i<=m)&&(o.push(f),o.push(p-1),o.push(g)),(0===c?r+i>=d:n+i>=m)&&(o.push(p+1),o.push(u),o.push(g))}}return s}(this.ids,this.coords,t,e,r,this.nodeSize)}};function ot(t){this.options=pt(Object.create(this.options),t),this.trees=new Array(this.options.maxZoom+1)}function st(t,e,r,n,i){return{x:t,y:e,zoom:1/0,id:n,properties:i,parentId:-1,numPoints:r}}function lt(t,e){var r=t.geometry.coordinates;return{x:ft(r[0]),y:ht(r[1]),zoom:1/0,id:e,parentId:-1}}function ct(t){return{type:"Feature",properties:ut(t),geometry:{type:"Point",coordinates:[(n=t.x,360*(n-.5)),(e=t.y,r=(180-360*e)*Math.PI/180,360*Math.atan(Math.exp(r))/Math.PI-90)]}};var e,r,n}function ut(t){var e=t.numPoints,r=e>=1e4?Math.round(e/1e3)+"k":e>=1e3?Math.round(e/100)/10+"k":e;return pt(pt({},t.properties),{cluster:!0,cluster_id:t.id,point_count:e,point_count_abbreviated:r})}function ft(t){return t/360+.5}function ht(t){var e=Math.sin(t*Math.PI/180),r=.5-.25*Math.log((1+e)/(1-e))/Math.PI;return r<0?0:r>1?1:r}function pt(t,e){for(var r in e)t[r]=e[r];return t}function dt(t){return t.x}function mt(t){return t.y}function gt(t,e,r,n,i,a){var o=i-r,s=a-n;if(0!==o||0!==s){var l=((t-r)*o+(e-n)*s)/(o*o+s*s);l>1?(r=i,n=a):l>0&&(r+=o*l,n+=s*l)}return(o=t-r)*o+(s=e-n)*s}function vt(t,e,r,n){var i={id:t||null,type:e,geometry:r,tags:n,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};return function(t){var e=t.geometry,r=t.type;if("Point"===r||"MultiPoint"===r||"LineString"===r)yt(t,e);else if("Polygon"===r||"MultiLineString"===r)for(var n=0;n0&&(o+=n?(i*c-l*a)/2:Math.sqrt(Math.pow(l-i,2)+Math.pow(c-a,2))),i=l,a=c}var u=e.length-3;e[2]=1,function t(e,r,n,i){for(var a,o=i,s=e[r],l=e[r+1],c=e[n],u=e[n+1],f=r+3;fo&&(a=f,o=h)}o>i&&(a-r>3&&t(e,r,a,i),e[a+2]=o,n-a>3&&t(e,a,n,i))}(e,0,u,r),e[u+2]=1,e.size=Math.abs(o),e.start=0,e.end=e.size}function wt(t,e,r,n){for(var i=0;i1?1:r}function At(t,e,r,n,i,a,o,s){if(n/=e,a>=(r/=e)&&o<=n)return t;if(a>n||o=r&&d<=n)l.push(u);else if(!(p>n||d=r&&o<=n&&(e.push(t[a]),e.push(t[a+1]),e.push(t[a+2]))}}function St(t,e,r,n,i,a,o){for(var s,l,c=Et(t),u=0===i?zt:Ot,f=t.start,h=0;h=r&&(l=u(c,p,d,g,v,r),o&&(c.start=f+s*l)):y>n?x<=n&&(l=u(c,p,d,g,v,n),o&&(c.start=f+s*l)):Lt(c,p,d,m),x=r&&(l=u(c,p,d,g,v,r),b=!0),x>n&&y<=n&&(l=u(c,p,d,g,v,n),b=!0),!a&&b&&(o&&(c.end=f+s*l),e.push(c),c=Et(t)),o&&(f+=s)}var _=t.length-3;p=t[_],d=t[_+1],m=t[_+2],(y=0===i?p:d)>=r&&y<=n&&Lt(c,p,d,m),_=c.length-3,a&&_>=3&&(c[_]!==c[0]||c[_+1]!==c[1])&&Lt(c,c[0],c[1],c[2]),c.length&&e.push(c)}function Et(t){var e=[];return e.size=t.size,e.start=t.start,e.end=t.end,e}function Ct(t,e,r,n,i,a){for(var o=0;oo.maxX&&(o.maxX=u),f>o.maxY&&(o.maxY=f)}return o}function Ft(t,e,r,n){var i=e.geometry,a=e.type,o=[];if("Point"===a||"MultiPoint"===a)for(var s=0;s0&&e.size<(i?o:n))r.numPoints+=e.length/3;else{for(var s=[],l=0;lo)&&(r.numSimplified++,s.push(e[l]),s.push(e[l+1])),r.numPoints++;i&&function(t,e){for(var r=0,n=0,i=t.length,a=i-2;n0===e)for(n=0,i=t.length;n24)throw new Error("maxZoom should be in the 0-24 range");var n=function(t,e){var r=[];if("FeatureCollection"===t.type)for(var n=0;n=this.options.minZoom;i--){var a=+Date.now();this.trees[i+1]=rt(n,dt,mt,this.options.nodeSize,Float32Array),n=this._cluster(n,i),e&&console.log("z%d: %d clusters in %dms",i,n.length,+Date.now()-a)}return this.trees[this.options.minZoom]=rt(n,dt,mt,this.options.nodeSize,Float32Array),e&&console.timeEnd("total time"),this},getClusters:function(t,e){for(var r=this.trees[this._limitZoom(e)],n=r.range(ft(t[0]),ht(t[3]),ft(t[2]),ht(t[1])),i=[],a=0;a1&&console.time("creation"),h=this.tiles[f]=Bt(t,e,r,n,l),this.tileCoords.push({z:e,x:r,y:n}),c)){c>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",e,r,n,h.numFeatures,h.numPoints,h.numSimplified),console.timeEnd("creation"));var p="z"+e;this.stats[p]=(this.stats[p]||0)+1,this.total++}if(h.source=t,i){if(e===l.maxZoom||e===i)continue;var d=1<1&&console.time("clipping");var m,g,v,y,x,b,_=.5*l.buffer/l.extent,w=.5-_,k=.5+_,M=1+_;m=g=v=y=null,x=At(t,u,r-_,r+k,0,h.minX,h.maxX,l),b=At(t,u,r+w,r+M,0,h.minX,h.maxX,l),t=null,x&&(m=At(x,u,n-_,n+k,1,h.minY,h.maxY,l),g=At(x,u,n+w,n+M,1,h.minY,h.maxY,l),x=null),b&&(v=At(b,u,n-_,n+k,1,h.minY,h.maxY,l),y=At(b,u,n+w,n+M,1,h.minY,h.maxY,l),b=null),c>1&&console.timeEnd("clipping"),s.push(m||[],e+1,2*r,2*n),s.push(g||[],e+1,2*r,2*n+1),s.push(v||[],e+1,2*r+1,2*n),s.push(y||[],e+1,2*r+1,2*n+1)}}},jt.prototype.getTile=function(t,e,r){var n=this.options,i=n.extent,a=n.debug;if(t<0||t>24)return null;var o=1<1&&console.log("drilling down to z%d-%d-%d",t,e,r);for(var l,c=t,u=e,f=r;!l&&c>0;)c--,u=Math.floor(u/2),f=Math.floor(f/2),l=this.tiles[Vt(c,u,f)];return l&&l.source?(a>1&&console.log("found parent tile z%d-%d-%d",c,u,f),a>1&&console.time("drilling down"),this.splitTile(l.source,c,u,f,t,e,r),a>1&&console.timeEnd("drilling down"),this.tiles[s]?Dt(this.tiles[s],i):null):null};var qt=function(e){function r(t,r,n){e.call(this,t,r,Ut),n&&(this.loadGeoJSON=n)}return e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r,r.prototype.loadData=function(t,e){this._pendingCallback&&this._pendingCallback(null,{abandoned:!0}),this._pendingCallback=e,this._pendingLoadDataParams=t,this._state&&"Idle"!==this._state?this._state="NeedsLoadData":(this._state="Coalescing",this._loadData())},r.prototype._loadData=function(){var t=this;if(this._pendingCallback&&this._pendingLoadDataParams){var e=this._pendingCallback,r=this._pendingLoadDataParams;delete this._pendingCallback,delete this._pendingLoadDataParams,this.loadGeoJSON(r,function(n,i){if(n||!i)return e(n);if("object"!=typeof i)return e(new Error("Input data is not a valid GeoJSON object."));!function t(e,r){switch(e&&e.type||null){case"FeatureCollection":return e.features=e.features.map(z(t,r)),e;case"Feature":return e.geometry=t(e.geometry,r),e;case"Polygon":case"MultiPolygon":return function(t,e){return"Polygon"===t.type?t.coordinates=O(t.coordinates,e):"MultiPolygon"===t.type&&(t.coordinates=t.coordinates.map(z(O,e))),t}(e,r);default:return e}}(i,!0);try{t._geoJSONIndex=r.cluster?function(t){return new ot(t)}(r.superclusterOptions).load(i.features):new jt(i,r.geojsonVtOptions)}catch(n){return e(n)}t.loaded={};var a={};if(r.request&&r.request.collectResourceTiming){var o=w(r.request.url);o&&(a.resourceTiming={},a.resourceTiming[r.source]=JSON.parse(JSON.stringify(o)))}e(null,a)})}},r.prototype.coalesce=function(){"Coalescing"===this._state?this._state="Idle":"NeedsLoadData"===this._state&&(this._state="Coalescing",this._loadData())},r.prototype.reloadTile=function(t,r){var n=this.loaded,i=t.uid;return n&&n[i]?e.prototype.reloadTile.call(this,t,r):this.loadTile(t,r)},r.prototype.loadGeoJSON=function(e,r){if(e.request)t.getJSON(e.request,r);else{if("string"!=typeof e.data)return r(new Error("Input data is not a valid GeoJSON object."));try{return r(null,JSON.parse(e.data))}catch(t){return r(new Error("Input data is not a valid GeoJSON object."))}}},r.prototype.removeSource=function(t,e){this._pendingCallback&&this._pendingCallback(null,{abandoned:!0}),e()},r}(M),Ht=function(e){var r=this;this.self=e,this.actor=new t.default$7(e,this),this.layerIndexes={},this.workerSourceTypes={vector:M,geojson:qt},this.workerSources={},this.demWorkerSources={},this.self.registerWorkerSource=function(t,e){if(r.workerSourceTypes[t])throw new Error('Worker source with name "'+t+'" already registered.');r.workerSourceTypes[t]=e},this.self.registerRTLTextPlugin=function(e){if(t.plugin.isLoaded())throw new Error("RTL text plugin already registered.");t.plugin.applyArabicShaping=e.applyArabicShaping,t.plugin.processBidirectionalText=e.processBidirectionalText}};return Ht.prototype.setLayers=function(t,e,r){this.getLayerIndex(t).replace(e),r()},Ht.prototype.updateLayers=function(t,e,r){this.getLayerIndex(t).update(e.layers,e.removedIds),r()},Ht.prototype.loadTile=function(t,e,r){this.getWorkerSource(t,e.type,e.source).loadTile(e,r)},Ht.prototype.loadDEMTile=function(t,e,r){this.getDEMWorkerSource(t,e.source).loadTile(e,r)},Ht.prototype.reloadTile=function(t,e,r){this.getWorkerSource(t,e.type,e.source).reloadTile(e,r)},Ht.prototype.abortTile=function(t,e,r){this.getWorkerSource(t,e.type,e.source).abortTile(e,r)},Ht.prototype.removeTile=function(t,e,r){this.getWorkerSource(t,e.type,e.source).removeTile(e,r)},Ht.prototype.removeDEMTile=function(t,e){this.getDEMWorkerSource(t,e.source).removeTile(e)},Ht.prototype.removeSource=function(t,e,r){if(this.workerSources[t]&&this.workerSources[t][e.type]&&this.workerSources[t][e.type][e.source]){var n=this.workerSources[t][e.type][e.source];delete this.workerSources[t][e.type][e.source],void 0!==n.removeSource?n.removeSource(e,r):r()}},Ht.prototype.loadWorkerSource=function(t,e,r){try{this.self.importScripts(e.url),r()}catch(t){r(t.toString())}},Ht.prototype.loadRTLTextPlugin=function(e,r,n){try{t.plugin.isLoaded()||(this.self.importScripts(r),n(t.plugin.isLoaded()?null:new Error("RTL Text Plugin failed to import scripts from "+r)))}catch(t){n(t.toString())}},Ht.prototype.getLayerIndex=function(t){var e=this.layerIndexes[t];return e||(e=this.layerIndexes[t]=new n),e},Ht.prototype.getWorkerSource=function(t,e,r){var n=this;if(this.workerSources[t]||(this.workerSources[t]={}),this.workerSources[t][e]||(this.workerSources[t][e]={}),!this.workerSources[t][e][r]){var i={send:function(e,r,i){n.actor.send(e,r,i,t)}};this.workerSources[t][e][r]=new this.workerSourceTypes[e](i,this.getLayerIndex(t))}return this.workerSources[t][e][r]},Ht.prototype.getDEMWorkerSource=function(t,e){return this.demWorkerSources[t]||(this.demWorkerSources[t]={}),this.demWorkerSources[t][e]||(this.demWorkerSources[t][e]=new A),this.demWorkerSources[t][e]},"undefined"!=typeof WorkerGlobalScope&&"undefined"!=typeof self&&self instanceof WorkerGlobalScope&&new Ht(self),Ht}),i(0,function(t){var e=t.createCommonjsModule(function(t){function e(t){return!!("undefined"!=typeof window&&"undefined"!=typeof document&&Array.prototype&&Array.prototype.every&&Array.prototype.filter&&Array.prototype.forEach&&Array.prototype.indexOf&&Array.prototype.lastIndexOf&&Array.prototype.map&&Array.prototype.some&&Array.prototype.reduce&&Array.prototype.reduceRight&&Array.isArray&&Function.prototype&&Function.prototype.bind&&Object.keys&&Object.create&&Object.getPrototypeOf&&Object.getOwnPropertyNames&&Object.isSealed&&Object.isFrozen&&Object.isExtensible&&Object.getOwnPropertyDescriptor&&Object.defineProperty&&Object.defineProperties&&Object.seal&&Object.freeze&&Object.preventExtensions&&"JSON"in window&&"parse"in JSON&&"stringify"in JSON&&function(){if(!("Worker"in window&&"Blob"in window&&"URL"in window))return!1;var t,e,r=new Blob([""],{type:"text/javascript"}),n=URL.createObjectURL(r);try{e=new Worker(n),t=!0}catch(e){t=!1}return e&&e.terminate(),URL.revokeObjectURL(n),t}()&&"Uint8ClampedArray"in window&&function(t){return void 0===r[t]&&(r[t]=function(t){var r=document.createElement("canvas"),n=Object.create(e.webGLContextAttributes);return n.failIfMajorPerformanceCaveat=t,r.probablySupportsContext?r.probablySupportsContext("webgl",n)||r.probablySupportsContext("experimental-webgl",n):r.supportsContext?r.supportsContext("webgl",n)||r.supportsContext("experimental-webgl",n):r.getContext("webgl",n)||r.getContext("experimental-webgl",n)}(t)),r[t]}(t&&t.failIfMajorPerformanceCaveat))}t.exports?t.exports=e:window&&(window.mapboxgl=window.mapboxgl||{},window.mapboxgl.supported=e);var r={};e.webGLContextAttributes={antialias:!1,alpha:!0,stencil:!0,depth:!0}}),r=t.default.performance&&t.default.performance.now?t.default.performance.now.bind(t.default.performance):Date.now.bind(Date),n=t.default.requestAnimationFrame||t.default.mozRequestAnimationFrame||t.default.webkitRequestAnimationFrame||t.default.msRequestAnimationFrame,i=t.default.cancelAnimationFrame||t.default.mozCancelAnimationFrame||t.default.webkitCancelAnimationFrame||t.default.msCancelAnimationFrame,a={now:r,frame:function(t){return n(t)},cancelFrame:function(t){return i(t)},getImageData:function(e){var r=t.default.document.createElement("canvas"),n=r.getContext("2d");if(!n)throw new Error("failed to create canvas 2d context");return r.width=e.width,r.height=e.height,n.drawImage(e,0,0,e.width,e.height),n.getImageData(0,0,e.width,e.height)},hardwareConcurrency:t.default.navigator.hardwareConcurrency||4,get devicePixelRatio(){return t.default.devicePixelRatio},supportsWebp:!1};if(t.default.document){var o=t.default.document.createElement("img");o.onload=function(){a.supportsWebp=!0},o.src="data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="}var s={create:function(e,r,n){var i=t.default.document.createElement(e);return r&&(i.className=r),n&&n.appendChild(i),i},createNS:function(e,r){return t.default.document.createElementNS(e,r)}},l=t.default.document?t.default.document.documentElement.style:null;function c(t){if(!l)return null;for(var e=0;e=0?0:e.button},s.remove=function(t){t.parentNode&&t.parentNode.removeChild(t)};var g={API_URL:"https://api.mapbox.com",REQUIRE_ACCESS_TOKEN:!0,ACCESS_TOKEN:null},v="See https://www.mapbox.com/api-documentation/#access-tokens";function y(t,e){var r=A(g.API_URL);if(t.protocol=r.protocol,t.authority=r.authority,"/"!==r.path&&(t.path=""+r.path+t.path),!g.REQUIRE_ACCESS_TOKEN)return T(t);if(!(e=e||g.ACCESS_TOKEN))throw new Error("An API access token is required to use Mapbox GL. "+v);if("s"===e[0])throw new Error("Use a public access token (pk.*) with Mapbox GL, not a secret access token (sk.*). "+v);return t.params.push("access_token="+e),T(t)}function x(t){return 0===t.indexOf("mapbox:")}var b=function(t,e){if(!x(t))return t;var r=A(t);return r.path="/v4/"+r.authority+".json",r.params.push("secure"),y(r,e)},_=function(t,e,r,n){var i=A(t);return x(t)?(i.path="/styles/v1"+i.path+"/sprite"+e+r,y(i,n)):(i.path+=""+e+r,T(i))},w=/(\.(png|jpg)\d*)(?=$)/,k=function(t,e,r){if(!e||!x(e))return t;var n=A(t),i=a.devicePixelRatio>=2||512===r?"@2x":"",o=a.supportsWebp?".webp":"$1";return n.path=n.path.replace(w,""+i+o),function(t){for(var e=0;e=0?1.2:1))}function R(t,e,r,n,i,a,o){for(var s=0;s65535)e(new Error("glyphs > 65535 not supported"));else{var l=a.requests[s];l||(l=a.requests[s]=[],F.loadGlyphRange(r,s,n.url,n.requestTransform,function(t,e){if(e)for(var r in e)a.glyphs[+r]=e[+r];for(var n=0,i=l;nthis.height)return t.warnOnce("LineAtlas out of space"),null;for(var a=0,o=0;o90||this.lat<-90)throw new Error("Invalid LngLat latitude value: must be between -90 and 90")};G.prototype.wrap=function(){return new G(t.wrap(this.lng,-180,180),this.lat)},G.prototype.toArray=function(){return[this.lng,this.lat]},G.prototype.toString=function(){return"LngLat("+this.lng+", "+this.lat+")"},G.prototype.toBounds=function(t){var e=360*t/40075017,r=e/Math.cos(Math.PI/180*this.lat);return new W(new G(this.lng-r,this.lat-e),new G(this.lng+r,this.lat+e))},G.convert=function(t){if(t instanceof G)return t;if(Array.isArray(t)&&(2===t.length||3===t.length))return new G(Number(t[0]),Number(t[1]));if(!Array.isArray(t)&&"object"==typeof t&&null!==t)return new G(Number(t.lng),Number(t.lat));throw new Error("`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, or an array of [, ]")};var W=function(t,e){t&&(e?this.setSouthWest(t).setNorthEast(e):4===t.length?this.setSouthWest([t[0],t[1]]).setNorthEast([t[2],t[3]]):this.setSouthWest(t[0]).setNorthEast(t[1]))};W.prototype.setNorthEast=function(t){return this._ne=t instanceof G?new G(t.lng,t.lat):G.convert(t),this},W.prototype.setSouthWest=function(t){return this._sw=t instanceof G?new G(t.lng,t.lat):G.convert(t),this},W.prototype.extend=function(t){var e,r,n=this._sw,i=this._ne;if(t instanceof G)e=t,r=t;else{if(!(t instanceof W))return Array.isArray(t)?t.every(Array.isArray)?this.extend(W.convert(t)):this.extend(G.convert(t)):this;if(e=t._sw,r=t._ne,!e||!r)return this}return n||i?(n.lng=Math.min(e.lng,n.lng),n.lat=Math.min(e.lat,n.lat),i.lng=Math.max(r.lng,i.lng),i.lat=Math.max(r.lat,i.lat)):(this._sw=new G(e.lng,e.lat),this._ne=new G(r.lng,r.lat)),this},W.prototype.getCenter=function(){return new G((this._sw.lng+this._ne.lng)/2,(this._sw.lat+this._ne.lat)/2)},W.prototype.getSouthWest=function(){return this._sw},W.prototype.getNorthEast=function(){return this._ne},W.prototype.getNorthWest=function(){return new G(this.getWest(),this.getNorth())},W.prototype.getSouthEast=function(){return new G(this.getEast(),this.getSouth())},W.prototype.getWest=function(){return this._sw.lng},W.prototype.getSouth=function(){return this._sw.lat},W.prototype.getEast=function(){return this._ne.lng},W.prototype.getNorth=function(){return this._ne.lat},W.prototype.toArray=function(){return[this._sw.toArray(),this._ne.toArray()]},W.prototype.toString=function(){return"LngLatBounds("+this._sw.toString()+", "+this._ne.toString()+")"},W.prototype.isEmpty=function(){return!(this._sw&&this._ne)},W.convert=function(t){return!t||t instanceof W?t:new W(t)};var Y=function(t,e,r){this.bounds=W.convert(this.validateBounds(t)),this.minzoom=e||0,this.maxzoom=r||24};Y.prototype.validateBounds=function(t){return Array.isArray(t)&&4===t.length?[Math.max(-180,t[0]),Math.max(-90,t[1]),Math.min(180,t[2]),Math.min(90,t[3])]:[-180,-90,180,90]},Y.prototype.contains=function(t){var e=Math.floor(this.lngX(this.bounds.getWest(),t.z)),r=Math.floor(this.latY(this.bounds.getNorth(),t.z)),n=Math.ceil(this.lngX(this.bounds.getEast(),t.z)),i=Math.ceil(this.latY(this.bounds.getSouth(),t.z));return t.x>=e&&t.x=r&&t.y0&&(l[new t.OverscaledTileID(e.overscaledZ,a,r.z,i,r.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,e.wrap,r.z,r.x,r.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,s,r.z,o,r.y-1).key]={backfilled:!1}),r.y+10&&(n.resourceTiming=e._resourceTiming,e._resourceTiming=[]),e.fire(new t.Event("data",n))}})},r.prototype.onAdd=function(t){this.map=t,this.load()},r.prototype.setData=function(e){var r=this;return this._data=e,this.fire(new t.Event("dataloading",{dataType:"source"})),this._updateWorkerData(function(e){if(e)return r.fire(new t.ErrorEvent(e));var n={dataType:"source",sourceDataType:"content"};r._collectResourceTiming&&r._resourceTiming&&r._resourceTiming.length>0&&(n.resourceTiming=r._resourceTiming,r._resourceTiming=[]),r.fire(new t.Event("data",n))}),this},r.prototype._updateWorkerData=function(e){var r,n,i=this,a=t.extend({},this.workerOptions),o=this._data;"string"==typeof o?(a.request=this.map._transformRequest((r=o,(n=t.default.document.createElement("a")).href=r,n.href),t.ResourceType.Source),a.request.collectResourceTiming=this._collectResourceTiming):a.data=JSON.stringify(o),this.workerID=this.dispatcher.send(this.type+"."+a.source+".loadData",a,function(t,r){i._removed||r&&r.abandoned||(i._loaded=!0,r&&r.resourceTiming&&r.resourceTiming[i.id]&&(i._resourceTiming=r.resourceTiming[i.id].slice(0)),i.dispatcher.send(i.type+"."+a.source+".coalesce",null,null,i.workerID),e(t))},this.workerID)},r.prototype.loadTile=function(t,e){var r=this,n=void 0===t.workerID?"loadTile":"reloadTile",i={type:this.type,uid:t.uid,tileID:t.tileID,zoom:t.tileID.overscaledZ,maxZoom:this.maxzoom,tileSize:this.tileSize,source:this.id,pixelRatio:a.devicePixelRatio,showCollisionBoxes:this.map.showCollisionBoxes};t.workerID=this.dispatcher.send(n,i,function(i,a){return t.unloadVectorData(),t.aborted?e(null):i?e(i):(t.loadVectorData(a,r.map.painter,"reloadTile"===n),e(null))},this.workerID)},r.prototype.abortTile=function(t){t.aborted=!0},r.prototype.unloadTile=function(t){t.unloadVectorData(),this.dispatcher.send("removeTile",{uid:t.uid,type:this.type,source:this.id},null,t.workerID)},r.prototype.onRemove=function(){this._removed=!0,this.dispatcher.send("removeSource",{type:this.type,source:this.id},null,this.workerID)},r.prototype.serialize=function(){return t.extend({},this._options,{type:this.type,data:this._data})},r.prototype.hasTransition=function(){return!1},r}(t.Evented),K=t.createLayout([{name:"a_pos",type:"Int16",components:2},{name:"a_texture_pos",type:"Int16",components:2}]),Q=function(){this.boundProgram=null,this.boundLayoutVertexBuffer=null,this.boundPaintVertexBuffers=[],this.boundIndexBuffer=null,this.boundVertexOffset=null,this.boundDynamicVertexBuffer=null,this.vao=null};Q.prototype.bind=function(t,e,r,n,i,a,o,s){this.context=t;for(var l=this.boundPaintVertexBuffers.length!==n.length,c=0;!l&&c>s.z,c=new t.default$1(s.x*l,s.y*l),u=new t.default$1(c.x+l,c.y+l),f=this.segments.prepareSegment(4,n,i);n.emplaceBack(c.x,c.y,c.x,c.y),n.emplaceBack(u.x,c.y,u.x,c.y),n.emplaceBack(c.x,u.y,c.x,u.y),n.emplaceBack(u.x,u.y,u.x,u.y);var h=f.vertexLength;i.emplaceBack(h,h+1,h+2),i.emplaceBack(h+1,h+2,h+3),f.vertexLength+=4,f.primitiveLength+=2}this.maskedBoundsBuffer=r.createVertexBuffer(n,K.members),this.maskedIndexBuffer=r.createIndexBuffer(i)}},st.prototype.hasData=function(){return"loaded"===this.state||"reloading"===this.state||"expired"===this.state},st.prototype.setExpiryData=function(e){var r=this.expirationTime;if(e.cacheControl){var n=t.parseCacheControl(e.cacheControl);n["max-age"]&&(this.expirationTime=Date.now()+1e3*n["max-age"])}else e.expires&&(this.expirationTime=new Date(e.expires).getTime());if(this.expirationTime){var i=Date.now(),a=!1;if(this.expirationTime>i)a=!1;else if(r)if(this.expirationTimethis.max){var o=this._getAndRemoveByKey(this.order[0]);o&&this.onRemove(o)}return this},lt.prototype.has=function(t){return t.wrapped().key in this.data},lt.prototype.getAndRemove=function(t){return this.has(t)?this._getAndRemoveByKey(t.wrapped().key):null},lt.prototype._getAndRemoveByKey=function(t){var e=this.data[t].shift();return e.timeout&&clearTimeout(e.timeout),0===this.data[t].length&&delete this.data[t],this.order.splice(this.order.indexOf(t),1),e.value},lt.prototype.get=function(t){return this.has(t)?this.data[t.wrapped().key][0].value:null},lt.prototype.remove=function(t,e){if(!this.has(t))return this;var r=t.wrapped().key,n=void 0===e?0:this.data[r].indexOf(e),i=this.data[r][n];return this.data[r].splice(n,1),i.timeout&&clearTimeout(i.timeout),0===this.data[r].length&&delete this.data[r],this.onRemove(i.value),this.order.splice(this.order.indexOf(r),1),this},lt.prototype.setMaxSize=function(t){for(this.max=t;this.order.length>this.max;){var e=this._getAndRemoveByKey(this.order[0]);e&&this.onRemove(e)}return this};var ct=function(t,e,r){this.context=t;var n=t.gl;this.buffer=n.createBuffer(),this.dynamicDraw=Boolean(r),this.unbindVAO(),t.bindElementBuffer.set(this.buffer),n.bufferData(n.ELEMENT_ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?n.DYNAMIC_DRAW:n.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer};ct.prototype.unbindVAO=function(){this.context.extVertexArrayObject&&this.context.bindVertexArrayOES.set(null)},ct.prototype.bind=function(){this.context.bindElementBuffer.set(this.buffer)},ct.prototype.updateData=function(t){var e=this.context.gl;this.unbindVAO(),this.bind(),e.bufferSubData(e.ELEMENT_ARRAY_BUFFER,0,t.arrayBuffer)},ct.prototype.destroy=function(){var t=this.context.gl;this.buffer&&(t.deleteBuffer(this.buffer),delete this.buffer)};var ut={Int8:"BYTE",Uint8:"UNSIGNED_BYTE",Int16:"SHORT",Uint16:"UNSIGNED_SHORT",Int32:"INT",Uint32:"UNSIGNED_INT",Float32:"FLOAT"},ft=function(t,e,r,n){this.length=e.length,this.attributes=r,this.itemSize=e.bytesPerElement,this.dynamicDraw=n,this.context=t;var i=t.gl;this.buffer=i.createBuffer(),t.bindVertexBuffer.set(this.buffer),i.bufferData(i.ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?i.DYNAMIC_DRAW:i.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer};ft.prototype.bind=function(){this.context.bindVertexBuffer.set(this.buffer)},ft.prototype.updateData=function(t){var e=this.context.gl;this.bind(),e.bufferSubData(e.ARRAY_BUFFER,0,t.arrayBuffer)},ft.prototype.enableAttributes=function(t,e){for(var r=0;r1||(Math.abs(r)>1&&(1===Math.abs(r+i)?r+=i:1===Math.abs(r-i)&&(r-=i)),e.dem&&t.dem&&(t.dem.backfillBorder(e.dem,r,n),t.neighboringTiles&&t.neighboringTiles[a]&&(t.neighboringTiles[a].backfilled=!0)))}},r.prototype.getTile=function(t){return this.getTileByID(t.key)},r.prototype.getTileByID=function(t){return this._tiles[t]},r.prototype.getZoom=function(t){return t.zoom+t.scaleZoom(t.tileSize/this._source.tileSize)},r.prototype._findLoadedChildren=function(t,e,r){var n=!1;for(var i in this._tiles){var a=this._tiles[i];if(!(r[i]||!a.hasData()||a.tileID.overscaledZ<=t.overscaledZ||a.tileID.overscaledZ>e)){var o=Math.pow(2,a.tileID.canonical.z-t.canonical.z);if(Math.floor(a.tileID.canonical.x/o)===t.canonical.x&&Math.floor(a.tileID.canonical.y/o)===t.canonical.y)for(r[i]=a.tileID,n=!0;a&&a.tileID.overscaledZ-1>t.overscaledZ;){var s=a.tileID.scaledTo(a.tileID.overscaledZ-1);if(!s)break;(a=this._tiles[s.key])&&a.hasData()&&(delete r[i],r[s.key]=s)}}}return n},r.prototype.findLoadedParent=function(t,e,r){for(var n=t.overscaledZ-1;n>=e;n--){var i=t.scaledTo(n);if(!i)return;var a=String(i.key),o=this._tiles[a];if(o&&o.hasData())return r[a]=i,o;if(this._cache.has(i))return r[a]=i,this._cache.get(i)}},r.prototype.updateCacheSize=function(t){var e=(Math.ceil(t.width/this._source.tileSize)+1)*(Math.ceil(t.height/this._source.tileSize)+1),r=Math.floor(5*e),n="number"==typeof this._maxTileCacheSize?Math.min(this._maxTileCacheSize,r):r;this._cache.setMaxSize(n)},r.prototype.handleWrapJump=function(t){var e=(t-(void 0===this._prevLng?t:this._prevLng))/360,r=Math.round(e);if(this._prevLng=t,r){var n={};for(var i in this._tiles){var a=this._tiles[i];a.tileID=a.tileID.unwrapTo(a.tileID.wrap+r),n[a.tileID.key]=a}for(var o in this._tiles=n,this._timers)clearTimeout(this._timers[o]),delete this._timers[o];for(var s in this._tiles){var l=this._tiles[s];this._setTileReloadTimer(s,l)}}},r.prototype.update=function(e){var n=this;if(this.transform=e,this._sourceLoaded&&!this._paused){var i;this.updateCacheSize(e),this.handleWrapJump(this.transform.center.lng),this._coveredTiles={},this.used?this._source.tileID?i=e.getVisibleUnwrappedCoordinates(this._source.tileID).map(function(e){return new t.OverscaledTileID(e.canonical.z,e.wrap,e.canonical.z,e.canonical.x,e.canonical.y)}):(i=e.coveringTiles({tileSize:this._source.tileSize,minzoom:this._source.minzoom,maxzoom:this._source.maxzoom,roundZoom:this._source.roundZoom,reparseOverscaled:this._source.reparseOverscaled}),this._source.hasTile&&(i=i.filter(function(t){return n._source.hasTile(t)}))):i=[];var o,s=(this._source.roundZoom?Math.round:Math.floor)(this.getZoom(e)),l=Math.max(s-r.maxOverzooming,this._source.minzoom),c=Math.max(s+r.maxUnderzooming,this._source.minzoom),u=this._updateRetainedTiles(i,s),f={};if(Zt(this._source.type))for(var h=Object.keys(u),p=0;p=a.now())){n._findLoadedChildren(m,c,u)&&(u[d]=m);var v=n.findLoadedParent(m,l,f);v&&n._addTile(v.tileID)}}for(o in f)u[o]||(n._coveredTiles[o]=!0);for(o in f)u[o]=f[o];for(var y=t.keysDifference(this._tiles,u),x=0;xthis._source.maxzoom){var h=l.children(this._source.maxzoom)[0],p=this.getTile(h);p&&p.hasData()?n[h.key]=h:f=!1}else{this._findLoadedChildren(l,o,n);for(var d=l.children(this._source.maxzoom),m=0;m=a;--g){var v=l.scaledTo(g);if(i[v.key])break;if(i[v.key]=!0,!(c=this.getTile(v))&&u&&(c=this._addTile(v)),c&&(n[v.key]=v,u=c.wasRequested(),c.hasData()))break}}}return n},r.prototype._addTile=function(e){var r=this._tiles[e.key];if(r)return r;(r=this._cache.getAndRemove(e))&&(this._setTileReloadTimer(e.key,r),r.tileID=e);var n=Boolean(r);return n||(r=new st(e,this._source.tileSize*e.overscaleFactor()),this._loadTile(r,this._tileLoaded.bind(this,r,e.key,r.state))),r?(r.uses++,this._tiles[e.key]=r,n||this._source.fire(new t.Event("dataloading",{tile:r,coord:r.tileID,dataType:"source"})),r):null},r.prototype._setTileReloadTimer=function(t,e){var r=this;t in this._timers&&(clearTimeout(this._timers[t]),delete this._timers[t]);var n=e.getExpiryTimeout();n&&(this._timers[t]=setTimeout(function(){r._reloadTile(t,"expired"),delete r._timers[t]},n))},r.prototype._removeTile=function(t){var e=this._tiles[t];e&&(e.uses--,delete this._tiles[t],this._timers[t]&&(clearTimeout(this._timers[t]),delete this._timers[t]),e.uses>0||(e.hasData()?this._cache.add(e.tileID,e,e.getExpiryTimeout()):(e.aborted=!0,this._abortTile(e),this._unloadTile(e))))},r.prototype.clearTiles=function(){for(var t in this._shouldReloadOnResume=!1,this._paused=!1,this._tiles)this._removeTile(t);this._cache.reset()},r.prototype.tilesIn=function(e,r){for(var n=[],i=this.getIds(),a=1/0,o=1/0,s=-1/0,l=-1/0,c=e[0].zoom,u=0;u=0&&v[1].y+g>=0){for(var y=[],x=0;x=a.now())return!0}return!1},r}(t.Evented);function Xt(e,r){var n=r.zoomTo(e.canonical.z);return new t.default$1((n.column-(e.canonical.x+e.wrap*Math.pow(2,e.canonical.z)))*t.default$8,(n.row-e.canonical.y)*t.default$8)}function Zt(t){return"raster"===t||"image"===t||"video"===t}function $t(){return new t.default.Worker(En.workerUrl)}Yt.maxOverzooming=10,Yt.maxUnderzooming=3;var Jt,Kt=function(){this.active={}};function Qt(e,r){var n={};for(var i in e)"ref"!==i&&(n[i]=e[i]);return t.default$18.forEach(function(t){t in r&&(n[t]=r[t])}),n}function te(t){t=t.slice();for(var e=Object.create(null),r=0;rthis.width||n<0||e>this.height)return!i&&[];var a=[];if(t<=0&&e<=0&&this.width<=r&&this.height<=n){if(i)return!0;for(var o=0;o0:a},ce.prototype._queryCircle=function(t,e,r,n){var i=t-r,a=t+r,o=e-r,s=e+r;if(a<0||i>this.width||s<0||o>this.height)return!n&&[];var l=[],c={hitTest:n,circle:{x:t,y:e,radius:r},seenUids:{box:{},circle:{}}};return this._forEachCell(i,o,a,s,this._queryCellCircle,l,c),n?l.length>0:l},ce.prototype.query=function(t,e,r,n){return this._query(t,e,r,n,!1)},ce.prototype.hitTest=function(t,e,r,n){return this._query(t,e,r,n,!0)},ce.prototype.hitTestCircle=function(t,e,r){return this._queryCircle(t,e,r,!0)},ce.prototype._queryCell=function(t,e,r,n,i,a,o){var s=o.seenUids,l=this.boxCells[i];if(null!==l)for(var c=this.bboxes,u=0,f=l;u=c[p+0]&&n>=c[p+1]){if(o.hitTest)return a.push(!0),!0;a.push({key:this.boxKeys[h],x1:c[p],y1:c[p+1],x2:c[p+2],y2:c[p+3]})}}}var d=this.circleCells[i];if(null!==d)for(var m=this.circles,g=0,v=d;go*o+s*s},ce.prototype._circleAndRectCollide=function(t,e,r,n,i,a,o){var s=(a-n)/2,l=Math.abs(t-(n+s));if(l>s+r)return!1;var c=(o-i)/2,u=Math.abs(e-(i+c));if(u>c+r)return!1;if(l<=s||u<=c)return!0;var f=l-s,h=u-c;return f*f+h*h<=r*r};var ue=t.default$19.layout;function fe(e,r,n,i,a){var o=t.mat4.identity(new Float32Array(16));return r?(t.mat4.identity(o),t.mat4.scale(o,o,[1/a,1/a,1]),n||t.mat4.rotateZ(o,o,i.angle)):(t.mat4.scale(o,o,[i.width/2,-i.height/2,1]),t.mat4.translate(o,o,[1,-1,0]),t.mat4.multiply(o,o,e)),o}function he(e,r,n,i,a){var o=t.mat4.identity(new Float32Array(16));return r?(t.mat4.multiply(o,o,e),t.mat4.scale(o,o,[a,a,1]),n||t.mat4.rotateZ(o,o,-i.angle)):(t.mat4.scale(o,o,[1,-1,1]),t.mat4.translate(o,o,[-1,-1,0]),t.mat4.scale(o,o,[2/i.width,2/i.height,1])),o}function pe(e,r){var n=[e.x,e.y,0,1];ke(n,n,r);var i=n[3];return{point:new t.default$1(n[0]/i,n[1]/i),signedDistanceFromCamera:i}}function de(t,e){var r=t[0]/t[3],n=t[1]/t[3];return r>=-e[0]&&r<=e[0]&&n>=-e[1]&&n<=e[1]}function me(e,r,n,i,a,o,s,l){var c=i?e.textSizeData:e.iconSizeData,u=t.evaluateSizeForZoom(c,n.transform.zoom,ue.properties[i?"text-size":"icon-size"]),f=[256/n.width*2+1,256/n.height*2+1],h=i?e.text.dynamicLayoutVertexArray:e.icon.dynamicLayoutVertexArray;h.clear();for(var p=e.lineVertexArray,d=i?e.text.placedSymbolArray:e.icon.placedSymbolArray,m=n.transform.width/n.transform.height,g=!1,v=0;vMath.abs(n.x-r.x)*i?{useVertical:!0}:(e===t.WritingMode.vertical?r.yn.x)?{needsFlipping:!0}:null}function ye(e,r,n,i,a,o,s,l,c,u,f,h,p,d){var m,g=r/24,v=e.lineOffsetX*r,y=e.lineOffsetY*r;if(e.numGlyphs>1){var x=e.glyphStartIndex+e.numGlyphs,b=e.lineStartIndex,_=e.lineStartIndex+e.lineLength,w=ge(g,l,v,y,n,f,h,e,c,o,p,!1);if(!w)return{notEnoughRoom:!0};var k=pe(w.first.point,s).point,M=pe(w.last.point,s).point;if(i&&!n){var A=ve(e.writingMode,k,M,d);if(A)return A}m=[w.first];for(var T=e.glyphStartIndex+1;T0?L.point:xe(h,C,S,1,a),O=ve(e.writingMode,S,z,d);if(O)return O}var I=be(g*l.getoffsetX(e.glyphStartIndex),v,y,n,f,h,e.segment,e.lineStartIndex,e.lineStartIndex+e.lineLength,c,o,p,!1);if(!I)return{notEnoughRoom:!0};m=[I]}for(var P=0,D=m;P0?1:-1,g=0;i&&(m*=-1,g=Math.PI),m<0&&(g+=Math.PI);for(var v=m>0?l+s:l+s+1,y=v,x=a,b=a,_=0,w=0,k=Math.abs(d);_+w<=k;){if((v+=m)=c)return null;if(b=x,void 0===(x=h[v])){var M=new t.default$1(u.getx(v),u.gety(v)),A=pe(M,f);if(A.signedDistanceFromCamera>0)x=h[v]=A.point;else{var T=v-m;x=xe(0===_?o:new t.default$1(u.getx(T),u.gety(T)),M,b,k-_+1,f)}}_+=w,w=b.dist(x)}var S=(k-_)/w,E=x.sub(b),C=E.mult(S)._add(b);return C._add(E._unit()._perp()._mult(n*m)),{point:C,angle:g+Math.atan2(x.y-b.y,x.x-b.x),tileDistance:p?{prevTileDistance:v-m===y?0:u.gettileUnitDistanceFromAnchor(v-m),lastSegmentViewportDistance:k-_}:null}}var _e=new Float32Array([-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0]);function we(t,e){for(var r=0;rT)Ae(e,S,!1);else{var O=this.projectPoint(u,E,C),I=L*k;if(d.length>0){var P=O.x-d[d.length-4],D=O.y-d[d.length-3];if(I*I*2>P*P+D*D&&S+8-A&&R=this.screenRightBoundary||n<100||e>this.screenBottomBoundary};var Se=t.default$19.layout,Ee=function(t,e,r,n){this.opacity=t?Math.max(0,Math.min(1,t.opacity+(t.placed?e:-e))):n&&r?1:0,this.placed=r};Ee.prototype.isHidden=function(){return 0===this.opacity&&!this.placed};var Ce=function(t,e,r,n,i){this.text=new Ee(t?t.text:null,e,r,i),this.icon=new Ee(t?t.icon:null,e,n,i)};Ce.prototype.isHidden=function(){return this.text.isHidden()&&this.icon.isHidden()};var Le=function(t,e,r){this.text=t,this.icon=e,this.skipFade=r},ze=function(t,e){this.transform=t.clone(),this.collisionIndex=new Me(this.transform),this.placements={},this.opacities={},this.stale=!1,this.fadeDuration=e,this.retainedQueryData={}};function Oe(t,e,r){t.emplaceBack(e?1:0,r?1:0),t.emplaceBack(e?1:0,r?1:0),t.emplaceBack(e?1:0,r?1:0),t.emplaceBack(e?1:0,r?1:0)}ze.prototype.placeLayerTile=function(e,r,n,i){var a=r.getBucket(e),o=r.latestFeatureIndex;if(a&&o&&e.id===a.layerIds[0]){var s=r.collisionBoxArray,l=a.layers[0].layout,c=Math.pow(2,this.transform.zoom-r.tileID.overscaledZ),u=r.tileSize/t.default$8,f=this.transform.calculatePosMatrix(r.tileID.toUnwrapped()),h=fe(f,"map"===l.get("text-pitch-alignment"),"map"===l.get("text-rotation-alignment"),this.transform,Te(r,1,this.transform.zoom)),p=fe(f,"map"===l.get("icon-pitch-alignment"),"map"===l.get("icon-rotation-alignment"),this.transform,Te(r,1,this.transform.zoom));this.retainedQueryData[a.bucketInstanceId]=new function(t,e,r,n,i){this.bucketInstanceId=t,this.featureIndex=e,this.sourceLayerIndex=r,this.bucketIndex=n,this.tileID=i}(a.bucketInstanceId,o,a.sourceLayerIndex,a.index,r.tileID),this.placeLayerBucket(a,f,h,p,c,u,n,i,s)}},ze.prototype.placeLayerBucket=function(e,r,n,i,a,o,s,l,c){for(var u=e.layers[0].layout,f=t.evaluateSizeForZoom(e.textSizeData,this.transform.zoom,Se.properties["text-size"]),h=!e.hasTextData()||u.get("text-optional"),p=!e.hasIconData()||u.get("icon-optional"),d=0,m=e.symbolInstances;d0,x=x&&b.offscreen);var A=g.collisionArrays.textCircles;if(A){var T=e.text.placedSymbolArray.get(g.placedTextSymbolIndices[0]),S=t.evaluateSizeForFeature(e.textSizeData,f,T);_=this.collisionIndex.placeCollisionCircles(A,u.get("text-allow-overlap"),a,o,g.key,T,e.lineVertexArray,e.glyphOffsetArray,S,r,n,s,"map"===u.get("text-pitch-alignment")),v=u.get("text-allow-overlap")||_.circles.length>0,x=x&&_.offscreen}g.collisionArrays.iconFeatureIndex&&(M=g.collisionArrays.iconFeatureIndex),g.collisionArrays.iconBox&&(y=(w=this.collisionIndex.placeCollisionBox(g.collisionArrays.iconBox,u.get("icon-allow-overlap"),o,r)).box.length>0,x=x&&w.offscreen),h||p?p?h||(y=y&&v):v=y&&v:y=v=y&&v,v&&b&&this.collisionIndex.insertCollisionBox(b.box,u.get("text-ignore-placement"),e.bucketInstanceId,k),y&&w&&this.collisionIndex.insertCollisionBox(w.box,u.get("icon-ignore-placement"),e.bucketInstanceId,M),v&&_&&this.collisionIndex.insertCollisionCircles(_.circles,u.get("text-ignore-placement"),e.bucketInstanceId,k),this.placements[g.crossTileID]=new Le(v,y,x||e.justReloaded),l[g.crossTileID]=!0}}e.justReloaded=!1},ze.prototype.commit=function(t,e){this.commitTime=e;var r=!1,n=t&&0!==this.fadeDuration?(this.commitTime-t.commitTime)/this.fadeDuration:1,i=t?t.opacities:{};for(var a in this.placements){var o=this.placements[a],s=i[a];s?(this.opacities[a]=new Ce(s,n,o.text,o.icon),r=r||o.text!==s.text.placed||o.icon!==s.icon.placed):(this.opacities[a]=new Ce(null,n,o.text,o.icon,o.skipFade),r=r||o.text||o.icon)}for(var l in i){var c=i[l];if(!this.opacities[l]){var u=new Ce(c,n,!1,!1);u.isHidden()||(this.opacities[l]=u,r=r||c.text.placed||c.icon.placed)}}r?this.lastPlacementChangeTime=e:"number"!=typeof this.lastPlacementChangeTime&&(this.lastPlacementChangeTime=t?t.lastPlacementChangeTime:e)},ze.prototype.updateLayerOpacities=function(t,e){for(var r={},n=0,i=e;n0||s.numVerticalGlyphVertices>0,f=s.numIconVertices>0;if(u){for(var h=je(c.text),p=(s.numGlyphVertices+s.numVerticalGlyphVertices)/4,d=0;dt},ze.prototype.setStale=function(){this.stale=!0};var Ie=Math.pow(2,25),Pe=Math.pow(2,24),De=Math.pow(2,17),Re=Math.pow(2,16),Be=Math.pow(2,9),Fe=Math.pow(2,8),Ne=Math.pow(2,1);function je(t){if(0===t.opacity&&!t.placed)return 0;if(1===t.opacity&&t.placed)return 4294967295;var e=t.placed?1:0,r=Math.floor(127*t.opacity);return r*Ie+e*Pe+r*De+e*Re+r*Be+e*Fe+r*Ne+e}var Ve=function(){this._currentTileIndex=0,this._seenCrossTileIDs={}};Ve.prototype.continuePlacement=function(t,e,r,n,i){for(;this._currentTileIndex2};this._currentPlacementIndex>=0;){var s=e[t[n._currentPlacementIndex]],l=n.placement.collisionIndex.transform.zoom;if("symbol"===s.type&&(!s.minzoom||s.minzoom<=l)&&(!s.maxzoom||s.maxzoom>l)){if(n._inProgressLayer||(n._inProgressLayer=new Ve),n._inProgressLayer.continuePlacement(r[s.source],n.placement,n._showCollisionBoxes,s,o))return;delete n._inProgressLayer}n._currentPlacementIndex--}this._done=!0},Ue.prototype.commit=function(t,e){return this.placement.commit(t,e),this.placement};var qe=512/t.default$8/2,He=function(t,e,r){this.tileID=t,this.indexedSymbolInstances={},this.bucketInstanceId=r;for(var n=0,i=e;nt.overscaledZ)for(var l in s){var c=s[l];c.tileID.isChildOf(t)&&c.findMatches(e.symbolInstances,t,a)}else{var u=s[t.scaledTo(Number(o)).key];u&&u.findMatches(e.symbolInstances,t,a)}}for(var f=0,h=e.symbolInstances;f1?"@2x":"";function c(){if(s)n(s);else if(i&&o){var e=a.getImageData(o),r={};for(var l in i){var c=i[l],u=c.width,f=c.height,h=c.x,p=c.y,d=c.sdf,m=c.pixelRatio,g=new t.RGBAImage({width:u,height:f});t.RGBAImage.copy(e,g,{x:h,y:p},{x:0,y:0},{width:u,height:f}),r[l]={data:g,pixelRatio:m,sdf:d}}n(null,r)}}t.getJSON(r(_(e,l,".json"),t.ResourceType.SpriteJSON),function(t,e){s||(s=t,i=e,c())}),t.getImage(r(_(e,l,".png"),t.ResourceType.SpriteImage),function(t,e){s||(s=t,o=e,c())})}(e.sprite,this.map._transformRequest,function(e,r){if(e)n.fire(new t.ErrorEvent(e));else if(r)for(var i in r)n.imageManager.addImage(i,r[i]);n.imageManager.setLoaded(!0),n.fire(new t.Event("data",{dataType:"style"}))}):this.imageManager.setLoaded(!0),this.glyphManager.setURL(e.glyphs);var o=te(this.stylesheet.layers);this._order=o.map(function(t){return t.id}),this._layers={};for(var s=0,l=o;s0)throw new Error("Unimplemented: "+i.map(function(t){return t.command}).join(", ")+".");return n.forEach(function(t){"setTransition"!==t.command&&r[t.command].apply(r,t.args)}),this.stylesheet=e,!0},r.prototype.addImage=function(e,r){if(this.getImage(e))return this.fire(new t.ErrorEvent(new Error("An image with this name already exists.")));this.imageManager.addImage(e,r),this.fire(new t.Event("data",{dataType:"style"}))},r.prototype.getImage=function(t){return this.imageManager.getImage(t)},r.prototype.removeImage=function(e){if(!this.getImage(e))return this.fire(new t.ErrorEvent(new Error("No image with this name exists.")));this.imageManager.removeImage(e),this.fire(new t.Event("data",{dataType:"style"}))},r.prototype.addSource=function(e,r,n){var i=this;if(this._checkLoaded(),void 0!==this.sourceCaches[e])throw new Error("There is already a source with this ID");if(!r.type)throw new Error("The type property must be defined, but the only the following properties were given: "+Object.keys(r).join(", ")+".");if(!(["vector","raster","geojson","video","image"].indexOf(r.type)>=0&&this._validate(t.validateStyle.source,"sources."+e,r,null,n))){this.map&&this.map._collectResourceTiming&&(r.collectResourceTiming=!0);var a=this.sourceCaches[e]=new Yt(e,r,this.dispatcher);a.style=this,a.setEventedParent(this,function(){return{isSourceLoaded:i.loaded(),source:a.serialize(),sourceId:e}}),a.onAdd(this.map),this._changed=!0}},r.prototype.removeSource=function(e){if(this._checkLoaded(),void 0===this.sourceCaches[e])throw new Error("There is no source with this ID");for(var r in this._layers)if(this._layers[r].source===e)return this.fire(new t.ErrorEvent(new Error('Source "'+e+'" cannot be removed while layer "'+r+'" is using it.')));var n=this.sourceCaches[e];delete this.sourceCaches[e],delete this._updatedSources[e],n.fire(new t.Event("data",{sourceDataType:"metadata",dataType:"source",sourceId:e})),n.setEventedParent(null),n.clearTiles(),n.onRemove&&n.onRemove(this.map),this._changed=!0},r.prototype.setGeoJSONSourceData=function(t,e){this._checkLoaded(),this.sourceCaches[t].getSource().setData(e),this._changed=!0},r.prototype.getSource=function(t){return this.sourceCaches[t]&&this.sourceCaches[t].getSource()},r.prototype.addLayer=function(e,r,n){this._checkLoaded();var i=e.id;if(this.getLayer(i))this.fire(new t.ErrorEvent(new Error('Layer with id "'+i+'" already exists on this map')));else if("object"==typeof e.source&&(this.addSource(i,e.source),e=t.clone(e),e=t.extend(e,{source:i})),!this._validate(t.validateStyle.layer,"layers."+i,e,{arrayIndex:-1},n)){var a=t.default$22(e);this._validateLayer(a),a.setEventedParent(this,{layer:{id:i}});var o=r?this._order.indexOf(r):this._order.length;if(r&&-1===o)this.fire(new t.ErrorEvent(new Error('Layer with id "'+r+'" does not exist on this map.')));else{if(this._order.splice(o,0,i),this._layerOrderChanged=!0,this._layers[i]=a,this._removedLayers[i]&&a.source){var s=this._removedLayers[i];delete this._removedLayers[i],s.type!==a.type?this._updatedSources[a.source]="clear":(this._updatedSources[a.source]="reload",this.sourceCaches[a.source].pause())}this._updateLayer(a)}}},r.prototype.moveLayer=function(e,r){if(this._checkLoaded(),this._changed=!0,this._layers[e]){if(e!==r){var n=this._order.indexOf(e);this._order.splice(n,1);var i=r?this._order.indexOf(r):this._order.length;r&&-1===i?this.fire(new t.ErrorEvent(new Error('Layer with id "'+r+'" does not exist on this map.'))):(this._order.splice(i,0,e),this._layerOrderChanged=!0)}}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be moved.")))},r.prototype.removeLayer=function(e){this._checkLoaded();var r=this._layers[e];if(r){r.setEventedParent(null);var n=this._order.indexOf(e);this._order.splice(n,1),this._layerOrderChanged=!0,this._changed=!0,this._removedLayers[e]=r,delete this._layers[e],delete this._updatedLayers[e],delete this._updatedPaintProps[e]}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be removed.")))},r.prototype.getLayer=function(t){return this._layers[t]},r.prototype.setLayerZoomRange=function(e,r,n){this._checkLoaded();var i=this.getLayer(e);i?i.minzoom===r&&i.maxzoom===n||(null!=r&&(i.minzoom=r),null!=n&&(i.maxzoom=n),this._updateLayer(i)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot have zoom extent.")))},r.prototype.setFilter=function(e,r){this._checkLoaded();var n=this.getLayer(e);if(n){if(!t.default$10(n.filter,r))return null==r?(n.filter=void 0,void this._updateLayer(n)):void(this._validate(t.validateStyle.filter,"layers."+n.id+".filter",r)||(n.filter=t.clone(r),this._updateLayer(n)))}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be filtered.")))},r.prototype.getFilter=function(e){return t.clone(this.getLayer(e).filter)},r.prototype.setLayoutProperty=function(e,r,n){this._checkLoaded();var i=this.getLayer(e);i?t.default$10(i.getLayoutProperty(r),n)||(i.setLayoutProperty(r,n),this._updateLayer(i)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")))},r.prototype.getLayoutProperty=function(t,e){return this.getLayer(t).getLayoutProperty(e)},r.prototype.setPaintProperty=function(e,r,n){this._checkLoaded();var i=this.getLayer(e);if(i){if(!t.default$10(i.getPaintProperty(r),n)){var a=i._transitionablePaint._values[r].value.isDataDriven();i.setPaintProperty(r,n),(i._transitionablePaint._values[r].value.isDataDriven()||a)&&this._updateLayer(i),this._changed=!0,this._updatedPaintProps[e]=!0}}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")))},r.prototype.getPaintProperty=function(t,e){return this.getLayer(t).getPaintProperty(e)},r.prototype.getTransition=function(){return t.extend({duration:300,delay:0},this.stylesheet&&this.stylesheet.transition)},r.prototype.serialize=function(){var e=this;return t.filterObject({version:this.stylesheet.version,name:this.stylesheet.name,metadata:this.stylesheet.metadata,light:this.stylesheet.light,center:this.stylesheet.center,zoom:this.stylesheet.zoom,bearing:this.stylesheet.bearing,pitch:this.stylesheet.pitch,sprite:this.stylesheet.sprite,glyphs:this.stylesheet.glyphs,transition:this.stylesheet.transition,sources:t.mapObject(this.sourceCaches,function(t){return t.serialize()}),layers:this._order.map(function(t){return e._layers[t].serialize()})},function(t){return void 0!==t})},r.prototype._updateLayer=function(t){this._updatedLayers[t.id]=!0,t.source&&!this._updatedSources[t.source]&&(this._updatedSources[t.source]="reload",this.sourceCaches[t.source].pause()),this._changed=!0},r.prototype._flattenRenderedFeatures=function(t){for(var e=[],r=this._order.length-1;r>=0;r--)for(var n=this._order[r],i=0,a=t;i 0.5) {\n gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5) * alpha;\n }\n\n if (v_notUsed > 0.5) {\n // This box not used, fade it out\n gl_FragColor *= .1;\n }\n}",vertexSource:"attribute vec2 a_pos;\nattribute vec2 a_anchor_pos;\nattribute vec2 a_extrude;\nattribute vec2 a_placed;\n\nuniform mat4 u_matrix;\nuniform vec2 u_extrude_scale;\nuniform float u_camera_to_center_distance;\n\nvarying float v_placed;\nvarying float v_notUsed;\n\nvoid main() {\n vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n highp float collision_perspective_ratio = clamp(\n 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),\n 0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles\n 4.0);\n\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio;\n\n v_placed = a_placed.x;\n v_notUsed = a_placed.y;\n}\n"},collisionCircle:{fragmentSource:"uniform float u_overscale_factor;\n\nvarying float v_placed;\nvarying float v_notUsed;\nvarying float v_radius;\nvarying vec2 v_extrude;\nvarying vec2 v_extrude_scale;\n\nvoid main() {\n float alpha = 0.5;\n\n // Red = collision, hide label\n vec4 color = vec4(1.0, 0.0, 0.0, 1.0) * alpha;\n\n // Blue = no collision, label is showing\n if (v_placed > 0.5) {\n color = vec4(0.0, 0.0, 1.0, 0.5) * alpha;\n }\n\n if (v_notUsed > 0.5) {\n // This box not used, fade it out\n color *= .2;\n }\n\n float extrude_scale_length = length(v_extrude_scale);\n float extrude_length = length(v_extrude) * extrude_scale_length;\n float stroke_width = 15.0 * extrude_scale_length / u_overscale_factor;\n float radius = v_radius * extrude_scale_length;\n\n float distance_to_edge = abs(extrude_length - radius);\n float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge);\n\n gl_FragColor = opacity_t * color;\n}\n",vertexSource:"attribute vec2 a_pos;\nattribute vec2 a_anchor_pos;\nattribute vec2 a_extrude;\nattribute vec2 a_placed;\n\nuniform mat4 u_matrix;\nuniform vec2 u_extrude_scale;\nuniform float u_camera_to_center_distance;\n\nvarying float v_placed;\nvarying float v_notUsed;\nvarying float v_radius;\n\nvarying vec2 v_extrude;\nvarying vec2 v_extrude_scale;\n\nvoid main() {\n vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n highp float collision_perspective_ratio = clamp(\n 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),\n 0.0, // Prevents oversized near-field circles in pitched/overzoomed tiles\n 4.0);\n\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n\n highp float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur\n gl_Position.xy += a_extrude * u_extrude_scale * padding_factor * gl_Position.w * collision_perspective_ratio;\n\n v_placed = a_placed.x;\n v_notUsed = a_placed.y;\n v_radius = abs(a_extrude.y); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius\n\n v_extrude = a_extrude * padding_factor;\n v_extrude_scale = u_extrude_scale * u_camera_to_center_distance * collision_perspective_ratio;\n}\n"},debug:{fragmentSource:"uniform highp vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n"},fill:{fragmentSource:"#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float opacity\n\n gl_FragColor = color * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n"},fillOutline:{fragmentSource:"#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_pos;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 outline_color\n #pragma mapbox: initialize lowp float opacity\n\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = 1.0 - smoothstep(0.0, 1.0, dist);\n gl_FragColor = outline_color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 outline_color\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world;\n}\n"},fillOutlinePattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec2 v_pos;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n // find distance to outline for alpha interpolation\n\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = 1.0 - smoothstep(0.0, 1.0, dist);\n\n\n gl_FragColor = mix(color1, color2, u_mix) * alpha * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_world;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\n\nattribute vec2 a_pos;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec2 v_pos;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);\n\n v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world;\n}\n"},fillPattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n gl_FragColor = mix(color1, color2, u_mix) * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\n\nattribute vec2 a_pos;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\n\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, a_pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, a_pos);\n}\n"},fillExtrusion:{fragmentSource:"varying vec4 v_color;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define highp vec4 color\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n #pragma mapbox: initialize highp vec4 color\n\n gl_FragColor = v_color;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec3 u_lightcolor;\nuniform lowp vec3 u_lightpos;\nuniform lowp float u_lightintensity;\n\nattribute vec2 a_pos;\nattribute vec4 a_normal_ed;\n\nvarying vec4 v_color;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\n#pragma mapbox: define highp vec4 color\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n #pragma mapbox: initialize highp vec4 color\n\n vec3 normal = a_normal_ed.xyz;\n\n base = max(0.0, base);\n height = max(0.0, height);\n\n float t = mod(normal.x, 2.0);\n\n gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1);\n\n // Relative luminance (how dark/bright is the surface color?)\n float colorvalue = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;\n\n v_color = vec4(0.0, 0.0, 0.0, 1.0);\n\n // Add slight ambient lighting so no extrusions are totally black\n vec4 ambientlight = vec4(0.03, 0.03, 0.03, 1.0);\n color += ambientlight;\n\n // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray\n float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0);\n\n // Adjust directional so that\n // the range of values for highlight/shading is narrower\n // with lower light intensity\n // and with lighter/brighter surface colors\n directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional);\n\n // Add gradient along z axis of side surfaces\n if (normal.y != 0.0) {\n directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);\n }\n\n // Assign final color based on surface + ambient light color, diffuse light directional, and light color\n // with lower bounds adjusted to hue of light\n // so that shading is tinted with the complementary (opposite) color to the light color\n v_color.r += clamp(color.r * directional * u_lightcolor.r, mix(0.0, 0.3, 1.0 - u_lightcolor.r), 1.0);\n v_color.g += clamp(color.g * directional * u_lightcolor.g, mix(0.0, 0.3, 1.0 - u_lightcolor.g), 1.0);\n v_color.b += clamp(color.b * directional * u_lightcolor.b, mix(0.0, 0.3, 1.0 - u_lightcolor.b), 1.0);\n}\n"},fillExtrusionPattern:{fragmentSource:"uniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_mix;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec4 v_lighting;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n\n vec2 imagecoord = mod(v_pos_a, 1.0);\n vec2 pos = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord_b = mod(v_pos_b, 1.0);\n vec2 pos2 = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, imagecoord_b);\n vec4 color2 = texture2D(u_image, pos2);\n\n vec4 mixedColor = mix(color1, color2, u_mix);\n\n gl_FragColor = mixedColor * v_lighting;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pixel_coord_upper;\nuniform vec2 u_pixel_coord_lower;\nuniform float u_scale_a;\nuniform float u_scale_b;\nuniform float u_tile_units_to_pixels;\nuniform float u_height_factor;\n\nuniform vec3 u_lightcolor;\nuniform lowp vec3 u_lightpos;\nuniform lowp float u_lightintensity;\n\nattribute vec2 a_pos;\nattribute vec4 a_normal_ed;\n\nvarying vec2 v_pos_a;\nvarying vec2 v_pos_b;\nvarying vec4 v_lighting;\nvarying float v_directional;\n\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n\nvoid main() {\n #pragma mapbox: initialize lowp float base\n #pragma mapbox: initialize lowp float height\n\n vec3 normal = a_normal_ed.xyz;\n float edgedistance = a_normal_ed.w;\n\n base = max(0.0, base);\n height = max(0.0, height);\n\n float t = mod(normal.x, 2.0);\n float z = t > 0.0 ? height : base;\n\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0\n ? a_pos // extrusion top\n : vec2(edgedistance, z * u_height_factor); // extrusion side\n\n v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, pos);\n v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, pos);\n\n v_lighting = vec4(0.0, 0.0, 0.0, 1.0);\n float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0);\n directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional);\n\n if (normal.y != 0.0) {\n directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);\n }\n\n v_lighting.rgb += clamp(directional * u_lightcolor, mix(vec3(0.0), vec3(0.3), 1.0 - u_lightcolor), vec3(1.0));\n}\n"},extrusionTexture:{fragmentSource:"uniform sampler2D u_image;\nuniform float u_opacity;\nvarying vec2 v_pos;\n\nvoid main() {\n gl_FragColor = texture2D(u_image, v_pos) * u_opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(0.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_world;\nattribute vec2 a_pos;\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1);\n\n v_pos.x = a_pos.x;\n v_pos.y = 1.0 - a_pos.y;\n}\n"},hillshadePrepare:{fragmentSource:"#ifdef GL_ES\nprecision highp float;\n#endif\n\nuniform sampler2D u_image;\nvarying vec2 v_pos;\nuniform vec2 u_dimension;\nuniform float u_zoom;\nuniform float u_maxzoom;\n\nfloat getElevation(vec2 coord, float bias) {\n // Convert encoded elevation value to meters\n vec4 data = texture2D(u_image, coord) * 255.0;\n return (data.r + data.g * 256.0 + data.b * 256.0 * 256.0) / 4.0;\n}\n\nvoid main() {\n vec2 epsilon = 1.0 / u_dimension;\n\n // queried pixels:\n // +-----------+\n // | | | |\n // | a | b | c |\n // | | | |\n // +-----------+\n // | | | |\n // | d | e | f |\n // | | | |\n // +-----------+\n // | | | |\n // | g | h | i |\n // | | | |\n // +-----------+\n\n float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y), 0.0);\n float b = getElevation(v_pos + vec2(0, -epsilon.y), 0.0);\n float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y), 0.0);\n float d = getElevation(v_pos + vec2(-epsilon.x, 0), 0.0);\n float e = getElevation(v_pos, 0.0);\n float f = getElevation(v_pos + vec2(epsilon.x, 0), 0.0);\n float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y), 0.0);\n float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);\n float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);\n\n // here we divide the x and y slopes by 8 * pixel size\n // where pixel size (aka meters/pixel) is:\n // circumference of the world / (pixels per tile * number of tiles)\n // which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom))\n // which can be reduced to: pow(2, 19.25619978527 - u_zoom)\n // we want to vertically exaggerate the hillshading though, because otherwise\n // it is barely noticeable at low zooms. to do this, we multiply this by some\n // scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value\n // Here we use a=0.3 which works out to the expression below. see \n // nickidlugash's awesome breakdown for more info\n // https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556\n float exaggeration = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;\n\n vec2 deriv = vec2(\n (c + f + f + i) - (a + d + d + g),\n (g + h + h + i) - (a + b + b + c)\n ) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);\n\n gl_FragColor = clamp(vec4(\n deriv.x / 2.0 + 0.5,\n deriv.y / 2.0 + 0.5,\n 1.0,\n 1.0), 0.0, 1.0);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = (a_texture_pos / 8192.0) / 2.0 + 0.25;\n}\n"},hillshade:{fragmentSource:"uniform sampler2D u_image;\nvarying vec2 v_pos;\n\nuniform vec2 u_latrange;\nuniform vec2 u_light;\nuniform vec4 u_shadow;\nuniform vec4 u_highlight;\nuniform vec4 u_accent;\n\n#define PI 3.141592653589793\n\nvoid main() {\n vec4 pixel = texture2D(u_image, v_pos);\n\n vec2 deriv = ((pixel.rg * 2.0) - 1.0);\n\n // We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude\n // to account for mercator projection distortion. see #4807 for details\n float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_latrange[1]));\n // We also multiply the slope by an arbitrary z-factor of 1.25\n float slope = atan(1.25 * length(deriv) / scaleFactor);\n float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);\n\n float intensity = u_light.x;\n // We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal\n // position property to account for 0deg corresponding to north/the top of the viewport in the style spec\n // and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal.\n float azimuth = u_light.y + PI;\n\n // We scale the slope exponentially based on intensity, using a calculation similar to\n // the exponential interpolation function in the style spec:\n // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228\n // so that higher intensity values create more opaque hillshading.\n float base = 1.875 - intensity * 1.75;\n float maxValue = 0.5 * PI;\n float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;\n\n // The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine\n // so that the accent color's rate of change eases in while the shade color's eases out.\n float accent = cos(scaledSlope);\n // We multiply both the accent and shade color by a clamped intensity value\n // so that intensities >= 0.5 do not additionally affect the color values\n // while intensity values < 0.5 make the overall color more transparent.\n vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);\n float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);\n vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);\n gl_FragColor = accent_color * (1.0 - shade_color.a) + shade_color;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n v_pos = a_texture_pos / 8192.0;\n}\n"},line:{fragmentSource:"#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_width2;\nvarying vec2 v_normal;\nvarying float v_gamma_scale;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_gamma_scale;\nvarying highp float v_linesofar;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n\n v_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_width2 = vec2(outset, inset);\n}\n"},lineGradient:{fragmentSource:"\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nuniform sampler2D u_image;\n\nvarying vec2 v_width2;\nvarying vec2 v_normal;\nvarying float v_gamma_scale;\nvarying highp float v_lineprogress;\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n // For gradient lines, v_lineprogress is the ratio along the entire line,\n // scaled to [0, 2^15), and the gradient ramp is stored in a texture.\n vec4 color = texture2D(u_image, vec2(v_lineprogress, 0.5));\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"\n// the attribute conveying progress along a line is scaled to [0, 2^15)\n#define MAX_LINE_DISTANCE 32767.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_gamma_scale;\nvarying highp float v_lineprogress;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n\n v_lineprogress = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0 / MAX_LINE_DISTANCE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_width2 = vec2(outset, inset);\n}\n"},linePattern:{fragmentSource:"uniform vec2 u_pattern_size_a;\nuniform vec2 u_pattern_size_b;\nuniform vec2 u_pattern_tl_a;\nuniform vec2 u_pattern_br_a;\nuniform vec2 u_pattern_tl_b;\nuniform vec2 u_pattern_br_b;\nuniform vec2 u_texsize;\nuniform float u_fade;\n\nuniform sampler2D u_image;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_linesofar;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0);\n float x_b = mod(v_linesofar / u_pattern_size_b.x, 1.0);\n\n // v_normal.y is 0 at the midpoint of the line, -1 at the lower edge, 1 at the upper edge\n // we clamp the line width outset to be between 0 and half the pattern height plus padding (2.0)\n // to ensure we don't sample outside the designated symbol on the sprite sheet.\n // 0.5 is added to shift the component to be bounded between 0 and 1 for interpolation of\n // the texture coordinate\n float y_a = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_a.y + 2.0) / 2.0) / u_pattern_size_a.y);\n float y_b = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_b.y + 2.0) / 2.0) / u_pattern_size_b.y);\n vec2 pos_a = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, vec2(x_a, y_a));\n vec2 pos_b = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, vec2(x_b, y_b));\n\n vec4 color = mix(texture2D(u_image, pos_a), texture2D(u_image, pos_b), u_fade);\n\n gl_FragColor = color * alpha * opacity;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\n// We scale the distance before adding it to the buffers so that we can store\n// long distances for long segments. Use this value to unscale the distance.\n#define LINE_DISTANCE_SCALE 2.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying float v_linesofar;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define mediump float width\n\nvoid main() {\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize mediump float width\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist = outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_linesofar = a_linesofar;\n v_width2 = vec2(outset, inset);\n}\n"},lineSDF:{fragmentSource:"\nuniform sampler2D u_image;\nuniform float u_sdfgamma;\nuniform float u_mix;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying vec2 v_tex_a;\nvarying vec2 v_tex_b;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float width\n #pragma mapbox: initialize lowp float floorwidth\n\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * v_width2.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_width2.t) or when fading out\n // (v_width2.s)\n float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;\n float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);\n\n float sdfdist_a = texture2D(u_image, v_tex_a).a;\n float sdfdist_b = texture2D(u_image, v_tex_b).a;\n float sdfdist = mix(sdfdist_a, sdfdist_b, u_mix);\n alpha *= smoothstep(0.5 - u_sdfgamma / floorwidth, 0.5 + u_sdfgamma / floorwidth, sdfdist);\n\n gl_FragColor = color * (alpha * opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n// #define scale 63.0\n#define scale 0.015873016\n\n// We scale the distance before adding it to the buffers so that we can store\n// long distances for long segments. Use this value to unscale the distance.\n#define LINE_DISTANCE_SCALE 2.0\n\n// the distance over which the line edge fades out.\n// Retina devices need a smaller distance to avoid aliasing.\n#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0\n\nattribute vec4 a_pos_normal;\nattribute vec4 a_data;\n\nuniform mat4 u_matrix;\nuniform mediump float u_ratio;\nuniform vec2 u_patternscale_a;\nuniform float u_tex_y_a;\nuniform vec2 u_patternscale_b;\nuniform float u_tex_y_b;\nuniform vec2 u_gl_units_to_pixels;\n\nvarying vec2 v_normal;\nvarying vec2 v_width2;\nvarying vec2 v_tex_a;\nvarying vec2 v_tex_b;\nvarying float v_gamma_scale;\n\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 color\n #pragma mapbox: initialize lowp float blur\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize mediump float gapwidth\n #pragma mapbox: initialize lowp float offset\n #pragma mapbox: initialize mediump float width\n #pragma mapbox: initialize lowp float floorwidth\n\n vec2 a_extrude = a_data.xy - 128.0;\n float a_direction = mod(a_data.z, 4.0) - 1.0;\n float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;\n\n vec2 pos = a_pos_normal.xy;\n\n // x is 1 if it's a round cap, 0 otherwise\n // y is 1 if the normal points up, and -1 if it points down\n mediump vec2 normal = a_pos_normal.zw;\n v_normal = normal;\n\n // these transformations used to be applied in the JS and native code bases.\n // moved them into the shader for clarity and simplicity.\n gapwidth = gapwidth / 2.0;\n float halfwidth = width / 2.0;\n offset = -1.0 * offset;\n\n float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);\n float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n mediump vec2 dist =outset * a_extrude * scale;\n\n // Calculate the offset when drawing a line that is to the side of the actual line.\n // We do this by creating a vector that points towards the extrude, but rotate\n // it when we're drawing round end points (a_direction = -1 or 1) since their\n // extrude vector points in another direction.\n mediump float u = 0.5 * a_direction;\n mediump float t = 1.0 - abs(u);\n mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);\n\n vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);\n gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;\n\n // calculate how much the perspective view squishes or stretches the extrude\n float extrude_length_without_perspective = length(dist);\n float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);\n v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;\n\n v_tex_a = vec2(a_linesofar * u_patternscale_a.x / floorwidth, normal.y * u_patternscale_a.y + u_tex_y_a);\n v_tex_b = vec2(a_linesofar * u_patternscale_b.x / floorwidth, normal.y * u_patternscale_b.y + u_tex_y_b);\n\n v_width2 = vec2(outset, inset);\n}\n"},raster:{fragmentSource:"uniform float u_fade_t;\nuniform float u_opacity;\nuniform sampler2D u_image0;\nuniform sampler2D u_image1;\nvarying vec2 v_pos0;\nvarying vec2 v_pos1;\n\nuniform float u_brightness_low;\nuniform float u_brightness_high;\n\nuniform float u_saturation_factor;\nuniform float u_contrast_factor;\nuniform vec3 u_spin_weights;\n\nvoid main() {\n\n // read and cross-fade colors from the main and parent tiles\n vec4 color0 = texture2D(u_image0, v_pos0);\n vec4 color1 = texture2D(u_image1, v_pos1);\n if (color0.a > 0.0) {\n color0.rgb = color0.rgb / color0.a;\n }\n if (color1.a > 0.0) {\n color1.rgb = color1.rgb / color1.a;\n }\n vec4 color = mix(color0, color1, u_fade_t);\n color.a *= u_opacity;\n vec3 rgb = color.rgb;\n\n // spin\n rgb = vec3(\n dot(rgb, u_spin_weights.xyz),\n dot(rgb, u_spin_weights.zxy),\n dot(rgb, u_spin_weights.yzx));\n\n // saturation\n float average = (color.r + color.g + color.b) / 3.0;\n rgb += (average - rgb) * u_saturation_factor;\n\n // contrast\n rgb = (rgb - 0.5) * u_contrast_factor + 0.5;\n\n // brightness\n vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low);\n vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high);\n\n gl_FragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"uniform mat4 u_matrix;\nuniform vec2 u_tl_parent;\nuniform float u_scale_parent;\nuniform float u_buffer_scale;\n\nattribute vec2 a_pos;\nattribute vec2 a_texture_pos;\n\nvarying vec2 v_pos0;\nvarying vec2 v_pos1;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n // We are using Int16 for texture position coordinates to give us enough precision for\n // fractional coordinates. We use 8192 to scale the texture coordinates in the buffer\n // as an arbitrarily high number to preserve adequate precision when rendering.\n // This is also the same value as the EXTENT we are using for our tile buffer pos coordinates,\n // so math for modifying either is consistent.\n v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5;\n v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent;\n}\n"},symbolIcon:{fragmentSource:"uniform sampler2D u_texture;\n\n#pragma mapbox: define lowp float opacity\n\nvarying vec2 v_tex;\nvarying float v_fade_opacity;\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n lowp float alpha = opacity * v_fade_opacity;\n gl_FragColor = texture2D(u_texture, v_tex) * alpha;\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"const float PI = 3.141592653589793;\n\nattribute vec4 a_pos_offset;\nattribute vec4 a_data;\nattribute vec3 a_projected_pos;\nattribute float a_fade_opacity;\n\nuniform bool u_is_size_zoom_constant;\nuniform bool u_is_size_feature_constant;\nuniform highp float u_size_t; // used to interpolate between zoom stops when size is a composite function\nuniform highp float u_size; // used when size is both zoom and feature constant\nuniform highp float u_camera_to_center_distance;\nuniform highp float u_pitch;\nuniform bool u_rotate_symbol;\nuniform highp float u_aspect_ratio;\nuniform float u_fade_change;\n\n#pragma mapbox: define lowp float opacity\n\nuniform mat4 u_matrix;\nuniform mat4 u_label_plane_matrix;\nuniform mat4 u_gl_coord_matrix;\n\nuniform bool u_is_text;\nuniform bool u_pitch_with_map;\n\nuniform vec2 u_texsize;\n\nvarying vec2 v_tex;\nvarying float v_fade_opacity;\n\nvoid main() {\n #pragma mapbox: initialize lowp float opacity\n\n vec2 a_pos = a_pos_offset.xy;\n vec2 a_offset = a_pos_offset.zw;\n\n vec2 a_tex = a_data.xy;\n vec2 a_size = a_data.zw;\n\n highp float segment_angle = -a_projected_pos[2];\n\n float size;\n if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = mix(a_size[0], a_size[1], u_size_t) / 10.0;\n } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = a_size[0] / 10.0;\n } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {\n size = u_size;\n } else {\n size = u_size;\n }\n\n vec4 projectedPoint = u_matrix * vec4(a_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n // See comments in symbol_sdf.vertex\n highp float distance_ratio = u_pitch_with_map ?\n camera_to_anchor_distance / u_camera_to_center_distance :\n u_camera_to_center_distance / camera_to_anchor_distance;\n highp float perspective_ratio = clamp(\n 0.5 + 0.5 * distance_ratio,\n 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles\n 4.0);\n\n size *= perspective_ratio;\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n highp float symbol_rotation = 0.0;\n if (u_rotate_symbol) {\n // See comments in symbol_sdf.vertex\n vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);\n\n vec2 a = projectedPoint.xy / projectedPoint.w;\n vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;\n\n symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);\n }\n\n highp float angle_sin = sin(segment_angle + symbol_rotation);\n highp float angle_cos = cos(segment_angle + symbol_rotation);\n mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);\n\n vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);\n gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);\n\n v_tex = a_tex / u_texsize;\n vec2 fade_opacity = unpack_opacity(a_fade_opacity);\n float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;\n v_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));\n}\n"},symbolSDF:{fragmentSource:"#define SDF_PX 8.0\n#define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO\n\nuniform bool u_is_halo;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\n\nuniform sampler2D u_texture;\nuniform highp float u_gamma_scale;\nuniform bool u_is_text;\n\nvarying vec2 v_data0;\nvarying vec3 v_data1;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 fill_color\n #pragma mapbox: initialize highp vec4 halo_color\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float halo_width\n #pragma mapbox: initialize lowp float halo_blur\n\n vec2 tex = v_data0.xy;\n float gamma_scale = v_data1.x;\n float size = v_data1.y;\n float fade_opacity = v_data1[2];\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n lowp vec4 color = fill_color;\n highp float gamma = EDGE_GAMMA / (fontScale * u_gamma_scale);\n lowp float buff = (256.0 - 64.0) / 256.0;\n if (u_is_halo) {\n color = halo_color;\n gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);\n buff = (6.0 - halo_width / fontScale) / SDF_PX;\n }\n\n lowp float dist = texture2D(u_texture, tex).a;\n highp float gamma_scaled = gamma * gamma_scale;\n highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);\n\n gl_FragColor = color * (alpha * opacity * fade_opacity);\n\n#ifdef OVERDRAW_INSPECTOR\n gl_FragColor = vec4(1.0);\n#endif\n}\n",vertexSource:"const float PI = 3.141592653589793;\n\nattribute vec4 a_pos_offset;\nattribute vec4 a_data;\nattribute vec3 a_projected_pos;\nattribute float a_fade_opacity;\n\n// contents of a_size vary based on the type of property value\n// used for {text,icon}-size.\n// For constants, a_size is disabled.\n// For source functions, we bind only one value per vertex: the value of {text,icon}-size evaluated for the current feature.\n// For composite functions:\n// [ text-size(lowerZoomStop, feature),\n// text-size(upperZoomStop, feature) ]\nuniform bool u_is_size_zoom_constant;\nuniform bool u_is_size_feature_constant;\nuniform highp float u_size_t; // used to interpolate between zoom stops when size is a composite function\nuniform highp float u_size; // used when size is both zoom and feature constant\n\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\n\nuniform mat4 u_matrix;\nuniform mat4 u_label_plane_matrix;\nuniform mat4 u_gl_coord_matrix;\n\nuniform bool u_is_text;\nuniform bool u_pitch_with_map;\nuniform highp float u_pitch;\nuniform bool u_rotate_symbol;\nuniform highp float u_aspect_ratio;\nuniform highp float u_camera_to_center_distance;\nuniform float u_fade_change;\n\nuniform vec2 u_texsize;\n\nvarying vec2 v_data0;\nvarying vec3 v_data1;\n\nvoid main() {\n #pragma mapbox: initialize highp vec4 fill_color\n #pragma mapbox: initialize highp vec4 halo_color\n #pragma mapbox: initialize lowp float opacity\n #pragma mapbox: initialize lowp float halo_width\n #pragma mapbox: initialize lowp float halo_blur\n\n vec2 a_pos = a_pos_offset.xy;\n vec2 a_offset = a_pos_offset.zw;\n\n vec2 a_tex = a_data.xy;\n vec2 a_size = a_data.zw;\n\n highp float segment_angle = -a_projected_pos[2];\n float size;\n\n if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = mix(a_size[0], a_size[1], u_size_t) / 10.0;\n } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {\n size = a_size[0] / 10.0;\n } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {\n size = u_size;\n } else {\n size = u_size;\n }\n\n vec4 projectedPoint = u_matrix * vec4(a_pos, 0, 1);\n highp float camera_to_anchor_distance = projectedPoint.w;\n // If the label is pitched with the map, layout is done in pitched space,\n // which makes labels in the distance smaller relative to viewport space.\n // We counteract part of that effect by multiplying by the perspective ratio.\n // If the label isn't pitched with the map, we do layout in viewport space,\n // which makes labels in the distance larger relative to the features around\n // them. We counteract part of that effect by dividing by the perspective ratio.\n highp float distance_ratio = u_pitch_with_map ?\n camera_to_anchor_distance / u_camera_to_center_distance :\n u_camera_to_center_distance / camera_to_anchor_distance;\n highp float perspective_ratio = clamp(\n 0.5 + 0.5 * distance_ratio,\n 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles\n 4.0);\n\n size *= perspective_ratio;\n\n float fontScale = u_is_text ? size / 24.0 : size;\n\n highp float symbol_rotation = 0.0;\n if (u_rotate_symbol) {\n // Point labels with 'rotation-alignment: map' are horizontal with respect to tile units\n // To figure out that angle in projected space, we draw a short horizontal line in tile\n // space, project it, and measure its angle in projected space.\n vec4 offsetProjectedPoint = u_matrix * vec4(a_pos + vec2(1, 0), 0, 1);\n\n vec2 a = projectedPoint.xy / projectedPoint.w;\n vec2 b = offsetProjectedPoint.xy / offsetProjectedPoint.w;\n\n symbol_rotation = atan((b.y - a.y) / u_aspect_ratio, b.x - a.x);\n }\n\n highp float angle_sin = sin(segment_angle + symbol_rotation);\n highp float angle_cos = cos(segment_angle + symbol_rotation);\n mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);\n\n vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);\n gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);\n float gamma_scale = gl_Position.w;\n\n vec2 tex = a_tex / u_texsize;\n vec2 fade_opacity = unpack_opacity(a_fade_opacity);\n float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;\n float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));\n\n v_data0 = vec2(tex.x, tex.y);\n v_data1 = vec3(gamma_scale, size, interpolated_fade_opacity);\n}\n"}},tr=/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g,er=function(t){var e=Qe[t],r={};e.fragmentSource=e.fragmentSource.replace(tr,function(t,e,n,i,a){return r[a]=!0,"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nvarying "+n+" "+i+" "+a+";\n#else\nuniform "+n+" "+i+" u_"+a+";\n#endif\n":"\n#ifdef HAS_UNIFORM_u_"+a+"\n "+n+" "+i+" "+a+" = u_"+a+";\n#endif\n"}),e.vertexSource=e.vertexSource.replace(tr,function(t,e,n,i,a){var o="float"===i?"vec2":"vec4";return r[a]?"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nuniform lowp float a_"+a+"_t;\nattribute "+n+" "+o+" a_"+a+";\nvarying "+n+" "+i+" "+a+";\n#else\nuniform "+n+" "+i+" u_"+a+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+a+" = unpack_mix_"+o+"(a_"+a+", a_"+a+"_t);\n#else\n "+n+" "+i+" "+a+" = u_"+a+";\n#endif\n":"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nuniform lowp float a_"+a+"_t;\nattribute "+n+" "+o+" a_"+a+";\n#else\nuniform "+n+" "+i+" u_"+a+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+n+" "+i+" "+a+" = unpack_mix_"+o+"(a_"+a+", a_"+a+"_t);\n#else\n "+n+" "+i+" "+a+" = u_"+a+";\n#endif\n"})};for(var rr in Qe)er(rr);var nr=Qe,ir=function(t,e,r,n){var i=t.gl;this.program=i.createProgram();var o=r.defines().concat("#define DEVICE_PIXEL_RATIO "+a.devicePixelRatio.toFixed(1));n&&o.push("#define OVERDRAW_INSPECTOR;");var s=o.concat(nr.prelude.fragmentSource,e.fragmentSource).join("\n"),l=o.concat(nr.prelude.vertexSource,e.vertexSource).join("\n"),c=i.createShader(i.FRAGMENT_SHADER);i.shaderSource(c,s),i.compileShader(c),i.attachShader(this.program,c);var u=i.createShader(i.VERTEX_SHADER);i.shaderSource(u,l),i.compileShader(u),i.attachShader(this.program,u);for(var f=r.layoutAttributes||[],h=0;h>16,s>>16),n.uniform2f(r.uniforms.u_pixel_coord_lower,65535&o,65535&s)};function vr(t,e,r,n,i){if(!dr(r.paint.get("fill-pattern"),t))for(var a=!0,o=0,s=n;o0){var l=a.now(),c=(l-e.timeAdded)/s,u=r?(l-r.timeAdded)/s:-1,f=n.getSource(),h=o.coveringZoomLevel({tileSize:f.tileSize,roundZoom:f.roundZoom}),p=!r||Math.abs(r.tileID.overscaledZ-h)>Math.abs(e.tileID.overscaledZ-h),d=p&&e.refreshedUponExpiration?1:t.clamp(p?c:1-u,0,1);return e.refreshedUponExpiration&&c>=1&&(e.refreshedUponExpiration=!1),r?{opacity:1,mix:1-d}:{opacity:d,mix:0}}return{opacity:1,mix:0}}function Er(e,r,n){var i=e.context,o=i.gl;i.lineWidth.set(1*a.devicePixelRatio);var s=n.posMatrix,l=e.useProgram("debug");i.setDepthMode(qt.disabled),i.setStencilMode(Ht.disabled),i.setColorMode(e.colorModeForRenderPass()),o.uniformMatrix4fv(l.uniforms.u_matrix,!1,s),o.uniform4f(l.uniforms.u_color,1,0,0,1),e.debugVAO.bind(i,l,e.debugBuffer,[]),o.drawArrays(o.LINE_STRIP,0,e.debugBuffer.length);for(var c=function(t,e,r,n){n=n||1;var i,a,o,s,l,c,u,f,h=[];for(i=0,a=t.length;i":[24,[4,18,20,9,4,0]],"?":[18,[3,16,3,17,4,19,5,20,7,21,11,21,13,20,14,19,15,17,15,15,14,13,13,12,9,10,9,7,-1,-1,9,2,8,1,9,0,10,1,9,2]],"@":[27,[18,13,17,15,15,16,12,16,10,15,9,14,8,11,8,8,9,6,11,5,14,5,16,6,17,8,-1,-1,12,16,10,14,9,11,9,8,10,6,11,5,-1,-1,18,16,17,8,17,6,19,5,21,5,23,7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12,21,9,20,7,19,5,17,4,15,3,12,3,9,4,6,5,4,7,2,9,1,12,0,15,0,18,1,20,2,21,3,-1,-1,19,16,18,8,18,6,19,5]],A:[18,[9,21,1,0,-1,-1,9,21,17,0,-1,-1,4,7,14,7]],B:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,-1,-1,4,11,13,11,16,10,17,9,18,7,18,4,17,2,16,1,13,0,4,0]],C:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5]],D:[21,[4,21,4,0,-1,-1,4,21,11,21,14,20,16,18,17,16,18,13,18,8,17,5,16,3,14,1,11,0,4,0]],E:[19,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11,-1,-1,4,0,17,0]],F:[18,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11]],G:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,18,8,-1,-1,13,8,18,8]],H:[22,[4,21,4,0,-1,-1,18,21,18,0,-1,-1,4,11,18,11]],I:[8,[4,21,4,0]],J:[16,[12,21,12,5,11,2,10,1,8,0,6,0,4,1,3,2,2,5,2,7]],K:[21,[4,21,4,0,-1,-1,18,21,4,7,-1,-1,9,12,18,0]],L:[17,[4,21,4,0,-1,-1,4,0,16,0]],M:[24,[4,21,4,0,-1,-1,4,21,12,0,-1,-1,20,21,12,0,-1,-1,20,21,20,0]],N:[22,[4,21,4,0,-1,-1,4,21,18,0,-1,-1,18,21,18,0]],O:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21]],P:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13,10,4,10]],Q:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21,-1,-1,12,4,18,-2]],R:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,4,11,-1,-1,11,11,18,0]],S:[20,[17,18,15,20,12,21,8,21,5,20,3,18,3,16,4,14,5,13,7,12,13,10,15,9,16,8,17,6,17,3,15,1,12,0,8,0,5,1,3,3]],T:[16,[8,21,8,0,-1,-1,1,21,15,21]],U:[22,[4,21,4,6,5,3,7,1,10,0,12,0,15,1,17,3,18,6,18,21]],V:[18,[1,21,9,0,-1,-1,17,21,9,0]],W:[24,[2,21,7,0,-1,-1,12,21,7,0,-1,-1,12,21,17,0,-1,-1,22,21,17,0]],X:[20,[3,21,17,0,-1,-1,17,21,3,0]],Y:[18,[1,21,9,11,9,0,-1,-1,17,21,9,11]],Z:[20,[17,21,3,0,-1,-1,3,21,17,21,-1,-1,3,0,17,0]],"[":[14,[4,25,4,-7,-1,-1,5,25,5,-7,-1,-1,4,25,11,25,-1,-1,4,-7,11,-7]],"\\":[14,[0,21,14,-3]],"]":[14,[9,25,9,-7,-1,-1,10,25,10,-7,-1,-1,3,25,10,25,-1,-1,3,-7,10,-7]],"^":[16,[6,15,8,18,10,15,-1,-1,3,12,8,17,13,12,-1,-1,8,17,8,0]],_:[16,[0,-2,16,-2]],"`":[10,[6,21,5,20,4,18,4,16,5,15,6,16,5,17]],a:[19,[15,14,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],b:[19,[4,21,4,0,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],c:[18,[15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],d:[19,[15,21,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],e:[18,[3,8,15,8,15,10,14,12,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],f:[12,[10,21,8,21,6,20,5,17,5,0,-1,-1,2,14,9,14]],g:[19,[15,14,15,-2,14,-5,13,-6,11,-7,8,-7,6,-6,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],h:[19,[4,21,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],i:[8,[3,21,4,20,5,21,4,22,3,21,-1,-1,4,14,4,0]],j:[10,[5,21,6,20,7,21,6,22,5,21,-1,-1,6,14,6,-3,5,-6,3,-7,1,-7]],k:[17,[4,21,4,0,-1,-1,14,14,4,4,-1,-1,8,8,15,0]],l:[8,[4,21,4,0]],m:[30,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0,-1,-1,15,10,18,13,20,14,23,14,25,13,26,10,26,0]],n:[19,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],o:[19,[8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3,16,6,16,8,15,11,13,13,11,14,8,14]],p:[19,[4,14,4,-7,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],q:[19,[15,14,15,-7,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],r:[13,[4,14,4,0,-1,-1,4,8,5,11,7,13,9,14,12,14]],s:[17,[14,11,13,13,10,14,7,14,4,13,3,11,4,9,6,8,11,7,13,6,14,4,14,3,13,1,10,0,7,0,4,1,3,3]],t:[12,[5,21,5,4,6,1,8,0,10,0,-1,-1,2,14,9,14]],u:[19,[4,14,4,4,5,1,7,0,10,0,12,1,15,4,-1,-1,15,14,15,0]],v:[16,[2,14,8,0,-1,-1,14,14,8,0]],w:[22,[3,14,7,0,-1,-1,11,14,7,0,-1,-1,11,14,15,0,-1,-1,19,14,15,0]],x:[17,[3,14,14,0,-1,-1,14,14,3,0]],y:[16,[2,14,8,0,-1,-1,14,14,8,0,6,-4,4,-6,2,-7,1,-7]],z:[17,[14,14,3,0,-1,-1,3,14,14,14,-1,-1,3,0,14,0]],"{":[14,[9,25,7,24,6,23,5,21,5,19,6,17,7,16,8,14,8,12,6,10,-1,-1,7,24,6,22,6,20,7,18,8,17,9,15,9,13,8,11,4,9,8,7,9,5,9,3,8,1,7,0,6,-2,6,-4,7,-6,-1,-1,6,8,8,6,8,4,7,2,6,1,5,-1,5,-3,6,-5,7,-6,9,-7]],"|":[8,[4,25,4,-7]],"}":[14,[5,25,7,24,8,23,9,21,9,19,8,17,7,16,6,14,6,12,8,10,-1,-1,7,24,8,22,8,20,7,18,6,17,5,15,5,13,6,11,10,9,6,7,5,5,5,3,6,1,7,0,8,-2,8,-4,7,-6,-1,-1,8,8,6,6,6,4,7,2,8,1,9,-1,9,-3,8,-5,7,-6,5,-7]],"~":[24,[3,6,3,8,4,11,6,12,8,12,10,11,14,8,16,7,18,7,20,8,21,10,-1,-1,3,8,4,10,6,11,8,11,10,10,14,7,16,6,18,6,20,7,21,10,21,12]]},Lr={symbol:function(t,e,r,n){if("translucent"===t.renderPass){var i=t.context;i.setStencilMode(Ht.disabled),i.setColorMode(t.colorModeForRenderPass()),0!==r.paint.get("icon-opacity").constantOr(1)&&cr(t,e,r,n,!1,r.paint.get("icon-translate"),r.paint.get("icon-translate-anchor"),r.layout.get("icon-rotation-alignment"),r.layout.get("icon-pitch-alignment"),r.layout.get("icon-keep-upright")),0!==r.paint.get("text-opacity").constantOr(1)&&cr(t,e,r,n,!0,r.paint.get("text-translate"),r.paint.get("text-translate-anchor"),r.layout.get("text-rotation-alignment"),r.layout.get("text-pitch-alignment"),r.layout.get("text-keep-upright")),e.map.showCollisionBoxes&&function(t,e,r,n){or(t,e,r,n,!1),or(t,e,r,n,!0)}(t,e,r,n)}},circle:function(t,e,r,n){if("translucent"===t.renderPass){var i=r.paint.get("circle-opacity"),a=r.paint.get("circle-stroke-width"),o=r.paint.get("circle-stroke-opacity");if(0!==i.constantOr(1)||0!==a.constantOr(1)&&0!==o.constantOr(1)){var s=t.context,l=s.gl;s.setDepthMode(t.depthModeForSublayer(0,qt.ReadOnly)),s.setStencilMode(Ht.disabled),s.setColorMode(t.colorModeForRenderPass());for(var c=!0,u=0;u0?1-1/(1.001-i):-i),s.uniform1f(c.uniforms.u_contrast_factor,(a=r.paint.get("raster-contrast"))>0?1/(1-a):1+a),s.uniform3fv(c.uniforms.u_spin_weights,function(t){t*=Math.PI/180;var e=Math.sin(t),r=Math.cos(t);return[(2*r+1)/3,(-Math.sqrt(3)*e-r+1)/3,(Math.sqrt(3)*e-r+1)/3]}(r.paint.get("raster-hue-rotate"))),s.uniform1f(c.uniforms.u_buffer_scale,1),s.uniform1i(c.uniforms.u_image0,0),s.uniform1i(c.uniforms.u_image1,1);for(var u=n.length&&n[0].overscaledZ,f=0,h=n;fe.row){var r=t;t=e,e=r}return{x0:t.column,y0:t.row,x1:e.column,y1:e.row,dx:e.column-t.column,dy:e.row-t.row}}function Ir(t,e,r,n,i){var a=Math.max(r,Math.floor(e.y0)),o=Math.min(n,Math.ceil(e.y1));if(t.x0===e.x0&&t.y0===e.y0?t.x0+e.dy/t.dy*t.dx0,f=e.dx<0,h=a;hl.dy&&(o=s,s=l,l=o),s.dy>c.dy&&(o=s,s=c,c=o),l.dy>c.dy&&(o=l,l=c,c=o),s.dy&&Ir(c,s,n,i,a),l.dy&&Ir(c,l,n,i,a)}zr.prototype.resize=function(t,e){var r=this.context.gl;if(this.width=t*a.devicePixelRatio,this.height=e*a.devicePixelRatio,this.context.viewport.set([0,0,this.width,this.height]),this.style)for(var n=0,i=this.style._order;n=0;this.currentLayer--){var v=n.style._layers[s[n.currentLayer]];v.source!==(m&&m.id)&&(g=[],(m=n.style.sourceCaches[v.source])&&(n.clearStencil(),g=m.getVisibleCoordinates(),m.getSource().isTileClipped&&n._renderTileClippingMasks(g))),n.renderLayer(n,m,v,g)}this.renderPass="translucent";var y,x=[];for(this.currentLayer=0,this.currentLayer;this.currentLayer0?e.pop():null},zr.prototype._createProgramCached=function(t,e){this.cache=this.cache||{};var r=""+t+(e.cacheKey||"")+(this._showOverdrawInspector?"/overdraw":"");return this.cache[r]||(this.cache[r]=new ir(this.context,nr[t],e,this._showOverdrawInspector)),this.cache[r]},zr.prototype.useProgram=function(t,e){var r=this._createProgramCached(t,e||this.emptyProgramConfiguration);return this.context.program.set(r.program),r};var Dr=t.default$20.vec4,Rr=t.default$20.mat4,Br=t.default$20.mat2,Fr=function(t,e,r){this.tileSize=512,this._renderWorldCopies=void 0===r||r,this._minZoom=t||0,this._maxZoom=e||22,this.latRange=[-85.05113,85.05113],this.width=0,this.height=0,this._center=new G(0,0),this.zoom=0,this.angle=0,this._fov=.6435011087932844,this._pitch=0,this._unmodified=!0,this._posMatrixCache={},this._alignedPosMatrixCache={}},Nr={minZoom:{configurable:!0},maxZoom:{configurable:!0},renderWorldCopies:{configurable:!0},worldSize:{configurable:!0},centerPoint:{configurable:!0},size:{configurable:!0},bearing:{configurable:!0},pitch:{configurable:!0},fov:{configurable:!0},zoom:{configurable:!0},center:{configurable:!0},unmodified:{configurable:!0},x:{configurable:!0},y:{configurable:!0},point:{configurable:!0}};Fr.prototype.clone=function(){var t=new Fr(this._minZoom,this._maxZoom,this._renderWorldCopies);return t.tileSize=this.tileSize,t.latRange=this.latRange,t.width=this.width,t.height=this.height,t._center=this._center,t.zoom=this.zoom,t.angle=this.angle,t._fov=this._fov,t._pitch=this._pitch,t._unmodified=this._unmodified,t._calcMatrices(),t},Nr.minZoom.get=function(){return this._minZoom},Nr.minZoom.set=function(t){this._minZoom!==t&&(this._minZoom=t,this.zoom=Math.max(this.zoom,t))},Nr.maxZoom.get=function(){return this._maxZoom},Nr.maxZoom.set=function(t){this._maxZoom!==t&&(this._maxZoom=t,this.zoom=Math.min(this.zoom,t))},Nr.renderWorldCopies.get=function(){return this._renderWorldCopies},Nr.renderWorldCopies.set=function(t){void 0===t?t=!0:null===t&&(t=!1),this._renderWorldCopies=t},Nr.worldSize.get=function(){return this.tileSize*this.scale},Nr.centerPoint.get=function(){return this.size._div(2)},Nr.size.get=function(){return new t.default$1(this.width,this.height)},Nr.bearing.get=function(){return-this.angle/Math.PI*180},Nr.bearing.set=function(e){var r=-t.wrap(e,-180,180)*Math.PI/180;this.angle!==r&&(this._unmodified=!1,this.angle=r,this._calcMatrices(),this.rotationMatrix=Br.create(),Br.rotate(this.rotationMatrix,this.rotationMatrix,this.angle))},Nr.pitch.get=function(){return this._pitch/Math.PI*180},Nr.pitch.set=function(e){var r=t.clamp(e,0,60)/180*Math.PI;this._pitch!==r&&(this._unmodified=!1,this._pitch=r,this._calcMatrices())},Nr.fov.get=function(){return this._fov/Math.PI*180},Nr.fov.set=function(t){t=Math.max(.01,Math.min(60,t)),this._fov!==t&&(this._unmodified=!1,this._fov=t/180*Math.PI,this._calcMatrices())},Nr.zoom.get=function(){return this._zoom},Nr.zoom.set=function(t){var e=Math.min(Math.max(t,this.minZoom),this.maxZoom);this._zoom!==e&&(this._unmodified=!1,this._zoom=e,this.scale=this.zoomScale(e),this.tileZoom=Math.floor(e),this.zoomFraction=e-this.tileZoom,this._constrain(),this._calcMatrices())},Nr.center.get=function(){return this._center},Nr.center.set=function(t){t.lat===this._center.lat&&t.lng===this._center.lng||(this._unmodified=!1,this._center=t,this._constrain(),this._calcMatrices())},Fr.prototype.coveringZoomLevel=function(t){return(t.roundZoom?Math.round:Math.floor)(this.zoom+this.scaleZoom(this.tileSize/t.tileSize))},Fr.prototype.getVisibleUnwrappedCoordinates=function(e){var r=this.pointCoordinate(new t.default$1(0,0),0),n=this.pointCoordinate(new t.default$1(this.width,0),0),i=Math.floor(r.column),a=Math.floor(n.column),o=[new t.UnwrappedTileID(0,e)];if(this._renderWorldCopies)for(var s=i;s<=a;s++)0!==s&&o.push(new t.UnwrappedTileID(s,e));return o},Fr.prototype.coveringTiles=function(e){var r=this.coveringZoomLevel(e),n=r;if(void 0!==e.minzoom&&re.maxzoom&&(r=e.maxzoom);var i=this.pointCoordinate(this.centerPoint,r),a=new t.default$1(i.column-.5,i.row-.5);return function(e,r,n,i){void 0===i&&(i=!0);var a=1<=0&&l<=a)for(c=r;co&&(i=o-m)}if(this.lngRange){var g=this.x,v=c.x/2;g-vl&&(n=l-v)}void 0===n&&void 0===i||(this.center=this.unproject(new t.default$1(void 0!==n?n:this.x,void 0!==i?i:this.y))),this._unmodified=u,this._constraining=!1}},Fr.prototype._calcMatrices=function(){if(this.height){this.cameraToCenterDistance=.5/Math.tan(this._fov/2)*this.height;var t=this._fov/2,e=Math.PI/2+this._pitch,r=Math.sin(t)*this.cameraToCenterDistance/Math.sin(Math.PI-e-t),n=this.x,i=this.y,a=1.01*(Math.cos(Math.PI/2-this._pitch)*r+this.cameraToCenterDistance),o=new Float64Array(16);Rr.perspective(o,this._fov,this.width/this.height,1,a),Rr.scale(o,o,[1,-1,1]),Rr.translate(o,o,[0,0,-this.cameraToCenterDistance]),Rr.rotateX(o,o,this._pitch),Rr.rotateZ(o,o,this.angle),Rr.translate(o,o,[-n,-i,0]);var s=this.worldSize/(2*Math.PI*6378137*Math.abs(Math.cos(this.center.lat*(Math.PI/180))));Rr.scale(o,o,[1,1,s,1]),this.projMatrix=o;var l=this.width%2/2,c=this.height%2/2,u=Math.cos(this.angle),f=Math.sin(this.angle),h=n-Math.round(n)+u*l+f*c,p=i-Math.round(i)+u*c+f*l,d=new Float64Array(o);if(Rr.translate(d,d,[h>.5?h-1:h,p>.5?p-1:p,0]),this.alignedProjMatrix=d,o=Rr.create(),Rr.scale(o,o,[this.width/2,-this.height/2,1]),Rr.translate(o,o,[1,-1,0]),this.pixelMatrix=Rr.multiply(new Float64Array(16),o,this.projMatrix),!(o=Rr.invert(new Float64Array(16),this.pixelMatrix)))throw new Error("failed to invert matrix");this.pixelMatrixInverse=o,this._posMatrixCache={},this._alignedPosMatrixCache={}}},Fr.prototype.maxPitchScaleFactor=function(){if(!this.pixelMatrixInverse)return 1;var e=this.pointCoordinate(new t.default$1(0,0)).zoomTo(this.zoom),r=[e.column*this.tileSize,e.row*this.tileSize,0,1];return Dr.transformMat4(r,r,this.pixelMatrix)[3]/this.cameraToCenterDistance},Object.defineProperties(Fr.prototype,Nr);var jr=function(){var e,r,n,i;t.bindAll(["_onHashChange","_updateHash"],this),this._updateHash=(e=this._updateHashUnthrottled.bind(this),300,r=!1,n=0,i=function(){n=0,r&&(e(),n=setTimeout(i,300),r=!1)},function(){return r=!0,n||i(),n})};jr.prototype.addTo=function(e){return this._map=e,t.default.addEventListener("hashchange",this._onHashChange,!1),this._map.on("moveend",this._updateHash),this},jr.prototype.remove=function(){return t.default.removeEventListener("hashchange",this._onHashChange,!1),this._map.off("moveend",this._updateHash),clearTimeout(this._updateHash()),delete this._map,this},jr.prototype.getHashString=function(t){var e=this._map.getCenter(),r=Math.round(100*this._map.getZoom())/100,n=Math.ceil((r*Math.LN2+Math.log(512/360/.5))/Math.LN10),i=Math.pow(10,n),a=Math.round(e.lng*i)/i,o=Math.round(e.lat*i)/i,s=this._map.getBearing(),l=this._map.getPitch(),c="";return c+=t?"#/"+a+"/"+o+"/"+r:"#"+r+"/"+o+"/"+a,(s||l)&&(c+="/"+Math.round(10*s)/10),l&&(c+="/"+Math.round(l)),c},jr.prototype._onHashChange=function(){var e=t.default.location.hash.replace("#","").split("/");return e.length>=3&&(this._map.jumpTo({center:[+e[2],+e[1]],zoom:+e[0],bearing:+(e[3]||0),pitch:+(e[4]||0)}),!0)},jr.prototype._updateHashUnthrottled=function(){var e=this.getHashString();t.default.history.replaceState(t.default.history.state,"",e)};var Vr=function(e){function r(r,n,i,a){void 0===a&&(a={});var o=s.mousePos(n.getCanvasContainer(),i),l=n.unproject(o);e.call(this,r,t.extend({point:o,lngLat:l,originalEvent:i},a)),this._defaultPrevented=!1,this.target=n}e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r;var n={defaultPrevented:{configurable:!0}};return r.prototype.preventDefault=function(){this._defaultPrevented=!0},n.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(r.prototype,n),r}(t.Event),Ur=function(e){function r(r,n,i){var a=s.touchPos(n.getCanvasContainer(),i),o=a.map(function(t){return n.unproject(t)}),l=a.reduce(function(t,e,r,n){return t.add(e.div(n.length))},new t.default$1(0,0)),c=n.unproject(l);e.call(this,r,{points:a,point:l,lngLats:o,lngLat:c,originalEvent:i}),this._defaultPrevented=!1}e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r;var n={defaultPrevented:{configurable:!0}};return r.prototype.preventDefault=function(){this._defaultPrevented=!0},n.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(r.prototype,n),r}(t.Event),qr=function(t){function e(e,r,n){t.call(this,e,{originalEvent:n}),this._defaultPrevented=!1}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={defaultPrevented:{configurable:!0}};return e.prototype.preventDefault=function(){this._defaultPrevented=!0},r.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(e.prototype,r),e}(t.Event),Hr=function(e){this._map=e,this._el=e.getCanvasContainer(),this._delta=0,t.bindAll(["_onWheel","_onTimeout","_onScrollFrame","_onScrollFinished"],this)};Hr.prototype.isEnabled=function(){return!!this._enabled},Hr.prototype.isActive=function(){return!!this._active},Hr.prototype.enable=function(t){this.isEnabled()||(this._enabled=!0,this._aroundCenter=t&&"center"===t.around)},Hr.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1)},Hr.prototype.onWheel=function(e){if(this.isEnabled()){var r=e.deltaMode===t.default.WheelEvent.DOM_DELTA_LINE?40*e.deltaY:e.deltaY,n=a.now(),i=n-(this._lastWheelEventTime||0);this._lastWheelEventTime=n,0!==r&&r%4.000244140625==0?this._type="wheel":0!==r&&Math.abs(r)<4?this._type="trackpad":i>400?(this._type=null,this._lastValue=r,this._timeout=setTimeout(this._onTimeout,40,e)):this._type||(this._type=Math.abs(i*r)<200?"trackpad":"wheel",this._timeout&&(clearTimeout(this._timeout),this._timeout=null,r+=this._lastValue)),e.shiftKey&&r&&(r/=4),this._type&&(this._lastWheelEvent=e,this._delta-=r,this.isActive()||this._start(e)),e.preventDefault()}},Hr.prototype._onTimeout=function(t){this._type="wheel",this._delta-=this._lastValue,this.isActive()||this._start(t)},Hr.prototype._start=function(e){if(this._delta){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),this._active=!0,this._map.fire(new t.Event("movestart",{originalEvent:e})),this._map.fire(new t.Event("zoomstart",{originalEvent:e})),this._finishTimeout&&clearTimeout(this._finishTimeout);var r=s.mousePos(this._el,e);this._around=G.convert(this._aroundCenter?this._map.getCenter():this._map.unproject(r)),this._aroundPoint=this._map.transform.locationPoint(this._around),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame))}},Hr.prototype._onScrollFrame=function(){var e=this;if(this._frameId=null,this.isActive()){var r=this._map.transform;if(0!==this._delta){var n="wheel"===this._type&&Math.abs(this._delta)>4.000244140625?1/450:.01,i=2/(1+Math.exp(-Math.abs(this._delta*n)));this._delta<0&&0!==i&&(i=1/i);var o="number"==typeof this._targetZoom?r.zoomScale(this._targetZoom):r.scale;this._targetZoom=Math.min(r.maxZoom,Math.max(r.minZoom,r.scaleZoom(o*i))),"wheel"===this._type&&(this._startZoom=r.zoom,this._easing=this._smoothOutEasing(200)),this._delta=0}var s=!1;if("wheel"===this._type){var l=Math.min((a.now()-this._lastWheelEventTime)/200,1),c=this._easing(l);r.zoom=t.number(this._startZoom,this._targetZoom,c),l<1?this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame)):s=!0}else r.zoom=this._targetZoom,s=!0;r.setLocationAtPoint(this._around,this._aroundPoint),this._map.fire(new t.Event("move",{originalEvent:this._lastWheelEvent})),this._map.fire(new t.Event("zoom",{originalEvent:this._lastWheelEvent})),s&&(this._active=!1,this._finishTimeout=setTimeout(function(){e._map.fire(new t.Event("zoomend",{originalEvent:e._lastWheelEvent})),e._map.fire(new t.Event("moveend",{originalEvent:e._lastWheelEvent})),delete e._targetZoom},200))}},Hr.prototype._smoothOutEasing=function(e){var r=t.ease;if(this._prevEase){var n=this._prevEase,i=(a.now()-n.start)/n.duration,o=n.easing(i+.01)-n.easing(i),s=.27/Math.sqrt(o*o+1e-4)*.01,l=Math.sqrt(.0729-s*s);r=t.bezier(s,l,.25,1)}return this._prevEase={start:a.now(),duration:e,easing:r},r};var Gr=function(e){this._map=e,this._el=e.getCanvasContainer(),this._container=e.getContainer(),t.bindAll(["_onMouseMove","_onMouseUp","_onKeyDown"],this)};Gr.prototype.isEnabled=function(){return!!this._enabled},Gr.prototype.isActive=function(){return!!this._active},Gr.prototype.enable=function(){this.isEnabled()||(this._enabled=!0)},Gr.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1)},Gr.prototype.onMouseDown=function(e){this.isEnabled()&&e.shiftKey&&0===e.button&&(t.default.document.addEventListener("mousemove",this._onMouseMove,!1),t.default.document.addEventListener("keydown",this._onKeyDown,!1),t.default.document.addEventListener("mouseup",this._onMouseUp,!1),s.disableDrag(),this._startPos=s.mousePos(this._el,e),this._active=!0)},Gr.prototype._onMouseMove=function(t){var e=this._startPos,r=s.mousePos(this._el,t);this._box||(this._box=s.create("div","mapboxgl-boxzoom",this._container),this._container.classList.add("mapboxgl-crosshair"),this._fireEvent("boxzoomstart",t));var n=Math.min(e.x,r.x),i=Math.max(e.x,r.x),a=Math.min(e.y,r.y),o=Math.max(e.y,r.y);s.setTransform(this._box,"translate("+n+"px,"+a+"px)"),this._box.style.width=i-n+"px",this._box.style.height=o-a+"px"},Gr.prototype._onMouseUp=function(e){if(0===e.button){var r=this._startPos,n=s.mousePos(this._el,e),i=(new W).extend(this._map.unproject(r)).extend(this._map.unproject(n));this._finish(),s.suppressClick(),r.x===n.x&&r.y===n.y?this._fireEvent("boxzoomcancel",e):this._map.fitBounds(i,{linear:!0}).fire(new t.Event("boxzoomend",{originalEvent:e,boxZoomBounds:i}))}},Gr.prototype._onKeyDown=function(t){27===t.keyCode&&(this._finish(),this._fireEvent("boxzoomcancel",t))},Gr.prototype._finish=function(){this._active=!1,t.default.document.removeEventListener("mousemove",this._onMouseMove,!1),t.default.document.removeEventListener("keydown",this._onKeyDown,!1),t.default.document.removeEventListener("mouseup",this._onMouseUp,!1),this._container.classList.remove("mapboxgl-crosshair"),this._box&&(s.remove(this._box),this._box=null),s.enableDrag()},Gr.prototype._fireEvent=function(e,r){return this._map.fire(new t.Event(e,{originalEvent:r}))};var Wr=t.bezier(0,0,.25,1),Yr=function(e,r){this._map=e,this._el=r.element||e.getCanvasContainer(),this._state="disabled",this._button=r.button||"right",this._bearingSnap=r.bearingSnap||0,this._pitchWithRotate=!1!==r.pitchWithRotate,t.bindAll(["_onMouseMove","_onMouseUp","_onBlur","_onDragFrame"],this)};Yr.prototype.isEnabled=function(){return"disabled"!==this._state},Yr.prototype.isActive=function(){return"active"===this._state},Yr.prototype.enable=function(){this.isEnabled()||(this._state="enabled")},Yr.prototype.disable=function(){if(this.isEnabled())switch(this._state){case"active":this._state="disabled",this._unbind(),this._deactivate(),this._fireEvent("rotateend"),this._pitchWithRotate&&this._fireEvent("pitchend"),this._fireEvent("moveend");break;case"pending":this._state="disabled",this._unbind();break;default:this._state="disabled"}},Yr.prototype.onMouseDown=function(e){if("enabled"===this._state){if("right"===this._button){if(this._eventButton=s.mouseButton(e),this._eventButton!==(e.ctrlKey?0:2))return}else{if(e.ctrlKey||0!==s.mouseButton(e))return;this._eventButton=0}s.disableDrag(),t.default.document.addEventListener("mousemove",this._onMouseMove,{capture:!0}),t.default.document.addEventListener("mouseup",this._onMouseUp),t.default.addEventListener("blur",this._onBlur),this._state="pending",this._inertia=[[a.now(),this._map.getBearing()]],this._previousPos=s.mousePos(this._el,e),this._center=this._map.transform.centerPoint,e.preventDefault()}},Yr.prototype._onMouseMove=function(t){this._lastMoveEvent=t,this._pos=s.mousePos(this._el,t),"pending"===this._state&&(this._state="active",this._fireEvent("rotatestart",t),this._fireEvent("movestart",t),this._pitchWithRotate&&this._fireEvent("pitchstart",t)),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onDragFrame))},Yr.prototype._onDragFrame=function(){this._frameId=null;var t=this._lastMoveEvent;if(t){var e=this._map.transform,r=this._previousPos,n=this._pos,i=.8*(r.x-n.x),o=-.5*(r.y-n.y),s=e.bearing-i,l=e.pitch-o,c=this._inertia,u=c[c.length-1];this._drainInertiaBuffer(),c.push([a.now(),this._map._normalizeBearing(s,u[1])]),e.bearing=s,this._pitchWithRotate&&(this._fireEvent("pitch",t),e.pitch=l),this._fireEvent("rotate",t),this._fireEvent("move",t),delete this._lastMoveEvent,this._previousPos=this._pos}},Yr.prototype._onMouseUp=function(t){if(s.mouseButton(t)===this._eventButton)switch(this._state){case"active":this._state="enabled",s.suppressClick(),this._unbind(),this._deactivate(),this._inertialRotate(t);break;case"pending":this._state="enabled",this._unbind()}},Yr.prototype._onBlur=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._fireEvent("rotateend",t),this._pitchWithRotate&&this._fireEvent("pitchend",t),this._fireEvent("moveend",t);break;case"pending":this._state="enabled",this._unbind()}},Yr.prototype._unbind=function(){t.default.document.removeEventListener("mousemove",this._onMouseMove,{capture:!0}),t.default.document.removeEventListener("mouseup",this._onMouseUp),t.default.removeEventListener("blur",this._onBlur),s.enableDrag()},Yr.prototype._deactivate=function(){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._lastMoveEvent,delete this._previousPos},Yr.prototype._inertialRotate=function(t){var e=this;this._fireEvent("rotateend",t),this._drainInertiaBuffer();var r=this._map,n=r.getBearing(),i=this._inertia,a=function(){Math.abs(n)180&&(p=180);var d=p/180;c+=f*p*(d/2),Math.abs(r._normalizeBearing(c,0))0&&e-t[0][0]>160;)t.shift()};var Xr=t.bezier(0,0,.3,1),Zr=function(e){this._map=e,this._el=e.getCanvasContainer(),this._state="disabled",t.bindAll(["_onMove","_onMouseUp","_onTouchEnd","_onBlur","_onDragFrame"],this)};Zr.prototype.isEnabled=function(){return"disabled"!==this._state},Zr.prototype.isActive=function(){return"active"===this._state},Zr.prototype.enable=function(){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-drag-pan"),this._state="enabled")},Zr.prototype.disable=function(){if(this.isEnabled())switch(this._el.classList.remove("mapboxgl-touch-drag-pan"),this._state){case"active":this._state="disabled",this._unbind(),this._deactivate(),this._fireEvent("dragend"),this._fireEvent("moveend");break;case"pending":this._state="disabled",this._unbind();break;default:this._state="disabled"}},Zr.prototype.onMouseDown=function(e){"enabled"===this._state&&(e.ctrlKey||0!==s.mouseButton(e)||(s.addEventListener(t.default.document,"mousemove",this._onMove,{capture:!0}),s.addEventListener(t.default.document,"mouseup",this._onMouseUp),this._start(e)))},Zr.prototype.onTouchStart=function(e){"enabled"===this._state&&(e.touches.length>1||(s.addEventListener(t.default.document,"touchmove",this._onMove,{capture:!0,passive:!1}),s.addEventListener(t.default.document,"touchend",this._onTouchEnd),this._start(e)))},Zr.prototype._start=function(e){t.default.addEventListener("blur",this._onBlur),this._state="pending",this._previousPos=s.mousePos(this._el,e),this._inertia=[[a.now(),this._previousPos]]},Zr.prototype._onMove=function(t){this._lastMoveEvent=t,t.preventDefault(),this._pos=s.mousePos(this._el,t),this._drainInertiaBuffer(),this._inertia.push([a.now(),this._pos]),"pending"===this._state&&(this._state="active",this._fireEvent("dragstart",t),this._fireEvent("movestart",t)),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onDragFrame))},Zr.prototype._onDragFrame=function(){this._frameId=null;var t=this._lastMoveEvent;if(t){var e=this._map.transform;e.setLocationAtPoint(e.pointLocation(this._previousPos),this._pos),this._fireEvent("drag",t),this._fireEvent("move",t),this._previousPos=this._pos,delete this._lastMoveEvent}},Zr.prototype._onMouseUp=function(t){if(0===s.mouseButton(t))switch(this._state){case"active":this._state="enabled",s.suppressClick(),this._unbind(),this._deactivate(),this._inertialPan(t);break;case"pending":this._state="enabled",this._unbind()}},Zr.prototype._onTouchEnd=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._inertialPan(t);break;case"pending":this._state="enabled",this._unbind()}},Zr.prototype._onBlur=function(t){switch(this._state){case"active":this._state="enabled",this._unbind(),this._deactivate(),this._fireEvent("dragend",t),this._fireEvent("moveend",t);break;case"pending":this._state="enabled",this._unbind()}},Zr.prototype._unbind=function(){s.removeEventListener(t.default.document,"touchmove",this._onMove,{capture:!0,passive:!1}),s.removeEventListener(t.default.document,"touchend",this._onTouchEnd),s.removeEventListener(t.default.document,"mousemove",this._onMove,{capture:!0}),s.removeEventListener(t.default.document,"mouseup",this._onMouseUp),s.removeEventListener(t.default,"blur",this._onBlur)},Zr.prototype._deactivate=function(){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._lastMoveEvent,delete this._previousPos,delete this._pos},Zr.prototype._inertialPan=function(t){this._fireEvent("dragend",t),this._drainInertiaBuffer();var e=this._inertia;if(e.length<2)this._fireEvent("moveend",t);else{var r=e[e.length-1],n=e[0],i=r[1].sub(n[1]),a=(r[0]-n[0])/1e3;if(0===a||r[1].equals(n[1]))this._fireEvent("moveend",t);else{var o=i.mult(.3/a),s=o.mag();s>1400&&(s=1400,o._unit()._mult(s));var l=s/750,c=o.mult(-l/2);this._map.panBy(c,{duration:1e3*l,easing:Xr,noMoveStart:!0},{originalEvent:t})}}},Zr.prototype._fireEvent=function(e,r){return this._map.fire(new t.Event(e,r?{originalEvent:r}:{}))},Zr.prototype._drainInertiaBuffer=function(){for(var t=this._inertia,e=a.now();t.length>0&&e-t[0][0]>160;)t.shift()};var $r=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onKeyDown"],this)};function Jr(t){return t*(2-t)}$r.prototype.isEnabled=function(){return!!this._enabled},$r.prototype.enable=function(){this.isEnabled()||(this._el.addEventListener("keydown",this._onKeyDown,!1),this._enabled=!0)},$r.prototype.disable=function(){this.isEnabled()&&(this._el.removeEventListener("keydown",this._onKeyDown),this._enabled=!1)},$r.prototype._onKeyDown=function(t){if(!(t.altKey||t.ctrlKey||t.metaKey)){var e=0,r=0,n=0,i=0,a=0;switch(t.keyCode){case 61:case 107:case 171:case 187:e=1;break;case 189:case 109:case 173:e=-1;break;case 37:t.shiftKey?r=-1:(t.preventDefault(),i=-1);break;case 39:t.shiftKey?r=1:(t.preventDefault(),i=1);break;case 38:t.shiftKey?n=1:(t.preventDefault(),a=-1);break;case 40:t.shiftKey?n=-1:(a=1,t.preventDefault());break;default:return}var o=this._map,s=o.getZoom(),l={duration:300,delayEndEvents:500,easing:Jr,zoom:e?Math.round(s)+e*(t.shiftKey?2:1):s,bearing:o.getBearing()+15*r,pitch:o.getPitch()+10*n,offset:[100*-i,100*-a],center:o.getCenter()};o.easeTo(l,{originalEvent:t})}};var Kr=function(e){this._map=e,t.bindAll(["_onDblClick","_onZoomEnd"],this)};Kr.prototype.isEnabled=function(){return!!this._enabled},Kr.prototype.isActive=function(){return!!this._active},Kr.prototype.enable=function(){this.isEnabled()||(this._enabled=!0)},Kr.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1)},Kr.prototype.onTouchStart=function(t){var e=this;this.isEnabled()&&(t.points.length>1||(this._tapped?(clearTimeout(this._tapped),this._tapped=null,this._zoom(t)):this._tapped=setTimeout(function(){e._tapped=null},300)))},Kr.prototype.onDblClick=function(t){this.isEnabled()&&(t.originalEvent.preventDefault(),this._zoom(t))},Kr.prototype._zoom=function(t){this._active=!0,this._map.on("zoomend",this._onZoomEnd),this._map.zoomTo(this._map.getZoom()+(t.originalEvent.shiftKey?-1:1),{around:t.lngLat},t)},Kr.prototype._onZoomEnd=function(){this._active=!1,this._map.off("zoomend",this._onZoomEnd)};var Qr=t.bezier(0,0,.15,1),tn=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onMove","_onEnd","_onTouchFrame"],this)};tn.prototype.isEnabled=function(){return!!this._enabled},tn.prototype.enable=function(t){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-zoom-rotate"),this._enabled=!0,this._aroundCenter=!!t&&"center"===t.around)},tn.prototype.disable=function(){this.isEnabled()&&(this._el.classList.remove("mapboxgl-touch-zoom-rotate"),this._enabled=!1)},tn.prototype.disableRotation=function(){this._rotationDisabled=!0},tn.prototype.enableRotation=function(){this._rotationDisabled=!1},tn.prototype.onStart=function(e){if(this.isEnabled()&&2===e.touches.length){var r=s.mousePos(this._el,e.touches[0]),n=s.mousePos(this._el,e.touches[1]);this._startVec=r.sub(n),this._gestureIntent=void 0,this._inertia=[],s.addEventListener(t.default.document,"touchmove",this._onMove,{passive:!1}),s.addEventListener(t.default.document,"touchend",this._onEnd)}},tn.prototype._getTouchEventData=function(t){var e=s.mousePos(this._el,t.touches[0]),r=s.mousePos(this._el,t.touches[1]),n=e.sub(r);return{vec:n,center:e.add(r).div(2),scale:n.mag()/this._startVec.mag(),bearing:this._rotationDisabled?0:180*n.angleWith(this._startVec)/Math.PI}},tn.prototype._onMove=function(e){if(2===e.touches.length){var r=this._getTouchEventData(e),n=r.vec,i=r.scale,a=r.bearing;if(!this._gestureIntent){var o=Math.abs(1-i)>.15;Math.abs(a)>10?this._gestureIntent="rotate":o&&(this._gestureIntent="zoom"),this._gestureIntent&&(this._map.fire(new t.Event(this._gestureIntent+"start",{originalEvent:e})),this._map.fire(new t.Event("movestart",{originalEvent:e})),this._startVec=n)}this._lastTouchEvent=e,this._frameId||(this._frameId=this._map._requestRenderFrame(this._onTouchFrame)),e.preventDefault()}},tn.prototype._onTouchFrame=function(){this._frameId=null;var e=this._gestureIntent;if(e){var r=this._map.transform;this._startScale||(this._startScale=r.scale,this._startBearing=r.bearing);var n=this._getTouchEventData(this._lastTouchEvent),i=n.center,o=n.bearing,s=n.scale,l=r.pointLocation(i),c=r.locationPoint(l);"rotate"===e&&(r.bearing=this._startBearing+o),r.zoom=r.scaleZoom(this._startScale*s),r.setLocationAtPoint(l,c),this._map.fire(new t.Event(e,{originalEvent:this._lastTouchEvent})),this._map.fire(new t.Event("move",{originalEvent:this._lastTouchEvent})),this._drainInertiaBuffer(),this._inertia.push([a.now(),s,i])}},tn.prototype._onEnd=function(e){s.removeEventListener(t.default.document,"touchmove",this._onMove,{passive:!1}),s.removeEventListener(t.default.document,"touchend",this._onEnd);var r=this._gestureIntent,n=this._startScale;if(this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._gestureIntent,delete this._startScale,delete this._startBearing,delete this._lastTouchEvent,r){this._map.fire(new t.Event(r+"end",{originalEvent:e})),this._drainInertiaBuffer();var i=this._inertia,a=this._map;if(i.length<2)a.snapToNorth({},{originalEvent:e});else{var o=i[i.length-1],l=i[0],c=a.transform.scaleZoom(n*o[1]),u=a.transform.scaleZoom(n*l[1]),f=c-u,h=(o[0]-l[0])/1e3,p=o[2];if(0!==h&&c!==u){var d=.15*f/h;Math.abs(d)>2.5&&(d=d>0?2.5:-2.5);var m=1e3*Math.abs(d/(12*.15)),g=c+d*m/2e3;g<0&&(g=0),a.easeTo({zoom:g,duration:m,easing:Qr,around:this._aroundCenter?a.getCenter():a.unproject(p),noMoveStart:!0},{originalEvent:e})}else a.snapToNorth({},{originalEvent:e})}}},tn.prototype._drainInertiaBuffer=function(){for(var t=this._inertia,e=a.now();t.length>2&&e-t[0][0]>160;)t.shift()};var en={scrollZoom:Hr,boxZoom:Gr,dragRotate:Yr,dragPan:Zr,keyboard:$r,doubleClickZoom:Kr,touchZoomRotate:tn},rn=function(e){function r(r,n){e.call(this),this._moving=!1,this._zooming=!1,this.transform=r,this._bearingSnap=n.bearingSnap,t.bindAll(["_renderFrameCallback"],this)}return e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r,r.prototype.getCenter=function(){return this.transform.center},r.prototype.setCenter=function(t,e){return this.jumpTo({center:t},e)},r.prototype.panBy=function(e,r,n){return e=t.default$1.convert(e).mult(-1),this.panTo(this.transform.center,t.extend({offset:e},r),n)},r.prototype.panTo=function(e,r,n){return this.easeTo(t.extend({center:e},r),n)},r.prototype.getZoom=function(){return this.transform.zoom},r.prototype.setZoom=function(t,e){return this.jumpTo({zoom:t},e),this},r.prototype.zoomTo=function(e,r,n){return this.easeTo(t.extend({zoom:e},r),n)},r.prototype.zoomIn=function(t,e){return this.zoomTo(this.getZoom()+1,t,e),this},r.prototype.zoomOut=function(t,e){return this.zoomTo(this.getZoom()-1,t,e),this},r.prototype.getBearing=function(){return this.transform.bearing},r.prototype.setBearing=function(t,e){return this.jumpTo({bearing:t},e),this},r.prototype.rotateTo=function(e,r,n){return this.easeTo(t.extend({bearing:e},r),n)},r.prototype.resetNorth=function(e,r){return this.rotateTo(0,t.extend({duration:1e3},e),r),this},r.prototype.snapToNorth=function(t,e){return Math.abs(this.getBearing())e?1:0}),["bottom","left","right","top"]))return t.warnOnce("options.padding must be a positive number, or an Object with keys 'bottom', 'left', 'right', 'top'"),this;e=W.convert(e);var a=[(r.padding.left-r.padding.right)/2,(r.padding.top-r.padding.bottom)/2],o=Math.min(r.padding.right,r.padding.left),s=Math.min(r.padding.top,r.padding.bottom);r.offset=[r.offset[0]+a[0],r.offset[1]+a[1]];var l=t.default$1.convert(r.offset),c=this.transform,u=c.project(e.getNorthWest()),f=c.project(e.getSouthEast()),h=f.sub(u),p=(c.width-2*o-2*Math.abs(l.x))/h.x,d=(c.height-2*s-2*Math.abs(l.y))/h.y;return d<0||p<0?(t.warnOnce("Map cannot fit within canvas with the given bounds, padding, and/or offset."),this):(r.center=c.unproject(u.add(f).div(2)),r.zoom=Math.min(c.scaleZoom(c.scale*Math.min(p,d)),r.maxZoom),r.bearing=0,r.linear?this.easeTo(r,n):this.flyTo(r,n))},r.prototype.jumpTo=function(e,r){this.stop();var n=this.transform,i=!1,a=!1,o=!1;return"zoom"in e&&n.zoom!==+e.zoom&&(i=!0,n.zoom=+e.zoom),void 0!==e.center&&(n.center=G.convert(e.center)),"bearing"in e&&n.bearing!==+e.bearing&&(a=!0,n.bearing=+e.bearing),"pitch"in e&&n.pitch!==+e.pitch&&(o=!0,n.pitch=+e.pitch),this.fire(new t.Event("movestart",r)).fire(new t.Event("move",r)),i&&this.fire(new t.Event("zoomstart",r)).fire(new t.Event("zoom",r)).fire(new t.Event("zoomend",r)),a&&this.fire(new t.Event("rotatestart",r)).fire(new t.Event("rotate",r)).fire(new t.Event("rotateend",r)),o&&this.fire(new t.Event("pitchstart",r)).fire(new t.Event("pitch",r)).fire(new t.Event("pitchend",r)),this.fire(new t.Event("moveend",r))},r.prototype.easeTo=function(e,r){var n=this;this.stop(),!1===(e=t.extend({offset:[0,0],duration:500,easing:t.ease},e)).animate&&(e.duration=0);var i=this.transform,a=this.getZoom(),o=this.getBearing(),s=this.getPitch(),l="zoom"in e?+e.zoom:a,c="bearing"in e?this._normalizeBearing(e.bearing,o):o,u="pitch"in e?+e.pitch:s,f=i.centerPoint.add(t.default$1.convert(e.offset)),h=i.pointLocation(f),p=G.convert(e.center||h);this._normalizeCenter(p);var d,m,g=i.project(h),v=i.project(p).sub(g),y=i.zoomScale(l-a);return e.around&&(d=G.convert(e.around),m=i.locationPoint(d)),this._zooming=l!==a,this._rotating=o!==c,this._pitching=u!==s,this._prepareEase(r,e.noMoveStart),clearTimeout(this._easeEndTimeoutID),this._ease(function(e){if(n._zooming&&(i.zoom=t.number(a,l,e)),n._rotating&&(i.bearing=t.number(o,c,e)),n._pitching&&(i.pitch=t.number(s,u,e)),d)i.setLocationAtPoint(d,m);else{var h=i.zoomScale(i.zoom-a),p=l>a?Math.min(2,y):Math.max(.5,y),x=Math.pow(p,1-e),b=i.unproject(g.add(v.mult(e*x)).mult(h));i.setLocationAtPoint(i.renderWorldCopies?b.wrap():b,f)}n._fireMoveEvents(r)},function(){e.delayEndEvents?n._easeEndTimeoutID=setTimeout(function(){return n._afterEase(r)},e.delayEndEvents):n._afterEase(r)},e),this},r.prototype._prepareEase=function(e,r){this._moving=!0,r||this.fire(new t.Event("movestart",e)),this._zooming&&this.fire(new t.Event("zoomstart",e)),this._rotating&&this.fire(new t.Event("rotatestart",e)),this._pitching&&this.fire(new t.Event("pitchstart",e))},r.prototype._fireMoveEvents=function(e){this.fire(new t.Event("move",e)),this._zooming&&this.fire(new t.Event("zoom",e)),this._rotating&&this.fire(new t.Event("rotate",e)),this._pitching&&this.fire(new t.Event("pitch",e))},r.prototype._afterEase=function(e){var r=this._zooming,n=this._rotating,i=this._pitching;this._moving=!1,this._zooming=!1,this._rotating=!1,this._pitching=!1,r&&this.fire(new t.Event("zoomend",e)),n&&this.fire(new t.Event("rotateend",e)),i&&this.fire(new t.Event("pitchend",e)),this.fire(new t.Event("moveend",e))},r.prototype.flyTo=function(e,r){var n=this;this.stop(),e=t.extend({offset:[0,0],speed:1.2,curve:1.42,easing:t.ease},e);var i=this.transform,a=this.getZoom(),o=this.getBearing(),s=this.getPitch(),l="zoom"in e?t.clamp(+e.zoom,i.minZoom,i.maxZoom):a,c="bearing"in e?this._normalizeBearing(e.bearing,o):o,u="pitch"in e?+e.pitch:s,f=i.zoomScale(l-a),h=i.centerPoint.add(t.default$1.convert(e.offset)),p=i.pointLocation(h),d=G.convert(e.center||p);this._normalizeCenter(d);var m=i.project(p),g=i.project(d).sub(m),v=e.curve,y=Math.max(i.width,i.height),x=y/f,b=g.mag();if("minZoom"in e){var _=t.clamp(Math.min(e.minZoom,a,l),i.minZoom,i.maxZoom),w=y/i.zoomScale(_-a);v=Math.sqrt(w/b*2)}var k=v*v;function M(t){var e=(x*x-y*y+(t?-1:1)*k*k*b*b)/(2*(t?x:y)*k*b);return Math.log(Math.sqrt(e*e+1)-e)}function A(t){return(Math.exp(t)-Math.exp(-t))/2}function T(t){return(Math.exp(t)+Math.exp(-t))/2}var S=M(0),E=function(t){return T(S)/T(S+v*t)},C=function(t){return y*((T(S)*(A(e=S+v*t)/T(e))-A(S))/k)/b;var e},L=(M(1)-S)/v;if(Math.abs(b)<1e-6||!isFinite(L)){if(Math.abs(y-x)<1e-6)return this.easeTo(e,r);var z=xe.maxDuration&&(e.duration=0),this._zooming=!0,this._rotating=o!==c,this._pitching=u!==s,this._prepareEase(r,!1),this._ease(function(e){var l=e*L,f=1/E(l);i.zoom=a+i.scaleZoom(f),n._rotating&&(i.bearing=t.number(o,c,e)),n._pitching&&(i.pitch=t.number(s,u,e));var p=i.unproject(m.add(g.mult(C(l))).mult(f));i.setLocationAtPoint(i.renderWorldCopies?p.wrap():p,h),n._fireMoveEvents(r)},function(){return n._afterEase(r)},e),this},r.prototype.isEasing=function(){return!!this._easeFrameId},r.prototype.stop=function(){if(this._easeFrameId&&(this._cancelRenderFrame(this._easeFrameId),delete this._easeFrameId,delete this._onEaseFrame),this._onEaseEnd){var t=this._onEaseEnd;delete this._onEaseEnd,t.call(this)}return this},r.prototype._ease=function(t,e,r){!1===r.animate||0===r.duration?(t(1),e()):(this._easeStart=a.now(),this._easeOptions=r,this._onEaseFrame=t,this._onEaseEnd=e,this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback))},r.prototype._renderFrameCallback=function(){var t=Math.min((a.now()-this._easeStart)/this._easeOptions.duration,1);this._onEaseFrame(this._easeOptions.easing(t)),t<1?this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback):this.stop()},r.prototype._normalizeBearing=function(e,r){e=t.wrap(e,-180,180);var n=Math.abs(e-r);return Math.abs(e-360-r)180?-360:r<-180?360:0}},r}(t.Evented),nn=function(e){void 0===e&&(e={}),this.options=e,t.bindAll(["_updateEditLink","_updateData","_updateCompact"],this)};nn.prototype.getDefaultPosition=function(){return"bottom-right"},nn.prototype.onAdd=function(t){var e=this.options&&this.options.compact;return this._map=t,this._container=s.create("div","mapboxgl-ctrl mapboxgl-ctrl-attrib"),e&&this._container.classList.add("mapboxgl-compact"),this._updateAttributions(),this._updateEditLink(),this._map.on("sourcedata",this._updateData),this._map.on("moveend",this._updateEditLink),void 0===e&&(this._map.on("resize",this._updateCompact),this._updateCompact()),this._container},nn.prototype.onRemove=function(){s.remove(this._container),this._map.off("sourcedata",this._updateData),this._map.off("moveend",this._updateEditLink),this._map.off("resize",this._updateCompact),this._map=void 0},nn.prototype._updateEditLink=function(){var t=this._editLink;t||(t=this._editLink=this._container.querySelector(".mapbox-improve-map"));var e=[{key:"owner",value:this.styleOwner},{key:"id",value:this.styleId},{key:"access_token",value:g.ACCESS_TOKEN}];if(t){var r=e.reduce(function(t,r,n){return r.value&&(t+=r.key+"="+r.value+(n=0)return!1;return!0})).length?(this._container.innerHTML=t.join(" | "),this._container.classList.remove("mapboxgl-attrib-empty")):this._container.classList.add("mapboxgl-attrib-empty"),this._editLink=null}},nn.prototype._updateCompact=function(){this._map.getCanvasContainer().offsetWidth<=640?this._container.classList.add("mapboxgl-compact"):this._container.classList.remove("mapboxgl-compact")};var an=function(){t.bindAll(["_updateLogo"],this)};an.prototype.onAdd=function(t){this._map=t,this._container=s.create("div","mapboxgl-ctrl");var e=s.create("a","mapboxgl-ctrl-logo");return e.target="_blank",e.href="https://www.mapbox.com/",e.setAttribute("aria-label","Mapbox logo"),this._container.appendChild(e),this._container.style.display="none",this._map.on("sourcedata",this._updateLogo),this._updateLogo(),this._container},an.prototype.onRemove=function(){s.remove(this._container),this._map.off("sourcedata",this._updateLogo)},an.prototype.getDefaultPosition=function(){return"bottom-left"},an.prototype._updateLogo=function(t){t&&"metadata"!==t.sourceDataType||(this._container.style.display=this._logoRequired()?"block":"none")},an.prototype._logoRequired=function(){if(this._map.style){var t=this._map.style.sourceCaches;for(var e in t)if(t[e].getSource().mapbox_logo)return!0;return!1}};var on=function(){this._queue=[],this._id=0,this._cleared=!1,this._currentlyRunning=!1};on.prototype.add=function(t){var e=++this._id;return this._queue.push({callback:t,id:e,cancelled:!1}),e},on.prototype.remove=function(t){for(var e=this._currentlyRunning,r=0,n=e?this._queue.concat(e):this._queue;re.maxZoom)throw new Error("maxZoom must be greater than minZoom");var n=new Fr(e.minZoom,e.maxZoom,e.renderWorldCopies);r.call(this,n,e),this._interactive=e.interactive,this._maxTileCacheSize=e.maxTileCacheSize,this._failIfMajorPerformanceCaveat=e.failIfMajorPerformanceCaveat,this._preserveDrawingBuffer=e.preserveDrawingBuffer,this._trackResize=e.trackResize,this._bearingSnap=e.bearingSnap,this._refreshExpiredTiles=e.refreshExpiredTiles,this._fadeDuration=e.fadeDuration,this._crossFadingFactor=1,this._collectResourceTiming=e.collectResourceTiming,this._renderTaskQueue=new on;var i=e.transformRequest;if(this._transformRequest=i?function(t,e){return i(t,e)||{url:t}}:function(t){return{url:t}},"string"==typeof e.container){var a=t.default.document.getElementById(e.container);if(!a)throw new Error("Container '"+e.container+"' not found.");this._container=a}else{if(!(e.container instanceof ln))throw new Error("Invalid type: 'container' must be a String or HTMLElement.");this._container=e.container}e.maxBounds&&this.setMaxBounds(e.maxBounds),t.bindAll(["_onWindowOnline","_onWindowResize","_contextLost","_contextRestored","_update","_render","_onData","_onDataLoading"],this),this._setupContainer(),this._setupPainter(),this.on("move",this._update.bind(this,!1)),this.on("zoom",this._update.bind(this,!0)),void 0!==t.default&&(t.default.addEventListener("online",this._onWindowOnline,!1),t.default.addEventListener("resize",this._onWindowResize,!1)),function(t,e){var r=t.getCanvasContainer(),n=null,i=!1;for(var a in en)t[a]=new en[a](t,e),e.interactive&&e[a]&&t[a].enable(e[a]);s.addEventListener(r,"mouseout",function(e){t.fire(new Vr("mouseout",t,e))}),s.addEventListener(r,"mousedown",function(r){i=!0;var n=new Vr("mousedown",t,r);t.fire(n),n.defaultPrevented||(e.interactive&&!t.doubleClickZoom.isActive()&&t.stop(),t.boxZoom.onMouseDown(r),t.boxZoom.isActive()||t.dragPan.isActive()||t.dragRotate.onMouseDown(r),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onMouseDown(r))}),s.addEventListener(r,"mouseup",function(e){var r=t.dragRotate.isActive();n&&!r&&t.fire(new Vr("contextmenu",t,n)),n=null,i=!1,t.fire(new Vr("mouseup",t,e))}),s.addEventListener(r,"mousemove",function(e){if(!t.dragPan.isActive()&&!t.dragRotate.isActive()){for(var n=e.toElement||e.target;n&&n!==r;)n=n.parentNode;n===r&&t.fire(new Vr("mousemove",t,e))}}),s.addEventListener(r,"mouseover",function(e){for(var n=e.toElement||e.target;n&&n!==r;)n=n.parentNode;n===r&&t.fire(new Vr("mouseover",t,e))}),s.addEventListener(r,"touchstart",function(r){var n=new Ur("touchstart",t,r);t.fire(n),n.defaultPrevented||(e.interactive&&t.stop(),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onTouchStart(r),t.touchZoomRotate.onStart(r),t.doubleClickZoom.onTouchStart(n))},{passive:!1}),s.addEventListener(r,"touchmove",function(e){t.fire(new Ur("touchmove",t,e))},{passive:!1}),s.addEventListener(r,"touchend",function(e){t.fire(new Ur("touchend",t,e))}),s.addEventListener(r,"touchcancel",function(e){t.fire(new Ur("touchcancel",t,e))}),s.addEventListener(r,"click",function(e){t.fire(new Vr("click",t,e))}),s.addEventListener(r,"dblclick",function(e){var r=new Vr("dblclick",t,e);t.fire(r),r.defaultPrevented||t.doubleClickZoom.onDblClick(r)}),s.addEventListener(r,"contextmenu",function(e){var r=t.dragRotate.isActive();i||r?i&&(n=e):t.fire(new Vr("contextmenu",t,e)),e.preventDefault()}),s.addEventListener(r,"wheel",function(e){var r=new qr("wheel",t,e);t.fire(r),r.defaultPrevented||t.scrollZoom.onWheel(e)},{passive:!1})}(this,e),this._hash=e.hash&&(new jr).addTo(this),this._hash&&this._hash._onHashChange()||this.jumpTo({center:e.center,zoom:e.zoom,bearing:e.bearing,pitch:e.pitch}),this.resize(),e.style&&this.setStyle(e.style,{localIdeographFontFamily:e.localIdeographFontFamily}),e.attributionControl&&this.addControl(new nn),this.addControl(new an,e.logoPosition),this.on("style.load",function(){this.transform.unmodified&&this.jumpTo(this.style.stylesheet)}),this.on("data",this._onData),this.on("dataloading",this._onDataLoading)}r&&(n.__proto__=r),n.prototype=Object.create(r&&r.prototype),n.prototype.constructor=n;var i={showTileBoundaries:{configurable:!0},showCollisionBoxes:{configurable:!0},showOverdrawInspector:{configurable:!0},repaint:{configurable:!0},vertices:{configurable:!0}};return n.prototype.addControl=function(t,e){void 0===e&&t.getDefaultPosition&&(e=t.getDefaultPosition()),void 0===e&&(e="top-right");var r=t.onAdd(this),n=this._controlPositions[e];return-1!==e.indexOf("bottom")?n.insertBefore(r,n.firstChild):n.appendChild(r),this},n.prototype.removeControl=function(t){return t.onRemove(this),this},n.prototype.resize=function(e){var r=this._containerDimensions(),n=r[0],i=r[1];return this._resizeCanvas(n,i),this.transform.resize(n,i),this.painter.resize(n,i),this.fire(new t.Event("movestart",e)).fire(new t.Event("move",e)).fire(new t.Event("resize",e)).fire(new t.Event("moveend",e))},n.prototype.getBounds=function(){var e=new W(this.transform.pointLocation(new t.default$1(0,this.transform.height)),this.transform.pointLocation(new t.default$1(this.transform.width,0)));return(this.transform.angle||this.transform.pitch)&&(e.extend(this.transform.pointLocation(new t.default$1(this.transform.size.x,0))),e.extend(this.transform.pointLocation(new t.default$1(0,this.transform.size.y)))),e},n.prototype.getMaxBounds=function(){return this.transform.latRange&&2===this.transform.latRange.length&&this.transform.lngRange&&2===this.transform.lngRange.length?new W([this.transform.lngRange[0],this.transform.latRange[0]],[this.transform.lngRange[1],this.transform.latRange[1]]):null},n.prototype.setMaxBounds=function(t){if(t){var e=W.convert(t);this.transform.lngRange=[e.getWest(),e.getEast()],this.transform.latRange=[e.getSouth(),e.getNorth()],this.transform._constrain(),this._update()}else null==t&&(this.transform.lngRange=null,this.transform.latRange=null,this._update());return this},n.prototype.setMinZoom=function(t){if((t=null==t?0:t)>=0&&t<=this.transform.maxZoom)return this.transform.minZoom=t,this._update(),this.getZoom()=this.transform.minZoom)return this.transform.maxZoom=t,this._update(),this.getZoom()>t&&this.setZoom(t),this;throw new Error("maxZoom must be greater than the current minZoom")},n.prototype.getRenderWorldCopies=function(){return this.transform.renderWorldCopies},n.prototype.setRenderWorldCopies=function(t){return this.transform.renderWorldCopies=t,this._update(),this},n.prototype.getMaxZoom=function(){return this.transform.maxZoom},n.prototype.project=function(t){return this.transform.locationPoint(G.convert(t))},n.prototype.unproject=function(e){return this.transform.pointLocation(t.default$1.convert(e))},n.prototype.isMoving=function(){return this._moving||this.dragPan.isActive()||this.dragRotate.isActive()||this.scrollZoom.isActive()},n.prototype.isZooming=function(){return this._zooming||this.scrollZoom.isActive()},n.prototype.isRotating=function(){return this._rotating||this.dragRotate.isActive()},n.prototype.on=function(t,e,n){var i,a=this;if(void 0===n)return r.prototype.on.call(this,t,e);var o=function(){if("mouseenter"===t||"mouseover"===t){var r=!1;return{layer:e,listener:n,delegates:{mousemove:function(i){var o=a.getLayer(e)?a.queryRenderedFeatures(i.point,{layers:[e]}):[];o.length?r||(r=!0,n.call(a,new Vr(t,a,i.originalEvent,{features:o}))):r=!1},mouseout:function(){r=!1}}}}if("mouseleave"===t||"mouseout"===t){var o=!1;return{layer:e,listener:n,delegates:{mousemove:function(r){(a.getLayer(e)?a.queryRenderedFeatures(r.point,{layers:[e]}):[]).length?o=!0:o&&(o=!1,n.call(a,new Vr(t,a,r.originalEvent)))},mouseout:function(e){o&&(o=!1,n.call(a,new Vr(t,a,e.originalEvent)))}}}}return{layer:e,listener:n,delegates:(i={},i[t]=function(t){var r=a.getLayer(e)?a.queryRenderedFeatures(t.point,{layers:[e]}):[];r.length&&(t.features=r,n.call(a,t),delete t.features)},i)}}();for(var s in this._delegatedListeners=this._delegatedListeners||{},this._delegatedListeners[t]=this._delegatedListeners[t]||[],this._delegatedListeners[t].push(o),o.delegates)a.on(s,o.delegates[s]);return this},n.prototype.off=function(t,e,n){if(void 0===n)return r.prototype.off.call(this,t,e);if(this._delegatedListeners&&this._delegatedListeners[t])for(var i=this._delegatedListeners[t],a=0;a180;){var o=r.locationPoint(t);if(o.x>=0&&o.y>=0&&o.x<=r.width&&o.y<=r.height)break;t.lng>r.center.lng?t.lng-=360:t.lng+=360}return t}pn.prototype._rotateCompassArrow=function(){var t="rotate("+this._map.transform.angle*(180/Math.PI)+"deg)";this._compassArrow.style.transform=t},pn.prototype.onAdd=function(t){return this._map=t,this.options.showCompass&&(this._map.on("rotate",this._rotateCompassArrow),this._rotateCompassArrow(),this._handler=new Yr(t,{button:"left",element:this._compass}),this._handler.enable()),this._container},pn.prototype.onRemove=function(){s.remove(this._container),this.options.showCompass&&(this._map.off("rotate",this._rotateCompassArrow),this._handler.disable(),delete this._handler),delete this._map},pn.prototype._createButton=function(t,e,r){var n=s.create("button",t,this._container);return n.type="button",n.setAttribute("aria-label",e),n.addEventListener("click",r),n};var mn={center:"translate(-50%,-50%)",top:"translate(-50%,0)","top-left":"translate(0,0)","top-right":"translate(-100%,0)",bottom:"translate(-50%,-100%)","bottom-left":"translate(0,-100%)","bottom-right":"translate(-100%,-100%)",left:"translate(0,-50%)",right:"translate(-100%,-50%)"};function gn(t,e,r){var n=t.classList;for(var i in mn)n.remove("mapboxgl-"+r+"-anchor-"+i);n.add("mapboxgl-"+r+"-anchor-"+e)}var vn=function(e){if((arguments[0]instanceof t.default.HTMLElement||2===arguments.length)&&(e=t.extend({element:e},arguments[1])),t.bindAll(["_update","_onMapClick"],this),this._anchor=e&&e.anchor||"center",this._color=e&&e.color||"#3FB1CE",e&&e.element)this._element=e.element,this._offset=t.default$1.convert(e&&e.offset||[0,0]);else{this._defaultMarker=!0,this._element=s.create("div");var r=s.createNS("http://www.w3.org/2000/svg","svg");r.setAttributeNS(null,"height","41px"),r.setAttributeNS(null,"width","27px"),r.setAttributeNS(null,"viewBox","0 0 27 41");var n=s.createNS("http://www.w3.org/2000/svg","g");n.setAttributeNS(null,"stroke","none"),n.setAttributeNS(null,"stroke-width","1"),n.setAttributeNS(null,"fill","none"),n.setAttributeNS(null,"fill-rule","evenodd");var i=s.createNS("http://www.w3.org/2000/svg","g");i.setAttributeNS(null,"fill-rule","nonzero");var a=s.createNS("http://www.w3.org/2000/svg","g");a.setAttributeNS(null,"transform","translate(3.0, 29.0)"),a.setAttributeNS(null,"fill","#000000");for(var o=0,l=[{rx:"10.5",ry:"5.25002273"},{rx:"10.5",ry:"5.25002273"},{rx:"9.5",ry:"4.77275007"},{rx:"8.5",ry:"4.29549936"},{rx:"7.5",ry:"3.81822308"},{rx:"6.5",ry:"3.34094679"},{rx:"5.5",ry:"2.86367051"},{rx:"4.5",ry:"2.38636864"}];o5280?Mn(e,c,h/5280,"mi"):Mn(e,c,h,"ft")}else r&&"nautical"===r.unit?Mn(e,c,f/1852,"nm"):Mn(e,c,f,"m")}function Mn(t,e,r,n){var i,a,o,s=(i=r,(a=Math.pow(10,(""+Math.floor(i)).length-1))*(o=(o=i/a)>=10?10:o>=5?5:o>=3?3:o>=2?2:1)),l=s/r;"m"===n&&s>=1e3&&(s/=1e3,n="km"),t.style.width=e*l+"px",t.innerHTML=s+n}wn.prototype.getDefaultPosition=function(){return"bottom-left"},wn.prototype._onMove=function(){kn(this._map,this._container,this.options)},wn.prototype.onAdd=function(t){return this._map=t,this._container=s.create("div","mapboxgl-ctrl mapboxgl-ctrl-scale",t.getContainer()),this._map.on("move",this._onMove),this._onMove(),this._container},wn.prototype.onRemove=function(){s.remove(this._container),this._map.off("move",this._onMove),this._map=void 0},wn.prototype.setUnit=function(t){this.options.unit=t,kn(this._map,this._container,this.options)};var An=function(){this._fullscreen=!1,t.bindAll(["_onClickFullscreen","_changeIcon"],this),"onfullscreenchange"in t.default.document?this._fullscreenchange="fullscreenchange":"onmozfullscreenchange"in t.default.document?this._fullscreenchange="mozfullscreenchange":"onwebkitfullscreenchange"in t.default.document?this._fullscreenchange="webkitfullscreenchange":"onmsfullscreenchange"in t.default.document&&(this._fullscreenchange="MSFullscreenChange"),this._className="mapboxgl-ctrl"};An.prototype.onAdd=function(e){return this._map=e,this._mapContainer=this._map.getContainer(),this._container=s.create("div",this._className+" mapboxgl-ctrl-group"),this._checkFullscreenSupport()?this._setupUI():(this._container.style.display="none",t.warnOnce("This device does not support fullscreen mode.")),this._container},An.prototype.onRemove=function(){s.remove(this._container),this._map=null,t.default.document.removeEventListener(this._fullscreenchange,this._changeIcon)},An.prototype._checkFullscreenSupport=function(){return!!(t.default.document.fullscreenEnabled||t.default.document.mozFullScreenEnabled||t.default.document.msFullscreenEnabled||t.default.document.webkitFullscreenEnabled)},An.prototype._setupUI=function(){var e=this._fullscreenButton=s.create("button",this._className+"-icon "+this._className+"-fullscreen",this._container);e.setAttribute("aria-label","Toggle fullscreen"),e.type="button",this._fullscreenButton.addEventListener("click",this._onClickFullscreen),t.default.document.addEventListener(this._fullscreenchange,this._changeIcon)},An.prototype._isFullscreen=function(){return this._fullscreen},An.prototype._changeIcon=function(){(t.default.document.fullscreenElement||t.default.document.mozFullScreenElement||t.default.document.webkitFullscreenElement||t.default.document.msFullscreenElement)===this._mapContainer!==this._fullscreen&&(this._fullscreen=!this._fullscreen,this._fullscreenButton.classList.toggle(this._className+"-shrink"),this._fullscreenButton.classList.toggle(this._className+"-fullscreen"))},An.prototype._onClickFullscreen=function(){this._isFullscreen()?t.default.document.exitFullscreen?t.default.document.exitFullscreen():t.default.document.mozCancelFullScreen?t.default.document.mozCancelFullScreen():t.default.document.msExitFullscreen?t.default.document.msExitFullscreen():t.default.document.webkitCancelFullScreen&&t.default.document.webkitCancelFullScreen():this._mapContainer.requestFullscreen?this._mapContainer.requestFullscreen():this._mapContainer.mozRequestFullScreen?this._mapContainer.mozRequestFullScreen():this._mapContainer.msRequestFullscreen?this._mapContainer.msRequestFullscreen():this._mapContainer.webkitRequestFullscreen&&this._mapContainer.webkitRequestFullscreen()};var Tn={closeButton:!0,closeOnClick:!0},Sn=function(e){function r(r){e.call(this),this.options=t.extend(Object.create(Tn),r),t.bindAll(["_update","_onClickClose"],this)}return e&&(r.__proto__=e),r.prototype=Object.create(e&&e.prototype),r.prototype.constructor=r,r.prototype.addTo=function(e){return this._map=e,this._map.on("move",this._update),this.options.closeOnClick&&this._map.on("click",this._onClickClose),this._update(),this.fire(new t.Event("open")),this},r.prototype.isOpen=function(){return!!this._map},r.prototype.remove=function(){return this._content&&s.remove(this._content),this._container&&(s.remove(this._container),delete this._container),this._map&&(this._map.off("move",this._update),this._map.off("click",this._onClickClose),delete this._map),this.fire(new t.Event("close")),this},r.prototype.getLngLat=function(){return this._lngLat},r.prototype.setLngLat=function(t){return this._lngLat=G.convert(t),this._pos=null,this._update(),this},r.prototype.setText=function(e){return this.setDOMContent(t.default.document.createTextNode(e))},r.prototype.setHTML=function(e){var r,n=t.default.document.createDocumentFragment(),i=t.default.document.createElement("body");for(i.innerHTML=e;r=i.firstChild;)n.appendChild(r);return this.setDOMContent(n)},r.prototype.setDOMContent=function(t){return this._createContent(),this._content.appendChild(t),this._update(),this},r.prototype._createContent=function(){this._content&&s.remove(this._content),this._content=s.create("div","mapboxgl-popup-content",this._container),this.options.closeButton&&(this._closeButton=s.create("button","mapboxgl-popup-close-button",this._content),this._closeButton.type="button",this._closeButton.setAttribute("aria-label","Close popup"),this._closeButton.innerHTML="×",this._closeButton.addEventListener("click",this._onClickClose))},r.prototype._update=function(){if(this._map&&this._lngLat&&this._content){this._container||(this._container=s.create("div","mapboxgl-popup",this._map.getContainer()),this._tip=s.create("div","mapboxgl-popup-tip",this._container),this._container.appendChild(this._content)),this._map.transform.renderWorldCopies&&(this._lngLat=dn(this._lngLat,this._pos,this._map.transform));var e=this._pos=this._map.project(this._lngLat),r=this.options.anchor,n=function e(r){if(r){if("number"==typeof r){var n=Math.round(Math.sqrt(.5*Math.pow(r,2)));return{center:new t.default$1(0,0),top:new t.default$1(0,r),"top-left":new t.default$1(n,n),"top-right":new t.default$1(-n,n),bottom:new t.default$1(0,-r),"bottom-left":new t.default$1(n,-n),"bottom-right":new t.default$1(-n,-n),left:new t.default$1(r,0),right:new t.default$1(-r,0)}}if(r instanceof t.default$1||Array.isArray(r)){var i=t.default$1.convert(r);return{center:i,top:i,"top-left":i,"top-right":i,bottom:i,"bottom-left":i,"bottom-right":i,left:i,right:i}}return{center:t.default$1.convert(r.center||[0,0]),top:t.default$1.convert(r.top||[0,0]),"top-left":t.default$1.convert(r["top-left"]||[0,0]),"top-right":t.default$1.convert(r["top-right"]||[0,0]),bottom:t.default$1.convert(r.bottom||[0,0]),"bottom-left":t.default$1.convert(r["bottom-left"]||[0,0]),"bottom-right":t.default$1.convert(r["bottom-right"]||[0,0]),left:t.default$1.convert(r.left||[0,0]),right:t.default$1.convert(r.right||[0,0])}}return e(new t.default$1(0,0))}(this.options.offset);if(!r){var i,a=this._container.offsetWidth,o=this._container.offsetHeight;i=e.y+n.bottom.ythis._map.transform.height-o?["bottom"]:[],e.xthis._map.transform.width-a/2&&i.push("right"),r=0===i.length?"bottom":i.join("-")}var l=e.add(n[r]).round();s.setTransform(this._container,mn[r]+" translate("+l.x+"px,"+l.y+"px)"),gn(this._container,r,"popup")}},r.prototype._onClickClose=function(){this.remove()},r}(t.Evented),En={version:"0.45.0",supported:e,workerCount:Math.max(Math.floor(a.hardwareConcurrency/2),1),setRTLTextPlugin:t.setRTLTextPlugin,Map:un,NavigationControl:pn,GeolocateControl:bn,AttributionControl:nn,ScaleControl:wn,FullscreenControl:An,Popup:Sn,Marker:vn,Style:Je,LngLat:G,LngLatBounds:W,Point:t.default$1,Evented:t.Evented,config:g,get accessToken(){return g.ACCESS_TOKEN},set accessToken(t){g.ACCESS_TOKEN=t},workerUrl:""};return En}),n})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],410:[function(t,e,r){"use strict";e.exports=function(t){for(var e=1<p[1][2]&&(v[0]=-v[0]),p[0][2]>p[2][0]&&(v[1]=-v[1]),p[1][0]>p[0][1]&&(v[2]=-v[2]),!0}},{"./normalize":412,"gl-mat4/clone":248,"gl-mat4/create":249,"gl-mat4/determinant":250,"gl-mat4/invert":254,"gl-mat4/transpose":264,"gl-vec3/cross":317,"gl-vec3/dot":322,"gl-vec3/length":332,"gl-vec3/normalize":339}],412:[function(t,e,r){e.exports=function(t,e){var r=e[15];if(0===r)return!1;for(var n=1/r,i=0;i<16;i++)t[i]=e[i]*n;return!0}},{}],413:[function(t,e,r){var n=t("gl-vec3/lerp"),i=t("mat4-recompose"),a=t("mat4-decompose"),o=t("gl-mat4/determinant"),s=t("quat-slerp"),l=f(),c=f(),u=f();function f(){return{translate:h(),scale:h(1),skew:h(),perspective:[0,0,0,1],quaternion:[0,0,0,1]}}function h(t){return[t||0,t||0,t||0]}e.exports=function(t,e,r,f){if(0===o(e)||0===o(r))return!1;var h=a(e,l.translate,l.scale,l.skew,l.perspective,l.quaternion),p=a(r,c.translate,c.scale,c.skew,c.perspective,c.quaternion);return!(!h||!p||(n(u.translate,l.translate,c.translate,f),n(u.skew,l.skew,c.skew,f),n(u.scale,l.scale,c.scale,f),n(u.perspective,l.perspective,c.perspective,f),s(u.quaternion,l.quaternion,c.quaternion,f),i(t,u.translate,u.scale,u.skew,u.perspective,u.quaternion),0))}},{"gl-mat4/determinant":250,"gl-vec3/lerp":333,"mat4-decompose":411,"mat4-recompose":414,"quat-slerp":466}],414:[function(t,e,r){var n={identity:t("gl-mat4/identity"),translate:t("gl-mat4/translate"),multiply:t("gl-mat4/multiply"),create:t("gl-mat4/create"),scale:t("gl-mat4/scale"),fromRotationTranslation:t("gl-mat4/fromRotationTranslation")},i=(n.create(),n.create());e.exports=function(t,e,r,a,o,s){return n.identity(t),n.fromRotationTranslation(t,s,e),t[3]=o[0],t[7]=o[1],t[11]=o[2],t[15]=o[3],n.identity(i),0!==a[2]&&(i[9]=a[2],n.multiply(t,t,i)),0!==a[1]&&(i[9]=0,i[8]=a[1],n.multiply(t,t,i)),0!==a[0]&&(i[8]=0,i[4]=a[0],n.multiply(t,t,i)),n.scale(t,t,r),t}},{"gl-mat4/create":249,"gl-mat4/fromRotationTranslation":252,"gl-mat4/identity":253,"gl-mat4/multiply":256,"gl-mat4/scale":262,"gl-mat4/translate":263}],415:[function(t,e,r){"use strict";e.exports=Math.log2||function(t){return Math.log(t)*Math.LOG2E}},{}],416:[function(t,e,r){"use strict";var n=t("binary-search-bounds"),i=t("mat4-interpolate"),a=t("gl-mat4/invert"),o=t("gl-mat4/rotateX"),s=t("gl-mat4/rotateY"),l=t("gl-mat4/rotateZ"),c=t("gl-mat4/lookAt"),u=t("gl-mat4/translate"),f=(t("gl-mat4/scale"),t("gl-vec3/normalize")),h=[0,0,0];function p(t){this._components=t.slice(),this._time=[0],this.prevMatrix=t.slice(),this.nextMatrix=t.slice(),this.computedMatrix=t.slice(),this.computedInverse=t.slice(),this.computedEye=[0,0,0],this.computedUp=[0,0,0],this.computedCenter=[0,0,0],this.computedRadius=[0],this._limits=[-1/0,1/0]}e.exports=function(t){return new p((t=t||{}).matrix||[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])};var d=p.prototype;d.recalcMatrix=function(t){var e=this._time,r=n.le(e,t),o=this.computedMatrix;if(!(r<0)){var s=this._components;if(r===e.length-1)for(var l=16*r,c=0;c<16;++c)o[c]=s[l++];else{var u=e[r+1]-e[r],h=(l=16*r,this.prevMatrix),p=!0;for(c=0;c<16;++c)h[c]=s[l++];var d=this.nextMatrix;for(c=0;c<16;++c)d[c]=s[l++],p=p&&h[c]===d[c];if(u<1e-6||p)for(c=0;c<16;++c)o[c]=h[c];else i(o,h,d,(t-e[r])/u)}var m=this.computedUp;m[0]=o[1],m[1]=o[5],m[2]=o[9],f(m,m);var g=this.computedInverse;a(g,o);var v=this.computedEye,y=g[15];v[0]=g[12]/y,v[1]=g[13]/y,v[2]=g[14]/y;var x=this.computedCenter,b=Math.exp(this.computedRadius[0]);for(c=0;c<3;++c)x[c]=v[c]-o[2+4*c]*b}},d.idle=function(t){if(!(t1&&n(t[o[u-2]],t[o[u-1]],c)<=0;)u-=1,o.pop();for(o.push(l),u=s.length;u>1&&n(t[s[u-2]],t[s[u-1]],c)>=0;)u-=1,s.pop();s.push(l)}for(var r=new Array(s.length+o.length-2),f=0,i=0,h=o.length;i0;--p)r[f++]=s[p];return r};var n=t("robust-orientation")[3]},{"robust-orientation":486}],418:[function(t,e,r){"use strict";e.exports=function(t,e){e||(e=t,t=window);var r=0,i=0,a=0,o={shift:!1,alt:!1,control:!1,meta:!1},s=!1;function l(t){var e=!1;return"altKey"in t&&(e=e||t.altKey!==o.alt,o.alt=!!t.altKey),"shiftKey"in t&&(e=e||t.shiftKey!==o.shift,o.shift=!!t.shiftKey),"ctrlKey"in t&&(e=e||t.ctrlKey!==o.control,o.control=!!t.ctrlKey),"metaKey"in t&&(e=e||t.metaKey!==o.meta,o.meta=!!t.metaKey),e}function c(t,s){var c=n.x(s),u=n.y(s);"buttons"in s&&(t=0|s.buttons),(t!==r||c!==i||u!==a||l(s))&&(r=0|t,i=c||0,a=u||0,e&&e(r,i,a,o))}function u(t){c(0,t)}function f(){(r||i||a||o.shift||o.alt||o.meta||o.control)&&(i=a=0,r=0,o.shift=o.alt=o.control=o.meta=!1,e&&e(0,0,0,o))}function h(t){l(t)&&e&&e(r,i,a,o)}function p(t){0===n.buttons(t)?c(0,t):c(r,t)}function d(t){c(r|n.buttons(t),t)}function m(t){c(r&~n.buttons(t),t)}function g(){s||(s=!0,t.addEventListener("mousemove",p),t.addEventListener("mousedown",d),t.addEventListener("mouseup",m),t.addEventListener("mouseleave",u),t.addEventListener("mouseenter",u),t.addEventListener("mouseout",u),t.addEventListener("mouseover",u),t.addEventListener("blur",f),t.addEventListener("keyup",h),t.addEventListener("keydown",h),t.addEventListener("keypress",h),t!==window&&(window.addEventListener("blur",f),window.addEventListener("keyup",h),window.addEventListener("keydown",h),window.addEventListener("keypress",h)))}g();var v={element:t};return Object.defineProperties(v,{enabled:{get:function(){return s},set:function(e){e?g():s&&(s=!1,t.removeEventListener("mousemove",p),t.removeEventListener("mousedown",d),t.removeEventListener("mouseup",m),t.removeEventListener("mouseleave",u),t.removeEventListener("mouseenter",u),t.removeEventListener("mouseout",u),t.removeEventListener("mouseover",u),t.removeEventListener("blur",f),t.removeEventListener("keyup",h),t.removeEventListener("keydown",h),t.removeEventListener("keypress",h),t!==window&&(window.removeEventListener("blur",f),window.removeEventListener("keyup",h),window.removeEventListener("keydown",h),window.removeEventListener("keypress",h)))},enumerable:!0},buttons:{get:function(){return r},enumerable:!0},x:{get:function(){return i},enumerable:!0},y:{get:function(){return a},enumerable:!0},mods:{get:function(){return o},enumerable:!0}}),v};var n=t("mouse-event")},{"mouse-event":420}],419:[function(t,e,r){var n={left:0,top:0};e.exports=function(t,e,r){e=e||t.currentTarget||t.srcElement,Array.isArray(r)||(r=[0,0]);var i=t.clientX||0,a=t.clientY||0,o=(s=e,s===window||s===document||s===document.body?n:s.getBoundingClientRect());var s;return r[0]=i-o.left,r[1]=a-o.top,r}},{}],420:[function(t,e,r){"use strict";function n(t){return t.target||t.srcElement||window}r.buttons=function(t){if("object"==typeof t){if("buttons"in t)return t.buttons;if("which"in t){if(2===(e=t.which))return 4;if(3===e)return 2;if(e>0)return 1<=0)return 1< 0");"function"!=typeof t.vertex&&e("Must specify vertex creation function");"function"!=typeof t.cell&&e("Must specify cell creation function");"function"!=typeof t.phase&&e("Must specify phase function");for(var E=t.getters||[],C=new Array(T),L=0;L=0?C[L]=!0:C[L]=!1;return function(t,e,r,T,S,E){var C=E.length,L=S.length;if(L<2)throw new Error("ndarray-extract-contour: Dimension must be at least 2");for(var z="extractContour"+S.join("_"),O=[],I=[],P=[],D=0;D0&&N.push(l(D,S[R-1])+"*"+s(S[R-1])),I.push(d(D,S[R])+"=("+N.join("-")+")|0")}for(var D=0;D=0;--D)j.push(s(S[D]));I.push(w+"=("+j.join("*")+")|0",b+"=mallocUint32("+w+")",x+"=mallocUint32("+w+")",k+"=0"),I.push(m(0)+"=0");for(var R=1;R<1<0;M=M-1&d)w.push(x+"["+k+"+"+v(M)+"]");w.push(y(0));for(var M=0;M=0;--e)G(e,0);for(var r=[],e=0;e0){",p(S[e]),"=1;");t(e-1,r|1<=0?s.push("0"):e.indexOf(-(l+1))>=0?s.push("s["+l+"]-1"):(s.push("-1"),a.push("1"),o.push("s["+l+"]-2"));var c=".lo("+a.join()+").hi("+o.join()+")";if(0===a.length&&(c=""),i>0){n.push("if(1");for(var l=0;l=0||e.indexOf(-(l+1))>=0||n.push("&&s[",l,"]>2");n.push("){grad",i,"(src.pick(",s.join(),")",c);for(var l=0;l=0||e.indexOf(-(l+1))>=0||n.push(",dst.pick(",s.join(),",",l,")",c);n.push(");")}for(var l=0;l1){dst.set(",s.join(),",",u,",0.5*(src.get(",h.join(),")-src.get(",p.join(),")))}else{dst.set(",s.join(),",",u,",0)};"):n.push("if(s[",u,"]>1){diff(",f,",src.pick(",h.join(),")",c,",src.pick(",p.join(),")",c,");}else{zero(",f,");};");break;case"mirror":0===i?n.push("dst.set(",s.join(),",",u,",0);"):n.push("zero(",f,");");break;case"wrap":var d=s.slice(),m=s.slice();e[l]<0?(d[u]="s["+u+"]-2",m[u]="0"):(d[u]="s["+u+"]-1",m[u]="1"),0===i?n.push("if(s[",u,"]>2){dst.set(",s.join(),",",u,",0.5*(src.get(",d.join(),")-src.get(",m.join(),")))}else{dst.set(",s.join(),",",u,",0)};"):n.push("if(s[",u,"]>2){diff(",f,",src.pick(",d.join(),")",c,",src.pick(",m.join(),")",c,");}else{zero(",f,");};");break;default:throw new Error("ndarray-gradient: Invalid boundary condition")}}i>0&&n.push("};")}for(var s=0;s<1<>",rrshift:">>>"};!function(){for(var t in s){var e=s[t];r[t]=o({args:["array","array","array"],body:{args:["a","b","c"],body:"a=b"+e+"c"},funcName:t}),r[t+"eq"]=o({args:["array","array"],body:{args:["a","b"],body:"a"+e+"=b"},rvalue:!0,funcName:t+"eq"}),r[t+"s"]=o({args:["array","array","scalar"],body:{args:["a","b","s"],body:"a=b"+e+"s"},funcName:t+"s"}),r[t+"seq"]=o({args:["array","scalar"],body:{args:["a","s"],body:"a"+e+"=s"},rvalue:!0,funcName:t+"seq"})}}();var l={not:"!",bnot:"~",neg:"-",recip:"1.0/"};!function(){for(var t in l){var e=l[t];r[t]=o({args:["array","array"],body:{args:["a","b"],body:"a="+e+"b"},funcName:t}),r[t+"eq"]=o({args:["array"],body:{args:["a"],body:"a="+e+"a"},rvalue:!0,count:2,funcName:t+"eq"})}}();var c={and:"&&",or:"||",eq:"===",neq:"!==",lt:"<",gt:">",leq:"<=",geq:">="};!function(){for(var t in c){var e=c[t];r[t]=o({args:["array","array","array"],body:{args:["a","b","c"],body:"a=b"+e+"c"},funcName:t}),r[t+"s"]=o({args:["array","array","scalar"],body:{args:["a","b","s"],body:"a=b"+e+"s"},funcName:t+"s"}),r[t+"eq"]=o({args:["array","array"],body:{args:["a","b"],body:"a=a"+e+"b"},rvalue:!0,count:2,funcName:t+"eq"}),r[t+"seq"]=o({args:["array","scalar"],body:{args:["a","s"],body:"a=a"+e+"s"},rvalue:!0,count:2,funcName:t+"seq"})}}();var u=["abs","acos","asin","atan","ceil","cos","exp","floor","log","round","sin","sqrt","tan"];!function(){for(var t=0;tthis_s){this_s=-a}else if(a>this_s){this_s=a}",localVars:[],thisVars:["this_s"]},post:{args:[],localVars:[],thisVars:["this_s"],body:"return this_s"},funcName:"norminf"}),r.norm1=n({args:["array"],pre:{args:[],localVars:[],thisVars:["this_s"],body:"this_s=0"},body:{args:[{name:"a",lvalue:!1,rvalue:!0,count:3}],body:"this_s+=a<0?-a:a",localVars:[],thisVars:["this_s"]},post:{args:[],localVars:[],thisVars:["this_s"],body:"return this_s"},funcName:"norm1"}),r.sup=n({args:["array"],pre:{body:"this_h=-Infinity",args:[],thisVars:["this_h"],localVars:[]},body:{body:"if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_",args:[{name:"_inline_1_arg0_",lvalue:!1,rvalue:!0,count:2}],thisVars:["this_h"],localVars:[]},post:{body:"return this_h",args:[],thisVars:["this_h"],localVars:[]}}),r.inf=n({args:["array"],pre:{body:"this_h=Infinity",args:[],thisVars:["this_h"],localVars:[]},body:{body:"if(_inline_1_arg0_this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",args:[{name:"_inline_1_arg0_",lvalue:!1,rvalue:!0,count:2},{name:"_inline_1_arg1_",lvalue:!1,rvalue:!0,count:2}],thisVars:["this_i","this_v"],localVars:["_inline_1_k"]},post:{body:"{return this_i}",args:[],thisVars:["this_i"],localVars:[]}}),r.random=o({args:["array"],pre:{args:[],body:"this_f=Math.random",thisVars:["this_f"]},body:{args:["a"],body:"a=this_f()",thisVars:["this_f"]},funcName:"random"}),r.assign=o({args:["array","array"],body:{args:["a","b"],body:"a=b"},funcName:"assign"}),r.assigns=o({args:["array","scalar"],body:{args:["a","b"],body:"a=b"},funcName:"assigns"}),r.equals=n({args:["array","array"],pre:i,body:{args:[{name:"x",lvalue:!1,rvalue:!0,count:1},{name:"y",lvalue:!1,rvalue:!0,count:1}],body:"if(x!==y){return false}",localVars:[],thisVars:[]},post:{args:[],localVars:[],thisVars:[],body:"return true"},funcName:"equals"})},{"cwise-compiler":134}],428:[function(t,e,r){"use strict";var n=t("ndarray"),i=t("./doConvert.js");e.exports=function(t,e){for(var r=[],a=t,o=1;Array.isArray(a);)r.push(a.length),o*=a.length,a=a[0];return 0===r.length?n():(e||(e=n(new Float64Array(o),r)),i(e,t),e)}},{"./doConvert.js":429,ndarray:433}],429:[function(t,e,r){e.exports=t("cwise-compiler")({args:["array","scalar","index"],pre:{body:"{}",args:[],thisVars:[],localVars:[]},body:{body:"{\nvar _inline_1_v=_inline_1_arg1_,_inline_1_i\nfor(_inline_1_i=0;_inline_1_i<_inline_1_arg2_.length-1;++_inline_1_i) {\n_inline_1_v=_inline_1_v[_inline_1_arg2_[_inline_1_i]]\n}\n_inline_1_arg0_=_inline_1_v[_inline_1_arg2_[_inline_1_arg2_.length-1]]\n}",args:[{name:"_inline_1_arg0_",lvalue:!0,rvalue:!1,count:1},{name:"_inline_1_arg1_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_1_arg2_",lvalue:!1,rvalue:!0,count:4}],thisVars:[],localVars:["_inline_1_i","_inline_1_v"]},post:{body:"{}",args:[],thisVars:[],localVars:[]},funcName:"convert",blockSize:64})},{"cwise-compiler":134}],430:[function(t,e,r){"use strict";var n=t("typedarray-pool"),i=32;function a(t){switch(t){case"uint8":return[n.mallocUint8,n.freeUint8];case"uint16":return[n.mallocUint16,n.freeUint16];case"uint32":return[n.mallocUint32,n.freeUint32];case"int8":return[n.mallocInt8,n.freeInt8];case"int16":return[n.mallocInt16,n.freeInt16];case"int32":return[n.mallocInt32,n.freeInt32];case"float32":return[n.mallocFloat,n.freeFloat];case"float64":return[n.mallocDouble,n.freeDouble];default:return null}}function o(t){for(var e=[],r=0;r0?s.push(["d",d,"=s",d,"-d",f,"*n",f].join("")):s.push(["d",d,"=s",d].join("")),f=d),0!=(p=t.length-1-l)&&(h>0?s.push(["e",p,"=s",p,"-e",h,"*n",h,",f",p,"=",c[p],"-f",h,"*n",h].join("")):s.push(["e",p,"=s",p,",f",p,"=",c[p]].join("")),h=p)}r.push("var "+s.join(","));var m=["0","n0-1","data","offset"].concat(o(t.length));r.push(["if(n0<=",i,"){","insertionSort(",m.join(","),")}else{","quickSort(",m.join(","),")}"].join("")),r.push("}return "+n);var g=new Function("insertionSort","quickSort",r.join("\n")),v=function(t,e){var r=["'use strict'"],n=["ndarrayInsertionSort",t.join("d"),e].join(""),i=["left","right","data","offset"].concat(o(t.length)),s=a(e),l=["i,j,cptr,ptr=left*s0+offset"];if(t.length>1){for(var c=[],u=1;u1){for(r.push("dptr=0;sptr=ptr"),u=t.length-1;u>=0;--u)0!==(p=t[u])&&r.push(["for(i",p,"=0;i",p,"b){break __l}"].join("")),u=t.length-1;u>=1;--u)r.push("sptr+=e"+u,"dptr+=f"+u,"}");for(r.push("dptr=cptr;sptr=cptr-s0"),u=t.length-1;u>=0;--u)0!==(p=t[u])&&r.push(["for(i",p,"=0;i",p,"=0;--u)0!==(p=t[u])&&r.push(["for(i",p,"=0;i",p,"scratch)){",h("cptr",f("cptr-s0")),"cptr-=s0","}",h("cptr","scratch"));return r.push("}"),t.length>1&&s&&r.push("free(scratch)"),r.push("} return "+n),s?new Function("malloc","free",r.join("\n"))(s[0],s[1]):new Function(r.join("\n"))()}(t,e),y=function(t,e,r){var n=["'use strict'"],s=["ndarrayQuickSort",t.join("d"),e].join(""),l=["left","right","data","offset"].concat(o(t.length)),c=a(e),u=0;n.push(["function ",s,"(",l.join(","),"){"].join(""));var f=["sixth=((right-left+1)/6)|0","index1=left+sixth","index5=right-sixth","index3=(left+right)>>1","index2=index3-sixth","index4=index3+sixth","el1=index1","el2=index2","el3=index3","el4=index4","el5=index5","less=left+1","great=right-1","pivots_are_equal=true","tmp","tmp0","x","y","z","k","ptr0","ptr1","ptr2","comp_pivot1=0","comp_pivot2=0","comp=0"];if(t.length>1){for(var h=[],p=1;p=0;--a)0!==(o=t[a])&&n.push(["for(i",o,"=0;i",o,"1)for(a=0;a1?n.push("ptr_shift+=d"+o):n.push("ptr0+=d"+o),n.push("}"))}}function y(e,r,i,a){if(1===r.length)n.push("ptr0="+d(r[0]));else{for(var o=0;o1)for(o=0;o=1;--o)i&&n.push("pivot_ptr+=f"+o),r.length>1?n.push("ptr_shift+=e"+o):n.push("ptr0+=e"+o),n.push("}")}function x(){t.length>1&&c&&n.push("free(pivot1)","free(pivot2)")}function b(e,r){var i="el"+e,a="el"+r;if(t.length>1){var o="__l"+ ++u;y(o,[i,a],!1,["comp=",m("ptr0"),"-",m("ptr1"),"\n","if(comp>0){tmp0=",i,";",i,"=",a,";",a,"=tmp0;break ",o,"}\n","if(comp<0){break ",o,"}"].join(""))}else n.push(["if(",m(d(i)),">",m(d(a)),"){tmp0=",i,";",i,"=",a,";",a,"=tmp0}"].join(""))}function _(e,r){t.length>1?v([e,r],!1,g("ptr0",m("ptr1"))):n.push(g(d(e),m(d(r))))}function w(e,r,i){if(t.length>1){var a="__l"+ ++u;y(a,[r],!0,[e,"=",m("ptr0"),"-pivot",i,"[pivot_ptr]\n","if(",e,"!==0){break ",a,"}"].join(""))}else n.push([e,"=",m(d(r)),"-pivot",i].join(""))}function k(e,r){t.length>1?v([e,r],!1,["tmp=",m("ptr0"),"\n",g("ptr0",m("ptr1")),"\n",g("ptr1","tmp")].join("")):n.push(["ptr0=",d(e),"\n","ptr1=",d(r),"\n","tmp=",m("ptr0"),"\n",g("ptr0",m("ptr1")),"\n",g("ptr1","tmp")].join(""))}function M(e,r,i){t.length>1?(v([e,r,i],!1,["tmp=",m("ptr0"),"\n",g("ptr0",m("ptr1")),"\n",g("ptr1",m("ptr2")),"\n",g("ptr2","tmp")].join("")),n.push("++"+r,"--"+i)):n.push(["ptr0=",d(e),"\n","ptr1=",d(r),"\n","ptr2=",d(i),"\n","++",r,"\n","--",i,"\n","tmp=",m("ptr0"),"\n",g("ptr0",m("ptr1")),"\n",g("ptr1",m("ptr2")),"\n",g("ptr2","tmp")].join(""))}function A(t,e){k(t,e),n.push("--"+e)}function T(e,r,i){t.length>1?v([e,r],!0,[g("ptr0",m("ptr1")),"\n",g("ptr1",["pivot",i,"[pivot_ptr]"].join(""))].join("")):n.push(g(d(e),m(d(r))),g(d(r),"pivot"+i))}function S(e,r){n.push(["if((",r,"-",e,")<=",i,"){\n","insertionSort(",e,",",r,",data,offset,",o(t.length).join(","),")\n","}else{\n",s,"(",e,",",r,",data,offset,",o(t.length).join(","),")\n","}"].join(""))}function E(e,r,i){t.length>1?(n.push(["__l",++u,":while(true){"].join("")),v([e],!0,["if(",m("ptr0"),"!==pivot",r,"[pivot_ptr]){break __l",u,"}"].join("")),n.push(i,"}")):n.push(["while(",m(d(e)),"===pivot",r,"){",i,"}"].join(""))}return n.push("var "+f.join(",")),b(1,2),b(4,5),b(1,3),b(2,3),b(1,4),b(3,4),b(2,5),b(2,3),b(4,5),t.length>1?v(["el1","el2","el3","el4","el5","index1","index3","index5"],!0,["pivot1[pivot_ptr]=",m("ptr1"),"\n","pivot2[pivot_ptr]=",m("ptr3"),"\n","pivots_are_equal=pivots_are_equal&&(pivot1[pivot_ptr]===pivot2[pivot_ptr])\n","x=",m("ptr0"),"\n","y=",m("ptr2"),"\n","z=",m("ptr4"),"\n",g("ptr5","x"),"\n",g("ptr6","y"),"\n",g("ptr7","z")].join("")):n.push(["pivot1=",m(d("el2")),"\n","pivot2=",m(d("el4")),"\n","pivots_are_equal=pivot1===pivot2\n","x=",m(d("el1")),"\n","y=",m(d("el3")),"\n","z=",m(d("el5")),"\n",g(d("index1"),"x"),"\n",g(d("index3"),"y"),"\n",g(d("index5"),"z")].join("")),_("index2","left"),_("index4","right"),n.push("if(pivots_are_equal){"),n.push("for(k=less;k<=great;++k){"),w("comp","k",1),n.push("if(comp===0){continue}"),n.push("if(comp<0){"),n.push("if(k!==less){"),k("k","less"),n.push("}"),n.push("++less"),n.push("}else{"),n.push("while(true){"),w("comp","great",1),n.push("if(comp>0){"),n.push("great--"),n.push("}else if(comp<0){"),M("k","less","great"),n.push("break"),n.push("}else{"),A("k","great"),n.push("break"),n.push("}"),n.push("}"),n.push("}"),n.push("}"),n.push("}else{"),n.push("for(k=less;k<=great;++k){"),w("comp_pivot1","k",1),n.push("if(comp_pivot1<0){"),n.push("if(k!==less){"),k("k","less"),n.push("}"),n.push("++less"),n.push("}else{"),w("comp_pivot2","k",2),n.push("if(comp_pivot2>0){"),n.push("while(true){"),w("comp","great",2),n.push("if(comp>0){"),n.push("if(--greatindex5){"),E("less",1,"++less"),E("great",2,"--great"),n.push("for(k=less;k<=great;++k){"),w("comp_pivot1","k",1),n.push("if(comp_pivot1===0){"),n.push("if(k!==less){"),k("k","less"),n.push("}"),n.push("++less"),n.push("}else{"),w("comp_pivot2","k",2),n.push("if(comp_pivot2===0){"),n.push("while(true){"),w("comp","great",2),n.push("if(comp===0){"),n.push("if(--great1&&c?new Function("insertionSort","malloc","free",n.join("\n"))(r,c[0],c[1]):new Function("insertionSort",n.join("\n"))(r)}(t,e,v);return g(v,y)}},{"typedarray-pool":522}],431:[function(t,e,r){"use strict";var n=t("./lib/compile_sort.js"),i={};e.exports=function(t){var e=t.order,r=t.dtype,a=[e,r].join(":"),o=i[a];return o||(i[a]=o=n(e,r)),o(t),t}},{"./lib/compile_sort.js":430}],432:[function(t,e,r){"use strict";var n=t("ndarray-linear-interpolate"),i=t("cwise/lib/wrapper")({args:["index","array","scalar","scalar","scalar"],pre:{body:"{this_warped=new Array(_inline_3_arg4_)}",args:[{name:"_inline_3_arg0_",lvalue:!1,rvalue:!1,count:0},{name:"_inline_3_arg1_",lvalue:!1,rvalue:!1,count:0},{name:"_inline_3_arg2_",lvalue:!1,rvalue:!1,count:0},{name:"_inline_3_arg3_",lvalue:!1,rvalue:!1,count:0},{name:"_inline_3_arg4_",lvalue:!1,rvalue:!0,count:1}],thisVars:["this_warped"],localVars:[]},body:{body:"{_inline_4_arg2_(this_warped,_inline_4_arg0_),_inline_4_arg1_=_inline_4_arg3_.apply(void 0,this_warped)}",args:[{name:"_inline_4_arg0_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_4_arg1_",lvalue:!0,rvalue:!1,count:1},{name:"_inline_4_arg2_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_4_arg3_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_4_arg4_",lvalue:!1,rvalue:!1,count:0}],thisVars:["this_warped"],localVars:[]},post:{body:"{}",args:[],thisVars:[],localVars:[]},debug:!1,funcName:"warpND",blockSize:64}),a=t("cwise/lib/wrapper")({args:["index","array","scalar","scalar","scalar"],pre:{body:"{this_warped=[0]}",args:[],thisVars:["this_warped"],localVars:[]},body:{body:"{_inline_7_arg2_(this_warped,_inline_7_arg0_),_inline_7_arg1_=_inline_7_arg3_(_inline_7_arg4_,this_warped[0])}",args:[{name:"_inline_7_arg0_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_7_arg1_",lvalue:!0,rvalue:!1,count:1},{name:"_inline_7_arg2_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_7_arg3_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_7_arg4_",lvalue:!1,rvalue:!0,count:1}],thisVars:["this_warped"],localVars:[]},post:{body:"{}",args:[],thisVars:[],localVars:[]},debug:!1,funcName:"warp1D",blockSize:64}),o=t("cwise/lib/wrapper")({args:["index","array","scalar","scalar","scalar"],pre:{body:"{this_warped=[0,0]}",args:[],thisVars:["this_warped"],localVars:[]},body:{body:"{_inline_10_arg2_(this_warped,_inline_10_arg0_),_inline_10_arg1_=_inline_10_arg3_(_inline_10_arg4_,this_warped[0],this_warped[1])}",args:[{name:"_inline_10_arg0_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_10_arg1_",lvalue:!0,rvalue:!1,count:1},{name:"_inline_10_arg2_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_10_arg3_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_10_arg4_",lvalue:!1,rvalue:!0,count:1}],thisVars:["this_warped"],localVars:[]},post:{body:"{}",args:[],thisVars:[],localVars:[]},debug:!1,funcName:"warp2D",blockSize:64}),s=t("cwise/lib/wrapper")({args:["index","array","scalar","scalar","scalar"],pre:{body:"{this_warped=[0,0,0]}",args:[],thisVars:["this_warped"],localVars:[]},body:{body:"{_inline_13_arg2_(this_warped,_inline_13_arg0_),_inline_13_arg1_=_inline_13_arg3_(_inline_13_arg4_,this_warped[0],this_warped[1],this_warped[2])}",args:[{name:"_inline_13_arg0_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_13_arg1_",lvalue:!0,rvalue:!1,count:1},{name:"_inline_13_arg2_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_13_arg3_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_13_arg4_",lvalue:!1,rvalue:!0,count:1}],thisVars:["this_warped"],localVars:[]},post:{body:"{}",args:[],thisVars:[],localVars:[]},debug:!1,funcName:"warp3D",blockSize:64});e.exports=function(t,e,r){switch(e.shape.length){case 1:a(t,r,n.d1,e);break;case 2:o(t,r,n.d2,e);break;case 3:s(t,r,n.d3,e);break;default:i(t,r,n.bind(void 0,e),e.shape.length)}return t}},{"cwise/lib/wrapper":137,"ndarray-linear-interpolate":426}],433:[function(t,e,r){var n=t("iota-array"),i=t("is-buffer"),a="undefined"!=typeof Float64Array;function o(t,e){return t[0]-e[0]}function s(){var t,e=this.stride,r=new Array(e.length);for(t=0;tMath.abs(this.stride[1]))?[1,0]:[0,1]}})"):3===e&&a.push("var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);if(s0>s1){if(s1>s2){return [2,1,0];}else if(s0>s2){return [1,2,0];}else{return [1,0,2];}}else if(s0>s2){return [2,0,1];}else if(s2>s1){return [0,1,2];}else{return [0,2,1];}}})")):a.push("ORDER})")),a.push("proto.set=function "+r+"_set("+l.join(",")+",v){"),i?a.push("return this.data.set("+u+",v)}"):a.push("return this.data["+u+"]=v}"),a.push("proto.get=function "+r+"_get("+l.join(",")+"){"),i?a.push("return this.data.get("+u+")}"):a.push("return this.data["+u+"]}"),a.push("proto.index=function "+r+"_index(",l.join(),"){return "+u+"}"),a.push("proto.hi=function "+r+"_hi("+l.join(",")+"){return new "+r+"(this.data,"+o.map(function(t){return["(typeof i",t,"!=='number'||i",t,"<0)?this.shape[",t,"]:i",t,"|0"].join("")}).join(",")+","+o.map(function(t){return"this.stride["+t+"]"}).join(",")+",this.offset)}");var p=o.map(function(t){return"a"+t+"=this.shape["+t+"]"}),d=o.map(function(t){return"c"+t+"=this.stride["+t+"]"});a.push("proto.lo=function "+r+"_lo("+l.join(",")+"){var b=this.offset,d=0,"+p.join(",")+","+d.join(","));for(var m=0;m=0){d=i"+m+"|0;b+=c"+m+"*d;a"+m+"-=d}");a.push("return new "+r+"(this.data,"+o.map(function(t){return"a"+t}).join(",")+","+o.map(function(t){return"c"+t}).join(",")+",b)}"),a.push("proto.step=function "+r+"_step("+l.join(",")+"){var "+o.map(function(t){return"a"+t+"=this.shape["+t+"]"}).join(",")+","+o.map(function(t){return"b"+t+"=this.stride["+t+"]"}).join(",")+",c=this.offset,d=0,ceil=Math.ceil");for(m=0;m=0){c=(c+this.stride["+m+"]*i"+m+")|0}else{a.push(this.shape["+m+"]);b.push(this.stride["+m+"])}");return a.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}"),a.push("return function construct_"+r+"(data,shape,stride,offset){return new "+r+"(data,"+o.map(function(t){return"shape["+t+"]"}).join(",")+","+o.map(function(t){return"stride["+t+"]"}).join(",")+",offset)}"),new Function("CTOR_LIST","ORDER",a.join("\n"))(c[t],s)}var c={float32:[],float64:[],int8:[],int16:[],int32:[],uint8:[],uint16:[],uint32:[],array:[],uint8_clamped:[],buffer:[],generic:[]};e.exports=function(t,e,r,n){if(void 0===t)return(0,c.array[0])([]);"number"==typeof t&&(t=[t]),void 0===e&&(e=[t.length]);var o=e.length;if(void 0===r){r=new Array(o);for(var s=o-1,u=1;s>=0;--s)r[s]=u,u*=e[s]}if(void 0===n)for(n=0,s=0;s>>0;e.exports=function(t,e){if(isNaN(t)||isNaN(e))return NaN;if(t===e)return t;if(0===t)return e<0?-i:i;var r=n.hi(t),o=n.lo(t);e>t==t>0?o===a?(r+=1,o=0):o+=1:0===o?(o=a,r-=1):o-=1;return n.pack(o,r)}},{"double-bits":152}],435:[function(t,e,r){var n=Math.PI,i=c(120);function a(t,e,r,n){return["C",t,e,r,n,r,n]}function o(t,e,r,n,i,a){return["C",t/3+2/3*r,e/3+2/3*n,i/3+2/3*r,a/3+2/3*n,i,a]}function s(t,e,r,a,o,c,u,f,h,p){if(p)k=p[0],M=p[1],_=p[2],w=p[3];else{var d=l(t,e,-o);t=d.x,e=d.y;var m=(t-(f=(d=l(f,h,-o)).x))/2,g=(e-(h=d.y))/2,v=m*m/(r*r)+g*g/(a*a);v>1&&(r*=v=Math.sqrt(v),a*=v);var y=r*r,x=a*a,b=(c==u?-1:1)*Math.sqrt(Math.abs((y*x-y*g*g-x*m*m)/(y*g*g+x*m*m)));b==1/0&&(b=1);var _=b*r*g/a+(t+f)/2,w=b*-a*m/r+(e+h)/2,k=Math.asin(((e-w)/a).toFixed(9)),M=Math.asin(((h-w)/a).toFixed(9));(k=t<_?n-k:k)<0&&(k=2*n+k),(M=f<_?n-M:M)<0&&(M=2*n+M),u&&k>M&&(k-=2*n),!u&&M>k&&(M-=2*n)}if(Math.abs(M-k)>i){var A=M,T=f,S=h;M=k+i*(u&&M>k?1:-1);var E=s(f=_+r*Math.cos(M),h=w+a*Math.sin(M),r,a,o,0,u,T,S,[M,A,_,w])}var C=Math.tan((M-k)/4),L=4/3*r*C,z=4/3*a*C,O=[2*t-(t+L*Math.sin(k)),2*e-(e-z*Math.cos(k)),f+L*Math.sin(M),h-z*Math.cos(M),f,h];if(p)return O;E&&(O=O.concat(E));for(var I=0;I7&&(r.push(v.splice(0,7)),v.unshift("C"));break;case"S":var x=p,b=d;"C"!=e&&"S"!=e||(x+=x-n,b+=b-i),v=["C",x,b,v[1],v[2],v[3],v[4]];break;case"T":"Q"==e||"T"==e?(f=2*p-f,h=2*d-h):(f=p,h=d),v=o(p,d,f,h,v[1],v[2]);break;case"Q":f=v[1],h=v[2],v=o(p,d,v[1],v[2],v[3],v[4]);break;case"L":v=a(p,d,v[1],v[2]);break;case"H":v=a(p,d,v[1],d);break;case"V":v=a(p,d,p,v[1]);break;case"Z":v=a(p,d,l,u)}e=y,p=v[v.length-2],d=v[v.length-1],v.length>4?(n=v[v.length-4],i=v[v.length-3]):(n=p,i=d),r.push(v)}return r}},{}],436:[function(t,e,r){r.vertexNormals=function(t,e,r){for(var n=e.length,i=new Array(n),a=void 0===r?1e-6:r,o=0;oa){var b=i[c],_=1/Math.sqrt(g*y);for(x=0;x<3;++x){var w=(x+1)%3,k=(x+2)%3;b[x]+=_*(v[w]*m[k]-v[k]*m[w])}}}for(o=0;oa)for(_=1/Math.sqrt(M),x=0;x<3;++x)b[x]*=_;else for(x=0;x<3;++x)b[x]=0}return i},r.faceNormals=function(t,e,r){for(var n=t.length,i=new Array(n),a=void 0===r?1e-6:r,o=0;oa?1/Math.sqrt(p):0;for(c=0;c<3;++c)h[c]*=p;i[o]=h}return i}},{}],437:[function(t,e,r){"use strict";var n=Object.getOwnPropertySymbols,i=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},r=0;r<10;r++)e["_"+String.fromCharCode(r)]=r;if("0123456789"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach(function(t){n[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(t){return!1}}()?Object.assign:function(t,e){for(var r,o,s=function(t){if(null==t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}(t),l=1;l0){var f=Math.sqrt(u+1);t[0]=.5*(o-l)/f,t[1]=.5*(s-n)/f,t[2]=.5*(r-a)/f,t[3]=.5*f}else{var h=Math.max(e,a,c),f=Math.sqrt(2*h-u+1);e>=h?(t[0]=.5*f,t[1]=.5*(i+r)/f,t[2]=.5*(s+n)/f,t[3]=.5*(o-l)/f):a>=h?(t[0]=.5*(r+i)/f,t[1]=.5*f,t[2]=.5*(l+o)/f,t[3]=.5*(s-n)/f):(t[0]=.5*(n+s)/f,t[1]=.5*(o+l)/f,t[2]=.5*f,t[3]=.5*(r-i)/f)}return t}},{}],439:[function(t,e,r){"use strict";e.exports=function(t){var e=(t=t||{}).center||[0,0,0],r=t.rotation||[0,0,0,1],n=t.radius||1;e=[].slice.call(e,0,3),u(r=[].slice.call(r,0,4),r);var i=new f(r,e,Math.log(n));i.setDistanceLimits(t.zoomMin,t.zoomMax),("eye"in t||"up"in t)&&i.lookAt(0,t.eye,t.center,t.up);return i};var n=t("filtered-vector"),i=t("gl-mat4/lookAt"),a=t("gl-mat4/fromQuat"),o=t("gl-mat4/invert"),s=t("./lib/quatFromFrame");function l(t,e,r){return Math.sqrt(Math.pow(t,2)+Math.pow(e,2)+Math.pow(r,2))}function c(t,e,r,n){return Math.sqrt(Math.pow(t,2)+Math.pow(e,2)+Math.pow(r,2)+Math.pow(n,2))}function u(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=c(r,n,i,a);o>1e-6?(t[0]=r/o,t[1]=n/o,t[2]=i/o,t[3]=a/o):(t[0]=t[1]=t[2]=0,t[3]=1)}function f(t,e,r){this.radius=n([r]),this.center=n(e),this.rotation=n(t),this.computedRadius=this.radius.curve(0),this.computedCenter=this.center.curve(0),this.computedRotation=this.rotation.curve(0),this.computedUp=[.1,0,0],this.computedEye=[.1,0,0],this.computedMatrix=[.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],this.recalcMatrix(0)}var h=f.prototype;h.lastT=function(){return Math.max(this.radius.lastT(),this.center.lastT(),this.rotation.lastT())},h.recalcMatrix=function(t){this.radius.curve(t),this.center.curve(t),this.rotation.curve(t);var e=this.computedRotation;u(e,e);var r=this.computedMatrix;a(r,e);var n=this.computedCenter,i=this.computedEye,o=this.computedUp,s=Math.exp(this.computedRadius[0]);i[0]=n[0]+s*r[2],i[1]=n[1]+s*r[6],i[2]=n[2]+s*r[10],o[0]=r[1],o[1]=r[5],o[2]=r[9];for(var l=0;l<3;++l){for(var c=0,f=0;f<3;++f)c+=r[l+4*f]*i[f];r[12+l]=-c}},h.getMatrix=function(t,e){this.recalcMatrix(t);var r=this.computedMatrix;if(e){for(var n=0;n<16;++n)e[n]=r[n];return e}return r},h.idle=function(t){this.center.idle(t),this.radius.idle(t),this.rotation.idle(t)},h.flush=function(t){this.center.flush(t),this.radius.flush(t),this.rotation.flush(t)},h.pan=function(t,e,r,n){e=e||0,r=r||0,n=n||0,this.recalcMatrix(t);var i=this.computedMatrix,a=i[1],o=i[5],s=i[9],c=l(a,o,s);a/=c,o/=c,s/=c;var u=i[0],f=i[4],h=i[8],p=u*a+f*o+h*s,d=l(u-=a*p,f-=o*p,h-=s*p);u/=d,f/=d,h/=d;var m=i[2],g=i[6],v=i[10],y=m*a+g*o+v*s,x=m*u+g*f+v*h,b=l(m-=y*a+x*u,g-=y*o+x*f,v-=y*s+x*h);m/=b,g/=b,v/=b;var _=u*e+a*r,w=f*e+o*r,k=h*e+s*r;this.center.move(t,_,w,k);var M=Math.exp(this.computedRadius[0]);M=Math.max(1e-4,M+n),this.radius.set(t,Math.log(M))},h.rotate=function(t,e,r,n){this.recalcMatrix(t),e=e||0,r=r||0;var i=this.computedMatrix,a=i[0],o=i[4],s=i[8],u=i[1],f=i[5],h=i[9],p=i[2],d=i[6],m=i[10],g=e*a+r*u,v=e*o+r*f,y=e*s+r*h,x=-(d*y-m*v),b=-(m*g-p*y),_=-(p*v-d*g),w=Math.sqrt(Math.max(0,1-Math.pow(x,2)-Math.pow(b,2)-Math.pow(_,2))),k=c(x,b,_,w);k>1e-6?(x/=k,b/=k,_/=k,w/=k):(x=b=_=0,w=1);var M=this.computedRotation,A=M[0],T=M[1],S=M[2],E=M[3],C=A*w+E*x+T*_-S*b,L=T*w+E*b+S*x-A*_,z=S*w+E*_+A*b-T*x,O=E*w-A*x-T*b-S*_;if(n){x=p,b=d,_=m;var I=Math.sin(n)/l(x,b,_);x*=I,b*=I,_*=I,O=O*(w=Math.cos(e))-(C=C*w+O*x+L*_-z*b)*x-(L=L*w+O*b+z*x-C*_)*b-(z=z*w+O*_+C*b-L*x)*_}var P=c(C,L,z,O);P>1e-6?(C/=P,L/=P,z/=P,O/=P):(C=L=z=0,O=1),this.rotation.set(t,C,L,z,O)},h.lookAt=function(t,e,r,n){this.recalcMatrix(t),r=r||this.computedCenter,e=e||this.computedEye,n=n||this.computedUp;var a=this.computedMatrix;i(a,e,r,n);var o=this.computedRotation;s(o,a[0],a[1],a[2],a[4],a[5],a[6],a[8],a[9],a[10]),u(o,o),this.rotation.set(t,o[0],o[1],o[2],o[3]);for(var l=0,c=0;c<3;++c)l+=Math.pow(r[c]-e[c],2);this.radius.set(t,.5*Math.log(Math.max(l,1e-6))),this.center.set(t,r[0],r[1],r[2])},h.translate=function(t,e,r,n){this.center.move(t,e||0,r||0,n||0)},h.setMatrix=function(t,e){var r=this.computedRotation;s(r,e[0],e[1],e[2],e[4],e[5],e[6],e[8],e[9],e[10]),u(r,r),this.rotation.set(t,r[0],r[1],r[2],r[3]);var n=this.computedMatrix;o(n,e);var i=n[15];if(Math.abs(i)>1e-6){var a=n[12]/i,l=n[13]/i,c=n[14]/i;this.recalcMatrix(t);var f=Math.exp(this.computedRadius[0]);this.center.set(t,a-n[2]*f,l-n[6]*f,c-n[10]*f),this.radius.idle(t)}else this.center.idle(t),this.radius.idle(t)},h.setDistance=function(t,e){e>0&&this.radius.set(t,Math.log(e))},h.setDistanceLimits=function(t,e){t=t>0?Math.log(t):-1/0,e=e>0?Math.log(e):1/0,e=Math.max(e,t),this.radius.bounds[0][0]=t,this.radius.bounds[1][0]=e},h.getDistanceLimits=function(t){var e=this.radius.bounds;return t?(t[0]=Math.exp(e[0][0]),t[1]=Math.exp(e[1][0]),t):[Math.exp(e[0][0]),Math.exp(e[1][0])]},h.toJSON=function(){return this.recalcMatrix(this.lastT()),{center:this.computedCenter.slice(),rotation:this.computedRotation.slice(),distance:Math.log(this.computedRadius[0]),zoomMin:this.radius.bounds[0][0],zoomMax:this.radius.bounds[1][0]}},h.fromJSON=function(t){var e=this.lastT(),r=t.center;r&&this.center.set(e,r[0],r[1],r[2]);var n=t.rotation;n&&this.rotation.set(e,n[0],n[1],n[2],n[3]);var i=t.distance;i&&i>0&&this.radius.set(e,Math.log(i)),this.setDistanceLimits(t.zoomMin,t.zoomMax)}},{"./lib/quatFromFrame":438,"filtered-vector":215,"gl-mat4/fromQuat":251,"gl-mat4/invert":254,"gl-mat4/lookAt":255}],440:[function(t,e,r){"use strict";var n=t("repeat-string");e.exports=function(t,e,r){return n(r="undefined"!=typeof r?r+"":" ",e)+t}},{"repeat-string":479}],441:[function(t,e,r){"use strict";function n(t,e){if("string"!=typeof t)return[t];var r=[t];"string"==typeof e||Array.isArray(e)?e={brackets:e}:e||(e={});var n=e.brackets?Array.isArray(e.brackets)?e.brackets:[e.brackets]:["{}","[]","()"],i=e.escape||"___",a=!!e.flat;n.forEach(function(t){var e=new RegExp(["\\",t[0],"[^\\",t[0],"\\",t[1],"]*\\",t[1]].join("")),n=[];function a(e,a,o){var s=r.push(e.slice(t[0].length,-t[1].length))-1;return n.push(s),i+s}r.forEach(function(t,n){for(var i,o=0;t!=i;)if(i=t,t=t.replace(e,a),o++>1e4)throw Error("References have circular dependency. Please, check them.");r[n]=t}),n=n.reverse(),r=r.map(function(e){return n.forEach(function(r){e=e.replace(new RegExp("(\\"+i+r+"(?![0-9]))","g"),t[0]+"$1"+t[1])}),e})});var o=new RegExp("\\"+i+"([0-9]+)");return a?r:function t(e,r,n){for(var i,a=[],s=0;i=o.exec(e);){if(s++>1e4)throw Error("Circular references in parenthesis");a.push(e.slice(0,i.index)),a.push(t(r[i[1]],r)),e=e.slice(i.index+i[0].length)}return a.push(e),a}(r[0],r)}function i(t,e){if(e&&e.flat){var r,n=e&&e.escape||"___",i=t[0];if(!i)return"";for(var a=new RegExp("\\"+n+"([0-9]+)"),o=0;i!=r;){if(o++>1e4)throw Error("Circular references in "+t);r=i,i=i.replace(a,s)}return i}return t.reduce(function t(e,r){return Array.isArray(r)&&(r=r.reduce(t,"")),e+r},"");function s(e,r){if(null==t[r])throw Error("Reference "+r+"is undefined");return t[r]}}function a(t,e){return Array.isArray(t)?i(t,e):n(t,e)}a.parse=n,a.stringify=i,e.exports=a},{}],442:[function(t,e,r){"use strict";var n=t("pick-by-alias");e.exports=function(t){var e;arguments.length>1&&(t=arguments);"string"==typeof t?t=t.split(/\s/).map(parseFloat):"number"==typeof t&&(t=[t]);t.length&&"number"==typeof t[0]?e=1===t.length?{width:t[0],height:t[0],x:0,y:0}:2===t.length?{width:t[0],height:t[1],x:0,y:0}:{x:t[0],y:t[1],width:t[2]-t[0]||0,height:t[3]-t[1]||0}:t&&(t=n(t,{left:"x l left Left",top:"y t top Top",width:"w width W Width",height:"h height W Width",bottom:"b bottom Bottom",right:"r right Right"}),e={x:t.left||0,y:t.top||0},null==t.width?t.right?e.width=t.right-e.x:e.width=0:e.width=t.width,null==t.height?t.bottom?e.height=t.bottom-e.y:e.height=0:e.height=t.height);return e}},{"pick-by-alias":448}],443:[function(t,e,r){e.exports=function(t){var e=[];return t.replace(i,function(t,r,i){var o=r.toLowerCase();for(i=function(t){var e=t.match(a);return e?e.map(Number):[]}(i),"m"==o&&i.length>2&&(e.push([r].concat(i.splice(0,2))),o="l",r="m"==r?"l":"L");;){if(i.length==n[o])return i.unshift(r),e.push(i);if(i.length0;--o)a=l[o],r=s[o],s[o]=s[a],s[a]=r,l[o]=l[r],l[r]=a,c=(c+r)*o;return n.freeUint32(l),n.freeUint32(s),c},r.unrank=function(t,e,r){switch(t){case 0:return r||[];case 1:return r?(r[0]=0,r):[0];case 2:return r?(e?(r[0]=0,r[1]=1):(r[0]=1,r[1]=0),r):e?[0,1]:[1,0]}var n,i,a,o=1;for((r=r||new Array(t))[0]=0,a=1;a0;--a)e=e-(n=e/o|0)*o|0,o=o/a|0,i=0|r[a],r[a]=0|r[n],r[n]=0|i;return r}},{"invert-permutation":398,"typedarray-pool":522}],448:[function(t,e,r){"use strict";e.exports=function(t,e,r){var n,a,o={};if("string"==typeof e&&(e=i(e)),Array.isArray(e)){var s={};for(a=0;a0){o=a[u][r][0],l=u;break}s=o[1^l];for(var f=0;f<2;++f)for(var h=a[f][r],p=0;p0&&(o=d,s=m,l=f)}return i?s:(o&&c(o,l),s)}function f(t,r){var i=a[r][t][0],o=[t];c(i,r);for(var s=i[1^r];;){for(;s!==t;)o.push(s),s=u(o[o.length-2],s,!1);if(a[0][t].length+a[1][t].length===0)break;var l=o[o.length-1],f=t,h=o[1],p=u(l,f,!0);if(n(e[l],e[f],e[h],e[p])<0)break;o.push(t),s=u(l,f)}return o}function h(t,e){return e[1]===e[e.length-1]}for(var o=0;o0;){a[0][o].length;var m=f(o,p);h(d,m)?d.push.apply(d,m):(d.length>0&&l.push(d),d=m)}d.length>0&&l.push(d)}return l};var n=t("compare-angle")},{"compare-angle":115}],450:[function(t,e,r){"use strict";e.exports=function(t,e){for(var r=n(t,e.length),i=new Array(e.length),a=new Array(e.length),o=[],s=0;s0;){var c=o.pop();i[c]=!1;for(var u=r[c],s=0;s0})).length,g=new Array(m),v=new Array(m),p=0;p0;){var N=B.pop(),j=C[N];l(j,function(t,e){return t-e});var V,U=j.length,q=F[N];if(0===q){var k=d[N];V=[k]}for(var p=0;p=0)&&(F[H]=1^q,B.push(H),0===q)){var k=d[H];R(k)||(k.reverse(),V.push(k))}}0===q&&r.push(V)}return r};var n=t("edges-to-adjacency-list"),i=t("planar-dual"),a=t("point-in-big-polygon"),o=t("two-product"),s=t("robust-sum"),l=t("uniq"),c=t("./lib/trim-leaves");function u(t,e){for(var r=new Array(t),n=0;n>>1;e.dtype||(e.dtype="array"),"string"==typeof e.dtype?d=new(f(e.dtype))(g):e.dtype&&(d=e.dtype,Array.isArray(d)&&(d.length=g));for(var v=0;vr){for(var h=0;hl||A>c||T=C||o===s)){var u=y[a];void 0===s&&(s=u.length);for(var f=o;f=m&&p<=v&&d>=g&&d<=w&&z.push(h)}var b=x[a],_=b[4*o+0],k=b[4*o+1],E=b[4*o+2],L=b[4*o+3],O=function(t,e){for(var r=null,n=0;null===r;)if(r=t[4*e+n],++n>t.length)return null;return r}(b,o+1),I=.5*i,P=a+1;e(r,n,I,P,_,k||E||L||O),e(r,n+I,I,P,k,E||L||O),e(r+I,n,I,P,E,L||O),e(r+I,n+I,I,P,L,O)}}}(0,0,1,0,0,1),z},d;function E(t,e,r){for(var n=1,i=.5,a=.5,o=.5,s=0;s0&&e[i]===r[0]))return 1;a=t[i-1]}for(var s=1;a;){var l=a.key,c=n(r,l[0],l[1]);if(l[0][0]0))return 0;s=-1,a=a.right}else if(c>0)a=a.left;else{if(!(c<0))return 0;s=1,a=a.right}}return s}}(v.slabs,v.coordinates);return 0===a.length?y:function(t,e){return function(r){return t(r[0],r[1])?0:e(r)}}(l(a),y)};var n=t("robust-orientation")[3],i=t("slab-decomposition"),a=t("interval-tree-1d"),o=t("binary-search-bounds");function s(){return!0}function l(t){for(var e={},r=0;r=-t},pointBetween:function(e,r,n){var i=e[1]-r[1],a=n[0]-r[0],o=e[0]-r[0],s=n[1]-r[1],l=o*a+i*s;return!(l-t)},pointsSameX:function(e,r){return Math.abs(e[0]-r[0])t!=o-i>t&&(a-c)*(i-u)/(o-u)+c-n>t&&(s=!s),a=c,o=u}return s}};return e}},{}],459:[function(t,e,r){var n={toPolygon:function(t,e){function r(e){if(e.length<=0)return t.segments({inverted:!1,regions:[]});function r(e){var r=e.slice(0,e.length-1);return t.segments({inverted:!1,regions:[r]})}for(var n=r(e[0]),i=1;i0})}function u(t,n){var i=t.seg,a=n.seg,o=i.start,s=i.end,c=a.start,u=a.end;r&&r.checkIntersection(i,a);var f=e.linesIntersect(o,s,c,u);if(!1===f){if(!e.pointsCollinear(o,s,c))return!1;if(e.pointsSame(o,u)||e.pointsSame(s,c))return!1;var h=e.pointsSame(o,c),p=e.pointsSame(s,u);if(h&&p)return n;var d=!h&&e.pointBetween(o,c,u),m=!p&&e.pointBetween(s,c,u);if(h)return m?l(n,s):l(t,u),n;d&&(p||(m?l(n,s):l(t,u)),l(n,o))}else 0===f.alongA&&(-1===f.alongB?l(t,c):0===f.alongB?l(t,f.pt):1===f.alongB&&l(t,u)),0===f.alongB&&(-1===f.alongA?l(n,o):0===f.alongA?l(n,f.pt):1===f.alongA&&l(n,s));return!1}for(var f=[];!a.isEmpty();){var h=a.getHead();if(r&&r.vert(h.pt[0]),h.isStart){r&&r.segmentNew(h.seg,h.primary);var p=c(h),d=p.before?p.before.ev:null,m=p.after?p.after.ev:null;function g(){if(d){var t=u(h,d);if(t)return t}return!!m&&u(h,m)}r&&r.tempStatus(h.seg,!!d&&d.seg,!!m&&m.seg);var v,y,x=g();if(x)t?(y=null===h.seg.myFill.below||h.seg.myFill.above!==h.seg.myFill.below)&&(x.seg.myFill.above=!x.seg.myFill.above):x.seg.otherFill=h.seg.myFill,r&&r.segmentUpdate(x.seg),h.other.remove(),h.remove();if(a.getHead()!==h){r&&r.rewind(h.seg);continue}t?(y=null===h.seg.myFill.below||h.seg.myFill.above!==h.seg.myFill.below,h.seg.myFill.below=m?m.seg.myFill.above:i,h.seg.myFill.above=y?!h.seg.myFill.below:h.seg.myFill.below):null===h.seg.otherFill&&(v=m?h.primary===m.primary?m.seg.otherFill.above:m.seg.myFill.above:h.primary?o:i,h.seg.otherFill={above:v,below:v}),r&&r.status(h.seg,!!d&&d.seg,!!m&&m.seg),h.other.status=p.insert(n.node({ev:h}))}else{var b=h.status;if(null===b)throw new Error("PolyBool: Zero-length segment detected; your epsilon is probably too small or too large");if(s.exists(b.prev)&&s.exists(b.next)&&u(b.prev.ev,b.next.ev),r&&r.statusRemove(b.ev.seg),b.remove(),!h.primary){var _=h.seg.myFill;h.seg.myFill=h.seg.otherFill,h.seg.otherFill=_}f.push(h.seg)}a.getHead().remove()}return r&&r.done(),f}return t?{addRegion:function(t){for(var n,i,a,o=t[t.length-1],l=0;l=c?(M=1,y=c+2*h+d):y=h*(M=-h/c)+d):(M=0,p>=0?(A=0,y=d):-p>=f?(A=1,y=f+2*p+d):y=p*(A=-p/f)+d);else if(A<0)A=0,h>=0?(M=0,y=d):-h>=c?(M=1,y=c+2*h+d):y=h*(M=-h/c)+d;else{var T=1/k;y=(M*=T)*(c*M+u*(A*=T)+2*h)+A*(u*M+f*A+2*p)+d}else M<0?(b=f+p)>(x=u+h)?(_=b-x)>=(w=c-2*u+f)?(M=1,A=0,y=c+2*h+d):y=(M=_/w)*(c*M+u*(A=1-M)+2*h)+A*(u*M+f*A+2*p)+d:(M=0,b<=0?(A=1,y=f+2*p+d):p>=0?(A=0,y=d):y=p*(A=-p/f)+d):A<0?(b=c+h)>(x=u+p)?(_=b-x)>=(w=c-2*u+f)?(A=1,M=0,y=f+2*p+d):y=(M=1-(A=_/w))*(c*M+u*A+2*h)+A*(u*M+f*A+2*p)+d:(A=0,b<=0?(M=1,y=c+2*h+d):h>=0?(M=0,y=d):y=h*(M=-h/c)+d):(_=f+p-u-h)<=0?(M=0,A=1,y=f+2*p+d):_>=(w=c-2*u+f)?(M=1,A=0,y=c+2*h+d):y=(M=_/w)*(c*M+u*(A=1-M)+2*h)+A*(u*M+f*A+2*p)+d;var S=1-M-A;for(l=0;l1)for(var r=1;r0){var c=t[r-1];if(0===n(s,c)&&a(c)!==l){r-=1;continue}}t[r++]=s}}return t.length=r,t}},{"cell-orientation":100,"compare-cell":116,"compare-oriented-cell":117}],473:[function(t,e,r){"use strict";var n=t("array-bounds"),i=t("color-normalize"),a=t("update-diff"),o=t("pick-by-alias"),s=t("object-assign"),l=t("flatten-vertex-data"),c=t("to-float32"),u=c.float32,f=c.fract32;e.exports=function(t,e){"function"==typeof t?(e||(e={}),e.regl=t):e=t;e.length&&(e.positions=e);if(!(t=e.regl).hasExtension("ANGLE_instanced_arrays"))throw Error("regl-error2d: `ANGLE_instanced_arrays` extension should be enabled");var r,c,p,d,m,g,v=t._gl,y={color:"black",capSize:5,lineWidth:1,opacity:1,viewport:null,range:null,offset:0,count:0,bounds:null,positions:[],errors:[]},x=[];return d=t.buffer({usage:"dynamic",type:"uint8",data:new Uint8Array(0)}),c=t.buffer({usage:"dynamic",type:"float",data:new Uint8Array(0)}),p=t.buffer({usage:"dynamic",type:"float",data:new Uint8Array(0)}),m=t.buffer({usage:"dynamic",type:"float",data:new Uint8Array(0)}),g=t.buffer({usage:"static",type:"float",data:h}),k(e),r=t({vert:"\n\t\tprecision highp float;\n\n\t\tattribute vec2 position, positionFract;\n\t\tattribute vec4 error;\n\t\tattribute vec4 color;\n\n\t\tattribute vec2 direction, lineOffset, capOffset;\n\n\t\tuniform vec4 viewport;\n\t\tuniform float lineWidth, capSize;\n\t\tuniform vec2 scale, scaleFract, translate, translateFract;\n\n\t\tvarying vec4 fragColor;\n\n\t\tvoid main() {\n\t\t\tfragColor = color / 255.;\n\n\t\t\tvec2 pixelOffset = lineWidth * lineOffset + (capSize + lineWidth) * capOffset;\n\n\t\t\tvec2 dxy = -step(.5, direction.xy) * error.xz + step(direction.xy, vec2(-.5)) * error.yw;\n\n\t\t\tvec2 position = position + dxy;\n\n\t\t\tvec2 pos = (position + translate) * scale\n\t\t\t\t+ (positionFract + translateFract) * scale\n\t\t\t\t+ (position + translate) * scaleFract\n\t\t\t\t+ (positionFract + translateFract) * scaleFract;\n\n\t\t\tpos += pixelOffset / viewport.zw;\n\n\t\t\tgl_Position = vec4(pos * 2. - 1., 0, 1);\n\t\t}\n\t\t",frag:"\n\t\tprecision mediump float;\n\n\t\tvarying vec4 fragColor;\n\n\t\tuniform float opacity;\n\n\t\tvoid main() {\n\t\t\tgl_FragColor = fragColor;\n\t\t\tgl_FragColor.a *= opacity;\n\t\t}\n\t\t",uniforms:{range:t.prop("range"),lineWidth:t.prop("lineWidth"),capSize:t.prop("capSize"),opacity:t.prop("opacity"),scale:t.prop("scale"),translate:t.prop("translate"),scaleFract:t.prop("scaleFract"),translateFract:t.prop("translateFract"),viewport:function(t,e){return[e.viewport.x,e.viewport.y,t.viewportWidth,t.viewportHeight]}},attributes:{color:{buffer:d,offset:function(t,e){return 4*e.offset},divisor:1},position:{buffer:c,offset:function(t,e){return 8*e.offset},divisor:1},positionFract:{buffer:p,offset:function(t,e){return 8*e.offset},divisor:1},error:{buffer:m,offset:function(t,e){return 16*e.offset},divisor:1},direction:{buffer:g,stride:24,offset:0},lineOffset:{buffer:g,stride:24,offset:8},capOffset:{buffer:g,stride:24,offset:16}},primitive:"triangles",blend:{enable:!0,color:[0,0,0,0],equation:{rgb:"add",alpha:"add"},func:{srcRGB:"src alpha",dstRGB:"one minus src alpha",srcAlpha:"one minus dst alpha",dstAlpha:"one"}},depth:{enable:!1},scissor:{enable:!0,box:t.prop("viewport")},viewport:t.prop("viewport"),stencil:!1,instances:t.prop("count"),count:h.length}),s(b,{update:k,draw:_,destroy:M,regl:t,gl:v,canvas:v.canvas,groups:x}),b;function b(t){t?k(t):null===t&&M(),_()}function _(e){if("number"==typeof e)return w(e);e&&!Array.isArray(e)&&(e=[e]),t._refresh(),x.forEach(function(t,r){t&&(e&&(e[r]?t.draw=!0:t.draw=!1),t.draw?w(r):t.draw=!0)})}function w(t){"number"==typeof t&&(t=x[t]),null!=t&&t&&t.count&&t.color&&t.opacity&&t.positions&&t.positions.length>1&&(t.scaleRatio=[t.scale[0]*t.viewport.width,t.scale[1]*t.viewport.height],r(t),t.after&&t.after(t))}function k(t){if(t){null!=t.length?"number"==typeof t[0]&&(t=[{positions:t}]):Array.isArray(t)||(t=[t]);var e=0,r=0;if(b.groups=x=t.map(function(t,c){var u=x[c];return t?("function"==typeof t?t={after:t}:"number"==typeof t[0]&&(t={positions:t}),t=o(t,{color:"color colors fill",capSize:"capSize cap capsize cap-size",lineWidth:"lineWidth line-width width line thickness",opacity:"opacity alpha",range:"range dataBox",viewport:"viewport viewBox",errors:"errors error",positions:"positions position data points"}),u||(x[c]=u={id:c,scale:null,translate:null,scaleFract:null,translateFract:null,draw:!0},t=s({},y,t)),a(u,t,[{lineWidth:function(t){return.5*+t},capSize:function(t){return.5*+t},opacity:parseFloat,errors:function(t){return t=l(t),r+=t.length,t},positions:function(t,r){return t=l(t,"float64"),r.count=Math.floor(t.length/2),r.bounds=n(t,2),r.offset=e,e+=r.count,t}},{color:function(t,e){var r=e.count;if(t||(t="transparent"),!Array.isArray(t)||"number"==typeof t[0]){var n=t;t=Array(r);for(var a=0;a 0. && baClipping < length(normalWidth * endBotJoin)) {\n\t\t//handle miter clipping\n\t\tbTopCoord -= normalWidth * endTopJoin;\n\t\tbTopCoord += normalize(endTopJoin * normalWidth) * baClipping;\n\t}\n\n\tif (nextReverse) {\n\t\t//make join rectangular\n\t\tvec2 miterShift = normalWidth * endJoinDirection * miterLimit * .5;\n\t\tfloat normalAdjust = 1. - min(miterLimit / endMiterRatio, 1.);\n\t\tbBotCoord = bCoord + miterShift - normalAdjust * normalWidth * currNormal * .5;\n\t\tbTopCoord = bCoord + miterShift + normalAdjust * normalWidth * currNormal * .5;\n\t}\n\telse if (!prevReverse && abClipping > 0. && abClipping < length(normalWidth * startBotJoin)) {\n\t\t//handle miter clipping\n\t\taBotCoord -= normalWidth * startBotJoin;\n\t\taBotCoord += normalize(startBotJoin * normalWidth) * abClipping;\n\t}\n\n\tvec2 aTopPosition = (aTopCoord) * adjustedScale + translate;\n\tvec2 aBotPosition = (aBotCoord) * adjustedScale + translate;\n\n\tvec2 bTopPosition = (bTopCoord) * adjustedScale + translate;\n\tvec2 bBotPosition = (bBotCoord) * adjustedScale + translate;\n\n\t//position is normalized 0..1 coord on the screen\n\tvec2 position = (aTopPosition * lineTop + aBotPosition * lineBot) * lineStart + (bTopPosition * lineTop + bBotPosition * lineBot) * lineEnd;\n\n\tstartCoord = aCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\tendCoord = bCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tenableStartMiter = step(dot(currTangent, prevTangent), .5);\n\tenableEndMiter = step(dot(currTangent, nextTangent), .5);\n\n\t//bevel miter cutoffs\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * miterLimit * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * miterLimit * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n\n\t//round miter cutoffs\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * abs(dot(startJoinDirection, currNormal)) * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * abs(dot(endJoinDirection, currNormal)) * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n}\n"]),frag:o(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D dashPattern;\nuniform float dashSize, pixelRatio, thickness, opacity, id, miterMode;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\nvarying vec4 startCutoff, endCutoff;\nvarying vec2 startCoord, endCoord;\nvarying float enableStartMiter, enableEndMiter;\n\nfloat distToLine(vec2 p, vec2 a, vec2 b) {\n\tvec2 diff = b - a;\n\tvec2 perp = normalize(vec2(-diff.y, diff.x));\n\treturn dot(p - a, perp);\n}\n\nvoid main() {\n\tfloat alpha = 1., distToStart, distToEnd;\n\tfloat cutoff = thickness * .5;\n\n\t//bevel miter\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToStart + 1., 0.), 1.);\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToEnd + 1., 0.), 1.);\n\t\t}\n\t}\n\n\t// round miter\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - startCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - endCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\t}\n\n\tfloat t = fract(dot(tangent, gl_FragCoord.xy) / dashSize) * .5 + .25;\n\tfloat dash = texture2D(dashPattern, vec2(t, .5)).r;\n\n\tgl_FragColor = fragColor;\n\tgl_FragColor.a *= alpha * opacity * dash;\n}\n"]),attributes:{lineEnd:{buffer:r,divisor:0,stride:8,offset:0},lineTop:{buffer:r,divisor:0,stride:8,offset:4},aColor:{buffer:t.prop("colorBuffer"),stride:4,offset:0,divisor:1},bColor:{buffer:t.prop("colorBuffer"),stride:4,offset:4,divisor:1},prevCoord:{buffer:t.prop("positionBuffer"),stride:8,offset:0,divisor:1},aCoord:{buffer:t.prop("positionBuffer"),stride:8,offset:8,divisor:1},bCoord:{buffer:t.prop("positionBuffer"),stride:8,offset:16,divisor:1},nextCoord:{buffer:t.prop("positionBuffer"),stride:8,offset:24,divisor:1}}},n))}catch(t){e=i}return{fill:t({primitive:"triangle",elements:function(t,e){return e.triangles},offset:0,vert:o(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 position, positionFract;\n\nuniform vec4 color;\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio, id;\nuniform vec4 viewport;\nuniform float opacity;\n\nvarying vec4 fragColor;\n\nconst float MAX_LINES = 256.;\n\nvoid main() {\n\tfloat depth = (MAX_LINES - 4. - id) / (MAX_LINES);\n\n\tvec2 position = position * scale + translate\n + positionFract * scale + translateFract\n + position * scaleFract\n + positionFract * scaleFract;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tfragColor = color / 255.;\n\tfragColor.a *= opacity;\n}\n"]),frag:o(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n\tgl_FragColor = fragColor;\n}\n"]),uniforms:{scale:t.prop("scale"),color:t.prop("fill"),scaleFract:t.prop("scaleFract"),translateFract:t.prop("translateFract"),translate:t.prop("translate"),opacity:t.prop("opacity"),pixelRatio:t.context("pixelRatio"),id:t.prop("id"),viewport:function(t,e){return[e.viewport.x,e.viewport.y,t.viewportWidth,t.viewportHeight]}},attributes:{position:{buffer:t.prop("positionBuffer"),stride:8,offset:8},positionFract:{buffer:t.prop("positionFractBuffer"),stride:8,offset:8}},blend:n.blend,depth:{enable:!1},scissor:n.scissor,stencil:n.stencil,viewport:n.viewport}),rect:i,miter:e}},g.defaults={dashes:null,join:"miter",miterLimit:1,thickness:10,cap:"square",color:"black",opacity:1,overlay:!1,viewport:null,range:null,close:!1,fill:null},g.prototype.render=function(){for(var t,e=[],r=arguments.length;r--;)e[r]=arguments[r];e.length&&(t=this).update.apply(t,e),this.draw()},g.prototype.draw=function(){for(var t=this,e=[],r=arguments.length;r--;)e[r]=arguments[r];return(e.length?e:this.passes).forEach(function(e,r){var n;if(e&&Array.isArray(e))return(n=t).draw.apply(n,e);"number"==typeof e&&(e=t.passes[e]),e&&e.count>1&&e.opacity&&(t.regl._refresh(),e.fill&&e.triangles&&e.triangles.length>2&&t.shaders.fill(e),e.thickness&&(e.scale[0]*e.viewport.width>g.precisionThreshold||e.scale[1]*e.viewport.height>g.precisionThreshold?t.shaders.rect(e):"rect"===e.join||!e.join&&(e.thickness<=2||e.count>=g.maxPoints)?t.shaders.rect(e):t.shaders.miter(e)))}),this},g.prototype.update=function(t){var e=this;if(t){null!=t.length?"number"==typeof t[0]&&(t=[{positions:t}]):Array.isArray(t)||(t=[t]);var r=this.regl,o=this.gl;if(t.forEach(function(t,f){var d=e.passes[f];if(void 0!==t)if(null!==t){if("number"==typeof t[0]&&(t={positions:t}),t=s(t,{positions:"positions points data coords",thickness:"thickness lineWidth lineWidths line-width linewidth width stroke-width strokewidth strokeWidth",join:"lineJoin linejoin join type mode",miterLimit:"miterlimit miterLimit",dashes:"dash dashes dasharray dash-array dashArray",color:"color colour stroke colors colours stroke-color strokeColor",fill:"fill fill-color fillColor",opacity:"alpha opacity",overlay:"overlay crease overlap intersect",close:"closed close closed-path closePath",range:"range dataBox",viewport:"viewport viewBox",hole:"holes hole hollow"}),d||(e.passes[f]=d={id:f,scale:null,scaleFract:null,translate:null,translateFract:null,count:0,hole:[],depth:0,dashLength:1,dashTexture:r.texture({channels:1,data:new Uint8Array([255]),width:1,height:1,mag:"linear",min:"linear"}),colorBuffer:r.buffer({usage:"dynamic",type:"uint8",data:new Uint8Array}),positionBuffer:r.buffer({usage:"dynamic",type:"float",data:new Uint8Array}),positionFractBuffer:r.buffer({usage:"dynamic",type:"float",data:new Uint8Array})},t=a({},g.defaults,t)),null!=t.thickness&&(d.thickness=parseFloat(t.thickness)),null!=t.opacity&&(d.opacity=parseFloat(t.opacity)),null!=t.miterLimit&&(d.miterLimit=parseFloat(t.miterLimit)),null!=t.overlay&&(d.overlay=!!t.overlay,f 1.0 + delta) {\n\t\tdiscard;\n\t}\n\n\talpha -= smoothstep(1.0 - delta, 1.0 + delta, radius);\n\n\tfloat borderRadius = fragBorderRadius;\n\tfloat ratio = smoothstep(borderRadius - delta, borderRadius + delta, radius);\n\tvec4 color = mix(fragColor, fragBorderColor, ratio);\n\tcolor.a *= alpha * opacity;\n\tgl_FragColor = color;\n}\n"]),u.vert=l(["precision highp float;\n#define GLSLIFY 1\n\nattribute float x, y, xFract, yFract;\nattribute float size, borderSize;\nattribute vec4 colorId, borderColorId;\nattribute float isActive;\n\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio;\nuniform sampler2D palette;\nuniform vec2 paletteSize;\n\nconst float maxSize = 100.;\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragBorderRadius, fragWidth;\n\nvec2 paletteCoord(float id) {\n return vec2(\n (mod(id, paletteSize.x) + .5) / paletteSize.x,\n (floor(id / paletteSize.x) + .5) / paletteSize.y\n );\n}\nvec2 paletteCoord(vec2 id) {\n return vec2(\n (id.x + .5) / paletteSize.x,\n (id.y + .5) / paletteSize.y\n );\n}\n\nvec4 getColor(vec4 id) {\n // zero-palette means we deal with direct buffer\n if (paletteSize.x == 0.) return id / 255.;\n return texture2D(palette, paletteCoord(id.xy));\n}\n\nvoid main() {\n // ignore inactive points\n if (isActive == 0.) return;\n\n vec2 position = vec2(x, y);\n vec2 positionFract = vec2(xFract, yFract);\n\n vec4 color = getColor(colorId);\n vec4 borderColor = getColor(borderColorId);\n\n float size = size * maxSize / 255.;\n float borderSize = borderSize * maxSize / 255.;\n\n gl_PointSize = (size + borderSize) * pixelRatio;\n\n vec2 pos = (position + translate) * scale\n + (positionFract + translateFract) * scale\n + (position + translate) * scaleFract\n + (positionFract + translateFract) * scaleFract;\n\n gl_Position = vec4(pos * 2. - 1., 0, 1);\n\n fragBorderRadius = 1. - 2. * borderSize / (size + borderSize);\n fragColor = color;\n fragBorderColor = borderColor.a == 0. || borderSize == 0. ? vec4(color.rgb, 0.) : borderColor;\n fragWidth = 1. / gl_PointSize;\n}\n"]),h&&(u.frag=u.frag.replace("smoothstep","smoothStep"),c.frag=c.frag.replace("smoothstep","smoothStep")),this.drawCircle=t(u)}e.exports=m,m.defaults={color:"black",borderColor:"transparent",borderSize:0,size:12,opacity:1,marker:void 0,viewport:null,range:null,pixelSize:null,count:0,offset:0,bounds:null,positions:[],snap:1e4},m.prototype.render=function(){for(var t,e=[],r=arguments.length;r--;)e[r]=arguments[r];return e.length&&(t=this).update.apply(t,e),this.draw(),this},m.prototype.draw=function(){for(var t=this,e=[],r=arguments.length;r--;)e[r]=arguments[r];var n=this.groups;if(1===e.length&&Array.isArray(e[0])&&(null===e[0][0]||Array.isArray(e[0][0]))&&(e=e[0]),this.regl._refresh(),e.length)for(var i=0;in)?e.tree=o(t,{bounds:h}):n&&n.length&&(e.tree=n),e.tree){var d={primitive:"points",usage:"static",data:e.tree,type:"uint32"};e.elements?e.elements(d):e.elements=l.elements(d)}return a({data:p.float(t),usage:"dynamic"}),s({data:p.fract(t),usage:"dynamic"}),c({data:new Uint8Array(u),type:"uint8",usage:"stream"}),t}},{marker:function(e,r,n){var i=r.activation;if(i.forEach(function(t){return t&&t.destroy&&t.destroy()}),i.length=0,e&&"number"!=typeof e[0]){for(var a=[],o=0,s=Math.min(e.length,r.count);o=0)return a;if(t instanceof Uint8Array||t instanceof Uint8ClampedArray)e=t;else{e=new Uint8Array(t.length);for(var o=0,s=t.length;oi*i*4&&(this.tooManyColors=!0),this.updatePalette(r),1===o.length?o[0]:o},m.prototype.updatePalette=function(t){if(!this.tooManyColors){var e=this.maxColors,r=this.paletteTexture,n=Math.ceil(.25*t.length/e);if(n>1)for(var i=.25*(t=t.slice()).length%e;i2?(s[0],s[2],n=s[1],i=s[3]):s.length?(n=s[0],i=s[1]):(s.x,n=s.y,s.x+s.width,i=s.y+s.height),l.length>2?(a=l[0],o=l[2],l[1],l[3]):l.length?(a=l[0],o=l[1]):(a=l.x,l.y,o=l.x+l.width,l.y+l.height),[a,n,o,i]}function p(t){if("number"==typeof t)return[t,t,t,t];if(2===t.length)return[t[0],t[1],t[0],t[1]];var e=l(t);return[e.x,e.y,e.x+e.width,e.y+e.height]}e.exports=u,u.prototype.render=function(){for(var t,e=this,r=[],n=arguments.length;n--;)r[n]=arguments[n];return r.length&&(t=this).update.apply(t,r),this.regl.attributes.preserveDrawingBuffer?this.draw():(this.dirty?null==this.planned&&(this.planned=o(function(){e.draw(),e.dirty=!0,e.planned=null})):(this.draw(),this.dirty=!0,o(function(){e.dirty=!1})),this)},u.prototype.update=function(){for(var t,e=[],r=arguments.length;r--;)e[r]=arguments[r];if(e.length){for(var n=0;nM))&&(s.lower||!(k=0&&(0|t)===t||n("invalid parameter type, ("+t+")"+a(e)+". must be a nonnegative integer")},oneOf:o,shaderError:function(t,e,n,a,o){if(!t.getShaderParameter(e,t.COMPILE_STATUS)){var s=t.getShaderInfoLog(e),c=a===t.FRAGMENT_SHADER?"fragment":"vertex";v(n,"string",c+" shader source must be a string",o);var u=d(n,o),h=function(t){var e=[];return t.split("\n").forEach(function(t){if(!(t.length<5)){var r=/^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(t);r?e.push(new f(0|r[1],0|r[2],r[3].trim())):t.length>0&&e.push(new f("unknown",0,t))}}),e}(s);!function(t,e){e.forEach(function(e){var r=t[e.file];if(r){var n=r.index[e.line];if(n)return n.errors.push(e),void(r.hasErrors=!0)}t.unknown.hasErrors=!0,t.unknown.lines[0].errors.push(e)})}(u,h),Object.keys(u).forEach(function(t){var e=u[t];if(e.hasErrors){var n=[""],i=[""];a("file number "+t+": "+e.name+"\n","color:red;text-decoration:underline;font-weight:bold"),e.lines.forEach(function(t){if(t.errors.length>0){a(l(t.number,4)+"| ","background-color:yellow; font-weight:bold"),a(t.line+r,"color:red; background-color:yellow; font-weight:bold");var e=0;t.errors.forEach(function(n){var i=n.message,o=/^\s*\'(.*)\'\s*\:\s*(.*)$/.exec(i);if(o){var s=o[1];switch(i=o[2],s){case"assign":s="="}e=Math.max(t.line.indexOf(s,e),0)}else e=0;a(l("| ",6)),a(l("^^^",e+3)+r,"font-weight:bold"),a(l("| ",6)),a(i+r,"font-weight:bold")}),a(l("| ",6)+r)}else a(l(t.number,4)+"| "),a(t.line+r,"color:red")}),"undefined"==typeof document||window.chrome?console.log(n.join("")):(i[0]=n.join("%c"),console.log.apply(console,i))}function a(t,e){n.push(t),i.push(e||"")}}),i.raise("Error compiling "+c+" shader, "+u[0].name)}},linkError:function(t,e,n,a,o){if(!t.getProgramParameter(e,t.LINK_STATUS)){var s=t.getProgramInfoLog(e),l=d(n,o),c='Error linking program with vertex shader, "'+d(a,o)[0].name+'", and fragment shader "'+l[0].name+'"';"undefined"!=typeof document?console.log("%c"+c+r+"%c"+s,"color:red;text-decoration:underline;font-weight:bold","color:red"):console.log(c+r+s),i.raise(c)}},callSite:p,saveCommandRef:m,saveDrawInfo:function(t,e,r,n){function i(t){return t?n.id(t):0}function a(t,e){Object.keys(e).forEach(function(e){t[n.id(e)]=!0})}m(t),t._fragId=i(t.static.frag),t._vertId=i(t.static.vert);var o=t._uniformSet={};a(o,e.static),a(o,e.dynamic);var s=t._attributeSet={};a(s,r.static),a(s,r.dynamic),t._hasCount="count"in t.static||"count"in t.dynamic||"elements"in t.static||"elements"in t.dynamic},framebufferFormat:function(t,e,r){t.texture?o(t.texture._texture.internalformat,e,"unsupported texture format for attachment"):o(t.renderbuffer._renderbuffer.format,r,"unsupported renderbuffer format for attachment")},guessCommand:h,texture2D:function(t,e,r){var n,a=e.width,o=e.height,s=e.channels;i(a>0&&a<=r.maxTextureSize&&o>0&&o<=r.maxTextureSize,"invalid texture shape"),t.wrapS===y&&t.wrapT===y||i(z(a)&&z(o),"incompatible wrap mode for texture, both width and height must be power of 2"),1===e.mipmask?1!==a&&1!==o&&i(t.minFilter!==b&&t.minFilter!==w&&t.minFilter!==_&&t.minFilter!==k,"min filter requires mipmap"):(i(z(a)&&z(o),"texture must be a square power of 2 to support mipmapping"),i(e.mipmask===(a<<1)-1,"missing or incomplete mipmap data")),e.type===M&&(r.extensions.indexOf("oes_texture_float_linear")<0&&i(t.minFilter===x&&t.magFilter===x,"filter not supported, must enable oes_texture_float_linear"),i(!t.genMipmaps,"mipmap generation not supported with float textures"));var l=e.images;for(n=0;n<16;++n)if(l[n]){var c=a>>n,u=o>>n;i(e.mipmask&1<0&&a<=n.maxTextureSize&&o>0&&o<=n.maxTextureSize,"invalid texture shape"),i(a===o,"cube map must be square"),i(e.wrapS===y&&e.wrapT===y,"wrap mode not supported by cube map");for(var l=0;l>f,d=o>>f;i(c.mipmask&1<1&&r===n&&('"'===r||"'"===r))return['"'+R(e.substr(1,e.length-2))+'"'];var i=/\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(e);if(i)return t(e.substr(0,i.index)).concat(t(i[1])).concat(t(e.substr(i.index+i[0].length)));var a=e.split(".");if(1===a.length)return['"'+R(e)+'"'];for(var o=[],s=0;s0,"invalid pixel ratio"))):i=(a=s).canvas:O.raise("invalid arguments to regl"),r&&("canvas"===r.nodeName.toLowerCase()?i=r:n=r),!a){if(!i){O("undefined"!=typeof document,"must manually specify webgl context outside of DOM environments");var m=function(t,r,n){var i=document.createElement("canvas");function a(){var r=window.innerWidth,a=window.innerHeight;if(t!==document.body){var o=t.getBoundingClientRect();r=o.right-o.left,a=o.bottom-o.top}i.width=n*r,i.height=n*a,e(i.style,{width:r+"px",height:a+"px"})}return e(i.style,{border:0,margin:0,padding:0,top:0,left:0}),t.appendChild(i),t===document.body&&(i.style.position="absolute",e(t.style,{margin:0,padding:0})),window.addEventListener("resize",a,!1),a(),{canvas:i,onDestroy:function(){window.removeEventListener("resize",a),t.removeChild(i)}}}(n||document.body,0,f);if(!m)return null;i=m.canvas,d=m.onDestroy}a=function(t,e){function r(r){try{return t.getContext(r,e)}catch(t){return null}}return r("webgl")||r("experimental-webgl")||r("webgl-experimental")}(i,l)}return a?{gl:a,canvas:i,container:n,extensions:c,optionalExtensions:u,pixelRatio:f,profile:h,onDone:p,onDestroy:d}:(d(),p("webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org"),null)}function H(t,e){for(var r=Array(t),n=0;n65535)<<4,e|=r=((t>>>=e)>255)<<3,e|=r=((t>>>=r)>15)<<2,(e|=r=((t>>>=r)>3)<<1)|(t>>>=r)>>1}function Q(){var t=H(8,function(){return[]});function e(e){var r=function(t){for(var e=16;e<=1<<28;e*=16)if(t<=e)return e;return 0}(e),n=t[K(r)>>2];return n.length>0?n.pop():new ArrayBuffer(r)}function r(e){t[K(e.byteLength)>>2].push(e)}return{alloc:e,free:r,allocType:function(t,r){var n=null;switch(t){case G:n=new Int8Array(e(r),0,r);break;case W:n=new Uint8Array(e(r),0,r);break;case Y:n=new Int16Array(e(2*r),0,r);break;case X:n=new Uint16Array(e(2*r),0,r);break;case Z:n=new Int32Array(e(4*r),0,r);break;case $:n=new Uint32Array(e(4*r),0,r);break;case J:n=new Float32Array(e(4*r),0,r);break;default:return null}return n.length!==r?n.subarray(0,r):n},freeType:function(t){r(t.buffer)}}}var tt=Q();tt.zero=Q();var et=function(t,e){var r=1;e.ext_texture_filter_anisotropic&&(r=t.getParameter(34047));var n=1,i=1;e.webgl_draw_buffers&&(n=t.getParameter(34852),i=t.getParameter(36063));var a=!!e.oes_texture_float;if(a){var o=t.createTexture();t.bindTexture(3553,o),t.texImage2D(3553,0,6408,1,1,0,6408,5126,null);var s=t.createFramebuffer();if(t.bindFramebuffer(36160,s),t.framebufferTexture2D(36160,36064,3553,o,0),t.bindTexture(3553,null),36053!==t.checkFramebufferStatus(36160))a=!1;else{t.viewport(0,0,1,1),t.clearColor(1,0,0,1),t.clear(16384);var l=tt.allocType(5126,4);t.readPixels(0,0,1,1,6408,5126,l),t.getError()?a=!1:(t.deleteFramebuffer(s),t.deleteTexture(o),a=1===l[0]),tt.freeType(l)}}var c,u=t.createTexture(),f=tt.allocType(5121,36);return t.activeTexture(33984),t.bindTexture(34067,u),t.texImage2D(34069,0,6408,3,3,0,6408,5121,f),tt.freeType(f),t.bindTexture(34067,null),t.deleteTexture(u),c=!t.getError(),{colorBits:[t.getParameter(3410),t.getParameter(3411),t.getParameter(3412),t.getParameter(3413)],depthBits:t.getParameter(3414),stencilBits:t.getParameter(3415),subpixelBits:t.getParameter(3408),extensions:Object.keys(e).filter(function(t){return!!e[t]}),maxAnisotropic:r,maxDrawbuffers:n,maxColorAttachments:i,pointSizeDims:t.getParameter(33901),lineWidthDims:t.getParameter(33902),maxViewportDims:t.getParameter(3386),maxCombinedTextureUnits:t.getParameter(35661),maxCubeMapSize:t.getParameter(34076),maxRenderbufferSize:t.getParameter(34024),maxTextureUnits:t.getParameter(34930),maxTextureSize:t.getParameter(3379),maxAttributes:t.getParameter(34921),maxVertexUniforms:t.getParameter(36347),maxVertexTextureUnits:t.getParameter(35660),maxVaryingVectors:t.getParameter(36348),maxFragmentUniforms:t.getParameter(36349),glsl:t.getParameter(35724),renderer:t.getParameter(7937),vendor:t.getParameter(7936),version:t.getParameter(7938),readFloat:a,npotTextureCube:c}};function rt(e){return!!e&&"object"==typeof e&&Array.isArray(e.shape)&&Array.isArray(e.stride)&&"number"==typeof e.offset&&e.shape.length===e.stride.length&&(Array.isArray(e.data)||t(e.data))}var nt=function(t){return Object.keys(t).map(function(e){return t[e]})},it={shape:function(t){for(var e=[],r=t;r.length;r=r[0])e.push(r.length);return e},flatten:function(t,e,r,n){var i=1;if(e.length)for(var a=0;a>>31<<15,a=(n<<1>>>24)-127,o=n>>13&1023;if(a<-24)e[r]=i;else if(a<-14){var s=-14-a;e[r]=i+(o+1024>>s)}else e[r]=a>15?i+31744:i+(a+15<<10)+o}return e}function Rt(e){return Array.isArray(e)||t(e)}var Bt=function(t){return!(t&t-1||!t)},Ft=34467,Nt=3553,jt=34067,Vt=34069,Ut=6408,qt=6406,Ht=6407,Gt=6409,Wt=6410,Yt=32854,Xt=32855,Zt=36194,$t=32819,Jt=32820,Kt=33635,Qt=34042,te=6402,ee=34041,re=35904,ne=35906,ie=36193,ae=33776,oe=33777,se=33778,le=33779,ce=35986,ue=35987,fe=34798,he=35840,pe=35841,de=35842,me=35843,ge=36196,ve=5121,ye=5123,xe=5125,be=5126,_e=10242,we=10243,ke=10497,Me=33071,Ae=33648,Te=10240,Se=10241,Ee=9728,Ce=9729,Le=9984,ze=9985,Oe=9986,Ie=9987,Pe=33170,De=4352,Re=4353,Be=4354,Fe=34046,Ne=3317,je=37440,Ve=37441,Ue=37443,qe=37444,He=33984,Ge=[Le,Oe,ze,Ie],We=[0,Gt,Wt,Ht,Ut],Ye={};function Xe(t){return"[object "+t+"]"}Ye[Gt]=Ye[qt]=Ye[te]=1,Ye[ee]=Ye[Wt]=2,Ye[Ht]=Ye[re]=3,Ye[Ut]=Ye[ne]=4;var Ze=Xe("HTMLCanvasElement"),$e=Xe("CanvasRenderingContext2D"),Je=Xe("ImageBitmap"),Ke=Xe("HTMLImageElement"),Qe=Xe("HTMLVideoElement"),tr=Object.keys(ot).concat([Ze,$e,Je,Ke,Qe]),er=[];er[ve]=1,er[be]=4,er[ie]=2,er[ye]=2,er[xe]=4;var rr=[];function nr(t){return Array.isArray(t)&&(0===t.length||"number"==typeof t[0])}function ir(t){return!!Array.isArray(t)&&!(0===t.length||!Rt(t[0]))}function ar(t){return Object.prototype.toString.call(t)}function or(t){return ar(t)===Ze}function sr(t){if(!t)return!1;var e=ar(t);return tr.indexOf(e)>=0||(nr(t)||ir(t)||rt(t))}function lr(t){return 0|ot[Object.prototype.toString.call(t)]}function cr(t,e){return tt.allocType(t.type===ie?be:t.type,e)}function ur(t,e){t.type===ie?(t.data=Dt(e),tt.freeType(e)):t.data=e}function fr(t,e,r,n,i,a){var o;if(o="undefined"!=typeof rr[t]?rr[t]:Ye[t]*er[e],a&&(o*=6),i){for(var s=0,l=r;l>=1;)s+=o*l*l,l/=2;return s}return o*r*n}function hr(r,n,i,a,o,s,l){var c={"don't care":De,"dont care":De,nice:Be,fast:Re},u={repeat:ke,clamp:Me,mirror:Ae},f={nearest:Ee,linear:Ce},h=e({mipmap:Ie,"nearest mipmap nearest":Le,"linear mipmap nearest":ze,"nearest mipmap linear":Oe,"linear mipmap linear":Ie},f),p={none:0,browser:qe},d={uint8:ve,rgba4:$t,rgb565:Kt,"rgb5 a1":Jt},m={alpha:qt,luminance:Gt,"luminance alpha":Wt,rgb:Ht,rgba:Ut,rgba4:Yt,"rgb5 a1":Xt,rgb565:Zt},g={};n.ext_srgb&&(m.srgb=re,m.srgba=ne),n.oes_texture_float&&(d.float32=d.float=be),n.oes_texture_half_float&&(d.float16=d["half float"]=ie),n.webgl_depth_texture&&(e(m,{depth:te,"depth stencil":ee}),e(d,{uint16:ye,uint32:xe,"depth stencil":Qt})),n.webgl_compressed_texture_s3tc&&e(g,{"rgb s3tc dxt1":ae,"rgba s3tc dxt1":oe,"rgba s3tc dxt3":se,"rgba s3tc dxt5":le}),n.webgl_compressed_texture_atc&&e(g,{"rgb atc":ce,"rgba atc explicit alpha":ue,"rgba atc interpolated alpha":fe}),n.webgl_compressed_texture_pvrtc&&e(g,{"rgb pvrtc 4bppv1":he,"rgb pvrtc 2bppv1":pe,"rgba pvrtc 4bppv1":de,"rgba pvrtc 2bppv1":me}),n.webgl_compressed_texture_etc1&&(g["rgb etc1"]=ge);var v=Array.prototype.slice.call(r.getParameter(Ft));Object.keys(g).forEach(function(t){var e=g[t];v.indexOf(e)>=0&&(m[t]=e)});var y=Object.keys(m);i.textureFormats=y;var x=[];Object.keys(m).forEach(function(t){var e=m[t];x[e]=t});var b=[];Object.keys(d).forEach(function(t){var e=d[t];b[e]=t});var _=[];Object.keys(f).forEach(function(t){var e=f[t];_[e]=t});var w=[];Object.keys(h).forEach(function(t){var e=h[t];w[e]=t});var k=[];Object.keys(u).forEach(function(t){var e=u[t];k[e]=t});var M=y.reduce(function(t,e){var r=m[e];return r===Gt||r===qt||r===Gt||r===Wt||r===te||r===ee?t[r]=r:r===Xt||e.indexOf("rgba")>=0?t[r]=Ut:t[r]=Ht,t},{});function A(){this.internalformat=Ut,this.format=Ut,this.type=ve,this.compressed=!1,this.premultiplyAlpha=!1,this.flipY=!1,this.unpackAlignment=1,this.colorSpace=qe,this.width=0,this.height=0,this.channels=0}function T(t,e){t.internalformat=e.internalformat,t.format=e.format,t.type=e.type,t.compressed=e.compressed,t.premultiplyAlpha=e.premultiplyAlpha,t.flipY=e.flipY,t.unpackAlignment=e.unpackAlignment,t.colorSpace=e.colorSpace,t.width=e.width,t.height=e.height,t.channels=e.channels}function S(t,e){if("object"==typeof e&&e){if("premultiplyAlpha"in e&&(O.type(e.premultiplyAlpha,"boolean","invalid premultiplyAlpha"),t.premultiplyAlpha=e.premultiplyAlpha),"flipY"in e&&(O.type(e.flipY,"boolean","invalid texture flip"),t.flipY=e.flipY),"alignment"in e&&(O.oneOf(e.alignment,[1,2,4,8],"invalid texture unpack alignment"),t.unpackAlignment=e.alignment),"colorSpace"in e&&(O.parameter(e.colorSpace,p,"invalid colorSpace"),t.colorSpace=p[e.colorSpace]),"type"in e){var r=e.type;O(n.oes_texture_float||!("float"===r||"float32"===r),"you must enable the OES_texture_float extension in order to use floating point textures."),O(n.oes_texture_half_float||!("half float"===r||"float16"===r),"you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures."),O(n.webgl_depth_texture||!("uint16"===r||"uint32"===r||"depth stencil"===r),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),O.parameter(r,d,"invalid texture type"),t.type=d[r]}var a=t.width,o=t.height,s=t.channels,l=!1;"shape"in e?(O(Array.isArray(e.shape)&&e.shape.length>=2,"shape must be an array"),a=e.shape[0],o=e.shape[1],3===e.shape.length&&(s=e.shape[2],O(s>0&&s<=4,"invalid number of channels"),l=!0),O(a>=0&&a<=i.maxTextureSize,"invalid width"),O(o>=0&&o<=i.maxTextureSize,"invalid height")):("radius"in e&&(a=o=e.radius,O(a>=0&&a<=i.maxTextureSize,"invalid radius")),"width"in e&&(a=e.width,O(a>=0&&a<=i.maxTextureSize,"invalid width")),"height"in e&&(o=e.height,O(o>=0&&o<=i.maxTextureSize,"invalid height")),"channels"in e&&(s=e.channels,O(s>0&&s<=4,"invalid number of channels"),l=!0)),t.width=0|a,t.height=0|o,t.channels=0|s;var c=!1;if("format"in e){var u=e.format;O(n.webgl_depth_texture||!("depth"===u||"depth stencil"===u),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),O.parameter(u,m,"invalid texture format");var f=t.internalformat=m[u];t.format=M[f],u in d&&("type"in e||(t.type=d[u])),u in g&&(t.compressed=!0),c=!0}!l&&c?t.channels=Ye[t.format]:l&&!c?t.channels!==We[t.format]&&(t.format=t.internalformat=We[t.channels]):c&&l&&O(t.channels===Ye[t.format],"number of channels inconsistent with specified format")}}function E(t){r.pixelStorei(je,t.flipY),r.pixelStorei(Ve,t.premultiplyAlpha),r.pixelStorei(Ue,t.colorSpace),r.pixelStorei(Ne,t.unpackAlignment)}function C(){A.call(this),this.xOffset=0,this.yOffset=0,this.data=null,this.needsFree=!1,this.element=null,this.needsCopy=!1}function L(e,r){var n=null;if(sr(r)?n=r:r&&(O.type(r,"object","invalid pixel data type"),S(e,r),"x"in r&&(e.xOffset=0|r.x),"y"in r&&(e.yOffset=0|r.y),sr(r.data)&&(n=r.data)),O(!e.compressed||n instanceof Uint8Array,"compressed texture data must be stored in a uint8array"),r.copy){O(!n,"can not specify copy and data field for the same texture");var a=o.viewportWidth,s=o.viewportHeight;e.width=e.width||a-e.xOffset,e.height=e.height||s-e.yOffset,e.needsCopy=!0,O(e.xOffset>=0&&e.xOffset=0&&e.yOffset0&&e.width<=a&&e.height>0&&e.height<=s,"copy texture read out of bounds")}else if(n){if(t(n))e.channels=e.channels||4,e.data=n,"type"in r||e.type!==ve||(e.type=lr(n));else if(nr(n))e.channels=e.channels||4,function(t,e){var r=e.length;switch(t.type){case ve:case ye:case xe:case be:var n=tt.allocType(t.type,r);n.set(e),t.data=n;break;case ie:t.data=Dt(e);break;default:O.raise("unsupported texture type, must specify a typed array")}}(e,n),e.alignment=1,e.needsFree=!0;else if(rt(n)){var l=n.data;Array.isArray(l)||e.type!==ve||(e.type=lr(l));var c,u,f,h,p,d,m=n.shape,g=n.stride;3===m.length?(f=m[2],d=g[2]):(O(2===m.length,"invalid ndarray pixel data, must be 2 or 3D"),f=1,d=1),c=m[0],u=m[1],h=g[0],p=g[1],e.alignment=1,e.width=c,e.height=u,e.channels=f,e.format=e.internalformat=We[f],e.needsFree=!0,function(t,e,r,n,i,a){for(var o=t.width,s=t.height,l=t.channels,c=cr(t,o*s*l),u=0,f=0;f=0,"oes_texture_float extension not enabled"):e.type===ie&&O(i.extensions.indexOf("oes_texture_half_float")>=0,"oes_texture_half_float extension not enabled")}function z(t,e,n){var i=t.element,o=t.data,s=t.internalformat,l=t.format,c=t.type,u=t.width,f=t.height,h=t.channels;if(E(t),i)r.texImage2D(e,n,l,l,c,i);else if(t.compressed)r.compressedTexImage2D(e,n,s,u,f,0,o);else if(t.needsCopy)a(),r.copyTexImage2D(e,n,l,t.xOffset,t.yOffset,u,f,0);else{var p=!o;p&&(o=tt.zero.allocType(c,u*f*h)),r.texImage2D(e,n,l,u,f,0,l,c,o),p&&o&&tt.zero.freeType(o)}}function I(t,e,n,i,o){var s=t.element,l=t.data,c=t.internalformat,u=t.format,f=t.type,h=t.width,p=t.height;E(t),s?r.texSubImage2D(e,o,n,i,u,f,s):t.compressed?r.compressedTexSubImage2D(e,o,n,i,c,h,p,l):t.needsCopy?(a(),r.copyTexSubImage2D(e,o,n,i,t.xOffset,t.yOffset,h,p)):r.texSubImage2D(e,o,n,i,h,p,u,f,l)}var P=[];function D(){return P.pop()||new C}function R(t){t.needsFree&&tt.freeType(t.data),C.call(t),P.push(t)}function B(){A.call(this),this.genMipmaps=!1,this.mipmapHint=De,this.mipmask=0,this.images=Array(16)}function F(t,e,r){var n=t.images[0]=D();t.mipmask=1,n.width=t.width=e,n.height=t.height=r,n.channels=t.channels=4}function N(t,e){var r=null;if(sr(e))T(r=t.images[0]=D(),t),L(r,e),t.mipmask=1;else if(S(t,e),Array.isArray(e.mipmap))for(var n=e.mipmap,i=0;i>=i,r.height>>=i,L(r,n[i]),t.mipmask|=1<=0&&!("faces"in e)&&(t.genMipmaps=!0)}if("mag"in e){var n=e.mag;O.parameter(n,f),t.magFilter=f[n]}var a=t.wrapS,o=t.wrapT;if("wrap"in e){var s=e.wrap;"string"==typeof s?(O.parameter(s,u),a=o=u[s]):Array.isArray(s)&&(O.parameter(s[0],u),O.parameter(s[1],u),a=u[s[0]],o=u[s[1]])}else{if("wrapS"in e){var l=e.wrapS;O.parameter(l,u),a=u[l]}if("wrapT"in e){var p=e.wrapT;O.parameter(p,u),o=u[p]}}if(t.wrapS=a,t.wrapT=o,"anisotropic"in e){var d=e.anisotropic;O("number"==typeof d&&d>=1&&d<=i.maxAnisotropic,"aniso samples must be between 1 and "),t.anisotropic=e.anisotropic}if("mipmap"in e){var m=!1;switch(typeof e.mipmap){case"string":O.parameter(e.mipmap,c,"invalid mipmap hint"),t.mipmapHint=c[e.mipmap],t.genMipmaps=!0,m=!0;break;case"boolean":m=t.genMipmaps=e.mipmap;break;case"object":O(Array.isArray(e.mipmap),"invalid mipmap type"),t.genMipmaps=!1,m=!0;break;default:O.raise("invalid mipmap type")}!m||"min"in e||(t.minFilter=Le)}}function W(t,e){r.texParameteri(e,Se,t.minFilter),r.texParameteri(e,Te,t.magFilter),r.texParameteri(e,_e,t.wrapS),r.texParameteri(e,we,t.wrapT),n.ext_texture_filter_anisotropic&&r.texParameteri(e,Fe,t.anisotropic),t.genMipmaps&&(r.hint(Pe,t.mipmapHint),r.generateMipmap(e))}var Y=0,X={},Z=i.maxTextureUnits,$=Array(Z).map(function(){return null});function J(t){A.call(this),this.mipmask=0,this.internalformat=Ut,this.id=Y++,this.refCount=1,this.target=t,this.texture=r.createTexture(),this.unit=-1,this.bindCount=0,this.texInfo=new H,l.profile&&(this.stats={size:0})}function K(t){r.activeTexture(He),r.bindTexture(t.target,t.texture)}function Q(){var t=$[0];t?r.bindTexture(t.target,t.texture):r.bindTexture(Nt,null)}function et(t){var e=t.texture;O(e,"must not double destroy texture");var n=t.unit,i=t.target;n>=0&&(r.activeTexture(He+n),r.bindTexture(i,null),$[n]=null),r.deleteTexture(e),t.texture=null,t.params=null,t.pixels=null,t.refCount=0,delete X[t.id],s.textureCount--}return e(J.prototype,{bind:function(){this.bindCount+=1;var t=this.unit;if(t<0){for(var e=0;e0)continue;n.unit=-1}$[e]=this,t=e;break}t>=Z&&O.raise("insufficient number of texture units"),l.profile&&s.maxTextureUnits>l)-o,c.height=c.height||(n.height>>l)-s,O(n.type===c.type&&n.format===c.format&&n.internalformat===c.internalformat,"incompatible format for texture.subimage"),O(o>=0&&s>=0&&o+c.width<=n.width&&s+c.height<=n.height,"texture.subimage write out of bounds"),O(n.mipmask&1<>f;++f){var h=o>>f,p=s>>f;if(!h||!p)break;i=tt.zero.allocType(u,h*p*c),r.texImage2D(Nt,f,n.format,h,p,0,n.format,n.type,i),i&&tt.zero.freeType(i)}return Q(),l.profile&&(n.stats.size=fr(n.internalformat,n.type,o,s,!1,!1)),a},a._reglType="texture2d",a._texture=n,l.profile&&(a.stats=n.stats),a.destroy=function(){n.decRef()},a},createCube:function(t,e,n,a,o,c){var u=new J(jt);X[u.id]=u,s.cubeCount++;var f=new Array(6);function h(t,e,r,n,a,o){var s,c=u.texInfo;for(H.call(c),s=0;s<6;++s)f[s]=U();if("number"!=typeof t&&t)if("object"==typeof t)if(e)N(f[0],t),N(f[1],e),N(f[2],r),N(f[3],n),N(f[4],a),N(f[5],o);else if(G(c,t),S(u,t),"faces"in t){var p=t.faces;for(O(Array.isArray(p)&&6===p.length,"cube faces must be a length 6 array"),s=0;s<6;++s)O("object"==typeof p[s]&&!!p[s],"invalid input for cube map face"),T(f[s],u),N(f[s],p[s])}else for(s=0;s<6;++s)N(f[s],t);else O.raise("invalid arguments to cube map");else{var d=0|t||1;for(s=0;s<6;++s)F(f[s],d,d)}for(T(u,f[0]),i.npotTextureCube||O(Bt(u.width)&&Bt(u.height),"your browser does not support non power or two texture dimensions"),c.genMipmaps?u.mipmask=(f[0].width<<1)-1:u.mipmask=f[0].mipmask,O.textureCube(u,c,f,i),u.internalformat=f[0].internalformat,h.width=f[0].width,h.height=f[0].height,K(u),s=0;s<6;++s)j(f[s],Vt+s);for(W(c,jt),Q(),l.profile&&(u.stats.size=fr(u.internalformat,u.type,h.width,h.height,c.genMipmaps,!0)),h.format=x[u.internalformat],h.type=b[u.type],h.mag=_[c.magFilter],h.min=w[c.minFilter],h.wrapS=k[c.wrapS],h.wrapT=k[c.wrapT],s=0;s<6;++s)q(f[s]);return h}return h(t,e,n,a,o,c),h.subimage=function(t,e,r,n,i){O(!!e,"must specify image data"),O("number"==typeof t&&t===(0|t)&&t>=0&&t<6,"invalid face");var a=0|r,o=0|n,s=0|i,l=D();return T(l,u),l.width=0,l.height=0,L(l,e),l.width=l.width||(u.width>>s)-a,l.height=l.height||(u.height>>s)-o,O(u.type===l.type&&u.format===l.format&&u.internalformat===l.internalformat,"incompatible format for texture.subimage"),O(a>=0&&o>=0&&a+l.width<=u.width&&o+l.height<=u.height,"texture.subimage write out of bounds"),O(u.mipmask&1<>i;++i)r.texImage2D(Vt+n,i,u.format,e>>i,e>>i,0,u.format,u.type,null);return Q(),l.profile&&(u.stats.size=fr(u.internalformat,u.type,h.width,h.height,!1,!0)),h}},h._reglType="textureCube",h._texture=u,l.profile&&(h.stats=u.stats),h.destroy=function(){u.decRef()},h},clear:function(){for(var t=0;t>e,t.height>>e,0,t.internalformat,t.type,null);else for(var n=0;n<6;++n)r.texImage2D(Vt+n,e,t.internalformat,t.width>>e,t.height>>e,0,t.internalformat,t.type,null);W(t.texInfo,t.target)})}}}rr[Yt]=2,rr[Xt]=2,rr[Zt]=2,rr[ee]=4,rr[ae]=.5,rr[oe]=.5,rr[se]=1,rr[le]=1,rr[ce]=.5,rr[ue]=1,rr[fe]=1,rr[he]=.5,rr[pe]=.25,rr[de]=.5,rr[me]=.25,rr[ge]=.5;var pr=36161,dr=32854,mr=[];function gr(t,e,r){return mr[t]*e*r}mr[dr]=2,mr[32855]=2,mr[36194]=2,mr[33189]=2,mr[36168]=1,mr[34041]=4,mr[35907]=4,mr[34836]=16,mr[34842]=8,mr[34843]=6;var vr=function(t,e,r,n,i){var a={rgba4:dr,rgb565:36194,"rgb5 a1":32855,depth:33189,stencil:36168,"depth stencil":34041};e.ext_srgb&&(a.srgba=35907),e.ext_color_buffer_half_float&&(a.rgba16f=34842,a.rgb16f=34843),e.webgl_color_buffer_float&&(a.rgba32f=34836);var o=[];Object.keys(a).forEach(function(t){var e=a[t];o[e]=t});var s=0,l={};function c(t){this.id=s++,this.refCount=1,this.renderbuffer=t,this.format=dr,this.width=0,this.height=0,i.profile&&(this.stats={size:0})}function u(e){var r=e.renderbuffer;O(r,"must not double destroy renderbuffer"),t.bindRenderbuffer(pr,null),t.deleteRenderbuffer(r),e.renderbuffer=null,e.refCount=0,delete l[e.id],n.renderbufferCount--}return c.prototype.decRef=function(){--this.refCount<=0&&u(this)},i.profile&&(n.getTotalRenderbufferSize=function(){var t=0;return Object.keys(l).forEach(function(e){t+=l[e].stats.size}),t}),{create:function(e,s){var u=new c(t.createRenderbuffer());function f(e,n){var s=0,l=0,c=dr;if("object"==typeof e&&e){var h=e;if("shape"in h){var p=h.shape;O(Array.isArray(p)&&p.length>=2,"invalid renderbuffer shape"),s=0|p[0],l=0|p[1]}else"radius"in h&&(s=l=0|h.radius),"width"in h&&(s=0|h.width),"height"in h&&(l=0|h.height);"format"in h&&(O.parameter(h.format,a,"invalid renderbuffer format"),c=a[h.format])}else"number"==typeof e?(s=0|e,l="number"==typeof n?0|n:s):e?O.raise("invalid arguments to renderbuffer constructor"):s=l=1;if(O(s>0&&l>0&&s<=r.maxRenderbufferSize&&l<=r.maxRenderbufferSize,"invalid renderbuffer size"),s!==u.width||l!==u.height||c!==u.format)return f.width=u.width=s,f.height=u.height=l,u.format=c,t.bindRenderbuffer(pr,u.renderbuffer),t.renderbufferStorage(pr,c,s,l),O(0===t.getError(),"invalid render buffer format"),i.profile&&(u.stats.size=gr(u.format,u.width,u.height)),f.format=o[u.format],f}return l[u.id]=u,n.renderbufferCount++,f(e,s),f.resize=function(e,n){var a=0|e,o=0|n||a;return a===u.width&&o===u.height?f:(O(a>0&&o>0&&a<=r.maxRenderbufferSize&&o<=r.maxRenderbufferSize,"invalid renderbuffer size"),f.width=u.width=a,f.height=u.height=o,t.bindRenderbuffer(pr,u.renderbuffer),t.renderbufferStorage(pr,u.format,a,o),O(0===t.getError(),"invalid render buffer format"),i.profile&&(u.stats.size=gr(u.format,u.width,u.height)),f)},f._reglType="renderbuffer",f._renderbuffer=u,i.profile&&(f.stats=u.stats),f.destroy=function(){u.decRef()},f},clear:function(){nt(l).forEach(u)},restore:function(){nt(l).forEach(function(e){e.renderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(pr,e.renderbuffer),t.renderbufferStorage(pr,e.format,e.width,e.height)}),t.bindRenderbuffer(pr,null)}}},yr=36160,xr=36161,br=3553,_r=34069,wr=36064,kr=36096,Mr=36128,Ar=33306,Tr=36053,Sr=6402,Er=[6407,6408],Cr=[];Cr[6408]=4,Cr[6407]=3;var Lr=[];Lr[5121]=1,Lr[5126]=4,Lr[36193]=2;var zr=33189,Or=36168,Ir=34041,Pr=[32854,32855,36194,35907,34842,34843,34836],Dr={};Dr[Tr]="complete",Dr[36054]="incomplete attachment",Dr[36057]="incomplete dimensions",Dr[36055]="incomplete, missing attachment",Dr[36061]="unsupported";var Rr=5126;function Br(){this.state=0,this.x=0,this.y=0,this.z=0,this.w=0,this.buffer=null,this.size=0,this.normalized=!1,this.type=Rr,this.offset=0,this.stride=0,this.divisor=0}var Fr=35632,Nr=35633,jr=35718,Vr=35721;var Ur=6408,qr=5121,Hr=3333,Gr=5126;function Wr(e,r,n,i,a,o,s){function l(l){var c;null===r.next?(O(a.preserveDrawingBuffer,'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer'),c=qr):(O(null!==r.next.colorAttachments[0].texture,"You cannot read from a renderbuffer"),c=r.next.colorAttachments[0].texture._texture.type,o.oes_texture_float?(O(c===qr||c===Gr,"Reading from a framebuffer is only allowed for the types 'uint8' and 'float'"),c===Gr&&O(s.readFloat,"Reading 'float' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float")):O(c===qr,"Reading from a framebuffer is only allowed for the type 'uint8'"));var u=0,f=0,h=i.framebufferWidth,p=i.framebufferHeight,d=null;t(l)?d=l:l&&(O.type(l,"object","invalid arguments to regl.read()"),u=0|l.x,f=0|l.y,O(u>=0&&u=0&&f0&&h+u<=i.framebufferWidth,"invalid width for read pixels"),O(p>0&&p+f<=i.framebufferHeight,"invalid height for read pixels"),n();var m=h*p*4;return d||(c===qr?d=new Uint8Array(m):c===Gr&&(d=d||new Float32Array(m))),O.isTypedArray(d,"data buffer for regl.read() must be a typedarray"),O(d.byteLength>=m,"data buffer for regl.read() too small"),e.pixelStorei(Hr,4),e.readPixels(u,f,h,p,Ur,c,d),d}return function(t){return t&&"framebuffer"in t?function(t){var e;return r.setFBO({framebuffer:t.framebuffer},function(){e=l(t)}),e}(t):l(t)}}function Yr(t){return Array.prototype.slice.call(t)}function Xr(t){return Yr(t).join("")}var Zr="xyzw".split(""),$r=5121,Jr=1,Kr=2,Qr=0,tn=1,en=2,rn=3,nn=4,an="dither",on="blend.enable",sn="blend.color",ln="blend.equation",cn="blend.func",un="depth.enable",fn="depth.func",hn="depth.range",pn="depth.mask",dn="colorMask",mn="cull.enable",gn="cull.face",vn="frontFace",yn="lineWidth",xn="polygonOffset.enable",bn="polygonOffset.offset",_n="sample.alpha",wn="sample.enable",kn="sample.coverage",Mn="stencil.enable",An="stencil.mask",Tn="stencil.func",Sn="stencil.opFront",En="stencil.opBack",Cn="scissor.enable",Ln="scissor.box",zn="viewport",On="profile",In="framebuffer",Pn="vert",Dn="frag",Rn="elements",Bn="primitive",Fn="count",Nn="offset",jn="instances",Vn=In+"Width",Un=In+"Height",qn=zn+"Width",Hn=zn+"Height",Gn="drawingBufferWidth",Wn="drawingBufferHeight",Yn=[cn,ln,Tn,Sn,En,kn,zn,Ln,bn],Xn=34962,Zn=34963,$n=3553,Jn=34067,Kn=2884,Qn=3042,ti=3024,ei=2960,ri=2929,ni=3089,ii=32823,ai=32926,oi=32928,si=5126,li=35664,ci=35665,ui=35666,fi=5124,hi=35667,pi=35668,di=35669,mi=35670,gi=35671,vi=35672,yi=35673,xi=35674,bi=35675,_i=35676,wi=35678,ki=35680,Mi=4,Ai=1028,Ti=1029,Si=2304,Ei=2305,Ci=32775,Li=32776,zi=519,Oi=7680,Ii=0,Pi=1,Di=32774,Ri=513,Bi=36160,Fi=36064,Ni={0:0,1:1,zero:0,one:1,"src color":768,"one minus src color":769,"src alpha":770,"one minus src alpha":771,"dst color":774,"one minus dst color":775,"dst alpha":772,"one minus dst alpha":773,"constant color":32769,"one minus constant color":32770,"constant alpha":32771,"one minus constant alpha":32772,"src alpha saturate":776},ji=["constant color, constant alpha","one minus constant color, constant alpha","constant color, one minus constant alpha","one minus constant color, one minus constant alpha","constant alpha, constant color","constant alpha, one minus constant color","one minus constant alpha, constant color","one minus constant alpha, one minus constant color"],Vi={never:512,less:513,"<":513,equal:514,"=":514,"==":514,"===":514,lequal:515,"<=":515,greater:516,">":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519},Ui={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},qi={frag:35632,vert:35633},Hi={cw:Si,ccw:Ei};function Gi(e){return Array.isArray(e)||t(e)||rt(e)}function Wi(t){return t.sort(function(t,e){return t===zn?-1:e===zn?1:t=1,n>=2,e)}if(r===nn){var i=t.data;return new Yi(i.thisDep,i.contextDep,i.propDep,e)}return new Yi(r===rn,r===en,r===tn,e)}var Ji=new Yi(!1,!1,!1,function(){});function Ki(t,r,n,i,a,o,s,l,c,u,f,h,p,d,m){var g=u.Record,v={add:32774,subtract:32778,"reverse subtract":32779};n.ext_blend_minmax&&(v.min=Ci,v.max=Li);var y=n.angle_instanced_arrays,x=n.webgl_draw_buffers,b={dirty:!0,profile:m.profile},_={},w=[],k={},M={};function A(t){return t.replace(".","_")}function T(t,e,r){var n=A(t);w.push(t),_[n]=b[n]=!!r,k[n]=e}function S(t,e,r){var n=A(t);w.push(t),Array.isArray(r)?(b[n]=r.slice(),_[n]=r.slice()):b[n]=_[n]=r,M[n]=e}T(an,ti),T(on,Qn),S(sn,"blendColor",[0,0,0,0]),S(ln,"blendEquationSeparate",[Di,Di]),S(cn,"blendFuncSeparate",[Pi,Ii,Pi,Ii]),T(un,ri,!0),S(fn,"depthFunc",Ri),S(hn,"depthRange",[0,1]),S(pn,"depthMask",!0),S(dn,dn,[!0,!0,!0,!0]),T(mn,Kn),S(gn,"cullFace",Ti),S(vn,vn,Ei),S(yn,yn,1),T(xn,ii),S(bn,"polygonOffset",[0,0]),T(_n,ai),T(wn,oi),S(kn,"sampleCoverage",[1,!1]),T(Mn,ei),S(An,"stencilMask",-1),S(Tn,"stencilFunc",[zi,0,-1]),S(Sn,"stencilOpSeparate",[Ai,Oi,Oi,Oi]),S(En,"stencilOpSeparate",[Ti,Oi,Oi,Oi]),T(Cn,ni),S(Ln,"scissor",[0,0,t.drawingBufferWidth,t.drawingBufferHeight]),S(zn,zn,[0,0,t.drawingBufferWidth,t.drawingBufferHeight]);var E={gl:t,context:p,strings:r,next:_,current:b,draw:h,elements:o,buffer:a,shader:f,attributes:u.state,uniforms:c,framebuffer:l,extensions:n,timer:d,isBufferArgs:Gi},C={primTypes:xt,compareFuncs:Vi,blendFuncs:Ni,blendEquations:v,stencilOps:Ui,glTypes:st,orientationType:Hi};O.optional(function(){E.isArrayLike=Rt}),x&&(C.backBuffer=[Ti],C.drawBuffer=H(i.maxDrawbuffers,function(t){return 0===t?[0]:H(t,function(t){return Fi+t})}));var L=0;function z(){var t=function(){var t=0,r=[],n=[];function i(){var r=[],n=[];return e(function(){r.push.apply(r,Yr(arguments))},{def:function(){var e="v"+t++;return n.push(e),arguments.length>0&&(r.push(e,"="),r.push.apply(r,Yr(arguments)),r.push(";")),e},toString:function(){return Xr([n.length>0?"var "+n+";":"",Xr(r)])}})}function a(){var t=i(),r=i(),n=t.toString,a=r.toString;function o(e,n){r(e,n,"=",t.def(e,n),";")}return e(function(){t.apply(t,Yr(arguments))},{def:t.def,entry:t,exit:r,save:o,set:function(e,r,n){o(e,r),t(e,r,"=",n,";")},toString:function(){return n()+a()}})}var o=i(),s={};return{global:o,link:function(e){for(var i=0;i=0,'unknown parameter "'+e+'"',c.commandStr)})}e(u),e(h)});var p=function(t,e){var r=t.static,n=t.dynamic;if(In in r){var i=r[In];return i?(i=l.getFramebuffer(i),O.command(i,"invalid framebuffer object"),Zi(function(t,e){var r=t.link(i),n=t.shared;e.set(n.framebuffer,".next",r);var a=n.context;return e.set(a,"."+Vn,r+".width"),e.set(a,"."+Un,r+".height"),r})):Zi(function(t,e){var r=t.shared;e.set(r.framebuffer,".next","null");var n=r.context;return e.set(n,"."+Vn,n+"."+Gn),e.set(n,"."+Un,n+"."+Wn),"null"})}if(In in n){var a=n[In];return $i(a,function(t,e){var r=t.invoke(e,a),n=t.shared,i=n.framebuffer,o=e.def(i,".getFramebuffer(",r,")");O.optional(function(){t.assert(e,"!"+r+"||"+o,"invalid framebuffer object")}),e.set(i,".next",o);var s=n.context;return e.set(s,"."+Vn,o+"?"+o+".width:"+s+"."+Gn),e.set(s,"."+Un,o+"?"+o+".height:"+s+"."+Wn),o})}return null}(t),d=function(t,e,r){var n=t.static,i=t.dynamic;function a(t){if(t in n){var a=n[t];O.commandType(a,"object","invalid "+t,r.commandStr);var o,s,l=!0,c=0|a.x,u=0|a.y;return"width"in a?(o=0|a.width,O.command(o>=0,"invalid "+t,r.commandStr)):l=!1,"height"in a?(s=0|a.height,O.command(s>=0,"invalid "+t,r.commandStr)):l=!1,new Yi(!l&&e&&e.thisDep,!l&&e&&e.contextDep,!l&&e&&e.propDep,function(t,e){var r=t.shared.context,n=o;"width"in a||(n=e.def(r,".",Vn,"-",c));var i=s;return"height"in a||(i=e.def(r,".",Un,"-",u)),[c,u,n,i]})}if(t in i){var f=i[t],h=$i(f,function(e,r){var n=e.invoke(r,f);O.optional(function(){e.assert(r,n+"&&typeof "+n+'==="object"',"invalid "+t)});var i=e.shared.context,a=r.def(n,".x|0"),o=r.def(n,".y|0"),s=r.def('"width" in ',n,"?",n,".width|0:","(",i,".",Vn,"-",a,")"),l=r.def('"height" in ',n,"?",n,".height|0:","(",i,".",Un,"-",o,")");return O.optional(function(){e.assert(r,s+">=0&&"+l+">=0","invalid "+t)}),[a,o,s,l]});return e&&(h.thisDep=h.thisDep||e.thisDep,h.contextDep=h.contextDep||e.contextDep,h.propDep=h.propDep||e.propDep),h}return e?new Yi(e.thisDep,e.contextDep,e.propDep,function(t,e){var r=t.shared.context;return[0,0,e.def(r,".",Vn),e.def(r,".",Un)]}):null}var o=a(zn);if(o){var s=o;o=new Yi(o.thisDep,o.contextDep,o.propDep,function(t,e){var r=s.append(t,e),n=t.shared.context;return e.set(n,"."+qn,r[2]),e.set(n,"."+Hn,r[3]),r})}return{viewport:o,scissor_box:a(Ln)}}(t,p,c),m=function(t,e){var r=t.static,n=t.dynamic,i=function(){if(Rn in r){var t=r[Rn];Gi(t)?t=o.getElements(o.create(t,!0)):t&&(t=o.getElements(t),O.command(t,"invalid elements",e.commandStr));var i=Zi(function(e,r){if(t){var n=e.link(t);return e.ELEMENTS=n,n}return e.ELEMENTS=null,null});return i.value=t,i}if(Rn in n){var a=n[Rn];return $i(a,function(t,e){var r=t.shared,n=r.isBufferArgs,i=r.elements,o=t.invoke(e,a),s=e.def("null"),l=e.def(n,"(",o,")"),c=t.cond(l).then(s,"=",i,".createStream(",o,");").else(s,"=",i,".getElements(",o,");");return O.optional(function(){t.assert(c.else,"!"+o+"||"+s,"invalid elements")}),e.entry(c),e.exit(t.cond(l).then(i,".destroyStream(",s,");")),t.ELEMENTS=s,s})}return null}();function a(t,a){if(t in r){var o=0|r[t];return O.command(!a||o>=0,"invalid "+t,e.commandStr),Zi(function(t,e){return a&&(t.OFFSET=o),o})}if(t in n){var s=n[t];return $i(s,function(e,r){var n=e.invoke(r,s);return a&&(e.OFFSET=n,O.optional(function(){e.assert(r,n+">=0","invalid "+t)})),n})}return a&&i?Zi(function(t,e){return t.OFFSET="0",0}):null}var s=a(Nn,!0);return{elements:i,primitive:function(){if(Bn in r){var t=r[Bn];return O.commandParameter(t,xt,"invalid primitve",e.commandStr),Zi(function(e,r){return xt[t]})}if(Bn in n){var a=n[Bn];return $i(a,function(t,e){var r=t.constants.primTypes,n=t.invoke(e,a);return O.optional(function(){t.assert(e,n+" in "+r,"invalid primitive, must be one of "+Object.keys(xt))}),e.def(r,"[",n,"]")})}return i?Xi(i)?i.value?Zi(function(t,e){return e.def(t.ELEMENTS,".primType")}):Zi(function(){return Mi}):new Yi(i.thisDep,i.contextDep,i.propDep,function(t,e){var r=t.ELEMENTS;return e.def(r,"?",r,".primType:",Mi)}):null}(),count:function(){if(Fn in r){var t=0|r[Fn];return O.command("number"==typeof t&&t>=0,"invalid vertex count",e.commandStr),Zi(function(){return t})}if(Fn in n){var a=n[Fn];return $i(a,function(t,e){var r=t.invoke(e,a);return O.optional(function(){t.assert(e,"typeof "+r+'==="number"&&'+r+">=0&&"+r+"===("+r+"|0)","invalid vertex count")}),r})}if(i){if(Xi(i)){if(i)return s?new Yi(s.thisDep,s.contextDep,s.propDep,function(t,e){var r=e.def(t.ELEMENTS,".vertCount-",t.OFFSET);return O.optional(function(){t.assert(e,r+">=0","invalid vertex offset/element buffer too small")}),r}):Zi(function(t,e){return e.def(t.ELEMENTS,".vertCount")});var o=Zi(function(){return-1});return O.optional(function(){o.MISSING=!0}),o}var l=new Yi(i.thisDep||s.thisDep,i.contextDep||s.contextDep,i.propDep||s.propDep,function(t,e){var r=t.ELEMENTS;return t.OFFSET?e.def(r,"?",r,".vertCount-",t.OFFSET,":-1"):e.def(r,"?",r,".vertCount:-1")});return O.optional(function(){l.DYNAMIC=!0}),l}return null}(),instances:a(jn,!1),offset:s}}(t,c),x=function(t,e){var r=t.static,n=t.dynamic,a={};return w.forEach(function(t){var o=A(t);function s(e,i){if(t in r){var s=e(r[t]);a[o]=Zi(function(){return s})}else if(t in n){var l=n[t];a[o]=$i(l,function(t,e){return i(t,e,t.invoke(e,l))})}}switch(t){case mn:case on:case an:case Mn:case un:case Cn:case xn:case _n:case wn:case pn:return s(function(r){return O.commandType(r,"boolean",t,e.commandStr),r},function(e,r,n){return O.optional(function(){e.assert(r,"typeof "+n+'==="boolean"',"invalid flag "+t,e.commandStr)}),n});case fn:return s(function(r){return O.commandParameter(r,Vi,"invalid "+t,e.commandStr),Vi[r]},function(e,r,n){var i=e.constants.compareFuncs;return O.optional(function(){e.assert(r,n+" in "+i,"invalid "+t+", must be one of "+Object.keys(Vi))}),r.def(i,"[",n,"]")});case hn:return s(function(t){return O.command(Rt(t)&&2===t.length&&"number"==typeof t[0]&&"number"==typeof t[1]&&t[0]<=t[1],"depth range is 2d array",e.commandStr),t},function(t,e,r){return O.optional(function(){t.assert(e,t.shared.isArrayLike+"("+r+")&&"+r+".length===2&&typeof "+r+'[0]==="number"&&typeof '+r+'[1]==="number"&&'+r+"[0]<="+r+"[1]","depth range must be a 2d array")}),[e.def("+",r,"[0]"),e.def("+",r,"[1]")]});case cn:return s(function(t){O.commandType(t,"object","blend.func",e.commandStr);var r="srcRGB"in t?t.srcRGB:t.src,n="srcAlpha"in t?t.srcAlpha:t.src,i="dstRGB"in t?t.dstRGB:t.dst,a="dstAlpha"in t?t.dstAlpha:t.dst;return O.commandParameter(r,Ni,o+".srcRGB",e.commandStr),O.commandParameter(n,Ni,o+".srcAlpha",e.commandStr),O.commandParameter(i,Ni,o+".dstRGB",e.commandStr),O.commandParameter(a,Ni,o+".dstAlpha",e.commandStr),O.command(-1===ji.indexOf(r+", "+i),"unallowed blending combination (srcRGB, dstRGB) = ("+r+", "+i+")",e.commandStr),[Ni[r],Ni[i],Ni[n],Ni[a]]},function(e,r,n){var i=e.constants.blendFuncs;function a(a,o){var s=r.def('"',a,o,'" in ',n,"?",n,".",a,o,":",n,".",a);return O.optional(function(){e.assert(r,s+" in "+i,"invalid "+t+"."+a+o+", must be one of "+Object.keys(Ni))}),s}O.optional(function(){e.assert(r,n+"&&typeof "+n+'==="object"',"invalid blend func, must be an object")});var o=a("src","RGB"),s=a("dst","RGB");O.optional(function(){var t=e.constants.invalidBlendCombinations;e.assert(r,t+".indexOf("+o+'+", "+'+s+") === -1 ","unallowed blending combination for (srcRGB, dstRGB)")});var l=r.def(i,"[",o,"]"),c=r.def(i,"[",a("src","Alpha"),"]");return[l,r.def(i,"[",s,"]"),c,r.def(i,"[",a("dst","Alpha"),"]")]});case ln:return s(function(r){return"string"==typeof r?(O.commandParameter(r,v,"invalid "+t,e.commandStr),[v[r],v[r]]):"object"==typeof r?(O.commandParameter(r.rgb,v,t+".rgb",e.commandStr),O.commandParameter(r.alpha,v,t+".alpha",e.commandStr),[v[r.rgb],v[r.alpha]]):void O.commandRaise("invalid blend.equation",e.commandStr)},function(e,r,n){var i=e.constants.blendEquations,a=r.def(),o=r.def(),s=e.cond("typeof ",n,'==="string"');return O.optional(function(){function r(t,r,n){e.assert(t,n+" in "+i,"invalid "+r+", must be one of "+Object.keys(v))}r(s.then,t,n),e.assert(s.else,n+"&&typeof "+n+'==="object"',"invalid "+t),r(s.else,t+".rgb",n+".rgb"),r(s.else,t+".alpha",n+".alpha")}),s.then(a,"=",o,"=",i,"[",n,"];"),s.else(a,"=",i,"[",n,".rgb];",o,"=",i,"[",n,".alpha];"),r(s),[a,o]});case sn:return s(function(t){return O.command(Rt(t)&&4===t.length,"blend.color must be a 4d array",e.commandStr),H(4,function(e){return+t[e]})},function(t,e,r){return O.optional(function(){t.assert(e,t.shared.isArrayLike+"("+r+")&&"+r+".length===4","blend.color must be a 4d array")}),H(4,function(t){return e.def("+",r,"[",t,"]")})});case An:return s(function(t){return O.commandType(t,"number",o,e.commandStr),0|t},function(t,e,r){return O.optional(function(){t.assert(e,"typeof "+r+'==="number"',"invalid stencil.mask")}),e.def(r,"|0")});case Tn:return s(function(r){O.commandType(r,"object",o,e.commandStr);var n=r.cmp||"keep",i=r.ref||0,a="mask"in r?r.mask:-1;return O.commandParameter(n,Vi,t+".cmp",e.commandStr),O.commandType(i,"number",t+".ref",e.commandStr),O.commandType(a,"number",t+".mask",e.commandStr),[Vi[n],i,a]},function(t,e,r){var n=t.constants.compareFuncs;return O.optional(function(){function i(){t.assert(e,Array.prototype.join.call(arguments,""),"invalid stencil.func")}i(r+"&&typeof ",r,'==="object"'),i('!("cmp" in ',r,")||(",r,".cmp in ",n,")")}),[e.def('"cmp" in ',r,"?",n,"[",r,".cmp]",":",Oi),e.def(r,".ref|0"),e.def('"mask" in ',r,"?",r,".mask|0:-1")]});case Sn:case En:return s(function(r){O.commandType(r,"object",o,e.commandStr);var n=r.fail||"keep",i=r.zfail||"keep",a=r.zpass||"keep";return O.commandParameter(n,Ui,t+".fail",e.commandStr),O.commandParameter(i,Ui,t+".zfail",e.commandStr),O.commandParameter(a,Ui,t+".zpass",e.commandStr),[t===En?Ti:Ai,Ui[n],Ui[i],Ui[a]]},function(e,r,n){var i=e.constants.stencilOps;function a(a){return O.optional(function(){e.assert(r,'!("'+a+'" in '+n+")||("+n+"."+a+" in "+i+")","invalid "+t+"."+a+", must be one of "+Object.keys(Ui))}),r.def('"',a,'" in ',n,"?",i,"[",n,".",a,"]:",Oi)}return O.optional(function(){e.assert(r,n+"&&typeof "+n+'==="object"',"invalid "+t)}),[t===En?Ti:Ai,a("fail"),a("zfail"),a("zpass")]});case bn:return s(function(t){O.commandType(t,"object",o,e.commandStr);var r=0|t.factor,n=0|t.units;return O.commandType(r,"number",o+".factor",e.commandStr),O.commandType(n,"number",o+".units",e.commandStr),[r,n]},function(e,r,n){return O.optional(function(){e.assert(r,n+"&&typeof "+n+'==="object"',"invalid "+t)}),[r.def(n,".factor|0"),r.def(n,".units|0")]});case gn:return s(function(t){var r=0;return"front"===t?r=Ai:"back"===t&&(r=Ti),O.command(!!r,o,e.commandStr),r},function(t,e,r){return O.optional(function(){t.assert(e,r+'==="front"||'+r+'==="back"',"invalid cull.face")}),e.def(r,'==="front"?',Ai,":",Ti)});case yn:return s(function(t){return O.command("number"==typeof t&&t>=i.lineWidthDims[0]&&t<=i.lineWidthDims[1],"invalid line width, must be a positive number between "+i.lineWidthDims[0]+" and "+i.lineWidthDims[1],e.commandStr),t},function(t,e,r){return O.optional(function(){t.assert(e,"typeof "+r+'==="number"&&'+r+">="+i.lineWidthDims[0]+"&&"+r+"<="+i.lineWidthDims[1],"invalid line width")}),r});case vn:return s(function(t){return O.commandParameter(t,Hi,o,e.commandStr),Hi[t]},function(t,e,r){return O.optional(function(){t.assert(e,r+'==="cw"||'+r+'==="ccw"',"invalid frontFace, must be one of cw,ccw")}),e.def(r+'==="cw"?'+Si+":"+Ei)});case dn:return s(function(t){return O.command(Rt(t)&&4===t.length,"color.mask must be length 4 array",e.commandStr),t.map(function(t){return!!t})},function(t,e,r){return O.optional(function(){t.assert(e,t.shared.isArrayLike+"("+r+")&&"+r+".length===4","invalid color.mask")}),H(4,function(t){return"!!"+r+"["+t+"]"})});case kn:return s(function(t){O.command("object"==typeof t&&t,o,e.commandStr);var r="value"in t?t.value:1,n=!!t.invert;return O.command("number"==typeof r&&r>=0&&r<=1,"sample.coverage.value must be a number between 0 and 1",e.commandStr),[r,n]},function(t,e,r){return O.optional(function(){t.assert(e,r+"&&typeof "+r+'==="object"',"invalid sample.coverage")}),[e.def('"value" in ',r,"?+",r,".value:1"),e.def("!!",r,".invert")]})}}),a}(t,c),b=function(t){var e=t.static,n=t.dynamic;function i(t){if(t in e){var i=r.id(e[t]);O.optional(function(){f.shader(qi[t],i,O.guessCommand())});var a=Zi(function(){return i});return a.id=i,a}if(t in n){var o=n[t];return $i(o,function(e,r){var n=e.invoke(r,o),i=r.def(e.shared.strings,".id(",n,")");return O.optional(function(){r(e.shared.shader,".shader(",qi[t],",",i,",",e.command,");")}),i})}return null}var a,o=i(Dn),s=i(Pn),l=null;return Xi(o)&&Xi(s)?(l=f.program(s.id,o.id),a=Zi(function(t,e){return t.link(l)})):a=new Yi(o&&o.thisDep||s&&s.thisDep,o&&o.contextDep||s&&s.contextDep,o&&o.propDep||s&&s.propDep,function(t,e){var r,n=t.shared.shader;r=o?o.append(t,e):e.def(n,".",Dn);var i=n+".program("+(s?s.append(t,e):e.def(n,".",Pn))+","+r;return O.optional(function(){i+=","+t.command}),e.def(i+")")}),{frag:o,vert:s,progVar:a,program:l}}(t);function _(t){var e=d[t];e&&(x[t]=e)}_(zn),_(A(Ln));var k=Object.keys(x).length>0,M={framebuffer:p,draw:m,shader:b,state:x,dirty:k};return M.profile=function(t){var e,r=t.static,n=t.dynamic;if(On in r){var i=!!r[On];(e=Zi(function(t,e){return i})).enable=i}else if(On in n){var a=n[On];e=$i(a,function(t,e){return t.invoke(e,a)})}return e}(t),M.uniforms=function(t,e){var r=t.static,n=t.dynamic,i={};return Object.keys(r).forEach(function(t){var n,a=r[t];if("number"==typeof a||"boolean"==typeof a)n=Zi(function(){return a});else if("function"==typeof a){var o=a._reglType;"texture2d"===o||"textureCube"===o?n=Zi(function(t){return t.link(a)}):"framebuffer"===o||"framebufferCube"===o?(O.command(a.color.length>0,'missing color attachment for framebuffer sent to uniform "'+t+'"',e.commandStr),n=Zi(function(t){return t.link(a.color[0])})):O.commandRaise('invalid data for uniform "'+t+'"',e.commandStr)}else Rt(a)?n=Zi(function(e){return e.global.def("[",H(a.length,function(r){return O.command("number"==typeof a[r]||"boolean"==typeof a[r],"invalid uniform "+t,e.commandStr),a[r]}),"]")}):O.commandRaise('invalid or missing data for uniform "'+t+'"',e.commandStr);n.value=a,i[t]=n}),Object.keys(n).forEach(function(t){var e=n[t];i[t]=$i(e,function(t,r){return t.invoke(r,e)})}),i}(n,c),M.attributes=function(t,e){var n=t.static,i=t.dynamic,o={};return Object.keys(n).forEach(function(t){var i=n[t],s=r.id(t),l=new g;if(Gi(i))l.state=Jr,l.buffer=a.getBuffer(a.create(i,Xn,!1,!0)),l.type=0;else{var c=a.getBuffer(i);if(c)l.state=Jr,l.buffer=c,l.type=0;else if(O.command("object"==typeof i&&i,"invalid data for attribute "+t,e.commandStr),"constant"in i){var u=i.constant;l.buffer="null",l.state=Kr,"number"==typeof u?l.x=u:(O.command(Rt(u)&&u.length>0&&u.length<=4,"invalid constant for attribute "+t,e.commandStr),Zr.forEach(function(t,e){e=0,'invalid offset for attribute "'+t+'"',e.commandStr);var h=0|i.stride;O.command(h>=0&&h<256,'invalid stride for attribute "'+t+'", must be integer betweeen [0, 255]',e.commandStr);var p=0|i.size;O.command(!("size"in i)||p>0&&p<=4,'invalid size for attribute "'+t+'", must be 1,2,3,4',e.commandStr);var d=!!i.normalized,m=0;"type"in i&&(O.commandParameter(i.type,st,"invalid type for attribute "+t,e.commandStr),m=st[i.type]);var v=0|i.divisor;"divisor"in i&&(O.command(0===v||y,'cannot specify divisor for attribute "'+t+'", instancing not supported',e.commandStr),O.command(v>=0,'invalid divisor for attribute "'+t+'"',e.commandStr)),O.optional(function(){var r=e.commandStr,n=["buffer","offset","divisor","normalized","type","size","stride"];Object.keys(i).forEach(function(e){O.command(n.indexOf(e)>=0,'unknown parameter "'+e+'" for attribute pointer "'+t+'" (valid parameters are '+n+")",r)})}),l.buffer=c,l.state=Jr,l.size=p,l.normalized=d,l.type=m||c.dtype,l.offset=f,l.stride=h,l.divisor=v}}o[t]=Zi(function(t,e){var r=t.attribCache;if(s in r)return r[s];var n={isStream:!1};return Object.keys(l).forEach(function(t){n[t]=l[t]}),l.buffer&&(n.buffer=t.link(l.buffer),n.type=n.type||n.buffer+".dtype"),r[s]=n,n})}),Object.keys(i).forEach(function(t){var e=i[t];o[t]=$i(e,function(r,n){var i=r.invoke(n,e),a=r.shared,o=a.isBufferArgs,s=a.buffer;O.optional(function(){r.assert(n,i+"&&(typeof "+i+'==="object"||typeof '+i+'==="function")&&('+o+"("+i+")||"+s+".getBuffer("+i+")||"+s+".getBuffer("+i+".buffer)||"+o+"("+i+'.buffer)||("constant" in '+i+"&&(typeof "+i+'.constant==="number"||'+a.isArrayLike+"("+i+".constant))))",'invalid dynamic attribute "'+t+'"')});var l={isStream:n.def(!1)},c=new g;c.state=Jr,Object.keys(c).forEach(function(t){l[t]=n.def(""+c[t])});var u=l.buffer,f=l.type;function h(t){n(l[t],"=",i,".",t,"|0;")}return n("if(",o,"(",i,")){",l.isStream,"=true;",u,"=",s,".createStream(",Xn,",",i,");",f,"=",u,".dtype;","}else{",u,"=",s,".getBuffer(",i,");","if(",u,"){",f,"=",u,".dtype;",'}else if("constant" in ',i,"){",l.state,"=",Kr,";","if(typeof "+i+'.constant === "number"){',l[Zr[0]],"=",i,".constant;",Zr.slice(1).map(function(t){return l[t]}).join("="),"=0;","}else{",Zr.map(function(t,e){return l[t]+"="+i+".constant.length>"+e+"?"+i+".constant["+e+"]:0;"}).join(""),"}}else{","if(",o,"(",i,".buffer)){",u,"=",s,".createStream(",Xn,",",i,".buffer);","}else{",u,"=",s,".getBuffer(",i,".buffer);","}",f,'="type" in ',i,"?",a.glTypes,"[",i,".type]:",u,".dtype;",l.normalized,"=!!",i,".normalized;"),h("size"),h("offset"),h("stride"),h("divisor"),n("}}"),n.exit("if(",l.isStream,"){",s,".destroyStream(",u,");","}"),l})}),o}(e,c),M.context=function(t){var e=t.static,r=t.dynamic,n={};return Object.keys(e).forEach(function(t){var r=e[t];n[t]=Zi(function(t,e){return"number"==typeof r||"boolean"==typeof r?""+r:t.link(r)})}),Object.keys(r).forEach(function(t){var e=r[t];n[t]=$i(e,function(t,r){return t.invoke(r,e)})}),n}(s),M}function P(t,e,r){var n=t.shared.context,i=t.scope();Object.keys(r).forEach(function(a){e.save(n,"."+a);var o=r[a];i(n,".",a,"=",o.append(t,e),";")}),e(i)}function D(t,e,r,n){var i,a=t.shared,o=a.gl,s=a.framebuffer;x&&(i=e.def(a.extensions,".webgl_draw_buffers"));var l,c=t.constants,u=c.drawBuffer,f=c.backBuffer;l=r?r.append(t,e):e.def(s,".next"),n||e("if(",l,"!==",s,".cur){"),e("if(",l,"){",o,".bindFramebuffer(",Bi,",",l,".framebuffer);"),x&&e(i,".drawBuffersWEBGL(",u,"[",l,".colorAttachments.length]);"),e("}else{",o,".bindFramebuffer(",Bi,",null);"),x&&e(i,".drawBuffersWEBGL(",f,");"),e("}",s,".cur=",l,";"),n||e("}")}function R(t,e,r){var n=t.shared,i=n.gl,a=t.current,o=t.next,s=n.current,l=n.next,c=t.cond(s,".dirty");w.forEach(function(e){var n,u,f=A(e);if(!(f in r.state))if(f in o){n=o[f],u=a[f];var h=H(b[f].length,function(t){return c.def(n,"[",t,"]")});c(t.cond(h.map(function(t,e){return t+"!=="+u+"["+e+"]"}).join("||")).then(i,".",M[f],"(",h,");",h.map(function(t,e){return u+"["+e+"]="+t}).join(";"),";"))}else{n=c.def(l,".",f);var p=t.cond(n,"!==",s,".",f);c(p),f in k?p(t.cond(n).then(i,".enable(",k[f],");").else(i,".disable(",k[f],");"),s,".",f,"=",n,";"):p(i,".",M[f],"(",n,");",s,".",f,"=",n,";")}}),0===Object.keys(r.state).length&&c(s,".dirty=false;"),e(c)}function B(t,e,r,n){var i=t.shared,a=t.current,o=i.current,s=i.gl;Wi(Object.keys(r)).forEach(function(i){var l=r[i];if(!n||n(l)){var c=l.append(t,e);if(k[i]){var u=k[i];Xi(l)?e(s,c?".enable(":".disable(",u,");"):e(t.cond(c).then(s,".enable(",u,");").else(s,".disable(",u,");")),e(o,".",i,"=",c,";")}else if(Rt(c)){var f=a[i];e(s,".",M[i],"(",c,");",c.map(function(t,e){return f+"["+e+"]="+t}).join(";"),";")}else e(s,".",M[i],"(",c,");",o,".",i,"=",c,";")}})}function N(t,e){y&&(t.instancing=e.def(t.shared.extensions,".angle_instanced_arrays"))}function j(t,e,r,n,i){var a,o,s,l=t.shared,c=t.stats,u=l.current,f=l.timer,h=r.profile;function p(){return"undefined"==typeof performance?"Date.now()":"performance.now()"}function m(t){t(a=e.def(),"=",p(),";"),"string"==typeof i?t(c,".count+=",i,";"):t(c,".count++;"),d&&(n?t(o=e.def(),"=",f,".getNumPendingQueries();"):t(f,".beginQuery(",c,");"))}function g(t){t(c,".cpuTime+=",p(),"-",a,";"),d&&(n?t(f,".pushScopeStats(",o,",",f,".getNumPendingQueries(),",c,");"):t(f,".endQuery();"))}function v(t){var r=e.def(u,".profile");e(u,".profile=",t,";"),e.exit(u,".profile=",r,";")}if(h){if(Xi(h))return void(h.enable?(m(e),g(e.exit),v("true")):v("false"));v(s=h.append(t,e))}else s=e.def(u,".profile");var y=t.block();m(y),e("if(",s,"){",y,"}");var x=t.block();g(x),e.exit("if(",s,"){",x,"}")}function V(t,e,r,n,i){var a=t.shared;n.forEach(function(n){var o,s=n.name,l=r.attributes[s];if(l){if(!i(l))return;o=l.append(t,e)}else{if(!i(Ji))return;var c=t.scopeAttrib(s);O.optional(function(){t.assert(e,c+".state","missing attribute "+s)}),o={},Object.keys(new g).forEach(function(t){o[t]=e.def(c,".",t)})}!function(r,n,i){var o=a.gl,s=e.def(r,".location"),l=e.def(a.attributes,"[",s,"]"),c=i.state,u=i.buffer,f=[i.x,i.y,i.z,i.w],h=["buffer","normalized","offset","stride"];function p(){e("if(!",l,".buffer){",o,".enableVertexAttribArray(",s,");}");var r,a=i.type;if(r=i.size?e.def(i.size,"||",n):n,e("if(",l,".type!==",a,"||",l,".size!==",r,"||",h.map(function(t){return l+"."+t+"!=="+i[t]}).join("||"),"){",o,".bindBuffer(",Xn,",",u,".buffer);",o,".vertexAttribPointer(",[s,r,a,i.normalized,i.stride,i.offset],");",l,".type=",a,";",l,".size=",r,";",h.map(function(t){return l+"."+t+"="+i[t]+";"}).join(""),"}"),y){var c=i.divisor;e("if(",l,".divisor!==",c,"){",t.instancing,".vertexAttribDivisorANGLE(",[s,c],");",l,".divisor=",c,";}")}}function d(){e("if(",l,".buffer){",o,".disableVertexAttribArray(",s,");","}if(",Zr.map(function(t,e){return l+"."+t+"!=="+f[e]}).join("||"),"){",o,".vertexAttrib4f(",s,",",f,");",Zr.map(function(t,e){return l+"."+t+"="+f[e]+";"}).join(""),"}")}c===Jr?p():c===Kr?d():(e("if(",c,"===",Jr,"){"),p(),e("}else{"),d(),e("}"))}(t.link(n),function(t){switch(t){case li:case hi:case gi:return 2;case ci:case pi:case vi:return 3;case ui:case di:case yi:return 4;default:return 1}}(n.info.type),o)})}function U(t,e,n,i,a){for(var o,s=t.shared,l=s.gl,c=0;c1?H(b,function(t){return u+"["+t+"]"}):u);e(");")}}function q(t,e,r,n){var i=t.shared,a=i.gl,o=i.draw,s=n.draw;var l=function(){var i,l=s.elements,c=e;return l?((l.contextDep&&n.contextDynamic||l.propDep)&&(c=r),i=l.append(t,c)):i=c.def(o,".",Rn),i&&c("if("+i+")"+a+".bindBuffer("+Zn+","+i+".buffer.buffer);"),i}();function c(i){var a=s[i];return a?a.contextDep&&n.contextDynamic||a.propDep?a.append(t,r):a.append(t,e):e.def(o,".",i)}var u,f,h=c(Bn),p=c(Nn),d=function(){var i,a=s.count,l=e;return a?((a.contextDep&&n.contextDynamic||a.propDep)&&(l=r),i=a.append(t,l),O.optional(function(){a.MISSING&&t.assert(e,"false","missing vertex count"),a.DYNAMIC&&t.assert(l,i+">=0","missing vertex count")})):(i=l.def(o,".",Fn),O.optional(function(){t.assert(l,i+">=0","missing vertex count")})),i}();if("number"==typeof d){if(0===d)return}else r("if(",d,"){"),r.exit("}");y&&(u=c(jn),f=t.instancing);var m=l+".type",g=s.elements&&Xi(s.elements);function v(){function t(){r(f,".drawElementsInstancedANGLE(",[h,d,m,p+"<<(("+m+"-"+$r+")>>1)",u],");")}function e(){r(f,".drawArraysInstancedANGLE(",[h,p,d,u],");")}l?g?t():(r("if(",l,"){"),t(),r("}else{"),e(),r("}")):e()}function x(){function t(){r(a+".drawElements("+[h,d,m,p+"<<(("+m+"-"+$r+")>>1)"]+");")}function e(){r(a+".drawArrays("+[h,p,d]+");")}l?g?t():(r("if(",l,"){"),t(),r("}else{"),e(),r("}")):e()}y&&("number"!=typeof u||u>=0)?"string"==typeof u?(r("if(",u,">0){"),v(),r("}else if(",u,"<0){"),x(),r("}")):v():x()}function G(t,e,r,n,i){var a=z(),o=a.proc("body",i);return O.optional(function(){a.commandStr=e.commandStr,a.command=a.link(e.commandStr)}),y&&(a.instancing=o.def(a.shared.extensions,".angle_instanced_arrays")),t(a,o,r,n),a.compile().body}function W(t,e,r,n){N(t,e),V(t,e,r,n.attributes,function(){return!0}),U(t,e,r,n.uniforms,function(){return!0}),q(t,e,e,r)}function Y(t,e,r,n){function i(){return!0}t.batchId="a1",N(t,e),V(t,e,r,n.attributes,i),U(t,e,r,n.uniforms,i),q(t,e,e,r)}function X(t,e,r,n){N(t,e);var i=r.contextDep,a=e.def(),o=e.def();t.shared.props=o,t.batchId=a;var s=t.scope(),l=t.scope();function c(t){return t.contextDep&&i||t.propDep}function u(t){return!c(t)}if(e(s.entry,"for(",a,"=0;",a,"<","a1",";++",a,"){",o,"=","a0","[",a,"];",l,"}",s.exit),r.needsContext&&P(t,l,r.context),r.needsFramebuffer&&D(t,l,r.framebuffer),B(t,l,r.state,c),r.profile&&c(r.profile)&&j(t,l,r,!1,!0),n)V(t,s,r,n.attributes,u),V(t,l,r,n.attributes,c),U(t,s,r,n.uniforms,u),U(t,l,r,n.uniforms,c),q(t,s,l,r);else{var f=t.global.def("{}"),h=r.shader.progVar.append(t,l),p=l.def(h,".id"),d=l.def(f,"[",p,"]");l(t.shared.gl,".useProgram(",h,".program);","if(!",d,"){",d,"=",f,"[",p,"]=",t.link(function(e){return G(Y,t,r,e,2)}),"(",h,");}",d,".call(this,a0[",a,"],",a,");")}}function Z(t,e,r){var n=e.static[r];if(n&&function(t){if("object"==typeof t&&!Rt(t)){for(var e=Object.keys(t),r=0;r0&&r(t.shared.current,".dirty=true;")}(o,s),function(t,e){var n=t.proc("scope",3);t.batchId="a2";var i=t.shared,a=i.current;function o(r){var a=e.shader[r];a&&n.set(i.shader,"."+r,a.append(t,n))}P(t,n,e.context),e.framebuffer&&e.framebuffer.append(t,n),Wi(Object.keys(e.state)).forEach(function(r){var a=e.state[r].append(t,n);Rt(a)?a.forEach(function(e,i){n.set(t.next[r],"["+i+"]",e)}):n.set(i.next,"."+r,a)}),j(t,n,e,!0,!0),[Rn,Nn,Fn,jn,Bn].forEach(function(r){var a=e.draw[r];a&&n.set(i.draw,"."+r,""+a.append(t,n))}),Object.keys(e.uniforms).forEach(function(a){n.set(i.uniforms,"["+r.id(a)+"]",e.uniforms[a].append(t,n))}),Object.keys(e.attributes).forEach(function(r){var i=e.attributes[r].append(t,n),a=t.scopeAttrib(r);Object.keys(new g).forEach(function(t){n.set(a,"."+t,i[t])})}),o(Pn),o(Dn),Object.keys(e.state).length>0&&(n(a,".dirty=true;"),n.exit(a,".dirty=true;")),n("a1(",t.shared.context,",a0,",t.batchId,");")}(o,s),function(t,e){var r=t.proc("batch",2);t.batchId="0",N(t,r);var n=!1,i=!0;Object.keys(e.context).forEach(function(t){n=n||e.context[t].propDep}),n||(P(t,r,e.context),i=!1);var a=e.framebuffer,o=!1;function s(t){return t.contextDep&&n||t.propDep}a?(a.propDep?n=o=!0:a.contextDep&&n&&(o=!0),o||D(t,r,a)):D(t,r,null),e.state.viewport&&e.state.viewport.propDep&&(n=!0),R(t,r,e),B(t,r,e.state,function(t){return!s(t)}),e.profile&&s(e.profile)||j(t,r,e,!1,"a1"),e.contextDep=n,e.needsContext=i,e.needsFramebuffer=o;var l=e.shader.progVar;if(l.contextDep&&n||l.propDep)X(t,r,e,null);else{var c=l.append(t,r);if(r(t.shared.gl,".useProgram(",c,".program);"),e.shader.program)X(t,r,e,e.shader.program);else{var u=t.global.def("{}"),f=r.def(c,".id"),h=r.def(u,"[",f,"]");r(t.cond(h).then(h,".call(this,a0,a1);").else(h,"=",u,"[",f,"]=",t.link(function(r){return G(X,t,e,r,2)}),"(",c,");",h,".call(this,a0,a1);"))}}Object.keys(e.state).length>0&&r(t.shared.current,".dirty=true;")}(o,s),o.compile()}}}var Qi=34918,ta=34919,ea=35007,ra=function(t,e){var r=e.ext_disjoint_timer_query;if(!r)return null;var n=[];function i(t){n.push(t)}var a=[];function o(){this.startQueryIndex=-1,this.endQueryIndex=-1,this.sum=0,this.stats=null}var s=[];function l(t){s.push(t)}var c=[];function u(t,e,r){var n=s.pop()||new o;n.startQueryIndex=t,n.endQueryIndex=e,n.sum=0,n.stats=r,c.push(n)}var f=[],h=[];return{beginQuery:function(t){var e=n.pop()||r.createQueryEXT();r.beginQueryEXT(ea,e),a.push(e),u(a.length-1,a.length,t)},endQuery:function(){r.endQueryEXT(ea)},pushScopeStats:u,update:function(){var t,e,n=a.length;if(0!==n){h.length=Math.max(h.length,n+1),f.length=Math.max(f.length,n+1),f[0]=0,h[0]=0;var o=0;for(t=0,e=0;e0)if(Array.isArray(r[0])){s=ut(r);for(var u=1,f=1;f0)if("number"==typeof e[0]){var a=tt.allocType(h.dtype,e.length);vt(a,e),d(a,i),tt.freeType(a)}else if(Array.isArray(e[0])||t(e[0])){n=ut(e);var o=ct(e,n,h.dtype);d(o,i),tt.freeType(o)}else O.raise("invalid buffer data")}else if(rt(e)){n=e.shape;var s=e.stride,l=0,c=0,u=0,f=0;1===n.length?(l=n[0],c=1,u=s[0],f=0):2===n.length?(l=n[0],c=n[1],u=s[0],f=s[1]):O.raise("invalid shape");var m=Array.isArray(e.data)?h.dtype:gt(e.data),g=tt.allocType(m,l*c);yt(g,e.data,l,c,u,f,e.offset),d(g,i),tt.freeType(g)}else O.raise("invalid data for buffer subdata");return p},n.profile&&(p.stats=h.stats),p.destroy=function(){f(h)},p},createStream:function(t,e){var r=l.pop();return r||(r=new s(t)),r.bind(),u(r,e,ht,0,1,!1),r},destroyStream:function(t){l.push(t)},clear:function(){nt(o).forEach(f),l.forEach(f)},getBuffer:function(t){return t&&t._buffer instanceof s?t._buffer:null},restore:function(){nt(o).forEach(function(t){t.buffer=e.createBuffer(),e.bindBuffer(t.type,t.buffer),e.bufferData(t.type,t.persistentData||t.byteLength,t.usage)})},_initBuffer:u}}(i,f,n,x),_=function(e,r,n,i){var a={},o=0,s={uint8:Mt,uint16:Tt};function l(t){this.id=o++,a[this.id]=this,this.buffer=t,this.primType=wt,this.vertCount=0,this.type=0}r.oes_element_index_uint&&(s.uint32=Et),l.prototype.bind=function(){this.buffer.bind()};var c=[];function u(i,a,o,s,l,c,u){if(i.buffer.bind(),a){var f=u;u||t(a)&&(!rt(a)||t(a.data))||(f=r.oes_element_index_uint?Et:Tt),n._initBuffer(i.buffer,a,o,f,3)}else e.bufferData(Ct,c,o),i.buffer.dtype=h||Mt,i.buffer.usage=o,i.buffer.dimension=3,i.buffer.byteLength=c;var h=u;if(!u){switch(i.buffer.dtype){case Mt:case kt:h=Mt;break;case Tt:case At:h=Tt;break;case Et:case St:h=Et;break;default:O.raise("unsupported type for element array")}i.buffer.dtype=h}i.type=h,O(h!==Et||!!r.oes_element_index_uint,"32 bit element buffers not supported, enable oes_element_index_uint first");var p=l;p<0&&(p=i.buffer.byteLength,h===Tt?p>>=1:h===Et&&(p>>=2)),i.vertCount=p;var d=s;if(s<0){d=wt;var m=i.buffer.dimension;1===m&&(d=bt),2===m&&(d=_t),3===m&&(d=wt)}i.primType=d}function f(t){i.elementsCount--,O(null!==t.buffer,"must not double destroy elements"),delete a[t.id],t.buffer.destroy(),t.buffer=null}return{create:function(e,r){var a=n.create(null,Ct,!0),o=new l(a._buffer);function c(e){if(e)if("number"==typeof e)a(e),o.primType=wt,o.vertCount=0|e,o.type=Mt;else{var r=null,n=zt,i=-1,l=-1,f=0,h=0;Array.isArray(e)||t(e)||rt(e)?r=e:(O.type(e,"object","invalid arguments for elements"),"data"in e&&(r=e.data,O(Array.isArray(r)||t(r)||rt(r),"invalid data for element buffer")),"usage"in e&&(O.parameter(e.usage,lt,"invalid element buffer usage"),n=lt[e.usage]),"primitive"in e&&(O.parameter(e.primitive,xt,"invalid element buffer primitive"),i=xt[e.primitive]),"count"in e&&(O("number"==typeof e.count&&e.count>=0,"invalid vertex count for elements"),l=0|e.count),"type"in e&&(O.parameter(e.type,s,"invalid buffer type"),h=s[e.type]),"length"in e?f=0|e.length:(f=l,h===Tt||h===At?f*=2:h!==Et&&h!==St||(f*=4))),u(o,r,n,i,l,f,h)}else a(),o.primType=wt,o.vertCount=0,o.type=Mt;return c}return i.elementsCount++,c(e),c._reglType="elements",c._elements=o,c.subdata=function(t,e){return a.subdata(t,e),c},c.destroy=function(){f(o)},c},createStream:function(t){var e=c.pop();return e||(e=new l(n.create(null,Ct,!0,!1)._buffer)),u(e,t,Lt,-1,-1,0,0),e},destroyStream:function(t){c.push(t)},getElements:function(t){return"function"==typeof t&&t._elements instanceof l?t._elements:null},clear:function(){nt(a).forEach(f)}}}(i,h,b,f),w=function(t,e,r,n){var i={},a={};function o(t,e,r,n){this.name=t,this.id=e,this.location=r,this.info=n}function s(t,e){for(var r=0;r1)for(var m=0;mt&&(t=e.stats.uniformsCount)}),t},r.getMaxAttributesCount=function(){var t=0;return u.forEach(function(e){e.stats.attributesCount>t&&(t=e.stats.attributesCount)}),t}),{clear:function(){var e=t.deleteShader.bind(t);nt(i).forEach(e),i={},nt(a).forEach(e),a={},u.forEach(function(e){t.deleteProgram(e.program)}),u.length=0,c={},r.shaderCount=0},program:function(t,e,n){O.command(t>=0,"missing vertex shader",n),O.command(e>=0,"missing fragment shader",n);var i=c[e];i||(i=c[e]={});var a=i[t];return a||(a=new h(e,t),r.shaderCount++,p(a,n),i[t]=a,u.push(a)),a},restore:function(){i={},a={};for(var t=0;t=_r&&e<_r+6,"invalid cube map target")):"renderbuffer"===a?(n=i,e=xr):O.raise("invalid regl object for attachment"),new f(e,r,n)}function g(t,e,r,n,o){if(r){var s=i.create2D({width:t,height:e,format:n,type:o});return s._texture.refCount=0,new f(br,s,null)}var l=a.create({width:t,height:e,format:n});return l._renderbuffer.refCount=0,new f(xr,null,l)}function v(t){return t&&(t.texture||t.renderbuffer)}function y(t,e,r){t&&(t.texture?t.texture.resize(e,r):t.renderbuffer&&t.renderbuffer.resize(e,r))}r.oes_texture_half_float&&u.push("half float","float16"),r.oes_texture_float&&u.push("float","float32");var x=0,b={};function _(){this.id=x++,b[this.id]=this,this.framebuffer=t.createFramebuffer(),this.width=0,this.height=0,this.colorAttachments=[],this.depthAttachment=null,this.stencilAttachment=null,this.depthStencilAttachment=null}function w(t){t.colorAttachments.forEach(h),h(t.depthAttachment),h(t.stencilAttachment),h(t.depthStencilAttachment)}function k(e){var r=e.framebuffer;O(r,"must not double destroy framebuffer"),t.deleteFramebuffer(r),e.framebuffer=null,o.framebufferCount--,delete b[e.id]}function M(e){var r;t.bindFramebuffer(yr,e.framebuffer);var i=e.colorAttachments;for(r=0;r=2,"invalid shape for framebuffer"),h=I[0],d=I[1]}else"radius"in z&&(h=d=z.radius),"width"in z&&(h=z.width),"height"in z&&(d=z.height);("color"in z||"colors"in z)&&(b=z.color||z.colors,Array.isArray(b)&&O(1===b.length||o,"multiple render targets not supported")),b||("colorCount"in z&&(T=0|z.colorCount,O(T>0,"invalid color buffer count")),"colorTexture"in z&&(_=!!z.colorTexture,k="rgba4"),"colorType"in z&&(A=z.colorType,_?(O(r.oes_texture_float||!("float"===A||"float32"===A),"you must enable OES_texture_float in order to use floating point framebuffer objects"),O(r.oes_texture_half_float||!("half float"===A||"float16"===A),"you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects")):"half float"===A||"float16"===A?(O(r.ext_color_buffer_half_float,"you must enable EXT_color_buffer_half_float to use 16-bit render buffers"),k="rgba16f"):"float"!==A&&"float32"!==A||(O(r.webgl_color_buffer_float,"you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers"),k="rgba32f"),O.oneOf(A,u,"invalid color type")),"colorFormat"in z&&(k=z.colorFormat,l.indexOf(k)>=0?_=!0:c.indexOf(k)>=0?_=!1:_?O.oneOf(z.colorFormat,l,"invalid color format for texture"):O.oneOf(z.colorFormat,c,"invalid color format for renderbuffer"))),("depthTexture"in z||"depthStencilTexture"in z)&&(L=!(!z.depthTexture&&!z.depthStencilTexture),O(!L||r.webgl_depth_texture,"webgl_depth_texture extension not supported")),"depth"in z&&("boolean"==typeof z.depth?y=z.depth:(S=z.depth,x=!1)),"stencil"in z&&("boolean"==typeof z.stencil?x=z.stencil:(E=z.stencil,y=!1)),"depthStencil"in z&&("boolean"==typeof z.depthStencil?y=x=z.depthStencil:(C=z.depthStencil,y=!1,x=!1))}else h=d=1;var P=null,D=null,R=null,B=null;if(Array.isArray(b))P=b.map(m);else if(b)P=[m(b)];else for(P=new Array(T),i=0;i=0||P[i].renderbuffer&&Pr.indexOf(P[i].renderbuffer._renderbuffer.format)>=0,"framebuffer color attachment "+i+" is invalid"),P[i]&&P[i].texture){var N=Cr[P[i].texture._texture.format]*Lr[P[i].texture._texture.type];null===F?F=N:O(F===N,"all color attachments much have the same number of bits per pixel.")}return p(D,h,d),O(!D||D.texture&&D.texture._texture.format===Sr||D.renderbuffer&&D.renderbuffer._renderbuffer.format===zr,"invalid depth attachment for framebuffer object"),p(R,h,d),O(!R||R.renderbuffer&&R.renderbuffer._renderbuffer.format===Or,"invalid stencil attachment for framebuffer object"),p(B,h,d),O(!B||B.texture&&B.texture._texture.format===Ir||B.renderbuffer&&B.renderbuffer._renderbuffer.format===Ir,"invalid depth-stencil attachment for framebuffer object"),w(a),a.width=h,a.height=d,a.colorAttachments=P,a.depthAttachment=D,a.stencilAttachment=R,a.depthStencilAttachment=B,f.color=P.map(v),f.depth=v(D),f.stencil=v(R),f.depthStencil=v(B),f.width=a.width,f.height=a.height,M(a),f}return o.framebufferCount++,f(t,i),e(f,{resize:function(t,e){O(s.next!==a,"can not resize a framebuffer which is currently in use");var r=0|t,n=0|e||r;if(r===a.width&&n===a.height)return f;for(var i=a.colorAttachments,o=0;o=2,"invalid shape for framebuffer"),O(x[0]===x[1],"cube framebuffer must be square"),p=x[0]}else"radius"in y&&(p=0|y.radius),"width"in y?(p=0|y.width,"height"in y&&O(y.height===p,"must be square")):"height"in y&&(p=0|y.height);("color"in y||"colors"in y)&&(d=y.color||y.colors,Array.isArray(d)&&O(1===d.length||f,"multiple render targets not supported")),d||("colorCount"in y&&(v=0|y.colorCount,O(v>0,"invalid color buffer count")),"colorType"in y&&(O.oneOf(y.colorType,u,"invalid color type"),g=y.colorType),"colorFormat"in y&&(m=y.colorFormat,O.oneOf(y.colorFormat,l,"invalid color format for texture"))),"depth"in y&&(h.depth=y.depth),"stencil"in y&&(h.stencil=y.stencil),"depthStencil"in y&&(h.depthStencil=y.depthStencil)}else p=1;if(d)if(Array.isArray(d))for(c=[],n=0;n0&&(h.depth=a[0].depth,h.stencil=a[0].stencil,h.depthStencil=a[0].depthStencil),a[n]?a[n](h):a[n]=A(h)}return e(o,{width:p,height:p,color:c})}return o(t),e(o,{faces:a,resize:function(t){var e,r=0|t;if(O(r>0&&r<=n.maxCubeMapSize,"invalid radius for cube fbo"),r===o.width)return o;var i=o.color;for(e=0;e=0;--t){var e=L[t];e&&e(v,null,0)}i.flush(),p&&p.update()}function B(){!D&&L.length>0&&(D=N.next(R))}function V(){D&&(N.cancel(R),D=null)}function U(t){t.preventDefault(),o=!0,V(),z.forEach(function(t){t()})}function H(t){i.getError(),o=!1,s.restore(),w.restore(),b.restore(),k.restore(),M.restore(),A.restore(),p&&p.restore(),T.procs.refresh(),B(),I.forEach(function(t){t()})}function G(t){function r(t){var e={},r={};return Object.keys(t).forEach(function(n){var i=t[n];F.isDynamic(i)?r[n]=F.unbox(i,n):e[n]=i}),{dynamic:r,static:e}}O(!!t,"invalid args to regl({...})"),O.type(t,"object","invalid args to regl({...})");var n=r(t.context||{}),i=r(t.uniforms||{}),a=r(t.attributes||{}),s=r(function(t){var r=e({},t);function n(t){if(t in r){var e=r[t];delete r[t],Object.keys(e).forEach(function(n){r[t+"."+n]=e[n]})}}return delete r.uniforms,delete r.attributes,delete r.context,"stencil"in r&&r.stencil.op&&(r.stencil.opBack=r.stencil.opFront=r.stencil.op,delete r.stencil.op),n("blend"),n("depth"),n("cull"),n("stencil"),n("polygonOffset"),n("scissor"),n("sample"),r}(t)),l={gpuTime:0,cpuTime:0,count:0},c=T.compile(s,a,i,n,l),u=c.draw,f=c.batch,h=c.scope,p=[];return e(function(t,e){var r;if(o&&O.raise("context lost"),"function"==typeof t)return h.call(this,null,t,0);if("function"==typeof e){if("number"==typeof t){for(r=0;r0)return f.call(this,function(t){for(;p.length=0,"cannot cancel a frame twice"),L[e]=function t(){var e=ha(L,t);L[e]=L[L.length-1],L.length-=1,L.length<=0&&V()}}}}function Z(){var t=E.viewport,e=E.scissor_box;t[0]=t[1]=e[0]=e[1]=0,v.viewportWidth=v.framebufferWidth=v.drawingBufferWidth=t[2]=e[2]=i.drawingBufferWidth,v.viewportHeight=v.framebufferHeight=v.drawingBufferHeight=t[3]=e[3]=i.drawingBufferHeight}function $(){v.tick+=1,v.time=K(),Z(),T.procs.poll()}function J(){Z(),T.procs.refresh(),p&&p.update()}function K(){return(j()-d)/1e3}J();var Q=e(G,{clear:function(t){if(O("object"==typeof t&&t,"regl.clear() takes an object as input"),"framebuffer"in t)if(t.framebuffer&&"framebufferCube"===t.framebuffer_reglType)for(var r=0;r<6;++r)W(e({framebuffer:t.framebuffer.faces[r]},t),Y);else W(t,Y);else Y(0,t)},prop:F.define.bind(null,ca),context:F.define.bind(null,ua),this:F.define.bind(null,fa),draw:G({}),buffer:function(t){return b.create(t,oa,!1,!1)},elements:function(t){return _.create(t,!1)},texture:k.create2D,cube:k.createCube,renderbuffer:M.create,framebuffer:A.create,framebufferCube:A.createCube,attributes:a,frame:X,on:function(t,e){var r;switch(O.type(e,"function","listener callback must be a function"),t){case"frame":return X(e);case"lost":r=z;break;case"restore":r=I;break;case"destroy":r=P;break;default:O.raise("invalid event, must be one of frame,lost,restore,destroy")}return r.push(e),{cancel:function(){for(var t=0;t=0},read:S,destroy:function(){L.length=0,V(),C&&(C.removeEventListener(sa,U),C.removeEventListener(la,H)),w.clear(),A.clear(),M.clear(),k.clear(),_.clear(),b.clear(),p&&p.clear(),P.forEach(function(t){t()})},_gl:i,_refresh:J,poll:function(){$(),p&&p.update()},now:K,stats:f});return n.onDone(null,Q),Q}},"object"==typeof r&&"undefined"!=typeof e?e.exports=i():n.createREGL=i()},{}],479:[function(t,e,r){"use strict";var n,i="";e.exports=function(t,e){if("string"!=typeof t)throw new TypeError("expected a string");if(1===e)return t;if(2===e)return t+t;var r=t.length*e;if(n!==t||"undefined"==typeof n)n=t,i="";else if(i.length>=r)return i.substr(0,r);for(;r>i.length&&e>1;)1&e&&(i+=t),e>>=1,t+=t;return i=(i+=t).substr(0,r)}},{}],480:[function(t,e,r){(function(t){e.exports=t.performance&&t.performance.now?function(){return performance.now()}:Date.now||function(){return+new Date}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],481:[function(t,e,r){"use strict";e.exports=function(t){for(var e=t.length,r=t[t.length-1],n=e,i=e-2;i>=0;--i){var a=r,o=t[i],s=(r=a+o)-a,l=o-s;l&&(t[--n]=r,r=l)}for(var c=0,i=n;i>1;return["sum(",t(e.slice(0,r)),",",t(e.slice(r)),")"].join("")}(e);var n}function u(t){return new Function("sum","scale","prod","compress",["function robustDeterminant",t,"(m){return compress(",c(function(t){for(var e=new Array(t),r=0;r>1;return["sum(",c(t.slice(0,e)),",",c(t.slice(e)),")"].join("")}function u(t,e){if("m"===t.charAt(0)){if("w"===e.charAt(0)){var r=t.split("[");return["w",e.substr(1),"m",r[0].substr(1)].join("")}return["prod(",t,",",e,")"].join("")}return u(e,t)}function f(t){if(2===t.length)return[["diff(",u(t[0][0],t[1][1]),",",u(t[1][0],t[0][1]),")"].join("")];for(var e=[],r=0;r0&&r.push(","),r.push("[");for(var o=0;o0&&r.push(","),o===i?r.push("+b[",a,"]"):r.push("+A[",a,"][",o,"]");r.push("]")}r.push("]),")}r.push("det(A)]}return ",e);var s=new Function("det",r.join(""));return s(t<6?n[t]:n)}var o=[function(){return[0]},function(t,e){return[[e[0]],[t[0][0]]]}];!function(){for(;o.length>1;return["sum(",c(t.slice(0,e)),",",c(t.slice(e)),")"].join("")}function u(t){if(2===t.length)return[["sum(prod(",t[0][0],",",t[1][1],"),prod(-",t[0][1],",",t[1][0],"))"].join("")];for(var e=[],r=0;r0){if(a<=0)return o;n=i+a}else{if(!(i<0))return o;if(a>=0)return o;n=-(i+a)}var s=3.3306690738754716e-16*n;return o>=s||o<=-s?o:h(t,e,r)},function(t,e,r,n){var i=t[0]-n[0],a=e[0]-n[0],o=r[0]-n[0],s=t[1]-n[1],l=e[1]-n[1],c=r[1]-n[1],u=t[2]-n[2],f=e[2]-n[2],h=r[2]-n[2],d=a*c,m=o*l,g=o*s,v=i*c,y=i*l,x=a*s,b=u*(d-m)+f*(g-v)+h*(y-x),_=7.771561172376103e-16*((Math.abs(d)+Math.abs(m))*Math.abs(u)+(Math.abs(g)+Math.abs(v))*Math.abs(f)+(Math.abs(y)+Math.abs(x))*Math.abs(h));return b>_||-b>_?b:p(t,e,r,n)}];!function(){for(;d.length<=s;)d.push(f(d.length));for(var t=[],r=["slow"],n=0;n<=s;++n)t.push("a"+n),r.push("o"+n);var i=["function getOrientation(",t.join(),"){switch(arguments.length){case 0:case 1:return 0;"];for(n=2;n<=s;++n)i.push("case ",n,":return o",n,"(",t.slice(0,n).join(),");");i.push("}var s=new Array(arguments.length);for(var i=0;i0&&o>0||a<0&&o<0)return!1;var s=n(r,t,e),l=n(i,t,e);if(s>0&&l>0||s<0&&l<0)return!1;if(0===a&&0===o&&0===s&&0===l)return function(t,e,r,n){for(var i=0;i<2;++i){var a=t[i],o=e[i],s=Math.min(a,o),l=Math.max(a,o),c=r[i],u=n[i],f=Math.min(c,u),h=Math.max(c,u);if(h=n?(i=f,(l+=1)=n?(i=f,(l+=1)0?1:0}},{}],493:[function(t,e,r){"use strict";e.exports=function(t){return i(n(t))};var n=t("boundary-cells"),i=t("reduce-simplicial-complex")},{"boundary-cells":83,"reduce-simplicial-complex":472}],494:[function(t,e,r){"use strict";e.exports=function(t,e,r,s){r=r||0,"undefined"==typeof s&&(s=function(t){for(var e=t.length,r=0,n=0;n>1,v=E[2*m+1];","if(v===b){return m}","if(b0&&l.push(","),l.push("[");for(var n=0;n0&&l.push(","),l.push("B(C,E,c[",i[0],"],c[",i[1],"])")}l.push("]")}l.push(");")}}for(var a=t+1;a>1;--a){a>1,s=a(t[o],e);s<=0?(0===s&&(i=o),r=o+1):s>0&&(n=o-1)}return i}function u(t,e){for(var r=new Array(t.length),i=0,o=r.length;i=t.length||0!==a(t[g],s)););}return r}function f(t,e){if(e<0)return[];for(var r=[],i=(1<>>u&1&&c.push(i[u]);e.push(c)}return s(e)},r.skeleton=f,r.boundary=function(t){for(var e=[],r=0,n=t.length;r>1:(t>>1)-1}function x(t){for(var e=v(t);;){var r=e,n=2*t+1,i=2*(t+1),a=t;if(n0;){var r=y(t);if(r>=0){var n=v(r);if(e0){var t=M[0];return g(0,S-1),S-=1,x(0),t}return-1}function w(t,e){var r=M[t];return c[r]===e?t:(c[r]=-1/0,b(t),_(),c[r]=e,b((S+=1)-1))}function k(t){if(!u[t]){u[t]=!0;var e=s[t],r=l[t];s[r]>=0&&(s[r]=e),l[e]>=0&&(l[e]=r),A[e]>=0&&w(A[e],m(e)),A[r]>=0&&w(A[r],m(r))}}for(var M=[],A=new Array(a),f=0;f>1;f>=0;--f)x(f);for(;;){var E=_();if(E<0||c[E]>r)break;k(E)}for(var C=[],f=0;f=0&&r>=0&&e!==r){var n=A[e],i=A[r];n!==i&&z.push([n,i])}}),i.unique(i.normalize(z)),{positions:C,edges:z}};var n=t("robust-orientation"),i=t("simplicial-complex")},{"robust-orientation":486,"simplicial-complex":498}],501:[function(t,e,r){"use strict";e.exports=function(t,e){var r,a,o,s;if(e[0][0]e[1][0]))return i(e,t);r=e[1],a=e[0]}if(t[0][0]t[1][0]))return-i(t,e);o=t[1],s=t[0]}var l=n(r,a,s),c=n(r,a,o);if(l<0){if(c<=0)return l}else if(l>0){if(c>=0)return l}else if(c)return c;if(l=n(s,o,a),c=n(s,o,r),l<0){if(c<=0)return l}else if(l>0){if(c>=0)return l}else if(c)return c;return a[0]-s[0]};var n=t("robust-orientation");function i(t,e){var r,i,a,o;if(e[0][0]e[1][0])){var s=Math.min(t[0][1],t[1][1]),l=Math.max(t[0][1],t[1][1]),c=Math.min(e[0][1],e[1][1]),u=Math.max(e[0][1],e[1][1]);return lu?s-u:l-u}r=e[1],i=e[0]}t[0][1]0)if(e[0]!==o[1][0])r=t,t=t.right;else{if(l=c(t.right,e))return l;t=t.left}else{if(e[0]!==o[1][0])return t;var l;if(l=c(t.right,e))return l;t=t.left}}return r}function u(t,e,r,n){this.y=t,this.index=e,this.start=r,this.closed=n}function f(t,e,r,n){this.x=t,this.segment=e,this.create=r,this.index=n}s.prototype.castUp=function(t){var e=n.le(this.coordinates,t[0]);if(e<0)return-1;this.slabs[e];var r=c(this.slabs[e],t),i=-1;if(r&&(i=r.value),this.coordinates[e]===t[0]){var s=null;if(r&&(s=r.key),e>0){var u=c(this.slabs[e-1],t);u&&(s?o(u.key,s)>0&&(s=u.key,i=u.value):(i=u.value,s=u.key))}var f=this.horizontal[e];if(f.length>0){var h=n.ge(f,t[1],l);if(h=f.length)return i;p=f[h]}}if(p.start)if(s){var d=a(s[0],s[1],[t[0],p.y]);s[0][0]>s[1][0]&&(d=-d),d>0&&(i=p.index)}else i=p.index;else p.y!==t[1]&&(i=p.index)}}}return i}},{"./lib/order-segments":501,"binary-search-bounds":79,"functional-red-black-tree":219,"robust-orientation":486}],503:[function(t,e,r){"use strict";var n=t("robust-dot-product"),i=t("robust-sum");function a(t,e){var r=i(n(t,e),[e[e.length-1]]);return r[r.length-1]}function o(t,e,r,n){var i=-e/(n-e);i<0?i=0:i>1&&(i=1);for(var a=1-i,o=t.length,s=new Array(o),l=0;l0||i>0&&u<0){var f=o(s,u,l,i);r.push(f),n.push(f.slice())}u<0?n.push(l.slice()):u>0?r.push(l.slice()):(r.push(l.slice()),n.push(l.slice())),i=u}return{positive:r,negative:n}},e.exports.positive=function(t,e){for(var r=[],n=a(t[t.length-1],e),i=t[t.length-1],s=t[0],l=0;l0||n>0&&c<0)&&r.push(o(i,c,s,n)),c>=0&&r.push(s.slice()),n=c}return r},e.exports.negative=function(t,e){for(var r=[],n=a(t[t.length-1],e),i=t[t.length-1],s=t[0],l=0;l0||n>0&&c<0)&&r.push(o(i,c,s,n)),c<=0&&r.push(s.slice()),n=c}return r}},{"robust-dot-product":483,"robust-sum":491}],504:[function(t,e,r){!function(){"use strict";var t={not_string:/[^s]/,not_bool:/[^t]/,not_type:/[^T]/,not_primitive:/[^v]/,number:/[diefg]/,numeric_arg:/[bcdiefguxX]/,json:/[j]/,not_json:/[^j]/,text:/^[^\x25]+/,modulo:/^\x25{2}/,placeholder:/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,key:/^([a-z_][a-z_\d]*)/i,key_access:/^\.([a-z_][a-z_\d]*)/i,index_access:/^\[(\d+)\]/,sign:/^[\+\-]/};function e(r){return function(r,n){var i,a,o,s,l,c,u,f,h,p=1,d=r.length,m="";for(a=0;a=0),s[8]){case"b":i=parseInt(i,10).toString(2);break;case"c":i=String.fromCharCode(parseInt(i,10));break;case"d":case"i":i=parseInt(i,10);break;case"j":i=JSON.stringify(i,null,s[6]?parseInt(s[6]):0);break;case"e":i=s[7]?parseFloat(i).toExponential(s[7]):parseFloat(i).toExponential();break;case"f":i=s[7]?parseFloat(i).toFixed(s[7]):parseFloat(i);break;case"g":i=s[7]?String(Number(i.toPrecision(s[7]))):parseFloat(i);break;case"o":i=(parseInt(i,10)>>>0).toString(8);break;case"s":i=String(i),i=s[7]?i.substring(0,s[7]):i;break;case"t":i=String(!!i),i=s[7]?i.substring(0,s[7]):i;break;case"T":i=Object.prototype.toString.call(i).slice(8,-1).toLowerCase(),i=s[7]?i.substring(0,s[7]):i;break;case"u":i=parseInt(i,10)>>>0;break;case"v":i=i.valueOf(),i=s[7]?i.substring(0,s[7]):i;break;case"x":i=(parseInt(i,10)>>>0).toString(16);break;case"X":i=(parseInt(i,10)>>>0).toString(16).toUpperCase()}t.json.test(s[8])?m+=i:(!t.number.test(s[8])||f&&!s[3]?h="":(h=f?"+":"-",i=i.toString().replace(t.sign,"")),c=s[4]?"0"===s[4]?"0":s[4].charAt(1):" ",u=s[6]-(h+i).length,l=s[6]&&u>0?c.repeat(u):"",m+=s[5]?h+i+l:"0"===c?h+l+i:l+h+i)}return m}(function(e){if(i[e])return i[e];var r,n=e,a=[],o=0;for(;n;){if(null!==(r=t.text.exec(n)))a.push(r[0]);else if(null!==(r=t.modulo.exec(n)))a.push("%");else{if(null===(r=t.placeholder.exec(n)))throw new SyntaxError("[sprintf] unexpected placeholder");if(r[2]){o|=1;var s=[],l=r[2],c=[];if(null===(c=t.key.exec(l)))throw new SyntaxError("[sprintf] failed to parse named argument key");for(s.push(c[1]);""!==(l=l.substring(c[0].length));)if(null!==(c=t.key_access.exec(l)))s.push(c[1]);else{if(null===(c=t.index_access.exec(l)))throw new SyntaxError("[sprintf] failed to parse named argument key");s.push(c[1])}r[2]=s}else o|=2;if(3===o)throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported");a.push(r)}n=n.substring(r[0].length)}return i[e]=a}(r),arguments)}function n(t,r){return e.apply(null,[t].concat(r||[]))}var i=Object.create(null);"undefined"!=typeof r&&(r.sprintf=e,r.vsprintf=n),"undefined"!=typeof window&&(window.sprintf=e,window.vsprintf=n)}()},{}],505:[function(t,e,r){"use strict";var n=t("parenthesis");e.exports=function(t,e,r){if(null==t)throw Error("First argument should be a string");if(null==e)throw Error("Separator should be a string or a RegExp");r?("string"==typeof r||Array.isArray(r))&&(r={ignore:r}):r={},null==r.escape&&(r.escape=!0),null==r.ignore?r.ignore=["[]","()","{}","<>",'""',"''","``","\u201c\u201d","\xab\xbb"]:("string"==typeof r.ignore&&(r.ignore=[r.ignore]),r.ignore=r.ignore.map(function(t){return 1===t.length&&(t+=t),t}));var i=n.parse(t,{flat:!0,brackets:r.ignore}),a=i[0].split(e);if(r.escape){for(var o=[],s=0;s0;){e=c[c.length-1];var p=t[e];if(a[e]=0&&s[e].push(o[m])}a[e]=d}else{if(n[e]===r[e]){for(var g=[],v=[],y=0,d=l.length-1;d>=0;--d){var x=l[d];if(i[x]=!1,g.push(x),v.push(s[x]),y+=s[x].length,o[x]=f.length,x===e){l.length=d;break}}f.push(g);for(var b=new Array(y),d=0;d c)|0 },"),"generic"===e&&a.push("getters:[0],");for(var s=[],l=[],c=0;c>>7){");for(var c=0;c<1<<(1<128&&c%128==0){f.length>0&&h.push("}}");var p="vExtra"+f.length;a.push("case ",c>>>7,":",p,"(m&0x7f,",l.join(),");break;"),h=["function ",p,"(m,",l.join(),"){switch(m){"],f.push(h)}h.push("case ",127&c,":");for(var d=new Array(r),m=new Array(r),g=new Array(r),v=new Array(r),y=0,x=0;xx)&&!(c&1<<_)!=!(c&1<0&&(A="+"+g[b]+"*c");var T=d[b].length/y*.5,S=.5+v[b]/y*.5;M.push("d"+b+"-"+S+"-"+T+"*("+d[b].join("+")+A+")/("+m[b].join("+")+")")}h.push("a.push([",M.join(),"]);","break;")}a.push("}},"),f.length>0&&h.push("}}");for(var E=[],c=0;c<1<1&&(a=1),a<-1&&(a=-1),i*Math.acos(a)};r.default=function(t){var e=t.px,r=t.py,l=t.cx,c=t.cy,u=t.rx,f=t.ry,h=t.xAxisRotation,p=void 0===h?0:h,d=t.largeArcFlag,m=void 0===d?0:d,g=t.sweepFlag,v=void 0===g?0:g,y=[];if(0===u||0===f)return[];var x=Math.sin(p*i/360),b=Math.cos(p*i/360),_=b*(e-l)/2+x*(r-c)/2,w=-x*(e-l)/2+b*(r-c)/2;if(0===_&&0===w)return[];u=Math.abs(u),f=Math.abs(f);var k=Math.pow(_,2)/Math.pow(u,2)+Math.pow(w,2)/Math.pow(f,2);k>1&&(u*=Math.sqrt(k),f*=Math.sqrt(k));var M=function(t,e,r,n,a,o,l,c,u,f,h,p){var d=Math.pow(a,2),m=Math.pow(o,2),g=Math.pow(h,2),v=Math.pow(p,2),y=d*m-d*v-m*g;y<0&&(y=0),y/=d*v+m*g;var x=(y=Math.sqrt(y)*(l===c?-1:1))*a/o*p,b=y*-o/a*h,_=f*x-u*b+(t+r)/2,w=u*x+f*b+(e+n)/2,k=(h-x)/a,M=(p-b)/o,A=(-h-x)/a,T=(-p-b)/o,S=s(1,0,k,M),E=s(k,M,A,T);return 0===c&&E>0&&(E-=i),1===c&&E<0&&(E+=i),[_,w,S,E]}(e,r,l,c,u,f,m,v,x,b,_,w),A=n(M,4),T=A[0],S=A[1],E=A[2],C=A[3],L=Math.abs(C)/(i/4);Math.abs(1-L)<1e-7&&(L=1);var z=Math.max(Math.ceil(L),1);C/=z;for(var O=0;Oe[2]&&(e[2]=c[u+0]),c[u+1]>e[3]&&(e[3]=c[u+1]);return e}},{"abs-svg-path":48,assert:56,"is-svg-path":407,"normalize-svg-path":511,"parse-svg-path":443}],511:[function(t,e,r){"use strict";e.exports=function(t){for(var e,r=[],o=0,s=0,l=0,c=0,u=null,f=null,h=0,p=0,d=0,m=t.length;d4?(o=g[g.length-4],s=g[g.length-3]):(o=h,s=p),r.push(g)}return r};var n=t("svg-arc-to-cubic-bezier");function i(t,e,r,n){return["C",t,e,r,n,r,n]}function a(t,e,r,n,i,a){return["C",t/3+2/3*r,e/3+2/3*n,i/3+2/3*r,a/3+2/3*n,i,a]}},{"svg-arc-to-cubic-bezier":509}],512:[function(t,e,r){"use strict";var n=t("svg-path-bounds"),i=t("parse-svg-path"),a=t("draw-svg-path"),o=t("is-svg-path"),s=t("bitmap-sdf"),l=document.createElement("canvas"),c=l.getContext("2d");e.exports=function(t,e){if(!o(t))throw Error("Argument should be valid svg path string");e||(e={});var r,u;e.shape?(r=e.shape[0],u=e.shape[1]):(r=l.width=e.w||e.width||200,u=l.height=e.h||e.height||200);var f=Math.min(r,u),h=e.stroke||0,p=e.viewbox||e.viewBox||n(t),d=[r/(p[2]-p[0]),u/(p[3]-p[1])],m=Math.min(d[0]||0,d[1]||0)/2;c.fillStyle="black",c.fillRect(0,0,r,u),c.fillStyle="white",h&&("number"!=typeof h&&(h=1),c.strokeStyle=h>0?"white":"black",c.lineWidth=Math.abs(h));if(c.translate(.5*r,.5*u),c.scale(m,m),function(){var t=document.createElement("canvas").getContext("2d");t.canvas.width=t.canvas.height=1;var e=new Path2D("M0,0h1v1h-1v-1Z");t.fillStyle="black",t.fill(e);var r=t.getImageData(0,0,1,1);return r&&r.data&&255===r.data[3]}()){var g=new Path2D(t);c.fill(g),h&&c.stroke(g)}else{var v=i(t);a(c,v),c.fill(),h&&c.stroke()}return c.setTransform(1,0,0,1,0,0),s(c,{cutoff:null!=e.cutoff?e.cutoff:.5,radius:null!=e.radius?e.radius:.5*f})}},{"bitmap-sdf":81,"draw-svg-path":153,"is-svg-path":407,"parse-svg-path":443,"svg-path-bounds":510}],513:[function(t,e,r){(function(r){"use strict";e.exports=function t(e,r,i){var i=i||{};var o=a[e];o||(o=a[e]={" ":{data:new Float32Array(0),shape:.2}});var s=o[r];if(!s)if(r.length<=1||!/\d/.test(r))s=o[r]=function(t){for(var e=t.cells,r=t.positions,n=new Float32Array(6*e.length),i=0,a=0,o=0;o0&&(f+=.02);for(var p=new Float32Array(u),d=0,m=-.5*f,h=0;h1&&(r-=1),r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t}if(t=L(t,360),e=L(e,100),r=L(r,100),0===e)n=i=a=r;else{var s=r<.5?r*(1+e):r+e-r*e,l=2*r-s;n=o(l,s,t+1/3),i=o(l,s,t),a=o(l,s,t-1/3)}return{r:255*n,g:255*i,b:255*a}}(e.h,l,u),f=!0,h="hsl"),e.hasOwnProperty("a")&&(a=e.a));var p,d,m;return a=C(a),{ok:f,format:e.format||h,r:o(255,s(i.r,0)),g:o(255,s(i.g,0)),b:o(255,s(i.b,0)),a:a}}(e);this._originalInput=e,this._r=u.r,this._g=u.g,this._b=u.b,this._a=u.a,this._roundA=a(100*this._a)/100,this._format=l.format||u.format,this._gradientType=l.gradientType,this._r<1&&(this._r=a(this._r)),this._g<1&&(this._g=a(this._g)),this._b<1&&(this._b=a(this._b)),this._ok=u.ok,this._tc_id=i++}function u(t,e,r){t=L(t,255),e=L(e,255),r=L(r,255);var n,i,a=s(t,e,r),l=o(t,e,r),c=(a+l)/2;if(a==l)n=i=0;else{var u=a-l;switch(i=c>.5?u/(2-a-l):u/(a+l),a){case t:n=(e-r)/u+(e>1)+720)%360;--e;)n.h=(n.h+i)%360,a.push(c(n));return a}function T(t,e){e=e||6;for(var r=c(t).toHsv(),n=r.h,i=r.s,a=r.v,o=[],s=1/e;e--;)o.push(c({h:n,s:i,v:a})),a=(a+s)%1;return o}c.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var e,r,n,i=this.toRgb();return e=i.r/255,r=i.g/255,n=i.b/255,.2126*(e<=.03928?e/12.92:t.pow((e+.055)/1.055,2.4))+.7152*(r<=.03928?r/12.92:t.pow((r+.055)/1.055,2.4))+.0722*(n<=.03928?n/12.92:t.pow((n+.055)/1.055,2.4))},setAlpha:function(t){return this._a=C(t),this._roundA=a(100*this._a)/100,this},toHsv:function(){var t=f(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=f(this._r,this._g,this._b),e=a(360*t.h),r=a(100*t.s),n=a(100*t.v);return 1==this._a?"hsv("+e+", "+r+"%, "+n+"%)":"hsva("+e+", "+r+"%, "+n+"%, "+this._roundA+")"},toHsl:function(){var t=u(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=u(this._r,this._g,this._b),e=a(360*t.h),r=a(100*t.s),n=a(100*t.l);return 1==this._a?"hsl("+e+", "+r+"%, "+n+"%)":"hsla("+e+", "+r+"%, "+n+"%, "+this._roundA+")"},toHex:function(t){return h(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return function(t,e,r,n,i){var o=[I(a(t).toString(16)),I(a(e).toString(16)),I(a(r).toString(16)),I(D(n))];if(i&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1))return o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0);return o.join("")}(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:a(this._r),g:a(this._g),b:a(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+a(this._r)+", "+a(this._g)+", "+a(this._b)+")":"rgba("+a(this._r)+", "+a(this._g)+", "+a(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:a(100*L(this._r,255))+"%",g:a(100*L(this._g,255))+"%",b:a(100*L(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+a(100*L(this._r,255))+"%, "+a(100*L(this._g,255))+"%, "+a(100*L(this._b,255))+"%)":"rgba("+a(100*L(this._r,255))+"%, "+a(100*L(this._g,255))+"%, "+a(100*L(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(E[h(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var e="#"+p(this._r,this._g,this._b,this._a),r=e,n=this._gradientType?"GradientType = 1, ":"";if(t){var i=c(t);r="#"+p(i._r,i._g,i._b,i._a)}return"progid:DXImageTransform.Microsoft.gradient("+n+"startColorstr="+e+",endColorstr="+r+")"},toString:function(t){var e=!!t;t=t||this._format;var r=!1,n=this._a<1&&this._a>=0;return e||!n||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"hex4"!==t&&"hex8"!==t&&"name"!==t?("rgb"===t&&(r=this.toRgbString()),"prgb"===t&&(r=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(r=this.toHexString()),"hex3"===t&&(r=this.toHexString(!0)),"hex4"===t&&(r=this.toHex8String(!0)),"hex8"===t&&(r=this.toHex8String()),"name"===t&&(r=this.toName()),"hsl"===t&&(r=this.toHslString()),"hsv"===t&&(r=this.toHsvString()),r||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},clone:function(){return c(this.toString())},_applyModification:function(t,e){var r=t.apply(null,[this].concat([].slice.call(e)));return this._r=r._r,this._g=r._g,this._b=r._b,this.setAlpha(r._a),this},lighten:function(){return this._applyModification(v,arguments)},brighten:function(){return this._applyModification(y,arguments)},darken:function(){return this._applyModification(x,arguments)},desaturate:function(){return this._applyModification(d,arguments)},saturate:function(){return this._applyModification(m,arguments)},greyscale:function(){return this._applyModification(g,arguments)},spin:function(){return this._applyModification(b,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(A,arguments)},complement:function(){return this._applyCombination(_,arguments)},monochromatic:function(){return this._applyCombination(T,arguments)},splitcomplement:function(){return this._applyCombination(M,arguments)},triad:function(){return this._applyCombination(w,arguments)},tetrad:function(){return this._applyCombination(k,arguments)}},c.fromRatio=function(t,e){if("object"==typeof t){var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]="a"===n?t[n]:P(t[n]));t=r}return c(t,e)},c.equals=function(t,e){return!(!t||!e)&&c(t).toRgbString()==c(e).toRgbString()},c.random=function(){return c.fromRatio({r:l(),g:l(),b:l()})},c.mix=function(t,e,r){r=0===r?0:r||50;var n=c(t).toRgb(),i=c(e).toRgb(),a=r/100;return c({r:(i.r-n.r)*a+n.r,g:(i.g-n.g)*a+n.g,b:(i.b-n.b)*a+n.b,a:(i.a-n.a)*a+n.a})},c.readability=function(e,r){var n=c(e),i=c(r);return(t.max(n.getLuminance(),i.getLuminance())+.05)/(t.min(n.getLuminance(),i.getLuminance())+.05)},c.isReadable=function(t,e,r){var n,i,a=c.readability(t,e);switch(i=!1,(n=function(t){var e,r;e=((t=t||{level:"AA",size:"small"}).level||"AA").toUpperCase(),r=(t.size||"small").toLowerCase(),"AA"!==e&&"AAA"!==e&&(e="AA");"small"!==r&&"large"!==r&&(r="small");return{level:e,size:r}}(r)).level+n.size){case"AAsmall":case"AAAlarge":i=a>=4.5;break;case"AAlarge":i=a>=3;break;case"AAAsmall":i=a>=7}return i},c.mostReadable=function(t,e,r){var n,i,a,o,s=null,l=0;i=(r=r||{}).includeFallbackColors,a=r.level,o=r.size;for(var u=0;ul&&(l=n,s=c(e[u]));return c.isReadable(t,s,{level:a,size:o})||!i?s:(r.includeFallbackColors=!1,c.mostReadable(t,["#fff","#000"],r))};var S=c.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},E=c.hexNames=function(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[t[r]]=r);return e}(S);function C(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function L(e,r){(function(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)})(e)&&(e="100%");var n=function(t){return"string"==typeof t&&-1!=t.indexOf("%")}(e);return e=o(r,s(0,parseFloat(e))),n&&(e=parseInt(e*r,10)/100),t.abs(e-r)<1e-6?1:e%r/parseFloat(r)}function z(t){return o(1,s(0,t))}function O(t){return parseInt(t,16)}function I(t){return 1==t.length?"0"+t:""+t}function P(t){return t<=1&&(t=100*t+"%"),t}function D(e){return t.round(255*parseFloat(e)).toString(16)}function R(t){return O(t)/255}var B,F,N,j=(F="[\\s|\\(]+("+(B="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+B+")[,|\\s]+("+B+")\\s*\\)?",N="[\\s|\\(]+("+B+")[,|\\s]+("+B+")[,|\\s]+("+B+")[,|\\s]+("+B+")\\s*\\)?",{CSS_UNIT:new RegExp(B),rgb:new RegExp("rgb"+F),rgba:new RegExp("rgba"+N),hsl:new RegExp("hsl"+F),hsla:new RegExp("hsla"+N),hsv:new RegExp("hsv"+F),hsva:new RegExp("hsva"+N),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function V(t){return!!j.CSS_UNIT.exec(t)}"undefined"!=typeof e&&e.exports?e.exports=c:window.tinycolor=c}(Math)},{}],515:[function(t,e,r){"use strict";function n(t){if(t instanceof Float32Array)return t;if("number"==typeof t)return new Float32Array([t])[0];var e=new Float32Array(t);return e.set(t),e}e.exports=n,e.exports.float32=e.exports.float=n,e.exports.fract32=e.exports.fract=function(t){if("number"==typeof t)return n(t-n(t));for(var e=n(t),r=0,i=e.length;rf&&(f=l[0]),l[1]h&&(h=l[1])}function i(t){switch(t.type){case"GeometryCollection":t.geometries.forEach(i);break;case"Point":n(t.coordinates);break;case"MultiPoint":t.coordinates.forEach(n)}}if(!e){var a,o,s=r(t),l=new Array(2),c=1/0,u=c,f=-c,h=-c;for(o in t.arcs.forEach(function(t){for(var e=-1,r=t.length;++ef&&(f=l[0]),l[1]h&&(h=l[1])}),t.objects)i(t.objects[o]);e=t.bbox=[c,u,f,h]}return e},i=function(t,e){for(var r,n=t.length,i=n-e;i<--n;)r=t[i],t[i++]=t[n],t[n]=r};function a(t,e){var r=e.id,n=e.bbox,i=null==e.properties?{}:e.properties,a=o(t,e);return null==r&&null==n?{type:"Feature",properties:i,geometry:a}:null==n?{type:"Feature",id:r,properties:i,geometry:a}:{type:"Feature",id:r,bbox:n,properties:i,geometry:a}}function o(t,e){var n=r(t),a=t.arcs;function o(t,e){e.length&&e.pop();for(var r=a[t<0?~t:t],o=0,s=r.length;o1)n=function(t,e,r){var n,i=[],a=[];function o(t){var e=t<0?~t:t;(a[e]||(a[e]=[])).push({i:t,g:n})}function s(t){t.forEach(o)}function l(t){t.forEach(s)}return function t(e){switch(n=e,e.type){case"GeometryCollection":e.geometries.forEach(t);break;case"LineString":s(e.arcs);break;case"MultiLineString":case"Polygon":l(e.arcs);break;case"MultiPolygon":e.arcs.forEach(l)}}(e),a.forEach(null==r?function(t){i.push(t[0].i)}:function(t){r(t[0].g,t[t.length-1].g)&&i.push(t[0].i)}),i}(0,e,r);else for(i=0,n=new Array(a=t.arcs.length);i1)for(var a,o,c=1,u=l(i[0]);cu&&(o=i[0],i[0]=i[c],i[c]=o,u=a);return i})}}var u=function(t,e){for(var r=0,n=t.length;r>>1;t[i]=2))throw new Error("n must be \u22652");if(t.transform)throw new Error("already quantized");var r,i=n(t),a=i[0],o=(i[2]-a)/(e-1)||1,s=i[1],l=(i[3]-s)/(e-1)||1;function c(t){t[0]=Math.round((t[0]-a)/o),t[1]=Math.round((t[1]-s)/l)}function u(t){switch(t.type){case"GeometryCollection":t.geometries.forEach(u);break;case"Point":c(t.coordinates);break;case"MultiPoint":t.coordinates.forEach(c)}}for(r in t.arcs.forEach(function(t){for(var e,r,n,i=1,c=1,u=t.length,f=t[0],h=f[0]=Math.round((f[0]-a)/o),p=f[1]=Math.round((f[1]-s)/l);iMath.max(r,n)?i[2]=1:r>Math.max(e,n)?i[0]=1:i[1]=1;for(var a=0,o=0,l=0;l<3;++l)a+=t[l]*t[l],o+=i[l]*t[l];for(l=0;l<3;++l)i[l]-=o/a*t[l];return s(i,i),i}function h(t,e,r,i,a,o,s,l){this.center=n(r),this.up=n(i),this.right=n(a),this.radius=n([o]),this.angle=n([s,l]),this.angle.bounds=[[-1/0,-Math.PI/2],[1/0,Math.PI/2]],this.setDistanceLimits(t,e),this.computedCenter=this.center.curve(0),this.computedUp=this.up.curve(0),this.computedRight=this.right.curve(0),this.computedRadius=this.radius.curve(0),this.computedAngle=this.angle.curve(0),this.computedToward=[0,0,0],this.computedEye=[0,0,0],this.computedMatrix=new Array(16);for(var c=0;c<16;++c)this.computedMatrix[c]=.5;this.recalcMatrix(0)}var p=h.prototype;p.setDistanceLimits=function(t,e){t=t>0?Math.log(t):-1/0,e=e>0?Math.log(e):1/0,e=Math.max(e,t),this.radius.bounds[0][0]=t,this.radius.bounds[1][0]=e},p.getDistanceLimits=function(t){var e=this.radius.bounds[0];return t?(t[0]=Math.exp(e[0][0]),t[1]=Math.exp(e[1][0]),t):[Math.exp(e[0][0]),Math.exp(e[1][0])]},p.recalcMatrix=function(t){this.center.curve(t),this.up.curve(t),this.right.curve(t),this.radius.curve(t),this.angle.curve(t);for(var e=this.computedUp,r=this.computedRight,n=0,i=0,a=0;a<3;++a)i+=e[a]*r[a],n+=e[a]*e[a];var l=Math.sqrt(n),u=0;for(a=0;a<3;++a)r[a]-=e[a]*i/n,u+=r[a]*r[a],e[a]/=l;var f=Math.sqrt(u);for(a=0;a<3;++a)r[a]/=f;var h=this.computedToward;o(h,e,r),s(h,h);var p=Math.exp(this.computedRadius[0]),d=this.computedAngle[0],m=this.computedAngle[1],g=Math.cos(d),v=Math.sin(d),y=Math.cos(m),x=Math.sin(m),b=this.computedCenter,_=g*y,w=v*y,k=x,M=-g*x,A=-v*x,T=y,S=this.computedEye,E=this.computedMatrix;for(a=0;a<3;++a){var C=_*r[a]+w*h[a]+k*e[a];E[4*a+1]=M*r[a]+A*h[a]+T*e[a],E[4*a+2]=C,E[4*a+3]=0}var L=E[1],z=E[5],O=E[9],I=E[2],P=E[6],D=E[10],R=z*D-O*P,B=O*I-L*D,F=L*P-z*I,N=c(R,B,F);R/=N,B/=N,F/=N,E[0]=R,E[4]=B,E[8]=F;for(a=0;a<3;++a)S[a]=b[a]+E[2+4*a]*p;for(a=0;a<3;++a){u=0;for(var j=0;j<3;++j)u+=E[a+4*j]*S[j];E[12+a]=-u}E[15]=1},p.getMatrix=function(t,e){this.recalcMatrix(t);var r=this.computedMatrix;if(e){for(var n=0;n<16;++n)e[n]=r[n];return e}return r};var d=[0,0,0];p.rotate=function(t,e,r,n){if(this.angle.move(t,e,r),n){this.recalcMatrix(t);var i=this.computedMatrix;d[0]=i[2],d[1]=i[6],d[2]=i[10];for(var o=this.computedUp,s=this.computedRight,l=this.computedToward,c=0;c<3;++c)i[4*c]=o[c],i[4*c+1]=s[c],i[4*c+2]=l[c];a(i,i,n,d);for(c=0;c<3;++c)o[c]=i[4*c],s[c]=i[4*c+1];this.up.set(t,o[0],o[1],o[2]),this.right.set(t,s[0],s[1],s[2])}},p.pan=function(t,e,r,n){e=e||0,r=r||0,n=n||0,this.recalcMatrix(t);var i=this.computedMatrix,a=(Math.exp(this.computedRadius[0]),i[1]),o=i[5],s=i[9],l=c(a,o,s);a/=l,o/=l,s/=l;var u=i[0],f=i[4],h=i[8],p=u*a+f*o+h*s,d=c(u-=a*p,f-=o*p,h-=s*p),m=(u/=d)*e+a*r,g=(f/=d)*e+o*r,v=(h/=d)*e+s*r;this.center.move(t,m,g,v);var y=Math.exp(this.computedRadius[0]);y=Math.max(1e-4,y+n),this.radius.set(t,Math.log(y))},p.translate=function(t,e,r,n){this.center.move(t,e||0,r||0,n||0)},p.setMatrix=function(t,e,r,n){var a=1;"number"==typeof r&&(a=0|r),(a<0||a>3)&&(a=1);var o=(a+2)%3;e||(this.recalcMatrix(t),e=this.computedMatrix);var s=e[a],l=e[a+4],f=e[a+8];if(n){var h=Math.abs(s),p=Math.abs(l),d=Math.abs(f),m=Math.max(h,p,d);h===m?(s=s<0?-1:1,l=f=0):d===m?(f=f<0?-1:1,s=l=0):(l=l<0?-1:1,s=f=0)}else{var g=c(s,l,f);s/=g,l/=g,f/=g}var v,y,x=e[o],b=e[o+4],_=e[o+8],w=x*s+b*l+_*f,k=c(x-=s*w,b-=l*w,_-=f*w),M=l*(_/=k)-f*(b/=k),A=f*(x/=k)-s*_,T=s*b-l*x,S=c(M,A,T);if(M/=S,A/=S,T/=S,this.center.jump(t,H,G,W),this.radius.idle(t),this.up.jump(t,s,l,f),this.right.jump(t,x,b,_),2===a){var E=e[1],C=e[5],L=e[9],z=E*x+C*b+L*_,O=E*M+C*A+L*T;v=R<0?-Math.PI/2:Math.PI/2,y=Math.atan2(O,z)}else{var I=e[2],P=e[6],D=e[10],R=I*s+P*l+D*f,B=I*x+P*b+D*_,F=I*M+P*A+D*T;v=Math.asin(u(R)),y=Math.atan2(F,B)}this.angle.jump(t,y,v),this.recalcMatrix(t);var N=e[2],j=e[6],V=e[10],U=this.computedMatrix;i(U,e);var q=U[15],H=U[12]/q,G=U[13]/q,W=U[14]/q,Y=Math.exp(this.computedRadius[0]);this.center.jump(t,H-N*Y,G-j*Y,W-V*Y)},p.lastT=function(){return Math.max(this.center.lastT(),this.up.lastT(),this.right.lastT(),this.radius.lastT(),this.angle.lastT())},p.idle=function(t){this.center.idle(t),this.up.idle(t),this.right.idle(t),this.radius.idle(t),this.angle.idle(t)},p.flush=function(t){this.center.flush(t),this.up.flush(t),this.right.flush(t),this.radius.flush(t),this.angle.flush(t)},p.setDistance=function(t,e){e>0&&this.radius.set(t,Math.log(e))},p.lookAt=function(t,e,r,n){this.recalcMatrix(t),e=e||this.computedEye,r=r||this.computedCenter;var i=(n=n||this.computedUp)[0],a=n[1],o=n[2],s=c(i,a,o);if(!(s<1e-6)){i/=s,a/=s,o/=s;var l=e[0]-r[0],f=e[1]-r[1],h=e[2]-r[2],p=c(l,f,h);if(!(p<1e-6)){l/=p,f/=p,h/=p;var d=this.computedRight,m=d[0],g=d[1],v=d[2],y=i*m+a*g+o*v,x=c(m-=y*i,g-=y*a,v-=y*o);if(!(x<.01&&(x=c(m=a*h-o*f,g=o*l-i*h,v=i*f-a*l))<1e-6)){m/=x,g/=x,v/=x,this.up.set(t,i,a,o),this.right.set(t,m,g,v),this.center.set(t,r[0],r[1],r[2]),this.radius.set(t,Math.log(p));var b=a*v-o*g,_=o*m-i*v,w=i*g-a*m,k=c(b,_,w),M=i*l+a*f+o*h,A=m*l+g*f+v*h,T=(b/=k)*l+(_/=k)*f+(w/=k)*h,S=Math.asin(u(M)),E=Math.atan2(T,A),C=this.angle._state,L=C[C.length-1],z=C[C.length-2];L%=2*Math.PI;var O=Math.abs(L+2*Math.PI-E),I=Math.abs(L-E),P=Math.abs(L-2*Math.PI-E);O0?r.pop():new ArrayBuffer(t)}function h(t){return new Uint8Array(f(t),0,t)}function p(t){return new Uint16Array(f(2*t),0,t)}function d(t){return new Uint32Array(f(4*t),0,t)}function m(t){return new Int8Array(f(t),0,t)}function g(t){return new Int16Array(f(2*t),0,t)}function v(t){return new Int32Array(f(4*t),0,t)}function y(t){return new Float32Array(f(4*t),0,t)}function x(t){return new Float64Array(f(8*t),0,t)}function b(t){return o?new Uint8ClampedArray(f(t),0,t):h(t)}function _(t){return new DataView(f(t),0,t)}function w(t){t=i.nextPow2(t);var e=i.log2(t),r=c[e];return r.length>0?r.pop():new n(t)}r.free=function(t){if(n.isBuffer(t))c[i.log2(t.length)].push(t);else{if("[object ArrayBuffer]"!==Object.prototype.toString.call(t)&&(t=t.buffer),!t)return;var e=t.length||t.byteLength,r=0|i.log2(e);l[r].push(t)}},r.freeUint8=r.freeUint16=r.freeUint32=r.freeInt8=r.freeInt16=r.freeInt32=r.freeFloat32=r.freeFloat=r.freeFloat64=r.freeDouble=r.freeUint8Clamped=r.freeDataView=function(t){u(t.buffer)},r.freeArrayBuffer=u,r.freeBuffer=function(t){c[i.log2(t.length)].push(t)},r.malloc=function(t,e){if(void 0===e||"arraybuffer"===e)return f(t);switch(e){case"uint8":return h(t);case"uint16":return p(t);case"uint32":return d(t);case"int8":return m(t);case"int16":return g(t);case"int32":return v(t);case"float":case"float32":return y(t);case"double":case"float64":return x(t);case"uint8_clamped":return b(t);case"buffer":return w(t);case"data":case"dataview":return _(t);default:return null}return null},r.mallocArrayBuffer=f,r.mallocUint8=h,r.mallocUint16=p,r.mallocUint32=d,r.mallocInt8=m,r.mallocInt16=g,r.mallocInt32=v,r.mallocFloat32=r.mallocFloat=y,r.mallocFloat64=r.mallocDouble=x,r.mallocUint8Clamped=b,r.mallocDataView=_,r.mallocBuffer=w,r.clearCache=function(){for(var t=0;t<32;++t)s.UINT8[t].length=0,s.UINT16[t].length=0,s.UINT32[t].length=0,s.INT8[t].length=0,s.INT16[t].length=0,s.INT32[t].length=0,s.FLOAT[t].length=0,s.DOUBLE[t].length=0,s.UINT8C[t].length=0,l[t].length=0,c[t].length=0}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},t("buffer").Buffer)},{"bit-twiddle":80,buffer:93,dup:155}],523:[function(t,e,r){"use strict";function n(t){this.roots=new Array(t),this.ranks=new Array(t);for(var e=0;e8192)throw new Error("vectorize-text: String too long (sorry, this will get fixed later)");var o=3*n;t.height=0?e[a]:i})},has___:{value:x(function(e){var n=y(e);return n?r in n:t.indexOf(e)>=0})},set___:{value:x(function(n,i){var a,o=y(n);return o?o[r]=i:(a=t.indexOf(n))>=0?e[a]=i:(a=t.length,e[a]=i,t[a]=n),this})},delete___:{value:x(function(n){var i,a,o=y(n);return o?r in o&&delete o[r]:!((i=t.indexOf(n))<0||(a=t.length-1,t[i]=void 0,e[i]=e[a],t[i]=t[a],t.length=a,e.length=a,0))})}})};m.prototype=Object.create(Object.prototype,{get:{value:function(t,e){return this.get___(t,e)},writable:!0,configurable:!0},has:{value:function(t){return this.has___(t)},writable:!0,configurable:!0},set:{value:function(t,e){return this.set___(t,e)},writable:!0,configurable:!0},delete:{value:function(t){return this.delete___(t)},writable:!0,configurable:!0}}),"function"==typeof r?function(){function n(){this instanceof m||b();var e,n=new r,i=void 0,a=!1;return e=t?function(t,e){return n.set(t,e),n.has(t)||(i||(i=new m),i.set(t,e)),this}:function(t,e){if(a)try{n.set(t,e)}catch(r){i||(i=new m),i.set___(t,e)}else n.set(t,e);return this},Object.create(m.prototype,{get___:{value:x(function(t,e){return i?n.has(t)?n.get(t):i.get___(t,e):n.get(t,e)})},has___:{value:x(function(t){return n.has(t)||!!i&&i.has___(t)})},set___:{value:x(e)},delete___:{value:x(function(t){var e=!!n.delete(t);return i&&i.delete___(t)||e})},permitHostObjects___:{value:x(function(t){if(t!==g)throw new Error("bogus call to permitHostObjects___");a=!0})}})}t&&"undefined"!=typeof Proxy&&(Proxy=void 0),n.prototype=m.prototype,e.exports=n,Object.defineProperty(WeakMap.prototype,"constructor",{value:WeakMap,enumerable:!1,configurable:!0,writable:!0})}():("undefined"!=typeof Proxy&&(Proxy=void 0),e.exports=m)}function g(t){t.permitHostObjects___&&t.permitHostObjects___(g)}function v(t){return!(t.substr(0,l.length)==l&&"___"===t.substr(t.length-3))}function y(t){if(t!==Object(t))throw new TypeError("Not an object: "+t);var e=t[c];if(e&&e.key===t)return e;if(s(t)){e={key:t};try{return o(t,c,{value:e,writable:!1,enumerable:!1,configurable:!1}),e}catch(t){return}}}function x(t){return t.prototype=null,Object.freeze(t)}function b(){p||"undefined"==typeof console||(p=!0,console.warn("WeakMap should be invoked as new WeakMap(), not WeakMap(). This will be an error in the future."))}}()},{}],530:[function(t,e,r){var n=t("./hidden-store.js");e.exports=function(){var t={};return function(e){if(("object"!=typeof e||null===e)&&"function"!=typeof e)throw new Error("Weakmap-shim: Key must be object");var r=e.valueOf(t);return r&&r.identity===t?r:n(e,t)}}},{"./hidden-store.js":531}],531:[function(t,e,r){e.exports=function(t,e){var r={identity:e},n=t.valueOf;return Object.defineProperty(t,"valueOf",{value:function(t){return t!==e?n.apply(this,arguments):r},writable:!0}),r}},{}],532:[function(t,e,r){var n=t("./create-store.js");e.exports=function(){var t=n();return{get:function(e,r){var n=t(e);return n.hasOwnProperty("value")?n.value:r},set:function(e,r){return t(e).value=r,this},has:function(e){return"value"in t(e)},delete:function(e){return delete t(e).value}}}},{"./create-store.js":530}],533:[function(t,e,r){var n=t("get-canvas-context");e.exports=function(t){return n("webgl",t)}},{"get-canvas-context":221}],534:[function(t,e,r){var n=t("../main"),i=t("object-assign"),a=n.instance();function o(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,i(o.prototype,{name:"Chinese",jdEpoch:1721425.5,hasYearZero:!1,minMonth:0,firstMonth:0,minDay:1,regionalOptions:{"":{name:"Chinese",epochs:["BEC","EC"],monthNumbers:function(t,e){if("string"==typeof t){var r=t.match(l);return r?r[0]:""}var n=this._validateYear(t),i=t.month(),a=""+this.toChineseMonth(n,i);return e&&a.length<2&&(a="0"+a),this.isIntercalaryMonth(n,i)&&(a+="i"),a},monthNames:function(t){if("string"==typeof t){var e=t.match(c);return e?e[0]:""}var r=this._validateYear(t),n=t.month(),i=["\u4e00\u6708","\u4e8c\u6708","\u4e09\u6708","\u56db\u6708","\u4e94\u6708","\u516d\u6708","\u4e03\u6708","\u516b\u6708","\u4e5d\u6708","\u5341\u6708","\u5341\u4e00\u6708","\u5341\u4e8c\u6708"][this.toChineseMonth(r,n)-1];return this.isIntercalaryMonth(r,n)&&(i="\u95f0"+i),i},monthNamesShort:function(t){if("string"==typeof t){var e=t.match(u);return e?e[0]:""}var r=this._validateYear(t),n=t.month(),i=["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"][this.toChineseMonth(r,n)-1];return this.isIntercalaryMonth(r,n)&&(i="\u95f0"+i),i},parseMonth:function(t,e){t=this._validateYear(t);var r,n=parseInt(e);if(isNaN(n))"\u95f0"===e[0]&&(r=!0,e=e.substring(1)),"\u6708"===e[e.length-1]&&(e=e.substring(0,e.length-1)),n=1+["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"].indexOf(e);else{var i=e[e.length-1];r="i"===i||"I"===i}return this.toMonthIndex(t,n,r)},dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:1,isRTL:!1}},_validateYear:function(t,e){if(t.year&&(t=t.year()),"number"!=typeof t||t<1888||t>2111)throw e.replace(/\{0\}/,this.local.name);return t},toMonthIndex:function(t,e,r){var i=this.intercalaryMonth(t);if(r&&e!==i||e<1||e>12)throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return i?!r&&e<=i?e-1:e:e-1},toChineseMonth:function(t,e){t.year&&(e=(t=t.year()).month());var r=this.intercalaryMonth(t);if(e<0||e>(r?12:11))throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return r?e>13},isIntercalaryMonth:function(t,e){t.year&&(e=(t=t.year()).month());var r=this.intercalaryMonth(t);return!!r&&r===e},leapYear:function(t){return 0!==this.intercalaryMonth(t)},weekOfYear:function(t,e,r){var i,o=this._validateYear(t,n.local.invalidyear),s=h[o-h[0]],l=s>>9&4095,c=s>>5&15,u=31&s;(i=a.newDate(l,c,u)).add(4-(i.dayOfWeek()||7),"d");var f=this.toJD(t,e,r)-i.toJD();return 1+Math.floor(f/7)},monthsInYear:function(t){return this.leapYear(t)?13:12},daysInMonth:function(t,e){t.year&&(e=t.month(),t=t.year()),t=this._validateYear(t);var r=f[t-f[0]];if(e>(r>>13?12:11))throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return r&1<<12-e?30:29},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,s,r,n.local.invalidDate);t=this._validateYear(i.year()),e=i.month(),r=i.day();var o=this.isIntercalaryMonth(t,e),s=this.toChineseMonth(t,e),l=function(t,e,r,n,i){var a,o,s;if("object"==typeof t)o=t,a=e||{};else{var l="number"==typeof t&&t>=1888&&t<=2111;if(!l)throw new Error("Lunar year outside range 1888-2111");var c="number"==typeof e&&e>=1&&e<=12;if(!c)throw new Error("Lunar month outside range 1 - 12");var u,p="number"==typeof r&&r>=1&&r<=30;if(!p)throw new Error("Lunar day outside range 1 - 30");"object"==typeof n?(u=!1,a=n):(u=!!n,a=i||{}),o={year:t,month:e,day:r,isIntercalary:u}}s=o.day-1;var d,m=f[o.year-f[0]],g=m>>13;d=g?o.month>g?o.month:o.isIntercalary?o.month:o.month-1:o.month-1;for(var v=0;v>9&4095,(x>>5&15)-1,(31&x)+s);return a.year=b.getFullYear(),a.month=1+b.getMonth(),a.day=b.getDate(),a}(t,s,r,o);return a.toJD(l.year,l.month,l.day)},fromJD:function(t){var e=a.fromJD(t),r=function(t,e,r,n){var i,a;if("object"==typeof t)i=t,a=e||{};else{var o="number"==typeof t&&t>=1888&&t<=2111;if(!o)throw new Error("Solar year outside range 1888-2111");var s="number"==typeof e&&e>=1&&e<=12;if(!s)throw new Error("Solar month outside range 1 - 12");var l="number"==typeof r&&r>=1&&r<=31;if(!l)throw new Error("Solar day outside range 1 - 31");i={year:t,month:e,day:r},a=n||{}}var c=h[i.year-h[0]],u=i.year<<9|i.month<<5|i.day;a.year=u>=c?i.year:i.year-1,c=h[a.year-h[0]];var p,d=new Date(c>>9&4095,(c>>5&15)-1,31&c),m=new Date(i.year,i.month-1,i.day);p=Math.round((m-d)/864e5);var g,v=f[a.year-f[0]];for(g=0;g<13;g++){var y=v&1<<12-g?30:29;if(p>13;!x||g=2&&n<=6},extraInfo:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return{century:o[Math.floor((i.year()-1)/100)+1]||""}},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return t=i.year()+(i.year()<0?1:0),e=i.month(),(r=i.day())+(e>1?16:0)+(e>2?32*(e-2):0)+400*(t-1)+this.jdEpoch-1},fromJD:function(t){t=Math.floor(t+.5)-Math.floor(this.jdEpoch)-1;var e=Math.floor(t/400)+1;t-=400*(e-1),t+=t>15?16:0;var r=Math.floor(t/32)+1,n=t-32*(r-1)+1;return this.newDate(e<=0?e-1:e,r,n)}});var o={20:"Fruitbat",21:"Anchovy"};n.calendars.discworld=a},{"../main":548,"object-assign":437}],537:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Ethiopian",jdEpoch:1724220.5,daysPerMonth:[30,30,30,30,30,30,30,30,30,30,30,30,5],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Ethiopian",epochs:["BEE","EE"],monthNames:["Meskerem","Tikemet","Hidar","Tahesas","Tir","Yekatit","Megabit","Miazia","Genbot","Sene","Hamle","Nehase","Pagume"],monthNamesShort:["Mes","Tik","Hid","Tah","Tir","Yek","Meg","Mia","Gen","Sen","Ham","Neh","Pag"],dayNames:["Ehud","Segno","Maksegno","Irob","Hamus","Arb","Kidame"],dayNamesShort:["Ehu","Seg","Mak","Iro","Ham","Arb","Kid"],dayNamesMin:["Eh","Se","Ma","Ir","Ha","Ar","Ki"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);return(t=e.year()+(e.year()<0?1:0))%4==3||t%4==-1},monthsInYear:function(t){return this._validate(t,this.minMonth,this.minDay,n.local.invalidYear||n.regionalOptions[""].invalidYear),13},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(13===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return(t=i.year())<0&&t++,i.day()+30*(i.month()-1)+365*(t-1)+Math.floor(t/4)+this.jdEpoch-1},fromJD:function(t){var e=Math.floor(t)+.5-this.jdEpoch,r=Math.floor((e-Math.floor((e+366)/1461))/365)+1;r<=0&&r--,e=Math.floor(t)+.5-this.newDate(r,1,1).toJD();var n=Math.floor(e/30)+1,i=e-30*(n-1)+1;return this.newDate(r,n,i)}}),n.calendars.ethiopian=a},{"../main":548,"object-assign":437}],538:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}function o(t,e){return t-e*Math.floor(t/e)}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Hebrew",jdEpoch:347995.5,daysPerMonth:[30,29,30,29,30,29,30,29,30,29,30,29,29],hasYearZero:!1,minMonth:1,firstMonth:7,minDay:1,regionalOptions:{"":{name:"Hebrew",epochs:["BAM","AM"],monthNames:["Nisan","Iyar","Sivan","Tammuz","Av","Elul","Tishrei","Cheshvan","Kislev","Tevet","Shevat","Adar","Adar II"],monthNamesShort:["Nis","Iya","Siv","Tam","Av","Elu","Tis","Che","Kis","Tev","She","Ada","Ad2"],dayNames:["Yom Rishon","Yom Sheni","Yom Shlishi","Yom Revi'i","Yom Chamishi","Yom Shishi","Yom Shabbat"],dayNamesShort:["Ris","She","Shl","Rev","Cha","Shi","Sha"],dayNamesMin:["Ri","She","Shl","Re","Ch","Shi","Sha"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);return this._leapYear(e.year())},_leapYear:function(t){return o(7*(t=t<0?t+1:t)+1,19)<7},monthsInYear:function(t){return this._validate(t,this.minMonth,this.minDay,n.local.invalidYear),this._leapYear(t.year?t.year():t)?13:12},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(t){return t=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear).year(),this.toJD(-1===t?1:t+1,7,1)-this.toJD(t,7,1)},daysInMonth:function(t,e){return t.year&&(e=t.month(),t=t.year()),this._validate(t,e,this.minDay,n.local.invalidMonth),12===e&&this.leapYear(t)?30:8===e&&5===o(this.daysInYear(t),10)?30:9===e&&3===o(this.daysInYear(t),10)?29:this.daysPerMonth[e-1]},weekDay:function(t,e,r){return 6!==this.dayOfWeek(t,e,r)},extraInfo:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return{yearType:(this.leapYear(i)?"embolismic":"common")+" "+["deficient","regular","complete"][this.daysInYear(i)%10-3]}},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);t=i.year(),e=i.month(),r=i.day();var a=t<=0?t+1:t,o=this.jdEpoch+this._delay1(a)+this._delay2(a)+r+1;if(e<7){for(var s=7;s<=this.monthsInYear(t);s++)o+=this.daysInMonth(t,s);for(s=1;s=this.toJD(-1===e?1:e+1,7,1);)e++;for(var r=tthis.toJD(e,r,this.daysInMonth(e,r));)r++;var n=t-this.toJD(e,r,1)+1;return this.newDate(e,r,n)}}),n.calendars.hebrew=a},{"../main":548,"object-assign":437}],539:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Islamic",jdEpoch:1948439.5,daysPerMonth:[30,29,30,29,30,29,30,29,30,29,30,29],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Islamic",epochs:["BH","AH"],monthNames:["Muharram","Safar","Rabi' al-awwal","Rabi' al-thani","Jumada al-awwal","Jumada al-thani","Rajab","Sha'aban","Ramadan","Shawwal","Dhu al-Qi'dah","Dhu al-Hijjah"],monthNamesShort:["Muh","Saf","Rab1","Rab2","Jum1","Jum2","Raj","Sha'","Ram","Shaw","DhuQ","DhuH"],dayNames:["Yawm al-ahad","Yawm al-ithnayn","Yawm ath-thulaathaa'","Yawm al-arbi'aa'","Yawm al-kham\u012bs","Yawm al-jum'a","Yawm as-sabt"],dayNamesShort:["Aha","Ith","Thu","Arb","Kha","Jum","Sab"],dayNamesMin:["Ah","It","Th","Ar","Kh","Ju","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:6,isRTL:!1}},leapYear:function(t){return(11*this._validate(t,this.minMonth,this.minDay,n.local.invalidYear).year()+14)%30<11},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(t){return this.leapYear(t)?355:354},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return 5!==this.dayOfWeek(t,e,r)},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return t=i.year(),e=i.month(),t=t<=0?t+1:t,(r=i.day())+Math.ceil(29.5*(e-1))+354*(t-1)+Math.floor((3+11*t)/30)+this.jdEpoch-1},fromJD:function(t){t=Math.floor(t)+.5;var e=Math.floor((30*(t-this.jdEpoch)+10646)/10631);e=e<=0?e-1:e;var r=Math.min(12,Math.ceil((t-29-this.toJD(e,1,1))/29.5)+1),n=t-this.toJD(e,r,1)+1;return this.newDate(e,r,n)}}),n.calendars.islamic=a},{"../main":548,"object-assign":437}],540:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Julian",jdEpoch:1721423.5,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Julian",epochs:["BC","AD"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"mm/dd/yyyy",firstDay:0,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);return(t=e.year()<0?e.year()+1:e.year())%4==0},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(4-(n.dayOfWeek()||7),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return t=i.year(),e=i.month(),r=i.day(),t<0&&t++,e<=2&&(t--,e+=12),Math.floor(365.25*(t+4716))+Math.floor(30.6001*(e+1))+r-1524.5},fromJD:function(t){var e=Math.floor(t+.5)+1524,r=Math.floor((e-122.1)/365.25),n=Math.floor(365.25*r),i=Math.floor((e-n)/30.6001),a=i-Math.floor(i<14?1:13),o=r-Math.floor(a>2?4716:4715),s=e-n-Math.floor(30.6001*i);return o<=0&&o--,this.newDate(o,a,s)}}),n.calendars.julian=a},{"../main":548,"object-assign":437}],541:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}function o(t,e){return t-e*Math.floor(t/e)}function s(t,e){return o(t-1,e)+1}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Mayan",jdEpoch:584282.5,hasYearZero:!0,minMonth:0,firstMonth:0,minDay:0,regionalOptions:{"":{name:"Mayan",epochs:["",""],monthNames:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17"],monthNamesShort:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17"],dayNames:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],dayNamesShort:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],dayNamesMin:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],digits:null,dateFormat:"YYYY.m.d",firstDay:0,isRTL:!1,haabMonths:["Pop","Uo","Zip","Zotz","Tzec","Xul","Yaxkin","Mol","Chen","Yax","Zac","Ceh","Mac","Kankin","Muan","Pax","Kayab","Cumku","Uayeb"],tzolkinMonths:["Imix","Ik","Akbal","Kan","Chicchan","Cimi","Manik","Lamat","Muluc","Oc","Chuen","Eb","Ben","Ix","Men","Cib","Caban","Etznab","Cauac","Ahau"]}},leapYear:function(t){return this._validate(t,this.minMonth,this.minDay,n.local.invalidYear),!1},formatYear:function(t){t=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear).year();var e=Math.floor(t/400);return t%=400,t+=t<0?400:0,e+"."+Math.floor(t/20)+"."+t%20},forYear:function(t){if((t=t.split(".")).length<3)throw"Invalid Mayan year";for(var e=0,r=0;r19||r>0&&n<0)throw"Invalid Mayan year";e=20*e+n}return e},monthsInYear:function(t){return this._validate(t,this.minMonth,this.minDay,n.local.invalidYear),18},weekOfYear:function(t,e,r){return this._validate(t,e,r,n.local.invalidDate),0},daysInYear:function(t){return this._validate(t,this.minMonth,this.minDay,n.local.invalidYear),360},daysInMonth:function(t,e){return this._validate(t,e,this.minDay,n.local.invalidMonth),20},daysInWeek:function(){return 5},dayOfWeek:function(t,e,r){return this._validate(t,e,r,n.local.invalidDate).day()},weekDay:function(t,e,r){return this._validate(t,e,r,n.local.invalidDate),!0},extraInfo:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate).toJD(),a=this._toHaab(i),o=this._toTzolkin(i);return{haabMonthName:this.local.haabMonths[a[0]-1],haabMonth:a[0],haabDay:a[1],tzolkinDayName:this.local.tzolkinMonths[o[0]-1],tzolkinDay:o[0],tzolkinTrecena:o[1]}},_toHaab:function(t){var e=o((t-=this.jdEpoch)+8+340,365);return[Math.floor(e/20)+1,o(e,20)]},_toTzolkin:function(t){return[s((t-=this.jdEpoch)+20,20),s(t+4,13)]},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);return i.day()+20*i.month()+360*i.year()+this.jdEpoch},fromJD:function(t){t=Math.floor(t)+.5-this.jdEpoch;var e=Math.floor(t/360);t%=360,t+=t<0?360:0;var r=Math.floor(t/20),n=t%20;return this.newDate(e,r,n)}}),n.calendars.mayan=a},{"../main":548,"object-assign":437}],542:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar;var o=n.instance("gregorian");i(a.prototype,{name:"Nanakshahi",jdEpoch:2257673.5,daysPerMonth:[31,31,31,31,31,30,30,30,30,30,30,30],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Nanakshahi",epochs:["BN","AN"],monthNames:["Chet","Vaisakh","Jeth","Harh","Sawan","Bhadon","Assu","Katak","Maghar","Poh","Magh","Phagun"],monthNamesShort:["Che","Vai","Jet","Har","Saw","Bha","Ass","Kat","Mgr","Poh","Mgh","Pha"],dayNames:["Somvaar","Mangalvar","Budhvaar","Veervaar","Shukarvaar","Sanicharvaar","Etvaar"],dayNamesShort:["Som","Mangal","Budh","Veer","Shukar","Sanichar","Et"],dayNamesMin:["So","Ma","Bu","Ve","Sh","Sa","Et"],digits:null,dateFormat:"dd-mm-yyyy",firstDay:0,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear||n.regionalOptions[""].invalidYear);return o.leapYear(e.year()+(e.year()<1?1:0)+1469)},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(1-(n.dayOfWeek()||7),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidMonth);(t=i.year())<0&&t++;for(var a=i.day(),s=1;s=this.toJD(e+1,1,1);)e++;for(var r=t-Math.floor(this.toJD(e,1,1)+.5)+1,n=1;r>this.daysInMonth(e,n);)r-=this.daysInMonth(e,n),n++;return this.newDate(e,n,r)}}),n.calendars.nanakshahi=a},{"../main":548,"object-assign":437}],543:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar,i(a.prototype,{name:"Nepali",jdEpoch:1700709.5,daysPerMonth:[31,31,32,32,31,30,30,29,30,29,30,30],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,daysPerYear:365,regionalOptions:{"":{name:"Nepali",epochs:["BBS","ABS"],monthNames:["Baisakh","Jestha","Ashadh","Shrawan","Bhadra","Ashwin","Kartik","Mangsir","Paush","Mangh","Falgun","Chaitra"],monthNamesShort:["Bai","Je","As","Shra","Bha","Ash","Kar","Mang","Pau","Ma","Fal","Chai"],dayNames:["Aaitabaar","Sombaar","Manglbaar","Budhabaar","Bihibaar","Shukrabaar","Shanibaar"],dayNamesShort:["Aaita","Som","Mangl","Budha","Bihi","Shukra","Shani"],dayNamesMin:["Aai","So","Man","Bu","Bi","Shu","Sha"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:1,isRTL:!1}},leapYear:function(t){return this.daysInYear(t)!==this.daysPerYear},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(t){if(t=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear).year(),"undefined"==typeof this.NEPALI_CALENDAR_DATA[t])return this.daysPerYear;for(var e=0,r=this.minMonth;r<=12;r++)e+=this.NEPALI_CALENDAR_DATA[t][r];return e},daysInMonth:function(t,e){return t.year&&(e=t.month(),t=t.year()),this._validate(t,e,this.minDay,n.local.invalidMonth),"undefined"==typeof this.NEPALI_CALENDAR_DATA[t]?this.daysPerMonth[e-1]:this.NEPALI_CALENDAR_DATA[t][e]},weekDay:function(t,e,r){return 6!==this.dayOfWeek(t,e,r)},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);t=i.year(),e=i.month(),r=i.day();var a=n.instance(),o=0,s=e,l=t;this._createMissingCalendarData(t);var c=t-(s>9||9===s&&r>=this.NEPALI_CALENDAR_DATA[l][0]?56:57);for(9!==e&&(o=r,s--);9!==s;)s<=0&&(s=12,l--),o+=this.NEPALI_CALENDAR_DATA[l][s],s--;return 9===e?(o+=r-this.NEPALI_CALENDAR_DATA[l][0])<0&&(o+=a.daysInYear(c)):o+=this.NEPALI_CALENDAR_DATA[l][9]-this.NEPALI_CALENDAR_DATA[l][0],a.newDate(c,1,1).add(o,"d").toJD()},fromJD:function(t){var e=n.instance().fromJD(t),r=e.year(),i=e.dayOfYear(),a=r+56;this._createMissingCalendarData(a);for(var o=9,s=this.NEPALI_CALENDAR_DATA[a][0],l=this.NEPALI_CALENDAR_DATA[a][o]-s+1;i>l;)++o>12&&(o=1,a++),l+=this.NEPALI_CALENDAR_DATA[a][o];var c=this.NEPALI_CALENDAR_DATA[a][o]-(l-i);return this.newDate(a,o,c)},_createMissingCalendarData:function(t){var e=this.daysPerMonth.slice(0);e.unshift(17);for(var r=t-1;r0?474:473))%2820+474+38)%2816<682},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-(n.dayOfWeek()+1)%7,"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return 5!==this.dayOfWeek(t,e,r)},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);t=i.year(),e=i.month(),r=i.day();var a=t-(t>=0?474:473),s=474+o(a,2820);return r+(e<=7?31*(e-1):30*(e-1)+6)+Math.floor((682*s-110)/2816)+365*(s-1)+1029983*Math.floor(a/2820)+this.jdEpoch-1},fromJD:function(t){var e=(t=Math.floor(t)+.5)-this.toJD(475,1,1),r=Math.floor(e/1029983),n=o(e,1029983),i=2820;if(1029982!==n){var a=Math.floor(n/366),s=o(n,366);i=Math.floor((2134*a+2816*s+2815)/1028522)+a+1}var l=i+2820*r+474;l=l<=0?l-1:l;var c=t-this.toJD(l,1,1)+1,u=c<=186?Math.ceil(c/31):Math.ceil((c-6)/30),f=t-this.toJD(l,u,1)+1;return this.newDate(l,u,f)}}),n.calendars.persian=a,n.calendars.jalali=a},{"../main":548,"object-assign":437}],545:[function(t,e,r){var n=t("../main"),i=t("object-assign"),a=n.instance();function o(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,i(o.prototype,{name:"Taiwan",jdEpoch:2419402.5,yearsOffset:1911,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Taiwan",epochs:["BROC","ROC"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:1,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);t=this._t2gYear(e.year());return a.leapYear(t)},weekOfYear:function(t,e,r){var i=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);t=this._t2gYear(i.year());return a.weekOfYear(t,i.month(),i.day())},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);t=this._t2gYear(i.year());return a.toJD(t,i.month(),i.day())},fromJD:function(t){var e=a.fromJD(t),r=this._g2tYear(e.year());return this.newDate(r,e.month(),e.day())},_t2gYear:function(t){return t+this.yearsOffset+(t>=-this.yearsOffset&&t<=-1?1:0)},_g2tYear:function(t){return t-this.yearsOffset-(t>=1&&t<=this.yearsOffset?1:0)}}),n.calendars.taiwan=o},{"../main":548,"object-assign":437}],546:[function(t,e,r){var n=t("../main"),i=t("object-assign"),a=n.instance();function o(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,i(o.prototype,{name:"Thai",jdEpoch:1523098.5,yearsOffset:543,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Thai",epochs:["BBE","BE"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);t=this._t2gYear(e.year());return a.leapYear(t)},weekOfYear:function(t,e,r){var i=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);t=this._t2gYear(i.year());return a.weekOfYear(t,i.month(),i.day())},daysInMonth:function(t,e){var r=this._validate(t,e,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(t,e,r){return(this.dayOfWeek(t,e,r)||7)<6},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate);t=this._t2gYear(i.year());return a.toJD(t,i.month(),i.day())},fromJD:function(t){var e=a.fromJD(t),r=this._g2tYear(e.year());return this.newDate(r,e.month(),e.day())},_t2gYear:function(t){return t-this.yearsOffset-(t>=1&&t<=this.yearsOffset?1:0)},_g2tYear:function(t){return t+this.yearsOffset+(t>=-this.yearsOffset&&t<=-1?1:0)}}),n.calendars.thai=o},{"../main":548,"object-assign":437}],547:[function(t,e,r){var n=t("../main"),i=t("object-assign");function a(t){this.local=this.regionalOptions[t||""]||this.regionalOptions[""]}a.prototype=new n.baseCalendar,i(a.prototype,{name:"UmmAlQura",hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Umm al-Qura",epochs:["BH","AH"],monthNames:["Al-Muharram","Safar","Rabi' al-awwal","Rabi' Al-Thani","Jumada Al-Awwal","Jumada Al-Thani","Rajab","Sha'aban","Ramadan","Shawwal","Dhu al-Qi'dah","Dhu al-Hijjah"],monthNamesShort:["Muh","Saf","Rab1","Rab2","Jum1","Jum2","Raj","Sha'","Ram","Shaw","DhuQ","DhuH"],dayNames:["Yawm al-Ahad","Yawm al-Ithnain","Yawm al-Thal\u0101th\u0101\u2019","Yawm al-Arba\u2018\u0101\u2019","Yawm al-Kham\u012bs","Yawm al-Jum\u2018a","Yawm al-Sabt"],dayNamesMin:["Ah","Ith","Th","Ar","Kh","Ju","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:6,isRTL:!0}},leapYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,n.local.invalidYear);return 355===this.daysInYear(e.year())},weekOfYear:function(t,e,r){var n=this.newDate(t,e,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(t){for(var e=0,r=1;r<=12;r++)e+=this.daysInMonth(t,r);return e},daysInMonth:function(t,e){for(var r=this._validate(t,e,this.minDay,n.local.invalidMonth).toJD()-24e5+.5,i=0,a=0;ar)return o[i]-o[i-1];i++}return 30},weekDay:function(t,e,r){return 5!==this.dayOfWeek(t,e,r)},toJD:function(t,e,r){var i=this._validate(t,e,r,n.local.invalidDate),a=12*(i.year()-1)+i.month()-15292;return i.day()+o[a-1]-1+24e5-.5},fromJD:function(t){for(var e=t-24e5+.5,r=0,n=0;ne);n++)r++;var i=r+15292,a=Math.floor((i-1)/12),s=a+1,l=i-12*a,c=e-o[r-1]+1;return this.newDate(s,l,c)},isValid:function(t,e,r){var i=n.baseCalendar.prototype.isValid.apply(this,arguments);return i&&(i=(t=null!=t.year?t.year:t)>=1276&&t<=1500),i},_validate:function(t,e,r,i){var a=n.baseCalendar.prototype._validate.apply(this,arguments);if(a.year<1276||a.year>1500)throw i.replace(/\{0\}/,this.local.name);return a}}),n.calendars.ummalqura=a;var o=[20,50,79,109,138,168,197,227,256,286,315,345,374,404,433,463,492,522,551,581,611,641,670,700,729,759,788,818,847,877,906,936,965,995,1024,1054,1083,1113,1142,1172,1201,1231,1260,1290,1320,1350,1379,1409,1438,1468,1497,1527,1556,1586,1615,1645,1674,1704,1733,1763,1792,1822,1851,1881,1910,1940,1969,1999,2028,2058,2087,2117,2146,2176,2205,2235,2264,2294,2323,2353,2383,2413,2442,2472,2501,2531,2560,2590,2619,2649,2678,2708,2737,2767,2796,2826,2855,2885,2914,2944,2973,3003,3032,3062,3091,3121,3150,3180,3209,3239,3268,3298,3327,3357,3386,3416,3446,3476,3505,3535,3564,3594,3623,3653,3682,3712,3741,3771,3800,3830,3859,3889,3918,3948,3977,4007,4036,4066,4095,4125,4155,4185,4214,4244,4273,4303,4332,4362,4391,4421,4450,4480,4509,4539,4568,4598,4627,4657,4686,4716,4745,4775,4804,4834,4863,4893,4922,4952,4981,5011,5040,5070,5099,5129,5158,5188,5218,5248,5277,5307,5336,5366,5395,5425,5454,5484,5513,5543,5572,5602,5631,5661,5690,5720,5749,5779,5808,5838,5867,5897,5926,5956,5985,6015,6044,6074,6103,6133,6162,6192,6221,6251,6281,6311,6340,6370,6399,6429,6458,6488,6517,6547,6576,6606,6635,6665,6694,6724,6753,6783,6812,6842,6871,6901,6930,6960,6989,7019,7048,7078,7107,7137,7166,7196,7225,7255,7284,7314,7344,7374,7403,7433,7462,7492,7521,7551,7580,7610,7639,7669,7698,7728,7757,7787,7816,7846,7875,7905,7934,7964,7993,8023,8053,8083,8112,8142,8171,8201,8230,8260,8289,8319,8348,8378,8407,8437,8466,8496,8525,8555,8584,8614,8643,8673,8702,8732,8761,8791,8821,8850,8880,8909,8938,8968,8997,9027,9056,9086,9115,9145,9175,9205,9234,9264,9293,9322,9352,9381,9410,9440,9470,9499,9529,9559,9589,9618,9648,9677,9706,9736,9765,9794,9824,9853,9883,9913,9943,9972,10002,10032,10061,10090,10120,10149,10178,10208,10237,10267,10297,10326,10356,10386,10415,10445,10474,10504,10533,10562,10592,10621,10651,10680,10710,10740,10770,10799,10829,10858,10888,10917,10947,10976,11005,11035,11064,11094,11124,11153,11183,11213,11242,11272,11301,11331,11360,11389,11419,11448,11478,11507,11537,11567,11596,11626,11655,11685,11715,11744,11774,11803,11832,11862,11891,11921,11950,11980,12010,12039,12069,12099,12128,12158,12187,12216,12246,12275,12304,12334,12364,12393,12423,12453,12483,12512,12542,12571,12600,12630,12659,12688,12718,12747,12777,12807,12837,12866,12896,12926,12955,12984,13014,13043,13072,13102,13131,13161,13191,13220,13250,13280,13310,13339,13368,13398,13427,13456,13486,13515,13545,13574,13604,13634,13664,13693,13723,13752,13782,13811,13840,13870,13899,13929,13958,13988,14018,14047,14077,14107,14136,14166,14195,14224,14254,14283,14313,14342,14372,14401,14431,14461,14490,14520,14550,14579,14609,14638,14667,14697,14726,14756,14785,14815,14844,14874,14904,14933,14963,14993,15021,15051,15081,15110,15140,15169,15199,15228,15258,15287,15317,15347,15377,15406,15436,15465,15494,15524,15553,15582,15612,15641,15671,15701,15731,15760,15790,15820,15849,15878,15908,15937,15966,15996,16025,16055,16085,16114,16144,16174,16204,16233,16262,16292,16321,16350,16380,16409,16439,16468,16498,16528,16558,16587,16617,16646,16676,16705,16734,16764,16793,16823,16852,16882,16912,16941,16971,17001,17030,17060,17089,17118,17148,17177,17207,17236,17266,17295,17325,17355,17384,17414,17444,17473,17502,17532,17561,17591,17620,17650,17679,17709,17738,17768,17798,17827,17857,17886,17916,17945,17975,18004,18034,18063,18093,18122,18152,18181,18211,18241,18270,18300,18330,18359,18388,18418,18447,18476,18506,18535,18565,18595,18625,18654,18684,18714,18743,18772,18802,18831,18860,18890,18919,18949,18979,19008,19038,19068,19098,19127,19156,19186,19215,19244,19274,19303,19333,19362,19392,19422,19452,19481,19511,19540,19570,19599,19628,19658,19687,19717,19746,19776,19806,19836,19865,19895,19924,19954,19983,20012,20042,20071,20101,20130,20160,20190,20219,20249,20279,20308,20338,20367,20396,20426,20455,20485,20514,20544,20573,20603,20633,20662,20692,20721,20751,20780,20810,20839,20869,20898,20928,20957,20987,21016,21046,21076,21105,21135,21164,21194,21223,21253,21282,21312,21341,21371,21400,21430,21459,21489,21519,21548,21578,21607,21637,21666,21696,21725,21754,21784,21813,21843,21873,21902,21932,21962,21991,22021,22050,22080,22109,22138,22168,22197,22227,22256,22286,22316,22346,22375,22405,22434,22464,22493,22522,22552,22581,22611,22640,22670,22700,22730,22759,22789,22818,22848,22877,22906,22936,22965,22994,23024,23054,23083,23113,23143,23173,23202,23232,23261,23290,23320,23349,23379,23408,23438,23467,23497,23527,23556,23586,23616,23645,23674,23704,23733,23763,23792,23822,23851,23881,23910,23940,23970,23999,24029,24058,24088,24117,24147,24176,24206,24235,24265,24294,24324,24353,24383,24413,24442,24472,24501,24531,24560,24590,24619,24648,24678,24707,24737,24767,24796,24826,24856,24885,24915,24944,24974,25003,25032,25062,25091,25121,25150,25180,25210,25240,25269,25299,25328,25358,25387,25416,25446,25475,25505,25534,25564,25594,25624,25653,25683,25712,25742,25771,25800,25830,25859,25888,25918,25948,25977,26007,26037,26067,26096,26126,26155,26184,26214,26243,26272,26302,26332,26361,26391,26421,26451,26480,26510,26539,26568,26598,26627,26656,26686,26715,26745,26775,26805,26834,26864,26893,26923,26952,26982,27011,27041,27070,27099,27129,27159,27188,27218,27248,27277,27307,27336,27366,27395,27425,27454,27484,27513,27542,27572,27602,27631,27661,27691,27720,27750,27779,27809,27838,27868,27897,27926,27956,27985,28015,28045,28074,28104,28134,28163,28193,28222,28252,28281,28310,28340,28369,28399,28428,28458,28488,28517,28547,28577,28607,28636,28665,28695,28724,28754,28783,28813,28843,28872,28901,28931,28960,28990,29019,29049,29078,29108,29137,29167,29196,29226,29255,29285,29315,29345,29375,29404,29434,29463,29492,29522,29551,29580,29610,29640,29669,29699,29729,29759,29788,29818,29847,29876,29906,29935,29964,29994,30023,30053,30082,30112,30141,30171,30200,30230,30259,30289,30318,30348,30378,30408,30437,30467,30496,30526,30555,30585,30614,30644,30673,30703,30732,30762,30791,30821,30850,30880,30909,30939,30968,30998,31027,31057,31086,31116,31145,31175,31204,31234,31263,31293,31322,31352,31381,31411,31441,31471,31500,31530,31559,31589,31618,31648,31676,31706,31736,31766,31795,31825,31854,31884,31913,31943,31972,32002,32031,32061,32090,32120,32150,32180,32209,32239,32268,32298,32327,32357,32386,32416,32445,32475,32504,32534,32563,32593,32622,32652,32681,32711,32740,32770,32799,32829,32858,32888,32917,32947,32976,33006,33035,33065,33094,33124,33153,33183,33213,33243,33272,33302,33331,33361,33390,33420,33450,33479,33509,33539,33568,33598,33627,33657,33686,33716,33745,33775,33804,33834,33863,33893,33922,33952,33981,34011,34040,34069,34099,34128,34158,34187,34217,34247,34277,34306,34336,34365,34395,34424,34454,34483,34512,34542,34571,34601,34631,34660,34690,34719,34749,34778,34808,34837,34867,34896,34926,34955,34985,35015,35044,35074,35103,35133,35162,35192,35222,35251,35280,35310,35340,35370,35399,35429,35458,35488,35517,35547,35576,35605,35635,35665,35694,35723,35753,35782,35811,35841,35871,35901,35930,35960,35989,36019,36048,36078,36107,36136,36166,36195,36225,36254,36284,36314,36343,36373,36403,36433,36462,36492,36521,36551,36580,36610,36639,36669,36698,36728,36757,36786,36816,36845,36875,36904,36934,36963,36993,37022,37052,37081,37111,37141,37170,37200,37229,37259,37288,37318,37347,37377,37406,37436,37465,37495,37524,37554,37584,37613,37643,37672,37701,37731,37760,37790,37819,37849,37878,37908,37938,37967,37997,38027,38056,38085,38115,38144,38174,38203,38233,38262,38292,38322,38351,38381,38410,38440,38469,38499,38528,38558,38587,38617,38646,38676,38705,38735,38764,38794,38823,38853,38882,38912,38941,38971,39001,39030,39059,39089,39118,39148,39178,39208,39237,39267,39297,39326,39355,39385,39414,39444,39473,39503,39532,39562,39592,39621,39650,39680,39709,39739,39768,39798,39827,39857,39886,39916,39946,39975,40005,40035,40064,40094,40123,40153,40182,40212,40241,40271,40300,40330,40359,40389,40418,40448,40477,40507,40536,40566,40595,40625,40655,40685,40714,40744,40773,40803,40832,40862,40892,40921,40951,40980,41009,41039,41068,41098,41127,41157,41186,41216,41245,41275,41304,41334,41364,41393,41422,41452,41481,41511,41540,41570,41599,41629,41658,41688,41718,41748,41777,41807,41836,41865,41894,41924,41953,41983,42012,42042,42072,42102,42131,42161,42190,42220,42249,42279,42308,42337,42367,42397,42426,42456,42485,42515,42545,42574,42604,42633,42662,42692,42721,42751,42780,42810,42839,42869,42899,42929,42958,42988,43017,43046,43076,43105,43135,43164,43194,43223,43253,43283,43312,43342,43371,43401,43430,43460,43489,43519,43548,43578,43607,43637,43666,43696,43726,43755,43785,43814,43844,43873,43903,43932,43962,43991,44021,44050,44080,44109,44139,44169,44198,44228,44258,44287,44317,44346,44375,44405,44434,44464,44493,44523,44553,44582,44612,44641,44671,44700,44730,44759,44788,44818,44847,44877,44906,44936,44966,44996,45025,45055,45084,45114,45143,45172,45202,45231,45261,45290,45320,45350,45380,45409,45439,45468,45498,45527,45556,45586,45615,45644,45674,45704,45733,45763,45793,45823,45852,45882,45911,45940,45970,45999,46028,46058,46088,46117,46147,46177,46206,46236,46265,46295,46324,46354,46383,46413,46442,46472,46501,46531,46560,46590,46620,46649,46679,46708,46738,46767,46797,46826,46856,46885,46915,46944,46974,47003,47033,47063,47092,47122,47151,47181,47210,47240,47269,47298,47328,47357,47387,47417,47446,47476,47506,47535,47565,47594,47624,47653,47682,47712,47741,47771,47800,47830,47860,47890,47919,47949,47978,48008,48037,48066,48096,48125,48155,48184,48214,48244,48273,48303,48333,48362,48392,48421,48450,48480,48509,48538,48568,48598,48627,48657,48687,48717,48746,48776,48805,48834,48864,48893,48922,48952,48982,49011,49041,49071,49100,49130,49160,49189,49218,49248,49277,49306,49336,49365,49395,49425,49455,49484,49514,49543,49573,49602,49632,49661,49690,49720,49749,49779,49809,49838,49868,49898,49927,49957,49986,50016,50045,50075,50104,50133,50163,50192,50222,50252,50281,50311,50340,50370,50400,50429,50459,50488,50518,50547,50576,50606,50635,50665,50694,50724,50754,50784,50813,50843,50872,50902,50931,50960,50990,51019,51049,51078,51108,51138,51167,51197,51227,51256,51286,51315,51345,51374,51403,51433,51462,51492,51522,51552,51582,51611,51641,51670,51699,51729,51758,51787,51816,51846,51876,51906,51936,51965,51995,52025,52054,52083,52113,52142,52171,52200,52230,52260,52290,52319,52349,52379,52408,52438,52467,52497,52526,52555,52585,52614,52644,52673,52703,52733,52762,52792,52822,52851,52881,52910,52939,52969,52998,53028,53057,53087,53116,53146,53176,53205,53235,53264,53294,53324,53353,53383,53412,53441,53471,53500,53530,53559,53589,53619,53648,53678,53708,53737,53767,53796,53825,53855,53884,53913,53943,53973,54003,54032,54062,54092,54121,54151,54180,54209,54239,54268,54297,54327,54357,54387,54416,54446,54476,54505,54535,54564,54593,54623,54652,54681,54711,54741,54770,54800,54830,54859,54889,54919,54948,54977,55007,55036,55066,55095,55125,55154,55184,55213,55243,55273,55302,55332,55361,55391,55420,55450,55479,55508,55538,55567,55597,55627,55657,55686,55716,55745,55775,55804,55834,55863,55892,55922,55951,55981,56011,56040,56070,56100,56129,56159,56188,56218,56247,56276,56306,56335,56365,56394,56424,56454,56483,56513,56543,56572,56601,56631,56660,56690,56719,56749,56778,56808,56837,56867,56897,56926,56956,56985,57015,57044,57074,57103,57133,57162,57192,57221,57251,57280,57310,57340,57369,57399,57429,57458,57487,57517,57546,57576,57605,57634,57664,57694,57723,57753,57783,57813,57842,57871,57901,57930,57959,57989,58018,58048,58077,58107,58137,58167,58196,58226,58255,58285,58314,58343,58373,58402,58432,58461,58491,58521,58551,58580,58610,58639,58669,58698,58727,58757,58786,58816,58845,58875,58905,58934,58964,58994,59023,59053,59082,59111,59141,59170,59200,59229,59259,59288,59318,59348,59377,59407,59436,59466,59495,59525,59554,59584,59613,59643,59672,59702,59731,59761,59791,59820,59850,59879,59909,59939,59968,59997,60027,60056,60086,60115,60145,60174,60204,60234,60264,60293,60323,60352,60381,60411,60440,60469,60499,60528,60558,60588,60618,60648,60677,60707,60736,60765,60795,60824,60853,60883,60912,60942,60972,61002,61031,61061,61090,61120,61149,61179,61208,61237,61267,61296,61326,61356,61385,61415,61445,61474,61504,61533,61563,61592,61621,61651,61680,61710,61739,61769,61799,61828,61858,61888,61917,61947,61976,62006,62035,62064,62094,62123,62153,62182,62212,62242,62271,62301,62331,62360,62390,62419,62448,62478,62507,62537,62566,62596,62625,62655,62685,62715,62744,62774,62803,62832,62862,62891,62921,62950,62980,63009,63039,63069,63099,63128,63157,63187,63216,63246,63275,63305,63334,63363,63393,63423,63453,63482,63512,63541,63571,63600,63630,63659,63689,63718,63747,63777,63807,63836,63866,63895,63925,63955,63984,64014,64043,64073,64102,64131,64161,64190,64220,64249,64279,64309,64339,64368,64398,64427,64457,64486,64515,64545,64574,64603,64633,64663,64692,64722,64752,64782,64811,64841,64870,64899,64929,64958,64987,65017,65047,65076,65106,65136,65166,65195,65225,65254,65283,65313,65342,65371,65401,65431,65460,65490,65520,65549,65579,65608,65638,65667,65697,65726,65755,65785,65815,65844,65874,65903,65933,65963,65992,66022,66051,66081,66110,66140,66169,66199,66228,66258,66287,66317,66346,66376,66405,66435,66465,66494,66524,66553,66583,66612,66641,66671,66700,66730,66760,66789,66819,66849,66878,66908,66937,66967,66996,67025,67055,67084,67114,67143,67173,67203,67233,67262,67292,67321,67351,67380,67409,67439,67468,67497,67527,67557,67587,67617,67646,67676,67705,67735,67764,67793,67823,67852,67882,67911,67941,67971,68e3,68030,68060,68089,68119,68148,68177,68207,68236,68266,68295,68325,68354,68384,68414,68443,68473,68502,68532,68561,68591,68620,68650,68679,68708,68738,68768,68797,68827,68857,68886,68916,68946,68975,69004,69034,69063,69092,69122,69152,69181,69211,69240,69270,69300,69330,69359,69388,69418,69447,69476,69506,69535,69565,69595,69624,69654,69684,69713,69743,69772,69802,69831,69861,69890,69919,69949,69978,70008,70038,70067,70097,70126,70156,70186,70215,70245,70274,70303,70333,70362,70392,70421,70451,70481,70510,70540,70570,70599,70629,70658,70687,70717,70746,70776,70805,70835,70864,70894,70924,70954,70983,71013,71042,71071,71101,71130,71159,71189,71218,71248,71278,71308,71337,71367,71397,71426,71455,71485,71514,71543,71573,71602,71632,71662,71691,71721,71751,71781,71810,71839,71869,71898,71927,71957,71986,72016,72046,72075,72105,72135,72164,72194,72223,72253,72282,72311,72341,72370,72400,72429,72459,72489,72518,72548,72577,72607,72637,72666,72695,72725,72754,72784,72813,72843,72872,72902,72931,72961,72991,73020,73050,73080,73109,73139,73168,73197,73227,73256,73286,73315,73345,73375,73404,73434,73464,73493,73523,73552,73581,73611,73640,73669,73699,73729,73758,73788,73818,73848,73877,73907,73936,73965,73995,74024,74053,74083,74113,74142,74172,74202,74231,74261,74291,74320,74349,74379,74408,74437,74467,74497,74526,74556,74586,74615,74645,74675,74704,74733,74763,74792,74822,74851,74881,74910,74940,74969,74999,75029,75058,75088,75117,75147,75176,75206,75235,75264,75294,75323,75353,75383,75412,75442,75472,75501,75531,75560,75590,75619,75648,75678,75707,75737,75766,75796,75826,75856,75885,75915,75944,75974,76003,76032,76062,76091,76121,76150,76180,76210,76239,76269,76299,76328,76358,76387,76416,76446,76475,76505,76534,76564,76593,76623,76653,76682,76712,76741,76771,76801,76830,76859,76889,76918,76948,76977,77007,77036,77066,77096,77125,77155,77185,77214,77243,77273,77302,77332,77361,77390,77420,77450,77479,77509,77539,77569,77598,77627,77657,77686,77715,77745,77774,77804,77833,77863,77893,77923,77952,77982,78011,78041,78070,78099,78129,78158,78188,78217,78247,78277,78307,78336,78366,78395,78425,78454,78483,78513,78542,78572,78601,78631,78661,78690,78720,78750,78779,78808,78838,78867,78897,78926,78956,78985,79015,79044,79074,79104,79133,79163,79192,79222,79251,79281,79310,79340,79369,79399,79428,79458,79487,79517,79546,79576,79606,79635,79665,79695,79724,79753,79783,79812,79841,79871,79900,79930,79960,79990]},{"../main":548,"object-assign":437}],548:[function(t,e,r){var n=t("object-assign");function i(){this.regionalOptions=[],this.regionalOptions[""]={invalidCalendar:"Calendar {0} not found",invalidDate:"Invalid {0} date",invalidMonth:"Invalid {0} month",invalidYear:"Invalid {0} year",differentCalendars:"Cannot mix {0} and {1} dates"},this.local=this.regionalOptions[""],this.calendars={},this._localCals={}}function a(t,e,r,n){if(this._calendar=t,this._year=e,this._month=r,this._day=n,0===this._calendar._validateLevel&&!this._calendar.isValid(this._year,this._month,this._day))throw(c.local.invalidDate||c.regionalOptions[""].invalidDate).replace(/\{0\}/,this._calendar.local.name)}function o(t,e){return"000000".substring(0,e-(t=""+t).length)+t}function s(){this.shortYearCutoff="+10"}function l(t){this.local=this.regionalOptions[t]||this.regionalOptions[""]}n(i.prototype,{instance:function(t,e){t=(t||"gregorian").toLowerCase(),e=e||"";var r=this._localCals[t+"-"+e];if(!r&&this.calendars[t]&&(r=new this.calendars[t](e),this._localCals[t+"-"+e]=r),!r)throw(this.local.invalidCalendar||this.regionalOptions[""].invalidCalendar).replace(/\{0\}/,t);return r},newDate:function(t,e,r,n,i){return(n=(null!=t&&t.year?t.calendar():"string"==typeof n?this.instance(n,i):n)||this.instance()).newDate(t,e,r)},substituteDigits:function(t){return function(e){return(e+"").replace(/[0-9]/g,function(e){return t[e]})}},substituteChineseDigits:function(t,e){return function(r){for(var n="",i=0;r>0;){var a=r%10;n=(0===a?"":t[a]+e[i])+n,i++,r=Math.floor(r/10)}return 0===n.indexOf(t[1]+e[1])&&(n=n.substr(1)),n||t[0]}}}),n(a.prototype,{newDate:function(t,e,r){return this._calendar.newDate(null==t?this:t,e,r)},year:function(t){return 0===arguments.length?this._year:this.set(t,"y")},month:function(t){return 0===arguments.length?this._month:this.set(t,"m")},day:function(t){return 0===arguments.length?this._day:this.set(t,"d")},date:function(t,e,r){if(!this._calendar.isValid(t,e,r))throw(c.local.invalidDate||c.regionalOptions[""].invalidDate).replace(/\{0\}/,this._calendar.local.name);return this._year=t,this._month=e,this._day=r,this},leapYear:function(){return this._calendar.leapYear(this)},epoch:function(){return this._calendar.epoch(this)},formatYear:function(){return this._calendar.formatYear(this)},monthOfYear:function(){return this._calendar.monthOfYear(this)},weekOfYear:function(){return this._calendar.weekOfYear(this)},daysInYear:function(){return this._calendar.daysInYear(this)},dayOfYear:function(){return this._calendar.dayOfYear(this)},daysInMonth:function(){return this._calendar.daysInMonth(this)},dayOfWeek:function(){return this._calendar.dayOfWeek(this)},weekDay:function(){return this._calendar.weekDay(this)},extraInfo:function(){return this._calendar.extraInfo(this)},add:function(t,e){return this._calendar.add(this,t,e)},set:function(t,e){return this._calendar.set(this,t,e)},compareTo:function(t){if(this._calendar.name!==t._calendar.name)throw(c.local.differentCalendars||c.regionalOptions[""].differentCalendars).replace(/\{0\}/,this._calendar.local.name).replace(/\{1\}/,t._calendar.local.name);var e=this._year!==t._year?this._year-t._year:this._month!==t._month?this.monthOfYear()-t.monthOfYear():this._day-t._day;return 0===e?0:e<0?-1:1},calendar:function(){return this._calendar},toJD:function(){return this._calendar.toJD(this)},fromJD:function(t){return this._calendar.fromJD(t)},toJSDate:function(){return this._calendar.toJSDate(this)},fromJSDate:function(t){return this._calendar.fromJSDate(t)},toString:function(){return(this.year()<0?"-":"")+o(Math.abs(this.year()),4)+"-"+o(this.month(),2)+"-"+o(this.day(),2)}}),n(s.prototype,{_validateLevel:0,newDate:function(t,e,r){return null==t?this.today():(t.year&&(this._validate(t,e,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),r=t.day(),e=t.month(),t=t.year()),new a(this,t,e,r))},today:function(){return this.fromJSDate(new Date)},epoch:function(t){return this._validate(t,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear).year()<0?this.local.epochs[0]:this.local.epochs[1]},formatYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear);return(e.year()<0?"-":"")+o(Math.abs(e.year()),4)},monthsInYear:function(t){return this._validate(t,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear),12},monthOfYear:function(t,e){var r=this._validate(t,e,this.minDay,c.local.invalidMonth||c.regionalOptions[""].invalidMonth);return(r.month()+this.monthsInYear(r)-this.firstMonth)%this.monthsInYear(r)+this.minMonth},fromMonthOfYear:function(t,e){var r=(e+this.firstMonth-2*this.minMonth)%this.monthsInYear(t)+this.minMonth;return this._validate(t,r,this.minDay,c.local.invalidMonth||c.regionalOptions[""].invalidMonth),r},daysInYear:function(t){var e=this._validate(t,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear);return this.leapYear(e)?366:365},dayOfYear:function(t,e,r){var n=this._validate(t,e,r,c.local.invalidDate||c.regionalOptions[""].invalidDate);return n.toJD()-this.newDate(n.year(),this.fromMonthOfYear(n.year(),this.minMonth),this.minDay).toJD()+1},daysInWeek:function(){return 7},dayOfWeek:function(t,e,r){var n=this._validate(t,e,r,c.local.invalidDate||c.regionalOptions[""].invalidDate);return(Math.floor(this.toJD(n))+2)%this.daysInWeek()},extraInfo:function(t,e,r){return this._validate(t,e,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),{}},add:function(t,e,r){return this._validate(t,this.minMonth,this.minDay,c.local.invalidDate||c.regionalOptions[""].invalidDate),this._correctAdd(t,this._add(t,e,r),e,r)},_add:function(t,e,r){if(this._validateLevel++,"d"===r||"w"===r){var n=t.toJD()+e*("w"===r?this.daysInWeek():1),i=t.calendar().fromJD(n);return this._validateLevel--,[i.year(),i.month(),i.day()]}try{var a=t.year()+("y"===r?e:0),o=t.monthOfYear()+("m"===r?e:0);i=t.day();"y"===r?(t.month()!==this.fromMonthOfYear(a,o)&&(o=this.newDate(a,t.month(),this.minDay).monthOfYear()),o=Math.min(o,this.monthsInYear(a)),i=Math.min(i,this.daysInMonth(a,this.fromMonthOfYear(a,o)))):"m"===r&&(!function(t){for(;oe-1+t.minMonth;)a++,o-=e,e=t.monthsInYear(a)}(this),i=Math.min(i,this.daysInMonth(a,this.fromMonthOfYear(a,o))));var s=[a,this.fromMonthOfYear(a,o),i];return this._validateLevel--,s}catch(t){throw this._validateLevel--,t}},_correctAdd:function(t,e,r,n){if(!(this.hasYearZero||"y"!==n&&"m"!==n||0!==e[0]&&t.year()>0==e[0]>0)){var i={y:[1,1,"y"],m:[1,this.monthsInYear(-1),"m"],w:[this.daysInWeek(),this.daysInYear(-1),"d"],d:[1,this.daysInYear(-1),"d"]}[n],a=r<0?-1:1;e=this._add(t,r*i[0]+a*i[1],i[2])}return t.date(e[0],e[1],e[2])},set:function(t,e,r){this._validate(t,this.minMonth,this.minDay,c.local.invalidDate||c.regionalOptions[""].invalidDate);var n="y"===r?e:t.year(),i="m"===r?e:t.month(),a="d"===r?e:t.day();return"y"!==r&&"m"!==r||(a=Math.min(a,this.daysInMonth(n,i))),t.date(n,i,a)},isValid:function(t,e,r){this._validateLevel++;var n=this.hasYearZero||0!==t;if(n){var i=this.newDate(t,e,this.minDay);n=e>=this.minMonth&&e-this.minMonth=this.minDay&&r-this.minDay13.5?13:1),c=i-(l>2.5?4716:4715);return c<=0&&c--,this.newDate(c,l,s)},toJSDate:function(t,e,r){var n=this._validate(t,e,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),i=new Date(n.year(),n.month()-1,n.day());return i.setHours(0),i.setMinutes(0),i.setSeconds(0),i.setMilliseconds(0),i.setHours(i.getHours()>12?i.getHours()+2:0),i},fromJSDate:function(t){return this.newDate(t.getFullYear(),t.getMonth()+1,t.getDate())}});var c=e.exports=new i;c.cdate=a,c.baseCalendar=s,c.calendars.gregorian=l},{"object-assign":437}],549:[function(t,e,r){var n=t("object-assign"),i=t("./main");n(i.regionalOptions[""],{invalidArguments:"Invalid arguments",invalidFormat:"Cannot format a date from another calendar",missingNumberAt:"Missing number at position {0}",unknownNameAt:"Unknown name at position {0}",unexpectedLiteralAt:"Unexpected literal at position {0}",unexpectedText:"Additional text found at end"}),i.local=i.regionalOptions[""],n(i.cdate.prototype,{formatDate:function(t,e){return"string"!=typeof t&&(e=t,t=""),this._calendar.formatDate(t||"",this,e)}}),n(i.baseCalendar.prototype,{UNIX_EPOCH:i.instance().newDate(1970,1,1).toJD(),SECS_PER_DAY:86400,TICKS_EPOCH:i.instance().jdEpoch,TICKS_PER_DAY:864e9,ATOM:"yyyy-mm-dd",COOKIE:"D, dd M yyyy",FULL:"DD, MM d, yyyy",ISO_8601:"yyyy-mm-dd",JULIAN:"J",RFC_822:"D, d M yy",RFC_850:"DD, dd-M-yy",RFC_1036:"D, d M yy",RFC_1123:"D, d M yyyy",RFC_2822:"D, d M yyyy",RSS:"D, d M yy",TICKS:"!",TIMESTAMP:"@",W3C:"yyyy-mm-dd",formatDate:function(t,e,r){if("string"!=typeof t&&(r=e,e=t,t=""),!e)return"";if(e.calendar()!==this)throw i.local.invalidFormat||i.regionalOptions[""].invalidFormat;t=t||this.local.dateFormat;for(var n,a,o,s,l=(r=r||{}).dayNamesShort||this.local.dayNamesShort,c=r.dayNames||this.local.dayNames,u=r.monthNumbers||this.local.monthNumbers,f=r.monthNamesShort||this.local.monthNamesShort,h=r.monthNames||this.local.monthNames,p=(r.calculateWeek||this.local.calculateWeek,function(e,r){for(var n=1;w+n1}),d=function(t,e,r,n){var i=""+e;if(p(t,n))for(;i.length1},x=function(t,r){var n=y(t,r),a=[2,3,n?4:2,n?4:2,10,11,20]["oyYJ@!".indexOf(t)+1],o=new RegExp("^-?\\d{1,"+a+"}"),s=e.substring(A).match(o);if(!s)throw(i.local.missingNumberAt||i.regionalOptions[""].missingNumberAt).replace(/\{0\}/,A);return A+=s[0].length,parseInt(s[0],10)},b=this,_=function(){if("function"==typeof l){y("m");var t=l.call(b,e.substring(A));return A+=t.length,t}return x("m")},w=function(t,r,n,a){for(var o=y(t,a)?n:r,s=0;s-1){p=1,d=m;for(var E=this.daysInMonth(h,p);d>E;E=this.daysInMonth(h,p))p++,d-=E}return f>-1?this.fromJD(f):this.newDate(h,p,d)},determineDate:function(t,e,r,n,i){r&&"object"!=typeof r&&(i=n,n=r,r=null),"string"!=typeof n&&(i=n,n="");var a=this;return e=e?e.newDate():null,t=null==t?e:"string"==typeof t?function(t){try{return a.parseDate(n,t,i)}catch(t){}for(var e=((t=t.toLowerCase()).match(/^c/)&&r?r.newDate():null)||a.today(),o=/([+-]?[0-9]+)\s*(d|w|m|y)?/g,s=o.exec(t);s;)e.add(parseInt(s[1],10),s[2]||"d"),s=o.exec(t);return e}(t):"number"==typeof t?isNaN(t)||t===1/0||t===-1/0?e:a.today().add(t,"d"):a.newDate(t)}})},{"./main":548,"object-assign":437}],550:[function(t,e,r){e.exports=t("cwise-compiler")({args:["array",{offset:[1],array:0},"scalar","scalar","index"],pre:{body:"{}",args:[],thisVars:[],localVars:[]},post:{body:"{}",args:[],thisVars:[],localVars:[]},body:{body:"{\n var _inline_1_da = _inline_1_arg0_ - _inline_1_arg3_\n var _inline_1_db = _inline_1_arg1_ - _inline_1_arg3_\n if((_inline_1_da >= 0) !== (_inline_1_db >= 0)) {\n _inline_1_arg2_.push(_inline_1_arg4_[0] + 0.5 + 0.5 * (_inline_1_da + _inline_1_db) / (_inline_1_da - _inline_1_db))\n }\n }",args:[{name:"_inline_1_arg0_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_1_arg1_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_1_arg2_",lvalue:!1,rvalue:!0,count:1},{name:"_inline_1_arg3_",lvalue:!1,rvalue:!0,count:2},{name:"_inline_1_arg4_",lvalue:!1,rvalue:!0,count:1}],thisVars:[],localVars:["_inline_1_da","_inline_1_db"]},funcName:"zeroCrossings"})},{"cwise-compiler":134}],551:[function(t,e,r){"use strict";e.exports=function(t,e){var r=[];return e=+e||0,n(t.hi(t.shape[0]-1),r,e),r};var n=t("./lib/zc-core")},{"./lib/zc-core":550}],552:[function(t,e,r){"use strict";e.exports=[{path:"",backoff:0},{path:"M-2.4,-3V3L0.6,0Z",backoff:.6},{path:"M-3.7,-2.5V2.5L1.3,0Z",backoff:1.3},{path:"M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z",backoff:1.55},{path:"M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z",backoff:1.6},{path:"M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z",backoff:2},{path:"M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z",backoff:0,noRotate:!0},{path:"M2,2V-2H-2V2Z",backoff:0,noRotate:!0}]},{}],553:[function(t,e,r){"use strict";var n=t("./arrow_paths"),i=t("../../plots/font_attributes"),a=t("../../plots/cartesian/constants"),o=t("../../plot_api/plot_template").templatedArray;e.exports=o("annotation",{visible:{valType:"boolean",dflt:!0,editType:"calc+arraydraw"},text:{valType:"string",editType:"calc+arraydraw"},textangle:{valType:"angle",dflt:0,editType:"calc+arraydraw"},font:i({editType:"calc+arraydraw",colorEditType:"arraydraw"}),width:{valType:"number",min:1,dflt:null,editType:"calc+arraydraw"},height:{valType:"number",min:1,dflt:null,editType:"calc+arraydraw"},opacity:{valType:"number",min:0,max:1,dflt:1,editType:"arraydraw"},align:{valType:"enumerated",values:["left","center","right"],dflt:"center",editType:"arraydraw"},valign:{valType:"enumerated",values:["top","middle","bottom"],dflt:"middle",editType:"arraydraw"},bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"arraydraw"},bordercolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"arraydraw"},borderpad:{valType:"number",min:0,dflt:1,editType:"calc+arraydraw"},borderwidth:{valType:"number",min:0,dflt:1,editType:"calc+arraydraw"},showarrow:{valType:"boolean",dflt:!0,editType:"calc+arraydraw"},arrowcolor:{valType:"color",editType:"arraydraw"},arrowhead:{valType:"integer",min:0,max:n.length,dflt:1,editType:"arraydraw"},startarrowhead:{valType:"integer",min:0,max:n.length,dflt:1,editType:"arraydraw"},arrowside:{valType:"flaglist",flags:["end","start"],extras:["none"],dflt:"end",editType:"arraydraw"},arrowsize:{valType:"number",min:.3,dflt:1,editType:"calc+arraydraw"},startarrowsize:{valType:"number",min:.3,dflt:1,editType:"calc+arraydraw"},arrowwidth:{valType:"number",min:.1,editType:"calc+arraydraw"},standoff:{valType:"number",min:0,dflt:0,editType:"calc+arraydraw"},startstandoff:{valType:"number",min:0,dflt:0,editType:"calc+arraydraw"},ax:{valType:"any",editType:"calc+arraydraw"},ay:{valType:"any",editType:"calc+arraydraw"},axref:{valType:"enumerated",dflt:"pixel",values:["pixel",a.idRegex.x.toString()],editType:"calc"},ayref:{valType:"enumerated",dflt:"pixel",values:["pixel",a.idRegex.y.toString()],editType:"calc"},xref:{valType:"enumerated",values:["paper",a.idRegex.x.toString()],editType:"calc"},x:{valType:"any",editType:"calc+arraydraw"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto",editType:"calc+arraydraw"},xshift:{valType:"number",dflt:0,editType:"calc+arraydraw"},yref:{valType:"enumerated",values:["paper",a.idRegex.y.toString()],editType:"calc"},y:{valType:"any",editType:"calc+arraydraw"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto",editType:"calc+arraydraw"},yshift:{valType:"number",dflt:0,editType:"calc+arraydraw"},clicktoshow:{valType:"enumerated",values:[!1,"onoff","onout"],dflt:!1,editType:"arraydraw"},xclick:{valType:"any",editType:"arraydraw"},yclick:{valType:"any",editType:"arraydraw"},hovertext:{valType:"string",editType:"arraydraw"},hoverlabel:{bgcolor:{valType:"color",editType:"arraydraw"},bordercolor:{valType:"color",editType:"arraydraw"},font:i({editType:"arraydraw"}),editType:"arraydraw"},captureevents:{valType:"boolean",editType:"arraydraw"},editType:"calc",_deprecated:{ref:{valType:"string",editType:"calc"}}})},{"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750,"../../plots/font_attributes":771,"./arrow_paths":552}],554:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../plots/cartesian/axes"),a=t("./draw").draw;function o(t){var e=t._fullLayout;n.filterVisible(e.annotations).forEach(function(e){var r=i.getFromId(t,e.xref),n=i.getFromId(t,e.yref);e._extremes={},r&&s(e,r),n&&s(e,n)})}function s(t,e){var r,n=e._id,a=n.charAt(0),o=t[a],s=t["a"+a],l=t[a+"ref"],c=t["a"+a+"ref"],u=t["_"+a+"padplus"],f=t["_"+a+"padminus"],h={x:1,y:-1}[a]*t[a+"shift"],p=3*t.arrowsize*t.arrowwidth||0,d=p+h,m=p-h,g=3*t.startarrowsize*t.arrowwidth||0,v=g+h,y=g-h;if(c===l){var x=i.findExtremes(e,[e.r2c(o)],{ppadplus:d,ppadminus:m}),b=i.findExtremes(e,[e.r2c(s)],{ppadplus:Math.max(u,v),ppadminus:Math.max(f,y)});r={min:[x.min[0],b.min[0]],max:[x.max[0],b.max[0]]}}else v=s?v+s:v,y=s?y-s:y,r=i.findExtremes(e,[e.r2c(o)],{ppadplus:Math.max(u,d,v),ppadminus:Math.max(f,m,y)});t._extremes[n]=r}e.exports=function(t){var e=t._fullLayout;if(n.filterVisible(e.annotations).length&&t._fullData.length)return n.syncOrAsync([a,o],t)}},{"../../lib":696,"../../plots/cartesian/axes":744,"./draw":559}],555:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("../../plot_api/plot_template").arrayEditor;function o(t,e){var r,n,i,a,o,l,c,u=t._fullLayout.annotations,f=[],h=[],p=[],d=(e||[]).length;for(r=0;r0||r.explicitOff.length>0},onClick:function(t,e){var r,s,l=o(t,e),c=l.on,u=l.off.concat(l.explicitOff),f={},h=t._fullLayout.annotations;if(!c.length&&!u.length)return;for(r=0;r2/3?"right":"center"),{center:0,middle:0,left:.5,bottom:-.5,right:-.5,top:.5}[e]}for(var q=!1,H=["x","y"],G=0;G1)&&(Q===K?((lt=tt.r2fraction(e["a"+J]))<0||lt>1)&&(q=!0):q=!0),W=tt._offset+tt.r2p(e[J]),Z=.5}else"x"===J?(X=e[J],W=b.l+b.w*X):(X=1-e[J],W=b.t+b.h*X),Z=e.showarrow?.5:X;if(e.showarrow){st.head=W;var ct=e["a"+J];$=rt*U(.5,e.xanchor)-nt*U(.5,e.yanchor),Q===K?(st.tail=tt._offset+tt.r2p(ct),Y=$):(st.tail=W+ct,Y=$+ct),st.text=st.tail+$;var ut=x["x"===J?"width":"height"];if("paper"===K&&(st.head=o.constrain(st.head,1,ut-1)),"pixel"===Q){var ft=-Math.max(st.tail-3,st.text),ht=Math.min(st.tail+3,st.text)-ut;ft>0?(st.tail+=ft,st.text+=ft):ht>0&&(st.tail-=ht,st.text-=ht)}st.tail+=ot,st.head+=ot}else Y=$=it*U(Z,at),st.text=W+$;st.text+=ot,$+=ot,Y+=ot,e["_"+J+"padplus"]=it/2+Y,e["_"+J+"padminus"]=it/2-Y,e["_"+J+"size"]=it,e["_"+J+"shift"]=$}if(t._dragging||!q){var pt=0,dt=0;if("left"!==e.align&&(pt=(w-v)*("center"===e.align?.5:1)),"top"!==e.valign&&(dt=(O-y)*("middle"===e.valign?.5:1)),u)n.select("svg").attr({x:R+pt-1,y:R+dt}).call(c.setClipUrl,F?T:null);else{var mt=R+dt-d.top,gt=R+pt-d.left;V.call(f.positionText,gt,mt).call(c.setClipUrl,F?T:null)}N.select("rect").call(c.setRect,R,R,w,O),B.call(c.setRect,P/2,P/2,D-P,j-P),I.call(c.setTranslate,Math.round(S.x.text-D/2),Math.round(S.y.text-j/2)),L.attr({transform:"rotate("+E+","+S.x.text+","+S.y.text+")"});var vt,yt=function(r,n){C.selectAll(".annotation-arrow-g").remove();var u=S.x.head,f=S.y.head,h=S.x.tail+r,d=S.y.tail+n,v=S.x.text+r,y=S.y.text+n,x=o.rotationXYMatrix(E,v,y),w=o.apply2DTransform(x),T=o.apply2DTransform2(x),z=+B.attr("width"),O=+B.attr("height"),P=v-.5*z,D=P+z,R=y-.5*O,F=R+O,N=[[P,R,P,F],[P,F,D,F],[D,F,D,R],[D,R,P,R]].map(T);if(!N.reduce(function(t,e){return t^!!o.segmentsIntersect(u,f,u+1e6,f+1e6,e[0],e[1],e[2],e[3])},!1)){N.forEach(function(t){var e=o.segmentsIntersect(h,d,u,f,t[0],t[1],t[2],t[3]);e&&(h=e.x,d=e.y)});var j=e.arrowwidth,V=e.arrowcolor,U=e.arrowside,q=C.append("g").style({opacity:l.opacity(V)}).classed("annotation-arrow-g",!0),H=q.append("path").attr("d","M"+h+","+d+"L"+u+","+f).style("stroke-width",j+"px").call(l.stroke,l.rgb(V));if(m(H,U,e),_.annotationPosition&&H.node().parentNode&&!a){var G=u,W=f;if(e.standoff){var Y=Math.sqrt(Math.pow(u-h,2)+Math.pow(f-d,2));G+=e.standoff*(h-u)/Y,W+=e.standoff*(d-f)/Y}var X,Z,$=q.append("path").classed("annotation-arrow",!0).classed("anndrag",!0).classed("cursor-move",!0).attr({d:"M3,3H-3V-3H3ZM0,0L"+(h-G)+","+(d-W),transform:"translate("+G+","+W+")"}).style("stroke-width",j+6+"px").call(l.stroke,"rgba(0,0,0,0)").call(l.fill,"rgba(0,0,0,0)");p.init({element:$.node(),gd:t,prepFn:function(){var t=c.getTranslate(I);X=t.x,Z=t.y,s&&s.autorange&&k(s._name+".autorange",!0),g&&g.autorange&&k(g._name+".autorange",!0)},moveFn:function(t,r){var n=w(X,Z),i=n[0]+t,a=n[1]+r;I.call(c.setTranslate,i,a),M("x",s?s.p2r(s.r2p(e.x)+t):e.x+t/b.w),M("y",g?g.p2r(g.r2p(e.y)+r):e.y-r/b.h),e.axref===e.xref&&M("ax",s.p2r(s.r2p(e.ax)+t)),e.ayref===e.yref&&M("ay",g.p2r(g.r2p(e.ay)+r)),q.attr("transform","translate("+t+","+r+")"),L.attr({transform:"rotate("+E+","+i+","+a+")"})},doneFn:function(){i.call("_guiRelayout",t,A());var e=document.querySelector(".js-notes-box-panel");e&&e.redraw(e.selectedObj)}})}}};if(e.showarrow&&yt(0,0),z)p.init({element:I.node(),gd:t,prepFn:function(){vt=L.attr("transform")},moveFn:function(t,r){var n="pointer";if(e.showarrow)e.axref===e.xref?M("ax",s.p2r(s.r2p(e.ax)+t)):M("ax",e.ax+t),e.ayref===e.yref?M("ay",g.p2r(g.r2p(e.ay)+r)):M("ay",e.ay+r),yt(t,r);else{if(a)return;var i,o;if(s)i=s.p2r(s.r2p(e.x)+t);else{var l=e._xsize/b.w,c=e.x+(e._xshift-e.xshift)/b.w-l/2;i=p.align(c+t/b.w,l,0,1,e.xanchor)}if(g)o=g.p2r(g.r2p(e.y)+r);else{var u=e._ysize/b.h,f=e.y-(e._yshift+e.yshift)/b.h-u/2;o=p.align(f-r/b.h,u,0,1,e.yanchor)}M("x",i),M("y",o),s&&g||(n=p.getCursor(s?.5:i,g?.5:o,e.xanchor,e.yanchor))}L.attr({transform:"translate("+t+","+r+")"+vt}),h(I,n)},doneFn:function(){h(I),i.call("_guiRelayout",t,A());var e=document.querySelector(".js-notes-box-panel");e&&e.redraw(e.selectedObj)}})}else I.remove()}}e.exports={draw:function(t){var e=t._fullLayout;e._infolayer.selectAll(".annotation").remove();for(var r=0;r=0,g=e.indexOf("end")>=0,v=f.backoff*p+r.standoff,y=h.backoff*d+r.startstandoff;if("line"===u.nodeName){o={x:+t.attr("x1"),y:+t.attr("y1")},s={x:+t.attr("x2"),y:+t.attr("y2")};var x=o.x-s.x,b=o.y-s.y;if(c=(l=Math.atan2(b,x))+Math.PI,v&&y&&v+y>Math.sqrt(x*x+b*b))return void z();if(v){if(v*v>x*x+b*b)return void z();var _=v*Math.cos(l),w=v*Math.sin(l);s.x+=_,s.y+=w,t.attr({x2:s.x,y2:s.y})}if(y){if(y*y>x*x+b*b)return void z();var k=y*Math.cos(l),M=y*Math.sin(l);o.x-=k,o.y-=M,t.attr({x1:o.x,y1:o.y})}}else if("path"===u.nodeName){var A=u.getTotalLength(),T="";if(A1){c=!0;break}}c?t.fullLayout._infolayer.select(".annotation-"+t.id+'[data-index="'+s+'"]').remove():(l._pdata=i(t.glplot.cameraParams,[e.xaxis.r2l(l.x)*r[0],e.yaxis.r2l(l.y)*r[1],e.zaxis.r2l(l.z)*r[2]]),n(t.graphDiv,l,s,t.id,l._xa,l._ya))}}},{"../../plots/gl3d/project":796,"../annotations/draw":559}],566:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib");e.exports={moduleType:"component",name:"annotations3d",schema:{subplots:{scene:{annotations:t("./attributes")}}},layoutAttributes:t("./attributes"),handleDefaults:t("./defaults"),includeBasePlot:function(t,e){var r=n.subplotsRegistry.gl3d;if(!r)return;for(var a=r.attrRegex,o=Object.keys(t),s=0;s=0))return t;if(3===o)n[o]>1&&(n[o]=1);else if(n[o]>=1)return t}var s=Math.round(255*n[0])+", "+Math.round(255*n[1])+", "+Math.round(255*n[2]);return a?"rgba("+s+", "+n[3]+")":"rgb("+s+")"}a.tinyRGB=function(t){var e=t.toRgb();return"rgb("+Math.round(e.r)+", "+Math.round(e.g)+", "+Math.round(e.b)+")"},a.rgb=function(t){return a.tinyRGB(n(t))},a.opacity=function(t){return t?n(t).getAlpha():0},a.addOpacity=function(t,e){var r=n(t).toRgb();return"rgba("+Math.round(r.r)+", "+Math.round(r.g)+", "+Math.round(r.b)+", "+e+")"},a.combine=function(t,e){var r=n(t).toRgb();if(1===r.a)return n(t).toRgbString();var i=n(e||l).toRgb(),a=1===i.a?i:{r:255*(1-i.a)+i.r*i.a,g:255*(1-i.a)+i.g*i.a,b:255*(1-i.a)+i.b*i.a},o={r:a.r*(1-r.a)+r.r*r.a,g:a.g*(1-r.a)+r.g*r.a,b:a.b*(1-r.a)+r.b*r.a};return n(o).toRgbString()},a.contrast=function(t,e,r){var i=n(t);return 1!==i.getAlpha()&&(i=n(a.combine(t,l))),(i.isDark()?e?i.lighten(e):l:r?i.darken(r):s).toString()},a.stroke=function(t,e){var r=n(e);t.style({stroke:a.tinyRGB(r),"stroke-opacity":r.getAlpha()})},a.fill=function(t,e){var r=n(e);t.style({fill:a.tinyRGB(r),"fill-opacity":r.getAlpha()})},a.clean=function(t){if(t&&"object"==typeof t){var e,r,n,i,o=Object.keys(t);for(e=0;e0?E>=D:E<=D));C++)E>B&&E0?E>=D:E<=D));C++)E>L[0]&&E1){var ot=Math.pow(10,Math.floor(Math.log(at)/Math.LN10));nt*=ot*c.roundUp(at/ot,[2,5,10]),(Math.abs(r.levels.start)/r.levels.size+1e-6)%1<2e-6&&(et.tick0=0)}et.dtick=nt}et.domain=[J+X,J+G-X],et.setScale();var st=c.ensureSingle(g._infolayer,"g",e,function(t){t.classed(M.colorbar,!0).each(function(){var t=n.select(this);t.append("rect").classed(M.cbbg,!0),t.append("g").classed(M.cbfills,!0),t.append("g").classed(M.cblines,!0),t.append("g").classed(M.cbaxis,!0).classed(M.crisp,!0),t.append("g").classed(M.cbtitleunshift,!0).append("g").classed(M.cbtitle,!0),t.append("rect").classed(M.cboutline,!0),t.select(".cbtitle").datum(0)})});st.attr("transform","translate("+Math.round(k.l)+","+Math.round(k.t)+")");var lt=st.select(".cbtitleunshift").attr("transform","translate(-"+Math.round(k.l)+",-"+Math.round(k.t)+")");et._axislayer=st.select(".cbaxis");var ct=0;if(-1!==["top","bottom"].indexOf(r.titleside)){var ut,ft=k.l+(r.x+W)*k.w,ht=et.titlefont.size;ut="top"===r.titleside?(1-(J+G-X))*k.h+k.t+3+.75*ht:(1-(J+X))*k.h+k.t-3-.25*ht,yt(et._id+"title",{attributes:{x:ft,y:ut,"text-anchor":"start"}})}var pt,dt,mt,gt=c.syncOrAsync([a.previousPromises,function(){if(-1!==["top","bottom"].indexOf(r.titleside)){var a=st.select(".cbtitle"),o=a.select("text"),l=[-r.outlinewidth/2,r.outlinewidth/2],u=a.select(".h"+et._id+"title-math-group").node(),f=15.6;if(o.node()&&(f=parseInt(o.node().style.fontSize,10)*v),u?(ct=h.bBox(u).height)>f&&(l[1]-=(ct-f)/2):o.node()&&!o.classed(M.jsPlaceholder)&&(ct=h.bBox(o.node()).height),ct){if(ct+=5,"top"===r.titleside)et.domain[1]-=ct/k.h,l[1]*=-1;else{et.domain[0]+=ct/k.h;var p=m.lineCount(o);l[1]+=(1-p)*f}a.attr("transform","translate("+l+")"),et.setScale()}}st.selectAll(".cbfills,.cblines").attr("transform","translate(0,"+Math.round(k.h*(1-et.domain[1]))+")"),et._axislayer.attr("transform","translate(0,"+Math.round(-k.t)+")");var d=st.select(".cbfills").selectAll("rect.cbfill").data(O);d.enter().append("rect").classed(M.cbfill,!0).style("stroke","none"),d.exit().remove();var y=L.map(et.c2p).map(Math.round).sort(function(t,e){return t-e});d.each(function(a,o){var s=[0===o?L[0]:(O[o]+O[o-1])/2,o===O.length-1?L[1]:(O[o]+O[o+1])/2].map(et.c2p).map(Math.round);s[1]=c.constrain(s[1]+(s[1]>s[0])?1:-1,y[0],y[1]);var l=n.select(this).attr({x:Z,width:Math.max(U,2),y:n.min(s),height:Math.max(n.max(s)-n.min(s),2)});if(r.fillgradient)h.gradient(l,t,e,"vertical",r.fillgradient,"fill");else{var u=P(a).replace("e-","");l.attr("fill",i(u).toHexString())}});var x=st.select(".cblines").selectAll("path.cbline").data(r.line.color&&r.line.width?z:[]);return x.enter().append("path").classed(M.cbline,!0),x.exit().remove(),x.each(function(t){n.select(this).attr("d","M"+Z+","+(Math.round(et.c2p(t))+r.line.width/2%1)+"h"+U).call(h.lineGroupStyle,r.line.width,I(t),r.line.dash)}),et._axislayer.selectAll("g."+et._id+"tick,path").remove(),et._pos=Z+U+(r.outlinewidth||0)/2-("outside"===r.ticks?1:0),et.side="right",c.syncOrAsync([function(){return s.doTicksSingle(t,et,!0)},function(){if(-1===["top","bottom"].indexOf(r.titleside)){var e=et.titlefont.size,i=et._offset+et._length/2,a=k.l+(et.position||0)*k.w+("right"===et.side?10+e*(et.showticklabels?1:.5):-10-e*(et.showticklabels?.5:0));yt("h"+et._id+"title",{avoid:{selection:n.select(t).selectAll("g."+et._id+"tick"),side:r.titleside,offsetLeft:k.l,offsetTop:0,maxShift:g.width},attributes:{x:a,y:i,"text-anchor":"middle"},transform:{rotate:"-90",offset:0}})}}])},a.previousPromises,function(){var n=U+r.outlinewidth/2+h.bBox(et._axislayer.node()).width;if((N=lt.select("text")).node()&&!N.classed(M.jsPlaceholder)){var i,o=lt.select(".h"+et._id+"title-math-group").node();i=o&&-1!==["top","bottom"].indexOf(r.titleside)?h.bBox(o).width:h.bBox(lt.node()).right-Z-k.l,n=Math.max(n,i)}var s=2*r.xpad+n+r.borderwidth+r.outlinewidth/2,l=K-Q;st.select(".cbbg").attr({x:Z-r.xpad-(r.borderwidth+r.outlinewidth)/2,y:Q-Y,width:Math.max(s,2),height:Math.max(l+2*Y,2)}).call(p.fill,r.bgcolor).call(p.stroke,r.bordercolor).style({"stroke-width":r.borderwidth}),st.selectAll(".cboutline").attr({x:Z,y:Q+r.ypad+("top"===r.titleside?ct:0),width:Math.max(U,2),height:Math.max(l-2*r.ypad-ct,2)}).call(p.stroke,r.outlinecolor).style({fill:"None","stroke-width":r.outlinewidth});var c=({center:.5,right:1}[r.xanchor]||0)*s;st.attr("transform","translate("+(k.l-c)+","+k.t+")");var u={},f=y[r.yanchor],d=x[r.yanchor];"pixels"===r.lenmode?(u.y=r.y,u.t=l*f,u.b=l*d):(u.t=u.b=0,u.yt=r.y+r.len*f,u.yb=r.y-r.len*d);var m=y[r.xanchor],g=x[r.xanchor];if("pixels"===r.thicknessmode)u.x=r.x,u.l=s*m,u.r=s*g;else{var v=s-U;u.l=v*m,u.r=v*g,u.xl=r.x-r.thickness*m,u.xr=r.x+r.thickness*g}a.autoMargin(t,e,u)}],t);if(gt&>.then&&(t._promises||[]).push(gt),t._context.edits.colorbarPosition)l.init({element:st.node(),gd:t,prepFn:function(){pt=st.attr("transform"),f(st)},moveFn:function(t,e){st.attr("transform",pt+" translate("+t+","+e+")"),dt=l.align($+t/k.w,q,0,1,r.xanchor),mt=l.align(J-e/k.h,G,0,1,r.yanchor);var n=l.getCursor(dt,mt,r.xanchor,r.yanchor);f(st,n)},doneFn:function(){if(f(st),void 0!==dt&&void 0!==mt){var e={};e[S("x")]=dt,e[S("y")]=mt,o.call("_guiRestyle",t,e,T().index)}}});return gt}function vt(t,e){return c.coerce(tt,et,w,t,e)}function yt(e,r){var n={propContainer:et,propName:S("title"),traceIndex:T().index,placeholder:g._dfltTitle.colorbar,containerGroup:st.select(".cbtitle")},i="h"===e.charAt(0)?e.substr(1):"h"+e;st.selectAll("."+i+",."+i+"-math-group").remove(),d.draw(t,e,u(n,r||{}))}g._infolayer.selectAll("g."+e).remove()}function T(){var r,n,i=e.substr(2);for(r=0;r=0?i.Reds:i.Blues,s.reversescale?a(y):y),l.autocolorscale||f("autocolorscale",!1))}},{"../../lib":696,"./flip_scale":582,"./scales":589}],579:[function(t,e,r){"use strict";var n=t("./scales");e.exports=n.RdBu},{"./scales":589}],580:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../lib"),a=t("../colorbar/has_colorbar"),o=t("../colorbar/defaults"),s=t("./is_valid_scale"),l=t("./flip_scale");e.exports=function(t,e,r,c,u){var f,h=u.prefix,p=u.cLetter,d=h.slice(0,h.length-1),m=h?i.nestedProperty(t,d).get()||{}:t,g=h?i.nestedProperty(e,d).get()||{}:e,v=m[p+"min"],y=m[p+"max"],x=m.colorscale;c(h+p+"auto",!(n(v)&&n(y)&&v=0;i--,a++)e=t[i],n[a]=[1-e[0],e[1]];return n}},{}],583:[function(t,e,r){"use strict";var n=t("./scales"),i=t("./default_scale"),a=t("./is_valid_scale_array");e.exports=function(t,e){if(e||(e=i),!t)return e;function r(){try{t=n[t]||JSON.parse(t)}catch(r){t=e}}return"string"==typeof t&&(r(),"string"==typeof t&&r()),a(t)?t:e}},{"./default_scale":579,"./is_valid_scale_array":587,"./scales":589}],584:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../lib"),a=t("./is_valid_scale");e.exports=function(t,e){var r=e?i.nestedProperty(t,e).get()||{}:t,o=r.color,s=!1;if(i.isArrayOrTypedArray(o))for(var l=0;l4/3-s?o:s}},{}],591:[function(t,e,r){"use strict";var n=t("../../lib"),i=[["sw-resize","s-resize","se-resize"],["w-resize","move","e-resize"],["nw-resize","n-resize","ne-resize"]];e.exports=function(t,e,r,a){return t="left"===r?0:"center"===r?1:"right"===r?2:n.constrain(Math.floor(3*t),0,2),e="bottom"===a?0:"middle"===a?1:"top"===a?2:n.constrain(Math.floor(3*e),0,2),i[e][t]}},{"../../lib":696}],592:[function(t,e,r){"use strict";var n=t("mouse-event-offset"),i=t("has-hover"),a=t("has-passive-events"),o=t("../../registry"),s=t("../../lib"),l=t("../../plots/cartesian/constants"),c=t("../../constants/interactions"),u=e.exports={};u.align=t("./align"),u.getCursor=t("./cursor");var f=t("./unhover");function h(){var t=document.createElement("div");t.className="dragcover";var e=t.style;return e.position="fixed",e.left=0,e.right=0,e.top=0,e.bottom=0,e.zIndex=999999999,e.background="none",document.body.appendChild(t),t}function p(t){return n(t.changedTouches?t.changedTouches[0]:t,document.body)}u.unhover=f.wrapped,u.unhoverRaw=f.raw,u.init=function(t){var e,r,n,f,d,m,g,v,y=t.gd,x=1,b=c.DBLCLICKDELAY,_=t.element;y._mouseDownTime||(y._mouseDownTime=0),_.style.pointerEvents="all",_.onmousedown=k,a?(_._ontouchstart&&_.removeEventListener("touchstart",_._ontouchstart),_._ontouchstart=k,_.addEventListener("touchstart",k,{passive:!1})):_.ontouchstart=k;var w=t.clampFn||function(t,e,r){return Math.abs(t)b&&(x=Math.max(x-1,1)),y._dragged)t.doneFn&&t.doneFn();else if(t.clickFn&&t.clickFn(x,m),!v){var r;try{r=new MouseEvent("click",e)}catch(t){var n=p(e);(r=document.createEvent("MouseEvents")).initMouseEvent("click",e.bubbles,e.cancelable,e.view,e.detail,e.screenX,e.screenY,n[0],n[1],e.ctrlKey,e.altKey,e.shiftKey,e.metaKey,e.button,e.relatedTarget)}g.dispatchEvent(r)}!function(t){t._dragging=!1,t._replotPending&&o.call("plot",t)}(y),y._dragged=!1}else y._dragged=!1}},u.coverSlip=h},{"../../constants/interactions":672,"../../lib":696,"../../plots/cartesian/constants":750,"../../registry":827,"./align":590,"./cursor":591,"./unhover":593,"has-hover":393,"has-passive-events":394,"mouse-event-offset":419}],593:[function(t,e,r){"use strict";var n=t("../../lib/events"),i=t("../../lib/throttle"),a=t("../../lib/get_graph_div"),o=t("../fx/constants"),s=e.exports={};s.wrapped=function(t,e,r){(t=a(t))._fullLayout&&i.clear(t._fullLayout._uid+o.HOVERID),s.raw(t,e,r)},s.raw=function(t,e){var r=t._fullLayout,i=t._hoverdata;e||(e={}),e.target&&!1===n.triggerHandler(t,"plotly_beforehover",e)||(r._hoverlayer.selectAll("g").remove(),r._hoverlayer.selectAll("line").remove(),r._hoverlayer.selectAll("circle").remove(),t._hoverdata=void 0,e.target&&i&&t.emit("plotly_unhover",{event:e,points:i}))}},{"../../lib/events":684,"../../lib/get_graph_div":691,"../../lib/throttle":721,"../fx/constants":607}],594:[function(t,e,r){"use strict";r.dash={valType:"string",values:["solid","dot","dash","longdash","dashdot","longdashdot"],dflt:"solid",editType:"style"}},{}],595:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("fast-isnumeric"),a=t("tinycolor2"),o=t("../../registry"),s=t("../color"),l=t("../colorscale"),c=t("../../lib"),u=t("../../lib/svg_text_utils"),f=t("../../constants/xmlns_namespaces"),h=t("../../constants/alignment").LINE_SPACING,p=t("../../constants/interactions").DESELECTDIM,d=t("../../traces/scatter/subtypes"),m=t("../../traces/scatter/make_bubble_size_func"),g=e.exports={};g.font=function(t,e,r,n){c.isPlainObject(e)&&(n=e.color,r=e.size,e=e.family),e&&t.style("font-family",e),r+1&&t.style("font-size",r+"px"),n&&t.call(s.fill,n)},g.setPosition=function(t,e,r){t.attr("x",e).attr("y",r)},g.setSize=function(t,e,r){t.attr("width",e).attr("height",r)},g.setRect=function(t,e,r,n,i){t.call(g.setPosition,e,r).call(g.setSize,n,i)},g.translatePoint=function(t,e,r,n){var a=r.c2p(t.x),o=n.c2p(t.y);return!!(i(a)&&i(o)&&e.node())&&("text"===e.node().nodeName?e.attr("x",a).attr("y",o):e.attr("transform","translate("+a+","+o+")"),!0)},g.translatePoints=function(t,e,r){t.each(function(t){var i=n.select(this);g.translatePoint(t,i,e,r)})},g.hideOutsideRangePoint=function(t,e,r,n,i,a){e.attr("display",r.isPtWithinRange(t,i)&&n.isPtWithinRange(t,a)?null:"none")},g.hideOutsideRangePoints=function(t,e){if(e._hasClipOnAxisFalse){var r=e.xaxis,i=e.yaxis;t.each(function(e){var a=e[0].trace,o=a.xcalendar,s=a.ycalendar,l="bar"===a.type?".bartext":".point,.textpoint";t.selectAll(l).each(function(t){g.hideOutsideRangePoint(t,n.select(this),r,i,o,s)})})}},g.crispRound=function(t,e,r){return e&&i(e)?t._context.staticPlot?e:e<1?1:Math.round(e):r||0},g.singleLineStyle=function(t,e,r,n,i){e.style("fill","none");var a=(((t||[])[0]||{}).trace||{}).line||{},o=r||a.width||0,l=i||a.dash||"";s.stroke(e,n||a.color),g.dashLine(e,l,o)},g.lineGroupStyle=function(t,e,r,i){t.style("fill","none").each(function(t){var a=(((t||[])[0]||{}).trace||{}).line||{},o=e||a.width||0,l=i||a.dash||"";n.select(this).call(s.stroke,r||a.color).call(g.dashLine,l,o)})},g.dashLine=function(t,e,r){r=+r||0,e=g.dashStyle(e,r),t.style({"stroke-dasharray":e,"stroke-width":r+"px"})},g.dashStyle=function(t,e){e=+e||1;var r=Math.max(e,3);return"solid"===t?t="":"dot"===t?t=r+"px,"+r+"px":"dash"===t?t=3*r+"px,"+3*r+"px":"longdash"===t?t=5*r+"px,"+5*r+"px":"dashdot"===t?t=3*r+"px,"+r+"px,"+r+"px,"+r+"px":"longdashdot"===t&&(t=5*r+"px,"+2*r+"px,"+r+"px,"+2*r+"px"),t},g.singleFillStyle=function(t){var e=(((n.select(t.node()).data()[0]||[])[0]||{}).trace||{}).fillcolor;e&&t.call(s.fill,e)},g.fillGroupStyle=function(t){t.style("stroke-width",0).each(function(t){n.select(this).call(s.fill,t[0].trace.fillcolor)})};var v=t("./symbol_defs");g.symbolNames=[],g.symbolFuncs=[],g.symbolNeedLines={},g.symbolNoDot={},g.symbolNoFill={},g.symbolList=[],Object.keys(v).forEach(function(t){var e=v[t];g.symbolList=g.symbolList.concat([e.n,t,e.n+100,t+"-open"]),g.symbolNames[e.n]=t,g.symbolFuncs[e.n]=e.f,e.needLine&&(g.symbolNeedLines[e.n]=!0),e.noDot?g.symbolNoDot[e.n]=!0:g.symbolList=g.symbolList.concat([e.n+200,t+"-dot",e.n+300,t+"-open-dot"]),e.noFill&&(g.symbolNoFill[e.n]=!0)});var y=g.symbolNames.length,x="M0,0.5L0.5,0L0,-0.5L-0.5,0Z";function b(t,e){var r=t%100;return g.symbolFuncs[r](e)+(t>=200?x:"")}g.symbolNumber=function(t){if("string"==typeof t){var e=0;t.indexOf("-open")>0&&(e=100,t=t.replace("-open","")),t.indexOf("-dot")>0&&(e+=200,t=t.replace("-dot","")),(t=g.symbolNames.indexOf(t))>=0&&(t+=e)}return t%100>=y||t>=400?0:Math.floor(Math.max(t,0))};var _={x1:1,x2:0,y1:0,y2:0},w={x1:0,x2:0,y1:1,y2:0},k=n.format("~.1f"),M={radial:{node:"radialGradient"},radialreversed:{node:"radialGradient",reversed:!0},horizontal:{node:"linearGradient",attrs:_},horizontalreversed:{node:"linearGradient",attrs:_,reversed:!0},vertical:{node:"linearGradient",attrs:w},verticalreversed:{node:"linearGradient",attrs:w,reversed:!0}};g.gradient=function(t,e,r,i,o,l){for(var u=o.length,f=M[i],h=new Array(u),p=0;p=100,e.attr("d",b(u,l))}var f,h,p,d=!1;if(t.so)p=o.outlierwidth,h=o.outliercolor,f=a.outliercolor;else{var m=(o||{}).width;p=(t.mlw+1||m+1||(t.trace?(t.trace.marker.line||{}).width:0)+1)-1||0,h="mlc"in t?t.mlcc=n.lineScale(t.mlc):c.isArrayOrTypedArray(o.color)?s.defaultLine:o.color,c.isArrayOrTypedArray(a.color)&&(f=s.defaultLine,d=!0),f="mc"in t?t.mcc=n.markerScale(t.mc):a.color||"rgba(0,0,0,0)",n.selectedColorFn&&(f=n.selectedColorFn(t))}if(t.om)e.call(s.stroke,f).style({"stroke-width":(p||1)+"px",fill:"none"});else{e.style("stroke-width",p+"px");var v=a.gradient,y=t.mgt;if(y?d=!0:y=v&&v.type,Array.isArray(y)&&(y=y[0],M[y]||(y=0)),y&&"none"!==y){var x=t.mgc;x?d=!0:x=v.color;var _=r.uid;d&&(_+="-"+t.i),g.gradient(e,i,_,y,[[0,x],[1,f]],"fill")}else s.fill(e,f);p&&s.stroke(e,h)}},g.makePointStyleFns=function(t){var e={},r=t.marker;return e.markerScale=g.tryColorscale(r,""),e.lineScale=g.tryColorscale(r,"line"),o.traceIs(t,"symbols")&&(e.ms2mrc=d.isBubble(t)?m(t):function(){return(r.size||6)/2}),t.selectedpoints&&c.extendFlat(e,g.makeSelectedPointStyleFns(t)),e},g.makeSelectedPointStyleFns=function(t){var e={},r=t.selected||{},n=t.unselected||{},i=t.marker||{},a=r.marker||{},s=n.marker||{},l=i.opacity,u=a.opacity,f=s.opacity,h=void 0!==u,d=void 0!==f;(c.isArrayOrTypedArray(l)||h||d)&&(e.selectedOpacityFn=function(t){var e=void 0===t.mo?i.opacity:t.mo;return t.selected?h?u:e:d?f:p*e});var m=i.color,g=a.color,v=s.color;(g||v)&&(e.selectedColorFn=function(t){var e=t.mcc||m;return t.selected?g||e:v||e});var y=i.size,x=a.size,b=s.size,_=void 0!==x,w=void 0!==b;return o.traceIs(t,"symbols")&&(_||w)&&(e.selectedSizeFn=function(t){var e=t.mrc||y/2;return t.selected?_?x/2:e:w?b/2:e}),e},g.makeSelectedTextStyleFns=function(t){var e={},r=t.selected||{},n=t.unselected||{},i=t.textfont||{},a=r.textfont||{},o=n.textfont||{},l=i.color,c=a.color,u=o.color;return e.selectedTextColorFn=function(t){var e=t.tc||l;return t.selected?c||e:u||(c?e:s.addOpacity(e,p))},e},g.selectedPointStyle=function(t,e){if(t.size()&&e.selectedpoints){var r=g.makeSelectedPointStyleFns(e),i=e.marker||{},a=[];r.selectedOpacityFn&&a.push(function(t,e){t.style("opacity",r.selectedOpacityFn(e))}),r.selectedColorFn&&a.push(function(t,e){s.fill(t,r.selectedColorFn(e))}),r.selectedSizeFn&&a.push(function(t,e){var n=e.mx||i.symbol||0,a=r.selectedSizeFn(e);t.attr("d",b(g.symbolNumber(n),a)),e.mrc2=a}),a.length&&t.each(function(t){for(var e=n.select(this),r=0;r0?r:0}g.textPointStyle=function(t,e,r){if(t.size()){var i;if(e.selectedpoints){var a=g.makeSelectedTextStyleFns(e);i=a.selectedTextColorFn}t.each(function(t){var a=n.select(this),o=c.extractOption(t,e,"tx","text");if(o||0===o){var s=t.tp||e.textposition,l=S(t,e),f=i?i(t):t.tc||e.textfont.color;a.call(g.font,t.tf||e.textfont.family,l,f).text(o).call(u.convertToTspans,r).call(T,s,l,t.mrc)}else a.remove()})}},g.selectedTextStyle=function(t,e){if(t.size()&&e.selectedpoints){var r=g.makeSelectedTextStyleFns(e);t.each(function(t){var i=n.select(this),a=r.selectedTextColorFn(t),o=t.tp||e.textposition,l=S(t,e);s.fill(i,a),T(i,o,l,t.mrc2||t.mrc)})}};var E=.5;function C(t,e,r,i){var a=t[0]-e[0],o=t[1]-e[1],s=r[0]-e[0],l=r[1]-e[1],c=Math.pow(a*a+o*o,E/2),u=Math.pow(s*s+l*l,E/2),f=(u*u*a-c*c*s)*i,h=(u*u*o-c*c*l)*i,p=3*u*(c+u),d=3*c*(c+u);return[[n.round(e[0]+(p&&f/p),2),n.round(e[1]+(p&&h/p),2)],[n.round(e[0]-(d&&f/d),2),n.round(e[1]-(d&&h/d),2)]]}g.smoothopen=function(t,e){if(t.length<3)return"M"+t.join("L");var r,n="M"+t[0],i=[];for(r=1;r=1e4&&(g.savedBBoxes={},O=0),r&&(g.savedBBoxes[r]=v),O++,c.extendFlat({},v)},g.setClipUrl=function(t,e){if(e){if(void 0===g.baseUrl){var r=n.select("base");r.size()&&r.attr("href")?g.baseUrl=window.location.href.split("#")[0]:g.baseUrl=""}t.attr("clip-path","url("+g.baseUrl+"#"+e+")")}else t.attr("clip-path",null)},g.getTranslate=function(t){var e=(t[t.attr?"attr":"getAttribute"]("transform")||"").replace(/.*\btranslate\((-?\d*\.?\d*)[^-\d]*(-?\d*\.?\d*)[^\d].*/,function(t,e,r){return[e,r].join(" ")}).split(" ");return{x:+e[0]||0,y:+e[1]||0}},g.setTranslate=function(t,e,r){var n=t.attr?"attr":"getAttribute",i=t.attr?"attr":"setAttribute",a=t[n]("transform")||"";return e=e||0,r=r||0,a=a.replace(/(\btranslate\(.*?\);?)/,"").trim(),a=(a+=" translate("+e+", "+r+")").trim(),t[i]("transform",a),a},g.getScale=function(t){var e=(t[t.attr?"attr":"getAttribute"]("transform")||"").replace(/.*\bscale\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/,function(t,e,r){return[e,r].join(" ")}).split(" ");return{x:+e[0]||1,y:+e[1]||1}},g.setScale=function(t,e,r){var n=t.attr?"attr":"getAttribute",i=t.attr?"attr":"setAttribute",a=t[n]("transform")||"";return e=e||1,r=r||1,a=a.replace(/(\bscale\(.*?\);?)/,"").trim(),a=(a+=" scale("+e+", "+r+")").trim(),t[i]("transform",a),a};var P=/\s*sc.*/;g.setPointGroupScale=function(t,e,r){if(e=e||1,r=r||1,t){var n=1===e&&1===r?"":" scale("+e+","+r+")";t.each(function(){var t=(this.getAttribute("transform")||"").replace(P,"");t=(t+=n).trim(),this.setAttribute("transform",t)})}};var D=/translate\([^)]*\)\s*$/;g.setTextPointsScale=function(t,e,r){t&&t.each(function(){var t,i=n.select(this),a=i.select("text");if(a.node()){var o=parseFloat(a.attr("x")||0),s=parseFloat(a.attr("y")||0),l=(i.attr("transform")||"").match(D);t=1===e&&1===r?[]:["translate("+o+","+s+")","scale("+e+","+r+")","translate("+-o+","+-s+")"],l&&t.push(l),i.attr("transform",t.join(" "))}})}},{"../../constants/alignment":668,"../../constants/interactions":672,"../../constants/xmlns_namespaces":674,"../../lib":696,"../../lib/svg_text_utils":720,"../../registry":827,"../../traces/scatter/make_bubble_size_func":1060,"../../traces/scatter/subtypes":1067,"../color":570,"../colorscale":585,"./symbol_defs":596,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,tinycolor2:514}],596:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js");e.exports={circle:{n:0,f:function(t){var e=n.round(t,2);return"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"}},square:{n:1,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"}},diamond:{n:2,f:function(t){var e=n.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"Z"}},cross:{n:3,f:function(t){var e=n.round(.4*t,2),r=n.round(1.2*t,2);return"M"+r+","+e+"H"+e+"V"+r+"H-"+e+"V"+e+"H-"+r+"V-"+e+"H-"+e+"V-"+r+"H"+e+"V-"+e+"H"+r+"Z"}},x:{n:4,f:function(t){var e=n.round(.8*t/Math.sqrt(2),2),r="l"+e+","+e,i="l"+e+",-"+e,a="l-"+e+",-"+e,o="l-"+e+","+e;return"M0,"+e+r+i+a+i+a+o+a+o+r+o+r+"Z"}},"triangle-up":{n:5,f:function(t){var e=n.round(2*t/Math.sqrt(3),2);return"M-"+e+","+n.round(t/2,2)+"H"+e+"L0,-"+n.round(t,2)+"Z"}},"triangle-down":{n:6,f:function(t){var e=n.round(2*t/Math.sqrt(3),2);return"M-"+e+",-"+n.round(t/2,2)+"H"+e+"L0,"+n.round(t,2)+"Z"}},"triangle-left":{n:7,f:function(t){var e=n.round(2*t/Math.sqrt(3),2);return"M"+n.round(t/2,2)+",-"+e+"V"+e+"L-"+n.round(t,2)+",0Z"}},"triangle-right":{n:8,f:function(t){var e=n.round(2*t/Math.sqrt(3),2);return"M-"+n.round(t/2,2)+",-"+e+"V"+e+"L"+n.round(t,2)+",0Z"}},"triangle-ne":{n:9,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M-"+r+",-"+e+"H"+e+"V"+r+"Z"}},"triangle-se":{n:10,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M"+e+",-"+r+"V"+e+"H-"+r+"Z"}},"triangle-sw":{n:11,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M"+r+","+e+"H-"+e+"V-"+r+"Z"}},"triangle-nw":{n:12,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M-"+e+","+r+"V-"+e+"H"+r+"Z"}},pentagon:{n:13,f:function(t){var e=n.round(.951*t,2),r=n.round(.588*t,2),i=n.round(-t,2),a=n.round(-.309*t,2);return"M"+e+","+a+"L"+r+","+n.round(.809*t,2)+"H-"+r+"L-"+e+","+a+"L0,"+i+"Z"}},hexagon:{n:14,f:function(t){var e=n.round(t,2),r=n.round(t/2,2),i=n.round(t*Math.sqrt(3)/2,2);return"M"+i+",-"+r+"V"+r+"L0,"+e+"L-"+i+","+r+"V-"+r+"L0,-"+e+"Z"}},hexagon2:{n:15,f:function(t){var e=n.round(t,2),r=n.round(t/2,2),i=n.round(t*Math.sqrt(3)/2,2);return"M-"+r+","+i+"H"+r+"L"+e+",0L"+r+",-"+i+"H-"+r+"L-"+e+",0Z"}},octagon:{n:16,f:function(t){var e=n.round(.924*t,2),r=n.round(.383*t,2);return"M-"+r+",-"+e+"H"+r+"L"+e+",-"+r+"V"+r+"L"+r+","+e+"H-"+r+"L-"+e+","+r+"V-"+r+"Z"}},star:{n:17,f:function(t){var e=1.4*t,r=n.round(.225*e,2),i=n.round(.951*e,2),a=n.round(.363*e,2),o=n.round(.588*e,2),s=n.round(-e,2),l=n.round(-.309*e,2),c=n.round(.118*e,2),u=n.round(.809*e,2);return"M"+r+","+l+"H"+i+"L"+a+","+c+"L"+o+","+u+"L0,"+n.round(.382*e,2)+"L-"+o+","+u+"L-"+a+","+c+"L-"+i+","+l+"H-"+r+"L0,"+s+"Z"}},hexagram:{n:18,f:function(t){var e=n.round(.66*t,2),r=n.round(.38*t,2),i=n.round(.76*t,2);return"M-"+i+",0l-"+r+",-"+e+"h"+i+"l"+r+",-"+e+"l"+r+","+e+"h"+i+"l-"+r+","+e+"l"+r+","+e+"h-"+i+"l-"+r+","+e+"l-"+r+",-"+e+"h-"+i+"Z"}},"star-triangle-up":{n:19,f:function(t){var e=n.round(t*Math.sqrt(3)*.8,2),r=n.round(.8*t,2),i=n.round(1.6*t,2),a=n.round(4*t,2),o="A "+a+","+a+" 0 0 1 ";return"M-"+e+","+r+o+e+","+r+o+"0,-"+i+o+"-"+e+","+r+"Z"}},"star-triangle-down":{n:20,f:function(t){var e=n.round(t*Math.sqrt(3)*.8,2),r=n.round(.8*t,2),i=n.round(1.6*t,2),a=n.round(4*t,2),o="A "+a+","+a+" 0 0 1 ";return"M"+e+",-"+r+o+"-"+e+",-"+r+o+"0,"+i+o+e+",-"+r+"Z"}},"star-square":{n:21,f:function(t){var e=n.round(1.1*t,2),r=n.round(2*t,2),i="A "+r+","+r+" 0 0 1 ";return"M-"+e+",-"+e+i+"-"+e+","+e+i+e+","+e+i+e+",-"+e+i+"-"+e+",-"+e+"Z"}},"star-diamond":{n:22,f:function(t){var e=n.round(1.4*t,2),r=n.round(1.9*t,2),i="A "+r+","+r+" 0 0 1 ";return"M-"+e+",0"+i+"0,"+e+i+e+",0"+i+"0,-"+e+i+"-"+e+",0Z"}},"diamond-tall":{n:23,f:function(t){var e=n.round(.7*t,2),r=n.round(1.4*t,2);return"M0,"+r+"L"+e+",0L0,-"+r+"L-"+e+",0Z"}},"diamond-wide":{n:24,f:function(t){var e=n.round(1.4*t,2),r=n.round(.7*t,2);return"M0,"+r+"L"+e+",0L0,-"+r+"L-"+e+",0Z"}},hourglass:{n:25,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"H-"+e+"L"+e+",-"+e+"H-"+e+"Z"},noDot:!0},bowtie:{n:26,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"V-"+e+"L-"+e+","+e+"V-"+e+"Z"},noDot:!0},"circle-cross":{n:27,f:function(t){var e=n.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"circle-x":{n:28,f:function(t){var e=n.round(t,2),r=n.round(t/Math.sqrt(2),2);return"M"+r+","+r+"L-"+r+",-"+r+"M"+r+",-"+r+"L-"+r+","+r+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"square-cross":{n:29,f:function(t){var e=n.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"square-x":{n:30,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"diamond-cross":{n:31,f:function(t){var e=n.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM0,-"+e+"V"+e+"M-"+e+",0H"+e},needLine:!0,noDot:!0},"diamond-x":{n:32,f:function(t){var e=n.round(1.3*t,2),r=n.round(.65*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM-"+r+",-"+r+"L"+r+","+r+"M-"+r+","+r+"L"+r+",-"+r},needLine:!0,noDot:!0},"cross-thin":{n:33,f:function(t){var e=n.round(1.4*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e},needLine:!0,noDot:!0,noFill:!0},"x-thin":{n:34,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0,noFill:!0},asterisk:{n:35,f:function(t){var e=n.round(1.2*t,2),r=n.round(.85*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+r+","+r+"L-"+r+",-"+r+"M"+r+",-"+r+"L-"+r+","+r},needLine:!0,noDot:!0,noFill:!0},hash:{n:36,f:function(t){var e=n.round(t/2,2),r=n.round(t,2);return"M"+e+","+r+"V-"+r+"m-"+r+",0V"+r+"M"+r+","+e+"H-"+r+"m0,-"+r+"H"+r},needLine:!0,noFill:!0},"y-up":{n:37,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),i=n.round(.8*t,2);return"M-"+e+","+i+"L0,0M"+e+","+i+"L0,0M0,-"+r+"L0,0"},needLine:!0,noDot:!0,noFill:!0},"y-down":{n:38,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),i=n.round(.8*t,2);return"M-"+e+",-"+i+"L0,0M"+e+",-"+i+"L0,0M0,"+r+"L0,0"},needLine:!0,noDot:!0,noFill:!0},"y-left":{n:39,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),i=n.round(.8*t,2);return"M"+i+","+e+"L0,0M"+i+",-"+e+"L0,0M-"+r+",0L0,0"},needLine:!0,noDot:!0,noFill:!0},"y-right":{n:40,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),i=n.round(.8*t,2);return"M-"+i+","+e+"L0,0M-"+i+",-"+e+"L0,0M"+r+",0L0,0"},needLine:!0,noDot:!0,noFill:!0},"line-ew":{n:41,f:function(t){var e=n.round(1.4*t,2);return"M"+e+",0H-"+e},needLine:!0,noDot:!0,noFill:!0},"line-ns":{n:42,f:function(t){var e=n.round(1.4*t,2);return"M0,"+e+"V-"+e},needLine:!0,noDot:!0,noFill:!0},"line-ne":{n:43,f:function(t){var e=n.round(t,2);return"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0,noFill:!0},"line-nw":{n:44,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e},needLine:!0,noDot:!0,noFill:!0}}},{"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],597:[function(t,e,r){"use strict";e.exports={visible:{valType:"boolean",editType:"calc"},type:{valType:"enumerated",values:["percent","constant","sqrt","data"],editType:"calc"},symmetric:{valType:"boolean",editType:"calc"},array:{valType:"data_array",editType:"calc"},arrayminus:{valType:"data_array",editType:"calc"},value:{valType:"number",min:0,dflt:10,editType:"calc"},valueminus:{valType:"number",min:0,dflt:10,editType:"calc"},traceref:{valType:"integer",min:0,dflt:0,editType:"style"},tracerefminus:{valType:"integer",min:0,dflt:0,editType:"style"},copy_ystyle:{valType:"boolean",editType:"plot"},copy_zstyle:{valType:"boolean",editType:"style"},color:{valType:"color",editType:"style"},thickness:{valType:"number",min:0,dflt:2,editType:"style"},width:{valType:"number",min:0,editType:"plot"},editType:"calc",_deprecated:{opacity:{valType:"number",editType:"style"}}}},{}],598:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../registry"),a=t("../../plots/cartesian/axes"),o=t("./compute_error");function s(t,e,r,i){var s=e["error_"+i]||{},l=[];if(s.visible&&-1!==["linear","log"].indexOf(r.type)){for(var c=o(s),u=0;u0;t.each(function(t){var u,f=t[0].trace,h=f.error_x||{},p=f.error_y||{};f.ids&&(u=function(t){return t.id});var d=o.hasMarkers(f)&&f.marker.maxdisplayed>0;p.visible||h.visible||(t=[]);var m=n.select(this).selectAll("g.errorbar").data(t,u);if(m.exit().remove(),t.length){h.visible||m.selectAll("path.xerror").remove(),p.visible||m.selectAll("path.yerror").remove(),m.style("opacity",1);var g=m.enter().append("g").classed("errorbar",!0);c&&g.style("opacity",0).transition().duration(r.duration).style("opacity",1),a.setClipUrl(m,e.layerClipId),m.each(function(t){var e=n.select(this),a=function(t,e,r){var n={x:e.c2p(t.x),y:r.c2p(t.y)};void 0!==t.yh&&(n.yh=r.c2p(t.yh),n.ys=r.c2p(t.ys),i(n.ys)||(n.noYS=!0,n.ys=r.c2p(t.ys,!0)));void 0!==t.xh&&(n.xh=e.c2p(t.xh),n.xs=e.c2p(t.xs),i(n.xs)||(n.noXS=!0,n.xs=e.c2p(t.xs,!0)));return n}(t,s,l);if(!d||t.vis){var o,u=e.select("path.yerror");if(p.visible&&i(a.x)&&i(a.yh)&&i(a.ys)){var f=p.width;o="M"+(a.x-f)+","+a.yh+"h"+2*f+"m-"+f+",0V"+a.ys,a.noYS||(o+="m-"+f+",0h"+2*f),!u.size()?u=e.append("path").style("vector-effect","non-scaling-stroke").classed("yerror",!0):c&&(u=u.transition().duration(r.duration).ease(r.easing)),u.attr("d",o)}else u.remove();var m=e.select("path.xerror");if(h.visible&&i(a.y)&&i(a.xh)&&i(a.xs)){var g=(h.copy_ystyle?p:h).width;o="M"+a.xh+","+(a.y-g)+"v"+2*g+"m0,-"+g+"H"+a.xs,a.noXS||(o+="m0,-"+g+"v"+2*g),!m.size()?m=e.append("path").style("vector-effect","non-scaling-stroke").classed("xerror",!0):c&&(m=m.transition().duration(r.duration).ease(r.easing)),m.attr("d",o)}else m.remove()}})}})}},{"../../traces/scatter/subtypes":1067,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],603:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../color");e.exports=function(t){t.each(function(t){var e=t[0].trace,r=e.error_y||{},a=e.error_x||{},o=n.select(this);o.selectAll("path.yerror").style("stroke-width",r.thickness+"px").call(i.stroke,r.color),a.copy_ystyle&&(a=r),o.selectAll("path.xerror").style("stroke-width",a.thickness+"px").call(i.stroke,a.color)})}},{"../color":570,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],604:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes");e.exports={hoverlabel:{bgcolor:{valType:"color",arrayOk:!0,editType:"none"},bordercolor:{valType:"color",arrayOk:!0,editType:"none"},font:n({arrayOk:!0,editType:"none"}),namelength:{valType:"integer",min:-1,arrayOk:!0,editType:"none"},editType:"calc"}}},{"../../plots/font_attributes":771}],605:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry");function a(t,e,r,i){i=i||n.identity,Array.isArray(t)&&(e[0][r]=i(t))}e.exports=function(t){var e=t.calcdata,r=t._fullLayout;function o(t){return function(e){return n.coerceHoverinfo({hoverinfo:e},{_module:t._module},r)}}for(var s=0;s=0&&r.index-1&&o.length>x&&(o=x>3?o.substr(0,x-3)+"...":o.substr(0,x))}void 0!==t.zLabel?(void 0!==t.xLabel&&(c+="x: "+t.xLabel+"
"),void 0!==t.yLabel&&(c+="y: "+t.yLabel+"
"),c+=(c?"z: ":"")+t.zLabel):L&&t[i+"Label"]===M?c=t[("x"===i?"y":"x")+"Label"]||"":void 0===t.xLabel?void 0!==t.yLabel&&(c=t.yLabel):c=void 0===t.yLabel?t.xLabel:"("+t.xLabel+", "+t.yLabel+")",!t.text&&0!==t.text||Array.isArray(t.text)||(c+=(c?"
":"")+t.text),void 0!==t.extraText&&(c+=(c?"
":"")+t.extraText),""===c&&(""===o&&e.remove(),c=o);var b=e.select("text.nums").call(u.font,t.fontFamily||d,t.fontSize||m,t.fontColor||y).text(c).attr("data-notex",1).call(l.positionText,0,0).call(l.convertToTspans,r),_=e.select("text.name"),A=0;o&&o!==c?(_.call(u.font,t.fontFamily||d,t.fontSize||m,g).text(o).attr("data-notex",1).call(l.positionText,0,0).call(l.convertToTspans,r),A=_.node().getBoundingClientRect().width+2*k):(_.remove(),e.select("rect").remove()),e.select("path").style({fill:p,stroke:y});var T,z,O=b.node().getBoundingClientRect(),I=t.xa._offset+(t.x0+t.x1)/2,P=t.ya._offset+(t.y0+t.y1)/2,D=Math.abs(t.x1-t.x0),R=Math.abs(t.y1-t.y0),B=O.width+w+k+A;t.ty0=S-O.top,t.bx=O.width+2*k,t.by=O.height+2*k,t.anchor="start",t.txwidth=O.width,t.tx2width=A,t.offset=0,a?(t.pos=I,T=P+R/2+B<=C,z=P-R/2-B>=0,"top"!==t.idealAlign&&T||!z?T?(P+=R/2,t.anchor="start"):t.anchor="middle":(P-=R/2,t.anchor="end")):(t.pos=P,T=I+D/2+B<=E,z=I-D/2-B>=0,"left"!==t.idealAlign&&T||!z?T?(I+=D/2,t.anchor="start"):t.anchor="middle":(I-=D/2,t.anchor="end")),b.attr("text-anchor",t.anchor),A&&_.attr("text-anchor",t.anchor),e.attr("transform","translate("+I+","+P+")"+(a?"rotate("+v+")":""))}),R}function A(t,e){t.each(function(t){var r=n.select(this);if(t.del)r.remove();else{var i="end"===t.anchor?-1:1,a=r.select("text.nums"),o={start:1,end:-1,middle:0}[t.anchor],s=o*(w+k),c=s+o*(t.txwidth+k),f=0,h=t.offset;"middle"===t.anchor&&(s-=t.tx2width/2,c+=t.txwidth/2+k),e&&(h*=-_,f=t.offset*b),r.select("path").attr("d","middle"===t.anchor?"M-"+(t.bx/2+t.tx2width/2)+","+(h-t.by/2)+"h"+t.bx+"v"+t.by+"h-"+t.bx+"Z":"M0,0L"+(i*w+f)+","+(w+h)+"v"+(t.by/2-w)+"h"+i*t.bx+"v-"+t.by+"H"+(i*w+f)+"V"+(h-w)+"Z"),a.call(l.positionText,s+f,h+t.ty0-t.by/2+k),t.tx2width&&(r.select("text.name").call(l.positionText,c+o*k+f,h+t.ty0-t.by/2+k),r.select("rect").call(u.setRect,c+(o-1)*t.tx2width/2+f,h-t.by/2-1,t.tx2width,t.by+2))}})}function T(t,e){var r=t.index,n=t.trace||{},i=t.cd[0],a=t.cd[r]||{},s=Array.isArray(r)?function(t,e){return o.castOption(i,r,t)||o.extractOption({},n,"",e)}:function(t,e){return o.extractOption(a,n,t,e)};function l(e,r,n){var i=s(r,n);i&&(t[e]=i)}if(l("hoverinfo","hi","hoverinfo"),l("bgcolor","hbg","hoverlabel.bgcolor"),l("borderColor","hbc","hoverlabel.bordercolor"),l("fontFamily","htf","hoverlabel.font.family"),l("fontSize","hts","hoverlabel.font.size"),l("fontColor","htc","hoverlabel.font.color"),l("nameLength","hnl","hoverlabel.namelength"),t.posref="y"===e?t.xa._offset+(t.x0+t.x1)/2:t.ya._offset+(t.y0+t.y1)/2,t.x0=o.constrain(t.x0,0,t.xa._length),t.x1=o.constrain(t.x1,0,t.xa._length),t.y0=o.constrain(t.y0,0,t.ya._length),t.y1=o.constrain(t.y1,0,t.ya._length),void 0!==t.xLabelVal&&(t.xLabel="xLabel"in t?t.xLabel:p.hoverLabelText(t.xa,t.xLabelVal),t.xVal=t.xa.c2d(t.xLabelVal)),void 0!==t.yLabelVal&&(t.yLabel="yLabel"in t?t.yLabel:p.hoverLabelText(t.ya,t.yLabelVal),t.yVal=t.ya.c2d(t.yLabelVal)),void 0!==t.zLabelVal&&void 0===t.zLabel&&(t.zLabel=String(t.zLabelVal)),!(isNaN(t.xerr)||"log"===t.xa.type&&t.xerr<=0)){var c=p.tickText(t.xa,t.xa.c2l(t.xerr),"hover").text;void 0!==t.xerrneg?t.xLabel+=" +"+c+" / -"+p.tickText(t.xa,t.xa.c2l(t.xerrneg),"hover").text:t.xLabel+=" \xb1 "+c,"x"===e&&(t.distance+=1)}if(!(isNaN(t.yerr)||"log"===t.ya.type&&t.yerr<=0)){var u=p.tickText(t.ya,t.ya.c2l(t.yerr),"hover").text;void 0!==t.yerrneg?t.yLabel+=" +"+u+" / -"+p.tickText(t.ya,t.ya.c2l(t.yerrneg),"hover").text:t.yLabel+=" \xb1 "+u,"y"===e&&(t.distance+=1)}var f=t.hoverinfo||t.trace.hoverinfo;return"all"!==f&&(-1===(f=Array.isArray(f)?f:f.split("+")).indexOf("x")&&(t.xLabel=void 0),-1===f.indexOf("y")&&(t.yLabel=void 0),-1===f.indexOf("z")&&(t.zLabel=void 0),-1===f.indexOf("text")&&(t.text=void 0),-1===f.indexOf("name")&&(t.name=void 0)),t}function S(t,e){var r,n,i=e.container,o=e.fullLayout,s=e.event,l=!!t.hLinePoint,c=!!t.vLinePoint;if(i.selectAll(".spikeline").remove(),c||l){var h=f.combine(o.plot_bgcolor,o.paper_bgcolor);if(l){var p,d,m=t.hLinePoint;r=m&&m.xa,"cursor"===(n=m&&m.ya).spikesnap?(p=s.pointerX,d=s.pointerY):(p=r._offset+m.x,d=n._offset+m.y);var g,v,y=a.readability(m.color,h)<1.5?f.contrast(h):m.color,x=n.spikemode,b=n.spikethickness,_=n.spikecolor||y,w=n._boundingBox,k=(w.left+w.right)/2w[0]._length||et<0||et>k[0]._length)return h.unhoverRaw(t,e)}if(e.pointerX=tt+w[0]._offset,e.pointerY=et+k[0]._offset,D="xval"in e?m.flat(l,e.xval):m.p2c(w,tt),R="yval"in e?m.flat(l,e.yval):m.p2c(k,et),!i(D[0])||!i(R[0]))return o.warn("Fx.hover failed",e,t),h.unhoverRaw(t,e)}var it=1/0;for(F=0;FY&&($.splice(0,Y),it=$[0].distance),y&&0!==Z&&0===$.length){W.distance=Z,W.index=!1;var ct=j._module.hoverPoints(W,H,G,"closest",u._hoverlayer);if(ct&&(ct=ct.filter(function(t){return t.spikeDistance<=Z})),ct&&ct.length){var ut,ft=ct.filter(function(t){return t.xa.showspikes});if(ft.length){var ht=ft[0];i(ht.x0)&&i(ht.y0)&&(ut=gt(ht),(!K.vLinePoint||K.vLinePoint.spikeDistance>ut.spikeDistance)&&(K.vLinePoint=ut))}var pt=ct.filter(function(t){return t.ya.showspikes});if(pt.length){var dt=pt[0];i(dt.x0)&&i(dt.y0)&&(ut=gt(dt),(!K.hLinePoint||K.hLinePoint.spikeDistance>ut.spikeDistance)&&(K.hLinePoint=ut))}}}}function mt(t,e){for(var r,n=null,i=1/0,a=0;a1||$.length>1)||"closest"===P&&Q&&$.length>1,Ct=f.combine(u.plot_bgcolor||f.background,u.paper_bgcolor),Lt={hovermode:P,rotateLabels:Et,bgColor:Ct,container:u._hoverlayer,outerContainer:u._paperdiv,commonLabelOpts:u.hoverlabel,hoverdistance:u.hoverdistance},zt=M($,Lt,t);if(function(t,e,r){var n,i,a,o,s,l,c,u=0,f=1,h=t.map(function(t,n){var i=t[e],a="x"===i._id.charAt(0),o=i.range;return!n&&o&&o[0]>o[1]!==a&&(f=-1),[{i:n,traceIndex:t.trace.index,dp:0,pos:t.pos,posref:t.posref,size:t.by*(a?x:1)/2,pmin:0,pmax:a?r.width:r.height}]}).sort(function(t,e){return t[0].posref-e[0].posref||f*(e[0].traceIndex-t[0].traceIndex)});function p(t){var e=t[0],r=t[t.length-1];if(i=e.pmin-e.pos-e.dp+e.size,a=r.pos+r.dp+r.size-e.pmax,i>.01){for(s=t.length-1;s>=0;s--)t[s].dp+=i;n=!1}if(!(a<.01)){if(i<-.01){for(s=t.length-1;s>=0;s--)t[s].dp-=a;n=!1}if(n){var c=0;for(o=0;oe.pmax&&c++;for(o=t.length-1;o>=0&&!(c<=0);o--)(l=t[o]).pos>e.pmax-1&&(l.del=!0,c--);for(o=0;o=0;s--)t[s].dp-=a;for(o=t.length-1;o>=0&&!(c<=0);o--)(l=t[o]).pos+l.dp+l.size>e.pmax&&(l.del=!0,c--)}}}for(;!n&&u<=t.length;){for(u++,n=!0,o=0;o.01&&g.pmin===v.pmin&&g.pmax===v.pmax){for(s=m.length-1;s>=0;s--)m[s].dp+=i;for(d.push.apply(d,m),h.splice(o+1,1),c=0,s=d.length-1;s>=0;s--)c+=d[s].dp;for(a=c/d.length,s=d.length-1;s>=0;s--)d[s].dp-=a;n=!1}else o++}h.forEach(p)}for(o=h.length-1;o>=0;o--){var y=h[o];for(s=y.length-1;s>=0;s--){var b=y[s],_=t[b.i];_.offset=b.dp,_.del=b.del}}}($,Et?"xa":"ya",u),A(zt,Et),e.target&&e.target.tagName){var Ot=d.getComponentMethod("annotations","hasClickToShow")(t,Tt);c(n.select(e.target),Ot?"pointer":"")}if(!e.target||a||!function(t,e,r){if(!r||r.length!==t._hoverdata.length)return!0;for(var n=r.length-1;n>=0;n--){var i=r[n],a=t._hoverdata[n];if(i.curveNumber!==a.curveNumber||String(i.pointNumber)!==String(a.pointNumber))return!0}return!1}(t,0,At))return;At&&t.emit("plotly_unhover",{event:e,points:At});t.emit("plotly_hover",{event:e,points:t._hoverdata,xaxes:w,yaxes:k,xvals:D,yvals:R})}(t,e,r,a)})},r.loneHover=function(t,e){var r={color:t.color||f.defaultLine,x0:t.x0||t.x||0,x1:t.x1||t.x||0,y0:t.y0||t.y||0,y1:t.y1||t.y||0,xLabel:t.xLabel,yLabel:t.yLabel,zLabel:t.zLabel,text:t.text,name:t.name,idealAlign:t.idealAlign,borderColor:t.borderColor,fontFamily:t.fontFamily,fontSize:t.fontSize,fontColor:t.fontColor,trace:{index:0,hoverinfo:""},xa:{_offset:0},ya:{_offset:0},index:0},i=n.select(e.container),a=e.outerContainer?n.select(e.outerContainer):i,o={hovermode:"closest",rotateLabels:!1,bgColor:e.bgColor||f.background,container:i,outerContainer:a},s=M([r],o,e.gd);return A(s,o.rotateLabels),s.node()},r.multiHovers=function(t,e){Array.isArray(t)||(t=[t]);var r=t.map(function(t){return{color:t.color||f.defaultLine,x0:t.x0||t.x||0,x1:t.x1||t.x||0,y0:t.y0||t.y||0,y1:t.y1||t.y||0,xLabel:t.xLabel,yLabel:t.yLabel,zLabel:t.zLabel,text:t.text,name:t.name,idealAlign:t.idealAlign,borderColor:t.borderColor,fontFamily:t.fontFamily,fontSize:t.fontSize,fontColor:t.fontColor,trace:{index:0,hoverinfo:""},xa:{_offset:0},ya:{_offset:0},index:0}}),i=n.select(e.container),a=e.outerContainer?n.select(e.outerContainer):i,o={hovermode:"closest",rotateLabels:!1,bgColor:e.bgColor||f.background,container:i,outerContainer:a},s=M(r,o,e.gd),l=0;return s.sort(function(t,e){return t.y0-e.y0}).each(function(t){var e=t.y0-t.by/2;t.offset=e-5-1?o="closest":(e._isHoriz=function(t){for(var e=!0,r=0;r1){h||p||d||"independent"===M("pattern")&&(h=!0),g._hasSubplotGrid=h;var x,b,_="top to bottom"===M("roworder"),w=h?.2:.1,k=h?.3:.1;m&&e._splomGridDflt&&(x=e._splomGridDflt.xside,b=e._splomGridDflt.yside),g._domains={x:u("x",M,w,x,y),y:u("y",M,k,b,v,_)}}else delete e.grid}function M(t,e){return n.coerce(r,g,l,t,e)}},contentDefaults:function(t,e){var r=e.grid;if(r&&r._domains){var n,i,a,o,s,l,u,h=t.grid||{},p=e._subplots,d=r._hasSubplotGrid,m=r.rows,g=r.columns,v="independent"===r.pattern,y=r._axisMap={};if(d){var x=h.subplots||[];l=r.subplots=new Array(m);var b=1;for(n=0;n=2/3},r.isCenterAnchor=function(t){return"center"===t.xanchor||"auto"===t.xanchor&&t.x>1/3&&t.x<2/3},r.isBottomAnchor=function(t){return"bottom"===t.yanchor||"auto"===t.yanchor&&t.y<=1/3},r.isMiddleAnchor=function(t){return"middle"===t.yanchor||"auto"===t.yanchor&&t.y>1/3&&t.y<2/3}},{}],623:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),i=t("../color/attributes");e.exports={bgcolor:{valType:"color",editType:"legend"},bordercolor:{valType:"color",dflt:i.defaultLine,editType:"legend"},borderwidth:{valType:"number",min:0,dflt:0,editType:"legend"},font:n({editType:"legend"}),orientation:{valType:"enumerated",values:["v","h"],dflt:"v",editType:"legend"},traceorder:{valType:"flaglist",flags:["reversed","grouped"],extras:["normal"],editType:"legend"},tracegroupgap:{valType:"number",min:0,dflt:10,editType:"legend"},x:{valType:"number",min:-2,max:3,dflt:1.02,editType:"legend"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left",editType:"legend"},y:{valType:"number",min:-2,max:3,dflt:1,editType:"legend"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto",editType:"legend"},uirevision:{valType:"any",editType:"none"},editType:"legend"}},{"../../plots/font_attributes":771,"../color/attributes":569}],624:[function(t,e,r){"use strict";e.exports={scrollBarWidth:6,scrollBarMinHeight:20,scrollBarColor:"#808BA4",scrollBarMargin:4,textOffsetX:40}},{}],625:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib"),a=t("../../plot_api/plot_template"),o=t("./attributes"),s=t("../../plots/layout_attributes"),l=t("./helpers");e.exports=function(t,e,r){for(var c,u,f,h,p=t.legend||{},d=0,m=!1,g="normal",v=0;v1);if(!1!==x||p.uirevision){var b=a.newContainer(e,"legend");if(w("uirevision",e.uirevision),!1!==x){if(w("bgcolor",e.paper_bgcolor),w("bordercolor"),w("borderwidth"),i.coerceFont(w,"font",e.font),w("orientation"),"h"===b.orientation){var _=t.xaxis;_&&_.rangeslider&&_.rangeslider.visible?(c=0,f="left",u=1.1,h="bottom"):(c=0,f="left",u=-.1,h="top")}w("traceorder",g),l.isGrouped(e.legend)&&w("tracegroupgap"),w("x",c),w("xanchor",f),w("y",u),w("yanchor",h),i.noneOrAll(p,b,["x","y"])}}function w(t,e){return i.coerce(p,b,o,t,e)}}},{"../../lib":696,"../../plot_api/plot_template":734,"../../plots/layout_attributes":799,"../../registry":827,"./attributes":623,"./helpers":629}],626:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib"),a=t("../../plots/plots"),o=t("../../registry"),s=t("../../lib/events"),l=t("../dragelement"),c=t("../drawing"),u=t("../color"),f=t("../../lib/svg_text_utils"),h=t("./handle_click"),p=t("./constants"),d=t("../../constants/interactions"),m=t("../../constants/alignment"),g=m.LINE_SPACING,v=m.FROM_TL,y=m.FROM_BR,x=t("./get_legend_data"),b=t("./style"),_=t("./helpers"),w=t("./anchor_utils"),k=d.DBLCLICKDELAY;function M(t,e,r,n,i){var a=r.data()[0][0].trace,o={event:i,node:r.node(),curveNumber:a.index,expandedIndex:a._expandedIndex,data:t.data,layout:t.layout,frames:t._transitionData._frames,config:t._context,fullData:t._fullData,fullLayout:t._fullLayout};if(a._group&&(o.group=a._group),"pie"===a.type&&(o.label=r.datum()[0].label),!1!==s.triggerHandler(t,"plotly_legendclick",o))if(1===n)e._clickTimeout=setTimeout(function(){h(r,t,n)},k);else if(2===n){e._clickTimeout&&clearTimeout(e._clickTimeout),t._legendMouseDownTime=0,!1!==s.triggerHandler(t,"plotly_legenddoubleclick",o)&&h(r,t,n)}}function A(t,e,r){var n=t.data()[0][0],a=e._fullLayout,s=n.trace,l=o.traceIs(s,"pie"),u=s.index,h=l?n.label:s.name,d=e._context.edits.legendText&&!l,m=i.ensureSingle(t,"text","legendtext");function v(r){f.convertToTspans(r,e,function(){!function(t,e){var r=t.data()[0][0];if(!r.trace.showlegend)return void t.remove();var n,i,a=t.select("g[class*=math-group]"),o=a.node(),s=e._fullLayout.legend.font.size*g;if(o){var l=c.bBox(o);n=l.height,i=l.width,c.setTranslate(a,0,n/4)}else{var u=t.select(".legendtext"),h=f.lineCount(u),d=u.node();n=s*h,i=d?c.bBox(d).width:0;var m=s*(.3+(1-h)/2);f.positionText(u,p.textOffsetX,m)}n=Math.max(n,16)+3,r.height=n,r.width=i}(t,e)})}m.attr("text-anchor","start").classed("user-select-none",!0).call(c.font,a.legend.font).text(d?T(h,r):h),f.positionText(m,p.textOffsetX,0),d?m.call(f.makeEditable,{gd:e,text:h}).call(v).on("edit",function(t){this.text(T(t,r)).call(v);var a=n.trace._fullInput||{},s={};if(o.hasTransform(a,"groupby")){var l=o.getTransformIndices(a,"groupby"),c=l[l.length-1],f=i.keyedContainer(a,"transforms["+c+"].styles","target","value.name");f.set(n.trace._group,t),s=f.constructUpdate()}else s.name=t;return o.call("_guiRestyle",e,s,u)}):v(m)}function T(t,e){var r=Math.max(4,e);if(t&&t.trim().length>=r/2)return t;for(var n=r-(t=t||"").length;n>0;n--)t+=" ";return t}function S(t,e){var r,a=1,o=i.ensureSingle(t,"rect","legendtoggle",function(t){t.style("cursor","pointer").attr("pointer-events","all").call(u.fill,"rgba(0,0,0,0)")});o.on("mousedown",function(){(r=(new Date).getTime())-e._legendMouseDownTimek&&(a=Math.max(a-1,1)),M(e,r,t,a,n.event)}})}function E(t,e,r){var i=t._fullLayout,a=i.legend,o=a.borderwidth,s=_.isGrouped(a),l=0;if(a._width=0,a._height=0,_.isVertical(a))s&&e.each(function(t,e){c.setTranslate(this,0,e*a.tracegroupgap)}),r.each(function(t){var e=t[0],r=e.height,n=e.width;c.setTranslate(this,o,5+o+a._height+r/2),a._height+=r,a._width=Math.max(a._width,n)}),a._width+=45+2*o,a._height+=10+2*o,s&&(a._height+=(a._lgroupsLength-1)*a.tracegroupgap),l=40;else if(s){for(var u=[a._width],f=e.data(),h=0,p=f.length;ho+w-k,r.each(function(t){var e=t[0],r=g?40+t[0].width:x;o+b+k+r>i._size.w&&(b=0,v+=y,a._height=a._height+y,y=0),c.setTranslate(this,o+b,5+o+e.height/2+v),a._width+=k+r,a._height=Math.max(a._height,e.height),b+=k+r,y=Math.max(e.height,y)}),a._width+=2*o,a._height+=10+2*o}a._width=Math.ceil(a._width),a._height=Math.ceil(a._height);var M=t._context.edits.legendText||t._context.edits.legendPosition;r.each(function(t){var e=t[0],r=n.select(this).select(".legendtoggle");c.setRect(r,0,-e.height/2,(M?0:a._width)+l,e.height)})}function C(t){var e=t._fullLayout.legend,r="left";w.isRightAnchor(e)?r="right":w.isCenterAnchor(e)&&(r="center");var n="top";w.isBottomAnchor(e)?n="bottom":w.isMiddleAnchor(e)&&(n="middle"),a.autoMargin(t,"legend",{x:e.x,y:e.y,l:e._width*v[r],r:e._width*y[r],b:e._height*y[n],t:e._height*v[n]})}e.exports=function(t){var e=t._fullLayout,r="legend"+e._uid;if(e._infolayer&&t.calcdata){t._legendMouseDownTime||(t._legendMouseDownTime=0);var s=e.legend,f=e.showlegend&&x(t.calcdata,s),h=e.hiddenlabels||[];if(!e.showlegend||!f.length)return e._infolayer.selectAll(".legend").remove(),e._topdefs.select("#"+r).remove(),void a.autoMargin(t,"legend");for(var d=0,m=0;mf?function(t){var e=t._fullLayout.legend,r="left";w.isRightAnchor(e)?r="right":w.isCenterAnchor(e)&&(r="center");a.autoMargin(t,"legend",{x:e.x,y:.5,l:e._width*v[r],r:e._width*y[r],b:0,t:0})}(t):C(t);var h=e._size,d=h.l+h.w*s.x,m=h.t+h.h*(1-s.y);w.isRightAnchor(s)?d-=s._width:w.isCenterAnchor(s)&&(d-=s._width/2),w.isBottomAnchor(s)?m-=s._height:w.isMiddleAnchor(s)&&(m-=s._height/2);var g=s._width,x=h.w;g>x?(d=h.l,g=x):(d+g>u&&(d=u-g),d<0&&(d=0),g=Math.min(u-d,s._width));var b,_,k,A,T=s._height,S=h.h;if(T>S?(m=h.t,T=S):(m+T>f&&(m=f-T),m<0&&(m=0),T=Math.min(f-m,s._height)),c.setTranslate(z,d,m),D.on(".drag",null),z.on("wheel",null),s._height<=T||t._context.staticPlot)I.attr({width:g-s.borderwidth,height:T-s.borderwidth,x:s.borderwidth/2,y:s.borderwidth/2}),c.setTranslate(P,0,0),O.select("rect").attr({width:g-2*s.borderwidth,height:T-2*s.borderwidth,x:s.borderwidth,y:s.borderwidth}),c.setClipUrl(P,r),c.setRect(D,0,0,0,0),delete s._scrollY;else{var F,N,j=Math.max(p.scrollBarMinHeight,T*T/s._height),V=T-j-2*p.scrollBarMargin,U=s._height-T,q=V/U,H=Math.min(s._scrollY||0,U);I.attr({width:g-2*s.borderwidth+p.scrollBarWidth+p.scrollBarMargin,height:T-s.borderwidth,x:s.borderwidth/2,y:s.borderwidth/2}),O.select("rect").attr({width:g-2*s.borderwidth+p.scrollBarWidth+p.scrollBarMargin,height:T-2*s.borderwidth,x:s.borderwidth,y:s.borderwidth+H}),c.setClipUrl(P,r),W(H,j,q),z.on("wheel",function(){W(H=i.constrain(s._scrollY+n.event.deltaY/V*U,0,U),j,q),0!==H&&H!==U&&n.event.preventDefault()});var G=n.behavior.drag().on("dragstart",function(){F=n.event.sourceEvent.clientY,N=H}).on("drag",function(){var t=n.event.sourceEvent;2===t.buttons||t.ctrlKey||W(H=i.constrain((t.clientY-F)/q+N,0,U),j,q)});D.call(G)}function W(e,r,n){s._scrollY=t._fullLayout.legend._scrollY=e,c.setTranslate(P,0,-e),c.setRect(D,g,p.scrollBarMargin+e*n,p.scrollBarWidth,r),O.select("rect").attr({y:s.borderwidth+e})}t._context.edits.legendPosition&&(z.classed("cursor-move",!0),l.init({element:z.node(),gd:t,prepFn:function(){var t=c.getTranslate(z);k=t.x,A=t.y},moveFn:function(t,e){var r=k+t,n=A+e;c.setTranslate(z,r,n),b=l.align(r,0,h.l,h.l+h.w,s.xanchor),_=l.align(n,0,h.t+h.h,h.t,s.yanchor)},doneFn:function(){void 0!==b&&void 0!==_&&o.call("_guiRelayout",t,{"legend.x":b,"legend.y":_})},clickFn:function(r,n){var i=e._infolayer.selectAll("g.traces").filter(function(){var t=this.getBoundingClientRect();return n.clientX>=t.left&&n.clientX<=t.right&&n.clientY>=t.top&&n.clientY<=t.bottom});i.size()>0&&M(t,z,i,r,n)}}))}],t)}}},{"../../constants/alignment":668,"../../constants/interactions":672,"../../lib":696,"../../lib/events":684,"../../lib/svg_text_utils":720,"../../plots/plots":808,"../../registry":827,"../color":570,"../dragelement":592,"../drawing":595,"./anchor_utils":622,"./constants":624,"./get_legend_data":627,"./handle_click":628,"./helpers":629,"./style":631,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],627:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("./helpers");e.exports=function(t,e){var r,a,o={},s=[],l=!1,c={},u=0;function f(t,r){if(""!==t&&i.isGrouped(e))-1===s.indexOf(t)?(s.push(t),l=!0,o[t]=[[r]]):o[t].push([r]);else{var n="~~i"+u;s.push(n),o[n]=[[r]],u++}}for(r=0;rr[1])return r[1]}return i}function d(t){return t[0]}if(u||f||h){var m={},g={};if(u){m.mc=p("marker.color",d),m.mx=p("marker.symbol",d),m.mo=p("marker.opacity",a.mean,[.2,1]),m.mlc=p("marker.line.color",d),m.mlw=p("marker.line.width",a.mean,[0,5]),g.marker={sizeref:1,sizemin:1,sizemode:"diameter"};var v=p("marker.size",a.mean,[2,16]);m.ms=v,g.marker.size=v}h&&(g.line={width:p("line.width",d,[0,10])}),f&&(m.tx="Aa",m.tp=p("textposition",d),m.ts=10,m.tc=p("textfont.color",d),m.tf=p("textfont.family",d)),r=[a.minExtend(s,m)],(i=a.minExtend(c,g)).selectedpoints=null}var y=n.select(this).select("g.legendpoints"),x=y.selectAll("path.scatterpts").data(u?r:[]);x.enter().insert("path",":first-child").classed("scatterpts",!0).attr("transform","translate(20,0)"),x.exit().remove(),x.call(o.pointStyle,i,e),u&&(r[0].mrc=3);var b=y.selectAll("g.pointtext").data(f?r:[]);b.enter().append("g").classed("pointtext",!0).append("text").attr("transform","translate(20,0)"),b.exit().remove(),b.selectAll("text").call(o.textPointStyle,i,e)}).each(function(t){var e=t[0].trace,r=n.select(this).select("g.legendpoints").selectAll("path.legendcandle").data("candlestick"===e.type&&e.visible?[t,t]:[]);r.enter().append("path").classed("legendcandle",!0).attr("d",function(t,e){return e?"M-15,0H-8M-8,6V-6H8Z":"M15,0H8M8,-6V6H-8Z"}).attr("transform","translate(20,0)").style("stroke-miterlimit",1),r.exit().remove(),r.each(function(t,r){var i=e[r?"increasing":"decreasing"],a=i.line.width,o=n.select(this);o.style("stroke-width",a+"px").call(s.fill,i.fillcolor),a&&s.stroke(o,i.line.color)})}).each(function(t){var e=t[0].trace,r=n.select(this).select("g.legendpoints").selectAll("path.legendohlc").data("ohlc"===e.type&&e.visible?[t,t]:[]);r.enter().append("path").classed("legendohlc",!0).attr("d",function(t,e){return e?"M-15,0H0M-8,-6V0":"M15,0H0M8,6V0"}).attr("transform","translate(20,0)").style("stroke-miterlimit",1),r.exit().remove(),r.each(function(t,r){var i=e[r?"increasing":"decreasing"],a=i.line.width,l=n.select(this);l.style("fill","none").call(o.dashLine,i.line.dash,a),a&&s.stroke(l,i.line.color)})})}},{"../../lib":696,"../../registry":827,"../../traces/pie/style_one":1029,"../../traces/scatter/subtypes":1067,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],632:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../plots/plots"),a=t("../../plots/cartesian/axis_ids"),o=t("../../lib"),s=t("../../../build/ploticon"),l=o._,c=e.exports={};function u(t,e){var r,i,o=e.currentTarget,s=o.getAttribute("data-attr"),l=o.getAttribute("data-val")||!0,c=t._fullLayout,u={},f=a.list(t,null,!0),h="on";if("zoom"===s){var p,d="in"===l?.5:2,m=(1+d)/2,g=(1-d)/2;for(i=0;i1?(_=["toggleHover"],w=["resetViews"]):f?(b=["zoomInGeo","zoomOutGeo"],_=["hoverClosestGeo"],w=["resetGeo"]):u?(_=["hoverClosest3d"],w=["resetCameraDefault3d","resetCameraLastSave3d"]):m?(_=["toggleHover"],w=["resetViewMapbox"]):_=p?["hoverClosestGl2d"]:h?["hoverClosestPie"]:["toggleHover"];c&&(_=["toggleSpikelines","hoverClosestCartesian","hoverCompareCartesian"]);!c&&!p||v||(b=["zoomIn2d","zoomOut2d","autoScale2d"],"resetViews"!==w[0]&&(w=["resetScale2d"]));u?k=["zoom3d","pan3d","orbitRotation","tableRotation"]:(c||p)&&!v||d?k=["zoom2d","pan2d"]:m||f?k=["pan2d"]:g&&(k=["zoom2d"]);(function(t){for(var e=!1,r=0;r0)){var m=function(t,e,r){for(var n=r.filter(function(r){return e[r].anchor===t._id}),i=0,a=0;a0?h+c:c;return{ppad:c,ppadplus:u?d:m,ppadminus:u?m:d}}return{ppad:c}}function u(t,e,r,n,i){var s="category"===t.type?t.r2c:t.d2c;if(void 0!==e)return[s(e),s(r)];if(n){var l,c,u,f,h=1/0,p=-1/0,d=n.match(a.segmentRE);for("date"===t.type&&(s=o.decodeDate(s)),l=0;lp&&(p=f)));return p>=h?[h,p]:void 0}}e.exports=function(t){var e=t._fullLayout,r=n.filterVisible(e.shapes);if(r.length&&t._fullData.length)for(var o=0;o10?t/2:10;return n.append("circle").attr({"data-line-point":"start-point",cx:D?q(r.xanchor)+r.x0:q(r.x0),cy:R?H(r.yanchor)-r.y0:H(r.y0),r:a}).style(i).classed("cursor-grab",!0),n.append("circle").attr({"data-line-point":"end-point",cx:D?q(r.xanchor)+r.x1:q(r.x1),cy:R?H(r.yanchor)-r.y1:H(r.y1),r:a}).style(i).classed("cursor-grab",!0),n}():e,X={element:Y.node(),gd:t,prepFn:function(n){D&&(_=q(r.xanchor));R&&(w=H(r.yanchor));"path"===r.type?z=r.path:(v=D?r.x0:q(r.x0),y=R?r.y0:H(r.y0),x=D?r.x1:q(r.x1),b=R?r.y1:H(r.y1));vb?(k=y,S="y0",M=b,E="y1"):(k=b,S="y1",M=y,E="y0");Z(n),K(p,r),function(t,e,r){var n=e.xref,i=e.yref,o=a.getFromId(r,n),l=a.getFromId(r,i),c="";"paper"===n||o.autorange||(c+=n);"paper"===i||l.autorange||(c+=i);t.call(s.setClipUrl,c?"clip"+r._fullLayout._uid+c:null)}(e,r,t),X.moveFn="move"===O?$:J},doneFn:function(){u(e),Q(p),d(e,t,r),n.call("_guiRelayout",t,N.getUpdateObj())},clickFn:function(){Q(p)}};function Z(t){if(B)O="path"===t.target.tagName?"move":"start-point"===t.target.attributes["data-line-point"].value?"resize-over-start-point":"resize-over-end-point";else{var r=X.element.getBoundingClientRect(),n=r.right-r.left,i=r.bottom-r.top,a=t.clientX-r.left,o=t.clientY-r.top,s=!F&&n>I&&i>P&&!t.shiftKey?c.getCursor(a/n,1-o/i):"move";u(e,s),O=s.split("-")[0]}}function $(n,i){if("path"===r.type){var a=function(t){return t},o=a,s=a;D?j("xanchor",r.xanchor=G(_+n)):(o=function(t){return G(q(t)+n)},V&&"date"===V.type&&(o=h.encodeDate(o))),R?j("yanchor",r.yanchor=W(w+i)):(s=function(t){return W(H(t)+i)},U&&"date"===U.type&&(s=h.encodeDate(s))),j("path",r.path=g(z,o,s))}else D?j("xanchor",r.xanchor=G(_+n)):(j("x0",r.x0=G(v+n)),j("x1",r.x1=G(x+n))),R?j("yanchor",r.yanchor=W(w+i)):(j("y0",r.y0=W(y+i)),j("y1",r.y1=W(b+i)));e.attr("d",m(t,r)),K(p,r)}function J(n,i){if(F){var a=function(t){return t},o=a,s=a;D?j("xanchor",r.xanchor=G(_+n)):(o=function(t){return G(q(t)+n)},V&&"date"===V.type&&(o=h.encodeDate(o))),R?j("yanchor",r.yanchor=W(w+i)):(s=function(t){return W(H(t)+i)},U&&"date"===U.type&&(s=h.encodeDate(s))),j("path",r.path=g(z,o,s))}else if(B){if("resize-over-start-point"===O){var l=v+n,c=R?y-i:y+i;j("x0",r.x0=D?l:G(l)),j("y0",r.y0=R?c:W(c))}else if("resize-over-end-point"===O){var u=x+n,f=R?b-i:b+i;j("x1",r.x1=D?u:G(u)),j("y1",r.y1=R?f:W(f))}}else{var d=~O.indexOf("n")?k+i:k,N=~O.indexOf("s")?M+i:M,Y=~O.indexOf("w")?A+n:A,X=~O.indexOf("e")?T+n:T;~O.indexOf("n")&&R&&(d=k-i),~O.indexOf("s")&&R&&(N=M-i),(!R&&N-d>P||R&&d-N>P)&&(j(S,r[S]=R?d:W(d)),j(E,r[E]=R?N:W(N))),X-Y>I&&(j(C,r[C]=D?Y:G(Y)),j(L,r[L]=D?X:G(X)))}e.attr("d",m(t,r)),K(p,r)}function K(t,e){(D||R)&&function(){var r="path"!==e.type,n=t.selectAll(".visual-cue").data([0]);n.enter().append("path").attr({fill:"#fff","fill-rule":"evenodd",stroke:"#000","stroke-width":1}).classed("visual-cue",!0);var a=q(D?e.xanchor:i.midRange(r?[e.x0,e.x1]:h.extractPathCoords(e.path,f.paramIsX))),o=H(R?e.yanchor:i.midRange(r?[e.y0,e.y1]:h.extractPathCoords(e.path,f.paramIsY)));if(a=h.roundPositionForSharpStrokeRendering(a,1),o=h.roundPositionForSharpStrokeRendering(o,1),D&&R){var s="M"+(a-1-1)+","+(o-1-1)+"h-8v2h8 v8h2v-8 h8v-2h-8 v-8h-2 Z";n.attr("d",s)}else if(D){var l="M"+(a-1-1)+","+(o-9-1)+"v18 h2 v-18 Z";n.attr("d",l)}else{var c="M"+(a-9-1)+","+(o-1-1)+"h18 v2 h-18 Z";n.attr("d",c)}}()}function Q(t){t.selectAll(".visual-cue").remove()}c.init(X),Y.node().onmousemove=Z}(t,x,r,e,p)}}function d(t,e,r){var n=(r.xref+r.yref).replace(/paper/g,"");t.call(s.setClipUrl,n?"clip"+e._fullLayout._uid+n:null)}function m(t,e){var r,n,o,s,l,c,u,p,d=e.type,m=a.getFromId(t,e.xref),g=a.getFromId(t,e.yref),v=t._fullLayout._size;if(m?(r=h.shapePositionToRange(m),n=function(t){return m._offset+m.r2p(r(t,!0))}):n=function(t){return v.l+v.w*t},g?(o=h.shapePositionToRange(g),s=function(t){return g._offset+g.r2p(o(t,!0))}):s=function(t){return v.t+v.h*(1-t)},"path"===d)return m&&"date"===m.type&&(n=h.decodeDate(n)),g&&"date"===g.type&&(s=h.decodeDate(s)),function(t,e,r){var n=t.path,a=t.xsizemode,o=t.ysizemode,s=t.xanchor,l=t.yanchor;return n.replace(f.segmentRE,function(t){var n=0,c=t.charAt(0),u=f.paramIsX[c],h=f.paramIsY[c],p=f.numParams[c],d=t.substr(1).replace(f.paramRE,function(t){return u[n]?t="pixel"===a?e(s)+Number(t):e(t):h[n]&&(t="pixel"===o?r(l)-Number(t):r(t)),++n>p&&(t="X"),t});return n>p&&(d=d.replace(/[\s,]*X.*/,""),i.log("Ignoring extra params in segment "+t)),c+d})}(e,n,s);if("pixel"===e.xsizemode){var y=n(e.xanchor);l=y+e.x0,c=y+e.x1}else l=n(e.x0),c=n(e.x1);if("pixel"===e.ysizemode){var x=s(e.yanchor);u=x-e.y0,p=x-e.y1}else u=s(e.y0),p=s(e.y1);if("line"===d)return"M"+l+","+u+"L"+c+","+p;if("rect"===d)return"M"+l+","+u+"H"+c+"V"+p+"H"+l+"Z";var b=(l+c)/2,_=(u+p)/2,w=Math.abs(b-l),k=Math.abs(_-u),M="A"+w+","+k,A=b+w+","+_;return"M"+A+M+" 0 1,1 "+(b+","+(_-k))+M+" 0 0,1 "+A+"Z"}function g(t,e,r){return t.replace(f.segmentRE,function(t){var n=0,i=t.charAt(0),a=f.paramIsX[i],o=f.paramIsY[i],s=f.numParams[i];return i+t.substr(1).replace(f.paramRE,function(t){return n>=s?t:(a[n]?t=e(t):o[n]&&(t=r(t)),n++,t)})})}e.exports={draw:function(t){var e=t._fullLayout;for(var r in e._shapeUpperLayer.selectAll("path").remove(),e._shapeLowerLayer.selectAll("path").remove(),e._plots){var n=e._plots[r].shapelayer;n&&n.selectAll("path").remove()}for(var i=0;i0&&(s=s.transition().duration(e.transition.duration).ease(e.transition.easing)),s.attr("transform","translate("+(o-.5*f.gripWidth)+","+e._dims.currentValueTotalHeight+")")}}function E(t,e){var r=t._dims;return r.inputAreaStart+f.stepInset+(r.inputAreaLength-2*f.stepInset)*Math.min(1,Math.max(0,e))}function C(t,e){var r=t._dims;return Math.min(1,Math.max(0,(e-f.stepInset-r.inputAreaStart)/(r.inputAreaLength-2*f.stepInset-2*r.inputAreaStart)))}function L(t,e,r){var n=r._dims,i=s.ensureSingle(t,"rect",f.railTouchRectClass,function(n){n.call(A,e,t,r).style("pointer-events","all")});i.attr({width:n.inputAreaLength,height:Math.max(n.inputAreaWidth,f.tickOffset+r.ticklen+n.labelHeight)}).call(a.fill,r.bgcolor).attr("opacity",0),o.setTranslate(i,0,n.currentValueTotalHeight)}function z(t,e){var r=e._dims,n=r.inputAreaLength-2*f.railInset,i=s.ensureSingle(t,"rect",f.railRectClass);i.attr({width:n,height:f.railWidth,rx:f.railRadius,ry:f.railRadius,"shape-rendering":"crispEdges"}).call(a.stroke,e.bordercolor).call(a.fill,e.bgcolor).style("stroke-width",e.borderwidth+"px"),o.setTranslate(i,f.railInset,.5*(r.inputAreaWidth-f.railWidth)+r.currentValueTotalHeight)}e.exports=function(t){var e=t._fullLayout,r=function(t,e){for(var r=t[f.name],n=[],i=0;i0?[0]:[]);function s(e){e._commandObserver&&(e._commandObserver.remove(),delete e._commandObserver),i.autoMargin(t,g(e))}if(a.enter().append("g").classed(f.containerClassName,!0).style("cursor","ew-resize"),a.exit().each(function(){n.select(this).selectAll("g."+f.groupClassName).each(s)}).remove(),0!==r.length){var l=a.selectAll("g."+f.groupClassName).data(r,v);l.enter().append("g").classed(f.groupClassName,!0),l.exit().each(s).remove();for(var c=0;c0||h<0){var m={left:[-r,0],right:[r,0],top:[0,-r],bottom:[0,r]}[y.side];e.attr("transform","translate("+m+")")}}}O.call(I),L&&(C?O.on(".opacity",null):(S=0,E=!0,O.text(g).on("mouseover.opacity",function(){n.select(this).transition().duration(f.SHOW_PLACEHOLDER).style("opacity",1)}).on("mouseout.opacity",function(){n.select(this).transition().duration(f.HIDE_PLACEHOLDER).style("opacity",0)})),O.call(u.makeEditable,{gd:t}).on("edit",function(e){void 0!==v?o.call("_guiRestyle",t,m,e,v):o.call("_guiRelayout",t,m,e)}).on("cancel",function(){this.text(this.attr("data-unformatted")).call(I)}).on("input",function(t){this.text(t||" ").call(u.positionText,x.x,x.y)}));return O.classed("js-placeholder",E),_}};var h=/ [XY][0-9]* /},{"../../constants/interactions":672,"../../lib":696,"../../lib/svg_text_utils":720,"../../plots/plots":808,"../../registry":827,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],662:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),i=t("../color/attributes"),a=t("../../lib/extend").extendFlat,o=t("../../plot_api/edit_types").overrideAll,s=t("../../plots/pad_attributes"),l=t("../../plot_api/plot_template").templatedArray,c=l("button",{visible:{valType:"boolean"},method:{valType:"enumerated",values:["restyle","relayout","animate","update","skip"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string",dflt:""},execute:{valType:"boolean",dflt:!0}});e.exports=o(l("updatemenu",{_arrayAttrRegexps:[/^updatemenus\[(0|[1-9][0-9]+)\]\.buttons/],visible:{valType:"boolean"},type:{valType:"enumerated",values:["dropdown","buttons"],dflt:"dropdown"},direction:{valType:"enumerated",values:["left","right","up","down"],dflt:"down"},active:{valType:"integer",min:-1,dflt:0},showactive:{valType:"boolean",dflt:!0},buttons:c,x:{valType:"number",min:-2,max:3,dflt:-.05},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"right"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},pad:a({},s,{}),font:n({}),bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:i.borderLine},borderwidth:{valType:"number",min:0,dflt:1,editType:"arraydraw"}}),"arraydraw","from-root")},{"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../../plots/font_attributes":771,"../../plots/pad_attributes":807,"../color/attributes":569}],663:[function(t,e,r){"use strict";e.exports={name:"updatemenus",containerClassName:"updatemenu-container",headerGroupClassName:"updatemenu-header-group",headerClassName:"updatemenu-header",headerArrowClassName:"updatemenu-header-arrow",dropdownButtonGroupClassName:"updatemenu-dropdown-button-group",dropdownButtonClassName:"updatemenu-dropdown-button",buttonClassName:"updatemenu-button",itemRectClassName:"updatemenu-item-rect",itemTextClassName:"updatemenu-item-text",menuIndexAttrName:"updatemenu-active-index",autoMarginIdRoot:"updatemenu-",blankHeaderOpts:{label:" "},minWidth:30,minHeight:30,textPadX:24,arrowPadX:16,rx:2,ry:2,textOffsetX:12,textOffsetY:3,arrowOffsetX:4,gapButtonHeader:5,gapButton:2,activeColor:"#F4FAFF",hoverColor:"#F4FAFF",arrowSymbol:{left:"\u25c4",right:"\u25ba",up:"\u25b2",down:"\u25bc"}}},{}],664:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../plots/array_container_defaults"),a=t("./attributes"),o=t("./constants").name,s=a.buttons;function l(t,e,r){function o(r,i){return n.coerce(t,e,a,r,i)}o("visible",i(t,e,{name:"buttons",handleItemDefaults:c}).length>0)&&(o("active"),o("direction"),o("type"),o("showactive"),o("x"),o("y"),n.noneOrAll(t,e,["x","y"]),o("xanchor"),o("yanchor"),o("pad.t"),o("pad.r"),o("pad.b"),o("pad.l"),n.coerceFont(o,"font",r.font),o("bgcolor",r.paper_bgcolor),o("bordercolor"),o("borderwidth"))}function c(t,e){function r(r,i){return n.coerce(t,e,s,r,i)}r("visible","skip"===t.method||Array.isArray(t.args))&&(r("method"),r("args"),r("label"),r("execute"))}e.exports=function(t,e){i(t,e,{name:o,handleItemDefaults:l})}},{"../../lib":696,"../../plots/array_container_defaults":740,"./attributes":662,"./constants":663}],665:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../plots/plots"),a=t("../color"),o=t("../drawing"),s=t("../../lib"),l=t("../../lib/svg_text_utils"),c=t("../legend/anchor_utils"),u=t("../../plot_api/plot_template").arrayEditor,f=t("../../constants/alignment").LINE_SPACING,h=t("./constants"),p=t("./scrollbox");function d(t){return t._index}function m(t,e){return+t.attr(h.menuIndexAttrName)===e._index}function g(t,e,r,n,i,a,o,s){e.active=o,u(t.layout,h.name,e).applyUpdate("active",o),"buttons"===e.type?y(t,n,null,null,e):"dropdown"===e.type&&(i.attr(h.menuIndexAttrName,"-1"),v(t,n,i,a,e),s||y(t,n,i,a,e))}function v(t,e,r,n,i){var a=s.ensureSingle(e,"g",h.headerClassName,function(t){t.style("pointer-events","all")}),l=i._dims,c=i.active,u=i.buttons[c]||h.blankHeaderOpts,f={y:i.pad.t,yPad:0,x:i.pad.l,xPad:0,index:0},p={width:l.headerWidth,height:l.headerHeight};a.call(x,i,u,t).call(S,i,f,p),s.ensureSingle(e,"text",h.headerArrowClassName,function(t){t.classed("user-select-none",!0).attr("text-anchor","end").call(o.font,i.font).text(h.arrowSymbol[i.direction])}).attr({x:l.headerWidth-h.arrowOffsetX+i.pad.l,y:l.headerHeight/2+h.textOffsetY+i.pad.t}),a.on("click",function(){r.call(E,String(m(r,i)?-1:i._index)),y(t,e,r,n,i)}),a.on("mouseover",function(){a.call(k)}),a.on("mouseout",function(){a.call(M,i)}),o.setTranslate(e,l.lx,l.ly)}function y(t,e,r,a,o){r||(r=e).attr("pointer-events","all");var l=function(t){return-1==+t.attr(h.menuIndexAttrName)}(r)&&"buttons"!==o.type?[]:o.buttons,c="dropdown"===o.type?h.dropdownButtonClassName:h.buttonClassName,u=r.selectAll("g."+c).data(s.filterVisible(l)),f=u.enter().append("g").classed(c,!0),p=u.exit();"dropdown"===o.type?(f.attr("opacity","0").transition().attr("opacity","1"),p.transition().attr("opacity","0").remove()):p.remove();var d=0,m=0,v=o._dims,y=-1!==["up","down"].indexOf(o.direction);"dropdown"===o.type&&(y?m=v.headerHeight+h.gapButtonHeader:d=v.headerWidth+h.gapButtonHeader),"dropdown"===o.type&&"up"===o.direction&&(m=-h.gapButtonHeader+h.gapButton-v.openHeight),"dropdown"===o.type&&"left"===o.direction&&(d=-h.gapButtonHeader+h.gapButton-v.openWidth);var b={x:v.lx+d+o.pad.l,y:v.ly+m+o.pad.t,yPad:h.gapButton,xPad:h.gapButton,index:0},_={l:b.x+o.borderwidth,t:b.y+o.borderwidth};u.each(function(s,l){var c=n.select(this);c.call(x,o,s,t).call(S,o,b),c.on("click",function(){n.event.defaultPrevented||(g(t,o,0,e,r,a,l),s.execute&&i.executeAPICommand(t,s.method,s.args),t.emit("plotly_buttonclicked",{menu:o,button:s,active:o.active}))}),c.on("mouseover",function(){c.call(k)}),c.on("mouseout",function(){c.call(M,o),u.call(w,o)})}),u.call(w,o),y?(_.w=Math.max(v.openWidth,v.headerWidth),_.h=b.y-_.t):(_.w=b.x-_.l,_.h=Math.max(v.openHeight,v.headerHeight)),_.direction=o.direction,a&&(u.size()?function(t,e,r,n,i,a){var o,s,l,c=i.direction,u="up"===c||"down"===c,f=i._dims,p=i.active;if(u)for(s=0,l=0;l0?[0]:[]);if(o.enter().append("g").classed(h.containerClassName,!0).style("cursor","pointer"),o.exit().each(function(){n.select(this).selectAll("g."+h.headerGroupClassName).each(a)}).remove(),0!==r.length){var l=o.selectAll("g."+h.headerGroupClassName).data(r,d);l.enter().append("g").classed(h.headerGroupClassName,!0);for(var c=s.ensureSingle(o,"g",h.dropdownButtonGroupClassName,function(t){t.style("pointer-events","all")}),u=0;uw,A=s.barLength+2*s.barPad,T=s.barWidth+2*s.barPad,S=d,E=g+v;E+T>c&&(E=c-T);var C=this.container.selectAll("rect.scrollbar-horizontal").data(M?[0]:[]);C.exit().on(".drag",null).remove(),C.enter().append("rect").classed("scrollbar-horizontal",!0).call(i.fill,s.barColor),M?(this.hbar=C.attr({rx:s.barRadius,ry:s.barRadius,x:S,y:E,width:A,height:T}),this._hbarXMin=S+A/2,this._hbarTranslateMax=w-A):(delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax);var L=v>k,z=s.barWidth+2*s.barPad,O=s.barLength+2*s.barPad,I=d+m,P=g;I+z>l&&(I=l-z);var D=this.container.selectAll("rect.scrollbar-vertical").data(L?[0]:[]);D.exit().on(".drag",null).remove(),D.enter().append("rect").classed("scrollbar-vertical",!0).call(i.fill,s.barColor),L?(this.vbar=D.attr({rx:s.barRadius,ry:s.barRadius,x:I,y:P,width:z,height:O}),this._vbarYMin=P+O/2,this._vbarTranslateMax=k-O):(delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax);var R=this.id,B=u-.5,F=L?f+z+.5:f+.5,N=h-.5,j=M?p+T+.5:p+.5,V=o._topdefs.selectAll("#"+R).data(M||L?[0]:[]);if(V.exit().remove(),V.enter().append("clipPath").attr("id",R).append("rect"),M||L?(this._clipRect=V.select("rect").attr({x:Math.floor(B),y:Math.floor(N),width:Math.ceil(F)-Math.floor(B),height:Math.ceil(j)-Math.floor(N)}),this.container.call(a.setClipUrl,R),this.bg.attr({x:d,y:g,width:m,height:v})):(this.bg.attr({width:0,height:0}),this.container.on("wheel",null).on(".drag",null).call(a.setClipUrl,null),delete this._clipRect),M||L){var U=n.behavior.drag().on("dragstart",function(){n.event.sourceEvent.preventDefault()}).on("drag",this._onBoxDrag.bind(this));this.container.on("wheel",null).on("wheel",this._onBoxWheel.bind(this)).on(".drag",null).call(U);var q=n.behavior.drag().on("dragstart",function(){n.event.sourceEvent.preventDefault(),n.event.sourceEvent.stopPropagation()}).on("drag",this._onBarDrag.bind(this));M&&this.hbar.on(".drag",null).call(q),L&&this.vbar.on(".drag",null).call(q)}this.setTranslate(e,r)},s.prototype.disable=function(){(this.hbar||this.vbar)&&(this.bg.attr({width:0,height:0}),this.container.on("wheel",null).on(".drag",null).call(a.setClipUrl,null),delete this._clipRect),this.hbar&&(this.hbar.on(".drag",null),this.hbar.remove(),delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax),this.vbar&&(this.vbar.on(".drag",null),this.vbar.remove(),delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax)},s.prototype._onBoxDrag=function(){var t=this.translateX,e=this.translateY;this.hbar&&(t-=n.event.dx),this.vbar&&(e-=n.event.dy),this.setTranslate(t,e)},s.prototype._onBoxWheel=function(){var t=this.translateX,e=this.translateY;this.hbar&&(t+=n.event.deltaY),this.vbar&&(e+=n.event.deltaY),this.setTranslate(t,e)},s.prototype._onBarDrag=function(){var t=this.translateX,e=this.translateY;if(this.hbar){var r=t+this._hbarXMin,i=r+this._hbarTranslateMax;t=(o.constrain(n.event.x,r,i)-r)/(i-r)*(this.position.w-this._box.w)}if(this.vbar){var a=e+this._vbarYMin,s=a+this._vbarTranslateMax;e=(o.constrain(n.event.y,a,s)-a)/(s-a)*(this.position.h-this._box.h)}this.setTranslate(t,e)},s.prototype.setTranslate=function(t,e){var r=this.position.w-this._box.w,n=this.position.h-this._box.h;if(t=o.constrain(t||0,0,r),e=o.constrain(e||0,0,n),this.translateX=t,this.translateY=e,this.container.call(a.setTranslate,this._box.l-this.position.l-t,this._box.t-this.position.t-e),this._clipRect&&this._clipRect.attr({x:Math.floor(this.position.l+t-.5),y:Math.floor(this.position.t+e-.5)}),this.hbar){var i=t/r;this.hbar.call(a.setTranslate,t+i*this._hbarTranslateMax,e)}if(this.vbar){var s=e/n;this.vbar.call(a.setTranslate,t,e+s*this._vbarTranslateMax)}}},{"../../lib":696,"../color":570,"../drawing":595,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],668:[function(t,e,r){"use strict";e.exports={FROM_BL:{left:0,center:.5,right:1,bottom:0,middle:.5,top:1},FROM_TL:{left:0,center:.5,right:1,bottom:1,middle:.5,top:0},FROM_BR:{left:1,center:.5,right:0,bottom:0,middle:.5,top:1},LINE_SPACING:1.3,MID_SHIFT:.35,OPPOSITE_SIDE:{left:"right",right:"left",top:"bottom",bottom:"top"}}},{}],669:[function(t,e,r){"use strict";e.exports={COMPARISON_OPS:["=","!=","<",">=",">","<="],COMPARISON_OPS2:["=","<",">=",">","<="],INTERVAL_OPS:["[]","()","[)","(]","][",")(","](",")["],SET_OPS:["{}","}{"],CONSTRAINT_REDUCTION:{"=":"=","<":"<","<=":"<",">":">",">=":">","[]":"[]","()":"[]","[)":"[]","(]":"[]","][":"][",")(":"][","](":"][",")[":"]["}}},{}],670:[function(t,e,r){"use strict";e.exports={solid:[[],0],dot:[[.5,1],200],dash:[[.5,1],50],longdash:[[.5,1],10],dashdot:[[.5,.625,.875,1],50],longdashdot:[[.5,.7,.8,1],10]}},{}],671:[function(t,e,r){"use strict";e.exports={circle:"\u25cf","circle-open":"\u25cb",square:"\u25a0","square-open":"\u25a1",diamond:"\u25c6","diamond-open":"\u25c7",cross:"+",x:"\u274c"}},{}],672:[function(t,e,r){"use strict";e.exports={SHOW_PLACEHOLDER:100,HIDE_PLACEHOLDER:1e3,DBLCLICKDELAY:300,DESELECTDIM:.2}},{}],673:[function(t,e,r){"use strict";e.exports={BADNUM:void 0,FP_SAFE:Number.MAX_VALUE/1e4,ONEAVGYEAR:315576e5,ONEAVGMONTH:26298e5,ONEDAY:864e5,ONEHOUR:36e5,ONEMIN:6e4,ONESEC:1e3,EPOCHJD:2440587.5,ALMOST_EQUAL:1-1e-6,LOG_CLIP:10,MINUS_SIGN:"\u2212"}},{}],674:[function(t,e,r){"use strict";r.xmlns="http://www.w3.org/2000/xmlns/",r.svg="http://www.w3.org/2000/svg",r.xlink="http://www.w3.org/1999/xlink",r.svgAttrs={xmlns:r.svg,"xmlns:xlink":r.xlink}},{}],675:[function(t,e,r){"use strict";r.version="1.42.5",t("es6-promise").polyfill(),t("../build/plotcss"),t("./fonts/mathjax_config");for(var n=t("./registry"),i=r.register=n.register,a=t("./plot_api"),o=Object.keys(a),s=0;ss-1e-15}function c(t,e){return a(e-t,s)}function u(t,e){if(l(e))return!0;var r,n;e[0](n=i(n,s))&&(n+=s);var a=i(t,s),o=a+s;return a>=r&&a<=n||o>=r&&o<=n}function f(t,e,r,n,i,a,c){i=i||0,a=a||0;var u,f,h,p,d,m=l([r,n]);function g(t,e){return[t*Math.cos(e)+i,a-t*Math.sin(e)]}m?(u=0,f=o,h=s):r=i&&t<=a);var i,a},pathArc:function(t,e,r,n,i){return f(null,t,e,r,n,i,0)},pathSector:function(t,e,r,n,i){return f(null,t,e,r,n,i,1)},pathAnnulus:function(t,e,r,n,i,a){return f(t,e,r,n,i,a,1)}}},{"./mod":703}],678:[function(t,e,r){"use strict";var n=Array.isArray,i="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer:{isView:function(){return!1}},a="undefined"==typeof DataView?function(){}:DataView;function o(t){return i.isView(t)&&!(t instanceof a)}function s(t){return n(t)||o(t)}r.isTypedArray=o,r.isArrayOrTypedArray=s,r.isArray1D=function(t){return!s(t[0])},r.ensureArray=function(t,e){return n(t)||(t=[]),t.length=e,t},r.concat=function(){var t,e,r,i,a,o,s,l,c=[],u=!0,f=0;for(r=0;ri.max?e.set(r):e.set(+t)}},integer:{coerceFunction:function(t,e,r,i){t%1||!n(t)||void 0!==i.min&&ti.max?e.set(r):e.set(+t)}},string:{coerceFunction:function(t,e,r,n){if("string"!=typeof t){var i="number"==typeof t;!0!==n.strict&&i?e.set(String(t)):e.set(r)}else n.noBlank&&!t?e.set(r):e.set(t)}},color:{coerceFunction:function(t,e,r){i(t).isValid()?e.set(t):e.set(r)}},colorlist:{coerceFunction:function(t,e,r){Array.isArray(t)&&t.length&&t.every(function(t){return i(t).isValid()})?e.set(t):e.set(r)}},colorscale:{coerceFunction:function(t,e,r){e.set(o(t,r))}},angle:{coerceFunction:function(t,e,r){"auto"===t?e.set("auto"):n(t)?e.set(u(+t,360)):e.set(r)}},subplotid:{coerceFunction:function(t,e,r,n){var i=n.regex||l(r);"string"==typeof t&&i.test(t)?e.set(t):e.set(r)},validateFunction:function(t,e){var r=e.dflt;return t===r||"string"==typeof t&&!!l(r).test(t)}},flaglist:{coerceFunction:function(t,e,r,n){if("string"==typeof t)if(-1===(n.extras||[]).indexOf(t)){for(var i=t.split("+"),a=0;a=n&&t<=i?t:u}if("string"!=typeof t&&"number"!=typeof t)return u;t=String(t);var c=_(e),v=t.charAt(0);!c||"G"!==v&&"g"!==v||(t=t.substr(1),e="");var w=c&&"chinese"===e.substr(0,7),k=t.match(w?x:y);if(!k)return u;var M=k[1],A=k[3]||"1",T=Number(k[5]||1),S=Number(k[7]||0),E=Number(k[9]||0),C=Number(k[11]||0);if(c){if(2===M.length)return u;var L;M=Number(M);try{var z=g.getComponentMethod("calendars","getCal")(e);if(w){var O="i"===A.charAt(A.length-1);A=parseInt(A,10),L=z.newDate(M,z.toMonthIndex(M,A,O),T)}else L=z.newDate(M,Number(A),T)}catch(t){return u}return L?(L.toJD()-m)*f+S*h+E*p+C*d:u}M=2===M.length?(Number(M)+2e3-b)%100+b:Number(M),A-=1;var I=new Date(Date.UTC(2e3,A,T,S,E));return I.setUTCFullYear(M),I.getUTCMonth()!==A?u:I.getUTCDate()!==T?u:I.getTime()+C*d},n=r.MIN_MS=r.dateTime2ms("-9999"),i=r.MAX_MS=r.dateTime2ms("9999-12-31 23:59:59.9999"),r.isDateTime=function(t,e){return r.dateTime2ms(t,e)!==u};var k=90*f,M=3*h,A=5*p;function T(t,e,r,n,i){if((e||r||n||i)&&(t+=" "+w(e,2)+":"+w(r,2),(n||i)&&(t+=":"+w(n,2),i))){for(var a=4;i%10==0;)a-=1,i/=10;t+="."+w(i,a)}return t}r.ms2DateTime=function(t,e,r){if("number"!=typeof t||!(t>=n&&t<=i))return u;e||(e=0);var a,o,s,c,y,x,b=Math.floor(10*l(t+.05,1)),w=Math.round(t-b/10);if(_(r)){var S=Math.floor(w/f)+m,E=Math.floor(l(t,f));try{a=g.getComponentMethod("calendars","getCal")(r).fromJD(S).formatDate("yyyy-mm-dd")}catch(t){a=v("G%Y-%m-%d")(new Date(w))}if("-"===a.charAt(0))for(;a.length<11;)a="-0"+a.substr(1);else for(;a.length<10;)a="0"+a;o=e=n+f&&t<=i-f))return u;var e=Math.floor(10*l(t+.05,1)),r=new Date(Math.round(t-e/10));return T(a.time.format("%Y-%m-%d")(r),r.getHours(),r.getMinutes(),r.getSeconds(),10*r.getUTCMilliseconds()+e)},r.cleanDate=function(t,e,n){if(t===u)return e;if(r.isJSDate(t)||"number"==typeof t&&isFinite(t)){if(_(n))return s.error("JS Dates and milliseconds are incompatible with world calendars",t),e;if(!(t=r.ms2DateTimeLocal(+t))&&void 0!==e)return e}else if(!r.isDateTime(t,n))return s.error("unrecognized date",t),e;return t};var S=/%\d?f/g;function E(t,e,r,n){t=t.replace(S,function(t){var r=Math.min(+t.charAt(1)||6,6);return(e/1e3%1+2).toFixed(r).substr(2).replace(/0+$/,"")||"0"});var i=new Date(Math.floor(e+.05));if(_(n))try{t=g.getComponentMethod("calendars","worldCalFmt")(t,e,n)}catch(t){return"Invalid"}return r(t)(i)}var C=[59,59.9,59.99,59.999,59.9999];r.formatDate=function(t,e,r,n,i,a){if(i=_(i)&&i,!e)if("y"===r)e=a.year;else if("m"===r)e=a.month;else{if("d"!==r)return function(t,e){var r=l(t+.05,f),n=w(Math.floor(r/h),2)+":"+w(l(Math.floor(r/p),60),2);if("M"!==e){o(e)||(e=0);var i=(100+Math.min(l(t/d,60),C[e])).toFixed(e).substr(1);e>0&&(i=i.replace(/0+$/,"").replace(/[\.]$/,"")),n+=":"+i}return n}(t,r)+"\n"+E(a.dayMonthYear,t,n,i);e=a.dayMonth+"\n"+a.year}return E(e,t,n,i)};var L=3*f;r.incrementMonth=function(t,e,r){r=_(r)&&r;var n=l(t,f);if(t=Math.round(t-n),r)try{var i=Math.round(t/f)+m,a=g.getComponentMethod("calendars","getCal")(r),o=a.fromJD(i);return e%12?a.add(o,e,"m"):a.add(o,e/12,"y"),(o.toJD()-m)*f+n}catch(e){s.error("invalid ms "+t+" in calendar "+r)}var c=new Date(t+L);return c.setUTCMonth(c.getUTCMonth()+e)+n-L},r.findExactDates=function(t,e){for(var r,n,i=0,a=0,s=0,l=0,c=_(e)&&g.getComponentMethod("calendars","getCal")(e),u=0;u0&&(r.push(i),i=[])}return i.length>0&&r.push(i),r},r.makeLine=function(t){return 1===t.length?{type:"LineString",coordinates:t[0]}:{type:"MultiLineString",coordinates:t}},r.makePolygon=function(t){if(1===t.length)return{type:"Polygon",coordinates:t};for(var e=new Array(t.length),r=0;r1||m<0||m>1?null:{x:t+l*m,y:e+f*m}}function l(t,e,r,n,i){var a=n*t+i*e;if(a<0)return n*n+i*i;if(a>r){var o=n-t,s=i-e;return o*o+s*s}var l=n*e-i*t;return l*l/r}r.segmentsIntersect=s,r.segmentDistance=function(t,e,r,n,i,a,o,c){if(s(t,e,r,n,i,a,o,c))return 0;var u=r-t,f=n-e,h=o-i,p=c-a,d=u*u+f*f,m=h*h+p*p,g=Math.min(l(u,f,d,i-t,a-e),l(u,f,d,o-t,c-e),l(h,p,m,t-i,e-a),l(h,p,m,r-i,n-a));return Math.sqrt(g)},r.getTextLocation=function(t,e,r,s){if(t===i&&s===a||(n={},i=t,a=s),n[r])return n[r];var l=t.getPointAtLength(o(r-s/2,e)),c=t.getPointAtLength(o(r+s/2,e)),u=Math.atan((c.y-l.y)/(c.x-l.x)),f=t.getPointAtLength(o(r,e)),h={x:(4*f.x+l.x+c.x)/6,y:(4*f.y+l.y+c.y)/6,theta:u};return n[r]=h,h},r.clearLocationCache=function(){i=null},r.getVisibleSegment=function(t,e,r){var n,i,a=e.left,o=e.right,s=e.top,l=e.bottom,c=0,u=t.getTotalLength(),f=u;function h(e){var r=t.getPointAtLength(e);0===e?n=r:e===u&&(i=r);var c=r.xo?r.x-o:0,f=r.yl?r.y-l:0;return Math.sqrt(c*c+f*f)}for(var p=h(c);p;){if((c+=p+r)>f)return;p=h(c)}for(p=h(f);p;){if(c>(f-=p+r))return;p=h(f)}return{min:c,max:f,len:f-c,total:u,isClosed:0===c&&f===u&&Math.abs(n.x-i.x)<.1&&Math.abs(n.y-i.y)<.1}},r.findPointOnPath=function(t,e,r,n){for(var i,a,o,s=(n=n||{}).pathLength||t.getTotalLength(),l=n.tolerance||.001,c=n.iterationLimit||30,u=t.getPointAtLength(0)[r]>t.getPointAtLength(s)[r]?-1:1,f=0,h=0,p=s;f0?p=i:h=i,f++}return a}},{"./mod":703}],691:[function(t,e,r){"use strict";e.exports=function(t){var e;if("string"==typeof t){if(null===(e=document.getElementById(t)))throw new Error("No DOM element with id '"+t+"' exists on the page.");return e}if(null==t)throw new Error("DOM element provided is null or undefined");return t}},{}],692:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("tinycolor2"),a=t("color-normalize"),o=t("../components/colorscale"),s=t("../components/color/attributes").defaultLine,l=t("./array").isArrayOrTypedArray,c=a(s),u=1;function f(t,e){var r=t;return r[3]*=e,r}function h(t){if(n(t))return c;var e=a(t);return e.length?e:c}function p(t){return n(t)?t:u}e.exports={formatColor:function(t,e,r){var n,i,s,d,m,g=t.color,v=l(g),y=l(e),x=[];if(n=void 0!==t.colorscale?o.makeColorScaleFunc(o.extractScale(t.colorscale,t.cmin,t.cmax)):h,i=v?function(t,e){return void 0===t[e]?c:a(n(t[e]))}:h,s=y?function(t,e){return void 0===t[e]?u:p(t[e])}:p,v||y)for(var b=0;b/g,"")}(function(t){for(var e=0;(e=t.indexOf("",e))>=0;){var r=t.indexOf("",e);if(r/g,"\n"))))}},{"./svg_text_utils":720,"superscript-text":507}],695:[function(t,e,r){"use strict";e.exports=function(t){return t}},{}],696:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("fast-isnumeric"),a=t("../constants/numerical"),o=a.FP_SAFE,s=a.BADNUM,l=e.exports={};l.nestedProperty=t("./nested_property"),l.keyedContainer=t("./keyed_container"),l.relativeAttr=t("./relative_attr"),l.isPlainObject=t("./is_plain_object"),l.toLogRange=t("./to_log_range"),l.relinkPrivateKeys=t("./relink_private");var c=t("./array");l.isTypedArray=c.isTypedArray,l.isArrayOrTypedArray=c.isArrayOrTypedArray,l.isArray1D=c.isArray1D,l.ensureArray=c.ensureArray,l.concat=c.concat;var u=t("./mod");l.mod=u.mod,l.modHalf=u.modHalf;var f=t("./coerce");l.valObjectMeta=f.valObjectMeta,l.coerce=f.coerce,l.coerce2=f.coerce2,l.coerceFont=f.coerceFont,l.coerceHoverinfo=f.coerceHoverinfo,l.coerceSelectionMarkerOpacity=f.coerceSelectionMarkerOpacity,l.validate=f.validate;var h=t("./dates");l.dateTime2ms=h.dateTime2ms,l.isDateTime=h.isDateTime,l.ms2DateTime=h.ms2DateTime,l.ms2DateTimeLocal=h.ms2DateTimeLocal,l.cleanDate=h.cleanDate,l.isJSDate=h.isJSDate,l.formatDate=h.formatDate,l.incrementMonth=h.incrementMonth,l.dateTick0=h.dateTick0,l.dfltRange=h.dfltRange,l.findExactDates=h.findExactDates,l.MIN_MS=h.MIN_MS,l.MAX_MS=h.MAX_MS;var p=t("./search");l.findBin=p.findBin,l.sorterAsc=p.sorterAsc,l.sorterDes=p.sorterDes,l.distinctVals=p.distinctVals,l.roundUp=p.roundUp,l.sort=p.sort,l.findIndexOfMin=p.findIndexOfMin;var d=t("./stats");l.aggNums=d.aggNums,l.len=d.len,l.mean=d.mean,l.midRange=d.midRange,l.variance=d.variance,l.stdev=d.stdev,l.interp=d.interp;var m=t("./matrix");l.init2dArray=m.init2dArray,l.transposeRagged=m.transposeRagged,l.dot=m.dot,l.translationMatrix=m.translationMatrix,l.rotationMatrix=m.rotationMatrix,l.rotationXYMatrix=m.rotationXYMatrix,l.apply2DTransform=m.apply2DTransform,l.apply2DTransform2=m.apply2DTransform2;var g=t("./angles");l.deg2rad=g.deg2rad,l.rad2deg=g.rad2deg,l.angleDelta=g.angleDelta,l.angleDist=g.angleDist,l.isFullCircle=g.isFullCircle,l.isAngleInsideSector=g.isAngleInsideSector,l.isPtInsideSector=g.isPtInsideSector,l.pathArc=g.pathArc,l.pathSector=g.pathSector,l.pathAnnulus=g.pathAnnulus;var v=t("./geometry2d");l.segmentsIntersect=v.segmentsIntersect,l.segmentDistance=v.segmentDistance,l.getTextLocation=v.getTextLocation,l.clearLocationCache=v.clearLocationCache,l.getVisibleSegment=v.getVisibleSegment,l.findPointOnPath=v.findPointOnPath;var y=t("./extend");l.extendFlat=y.extendFlat,l.extendDeep=y.extendDeep,l.extendDeepAll=y.extendDeepAll,l.extendDeepNoArrays=y.extendDeepNoArrays;var x=t("./loggers");l.log=x.log,l.warn=x.warn,l.error=x.error;var b=t("./regex");l.counterRegex=b.counter;var _=t("./throttle");function w(t){var e={};for(var r in t)for(var n=t[r],i=0;io?s:i(t)?Number(t):s:s},l.isIndex=function(t,e){return!(void 0!==e&&t>=e)&&(i(t)&&t>=0&&t%1==0)},l.noop=t("./noop"),l.identity=t("./identity"),l.repeat=function(t,e){for(var r=new Array(e),n=0;nr?Math.max(r,Math.min(e,t)):Math.max(e,Math.min(r,t))},l.bBoxIntersect=function(t,e,r){return r=r||0,t.left<=e.right+r&&e.left<=t.right+r&&t.top<=e.bottom+r&&e.top<=t.bottom+r},l.simpleMap=function(t,e,r,n){for(var i=t.length,a=new Array(i),o=0;o=Math.pow(2,r)?i>10?(l.warn("randstr failed uniqueness"),c):t(e,r,n,(i||0)+1):c},l.OptionControl=function(t,e){t||(t={}),e||(e="opt");var r={optionList:[],_newoption:function(n){n[e]=t,r[n.name]=n,r.optionList.push(n)}};return r["_"+e]=t,r},l.smooth=function(t,e){if((e=Math.round(e)||0)<2)return t;var r,n,i,a,o=t.length,s=2*o,l=2*e-1,c=new Array(l),u=new Array(o);for(r=0;r=s&&(i-=s*Math.floor(i/s)),i<0?i=-1-i:i>=o&&(i=s-1-i),a+=t[i]*c[n];u[r]=a}return u},l.syncOrAsync=function(t,e,r){var n;function i(){return l.syncOrAsync(t,e,r)}for(;t.length;)if((n=(0,t.splice(0,1)[0])(e))&&n.then)return n.then(i).then(void 0,l.promiseError);return r&&r(e)},l.stripTrailingSlash=function(t){return"/"===t.substr(-1)?t.substr(0,t.length-1):t},l.noneOrAll=function(t,e,r){if(t){var n,i=!1,a=!0;for(n=0;n1?i+o[1]:"";if(a&&(o.length>1||s.length>4||r))for(;n.test(s);)s=s.replace(n,"$1"+a+"$2");return s+l};var A=/%{([^\s%{}]*)}/g,T=/^\w*$/;l.templateString=function(t,e){var r={};return t.replace(A,function(t,n){return T.test(n)?e[n]||"":(r[n]=r[n]||l.nestedProperty(e,n).get,r[n]()||"")})};l.subplotSort=function(t,e){for(var r=Math.min(t.length,e.length)+1,n=0,i=0,a=0;a=48&&o<=57,c=s>=48&&s<=57;if(l&&(n=10*n+o-48),c&&(i=10*i+s-48),!l||!c){if(n!==i)return n-i;if(o!==s)return o-s}}return i-n};var S=2e9;l.seedPseudoRandom=function(){S=2e9},l.pseudoRandom=function(){var t=S;return S=(69069*S+1)%4294967296,Math.abs(S-t)<429496729?l.pseudoRandom():S/4294967296}},{"../constants/numerical":673,"./angles":677,"./array":678,"./clean_number":679,"./clear_responsive":681,"./coerce":682,"./dates":683,"./extend":685,"./filter_unique":686,"./filter_visible":687,"./geometry2d":690,"./get_graph_div":691,"./identity":695,"./is_plain_object":697,"./keyed_container":698,"./localize":699,"./loggers":700,"./make_trace_groups":701,"./matrix":702,"./mod":703,"./nested_property":704,"./noop":705,"./notifier":706,"./push_unique":710,"./regex":712,"./relative_attr":713,"./relink_private":714,"./search":715,"./stats":718,"./throttle":721,"./to_log_range":722,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],697:[function(t,e,r){"use strict";e.exports=function(t){return window&&window.process&&window.process.versions?"[object Object]"===Object.prototype.toString.call(t):"[object Object]"===Object.prototype.toString.call(t)&&Object.getPrototypeOf(t)===Object.prototype}},{}],698:[function(t,e,r){"use strict";var n=t("./nested_property"),i=/^\w*$/;e.exports=function(t,e,r,a){var o,s,l;r=r||"name",a=a||"value";var c={};e&&e.length?(l=n(t,e),s=l.get()):s=t,e=e||"";var u={};if(s)for(o=0;o2)return c[e]=2|c[e],h.set(t,null);if(f){for(o=e;o1){for(var t=["LOG:"],e=0;e0){for(var t=["WARN:"],e=0;e0){for(var t=["ERROR:"],e=0;ee/2?t-Math.round(t/e)*e:t}}},{}],704:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("./array").isArrayOrTypedArray;e.exports=function(t,e){if(n(e))e=String(e);else if("string"!=typeof e||"[-1]"===e.substr(e.length-4))throw"bad property string";for(var r,a,o,l=0,c=e.split(".");l/g),o=0;oa||c===i||cs||e&&l(t))}:function(t,e){var l=t[0],c=t[1];if(l===i||la||c===i||cs)return!1;var u,f,h,p,d,m=r.length,g=r[0][0],v=r[0][1],y=0;for(u=1;uMath.max(f,g)||c>Math.max(h,v)))if(cu||Math.abs(n(o,h))>i)return!0;return!1};a.filter=function(t,e){var r=[t[0]],n=0,i=0;function a(a){t.push(a);var s=r.length,l=n;r.splice(i+1);for(var c=l+1;c1&&a(t.pop());return{addPt:a,raw:t,filtered:r}}},{"../constants/numerical":673,"./matrix":702}],709:[function(t,e,r){(function(r){"use strict";var n=t("./show_no_webgl_msg"),i=t("regl");e.exports=function(t,e){var a=t._fullLayout,o=!0;return a._glcanvas.each(function(n){if(!n.regl&&(!n.pick||a._has("parcoords"))){try{n.regl=i({canvas:this,attributes:{antialias:!n.pick,preserveDrawingBuffer:!0},pixelRatio:t._context.plotGlPixelRatio||r.devicePixelRatio,extensions:e||[]})}catch(t){o=!1}o&&this.addEventListener("webglcontextlost",function(e){t&&t.emit&&t.emit("plotly_webglcontextlost",{event:e,layer:n.key})},!1)}}),o||n({container:a._glcontainer.node()}),o}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./show_no_webgl_msg":717,regl:478}],710:[function(t,e,r){"use strict";e.exports=function(t,e){if(e instanceof RegExp){var r,n=e.toString();for(r=0;ri.queueLength&&(t.undoQueue.queue.shift(),t.undoQueue.index--))},startSequence:function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!0,t.undoQueue.beginSequence=!0},stopSequence:function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!1,t.undoQueue.beginSequence=!1},undo:function(t){var e,r;if(t.framework&&t.framework.isPolar)t.framework.undo();else if(!(void 0===t.undoQueue||isNaN(t.undoQueue.index)||t.undoQueue.index<=0)){for(t.undoQueue.index--,e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;r=t.undoQueue.queue.length)){for(e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;re}function c(t,e){return t>=e}r.findBin=function(t,e,r){if(n(e.start))return r?Math.ceil((t-e.start)/e.size-1e-9)-1:Math.floor((t-e.start)/e.size+1e-9);var a,u,f=0,h=e.length,p=0,d=h>1?(e[h-1]-e[0])/(h-1):1;for(u=d>=0?r?o:s:r?c:l,t+=1e-9*d*(r?-1:1)*(d>=0?1:-1);f90&&i.log("Long binary search..."),f-1},r.sorterAsc=function(t,e){return t-e},r.sorterDes=function(t,e){return e-t},r.distinctVals=function(t){var e=t.slice();e.sort(r.sorterAsc);for(var n=e.length-1,i=e[n]-e[0]||1,a=i/(n||1)/1e4,o=[e[0]],s=0;se[s]+a&&(i=Math.min(i,e[s+1]-e[s]),o.push(e[s+1]));return{vals:o,minDiff:i}},r.roundUp=function(t,e,r){for(var n,i=0,a=e.length-1,o=0,s=r?0:1,l=r?1:0,c=r?Math.ceil:Math.floor;i0&&(n=1),r&&n)return t.sort(e)}return n?t:t.reverse()},r.findIndexOfMin=function(t,e){e=e||a;for(var r,n=1/0,i=0;ia.length)&&(o=a.length),n(e)||(e=!1),i(a[0])){for(l=new Array(o),s=0;st.length-1)return t[t.length-1];var r=e%1;return r*t[Math.ceil(e)]+(1-r)*t[Math.floor(e)]}},{"./array":678,"fast-isnumeric":214}],719:[function(t,e,r){"use strict";var n=t("color-normalize");e.exports=function(t){return t?n(t):[0,0,0,1]}},{"color-normalize":108}],720:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../lib"),a=t("../constants/xmlns_namespaces"),o=t("../constants/alignment").LINE_SPACING;function s(t,e){return t.node().getBoundingClientRect()[e]}var l=/([^$]*)([$]+[^$]*[$]+)([^$]*)/;r.convertToTspans=function(t,e,g){var S=t.text(),E=!t.attr("data-notex")&&"undefined"!=typeof MathJax&&S.match(l),L=n.select(t.node().parentNode);if(!L.empty()){var z=t.attr("class")?t.attr("class").split(" ")[0]:"text";return z+="-math",L.selectAll("svg."+z).remove(),L.selectAll("g."+z+"-group").remove(),t.style("display",null).attr({"data-unformatted":S,"data-math":"N"}),E?(e&&e._promises||[]).push(new Promise(function(e){t.style("display","none");var r=parseInt(t.node().style.fontSize,10),a={fontSize:r};!function(t,e,r){var a,o,s,l;MathJax.Hub.Queue(function(){return o=i.extendDeepAll({},MathJax.Hub.config),s=MathJax.Hub.processSectionDelay,void 0!==MathJax.Hub.processSectionDelay&&(MathJax.Hub.processSectionDelay=0),MathJax.Hub.Config({messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]]},displayAlign:"left"})},function(){if("SVG"!==(a=MathJax.Hub.config.menuSettings.renderer))return MathJax.Hub.setRenderer("SVG")},function(){var r="math-output-"+i.randstr({},64);return l=n.select("body").append("div").attr({id:r}).style({visibility:"hidden",position:"absolute"}).style({"font-size":e.fontSize+"px"}).text(t.replace(c,"\\lt ").replace(u,"\\gt ")),MathJax.Hub.Typeset(l.node())},function(){var e=n.select("body").select("#MathJax_SVG_glyphs");if(l.select(".MathJax_SVG").empty()||!l.select("svg").node())i.log("There was an error in the tex syntax.",t),r();else{var o=l.select("svg").node().getBoundingClientRect();r(l.select(".MathJax_SVG"),e,o)}if(l.remove(),"SVG"!==a)return MathJax.Hub.setRenderer(a)},function(){return void 0!==s&&(MathJax.Hub.processSectionDelay=s),MathJax.Hub.Config(o)})}(E[2],a,function(n,i,a){L.selectAll("svg."+z).remove(),L.selectAll("g."+z+"-group").remove();var o=n&&n.select("svg");if(!o||!o.node())return O(),void e();var l=L.append("g").classed(z+"-group",!0).attr({"pointer-events":"none","data-unformatted":S,"data-math":"Y"});l.node().appendChild(o.node()),i&&i.node()&&o.node().insertBefore(i.node().cloneNode(!0),o.node().firstChild),o.attr({class:z,height:a.height,preserveAspectRatio:"xMinYMin meet"}).style({overflow:"visible","pointer-events":"none"});var c=t.node().style.fill||"black";o.select("g").attr({fill:c,stroke:c});var u=s(o,"width"),f=s(o,"height"),h=+t.attr("x")-u*{start:0,middle:.5,end:1}[t.attr("text-anchor")||"start"],p=-(r||s(t,"height"))/4;"y"===z[0]?(l.attr({transform:"rotate("+[-90,+t.attr("x"),+t.attr("y")]+") translate("+[-u/2,p-f/2]+")"}),o.attr({x:+t.attr("x"),y:+t.attr("y")})):"l"===z[0]?o.attr({x:t.attr("x"),y:p-f/2}):"a"===z[0]?o.attr({x:0,y:p}):o.attr({x:h,y:+t.attr("y")+p-f/2}),g&&g.call(t,l),e(l)})})):O(),t}function O(){L.empty()||(z=t.attr("class")+"-math",L.select("svg."+z).remove()),t.text("").style("white-space","pre"),function(t,e){e=e.replace(v," ");var r,s=!1,l=[],c=-1;function u(){c++;var e=document.createElementNS(a.svg,"tspan");n.select(e).attr({class:"line",dy:c*o+"em"}),t.appendChild(e),r=e;var i=l;if(l=[{node:e}],i.length>1)for(var s=1;s doesnt match end tag <"+t+">. Pretending it did match.",e),r=l[l.length-1].node}else i.log("Ignoring unexpected end tag .",e)}b.test(e)?u():(r=t,l=[{node:t}]);for(var L=e.split(y),z=0;z|>|>)/g;var f={sup:"font-size:70%",sub:"font-size:70%",b:"font-weight:bold",i:"font-style:italic",a:"cursor:pointer",span:"",em:"font-style:italic;font-weight:bold"},h={sub:"0.3em",sup:"-0.6em"},p={sub:"-0.21em",sup:"0.42em"},d="\u200b",m=["http:","https:","mailto:","",void 0,":"],g=new RegExp("]*)?/?>","g"),v=/(\r\n?|\n)/g,y=/(<[^<>]*>)/,x=/<(\/?)([^ >]*)(\s+(.*))?>/i,b=//i,_=/(^|[\s"'])style\s*=\s*("([^"]*);?"|'([^']*);?')/i,w=/(^|[\s"'])href\s*=\s*("([^"]*)"|'([^']*)')/i,k=/(^|[\s"'])target\s*=\s*("([^"\s]*)"|'([^'\s]*)')/i,M=/(^|[\s"'])popup\s*=\s*("([\w=,]*)"|'([\w=,]*)')/i;function A(t,e){if(!t)return null;var r=t.match(e),n=r&&(r[3]||r[4]);return n&&C(n)}var T=/(^|;)\s*color:/;r.plainText=function(t){return(t||"").replace(g," ")};var S={mu:"\u03bc",amp:"&",lt:"<",gt:">",nbsp:"\xa0",times:"\xd7",plusmn:"\xb1",deg:"\xb0"},E=/&(#\d+|#x[\da-fA-F]+|[a-z]+);/g;function C(t){return t.replace(E,function(t,e){return("#"===e.charAt(0)?function(t){if(t>1114111)return;var e=String.fromCodePoint;if(e)return e(t);var r=String.fromCharCode;return t<=65535?r(t):r(55232+(t>>10),t%1024+56320)}("x"===e.charAt(1)?parseInt(e.substr(2),16):parseInt(e.substr(1),10)):S[e])||t})}function L(t,e,r){var n,i,a,o=r.horizontalAlign,s=r.verticalAlign||"top",l=t.node().getBoundingClientRect(),c=e.node().getBoundingClientRect();return i="bottom"===s?function(){return l.bottom-n.height}:"middle"===s?function(){return l.top+(l.height-n.height)/2}:function(){return l.top},a="right"===o?function(){return l.right-n.width}:"center"===o?function(){return l.left+(l.width-n.width)/2}:function(){return l.left},function(){return n=this.node().getBoundingClientRect(),this.style({top:i()-c.top+"px",left:a()-c.left+"px","z-index":1e3}),this}}r.convertEntities=C,r.lineCount=function(t){return t.selectAll("tspan.line").size()||1},r.positionText=function(t,e,r){return t.each(function(){var t=n.select(this);function i(e,r){return void 0===r?null===(r=t.attr(e))&&(t.attr(e,0),r=0):t.attr(e,r),r}var a=i("x",e),o=i("y",r);"text"===this.nodeName&&t.selectAll("tspan.line").attr({x:a,y:o})})},r.makeEditable=function(t,e){var r=e.gd,i=e.delegate,a=n.dispatch("edit","input","cancel"),o=i||t;if(t.style({"pointer-events":i?"none":"all"}),1!==t.size())throw new Error("boo");function s(){!function(){var i=n.select(r).select(".svg-container"),o=i.append("div"),s=t.node().style,c=parseFloat(s.fontSize||12),u=e.text;void 0===u&&(u=t.attr("data-unformatted"));o.classed("plugin-editable editable",!0).style({position:"absolute","font-family":s.fontFamily||"Arial","font-size":c,color:e.fill||s.fill||"black",opacity:1,"background-color":e.background||"transparent",outline:"#ffffff33 1px solid",margin:[-c/8+1,0,0,-1].join("px ")+"px",padding:"0","box-sizing":"border-box"}).attr({contenteditable:!0}).text(u).call(L(t,i,e)).on("blur",function(){r._editing=!1,t.text(this.textContent).style({opacity:1});var e,i=n.select(this).attr("class");(e=i?"."+i.split(" ")[0]+"-math-group":"[class*=-math-group]")&&n.select(t.node().parentNode).select(e).style({opacity:0});var o=this.textContent;n.select(this).transition().duration(0).remove(),n.select(document).on("mouseup",null),a.edit.call(t,o)}).on("focus",function(){var t=this;r._editing=!0,n.select(document).on("mouseup",function(){if(n.event.target===t)return!1;document.activeElement===o.node()&&o.node().blur()})}).on("keyup",function(){27===n.event.which?(r._editing=!1,t.style({opacity:1}),n.select(this).style({opacity:0}).on("blur",function(){return!1}).transition().remove(),a.cancel.call(t,this.textContent)):(a.input.call(t,this.textContent),n.select(this).call(L(t,i,e)))}).on("keydown",function(){13===n.event.which&&this.blur()}).call(l)}(),t.style({opacity:0});var i,s=o.attr("class");(i=s?"."+s.split(" ")[0]+"-math-group":"[class*=-math-group]")&&n.select(t.node().parentNode).select(i).style({opacity:0})}function l(t){var e=t.node(),r=document.createRange();r.selectNodeContents(e);var n=window.getSelection();n.removeAllRanges(),n.addRange(r),e.focus()}return e.immediate?s():o.on("click",s),n.rebind(t,a,"on")}},{"../constants/alignment":668,"../constants/xmlns_namespaces":674,"../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],721:[function(t,e,r){"use strict";var n={};function i(t){t&&null!==t.timer&&(clearTimeout(t.timer),t.timer=null)}r.throttle=function(t,e,r){var a=n[t],o=Date.now();if(!a){for(var s in n)n[s].tsa.ts+e?l():a.timer=setTimeout(function(){l(),a.timer=null},e)},r.done=function(t){var e=n[t];return e&&e.timer?new Promise(function(t){var r=e.onDone;e.onDone=function(){r&&r(),t(),e.onDone=null}}):Promise.resolve()},r.clear=function(t){if(t)i(n[t]),delete n[t];else for(var e in n)r.clear(e)}},{}],722:[function(t,e,r){"use strict";var n=t("fast-isnumeric");e.exports=function(t,e){if(t>0)return Math.log(t)/Math.LN10;var r=Math.log(Math.min(e[0],e[1]))/Math.LN10;return n(r)||(r=Math.log(Math.max(e[0],e[1]))/Math.LN10-6),r}},{"fast-isnumeric":214}],723:[function(t,e,r){"use strict";var n=e.exports={},i=t("../plots/geo/constants").locationmodeToLayer,a=t("topojson-client").feature;n.getTopojsonName=function(t){return[t.scope.replace(/ /g,"-"),"_",t.resolution.toString(),"m"].join("")},n.getTopojsonPath=function(t,e){return t+e+".json"},n.getTopojsonFeatures=function(t,e){var r=i[t.locationmode],n=e.objects[r];return a(e,n).features}},{"../plots/geo/constants":773,"topojson-client":517}],724:[function(t,e,r){"use strict";e.exports={moduleType:"locale",name:"en-US",dictionary:{"Click to enter Colorscale title":"Click to enter Colorscale title"},format:{date:"%m/%d/%Y"}}},{}],725:[function(t,e,r){"use strict";e.exports={moduleType:"locale",name:"en",dictionary:{"Click to enter Colorscale title":"Click to enter Colourscale title"},format:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],periods:["AM","PM"],dateTime:"%a %b %e %X %Y",date:"%d/%m/%Y",time:"%H:%M:%S",decimal:".",thousands:",",grouping:[3],currency:["$",""],year:"%Y",month:"%b %Y",dayMonth:"%b %-d",dayMonthYear:"%b %-d, %Y"}}},{}],726:[function(t,e,r){"use strict";var n=t("../registry");e.exports=function(t){for(var e,r,i=n.layoutArrayContainers,a=n.layoutArrayRegexes,o=t.split("[")[0],s=0;s0&&o.log("Clearing previous rejected promises from queue."),t._promises=[]},r.cleanLayout=function(t){var e,r;t||(t={}),t.xaxis1&&(t.xaxis||(t.xaxis=t.xaxis1),delete t.xaxis1),t.yaxis1&&(t.yaxis||(t.yaxis=t.yaxis1),delete t.yaxis1),t.scene1&&(t.scene||(t.scene=t.scene1),delete t.scene1);var n=(s.subplotsRegistry.cartesian||{}).attrRegex,a=(s.subplotsRegistry.gl3d||{}).attrRegex,l=Object.keys(t);for(e=0;e3?(T.x=1.02,T.xanchor="left"):T.x<-2&&(T.x=-.02,T.xanchor="right"),T.y>3?(T.y=1.02,T.yanchor="bottom"):T.y<-2&&(T.y=-.02,T.yanchor="top")),"rotate"===t.dragmode&&(t.dragmode="orbit"),f.clean(t),t},r.cleanData=function(t){for(var e=0;e0)return t.substr(0,e)}r.hasParent=function(t,e){for(var r=y(e);r;){if(r in t)return!0;r=y(r)}return!1};var x=["x","y","z"];r.clearAxisTypes=function(t,e,r){for(var n=0;n1&&a.warn("Full array edits are incompatible with other edits",f);var y=r[""][""];if(c(y))e.set(null);else{if(!Array.isArray(y))return a.warn("Unrecognized full array edit value",f,y),!0;e.set(y)}return!m&&(h(g,v),p(t),!0)}var x,b,_,w,k,M,A,T,S=Object.keys(r).map(Number).sort(o),E=e.get(),C=E||[],L=u(v,f).get(),z=[],O=-1,I=C.length;for(x=0;xC.length-(A?0:1))a.warn("index out of range",f,_);else if(void 0!==M)k.length>1&&a.warn("Insertion & removal are incompatible with edits to the same index.",f,_),c(M)?z.push(_):A?("add"===M&&(M={}),C.splice(_,0,M),L&&L.splice(_,0,{})):a.warn("Unrecognized full object edit value",f,_,M),-1===O&&(O=_);else for(b=0;b=0;x--)C.splice(z[x],1),L&&L.splice(z[x],1);if(C.length?E||e.set(C):e.set(null),m)return!1;if(h(g,v),d!==i){var P;if(-1===O)P=S;else{for(I=Math.max(C.length,I),P=[],x=0;x=O);x++)P.push(_);for(x=O;x=t.data.length||i<-t.data.length)throw new Error(r+" must be valid indices for gd.data.");if(e.indexOf(i,n+1)>-1||i>=0&&e.indexOf(-t.data.length+i)>-1||i<0&&e.indexOf(t.data.length+i)>-1)throw new Error("each index in "+r+" must be unique.")}}function P(t,e,r){if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if("undefined"==typeof e)throw new Error("currentIndices is a required argument.");if(Array.isArray(e)||(e=[e]),I(t,e,"currentIndices"),"undefined"==typeof r||Array.isArray(r)||(r=[r]),"undefined"!=typeof r&&I(t,r,"newIndices"),"undefined"!=typeof r&&e.length!==r.length)throw new Error("current and new indices must be of equal length.")}function D(t,e,r,n,a){!function(t,e,r,n){var i=o.isPlainObject(n);if(!Array.isArray(t.data))throw new Error("gd.data must be an array");if(!o.isPlainObject(e))throw new Error("update must be a key:value object");if("undefined"==typeof r)throw new Error("indices must be an integer or array of integers");for(var a in I(t,r,"indices"),e){if(!Array.isArray(e[a])||e[a].length!==r.length)throw new Error("attribute "+a+" must be an array of length equal to indices array length");if(i&&(!(a in n)||!Array.isArray(n[a])||n[a].length!==e[a].length))throw new Error("when maxPoints is set as a key:value object it must contain a 1:1 corrispondence with the keys and number of traces in the update object")}}(t,e,r,n);for(var l=function(t,e,r,n){var a,l,c,u,f,h=o.isPlainObject(n),p=[];for(var d in Array.isArray(r)||(r=[r]),r=O(r,t.data.length-1),e)for(var m=0;m=0&&r=0&&r0&&"string"!=typeof O.parts[P];)P--;var D=O.parts[P],R=O.parts[P-1]+"."+D,B=O.parts.slice(0,P).join("."),j=s(t.layout,B).get(),V=s(l,B).get(),U=O.get();if(void 0!==I){_[z]=I,M[z]="reverse"===D?I:F(U);var q=f.getLayoutValObject(l,O.parts);if(q&&q.impliedEdits&&null!==I)for(var H in q.impliedEdits)S(o.relativeAttr(z,H),q.impliedEdits[H]);if(-1!==["width","height"].indexOf(z))if(I){S("autosize",null);var X="height"===z?"width":"height";S(X,l[X])}else l[z]=t._initialAutoSize[z];else if("autosize"===z)S("width",I?null:l.width),S("height",I?null:l.height);else if(R.match(G))L(R),s(l,B+"._inputRange").set(null);else if(R.match(W)){L(R),s(l,B+"._inputRange").set(null);var $=s(l,B).get();$._inputDomain&&($._input.domain=$._inputDomain.slice())}else R.match(Y)&&s(l,B+"._inputDomain").set(null);if("type"===D){var J=j,K="linear"===V.type&&"log"===I,Q="log"===V.type&&"linear"===I;if(K||Q){if(J&&J.range)if(V.autorange)K&&(J.range=J.range[1]>J.range[0]?[1,2]:[2,1]);else{var tt=J.range[0],et=J.range[1];K?(tt<=0&&et<=0&&S(B+".autorange",!0),tt<=0?tt=et/1e6:et<=0&&(et=tt/1e6),S(B+".range[0]",Math.log(tt)/Math.LN10),S(B+".range[1]",Math.log(et)/Math.LN10)):(S(B+".range[0]",Math.pow(10,tt)),S(B+".range[1]",Math.pow(10,et)))}else S(B+".autorange",!0);Array.isArray(l._subplots.polar)&&l._subplots.polar.length&&l[O.parts[0]]&&"radialaxis"===O.parts[1]&&delete l[O.parts[0]]._subplot.viewInitial["radialaxis.range"],u.getComponentMethod("annotations","convertCoords")(t,V,I,S),u.getComponentMethod("images","convertCoords")(t,V,I,S)}else S(B+".autorange",!0),S(B+".range",null);s(l,B+"._inputRange").set(null)}else if(D.match(T)){var rt=s(l,z).get(),nt=(I||{}).type;nt&&"-"!==nt||(nt="linear"),u.getComponentMethod("annotations","convertCoords")(t,rt,nt,S),u.getComponentMethod("images","convertCoords")(t,rt,nt,S)}var it=w.containerArrayMatch(z);if(it){r=it.array,n=it.index;var at=it.property,ot=q||{editType:"calc"};""!==n&&""===at&&(w.isAddVal(I)?M[z]=null:w.isRemoveVal(I)?M[z]=(s(a,r).get()||[])[n]:o.warn("unrecognized full object value",e)),A.update(b,ot),g[r]||(g[r]={});var st=g[r][n];st||(st=g[r][n]={}),st[at]=I,delete e[z]}else"reverse"===D?(j.range?j.range.reverse():(S(B+".autorange",!0),j.range=[1,0]),V.autorange?b.calc=!0:b.plot=!0):(l._has("scatter-like")&&l._has("regl")&&"dragmode"===z&&("lasso"===I||"select"===I)&&"lasso"!==U&&"select"!==U?b.plot=!0:q?A.update(b,q):b.calc=!0,O.set(I))}}for(r in g){w.applyContainerArrayChanges(t,h(a,r),g[r],b,h)||(b.plot=!0)}var lt=l._axisConstraintGroups||[];for(E in C)for(n=0;n1;)if(n.pop(),void 0!==(r=s(e,n.join(".")+".uirevision").get()))return r;return e.uirevision}function rt(t,e){for(var r=0;r=i.length?i[0]:i[t]:i}function l(t){return Array.isArray(a)?t>=a.length?a[0]:a[t]:a}function c(t,e){var r=0;return function(){if(t&&++r===e)return t()}}return void 0===n._frameWaitingCnt&&(n._frameWaitingCnt=0),new Promise(function(a,u){function f(){n._currentFrame&&n._currentFrame.onComplete&&n._currentFrame.onComplete();var e=n._currentFrame=n._frameQueue.shift();if(e){var r=e.name?e.name.toString():null;t._fullLayout._currentFrame=r,n._lastFrameAt=Date.now(),n._timeToNext=e.frameOpts.duration,h.transition(t,e.frame.data,e.frame.layout,k.coerceTraceIndices(t,e.frame.traces),e.frameOpts,e.transitionOpts).then(function(){e.onComplete&&e.onComplete()}),t.emit("plotly_animatingframe",{name:r,frame:e.frame,animation:{frame:e.frameOpts,transition:e.transitionOpts}})}else t.emit("plotly_animated"),window.cancelAnimationFrame(n._animationRaf),n._animationRaf=null}function p(){t.emit("plotly_animating"),n._lastFrameAt=-1/0,n._timeToNext=0,n._runningTransitions=0,n._currentFrame=null;var e=function(){n._animationRaf=window.requestAnimationFrame(e),Date.now()-n._lastFrameAt>n._timeToNext&&f()};e()}var d,m,g=0;function v(t){return Array.isArray(i)?g>=i.length?t.transitionOpts=i[g]:t.transitionOpts=i[0]:t.transitionOpts=i,g++,t}var y=[],x=null==e,b=Array.isArray(e);if(!x&&!b&&o.isPlainObject(e))y.push({type:"object",data:v(o.extendFlat({},e))});else if(x||-1!==["string","number"].indexOf(typeof e))for(d=0;d0&&MM)&&A.push(m);y=A}}y.length>0?function(e){if(0!==e.length){for(var i=0;i=0;n--)if(o.isPlainObject(e[n])){var m=e[n].name,g=(u[m]||d[m]||{}).name,v=e[n].name,y=u[g]||d[g];g&&v&&"number"==typeof v&&y&&S<5&&(S++,o.warn('addFrames: overwriting frame "'+(u[g]||d[g]).name+'" with a frame whose name of type "number" also equates to "'+g+'". This is valid but may potentially lead to unexpected behavior since all plotly.js frame names are stored internally as strings.'),5===S&&o.warn("addFrames: This API call has yielded too many of these warnings. For the rest of this call, further warnings about numeric frame names will be suppressed.")),d[m]={name:m},p.push({frame:h.supplyFrameDefaults(e[n]),index:r&&void 0!==r[n]&&null!==r[n]?r[n]:f+n})}p.sort(function(t,e){return t.index>e.index?-1:t.index=0;n--){if("number"==typeof(i=p[n].frame).name&&o.warn("Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings"),!i.name)for(;u[i.name="frame "+t._transitionData._counter++];);if(u[i.name]){for(a=0;a=0;r--)n=e[r],a.push({type:"delete",index:n}),s.unshift({type:"insert",index:n,value:i[n]});var l=h.modifyFrames,u=h.modifyFrames,f=[t,s],p=[t,a];return c&&c.add(t,l,f,u,p),h.modifyFrames(t,a)},r.purge=function(t){var e=(t=o.getGraphDiv(t))._fullLayout||{},r=t._fullData||[];return h.cleanPlot([],{},r,e),h.purge(t),l.purge(t),e._container&&e._container.remove(),delete t._context,t}},{"../components/color":570,"../components/colorbar/connect":572,"../components/drawing":595,"../constants/xmlns_namespaces":674,"../lib":696,"../lib/events":684,"../lib/queue":711,"../lib/svg_text_utils":720,"../plots/cartesian/axes":744,"../plots/cartesian/constants":750,"../plots/cartesian/graph_interact":754,"../plots/plots":808,"../plots/polar/legacy":816,"../registry":827,"./edit_types":727,"./helpers":728,"./manage_arrays":730,"./plot_config":732,"./plot_schema":733,"./subroutines":735,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214,"has-hover":393}],732:[function(t,e,r){"use strict";e.exports={staticPlot:!1,plotlyServerURL:"https://plot.ly",editable:!1,edits:{annotationPosition:!1,annotationTail:!1,annotationText:!1,axisTitleText:!1,colorbarPosition:!1,colorbarTitleText:!1,legendPosition:!1,legendText:!1,shapePosition:!1,titleText:!1},autosizable:!1,responsive:!1,queueLength:0,fillFrame:!1,frameMargins:0,scrollZoom:!1,doubleClick:"reset+autosize",showTips:!0,showAxisDragHandles:!0,showAxisRangeEntryBoxes:!0,showLink:!1,sendData:!0,linkText:"Edit chart",showSources:!1,displayModeBar:"hover",modeBarButtonsToRemove:[],modeBarButtonsToAdd:[],modeBarButtons:!1,toImageButtonOptions:{},displaylogo:!0,plotGlPixelRatio:2,setBackground:"transparent",topojsonURL:"https://cdn.plot.ly/",mapboxAccessToken:null,logging:1,globalTransforms:[],locale:"en-US",locales:{}}},{}],733:[function(t,e,r){"use strict";var n=t("../registry"),i=t("../lib"),a=t("../plots/attributes"),o=t("../plots/layout_attributes"),s=t("../plots/frame_attributes"),l=t("../plots/animation_attributes"),c=t("../plots/polar/legacy/area_attributes"),u=t("../plots/polar/legacy/axis_attributes"),f=t("./edit_types"),h=i.extendFlat,p=i.extendDeepAll,d=i.isPlainObject,m="_isSubplotObj",g="_isLinkedToArray",v=[m,g,"_arrayAttrRegexps","_deprecated"];function y(t,e,r){if(!t)return!1;if(t._isLinkedToArray)if(x(e[r]))r++;else if(r=a.length)return!1;if(2===t.dimensions){if(r++,e.length===r)return t;var o=e[r];if(!x(o))return!1;t=a[i][o]}else t=a[i]}else t=a}}return t}function x(t){return t===Math.round(t)&&t>=0}function b(t){return function(t){r.crawl(t,function(t,e,n){r.isValObject(t)?"data_array"===t.valType?(t.role="data",n[e+"src"]={valType:"string",editType:"none"}):!0===t.arrayOk&&(n[e+"src"]={valType:"string",editType:"none"}):d(t)&&(t.role="object")})}(t),function(t){r.crawl(t,function(t,e,r){if(!t)return;var n=t[g];if(!n)return;delete t[g],r[e]={items:{}},r[e].items[n]=t,r[e].role="object"})}(t),function(t){!function t(e){for(var r in e)if(d(e[r]))t(e[r]);else if(Array.isArray(e[r]))for(var n=0;n=l.length)return!1;i=(r=(n.transformsRegistry[l[u].type]||{}).attributes)&&r[e[2]],s=3}else if("area"===t.type)i=c[o];else{var f=t._module;if(f||(f=(n.modules[t.type||a.type.dflt]||{})._module),!f)return!1;if(!(i=(r=f.attributes)&&r[o])){var h=f.basePlotModule;h&&h.attributes&&(i=h.attributes[o])}i||(i=a[o])}return y(i,e,s)},r.getLayoutValObject=function(t,e){return y(function(t,e){var r,i,a,s,l=t._basePlotModules;if(l){var c;for(r=0;r=i&&(r._input||{})._templateitemname;s&&(o=i);var l,c=e+"["+o+"]";function u(){l={},s&&(l[c]={},l[c][a]=s)}function f(t,e){s?n.nestedProperty(l[c],t).set(e):l[c+"."+t]=e}function h(){var t=l;return u(),t}return u(),{modifyBase:function(t,e){l[t]=e},modifyItem:f,getUpdateObj:h,applyUpdate:function(e,r){e&&f(e,r);var i=h();for(var a in i)n.nestedProperty(t,a).set(i[a])}}}},{"../lib":696,"../plots/attributes":741}],735:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../registry"),a=t("../plots/plots"),o=t("../lib"),s=t("../lib/clear_gl_canvases"),l=t("../components/color"),c=t("../components/drawing"),u=t("../components/titles"),f=t("../components/modebar"),h=t("../plots/cartesian/axes"),p=t("../constants/alignment"),d=t("../plots/cartesian/constraints"),m=d.enforce,g=d.clean,v=t("../plots/cartesian/autorange").doAutoRange;function y(t,e,r){for(var n=0;n=t[1]||i[1]<=t[0])&&(a[0]e[0]))return!0}return!1}function x(t){var e,i,a,s,u,d=t._fullLayout,m=d._size,g=m.p,v=h.list(t,"",!0);if(d._paperdiv.style({width:t._context.responsive&&d.autosize&&!t._context._hasZeroWidth&&!t.layout.width?"100%":d.width+"px",height:t._context.responsive&&d.autosize&&!t._context._hasZeroHeight&&!t.layout.height?"100%":d.height+"px"}).selectAll(".main-svg").call(c.setSize,d.width,d.height),t._context.setBackground(t,d.paper_bgcolor),r.drawMainTitle(t),f.manage(t),!d._has("cartesian"))return t._promises.length&&Promise.all(t._promises);function x(t,e,r){var n=t._lw/2;return"x"===t._id.charAt(0)?e?"top"===r?e._offset-g-n:e._offset+e._length+g+n:m.t+m.h*(1-(t.position||0))+n%1:e?"right"===r?e._offset+e._length+g+n:e._offset-g-n:m.l+m.w*(t.position||0)+n%1}for(e=0;ek?u.push({code:"unused",traceType:y,templateCount:w,dataCount:k}):k>w&&u.push({code:"reused",traceType:y,templateCount:w,dataCount:k})}}else u.push({code:"data"});if(function t(e,r){for(var n in e)if("_"!==n.charAt(0)){var a=e[n],o=p(e,n,r);i(a)?(Array.isArray(e)&&!1===a._template&&a.templateitemname&&u.push({code:"missing",path:o,templateitemname:a.templateitemname}),t(a,o)):Array.isArray(a)&&d(a)&&t(a,o)}}({data:g,layout:h},""),u.length)return u.map(m)}},{"../lib":696,"../plots/attributes":741,"../plots/plots":808,"./plot_config":732,"./plot_schema":733,"./plot_template":734}],737:[function(t,e,r){"use strict";var n=t("./plot_api"),i=t("../lib"),a=t("../snapshot/helpers"),o=t("../snapshot/tosvg"),s=t("../snapshot/svgtoimg"),l={format:{valType:"enumerated",values:["png","jpeg","webp","svg"],dflt:"png"},width:{valType:"number",min:1},height:{valType:"number",min:1},scale:{valType:"number",min:0,dflt:1},setBackground:{valType:"any",dflt:!1},imageDataOnly:{valType:"boolean",dflt:!1}},c=/^data:image\/\w+;base64,/;e.exports=function(t,e){var r,u,f;function h(t){return!(t in e)||i.validate(e[t],l[t])}if(e=e||{},i.isPlainObject(t)?(r=t.data||[],u=t.layout||{},f=t.config||{}):(t=i.getGraphDiv(t),r=i.extendDeep([],t.data),u=i.extendDeep({},t.layout),f=t._context),!h("width")||!h("height"))throw new Error("Height and width should be pixel values.");if(!h("format"))throw new Error("Image format is not jpeg, png, svg or webp.");var p={};function d(t,r){return i.coerce(e,p,l,t,r)}var m=d("format"),g=d("width"),v=d("height"),y=d("scale"),x=d("setBackground"),b=d("imageDataOnly"),_=document.createElement("div");_.style.position="absolute",_.style.left="-5000px",document.body.appendChild(_);var w=i.extendFlat({},u);g&&(w.width=g),v&&(w.height=v);var k=i.extendFlat({},f,{staticPlot:!0,setBackground:x}),M=a.getRedrawFunc(_);function A(){return new Promise(function(t){setTimeout(t,a.getDelay(_._fullLayout))})}function T(){return new Promise(function(t,e){var r=o(_,m,y),a=_._fullLayout.width,l=_._fullLayout.height;if(n.purge(_),document.body.removeChild(_),"svg"===m)return t(b?r:"data:image/svg+xml,"+encodeURIComponent(r));var c=document.createElement("canvas");c.id=i.randstr(),s({format:m,width:a,height:l,scale:y,canvas:c,svg:r,promise:!0}).then(t).catch(e)})}return new Promise(function(t,e){n.plot(_,r,w,k).then(M).then(A).then(T).then(function(e){t(function(t){return b?t.replace(c,""):t}(e))}).catch(function(t){e(t)})})}},{"../lib":696,"../snapshot/helpers":831,"../snapshot/svgtoimg":833,"../snapshot/tosvg":835,"./plot_api":731}],738:[function(t,e,r){"use strict";var n=t("../lib"),i=t("../plots/plots"),a=t("./plot_schema"),o=t("./plot_config"),s=n.isPlainObject,l=Array.isArray,c=n.isArrayOrTypedArray;function u(t,e,r,i,a,o){o=o||[];for(var f=Object.keys(t),h=0;hx.length&&i.push(p("unused",a,v.concat(x.length)));var M,A,T,S,E,C=x.length,L=Array.isArray(k);if(L&&(C=Math.min(C,k.length)),2===b.dimensions)for(A=0;Ax[A].length&&i.push(p("unused",a,v.concat(A,x[A].length)));var z=x[A].length;for(M=0;M<(L?Math.min(z,k[A].length):z);M++)T=L?k[A][M]:k,S=y[A][M],E=x[A][M],n.validate(S,T)?E!==S&&E!==+S&&i.push(p("dynamic",a,v.concat(A,M),S,E)):i.push(p("value",a,v.concat(A,M),S))}else i.push(p("array",a,v.concat(A),y[A]));else for(A=0;A1&&h.push(p("object","layout"))),i.supplyDefaults(d);for(var m=d._fullData,g=r.length,v=0;v0&&((b=A-o(g)-o(v))>T?_/b>S&&(y=g,x=v,S=_/b):_/A>S&&(y={val:g.val,pad:0},x={val:v.val,pad:0},S=_/A));if(h===p){var E=h-1,C=h+1;if(k)if(0===h)a=[0,1];else{var L=(h>0?f:u).reduce(function(t,e){return Math.max(t,o(e))},0),z=h/(1-Math.min(.5,L/A));a=h>0?[0,z]:[z,0]}else a=M?[Math.max(0,E),Math.max(1,C)]:[E,C]}else k?(y.val>=0&&(y={val:0,pad:0}),x.val<=0&&(x={val:0,pad:0})):M&&(y.val-S*o(y)<0&&(y={val:0,pad:0}),x.val<=0&&(x={val:1,pad:0})),S=(x.val-y.val)/(A-o(y)-o(x)),a=[y.val-S*o(y),x.val+S*o(x)];return d&&a.reverse(),i.simpleMap(a,e.l2r||Number)}function l(t){var e=t._length/20;return"domain"===t.constrain&&t._inputDomain&&(e*=(t._inputDomain[1]-t._inputDomain[0])/(t.domain[1]-t.domain[0])),function(t){return t.pad+(t.extrapad?e:0)}}function c(t,e){var r,n,i,a=e._id,o=t._fullData,s=t._fullLayout,l=[],c=[];function h(t,e){for(r=0;r=r&&(c.extrapad||!o)){s=!1;break}i(e,c.val)&&c.pad<=r&&(o||!c.extrapad)&&(t.splice(l,1),l--)}if(s){var u=a&&0===e;t.push({val:e,pad:u?0:r,extrapad:!u&&o})}}function p(t){return n(t)&&Math.abs(t)=e}e.exports={getAutoRange:s,makePadFn:l,doAutoRange:function(t,e){e._length||e.setScale();var r;if(e.autorange){e.range=s(t,e),e._r=e.range.slice(),e._rl=i.simpleMap(e._r,e.r2l),r=e._input;var n={};n[e._attr+".range"]=e.range,n[e._attr+".autorange"]=e.autorange,o.call("_storeDirectGUIEdit",t.layout,t._fullLayout._preGUI,n),r.range=e.range.slice(),r.autorange=e.autorange}if(e._anchorAxis&&e._anchorAxis.rangeslider){var a=e._anchorAxis.rangeslider[e._name];a&&"auto"===a.rangemode&&(a.range=s(t,e)),(r=e._anchorAxis._input).rangeslider[e._name]=i.extendFlat({},a)}},findExtremes:function(t,e,r){r||(r={});t._m||t.setScale();var i,o,s,l,c,h,d,m,g,v=[],y=[],x=e.length,b=r.padded||!1,_=r.tozero&&("linear"===t.type||"-"===t.type),w="log"===t.type,k=!1;function M(t){if(Array.isArray(t))return k=!0,function(e){return Math.max(Number(t[e]||0),0)};var e=Math.max(Number(t||0),0);return function(){return e}}var A=M((t._m>0?r.ppadplus:r.ppadminus)||r.ppad||0),T=M((t._m>0?r.ppadminus:r.ppadplus)||r.ppad||0),S=M(r.vpadplus||r.vpad),E=M(r.vpadminus||r.vpad);if(!k){if(m=1/0,g=-1/0,w)for(i=0;i0&&(m=o),o>g&&o-a&&(m=o),o>g&&o=z;i--)L(i);return{min:v,max:y}},concatExtremes:c}},{"../../constants/numerical":673,"../../lib":696,"../../registry":827,"fast-isnumeric":214}],744:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("fast-isnumeric"),a=t("../../plots/plots"),o=t("../../registry"),s=t("../../lib"),l=t("../../lib/svg_text_utils"),c=t("../../components/titles"),u=t("../../components/color"),f=t("../../components/drawing"),h=t("./layout_attributes"),p=t("./clean_ticks"),d=t("../../constants/numerical"),m=d.ONEAVGYEAR,g=d.ONEAVGMONTH,v=d.ONEDAY,y=d.ONEHOUR,x=d.ONEMIN,b=d.ONESEC,_=d.MINUS_SIGN,w=d.BADNUM,k=t("../../constants/alignment").MID_SHIFT,M=t("../../constants/alignment").LINE_SPACING,A=e.exports={};A.setConvert=t("./set_convert");var T=t("./axis_autotype"),S=t("./axis_ids");A.id2name=S.id2name,A.name2id=S.name2id,A.cleanId=S.cleanId,A.list=S.list,A.listIds=S.listIds,A.getFromId=S.getFromId,A.getFromTrace=S.getFromTrace;var E=t("./autorange");A.getAutoRange=E.getAutoRange,A.findExtremes=E.findExtremes,A.coerceRef=function(t,e,r,n,i,a){var o=n.charAt(n.length-1),l=r._fullLayout._subplots[o+"axis"],c=n+"ref",u={};return i||(i=l[0]||a),a||(a=i),u[c]={valType:"enumerated",values:l.concat(a?[a]:[]),dflt:i},s.coerce(t,e,u,c)},A.coercePosition=function(t,e,r,n,i,a){var o,l;if("paper"===n||"pixel"===n)o=s.ensureNumber,l=r(i,a);else{var c=A.getFromId(e,n);l=r(i,a=c.fraction2r(a)),o=c.cleanPos}t[i]=o(l)},A.cleanPosition=function(t,e,r){return("paper"===r||"pixel"===r?s.ensureNumber:A.getFromId(e,r).cleanPos)(t)};var C=A.getDataConversions=function(t,e,r,n){var i,a="x"===r||"y"===r||"z"===r?r:n;if(Array.isArray(a)){if(i={type:T(n),_categories:[]},A.setConvert(i),"category"===i.type)for(var o=0;o2e-6||((r-t._forceTick0)/t._minDtick%1+1.000001)%1>2e-6)&&(t._minDtick=0)):t._minDtick=0},A.saveRangeInitial=function(t,e){for(var r=A.list(t,"",!0),n=!1,i=0;i.3*h||u(n)||u(a))){var p=r.dtick/2;t+=t+p.8){var o=Number(r.substr(1));a.exactYears>.8&&o%12==0?t=A.tickIncrement(t,"M6","reverse")+1.5*v:a.exactMonths>.8?t=A.tickIncrement(t,"M1","reverse")+15.5*v:t-=v/2;var l=A.tickIncrement(t,r);if(l<=n)return l}return t}(x,t,y,c,a)),g=x,0;g<=u;)g=A.tickIncrement(g,y,!1,a),0;return{start:e.c2r(x,0,a),end:e.c2r(g,0,a),size:y,_dataSpan:u-c}},A.prepTicks=function(t){var e=s.simpleMap(t.range,t.r2l);if("auto"===t.tickmode||!t.dtick){var r,n=t.nticks;n||("category"===t.type?(r=t.tickfont?1.2*(t.tickfont.size||12):15,n=t._length/r):(r="y"===t._id.charAt(0)?40:80,n=s.constrain(t._length/r,4,9)+1),"radialaxis"===t._name&&(n*=2)),"array"===t.tickmode&&(n*=100),A.autoTicks(t,Math.abs(e[1]-e[0])/n),t._minDtick>0&&t.dtick<2*t._minDtick&&(t.dtick=t._minDtick,t.tick0=t.l2r(t._forceTick0))}t.tick0||(t.tick0="date"===t.type?"2000-01-01":0),"date"===t.type&&t.dtick<.1&&(t.dtick=.1),j(t)},A.calcTicks=function(t){A.prepTicks(t);var e=s.simpleMap(t.range,t.r2l);if("array"===t.tickmode)return function(t){var e,r,n=t.tickvals,i=t.ticktext,a=new Array(n.length),o=s.simpleMap(t.range,t.r2l),l=1.0001*o[0]-1e-4*o[1],c=1.0001*o[1]-1e-4*o[0],u=Math.min(l,c),f=Math.max(l,c),h=0;Array.isArray(i)||(i=[]);var p="category"===t.type?t.d2l_noadd:t.d2l;"log"===t.type&&"L"!==String(t.dtick).charAt(0)&&(t.dtick="L"+Math.pow(10,Math.floor(Math.min(t.range[0],t.range[1]))-1));for(r=0;ru&&e=n:c<=n)&&!(a.length>l||c===o);c=A.tickIncrement(c,t.dtick,i,t.calendar))o=c,a.push(c);$(t)&&360===Math.abs(e[1]-e[0])&&a.pop(),t._tmax=a[a.length-1],t._prevDateHead="",t._inCalcTicks=!0;for(var u=new Array(a.length),f=0;f10||"01-01"!==n.substr(5)?t._tickround="d":t._tickround=+e.substr(1)%12==0?"y":"m";else if(e>=v&&a<=10||e>=15*v)t._tickround="d";else if(e>=x&&a<=16||e>=y)t._tickround="M";else if(e>=b&&a<=19||e>=x)t._tickround="S";else{var o=t.l2r(r+e).replace(/^-/,"").length;t._tickround=Math.max(a,o)-20,t._tickround<0&&(t._tickround=4)}}else if(i(e)||"L"===e.charAt(0)){var s=t.range.map(t.r2d||Number);i(e)||(e=Number(e.substr(1))),t._tickround=2-Math.floor(Math.log(e)/Math.LN10+.01);var l=Math.max(Math.abs(s[0]),Math.abs(s[1])),c=Math.floor(Math.log(l)/Math.LN10+.01);Math.abs(c)>3&&(q(t.exponentformat)&&!H(c)?t._tickexponent=3*Math.round((c-1)/3):t._tickexponent=c)}else t._tickround=null}function V(t,e,r){var n=t.tickfont||{};return{x:e,dx:0,dy:0,text:r||"",fontSize:n.size,font:n.family,fontColor:n.color}}A.autoTicks=function(t,e){var r;function n(t){return Math.pow(t,Math.floor(Math.log(e)/Math.LN10))}if("date"===t.type){t.tick0=s.dateTick0(t.calendar);var a=2*e;a>m?(e/=m,r=n(10),t.dtick="M"+12*N(e,r,O)):a>g?(e/=g,t.dtick="M"+N(e,1,I)):a>v?(t.dtick=N(e,v,D),t.tick0=s.dateTick0(t.calendar,!0)):a>y?t.dtick=N(e,y,I):a>x?t.dtick=N(e,x,P):a>b?t.dtick=N(e,b,P):(r=n(10),t.dtick=N(e,r,O))}else if("log"===t.type){t.tick0=0;var o=s.simpleMap(t.range,t.r2l);if(e>.7)t.dtick=Math.ceil(e);else if(Math.abs(o[1]-o[0])<1){var l=1.5*Math.abs((o[1]-o[0])/e);e=Math.abs(Math.pow(10,o[1])-Math.pow(10,o[0]))/l,r=n(10),t.dtick="L"+N(e,r,O)}else t.dtick=e>.3?"D2":"D1"}else"category"===t.type?(t.tick0=0,t.dtick=Math.ceil(Math.max(e,1))):$(t)?(t.tick0=0,r=1,t.dtick=N(e,r,F)):(t.tick0=0,r=n(10),t.dtick=N(e,r,O));if(0===t.dtick&&(t.dtick=1),!i(t.dtick)&&"string"!=typeof t.dtick){var c=t.dtick;throw t.dtick=1,"ax.dtick error: "+String(c)}},A.tickIncrement=function(t,e,r,a){var o=r?-1:1;if(i(e))return t+o*e;var l=e.charAt(0),c=o*Number(e.substr(1));if("M"===l)return s.incrementMonth(t,c,a);if("L"===l)return Math.log(Math.pow(10,t)+c)/Math.LN10;if("D"===l){var u="D2"===e?B:R,f=t+.01*o,h=s.roundUp(s.mod(f,1),u,r);return Math.floor(f)+Math.log(n.round(Math.pow(10,h),1))/Math.LN10}throw"unrecognized dtick "+String(e)},A.tickFirst=function(t){var e=t.r2l||Number,r=s.simpleMap(t.range,e),a=r[1]"+l,t._prevDateHead=l));e.text=c}(t,o,r,c):"log"===t.type?function(t,e,r,n,a){var o=t.dtick,l=e.x,c=t.tickformat,u="string"==typeof o&&o.charAt(0);"never"===a&&(a="");n&&"L"!==u&&(o="L3",u="L");if(c||"L"===u)e.text=G(Math.pow(10,l),t,a,n);else if(i(o)||"D"===u&&s.mod(l+.01,1)<.1){var f=Math.round(l),h=Math.abs(f),p=t.exponentformat;"power"===p||q(p)&&H(f)?(e.text=0===f?1:1===f?"10":"10"+(f>1?"":_)+h+"",e.fontSize*=1.25):("e"===p||"E"===p)&&h>2?e.text="1"+p+(f>0?"+":_)+h:(e.text=G(Math.pow(10,l),t,"","fakehover"),"D1"===o&&"y"===t._id.charAt(0)&&(e.dy-=e.fontSize/6))}else{if("D"!==u)throw"unrecognized dtick "+String(o);e.text=String(Math.round(Math.pow(10,s.mod(l,1)))),e.fontSize*=.75}if("D1"===t.dtick){var d=String(e.text).charAt(0);"0"!==d&&"1"!==d||("y"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(l<0?.5:.25)))}}(t,o,0,c,n):"category"===t.type?function(t,e){var r=t._categories[Math.round(e.x)];void 0===r&&(r="");e.text=String(r)}(t,o):$(t)?function(t,e,r,n,i){if("radians"!==t.thetaunit||r)e.text=G(e.x,t,i,n);else{var a=e.x/180;if(0===a)e.text="0";else{var o=function(t){function e(t,e){return Math.abs(t-e)<=1e-6}var r=function(t){var r=1;for(;!e(Math.round(t*r)/r,t);)r*=10;return r}(t),n=t*r,i=Math.abs(function t(r,n){return e(n,0)?r:t(n,r%n)}(n,r));return[Math.round(n/i),Math.round(r/i)]}(a);if(o[1]>=100)e.text=G(s.deg2rad(e.x),t,i,n);else{var l=e.x<0;1===o[1]?1===o[0]?e.text="\u03c0":e.text=o[0]+"\u03c0":e.text=["",o[0],"","\u2044","",o[1],"","\u03c0"].join(""),l&&(e.text=_+e.text)}}}}(t,o,r,c,n):function(t,e,r,n,i){"never"===i?i="":"all"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(i="hide");e.text=G(e.x,t,i,n)}(t,o,0,c,n),t.tickprefix&&!p(t.showtickprefix)&&(o.text=t.tickprefix+o.text),t.ticksuffix&&!p(t.showticksuffix)&&(o.text+=t.ticksuffix),o},A.hoverLabelText=function(t,e,r){if(r!==w&&r!==e)return A.hoverLabelText(t,e)+" - "+A.hoverLabelText(t,r);var n="log"===t.type&&e<=0,i=A.tickText(t,t.c2l(n?-e:e),"hover").text;return n?0===e?"0":_+i:i};var U=["f","p","n","\u03bc","m","","k","M","G","T"];function q(t){return"SI"===t||"B"===t}function H(t){return t>14||t<-15}function G(t,e,r,n){var a=t<0,o=e._tickround,l=r||e.exponentformat||"B",c=e._tickexponent,u=A.getTickFormat(e),f=e.separatethousands;if(n){var h={exponentformat:l,dtick:"none"===e.showexponent?e.dtick:i(t)&&Math.abs(t)||1,range:"none"===e.showexponent?e.range.map(e.r2d):[0,t||1]};j(h),o=(Number(h._tickround)||0)+4,c=h._tickexponent,e.hoverformat&&(u=e.hoverformat)}if(u)return e._numFormat(u)(t).replace(/-/g,_);var p,d=Math.pow(10,-o)/2;if("none"===l&&(c=0),(t=Math.abs(t))"+p+"":"B"===l&&9===c?t+="B":q(l)&&(t+=U[c/3+5]));return a?_+t:t}function W(t,e){var r=t.l2p(e);return r>1&&r=0,a=u(t,e[1])<=0;return(r||i)&&(n||a)}if(t.tickformatstops&&t.tickformatstops.length>0)switch(t.type){case"date":case"linear":for(e=0;e=o(i)))){r=n;break}break;case"log":for(e=0;e1)for(n=1;n2*o}(t,e)?"date":function(t){for(var e=Math.max(1,(t.length-1)/1e3),r=0,n=0,o={},s=0;s2*r}(t)?"category":function(t){if(!t)return!1;for(var e=0;en?1:-1:+(t.substr(1)||1)-+(e.substr(1)||1)}},{"../../registry":827,"./constants":750}],748:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){if("category"===e.type){var i,a=t.categoryarray,o=Array.isArray(a)&&a.length>0;o&&(i="array");var s,l=r("categoryorder",i);"array"===l&&(s=r("categoryarray")),o||"array"!==l||(l=e.categoryorder="trace"),"trace"===l?e._initialCategories=[]:"array"===l?e._initialCategories=s.slice():(s=function(t,e){var r,n,i,a=e.dataAttr||t._id.charAt(0),o={};if(e.axData)r=e.axData;else for(r=[],n=0;ns*x)||k)for(r=0;rI&&Rz&&(z=R);p/=(z-L)/(2*O),L=u.l2r(L),z=u.l2r(z),u.range=u._input.range=S=0?Math.min(t,.9):1/(1/Math.max(t,-.3)+3.222))}function P(t,e,r,n,i){return t.append("path").attr("class","zoombox").style({fill:e>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("transform","translate("+r+", "+n+")").attr("d",i+"Z")}function D(t,e,r){return t.append("path").attr("class","zoombox-corners").style({fill:c.background,stroke:c.defaultLine,"stroke-width":1,opacity:0}).attr("transform","translate("+e+", "+r+")").attr("d","M0,0Z")}function R(t,e,r,n,i,a){t.attr("d",n+"M"+r.l+","+r.t+"v"+r.h+"h"+r.w+"v-"+r.h+"h-"+r.w+"Z"),B(t,e,i,a)}function B(t,e,r,n){r||(t.transition().style("fill",n>.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),e.transition().style("opacity",1).duration(200))}function F(t){n.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function N(t){S&&t.data&&t._context.showTips&&(s.notifier(s._(t,"Double-click to zoom back out"),"long"),S=!1)}function j(t){return"lasso"===t||"select"===t}function V(t){var e=Math.floor(Math.min(t.b-t.t,t.r-t.l,T)/2);return"M"+(t.l-3.5)+","+(t.t-.5+e)+"h3v"+-e+"h"+e+"v-3h-"+(e+3)+"ZM"+(t.r+3.5)+","+(t.t-.5+e)+"h-3v"+-e+"h"+-e+"v-3h"+(e+3)+"ZM"+(t.r+3.5)+","+(t.b+.5-e)+"h-3v"+e+"h"+-e+"v3h"+(e+3)+"ZM"+(t.l-3.5)+","+(t.b+.5-e)+"h3v"+e+"h"+e+"v3h-"+(e+3)+"Z"}function U(t,e){if(a){var r=void 0!==t.onwheel?"wheel":"mousewheel";t._onwheel&&t.removeEventListener(r,t._onwheel),t._onwheel=e,t.addEventListener(r,e,{passive:!1})}else void 0!==t.onwheel?t.onwheel=e:void 0!==t.onmousewheel&&(t.onmousewheel=e)}function q(t){var e=[];for(var r in t)e.push(t[r]);return e}e.exports={makeDragBox:function(t,e,r,a,c,h,S,E){var B,H,G,W,Y,X,Z,$,J,K,Q,tt,et,rt,nt,it,at,ot,st,lt,ct,ut=t._fullLayout._zoomlayer,ft=S+E==="nsew",ht=1===(S+E).length;function pt(){if(B=e.xaxis,H=e.yaxis,J=B._length,K=H._length,Z=B._offset,$=H._offset,(G={})[B._id]=B,(W={})[H._id]=H,S&&E)for(var r=e.overlays,n=0;n-1&&w(i,t,Y,X,e.id,Tt),a.indexOf("event")>-1&&f.click(t,i,e.id);else if(1===r&&ht){var s=S?H:B,c="s"===S||"w"===E?0:1,u=s._name+".range["+c+"]",h=function(t,e){var r,i=t.range[e],a=Math.abs(i-t.range[1-e]);return"date"===t.type?i:"log"===t.type?(r=Math.ceil(Math.max(0,-Math.log(a)/Math.LN10))+3,n.format("."+r+"g")(Math.pow(10,i))):(r=Math.floor(Math.log(Math.abs(i))/Math.LN10)-Math.floor(Math.log(a)/Math.LN10)+4,n.format("."+String(r)+"g")(i))}(s,c),p="left",d="middle";if(s.fixedrange)return;S?(d="n"===S?"top":"bottom","right"===s.side&&(p="right")):"e"===E&&(p="right"),t._context.showAxisRangeEntryBoxes&&n.select(mt).call(l.makeEditable,{gd:t,immediate:!0,background:t._fullLayout.paper_bgcolor,text:String(h),fill:s.tickfont?s.tickfont.color:"#444",horizontalAlign:p,verticalAlign:d}).on("edit",function(e){var r=s.d2r(e);void 0!==r&&o.call("_guiRelayout",t,u,r)})}}function Ct(e,r){if(t._transitioningWithDuration)return!1;var n=Math.max(0,Math.min(J,e+gt)),i=Math.max(0,Math.min(K,r+vt)),a=Math.abs(n-gt),o=Math.abs(i-vt);function s(){wt="",yt.r=yt.l,yt.t=yt.b,Mt.attr("d","M0,0Z")}yt.l=Math.min(gt,n),yt.r=Math.max(gt,n),yt.t=Math.min(vt,i),yt.b=Math.max(vt,i),nt?a>T||o>T?(wt="xy",a/J>o/K?(o=a*K/J,vt>i?yt.t=vt-o:yt.b=vt+o):(a=o*J/K,gt>n?yt.l=gt-a:yt.r=gt+a),Mt.attr("d",V(yt))):s():!et||o10||r.scrollWidth-r.clientWidth>10)){clearTimeout(Pt);var n=-e.deltaY;if(isFinite(n)||(n=e.wheelDelta/10),isFinite(n)){var i,a=Math.exp(-Math.min(Math.max(n,-20),20)/200),o=Rt.draglayer.select(".nsewdrag").node().getBoundingClientRect(),l=(e.clientX-o.left)/o.width,c=(o.bottom-e.clientY)/o.height;if(it){for(E||(l=.5),i=0;im[1]-.01&&(e.domain=s),i.noneOrAll(t.domain,e.domain,s)}return r("layer"),e}},{"../../lib":696,"fast-isnumeric":214}],761:[function(t,e,r){"use strict";var n=t("../../constants/alignment").FROM_BL;e.exports=function(t,e,r){void 0===r&&(r=n[t.constraintoward||"center"]);var i=[t.r2l(t.range[0]),t.r2l(t.range[1])],a=i[0]+(i[1]-i[0])*r;t.range=t._input.range=[t.l2r(a+(i[0]-a)*e),t.l2r(a+(i[1]-a)*e)]}},{"../../constants/alignment":668}],762:[function(t,e,r){"use strict";var n=t("polybooljs"),i=t("../../registry"),a=t("../../components/color"),o=t("../../components/fx"),s=t("../../lib/polygon"),l=t("../../lib/throttle"),c=t("../../components/fx/helpers").makeEventData,u=t("./axis_ids").getFromId,f=t("../../lib/clear_gl_canvases"),h=t("../../plot_api/subroutines").redrawReglTraces,p=t("./constants"),d=p.MINSELECT,m=s.filter,g=s.tester;function v(t){return t._id}function y(t,e,r,n,i,a,o){var s,l,c,u,f,h,p,d,m,g=e._hoverdata,v=e._fullLayout.clickmode.indexOf("event")>-1,y=[];if(function(t){return t&&Array.isArray(t)&&!0!==t[0].hoverOnBox}(g)){w(t,e,a);var x=function(t,e){var r,n,i=t[0],a=-1,o=[];for(n=0;n0?function(t,e){var r,n,i,a=[];for(i=0;i0&&a.push(r);if(1===a.length&&a[0]===e.searchInfo&&(n=e.searchInfo.cd[0].trace).selectedpoints.length===e.pointNumbers.length){for(i=0;i1)return!1;if((i+=r.selectedpoints.length)>1)return!1}return 1===i}(s)&&(h=T(x))){for(o&&o.remove(),m=0;m0?"M"+i.join("M")+"Z":"M0,0Z",e.attr("d",n)}function T(t){var e=t.searchInfo.cd[0].trace,r=t.pointNumber,n=t.pointNumbers,i=n.length>0?n[0]:r;return!!e.selectedpoints&&e.selectedpoints.indexOf(i)>-1}function S(t,e,r){var n,a,o,s;for(n=0;n-1&&y(e,T,i.xaxes,i.yaxes,i.subplot,i,H),"event"===r&&T.emit("plotly_selected",void 0);o.click(T,e)})},i.doneFn=function(){W.remove(),l.done(Y).then(function(){l.clear(Y),i.gd.emit("plotly_selected",b),h&&i.selectionDefs&&(h.subtract=q,i.selectionDefs.push(h),i.mergedPolygons.length=0,[].push.apply(i.mergedPolygons,f))})}},clearSelect:C,selectOnClick:y}},{"../../components/color":570,"../../components/fx":612,"../../components/fx/helpers":609,"../../lib/clear_gl_canvases":680,"../../lib/polygon":708,"../../lib/throttle":721,"../../plot_api/subroutines":735,"../../registry":827,"./axis_ids":747,"./constants":750,polybooljs:456}],763:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("fast-isnumeric"),a=t("../../lib"),o=a.cleanNumber,s=a.ms2DateTime,l=a.dateTime2ms,c=a.ensureNumber,u=t("../../constants/numerical"),f=u.FP_SAFE,h=u.BADNUM,p=u.LOG_CLIP,d=t("./constants"),m=t("./axis_ids");function g(t){return Math.pow(10,t)}e.exports=function(t,e){e=e||{};var r=(t._id||"x").charAt(0);function u(e,r){if(e>0)return Math.log(e)/Math.LN10;if(e<=0&&r&&t.range&&2===t.range.length){var n=t.range[0],i=t.range[1];return.5*(n+i-2*p*Math.abs(n-i))}return h}function v(e,r,n){var o=l(e,n||t.calendar);if(o===h){if(!i(e))return h;e=+e;var s=Math.floor(10*a.mod(e+.05,1)),c=Math.round(e-s/10);o=l(new Date(c))+s/10}return o}function y(e,r,n){return s(e,r,n||t.calendar)}function x(e){return t._categories[Math.round(e)]}function b(e){if(t._categoriesMap){var r=t._categoriesMap[e];if(void 0!==r)return r}if(i(e))return+e}function _(e){return i(e)?n.round(t._b+t._m*e,2):h}function w(e){return(e-t._b)/t._m}t.c2l="log"===t.type?u:c,t.l2c="log"===t.type?g:c,t.l2p=_,t.p2l=w,t.c2p="log"===t.type?function(t,e){return _(u(t,e))}:_,t.p2c="log"===t.type?function(t){return g(w(t))}:w,-1!==["linear","-"].indexOf(t.type)?(t.d2r=t.r2d=t.d2c=t.r2c=t.d2l=t.r2l=o,t.c2d=t.c2r=t.l2d=t.l2r=c,t.d2p=t.r2p=function(e){return t.l2p(o(e))},t.p2d=t.p2r=w,t.cleanPos=c):"log"===t.type?(t.d2r=t.d2l=function(t,e){return u(o(t),e)},t.r2d=t.r2c=function(t){return g(o(t))},t.d2c=t.r2l=o,t.c2d=t.l2r=c,t.c2r=u,t.l2d=g,t.d2p=function(e,r){return t.l2p(t.d2r(e,r))},t.p2d=function(t){return g(w(t))},t.r2p=function(e){return t.l2p(o(e))},t.p2r=w,t.cleanPos=c):"date"===t.type?(t.d2r=t.r2d=a.identity,t.d2c=t.r2c=t.d2l=t.r2l=v,t.c2d=t.c2r=t.l2d=t.l2r=y,t.d2p=t.r2p=function(e,r,n){return t.l2p(v(e,0,n))},t.p2d=t.p2r=function(t,e,r){return y(w(t),e,r)},t.cleanPos=function(e){return a.cleanDate(e,h,t.calendar)}):"category"===t.type&&(t.d2c=t.d2l=function(e){if(null!=e){if(void 0===t._categoriesMap&&(t._categoriesMap={}),void 0!==t._categoriesMap[e])return t._categoriesMap[e];t._categories.push(e);var r=t._categories.length-1;return t._categoriesMap[e]=r,r}return h},t.r2d=t.c2d=t.l2d=x,t.d2r=t.d2l_noadd=b,t.r2c=function(e){var r=b(e);return void 0!==r?r:t.fraction2r(.5)},t.l2r=t.c2r=c,t.r2l=b,t.d2p=function(e){return t.l2p(t.r2c(e))},t.p2d=function(t){return x(w(t))},t.r2p=t.d2p,t.p2r=w,t.cleanPos=function(t){return"string"==typeof t&&""!==t?t:c(t)}),t.fraction2r=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return t.l2r(r+e*(n-r))},t.r2fraction=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return(t.r2l(e)-r)/(n-r)},t.cleanRange=function(e,n){n||(n={}),e||(e="range");var o,s,l=a.nestedProperty(t,e).get();if(s=(s="date"===t.type?a.dfltRange(t.calendar):"y"===r?d.DFLTRANGEY:n.dfltRange||d.DFLTRANGEX).slice(),l&&2===l.length)for("date"===t.type&&(l[0]=a.cleanDate(l[0],h,t.calendar),l[1]=a.cleanDate(l[1],h,t.calendar)),o=0;o<2;o++)if("date"===t.type){if(!a.isDateTime(l[o],t.calendar)){t[e]=s;break}if(t.r2l(l[0])===t.r2l(l[1])){var c=a.constrain(t.r2l(l[0]),a.MIN_MS+1e3,a.MAX_MS-1e3);l[0]=t.l2r(c-1e3),l[1]=t.l2r(c+1e3);break}}else{if(!i(l[o])){if(!i(l[1-o])){t[e]=s;break}l[o]=l[1-o]*(o?10:.1)}if(l[o]<-f?l[o]=-f:l[o]>f&&(l[o]=f),l[0]===l[1]){var u=Math.max(1,Math.abs(1e-6*l[0]));l[0]-=u,l[1]+=u}}else a.nestedProperty(t,e).set(s)},t.setScale=function(n){var i=e._size;if(t._categories||(t._categories=[]),t._categoriesMap||(t._categoriesMap={}),t.overlaying){var a=m.getFromId({_fullLayout:e},t.overlaying);t.domain=a.domain}var o=n&&t._r?"_r":"range",s=t.calendar;t.cleanRange(o);var l=t.r2l(t[o][0],s),c=t.r2l(t[o][1],s);if("y"===r?(t._offset=i.t+(1-t.domain[1])*i.h,t._length=i.h*(t.domain[1]-t.domain[0]),t._m=t._length/(l-c),t._b=-t._m*c):(t._offset=i.l+t.domain[0]*i.w,t._length=i.w*(t.domain[1]-t.domain[0]),t._m=t._length/(c-l),t._b=-t._m*l),!isFinite(t._m)||!isFinite(t._b))throw e._replotting=!1,new Error("Something went wrong with axis scaling")},t.makeCalcdata=function(e,r){var n,i,o,s,l=t.type,c="date"===l&&e[r+"calendar"];if(r in e){if(n=e[r],s=e._length||n.length,a.isTypedArray(n)&&("linear"===l||"log"===l)){if(s===n.length)return n;if(n.subarray)return n.subarray(0,s)}for(i=new Array(s),o=0;o rect").call(a.setTranslate,0,0).call(a.setScale,1,1),t.plot.call(a.setTranslate,e._offset,r._offset).call(a.setScale,1,1);var n=t.plot.selectAll(".scatterlayer .trace");n.selectAll(".point").call(a.setPointGroupScale,1,1),n.selectAll(".textpoint").call(a.setTextPointsScale,1,1),n.call(a.hideOutsideRangePoints,t)}function x(e,r){var n,s,l,c=m[e.xaxis._id],u=m[e.yaxis._id],f=[];if(c){s=(n=t._fullLayout[c.axisName])._r,l=c.to,f[0]=(s[0]*(1-r)+r*l[0]-s[0])/(s[1]-s[0])*e.xaxis._length;var h=s[1]-s[0],d=l[1]-l[0];n.range[0]=s[0]*(1-r)+r*l[0],n.range[1]=s[1]*(1-r)+r*l[1],f[2]=e.xaxis._length*(1-r+r*d/h)}else f[0]=0,f[2]=e.xaxis._length;if(u){s=(n=t._fullLayout[u.axisName])._r,l=u.to,f[1]=(s[1]*(1-r)+r*l[1]-s[1])/(s[0]-s[1])*e.yaxis._length;var g=s[1]-s[0],v=l[1]-l[0];n.range[0]=s[0]*(1-r)+r*l[0],n.range[1]=s[1]*(1-r)+r*l[1],f[3]=e.yaxis._length*(1-r+r*v/g)}else f[1]=0,f[3]=e.yaxis._length;!function(e,r){var n,a=[];for(a=[e._id,r._id],n=0;nr.duration?(function(){for(var e={},r=0;r rect").call(a.setTranslate,0,0).call(a.setScale,1,1),t.plot.call(a.setTranslate,e._offset,r._offset).call(a.setScale,1,1);var n=t.plot.selectAll(".scatterlayer .trace");n.selectAll(".point").call(a.setPointGroupScale,1,1),n.selectAll(".textpoint").call(a.setTextPointsScale,1,1),n.call(a.hideOutsideRangePoints,t)}function d(e,r){var n=e.plotinfo,s=n.xaxis,l=n.yaxis,c=e.xr0,u=e.xr1,f=s._length,p=e.yr0,d=e.yr1,m=l._length,g=c[0]!==u[0]||c[1]!==u[1],v=p[0]!==d[0]||p[1]!==d[1],y=[];if(g){var x=c[1]-c[0],b=u[1]-u[0];y[0]=(c[0]*(1-r)+r*u[0]-c[0])/(c[1]-c[0])*f,y[2]=f*(1-r+r*b/x),s.range[0]=c[0]*(1-r)+r*u[0],s.range[1]=c[1]*(1-r)+r*u[1]}else y[0]=0,y[2]=f;if(v){var _=p[1]-p[0],w=d[1]-d[0];y[1]=(p[1]*(1-r)+r*d[1]-p[1])/(p[0]-p[1])*m,y[3]=m*(1-r+r*w/_),l.range[0]=p[0]*(1-r)+r*d[0],l.range[1]=p[1]*(1-r)+r*d[1]}else y[1]=0,y[3]=m;!function(e,r){var n,a=[e._id,r._id];for(n=0;nr.duration?(m(),f=window.cancelAnimationFrame(t)):f=window.requestAnimationFrame(t)}),Promise.resolve()}}},{"../../components/drawing":595,"../../registry":827,"./axes":744,"./constants":750,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],768:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("./axis_autotype");function a(t){return{v:"x",h:"y"}[t.orientation||"v"]}function o(t,e){var r=a(t),i=n.traceIs(t,"box-violin"),o=n.traceIs(t._fullInput||{},"candlestick");return i&&!o&&e===r&&void 0===t[r]&&void 0===t[r+"0"]}e.exports=function(t,e,r,s){"-"===r("type",(s.splomStash||{}).type)&&(!function(t,e){if("-"!==t.type)return;var r=t._id,s=r.charAt(0);-1!==r.indexOf("scene")&&(r=s);var l=function(t,e,r){for(var n=0;n0&&(i["_"+r+"axes"]||{})[e])return i;if((i[r+"axis"]||r)===e){if(o(i,r))return i;if((i[r]||[]).length||i[r+"0"])return i}}}(e,r,s);if(!l)return;if("histogram"===l.type&&s==={v:"y",h:"x"}[l.orientation||"v"])return void(t.type="linear");var c,u=s+"calendar",f=l[u];if(o(l,s)){var h=a(l),p=[];for(c=0;c0?".":"")+a;i.isPlainObject(o)?l(o,e,s,n+1):e(s,a,o)}})}r.manageCommandObserver=function(t,e,n,o){var s={},l=!0;e&&e._commandObserver&&(s=e._commandObserver),s.cache||(s.cache={}),s.lookupTable={};var c=r.hasSimpleAPICommandBindings(t,n,s.lookupTable);if(e&&e._commandObserver){if(c)return s;if(e._commandObserver.remove)return e._commandObserver.remove(),e._commandObserver=null,s}if(c){a(t,c,s.cache),s.check=function(){if(l){var e=a(t,c,s.cache);return e.changed&&o&&void 0!==s.lookupTable[e.value]&&(s.disable(),Promise.resolve(o({value:e.value,type:c.type,prop:c.prop,traces:c.traces,index:s.lookupTable[e.value]})).then(s.enable,s.enable)),e.changed}};for(var u=["plotly_relayout","plotly_redraw","plotly_restyle","plotly_update","plotly_animatingframe","plotly_afterplot"],f=0;fi*Math.PI/180}return!1},r.getPath=function(){return n.geo.path().projection(r)},r.getBounds=function(t){return r.getPath().bounds(t)},r.fitExtent=function(t,e){var n=t[1][0]-t[0][0],i=t[1][1]-t[0][1],a=r.clipExtent&&r.clipExtent();r.scale(150).translate([0,0]),a&&r.clipExtent(null);var o=r.getBounds(e),s=Math.min(n/(o[1][0]-o[0][0]),i/(o[1][1]-o[0][1])),l=+t[0][0]+(n-s*(o[1][0]+o[0][0]))/2,c=+t[0][1]+(i-s*(o[1][1]+o[0][1]))/2;return a&&r.clipExtent(a),r.scale(150*s).translate([l,c])},r.precision(m.precision),i&&r.clipAngle(i-m.clipPad);return r}(e);u.center([c.lon-l.lon,c.lat-l.lat]).rotate([-l.lon,-l.lat,l.roll]).parallels(s.parallels);var f=[[r.l+r.w*o.x[0],r.t+r.h*(1-o.y[1])],[r.l+r.w*o.x[1],r.t+r.h*(1-o.y[0])]],h=e.lonaxis,p=e.lataxis,d=function(t,e){var r=m.clipPad,n=t[0]+r,i=t[1]-r,a=e[0]+r,o=e[1]-r;n>0&&i<0&&(i+=360);var s=(i-n)/4;return{type:"Polygon",coordinates:[[[n,a],[n,o],[n+s,o],[n+2*s,o],[n+3*s,o],[i,o],[i,a],[i-s,a],[i-2*s,a],[i-3*s,a],[n,a]]]}}(h.range,p.range);u.fitExtent(f,d);var g=this.bounds=u.getBounds(d),v=this.fitScale=u.scale(),y=u.translate();if(!isFinite(g[0][0])||!isFinite(g[0][1])||!isFinite(g[1][0])||!isFinite(g[1][1])||isNaN(y[0])||isNaN(y[0])){for(var x=this.graphDiv,b=["projection.rotation","center","lonaxis.range","lataxis.range"],_="Invalid geo settings, relayout'ing to default view.",w={},k=0;k-1&&p(n.event,a,[r.xaxis],[r.yaxis],r.id,m),c.indexOf("event")>-1&&l.click(a,n.event))})}function g(t){return r.projection.invert([t[0]+r.xaxis._offset,t[1]+r.yaxis._offset])}},x.makeFramework=function(){var t=this,e=t.graphDiv._fullLayout,r="clip"+e._uid+t.id;t.clipDef=e._clips.append("clipPath").attr("id",r),t.clipRect=t.clipDef.append("rect"),t.framework=n.select(t.container).append("g").attr("class","geo "+t.id).call(s.setClipUrl,r),t.project=function(e){var r=t.projection(e);return r?[r[0]-t.xaxis._offset,r[1]-t.yaxis._offset]:[null,null]},t.xaxis={_id:"x",c2p:function(e){return t.project(e)[0]}},t.yaxis={_id:"y",c2p:function(e){return t.project(e)[1]}},t.mockAxis={type:"linear",showexponent:"all",exponentformat:"B"},u.setConvert(t.mockAxis,e)},x.saveViewInitial=function(t){var e=t.center||{},r=t.projection,n=r.rotation||{};t._isScoped?this.viewInitial={"center.lon":e.lon,"center.lat":e.lat,"projection.scale":r.scale}:t._isClipped?this.viewInitial={"projection.scale":r.scale,"projection.rotation.lon":n.lon,"projection.rotation.lat":n.lat}:this.viewInitial={"center.lon":e.lon,"center.lat":e.lat,"projection.scale":r.scale,"projection.rotation.lon":n.lon}},x.render=function(){var t,e=this.projection,r=e.getPath();function n(t){var r=e(t.lonlat);return r?"translate("+r[0]+","+r[1]+")":null}function i(t){return e.isLonLatOverEdges(t.lonlat)?"none":null}for(t in this.basePaths)this.basePaths[t].attr("d",r);for(t in this.dataPaths)this.dataPaths[t].attr("d",function(t){return r(t.geojson)});for(t in this.dataPoints)this.dataPoints[t].attr("display",i).attr("transform",n)}},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/topojson_utils":723,"../../registry":827,"../cartesian/axes":744,"../cartesian/select":762,"../plots":808,"./constants":773,"./projections":779,"./zoom":780,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"topojson-client":517}],775:[function(t,e,r){"use strict";var n=t("./geo"),i=t("../../plots/get_data").getSubplotCalcData,a=t("../../lib").counterRegex,o="geo";r.name=o,r.attr=o,r.idRoot=o,r.idRegex=r.attrRegex=a(o),r.attributes=t("./layout/attributes"),r.layoutAttributes=t("./layout/layout_attributes"),r.supplyLayoutDefaults=t("./layout/defaults"),r.plot=function(t){var e=t._fullLayout,r=t.calcdata,a=e._subplots.geo;void 0===window.PlotlyGeoAssets&&(window.PlotlyGeoAssets={topojson:{}});for(var s=0;s0&&k<0&&(k+=360);var M,A,T,S=(w+k)/2;if(!c){var E=u?s.projRotate:[S,0,0];M=r("projection.rotation.lon",E[0]),r("projection.rotation.lat",E[1]),r("projection.rotation.roll",E[2]),r("showcoastlines",!u)&&(r("coastlinecolor"),r("coastlinewidth")),r("showocean")&&r("oceancolor")}(c?(A=-96.6,T=38.7):(A=u?S:M,T=(_[0]+_[1])/2),r("center.lon",A),r("center.lat",T),f)&&r("projection.parallels",s.projParallels||[0,60]);r("projection.scale"),r("showland")&&r("landcolor"),r("showlakes")&&r("lakecolor"),r("showrivers")&&(r("rivercolor"),r("riverwidth")),r("showcountries",u&&"usa"!==a)&&(r("countrycolor"),r("countrywidth")),("usa"===a||"north america"===a&&50===n)&&(r("showsubunits",!0),r("subunitcolor"),r("subunitwidth")),u||r("showframe",!0)&&(r("framecolor"),r("framewidth")),r("bgcolor")}e.exports=function(t,e,r){n(t,e,r,{type:"geo",attributes:a,handleDefaults:s,partition:"y"})}},{"../../subplot_defaults":822,"../constants":773,"./layout_attributes":778}],778:[function(t,e,r){"use strict";var n=t("../../../components/color/attributes"),i=t("../../domain").attributes,a=t("../constants"),o=t("../../../plot_api/edit_types").overrideAll,s={range:{valType:"info_array",items:[{valType:"number"},{valType:"number"}]},showgrid:{valType:"boolean",dflt:!1},tick0:{valType:"number"},dtick:{valType:"number"},gridcolor:{valType:"color",dflt:n.lightLine},gridwidth:{valType:"number",min:0,dflt:1}};(e.exports=o({domain:i({name:"geo"},{}),resolution:{valType:"enumerated",values:[110,50],dflt:110,coerceNumber:!0},scope:{valType:"enumerated",values:Object.keys(a.scopeDefaults),dflt:"world"},projection:{type:{valType:"enumerated",values:Object.keys(a.projNames)},rotation:{lon:{valType:"number"},lat:{valType:"number"},roll:{valType:"number"}},parallels:{valType:"info_array",items:[{valType:"number"},{valType:"number"}]},scale:{valType:"number",min:0,dflt:1}},center:{lon:{valType:"number"},lat:{valType:"number"}},showcoastlines:{valType:"boolean"},coastlinecolor:{valType:"color",dflt:n.defaultLine},coastlinewidth:{valType:"number",min:0,dflt:1},showland:{valType:"boolean",dflt:!1},landcolor:{valType:"color",dflt:a.landColor},showocean:{valType:"boolean",dflt:!1},oceancolor:{valType:"color",dflt:a.waterColor},showlakes:{valType:"boolean",dflt:!1},lakecolor:{valType:"color",dflt:a.waterColor},showrivers:{valType:"boolean",dflt:!1},rivercolor:{valType:"color",dflt:a.waterColor},riverwidth:{valType:"number",min:0,dflt:1},showcountries:{valType:"boolean"},countrycolor:{valType:"color",dflt:n.defaultLine},countrywidth:{valType:"number",min:0,dflt:1},showsubunits:{valType:"boolean"},subunitcolor:{valType:"color",dflt:n.defaultLine},subunitwidth:{valType:"number",min:0,dflt:1},showframe:{valType:"boolean"},framecolor:{valType:"color",dflt:n.defaultLine},framewidth:{valType:"number",min:0,dflt:1},bgcolor:{valType:"color",dflt:n.background},lonaxis:s,lataxis:s},"plot","from-root")).uirevision={valType:"any",editType:"none"}},{"../../../components/color/attributes":569,"../../../plot_api/edit_types":727,"../../domain":770,"../constants":773}],779:[function(t,e,r){"use strict";e.exports=function(t){function e(t,e){return{type:"Feature",id:t.id,properties:t.properties,geometry:r(t.geometry,e)}}function r(e,n){if(!e)return null;if("GeometryCollection"===e.type)return{type:"GeometryCollection",geometries:object.geometries.map(function(t){return r(t,n)})};if(!c.hasOwnProperty(e.type))return null;var i=c[e.type];return t.geo.stream(e,n(i)),i.result()}t.geo.project=function(t,e){var i=e.stream;if(!i)throw new Error("not yet supported");return(t&&n.hasOwnProperty(t.type)?n[t.type]:r)(t,i)};var n={Feature:e,FeatureCollection:function(t,r){return{type:"FeatureCollection",features:t.features.map(function(t){return e(t,r)})}}},i=[],a=[],o={point:function(t,e){i.push([t,e])},result:function(){var t=i.length?i.length<2?{type:"Point",coordinates:i[0]}:{type:"MultiPoint",coordinates:i}:null;return i=[],t}},s={lineStart:u,point:function(t,e){i.push([t,e])},lineEnd:function(){i.length&&(a.push(i),i=[])},result:function(){var t=a.length?a.length<2?{type:"LineString",coordinates:a[0]}:{type:"MultiLineString",coordinates:a}:null;return a=[],t}},l={polygonStart:u,lineStart:u,point:function(t,e){i.push([t,e])},lineEnd:function(){var t=i.length;if(t){do{i.push(i[0].slice())}while(++t<4);a.push(i),i=[]}},polygonEnd:u,result:function(){if(!a.length)return null;var t=[],e=[];return a.forEach(function(r){!function(t){if((e=t.length)<4)return!1;for(var e,r=0,n=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];++rn^p>n&&r<(h-c)*(n-u)/(p-u)+c&&(i=!i)}return i}(t[0],r))return t.push(e),!0})||t.push([e])}),a=[],t.length?t.length>1?{type:"MultiPolygon",coordinates:t}:{type:"Polygon",coordinates:t[0]}:null}},c={Point:o,MultiPoint:o,LineString:s,MultiLineString:s,Polygon:l,MultiPolygon:l,Sphere:l};function u(){}var f=1e-6,h=f*f,p=Math.PI,d=p/2,m=(Math.sqrt(p),p/180),g=180/p;function v(t){return t>1?d:t<-1?-d:Math.asin(t)}function y(t){return t>1?0:t<-1?p:Math.acos(t)}var x=t.geo.projection,b=t.geo.projectionMutator;function _(t,e){var r=(2+d)*Math.sin(e);e/=2;for(var n=0,i=1/0;n<10&&Math.abs(i)>f;n++){var a=Math.cos(e);e-=i=(e+Math.sin(e)*(a+2)-r)/(2*a*(1+a))}return[2/Math.sqrt(p*(4+p))*t*(1+Math.cos(e)),2*Math.sqrt(p/(4+p))*Math.sin(e)]}t.geo.interrupt=function(e){var r,n=[[[[-p,0],[0,d],[p,0]]],[[[-p,0],[0,-d],[p,0]]]];function i(t,r){for(var i=r<0?-1:1,a=n[+(r<0)],o=0,s=a.length-1;oa[o][2][0];++o);var l=e(t-a[o][1][0],r);return l[0]+=e(a[o][1][0],i*r>i*a[o][0][1]?a[o][0][1]:r)[0],l}e.invert&&(i.invert=function(t,a){for(var o=r[+(a<0)],s=n[+(a<0)],c=0,u=o.length;c=0;--i){var o=n[1][i],l=180*o[0][0]/p,c=180*o[0][1]/p,u=180*o[1][1]/p,f=180*o[2][0]/p,h=180*o[2][1]/p;r.push(s([[f-e,h-e],[f-e,u+e],[l+e,u+e],[l+e,c-e]],30))}return{type:"Polygon",coordinates:[t.merge(r)]}}(),l)},i},a.lobes=function(t){return arguments.length?(n=t.map(function(t){return t.map(function(t){return[[t[0][0]*p/180,t[0][1]*p/180],[t[1][0]*p/180,t[1][1]*p/180],[t[2][0]*p/180,t[2][1]*p/180]]})}),r=n.map(function(t){return t.map(function(t){var r,n=e(t[0][0],t[0][1])[0],i=e(t[2][0],t[2][1])[0],a=e(t[1][0],t[0][1])[1],o=e(t[1][0],t[1][1])[1];return a>o&&(r=a,a=o,o=r),[[n,a],[i,o]]})}),a):n.map(function(t){return t.map(function(t){return[[180*t[0][0]/p,180*t[0][1]/p],[180*t[1][0]/p,180*t[1][1]/p],[180*t[2][0]/p,180*t[2][1]/p]]})})},a},_.invert=function(t,e){var r=.5*e*Math.sqrt((4+p)/p),n=v(r),i=Math.cos(n);return[t/(2/Math.sqrt(p*(4+p))*(1+i)),v((n+r*(i+2))/(2+d))]},(t.geo.eckert4=function(){return x(_)}).raw=_;var w=t.geo.azimuthalEqualArea.raw;function k(t,e){if(arguments.length<2&&(e=t),1===e)return w;if(e===1/0)return M;function r(r,n){var i=w(r/e,n);return i[0]*=t,i}return r.invert=function(r,n){var i=w.invert(r/t,n);return i[0]*=e,i},r}function M(t,e){return[t*Math.cos(e)/Math.cos(e/=2),2*Math.sin(e)]}function A(t,e){return[3*t/(2*p)*Math.sqrt(p*p/3-e*e),e]}function T(t,e){return[t,1.25*Math.log(Math.tan(p/4+.4*e))]}function S(t){return function(e){var r,n=t*Math.sin(e),i=30;do{e-=r=(e+Math.sin(e)-n)/(1+Math.cos(e))}while(Math.abs(r)>f&&--i>0);return e/2}}M.invert=function(t,e){var r=2*v(e/2);return[t*Math.cos(r/2)/Math.cos(r),r]},(t.geo.hammer=function(){var t=2,e=b(k),r=e(t);return r.coefficient=function(r){return arguments.length?e(t=+r):t},r}).raw=k,A.invert=function(t,e){return[2/3*p*t/Math.sqrt(p*p/3-e*e),e]},(t.geo.kavrayskiy7=function(){return x(A)}).raw=A,T.invert=function(t,e){return[t,2.5*Math.atan(Math.exp(.8*e))-.625*p]},(t.geo.miller=function(){return x(T)}).raw=T,S(p);var E=function(t,e,r){var n=S(r);function i(r,i){return[t*r*Math.cos(i=n(i)),e*Math.sin(i)]}return i.invert=function(n,i){var a=v(i/e);return[n/(t*Math.cos(a)),v((2*a+Math.sin(2*a))/r)]},i}(Math.SQRT2/d,Math.SQRT2,p);function C(t,e){var r=e*e,n=r*r;return[t*(.8707-.131979*r+n*(n*(.003971*r-.001529*n)-.013791)),e*(1.007226+r*(.015085+n*(.028874*r-.044475-.005916*n)))]}(t.geo.mollweide=function(){return x(E)}).raw=E,C.invert=function(t,e){var r,n=e,i=25;do{var a=n*n,o=a*a;n-=r=(n*(1.007226+a*(.015085+o*(.028874*a-.044475-.005916*o)))-e)/(1.007226+a*(.045255+o*(.259866*a-.311325-.005916*11*o)))}while(Math.abs(r)>f&&--i>0);return[t/(.8707+(a=n*n)*(a*(a*a*a*(.003971-.001529*a)-.013791)-.131979)),n]},(t.geo.naturalEarth=function(){return x(C)}).raw=C;var L=[[.9986,-.062],[1,0],[.9986,.062],[.9954,.124],[.99,.186],[.9822,.248],[.973,.31],[.96,.372],[.9427,.434],[.9216,.4958],[.8962,.5571],[.8679,.6176],[.835,.6769],[.7986,.7346],[.7597,.7903],[.7186,.8435],[.6732,.8936],[.6213,.9394],[.5722,.9761],[.5322,1]];function z(t,e){var r,n=Math.min(18,36*Math.abs(e)/p),i=Math.floor(n),a=n-i,o=(r=L[i])[0],s=r[1],l=(r=L[++i])[0],c=r[1],u=(r=L[Math.min(19,++i)])[0],f=r[1];return[t*(l+a*(u-o)/2+a*a*(u-2*l+o)/2),(e>0?d:-d)*(c+a*(f-s)/2+a*a*(f-2*c+s)/2)]}function O(t,e){return[t*Math.cos(e),e]}function I(t,e){var r,n=Math.cos(e),i=(r=y(n*Math.cos(t/=2)))?r/Math.sin(r):1;return[2*n*Math.sin(t)*i,Math.sin(e)*i]}function P(t,e){var r=I(t,e);return[(r[0]+t/d)/2,(r[1]+e)/2]}L.forEach(function(t){t[1]*=1.0144}),z.invert=function(t,e){var r=e/d,n=90*r,i=Math.min(18,Math.abs(n/5)),a=Math.max(0,Math.floor(i));do{var o=L[a][1],s=L[a+1][1],l=L[Math.min(19,a+2)][1],c=l-o,u=l-2*s+o,f=2*(Math.abs(r)-s)/c,p=u/c,v=f*(1-p*f*(1-2*p*f));if(v>=0||1===a){n=(e>=0?5:-5)*(v+i);var y,x=50;do{v=(i=Math.min(18,Math.abs(n)/5))-(a=Math.floor(i)),o=L[a][1],s=L[a+1][1],l=L[Math.min(19,a+2)][1],n-=(y=(e>=0?d:-d)*(s+v*(l-o)/2+v*v*(l-2*s+o)/2)-e)*g}while(Math.abs(y)>h&&--x>0);break}}while(--a>=0);var b=L[a][0],_=L[a+1][0],w=L[Math.min(19,a+2)][0];return[t/(_+v*(w-b)/2+v*v*(w-2*_+b)/2),n*m]},(t.geo.robinson=function(){return x(z)}).raw=z,O.invert=function(t,e){return[t/Math.cos(e),e]},(t.geo.sinusoidal=function(){return x(O)}).raw=O,I.invert=function(t,e){if(!(t*t+4*e*e>p*p+f)){var r=t,n=e,i=25;do{var a,o=Math.sin(r),s=Math.sin(r/2),l=Math.cos(r/2),c=Math.sin(n),u=Math.cos(n),h=Math.sin(2*n),d=c*c,m=u*u,g=s*s,v=1-m*l*l,x=v?y(u*l)*Math.sqrt(a=1/v):a=0,b=2*x*u*s-t,_=x*c-e,w=a*(m*g+x*u*l*d),k=a*(.5*o*h-2*x*c*s),M=.25*a*(h*s-x*c*m*o),A=a*(d*l+x*g*u),T=k*M-A*w;if(!T)break;var S=(_*k-b*A)/T,E=(b*M-_*w)/T;r-=S,n-=E}while((Math.abs(S)>f||Math.abs(E)>f)&&--i>0);return[r,n]}},(t.geo.aitoff=function(){return x(I)}).raw=I,P.invert=function(t,e){var r=t,n=e,i=25;do{var a,o=Math.cos(n),s=Math.sin(n),l=Math.sin(2*n),c=s*s,u=o*o,h=Math.sin(r),p=Math.cos(r/2),m=Math.sin(r/2),g=m*m,v=1-u*p*p,x=v?y(o*p)*Math.sqrt(a=1/v):a=0,b=.5*(2*x*o*m+r/d)-t,_=.5*(x*s+n)-e,w=.5*a*(u*g+x*o*p*c)+.5/d,k=a*(h*l/4-x*s*m),M=.125*a*(l*m-x*s*u*h),A=.5*a*(c*p+x*g*o)+.5,T=k*M-A*w,S=(_*k-b*A)/T,E=(b*M-_*w)/T;r-=S,n-=E}while((Math.abs(S)>f||Math.abs(E)>f)&&--i>0);return[r,n]},(t.geo.winkel3=function(){return x(P)}).raw=P}},{}],780:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib"),a=t("../../registry"),o=Math.PI/180,s=180/Math.PI,l={cursor:"pointer"},c={cursor:"auto"};function u(t,e){return n.behavior.zoom().translate(e.translate()).scale(e.scale())}function f(t,e,r){var n=t.id,o=t.graphDiv,s=o.layout,l=s[n],c=o._fullLayout,u=c[n],f={};function h(t,e){var r=i.nestedProperty(u,t);r.get()!==e&&(r.set(e),i.nestedProperty(l,t).set(e),f[n+"."+t]=e)}r(h),h("projection.scale",e.scale()/t.fitScale),a.call("_storeDirectGUIEdit",s,c._preGUI,f),o.emit("plotly_relayout",f)}function h(t,e){var r=u(0,e);function i(r){var n=e.invert(t.midPt);r("center.lon",n[0]),r("center.lat",n[1])}return r.on("zoomstart",function(){n.select(this).style(l)}).on("zoom",function(){e.scale(n.event.scale).translate(n.event.translate),t.render()}).on("zoomend",function(){n.select(this).style(c),f(t,e,i)}),r}function p(t,e){var r,i,a,o,s,h,p,d,m,g=u(0,e),v=2;function y(t){return e.invert(t)}function x(r){var n=e.rotate(),i=e.invert(t.midPt);r("projection.rotation.lon",-n[0]),r("center.lon",i[0]),r("center.lat",i[1])}return g.on("zoomstart",function(){n.select(this).style(l),r=n.mouse(this),i=e.rotate(),a=e.translate(),o=i,s=y(r)}).on("zoom",function(){if(h=n.mouse(this),function(t){var r=y(t);if(!r)return!0;var n=e(r);return Math.abs(n[0]-t[0])>v||Math.abs(n[1]-t[1])>v}(r))return g.scale(e.scale()),void g.translate(e.translate());e.scale(n.event.scale),e.translate([a[0],n.event.translate[1]]),s?y(h)&&(d=y(h),p=[o[0]+(d[0]-s[0]),i[1],i[2]],e.rotate(p),o=p):s=y(r=h),m=!0,t.render()}).on("zoomend",function(){n.select(this).style(c),m&&f(t,e,x)}),g}function d(t,e){var r,i={r:e.rotate(),k:e.scale()},a=u(0,e),h=function(t){var e=0,r=arguments.length,i=[];for(;++ed?(a=(f>0?90:-90)-p,i=0):(a=Math.asin(f/d)*s-p,i=Math.sqrt(d*d-f*f));var m=180-a-2*p,v=(Math.atan2(h,u)-Math.atan2(c,i))*s,x=(Math.atan2(h,u)-Math.atan2(c,-i))*s,b=g(r[0],r[1],a,v),_=g(r[0],r[1],m,x);return b<=_?[a,v,r[2]]:[m,x,r[2]]}(k,r,E);isFinite(M[0])&&isFinite(M[1])&&isFinite(M[2])||(M=E),e.rotate(M),E=M}}else r=m(e,T=b);h.of(this,arguments)({type:"zoom"})}),A=h.of(this,arguments),p++||A({type:"zoomstart"})}).on("zoomend",function(){var r;n.select(this).style(c),d.call(a,"zoom",null),r=h.of(this,arguments),--p||r({type:"zoomend"}),f(t,e,v)}).on("zoom.redraw",function(){t.render()}),n.rebind(a,h,"on")}function m(t,e){var r=t.invert(e);return r&&isFinite(r[0])&&isFinite(r[1])&&function(t){var e=t[0]*o,r=t[1]*o,n=Math.cos(r);return[n*Math.cos(e),n*Math.sin(e),Math.sin(r)]}(r)}function g(t,e,r,n){var i=v(r-t),a=v(n-e);return Math.sqrt(i*i+a*a)}function v(t){return(t%360+540)%360-180}function y(t,e,r){var n=r*o,i=t.slice(),a=0===e?1:0,s=2===e?1:2,l=Math.cos(n),c=Math.sin(n);return i[a]=t[a]*l-t[s]*c,i[s]=t[s]*l+t[a]*c,i}function x(t,e){for(var r=0,n=0,i=t.length;nMath.abs(s)?(c.boxEnd[1]=c.boxStart[1]+Math.abs(a)*_*(s>=0?1:-1),c.boxEnd[1]l[3]&&(c.boxEnd[1]=l[3],c.boxEnd[0]=c.boxStart[0]+(l[3]-c.boxStart[1])/Math.abs(_))):(c.boxEnd[0]=c.boxStart[0]+Math.abs(s)/_*(a>=0?1:-1),c.boxEnd[0]l[2]&&(c.boxEnd[0]=l[2],c.boxEnd[1]=c.boxStart[1]+(l[2]-c.boxStart[0])*Math.abs(_)))}}else c.boxEnabled?(a=c.boxStart[0]!==c.boxEnd[0],s=c.boxStart[1]!==c.boxEnd[1],a||s?(a&&(g(0,c.boxStart[0],c.boxEnd[0]),t.xaxis.autorange=!1),s&&(g(1,c.boxStart[1],c.boxEnd[1]),t.yaxis.autorange=!1),t.relayoutCallback()):t.glplot.setDirty(),c.boxEnabled=!1,c.boxInited=!1):c.boxInited&&(c.boxInited=!1);break;case"pan":c.boxEnabled=!1,c.boxInited=!1,e?(c.panning||(c.dragStart[0]=n,c.dragStart[1]=i),Math.abs(c.dragStart[0]-n)Math.abs(e))c.rotate(a,0,0,-t*r*Math.PI*d.rotateSpeed/window.innerWidth);else{var o=-d.zoomSpeed*i*e/window.innerHeight*(a-c.lastT())/20;c.pan(a,0,0,f*(Math.exp(o)-1))}}},!0),d};var n=t("right-now"),i=t("3d-view"),a=t("mouse-change"),o=t("mouse-wheel"),s=t("mouse-event-offset"),l=t("has-passive-events")},{"3d-view":45,"has-passive-events":394,"mouse-change":418,"mouse-event-offset":419,"mouse-wheel":421,"right-now":480}],787:[function(t,e,r){"use strict";var n=t("../../plot_api/edit_types").overrideAll,i=t("../../components/fx/layout_attributes"),a=t("./scene"),o=t("../get_data").getSubplotData,s=t("../../lib"),l=t("../../constants/xmlns_namespaces");r.name="gl3d",r.attr="scene",r.idRoot="scene",r.idRegex=r.attrRegex=s.counterRegex("scene"),r.attributes=t("./layout/attributes"),r.layoutAttributes=t("./layout/layout_attributes"),r.baseLayoutAttrOverrides=n({hoverlabel:i.hoverlabel},"plot","nested"),r.supplyLayoutDefaults=t("./layout/defaults"),r.plot=function(t){for(var e=t._fullLayout,r=t._fullData,n=e._subplots.gl3d,i=0;i1;o(t,e,r,{type:"gl3d",attributes:l,handleDefaults:c,fullLayout:e,font:e.font,fullData:r,getDfltFromLayout:function(e){if(!i)return n.validate(t[e],l[e])?t[e]:void 0},paper_bgcolor:e.paper_bgcolor,calendar:e.calendar})}},{"../../../components/color":570,"../../../lib":696,"../../../registry":827,"../../subplot_defaults":822,"./axis_defaults":790,"./layout_attributes":793}],793:[function(t,e,r){"use strict";var n=t("./axis_attributes"),i=t("../../domain").attributes,a=t("../../../lib/extend").extendFlat,o=t("../../../lib").counterRegex;function s(t,e,r){return{x:{valType:"number",dflt:t,editType:"camera"},y:{valType:"number",dflt:e,editType:"camera"},z:{valType:"number",dflt:r,editType:"camera"},editType:"camera"}}e.exports={_arrayAttrRegexps:[o("scene",".annotations",!0)],bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"plot"},camera:{up:a(s(0,0,1),{}),center:a(s(0,0,0),{}),eye:a(s(1.25,1.25,1.25),{}),editType:"camera"},domain:i({name:"scene",editType:"plot"}),aspectmode:{valType:"enumerated",values:["auto","cube","data","manual"],dflt:"auto",editType:"plot",impliedEdits:{"aspectratio.x":void 0,"aspectratio.y":void 0,"aspectratio.z":void 0}},aspectratio:{x:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},y:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},z:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},editType:"plot",impliedEdits:{aspectmode:"manual"}},xaxis:n,yaxis:n,zaxis:n,dragmode:{valType:"enumerated",values:["orbit","turntable","zoom","pan",!1],dflt:"turntable",editType:"plot"},hovermode:{valType:"enumerated",values:["closest",!1],dflt:"closest",editType:"modebar"},uirevision:{valType:"any",editType:"none"},editType:"plot",_deprecated:{cameraposition:{valType:"info_array",editType:"camera"}}}},{"../../../lib":696,"../../../lib/extend":685,"../../domain":770,"./axis_attributes":789}],794:[function(t,e,r){"use strict";var n=t("../../../lib/str2rgbarray"),i=["xaxis","yaxis","zaxis"];function a(){this.enabled=[!0,!0,!0],this.colors=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.drawSides=[!0,!0,!0],this.lineWidth=[1,1,1]}a.prototype.merge=function(t){for(var e=0;e<3;++e){var r=t[i[e]];r.visible?(this.enabled[e]=r.showspikes,this.colors[e]=n(r.spikecolor),this.drawSides[e]=r.spikesides,this.lineWidth[e]=r.spikethickness):(this.enabled[e]=!1,this.drawSides[e]=!1)}},e.exports=function(t){var e=new a;return e.merge(t),e}},{"../../../lib/str2rgbarray":719}],795:[function(t,e,r){"use strict";e.exports=function(t){for(var e=t.axesOptions,r=t.glplot.axesPixels,l=t.fullSceneLayout,c=[[],[],[]],u=0;u<3;++u){var f=l[o[u]];if(f._length=(r[u].hi-r[u].lo)*r[u].pixelsPerDataUnit/t.dataScale[u],Math.abs(f._length)===1/0||isNaN(f._length))c[u]=[];else{f._input_range=f.range.slice(),f.range[0]=r[u].lo/t.dataScale[u],f.range[1]=r[u].hi/t.dataScale[u],f._m=1/(t.dataScale[u]*r[u].pixelsPerDataUnit),f.range[0]===f.range[1]&&(f.range[0]-=1,f.range[1]+=1);var h=f.tickmode;if("auto"===f.tickmode){f.tickmode="linear";var p=f.nticks||i.constrain(f._length/40,4,9);n.autoTicks(f,Math.abs(f.range[1]-f.range[0])/p)}for(var d=n.calcTicks(f),m=0;m")}else g=c.textLabel;t.fullSceneLayout.hovermode&&f.loneHover({x:(.5+.5*d[0]/d[3])*i,y:(.5-.5*d[1]/d[3])*a,xLabel:w,yLabel:k,zLabel:M,text:g,name:l.name,color:f.castHoverOption(e,v,"bgcolor")||l.color,borderColor:f.castHoverOption(e,v,"bordercolor"),fontFamily:f.castHoverOption(e,v,"font.family"),fontSize:f.castHoverOption(e,v,"font.size"),fontColor:f.castHoverOption(e,v,"font.color")},{container:r,gd:t.graphDiv});var T={x:c.traceCoordinate[0],y:c.traceCoordinate[1],z:c.traceCoordinate[2],data:e._input,fullData:e,curveNumber:e.index,pointNumber:v};e._module.eventData&&(T=e._module.eventData(T,c,e,{},v)),f.appendArrayPointValue(T,e,v);var S={points:[T]};c.buttons&&c.distance<5?t.graphDiv.emit("plotly_click",S):t.graphDiv.emit("plotly_hover",S),o=S}else f.loneUnhover(r),t.graphDiv.emit("plotly_unhover",o);t.drawAnnotations(t)}.bind(null,t),t.traces={},!0}function b(t,e){var r=document.createElement("div"),n=t.container;this.graphDiv=t.graphDiv;var i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.style.position="absolute",i.style.top=i.style.left="0px",i.style.width=i.style.height="100%",i.style["z-index"]=20,i.style["pointer-events"]="none",r.appendChild(i),this.svgContainer=i,r.id=t.id,r.style.position="absolute",r.style.top=r.style.left="0px",r.style.width=r.style.height="100%",n.appendChild(r),this.fullLayout=e,this.id=t.id||"scene",this.fullSceneLayout=e[this.id],this.plotArgs=[[],{},{}],this.axesOptions=g(e[this.id]),this.spikeOptions=v(e[this.id]),this.container=r,this.staticMode=!!t.staticPlot,this.pixelRatio=t.plotGlPixelRatio||2,this.dataScale=[1,1,1],this.contourLevels=[[],[],[]],this.convertAnnotations=l.getComponentMethod("annotations3d","convert"),this.drawAnnotations=l.getComponentMethod("annotations3d","draw"),x(this)}var _=b.prototype;_.recoverContext=function(){var t=this,e=this.glplot.gl,r=this.glplot.canvas;this.glplot.dispose(),requestAnimationFrame(function n(){e.isContextLost()?requestAnimationFrame(n):x(t,t.fullLayout,r,e)?t.plot.apply(t,t.plotArgs):c.error("Catastrophic and unrecoverable WebGL error. Context lost.")})};var w=["xaxis","yaxis","zaxis"];function k(t,e,r){for(var n=t.fullSceneLayout,i=0;i<3;i++){var a=w[i],o=a.charAt(0),s=n[a],l=e[o],u=e[o+"calendar"],f=e["_"+o+"length"];if(c.isArrayOrTypedArray(l))for(var h,p=0;p<(f||l.length);p++)if(c.isArrayOrTypedArray(l[p]))for(var d=0;dm[1][a])m[0][a]=-1,m[1][a]=1;else{var E=m[1][a]-m[0][a];m[0][a]-=E/32,m[1][a]+=E/32}if("reversed"===s.autorange){var C=m[0][a];m[0][a]=m[1][a],m[1][a]=C}}else{var L=s.range;m[0][a]=s.r2l(L[0]),m[1][a]=s.r2l(L[1])}m[0][a]===m[1][a]&&(m[0][a]-=1,m[1][a]+=1),g[a]=m[1][a]-m[0][a],this.glplot.bounds[0][a]=m[0][a]*p[a],this.glplot.bounds[1][a]=m[1][a]*p[a]}var z=[1,1,1];for(a=0;a<3;++a){var O=v[l=(s=c[w[a]]).type];z[a]=Math.pow(O.acc,1/O.count)/p[a]}var I;if("auto"===c.aspectmode)I=Math.max.apply(null,z)/Math.min.apply(null,z)<=4?z:[1,1,1];else if("cube"===c.aspectmode)I=[1,1,1];else if("data"===c.aspectmode)I=z;else{if("manual"!==c.aspectmode)throw new Error("scene.js aspectRatio was not one of the enumerated types");var P=c.aspectratio;I=[P.x,P.y,P.z]}c.aspectratio.x=u.aspectratio.x=I[0],c.aspectratio.y=u.aspectratio.y=I[1],c.aspectratio.z=u.aspectratio.z=I[2],this.glplot.aspect=I;var D=c.domain||null,R=e._size||null;if(D&&R){var B=this.container.style;B.position="absolute",B.left=R.l+D.x[0]*R.w+"px",B.top=R.t+(1-D.y[1])*R.h+"px",B.width=R.w*(D.x[1]-D.x[0])+"px",B.height=R.h*(D.y[1]-D.y[0])+"px"}this.glplot.redraw()}},_.destroy=function(){this.glplot&&(this.camera.mouseListener.enabled=!1,this.container.removeEventListener("wheel",this.camera.wheelListener),this.camera=this.glplot.camera=null,this.glplot.dispose(),this.container.parentNode.removeChild(this.container),this.glplot=null)},_.getCamera=function(){return this.glplot.camera.view.recalcMatrix(this.camera.view.lastT()),M(this.glplot.camera)},_.setCamera=function(t){var e;this.glplot.camera.lookAt.apply(this,[[(e=t).eye.x,e.eye.y,e.eye.z],[e.center.x,e.center.y,e.center.z],[e.up.x,e.up.y,e.up.z]])},_.saveCamera=function(t){var e=this.getCamera(),r=c.nestedProperty(t,this.id+".camera"),n=r.get(),i=!1;function a(t,e,r,n){var i=["up","center","eye"],a=["x","y","z"];return e[i[r]]&&t[i[r]][a[n]]===e[i[r]][a[n]]}if(void 0===n)i=!0;else for(var o=0;o<3;o++)for(var s=0;s<3;s++)if(!a(e,n,o,s)){i=!0;break}return i&&r.set(e),i},_.updateFx=function(t,e){var r=this.camera;r&&("orbit"===t?(r.mode="orbit",r.keyBindingMode="rotate"):"turntable"===t?(r.up=[0,0,1],r.mode="turntable",r.keyBindingMode="rotate"):r.keyBindingMode=t),this.fullSceneLayout.hovermode=e},_.toImage=function(t){t||(t="png"),this.staticMode&&this.container.appendChild(n),this.glplot.redraw();var e=this.glplot.gl,r=e.drawingBufferWidth,i=e.drawingBufferHeight;e.bindFramebuffer(e.FRAMEBUFFER,null);var a=new Uint8Array(r*i*4);e.readPixels(0,0,r,i,e.RGBA,e.UNSIGNED_BYTE,a);for(var o=0,s=i-1;o0)}function l(t){var e={},r={};switch(t.type){case"circle":n.extendFlat(r,{"circle-radius":t.circle.radius,"circle-color":t.color,"circle-opacity":t.opacity});break;case"line":n.extendFlat(r,{"line-width":t.line.width,"line-color":t.color,"line-opacity":t.opacity});break;case"fill":n.extendFlat(r,{"fill-color":t.color,"fill-outline-color":t.fill.outlinecolor,"fill-opacity":t.opacity});break;case"symbol":var a=t.symbol,o=i(a.textposition,a.iconsize);n.extendFlat(e,{"icon-image":a.icon+"-15","icon-size":a.iconsize/10,"text-field":a.text,"text-size":a.textfont.size,"text-anchor":o.anchor,"text-offset":o.offset}),n.extendFlat(r,{"icon-color":t.color,"text-color":a.textfont.color,"text-opacity":t.opacity})}return{layout:e,paint:r}}o.update=function(t){this.visible?this.needsNewSource(t)?(this.removeLayer(),this.updateSource(t),this.updateLayer(t)):this.needsNewLayer(t)?this.updateLayer(t):this.updateStyle(t):(this.updateSource(t),this.updateLayer(t)),this.visible=s(t)},o.needsNewSource=function(t){return this.sourceType!==t.sourcetype||this.source!==t.source||this.layerType!==t.type},o.needsNewLayer=function(t){return this.layerType!==t.type||this.below!==t.below},o.updateSource=function(t){var e=this.map;if(e.getSource(this.idSource)&&e.removeSource(this.idSource),this.sourceType=t.sourcetype,this.source=t.source,s(t)){var r=function(t){var e,r=t.sourcetype,n=t.source,i={type:r};"geojson"===r?e="data":"vector"===r&&(e="string"==typeof n?"url":"tiles");return i[e]=n,i}(t);e.addSource(this.idSource,r)}},o.updateLayer=function(t){var e=this.map,r=l(t);this.removeLayer(),this.layerType=t.type,s(t)&&e.addLayer({id:this.idLayer,source:this.idSource,"source-layer":t.sourcelayer||"",type:t.type,layout:r.layout,paint:r.paint},t.below)},o.updateStyle=function(t){if(s(t)){var e=l(t);this.mapbox.setOptions(this.idLayer,"setLayoutProperty",e.layout),this.mapbox.setOptions(this.idLayer,"setPaintProperty",e.paint)}},o.removeLayer=function(){var t=this.map;t.getLayer(this.idLayer)&&t.removeLayer(this.idLayer)},o.dispose=function(){var t=this.map;t.removeLayer(this.idLayer),t.removeSource(this.idSource)},e.exports=function(t,e,r){var n=new a(t,e);return n.update(r),n}},{"../../lib":696,"./convert_text_opts":801}],804:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../components/color").defaultLine,a=t("../domain").attributes,o=t("../font_attributes"),s=t("../../traces/scatter/attributes").textposition,l=t("../../plot_api/edit_types").overrideAll,c=t("../../plot_api/plot_template").templatedArray,u=o({});u.family.dflt="Open Sans Regular, Arial Unicode MS Regular",(e.exports=l({_arrayAttrRegexps:[n.counterRegex("mapbox",".layers",!0)],domain:a({name:"mapbox"}),accesstoken:{valType:"string",noBlank:!0,strict:!0},style:{valType:"any",values:["basic","streets","outdoors","light","dark","satellite","satellite-streets"],dflt:"basic"},center:{lon:{valType:"number",dflt:0},lat:{valType:"number",dflt:0}},zoom:{valType:"number",dflt:1},bearing:{valType:"number",dflt:0},pitch:{valType:"number",dflt:0},layers:c("layer",{visible:{valType:"boolean",dflt:!0},sourcetype:{valType:"enumerated",values:["geojson","vector"],dflt:"geojson"},source:{valType:"any"},sourcelayer:{valType:"string",dflt:""},type:{valType:"enumerated",values:["circle","line","fill","symbol"],dflt:"circle"},below:{valType:"string",dflt:""},color:{valType:"color",dflt:i},opacity:{valType:"number",min:0,max:1,dflt:1},circle:{radius:{valType:"number",dflt:15}},line:{width:{valType:"number",dflt:2}},fill:{outlinecolor:{valType:"color",dflt:i}},symbol:{icon:{valType:"string",dflt:"marker"},iconsize:{valType:"number",dflt:10},text:{valType:"string",dflt:""},textfont:u,textposition:n.extendFlat({},s,{arrayOk:!1})}})},"plot","from-root")).uirevision={valType:"any",editType:"none"}},{"../../components/color":570,"../../lib":696,"../../plot_api/edit_types":727,"../../plot_api/plot_template":734,"../../traces/scatter/attributes":1043,"../domain":770,"../font_attributes":771}],805:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../subplot_defaults"),a=t("../array_container_defaults"),o=t("./layout_attributes");function s(t,e,r,n){r("accesstoken",n.accessToken),r("style"),r("center.lon"),r("center.lat"),r("zoom"),r("bearing"),r("pitch"),a(t,e,{name:"layers",handleItemDefaults:l}),e._input=t}function l(t,e){function r(r,i){return n.coerce(t,e,o.layers,r,i)}if(r("visible")){var i=r("sourcetype");r("source"),"vector"===i&&r("sourcelayer");var a=r("type");r("below"),r("color"),r("opacity"),"circle"===a&&r("circle.radius"),"line"===a&&r("line.width"),"fill"===a&&r("fill.outlinecolor"),"symbol"===a&&(r("symbol.icon"),r("symbol.iconsize"),r("symbol.text"),n.coerceFont(r,"symbol.textfont"),r("symbol.textposition"))}}e.exports=function(t,e,r){i(t,e,r,{type:"mapbox",attributes:o,handleDefaults:s,partition:"y",accessToken:e._mapboxAccessToken})}},{"../../lib":696,"../array_container_defaults":740,"../subplot_defaults":822,"./layout_attributes":804}],806:[function(t,e,r){"use strict";var n=t("mapbox-gl"),i=t("../../components/fx"),a=t("../../lib"),o=t("../../registry"),s=t("../../components/dragelement"),l=t("../cartesian/select").prepSelect,c=t("../cartesian/select").selectOnClick,u=t("./constants"),f=t("./layout_attributes"),h=t("./layers");function p(t){this.id=t.id,this.gd=t.gd,this.container=t.container,this.isStatic=t.staticPlot;var e=t.fullLayout;this.uid=e._uid+"-"+this.id,this.opts=e[this.id],this.div=null,this.xaxis=null,this.yaxis=null,this.createFramework(e),this.map=null,this.accessToken=null,this.styleObj=null,this.traceHash={},this.layerList=[]}var d=p.prototype;function m(t){var e=f.style.values,r=f.style.dflt,n={};return a.isPlainObject(t)?(n.id=t.id,n.style=t):"string"==typeof t?(n.id=t,n.style=-1!==e.indexOf(t)?g(t):t):(n.id=r,n.style=g(r)),n.transition={duration:0,delay:0},n}function g(t){return u.styleUrlPrefix+t+"-"+u.styleUrlSuffix}function v(t){return[t.lon,t.lat]}e.exports=function(t){return new p(t)},d.plot=function(t,e,r){var n,i=this,a=i.opts=e[this.id];i.map&&a.accesstoken!==i.accessToken&&(i.map.remove(),i.map=null,i.styleObj=null,i.traceHash=[],i.layerList={}),n=i.map?new Promise(function(r,n){i.updateMap(t,e,r,n)}):new Promise(function(r,n){i.createMap(t,e,r,n)}),r.push(n)},d.createMap=function(t,e,r,a){var s=this,l=s.gd,f=s.opts,h=s.styleObj=m(f.style);s.accessToken=f.accesstoken;var p=s.map=new n.Map({container:s.div,style:h.style,center:v(f.center),zoom:f.zoom,bearing:f.bearing,pitch:f.pitch,interactive:!s.isStatic,preserveDrawingBuffer:s.isStatic,doubleClickZoom:!1,boxZoom:!1}),d=u.controlContainerClassName,g=s.div.getElementsByClassName(d)[0];if(s.div.removeChild(g),p._canvas.style.left="0px",p._canvas.style.top="0px",s.rejectOnError(a),p.once("load",function(){s.updateData(t),s.updateLayout(e),s.resolveOnRender(r)}),!s.isStatic){var y=!1;p.on("moveend",function(t){if(s.map){if(t.originalEvent||y){var e=s.getView();f._input.center=f.center=e.center,f._input.zoom=f.zoom=e.zoom,f._input.bearing=f.bearing=e.bearing,f._input.pitch=f.pitch=e.pitch,b(e)}y=!1}}),p.on("wheel",function(){y=!0}),p.on("mousemove",function(t){var e=s.div.getBoundingClientRect();t.clientX=t.point.x+e.left,t.clientY=t.point.y+e.top,t.target.getBoundingClientRect=function(){return e},s.xaxis.p2c=function(){return t.lngLat.lng},s.yaxis.p2c=function(){return t.lngLat.lat},i.hover(l,t,s.id)}),p.on("dragstart",x),p.on("zoomstart",x),p.on("dblclick",function(){l.emit("plotly_doubleclick",null);var t=s.viewInitial;p.setCenter(v(t.center)),p.setZoom(t.zoom),p.setBearing(t.bearing),p.setPitch(t.pitch);var e=s.getView();f._input.center=f.center=e.center,f._input.zoom=f.zoom=e.zoom,f._input.bearing=f.bearing=e.bearing,f._input.pitch=f.pitch=e.pitch,b(e)}),s.clearSelect=function(){l._fullLayout._zoomlayer.selectAll(".select-outline").remove()},s.onClickInPanFn=function(t){return function(e){var r=l._fullLayout.clickmode;r.indexOf("select")>-1&&c(e.originalEvent,l,[s.xaxis],[s.yaxis],s.id,t),r.indexOf("event")>-1&&i.click(l,e.originalEvent)}}}function x(){i.loneUnhover(e._toppaper)}function b(t){var e=s.id,r={};for(var n in t)r[e+"."+n]=t[n];o.call("_storeDirectGUIEdit",l.layout,l._fullLayout._preGUI,r),l.emit("plotly_relayout",r)}},d.updateMap=function(t,e,r,n){var i=this,a=i.map;i.rejectOnError(n);var o=m(i.opts.style);i.styleObj.id!==o.id?(i.styleObj=o,a.setStyle(o.style),a.once("styledata",function(){i.traceHash={},i.updateData(t),i.updateLayout(e),i.resolveOnRender(r)})):(i.updateData(t),i.updateLayout(e),i.resolveOnRender(r))},d.updateData=function(t){var e,r,n,i,a=this.traceHash;for(n=0;n=e.width-20?(a["text-anchor"]="start",a.x=5):(a["text-anchor"]="end",a.x=e._paper.attr("width")-7),r.attr(a);var o=r.select(".js-link-to-tool"),s=r.select(".js-link-spacer"),u=r.select(".js-sourcelinks");t._context.showSources&&t._context.showSources(t),t._context.showLink&&function(t,e){e.text("");var r=e.append("a").attr({"xlink:xlink:href":"#",class:"link--impt link--embedview","font-weight":"bold"}).text(t._context.linkText+" "+String.fromCharCode(187));if(t._context.sendData)r.on("click",function(){g.sendDataToCloud(t)});else{var n=window.location.pathname.split("/"),i=window.location.search;r.attr({"xlink:xlink:show":"new","xlink:xlink:href":"/"+n[2].split(".")[0]+"/"+n[1]+i})}}(t,o),s.text(o.text()&&u.text()?" - ":"")}},g.sendDataToCloud=function(t){t.emit("plotly_beforeexport");var e=(window.PLOTLYENV||{}).BASE_URL||t._context.plotlyServerURL,r=n.select(t).append("div").attr("id","hiddenform").style("display","none"),i=r.append("form").attr({action:e+"/external",method:"post",target:"_blank"});return i.append("input").attr({type:"text",name:"data"}).node().value=g.graphJson(t,!1,"keepdata"),i.node().submit(),r.remove(),t.emit("plotly_afterexport"),!1};var x,b=["days","shortDays","months","shortMonths","periods","dateTime","date","time","decimal","thousands","grouping","currency"],_=["year","month","dayMonth","dayMonthYear"];function w(t,e){var r=t._context.locale,n=!1,i={};function o(t){for(var r=!0,a=0;a1&&I.length>1){for(a.getComponentMethod("grid","sizeDefaults")(c,s),o=0;o15&&I.length>15&&0===s.shapes.length&&0===s.images.length,s._hasCartesian=s._has("cartesian"),s._hasGeo=s._has("geo"),s._hasGL3D=s._has("gl3d"),s._hasGL2D=s._has("gl2d"),s._hasTernary=s._has("ternary"),s._hasPie=s._has("pie"),g.linkSubplots(h,s,u,i),g.cleanPlot(h,s,u,i),d(s,i),s._preGUI||(s._preGUI={}),s._tracePreGUI||(s._tracePreGUI={});var F,N=s._tracePreGUI,j={};for(F in N)j[F]="old";for(o=0;o0){var f=1-2*s;n=Math.round(f*n),a=Math.round(f*a)}}var h=g.layoutAttributes.width.min,p=g.layoutAttributes.height.min;n1,m=!e.height&&Math.abs(r.height-a)>1;(m||d)&&(d&&(r.width=n),m&&(r.height=a)),t._initialAutoSize||(t._initialAutoSize={width:n,height:a}),g.sanitizeMargins(r)},g.supplyLayoutModuleDefaults=function(t,e,r,n){var i,o,s,c=a.componentsRegistry,u=e._basePlotModules,f=a.subplotsRegistry.cartesian;for(i in c)(s=c[i]).includeBasePlot&&s.includeBasePlot(t,e);for(var h in u.length||u.push(f),e._has("cartesian")&&(a.getComponentMethod("grid","contentDefaults")(t,e),f.finalizeSubplots(t,e)),e._subplots)e._subplots[h].sort(l.subplotSort);for(o=0;o.5*n.width&&(r.l=r.r=0),r.b+r.t>.5*n.height&&(r.b=r.t=0);var l=void 0!==r.xl?r.xl:r.x,c=void 0!==r.xr?r.xr:r.x,u=void 0!==r.yt?r.yt:r.y,f=void 0!==r.yb?r.yb:r.y;i[e]={l:{val:l,size:r.l+o},r:{val:c,size:r.r+o},b:{val:f,size:r.b+o},t:{val:u,size:r.t+o}},a[e]=1}else delete i[e],delete a[e];n._replotting||g.doAutoMargin(t)}},g.doAutoMargin=function(t){var e=t._fullLayout;e._size||(e._size={}),A(e);var r=e._size,n=JSON.stringify(r),o=Math.max(e.margin.l||0,0),s=Math.max(e.margin.r||0,0),l=Math.max(e.margin.t||0,0),c=Math.max(e.margin.b||0,0),u=e._pushmargin,f=e._pushmarginIds;if(!1!==e.margin.autoexpand){for(var h in u)f[h]||delete u[h];for(var p in u.base={l:{val:0,size:o},r:{val:1,size:s},t:{val:1,size:l},b:{val:0,size:c}},u){var d=u[p].l||{},m=u[p].b||{},g=d.val,v=d.size,y=m.val,x=m.size;for(var b in u){if(i(v)&&u[b].r){var _=u[b].r.val,w=u[b].r.size;if(_>g){var k=(v*_+(w-e.width)*g)/(_-g),M=(w*(1-g)+(v-e.width)*(1-_))/(_-g);k>=0&&M>=0&&k+M>o+s&&(o=k,s=M)}}if(i(x)&&u[b].t){var T=u[b].t.val,S=u[b].t.size;if(T>y){var E=(x*T+(S-e.height)*y)/(T-y),C=(S*(1-y)+(x-e.height)*(1-T))/(T-y);E>=0&&C>=0&&E+C>c+l&&(c=E,l=C)}}}}}if(r.l=Math.round(o),r.r=Math.round(s),r.t=Math.round(l),r.b=Math.round(c),r.p=Math.round(e.margin.pad),r.w=Math.round(e.width)-r.l-r.r,r.h=Math.round(e.height)-r.t-r.b,!e._replotting&&"{}"!==n&&n!==JSON.stringify(e._size))return"_redrawFromAutoMarginCount"in e?e._redrawFromAutoMarginCount++:e._redrawFromAutoMarginCount=1,a.call("plot",t)},g.graphJson=function(t,e,r,n,i){(i&&e&&!t._fullData||i&&!e&&!t._fullLayout)&&g.supplyDefaults(t);var a=i?t._fullData:t.data,o=i?t._fullLayout:t.layout,s=(t._transitionData||{})._frames;function c(t){if("function"==typeof t)return null;if(l.isPlainObject(t)){var e,n,i={};for(e in t)if("function"!=typeof t[e]&&-1===["_","["].indexOf(e.charAt(0))){if("keepdata"===r){if("src"===e.substr(e.length-3))continue}else if("keepstream"===r){if("string"==typeof(n=t[e+"src"])&&n.indexOf(":")>0&&!l.isPlainObject(t.stream))continue}else if("keepall"!==r&&"string"==typeof(n=t[e+"src"])&&n.indexOf(":")>0)continue;i[e]=c(t[e])}return i}return Array.isArray(t)?t.map(c):l.isTypedArray(t)?l.simpleMap(t,l.identity):l.isJSDate(t)?l.ms2DateTimeLocal(+t):t}var u={data:(a||[]).map(function(t){var r=c(t);return e&&delete r.fit,r})};return e||(u.layout=c(o)),t.framework&&t.framework.isPolar&&(u=t.framework.getConfig()),s&&(u.frames=c(s)),"object"===n?u:JSON.stringify(u)},g.modifyFrames=function(t,e){var r,n,i,a=t._transitionData._frames,o=t._transitionData._frameHash;for(r=0;r0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push(function(){p=!0}),i.redraw&&t._transitionData._interruptCallbacks.push(function(){return a.call("redraw",t)}),t._transitionData._interruptCallbacks.push(function(){t.emit("plotly_transitioninterrupted",[])});var n,s,c=0,u=0;function f(){return c++,function(){var r;u++,p||u!==c||(r=e,t._transitionData&&(function(t){if(t)for(;t.length;)t.shift()}(t._transitionData._interruptCallbacks),Promise.resolve().then(function(){if(i.redraw)return a.call("redraw",t)}).then(function(){t._transitioning=!1,t._transitioningWithDuration=!1,t.emit("plotly_transitioned",[])}).then(r)))}}var d=t._fullLayout._basePlotModules,m=!1;if(r)for(s=0;s0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push(function(){o=!0}),s&&t._transitionData._interruptCallbacks.push(function(){return a.call("redraw",t)}),t._transitionData._interruptCallbacks.push(function(){t.emit("plotly_transitioninterrupted",[])});var p,d=0,m=0;function g(){return d++,function(){var e;m++,o||m!==d||(e=r,t._transitionData&&(function(t){if(t)for(;t.length;)t.shift()}(t._transitionData._interruptCallbacks),Promise.resolve().then(function(){if(s)return a.call("redraw",t)}).then(function(){t._transitioning=!1,t._transitioningWithDuration=!1,t.emit("plotly_transitioned",[])}).then(e)))}}var v=[];if(Object.keys(i).length){for(n=0;n=0;s--)if(o[s].enabled){r._indexToPoints=o[s]._indexToPoints;break}n&&n.calc&&(a=n.calc(t,r))}Array.isArray(a)&&a[0]||(a=[{x:u,y:u}]),a[0].t||(a[0].t={}),a[0].trace=r,d[e]=a}}for(y&&T(c),i=0;i1e-10?t:0}function h(t,e,r){e=e||0,r=r||0;for(var n=t.length,i=new Array(n),a=0;a0?r:1/0}),i=n.mod(r+1,e.length);return[e[r],e[i]]},findIntersectionXY:c,findXYatLength:function(t,e,r,n){var i=-e*r,a=e*e+1,o=2*(e*i-r),s=i*i+r*r-t*t,l=Math.sqrt(o*o-4*a*s),c=(-o+l)/(2*a),u=(-o-l)/(2*a);return[[c,e*c+i+n],[u,e*u+i+n]]},clampTiny:f,pathPolygon:function(t,e,r,n,i,a){return"M"+h(u(t,e,r,n),i,a).join("L")},pathPolygonAnnulus:function(t,e,r,n,i,a,o){var s,l;t=0?h.angularAxis.domain:n.extent(k),E=Math.abs(k[1]-k[0]);A&&!M&&(E=0);var C=S.slice();T&&M&&(C[1]+=E);var L=h.angularAxis.ticksCount||4;L>8&&(L=L/(L/8)+L%8),h.angularAxis.ticksStep&&(L=(C[1]-C[0])/L);var z=h.angularAxis.ticksStep||(C[1]-C[0])/(L*(h.minorTicks+1));w&&(z=Math.max(Math.round(z),1)),C[2]||(C[2]=z);var O=n.range.apply(this,C);if(O=O.map(function(t,e){return parseFloat(t.toPrecision(12))}),s=n.scale.linear().domain(C.slice(0,2)).range("clockwise"===h.direction?[0,360]:[360,0]),u.layout.angularAxis.domain=s.domain(),u.layout.angularAxis.endPadding=T?E:0,"undefined"==typeof(t=n.select(this).select("svg.chart-root"))||t.empty()){var I=(new DOMParser).parseFromString("' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '","application/xml"),P=this.appendChild(this.ownerDocument.importNode(I.documentElement,!0));t=n.select(P)}t.select(".guides-group").style({"pointer-events":"none"}),t.select(".angular.axis-group").style({"pointer-events":"none"}),t.select(".radial.axis-group").style({"pointer-events":"none"});var D,R=t.select(".chart-group"),B={fill:"none",stroke:h.tickColor},F={"font-size":h.font.size,"font-family":h.font.family,fill:h.font.color,"text-shadow":["-1px 0px","1px -1px","-1px 1px","1px 1px"].map(function(t,e){return" "+t+" 0 "+h.font.outlineColor}).join(",")};if(h.showLegend){D=t.select(".legend-group").attr({transform:"translate("+[x,h.margin.top]+")"}).style({display:"block"});var N=p.map(function(t,e){var r=o.util.cloneJson(t);return r.symbol="DotPlot"===t.geometry?t.dotType||"circle":"LinePlot"!=t.geometry?"square":"line",r.visibleInLegend="undefined"==typeof t.visibleInLegend||t.visibleInLegend,r.color="LinePlot"===t.geometry?t.strokeColor:t.color,r});o.Legend().config({data:p.map(function(t,e){return t.name||"Element"+e}),legendConfig:i({},o.Legend.defaultConfig().legendConfig,{container:D,elements:N,reverseOrder:h.legend.reverseOrder})})();var j=D.node().getBBox();x=Math.min(h.width-j.width-h.margin.left-h.margin.right,h.height-h.margin.top-h.margin.bottom)/2,x=Math.max(10,x),_=[h.margin.left+x,h.margin.top+x],r.range([0,x]),u.layout.radialAxis.domain=r.domain(),D.attr("transform","translate("+[_[0]+x,_[1]-x]+")")}else D=t.select(".legend-group").style({display:"none"});t.attr({width:h.width,height:h.height}).style({opacity:h.opacity}),R.attr("transform","translate("+_+")").style({cursor:"crosshair"});var V=[(h.width-(h.margin.left+h.margin.right+2*x+(j?j.width:0)))/2,(h.height-(h.margin.top+h.margin.bottom+2*x))/2];if(V[0]=Math.max(0,V[0]),V[1]=Math.max(0,V[1]),t.select(".outer-group").attr("transform","translate("+V+")"),h.title){var U=t.select("g.title-group text").style(F).text(h.title),q=U.node().getBBox();U.attr({x:_[0]-q.width/2,y:_[1]-x-20})}var H=t.select(".radial.axis-group");if(h.radialAxis.gridLinesVisible){var G=H.selectAll("circle.grid-circle").data(r.ticks(5));G.enter().append("circle").attr({class:"grid-circle"}).style(B),G.attr("r",r),G.exit().remove()}H.select("circle.outside-circle").attr({r:x}).style(B);var W=t.select("circle.background-circle").attr({r:x}).style({fill:h.backgroundColor,stroke:h.stroke});function Y(t,e){return s(t)%360+h.orientation}if(h.radialAxis.visible){var X=n.svg.axis().scale(r).ticks(5).tickSize(5);H.call(X).attr({transform:"rotate("+h.radialAxis.orientation+")"}),H.selectAll(".domain").style(B),H.selectAll("g>text").text(function(t,e){return this.textContent+h.radialAxis.ticksSuffix}).style(F).style({"text-anchor":"start"}).attr({x:0,y:0,dx:0,dy:0,transform:function(t,e){return"horizontal"===h.radialAxis.tickOrientation?"rotate("+-h.radialAxis.orientation+") translate("+[0,F["font-size"]]+")":"translate("+[0,F["font-size"]]+")"}}),H.selectAll("g>line").style({stroke:"black"})}var Z=t.select(".angular.axis-group").selectAll("g.angular-tick").data(O),$=Z.enter().append("g").classed("angular-tick",!0);Z.attr({transform:function(t,e){return"rotate("+Y(t)+")"}}).style({display:h.angularAxis.visible?"block":"none"}),Z.exit().remove(),$.append("line").classed("grid-line",!0).classed("major",function(t,e){return e%(h.minorTicks+1)==0}).classed("minor",function(t,e){return!(e%(h.minorTicks+1)==0)}).style(B),$.selectAll(".minor").style({stroke:h.minorTickColor}),Z.select("line.grid-line").attr({x1:h.tickLength?x-h.tickLength:0,x2:x}).style({display:h.angularAxis.gridLinesVisible?"block":"none"}),$.append("text").classed("axis-text",!0).style(F);var J=Z.select("text.axis-text").attr({x:x+h.labelOffset,dy:a+"em",transform:function(t,e){var r=Y(t),n=x+h.labelOffset,i=h.angularAxis.tickOrientation;return"horizontal"==i?"rotate("+-r+" "+n+" 0)":"radial"==i?r<270&&r>90?"rotate(180 "+n+" 0)":null:"rotate("+(r<=180&&r>0?-90:90)+" "+n+" 0)"}}).style({"text-anchor":"middle",display:h.angularAxis.labelsVisible?"block":"none"}).text(function(t,e){return e%(h.minorTicks+1)!=0?"":w?w[t]+h.angularAxis.ticksSuffix:t+h.angularAxis.ticksSuffix}).style(F);h.angularAxis.rewriteTicks&&J.text(function(t,e){return e%(h.minorTicks+1)!=0?"":h.angularAxis.rewriteTicks(this.textContent,e)});var K=n.max(R.selectAll(".angular-tick text")[0].map(function(t,e){return t.getCTM().e+t.getBBox().width}));D.attr({transform:"translate("+[x+K,h.margin.top]+")"});var Q=t.select("g.geometry-group").selectAll("g").size()>0,tt=t.select("g.geometry-group").selectAll("g.geometry").data(p);if(tt.enter().append("g").attr({class:function(t,e){return"geometry geometry"+e}}),tt.exit().remove(),p[0]||Q){var et=[];p.forEach(function(t,e){var n={};n.radialScale=r,n.angularScale=s,n.container=tt.filter(function(t,r){return r==e}),n.geometry=t.geometry,n.orientation=h.orientation,n.direction=h.direction,n.index=e,et.push({data:t,geometryConfig:n})});var rt=n.nest().key(function(t,e){return"undefined"!=typeof t.data.groupId||"unstacked"}).entries(et),nt=[];rt.forEach(function(t,e){"unstacked"===t.key?nt=nt.concat(t.values.map(function(t,e){return[t]})):nt.push(t.values)}),nt.forEach(function(t,e){var r;r=Array.isArray(t)?t[0].geometryConfig.geometry:t.geometryConfig.geometry;var n=t.map(function(t,e){return i(o[r].defaultConfig(),t)});o[r]().config(n)()})}var it,at,ot=t.select(".guides-group"),st=t.select(".tooltips-group"),lt=o.tooltipPanel().config({container:st,fontSize:8})(),ct=o.tooltipPanel().config({container:st,fontSize:8})(),ut=o.tooltipPanel().config({container:st,hasTick:!0})();if(!M){var ft=ot.select("line").attr({x1:0,y1:0,y2:0}).style({stroke:"grey","pointer-events":"none"});R.on("mousemove.angular-guide",function(t,e){var r=o.util.getMousePos(W).angle;ft.attr({x2:-x,transform:"rotate("+r+")"}).style({opacity:.5});var n=(r+180+360-h.orientation)%360;it=s.invert(n);var i=o.util.convertToCartesian(x+12,r+180);lt.text(o.util.round(it)).move([i[0]+_[0],i[1]+_[1]])}).on("mouseout.angular-guide",function(t,e){ot.select("line").style({opacity:0})})}var ht=ot.select("circle").style({stroke:"grey",fill:"none"});R.on("mousemove.radial-guide",function(t,e){var n=o.util.getMousePos(W).radius;ht.attr({r:n}).style({opacity:.5}),at=r.invert(o.util.getMousePos(W).radius);var i=o.util.convertToCartesian(n,h.radialAxis.orientation);ct.text(o.util.round(at)).move([i[0]+_[0],i[1]+_[1]])}).on("mouseout.radial-guide",function(t,e){ht.style({opacity:0}),ut.hide(),lt.hide(),ct.hide()}),t.selectAll(".geometry-group .mark").on("mouseover.tooltip",function(e,r){var i=n.select(this),a=this.style.fill,s="black",l=this.style.opacity||1;if(i.attr({"data-opacity":l}),a&&"none"!==a){i.attr({"data-fill":a}),s=n.hsl(a).darker().toString(),i.style({fill:s,opacity:1});var c={t:o.util.round(e[0]),r:o.util.round(e[1])};M&&(c.t=w[e[0]]);var u="t: "+c.t+", r: "+c.r,f=this.getBoundingClientRect(),h=t.node().getBoundingClientRect(),p=[f.left+f.width/2-V[0]-h.left,f.top+f.height/2-V[1]-h.top];ut.config({color:s}).text(u),ut.move(p)}else a=this.style.stroke||"black",i.attr({"data-stroke":a}),s=n.hsl(a).darker().toString(),i.style({stroke:s,opacity:1})}).on("mousemove.tooltip",function(t,e){if(0!=n.event.which)return!1;n.select(this).attr("data-fill")&&ut.show()}).on("mouseout.tooltip",function(t,e){ut.hide();var r=n.select(this),i=r.attr("data-fill");i?r.style({fill:i,opacity:r.attr("data-opacity")}):r.style({stroke:r.attr("data-stroke"),opacity:r.attr("data-opacity")})})})}(c),this},h.config=function(t){if(!arguments.length)return l;var e=o.util.cloneJson(t);return e.data.forEach(function(t,e){l.data[e]||(l.data[e]={}),i(l.data[e],o.Axis.defaultConfig().data[0]),i(l.data[e],t)}),i(l.layout,o.Axis.defaultConfig().layout),i(l.layout,e.layout),this},h.getLiveConfig=function(){return u},h.getinputConfig=function(){return c},h.radialScale=function(t){return r},h.angularScale=function(t){return s},h.svg=function(){return t},n.rebind(h,f,"on"),h},o.Axis.defaultConfig=function(t,e){return{data:[{t:[1,2,3,4],r:[10,11,12,13],name:"Line1",geometry:"LinePlot",color:null,strokeDash:"solid",strokeColor:null,strokeSize:"1",visibleInLegend:!0,opacity:1}],layout:{defaultColorRange:n.scale.category10().range(),title:null,height:450,width:500,margin:{top:40,right:40,bottom:40,left:40},font:{size:12,color:"gray",outlineColor:"white",family:"Tahoma, sans-serif"},direction:"clockwise",orientation:0,labelOffset:10,radialAxis:{domain:null,orientation:-45,ticksSuffix:"",visible:!0,gridLinesVisible:!0,tickOrientation:"horizontal",rewriteTicks:null},angularAxis:{domain:[0,360],ticksSuffix:"",visible:!0,gridLinesVisible:!0,labelsVisible:!0,tickOrientation:"horizontal",rewriteTicks:null,ticksCount:null,ticksStep:null},minorTicks:0,tickLength:null,tickColor:"silver",minorTickColor:"#eee",backgroundColor:"none",needsEndSpacing:null,showLegend:!0,legend:{reverseOrder:!1},opacity:1}}},o.util={},o.DATAEXTENT="dataExtent",o.AREA="AreaChart",o.LINE="LinePlot",o.DOT="DotPlot",o.BAR="BarChart",o.util._override=function(t,e){for(var r in t)r in e&&(e[r]=t[r])},o.util._extend=function(t,e){for(var r in t)e[r]=t[r]},o.util._rndSnd=function(){return 2*Math.random()-1+(2*Math.random()-1)+(2*Math.random()-1)},o.util.dataFromEquation2=function(t,e){var r=e||6;return n.range(0,360+r,r).map(function(e,r){var n=e*Math.PI/180;return[e,t(n)]})},o.util.dataFromEquation=function(t,e,r){var i=e||6,a=[],o=[];n.range(0,360+i,i).forEach(function(e,r){var n=e*Math.PI/180,i=t(n);a.push(e),o.push(i)});var s={t:a,r:o};return r&&(s.name=r),s},o.util.ensureArray=function(t,e){if("undefined"==typeof t)return null;var r=[].concat(t);return n.range(e).map(function(t,e){return r[e]||r[0]})},o.util.fillArrays=function(t,e,r){return e.forEach(function(e,n){t[e]=o.util.ensureArray(t[e],r)}),t},o.util.cloneJson=function(t){return JSON.parse(JSON.stringify(t))},o.util.validateKeys=function(t,e){"string"==typeof e&&(e=e.split("."));var r=e.shift();return t[r]&&(!e.length||objHasKeys(t[r],e))},o.util.sumArrays=function(t,e){return n.zip(t,e).map(function(t,e){return n.sum(t)})},o.util.arrayLast=function(t){return t[t.length-1]},o.util.arrayEqual=function(t,e){for(var r=Math.max(t.length,e.length,1);r-- >=0&&t[r]===e[r];);return-2===r},o.util.flattenArray=function(t){for(var e=[];!o.util.arrayEqual(e,t);)e=t,t=[].concat.apply([],t);return t},o.util.deduplicate=function(t){return t.filter(function(t,e,r){return r.indexOf(t)==e})},o.util.convertToCartesian=function(t,e){var r=e*Math.PI/180;return[t*Math.cos(r),t*Math.sin(r)]},o.util.round=function(t,e){var r=e||2,n=Math.pow(10,r);return Math.round(t*n)/n},o.util.getMousePos=function(t){var e=n.mouse(t.node()),r=e[0],i=e[1],a={};return a.x=r,a.y=i,a.pos=e,a.angle=180*(Math.atan2(i,r)+Math.PI)/Math.PI,a.radius=Math.sqrt(r*r+i*i),a},o.util.duplicatesCount=function(t){for(var e,r={},n={},i=0,a=t.length;i0)){var l=n.select(this.parentNode).selectAll("path.line").data([0]);l.enter().insert("path"),l.attr({class:"line",d:u(s),transform:function(t,r){return"rotate("+(e.orientation+90)+")"},"pointer-events":"none"}).style({fill:function(t,e){return d.fill(r,i,a)},"fill-opacity":0,stroke:function(t,e){return d.stroke(r,i,a)},"stroke-width":function(t,e){return d["stroke-width"](r,i,a)},"stroke-dasharray":function(t,e){return d["stroke-dasharray"](r,i,a)},opacity:function(t,e){return d.opacity(r,i,a)},display:function(t,e){return d.display(r,i,a)}})}};var f=e.angularScale.range(),h=Math.abs(f[1]-f[0])/o[0].length*Math.PI/180,p=n.svg.arc().startAngle(function(t){return-h/2}).endAngle(function(t){return h/2}).innerRadius(function(t){return e.radialScale(l+(t[2]||0))}).outerRadius(function(t){return e.radialScale(l+(t[2]||0))+e.radialScale(t[1])});c.arc=function(t,r,i){n.select(this).attr({class:"mark arc",d:p,transform:function(t,r){return"rotate("+(e.orientation+s(t[0])+90)+")"}})};var d={fill:function(e,r,n){return t[n].data.color},stroke:function(e,r,n){return t[n].data.strokeColor},"stroke-width":function(e,r,n){return t[n].data.strokeSize+"px"},"stroke-dasharray":function(e,n,i){return r[t[i].data.strokeDash]},opacity:function(e,r,n){return t[n].data.opacity},display:function(e,r,n){return"undefined"==typeof t[n].data.visible||t[n].data.visible?"block":"none"}},m=n.select(this).selectAll("g.layer").data(o);m.enter().append("g").attr({class:"layer"});var g=m.selectAll("path.mark").data(function(t,e){return t});g.enter().append("path").attr({class:"mark"}),g.style(d).each(c[e.geometryType]),g.exit().remove(),m.exit().remove()})}return a.config=function(e){return arguments.length?(e.forEach(function(e,r){t[r]||(t[r]={}),i(t[r],o.PolyChart.defaultConfig()),i(t[r],e)}),this):t},a.getColorScale=function(){},n.rebind(a,e,"on"),a},o.PolyChart.defaultConfig=function(){return{data:{name:"geom1",t:[[1,2,3,4]],r:[[1,2,3,4]],dotType:"circle",dotSize:64,dotVisible:!1,barWidth:20,color:"#ffa500",strokeSize:1,strokeColor:"silver",strokeDash:"solid",opacity:1,index:0,visible:!0,visibleInLegend:!0},geometryConfig:{geometry:"LinePlot",geometryType:"arc",direction:"clockwise",orientation:0,container:"body",radialScale:null,angularScale:null,colorScale:n.scale.category20()}}},o.BarChart=function(){return o.PolyChart()},o.BarChart.defaultConfig=function(){return{geometryConfig:{geometryType:"bar"}}},o.AreaChart=function(){return o.PolyChart()},o.AreaChart.defaultConfig=function(){return{geometryConfig:{geometryType:"arc"}}},o.DotPlot=function(){return o.PolyChart()},o.DotPlot.defaultConfig=function(){return{geometryConfig:{geometryType:"dot",dotType:"circle"}}},o.LinePlot=function(){return o.PolyChart()},o.LinePlot.defaultConfig=function(){return{geometryConfig:{geometryType:"line"}}},o.Legend=function(){var t=o.Legend.defaultConfig(),e=n.dispatch("hover");function r(){var e=t.legendConfig,a=t.data.map(function(t,r){return[].concat(t).map(function(t,n){var a=i({},e.elements[r]);return a.name=t,a.color=[].concat(e.elements[r].color)[n],a})}),o=n.merge(a);o=o.filter(function(t,r){return e.elements[r]&&(e.elements[r].visibleInLegend||"undefined"==typeof e.elements[r].visibleInLegend)}),e.reverseOrder&&(o=o.reverse());var s=e.container;("string"==typeof s||s.nodeName)&&(s=n.select(s));var l=o.map(function(t,e){return t.color}),c=e.fontSize,u=null==e.isContinuous?"number"==typeof o[0]:e.isContinuous,f=u?e.height:c*o.length,h=s.classed("legend-group",!0).selectAll("svg").data([0]),p=h.enter().append("svg").attr({width:300,height:f+c,xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"});p.append("g").classed("legend-axis",!0),p.append("g").classed("legend-marks",!0);var d=n.range(o.length),m=n.scale[u?"linear":"ordinal"]().domain(d).range(l),g=n.scale[u?"linear":"ordinal"]().domain(d)[u?"range":"rangePoints"]([0,f]);if(u){var v=h.select(".legend-marks").append("defs").append("linearGradient").attr({id:"grad1",x1:"0%",y1:"0%",x2:"0%",y2:"100%"}).selectAll("stop").data(l);v.enter().append("stop"),v.attr({offset:function(t,e){return e/(l.length-1)*100+"%"}}).style({"stop-color":function(t,e){return t}}),h.append("rect").classed("legend-mark",!0).attr({height:e.height,width:e.colorBandWidth,fill:"url(#grad1)"})}else{var y=h.select(".legend-marks").selectAll("path.legend-mark").data(o);y.enter().append("path").classed("legend-mark",!0),y.attr({transform:function(t,e){return"translate("+[c/2,g(e)+c/2]+")"},d:function(t,e){var r,i,a,o=t.symbol;return a=3*(i=c),"line"===(r=o)?"M"+[[-i/2,-i/12],[i/2,-i/12],[i/2,i/12],[-i/2,i/12]]+"Z":-1!=n.svg.symbolTypes.indexOf(r)?n.svg.symbol().type(r).size(a)():n.svg.symbol().type("square").size(a)()},fill:function(t,e){return m(e)}}),y.exit().remove()}var x=n.svg.axis().scale(g).orient("right"),b=h.select("g.legend-axis").attr({transform:"translate("+[u?e.colorBandWidth:c,c/2]+")"}).call(x);return b.selectAll(".domain").style({fill:"none",stroke:"none"}),b.selectAll("line").style({fill:"none",stroke:u?e.textColor:"none"}),b.selectAll("text").style({fill:e.textColor,"font-size":e.fontSize}).text(function(t,e){return o[e].name}),r}return r.config=function(e){return arguments.length?(i(t,e),this):t},n.rebind(r,e,"on"),r},o.Legend.defaultConfig=function(t,e){return{data:["a","b","c"],legendConfig:{elements:[{symbol:"line",color:"red"},{symbol:"square",color:"yellow"},{symbol:"diamond",color:"limegreen"}],height:150,colorBandWidth:30,fontSize:12,container:"body",isContinuous:null,textColor:"grey",reverseOrder:!1}}},o.tooltipPanel=function(){var t,e,r,a={container:null,hasTick:!1,fontSize:12,color:"white",padding:5},s="tooltip-"+o.tooltipPanel.uid++,l=10,c=function(){var n=(t=a.container.selectAll("g."+s).data([0])).enter().append("g").classed(s,!0).style({"pointer-events":"none",display:"none"});return r=n.append("path").style({fill:"white","fill-opacity":.9}).attr({d:"M0 0"}),e=n.append("text").attr({dx:a.padding+l,dy:.3*+a.fontSize}),c};return c.text=function(i){var o=n.hsl(a.color).l,s=o>=.5?"#aaa":"white",u=o>=.5?"black":"white",f=i||"";e.style({fill:u,"font-size":a.fontSize+"px"}).text(f);var h=a.padding,p=e.node().getBBox(),d={fill:a.color,stroke:s,"stroke-width":"2px"},m=p.width+2*h+l,g=p.height+2*h;return r.attr({d:"M"+[[l,-g/2],[l,-g/4],[a.hasTick?0:l,0],[l,g/4],[l,g/2],[m,g/2],[m,-g/2]].join("L")+"Z"}).style(d),t.attr({transform:"translate("+[l,-g/2+2*h]+")"}),t.style({display:"block"}),c},c.move=function(e){if(t)return t.attr({transform:"translate("+[e[0],e[1]]+")"}).style({display:"block"}),c},c.hide=function(){if(t)return t.style({display:"none"}),c},c.show=function(){if(t)return t.style({display:"block"}),c},c.config=function(t){return i(a,t),c},c},o.tooltipPanel.uid=1,o.adapter={},o.adapter.plotly=function(){var t={convert:function(t,e){var r={};if(t.data&&(r.data=t.data.map(function(t,r){var n=i({},t);return[[n,["marker","color"],["color"]],[n,["marker","opacity"],["opacity"]],[n,["marker","line","color"],["strokeColor"]],[n,["marker","line","dash"],["strokeDash"]],[n,["marker","line","width"],["strokeSize"]],[n,["marker","symbol"],["dotType"]],[n,["marker","size"],["dotSize"]],[n,["marker","barWidth"],["barWidth"]],[n,["line","interpolation"],["lineInterpolation"]],[n,["showlegend"],["visibleInLegend"]]].forEach(function(t,r){o.util.translator.apply(null,t.concat(e))}),e||delete n.marker,e&&delete n.groupId,e?("LinePlot"===n.geometry?(n.type="scatter",!0===n.dotVisible?(delete n.dotVisible,n.mode="lines+markers"):n.mode="lines"):"DotPlot"===n.geometry?(n.type="scatter",n.mode="markers"):"AreaChart"===n.geometry?n.type="area":"BarChart"===n.geometry&&(n.type="bar"),delete n.geometry):("scatter"===n.type?"lines"===n.mode?n.geometry="LinePlot":"markers"===n.mode?n.geometry="DotPlot":"lines+markers"===n.mode&&(n.geometry="LinePlot",n.dotVisible=!0):"area"===n.type?n.geometry="AreaChart":"bar"===n.type&&(n.geometry="BarChart"),delete n.mode,delete n.type),n}),!e&&t.layout&&"stack"===t.layout.barmode)){var a=o.util.duplicates(r.data.map(function(t,e){return t.geometry}));r.data.forEach(function(t,e){var n=a.indexOf(t.geometry);-1!=n&&(r.data[e].groupId=n)})}if(t.layout){var s=i({},t.layout);if([[s,["plot_bgcolor"],["backgroundColor"]],[s,["showlegend"],["showLegend"]],[s,["radialaxis"],["radialAxis"]],[s,["angularaxis"],["angularAxis"]],[s.angularaxis,["showline"],["gridLinesVisible"]],[s.angularaxis,["showticklabels"],["labelsVisible"]],[s.angularaxis,["nticks"],["ticksCount"]],[s.angularaxis,["tickorientation"],["tickOrientation"]],[s.angularaxis,["ticksuffix"],["ticksSuffix"]],[s.angularaxis,["range"],["domain"]],[s.angularaxis,["endpadding"],["endPadding"]],[s.radialaxis,["showline"],["gridLinesVisible"]],[s.radialaxis,["tickorientation"],["tickOrientation"]],[s.radialaxis,["ticksuffix"],["ticksSuffix"]],[s.radialaxis,["range"],["domain"]],[s.angularAxis,["showline"],["gridLinesVisible"]],[s.angularAxis,["showticklabels"],["labelsVisible"]],[s.angularAxis,["nticks"],["ticksCount"]],[s.angularAxis,["tickorientation"],["tickOrientation"]],[s.angularAxis,["ticksuffix"],["ticksSuffix"]],[s.angularAxis,["range"],["domain"]],[s.angularAxis,["endpadding"],["endPadding"]],[s.radialAxis,["showline"],["gridLinesVisible"]],[s.radialAxis,["tickorientation"],["tickOrientation"]],[s.radialAxis,["ticksuffix"],["ticksSuffix"]],[s.radialAxis,["range"],["domain"]],[s.font,["outlinecolor"],["outlineColor"]],[s.legend,["traceorder"],["reverseOrder"]],[s,["labeloffset"],["labelOffset"]],[s,["defaultcolorrange"],["defaultColorRange"]]].forEach(function(t,r){o.util.translator.apply(null,t.concat(e))}),e?("undefined"!=typeof s.tickLength&&(s.angularaxis.ticklen=s.tickLength,delete s.tickLength),s.tickColor&&(s.angularaxis.tickcolor=s.tickColor,delete s.tickColor)):(s.angularAxis&&"undefined"!=typeof s.angularAxis.ticklen&&(s.tickLength=s.angularAxis.ticklen),s.angularAxis&&"undefined"!=typeof s.angularAxis.tickcolor&&(s.tickColor=s.angularAxis.tickcolor)),s.legend&&"boolean"!=typeof s.legend.reverseOrder&&(s.legend.reverseOrder="normal"!=s.legend.reverseOrder),s.legend&&"boolean"==typeof s.legend.traceorder&&(s.legend.traceorder=s.legend.traceorder?"reversed":"normal",delete s.legend.reverseOrder),s.margin&&"undefined"!=typeof s.margin.t){var l=["t","r","b","l","pad"],c=["top","right","bottom","left","pad"],u={};n.entries(s.margin).forEach(function(t,e){u[c[l.indexOf(t.key)]]=t.value}),s.margin=u}e&&(delete s.needsEndSpacing,delete s.minorTickColor,delete s.minorTicks,delete s.angularaxis.ticksCount,delete s.angularaxis.ticksCount,delete s.angularaxis.ticksStep,delete s.angularaxis.rewriteTicks,delete s.angularaxis.nticks,delete s.radialaxis.ticksCount,delete s.radialaxis.ticksCount,delete s.radialaxis.ticksStep,delete s.radialaxis.rewriteTicks,delete s.radialaxis.nticks),r.layout=s}return r}};return t}},{"../../../constants/alignment":668,"../../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],818:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../../lib"),a=t("../../../components/color"),o=t("./micropolar"),s=t("./undo_manager"),l=i.extendDeepAll,c=e.exports={};c.framework=function(t){var e,r,i,a,u,f=new s;function h(r,s){return s&&(u=s),n.select(n.select(u).node().parentNode).selectAll(".svg-container>*:not(.chart-root)").remove(),e=e?l(e,r):r,i||(i=o.Axis()),a=o.adapter.plotly().convert(e),i.config(a).render(u),t.data=e.data,t.layout=e.layout,c.fillLayout(t),e}return h.isPolar=!0,h.svg=function(){return i.svg()},h.getConfig=function(){return e},h.getLiveConfig=function(){return o.adapter.plotly().convert(i.getLiveConfig(),!0)},h.getLiveScales=function(){return{t:i.angularScale(),r:i.radialScale()}},h.setUndoPoint=function(){var t,n,i=this,a=o.util.cloneJson(e);t=a,n=r,f.add({undo:function(){n&&i(n)},redo:function(){i(t)}}),r=o.util.cloneJson(a)},h.undo=function(){f.undo()},h.redo=function(){f.redo()},h},c.fillLayout=function(t){var e=n.select(t).selectAll(".plot-container"),r=e.selectAll(".svg-container"),i=t.framework&&t.framework.svg&&t.framework.svg(),o={width:800,height:600,paper_bgcolor:a.background,_container:e,_paperdiv:r,_paper:i};t._fullLayout=l(o,t.layout)}},{"../../../components/color":570,"../../../lib":696,"./micropolar":817,"./undo_manager":819,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],819:[function(t,e,r){"use strict";e.exports=function(){var t,e=[],r=-1,n=!1;function i(t,e){return t?(n=!0,t[e](),n=!1,this):this}return{add:function(t){return n?this:(e.splice(r+1,e.length-r),e.push(t),r=e.length-1,this)},setCallback:function(e){t=e},undo:function(){var n=e[r];return n?(i(n,"undo"),r-=1,t&&t(n.undo),this):this},redo:function(){var n=e[r+1];return n?(i(n,"redo"),r+=1,t&&t(n.redo),this):this},clear:function(){e=[],r=-1},hasUndo:function(){return-1!==r},hasRedo:function(){return r0?1:-1}function N(t){return F(Math.cos(t))}function j(t){return F(Math.sin(t))}e.exports=function(t,e){return new z(t,e)},O.plot=function(t,e){var r=e[this.id];this._hasClipOnAxisFalse=!1;for(var n=0;n=90||s>90&&l>=450?1:u<=0&&h<=0?0:Math.max(u,h);e=s<=180&&l>=180||s>180&&l>=540?-1:c>=0&&f>=0?0:Math.min(c,f);r=s<=270&&l>=270||s>270&&l>=630?-1:u>=0&&h>=0?0:Math.min(u,h);n=l>=360?1:c<=0&&f<=0?0:Math.max(c,f);return[e,r,n,i]}(h),x=y[2]-y[0],b=y[3]-y[1],_=f/u,w=Math.abs(b/x);_>w?(p=u,v=(f-(d=u*w))/n.h/2,m=[o[0],o[1]],g=[c[0]+v,c[1]-v]):(d=f,v=(u-(p=f/w))/n.w/2,m=[o[0]+v,o[1]-v],g=[c[0],c[1]]),this.xLength2=p,this.yLength2=d,this.xDomain2=m,this.yDomain2=g;var k=this.xOffset2=n.l+n.w*m[0],M=this.yOffset2=n.t+n.h*(1-g[1]),A=this.radius=p/x,T=this.innerRadius=e.hole*A,S=this.cx=k-A*y[0],L=this.cy=M+A*y[3],z=this.cxx=S-k,O=this.cyy=L-M;this.radialAxis=this.mockAxis(t,e,i,{_axislayer:r["radial-axis"],_gridlayer:r["radial-grid"],_id:"x",side:{counterclockwise:"top",clockwise:"bottom"}[i.side],domain:[T/n.w,A/n.w]}),this.angularAxis=this.mockAxis(t,e,a,{_axislayer:r["angular-axis"],_gridlayer:r["angular-grid"],side:"right",domain:[0,Math.PI],autorange:!1}),this.doAutoRange(t,e),this.updateAngularAxis(t,e),this.updateRadialAxis(t,e),this.updateRadialAxisTitle(t,e),this.xaxis=this.mockCartesianAxis(t,e,{_id:"x",domain:m}),this.yaxis=this.mockCartesianAxis(t,e,{_id:"y",domain:g});var I=this.pathSubplot();this.clipPaths.forTraces.select("path").attr("d",I).attr("transform",R(z,O)),r.frontplot.attr("transform",R(k,M)).call(l.setClipUrl,this._hasClipOnAxisFalse?null:this.clipIds.forTraces),r.bg.attr("d",I).attr("transform",R(S,L)).call(s.fill,e.bgcolor),this.framework.selectAll(".crisp").classed("crisp",0)},O.mockAxis=function(t,e,r,n){var i=o.extendFlat({anchor:"free",position:0,_pos:0,_counteraxis:!0,automargin:!1},r,n);return f(i,e,t),i},O.mockCartesianAxis=function(t,e,r){var n=this,i=r._id,a=o.extendFlat({type:"linear"},r);u(a,t);var s={x:[0,2],y:[1,3]};return a.setRange=function(){var t=n.sectorBBox,r=s[i],o=n.radialAxis._rl,l=(o[1]-o[0])/(1-e.hole);a.range=[t[r[0]]*l,t[r[1]]*l]},a.isPtWithinRange="x"===i?function(t){return n.isPtInside(t)}:function(){return!0},a.setRange(),a.setScale(),a},O.doAutoRange=function(t,e){var r=this.gd,n=this.radialAxis,i=e.radialaxis;n.setScale(),h(r,n);var a=n.range;i.range=a.slice(),i._input.range=a.slice(),n._rl=[n.r2l(a[0],null,"gregorian"),n.r2l(a[1],null,"gregorian")]},O.updateRadialAxis=function(t,e){var r=this,n=r.gd,i=r.layers,a=r.radius,o=r.innerRadius,l=r.cx,c=r.cy,u=e.radialaxis,f=E(e.sector[0],360),h=r.radialAxis,d=o90&&f<=270&&(h.tickangle=180),h._transfn=function(t){return"translate("+(h.l2p(t.x)+o)+",0)"},h._gridpath=function(t){return r.pathArc(h.r2p(t.x)+o)};var m=I(u);r.radialTickLayout!==m&&(i["radial-axis"].selectAll(".xtick").remove(),r.radialTickLayout=m),d&&(h.setScale(),p(n,h,!0));var g=r.radialAxisAngle=r.vangles?L(P(C(u.angle),r.vangles)):u.angle,v=R(l,c)+B(-g);D(i["radial-axis"],d&&(u.showticklabels||u.ticks),{transform:v}),D(i["radial-grid"],d&&u.showgrid,{transform:R(l,c)}).selectAll("path").attr("transform",null),D(i["radial-line"].select("line"),d&&u.showline,{x1:o,y1:0,x2:a,y2:0,transform:v}).attr("stroke-width",u.linewidth).call(s.stroke,u.linecolor)},O.updateRadialAxisTitle=function(t,e,r){var n=this.gd,i=this.radius,a=this.cx,o=this.cy,s=e.radialaxis,c=this.id+"title",u=void 0!==r?r:this.radialAxisAngle,f=C(u),h=Math.cos(f),p=Math.sin(f),d=0;if(s.title){var m=l.bBox(this.layers["radial-axis"].node()).height,g=s.titlefont.size;d="counterclockwise"===s.side?-m-.4*g:m+.8*g}this.layers["radial-axis-title"]=v.draw(n,c,{propContainer:s,propName:this.id+".radialaxis.title",placeholder:S(n,"Click to enter radial axis title"),attributes:{x:a+i/2*h+d*p,y:o-i/2*p+d*h,"text-anchor":"middle"},transform:{rotate:-u}})},O.updateAngularAxis=function(t,e){var r=this,i=r.gd,a=r.layers,l=r.radius,c=r.innerRadius,u=r.cx,f=r.cy,h=e.angularaxis,d=r.angularAxis;r.fillViewInitialKey("angularaxis.rotation",h.rotation),d.setGeometry();var m=function(t){return d.t2g(t.x)};"linear"===d.type&&"radians"===d.thetaunit&&(d.tick0=L(d.tick0),d.dtick=L(d.dtick)),"category"===d.type&&(d._tickFilter=function(t){return o.isAngleInsideSector(m(t),r.sectorInRad)}),d._transfn=function(t){var e=n.select(this),r=e&&e.node();if(r&&e.classed("angularaxisgrid"))return"";var i=m(t),a=R(u+l*Math.cos(i),f-l*Math.sin(i));return r&&e.classed("ticks")&&(a+=B(-L(i))),a},d._gridpath=function(t){var e=m(t),r=Math.cos(e),n=Math.sin(e);return"M"+[u+c*r,f-c*n]+"L"+[u+l*r,f-l*n]};var g="outside"!==h.ticks?.7:.5;d._labelx=function(t){var e=m(t),r=d._labelStandoff,n=d._pad;return(0===j(e)?0:Math.cos(e)*(r+n+g*t.fontSize))+N(e)*(t.dx+r+n)},d._labely=function(t){var e=m(t),r=d._labelStandoff,n=d._labelShift,i=d._pad;return t.dy+t.fontSize*M-n+-Math.sin(e)*(r+i+g*t.fontSize)},d._labelanchor=function(t,e){var r=m(e);return 0===j(r)?N(r)>0?"start":"end":"middle"};var v,y=I(h);r.angularTickLayout!==y&&(a["angular-axis"].selectAll("."+d._id+"tick").remove(),r.angularTickLayout=y),d.setScale(),p(i,d,!0),"linear"===e.gridshape?(v=d._vals.map(m),o.angleDelta(v[0],v[1])<0&&(v=v.slice().reverse())):v=null,r.vangles=v,D(a["angular-line"].select("path"),h.showline,{d:r.pathSubplot(),transform:R(u,f)}).attr("stroke-width",h.linewidth).call(s.stroke,h.linecolor)},O.updateFx=function(t,e){this.gd._context.staticPlot||(this.updateAngularDrag(t),this.updateRadialDrag(t,e,0),this.updateRadialDrag(t,e,1),this.updateMainDrag(t))},O.updateMainDrag=function(t){var e=this,r=e.gd,o=e.layers,s=t._zoomlayer,l=A.MINZOOM,c=A.OFFEDGE,u=e.radius,f=e.innerRadius,h=e.cx,p=e.cy,v=e.cxx,_=e.cyy,w=e.sectorInRad,k=e.vangles,M=e.radialAxis,S=T.clampTiny,E=T.findXYatLength,C=T.findEnclosingVertexAngles,L=A.cornerHalfWidth,z=A.cornerLen/2,O=d.makeDragger(o,"path","maindrag","crosshair");n.select(O).attr("d",e.pathSubplot()).attr("transform",R(h,p));var I,P,D,B,F,N,j,V,U,q={element:O,gd:r,subplot:e.id,plotinfo:{id:e.id,xaxis:e.xaxis,yaxis:e.yaxis},xaxes:[e.xaxis],yaxes:[e.yaxis]};function H(t,e){return Math.sqrt(t*t+e*e)}function G(t,e){return H(t-v,e-_)}function W(t,e){return Math.atan2(_-e,t-v)}function Y(t,e){return[t*Math.cos(e),t*Math.sin(-e)]}function X(t,r){if(0===t)return e.pathSector(2*L);var n=z/t,i=r-n,a=r+n,o=Math.max(0,Math.min(t,u)),s=o-L,l=o+L;return"M"+Y(s,i)+"A"+[s,s]+" 0,0,0 "+Y(s,a)+"L"+Y(l,a)+"A"+[l,l]+" 0,0,1 "+Y(l,i)+"Z"}function Z(t,r,n){if(0===t)return e.pathSector(2*L);var i,a,o=Y(t,r),s=Y(t,n),l=S((o[0]+s[0])/2),c=S((o[1]+s[1])/2);if(l&&c){var u=c/l,f=-1/u,h=E(L,u,l,c);i=E(z,f,h[0][0],h[0][1]),a=E(z,f,h[1][0],h[1][1])}else{var p,d;c?(p=z,d=L):(p=L,d=z),i=[[l-p,c-d],[l+p,c-d]],a=[[l-p,c+d],[l+p,c+d]]}return"M"+i.join("L")+"L"+a.reverse().join("L")+"Z"}function $(t,e){return e=Math.max(Math.min(e,u),f),tl?(t-1&&1===t&&x(n,r,[e.xaxis],[e.yaxis],e.id,q),i.indexOf("event")>-1&&g.click(r,n,e.id)}q.prepFn=function(t,n,a){var o=r._fullLayout.dragmode,l=O.getBoundingClientRect();if(I=n-l.left,P=a-l.top,k){var c=T.findPolygonOffset(u,w[0],w[1],k);I+=v+c[0],P+=_+c[1]}switch(o){case"zoom":q.moveFn=k?tt:K,q.clickFn=rt,q.doneFn=et,function(){D=null,B=null,F=e.pathSubplot(),N=!1;var t=r._fullLayout[e.id];j=i(t.bgcolor).getLuminance(),(V=d.makeZoombox(s,j,h,p,F)).attr("fill-rule","evenodd"),U=d.makeCorners(s,h,p),b(s)}();break;case"select":case"lasso":y(t,n,a,q,o)}},O.onmousemove=function(t){g.hover(r,t,e.id),r._fullLayout._lasthover=O,r._fullLayout._hoversubplot=e.id},O.onmouseout=function(t){r._dragging||m.unhover(r,t)},m.init(q)},O.updateRadialDrag=function(t,e,r){var i=this,s=i.gd,l=i.layers,c=i.radius,u=i.innerRadius,f=i.cx,h=i.cy,g=i.radialAxis,v=A.radialDragBoxSize,y=v/2;if(g.visible){var x,_,M,T=C(i.radialAxisAngle),S=g._rl,E=S[0],z=S[1],O=S[r],I=.75*(S[1]-S[0])/(1-e.hole)/c;r?(x=f+(c+y)*Math.cos(T),_=h-(c+y)*Math.sin(T),M="radialdrag"):(x=f+(u-y)*Math.cos(T),_=h-(u-y)*Math.sin(T),M="radialdrag-inner");var F,N,j,V=d.makeRectDragger(l,M,"crosshair",-y,-y,v,v),U={element:V,gd:s};D(n.select(V),g.visible&&u0==(r?j>E:jn?function(t){return t<=0}:function(t){return t>=0};t.c2g=function(r){var n=t.c2l(r)-e;return(s(n)?n:0)+o},t.g2c=function(r){return t.l2c(r+e-o)},t.g2p=function(t){return t*a},t.c2p=function(e){return t.g2p(t.c2g(e))}}}(t,e);break;case"angularaxis":!function(t,e){var r=t.type;if("linear"===r){var i=t.d2c,s=t.c2d;t.d2c=function(t,e){return function(t,e){return"degrees"===e?a(t):t}(i(t),e)},t.c2d=function(t,e){return s(function(t,e){return"degrees"===e?o(t):t}(t,e))}}t.makeCalcdata=function(e,i){var a,o,s=e[i],l=e._length,c=function(r){return t.d2c(r,e.thetaunit)};if(s){if(n.isTypedArray(s)&&"linear"===r){if(l===s.length)return s;if(s.subarray)return s.subarray(0,l)}for(a=new Array(l),o=0;o=u&&(p.min=0,m.min=0,g.min=0,t.aaxis&&delete t.aaxis.min,t.baxis&&delete t.baxis.min,t.caxis&&delete t.caxis.min)}function d(t,e,r,n){var i=f[e._name];function o(r,n){return a.coerce(t,e,i,r,n)}o("uirevision",n.uirevision),e.type="linear";var h=o("color"),p=h!==i.color.dflt?h:r.font.color,d=e._name.charAt(0).toUpperCase(),m="Component "+d,g=o("title",m);e._hovertitle=g===m?g:d,a.coerceFont(o,"titlefont",{family:r.font.family,size:Math.round(1.2*r.font.size),color:p}),o("min"),c(t,e,o,"linear"),s(t,e,o,"linear",{}),l(t,e,o,{outerTicks:!0}),o("showticklabels")&&(a.coerceFont(o,"tickfont",{family:r.font.family,size:r.font.size,color:p}),o("tickangle"),o("tickformat")),u(t,e,o,{dfltColor:h,bgColor:r.bgColor,blend:60,showLine:!0,showGrid:!0,noZeroLine:!0,attributes:i}),o("hoverformat"),o("layer")}e.exports=function(t,e,r){o(t,e,r,{type:"ternary",attributes:f,handleDefaults:p,font:e.font,paper_bgcolor:e.paper_bgcolor})}},{"../../components/color":570,"../../lib":696,"../../plot_api/plot_template":734,"../cartesian/line_grid_defaults":759,"../cartesian/tick_label_defaults":764,"../cartesian/tick_mark_defaults":765,"../cartesian/tick_value_defaults":766,"../subplot_defaults":822,"./layout_attributes":824}],826:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("tinycolor2"),a=t("../../registry"),o=t("../../lib"),s=o._,l=t("../../components/color"),c=t("../../components/drawing"),u=t("../cartesian/set_convert"),f=t("../../lib/extend").extendFlat,h=t("../plots"),p=t("../cartesian/axes"),d=t("../../components/dragelement"),m=t("../../components/fx"),g=t("../../components/titles"),v=t("../cartesian/select").prepSelect,y=t("../cartesian/select").selectOnClick,x=t("../cartesian/select").clearSelect,b=t("../cartesian/constants");function _(t,e){this.id=t.id,this.graphDiv=t.graphDiv,this.init(e),this.makeFramework(e),this.aTickLayout=null,this.bTickLayout=null,this.cTickLayout=null}e.exports=_;var w=_.prototype;w.init=function(t){this.container=t._ternarylayer,this.defs=t._defs,this.layoutId=t._uid,this.traceHash={},this.layers={}},w.plot=function(t,e){var r=e[this.id],n=e._size;this._hasClipOnAxisFalse=!1;for(var i=0;ik*x?i=(a=x)*k:a=(i=y)/k,o=g*i/y,s=v*a/x,r=e.l+e.w*d-i/2,n=e.t+e.h*(1-m)-a/2,h.x0=r,h.y0=n,h.w=i,h.h=a,h.sum=b,h.xaxis={type:"linear",range:[_+2*M-b,b-_-2*w],domain:[d-o/2,d+o/2],_id:"x"},u(h.xaxis,h.graphDiv._fullLayout),h.xaxis.setScale(),h.xaxis.isPtWithinRange=function(t){return t.a>=h.aaxis.range[0]&&t.a<=h.aaxis.range[1]&&t.b>=h.baxis.range[1]&&t.b<=h.baxis.range[0]&&t.c>=h.caxis.range[1]&&t.c<=h.caxis.range[0]},h.yaxis={type:"linear",range:[_,b-w-M],domain:[m-s/2,m+s/2],_id:"y"},u(h.yaxis,h.graphDiv._fullLayout),h.yaxis.setScale(),h.yaxis.isPtWithinRange=function(){return!0};var A=h.yaxis.domain[0],T=h.aaxis=f({},t.aaxis,{visible:!0,range:[_,b-w-M],side:"left",_counterangle:30,tickangle:(+t.aaxis.tickangle||0)-30,domain:[A,A+s*k],_axislayer:h.layers.aaxis,_gridlayer:h.layers.agrid,anchor:"free",position:0,_pos:0,_id:"y",_length:i,_gridpath:"M0,0l"+a+",-"+i/2,automargin:!1});u(T,h.graphDiv._fullLayout),T.setScale();var S=h.baxis=f({},t.baxis,{visible:!0,range:[b-_-M,w],side:"bottom",_counterangle:30,domain:h.xaxis.domain,_axislayer:h.layers.baxis,_gridlayer:h.layers.bgrid,_counteraxis:h.aaxis,anchor:"free",position:0,_pos:0,_id:"x",_length:i,_gridpath:"M0,0l-"+i/2+",-"+a,automargin:!1});u(S,h.graphDiv._fullLayout),S.setScale(),T._counteraxis=S;var E=h.caxis=f({},t.caxis,{visible:!0,range:[b-_-w,M],side:"right",_counterangle:30,tickangle:(+t.caxis.tickangle||0)+30,domain:[A,A+s*k],_axislayer:h.layers.caxis,_gridlayer:h.layers.cgrid,_counteraxis:h.baxis,anchor:"free",position:0,_pos:0,_id:"y",_length:i,_gridpath:"M0,0l-"+a+","+i/2,automargin:!1});u(E,h.graphDiv._fullLayout),E.setScale();var C="M"+r+","+(n+a)+"h"+i+"l-"+i/2+",-"+a+"Z";h.clipDef.select("path").attr("d",C),h.layers.plotbg.select("path").attr("d",C);var L="M0,"+a+"h"+i+"l-"+i/2+",-"+a+"Z";h.clipDefRelative.select("path").attr("d",L);var z="translate("+r+","+n+")";h.plotContainer.selectAll(".scatterlayer,.maplayer").attr("transform",z),h.clipDefRelative.select("path").attr("transform",null);var O="translate("+(r-S._offset)+","+(n+a)+")";h.layers.baxis.attr("transform",O),h.layers.bgrid.attr("transform",O);var I="translate("+(r+i/2)+","+n+")rotate(30)translate(0,"+-T._offset+")";h.layers.aaxis.attr("transform",I),h.layers.agrid.attr("transform",I);var P="translate("+(r+i/2)+","+n+")rotate(-30)translate(0,"+-E._offset+")";h.layers.caxis.attr("transform",P),h.layers.cgrid.attr("transform",P),h.drawAxes(!0),h.plotContainer.selectAll(".crisp").classed("crisp",!1),h.layers.aline.select("path").attr("d",T.showline?"M"+r+","+(n+a)+"l"+i/2+",-"+a:"M0,0").call(l.stroke,T.linecolor||"#000").style("stroke-width",(T.linewidth||0)+"px"),h.layers.bline.select("path").attr("d",S.showline?"M"+r+","+(n+a)+"h"+i:"M0,0").call(l.stroke,S.linecolor||"#000").style("stroke-width",(S.linewidth||0)+"px"),h.layers.cline.select("path").attr("d",E.showline?"M"+(r+i/2)+","+n+"l"+i/2+","+a:"M0,0").call(l.stroke,E.linecolor||"#000").style("stroke-width",(E.linewidth||0)+"px"),h.graphDiv._context.staticPlot||h.initInteractions(),c.setClipUrl(h.layers.frontplot,h._hasClipOnAxisFalse?null:h.clipId)},w.drawAxes=function(t){var e,r=this.graphDiv,n=this.id.substr(7)+"title",i=this.layers,a=this.aaxis,o=this.baxis,l=this.caxis;if(e=M(a),this.aTickLayout!==e&&(i.aaxis.selectAll(".ytick").remove(),this.aTickLayout=e),e=M(o),this.bTickLayout!==e&&(i.baxis.selectAll(".xtick").remove(),this.bTickLayout=e),e=M(l),this.cTickLayout!==e&&(i.caxis.selectAll(".ytick").remove(),this.cTickLayout=e),p.doTicksSingle(r,a,!0),p.doTicksSingle(r,o,!0),p.doTicksSingle(r,l,!0),t){var c=Math.max(a.showticklabels?a.tickfont.size/2:0,(l.showticklabels?.75*l.tickfont.size:0)+("outside"===l.ticks?.87*l.ticklen:0));this.layers["a-title"]=g.draw(r,"a"+n,{propContainer:a,propName:this.id+".aaxis.title",placeholder:s(r,"Click to enter Component A title"),attributes:{x:this.x0+this.w/2,y:this.y0-a.titlefont.size/3-c,"text-anchor":"middle"}});var u=(o.showticklabels?o.tickfont.size:0)+("outside"===o.ticks?o.ticklen:0)+3;this.layers["b-title"]=g.draw(r,"b"+n,{propContainer:o,propName:this.id+".baxis.title",placeholder:s(r,"Click to enter Component B title"),attributes:{x:this.x0-u,y:this.y0+this.h+.83*o.titlefont.size+u,"text-anchor":"middle"}}),this.layers["c-title"]=g.draw(r,"c"+n,{propContainer:l,propName:this.id+".caxis.title",placeholder:s(r,"Click to enter Component C title"),attributes:{x:this.x0+this.w+u,y:this.y0+this.h+.83*l.titlefont.size+u,"text-anchor":"middle"}})}};var A=b.MINZOOM/2+.87,T="m-0.87,.5h"+A+"v3h-"+(A+5.2)+"l"+(A/2+2.6)+",-"+(.87*A+4.5)+"l2.6,1.5l-"+A/2+","+.87*A+"Z",S="m0.87,.5h-"+A+"v3h"+(A+5.2)+"l-"+(A/2+2.6)+",-"+(.87*A+4.5)+"l-2.6,1.5l"+A/2+","+.87*A+"Z",E="m0,1l"+A/2+","+.87*A+"l2.6,-1.5l-"+(A/2+2.6)+",-"+(.87*A+4.5)+"l-"+(A/2+2.6)+","+(.87*A+4.5)+"l2.6,1.5l"+A/2+",-"+.87*A+"Z",C="m0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z",L=!0;function z(t){n.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}w.initInteractions=function(){var t,e,r,n,u,f,h,p,g,_,w=this,M=w.layers.plotbg.select("path").node(),A=w.graphDiv,O=A._fullLayout._zoomlayer,I={element:M,gd:A,plotinfo:{id:w.id,xaxis:w.xaxis,yaxis:w.yaxis},subplot:w.id,prepFn:function(a,o,s){I.xaxes=[w.xaxis],I.yaxes=[w.yaxis];var c=A._fullLayout.dragmode;I.minDrag="lasso"===c?1:void 0,"zoom"===c?(I.moveFn=N,I.clickFn=D,I.doneFn=j,function(a,o,s){var c=M.getBoundingClientRect();t=o-c.left,e=s-c.top,r={a:w.aaxis.range[0],b:w.baxis.range[1],c:w.caxis.range[1]},u=r,n=w.aaxis.range[1]-r.a,f=i(w.graphDiv._fullLayout[w.id].bgcolor).getLuminance(),h="M0,"+w.h+"L"+w.w/2+", 0L"+w.w+","+w.h+"Z",p=!1,g=O.append("path").attr("class","zoombox").attr("transform","translate("+w.x0+", "+w.y0+")").style({fill:f>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("d",h),_=O.append("path").attr("class","zoombox-corners").attr("transform","translate("+w.x0+", "+w.y0+")").style({fill:l.background,stroke:l.defaultLine,"stroke-width":1,opacity:0}).attr("d","M0,0Z"),x(O)}(0,o,s)):"pan"===c?(I.moveFn=V,I.clickFn=D,I.doneFn=U,r={a:w.aaxis.range[0],b:w.baxis.range[1],c:w.caxis.range[1]},u=r,x(O)):"select"!==c&&"lasso"!==c||v(a,o,s,I,c)}};function P(t){var e={};return e[w.id+".aaxis.min"]=t.a,e[w.id+".baxis.min"]=t.b,e[w.id+".caxis.min"]=t.c,e}function D(t,e){var r=A._fullLayout.clickmode;z(A),2===t&&(A.emit("plotly_doubleclick",null),a.call("_guiRelayout",A,P({a:0,b:0,c:0}))),r.indexOf("select")>-1&&1===t&&y(e,A,[w.xaxis],[w.yaxis],w.id,I),r.indexOf("event")>-1&&m.click(A,e,w.id)}function R(t,e){return 1-e/w.h}function B(t,e){return 1-(t+(w.h-e)/Math.sqrt(3))/w.w}function F(t,e){return(t-(w.h-e)/Math.sqrt(3))/w.w}function N(i,a){var o=t+i,s=e+a,l=Math.max(0,Math.min(1,R(0,e),R(0,s))),c=Math.max(0,Math.min(1,B(t,e),B(o,s))),d=Math.max(0,Math.min(1,F(t,e),F(o,s))),m=(l/2+d)*w.w,v=(1-l/2-c)*w.w,y=(m+v)/2,x=v-m,M=(1-l)*w.h,A=M-x/k;x.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),_.transition().style("opacity",1).duration(200),p=!0)}function j(){z(A),u!==r&&(a.call("_guiRelayout",A,P(u)),L&&A.data&&A._context.showTips&&(o.notifier(s(A,"Double-click to zoom back out"),"long"),L=!1))}function V(t,e){var n=t/w.xaxis._m,i=e/w.yaxis._m,a=[(u={a:r.a-i,b:r.b+(n+i)/2,c:r.c-(n-i)/2}).a,u.b,u.c].sort(),o=a.indexOf(u.a),s=a.indexOf(u.b),l=a.indexOf(u.c);a[0]<0&&(a[1]+a[0]/2<0?(a[2]+=a[0]+a[1],a[0]=a[1]=0):(a[2]+=a[0]/2,a[1]+=a[0]/2,a[0]=0),u={a:a[o],b:a[s],c:a[l]},e=(r.a-u.a)*w.yaxis._m,t=(r.c-u.c-r.b+u.b)*w.xaxis._m);var f="translate("+(w.x0+t)+","+(w.y0+e)+")";w.plotContainer.selectAll(".scatterlayer,.maplayer").attr("transform",f);var h="translate("+-t+","+-e+")";w.clipDefRelative.select("path").attr("transform",h),w.aaxis.range=[u.a,w.sum-u.b-u.c],w.baxis.range=[w.sum-u.a-u.c,u.b],w.caxis.range=[w.sum-u.a-u.b,u.c],w.drawAxes(!1),w.plotContainer.selectAll(".crisp").classed("crisp",!1),w._hasClipOnAxisFalse&&w.plotContainer.select(".scatterlayer").selectAll(".trace").call(c.hideOutsideRangePoints,w)}function U(){a.call("_guiRelayout",A,P(u))}M.onmousemove=function(t){m.hover(A,t,w.id),A._fullLayout._lasthover=M,A._fullLayout._hoversubplot=w.id},M.onmouseout=function(t){A._dragging||d.unhover(A,t)},d.init(I)}},{"../../components/color":570,"../../components/dragelement":592,"../../components/drawing":595,"../../components/fx":612,"../../components/titles":661,"../../lib":696,"../../lib/extend":685,"../../registry":827,"../cartesian/axes":744,"../cartesian/constants":750,"../cartesian/select":762,"../cartesian/set_convert":763,"../plots":808,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,tinycolor2:514}],827:[function(t,e,r){"use strict";var n=t("./lib/loggers"),i=t("./lib/noop"),a=t("./lib/push_unique"),o=t("./lib/is_plain_object"),s=t("./lib/extend"),l=t("./plots/attributes"),c=t("./plots/layout_attributes"),u=s.extendFlat,f=s.extendDeepAll;function h(t){var e=t.name,i=t.categories,a=t.meta;if(r.modules[e])n.log("Type "+e+" already registered");else{r.subplotsRegistry[t.basePlotModule.name]||function(t){var e=t.name;if(r.subplotsRegistry[e])return void n.log("Plot type "+e+" already registered.");for(var i in g(t),r.subplotsRegistry[e]=t,r.componentsRegistry)x(i,t.name)}(t.basePlotModule);for(var o={},s=0;s-1&&(u[h[r]].title="");for(r=0;rpath, .legendlines>path, .cbfill").each(function(){var t=n.select(this),e=this.style.fill;e&&-1!==e.indexOf("url(")&&t.style("fill",e.replace(l,"TOBESTRIPPED"));var r=this.style.stroke;r&&-1!==r.indexOf("url(")&&t.style("stroke",r.replace(l,"TOBESTRIPPED"))}),"pdf"!==e&&"eps"!==e||h.selectAll("#MathJax_SVG_glyphs path").attr("stroke-width",0),h.node().setAttributeNS(s.xmlns,"xmlns",s.svg),h.node().setAttributeNS(s.xmlns,"xmlns:xlink",s.xlink),"svg"===e&&r&&(h.attr("width",r*d),h.attr("height",r*m),h.attr("viewBox","0 0 "+d+" "+m));var _=(new window.XMLSerializer).serializeToString(h.node());return _=function(t){var e=n.select("body").append("div").style({display:"none"}).html(""),r=t.replace(/(&[^;]*;)/gi,function(t){return"<"===t?"<":"&rt;"===t?">":-1!==t.indexOf("<")||-1!==t.indexOf(">")?"":e.html(t).text()});return e.remove(),r}(_),_=(_=_.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g,"&")).replace(c,"'"),i.isIE()&&(_=(_=(_=_.replace(/"/gi,"'")).replace(/(\('#)([^']*)('\))/gi,'("#$2")')).replace(/(\\')/gi,'"')),_}},{"../components/color":570,"../components/drawing":595,"../constants/xmlns_namespaces":674,"../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],836:[function(t,e,r){"use strict";var n=t("../../lib").mergeArray;e.exports=function(t,e){for(var r=0;rf+c||!n(u))&&(p=!0,m(h,t))}for(var g=0;ga))return e}return void 0!==r?r:t.dflt},r.coerceColor=function(t,e,r){return i(e).isValid()?e:void 0!==r?r:t.dflt},r.coerceEnumerated=function(t,e,r){return t.coerceNumber&&(e=+e),-1!==t.values.indexOf(e)?e:void 0!==r?r:t.dflt},r.getValue=function(t,e){var r;return Array.isArray(t)?e.01?C:function(t,e){return Math.abs(t-e)>=2?C(t):t>e?Math.ceil(t):Math.floor(t)};_=E(_,w),w=E(w,_),k=E(k,M),M=E(M,k)}a.ensureSingle(A,"path").style("vector-effect","non-scaling-stroke").attr("d","M"+_+","+k+"V"+M+"H"+w+"V"+k+"Z").call(l.setClipUrl,e.layerClipId),function(t,e,r,n,i,s,c,u){var v;function y(e,r,n){var i=a.ensureSingle(e,"text").text(r).attr({class:"bartext bartext-"+v,transform:"","text-anchor":"middle","data-notex":1}).call(l.font,n).call(o.convertToTspans,t);return i}var x=r[0].trace,b=x.orientation,_=function(t,e){var r=p.getValue(t.text,e);return p.coerceString(f,r)}(x,n);if(v=function(t,e){var r=p.getValue(t.textposition,e);return p.coerceEnumerated(h,r)}(x,n),!_||"none"===v)return void e.select("text").remove();var w,k,M,A,T,S,E=t._fullLayout.font,C=d.getBarColor(r[n],x),L=d.getInsideTextFont(x,n,E,C),z=d.getOutsideTextFont(x,n,E),O=t._fullLayout.barmode,I="relative"===O,P="stack"===O||I,D=r[n],R=!P||D._outmost,B=Math.abs(s-i)-2*m,F=Math.abs(u-c)-2*m;"outside"===v&&(R||D.hasB||(v="inside"));if("auto"===v)if(R){v="inside",w=y(e,_,L),k=l.bBox(w.node()),M=k.width,A=k.height;var N=M>0&&A>0,j=M<=B&&A<=F,V=M<=F&&A<=B,U="h"===b?B>=M*(F/A):F>=A*(B/M);N&&(j||V||U)?v="inside":(v="outside",w.remove(),w=null)}else v="inside";if(!w&&(w=y(e,_,"outside"===v?z:L),k=l.bBox(w.node()),M=k.width,A=k.height,M<=0||A<=0))return void w.remove();"outside"===v?(S="both"===x.constraintext||"outside"===x.constraintext,T=function(t,e,r,n,i,a,o){var s,l="h"===a?Math.abs(n-r):Math.abs(e-t);l>2*m&&(s=m);var c=1;o&&(c="h"===a?Math.min(1,l/i.height):Math.min(1,l/i.width));var u,f,h,p,d=(i.left+i.right)/2,v=(i.top+i.bottom)/2;u=c*i.width,f=c*i.height,"h"===a?er?(h=(t+e)/2,p=n+s+f/2):(h=(t+e)/2,p=n-s-f/2);return g(d,v,h,p,c,!1)}(i,s,c,u,k,b,S)):(S="both"===x.constraintext||"inside"===x.constraintext,T=function(t,e,r,n,i,a,o){var s,l,c,u,f,h,p,d=i.width,v=i.height,y=(i.left+i.right)/2,x=(i.top+i.bottom)/2,b=Math.abs(e-t),_=Math.abs(n-r);b>2*m&&_>2*m?(b-=2*(f=m),_-=2*f):f=0;d<=b&&v<=_?(h=!1,p=1):d<=_&&v<=b?(h=!0,p=1):dr?(c=(t+e)/2,u=n-f-l/2):(c=(t+e)/2,u=n+f+l/2);return g(y,x,c,u,p,h)}(i,s,c,u,k,b,S));w.attr("transform",T)}(t,A,r,u,_,w,k,M),e.layerClipId&&l.hideOutsideRangePoint(c,A.select("text"),v,y,b.xcalendar,b.ycalendar)}else A.remove();function C(t){return 0===x.bargap&&0===x.bargroupgap?n.round(Math.round(t)-S,2):t}});var w=!1===u.trace.cliponaxis;l.setClipUrl(c,w?null:e.layerClipId)});c.getComponentMethod("errorbars","plot")(b,e)}},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../lib/svg_text_utils":720,"../../registry":827,"./attributes":837,"./helpers":841,"./style":849,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],847:[function(t,e,r){"use strict";e.exports=function(t,e){var r,n=t.cd,i=t.xaxis,a=t.yaxis,o=[];if(!1===e)for(r=0;r1||0===a.bargap&&0===a.bargroupgap&&!t[0].trace.marker.line.width)&&n.select(this).attr("shape-rendering","crispEdges")}),r.selectAll("g.points").each(function(e){p(n.select(this),e[0].trace,t)}),s.getComponentMethod("errorbars","style")(r)},styleOnSelect:function(t,e){var r=e[0].node3,i=e[0].trace;i.selectedpoints?function(t,e,r){a.selectedPointStyle(t.selectAll("path"),e),function(t,e,r){t.each(function(t){var i,s=n.select(this);if(t.selected){i=o.extendFlat({},d(s,t,e,r));var l=e.selected.textfont&&e.selected.textfont.color;l&&(i.color=l),a.font(s,i)}else a.selectedTextStyle(s,e)})}(t.selectAll("text"),e,r)}(r,i,t):p(r,i,t)},getInsideTextFont:g,getOutsideTextFont:v,getBarColor:x}},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../registry":827,"./attributes":837,"./helpers":841,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],850:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/defaults");e.exports=function(t,e,r,o,s){r("marker.color",o),i(t,"marker")&&a(t,e,s,r,{prefix:"marker.",cLetter:"c"}),r("marker.line.color",n.defaultLine),i(t,"marker.line")&&a(t,e,s,r,{prefix:"marker.line.",cLetter:"c"}),r("marker.line.width"),r("marker.opacity"),r("selected.marker.color"),r("unselected.marker.color")}},{"../../components/color":570,"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584}],851:[function(t,e,r){"use strict";var n=t("../../lib/extend").extendFlat,i=t("../scatterpolar/attributes"),a=t("../bar/attributes");e.exports={r:i.r,theta:i.theta,r0:i.r0,dr:i.dr,theta0:i.theta0,dtheta:i.dtheta,thetaunit:i.thetaunit,base:n({},a.base,{}),offset:n({},a.offset,{}),width:n({},a.width,{}),text:n({},a.text,{}),marker:a.marker,hoverinfo:i.hoverinfo,selected:a.selected,unselected:a.unselected}},{"../../lib/extend":685,"../bar/attributes":837,"../scatterpolar/attributes":1105}],852:[function(t,e,r){"use strict";var n=t("../../components/colorscale/has_colorscale"),i=t("../../components/colorscale/calc"),a=t("../bar/arrays_to_calcdata"),o=t("../bar/cross_trace_calc").setGroupPositions,s=t("../scatter/calc_selection"),l=t("../../registry").traceIs,c=t("../../lib").extendFlat;e.exports={calc:function(t,e){for(var r=t._fullLayout,o=e.subplot,l=r[o].radialaxis,c=r[o].angularaxis,u=l.makeCalcdata(e,"r"),f=c.makeCalcdata(e,"theta"),h=e._length,p=new Array(h),d=u,m=f,g=0;gh.range[1]&&(x+=Math.PI);if(n.getClosest(c,function(t){return m(y,x,[t.rp0,t.rp1],[t.thetag0,t.thetag1],d)?g+Math.min(1,Math.abs(t.thetag1-t.thetag0)/v)-1+(t.rp1-y)/(t.rp1-t.rp0)-1:1/0},t),!1!==t.index){var b=c[t.index];t.x0=t.x1=b.ct[0],t.y0=t.y1=b.ct[1];var _=i.extendFlat({},b,{r:b.s,theta:b.p});return o(b,u,t),s(_,u,f,t),t.color=a(u,b),t.xLabelVal=t.yLabelVal=void 0,b.s<0&&(t.idealAlign="left"),[t]}}},{"../../components/fx":612,"../../lib":696,"../../plots/polar/helpers":810,"../bar/hover":842,"../scatter/fill_hover_text":1051,"../scatterpolar/hover":1108}],855:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"barpolar",basePlotModule:t("../../plots/polar"),categories:["polar","bar","showLegend"],attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./calc").crossTraceCalc,plot:t("./plot"),colorbar:t("../scatter/marker_colorbar"),style:t("../bar/style").style,hoverPoints:t("./hover"),selectPoints:t("../bar/select"),meta:{}}},{"../../plots/polar":811,"../bar/select":847,"../bar/style":849,"../scatter/marker_colorbar":1061,"./attributes":851,"./calc":852,"./defaults":853,"./hover":854,"./layout_attributes":856,"./layout_defaults":857,"./plot":858}],856:[function(t,e,r){"use strict";e.exports={barmode:{valType:"enumerated",values:["stack","overlay"],dflt:"stack",editType:"calc"},bargap:{valType:"number",dflt:.1,min:0,max:1,editType:"calc"}}},{}],857:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e,r){var a,o={};function s(r,o){return n.coerce(t[a]||{},e[a],i,r,o)}for(var l=0;l0?(c=o,u=l):(c=l,u=o);var f=s.findEnclosingVertexAngles(c,t.vangles)[0],h=s.findEnclosingVertexAngles(u,t.vangles)[1],p=[f,(c+u)/2,h];return s.pathPolygonAnnulus(n,i,c,u,p,e,r)};return function(t,n,i,o){return a.pathAnnulus(t,n,i,o,e,r)}}(e),p=e.layers.frontplot.select("g.barlayer");a.makeTraceGroups(p,r,"trace bars").each(function(t){var r=t[0].node3=n.select(this),s=a.ensureSingle(r,"g","points").selectAll("g.point").data(a.identity);s.enter().append("g").style("vector-effect","non-scaling-stroke").style("stroke-miterlimit",2).classed("point",!0),s.exit().remove(),s.each(function(t){var e,r=n.select(this),o=t.rp0=u.c2p(t.s0),s=t.rp1=u.c2p(t.s1),p=t.thetag0=f.c2g(t.p0),d=t.thetag1=f.c2g(t.p1);if(i(o)&&i(s)&&i(p)&&i(d)&&o!==s&&p!==d){var m=u.c2g(t.s1),g=(p+d)/2;t.ct=[l.c2p(m*Math.cos(g)),c.c2p(m*Math.sin(g))],e=h(o,s,p,d)}else e="M0,0Z";a.ensureSingle(r,"path").attr("d",e)}),o.setClipUrl(r,e._hasClipOnAxisFalse?e.clipIds.forTraces:null)})}},{"../../components/drawing":595,"../../lib":696,"../../plots/polar/helpers":810,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"fast-isnumeric":214}],859:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../components/color/attributes"),a=t("../../lib/extend").extendFlat,o=n.marker,s=o.line;e.exports={y:{valType:"data_array",editType:"calc+clearAxisTypes"},x:{valType:"data_array",editType:"calc+clearAxisTypes"},x0:{valType:"any",editType:"calc+clearAxisTypes"},y0:{valType:"any",editType:"calc+clearAxisTypes"},name:{valType:"string",editType:"calc+clearAxisTypes"},text:a({},n.text,{}),whiskerwidth:{valType:"number",min:0,max:1,dflt:.5,editType:"calc"},notched:{valType:"boolean",editType:"calc"},notchwidth:{valType:"number",min:0,max:.5,dflt:.25,editType:"calc"},boxpoints:{valType:"enumerated",values:["all","outliers","suspectedoutliers",!1],dflt:"outliers",editType:"calc"},boxmean:{valType:"enumerated",values:[!0,"sd",!1],dflt:!1,editType:"calc"},jitter:{valType:"number",min:0,max:1,editType:"calc"},pointpos:{valType:"number",min:-2,max:2,editType:"calc"},orientation:{valType:"enumerated",values:["v","h"],editType:"calc+clearAxisTypes"},marker:{outliercolor:{valType:"color",dflt:"rgba(0, 0, 0, 0)",editType:"style"},symbol:a({},o.symbol,{arrayOk:!1,editType:"plot"}),opacity:a({},o.opacity,{arrayOk:!1,dflt:1,editType:"style"}),size:a({},o.size,{arrayOk:!1,editType:"calc"}),color:a({},o.color,{arrayOk:!1,editType:"style"}),line:{color:a({},s.color,{arrayOk:!1,dflt:i.defaultLine,editType:"style"}),width:a({},s.width,{arrayOk:!1,dflt:0,editType:"style"}),outliercolor:{valType:"color",editType:"style"},outlierwidth:{valType:"number",min:0,dflt:1,editType:"style"},editType:"style"},editType:"plot"},line:{color:{valType:"color",editType:"style"},width:{valType:"number",min:0,dflt:2,editType:"style"},editType:"plot"},fillcolor:n.fillcolor,selected:{marker:n.selected.marker,editType:"style"},unselected:{marker:n.unselected.marker,editType:"style"},hoveron:{valType:"flaglist",flags:["boxes","points"],dflt:"boxes+points",editType:"style"}}},{"../../components/color/attributes":569,"../../lib/extend":685,"../scatter/attributes":1043}],860:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../lib"),a=i._,o=t("../../plots/cartesian/axes");function s(t,e,r){var n={text:"tx"};for(var i in n)Array.isArray(e[i])&&(t[n[i]]=e[i][r])}function l(t,e){return t.v-e.v}function c(t){return t.v}e.exports=function(t,e){var r,u,f,h,p,d=t._fullLayout,m=o.getFromId(t,e.xaxis||"x"),g=o.getFromId(t,e.yaxis||"y"),v=[],y="violin"===e.type?"_numViolins":"_numBoxes";"h"===e.orientation?(u=m,f="x",h=g,p="y"):(u=g,f="y",h=m,p="x");var x=u.makeCalcdata(e,f),b=function(t,e,r,a,o){if(e in t)return r.makeCalcdata(t,e);var s;s=e+"0"in t?t[e+"0"]:"name"in t&&("category"===r.type||n(t.name)&&-1!==["linear","log"].indexOf(r.type)||i.isDateTime(t.name)&&"date"===r.type)?t.name:o;var l=r.d2c(s,0,t[e+"calendar"]);return a.map(function(){return l})}(e,p,h,x,d[y]),_=i.distinctVals(b),w=_.vals,k=_.minDiff/2,M=function(t,e){for(var r=t.length,n=new Array(r+1),i=0;i=0&&E0){var L=T[r].sort(l),z=L.map(c),O=z.length,I={pos:w[r],pts:L};I.min=z[0],I.max=z[O-1],I.mean=i.mean(z,O),I.sd=i.stdev(z,O,I.mean),I.q1=i.interp(z,.25),I.med=i.interp(z,.5),I.q3=i.interp(z,.75),I.lf=Math.min(I.q1,z[Math.min(i.findBin(2.5*I.q1-1.5*I.q3,z,!0)+1,O-1)]),I.uf=Math.max(I.q3,z[Math.max(i.findBin(2.5*I.q3-1.5*I.q1,z),0)]),I.lo=4*I.q1-3*I.q3,I.uo=4*I.q3-3*I.q1;var P=1.57*(I.q3-I.q1)/Math.sqrt(O);I.ln=I.med-P,I.un=I.med+P,v.push(I)}!function(t,e){if(i.isArrayOrTypedArray(e.selectedpoints))for(var r=0;r0?(v[0].t={num:d[y],dPos:k,posLetter:p,valLetter:f,labels:{med:a(t,"median:"),min:a(t,"min:"),q1:a(t,"q1:"),q3:a(t,"q3:"),max:a(t,"max:"),mean:"sd"===e.boxmean?a(t,"mean \xb1 \u03c3:"):a(t,"mean:"),lf:a(t,"lower fence:"),uf:a(t,"upper fence:")}},d[y]++,v):[{t:{empty:!0}}]}},{"../../lib":696,"../../plots/cartesian/axes":744,"fast-isnumeric":214}],861:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib"),a=["v","h"];function o(t,e,r,a,o){var s,l,c,u=e.calcdata,f=e._fullLayout,h=[],p="violin"===t?"_numViolins":"_numBoxes";for(s=0;st.uf}),l=Math.max((t.max-t.min)/10,t.q3-t.q1),c=1e-9*l,p=l*s,d=[],m=0;if(r.jitter){if(0===l)for(m=1,d=new Array(a.length),e=0;et.lo&&(_.so=!0)}return a});d.enter().append("path").classed("point",!0),d.exit().remove(),d.call(a.translatePoints,l,c)}function u(t,e,r,a){var o,s,l=e.pos,c=e.val,u=a.bPos,f=a.bPosPxOffset||0,h=r.boxmean||(r.meanline||{}).visible;Array.isArray(a.bdPos)?(o=a.bdPos[0],s=a.bdPos[1]):(o=a.bdPos,s=a.bdPos);var p=t.selectAll("path.mean").data("box"===r.type&&r.boxmean||"violin"===r.type&&r.box.visible&&r.meanline.visible?i.identity:[]);p.enter().append("path").attr("class","mean").style({fill:"none","vector-effect":"non-scaling-stroke"}),p.exit().remove(),p.each(function(t){var e=l.c2p(t.pos+u,!0)+f,i=l.c2p(t.pos+u-o,!0)+f,a=l.c2p(t.pos+u+s,!0)+f,p=c.c2p(t.mean,!0),d=c.c2p(t.mean-t.sd,!0),m=c.c2p(t.mean+t.sd,!0);"h"===r.orientation?n.select(this).attr("d","M"+p+","+i+"V"+a+("sd"===h?"m0,0L"+d+","+e+"L"+p+","+i+"L"+m+","+e+"Z":"")):n.select(this).attr("d","M"+i+","+p+"H"+a+("sd"===h?"m0,0L"+e+","+d+"L"+i+","+p+"L"+e+","+m+"Z":""))})}e.exports={plot:function(t,e,r,a){var o=t._fullLayout,s=e.xaxis,f=e.yaxis,h=o._numBoxes,p=1-o.boxgap,d="group"===o.boxmode&&h>1;i.makeTraceGroups(a,r,"trace boxes").each(function(t){var r=n.select(this),i=t[0],a=i.t,m=i.trace;e.isRangePlot||(i.node3=r);var g,v,y=a.dPos*p*(1-o.boxgroupgap)/(d?h:1),x=d?2*a.dPos*((a.num+.5)/h-.5)*p:0,b=y*m.whiskerwidth;!0!==m.visible||a.empty?r.remove():("h"===m.orientation?(g=f,v=s):(g=s,v=f),a.bPos=x,a.bdPos=y,a.wdPos=b,a.wHover=a.dPos*(d?p/h:1),l(r,{pos:g,val:v},m,a),c(r,{x:s,y:f},m,a),u(r,{pos:g,val:v},m,a))})},plotBoxAndWhiskers:l,plotPoints:c,plotBoxMean:u}},{"../../components/drawing":595,"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],869:[function(t,e,r){"use strict";e.exports=function(t,e){var r,n,i=t.cd,a=t.xaxis,o=t.yaxis,s=[];if(!1===e)for(r=0;r=10)return null;var i=1/0;var a=-1/0;var o=e.length;for(var s=0;s0?Math.floor:Math.ceil,O=C>0?Math.ceil:Math.floor,I=C>0?Math.min:Math.max,P=C>0?Math.max:Math.min,D=z(S+L),R=O(E-L),B=[[f=T(S)]];for(a=D;a*C=0;i--)a[u-i]=t[f][i],o[u-i]=e[f][i];for(s.push({x:a,y:o,bicubic:l}),i=f,a=[],o=[];i>=0;i--)a[f-i]=t[i][0],o[f-i]=e[i][0];return s.push({x:a,y:o,bicubic:c}),s}},{}],883:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib/extend").extendFlat;e.exports=function(t,e,r){var a,o,s,l,c,u,f,h,p,d,m,g,v,y,x=t["_"+e],b=t[e+"axis"],_=b._gridlines=[],w=b._minorgridlines=[],k=b._boundarylines=[],M=t["_"+r],A=t[r+"axis"];"array"===b.tickmode&&(b.tickvals=x.slice());var T=t._xctrl,S=t._yctrl,E=T[0].length,C=T.length,L=t._a.length,z=t._b.length;n.prepTicks(b),"array"===b.tickmode&&delete b.tickvals;var O=b.smoothing?3:1;function I(n){var i,a,o,s,l,c,u,f,p,d,m,g,v=[],y=[],x={};if("b"===e)for(a=t.b2j(n),o=Math.floor(Math.max(0,Math.min(z-2,a))),s=a-o,x.length=z,x.crossLength=L,x.xy=function(e){return t.evalxy([],e,a)},x.dxy=function(e,r){return t.dxydi([],e,o,r,s)},i=0;i0&&(p=t.dxydi([],i-1,o,0,s),v.push(l[0]+p[0]/3),y.push(l[1]+p[1]/3),d=t.dxydi([],i-1,o,1,s),v.push(f[0]-d[0]/3),y.push(f[1]-d[1]/3)),v.push(f[0]),y.push(f[1]),l=f;else for(i=t.a2i(n),c=Math.floor(Math.max(0,Math.min(L-2,i))),u=i-c,x.length=L,x.crossLength=z,x.xy=function(e){return t.evalxy([],i,e)},x.dxy=function(e,r){return t.dxydj([],c,e,u,r)},a=0;a0&&(m=t.dxydj([],c,a-1,u,0),v.push(l[0]+m[0]/3),y.push(l[1]+m[1]/3),g=t.dxydj([],c,a-1,u,1),v.push(f[0]-g[0]/3),y.push(f[1]-g[1]/3)),v.push(f[0]),y.push(f[1]),l=f;return x.axisLetter=e,x.axis=b,x.crossAxis=A,x.value=n,x.constvar=r,x.index=h,x.x=v,x.y=y,x.smoothing=A.smoothing,x}function P(n){var i,a,o,s,l,c=[],u=[],f={};if(f.length=x.length,f.crossLength=M.length,"b"===e)for(o=Math.max(0,Math.min(z-2,n)),l=Math.min(1,Math.max(0,n-o)),f.xy=function(e){return t.evalxy([],e,n)},f.dxy=function(e,r){return t.dxydi([],e,o,r,l)},i=0;ix.length-1||_.push(i(P(o),{color:b.gridcolor,width:b.gridwidth}));for(h=u;hx.length-1||m<0||m>x.length-1))for(g=x[s],v=x[m],a=0;ax[x.length-1]||w.push(i(I(d),{color:b.minorgridcolor,width:b.minorgridwidth}));b.startline&&k.push(i(P(0),{color:b.startlinecolor,width:b.startlinewidth})),b.endline&&k.push(i(P(x.length-1),{color:b.endlinecolor,width:b.endlinewidth}))}else{for(l=5e-15,u=(c=[Math.floor((x[x.length-1]-b.tick0)/b.dtick*(1+l)),Math.ceil((x[0]-b.tick0)/b.dtick/(1+l))].sort(function(t,e){return t-e}))[0],f=c[1],h=u;h<=f;h++)p=b.tick0+b.dtick*h,_.push(i(I(p),{color:b.gridcolor,width:b.gridwidth}));for(h=u-1;hx[x.length-1]||w.push(i(I(d),{color:b.minorgridcolor,width:b.minorgridwidth}));b.startline&&k.push(i(I(x[0]),{color:b.startlinecolor,width:b.startlinewidth})),b.endline&&k.push(i(I(x[x.length-1]),{color:b.endlinecolor,width:b.endlinewidth}))}}},{"../../lib/extend":685,"../../plots/cartesian/axes":744}],884:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib/extend").extendFlat;e.exports=function(t,e){var r,a,o,s=e._labels=[],l=e._gridlines;for(r=0;re.length&&(t=t.slice(0,e.length)):t=[],i=0;i90&&(p-=180,l=-l),{angle:p,flip:l,p:t.c2p(n,e,r),offsetMultplier:c}}},{}],898:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../components/drawing"),a=t("./map_1d_array"),o=t("./makepath"),s=t("./orient_text"),l=t("../../lib/svg_text_utils"),c=t("../../lib"),u=t("../../constants/alignment");function f(t,e,r,i,s,l){var c="const-"+s+"-lines",u=r.selectAll("."+c).data(l);u.enter().append("path").classed(c,!0).style("vector-effect","non-scaling-stroke"),u.each(function(r){var i=r,s=i.x,l=i.y,c=a([],s,t.c2p),u=a([],l,e.c2p),f="M"+o(c,u,i.smoothing);n.select(this).attr("d",f).style("stroke-width",i.width).style("stroke",i.color).style("fill","none")}),u.exit().remove()}function h(t,e,r,a,o,c,u,f){var h=c.selectAll("text."+f).data(u);h.enter().append("text").classed(f,!0);var p=0,d={};return h.each(function(o,c){var u;if("auto"===o.axis.tickangle)u=s(a,e,r,o.xy,o.dxy);else{var f=(o.axis.tickangle+180)*Math.PI/180;u=s(a,e,r,o.xy,[Math.cos(f),Math.sin(f)])}c||(d={angle:u.angle,flip:u.flip});var h=(o.endAnchor?-1:1)*u.flip,m=n.select(this).attr({"text-anchor":h>0?"start":"end","data-notex":1}).call(i.font,o.font).text(o.text).call(l.convertToTspans,t),g=i.bBox(this);m.attr("transform","translate("+u.p[0]+","+u.p[1]+") rotate("+u.angle+")translate("+o.axis.labelpadding*h+","+.3*g.height+")"),p=Math.max(p,g.width+o.axis.labelpadding)}),h.exit().remove(),d.maxExtent=p,d}e.exports=function(t,e,r,i){var l=e.xaxis,u=e.yaxis,p=t._fullLayout._clips;c.makeTraceGroups(i,r,"trace").each(function(e){var r=n.select(this),i=e[0],d=i.trace,g=d.aaxis,v=d.baxis,y=c.ensureSingle(r,"g","minorlayer"),x=c.ensureSingle(r,"g","majorlayer"),b=c.ensureSingle(r,"g","boundarylayer"),_=c.ensureSingle(r,"g","labellayer");r.style("opacity",d.opacity),f(l,u,x,g,"a",g._gridlines),f(l,u,x,v,"b",v._gridlines),f(l,u,y,g,"a",g._minorgridlines),f(l,u,y,v,"b",v._minorgridlines),f(l,u,b,g,"a-boundary",g._boundarylines),f(l,u,b,v,"b-boundary",v._boundarylines);var w=h(t,l,u,d,i,_,g._labels,"a-label"),k=h(t,l,u,d,i,_,v._labels,"b-label");!function(t,e,r,n,i,a,o,l){var u,f,h,p;u=.5*(r.a[0]+r.a[r.a.length-1]),f=r.b[0],h=r.ab2xy(u,f,!0),p=r.dxyda_rough(u,f),void 0===o.angle&&c.extendFlat(o,s(r,i,a,h,r.dxydb_rough(u,f)));m(t,e,r,n,h,p,r.aaxis,i,a,o,"a-title"),u=r.a[0],f=.5*(r.b[0]+r.b[r.b.length-1]),h=r.ab2xy(u,f,!0),p=r.dxydb_rough(u,f),void 0===l.angle&&c.extendFlat(l,s(r,i,a,h,r.dxyda_rough(u,f)));m(t,e,r,n,h,p,r.baxis,i,a,l,"b-title")}(t,_,d,i,l,u,w,k),function(t,e,r,n,i){var s,l,u,f,h=r.select("#"+t._clipPathId);h.size()||(h=r.append("clipPath").classed("carpetclip",!0));var p=c.ensureSingle(h,"path","carpetboundary"),d=e.clipsegments,m=[];for(f=0;f90&&g<270,y=n.select(this);y.text(u.title||"").call(l.convertToTspans,t),v&&(x=(-l.lineCount(y)+d)*p*a-x),y.attr("transform","translate("+e.p[0]+","+e.p[1]+") rotate("+e.angle+") translate(0,"+x+")").classed("user-select-none",!0).attr("text-anchor","middle").call(i.font,u.titlefont)}),y.exit().remove()}},{"../../components/drawing":595,"../../constants/alignment":668,"../../lib":696,"../../lib/svg_text_utils":720,"./makepath":895,"./map_1d_array":896,"./orient_text":897,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],899:[function(t,e,r){"use strict";var n=t("./constants"),i=t("../../lib/search").findBin,a=t("./compute_control_points"),o=t("./create_spline_evaluator"),s=t("./create_i_derivative_evaluator"),l=t("./create_j_derivative_evaluator");e.exports=function(t){var e=t._a,r=t._b,c=e.length,u=r.length,f=t.aaxis,h=t.baxis,p=e[0],d=e[c-1],m=r[0],g=r[u-1],v=e[e.length-1]-e[0],y=r[r.length-1]-r[0],x=v*n.RELATIVE_CULL_TOLERANCE,b=y*n.RELATIVE_CULL_TOLERANCE;p-=x,d+=x,m-=b,g+=b,t.isVisible=function(t,e){return t>p&&tm&&ed||eg},t.setScale=function(){var e=t._x,r=t._y,n=a(t._xctrl,t._yctrl,e,r,f.smoothing,h.smoothing);t._xctrl=n[0],t._yctrl=n[1],t.evalxy=o([t._xctrl,t._yctrl],c,u,f.smoothing,h.smoothing),t.dxydi=s([t._xctrl,t._yctrl],f.smoothing,h.smoothing),t.dxydj=l([t._xctrl,t._yctrl],f.smoothing,h.smoothing)},t.i2a=function(t){var r=Math.max(0,Math.floor(t[0]),c-2),n=t[0]-r;return(1-n)*e[r]+n*e[r+1]},t.j2b=function(t){var e=Math.max(0,Math.floor(t[1]),c-2),n=t[1]-e;return(1-n)*r[e]+n*r[e+1]},t.ij2ab=function(e){return[t.i2a(e[0]),t.j2b(e[1])]},t.a2i=function(t){var r=Math.max(0,Math.min(i(t,e),c-2)),n=e[r],a=e[r+1];return Math.max(0,Math.min(c-1,r+(t-n)/(a-n)))},t.b2j=function(t){var e=Math.max(0,Math.min(i(t,r),u-2)),n=r[e],a=r[e+1];return Math.max(0,Math.min(u-1,e+(t-n)/(a-n)))},t.ab2ij=function(e){return[t.a2i(e[0]),t.b2j(e[1])]},t.i2c=function(e,r){return t.evalxy([],e,r)},t.ab2xy=function(n,i,a){if(!a&&(ne[c-1]|ir[u-1]))return[!1,!1];var o=t.a2i(n),s=t.b2j(i),l=t.evalxy([],o,s);if(a){var f,h,p,d,m=0,g=0,v=[];ne[c-1]?(f=c-2,h=1,m=(n-e[c-1])/(e[c-1]-e[c-2])):h=o-(f=Math.max(0,Math.min(c-2,Math.floor(o)))),ir[u-1]?(p=u-2,d=1,g=(i-r[u-1])/(r[u-1]-r[u-2])):d=s-(p=Math.max(0,Math.min(u-2,Math.floor(s)))),m&&(t.dxydi(v,f,p,h,d),l[0]+=v[0]*m,l[1]+=v[1]*m),g&&(t.dxydj(v,f,p,h,d),l[0]+=v[0]*g,l[1]+=v[1]*g)}return l},t.c2p=function(t,e,r){return[e.c2p(t[0]),r.c2p(t[1])]},t.p2x=function(t,e,r){return[e.p2c(t[0]),r.p2c(t[1])]},t.dadi=function(t){var r=Math.max(0,Math.min(e.length-2,t));return e[r+1]-e[r]},t.dbdj=function(t){var e=Math.max(0,Math.min(r.length-2,t));return r[e+1]-r[e]},t.dxyda=function(e,r,n,i){var a=t.dxydi(null,e,r,n,i),o=t.dadi(e,n);return[a[0]/o,a[1]/o]},t.dxydb=function(e,r,n,i){var a=t.dxydj(null,e,r,n,i),o=t.dbdj(r,i);return[a[0]/o,a[1]/o]},t.dxyda_rough=function(e,r,n){var i=v*(n||.1),a=t.ab2xy(e+i,r,!0),o=t.ab2xy(e-i,r,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dxydb_rough=function(e,r,n){var i=y*(n||.1),a=t.ab2xy(e,r+i,!0),o=t.ab2xy(e,r-i,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dpdx=function(t){return t._m},t.dpdy=function(t){return t._m}}},{"../../lib/search":715,"./compute_control_points":887,"./constants":888,"./create_i_derivative_evaluator":889,"./create_j_derivative_evaluator":890,"./create_spline_evaluator":891}],900:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e,r){var i,a,o,s=[],l=[],c=t[0].length,u=t.length;function f(e,r){var n,i=0,a=0;return e>0&&void 0!==(n=t[r][e-1])&&(a++,i+=n),e0&&void 0!==(n=t[r-1][e])&&(a++,i+=n),r0&&a0&&i1e-5);return n.log("Smoother converged to",M,"after",A,"iterations"),t}},{"../../lib":696}],901:[function(t,e,r){"use strict";var n=t("../../lib").isArray1D;e.exports=function(t,e,r){var i=r("x"),a=i&&i.length,o=r("y"),s=o&&o.length;if(!a&&!s)return!1;if(e._cheater=!i,a&&!n(i)||s&&!n(o))e._length=null;else{var l=a?i.length:1/0;s&&(l=Math.min(l,o.length)),e.a&&e.a.length&&(l=Math.min(l,e.a.length)),e.b&&e.b.length&&(l=Math.min(l,e.b.length)),e._length=l}return!0}},{"../../lib":696}],902:[function(t,e,r){"use strict";var n=t("../scattergeo/attributes"),i=t("../../components/colorscale/attributes"),a=t("../../components/colorbar/attributes"),o=t("../../plots/attributes"),s=t("../../lib/extend").extendFlat,l=n.marker.line;e.exports=s({locations:{valType:"data_array",editType:"calc"},locationmode:n.locationmode,z:{valType:"data_array",editType:"calc"},text:s({},n.text,{}),marker:{line:{color:l.color,width:s({},l.width,{dflt:1}),editType:"calc"},opacity:{valType:"number",arrayOk:!0,min:0,max:1,dflt:1,editType:"style"},editType:"calc"},selected:{marker:{opacity:n.selected.marker.opacity,editType:"plot"},editType:"plot"},unselected:{marker:{opacity:n.unselected.marker.opacity,editType:"plot"},editType:"plot"},hoverinfo:s({},o.hoverinfo,{editType:"calc",flags:["location","z","text","name"]})},i("",{cLetter:"z",editTypeOverride:"calc"}),{colorbar:a})},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../scattergeo/attributes":1083}],903:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../constants/numerical").BADNUM,a=t("../../components/colorscale/calc"),o=t("../scatter/arrays_to_calcdata"),s=t("../scatter/calc_selection");e.exports=function(t,e){for(var r=e._length,l=new Array(r),c=0;c")}(t,f,o,h.mockAxis),[t]}},{"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051,"./attributes":902}],907:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../heatmap/colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("./style").style,n.styleOnSelect=t("./style").styleOnSelect,n.hoverPoints=t("./hover"),n.eventData=t("./event_data"),n.selectPoints=t("./select"),n.moduleType="trace",n.name="choropleth",n.basePlotModule=t("../../plots/geo"),n.categories=["geo","noOpacity"],n.meta={},e.exports=n},{"../../plots/geo":775,"../heatmap/colorbar":948,"./attributes":902,"./calc":903,"./defaults":904,"./event_data":905,"./hover":906,"./plot":908,"./select":909,"./style":910}],908:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib"),a=t("../../lib/polygon"),o=t("../../lib/topojson_utils").getTopojsonFeatures,s=t("../../lib/geo_location_utils").locationToFeature,l=t("./style").style;function c(t,e){for(var r=t[0].trace,n=t.length,i=o(r,e),a=0;a0&&t[e+1][0]<0)return e;return null}switch(e="RUS"===l||"FJI"===l?function(t){var e;if(null===u(t))e=t;else for(e=new Array(t.length),i=0;ie?r[n++]=[t[i][0]+360,t[i][1]]:i===e?(r[n++]=t[i],r[n++]=[t[i][0],-90]):r[n++]=t[i];var o=a.tester(r);o.pts.pop(),c.push(o)}:function(t){c.push(a.tester(t))},o.type){case"MultiPolygon":for(r=0;r":f.value>h&&(s.prefixBoundary=!0);break;case"<":f.valueh)&&(s.prefixBoundary=!0);break;case"][":a=Math.min.apply(null,f.value),o=Math.max.apply(null,f.value),ah&&(s.prefixBoundary=!0)}}},{}],919:[function(t,e,r){"use strict";var n=t("../../components/colorbar/draw"),i=t("./make_color_map"),a=t("./end_plus");e.exports=function(t,e){var r=e[0].trace,o="cb"+r.uid;if(t._fullLayout._infolayer.selectAll("."+o).remove(),r.showscale){var s=e[0].t.cb=n(t,o),l=r.contours,c=r.line,u=l.size||1,f=l.coloring,h=i(r,{isColorbar:!0});s.fillgradient("heatmap"===f?r.colorscale:"").zrange("heatmap"===f?[r.zmin,r.zmax]:"").fillcolor("fill"===f?h:"").line({color:"lines"===f?h:c.color,width:!1!==l.showlines?c.width:0,dash:c.dash}).levels({start:l.start,end:a(l),size:u}).options(r.colorbar)()}}},{"../../components/colorbar/draw":575,"./end_plus":927,"./make_color_map":932}],920:[function(t,e,r){"use strict";e.exports={BOTTOMSTART:[1,9,13,104,713],TOPSTART:[4,6,7,104,713],LEFTSTART:[8,12,14,208,1114],RIGHTSTART:[2,3,11,208,1114],NEWDELTA:[null,[-1,0],[0,-1],[-1,0],[1,0],null,[0,-1],[-1,0],[0,1],[0,1],null,[0,1],[1,0],[1,0],[0,-1]],CHOOSESADDLE:{104:[4,1],208:[2,8],713:[7,13],1114:[11,14]},SADDLEREMAINDER:{1:4,2:8,4:1,7:13,8:2,11:14,13:7,14:11},LABELDISTANCE:2,LABELINCREASE:10,LABELMIN:3,LABELMAX:10,LABELOPTIMIZER:{EDGECOST:1,ANGLECOST:1,NEIGHBORCOST:5,SAMELEVELFACTOR:10,SAMELEVELDISTANCE:5,MAXCOST:100,INITIALSEARCHPOINTS:10,ITERATIONS:5}}},{}],921:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("./label_defaults"),a=t("../../components/color"),o=a.addOpacity,s=a.opacity,l=t("../../constants/filter_ops"),c=l.CONSTRAINT_REDUCTION,u=l.COMPARISON_OPS2;e.exports=function(t,e,r,a,l,f){var h,p,d,m=e.contours,g=r("contours.operation");(m._operation=c[g],function(t,e){var r;-1===u.indexOf(e.operation)?(t("contours.value",[0,1]),Array.isArray(e.value)?e.value.length>2?e.value=e.value.slice(2):0===e.length?e.value=[0,1]:e.length<2?(r=parseFloat(e.value[0]),e.value=[r,r+1]):e.value=[parseFloat(e.value[0]),parseFloat(e.value[1])]:n(e.value)&&(r=parseFloat(e.value),e.value=[r,r+1])):(t("contours.value",0),n(e.value)||(Array.isArray(e.value)?e.value=parseFloat(e.value[0]):e.value=0))}(r,m),"="===g?h=m.showlines=!0:(h=r("contours.showlines"),d=r("fillcolor",o((t.line||{}).color||l,.5))),h)&&(p=r("line.color",d&&s(d)?o(e.fillcolor,1):l),r("line.width",2),r("line.dash"));r("line.smoothing"),i(r,a,p,f)}},{"../../components/color":570,"../../constants/filter_ops":669,"./label_defaults":931,"fast-isnumeric":214}],922:[function(t,e,r){"use strict";var n=t("../../constants/filter_ops"),i=t("fast-isnumeric");function a(t,e){var r,a=Array.isArray(e);function o(t){return i(t)?+t:null}return-1!==n.COMPARISON_OPS2.indexOf(t)?r=o(a?e[0]:e):-1!==n.INTERVAL_OPS.indexOf(t)?r=a?[o(e[0]),o(e[1])]:[o(e),o(e)]:-1!==n.SET_OPS.indexOf(t)&&(r=a?e.map(o):[o(e)]),r}function o(t){return function(e){e=a(t,e);var r=Math.min(e[0],e[1]),n=Math.max(e[0],e[1]);return{start:r,end:n,size:n-r}}}function s(t){return function(e){return{start:e=a(t,e),end:1/0,size:1/0}}}e.exports={"[]":o("[]"),"][":o("]["),">":s(">"),"<":s("<"),"=":s("=")}},{"../../constants/filter_ops":669,"fast-isnumeric":214}],923:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var i=n("contours.start"),a=n("contours.end"),o=!1===i||!1===a,s=r("contours.size");!(o?e.autocontour=!0:r("autocontour",!1))&&s||r("ncontours")}},{}],924:[function(t,e,r){"use strict";var n=t("../../lib");function i(t){return n.extendFlat({},t,{edgepaths:n.extendDeep([],t.edgepaths),paths:n.extendDeep([],t.paths)})}e.exports=function(t,e){var r,a,o,s=function(t){return t.reverse()},l=function(t){return t};switch(e){case"=":case"<":return t;case">":for(1!==t.length&&n.warn("Contour data invalid for the specified inequality operation."),a=t[0],r=0;r1e3){n.warn("Too many contours, clipping at 1000",t);break}return l}},{"../../lib":696,"./constraint_mapping":922,"./end_plus":927}],927:[function(t,e,r){"use strict";e.exports=function(t){return t.end+t.size/1e6}},{}],928:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./constants");function a(t,e,r,n){return Math.abs(t[0]-e[0])20&&e?208===t||1114===t?n=0===r[0]?1:-1:a=0===r[1]?1:-1:-1!==i.BOTTOMSTART.indexOf(t)?a=1:-1!==i.LEFTSTART.indexOf(t)?n=1:-1!==i.TOPSTART.indexOf(t)?a=-1:n=-1;return[n,a]}(h,r,e),d=[s(t,e,[-p[0],-p[1]])],m=p.join(","),g=t.z.length,v=t.z[0].length;for(c=0;c<1e4;c++){if(h>20?(h=i.CHOOSESADDLE[h][(p[0]||p[1])<0?0:1],t.crossings[f]=i.SADDLEREMAINDER[h]):delete t.crossings[f],!(p=i.NEWDELTA[h])){n.log("Found bad marching index:",h,e,t.level);break}d.push(s(t,e,p)),e[0]+=p[0],e[1]+=p[1],a(d[d.length-1],d[d.length-2],o,l)&&d.pop(),f=e.join(",");var y=p[0]&&(e[0]<0||e[0]>v-2)||p[1]&&(e[1]<0||e[1]>g-2);if(f===u&&p.join(",")===m||r&&y)break;h=t.crossings[f]}1e4===c&&n.log("Infinite loop in contour?");var x,b,_,w,k,M,A,T,S,E,C,L,z,O,I,P=a(d[0],d[d.length-1],o,l),D=0,R=.2*t.smoothing,B=[],F=0;for(c=1;c=F;c--)if((x=B[c])=F&&x+B[b]T&&S--,t.edgepaths[S]=C.concat(d,E));break}U||(t.edgepaths[T]=d.concat(E))}for(T=0;Tt?0:1)+(e[0][1]>t?0:2)+(e[1][1]>t?0:4)+(e[1][0]>t?0:8);return 5===r||10===r?t>(e[0][0]+e[0][1]+e[1][0]+e[1][1])/4?5===r?713:1114:5===r?104:208:15===r?0:r}e.exports=function(t){var e,r,a,o,s,l,c,u,f,h=t[0].z,p=h.length,d=h[0].length,m=2===p||2===d;for(r=0;rt.level}return r?"M"+e.join("L")+"Z":""}(t,e),h=0,p=t.edgepaths.map(function(t,e){return e}),d=!0;function m(t){return Math.abs(t[1]-e[2][1])<.01}function g(t){return Math.abs(t[0]-e[0][0])<.01}function v(t){return Math.abs(t[0]-e[2][0])<.01}for(;p.length;){for(c=a.smoothopen(t.edgepaths[h],t.smoothing),f+=d?c:c.replace(/^M/,"L"),p.splice(p.indexOf(h),1),r=t.edgepaths[h][t.edgepaths[h].length-1],s=-1,o=0;o<4;o++){if(!r){i.log("Missing end?",h,t);break}for(u=r,Math.abs(u[1]-e[0][1])<.01&&!v(r)?n=e[1]:g(r)?n=e[0]:m(r)?n=e[3]:v(r)&&(n=e[2]),l=0;l=0&&(n=y,s=l):Math.abs(r[1]-n[1])<.01?Math.abs(r[1]-y[1])<.01&&(y[0]-r[0])*(n[0]-y[0])>=0&&(n=y,s=l):i.log("endpt to newendpt is not vert. or horz.",r,n,y)}if(r=n,s>=0)break;f+="L"+n}if(s===t.edgepaths.length){i.log("unclosed perimeter path");break}h=s,(d=-1===p.indexOf(h))&&(h=p[0],f+="Z")}for(h=0;hn.center?n.right-s:s-n.left)/(u+Math.abs(Math.sin(c)*o)),p=(l>n.middle?n.bottom-l:l-n.top)/(Math.abs(f)+Math.cos(c)*o);if(h<1||p<1)return 1/0;var d=g.EDGECOST*(1/(h-1)+1/(p-1));d+=g.ANGLECOST*c*c;for(var m=s-u,v=l-f,y=s+u,x=l+f,b=0;b2*g.MAXCOST)break;p&&(s/=2),l=(o=c-s/2)+1.5*s}if(h<=g.MAXCOST)return u},r.addLabelData=function(t,e,r,n){var i=e.width/2,a=e.height/2,o=t.x,s=t.y,l=t.theta,c=Math.sin(l),u=Math.cos(l),f=i*u,h=a*c,p=i*c,d=-a*u,m=[[o-f-h,s-p-d],[o+f-h,s+p-d],[o+f+h,s+p+d],[o-f+h,s-p+d]];r.push({text:e.text,x:o,y:s,dy:e.dy,theta:l,level:e.level,width:e.width,height:e.height}),n.push(m)},r.drawLabels=function(t,e,r,a,s){var l=t.selectAll("text").data(e,function(t){return t.text+","+t.x+","+t.y+","+t.theta});if(l.exit().remove(),l.enter().append("text").attr({"data-notex":1,"text-anchor":"middle"}).each(function(t){var e=t.x+Math.sin(t.theta)*t.dy,i=t.y-Math.cos(t.theta)*t.dy;n.select(this).text(t.text).attr({x:e,y:i,transform:"rotate("+180*t.theta/Math.PI+" "+e+" "+i+")"}).call(o.convertToTspans,r)}),s){for(var c="",u=0;ue.end&&(e.start=e.end=(e.start+e.end)/2),t._input.contours||(t._input.contours={}),i.extendFlat(t._input.contours,{start:e.start,end:e.end,size:e.size}),t._input.autocontour=!0}else if("constraint"!==e.type){var l,c=e.start,u=e.end,f=t._input.contours;if(c>u&&(e.start=f.start=u,u=e.end=f.end=c,c=e.start),!(e.size>0))l=c===u?1:a(c,u,t.ncontours).dtick,f.size=e.size=l}}},{"../../lib":696,"../../plots/cartesian/axes":744}],936:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../components/drawing"),a=t("../heatmap/style"),o=t("./make_color_map");e.exports=function(t){var e=n.select(t).selectAll("g.contour");e.style("opacity",function(t){return t[0].trace.opacity}),e.each(function(t){var e=n.select(this),r=t[0].trace,a=r.contours,s=r.line,l=a.size||1,c=a.start,u="constraint"===a.type,f=!u&&"lines"===a.coloring,h=!u&&"fill"===a.coloring,p=f||h?o(r):null;e.selectAll("g.contourlevel").each(function(t){n.select(this).selectAll("path").call(i.lineGroupStyle,s.width,f?p(t.level):s.color,s.dash)});var d=a.labelfont;if(e.selectAll("g.contourlabels text").each(function(t){i.font(n.select(this),{family:d.family,size:d.size,color:d.color||(f?p(t.level):s.color)})}),u)e.selectAll("g.contourfill path").style("fill",r.fillcolor);else if(h){var m;e.selectAll("g.contourfill path").style("fill",function(t){return void 0===m&&(m=t.level),p(t.level+.5*l)}),void 0===m&&(m=c),e.selectAll("g.contourbg path").style("fill",p(m-.5*l))}}),a(t)}},{"../../components/drawing":595,"../heatmap/style":958,"./make_color_map":932,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],937:[function(t,e,r){"use strict";var n=t("../../components/colorscale/defaults"),i=t("./label_defaults");e.exports=function(t,e,r,a,o){var s,l=r("contours.coloring"),c="";"fill"===l&&(s=r("contours.showlines")),!1!==s&&("lines"!==l&&(c=r("line.color","#000")),r("line.width",.5),r("line.dash")),"none"!==l&&(!0!==t.showlegend&&(e.showlegend=!1),e._dfltShowLegend=!1,n(t,e,a,r,{prefix:"",cLetter:"z"})),r("line.smoothing"),i(r,a,c,o)}},{"../../components/colorscale/defaults":580,"./label_defaults":931}],938:[function(t,e,r){"use strict";var n=t("../heatmap/attributes"),i=t("../contour/attributes"),a=i.contours,o=t("../scatter/attributes"),s=t("../../components/colorscale/attributes"),l=t("../../components/colorbar/attributes"),c=t("../../lib/extend").extendFlat,u=o.line;e.exports=c({carpet:{valType:"string",editType:"calc"},z:n.z,a:n.x,a0:n.x0,da:n.dx,b:n.y,b0:n.y0,db:n.dy,text:n.text,transpose:n.transpose,atype:n.xtype,btype:n.ytype,fillcolor:i.fillcolor,autocontour:i.autocontour,ncontours:i.ncontours,contours:{type:a.type,start:a.start,end:a.end,size:a.size,coloring:{valType:"enumerated",values:["fill","lines","none"],dflt:"fill",editType:"calc"},showlines:a.showlines,showlabels:a.showlabels,labelfont:a.labelfont,labelformat:a.labelformat,operation:a.operation,value:a.value,editType:"calc",impliedEdits:{autocontour:!1}},line:{color:c({},u.color,{}),width:u.width,dash:u.dash,smoothing:c({},u.smoothing,{}),editType:"plot"},transforms:void 0},s("",{cLetter:"z",autoColorDflt:!1}),{colorbar:l})},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../contour/attributes":916,"../heatmap/attributes":945,"../scatter/attributes":1043}],939:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc"),i=t("../../lib").isArray1D,a=t("../heatmap/convert_column_xyz"),o=t("../heatmap/clean_2d_array"),s=t("../heatmap/max_row_length"),l=t("../heatmap/interp2d"),c=t("../heatmap/find_empties"),u=t("../heatmap/make_bound_array"),f=t("./defaults"),h=t("../carpet/lookup_carpetid"),p=t("../contour/set_contours");e.exports=function(t,e){var r=e._carpetTrace=h(t,e);if(r&&r.visible&&"legendonly"!==r.visible){if(!e.a||!e.b){var d=t.data[r.index],m=t.data[e.index];m.a||(m.a=d.a),m.b||(m.b=d.b),f(m,e,e._defaultColor,t._fullLayout)}var g=function(t,e){var r,f,h,p,d,m,g,v=e._carpetTrace,y=v.aaxis,x=v.baxis;y._minDtick=0,x._minDtick=0,i(e.z)&&a(e,y,x,"a","b",["z"]);r=e._a=e._a||e.a,p=e._b=e._b||e.b,r=r?y.makeCalcdata(e,"_a"):[],p=p?x.makeCalcdata(e,"_b"):[],f=e.a0||0,h=e.da||1,d=e.b0||0,m=e.db||1,g=e._z=o(e._z||e.z,e.transpose),e._emptypoints=c(g),l(g,e._emptypoints);var b=s(g),_="scaled"===e.xtype?"":r,w=u(e,_,f,h,b,y),k="scaled"===e.ytype?"":p,M=u(e,k,d,m,g.length,x),A={a:w,b:M,z:g};"levels"===e.contours.type&&"none"!==e.contours.coloring&&n(e,g,"","z");return[A]}(0,e);return p(e),g}}},{"../../components/colorscale/calc":578,"../../lib":696,"../carpet/lookup_carpetid":894,"../contour/set_contours":935,"../heatmap/clean_2d_array":947,"../heatmap/convert_column_xyz":949,"../heatmap/find_empties":951,"../heatmap/interp2d":954,"../heatmap/make_bound_array":955,"../heatmap/max_row_length":956,"./defaults":940}],940:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../heatmap/xyz_defaults"),a=t("./attributes"),o=t("../contour/constraint_defaults"),s=t("../contour/contours_defaults"),l=t("../contour/style_defaults");e.exports=function(t,e,r,c){function u(r,i){return n.coerce(t,e,a,r,i)}if(u("carpet"),t.a&&t.b){if(!i(t,e,u,c,"a","b"))return void(e.visible=!1);u("text"),"constraint"===u("contours.type")?o(t,e,u,c,r,{hasHover:!1}):(s(t,e,u,function(r){return n.coerce2(t,e,a,r)}),l(t,e,u,c,{hasHover:!1}))}else e._defaultColor=r,e._length=null}},{"../../lib":696,"../contour/constraint_defaults":921,"../contour/contours_defaults":923,"../contour/style_defaults":937,"../heatmap/xyz_defaults":960,"./attributes":938}],941:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../contour/colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("../contour/style"),n.moduleType="trace",n.name="contourcarpet",n.basePlotModule=t("../../plots/cartesian"),n.categories=["cartesian","svg","carpet","contour","symbols","showLegend","hasLines","carpetDependent"],n.meta={},e.exports=n},{"../../plots/cartesian":756,"../contour/colorbar":919,"../contour/style":936,"./attributes":938,"./calc":939,"./defaults":940,"./plot":944}],942:[function(t,e,r){"use strict";var n=t("../../components/drawing"),i=t("../carpet/axis_aligned_line"),a=t("../../lib");e.exports=function(t,e,r,o,s,l,c,u){var f,h,p,d,m,g,v,y="",x=e.edgepaths.map(function(t,e){return e}),b=!0,_=1e-4*Math.abs(r[0][0]-r[2][0]),w=1e-4*Math.abs(r[0][1]-r[2][1]);function k(t){return Math.abs(t[1]-r[0][1])=0&&(p=C,m=g):Math.abs(h[1]-p[1])=0&&(p=C,m=g):a.log("endpt to newendpt is not vert. or horz.",h,p,C)}if(m>=0)break;y+=S(h,p),h=p}if(m===e.edgepaths.length){a.log("unclosed perimeter path");break}f=m,(b=-1===x.indexOf(f))&&(f=x[0],y+=S(h,p)+"Z",h=null)}for(f=0;f=0;V--)F=S.clipsegments[V],N=i([],F.x,w.c2p),j=i([],F.y,k.c2p),N.reverse(),j.reverse(),q.push(a(N,j,F.bicubic));var H="M"+q.join("L")+"Z";!function(t,e,r,n,o,l){var c,u,f,h,p=s.ensureSingle(t,"g","contourbg").selectAll("path").data("fill"!==l||o?[]:[0]);p.enter().append("path"),p.exit().remove();var d=[];for(h=0;hg&&(n.max=g);n.len=n.max-n.min}(this,r,t,n,c,e.height),!(n.len<(e.width+e.height)*f.LABELMIN)))for(var i=Math.min(Math.ceil(n.len/O),f.LABELMAX),a=0;az){C("x scale is not linear");break}}if(g.length&&"fast"===S){var O=(g[g.length-1]-g[0])/(g.length-1),I=Math.abs(O/100);for(b=0;bI){C("y scale is not linear");break}}}var P=c(x),D="scaled"===e.xtype?"":r,R=p(e,D,d,m,P,w),B="scaled"===e.ytype?"":g,F=p(e,B,v,y,x.length,k);T||(e._extremes[w._id]=a.findExtremes(w,R),e._extremes[k._id]=a.findExtremes(k,F));var N={x:R,y:F,z:x,text:e._text||e.text};if(D&&D.length===R.length-1&&(N.xCenter=D),B&&B.length===F.length-1&&(N.yCenter=B),A&&(N.xRanges=_.xRanges,N.yRanges=_.yRanges,N.pts=_.pts),M&&"constraint"===e.contours.type||s(e,x,"","z"),M&&e.contours&&"heatmap"===e.contours.coloring){var j={type:"contour"===e.type?"heatmap":"histogram2d",xcalendar:e.xcalendar,ycalendar:e.ycalendar};N.xfill=p(j,D,d,m,P,w),N.yfill=p(j,B,v,y,x.length,k)}return[N]}},{"../../components/colorscale/calc":578,"../../lib":696,"../../plots/cartesian/axes":744,"../../registry":827,"../histogram2d/calc":977,"./clean_2d_array":947,"./convert_column_xyz":949,"./find_empties":951,"./interp2d":954,"./make_bound_array":955,"./max_row_length":956}],947:[function(t,e,r){"use strict";var n=t("fast-isnumeric");e.exports=function(t,e){var r,i,a,o,s,l;function c(t){if(n(t))return+t}if(e){for(r=0,s=0;s=0;o--)(s=((f[[(r=(a=h[o])[0])-1,i=a[1]]]||m)[2]+(f[[r+1,i]]||m)[2]+(f[[r,i-1]]||m)[2]+(f[[r,i+1]]||m)[2])/20)&&(l[a]=[r,i,s],h.splice(o,1),c=!0);if(!c)throw"findEmpties iterated with no new neighbors";for(a in l)f[a]=l[a],u.push(l[a])}return u.sort(function(t,e){return e[2]-t[2]})}},{"./max_row_length":956}],952:[function(t,e,r){"use strict";var n=t("../../components/fx"),i=t("../../lib"),a=t("../../plots/cartesian/axes");e.exports=function(t,e,r,o,s,l){var c,u,f,h,p=t.cd[0],d=p.trace,m=t.xa,g=t.ya,v=p.x,y=p.y,x=p.z,b=p.xCenter,_=p.yCenter,w=p.zmask,k=[d.zmin,d.zmax],M=d.zhoverformat,A=v,T=y;if(!1!==t.index){try{f=Math.round(t.index[1]),h=Math.round(t.index[0])}catch(e){return void i.error("Error hovering on heatmap, pointNumber must be [row,col], found:",t.index)}if(f<0||f>=x[0].length||h<0||h>x.length)return}else{if(n.inbox(e-v[0],e-v[v.length-1],0)>0||n.inbox(r-y[0],r-y[y.length-1],0)>0)return;if(l){var S;for(A=[2*v[0]-v[1]],S=1;Sm&&(v=Math.max(v,Math.abs(t[a][o]-d)/(g-m))))}return v}e.exports=function(t,e){var r,i=1;for(o(t,e),r=0;r.01;r++)i=o(t,e,a(i));return i>.01&&n.log("interp2d didn't converge quickly",i),t}},{"../../lib":696}],955:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib").isArrayOrTypedArray;e.exports=function(t,e,r,a,o,s){var l,c,u,f=[],h=n.traceIs(t,"contour"),p=n.traceIs(t,"histogram"),d=n.traceIs(t,"gl2d");if(i(e)&&e.length>1&&!p&&"category"!==s.type){var m=e.length;if(!(m<=o))return h?e.slice(0,o):e.slice(0,o+1);if(h||d)f=e.slice(0,o);else if(1===o)f=[e[0]-.5,e[0]+.5];else{for(f=[1.5*e[0]-.5*e[1]],u=1;u0;)p=d.c2p(M[x]),x--;for(p0;)y=m.c2p(A[x]),x--;if(y0&&(a=!0);for(var l=0;la){var o=a-r[t];return r[t]=a,o}}return 0},max:function(t,e,r,i){var a=i[e];if(n(a)){if(a=Number(a),!n(r[t]))return r[t]=a,a;if(r[t]c?t>o?t>1.1*i?i:t>1.1*a?a:o:t>s?s:t>l?l:c:Math.pow(10,Math.floor(Math.log(t)/Math.LN10))}function p(t,e,r,n,a,s){if(n&&t>o){var l=d(e,a,s),c=d(r,a,s),u=t===i?0:1;return l[u]!==c[u]}return Math.floor(r/t)-Math.floor(e/t)>.1}function d(t,e,r){var n=e.c2d(t,i,r).split("-");return""===n[0]&&(n.unshift(),n[0]="-"+n[0]),n}e.exports=function(t,e,r,n,a){var s,l,c=-1.1*e,h=-.1*e,p=t-h,d=r[0],m=r[1],g=Math.min(f(d+h,d+p,n,a),f(m+h,m+p,n,a)),v=Math.min(f(d+c,d+h,n,a),f(m+c,m+h,n,a));if(g>v&&vo){var y=s===i?1:6,x=s===i?"M12":"M1";return function(e,r){var o=n.c2d(e,i,a),s=o.indexOf("-",y);s>0&&(o=o.substr(0,s));var c=n.d2c(o,0,a);if(cr.r2l(z)&&(I=a.tickIncrement(I,_.size,!0,h)),S.start=r.l2r(I),L||i.nestedProperty(e,g+".start").set(S.start)}var P=_.end,D=r.r2l(T.end),R=void 0!==D;if((_.endFound||R)&&D!==r.r2l(P)){var B=R?D:i.aggNums(Math.max,null,p);S.end=r.l2r(B),R||i.nestedProperty(e,g+".start").set(S.end)}var F="autobin"+o;return!1===e._input[F]&&(e._input[g]=i.extendFlat({},e[g]||{}),delete e._input[F],delete e[F]),[S,p]}e.exports=function(t,e){if(!0===e.visible){var r,h,p,d,m=[],g=[],v=a.getFromId(t,"h"===e.orientation?e.yaxis||"y":e.xaxis||"x"),y="h"===e.orientation?"y":"x",x={x:"y",y:"x"}[y],b=e[y+"calendar"],_=e.cumulative,w=f(t,e,v,y),k=w[0],M=w[1],A="string"==typeof k.size,T=[],S=A?T:k,E=[],C=[],L=[],z=0,O=e.histnorm,I=e.histfunc,P=-1!==O.indexOf("density");_.enabled&&P&&(O=O.replace(/ ?density$/,""),P=!1);var D,R="max"===I||"min"===I?null:0,B=s.count,F=l[O],N=!1,j=function(t){return v.r2c(t,0,b)};for(i.isArrayOrTypedArray(e[x])&&"count"!==I&&(D=e[x],N="avg"===I,B=s[I]),r=j(k.start),p=j(k.end)+(r-a.tickIncrement(r,k.size,!1,b))/1e6;r=0&&d=0;n--)s(n);else if("increasing"===e){for(n=1;n=0;n--)t[n]+=t[n+1];"exclude"===r&&(t.push(0),t.shift())}}(g,_.direction,_.currentbin);var X=Math.min(m.length,g.length),Z=[],$=0,J=X-1;for(r=0;r=$;r--)if(g[r]){J=r;break}for(r=$;r<=J;r++)if(n(m[r])&&n(g[r])){var K={p:m[r],s:g[r],b:0};_.enabled||(K.pts=L[r],q?K.ph0=K.ph1=L[r].length?M[L[r][0]]:m[r]:(K.ph0=V(T[r]),K.ph1=V(T[r+1],!0))),Z.push(K)}return 1===Z.length&&(Z[0].width1=a.tickIncrement(Z[0].p,k.size,!1,b)-Z[0].p),o(Z,e),i.isArrayOrTypedArray(e.selectedpoints)&&i.tagSelected(Z,e,W),Z}}},{"../../lib":696,"../../plots/cartesian/axes":744,"../bar/arrays_to_calcdata":836,"./average":965,"./bin_functions":967,"./bin_label_vals":968,"./norm_functions":975,"fast-isnumeric":214}],970:[function(t,e,r){"use strict";var n=t("../../lib"),i=n.nestedProperty,a=t("./attributes"),o={x:[{aStr:"xbins.start",name:"start"},{aStr:"xbins.end",name:"end"},{aStr:"xbins.size",name:"size"},{aStr:"nbinsx",name:"nbins"}],y:[{aStr:"ybins.start",name:"start"},{aStr:"ybins.end",name:"end"},{aStr:"ybins.size",name:"size"},{aStr:"nbinsy",name:"nbins"}]};e.exports=function(t,e){var r,s,l,c,u,f,h,p=e._histogramBinOpts={},d="overlay"===e.barmode;function m(t){return n.coerce(l._input,l,a,t)}for(r=0;rA&&g.splice(A,g.length-A),y.length>A&&y.splice(A,y.length-A),c(e,"x",g,m,_,k,x),c(e,"y",y,v,w,M,b);var T=[],S=[],E=[],C="string"==typeof e.xbins.size,L="string"==typeof e.ybins.size,z=[],O=[],I=C?z:e.xbins,P=L?O:e.ybins,D=0,R=[],B=[],F=e.histnorm,N=e.histfunc,j=-1!==F.indexOf("density"),V="max"===N||"min"===N?null:0,U=a.count,q=o[F],H=!1,G=[],W=[],Y="z"in e?e.z:"marker"in e&&Array.isArray(e.marker.color)?e.marker.color:"";Y&&"count"!==N&&(H="avg"===N,U=a[N]);var X=e.xbins,Z=_(X.start),$=_(X.end)+(Z-i.tickIncrement(Z,X.size,!1,x))/1e6;for(r=Z;r<$;r=i.tickIncrement(r,X.size,!1,x))S.push(V),z.push(r),H&&E.push(0);z.push(r);var J=S.length,K=_(e.xbins.start),Q=(r-K)/J,tt=k(K+Q/2);for(Z=w((X=e.ybins).start),$=w(X.end)+(Z-i.tickIncrement(Z,X.size,!1,b))/1e6,r=Z;r<$;r=i.tickIncrement(r,X.size,!1,b)){T.push(S.slice()),O.push(r);var et=new Array(J);for(l=0;l=0&&p=0&&d0?Number(d):p;else if("string"!=typeof d)u.size=p;else{var m=d.charAt(0),g=d.substr(1);((g=n(g)?Number(g):0)<=0||"date"!==l||"M"!==m||g!==Math.round(g))&&(u.size=p)}}e.exports=function(t,e){var r,n,i,a;function u(t){return o.coerce(i._input,i,s,t)}for(r=0;r0)u=a(t.alphahull,f);else{var p=["x","y","z"].indexOf(t.delaunayaxis);u=i(f.map(function(t){return[t[(p+1)%3],t[(p+2)%3]]}))}var d={positions:f,cells:u,lightPosition:[t.lightposition.x,t.lightposition.y,t.lightposition.z],ambient:t.lighting.ambient,diffuse:t.lighting.diffuse,specular:t.lighting.specular,roughness:t.lighting.roughness,fresnel:t.lighting.fresnel,vertexNormalsEpsilon:t.lighting.vertexnormalsepsilon,faceNormalsEpsilon:t.lighting.facenormalsepsilon,opacity:t.opacity,contourEnable:t.contour.show,contourColor:l(t.contour.color).slice(0,3),contourWidth:t.contour.width,useFacetNormals:t.flatshading};t.intensity?(this.color="#fff",d.vertexIntensity=t.intensity,d.vertexIntensityBounds=[t.cmin,t.cmax],d.colormap=s(t.colorscale)):t.vertexcolor?(this.color=t.vertexcolor[0],d.vertexColors=h(t.vertexcolor)):t.facecolor?(this.color=t.facecolor[0],d.cellColors=h(t.facecolor)):(this.color=t.color,d.meshColor=l(t.color)),this.mesh.update(d)},f.dispose=function(){this.scene.glplot.remove(this.mesh),this.mesh.dispose()},e.exports=function(t,e){var r=t.glplot.gl,i=n({gl:r}),a=new u(t,i,e.uid);return i._trace=a,a.update(e),t.glplot.add(i),a}},{"../../lib/gl_format_color":692,"../../lib/str2rgbarray":719,"../../plots/gl3d/zip3":798,"alpha-shape":52,"convex-hull":118,"delaunay-triangulate":150,"gl-mesh3d":268}],989:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib"),a=t("../../components/colorscale/defaults"),o=t("./attributes");e.exports=function(t,e,r,s){function l(r,n){return i.coerce(t,e,o,r,n)}function c(t){var e=t.map(function(t){var e=l(t);return e&&i.isArrayOrTypedArray(e)?e:null});return e.every(function(t){return t&&t.length===e[0].length})&&e}var u=c(["x","y","z"]),f=c(["i","j","k"]);u?(f&&f.forEach(function(t){for(var e=0;ed):p=_>y,d=_;var w=s(y,x,b,_);w.pos=v,w.yc=(y+_)/2,w.i=g,w.dir=p?"increasing":"decreasing",h&&(w.tx=e.text[g]),m.push(w)}}return e._extremes[n._id]=a.findExtremes(n,u.concat(c),{padded:!0}),m.length&&(m[0].t={labels:{open:i(t,"open:")+" ",high:i(t,"high:")+" ",low:i(t,"low:")+" ",close:i(t,"close:")+" "}}),m}e.exports={calc:function(t,e){var r=a.getFromId(t,e.xaxis),i=a.getFromId(t,e.yaxis),o=function(t,e,r){var i=r._minDiff;if(!i){var a,o=t._fullData,s=[];for(i=1/0,a=0;a"+u.labels[x]+n.hoverLabelText(s,b):((y=i.extendFlat({},h)).y0=y.y1=_,y.yLabelVal=b,y.yLabel=u.labels[x]+n.hoverLabelText(s,b),y.name="",f.push(y),g[b]=y)}return f}function f(t,e,r,i){var a=t.cd,o=t.ya,u=a[0].trace,f=a[0].t,h=c(t,e,r,i);if(!h)return[];var p=a[h.index],d=h.index=p.i,m=p.dir;function g(t){return f.labels[t]+n.hoverLabelText(o,u[t][d])}var v=p.hi||u.hoverinfo,y=v.split("+"),x="all"===v,b=x||-1!==y.indexOf("y"),_=x||-1!==y.indexOf("text"),w=b?[g("open"),g("high"),g("low"),g("close")+" "+l[m]]:[];return _&&s(p,u,w),h.extraText=w.join("
"),h.y0=h.y1=o.c2p(p.yc,!0),[h]}e.exports={hoverPoints:function(t,e,r,n){return t.cd[0].trace.hoverlabel.split?u(t,e,r,n):f(t,e,r,n)},hoverSplit:u,hoverOnPoints:f}},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051}],995:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"ohlc",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","showLegend"],meta:{},attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc").calc,plot:t("./plot"),style:t("./style"),hoverPoints:t("./hover").hoverPoints,selectPoints:t("./select")}},{"../../plots/cartesian":756,"./attributes":991,"./calc":992,"./defaults":993,"./hover":994,"./plot":997,"./select":998,"./style":999}],996:[function(t,e,r){"use strict";var n=t("../../registry");e.exports=function(t,e,r,i){var a=r("x"),o=r("open"),s=r("high"),l=r("low"),c=r("close");if(r("hoverlabel.split"),n.getComponentMethod("calendars","handleTraceDefaults")(t,e,["x"],i),o&&s&&l&&c){var u=Math.min(o.length,s.length,l.length,c.length);return a&&(u=Math.min(u,a.length)),e._length=u,u}}},{"../../registry":827}],997:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib");e.exports=function(t,e,r,a){var o=e.xaxis,s=e.yaxis;i.makeTraceGroups(a,r,"trace ohlc").each(function(t){var r=n.select(this),a=t[0],l=a.t,c=a.trace;if(e.isRangePlot||(a.node3=r),!0!==c.visible||l.empty)r.remove();else{var u=l.tickLen,f=r.selectAll("path").data(i.identity);f.enter().append("path"),f.exit().remove(),f.attr("d",function(t){var e=o.c2p(t.pos,!0),r=o.c2p(t.pos-u,!0),n=o.c2p(t.pos+u,!0);return"M"+r+","+s.c2p(t.o,!0)+"H"+e+"M"+e+","+s.c2p(t.h,!0)+"V"+s.c2p(t.l,!0)+"M"+n+","+s.c2p(t.c,!0)+"H"+e})}})}},{"../../lib":696,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],998:[function(t,e,r){"use strict";e.exports=function(t,e){var r,n=t.cd,i=t.xaxis,a=t.yaxis,o=[],s=n[0].t.bPos||0;if(!1===e)for(r=0;r=t.length)return!1;if(void 0!==e[t[r]])return!1;e[t[r]]=!0}return!0}(t.map(function(t){return t.displayindex})))for(e=0;e0;c&&(o="array");var u=r("categoryorder",o);"array"===u?(r("categoryarray"),r("ticktext")):(delete t.categoryarray,delete t.ticktext),c||"array"!==u||(e.categoryorder="trace")}}e.exports=function(t,e,r,f){function h(r,i){return n.coerce(t,e,l,r,i)}var p=s(t,e,{name:"dimensions",handleItemDefaults:u}),d=function(t,e,r,o,s){s("line.shape");var l=s("line.color",o.colorway[0]);if(i(t,"line")&&n.isArrayOrTypedArray(l)){if(l.length)return s("line.colorscale"),a(t,e,o,s,{prefix:"line.",cLetter:"c"}),l.length;e.line.color=r}return 1/0}(t,e,r,f,h);o(e,f,h),Array.isArray(p)&&p.length||(e.visible=!1),c(e,p,"values",d),h("hoveron"),h("arrangement"),h("bundlecolors"),h("sortpaths"),h("counts");var m={family:f.font.family,size:Math.round(f.font.size),color:f.font.color};n.coerceFont(h,"labelfont",m);var g={family:f.font.family,size:Math.round(f.font.size/1.2),color:f.font.color};n.coerceFont(h,"tickfont",g)}},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/domain":770,"../parcoords/merge_length":1015,"./attributes":1e3}],1004:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.calc=t("./calc"),n.plot=t("./plot"),n.colorbar={container:"line",min:"cmin",max:"cmax"},n.moduleType="trace",n.name="parcats",n.basePlotModule=t("./base_plot"),n.categories=["noOpacity"],n.meta={},e.exports=n},{"./attributes":1e3,"./base_plot":1001,"./calc":1002,"./defaults":1003,"./plot":1006}],1005:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../plot_api/plot_api"),a=t("../../components/fx"),o=t("../../lib"),s=t("../../components/drawing"),l=t("tinycolor2"),c=t("../../lib/svg_text_utils");function u(t,e,r,i){var a=t.map(function(t,e,r){var n,i=r[0],a=e.margin||{l:80,r:80,t:100,b:80},o=i.trace,s=o.domain,l=e.width,c=e.height,u=Math.floor(l*(s.x[1]-s.x[0])),f=Math.floor(c*(s.y[1]-s.y[0])),h=s.x[0]*l+a.l,p=e.height-s.y[1]*e.height+a.t,d=o.line.shape;n="all"===o.hoverinfo?["count","probability"]:o.hoverinfo.split("+");var m={key:o.uid,model:i,x:h,y:p,width:u,height:f,hoveron:o.hoveron,hoverinfoItems:n,arrangement:o.arrangement,bundlecolors:o.bundlecolors,sortpaths:o.sortpaths,labelfont:o.labelfont,categorylabelfont:o.tickfont,pathShape:d,dragDimension:null,margin:a,paths:[],dimensions:[],graphDiv:t,traceSelection:null,pathSelection:null,dimensionSelection:null};i.dimensions&&(R(m),D(m));return m}.bind(0,e,r)),l=i.selectAll("g.parcatslayer").data([null]);l.enter().append("g").attr("class","parcatslayer").style("pointer-events","all");var u=l.selectAll("g.trace.parcats").data(a,f),g=u.enter().append("g").attr("class","trace parcats");u.attr("transform",function(t){return"translate("+t.x+", "+t.y+")"}),g.append("g").attr("class","paths");var x=u.select("g.paths").selectAll("path.path").data(function(t){return t.paths},f);x.attr("fill",function(t){return t.model.color});var w=x.enter().append("path").attr("class","path").attr("stroke-opacity",0).attr("fill",function(t){return t.model.color}).attr("fill-opacity",0);y(w),x.attr("d",function(t){return t.svgD}),w.empty()||x.sort(p),x.exit().remove(),x.on("mouseover",d).on("mouseout",m).on("click",v),g.append("g").attr("class","dimensions");var k=u.select("g.dimensions").selectAll("g.dimension").data(function(t){return t.dimensions},f);k.enter().append("g").attr("class","dimension"),k.attr("transform",function(t){return"translate("+t.x+", 0)"}),k.exit().remove();var M=k.selectAll("g.category").data(function(t){return t.categories},f),A=M.enter().append("g").attr("class","category");M.attr("transform",function(t){return"translate(0, "+t.y+")"}),A.append("rect").attr("class","catrect").attr("pointer-events","none"),M.select("rect.catrect").attr("fill","none").attr("width",function(t){return t.width}).attr("height",function(t){return t.height}),b(A);var z=M.selectAll("rect.bandrect").data(function(t){return t.bands},f);z.each(function(){o.raiseToTop(this)}),z.attr("fill",function(t){return t.color});var O=z.enter().append("rect").attr("class","bandrect").attr("stroke-opacity",0).attr("fill",function(t){return t.color}).attr("fill-opacity",0);z.attr("fill",function(t){return t.color}).attr("width",function(t){return t.width}).attr("height",function(t){return t.height}).attr("y",function(t){return t.y}).attr("cursor",function(t){return"fixed"===t.parcatsViewModel.arrangement?"default":"perpendicular"===t.parcatsViewModel.arrangement?"ns-resize":"move"}),_(O),z.exit().remove(),A.append("text").attr("class","catlabel").attr("pointer-events","none");var I=e._fullLayout.paper_bgcolor;M.select("text.catlabel").attr("text-anchor",function(t){return h(t)?"start":"end"}).attr("alignment-baseline","middle").style("text-shadow",I+" -1px 1px 2px, "+I+" 1px 1px 2px, "+I+" 1px -1px 2px, "+I+" -1px -1px 2px").style("fill","rgb(0, 0, 0)").attr("x",function(t){return h(t)?t.width+5:-5}).attr("y",function(t){return t.height/2}).text(function(t){return t.model.categoryLabel}).each(function(t){s.font(n.select(this),t.parcatsViewModel.categorylabelfont),c.convertToTspans(n.select(this),e)}),A.append("text").attr("class","dimlabel"),M.select("text.dimlabel").attr("text-anchor","middle").attr("alignment-baseline","baseline").attr("cursor",function(t){return"fixed"===t.parcatsViewModel.arrangement?"default":"ew-resize"}).attr("x",function(t){return t.width/2}).attr("y",-5).text(function(t,e){return 0===e?t.parcatsViewModel.model.dimensions[t.model.dimensionInd].dimensionLabel:null}).each(function(t){s.font(n.select(this),t.parcatsViewModel.labelfont)}),M.selectAll("rect.bandrect").on("mouseover",T).on("mouseout",S),M.exit().remove(),k.call(n.behavior.drag().origin(function(t){return{x:t.x,y:0}}).on("dragstart",E).on("drag",C).on("dragend",L)),u.each(function(t){t.traceSelection=n.select(this),t.pathSelection=n.select(this).selectAll("g.paths").selectAll("path.path"),t.dimensionSelection=n.select(this).selectAll("g.dimensions").selectAll("g.dimension")}),u.exit().remove()}function f(t){return t.key}function h(t){var e=t.parcatsViewModel.dimensions.length,r=t.parcatsViewModel.dimensions[e-1].model.dimensionInd;return t.model.dimensionInd===r}function p(t,e){return t.model.rawColor>e.model.rawColor?1:t.model.rawColor"),k=n.mouse(u)[0];a.loneHover({x:v-h.left+p.left,y:y-h.top+p.top,text:w,color:t.model.color,borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontSize:10,fontColor:b,idealAlign:k1&&c.displayInd===l.dimensions.length-1?(r=o.left,i="left"):(r=o.left+o.width,i="right");var f=[];-1!==s.parcatsViewModel.hoverinfoItems.indexOf("count")&&f.push(["Count:",s.model.count].join(" ")),-1!==s.parcatsViewModel.hoverinfoItems.indexOf("probability")&&f.push(["P("+s.model.categoryLabel+"):",(s.model.count/s.parcatsViewModel.model.count).toFixed(3)].join(" "));var h=f.join("
");return{x:r-t.left,y:u-t.top,text:h,color:"lightgray",borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontSize:12,fontColor:"black",idealAlign:i}}function T(t){if(!t.parcatsViewModel.dragDimension&&-1===t.parcatsViewModel.hoverinfoItems.indexOf("skip")){if(n.mouse(this)[1]<-1)return;var e,r=t.parcatsViewModel.graphDiv,i=r._fullLayout,s=i._paperdiv.node().getBoundingClientRect(),c=t.parcatsViewModel.hoveron;if("color"===c?(!function(t){var e=n.select(t).datum(),r=w(e);x(r),r.each(function(){o.raiseToTop(this)}),n.select(t.parentNode).selectAll("rect.bandrect").filter(function(t){return t.color===e.color}).each(function(){o.raiseToTop(this),n.select(this).attr("stroke","black").attr("stroke-width",1.5)})}(this),M(this,"plotly_hover",n.event)):(!function(t){n.select(t.parentNode).selectAll("rect.bandrect").each(function(t){var e=w(t);x(e),e.each(function(){o.raiseToTop(this)})}),n.select(t.parentNode).select("rect.catrect").attr("stroke","black").attr("stroke-width",2.5)}(this),k(this,"plotly_hover",n.event)),-1===t.parcatsViewModel.hoverinfoItems.indexOf("none"))"category"===c?e=A(s,this):"color"===c?e=function(t,e){var r,i,a=e.getBoundingClientRect(),o=n.select(e).datum(),s=o.categoryViewModel,c=s.parcatsViewModel,u=c.model.dimensions[s.model.dimensionInd],f=a.y+a.height/2;c.dimensions.length>1&&u.displayInd===c.dimensions.length-1?(r=a.left,i="left"):(r=a.left+a.width,i="right");var h=s.model.categoryLabel,p=o.parcatsViewModel.model.count,d=0;o.categoryViewModel.bands.forEach(function(t){t.color===o.color&&(d+=t.count)});var m=s.model.count,g=0;c.pathSelection.each(function(t){t.model.color===o.color&&(g+=t.model.count)});var v=[];if(-1!==s.parcatsViewModel.hoverinfoItems.indexOf("count")&&v.push(["Count:",d].join(" ")),-1!==s.parcatsViewModel.hoverinfoItems.indexOf("probability")){var y="P(color \u2229 "+h+"): "+(d/p).toFixed(3);v.push(y);var x="P("+h+" | color): "+(d/g).toFixed(3);v.push(x);var b="P(color | "+h+"): "+(d/m).toFixed(3);v.push(b)}var _=v.join("
"),w=l.mostReadable(o.color,["black","white"]);return{x:r-t.left,y:f-t.top,text:_,color:o.color,borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontColor:w,fontSize:10,idealAlign:i}}(s,this):"dimension"===c&&(e=function(t,e){var r=[];return n.select(e.parentNode.parentNode).selectAll("g.category").select("rect.catrect").each(function(){r.push(A(t,this))}),r}(s,this)),e&&a.multiHovers(e,{container:i._hoverlayer.node(),outerContainer:i._paper.node(),gd:r})}}function S(t){var e=t.parcatsViewModel;if(!e.dragDimension&&(y(e.pathSelection),b(e.dimensionSelection.selectAll("g.category")),_(e.dimensionSelection.selectAll("g.category").selectAll("rect.bandrect")),a.loneUnhover(e.graphDiv._fullLayout._hoverlayer.node()),e.pathSelection.sort(p),-1===e.hoverinfoItems.indexOf("skip"))){"color"===t.parcatsViewModel.hoveron?M(this,"plotly_unhover",n.event):k(this,"plotly_unhover",n.event)}}function E(t){"fixed"!==t.parcatsViewModel.arrangement&&(t.dragDimensionDisplayInd=t.model.displayInd,t.initialDragDimensionDisplayInds=t.parcatsViewModel.model.dimensions.map(function(t){return t.displayInd}),t.dragHasMoved=!1,t.dragCategoryDisplayInd=null,n.select(this).selectAll("g.category").select("rect.catrect").each(function(e){var r=n.mouse(this)[0],i=n.mouse(this)[1];-2<=r&&r<=e.width+2&&-2<=i&&i<=e.height+2&&(t.dragCategoryDisplayInd=e.model.displayInd,t.initialDragCategoryDisplayInds=t.model.categories.map(function(t){return t.displayInd}),e.model.dragY=e.y,o.raiseToTop(this.parentNode),n.select(this.parentNode).selectAll("rect.bandrect").each(function(e){e.yf.y+f.height/2&&(o.model.displayInd=f.model.displayInd,f.model.displayInd=l),t.dragCategoryDisplayInd=o.model.displayInd}if(null===t.dragCategoryDisplayInd||"freeform"===t.parcatsViewModel.arrangement){a.model.dragX=n.event.x;var h=t.parcatsViewModel.dimensions[r],p=t.parcatsViewModel.dimensions[i];void 0!==h&&a.model.dragXp.x&&(a.model.displayInd=p.model.displayInd,p.model.displayInd=t.dragDimensionDisplayInd),t.dragDimensionDisplayInd=a.model.displayInd}R(t.parcatsViewModel),D(t.parcatsViewModel),I(t.parcatsViewModel),O(t.parcatsViewModel)}}function L(t){if("fixed"!==t.parcatsViewModel.arrangement&&null!==t.dragDimensionDisplayInd){n.select(this).selectAll("text").attr("font-weight","normal");var e={},r=z(t.parcatsViewModel),a=t.parcatsViewModel.model.dimensions.map(function(t){return t.displayInd}),o=t.initialDragDimensionDisplayInds.some(function(t,e){return t!==a[e]});o&&a.forEach(function(r,n){var i=t.parcatsViewModel.model.dimensions[n].containerInd;e["dimensions["+i+"].displayindex"]=r});var s=!1;if(null!==t.dragCategoryDisplayInd){var l=t.model.categories.map(function(t){return t.displayInd});if(s=t.initialDragCategoryDisplayInds.some(function(t,e){return t!==l[e]})){var c=t.model.categories.slice().sort(function(t,e){return t.displayInd-e.displayInd}),u=c.map(function(t){return t.categoryValue}),f=c.map(function(t){return t.categoryLabel});e["dimensions["+t.model.containerInd+"].categoryarray"]=[u],e["dimensions["+t.model.containerInd+"].ticktext"]=[f],e["dimensions["+t.model.containerInd+"].categoryorder"]="array"}}if(-1===t.parcatsViewModel.hoverinfoItems.indexOf("skip")&&!t.dragHasMoved&&t.potentialClickBand&&("color"===t.parcatsViewModel.hoveron?M(t.potentialClickBand,"plotly_click",n.event.sourceEvent):k(t.potentialClickBand,"plotly_click",n.event.sourceEvent)),t.model.dragX=null,null!==t.dragCategoryDisplayInd)t.parcatsViewModel.dimensions[t.dragDimensionDisplayInd].categories[t.dragCategoryDisplayInd].model.dragY=null,t.dragCategoryDisplayInd=null;t.dragDimensionDisplayInd=null,t.parcatsViewModel.dragDimension=null,t.dragHasMoved=null,t.potentialClickBand=null,R(t.parcatsViewModel),D(t.parcatsViewModel),n.transition().duration(300).ease("cubic-in-out").each(function(){I(t.parcatsViewModel,!0),O(t.parcatsViewModel,!0)}).each("end",function(){(o||s)&&i.restyle(t.parcatsViewModel.graphDiv,e,[r])})}}function z(t){for(var e,r=t.graphDiv._fullData,n=0;n=0;s--)u+="C"+c[s]+","+(e[s+1]+i)+" "+l[s]+","+(e[s]+i)+" "+(t[s]+r[s])+","+(e[s]+i),u+="l-"+r[s]+",0 ";return u+="Z"}function D(t){var e=t.dimensions,r=t.model,n=e.map(function(t){return t.categories.map(function(t){return t.y})}),i=t.model.dimensions.map(function(t){return t.categories.map(function(t){return t.displayInd})}),a=t.model.dimensions.map(function(t){return t.displayInd}),o=t.dimensions.map(function(t){return t.model.dimensionInd}),s=e.map(function(t){return t.x}),l=e.map(function(t){return t.width}),c=[];for(var u in r.paths)r.paths.hasOwnProperty(u)&&c.push(r.paths[u]);function f(t){var e=t.categoryInds.map(function(t,e){return i[e][t]});return o.map(function(t){return e[t]})}c.sort(function(e,r){var n=f(e),i=f(r);return"backward"===t.sortpaths&&(n.reverse(),i.reverse()),n.push(e.valueInds[0]),i.push(r.valueInds[0]),t.bundlecolors&&(n.unshift(e.rawColor),i.unshift(r.rawColor)),ni?1:0});for(var h=new Array(c.length),p=e[0].model.count,d=e[0].categories.map(function(t){return t.height}).reduce(function(t,e){return t+e}),m=0;m0?d*(v.count/p):0;for(var y,x=new Array(n.length),b=0;b1?(t.width-80-16)/(n-1):0)*i;var a,o,s,l,c,u=[],f=t.model.maxCats,h=e.categories.length,p=e.count,d=t.height-8*(f-1),m=8*(f-h)/2,g=e.categories.map(function(t){return{displayInd:t.displayInd,categoryInd:t.categoryInd}});for(g.sort(function(t,e){return t.displayInd-e.displayInd}),c=0;c0?o.count/p*d:0,s={key:o.valueInds[0],model:o,width:16,height:a,y:null!==o.dragY?o.dragY:m,bands:[],parcatsViewModel:t},m=m+a+8,u.push(s);return{key:e.dimensionInd,x:null!==e.dragX?e.dragX:r,y:0,width:16,model:e,categories:u,parcatsViewModel:t,dragCategoryDisplayInd:null,dragDimensionDisplayInd:null,initialDragDimensionDisplayInds:null,initialDragCategoryDisplayInds:null,dragHasMoved:null,potentialClickBand:null}}e.exports=function(t,e,r,n){u(r,t,n,e)}},{"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/svg_text_utils":720,"../../plot_api/plot_api":731,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,tinycolor2:514}],1006:[function(t,e,r){"use strict";var n=t("./parcats");e.exports=function(t,e,r,i){var a=t._fullLayout,o=a._paper,s=a._size;n(t,o,e,{width:s.w,height:s.h,margin:{t:s.t,r:s.r,b:s.b,l:s.l}},r,i)}},{"./parcats":1005}],1007:[function(t,e,r){"use strict";var n=t("../../components/colorscale/attributes"),i=t("../../components/colorbar/attributes"),a=t("../../plots/cartesian/layout_attributes"),o=t("../../plots/font_attributes"),s=t("../../plots/domain").attributes,l=t("../../lib/extend").extendFlat,c=t("../../plot_api/plot_template").templatedArray;e.exports={domain:s({name:"parcoords",trace:!0,editType:"calc"}),hoverlabel:void 0,labelfont:o({editType:"calc"}),tickfont:o({editType:"calc"}),rangefont:o({editType:"calc"}),dimensions:c("dimension",{label:{valType:"string",editType:"calc"},tickvals:l({},a.tickvals,{editType:"calc"}),ticktext:l({},a.ticktext,{editType:"calc"}),tickformat:{valType:"string",dflt:"3s",editType:"calc"},visible:{valType:"boolean",dflt:!0,editType:"calc"},range:{valType:"info_array",items:[{valType:"number",editType:"calc"},{valType:"number",editType:"calc"}],editType:"calc"},constraintrange:{valType:"info_array",freeLength:!0,dimensions:"1-2",items:[{valType:"number",editType:"calc"},{valType:"number",editType:"calc"}],editType:"calc"},multiselect:{valType:"boolean",dflt:!0,editType:"calc"},values:{valType:"data_array",editType:"calc"},editType:"calc"}),line:l(n("line",{colorscaleDflt:"Viridis",autoColorDflt:!1,editTypeOverride:"calc"}),{colorbar:i,editType:"calc"})}},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/plot_template":734,"../../plots/cartesian/layout_attributes":757,"../../plots/domain":770,"../../plots/font_attributes":771}],1008:[function(t,e,r){"use strict";var n=t("./constants"),i=t("/home/circleci/plotly.js/test/image/strict-d3.js"),a=t("../../lib/gup").keyFun,o=t("../../lib/gup").repeat,s=t("../../lib").sorterAsc,l=n.bar.snapRatio;function c(t,e){return t*(1-l)+e*l}var u=n.bar.snapClose;function f(t,e){return t*(1-u)+e*u}function h(t,e,r){if(d(e,r))return e;for(var n=t[0],i=n,a=1;a=0;a--){var o=t[a];if(e>f(n,o))return c(n,i);if(e>o||a===t.length-1)return c(o,n);i=n,n=o}}function d(t,e){for(var r=0;r=e[r][0]&&t<=e[r][1])return!0;return!1}function m(t){t.attr("x",-n.bar.captureWidth/2).attr("width",n.bar.captureWidth)}function g(t){t.attr("visibility","visible").style("visibility","visible").attr("fill","yellow").attr("opacity",0)}function v(t){if(!t.brush.filterSpecified)return"0,"+t.height;for(var e,r,n,i=y(t.brush.filter.getConsolidated(),t.height),a=[0],o=i.length?i[0][0]:null,s=0;se){h=r;break}}if(a=u,isNaN(a)&&(a=isNaN(f)||isNaN(h)?isNaN(f)?h:f:e-c[f][1]t[1]+r||e=.9*t[1]+.1*t[0]?"n":e<=.9*t[0]+.1*t[1]?"s":"ns"}(d,e);m&&(o.interval=l[a],o.intervalPix=d,o.region=m)}}if(t.ordinal&&!o.region){var g=t.unitTickvals,v=t.unitToPaddedPx.invert(e);for(r=0;r=x[0]&&v<=x[1]){o.clickableOrdinalRange=x;break}}}return o}function k(t){t.on("mousemove",function(t){if(i.event.preventDefault(),!t.parent.inBrushDrag){var e=w(t,t.height-i.mouse(this)[1]-2*n.verticalPadding),r="crosshair";e.clickableOrdinalRange?r="pointer":e.region&&(r=e.region+"-resize"),i.select(document.body).style("cursor",r)}}).on("mouseleave",function(t){t.parent.inBrushDrag||x()}).call(i.behavior.drag().on("dragstart",function(t){i.event.sourceEvent.stopPropagation();var e=t.height-i.mouse(this)[1]-2*n.verticalPadding,r=t.unitToPaddedPx.invert(e),a=t.brush,o=w(t,e),s=o.interval,l=a.svgBrush;if(l.wasDragged=!1,l.grabbingBar="ns"===o.region,l.grabbingBar){var c=s.map(t.unitToPaddedPx);l.grabPoint=e-c[0]-n.verticalPadding,l.barLength=c[1]-c[0]}l.clickableOrdinalRange=o.clickableOrdinalRange,l.stayingIntervals=t.multiselect&&a.filterSpecified?a.filter.getConsolidated():[],s&&(l.stayingIntervals=l.stayingIntervals.filter(function(t){return t[0]!==s[0]&&t[1]!==s[1]})),l.startExtent=o.region?s["s"===o.region?1:0]:r,t.parent.inBrushDrag=!0,l.brushStartCallback()}).on("drag",function(t){i.event.sourceEvent.stopPropagation();var e=t.height-i.mouse(this)[1]-2*n.verticalPadding,r=t.brush.svgBrush;r.wasDragged=!0,r.grabbingBar?r.newExtent=[e-r.grabPoint,e+r.barLength-r.grabPoint].map(t.unitToPaddedPx.invert):r.newExtent=[r.startExtent,t.unitToPaddedPx.invert(e)].sort(s);var a=Math.max(0,-r.newExtent[0]),o=Math.max(0,r.newExtent[1]-1);r.newExtent[0]+=a,r.newExtent[1]-=o,r.grabbingBar&&(r.newExtent[1]+=a,r.newExtent[0]-=o),t.brush.filterSpecified=!0,r.extent=r.stayingIntervals.concat([r.newExtent]),r.brushCallback(t),_(this.parentNode)}).on("dragend",function(t){i.event.sourceEvent.stopPropagation();var e=t.brush,r=e.filter,n=e.svgBrush,a=n.grabbingBar;if(n.grabbingBar=!1,n.grabLocation=void 0,t.parent.inBrushDrag=!1,x(),!n.wasDragged)return n.wasDragged=void 0,n.clickableOrdinalRange?e.filterSpecified&&t.multiselect?n.extent.push(n.clickableOrdinalRange):(n.extent=[n.clickableOrdinalRange],e.filterSpecified=!0):a?(n.extent=n.stayingIntervals,0===n.extent.length&&A(e)):A(e),n.brushCallback(t),_(this.parentNode),void n.brushEndCallback(e.filterSpecified?r.getConsolidated():[]);var o=function(){r.set(r.getConsolidated())};if(t.ordinal){var s=t.unitTickvals;s[s.length-1]n.newExtent[0];n.extent=n.stayingIntervals.concat(l?[n.newExtent]:[]),n.extent.length||A(e),n.brushCallback(t),l?_(this.parentNode,o):(o(),_(this.parentNode))}else o();n.brushEndCallback(e.filterSpecified?r.getConsolidated():[])}))}function M(t,e){return t[0]-e[0]}function A(t){t.filterSpecified=!1,t.svgBrush.extent=[[0,1]]}function T(t){for(var e,r=t.slice(),n=[],i=r.shift();i;){for(e=i.slice();(i=r.shift())&&i[0]<=e[1];)e[1]=Math.max(e[1],i[1]);n.push(e)}return n}e.exports={makeBrush:function(t,e,r,n,i,a){var o,l=function(){var t,e,r=[];return{set:function(n){r=n.map(function(t){return t.slice().sort(s)}).sort(M),t=T(r),e=r.reduce(function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]},[1/0,-1/0])},get:function(){return r.slice()},getConsolidated:function(){return t},getBounds:function(){return e}}}();return l.set(r),{filter:l,filterSpecified:e,svgBrush:{extent:[],brushStartCallback:n,brushCallback:(o=i,function(t){var e=t.brush,r=function(t){return t.svgBrush.extent.map(function(t){return t.slice()})}(e).slice();e.filter.set(r),o()}),brushEndCallback:a}}},ensureAxisBrush:function(t){var e=t.selectAll("."+n.cn.axisBrush).data(o,a);e.enter().append("g").classed(n.cn.axisBrush,!0),function(t){var e=t.selectAll(".background").data(o);e.enter().append("rect").classed("background",!0).call(m).call(g).style("pointer-events","auto").attr("transform","translate(0 "+n.verticalPadding+")"),e.call(k).attr("height",function(t){return t.height-n.verticalPadding});var r=t.selectAll(".highlight-shadow").data(o);r.enter().append("line").classed("highlight-shadow",!0).attr("x",-n.bar.width/2).attr("stroke-width",n.bar.width+n.bar.strokeWidth).attr("stroke",n.bar.strokeColor).attr("opacity",n.bar.strokeOpacity).attr("stroke-linecap","butt"),r.attr("y1",function(t){return t.height}).call(b);var i=t.selectAll(".highlight").data(o);i.enter().append("line").classed("highlight",!0).attr("x",-n.bar.width/2).attr("stroke-width",n.bar.width-n.bar.strokeWidth).attr("stroke",n.bar.fillColor).attr("opacity",n.bar.fillOpacity).attr("stroke-linecap","butt"),i.attr("y1",function(t){return t.height}).call(b)}(e)},cleanRanges:function(t,e){if(Array.isArray(t[0])?(t=t.map(function(t){return t.sort(s)}),t=e.multiselect?T(t.sort(M)):[t[0]]):t=[t.sort(s)],e.tickvals){var r=e.tickvals.slice().sort(s);if(!(t=t.map(function(t){var e=[h(r,t[0],[]),p(r,t[1],[])];if(e[1]>e[0])return e}).filter(function(t){return t})).length)return}return t.length>1?t:t[0]}}},{"../../lib":696,"../../lib/gup":693,"./constants":1011,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1009:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../plots/get_data").getModuleCalcData,a=t("./plot"),o=t("../../constants/xmlns_namespaces");r.name="parcoords",r.plot=function(t){var e=i(t.calcdata,"parcoords")[0];e.length&&a(t,e)},r.clean=function(t,e,r,n){var i=n._has&&n._has("parcoords"),a=e._has&&e._has("parcoords");i&&!a&&(n._paperdiv.selectAll(".parcoords").remove(),n._glimages.selectAll("*").remove())},r.toSVG=function(t){var e=t._fullLayout._glimages,r=n.select(t).selectAll(".svg-container");r.filter(function(t,e){return e===r.size()-1}).selectAll(".gl-canvas-context, .gl-canvas-focus").each(function(){var t=this.toDataURL("image/png");e.append("svg:image").attr({xmlns:o.svg,"xlink:href":t,preserveAspectRatio:"none",x:0,y:0,width:this.width,height:this.height})}),window.setTimeout(function(){n.selectAll("#filterBarPattern").attr("id","filterBarPattern")},60)}},{"../../constants/xmlns_namespaces":674,"../../plots/get_data":781,"./plot":1017,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1010:[function(t,e,r){"use strict";var n=t("../../components/colorscale/has_colorscale"),i=t("../../components/colorscale/calc"),a=t("../../lib"),o=t("../../lib/gup").wrap;e.exports=function(t,e){var r=!!e.line.colorscale&&a.isArrayOrTypedArray(e.line.color),s=r?e.line.color:function(t){for(var e=new Array(t),r=0;ru&&(n.log("parcoords traces support up to "+u+" dimensions at the moment"),d.splice(u));var m=s(t,e,{name:"dimensions",handleItemDefaults:h}),g=function(t,e,r,o,s){var l=s("line.color",r);if(i(t,"line")&&n.isArrayOrTypedArray(l)){if(l.length)return s("line.colorscale"),a(t,e,o,s,{prefix:"line.",cLetter:"c"}),l.length;e.line.color=r}return 1/0}(t,e,r,c,p);o(e,c,p),Array.isArray(m)&&m.length||(e.visible=!1),f(e,m,"values",g);var v={family:c.font.family,size:Math.round(c.font.size/1.2),color:c.font.color};n.coerceFont(p,"labelfont",v),n.coerceFont(p,"tickfont",v),n.coerceFont(p,"rangefont",v)}},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696,"../../plots/array_container_defaults":740,"../../plots/domain":770,"./attributes":1007,"./axisbrush":1008,"./constants":1011,"./merge_length":1015}],1013:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.calc=t("./calc"),n.plot=t("./plot"),n.colorbar={container:"line",min:"cmin",max:"cmax"},n.moduleType="trace",n.name="parcoords",n.basePlotModule=t("./base_plot"),n.categories=["gl","regl","noOpacity"],n.meta={},e.exports=n},{"./attributes":1007,"./base_plot":1009,"./calc":1010,"./defaults":1012,"./plot":1017}],1014:[function(t,e,r){"use strict";var n=t("glslify"),i=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D palette;\nuniform sampler2D mask;\nuniform float maskHeight;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec4 unit_1 = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit_1, unit_1);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nconst int bitsPerByte = 8;\n\nint mod2(int a) {\n return a - 2 * (a / 2);\n}\n\nint mod8(int a) {\n return a - 8 * (a / 8);\n}\n\nvec4 zero = vec4(0, 0, 0, 0);\nvec4 unit_0 = vec4(1, 1, 1, 1);\nvec2 xyProjection = vec2(1, 1);\n\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\n return mat4(clamp(m[0], lo[0], hi[0]),\n clamp(m[1], lo[1], hi[1]),\n clamp(m[2], lo[2], hi[2]),\n clamp(m[3], lo[3], hi[3]));\n}\n\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\n return mclamp(p, lo, hi) == p;\n}\n\nbool withinBoundingBox(\n mat4 d[4],\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD\n ) {\n\n return mshow(d[0], loA, hiA) &&\n mshow(d[1], loB, hiB) &&\n mshow(d[2], loC, hiC) &&\n mshow(d[3], loD, hiD);\n}\n\nbool withinRasterMask(mat4 d[4], sampler2D mask, float height) {\n bool result = true;\n int bitInByteStepper;\n float valY, valueY, scaleX;\n int hit, bitmask, valX;\n for(int i = 0; i < 4; i++) {\n for(int j = 0; j < 4; j++) {\n for(int k = 0; k < 4; k++) {\n bitInByteStepper = mod8(j * 4 + k);\n valX = i * 2 + j / 2;\n valY = d[i][j][k];\n valueY = valY * (height - 1.0) + 0.5;\n scaleX = (float(valX) + 0.5) / 8.0;\n hit = int(texture2D(mask, vec2(scaleX, (valueY + 0.5) / height))[3] * 255.0) / int(pow(2.0, float(bitInByteStepper)));\n result = result && mod2(hit) == 1;\n }\n }\n }\n return result;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D,\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD,\n sampler2D mask, float maskHeight\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n float show = float(\n withinBoundingBox(dims, loA, hiA, loB, hiB, loC, hiC, loD, hiD)\n && withinRasterMask(dims, mask, maskHeight)\n );\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n float depthOrHide = depth + 2.0 * (1.0 - show);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depthOrHide,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD,\n mask, maskHeight\n );\n\n float clampedColorIndex = clamp((prominence - colorClamp[0]) / (colorClamp[1] - colorClamp[0]), 0.0, 1.0);\n fragColor = texture2D(palette, vec2((clampedColorIndex * 255.0 + 0.5) / 256.0, 0.5));\n}\n"]),a=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D palette;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec2 xyProjection = vec2(1, 1);\n\nvec4 unit = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit, unit);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depth,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D\n );\n\n float clampedColorIndex = clamp((prominence - colorClamp[0]) / (colorClamp[1] - colorClamp[0]), 0.0, 1.0);\n fragColor = texture2D(palette, vec2((clampedColorIndex * 255.0 + 0.5) / 256.0, 0.5));\n}\n"]),o=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 p0, p1, p2, p3,\n p4, p5, p6, p7,\n p8, p9, pa, pb,\n pc, pd, pe;\n\nattribute vec4 pf;\n\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution,\n viewBoxPosition,\n viewBoxSize;\n\nuniform sampler2D mask;\nuniform float maskHeight;\n\nuniform vec2 colorClamp;\n\nvarying vec4 fragColor;\n\nvec4 unit_1 = vec4(1, 1, 1, 1);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * unit_1, unit_1);\n}\n\nfloat axisY(\n float x,\n mat4 d[4],\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D\n ) {\n\n float y1 = val(d[0], dim1A) + val(d[1], dim1B) + val(d[2], dim1C) + val(d[3], dim1D);\n float y2 = val(d[0], dim2A) + val(d[1], dim2B) + val(d[2], dim2C) + val(d[3], dim2D);\n return y1 * (1.0 - x) + y2 * x;\n}\n\nconst int bitsPerByte = 8;\n\nint mod2(int a) {\n return a - 2 * (a / 2);\n}\n\nint mod8(int a) {\n return a - 8 * (a / 8);\n}\n\nvec4 zero = vec4(0, 0, 0, 0);\nvec4 unit_0 = vec4(1, 1, 1, 1);\nvec2 xyProjection = vec2(1, 1);\n\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\n return mat4(clamp(m[0], lo[0], hi[0]),\n clamp(m[1], lo[1], hi[1]),\n clamp(m[2], lo[2], hi[2]),\n clamp(m[3], lo[3], hi[3]));\n}\n\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\n return mclamp(p, lo, hi) == p;\n}\n\nbool withinBoundingBox(\n mat4 d[4],\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD\n ) {\n\n return mshow(d[0], loA, hiA) &&\n mshow(d[1], loB, hiB) &&\n mshow(d[2], loC, hiC) &&\n mshow(d[3], loD, hiD);\n}\n\nbool withinRasterMask(mat4 d[4], sampler2D mask, float height) {\n bool result = true;\n int bitInByteStepper;\n float valY, valueY, scaleX;\n int hit, bitmask, valX;\n for(int i = 0; i < 4; i++) {\n for(int j = 0; j < 4; j++) {\n for(int k = 0; k < 4; k++) {\n bitInByteStepper = mod8(j * 4 + k);\n valX = i * 2 + j / 2;\n valY = d[i][j][k];\n valueY = valY * (height - 1.0) + 0.5;\n scaleX = (float(valX) + 0.5) / 8.0;\n hit = int(texture2D(mask, vec2(scaleX, (valueY + 0.5) / height))[3] * 255.0) / int(pow(2.0, float(bitInByteStepper)));\n result = result && mod2(hit) == 1;\n }\n }\n }\n return result;\n}\n\nvec4 position(\n float depth,\n vec2 resolution, vec2 viewBoxPosition, vec2 viewBoxSize,\n mat4 dims[4],\n float signum,\n mat4 dim1A, mat4 dim2A, mat4 dim1B, mat4 dim2B, mat4 dim1C, mat4 dim2C, mat4 dim1D, mat4 dim2D,\n mat4 loA, mat4 hiA, mat4 loB, mat4 hiB, mat4 loC, mat4 hiC, mat4 loD, mat4 hiD,\n sampler2D mask, float maskHeight\n ) {\n\n float x = 0.5 * signum + 0.5;\n float y = axisY(x, dims, dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D);\n\n float show = float(\n withinBoundingBox(dims, loA, hiA, loB, hiB, loC, hiC, loD, hiD)\n && withinRasterMask(dims, mask, maskHeight)\n );\n\n vec2 viewBoxXY = viewBoxPosition + viewBoxSize * vec2(x, y);\n float depthOrHide = depth + 2.0 * (1.0 - show);\n\n return vec4(\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\n depthOrHide,\n 1.0\n );\n}\n\nvoid main() {\n\n float prominence = abs(pf[3]);\n\n mat4 p[4];\n p[0] = mat4(p0, p1, p2, p3);\n p[1] = mat4(p4, p5, p6, p7);\n p[2] = mat4(p8, p9, pa, pb);\n p[3] = mat4(pc, pd, pe, abs(pf));\n\n gl_Position = position(\n 1.0 - prominence,\n resolution, viewBoxPosition, viewBoxSize,\n p,\n sign(pf[3]),\n dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD,\n mask, maskHeight\n );\n\n fragColor = vec4(pf.rgb, 1.0);\n}\n"]),s=n(["precision lowp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n gl_FragColor = fragColor;\n}\n"]),l=t("../../lib"),c=1e-6,u=1e-7,f=2048,h=64,p=2,d=4,m=8,g=h/m,v=[119,119,119],y=new Uint8Array(4),x=new Uint8Array(4),b={shape:[256,1],format:"rgba",type:"uint8",mag:"nearest",min:"nearest"};function _(t,e,r,n,i){var a=t._gl;a.enable(a.SCISSOR_TEST),a.scissor(e,r,n,i),t.clear({color:[0,0,0,0],depth:1})}function w(t,e,r,n,i,a){var o=a.key;r.drawCompleted||(!function(t){t.read({x:0,y:0,width:1,height:1,data:y})}(t),r.drawCompleted=!0),function s(l){var c;c=Math.min(n,i-l*n),a.offset=p*l*n,a.count=p*c,0===l&&(window.cancelAnimationFrame(r.currentRafs[o]),delete r.currentRafs[o],_(t,a.scissorX,a.scissorY,a.scissorWidth,a.viewBoxSize[1])),r.clearOnly||(e(a),l*n+c>>8*e)%256/255}function M(t,e,r){var n,i,a,o=[];for(i=0;i=h-4?k(o,h-2-s):.5);return a}(d,p,i);!function(t,e,r){for(var n=0;n<16;n++)t["p"+n.toString(16)](M(e,r,n))}(C,d,o),L=S.texture(l.extendFlat({data:function(t,e,r){for(var n=[],i=0;i<256;i++){var a=t(i/255);n.push((e?v:a).concat(r))}return n}(r.unitToColor,A,Math.round(255*(A?a:1)))},b))}var I=[0,1];var P=[];function D(t,e,n,i,a,o,s,c,u,f,h){var p,d,m,g,v=[t,e],y=[0,1].map(function(){return[0,1,2,3].map(function(){return new Float32Array(16)})});for(p=0;p<2;p++)for(g=v[p],d=0;d<4;d++)for(m=0;m<16;m++)y[p][d][m]=m+16*d===g?1:0;var x=r.lines.canvasOverdrag,b=r.domain,_=r.canvasWidth,w=r.canvasHeight;return l.extendFlat({key:s,resolution:[_,w],viewBoxPosition:[n+x,i],viewBoxSize:[a,o],i:t,ii:e,dim1A:y[0][0],dim1B:y[0][1],dim1C:y[0][2],dim1D:y[0][3],dim2A:y[1][0],dim2B:y[1][1],dim2C:y[1][2],dim2D:y[1][3],colorClamp:I,scissorX:(c===u?0:n+x)+(r.pad.l-x)+r.layoutWidth*b.x[0],scissorWidth:(c===f?_-n+x:a+.5)+(c===u?n+x:0),scissorY:i+r.pad.b+r.layoutHeight*b.y[0],scissorHeight:o,viewportX:r.pad.l-x+r.layoutWidth*b.x[0],viewportY:r.pad.b+r.layoutHeight*b.y[0],viewportWidth:_,viewportHeight:w},h)}return{setColorDomain:function(t){I[0]=t[0],I[1]=t[1]},render:function(t,e,n){var i,a,o,s=t.length,l=1/0,c=-1/0;for(i=0;ic&&(c=t[i].dim2.canvasX,o=i),t[i].dim1.canvasXn._length&&(M=M.slice(0,n._length));var A,T=n.tickvals;function S(t,e){return{val:t,text:A[e]}}function E(t,e){return t.val-e.val}if(Array.isArray(T)&&T.length){A=n.ticktext,Array.isArray(A)&&A.length?A.length>T.length?A=A.slice(0,T.length):T.length>A.length&&(T=T.slice(0,A.length)):A=T.map(o.format(n.tickformat));for(var C=1;C=r||s>=n)return;var l=t.lineLayer.readPixel(a,n-1-s),c=0!==l[3],u=c?l[2]+256*(l[1]+256*l[0]):null,f={x:a,y:s,clientX:e.clientX,clientY:e.clientY,dataIndex:t.model.key,curveNumber:u};u!==M&&(c?d.hover(f):d.unhover&&d.unhover(f),M=u)}}),k.style("opacity",function(t){return t.pick?.01:1}),e.style("background","rgba(255, 255, 255, 0)");var A=e.selectAll("."+i.cn.parcoords).data(w,c);A.exit().remove(),A.enter().append("g").classed(i.cn.parcoords,!0).style("shape-rendering","crispEdges").style("pointer-events","none"),A.attr("transform",function(t){return"translate("+t.model.translateX+","+t.model.translateY+")"});var T=A.selectAll("."+i.cn.parcoordsControlView).data(u,c);T.enter().append("g").classed(i.cn.parcoordsControlView,!0),T.attr("transform",function(t){return"translate("+t.model.pad.l+","+t.model.pad.t+")"});var S=T.selectAll("."+i.cn.yAxis).data(function(t){return t.dimensions},c);function E(t,e){for(var r=e.panels||(e.panels=[]),n=t.data(),i=n.length-1,a=0;aline").attr("fill","none").attr("stroke","black").attr("stroke-opacity",.25).attr("stroke-width","1px"),L.selectAll("text").style("text-shadow","1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff").style("cursor","default").style("user-select","none");var z=C.selectAll("."+i.cn.axisHeading).data(u,c);z.enter().append("g").classed(i.cn.axisHeading,!0);var O=z.selectAll("."+i.cn.axisTitle).data(u,c);O.enter().append("text").classed(i.cn.axisTitle,!0).attr("text-anchor","middle").style("cursor","ew-resize").style("user-select","none").style("pointer-events","auto"),O.attr("transform","translate(0,"+-i.axisTitleOffset+")").text(function(t){return t.label}).each(function(t){s.font(o.select(this),t.model.labelFont)});var I=C.selectAll("."+i.cn.axisExtent).data(u,c);I.enter().append("g").classed(i.cn.axisExtent,!0);var P=I.selectAll("."+i.cn.axisExtentTop).data(u,c);P.enter().append("g").classed(i.cn.axisExtentTop,!0),P.attr("transform","translate(0,"+-i.axisExtentOffset+")");var D=P.selectAll("."+i.cn.axisExtentTopText).data(u,c);function R(t,e){if(t.ordinal)return"";var r=t.domainScale.domain();return o.format(t.tickFormat)(r[e?r.length-1:0])}D.enter().append("text").classed(i.cn.axisExtentTopText,!0).call(y),D.text(function(t){return R(t,!0)}).each(function(t){s.font(o.select(this),t.model.rangeFont)});var B=I.selectAll("."+i.cn.axisExtentBottom).data(u,c);B.enter().append("g").classed(i.cn.axisExtentBottom,!0),B.attr("transform",function(t){return"translate(0,"+(t.model.height+i.axisExtentOffset)+")"});var F=B.selectAll("."+i.cn.axisExtentBottomText).data(u,c);F.enter().append("text").classed(i.cn.axisExtentBottomText,!0).attr("dy","0.75em").call(y),F.text(function(t){return R(t)}).each(function(t){s.font(o.select(this),t.model.rangeFont)}),h.ensureAxisBrush(C)}},{"../../components/drawing":595,"../../lib":696,"../../lib/gup":693,"./axisbrush":1008,"./constants":1011,"./lines":1014,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1017:[function(t,e,r){"use strict";var n=t("./parcoords"),i=t("../../lib/prepare_regl");e.exports=function(t,e){var r=t._fullLayout,a=r._toppaper,o=r._paperdiv,s=r._glcontainer;if(i(t)){var l={},c={},u={},f={},h=r._size;e.forEach(function(e,r){var n=e[0].trace;u[r]=n.index;var i=f[r]=n._fullInput.index;l[r]=t.data[i].dimensions,c[r]=t.data[i].dimensions.slice()});n(o,a,s,e,{width:h.w,height:h.h,margin:{t:h.t,r:h.r,b:h.b,l:h.l}},{filterChanged:function(e,n,i){var a=c[e][n],o=i.map(function(t){return t.slice()}),s="dimensions["+n+"].constraintrange",l=r._tracePreGUI[t._fullData[u[e]]._fullInput.uid];if(void 0===l[s]){var h=a.constraintrange;l[s]=h||null}var p=t._fullData[u[e]].dimensions[n];o.length?(1===o.length&&(o=o[0]),a.constraintrange=o,p.constraintrange=o.slice(),o=[o]):(delete a.constraintrange,delete p.constraintrange,o=null);var d={};d[s]=o,t.emit("plotly_restyle",[d,[f[e]]])},hover:function(e){t.emit("plotly_hover",e)},unhover:function(e){t.emit("plotly_unhover",e)},axesMoved:function(e,r){function n(t){return!("visible"in t)||t.visible}function i(t,e,r){var n=e.indexOf(r),i=t.indexOf(n);return-1===i&&(i+=e.length),i}var a=function(t){return function(e,n){return i(r,t,e)-i(r,t,n)}}(c[e].filter(n));l[e].sort(a),c[e].filter(function(t){return!n(t)}).sort(function(t){return c[e].indexOf(t)}).forEach(function(t){l[e].splice(l[e].indexOf(t),1),l[e].splice(c[e].indexOf(t),0,t)}),t.emit("plotly_restyle",[{dimensions:[l[e]]},[f[e]]])}})}}},{"../../lib/prepare_regl":709,"./parcoords":1016}],1018:[function(t,e,r){"use strict";var n=t("../../components/color/attributes"),i=t("../../plots/font_attributes"),a=t("../../plots/attributes"),o=t("../../plots/domain").attributes,s=t("../../lib/extend").extendFlat,l=i({editType:"calc",arrayOk:!0,colorEditType:"plot"});e.exports={labels:{valType:"data_array",editType:"calc"},label0:{valType:"number",dflt:0,editType:"calc"},dlabel:{valType:"number",dflt:1,editType:"calc"},values:{valType:"data_array",editType:"calc"},marker:{colors:{valType:"data_array",editType:"calc"},line:{color:{valType:"color",dflt:n.defaultLine,arrayOk:!0,editType:"style"},width:{valType:"number",min:0,dflt:0,arrayOk:!0,editType:"style"},editType:"calc"},editType:"calc"},text:{valType:"data_array",editType:"calc"},hovertext:{valType:"string",dflt:"",arrayOk:!0,editType:"style"},scalegroup:{valType:"string",dflt:"",editType:"calc"},textinfo:{valType:"flaglist",flags:["label","text","value","percent"],extras:["none"],editType:"calc"},hoverinfo:s({},a.hoverinfo,{flags:["label","text","value","percent","name"]}),textposition:{valType:"enumerated",values:["inside","outside","auto","none"],dflt:"auto",arrayOk:!0,editType:"calc"},textfont:s({},l,{}),insidetextfont:s({},l,{}),outsidetextfont:s({},l,{}),title:{valType:"string",dflt:"",editType:"calc"},titleposition:{valType:"enumerated",values:["top left","top center","top right","middle center","bottom left","bottom center","bottom right"],editType:"calc"},titlefont:s({},l,{}),domain:o({name:"pie",trace:!0,editType:"calc"}),hole:{valType:"number",min:0,max:1,dflt:0,editType:"calc"},sort:{valType:"boolean",dflt:!0,editType:"calc"},direction:{valType:"enumerated",values:["clockwise","counterclockwise"],dflt:"counterclockwise",editType:"calc"},rotation:{valType:"number",min:-360,max:360,dflt:0,editType:"calc"},pull:{valType:"number",min:0,max:1,dflt:0,arrayOk:!0,editType:"calc"}}},{"../../components/color/attributes":569,"../../lib/extend":685,"../../plots/attributes":741,"../../plots/domain":770,"../../plots/font_attributes":771}],1019:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../plots/get_data").getModuleCalcData;r.name="pie",r.plot=function(t){var e=n.getModule("pie"),r=i(t.calcdata,e)[0];r.length&&e.plot(t,r)},r.clean=function(t,e,r,n){var i=n._has&&n._has("pie"),a=e._has&&e._has("pie");i&&!a&&n._pielayer.selectAll("g.trace").remove()}},{"../../plots/get_data":781,"../../registry":827}],1020:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../lib").isArrayOrTypedArray,a=t("tinycolor2"),o=t("../../components/color"),s=t("./helpers");r.calc=function(t,e){var r,l,c,u,f,h=e.values,p=i(h)&&h.length,d=e.labels,m=e.marker.colors||[],g=[],v=t._fullLayout,y=v._piecolormap,x={},b=0,_=v.hiddenlabels||[];if(e.dlabel)for(d=new Array(h.length),r=0;r")}}return g},r.crossTraceCalc=function(t){var e=t._fullLayout,r=t.calcdata,n=e.piecolorway,i=e._piecolormap;e.extendpiecolors&&(n=function(t){var e,r=JSON.stringify(t),n=l[r];if(!n){for(n=t.slice(),e=0;e0?1:-1)/2,y:a/(1+r*r/(n*n)),outside:!0}}function p(t,e){var r=t.trace,n=e.h*(r.domain.y[1]-r.domain.y[0]);return Math.min(t.titleBox.height,n/2)}function d(t){var e,r=t.pull;if(Array.isArray(r))for(r=0,e=0;er&&(r=t.pull[e]);return r}e.exports=function(t,e){var r=t._fullLayout;!function(t,e){for(var r,n,i=0;ii.vTotal/2?1:0)}(e),m.attr("stroke-linejoin","round"),m.each(function(){var m=n.select(this).selectAll("g.slice").data(e);m.enter().append("g").classed("slice",!0),m.exit().remove();var y=[[[],[]],[[],[]]],x=!1;m.each(function(e){if(e.hidden)n.select(this).selectAll("path,g").remove();else{e.pointNumber=e.i,e.curveNumber=v.index,y[e.pxmid[1]<0?0:1][e.pxmid[0]<0?0:1].push(e);var p=g.cx,d=g.cy,m=n.select(this),b=m.selectAll("path.surface").data([e]),_=!1,w=!1;if(b.enter().append("path").classed("surface",!0).style({"pointer-events":"all"}),m.select("path.textline").remove(),m.on("mouseover",function(){var a=t._fullLayout,o=t._fullData[v.index];if(!t._dragging&&!1!==a.hovermode){var s=o.hoverinfo;if(Array.isArray(s)&&(s=i.castHoverinfo({hoverinfo:[c.castOption(s,e.pts)],_module:v._module},a,0)),"all"===s&&(s="label+text+value+percent+name"),"none"!==s&&"skip"!==s&&s){var l=f(e,g),h=p+e.pxmid[0]*(1-l),m=d+e.pxmid[1]*(1-l),y=r.separators,x=[];if(-1!==s.indexOf("label")&&x.push(e.label),-1!==s.indexOf("text")){var b=c.castOption(o.hovertext||o.text,e.pts);b&&x.push(b)}-1!==s.indexOf("value")&&x.push(c.formatPieValue(e.v,y)),-1!==s.indexOf("percent")&&x.push(c.formatPiePercent(e.v/g.vTotal,y));var k=v.hoverlabel,M=k.font;i.loneHover({x0:h-l*g.r,x1:h+l*g.r,y:m,text:x.join("
"),name:-1!==s.indexOf("name")?o.name:void 0,idealAlign:e.pxmid[0]<0?"left":"right",color:c.castOption(k.bgcolor,e.pts)||e.color,borderColor:c.castOption(k.bordercolor,e.pts),fontFamily:c.castOption(M.family,e.pts),fontSize:c.castOption(M.size,e.pts),fontColor:c.castOption(M.color,e.pts)},{container:a._hoverlayer.node(),outerContainer:a._paper.node(),gd:t}),_=!0}t.emit("plotly_hover",{points:[u(e,o)],event:n.event}),w=!0}}).on("mouseout",function(r){var a=t._fullLayout,o=t._fullData[v.index];w&&(r.originalEvent=n.event,t.emit("plotly_unhover",{points:[u(e,o)],event:n.event}),w=!1),_&&(i.loneUnhover(a._hoverlayer.node()),_=!1)}).on("click",function(){var r=t._fullLayout,a=t._fullData[v.index];t._dragging||!1===r.hovermode||(t._hoverdata=[u(e,a)],i.click(t,n.event))}),v.pull){var k=+c.castOption(v.pull,e.pts)||0;k>0&&(p+=k*e.pxmid[0],d+=k*e.pxmid[1])}e.cxFinal=p,e.cyFinal=d;var M=v.hole;if(e.v===g.vTotal){var A="M"+(p+e.px0[0])+","+(d+e.px0[1])+L(e.px0,e.pxmid,!0,1)+L(e.pxmid,e.px0,!0,1)+"Z";M?b.attr("d","M"+(p+M*e.px0[0])+","+(d+M*e.px0[1])+L(e.px0,e.pxmid,!1,M)+L(e.pxmid,e.px0,!1,M)+"Z"+A):b.attr("d",A)}else{var T=L(e.px0,e.px1,!0,1);if(M){var S=1-M;b.attr("d","M"+(p+M*e.px1[0])+","+(d+M*e.px1[1])+L(e.px1,e.px0,!1,M)+"l"+S*e.px0[0]+","+S*e.px0[1]+T+"Z")}else b.attr("d","M"+p+","+d+"l"+e.px0[0]+","+e.px0[1]+T+"Z")}var E=c.castOption(v.textposition,e.pts),C=m.selectAll("g.slicetext").data(e.text&&"none"!==E?[0]:[]);C.enter().append("g").classed("slicetext",!0),C.exit().remove(),C.each(function(){var r=s.ensureSingle(n.select(this),"text","",function(t){t.attr("data-notex",1)});r.text(e.text).attr({class:"slicetext",transform:"","text-anchor":"middle"}).call(o.font,"outside"===E?function(t,e,r){var n=c.castOption(t.outsidetextfont.color,e.pts)||c.castOption(t.textfont.color,e.pts)||r.color,i=c.castOption(t.outsidetextfont.family,e.pts)||c.castOption(t.textfont.family,e.pts)||r.family,a=c.castOption(t.outsidetextfont.size,e.pts)||c.castOption(t.textfont.size,e.pts)||r.size;return{color:n,family:i,size:a}}(v,e,t._fullLayout.font):function(t,e,r){var n=c.castOption(t.insidetextfont.color,e.pts);!n&&t._input.textfont&&(n=c.castOption(t._input.textfont.color,e.pts));var i=c.castOption(t.insidetextfont.family,e.pts)||c.castOption(t.textfont.family,e.pts)||r.family,o=c.castOption(t.insidetextfont.size,e.pts)||c.castOption(t.textfont.size,e.pts)||r.size;return{color:n||a.contrast(e.color),family:i,size:o}}(v,e,t._fullLayout.font)).call(l.convertToTspans,t);var i,u=o.bBox(r.node());"outside"===E?i=h(u,e):(i=function(t,e,r){var n=Math.sqrt(t.width*t.width+t.height*t.height),i=t.width/t.height,a=Math.PI*Math.min(e.v/r.vTotal,.5),o=1-r.trace.hole,s=f(e,r),l={scale:s*r.r*2/n,rCenter:1-s,rotate:0};if(l.scale>=1)return l;var c=i+1/(2*Math.tan(a)),u=r.r*Math.min(1/(Math.sqrt(c*c+.5)+c),o/(Math.sqrt(i*i+o/2)+i)),h={scale:2*u/t.height,rCenter:Math.cos(u/r.r)-u*i/r.r,rotate:(180/Math.PI*e.midangle+720)%180-90},p=1/i,d=p+1/(2*Math.tan(a)),m=r.r*Math.min(1/(Math.sqrt(d*d+.5)+d),o/(Math.sqrt(p*p+o/2)+p)),g={scale:2*m/t.width,rCenter:Math.cos(m/r.r)-m/i/r.r,rotate:(180/Math.PI*e.midangle+810)%180-90},v=g.scale>h.scale?g:h;return l.scale<1&&v.scale>l.scale?v:l}(u,e,g),"auto"===E&&i.scale<1&&(r.call(o.font,v.outsidetextfont),v.outsidetextfont.family===v.insidetextfont.family&&v.outsidetextfont.size===v.insidetextfont.size||(u=o.bBox(r.node())),i=h(u,e)));var m=p+e.pxmid[0]*i.rCenter+(i.x||0),y=d+e.pxmid[1]*i.rCenter+(i.y||0);i.outside&&(e.yLabelMin=y-u.height/2,e.yLabelMid=y,e.yLabelMax=y+u.height/2,e.labelExtraX=0,e.labelExtraY=0,x=!0),r.attr("transform","translate("+m+","+y+")"+(i.scale<1?"scale("+i.scale+")":"")+(i.rotate?"rotate("+i.rotate+")":"")+"translate("+-(u.left+u.right)/2+","+-(u.top+u.bottom)/2+")")})}function L(t,r,n,i){return"a"+i*g.r+","+i*g.r+" 0 "+e.largeArc+(n?" 1 ":" 0 ")+i*(r[0]-t[0])+","+i*(r[1]-t[1])}});var b=n.select(this).selectAll("g.titletext").data(v.title?[0]:[]);b.enter().append("g").classed("titletext",!0),b.exit().remove(),b.each(function(){var e,i=s.ensureSingle(n.select(this),"text","",function(t){t.attr("data-notex",1)});i.text(v.title).attr({class:"titletext",transform:"","text-anchor":"middle"}).call(o.font,v.titlefont).call(l.convertToTspans,t),e="middle center"===v.titleposition?function(t){var e=Math.sqrt(t.titleBox.width*t.titleBox.width+t.titleBox.height*t.titleBox.height);return{x:t.cx,y:t.cy,scale:t.trace.hole*t.r*2/e,tx:0,ty:-t.titleBox.height/2+t.trace.titlefont.size}}(g):function(t,e){var r,n,i=1,a=1,o=t.trace,s={x:t.cx,y:t.cy},l={tx:0,ty:0};l.ty+=o.titlefont.size,n=d(o),-1!==o.titleposition.indexOf("top")?(s.y-=(1+n)*t.r,l.ty-=t.titleBox.height):-1!==o.titleposition.indexOf("bottom")&&(s.y+=(1+n)*t.r);-1!==o.titleposition.indexOf("left")?(r=e.w*(o.domain.x[1]-o.domain.x[0])/2+t.r,s.x-=(1+n)*t.r,l.tx+=t.titleBox.width/2):-1!==o.titleposition.indexOf("center")?r=e.w*(o.domain.x[1]-o.domain.x[0]):-1!==o.titleposition.indexOf("right")&&(r=e.w*(o.domain.x[1]-o.domain.x[0])/2+t.r,s.x+=(1+n)*t.r,l.tx-=t.titleBox.width/2);return i=r/t.titleBox.width,a=p(t,e)/t.titleBox.height,{x:s.x,y:s.y,scale:Math.min(i,a),tx:l.tx,ty:l.ty}}(g,r._size),i.attr("transform","translate("+e.x+","+e.y+")"+(e.scale<1?"scale("+e.scale+")":"")+"translate("+e.tx+","+e.ty+")")}),x&&function(t,e){var r,n,i,a,o,s,l,u,f,h,p,d,m;function g(t,e){return t.pxmid[1]-e.pxmid[1]}function v(t,e){return e.pxmid[1]-t.pxmid[1]}function y(t,r){r||(r={});var i,u,f,p,d,m,g=r.labelExtraY+(n?r.yLabelMax:r.yLabelMin),v=n?t.yLabelMin:t.yLabelMax,y=n?t.yLabelMax:t.yLabelMin,x=t.cyFinal+o(t.px0[1],t.px1[1]),b=g-v;if(b*l>0&&(t.labelExtraY=b),Array.isArray(e.pull))for(u=0;u=(c.castOption(e.pull,f.pts)||0)||((t.pxmid[1]-f.pxmid[1])*l>0?(p=f.cyFinal+o(f.px0[1],f.px1[1]),(b=p-v-t.labelExtraY)*l>0&&(t.labelExtraY+=b)):(y+t.labelExtraY-x)*l>0&&(i=3*s*Math.abs(u-h.indexOf(t)),d=f.cxFinal+a(f.px0[0],f.px1[0]),(m=d+i-(t.cxFinal+t.pxmid[0])-t.labelExtraX)*s>0&&(t.labelExtraX+=m)))}for(n=0;n<2;n++)for(i=n?g:v,o=n?Math.max:Math.min,l=n?1:-1,r=0;r<2;r++){for(a=r?Math.max:Math.min,s=r?1:-1,(u=t[n][r]).sort(i),f=t[1-n][r],h=f.concat(u),d=[],p=0;pMath.abs(c)?o+="l"+c*t.pxmid[0]/t.pxmid[1]+","+c+"H"+(i+t.labelExtraX+s):o+="l"+t.labelExtraX+","+l+"v"+(c-l)+"h"+s}else o+="V"+(t.yLabelMid+t.labelExtraY)+"h"+s;e.append("path").classed("textline",!0).call(a.stroke,v.outsidetextfont.color).attr({"stroke-width":Math.min(2,v.outsidetextfont.size/8),d:o,fill:"none"})}})})});setTimeout(function(){m.selectAll("tspan").each(function(){var t=n.select(this);t.attr("dy")&&t.attr("dy",t.attr("dy"))})},0)}},{"../../components/color":570,"../../components/drawing":595,"../../components/fx":612,"../../lib":696,"../../lib/svg_text_utils":720,"./event_data":1022,"./helpers":1023,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1028:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("./style_one");e.exports=function(t){t._fullLayout._pielayer.selectAll(".trace").each(function(t){var e=t[0].trace,r=n.select(this);r.style({opacity:e.opacity}),r.selectAll("path.surface").each(function(t){n.select(this).call(i,t,e)})})}},{"./style_one":1029,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1029:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("./helpers").castOption;e.exports=function(t,e,r){var a=r.marker.line,o=i(a.color,e.pts)||n.defaultLine,s=i(a.width,e.pts)||0;t.style({"stroke-width":s}).call(n.fill,e.color).call(n.stroke,o)}},{"../../components/color":570,"./helpers":1023}],1030:[function(t,e,r){"use strict";var n=t("../scatter/attributes");e.exports={x:n.x,y:n.y,xy:{valType:"data_array",editType:"calc"},indices:{valType:"data_array",editType:"calc"},xbounds:{valType:"data_array",editType:"calc"},ybounds:{valType:"data_array",editType:"calc"},text:n.text,marker:{color:{valType:"color",arrayOk:!1,editType:"calc"},opacity:{valType:"number",min:0,max:1,dflt:1,arrayOk:!1,editType:"calc"},blend:{valType:"boolean",dflt:null,editType:"calc"},sizemin:{valType:"number",min:.1,max:2,dflt:.5,editType:"calc"},sizemax:{valType:"number",min:.1,dflt:20,editType:"calc"},border:{color:{valType:"color",arrayOk:!1,editType:"calc"},arearatio:{valType:"number",min:0,max:1,dflt:0,editType:"calc"},editType:"calc"},editType:"calc"},transforms:void 0}},{"../scatter/attributes":1043}],1031:[function(t,e,r){"use strict";var n=t("gl-pointcloud2d"),i=t("../../lib/str2rgbarray"),a=t("../../plots/cartesian/autorange").findExtremes,o=t("../scatter/get_trace_color");function s(t,e){this.scene=t,this.uid=e,this.type="pointcloud",this.pickXData=[],this.pickYData=[],this.xData=[],this.yData=[],this.textLabels=[],this.color="rgb(0, 0, 0)",this.name="",this.hoverinfo="all",this.idToIndex=new Int32Array(0),this.bounds=[0,0,0,0],this.pointcloudOptions={positions:new Float32Array(0),idToIndex:this.idToIndex,sizemin:.5,sizemax:12,color:[0,0,0,1],areaRatio:1,borderColor:[0,0,0,1]},this.pointcloud=n(t.glplot,this.pointcloudOptions),this.pointcloud._trace=this}var l=s.prototype;l.handlePick=function(t){var e=this.idToIndex[t.pointId];return{trace:this,dataCoord:t.dataCoord,traceCoord:this.pickXYData?[this.pickXYData[2*e],this.pickXYData[2*e+1]]:[this.pickXData[e],this.pickYData[e]],textLabel:Array.isArray(this.textLabels)?this.textLabels[e]:this.textLabels,color:this.color,name:this.name,pointIndex:e,hoverinfo:this.hoverinfo}},l.update=function(t){this.index=t.index,this.textLabels=t.text,this.name=t.name,this.hoverinfo=t.hoverinfo,this.bounds=[1/0,1/0,-1/0,-1/0],this.updateFast(t),this.color=o(t,{})},l.updateFast=function(t){var e,r,n,o,s,l,c=this.xData=this.pickXData=t.x,u=this.yData=this.pickYData=t.y,f=this.pickXYData=t.xy,h=t.xbounds&&t.ybounds,p=t.indices,d=this.bounds;if(f){if(n=f,e=f.length>>>1,h)d[0]=t.xbounds[0],d[2]=t.xbounds[1],d[1]=t.ybounds[0],d[3]=t.ybounds[1];else for(l=0;ld[2]&&(d[2]=o),sd[3]&&(d[3]=s);if(p)r=p;else for(r=new Int32Array(e),l=0;ld[2]&&(d[2]=o),sd[3]&&(d[3]=s);this.idToIndex=r,this.pointcloudOptions.idToIndex=r,this.pointcloudOptions.positions=n;var m=i(t.marker.color),g=i(t.marker.border.color),v=t.opacity*t.marker.opacity;m[3]*=v,this.pointcloudOptions.color=m;var y=t.marker.blend;if(null===y){y=c.length<100||u.length<100}this.pointcloudOptions.blend=y,g[3]*=v,this.pointcloudOptions.borderColor=g;var x=t.marker.sizemin,b=Math.max(t.marker.sizemax,t.marker.sizemin);this.pointcloudOptions.sizeMin=x,this.pointcloudOptions.sizeMax=b,this.pointcloudOptions.areaRatio=t.marker.border.arearatio,this.pointcloud.update(this.pointcloudOptions);var _=this.scene.xaxis,w=this.scene.yaxis,k=b/2||.5;t._extremes[_._id]=a(_,[d[0],d[2]],{ppad:k}),t._extremes[w._id]=a(w,[d[1],d[3]],{ppad:k})},l.dispose=function(){this.pointcloud.dispose()},e.exports=function(t,e){var r=new s(t,e.uid);return r.update(e),r}},{"../../lib/str2rgbarray":719,"../../plots/cartesian/autorange":743,"../scatter/get_trace_color":1053,"gl-pointcloud2d":279}],1032:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes");e.exports=function(t,e,r){function a(r,a){return n.coerce(t,e,i,r,a)}a("x"),a("y"),a("xbounds"),a("ybounds"),t.xy&&t.xy instanceof Float32Array&&(e.xy=t.xy),t.indices&&t.indices instanceof Int32Array&&(e.indices=t.indices),a("text"),a("marker.color",r),a("marker.opacity"),a("marker.blend"),a("marker.sizemin"),a("marker.sizemax"),a("marker.border.color",r),a("marker.border.arearatio"),e._length=null}},{"../../lib":696,"./attributes":1030}],1033:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.calc=t("../scatter3d/calc"),n.plot=t("./convert"),n.moduleType="trace",n.name="pointcloud",n.basePlotModule=t("../../plots/gl2d"),n.categories=["gl","gl2d","showLegend"],n.meta={},e.exports=n},{"../../plots/gl2d":784,"../scatter3d/calc":1071,"./attributes":1030,"./convert":1031,"./defaults":1032}],1034:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),i=t("../../plots/attributes"),a=t("../../components/color/attributes"),o=t("../../components/fx/attributes"),s=t("../../plots/domain").attributes,l=t("../../lib/extend").extendFlat,c=t("../../plot_api/edit_types").overrideAll;(e.exports=c({hoverinfo:l({},i.hoverinfo,{flags:[],arrayOk:!1}),hoverlabel:o.hoverlabel,domain:s({name:"sankey",trace:!0}),orientation:{valType:"enumerated",values:["v","h"],dflt:"h"},valueformat:{valType:"string",dflt:".3s"},valuesuffix:{valType:"string",dflt:""},arrangement:{valType:"enumerated",values:["snap","perpendicular","freeform","fixed"],dflt:"snap"},textfont:n({}),node:{label:{valType:"data_array",dflt:[]},color:{valType:"color",arrayOk:!0},line:{color:{valType:"color",dflt:a.defaultLine,arrayOk:!0},width:{valType:"number",min:0,dflt:.5,arrayOk:!0}},pad:{valType:"number",arrayOk:!1,min:0,dflt:20},thickness:{valType:"number",arrayOk:!1,min:1,dflt:20},hoverinfo:{valType:"enumerated",values:["all","none","skip"],dflt:"all"},hoverlabel:o.hoverlabel},link:{label:{valType:"data_array",dflt:[]},color:{valType:"color",arrayOk:!0},line:{color:{valType:"color",dflt:a.defaultLine,arrayOk:!0},width:{valType:"number",min:0,dflt:0,arrayOk:!0}},source:{valType:"data_array",dflt:[]},target:{valType:"data_array",dflt:[]},value:{valType:"data_array",dflt:[]},hoverinfo:{valType:"enumerated",values:["all","none","skip"],dflt:"all"},hoverlabel:o.hoverlabel}},"calc","nested")).transforms=void 0},{"../../components/color/attributes":569,"../../components/fx/attributes":604,"../../lib/extend":685,"../../plot_api/edit_types":727,"../../plots/attributes":741,"../../plots/domain":770,"../../plots/font_attributes":771}],1035:[function(t,e,r){"use strict";var n=t("../../plot_api/edit_types").overrideAll,i=t("../../plots/get_data").getModuleCalcData,a=t("./plot"),o=t("../../components/fx/layout_attributes");r.name="sankey",r.baseLayoutAttrOverrides=n({hoverlabel:o.hoverlabel},"plot","nested"),r.plot=function(t){var e=i(t.calcdata,"sankey")[0];a(t,e)},r.clean=function(t,e,r,n){var i=n._has&&n._has("sankey"),a=e._has&&e._has("sankey");i&&!a&&n._paperdiv.selectAll(".sankey").remove()}},{"../../components/fx/layout_attributes":613,"../../plot_api/edit_types":727,"../../plots/get_data":781,"./plot":1040}],1036:[function(t,e,r){"use strict";var n=t("strongly-connected-components"),i=t("../../lib"),a=t("../../lib/gup").wrap;e.exports=function(t,e){return function(t,e,r){for(var a=t.length,o=i.init2dArray(a,0),s=0;s1})}(e.node.label,e.link.source,e.link.target)&&(i.error("Circularity is present in the Sankey data. Removing all nodes and links."),e.link.label=[],e.link.source=[],e.link.target=[],e.link.value=[],e.link.color=[],e.node.label=[],e.node.color=[]),a({link:e.link,node:e.node})}},{"../../lib":696,"../../lib/gup":693,"strongly-connected-components":506}],1037:[function(t,e,r){"use strict";e.exports={nodeTextOffsetHorizontal:4,nodeTextOffsetVertical:3,nodePadAcross:10,sankeyIterations:50,forceIterations:5,forceTicksPerFrame:10,duration:500,ease:"cubic-in-out",cn:{sankey:"sankey",sankeyLinks:"sankey-links",sankeyLink:"sankey-link",sankeyNodeSet:"sankey-node-set",sankeyNode:"sankey-node",nodeRect:"node-rect",nodeCapture:"node-capture",nodeCentered:"node-entered",nodeLabelGuide:"node-label-guide",nodeLabel:"node-label",nodeLabelTextPath:"node-label-text-path"}}},{}],1038:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../components/color"),o=t("tinycolor2"),s=t("../../plots/domain").defaults,l=t("../../components/fx/hoverlabel_defaults"),c=t("../../plot_api/plot_template");e.exports=function(t,e,r,u){function f(r,a){return n.coerce(t,e,i,r,a)}var h=n.extendDeep(u.hoverlabel,t.hoverlabel),p=t.node,d=c.newContainer(e,"node");function m(t,e){return n.coerce(p,d,i.node,t,e)}m("label"),m("pad"),m("thickness"),m("line.color"),m("line.width"),m("hoverinfo",t.hoverinfo),l(p,d,m,h);var g=u.colorway;m("color",d.label.map(function(t,e){return a.addOpacity(function(t){return g[t%g.length]}(e),.8)}));var v=t.link,y=c.newContainer(e,"link");function x(t,e){return n.coerce(v,y,i.link,t,e)}x("label"),x("source"),x("target"),x("value"),x("line.color"),x("line.width"),x("hoverinfo",t.hoverinfo),l(v,y,x,h);var b=o(u.paper_bgcolor).getLuminance()<.333?"rgba(255, 255, 255, 0.6)":"rgba(0, 0, 0, 0.2)";x("color",n.repeat(b,y.value.length)),s(e,u,f),f("orientation"),f("valueformat"),f("valuesuffix"),f("arrangement"),n.coerceFont(f,"textfont",n.extendFlat({},u.font)),e._length=null}},{"../../components/color":570,"../../components/fx/hoverlabel_defaults":611,"../../lib":696,"../../plot_api/plot_template":734,"../../plots/domain":770,"./attributes":1034,tinycolor2:514}],1039:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.calc=t("./calc"),n.plot=t("./plot"),n.moduleType="trace",n.name="sankey",n.basePlotModule=t("./base_plot"),n.categories=["noOpacity"],n.meta={},e.exports=n},{"./attributes":1034,"./base_plot":1035,"./calc":1036,"./defaults":1038,"./plot":1040}],1040:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("./render"),a=t("../../components/fx"),o=t("../../components/color"),s=t("../../lib"),l=t("./constants").cn,c=s._;function u(t){return""!==t}function f(t,e){return t.filter(function(t){return t.key===e.traceId})}function h(t,e){n.select(t).select("path").style("fill-opacity",e),n.select(t).select("rect").style("fill-opacity",e)}function p(t){n.select(t).select("text.name").style("fill","black")}function d(t){return function(e){return-1!==t.node.sourceLinks.indexOf(e.link)||-1!==t.node.targetLinks.indexOf(e.link)}}function m(t){return function(e){return-1!==e.node.sourceLinks.indexOf(t.link)||-1!==e.node.targetLinks.indexOf(t.link)}}function g(t,e,r){e&&r&&f(r,e).selectAll("."+l.sankeyLink).filter(d(e)).call(y.bind(0,e,r,!1))}function v(t,e,r){e&&r&&f(r,e).selectAll("."+l.sankeyLink).filter(d(e)).call(x.bind(0,e,r,!1))}function y(t,e,r,n){var i=n.datum().link.label;n.style("fill-opacity",.4),i&&f(e,t).selectAll("."+l.sankeyLink).filter(function(t){return t.link.label===i}).style("fill-opacity",.4),r&&f(e,t).selectAll("."+l.sankeyNode).filter(m(t)).call(g)}function x(t,e,r,n){var i=n.datum().link.label;n.style("fill-opacity",function(t){return t.tinyColorAlpha}),i&&f(e,t).selectAll("."+l.sankeyLink).filter(function(t){return t.link.label===i}).style("fill-opacity",function(t){return t.tinyColorAlpha}),r&&f(e,t).selectAll(l.sankeyNode).filter(m(t)).call(v)}function b(t,e){var r=t.hoverlabel||{},n=s.nestedProperty(r,e).get();return!Array.isArray(n)&&n}e.exports=function(t,e){var r=t._fullLayout,s=r._paper,f=r._size,d=c(t,"source:")+" ",m=c(t,"target:")+" ",_=c(t,"incoming flow count:")+" ",w=c(t,"outgoing flow count:")+" ";i(s,e,{width:f.w,height:f.h,margin:{t:f.t,r:f.r,b:f.b,l:f.l}},{linkEvents:{hover:function(e,r,i){!1!==t._fullLayout.hovermode&&(n.select(e).call(y.bind(0,r,i,!0)),"skip"!==r.link.trace.link.hoverinfo&&t.emit("plotly_hover",{event:n.event,points:[r.link]}))},follow:function(e,i){if(!1!==t._fullLayout.hovermode){var s=i.link.trace.link;if("none"!==s.hoverinfo&&"skip"!==s.hoverinfo){var l=t._fullLayout._paperdiv.node().getBoundingClientRect(),c=e.getBoundingClientRect(),f=c.left+c.width/2,g=c.top+c.height/2,v=a.loneHover({x:f-l.left,y:g-l.top,name:n.format(i.valueFormat)(i.link.value)+i.valueSuffix,text:[i.link.label||"",d+i.link.source.label,m+i.link.target.label].filter(u).join("
"),color:b(s,"bgcolor")||o.addOpacity(i.tinyColorHue,1),borderColor:b(s,"bordercolor"),fontFamily:b(s,"font.family"),fontSize:b(s,"font.size"),fontColor:b(s,"font.color"),idealAlign:n.event.x"),color:b(o,"bgcolor")||i.tinyColorHue,borderColor:b(o,"bordercolor"),fontFamily:b(o,"font.family"),fontSize:b(o,"font.size"),fontColor:b(o,"font.color"),idealAlign:"left"},{container:r._hoverlayer.node(),outerContainer:r._paper.node(),gd:t});h(v,.85),p(v)}}},unhover:function(e,i,o){!1!==t._fullLayout.hovermode&&(n.select(e).call(v,i,o),"skip"!==i.node.trace.node.hoverinfo&&t.emit("plotly_unhover",{event:n.event,points:[i.node]}),a.loneUnhover(r._hoverlayer.node()))},select:function(e,r,i){var o=r.node;o.originalEvent=n.event,t._hoverdata=[o],n.select(e).call(v,r,i),a.click(t,{target:!0})}}})}},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"./constants":1037,"./render":1041,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1041:[function(t,e,r){"use strict";var n=t("./constants"),i=t("/home/circleci/plotly.js/test/image/strict-d3.js"),a=t("tinycolor2"),o=t("../../components/color"),s=t("../../components/drawing"),l=t("@plotly/d3-sankey").sankey,c=t("d3-force"),u=t("../../lib"),f=u.isArrayOrTypedArray,h=u.isIndex,p=t("../../lib/gup"),d=p.keyFun,m=p.repeat,g=p.unwrap;function v(t){t.lastDraggedX=t.x,t.lastDraggedY=t.y}function y(t){return function(e){return e.node.originalX===t.node.originalX}}function x(t){for(var e=0;e1||t.linkLineWidth>0}function T(t){return"translate("+t.translateX+","+t.translateY+")"+(t.horizontal?"matrix(1 0 0 1 0 0)":"matrix(0 1 1 0 0 0)")}function S(t){return"translate("+(t.horizontal?0:t.labelY)+" "+(t.horizontal?t.labelY:0)+")"}function E(t){return i.svg.line()([[t.horizontal?t.left?-t.sizeAcross:t.visibleWidth+n.nodeTextOffsetHorizontal:n.nodeTextOffsetHorizontal,0],[t.horizontal?t.left?-n.nodeTextOffsetHorizontal:t.sizeAcross:t.visibleHeight-n.nodeTextOffsetHorizontal,0]])}function C(t){return t.horizontal?"matrix(1 0 0 1 0 0)":"matrix(0 1 1 0 0 0)"}function L(t){return t.horizontal?"scale(1 1)":"scale(-1 1)"}function z(t){return t.darkBackground&&!t.horizontal?"rgb(255,255,255)":"rgb(0,0,0)"}function O(t){return t.horizontal&&t.left?"100%":"0%"}function I(t,e,r){t.on(".basic",null).on("mouseover.basic",function(t){t.interactionState.dragInProgress||(r.hover(this,t,e),t.interactionState.hovered=[this,t])}).on("mousemove.basic",function(t){t.interactionState.dragInProgress||(r.follow(this,t),t.interactionState.hovered=[this,t])}).on("mouseout.basic",function(t){t.interactionState.dragInProgress||(r.unhover(this,t,e),t.interactionState.hovered=!1)}).on("click.basic",function(t){t.interactionState.hovered&&(r.unhover(this,t,e),t.interactionState.hovered=!1),t.interactionState.dragInProgress||r.select(this,t,e)})}function P(t,e,r){var a=i.behavior.drag().origin(function(t){return t.node}).on("dragstart",function(i){if("fixed"!==i.arrangement&&(u.raiseToTop(this),i.interactionState.dragInProgress=i.node,v(i.node),i.interactionState.hovered&&(r.nodeEvents.unhover.apply(0,i.interactionState.hovered),i.interactionState.hovered=!1),"snap"===i.arrangement)){var a=i.traceId+"|"+Math.floor(i.node.originalX);i.forceLayouts[a]?i.forceLayouts[a].alpha(1):function(t,e,r){var i=r.sankey.nodes().filter(function(t){return t.originalX===r.node.originalX});r.forceLayouts[e]=c.forceSimulation(i).alphaDecay(0).force("collide",c.forceCollide().radius(function(t){return t.dy/2+r.nodePad/2}).strength(1).iterations(n.forceIterations)).force("constrain",function(t,e,r,i){return function(){for(var t=0,a=0;a0&&i.forceLayouts[e].alpha(0)}}(0,e,i,r)).stop()}(0,a,i),function(t,e,r,i){window.requestAnimationFrame(function a(){for(var o=0;o0&&window.requestAnimationFrame(a)})}(t,e,i,a)}}).on("drag",function(r){if("fixed"!==r.arrangement){var n=i.event.x,a=i.event.y;"snap"===r.arrangement?(r.node.x=n,r.node.y=a):("freeform"===r.arrangement&&(r.node.x=n),r.node.y=Math.max(r.node.dy/2,Math.min(r.size-r.node.dy/2,a))),v(r.node),"snap"!==r.arrangement&&(r.sankey.relayout(),k(t.filter(y(r)),e))}}).on("dragend",function(t){t.interactionState.dragInProgress=!1});t.on(".drag",null).call(a)}e.exports=function(t,e,r,i){var c=t.selectAll("."+n.cn.sankey).data(e.filter(function(t){return g(t).trace.visible}).map(function(t,e,r){var i,a=g(e).trace,o=a.domain,s=a.node,c=a.link,p=a.arrangement,d="h"===a.orientation,m=a.node.pad,v=a.node.thickness,y=a.node.line.color,b=a.node.line.width,_=a.link.line.color,w=a.link.line.width,k=a.valueformat,M=a.valuesuffix,A=a.textfont,T=t.width*(o.x[1]-o.x[0]),S=t.height*(o.y[1]-o.y[0]),E=[],C=f(c.color),L={},z=s.label.length;for(i=0;i0&&h(I,z)&&h(P,z)&&(P=+P,L[I=+I]=L[P]=!0,E.push({pointNumber:i,label:c.label[i],color:C?c.color[i]:c.color,source:I,target:P,value:+O}))}var D=f(s.color),R=[],B=!1,F={};for(i=0;i5?t.node.label:""}).attr("text-anchor",function(t){return t.horizontal&&t.left?"end":"start"}),N.transition().ease(n.ease).duration(n.duration).attr("startOffset",O).style("fill",z)}},{"../../components/color":570,"../../components/drawing":595,"../../lib":696,"../../lib/gup":693,"./constants":1037,"/home/circleci/plotly.js/test/image/strict-d3.js":1160,"@plotly/d3-sankey":46,"d3-force":144,tinycolor2:514}],1042:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e){for(var r=0;rs&&A[g].gap;)g--;for(y=A[g].s,d=A.length-1;d>g;d--)A[d].s=y;for(;sT[u]&&u=0;i--){var a=t[i];if("scatter"===a.type&&a.xaxis===r.xaxis&&a.yaxis===r.yaxis){a.opacity=void 0;break}}}}}},{}],1050:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("./attributes"),o=t("./constants"),s=t("./subtypes"),l=t("./xy_defaults"),c=t("./stack_defaults"),u=t("./marker_defaults"),f=t("./line_defaults"),h=t("./line_shape_defaults"),p=t("./text_defaults"),d=t("./fillcolor_defaults");e.exports=function(t,e,r,m){function g(r,i){return n.coerce(t,e,a,r,i)}var v=l(t,e,m,g);if(v||(e.visible=!1),e.visible){var y=c(t,e,m,g),x=!y&&vG!=(B=O[L][1])>=G&&(P=O[L-1][0],D=O[L][0],B-R&&(I=P+(D-P)*(G-R)/(B-R),V=Math.min(V,I),U=Math.max(U,I)));V=Math.max(V,0),U=Math.min(U,h._length);var W=s.defaultLine;return s.opacity(f.fillcolor)?W=f.fillcolor:s.opacity((f.line||{}).color)&&(W=f.line.color),n.extendFlat(t,{distance:t.maxHoverDistance,x0:V,x1:U,y0:G,y1:G,color:W}),delete t.index,f.text&&!Array.isArray(f.text)?t.text=String(f.text):t.text=f.name,[t]}}}},{"../../components/color":570,"../../components/fx":612,"../../lib":696,"../../registry":827,"./fill_hover_text":1051,"./get_trace_color":1053}],1055:[function(t,e,r){"use strict";var n={},i=t("./subtypes");n.hasLines=i.hasLines,n.hasMarkers=i.hasMarkers,n.hasText=i.hasText,n.isBubble=i.isBubble,n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.crossTraceDefaults=t("./cross_trace_defaults"),n.calc=t("./calc").calc,n.crossTraceCalc=t("./cross_trace_calc"),n.arraysToCalcdata=t("./arrays_to_calcdata"),n.plot=t("./plot"),n.colorbar=t("./marker_colorbar"),n.style=t("./style").style,n.styleOnSelect=t("./style").styleOnSelect,n.hoverPoints=t("./hover"),n.selectPoints=t("./select"),n.animatable=!0,n.moduleType="trace",n.name="scatter",n.basePlotModule=t("../../plots/cartesian"),n.categories=["cartesian","svg","symbols","errorBarsOK","showLegend","scatter-like","zoomScale"],n.meta={},e.exports=n},{"../../plots/cartesian":756,"./arrays_to_calcdata":1042,"./attributes":1043,"./calc":1044,"./cross_trace_calc":1048,"./cross_trace_defaults":1049,"./defaults":1050,"./hover":1054,"./marker_colorbar":1061,"./plot":1063,"./select":1064,"./style":1066,"./subtypes":1067}],1056:[function(t,e,r){"use strict";var n=t("../../lib").isArrayOrTypedArray,i=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/defaults");e.exports=function(t,e,r,o,s,l){var c=(t.marker||{}).color;(s("line.color",r),i(t,"line"))?a(t,e,o,s,{prefix:"line.",cLetter:"c",noScale:!0}):s("line.color",!n(c)&&c||r);s("line.width"),(l||{}).noDash||s("line.dash")}},{"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"../../lib":696}],1057:[function(t,e,r){"use strict";var n=t("../../constants/numerical"),i=n.BADNUM,a=n.LOG_CLIP,o=a+.5,s=a-.5,l=t("../../lib"),c=l.segmentsIntersect,u=l.constrain,f=t("./constants");e.exports=function(t,e){var r,n,a,h,p,d,m,g,v,y,x,b,_,w,k,M,A,T,S=e.xaxis,E=e.yaxis,C="log"===S.type,L="log"===E.type,z=S._length,O=E._length,I=e.connectGaps,P=e.baseTolerance,D=e.shape,R="linear"===D,B=[],F=f.minTolerance,N=new Array(t.length),j=0;function V(e){var r=t[e];if(!r)return!1;var n=S.c2p(r.x),a=E.c2p(r.y);if(n===i){if(C&&(n=S.c2p(r.x,!0)),n===i)return!1;L&&a===i&&(n*=Math.abs(S._m*O*(S._m>0?o:s)/(E._m*z*(E._m>0?o:s)))),n*=1e3}if(a===i){if(L&&(a=E.c2p(r.y,!0)),a===i)return!1;a*=1e3}return[n,a]}function U(t,e,r,n){var i=r-t,a=n-e,o=.5-t,s=.5-e,l=i*i+a*a,c=i*o+a*s;if(c>0&&ctt||t[1]rt)return[u(t[0],Q,tt),u(t[1],et,rt)]}function at(t,e){return t[0]===e[0]&&(t[0]===Q||t[0]===tt)||(t[1]===e[1]&&(t[1]===et||t[1]===rt)||void 0)}function ot(t,e,r){return function(n,i){var a=it(n),o=it(i),s=[];if(a&&o&&at(a,o))return s;a&&s.push(a),o&&s.push(o);var c=2*l.constrain((n[t]+i[t])/2,e,r)-((a||n)[t]+(o||i)[t]);c&&((a&&o?c>0==a[t]>o[t]?a:o:a||o)[t]+=c);return s}}function st(t){var e=t[0],r=t[1],n=e===N[j-1][0],i=r===N[j-1][1];if(!n||!i)if(j>1){var a=e===N[j-2][0],o=r===N[j-2][1];n&&(e===Q||e===tt)&&a?o?j--:N[j-1]=t:i&&(r===et||r===rt)&&o?a?j--:N[j-1]=t:N[j++]=t}else N[j++]=t}function lt(t){N[j-1][0]!==t[0]&&N[j-1][1]!==t[1]&&st([Y,X]),st(t),Z=null,Y=X=0}function ct(t){if(A=t[0]/z,T=t[1]/O,G=t[0]tt?tt:0,W=t[1]rt?rt:0,G||W){if(j)if(Z){var e=J(Z,t);e.length>1&&(lt(e[0]),N[j++]=e[1])}else $=J(N[j-1],t)[0],N[j++]=$;else N[j++]=[G||t[0],W||t[1]];var r=N[j-1];G&&W&&(r[0]!==G||r[1]!==W)?(Z&&(Y!==G&&X!==W?st(Y&&X?(n=Z,a=(i=t)[0]-n[0],o=(i[1]-n[1])/a,(n[1]*i[0]-i[1]*n[0])/a>0?[o>0?Q:tt,rt]:[o>0?tt:Q,et]):[Y||G,X||W]):Y&&X&&st([Y,X])),st([G,W])):Y-G&&X-W&&st([G||Y,W||X]),Z=t,Y=G,X=W}else Z&<(J(Z,t)[0]),N[j++]=t;var n,i,a,o}for("linear"===D||"spline"===D?J=function(t,e){for(var r=[],n=0,i=0;i<4;i++){var a=nt[i],o=c(t[0],t[1],e[0],e[1],a[0],a[1],a[2],a[3]);o&&(!n||Math.abs(o.x-r[0][0])>1||Math.abs(o.y-r[0][1])>1)&&(o=[o.x,o.y],n&&H(o,t)q(d,ut))break;a=d,(_=v[0]*g[0]+v[1]*g[1])>x?(x=_,h=d,m=!1):_=t.length||!d)break;ct(d),n=d}}else ct(h)}Z&&st([Y||Z[0],X||Z[1]]),B.push(N.slice(0,j))}return B}},{"../../constants/numerical":673,"../../lib":696,"./constants":1047}],1058:[function(t,e,r){"use strict";e.exports=function(t,e,r){"spline"===r("line.shape")&&r("line.smoothing")}},{}],1059:[function(t,e,r){"use strict";var n={tonextx:1,tonexty:1,tonext:1};e.exports=function(t,e,r){var i,a,o,s,l,c={},u=!1,f=-1,h=0,p=-1;for(a=0;a=0?l=p:(l=p=h,h++),l0?Math.max(e,i):0}}},{"fast-isnumeric":214}],1061:[function(t,e,r){"use strict";e.exports={container:"marker",min:"cmin",max:"cmax"}},{}],1062:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/defaults"),o=t("./subtypes");e.exports=function(t,e,r,s,l,c){var u=o.isBubble(t),f=(t.line||{}).color;(c=c||{},f&&(r=f),l("marker.symbol"),l("marker.opacity",u?.7:1),l("marker.size"),l("marker.color",r),i(t,"marker")&&a(t,e,s,l,{prefix:"marker.",cLetter:"c"}),c.noSelect||(l("selected.marker.color"),l("unselected.marker.color"),l("selected.marker.size"),l("unselected.marker.size")),c.noLine||(l("marker.line.color",f&&!Array.isArray(f)&&e.marker.color!==f?f:u?n.background:n.defaultLine),i(t,"marker.line")&&a(t,e,s,l,{prefix:"marker.line.",cLetter:"c"}),l("marker.line.width",u?1:0)),u&&(l("marker.sizeref"),l("marker.sizemin"),l("marker.sizemode")),c.gradient)&&("none"!==l("marker.gradient.type")&&l("marker.gradient.color"))}},{"../../components/color":570,"../../components/colorscale/defaults":580,"../../components/colorscale/has_colorscale":584,"./subtypes":1067}],1063:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../registry"),a=t("../../lib"),o=a.ensureSingle,s=a.identity,l=t("../../components/drawing"),c=t("./subtypes"),u=t("./line_points"),f=t("./link_traces"),h=t("../../lib/polygon").tester;function p(t,e,r,f,p,d,m){var g;!function(t,e,r,i,o){var s=r.xaxis,l=r.yaxis,u=n.extent(a.simpleMap(s.range,s.r2c)),f=n.extent(a.simpleMap(l.range,l.r2c)),h=i[0].trace;if(!c.hasMarkers(h))return;var p=h.marker.maxdisplayed;if(0===p)return;var d=i.filter(function(t){return t.x>=u[0]&&t.x<=u[1]&&t.y>=f[0]&&t.y<=f[1]}),m=Math.ceil(d.length/p),g=0;o.forEach(function(t,r){var n=t[0].trace;c.hasMarkers(n)&&n.marker.maxdisplayed>0&&r0;function y(t){return v?t.transition():t}var x=r.xaxis,b=r.yaxis,_=f[0].trace,w=_.line,k=n.select(d),M=o(k,"g","errorbars"),A=o(k,"g","lines"),T=o(k,"g","points"),S=o(k,"g","text");if(i.getComponentMethod("errorbars","plot")(M,r,m),!0===_.visible){var E,C;y(k).style("opacity",_.opacity);var L=_.fill.charAt(_.fill.length-1);"x"!==L&&"y"!==L&&(L=""),r.isRangePlot||(f[0].node3=k);var z="",O=[],I=_._prevtrace;I&&(z=I._prevRevpath||"",C=I._nextFill,O=I._polygons);var P,D,R,B,F,N,j,V,U,q="",H="",G=[],W=a.noop;if(E=_._ownFill,c.hasLines(_)||"none"!==_.fill){for(C&&C.datum(f),-1!==["hv","vh","hvh","vhv"].indexOf(w.shape)?(R=l.steps(w.shape),B=l.steps(w.shape.split("").reverse().join(""))):R=B="spline"===w.shape?function(t){var e=t[t.length-1];return t.length>1&&t[0][0]===e[0]&&t[0][1]===e[1]?l.smoothclosed(t.slice(1),w.smoothing):l.smoothopen(t,w.smoothing)}:function(t){return"M"+t.join("L")},F=function(t){return B(t.reverse())},G=u(f,{xaxis:x,yaxis:b,connectGaps:_.connectgaps,baseTolerance:Math.max(w.width||1,3)/4,shape:w.shape,simplify:w.simplify}),U=_._polygons=new Array(G.length),g=0;g1){var r=n.select(this);if(r.datum(f),t)y(r.style("opacity",0).attr("d",P).call(l.lineGroupStyle)).style("opacity",1);else{var i=y(r);i.attr("d",P),l.singleLineStyle(f,i)}}}}}var Y=A.selectAll(".js-line").data(G);y(Y.exit()).style("opacity",0).remove(),Y.each(W(!1)),Y.enter().append("path").classed("js-line",!0).style("vector-effect","non-scaling-stroke").call(l.lineGroupStyle).each(W(!0)),l.setClipUrl(Y,r.layerClipId),G.length?(E?(E.datum(f),N&&V&&(L?("y"===L?N[1]=V[1]=b.c2p(0,!0):"x"===L&&(N[0]=V[0]=x.c2p(0,!0)),y(E).attr("d","M"+V+"L"+N+"L"+q.substr(1)).call(l.singleFillStyle)):y(E).attr("d",q+"Z").call(l.singleFillStyle))):C&&("tonext"===_.fill.substr(0,6)&&q&&z?("tonext"===_.fill?y(C).attr("d",q+"Z"+z+"Z").call(l.singleFillStyle):y(C).attr("d",q+"L"+z.substr(1)+"Z").call(l.singleFillStyle),_._polygons=_._polygons.concat(O)):(Z(C),_._polygons=null)),_._prevRevpath=H,_._prevPolygons=U):(E?Z(E):C&&Z(C),_._polygons=_._prevRevpath=_._prevPolygons=null),T.datum(f),S.datum(f),function(e,i,a){var o,u=a[0].trace,f=c.hasMarkers(u),h=c.hasText(u),p=tt(u),d=et,m=et;if(f||h){var g=s,_=u.stackgroup,w=_&&"infer zero"===t._fullLayout._scatterStackOpts[x._id+b._id][_].stackgaps;u.marker.maxdisplayed||u._needsCull?g=w?J:$:_&&!w&&(g=K),f&&(d=g),h&&(m=g)}var k,M=(o=e.selectAll("path.point").data(d,p)).enter().append("path").classed("point",!0);v&&M.call(l.pointStyle,u,t).call(l.translatePoints,x,b).style("opacity",0).transition().style("opacity",1),o.order(),f&&(k=l.makePointStyleFns(u)),o.each(function(e){var i=n.select(this),a=y(i);l.translatePoint(e,a,x,b)?(l.singlePointStyle(e,a,u,k,t),r.layerClipId&&l.hideOutsideRangePoint(e,a,x,b,u.xcalendar,u.ycalendar),u.customdata&&i.classed("plotly-customdata",null!==e.data&&void 0!==e.data)):a.remove()}),v?o.exit().transition().style("opacity",0).remove():o.exit().remove(),(o=i.selectAll("g").data(m,p)).enter().append("g").classed("textpoint",!0).append("text"),o.order(),o.each(function(t){var e=n.select(this),i=y(e.select("text"));l.translatePoint(t,i,x,b)?r.layerClipId&&l.hideOutsideRangePoint(t,e,x,b,u.xcalendar,u.ycalendar):e.remove()}),o.selectAll("text").call(l.textPointStyle,u,t).each(function(t){var e=x.c2p(t.x),r=b.c2p(t.y);n.select(this).selectAll("tspan.line").each(function(){y(n.select(this)).attr({x:e,y:r})})}),o.exit().remove()}(T,S,f);var X=!1===_.cliponaxis?null:r.layerClipId;l.setClipUrl(T,X),l.setClipUrl(S,X)}function Z(t){y(t).attr("d","M0,0Z")}function $(t){return t.filter(function(t){return!t.gap&&t.vis})}function J(t){return t.filter(function(t){return t.vis})}function K(t){return t.filter(function(t){return!t.gap})}function Q(t){return t.id}function tt(t){if(t.ids)return Q}function et(){return!1}}e.exports=function(t,e,r,i,a,c){var u,h,d=!a,m=!!a&&a.duration>0,g=f(t,e,r);((u=i.selectAll("g.trace").data(g,function(t){return t[0].trace.uid})).enter().append("g").attr("class",function(t){return"trace scatter trace"+t[0].trace.uid}).style("stroke-miterlimit",2),u.order(),function(t,e,r){e.each(function(t){var e=o(n.select(this),"g","fills");l.setClipUrl(e,r.layerClipId);var i=t[0].trace,a=[];i._ownfill&&a.push("_ownFill"),i._nexttrace&&a.push("_nextFill");var c=e.selectAll("g").data(a,s);c.enter().append("g"),c.exit().each(function(t){i[t]=null}).remove(),c.order().each(function(t){i[t]=o(n.select(this),"path","js-fill")})})}(0,u,e),m)?(c&&(h=c()),n.transition().duration(a.duration).ease(a.easing).each("end",function(){h&&h()}).each("interrupt",function(){h&&h()}).each(function(){i.selectAll("g.trace").each(function(r,n){p(t,n,e,r,g,this,a)})})):u.each(function(r,n){p(t,n,e,r,g,this,a)});d&&u.exit().remove(),i.selectAll("path:not([d])").remove()}},{"../../components/drawing":595,"../../lib":696,"../../lib/polygon":708,"../../registry":827,"./line_points":1057,"./link_traces":1059,"./subtypes":1067,"/home/circleci/plotly.js/test/image/strict-d3.js":1160}],1064:[function(t,e,r){"use strict";var n=t("./subtypes");e.exports=function(t,e){var r,i,a,o,s=t.cd,l=t.xaxis,c=t.yaxis,u=[],f=s[0].trace;if(!n.hasMarkers(f)&&!n.hasText(f))return[];if(!1===e)for(r=0;r0){var h=i.c2l(u);i._lowerLogErrorBound||(i._lowerLogErrorBound=h),i._lowerErrorBound=Math.min(i._lowerLogErrorBound,h)}}else o[s]=[-l[0]*r,l[1]*r]}return o}e.exports=function(t,e,r){var n=[i(t.x,t.error_x,e[0],r.xaxis),i(t.y,t.error_y,e[1],r.yaxis),i(t.z,t.error_z,e[2],r.zaxis)],a=function(t){for(var e=0;e-1?-1:t.indexOf("right")>-1?1:0}function y(t){return null==t?0:t.indexOf("top")>-1?-1:t.indexOf("bottom")>-1?1:0}function x(t,e){return e(4*t)}function b(t){return p[t]}function _(t,e,r,n,i){var a=null;if(l.isArrayOrTypedArray(t)){a=[];for(var o=0;o=0){var m=function(t,e,r){var n,i=(r+1)%3,a=(r+2)%3,o=[],l=[];for(n=0;n=0&&f("surfacecolor",h||p);for(var d=["x","y","z"],m=0;m<3;++m){var g="projection."+d[m];f(g+".show")&&(f(g+".opacity"),f(g+".scale"))}var v=n.getComponentMethod("errorbars","supplyDefaults");v(t,e,r,{axis:"z"}),v(t,e,r,{axis:"y",inherit:"z"}),v(t,e,r,{axis:"x",inherit:"z"})}else e.visible=!1}},{"../../lib":696,"../../registry":827,"../scatter/line_defaults":1056,"../scatter/marker_defaults":1062,"../scatter/subtypes":1067,"../scatter/text_defaults":1068,"./attributes":1070}],1075:[function(t,e,r){"use strict";var n={};n.plot=t("./convert"),n.attributes=t("./attributes"),n.markerSymbols=t("../../constants/gl3d_markers"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/marker_colorbar"),n.calc=t("./calc"),n.moduleType="trace",n.name="scatter3d",n.basePlotModule=t("../../plots/gl3d"),n.categories=["gl3d","symbols","showLegend"],n.meta={},e.exports=n},{"../../constants/gl3d_markers":671,"../../plots/gl3d":787,"../scatter/marker_colorbar":1061,"./attributes":1070,"./calc":1071,"./convert":1073,"./defaults":1074}],1076:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../plots/attributes"),a=t("../../components/colorscale/attributes"),o=t("../../components/colorbar/attributes"),s=t("../../lib/extend").extendFlat,l=n.marker,c=n.line,u=l.line;e.exports={carpet:{valType:"string",editType:"calc"},a:{valType:"data_array",editType:"calc"},b:{valType:"data_array",editType:"calc"},mode:s({},n.mode,{dflt:"markers"}),text:s({},n.text,{}),line:{color:c.color,width:c.width,dash:c.dash,shape:s({},c.shape,{values:["linear","spline"]}),smoothing:c.smoothing,editType:"calc"},connectgaps:n.connectgaps,fill:s({},n.fill,{values:["none","toself","tonext"],dflt:"none"}),fillcolor:n.fillcolor,marker:s({symbol:l.symbol,opacity:l.opacity,maxdisplayed:l.maxdisplayed,size:l.size,sizeref:l.sizeref,sizemin:l.sizemin,sizemode:l.sizemode,line:s({width:u.width,editType:"calc"},a("marker.line")),gradient:l.gradient,editType:"calc"},a("marker"),{colorbar:o}),textfont:n.textfont,textposition:n.textposition,selected:n.selected,unselected:n.unselected,hoverinfo:s({},i.hoverinfo,{flags:["a","b","text","name"]}),hoveron:n.hoveron}},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plots/attributes":741,"../scatter/attributes":1043}],1077:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../scatter/colorscale_calc"),a=t("../scatter/arrays_to_calcdata"),o=t("../scatter/calc_selection"),s=t("../scatter/calc").calcMarkerSize,l=t("../carpet/lookup_carpetid");e.exports=function(t,e){var r=e._carpetTrace=l(t,e);if(r&&r.visible&&"legendonly"!==r.visible){var c;e.xaxis=r.xaxis,e.yaxis=r.yaxis;var u,f,h=e._length,p=new Array(h),d=!1;for(c=0;c"),a}function w(t,e){var r;r=t.labelprefix&&t.labelprefix.length>0?t.labelprefix.replace(/ = $/,""):t._hovertitle,m.push(r+": "+e.toFixed(3)+t.labelsuffix)}}},{"../scatter/hover":1054}],1081:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/marker_colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("../scatter/style").style,n.styleOnSelect=t("../scatter/style").styleOnSelect,n.hoverPoints=t("./hover"),n.selectPoints=t("../scatter/select"),n.eventData=t("./event_data"),n.moduleType="trace",n.name="scattercarpet",n.basePlotModule=t("../../plots/cartesian"),n.categories=["svg","carpet","symbols","showLegend","carpetDependent","zoomScale"],n.meta={},e.exports=n},{"../../plots/cartesian":756,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1076,"./calc":1077,"./defaults":1078,"./event_data":1079,"./hover":1080,"./plot":1082}],1082:[function(t,e,r){"use strict";var n=t("../scatter/plot"),i=t("../../plots/cartesian/axes"),a=t("../../components/drawing");e.exports=function(t,e,r,o){var s,l,c,u=r[0][0].carpet,f={xaxis:i.getFromId(t,u.xaxis||"x"),yaxis:i.getFromId(t,u.yaxis||"y"),plot:e.plot};for(n(t,f,r,o),s=0;s")}(u,g,p.mockAxis,c[0].t.labels),[t]}}},{"../../components/fx":612,"../../constants/numerical":673,"../../plots/cartesian/axes":744,"../scatter/fill_hover_text":1051,"../scatter/get_trace_color":1053,"./attributes":1083}],1088:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/marker_colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("./style"),n.styleOnSelect=t("../scatter/style").styleOnSelect,n.hoverPoints=t("./hover"),n.eventData=t("./event_data"),n.selectPoints=t("./select"),n.moduleType="trace",n.name="scattergeo",n.basePlotModule=t("../../plots/geo"),n.categories=["geo","symbols","showLegend","scatter-like"],n.meta={},e.exports=n},{"../../plots/geo":775,"../scatter/marker_colorbar":1061,"../scatter/style":1066,"./attributes":1083,"./calc":1084,"./defaults":1085,"./event_data":1086,"./hover":1087,"./plot":1089,"./select":1090,"./style":1091}],1089:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib"),a=t("../../constants/numerical").BADNUM,o=t("../../lib/topojson_utils").getTopojsonFeatures,s=t("../../lib/geo_location_utils").locationToFeature,l=t("../../lib/geojson_utils"),c=t("../scatter/subtypes"),u=t("./style");function f(t,e){var r=t[0].trace;if(Array.isArray(r.locations))for(var n=o(r,e),i=r.locationmode,l=0;lp.TOO_MANY_POINTS?"rect":f.hasMarkers(e)?"rect":"round";if(c&&e.connectgaps){var h=n[0],d=n[1];for(i=0;i1?l[i]:l[0]:l,d=Array.isArray(c)?c.length>1?c[i]:c[0]:c,g=m[p],v=m[d],y=u?u/.8+1:0,x=-v*y-.5*v;o.offset[i]=[g*y/h,x/h]}}return o}}},{"../../components/drawing":595,"../../constants/interactions":672,"../../lib":696,"../../lib/gl_format_color":692,"../../plots/cartesian/axis_ids":747,"../../registry":827,"../scatter/make_bubble_size_func":1060,"../scatter/subtypes":1067,"./constants":1093,"color-normalize":108,"fast-isnumeric":214,"svg-path-sdf":512}],1095:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("./attributes"),o=t("../scatter/constants"),s=t("../scatter/subtypes"),l=t("../scatter/xy_defaults"),c=t("../scatter/marker_defaults"),u=t("../scatter/line_defaults"),f=t("../scatter/fillcolor_defaults"),h=t("../scatter/text_defaults");e.exports=function(t,e,r,p){function d(r,i){return n.coerce(t,e,a,r,i)}var m=!!t.marker&&/-open/.test(t.marker.symbol),g=s.isBubble(t),v=l(t,e,p,d);if(v){var y=v1&&u.extendFlat(o.line,M.linePositions(t,r,n)),o.errorX||o.errorY){var s=M.errorBarPositions(t,r,n,i,a);o.errorX&&u.extendFlat(o.errorX,s.x),o.errorY&&u.extendFlat(o.errorY,s.y)}return o.text&&(u.extendFlat(o.text,{positions:n},M.textPosition(t,r,o.text,o.marker)),u.extendFlat(o.textSel,{positions:n},M.textPosition(t,r,o.text,o.markerSel)),u.extendFlat(o.textUnsel,{positions:n},M.textPosition(t,r,o.text,o.markerUnsel))),o}(t,0,e,_,m,g),L=C(0,c);return x(a,e),f=T&&(S.marker.cluster=d.tree),L.lineOptions.push(S.line),L.errorXOptions.push(S.errorX),L.errorYOptions.push(S.errorY),L.fillOptions.push(S.fill),L.markerOptions.push(S.marker),L.markerSelectedOptions.push(S.markerSel),L.markerUnselectedOptions.push(S.markerUnsel),L.textOptions.push(S.text),L.textSelectedOptions.push(S.textSel),L.textUnselectedOptions.push(S.textUnsel),d._scene=L,d.index=L.count,d.x=m,d.y=g,d.positions=_,L.count++,[{x:!1,y:!1,t:d,trace:e}]},plot:function(t,e,r){if(r.length){var o,s,c=t._fullLayout,h=e._scene,p=e.xaxis,d=e.yaxis;if(h)if(f(t,["ANGLE_instanced_arrays","OES_element_index_uint"])){var m=c._glcanvas.data()[0].regl;if(_(t,e,r),h.dirty){if(!0===h.error2d&&(h.error2d=a(m)),!0===h.line2d&&(h.line2d=i(m)),!0===h.scatter2d&&(h.scatter2d=n(m)),!0===h.fill2d&&(h.fill2d=i(m)),!0===h.glText)for(h.glText=new Array(h.count),o=0;or&&(isNaN(e[n])||isNaN(e[n+1]));)n-=2;t.positions=e.slice(r,n+2)}return t}),h.line2d.update(h.lineOptions)),h.error2d){var g=(h.errorXOptions||[]).concat(h.errorYOptions||[]);h.error2d.update(g)}h.scatter2d&&h.scatter2d.update(h.markerOptions),h.fillOrder=u.repeat(null,h.count),h.fill2d&&(h.fillOptions=h.fillOptions.map(function(t,e){var n=r[e];if(t&&n&&n[0]&&n[0].trace){var i,a,o=n[0],s=o.trace,l=o.t,c=h.lineOptions[e],u=[];s._ownfill&&u.push(e),s._nexttrace&&u.push(e+1),u.length&&(h.fillOrder[e]=u);var f,p,d=[],m=c&&c.positions||l.positions;if("tozeroy"===s.fill){for(f=0;ff&&isNaN(m[p+1]);)p-=2;0!==m[f+1]&&(d=[m[f],0]),d=d.concat(m.slice(f,p+2)),0!==m[p+1]&&(d=d.concat([m[p],0]))}else if("tozerox"===s.fill){for(f=0;ff&&isNaN(m[p]);)p-=2;0!==m[f]&&(d=[0,m[f+1]]),d=d.concat(m.slice(f,p+2)),0!==m[p]&&(d=d.concat([0,m[p+1]]))}else if("toself"===s.fill||"tonext"===s.fill){for(d=[],i=0,a=0;a-1;for(o=0;o=0?Math.floor((e+180)/360):Math.ceil((e-180)/360)),d=e-p;if(n.getClosest(l,function(t){var e=t.lonlat;if(e[0]===s)return 1/0;var n=i.modHalf(e[0],360),a=e[1],o=h.project([n,a]),l=o.x-u.c2p([d,a]),c=o.y-f.c2p([n,r]),p=Math.max(3,t.mrc||0);return Math.max(Math.sqrt(l*l+c*c)-p,1-3/p)},t),!1!==t.index){var m=l[t.index],g=m.lonlat,v=[i.modHalf(g[0],360)+p,g[1]],y=u.c2p(v),x=f.c2p(v),b=m.mrc||1;return t.x0=y-b,t.x1=y+b,t.y0=x-b,t.y1=x+b,t.color=a(c,m),t.extraText=function(t,e,r){var n=(e.hi||t.hoverinfo).split("+"),i=-1!==n.indexOf("all"),a=-1!==n.indexOf("lon"),s=-1!==n.indexOf("lat"),l=e.lonlat,c=[];function u(t){return t+"\xb0"}i||a&&s?c.push("("+u(l[0])+", "+u(l[1])+")"):a?c.push(r.lon+u(l[0])):s&&c.push(r.lat+u(l[1]));(i||-1!==n.indexOf("text"))&&o(e,t,c);return c.join("
")}(c,m,l[0].t.labels),[t]}}},{"../../components/fx":612,"../../constants/numerical":673,"../../lib":696,"../scatter/fill_hover_text":1051,"../scatter/get_trace_color":1053}],1102:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/marker_colorbar"),n.calc=t("../scattergeo/calc"),n.plot=t("./plot"),n.hoverPoints=t("./hover"),n.eventData=t("./event_data"),n.selectPoints=t("./select"),n.style=function(t,e){e&&e[0].trace._glTrace.update(e)},n.moduleType="trace",n.name="scattermapbox",n.basePlotModule=t("../../plots/mapbox"),n.categories=["mapbox","gl","symbols","showLegend","scatterlike"],n.meta={},e.exports=n},{"../../plots/mapbox":802,"../scatter/marker_colorbar":1061,"../scattergeo/calc":1084,"./attributes":1097,"./defaults":1099,"./event_data":1100,"./hover":1101,"./plot":1103,"./select":1104}],1103:[function(t,e,r){"use strict";var n=t("./convert");function i(t,e){this.subplot=t,this.uid=e,this.sourceIds={fill:e+"-source-fill",line:e+"-source-line",circle:e+"-source-circle",symbol:e+"-source-symbol"},this.layerIds={fill:e+"-layer-fill",line:e+"-layer-line",circle:e+"-layer-circle",symbol:e+"-layer-symbol"},this.order=["fill","line","circle","symbol"]}var a=i.prototype;a.addSource=function(t,e){this.subplot.map.addSource(this.sourceIds[t],{type:"geojson",data:e.geojson})},a.setSourceData=function(t,e){this.subplot.map.getSource(this.sourceIds[t]).setData(e.geojson)},a.addLayer=function(t,e){this.subplot.map.addLayer({type:t,id:this.layerIds[t],source:this.sourceIds[t],layout:e.layout,paint:e.paint})},a.update=function(t){for(var e=this.subplot,r=n(t),i=0;i")}e.exports={hoverPoints:function(t,e,r,i){var a=n(t,e,r,i);if(a&&!1!==a[0].index){var s=a[0];if(void 0===s.index)return a;var l=t.subplot,c=s.cd[s.index],u=s.trace;if(l.isPtInside(c))return s.xLabelVal=void 0,s.yLabelVal=void 0,o(c,u,l,s),a}},makeHoverPointText:o}},{"../../lib":696,"../../plots/cartesian/axes":744,"../scatter/hover":1054}],1109:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"scatterpolar",basePlotModule:t("../../plots/polar"),categories:["polar","symbols","showLegend","scatter-like"],attributes:t("./attributes"),supplyDefaults:t("./defaults").supplyDefaults,colorbar:t("../scatter/marker_colorbar"),calc:t("./calc"),plot:t("./plot"),style:t("../scatter/style").style,hoverPoints:t("./hover").hoverPoints,selectPoints:t("../scatter/select"),meta:{}}},{"../../plots/polar":811,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1105,"./calc":1106,"./defaults":1107,"./hover":1108,"./plot":1110}],1110:[function(t,e,r){"use strict";var n=t("../scatter/plot"),i=t("../../constants/numerical").BADNUM;e.exports=function(t,e,r){for(var a=e.layers.frontplot.select("g.scatterlayer"),o={xaxis:e.xaxis,yaxis:e.yaxis,plot:e.framework,layerClipId:e._hasClipOnAxisFalse?e.clipIds.forTraces:null},s=e.radialAxis,l=e.angularAxis,c=0;c=h&&(y.marker.cluster=d.tree),y.marker&&(y.markerSel.positions=y.markerUnsel.positions=y.marker.positions=_),y.line&&_.length>1&&c.extendFlat(y.line,l.linePositions(t,p,_)),y.text&&(c.extendFlat(y.text,{positions:_},l.textPosition(t,p,y.text,y.marker)),c.extendFlat(y.textSel,{positions:_},l.textPosition(t,p,y.text,y.markerSel)),c.extendFlat(y.textUnsel,{positions:_},l.textPosition(t,p,y.text,y.markerUnsel))),y.fill&&!u.fill2d&&(u.fill2d=!0),y.marker&&!u.scatter2d&&(u.scatter2d=!0),y.line&&!u.line2d&&(u.line2d=!0),y.text&&!u.glText&&(u.glText=!0),u.lineOptions.push(y.line),u.fillOptions.push(y.fill),u.markerOptions.push(y.marker),u.markerSelectedOptions.push(y.markerSel),u.markerUnselectedOptions.push(y.markerUnsel),u.textOptions.push(y.text),u.textSelectedOptions.push(y.textSel),u.textUnselectedOptions.push(y.textUnsel),d.x=w,d.y=k,d.rawx=w,d.rawy=k,d.r=g,d.theta=v,d.positions=_,d._scene=u,d.index=u.count,u.count++}}),a.plot(t,e,r)}},hoverPoints:function(t,e,r,n){var i=t.cd[0].t,o=i.r,s=i.theta,l=a.hoverPoints(t,e,r,n);if(l&&!1!==l[0].index){var c=l[0];if(void 0===c.index)return l;var u=t.subplot,h=c.cd[c.index],p=c.trace;if(h.r=o[c.index],h.theta=s[c.index],u.isPtInside(h))return c.xLabelVal=void 0,c.yLabelVal=void 0,f(h,p,u,c),l}},selectPoints:a.selectPoints,meta:{}}},{"../../lib":696,"../../plots/cartesian/axes":744,"../../plots/polar":811,"../scatter/calc":1044,"../scatter/colorscale_calc":1046,"../scatter/marker_colorbar":1061,"../scattergl":1096,"../scattergl/constants":1093,"../scattergl/convert":1094,"../scatterpolar/hover":1108,"./attributes":1111,"./defaults":1112,"fast-isnumeric":214,"point-cluster":452}],1114:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../plots/attributes"),a=t("../../components/colorscale/attributes"),o=t("../../components/colorbar/attributes"),s=t("../../components/drawing/attributes").dash,l=t("../../lib/extend").extendFlat,c=n.marker,u=n.line,f=c.line;e.exports={a:{valType:"data_array",editType:"calc"},b:{valType:"data_array",editType:"calc"},c:{valType:"data_array",editType:"calc"},sum:{valType:"number",dflt:0,min:0,editType:"calc"},mode:l({},n.mode,{dflt:"markers"}),text:l({},n.text,{}),hovertext:l({},n.hovertext,{}),line:{color:u.color,width:u.width,dash:s,shape:l({},u.shape,{values:["linear","spline"]}),smoothing:u.smoothing,editType:"calc"},connectgaps:n.connectgaps,cliponaxis:n.cliponaxis,fill:l({},n.fill,{values:["none","toself","tonext"],dflt:"none"}),fillcolor:n.fillcolor,marker:l({symbol:c.symbol,opacity:c.opacity,maxdisplayed:c.maxdisplayed,size:c.size,sizeref:c.sizeref,sizemin:c.sizemin,sizemode:c.sizemode,line:l({width:f.width,editType:"calc"},a("marker.line")),gradient:c.gradient,editType:"calc"},a("marker"),{colorbar:o}),textfont:n.textfont,textposition:n.textposition,selected:n.selected,unselected:n.unselected,hoverinfo:l({},i.hoverinfo,{flags:["a","b","c","text","name"]}),hoveron:n.hoveron}},{"../../components/colorbar/attributes":571,"../../components/colorscale/attributes":577,"../../components/drawing/attributes":594,"../../lib/extend":685,"../../plots/attributes":741,"../scatter/attributes":1043}],1115:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../scatter/colorscale_calc"),a=t("../scatter/arrays_to_calcdata"),o=t("../scatter/calc_selection"),s=t("../scatter/calc").calcMarkerSize,l=["a","b","c"],c={a:["b","c"],b:["a","c"],c:["a","b"]};e.exports=function(t,e){var r,u,f,h,p,d,m=t._fullLayout[e.subplot].sum,g=e.sum||m,v={a:e.a,b:e.b,c:e.c};for(r=0;r"),o}function v(t,e){g.push(t._hovertitle+": "+i.tickText(t,e,"hover").text)}}},{"../../plots/cartesian/axes":744,"../scatter/hover":1054}],1119:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/marker_colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("../scatter/style").style,n.styleOnSelect=t("../scatter/style").styleOnSelect,n.hoverPoints=t("./hover"),n.selectPoints=t("../scatter/select"),n.eventData=t("./event_data"),n.moduleType="trace",n.name="scatterternary",n.basePlotModule=t("../../plots/ternary"),n.categories=["ternary","symbols","showLegend","scatter-like"],n.meta={},e.exports=n},{"../../plots/ternary":823,"../scatter/marker_colorbar":1061,"../scatter/select":1064,"../scatter/style":1066,"./attributes":1114,"./calc":1115,"./defaults":1116,"./event_data":1117,"./hover":1118,"./plot":1120}],1120:[function(t,e,r){"use strict";var n=t("../scatter/plot");e.exports=function(t,e,r){var i=e.plotContainer;i.select(".scatterlayer").selectAll("*").remove();var a={xaxis:e.xaxis,yaxis:e.yaxis,plot:i,layerClipId:e._hasClipOnAxisFalse?e.clipIdRelative:null},o=e.layers.frontplot.select("g.scatterlayer");n(t,a,r,o)}},{"../scatter/plot":1063}],1121:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../components/colorscale/attributes"),a=t("../scattergl/attributes"),o=t("../../plots/cartesian/constants").idRegex,s=t("../../plot_api/plot_template").templatedArray,l=t("../../lib/extend").extendFlat,c=n.marker,u=c.line,f=l(i("marker.line",{editTypeOverride:"calc"}),{width:l({},u.width,{editType:"calc"}),editType:"calc"}),h=l(i("marker"),{symbol:c.symbol,size:l({},c.size,{editType:"markerSize"}),sizeref:c.sizeref,sizemin:c.sizemin,sizemode:c.sizemode,opacity:c.opacity,colorbar:c.colorbar,line:f,editType:"calc"});function p(t){return{valType:"info_array",freeLength:!0,editType:"calc",items:{valType:"subplotid",regex:o[t],editType:"plot"}}}h.color.editType=h.cmin.editType=h.cmax.editType="style",e.exports={dimensions:s("dimension",{visible:{valType:"boolean",dflt:!0,editType:"calc"},label:{valType:"string",editType:"calc"},values:{valType:"data_array",editType:"calc+clearAxisTypes"},axis:{type:{valType:"enumerated",values:["linear","log","date","category"],editType:"calc+clearAxisTypes"},editType:"calc+clearAxisTypes"},editType:"calc+clearAxisTypes"}),text:l({},a.text,{}),marker:h,xaxes:p("x"),yaxes:p("y"),diagonal:{visible:{valType:"boolean",dflt:!0,editType:"calc"},editType:"calc"},showupperhalf:{valType:"boolean",dflt:!0,editType:"calc"},showlowerhalf:{valType:"boolean",dflt:!0,editType:"calc"},selected:{marker:a.selected.marker,editType:"calc"},unselected:{marker:a.unselected.marker,editType:"calc"},opacity:a.opacity}},{"../../components/colorscale/attributes":577,"../../lib/extend":685,"../../plot_api/plot_template":734,"../../plots/cartesian/constants":750,"../scatter/attributes":1043,"../scattergl/attributes":1092}],1122:[function(t,e,r){"use strict";var n=t("regl-line2d"),i=t("../../registry"),a=t("../../lib/prepare_regl"),o=t("../../plots/get_data").getModuleCalcData,s=t("../../plots/cartesian"),l=t("../../plots/cartesian/axis_ids").getFromId,c=t("../../plots/cartesian/axes").shouldShowZeroLine,u="splom";function f(t,e,r){for(var n=r.matrixOptions.data.length,i=e._visibleDims,a=r.viewOpts.ranges=new Array(n),o=0;oa&&l?r._splomSubplots[S]=1:i-1,A="lasso"===y||"select"===y||!!h.selectedpoints||M;if(d.selectBatch=null,d.unselectBatch=null,A){var T=h._length;if(d.selectBatch||(d.selectBatch=[],d.unselectBatch=[]),h.selectedpoints){d.selectBatch=h.selectedpoints;var S=h.selectedpoints,E={};for(a=0;av?2*(x.sizeAvg||Math.max(x.size,3)):u(e,y),n=0;n2?t.slice(1,e-1):2===e?[(t[0]+t[1])/2]:t}function p(t){var e=t.length;return 1===e?[.5,.5]:[t[1]-t[0],t[e-1]-t[e-2]]}function d(t,e){var r=t.fullSceneLayout,i=t.dataScale,c=e._len,u={};function d(t,e){var n=r[e],o=i[l[e]];return a.simpleMap(t,function(t){return n.d2l(t)*o})}u.vectors=s(d(e.u,"xaxis"),d(e.v,"yaxis"),d(e.w,"zaxis"),c);var m=f(e.x.slice(0,c)),g=f(e.y.slice(0,c)),v=f(e.z.slice(0,c));if(m.length*g.length*v.length>c)return{positions:[],cells:[]};var y=d(m,"xaxis"),x=d(g,"yaxis"),b=d(v,"zaxis");if(u.meshgrid=[y,x,b],e.starts){var _=e._slen;u.startingPositions=s(d(e.starts.x.slice(0,_),"xaxis"),d(e.starts.y.slice(0,_),"yaxis"),d(e.starts.z.slice(0,_),"zaxis"))}else{for(var w=x[0],k=h(y),M=h(b),A=new Array(k.length*M.length),T=0,S=0;S",maxDimensionCount:60,overdrag:45,releaseTransitionDuration:120,releaseTransitionEase:"cubic-out",scrollbarCaptureWidth:18,scrollbarHideDelay:1e3,scrollbarHideDuration:1e3,scrollbarOffset:5,scrollbarWidth:8,transitionDuration:100,transitionEase:"cubic-out",uplift:5,wrapSpacer:" ",wrapSplitCharacter:" ",cn:{table:"table",tableControlView:"table-control-view",scrollBackground:"scroll-background",yColumn:"y-column",columnBlock:"column-block",scrollAreaClip:"scroll-area-clip",scrollAreaClipRect:"scroll-area-clip-rect",columnBoundary:"column-boundary",columnBoundaryClippath:"column-boundary-clippath",columnBoundaryRect:"column-boundary-rect",columnCells:"column-cells",columnCell:"column-cell",cellRect:"cell-rect",cellText:"cell-text",cellTextHolder:"cell-text-holder",scrollbarKit:"scrollbar-kit",scrollbar:"scrollbar",scrollbarSlider:"scrollbar-slider",scrollbarGlyph:"scrollbar-glyph",scrollbarCaptureZone:"scrollbar-capture-zone"}}},{}],1139:[function(t,e,r){"use strict";var n=t("./constants"),i=t("../../lib/extend").extendFlat,a=t("fast-isnumeric");function o(t){if(Array.isArray(t)){for(var e=0,r=0;r=e||c===t.length-1)&&(n[i]=o,o.key=l++,o.firstRowIndex=s,o.lastRowIndex=c,o={firstRowIndex:null,lastRowIndex:null,rows:[]},i+=a,s=c+1,a=0);return n}e.exports=function(t,e){var r=l(e.cells.values),p=function(t){return t.slice(e.header.values.length,t.length)},d=l(e.header.values);d.length&&!d[0].length&&(d[0]=[""],d=l(d));var m=d.concat(p(r).map(function(){return c((d[0]||[""]).length)})),g=e.domain,v=Math.floor(t._fullLayout._size.w*(g.x[1]-g.x[0])),y=Math.floor(t._fullLayout._size.h*(g.y[1]-g.y[0])),x=e.header.values.length?m[0].map(function(){return e.header.height}):[n.emptyHeaderHeight],b=r.length?r[0].map(function(){return e.cells.height}):[],_=x.reduce(s,0),w=h(b,y-_+n.uplift),k=f(h(x,_),[]),M=f(w,k),A={},T=e._fullInput.columnorder.concat(p(r.map(function(t,e){return e}))),S=m.map(function(t,r){var n=Array.isArray(e.columnwidth)?e.columnwidth[Math.min(r,e.columnwidth.length-1)]:e.columnwidth;return a(n)?Number(n):1}),E=S.reduce(s,0);S=S.map(function(t){return t/E*v});var C=Math.max(o(e.header.line.width),o(e.cells.line.width)),L={key:e.index,translateX:g.x[0]*t._fullLayout._size.w,translateY:t._fullLayout._size.h*(1-g.y[1]),size:t._fullLayout._size,width:v,maxLineWidth:C,height:y,columnOrder:T,groupHeight:y,rowBlocks:M,headerRowBlocks:k,scrollY:0,cells:i({},e.cells,{values:r}),headerCells:i({},e.header,{values:m}),gdColumns:m.map(function(t){return t[0]}),gdColumnsOriginalOrder:m.map(function(t){return t[0]}),prevPages:[0,0],scrollbarState:{scrollbarScrollInProgress:!1},columns:m.map(function(t,e){var r=A[t];return A[t]=(r||0)+1,{key:t+"__"+A[t],label:t,specIndex:e,xIndex:T[e],xScale:u,x:void 0,calcdata:void 0,columnWidth:S[e]}})};return L.columns.forEach(function(t){t.calcdata=L,t.x=u(t)}),L}},{"../../lib/extend":685,"./constants":1138,"fast-isnumeric":214}],1140:[function(t,e,r){"use strict";var n=t("../../lib/extend").extendFlat;r.splitToPanels=function(t){var e=[0,0],r=n({},t,{key:"header",type:"header",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!0,values:t.calcdata.headerCells.values[t.specIndex],rowBlocks:t.calcdata.headerRowBlocks,calcdata:n({},t.calcdata,{cells:t.calcdata.headerCells})});return[n({},t,{key:"cells1",type:"cells",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),n({},t,{key:"cells2",type:"cells",page:1,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),r]},r.splitToCells=function(t){var e=function(t){var e=t.rowBlocks[t.page],r=e?e.rows[0].rowIndex:0,n=e?r+e.rows.length:0;return[r,n]}(t);return(t.values||[]).slice(e[0],e[1]).map(function(r,n){return{keyWithinBlock:n+("string"==typeof r&&r.match(/[<$&> ]/)?"_keybuster_"+Math.random():""),key:e[0]+n,column:t,calcdata:t.calcdata,page:t.page,rowBlocks:t.rowBlocks,value:r}})}},{"../../lib/extend":685}],1141:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../plots/domain").defaults;e.exports=function(t,e,r,o){function s(r,a){return n.coerce(t,e,i,r,a)}a(e,o,s),s("columnwidth"),s("header.values"),s("header.format"),s("header.align"),s("header.prefix"),s("header.suffix"),s("header.height"),s("header.line.width"),s("header.line.color"),s("header.fill.color"),n.coerceFont(s,"header.font",n.extendFlat({},o.font)),function(t,e){for(var r=t.columnorder||[],n=t.header.values.length,i=r.slice(0,n),a=i.slice().sort(function(t,e){return t-e}),o=i.map(function(t){return a.indexOf(t)}),s=o.length;s/i),l=!o||s;t.mayHaveMarkup=o&&a.match(/[<&>]/);var c,u="string"==typeof(c=a)&&c.match(n.latexCheck);t.latex=u;var f,h,p=u?"":_(t.calcdata.cells.prefix,e,r)||"",d=u?"":_(t.calcdata.cells.suffix,e,r)||"",m=u?null:_(t.calcdata.cells.format,e,r)||null,g=p+(m?i.format(m)(t.value):t.value)+d;if(t.wrappingNeeded=!t.wrapped&&!l&&!u&&(f=b(g)),t.cellHeightMayIncrease=s||u||t.mayHaveMarkup||(void 0===f?b(g):f),t.needsConvertToTspans=t.mayHaveMarkup||t.wrappingNeeded||t.latex,t.wrappingNeeded){var v=(" "===n.wrapSplitCharacter?g.replace(/
i&&n.push(a),i+=l}return n}(i,l,s);1===c.length&&(c[0]===i.length-1?c.unshift(c[0]-1):c.push(c[0]+1)),c[0]%2&&c.reverse(),e.each(function(t,e){t.page=c[e],t.scrollY=l}),e.attr("transform",function(t){return"translate(0 "+(I(t.rowBlocks,t.page)-t.scrollY)+")"}),t&&(E(t,r,e,c,n.prevPages,n,0),E(t,r,e,c,n.prevPages,n,1),v(r,t))}}function S(t,e,r,a){return function(o){var s=o.calcdata?o.calcdata:o,l=e.filter(function(t){return s.key===t.key}),c=r||s.scrollbarState.dragMultiplier;s.scrollY=void 0===a?s.scrollY+c*i.event.dy:a;var u=l.selectAll("."+n.cn.yColumn).selectAll("."+n.cn.columnBlock).filter(k);T(t,u,l)}}function E(t,e,r,n,i,a,o){n[o]!==i[o]&&(clearTimeout(a.currentRepaint[o]),a.currentRepaint[o]=setTimeout(function(){var a=r.filter(function(t,e){return e===o&&n[e]!==i[e]});y(t,e,a,r),i[o]=n[o]}))}function C(t,e,r,a){return function(){var o=i.select(e.parentNode);o.each(function(t){var e=t.fragments;o.selectAll("tspan.line").each(function(t,r){e[r].width=this.getComputedTextLength()});var r,i,a=e[e.length-1].width,s=e.slice(0,-1),l=[],c=0,u=t.column.columnWidth-2*n.cellPad;for(t.value="";s.length;)c+(i=(r=s.shift()).width+a)>u&&(t.value+=l.join(n.wrapSpacer)+n.lineBreaker,l=[],c=0),l.push(r.text),c+=i;c&&(t.value+=l.join(n.wrapSpacer)),t.wrapped=!0}),o.selectAll("tspan.line").remove(),x(o.select("."+n.cn.cellText),r,t,a),i.select(e.parentNode.parentNode).call(O)}}function L(t,e,r,a,o){return function(){if(!o.settledY){var s=i.select(e.parentNode),l=R(o),c=o.key-l.firstRowIndex,u=l.rows[c].rowHeight,f=o.cellHeightMayIncrease?e.parentNode.getBoundingClientRect().height+2*n.cellPad:u,h=Math.max(f,u);h-l.rows[c].rowHeight&&(l.rows[c].rowHeight=h,t.selectAll("."+n.cn.columnCell).call(O),T(null,t.filter(k),0),v(r,a,!0)),s.attr("transform",function(){var t=this.parentNode.getBoundingClientRect(),e=i.select(this.parentNode).select("."+n.cn.cellRect).node().getBoundingClientRect(),r=this.transform.baseVal.consolidate(),a=e.top-t.top+(r?r.matrix.f:n.cellPad);return"translate("+z(o,i.select(this.parentNode).select("."+n.cn.cellTextHolder).node().getBoundingClientRect().width)+" "+a+")"}),o.settledY=!0}}}function z(t,e){switch(t.align){case"left":return n.cellPad;case"right":return t.column.columnWidth-(e||0)-n.cellPad;case"center":return(t.column.columnWidth-(e||0))/2;default:return n.cellPad}}function O(t){t.attr("transform",function(t){var e=t.rowBlocks[0].auxiliaryBlocks.reduce(function(t,e){return t+P(e,1/0)},0);return"translate(0 "+(P(R(t),t.key)+e)+")"}).selectAll("."+n.cn.cellRect).attr("height",function(t){return(e=R(t),r=t.key,e.rows[r-e.firstRowIndex]).rowHeight;var e,r})}function I(t,e){for(var r=0,n=e-1;n>=0;n--)r+=D(t[n]);return r}function P(t,e){for(var r=0,n=0;n0){var y,x,b,_,w,k=t.xa,M=t.ya;"h"===h.orientation?(w=e,y="y",b=M,x="x",_=k):(w=r,y="x",b=k,x="y",_=M);var A=f[t.index];if(w>=A.span[0]&&w<=A.span[1]){var T=n.extendFlat({},t),S=_.c2p(w,!0),E=o.getKdeValue(A,h,w),C=o.getPositionOnKdePath(A,h,S),L=b._offset,z=b._length;T[y+"0"]=C[0],T[y+"1"]=C[1],T[x+"0"]=T[x+"1"]=S,T[x+"Label"]=x+": "+i.hoverLabelText(_,w)+", "+f[0].t.labels.kde+" "+E.toFixed(3),T.spikeDistance=v[0].spikeDistance;var O=y+"Spike";T[O]=v[0][O],v[0].spikeDistance=void 0,v[0][O]=void 0,g.push(T),(u={stroke:t.color})[y+"1"]=n.constrain(L+C[0],L,L+z),u[y+"2"]=n.constrain(L+C[1],L,L+z),u[x+"1"]=u[x+"2"]=_._offset+S}}}-1!==p.indexOf("points")&&(c=a.hoverOnPoints(t,e,r));var I=l.selectAll(".violinline-"+h.uid).data(u?[0]:[]);return I.enter().append("line").classed("violinline-"+h.uid,!0).attr("stroke-width",1.5),I.exit().remove(),I.attr(u),"closest"===s?c?[c]:g:c?(g.push(c),g):g}},{"../../lib":696,"../../plots/cartesian/axes":744,"../box/hover":864,"./helpers":1148}],1150:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc"),crossTraceCalc:t("./cross_trace_calc"),plot:t("./plot"),style:t("./style"),styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("../box/select"),moduleType:"trace",name:"violin",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","symbols","oriented","box-violin","showLegend","violinLayout","zoomScale"],meta:{}}},{"../../plots/cartesian":756,"../box/select":869,"../scatter/style":1066,"./attributes":1144,"./calc":1145,"./cross_trace_calc":1146,"./defaults":1147,"./hover":1149,"./layout_attributes":1151,"./layout_defaults":1152,"./plot":1153,"./style":1154}],1151:[function(t,e,r){"use strict";var n=t("../box/layout_attributes"),i=t("../../lib").extendFlat;e.exports={violinmode:i({},n.boxmode,{}),violingap:i({},n.boxgap,{}),violingroupgap:i({},n.boxgroupgap,{})}},{"../../lib":696,"../box/layout_attributes":866}],1152:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes"),a=t("../box/layout_defaults");e.exports=function(t,e,r){a._supply(t,e,r,function(r,a){return n.coerce(t,e,i,r,a)},"violin")}},{"../../lib":696,"../box/layout_defaults":867,"./layout_attributes":1151}],1153:[function(t,e,r){"use strict";var n=t("/home/circleci/plotly.js/test/image/strict-d3.js"),i=t("../../lib"),a=t("../../components/drawing"),o=t("../box/plot"),s=t("../scatter/line_points"),l=t("./helpers");e.exports=function(t,e,r,c){var u=t._fullLayout,f=e.xaxis,h=e.yaxis;function p(t){var e=s(t,{xaxis:f,yaxis:h,connectGaps:!0,baseTolerance:.75,shape:"spline",simplify:!0});return a.smoothopen(e[0],1)}i.makeTraceGroups(c,r,"trace violins").each(function(t){var r=n.select(this),a=t[0],s=a.t,c=a.trace;e.isRangePlot||(a.node3=r);var d=u._numViolins,m="group"===u.violinmode&&d>1,g=1-u.violingap,v=s.bdPos=s.dPos*g*(1-u.violingroupgap)/(m?d:1),y=s.bPos=m?2*s.dPos*((s.num+.5)/d-.5)*g:0;if(s.wHover=s.dPos*(m?g/d:1),!0!==c.visible||s.empty)r.remove();else{var x=e[s.valLetter+"axis"],b=e[s.posLetter+"axis"],_="both"===c.side,w=_||"positive"===c.side,k=_||"negative"===c.side,M=u._violinScaleGroupStats[c.scalegroup],A=r.selectAll("path.violin").data(i.identity);A.enter().append("path").style("vector-effect","non-scaling-stroke").attr("class","violin"),A.exit().remove(),A.each(function(t){var e,r,i,a,o,l,u,f,h=n.select(this),d=t.density,m=d.length,g=t.pos+y,A=b.c2p(g);switch(c.scalemode){case"width":e=M.maxWidth/v;break;case"count":e=M.maxWidth/v*(M.maxCount/t.pts.length)}if(w){for(u=new Array(m),o=0;oa&&(a=u,o=c)}}return a?i(o):s};case"rms":return function(t,e){for(var r=0,a=0,o=0;o":return function(t){return h(t)>s};case">=":return function(t){return h(t)>=s};case"[]":return function(t){var e=h(t);return e>=s[0]&&e<=s[1]};case"()":return function(t){var e=h(t);return e>s[0]&&e=s[0]&&es[0]&&e<=s[1]};case"][":return function(t){var e=h(t);return e<=s[0]||e>=s[1]};case")(":return function(t){var e=h(t);return es[1]};case"](":return function(t){var e=h(t);return e<=s[0]||e>s[1]};case")[":return function(t){var e=h(t);return e=s[1]};case"{}":return function(t){return-1!==s.indexOf(h(t))};case"}{":return function(t){return-1===s.indexOf(h(t))}}}(r,a.getDataToCoordFunc(t,e,s,i),h),x={},b={},_=0;d?(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set(new Array(f))},v=function(t,e){var r=x[t.astr][e];t.get()[e]=r}):(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set([])},v=function(t,e){var r=x[t.astr][e];t.get().push(r)}),M(g);for(var w=o(e.transforms,r),k=0;k1?"%{group} (%{trace})":"%{group}");var l=t.styles,c=o.styles=[];if(l)for(a=0;a